summaryrefslogtreecommitdiff
path: root/thirdparty
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty')
-rw-r--r--thirdparty/README.md131
-rw-r--r--thirdparty/assimp/CREDITS183
-rw-r--r--thirdparty/assimp/LICENSE78
-rw-r--r--thirdparty/assimp/assimp/config.h980
-rw-r--r--thirdparty/assimp/code/BaseImporter.cpp616
-rw-r--r--thirdparty/assimp/code/BaseProcess.cpp107
-rw-r--r--thirdparty/assimp/code/BaseProcess.h290
-rw-r--r--thirdparty/assimp/code/Bitmap.cpp155
-rw-r--r--thirdparty/assimp/code/CInterfaceIOWrapper.cpp136
-rw-r--r--thirdparty/assimp/code/CInterfaceIOWrapper.h99
-rw-r--r--thirdparty/assimp/code/CalcTangentsProcess.cpp319
-rw-r--r--thirdparty/assimp/code/CalcTangentsProcess.h117
-rw-r--r--thirdparty/assimp/code/ComputeUVMappingProcess.cpp506
-rw-r--r--thirdparty/assimp/code/ComputeUVMappingProcess.h148
-rw-r--r--thirdparty/assimp/code/ConvertToLHProcess.cpp414
-rw-r--r--thirdparty/assimp/code/ConvertToLHProcess.h170
-rw-r--r--thirdparty/assimp/code/CreateAnimMesh.cpp92
-rw-r--r--thirdparty/assimp/code/DeboneProcess.cpp465
-rw-r--r--thirdparty/assimp/code/DeboneProcess.h134
-rw-r--r--thirdparty/assimp/code/DefaultIOStream.cpp154
-rw-r--r--thirdparty/assimp/code/DefaultIOSystem.cpp257
-rw-r--r--thirdparty/assimp/code/DefaultLogger.cpp418
-rw-r--r--thirdparty/assimp/code/DefaultProgressHandler.h65
-rw-r--r--thirdparty/assimp/code/DropFaceNormalsProcess.cpp109
-rw-r--r--thirdparty/assimp/code/DropFaceNormalsProcess.h86
-rw-r--r--thirdparty/assimp/code/EmbedTexturesProcess.cpp152
-rw-r--r--thirdparty/assimp/code/EmbedTexturesProcess.h85
-rw-r--r--thirdparty/assimp/code/Exporter.cpp648
-rw-r--r--thirdparty/assimp/code/FBXAnimation.cpp305
-rw-r--r--thirdparty/assimp/code/FBXBinaryTokenizer.cpp466
-rw-r--r--thirdparty/assimp/code/FBXCommon.h86
-rw-r--r--thirdparty/assimp/code/FBXCompileConfig.h70
-rw-r--r--thirdparty/assimp/code/FBXConverter.cpp3536
-rw-r--r--thirdparty/assimp/code/FBXConverter.h461
-rw-r--r--thirdparty/assimp/code/FBXDeformer.cpp213
-rw-r--r--thirdparty/assimp/code/FBXDocument.cpp726
-rw-r--r--thirdparty/assimp/code/FBXDocument.h1180
-rw-r--r--thirdparty/assimp/code/FBXDocumentUtil.cpp135
-rw-r--r--thirdparty/assimp/code/FBXDocumentUtil.h120
-rw-r--r--thirdparty/assimp/code/FBXExportNode.cpp568
-rw-r--r--thirdparty/assimp/code/FBXExportNode.h271
-rw-r--r--thirdparty/assimp/code/FBXExportProperty.cpp364
-rw-r--r--thirdparty/assimp/code/FBXExportProperty.h129
-rw-r--r--thirdparty/assimp/code/FBXExporter.cpp2480
-rw-r--r--thirdparty/assimp/code/FBXExporter.h178
-rw-r--r--thirdparty/assimp/code/FBXImportSettings.h153
-rw-r--r--thirdparty/assimp/code/FBXImporter.cpp197
-rw-r--r--thirdparty/assimp/code/FBXImporter.h100
-rw-r--r--thirdparty/assimp/code/FBXMaterial.cpp381
-rw-r--r--thirdparty/assimp/code/FBXMeshGeometry.cpp711
-rw-r--r--thirdparty/assimp/code/FBXMeshGeometry.h235
-rw-r--r--thirdparty/assimp/code/FBXModel.cpp153
-rw-r--r--thirdparty/assimp/code/FBXNodeAttribute.cpp170
-rw-r--r--thirdparty/assimp/code/FBXParser.cpp1313
-rw-r--r--thirdparty/assimp/code/FBXParser.h235
-rw-r--r--thirdparty/assimp/code/FBXProperties.cpp235
-rw-r--r--thirdparty/assimp/code/FBXProperties.h185
-rw-r--r--thirdparty/assimp/code/FBXTokenizer.cpp248
-rw-r--r--thirdparty/assimp/code/FBXTokenizer.h187
-rw-r--r--thirdparty/assimp/code/FBXUtil.cpp164
-rw-r--r--thirdparty/assimp/code/FBXUtil.h120
-rw-r--r--thirdparty/assimp/code/FIReader.cpp1834
-rw-r--r--thirdparty/assimp/code/FileLogStream.h107
-rw-r--r--thirdparty/assimp/code/FileSystemFilter.h345
-rw-r--r--thirdparty/assimp/code/FindDegenerates.cpp300
-rw-r--r--thirdparty/assimp/code/FindDegenerates.h129
-rw-r--r--thirdparty/assimp/code/FindInstancesProcess.cpp277
-rw-r--r--thirdparty/assimp/code/FindInstancesProcess.h137
-rw-r--r--thirdparty/assimp/code/FindInvalidDataProcess.cpp424
-rw-r--r--thirdparty/assimp/code/FindInvalidDataProcess.h105
-rw-r--r--thirdparty/assimp/code/FixNormalsStep.cpp184
-rw-r--r--thirdparty/assimp/code/FixNormalsStep.h91
-rw-r--r--thirdparty/assimp/code/GenFaceNormalsProcess.cpp146
-rw-r--r--thirdparty/assimp/code/GenFaceNormalsProcess.h87
-rw-r--r--thirdparty/assimp/code/GenVertexNormalsProcess.cpp239
-rw-r--r--thirdparty/assimp/code/GenVertexNormalsProcess.h115
-rw-r--r--thirdparty/assimp/code/Importer.cpp1171
-rw-r--r--thirdparty/assimp/code/Importer.h247
-rw-r--r--thirdparty/assimp/code/ImporterRegistry.cpp371
-rw-r--r--thirdparty/assimp/code/ImproveCacheLocality.cpp386
-rw-r--r--thirdparty/assimp/code/ImproveCacheLocality.h100
-rw-r--r--thirdparty/assimp/code/JoinVerticesProcess.cpp463
-rw-r--r--thirdparty/assimp/code/JoinVerticesProcess.h99
-rw-r--r--thirdparty/assimp/code/LimitBoneWeightsProcess.cpp201
-rw-r--r--thirdparty/assimp/code/LimitBoneWeightsProcess.h148
-rw-r--r--thirdparty/assimp/code/MMDCpp14.h83
-rw-r--r--thirdparty/assimp/code/MMDImporter.cpp370
-rw-r--r--thirdparty/assimp/code/MMDImporter.h96
-rw-r--r--thirdparty/assimp/code/MMDPmdParser.h597
-rw-r--r--thirdparty/assimp/code/MMDPmxParser.cpp604
-rw-r--r--thirdparty/assimp/code/MMDPmxParser.h782
-rw-r--r--thirdparty/assimp/code/MMDVmdParser.h376
-rw-r--r--thirdparty/assimp/code/MakeVerboseFormat.cpp226
-rw-r--r--thirdparty/assimp/code/MakeVerboseFormat.h105
-rw-r--r--thirdparty/assimp/code/MaterialSystem.cpp647
-rw-r--r--thirdparty/assimp/code/MaterialSystem.h72
-rw-r--r--thirdparty/assimp/code/OptimizeGraph.cpp353
-rw-r--r--thirdparty/assimp/code/OptimizeGraph.h145
-rw-r--r--thirdparty/assimp/code/OptimizeMeshes.cpp256
-rw-r--r--thirdparty/assimp/code/OptimizeMeshes.h186
-rw-r--r--thirdparty/assimp/code/PolyTools.h229
-rw-r--r--thirdparty/assimp/code/PostStepRegistry.cpp251
-rw-r--r--thirdparty/assimp/code/PretransformVertices.cpp728
-rw-r--r--thirdparty/assimp/code/PretransformVertices.h163
-rw-r--r--thirdparty/assimp/code/ProcessHelper.cpp443
-rw-r--r--thirdparty/assimp/code/ProcessHelper.h386
-rw-r--r--thirdparty/assimp/code/RawLoader.cpp331
-rw-r--r--thirdparty/assimp/code/RemoveComments.cpp113
-rw-r--r--thirdparty/assimp/code/RemoveRedundantMaterials.cpp221
-rw-r--r--thirdparty/assimp/code/RemoveRedundantMaterials.h107
-rw-r--r--thirdparty/assimp/code/RemoveVCProcess.cpp337
-rw-r--r--thirdparty/assimp/code/RemoveVCProcess.h123
-rw-r--r--thirdparty/assimp/code/SGSpatialSort.cpp168
-rw-r--r--thirdparty/assimp/code/ScaleProcess.cpp103
-rw-r--r--thirdparty/assimp/code/ScaleProcess.h88
-rw-r--r--thirdparty/assimp/code/SceneCombiner.cpp1300
-rw-r--r--thirdparty/assimp/code/ScenePreprocessor.cpp261
-rw-r--r--thirdparty/assimp/code/ScenePreprocessor.h125
-rw-r--r--thirdparty/assimp/code/ScenePrivate.h105
-rw-r--r--thirdparty/assimp/code/SkeletonMeshBuilder.cpp270
-rw-r--r--thirdparty/assimp/code/SortByPTypeProcess.cpp403
-rw-r--r--thirdparty/assimp/code/SortByPTypeProcess.h85
-rw-r--r--thirdparty/assimp/code/SpatialSort.cpp342
-rw-r--r--thirdparty/assimp/code/SplitByBoneCountProcess.cpp407
-rw-r--r--thirdparty/assimp/code/SplitByBoneCountProcess.h111
-rw-r--r--thirdparty/assimp/code/SplitLargeMeshes.cpp623
-rw-r--r--thirdparty/assimp/code/SplitLargeMeshes.h210
-rw-r--r--thirdparty/assimp/code/StandardShapes.cpp507
-rw-r--r--thirdparty/assimp/code/StdOStreamLogStream.h101
-rw-r--r--thirdparty/assimp/code/Subdivision.cpp588
-rw-r--r--thirdparty/assimp/code/TargetAnimation.cpp248
-rw-r--r--thirdparty/assimp/code/TargetAnimation.h183
-rw-r--r--thirdparty/assimp/code/TextureTransform.cpp566
-rw-r--r--thirdparty/assimp/code/TextureTransform.h232
-rw-r--r--thirdparty/assimp/code/TriangulateProcess.cpp530
-rw-r--r--thirdparty/assimp/code/TriangulateProcess.h95
-rw-r--r--thirdparty/assimp/code/ValidateDataStructure.cpp986
-rw-r--r--thirdparty/assimp/code/ValidateDataStructure.h188
-rw-r--r--thirdparty/assimp/code/Version.cpp185
-rw-r--r--thirdparty/assimp/code/VertexTriangleAdjacency.cpp134
-rw-r--r--thirdparty/assimp/code/VertexTriangleAdjacency.h117
-rw-r--r--thirdparty/assimp/code/Win32DebugLogStream.h95
-rw-r--r--thirdparty/assimp/code/revision.h7
-rw-r--r--thirdparty/assimp/code/scene.cpp140
-rw-r--r--thirdparty/assimp/code/simd.cpp79
-rw-r--r--thirdparty/assimp/code/simd.h53
-rw-r--r--thirdparty/assimp/contrib/utf8cpp/source/utf8.h34
-rw-r--r--thirdparty/assimp/contrib/utf8cpp/source/utf8/checked.h327
-rw-r--r--thirdparty/assimp/contrib/utf8cpp/source/utf8/core.h329
-rw-r--r--thirdparty/assimp/contrib/utf8cpp/source/utf8/unchecked.h228
-rw-r--r--thirdparty/assimp/include/assimp/.editorconfig8
-rw-r--r--thirdparty/assimp/include/assimp/BaseImporter.h361
-rw-r--r--thirdparty/assimp/include/assimp/Bitmap.h125
-rw-r--r--thirdparty/assimp/include/assimp/BlobIOSystem.h338
-rw-r--r--thirdparty/assimp/include/assimp/ByteSwapper.h287
-rw-r--r--thirdparty/assimp/include/assimp/Compiler/poppack1.h22
-rw-r--r--thirdparty/assimp/include/assimp/Compiler/pstdint.h912
-rw-r--r--thirdparty/assimp/include/assimp/Compiler/pushpack1.h43
-rw-r--r--thirdparty/assimp/include/assimp/CreateAnimMesh.h58
-rw-r--r--thirdparty/assimp/include/assimp/DefaultIOStream.h140
-rw-r--r--thirdparty/assimp/include/assimp/DefaultIOSystem.h93
-rw-r--r--thirdparty/assimp/include/assimp/DefaultLogger.hpp188
-rw-r--r--thirdparty/assimp/include/assimp/Defines.h49
-rw-r--r--thirdparty/assimp/include/assimp/Exceptional.h125
-rw-r--r--thirdparty/assimp/include/assimp/Exporter.hpp505
-rw-r--r--thirdparty/assimp/include/assimp/GenericProperty.h133
-rw-r--r--thirdparty/assimp/include/assimp/Hash.h118
-rw-r--r--thirdparty/assimp/include/assimp/IOStream.hpp142
-rw-r--r--thirdparty/assimp/include/assimp/IOStreamBuffer.h355
-rw-r--r--thirdparty/assimp/include/assimp/IOSystem.hpp357
-rw-r--r--thirdparty/assimp/include/assimp/Importer.hpp659
-rw-r--r--thirdparty/assimp/include/assimp/LineSplitter.h285
-rw-r--r--thirdparty/assimp/include/assimp/LogAux.h131
-rw-r--r--thirdparty/assimp/include/assimp/LogStream.hpp111
-rw-r--r--thirdparty/assimp/include/assimp/Logger.hpp305
-rw-r--r--thirdparty/assimp/include/assimp/Macros.h49
-rw-r--r--thirdparty/assimp/include/assimp/MathFunctions.h77
-rw-r--r--thirdparty/assimp/include/assimp/MemoryIOWrapper.h244
-rw-r--r--thirdparty/assimp/include/assimp/NullLogger.hpp99
-rw-r--r--thirdparty/assimp/include/assimp/ParsingUtils.h260
-rw-r--r--thirdparty/assimp/include/assimp/Profiler.h99
-rw-r--r--thirdparty/assimp/include/assimp/ProgressHandler.hpp145
-rw-r--r--thirdparty/assimp/include/assimp/RemoveComments.h91
-rw-r--r--thirdparty/assimp/include/assimp/SGSpatialSort.h150
-rw-r--r--thirdparty/assimp/include/assimp/SceneCombiner.h401
-rw-r--r--thirdparty/assimp/include/assimp/SkeletonMeshBuilder.h125
-rw-r--r--thirdparty/assimp/include/assimp/SmoothingGroups.h108
-rw-r--r--thirdparty/assimp/include/assimp/SmoothingGroups.inl138
-rw-r--r--thirdparty/assimp/include/assimp/SpatialSort.h174
-rw-r--r--thirdparty/assimp/include/assimp/StandardShapes.h200
-rw-r--r--thirdparty/assimp/include/assimp/StreamReader.h343
-rw-r--r--thirdparty/assimp/include/assimp/StreamWriter.h303
-rw-r--r--thirdparty/assimp/include/assimp/StringComparison.h233
-rw-r--r--thirdparty/assimp/include/assimp/StringUtils.h143
-rw-r--r--thirdparty/assimp/include/assimp/Subdivision.h131
-rw-r--r--thirdparty/assimp/include/assimp/TinyFormatter.h166
-rw-r--r--thirdparty/assimp/include/assimp/Vertex.h348
-rw-r--r--thirdparty/assimp/include/assimp/XMLTools.h83
-rw-r--r--thirdparty/assimp/include/assimp/ai_assert.h57
-rw-r--r--thirdparty/assimp/include/assimp/anim.h577
-rw-r--r--thirdparty/assimp/include/assimp/camera.h226
-rw-r--r--thirdparty/assimp/include/assimp/cexport.h261
-rw-r--r--thirdparty/assimp/include/assimp/cfileio.h138
-rw-r--r--thirdparty/assimp/include/assimp/cimport.h565
-rw-r--r--thirdparty/assimp/include/assimp/color4.h104
-rw-r--r--thirdparty/assimp/include/assimp/color4.inl205
-rw-r--r--thirdparty/assimp/include/assimp/config.h.in992
-rw-r--r--thirdparty/assimp/include/assimp/defs.h303
-rw-r--r--thirdparty/assimp/include/assimp/fast_atof.h373
-rw-r--r--thirdparty/assimp/include/assimp/importerdesc.h146
-rw-r--r--thirdparty/assimp/include/assimp/irrXMLWrapper.h144
-rw-r--r--thirdparty/assimp/include/assimp/light.h259
-rw-r--r--thirdparty/assimp/include/assimp/material.h1580
-rw-r--r--thirdparty/assimp/include/assimp/material.inl390
-rw-r--r--thirdparty/assimp/include/assimp/matrix3x3.h183
-rw-r--r--thirdparty/assimp/include/assimp/matrix3x3.inl357
-rw-r--r--thirdparty/assimp/include/assimp/matrix4x4.h280
-rw-r--r--thirdparty/assimp/include/assimp/matrix4x4.inl686
-rw-r--r--thirdparty/assimp/include/assimp/mesh.h852
-rw-r--r--thirdparty/assimp/include/assimp/metadata.h380
-rw-r--r--thirdparty/assimp/include/assimp/pbrmaterial.h77
-rw-r--r--thirdparty/assimp/include/assimp/port/AndroidJNI/AndroidJNIIOSystem.h92
-rw-r--r--thirdparty/assimp/include/assimp/postprocess.h679
-rw-r--r--thirdparty/assimp/include/assimp/qnan.h165
-rw-r--r--thirdparty/assimp/include/assimp/quaternion.h130
-rw-r--r--thirdparty/assimp/include/assimp/quaternion.inl286
-rw-r--r--thirdparty/assimp/include/assimp/scene.h416
-rw-r--r--thirdparty/assimp/include/assimp/texture.h227
-rw-r--r--thirdparty/assimp/include/assimp/types.h529
-rw-r--r--thirdparty/assimp/include/assimp/vector2.h107
-rw-r--r--thirdparty/assimp/include/assimp/vector2.inl244
-rw-r--r--thirdparty/assimp/include/assimp/vector3.h146
-rw-r--r--thirdparty/assimp/include/assimp/vector3.inl309
-rw-r--r--thirdparty/assimp/include/assimp/version.h115
-rw-r--r--thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3BroadphaseCallback.h16
-rw-r--r--thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.cpp1393
-rw-r--r--thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.h1463
-rw-r--r--thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.cpp822
-rw-r--r--thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.h195
-rw-r--r--thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3OverlappingPair.h44
-rw-r--r--thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3OverlappingPairCache.cpp301
-rw-r--r--thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3OverlappingPairCache.h355
-rw-r--r--thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h51
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3Config.h40
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3Contact4.h33
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.cpp314
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.h39
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3CpuNarrowPhase.cpp190
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3CpuNarrowPhase.h61
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3RaycastInfo.h21
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3RigidBodyCL.h8
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3BvhSubtreeInfoData.h13
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3BvhTraversal.h103
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ClipFaces.h219
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h53
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h26
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ContactConvexConvexSAT.h478
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ContactSphereSphere.h143
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h22
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3FindConcaveSatAxis.h935
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3FindSeparatingAxis.h149
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3MprPenetration.h1232
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3NewContactReduction.h291
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3QuantizedBvhNodeData.h52
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ReduceContacts.h162
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h23
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3UpdateAabbs.h29
-rw-r--r--thirdparty/bullet/Bullet3Common/b3AlignedAllocator.cpp161
-rw-r--r--thirdparty/bullet/Bullet3Common/b3AlignedAllocator.h99
-rw-r--r--thirdparty/bullet/Bullet3Common/b3AlignedObjectArray.h681
-rw-r--r--thirdparty/bullet/Bullet3Common/b3CommandLineArgs.h77
-rw-r--r--thirdparty/bullet/Bullet3Common/b3FileUtils.h85
-rw-r--r--thirdparty/bullet/Bullet3Common/b3HashMap.h252
-rw-r--r--thirdparty/bullet/Bullet3Common/b3Logging.cpp87
-rw-r--r--thirdparty/bullet/Bullet3Common/b3Logging.h107
-rw-r--r--thirdparty/bullet/Bullet3Common/b3Matrix3x3.h1446
-rw-r--r--thirdparty/bullet/Bullet3Common/b3MinMax.h32
-rw-r--r--thirdparty/bullet/Bullet3Common/b3PoolAllocator.h82
-rw-r--r--thirdparty/bullet/Bullet3Common/b3QuadWord.h243
-rw-r--r--thirdparty/bullet/Bullet3Common/b3Quaternion.h841
-rw-r--r--thirdparty/bullet/Bullet3Common/b3Random.h14
-rw-r--r--thirdparty/bullet/Bullet3Common/b3ResizablePool.h65
-rw-r--r--thirdparty/bullet/Bullet3Common/b3Scalar.h732
-rw-r--r--thirdparty/bullet/Bullet3Common/b3StackAlloc.h96
-rw-r--r--thirdparty/bullet/Bullet3Common/b3Transform.h206
-rw-r--r--thirdparty/bullet/Bullet3Common/b3TransformUtil.h146
-rw-r--r--thirdparty/bullet/Bullet3Common/b3Vector3.cpp2986
-rw-r--r--thirdparty/bullet/Bullet3Common/b3Vector3.h857
-rw-r--r--thirdparty/bullet/Bullet3Common/shared/b3Float4.h137
-rw-r--r--thirdparty/bullet/Bullet3Common/shared/b3Int2.h15
-rw-r--r--thirdparty/bullet/Bullet3Common/shared/b3Int4.h33
-rw-r--r--thirdparty/bullet/Bullet3Common/shared/b3Mat3x3.h108
-rw-r--r--thirdparty/bullet/Bullet3Common/shared/b3PlatformDefinitions.h10
-rw-r--r--thirdparty/bullet/Bullet3Common/shared/b3Quat.h71
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3ContactSolverInfo.h172
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3FixedConstraint.cpp103
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3FixedConstraint.h19
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3Generic6DofConstraint.cpp576
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3Generic6DofConstraint.h567
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3JacobianEntry.h103
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3PgsJacobiSolver.cpp1381
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3PgsJacobiSolver.h144
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3Point2PointConstraint.cpp151
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3Point2PointConstraint.h96
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3SolverBody.h187
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3SolverConstraint.h59
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.cpp58
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.h210
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/b3CpuRigidBodyPipeline.cpp317
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/b3CpuRigidBodyPipeline.h49
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/shared/b3ContactConstraint4.h19
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/shared/b3ConvertConstraint4.h133
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/shared/b3Inertia.h3
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/shared/b3IntegrateTransforms.h53
-rw-r--r--thirdparty/bullet/Bullet3Geometry/b3AabbUtil.h189
-rw-r--r--thirdparty/bullet/Bullet3Geometry/b3ConvexHullComputer.cpp1554
-rw-r--r--thirdparty/bullet/Bullet3Geometry/b3ConvexHullComputer.h102
-rw-r--r--thirdparty/bullet/Bullet3Geometry/b3GeometryUtil.cpp113
-rw-r--r--thirdparty/bullet/Bullet3Geometry/b3GeometryUtil.h22
-rw-r--r--thirdparty/bullet/Bullet3Geometry/b3GrahamScan2dConvexHull.h63
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuBroadphaseInterface.h28
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuGridBroadphase.cpp253
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuGridBroadphase.h68
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.cpp540
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.h68
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvhBroadphase.cpp44
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvhBroadphase.h24
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuSapBroadphase.cpp918
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuSapBroadphase.h146
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3SapAabb.h9
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/kernels/gridBroadphaseKernels.h395
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/kernels/parallelLinearBvhKernels.h1455
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/kernels/sapKernels.h681
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/Initialize/b3OpenCLInclude.h23
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/Initialize/b3OpenCLUtils.cpp590
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/Initialize/b3OpenCLUtils.h140
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3BvhInfo.h17
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ContactCache.cpp7
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ContactCache.h34
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ConvexHullContact.cpp4985
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ConvexHullContact.h148
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ConvexPolyhedronCL.h4
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3GjkEpa.cpp1562
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3GjkEpa.h49
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3OptimizedBvh.cpp296
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3OptimizedBvh.h29
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3QuantizedBvh.cpp551
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3QuantizedBvh.h369
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.cpp229
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.h203
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3SupportMappings.h34
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleCallback.cpp4
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleCallback.h9
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.cpp41
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.h113
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3VectorFloat4.h3
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.cpp493
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.h149
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/bvhTraversal.h513
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/mprKernels.h2889
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/primitiveContacts.h2575
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/satClipHullContacts.h4195
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/satConcaveKernels.h2911
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/satKernels.h4205
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.cpp162
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.h55
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3BufferInfoCL.h7
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3FillCL.cpp83
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3FillCL.h63
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.cpp376
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h165
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h174
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.cpp84
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.h14
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanFloat4CL.cpp86
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanFloat4CL.h12
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.cpp730
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h103
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/BoundSearchKernelsCL.h171
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/CopyKernelsCL.h261
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/FillKernelsCL.h179
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernelsCL.h255
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernelsFloat4CL.h255
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/RadixSort32KernelsCL.h1817
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/Raycast/b3GpuRaycast.cpp259
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/Raycast/b3GpuRaycast.h22
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/Raycast/kernels/rayCastKernels.h759
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuConstraint4.h11
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuGenericConstraint.cpp75
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuGenericConstraint.h64
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuJacobiContactSolver.cpp639
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuJacobiContactSolver.h22
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuNarrowPhase.cpp732
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuNarrowPhase.h72
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuNarrowPhaseInternalData.h74
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuPgsConstraintSolver.cpp692
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuPgsConstraintSolver.h50
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuPgsContactSolver.cpp1251
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuPgsContactSolver.h30
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipeline.cpp351
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipeline.h42
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipelineInternalData.h39
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuSolverBody.h120
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuSolverConstraint.h63
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/b3Solver.cpp835
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/b3Solver.h126
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/batchingKernels.h773
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/batchingKernelsNew.h579
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/integrateKernel.h863
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/jointSolver.h1439
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solveContact.h783
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solveFriction.h839
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solverSetup.h1403
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solverSetup2.h1199
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solverUtils.h1815
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/updateAabbsKernel.h963
-rw-r--r--thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/autogenerated/bullet2.h1994
-rw-r--r--thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3BulletFile.cpp253
-rw-r--r--thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3BulletFile.h69
-rw-r--r--thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Chunk.cpp12
-rw-r--r--thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Chunk.h130
-rw-r--r--thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Common.h33
-rw-r--r--thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3DNA.cpp355
-rw-r--r--thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3DNA.h141
-rw-r--r--thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Defines.h199
-rw-r--r--thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3File.cpp990
-rw-r--r--thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3File.h253
-rw-r--r--thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Serializer.cpp18970
-rw-r--r--thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Serializer.h808
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp12
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3.h8
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3Internal.h528
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h53
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp2
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h193
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp1
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h42
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvt.cpp1395
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvt.h1517
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp855
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h148
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btDispatcher.cpp2
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btDispatcher.h87
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp384
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h348
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h16
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp594
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.h336
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp147
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h107
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp148
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/SphereTriangleDetector.h24
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp28
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h12
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp106
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h25
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp30
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h25
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp1225
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btBoxBoxDetector.h12
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionConfiguration.h12
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h10
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp188
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.h88
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.cpp236
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.h16
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObject.cpp79
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObject.h372
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h26
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.cpp1397
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.h344
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp812
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorldImporter.h98
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp231
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h45
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp306
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h45
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp99
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h49
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp183
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h74
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp979
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h46
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp96
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h46
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp219
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h87
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp8
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h18
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btGhostObject.cpp97
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btGhostObject.h79
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp85
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btHashedSimplePairCache.h99
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp750
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h18
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btManifoldResult.cpp182
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btManifoldResult.h90
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp264
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.h38
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp89
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h38
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp36
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h26
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp32
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h30
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btUnionFind.cpp50
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btUnionFind.h172
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btBox2dShape.cpp25
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btBox2dShape.h349
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btBoxShape.cpp30
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btBoxShape.h317
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp328
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h81
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btCapsuleShape.cpp81
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btCapsuleShape.h109
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btCollisionMargin.h7
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btCollisionShape.cpp57
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btCollisionShape.h89
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btCompoundShape.cpp192
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btCompoundShape.h97
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btConcaveShape.cpp3
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btConcaveShape.h20
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btConeShape.cpp107
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btConeShape.h141
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btConvex2dShape.cpp46
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btConvex2dShape.h55
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btConvexHullShape.cpp150
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btConvexHullShape.h61
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btConvexInternalShape.cpp124
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btConvexInternalShape.h123
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp94
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPointCloudShape.h46
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp187
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPolyhedron.h45
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btConvexShape.cpp631
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btConvexShape.h56
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp312
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h55
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btCylinderShape.cpp203
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btCylinderShape.h131
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btEmptyShape.cpp18
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btEmptyShape.h31
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp704
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h102
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btMaterial.h21
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btMiniSDF.cpp540
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btMiniSDF.h37
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp50
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btMinkowskiSumShape.h45
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btMultiSphereShape.cpp134
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btMultiSphereShape.h56
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp40
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h150
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btOptimizedBvh.cpp296
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btOptimizedBvh.h29
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp382
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h75
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp62
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h53
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btSdfCollisionShape.cpp35
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btSdfCollisionShape.h19
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btShapeHull.cpp670
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btShapeHull.h23
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btSphereShape.cpp36
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btSphereShape.h37
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp58
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btStaticPlaneShape.h72
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp370
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.h167
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btTetrahedronShape.cpp177
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btTetrahedronShape.h45
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleBuffer.cpp25
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleBuffer.h32
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleCallback.cpp4
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleCallback.h9
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp41
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h113
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp82
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h77
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleInfoMap.h122
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleMesh.cpp92
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleMesh.h65
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp106
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleMeshShape.h36
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleShape.h125
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btUniformScalingShape.cpp118
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btUniformScalingShape.h61
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btBoxCollision.h471
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btClipPolygon.h139
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btCompoundFromGimpact.h162
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btContactProcessing.cpp122
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btContactProcessing.h20
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btContactProcessingStructs.h92
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btGImpactBvh.cpp286
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btGImpactBvh.h109
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btGImpactBvhStructs.h35
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp636
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h246
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btGImpactMassUtil.h34
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp304
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btGImpactQuantizedBvh.h121
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btGImpactQuantizedBvhStructs.h28
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btGImpactShape.cpp198
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btGImpactShape.h669
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btGenericPoolAllocator.cpp125
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btGenericPoolAllocator.h50
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btGeometryOperations.h224
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btQuantization.h43
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btTriangleShapeEx.cpp265
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btTriangleShapeEx.h73
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_array.h336
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_basic_geometry_operations.h542
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_bitset.h50
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_box_collision.h397
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_box_set.cpp88
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_box_set.h275
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_clip_polygon.h181
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_contact.cpp74
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_contact.h126
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_geom_types.h7
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_geometry.h2
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_hash_table.h1385
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_linear_math.h2269
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_math.h111
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_memory.cpp69
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_memory.h171
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_radixsort.h214
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_tri_collision.cpp321
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_tri_collision.h274
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btComputeGjkEpaPenetration.h633
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp125
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h34
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btConvexCast.h71
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h21
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h57
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkCollisionDescription.h32
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp76
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h26
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp1703
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h62
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa3.h1824
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp23
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h29
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp494
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h52
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h277
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp253
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h18
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMprPenetration.h1160
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp218
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h125
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPointCollector.h24
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp354
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h17
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp135
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h45
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h19
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp118
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h23
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp493
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h154
-rw-r--r--thirdparty/bullet/BulletDynamics/Character/btCharacterControllerInterface.h33
-rw-r--r--thirdparty/bullet/BulletDynamics/Character/btKinematicCharacterController.cpp364
-rw-r--r--thirdparty/bullet/BulletDynamics/Character/btKinematicCharacterController.h114
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.cpp1794
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.h70
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp604
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h266
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btConstraintSolver.h32
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactConstraint.cpp136
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactConstraint.h30
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactSolverInfo.h189
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btFixedConstraint.cpp19
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btFixedConstraint.h11
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btGearConstraint.cpp28
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btGearConstraint.h94
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp708
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h664
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp640
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h533
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp64
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h96
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp29
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btHinge2Constraint.h27
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp683
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btHingeConstraint.h415
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btJacobianEntry.h103
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.cpp262
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.h35
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp184
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h131
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp1755
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h187
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.cpp2555
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.h168
-rwxr-xr-xthirdparty/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp640
-rwxr-xr-xthirdparty/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.h213
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp170
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h88
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolverBody.h191
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolverConstraint.h70
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp102
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btTypedConstraint.h225
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp43
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btUniversalConstraint.h30
-rw-r--r--thirdparty/bullet/BulletDynamics/Dynamics/btActionInterface.h11
-rw-r--r--thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp1021
-rw-r--r--thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h159
-rw-r--r--thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.cpp289
-rw-r--r--thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.h143
-rw-r--r--thirdparty/bullet/BulletDynamics/Dynamics/btDynamicsWorld.h200
-rw-r--r--thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.cpp263
-rw-r--r--thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.h504
-rw-r--r--thirdparty/bullet/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp114
-rw-r--r--thirdparty/bullet/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h57
-rw-r--r--thirdparty/bullet/BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp1023
-rw-r--r--thirdparty/bullet/BulletDynamics/Dynamics/btSimulationIslandManagerMt.h128
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.cpp2058
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.h946
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp670
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraint.h167
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp1399
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h113
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp861
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h65
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.cpp184
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.h81
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyGearConstraint.cpp86
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyGearConstraint.h90
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointFeedback.h6
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp94
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.h13
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp101
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointMotor.h46
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyLink.h191
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyLinkCollider.h61
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp113
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyPoint2Point.h30
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySliderConstraint.cpp221
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySliderConstraint.h103
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySolverConstraint.h82
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySphericalJointMotor.cpp172
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySphericalJointMotor.h77
-rw-r--r--thirdparty/bullet/BulletDynamics/MLCPSolvers/btDantzigLCP.cpp3526
-rw-r--r--thirdparty/bullet/BulletDynamics/MLCPSolvers/btDantzigLCP.h12
-rw-r--r--thirdparty/bullet/BulletDynamics/MLCPSolvers/btDantzigSolver.h32
-rw-r--r--thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeAlgorithm.cpp482
-rw-r--r--thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeAlgorithm.h82
-rw-r--r--thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeSolver.h472
-rw-r--r--thirdparty/bullet/BulletDynamics/MLCPSolvers/btMLCPSolver.cpp395
-rw-r--r--thirdparty/bullet/BulletDynamics/MLCPSolvers/btMLCPSolver.h40
-rw-r--r--thirdparty/bullet/BulletDynamics/MLCPSolvers/btMLCPSolverInterface.h4
-rw-r--r--thirdparty/bullet/BulletDynamics/MLCPSolvers/btPATHSolver.h61
-rw-r--r--thirdparty/bullet/BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h65
-rw-r--r--thirdparty/bullet/BulletDynamics/Vehicle/btRaycastVehicle.cpp554
-rw-r--r--thirdparty/bullet/BulletDynamics/Vehicle/btRaycastVehicle.h158
-rw-r--r--thirdparty/bullet/BulletDynamics/Vehicle/btVehicleRaycaster.h20
-rw-r--r--thirdparty/bullet/BulletDynamics/Vehicle/btWheelInfo.cpp21
-rw-r--r--thirdparty/bullet/BulletDynamics/Vehicle/btWheelInfo.h107
-rw-r--r--thirdparty/bullet/BulletInverseDynamics/IDConfig.hpp26
-rw-r--r--thirdparty/bullet/BulletInverseDynamics/IDConfigBuiltin.hpp19
-rw-r--r--thirdparty/bullet/BulletInverseDynamics/IDConfigEigen.hpp3
-rw-r--r--thirdparty/bullet/BulletInverseDynamics/IDErrorMessages.hpp18
-rw-r--r--thirdparty/bullet/BulletInverseDynamics/IDMath.cpp351
-rw-r--r--thirdparty/bullet/BulletInverseDynamics/IDMath.hpp15
-rw-r--r--thirdparty/bullet/BulletInverseDynamics/MultiBodyTree.cpp345
-rw-r--r--thirdparty/bullet/BulletInverseDynamics/MultiBodyTree.hpp94
-rw-r--r--thirdparty/bullet/BulletInverseDynamics/details/IDEigenInterface.hpp23
-rw-r--r--thirdparty/bullet/BulletInverseDynamics/details/IDLinearMathInterface.hpp156
-rw-r--r--thirdparty/bullet/BulletInverseDynamics/details/IDMatVec.hpp324
-rw-r--r--thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeImpl.cpp933
-rw-r--r--thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeImpl.hpp93
-rw-r--r--thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeInitCache.cpp60
-rw-r--r--thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeInitCache.hpp14
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDefaultSoftBodySolver.cpp69
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDefaultSoftBodySolver.h27
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftBody.cpp3766
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftBody.h1474
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp198
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h70
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftBodyData.h311
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.cpp1282
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.h231
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftBodyInternals.h1086
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp73
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h21
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftBodySolverVertexBuffer.h13
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftBodySolvers.h34
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftMultiBodyDynamicsWorld.cpp241
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftMultiBodyDynamicsWorld.h67
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp35
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftRigidCollisionAlgorithm.h28
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftRigidDynamicsWorld.cpp241
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftRigidDynamicsWorld.h67
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp12
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftSoftCollisionAlgorithm.h28
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSparseSDF.h378
-rw-r--r--thirdparty/bullet/LinearMath/TaskScheduler/btTaskScheduler.cpp1406
-rw-r--r--thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportInterface.h76
-rw-r--r--thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportPosix.cpp458
-rw-r--r--thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportWin32.cpp700
-rw-r--r--thirdparty/bullet/LinearMath/btAabbUtil2.h175
-rw-r--r--thirdparty/bullet/LinearMath/btAlignedAllocator.cpp266
-rw-r--r--thirdparty/bullet/LinearMath/btAlignedAllocator.h100
-rw-r--r--thirdparty/bullet/LinearMath/btAlignedObjectArray.h653
-rw-r--r--thirdparty/bullet/LinearMath/btConvexHull.cpp951
-rw-r--r--thirdparty/bullet/LinearMath/btConvexHull.h180
-rw-r--r--thirdparty/bullet/LinearMath/btConvexHullComputer.cpp1574
-rw-r--r--thirdparty/bullet/LinearMath/btConvexHullComputer.h102
-rw-r--r--thirdparty/bullet/LinearMath/btCpuFeatureUtility.h38
-rw-r--r--thirdparty/bullet/LinearMath/btDefaultMotionState.h28
-rw-r--r--thirdparty/bullet/LinearMath/btGeometryUtil.cpp113
-rw-r--r--thirdparty/bullet/LinearMath/btGeometryUtil.h22
-rw-r--r--thirdparty/bullet/LinearMath/btGrahamScan2dConvexHull.h91
-rw-r--r--thirdparty/bullet/LinearMath/btHashMap.h248
-rw-r--r--thirdparty/bullet/LinearMath/btIDebugDraw.h340
-rw-r--r--thirdparty/bullet/LinearMath/btList.h92
-rw-r--r--thirdparty/bullet/LinearMath/btMatrix3x3.h1472
-rw-r--r--thirdparty/bullet/LinearMath/btMatrixX.h387
-rw-r--r--thirdparty/bullet/LinearMath/btMinMax.h32
-rw-r--r--thirdparty/bullet/LinearMath/btMotionState.h26
-rw-r--r--thirdparty/bullet/LinearMath/btPolarDecomposition.cpp144
-rw-r--r--thirdparty/bullet/LinearMath/btPolarDecomposition.h29
-rw-r--r--thirdparty/bullet/LinearMath/btPoolAllocator.h98
-rw-r--r--thirdparty/bullet/LinearMath/btQuadWord.h244
-rw-r--r--thirdparty/bullet/LinearMath/btQuaternion.h895
-rw-r--r--thirdparty/bullet/LinearMath/btQuickprof.cpp617
-rw-r--r--thirdparty/bullet/LinearMath/btQuickprof.h208
-rw-r--r--thirdparty/bullet/LinearMath/btRandom.h13
-rw-r--r--thirdparty/bullet/LinearMath/btScalar.h18
-rw-r--r--thirdparty/bullet/LinearMath/btSerializer.cpp3
-rw-r--r--thirdparty/bullet/LinearMath/btSerializer.h1195
-rw-r--r--thirdparty/bullet/LinearMath/btSerializer64.cpp2
-rw-r--r--thirdparty/bullet/LinearMath/btSpatialAlgebra.h248
-rw-r--r--thirdparty/bullet/LinearMath/btStackAlloc.h96
-rw-r--r--thirdparty/bullet/LinearMath/btThreads.cpp941
-rw-r--r--thirdparty/bullet/LinearMath/btThreads.h97
-rw-r--r--thirdparty/bullet/LinearMath/btTransform.h207
-rw-r--r--thirdparty/bullet/LinearMath/btTransformUtil.h158
-rw-r--r--thirdparty/bullet/LinearMath/btVector3.cpp3038
-rw-r--r--thirdparty/bullet/LinearMath/btVector3.h1069
-rw-r--r--thirdparty/bullet/btBulletCollisionCommon.h4
-rw-r--r--thirdparty/bullet/btBulletDynamicsCommon.h10
-rw-r--r--thirdparty/bullet/clew/clew.c582
-rw-r--r--thirdparty/bullet/clew/clew.h4597
-rw-r--r--thirdparty/cvtt/LICENSE.txt88
-rw-r--r--thirdparty/enet/enet/godot.h4
-rw-r--r--thirdparty/enet/godot.cpp45
-rw-r--r--thirdparty/freetype/include/freetype/config/ftconfig.h420
-rw-r--r--thirdparty/freetype/include/freetype/config/ftheader.h352
-rw-r--r--thirdparty/freetype/include/freetype/config/ftmodule.h12
-rw-r--r--thirdparty/freetype/include/freetype/config/ftoption.h1381
-rw-r--r--thirdparty/freetype/include/freetype/config/ftstdlib.h160
-rw-r--r--thirdparty/freetype/include/freetype/freetype.h6945
-rw-r--r--thirdparty/freetype/include/freetype/ftadvanc.h239
-rw-r--r--thirdparty/freetype/include/freetype/ftautoh.h533
-rw-r--r--thirdparty/freetype/include/freetype/ftbbox.h129
-rw-r--r--thirdparty/freetype/include/freetype/ftbdf.h241
-rw-r--r--thirdparty/freetype/include/freetype/ftbitmap.h438
-rw-r--r--thirdparty/freetype/include/freetype/ftbzip2.h140
-rw-r--r--thirdparty/freetype/include/freetype/ftcache.h1190
-rw-r--r--thirdparty/freetype/include/freetype/ftcffdrv.h321
-rw-r--r--thirdparty/freetype/include/freetype/ftchapters.h284
-rw-r--r--thirdparty/freetype/include/freetype/ftcid.h102
-rw-r--r--thirdparty/freetype/include/freetype/ftcolor.h311
-rw-r--r--thirdparty/freetype/include/freetype/ftdriver.h749
-rw-r--r--thirdparty/freetype/include/freetype/fterrdef.h101
-rw-r--r--thirdparty/freetype/include/freetype/fterrors.h259
-rw-r--r--thirdparty/freetype/include/freetype/ftfntfmt.h117
-rw-r--r--thirdparty/freetype/include/freetype/ftgasp.h74
-rw-r--r--thirdparty/freetype/include/freetype/ftglyph.h999
-rw-r--r--thirdparty/freetype/include/freetype/ftgxval.h490
-rw-r--r--thirdparty/freetype/include/freetype/ftgzip.h226
-rw-r--r--thirdparty/freetype/include/freetype/ftimage.h1773
-rw-r--r--thirdparty/freetype/include/freetype/ftincrem.h139
-rw-r--r--thirdparty/freetype/include/freetype/ftlcdfil.h311
-rw-r--r--thirdparty/freetype/include/freetype/ftlist.h421
-rw-r--r--thirdparty/freetype/include/freetype/ftlzw.h137
-rw-r--r--thirdparty/freetype/include/freetype/ftmac.h399
-rw-r--r--thirdparty/freetype/include/freetype/ftmm.h1103
-rw-r--r--thirdparty/freetype/include/freetype/ftmodapi.h944
-rw-r--r--thirdparty/freetype/include/freetype/ftmoderr.h191
-rw-r--r--thirdparty/freetype/include/freetype/ftotval.h303
-rw-r--r--thirdparty/freetype/include/freetype/ftoutln.h941
-rw-r--r--thirdparty/freetype/include/freetype/ftparams.h99
-rw-r--r--thirdparty/freetype/include/freetype/ftpcfdrv.h105
-rw-r--r--thirdparty/freetype/include/freetype/ftpfr.h258
-rw-r--r--thirdparty/freetype/include/freetype/ftrender.h214
-rw-r--r--thirdparty/freetype/include/freetype/ftsizes.h239
-rw-r--r--thirdparty/freetype/include/freetype/ftsnames.h394
-rw-r--r--thirdparty/freetype/include/freetype/ftstroke.h431
-rw-r--r--thirdparty/freetype/include/freetype/ftsynth.h38
-rw-r--r--thirdparty/freetype/include/freetype/ftsystem.h134
-rw-r--r--thirdparty/freetype/include/freetype/fttrigon.h84
-rw-r--r--thirdparty/freetype/include/freetype/ftttdrv.h328
-rw-r--r--thirdparty/freetype/include/freetype/fttypes.h851
-rw-r--r--thirdparty/freetype/include/freetype/ftwinfnt.h162
-rw-r--r--thirdparty/freetype/include/freetype/internal/autohint.h326
-rw-r--r--thirdparty/freetype/include/freetype/internal/cffotypes.h88
-rw-r--r--thirdparty/freetype/include/freetype/internal/cfftypes.h95
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftcalc.h246
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftdebug.h248
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftdriver.h400
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftdrv.h336
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftgloadr.h55
-rw-r--r--thirdparty/freetype/include/freetype/internal/fthash.h28
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftmemory.h77
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftobjs.h1267
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftpic.h71
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftpsprop.h32
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftrfork.h305
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftserv.h669
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftstream.h95
-rw-r--r--thirdparty/freetype/include/freetype/internal/fttrace.h83
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftvalid.h82
-rw-r--r--thirdparty/freetype/include/freetype/internal/internal.h45
-rw-r--r--thirdparty/freetype/include/freetype/internal/psaux.h593
-rw-r--r--thirdparty/freetype/include/freetype/internal/pshints.h170
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svbdf.h48
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svcfftl.h54
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svcid.h53
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svfntfmt.h38
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svgldict.h55
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svgxval.h50
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svkern.h32
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svmetric.h62
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svmm.h150
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svotval.h32
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svpfr.h32
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svpostnm.h58
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svprop.h48
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svpscmap.h80
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svpsinfo.h57
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svsfnt.h49
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svttcmap.h94
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svtteng.h34
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svttglyf.h45
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svwinfnt.h32
-rw-r--r--thirdparty/freetype/include/freetype/internal/sfnt.h1093
-rw-r--r--thirdparty/freetype/include/freetype/internal/t1types.h81
-rw-r--r--thirdparty/freetype/include/freetype/internal/tttypes.h2017
-rw-r--r--thirdparty/freetype/include/freetype/t1tables.h616
-rw-r--r--thirdparty/freetype/include/freetype/ttnameid.h138
-rw-r--r--thirdparty/freetype/include/freetype/tttables.h976
-rw-r--r--thirdparty/freetype/include/freetype/tttags.h34
-rw-r--r--thirdparty/freetype/include/freetype/ttunpat.h63
-rw-r--r--thirdparty/freetype/include/ft2build.h64
-rw-r--r--thirdparty/freetype/src/autofit/afangles.c52
-rw-r--r--thirdparty/freetype/src/autofit/afangles.h6
-rw-r--r--thirdparty/freetype/src/autofit/afblue.c32
-rw-r--r--thirdparty/freetype/src/autofit/afblue.cin32
-rw-r--r--thirdparty/freetype/src/autofit/afblue.dat18
-rw-r--r--thirdparty/freetype/src/autofit/afblue.h32
-rw-r--r--thirdparty/freetype/src/autofit/afblue.hin32
-rw-r--r--thirdparty/freetype/src/autofit/afcjk.c190
-rw-r--r--thirdparty/freetype/src/autofit/afcjk.h38
-rw-r--r--thirdparty/freetype/src/autofit/afcover.h32
-rw-r--r--thirdparty/freetype/src/autofit/afdummy.c42
-rw-r--r--thirdparty/freetype/src/autofit/afdummy.h34
-rw-r--r--thirdparty/freetype/src/autofit/aferrors.h48
-rw-r--r--thirdparty/freetype/src/autofit/afglobal.c87
-rw-r--r--thirdparty/freetype/src/autofit/afglobal.h46
-rw-r--r--thirdparty/freetype/src/autofit/afhints.c181
-rw-r--r--thirdparty/freetype/src/autofit/afhints.h238
-rw-r--r--thirdparty/freetype/src/autofit/afindic.c32
-rw-r--r--thirdparty/freetype/src/autofit/afindic.h34
-rw-r--r--thirdparty/freetype/src/autofit/aflatin.c246
-rw-r--r--thirdparty/freetype/src/autofit/aflatin.h44
-rw-r--r--thirdparty/freetype/src/autofit/aflatin2.c147
-rw-r--r--thirdparty/freetype/src/autofit/aflatin2.h34
-rw-r--r--thirdparty/freetype/src/autofit/afloader.c175
-rw-r--r--thirdparty/freetype/src/autofit/afloader.h42
-rw-r--r--thirdparty/freetype/src/autofit/afmodule.c88
-rw-r--r--thirdparty/freetype/src/autofit/afmodule.h36
-rw-r--r--thirdparty/freetype/src/autofit/afpic.c152
-rw-r--r--thirdparty/freetype/src/autofit/afpic.h105
-rw-r--r--thirdparty/freetype/src/autofit/afranges.c32
-rw-r--r--thirdparty/freetype/src/autofit/afranges.h32
-rw-r--r--thirdparty/freetype/src/autofit/afscript.h32
-rw-r--r--thirdparty/freetype/src/autofit/afshaper.c61
-rw-r--r--thirdparty/freetype/src/autofit/afshaper.h32
-rw-r--r--thirdparty/freetype/src/autofit/afstyles.h32
-rw-r--r--thirdparty/freetype/src/autofit/aftypes.h252
-rw-r--r--thirdparty/freetype/src/autofit/afwarp.c54
-rw-r--r--thirdparty/freetype/src/autofit/afwarp.h36
-rw-r--r--thirdparty/freetype/src/autofit/afwrtsys.h32
-rw-r--r--thirdparty/freetype/src/autofit/autofit.c33
-rw-r--r--thirdparty/freetype/src/autofit/module.mk2
-rw-r--r--thirdparty/freetype/src/autofit/rules.mk3
-rw-r--r--thirdparty/freetype/src/base/basepic.c108
-rw-r--r--thirdparty/freetype/src/base/basepic.h91
-rw-r--r--thirdparty/freetype/src/base/ftadvanc.c32
-rw-r--r--thirdparty/freetype/src/base/ftapi.c121
-rw-r--r--thirdparty/freetype/src/base/ftbase.c36
-rw-r--r--thirdparty/freetype/src/base/ftbase.h32
-rw-r--r--thirdparty/freetype/src/base/ftbbox.c356
-rw-r--r--thirdparty/freetype/src/base/ftbdf.c32
-rw-r--r--thirdparty/freetype/src/base/ftbitmap.c369
-rw-r--r--thirdparty/freetype/src/base/ftcalc.c194
-rw-r--r--thirdparty/freetype/src/base/ftcid.c32
-rw-r--r--thirdparty/freetype/src/base/ftcolor.c157
-rw-r--r--thirdparty/freetype/src/base/ftdbgmem.c60
-rw-r--r--thirdparty/freetype/src/base/ftdebug.c179
-rw-r--r--thirdparty/freetype/src/base/fterrors.c45
-rw-r--r--thirdparty/freetype/src/base/ftfntfmt.c32
-rw-r--r--thirdparty/freetype/src/base/ftfstype.c32
-rw-r--r--thirdparty/freetype/src/base/ftgasp.c32
-rw-r--r--thirdparty/freetype/src/base/ftgloadr.c134
-rw-r--r--thirdparty/freetype/src/base/ftglyph.c141
-rw-r--r--thirdparty/freetype/src/base/ftgxval.c50
-rw-r--r--thirdparty/freetype/src/base/fthash.c28
-rw-r--r--thirdparty/freetype/src/base/ftinit.c214
-rw-r--r--thirdparty/freetype/src/base/ftlcdfil.c115
-rw-r--r--thirdparty/freetype/src/base/ftmac.c106
-rw-r--r--thirdparty/freetype/src/base/ftmm.c107
-rw-r--r--thirdparty/freetype/src/base/ftobjs.c585
-rw-r--r--thirdparty/freetype/src/base/ftotval.c32
-rw-r--r--thirdparty/freetype/src/base/ftoutln.c135
-rw-r--r--thirdparty/freetype/src/base/ftpatent.c34
-rw-r--r--thirdparty/freetype/src/base/ftpfr.c32
-rw-r--r--thirdparty/freetype/src/base/ftpic.c55
-rw-r--r--thirdparty/freetype/src/base/ftpsprop.c48
-rw-r--r--thirdparty/freetype/src/base/ftrfork.c72
-rw-r--r--thirdparty/freetype/src/base/ftsnames.c78
-rw-r--r--thirdparty/freetype/src/base/ftstream.c58
-rw-r--r--thirdparty/freetype/src/base/ftstroke.c64
-rw-r--r--thirdparty/freetype/src/base/ftsynth.c46
-rw-r--r--thirdparty/freetype/src/base/ftsystem.c281
-rw-r--r--thirdparty/freetype/src/base/fttrigon.c76
-rw-r--r--thirdparty/freetype/src/base/fttype1.c32
-rw-r--r--thirdparty/freetype/src/base/ftutil.c54
-rw-r--r--thirdparty/freetype/src/base/ftver.rc10
-rw-r--r--thirdparty/freetype/src/base/ftwinfnt.c32
-rw-r--r--thirdparty/freetype/src/base/rules.mk11
-rw-r--r--thirdparty/freetype/src/bdf/bdf.h76
-rw-r--r--thirdparty/freetype/src/bdf/bdfdrivr.c43
-rw-r--r--thirdparty/freetype/src/bdf/bdfdrivr.h9
-rw-r--r--thirdparty/freetype/src/bdf/bdferror.h10
-rw-r--r--thirdparty/freetype/src/bdf/bdflib.c192
-rw-r--r--thirdparty/freetype/src/bzip2/ftbzip2.c52
-rw-r--r--thirdparty/freetype/src/bzip2/rules.mk2
-rw-r--r--thirdparty/freetype/src/cache/ftcache.c32
-rw-r--r--thirdparty/freetype/src/cache/ftcbasic.c36
-rw-r--r--thirdparty/freetype/src/cache/ftccache.c34
-rw-r--r--thirdparty/freetype/src/cache/ftccache.h64
-rw-r--r--thirdparty/freetype/src/cache/ftccback.h32
-rw-r--r--thirdparty/freetype/src/cache/ftccmap.c62
-rw-r--r--thirdparty/freetype/src/cache/ftcerror.h48
-rw-r--r--thirdparty/freetype/src/cache/ftcglyph.c32
-rw-r--r--thirdparty/freetype/src/cache/ftcglyph.h166
-rw-r--r--thirdparty/freetype/src/cache/ftcimage.c32
-rw-r--r--thirdparty/freetype/src/cache/ftcimage.h50
-rw-r--r--thirdparty/freetype/src/cache/ftcmanag.c38
-rw-r--r--thirdparty/freetype/src/cache/ftcmanag.h143
-rw-r--r--thirdparty/freetype/src/cache/ftcmru.c32
-rw-r--r--thirdparty/freetype/src/cache/ftcmru.h80
-rw-r--r--thirdparty/freetype/src/cache/ftcsbits.c92
-rw-r--r--thirdparty/freetype/src/cache/ftcsbits.h32
-rw-r--r--thirdparty/freetype/src/cache/rules.mk2
-rw-r--r--thirdparty/freetype/src/cff/cf2arrst.c241
-rw-r--r--thirdparty/freetype/src/cff/cf2arrst.h100
-rw-r--r--thirdparty/freetype/src/cff/cf2blues.c582
-rw-r--r--thirdparty/freetype/src/cff/cf2blues.h185
-rw-r--r--thirdparty/freetype/src/cff/cf2error.c52
-rw-r--r--thirdparty/freetype/src/cff/cf2error.h119
-rw-r--r--thirdparty/freetype/src/cff/cf2fixed.h95
-rw-r--r--thirdparty/freetype/src/cff/cf2font.c562
-rw-r--r--thirdparty/freetype/src/cff/cf2font.h130
-rw-r--r--thirdparty/freetype/src/cff/cf2ft.c755
-rw-r--r--thirdparty/freetype/src/cff/cf2ft.h159
-rw-r--r--thirdparty/freetype/src/cff/cf2glue.h144
-rw-r--r--thirdparty/freetype/src/cff/cf2hints.c1875
-rw-r--r--thirdparty/freetype/src/cff/cf2hints.h289
-rw-r--r--thirdparty/freetype/src/cff/cf2intrp.c1959
-rw-r--r--thirdparty/freetype/src/cff/cf2intrp.h83
-rw-r--r--thirdparty/freetype/src/cff/cf2read.c112
-rw-r--r--thirdparty/freetype/src/cff/cf2read.h68
-rw-r--r--thirdparty/freetype/src/cff/cf2stack.c328
-rw-r--r--thirdparty/freetype/src/cff/cf2stack.h121
-rw-r--r--thirdparty/freetype/src/cff/cf2types.h78
-rw-r--r--thirdparty/freetype/src/cff/cff.c33
-rw-r--r--thirdparty/freetype/src/cff/cffcmap.c35
-rw-r--r--thirdparty/freetype/src/cff/cffcmap.h32
-rw-r--r--thirdparty/freetype/src/cff/cffdrivr.c322
-rw-r--r--thirdparty/freetype/src/cff/cffdrivr.h34
-rw-r--r--thirdparty/freetype/src/cff/cfferrs.h46
-rw-r--r--thirdparty/freetype/src/cff/cffgload.c64
-rw-r--r--thirdparty/freetype/src/cff/cffgload.h32
-rw-r--r--thirdparty/freetype/src/cff/cffload.c61
-rw-r--r--thirdparty/freetype/src/cff/cffload.h32
-rw-r--r--thirdparty/freetype/src/cff/cffobjs.c116
-rw-r--r--thirdparty/freetype/src/cff/cffobjs.h48
-rw-r--r--thirdparty/freetype/src/cff/cffparse.c333
-rw-r--r--thirdparty/freetype/src/cff/cffparse.h42
-rw-r--r--thirdparty/freetype/src/cff/cffpic.c138
-rw-r--r--thirdparty/freetype/src/cff/cffpic.h121
-rw-r--r--thirdparty/freetype/src/cff/cfftoken.h32
-rw-r--r--thirdparty/freetype/src/cff/cfftypes.h405
-rw-r--r--thirdparty/freetype/src/cff/module.mk2
-rw-r--r--thirdparty/freetype/src/cff/rules.mk5
-rw-r--r--thirdparty/freetype/src/cid/ciderrs.h46
-rw-r--r--thirdparty/freetype/src/cid/cidgload.c49
-rw-r--r--thirdparty/freetype/src/cid/cidgload.h32
-rw-r--r--thirdparty/freetype/src/cid/cidload.c185
-rw-r--r--thirdparty/freetype/src/cid/cidload.h32
-rw-r--r--thirdparty/freetype/src/cid/cidobjs.c204
-rw-r--r--thirdparty/freetype/src/cid/cidobjs.h116
-rw-r--r--thirdparty/freetype/src/cid/cidparse.c46
-rw-r--r--thirdparty/freetype/src/cid/cidparse.h108
-rw-r--r--thirdparty/freetype/src/cid/cidriver.c56
-rw-r--r--thirdparty/freetype/src/cid/cidriver.h38
-rw-r--r--thirdparty/freetype/src/cid/cidtoken.h57
-rw-r--r--thirdparty/freetype/src/cid/module.mk2
-rw-r--r--thirdparty/freetype/src/cid/rules.mk2
-rw-r--r--thirdparty/freetype/src/cid/type1cid.c32
-rw-r--r--thirdparty/freetype/src/gxvalid/README2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvalid.c34
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvalid.h50
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvbsln.c64
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvcommn.c68
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvcommn.h60
-rw-r--r--thirdparty/freetype/src/gxvalid/gxverror.h66
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvfeat.c64
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvfeat.h50
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvfgen.c114
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvjust.c66
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvkern.c64
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvlcar.c64
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmod.c64
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmod.h56
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmort.c65
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmort.h50
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmort0.c66
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmort1.c66
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmort2.c66
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmort4.c66
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmort5.c66
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmorx.c64
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmorx.h50
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmorx0.c66
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmorx1.c66
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmorx2.c66
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmorx4.c66
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmorx5.c66
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvopbd.c64
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvprop.c64
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvtrak.c64
-rw-r--r--thirdparty/freetype/src/gxvalid/module.mk2
-rw-r--r--thirdparty/freetype/src/gxvalid/rules.mk2
-rw-r--r--thirdparty/freetype/src/gzip/ftgzip.c62
-rw-r--r--thirdparty/freetype/src/gzip/rules.mk2
-rw-r--r--thirdparty/freetype/src/lzw/ftlzw.c56
-rw-r--r--thirdparty/freetype/src/lzw/ftzopen.c48
-rw-r--r--thirdparty/freetype/src/lzw/ftzopen.h116
-rw-r--r--thirdparty/freetype/src/lzw/rules.mk2
-rw-r--r--thirdparty/freetype/src/otvalid/module.mk2
-rw-r--r--thirdparty/freetype/src/otvalid/otvalid.c32
-rw-r--r--thirdparty/freetype/src/otvalid/otvalid.h32
-rw-r--r--thirdparty/freetype/src/otvalid/otvbase.c46
-rw-r--r--thirdparty/freetype/src/otvalid/otvcommn.c46
-rw-r--r--thirdparty/freetype/src/otvalid/otvcommn.h32
-rw-r--r--thirdparty/freetype/src/otvalid/otverror.h48
-rw-r--r--thirdparty/freetype/src/otvalid/otvgdef.c46
-rw-r--r--thirdparty/freetype/src/otvalid/otvgpos.c46
-rw-r--r--thirdparty/freetype/src/otvalid/otvgpos.h32
-rw-r--r--thirdparty/freetype/src/otvalid/otvgsub.c46
-rw-r--r--thirdparty/freetype/src/otvalid/otvjstf.c46
-rw-r--r--thirdparty/freetype/src/otvalid/otvmath.c50
-rw-r--r--thirdparty/freetype/src/otvalid/otvmod.c46
-rw-r--r--thirdparty/freetype/src/otvalid/otvmod.h38
-rw-r--r--thirdparty/freetype/src/otvalid/rules.mk2
-rw-r--r--thirdparty/freetype/src/pcf/pcf.h56
-rw-r--r--thirdparty/freetype/src/pcf/pcfdrivr.c163
-rw-r--r--thirdparty/freetype/src/pcf/pcfdrivr.h5
-rw-r--r--thirdparty/freetype/src/pcf/pcferror.h46
-rw-r--r--thirdparty/freetype/src/pcf/pcfread.c293
-rw-r--r--thirdparty/freetype/src/pcf/pcfutil.c6
-rw-r--r--thirdparty/freetype/src/pfr/module.mk2
-rw-r--r--thirdparty/freetype/src/pfr/pfr.c32
-rw-r--r--thirdparty/freetype/src/pfr/pfrcmap.c32
-rw-r--r--thirdparty/freetype/src/pfr/pfrcmap.h32
-rw-r--r--thirdparty/freetype/src/pfr/pfrdrivr.c48
-rw-r--r--thirdparty/freetype/src/pfr/pfrdrivr.h38
-rw-r--r--thirdparty/freetype/src/pfr/pfrerror.h46
-rw-r--r--thirdparty/freetype/src/pfr/pfrgload.c52
-rw-r--r--thirdparty/freetype/src/pfr/pfrgload.h32
-rw-r--r--thirdparty/freetype/src/pfr/pfrload.c162
-rw-r--r--thirdparty/freetype/src/pfr/pfrload.h32
-rw-r--r--thirdparty/freetype/src/pfr/pfrobjs.c38
-rw-r--r--thirdparty/freetype/src/pfr/pfrobjs.h32
-rw-r--r--thirdparty/freetype/src/pfr/pfrsbit.c34
-rw-r--r--thirdparty/freetype/src/pfr/pfrsbit.h32
-rw-r--r--thirdparty/freetype/src/pfr/pfrtypes.h32
-rw-r--r--thirdparty/freetype/src/pfr/rules.mk2
-rw-r--r--thirdparty/freetype/src/psaux/afmparse.c56
-rw-r--r--thirdparty/freetype/src/psaux/afmparse.h32
-rw-r--r--thirdparty/freetype/src/psaux/cffdecode.c300
-rw-r--r--thirdparty/freetype/src/psaux/cffdecode.h32
-rw-r--r--thirdparty/freetype/src/psaux/module.mk2
-rw-r--r--thirdparty/freetype/src/psaux/psarrst.c72
-rw-r--r--thirdparty/freetype/src/psaux/psarrst.h72
-rw-r--r--thirdparty/freetype/src/psaux/psaux.c32
-rw-r--r--thirdparty/freetype/src/psaux/psauxerr.h48
-rw-r--r--thirdparty/freetype/src/psaux/psauxmod.c32
-rw-r--r--thirdparty/freetype/src/psaux/psauxmod.h36
-rw-r--r--thirdparty/freetype/src/psaux/psblues.c100
-rw-r--r--thirdparty/freetype/src/psaux/psblues.h72
-rw-r--r--thirdparty/freetype/src/psaux/psconv.c46
-rw-r--r--thirdparty/freetype/src/psaux/psconv.h32
-rw-r--r--thirdparty/freetype/src/psaux/pserror.c72
-rw-r--r--thirdparty/freetype/src/psaux/pserror.h72
-rw-r--r--thirdparty/freetype/src/psaux/psfixed.h72
-rw-r--r--thirdparty/freetype/src/psaux/psfont.c76
-rw-r--r--thirdparty/freetype/src/psaux/psfont.h72
-rw-r--r--thirdparty/freetype/src/psaux/psft.c95
-rw-r--r--thirdparty/freetype/src/psaux/psft.h72
-rw-r--r--thirdparty/freetype/src/psaux/psglue.h72
-rw-r--r--thirdparty/freetype/src/psaux/pshints.c117
-rw-r--r--thirdparty/freetype/src/psaux/pshints.h72
-rw-r--r--thirdparty/freetype/src/psaux/psintrp.c148
-rw-r--r--thirdparty/freetype/src/psaux/psintrp.h72
-rw-r--r--thirdparty/freetype/src/psaux/psobjs.c478
-rw-r--r--thirdparty/freetype/src/psaux/psobjs.h32
-rw-r--r--thirdparty/freetype/src/psaux/psread.c74
-rw-r--r--thirdparty/freetype/src/psaux/psread.h72
-rw-r--r--thirdparty/freetype/src/psaux/psstack.c75
-rw-r--r--thirdparty/freetype/src/psaux/psstack.h72
-rw-r--r--thirdparty/freetype/src/psaux/pstypes.h72
-rw-r--r--thirdparty/freetype/src/psaux/rules.mk2
-rw-r--r--thirdparty/freetype/src/psaux/t1cmap.c35
-rw-r--r--thirdparty/freetype/src/psaux/t1cmap.h32
-rw-r--r--thirdparty/freetype/src/psaux/t1decode.c341
-rw-r--r--thirdparty/freetype/src/psaux/t1decode.h32
-rw-r--r--thirdparty/freetype/src/pshinter/module.mk2
-rw-r--r--thirdparty/freetype/src/pshinter/pshalgo.c50
-rw-r--r--thirdparty/freetype/src/pshinter/pshalgo.h32
-rw-r--r--thirdparty/freetype/src/pshinter/pshglob.c39
-rw-r--r--thirdparty/freetype/src/pshinter/pshglob.h68
-rw-r--r--thirdparty/freetype/src/pshinter/pshinter.c33
-rw-r--r--thirdparty/freetype/src/pshinter/pshmod.c35
-rw-r--r--thirdparty/freetype/src/pshinter/pshmod.h32
-rw-r--r--thirdparty/freetype/src/pshinter/pshnterr.h46
-rw-r--r--thirdparty/freetype/src/pshinter/pshpic.c76
-rw-r--r--thirdparty/freetype/src/pshinter/pshpic.h63
-rw-r--r--thirdparty/freetype/src/pshinter/pshrec.c38
-rw-r--r--thirdparty/freetype/src/pshinter/pshrec.h56
-rw-r--r--thirdparty/freetype/src/pshinter/rules.mk3
-rw-r--r--thirdparty/freetype/src/psnames/module.mk2
-rw-r--r--thirdparty/freetype/src/psnames/psmodule.c73
-rw-r--r--thirdparty/freetype/src/psnames/psmodule.h32
-rw-r--r--thirdparty/freetype/src/psnames/psnamerr.h48
-rw-r--r--thirdparty/freetype/src/psnames/psnames.c33
-rw-r--r--thirdparty/freetype/src/psnames/pspic.c97
-rw-r--r--thirdparty/freetype/src/psnames/pspic.h68
-rw-r--r--thirdparty/freetype/src/psnames/pstables.h44
-rw-r--r--thirdparty/freetype/src/psnames/rules.mk21
-rw-r--r--thirdparty/freetype/src/raster/ftmisc.h50
-rw-r--r--thirdparty/freetype/src/raster/ftraster.c1213
-rw-r--r--thirdparty/freetype/src/raster/ftraster.h42
-rw-r--r--thirdparty/freetype/src/raster/ftrend1.c41
-rw-r--r--thirdparty/freetype/src/raster/ftrend1.h32
-rw-r--r--thirdparty/freetype/src/raster/module.mk2
-rw-r--r--thirdparty/freetype/src/raster/raster.c33
-rw-r--r--thirdparty/freetype/src/raster/rasterrs.h48
-rw-r--r--thirdparty/freetype/src/raster/rastpic.c89
-rw-r--r--thirdparty/freetype/src/raster/rastpic.h63
-rw-r--r--thirdparty/freetype/src/raster/rules.mk5
-rw-r--r--thirdparty/freetype/src/sfnt/module.mk2
-rw-r--r--thirdparty/freetype/src/sfnt/pngshim.c34
-rw-r--r--thirdparty/freetype/src/sfnt/pngshim.h34
-rw-r--r--thirdparty/freetype/src/sfnt/rules.mk21
-rw-r--r--thirdparty/freetype/src/sfnt/sfdriver.c241
-rw-r--r--thirdparty/freetype/src/sfnt/sfdriver.h34
-rw-r--r--thirdparty/freetype/src/sfnt/sferrors.h46
-rw-r--r--thirdparty/freetype/src/sfnt/sfnt.c36
-rw-r--r--thirdparty/freetype/src/sfnt/sfntpic.c143
-rw-r--r--thirdparty/freetype/src/sfnt/sfntpic.h112
-rw-r--r--thirdparty/freetype/src/sfnt/sfobjs.c255
-rw-r--r--thirdparty/freetype/src/sfnt/sfobjs.h32
-rw-r--r--thirdparty/freetype/src/sfnt/ttbdf.c54
-rw-r--r--thirdparty/freetype/src/sfnt/ttbdf.h32
-rw-r--r--thirdparty/freetype/src/sfnt/ttcmap.c651
-rw-r--r--thirdparty/freetype/src/sfnt/ttcmap.h70
-rw-r--r--thirdparty/freetype/src/sfnt/ttcmapc.h32
-rw-r--r--thirdparty/freetype/src/sfnt/ttcolr.c451
-rw-r--r--thirdparty/freetype/src/sfnt/ttcolr.h58
-rw-r--r--thirdparty/freetype/src/sfnt/ttcpal.c311
-rw-r--r--thirdparty/freetype/src/sfnt/ttcpal.h49
-rw-r--r--thirdparty/freetype/src/sfnt/ttkern.c56
-rw-r--r--thirdparty/freetype/src/sfnt/ttkern.h34
-rw-r--r--thirdparty/freetype/src/sfnt/ttload.c569
-rw-r--r--thirdparty/freetype/src/sfnt/ttload.h34
-rw-r--r--thirdparty/freetype/src/sfnt/ttmtx.c181
-rw-r--r--thirdparty/freetype/src/sfnt/ttmtx.h32
-rw-r--r--thirdparty/freetype/src/sfnt/ttpost.c117
-rw-r--r--thirdparty/freetype/src/sfnt/ttpost.h34
-rw-r--r--thirdparty/freetype/src/sfnt/ttsbit.c64
-rw-r--r--thirdparty/freetype/src/sfnt/ttsbit.h32
-rw-r--r--thirdparty/freetype/src/smooth/ftgrays.c451
-rw-r--r--thirdparty/freetype/src/smooth/ftgrays.h49
-rw-r--r--thirdparty/freetype/src/smooth/ftsmerrs.h48
-rw-r--r--thirdparty/freetype/src/smooth/ftsmooth.c125
-rw-r--r--thirdparty/freetype/src/smooth/ftsmooth.h32
-rw-r--r--thirdparty/freetype/src/smooth/ftspic.c118
-rw-r--r--thirdparty/freetype/src/smooth/ftspic.h75
-rw-r--r--thirdparty/freetype/src/smooth/module.mk2
-rw-r--r--thirdparty/freetype/src/smooth/rules.mk5
-rw-r--r--thirdparty/freetype/src/smooth/smooth.c33
-rw-r--r--thirdparty/freetype/src/truetype/module.mk2
-rw-r--r--thirdparty/freetype/src/truetype/rules.mk3
-rw-r--r--thirdparty/freetype/src/truetype/truetype.c33
-rw-r--r--thirdparty/freetype/src/truetype/ttdriver.c224
-rw-r--r--thirdparty/freetype/src/truetype/ttdriver.h34
-rw-r--r--thirdparty/freetype/src/truetype/tterrors.h48
-rw-r--r--thirdparty/freetype/src/truetype/ttgload.c432
-rw-r--r--thirdparty/freetype/src/truetype/ttgload.h32
-rw-r--r--thirdparty/freetype/src/truetype/ttgxvar.c1364
-rw-r--r--thirdparty/freetype/src/truetype/ttgxvar.h312
-rw-r--r--thirdparty/freetype/src/truetype/ttinterp.c3262
-rw-r--r--thirdparty/freetype/src/truetype/ttinterp.h168
-rw-r--r--thirdparty/freetype/src/truetype/ttobjs.c464
-rw-r--r--thirdparty/freetype/src/truetype/ttobjs.h312
-rw-r--r--thirdparty/freetype/src/truetype/ttpic.c101
-rw-r--r--thirdparty/freetype/src/truetype/ttpic.h88
-rw-r--r--thirdparty/freetype/src/truetype/ttpload.c238
-rw-r--r--thirdparty/freetype/src/truetype/ttpload.h32
-rw-r--r--thirdparty/freetype/src/truetype/ttsubpix.c90
-rw-r--r--thirdparty/freetype/src/truetype/ttsubpix.h52
-rw-r--r--thirdparty/freetype/src/type1/module.mk2
-rw-r--r--thirdparty/freetype/src/type1/rules.mk2
-rw-r--r--thirdparty/freetype/src/type1/t1afm.c46
-rw-r--r--thirdparty/freetype/src/type1/t1afm.h32
-rw-r--r--thirdparty/freetype/src/type1/t1driver.c213
-rw-r--r--thirdparty/freetype/src/type1/t1driver.h38
-rw-r--r--thirdparty/freetype/src/type1/t1errors.h46
-rw-r--r--thirdparty/freetype/src/type1/t1gload.c77
-rw-r--r--thirdparty/freetype/src/type1/t1gload.h32
-rw-r--r--thirdparty/freetype/src/type1/t1load.c420
-rw-r--r--thirdparty/freetype/src/type1/t1load.h42
-rw-r--r--thirdparty/freetype/src/type1/t1objs.c213
-rw-r--r--thirdparty/freetype/src/type1/t1objs.h132
-rw-r--r--thirdparty/freetype/src/type1/t1parse.c110
-rw-r--r--thirdparty/freetype/src/type1/t1parse.h101
-rw-r--r--thirdparty/freetype/src/type1/t1tokens.h32
-rw-r--r--thirdparty/freetype/src/type1/type1.c32
-rw-r--r--thirdparty/freetype/src/type42/module.mk2
-rw-r--r--thirdparty/freetype/src/type42/rules.mk2
-rw-r--r--thirdparty/freetype/src/type42/t42drivr.c82
-rw-r--r--thirdparty/freetype/src/type42/t42drivr.h38
-rw-r--r--thirdparty/freetype/src/type42/t42error.h46
-rw-r--r--thirdparty/freetype/src/type42/t42objs.c66
-rw-r--r--thirdparty/freetype/src/type42/t42objs.h32
-rw-r--r--thirdparty/freetype/src/type42/t42parse.c87
-rw-r--r--thirdparty/freetype/src/type42/t42parse.h32
-rw-r--r--thirdparty/freetype/src/type42/t42types.h32
-rw-r--r--thirdparty/freetype/src/type42/type42.c32
-rw-r--r--thirdparty/freetype/src/winfonts/fnterrs.h48
-rw-r--r--thirdparty/freetype/src/winfonts/module.mk2
-rw-r--r--thirdparty/freetype/src/winfonts/rules.mk2
-rw-r--r--thirdparty/freetype/src/winfonts/winfnt.c58
-rw-r--r--thirdparty/freetype/src/winfonts/winfnt.h40
-rw-r--r--thirdparty/glad/LICENSE20
-rw-r--r--thirdparty/glad/glad.c30
-rw-r--r--thirdparty/glad/glad/glad.h29
-rw-r--r--thirdparty/libpng/LICENSE177
-rw-r--r--thirdparty/libpng/arm/arm_init.c3
-rw-r--r--thirdparty/libpng/arm/filter_neon.S2
-rw-r--r--thirdparty/libpng/arm/filter_neon_intrinsics.c27
-rw-r--r--thirdparty/libpng/arm/palette_neon_intrinsics.c149
-rw-r--r--thirdparty/libpng/png.c53
-rw-r--r--thirdparty/libpng/png.h408
-rw-r--r--thirdparty/libpng/pngconf.h18
-rw-r--r--thirdparty/libpng/pngdebug.h6
-rw-r--r--thirdparty/libpng/pngerror.c12
-rw-r--r--thirdparty/libpng/pngget.c168
-rw-r--r--thirdparty/libpng/pnginfo.h19
-rw-r--r--thirdparty/libpng/pnglibconf.h11
-rw-r--r--thirdparty/libpng/pngmem.c6
-rw-r--r--thirdparty/libpng/pngpread.c215
-rw-r--r--thirdparty/libpng/pngpriv.h93
-rw-r--r--thirdparty/libpng/pngread.c118
-rw-r--r--thirdparty/libpng/pngrio.c6
-rw-r--r--thirdparty/libpng/pngrtran.c116
-rw-r--r--thirdparty/libpng/pngrutil.c329
-rw-r--r--thirdparty/libpng/pngset.c158
-rw-r--r--thirdparty/libpng/pngstruct.h33
-rw-r--r--thirdparty/libpng/pngtrans.c12
-rw-r--r--thirdparty/libpng/pngwio.c6
-rw-r--r--thirdparty/libpng/pngwrite.c80
-rw-r--r--thirdparty/libpng/pngwtran.c11
-rw-r--r--thirdparty/libpng/pngwutil.c177
-rw-r--r--thirdparty/libsimplewebm/OpusVorbisDecoder.cpp2
-rw-r--r--thirdparty/libsimplewebm/OpusVorbisDecoder.hpp4
-rw-r--r--thirdparty/libsimplewebm/VPXDecoder.cpp14
-rw-r--r--thirdparty/libsimplewebm/VPXDecoder.hpp6
-rw-r--r--thirdparty/libtheora/decode.c8
-rw-r--r--thirdparty/libtheora/patches/theora.git-0ae66d565e6bead8604d312bc1a4e9dccf245c88.patch38
-rw-r--r--thirdparty/libvpx/rtcd/vpx_dsp_rtcd_x86.h10
-rw-r--r--thirdparty/libvpx/vpx_config.h4
-rw-r--r--thirdparty/libwebp/AUTHORS5
-rw-r--r--thirdparty/libwebp/src/dec/vp8i_dec.h2
-rw-r--r--thirdparty/libwebp/src/demux/demux.c2
-rw-r--r--thirdparty/libwebp/src/dsp/cost.c6
-rw-r--r--thirdparty/libwebp/src/dsp/cost_neon.c122
-rw-r--r--thirdparty/libwebp/src/dsp/quant.h70
-rw-r--r--thirdparty/libwebp/src/enc/histogram_enc.c368
-rw-r--r--thirdparty/libwebp/src/enc/predictor_enc.c14
-rw-r--r--thirdparty/libwebp/src/enc/quant_enc.c14
-rw-r--r--thirdparty/libwebp/src/enc/vp8i_enc.h2
-rw-r--r--thirdparty/libwebp/src/enc/vp8l_enc.c1
-rw-r--r--thirdparty/libwebp/src/mux/muxi.h2
-rw-r--r--thirdparty/libwebp/src/utils/bit_writer_utils.c1
-rw-r--r--thirdparty/libwebp/src/utils/utils.h26
-rw-r--r--thirdparty/libwebp/src/webp/decode.h12
-rw-r--r--thirdparty/libwebsockets/ipv6_fixes.diff32
-rw-r--r--thirdparty/libwebsockets/lws_config.h5
-rw-r--r--thirdparty/libwebsockets/plat/lws-plat-unix.c5
-rw-r--r--thirdparty/libwebsockets/plat/lws-plat-win.c5
-rw-r--r--thirdparty/mbedtls/1453.diff22
-rw-r--r--thirdparty/mbedtls/include/mbedtls/aes.h76
-rw-r--r--thirdparty/mbedtls/include/mbedtls/aesni.h46
-rw-r--r--thirdparty/mbedtls/include/mbedtls/arc4.h3
-rw-r--r--thirdparty/mbedtls/include/mbedtls/aria.h105
-rw-r--r--thirdparty/mbedtls/include/mbedtls/asn1write.h310
-rw-r--r--thirdparty/mbedtls/include/mbedtls/bignum.h807
-rw-r--r--thirdparty/mbedtls/include/mbedtls/blowfish.h143
-rw-r--r--thirdparty/mbedtls/include/mbedtls/bn_mul.h44
-rw-r--r--thirdparty/mbedtls/include/mbedtls/camellia.h219
-rw-r--r--thirdparty/mbedtls/include/mbedtls/ccm.h115
-rw-r--r--thirdparty/mbedtls/include/mbedtls/chacha20.h56
-rw-r--r--thirdparty/mbedtls/include/mbedtls/chachapoly.h85
-rw-r--r--thirdparty/mbedtls/include/mbedtls/check_config.h15
-rw-r--r--thirdparty/mbedtls/include/mbedtls/cipher.h237
-rw-r--r--thirdparty/mbedtls/include/mbedtls/cmac.h1
-rw-r--r--thirdparty/mbedtls/include/mbedtls/config.h240
-rw-r--r--thirdparty/mbedtls/include/mbedtls/ctr_drbg.h66
-rw-r--r--thirdparty/mbedtls/include/mbedtls/debug.h36
-rw-r--r--thirdparty/mbedtls/include/mbedtls/des.h6
-rw-r--r--thirdparty/mbedtls/include/mbedtls/dhm.h172
-rw-r--r--thirdparty/mbedtls/include/mbedtls/ecdh.h288
-rw-r--r--thirdparty/mbedtls/include/mbedtls/ecdsa.h326
-rw-r--r--thirdparty/mbedtls/include/mbedtls/ecjpake.h145
-rw-r--r--thirdparty/mbedtls/include/mbedtls/ecp.h590
-rw-r--r--thirdparty/mbedtls/include/mbedtls/entropy.h4
-rw-r--r--thirdparty/mbedtls/include/mbedtls/error.h13
-rw-r--r--thirdparty/mbedtls/include/mbedtls/gcm.h100
-rw-r--r--thirdparty/mbedtls/include/mbedtls/havege.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/hkdf.h14
-rw-r--r--thirdparty/mbedtls/include/mbedtls/hmac_drbg.h32
-rw-r--r--thirdparty/mbedtls/include/mbedtls/md.h5
-rw-r--r--thirdparty/mbedtls/include/mbedtls/md2.h3
-rw-r--r--thirdparty/mbedtls/include/mbedtls/md4.h3
-rw-r--r--thirdparty/mbedtls/include/mbedtls/md5.h3
-rw-r--r--thirdparty/mbedtls/include/mbedtls/net_sockets.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/oid.h3
-rw-r--r--thirdparty/mbedtls/include/mbedtls/padlock.h34
-rw-r--r--thirdparty/mbedtls/include/mbedtls/pem.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/pk.h221
-rw-r--r--thirdparty/mbedtls/include/mbedtls/pk_internal.h23
-rw-r--r--thirdparty/mbedtls/include/mbedtls/pkcs11.h3
-rw-r--r--thirdparty/mbedtls/include/mbedtls/pkcs12.h4
-rw-r--r--thirdparty/mbedtls/include/mbedtls/pkcs5.h4
-rw-r--r--thirdparty/mbedtls/include/mbedtls/platform.h6
-rw-r--r--thirdparty/mbedtls/include/mbedtls/platform_util.h123
-rw-r--r--thirdparty/mbedtls/include/mbedtls/poly1305.h55
-rw-r--r--thirdparty/mbedtls/include/mbedtls/ripemd160.h4
-rw-r--r--thirdparty/mbedtls/include/mbedtls/rsa.h596
-rw-r--r--thirdparty/mbedtls/include/mbedtls/sha1.h64
-rw-r--r--thirdparty/mbedtls/include/mbedtls/sha256.h91
-rw-r--r--thirdparty/mbedtls/include/mbedtls/sha512.h91
-rw-r--r--thirdparty/mbedtls/include/mbedtls/ssl.h380
-rw-r--r--thirdparty/mbedtls/include/mbedtls/ssl_cookie.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/ssl_internal.h74
-rw-r--r--thirdparty/mbedtls/include/mbedtls/ssl_ticket.h4
-rw-r--r--thirdparty/mbedtls/include/mbedtls/threading.h16
-rw-r--r--thirdparty/mbedtls/include/mbedtls/timing.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/version.h8
-rw-r--r--thirdparty/mbedtls/include/mbedtls/x509_crt.h139
-rw-r--r--thirdparty/mbedtls/include/mbedtls/xtea.h4
-rw-r--r--thirdparty/mbedtls/library/aes.c134
-rw-r--r--thirdparty/mbedtls/library/aria.c85
-rw-r--r--thirdparty/mbedtls/library/asn1write.c57
-rw-r--r--thirdparty/mbedtls/library/bignum.c265
-rw-r--r--thirdparty/mbedtls/library/blowfish.c58
-rw-r--r--thirdparty/mbedtls/library/camellia.c70
-rw-r--r--thirdparty/mbedtls/library/ccm.c73
-rw-r--r--thirdparty/mbedtls/library/certs.c43
-rw-r--r--thirdparty/mbedtls/library/chacha20.c48
-rw-r--r--thirdparty/mbedtls/library/chachapoly.c111
-rw-r--r--thirdparty/mbedtls/library/cipher.c140
-rw-r--r--thirdparty/mbedtls/library/cipher_wrap.c6
-rw-r--r--thirdparty/mbedtls/library/ctr_drbg.c175
-rw-r--r--thirdparty/mbedtls/library/debug.c50
-rw-r--r--thirdparty/mbedtls/library/dhm.c58
-rw-r--r--thirdparty/mbedtls/library/ecdh.c535
-rw-r--r--thirdparty/mbedtls/library/ecdsa.c563
-rw-r--r--thirdparty/mbedtls/library/ecjpake.c38
-rw-r--r--thirdparty/mbedtls/library/ecp.c1204
-rw-r--r--thirdparty/mbedtls/library/ecp_curves.c8
-rw-r--r--thirdparty/mbedtls/library/entropy_poll.c57
-rw-r--r--thirdparty/mbedtls/library/entropy_poll.c.orig275
-rw-r--r--thirdparty/mbedtls/library/error.c39
-rw-r--r--thirdparty/mbedtls/library/gcm.c50
-rw-r--r--thirdparty/mbedtls/library/hmac_drbg.c124
-rw-r--r--thirdparty/mbedtls/library/nist_kw.c4
-rw-r--r--thirdparty/mbedtls/library/pem.c6
-rw-r--r--thirdparty/mbedtls/library/pk.c209
-rw-r--r--thirdparty/mbedtls/library/pk_wrap.c200
-rw-r--r--thirdparty/mbedtls/library/pkcs12.c4
-rw-r--r--thirdparty/mbedtls/library/pkcs5.c17
-rw-r--r--thirdparty/mbedtls/library/pkparse.c89
-rw-r--r--thirdparty/mbedtls/library/pkwrite.c32
-rw-r--r--thirdparty/mbedtls/library/platform.c13
-rw-r--r--thirdparty/mbedtls/library/platform_util.c69
-rw-r--r--thirdparty/mbedtls/library/poly1305.c48
-rw-r--r--thirdparty/mbedtls/library/rsa.c490
-rw-r--r--thirdparty/mbedtls/library/rsa_internal.c9
-rw-r--r--thirdparty/mbedtls/library/sha1.c24
-rw-r--r--thirdparty/mbedtls/library/sha256.c25
-rw-r--r--thirdparty/mbedtls/library/sha512.c25
-rw-r--r--thirdparty/mbedtls/library/ssl_ciphersuites.c6
-rw-r--r--thirdparty/mbedtls/library/ssl_cli.c196
-rw-r--r--thirdparty/mbedtls/library/ssl_srv.c89
-rw-r--r--thirdparty/mbedtls/library/ssl_ticket.c16
-rw-r--r--thirdparty/mbedtls/library/ssl_tls.c2077
-rw-r--r--thirdparty/mbedtls/library/threading.c47
-rw-r--r--thirdparty/mbedtls/library/timing.c12
-rw-r--r--thirdparty/mbedtls/library/version_features.c6
-rw-r--r--thirdparty/mbedtls/library/x509.c11
-rw-r--r--thirdparty/mbedtls/library/x509_create.c171
-rw-r--r--thirdparty/mbedtls/library/x509_crt.c706
-rw-r--r--thirdparty/mbedtls/padlock.diff13
-rw-r--r--thirdparty/misc/base64.h4
-rw-r--r--thirdparty/misc/clipper-exceptions.patch154
-rw-r--r--thirdparty/misc/clipper.cpp68
-rw-r--r--thirdparty/misc/pcg.cpp10
-rw-r--r--thirdparty/misc/pcg.h1
-rw-r--r--thirdparty/misc/stb_truetype.h87
-rw-r--r--thirdparty/misc/stb_vorbis.c31
-rw-r--r--thirdparty/misc/yuv2rgb.h121
-rw-r--r--thirdparty/nanosvg/nanosvg.h80
-rw-r--r--thirdparty/nanosvg/nanosvgrast.h7
-rw-r--r--thirdparty/opus/http.c3465
-rw-r--r--thirdparty/opus/wincerts.c171
-rw-r--r--thirdparty/opus/winerrno.h90
-rw-r--r--thirdparty/pcre2/LICENCE14
-rw-r--r--thirdparty/pcre2/src/config.h32
-rw-r--r--thirdparty/pcre2/src/pcre2.h30
-rw-r--r--thirdparty/pcre2/src/pcre2_auto_possess.c7
-rw-r--r--thirdparty/pcre2/src/pcre2_chartables.c50
-rw-r--r--thirdparty/pcre2/src/pcre2_compile.c336
-rw-r--r--thirdparty/pcre2/src/pcre2_convert.c12
-rw-r--r--thirdparty/pcre2/src/pcre2_dfa_match.c271
-rw-r--r--thirdparty/pcre2/src/pcre2_error.c15
-rw-r--r--thirdparty/pcre2/src/pcre2_extuni.c8
-rw-r--r--thirdparty/pcre2/src/pcre2_find_bracket.c3
-rw-r--r--thirdparty/pcre2/src/pcre2_internal.h131
-rw-r--r--thirdparty/pcre2/src/pcre2_intmodedep.h17
-rw-r--r--thirdparty/pcre2/src/pcre2_jit_compile.c37
-rw-r--r--thirdparty/pcre2/src/pcre2_maketables.c9
-rw-r--r--thirdparty/pcre2/src/pcre2_match.c54
-rw-r--r--thirdparty/pcre2/src/pcre2_pattern_info.c3
-rw-r--r--thirdparty/pcre2/src/pcre2_serialize.c22
-rw-r--r--thirdparty/pcre2/src/pcre2_string_utils.c38
-rw-r--r--thirdparty/pcre2/src/pcre2_study.c6
-rw-r--r--thirdparty/pcre2/src/pcre2_substitute.c47
-rw-r--r--thirdparty/pcre2/src/pcre2_tables.c378
-rw-r--r--thirdparty/pcre2/src/pcre2_ucd.c6727
-rw-r--r--thirdparty/pcre2/src/pcre2_ucp.h48
-rw-r--r--thirdparty/pcre2/src/sljit/sljitConfigInternal.h29
-rw-r--r--thirdparty/pcre2/src/sljit/sljitExecAllocator.c9
-rw-r--r--thirdparty/pcre2/src/sljit/sljitLir.c10
-rw-r--r--thirdparty/pcre2/src/sljit/sljitLir.h20
-rw-r--r--thirdparty/pcre2/src/sljit/sljitNativeARM_64.c250
-rw-r--r--thirdparty/pcre2/src/sljit/sljitNativeARM_T2_32.c112
-rw-r--r--thirdparty/pcre2/src/sljit/sljitNativeMIPS_32.c4
-rw-r--r--thirdparty/pcre2/src/sljit/sljitNativeMIPS_64.c4
-rw-r--r--thirdparty/pcre2/src/sljit/sljitNativeMIPS_common.c48
-rw-r--r--thirdparty/pcre2/src/sljit/sljitNativeX86_32.c79
-rw-r--r--thirdparty/pcre2/src/sljit/sljitNativeX86_64.c120
-rw-r--r--thirdparty/pcre2/src/sljit/sljitNativeX86_common.c17
-rw-r--r--thirdparty/rtaudio/RtAudio.cpp10232
-rw-r--r--thirdparty/rtaudio/RtAudio.h1183
-rw-r--r--thirdparty/thekla_atlas/godot-changes.patch154
-rw-r--r--thirdparty/thekla_atlas/nvconfig.h37
-rw-r--r--thirdparty/thekla_atlas/nvcore/Array.h182
-rw-r--r--thirdparty/thekla_atlas/nvcore/Array.inl452
-rw-r--r--thirdparty/thekla_atlas/nvcore/BitArray.h250
-rw-r--r--thirdparty/thekla_atlas/nvcore/Debug.cpp1357
-rw-r--r--thirdparty/thekla_atlas/nvcore/Debug.h246
-rw-r--r--thirdparty/thekla_atlas/nvcore/DefsGnucDarwin.h57
-rw-r--r--thirdparty/thekla_atlas/nvcore/DefsGnucLinux.h59
-rw-r--r--thirdparty/thekla_atlas/nvcore/DefsGnucWin32.h67
-rw-r--r--thirdparty/thekla_atlas/nvcore/DefsVcWin32.h94
-rw-r--r--thirdparty/thekla_atlas/nvcore/FileSystem.cpp75
-rw-r--r--thirdparty/thekla_atlas/nvcore/FileSystem.h24
-rw-r--r--thirdparty/thekla_atlas/nvcore/ForEach.h71
-rw-r--r--thirdparty/thekla_atlas/nvcore/Hash.h83
-rw-r--r--thirdparty/thekla_atlas/nvcore/HashMap.h174
-rw-r--r--thirdparty/thekla_atlas/nvcore/HashMap.inl550
-rw-r--r--thirdparty/thekla_atlas/nvcore/Memory.cpp153
-rw-r--r--thirdparty/thekla_atlas/nvcore/Memory.h72
-rw-r--r--thirdparty/thekla_atlas/nvcore/Ptr.h322
-rw-r--r--thirdparty/thekla_atlas/nvcore/RadixSort.cpp285
-rw-r--r--thirdparty/thekla_atlas/nvcore/RadixSort.h75
-rw-r--r--thirdparty/thekla_atlas/nvcore/RefCounted.h149
-rw-r--r--thirdparty/thekla_atlas/nvcore/StdStream.h474
-rw-r--r--thirdparty/thekla_atlas/nvcore/StrLib.cpp796
-rw-r--r--thirdparty/thekla_atlas/nvcore/StrLib.h433
-rw-r--r--thirdparty/thekla_atlas/nvcore/Stream.h164
-rw-r--r--thirdparty/thekla_atlas/nvcore/Utils.h315
-rw-r--r--thirdparty/thekla_atlas/nvcore/nvcore.h360
-rw-r--r--thirdparty/thekla_atlas/nvcore/scanf.c641
-rw-r--r--thirdparty/thekla_atlas/nvimage/BitMap.cpp27
-rw-r--r--thirdparty/thekla_atlas/nvimage/BitMap.h87
-rw-r--r--thirdparty/thekla_atlas/nvimage/Image.cpp210
-rw-r--r--thirdparty/thekla_atlas/nvimage/Image.h89
-rw-r--r--thirdparty/thekla_atlas/nvimage/nvimage.h48
-rw-r--r--thirdparty/thekla_atlas/nvmath/Basis.cpp270
-rw-r--r--thirdparty/thekla_atlas/nvmath/Basis.h82
-rw-r--r--thirdparty/thekla_atlas/nvmath/Box.cpp119
-rw-r--r--thirdparty/thekla_atlas/nvmath/Box.h103
-rw-r--r--thirdparty/thekla_atlas/nvmath/Box.inl154
-rw-r--r--thirdparty/thekla_atlas/nvmath/Color.h150
-rw-r--r--thirdparty/thekla_atlas/nvmath/ConvexHull.cpp120
-rw-r--r--thirdparty/thekla_atlas/nvmath/ConvexHull.h17
-rw-r--r--thirdparty/thekla_atlas/nvmath/Fitting.cpp1205
-rw-r--r--thirdparty/thekla_atlas/nvmath/Fitting.h50
-rw-r--r--thirdparty/thekla_atlas/nvmath/KahanSum.h39
-rw-r--r--thirdparty/thekla_atlas/nvmath/Matrix.cpp441
-rw-r--r--thirdparty/thekla_atlas/nvmath/Matrix.h113
-rw-r--r--thirdparty/thekla_atlas/nvmath/Matrix.inl1274
-rw-r--r--thirdparty/thekla_atlas/nvmath/Morton.h83
-rw-r--r--thirdparty/thekla_atlas/nvmath/Plane.cpp27
-rw-r--r--thirdparty/thekla_atlas/nvmath/Plane.h42
-rw-r--r--thirdparty/thekla_atlas/nvmath/Plane.inl50
-rw-r--r--thirdparty/thekla_atlas/nvmath/ProximityGrid.cpp158
-rw-r--r--thirdparty/thekla_atlas/nvmath/ProximityGrid.h99
-rw-r--r--thirdparty/thekla_atlas/nvmath/Quaternion.h213
-rw-r--r--thirdparty/thekla_atlas/nvmath/Random.cpp54
-rw-r--r--thirdparty/thekla_atlas/nvmath/Random.h376
-rw-r--r--thirdparty/thekla_atlas/nvmath/Solver.cpp744
-rw-r--r--thirdparty/thekla_atlas/nvmath/Solver.h24
-rw-r--r--thirdparty/thekla_atlas/nvmath/Sparse.cpp889
-rw-r--r--thirdparty/thekla_atlas/nvmath/Sparse.h204
-rw-r--r--thirdparty/thekla_atlas/nvmath/Sphere.cpp431
-rw-r--r--thirdparty/thekla_atlas/nvmath/Sphere.h43
-rw-r--r--thirdparty/thekla_atlas/nvmath/TypeSerialization.cpp54
-rw-r--r--thirdparty/thekla_atlas/nvmath/TypeSerialization.h35
-rw-r--r--thirdparty/thekla_atlas/nvmath/Vector.cpp4
-rw-r--r--thirdparty/thekla_atlas/nvmath/Vector.h149
-rw-r--r--thirdparty/thekla_atlas/nvmath/Vector.inl919
-rw-r--r--thirdparty/thekla_atlas/nvmath/ftoi.h261
-rw-r--r--thirdparty/thekla_atlas/nvmath/nvmath.h342
-rw-r--r--thirdparty/thekla_atlas/nvmesh/BaseMesh.cpp19
-rw-r--r--thirdparty/thekla_atlas/nvmesh/BaseMesh.h72
-rw-r--r--thirdparty/thekla_atlas/nvmesh/MeshBuilder.cpp1000
-rw-r--r--thirdparty/thekla_atlas/nvmesh/MeshBuilder.h119
-rw-r--r--thirdparty/thekla_atlas/nvmesh/MeshTopology.cpp122
-rw-r--r--thirdparty/thekla_atlas/nvmesh/MeshTopology.h66
-rw-r--r--thirdparty/thekla_atlas/nvmesh/QuadTriMesh.cpp36
-rw-r--r--thirdparty/thekla_atlas/nvmesh/QuadTriMesh.h60
-rw-r--r--thirdparty/thekla_atlas/nvmesh/TriMesh.cpp25
-rw-r--r--thirdparty/thekla_atlas/nvmesh/TriMesh.h51
-rw-r--r--thirdparty/thekla_atlas/nvmesh/geometry/Bounds.cpp54
-rw-r--r--thirdparty/thekla_atlas/nvmesh/geometry/Bounds.h28
-rw-r--r--thirdparty/thekla_atlas/nvmesh/geometry/Measurements.cpp36
-rw-r--r--thirdparty/thekla_atlas/nvmesh/geometry/Measurements.h18
-rw-r--r--thirdparty/thekla_atlas/nvmesh/halfedge/Edge.cpp57
-rw-r--r--thirdparty/thekla_atlas/nvmesh/halfedge/Edge.h70
-rw-r--r--thirdparty/thekla_atlas/nvmesh/halfedge/Face.cpp268
-rw-r--r--thirdparty/thekla_atlas/nvmesh/halfedge/Face.h106
-rw-r--r--thirdparty/thekla_atlas/nvmesh/halfedge/Mesh.cpp1284
-rw-r--r--thirdparty/thekla_atlas/nvmesh/halfedge/Mesh.h274
-rw-r--r--thirdparty/thekla_atlas/nvmesh/halfedge/Vertex.cpp94
-rw-r--r--thirdparty/thekla_atlas/nvmesh/halfedge/Vertex.h221
-rw-r--r--thirdparty/thekla_atlas/nvmesh/nvmesh.cpp2
-rw-r--r--thirdparty/thekla_atlas/nvmesh/nvmesh.h34
-rw-r--r--thirdparty/thekla_atlas/nvmesh/param/Atlas.cpp1519
-rw-r--r--thirdparty/thekla_atlas/nvmesh/param/Atlas.h186
-rw-r--r--thirdparty/thekla_atlas/nvmesh/param/AtlasBuilder.cpp1320
-rw-r--r--thirdparty/thekla_atlas/nvmesh/param/AtlasBuilder.h111
-rw-r--r--thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.cpp1401
-rw-r--r--thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.h65
-rw-r--r--thirdparty/thekla_atlas/nvmesh/param/LeastSquaresConformalMap.cpp483
-rw-r--r--thirdparty/thekla_atlas/nvmesh/param/LeastSquaresConformalMap.h15
-rw-r--r--thirdparty/thekla_atlas/nvmesh/param/OrthogonalProjectionMap.cpp99
-rw-r--r--thirdparty/thekla_atlas/nvmesh/param/OrthogonalProjectionMap.h15
-rw-r--r--thirdparty/thekla_atlas/nvmesh/param/ParameterizationQuality.cpp323
-rw-r--r--thirdparty/thekla_atlas/nvmesh/param/ParameterizationQuality.h56
-rw-r--r--thirdparty/thekla_atlas/nvmesh/param/SingleFaceMap.cpp53
-rw-r--r--thirdparty/thekla_atlas/nvmesh/param/SingleFaceMap.h18
-rw-r--r--thirdparty/thekla_atlas/nvmesh/param/Util.cpp326
-rw-r--r--thirdparty/thekla_atlas/nvmesh/param/Util.h18
-rw-r--r--thirdparty/thekla_atlas/nvmesh/raster/ClippedTriangle.h159
-rw-r--r--thirdparty/thekla_atlas/nvmesh/raster/Raster.cpp626
-rw-r--r--thirdparty/thekla_atlas/nvmesh/raster/Raster.h49
-rw-r--r--thirdparty/thekla_atlas/nvmesh/weld/Snap.cpp100
-rw-r--r--thirdparty/thekla_atlas/nvmesh/weld/Snap.h18
-rw-r--r--thirdparty/thekla_atlas/nvmesh/weld/VertexWeld.cpp205
-rw-r--r--thirdparty/thekla_atlas/nvmesh/weld/VertexWeld.h19
-rw-r--r--thirdparty/thekla_atlas/nvmesh/weld/Weld.h171
-rw-r--r--thirdparty/thekla_atlas/poshlib/posh.c1006
-rw-r--r--thirdparty/thekla_atlas/poshlib/posh.h1040
-rw-r--r--thirdparty/thekla_atlas/thekla/thekla_atlas.cpp288
-rw-r--r--thirdparty/thekla_atlas/thekla/thekla_atlas.h116
-rw-r--r--thirdparty/tinyexr/tinyexr.h222
-rw-r--r--thirdparty/vhacd/0001-bullet-namespace.patch213
-rw-r--r--thirdparty/vhacd/0002-fpermissive-fix.patch53
-rw-r--r--thirdparty/vhacd/LICENSE29
-rw-r--r--thirdparty/vhacd/inc/FloatMath.h525
-rw-r--r--thirdparty/vhacd/inc/btAlignedAllocator.h113
-rw-r--r--thirdparty/vhacd/inc/btAlignedObjectArray.h456
-rw-r--r--thirdparty/vhacd/inc/btConvexHullComputer.h105
-rw-r--r--thirdparty/vhacd/inc/btMinMax.h73
-rw-r--r--thirdparty/vhacd/inc/btScalar.h573
-rw-r--r--thirdparty/vhacd/inc/btVector3.h723
-rw-r--r--thirdparty/vhacd/inc/vhacdCircularList.h79
-rw-r--r--thirdparty/vhacd/inc/vhacdCircularList.inl161
-rw-r--r--thirdparty/vhacd/inc/vhacdICHull.h98
-rw-r--r--thirdparty/vhacd/inc/vhacdManifoldMesh.h142
-rw-r--r--thirdparty/vhacd/inc/vhacdMesh.h130
-rw-r--r--thirdparty/vhacd/inc/vhacdMutex.h148
-rw-r--r--thirdparty/vhacd/inc/vhacdRaycastMesh.h39
-rw-r--r--thirdparty/vhacd/inc/vhacdSArray.h158
-rw-r--r--thirdparty/vhacd/inc/vhacdTimer.h121
-rw-r--r--thirdparty/vhacd/inc/vhacdVHACD.h371
-rw-r--r--thirdparty/vhacd/inc/vhacdVector.h168
-rw-r--r--thirdparty/vhacd/inc/vhacdVector.inl362
-rw-r--r--thirdparty/vhacd/inc/vhacdVolume.h430
-rw-r--r--thirdparty/vhacd/public/VHACD.h153
-rw-r--r--thirdparty/vhacd/src/FloatMath.cpp17
-rw-r--r--thirdparty/vhacd/src/FloatMath.inl5276
-rw-r--r--thirdparty/vhacd/src/VHACD-ASYNC.cpp334
-rw-r--r--thirdparty/vhacd/src/VHACD.cpp1589
-rw-r--r--thirdparty/vhacd/src/btAlignedAllocator.cpp192
-rw-r--r--thirdparty/vhacd/src/btConvexHullComputer.cpp2487
-rw-r--r--thirdparty/vhacd/src/vhacdICHull.cpp731
-rw-r--r--thirdparty/vhacd/src/vhacdManifoldMesh.cpp202
-rw-r--r--thirdparty/vhacd/src/vhacdMesh.cpp376
-rw-r--r--thirdparty/vhacd/src/vhacdRaycastMesh.cpp208
-rw-r--r--thirdparty/vhacd/src/vhacdVolume.cpp1626
-rw-r--r--thirdparty/xatlas/LICENSE (renamed from thirdparty/thekla_atlas/LICENSE)8
-rw-r--r--thirdparty/xatlas/avoid-failing-on-bad-geometry.patch157
-rw-r--r--thirdparty/xatlas/build-fix-limits.patch14
-rw-r--r--thirdparty/xatlas/xatlas.cpp2407
-rw-r--r--thirdparty/xatlas/xatlas.h61
-rw-r--r--thirdparty/zstd/1314.diff13
-rw-r--r--thirdparty/zstd/common/bitstream.h48
-rw-r--r--thirdparty/zstd/common/compiler.h51
-rw-r--r--thirdparty/zstd/common/cpu.h5
-rw-r--r--thirdparty/zstd/common/debug.c44
-rw-r--r--thirdparty/zstd/common/debug.h134
-rw-r--r--thirdparty/zstd/common/entropy_common.c17
-rw-r--r--thirdparty/zstd/common/error_private.c6
-rw-r--r--thirdparty/zstd/common/fse.h92
-rw-r--r--thirdparty/zstd/common/fse_decompress.c2
-rw-r--r--thirdparty/zstd/common/huf.h85
-rw-r--r--thirdparty/zstd/common/mem.h22
-rw-r--r--thirdparty/zstd/common/pool.c123
-rw-r--r--thirdparty/zstd/common/pool.h48
-rw-r--r--thirdparty/zstd/common/threading.c4
-rw-r--r--thirdparty/zstd/common/xxhash.c5
-rw-r--r--thirdparty/zstd/common/zstd_common.c9
-rw-r--r--thirdparty/zstd/common/zstd_errors.h1
-rw-r--r--thirdparty/zstd/common/zstd_internal.h115
-rw-r--r--thirdparty/zstd/compress/fse_compress.c298
-rw-r--r--thirdparty/zstd/compress/hist.c203
-rw-r--r--thirdparty/zstd/compress/hist.h95
-rw-r--r--thirdparty/zstd/compress/huf_compress.c84
-rw-r--r--thirdparty/zstd/compress/zstd_compress.c2706
-rw-r--r--thirdparty/zstd/compress/zstd_compress_internal.h264
-rw-r--r--thirdparty/zstd/compress/zstd_double_fast.c362
-rw-r--r--thirdparty/zstd/compress/zstd_double_fast.h10
-rw-r--r--thirdparty/zstd/compress/zstd_fast.c377
-rw-r--r--thirdparty/zstd/compress/zstd_fast.h10
-rw-r--r--thirdparty/zstd/compress/zstd_lazy.c554
-rw-r--r--thirdparty/zstd/compress/zstd_lazy.h35
-rw-r--r--thirdparty/zstd/compress/zstd_ldm.c130
-rw-r--r--thirdparty/zstd/compress/zstd_ldm.h12
-rw-r--r--thirdparty/zstd/compress/zstd_opt.c926
-rw-r--r--thirdparty/zstd/compress/zstd_opt.h28
-rw-r--r--thirdparty/zstd/compress/zstdmt_compress.c618
-rw-r--r--thirdparty/zstd/compress/zstdmt_compress.h119
-rw-r--r--thirdparty/zstd/decompress/huf_decompress.c868
-rw-r--r--thirdparty/zstd/decompress/zstd_ddict.c240
-rw-r--r--thirdparty/zstd/decompress/zstd_ddict.h44
-rw-r--r--thirdparty/zstd/decompress/zstd_decompress.c2304
-rw-r--r--thirdparty/zstd/decompress/zstd_decompress_block.c1311
-rw-r--r--thirdparty/zstd/decompress/zstd_decompress_block.h59
-rw-r--r--thirdparty/zstd/decompress/zstd_decompress_internal.h175
-rw-r--r--thirdparty/zstd/zstd.h1958
1792 files changed, 272871 insertions, 211852 deletions
diff --git a/thirdparty/README.md b/thirdparty/README.md
index 5e42436f32..732c08fdea 100644
--- a/thirdparty/README.md
+++ b/thirdparty/README.md
@@ -1,6 +1,13 @@
# Third party libraries
+## assimp
+
+- Upstream: http://github.com/assimp/assimp
+- Version: git (d3d98a7ec0c8d38e1952b46dfe53f7e9233dc92d)
+- License: BSD-3-Clause
+
+
## b2d_convexdecomp
- Upstream: https://github.com/erincatto/Box2D/tree/master/Contributions/Utilities/ConvexDecomposition
@@ -19,7 +26,7 @@ comments.
## bullet
- Upstream: https://github.com/bulletphysics/bullet3
-- Version: git (12409f1118a7c7a266f9071350c70789dfe73bb9, Commits on Sep 6, 2018 )
+- Version: 2.88
- License: zlib
Files extracted from upstream source:
@@ -115,7 +122,7 @@ Use UI font variant if available, because it has tight vertical metrics and good
## freetype
- Upstream: https://www.freetype.org
-- Version: 2.9.1
+- Version: 2.10.0
- License: FreeType License (BSD-like)
Files extracted from upstream source:
@@ -128,7 +135,7 @@ Files extracted from upstream source:
## glad
- Upstream: https://github.com/Dav1dde/glad
-- Version: 0.1.28
+- Version: 0.1.29
- License: MIT
The files we package are automatically generated.
@@ -163,7 +170,7 @@ Files extracted from upstream source:
## libpng
- Upstream: http://libpng.org/pub/png/libpng.html
-- Version: 1.6.35
+- Version: 1.6.37
- License: libpng/zlib
Files extracted from upstream source:
@@ -178,18 +185,21 @@ Files extracted from upstream source:
## libsimplewebm
- Upstream: https://github.com/zaps166/libsimplewebm
-- Version: git (05cfdc2, 2016)
-- License: MIT, BSD-3-Clause
+- Version: git (fe57fd3, 2019)
+- License: MIT (main), BSD-3-Clause (libwebm)
+
+This contains libwebm, but the version in use is updated from the one used by libsimplewebm,
+and may have *unmarked* alterations from that.
Files extracted from upstream source:
-TODO.
+- all the .cpp, .hpp files in the main folder except `example.cpp`
+- LICENSE
Important: Some files have Godot-made changes.
They are marked with `// -- GODOT start --` and `// -- GODOT end --`
comments.
-
## libtheora
- Upstream: https://www.theora.org
@@ -202,6 +212,9 @@ Files extracted from upstream source:
- all .h files in include/theora/ as theora/
- COPYING and LICENSE
+Upstream patches included in the `patches` directory have been applied
+on top of the 1.1.1 source (not included in any stable release yet).
+
## libvorbis
@@ -236,7 +249,7 @@ from the Android NDK r18.
## libwebp
- Upstream: https://chromium.googlesource.com/webm/libwebp/
-- Version: 1.0.1
+- Version: 1.0.2
- License: BSD-3-Clause
Files extracted from upstream source:
@@ -252,7 +265,7 @@ changes are marked with `// -- GODOT --` comments.
## libwebsockets
- Upstream: https://github.com/warmcat/libwebsockets
-- Version: 3.0.0
+- Version: 3.0.1
- License: LGPLv2.1 + static linking exception
File extracted from upstream source:
@@ -269,6 +282,8 @@ File extracted from upstream source:
- Also copy `win32helpers/` from `win32port/` inside `thirdparty/libwebsockets`
- A fix has been added to allow building for 32-bits UWP, replacing `GetFileSize[Ex]` and `CreateFileW` with supported functions.
There is a diff for this change in `thirdparty/libwebsockets/uwp_fixes.diff`
+- A fix to disable V6ONLY flag from IPv6 sockets (on by default on some systems) has been also applied.
+ The diff for this change can be found in `thirdparty/libwebsockets/ipv6_fixes.diff`
Important: `lws_config.h` and `lws_config_private.h` contains custom
Godot build configurations, check them out when updating.
@@ -277,22 +292,27 @@ Godot build configurations, check them out when updating.
## mbedtls
- Upstream: https://tls.mbed.org/
-- Version: 2.12.0
+- Version: 2.16.0
- License: Apache 2.0
-File extracted from upstream release tarball `mbedtls-2.12.0-apache.tgz`:
+File extracted from upstream release tarball `mbedtls-2.16.0-apache.tgz`:
- All `*.h` from `include/mbedtls/` to `thirdparty/mbedtls/include/mbedtls/`
- All `*.c` from `library/` to `thirdparty/mbedtls/library/`
-- Applied the patch in `thirdparty/mbedtls/1453.diff` (PR 1453). Soon to be merged upstream. Check it out at next update.
+- Applied the patch in `thirdparty/mbedtls/1453.diff` (PR 1453).
+ Soon to be merged upstream. Check it out at next update.
+- Applied the patch in `thirdparty/mbedtls/padlock.diff`. This disables VIA
+ padlock support which defines a symbol `unsupported` which clashes with
+ a symbol in libwebsockets.
## miniupnpc
- Upstream: https://github.com/miniupnp/miniupnp/tree/master/miniupnpc
-- Version: 2.1 (git 25615e0, 2018-05-08) with modifications
+- Version: git (25615e0, 2018)
- License: BSD-3-Clause
-The only modified file is miniupnpcstrings.h, which was created for Godot (is usually autogenerated by cmake).
+The only modified file is miniupnpcstrings.h, which was created for Godot
+(it is usually autogenerated by cmake).
## minizip
@@ -326,7 +346,7 @@ Collection of single-file libraries used in Godot components.
* License: Public Domain
- `clipper.{cpp,hpp}`
* Upstream: https://sourceforge.net/projects/polyclipping
- * Version: 6.4.2
+ * Version: 6.4.2 + Godot changes (added optional exceptions handling)
* License: BSL-1.0
- `fastlz.{c,h}`
* Upstream: https://github.com/ariya/FastLZ
@@ -377,7 +397,7 @@ Collection of single-file libraries used in Godot components.
- `ifaddrs-android.{cc,h}`
* Upstream: https://chromium.googlesource.com/external/webrtc/stable/talk/+/master/base/ifaddrs-android.h
- * Version: 5976650 (2013)
+ * Version: git (5976650, 2013)
* License: BSD-3-Clause
### scene
@@ -392,18 +412,18 @@ Collection of single-file libraries used in Godot components.
* License: zlib
- `stb_truetype.h`
* Upstream: https://github.com/nothings/stb
- * Version: 1.19
+ * Version: 1.21
* License: Public Domain (Unlicense) or MIT
- `stb_vorbis.c`
* Upstream: https://github.com/nothings/stb
- * Version: 1.14
+ * Version: 1.15
* License: Public Domain (Unlicense) or MIT
## nanosvg
- Upstream: https://github.com/memononen/nanosvg
-- Version: 9a74da4 (git)
+- Version: git (c1f6e20, 2018)
- License: zlib
Files extracted from the upstream source:
@@ -420,9 +440,11 @@ Files extracted from the upstream source:
Files extracted from upstream source:
-- all .c and .h files in src/ (both opus and opusfile),
- except `opus_demo.c`
+- all .c and .h files in src/ (both opus and opusfile)
- all .h files in include/ (both opus and opusfile) as opus/
+- remove unused `opus_demo.c`,
+- remove `http.c`, `wincerts.c` and `winerrno.h` (part of
+ unused libopusurl)
- celt/ and silk/ subfolders
- COPYING
@@ -430,16 +452,16 @@ Files extracted from upstream source:
## pcre2
- Upstream: http://www.pcre.org/
-- Version: 10.31
+- Version: 10.32
- License: BSD-3-Clause
Files extracted from upstream source:
- Files listed in the file NON-AUTOTOOLS-BUILD steps 1-4
-- All .h files in src/
+- All .h files in src/ apart from pcre2posix.h
+- src/pcre2_jit_compile.c
- src/pcre2_jit_match.c
- src/pcre2_jit_misc.c
-- src/pcre2_jit_maketables.c
- src/sljit/*
- AUTHORS and LICENCE
@@ -468,17 +490,6 @@ Files extracted from upstream source:
- License.txt
-## rtaudio
-
-- Upstream: http://www.music.mcgill.ca/~gary/rtaudio/
-- Version: 4.1.2
-- License: MIT-like
-
-Files extracted from upstream source:
-
-- `RtAudio.{cpp,h}`
-
-
## squish
- Upstream: https://sourceforge.net/projects/libsquish
@@ -494,30 +505,46 @@ They are marked with `// -- GODOT start --` and `// -- GODOT end --`
comments and a patch is provided in the squish/ folder.
-## thekla_atlas
-
-- Upstream: https://github.com/Thekla/thekla_atlas
-- Version: git (80a1430, 2017)
-- License: MIT
+## tinyexr
-Files extracted from the upstream source:
+- Upstream: https://github.com/syoyo/tinyexr
+- Version: git (65f9859, 2018)
+- License: BSD-3-Clause
-- Relevant sources from src/
-- License.txt
+Files extracted from upstream source:
-Important: Some files have Godot-made changes, those
-changes are marked with `// -- GODOT --` comments.
+- `tinyexr.{cc,h}`
-## tinyexr
+## vhacd
-- Upstream: https://github.com/syoyo/tinyexr
-- Version: git (5ae30aa, 2018)
+- Upstream: https://github.com/kmammou/v-hacd
+- Version: git (2297aa1, 2018)
- License: BSD-3-Clause
Files extracted from upstream source:
-- `tinyexr.{cc,h}`
+- From `src/VHACD_Lib/`: `inc`, `public` and `src`
+- `LICENSE`
+
+Some downstream changes have been made and are identified by
+`// -- GODOT start --` and `// -- GODOT end --` comments.
+They can be reapplied using the patches included in the `vhacd`
+folder.
+
+
+## xatlas
+
+- Upstream: https://github.com/jpcy/xatlas
+- Version: git (b8ec29b, 2018)
+- License: MIT
+
+Files extracted from upstream source:
+
+- `xatlas.{cpp,h}`
+
+Note: License is marked as Public Domain in the files, but it was
+later clarified upstream to MIT license.
## zlib
@@ -534,12 +561,10 @@ Files extracted from upstream source:
## zstd
- Upstream: https://github.com/facebook/zstd
-- Version: 1.3.4
+- Version: 1.4.0
- License: BSD-3-Clause
Files extracted from upstream source:
- lib/{common/,compress/,decompress/,zstd.h}
- LICENSE
-
-- Applied the patch in `thirdparty/zstd/1314.diff` (PR 1314 upstream, already merged). Needed to build on UWP ARM. Can be removed when a new version is released with the patch.
diff --git a/thirdparty/assimp/CREDITS b/thirdparty/assimp/CREDITS
new file mode 100644
index 0000000000..26e21d2f41
--- /dev/null
+++ b/thirdparty/assimp/CREDITS
@@ -0,0 +1,183 @@
+===============================================================
+Open Asset Import Library (Assimp)
+Developers and Contributors
+===============================================================
+
+The following is a non-exhaustive list of all constributors over the years.
+If you think your name should be listed here, drop us a line and we'll add you.
+
+- Alexander Gessler,
+3DS-, BLEND-, ASE-, DXF-, HMP-, MDL-, MD2-, MD3-, MD5-, MDC-, NFF-, PLY-, STL-, RAW-, OFF-, MS3D-, Q3D- and LWO-Loader, Assimp-Viewer, assimp-cmd, -noboost, Website (Design).
+
+- Thomas Schulze,
+X-, Collada-, BVH-Loader, Postprocessing framework. Data structure & Interface design, documentation.
+
+- Kim Kulling,
+Obj-, Q3BSD-, OpenGEX-Loader, Logging system, CMake-build-environment, Linux-build, Website ( Admin ), Coverity ( Admin ), Glitter ( Admin ).
+
+- R.Schmidt,
+Linux build, eclipse support.
+
+- Matthias Gubisch,
+Assimp.net
+Visual Studio 9 support, bugfixes.
+
+- Mark Sibly
+B3D-Loader, Assimp testing
+
+- Jonathan Klein
+Ogre Loader, VC2010 fixes and CMake fixes.
+
+- Sebastian Hempel,
+PyAssimp (first version)
+Compile-Bugfixes for mingw, add environment for static library support in make.
+
+- Jonathan Pokrass
+Supplied a bugfix concerning the scaling in the md3 loader.
+
+- Andrew Galante,
+Submitted patches to make Assimp compile with GCC-4, a makefile and the xcode3 workspace.
+
+- Andreas Nagel
+First Assimp testing & verification under Windows Vista 64 Bit.
+
+- Marius Schr�der
+Allowed us to use many of his models for screenshots and testing.
+
+- Christian Schubert
+Supplied various XFiles for testing purposes.
+
+- Tizian Wieland
+Searched the web for hundreds of test models for internal use
+
+- John Connors
+Supplied patches for linux and SCons.
+
+- T. R.
+The GUY who performed some of the CSM mocaps.
+
+- Andy Maloney
+Contributed fixes for the documentation and the doxygen markup
+
+- Zhao Lei
+Contributed several bugfixes fixing memory leaks and improving float parsing
+
+- sueastside
+Updated PyAssimp to the latest Assimp data structures and provided a script to keep the Python binding up-to-date.
+
+- Tobias Rittig
+Collada testing with Cinema 4D
+
+- Brad Grantham
+Improvements in OpenGL-Sample.
+
+- Robert Ramirez
+Add group loading feature to Obj-Loader.
+
+- Chris Maiwald
+Many bugreports, improving Assimp's portability, regular testing & feedback.
+
+- Stepan Hrbek
+Bugreport and fix for a obj-materialloader crash.
+
+- David Nadlinger
+D bindings, CMake install support.
+
+- Dario Accornero
+Contributed several patches regarding Mac OS/XCode targets, bug reports.
+
+- Martin Walser (Samhayne)
+Contributed the 'SimpleTexturedOpenGl' sample.
+
+- Matthias Fauconneau
+Contributed a fix for the Q3-BSP loader.
+
+- Jørgen P. Tjernø
+Contributed updated and improved xcode workspaces
+
+- drparallax
+Contributed the /samples/SimpleAssimpViewX sample
+
+- Carsten Fuchs
+Contributed a fix for the Normalize method in aiQuaternion.
+
+- dbburgess
+Contributes a Android-specific build issue: log the hardware architecture for ARM.
+
+- alfiereinre7
+Contributes a obj-fileparser fix: missing tokens in the obj-token list.
+
+- Roman Kharitonov
+Contributes a fix for the configure script environment.
+
+- Ed Diana
+Contributed AssimpDelphi (/port/AssimpDelphi).
+
+- rdb
+Contributes a bundle of fixes and improvements for the bsp-importer.
+
+- Mick P
+For contributing the De-bone postprocessing step and filing various bug reports.
+
+- Rosen Diankov
+Contributed patches to build assimp debian packages using cmake.
+
+- Mark Page
+Contributed a patch to fix the VertexTriangleAdjacency postprocessing step.
+
+- IOhannes
+Contributed the Debian build fixes ( architecture macro ).
+
+- gellule
+Several LWO and LWS fixes (pivoting).
+
+- Marcel Metz
+GCC/Linux fixes for the SimpleOpenGL sample.
+
+- Brian Miller
+Bugfix for a compiler fix for iOS on arm.
+
+- Séverin Lemaignan
+Rewrite of PyAssimp, distutils and Python3 support
+
+- albert-wang
+Bugfixes for the collada parser
+
+- Ya ping Jin
+Bugfixes for uv-tanget calculation.
+
+- Jonne Nauha
+Ogre Binary format support
+
+- Filip Wasil, Tieto Poland Sp. z o.o.
+Android JNI asset extraction support
+
+- Richard Steffen
+Contributed ExportProperties interface
+Contributed X File exporter
+Contributed Step (stp) exporter
+
+- Thomas Iorns (mesilliac)
+Initial FBX Export support
+
+For a more detailed list just check: https://github.com/assimp/assimp/network/members
+
+
+========
+Patreons
+========
+
+Huge thanks to our Patreons!
+
+- migenius
+- Marcus
+- Cort
+- elect
+- Steffen
+
+
+===================
+Commercial Sponsors
+===================
+
+- MyDidimo (mydidimo.com): Sponsored development of FBX Export support
diff --git a/thirdparty/assimp/LICENSE b/thirdparty/assimp/LICENSE
new file mode 100644
index 0000000000..262606aff3
--- /dev/null
+++ b/thirdparty/assimp/LICENSE
@@ -0,0 +1,78 @@
+Open Asset Import Library (assimp)
+
+Copyright (c) 2006-2016, assimp team
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+
+******************************************************************************
+
+AN EXCEPTION applies to all files in the ./test/models-nonbsd folder.
+These are 3d models for testing purposes, from various free sources
+on the internet. They are - unless otherwise stated - copyright of
+their respective creators, which may impose additional requirements
+on the use of their work. For any of these models, see
+<model-name>.source.txt for more legal information. Contact us if you
+are a copyright holder and believe that we credited you inproperly or
+if you don't want your files to appear in the repository.
+
+
+******************************************************************************
+
+Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
+http://code.google.com/p/poly2tri/
+
+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 name of Poly2Tri 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.
diff --git a/thirdparty/assimp/assimp/config.h b/thirdparty/assimp/assimp/config.h
new file mode 100644
index 0000000000..8b0634d28b
--- /dev/null
+++ b/thirdparty/assimp/assimp/config.h
@@ -0,0 +1,980 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2018, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file config.h
+ * @brief Defines constants for configurable properties for the library
+ *
+ * Typically these properties are set via
+ * #Assimp::Importer::SetPropertyFloat,
+ * #Assimp::Importer::SetPropertyInteger or
+ * #Assimp::Importer::SetPropertyString,
+ * depending on the data type of a property. All properties have a
+ * default value. See the doc for the mentioned methods for more details.
+ *
+ * <br><br>
+ * The corresponding functions for use with the plain-c API are:
+ * #aiSetImportPropertyInteger,
+ * #aiSetImportPropertyFloat,
+ * #aiSetImportPropertyString
+ */
+#pragma once
+#ifndef AI_CONFIG_H_INC
+#define AI_CONFIG_H_INC
+
+// ###########################################################################
+// LIBRARY SETTINGS
+// General, global settings
+// ###########################################################################
+
+// ---------------------------------------------------------------------------
+/** @brief Enables time measurements.
+ *
+ * If enabled, measures the time needed for each part of the loading
+ * process (i.e. IO time, importing, postprocessing, ..) and dumps
+ * these timings to the DefaultLogger. See the @link perf Performance
+ * Page@endlink for more information on this topic.
+ *
+ * Property type: bool. Default value: false.
+ */
+#define AI_CONFIG_GLOB_MEASURE_TIME \
+ "GLOB_MEASURE_TIME"
+
+// ---------------------------------------------------------------------------
+/** @brief Global setting to disable generation of skeleton dummy meshes
+ *
+ * Skeleton dummy meshes are generated as a visualization aid in cases which
+ * the input data contains no geometry, but only animation data.
+ * Property data type: bool. Default value: false
+ */
+// ---------------------------------------------------------------------------
+#define AI_CONFIG_IMPORT_NO_SKELETON_MESHES \
+ "IMPORT_NO_SKELETON_MESHES"
+
+#if 0 // not implemented yet
+// ---------------------------------------------------------------------------
+/** @brief Set Assimp's multithreading policy.
+ *
+ * This setting is ignored if Assimp was built without boost.thread
+ * support (ASSIMP_BUILD_NO_THREADING, which is implied by ASSIMP_BUILD_BOOST_WORKAROUND).
+ * Possible values are: -1 to let Assimp decide what to do, 0 to disable
+ * multithreading entirely and any number larger than 0 to force a specific
+ * number of threads. Assimp is always free to ignore this settings, which is
+ * merely a hint. Usually, the default value (-1) will be fine. However, if
+ * Assimp is used concurrently from multiple user threads, it might be useful
+ * to limit each Importer instance to a specific number of cores.
+ *
+ * For more information, see the @link threading Threading page@endlink.
+ * Property type: int, default value: -1.
+ */
+#define AI_CONFIG_GLOB_MULTITHREADING \
+ "GLOB_MULTITHREADING"
+#endif
+
+// ###########################################################################
+// POST PROCESSING SETTINGS
+// Various stuff to fine-tune the behavior of a specific post processing step.
+// ###########################################################################
+
+// ---------------------------------------------------------------------------
+/** @brief Maximum bone count per mesh for the SplitbyBoneCount step.
+ *
+ * Meshes are split until the maximum number of bones is reached. The default
+ * value is AI_SBBC_DEFAULT_MAX_BONES, which may be altered at
+ * compile-time.
+ * Property data type: integer.
+ */
+// ---------------------------------------------------------------------------
+#define AI_CONFIG_PP_SBBC_MAX_BONES \
+ "PP_SBBC_MAX_BONES"
+
+// default limit for bone count
+#if (!defined AI_SBBC_DEFAULT_MAX_BONES)
+#define AI_SBBC_DEFAULT_MAX_BONES 60
+#endif
+
+// ---------------------------------------------------------------------------
+/** @brief Specifies the maximum angle that may be between two vertex tangents
+ * that their tangents and bi-tangents are smoothed.
+ *
+ * This applies to the CalcTangentSpace-Step. The angle is specified
+ * in degrees. The maximum value is 175.
+ * Property type: float. Default value: 45 degrees
+ */
+#define AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE \
+ "PP_CT_MAX_SMOOTHING_ANGLE"
+
+// ---------------------------------------------------------------------------
+/** @brief Source UV channel for tangent space computation.
+ *
+ * The specified channel must exist or an error will be raised.
+ * Property type: integer. Default value: 0
+ */
+// ---------------------------------------------------------------------------
+#define AI_CONFIG_PP_CT_TEXTURE_CHANNEL_INDEX \
+ "PP_CT_TEXTURE_CHANNEL_INDEX"
+
+// ---------------------------------------------------------------------------
+/** @brief Specifies the maximum angle that may be between two face normals
+ * at the same vertex position that their are smoothed together.
+ *
+ * Sometimes referred to as 'crease angle'.
+ * This applies to the GenSmoothNormals-Step. The angle is specified
+ * in degrees, so 180 is PI. The default value is 175 degrees (all vertex
+ * normals are smoothed). The maximum value is 175, too. Property type: float.
+ * Warning: setting this option may cause a severe loss of performance. The
+ * performance is unaffected if the #AI_CONFIG_FAVOUR_SPEED flag is set but
+ * the output quality may be reduced.
+ */
+#define AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE \
+ "PP_GSN_MAX_SMOOTHING_ANGLE"
+
+// ---------------------------------------------------------------------------
+/** @brief Sets the colormap (= palette) to be used to decode embedded
+ * textures in MDL (Quake or 3DGS) files.
+ *
+ * This must be a valid path to a file. The file is 768 (256*3) bytes
+ * large and contains RGB triplets for each of the 256 palette entries.
+ * The default value is colormap.lmp. If the file is not found,
+ * a default palette (from Quake 1) is used.
+ * Property type: string.
+ */
+#define AI_CONFIG_IMPORT_MDL_COLORMAP \
+ "IMPORT_MDL_COLORMAP"
+
+// ---------------------------------------------------------------------------
+/** @brief Configures the #aiProcess_RemoveRedundantMaterials step to
+ * keep materials matching a name in a given list.
+ *
+ * This is a list of 1 to n strings, ' ' serves as delimiter character.
+ * Identifiers containing whitespaces must be enclosed in *single*
+ * quotation marks. For example:<tt>
+ * "keep-me and_me_to anotherMaterialToBeKept \'name with whitespace\'"</tt>.
+ * If a material matches on of these names, it will not be modified or
+ * removed by the postprocessing step nor will other materials be replaced
+ * by a reference to it. <br>
+ * This option might be useful if you are using some magic material names
+ * to pass additional semantics through the content pipeline. This ensures
+ * they won't be optimized away, but a general optimization is still
+ * performed for materials not contained in the list.
+ * Property type: String. Default value: n/a
+ * @note Linefeeds, tabs or carriage returns are treated as whitespace.
+ * Material names are case sensitive.
+ */
+#define AI_CONFIG_PP_RRM_EXCLUDE_LIST \
+ "PP_RRM_EXCLUDE_LIST"
+
+// ---------------------------------------------------------------------------
+/** @brief Configures the #aiProcess_PreTransformVertices step to
+ * keep the scene hierarchy. Meshes are moved to worldspace, but
+ * no optimization is performed (read: meshes with equal materials are not
+ * joined. The total number of meshes won't change).
+ *
+ * This option could be of use for you if the scene hierarchy contains
+ * important additional information which you intend to parse.
+ * For rendering, you can still render all meshes in the scene without
+ * any transformations.
+ * Property type: bool. Default value: false.
+ */
+#define AI_CONFIG_PP_PTV_KEEP_HIERARCHY \
+ "PP_PTV_KEEP_HIERARCHY"
+
+// ---------------------------------------------------------------------------
+/** @brief Configures the #aiProcess_PreTransformVertices step to normalize
+ * all vertex components into the [-1,1] range. That is, a bounding box
+ * for the whole scene is computed, the maximum component is taken and all
+ * meshes are scaled appropriately (uniformly of course!).
+ * This might be useful if you don't know the spatial dimension of the input
+ * data*/
+#define AI_CONFIG_PP_PTV_NORMALIZE \
+ "PP_PTV_NORMALIZE"
+
+// ---------------------------------------------------------------------------
+/** @brief Configures the #aiProcess_PreTransformVertices step to use
+ * a users defined matrix as the scene root node transformation before
+ * transforming vertices.
+ * Property type: bool. Default value: false.
+ */
+#define AI_CONFIG_PP_PTV_ADD_ROOT_TRANSFORMATION \
+ "PP_PTV_ADD_ROOT_TRANSFORMATION"
+
+// ---------------------------------------------------------------------------
+/** @brief Configures the #aiProcess_PreTransformVertices step to use
+ * a users defined matrix as the scene root node transformation before
+ * transforming vertices. This property correspond to the 'a1' component
+ * of the transformation matrix.
+ * Property type: aiMatrix4x4.
+ */
+#define AI_CONFIG_PP_PTV_ROOT_TRANSFORMATION \
+ "PP_PTV_ROOT_TRANSFORMATION"
+
+// ---------------------------------------------------------------------------
+/** @brief Configures the #aiProcess_FindDegenerates step to
+ * remove degenerated primitives from the import - immediately.
+ *
+ * The default behaviour converts degenerated triangles to lines and
+ * degenerated lines to points. See the documentation to the
+ * #aiProcess_FindDegenerates step for a detailed example of the various ways
+ * to get rid of these lines and points if you don't want them.
+ * Property type: bool. Default value: false.
+ */
+#define AI_CONFIG_PP_FD_REMOVE \
+ "PP_FD_REMOVE"
+
+// ---------------------------------------------------------------------------
+/**
+ * @brief Configures the #aiProcess_FindDegenerates to check the area of a
+ * trinagle to be greates than e-6. If this is not the case the triangle will
+ * be removed if #AI_CONFIG_PP_FD_REMOVE is set to true.
+ */
+#define AI_CONFIG_PP_FD_CHECKAREA \
+ "PP_FD_CHECKAREA"
+
+// ---------------------------------------------------------------------------
+/** @brief Configures the #aiProcess_OptimizeGraph step to preserve nodes
+ * matching a name in a given list.
+ *
+ * This is a list of 1 to n strings, ' ' serves as delimiter character.
+ * Identifiers containing whitespaces must be enclosed in *single*
+ * quotation marks. For example:<tt>
+ * "keep-me and_me_to anotherNodeToBeKept \'name with whitespace\'"</tt>.
+ * If a node matches on of these names, it will not be modified or
+ * removed by the postprocessing step.<br>
+ * This option might be useful if you are using some magic node names
+ * to pass additional semantics through the content pipeline. This ensures
+ * they won't be optimized away, but a general optimization is still
+ * performed for nodes not contained in the list.
+ * Property type: String. Default value: n/a
+ * @note Linefeeds, tabs or carriage returns are treated as whitespace.
+ * Node names are case sensitive.
+ */
+#define AI_CONFIG_PP_OG_EXCLUDE_LIST \
+ "PP_OG_EXCLUDE_LIST"
+
+// ---------------------------------------------------------------------------
+/** @brief Set the maximum number of triangles in a mesh.
+ *
+ * This is used by the "SplitLargeMeshes" PostProcess-Step to determine
+ * whether a mesh must be split or not.
+ * @note The default value is AI_SLM_DEFAULT_MAX_TRIANGLES
+ * Property type: integer.
+ */
+#define AI_CONFIG_PP_SLM_TRIANGLE_LIMIT \
+ "PP_SLM_TRIANGLE_LIMIT"
+
+// default value for AI_CONFIG_PP_SLM_TRIANGLE_LIMIT
+#if (!defined AI_SLM_DEFAULT_MAX_TRIANGLES)
+#define AI_SLM_DEFAULT_MAX_TRIANGLES 1000000
+#endif
+
+// ---------------------------------------------------------------------------
+/** @brief Set the maximum number of vertices in a mesh.
+ *
+ * This is used by the "SplitLargeMeshes" PostProcess-Step to determine
+ * whether a mesh must be split or not.
+ * @note The default value is AI_SLM_DEFAULT_MAX_VERTICES
+ * Property type: integer.
+ */
+#define AI_CONFIG_PP_SLM_VERTEX_LIMIT \
+ "PP_SLM_VERTEX_LIMIT"
+
+// default value for AI_CONFIG_PP_SLM_VERTEX_LIMIT
+#if (!defined AI_SLM_DEFAULT_MAX_VERTICES)
+#define AI_SLM_DEFAULT_MAX_VERTICES 1000000
+#endif
+
+// ---------------------------------------------------------------------------
+/** @brief Set the maximum number of bones affecting a single vertex
+ *
+ * This is used by the #aiProcess_LimitBoneWeights PostProcess-Step.
+ * @note The default value is AI_LMW_MAX_WEIGHTS
+ * Property type: integer.*/
+#define AI_CONFIG_PP_LBW_MAX_WEIGHTS \
+ "PP_LBW_MAX_WEIGHTS"
+
+// default value for AI_CONFIG_PP_LBW_MAX_WEIGHTS
+#if (!defined AI_LMW_MAX_WEIGHTS)
+#define AI_LMW_MAX_WEIGHTS 0x4
+#endif // !! AI_LMW_MAX_WEIGHTS
+
+// ---------------------------------------------------------------------------
+/** @brief Lower the deboning threshold in order to remove more bones.
+ *
+ * This is used by the #aiProcess_Debone PostProcess-Step.
+ * @note The default value is AI_DEBONE_THRESHOLD
+ * Property type: float.*/
+#define AI_CONFIG_PP_DB_THRESHOLD \
+ "PP_DB_THRESHOLD"
+
+// default value for AI_CONFIG_PP_LBW_MAX_WEIGHTS
+#if (!defined AI_DEBONE_THRESHOLD)
+#define AI_DEBONE_THRESHOLD 1.0f
+#endif // !! AI_DEBONE_THRESHOLD
+
+// ---------------------------------------------------------------------------
+/** @brief Require all bones qualify for deboning before removing any
+ *
+ * This is used by the #aiProcess_Debone PostProcess-Step.
+ * @note The default value is 0
+ * Property type: bool.*/
+#define AI_CONFIG_PP_DB_ALL_OR_NONE \
+ "PP_DB_ALL_OR_NONE"
+
+/** @brief Default value for the #AI_CONFIG_PP_ICL_PTCACHE_SIZE property
+ */
+#ifndef PP_ICL_PTCACHE_SIZE
+#define PP_ICL_PTCACHE_SIZE 12
+#endif
+
+// ---------------------------------------------------------------------------
+/** @brief Set the size of the post-transform vertex cache to optimize the
+ * vertices for. This configures the #aiProcess_ImproveCacheLocality step.
+ *
+ * The size is given in vertices. Of course you can't know how the vertex
+ * format will exactly look like after the import returns, but you can still
+ * guess what your meshes will probably have.
+ * @note The default value is #PP_ICL_PTCACHE_SIZE. That results in slight
+ * performance improvements for most nVidia/AMD cards since 2002.
+ * Property type: integer.
+ */
+#define AI_CONFIG_PP_ICL_PTCACHE_SIZE "PP_ICL_PTCACHE_SIZE"
+
+// ---------------------------------------------------------------------------
+/** @brief Enumerates components of the aiScene and aiMesh data structures
+ * that can be excluded from the import using the #aiProcess_RemoveComponent step.
+ *
+ * See the documentation to #aiProcess_RemoveComponent for more details.
+ */
+enum aiComponent {
+/** Normal vectors */
+#ifdef SWIG
+ aiComponent_NORMALS = 0x2,
+#else
+ aiComponent_NORMALS = 0x2u,
+#endif
+
+/** Tangents and bitangents go always together ... */
+#ifdef SWIG
+ aiComponent_TANGENTS_AND_BITANGENTS = 0x4,
+#else
+ aiComponent_TANGENTS_AND_BITANGENTS = 0x4u,
+#endif
+
+ /** ALL color sets
+ * Use aiComponent_COLORn(N) to specify the N'th set */
+ aiComponent_COLORS = 0x8,
+
+ /** ALL texture UV sets
+ * aiComponent_TEXCOORDn(N) to specify the N'th set */
+ aiComponent_TEXCOORDS = 0x10,
+
+ /** Removes all bone weights from all meshes.
+ * The scenegraph nodes corresponding to the bones are NOT removed.
+ * use the #aiProcess_OptimizeGraph step to do this */
+ aiComponent_BONEWEIGHTS = 0x20,
+
+ /** Removes all node animations (aiScene::mAnimations).
+ * The corresponding scenegraph nodes are NOT removed.
+ * use the #aiProcess_OptimizeGraph step to do this */
+ aiComponent_ANIMATIONS = 0x40,
+
+ /** Removes all embedded textures (aiScene::mTextures) */
+ aiComponent_TEXTURES = 0x80,
+
+ /** Removes all light sources (aiScene::mLights).
+ * The corresponding scenegraph nodes are NOT removed.
+ * use the #aiProcess_OptimizeGraph step to do this */
+ aiComponent_LIGHTS = 0x100,
+
+ /** Removes all cameras (aiScene::mCameras).
+ * The corresponding scenegraph nodes are NOT removed.
+ * use the #aiProcess_OptimizeGraph step to do this */
+ aiComponent_CAMERAS = 0x200,
+
+ /** Removes all meshes (aiScene::mMeshes). */
+ aiComponent_MESHES = 0x400,
+
+ /** Removes all materials. One default material will
+ * be generated, so aiScene::mNumMaterials will be 1. */
+ aiComponent_MATERIALS = 0x800,
+
+/** This value is not used. It is just there to force the
+ * compiler to map this enum to a 32 Bit integer. */
+#ifndef SWIG
+ _aiComponent_Force32Bit = 0x9fffffff
+#endif
+};
+
+// Remove a specific color channel 'n'
+#define aiComponent_COLORSn(n) (1u << (n + 20u))
+
+// Remove a specific UV channel 'n'
+#define aiComponent_TEXCOORDSn(n) (1u << (n + 25u))
+
+// ---------------------------------------------------------------------------
+/** @brief Input parameter to the #aiProcess_RemoveComponent step:
+ * Specifies the parts of the data structure to be removed.
+ *
+ * See the documentation to this step for further details. The property
+ * is expected to be an integer, a bitwise combination of the
+ * #aiComponent flags defined above in this header. The default
+ * value is 0. Important: if no valid mesh is remaining after the
+ * step has been executed (e.g you thought it was funny to specify ALL
+ * of the flags defined above) the import FAILS. Mainly because there is
+ * no data to work on anymore ...
+ */
+#define AI_CONFIG_PP_RVC_FLAGS \
+ "PP_RVC_FLAGS"
+
+// ---------------------------------------------------------------------------
+/** @brief Input parameter to the #aiProcess_SortByPType step:
+ * Specifies which primitive types are removed by the step.
+ *
+ * This is a bitwise combination of the aiPrimitiveType flags.
+ * Specifying all of them is illegal, of course. A typical use would
+ * be to exclude all line and point meshes from the import. This
+ * is an integer property, its default value is 0.
+ */
+#define AI_CONFIG_PP_SBP_REMOVE \
+ "PP_SBP_REMOVE"
+
+// ---------------------------------------------------------------------------
+/** @brief Input parameter to the #aiProcess_FindInvalidData step:
+ * Specifies the floating-point accuracy for animation values. The step
+ * checks for animation tracks where all frame values are absolutely equal
+ * and removes them. This tweakable controls the epsilon for floating-point
+ * comparisons - two keys are considered equal if the invariant
+ * abs(n0-n1)>epsilon holds true for all vector respectively quaternion
+ * components. The default value is 0.f - comparisons are exact then.
+ */
+#define AI_CONFIG_PP_FID_ANIM_ACCURACY \
+ "PP_FID_ANIM_ACCURACY"
+
+// TransformUVCoords evaluates UV scalings
+#define AI_UVTRAFO_SCALING 0x1
+
+// TransformUVCoords evaluates UV rotations
+#define AI_UVTRAFO_ROTATION 0x2
+
+// TransformUVCoords evaluates UV translation
+#define AI_UVTRAFO_TRANSLATION 0x4
+
+// Everything baked together -> default value
+#define AI_UVTRAFO_ALL (AI_UVTRAFO_SCALING | AI_UVTRAFO_ROTATION | AI_UVTRAFO_TRANSLATION)
+
+// ---------------------------------------------------------------------------
+/** @brief Input parameter to the #aiProcess_FindInvalidData step:
+ * Set to true to ignore texture coordinates. This may be useful if you have
+ * to assign different kind of textures like one for the summer or one for the winter.
+ */
+#define AI_CONFIG_PP_FID_IGNORE_TEXTURECOORDS \
+ "PP_FID_IGNORE_TEXTURECOORDS"
+
+// ---------------------------------------------------------------------------
+/** @brief Input parameter to the #aiProcess_TransformUVCoords step:
+ * Specifies which UV transformations are evaluated.
+ *
+ * This is a bitwise combination of the AI_UVTRAFO_XXX flags (integer
+ * property, of course). By default all transformations are enabled
+ * (AI_UVTRAFO_ALL).
+ */
+#define AI_CONFIG_PP_TUV_EVALUATE \
+ "PP_TUV_EVALUATE"
+
+// ---------------------------------------------------------------------------
+/** @brief A hint to assimp to favour speed against import quality.
+ *
+ * Enabling this option may result in faster loading, but it needn't.
+ * It represents just a hint to loaders and post-processing steps to use
+ * faster code paths, if possible.
+ * This property is expected to be an integer, != 0 stands for true.
+ * The default value is 0.
+ */
+#define AI_CONFIG_FAVOUR_SPEED \
+ "FAVOUR_SPEED"
+
+// ###########################################################################
+// IMPORTER SETTINGS
+// Various stuff to fine-tune the behaviour of specific importer plugins.
+// ###########################################################################
+
+// ---------------------------------------------------------------------------
+/** @brief Set whether the fbx importer will merge all geometry layers present
+ * in the source file or take only the first.
+ *
+ * The default value is true (1)
+ * Property type: bool
+ */
+#define AI_CONFIG_IMPORT_FBX_READ_ALL_GEOMETRY_LAYERS \
+ "IMPORT_FBX_READ_ALL_GEOMETRY_LAYERS"
+
+// ---------------------------------------------------------------------------
+/** @brief Set whether the fbx importer will read all materials present in the
+ * source file or take only the referenced materials.
+ *
+ * This is void unless IMPORT_FBX_READ_MATERIALS=1.
+ *
+ * The default value is false (0)
+ * Property type: bool
+ */
+#define AI_CONFIG_IMPORT_FBX_READ_ALL_MATERIALS \
+ "IMPORT_FBX_READ_ALL_MATERIALS"
+
+// ---------------------------------------------------------------------------
+/** @brief Set whether the fbx importer will read materials.
+ *
+ * The default value is true (1)
+ * Property type: bool
+ */
+#define AI_CONFIG_IMPORT_FBX_READ_MATERIALS \
+ "IMPORT_FBX_READ_MATERIALS"
+
+// ---------------------------------------------------------------------------
+/** @brief Set whether the fbx importer will read embedded textures.
+ *
+ * The default value is true (1)
+ * Property type: bool
+ */
+#define AI_CONFIG_IMPORT_FBX_READ_TEXTURES \
+ "IMPORT_FBX_READ_TEXTURES"
+
+// ---------------------------------------------------------------------------
+/** @brief Set whether the fbx importer will read cameras.
+ *
+ * The default value is true (1)
+ * Property type: bool
+ */
+#define AI_CONFIG_IMPORT_FBX_READ_CAMERAS \
+ "IMPORT_FBX_READ_CAMERAS"
+
+// ---------------------------------------------------------------------------
+/** @brief Set whether the fbx importer will read light sources.
+ *
+ * The default value is true (1)
+ * Property type: bool
+ */
+#define AI_CONFIG_IMPORT_FBX_READ_LIGHTS \
+ "IMPORT_FBX_READ_LIGHTS"
+
+// ---------------------------------------------------------------------------
+/** @brief Set whether the fbx importer will read animations.
+ *
+ * The default value is true (1)
+ * Property type: bool
+ */
+#define AI_CONFIG_IMPORT_FBX_READ_ANIMATIONS \
+ "IMPORT_FBX_READ_ANIMATIONS"
+
+// ---------------------------------------------------------------------------
+/** @brief Set whether the fbx importer will act in strict mode in which only
+ * FBX 2013 is supported and any other sub formats are rejected. FBX 2013
+ * is the primary target for the importer, so this format is best
+ * supported and well-tested.
+ *
+ * The default value is false (0)
+ * Property type: bool
+ */
+#define AI_CONFIG_IMPORT_FBX_STRICT_MODE \
+ "IMPORT_FBX_STRICT_MODE"
+
+// ---------------------------------------------------------------------------
+/** @brief Set whether the fbx importer will preserve pivot points for
+ * transformations (as extra nodes). If set to false, pivots and offsets
+ * will be evaluated whenever possible.
+ *
+ * The default value is true (1)
+ * Property type: bool
+ */
+#define AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS \
+ "IMPORT_FBX_PRESERVE_PIVOTS"
+
+// ---------------------------------------------------------------------------
+/** @brief Specifies whether the importer will drop empty animation curves or
+ * animation curves which match the bind pose transformation over their
+ * entire defined range.
+ *
+ * The default value is true (1)
+ * Property type: bool
+ */
+#define AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES \
+ "IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES"
+
+// ---------------------------------------------------------------------------
+/** @brief Set whether the fbx importer will use the legacy embedded texture naming.
+*
+* The default value is false (0)
+* Property type: bool
+*/
+#define AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING \
+ "AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING"
+
+// ---------------------------------------------------------------------------
+/** @brief Set the vertex animation keyframe to be imported
+ *
+ * ASSIMP does not support vertex keyframes (only bone animation is supported).
+ * The library reads only one frame of models with vertex animations.
+ * By default this is the first frame.
+ * \note The default value is 0. This option applies to all importers.
+ * However, it is also possible to override the global setting
+ * for a specific loader. You can use the AI_CONFIG_IMPORT_XXX_KEYFRAME
+ * options (where XXX is a placeholder for the file format for which you
+ * want to override the global setting).
+ * Property type: integer.
+ */
+#define AI_CONFIG_IMPORT_GLOBAL_KEYFRAME "IMPORT_GLOBAL_KEYFRAME"
+
+#define AI_CONFIG_IMPORT_MD3_KEYFRAME "IMPORT_MD3_KEYFRAME"
+#define AI_CONFIG_IMPORT_MD2_KEYFRAME "IMPORT_MD2_KEYFRAME"
+#define AI_CONFIG_IMPORT_MDL_KEYFRAME "IMPORT_MDL_KEYFRAME"
+#define AI_CONFIG_IMPORT_MDC_KEYFRAME "IMPORT_MDC_KEYFRAME"
+#define AI_CONFIG_IMPORT_SMD_KEYFRAME "IMPORT_SMD_KEYFRAME"
+#define AI_CONFIG_IMPORT_UNREAL_KEYFRAME "IMPORT_UNREAL_KEYFRAME"
+
+// ---------------------------------------------------------------------------
+/** Smd load multiple animations
+ *
+ * Property type: bool. Default value: true.
+ */
+#define AI_CONFIG_IMPORT_SMD_LOAD_ANIMATION_LIST "IMPORT_SMD_LOAD_ANIMATION_LIST"
+
+// ---------------------------------------------------------------------------
+/** @brief Configures the AC loader to collect all surfaces which have the
+ * "Backface cull" flag set in separate meshes.
+ *
+ * Property type: bool. Default value: true.
+ */
+#define AI_CONFIG_IMPORT_AC_SEPARATE_BFCULL \
+ "IMPORT_AC_SEPARATE_BFCULL"
+
+// ---------------------------------------------------------------------------
+/** @brief Configures whether the AC loader evaluates subdivision surfaces (
+ * indicated by the presence of the 'subdiv' attribute in the file). By
+ * default, Assimp performs the subdivision using the standard
+ * Catmull-Clark algorithm
+ *
+ * * Property type: bool. Default value: true.
+ */
+#define AI_CONFIG_IMPORT_AC_EVAL_SUBDIVISION \
+ "IMPORT_AC_EVAL_SUBDIVISION"
+
+// ---------------------------------------------------------------------------
+/** @brief Configures the UNREAL 3D loader to separate faces with different
+ * surface flags (e.g. two-sided vs. single-sided).
+ *
+ * * Property type: bool. Default value: true.
+ */
+#define AI_CONFIG_IMPORT_UNREAL_HANDLE_FLAGS \
+ "UNREAL_HANDLE_FLAGS"
+
+// ---------------------------------------------------------------------------
+/** @brief Configures the terragen import plugin to compute uv's for
+ * terrains, if not given. Furthermore a default texture is assigned.
+ *
+ * UV coordinates for terrains are so simple to compute that you'll usually
+ * want to compute them on your own, if you need them. This option is intended
+ * for model viewers which want to offer an easy way to apply textures to
+ * terrains.
+ * * Property type: bool. Default value: false.
+ */
+#define AI_CONFIG_IMPORT_TER_MAKE_UVS \
+ "IMPORT_TER_MAKE_UVS"
+
+// ---------------------------------------------------------------------------
+/** @brief Configures the ASE loader to always reconstruct normal vectors
+ * basing on the smoothing groups loaded from the file.
+ *
+ * Some ASE files have carry invalid normals, other don't.
+ * * Property type: bool. Default value: true.
+ */
+#define AI_CONFIG_IMPORT_ASE_RECONSTRUCT_NORMALS \
+ "IMPORT_ASE_RECONSTRUCT_NORMALS"
+
+// ---------------------------------------------------------------------------
+/** @brief Configures the M3D loader to detect and process multi-part
+ * Quake player models.
+ *
+ * These models usually consist of 3 files, lower.md3, upper.md3 and
+ * head.md3. If this property is set to true, Assimp will try to load and
+ * combine all three files if one of them is loaded.
+ * Property type: bool. Default value: true.
+ */
+#define AI_CONFIG_IMPORT_MD3_HANDLE_MULTIPART \
+ "IMPORT_MD3_HANDLE_MULTIPART"
+
+// ---------------------------------------------------------------------------
+/** @brief Tells the MD3 loader which skin files to load.
+ *
+ * When loading MD3 files, Assimp checks whether a file
+ * [md3_file_name]_[skin_name].skin is existing. These files are used by
+ * Quake III to be able to assign different skins (e.g. red and blue team)
+ * to models. 'default', 'red', 'blue' are typical skin names.
+ * Property type: String. Default value: "default".
+ */
+#define AI_CONFIG_IMPORT_MD3_SKIN_NAME \
+ "IMPORT_MD3_SKIN_NAME"
+
+// ---------------------------------------------------------------------------
+/** @brief Specify the Quake 3 shader file to be used for a particular
+ * MD3 file. This can also be a search path.
+ *
+ * By default Assimp's behaviour is as follows: If a MD3 file
+ * <tt>any_path/models/any_q3_subdir/model_name/file_name.md3</tt> is
+ * loaded, the library tries to locate the corresponding shader file in
+ * <tt>any_path/scripts/model_name.shader</tt>. This property overrides this
+ * behaviour. It can either specify a full path to the shader to be loaded
+ * or alternatively the path (relative or absolute) to the directory where
+ * the shaders for all MD3s to be loaded reside. Assimp attempts to open
+ * <tt>IMPORT_MD3_SHADER_SRC/model_name.shader</tt> first, <tt>IMPORT_MD3_SHADER_SRC/file_name.shader</tt>
+ * is the fallback file. Note that IMPORT_MD3_SHADER_SRC should have a terminal (back)slash.
+ * Property type: String. Default value: n/a.
+ */
+#define AI_CONFIG_IMPORT_MD3_SHADER_SRC \
+ "IMPORT_MD3_SHADER_SRC"
+
+// ---------------------------------------------------------------------------
+/** @brief Configures the LWO loader to load just one layer from the model.
+ *
+ * LWO files consist of layers and in some cases it could be useful to load
+ * only one of them. This property can be either a string - which specifies
+ * the name of the layer - or an integer - the index of the layer. If the
+ * property is not set the whole LWO model is loaded. Loading fails if the
+ * requested layer is not available. The layer index is zero-based and the
+ * layer name may not be empty.<br>
+ * Property type: Integer. Default value: all layers are loaded.
+ */
+#define AI_CONFIG_IMPORT_LWO_ONE_LAYER_ONLY \
+ "IMPORT_LWO_ONE_LAYER_ONLY"
+
+// ---------------------------------------------------------------------------
+/** @brief Configures the MD5 loader to not load the MD5ANIM file for
+ * a MD5MESH file automatically.
+ *
+ * The default strategy is to look for a file with the same name but the
+ * MD5ANIM extension in the same directory. If it is found, it is loaded
+ * and combined with the MD5MESH file. This configuration option can be
+ * used to disable this behaviour.
+ *
+ * * Property type: bool. Default value: false.
+ */
+#define AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD \
+ "IMPORT_MD5_NO_ANIM_AUTOLOAD"
+
+// ---------------------------------------------------------------------------
+/** @brief Defines the begin of the time range for which the LWS loader
+ * evaluates animations and computes aiNodeAnim's.
+ *
+ * Assimp provides full conversion of LightWave's envelope system, including
+ * pre and post conditions. The loader computes linearly subsampled animation
+ * chanels with the frame rate given in the LWS file. This property defines
+ * the start time. Note: animation channels are only generated if a node
+ * has at least one envelope with more tan one key assigned. This property.
+ * is given in frames, '0' is the first frame. By default, if this property
+ * is not set, the importer takes the animation start from the input LWS
+ * file ('FirstFrame' line)<br>
+ * Property type: Integer. Default value: taken from file.
+ *
+ * @see AI_CONFIG_IMPORT_LWS_ANIM_END - end of the imported time range
+ */
+#define AI_CONFIG_IMPORT_LWS_ANIM_START \
+ "IMPORT_LWS_ANIM_START"
+#define AI_CONFIG_IMPORT_LWS_ANIM_END \
+ "IMPORT_LWS_ANIM_END"
+
+// ---------------------------------------------------------------------------
+/** @brief Defines the output frame rate of the IRR loader.
+ *
+ * IRR animations are difficult to convert for Assimp and there will
+ * always be a loss of quality. This setting defines how many keys per second
+ * are returned by the converter.<br>
+ * Property type: integer. Default value: 100
+ */
+#define AI_CONFIG_IMPORT_IRR_ANIM_FPS \
+ "IMPORT_IRR_ANIM_FPS"
+
+// ---------------------------------------------------------------------------
+/** @brief Ogre Importer will try to find referenced materials from this file.
+ *
+ * Ogre meshes reference with material names, this does not tell Assimp the file
+ * where it is located in. Assimp will try to find the source file in the following
+ * order: <material-name>.material, <mesh-filename-base>.material and
+ * lastly the material name defined by this config property.
+ * <br>
+ * Property type: String. Default value: Scene.material.
+ */
+#define AI_CONFIG_IMPORT_OGRE_MATERIAL_FILE \
+ "IMPORT_OGRE_MATERIAL_FILE"
+
+// ---------------------------------------------------------------------------
+/** @brief Ogre Importer detect the texture usage from its filename.
+ *
+ * Ogre material texture units do not define texture type, the textures usage
+ * depends on the used shader or Ogre's fixed pipeline. If this config property
+ * is true Assimp will try to detect the type from the textures filename postfix:
+ * _n, _nrm, _nrml, _normal, _normals and _normalmap for normal map, _s, _spec,
+ * _specular and _specularmap for specular map, _l, _light, _lightmap, _occ
+ * and _occlusion for light map, _disp and _displacement for displacement map.
+ * The matching is case insensitive. Post fix is taken between the last
+ * underscore and the last period.
+ * Default behavior is to detect type from lower cased texture unit name by
+ * matching against: normalmap, specularmap, lightmap and displacementmap.
+ * For both cases if no match is found aiTextureType_DIFFUSE is used.
+ * <br>
+ * Property type: Bool. Default value: false.
+ */
+#define AI_CONFIG_IMPORT_OGRE_TEXTURETYPE_FROM_FILENAME \
+ "IMPORT_OGRE_TEXTURETYPE_FROM_FILENAME"
+
+/** @brief Specifies whether the Android JNI asset extraction is supported.
+ *
+ * Turn on this option if you want to manage assets in native
+ * Android application without having to keep the internal directory and asset
+ * manager pointer.
+ */
+#define AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT "AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT"
+
+// ---------------------------------------------------------------------------
+/** @brief Specifies whether the IFC loader skips over IfcSpace elements.
+ *
+ * IfcSpace elements (and their geometric representations) are used to
+ * represent, well, free space in a building storey.<br>
+ * Property type: Bool. Default value: true.
+ */
+#define AI_CONFIG_IMPORT_IFC_SKIP_SPACE_REPRESENTATIONS "IMPORT_IFC_SKIP_SPACE_REPRESENTATIONS"
+
+// ---------------------------------------------------------------------------
+/** @brief Specifies whether the IFC loader will use its own, custom triangulation
+ * algorithm to triangulate wall and floor meshes.
+ *
+ * If this property is set to false, walls will be either triangulated by
+ * #aiProcess_Triangulate or will be passed through as huge polygons with
+ * faked holes (i.e. holes that are connected with the outer boundary using
+ * a dummy edge). It is highly recommended to set this property to true
+ * if you want triangulated data because #aiProcess_Triangulate is known to
+ * have problems with the kind of polygons that the IFC loader spits out for
+ * complicated meshes.
+ * Property type: Bool. Default value: true.
+ */
+#define AI_CONFIG_IMPORT_IFC_CUSTOM_TRIANGULATION "IMPORT_IFC_CUSTOM_TRIANGULATION"
+
+// ---------------------------------------------------------------------------
+/** @brief Set the tessellation conic angle for IFC smoothing curves.
+ *
+ * This is used by the IFC importer to determine the tessellation parameter
+ * for smoothing curves.
+ * @note The default value is AI_IMPORT_IFC_DEFAULT_SMOOTHING_ANGLE and the
+ * accepted values are in range [5.0, 120.0].
+ * Property type: Float.
+ */
+#define AI_CONFIG_IMPORT_IFC_SMOOTHING_ANGLE "IMPORT_IFC_SMOOTHING_ANGLE"
+
+// default value for AI_CONFIG_IMPORT_IFC_SMOOTHING_ANGLE
+#if (!defined AI_IMPORT_IFC_DEFAULT_SMOOTHING_ANGLE)
+#define AI_IMPORT_IFC_DEFAULT_SMOOTHING_ANGLE 10.0f
+#endif
+
+// ---------------------------------------------------------------------------
+/** @brief Set the tessellation for IFC cylindrical shapes.
+ *
+ * This is used by the IFC importer to determine the tessellation parameter
+ * for cylindrical shapes, i.e. the number of segments used to approximate a circle.
+ * @note The default value is AI_IMPORT_IFC_DEFAULT_CYLINDRICAL_TESSELLATION and the
+ * accepted values are in range [3, 180].
+ * Property type: Integer.
+ */
+#define AI_CONFIG_IMPORT_IFC_CYLINDRICAL_TESSELLATION "IMPORT_IFC_CYLINDRICAL_TESSELLATION"
+
+// default value for AI_CONFIG_IMPORT_IFC_CYLINDRICAL_TESSELLATION
+#if (!defined AI_IMPORT_IFC_DEFAULT_CYLINDRICAL_TESSELLATION)
+#define AI_IMPORT_IFC_DEFAULT_CYLINDRICAL_TESSELLATION 32
+#endif
+
+// ---------------------------------------------------------------------------
+/** @brief Specifies whether the Collada loader will ignore the provided up direction.
+ *
+ * If this property is set to true, the up direction provided in the file header will
+ * be ignored and the file will be loaded as is.
+ * Property type: Bool. Default value: false.
+ */
+#define AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION "IMPORT_COLLADA_IGNORE_UP_DIRECTION"
+
+// ---------------------------------------------------------------------------
+/** @brief Specifies whether the Collada loader should use Collada names as node names.
+ *
+ * If this property is set to true, the Collada names will be used as the
+ * node name. The default is to use the id tag (resp. sid tag, if no id tag is present)
+ * instead.
+ * Property type: Bool. Default value: false.
+ */
+#define AI_CONFIG_IMPORT_COLLADA_USE_COLLADA_NAMES "IMPORT_COLLADA_USE_COLLADA_NAMES"
+
+// ---------- All the Export defines ------------
+
+/** @brief Specifies the xfile use double for real values of float
+ *
+ * Property type: Bool. Default value: false.
+ */
+
+#define AI_CONFIG_EXPORT_XFILE_64BIT "EXPORT_XFILE_64BIT"
+
+/**
+ *
+ */
+#define AI_CONFIG_EXPORT_POINT_CLOUDS "EXPORT_POINT_CLOUDS"
+
+/**
+ * @brief Specifies a gobal key factor for scale, float value
+ */
+#define AI_CONFIG_GLOBAL_SCALE_FACTOR_KEY "GLOBAL_SCALE_FACTOR"
+
+#if (!defined AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT)
+#define AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT 1.0f
+#endif // !! AI_DEBONE_THRESHOLD
+
+// ---------- All the Build/Compile-time defines ------------
+
+/** @brief Specifies if double precision is supported inside assimp
+ *
+ * Property type: Bool. Default value: undefined.
+ */
+
+/* #cmakedefine ASSIMP_DOUBLE_PRECISION 1 */
+
+#endif // !! AI_CONFIG_H_INC
diff --git a/thirdparty/assimp/code/BaseImporter.cpp b/thirdparty/assimp/code/BaseImporter.cpp
new file mode 100644
index 0000000000..4803c6d6f2
--- /dev/null
+++ b/thirdparty/assimp/code/BaseImporter.cpp
@@ -0,0 +1,616 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file BaseImporter.cpp
+ * @brief Implementation of BaseImporter
+ */
+
+#include <assimp/BaseImporter.h>
+#include <assimp/ParsingUtils.h>
+#include "FileSystemFilter.h"
+#include "Importer.h"
+#include <assimp/ByteSwapper.h>
+#include <assimp/scene.h>
+#include <assimp/Importer.hpp>
+#include <assimp/postprocess.h>
+#include <assimp/importerdesc.h>
+
+#include <ios>
+#include <list>
+#include <memory>
+#include <sstream>
+#include <cctype>
+
+using namespace Assimp;
+
+// ------------------------------------------------------------------------------------------------
+// Constructor to be privately used by Importer
+BaseImporter::BaseImporter() AI_NO_EXCEPT
+: m_progress() {
+ // nothing to do here
+}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor, private as well
+BaseImporter::~BaseImporter() {
+ // nothing to do here
+}
+
+// ------------------------------------------------------------------------------------------------
+// Imports the given file and returns the imported data.
+aiScene* BaseImporter::ReadFile(const Importer* pImp, const std::string& pFile, IOSystem* pIOHandler) {
+ m_progress = pImp->GetProgressHandler();
+ if (nullptr == m_progress) {
+ return nullptr;
+ }
+
+ ai_assert(m_progress);
+
+ // Gather configuration properties for this run
+ SetupProperties( pImp );
+
+ // Construct a file system filter to improve our success ratio at reading external files
+ FileSystemFilter filter(pFile,pIOHandler);
+
+ // create a scene object to hold the data
+ std::unique_ptr<aiScene> sc(new aiScene());
+
+ // dispatch importing
+ try
+ {
+ InternReadFile( pFile, sc.get(), &filter);
+
+ } catch( const std::exception& err ) {
+ // extract error description
+ m_ErrorText = err.what();
+ ASSIMP_LOG_ERROR(m_ErrorText);
+ return nullptr;
+ }
+
+ // return what we gathered from the import.
+ return sc.release();
+}
+
+// ------------------------------------------------------------------------------------------------
+void BaseImporter::SetupProperties(const Importer* /*pImp*/)
+{
+ // the default implementation does nothing
+}
+
+// ------------------------------------------------------------------------------------------------
+void BaseImporter::GetExtensionList(std::set<std::string>& extensions) {
+ const aiImporterDesc* desc = GetInfo();
+ ai_assert(desc != nullptr);
+
+ const char* ext = desc->mFileExtensions;
+ ai_assert(ext != nullptr );
+
+ const char* last = ext;
+ do {
+ if (!*ext || *ext == ' ') {
+ extensions.insert(std::string(last,ext-last));
+ ai_assert(ext-last > 0);
+ last = ext;
+ while(*last == ' ') {
+ ++last;
+ }
+ }
+ }
+ while(*ext++);
+}
+
+// ------------------------------------------------------------------------------------------------
+/*static*/ bool BaseImporter::SearchFileHeaderForToken( IOSystem* pIOHandler,
+ const std::string& pFile,
+ const char** tokens,
+ unsigned int numTokens,
+ unsigned int searchBytes /* = 200 */,
+ bool tokensSol /* false */,
+ bool noAlphaBeforeTokens /* false */)
+{
+ ai_assert( nullptr != tokens );
+ ai_assert( 0 != numTokens );
+ ai_assert( 0 != searchBytes);
+
+ if ( nullptr == pIOHandler ) {
+ return false;
+ }
+
+ std::unique_ptr<IOStream> pStream (pIOHandler->Open(pFile));
+ if (pStream.get() ) {
+ // read 200 characters from the file
+ std::unique_ptr<char[]> _buffer (new char[searchBytes+1 /* for the '\0' */]);
+ char *buffer( _buffer.get() );
+ const size_t read( pStream->Read(buffer,1,searchBytes) );
+ if( 0 == read ) {
+ return false;
+ }
+
+ for( size_t i = 0; i < read; ++i ) {
+ buffer[ i ] = static_cast<char>( ::tolower( buffer[ i ] ) );
+ }
+
+ // It is not a proper handling of unicode files here ...
+ // ehm ... but it works in most cases.
+ char* cur = buffer,*cur2 = buffer,*end = &buffer[read];
+ while (cur != end) {
+ if( *cur ) {
+ *cur2++ = *cur;
+ }
+ ++cur;
+ }
+ *cur2 = '\0';
+
+ std::string token;
+ for (unsigned int i = 0; i < numTokens; ++i ) {
+ ai_assert( nullptr != tokens[i] );
+ const size_t len( strlen( tokens[ i ] ) );
+ token.clear();
+ const char *ptr( tokens[ i ] );
+ for ( size_t tokIdx = 0; tokIdx < len; ++tokIdx ) {
+ token.push_back( static_cast<char>( tolower( *ptr ) ) );
+ ++ptr;
+ }
+ const char* r = strstr( buffer, token.c_str() );
+ if( !r ) {
+ continue;
+ }
+ // We need to make sure that we didn't accidentially identify the end of another token as our token,
+ // e.g. in a previous version the "gltf " present in some gltf files was detected as "f "
+ if (noAlphaBeforeTokens && (r != buffer && isalpha(r[-1]))) {
+ continue;
+ }
+ // We got a match, either we don't care where it is, or it happens to
+ // be in the beginning of the file / line
+ if (!tokensSol || r == buffer || r[-1] == '\r' || r[-1] == '\n') {
+ ASSIMP_LOG_DEBUG_F( "Found positive match for header keyword: ", tokens[i] );
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Simple check for file extension
+/*static*/ bool BaseImporter::SimpleExtensionCheck (const std::string& pFile,
+ const char* ext0,
+ const char* ext1,
+ const char* ext2)
+{
+ std::string::size_type pos = pFile.find_last_of('.');
+
+ // no file extension - can't read
+ if( pos == std::string::npos)
+ return false;
+
+ const char* ext_real = & pFile[ pos+1 ];
+ if( !ASSIMP_stricmp(ext_real,ext0) )
+ return true;
+
+ // check for other, optional, file extensions
+ if (ext1 && !ASSIMP_stricmp(ext_real,ext1))
+ return true;
+
+ if (ext2 && !ASSIMP_stricmp(ext_real,ext2))
+ return true;
+
+ return false;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Get file extension from path
+std::string BaseImporter::GetExtension( const std::string& file ) {
+ std::string::size_type pos = file.find_last_of('.');
+
+ // no file extension at all
+ if (pos == std::string::npos) {
+ return "";
+ }
+
+
+ // thanks to Andy Maloney for the hint
+ std::string ret = file.substr( pos + 1 );
+ std::transform( ret.begin(), ret.end(), ret.begin(), ToLower<char>);
+
+ return ret;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Check for magic bytes at the beginning of the file.
+/* static */ bool BaseImporter::CheckMagicToken(IOSystem* pIOHandler, const std::string& pFile,
+ const void* _magic, unsigned int num, unsigned int offset, unsigned int size)
+{
+ ai_assert( size <= 16 );
+ ai_assert( _magic );
+
+ if (!pIOHandler) {
+ return false;
+ }
+ union {
+ const char* magic;
+ const uint16_t* magic_u16;
+ const uint32_t* magic_u32;
+ };
+ magic = reinterpret_cast<const char*>(_magic);
+ std::unique_ptr<IOStream> pStream (pIOHandler->Open(pFile));
+ if (pStream.get() ) {
+
+ // skip to offset
+ pStream->Seek(offset,aiOrigin_SET);
+
+ // read 'size' characters from the file
+ union {
+ char data[16];
+ uint16_t data_u16[8];
+ uint32_t data_u32[4];
+ };
+ if(size != pStream->Read(data,1,size)) {
+ return false;
+ }
+
+ for (unsigned int i = 0; i < num; ++i) {
+ // also check against big endian versions of tokens with size 2,4
+ // that's just for convenience, the chance that we cause conflicts
+ // is quite low and it can save some lines and prevent nasty bugs
+ if (2 == size) {
+ uint16_t rev = *magic_u16;
+ ByteSwap::Swap(&rev);
+ if (data_u16[0] == *magic_u16 || data_u16[0] == rev) {
+ return true;
+ }
+ }
+ else if (4 == size) {
+ uint32_t rev = *magic_u32;
+ ByteSwap::Swap(&rev);
+ if (data_u32[0] == *magic_u32 || data_u32[0] == rev) {
+ return true;
+ }
+ }
+ else {
+ // any length ... just compare
+ if(!memcmp(magic,data,size)) {
+ return true;
+ }
+ }
+ magic += size;
+ }
+ }
+ return false;
+}
+
+#include "../contrib/utf8cpp/source/utf8.h"
+
+// ------------------------------------------------------------------------------------------------
+// Convert to UTF8 data
+void BaseImporter::ConvertToUTF8(std::vector<char>& data)
+{
+ //ConversionResult result;
+ if(data.size() < 8) {
+ throw DeadlyImportError("File is too small");
+ }
+
+ // UTF 8 with BOM
+ if((uint8_t)data[0] == 0xEF && (uint8_t)data[1] == 0xBB && (uint8_t)data[2] == 0xBF) {
+ ASSIMP_LOG_DEBUG("Found UTF-8 BOM ...");
+
+ std::copy(data.begin()+3,data.end(),data.begin());
+ data.resize(data.size()-3);
+ return;
+ }
+
+
+ // UTF 32 BE with BOM
+ if(*((uint32_t*)&data.front()) == 0xFFFE0000) {
+
+ // swap the endianness ..
+ for(uint32_t* p = (uint32_t*)&data.front(), *end = (uint32_t*)&data.back(); p <= end; ++p) {
+ AI_SWAP4P(p);
+ }
+ }
+
+ // UTF 32 LE with BOM
+ if(*((uint32_t*)&data.front()) == 0x0000FFFE) {
+ ASSIMP_LOG_DEBUG("Found UTF-32 BOM ...");
+
+ std::vector<char> output;
+ int *ptr = (int*)&data[ 0 ];
+ int *end = ptr + ( data.size() / sizeof(int) ) +1;
+ utf8::utf32to8( ptr, end, back_inserter(output));
+ return;
+ }
+
+ // UTF 16 BE with BOM
+ if(*((uint16_t*)&data.front()) == 0xFFFE) {
+
+ // swap the endianness ..
+ for(uint16_t* p = (uint16_t*)&data.front(), *end = (uint16_t*)&data.back(); p <= end; ++p) {
+ ByteSwap::Swap2(p);
+ }
+ }
+
+ // UTF 16 LE with BOM
+ if(*((uint16_t*)&data.front()) == 0xFEFF) {
+ ASSIMP_LOG_DEBUG("Found UTF-16 BOM ...");
+
+ std::vector<unsigned char> output;
+ utf8::utf16to8(data.begin(), data.end(), back_inserter(output));
+ return;
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Convert to UTF8 data to ISO-8859-1
+void BaseImporter::ConvertUTF8toISO8859_1(std::string& data)
+{
+ size_t size = data.size();
+ size_t i = 0, j = 0;
+
+ while(i < size) {
+ if ((unsigned char) data[i] < (size_t) 0x80) {
+ data[j] = data[i];
+ } else if(i < size - 1) {
+ if((unsigned char) data[i] == 0xC2) {
+ data[j] = data[++i];
+ } else if((unsigned char) data[i] == 0xC3) {
+ data[j] = ((unsigned char) data[++i] + 0x40);
+ } else {
+ std::stringstream stream;
+ stream << "UTF8 code " << std::hex << data[i] << data[i + 1] << " can not be converted into ISA-8859-1.";
+ ASSIMP_LOG_ERROR( stream.str() );
+
+ data[j++] = data[i++];
+ data[j] = data[i];
+ }
+ } else {
+ ASSIMP_LOG_ERROR("UTF8 code but only one character remaining");
+
+ data[j] = data[i];
+ }
+
+ i++; j++;
+ }
+
+ data.resize(j);
+}
+
+// ------------------------------------------------------------------------------------------------
+void BaseImporter::TextFileToBuffer(IOStream* stream,
+ std::vector<char>& data,
+ TextFileMode mode)
+{
+ ai_assert(nullptr != stream);
+
+ const size_t fileSize = stream->FileSize();
+ if (mode == FORBID_EMPTY) {
+ if(!fileSize) {
+ throw DeadlyImportError("File is empty");
+ }
+ }
+
+ data.reserve(fileSize+1);
+ data.resize(fileSize);
+ if(fileSize > 0) {
+ if(fileSize != stream->Read( &data[0], 1, fileSize)) {
+ throw DeadlyImportError("File read error");
+ }
+
+ ConvertToUTF8(data);
+ }
+
+ // append a binary zero to simplify string parsing
+ data.push_back(0);
+}
+
+// ------------------------------------------------------------------------------------------------
+namespace Assimp {
+ // Represents an import request
+ struct LoadRequest {
+ LoadRequest(const std::string& _file, unsigned int _flags,const BatchLoader::PropertyMap* _map, unsigned int _id)
+ : file(_file)
+ , flags(_flags)
+ , refCnt(1)
+ , scene(NULL)
+ , loaded(false)
+ , id(_id) {
+ if ( _map ) {
+ map = *_map;
+ }
+ }
+
+ bool operator== ( const std::string& f ) const {
+ return file == f;
+ }
+
+ const std::string file;
+ unsigned int flags;
+ unsigned int refCnt;
+ aiScene *scene;
+ bool loaded;
+ BatchLoader::PropertyMap map;
+ unsigned int id;
+ };
+}
+
+// ------------------------------------------------------------------------------------------------
+// BatchLoader::pimpl data structure
+struct Assimp::BatchData {
+ BatchData( IOSystem* pIO, bool validate )
+ : pIOSystem( pIO )
+ , pImporter( nullptr )
+ , next_id(0xffff)
+ , validate( validate ) {
+ ai_assert( nullptr != pIO );
+
+ pImporter = new Importer();
+ pImporter->SetIOHandler( pIO );
+ }
+
+ ~BatchData() {
+ pImporter->SetIOHandler( nullptr ); /* get pointer back into our possession */
+ delete pImporter;
+ }
+
+ // IO system to be used for all imports
+ IOSystem* pIOSystem;
+
+ // Importer used to load all meshes
+ Importer* pImporter;
+
+ // List of all imports
+ std::list<LoadRequest> requests;
+
+ // Base path
+ std::string pathBase;
+
+ // Id for next item
+ unsigned int next_id;
+
+ // Validation enabled state
+ bool validate;
+};
+
+typedef std::list<LoadRequest>::iterator LoadReqIt;
+
+// ------------------------------------------------------------------------------------------------
+BatchLoader::BatchLoader(IOSystem* pIO, bool validate ) {
+ ai_assert(nullptr != pIO);
+
+ m_data = new BatchData( pIO, validate );
+}
+
+// ------------------------------------------------------------------------------------------------
+BatchLoader::~BatchLoader()
+{
+ // delete all scenes what have not been polled by the user
+ for ( LoadReqIt it = m_data->requests.begin();it != m_data->requests.end(); ++it) {
+ delete (*it).scene;
+ }
+ delete m_data;
+}
+
+// ------------------------------------------------------------------------------------------------
+void BatchLoader::setValidation( bool enabled ) {
+ m_data->validate = enabled;
+}
+
+// ------------------------------------------------------------------------------------------------
+bool BatchLoader::getValidation() const {
+ return m_data->validate;
+}
+
+// ------------------------------------------------------------------------------------------------
+unsigned int BatchLoader::AddLoadRequest(const std::string& file,
+ unsigned int steps /*= 0*/, const PropertyMap* map /*= NULL*/)
+{
+ ai_assert(!file.empty());
+
+ // check whether we have this loading request already
+ for ( LoadReqIt it = m_data->requests.begin();it != m_data->requests.end(); ++it) {
+ // Call IOSystem's path comparison function here
+ if ( m_data->pIOSystem->ComparePaths((*it).file,file)) {
+ if (map) {
+ if ( !( ( *it ).map == *map ) ) {
+ continue;
+ }
+ }
+ else if ( !( *it ).map.empty() ) {
+ continue;
+ }
+
+ (*it).refCnt++;
+ return (*it).id;
+ }
+ }
+
+ // no, we don't have it. So add it to the queue ...
+ m_data->requests.push_back(LoadRequest(file,steps,map, m_data->next_id));
+ return m_data->next_id++;
+}
+
+// ------------------------------------------------------------------------------------------------
+aiScene* BatchLoader::GetImport( unsigned int which )
+{
+ for ( LoadReqIt it = m_data->requests.begin();it != m_data->requests.end(); ++it) {
+ if ((*it).id == which && (*it).loaded) {
+ aiScene* sc = (*it).scene;
+ if (!(--(*it).refCnt)) {
+ m_data->requests.erase(it);
+ }
+ return sc;
+ }
+ }
+ return nullptr;
+}
+
+// ------------------------------------------------------------------------------------------------
+void BatchLoader::LoadAll()
+{
+ // no threaded implementation for the moment
+ for ( LoadReqIt it = m_data->requests.begin();it != m_data->requests.end(); ++it) {
+ // force validation in debug builds
+ unsigned int pp = (*it).flags;
+ if ( m_data->validate ) {
+ pp |= aiProcess_ValidateDataStructure;
+ }
+
+ // setup config properties if necessary
+ ImporterPimpl* pimpl = m_data->pImporter->Pimpl();
+ pimpl->mFloatProperties = (*it).map.floats;
+ pimpl->mIntProperties = (*it).map.ints;
+ pimpl->mStringProperties = (*it).map.strings;
+ pimpl->mMatrixProperties = (*it).map.matrices;
+
+ if (!DefaultLogger::isNullLogger())
+ {
+ ASSIMP_LOG_INFO("%%% BEGIN EXTERNAL FILE %%%");
+ ASSIMP_LOG_INFO_F("File: ", (*it).file);
+ }
+ m_data->pImporter->ReadFile((*it).file,pp);
+ (*it).scene = m_data->pImporter->GetOrphanedScene();
+ (*it).loaded = true;
+
+ ASSIMP_LOG_INFO("%%% END EXTERNAL FILE %%%");
+ }
+}
diff --git a/thirdparty/assimp/code/BaseProcess.cpp b/thirdparty/assimp/code/BaseProcess.cpp
new file mode 100644
index 0000000000..18872c3693
--- /dev/null
+++ b/thirdparty/assimp/code/BaseProcess.cpp
@@ -0,0 +1,107 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file Implementation of BaseProcess */
+
+#include <assimp/BaseImporter.h>
+#include "BaseProcess.h"
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/scene.h>
+#include "Importer.h"
+
+using namespace Assimp;
+
+// ------------------------------------------------------------------------------------------------
+// Constructor to be privately used by Importer
+BaseProcess::BaseProcess() AI_NO_EXCEPT
+: shared()
+, progress()
+{
+}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor, private as well
+BaseProcess::~BaseProcess()
+{
+ // nothing to do here
+}
+
+// ------------------------------------------------------------------------------------------------
+void BaseProcess::ExecuteOnScene( Importer* pImp)
+{
+ ai_assert(NULL != pImp && NULL != pImp->Pimpl()->mScene);
+
+ progress = pImp->GetProgressHandler();
+ ai_assert(progress);
+
+ SetupProperties( pImp );
+
+ // catch exceptions thrown inside the PostProcess-Step
+ try
+ {
+ Execute(pImp->Pimpl()->mScene);
+
+ } catch( const std::exception& err ) {
+
+ // extract error description
+ pImp->Pimpl()->mErrorString = err.what();
+ ASSIMP_LOG_ERROR(pImp->Pimpl()->mErrorString);
+
+ // and kill the partially imported data
+ delete pImp->Pimpl()->mScene;
+ pImp->Pimpl()->mScene = NULL;
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+void BaseProcess::SetupProperties(const Importer* /*pImp*/)
+{
+ // the default implementation does nothing
+}
+
+// ------------------------------------------------------------------------------------------------
+bool BaseProcess::RequireVerboseFormat() const
+{
+ return true;
+}
+
diff --git a/thirdparty/assimp/code/BaseProcess.h b/thirdparty/assimp/code/BaseProcess.h
new file mode 100644
index 0000000000..4d5c7a76be
--- /dev/null
+++ b/thirdparty/assimp/code/BaseProcess.h
@@ -0,0 +1,290 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file Base class of all import post processing steps */
+#ifndef INCLUDED_AI_BASEPROCESS_H
+#define INCLUDED_AI_BASEPROCESS_H
+
+#include <map>
+#include <assimp/GenericProperty.h>
+
+struct aiScene;
+
+namespace Assimp {
+
+class Importer;
+
+// ---------------------------------------------------------------------------
+/** Helper class to allow post-processing steps to interact with each other.
+ *
+ * The class maintains a simple property list that can be used by pp-steps
+ * to provide additional information to other steps. This is primarily
+ * intended for cross-step optimizations.
+ */
+class SharedPostProcessInfo
+{
+public:
+
+ struct Base
+ {
+ virtual ~Base()
+ {}
+ };
+
+ //! Represents data that is allocated on the heap, thus needs to be deleted
+ template <typename T>
+ struct THeapData : public Base
+ {
+ explicit THeapData(T* in)
+ : data (in)
+ {}
+
+ ~THeapData()
+ {
+ delete data;
+ }
+ T* data;
+ };
+
+ //! Represents static, by-value data not allocated on the heap
+ template <typename T>
+ struct TStaticData : public Base
+ {
+ explicit TStaticData(T in)
+ : data (in)
+ {}
+
+ ~TStaticData()
+ {}
+
+ T data;
+ };
+
+ // some typedefs for cleaner code
+ typedef unsigned int KeyType;
+ typedef std::map<KeyType, Base*> PropertyMap;
+
+public:
+
+ //! Destructor
+ ~SharedPostProcessInfo()
+ {
+ Clean();
+ }
+
+ //! Remove all stored properties from the table
+ void Clean()
+ {
+ // invoke the virtual destructor for all stored properties
+ for (PropertyMap::iterator it = pmap.begin(), end = pmap.end();
+ it != end; ++it)
+ {
+ delete (*it).second;
+ }
+ pmap.clear();
+ }
+
+ //! Add a heap property to the list
+ template <typename T>
+ void AddProperty( const char* name, T* in ){
+ AddProperty(name,(Base*)new THeapData<T>(in));
+ }
+
+ //! Add a static by-value property to the list
+ template <typename T>
+ void AddProperty( const char* name, T in ){
+ AddProperty(name,(Base*)new TStaticData<T>(in));
+ }
+
+
+ //! Get a heap property
+ template <typename T>
+ bool GetProperty( const char* name, T*& out ) const
+ {
+ THeapData<T>* t = (THeapData<T>*)GetPropertyInternal(name);
+ if(!t)
+ {
+ out = NULL;
+ return false;
+ }
+ out = t->data;
+ return true;
+ }
+
+ //! Get a static, by-value property
+ template <typename T>
+ bool GetProperty( const char* name, T& out ) const
+ {
+ TStaticData<T>* t = (TStaticData<T>*)GetPropertyInternal(name);
+ if(!t)return false;
+ out = t->data;
+ return true;
+ }
+
+ //! Remove a property of a specific type
+ void RemoveProperty( const char* name) {
+ SetGenericPropertyPtr<Base>(pmap,name,NULL);
+ }
+
+private:
+
+ void AddProperty( const char* name, Base* data) {
+ SetGenericPropertyPtr<Base>(pmap,name,data);
+ }
+
+ Base* GetPropertyInternal( const char* name) const {
+ return GetGenericProperty<Base*>(pmap,name,NULL);
+ }
+
+private:
+
+ //! Map of all stored properties
+ PropertyMap pmap;
+};
+
+#if 0
+
+// ---------------------------------------------------------------------------
+/** @brief Represents a dependency table for a postprocessing steps.
+ *
+ * For future use.
+ */
+ struct PPDependencyTable
+ {
+ unsigned int execute_me_before_these;
+ unsigned int execute_me_after_these;
+ unsigned int only_if_these_are_not_specified;
+ unsigned int mutually_exclusive_with;
+ };
+
+#endif
+
+
+#define AI_SPP_SPATIAL_SORT "$Spat"
+
+// ---------------------------------------------------------------------------
+/** The BaseProcess defines a common interface for all post processing steps.
+ * A post processing step is run after a successful import if the caller
+ * specified the corresponding flag when calling ReadFile().
+ * Enum #aiPostProcessSteps defines which flags are available.
+ * After a successful import the Importer iterates over its internal array
+ * of processes and calls IsActive() on each process to evaluate if the step
+ * should be executed. If the function returns true, the class' Execute()
+ * function is called subsequently.
+ */
+class ASSIMP_API_WINONLY BaseProcess {
+ friend class Importer;
+
+public:
+ /** Constructor to be privately used by Importer */
+ BaseProcess() AI_NO_EXCEPT;
+
+ /** Destructor, private as well */
+ virtual ~BaseProcess();
+
+ // -------------------------------------------------------------------
+ /** Returns whether the processing step is present in the given flag.
+ * @param pFlags The processing flags the importer was called with. A
+ * bitwise combination of #aiPostProcessSteps.
+ * @return true if the process is present in this flag fields,
+ * false if not.
+ */
+ virtual bool IsActive( unsigned int pFlags) const = 0;
+
+ // -------------------------------------------------------------------
+ /** Check whether this step expects its input vertex data to be
+ * in verbose format. */
+ virtual bool RequireVerboseFormat() const;
+
+ // -------------------------------------------------------------------
+ /** Executes the post processing step on the given imported data.
+ * The function deletes the scene if the postprocess step fails (
+ * the object pointer will be set to NULL).
+ * @param pImp Importer instance (pImp->mScene must be valid)
+ */
+ void ExecuteOnScene( Importer* pImp);
+
+ // -------------------------------------------------------------------
+ /** Called prior to ExecuteOnScene().
+ * The function is a request to the process to update its configuration
+ * basing on the Importer's configuration property list.
+ */
+ virtual void SetupProperties(const Importer* pImp);
+
+ // -------------------------------------------------------------------
+ /** Executes the post processing step on the given imported data.
+ * A process should throw an ImportErrorException* if it fails.
+ * This method must be implemented by deriving classes.
+ * @param pScene The imported data to work at.
+ */
+ virtual void Execute( aiScene* pScene) = 0;
+
+
+ // -------------------------------------------------------------------
+ /** Assign a new SharedPostProcessInfo to the step. This object
+ * allows multiple postprocess steps to share data.
+ * @param sh May be NULL
+ */
+ inline void SetSharedData(SharedPostProcessInfo* sh) {
+ shared = sh;
+ }
+
+ // -------------------------------------------------------------------
+ /** Get the shared data that is assigned to the step.
+ */
+ inline SharedPostProcessInfo* GetSharedData() {
+ return shared;
+ }
+
+protected:
+
+ /** See the doc of #SharedPostProcessInfo for more details */
+ SharedPostProcessInfo* shared;
+
+ /** Currently active progress handler */
+ ProgressHandler* progress;
+};
+
+
+} // end of namespace Assimp
+
+#endif // AI_BASEPROCESS_H_INC
diff --git a/thirdparty/assimp/code/Bitmap.cpp b/thirdparty/assimp/code/Bitmap.cpp
new file mode 100644
index 0000000000..b22b71ea9e
--- /dev/null
+++ b/thirdparty/assimp/code/Bitmap.cpp
@@ -0,0 +1,155 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file Bitmap.cpp
+ * @brief Defines bitmap format helper for textures
+ *
+ * Used for file formats which embed their textures into the model file.
+ */
+
+
+#include <assimp/Bitmap.h>
+#include <assimp/texture.h>
+#include <assimp/IOStream.hpp>
+#include <assimp/ByteSwapper.h>
+
+namespace Assimp {
+
+ void Bitmap::Save(aiTexture* texture, IOStream* file) {
+ if(file != NULL) {
+ Header header;
+ DIB dib;
+
+ dib.size = DIB::dib_size;
+ dib.width = texture->mWidth;
+ dib.height = texture->mHeight;
+ dib.planes = 1;
+ dib.bits_per_pixel = 8 * mBytesPerPixel;
+ dib.compression = 0;
+ dib.image_size = (((dib.width * mBytesPerPixel) + 3) & 0x0000FFFC) * dib.height;
+ dib.x_resolution = 0;
+ dib.y_resolution = 0;
+ dib.nb_colors = 0;
+ dib.nb_important_colors = 0;
+
+ header.type = 0x4D42; // 'BM'
+ header.offset = Header::header_size + DIB::dib_size;
+ header.size = header.offset + dib.image_size;
+ header.reserved1 = 0;
+ header.reserved2 = 0;
+
+ WriteHeader(header, file);
+ WriteDIB(dib, file);
+ WriteData(texture, file);
+ }
+ }
+
+ template<typename T>
+ inline
+ std::size_t Copy(uint8_t* data, const T &field) {
+#ifdef AI_BUILD_BIG_ENDIAN
+ T field_swapped=AI_BE(field);
+ std::memcpy(data, &field_swapped, sizeof(field)); return sizeof(field);
+#else
+ std::memcpy(data, &AI_BE(field), sizeof(field)); return sizeof(field);
+#endif
+ }
+
+ void Bitmap::WriteHeader(Header& header, IOStream* file) {
+ uint8_t data[Header::header_size];
+
+ std::size_t offset = 0;
+
+ offset += Copy(&data[offset], header.type);
+ offset += Copy(&data[offset], header.size);
+ offset += Copy(&data[offset], header.reserved1);
+ offset += Copy(&data[offset], header.reserved2);
+ Copy(&data[offset], header.offset);
+
+ file->Write(data, Header::header_size, 1);
+ }
+
+ void Bitmap::WriteDIB(DIB& dib, IOStream* file) {
+ uint8_t data[DIB::dib_size];
+
+ std::size_t offset = 0;
+
+ offset += Copy(&data[offset], dib.size);
+ offset += Copy(&data[offset], dib.width);
+ offset += Copy(&data[offset], dib.height);
+ offset += Copy(&data[offset], dib.planes);
+ offset += Copy(&data[offset], dib.bits_per_pixel);
+ offset += Copy(&data[offset], dib.compression);
+ offset += Copy(&data[offset], dib.image_size);
+ offset += Copy(&data[offset], dib.x_resolution);
+ offset += Copy(&data[offset], dib.y_resolution);
+ offset += Copy(&data[offset], dib.nb_colors);
+ Copy(&data[offset], dib.nb_important_colors);
+
+ file->Write(data, DIB::dib_size, 1);
+ }
+
+ void Bitmap::WriteData(aiTexture* texture, IOStream* file) {
+ static const std::size_t padding_offset = 4;
+ static const uint8_t padding_data[padding_offset] = {0x0, 0x0, 0x0, 0x0};
+
+ unsigned int padding = (padding_offset - ((mBytesPerPixel * texture->mWidth) % padding_offset)) % padding_offset;
+ uint8_t pixel[mBytesPerPixel];
+
+ for(std::size_t i = 0; i < texture->mHeight; ++i) {
+ for(std::size_t j = 0; j < texture->mWidth; ++j) {
+ const aiTexel& texel = texture->pcData[(texture->mHeight - i - 1) * texture->mWidth + j]; // Bitmap files are stored in bottom-up format
+
+ pixel[0] = texel.r;
+ pixel[1] = texel.g;
+ pixel[2] = texel.b;
+ pixel[3] = texel.a;
+
+ file->Write(pixel, mBytesPerPixel, 1);
+ }
+
+ file->Write(padding_data, padding, 1);
+ }
+ }
+
+}
diff --git a/thirdparty/assimp/code/CInterfaceIOWrapper.cpp b/thirdparty/assimp/code/CInterfaceIOWrapper.cpp
new file mode 100644
index 0000000000..5a3a49565a
--- /dev/null
+++ b/thirdparty/assimp/code/CInterfaceIOWrapper.cpp
@@ -0,0 +1,136 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file aiFileIO -> IOSystem wrapper*/
+
+#include "CInterfaceIOWrapper.h"
+
+namespace Assimp {
+
+CIOStreamWrapper::~CIOStreamWrapper(void)
+{
+ /* Various places depend on this destructor to close the file */
+ if (mFile) {
+ mIO->mFileSystem->CloseProc(mIO->mFileSystem, mFile);
+ mFile = nullptr;
+ }
+}
+
+// ...................................................................
+size_t CIOStreamWrapper::Read(void* pvBuffer,
+ size_t pSize,
+ size_t pCount
+){
+ // need to typecast here as C has no void*
+ return mFile->ReadProc(mFile,(char*)pvBuffer,pSize,pCount);
+}
+
+// ...................................................................
+size_t CIOStreamWrapper::Write(const void* pvBuffer,
+ size_t pSize,
+ size_t pCount
+){
+ // need to typecast here as C has no void*
+ return mFile->WriteProc(mFile,(const char*)pvBuffer,pSize,pCount);
+}
+
+// ...................................................................
+aiReturn CIOStreamWrapper::Seek(size_t pOffset,
+ aiOrigin pOrigin
+){
+ return mFile->SeekProc(mFile,pOffset,pOrigin);
+}
+
+// ...................................................................
+size_t CIOStreamWrapper::Tell(void) const {
+ return mFile->TellProc(mFile);
+}
+
+// ...................................................................
+size_t CIOStreamWrapper::FileSize() const {
+ return mFile->FileSizeProc(mFile);
+}
+
+// ...................................................................
+void CIOStreamWrapper::Flush () {
+ return mFile->FlushProc(mFile);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Custom IOStream implementation for the C-API
+bool CIOSystemWrapper::Exists( const char* pFile) const {
+ aiFile* p = mFileSystem->OpenProc(mFileSystem,pFile,"rb");
+ if (p){
+ mFileSystem->CloseProc(mFileSystem,p);
+ return true;
+ }
+ return false;
+}
+
+// ...................................................................
+char CIOSystemWrapper::getOsSeparator() const {
+#ifndef _WIN32
+ return '/';
+#else
+ return '\\';
+#endif
+}
+
+// ...................................................................
+IOStream* CIOSystemWrapper::Open(const char* pFile,const char* pMode) {
+ aiFile* p = mFileSystem->OpenProc(mFileSystem,pFile,pMode);
+ if (!p) {
+ return NULL;
+ }
+ return new CIOStreamWrapper(p, this);
+}
+
+// ...................................................................
+void CIOSystemWrapper::Close( IOStream* pFile) {
+ if (!pFile) {
+ return;
+ }
+ delete pFile;
+}
+
+}
diff --git a/thirdparty/assimp/code/CInterfaceIOWrapper.h b/thirdparty/assimp/code/CInterfaceIOWrapper.h
new file mode 100644
index 0000000000..2162320302
--- /dev/null
+++ b/thirdparty/assimp/code/CInterfaceIOWrapper.h
@@ -0,0 +1,99 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file aiFileIO -> IOSystem wrapper*/
+
+#ifndef AI_CIOSYSTEM_H_INCLUDED
+#define AI_CIOSYSTEM_H_INCLUDED
+
+#include <assimp/cfileio.h>
+#include <assimp/IOStream.hpp>
+#include <assimp/IOSystem.hpp>
+
+namespace Assimp {
+
+class CIOSystemWrapper;
+
+// ------------------------------------------------------------------------------------------------
+// Custom IOStream implementation for the C-API
+class CIOStreamWrapper : public IOStream
+{
+public:
+ explicit CIOStreamWrapper(aiFile* pFile, CIOSystemWrapper* io)
+ : mFile(pFile),
+ mIO(io)
+ {}
+ ~CIOStreamWrapper(void);
+
+ size_t Read(void* pvBuffer, size_t pSize, size_t pCount);
+ size_t Write(const void* pvBuffer, size_t pSize, size_t pCount);
+ aiReturn Seek(size_t pOffset, aiOrigin pOrigin);
+ size_t Tell(void) const;
+ size_t FileSize() const;
+ void Flush();
+
+private:
+ aiFile* mFile;
+ CIOSystemWrapper* mIO;
+};
+
+class CIOSystemWrapper : public IOSystem
+{
+ friend class CIOStreamWrapper;
+public:
+ explicit CIOSystemWrapper(aiFileIO* pFile)
+ : mFileSystem(pFile)
+ {}
+
+ bool Exists( const char* pFile) const;
+ char getOsSeparator() const;
+ IOStream* Open(const char* pFile,const char* pMode = "rb");
+ void Close( IOStream* pFile);
+private:
+ aiFileIO* mFileSystem;
+};
+
+}
+
+#endif
+
diff --git a/thirdparty/assimp/code/CalcTangentsProcess.cpp b/thirdparty/assimp/code/CalcTangentsProcess.cpp
new file mode 100644
index 0000000000..b30f39c274
--- /dev/null
+++ b/thirdparty/assimp/code/CalcTangentsProcess.cpp
@@ -0,0 +1,319 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file Implementation of the post processing step to calculate
+ * tangents and bitangents for all imported meshes
+ */
+
+// internal headers
+#include "CalcTangentsProcess.h"
+#include "ProcessHelper.h"
+#include <assimp/TinyFormatter.h>
+#include <assimp/qnan.h>
+
+using namespace Assimp;
+
+// ------------------------------------------------------------------------------------------------
+// Constructor to be privately used by Importer
+CalcTangentsProcess::CalcTangentsProcess()
+: configMaxAngle( AI_DEG_TO_RAD(45.f) )
+, configSourceUV( 0 ) {
+ // nothing to do here
+}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor, private as well
+CalcTangentsProcess::~CalcTangentsProcess()
+{
+ // nothing to do here
+}
+
+// ------------------------------------------------------------------------------------------------
+// Returns whether the processing step is present in the given flag field.
+bool CalcTangentsProcess::IsActive( unsigned int pFlags) const
+{
+ return (pFlags & aiProcess_CalcTangentSpace) != 0;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+void CalcTangentsProcess::SetupProperties(const Importer* pImp)
+{
+ ai_assert( NULL != pImp );
+
+ // get the current value of the property
+ configMaxAngle = pImp->GetPropertyFloat(AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE,45.f);
+ configMaxAngle = std::max(std::min(configMaxAngle,45.0f),0.0f);
+ configMaxAngle = AI_DEG_TO_RAD(configMaxAngle);
+
+ configSourceUV = pImp->GetPropertyInteger(AI_CONFIG_PP_CT_TEXTURE_CHANNEL_INDEX,0);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+void CalcTangentsProcess::Execute( aiScene* pScene)
+{
+ ai_assert( NULL != pScene );
+
+ ASSIMP_LOG_DEBUG("CalcTangentsProcess begin");
+
+ bool bHas = false;
+ for ( unsigned int a = 0; a < pScene->mNumMeshes; a++ ) {
+ if(ProcessMesh( pScene->mMeshes[a],a))bHas = true;
+ }
+
+ if ( bHas ) {
+ ASSIMP_LOG_INFO("CalcTangentsProcess finished. Tangents have been calculated");
+ } else {
+ ASSIMP_LOG_DEBUG("CalcTangentsProcess finished");
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Calculates tangents and bi-tangents for the given mesh
+bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
+{
+ // we assume that the mesh is still in the verbose vertex format where each face has its own set
+ // of vertices and no vertices are shared between faces. Sadly I don't know any quick test to
+ // assert() it here.
+ // assert( must be verbose, dammit);
+
+ if (pMesh->mTangents) // this implies that mBitangents is also there
+ return false;
+
+ // If the mesh consists of lines and/or points but not of
+ // triangles or higher-order polygons the normal vectors
+ // are undefined.
+ if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON)))
+ {
+ ASSIMP_LOG_INFO("Tangents are undefined for line and point meshes");
+ return false;
+ }
+
+ // what we can check, though, is if the mesh has normals and texture coordinates. That's a requirement
+ if( pMesh->mNormals == NULL)
+ {
+ ASSIMP_LOG_ERROR("Failed to compute tangents; need normals");
+ return false;
+ }
+ if( configSourceUV >= AI_MAX_NUMBER_OF_TEXTURECOORDS || !pMesh->mTextureCoords[configSourceUV] )
+ {
+ ASSIMP_LOG_ERROR((Formatter::format("Failed to compute tangents; need UV data in channel"),configSourceUV));
+ return false;
+ }
+
+ const float angleEpsilon = 0.9999f;
+
+ std::vector<bool> vertexDone( pMesh->mNumVertices, false);
+ const float qnan = get_qnan();
+
+ // create space for the tangents and bitangents
+ pMesh->mTangents = new aiVector3D[pMesh->mNumVertices];
+ pMesh->mBitangents = new aiVector3D[pMesh->mNumVertices];
+
+ const aiVector3D* meshPos = pMesh->mVertices;
+ const aiVector3D* meshNorm = pMesh->mNormals;
+ const aiVector3D* meshTex = pMesh->mTextureCoords[configSourceUV];
+ aiVector3D* meshTang = pMesh->mTangents;
+ aiVector3D* meshBitang = pMesh->mBitangents;
+
+ // calculate the tangent and bitangent for every face
+ for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
+ {
+ const aiFace& face = pMesh->mFaces[a];
+ if (face.mNumIndices < 3)
+ {
+ // There are less than three indices, thus the tangent vector
+ // is not defined. We are finished with these vertices now,
+ // their tangent vectors are set to qnan.
+ for (unsigned int i = 0; i < face.mNumIndices;++i)
+ {
+ unsigned int idx = face.mIndices[i];
+ vertexDone [idx] = true;
+ meshTang [idx] = aiVector3D(qnan);
+ meshBitang [idx] = aiVector3D(qnan);
+ }
+
+ continue;
+ }
+
+ // triangle or polygon... we always use only the first three indices. A polygon
+ // is supposed to be planar anyways....
+ // FIXME: (thom) create correct calculation for multi-vertex polygons maybe?
+ const unsigned int p0 = face.mIndices[0], p1 = face.mIndices[1], p2 = face.mIndices[2];
+
+ // position differences p1->p2 and p1->p3
+ aiVector3D v = meshPos[p1] - meshPos[p0], w = meshPos[p2] - meshPos[p0];
+
+ // texture offset p1->p2 and p1->p3
+ float sx = meshTex[p1].x - meshTex[p0].x, sy = meshTex[p1].y - meshTex[p0].y;
+ float tx = meshTex[p2].x - meshTex[p0].x, ty = meshTex[p2].y - meshTex[p0].y;
+ float dirCorrection = (tx * sy - ty * sx) < 0.0f ? -1.0f : 1.0f;
+ // when t1, t2, t3 in same position in UV space, just use default UV direction.
+ if ( sx * ty == sy * tx ) {
+ sx = 0.0; sy = 1.0;
+ tx = 1.0; ty = 0.0;
+ }
+
+ // tangent points in the direction where to positive X axis of the texture coord's would point in model space
+ // bitangent's points along the positive Y axis of the texture coord's, respectively
+ aiVector3D tangent, bitangent;
+ tangent.x = (w.x * sy - v.x * ty) * dirCorrection;
+ tangent.y = (w.y * sy - v.y * ty) * dirCorrection;
+ tangent.z = (w.z * sy - v.z * ty) * dirCorrection;
+ bitangent.x = (w.x * sx - v.x * tx) * dirCorrection;
+ bitangent.y = (w.y * sx - v.y * tx) * dirCorrection;
+ bitangent.z = (w.z * sx - v.z * tx) * dirCorrection;
+
+ // store for every vertex of that face
+ for( unsigned int b = 0; b < face.mNumIndices; ++b ) {
+ unsigned int p = face.mIndices[b];
+
+ // project tangent and bitangent into the plane formed by the vertex' normal
+ aiVector3D localTangent = tangent - meshNorm[p] * (tangent * meshNorm[p]);
+ aiVector3D localBitangent = bitangent - meshNorm[p] * (bitangent * meshNorm[p]);
+ localTangent.Normalize(); localBitangent.Normalize();
+
+ // reconstruct tangent/bitangent according to normal and bitangent/tangent when it's infinite or NaN.
+ bool invalid_tangent = is_special_float(localTangent.x) || is_special_float(localTangent.y) || is_special_float(localTangent.z);
+ bool invalid_bitangent = is_special_float(localBitangent.x) || is_special_float(localBitangent.y) || is_special_float(localBitangent.z);
+ if (invalid_tangent != invalid_bitangent) {
+ if (invalid_tangent) {
+ localTangent = meshNorm[p] ^ localBitangent;
+ localTangent.Normalize();
+ } else {
+ localBitangent = localTangent ^ meshNorm[p];
+ localBitangent.Normalize();
+ }
+ }
+
+ // and write it into the mesh.
+ meshTang[ p ] = localTangent;
+ meshBitang[ p ] = localBitangent;
+ }
+ }
+
+
+ // create a helper to quickly find locally close vertices among the vertex array
+ // FIX: check whether we can reuse the SpatialSort of a previous step
+ SpatialSort* vertexFinder = NULL;
+ SpatialSort _vertexFinder;
+ float posEpsilon;
+ if (shared)
+ {
+ std::vector<std::pair<SpatialSort,float> >* avf;
+ shared->GetProperty(AI_SPP_SPATIAL_SORT,avf);
+ if (avf)
+ {
+ std::pair<SpatialSort,float>& blubb = avf->operator [] (meshIndex);
+ vertexFinder = &blubb.first;
+ posEpsilon = blubb.second;;
+ }
+ }
+ if (!vertexFinder)
+ {
+ _vertexFinder.Fill(pMesh->mVertices, pMesh->mNumVertices, sizeof( aiVector3D));
+ vertexFinder = &_vertexFinder;
+ posEpsilon = ComputePositionEpsilon(pMesh);
+ }
+ std::vector<unsigned int> verticesFound;
+
+ const float fLimit = std::cos(configMaxAngle);
+ std::vector<unsigned int> closeVertices;
+
+ // in the second pass we now smooth out all tangents and bitangents at the same local position
+ // if they are not too far off.
+ for( unsigned int a = 0; a < pMesh->mNumVertices; a++)
+ {
+ if( vertexDone[a])
+ continue;
+
+ const aiVector3D& origPos = pMesh->mVertices[a];
+ const aiVector3D& origNorm = pMesh->mNormals[a];
+ const aiVector3D& origTang = pMesh->mTangents[a];
+ const aiVector3D& origBitang = pMesh->mBitangents[a];
+ closeVertices.resize( 0 );
+
+ // find all vertices close to that position
+ vertexFinder->FindPositions( origPos, posEpsilon, verticesFound);
+
+ closeVertices.reserve (verticesFound.size()+5);
+ closeVertices.push_back( a);
+
+ // look among them for other vertices sharing the same normal and a close-enough tangent/bitangent
+ for( unsigned int b = 0; b < verticesFound.size(); b++)
+ {
+ unsigned int idx = verticesFound[b];
+ if( vertexDone[idx])
+ continue;
+ if( meshNorm[idx] * origNorm < angleEpsilon)
+ continue;
+ if( meshTang[idx] * origTang < fLimit)
+ continue;
+ if( meshBitang[idx] * origBitang < fLimit)
+ continue;
+
+ // it's similar enough -> add it to the smoothing group
+ closeVertices.push_back( idx);
+ vertexDone[idx] = true;
+ }
+
+ // smooth the tangents and bitangents of all vertices that were found to be close enough
+ aiVector3D smoothTangent( 0, 0, 0), smoothBitangent( 0, 0, 0);
+ for( unsigned int b = 0; b < closeVertices.size(); ++b)
+ {
+ smoothTangent += meshTang[ closeVertices[b] ];
+ smoothBitangent += meshBitang[ closeVertices[b] ];
+ }
+ smoothTangent.Normalize();
+ smoothBitangent.Normalize();
+
+ // and write it back into all affected tangents
+ for( unsigned int b = 0; b < closeVertices.size(); ++b)
+ {
+ meshTang[ closeVertices[b] ] = smoothTangent;
+ meshBitang[ closeVertices[b] ] = smoothBitangent;
+ }
+ }
+ return true;
+}
diff --git a/thirdparty/assimp/code/CalcTangentsProcess.h b/thirdparty/assimp/code/CalcTangentsProcess.h
new file mode 100644
index 0000000000..18775abcc7
--- /dev/null
+++ b/thirdparty/assimp/code/CalcTangentsProcess.h
@@ -0,0 +1,117 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+
+/** @file Defines a post processing step to calculate tangents and
+ bitangents on all imported meshes.*/
+#ifndef AI_CALCTANGENTSPROCESS_H_INC
+#define AI_CALCTANGENTSPROCESS_H_INC
+
+#include "BaseProcess.h"
+
+struct aiMesh;
+
+namespace Assimp
+{
+
+// ---------------------------------------------------------------------------
+/** The CalcTangentsProcess calculates the tangent and bitangent for any vertex
+ * of all meshes. It is expected to be run before the JoinVerticesProcess runs
+ * because the joining of vertices also considers tangents and bitangents for
+ * uniqueness.
+ */
+class ASSIMP_API_WINONLY CalcTangentsProcess : public BaseProcess
+{
+public:
+
+ CalcTangentsProcess();
+ ~CalcTangentsProcess();
+
+public:
+ // -------------------------------------------------------------------
+ /** Returns whether the processing step is present in the given flag.
+ * @param pFlags The processing flags the importer was called with.
+ * A bitwise combination of #aiPostProcessSteps.
+ * @return true if the process is present in this flag fields,
+ * false if not.
+ */
+ bool IsActive( unsigned int pFlags) const;
+
+ // -------------------------------------------------------------------
+ /** Called prior to ExecuteOnScene().
+ * The function is a request to the process to update its configuration
+ * basing on the Importer's configuration property list.
+ */
+ void SetupProperties(const Importer* pImp);
+
+
+ // setter for configMaxAngle
+ inline void SetMaxSmoothAngle(float f)
+ {
+ configMaxAngle =f;
+ }
+
+protected:
+
+ // -------------------------------------------------------------------
+ /** Calculates tangents and bitangents for a specific mesh.
+ * @param pMesh The mesh to process.
+ * @param meshIndex Index of the mesh
+ */
+ bool ProcessMesh( aiMesh* pMesh, unsigned int meshIndex);
+
+ // -------------------------------------------------------------------
+ /** Executes the post processing step on the given imported data.
+ * @param pScene The imported data to work at.
+ */
+ void Execute( aiScene* pScene);
+
+private:
+
+ /** Configuration option: maximum smoothing angle, in radians*/
+ float configMaxAngle;
+ unsigned int configSourceUV;
+};
+
+} // end of namespace Assimp
+
+#endif // AI_CALCTANGENTSPROCESS_H_INC
diff --git a/thirdparty/assimp/code/ComputeUVMappingProcess.cpp b/thirdparty/assimp/code/ComputeUVMappingProcess.cpp
new file mode 100644
index 0000000000..bb571a551b
--- /dev/null
+++ b/thirdparty/assimp/code/ComputeUVMappingProcess.cpp
@@ -0,0 +1,506 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file GenUVCoords step */
+
+
+#include "ComputeUVMappingProcess.h"
+#include "ProcessHelper.h"
+#include <assimp/Exceptional.h>
+
+using namespace Assimp;
+
+namespace {
+
+ const static aiVector3D base_axis_y(0.0,1.0,0.0);
+ const static aiVector3D base_axis_x(1.0,0.0,0.0);
+ const static aiVector3D base_axis_z(0.0,0.0,1.0);
+ const static ai_real angle_epsilon = ai_real( 0.95 );
+}
+
+// ------------------------------------------------------------------------------------------------
+// Constructor to be privately used by Importer
+ComputeUVMappingProcess::ComputeUVMappingProcess()
+{
+ // nothing to do here
+}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor, private as well
+ComputeUVMappingProcess::~ComputeUVMappingProcess()
+{
+ // nothing to do here
+}
+
+// ------------------------------------------------------------------------------------------------
+// Returns whether the processing step is present in the given flag field.
+bool ComputeUVMappingProcess::IsActive( unsigned int pFlags) const
+{
+ return (pFlags & aiProcess_GenUVCoords) != 0;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Check whether a ray intersects a plane and find the intersection point
+inline bool PlaneIntersect(const aiRay& ray, const aiVector3D& planePos,
+ const aiVector3D& planeNormal, aiVector3D& pos)
+{
+ const ai_real b = planeNormal * (planePos - ray.pos);
+ ai_real h = ray.dir * planeNormal;
+ if ((h < 10e-5 && h > -10e-5) || (h = b/h) < 0)
+ return false;
+
+ pos = ray.pos + (ray.dir * h);
+ return true;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Find the first empty UV channel in a mesh
+inline unsigned int FindEmptyUVChannel (aiMesh* mesh)
+{
+ for (unsigned int m = 0; m < AI_MAX_NUMBER_OF_TEXTURECOORDS;++m)
+ if (!mesh->mTextureCoords[m])return m;
+
+ ASSIMP_LOG_ERROR("Unable to compute UV coordinates, no free UV slot found");
+ return UINT_MAX;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Try to remove UV seams
+void RemoveUVSeams (aiMesh* mesh, aiVector3D* out)
+{
+ // TODO: just a very rough algorithm. I think it could be done
+ // much easier, but I don't know how and am currently too tired to
+ // to think about a better solution.
+
+ const static ai_real LOWER_LIMIT = ai_real( 0.1 );
+ const static ai_real UPPER_LIMIT = ai_real( 0.9 );
+
+ const static ai_real LOWER_EPSILON = ai_real( 10e-3 );
+ const static ai_real UPPER_EPSILON = ai_real( 1.0-10e-3 );
+
+ for (unsigned int fidx = 0; fidx < mesh->mNumFaces;++fidx)
+ {
+ const aiFace& face = mesh->mFaces[fidx];
+ if (face.mNumIndices < 3) continue; // triangles and polygons only, please
+
+ unsigned int small = face.mNumIndices, large = small;
+ bool zero = false, one = false, round_to_zero = false;
+
+ // Check whether this face lies on a UV seam. We can just guess,
+ // but the assumption that a face with at least one very small
+ // on the one side and one very large U coord on the other side
+ // lies on a UV seam should work for most cases.
+ for (unsigned int n = 0; n < face.mNumIndices;++n)
+ {
+ if (out[face.mIndices[n]].x < LOWER_LIMIT)
+ {
+ small = n;
+
+ // If we have a U value very close to 0 we can't
+ // round the others to 0, too.
+ if (out[face.mIndices[n]].x <= LOWER_EPSILON)
+ zero = true;
+ else round_to_zero = true;
+ }
+ if (out[face.mIndices[n]].x > UPPER_LIMIT)
+ {
+ large = n;
+
+ // If we have a U value very close to 1 we can't
+ // round the others to 1, too.
+ if (out[face.mIndices[n]].x >= UPPER_EPSILON)
+ one = true;
+ }
+ }
+ if (small != face.mNumIndices && large != face.mNumIndices)
+ {
+ for (unsigned int n = 0; n < face.mNumIndices;++n)
+ {
+ // If the u value is over the upper limit and no other u
+ // value of that face is 0, round it to 0
+ if (out[face.mIndices[n]].x > UPPER_LIMIT && !zero)
+ out[face.mIndices[n]].x = 0.0;
+
+ // If the u value is below the lower limit and no other u
+ // value of that face is 1, round it to 1
+ else if (out[face.mIndices[n]].x < LOWER_LIMIT && !one)
+ out[face.mIndices[n]].x = 1.0;
+
+ // The face contains both 0 and 1 as UV coords. This can occur
+ // for faces which have an edge that lies directly on the seam.
+ // Due to numerical inaccuracies one U coord becomes 0, the
+ // other 1. But we do still have a third UV coord to determine
+ // to which side we must round to.
+ else if (one && zero)
+ {
+ if (round_to_zero && out[face.mIndices[n]].x >= UPPER_EPSILON)
+ out[face.mIndices[n]].x = 0.0;
+ else if (!round_to_zero && out[face.mIndices[n]].x <= LOWER_EPSILON)
+ out[face.mIndices[n]].x = 1.0;
+ }
+ }
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+void ComputeUVMappingProcess::ComputeSphereMapping(aiMesh* mesh,const aiVector3D& axis, aiVector3D* out)
+{
+ aiVector3D center, min, max;
+ FindMeshCenter(mesh, center, min, max);
+
+ // If the axis is one of x,y,z run a faster code path. It's worth the extra effort ...
+ // currently the mapping axis will always be one of x,y,z, except if the
+ // PretransformVertices step is used (it transforms the meshes into worldspace,
+ // thus changing the mapping axis)
+ if (axis * base_axis_x >= angle_epsilon) {
+
+ // For each point get a normalized projection vector in the sphere,
+ // get its longitude and latitude and map them to their respective
+ // UV axes. Problems occur around the poles ... unsolvable.
+ //
+ // The spherical coordinate system looks like this:
+ // x = cos(lon)*cos(lat)
+ // y = sin(lon)*cos(lat)
+ // z = sin(lat)
+ //
+ // Thus we can derive:
+ // lat = arcsin (z)
+ // lon = arctan (y/x)
+ for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
+ const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize();
+ out[pnt] = aiVector3D((std::atan2(diff.z, diff.y) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
+ (std::asin (diff.x) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0);
+ }
+ }
+ else if (axis * base_axis_y >= angle_epsilon) {
+ // ... just the same again
+ for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
+ const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize();
+ out[pnt] = aiVector3D((std::atan2(diff.x, diff.z) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
+ (std::asin (diff.y) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0);
+ }
+ }
+ else if (axis * base_axis_z >= angle_epsilon) {
+ // ... just the same again
+ for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
+ const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize();
+ out[pnt] = aiVector3D((std::atan2(diff.y, diff.x) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
+ (std::asin (diff.z) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0);
+ }
+ }
+ // slower code path in case the mapping axis is not one of the coordinate system axes
+ else {
+ aiMatrix4x4 mTrafo;
+ aiMatrix4x4::FromToMatrix(axis,base_axis_y,mTrafo);
+
+ // again the same, except we're applying a transformation now
+ for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
+ const aiVector3D diff = ((mTrafo*mesh->mVertices[pnt])-center).Normalize();
+ out[pnt] = aiVector3D((std::atan2(diff.y, diff.x) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
+ (std::asin(diff.z) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0);
+ }
+ }
+
+
+ // Now find and remove UV seams. A seam occurs if a face has a tcoord
+ // close to zero on the one side, and a tcoord close to one on the
+ // other side.
+ RemoveUVSeams(mesh,out);
+}
+
+// ------------------------------------------------------------------------------------------------
+void ComputeUVMappingProcess::ComputeCylinderMapping(aiMesh* mesh,const aiVector3D& axis, aiVector3D* out)
+{
+ aiVector3D center, min, max;
+
+ // If the axis is one of x,y,z run a faster code path. It's worth the extra effort ...
+ // currently the mapping axis will always be one of x,y,z, except if the
+ // PretransformVertices step is used (it transforms the meshes into worldspace,
+ // thus changing the mapping axis)
+ if (axis * base_axis_x >= angle_epsilon) {
+ FindMeshCenter(mesh, center, min, max);
+ const ai_real diff = max.x - min.x;
+
+ // If the main axis is 'z', the z coordinate of a point 'p' is mapped
+ // directly to the texture V axis. The other axis is derived from
+ // the angle between ( p.x - c.x, p.y - c.y ) and (1,0), where
+ // 'c' is the center point of the mesh.
+ for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
+ const aiVector3D& pos = mesh->mVertices[pnt];
+ aiVector3D& uv = out[pnt];
+
+ uv.y = (pos.x - min.x) / diff;
+ uv.x = (std::atan2( pos.z - center.z, pos.y - center.y) +(ai_real)AI_MATH_PI ) / (ai_real)AI_MATH_TWO_PI;
+ }
+ }
+ else if (axis * base_axis_y >= angle_epsilon) {
+ FindMeshCenter(mesh, center, min, max);
+ const ai_real diff = max.y - min.y;
+
+ // just the same ...
+ for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
+ const aiVector3D& pos = mesh->mVertices[pnt];
+ aiVector3D& uv = out[pnt];
+
+ uv.y = (pos.y - min.y) / diff;
+ uv.x = (std::atan2( pos.x - center.x, pos.z - center.z) +(ai_real)AI_MATH_PI ) / (ai_real)AI_MATH_TWO_PI;
+ }
+ }
+ else if (axis * base_axis_z >= angle_epsilon) {
+ FindMeshCenter(mesh, center, min, max);
+ const ai_real diff = max.z - min.z;
+
+ // just the same ...
+ for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
+ const aiVector3D& pos = mesh->mVertices[pnt];
+ aiVector3D& uv = out[pnt];
+
+ uv.y = (pos.z - min.z) / diff;
+ uv.x = (std::atan2( pos.y - center.y, pos.x - center.x) +(ai_real)AI_MATH_PI ) / (ai_real)AI_MATH_TWO_PI;
+ }
+ }
+ // slower code path in case the mapping axis is not one of the coordinate system axes
+ else {
+ aiMatrix4x4 mTrafo;
+ aiMatrix4x4::FromToMatrix(axis,base_axis_y,mTrafo);
+ FindMeshCenterTransformed(mesh, center, min, max,mTrafo);
+ const ai_real diff = max.y - min.y;
+
+ // again the same, except we're applying a transformation now
+ for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt){
+ const aiVector3D pos = mTrafo* mesh->mVertices[pnt];
+ aiVector3D& uv = out[pnt];
+
+ uv.y = (pos.y - min.y) / diff;
+ uv.x = (std::atan2( pos.x - center.x, pos.z - center.z) +(ai_real)AI_MATH_PI ) / (ai_real)AI_MATH_TWO_PI;
+ }
+ }
+
+ // Now find and remove UV seams. A seam occurs if a face has a tcoord
+ // close to zero on the one side, and a tcoord close to one on the
+ // other side.
+ RemoveUVSeams(mesh,out);
+}
+
+// ------------------------------------------------------------------------------------------------
+void ComputeUVMappingProcess::ComputePlaneMapping(aiMesh* mesh,const aiVector3D& axis, aiVector3D* out)
+{
+ ai_real diffu,diffv;
+ aiVector3D center, min, max;
+
+ // If the axis is one of x,y,z run a faster code path. It's worth the extra effort ...
+ // currently the mapping axis will always be one of x,y,z, except if the
+ // PretransformVertices step is used (it transforms the meshes into worldspace,
+ // thus changing the mapping axis)
+ if (axis * base_axis_x >= angle_epsilon) {
+ FindMeshCenter(mesh, center, min, max);
+ diffu = max.z - min.z;
+ diffv = max.y - min.y;
+
+ for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
+ const aiVector3D& pos = mesh->mVertices[pnt];
+ out[pnt].Set((pos.z - min.z) / diffu,(pos.y - min.y) / diffv,0.0);
+ }
+ }
+ else if (axis * base_axis_y >= angle_epsilon) {
+ FindMeshCenter(mesh, center, min, max);
+ diffu = max.x - min.x;
+ diffv = max.z - min.z;
+
+ for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
+ const aiVector3D& pos = mesh->mVertices[pnt];
+ out[pnt].Set((pos.x - min.x) / diffu,(pos.z - min.z) / diffv,0.0);
+ }
+ }
+ else if (axis * base_axis_z >= angle_epsilon) {
+ FindMeshCenter(mesh, center, min, max);
+ diffu = max.y - min.y;
+ diffv = max.z - min.z;
+
+ for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
+ const aiVector3D& pos = mesh->mVertices[pnt];
+ out[pnt].Set((pos.y - min.y) / diffu,(pos.x - min.x) / diffv,0.0);
+ }
+ }
+ // slower code path in case the mapping axis is not one of the coordinate system axes
+ else
+ {
+ aiMatrix4x4 mTrafo;
+ aiMatrix4x4::FromToMatrix(axis,base_axis_y,mTrafo);
+ FindMeshCenterTransformed(mesh, center, min, max,mTrafo);
+ diffu = max.x - min.x;
+ diffv = max.z - min.z;
+
+ // again the same, except we're applying a transformation now
+ for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
+ const aiVector3D pos = mTrafo * mesh->mVertices[pnt];
+ out[pnt].Set((pos.x - min.x) / diffu,(pos.z - min.z) / diffv,0.0);
+ }
+ }
+
+ // shouldn't be necessary to remove UV seams ...
+}
+
+// ------------------------------------------------------------------------------------------------
+void ComputeUVMappingProcess::ComputeBoxMapping( aiMesh*, aiVector3D* )
+{
+ ASSIMP_LOG_ERROR("Mapping type currently not implemented");
+}
+
+// ------------------------------------------------------------------------------------------------
+void ComputeUVMappingProcess::Execute( aiScene* pScene)
+{
+ ASSIMP_LOG_DEBUG("GenUVCoordsProcess begin");
+ char buffer[1024];
+
+ if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT)
+ throw DeadlyImportError("Post-processing order mismatch: expecting pseudo-indexed (\"verbose\") vertices here");
+
+ std::list<MappingInfo> mappingStack;
+
+ /* Iterate through all materials and search for non-UV mapped textures
+ */
+ for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
+ {
+ mappingStack.clear();
+ aiMaterial* mat = pScene->mMaterials[i];
+ for (unsigned int a = 0; a < mat->mNumProperties;++a)
+ {
+ aiMaterialProperty* prop = mat->mProperties[a];
+ if (!::strcmp( prop->mKey.data, "$tex.mapping"))
+ {
+ aiTextureMapping& mapping = *((aiTextureMapping*)prop->mData);
+ if (aiTextureMapping_UV != mapping)
+ {
+ if (!DefaultLogger::isNullLogger())
+ {
+ ai_snprintf(buffer, 1024, "Found non-UV mapped texture (%s,%u). Mapping type: %s",
+ TextureTypeToString((aiTextureType)prop->mSemantic),prop->mIndex,
+ MappingTypeToString(mapping));
+
+ ASSIMP_LOG_INFO(buffer);
+ }
+
+ if (aiTextureMapping_OTHER == mapping)
+ continue;
+
+ MappingInfo info (mapping);
+
+ // Get further properties - currently only the major axis
+ for (unsigned int a2 = 0; a2 < mat->mNumProperties;++a2)
+ {
+ aiMaterialProperty* prop2 = mat->mProperties[a2];
+ if (prop2->mSemantic != prop->mSemantic || prop2->mIndex != prop->mIndex)
+ continue;
+
+ if ( !::strcmp( prop2->mKey.data, "$tex.mapaxis")) {
+ info.axis = *((aiVector3D*)prop2->mData);
+ break;
+ }
+ }
+
+ unsigned int idx( 99999999 );
+
+ // Check whether we have this mapping mode already
+ std::list<MappingInfo>::iterator it = std::find (mappingStack.begin(),mappingStack.end(), info);
+ if (mappingStack.end() != it)
+ {
+ idx = (*it).uv;
+ }
+ else
+ {
+ /* We have found a non-UV mapped texture. Now
+ * we need to find all meshes using this material
+ * that we can compute UV channels for them.
+ */
+ for (unsigned int m = 0; m < pScene->mNumMeshes;++m)
+ {
+ aiMesh* mesh = pScene->mMeshes[m];
+ unsigned int outIdx = 0;
+ if ( mesh->mMaterialIndex != i || ( outIdx = FindEmptyUVChannel(mesh) ) == UINT_MAX ||
+ !mesh->mNumVertices)
+ {
+ continue;
+ }
+
+ // Allocate output storage
+ aiVector3D* p = mesh->mTextureCoords[outIdx] = new aiVector3D[mesh->mNumVertices];
+
+ switch (mapping)
+ {
+ case aiTextureMapping_SPHERE:
+ ComputeSphereMapping(mesh,info.axis,p);
+ break;
+ case aiTextureMapping_CYLINDER:
+ ComputeCylinderMapping(mesh,info.axis,p);
+ break;
+ case aiTextureMapping_PLANE:
+ ComputePlaneMapping(mesh,info.axis,p);
+ break;
+ case aiTextureMapping_BOX:
+ ComputeBoxMapping(mesh,p);
+ break;
+ default:
+ ai_assert(false);
+ }
+ if (m && idx != outIdx)
+ {
+ ASSIMP_LOG_WARN("UV index mismatch. Not all meshes assigned to "
+ "this material have equal numbers of UV channels. The UV index stored in "
+ "the material structure does therefore not apply for all meshes. ");
+ }
+ idx = outIdx;
+ }
+ info.uv = idx;
+ mappingStack.push_back(info);
+ }
+
+ // Update the material property list
+ mapping = aiTextureMapping_UV;
+ ((aiMaterial*)mat)->AddProperty(&idx,1,AI_MATKEY_UVWSRC(prop->mSemantic,prop->mIndex));
+ }
+ }
+ }
+ }
+ ASSIMP_LOG_DEBUG("GenUVCoordsProcess finished");
+}
diff --git a/thirdparty/assimp/code/ComputeUVMappingProcess.h b/thirdparty/assimp/code/ComputeUVMappingProcess.h
new file mode 100644
index 0000000000..24f6bb7218
--- /dev/null
+++ b/thirdparty/assimp/code/ComputeUVMappingProcess.h
@@ -0,0 +1,148 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file Defines a post processing step to compute UV coordinates
+ from abstract mappings, such as box or spherical*/
+#ifndef AI_COMPUTEUVMAPPING_H_INC
+#define AI_COMPUTEUVMAPPING_H_INC
+
+#include "BaseProcess.h"
+#include <assimp/mesh.h>
+#include <assimp/material.h>
+#include <assimp/types.h>
+
+class ComputeUVMappingTest;
+
+namespace Assimp {
+
+// ---------------------------------------------------------------------------
+/** ComputeUVMappingProcess - converts special mappings, such as spherical,
+ * cylindrical or boxed to proper UV coordinates for rendering.
+*/
+class ComputeUVMappingProcess : public BaseProcess
+{
+public:
+ ComputeUVMappingProcess();
+ ~ComputeUVMappingProcess();
+
+public:
+
+ // -------------------------------------------------------------------
+ /** Returns whether the processing step is present in the given flag field.
+ * @param pFlags The processing flags the importer was called with. A bitwise
+ * combination of #aiPostProcessSteps.
+ * @return true if the process is present in this flag fields, false if not.
+ */
+ bool IsActive( unsigned int pFlags) const;
+
+ // -------------------------------------------------------------------
+ /** Executes the post processing step on the given imported data.
+ * At the moment a process is not supposed to fail.
+ * @param pScene The imported data to work at.
+ */
+ void Execute( aiScene* pScene);
+
+protected:
+
+ // -------------------------------------------------------------------
+ /** Computes spherical UV coordinates for a mesh
+ *
+ * @param mesh Mesh to be processed
+ * @param axis Main axis
+ * @param out Receives output UV coordinates
+ */
+ void ComputeSphereMapping(aiMesh* mesh,const aiVector3D& axis,
+ aiVector3D* out);
+
+ // -------------------------------------------------------------------
+ /** Computes cylindrical UV coordinates for a mesh
+ *
+ * @param mesh Mesh to be processed
+ * @param axis Main axis
+ * @param out Receives output UV coordinates
+ */
+ void ComputeCylinderMapping(aiMesh* mesh,const aiVector3D& axis,
+ aiVector3D* out);
+
+ // -------------------------------------------------------------------
+ /** Computes planar UV coordinates for a mesh
+ *
+ * @param mesh Mesh to be processed
+ * @param axis Main axis
+ * @param out Receives output UV coordinates
+ */
+ void ComputePlaneMapping(aiMesh* mesh,const aiVector3D& axis,
+ aiVector3D* out);
+
+ // -------------------------------------------------------------------
+ /** Computes cubic UV coordinates for a mesh
+ *
+ * @param mesh Mesh to be processed
+ * @param out Receives output UV coordinates
+ */
+ void ComputeBoxMapping(aiMesh* mesh, aiVector3D* out);
+
+private:
+
+ // temporary structure to describe a mapping
+ struct MappingInfo
+ {
+ explicit MappingInfo(aiTextureMapping _type)
+ : type (_type)
+ , axis (0.f,1.f,0.f)
+ , uv (0u)
+ {}
+
+ aiTextureMapping type;
+ aiVector3D axis;
+ unsigned int uv;
+
+ bool operator== (const MappingInfo& other)
+ {
+ return type == other.type && axis == other.axis;
+ }
+ };
+};
+
+} // end of namespace Assimp
+
+#endif // AI_COMPUTEUVMAPPING_H_INC
diff --git a/thirdparty/assimp/code/ConvertToLHProcess.cpp b/thirdparty/assimp/code/ConvertToLHProcess.cpp
new file mode 100644
index 0000000000..b7cd4f0bc6
--- /dev/null
+++ b/thirdparty/assimp/code/ConvertToLHProcess.cpp
@@ -0,0 +1,414 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file MakeLeftHandedProcess.cpp
+ * @brief Implementation of the post processing step to convert all
+ * imported data to a left-handed coordinate system.
+ *
+ * Face order & UV flip are also implemented here, for the sake of a
+ * better location.
+ */
+
+
+#include "ConvertToLHProcess.h"
+#include <assimp/scene.h>
+#include <assimp/postprocess.h>
+#include <assimp/DefaultLogger.hpp>
+
+using namespace Assimp;
+
+#ifndef ASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS
+
+namespace {
+
+template <typename aiMeshType>
+void flipUVs(aiMeshType* pMesh) {
+ if (pMesh == nullptr) { return; }
+ // mirror texture y coordinate
+ for (unsigned int tcIdx = 0; tcIdx < AI_MAX_NUMBER_OF_TEXTURECOORDS; tcIdx++) {
+ if (!pMesh->HasTextureCoords(tcIdx)) {
+ break;
+ }
+
+ for (unsigned int vIdx = 0; vIdx < pMesh->mNumVertices; vIdx++) {
+ pMesh->mTextureCoords[tcIdx][vIdx].y = 1.0f - pMesh->mTextureCoords[tcIdx][vIdx].y;
+ }
+ }
+}
+
+} // namespace
+
+// ------------------------------------------------------------------------------------------------
+// Constructor to be privately used by Importer
+MakeLeftHandedProcess::MakeLeftHandedProcess()
+: BaseProcess() {
+ // empty
+}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor, private as well
+MakeLeftHandedProcess::~MakeLeftHandedProcess() {
+ // empty
+}
+
+// ------------------------------------------------------------------------------------------------
+// Returns whether the processing step is present in the given flag field.
+bool MakeLeftHandedProcess::IsActive( unsigned int pFlags) const
+{
+ return 0 != (pFlags & aiProcess_MakeLeftHanded);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+void MakeLeftHandedProcess::Execute( aiScene* pScene)
+{
+ // Check for an existent root node to proceed
+ ai_assert(pScene->mRootNode != NULL);
+ ASSIMP_LOG_DEBUG("MakeLeftHandedProcess begin");
+
+ // recursively convert all the nodes
+ ProcessNode( pScene->mRootNode, aiMatrix4x4());
+
+ // process the meshes accordingly
+ for ( unsigned int a = 0; a < pScene->mNumMeshes; ++a ) {
+ ProcessMesh( pScene->mMeshes[ a ] );
+ }
+
+ // process the materials accordingly
+ for ( unsigned int a = 0; a < pScene->mNumMaterials; ++a ) {
+ ProcessMaterial( pScene->mMaterials[ a ] );
+ }
+
+ // transform all animation channels as well
+ for( unsigned int a = 0; a < pScene->mNumAnimations; a++)
+ {
+ aiAnimation* anim = pScene->mAnimations[a];
+ for( unsigned int b = 0; b < anim->mNumChannels; b++)
+ {
+ aiNodeAnim* nodeAnim = anim->mChannels[b];
+ ProcessAnimation( nodeAnim);
+ }
+ }
+ ASSIMP_LOG_DEBUG("MakeLeftHandedProcess finished");
+}
+
+// ------------------------------------------------------------------------------------------------
+// Recursively converts a node, all of its children and all of its meshes
+void MakeLeftHandedProcess::ProcessNode( aiNode* pNode, const aiMatrix4x4& pParentGlobalRotation)
+{
+ // mirror all base vectors at the local Z axis
+ pNode->mTransformation.c1 = -pNode->mTransformation.c1;
+ pNode->mTransformation.c2 = -pNode->mTransformation.c2;
+ pNode->mTransformation.c3 = -pNode->mTransformation.c3;
+ pNode->mTransformation.c4 = -pNode->mTransformation.c4;
+
+ // now invert the Z axis again to keep the matrix determinant positive.
+ // The local meshes will be inverted accordingly so that the result should look just fine again.
+ pNode->mTransformation.a3 = -pNode->mTransformation.a3;
+ pNode->mTransformation.b3 = -pNode->mTransformation.b3;
+ pNode->mTransformation.c3 = -pNode->mTransformation.c3;
+ pNode->mTransformation.d3 = -pNode->mTransformation.d3; // useless, but anyways...
+
+ // continue for all children
+ for( size_t a = 0; a < pNode->mNumChildren; ++a ) {
+ ProcessNode( pNode->mChildren[ a ], pParentGlobalRotation * pNode->mTransformation );
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Converts a single mesh to left handed coordinates.
+void MakeLeftHandedProcess::ProcessMesh( aiMesh* pMesh) {
+ if ( nullptr == pMesh ) {
+ ASSIMP_LOG_ERROR( "Nullptr to mesh found." );
+ return;
+ }
+ // mirror positions, normals and stuff along the Z axis
+ for( size_t a = 0; a < pMesh->mNumVertices; ++a)
+ {
+ pMesh->mVertices[a].z *= -1.0f;
+ if (pMesh->HasNormals()) {
+ pMesh->mNormals[a].z *= -1.0f;
+ }
+ if( pMesh->HasTangentsAndBitangents())
+ {
+ pMesh->mTangents[a].z *= -1.0f;
+ pMesh->mBitangents[a].z *= -1.0f;
+ }
+ }
+
+ // mirror anim meshes positions, normals and stuff along the Z axis
+ for (size_t m = 0; m < pMesh->mNumAnimMeshes; ++m)
+ {
+ for (size_t a = 0; a < pMesh->mAnimMeshes[m]->mNumVertices; ++a)
+ {
+ pMesh->mAnimMeshes[m]->mVertices[a].z *= -1.0f;
+ if (pMesh->mAnimMeshes[m]->HasNormals()) {
+ pMesh->mAnimMeshes[m]->mNormals[a].z *= -1.0f;
+ }
+ if (pMesh->mAnimMeshes[m]->HasTangentsAndBitangents())
+ {
+ pMesh->mAnimMeshes[m]->mTangents[a].z *= -1.0f;
+ pMesh->mAnimMeshes[m]->mBitangents[a].z *= -1.0f;
+ }
+ }
+ }
+
+ // mirror offset matrices of all bones
+ for( size_t a = 0; a < pMesh->mNumBones; ++a)
+ {
+ aiBone* bone = pMesh->mBones[a];
+ bone->mOffsetMatrix.a3 = -bone->mOffsetMatrix.a3;
+ bone->mOffsetMatrix.b3 = -bone->mOffsetMatrix.b3;
+ bone->mOffsetMatrix.d3 = -bone->mOffsetMatrix.d3;
+ bone->mOffsetMatrix.c1 = -bone->mOffsetMatrix.c1;
+ bone->mOffsetMatrix.c2 = -bone->mOffsetMatrix.c2;
+ bone->mOffsetMatrix.c4 = -bone->mOffsetMatrix.c4;
+ }
+
+ // mirror bitangents as well as they're derived from the texture coords
+ if( pMesh->HasTangentsAndBitangents())
+ {
+ for( unsigned int a = 0; a < pMesh->mNumVertices; a++)
+ pMesh->mBitangents[a] *= -1.0f;
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Converts a single material to left handed coordinates.
+void MakeLeftHandedProcess::ProcessMaterial( aiMaterial* _mat) {
+ if ( nullptr == _mat ) {
+ ASSIMP_LOG_ERROR( "Nullptr to aiMaterial found." );
+ return;
+ }
+
+ aiMaterial* mat = (aiMaterial*)_mat;
+ for (unsigned int a = 0; a < mat->mNumProperties;++a) {
+ aiMaterialProperty* prop = mat->mProperties[a];
+
+ // Mapping axis for UV mappings?
+ if (!::strcmp( prop->mKey.data, "$tex.mapaxis")) {
+ ai_assert( prop->mDataLength >= sizeof(aiVector3D)); /* something is wrong with the validation if we end up here */
+ aiVector3D* pff = (aiVector3D*)prop->mData;
+ pff->z *= -1.f;
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Converts the given animation to LH coordinates.
+void MakeLeftHandedProcess::ProcessAnimation( aiNodeAnim* pAnim)
+{
+ // position keys
+ for( unsigned int a = 0; a < pAnim->mNumPositionKeys; a++)
+ pAnim->mPositionKeys[a].mValue.z *= -1.0f;
+
+ // rotation keys
+ for( unsigned int a = 0; a < pAnim->mNumRotationKeys; a++)
+ {
+ /* That's the safe version, but the float errors add up. So we try the short version instead
+ aiMatrix3x3 rotmat = pAnim->mRotationKeys[a].mValue.GetMatrix();
+ rotmat.a3 = -rotmat.a3; rotmat.b3 = -rotmat.b3;
+ rotmat.c1 = -rotmat.c1; rotmat.c2 = -rotmat.c2;
+ aiQuaternion rotquat( rotmat);
+ pAnim->mRotationKeys[a].mValue = rotquat;
+ */
+ pAnim->mRotationKeys[a].mValue.x *= -1.0f;
+ pAnim->mRotationKeys[a].mValue.y *= -1.0f;
+ }
+}
+
+#endif // !! ASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS
+#ifndef ASSIMP_BUILD_NO_FLIPUVS_PROCESS
+// # FlipUVsProcess
+
+// ------------------------------------------------------------------------------------------------
+// Constructor to be privately used by Importer
+FlipUVsProcess::FlipUVsProcess()
+{}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor, private as well
+FlipUVsProcess::~FlipUVsProcess()
+{}
+
+// ------------------------------------------------------------------------------------------------
+// Returns whether the processing step is present in the given flag field.
+bool FlipUVsProcess::IsActive( unsigned int pFlags) const
+{
+ return 0 != (pFlags & aiProcess_FlipUVs);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+void FlipUVsProcess::Execute( aiScene* pScene)
+{
+ ASSIMP_LOG_DEBUG("FlipUVsProcess begin");
+ for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
+ ProcessMesh(pScene->mMeshes[i]);
+
+ for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
+ ProcessMaterial(pScene->mMaterials[i]);
+ ASSIMP_LOG_DEBUG("FlipUVsProcess finished");
+}
+
+// ------------------------------------------------------------------------------------------------
+// Converts a single material
+void FlipUVsProcess::ProcessMaterial (aiMaterial* _mat)
+{
+ aiMaterial* mat = (aiMaterial*)_mat;
+ for (unsigned int a = 0; a < mat->mNumProperties;++a) {
+ aiMaterialProperty* prop = mat->mProperties[a];
+ if( !prop ) {
+ ASSIMP_LOG_DEBUG( "Property is null" );
+ continue;
+ }
+
+ // UV transformation key?
+ if (!::strcmp( prop->mKey.data, "$tex.uvtrafo")) {
+ ai_assert( prop->mDataLength >= sizeof(aiUVTransform)); /* something is wrong with the validation if we end up here */
+ aiUVTransform* uv = (aiUVTransform*)prop->mData;
+
+ // just flip it, that's everything
+ uv->mTranslation.y *= -1.f;
+ uv->mRotation *= -1.f;
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Converts a single mesh
+void FlipUVsProcess::ProcessMesh( aiMesh* pMesh)
+{
+ flipUVs(pMesh);
+ for (unsigned int idx = 0; idx < pMesh->mNumAnimMeshes; idx++) {
+ flipUVs(pMesh->mAnimMeshes[idx]);
+ }
+}
+
+#endif // !ASSIMP_BUILD_NO_FLIPUVS_PROCESS
+#ifndef ASSIMP_BUILD_NO_FLIPWINDING_PROCESS
+// # FlipWindingOrderProcess
+
+// ------------------------------------------------------------------------------------------------
+// Constructor to be privately used by Importer
+FlipWindingOrderProcess::FlipWindingOrderProcess()
+{}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor, private as well
+FlipWindingOrderProcess::~FlipWindingOrderProcess()
+{}
+
+// ------------------------------------------------------------------------------------------------
+// Returns whether the processing step is present in the given flag field.
+bool FlipWindingOrderProcess::IsActive( unsigned int pFlags) const
+{
+ return 0 != (pFlags & aiProcess_FlipWindingOrder);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+void FlipWindingOrderProcess::Execute( aiScene* pScene)
+{
+ ASSIMP_LOG_DEBUG("FlipWindingOrderProcess begin");
+ for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
+ ProcessMesh(pScene->mMeshes[i]);
+ ASSIMP_LOG_DEBUG("FlipWindingOrderProcess finished");
+}
+
+// ------------------------------------------------------------------------------------------------
+// Converts a single mesh
+void FlipWindingOrderProcess::ProcessMesh( aiMesh* pMesh)
+{
+ // invert the order of all faces in this mesh
+ for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
+ {
+ aiFace& face = pMesh->mFaces[a];
+ for (unsigned int b = 0; b < face.mNumIndices / 2; b++) {
+ std::swap(face.mIndices[b], face.mIndices[face.mNumIndices - 1 - b]);
+ }
+ }
+
+ // invert the order of all components in this mesh anim meshes
+ for (unsigned int m = 0; m < pMesh->mNumAnimMeshes; m++) {
+ aiAnimMesh* animMesh = pMesh->mAnimMeshes[m];
+ unsigned int numVertices = animMesh->mNumVertices;
+ if (animMesh->HasPositions()) {
+ for (unsigned int a = 0; a < numVertices; a++)
+ {
+ std::swap(animMesh->mVertices[a], animMesh->mVertices[numVertices - 1 - a]);
+ }
+ }
+ if (animMesh->HasNormals()) {
+ for (unsigned int a = 0; a < numVertices; a++)
+ {
+ std::swap(animMesh->mNormals[a], animMesh->mNormals[numVertices - 1 - a]);
+ }
+ }
+ for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; i++) {
+ if (animMesh->HasTextureCoords(i)) {
+ for (unsigned int a = 0; a < numVertices; a++)
+ {
+ std::swap(animMesh->mTextureCoords[i][a], animMesh->mTextureCoords[i][numVertices - 1 - a]);
+ }
+ }
+ }
+ if (animMesh->HasTangentsAndBitangents()) {
+ for (unsigned int a = 0; a < numVertices; a++)
+ {
+ std::swap(animMesh->mTangents[a], animMesh->mTangents[numVertices - 1 - a]);
+ std::swap(animMesh->mBitangents[a], animMesh->mBitangents[numVertices - 1 - a]);
+ }
+ }
+ for (unsigned int v = 0; v < AI_MAX_NUMBER_OF_COLOR_SETS; v++) {
+ if (animMesh->HasVertexColors(v)) {
+ for (unsigned int a = 0; a < numVertices; a++)
+ {
+ std::swap(animMesh->mColors[v][a], animMesh->mColors[v][numVertices - 1 - a]);
+ }
+ }
+ }
+ }
+}
+
+#endif // !! ASSIMP_BUILD_NO_FLIPWINDING_PROCESS
diff --git a/thirdparty/assimp/code/ConvertToLHProcess.h b/thirdparty/assimp/code/ConvertToLHProcess.h
new file mode 100644
index 0000000000..63351568d0
--- /dev/null
+++ b/thirdparty/assimp/code/ConvertToLHProcess.h
@@ -0,0 +1,170 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file MakeLeftHandedProcess.h
+ * @brief Defines a bunch of post-processing steps to handle
+ * coordinate system conversions.
+ *
+ * - LH to RH
+ * - UV origin upper-left to lower-left
+ * - face order cw to ccw
+ */
+#ifndef AI_CONVERTTOLHPROCESS_H_INC
+#define AI_CONVERTTOLHPROCESS_H_INC
+
+#include <assimp/types.h>
+#include "BaseProcess.h"
+
+struct aiMesh;
+struct aiNodeAnim;
+struct aiNode;
+struct aiMaterial;
+
+namespace Assimp {
+
+// -----------------------------------------------------------------------------------
+/** @brief The MakeLeftHandedProcess converts all imported data to a left-handed
+ * coordinate system.
+ *
+ * This implies a mirroring of the Z axis of the coordinate system. But to keep
+ * transformation matrices free from reflections we shift the reflection to other
+ * places. We mirror the meshes and adapt the rotations.
+ *
+ * @note RH-LH and LH-RH is the same, so this class can be used for both
+ */
+class MakeLeftHandedProcess : public BaseProcess
+{
+
+
+public:
+ MakeLeftHandedProcess();
+ ~MakeLeftHandedProcess();
+
+ // -------------------------------------------------------------------
+ bool IsActive( unsigned int pFlags) const;
+
+ // -------------------------------------------------------------------
+ void Execute( aiScene* pScene);
+
+protected:
+
+ // -------------------------------------------------------------------
+ /** Recursively converts a node and all of its children
+ */
+ void ProcessNode( aiNode* pNode, const aiMatrix4x4& pParentGlobalRotation);
+
+ // -------------------------------------------------------------------
+ /** Converts a single mesh to left handed coordinates.
+ * This means that positions, normals and tangents are mirrored at
+ * the local Z axis and the order of all faces are inverted.
+ * @param pMesh The mesh to convert.
+ */
+ void ProcessMesh( aiMesh* pMesh);
+
+ // -------------------------------------------------------------------
+ /** Converts a single material to left-handed coordinates
+ * @param pMat Material to convert
+ */
+ void ProcessMaterial( aiMaterial* pMat);
+
+ // -------------------------------------------------------------------
+ /** Converts the given animation to LH coordinates.
+ * The rotation and translation keys are transformed, the scale keys
+ * work in local space and can therefore be left untouched.
+ * @param pAnim The bone animation to transform
+ */
+ void ProcessAnimation( aiNodeAnim* pAnim);
+};
+
+
+// ---------------------------------------------------------------------------
+/** Postprocessing step to flip the face order of the imported data
+ */
+class FlipWindingOrderProcess : public BaseProcess
+{
+ friend class Importer;
+
+public:
+ /** Constructor to be privately used by Importer */
+ FlipWindingOrderProcess();
+
+ /** Destructor, private as well */
+ ~FlipWindingOrderProcess();
+
+ // -------------------------------------------------------------------
+ bool IsActive( unsigned int pFlags) const;
+
+ // -------------------------------------------------------------------
+ void Execute( aiScene* pScene);
+
+protected:
+ void ProcessMesh( aiMesh* pMesh);
+};
+
+// ---------------------------------------------------------------------------
+/** Postprocessing step to flip the UV coordinate system of the import data
+ */
+class FlipUVsProcess : public BaseProcess
+{
+ friend class Importer;
+
+public:
+ /** Constructor to be privately used by Importer */
+ FlipUVsProcess();
+
+ /** Destructor, private as well */
+ ~FlipUVsProcess();
+
+ // -------------------------------------------------------------------
+ bool IsActive( unsigned int pFlags) const;
+
+ // -------------------------------------------------------------------
+ void Execute( aiScene* pScene);
+
+protected:
+ void ProcessMesh( aiMesh* pMesh);
+ void ProcessMaterial( aiMaterial* mat);
+};
+
+} // end of namespace Assimp
+
+#endif // AI_CONVERTTOLHPROCESS_H_INC
diff --git a/thirdparty/assimp/code/CreateAnimMesh.cpp b/thirdparty/assimp/code/CreateAnimMesh.cpp
new file mode 100644
index 0000000000..1a052849bb
--- /dev/null
+++ b/thirdparty/assimp/code/CreateAnimMesh.cpp
@@ -0,0 +1,92 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (C) 2016 The Qt Company Ltd.
+Copyright (c) 2006-2012, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+#include <assimp/CreateAnimMesh.h>
+
+namespace Assimp {
+
+aiAnimMesh *aiCreateAnimMesh(const aiMesh *mesh)
+{
+ aiAnimMesh *animesh = new aiAnimMesh;
+ animesh->mVertices = NULL;
+ animesh->mNormals = NULL;
+ animesh->mTangents = NULL;
+ animesh->mBitangents = NULL;
+ animesh->mNumVertices = mesh->mNumVertices;
+ if (mesh->mVertices) {
+ animesh->mVertices = new aiVector3D[animesh->mNumVertices];
+ std::memcpy(animesh->mVertices, mesh->mVertices, mesh->mNumVertices * sizeof(aiVector3D));
+ }
+ if (mesh->mNormals) {
+ animesh->mNormals = new aiVector3D[animesh->mNumVertices];
+ std::memcpy(animesh->mNormals, mesh->mNormals, mesh->mNumVertices * sizeof(aiVector3D));
+ }
+ if (mesh->mTangents) {
+ animesh->mTangents = new aiVector3D[animesh->mNumVertices];
+ std::memcpy(animesh->mTangents, mesh->mTangents, mesh->mNumVertices * sizeof(aiVector3D));
+ }
+ if (mesh->mBitangents) {
+ animesh->mBitangents = new aiVector3D[animesh->mNumVertices];
+ std::memcpy(animesh->mBitangents, mesh->mBitangents, mesh->mNumVertices * sizeof(aiVector3D));
+ }
+
+ for (int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) {
+ if (mesh->mColors[i]) {
+ animesh->mColors[i] = new aiColor4D[animesh->mNumVertices];
+ std::memcpy(animesh->mColors[i], mesh->mColors[i], mesh->mNumVertices * sizeof(aiColor4D));
+ } else {
+ animesh->mColors[i] = NULL;
+ }
+ }
+
+ for (int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
+ if (mesh->mTextureCoords[i]) {
+ animesh->mTextureCoords[i] = new aiVector3D[animesh->mNumVertices];
+ std::memcpy(animesh->mTextureCoords[i], mesh->mTextureCoords[i], mesh->mNumVertices * sizeof(aiVector3D));
+ } else {
+ animesh->mTextureCoords[i] = NULL;
+ }
+ }
+ return animesh;
+}
+
+} // end of namespace Assimp
diff --git a/thirdparty/assimp/code/DeboneProcess.cpp b/thirdparty/assimp/code/DeboneProcess.cpp
new file mode 100644
index 0000000000..83b8336bc9
--- /dev/null
+++ b/thirdparty/assimp/code/DeboneProcess.cpp
@@ -0,0 +1,465 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/// @file DeboneProcess.cpp
+/** Implementation of the DeboneProcess post processing step */
+
+
+
+// internal headers of the post-processing framework
+#include "ProcessHelper.h"
+#include "DeboneProcess.h"
+#include <stdio.h>
+
+
+using namespace Assimp;
+
+// ------------------------------------------------------------------------------------------------
+// Constructor to be privately used by Importer
+DeboneProcess::DeboneProcess()
+{
+ mNumBones = 0;
+ mNumBonesCanDoWithout = 0;
+
+ mThreshold = AI_DEBONE_THRESHOLD;
+ mAllOrNone = false;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor, private as well
+DeboneProcess::~DeboneProcess()
+{
+ // nothing to do here
+}
+
+// ------------------------------------------------------------------------------------------------
+// Returns whether the processing step is present in the given flag field.
+bool DeboneProcess::IsActive( unsigned int pFlags) const
+{
+ return (pFlags & aiProcess_Debone) != 0;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+void DeboneProcess::SetupProperties(const Importer* pImp)
+{
+ // get the current value of the property
+ mAllOrNone = pImp->GetPropertyInteger(AI_CONFIG_PP_DB_ALL_OR_NONE,0)?true:false;
+ mThreshold = pImp->GetPropertyFloat(AI_CONFIG_PP_DB_THRESHOLD,AI_DEBONE_THRESHOLD);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+void DeboneProcess::Execute( aiScene* pScene)
+{
+ ASSIMP_LOG_DEBUG("DeboneProcess begin");
+
+ if(!pScene->mNumMeshes) {
+ return;
+ }
+
+ std::vector<bool> splitList(pScene->mNumMeshes);
+ for( unsigned int a = 0; a < pScene->mNumMeshes; a++) {
+ splitList[a] = ConsiderMesh( pScene->mMeshes[a] );
+ }
+
+ int numSplits = 0;
+
+ if(!!mNumBonesCanDoWithout && (!mAllOrNone||mNumBonesCanDoWithout==mNumBones)) {
+ for(unsigned int a = 0; a < pScene->mNumMeshes; a++) {
+ if(splitList[a]) {
+ numSplits++;
+ }
+ }
+ }
+
+ if(numSplits) {
+ // we need to do something. Let's go.
+ //mSubMeshIndices.clear(); // really needed?
+ mSubMeshIndices.resize(pScene->mNumMeshes); // because we're doing it here anyway
+
+ // build a new array of meshes for the scene
+ std::vector<aiMesh*> meshes;
+
+ for(unsigned int a=0;a<pScene->mNumMeshes;a++)
+ {
+ aiMesh* srcMesh = pScene->mMeshes[a];
+
+ std::vector<std::pair<aiMesh*,const aiBone*> > newMeshes;
+
+ if(splitList[a]) {
+ SplitMesh(srcMesh,newMeshes);
+ }
+
+ // mesh was split
+ if(!newMeshes.empty()) {
+ unsigned int out = 0, in = srcMesh->mNumBones;
+
+ // store new meshes and indices of the new meshes
+ for(unsigned int b=0;b<newMeshes.size();b++) {
+ const aiString *find = newMeshes[b].second?&newMeshes[b].second->mName:0;
+
+ aiNode *theNode = find?pScene->mRootNode->FindNode(*find):0;
+ std::pair<unsigned int,aiNode*> push_pair(static_cast<unsigned int>(meshes.size()),theNode);
+
+ mSubMeshIndices[a].push_back(push_pair);
+ meshes.push_back(newMeshes[b].first);
+
+ out+=newMeshes[b].first->mNumBones;
+ }
+
+ if(!DefaultLogger::isNullLogger()) {
+ ASSIMP_LOG_INFO_F("Removed %u bones. Input bones:", in - out, ". Output bones: ", out);
+ }
+
+ // and destroy the source mesh. It should be completely contained inside the new submeshes
+ delete srcMesh;
+ }
+ else {
+ // Mesh is kept unchanged - store it's new place in the mesh array
+ mSubMeshIndices[a].push_back(std::pair<unsigned int,aiNode*>(static_cast<unsigned int>(meshes.size()),(aiNode*)0));
+ meshes.push_back(srcMesh);
+ }
+ }
+
+ // rebuild the scene's mesh array
+ pScene->mNumMeshes = static_cast<unsigned int>(meshes.size());
+ delete [] pScene->mMeshes;
+ pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
+ std::copy( meshes.begin(), meshes.end(), pScene->mMeshes);
+
+ // recurse through all nodes and translate the node's mesh indices to fit the new mesh array
+ UpdateNode( pScene->mRootNode);
+ }
+
+ ASSIMP_LOG_DEBUG("DeboneProcess end");
+}
+
+// ------------------------------------------------------------------------------------------------
+// Counts bones total/removable in a given mesh.
+bool DeboneProcess::ConsiderMesh(const aiMesh* pMesh)
+{
+ if(!pMesh->HasBones()) {
+ return false;
+ }
+
+ bool split = false;
+
+ //interstitial faces not permitted
+ bool isInterstitialRequired = false;
+
+ std::vector<bool> isBoneNecessary(pMesh->mNumBones,false);
+ std::vector<unsigned int> vertexBones(pMesh->mNumVertices,UINT_MAX);
+
+ const unsigned int cUnowned = UINT_MAX;
+ const unsigned int cCoowned = UINT_MAX-1;
+
+ for(unsigned int i=0;i<pMesh->mNumBones;i++) {
+ for(unsigned int j=0;j<pMesh->mBones[i]->mNumWeights;j++) {
+ float w = pMesh->mBones[i]->mWeights[j].mWeight;
+
+ if(w==0.0f) {
+ continue;
+ }
+
+ unsigned int vid = pMesh->mBones[i]->mWeights[j].mVertexId;
+ if(w>=mThreshold) {
+
+ if(vertexBones[vid]!=cUnowned) {
+ if(vertexBones[vid]==i) //double entry
+ {
+ ASSIMP_LOG_WARN("Encountered double entry in bone weights");
+ }
+ else //TODO: track attraction in order to break tie
+ {
+ vertexBones[vid] = cCoowned;
+ }
+ }
+ else vertexBones[vid] = i;
+ }
+
+ if(!isBoneNecessary[i]) {
+ isBoneNecessary[i] = w<mThreshold;
+ }
+ }
+
+ if(!isBoneNecessary[i]) {
+ isInterstitialRequired = true;
+ }
+ }
+
+ if(isInterstitialRequired) {
+ for(unsigned int i=0;i<pMesh->mNumFaces;i++) {
+ unsigned int v = vertexBones[pMesh->mFaces[i].mIndices[0]];
+
+ for(unsigned int j=1;j<pMesh->mFaces[i].mNumIndices;j++) {
+ unsigned int w = vertexBones[pMesh->mFaces[i].mIndices[j]];
+
+ if(v!=w) {
+ if(v<pMesh->mNumBones) isBoneNecessary[v] = true;
+ if(w<pMesh->mNumBones) isBoneNecessary[w] = true;
+ }
+ }
+ }
+ }
+
+ for(unsigned int i=0;i<pMesh->mNumBones;i++) {
+ if(!isBoneNecessary[i]) {
+ mNumBonesCanDoWithout++;
+ split = true;
+ }
+
+ mNumBones++;
+ }
+ return split;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Splits the given mesh by bone count.
+void DeboneProcess::SplitMesh( const aiMesh* pMesh, std::vector< std::pair< aiMesh*,const aiBone* > >& poNewMeshes) const
+{
+ // same deal here as ConsiderMesh basically
+
+ std::vector<bool> isBoneNecessary(pMesh->mNumBones,false);
+ std::vector<unsigned int> vertexBones(pMesh->mNumVertices,UINT_MAX);
+
+ const unsigned int cUnowned = UINT_MAX;
+ const unsigned int cCoowned = UINT_MAX-1;
+
+ for(unsigned int i=0;i<pMesh->mNumBones;i++) {
+ for(unsigned int j=0;j<pMesh->mBones[i]->mNumWeights;j++) {
+ float w = pMesh->mBones[i]->mWeights[j].mWeight;
+
+ if(w==0.0f) {
+ continue;
+ }
+
+ unsigned int vid = pMesh->mBones[i]->mWeights[j].mVertexId;
+
+ if(w>=mThreshold) {
+ if(vertexBones[vid]!=cUnowned) {
+ if(vertexBones[vid]==i) //double entry
+ {
+ ASSIMP_LOG_WARN("Encountered double entry in bone weights");
+ }
+ else //TODO: track attraction in order to break tie
+ {
+ vertexBones[vid] = cCoowned;
+ }
+ }
+ else vertexBones[vid] = i;
+ }
+
+ if(!isBoneNecessary[i]) {
+ isBoneNecessary[i] = w<mThreshold;
+ }
+ }
+ }
+
+ unsigned int nFacesUnowned = 0;
+
+ std::vector<unsigned int> faceBones(pMesh->mNumFaces,UINT_MAX);
+ std::vector<unsigned int> facesPerBone(pMesh->mNumBones,0);
+
+ for(unsigned int i=0;i<pMesh->mNumFaces;i++) {
+ unsigned int nInterstitial = 1;
+
+ unsigned int v = vertexBones[pMesh->mFaces[i].mIndices[0]];
+
+ for(unsigned int j=1;j<pMesh->mFaces[i].mNumIndices;j++) {
+ unsigned int w = vertexBones[pMesh->mFaces[i].mIndices[j]];
+
+ if(v!=w) {
+ if(v<pMesh->mNumBones) isBoneNecessary[v] = true;
+ if(w<pMesh->mNumBones) isBoneNecessary[w] = true;
+ }
+ else nInterstitial++;
+ }
+
+ if(v<pMesh->mNumBones &&nInterstitial==pMesh->mFaces[i].mNumIndices) {
+ faceBones[i] = v; //primitive belongs to bone #v
+ facesPerBone[v]++;
+ }
+ else nFacesUnowned++;
+ }
+
+ // invalidate any "cojoined" faces
+ for(unsigned int i=0;i<pMesh->mNumFaces;i++) {
+ if(faceBones[i]<pMesh->mNumBones&&isBoneNecessary[faceBones[i]])
+ {
+ ai_assert(facesPerBone[faceBones[i]]>0);
+ facesPerBone[faceBones[i]]--;
+
+ nFacesUnowned++;
+ faceBones[i] = cUnowned;
+ }
+ }
+
+ if(nFacesUnowned) {
+ std::vector<unsigned int> subFaces;
+
+ for(unsigned int i=0;i<pMesh->mNumFaces;i++) {
+ if(faceBones[i]==cUnowned) {
+ subFaces.push_back(i);
+ }
+ }
+
+ aiMesh *baseMesh = MakeSubmesh(pMesh,subFaces,0);
+ std::pair<aiMesh*,const aiBone*> push_pair(baseMesh,(const aiBone*)0);
+
+ poNewMeshes.push_back(push_pair);
+ }
+
+ for(unsigned int i=0;i<pMesh->mNumBones;i++) {
+
+ if(!isBoneNecessary[i]&&facesPerBone[i]>0) {
+ std::vector<unsigned int> subFaces;
+
+ for(unsigned int j=0;j<pMesh->mNumFaces;j++) {
+ if(faceBones[j]==i) {
+ subFaces.push_back(j);
+ }
+ }
+
+ unsigned int f = AI_SUBMESH_FLAGS_SANS_BONES;
+ aiMesh *subMesh =MakeSubmesh(pMesh,subFaces,f);
+
+ //Lifted from PretransformVertices.cpp
+ ApplyTransform(subMesh,pMesh->mBones[i]->mOffsetMatrix);
+ std::pair<aiMesh*,const aiBone*> push_pair(subMesh,pMesh->mBones[i]);
+
+ poNewMeshes.push_back(push_pair);
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Recursively updates the node's mesh list to account for the changed mesh list
+void DeboneProcess::UpdateNode(aiNode* pNode) const
+{
+ // rebuild the node's mesh index list
+
+ std::vector<unsigned int> newMeshList;
+
+ // this will require two passes
+
+ unsigned int m = static_cast<unsigned int>(pNode->mNumMeshes), n = static_cast<unsigned int>(mSubMeshIndices.size());
+
+ // first pass, look for meshes which have not moved
+
+ for(unsigned int a=0;a<m;a++) {
+
+ unsigned int srcIndex = pNode->mMeshes[a];
+ const std::vector< std::pair< unsigned int,aiNode* > > &subMeshes = mSubMeshIndices[srcIndex];
+ unsigned int nSubmeshes = static_cast<unsigned int>(subMeshes.size());
+
+ for(unsigned int b=0;b<nSubmeshes;b++) {
+ if(!subMeshes[b].second) {
+ newMeshList.push_back(subMeshes[b].first);
+ }
+ }
+ }
+
+ // second pass, collect deboned meshes
+
+ for(unsigned int a=0;a<n;a++)
+ {
+ const std::vector< std::pair< unsigned int,aiNode* > > &subMeshes = mSubMeshIndices[a];
+ unsigned int nSubmeshes = static_cast<unsigned int>(subMeshes.size());
+
+ for(unsigned int b=0;b<nSubmeshes;b++) {
+ if(subMeshes[b].second == pNode) {
+ newMeshList.push_back(subMeshes[b].first);
+ }
+ }
+ }
+
+ if( pNode->mNumMeshes > 0 ) {
+ delete [] pNode->mMeshes; pNode->mMeshes = NULL;
+ }
+
+ pNode->mNumMeshes = static_cast<unsigned int>(newMeshList.size());
+
+ if(pNode->mNumMeshes) {
+ pNode->mMeshes = new unsigned int[pNode->mNumMeshes];
+ std::copy( newMeshList.begin(), newMeshList.end(), pNode->mMeshes);
+ }
+
+ // do that also recursively for all children
+ for( unsigned int a = 0; a < pNode->mNumChildren; ++a ) {
+ UpdateNode( pNode->mChildren[a]);
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Apply the node transformation to a mesh
+void DeboneProcess::ApplyTransform(aiMesh* mesh, const aiMatrix4x4& mat)const
+{
+ // Check whether we need to transform the coordinates at all
+ if (!mat.IsIdentity()) {
+
+ if (mesh->HasPositions()) {
+ for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
+ mesh->mVertices[i] = mat * mesh->mVertices[i];
+ }
+ }
+ if (mesh->HasNormals() || mesh->HasTangentsAndBitangents()) {
+ aiMatrix4x4 mWorldIT = mat;
+ mWorldIT.Inverse().Transpose();
+
+ // TODO: implement Inverse() for aiMatrix3x3
+ aiMatrix3x3 m = aiMatrix3x3(mWorldIT);
+
+ if (mesh->HasNormals()) {
+ for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
+ mesh->mNormals[i] = (m * mesh->mNormals[i]).Normalize();
+ }
+ }
+ if (mesh->HasTangentsAndBitangents()) {
+ for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
+ mesh->mTangents[i] = (m * mesh->mTangents[i]).Normalize();
+ mesh->mBitangents[i] = (m * mesh->mBitangents[i]).Normalize();
+ }
+ }
+ }
+ }
+}
diff --git a/thirdparty/assimp/code/DeboneProcess.h b/thirdparty/assimp/code/DeboneProcess.h
new file mode 100644
index 0000000000..ba77aba70e
--- /dev/null
+++ b/thirdparty/assimp/code/DeboneProcess.h
@@ -0,0 +1,134 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** Defines a post processing step to limit the number of bones affecting a single vertex. */
+#ifndef AI_DEBONEPROCESS_H_INC
+#define AI_DEBONEPROCESS_H_INC
+
+#include <vector>
+#include <utility>
+#include "BaseProcess.h"
+
+#include <assimp/mesh.h>
+#include <assimp/scene.h>
+
+class DeboneTest;
+
+namespace Assimp
+{
+
+#if (!defined AI_DEBONE_THRESHOLD)
+# define AI_DEBONE_THRESHOLD 1.0f
+#endif // !! AI_DEBONE_THRESHOLD
+
+// ---------------------------------------------------------------------------
+/** This post processing step removes bones nearly losslessly or according to
+* a configured threshold. In order to remove the bone, the primitives affected by
+* the bone are split from the mesh. The split off (new) mesh is boneless. At any
+* point in time, bones without affect upon a given mesh are to be removed.
+*/
+class DeboneProcess : public BaseProcess
+{
+public:
+
+ DeboneProcess();
+ ~DeboneProcess();
+
+public:
+ // -------------------------------------------------------------------
+ /** Returns whether the processing step is present in the given flag.
+ * @param pFlags The processing flags the importer was called with.
+ * A bitwise combination of #aiPostProcessSteps.
+ * @return true if the process is present in this flag fields,
+ * false if not.
+ */
+ bool IsActive( unsigned int pFlags) const;
+
+ // -------------------------------------------------------------------
+ /** Called prior to ExecuteOnScene().
+ * The function is a request to the process to update its configuration
+ * basing on the Importer's configuration property list.
+ */
+ void SetupProperties(const Importer* pImp);
+
+protected:
+
+ // -------------------------------------------------------------------
+ /** Executes the post processing step on the given imported data.
+ * At the moment a process is not supposed to fail.
+ * @param pScene The imported data to work at.
+ */
+ void Execute( aiScene* pScene);
+
+ // -------------------------------------------------------------------
+ /** Counts bones total/removable in a given mesh.
+ * @param pMesh The mesh to process.
+ */
+ bool ConsiderMesh( const aiMesh* pMesh);
+
+ /// Splits the given mesh by bone count.
+ /// @param pMesh the Mesh to split. Is not changed at all, but might be superfluous in case it was split.
+ /// @param poNewMeshes Array of submeshes created in the process. Empty if splitting was not necessary.
+ void SplitMesh(const aiMesh* pMesh, std::vector< std::pair< aiMesh*,const aiBone* > >& poNewMeshes) const;
+
+ /// Recursively updates the node's mesh list to account for the changed mesh list
+ void UpdateNode(aiNode* pNode) const;
+
+ // -------------------------------------------------------------------
+ // Apply transformation to a mesh
+ void ApplyTransform(aiMesh* mesh, const aiMatrix4x4& mat)const;
+
+public:
+ /** Number of bones present in the scene. */
+ unsigned int mNumBones;
+ unsigned int mNumBonesCanDoWithout;
+
+ float mThreshold;
+ bool mAllOrNone;
+
+ /// Per mesh index: Array of indices of the new submeshes.
+ std::vector< std::vector< std::pair< unsigned int,aiNode* > > > mSubMeshIndices;
+};
+
+} // end of namespace Assimp
+
+#endif // AI_DEBONEPROCESS_H_INC
diff --git a/thirdparty/assimp/code/DefaultIOStream.cpp b/thirdparty/assimp/code/DefaultIOStream.cpp
new file mode 100644
index 0000000000..1c100b6189
--- /dev/null
+++ b/thirdparty/assimp/code/DefaultIOStream.cpp
@@ -0,0 +1,154 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+/** @file DefaultIOStream.cpp
+ * @brief Default File I/O implementation for #Importer
+ */
+
+
+#include <assimp/ai_assert.h>
+#include <assimp/DefaultIOStream.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+using namespace Assimp;
+
+// ----------------------------------------------------------------------------------
+DefaultIOStream::~DefaultIOStream()
+{
+ if (mFile) {
+ ::fclose(mFile);
+ mFile = nullptr;
+ }
+}
+
+// ----------------------------------------------------------------------------------
+size_t DefaultIOStream::Read(void* pvBuffer,
+ size_t pSize,
+ size_t pCount)
+{
+ ai_assert(NULL != pvBuffer && 0 != pSize && 0 != pCount);
+ return (mFile ? ::fread(pvBuffer, pSize, pCount, mFile) : 0);
+}
+
+// ----------------------------------------------------------------------------------
+size_t DefaultIOStream::Write(const void* pvBuffer,
+ size_t pSize,
+ size_t pCount)
+{
+ ai_assert(NULL != pvBuffer && 0 != pSize && 0 != pCount);
+ return (mFile ? ::fwrite(pvBuffer, pSize, pCount, mFile) : 0);
+}
+
+// ----------------------------------------------------------------------------------
+aiReturn DefaultIOStream::Seek(size_t pOffset,
+ aiOrigin pOrigin)
+{
+ if (!mFile) {
+ return AI_FAILURE;
+ }
+
+ // Just to check whether our enum maps one to one with the CRT constants
+ static_assert(aiOrigin_CUR == SEEK_CUR &&
+ aiOrigin_END == SEEK_END && aiOrigin_SET == SEEK_SET, "aiOrigin_CUR == SEEK_CUR && \
+ aiOrigin_END == SEEK_END && aiOrigin_SET == SEEK_SET");
+
+ // do the seek
+ return (0 == ::fseek(mFile, (long)pOffset,(int)pOrigin) ? AI_SUCCESS : AI_FAILURE);
+}
+
+// ----------------------------------------------------------------------------------
+size_t DefaultIOStream::Tell() const
+{
+ if (!mFile) {
+ return 0;
+ }
+ return ::ftell(mFile);
+}
+
+// ----------------------------------------------------------------------------------
+size_t DefaultIOStream::FileSize() const
+{
+ if (! mFile || mFilename.empty()) {
+ return 0;
+ }
+
+ if (SIZE_MAX == mCachedSize ) {
+
+ // Although fseek/ftell would allow us to reuse the existing file handle here,
+ // it is generally unsafe because:
+ // - For binary streams, it is not technically well-defined
+ // - For text files the results are meaningless
+ // That's why we use the safer variant fstat here.
+ //
+ // See here for details:
+ // https://www.securecoding.cert.org/confluence/display/seccode/FIO19-C.+Do+not+use+fseek()+and+ftell()+to+compute+the+size+of+a+regular+file
+#if defined _WIN32 && (!defined __GNUC__ || __MSVCRT_VERSION__ >= 0x0601)
+ struct __stat64 fileStat;
+ //using fileno + fstat avoids having to handle the filename
+ int err = _fstat64( _fileno(mFile), &fileStat );
+ if (0 != err)
+ return 0;
+ mCachedSize = (size_t) (fileStat.st_size);
+#elif defined __GNUC__ || defined __APPLE__ || defined __MACH__ || defined __FreeBSD__
+ struct stat fileStat;
+ int err = stat(mFilename.c_str(), &fileStat );
+ if (0 != err)
+ return 0;
+ const unsigned long long cachedSize = fileStat.st_size;
+ mCachedSize = static_cast< size_t >( cachedSize );
+#else
+# error "Unknown platform"
+#endif
+ }
+ return mCachedSize;
+}
+
+// ----------------------------------------------------------------------------------
+void DefaultIOStream::Flush()
+{
+ if (mFile) {
+ ::fflush(mFile);
+ }
+}
+
+// ----------------------------------------------------------------------------------
diff --git a/thirdparty/assimp/code/DefaultIOSystem.cpp b/thirdparty/assimp/code/DefaultIOSystem.cpp
new file mode 100644
index 0000000000..d40b67de32
--- /dev/null
+++ b/thirdparty/assimp/code/DefaultIOSystem.cpp
@@ -0,0 +1,257 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+/** @file Default implementation of IOSystem using the standard C file functions */
+
+#include <assimp/StringComparison.h>
+
+#include <assimp/DefaultIOSystem.h>
+#include <assimp/DefaultIOStream.h>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/ai_assert.h>
+#include <stdlib.h>
+
+#ifdef __unix__
+#include <sys/param.h>
+#include <stdlib.h>
+#endif
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+using namespace Assimp;
+
+// maximum path length
+// XXX http://insanecoding.blogspot.com/2007/11/pathmax-simply-isnt.html
+#ifdef PATH_MAX
+# define PATHLIMIT PATH_MAX
+#else
+# define PATHLIMIT 4096
+#endif
+
+// ------------------------------------------------------------------------------------------------
+// Tests for the existence of a file at the given path.
+bool DefaultIOSystem::Exists( const char* pFile) const
+{
+#ifdef _WIN32
+ wchar_t fileName16[PATHLIMIT];
+
+#ifndef WindowsStore
+ bool isUnicode = IsTextUnicode(pFile, static_cast<int>(strlen(pFile)), NULL) != 0;
+ if (isUnicode) {
+
+ MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, pFile, -1, fileName16, PATHLIMIT);
+ struct __stat64 filestat;
+ if (0 != _wstat64(fileName16, &filestat)) {
+ return false;
+ }
+ } else {
+#endif
+ FILE* file = ::fopen(pFile, "rb");
+ if (!file)
+ return false;
+
+ ::fclose(file);
+#ifndef WindowsStore
+ }
+#endif
+#else
+ FILE* file = ::fopen( pFile, "rb");
+ if( !file)
+ return false;
+
+ ::fclose( file);
+#endif
+ return true;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Open a new file with a given path.
+IOStream* DefaultIOSystem::Open( const char* strFile, const char* strMode)
+{
+ ai_assert(NULL != strFile);
+ ai_assert(NULL != strMode);
+ FILE* file;
+#ifdef _WIN32
+ wchar_t fileName16[PATHLIMIT];
+#ifndef WindowsStore
+ bool isUnicode = IsTextUnicode(strFile, static_cast<int>(strlen(strFile)), NULL) != 0;
+ if (isUnicode) {
+ MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, strFile, -1, fileName16, PATHLIMIT);
+ std::string mode8(strMode);
+ file = ::_wfopen(fileName16, std::wstring(mode8.begin(), mode8.end()).c_str());
+ } else {
+#endif
+ file = ::fopen(strFile, strMode);
+#ifndef WindowsStore
+ }
+#endif
+#else
+ file = ::fopen(strFile, strMode);
+#endif
+ if (nullptr == file)
+ return nullptr;
+
+ return new DefaultIOStream(file, (std::string) strFile);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Closes the given file and releases all resources associated with it.
+void DefaultIOSystem::Close( IOStream* pFile)
+{
+ delete pFile;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Returns the operation specific directory separator
+char DefaultIOSystem::getOsSeparator() const
+{
+#ifndef _WIN32
+ return '/';
+#else
+ return '\\';
+#endif
+}
+
+// ------------------------------------------------------------------------------------------------
+// IOSystem default implementation (ComparePaths isn't a pure virtual function)
+bool IOSystem::ComparePaths (const char* one, const char* second) const
+{
+ return !ASSIMP_stricmp(one,second);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Convert a relative path into an absolute path
+inline static void MakeAbsolutePath (const char* in, char* _out)
+{
+ ai_assert(in && _out);
+#if defined( _MSC_VER ) || defined( __MINGW32__ )
+#ifndef WindowsStore
+ bool isUnicode = IsTextUnicode(in, static_cast<int>(strlen(in)), NULL) != 0;
+ if (isUnicode) {
+ wchar_t out16[PATHLIMIT];
+ wchar_t in16[PATHLIMIT];
+ MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, in, -1, out16, PATHLIMIT);
+ wchar_t* ret = ::_wfullpath(out16, in16, PATHLIMIT);
+ if (ret) {
+ WideCharToMultiByte(CP_UTF8, MB_PRECOMPOSED, out16, -1, _out, PATHLIMIT, nullptr, nullptr);
+ }
+ if (!ret) {
+ // preserve the input path, maybe someone else is able to fix
+ // the path before it is accessed (e.g. our file system filter)
+ ASSIMP_LOG_WARN_F("Invalid path: ", std::string(in));
+ strcpy(_out, in);
+ }
+
+ } else {
+#endif
+ char* ret = :: _fullpath(_out, in, PATHLIMIT);
+ if (!ret) {
+ // preserve the input path, maybe someone else is able to fix
+ // the path before it is accessed (e.g. our file system filter)
+ ASSIMP_LOG_WARN_F("Invalid path: ", std::string(in));
+ strcpy(_out, in);
+ }
+#ifndef WindowsStore
+ }
+#endif
+#else
+ // use realpath
+ char* ret = realpath(in, _out);
+ if(!ret) {
+ // preserve the input path, maybe someone else is able to fix
+ // the path before it is accessed (e.g. our file system filter)
+ ASSIMP_LOG_WARN_F("Invalid path: ", std::string(in));
+ strcpy(_out,in);
+ }
+#endif
+}
+
+// ------------------------------------------------------------------------------------------------
+// DefaultIOSystem's more specialized implementation
+bool DefaultIOSystem::ComparePaths (const char* one, const char* second) const
+{
+ // chances are quite good both paths are formatted identically,
+ // so we can hopefully return here already
+ if( !ASSIMP_stricmp(one,second) )
+ return true;
+
+ char temp1[PATHLIMIT];
+ char temp2[PATHLIMIT];
+
+ MakeAbsolutePath (one, temp1);
+ MakeAbsolutePath (second, temp2);
+
+ return !ASSIMP_stricmp(temp1,temp2);
+}
+
+// ------------------------------------------------------------------------------------------------
+std::string DefaultIOSystem::fileName( const std::string &path )
+{
+ std::string ret = path;
+ std::size_t last = ret.find_last_of("\\/");
+ if (last != std::string::npos) ret = ret.substr(last + 1);
+ return ret;
+}
+
+// ------------------------------------------------------------------------------------------------
+std::string DefaultIOSystem::completeBaseName( const std::string &path )
+{
+ std::string ret = fileName(path);
+ std::size_t pos = ret.find_last_of('.');
+ if(pos != ret.npos) ret = ret.substr(0, pos);
+ return ret;
+}
+
+// ------------------------------------------------------------------------------------------------
+std::string DefaultIOSystem::absolutePath( const std::string &path )
+{
+ std::string ret = path;
+ std::size_t last = ret.find_last_of("\\/");
+ if (last != std::string::npos) ret = ret.substr(0, last);
+ return ret;
+}
+
+// ------------------------------------------------------------------------------------------------
+
+#undef PATHLIMIT
diff --git a/thirdparty/assimp/code/DefaultLogger.cpp b/thirdparty/assimp/code/DefaultLogger.cpp
new file mode 100644
index 0000000000..de3528d2b4
--- /dev/null
+++ b/thirdparty/assimp/code/DefaultLogger.cpp
@@ -0,0 +1,418 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file DefaultLogger.cpp
+ * @brief Implementation of DefaultLogger (and Logger)
+ */
+
+// Default log streams
+#include "Win32DebugLogStream.h"
+#include "StdOStreamLogStream.h"
+#include "FileLogStream.h"
+#include <assimp/StringUtils.h>
+
+#include <assimp/DefaultIOSystem.h>
+#include <assimp/NullLogger.hpp>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/ai_assert.h>
+#include <iostream>
+#include <stdio.h>
+
+#ifndef ASSIMP_BUILD_SINGLETHREADED
+# include <thread>
+# include <mutex>
+ std::mutex loggerMutex;
+#endif
+
+namespace Assimp {
+
+// ----------------------------------------------------------------------------------
+NullLogger DefaultLogger::s_pNullLogger;
+Logger *DefaultLogger::m_pLogger = &DefaultLogger::s_pNullLogger;
+
+static const unsigned int SeverityAll = Logger::Info | Logger::Err | Logger::Warn | Logger::Debugging;
+
+// ----------------------------------------------------------------------------------
+// Represents a log-stream + its error severity
+struct LogStreamInfo {
+ unsigned int m_uiErrorSeverity;
+ LogStream *m_pStream;
+
+ // Constructor
+ LogStreamInfo( unsigned int uiErrorSev, LogStream *pStream ) :
+ m_uiErrorSeverity( uiErrorSev ),
+ m_pStream( pStream ) {
+ // empty
+ }
+
+ // Destructor
+ ~LogStreamInfo() {
+ delete m_pStream;
+ }
+};
+
+// ----------------------------------------------------------------------------------
+// Construct a default log stream
+LogStream* LogStream::createDefaultStream(aiDefaultLogStream streams,
+ const char* name /*= "AssimpLog.txt"*/,
+ IOSystem* io /*= NULL*/)
+{
+ switch (streams)
+ {
+ // This is a platform-specific feature
+ case aiDefaultLogStream_DEBUGGER:
+#ifdef WIN32
+ return new Win32DebugLogStream();
+#else
+ return nullptr;
+#endif
+
+ // Platform-independent default streams
+ case aiDefaultLogStream_STDERR:
+ return new StdOStreamLogStream(std::cerr);
+ case aiDefaultLogStream_STDOUT:
+ return new StdOStreamLogStream(std::cout);
+ case aiDefaultLogStream_FILE:
+ return (name && *name ? new FileLogStream(name,io) : nullptr );
+ default:
+ // We don't know this default log stream, so raise an assertion
+ ai_assert(false);
+
+ };
+
+ // For compilers without dead code path detection
+ return NULL;
+}
+
+// ----------------------------------------------------------------------------------
+// Creates the only singleton instance
+Logger *DefaultLogger::create(const char* name /*= "AssimpLog.txt"*/,
+ LogSeverity severity /*= NORMAL*/,
+ unsigned int defStreams /*= aiDefaultLogStream_DEBUGGER | aiDefaultLogStream_FILE*/,
+ IOSystem* io /*= NULL*/) {
+ // enter the mutex here to avoid concurrency problems
+#ifndef ASSIMP_BUILD_SINGLETHREADED
+ std::lock_guard<std::mutex> lock(loggerMutex);
+#endif
+
+ if ( m_pLogger && !isNullLogger() ) {
+ delete m_pLogger;
+ }
+
+ m_pLogger = new DefaultLogger( severity );
+
+ // Attach default log streams
+ // Stream the log to the MSVC debugger?
+ if ( defStreams & aiDefaultLogStream_DEBUGGER ) {
+ m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_DEBUGGER ) );
+ }
+
+ // Stream the log to COUT?
+ if ( defStreams & aiDefaultLogStream_STDOUT ) {
+ m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_STDOUT ) );
+ }
+
+ // Stream the log to CERR?
+ if ( defStreams & aiDefaultLogStream_STDERR ) {
+ m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_STDERR ) );
+ }
+
+ // Stream the log to a file
+ if ( defStreams & aiDefaultLogStream_FILE && name && *name ) {
+ m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_FILE, name, io ) );
+ }
+
+ return m_pLogger;
+}
+
+// ----------------------------------------------------------------------------------
+void Logger::debug(const char* message) {
+
+ // SECURITY FIX: otherwise it's easy to produce overruns since
+ // sometimes importers will include data from the input file
+ // (i.e. node names) in their messages.
+ if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) {
+ return;
+ }
+ return OnDebug(message);
+}
+
+// ----------------------------------------------------------------------------------
+void Logger::info(const char* message) {
+
+ // SECURITY FIX: see above
+ if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) {
+ return;
+ }
+ return OnInfo(message);
+}
+
+// ----------------------------------------------------------------------------------
+void Logger::warn(const char* message) {
+
+ // SECURITY FIX: see above
+ if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) {
+ return;
+ }
+ return OnWarn(message);
+}
+
+// ----------------------------------------------------------------------------------
+void Logger::error(const char* message) {
+ // SECURITY FIX: see above
+ if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) {
+ return;
+ }
+ return OnError(message);
+}
+
+// ----------------------------------------------------------------------------------
+void DefaultLogger::set( Logger *logger ) {
+ // enter the mutex here to avoid concurrency problems
+#ifndef ASSIMP_BUILD_SINGLETHREADED
+ std::lock_guard<std::mutex> lock(loggerMutex);
+#endif
+
+ if ( nullptr == logger ) {
+ logger = &s_pNullLogger;
+ }
+ if ( nullptr != m_pLogger && !isNullLogger() ) {
+ delete m_pLogger;
+ }
+
+ DefaultLogger::m_pLogger = logger;
+}
+
+// ----------------------------------------------------------------------------------
+bool DefaultLogger::isNullLogger() {
+ return m_pLogger == &s_pNullLogger;
+}
+
+// ----------------------------------------------------------------------------------
+Logger *DefaultLogger::get() {
+ return m_pLogger;
+}
+
+// ----------------------------------------------------------------------------------
+// Kills the only instance
+void DefaultLogger::kill() {
+ // enter the mutex here to avoid concurrency problems
+#ifndef ASSIMP_BUILD_SINGLETHREADED
+ std::lock_guard<std::mutex> lock(loggerMutex);
+#endif
+
+ if ( m_pLogger == &s_pNullLogger ) {
+ return;
+ }
+ delete m_pLogger;
+ m_pLogger = &s_pNullLogger;
+}
+
+// ----------------------------------------------------------------------------------
+// Debug message
+void DefaultLogger::OnDebug( const char* message ) {
+ if ( m_Severity == Logger::NORMAL ) {
+ return;
+ }
+
+ static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
+ char msg[Size];
+ ai_snprintf(msg, Size, "Debug, T%u: %s", GetThreadID(), message);
+
+ WriteToStreams( msg, Logger::Debugging );
+}
+
+// ----------------------------------------------------------------------------------
+// Logs an info
+void DefaultLogger::OnInfo( const char* message ){
+ static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
+ char msg[Size];
+ ai_snprintf(msg, Size, "Info, T%u: %s", GetThreadID(), message );
+
+ WriteToStreams( msg , Logger::Info );
+}
+
+// ----------------------------------------------------------------------------------
+// Logs a warning
+void DefaultLogger::OnWarn( const char* message ) {
+ static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
+ char msg[Size];
+ ai_snprintf(msg, Size, "Warn, T%u: %s", GetThreadID(), message );
+
+ WriteToStreams( msg, Logger::Warn );
+}
+
+// ----------------------------------------------------------------------------------
+// Logs an error
+void DefaultLogger::OnError( const char* message ) {
+ static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
+ char msg[ Size ];
+ ai_snprintf(msg, Size, "Error, T%u: %s", GetThreadID(), message );
+
+ WriteToStreams( msg, Logger::Err );
+}
+
+// ----------------------------------------------------------------------------------
+// Will attach a new stream
+bool DefaultLogger::attachStream( LogStream *pStream, unsigned int severity ) {
+ if ( nullptr == pStream ) {
+ return false;
+ }
+
+ if (0 == severity) {
+ severity = Logger::Info | Logger::Err | Logger::Warn | Logger::Debugging;
+ }
+
+ for ( StreamIt it = m_StreamArray.begin();
+ it != m_StreamArray.end();
+ ++it )
+ {
+ if ( (*it)->m_pStream == pStream ) {
+ (*it)->m_uiErrorSeverity |= severity;
+ return true;
+ }
+ }
+
+ LogStreamInfo *pInfo = new LogStreamInfo( severity, pStream );
+ m_StreamArray.push_back( pInfo );
+ return true;
+}
+
+// ----------------------------------------------------------------------------------
+// Detach a stream
+bool DefaultLogger::detatchStream( LogStream *pStream, unsigned int severity ) {
+ if ( nullptr == pStream ) {
+ return false;
+ }
+
+ if (0 == severity) {
+ severity = SeverityAll;
+ }
+
+ bool res( false );
+ for ( StreamIt it = m_StreamArray.begin(); it != m_StreamArray.end(); ++it ) {
+ if ( (*it)->m_pStream == pStream ) {
+ (*it)->m_uiErrorSeverity &= ~severity;
+ if ( (*it)->m_uiErrorSeverity == 0 ) {
+ // don't delete the underlying stream 'cause the caller gains ownership again
+ (**it).m_pStream = nullptr;
+ delete *it;
+ m_StreamArray.erase( it );
+ res = true;
+ break;
+ }
+ return true;
+ }
+ }
+ return res;
+}
+
+// ----------------------------------------------------------------------------------
+// Constructor
+DefaultLogger::DefaultLogger(LogSeverity severity)
+ : Logger ( severity )
+ , noRepeatMsg (false)
+ , lastLen( 0 ) {
+ lastMsg[0] = '\0';
+}
+
+// ----------------------------------------------------------------------------------
+// Destructor
+DefaultLogger::~DefaultLogger() {
+ for ( StreamIt it = m_StreamArray.begin(); it != m_StreamArray.end(); ++it ) {
+ // also frees the underlying stream, we are its owner.
+ delete *it;
+ }
+}
+
+// ----------------------------------------------------------------------------------
+// Writes message to stream
+void DefaultLogger::WriteToStreams(const char *message, ErrorSeverity ErrorSev ) {
+ ai_assert(nullptr != message);
+
+ // Check whether this is a repeated message
+ if (! ::strncmp( message,lastMsg, lastLen-1))
+ {
+ if (!noRepeatMsg)
+ {
+ noRepeatMsg = true;
+ message = "Skipping one or more lines with the same contents\n";
+ }
+ else return;
+ }
+ else
+ {
+ // append a new-line character to the message to be printed
+ lastLen = ::strlen(message);
+ ::memcpy(lastMsg,message,lastLen+1);
+ ::strcat(lastMsg+lastLen,"\n");
+
+ message = lastMsg;
+ noRepeatMsg = false;
+ ++lastLen;
+ }
+ for ( ConstStreamIt it = m_StreamArray.begin();
+ it != m_StreamArray.end();
+ ++it)
+ {
+ if ( ErrorSev & (*it)->m_uiErrorSeverity )
+ (*it)->m_pStream->write( message);
+ }
+}
+
+// ----------------------------------------------------------------------------------
+// Returns thread id, if not supported only a zero will be returned.
+unsigned int DefaultLogger::GetThreadID()
+{
+ // fixme: we can get this value via std::threads
+ // std::this_thread::get_id().hash() returns a (big) size_t, not sure if this is useful in this case.
+#ifdef WIN32
+ return (unsigned int)::GetCurrentThreadId();
+#else
+ return 0; // not supported
+#endif
+}
+
+// ----------------------------------------------------------------------------------
+
+} // !namespace Assimp
diff --git a/thirdparty/assimp/code/DefaultProgressHandler.h b/thirdparty/assimp/code/DefaultProgressHandler.h
new file mode 100644
index 0000000000..bd2cce00be
--- /dev/null
+++ b/thirdparty/assimp/code/DefaultProgressHandler.h
@@ -0,0 +1,65 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file ProgressHandler.hpp
+ * @brief Abstract base class 'ProgressHandler'.
+ */
+#ifndef INCLUDED_AI_DEFAULTPROGRESSHANDLER_H
+#define INCLUDED_AI_DEFAULTPROGRESSHANDLER_H
+
+#include <assimp/ProgressHandler.hpp>
+
+namespace Assimp {
+
+// ------------------------------------------------------------------------------------
+/** @brief Internal default implementation of the #ProgressHandler interface. */
+class DefaultProgressHandler : public ProgressHandler {
+
+ virtual bool Update(float /*percentage*/) {
+ return false;
+ }
+
+
+}; // !class DefaultProgressHandler
+} // Namespace Assimp
+
+#endif
diff --git a/thirdparty/assimp/code/DropFaceNormalsProcess.cpp b/thirdparty/assimp/code/DropFaceNormalsProcess.cpp
new file mode 100644
index 0000000000..b11615bb82
--- /dev/null
+++ b/thirdparty/assimp/code/DropFaceNormalsProcess.cpp
@@ -0,0 +1,109 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file Implementation of the post processing step to drop face
+* normals for all imported faces.
+*/
+
+
+#include "DropFaceNormalsProcess.h"
+#include <assimp/postprocess.h>
+#include <assimp/scene.h>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/Exceptional.h>
+
+using namespace Assimp;
+
+// ------------------------------------------------------------------------------------------------
+// Constructor to be privately used by Importer
+DropFaceNormalsProcess::DropFaceNormalsProcess()
+{
+ // nothing to do here
+}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor, private as well
+DropFaceNormalsProcess::~DropFaceNormalsProcess()
+{
+ // nothing to do here
+}
+
+// ------------------------------------------------------------------------------------------------
+// Returns whether the processing step is present in the given flag field.
+bool DropFaceNormalsProcess::IsActive( unsigned int pFlags) const {
+ return (pFlags & aiProcess_DropNormals) != 0;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+void DropFaceNormalsProcess::Execute( aiScene* pScene) {
+ ASSIMP_LOG_DEBUG("DropFaceNormalsProcess begin");
+
+ if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) {
+ throw DeadlyImportError("Post-processing order mismatch: expecting pseudo-indexed (\"verbose\") vertices here");
+ }
+
+ bool bHas = false;
+ for( unsigned int a = 0; a < pScene->mNumMeshes; a++) {
+ bHas |= this->DropMeshFaceNormals( pScene->mMeshes[a]);
+ }
+ if (bHas) {
+ ASSIMP_LOG_INFO("DropFaceNormalsProcess finished. "
+ "Face normals have been removed");
+ } else {
+ ASSIMP_LOG_DEBUG("DropFaceNormalsProcess finished. "
+ "No normals were present");
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+bool DropFaceNormalsProcess::DropMeshFaceNormals (aiMesh* pMesh) {
+ if (NULL == pMesh->mNormals) {
+ return false;
+ }
+
+ delete[] pMesh->mNormals;
+ pMesh->mNormals = nullptr;
+ return true;
+}
diff --git a/thirdparty/assimp/code/DropFaceNormalsProcess.h b/thirdparty/assimp/code/DropFaceNormalsProcess.h
new file mode 100644
index 0000000000..0d116663b7
--- /dev/null
+++ b/thirdparty/assimp/code/DropFaceNormalsProcess.h
@@ -0,0 +1,86 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file Defines a post processing step to compute face normals for all loaded faces*/
+#ifndef AI_DROPFACENORMALPROCESS_H_INC
+#define AI_DROPFACENORMALPROCESS_H_INC
+
+#include "BaseProcess.h"
+#include <assimp/mesh.h>
+
+namespace Assimp
+{
+
+// ---------------------------------------------------------------------------
+/** The DropFaceNormalsProcess computes face normals for all faces of all meshes
+*/
+class ASSIMP_API_WINONLY DropFaceNormalsProcess : public BaseProcess
+{
+public:
+
+ DropFaceNormalsProcess();
+ ~DropFaceNormalsProcess();
+
+public:
+ // -------------------------------------------------------------------
+ /** Returns whether the processing step is present in the given flag field.
+ * @param pFlags The processing flags the importer was called with. A bitwise
+ * combination of #aiPostProcessSteps.
+ * @return true if the process is present in this flag fields, false if not.
+ */
+ bool IsActive( unsigned int pFlags) const;
+
+ // -------------------------------------------------------------------
+ /** Executes the post processing step on the given imported data.
+ * At the moment a process is not supposed to fail.
+ * @param pScene The imported data to work at.
+ */
+ void Execute( aiScene* pScene);
+
+
+private:
+ bool DropMeshFaceNormals(aiMesh* pcMesh);
+};
+
+} // end of namespace Assimp
+
+#endif // !!AI_DROPFACENORMALPROCESS_H_INC
diff --git a/thirdparty/assimp/code/EmbedTexturesProcess.cpp b/thirdparty/assimp/code/EmbedTexturesProcess.cpp
new file mode 100644
index 0000000000..739382a057
--- /dev/null
+++ b/thirdparty/assimp/code/EmbedTexturesProcess.cpp
@@ -0,0 +1,152 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+#include "EmbedTexturesProcess.h"
+#include <assimp/ParsingUtils.h>
+#include "ProcessHelper.h"
+
+#include <fstream>
+
+using namespace Assimp;
+
+EmbedTexturesProcess::EmbedTexturesProcess()
+: BaseProcess() {
+}
+
+EmbedTexturesProcess::~EmbedTexturesProcess() {
+}
+
+bool EmbedTexturesProcess::IsActive(unsigned int pFlags) const {
+ return (pFlags & aiProcess_EmbedTextures) != 0;
+}
+
+void EmbedTexturesProcess::SetupProperties(const Importer* pImp) {
+ mRootPath = pImp->GetPropertyString("sourceFilePath");
+ mRootPath = mRootPath.substr(0, mRootPath.find_last_of("\\/") + 1u);
+}
+
+void EmbedTexturesProcess::Execute(aiScene* pScene) {
+ if (pScene == nullptr || pScene->mRootNode == nullptr) return;
+
+ aiString path;
+
+ uint32_t embeddedTexturesCount = 0u;
+
+ for (auto matId = 0u; matId < pScene->mNumMaterials; ++matId) {
+ auto material = pScene->mMaterials[matId];
+
+ for (auto ttId = 1u; ttId < AI_TEXTURE_TYPE_MAX; ++ttId) {
+ auto tt = static_cast<aiTextureType>(ttId);
+ auto texturesCount = material->GetTextureCount(tt);
+
+ for (auto texId = 0u; texId < texturesCount; ++texId) {
+ material->GetTexture(tt, texId, &path);
+ if (path.data[0] == '*') continue; // Already embedded
+
+ // Indeed embed
+ if (addTexture(pScene, path.data)) {
+ auto embeddedTextureId = pScene->mNumTextures - 1u;
+ ::ai_snprintf(path.data, 1024, "*%u", embeddedTextureId);
+ material->AddProperty(&path, AI_MATKEY_TEXTURE(tt, texId));
+ embeddedTexturesCount++;
+ }
+ }
+ }
+ }
+
+ ASSIMP_LOG_INFO_F("EmbedTexturesProcess finished. Embedded ", embeddedTexturesCount, " textures." );
+}
+
+bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const {
+ std::streampos imageSize = 0;
+ std::string imagePath = path;
+
+ // Test path directly
+ std::ifstream file(imagePath, std::ios::binary | std::ios::ate);
+ if ((imageSize = file.tellg()) == std::streampos(-1)) {
+ ASSIMP_LOG_WARN_F("EmbedTexturesProcess: Cannot find image: ", imagePath, ". Will try to find it in root folder.");
+
+ // Test path in root path
+ imagePath = mRootPath + path;
+ file.open(imagePath, std::ios::binary | std::ios::ate);
+ if ((imageSize = file.tellg()) == std::streampos(-1)) {
+ // Test path basename in root path
+ imagePath = mRootPath + path.substr(path.find_last_of("\\/") + 1u);
+ file.open(imagePath, std::ios::binary | std::ios::ate);
+ if ((imageSize = file.tellg()) == std::streampos(-1)) {
+ ASSIMP_LOG_ERROR_F("EmbedTexturesProcess: Unable to embed texture: ", path, ".");
+ return false;
+ }
+ }
+ }
+
+ aiTexel* imageContent = new aiTexel[ 1ul + static_cast<unsigned long>( imageSize ) / sizeof(aiTexel)];
+ file.seekg(0, std::ios::beg);
+ file.read(reinterpret_cast<char*>(imageContent), imageSize);
+
+ // Enlarging the textures table
+ unsigned int textureId = pScene->mNumTextures++;
+ auto oldTextures = pScene->mTextures;
+ pScene->mTextures = new aiTexture*[pScene->mNumTextures];
+ ::memmove(pScene->mTextures, oldTextures, sizeof(aiTexture*) * (pScene->mNumTextures - 1u));
+
+ // Add the new texture
+ auto pTexture = new aiTexture;
+ pTexture->mHeight = 0; // Means that this is still compressed
+ pTexture->mWidth = static_cast<uint32_t>(imageSize);
+ pTexture->pcData = imageContent;
+
+ auto extension = path.substr(path.find_last_of('.') + 1u);
+ std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
+ if (extension == "jpeg") {
+ extension = "jpg";
+ }
+
+ size_t len = extension.size();
+ if (len > HINTMAXTEXTURELEN -1 ) {
+ len = HINTMAXTEXTURELEN - 1;
+ }
+ ::strncpy(pTexture->achFormatHint, extension.c_str(), len);
+ pScene->mTextures[textureId] = pTexture;
+
+ return true;
+}
diff --git a/thirdparty/assimp/code/EmbedTexturesProcess.h b/thirdparty/assimp/code/EmbedTexturesProcess.h
new file mode 100644
index 0000000000..cdf40bef74
--- /dev/null
+++ b/thirdparty/assimp/code/EmbedTexturesProcess.h
@@ -0,0 +1,85 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+#pragma once
+
+#include "BaseProcess.h"
+
+#include <string>
+
+struct aiNode;
+
+namespace Assimp {
+
+/**
+ * Force embedding of textures (using the path = "*1" convention).
+ * If a texture's file does not exist at the specified path
+ * (due, for instance, to an absolute path generated on another system),
+ * it will check if a file with the same name exists at the root folder
+ * of the imported model. And if so, it uses that.
+ */
+class ASSIMP_API EmbedTexturesProcess : public BaseProcess {
+public:
+ /// The default class constructor.
+ EmbedTexturesProcess();
+
+ /// The class destructor.
+ virtual ~EmbedTexturesProcess();
+
+ /// Overwritten, @see BaseProcess
+ virtual bool IsActive(unsigned int pFlags) const;
+
+ /// Overwritten, @see BaseProcess
+ virtual void SetupProperties(const Importer* pImp);
+
+ /// Overwritten, @see BaseProcess
+ virtual void Execute(aiScene* pScene);
+
+private:
+ // Resolve the path and add the file content to the scene as a texture.
+ bool addTexture(aiScene* pScene, std::string path) const;
+
+private:
+ std::string mRootPath;
+};
+
+} // namespace Assimp
diff --git a/thirdparty/assimp/code/Exporter.cpp b/thirdparty/assimp/code/Exporter.cpp
new file mode 100644
index 0000000000..8848e87f5b
--- /dev/null
+++ b/thirdparty/assimp/code/Exporter.cpp
@@ -0,0 +1,648 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file Exporter.cpp
+
+Assimp export interface. While it's public interface bears many similarities
+to the import interface (in fact, it is largely symmetric), the internal
+implementations differs a lot. Exporters are considered stateless and are
+simple callbacks which we maintain in a global list along with their
+description strings.
+
+Here we implement only the C++ interface (Assimp::Exporter).
+*/
+
+#ifndef ASSIMP_BUILD_NO_EXPORT
+
+#include <assimp/BlobIOSystem.h>
+#include <assimp/SceneCombiner.h>
+#include <assimp/DefaultIOSystem.h>
+#include <assimp/Exporter.hpp>
+#include <assimp/mesh.h>
+#include <assimp/postprocess.h>
+#include <assimp/scene.h>
+
+#include "DefaultProgressHandler.h"
+#include "BaseProcess.h"
+#include "JoinVerticesProcess.h"
+#include "MakeVerboseFormat.h"
+#include "ConvertToLHProcess.h"
+#include "PretransformVertices.h"
+#include <assimp/Exceptional.h>
+#include "ScenePrivate.h"
+
+#include <memory>
+
+namespace Assimp {
+
+// PostStepRegistry.cpp
+void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out);
+
+// ------------------------------------------------------------------------------------------------
+// Exporter worker function prototypes. Should not be necessary to #ifndef them, it's just a prototype
+// do not use const, because some exporter need to convert the scene temporary
+void ExportSceneCollada(const char*,IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneXFile(const char*,IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneStep(const char*,IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneObj(const char*,IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneObjNoMtl(const char*,IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneSTL(const char*,IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneSTLBinary(const char*,IOSystem*, const aiScene*, const ExportProperties*);
+void ExportScenePly(const char*,IOSystem*, const aiScene*, const ExportProperties*);
+void ExportScenePlyBinary(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+void ExportScene3DS(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneGLTF(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneGLB(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneGLTF2(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneGLB2(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneAssbin(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneAssxml(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneX3D(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneFBX(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneFBXA(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+void ExportScene3MF( const char*, IOSystem*, const aiScene*, const ExportProperties* );
+
+// ------------------------------------------------------------------------------------------------
+// global array of all export formats which Assimp supports in its current build
+Exporter::ExportFormatEntry gExporters[] =
+{
+#ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER
+ Exporter::ExportFormatEntry( "collada", "COLLADA - Digital Asset Exchange Schema", "dae", &ExportSceneCollada ),
+#endif
+
+#ifndef ASSIMP_BUILD_NO_X_EXPORTER
+ Exporter::ExportFormatEntry( "x", "X Files", "x", &ExportSceneXFile,
+ aiProcess_MakeLeftHanded | aiProcess_FlipWindingOrder | aiProcess_FlipUVs ),
+#endif
+
+#ifndef ASSIMP_BUILD_NO_STEP_EXPORTER
+ Exporter::ExportFormatEntry( "stp", "Step Files", "stp", &ExportSceneStep, 0 ),
+#endif
+
+#ifndef ASSIMP_BUILD_NO_OBJ_EXPORTER
+ Exporter::ExportFormatEntry( "obj", "Wavefront OBJ format", "obj", &ExportSceneObj,
+ aiProcess_GenSmoothNormals /*| aiProcess_PreTransformVertices */ ),
+ Exporter::ExportFormatEntry( "objnomtl", "Wavefront OBJ format without material file", "obj", &ExportSceneObjNoMtl,
+ aiProcess_GenSmoothNormals /*| aiProcess_PreTransformVertices */ ),
+#endif
+
+#ifndef ASSIMP_BUILD_NO_STL_EXPORTER
+ Exporter::ExportFormatEntry( "stl", "Stereolithography", "stl" , &ExportSceneSTL,
+ aiProcess_Triangulate | aiProcess_GenNormals | aiProcess_PreTransformVertices
+ ),
+ Exporter::ExportFormatEntry( "stlb", "Stereolithography (binary)", "stl" , &ExportSceneSTLBinary,
+ aiProcess_Triangulate | aiProcess_GenNormals | aiProcess_PreTransformVertices
+ ),
+#endif
+
+#ifndef ASSIMP_BUILD_NO_PLY_EXPORTER
+ Exporter::ExportFormatEntry( "ply", "Stanford Polygon Library", "ply" , &ExportScenePly,
+ aiProcess_PreTransformVertices
+ ),
+ Exporter::ExportFormatEntry( "plyb", "Stanford Polygon Library (binary)", "ply", &ExportScenePlyBinary,
+ aiProcess_PreTransformVertices
+ ),
+#endif
+
+#ifndef ASSIMP_BUILD_NO_3DS_EXPORTER
+ Exporter::ExportFormatEntry( "3ds", "Autodesk 3DS (legacy)", "3ds" , &ExportScene3DS,
+ aiProcess_Triangulate | aiProcess_SortByPType | aiProcess_JoinIdenticalVertices ),
+#endif
+
+#ifndef ASSIMP_BUILD_NO_GLTF_EXPORTER
+ Exporter::ExportFormatEntry( "gltf2", "GL Transmission Format v. 2", "gltf", &ExportSceneGLTF2,
+ aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
+ Exporter::ExportFormatEntry( "glb2", "GL Transmission Format v. 2 (binary)", "glb", &ExportSceneGLB2,
+ aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
+ Exporter::ExportFormatEntry( "gltf", "GL Transmission Format", "gltf", &ExportSceneGLTF,
+ aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
+ Exporter::ExportFormatEntry( "glb", "GL Transmission Format (binary)", "glb", &ExportSceneGLB,
+ aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
+#endif
+
+#ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER
+ Exporter::ExportFormatEntry( "assbin", "Assimp Binary", "assbin" , &ExportSceneAssbin, 0 ),
+#endif
+
+#ifndef ASSIMP_BUILD_NO_ASSXML_EXPORTER
+ Exporter::ExportFormatEntry( "assxml", "Assxml Document", "assxml" , &ExportSceneAssxml, 0 ),
+#endif
+
+#ifndef ASSIMP_BUILD_NO_X3D_EXPORTER
+ Exporter::ExportFormatEntry( "x3d", "Extensible 3D", "x3d" , &ExportSceneX3D, 0 ),
+#endif
+
+#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
+ Exporter::ExportFormatEntry( "fbx", "Autodesk FBX (binary)", "fbx", &ExportSceneFBX, 0 ),
+ Exporter::ExportFormatEntry( "fbxa", "Autodesk FBX (ascii)", "fbx", &ExportSceneFBXA, 0 ),
+#endif
+
+#ifndef ASSIMP_BUILD_NO_3MF_EXPORTER
+ Exporter::ExportFormatEntry( "3mf", "The 3MF-File-Format", "3mf", &ExportScene3MF, 0 )
+#endif
+};
+
+#define ASSIMP_NUM_EXPORTERS (sizeof(gExporters)/sizeof(gExporters[0]))
+
+
+class ExporterPimpl {
+public:
+ ExporterPimpl()
+ : blob()
+ , mIOSystem(new Assimp::DefaultIOSystem())
+ , mIsDefaultIOHandler(true)
+ , mProgressHandler( nullptr )
+ , mIsDefaultProgressHandler( true )
+ , mPostProcessingSteps()
+ , mError()
+ , mExporters() {
+ GetPostProcessingStepInstanceList(mPostProcessingSteps);
+
+ // grab all built-in exporters
+ if ( 0 != ( ASSIMP_NUM_EXPORTERS ) ) {
+ mExporters.resize( ASSIMP_NUM_EXPORTERS );
+ std::copy( gExporters, gExporters + ASSIMP_NUM_EXPORTERS, mExporters.begin() );
+ }
+ }
+
+ ~ExporterPimpl() {
+ delete blob;
+
+ // Delete all post-processing plug-ins
+ for( unsigned int a = 0; a < mPostProcessingSteps.size(); a++) {
+ delete mPostProcessingSteps[a];
+ }
+ delete mProgressHandler;
+ }
+
+public:
+ aiExportDataBlob* blob;
+ std::shared_ptr< Assimp::IOSystem > mIOSystem;
+ bool mIsDefaultIOHandler;
+
+ /** The progress handler */
+ ProgressHandler *mProgressHandler;
+ bool mIsDefaultProgressHandler;
+
+ /** Post processing steps we can apply at the imported data. */
+ std::vector< BaseProcess* > mPostProcessingSteps;
+
+ /** Last fatal export error */
+ std::string mError;
+
+ /** Exporters, this includes those registered using #Assimp::Exporter::RegisterExporter */
+ std::vector<Exporter::ExportFormatEntry> mExporters;
+};
+
+} // end of namespace Assimp
+
+using namespace Assimp;
+
+// ------------------------------------------------------------------------------------------------
+Exporter :: Exporter()
+: pimpl(new ExporterPimpl()) {
+ pimpl->mProgressHandler = new DefaultProgressHandler();
+}
+
+// ------------------------------------------------------------------------------------------------
+Exporter::~Exporter() {
+ FreeBlob();
+ delete pimpl;
+}
+
+// ------------------------------------------------------------------------------------------------
+void Exporter::SetIOHandler( IOSystem* pIOHandler) {
+ pimpl->mIsDefaultIOHandler = !pIOHandler;
+ pimpl->mIOSystem.reset(pIOHandler);
+}
+
+// ------------------------------------------------------------------------------------------------
+IOSystem* Exporter::GetIOHandler() const {
+ return pimpl->mIOSystem.get();
+}
+
+// ------------------------------------------------------------------------------------------------
+bool Exporter::IsDefaultIOHandler() const {
+ return pimpl->mIsDefaultIOHandler;
+}
+
+// ------------------------------------------------------------------------------------------------
+void Exporter::SetProgressHandler(ProgressHandler* pHandler) {
+ ai_assert(nullptr != pimpl);
+
+ if ( nullptr == pHandler) {
+ // Release pointer in the possession of the caller
+ pimpl->mProgressHandler = new DefaultProgressHandler();
+ pimpl->mIsDefaultProgressHandler = true;
+ return;
+ }
+
+ if (pimpl->mProgressHandler == pHandler) {
+ return;
+ }
+
+ delete pimpl->mProgressHandler;
+ pimpl->mProgressHandler = pHandler;
+ pimpl->mIsDefaultProgressHandler = false;
+}
+
+// ------------------------------------------------------------------------------------------------
+const aiExportDataBlob* Exporter::ExportToBlob( const aiScene* pScene, const char* pFormatId,
+ unsigned int, const ExportProperties* /*pProperties*/ ) {
+ if (pimpl->blob) {
+ delete pimpl->blob;
+ pimpl->blob = nullptr;
+ }
+
+ std::shared_ptr<IOSystem> old = pimpl->mIOSystem;
+ BlobIOSystem* blobio = new BlobIOSystem();
+ pimpl->mIOSystem = std::shared_ptr<IOSystem>( blobio );
+
+ if (AI_SUCCESS != Export(pScene,pFormatId,blobio->GetMagicFileName())) {
+ pimpl->mIOSystem = old;
+ return nullptr;
+ }
+
+ pimpl->blob = blobio->GetBlobChain();
+ pimpl->mIOSystem = old;
+
+ return pimpl->blob;
+}
+
+// ------------------------------------------------------------------------------------------------
+bool IsVerboseFormat(const aiMesh* mesh) {
+ // avoid slow vector<bool> specialization
+ std::vector<unsigned int> seen(mesh->mNumVertices,0);
+ for(unsigned int i = 0; i < mesh->mNumFaces; ++i) {
+ const aiFace& f = mesh->mFaces[i];
+ for(unsigned int j = 0; j < f.mNumIndices; ++j) {
+ if(++seen[f.mIndices[j]] == 2) {
+ // found a duplicate index
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+// ------------------------------------------------------------------------------------------------
+bool IsVerboseFormat(const aiScene* pScene) {
+ for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
+ if(!IsVerboseFormat(pScene->mMeshes[i])) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// ------------------------------------------------------------------------------------------------
+aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const char* pPath,
+ unsigned int pPreprocessing, const ExportProperties* pProperties) {
+ ASSIMP_BEGIN_EXCEPTION_REGION();
+
+ // when they create scenes from scratch, users will likely create them not in verbose
+ // format. They will likely not be aware that there is a flag in the scene to indicate
+ // this, however. To avoid surprises and bug reports, we check for duplicates in
+ // meshes upfront.
+ const bool is_verbose_format = !(pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) || IsVerboseFormat(pScene);
+
+ pimpl->mProgressHandler->UpdateFileWrite(0, 4);
+
+ pimpl->mError = "";
+ for (size_t i = 0; i < pimpl->mExporters.size(); ++i) {
+ const Exporter::ExportFormatEntry& exp = pimpl->mExporters[i];
+ if (!strcmp(exp.mDescription.id,pFormatId)) {
+ try {
+ // Always create a full copy of the scene. We might optimize this one day,
+ // but for now it is the most pragmatic way.
+ aiScene* scenecopy_tmp = nullptr;
+ SceneCombiner::CopyScene(&scenecopy_tmp,pScene);
+
+ pimpl->mProgressHandler->UpdateFileWrite(1, 4);
+
+ std::unique_ptr<aiScene> scenecopy(scenecopy_tmp);
+ const ScenePrivateData* const priv = ScenePriv(pScene);
+
+ // steps that are not idempotent, i.e. we might need to run them again, usually to get back to the
+ // original state before the step was applied first. When checking which steps we don't need
+ // to run, those are excluded.
+ const unsigned int nonIdempotentSteps = aiProcess_FlipWindingOrder | aiProcess_FlipUVs | aiProcess_MakeLeftHanded;
+
+ // Erase all pp steps that were already applied to this scene
+ const unsigned int pp = (exp.mEnforcePP | pPreprocessing) & ~(priv && !priv->mIsCopy
+ ? (priv->mPPStepsApplied & ~nonIdempotentSteps)
+ : 0u);
+
+ // If no extra post-processing was specified, and we obtained this scene from an
+ // Assimp importer, apply the reverse steps automatically.
+ // TODO: either drop this, or document it. Otherwise it is just a bad surprise.
+ //if (!pPreprocessing && priv) {
+ // pp |= (nonIdempotentSteps & priv->mPPStepsApplied);
+ //}
+
+ // If the input scene is not in verbose format, but there is at least post-processing step that relies on it,
+ // we need to run the MakeVerboseFormat step first.
+ bool must_join_again = false;
+ if (!is_verbose_format) {
+ bool verbosify = false;
+ for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
+ BaseProcess* const p = pimpl->mPostProcessingSteps[a];
+
+ if (p->IsActive(pp) && p->RequireVerboseFormat()) {
+ verbosify = true;
+ break;
+ }
+ }
+
+ if (verbosify || (exp.mEnforcePP & aiProcess_JoinIdenticalVertices)) {
+ ASSIMP_LOG_DEBUG("export: Scene data not in verbose format, applying MakeVerboseFormat step first");
+
+ MakeVerboseFormatProcess proc;
+ proc.Execute(scenecopy.get());
+
+ if(!(exp.mEnforcePP & aiProcess_JoinIdenticalVertices)) {
+ must_join_again = true;
+ }
+ }
+ }
+
+ pimpl->mProgressHandler->UpdateFileWrite(2, 4);
+
+ if (pp) {
+ // the three 'conversion' steps need to be executed first because all other steps rely on the standard data layout
+ {
+ FlipWindingOrderProcess step;
+ if (step.IsActive(pp)) {
+ step.Execute(scenecopy.get());
+ }
+ }
+
+ {
+ FlipUVsProcess step;
+ if (step.IsActive(pp)) {
+ step.Execute(scenecopy.get());
+ }
+ }
+
+ {
+ MakeLeftHandedProcess step;
+ if (step.IsActive(pp)) {
+ step.Execute(scenecopy.get());
+ }
+ }
+
+ bool exportPointCloud(false);
+ if (nullptr != pProperties) {
+ exportPointCloud = pProperties->GetPropertyBool(AI_CONFIG_EXPORT_POINT_CLOUDS);
+ }
+
+ // dispatch other processes
+ for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
+ BaseProcess* const p = pimpl->mPostProcessingSteps[a];
+
+ if (p->IsActive(pp)
+ && !dynamic_cast<FlipUVsProcess*>(p)
+ && !dynamic_cast<FlipWindingOrderProcess*>(p)
+ && !dynamic_cast<MakeLeftHandedProcess*>(p)) {
+ if (dynamic_cast<PretransformVertices*>(p) && exportPointCloud) {
+ continue;
+ }
+ p->Execute(scenecopy.get());
+ }
+ }
+ ScenePrivateData* const privOut = ScenePriv(scenecopy.get());
+ ai_assert(nullptr != privOut);
+
+ privOut->mPPStepsApplied |= pp;
+ }
+
+ pimpl->mProgressHandler->UpdateFileWrite(3, 4);
+
+ if(must_join_again) {
+ JoinVerticesProcess proc;
+ proc.Execute(scenecopy.get());
+ }
+
+ ExportProperties emptyProperties; // Never pass NULL ExportProperties so Exporters don't have to worry.
+ exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get(), pProperties ? pProperties : &emptyProperties);
+
+ pimpl->mProgressHandler->UpdateFileWrite(4, 4);
+ } catch (DeadlyExportError& err) {
+ pimpl->mError = err.what();
+ return AI_FAILURE;
+ }
+ return AI_SUCCESS;
+ }
+ }
+
+ pimpl->mError = std::string("Found no exporter to handle this file format: ") + pFormatId;
+ ASSIMP_END_EXCEPTION_REGION(aiReturn);
+
+ return AI_FAILURE;
+}
+
+// ------------------------------------------------------------------------------------------------
+const char* Exporter::GetErrorString() const {
+ return pimpl->mError.c_str();
+}
+
+// ------------------------------------------------------------------------------------------------
+void Exporter::FreeBlob() {
+ delete pimpl->blob;
+ pimpl->blob = nullptr;
+
+ pimpl->mError = "";
+}
+
+// ------------------------------------------------------------------------------------------------
+const aiExportDataBlob* Exporter::GetBlob() const {
+ return pimpl->blob;
+}
+
+// ------------------------------------------------------------------------------------------------
+const aiExportDataBlob* Exporter::GetOrphanedBlob() const {
+ const aiExportDataBlob* tmp = pimpl->blob;
+ pimpl->blob = nullptr;
+ return tmp;
+}
+
+// ------------------------------------------------------------------------------------------------
+size_t Exporter::GetExportFormatCount() const {
+ return pimpl->mExporters.size();
+}
+
+// ------------------------------------------------------------------------------------------------
+const aiExportFormatDesc* Exporter::GetExportFormatDescription( size_t index ) const {
+ if (index >= GetExportFormatCount()) {
+ return nullptr;
+ }
+
+ // Return from static storage if the requested index is built-in.
+ if (index < sizeof(gExporters) / sizeof(gExporters[0])) {
+ return &gExporters[index].mDescription;
+ }
+
+ return &pimpl->mExporters[index].mDescription;
+}
+
+// ------------------------------------------------------------------------------------------------
+aiReturn Exporter::RegisterExporter(const ExportFormatEntry& desc) {
+ for(const ExportFormatEntry& e : pimpl->mExporters) {
+ if (!strcmp(e.mDescription.id,desc.mDescription.id)) {
+ return aiReturn_FAILURE;
+ }
+ }
+
+ pimpl->mExporters.push_back(desc);
+ return aiReturn_SUCCESS;
+}
+
+// ------------------------------------------------------------------------------------------------
+void Exporter::UnregisterExporter(const char* id) {
+ for(std::vector<ExportFormatEntry>::iterator it = pimpl->mExporters.begin();
+ it != pimpl->mExporters.end(); ++it) {
+ if (!strcmp((*it).mDescription.id,id)) {
+ pimpl->mExporters.erase(it);
+ break;
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+ExportProperties::ExportProperties() {
+ // empty
+}
+
+// ------------------------------------------------------------------------------------------------
+ExportProperties::ExportProperties(const ExportProperties &other)
+: mIntProperties(other.mIntProperties)
+, mFloatProperties(other.mFloatProperties)
+, mStringProperties(other.mStringProperties)
+, mMatrixProperties(other.mMatrixProperties) {
+ // empty
+}
+
+// ------------------------------------------------------------------------------------------------
+// Set a configuration property
+bool ExportProperties::SetPropertyInteger(const char* szName, int iValue) {
+ return SetGenericProperty<int>(mIntProperties, szName,iValue);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Set a configuration property
+bool ExportProperties::SetPropertyFloat(const char* szName, ai_real iValue) {
+ return SetGenericProperty<ai_real>(mFloatProperties, szName,iValue);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Set a configuration property
+bool ExportProperties::SetPropertyString(const char* szName, const std::string& value) {
+ return SetGenericProperty<std::string>(mStringProperties, szName,value);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Set a configuration property
+bool ExportProperties::SetPropertyMatrix(const char* szName, const aiMatrix4x4& value) {
+ return SetGenericProperty<aiMatrix4x4>(mMatrixProperties, szName,value);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Get a configuration property
+int ExportProperties::GetPropertyInteger(const char* szName, int iErrorReturn /*= 0xffffffff*/) const {
+ return GetGenericProperty<int>(mIntProperties,szName,iErrorReturn);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Get a configuration property
+ai_real ExportProperties::GetPropertyFloat(const char* szName, ai_real iErrorReturn /*= 10e10*/) const {
+ return GetGenericProperty<ai_real>(mFloatProperties,szName,iErrorReturn);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Get a configuration property
+const std::string ExportProperties::GetPropertyString(const char* szName,
+ const std::string& iErrorReturn /*= ""*/) const {
+ return GetGenericProperty<std::string>(mStringProperties,szName,iErrorReturn);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Has a configuration property
+const aiMatrix4x4 ExportProperties::GetPropertyMatrix(const char* szName,
+ const aiMatrix4x4& iErrorReturn /*= aiMatrix4x4()*/) const {
+ return GetGenericProperty<aiMatrix4x4>(mMatrixProperties,szName,iErrorReturn);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Has a configuration property
+bool ExportProperties::HasPropertyInteger(const char* szName) const {
+ return HasGenericProperty<int>(mIntProperties, szName);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Has a configuration property
+bool ExportProperties::HasPropertyBool(const char* szName) const {
+ return HasGenericProperty<int>(mIntProperties, szName);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Has a configuration property
+bool ExportProperties::HasPropertyFloat(const char* szName) const {
+ return HasGenericProperty<ai_real>(mFloatProperties, szName);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Has a configuration property
+bool ExportProperties::HasPropertyString(const char* szName) const {
+ return HasGenericProperty<std::string>(mStringProperties, szName);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Has a configuration property
+bool ExportProperties::HasPropertyMatrix(const char* szName) const {
+ return HasGenericProperty<aiMatrix4x4>(mMatrixProperties, szName);
+}
+
+
+#endif // !ASSIMP_BUILD_NO_EXPORT
diff --git a/thirdparty/assimp/code/FBXAnimation.cpp b/thirdparty/assimp/code/FBXAnimation.cpp
new file mode 100644
index 0000000000..874914431b
--- /dev/null
+++ b/thirdparty/assimp/code/FBXAnimation.cpp
@@ -0,0 +1,305 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file FBXAnimation.cpp
+ * @brief Assimp::FBX::AnimationCurve, Assimp::FBX::AnimationCurveNode,
+ * Assimp::FBX::AnimationLayer, Assimp::FBX::AnimationStack
+ */
+
+#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
+
+#include "FBXParser.h"
+#include "FBXDocument.h"
+#include "FBXImporter.h"
+#include "FBXDocumentUtil.h"
+
+namespace Assimp {
+namespace FBX {
+
+using namespace Util;
+
+// ------------------------------------------------------------------------------------------------
+AnimationCurve::AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& /*doc*/)
+: Object(id, element, name)
+{
+ const Scope& sc = GetRequiredScope(element);
+ const Element& KeyTime = GetRequiredElement(sc,"KeyTime");
+ const Element& KeyValueFloat = GetRequiredElement(sc,"KeyValueFloat");
+
+ ParseVectorDataArray(keys, KeyTime);
+ ParseVectorDataArray(values, KeyValueFloat);
+
+ if(keys.size() != values.size()) {
+ DOMError("the number of key times does not match the number of keyframe values",&KeyTime);
+ }
+
+ // check if the key times are well-ordered
+ if(!std::equal(keys.begin(), keys.end() - 1, keys.begin() + 1, std::less<KeyTimeList::value_type>())) {
+ DOMError("the keyframes are not in ascending order",&KeyTime);
+ }
+
+ const Element* KeyAttrDataFloat = sc["KeyAttrDataFloat"];
+ if(KeyAttrDataFloat) {
+ ParseVectorDataArray(attributes, *KeyAttrDataFloat);
+ }
+
+ const Element* KeyAttrFlags = sc["KeyAttrFlags"];
+ if(KeyAttrFlags) {
+ ParseVectorDataArray(flags, *KeyAttrFlags);
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+AnimationCurve::~AnimationCurve()
+{
+ // empty
+}
+
+// ------------------------------------------------------------------------------------------------
+AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, const std::string& name,
+ const Document& doc, const char* const * target_prop_whitelist /*= NULL*/,
+ size_t whitelist_size /*= 0*/)
+: Object(id, element, name)
+, target()
+, doc(doc)
+{
+ const Scope& sc = GetRequiredScope(element);
+
+ // find target node
+ const char* whitelist[] = {"Model","NodeAttribute","Deformer"};
+ const std::vector<const Connection*>& conns = doc.GetConnectionsBySourceSequenced(ID(),whitelist,3);
+
+ for(const Connection* con : conns) {
+
+ // link should go for a property
+ if (!con->PropertyName().length()) {
+ continue;
+ }
+
+ if(target_prop_whitelist) {
+ const char* const s = con->PropertyName().c_str();
+ bool ok = false;
+ for (size_t i = 0; i < whitelist_size; ++i) {
+ if (!strcmp(s, target_prop_whitelist[i])) {
+ ok = true;
+ break;
+ }
+ }
+
+ if (!ok) {
+ throw std::range_error("AnimationCurveNode target property is not in whitelist");
+ }
+ }
+
+ const Object* const ob = con->DestinationObject();
+ if(!ob) {
+ DOMWarning("failed to read destination object for AnimationCurveNode->Model link, ignoring",&element);
+ continue;
+ }
+
+ // XXX support constraints as DOM class
+ //ai_assert(dynamic_cast<const Model*>(ob) || dynamic_cast<const NodeAttribute*>(ob));
+ target = ob;
+ if(!target) {
+ continue;
+ }
+
+ prop = con->PropertyName();
+ break;
+ }
+
+ if(!target) {
+ DOMWarning("failed to resolve target Model/NodeAttribute/Constraint for AnimationCurveNode",&element);
+ }
+
+ props = GetPropertyTable(doc,"AnimationCurveNode.FbxAnimCurveNode",element,sc,false);
+}
+
+// ------------------------------------------------------------------------------------------------
+AnimationCurveNode::~AnimationCurveNode()
+{
+ // empty
+}
+
+// ------------------------------------------------------------------------------------------------
+const AnimationCurveMap& AnimationCurveNode::Curves() const
+{
+ if ( curves.empty() ) {
+ // resolve attached animation curves
+ const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationCurve");
+
+ for(const Connection* con : conns) {
+
+ // link should go for a property
+ if (!con->PropertyName().length()) {
+ continue;
+ }
+
+ const Object* const ob = con->SourceObject();
+ if(!ob) {
+ DOMWarning("failed to read source object for AnimationCurve->AnimationCurveNode link, ignoring",&element);
+ continue;
+ }
+
+ const AnimationCurve* const anim = dynamic_cast<const AnimationCurve*>(ob);
+ if(!anim) {
+ DOMWarning("source object for ->AnimationCurveNode link is not an AnimationCurve",&element);
+ continue;
+ }
+
+ curves[con->PropertyName()] = anim;
+ }
+ }
+
+ return curves;
+}
+
+// ------------------------------------------------------------------------------------------------
+AnimationLayer::AnimationLayer(uint64_t id, const Element& element, const std::string& name, const Document& doc)
+: Object(id, element, name)
+, doc(doc)
+{
+ const Scope& sc = GetRequiredScope(element);
+
+ // note: the props table here bears little importance and is usually absent
+ props = GetPropertyTable(doc,"AnimationLayer.FbxAnimLayer",element,sc, true);
+}
+
+// ------------------------------------------------------------------------------------------------
+AnimationLayer::~AnimationLayer()
+{
+ // empty
+}
+
+// ------------------------------------------------------------------------------------------------
+AnimationCurveNodeList AnimationLayer::Nodes(const char* const * target_prop_whitelist /*= NULL*/,
+ size_t whitelist_size /*= 0*/) const
+{
+ AnimationCurveNodeList nodes;
+
+ // resolve attached animation nodes
+ const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationCurveNode");
+ nodes.reserve(conns.size());
+
+ for(const Connection* con : conns) {
+
+ // link should not go to a property
+ if (con->PropertyName().length()) {
+ continue;
+ }
+
+ const Object* const ob = con->SourceObject();
+ if(!ob) {
+ DOMWarning("failed to read source object for AnimationCurveNode->AnimationLayer link, ignoring",&element);
+ continue;
+ }
+
+ const AnimationCurveNode* const anim = dynamic_cast<const AnimationCurveNode*>(ob);
+ if(!anim) {
+ DOMWarning("source object for ->AnimationLayer link is not an AnimationCurveNode",&element);
+ continue;
+ }
+
+ if(target_prop_whitelist) {
+ const char* s = anim->TargetProperty().c_str();
+ bool ok = false;
+ for (size_t i = 0; i < whitelist_size; ++i) {
+ if (!strcmp(s, target_prop_whitelist[i])) {
+ ok = true;
+ break;
+ }
+ }
+ if(!ok) {
+ continue;
+ }
+ }
+ nodes.push_back(anim);
+ }
+
+ return nodes; // pray for NRVO
+}
+
+// ------------------------------------------------------------------------------------------------
+AnimationStack::AnimationStack(uint64_t id, const Element& element, const std::string& name, const Document& doc)
+: Object(id, element, name)
+{
+ const Scope& sc = GetRequiredScope(element);
+
+ // note: we don't currently use any of these properties so we shouldn't bother if it is missing
+ props = GetPropertyTable(doc,"AnimationStack.FbxAnimStack",element,sc, true);
+
+ // resolve attached animation layers
+ const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationLayer");
+ layers.reserve(conns.size());
+
+ for(const Connection* con : conns) {
+
+ // link should not go to a property
+ if (con->PropertyName().length()) {
+ continue;
+ }
+
+ const Object* const ob = con->SourceObject();
+ if(!ob) {
+ DOMWarning("failed to read source object for AnimationLayer->AnimationStack link, ignoring",&element);
+ continue;
+ }
+
+ const AnimationLayer* const anim = dynamic_cast<const AnimationLayer*>(ob);
+ if(!anim) {
+ DOMWarning("source object for ->AnimationStack link is not an AnimationLayer",&element);
+ continue;
+ }
+ layers.push_back(anim);
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+AnimationStack::~AnimationStack()
+{
+ // empty
+}
+
+} //!FBX
+} //!Assimp
+
+#endif // ASSIMP_BUILD_NO_FBX_IMPORTER
diff --git a/thirdparty/assimp/code/FBXBinaryTokenizer.cpp b/thirdparty/assimp/code/FBXBinaryTokenizer.cpp
new file mode 100644
index 0000000000..7138df4315
--- /dev/null
+++ b/thirdparty/assimp/code/FBXBinaryTokenizer.cpp
@@ -0,0 +1,466 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+/** @file FBXBinaryTokenizer.cpp
+ * @brief Implementation of a fake lexer for binary fbx files -
+ * we emit tokens so the parser needs almost no special handling
+ * for binary files.
+ */
+
+#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
+
+#include "FBXTokenizer.h"
+#include "FBXUtil.h"
+#include <assimp/defs.h>
+#include <stdint.h>
+#include <assimp/Exceptional.h>
+#include <assimp/ByteSwapper.h>
+
+namespace Assimp {
+namespace FBX {
+
+//enum Flag
+//{
+// e_unknown_0 = 1 << 0,
+// e_unknown_1 = 1 << 1,
+// e_unknown_2 = 1 << 2,
+// e_unknown_3 = 1 << 3,
+// e_unknown_4 = 1 << 4,
+// e_unknown_5 = 1 << 5,
+// e_unknown_6 = 1 << 6,
+// e_unknown_7 = 1 << 7,
+// e_unknown_8 = 1 << 8,
+// e_unknown_9 = 1 << 9,
+// e_unknown_10 = 1 << 10,
+// e_unknown_11 = 1 << 11,
+// e_unknown_12 = 1 << 12,
+// e_unknown_13 = 1 << 13,
+// e_unknown_14 = 1 << 14,
+// e_unknown_15 = 1 << 15,
+// e_unknown_16 = 1 << 16,
+// e_unknown_17 = 1 << 17,
+// e_unknown_18 = 1 << 18,
+// e_unknown_19 = 1 << 19,
+// e_unknown_20 = 1 << 20,
+// e_unknown_21 = 1 << 21,
+// e_unknown_22 = 1 << 22,
+// e_unknown_23 = 1 << 23,
+// e_flag_field_size_64_bit = 1 << 24, // Not sure what is
+// e_unknown_25 = 1 << 25,
+// e_unknown_26 = 1 << 26,
+// e_unknown_27 = 1 << 27,
+// e_unknown_28 = 1 << 28,
+// e_unknown_29 = 1 << 29,
+// e_unknown_30 = 1 << 30,
+// e_unknown_31 = 1 << 31
+//};
+//
+//bool check_flag(uint32_t flags, Flag to_check)
+//{
+// return (flags & to_check) != 0;
+//}
+// ------------------------------------------------------------------------------------------------
+Token::Token(const char* sbegin, const char* send, TokenType type, unsigned int offset)
+ :
+ #ifdef DEBUG
+ contents(sbegin, static_cast<size_t>(send-sbegin)),
+ #endif
+ sbegin(sbegin)
+ , send(send)
+ , type(type)
+ , line(offset)
+ , column(BINARY_MARKER)
+{
+ ai_assert(sbegin);
+ ai_assert(send);
+
+ // binary tokens may have zero length because they are sometimes dummies
+ // inserted by TokenizeBinary()
+ ai_assert(send >= sbegin);
+}
+
+
+namespace {
+
+// ------------------------------------------------------------------------------------------------
+// signal tokenization error, this is always unrecoverable. Throws DeadlyImportError.
+AI_WONT_RETURN void TokenizeError(const std::string& message, unsigned int offset) AI_WONT_RETURN_SUFFIX;
+AI_WONT_RETURN void TokenizeError(const std::string& message, unsigned int offset)
+{
+ throw DeadlyImportError(Util::AddOffset("FBX-Tokenize",message,offset));
+}
+
+
+// ------------------------------------------------------------------------------------------------
+uint32_t Offset(const char* begin, const char* cursor) {
+ ai_assert(begin <= cursor);
+
+ return static_cast<unsigned int>(cursor - begin);
+}
+
+// ------------------------------------------------------------------------------------------------
+void TokenizeError(const std::string& message, const char* begin, const char* cursor) {
+ TokenizeError(message, Offset(begin, cursor));
+}
+
+// ------------------------------------------------------------------------------------------------
+uint32_t ReadWord(const char* input, const char*& cursor, const char* end) {
+ const size_t k_to_read = sizeof( uint32_t );
+ if(Offset(cursor, end) < k_to_read ) {
+ TokenizeError("cannot ReadWord, out of bounds",input, cursor);
+ }
+
+ uint32_t word;
+ ::memcpy(&word, cursor, 4);
+ AI_SWAP4(word);
+
+ cursor += k_to_read;
+
+ return word;
+}
+
+// ------------------------------------------------------------------------------------------------
+uint64_t ReadDoubleWord(const char* input, const char*& cursor, const char* end) {
+ const size_t k_to_read = sizeof(uint64_t);
+ if(Offset(cursor, end) < k_to_read) {
+ TokenizeError("cannot ReadDoubleWord, out of bounds",input, cursor);
+ }
+
+ uint64_t dword /*= *reinterpret_cast<const uint64_t*>(cursor)*/;
+ ::memcpy( &dword, cursor, sizeof( uint64_t ) );
+ AI_SWAP8(dword);
+
+ cursor += k_to_read;
+
+ return dword;
+}
+
+// ------------------------------------------------------------------------------------------------
+uint8_t ReadByte(const char* input, const char*& cursor, const char* end) {
+ if(Offset(cursor, end) < sizeof( uint8_t ) ) {
+ TokenizeError("cannot ReadByte, out of bounds",input, cursor);
+ }
+
+ uint8_t word;/* = *reinterpret_cast< const uint8_t* >( cursor )*/
+ ::memcpy( &word, cursor, sizeof( uint8_t ) );
+ ++cursor;
+
+ return word;
+}
+
+// ------------------------------------------------------------------------------------------------
+unsigned int ReadString(const char*& sbegin_out, const char*& send_out, const char* input,
+ const char*& cursor, const char* end, bool long_length = false, bool allow_null = false) {
+ const uint32_t len_len = long_length ? 4 : 1;
+ if(Offset(cursor, end) < len_len) {
+ TokenizeError("cannot ReadString, out of bounds reading length",input, cursor);
+ }
+
+ const uint32_t length = long_length ? ReadWord(input, cursor, end) : ReadByte(input, cursor, end);
+
+ if (Offset(cursor, end) < length) {
+ TokenizeError("cannot ReadString, length is out of bounds",input, cursor);
+ }
+
+ sbegin_out = cursor;
+ cursor += length;
+
+ send_out = cursor;
+
+ if(!allow_null) {
+ for (unsigned int i = 0; i < length; ++i) {
+ if(sbegin_out[i] == '\0') {
+ TokenizeError("failed ReadString, unexpected NUL character in string",input, cursor);
+ }
+ }
+ }
+
+ return length;
+}
+
+// ------------------------------------------------------------------------------------------------
+void ReadData(const char*& sbegin_out, const char*& send_out, const char* input, const char*& cursor, const char* end) {
+ if(Offset(cursor, end) < 1) {
+ TokenizeError("cannot ReadData, out of bounds reading length",input, cursor);
+ }
+
+ const char type = *cursor;
+ sbegin_out = cursor++;
+
+ switch(type)
+ {
+ // 16 bit int
+ case 'Y':
+ cursor += 2;
+ break;
+
+ // 1 bit bool flag (yes/no)
+ case 'C':
+ cursor += 1;
+ break;
+
+ // 32 bit int
+ case 'I':
+ // <- fall through
+
+ // float
+ case 'F':
+ cursor += 4;
+ break;
+
+ // double
+ case 'D':
+ cursor += 8;
+ break;
+
+ // 64 bit int
+ case 'L':
+ cursor += 8;
+ break;
+
+ // note: do not write cursor += ReadWord(...cursor) as this would be UB
+
+ // raw binary data
+ case 'R':
+ {
+ const uint32_t length = ReadWord(input, cursor, end);
+ cursor += length;
+ break;
+ }
+
+ case 'b':
+ // TODO: what is the 'b' type code? Right now we just skip over it /
+ // take the full range we could get
+ cursor = end;
+ break;
+
+ // array of *
+ case 'f':
+ case 'd':
+ case 'l':
+ case 'i':
+ case 'c': {
+ const uint32_t length = ReadWord(input, cursor, end);
+ const uint32_t encoding = ReadWord(input, cursor, end);
+
+ const uint32_t comp_len = ReadWord(input, cursor, end);
+
+ // compute length based on type and check against the stored value
+ if(encoding == 0) {
+ uint32_t stride = 0;
+ switch(type)
+ {
+ case 'f':
+ case 'i':
+ stride = 4;
+ break;
+
+ case 'd':
+ case 'l':
+ stride = 8;
+ break;
+
+ case 'c':
+ stride = 1;
+ break;
+
+ default:
+ ai_assert(false);
+ };
+ ai_assert(stride > 0);
+ if(length * stride != comp_len) {
+ TokenizeError("cannot ReadData, calculated data stride differs from what the file claims",input, cursor);
+ }
+ }
+ // zip/deflate algorithm (encoding==1)? take given length. anything else? die
+ else if (encoding != 1) {
+ TokenizeError("cannot ReadData, unknown encoding",input, cursor);
+ }
+ cursor += comp_len;
+ break;
+ }
+
+ // string
+ case 'S': {
+ const char* sb, *se;
+ // 0 characters can legally happen in such strings
+ ReadString(sb, se, input, cursor, end, true, true);
+ break;
+ }
+ default:
+ TokenizeError("cannot ReadData, unexpected type code: " + std::string(&type, 1),input, cursor);
+ }
+
+ if(cursor > end) {
+ TokenizeError("cannot ReadData, the remaining size is too small for the data type: " + std::string(&type, 1),input, cursor);
+ }
+
+ // the type code is contained in the returned range
+ send_out = cursor;
+}
+
+
+// ------------------------------------------------------------------------------------------------
+bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor, const char* end, bool const is64bits)
+{
+ // the first word contains the offset at which this block ends
+ const uint64_t end_offset = is64bits ? ReadDoubleWord(input, cursor, end) : ReadWord(input, cursor, end);
+
+ // we may get 0 if reading reached the end of the file -
+ // fbx files have a mysterious extra footer which I don't know
+ // how to extract any information from, but at least it always
+ // starts with a 0.
+ if(!end_offset) {
+ return false;
+ }
+
+ if(end_offset > Offset(input, end)) {
+ TokenizeError("block offset is out of range",input, cursor);
+ }
+ else if(end_offset < Offset(input, cursor)) {
+ TokenizeError("block offset is negative out of range",input, cursor);
+ }
+
+ // the second data word contains the number of properties in the scope
+ const uint64_t prop_count = is64bits ? ReadDoubleWord(input, cursor, end) : ReadWord(input, cursor, end);
+
+ // the third data word contains the length of the property list
+ const uint64_t prop_length = is64bits ? ReadDoubleWord(input, cursor, end) : ReadWord(input, cursor, end);
+
+ // now comes the name of the scope/key
+ const char* sbeg, *send;
+ ReadString(sbeg, send, input, cursor, end);
+
+ output_tokens.push_back(new_Token(sbeg, send, TokenType_KEY, Offset(input, cursor) ));
+
+ // now come the individual properties
+ const char* begin_cursor = cursor;
+ for (unsigned int i = 0; i < prop_count; ++i) {
+ ReadData(sbeg, send, input, cursor, begin_cursor + prop_length);
+
+ output_tokens.push_back(new_Token(sbeg, send, TokenType_DATA, Offset(input, cursor) ));
+
+ if(i != prop_count-1) {
+ output_tokens.push_back(new_Token(cursor, cursor + 1, TokenType_COMMA, Offset(input, cursor) ));
+ }
+ }
+
+ if (Offset(begin_cursor, cursor) != prop_length) {
+ TokenizeError("property length not reached, something is wrong",input, cursor);
+ }
+
+ // at the end of each nested block, there is a NUL record to indicate
+ // that the sub-scope exists (i.e. to distinguish between P: and P : {})
+ // this NUL record is 13 bytes long on 32 bit version and 25 bytes long on 64 bit.
+ const size_t sentinel_block_length = is64bits ? (sizeof(uint64_t)* 3 + 1) : (sizeof(uint32_t)* 3 + 1);
+
+ if (Offset(input, cursor) < end_offset) {
+ if (end_offset - Offset(input, cursor) < sentinel_block_length) {
+ TokenizeError("insufficient padding bytes at block end",input, cursor);
+ }
+
+ output_tokens.push_back(new_Token(cursor, cursor + 1, TokenType_OPEN_BRACKET, Offset(input, cursor) ));
+
+ // XXX this is vulnerable to stack overflowing ..
+ while(Offset(input, cursor) < end_offset - sentinel_block_length) {
+ ReadScope(output_tokens, input, cursor, input + end_offset - sentinel_block_length, is64bits);
+ }
+ output_tokens.push_back(new_Token(cursor, cursor + 1, TokenType_CLOSE_BRACKET, Offset(input, cursor) ));
+
+ for (unsigned int i = 0; i < sentinel_block_length; ++i) {
+ if(cursor[i] != '\0') {
+ TokenizeError("failed to read nested block sentinel, expected all bytes to be 0",input, cursor);
+ }
+ }
+ cursor += sentinel_block_length;
+ }
+
+ if (Offset(input, cursor) != end_offset) {
+ TokenizeError("scope length not reached, something is wrong",input, cursor);
+ }
+
+ return true;
+}
+
+} // anonymous namespace
+
+// ------------------------------------------------------------------------------------------------
+// TODO: Test FBX Binary files newer than the 7500 version to check if the 64 bits address behaviour is consistent
+void TokenizeBinary(TokenList& output_tokens, const char* input, unsigned int length)
+{
+ ai_assert(input);
+
+ if(length < 0x1b) {
+ TokenizeError("file is too short",0);
+ }
+
+ //uint32_t offset = 0x15;
+/* const char* cursor = input + 0x15;
+
+ const uint32_t flags = ReadWord(input, cursor, input + length);
+
+ const uint8_t padding_0 = ReadByte(input, cursor, input + length); // unused
+ const uint8_t padding_1 = ReadByte(input, cursor, input + length); // unused*/
+
+ if (strncmp(input,"Kaydara FBX Binary",18)) {
+ TokenizeError("magic bytes not found",0);
+ }
+
+ const char* cursor = input + 18;
+ /*Result ignored*/ ReadByte(input, cursor, input + length);
+ /*Result ignored*/ ReadByte(input, cursor, input + length);
+ /*Result ignored*/ ReadByte(input, cursor, input + length);
+ /*Result ignored*/ ReadByte(input, cursor, input + length);
+ /*Result ignored*/ ReadByte(input, cursor, input + length);
+ const uint32_t version = ReadWord(input, cursor, input + length);
+ const bool is64bits = version >= 7500;
+ const char *end = input + length;
+ while (cursor < end ) {
+ if (!ReadScope(output_tokens, input, cursor, input + length, is64bits)) {
+ break;
+ }
+ }
+}
+
+} // !FBX
+} // !Assimp
+
+#endif
diff --git a/thirdparty/assimp/code/FBXCommon.h b/thirdparty/assimp/code/FBXCommon.h
new file mode 100644
index 0000000000..fcb20a5cad
--- /dev/null
+++ b/thirdparty/assimp/code/FBXCommon.h
@@ -0,0 +1,86 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file FBXCommon.h
+* Some useful constants and enums for dealing with FBX files.
+*/
+#ifndef AI_FBXCOMMON_H_INC
+#define AI_FBXCOMMON_H_INC
+
+#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
+
+
+namespace FBX
+{
+ const std::string NULL_RECORD = { // 13 null bytes
+ '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0'
+ }; // who knows why
+ const std::string SEPARATOR = {'\x00', '\x01'}; // for use inside strings
+ const std::string MAGIC_NODE_TAG = "_$AssimpFbx$"; // from import
+ const int64_t SECOND = 46186158000; // FBX's kTime unit
+
+ // rotation order. We'll probably use EulerXYZ for everything
+ enum RotOrder {
+ RotOrder_EulerXYZ = 0,
+ RotOrder_EulerXZY,
+ RotOrder_EulerYZX,
+ RotOrder_EulerYXZ,
+ RotOrder_EulerZXY,
+ RotOrder_EulerZYX,
+
+ RotOrder_SphericXYZ,
+
+ RotOrder_MAX // end-of-enum sentinel
+ };
+
+ // transformation inheritance method. Most of the time RSrs
+ enum TransformInheritance {
+ TransformInheritance_RrSs = 0,
+ TransformInheritance_RSrs,
+ TransformInheritance_Rrs,
+
+ TransformInheritance_MAX // end-of-enum sentinel
+ };
+}
+
+#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
+
+#endif // AI_FBXCOMMON_H_INC
diff --git a/thirdparty/assimp/code/FBXCompileConfig.h b/thirdparty/assimp/code/FBXCompileConfig.h
new file mode 100644
index 0000000000..3a3841fa5b
--- /dev/null
+++ b/thirdparty/assimp/code/FBXCompileConfig.h
@@ -0,0 +1,70 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file FBXCompileConfig.h
+ * @brief FBX importer compile-time switches
+ */
+#ifndef INCLUDED_AI_FBX_COMPILECONFIG_H
+#define INCLUDED_AI_FBX_COMPILECONFIG_H
+
+#include <map>
+
+//
+#if _MSC_VER > 1500 || (defined __GNUC___)
+# define ASSIMP_FBX_USE_UNORDERED_MULTIMAP
+# else
+# define fbx_unordered_map map
+# define fbx_unordered_multimap multimap
+#endif
+
+#ifdef ASSIMP_FBX_USE_UNORDERED_MULTIMAP
+# include <unordered_map>
+# if _MSC_VER > 1600
+# define fbx_unordered_map unordered_map
+# define fbx_unordered_multimap unordered_multimap
+# else
+# define fbx_unordered_map tr1::unordered_map
+# define fbx_unordered_multimap tr1::unordered_multimap
+# endif
+#endif
+
+#endif // INCLUDED_AI_FBX_COMPILECONFIG_H
diff --git a/thirdparty/assimp/code/FBXConverter.cpp b/thirdparty/assimp/code/FBXConverter.cpp
new file mode 100644
index 0000000000..09ae06a64f
--- /dev/null
+++ b/thirdparty/assimp/code/FBXConverter.cpp
@@ -0,0 +1,3536 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file FBXConverter.cpp
+ * @brief Implementation of the FBX DOM -> aiScene converter
+ */
+
+#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
+
+#include "FBXConverter.h"
+#include "FBXParser.h"
+#include "FBXMeshGeometry.h"
+#include "FBXDocument.h"
+#include "FBXUtil.h"
+#include "FBXProperties.h"
+#include "FBXImporter.h"
+
+#include <assimp/StringComparison.h>
+
+#include <assimp/scene.h>
+
+#include <assimp/CreateAnimMesh.h>
+
+#include <tuple>
+#include <memory>
+#include <iterator>
+#include <vector>
+#include <sstream>
+#include <iomanip>
+
+namespace Assimp {
+ namespace FBX {
+
+ using namespace Util;
+
+#define MAGIC_NODE_TAG "_$AssimpFbx$"
+
+#define CONVERT_FBX_TIME(time) static_cast<double>(time) / 46186158000L
+
+ FBXConverter::FBXConverter(aiScene* out, const Document& doc)
+ : defaultMaterialIndex()
+ , lights()
+ , cameras()
+ , textures()
+ , materials_converted()
+ , textures_converted()
+ , meshes_converted()
+ , node_anim_chain_bits()
+ , mNodeNameInstances()
+ , mNodeNames()
+ , anim_fps()
+ , out(out)
+ , doc(doc) {
+ // animations need to be converted first since this will
+ // populate the node_anim_chain_bits map, which is needed
+ // to determine which nodes need to be generated.
+ ConvertAnimations();
+ ConvertRootNode();
+
+ if (doc.Settings().readAllMaterials) {
+ // unfortunately this means we have to evaluate all objects
+ for (const ObjectMap::value_type& v : doc.Objects()) {
+
+ const Object* ob = v.second->Get();
+ if (!ob) {
+ continue;
+ }
+
+ const Material* mat = dynamic_cast<const Material*>(ob);
+ if (mat) {
+
+ if (materials_converted.find(mat) == materials_converted.end()) {
+ ConvertMaterial(*mat, 0);
+ }
+ }
+ }
+ }
+
+ ConvertGlobalSettings();
+ TransferDataToScene();
+
+ // if we didn't read any meshes set the AI_SCENE_FLAGS_INCOMPLETE
+ // to make sure the scene passes assimp's validation. FBX files
+ // need not contain geometry (i.e. camera animations, raw armatures).
+ if (out->mNumMeshes == 0) {
+ out->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
+ }
+ }
+
+
+ FBXConverter::~FBXConverter() {
+ std::for_each(meshes.begin(), meshes.end(), Util::delete_fun<aiMesh>());
+ std::for_each(materials.begin(), materials.end(), Util::delete_fun<aiMaterial>());
+ std::for_each(animations.begin(), animations.end(), Util::delete_fun<aiAnimation>());
+ std::for_each(lights.begin(), lights.end(), Util::delete_fun<aiLight>());
+ std::for_each(cameras.begin(), cameras.end(), Util::delete_fun<aiCamera>());
+ std::for_each(textures.begin(), textures.end(), Util::delete_fun<aiTexture>());
+ }
+
+ void FBXConverter::ConvertRootNode() {
+ out->mRootNode = new aiNode();
+ out->mRootNode->mName.Set("RootNode");
+
+ // root has ID 0
+ ConvertNodes(0L, *out->mRootNode);
+ }
+
+ void FBXConverter::ConvertNodes(uint64_t id, aiNode& parent, const aiMatrix4x4& parent_transform) {
+ const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(id, "Model");
+
+ std::vector<aiNode*> nodes;
+ nodes.reserve(conns.size());
+
+ std::vector<aiNode*> nodes_chain;
+ std::vector<aiNode*> post_nodes_chain;
+
+ try {
+ for (const Connection* con : conns) {
+
+ // ignore object-property links
+ if (con->PropertyName().length()) {
+ continue;
+ }
+
+ const Object* const object = con->SourceObject();
+ if (nullptr == object) {
+ FBXImporter::LogWarn("failed to convert source object for Model link");
+ continue;
+ }
+
+ const Model* const model = dynamic_cast<const Model*>(object);
+
+ if (nullptr != model) {
+ nodes_chain.clear();
+ post_nodes_chain.clear();
+
+ aiMatrix4x4 new_abs_transform = parent_transform;
+
+ // even though there is only a single input node, the design of
+ // assimp (or rather: the complicated transformation chain that
+ // is employed by fbx) means that we may need multiple aiNode's
+ // to represent a fbx node's transformation.
+ GenerateTransformationNodeChain(*model, nodes_chain, post_nodes_chain);
+
+ ai_assert(nodes_chain.size());
+
+ std::string original_name = FixNodeName(model->Name());
+
+ // check if any of the nodes in the chain has the name the fbx node
+ // is supposed to have. If there is none, add another node to
+ // preserve the name - people might have scripts etc. that rely
+ // on specific node names.
+ aiNode* name_carrier = NULL;
+ for (aiNode* prenode : nodes_chain) {
+ if (!strcmp(prenode->mName.C_Str(), original_name.c_str())) {
+ name_carrier = prenode;
+ break;
+ }
+ }
+
+ if (!name_carrier) {
+ std::string old_original_name = original_name;
+ GetUniqueName(old_original_name, original_name);
+ nodes_chain.push_back(new aiNode(original_name));
+ }
+ else {
+ original_name = nodes_chain.back()->mName.C_Str();
+ }
+
+ //setup metadata on newest node
+ SetupNodeMetadata(*model, *nodes_chain.back());
+
+ // link all nodes in a row
+ aiNode* last_parent = &parent;
+ for (aiNode* prenode : nodes_chain) {
+ ai_assert(prenode);
+
+ if (last_parent != &parent) {
+ last_parent->mNumChildren = 1;
+ last_parent->mChildren = new aiNode*[1];
+ last_parent->mChildren[0] = prenode;
+ }
+
+ prenode->mParent = last_parent;
+ last_parent = prenode;
+
+ new_abs_transform *= prenode->mTransformation;
+ }
+
+ // attach geometry
+ ConvertModel(*model, *nodes_chain.back(), new_abs_transform);
+
+ // check if there will be any child nodes
+ const std::vector<const Connection*>& child_conns
+ = doc.GetConnectionsByDestinationSequenced(model->ID(), "Model");
+
+ // if so, link the geometric transform inverse nodes
+ // before we attach any child nodes
+ if (child_conns.size()) {
+ for (aiNode* postnode : post_nodes_chain) {
+ ai_assert(postnode);
+
+ if (last_parent != &parent) {
+ last_parent->mNumChildren = 1;
+ last_parent->mChildren = new aiNode*[1];
+ last_parent->mChildren[0] = postnode;
+ }
+
+ postnode->mParent = last_parent;
+ last_parent = postnode;
+
+ new_abs_transform *= postnode->mTransformation;
+ }
+ }
+ else {
+ // free the nodes we allocated as we don't need them
+ Util::delete_fun<aiNode> deleter;
+ std::for_each(
+ post_nodes_chain.begin(),
+ post_nodes_chain.end(),
+ deleter
+ );
+ }
+
+ // attach sub-nodes (if any)
+ ConvertNodes(model->ID(), *last_parent, new_abs_transform);
+
+ if (doc.Settings().readLights) {
+ ConvertLights(*model, original_name);
+ }
+
+ if (doc.Settings().readCameras) {
+ ConvertCameras(*model, original_name);
+ }
+
+ nodes.push_back(nodes_chain.front());
+ nodes_chain.clear();
+ }
+ }
+
+ if (nodes.size()) {
+ parent.mChildren = new aiNode*[nodes.size()]();
+ parent.mNumChildren = static_cast<unsigned int>(nodes.size());
+
+ std::swap_ranges(nodes.begin(), nodes.end(), parent.mChildren);
+ }
+ }
+ catch (std::exception&) {
+ Util::delete_fun<aiNode> deleter;
+ std::for_each(nodes.begin(), nodes.end(), deleter);
+ std::for_each(nodes_chain.begin(), nodes_chain.end(), deleter);
+ std::for_each(post_nodes_chain.begin(), post_nodes_chain.end(), deleter);
+ }
+ }
+
+
+ void FBXConverter::ConvertLights(const Model& model, const std::string &orig_name) {
+ const std::vector<const NodeAttribute*>& node_attrs = model.GetAttributes();
+ for (const NodeAttribute* attr : node_attrs) {
+ const Light* const light = dynamic_cast<const Light*>(attr);
+ if (light) {
+ ConvertLight(*light, orig_name);
+ }
+ }
+ }
+
+ void FBXConverter::ConvertCameras(const Model& model, const std::string &orig_name) {
+ const std::vector<const NodeAttribute*>& node_attrs = model.GetAttributes();
+ for (const NodeAttribute* attr : node_attrs) {
+ const Camera* const cam = dynamic_cast<const Camera*>(attr);
+ if (cam) {
+ ConvertCamera(*cam, orig_name);
+ }
+ }
+ }
+
+ void FBXConverter::ConvertLight(const Light& light, const std::string &orig_name) {
+ lights.push_back(new aiLight());
+ aiLight* const out_light = lights.back();
+
+ out_light->mName.Set(orig_name);
+
+ const float intensity = light.Intensity() / 100.0f;
+ const aiVector3D& col = light.Color();
+
+ out_light->mColorDiffuse = aiColor3D(col.x, col.y, col.z);
+ out_light->mColorDiffuse.r *= intensity;
+ out_light->mColorDiffuse.g *= intensity;
+ out_light->mColorDiffuse.b *= intensity;
+
+ out_light->mColorSpecular = out_light->mColorDiffuse;
+
+ //lights are defined along negative y direction
+ out_light->mPosition = aiVector3D(0.0f);
+ out_light->mDirection = aiVector3D(0.0f, -1.0f, 0.0f);
+ out_light->mUp = aiVector3D(0.0f, 0.0f, -1.0f);
+
+ switch (light.LightType())
+ {
+ case Light::Type_Point:
+ out_light->mType = aiLightSource_POINT;
+ break;
+
+ case Light::Type_Directional:
+ out_light->mType = aiLightSource_DIRECTIONAL;
+ break;
+
+ case Light::Type_Spot:
+ out_light->mType = aiLightSource_SPOT;
+ out_light->mAngleOuterCone = AI_DEG_TO_RAD(light.OuterAngle());
+ out_light->mAngleInnerCone = AI_DEG_TO_RAD(light.InnerAngle());
+ break;
+
+ case Light::Type_Area:
+ FBXImporter::LogWarn("cannot represent area light, set to UNDEFINED");
+ out_light->mType = aiLightSource_UNDEFINED;
+ break;
+
+ case Light::Type_Volume:
+ FBXImporter::LogWarn("cannot represent volume light, set to UNDEFINED");
+ out_light->mType = aiLightSource_UNDEFINED;
+ break;
+ default:
+ ai_assert(false);
+ }
+
+ float decay = light.DecayStart();
+ switch (light.DecayType())
+ {
+ case Light::Decay_None:
+ out_light->mAttenuationConstant = decay;
+ out_light->mAttenuationLinear = 0.0f;
+ out_light->mAttenuationQuadratic = 0.0f;
+ break;
+ case Light::Decay_Linear:
+ out_light->mAttenuationConstant = 0.0f;
+ out_light->mAttenuationLinear = 2.0f / decay;
+ out_light->mAttenuationQuadratic = 0.0f;
+ break;
+ case Light::Decay_Quadratic:
+ out_light->mAttenuationConstant = 0.0f;
+ out_light->mAttenuationLinear = 0.0f;
+ out_light->mAttenuationQuadratic = 2.0f / (decay * decay);
+ break;
+ case Light::Decay_Cubic:
+ FBXImporter::LogWarn("cannot represent cubic attenuation, set to Quadratic");
+ out_light->mAttenuationQuadratic = 1.0f;
+ break;
+ default:
+ ai_assert(false);
+ }
+ }
+
+ void FBXConverter::ConvertCamera(const Camera& cam, const std::string &orig_name)
+ {
+ cameras.push_back(new aiCamera());
+ aiCamera* const out_camera = cameras.back();
+
+ out_camera->mName.Set(orig_name);
+
+ out_camera->mAspect = cam.AspectWidth() / cam.AspectHeight();
+
+ //cameras are defined along positive x direction
+ /*out_camera->mPosition = cam.Position();
+ out_camera->mLookAt = (cam.InterestPosition() - out_camera->mPosition).Normalize();
+ out_camera->mUp = cam.UpVector();*/
+
+ out_camera->mPosition = aiVector3D(0.0f);
+ out_camera->mLookAt = aiVector3D(1.0f, 0.0f, 0.0f);
+ out_camera->mUp = aiVector3D(0.0f, 1.0f, 0.0f);
+
+ out_camera->mHorizontalFOV = AI_DEG_TO_RAD(cam.FieldOfView());
+
+ out_camera->mClipPlaneNear = cam.NearPlane();
+ out_camera->mClipPlaneFar = cam.FarPlane();
+
+ out_camera->mHorizontalFOV = AI_DEG_TO_RAD(cam.FieldOfView());
+ out_camera->mClipPlaneNear = cam.NearPlane();
+ out_camera->mClipPlaneFar = cam.FarPlane();
+ }
+
+ void FBXConverter::GetUniqueName(const std::string &name, std::string &uniqueName)
+ {
+ uniqueName = name;
+ int i = 0;
+ auto it = mNodeNameInstances.find(name); // duplicate node name instance count
+ if (it != mNodeNameInstances.end())
+ {
+ i = it->second;
+ while (mNodeNames.find(uniqueName) != mNodeNames.end())
+ {
+ i++;
+ std::stringstream ext;
+ ext << name << std::setfill('0') << std::setw(3) << i;
+ uniqueName = ext.str();
+ }
+ }
+ mNodeNameInstances[name] = i;
+ mNodeNames.insert(uniqueName);
+ }
+
+ const char* FBXConverter::NameTransformationComp(TransformationComp comp) {
+ switch (comp) {
+ case TransformationComp_Translation:
+ return "Translation";
+ case TransformationComp_RotationOffset:
+ return "RotationOffset";
+ case TransformationComp_RotationPivot:
+ return "RotationPivot";
+ case TransformationComp_PreRotation:
+ return "PreRotation";
+ case TransformationComp_Rotation:
+ return "Rotation";
+ case TransformationComp_PostRotation:
+ return "PostRotation";
+ case TransformationComp_RotationPivotInverse:
+ return "RotationPivotInverse";
+ case TransformationComp_ScalingOffset:
+ return "ScalingOffset";
+ case TransformationComp_ScalingPivot:
+ return "ScalingPivot";
+ case TransformationComp_Scaling:
+ return "Scaling";
+ case TransformationComp_ScalingPivotInverse:
+ return "ScalingPivotInverse";
+ case TransformationComp_GeometricScaling:
+ return "GeometricScaling";
+ case TransformationComp_GeometricRotation:
+ return "GeometricRotation";
+ case TransformationComp_GeometricTranslation:
+ return "GeometricTranslation";
+ case TransformationComp_GeometricScalingInverse:
+ return "GeometricScalingInverse";
+ case TransformationComp_GeometricRotationInverse:
+ return "GeometricRotationInverse";
+ case TransformationComp_GeometricTranslationInverse:
+ return "GeometricTranslationInverse";
+ case TransformationComp_MAXIMUM: // this is to silence compiler warnings
+ default:
+ break;
+ }
+
+ ai_assert(false);
+
+ return nullptr;
+ }
+
+ const char* FBXConverter::NameTransformationCompProperty(TransformationComp comp) {
+ switch (comp) {
+ case TransformationComp_Translation:
+ return "Lcl Translation";
+ case TransformationComp_RotationOffset:
+ return "RotationOffset";
+ case TransformationComp_RotationPivot:
+ return "RotationPivot";
+ case TransformationComp_PreRotation:
+ return "PreRotation";
+ case TransformationComp_Rotation:
+ return "Lcl Rotation";
+ case TransformationComp_PostRotation:
+ return "PostRotation";
+ case TransformationComp_RotationPivotInverse:
+ return "RotationPivotInverse";
+ case TransformationComp_ScalingOffset:
+ return "ScalingOffset";
+ case TransformationComp_ScalingPivot:
+ return "ScalingPivot";
+ case TransformationComp_Scaling:
+ return "Lcl Scaling";
+ case TransformationComp_ScalingPivotInverse:
+ return "ScalingPivotInverse";
+ case TransformationComp_GeometricScaling:
+ return "GeometricScaling";
+ case TransformationComp_GeometricRotation:
+ return "GeometricRotation";
+ case TransformationComp_GeometricTranslation:
+ return "GeometricTranslation";
+ case TransformationComp_GeometricScalingInverse:
+ return "GeometricScalingInverse";
+ case TransformationComp_GeometricRotationInverse:
+ return "GeometricRotationInverse";
+ case TransformationComp_GeometricTranslationInverse:
+ return "GeometricTranslationInverse";
+ case TransformationComp_MAXIMUM: // this is to silence compiler warnings
+ break;
+ }
+
+ ai_assert(false);
+
+ return nullptr;
+ }
+
+ aiVector3D FBXConverter::TransformationCompDefaultValue(TransformationComp comp)
+ {
+ // XXX a neat way to solve the never-ending special cases for scaling
+ // would be to do everything in log space!
+ return comp == TransformationComp_Scaling ? aiVector3D(1.f, 1.f, 1.f) : aiVector3D();
+ }
+
+ void FBXConverter::GetRotationMatrix(Model::RotOrder mode, const aiVector3D& rotation, aiMatrix4x4& out)
+ {
+ if (mode == Model::RotOrder_SphericXYZ) {
+ FBXImporter::LogError("Unsupported RotationMode: SphericXYZ");
+ out = aiMatrix4x4();
+ return;
+ }
+
+ const float angle_epsilon = 1e-6f;
+
+ out = aiMatrix4x4();
+
+ bool is_id[3] = { true, true, true };
+
+ aiMatrix4x4 temp[3];
+ if (std::fabs(rotation.z) > angle_epsilon) {
+ aiMatrix4x4::RotationZ(AI_DEG_TO_RAD(rotation.z), temp[2]);
+ is_id[2] = false;
+ }
+ if (std::fabs(rotation.y) > angle_epsilon) {
+ aiMatrix4x4::RotationY(AI_DEG_TO_RAD(rotation.y), temp[1]);
+ is_id[1] = false;
+ }
+ if (std::fabs(rotation.x) > angle_epsilon) {
+ aiMatrix4x4::RotationX(AI_DEG_TO_RAD(rotation.x), temp[0]);
+ is_id[0] = false;
+ }
+
+ int order[3] = { -1, -1, -1 };
+
+ // note: rotation order is inverted since we're left multiplying as is usual in assimp
+ switch (mode)
+ {
+ case Model::RotOrder_EulerXYZ:
+ order[0] = 2;
+ order[1] = 1;
+ order[2] = 0;
+ break;
+
+ case Model::RotOrder_EulerXZY:
+ order[0] = 1;
+ order[1] = 2;
+ order[2] = 0;
+ break;
+
+ case Model::RotOrder_EulerYZX:
+ order[0] = 0;
+ order[1] = 2;
+ order[2] = 1;
+ break;
+
+ case Model::RotOrder_EulerYXZ:
+ order[0] = 2;
+ order[1] = 0;
+ order[2] = 1;
+ break;
+
+ case Model::RotOrder_EulerZXY:
+ order[0] = 1;
+ order[1] = 0;
+ order[2] = 2;
+ break;
+
+ case Model::RotOrder_EulerZYX:
+ order[0] = 0;
+ order[1] = 1;
+ order[2] = 2;
+ break;
+
+ default:
+ ai_assert(false);
+ break;
+ }
+
+ ai_assert(order[0] >= 0);
+ ai_assert(order[0] <= 2);
+ ai_assert(order[1] >= 0);
+ ai_assert(order[1] <= 2);
+ ai_assert(order[2] >= 0);
+ ai_assert(order[2] <= 2);
+
+ if (!is_id[order[0]]) {
+ out = temp[order[0]];
+ }
+
+ if (!is_id[order[1]]) {
+ out = out * temp[order[1]];
+ }
+
+ if (!is_id[order[2]]) {
+ out = out * temp[order[2]];
+ }
+ }
+
+ bool FBXConverter::NeedsComplexTransformationChain(const Model& model)
+ {
+ const PropertyTable& props = model.Props();
+ bool ok;
+
+ const float zero_epsilon = 1e-6f;
+ const aiVector3D all_ones(1.0f, 1.0f, 1.0f);
+ for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i) {
+ const TransformationComp comp = static_cast<TransformationComp>(i);
+
+ if (comp == TransformationComp_Rotation || comp == TransformationComp_Scaling || comp == TransformationComp_Translation) {
+ continue;
+ }
+
+ bool scale_compare = (comp == TransformationComp_GeometricScaling || comp == TransformationComp_Scaling);
+
+ const aiVector3D& v = PropertyGet<aiVector3D>(props, NameTransformationCompProperty(comp), ok);
+ if (ok && scale_compare) {
+ if ((v - all_ones).SquareLength() > zero_epsilon) {
+ return true;
+ }
+ }
+ else if (ok) {
+ if (v.SquareLength() > zero_epsilon) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ std::string FBXConverter::NameTransformationChainNode(const std::string& name, TransformationComp comp)
+ {
+ return name + std::string(MAGIC_NODE_TAG) + "_" + NameTransformationComp(comp);
+ }
+
+ void FBXConverter::GenerateTransformationNodeChain(const Model& model, std::vector<aiNode*>& output_nodes,
+ std::vector<aiNode*>& post_output_nodes) {
+ const PropertyTable& props = model.Props();
+ const Model::RotOrder rot = model.RotationOrder();
+
+ bool ok;
+
+ aiMatrix4x4 chain[TransformationComp_MAXIMUM];
+ std::fill_n(chain, static_cast<unsigned int>(TransformationComp_MAXIMUM), aiMatrix4x4());
+
+ // generate transformation matrices for all the different transformation components
+ const float zero_epsilon = 1e-6f;
+ const aiVector3D all_ones(1.0f, 1.0f, 1.0f);
+ bool is_complex = false;
+
+ const aiVector3D& PreRotation = PropertyGet<aiVector3D>(props, "PreRotation", ok);
+ if (ok && PreRotation.SquareLength() > zero_epsilon) {
+ is_complex = true;
+
+ GetRotationMatrix(Model::RotOrder::RotOrder_EulerXYZ, PreRotation, chain[TransformationComp_PreRotation]);
+ }
+
+ const aiVector3D& PostRotation = PropertyGet<aiVector3D>(props, "PostRotation", ok);
+ if (ok && PostRotation.SquareLength() > zero_epsilon) {
+ is_complex = true;
+
+ GetRotationMatrix(Model::RotOrder::RotOrder_EulerXYZ, PostRotation, chain[TransformationComp_PostRotation]);
+ }
+
+ const aiVector3D& RotationPivot = PropertyGet<aiVector3D>(props, "RotationPivot", ok);
+ if (ok && RotationPivot.SquareLength() > zero_epsilon) {
+ is_complex = true;
+
+ aiMatrix4x4::Translation(RotationPivot, chain[TransformationComp_RotationPivot]);
+ aiMatrix4x4::Translation(-RotationPivot, chain[TransformationComp_RotationPivotInverse]);
+ }
+
+ const aiVector3D& RotationOffset = PropertyGet<aiVector3D>(props, "RotationOffset", ok);
+ if (ok && RotationOffset.SquareLength() > zero_epsilon) {
+ is_complex = true;
+
+ aiMatrix4x4::Translation(RotationOffset, chain[TransformationComp_RotationOffset]);
+ }
+
+ const aiVector3D& ScalingOffset = PropertyGet<aiVector3D>(props, "ScalingOffset", ok);
+ if (ok && ScalingOffset.SquareLength() > zero_epsilon) {
+ is_complex = true;
+
+ aiMatrix4x4::Translation(ScalingOffset, chain[TransformationComp_ScalingOffset]);
+ }
+
+ const aiVector3D& ScalingPivot = PropertyGet<aiVector3D>(props, "ScalingPivot", ok);
+ if (ok && ScalingPivot.SquareLength() > zero_epsilon) {
+ is_complex = true;
+
+ aiMatrix4x4::Translation(ScalingPivot, chain[TransformationComp_ScalingPivot]);
+ aiMatrix4x4::Translation(-ScalingPivot, chain[TransformationComp_ScalingPivotInverse]);
+ }
+
+ const aiVector3D& Translation = PropertyGet<aiVector3D>(props, "Lcl Translation", ok);
+ if (ok && Translation.SquareLength() > zero_epsilon) {
+ aiMatrix4x4::Translation(Translation, chain[TransformationComp_Translation]);
+ }
+
+ const aiVector3D& Scaling = PropertyGet<aiVector3D>(props, "Lcl Scaling", ok);
+ if (ok && (Scaling - all_ones).SquareLength() > zero_epsilon) {
+ aiMatrix4x4::Scaling(Scaling, chain[TransformationComp_Scaling]);
+ }
+
+ const aiVector3D& Rotation = PropertyGet<aiVector3D>(props, "Lcl Rotation", ok);
+ if (ok && Rotation.SquareLength() > zero_epsilon) {
+ GetRotationMatrix(rot, Rotation, chain[TransformationComp_Rotation]);
+ }
+
+ const aiVector3D& GeometricScaling = PropertyGet<aiVector3D>(props, "GeometricScaling", ok);
+ if (ok && (GeometricScaling - all_ones).SquareLength() > zero_epsilon) {
+ is_complex = true;
+ aiMatrix4x4::Scaling(GeometricScaling, chain[TransformationComp_GeometricScaling]);
+ aiVector3D GeometricScalingInverse = GeometricScaling;
+ bool canscale = true;
+ for (unsigned int i = 0; i < 3; ++i) {
+ if (std::fabs(GeometricScalingInverse[i]) > zero_epsilon) {
+ GeometricScalingInverse[i] = 1.0f / GeometricScaling[i];
+ }
+ else {
+ FBXImporter::LogError("cannot invert geometric scaling matrix with a 0.0 scale component");
+ canscale = false;
+ break;
+ }
+ }
+ if (canscale) {
+ aiMatrix4x4::Scaling(GeometricScalingInverse, chain[TransformationComp_GeometricScalingInverse]);
+ }
+ }
+
+ const aiVector3D& GeometricRotation = PropertyGet<aiVector3D>(props, "GeometricRotation", ok);
+ if (ok && GeometricRotation.SquareLength() > zero_epsilon) {
+ is_complex = true;
+ GetRotationMatrix(rot, GeometricRotation, chain[TransformationComp_GeometricRotation]);
+ GetRotationMatrix(rot, GeometricRotation, chain[TransformationComp_GeometricRotationInverse]);
+ chain[TransformationComp_GeometricRotationInverse].Inverse();
+ }
+
+ const aiVector3D& GeometricTranslation = PropertyGet<aiVector3D>(props, "GeometricTranslation", ok);
+ if (ok && GeometricTranslation.SquareLength() > zero_epsilon) {
+ is_complex = true;
+ aiMatrix4x4::Translation(GeometricTranslation, chain[TransformationComp_GeometricTranslation]);
+ aiMatrix4x4::Translation(-GeometricTranslation, chain[TransformationComp_GeometricTranslationInverse]);
+ }
+
+ // is_complex needs to be consistent with NeedsComplexTransformationChain()
+ // or the interplay between this code and the animation converter would
+ // not be guaranteed.
+ ai_assert(NeedsComplexTransformationChain(model) == is_complex);
+
+ std::string name = FixNodeName(model.Name());
+
+ // now, if we have more than just Translation, Scaling and Rotation,
+ // we need to generate a full node chain to accommodate for assimp's
+ // lack to express pivots and offsets.
+ if (is_complex && doc.Settings().preservePivots) {
+ FBXImporter::LogInfo("generating full transformation chain for node: " + name);
+
+ // query the anim_chain_bits dictionary to find out which chain elements
+ // have associated node animation channels. These can not be dropped
+ // even if they have identity transform in bind pose.
+ NodeAnimBitMap::const_iterator it = node_anim_chain_bits.find(name);
+ const unsigned int anim_chain_bitmask = (it == node_anim_chain_bits.end() ? 0 : (*it).second);
+
+ unsigned int bit = 0x1;
+ for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i, bit <<= 1) {
+ const TransformationComp comp = static_cast<TransformationComp>(i);
+
+ if (chain[i].IsIdentity() && (anim_chain_bitmask & bit) == 0) {
+ continue;
+ }
+
+ if (comp == TransformationComp_PostRotation) {
+ chain[i] = chain[i].Inverse();
+ }
+
+ aiNode* nd = new aiNode();
+ nd->mName.Set(NameTransformationChainNode(name, comp));
+ nd->mTransformation = chain[i];
+
+ // geometric inverses go in a post-node chain
+ if (comp == TransformationComp_GeometricScalingInverse ||
+ comp == TransformationComp_GeometricRotationInverse ||
+ comp == TransformationComp_GeometricTranslationInverse
+ ) {
+ post_output_nodes.push_back(nd);
+ }
+ else {
+ output_nodes.push_back(nd);
+ }
+ }
+
+ ai_assert(output_nodes.size());
+ return;
+ }
+
+ // else, we can just multiply the matrices together
+ aiNode* nd = new aiNode();
+ output_nodes.push_back(nd);
+ std::string uniqueName;
+ GetUniqueName(name, uniqueName);
+
+ nd->mName.Set(uniqueName);
+
+ for (const auto &transform : chain) {
+ nd->mTransformation = nd->mTransformation * transform;
+ }
+ }
+
+ void FBXConverter::SetupNodeMetadata(const Model& model, aiNode& nd)
+ {
+ const PropertyTable& props = model.Props();
+ DirectPropertyMap unparsedProperties = props.GetUnparsedProperties();
+
+ // create metadata on node
+ const std::size_t numStaticMetaData = 2;
+ aiMetadata* data = aiMetadata::Alloc(static_cast<unsigned int>(unparsedProperties.size() + numStaticMetaData));
+ nd.mMetaData = data;
+ int index = 0;
+
+ // find user defined properties (3ds Max)
+ data->Set(index++, "UserProperties", aiString(PropertyGet<std::string>(props, "UDP3DSMAX", "")));
+ // preserve the info that a node was marked as Null node in the original file.
+ data->Set(index++, "IsNull", model.IsNull() ? true : false);
+
+ // add unparsed properties to the node's metadata
+ for (const DirectPropertyMap::value_type& prop : unparsedProperties) {
+ // Interpret the property as a concrete type
+ if (const TypedProperty<bool>* interpreted = prop.second->As<TypedProperty<bool> >()) {
+ data->Set(index++, prop.first, interpreted->Value());
+ }
+ else if (const TypedProperty<int>* interpreted = prop.second->As<TypedProperty<int> >()) {
+ data->Set(index++, prop.first, interpreted->Value());
+ }
+ else if (const TypedProperty<uint64_t>* interpreted = prop.second->As<TypedProperty<uint64_t> >()) {
+ data->Set(index++, prop.first, interpreted->Value());
+ }
+ else if (const TypedProperty<float>* interpreted = prop.second->As<TypedProperty<float> >()) {
+ data->Set(index++, prop.first, interpreted->Value());
+ }
+ else if (const TypedProperty<std::string>* interpreted = prop.second->As<TypedProperty<std::string> >()) {
+ data->Set(index++, prop.first, aiString(interpreted->Value()));
+ }
+ else if (const TypedProperty<aiVector3D>* interpreted = prop.second->As<TypedProperty<aiVector3D> >()) {
+ data->Set(index++, prop.first, interpreted->Value());
+ }
+ else {
+ ai_assert(false);
+ }
+ }
+ }
+
+ void FBXConverter::ConvertModel(const Model& model, aiNode& nd, const aiMatrix4x4& node_global_transform)
+ {
+ const std::vector<const Geometry*>& geos = model.GetGeometry();
+
+ std::vector<unsigned int> meshes;
+ meshes.reserve(geos.size());
+
+ for (const Geometry* geo : geos) {
+
+ const MeshGeometry* const mesh = dynamic_cast<const MeshGeometry*>(geo);
+ const LineGeometry* const line = dynamic_cast<const LineGeometry*>(geo);
+ if (mesh) {
+ const std::vector<unsigned int>& indices = ConvertMesh(*mesh, model, node_global_transform, nd);
+ std::copy(indices.begin(), indices.end(), std::back_inserter(meshes));
+ }
+ else if (line) {
+ const std::vector<unsigned int>& indices = ConvertLine(*line, model, node_global_transform, nd);
+ std::copy(indices.begin(), indices.end(), std::back_inserter(meshes));
+ }
+ else {
+ FBXImporter::LogWarn("ignoring unrecognized geometry: " + geo->Name());
+ }
+ }
+
+ if (meshes.size()) {
+ nd.mMeshes = new unsigned int[meshes.size()]();
+ nd.mNumMeshes = static_cast<unsigned int>(meshes.size());
+
+ std::swap_ranges(meshes.begin(), meshes.end(), nd.mMeshes);
+ }
+ }
+
+ std::vector<unsigned int> FBXConverter::ConvertMesh(const MeshGeometry& mesh, const Model& model,
+ const aiMatrix4x4& node_global_transform, aiNode& nd)
+ {
+ std::vector<unsigned int> temp;
+
+ MeshMap::const_iterator it = meshes_converted.find(&mesh);
+ if (it != meshes_converted.end()) {
+ std::copy((*it).second.begin(), (*it).second.end(), std::back_inserter(temp));
+ return temp;
+ }
+
+ const std::vector<aiVector3D>& vertices = mesh.GetVertices();
+ const std::vector<unsigned int>& faces = mesh.GetFaceIndexCounts();
+ if (vertices.empty() || faces.empty()) {
+ FBXImporter::LogWarn("ignoring empty geometry: " + mesh.Name());
+ return temp;
+ }
+
+ // one material per mesh maps easily to aiMesh. Multiple material
+ // meshes need to be split.
+ const MatIndexArray& mindices = mesh.GetMaterialIndices();
+ if (doc.Settings().readMaterials && !mindices.empty()) {
+ const MatIndexArray::value_type base = mindices[0];
+ for (MatIndexArray::value_type index : mindices) {
+ if (index != base) {
+ return ConvertMeshMultiMaterial(mesh, model, node_global_transform, nd);
+ }
+ }
+ }
+
+ // faster code-path, just copy the data
+ temp.push_back(ConvertMeshSingleMaterial(mesh, model, node_global_transform, nd));
+ return temp;
+ }
+
+ std::vector<unsigned int> FBXConverter::ConvertLine(const LineGeometry& line, const Model& model,
+ const aiMatrix4x4& node_global_transform, aiNode& nd)
+ {
+ std::vector<unsigned int> temp;
+
+ const std::vector<aiVector3D>& vertices = line.GetVertices();
+ const std::vector<int>& indices = line.GetIndices();
+ if (vertices.empty() || indices.empty()) {
+ FBXImporter::LogWarn("ignoring empty line: " + line.Name());
+ return temp;
+ }
+
+ aiMesh* const out_mesh = SetupEmptyMesh(line, nd);
+ out_mesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
+
+ // copy vertices
+ out_mesh->mNumVertices = static_cast<unsigned int>(vertices.size());
+ out_mesh->mVertices = new aiVector3D[out_mesh->mNumVertices];
+ std::copy(vertices.begin(), vertices.end(), out_mesh->mVertices);
+
+ //Number of line segments (faces) is "Number of Points - Number of Endpoints"
+ //N.B.: Endpoints in FbxLine are denoted by negative indices.
+ //If such an Index is encountered, add 1 and multiply by -1 to get the real index.
+ unsigned int epcount = 0;
+ for (unsigned i = 0; i < indices.size(); i++)
+ {
+ if (indices[i] < 0) epcount++;
+ }
+ unsigned int pcount = static_cast<unsigned int>( indices.size() );
+ unsigned int scount = out_mesh->mNumFaces = pcount - epcount;
+
+ aiFace* fac = out_mesh->mFaces = new aiFace[scount]();
+ for (unsigned int i = 0; i < pcount; ++i) {
+ if (indices[i] < 0) continue;
+ aiFace& f = *fac++;
+ f.mNumIndices = 2; //2 == aiPrimitiveType_LINE
+ f.mIndices = new unsigned int[2];
+ f.mIndices[0] = indices[i];
+ int segid = indices[(i + 1 == pcount ? 0 : i + 1)]; //If we have reached he last point, wrap around
+ f.mIndices[1] = (segid < 0 ? (segid + 1)*-1 : segid); //Convert EndPoint Index to normal Index
+ }
+ temp.push_back(static_cast<unsigned int>(meshes.size() - 1));
+ return temp;
+ }
+
+ aiMesh* FBXConverter::SetupEmptyMesh(const Geometry& mesh, aiNode& nd)
+ {
+ aiMesh* const out_mesh = new aiMesh();
+ meshes.push_back(out_mesh);
+ meshes_converted[&mesh].push_back(static_cast<unsigned int>(meshes.size() - 1));
+
+ // set name
+ std::string name = mesh.Name();
+ if (name.substr(0, 10) == "Geometry::") {
+ name = name.substr(10);
+ }
+
+ if (name.length()) {
+ out_mesh->mName.Set(name);
+ }
+ else
+ {
+ out_mesh->mName = nd.mName;
+ }
+
+ return out_mesh;
+ }
+
+ unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry& mesh, const Model& model,
+ const aiMatrix4x4& node_global_transform, aiNode& nd)
+ {
+ const MatIndexArray& mindices = mesh.GetMaterialIndices();
+ aiMesh* const out_mesh = SetupEmptyMesh(mesh, nd);
+
+ const std::vector<aiVector3D>& vertices = mesh.GetVertices();
+ const std::vector<unsigned int>& faces = mesh.GetFaceIndexCounts();
+
+ // copy vertices
+ out_mesh->mNumVertices = static_cast<unsigned int>(vertices.size());
+ out_mesh->mVertices = new aiVector3D[vertices.size()];
+
+ std::copy(vertices.begin(), vertices.end(), out_mesh->mVertices);
+
+ // generate dummy faces
+ out_mesh->mNumFaces = static_cast<unsigned int>(faces.size());
+ aiFace* fac = out_mesh->mFaces = new aiFace[faces.size()]();
+
+ unsigned int cursor = 0;
+ for (unsigned int pcount : faces) {
+ aiFace& f = *fac++;
+ f.mNumIndices = pcount;
+ f.mIndices = new unsigned int[pcount];
+ switch (pcount)
+ {
+ case 1:
+ out_mesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
+ break;
+ case 2:
+ out_mesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
+ break;
+ case 3:
+ out_mesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
+ break;
+ default:
+ out_mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
+ break;
+ }
+ for (unsigned int i = 0; i < pcount; ++i) {
+ f.mIndices[i] = cursor++;
+ }
+ }
+
+ // copy normals
+ const std::vector<aiVector3D>& normals = mesh.GetNormals();
+ if (normals.size()) {
+ ai_assert(normals.size() == vertices.size());
+
+ out_mesh->mNormals = new aiVector3D[vertices.size()];
+ std::copy(normals.begin(), normals.end(), out_mesh->mNormals);
+ }
+
+ // copy tangents - assimp requires both tangents and bitangents (binormals)
+ // to be present, or neither of them. Compute binormals from normals
+ // and tangents if needed.
+ const std::vector<aiVector3D>& tangents = mesh.GetTangents();
+ const std::vector<aiVector3D>* binormals = &mesh.GetBinormals();
+
+ if (tangents.size()) {
+ std::vector<aiVector3D> tempBinormals;
+ if (!binormals->size()) {
+ if (normals.size()) {
+ tempBinormals.resize(normals.size());
+ for (unsigned int i = 0; i < tangents.size(); ++i) {
+ tempBinormals[i] = normals[i] ^ tangents[i];
+ }
+
+ binormals = &tempBinormals;
+ }
+ else {
+ binormals = NULL;
+ }
+ }
+
+ if (binormals) {
+ ai_assert(tangents.size() == vertices.size());
+ ai_assert(binormals->size() == vertices.size());
+
+ out_mesh->mTangents = new aiVector3D[vertices.size()];
+ std::copy(tangents.begin(), tangents.end(), out_mesh->mTangents);
+
+ out_mesh->mBitangents = new aiVector3D[vertices.size()];
+ std::copy(binormals->begin(), binormals->end(), out_mesh->mBitangents);
+ }
+ }
+
+ // copy texture coords
+ for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
+ const std::vector<aiVector2D>& uvs = mesh.GetTextureCoords(i);
+ if (uvs.empty()) {
+ break;
+ }
+
+ aiVector3D* out_uv = out_mesh->mTextureCoords[i] = new aiVector3D[vertices.size()];
+ for (const aiVector2D& v : uvs) {
+ *out_uv++ = aiVector3D(v.x, v.y, 0.0f);
+ }
+
+ out_mesh->mNumUVComponents[i] = 2;
+ }
+
+ // copy vertex colors
+ for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) {
+ const std::vector<aiColor4D>& colors = mesh.GetVertexColors(i);
+ if (colors.empty()) {
+ break;
+ }
+
+ out_mesh->mColors[i] = new aiColor4D[vertices.size()];
+ std::copy(colors.begin(), colors.end(), out_mesh->mColors[i]);
+ }
+
+ if (!doc.Settings().readMaterials || mindices.empty()) {
+ FBXImporter::LogError("no material assigned to mesh, setting default material");
+ out_mesh->mMaterialIndex = GetDefaultMaterial();
+ }
+ else {
+ ConvertMaterialForMesh(out_mesh, model, mesh, mindices[0]);
+ }
+
+ if (doc.Settings().readWeights && mesh.DeformerSkin() != NULL) {
+ ConvertWeights(out_mesh, model, mesh, node_global_transform, NO_MATERIAL_SEPARATION);
+ }
+
+ std::vector<aiAnimMesh*> animMeshes;
+ for (const BlendShape* blendShape : mesh.GetBlendShapes()) {
+ for (const BlendShapeChannel* blendShapeChannel : blendShape->BlendShapeChannels()) {
+ const std::vector<const ShapeGeometry*>& shapeGeometries = blendShapeChannel->GetShapeGeometries();
+ for (size_t i = 0; i < shapeGeometries.size(); i++) {
+ aiAnimMesh *animMesh = aiCreateAnimMesh(out_mesh);
+ const ShapeGeometry* shapeGeometry = shapeGeometries.at(i);
+ const std::vector<aiVector3D>& vertices = shapeGeometry->GetVertices();
+ const std::vector<aiVector3D>& normals = shapeGeometry->GetNormals();
+ const std::vector<unsigned int>& indices = shapeGeometry->GetIndices();
+ animMesh->mName.Set(FixAnimMeshName(shapeGeometry->Name()));
+ for (size_t j = 0; j < indices.size(); j++) {
+ unsigned int index = indices.at(j);
+ aiVector3D vertex = vertices.at(j);
+ aiVector3D normal = normals.at(j);
+ unsigned int count = 0;
+ const unsigned int* outIndices = mesh.ToOutputVertexIndex(index, count);
+ for (unsigned int k = 0; k < count; k++) {
+ unsigned int index = outIndices[k];
+ animMesh->mVertices[index] += vertex;
+ if (animMesh->mNormals != nullptr) {
+ animMesh->mNormals[index] += normal;
+ animMesh->mNormals[index].NormalizeSafe();
+ }
+ }
+ }
+ animMesh->mWeight = shapeGeometries.size() > 1 ? blendShapeChannel->DeformPercent() / 100.0f : 1.0f;
+ animMeshes.push_back(animMesh);
+ }
+ }
+ }
+ const size_t numAnimMeshes = animMeshes.size();
+ if (numAnimMeshes > 0) {
+ out_mesh->mNumAnimMeshes = static_cast<unsigned int>(numAnimMeshes);
+ out_mesh->mAnimMeshes = new aiAnimMesh*[numAnimMeshes];
+ for (size_t i = 0; i < numAnimMeshes; i++) {
+ out_mesh->mAnimMeshes[i] = animMeshes.at(i);
+ }
+ }
+ return static_cast<unsigned int>(meshes.size() - 1);
+ }
+
+ std::vector<unsigned int> FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model,
+ const aiMatrix4x4& node_global_transform, aiNode& nd)
+ {
+ const MatIndexArray& mindices = mesh.GetMaterialIndices();
+ ai_assert(mindices.size());
+
+ std::set<MatIndexArray::value_type> had;
+ std::vector<unsigned int> indices;
+
+ for (MatIndexArray::value_type index : mindices) {
+ if (had.find(index) == had.end()) {
+
+ indices.push_back(ConvertMeshMultiMaterial(mesh, model, index, node_global_transform, nd));
+ had.insert(index);
+ }
+ }
+
+ return indices;
+ }
+
+ unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model,
+ MatIndexArray::value_type index,
+ const aiMatrix4x4& node_global_transform,
+ aiNode& nd)
+ {
+ aiMesh* const out_mesh = SetupEmptyMesh(mesh, nd);
+
+ const MatIndexArray& mindices = mesh.GetMaterialIndices();
+ const std::vector<aiVector3D>& vertices = mesh.GetVertices();
+ const std::vector<unsigned int>& faces = mesh.GetFaceIndexCounts();
+
+ const bool process_weights = doc.Settings().readWeights && mesh.DeformerSkin() != NULL;
+
+ unsigned int count_faces = 0;
+ unsigned int count_vertices = 0;
+
+ // count faces
+ std::vector<unsigned int>::const_iterator itf = faces.begin();
+ for (MatIndexArray::const_iterator it = mindices.begin(),
+ end = mindices.end(); it != end; ++it, ++itf)
+ {
+ if ((*it) != index) {
+ continue;
+ }
+ ++count_faces;
+ count_vertices += *itf;
+ }
+
+ ai_assert(count_faces);
+ ai_assert(count_vertices);
+
+ // mapping from output indices to DOM indexing, needed to resolve weights
+ std::vector<unsigned int> reverseMapping;
+
+ if (process_weights) {
+ reverseMapping.resize(count_vertices);
+ }
+
+ // allocate output data arrays, but don't fill them yet
+ out_mesh->mNumVertices = count_vertices;
+ out_mesh->mVertices = new aiVector3D[count_vertices];
+
+ out_mesh->mNumFaces = count_faces;
+ aiFace* fac = out_mesh->mFaces = new aiFace[count_faces]();
+
+
+ // allocate normals
+ const std::vector<aiVector3D>& normals = mesh.GetNormals();
+ if (normals.size()) {
+ ai_assert(normals.size() == vertices.size());
+ out_mesh->mNormals = new aiVector3D[vertices.size()];
+ }
+
+ // allocate tangents, binormals.
+ const std::vector<aiVector3D>& tangents = mesh.GetTangents();
+ const std::vector<aiVector3D>* binormals = &mesh.GetBinormals();
+ std::vector<aiVector3D> tempBinormals;
+
+ if (tangents.size()) {
+ if (!binormals->size()) {
+ if (normals.size()) {
+ // XXX this computes the binormals for the entire mesh, not only
+ // the part for which we need them.
+ tempBinormals.resize(normals.size());
+ for (unsigned int i = 0; i < tangents.size(); ++i) {
+ tempBinormals[i] = normals[i] ^ tangents[i];
+ }
+
+ binormals = &tempBinormals;
+ }
+ else {
+ binormals = NULL;
+ }
+ }
+
+ if (binormals) {
+ ai_assert(tangents.size() == vertices.size() && binormals->size() == vertices.size());
+
+ out_mesh->mTangents = new aiVector3D[vertices.size()];
+ out_mesh->mBitangents = new aiVector3D[vertices.size()];
+ }
+ }
+
+ // allocate texture coords
+ unsigned int num_uvs = 0;
+ for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i, ++num_uvs) {
+ const std::vector<aiVector2D>& uvs = mesh.GetTextureCoords(i);
+ if (uvs.empty()) {
+ break;
+ }
+
+ out_mesh->mTextureCoords[i] = new aiVector3D[vertices.size()];
+ out_mesh->mNumUVComponents[i] = 2;
+ }
+
+ // allocate vertex colors
+ unsigned int num_vcs = 0;
+ for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i, ++num_vcs) {
+ const std::vector<aiColor4D>& colors = mesh.GetVertexColors(i);
+ if (colors.empty()) {
+ break;
+ }
+
+ out_mesh->mColors[i] = new aiColor4D[vertices.size()];
+ }
+
+ unsigned int cursor = 0, in_cursor = 0;
+
+ itf = faces.begin();
+ for (MatIndexArray::const_iterator it = mindices.begin(), end = mindices.end(); it != end; ++it, ++itf)
+ {
+ const unsigned int pcount = *itf;
+ if ((*it) != index) {
+ in_cursor += pcount;
+ continue;
+ }
+
+ aiFace& f = *fac++;
+
+ f.mNumIndices = pcount;
+ f.mIndices = new unsigned int[pcount];
+ switch (pcount)
+ {
+ case 1:
+ out_mesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
+ break;
+ case 2:
+ out_mesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
+ break;
+ case 3:
+ out_mesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
+ break;
+ default:
+ out_mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
+ break;
+ }
+ for (unsigned int i = 0; i < pcount; ++i, ++cursor, ++in_cursor) {
+ f.mIndices[i] = cursor;
+
+ if (reverseMapping.size()) {
+ reverseMapping[cursor] = in_cursor;
+ }
+
+ out_mesh->mVertices[cursor] = vertices[in_cursor];
+
+ if (out_mesh->mNormals) {
+ out_mesh->mNormals[cursor] = normals[in_cursor];
+ }
+
+ if (out_mesh->mTangents) {
+ out_mesh->mTangents[cursor] = tangents[in_cursor];
+ out_mesh->mBitangents[cursor] = (*binormals)[in_cursor];
+ }
+
+ for (unsigned int j = 0; j < num_uvs; ++j) {
+ const std::vector<aiVector2D>& uvs = mesh.GetTextureCoords(j);
+ out_mesh->mTextureCoords[j][cursor] = aiVector3D(uvs[in_cursor].x, uvs[in_cursor].y, 0.0f);
+ }
+
+ for (unsigned int j = 0; j < num_vcs; ++j) {
+ const std::vector<aiColor4D>& cols = mesh.GetVertexColors(j);
+ out_mesh->mColors[j][cursor] = cols[in_cursor];
+ }
+ }
+ }
+
+ ConvertMaterialForMesh(out_mesh, model, mesh, index);
+
+ if (process_weights) {
+ ConvertWeights(out_mesh, model, mesh, node_global_transform, index, &reverseMapping);
+ }
+
+ return static_cast<unsigned int>(meshes.size() - 1);
+ }
+
+ void FBXConverter::ConvertWeights(aiMesh* out, const Model& model, const MeshGeometry& geo,
+ const aiMatrix4x4& node_global_transform,
+ unsigned int materialIndex,
+ std::vector<unsigned int>* outputVertStartIndices)
+ {
+ ai_assert(geo.DeformerSkin());
+
+ std::vector<size_t> out_indices;
+ std::vector<size_t> index_out_indices;
+ std::vector<size_t> count_out_indices;
+
+ const Skin& sk = *geo.DeformerSkin();
+
+ std::vector<aiBone*> bones;
+ bones.reserve(sk.Clusters().size());
+
+ const bool no_mat_check = materialIndex == NO_MATERIAL_SEPARATION;
+ ai_assert(no_mat_check || outputVertStartIndices);
+
+ try {
+
+ for (const Cluster* cluster : sk.Clusters()) {
+ ai_assert(cluster);
+
+ const WeightIndexArray& indices = cluster->GetIndices();
+
+ if (indices.empty()) {
+ continue;
+ }
+
+ const MatIndexArray& mats = geo.GetMaterialIndices();
+
+ bool ok = false;
+
+ const size_t no_index_sentinel = std::numeric_limits<size_t>::max();
+
+ count_out_indices.clear();
+ index_out_indices.clear();
+ out_indices.clear();
+
+ // now check if *any* of these weights is contained in the output mesh,
+ // taking notes so we don't need to do it twice.
+ for (WeightIndexArray::value_type index : indices) {
+
+ unsigned int count = 0;
+ const unsigned int* const out_idx = geo.ToOutputVertexIndex(index, count);
+ // ToOutputVertexIndex only returns NULL if index is out of bounds
+ // which should never happen
+ ai_assert(out_idx != NULL);
+
+ index_out_indices.push_back(no_index_sentinel);
+ count_out_indices.push_back(0);
+
+ for (unsigned int i = 0; i < count; ++i) {
+ if (no_mat_check || static_cast<size_t>(mats[geo.FaceForVertexIndex(out_idx[i])]) == materialIndex) {
+
+ if (index_out_indices.back() == no_index_sentinel) {
+ index_out_indices.back() = out_indices.size();
+
+ }
+
+ if (no_mat_check) {
+ out_indices.push_back(out_idx[i]);
+ }
+ else {
+ // this extra lookup is in O(logn), so the entire algorithm becomes O(nlogn)
+ const std::vector<unsigned int>::iterator it = std::lower_bound(
+ outputVertStartIndices->begin(),
+ outputVertStartIndices->end(),
+ out_idx[i]
+ );
+
+ out_indices.push_back(std::distance(outputVertStartIndices->begin(), it));
+ }
+
+ ++count_out_indices.back();
+ ok = true;
+ }
+ }
+ }
+
+ // if we found at least one, generate the output bones
+ // XXX this could be heavily simplified by collecting the bone
+ // data in a single step.
+ if (ok) {
+ ConvertCluster(bones, model, *cluster, out_indices, index_out_indices,
+ count_out_indices, node_global_transform);
+ }
+ }
+ }
+ catch (std::exception&) {
+ std::for_each(bones.begin(), bones.end(), Util::delete_fun<aiBone>());
+ throw;
+ }
+
+ if (bones.empty()) {
+ return;
+ }
+
+ out->mBones = new aiBone*[bones.size()]();
+ out->mNumBones = static_cast<unsigned int>(bones.size());
+
+ std::swap_ranges(bones.begin(), bones.end(), out->mBones);
+ }
+
+ void FBXConverter::ConvertCluster(std::vector<aiBone*>& bones, const Model& /*model*/, const Cluster& cl,
+ std::vector<size_t>& out_indices,
+ std::vector<size_t>& index_out_indices,
+ std::vector<size_t>& count_out_indices,
+ const aiMatrix4x4& node_global_transform)
+ {
+
+ aiBone* const bone = new aiBone();
+ bones.push_back(bone);
+
+ bone->mName = FixNodeName(cl.TargetNode()->Name());
+
+ bone->mOffsetMatrix = cl.TransformLink();
+ bone->mOffsetMatrix.Inverse();
+
+ bone->mOffsetMatrix = bone->mOffsetMatrix * node_global_transform;
+
+ bone->mNumWeights = static_cast<unsigned int>(out_indices.size());
+ aiVertexWeight* cursor = bone->mWeights = new aiVertexWeight[out_indices.size()];
+
+ const size_t no_index_sentinel = std::numeric_limits<size_t>::max();
+ const WeightArray& weights = cl.GetWeights();
+
+ const size_t c = index_out_indices.size();
+ for (size_t i = 0; i < c; ++i) {
+ const size_t index_index = index_out_indices[i];
+
+ if (index_index == no_index_sentinel) {
+ continue;
+ }
+
+ const size_t cc = count_out_indices[i];
+ for (size_t j = 0; j < cc; ++j) {
+ aiVertexWeight& out_weight = *cursor++;
+
+ out_weight.mVertexId = static_cast<unsigned int>(out_indices[index_index + j]);
+ out_weight.mWeight = weights[i];
+ }
+ }
+ }
+
+ void FBXConverter::ConvertMaterialForMesh(aiMesh* out, const Model& model, const MeshGeometry& geo,
+ MatIndexArray::value_type materialIndex)
+ {
+ // locate source materials for this mesh
+ const std::vector<const Material*>& mats = model.GetMaterials();
+ if (static_cast<unsigned int>(materialIndex) >= mats.size() || materialIndex < 0) {
+ FBXImporter::LogError("material index out of bounds, setting default material");
+ out->mMaterialIndex = GetDefaultMaterial();
+ return;
+ }
+
+ const Material* const mat = mats[materialIndex];
+ MaterialMap::const_iterator it = materials_converted.find(mat);
+ if (it != materials_converted.end()) {
+ out->mMaterialIndex = (*it).second;
+ return;
+ }
+
+ out->mMaterialIndex = ConvertMaterial(*mat, &geo);
+ materials_converted[mat] = out->mMaterialIndex;
+ }
+
+ unsigned int FBXConverter::GetDefaultMaterial()
+ {
+ if (defaultMaterialIndex) {
+ return defaultMaterialIndex - 1;
+ }
+
+ aiMaterial* out_mat = new aiMaterial();
+ materials.push_back(out_mat);
+
+ const aiColor3D diffuse = aiColor3D(0.8f, 0.8f, 0.8f);
+ out_mat->AddProperty(&diffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
+
+ aiString s;
+ s.Set(AI_DEFAULT_MATERIAL_NAME);
+
+ out_mat->AddProperty(&s, AI_MATKEY_NAME);
+
+ defaultMaterialIndex = static_cast<unsigned int>(materials.size());
+ return defaultMaterialIndex - 1;
+ }
+
+
+ unsigned int FBXConverter::ConvertMaterial(const Material& material, const MeshGeometry* const mesh)
+ {
+ const PropertyTable& props = material.Props();
+
+ // generate empty output material
+ aiMaterial* out_mat = new aiMaterial();
+ materials_converted[&material] = static_cast<unsigned int>(materials.size());
+
+ materials.push_back(out_mat);
+
+ aiString str;
+
+ // strip Material:: prefix
+ std::string name = material.Name();
+ if (name.substr(0, 10) == "Material::") {
+ name = name.substr(10);
+ }
+
+ // set material name if not empty - this could happen
+ // and there should be no key for it in this case.
+ if (name.length()) {
+ str.Set(name);
+ out_mat->AddProperty(&str, AI_MATKEY_NAME);
+ }
+
+ // shading stuff and colors
+ SetShadingPropertiesCommon(out_mat, props);
+ SetShadingPropertiesRaw( out_mat, props, material.Textures(), mesh );
+
+ // texture assignments
+ SetTextureProperties(out_mat, material.Textures(), mesh);
+ SetTextureProperties(out_mat, material.LayeredTextures(), mesh);
+
+ return static_cast<unsigned int>(materials.size() - 1);
+ }
+
+ unsigned int FBXConverter::ConvertVideo(const Video& video)
+ {
+ // generate empty output texture
+ aiTexture* out_tex = new aiTexture();
+ textures.push_back(out_tex);
+
+ // assuming the texture is compressed
+ out_tex->mWidth = static_cast<unsigned int>(video.ContentLength()); // total data size
+ out_tex->mHeight = 0; // fixed to 0
+
+ // steal the data from the Video to avoid an additional copy
+ out_tex->pcData = reinterpret_cast<aiTexel*>(const_cast<Video&>(video).RelinquishContent());
+
+ // try to extract a hint from the file extension
+ const std::string& filename = video.FileName().empty() ? video.RelativeFilename() : video.FileName();
+ std::string ext = BaseImporter::GetExtension(filename);
+
+ if (ext == "jpeg") {
+ ext = "jpg";
+ }
+
+ if (ext.size() <= 3) {
+ memcpy(out_tex->achFormatHint, ext.c_str(), ext.size());
+ }
+
+ out_tex->mFilename.Set(video.FileName().c_str());
+
+ return static_cast<unsigned int>(textures.size() - 1);
+ }
+
+ aiString FBXConverter::GetTexturePath(const Texture* tex)
+ {
+ aiString path;
+ path.Set(tex->RelativeFilename());
+
+ const Video* media = tex->Media();
+ if (media != nullptr) {
+ bool textureReady = false; //tells if our texture is ready (if it was loaded or if it was found)
+ unsigned int index;
+
+ VideoMap::const_iterator it = textures_converted.find(media);
+ if (it != textures_converted.end()) {
+ index = (*it).second;
+ textureReady = true;
+ }
+ else {
+ if (media->ContentLength() > 0) {
+ index = ConvertVideo(*media);
+ textures_converted[media] = index;
+ textureReady = true;
+ }
+ }
+
+ // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture), if the texture is ready
+ if (doc.Settings().useLegacyEmbeddedTextureNaming) {
+ if (textureReady) {
+ // TODO: check the possibility of using the flag "AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING"
+ // In FBX files textures are now stored internally by Assimp with their filename included
+ // Now Assimp can lookup through the loaded textures after all data is processed
+ // We need to load all textures before referencing them, as FBX file format order may reference a texture before loading it
+ // This may occur on this case too, it has to be studied
+ path.data[0] = '*';
+ path.length = 1 + ASSIMP_itoa10(path.data + 1, MAXLEN - 1, index);
+ }
+ }
+ }
+
+ return path;
+ }
+
+ void FBXConverter::TrySetTextureProperties(aiMaterial* out_mat, const TextureMap& textures,
+ const std::string& propName,
+ aiTextureType target, const MeshGeometry* const mesh)
+ {
+ TextureMap::const_iterator it = textures.find(propName);
+ if (it == textures.end()) {
+ return;
+ }
+
+ const Texture* const tex = (*it).second;
+ if (tex != 0)
+ {
+ aiString path = GetTexturePath(tex);
+ out_mat->AddProperty(&path, _AI_MATKEY_TEXTURE_BASE, target, 0);
+
+ aiUVTransform uvTrafo;
+ // XXX handle all kinds of UV transformations
+ uvTrafo.mScaling = tex->UVScaling();
+ uvTrafo.mTranslation = tex->UVTranslation();
+ out_mat->AddProperty(&uvTrafo, 1, _AI_MATKEY_UVTRANSFORM_BASE, target, 0);
+
+ const PropertyTable& props = tex->Props();
+
+ int uvIndex = 0;
+
+ bool ok;
+ const std::string& uvSet = PropertyGet<std::string>(props, "UVSet", ok);
+ if (ok) {
+ // "default" is the name which usually appears in the FbxFileTexture template
+ if (uvSet != "default" && uvSet.length()) {
+ // this is a bit awkward - we need to find a mesh that uses this
+ // material and scan its UV channels for the given UV name because
+ // assimp references UV channels by index, not by name.
+
+ // XXX: the case that UV channels may appear in different orders
+ // in meshes is unhandled. A possible solution would be to sort
+ // the UV channels alphabetically, but this would have the side
+ // effect that the primary (first) UV channel would sometimes
+ // be moved, causing trouble when users read only the first
+ // UV channel and ignore UV channel assignments altogether.
+
+ const unsigned int matIndex = static_cast<unsigned int>(std::distance(materials.begin(),
+ std::find(materials.begin(), materials.end(), out_mat)
+ ));
+
+
+ uvIndex = -1;
+ if (!mesh)
+ {
+ for (const MeshMap::value_type& v : meshes_converted) {
+ const MeshGeometry* const meshGeom = dynamic_cast<const MeshGeometry*> (v.first);
+ if (!meshGeom) {
+ continue;
+ }
+
+ const MatIndexArray& mats = meshGeom->GetMaterialIndices();
+ if (std::find(mats.begin(), mats.end(), matIndex) == mats.end()) {
+ continue;
+ }
+
+ int index = -1;
+ for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
+ if (meshGeom->GetTextureCoords(i).empty()) {
+ break;
+ }
+ const std::string& name = meshGeom->GetTextureCoordChannelName(i);
+ if (name == uvSet) {
+ index = static_cast<int>(i);
+ break;
+ }
+ }
+ if (index == -1) {
+ FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material");
+ continue;
+ }
+
+ if (uvIndex == -1) {
+ uvIndex = index;
+ }
+ else {
+ FBXImporter::LogWarn("the UV channel named " + uvSet +
+ " appears at different positions in meshes, results will be wrong");
+ }
+ }
+ }
+ else
+ {
+ int index = -1;
+ for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
+ if (mesh->GetTextureCoords(i).empty()) {
+ break;
+ }
+ const std::string& name = mesh->GetTextureCoordChannelName(i);
+ if (name == uvSet) {
+ index = static_cast<int>(i);
+ break;
+ }
+ }
+ if (index == -1) {
+ FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material");
+ }
+
+ if (uvIndex == -1) {
+ uvIndex = index;
+ }
+ }
+
+ if (uvIndex == -1) {
+ FBXImporter::LogWarn("failed to resolve UV channel " + uvSet + ", using first UV channel");
+ uvIndex = 0;
+ }
+ }
+ }
+
+ out_mat->AddProperty(&uvIndex, 1, _AI_MATKEY_UVWSRC_BASE, target, 0);
+ }
+ }
+
+ void FBXConverter::TrySetTextureProperties(aiMaterial* out_mat, const LayeredTextureMap& layeredTextures,
+ const std::string& propName,
+ aiTextureType target, const MeshGeometry* const mesh) {
+ LayeredTextureMap::const_iterator it = layeredTextures.find(propName);
+ if (it == layeredTextures.end()) {
+ return;
+ }
+
+ int texCount = (*it).second->textureCount();
+
+ // Set the blend mode for layered textures
+ int blendmode = (*it).second->GetBlendMode();
+ out_mat->AddProperty(&blendmode, 1, _AI_MATKEY_TEXOP_BASE, target, 0);
+
+ for (int texIndex = 0; texIndex < texCount; texIndex++) {
+
+ const Texture* const tex = (*it).second->getTexture(texIndex);
+
+ aiString path = GetTexturePath(tex);
+ out_mat->AddProperty(&path, _AI_MATKEY_TEXTURE_BASE, target, texIndex);
+
+ aiUVTransform uvTrafo;
+ // XXX handle all kinds of UV transformations
+ uvTrafo.mScaling = tex->UVScaling();
+ uvTrafo.mTranslation = tex->UVTranslation();
+ out_mat->AddProperty(&uvTrafo, 1, _AI_MATKEY_UVTRANSFORM_BASE, target, texIndex);
+
+ const PropertyTable& props = tex->Props();
+
+ int uvIndex = 0;
+
+ bool ok;
+ const std::string& uvSet = PropertyGet<std::string>(props, "UVSet", ok);
+ if (ok) {
+ // "default" is the name which usually appears in the FbxFileTexture template
+ if (uvSet != "default" && uvSet.length()) {
+ // this is a bit awkward - we need to find a mesh that uses this
+ // material and scan its UV channels for the given UV name because
+ // assimp references UV channels by index, not by name.
+
+ // XXX: the case that UV channels may appear in different orders
+ // in meshes is unhandled. A possible solution would be to sort
+ // the UV channels alphabetically, but this would have the side
+ // effect that the primary (first) UV channel would sometimes
+ // be moved, causing trouble when users read only the first
+ // UV channel and ignore UV channel assignments altogether.
+
+ const unsigned int matIndex = static_cast<unsigned int>(std::distance(materials.begin(),
+ std::find(materials.begin(), materials.end(), out_mat)
+ ));
+
+ uvIndex = -1;
+ if (!mesh)
+ {
+ for (const MeshMap::value_type& v : meshes_converted) {
+ const MeshGeometry* const meshGeom = dynamic_cast<const MeshGeometry*> (v.first);
+ if (!meshGeom) {
+ continue;
+ }
+
+ const MatIndexArray& mats = meshGeom->GetMaterialIndices();
+ if (std::find(mats.begin(), mats.end(), matIndex) == mats.end()) {
+ continue;
+ }
+
+ int index = -1;
+ for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
+ if (meshGeom->GetTextureCoords(i).empty()) {
+ break;
+ }
+ const std::string& name = meshGeom->GetTextureCoordChannelName(i);
+ if (name == uvSet) {
+ index = static_cast<int>(i);
+ break;
+ }
+ }
+ if (index == -1) {
+ FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material");
+ continue;
+ }
+
+ if (uvIndex == -1) {
+ uvIndex = index;
+ }
+ else {
+ FBXImporter::LogWarn("the UV channel named " + uvSet +
+ " appears at different positions in meshes, results will be wrong");
+ }
+ }
+ }
+ else
+ {
+ int index = -1;
+ for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
+ if (mesh->GetTextureCoords(i).empty()) {
+ break;
+ }
+ const std::string& name = mesh->GetTextureCoordChannelName(i);
+ if (name == uvSet) {
+ index = static_cast<int>(i);
+ break;
+ }
+ }
+ if (index == -1) {
+ FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material");
+ }
+
+ if (uvIndex == -1) {
+ uvIndex = index;
+ }
+ }
+
+ if (uvIndex == -1) {
+ FBXImporter::LogWarn("failed to resolve UV channel " + uvSet + ", using first UV channel");
+ uvIndex = 0;
+ }
+ }
+ }
+
+ out_mat->AddProperty(&uvIndex, 1, _AI_MATKEY_UVWSRC_BASE, target, texIndex);
+ }
+ }
+
+ void FBXConverter::SetTextureProperties(aiMaterial* out_mat, const TextureMap& textures, const MeshGeometry* const mesh)
+ {
+ TrySetTextureProperties(out_mat, textures, "DiffuseColor", aiTextureType_DIFFUSE, mesh);
+ TrySetTextureProperties(out_mat, textures, "AmbientColor", aiTextureType_AMBIENT, mesh);
+ TrySetTextureProperties(out_mat, textures, "EmissiveColor", aiTextureType_EMISSIVE, mesh);
+ TrySetTextureProperties(out_mat, textures, "SpecularColor", aiTextureType_SPECULAR, mesh);
+ TrySetTextureProperties(out_mat, textures, "SpecularFactor", aiTextureType_SPECULAR, mesh);
+ TrySetTextureProperties(out_mat, textures, "TransparentColor", aiTextureType_OPACITY, mesh);
+ TrySetTextureProperties(out_mat, textures, "ReflectionColor", aiTextureType_REFLECTION, mesh);
+ TrySetTextureProperties(out_mat, textures, "DisplacementColor", aiTextureType_DISPLACEMENT, mesh);
+ TrySetTextureProperties(out_mat, textures, "NormalMap", aiTextureType_NORMALS, mesh);
+ TrySetTextureProperties(out_mat, textures, "Bump", aiTextureType_HEIGHT, mesh);
+ TrySetTextureProperties(out_mat, textures, "ShininessExponent", aiTextureType_SHININESS, mesh);
+ TrySetTextureProperties( out_mat, textures, "TransparencyFactor", aiTextureType_OPACITY, mesh );
+ TrySetTextureProperties( out_mat, textures, "EmissiveFactor", aiTextureType_EMISSIVE, mesh );
+ //Maya counterparts
+ TrySetTextureProperties(out_mat, textures, "Maya|DiffuseTexture", aiTextureType_DIFFUSE, mesh);
+ TrySetTextureProperties(out_mat, textures, "Maya|NormalTexture", aiTextureType_NORMALS, mesh);
+ TrySetTextureProperties(out_mat, textures, "Maya|SpecularTexture", aiTextureType_SPECULAR, mesh);
+ TrySetTextureProperties(out_mat, textures, "Maya|FalloffTexture", aiTextureType_OPACITY, mesh);
+ TrySetTextureProperties(out_mat, textures, "Maya|ReflectionMapTexture", aiTextureType_REFLECTION, mesh);
+ }
+
+ void FBXConverter::SetTextureProperties(aiMaterial* out_mat, const LayeredTextureMap& layeredTextures, const MeshGeometry* const mesh)
+ {
+ TrySetTextureProperties(out_mat, layeredTextures, "DiffuseColor", aiTextureType_DIFFUSE, mesh);
+ TrySetTextureProperties(out_mat, layeredTextures, "AmbientColor", aiTextureType_AMBIENT, mesh);
+ TrySetTextureProperties(out_mat, layeredTextures, "EmissiveColor", aiTextureType_EMISSIVE, mesh);
+ TrySetTextureProperties(out_mat, layeredTextures, "SpecularColor", aiTextureType_SPECULAR, mesh);
+ TrySetTextureProperties(out_mat, layeredTextures, "SpecularFactor", aiTextureType_SPECULAR, mesh);
+ TrySetTextureProperties(out_mat, layeredTextures, "TransparentColor", aiTextureType_OPACITY, mesh);
+ TrySetTextureProperties(out_mat, layeredTextures, "ReflectionColor", aiTextureType_REFLECTION, mesh);
+ TrySetTextureProperties(out_mat, layeredTextures, "DisplacementColor", aiTextureType_DISPLACEMENT, mesh);
+ TrySetTextureProperties(out_mat, layeredTextures, "NormalMap", aiTextureType_NORMALS, mesh);
+ TrySetTextureProperties(out_mat, layeredTextures, "Bump", aiTextureType_HEIGHT, mesh);
+ TrySetTextureProperties(out_mat, layeredTextures, "ShininessExponent", aiTextureType_SHININESS, mesh);
+ TrySetTextureProperties( out_mat, layeredTextures, "EmissiveFactor", aiTextureType_EMISSIVE, mesh );
+ TrySetTextureProperties( out_mat, layeredTextures, "TransparencyFactor", aiTextureType_OPACITY, mesh );
+ }
+
+ aiColor3D FBXConverter::GetColorPropertyFactored(const PropertyTable& props, const std::string& colorName,
+ const std::string& factorName, bool& result, bool useTemplate)
+ {
+ result = true;
+
+ bool ok;
+ aiVector3D BaseColor = PropertyGet<aiVector3D>(props, colorName, ok, useTemplate);
+ if (!ok) {
+ result = false;
+ return aiColor3D(0.0f, 0.0f, 0.0f);
+ }
+
+ // if no factor name, return the colour as is
+ if (factorName.empty()) {
+ return aiColor3D(BaseColor.x, BaseColor.y, BaseColor.z);
+ }
+
+ // otherwise it should be multiplied by the factor, if found.
+ float factor = PropertyGet<float>(props, factorName, ok, useTemplate);
+ if (ok) {
+ BaseColor *= factor;
+ }
+ return aiColor3D(BaseColor.x, BaseColor.y, BaseColor.z);
+ }
+
+ aiColor3D FBXConverter::GetColorPropertyFromMaterial(const PropertyTable& props, const std::string& baseName,
+ bool& result)
+ {
+ return GetColorPropertyFactored(props, baseName + "Color", baseName + "Factor", result, true);
+ }
+
+ aiColor3D FBXConverter::GetColorProperty(const PropertyTable& props, const std::string& colorName,
+ bool& result, bool useTemplate)
+ {
+ result = true;
+ bool ok;
+ const aiVector3D& ColorVec = PropertyGet<aiVector3D>(props, colorName, ok, useTemplate);
+ if (!ok) {
+ result = false;
+ return aiColor3D(0.0f, 0.0f, 0.0f);
+ }
+ return aiColor3D(ColorVec.x, ColorVec.y, ColorVec.z);
+ }
+
+ void FBXConverter::SetShadingPropertiesCommon(aiMaterial* out_mat, const PropertyTable& props)
+ {
+ // Set shading properties.
+ // Modern FBX Files have two separate systems for defining these,
+ // with only the more comprehensive one described in the property template.
+ // Likely the other values are a legacy system,
+ // which is still always exported by the official FBX SDK.
+ //
+ // Blender's FBX import and export mostly ignore this legacy system,
+ // and as we only support recent versions of FBX anyway, we can do the same.
+ bool ok;
+
+ const aiColor3D& Diffuse = GetColorPropertyFromMaterial(props, "Diffuse", ok);
+ if (ok) {
+ out_mat->AddProperty(&Diffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
+ }
+
+ const aiColor3D& Emissive = GetColorPropertyFromMaterial(props, "Emissive", ok);
+ if (ok) {
+ out_mat->AddProperty(&Emissive, 1, AI_MATKEY_COLOR_EMISSIVE);
+ }
+
+ const aiColor3D& Ambient = GetColorPropertyFromMaterial(props, "Ambient", ok);
+ if (ok) {
+ out_mat->AddProperty(&Ambient, 1, AI_MATKEY_COLOR_AMBIENT);
+ }
+
+ // we store specular factor as SHININESS_STRENGTH, so just get the color
+ const aiColor3D& Specular = GetColorProperty(props, "SpecularColor", ok, true);
+ if (ok) {
+ out_mat->AddProperty(&Specular, 1, AI_MATKEY_COLOR_SPECULAR);
+ }
+
+ // and also try to get SHININESS_STRENGTH
+ const float SpecularFactor = PropertyGet<float>(props, "SpecularFactor", ok, true);
+ if (ok) {
+ out_mat->AddProperty(&SpecularFactor, 1, AI_MATKEY_SHININESS_STRENGTH);
+ }
+
+ // and the specular exponent
+ const float ShininessExponent = PropertyGet<float>(props, "ShininessExponent", ok);
+ if (ok) {
+ out_mat->AddProperty(&ShininessExponent, 1, AI_MATKEY_SHININESS);
+ }
+
+ // TransparentColor / TransparencyFactor... gee thanks FBX :rolleyes:
+ const aiColor3D& Transparent = GetColorPropertyFactored(props, "TransparentColor", "TransparencyFactor", ok);
+ float CalculatedOpacity = 1.0f;
+ if (ok) {
+ out_mat->AddProperty(&Transparent, 1, AI_MATKEY_COLOR_TRANSPARENT);
+ // as calculated by FBX SDK 2017:
+ CalculatedOpacity = 1.0f - ((Transparent.r + Transparent.g + Transparent.b) / 3.0f);
+ }
+
+ // try to get the transparency factor
+ const float TransparencyFactor = PropertyGet<float>(props, "TransparencyFactor", ok);
+ if (ok) {
+ out_mat->AddProperty(&TransparencyFactor, 1, AI_MATKEY_TRANSPARENCYFACTOR);
+ }
+
+ // use of TransparencyFactor is inconsistent.
+ // Maya always stores it as 1.0,
+ // so we can't use it to set AI_MATKEY_OPACITY.
+ // Blender is more sensible and stores it as the alpha value.
+ // However both the FBX SDK and Blender always write an additional
+ // legacy "Opacity" field, so we can try to use that.
+ //
+ // If we can't find it,
+ // we can fall back to the value which the FBX SDK calculates
+ // from transparency colour (RGB) and factor (F) as
+ // 1.0 - F*((R+G+B)/3).
+ //
+ // There's no consistent way to interpret this opacity value,
+ // so it's up to clients to do the correct thing.
+ const float Opacity = PropertyGet<float>(props, "Opacity", ok);
+ if (ok) {
+ out_mat->AddProperty(&Opacity, 1, AI_MATKEY_OPACITY);
+ }
+ else if (CalculatedOpacity != 1.0) {
+ out_mat->AddProperty(&CalculatedOpacity, 1, AI_MATKEY_OPACITY);
+ }
+
+ // reflection color and factor are stored separately
+ const aiColor3D& Reflection = GetColorProperty(props, "ReflectionColor", ok, true);
+ if (ok) {
+ out_mat->AddProperty(&Reflection, 1, AI_MATKEY_COLOR_REFLECTIVE);
+ }
+
+ float ReflectionFactor = PropertyGet<float>(props, "ReflectionFactor", ok, true);
+ if (ok) {
+ out_mat->AddProperty(&ReflectionFactor, 1, AI_MATKEY_REFLECTIVITY);
+ }
+
+ const float BumpFactor = PropertyGet<float>(props, "BumpFactor", ok);
+ if (ok) {
+ out_mat->AddProperty(&BumpFactor, 1, AI_MATKEY_BUMPSCALING);
+ }
+
+ const float DispFactor = PropertyGet<float>(props, "DisplacementFactor", ok);
+ if (ok) {
+ out_mat->AddProperty(&DispFactor, 1, "$mat.displacementscaling", 0, 0);
+ }
+}
+
+
+void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTable& props, const TextureMap& textures, const MeshGeometry* const mesh)
+{
+ // Add all the unparsed properties with a "$raw." prefix
+
+ const std::string prefix = "$raw.";
+
+ for (const DirectPropertyMap::value_type& prop : props.GetUnparsedProperties()) {
+
+ std::string name = prefix + prop.first;
+
+ if (const TypedProperty<aiVector3D>* interpreted = prop.second->As<TypedProperty<aiVector3D> >())
+ {
+ out_mat->AddProperty(&interpreted->Value(), 1, name.c_str(), 0, 0);
+ }
+ else if (const TypedProperty<aiColor3D>* interpreted = prop.second->As<TypedProperty<aiColor3D> >())
+ {
+ out_mat->AddProperty(&interpreted->Value(), 1, name.c_str(), 0, 0);
+ }
+ else if (const TypedProperty<aiColor4D>* interpreted = prop.second->As<TypedProperty<aiColor4D> >())
+ {
+ out_mat->AddProperty(&interpreted->Value(), 1, name.c_str(), 0, 0);
+ }
+ else if (const TypedProperty<float>* interpreted = prop.second->As<TypedProperty<float> >())
+ {
+ out_mat->AddProperty(&interpreted->Value(), 1, name.c_str(), 0, 0);
+ }
+ else if (const TypedProperty<int>* interpreted = prop.second->As<TypedProperty<int> >())
+ {
+ out_mat->AddProperty(&interpreted->Value(), 1, name.c_str(), 0, 0);
+ }
+ else if (const TypedProperty<bool>* interpreted = prop.second->As<TypedProperty<bool> >())
+ {
+ int value = interpreted->Value() ? 1 : 0;
+ out_mat->AddProperty(&value, 1, name.c_str(), 0, 0);
+ }
+ else if (const TypedProperty<std::string>* interpreted = prop.second->As<TypedProperty<std::string> >())
+ {
+ const aiString value = aiString(interpreted->Value());
+ out_mat->AddProperty(&value, name.c_str(), 0, 0);
+ }
+ }
+
+ // Add the textures' properties
+
+ for (TextureMap::const_iterator it = textures.begin(); it != textures.end(); it++) {
+
+ std::string name = prefix + it->first;
+
+ const Texture* const tex = (*it).second;
+ if (tex != nullptr)
+ {
+ aiString path;
+ path.Set(tex->RelativeFilename());
+
+ const Video* media = tex->Media();
+ if (media != nullptr && media->ContentLength() > 0) {
+ unsigned int index;
+
+ VideoMap::const_iterator it = textures_converted.find(media);
+ if (it != textures_converted.end()) {
+ index = (*it).second;
+ }
+ else {
+ index = ConvertVideo(*media);
+ textures_converted[media] = index;
+ }
+
+ // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture)
+ path.data[0] = '*';
+ path.length = 1 + ASSIMP_itoa10(path.data + 1, MAXLEN - 1, index);
+ }
+
+ out_mat->AddProperty(&path, (name + "|file").c_str(), aiTextureType_UNKNOWN, 0);
+
+ aiUVTransform uvTrafo;
+ // XXX handle all kinds of UV transformations
+ uvTrafo.mScaling = tex->UVScaling();
+ uvTrafo.mTranslation = tex->UVTranslation();
+ out_mat->AddProperty(&uvTrafo, 1, (name + "|uvtrafo").c_str(), aiTextureType_UNKNOWN, 0);
+
+ int uvIndex = 0;
+
+ bool uvFound = false;
+ const std::string& uvSet = PropertyGet<std::string>(tex->Props(), "UVSet", uvFound);
+ if (uvFound) {
+ // "default" is the name which usually appears in the FbxFileTexture template
+ if (uvSet != "default" && uvSet.length()) {
+ // this is a bit awkward - we need to find a mesh that uses this
+ // material and scan its UV channels for the given UV name because
+ // assimp references UV channels by index, not by name.
+
+ // XXX: the case that UV channels may appear in different orders
+ // in meshes is unhandled. A possible solution would be to sort
+ // the UV channels alphabetically, but this would have the side
+ // effect that the primary (first) UV channel would sometimes
+ // be moved, causing trouble when users read only the first
+ // UV channel and ignore UV channel assignments altogether.
+
+ std::vector<aiMaterial*>::iterator materialIt = std::find(materials.begin(), materials.end(), out_mat);
+ const unsigned int matIndex = static_cast<unsigned int>(std::distance(materials.begin(), materialIt));
+
+ uvIndex = -1;
+ if (!mesh)
+ {
+ for (const MeshMap::value_type& v : meshes_converted) {
+ const MeshGeometry* const meshGeom = dynamic_cast<const MeshGeometry*>(v.first);
+ if (!meshGeom) {
+ continue;
+ }
+
+ const MatIndexArray& mats = meshGeom->GetMaterialIndices();
+ if (std::find(mats.begin(), mats.end(), matIndex) == mats.end()) {
+ continue;
+ }
+
+ int index = -1;
+ for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
+ if (meshGeom->GetTextureCoords(i).empty()) {
+ break;
+ }
+ const std::string& name = meshGeom->GetTextureCoordChannelName(i);
+ if (name == uvSet) {
+ index = static_cast<int>(i);
+ break;
+ }
+ }
+ if (index == -1) {
+ FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material");
+ continue;
+ }
+
+ if (uvIndex == -1) {
+ uvIndex = index;
+ }
+ else {
+ FBXImporter::LogWarn("the UV channel named " + uvSet + " appears at different positions in meshes, results will be wrong");
+ }
+ }
+ }
+ else
+ {
+ int index = -1;
+ for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
+ if (mesh->GetTextureCoords(i).empty()) {
+ break;
+ }
+ const std::string& name = mesh->GetTextureCoordChannelName(i);
+ if (name == uvSet) {
+ index = static_cast<int>(i);
+ break;
+ }
+ }
+ if (index == -1) {
+ FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material");
+ }
+
+ if (uvIndex == -1) {
+ uvIndex = index;
+ }
+ }
+
+ if (uvIndex == -1) {
+ FBXImporter::LogWarn("failed to resolve UV channel " + uvSet + ", using first UV channel");
+ uvIndex = 0;
+ }
+ }
+ }
+
+ out_mat->AddProperty(&uvIndex, 1, (name + "|uvwsrc").c_str(), aiTextureType_UNKNOWN, 0);
+ }
+ }
+ }
+
+
+ double FBXConverter::FrameRateToDouble(FileGlobalSettings::FrameRate fp, double customFPSVal) {
+ switch (fp) {
+ case FileGlobalSettings::FrameRate_DEFAULT:
+ return 1.0;
+
+ case FileGlobalSettings::FrameRate_120:
+ return 120.0;
+
+ case FileGlobalSettings::FrameRate_100:
+ return 100.0;
+
+ case FileGlobalSettings::FrameRate_60:
+ return 60.0;
+
+ case FileGlobalSettings::FrameRate_50:
+ return 50.0;
+
+ case FileGlobalSettings::FrameRate_48:
+ return 48.0;
+
+ case FileGlobalSettings::FrameRate_30:
+ case FileGlobalSettings::FrameRate_30_DROP:
+ return 30.0;
+
+ case FileGlobalSettings::FrameRate_NTSC_DROP_FRAME:
+ case FileGlobalSettings::FrameRate_NTSC_FULL_FRAME:
+ return 29.9700262;
+
+ case FileGlobalSettings::FrameRate_PAL:
+ return 25.0;
+
+ case FileGlobalSettings::FrameRate_CINEMA:
+ return 24.0;
+
+ case FileGlobalSettings::FrameRate_1000:
+ return 1000.0;
+
+ case FileGlobalSettings::FrameRate_CINEMA_ND:
+ return 23.976;
+
+ case FileGlobalSettings::FrameRate_CUSTOM:
+ return customFPSVal;
+
+ case FileGlobalSettings::FrameRate_MAX: // this is to silence compiler warnings
+ break;
+ }
+
+ ai_assert(false);
+
+ return -1.0f;
+ }
+
+
+ void FBXConverter::ConvertAnimations()
+ {
+ // first of all determine framerate
+ const FileGlobalSettings::FrameRate fps = doc.GlobalSettings().TimeMode();
+ const float custom = doc.GlobalSettings().CustomFrameRate();
+ anim_fps = FrameRateToDouble(fps, custom);
+
+ const std::vector<const AnimationStack*>& animations = doc.AnimationStacks();
+ for (const AnimationStack* stack : animations) {
+ ConvertAnimationStack(*stack);
+ }
+ }
+
+ std::string FBXConverter::FixNodeName(const std::string& name) {
+ // strip Model:: prefix, avoiding ambiguities (i.e. don't strip if
+ // this causes ambiguities, well possible between empty identifiers,
+ // such as "Model::" and ""). Make sure the behaviour is consistent
+ // across multiple calls to FixNodeName().
+ if (name.substr(0, 7) == "Model::") {
+ std::string temp = name.substr(7);
+ return temp;
+ }
+
+ return name;
+ }
+
+ std::string FBXConverter::FixAnimMeshName(const std::string& name) {
+ if (name.length()) {
+ size_t indexOf = name.find_first_of("::");
+ if (indexOf != std::string::npos && indexOf < name.size() - 2) {
+ return name.substr(indexOf + 2);
+ }
+ }
+ return name.length() ? name : "AnimMesh";
+ }
+
+ void FBXConverter::ConvertAnimationStack(const AnimationStack& st)
+ {
+ const AnimationLayerList& layers = st.Layers();
+ if (layers.empty()) {
+ return;
+ }
+
+ aiAnimation* const anim = new aiAnimation();
+ animations.push_back(anim);
+
+ // strip AnimationStack:: prefix
+ std::string name = st.Name();
+ if (name.substr(0, 16) == "AnimationStack::") {
+ name = name.substr(16);
+ }
+ else if (name.substr(0, 11) == "AnimStack::") {
+ name = name.substr(11);
+ }
+
+ anim->mName.Set(name);
+
+ // need to find all nodes for which we need to generate node animations -
+ // it may happen that we need to merge multiple layers, though.
+ NodeMap node_map;
+
+ // reverse mapping from curves to layers, much faster than querying
+ // the FBX DOM for it.
+ LayerMap layer_map;
+
+ const char* prop_whitelist[] = {
+ "Lcl Scaling",
+ "Lcl Rotation",
+ "Lcl Translation",
+ "DeformPercent"
+ };
+
+ std::map<std::string, morphAnimData*> morphAnimDatas;
+
+ for (const AnimationLayer* layer : layers) {
+ ai_assert(layer);
+ const AnimationCurveNodeList& nodes = layer->Nodes(prop_whitelist, 4);
+ for (const AnimationCurveNode* node : nodes) {
+ ai_assert(node);
+ const Model* const model = dynamic_cast<const Model*>(node->Target());
+ if (model) {
+ const std::string& name = FixNodeName(model->Name());
+ node_map[name].push_back(node);
+ layer_map[node] = layer;
+ continue;
+ }
+ const BlendShapeChannel* const bsc = dynamic_cast<const BlendShapeChannel*>(node->Target());
+ if (bsc) {
+ ProcessMorphAnimDatas(&morphAnimDatas, bsc, node);
+ }
+ }
+ }
+
+ // generate node animations
+ std::vector<aiNodeAnim*> node_anims;
+
+ double min_time = 1e10;
+ double max_time = -1e10;
+
+ int64_t start_time = st.LocalStart();
+ int64_t stop_time = st.LocalStop();
+ bool has_local_startstop = start_time != 0 || stop_time != 0;
+ if (!has_local_startstop) {
+ // no time range given, so accept every keyframe and use the actual min/max time
+ // the numbers are INT64_MIN/MAX, the 20000 is for safety because GenerateNodeAnimations uses an epsilon of 10000
+ start_time = -9223372036854775807ll + 20000;
+ stop_time = 9223372036854775807ll - 20000;
+ }
+
+ try {
+ for (const NodeMap::value_type& kv : node_map) {
+ GenerateNodeAnimations(node_anims,
+ kv.first,
+ kv.second,
+ layer_map,
+ start_time, stop_time,
+ max_time,
+ min_time);
+ }
+ }
+ catch (std::exception&) {
+ std::for_each(node_anims.begin(), node_anims.end(), Util::delete_fun<aiNodeAnim>());
+ throw;
+ }
+
+ if (node_anims.size() || morphAnimDatas.size()) {
+ if (node_anims.size()) {
+ anim->mChannels = new aiNodeAnim*[node_anims.size()]();
+ anim->mNumChannels = static_cast<unsigned int>(node_anims.size());
+ std::swap_ranges(node_anims.begin(), node_anims.end(), anim->mChannels);
+ }
+ if (morphAnimDatas.size()) {
+ unsigned int numMorphMeshChannels = static_cast<unsigned int>(morphAnimDatas.size());
+ anim->mMorphMeshChannels = new aiMeshMorphAnim*[numMorphMeshChannels];
+ anim->mNumMorphMeshChannels = numMorphMeshChannels;
+ unsigned int i = 0;
+ for (auto morphAnimIt : morphAnimDatas) {
+ morphAnimData* animData = morphAnimIt.second;
+ unsigned int numKeys = static_cast<unsigned int>(animData->size());
+ aiMeshMorphAnim* meshMorphAnim = new aiMeshMorphAnim();
+ meshMorphAnim->mName.Set(morphAnimIt.first);
+ meshMorphAnim->mNumKeys = numKeys;
+ meshMorphAnim->mKeys = new aiMeshMorphKey[numKeys];
+ unsigned int j = 0;
+ for (auto animIt : *animData) {
+ morphKeyData* keyData = animIt.second;
+ unsigned int numValuesAndWeights = static_cast<unsigned int>(keyData->values.size());
+ meshMorphAnim->mKeys[j].mNumValuesAndWeights = numValuesAndWeights;
+ meshMorphAnim->mKeys[j].mValues = new unsigned int[numValuesAndWeights];
+ meshMorphAnim->mKeys[j].mWeights = new double[numValuesAndWeights];
+ meshMorphAnim->mKeys[j].mTime = CONVERT_FBX_TIME(animIt.first) * anim_fps;
+ for (unsigned int k = 0; k < numValuesAndWeights; k++) {
+ meshMorphAnim->mKeys[j].mValues[k] = keyData->values.at(k);
+ meshMorphAnim->mKeys[j].mWeights[k] = keyData->weights.at(k);
+ }
+ j++;
+ }
+ anim->mMorphMeshChannels[i++] = meshMorphAnim;
+ }
+ }
+ }
+ else {
+ // empty animations would fail validation, so drop them
+ delete anim;
+ animations.pop_back();
+ FBXImporter::LogInfo("ignoring empty AnimationStack (using IK?): " + name);
+ return;
+ }
+
+ double start_time_fps = has_local_startstop ? (CONVERT_FBX_TIME(start_time) * anim_fps) : min_time;
+ double stop_time_fps = has_local_startstop ? (CONVERT_FBX_TIME(stop_time) * anim_fps) : max_time;
+
+ // adjust relative timing for animation
+ for (unsigned int c = 0; c < anim->mNumChannels; c++) {
+ aiNodeAnim* channel = anim->mChannels[c];
+ for (uint32_t i = 0; i < channel->mNumPositionKeys; i++) {
+ channel->mPositionKeys[i].mTime -= start_time_fps;
+ }
+ for (uint32_t i = 0; i < channel->mNumRotationKeys; i++) {
+ channel->mRotationKeys[i].mTime -= start_time_fps;
+ }
+ for (uint32_t i = 0; i < channel->mNumScalingKeys; i++) {
+ channel->mScalingKeys[i].mTime -= start_time_fps;
+ }
+ }
+ for (unsigned int c = 0; c < anim->mNumMorphMeshChannels; c++) {
+ aiMeshMorphAnim* channel = anim->mMorphMeshChannels[c];
+ for (uint32_t i = 0; i < channel->mNumKeys; i++) {
+ channel->mKeys[i].mTime -= start_time_fps;
+ }
+ }
+
+ // for some mysterious reason, mDuration is simply the maximum key -- the
+ // validator always assumes animations to start at zero.
+ anim->mDuration = stop_time_fps - start_time_fps;
+ anim->mTicksPerSecond = anim_fps;
+ }
+
+ // ------------------------------------------------------------------------------------------------
+ void FBXConverter::ProcessMorphAnimDatas(std::map<std::string, morphAnimData*>* morphAnimDatas, const BlendShapeChannel* bsc, const AnimationCurveNode* node) {
+ std::vector<const Connection*> bscConnections = doc.GetConnectionsBySourceSequenced(bsc->ID(), "Deformer");
+ for (const Connection* bscConnection : bscConnections) {
+ auto bs = dynamic_cast<const BlendShape*>(bscConnection->DestinationObject());
+ if (bs) {
+ auto channelIt = std::find(bs->BlendShapeChannels().begin(), bs->BlendShapeChannels().end(), bsc);
+ if (channelIt != bs->BlendShapeChannels().end()) {
+ auto channelIndex = static_cast<unsigned int>(std::distance(bs->BlendShapeChannels().begin(), channelIt));
+ std::vector<const Connection*> bsConnections = doc.GetConnectionsBySourceSequenced(bs->ID(), "Geometry");
+ for (const Connection* bsConnection : bsConnections) {
+ auto geo = dynamic_cast<const Geometry*>(bsConnection->DestinationObject());
+ if (geo) {
+ std::vector<const Connection*> geoConnections = doc.GetConnectionsBySourceSequenced(geo->ID(), "Model");
+ for (const Connection* geoConnection : geoConnections) {
+ auto model = dynamic_cast<const Model*>(geoConnection->DestinationObject());
+ if (model) {
+ auto geoIt = std::find(model->GetGeometry().begin(), model->GetGeometry().end(), geo);
+ auto geoIndex = static_cast<unsigned int>(std::distance(model->GetGeometry().begin(), geoIt));
+ auto name = aiString(FixNodeName(model->Name() + "*"));
+ name.length = 1 + ASSIMP_itoa10(name.data + name.length, MAXLEN - 1, geoIndex);
+ morphAnimData* animData;
+ auto animIt = morphAnimDatas->find(name.C_Str());
+ if (animIt == morphAnimDatas->end()) {
+ animData = new morphAnimData();
+ morphAnimDatas->insert(std::make_pair(name.C_Str(), animData));
+ }
+ else {
+ animData = animIt->second;
+ }
+ for (std::pair<std::string, const AnimationCurve*> curvesIt : node->Curves()) {
+ if (curvesIt.first == "d|DeformPercent") {
+ const AnimationCurve* animationCurve = curvesIt.second;
+ const KeyTimeList& keys = animationCurve->GetKeys();
+ const KeyValueList& values = animationCurve->GetValues();
+ unsigned int k = 0;
+ for (auto key : keys) {
+ morphKeyData* keyData;
+ auto keyIt = animData->find(key);
+ if (keyIt == animData->end()) {
+ keyData = new morphKeyData();
+ animData->insert(std::make_pair(key, keyData));
+ }
+ else {
+ keyData = keyIt->second;
+ }
+ keyData->values.push_back(channelIndex);
+ keyData->weights.push_back(values.at(k) / 100.0f);
+ k++;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // ------------------------------------------------------------------------------------------------
+#ifdef ASSIMP_BUILD_DEBUG
+ // ------------------------------------------------------------------------------------------------
+ // sanity check whether the input is ok
+ static void validateAnimCurveNodes(const std::vector<const AnimationCurveNode*>& curves,
+ bool strictMode) {
+ const Object* target(NULL);
+ for (const AnimationCurveNode* node : curves) {
+ if (!target) {
+ target = node->Target();
+ }
+ if (node->Target() != target) {
+ FBXImporter::LogWarn("Node target is nullptr type.");
+ }
+ if (strictMode) {
+ ai_assert(node->Target() == target);
+ }
+ }
+ }
+#endif // ASSIMP_BUILD_DEBUG
+
+ // ------------------------------------------------------------------------------------------------
+ void FBXConverter::GenerateNodeAnimations(std::vector<aiNodeAnim*>& node_anims,
+ const std::string& fixed_name,
+ const std::vector<const AnimationCurveNode*>& curves,
+ const LayerMap& layer_map,
+ int64_t start, int64_t stop,
+ double& max_time,
+ double& min_time)
+ {
+
+ NodeMap node_property_map;
+ ai_assert(curves.size());
+
+#ifdef ASSIMP_BUILD_DEBUG
+ validateAnimCurveNodes(curves, doc.Settings().strictMode);
+#endif
+ const AnimationCurveNode* curve_node = NULL;
+ for (const AnimationCurveNode* node : curves) {
+ ai_assert(node);
+
+ if (node->TargetProperty().empty()) {
+ FBXImporter::LogWarn("target property for animation curve not set: " + node->Name());
+ continue;
+ }
+
+ curve_node = node;
+ if (node->Curves().empty()) {
+ FBXImporter::LogWarn("no animation curves assigned to AnimationCurveNode: " + node->Name());
+ continue;
+ }
+
+ node_property_map[node->TargetProperty()].push_back(node);
+ }
+
+ ai_assert(curve_node);
+ ai_assert(curve_node->TargetAsModel());
+
+ const Model& target = *curve_node->TargetAsModel();
+
+ // check for all possible transformation components
+ NodeMap::const_iterator chain[TransformationComp_MAXIMUM];
+
+ bool has_any = false;
+ bool has_complex = false;
+
+ for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i) {
+ const TransformationComp comp = static_cast<TransformationComp>(i);
+
+ // inverse pivots don't exist in the input, we just generate them
+ if (comp == TransformationComp_RotationPivotInverse || comp == TransformationComp_ScalingPivotInverse) {
+ chain[i] = node_property_map.end();
+ continue;
+ }
+
+ chain[i] = node_property_map.find(NameTransformationCompProperty(comp));
+ if (chain[i] != node_property_map.end()) {
+
+ // check if this curves contains redundant information by looking
+ // up the corresponding node's transformation chain.
+ if (doc.Settings().optimizeEmptyAnimationCurves &&
+ IsRedundantAnimationData(target, comp, (*chain[i]).second)) {
+
+ FBXImporter::LogDebug("dropping redundant animation channel for node " + target.Name());
+ continue;
+ }
+
+ has_any = true;
+
+ if (comp != TransformationComp_Rotation && comp != TransformationComp_Scaling && comp != TransformationComp_Translation)
+ {
+ has_complex = true;
+ }
+ }
+ }
+
+ if (!has_any) {
+ FBXImporter::LogWarn("ignoring node animation, did not find any transformation key frames");
+ return;
+ }
+
+ // this needs to play nicely with GenerateTransformationNodeChain() which will
+ // be invoked _later_ (animations come first). If this node has only rotation,
+ // scaling and translation _and_ there are no animated other components either,
+ // we can use a single node and also a single node animation channel.
+ if (!has_complex && !NeedsComplexTransformationChain(target)) {
+
+ aiNodeAnim* const nd = GenerateSimpleNodeAnim(fixed_name, target, chain,
+ node_property_map.end(),
+ layer_map,
+ start, stop,
+ max_time,
+ min_time,
+ true // input is TRS order, assimp is SRT
+ );
+
+ ai_assert(nd);
+ if (nd->mNumPositionKeys == 0 && nd->mNumRotationKeys == 0 && nd->mNumScalingKeys == 0) {
+ delete nd;
+ }
+ else {
+ node_anims.push_back(nd);
+ }
+ return;
+ }
+
+ // otherwise, things get gruesome and we need separate animation channels
+ // for each part of the transformation chain. Remember which channels
+ // we generated and pass this information to the node conversion
+ // code to avoid nodes that have identity transform, but non-identity
+ // animations, being dropped.
+ unsigned int flags = 0, bit = 0x1;
+ for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i, bit <<= 1) {
+ const TransformationComp comp = static_cast<TransformationComp>(i);
+
+ if (chain[i] != node_property_map.end()) {
+ flags |= bit;
+
+ ai_assert(comp != TransformationComp_RotationPivotInverse);
+ ai_assert(comp != TransformationComp_ScalingPivotInverse);
+
+ const std::string& chain_name = NameTransformationChainNode(fixed_name, comp);
+
+ aiNodeAnim* na = nullptr;
+ switch (comp)
+ {
+ case TransformationComp_Rotation:
+ case TransformationComp_PreRotation:
+ case TransformationComp_PostRotation:
+ case TransformationComp_GeometricRotation:
+ na = GenerateRotationNodeAnim(chain_name,
+ target,
+ (*chain[i]).second,
+ layer_map,
+ start, stop,
+ max_time,
+ min_time);
+
+ break;
+
+ case TransformationComp_RotationOffset:
+ case TransformationComp_RotationPivot:
+ case TransformationComp_ScalingOffset:
+ case TransformationComp_ScalingPivot:
+ case TransformationComp_Translation:
+ case TransformationComp_GeometricTranslation:
+ na = GenerateTranslationNodeAnim(chain_name,
+ target,
+ (*chain[i]).second,
+ layer_map,
+ start, stop,
+ max_time,
+ min_time);
+
+ // pivoting requires us to generate an implicit inverse channel to undo the pivot translation
+ if (comp == TransformationComp_RotationPivot) {
+ const std::string& invName = NameTransformationChainNode(fixed_name,
+ TransformationComp_RotationPivotInverse);
+
+ aiNodeAnim* const inv = GenerateTranslationNodeAnim(invName,
+ target,
+ (*chain[i]).second,
+ layer_map,
+ start, stop,
+ max_time,
+ min_time,
+ true);
+
+ ai_assert(inv);
+ if (inv->mNumPositionKeys == 0 && inv->mNumRotationKeys == 0 && inv->mNumScalingKeys == 0) {
+ delete inv;
+ }
+ else {
+ node_anims.push_back(inv);
+ }
+
+ ai_assert(TransformationComp_RotationPivotInverse > i);
+ flags |= bit << (TransformationComp_RotationPivotInverse - i);
+ }
+ else if (comp == TransformationComp_ScalingPivot) {
+ const std::string& invName = NameTransformationChainNode(fixed_name,
+ TransformationComp_ScalingPivotInverse);
+
+ aiNodeAnim* const inv = GenerateTranslationNodeAnim(invName,
+ target,
+ (*chain[i]).second,
+ layer_map,
+ start, stop,
+ max_time,
+ min_time,
+ true);
+
+ ai_assert(inv);
+ if (inv->mNumPositionKeys == 0 && inv->mNumRotationKeys == 0 && inv->mNumScalingKeys == 0) {
+ delete inv;
+ }
+ else {
+ node_anims.push_back(inv);
+ }
+
+ ai_assert(TransformationComp_RotationPivotInverse > i);
+ flags |= bit << (TransformationComp_RotationPivotInverse - i);
+ }
+
+ break;
+
+ case TransformationComp_Scaling:
+ case TransformationComp_GeometricScaling:
+ na = GenerateScalingNodeAnim(chain_name,
+ target,
+ (*chain[i]).second,
+ layer_map,
+ start, stop,
+ max_time,
+ min_time);
+
+ break;
+
+ default:
+ ai_assert(false);
+ }
+
+ ai_assert(na);
+ if (na->mNumPositionKeys == 0 && na->mNumRotationKeys == 0 && na->mNumScalingKeys == 0) {
+ delete na;
+ }
+ else {
+ node_anims.push_back(na);
+ }
+ continue;
+ }
+ }
+
+ node_anim_chain_bits[fixed_name] = flags;
+ }
+
+
+ bool FBXConverter::IsRedundantAnimationData(const Model& target,
+ TransformationComp comp,
+ const std::vector<const AnimationCurveNode*>& curves) {
+ ai_assert(curves.size());
+
+ // look for animation nodes with
+ // * sub channels for all relevant components set
+ // * one key/value pair per component
+ // * combined values match up the corresponding value in the bind pose node transformation
+ // only such nodes are 'redundant' for this function.
+
+ if (curves.size() > 1) {
+ return false;
+ }
+
+ const AnimationCurveNode& nd = *curves.front();
+ const AnimationCurveMap& sub_curves = nd.Curves();
+
+ const AnimationCurveMap::const_iterator dx = sub_curves.find("d|X");
+ const AnimationCurveMap::const_iterator dy = sub_curves.find("d|Y");
+ const AnimationCurveMap::const_iterator dz = sub_curves.find("d|Z");
+
+ if (dx == sub_curves.end() || dy == sub_curves.end() || dz == sub_curves.end()) {
+ return false;
+ }
+
+ const KeyValueList& vx = (*dx).second->GetValues();
+ const KeyValueList& vy = (*dy).second->GetValues();
+ const KeyValueList& vz = (*dz).second->GetValues();
+
+ if (vx.size() != 1 || vy.size() != 1 || vz.size() != 1) {
+ return false;
+ }
+
+ const aiVector3D dyn_val = aiVector3D(vx[0], vy[0], vz[0]);
+ const aiVector3D& static_val = PropertyGet<aiVector3D>(target.Props(),
+ NameTransformationCompProperty(comp),
+ TransformationCompDefaultValue(comp)
+ );
+
+ const float epsilon = 1e-6f;
+ return (dyn_val - static_val).SquareLength() < epsilon;
+ }
+
+
+ aiNodeAnim* FBXConverter::GenerateRotationNodeAnim(const std::string& name,
+ const Model& target,
+ const std::vector<const AnimationCurveNode*>& curves,
+ const LayerMap& layer_map,
+ int64_t start, int64_t stop,
+ double& max_time,
+ double& min_time)
+ {
+ std::unique_ptr<aiNodeAnim> na(new aiNodeAnim());
+ na->mNodeName.Set(name);
+
+ ConvertRotationKeys(na.get(), curves, layer_map, start, stop, max_time, min_time, target.RotationOrder());
+
+ // dummy scaling key
+ na->mScalingKeys = new aiVectorKey[1];
+ na->mNumScalingKeys = 1;
+
+ na->mScalingKeys[0].mTime = 0.;
+ na->mScalingKeys[0].mValue = aiVector3D(1.0f, 1.0f, 1.0f);
+
+ // dummy position key
+ na->mPositionKeys = new aiVectorKey[1];
+ na->mNumPositionKeys = 1;
+
+ na->mPositionKeys[0].mTime = 0.;
+ na->mPositionKeys[0].mValue = aiVector3D();
+
+ return na.release();
+ }
+
+ aiNodeAnim* FBXConverter::GenerateScalingNodeAnim(const std::string& name,
+ const Model& /*target*/,
+ const std::vector<const AnimationCurveNode*>& curves,
+ const LayerMap& layer_map,
+ int64_t start, int64_t stop,
+ double& max_time,
+ double& min_time)
+ {
+ std::unique_ptr<aiNodeAnim> na(new aiNodeAnim());
+ na->mNodeName.Set(name);
+
+ ConvertScaleKeys(na.get(), curves, layer_map, start, stop, max_time, min_time);
+
+ // dummy rotation key
+ na->mRotationKeys = new aiQuatKey[1];
+ na->mNumRotationKeys = 1;
+
+ na->mRotationKeys[0].mTime = 0.;
+ na->mRotationKeys[0].mValue = aiQuaternion();
+
+ // dummy position key
+ na->mPositionKeys = new aiVectorKey[1];
+ na->mNumPositionKeys = 1;
+
+ na->mPositionKeys[0].mTime = 0.;
+ na->mPositionKeys[0].mValue = aiVector3D();
+
+ return na.release();
+ }
+
+ aiNodeAnim* FBXConverter::GenerateTranslationNodeAnim(const std::string& name,
+ const Model& /*target*/,
+ const std::vector<const AnimationCurveNode*>& curves,
+ const LayerMap& layer_map,
+ int64_t start, int64_t stop,
+ double& max_time,
+ double& min_time,
+ bool inverse) {
+ std::unique_ptr<aiNodeAnim> na(new aiNodeAnim());
+ na->mNodeName.Set(name);
+
+ ConvertTranslationKeys(na.get(), curves, layer_map, start, stop, max_time, min_time);
+
+ if (inverse) {
+ for (unsigned int i = 0; i < na->mNumPositionKeys; ++i) {
+ na->mPositionKeys[i].mValue *= -1.0f;
+ }
+ }
+
+ // dummy scaling key
+ na->mScalingKeys = new aiVectorKey[1];
+ na->mNumScalingKeys = 1;
+
+ na->mScalingKeys[0].mTime = 0.;
+ na->mScalingKeys[0].mValue = aiVector3D(1.0f, 1.0f, 1.0f);
+
+ // dummy rotation key
+ na->mRotationKeys = new aiQuatKey[1];
+ na->mNumRotationKeys = 1;
+
+ na->mRotationKeys[0].mTime = 0.;
+ na->mRotationKeys[0].mValue = aiQuaternion();
+
+ return na.release();
+ }
+
+ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name,
+ const Model& target,
+ NodeMap::const_iterator chain[TransformationComp_MAXIMUM],
+ NodeMap::const_iterator iter_end,
+ const LayerMap& layer_map,
+ int64_t start, int64_t stop,
+ double& max_time,
+ double& min_time,
+ bool reverse_order)
+
+ {
+ std::unique_ptr<aiNodeAnim> na(new aiNodeAnim());
+ na->mNodeName.Set(name);
+
+ const PropertyTable& props = target.Props();
+
+ // need to convert from TRS order to SRT?
+ if (reverse_order) {
+
+ aiVector3D def_scale = PropertyGet(props, "Lcl Scaling", aiVector3D(1.f, 1.f, 1.f));
+ aiVector3D def_translate = PropertyGet(props, "Lcl Translation", aiVector3D(0.f, 0.f, 0.f));
+ aiVector3D def_rot = PropertyGet(props, "Lcl Rotation", aiVector3D(0.f, 0.f, 0.f));
+
+ KeyFrameListList scaling;
+ KeyFrameListList translation;
+ KeyFrameListList rotation;
+
+ if (chain[TransformationComp_Scaling] != iter_end) {
+ scaling = GetKeyframeList((*chain[TransformationComp_Scaling]).second, start, stop);
+ }
+
+ if (chain[TransformationComp_Translation] != iter_end) {
+ translation = GetKeyframeList((*chain[TransformationComp_Translation]).second, start, stop);
+ }
+
+ if (chain[TransformationComp_Rotation] != iter_end) {
+ rotation = GetKeyframeList((*chain[TransformationComp_Rotation]).second, start, stop);
+ }
+
+ KeyFrameListList joined;
+ joined.insert(joined.end(), scaling.begin(), scaling.end());
+ joined.insert(joined.end(), translation.begin(), translation.end());
+ joined.insert(joined.end(), rotation.begin(), rotation.end());
+
+ const KeyTimeList& times = GetKeyTimeList(joined);
+
+ aiQuatKey* out_quat = new aiQuatKey[times.size()];
+ aiVectorKey* out_scale = new aiVectorKey[times.size()];
+ aiVectorKey* out_translation = new aiVectorKey[times.size()];
+
+ if (times.size())
+ {
+ ConvertTransformOrder_TRStoSRT(out_quat, out_scale, out_translation,
+ scaling,
+ translation,
+ rotation,
+ times,
+ max_time,
+ min_time,
+ target.RotationOrder(),
+ def_scale,
+ def_translate,
+ def_rot);
+ }
+
+ // XXX remove duplicates / redundant keys which this operation did
+ // likely produce if not all three channels were equally dense.
+
+ na->mNumScalingKeys = static_cast<unsigned int>(times.size());
+ na->mNumRotationKeys = na->mNumScalingKeys;
+ na->mNumPositionKeys = na->mNumScalingKeys;
+
+ na->mScalingKeys = out_scale;
+ na->mRotationKeys = out_quat;
+ na->mPositionKeys = out_translation;
+ }
+ else {
+
+ // if a particular transformation is not given, grab it from
+ // the corresponding node to meet the semantics of aiNodeAnim,
+ // which requires all of rotation, scaling and translation
+ // to be set.
+ if (chain[TransformationComp_Scaling] != iter_end) {
+ ConvertScaleKeys(na.get(), (*chain[TransformationComp_Scaling]).second,
+ layer_map,
+ start, stop,
+ max_time,
+ min_time);
+ }
+ else {
+ na->mScalingKeys = new aiVectorKey[1];
+ na->mNumScalingKeys = 1;
+
+ na->mScalingKeys[0].mTime = 0.;
+ na->mScalingKeys[0].mValue = PropertyGet(props, "Lcl Scaling",
+ aiVector3D(1.f, 1.f, 1.f));
+ }
+
+ if (chain[TransformationComp_Rotation] != iter_end) {
+ ConvertRotationKeys(na.get(), (*chain[TransformationComp_Rotation]).second,
+ layer_map,
+ start, stop,
+ max_time,
+ min_time,
+ target.RotationOrder());
+ }
+ else {
+ na->mRotationKeys = new aiQuatKey[1];
+ na->mNumRotationKeys = 1;
+
+ na->mRotationKeys[0].mTime = 0.;
+ na->mRotationKeys[0].mValue = EulerToQuaternion(
+ PropertyGet(props, "Lcl Rotation", aiVector3D(0.f, 0.f, 0.f)),
+ target.RotationOrder());
+ }
+
+ if (chain[TransformationComp_Translation] != iter_end) {
+ ConvertTranslationKeys(na.get(), (*chain[TransformationComp_Translation]).second,
+ layer_map,
+ start, stop,
+ max_time,
+ min_time);
+ }
+ else {
+ na->mPositionKeys = new aiVectorKey[1];
+ na->mNumPositionKeys = 1;
+
+ na->mPositionKeys[0].mTime = 0.;
+ na->mPositionKeys[0].mValue = PropertyGet(props, "Lcl Translation",
+ aiVector3D(0.f, 0.f, 0.f));
+ }
+
+ }
+ return na.release();
+ }
+
+ FBXConverter::KeyFrameListList FBXConverter::GetKeyframeList(const std::vector<const AnimationCurveNode*>& nodes, int64_t start, int64_t stop)
+ {
+ KeyFrameListList inputs;
+ inputs.reserve(nodes.size() * 3);
+
+ //give some breathing room for rounding errors
+ int64_t adj_start = start - 10000;
+ int64_t adj_stop = stop + 10000;
+
+ for (const AnimationCurveNode* node : nodes) {
+ ai_assert(node);
+
+ const AnimationCurveMap& curves = node->Curves();
+ for (const AnimationCurveMap::value_type& kv : curves) {
+
+ unsigned int mapto;
+ if (kv.first == "d|X") {
+ mapto = 0;
+ }
+ else if (kv.first == "d|Y") {
+ mapto = 1;
+ }
+ else if (kv.first == "d|Z") {
+ mapto = 2;
+ }
+ else {
+ FBXImporter::LogWarn("ignoring scale animation curve, did not recognize target component");
+ continue;
+ }
+
+ const AnimationCurve* const curve = kv.second;
+ ai_assert(curve->GetKeys().size() == curve->GetValues().size() && curve->GetKeys().size());
+
+ //get values within the start/stop time window
+ std::shared_ptr<KeyTimeList> Keys(new KeyTimeList());
+ std::shared_ptr<KeyValueList> Values(new KeyValueList());
+ const size_t count = curve->GetKeys().size();
+ Keys->reserve(count);
+ Values->reserve(count);
+ for (size_t n = 0; n < count; n++)
+ {
+ int64_t k = curve->GetKeys().at(n);
+ if (k >= adj_start && k <= adj_stop)
+ {
+ Keys->push_back(k);
+ Values->push_back(curve->GetValues().at(n));
+ }
+ }
+
+ inputs.push_back(std::make_tuple(Keys, Values, mapto));
+ }
+ }
+ return inputs; // pray for NRVO :-)
+ }
+
+
+ KeyTimeList FBXConverter::GetKeyTimeList(const KeyFrameListList& inputs) {
+ ai_assert(!inputs.empty());
+
+ // reserve some space upfront - it is likely that the key-frame lists
+ // have matching time values, so max(of all key-frame lists) should
+ // be a good estimate.
+ KeyTimeList keys;
+
+ size_t estimate = 0;
+ for (const KeyFrameList& kfl : inputs) {
+ estimate = std::max(estimate, std::get<0>(kfl)->size());
+ }
+
+ keys.reserve(estimate);
+
+ std::vector<unsigned int> next_pos;
+ next_pos.resize(inputs.size(), 0);
+
+ const size_t count = inputs.size();
+ while (true) {
+
+ int64_t min_tick = std::numeric_limits<int64_t>::max();
+ for (size_t i = 0; i < count; ++i) {
+ const KeyFrameList& kfl = inputs[i];
+
+ if (std::get<0>(kfl)->size() > next_pos[i] && std::get<0>(kfl)->at(next_pos[i]) < min_tick) {
+ min_tick = std::get<0>(kfl)->at(next_pos[i]);
+ }
+ }
+
+ if (min_tick == std::numeric_limits<int64_t>::max()) {
+ break;
+ }
+ keys.push_back(min_tick);
+
+ for (size_t i = 0; i < count; ++i) {
+ const KeyFrameList& kfl = inputs[i];
+
+
+ while (std::get<0>(kfl)->size() > next_pos[i] && std::get<0>(kfl)->at(next_pos[i]) == min_tick) {
+ ++next_pos[i];
+ }
+ }
+ }
+
+ return keys;
+ }
+
+ void FBXConverter::InterpolateKeys(aiVectorKey* valOut, const KeyTimeList& keys, const KeyFrameListList& inputs,
+ const aiVector3D& def_value,
+ double& max_time,
+ double& min_time) {
+ ai_assert(!keys.empty());
+ ai_assert(nullptr != valOut);
+
+ std::vector<unsigned int> next_pos;
+ const size_t count(inputs.size());
+
+ next_pos.resize(inputs.size(), 0);
+
+ for (KeyTimeList::value_type time : keys) {
+ ai_real result[3] = { def_value.x, def_value.y, def_value.z };
+
+ for (size_t i = 0; i < count; ++i) {
+ const KeyFrameList& kfl = inputs[i];
+
+ const size_t ksize = std::get<0>(kfl)->size();
+ if (ksize == 0) {
+ continue;
+ }
+ if (ksize > next_pos[i] && std::get<0>(kfl)->at(next_pos[i]) == time) {
+ ++next_pos[i];
+ }
+
+ const size_t id0 = next_pos[i] > 0 ? next_pos[i] - 1 : 0;
+ const size_t id1 = next_pos[i] == ksize ? ksize - 1 : next_pos[i];
+
+ // use lerp for interpolation
+ const KeyValueList::value_type valueA = std::get<1>(kfl)->at(id0);
+ const KeyValueList::value_type valueB = std::get<1>(kfl)->at(id1);
+
+ const KeyTimeList::value_type timeA = std::get<0>(kfl)->at(id0);
+ const KeyTimeList::value_type timeB = std::get<0>(kfl)->at(id1);
+
+ const ai_real factor = timeB == timeA ? ai_real(0.) : static_cast<ai_real>((time - timeA)) / (timeB - timeA);
+ const ai_real interpValue = static_cast<ai_real>(valueA + (valueB - valueA) * factor);
+
+ result[std::get<2>(kfl)] = interpValue;
+ }
+
+ // magic value to convert fbx times to seconds
+ valOut->mTime = CONVERT_FBX_TIME(time) * anim_fps;
+
+ min_time = std::min(min_time, valOut->mTime);
+ max_time = std::max(max_time, valOut->mTime);
+
+ valOut->mValue.x = result[0];
+ valOut->mValue.y = result[1];
+ valOut->mValue.z = result[2];
+
+ ++valOut;
+ }
+ }
+
+ void FBXConverter::InterpolateKeys(aiQuatKey* valOut, const KeyTimeList& keys, const KeyFrameListList& inputs,
+ const aiVector3D& def_value,
+ double& maxTime,
+ double& minTime,
+ Model::RotOrder order)
+ {
+ ai_assert(!keys.empty());
+ ai_assert(nullptr != valOut);
+
+ std::unique_ptr<aiVectorKey[]> temp(new aiVectorKey[keys.size()]);
+ InterpolateKeys(temp.get(), keys, inputs, def_value, maxTime, minTime);
+
+ aiMatrix4x4 m;
+
+ aiQuaternion lastq;
+
+ for (size_t i = 0, c = keys.size(); i < c; ++i) {
+
+ valOut[i].mTime = temp[i].mTime;
+
+ GetRotationMatrix(order, temp[i].mValue, m);
+ aiQuaternion quat = aiQuaternion(aiMatrix3x3(m));
+
+ // take shortest path by checking the inner product
+ // http://www.3dkingdoms.com/weekly/weekly.php?a=36
+ if (quat.x * lastq.x + quat.y * lastq.y + quat.z * lastq.z + quat.w * lastq.w < 0)
+ {
+ quat.x = -quat.x;
+ quat.y = -quat.y;
+ quat.z = -quat.z;
+ quat.w = -quat.w;
+ }
+ lastq = quat;
+
+ valOut[i].mValue = quat;
+ }
+ }
+
+ void FBXConverter::ConvertTransformOrder_TRStoSRT(aiQuatKey* out_quat, aiVectorKey* out_scale,
+ aiVectorKey* out_translation,
+ const KeyFrameListList& scaling,
+ const KeyFrameListList& translation,
+ const KeyFrameListList& rotation,
+ const KeyTimeList& times,
+ double& maxTime,
+ double& minTime,
+ Model::RotOrder order,
+ const aiVector3D& def_scale,
+ const aiVector3D& def_translate,
+ const aiVector3D& def_rotation)
+ {
+ if (rotation.size()) {
+ InterpolateKeys(out_quat, times, rotation, def_rotation, maxTime, minTime, order);
+ }
+ else {
+ for (size_t i = 0; i < times.size(); ++i) {
+ out_quat[i].mTime = CONVERT_FBX_TIME(times[i]) * anim_fps;
+ out_quat[i].mValue = EulerToQuaternion(def_rotation, order);
+ }
+ }
+
+ if (scaling.size()) {
+ InterpolateKeys(out_scale, times, scaling, def_scale, maxTime, minTime);
+ }
+ else {
+ for (size_t i = 0; i < times.size(); ++i) {
+ out_scale[i].mTime = CONVERT_FBX_TIME(times[i]) * anim_fps;
+ out_scale[i].mValue = def_scale;
+ }
+ }
+
+ if (translation.size()) {
+ InterpolateKeys(out_translation, times, translation, def_translate, maxTime, minTime);
+ }
+ else {
+ for (size_t i = 0; i < times.size(); ++i) {
+ out_translation[i].mTime = CONVERT_FBX_TIME(times[i]) * anim_fps;
+ out_translation[i].mValue = def_translate;
+ }
+ }
+
+ const size_t count = times.size();
+ for (size_t i = 0; i < count; ++i) {
+ aiQuaternion& r = out_quat[i].mValue;
+ aiVector3D& s = out_scale[i].mValue;
+ aiVector3D& t = out_translation[i].mValue;
+
+ aiMatrix4x4 mat, temp;
+ aiMatrix4x4::Translation(t, mat);
+ mat *= aiMatrix4x4(r.GetMatrix());
+ mat *= aiMatrix4x4::Scaling(s, temp);
+
+ mat.Decompose(s, r, t);
+ }
+ }
+
+ aiQuaternion FBXConverter::EulerToQuaternion(const aiVector3D& rot, Model::RotOrder order)
+ {
+ aiMatrix4x4 m;
+ GetRotationMatrix(order, rot, m);
+
+ return aiQuaternion(aiMatrix3x3(m));
+ }
+
+ void FBXConverter::ConvertScaleKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, const LayerMap& /*layers*/,
+ int64_t start, int64_t stop,
+ double& maxTime,
+ double& minTime)
+ {
+ ai_assert(nodes.size());
+
+ // XXX for now, assume scale should be blended geometrically (i.e. two
+ // layers should be multiplied with each other). There is a FBX
+ // property in the layer to specify the behaviour, though.
+
+ const KeyFrameListList& inputs = GetKeyframeList(nodes, start, stop);
+ const KeyTimeList& keys = GetKeyTimeList(inputs);
+
+ na->mNumScalingKeys = static_cast<unsigned int>(keys.size());
+ na->mScalingKeys = new aiVectorKey[keys.size()];
+ if (keys.size() > 0)
+ InterpolateKeys(na->mScalingKeys, keys, inputs, aiVector3D(1.0f, 1.0f, 1.0f), maxTime, minTime);
+ }
+
+ void FBXConverter::ConvertTranslationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes,
+ const LayerMap& /*layers*/,
+ int64_t start, int64_t stop,
+ double& maxTime,
+ double& minTime)
+ {
+ ai_assert(nodes.size());
+
+ // XXX see notes in ConvertScaleKeys()
+ const KeyFrameListList& inputs = GetKeyframeList(nodes, start, stop);
+ const KeyTimeList& keys = GetKeyTimeList(inputs);
+
+ na->mNumPositionKeys = static_cast<unsigned int>(keys.size());
+ na->mPositionKeys = new aiVectorKey[keys.size()];
+ if (keys.size() > 0)
+ InterpolateKeys(na->mPositionKeys, keys, inputs, aiVector3D(0.0f, 0.0f, 0.0f), maxTime, minTime);
+ }
+
+ void FBXConverter::ConvertRotationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes,
+ const LayerMap& /*layers*/,
+ int64_t start, int64_t stop,
+ double& maxTime,
+ double& minTime,
+ Model::RotOrder order)
+ {
+ ai_assert(nodes.size());
+
+ // XXX see notes in ConvertScaleKeys()
+ const std::vector< KeyFrameList >& inputs = GetKeyframeList(nodes, start, stop);
+ const KeyTimeList& keys = GetKeyTimeList(inputs);
+
+ na->mNumRotationKeys = static_cast<unsigned int>(keys.size());
+ na->mRotationKeys = new aiQuatKey[keys.size()];
+ if (!keys.empty()) {
+ InterpolateKeys(na->mRotationKeys, keys, inputs, aiVector3D(0.0f, 0.0f, 0.0f), maxTime, minTime, order);
+ }
+ }
+
+ void FBXConverter::ConvertGlobalSettings() {
+ if (nullptr == out) {
+ return;
+ }
+
+ out->mMetaData = aiMetadata::Alloc(15);
+ out->mMetaData->Set(0, "UpAxis", doc.GlobalSettings().UpAxis());
+ out->mMetaData->Set(1, "UpAxisSign", doc.GlobalSettings().UpAxisSign());
+ out->mMetaData->Set(2, "FrontAxis", doc.GlobalSettings().FrontAxis());
+ out->mMetaData->Set(3, "FrontAxisSign", doc.GlobalSettings().FrontAxisSign());
+ out->mMetaData->Set(4, "CoordAxis", doc.GlobalSettings().CoordAxis());
+ out->mMetaData->Set(5, "CoordAxisSign", doc.GlobalSettings().CoordAxisSign());
+ out->mMetaData->Set(6, "OriginalUpAxis", doc.GlobalSettings().OriginalUpAxis());
+ out->mMetaData->Set(7, "OriginalUpAxisSign", doc.GlobalSettings().OriginalUpAxisSign());
+ out->mMetaData->Set(8, "UnitScaleFactor", (double)doc.GlobalSettings().UnitScaleFactor());
+ out->mMetaData->Set(9, "OriginalUnitScaleFactor", doc.GlobalSettings().OriginalUnitScaleFactor());
+ out->mMetaData->Set(10, "AmbientColor", doc.GlobalSettings().AmbientColor());
+ out->mMetaData->Set(11, "FrameRate", (int)doc.GlobalSettings().TimeMode());
+ out->mMetaData->Set(12, "TimeSpanStart", doc.GlobalSettings().TimeSpanStart());
+ out->mMetaData->Set(13, "TimeSpanStop", doc.GlobalSettings().TimeSpanStop());
+ out->mMetaData->Set(14, "CustomFrameRate", doc.GlobalSettings().CustomFrameRate());
+ }
+
+ void FBXConverter::TransferDataToScene()
+ {
+ ai_assert(!out->mMeshes);
+ ai_assert(!out->mNumMeshes);
+
+ // note: the trailing () ensures initialization with NULL - not
+ // many C++ users seem to know this, so pointing it out to avoid
+ // confusion why this code works.
+
+ if (meshes.size()) {
+ out->mMeshes = new aiMesh*[meshes.size()]();
+ out->mNumMeshes = static_cast<unsigned int>(meshes.size());
+
+ std::swap_ranges(meshes.begin(), meshes.end(), out->mMeshes);
+ }
+
+ if (materials.size()) {
+ out->mMaterials = new aiMaterial*[materials.size()]();
+ out->mNumMaterials = static_cast<unsigned int>(materials.size());
+
+ std::swap_ranges(materials.begin(), materials.end(), out->mMaterials);
+ }
+
+ if (animations.size()) {
+ out->mAnimations = new aiAnimation*[animations.size()]();
+ out->mNumAnimations = static_cast<unsigned int>(animations.size());
+
+ std::swap_ranges(animations.begin(), animations.end(), out->mAnimations);
+ }
+
+ if (lights.size()) {
+ out->mLights = new aiLight*[lights.size()]();
+ out->mNumLights = static_cast<unsigned int>(lights.size());
+
+ std::swap_ranges(lights.begin(), lights.end(), out->mLights);
+ }
+
+ if (cameras.size()) {
+ out->mCameras = new aiCamera*[cameras.size()]();
+ out->mNumCameras = static_cast<unsigned int>(cameras.size());
+
+ std::swap_ranges(cameras.begin(), cameras.end(), out->mCameras);
+ }
+
+ if (textures.size()) {
+ out->mTextures = new aiTexture*[textures.size()]();
+ out->mNumTextures = static_cast<unsigned int>(textures.size());
+
+ std::swap_ranges(textures.begin(), textures.end(), out->mTextures);
+ }
+ }
+
+ // ------------------------------------------------------------------------------------------------
+ void ConvertToAssimpScene(aiScene* out, const Document& doc)
+ {
+ FBXConverter converter(out, doc);
+ }
+
+ } // !FBX
+} // !Assimp
+
+#endif
diff --git a/thirdparty/assimp/code/FBXConverter.h b/thirdparty/assimp/code/FBXConverter.h
new file mode 100644
index 0000000000..50637468b9
--- /dev/null
+++ b/thirdparty/assimp/code/FBXConverter.h
@@ -0,0 +1,461 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file FBXDConverter.h
+ * @brief FBX DOM to aiScene conversion
+ */
+#ifndef INCLUDED_AI_FBX_CONVERTER_H
+#define INCLUDED_AI_FBX_CONVERTER_H
+
+#include "FBXParser.h"
+#include "FBXMeshGeometry.h"
+#include "FBXDocument.h"
+#include "FBXUtil.h"
+#include "FBXProperties.h"
+#include "FBXImporter.h"
+#include <assimp/anim.h>
+#include <assimp/material.h>
+#include <assimp/light.h>
+#include <assimp/texture.h>
+#include <assimp/camera.h>
+#include <assimp/StringComparison.h>
+#include <unordered_map>
+#include <unordered_set>
+
+struct aiScene;
+struct aiNode;
+struct aiMaterial;
+
+struct morphKeyData {
+ std::vector<unsigned int> values;
+ std::vector<float> weights;
+};
+typedef std::map<int64_t, morphKeyData*> morphAnimData;
+
+namespace Assimp {
+namespace FBX {
+
+class Document;
+
+/**
+ * Convert a FBX #Document to #aiScene
+ * @param out Empty scene to be populated
+ * @param doc Parsed FBX document
+ */
+void ConvertToAssimpScene(aiScene* out, const Document& doc);
+
+/** Dummy class to encapsulate the conversion process */
+class FBXConverter {
+public:
+ /**
+ * The different parts that make up the final local transformation of a fbx-node
+ */
+ enum TransformationComp {
+ TransformationComp_GeometricScalingInverse = 0,
+ TransformationComp_GeometricRotationInverse,
+ TransformationComp_GeometricTranslationInverse,
+ TransformationComp_Translation,
+ TransformationComp_RotationOffset,
+ TransformationComp_RotationPivot,
+ TransformationComp_PreRotation,
+ TransformationComp_Rotation,
+ TransformationComp_PostRotation,
+ TransformationComp_RotationPivotInverse,
+ TransformationComp_ScalingOffset,
+ TransformationComp_ScalingPivot,
+ TransformationComp_Scaling,
+ TransformationComp_ScalingPivotInverse,
+ TransformationComp_GeometricTranslation,
+ TransformationComp_GeometricRotation,
+ TransformationComp_GeometricScaling,
+
+ TransformationComp_MAXIMUM
+ };
+
+public:
+ FBXConverter(aiScene* out, const Document& doc);
+ ~FBXConverter();
+
+private:
+ // ------------------------------------------------------------------------------------------------
+ // find scene root and trigger recursive scene conversion
+ void ConvertRootNode();
+
+ // ------------------------------------------------------------------------------------------------
+ // collect and assign child nodes
+ void ConvertNodes(uint64_t id, aiNode& parent, const aiMatrix4x4& parent_transform = aiMatrix4x4());
+
+ // ------------------------------------------------------------------------------------------------
+ void ConvertLights(const Model& model, const std::string &orig_name );
+
+ // ------------------------------------------------------------------------------------------------
+ void ConvertCameras(const Model& model, const std::string &orig_name );
+
+ // ------------------------------------------------------------------------------------------------
+ void ConvertLight( const Light& light, const std::string &orig_name );
+
+ // ------------------------------------------------------------------------------------------------
+ void ConvertCamera( const Camera& cam, const std::string &orig_name );
+
+ // ------------------------------------------------------------------------------------------------
+ void GetUniqueName( const std::string &name, std::string& uniqueName );
+
+ // ------------------------------------------------------------------------------------------------
+ // this returns unified names usable within assimp identifiers (i.e. no space characters -
+ // while these would be allowed, they are a potential trouble spot so better not use them).
+ const char* NameTransformationComp(TransformationComp comp);
+
+ // ------------------------------------------------------------------------------------------------
+ // note: this returns the REAL fbx property names
+ const char* NameTransformationCompProperty(TransformationComp comp);
+
+ // ------------------------------------------------------------------------------------------------
+ aiVector3D TransformationCompDefaultValue(TransformationComp comp);
+
+ // ------------------------------------------------------------------------------------------------
+ void GetRotationMatrix(Model::RotOrder mode, const aiVector3D& rotation, aiMatrix4x4& out);
+ // ------------------------------------------------------------------------------------------------
+ /**
+ * checks if a node has more than just scaling, rotation and translation components
+ */
+ bool NeedsComplexTransformationChain(const Model& model);
+
+ // ------------------------------------------------------------------------------------------------
+ // note: name must be a FixNodeName() result
+ std::string NameTransformationChainNode(const std::string& name, TransformationComp comp);
+
+ // ------------------------------------------------------------------------------------------------
+ /**
+ * note: memory for output_nodes will be managed by the caller
+ */
+ void GenerateTransformationNodeChain(const Model& model, std::vector<aiNode*>& output_nodes, std::vector<aiNode*>& post_output_nodes);
+
+ // ------------------------------------------------------------------------------------------------
+ void SetupNodeMetadata(const Model& model, aiNode& nd);
+
+ // ------------------------------------------------------------------------------------------------
+ void ConvertModel(const Model& model, aiNode& nd, const aiMatrix4x4& node_global_transform);
+
+ // ------------------------------------------------------------------------------------------------
+ // MeshGeometry -> aiMesh, return mesh index + 1 or 0 if the conversion failed
+ std::vector<unsigned int> ConvertMesh(const MeshGeometry& mesh, const Model& model,
+ const aiMatrix4x4& node_global_transform, aiNode& nd);
+
+ // ------------------------------------------------------------------------------------------------
+ std::vector<unsigned int> ConvertLine(const LineGeometry& line, const Model& model,
+ const aiMatrix4x4& node_global_transform, aiNode& nd);
+
+ // ------------------------------------------------------------------------------------------------
+ aiMesh* SetupEmptyMesh(const Geometry& mesh, aiNode& nd);
+
+ // ------------------------------------------------------------------------------------------------
+ unsigned int ConvertMeshSingleMaterial(const MeshGeometry& mesh, const Model& model,
+ const aiMatrix4x4& node_global_transform, aiNode& nd);
+
+ // ------------------------------------------------------------------------------------------------
+ std::vector<unsigned int> ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model,
+ const aiMatrix4x4& node_global_transform, aiNode& nd);
+
+ // ------------------------------------------------------------------------------------------------
+ unsigned int ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model,
+ MatIndexArray::value_type index,
+ const aiMatrix4x4& node_global_transform, aiNode& nd);
+
+ // ------------------------------------------------------------------------------------------------
+ static const unsigned int NO_MATERIAL_SEPARATION = /* std::numeric_limits<unsigned int>::max() */
+ static_cast<unsigned int>(-1);
+
+ // ------------------------------------------------------------------------------------------------
+ /**
+ * - if materialIndex == NO_MATERIAL_SEPARATION, materials are not taken into
+ * account when determining which weights to include.
+ * - outputVertStartIndices is only used when a material index is specified, it gives for
+ * each output vertex the DOM index it maps to.
+ */
+ void ConvertWeights(aiMesh* out, const Model& model, const MeshGeometry& geo,
+ const aiMatrix4x4& node_global_transform = aiMatrix4x4(),
+ unsigned int materialIndex = NO_MATERIAL_SEPARATION,
+ std::vector<unsigned int>* outputVertStartIndices = NULL);
+
+ // ------------------------------------------------------------------------------------------------
+ void ConvertCluster(std::vector<aiBone*>& bones, const Model& /*model*/, const Cluster& cl,
+ std::vector<size_t>& out_indices,
+ std::vector<size_t>& index_out_indices,
+ std::vector<size_t>& count_out_indices,
+ const aiMatrix4x4& node_global_transform);
+
+ // ------------------------------------------------------------------------------------------------
+ void ConvertMaterialForMesh(aiMesh* out, const Model& model, const MeshGeometry& geo,
+ MatIndexArray::value_type materialIndex);
+
+ // ------------------------------------------------------------------------------------------------
+ unsigned int GetDefaultMaterial();
+
+ // ------------------------------------------------------------------------------------------------
+ // Material -> aiMaterial
+ unsigned int ConvertMaterial(const Material& material, const MeshGeometry* const mesh);
+
+ // ------------------------------------------------------------------------------------------------
+ // Video -> aiTexture
+ unsigned int ConvertVideo(const Video& video);
+
+ // ------------------------------------------------------------------------------------------------
+ // convert embedded texture if necessary and return actual texture path
+ aiString GetTexturePath(const Texture* tex);
+
+ // ------------------------------------------------------------------------------------------------
+ void TrySetTextureProperties(aiMaterial* out_mat, const TextureMap& textures,
+ const std::string& propName,
+ aiTextureType target, const MeshGeometry* const mesh);
+
+ // ------------------------------------------------------------------------------------------------
+ void TrySetTextureProperties(aiMaterial* out_mat, const LayeredTextureMap& layeredTextures,
+ const std::string& propName,
+ aiTextureType target, const MeshGeometry* const mesh);
+
+ // ------------------------------------------------------------------------------------------------
+ void SetTextureProperties(aiMaterial* out_mat, const TextureMap& textures, const MeshGeometry* const mesh);
+
+ // ------------------------------------------------------------------------------------------------
+ void SetTextureProperties(aiMaterial* out_mat, const LayeredTextureMap& layeredTextures, const MeshGeometry* const mesh);
+
+ // ------------------------------------------------------------------------------------------------
+ aiColor3D GetColorPropertyFromMaterial(const PropertyTable& props, const std::string& baseName,
+ bool& result);
+ aiColor3D GetColorPropertyFactored(const PropertyTable& props, const std::string& colorName,
+ const std::string& factorName, bool& result, bool useTemplate = true);
+ aiColor3D GetColorProperty(const PropertyTable& props, const std::string& colorName,
+ bool& result, bool useTemplate = true);
+
+ // ------------------------------------------------------------------------------------------------
+ void SetShadingPropertiesCommon(aiMaterial* out_mat, const PropertyTable& props);
+ void SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTable& props, const TextureMap& textures, const MeshGeometry* const mesh);
+
+ // ------------------------------------------------------------------------------------------------
+ // get the number of fps for a FrameRate enumerated value
+ static double FrameRateToDouble(FileGlobalSettings::FrameRate fp, double customFPSVal = -1.0);
+
+ // ------------------------------------------------------------------------------------------------
+ // convert animation data to aiAnimation et al
+ void ConvertAnimations();
+
+ // ------------------------------------------------------------------------------------------------
+ // takes a fbx node name and returns the identifier to be used in the assimp output scene.
+ // the function is guaranteed to provide consistent results over multiple invocations
+ // UNLESS RenameNode() is called for a particular node name.
+ std::string FixNodeName(const std::string& name);
+ std::string FixAnimMeshName(const std::string& name);
+
+ typedef std::map<const AnimationCurveNode*, const AnimationLayer*> LayerMap;
+
+ // XXX: better use multi_map ..
+ typedef std::map<std::string, std::vector<const AnimationCurveNode*> > NodeMap;
+
+ // ------------------------------------------------------------------------------------------------
+ void ConvertAnimationStack(const AnimationStack& st);
+
+ // ------------------------------------------------------------------------------------------------
+ void ProcessMorphAnimDatas(std::map<std::string, morphAnimData*>* morphAnimDatas, const BlendShapeChannel* bsc, const AnimationCurveNode* node);
+
+ // ------------------------------------------------------------------------------------------------
+ void GenerateNodeAnimations(std::vector<aiNodeAnim*>& node_anims,
+ const std::string& fixed_name,
+ const std::vector<const AnimationCurveNode*>& curves,
+ const LayerMap& layer_map,
+ int64_t start, int64_t stop,
+ double& max_time,
+ double& min_time);
+
+ // ------------------------------------------------------------------------------------------------
+ bool IsRedundantAnimationData(const Model& target,
+ TransformationComp comp,
+ const std::vector<const AnimationCurveNode*>& curves);
+
+ // ------------------------------------------------------------------------------------------------
+ aiNodeAnim* GenerateRotationNodeAnim(const std::string& name,
+ const Model& target,
+ const std::vector<const AnimationCurveNode*>& curves,
+ const LayerMap& layer_map,
+ int64_t start, int64_t stop,
+ double& max_time,
+ double& min_time);
+
+ // ------------------------------------------------------------------------------------------------
+ aiNodeAnim* GenerateScalingNodeAnim(const std::string& name,
+ const Model& /*target*/,
+ const std::vector<const AnimationCurveNode*>& curves,
+ const LayerMap& layer_map,
+ int64_t start, int64_t stop,
+ double& max_time,
+ double& min_time);
+
+ // ------------------------------------------------------------------------------------------------
+ aiNodeAnim* GenerateTranslationNodeAnim(const std::string& name,
+ const Model& /*target*/,
+ const std::vector<const AnimationCurveNode*>& curves,
+ const LayerMap& layer_map,
+ int64_t start, int64_t stop,
+ double& max_time,
+ double& min_time,
+ bool inverse = false);
+
+ // ------------------------------------------------------------------------------------------------
+ // generate node anim, extracting only Rotation, Scaling and Translation from the given chain
+ aiNodeAnim* GenerateSimpleNodeAnim(const std::string& name,
+ const Model& target,
+ NodeMap::const_iterator chain[TransformationComp_MAXIMUM],
+ NodeMap::const_iterator iter_end,
+ const LayerMap& layer_map,
+ int64_t start, int64_t stop,
+ double& max_time,
+ double& min_time,
+ bool reverse_order = false);
+
+ // key (time), value, mapto (component index)
+ typedef std::tuple<std::shared_ptr<KeyTimeList>, std::shared_ptr<KeyValueList>, unsigned int > KeyFrameList;
+ typedef std::vector<KeyFrameList> KeyFrameListList;
+
+ // ------------------------------------------------------------------------------------------------
+ KeyFrameListList GetKeyframeList(const std::vector<const AnimationCurveNode*>& nodes, int64_t start, int64_t stop);
+
+ // ------------------------------------------------------------------------------------------------
+ KeyTimeList GetKeyTimeList(const KeyFrameListList& inputs);
+
+ // ------------------------------------------------------------------------------------------------
+ void InterpolateKeys(aiVectorKey* valOut, const KeyTimeList& keys, const KeyFrameListList& inputs,
+ const aiVector3D& def_value,
+ double& max_time,
+ double& min_time);
+
+ // ------------------------------------------------------------------------------------------------
+ void InterpolateKeys(aiQuatKey* valOut, const KeyTimeList& keys, const KeyFrameListList& inputs,
+ const aiVector3D& def_value,
+ double& maxTime,
+ double& minTime,
+ Model::RotOrder order);
+
+ // ------------------------------------------------------------------------------------------------
+ void ConvertTransformOrder_TRStoSRT(aiQuatKey* out_quat, aiVectorKey* out_scale,
+ aiVectorKey* out_translation,
+ const KeyFrameListList& scaling,
+ const KeyFrameListList& translation,
+ const KeyFrameListList& rotation,
+ const KeyTimeList& times,
+ double& maxTime,
+ double& minTime,
+ Model::RotOrder order,
+ const aiVector3D& def_scale,
+ const aiVector3D& def_translate,
+ const aiVector3D& def_rotation);
+
+ // ------------------------------------------------------------------------------------------------
+ // euler xyz -> quat
+ aiQuaternion EulerToQuaternion(const aiVector3D& rot, Model::RotOrder order);
+
+ // ------------------------------------------------------------------------------------------------
+ void ConvertScaleKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, const LayerMap& /*layers*/,
+ int64_t start, int64_t stop,
+ double& maxTime,
+ double& minTime);
+
+ // ------------------------------------------------------------------------------------------------
+ void ConvertTranslationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes,
+ const LayerMap& /*layers*/,
+ int64_t start, int64_t stop,
+ double& maxTime,
+ double& minTime);
+
+ // ------------------------------------------------------------------------------------------------
+ void ConvertRotationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes,
+ const LayerMap& /*layers*/,
+ int64_t start, int64_t stop,
+ double& maxTime,
+ double& minTime,
+ Model::RotOrder order);
+
+ void ConvertGlobalSettings();
+
+ // ------------------------------------------------------------------------------------------------
+ // copy generated meshes, animations, lights, cameras and textures to the output scene
+ void TransferDataToScene();
+
+private:
+ // 0: not assigned yet, others: index is value - 1
+ unsigned int defaultMaterialIndex;
+
+ std::vector<aiMesh*> meshes;
+ std::vector<aiMaterial*> materials;
+ std::vector<aiAnimation*> animations;
+ std::vector<aiLight*> lights;
+ std::vector<aiCamera*> cameras;
+ std::vector<aiTexture*> textures;
+
+ using MaterialMap = std::map<const Material*, unsigned int>;
+ MaterialMap materials_converted;
+
+ using VideoMap = std::map<const Video*, unsigned int>;
+ VideoMap textures_converted;
+
+ using MeshMap = std::map<const Geometry*, std::vector<unsigned int> >;
+ MeshMap meshes_converted;
+
+ // fixed node name -> which trafo chain components have animations?
+ using NodeAnimBitMap = std::map<std::string, unsigned int> ;
+ NodeAnimBitMap node_anim_chain_bits;
+
+ // number of nodes with the same name
+ using NodeAnimNameMap = std::unordered_map<std::string, unsigned int>;
+ NodeAnimNameMap mNodeNameInstances;
+
+ using NodeNameCache = std::unordered_set<std::string>;
+ NodeNameCache mNodeNames;
+
+ double anim_fps;
+
+ aiScene* const out;
+ const FBX::Document& doc;
+};
+
+}
+}
+
+#endif // INCLUDED_AI_FBX_CONVERTER_H
diff --git a/thirdparty/assimp/code/FBXDeformer.cpp b/thirdparty/assimp/code/FBXDeformer.cpp
new file mode 100644
index 0000000000..6927553450
--- /dev/null
+++ b/thirdparty/assimp/code/FBXDeformer.cpp
@@ -0,0 +1,213 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file FBXNoteAttribute.cpp
+ * @brief Assimp::FBX::NodeAttribute (and subclasses) implementation
+ */
+
+#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
+
+#include "FBXParser.h"
+#include "FBXDocument.h"
+#include "FBXMeshGeometry.h"
+#include "FBXImporter.h"
+#include "FBXDocumentUtil.h"
+
+namespace Assimp {
+namespace FBX {
+
+using namespace Util;
+
+// ------------------------------------------------------------------------------------------------
+Deformer::Deformer(uint64_t id, const Element& element, const Document& doc, const std::string& name)
+ : Object(id,element,name)
+{
+ const Scope& sc = GetRequiredScope(element);
+
+ const std::string& classname = ParseTokenAsString(GetRequiredToken(element,2));
+ props = GetPropertyTable(doc,"Deformer.Fbx" + classname,element,sc,true);
+}
+
+
+// ------------------------------------------------------------------------------------------------
+Deformer::~Deformer()
+{
+
+}
+
+
+// ------------------------------------------------------------------------------------------------
+Cluster::Cluster(uint64_t id, const Element& element, const Document& doc, const std::string& name)
+: Deformer(id,element,doc,name)
+, node()
+{
+ const Scope& sc = GetRequiredScope(element);
+
+ const Element* const Indexes = sc["Indexes"];
+ const Element* const Weights = sc["Weights"];
+
+ const Element& Transform = GetRequiredElement(sc,"Transform",&element);
+ const Element& TransformLink = GetRequiredElement(sc,"TransformLink",&element);
+
+ transform = ReadMatrix(Transform);
+ transformLink = ReadMatrix(TransformLink);
+
+ // it is actually possible that there be Deformer's with no weights
+ if (!!Indexes != !!Weights) {
+ DOMError("either Indexes or Weights are missing from Cluster",&element);
+ }
+
+ if(Indexes) {
+ ParseVectorDataArray(indices,*Indexes);
+ ParseVectorDataArray(weights,*Weights);
+ }
+
+ if(indices.size() != weights.size()) {
+ DOMError("sizes of index and weight array don't match up",&element);
+ }
+
+ // read assigned node
+ const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"Model");
+ for(const Connection* con : conns) {
+ const Model* const mod = ProcessSimpleConnection<Model>(*con, false, "Model -> Cluster", element);
+ if(mod) {
+ node = mod;
+ break;
+ }
+ }
+
+ if (!node) {
+ DOMError("failed to read target Node for Cluster",&element);
+ }
+}
+
+
+// ------------------------------------------------------------------------------------------------
+Cluster::~Cluster()
+{
+
+}
+
+
+// ------------------------------------------------------------------------------------------------
+Skin::Skin(uint64_t id, const Element& element, const Document& doc, const std::string& name)
+: Deformer(id,element,doc,name)
+, accuracy( 0.0f ) {
+ const Scope& sc = GetRequiredScope(element);
+
+ const Element* const Link_DeformAcuracy = sc["Link_DeformAcuracy"];
+ if(Link_DeformAcuracy) {
+ accuracy = ParseTokenAsFloat(GetRequiredToken(*Link_DeformAcuracy,0));
+ }
+
+ // resolve assigned clusters
+ const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"Deformer");
+
+ clusters.reserve(conns.size());
+ for(const Connection* con : conns) {
+
+ const Cluster* const cluster = ProcessSimpleConnection<Cluster>(*con, false, "Cluster -> Skin", element);
+ if(cluster) {
+ clusters.push_back(cluster);
+ continue;
+ }
+ }
+}
+
+
+// ------------------------------------------------------------------------------------------------
+Skin::~Skin()
+{
+
+}
+// ------------------------------------------------------------------------------------------------
+BlendShape::BlendShape(uint64_t id, const Element& element, const Document& doc, const std::string& name)
+ : Deformer(id, element, doc, name)
+{
+ const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(), "Deformer");
+ blendShapeChannels.reserve(conns.size());
+ for (const Connection* con : conns) {
+ const BlendShapeChannel* const bspc = ProcessSimpleConnection<BlendShapeChannel>(*con, false, "BlendShapeChannel -> BlendShape", element);
+ if (bspc) {
+ blendShapeChannels.push_back(bspc);
+ continue;
+ }
+ }
+}
+// ------------------------------------------------------------------------------------------------
+BlendShape::~BlendShape()
+{
+
+}
+// ------------------------------------------------------------------------------------------------
+BlendShapeChannel::BlendShapeChannel(uint64_t id, const Element& element, const Document& doc, const std::string& name)
+ : Deformer(id, element, doc, name)
+{
+ const Scope& sc = GetRequiredScope(element);
+ const Element* const DeformPercent = sc["DeformPercent"];
+ if (DeformPercent) {
+ percent = ParseTokenAsFloat(GetRequiredToken(*DeformPercent, 0));
+ }
+ const Element* const FullWeights = sc["FullWeights"];
+ if (FullWeights) {
+ ParseVectorDataArray(fullWeights, *FullWeights);
+ }
+ const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(), "Geometry");
+ shapeGeometries.reserve(conns.size());
+ for (const Connection* con : conns) {
+ const ShapeGeometry* const sg = ProcessSimpleConnection<ShapeGeometry>(*con, false, "Shape -> BlendShapeChannel", element);
+ if (sg) {
+ shapeGeometries.push_back(sg);
+ continue;
+ }
+ }
+}
+// ------------------------------------------------------------------------------------------------
+BlendShapeChannel::~BlendShapeChannel()
+{
+
+}
+// ------------------------------------------------------------------------------------------------
+}
+}
+#endif
+
diff --git a/thirdparty/assimp/code/FBXDocument.cpp b/thirdparty/assimp/code/FBXDocument.cpp
new file mode 100644
index 0000000000..1af08fe6d8
--- /dev/null
+++ b/thirdparty/assimp/code/FBXDocument.cpp
@@ -0,0 +1,726 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the*
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file FBXDocument.cpp
+ * @brief Implementation of the FBX DOM classes
+ */
+
+#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
+
+#include "FBXDocument.h"
+#include "FBXMeshGeometry.h"
+#include "FBXParser.h"
+#include "FBXUtil.h"
+#include "FBXImporter.h"
+#include "FBXImportSettings.h"
+#include "FBXDocumentUtil.h"
+#include "FBXProperties.h"
+
+#include <memory>
+#include <functional>
+#include <map>
+
+namespace Assimp {
+namespace FBX {
+
+using namespace Util;
+
+// ------------------------------------------------------------------------------------------------
+LazyObject::LazyObject(uint64_t id, const Element& element, const Document& doc)
+: doc(doc)
+, element(element)
+, id(id)
+, flags() {
+ // empty
+}
+
+// ------------------------------------------------------------------------------------------------
+LazyObject::~LazyObject()
+{
+ // empty
+}
+
+// ------------------------------------------------------------------------------------------------
+const Object* LazyObject::Get(bool dieOnError)
+{
+ if(IsBeingConstructed() || FailedToConstruct()) {
+ return nullptr;
+ }
+
+ if (object.get()) {
+ return object.get();
+ }
+
+ // if this is the root object, we return a dummy since there
+ // is no root object int he fbx file - it is just referenced
+ // with id 0.
+ if(id == 0L) {
+ object.reset(new Object(id, element, "Model::RootNode"));
+ return object.get();
+ }
+
+ const Token& key = element.KeyToken();
+ const TokenList& tokens = element.Tokens();
+
+ if(tokens.size() < 3) {
+ DOMError("expected at least 3 tokens: id, name and class tag",&element);
+ }
+
+ const char* err;
+ std::string name = ParseTokenAsString(*tokens[1],err);
+ if (err) {
+ DOMError(err,&element);
+ }
+
+ // small fix for binary reading: binary fbx files don't use
+ // prefixes such as Model:: in front of their names. The
+ // loading code expects this at many places, though!
+ // so convert the binary representation (a 0x0001) to the
+ // double colon notation.
+ if(tokens[1]->IsBinary()) {
+ for (size_t i = 0; i < name.length(); ++i) {
+ if (name[i] == 0x0 && name[i+1] == 0x1) {
+ name = name.substr(i+2) + "::" + name.substr(0,i);
+ }
+ }
+ }
+
+ const std::string classtag = ParseTokenAsString(*tokens[2],err);
+ if (err) {
+ DOMError(err,&element);
+ }
+
+ // prevent recursive calls
+ flags |= BEING_CONSTRUCTED;
+
+ try {
+ // this needs to be relatively fast since it happens a lot,
+ // so avoid constructing strings all the time.
+ const char* obtype = key.begin();
+ const size_t length = static_cast<size_t>(key.end()-key.begin());
+
+ // For debugging
+ //dumpObjectClassInfo( objtype, classtag );
+
+ if (!strncmp(obtype,"Geometry",length)) {
+ if (!strcmp(classtag.c_str(),"Mesh")) {
+ object.reset(new MeshGeometry(id,element,name,doc));
+ }
+ if (!strcmp(classtag.c_str(), "Shape")) {
+ object.reset(new ShapeGeometry(id, element, name, doc));
+ }
+ if (!strcmp(classtag.c_str(), "Line")) {
+ object.reset(new LineGeometry(id, element, name, doc));
+ }
+ }
+ else if (!strncmp(obtype,"NodeAttribute",length)) {
+ if (!strcmp(classtag.c_str(),"Camera")) {
+ object.reset(new Camera(id,element,doc,name));
+ }
+ else if (!strcmp(classtag.c_str(),"CameraSwitcher")) {
+ object.reset(new CameraSwitcher(id,element,doc,name));
+ }
+ else if (!strcmp(classtag.c_str(),"Light")) {
+ object.reset(new Light(id,element,doc,name));
+ }
+ else if (!strcmp(classtag.c_str(),"Null")) {
+ object.reset(new Null(id,element,doc,name));
+ }
+ else if (!strcmp(classtag.c_str(),"LimbNode")) {
+ object.reset(new LimbNode(id,element,doc,name));
+ }
+ }
+ else if (!strncmp(obtype,"Deformer",length)) {
+ if (!strcmp(classtag.c_str(),"Cluster")) {
+ object.reset(new Cluster(id,element,doc,name));
+ }
+ else if (!strcmp(classtag.c_str(),"Skin")) {
+ object.reset(new Skin(id,element,doc,name));
+ }
+ else if (!strcmp(classtag.c_str(), "BlendShape")) {
+ object.reset(new BlendShape(id, element, doc, name));
+ }
+ else if (!strcmp(classtag.c_str(), "BlendShapeChannel")) {
+ object.reset(new BlendShapeChannel(id, element, doc, name));
+ }
+ }
+ else if ( !strncmp( obtype, "Model", length ) ) {
+ // FK and IK effectors are not supported
+ if ( strcmp( classtag.c_str(), "IKEffector" ) && strcmp( classtag.c_str(), "FKEffector" ) ) {
+ object.reset( new Model( id, element, doc, name ) );
+ }
+ }
+ else if (!strncmp(obtype,"Material",length)) {
+ object.reset(new Material(id,element,doc,name));
+ }
+ else if (!strncmp(obtype,"Texture",length)) {
+ object.reset(new Texture(id,element,doc,name));
+ }
+ else if (!strncmp(obtype,"LayeredTexture",length)) {
+ object.reset(new LayeredTexture(id,element,doc,name));
+ }
+ else if (!strncmp(obtype,"Video",length)) {
+ object.reset(new Video(id,element,doc,name));
+ }
+ else if (!strncmp(obtype,"AnimationStack",length)) {
+ object.reset(new AnimationStack(id,element,name,doc));
+ }
+ else if (!strncmp(obtype,"AnimationLayer",length)) {
+ object.reset(new AnimationLayer(id,element,name,doc));
+ }
+ // note: order matters for these two
+ else if (!strncmp(obtype,"AnimationCurve",length)) {
+ object.reset(new AnimationCurve(id,element,name,doc));
+ }
+ else if (!strncmp(obtype,"AnimationCurveNode",length)) {
+ object.reset(new AnimationCurveNode(id,element,name,doc));
+ }
+ }
+ catch(std::exception& ex) {
+ flags &= ~BEING_CONSTRUCTED;
+ flags |= FAILED_TO_CONSTRUCT;
+
+ if(dieOnError || doc.Settings().strictMode) {
+ throw;
+ }
+
+ // note: the error message is already formatted, so raw logging is ok
+ if(!DefaultLogger::isNullLogger()) {
+ ASSIMP_LOG_ERROR(ex.what());
+ }
+ return NULL;
+ }
+
+ if (!object.get()) {
+ //DOMError("failed to convert element to DOM object, class: " + classtag + ", name: " + name,&element);
+ }
+
+ flags &= ~BEING_CONSTRUCTED;
+ return object.get();
+}
+
+// ------------------------------------------------------------------------------------------------
+Object::Object(uint64_t id, const Element& element, const std::string& name)
+: element(element)
+, name(name)
+, id(id)
+{
+ // empty
+}
+
+// ------------------------------------------------------------------------------------------------
+Object::~Object()
+{
+ // empty
+}
+
+// ------------------------------------------------------------------------------------------------
+FileGlobalSettings::FileGlobalSettings(const Document& doc, std::shared_ptr<const PropertyTable> props)
+: props(props)
+, doc(doc)
+{
+ // empty
+}
+
+// ------------------------------------------------------------------------------------------------
+FileGlobalSettings::~FileGlobalSettings()
+{
+ // empty
+}
+
+// ------------------------------------------------------------------------------------------------
+Document::Document(const Parser& parser, const ImportSettings& settings)
+: settings(settings)
+, parser(parser)
+{
+ // Cannot use array default initialization syntax because vc8 fails on it
+ for (auto &timeStamp : creationTimeStamp) {
+ timeStamp = 0;
+ }
+
+ ReadHeader();
+ ReadPropertyTemplates();
+
+ ReadGlobalSettings();
+
+ // This order is important, connections need parsed objects to check
+ // whether connections are ok or not. Objects may not be evaluated yet,
+ // though, since this may require valid connections.
+ ReadObjects();
+ ReadConnections();
+}
+
+// ------------------------------------------------------------------------------------------------
+Document::~Document()
+{
+ for(ObjectMap::value_type& v : objects) {
+ delete v.second;
+ }
+
+ for(ConnectionMap::value_type& v : src_connections) {
+ delete v.second;
+ }
+ // |dest_connections| contain the same Connection objects as the |src_connections|
+}
+
+// ------------------------------------------------------------------------------------------------
+static const unsigned int LowerSupportedVersion = 7100;
+static const unsigned int UpperSupportedVersion = 7400;
+
+void Document::ReadHeader() {
+ // Read ID objects from "Objects" section
+ const Scope& sc = parser.GetRootScope();
+ const Element* const ehead = sc["FBXHeaderExtension"];
+ if(!ehead || !ehead->Compound()) {
+ DOMError("no FBXHeaderExtension dictionary found");
+ }
+
+ const Scope& shead = *ehead->Compound();
+ fbxVersion = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(shead,"FBXVersion",ehead),0));
+
+ // While we may have some success with newer files, we don't support
+ // the older 6.n fbx format
+ if(fbxVersion < LowerSupportedVersion ) {
+ DOMError("unsupported, old format version, supported are only FBX 2011, FBX 2012 and FBX 2013");
+ }
+ if(fbxVersion > UpperSupportedVersion ) {
+ if(Settings().strictMode) {
+ DOMError("unsupported, newer format version, supported are only FBX 2011, FBX 2012 and FBX 2013"
+ " (turn off strict mode to try anyhow) ");
+ }
+ else {
+ DOMWarning("unsupported, newer format version, supported are only FBX 2011, FBX 2012 and FBX 2013,"
+ " trying to read it nevertheless");
+ }
+ }
+
+ const Element* const ecreator = shead["Creator"];
+ if(ecreator) {
+ creator = ParseTokenAsString(GetRequiredToken(*ecreator,0));
+ }
+
+ const Element* const etimestamp = shead["CreationTimeStamp"];
+ if(etimestamp && etimestamp->Compound()) {
+ const Scope& stimestamp = *etimestamp->Compound();
+ creationTimeStamp[0] = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(stimestamp,"Year"),0));
+ creationTimeStamp[1] = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(stimestamp,"Month"),0));
+ creationTimeStamp[2] = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(stimestamp,"Day"),0));
+ creationTimeStamp[3] = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(stimestamp,"Hour"),0));
+ creationTimeStamp[4] = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(stimestamp,"Minute"),0));
+ creationTimeStamp[5] = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(stimestamp,"Second"),0));
+ creationTimeStamp[6] = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(stimestamp,"Millisecond"),0));
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+void Document::ReadGlobalSettings()
+{
+ const Scope& sc = parser.GetRootScope();
+ const Element* const ehead = sc["GlobalSettings"];
+ if ( nullptr == ehead || !ehead->Compound() ) {
+ DOMWarning( "no GlobalSettings dictionary found" );
+ globals.reset(new FileGlobalSettings(*this, std::make_shared<const PropertyTable>()));
+ return;
+ }
+
+ std::shared_ptr<const PropertyTable> props = GetPropertyTable( *this, "", *ehead, *ehead->Compound(), true );
+
+ //double v = PropertyGet<float>( *props.get(), std::string("UnitScaleFactor"), 1.0 );
+
+ if(!props) {
+ DOMError("GlobalSettings dictionary contains no property table");
+ }
+
+ globals.reset(new FileGlobalSettings(*this, props));
+}
+
+// ------------------------------------------------------------------------------------------------
+void Document::ReadObjects()
+{
+ // read ID objects from "Objects" section
+ const Scope& sc = parser.GetRootScope();
+ const Element* const eobjects = sc["Objects"];
+ if(!eobjects || !eobjects->Compound()) {
+ DOMError("no Objects dictionary found");
+ }
+
+ // add a dummy entry to represent the Model::RootNode object (id 0),
+ // which is only indirectly defined in the input file
+ objects[0] = new LazyObject(0L, *eobjects, *this);
+
+ const Scope& sobjects = *eobjects->Compound();
+ for(const ElementMap::value_type& el : sobjects.Elements()) {
+
+ // extract ID
+ const TokenList& tok = el.second->Tokens();
+
+ if (tok.empty()) {
+ DOMError("expected ID after object key",el.second);
+ }
+
+ const char* err;
+ const uint64_t id = ParseTokenAsID(*tok[0], err);
+ if(err) {
+ DOMError(err,el.second);
+ }
+
+ // id=0 is normally implicit
+ if(id == 0L) {
+ DOMError("encountered object with implicitly defined id 0",el.second);
+ }
+
+ if(objects.find(id) != objects.end()) {
+ DOMWarning("encountered duplicate object id, ignoring first occurrence",el.second);
+ }
+
+ objects[id] = new LazyObject(id, *el.second, *this);
+
+ // grab all animation stacks upfront since there is no listing of them
+ if(!strcmp(el.first.c_str(),"AnimationStack")) {
+ animationStacks.push_back(id);
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+void Document::ReadPropertyTemplates()
+{
+ const Scope& sc = parser.GetRootScope();
+ // read property templates from "Definitions" section
+ const Element* const edefs = sc["Definitions"];
+ if(!edefs || !edefs->Compound()) {
+ DOMWarning("no Definitions dictionary found");
+ return;
+ }
+
+ const Scope& sdefs = *edefs->Compound();
+ const ElementCollection otypes = sdefs.GetCollection("ObjectType");
+ for(ElementMap::const_iterator it = otypes.first; it != otypes.second; ++it) {
+ const Element& el = *(*it).second;
+ const Scope* sc = el.Compound();
+ if(!sc) {
+ DOMWarning("expected nested scope in ObjectType, ignoring",&el);
+ continue;
+ }
+
+ const TokenList& tok = el.Tokens();
+ if(tok.empty()) {
+ DOMWarning("expected name for ObjectType element, ignoring",&el);
+ continue;
+ }
+
+ const std::string& oname = ParseTokenAsString(*tok[0]);
+
+ const ElementCollection templs = sc->GetCollection("PropertyTemplate");
+ for(ElementMap::const_iterator it = templs.first; it != templs.second; ++it) {
+ const Element& el = *(*it).second;
+ const Scope* sc = el.Compound();
+ if(!sc) {
+ DOMWarning("expected nested scope in PropertyTemplate, ignoring",&el);
+ continue;
+ }
+
+ const TokenList& tok = el.Tokens();
+ if(tok.empty()) {
+ DOMWarning("expected name for PropertyTemplate element, ignoring",&el);
+ continue;
+ }
+
+ const std::string& pname = ParseTokenAsString(*tok[0]);
+
+ const Element* Properties70 = (*sc)["Properties70"];
+ if(Properties70) {
+ std::shared_ptr<const PropertyTable> props = std::make_shared<const PropertyTable>(
+ *Properties70,std::shared_ptr<const PropertyTable>(static_cast<const PropertyTable*>(NULL))
+ );
+
+ templates[oname+"."+pname] = props;
+ }
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+void Document::ReadConnections()
+{
+ const Scope& sc = parser.GetRootScope();
+ // read property templates from "Definitions" section
+ const Element* const econns = sc["Connections"];
+ if(!econns || !econns->Compound()) {
+ DOMError("no Connections dictionary found");
+ }
+
+ uint64_t insertionOrder = 0l;
+ const Scope& sconns = *econns->Compound();
+ const ElementCollection conns = sconns.GetCollection("C");
+ for(ElementMap::const_iterator it = conns.first; it != conns.second; ++it) {
+ const Element& el = *(*it).second;
+ const std::string& type = ParseTokenAsString(GetRequiredToken(el,0));
+
+ // PP = property-property connection, ignored for now
+ // (tokens: "PP", ID1, "Property1", ID2, "Property2")
+ if ( type == "PP" ) {
+ continue;
+ }
+
+ const uint64_t src = ParseTokenAsID(GetRequiredToken(el,1));
+ const uint64_t dest = ParseTokenAsID(GetRequiredToken(el,2));
+
+ // OO = object-object connection
+ // OP = object-property connection, in which case the destination property follows the object ID
+ const std::string& prop = (type == "OP" ? ParseTokenAsString(GetRequiredToken(el,3)) : "");
+
+ if(objects.find(src) == objects.end()) {
+ DOMWarning("source object for connection does not exist",&el);
+ continue;
+ }
+
+ // dest may be 0 (root node) but we added a dummy object before
+ if(objects.find(dest) == objects.end()) {
+ DOMWarning("destination object for connection does not exist",&el);
+ continue;
+ }
+
+ // add new connection
+ const Connection* const c = new Connection(insertionOrder++,src,dest,prop,*this);
+ src_connections.insert(ConnectionMap::value_type(src,c));
+ dest_connections.insert(ConnectionMap::value_type(dest,c));
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+const std::vector<const AnimationStack*>& Document::AnimationStacks() const
+{
+ if (!animationStacksResolved.empty() || animationStacks.empty()) {
+ return animationStacksResolved;
+ }
+
+ animationStacksResolved.reserve(animationStacks.size());
+ for(uint64_t id : animationStacks) {
+ LazyObject* const lazy = GetObject(id);
+ const AnimationStack* stack;
+ if(!lazy || !(stack = lazy->Get<AnimationStack>())) {
+ DOMWarning("failed to read AnimationStack object");
+ continue;
+ }
+ animationStacksResolved.push_back(stack);
+ }
+
+ return animationStacksResolved;
+}
+
+// ------------------------------------------------------------------------------------------------
+LazyObject* Document::GetObject(uint64_t id) const
+{
+ ObjectMap::const_iterator it = objects.find(id);
+ return it == objects.end() ? nullptr : (*it).second;
+}
+
+#define MAX_CLASSNAMES 6
+
+// ------------------------------------------------------------------------------------------------
+std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, const ConnectionMap& conns) const
+{
+ std::vector<const Connection*> temp;
+
+ const std::pair<ConnectionMap::const_iterator,ConnectionMap::const_iterator> range =
+ conns.equal_range(id);
+
+ temp.reserve(std::distance(range.first,range.second));
+ for (ConnectionMap::const_iterator it = range.first; it != range.second; ++it) {
+ temp.push_back((*it).second);
+ }
+
+ std::sort(temp.begin(), temp.end(), std::mem_fn(&Connection::Compare));
+
+ return temp; // NRVO should handle this
+}
+
+// ------------------------------------------------------------------------------------------------
+std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, bool is_src,
+ const ConnectionMap& conns,
+ const char* const* classnames,
+ size_t count) const
+
+{
+ ai_assert(classnames);
+ ai_assert( count != 0 );
+ ai_assert( count <= MAX_CLASSNAMES);
+
+ size_t lengths[MAX_CLASSNAMES];
+
+ const size_t c = count;
+ for (size_t i = 0; i < c; ++i) {
+ lengths[ i ] = strlen(classnames[i]);
+ }
+
+ std::vector<const Connection*> temp;
+ const std::pair<ConnectionMap::const_iterator,ConnectionMap::const_iterator> range =
+ conns.equal_range(id);
+
+ temp.reserve(std::distance(range.first,range.second));
+ for (ConnectionMap::const_iterator it = range.first; it != range.second; ++it) {
+ const Token& key = (is_src
+ ? (*it).second->LazyDestinationObject()
+ : (*it).second->LazySourceObject()
+ ).GetElement().KeyToken();
+
+ const char* obtype = key.begin();
+
+ for (size_t i = 0; i < c; ++i) {
+ ai_assert(classnames[i]);
+ if(static_cast<size_t>(std::distance(key.begin(),key.end())) == lengths[i] && !strncmp(classnames[i],obtype,lengths[i])) {
+ obtype = nullptr;
+ break;
+ }
+ }
+
+ if(obtype) {
+ continue;
+ }
+
+ temp.push_back((*it).second);
+ }
+
+ std::sort(temp.begin(), temp.end(), std::mem_fn(&Connection::Compare));
+ return temp; // NRVO should handle this
+}
+
+// ------------------------------------------------------------------------------------------------
+std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t source) const
+{
+ return GetConnectionsSequenced(source, ConnectionsBySource());
+}
+
+// ------------------------------------------------------------------------------------------------
+std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t src, const char* classname) const
+{
+ const char* arr[] = {classname};
+ return GetConnectionsBySourceSequenced(src, arr,1);
+}
+
+// ------------------------------------------------------------------------------------------------
+std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t source,
+ const char* const* classnames, size_t count) const
+{
+ return GetConnectionsSequenced(source, true, ConnectionsBySource(),classnames, count);
+}
+
+// ------------------------------------------------------------------------------------------------
+std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest,
+ const char* classname) const
+{
+ const char* arr[] = {classname};
+ return GetConnectionsByDestinationSequenced(dest, arr,1);
+}
+
+// ------------------------------------------------------------------------------------------------
+std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest) const
+{
+ return GetConnectionsSequenced(dest, ConnectionsByDestination());
+}
+
+// ------------------------------------------------------------------------------------------------
+std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest,
+ const char* const* classnames, size_t count) const
+
+{
+ return GetConnectionsSequenced(dest, false, ConnectionsByDestination(),classnames, count);
+}
+
+// ------------------------------------------------------------------------------------------------
+Connection::Connection(uint64_t insertionOrder, uint64_t src, uint64_t dest, const std::string& prop,
+ const Document& doc)
+
+: insertionOrder(insertionOrder)
+, prop(prop)
+, src(src)
+, dest(dest)
+, doc(doc)
+{
+ ai_assert(doc.Objects().find(src) != doc.Objects().end());
+ // dest may be 0 (root node)
+ ai_assert(!dest || doc.Objects().find(dest) != doc.Objects().end());
+}
+
+// ------------------------------------------------------------------------------------------------
+Connection::~Connection()
+{
+ // empty
+}
+
+// ------------------------------------------------------------------------------------------------
+LazyObject& Connection::LazySourceObject() const
+{
+ LazyObject* const lazy = doc.GetObject(src);
+ ai_assert(lazy);
+ return *lazy;
+}
+
+// ------------------------------------------------------------------------------------------------
+LazyObject& Connection::LazyDestinationObject() const
+{
+ LazyObject* const lazy = doc.GetObject(dest);
+ ai_assert(lazy);
+ return *lazy;
+}
+
+// ------------------------------------------------------------------------------------------------
+const Object* Connection::SourceObject() const
+{
+ LazyObject* const lazy = doc.GetObject(src);
+ ai_assert(lazy);
+ return lazy->Get();
+}
+
+// ------------------------------------------------------------------------------------------------
+const Object* Connection::DestinationObject() const
+{
+ LazyObject* const lazy = doc.GetObject(dest);
+ ai_assert(lazy);
+ return lazy->Get();
+}
+
+} // !FBX
+} // !Assimp
+
+#endif
diff --git a/thirdparty/assimp/code/FBXDocument.h b/thirdparty/assimp/code/FBXDocument.h
new file mode 100644
index 0000000000..c849defdcd
--- /dev/null
+++ b/thirdparty/assimp/code/FBXDocument.h
@@ -0,0 +1,1180 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file FBXDocument.h
+ * @brief FBX DOM
+ */
+#ifndef INCLUDED_AI_FBX_DOCUMENT_H
+#define INCLUDED_AI_FBX_DOCUMENT_H
+
+#include <numeric>
+#include <stdint.h>
+#include <assimp/mesh.h>
+#include "FBXProperties.h"
+#include "FBXParser.h"
+
+#define _AI_CONCAT(a,b) a ## b
+#define AI_CONCAT(a,b) _AI_CONCAT(a,b)
+
+namespace Assimp {
+namespace FBX {
+
+class Parser;
+class Object;
+struct ImportSettings;
+
+class PropertyTable;
+class Document;
+class Material;
+class ShapeGeometry;
+class LineGeometry;
+class Geometry;
+
+class Video;
+
+class AnimationCurve;
+class AnimationCurveNode;
+class AnimationLayer;
+class AnimationStack;
+
+class BlendShapeChannel;
+class BlendShape;
+class Skin;
+class Cluster;
+
+
+/** Represents a delay-parsed FBX objects. Many objects in the scene
+ * are not needed by assimp, so it makes no sense to parse them
+ * upfront. */
+class LazyObject {
+public:
+ LazyObject(uint64_t id, const Element& element, const Document& doc);
+
+ ~LazyObject();
+
+ const Object* Get(bool dieOnError = false);
+
+ template <typename T>
+ const T* Get(bool dieOnError = false) {
+ const Object* const ob = Get(dieOnError);
+ return ob ? dynamic_cast<const T*>(ob) : NULL;
+ }
+
+ uint64_t ID() const {
+ return id;
+ }
+
+ bool IsBeingConstructed() const {
+ return (flags & BEING_CONSTRUCTED) != 0;
+ }
+
+ bool FailedToConstruct() const {
+ return (flags & FAILED_TO_CONSTRUCT) != 0;
+ }
+
+ const Element& GetElement() const {
+ return element;
+ }
+
+ const Document& GetDocument() const {
+ return doc;
+ }
+
+private:
+ const Document& doc;
+ const Element& element;
+ std::unique_ptr<const Object> object;
+
+ const uint64_t id;
+
+ enum Flags {
+ BEING_CONSTRUCTED = 0x1,
+ FAILED_TO_CONSTRUCT = 0x2
+ };
+
+ unsigned int flags;
+};
+
+/** Base class for in-memory (DOM) representations of FBX objects */
+class Object {
+public:
+ Object(uint64_t id, const Element& element, const std::string& name);
+
+ virtual ~Object();
+
+ const Element& SourceElement() const {
+ return element;
+ }
+
+ const std::string& Name() const {
+ return name;
+ }
+
+ uint64_t ID() const {
+ return id;
+ }
+
+protected:
+ const Element& element;
+ const std::string name;
+ const uint64_t id;
+};
+
+/** DOM class for generic FBX NoteAttribute blocks. NoteAttribute's just hold a property table,
+ * fixed members are added by deriving classes. */
+class NodeAttribute : public Object {
+public:
+ NodeAttribute(uint64_t id, const Element& element, const Document& doc, const std::string& name);
+
+ virtual ~NodeAttribute();
+
+ const PropertyTable& Props() const {
+ ai_assert(props.get());
+ return *props.get();
+ }
+
+private:
+ std::shared_ptr<const PropertyTable> props;
+};
+
+/** DOM base class for FBX camera settings attached to a node */
+class CameraSwitcher : public NodeAttribute {
+public:
+ CameraSwitcher(uint64_t id, const Element& element, const Document& doc, const std::string& name);
+
+ virtual ~CameraSwitcher();
+
+ int CameraID() const {
+ return cameraId;
+ }
+
+ const std::string& CameraName() const {
+ return cameraName;
+ }
+
+ const std::string& CameraIndexName() const {
+ return cameraIndexName;
+ }
+
+private:
+ int cameraId;
+ std::string cameraName;
+ std::string cameraIndexName;
+};
+
+#define fbx_stringize(a) #a
+
+#define fbx_simple_property(name, type, default_value) \
+ type name() const { \
+ return PropertyGet<type>(Props(), fbx_stringize(name), (default_value)); \
+ }
+
+// XXX improve logging
+#define fbx_simple_enum_property(name, type, default_value) \
+ type name() const { \
+ const int ival = PropertyGet<int>(Props(), fbx_stringize(name), static_cast<int>(default_value)); \
+ if (ival < 0 || ival >= AI_CONCAT(type, _MAX)) { \
+ ai_assert(static_cast<int>(default_value) >= 0 && static_cast<int>(default_value) < AI_CONCAT(type, _MAX)); \
+ return static_cast<type>(default_value); \
+ } \
+ return static_cast<type>(ival); \
+}
+
+
+/** DOM base class for FBX cameras attached to a node */
+class Camera : public NodeAttribute {
+public:
+ Camera(uint64_t id, const Element& element, const Document& doc, const std::string& name);
+
+ virtual ~Camera();
+
+ fbx_simple_property(Position, aiVector3D, aiVector3D(0,0,0))
+ fbx_simple_property(UpVector, aiVector3D, aiVector3D(0,1,0))
+ fbx_simple_property(InterestPosition, aiVector3D, aiVector3D(0,0,0))
+
+ fbx_simple_property(AspectWidth, float, 1.0f)
+ fbx_simple_property(AspectHeight, float, 1.0f)
+ fbx_simple_property(FilmWidth, float, 1.0f)
+ fbx_simple_property(FilmHeight, float, 1.0f)
+
+ fbx_simple_property(NearPlane, float, 0.1f)
+ fbx_simple_property(FarPlane, float, 100.0f)
+
+ fbx_simple_property(FilmAspectRatio, float, 1.0f)
+ fbx_simple_property(ApertureMode, int, 0)
+
+ fbx_simple_property(FieldOfView, float, 1.0f)
+ fbx_simple_property(FocalLength, float, 1.0f)
+};
+
+/** DOM base class for FBX null markers attached to a node */
+class Null : public NodeAttribute {
+public:
+ Null(uint64_t id, const Element& element, const Document& doc, const std::string& name);
+ virtual ~Null();
+};
+
+/** DOM base class for FBX limb node markers attached to a node */
+class LimbNode : public NodeAttribute {
+public:
+ LimbNode(uint64_t id, const Element& element, const Document& doc, const std::string& name);
+ virtual ~LimbNode();
+};
+
+/** DOM base class for FBX lights attached to a node */
+class Light : public NodeAttribute {
+public:
+ Light(uint64_t id, const Element& element, const Document& doc, const std::string& name);
+ virtual ~Light();
+
+ enum Type
+ {
+ Type_Point,
+ Type_Directional,
+ Type_Spot,
+ Type_Area,
+ Type_Volume,
+
+ Type_MAX // end-of-enum sentinel
+ };
+
+ enum Decay
+ {
+ Decay_None,
+ Decay_Linear,
+ Decay_Quadratic,
+ Decay_Cubic,
+
+ Decay_MAX // end-of-enum sentinel
+ };
+
+ fbx_simple_property(Color, aiVector3D, aiVector3D(1,1,1))
+ fbx_simple_enum_property(LightType, Type, 0)
+ fbx_simple_property(CastLightOnObject, bool, false)
+ fbx_simple_property(DrawVolumetricLight, bool, true)
+ fbx_simple_property(DrawGroundProjection, bool, true)
+ fbx_simple_property(DrawFrontFacingVolumetricLight, bool, false)
+ fbx_simple_property(Intensity, float, 100.0f)
+ fbx_simple_property(InnerAngle, float, 0.0f)
+ fbx_simple_property(OuterAngle, float, 45.0f)
+ fbx_simple_property(Fog, int, 50)
+ fbx_simple_enum_property(DecayType, Decay, 2)
+ fbx_simple_property(DecayStart, float, 1.0f)
+ fbx_simple_property(FileName, std::string, "")
+
+ fbx_simple_property(EnableNearAttenuation, bool, false)
+ fbx_simple_property(NearAttenuationStart, float, 0.0f)
+ fbx_simple_property(NearAttenuationEnd, float, 0.0f)
+ fbx_simple_property(EnableFarAttenuation, bool, false)
+ fbx_simple_property(FarAttenuationStart, float, 0.0f)
+ fbx_simple_property(FarAttenuationEnd, float, 0.0f)
+
+ fbx_simple_property(CastShadows, bool, true)
+ fbx_simple_property(ShadowColor, aiVector3D, aiVector3D(0,0,0))
+
+ fbx_simple_property(AreaLightShape, int, 0)
+
+ fbx_simple_property(LeftBarnDoor, float, 20.0f)
+ fbx_simple_property(RightBarnDoor, float, 20.0f)
+ fbx_simple_property(TopBarnDoor, float, 20.0f)
+ fbx_simple_property(BottomBarnDoor, float, 20.0f)
+ fbx_simple_property(EnableBarnDoor, bool, true)
+};
+
+/** DOM base class for FBX models (even though its semantics are more "node" than "model" */
+class Model : public Object {
+public:
+ enum RotOrder {
+ RotOrder_EulerXYZ = 0,
+ RotOrder_EulerXZY,
+ RotOrder_EulerYZX,
+ RotOrder_EulerYXZ,
+ RotOrder_EulerZXY,
+ RotOrder_EulerZYX,
+
+ RotOrder_SphericXYZ,
+
+ RotOrder_MAX // end-of-enum sentinel
+ };
+
+ enum TransformInheritance {
+ TransformInheritance_RrSs = 0,
+ TransformInheritance_RSrs,
+ TransformInheritance_Rrs,
+
+ TransformInheritance_MAX // end-of-enum sentinel
+ };
+
+ Model(uint64_t id, const Element& element, const Document& doc, const std::string& name);
+
+ virtual ~Model();
+
+ fbx_simple_property(QuaternionInterpolate, int, 0)
+
+ fbx_simple_property(RotationOffset, aiVector3D, aiVector3D())
+ fbx_simple_property(RotationPivot, aiVector3D, aiVector3D())
+ fbx_simple_property(ScalingOffset, aiVector3D, aiVector3D())
+ fbx_simple_property(ScalingPivot, aiVector3D, aiVector3D())
+ fbx_simple_property(TranslationActive, bool, false)
+
+ fbx_simple_property(TranslationMin, aiVector3D, aiVector3D())
+ fbx_simple_property(TranslationMax, aiVector3D, aiVector3D())
+
+ fbx_simple_property(TranslationMinX, bool, false)
+ fbx_simple_property(TranslationMaxX, bool, false)
+ fbx_simple_property(TranslationMinY, bool, false)
+ fbx_simple_property(TranslationMaxY, bool, false)
+ fbx_simple_property(TranslationMinZ, bool, false)
+ fbx_simple_property(TranslationMaxZ, bool, false)
+
+ fbx_simple_enum_property(RotationOrder, RotOrder, 0)
+ fbx_simple_property(RotationSpaceForLimitOnly, bool, false)
+ fbx_simple_property(RotationStiffnessX, float, 0.0f)
+ fbx_simple_property(RotationStiffnessY, float, 0.0f)
+ fbx_simple_property(RotationStiffnessZ, float, 0.0f)
+ fbx_simple_property(AxisLen, float, 0.0f)
+
+ fbx_simple_property(PreRotation, aiVector3D, aiVector3D())
+ fbx_simple_property(PostRotation, aiVector3D, aiVector3D())
+ fbx_simple_property(RotationActive, bool, false)
+
+ fbx_simple_property(RotationMin, aiVector3D, aiVector3D())
+ fbx_simple_property(RotationMax, aiVector3D, aiVector3D())
+
+ fbx_simple_property(RotationMinX, bool, false)
+ fbx_simple_property(RotationMaxX, bool, false)
+ fbx_simple_property(RotationMinY, bool, false)
+ fbx_simple_property(RotationMaxY, bool, false)
+ fbx_simple_property(RotationMinZ, bool, false)
+ fbx_simple_property(RotationMaxZ, bool, false)
+ fbx_simple_enum_property(InheritType, TransformInheritance, 0)
+
+ fbx_simple_property(ScalingActive, bool, false)
+ fbx_simple_property(ScalingMin, aiVector3D, aiVector3D())
+ fbx_simple_property(ScalingMax, aiVector3D, aiVector3D(1.f,1.f,1.f))
+ fbx_simple_property(ScalingMinX, bool, false)
+ fbx_simple_property(ScalingMaxX, bool, false)
+ fbx_simple_property(ScalingMinY, bool, false)
+ fbx_simple_property(ScalingMaxY, bool, false)
+ fbx_simple_property(ScalingMinZ, bool, false)
+ fbx_simple_property(ScalingMaxZ, bool, false)
+
+ fbx_simple_property(GeometricTranslation, aiVector3D, aiVector3D())
+ fbx_simple_property(GeometricRotation, aiVector3D, aiVector3D())
+ fbx_simple_property(GeometricScaling, aiVector3D, aiVector3D(1.f, 1.f, 1.f))
+
+ fbx_simple_property(MinDampRangeX, float, 0.0f)
+ fbx_simple_property(MinDampRangeY, float, 0.0f)
+ fbx_simple_property(MinDampRangeZ, float, 0.0f)
+ fbx_simple_property(MaxDampRangeX, float, 0.0f)
+ fbx_simple_property(MaxDampRangeY, float, 0.0f)
+ fbx_simple_property(MaxDampRangeZ, float, 0.0f)
+
+ fbx_simple_property(MinDampStrengthX, float, 0.0f)
+ fbx_simple_property(MinDampStrengthY, float, 0.0f)
+ fbx_simple_property(MinDampStrengthZ, float, 0.0f)
+ fbx_simple_property(MaxDampStrengthX, float, 0.0f)
+ fbx_simple_property(MaxDampStrengthY, float, 0.0f)
+ fbx_simple_property(MaxDampStrengthZ, float, 0.0f)
+
+ fbx_simple_property(PreferredAngleX, float, 0.0f)
+ fbx_simple_property(PreferredAngleY, float, 0.0f)
+ fbx_simple_property(PreferredAngleZ, float, 0.0f)
+
+ fbx_simple_property(Show, bool, true)
+ fbx_simple_property(LODBox, bool, false)
+ fbx_simple_property(Freeze, bool, false)
+
+ const std::string& Shading() const {
+ return shading;
+ }
+
+ const std::string& Culling() const {
+ return culling;
+ }
+
+ const PropertyTable& Props() const {
+ ai_assert(props.get());
+ return *props.get();
+ }
+
+ /** Get material links */
+ const std::vector<const Material*>& GetMaterials() const {
+ return materials;
+ }
+
+ /** Get geometry links */
+ const std::vector<const Geometry*>& GetGeometry() const {
+ return geometry;
+ }
+
+ /** Get node attachments */
+ const std::vector<const NodeAttribute*>& GetAttributes() const {
+ return attributes;
+ }
+
+ /** convenience method to check if the node has a Null node marker */
+ bool IsNull() const;
+
+private:
+ void ResolveLinks(const Element& element, const Document& doc);
+
+private:
+ std::vector<const Material*> materials;
+ std::vector<const Geometry*> geometry;
+ std::vector<const NodeAttribute*> attributes;
+
+ std::string shading;
+ std::string culling;
+ std::shared_ptr<const PropertyTable> props;
+};
+
+/** DOM class for generic FBX textures */
+class Texture : public Object {
+public:
+ Texture(uint64_t id, const Element& element, const Document& doc, const std::string& name);
+
+ virtual ~Texture();
+
+ const std::string& Type() const {
+ return type;
+ }
+
+ const std::string& FileName() const {
+ return fileName;
+ }
+
+ const std::string& RelativeFilename() const {
+ return relativeFileName;
+ }
+
+ const std::string& AlphaSource() const {
+ return alphaSource;
+ }
+
+ const aiVector2D& UVTranslation() const {
+ return uvTrans;
+ }
+
+ const aiVector2D& UVScaling() const {
+ return uvScaling;
+ }
+
+ const PropertyTable& Props() const {
+ ai_assert(props.get());
+ return *props.get();
+ }
+
+ // return a 4-tuple
+ const unsigned int* Crop() const {
+ return crop;
+ }
+
+ const Video* Media() const {
+ return media;
+ }
+
+private:
+ aiVector2D uvTrans;
+ aiVector2D uvScaling;
+
+ std::string type;
+ std::string relativeFileName;
+ std::string fileName;
+ std::string alphaSource;
+ std::shared_ptr<const PropertyTable> props;
+
+ unsigned int crop[4];
+
+ const Video* media;
+};
+
+/** DOM class for layered FBX textures */
+class LayeredTexture : public Object {
+public:
+ LayeredTexture(uint64_t id, const Element& element, const Document& doc, const std::string& name);
+ virtual ~LayeredTexture();
+
+ // Can only be called after construction of the layered texture object due to construction flag.
+ void fillTexture(const Document& doc);
+
+ enum BlendMode {
+ BlendMode_Translucent,
+ BlendMode_Additive,
+ BlendMode_Modulate,
+ BlendMode_Modulate2,
+ BlendMode_Over,
+ BlendMode_Normal,
+ BlendMode_Dissolve,
+ BlendMode_Darken,
+ BlendMode_ColorBurn,
+ BlendMode_LinearBurn,
+ BlendMode_DarkerColor,
+ BlendMode_Lighten,
+ BlendMode_Screen,
+ BlendMode_ColorDodge,
+ BlendMode_LinearDodge,
+ BlendMode_LighterColor,
+ BlendMode_SoftLight,
+ BlendMode_HardLight,
+ BlendMode_VividLight,
+ BlendMode_LinearLight,
+ BlendMode_PinLight,
+ BlendMode_HardMix,
+ BlendMode_Difference,
+ BlendMode_Exclusion,
+ BlendMode_Subtract,
+ BlendMode_Divide,
+ BlendMode_Hue,
+ BlendMode_Saturation,
+ BlendMode_Color,
+ BlendMode_Luminosity,
+ BlendMode_Overlay,
+ BlendMode_BlendModeCount
+ };
+
+ const Texture* getTexture(int index=0) const
+ {
+ return textures[index];
+
+ }
+ int textureCount() const {
+ return static_cast<int>(textures.size());
+ }
+ BlendMode GetBlendMode() const
+ {
+ return blendMode;
+ }
+ float Alpha()
+ {
+ return alpha;
+ }
+private:
+ std::vector<const Texture*> textures;
+ BlendMode blendMode;
+ float alpha;
+};
+
+typedef std::fbx_unordered_map<std::string, const Texture*> TextureMap;
+typedef std::fbx_unordered_map<std::string, const LayeredTexture*> LayeredTextureMap;
+
+
+/** DOM class for generic FBX videos */
+class Video : public Object {
+public:
+ Video(uint64_t id, const Element& element, const Document& doc, const std::string& name);
+
+ virtual ~Video();
+
+ const std::string& Type() const {
+ return type;
+ }
+
+ const std::string& FileName() const {
+ return fileName;
+ }
+
+ const std::string& RelativeFilename() const {
+ return relativeFileName;
+ }
+
+ const PropertyTable& Props() const {
+ ai_assert(props.get());
+ return *props.get();
+ }
+
+ const uint8_t* Content() const {
+ ai_assert(content);
+ return content;
+ }
+
+ uint32_t ContentLength() const {
+ return contentLength;
+ }
+
+ uint8_t* RelinquishContent() {
+ uint8_t* ptr = content;
+ content = 0;
+ return ptr;
+ }
+
+private:
+ std::string type;
+ std::string relativeFileName;
+ std::string fileName;
+ std::shared_ptr<const PropertyTable> props;
+
+ uint32_t contentLength;
+ uint8_t* content;
+};
+
+/** DOM class for generic FBX materials */
+class Material : public Object {
+public:
+ Material(uint64_t id, const Element& element, const Document& doc, const std::string& name);
+
+ virtual ~Material();
+
+ const std::string& GetShadingModel() const {
+ return shading;
+ }
+
+ bool IsMultilayer() const {
+ return multilayer;
+ }
+
+ const PropertyTable& Props() const {
+ ai_assert(props.get());
+ return *props.get();
+ }
+
+ const TextureMap& Textures() const {
+ return textures;
+ }
+
+ const LayeredTextureMap& LayeredTextures() const {
+ return layeredTextures;
+ }
+
+private:
+ std::string shading;
+ bool multilayer;
+ std::shared_ptr<const PropertyTable> props;
+
+ TextureMap textures;
+ LayeredTextureMap layeredTextures;
+};
+
+typedef std::vector<int64_t> KeyTimeList;
+typedef std::vector<float> KeyValueList;
+
+/** Represents a FBX animation curve (i.e. a 1-dimensional set of keyframes and values therefor) */
+class AnimationCurve : public Object {
+public:
+ AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& doc);
+ virtual ~AnimationCurve();
+
+ /** get list of keyframe positions (time).
+ * Invariant: |GetKeys()| > 0 */
+ const KeyTimeList& GetKeys() const {
+ return keys;
+ }
+
+ /** get list of keyframe values.
+ * Invariant: |GetKeys()| == |GetValues()| && |GetKeys()| > 0*/
+ const KeyValueList& GetValues() const {
+ return values;
+ }
+
+ const std::vector<float>& GetAttributes() const {
+ return attributes;
+ }
+
+ const std::vector<unsigned int>& GetFlags() const {
+ return flags;
+ }
+
+private:
+ KeyTimeList keys;
+ KeyValueList values;
+ std::vector<float> attributes;
+ std::vector<unsigned int> flags;
+};
+
+// property-name -> animation curve
+typedef std::map<std::string, const AnimationCurve*> AnimationCurveMap;
+
+/** Represents a FBX animation curve (i.e. a mapping from single animation curves to nodes) */
+class AnimationCurveNode : public Object {
+public:
+ /* the optional white list specifies a list of property names for which the caller
+ wants animations for. If the curve node does not match one of these, std::range_error
+ will be thrown. */
+ AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, const Document& doc,
+ const char* const * target_prop_whitelist = NULL, size_t whitelist_size = 0);
+
+ virtual ~AnimationCurveNode();
+
+ const PropertyTable& Props() const {
+ ai_assert(props.get());
+ return *props.get();
+ }
+
+
+ const AnimationCurveMap& Curves() const;
+
+ /** Object the curve is assigned to, this can be NULL if the
+ * target object has no DOM representation or could not
+ * be read for other reasons.*/
+ const Object* Target() const {
+ return target;
+ }
+
+ const Model* TargetAsModel() const {
+ return dynamic_cast<const Model*>(target);
+ }
+
+ const NodeAttribute* TargetAsNodeAttribute() const {
+ return dynamic_cast<const NodeAttribute*>(target);
+ }
+
+ /** Property of Target() that is being animated*/
+ const std::string& TargetProperty() const {
+ return prop;
+ }
+
+private:
+ const Object* target;
+ std::shared_ptr<const PropertyTable> props;
+ mutable AnimationCurveMap curves;
+
+ std::string prop;
+ const Document& doc;
+};
+
+typedef std::vector<const AnimationCurveNode*> AnimationCurveNodeList;
+
+/** Represents a FBX animation layer (i.e. a list of node animations) */
+class AnimationLayer : public Object {
+public:
+ AnimationLayer(uint64_t id, const Element& element, const std::string& name, const Document& doc);
+ virtual ~AnimationLayer();
+
+ const PropertyTable& Props() const {
+ ai_assert(props.get());
+ return *props.get();
+ }
+
+ /* the optional white list specifies a list of property names for which the caller
+ wants animations for. Curves not matching this list will not be added to the
+ animation layer. */
+ AnimationCurveNodeList Nodes(const char* const * target_prop_whitelist = nullptr, size_t whitelist_size = 0) const;
+
+private:
+ std::shared_ptr<const PropertyTable> props;
+ const Document& doc;
+};
+
+typedef std::vector<const AnimationLayer*> AnimationLayerList;
+
+/** Represents a FBX animation stack (i.e. a list of animation layers) */
+class AnimationStack : public Object {
+public:
+ AnimationStack(uint64_t id, const Element& element, const std::string& name, const Document& doc);
+ virtual ~AnimationStack();
+
+ fbx_simple_property(LocalStart, int64_t, 0L)
+ fbx_simple_property(LocalStop, int64_t, 0L)
+ fbx_simple_property(ReferenceStart, int64_t, 0L)
+ fbx_simple_property(ReferenceStop, int64_t, 0L)
+
+ const PropertyTable& Props() const {
+ ai_assert(props.get());
+ return *props.get();
+ }
+
+ const AnimationLayerList& Layers() const {
+ return layers;
+ }
+
+private:
+ std::shared_ptr<const PropertyTable> props;
+ AnimationLayerList layers;
+};
+
+
+/** DOM class for deformers */
+class Deformer : public Object {
+public:
+ Deformer(uint64_t id, const Element& element, const Document& doc, const std::string& name);
+ virtual ~Deformer();
+
+ const PropertyTable& Props() const {
+ ai_assert(props.get());
+ return *props.get();
+ }
+
+private:
+ std::shared_ptr<const PropertyTable> props;
+};
+
+typedef std::vector<float> WeightArray;
+typedef std::vector<unsigned int> WeightIndexArray;
+
+
+/** DOM class for BlendShapeChannel deformers */
+class BlendShapeChannel : public Deformer {
+public:
+ BlendShapeChannel(uint64_t id, const Element& element, const Document& doc, const std::string& name);
+
+ virtual ~BlendShapeChannel();
+
+ float DeformPercent() const {
+ return percent;
+ }
+
+ const WeightArray& GetFullWeights() const {
+ return fullWeights;
+ }
+
+ const std::vector<const ShapeGeometry*>& GetShapeGeometries() const {
+ return shapeGeometries;
+ }
+
+private:
+ float percent;
+ WeightArray fullWeights;
+ std::vector<const ShapeGeometry*> shapeGeometries;
+};
+
+/** DOM class for BlendShape deformers */
+class BlendShape : public Deformer {
+public:
+ BlendShape(uint64_t id, const Element& element, const Document& doc, const std::string& name);
+
+ virtual ~BlendShape();
+
+ const std::vector<const BlendShapeChannel*>& BlendShapeChannels() const {
+ return blendShapeChannels;
+ }
+
+private:
+ std::vector<const BlendShapeChannel*> blendShapeChannels;
+};
+
+/** DOM class for skin deformer clusters (aka sub-deformers) */
+class Cluster : public Deformer {
+public:
+ Cluster(uint64_t id, const Element& element, const Document& doc, const std::string& name);
+
+ virtual ~Cluster();
+
+ /** get the list of deformer weights associated with this cluster.
+ * Use #GetIndices() to get the associated vertices. Both arrays
+ * have the same size (and may also be empty). */
+ const WeightArray& GetWeights() const {
+ return weights;
+ }
+
+ /** get indices into the vertex data of the geometry associated
+ * with this cluster. Use #GetWeights() to get the associated weights.
+ * Both arrays have the same size (and may also be empty). */
+ const WeightIndexArray& GetIndices() const {
+ return indices;
+ }
+
+ /** */
+ const aiMatrix4x4& Transform() const {
+ return transform;
+ }
+
+ const aiMatrix4x4& TransformLink() const {
+ return transformLink;
+ }
+
+ const Model* TargetNode() const {
+ return node;
+ }
+
+private:
+ WeightArray weights;
+ WeightIndexArray indices;
+
+ aiMatrix4x4 transform;
+ aiMatrix4x4 transformLink;
+
+ const Model* node;
+};
+
+/** DOM class for skin deformers */
+class Skin : public Deformer {
+public:
+ Skin(uint64_t id, const Element& element, const Document& doc, const std::string& name);
+
+ virtual ~Skin();
+
+ float DeformAccuracy() const {
+ return accuracy;
+ }
+
+ const std::vector<const Cluster*>& Clusters() const {
+ return clusters;
+ }
+
+private:
+ float accuracy;
+ std::vector<const Cluster*> clusters;
+};
+
+/** Represents a link between two FBX objects. */
+class Connection {
+public:
+ Connection(uint64_t insertionOrder, uint64_t src, uint64_t dest, const std::string& prop, const Document& doc);
+
+ ~Connection();
+
+ // note: a connection ensures that the source and dest objects exist, but
+ // not that they have DOM representations, so the return value of one of
+ // these functions can still be NULL.
+ const Object* SourceObject() const;
+ const Object* DestinationObject() const;
+
+ // these, however, are always guaranteed to be valid
+ LazyObject& LazySourceObject() const;
+ LazyObject& LazyDestinationObject() const;
+
+
+ /** return the name of the property the connection is attached to.
+ * this is an empty string for object to object (OO) connections. */
+ const std::string& PropertyName() const {
+ return prop;
+ }
+
+ uint64_t InsertionOrder() const {
+ return insertionOrder;
+ }
+
+ int CompareTo(const Connection* c) const {
+ ai_assert( nullptr != c );
+
+ // note: can't subtract because this would overflow uint64_t
+ if(InsertionOrder() > c->InsertionOrder()) {
+ return 1;
+ }
+ else if(InsertionOrder() < c->InsertionOrder()) {
+ return -1;
+ }
+ return 0;
+ }
+
+ bool Compare(const Connection* c) const {
+ ai_assert( nullptr != c );
+
+ return InsertionOrder() < c->InsertionOrder();
+ }
+
+public:
+ uint64_t insertionOrder;
+ const std::string prop;
+
+ uint64_t src, dest;
+ const Document& doc;
+};
+
+// XXX again, unique_ptr would be useful. shared_ptr is too
+// bloated since the objects have a well-defined single owner
+// during their entire lifetime (Document). FBX files have
+// up to many thousands of objects (most of which we never use),
+// so the memory overhead for them should be kept at a minimum.
+typedef std::map<uint64_t, LazyObject*> ObjectMap;
+typedef std::fbx_unordered_map<std::string, std::shared_ptr<const PropertyTable> > PropertyTemplateMap;
+
+typedef std::multimap<uint64_t, const Connection*> ConnectionMap;
+
+/** DOM class for global document settings, a single instance per document can
+ * be accessed via Document.Globals(). */
+class FileGlobalSettings {
+public:
+ FileGlobalSettings(const Document& doc, std::shared_ptr<const PropertyTable> props);
+
+ ~FileGlobalSettings();
+
+ const PropertyTable& Props() const {
+ ai_assert(props.get());
+ return *props.get();
+ }
+
+ const Document& GetDocument() const {
+ return doc;
+ }
+
+ fbx_simple_property(UpAxis, int, 1)
+ fbx_simple_property(UpAxisSign, int, 1)
+ fbx_simple_property(FrontAxis, int, 2)
+ fbx_simple_property(FrontAxisSign, int, 1)
+ fbx_simple_property(CoordAxis, int, 0)
+ fbx_simple_property(CoordAxisSign, int, 1)
+ fbx_simple_property(OriginalUpAxis, int, 0)
+ fbx_simple_property(OriginalUpAxisSign, int, 1)
+ fbx_simple_property(UnitScaleFactor, float, 1)
+ fbx_simple_property(OriginalUnitScaleFactor, float, 1)
+ fbx_simple_property(AmbientColor, aiVector3D, aiVector3D(0,0,0))
+ fbx_simple_property(DefaultCamera, std::string, "")
+
+
+ enum FrameRate {
+ FrameRate_DEFAULT = 0,
+ FrameRate_120 = 1,
+ FrameRate_100 = 2,
+ FrameRate_60 = 3,
+ FrameRate_50 = 4,
+ FrameRate_48 = 5,
+ FrameRate_30 = 6,
+ FrameRate_30_DROP = 7,
+ FrameRate_NTSC_DROP_FRAME = 8,
+ FrameRate_NTSC_FULL_FRAME = 9,
+ FrameRate_PAL = 10,
+ FrameRate_CINEMA = 11,
+ FrameRate_1000 = 12,
+ FrameRate_CINEMA_ND = 13,
+ FrameRate_CUSTOM = 14,
+
+ FrameRate_MAX// end-of-enum sentinel
+ };
+
+ fbx_simple_enum_property(TimeMode, FrameRate, FrameRate_DEFAULT)
+ fbx_simple_property(TimeSpanStart, uint64_t, 0L)
+ fbx_simple_property(TimeSpanStop, uint64_t, 0L)
+ fbx_simple_property(CustomFrameRate, float, -1.0f)
+
+private:
+ std::shared_ptr<const PropertyTable> props;
+ const Document& doc;
+};
+
+/** DOM root for a FBX file */
+class Document {
+public:
+ Document(const Parser& parser, const ImportSettings& settings);
+
+ ~Document();
+
+ LazyObject* GetObject(uint64_t id) const;
+
+ bool IsBinary() const {
+ return parser.IsBinary();
+ }
+
+ unsigned int FBXVersion() const {
+ return fbxVersion;
+ }
+
+ const std::string& Creator() const {
+ return creator;
+ }
+
+ // elements (in this order): Year, Month, Day, Hour, Second, Millisecond
+ const unsigned int* CreationTimeStamp() const {
+ return creationTimeStamp;
+ }
+
+ const FileGlobalSettings& GlobalSettings() const {
+ ai_assert(globals.get());
+ return *globals.get();
+ }
+
+ const PropertyTemplateMap& Templates() const {
+ return templates;
+ }
+
+ const ObjectMap& Objects() const {
+ return objects;
+ }
+
+ const ImportSettings& Settings() const {
+ return settings;
+ }
+
+ const ConnectionMap& ConnectionsBySource() const {
+ return src_connections;
+ }
+
+ const ConnectionMap& ConnectionsByDestination() const {
+ return dest_connections;
+ }
+
+ // note: the implicit rule in all DOM classes is to always resolve
+ // from destination to source (since the FBX object hierarchy is,
+ // with very few exceptions, a DAG, this avoids cycles). In all
+ // cases that may involve back-facing edges in the object graph,
+ // use LazyObject::IsBeingConstructed() to check.
+
+ std::vector<const Connection*> GetConnectionsBySourceSequenced(uint64_t source) const;
+ std::vector<const Connection*> GetConnectionsByDestinationSequenced(uint64_t dest) const;
+
+ std::vector<const Connection*> GetConnectionsBySourceSequenced(uint64_t source, const char* classname) const;
+ std::vector<const Connection*> GetConnectionsByDestinationSequenced(uint64_t dest, const char* classname) const;
+
+ std::vector<const Connection*> GetConnectionsBySourceSequenced(uint64_t source,
+ const char* const* classnames, size_t count) const;
+ std::vector<const Connection*> GetConnectionsByDestinationSequenced(uint64_t dest,
+ const char* const* classnames,
+ size_t count) const;
+
+ const std::vector<const AnimationStack*>& AnimationStacks() const;
+
+private:
+ std::vector<const Connection*> GetConnectionsSequenced(uint64_t id, const ConnectionMap&) const;
+ std::vector<const Connection*> GetConnectionsSequenced(uint64_t id, bool is_src,
+ const ConnectionMap&,
+ const char* const* classnames,
+ size_t count) const;
+ void ReadHeader();
+ void ReadObjects();
+ void ReadPropertyTemplates();
+ void ReadConnections();
+ void ReadGlobalSettings();
+
+private:
+ const ImportSettings& settings;
+
+ ObjectMap objects;
+ const Parser& parser;
+
+ PropertyTemplateMap templates;
+ ConnectionMap src_connections;
+ ConnectionMap dest_connections;
+
+ unsigned int fbxVersion;
+ std::string creator;
+ unsigned int creationTimeStamp[7];
+
+ std::vector<uint64_t> animationStacks;
+ mutable std::vector<const AnimationStack*> animationStacksResolved;
+
+ std::unique_ptr<FileGlobalSettings> globals;
+};
+
+} // Namespace FBX
+} // Namespace Assimp
+
+#endif // INCLUDED_AI_FBX_DOCUMENT_H
diff --git a/thirdparty/assimp/code/FBXDocumentUtil.cpp b/thirdparty/assimp/code/FBXDocumentUtil.cpp
new file mode 100644
index 0000000000..f84691479a
--- /dev/null
+++ b/thirdparty/assimp/code/FBXDocumentUtil.cpp
@@ -0,0 +1,135 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file FBXDocumentUtil.cpp
+ * @brief Implementation of the FBX DOM utility functions declared in FBXDocumentUtil.h
+ */
+
+#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
+
+#include "FBXParser.h"
+#include "FBXDocument.h"
+#include "FBXUtil.h"
+#include "FBXDocumentUtil.h"
+#include "FBXProperties.h"
+
+
+namespace Assimp {
+namespace FBX {
+namespace Util {
+
+// ------------------------------------------------------------------------------------------------
+// signal DOM construction error, this is always unrecoverable. Throws DeadlyImportError.
+void DOMError(const std::string& message, const Token& token)
+{
+ throw DeadlyImportError(Util::AddTokenText("FBX-DOM",message,&token));
+}
+
+// ------------------------------------------------------------------------------------------------
+void DOMError(const std::string& message, const Element* element /*= NULL*/)
+{
+ if(element) {
+ DOMError(message,element->KeyToken());
+ }
+ throw DeadlyImportError("FBX-DOM " + message);
+}
+
+
+// ------------------------------------------------------------------------------------------------
+// print warning, do return
+void DOMWarning(const std::string& message, const Token& token)
+{
+ if(DefaultLogger::get()) {
+ ASSIMP_LOG_WARN(Util::AddTokenText("FBX-DOM",message,&token));
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+void DOMWarning(const std::string& message, const Element* element /*= NULL*/)
+{
+ if(element) {
+ DOMWarning(message,element->KeyToken());
+ return;
+ }
+ if(DefaultLogger::get()) {
+ ASSIMP_LOG_WARN("FBX-DOM: " + message);
+ }
+}
+
+
+// ------------------------------------------------------------------------------------------------
+// fetch a property table and the corresponding property template
+std::shared_ptr<const PropertyTable> GetPropertyTable(const Document& doc,
+ const std::string& templateName,
+ const Element &element,
+ const Scope& sc,
+ bool no_warn /*= false*/)
+{
+ const Element* const Properties70 = sc["Properties70"];
+ std::shared_ptr<const PropertyTable> templateProps = std::shared_ptr<const PropertyTable>(
+ static_cast<const PropertyTable*>(NULL));
+
+ if(templateName.length()) {
+ PropertyTemplateMap::const_iterator it = doc.Templates().find(templateName);
+ if(it != doc.Templates().end()) {
+ templateProps = (*it).second;
+ }
+ }
+
+ if(!Properties70 || !Properties70->Compound()) {
+ if(!no_warn) {
+ DOMWarning("property table (Properties70) not found",&element);
+ }
+ if(templateProps) {
+ return templateProps;
+ }
+ else {
+ return std::make_shared<const PropertyTable>();
+ }
+ }
+ return std::make_shared<const PropertyTable>(*Properties70,templateProps);
+}
+} // !Util
+} // !FBX
+} // !Assimp
+
+#endif
diff --git a/thirdparty/assimp/code/FBXDocumentUtil.h b/thirdparty/assimp/code/FBXDocumentUtil.h
new file mode 100644
index 0000000000..2450109e59
--- /dev/null
+++ b/thirdparty/assimp/code/FBXDocumentUtil.h
@@ -0,0 +1,120 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file FBXDocumentUtil.h
+ * @brief FBX internal utilities used by the DOM reading code
+ */
+#ifndef INCLUDED_AI_FBX_DOCUMENT_UTIL_H
+#define INCLUDED_AI_FBX_DOCUMENT_UTIL_H
+
+#include <assimp/defs.h>
+#include <string>
+#include <memory>
+#include "FBXDocument.h"
+
+struct Token;
+struct Element;
+
+namespace Assimp {
+namespace FBX {
+namespace Util {
+
+/* DOM/Parse error reporting - does not return */
+AI_WONT_RETURN void DOMError(const std::string& message, const Token& token) AI_WONT_RETURN_SUFFIX;
+AI_WONT_RETURN void DOMError(const std::string& message, const Element* element = NULL) AI_WONT_RETURN_SUFFIX;
+
+// does return
+void DOMWarning(const std::string& message, const Token& token);
+void DOMWarning(const std::string& message, const Element* element = NULL);
+
+
+// fetch a property table and the corresponding property template
+std::shared_ptr<const PropertyTable> GetPropertyTable(const Document& doc,
+ const std::string& templateName,
+ const Element &element,
+ const Scope& sc,
+ bool no_warn = false);
+
+// ------------------------------------------------------------------------------------------------
+template <typename T>
+inline
+const T* ProcessSimpleConnection(const Connection& con,
+ bool is_object_property_conn,
+ const char* name,
+ const Element& element,
+ const char** propNameOut = nullptr)
+{
+ if (is_object_property_conn && !con.PropertyName().length()) {
+ DOMWarning("expected incoming " + std::string(name) +
+ " link to be an object-object connection, ignoring",
+ &element
+ );
+ return nullptr;
+ }
+ else if (!is_object_property_conn && con.PropertyName().length()) {
+ DOMWarning("expected incoming " + std::string(name) +
+ " link to be an object-property connection, ignoring",
+ &element
+ );
+ return nullptr;
+ }
+
+ if(is_object_property_conn && propNameOut) {
+ // note: this is ok, the return value of PropertyValue() is guaranteed to
+ // remain valid and unchanged as long as the document exists.
+ *propNameOut = con.PropertyName().c_str();
+ }
+
+ const Object* const ob = con.SourceObject();
+ if(!ob) {
+ DOMWarning("failed to read source object for incoming " + std::string(name) +
+ " link, ignoring",
+ &element);
+ return nullptr;
+ }
+
+ return dynamic_cast<const T*>(ob);
+}
+
+} //!Util
+} //!FBX
+} //!Assimp
+
+#endif
diff --git a/thirdparty/assimp/code/FBXExportNode.cpp b/thirdparty/assimp/code/FBXExportNode.cpp
new file mode 100644
index 0000000000..e5215466a1
--- /dev/null
+++ b/thirdparty/assimp/code/FBXExportNode.cpp
@@ -0,0 +1,568 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+#ifndef ASSIMP_BUILD_NO_EXPORT
+#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
+
+#include "FBXExportNode.h"
+#include "FBXCommon.h"
+
+#include <assimp/StreamWriter.h> // StreamWriterLE
+#include <assimp/Exceptional.h> // DeadlyExportError
+#include <assimp/ai_assert.h>
+#include <assimp/StringUtils.h> // ai_snprintf
+
+#include <string>
+#include <ostream>
+#include <sstream> // ostringstream
+#include <memory> // shared_ptr
+
+// AddP70<type> helpers... there's no usable pattern here,
+// so all are defined as separate functions.
+// Even "animatable" properties are often completely different
+// from the standard (nonanimated) property definition,
+// so they are specified with an 'A' suffix.
+
+void FBX::Node::AddP70int(
+ const std::string& name, int32_t value
+) {
+ FBX::Node n("P");
+ n.AddProperties(name, "int", "Integer", "", value);
+ AddChild(n);
+}
+
+void FBX::Node::AddP70bool(
+ const std::string& name, bool value
+) {
+ FBX::Node n("P");
+ n.AddProperties(name, "bool", "", "", int32_t(value));
+ AddChild(n);
+}
+
+void FBX::Node::AddP70double(
+ const std::string& name, double value
+) {
+ FBX::Node n("P");
+ n.AddProperties(name, "double", "Number", "", value);
+ AddChild(n);
+}
+
+void FBX::Node::AddP70numberA(
+ const std::string& name, double value
+) {
+ FBX::Node n("P");
+ n.AddProperties(name, "Number", "", "A", value);
+ AddChild(n);
+}
+
+void FBX::Node::AddP70color(
+ const std::string& name, double r, double g, double b
+) {
+ FBX::Node n("P");
+ n.AddProperties(name, "ColorRGB", "Color", "", r, g, b);
+ AddChild(n);
+}
+
+void FBX::Node::AddP70colorA(
+ const std::string& name, double r, double g, double b
+) {
+ FBX::Node n("P");
+ n.AddProperties(name, "Color", "", "A", r, g, b);
+ AddChild(n);
+}
+
+void FBX::Node::AddP70vector(
+ const std::string& name, double x, double y, double z
+) {
+ FBX::Node n("P");
+ n.AddProperties(name, "Vector3D", "Vector", "", x, y, z);
+ AddChild(n);
+}
+
+void FBX::Node::AddP70vectorA(
+ const std::string& name, double x, double y, double z
+) {
+ FBX::Node n("P");
+ n.AddProperties(name, "Vector", "", "A", x, y, z);
+ AddChild(n);
+}
+
+void FBX::Node::AddP70string(
+ const std::string& name, const std::string& value
+) {
+ FBX::Node n("P");
+ n.AddProperties(name, "KString", "", "", value);
+ AddChild(n);
+}
+
+void FBX::Node::AddP70enum(
+ const std::string& name, int32_t value
+) {
+ FBX::Node n("P");
+ n.AddProperties(name, "enum", "", "", value);
+ AddChild(n);
+}
+
+void FBX::Node::AddP70time(
+ const std::string& name, int64_t value
+) {
+ FBX::Node n("P");
+ n.AddProperties(name, "KTime", "Time", "", value);
+ AddChild(n);
+}
+
+
+// public member functions for writing nodes to stream
+
+void FBX::Node::Dump(
+ std::shared_ptr<Assimp::IOStream> outfile,
+ bool binary, int indent
+) {
+ if (binary) {
+ Assimp::StreamWriterLE outstream(outfile);
+ DumpBinary(outstream);
+ } else {
+ std::ostringstream ss;
+ DumpAscii(ss, indent);
+ std::string s = ss.str();
+ outfile->Write(s.c_str(), s.size(), 1);
+ }
+}
+
+void FBX::Node::Dump(
+ Assimp::StreamWriterLE &outstream,
+ bool binary, int indent
+) {
+ if (binary) {
+ DumpBinary(outstream);
+ } else {
+ std::ostringstream ss;
+ DumpAscii(ss, indent);
+ outstream.PutString(ss.str());
+ }
+}
+
+
+// public member functions for low-level writing
+
+void FBX::Node::Begin(
+ Assimp::StreamWriterLE &s,
+ bool binary, int indent
+) {
+ if (binary) {
+ BeginBinary(s);
+ } else {
+ // assume we're at the correct place to start already
+ (void)indent;
+ std::ostringstream ss;
+ BeginAscii(ss, indent);
+ s.PutString(ss.str());
+ }
+}
+
+void FBX::Node::DumpProperties(
+ Assimp::StreamWriterLE& s,
+ bool binary, int indent
+) {
+ if (binary) {
+ DumpPropertiesBinary(s);
+ } else {
+ std::ostringstream ss;
+ DumpPropertiesAscii(ss, indent);
+ s.PutString(ss.str());
+ }
+}
+
+void FBX::Node::EndProperties(
+ Assimp::StreamWriterLE &s,
+ bool binary, int indent
+) {
+ EndProperties(s, binary, indent, properties.size());
+}
+
+void FBX::Node::EndProperties(
+ Assimp::StreamWriterLE &s,
+ bool binary, int indent,
+ size_t num_properties
+) {
+ if (binary) {
+ EndPropertiesBinary(s, num_properties);
+ } else {
+ // nothing to do
+ (void)indent;
+ }
+}
+
+void FBX::Node::BeginChildren(
+ Assimp::StreamWriterLE &s,
+ bool binary, int indent
+) {
+ if (binary) {
+ // nothing to do
+ } else {
+ std::ostringstream ss;
+ BeginChildrenAscii(ss, indent);
+ s.PutString(ss.str());
+ }
+}
+
+void FBX::Node::DumpChildren(
+ Assimp::StreamWriterLE& s,
+ bool binary, int indent
+) {
+ if (binary) {
+ DumpChildrenBinary(s);
+ } else {
+ std::ostringstream ss;
+ DumpChildrenAscii(ss, indent);
+ s.PutString(ss.str());
+ }
+}
+
+void FBX::Node::End(
+ Assimp::StreamWriterLE &s,
+ bool binary, int indent,
+ bool has_children
+) {
+ if (binary) {
+ EndBinary(s, has_children);
+ } else {
+ std::ostringstream ss;
+ EndAscii(ss, indent, has_children);
+ s.PutString(ss.str());
+ }
+}
+
+
+// public member functions for writing to binary fbx
+
+void FBX::Node::DumpBinary(Assimp::StreamWriterLE &s)
+{
+ // write header section (with placeholders for some things)
+ BeginBinary(s);
+
+ // write properties
+ DumpPropertiesBinary(s);
+
+ // go back and fill in property related placeholders
+ EndPropertiesBinary(s, properties.size());
+
+ // write children
+ DumpChildrenBinary(s);
+
+ // finish, filling in end offset placeholder
+ EndBinary(s, force_has_children || !children.empty());
+}
+
+
+// public member functions for writing to ascii fbx
+
+void FBX::Node::DumpAscii(std::ostream &s, int indent)
+{
+ // write name
+ BeginAscii(s, indent);
+
+ // write properties
+ DumpPropertiesAscii(s, indent);
+
+ if (force_has_children || !children.empty()) {
+ // begin children (with a '{')
+ BeginChildrenAscii(s, indent + 1);
+ // write children
+ DumpChildrenAscii(s, indent + 1);
+ }
+
+ // finish (also closing the children bracket '}')
+ EndAscii(s, indent, force_has_children || !children.empty());
+}
+
+
+// private member functions for low-level writing to fbx
+
+void FBX::Node::BeginBinary(Assimp::StreamWriterLE &s)
+{
+ // remember start pos so we can come back and write the end pos
+ this->start_pos = s.Tell();
+
+ // placeholders for end pos and property section info
+ s.PutU4(0); // end pos
+ s.PutU4(0); // number of properties
+ s.PutU4(0); // total property section length
+
+ // node name
+ s.PutU1(uint8_t(name.size())); // length of node name
+ s.PutString(name); // node name as raw bytes
+
+ // property data comes after here
+ this->property_start = s.Tell();
+}
+
+void FBX::Node::DumpPropertiesBinary(Assimp::StreamWriterLE& s)
+{
+ for (auto &p : properties) {
+ p.DumpBinary(s);
+ }
+}
+
+void FBX::Node::EndPropertiesBinary(
+ Assimp::StreamWriterLE &s,
+ size_t num_properties
+) {
+ if (num_properties == 0) { return; }
+ size_t pos = s.Tell();
+ ai_assert(pos > property_start);
+ size_t property_section_size = pos - property_start;
+ s.Seek(start_pos + 4);
+ s.PutU4(uint32_t(num_properties));
+ s.PutU4(uint32_t(property_section_size));
+ s.Seek(pos);
+}
+
+void FBX::Node::DumpChildrenBinary(Assimp::StreamWriterLE& s)
+{
+ for (FBX::Node& child : children) {
+ child.DumpBinary(s);
+ }
+}
+
+void FBX::Node::EndBinary(
+ Assimp::StreamWriterLE &s,
+ bool has_children
+) {
+ // if there were children, add a null record
+ if (has_children) { s.PutString(FBX::NULL_RECORD); }
+
+ // now go back and write initial pos
+ this->end_pos = s.Tell();
+ s.Seek(start_pos);
+ s.PutU4(uint32_t(end_pos));
+ s.Seek(end_pos);
+}
+
+
+void FBX::Node::BeginAscii(std::ostream& s, int indent)
+{
+ s << '\n';
+ for (int i = 0; i < indent; ++i) { s << '\t'; }
+ s << name << ": ";
+}
+
+void FBX::Node::DumpPropertiesAscii(std::ostream &s, int indent)
+{
+ for (size_t i = 0; i < properties.size(); ++i) {
+ if (i > 0) { s << ", "; }
+ properties[i].DumpAscii(s, indent);
+ }
+}
+
+void FBX::Node::BeginChildrenAscii(std::ostream& s, int indent)
+{
+ // only call this if there are actually children
+ s << " {";
+ (void)indent;
+}
+
+void FBX::Node::DumpChildrenAscii(std::ostream& s, int indent)
+{
+ // children will need a lot of padding and corralling
+ if (children.size() || force_has_children) {
+ for (size_t i = 0; i < children.size(); ++i) {
+ // no compression in ascii files, so skip this node if it exists
+ if (children[i].name == "EncryptionType") { continue; }
+ // the child can dump itself
+ children[i].DumpAscii(s, indent);
+ }
+ }
+}
+
+void FBX::Node::EndAscii(std::ostream& s, int indent, bool has_children)
+{
+ if (!has_children) { return; } // nothing to do
+ s << '\n';
+ for (int i = 0; i < indent; ++i) { s << '\t'; }
+ s << "}";
+}
+
+// private helpers for static member functions
+
+// ascii property node from vector of doubles
+void FBX::Node::WritePropertyNodeAscii(
+ const std::string& name,
+ const std::vector<double>& v,
+ Assimp::StreamWriterLE& s,
+ int indent
+){
+ char buffer[32];
+ FBX::Node node(name);
+ node.Begin(s, false, indent);
+ std::string vsize = to_string(v.size());
+ // *<size> {
+ s.PutChar('*'); s.PutString(vsize); s.PutString(" {\n");
+ // indent + 1
+ for (int i = 0; i < indent + 1; ++i) { s.PutChar('\t'); }
+ // a: value,value,value,...
+ s.PutString("a: ");
+ int count = 0;
+ for (size_t i = 0; i < v.size(); ++i) {
+ if (i > 0) { s.PutChar(','); }
+ int len = ai_snprintf(buffer, sizeof(buffer), "%f", v[i]);
+ count += len;
+ if (count > 2048) { s.PutChar('\n'); count = 0; }
+ if (len < 0 || len > 31) {
+ // this should never happen
+ throw DeadlyExportError("failed to convert double to string");
+ }
+ for (int j = 0; j < len; ++j) { s.PutChar(buffer[j]); }
+ }
+ // }
+ s.PutChar('\n');
+ for (int i = 0; i < indent; ++i) { s.PutChar('\t'); }
+ s.PutChar('}'); s.PutChar(' ');
+ node.End(s, false, indent, false);
+}
+
+// ascii property node from vector of int32_t
+void FBX::Node::WritePropertyNodeAscii(
+ const std::string& name,
+ const std::vector<int32_t>& v,
+ Assimp::StreamWriterLE& s,
+ int indent
+){
+ char buffer[32];
+ FBX::Node node(name);
+ node.Begin(s, false, indent);
+ std::string vsize = to_string(v.size());
+ // *<size> {
+ s.PutChar('*'); s.PutString(vsize); s.PutString(" {\n");
+ // indent + 1
+ for (int i = 0; i < indent + 1; ++i) { s.PutChar('\t'); }
+ // a: value,value,value,...
+ s.PutString("a: ");
+ int count = 0;
+ for (size_t i = 0; i < v.size(); ++i) {
+ if (i > 0) { s.PutChar(','); }
+ int len = ai_snprintf(buffer, sizeof(buffer), "%d", v[i]);
+ count += len;
+ if (count > 2048) { s.PutChar('\n'); count = 0; }
+ if (len < 0 || len > 31) {
+ // this should never happen
+ throw DeadlyExportError("failed to convert double to string");
+ }
+ for (int j = 0; j < len; ++j) { s.PutChar(buffer[j]); }
+ }
+ // }
+ s.PutChar('\n');
+ for (int i = 0; i < indent; ++i) { s.PutChar('\t'); }
+ s.PutChar('}'); s.PutChar(' ');
+ node.End(s, false, indent, false);
+}
+
+// binary property node from vector of doubles
+// TODO: optional zip compression!
+void FBX::Node::WritePropertyNodeBinary(
+ const std::string& name,
+ const std::vector<double>& v,
+ Assimp::StreamWriterLE& s
+){
+ FBX::Node node(name);
+ node.BeginBinary(s);
+ s.PutU1('d');
+ s.PutU4(uint32_t(v.size())); // number of elements
+ s.PutU4(0); // no encoding (1 would be zip-compressed)
+ s.PutU4(uint32_t(v.size()) * 8); // data size
+ for (auto it = v.begin(); it != v.end(); ++it) { s.PutF8(*it); }
+ node.EndPropertiesBinary(s, 1);
+ node.EndBinary(s, false);
+}
+
+// binary property node from vector of int32_t
+// TODO: optional zip compression!
+void FBX::Node::WritePropertyNodeBinary(
+ const std::string& name,
+ const std::vector<int32_t>& v,
+ Assimp::StreamWriterLE& s
+){
+ FBX::Node node(name);
+ node.BeginBinary(s);
+ s.PutU1('i');
+ s.PutU4(uint32_t(v.size())); // number of elements
+ s.PutU4(0); // no encoding (1 would be zip-compressed)
+ s.PutU4(uint32_t(v.size()) * 4); // data size
+ for (auto it = v.begin(); it != v.end(); ++it) { s.PutI4(*it); }
+ node.EndPropertiesBinary(s, 1);
+ node.EndBinary(s, false);
+}
+
+// public static member functions
+
+// convenience function to create and write a property node,
+// holding a single property which is an array of values.
+// does not copy the data, so is efficient for large arrays.
+void FBX::Node::WritePropertyNode(
+ const std::string& name,
+ const std::vector<double>& v,
+ Assimp::StreamWriterLE& s,
+ bool binary, int indent
+){
+ if (binary) {
+ FBX::Node::WritePropertyNodeBinary(name, v, s);
+ } else {
+ FBX::Node::WritePropertyNodeAscii(name, v, s, indent);
+ }
+}
+
+// convenience function to create and write a property node,
+// holding a single property which is an array of values.
+// does not copy the data, so is efficient for large arrays.
+void FBX::Node::WritePropertyNode(
+ const std::string& name,
+ const std::vector<int32_t>& v,
+ Assimp::StreamWriterLE& s,
+ bool binary, int indent
+){
+ if (binary) {
+ FBX::Node::WritePropertyNodeBinary(name, v, s);
+ } else {
+ FBX::Node::WritePropertyNodeAscii(name, v, s, indent);
+ }
+}
+
+#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
+#endif // ASSIMP_BUILD_NO_EXPORT
diff --git a/thirdparty/assimp/code/FBXExportNode.h b/thirdparty/assimp/code/FBXExportNode.h
new file mode 100644
index 0000000000..e1ebc36969
--- /dev/null
+++ b/thirdparty/assimp/code/FBXExportNode.h
@@ -0,0 +1,271 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file FBXExportNode.h
+* Declares the FBX::Node helper class for fbx export.
+*/
+#ifndef AI_FBXEXPORTNODE_H_INC
+#define AI_FBXEXPORTNODE_H_INC
+
+#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
+
+#include "FBXExportProperty.h"
+
+#include <assimp/StreamWriter.h> // StreamWriterLE
+
+#include <string>
+#include <vector>
+
+namespace FBX {
+ class Node;
+}
+
+class FBX::Node
+{
+public: // public data members
+ // TODO: accessors
+ std::string name; // node name
+ std::vector<FBX::Property> properties; // node properties
+ std::vector<FBX::Node> children; // child nodes
+
+ // some nodes always pretend they have children...
+ bool force_has_children = false;
+
+public: // constructors
+ /// The default class constructor.
+ Node() = default;
+
+ /// The class constructor with the name.
+ Node(const std::string& n)
+ : name(n)
+ , properties()
+ , children()
+ , force_has_children( false ) {
+ // empty
+ }
+
+ // convenience template to construct with properties directly
+ template <typename... More>
+ Node(const std::string& n, const More... more)
+ : name(n)
+ , properties()
+ , children()
+ , force_has_children(false) {
+ AddProperties(more...);
+ }
+
+public: // functions to add properties or children
+ // add a single property to the node
+ template <typename T>
+ void AddProperty(T value) {
+ properties.emplace_back(value);
+ }
+
+ // convenience function to add multiple properties at once
+ template <typename T, typename... More>
+ void AddProperties(T value, More... more) {
+ properties.emplace_back(value);
+ AddProperties(more...);
+ }
+ void AddProperties() {}
+
+ // add a child node directly
+ void AddChild(const Node& node) { children.push_back(node); }
+
+ // convenience function to add a child node with a single property
+ template <typename... More>
+ void AddChild(
+ const std::string& name,
+ More... more
+ ) {
+ FBX::Node c(name);
+ c.AddProperties(more...);
+ children.push_back(c);
+ }
+
+public: // support specifically for dealing with Properties70 nodes
+
+ // it really is simpler to make these all separate functions.
+ // the versions with 'A' suffixes are for animatable properties.
+ // those often follow a completely different format internally in FBX.
+ void AddP70int(const std::string& name, int32_t value);
+ void AddP70bool(const std::string& name, bool value);
+ void AddP70double(const std::string& name, double value);
+ void AddP70numberA(const std::string& name, double value);
+ void AddP70color(const std::string& name, double r, double g, double b);
+ void AddP70colorA(const std::string& name, double r, double g, double b);
+ void AddP70vector(const std::string& name, double x, double y, double z);
+ void AddP70vectorA(const std::string& name, double x, double y, double z);
+ void AddP70string(const std::string& name, const std::string& value);
+ void AddP70enum(const std::string& name, int32_t value);
+ void AddP70time(const std::string& name, int64_t value);
+
+ // template for custom P70 nodes.
+ // anything that doesn't fit in the above can be created manually.
+ template <typename... More>
+ void AddP70(
+ const std::string& name,
+ const std::string& type,
+ const std::string& type2,
+ const std::string& flags,
+ More... more
+ ) {
+ Node n("P");
+ n.AddProperties(name, type, type2, flags, more...);
+ AddChild(n);
+ }
+
+public: // member functions for writing data to a file or stream
+
+ // write the full node to the given file or stream
+ void Dump(
+ std::shared_ptr<Assimp::IOStream> outfile,
+ bool binary, int indent
+ );
+ void Dump(Assimp::StreamWriterLE &s, bool binary, int indent);
+
+ // these other functions are for writing data piece by piece.
+ // they must be used carefully.
+ // for usage examples see FBXExporter.cpp.
+ void Begin(Assimp::StreamWriterLE &s, bool binary, int indent);
+ void DumpProperties(Assimp::StreamWriterLE& s, bool binary, int indent);
+ void EndProperties(Assimp::StreamWriterLE &s, bool binary, int indent);
+ void EndProperties(
+ Assimp::StreamWriterLE &s, bool binary, int indent,
+ size_t num_properties
+ );
+ void BeginChildren(Assimp::StreamWriterLE &s, bool binary, int indent);
+ void DumpChildren(Assimp::StreamWriterLE& s, bool binary, int indent);
+ void End(
+ Assimp::StreamWriterLE &s, bool binary, int indent,
+ bool has_children
+ );
+
+private: // internal functions used for writing
+
+ void DumpBinary(Assimp::StreamWriterLE &s);
+ void DumpAscii(Assimp::StreamWriterLE &s, int indent);
+ void DumpAscii(std::ostream &s, int indent);
+
+ void BeginBinary(Assimp::StreamWriterLE &s);
+ void DumpPropertiesBinary(Assimp::StreamWriterLE& s);
+ void EndPropertiesBinary(Assimp::StreamWriterLE &s);
+ void EndPropertiesBinary(Assimp::StreamWriterLE &s, size_t num_properties);
+ void DumpChildrenBinary(Assimp::StreamWriterLE& s);
+ void EndBinary(Assimp::StreamWriterLE &s, bool has_children);
+
+ void BeginAscii(std::ostream &s, int indent);
+ void DumpPropertiesAscii(std::ostream &s, int indent);
+ void BeginChildrenAscii(std::ostream &s, int indent);
+ void DumpChildrenAscii(std::ostream &s, int indent);
+ void EndAscii(std::ostream &s, int indent, bool has_children);
+
+private: // data used for binary dumps
+ size_t start_pos; // starting position in stream
+ size_t end_pos; // ending position in stream
+ size_t property_start; // starting position of property section
+
+public: // static member functions
+
+ // convenience function to create a node with a single property,
+ // and write it to the stream.
+ template <typename T>
+ static void WritePropertyNode(
+ const std::string& name,
+ const T value,
+ Assimp::StreamWriterLE& s,
+ bool binary, int indent
+ ) {
+ FBX::Property p(value);
+ FBX::Node node(name, p);
+ node.Dump(s, binary, indent);
+ }
+
+ // convenience function to create and write a property node,
+ // holding a single property which is an array of values.
+ // does not copy the data, so is efficient for large arrays.
+ static void WritePropertyNode(
+ const std::string& name,
+ const std::vector<double>& v,
+ Assimp::StreamWriterLE& s,
+ bool binary, int indent
+ );
+
+ // convenience function to create and write a property node,
+ // holding a single property which is an array of values.
+ // does not copy the data, so is efficient for large arrays.
+ static void WritePropertyNode(
+ const std::string& name,
+ const std::vector<int32_t>& v,
+ Assimp::StreamWriterLE& s,
+ bool binary, int indent
+ );
+
+private: // static helper functions
+ static void WritePropertyNodeAscii(
+ const std::string& name,
+ const std::vector<double>& v,
+ Assimp::StreamWriterLE& s,
+ int indent
+ );
+ static void WritePropertyNodeAscii(
+ const std::string& name,
+ const std::vector<int32_t>& v,
+ Assimp::StreamWriterLE& s,
+ int indent
+ );
+ static void WritePropertyNodeBinary(
+ const std::string& name,
+ const std::vector<double>& v,
+ Assimp::StreamWriterLE& s
+ );
+ static void WritePropertyNodeBinary(
+ const std::string& name,
+ const std::vector<int32_t>& v,
+ Assimp::StreamWriterLE& s
+ );
+
+};
+
+
+#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
+
+#endif // AI_FBXEXPORTNODE_H_INC
diff --git a/thirdparty/assimp/code/FBXExportProperty.cpp b/thirdparty/assimp/code/FBXExportProperty.cpp
new file mode 100644
index 0000000000..9981d6b1c6
--- /dev/null
+++ b/thirdparty/assimp/code/FBXExportProperty.cpp
@@ -0,0 +1,364 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+#ifndef ASSIMP_BUILD_NO_EXPORT
+#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
+
+#include "FBXExportProperty.h"
+
+#include <assimp/StreamWriter.h> // StreamWriterLE
+#include <assimp/Exceptional.h> // DeadlyExportError
+
+#include <string>
+#include <vector>
+#include <ostream>
+#include <locale>
+#include <sstream> // ostringstream
+
+
+// constructors for single element properties
+
+FBX::Property::Property(bool v)
+ : type('C'), data(1)
+{
+ data = {uint8_t(v)};
+}
+
+FBX::Property::Property(int16_t v) : type('Y'), data(2)
+{
+ uint8_t* d = data.data();
+ (reinterpret_cast<int16_t*>(d))[0] = v;
+}
+
+FBX::Property::Property(int32_t v) : type('I'), data(4)
+{
+ uint8_t* d = data.data();
+ (reinterpret_cast<int32_t*>(d))[0] = v;
+}
+
+FBX::Property::Property(float v) : type('F'), data(4)
+{
+ uint8_t* d = data.data();
+ (reinterpret_cast<float*>(d))[0] = v;
+}
+
+FBX::Property::Property(double v) : type('D'), data(8)
+{
+ uint8_t* d = data.data();
+ (reinterpret_cast<double*>(d))[0] = v;
+}
+
+FBX::Property::Property(int64_t v) : type('L'), data(8)
+{
+ uint8_t* d = data.data();
+ (reinterpret_cast<int64_t*>(d))[0] = v;
+}
+
+
+// constructors for array-type properties
+
+FBX::Property::Property(const char* c, bool raw)
+ : Property(std::string(c), raw)
+{}
+
+// strings can either be saved as "raw" (R) data, or "string" (S) data
+FBX::Property::Property(const std::string& s, bool raw)
+ : type(raw ? 'R' : 'S'), data(s.size())
+{
+ for (size_t i = 0; i < s.size(); ++i) {
+ data[i] = uint8_t(s[i]);
+ }
+}
+
+FBX::Property::Property(const std::vector<uint8_t>& r)
+ : type('R'), data(r)
+{}
+
+FBX::Property::Property(const std::vector<int32_t>& va)
+ : type('i'), data(4*va.size())
+{
+ int32_t* d = reinterpret_cast<int32_t*>(data.data());
+ for (size_t i = 0; i < va.size(); ++i) { d[i] = va[i]; }
+}
+
+FBX::Property::Property(const std::vector<int64_t>& va)
+ : type('l'), data(8*va.size())
+{
+ int64_t* d = reinterpret_cast<int64_t*>(data.data());
+ for (size_t i = 0; i < va.size(); ++i) { d[i] = va[i]; }
+}
+
+FBX::Property::Property(const std::vector<float>& va)
+ : type('f'), data(4*va.size())
+{
+ float* d = reinterpret_cast<float*>(data.data());
+ for (size_t i = 0; i < va.size(); ++i) { d[i] = va[i]; }
+}
+
+FBX::Property::Property(const std::vector<double>& va)
+ : type('d'), data(8*va.size())
+{
+ double* d = reinterpret_cast<double*>(data.data());
+ for (size_t i = 0; i < va.size(); ++i) { d[i] = va[i]; }
+}
+
+FBX::Property::Property(const aiMatrix4x4& vm)
+ : type('d'), data(8*16)
+{
+ double* d = reinterpret_cast<double*>(data.data());
+ for (unsigned int c = 0; c < 4; ++c) {
+ for (unsigned int r = 0; r < 4; ++r) {
+ d[4*c+r] = vm[r][c];
+ }
+ }
+}
+
+// public member functions
+
+size_t FBX::Property::size()
+{
+ switch (type) {
+ case 'C': case 'Y': case 'I': case 'F': case 'D': case 'L':
+ return data.size() + 1;
+ case 'S': case 'R':
+ return data.size() + 5;
+ case 'i': case 'd':
+ return data.size() + 13;
+ default:
+ throw DeadlyExportError("Requested size on property of unknown type");
+ }
+}
+
+void FBX::Property::DumpBinary(Assimp::StreamWriterLE &s)
+{
+ s.PutU1(type);
+ uint8_t* d = data.data();
+ size_t N;
+ switch (type) {
+ case 'C': s.PutU1(*(reinterpret_cast<uint8_t*>(d))); return;
+ case 'Y': s.PutI2(*(reinterpret_cast<int16_t*>(d))); return;
+ case 'I': s.PutI4(*(reinterpret_cast<int32_t*>(d))); return;
+ case 'F': s.PutF4(*(reinterpret_cast<float*>(d))); return;
+ case 'D': s.PutF8(*(reinterpret_cast<double*>(d))); return;
+ case 'L': s.PutI8(*(reinterpret_cast<int64_t*>(d))); return;
+ case 'S':
+ case 'R':
+ s.PutU4(uint32_t(data.size()));
+ for (size_t i = 0; i < data.size(); ++i) { s.PutU1(data[i]); }
+ return;
+ case 'i':
+ N = data.size() / 4;
+ s.PutU4(uint32_t(N)); // number of elements
+ s.PutU4(0); // no encoding (1 would be zip-compressed)
+ // TODO: compress if large?
+ s.PutU4(uint32_t(data.size())); // data size
+ for (size_t i = 0; i < N; ++i) {
+ s.PutI4((reinterpret_cast<int32_t*>(d))[i]);
+ }
+ return;
+ case 'l':
+ N = data.size() / 8;
+ s.PutU4(uint32_t(N)); // number of elements
+ s.PutU4(0); // no encoding (1 would be zip-compressed)
+ // TODO: compress if large?
+ s.PutU4(uint32_t(data.size())); // data size
+ for (size_t i = 0; i < N; ++i) {
+ s.PutI8((reinterpret_cast<int64_t*>(d))[i]);
+ }
+ return;
+ case 'f':
+ N = data.size() / 4;
+ s.PutU4(uint32_t(N)); // number of elements
+ s.PutU4(0); // no encoding (1 would be zip-compressed)
+ // TODO: compress if large?
+ s.PutU4(uint32_t(data.size())); // data size
+ for (size_t i = 0; i < N; ++i) {
+ s.PutF4((reinterpret_cast<float*>(d))[i]);
+ }
+ return;
+ case 'd':
+ N = data.size() / 8;
+ s.PutU4(uint32_t(N)); // number of elements
+ s.PutU4(0); // no encoding (1 would be zip-compressed)
+ // TODO: compress if large?
+ s.PutU4(uint32_t(data.size())); // data size
+ for (size_t i = 0; i < N; ++i) {
+ s.PutF8((reinterpret_cast<double*>(d))[i]);
+ }
+ return;
+ default:
+ std::ostringstream err;
+ err << "Tried to dump property with invalid type '";
+ err << type << "'!";
+ throw DeadlyExportError(err.str());
+ }
+}
+
+void FBX::Property::DumpAscii(Assimp::StreamWriterLE &outstream, int indent)
+{
+ std::ostringstream ss;
+ ss.imbue(std::locale::classic());
+ ss.precision(15); // this seems to match official FBX SDK exports
+ DumpAscii(ss, indent);
+ outstream.PutString(ss.str());
+}
+
+void FBX::Property::DumpAscii(std::ostream& s, int indent)
+{
+ // no writing type... or anything. just shove it into the stream.
+ uint8_t* d = data.data();
+ size_t N;
+ size_t swap = data.size();
+ size_t count = 0;
+ switch (type) {
+ case 'C':
+ if (*(reinterpret_cast<uint8_t*>(d))) { s << 'T'; }
+ else { s << 'F'; }
+ return;
+ case 'Y': s << *(reinterpret_cast<int16_t*>(d)); return;
+ case 'I': s << *(reinterpret_cast<int32_t*>(d)); return;
+ case 'F': s << *(reinterpret_cast<float*>(d)); return;
+ case 'D': s << *(reinterpret_cast<double*>(d)); return;
+ case 'L': s << *(reinterpret_cast<int64_t*>(d)); return;
+ case 'S':
+ // first search to see if it has "\x00\x01" in it -
+ // which separates fields which are reversed in the ascii version.
+ // yeah.
+ // FBX, yeah.
+ for (size_t i = 0; i < data.size(); ++i) {
+ if (data[i] == '\0') {
+ swap = i;
+ break;
+ }
+ }
+ case 'R':
+ s << '"';
+ // we might as well check this now,
+ // probably it will never happen
+ for (size_t i = 0; i < data.size(); ++i) {
+ char c = data[i];
+ if (c == '"') {
+ throw runtime_error("can't handle quotes in property string");
+ }
+ }
+ // first write the SWAPPED member (if any)
+ for (size_t i = swap + 2; i < data.size(); ++i) {
+ char c = data[i];
+ s << c;
+ }
+ // then a separator
+ if (swap != data.size()) {
+ s << "::";
+ }
+ // then the initial member
+ for (size_t i = 0; i < swap; ++i) {
+ char c = data[i];
+ s << c;
+ }
+ s << '"';
+ return;
+ case 'i':
+ N = data.size() / 4; // number of elements
+ s << '*' << N << " {\n";
+ for (int i = 0; i < indent + 1; ++i) { s << '\t'; }
+ s << "a: ";
+ for (size_t i = 0; i < N; ++i) {
+ if (i > 0) { s << ','; }
+ if (count++ > 120) { s << '\n'; count = 0; }
+ s << (reinterpret_cast<int32_t*>(d))[i];
+ }
+ s << '\n';
+ for (int i = 0; i < indent; ++i) { s << '\t'; }
+ s << "} ";
+ return;
+ case 'l':
+ N = data.size() / 8;
+ s << '*' << N << " {\n";
+ for (int i = 0; i < indent + 1; ++i) { s << '\t'; }
+ s << "a: ";
+ for (size_t i = 0; i < N; ++i) {
+ if (i > 0) { s << ','; }
+ if (count++ > 120) { s << '\n'; count = 0; }
+ s << (reinterpret_cast<int64_t*>(d))[i];
+ }
+ s << '\n';
+ for (int i = 0; i < indent; ++i) { s << '\t'; }
+ s << "} ";
+ return;
+ case 'f':
+ N = data.size() / 4;
+ s << '*' << N << " {\n";
+ for (int i = 0; i < indent + 1; ++i) { s << '\t'; }
+ s << "a: ";
+ for (size_t i = 0; i < N; ++i) {
+ if (i > 0) { s << ','; }
+ if (count++ > 120) { s << '\n'; count = 0; }
+ s << (reinterpret_cast<float*>(d))[i];
+ }
+ s << '\n';
+ for (int i = 0; i < indent; ++i) { s << '\t'; }
+ s << "} ";
+ return;
+ case 'd':
+ N = data.size() / 8;
+ s << '*' << N << " {\n";
+ for (int i = 0; i < indent + 1; ++i) { s << '\t'; }
+ s << "a: ";
+ // set precision to something that can handle doubles
+ s.precision(15);
+ for (size_t i = 0; i < N; ++i) {
+ if (i > 0) { s << ','; }
+ if (count++ > 120) { s << '\n'; count = 0; }
+ s << (reinterpret_cast<double*>(d))[i];
+ }
+ s << '\n';
+ for (int i = 0; i < indent; ++i) { s << '\t'; }
+ s << "} ";
+ return;
+ default:
+ std::ostringstream err;
+ err << "Tried to dump property with invalid type '";
+ err << type << "'!";
+ throw runtime_error(err.str());
+ }
+}
+
+#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
+#endif // ASSIMP_BUILD_NO_EXPORT
diff --git a/thirdparty/assimp/code/FBXExportProperty.h b/thirdparty/assimp/code/FBXExportProperty.h
new file mode 100644
index 0000000000..9c9d37c362
--- /dev/null
+++ b/thirdparty/assimp/code/FBXExportProperty.h
@@ -0,0 +1,129 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file FBXExportProperty.h
+* Declares the FBX::Property helper class for fbx export.
+*/
+#ifndef AI_FBXEXPORTPROPERTY_H_INC
+#define AI_FBXEXPORTPROPERTY_H_INC
+
+#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
+
+
+#include <assimp/types.h> // aiMatrix4x4
+#include <assimp/StreamWriter.h> // StreamWriterLE
+
+#include <string>
+#include <vector>
+#include <ostream>
+#include <type_traits> // is_void
+
+namespace FBX {
+ class Property;
+}
+
+/** FBX::Property
+ *
+ * Holds a value of any of FBX's recognized types,
+ * each represented by a particular one-character code.
+ * C : 1-byte uint8, usually 0x00 or 0x01 to represent boolean false and true
+ * Y : 2-byte int16
+ * I : 4-byte int32
+ * F : 4-byte float
+ * D : 8-byte double
+ * L : 8-byte int64
+ * i : array of int32
+ * f : array of float
+ * d : array of double
+ * l : array of int64
+ * b : array of 1-byte booleans (0x00 or 0x01)
+ * S : string (array of 1-byte char)
+ * R : raw data (array of bytes)
+ */
+class FBX::Property
+{
+public:
+ // constructors for basic types.
+ // all explicit to avoid accidental typecasting
+ explicit Property(bool v);
+ // TODO: determine if there is actually a byte type,
+ // or if this always means <bool>. 'C' seems to imply <char>,
+ // so possibly the above was intended to represent both.
+ explicit Property(int16_t v);
+ explicit Property(int32_t v);
+ explicit Property(float v);
+ explicit Property(double v);
+ explicit Property(int64_t v);
+ // strings can either be stored as 'R' (raw) or 'S' (string) type
+ explicit Property(const char* c, bool raw=false);
+ explicit Property(const std::string& s, bool raw=false);
+ explicit Property(const std::vector<uint8_t>& r);
+ explicit Property(const std::vector<int32_t>& va);
+ explicit Property(const std::vector<int64_t>& va);
+ explicit Property(const std::vector<double>& va);
+ explicit Property(const std::vector<float>& va);
+ explicit Property(const aiMatrix4x4& vm);
+
+ // this will catch any type not defined above,
+ // so that we don't accidentally convert something we don't want.
+ // for example (const char*) --> (bool)... seriously wtf C++
+ template <class T>
+ explicit Property(T v) : type('X') {
+ static_assert(std::is_void<T>::value, "TRIED TO CREATE FBX PROPERTY WITH UNSUPPORTED TYPE, CHECK YOUR PROPERTY INSTANTIATION");
+ } // note: no line wrap so it appears verbatim on the compiler error
+
+ // the size of this property node in a binary file, in bytes
+ size_t size();
+
+ // write this property node as binary data to the given stream
+ void DumpBinary(Assimp::StreamWriterLE &s);
+ void DumpAscii(Assimp::StreamWriterLE &s, int indent=0);
+ void DumpAscii(std::ostream &s, int indent=0);
+ // note: make sure the ostream is in classic "C" locale
+
+private:
+ char type;
+ std::vector<uint8_t> data;
+};
+
+#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
+
+#endif // AI_FBXEXPORTPROPERTY_H_INC
diff --git a/thirdparty/assimp/code/FBXExporter.cpp b/thirdparty/assimp/code/FBXExporter.cpp
new file mode 100644
index 0000000000..acb1227144
--- /dev/null
+++ b/thirdparty/assimp/code/FBXExporter.cpp
@@ -0,0 +1,2480 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+#ifndef ASSIMP_BUILD_NO_EXPORT
+#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
+
+#include "FBXExporter.h"
+#include "FBXExportNode.h"
+#include "FBXExportProperty.h"
+#include "FBXCommon.h"
+
+#include <assimp/version.h> // aiGetVersion
+#include <assimp/IOSystem.hpp>
+#include <assimp/Exporter.hpp>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/StreamWriter.h> // StreamWriterLE
+#include <assimp/Exceptional.h> // DeadlyExportError
+#include <assimp/material.h> // aiTextureType
+#include <assimp/scene.h>
+#include <assimp/mesh.h>
+
+// Header files, standard library.
+#include <memory> // shared_ptr
+#include <string>
+#include <sstream> // stringstream
+#include <ctime> // localtime, tm_*
+#include <map>
+#include <set>
+#include <vector>
+#include <array>
+#include <unordered_set>
+
+// RESOURCES:
+// https://code.blender.org/2013/08/fbx-binary-file-format-specification/
+// https://wiki.blender.org/index.php/User:Mont29/Foundation/FBX_File_Structure
+
+const ai_real DEG = ai_real( 57.29577951308232087679815481 ); // degrees per radian
+
+// some constants that we'll use for writing metadata
+namespace FBX {
+ const std::string EXPORT_VERSION_STR = "7.4.0";
+ const uint32_t EXPORT_VERSION_INT = 7400; // 7.4 == 2014/2015
+ // FBX files have some hashed values that depend on the creation time field,
+ // but for now we don't actually know how to generate these.
+ // what we can do is set them to a known-working version.
+ // this is the data that Blender uses in their FBX export process.
+ const std::string GENERIC_CTIME = "1970-01-01 10:00:00:000";
+ const std::string GENERIC_FILEID =
+ "\x28\xb3\x2a\xeb\xb6\x24\xcc\xc2\xbf\xc8\xb0\x2a\xa9\x2b\xfc\xf1";
+ const std::string GENERIC_FOOTID =
+ "\xfa\xbc\xab\x09\xd0\xc8\xd4\x66\xb1\x76\xfb\x83\x1c\xf7\x26\x7e";
+ const std::string FOOT_MAGIC =
+ "\xf8\x5a\x8c\x6a\xde\xf5\xd9\x7e\xec\xe9\x0c\xe3\x75\x8f\x29\x0b";
+ const std::string COMMENT_UNDERLINE =
+ ";------------------------------------------------------------------";
+}
+
+using namespace Assimp;
+using namespace FBX;
+
+namespace Assimp {
+
+ // ---------------------------------------------------------------------
+ // Worker function for exporting a scene to binary FBX.
+ // Prototyped and registered in Exporter.cpp
+ void ExportSceneFBX (
+ const char* pFile,
+ IOSystem* pIOSystem,
+ const aiScene* pScene,
+ const ExportProperties* pProperties
+ ){
+ // initialize the exporter
+ FBXExporter exporter(pScene, pProperties);
+
+ // perform binary export
+ exporter.ExportBinary(pFile, pIOSystem);
+ }
+
+ // ---------------------------------------------------------------------
+ // Worker function for exporting a scene to ASCII FBX.
+ // Prototyped and registered in Exporter.cpp
+ void ExportSceneFBXA (
+ const char* pFile,
+ IOSystem* pIOSystem,
+ const aiScene* pScene,
+ const ExportProperties* pProperties
+ ){
+ // initialize the exporter
+ FBXExporter exporter(pScene, pProperties);
+
+ // perform ascii export
+ exporter.ExportAscii(pFile, pIOSystem);
+ }
+
+} // end of namespace Assimp
+
+FBXExporter::FBXExporter ( const aiScene* pScene, const ExportProperties* pProperties )
+: binary(false)
+, mScene(pScene)
+, mProperties(pProperties)
+, outfile()
+, connections()
+, mesh_uids()
+, material_uids()
+, node_uids() {
+ // will probably need to determine UIDs, connections, etc here.
+ // basically anything that needs to be known
+ // before we start writing sections to the stream.
+}
+
+void FBXExporter::ExportBinary (
+ const char* pFile,
+ IOSystem* pIOSystem
+){
+ // remember that we're exporting in binary mode
+ binary = true;
+
+ // we're not currently using these preferences,
+ // but clang will cry about it if we never touch it.
+ // TODO: some of these might be relevant to export
+ (void)mProperties;
+
+ // open the indicated file for writing (in binary mode)
+ outfile.reset(pIOSystem->Open(pFile,"wb"));
+ if (!outfile) {
+ throw DeadlyExportError(
+ "could not open output .fbx file: " + std::string(pFile)
+ );
+ }
+
+ // first a binary-specific file header
+ WriteBinaryHeader();
+
+ // the rest of the file is in node entries.
+ // we have to serialize each entry before we write to the output,
+ // as the first thing we write is the byte offset of the _next_ entry.
+ // Either that or we can skip back to write the offset when we finish.
+ WriteAllNodes();
+
+ // finally we have a binary footer to the file
+ WriteBinaryFooter();
+
+ // explicitly release file pointer,
+ // so we don't have to rely on class destruction.
+ outfile.reset();
+}
+
+void FBXExporter::ExportAscii (
+ const char* pFile,
+ IOSystem* pIOSystem
+){
+ // remember that we're exporting in ascii mode
+ binary = false;
+
+ // open the indicated file for writing in text mode
+ outfile.reset(pIOSystem->Open(pFile,"wt"));
+ if (!outfile) {
+ throw DeadlyExportError(
+ "could not open output .fbx file: " + std::string(pFile)
+ );
+ }
+
+ // write the ascii header
+ WriteAsciiHeader();
+
+ // write all the sections
+ WriteAllNodes();
+
+ // make sure the file ends with a newline.
+ // note: if the file is opened in text mode,
+ // this should do the right cross-platform thing.
+ outfile->Write("\n", 1, 1);
+
+ // explicitly release file pointer,
+ // so we don't have to rely on class destruction.
+ outfile.reset();
+}
+
+void FBXExporter::WriteAsciiHeader()
+{
+ // basically just a comment at the top of the file
+ std::stringstream head;
+ head << "; FBX " << EXPORT_VERSION_STR << " project file\n";
+ head << "; Created by the Open Asset Import Library (Assimp)\n";
+ head << "; http://assimp.org\n";
+ head << "; -------------------------------------------------\n";
+ const std::string ascii_header = head.str();
+ outfile->Write(ascii_header.c_str(), ascii_header.size(), 1);
+}
+
+void FBXExporter::WriteAsciiSectionHeader(const std::string& title)
+{
+ StreamWriterLE outstream(outfile);
+ std::stringstream s;
+ s << "\n\n; " << title << '\n';
+ s << FBX::COMMENT_UNDERLINE << "\n";
+ outstream.PutString(s.str());
+}
+
+void FBXExporter::WriteBinaryHeader()
+{
+ // first a specific sequence of 23 bytes, always the same
+ const char binary_header[24] = "Kaydara FBX Binary\x20\x20\x00\x1a\x00";
+ outfile->Write(binary_header, 1, 23);
+
+ // then FBX version number, "multiplied" by 1000, as little-endian uint32.
+ // so 7.3 becomes 7300 == 0x841C0000, 7.4 becomes 7400 == 0xE81C0000, etc
+ {
+ StreamWriterLE outstream(outfile);
+ outstream.PutU4(EXPORT_VERSION_INT);
+ } // StreamWriter destructor writes the data to the file
+
+ // after this the node data starts immediately
+ // (probably with the FBXHEaderExtension node)
+}
+
+void FBXExporter::WriteBinaryFooter()
+{
+ outfile->Write(NULL_RECORD.c_str(), NULL_RECORD.size(), 1);
+
+ outfile->Write(GENERIC_FOOTID.c_str(), GENERIC_FOOTID.size(), 1);
+
+ // here some padding is added for alignment to 16 bytes.
+ // if already aligned, the full 16 bytes is added.
+ size_t pos = outfile->Tell();
+ size_t pad = 16 - (pos % 16);
+ for (size_t i = 0; i < pad; ++i) {
+ outfile->Write("\x00", 1, 1);
+ }
+
+ // not sure what this is, but it seems to always be 0 in modern files
+ for (size_t i = 0; i < 4; ++i) {
+ outfile->Write("\x00", 1, 1);
+ }
+
+ // now the file version again
+ {
+ StreamWriterLE outstream(outfile);
+ outstream.PutU4(EXPORT_VERSION_INT);
+ } // StreamWriter destructor writes the data to the file
+
+ // and finally some binary footer added to all files
+ for (size_t i = 0; i < 120; ++i) {
+ outfile->Write("\x00", 1, 1);
+ }
+ outfile->Write(FOOT_MAGIC.c_str(), FOOT_MAGIC.size(), 1);
+}
+
+void FBXExporter::WriteAllNodes ()
+{
+ // header
+ // (and fileid, creation time, creator, if binary)
+ WriteHeaderExtension();
+
+ // global settings
+ WriteGlobalSettings();
+
+ // documents
+ WriteDocuments();
+
+ // references
+ WriteReferences();
+
+ // definitions
+ WriteDefinitions();
+
+ // objects
+ WriteObjects();
+
+ // connections
+ WriteConnections();
+
+ // WriteTakes? (deprecated since at least 2015 (fbx 7.4))
+}
+
+//FBXHeaderExtension top-level node
+void FBXExporter::WriteHeaderExtension ()
+{
+ if (!binary) {
+ // no title, follows directly from the top comment
+ }
+ FBX::Node n("FBXHeaderExtension");
+ StreamWriterLE outstream(outfile);
+ int indent = 0;
+
+ // begin node
+ n.Begin(outstream, binary, indent);
+
+ // write properties
+ // (none)
+
+ // finish properties
+ n.EndProperties(outstream, binary, indent, 0);
+
+ // begin children
+ n.BeginChildren(outstream, binary, indent);
+
+ indent = 1;
+
+ // write child nodes
+ FBX::Node::WritePropertyNode(
+ "FBXHeaderVersion", int32_t(1003), outstream, binary, indent
+ );
+ FBX::Node::WritePropertyNode(
+ "FBXVersion", int32_t(EXPORT_VERSION_INT), outstream, binary, indent
+ );
+ if (binary) {
+ FBX::Node::WritePropertyNode(
+ "EncryptionType", int32_t(0), outstream, binary, indent
+ );
+ }
+
+ FBX::Node CreationTimeStamp("CreationTimeStamp");
+ time_t rawtime;
+ time(&rawtime);
+ struct tm * now = localtime(&rawtime);
+ CreationTimeStamp.AddChild("Version", int32_t(1000));
+ CreationTimeStamp.AddChild("Year", int32_t(now->tm_year + 1900));
+ CreationTimeStamp.AddChild("Month", int32_t(now->tm_mon + 1));
+ CreationTimeStamp.AddChild("Day", int32_t(now->tm_mday));
+ CreationTimeStamp.AddChild("Hour", int32_t(now->tm_hour));
+ CreationTimeStamp.AddChild("Minute", int32_t(now->tm_min));
+ CreationTimeStamp.AddChild("Second", int32_t(now->tm_sec));
+ CreationTimeStamp.AddChild("Millisecond", int32_t(0));
+ CreationTimeStamp.Dump(outstream, binary, indent);
+
+ std::stringstream creator;
+ creator << "Open Asset Import Library (Assimp) " << aiGetVersionMajor()
+ << "." << aiGetVersionMinor() << "." << aiGetVersionRevision();
+ FBX::Node::WritePropertyNode(
+ "Creator", creator.str(), outstream, binary, indent
+ );
+
+ //FBX::Node sceneinfo("SceneInfo");
+ //sceneinfo.AddProperty("GlobalInfo" + FBX::SEPARATOR + "SceneInfo");
+ // not sure if any of this is actually needed,
+ // so just write an empty node for now.
+ //sceneinfo.Dump(outstream, binary, indent);
+
+ indent = 0;
+
+ // finish node
+ n.End(outstream, binary, indent, true);
+
+ // that's it for FBXHeaderExtension...
+ if (!binary) { return; }
+
+ // but binary files also need top-level FileID, CreationTime, Creator:
+ std::vector<uint8_t> raw(GENERIC_FILEID.size());
+ for (size_t i = 0; i < GENERIC_FILEID.size(); ++i) {
+ raw[i] = uint8_t(GENERIC_FILEID[i]);
+ }
+ FBX::Node::WritePropertyNode(
+ "FileId", raw, outstream, binary, indent
+ );
+ FBX::Node::WritePropertyNode(
+ "CreationTime", GENERIC_CTIME, outstream, binary, indent
+ );
+ FBX::Node::WritePropertyNode(
+ "Creator", creator.str(), outstream, binary, indent
+ );
+}
+
+void FBXExporter::WriteGlobalSettings ()
+{
+ if (!binary) {
+ // no title, follows directly from the header extension
+ }
+ FBX::Node gs("GlobalSettings");
+ gs.AddChild("Version", int32_t(1000));
+
+ FBX::Node p("Properties70");
+ p.AddP70int("UpAxis", 1);
+ p.AddP70int("UpAxisSign", 1);
+ p.AddP70int("FrontAxis", 2);
+ p.AddP70int("FrontAxisSign", 1);
+ p.AddP70int("CoordAxis", 0);
+ p.AddP70int("CoordAxisSign", 1);
+ p.AddP70int("OriginalUpAxis", 1);
+ p.AddP70int("OriginalUpAxisSign", 1);
+ p.AddP70double("UnitScaleFactor", 1.0);
+ p.AddP70double("OriginalUnitScaleFactor", 1.0);
+ p.AddP70color("AmbientColor", 0.0, 0.0, 0.0);
+ p.AddP70string("DefaultCamera", "Producer Perspective");
+ p.AddP70enum("TimeMode", 11);
+ p.AddP70enum("TimeProtocol", 2);
+ p.AddP70enum("SnapOnFrameMode", 0);
+ p.AddP70time("TimeSpanStart", 0); // TODO: animation support
+ p.AddP70time("TimeSpanStop", FBX::SECOND); // TODO: animation support
+ p.AddP70double("CustomFrameRate", -1.0);
+ p.AddP70("TimeMarker", "Compound", "", ""); // not sure what this is
+ p.AddP70int("CurrentTimeMarker", -1);
+ gs.AddChild(p);
+
+ gs.Dump(outfile, binary, 0);
+}
+
+void FBXExporter::WriteDocuments ()
+{
+ if (!binary) {
+ WriteAsciiSectionHeader("Documents Description");
+ }
+
+ // not sure what the use of multiple documents would be,
+ // or whether any end-application supports it
+ FBX::Node docs("Documents");
+ docs.AddChild("Count", int32_t(1));
+ FBX::Node doc("Document");
+
+ // generate uid
+ int64_t uid = generate_uid();
+ doc.AddProperties(uid, "", "Scene");
+ FBX::Node p("Properties70");
+ p.AddP70("SourceObject", "object", "", ""); // what is this even for?
+ p.AddP70string("ActiveAnimStackName", ""); // should do this properly?
+ doc.AddChild(p);
+
+ // UID for root node in scene hierarchy.
+ // always set to 0 in the case of a single document.
+ // not sure what happens if more than one document exists,
+ // but that won't matter to us as we're exporting a single scene.
+ doc.AddChild("RootNode", int64_t(0));
+
+ docs.AddChild(doc);
+ docs.Dump(outfile, binary, 0);
+}
+
+void FBXExporter::WriteReferences ()
+{
+ if (!binary) {
+ WriteAsciiSectionHeader("Document References");
+ }
+ // always empty for now.
+ // not really sure what this is for.
+ FBX::Node n("References");
+ n.force_has_children = true;
+ n.Dump(outfile, binary, 0);
+}
+
+
+// ---------------------------------------------------------------
+// some internal helper functions used for writing the definitions
+// (before any actual data is written)
+// ---------------------------------------------------------------
+
+size_t count_nodes(const aiNode* n) {
+ size_t count = 1;
+ for (size_t i = 0; i < n->mNumChildren; ++i) {
+ count += count_nodes(n->mChildren[i]);
+ }
+ return count;
+}
+
+bool has_phong_mat(const aiScene* scene)
+{
+ // just search for any material with a shininess exponent
+ for (size_t i = 0; i < scene->mNumMaterials; ++i) {
+ aiMaterial* mat = scene->mMaterials[i];
+ float shininess = 0;
+ mat->Get(AI_MATKEY_SHININESS, shininess);
+ if (shininess > 0) {
+ return true;
+ }
+ }
+ return false;
+}
+
+size_t count_images(const aiScene* scene) {
+ std::unordered_set<std::string> images;
+ aiString texpath;
+ for (size_t i = 0; i < scene->mNumMaterials; ++i) {
+ aiMaterial* mat = scene->mMaterials[i];
+ for (
+ size_t tt = aiTextureType_DIFFUSE;
+ tt < aiTextureType_UNKNOWN;
+ ++tt
+ ){
+ const aiTextureType textype = static_cast<aiTextureType>(tt);
+ const size_t texcount = mat->GetTextureCount(textype);
+ for (unsigned int j = 0; j < texcount; ++j) {
+ mat->GetTexture(textype, j, &texpath);
+ images.insert(std::string(texpath.C_Str()));
+ }
+ }
+ }
+ return images.size();
+}
+
+size_t count_textures(const aiScene* scene) {
+ size_t count = 0;
+ for (size_t i = 0; i < scene->mNumMaterials; ++i) {
+ aiMaterial* mat = scene->mMaterials[i];
+ for (
+ size_t tt = aiTextureType_DIFFUSE;
+ tt < aiTextureType_UNKNOWN;
+ ++tt
+ ){
+ // TODO: handle layered textures
+ if (mat->GetTextureCount(static_cast<aiTextureType>(tt)) > 0) {
+ count += 1;
+ }
+ }
+ }
+ return count;
+}
+
+size_t count_deformers(const aiScene* scene) {
+ size_t count = 0;
+ for (size_t i = 0; i < scene->mNumMeshes; ++i) {
+ const size_t n = scene->mMeshes[i]->mNumBones;
+ if (n) {
+ // 1 main deformer, 1 subdeformer per bone
+ count += n + 1;
+ }
+ }
+ return count;
+}
+
+void FBXExporter::WriteDefinitions ()
+{
+ // basically this is just bookkeeping:
+ // determining how many of each type of object there are
+ // and specifying the base properties to use when otherwise unspecified.
+
+ // ascii section header
+ if (!binary) {
+ WriteAsciiSectionHeader("Object definitions");
+ }
+
+ // we need to count the objects
+ int32_t count;
+ int32_t total_count = 0;
+
+ // and store them
+ std::vector<FBX::Node> object_nodes;
+ FBX::Node n, pt, p;
+
+ // GlobalSettings
+ // this seems to always be here in Maya exports
+ n = FBX::Node("ObjectType", "GlobalSettings");
+ count = 1;
+ n.AddChild("Count", count);
+ object_nodes.push_back(n);
+ total_count += count;
+
+ // AnimationStack / FbxAnimStack
+ // this seems to always be here in Maya exports,
+ // but no harm seems to come of leaving it out.
+ count = mScene->mNumAnimations;
+ if (count) {
+ n = FBX::Node("ObjectType", "AnimationStack");
+ n.AddChild("Count", count);
+ pt = FBX::Node("PropertyTemplate", "FbxAnimStack");
+ p = FBX::Node("Properties70");
+ p.AddP70string("Description", "");
+ p.AddP70time("LocalStart", 0);
+ p.AddP70time("LocalStop", 0);
+ p.AddP70time("ReferenceStart", 0);
+ p.AddP70time("ReferenceStop", 0);
+ pt.AddChild(p);
+ n.AddChild(pt);
+ object_nodes.push_back(n);
+ total_count += count;
+ }
+
+ // AnimationLayer / FbxAnimLayer
+ // this seems to always be here in Maya exports,
+ // but no harm seems to come of leaving it out.
+ // Assimp doesn't support animation layers,
+ // so there will be one per aiAnimation
+ count = mScene->mNumAnimations;
+ if (count) {
+ n = FBX::Node("ObjectType", "AnimationLayer");
+ n.AddChild("Count", count);
+ pt = FBX::Node("PropertyTemplate", "FBXAnimLayer");
+ p = FBX::Node("Properties70");
+ p.AddP70("Weight", "Number", "", "A", double(100));
+ p.AddP70bool("Mute", 0);
+ p.AddP70bool("Solo", 0);
+ p.AddP70bool("Lock", 0);
+ p.AddP70color("Color", 0.8, 0.8, 0.8);
+ p.AddP70("BlendMode", "enum", "", "", int32_t(0));
+ p.AddP70("RotationAccumulationMode", "enum", "", "", int32_t(0));
+ p.AddP70("ScaleAccumulationMode", "enum", "", "", int32_t(0));
+ p.AddP70("BlendModeBypass", "ULongLong", "", "", int64_t(0));
+ pt.AddChild(p);
+ n.AddChild(pt);
+ object_nodes.push_back(n);
+ total_count += count;
+ }
+
+ // NodeAttribute
+ // this is completely absurd.
+ // there can only be one "NodeAttribute" template,
+ // but FbxSkeleton, FbxCamera, FbxLight all are "NodeAttributes".
+ // so if only one exists we should set the template for that,
+ // otherwise... we just pick one :/.
+ // the others have to set all their properties every instance,
+ // because there's no template.
+ count = 1; // TODO: select properly
+ if (count) {
+ // FbxSkeleton
+ n = FBX::Node("ObjectType", "NodeAttribute");
+ n.AddChild("Count", count);
+ pt = FBX::Node("PropertyTemplate", "FbxSkeleton");
+ p = FBX::Node("Properties70");
+ p.AddP70color("Color", 0.8, 0.8, 0.8);
+ p.AddP70double("Size", 33.333333333333);
+ p.AddP70("LimbLength", "double", "Number", "H", double(1));
+ // note: not sure what the "H" flag is for - hidden?
+ pt.AddChild(p);
+ n.AddChild(pt);
+ object_nodes.push_back(n);
+ total_count += count;
+ }
+
+ // Model / FbxNode
+ // <~~ node hierarchy
+ count = int32_t(count_nodes(mScene->mRootNode)) - 1; // (not counting root node)
+ if (count) {
+ n = FBX::Node("ObjectType", "Model");
+ n.AddChild("Count", count);
+ pt = FBX::Node("PropertyTemplate", "FbxNode");
+ p = FBX::Node("Properties70");
+ p.AddP70enum("QuaternionInterpolate", 0);
+ p.AddP70vector("RotationOffset", 0.0, 0.0, 0.0);
+ p.AddP70vector("RotationPivot", 0.0, 0.0, 0.0);
+ p.AddP70vector("ScalingOffset", 0.0, 0.0, 0.0);
+ p.AddP70vector("ScalingPivot", 0.0, 0.0, 0.0);
+ p.AddP70bool("TranslationActive", 0);
+ p.AddP70vector("TranslationMin", 0.0, 0.0, 0.0);
+ p.AddP70vector("TranslationMax", 0.0, 0.0, 0.0);
+ p.AddP70bool("TranslationMinX", 0);
+ p.AddP70bool("TranslationMinY", 0);
+ p.AddP70bool("TranslationMinZ", 0);
+ p.AddP70bool("TranslationMaxX", 0);
+ p.AddP70bool("TranslationMaxY", 0);
+ p.AddP70bool("TranslationMaxZ", 0);
+ p.AddP70enum("RotationOrder", 0);
+ p.AddP70bool("RotationSpaceForLimitOnly", 0);
+ p.AddP70double("RotationStiffnessX", 0.0);
+ p.AddP70double("RotationStiffnessY", 0.0);
+ p.AddP70double("RotationStiffnessZ", 0.0);
+ p.AddP70double("AxisLen", 10.0);
+ p.AddP70vector("PreRotation", 0.0, 0.0, 0.0);
+ p.AddP70vector("PostRotation", 0.0, 0.0, 0.0);
+ p.AddP70bool("RotationActive", 0);
+ p.AddP70vector("RotationMin", 0.0, 0.0, 0.0);
+ p.AddP70vector("RotationMax", 0.0, 0.0, 0.0);
+ p.AddP70bool("RotationMinX", 0);
+ p.AddP70bool("RotationMinY", 0);
+ p.AddP70bool("RotationMinZ", 0);
+ p.AddP70bool("RotationMaxX", 0);
+ p.AddP70bool("RotationMaxY", 0);
+ p.AddP70bool("RotationMaxZ", 0);
+ p.AddP70enum("InheritType", 0);
+ p.AddP70bool("ScalingActive", 0);
+ p.AddP70vector("ScalingMin", 0.0, 0.0, 0.0);
+ p.AddP70vector("ScalingMax", 1.0, 1.0, 1.0);
+ p.AddP70bool("ScalingMinX", 0);
+ p.AddP70bool("ScalingMinY", 0);
+ p.AddP70bool("ScalingMinZ", 0);
+ p.AddP70bool("ScalingMaxX", 0);
+ p.AddP70bool("ScalingMaxY", 0);
+ p.AddP70bool("ScalingMaxZ", 0);
+ p.AddP70vector("GeometricTranslation", 0.0, 0.0, 0.0);
+ p.AddP70vector("GeometricRotation", 0.0, 0.0, 0.0);
+ p.AddP70vector("GeometricScaling", 1.0, 1.0, 1.0);
+ p.AddP70double("MinDampRangeX", 0.0);
+ p.AddP70double("MinDampRangeY", 0.0);
+ p.AddP70double("MinDampRangeZ", 0.0);
+ p.AddP70double("MaxDampRangeX", 0.0);
+ p.AddP70double("MaxDampRangeY", 0.0);
+ p.AddP70double("MaxDampRangeZ", 0.0);
+ p.AddP70double("MinDampStrengthX", 0.0);
+ p.AddP70double("MinDampStrengthY", 0.0);
+ p.AddP70double("MinDampStrengthZ", 0.0);
+ p.AddP70double("MaxDampStrengthX", 0.0);
+ p.AddP70double("MaxDampStrengthY", 0.0);
+ p.AddP70double("MaxDampStrengthZ", 0.0);
+ p.AddP70double("PreferedAngleX", 0.0);
+ p.AddP70double("PreferedAngleY", 0.0);
+ p.AddP70double("PreferedAngleZ", 0.0);
+ p.AddP70("LookAtProperty", "object", "", "");
+ p.AddP70("UpVectorProperty", "object", "", "");
+ p.AddP70bool("Show", 1);
+ p.AddP70bool("NegativePercentShapeSupport", 1);
+ p.AddP70int("DefaultAttributeIndex", -1);
+ p.AddP70bool("Freeze", 0);
+ p.AddP70bool("LODBox", 0);
+ p.AddP70(
+ "Lcl Translation", "Lcl Translation", "", "A",
+ double(0), double(0), double(0)
+ );
+ p.AddP70(
+ "Lcl Rotation", "Lcl Rotation", "", "A",
+ double(0), double(0), double(0)
+ );
+ p.AddP70(
+ "Lcl Scaling", "Lcl Scaling", "", "A",
+ double(1), double(1), double(1)
+ );
+ p.AddP70("Visibility", "Visibility", "", "A", double(1));
+ p.AddP70(
+ "Visibility Inheritance", "Visibility Inheritance", "", "",
+ int32_t(1)
+ );
+ pt.AddChild(p);
+ n.AddChild(pt);
+ object_nodes.push_back(n);
+ total_count += count;
+ }
+
+ // Geometry / FbxMesh
+ // <~~ aiMesh
+ count = mScene->mNumMeshes;
+ if (count) {
+ n = FBX::Node("ObjectType", "Geometry");
+ n.AddChild("Count", count);
+ pt = FBX::Node("PropertyTemplate", "FbxMesh");
+ p = FBX::Node("Properties70");
+ p.AddP70color("Color", 0, 0, 0);
+ p.AddP70vector("BBoxMin", 0, 0, 0);
+ p.AddP70vector("BBoxMax", 0, 0, 0);
+ p.AddP70bool("Primary Visibility", 1);
+ p.AddP70bool("Casts Shadows", 1);
+ p.AddP70bool("Receive Shadows", 1);
+ pt.AddChild(p);
+ n.AddChild(pt);
+ object_nodes.push_back(n);
+ total_count += count;
+ }
+
+ // Material / FbxSurfacePhong, FbxSurfaceLambert, FbxSurfaceMaterial
+ // <~~ aiMaterial
+ // basically if there's any phong material this is defined as phong,
+ // and otherwise lambert.
+ // More complex materials cause a bare-bones FbxSurfaceMaterial definition
+ // and are treated specially, as they're not really supported by FBX.
+ // TODO: support Maya's Stingray PBS material
+ count = mScene->mNumMaterials;
+ if (count) {
+ bool has_phong = has_phong_mat(mScene);
+ n = FBX::Node("ObjectType", "Material");
+ n.AddChild("Count", count);
+ pt = FBX::Node("PropertyTemplate");
+ if (has_phong) {
+ pt.AddProperty("FbxSurfacePhong");
+ } else {
+ pt.AddProperty("FbxSurfaceLambert");
+ }
+ p = FBX::Node("Properties70");
+ if (has_phong) {
+ p.AddP70string("ShadingModel", "Phong");
+ } else {
+ p.AddP70string("ShadingModel", "Lambert");
+ }
+ p.AddP70bool("MultiLayer", 0);
+ p.AddP70colorA("EmissiveColor", 0.0, 0.0, 0.0);
+ p.AddP70numberA("EmissiveFactor", 1.0);
+ p.AddP70colorA("AmbientColor", 0.2, 0.2, 0.2);
+ p.AddP70numberA("AmbientFactor", 1.0);
+ p.AddP70colorA("DiffuseColor", 0.8, 0.8, 0.8);
+ p.AddP70numberA("DiffuseFactor", 1.0);
+ p.AddP70vector("Bump", 0.0, 0.0, 0.0);
+ p.AddP70vector("NormalMap", 0.0, 0.0, 0.0);
+ p.AddP70double("BumpFactor", 1.0);
+ p.AddP70colorA("TransparentColor", 0.0, 0.0, 0.0);
+ p.AddP70numberA("TransparencyFactor", 0.0);
+ p.AddP70color("DisplacementColor", 0.0, 0.0, 0.0);
+ p.AddP70double("DisplacementFactor", 1.0);
+ p.AddP70color("VectorDisplacementColor", 0.0, 0.0, 0.0);
+ p.AddP70double("VectorDisplacementFactor", 1.0);
+ if (has_phong) {
+ p.AddP70colorA("SpecularColor", 0.2, 0.2, 0.2);
+ p.AddP70numberA("SpecularFactor", 1.0);
+ p.AddP70numberA("ShininessExponent", 20.0);
+ p.AddP70colorA("ReflectionColor", 0.0, 0.0, 0.0);
+ p.AddP70numberA("ReflectionFactor", 1.0);
+ }
+ pt.AddChild(p);
+ n.AddChild(pt);
+ object_nodes.push_back(n);
+ total_count += count;
+ }
+
+ // Video / FbxVideo
+ // one for each image file.
+ count = int32_t(count_images(mScene));
+ if (count) {
+ n = FBX::Node("ObjectType", "Video");
+ n.AddChild("Count", count);
+ pt = FBX::Node("PropertyTemplate", "FbxVideo");
+ p = FBX::Node("Properties70");
+ p.AddP70bool("ImageSequence", 0);
+ p.AddP70int("ImageSequenceOffset", 0);
+ p.AddP70double("FrameRate", 0.0);
+ p.AddP70int("LastFrame", 0);
+ p.AddP70int("Width", 0);
+ p.AddP70int("Height", 0);
+ p.AddP70("Path", "KString", "XRefUrl", "", "");
+ p.AddP70int("StartFrame", 0);
+ p.AddP70int("StopFrame", 0);
+ p.AddP70double("PlaySpeed", 0.0);
+ p.AddP70time("Offset", 0);
+ p.AddP70enum("InterlaceMode", 0);
+ p.AddP70bool("FreeRunning", 0);
+ p.AddP70bool("Loop", 0);
+ p.AddP70enum("AccessMode", 0);
+ pt.AddChild(p);
+ n.AddChild(pt);
+ object_nodes.push_back(n);
+ total_count += count;
+ }
+
+ // Texture / FbxFileTexture
+ // <~~ aiTexture
+ count = int32_t(count_textures(mScene));
+ if (count) {
+ n = FBX::Node("ObjectType", "Texture");
+ n.AddChild("Count", count);
+ pt = FBX::Node("PropertyTemplate", "FbxFileTexture");
+ p = FBX::Node("Properties70");
+ p.AddP70enum("TextureTypeUse", 0);
+ p.AddP70numberA("Texture alpha", 1.0);
+ p.AddP70enum("CurrentMappingType", 0);
+ p.AddP70enum("WrapModeU", 0);
+ p.AddP70enum("WrapModeV", 0);
+ p.AddP70bool("UVSwap", 0);
+ p.AddP70bool("PremultiplyAlpha", 1);
+ p.AddP70vectorA("Translation", 0.0, 0.0, 0.0);
+ p.AddP70vectorA("Rotation", 0.0, 0.0, 0.0);
+ p.AddP70vectorA("Scaling", 1.0, 1.0, 1.0);
+ p.AddP70vector("TextureRotationPivot", 0.0, 0.0, 0.0);
+ p.AddP70vector("TextureScalingPivot", 0.0, 0.0, 0.0);
+ p.AddP70enum("CurrentTextureBlendMode", 1);
+ p.AddP70string("UVSet", "default");
+ p.AddP70bool("UseMaterial", 0);
+ p.AddP70bool("UseMipMap", 0);
+ pt.AddChild(p);
+ n.AddChild(pt);
+ object_nodes.push_back(n);
+ total_count += count;
+ }
+
+ // AnimationCurveNode / FbxAnimCurveNode
+ count = mScene->mNumAnimations * 3;
+ if (count) {
+ n = FBX::Node("ObjectType", "AnimationCurveNode");
+ n.AddChild("Count", count);
+ pt = FBX::Node("PropertyTemplate", "FbxAnimCurveNode");
+ p = FBX::Node("Properties70");
+ p.AddP70("d", "Compound", "", "");
+ pt.AddChild(p);
+ n.AddChild(pt);
+ object_nodes.push_back(n);
+ total_count += count;
+ }
+
+ // AnimationCurve / FbxAnimCurve
+ count = mScene->mNumAnimations * 9;
+ if (count) {
+ n = FBX::Node("ObjectType", "AnimationCurve");
+ n.AddChild("Count", count);
+ object_nodes.push_back(n);
+ total_count += count;
+ }
+
+ // Pose
+ count = 0;
+ for (size_t i = 0; i < mScene->mNumMeshes; ++i) {
+ aiMesh* mesh = mScene->mMeshes[i];
+ if (mesh->HasBones()) { ++count; }
+ }
+ if (count) {
+ n = FBX::Node("ObjectType", "Pose");
+ n.AddChild("Count", count);
+ object_nodes.push_back(n);
+ total_count += count;
+ }
+
+ // Deformer
+ count = int32_t(count_deformers(mScene));
+ if (count) {
+ n = FBX::Node("ObjectType", "Deformer");
+ n.AddChild("Count", count);
+ object_nodes.push_back(n);
+ total_count += count;
+ }
+
+ // (template)
+ count = 0;
+ if (count) {
+ n = FBX::Node("ObjectType", "");
+ n.AddChild("Count", count);
+ pt = FBX::Node("PropertyTemplate", "");
+ p = FBX::Node("Properties70");
+ pt.AddChild(p);
+ n.AddChild(pt);
+ object_nodes.push_back(n);
+ total_count += count;
+ }
+
+ // now write it all
+ FBX::Node defs("Definitions");
+ defs.AddChild("Version", int32_t(100));
+ defs.AddChild("Count", int32_t(total_count));
+ for (auto &n : object_nodes) { defs.AddChild(n); }
+ defs.Dump(outfile, binary, 0);
+}
+
+
+// -------------------------------------------------------------------
+// some internal helper functions used for writing the objects section
+// (which holds the actual data)
+// -------------------------------------------------------------------
+
+aiNode* get_node_for_mesh(unsigned int meshIndex, aiNode* node)
+{
+ for (size_t i = 0; i < node->mNumMeshes; ++i) {
+ if (node->mMeshes[i] == meshIndex) {
+ return node;
+ }
+ }
+ for (size_t i = 0; i < node->mNumChildren; ++i) {
+ aiNode* ret = get_node_for_mesh(meshIndex, node->mChildren[i]);
+ if (ret) { return ret; }
+ }
+ return nullptr;
+}
+
+aiMatrix4x4 get_world_transform(const aiNode* node, const aiScene* scene)
+{
+ std::vector<const aiNode*> node_chain;
+ while (node != scene->mRootNode) {
+ node_chain.push_back(node);
+ node = node->mParent;
+ }
+ aiMatrix4x4 transform;
+ for (auto n = node_chain.rbegin(); n != node_chain.rend(); ++n) {
+ transform *= (*n)->mTransformation;
+ }
+ return transform;
+}
+
+int64_t to_ktime(double ticks, const aiAnimation* anim) {
+ if (anim->mTicksPerSecond <= 0) {
+ return static_cast<int64_t>(ticks) * FBX::SECOND;
+ }
+ return (static_cast<int64_t>(ticks) / static_cast<int64_t>(anim->mTicksPerSecond)) * FBX::SECOND;
+}
+
+int64_t to_ktime(double time) {
+ return (static_cast<int64_t>(time * FBX::SECOND));
+}
+
+void FBXExporter::WriteObjects ()
+{
+ if (!binary) {
+ WriteAsciiSectionHeader("Object properties");
+ }
+ // numbers should match those given in definitions! make sure to check
+ StreamWriterLE outstream(outfile);
+ FBX::Node object_node("Objects");
+ int indent = 0;
+ object_node.Begin(outstream, binary, indent);
+ object_node.EndProperties(outstream, binary, indent);
+ object_node.BeginChildren(outstream, binary, indent);
+
+ // geometry (aiMesh)
+ mesh_uids.clear();
+ indent = 1;
+ for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) {
+ // it's all about this mesh
+ aiMesh* m = mScene->mMeshes[mi];
+
+ // start the node record
+ FBX::Node n("Geometry");
+ int64_t uid = generate_uid();
+ mesh_uids.push_back(uid);
+ n.AddProperty(uid);
+ n.AddProperty(FBX::SEPARATOR + "Geometry");
+ n.AddProperty("Mesh");
+ n.Begin(outstream, binary, indent);
+ n.DumpProperties(outstream, binary, indent);
+ n.EndProperties(outstream, binary, indent);
+ n.BeginChildren(outstream, binary, indent);
+ indent = 2;
+
+ // output vertex data - each vertex should be unique (probably)
+ std::vector<double> flattened_vertices;
+ // index of original vertex in vertex data vector
+ std::vector<int32_t> vertex_indices;
+ // map of vertex value to its index in the data vector
+ std::map<aiVector3D,size_t> index_by_vertex_value;
+ int32_t index = 0;
+ for (size_t vi = 0; vi < m->mNumVertices; ++vi) {
+ aiVector3D vtx = m->mVertices[vi];
+ auto elem = index_by_vertex_value.find(vtx);
+ if (elem == index_by_vertex_value.end()) {
+ vertex_indices.push_back(index);
+ index_by_vertex_value[vtx] = index;
+ flattened_vertices.push_back(vtx[0]);
+ flattened_vertices.push_back(vtx[1]);
+ flattened_vertices.push_back(vtx[2]);
+ ++index;
+ } else {
+ vertex_indices.push_back(int32_t(elem->second));
+ }
+ }
+ FBX::Node::WritePropertyNode(
+ "Vertices", flattened_vertices, outstream, binary, indent
+ );
+
+ // output polygon data as a flattened array of vertex indices.
+ // the last vertex index of each polygon is negated and - 1
+ std::vector<int32_t> polygon_data;
+ for (size_t fi = 0; fi < m->mNumFaces; ++fi) {
+ const aiFace &f = m->mFaces[fi];
+ for (size_t pvi = 0; pvi < f.mNumIndices - 1; ++pvi) {
+ polygon_data.push_back(vertex_indices[f.mIndices[pvi]]);
+ }
+ polygon_data.push_back(
+ -1 - vertex_indices[f.mIndices[f.mNumIndices-1]]
+ );
+ }
+ FBX::Node::WritePropertyNode(
+ "PolygonVertexIndex", polygon_data, outstream, binary, indent
+ );
+
+ // here could be edges but they're insane.
+ // it's optional anyway, so let's ignore it.
+
+ FBX::Node::WritePropertyNode(
+ "GeometryVersion", int32_t(124), outstream, binary, indent
+ );
+
+ // normals, if any
+ if (m->HasNormals()) {
+ FBX::Node normals("LayerElementNormal", int32_t(0));
+ normals.Begin(outstream, binary, indent);
+ normals.DumpProperties(outstream, binary, indent);
+ normals.EndProperties(outstream, binary, indent);
+ normals.BeginChildren(outstream, binary, indent);
+ indent = 3;
+ FBX::Node::WritePropertyNode(
+ "Version", int32_t(101), outstream, binary, indent
+ );
+ FBX::Node::WritePropertyNode(
+ "Name", "", outstream, binary, indent
+ );
+ FBX::Node::WritePropertyNode(
+ "MappingInformationType", "ByPolygonVertex",
+ outstream, binary, indent
+ );
+ // TODO: vertex-normals or indexed normals when appropriate
+ FBX::Node::WritePropertyNode(
+ "ReferenceInformationType", "Direct",
+ outstream, binary, indent
+ );
+ std::vector<double> normal_data;
+ normal_data.reserve(3 * polygon_data.size());
+ for (size_t fi = 0; fi < m->mNumFaces; ++fi) {
+ const aiFace &f = m->mFaces[fi];
+ for (size_t pvi = 0; pvi < f.mNumIndices; ++pvi) {
+ const aiVector3D &n = m->mNormals[f.mIndices[pvi]];
+ normal_data.push_back(n.x);
+ normal_data.push_back(n.y);
+ normal_data.push_back(n.z);
+ }
+ }
+ FBX::Node::WritePropertyNode(
+ "Normals", normal_data, outstream, binary, indent
+ );
+ // note: version 102 has a NormalsW also... not sure what it is,
+ // so we can stick with version 101 for now.
+ indent = 2;
+ normals.End(outstream, binary, indent, true);
+ }
+
+ // uvs, if any
+ for (size_t uvi = 0; uvi < m->GetNumUVChannels(); ++uvi) {
+ if (m->mNumUVComponents[uvi] > 2) {
+ // FBX only supports 2-channel UV maps...
+ // or at least i'm not sure how to indicate a different number
+ std::stringstream err;
+ err << "Only 2-channel UV maps supported by FBX,";
+ err << " but mesh " << mi;
+ if (m->mName.length) {
+ err << " (" << m->mName.C_Str() << ")";
+ }
+ err << " UV map " << uvi;
+ err << " has " << m->mNumUVComponents[uvi];
+ err << " components! Data will be preserved,";
+ err << " but may be incorrectly interpreted on load.";
+ ASSIMP_LOG_WARN(err.str());
+ }
+ FBX::Node uv("LayerElementUV", int32_t(uvi));
+ uv.Begin(outstream, binary, indent);
+ uv.DumpProperties(outstream, binary, indent);
+ uv.EndProperties(outstream, binary, indent);
+ uv.BeginChildren(outstream, binary, indent);
+ indent = 3;
+ FBX::Node::WritePropertyNode(
+ "Version", int32_t(101), outstream, binary, indent
+ );
+ // it doesn't seem like assimp keeps the uv map name,
+ // so just leave it blank.
+ FBX::Node::WritePropertyNode(
+ "Name", "", outstream, binary, indent
+ );
+ FBX::Node::WritePropertyNode(
+ "MappingInformationType", "ByPolygonVertex",
+ outstream, binary, indent
+ );
+ FBX::Node::WritePropertyNode(
+ "ReferenceInformationType", "IndexToDirect",
+ outstream, binary, indent
+ );
+
+ std::vector<double> uv_data;
+ std::vector<int32_t> uv_indices;
+ std::map<aiVector3D,int32_t> index_by_uv;
+ int32_t index = 0;
+ for (size_t fi = 0; fi < m->mNumFaces; ++fi) {
+ const aiFace &f = m->mFaces[fi];
+ for (size_t pvi = 0; pvi < f.mNumIndices; ++pvi) {
+ const aiVector3D &uv =
+ m->mTextureCoords[uvi][f.mIndices[pvi]];
+ auto elem = index_by_uv.find(uv);
+ if (elem == index_by_uv.end()) {
+ index_by_uv[uv] = index;
+ uv_indices.push_back(index);
+ for (unsigned int x = 0; x < m->mNumUVComponents[uvi]; ++x) {
+ uv_data.push_back(uv[x]);
+ }
+ ++index;
+ } else {
+ uv_indices.push_back(elem->second);
+ }
+ }
+ }
+ FBX::Node::WritePropertyNode(
+ "UV", uv_data, outstream, binary, indent
+ );
+ FBX::Node::WritePropertyNode(
+ "UVIndex", uv_indices, outstream, binary, indent
+ );
+ indent = 2;
+ uv.End(outstream, binary, indent, true);
+ }
+
+ // i'm not really sure why this material section exists,
+ // as the material is linked via "Connections".
+ // it seems to always have the same "0" value.
+ FBX::Node mat("LayerElementMaterial", int32_t(0));
+ mat.AddChild("Version", int32_t(101));
+ mat.AddChild("Name", "");
+ mat.AddChild("MappingInformationType", "AllSame");
+ mat.AddChild("ReferenceInformationType", "IndexToDirect");
+ std::vector<int32_t> mat_indices = {0};
+ mat.AddChild("Materials", mat_indices);
+ mat.Dump(outstream, binary, indent);
+
+ // finally we have the layer specifications,
+ // which select the normals / UV set / etc to use.
+ // TODO: handle multiple uv sets correctly?
+ FBX::Node layer("Layer", int32_t(0));
+ layer.AddChild("Version", int32_t(100));
+ FBX::Node le("LayerElement");
+ le.AddChild("Type", "LayerElementNormal");
+ le.AddChild("TypedIndex", int32_t(0));
+ layer.AddChild(le);
+ le = FBX::Node("LayerElement");
+ le.AddChild("Type", "LayerElementMaterial");
+ le.AddChild("TypedIndex", int32_t(0));
+ layer.AddChild(le);
+ le = FBX::Node("LayerElement");
+ le.AddChild("Type", "LayerElementUV");
+ le.AddChild("TypedIndex", int32_t(0));
+ layer.AddChild(le);
+ layer.Dump(outstream, binary, indent);
+
+ // finish the node record
+ indent = 1;
+ n.End(outstream, binary, indent, true);
+ }
+
+ // aiMaterial
+ material_uids.clear();
+ for (size_t i = 0; i < mScene->mNumMaterials; ++i) {
+ // it's all about this material
+ aiMaterial* m = mScene->mMaterials[i];
+
+ // these are used to receive material data
+ float f; aiColor3D c;
+
+ // start the node record
+ FBX::Node n("Material");
+
+ int64_t uid = generate_uid();
+ material_uids.push_back(uid);
+ n.AddProperty(uid);
+
+ aiString name;
+ m->Get(AI_MATKEY_NAME, name);
+ n.AddProperty(name.C_Str() + FBX::SEPARATOR + "Material");
+
+ n.AddProperty("");
+
+ n.AddChild("Version", int32_t(102));
+ f = 0;
+ m->Get(AI_MATKEY_SHININESS, f);
+ bool phong = (f > 0);
+ if (phong) {
+ n.AddChild("ShadingModel", "phong");
+ } else {
+ n.AddChild("ShadingModel", "lambert");
+ }
+ n.AddChild("MultiLayer", int32_t(0));
+
+ FBX::Node p("Properties70");
+
+ // materials exported using the FBX SDK have two sets of fields.
+ // there are the properties specified in the PropertyTemplate,
+ // which are those supported by the modernFBX SDK,
+ // and an extra set of properties with simpler names.
+ // The extra properties are a legacy material system from pre-2009.
+ //
+ // In the modern system, each property has "color" and "factor".
+ // Generally the interpretation of these seems to be
+ // that the colour is multiplied by the factor before use,
+ // but this is not always clear-cut.
+ //
+ // Usually assimp only stores the colour,
+ // so we can just leave the factors at the default "1.0".
+
+ // first we can export the "standard" properties
+ if (m->Get(AI_MATKEY_COLOR_AMBIENT, c) == aiReturn_SUCCESS) {
+ p.AddP70colorA("AmbientColor", c.r, c.g, c.b);
+ //p.AddP70numberA("AmbientFactor", 1.0);
+ }
+ if (m->Get(AI_MATKEY_COLOR_DIFFUSE, c) == aiReturn_SUCCESS) {
+ p.AddP70colorA("DiffuseColor", c.r, c.g, c.b);
+ //p.AddP70numberA("DiffuseFactor", 1.0);
+ }
+ if (m->Get(AI_MATKEY_COLOR_TRANSPARENT, c) == aiReturn_SUCCESS) {
+ // "TransparentColor" / "TransparencyFactor"...
+ // thanks FBX, for your insightful interpretation of consistency
+ p.AddP70colorA("TransparentColor", c.r, c.g, c.b);
+ // TransparencyFactor defaults to 0.0, so set it to 1.0.
+ // note: Maya always sets this to 1.0,
+ // so we can't use it sensibly as "Opacity".
+ // In stead we rely on the legacy "Opacity" value, below.
+ // Blender also relies on "Opacity" not "TransparencyFactor",
+ // probably for a similar reason.
+ p.AddP70numberA("TransparencyFactor", 1.0);
+ }
+ if (m->Get(AI_MATKEY_COLOR_REFLECTIVE, c) == aiReturn_SUCCESS) {
+ p.AddP70colorA("ReflectionColor", c.r, c.g, c.b);
+ }
+ if (m->Get(AI_MATKEY_REFLECTIVITY, f) == aiReturn_SUCCESS) {
+ p.AddP70numberA("ReflectionFactor", f);
+ }
+ if (phong) {
+ if (m->Get(AI_MATKEY_COLOR_SPECULAR, c) == aiReturn_SUCCESS) {
+ p.AddP70colorA("SpecularColor", c.r, c.g, c.b);
+ }
+ if (m->Get(AI_MATKEY_SHININESS_STRENGTH, f) == aiReturn_SUCCESS) {
+ p.AddP70numberA("ShininessFactor", f);
+ }
+ if (m->Get(AI_MATKEY_SHININESS, f) == aiReturn_SUCCESS) {
+ p.AddP70numberA("ShininessExponent", f);
+ }
+ if (m->Get(AI_MATKEY_REFLECTIVITY, f) == aiReturn_SUCCESS) {
+ p.AddP70numberA("ReflectionFactor", f);
+ }
+ }
+
+ // Now the legacy system.
+ // For safety let's include it.
+ // thrse values don't exist in the property template,
+ // and usually are completely ignored when loading.
+ // One notable exception is the "Opacity" property,
+ // which Blender uses as (1.0 - alpha).
+ c.r = 0.0f; c.g = 0.0f; c.b = 0.0f;
+ m->Get(AI_MATKEY_COLOR_EMISSIVE, c);
+ p.AddP70vector("Emissive", c.r, c.g, c.b);
+ c.r = 0.2f; c.g = 0.2f; c.b = 0.2f;
+ m->Get(AI_MATKEY_COLOR_AMBIENT, c);
+ p.AddP70vector("Ambient", c.r, c.g, c.b);
+ c.r = 0.8f; c.g = 0.8f; c.b = 0.8f;
+ m->Get(AI_MATKEY_COLOR_DIFFUSE, c);
+ p.AddP70vector("Diffuse", c.r, c.g, c.b);
+ // The FBX SDK determines "Opacity" from transparency colour (RGB)
+ // and factor (F) as: O = (1.0 - F * ((R + G + B) / 3)).
+ // However we actually have an opacity value,
+ // so we should take it from AI_MATKEY_OPACITY if possible.
+ // It might make more sense to use TransparencyFactor,
+ // but Blender actually loads "Opacity" correctly, so let's use it.
+ f = 1.0f;
+ if (m->Get(AI_MATKEY_COLOR_TRANSPARENT, c) == aiReturn_SUCCESS) {
+ f = 1.0f - ((c.r + c.g + c.b) / 3.0f);
+ }
+ m->Get(AI_MATKEY_OPACITY, f);
+ p.AddP70double("Opacity", f);
+ if (phong) {
+ // specular color is multiplied by shininess_strength
+ c.r = 0.2f; c.g = 0.2f; c.b = 0.2f;
+ m->Get(AI_MATKEY_COLOR_SPECULAR, c);
+ f = 1.0f;
+ m->Get(AI_MATKEY_SHININESS_STRENGTH, f);
+ p.AddP70vector("Specular", f*c.r, f*c.g, f*c.b);
+ f = 20.0f;
+ m->Get(AI_MATKEY_SHININESS, f);
+ p.AddP70double("Shininess", f);
+ // Legacy "Reflectivity" is F*F*((R+G+B)/3),
+ // where F is the proportion of light reflected (AKA reflectivity),
+ // and RGB is the reflective colour of the material.
+ // No idea why, but we might as well set it the same way.
+ f = 0.0f;
+ m->Get(AI_MATKEY_REFLECTIVITY, f);
+ c.r = 1.0f, c.g = 1.0f, c.b = 1.0f;
+ m->Get(AI_MATKEY_COLOR_REFLECTIVE, c);
+ p.AddP70double("Reflectivity", f*f*((c.r+c.g+c.b)/3.0));
+ }
+
+ n.AddChild(p);
+
+ n.Dump(outstream, binary, indent);
+ }
+
+ // we need to look up all the images we're using,
+ // so we can generate uids, and eliminate duplicates.
+ std::map<std::string, int64_t> uid_by_image;
+ for (size_t i = 0; i < mScene->mNumMaterials; ++i) {
+ aiString texpath;
+ aiMaterial* mat = mScene->mMaterials[i];
+ for (
+ size_t tt = aiTextureType_DIFFUSE;
+ tt < aiTextureType_UNKNOWN;
+ ++tt
+ ){
+ const aiTextureType textype = static_cast<aiTextureType>(tt);
+ const size_t texcount = mat->GetTextureCount(textype);
+ for (size_t j = 0; j < texcount; ++j) {
+ mat->GetTexture(textype, (unsigned int)j, &texpath);
+ const std::string texstring = texpath.C_Str();
+ auto elem = uid_by_image.find(texstring);
+ if (elem == uid_by_image.end()) {
+ uid_by_image[texstring] = generate_uid();
+ }
+ }
+ }
+ }
+
+ // FbxVideo - stores images used by textures.
+ for (const auto &it : uid_by_image) {
+ if (it.first.compare(0, 1, "*") == 0) {
+ // TODO: embedded textures
+ continue;
+ }
+ FBX::Node n("Video");
+ const int64_t& uid = it.second;
+ const std::string name = ""; // TODO: ... name???
+ n.AddProperties(uid, name + FBX::SEPARATOR + "Video", "Clip");
+ n.AddChild("Type", "Clip");
+ FBX::Node p("Properties70");
+ // TODO: get full path... relative path... etc... ugh...
+ // for now just use the same path for everything,
+ // and hopefully one of them will work out.
+ const std::string& path = it.first;
+ p.AddP70("Path", "KString", "XRefUrl", "", path);
+ n.AddChild(p);
+ n.AddChild("UseMipMap", int32_t(0));
+ n.AddChild("Filename", path);
+ n.AddChild("RelativeFilename", path);
+ n.Dump(outstream, binary, indent);
+ }
+
+ // Textures
+ // referenced by material_index/texture_type pairs.
+ std::map<std::pair<size_t,size_t>,int64_t> texture_uids;
+ const std::map<aiTextureType,std::string> prop_name_by_tt = {
+ {aiTextureType_DIFFUSE, "DiffuseColor"},
+ {aiTextureType_SPECULAR, "SpecularColor"},
+ {aiTextureType_AMBIENT, "AmbientColor"},
+ {aiTextureType_EMISSIVE, "EmissiveColor"},
+ {aiTextureType_HEIGHT, "Bump"},
+ {aiTextureType_NORMALS, "NormalMap"},
+ {aiTextureType_SHININESS, "ShininessExponent"},
+ {aiTextureType_OPACITY, "TransparentColor"},
+ {aiTextureType_DISPLACEMENT, "DisplacementColor"},
+ //{aiTextureType_LIGHTMAP, "???"},
+ {aiTextureType_REFLECTION, "ReflectionColor"}
+ //{aiTextureType_UNKNOWN, ""}
+ };
+ for (size_t i = 0; i < mScene->mNumMaterials; ++i) {
+ // textures are attached to materials
+ aiMaterial* mat = mScene->mMaterials[i];
+ int64_t material_uid = material_uids[i];
+
+ for (
+ size_t j = aiTextureType_DIFFUSE;
+ j < aiTextureType_UNKNOWN;
+ ++j
+ ) {
+ const aiTextureType tt = static_cast<aiTextureType>(j);
+ size_t n = mat->GetTextureCount(tt);
+
+ if (n < 1) { // no texture of this type
+ continue;
+ }
+
+ if (n > 1) {
+ // TODO: multilayer textures
+ std::stringstream err;
+ err << "Multilayer textures not supported (for now),";
+ err << " skipping texture type " << j;
+ err << " of material " << i;
+ ASSIMP_LOG_WARN(err.str());
+ }
+
+ // get image path for this (single-image) texture
+ aiString tpath;
+ if (mat->GetTexture(tt, 0, &tpath) != aiReturn_SUCCESS) {
+ std::stringstream err;
+ err << "Failed to get texture 0 for texture of type " << tt;
+ err << " on material " << i;
+ err << ", however GetTextureCount returned 1.";
+ throw DeadlyExportError(err.str());
+ }
+ const std::string texture_path(tpath.C_Str());
+
+ // get connected image uid
+ auto elem = uid_by_image.find(texture_path);
+ if (elem == uid_by_image.end()) {
+ // this should never happen
+ std::stringstream err;
+ err << "Failed to find video element for texture with path";
+ err << " \"" << texture_path << "\"";
+ err << ", type " << j << ", material " << i;
+ throw DeadlyExportError(err.str());
+ }
+ const int64_t image_uid = elem->second;
+
+ // get the name of the material property to connect to
+ auto elem2 = prop_name_by_tt.find(tt);
+ if (elem2 == prop_name_by_tt.end()) {
+ // don't know how to handle this type of texture,
+ // so skip it.
+ std::stringstream err;
+ err << "Not sure how to handle texture of type " << j;
+ err << " on material " << i;
+ err << ", skipping...";
+ ASSIMP_LOG_WARN(err.str());
+ continue;
+ }
+ const std::string& prop_name = elem2->second;
+
+ // generate a uid for this texture
+ const int64_t texture_uid = generate_uid();
+
+ // link the texture to the material
+ connections.emplace_back(
+ "C", "OP", texture_uid, material_uid, prop_name
+ );
+
+ // link the image data to the texture
+ connections.emplace_back("C", "OO", image_uid, texture_uid);
+
+ // now write the actual texture node
+ FBX::Node tnode("Texture");
+ // TODO: some way to determine texture name?
+ const std::string texture_name = "" + FBX::SEPARATOR + "Texture";
+ tnode.AddProperties(texture_uid, texture_name, "");
+ // there really doesn't seem to be a better type than this:
+ tnode.AddChild("Type", "TextureVideoClip");
+ tnode.AddChild("Version", int32_t(202));
+ tnode.AddChild("TextureName", texture_name);
+ FBX::Node p("Properties70");
+ p.AddP70enum("CurrentTextureBlendMode", 0); // TODO: verify
+ //p.AddP70string("UVSet", ""); // TODO: how should this work?
+ p.AddP70bool("UseMaterial", 1);
+ tnode.AddChild(p);
+ // can't easily detrmine which texture path will be correct,
+ // so just store what we have in every field.
+ // these being incorrect is a common problem with FBX anyway.
+ tnode.AddChild("FileName", texture_path);
+ tnode.AddChild("RelativeFilename", texture_path);
+ tnode.AddChild("ModelUVTranslation", double(0.0), double(0.0));
+ tnode.AddChild("ModelUVScaling", double(1.0), double(1.0));
+ tnode.AddChild("Texture_Alpha_Source", "None");
+ tnode.AddChild(
+ "Cropping", int32_t(0), int32_t(0), int32_t(0), int32_t(0)
+ );
+ tnode.Dump(outstream, binary, indent);
+ }
+ }
+
+ // bones.
+ //
+ // output structure:
+ // subset of node hierarchy that are "skeleton",
+ // i.e. do not have meshes but only bones.
+ // but.. i'm not sure how anyone could guarantee that...
+ //
+ // input...
+ // well, for each mesh it has "bones",
+ // and the bone names correspond to nodes.
+ // of course we also need the parent nodes,
+ // as they give some of the transform........
+ //
+ // well. we can assume a sane input, i suppose.
+ //
+ // so input is the bone node hierarchy,
+ // with an extra thing for the transformation of the MESH in BONE space.
+ //
+ // output is a set of bone nodes,
+ // a "bindpose" which indicates the default local transform of all bones,
+ // and a set of "deformers".
+ // each deformer is parented to a mesh geometry,
+ // and has one or more "subdeformer"s as children.
+ // each subdeformer has one bone node as a child,
+ // and represents the influence of that bone on the grandparent mesh.
+ // the subdeformer has a list of indices, and weights,
+ // with indices specifying vertex indices,
+ // and weights specifying the corresponding influence of this bone.
+ // it also has Transform and TransformLink elements,
+ // specifying the transform of the MESH in BONE space,
+ // and the transformation of the BONE in WORLD space,
+ // likely in the bindpose.
+ //
+ // the input bone structure is different but similar,
+ // storing the number of weights for this bone,
+ // and an array of (vertex index, weight) pairs.
+ //
+ // one sticky point is that the number of vertices may not match,
+ // because assimp splits vertices by normal, uv, etc.
+
+ // first we should mark the skeleton for each mesh.
+ // the skeleton must include not only the aiBones,
+ // but also all their parent nodes.
+ // anything that affects the position of any bone node must be included.
+ std::vector<std::set<const aiNode*>> skeleton_by_mesh(mScene->mNumMeshes);
+ // at the same time we can build a list of all the skeleton nodes,
+ // which will be used later to mark them as type "limbNode".
+ std::unordered_set<const aiNode*> limbnodes;
+ // and a map of nodes by bone name, as finding them is annoying.
+ std::map<std::string,aiNode*> node_by_bone;
+ for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) {
+ const aiMesh* m = mScene->mMeshes[mi];
+ std::set<const aiNode*> skeleton;
+ for (size_t bi =0; bi < m->mNumBones; ++bi) {
+ const aiBone* b = m->mBones[bi];
+ const std::string name(b->mName.C_Str());
+ auto elem = node_by_bone.find(name);
+ aiNode* n;
+ if (elem != node_by_bone.end()) {
+ n = elem->second;
+ } else {
+ n = mScene->mRootNode->FindNode(b->mName);
+ if (!n) {
+ // this should never happen
+ std::stringstream err;
+ err << "Failed to find node for bone: \"" << name << "\"";
+ throw DeadlyExportError(err.str());
+ }
+ node_by_bone[name] = n;
+ limbnodes.insert(n);
+ }
+ skeleton.insert(n);
+ // mark all parent nodes as skeleton as well,
+ // up until we find the root node,
+ // or else the node containing the mesh,
+ // or else the parent of a node containig the mesh.
+ for (
+ const aiNode* parent = n->mParent;
+ parent && parent != mScene->mRootNode;
+ parent = parent->mParent
+ ) {
+ // if we've already done this node we can skip it all
+ if (skeleton.count(parent)) {
+ break;
+ }
+ // ignore fbx transform nodes as these will be collapsed later
+ // TODO: cache this by aiNode*
+ const std::string node_name(parent->mName.C_Str());
+ if (node_name.find(MAGIC_NODE_TAG) != std::string::npos) {
+ continue;
+ }
+ // otherwise check if this is the root of the skeleton
+ bool end = false;
+ // is the mesh part of this node?
+ for (size_t i = 0; i < parent->mNumMeshes; ++i) {
+ if (parent->mMeshes[i] == mi) {
+ end = true;
+ break;
+ }
+ }
+ // is the mesh in one of the children of this node?
+ for (size_t j = 0; j < parent->mNumChildren; ++j) {
+ aiNode* child = parent->mChildren[j];
+ for (size_t i = 0; i < child->mNumMeshes; ++i) {
+ if (child->mMeshes[i] == mi) {
+ end = true;
+ break;
+ }
+ }
+ if (end) { break; }
+ }
+ limbnodes.insert(parent);
+ skeleton.insert(parent);
+ // if it was the skeleton root we can finish here
+ if (end) { break; }
+ }
+ }
+ skeleton_by_mesh[mi] = skeleton;
+ }
+
+ // we'll need the uids for the bone nodes, so generate them now
+ for (size_t i = 0; i < mScene->mNumMeshes; ++i) {
+ auto &s = skeleton_by_mesh[i];
+ for (const aiNode* n : s) {
+ auto elem = node_uids.find(n);
+ if (elem == node_uids.end()) {
+ node_uids[n] = generate_uid();
+ }
+ }
+ }
+
+ // now, for each aiMesh, we need to export a deformer,
+ // and for each aiBone a subdeformer,
+ // which should have all the skinning info.
+ // these will need to be connected properly to the mesh,
+ // and we can do that all now.
+ for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) {
+ const aiMesh* m = mScene->mMeshes[mi];
+ if (!m->HasBones()) {
+ continue;
+ }
+ // make a deformer for this mesh
+ int64_t deformer_uid = generate_uid();
+ FBX::Node dnode("Deformer");
+ dnode.AddProperties(deformer_uid, FBX::SEPARATOR + "Deformer", "Skin");
+ dnode.AddChild("Version", int32_t(101));
+ // "acuracy"... this is not a typo....
+ dnode.AddChild("Link_DeformAcuracy", double(50));
+ dnode.AddChild("SkinningType", "Linear"); // TODO: other modes?
+ dnode.Dump(outstream, binary, indent);
+
+ // connect it
+ connections.emplace_back("C", "OO", deformer_uid, mesh_uids[mi]);
+
+ // we will be indexing by vertex...
+ // but there might be a different number of "vertices"
+ // between assimp and our output FBX.
+ // this code is cut-and-pasted from the geometry section above...
+ // ideally this should not be so.
+ // ---
+ // index of original vertex in vertex data vector
+ std::vector<int32_t> vertex_indices;
+ // map of vertex value to its index in the data vector
+ std::map<aiVector3D,size_t> index_by_vertex_value;
+ int32_t index = 0;
+ for (size_t vi = 0; vi < m->mNumVertices; ++vi) {
+ aiVector3D vtx = m->mVertices[vi];
+ auto elem = index_by_vertex_value.find(vtx);
+ if (elem == index_by_vertex_value.end()) {
+ vertex_indices.push_back(index);
+ index_by_vertex_value[vtx] = index;
+ ++index;
+ } else {
+ vertex_indices.push_back(int32_t(elem->second));
+ }
+ }
+
+ // TODO, FIXME: this won't work if anything is not in the bind pose.
+ // for now if such a situation is detected, we throw an exception.
+ std::set<const aiBone*> not_in_bind_pose;
+ std::set<const aiNode*> no_offset_matrix;
+
+ // first get this mesh's position in world space,
+ // as we'll need it for each subdeformer.
+ //
+ // ...of course taking the position of the MESH doesn't make sense,
+ // as it can be instanced to many nodes.
+ // All we can do is assume no instancing,
+ // and take the first node we find that contains the mesh.
+ aiNode* mesh_node = get_node_for_mesh((unsigned int)mi, mScene->mRootNode);
+ aiMatrix4x4 mesh_xform = get_world_transform(mesh_node, mScene);
+
+ // now make a subdeformer for each bone in the skeleton
+ const std::set<const aiNode*> &skeleton = skeleton_by_mesh[mi];
+ for (const aiNode* bone_node : skeleton) {
+ // if there's a bone for this node, find it
+ const aiBone* b = nullptr;
+ for (size_t bi = 0; bi < m->mNumBones; ++bi) {
+ // TODO: this probably should index by something else
+ const std::string name(m->mBones[bi]->mName.C_Str());
+ if (node_by_bone[name] == bone_node) {
+ b = m->mBones[bi];
+ break;
+ }
+ }
+ if (!b) {
+ no_offset_matrix.insert(bone_node);
+ }
+
+ // start the subdeformer node
+ const int64_t subdeformer_uid = generate_uid();
+ FBX::Node sdnode("Deformer");
+ sdnode.AddProperties(
+ subdeformer_uid, FBX::SEPARATOR + "SubDeformer", "Cluster"
+ );
+ sdnode.AddChild("Version", int32_t(100));
+ sdnode.AddChild("UserData", "", "");
+
+ // add indices and weights, if any
+ if (b) {
+ std::vector<int32_t> subdef_indices;
+ std::vector<double> subdef_weights;
+ int32_t last_index = -1;
+ for (size_t wi = 0; wi < b->mNumWeights; ++wi) {
+ int32_t vi = vertex_indices[b->mWeights[wi].mVertexId];
+ if (vi == last_index) {
+ // only for vertices we exported to fbx
+ // TODO, FIXME: this assumes identically-located vertices
+ // will always deform in the same way.
+ // as assimp doesn't store a separate list of "positions",
+ // there's not much that can be done about this
+ // other than assuming that identical position means
+ // identical vertex.
+ continue;
+ }
+ subdef_indices.push_back(vi);
+ subdef_weights.push_back(b->mWeights[wi].mWeight);
+ last_index = vi;
+ }
+ // yes, "indexes"
+ sdnode.AddChild("Indexes", subdef_indices);
+ sdnode.AddChild("Weights", subdef_weights);
+ }
+
+ // transform is the transform of the mesh, but in bone space.
+ // if the skeleton is in the bind pose,
+ // we can take the inverse of the world-space bone transform
+ // and multiply by the world-space transform of the mesh.
+ aiMatrix4x4 bone_xform = get_world_transform(bone_node, mScene);
+ aiMatrix4x4 inverse_bone_xform = bone_xform;
+ inverse_bone_xform.Inverse();
+ aiMatrix4x4 tr = inverse_bone_xform * mesh_xform;
+
+ // this should be the same as the bone's mOffsetMatrix.
+ // if it's not the same, the skeleton isn't in the bind pose.
+ const float epsilon = 1e-4f; // some error is to be expected
+ bool bone_xform_okay = true;
+ if (b && ! tr.Equal(b->mOffsetMatrix, epsilon)) {
+ not_in_bind_pose.insert(b);
+ bone_xform_okay = false;
+ }
+
+ // if we have a bone we should use the mOffsetMatrix,
+ // otherwise try to just use the calculated transform.
+ if (b) {
+ sdnode.AddChild("Transform", b->mOffsetMatrix);
+ } else {
+ sdnode.AddChild("Transform", tr);
+ }
+ // note: it doesn't matter if we mix these,
+ // because if they disagree we'll throw an exception later.
+ // it could be that the skeleton is not in the bone pose
+ // but all bones are still defined,
+ // in which case this would use the mOffsetMatrix for everything
+ // and a correct skeleton would still be output.
+
+ // transformlink should be the position of the bone in world space.
+ // if the bone is in the bind pose (or nonexistent),
+ // we can just use the matrix we already calculated
+ if (bone_xform_okay) {
+ sdnode.AddChild("TransformLink", bone_xform);
+ // otherwise we can only work it out using the mesh position.
+ } else {
+ aiMatrix4x4 trl = b->mOffsetMatrix;
+ trl.Inverse();
+ trl *= mesh_xform;
+ sdnode.AddChild("TransformLink", trl);
+ }
+ // note: this means we ALWAYS rely on the mesh node transform
+ // being unchanged from the time the skeleton was bound.
+ // there's not really any way around this at the moment.
+
+ // done
+ sdnode.Dump(outstream, binary, indent);
+
+ // lastly, connect to the parent deformer
+ connections.emplace_back(
+ "C", "OO", subdeformer_uid, deformer_uid
+ );
+
+ // we also need to connect the limb node to the subdeformer.
+ connections.emplace_back(
+ "C", "OO", node_uids[bone_node], subdeformer_uid
+ );
+ }
+
+ // if we cannot create a valid FBX file, simply die.
+ // this will both prevent unnecessary bug reports,
+ // and tell the user what they can do to fix the situation
+ // (i.e. export their model in the bind pose).
+ if (no_offset_matrix.size() && not_in_bind_pose.size()) {
+ std::stringstream err;
+ err << "Not enough information to construct bind pose";
+ err << " for mesh " << mi << "!";
+ err << " Transform matrix for bone \"";
+ err << (*not_in_bind_pose.begin())->mName.C_Str() << "\"";
+ if (not_in_bind_pose.size() > 1) {
+ err << " (and " << not_in_bind_pose.size() - 1 << " more)";
+ }
+ err << " does not match mOffsetMatrix,";
+ err << " and node \"";
+ err << (*no_offset_matrix.begin())->mName.C_Str() << "\"";
+ if (no_offset_matrix.size() > 1) {
+ err << " (and " << no_offset_matrix.size() - 1 << " more)";
+ }
+ err << " has no offset matrix to rely on.";
+ err << " Please ensure bones are in the bind pose to export.";
+ throw DeadlyExportError(err.str());
+ }
+
+ }
+
+ // BindPose
+ //
+ // This is a legacy system, which should be unnecessary.
+ //
+ // Somehow including it slows file loading by the official FBX SDK,
+ // and as it can reconstruct it from the deformers anyway,
+ // this is not currently included.
+ //
+ // The code is kept here in case it's useful in the future,
+ // but it's pretty much a hack anyway,
+ // as assimp doesn't store bindpose information for full skeletons.
+ //
+ /*for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) {
+ aiMesh* mesh = mScene->mMeshes[mi];
+ if (! mesh->HasBones()) { continue; }
+ int64_t bindpose_uid = generate_uid();
+ FBX::Node bpnode("Pose");
+ bpnode.AddProperty(bindpose_uid);
+ // note: this uid is never linked or connected to anything.
+ bpnode.AddProperty(FBX::SEPARATOR + "Pose"); // blank name
+ bpnode.AddProperty("BindPose");
+
+ bpnode.AddChild("Type", "BindPose");
+ bpnode.AddChild("Version", int32_t(100));
+
+ aiNode* mesh_node = get_node_for_mesh(mi, mScene->mRootNode);
+
+ // next get the whole skeleton for this mesh.
+ // we need it all to define the bindpose section.
+ // the FBX SDK will complain if it's missing,
+ // and also if parents of used bones don't have a subdeformer.
+ // order shouldn't matter.
+ std::set<aiNode*> skeleton;
+ for (size_t bi = 0; bi < mesh->mNumBones; ++bi) {
+ // bone node should have already been indexed
+ const aiBone* b = mesh->mBones[bi];
+ const std::string bone_name(b->mName.C_Str());
+ aiNode* parent = node_by_bone[bone_name];
+ // insert all nodes down to the root or mesh node
+ while (
+ parent
+ && parent != mScene->mRootNode
+ && parent != mesh_node
+ ) {
+ skeleton.insert(parent);
+ parent = parent->mParent;
+ }
+ }
+
+ // number of pose nodes. includes one for the mesh itself.
+ bpnode.AddChild("NbPoseNodes", int32_t(1 + skeleton.size()));
+
+ // the first pose node is always the mesh itself
+ FBX::Node pose("PoseNode");
+ pose.AddChild("Node", mesh_uids[mi]);
+ aiMatrix4x4 mesh_node_xform = get_world_transform(mesh_node, mScene);
+ pose.AddChild("Matrix", mesh_node_xform);
+ bpnode.AddChild(pose);
+
+ for (aiNode* bonenode : skeleton) {
+ // does this node have a uid yet?
+ int64_t node_uid;
+ auto node_uid_iter = node_uids.find(bonenode);
+ if (node_uid_iter != node_uids.end()) {
+ node_uid = node_uid_iter->second;
+ } else {
+ node_uid = generate_uid();
+ node_uids[bonenode] = node_uid;
+ }
+
+ // make a pose thingy
+ pose = FBX::Node("PoseNode");
+ pose.AddChild("Node", node_uid);
+ aiMatrix4x4 node_xform = get_world_transform(bonenode, mScene);
+ pose.AddChild("Matrix", node_xform);
+ bpnode.AddChild(pose);
+ }
+
+ // now write it
+ bpnode.Dump(outstream, binary, indent);
+ }*/
+
+ // TODO: cameras, lights
+
+ // write nodes (i.e. model hierarchy)
+ // start at root node
+ WriteModelNodes(
+ outstream, mScene->mRootNode, 0, limbnodes
+ );
+
+ // animations
+ //
+ // in FBX there are:
+ // * AnimationStack - corresponds to an aiAnimation
+ // * AnimationLayer - a combinable animation component
+ // * AnimationCurveNode - links the property to be animated
+ // * AnimationCurve - defines animation data for a single property value
+ //
+ // the CurveNode also provides the default value for a property,
+ // such as the X, Y, Z coordinates for animatable translation.
+ //
+ // the Curve only specifies values for one component of the property,
+ // so there will be a separate AnimationCurve for X, Y, and Z.
+ //
+ // Assimp has:
+ // * aiAnimation - basically corresponds to an AnimationStack
+ // * aiNodeAnim - defines all animation for one aiNode
+ // * aiVectorKey/aiQuatKey - define the keyframe data for T/R/S
+ //
+ // assimp has no equivalent for AnimationLayer,
+ // and these are flattened on FBX import.
+ // we can assume there will be one per AnimationStack.
+ //
+ // the aiNodeAnim contains all animation data for a single aiNode,
+ // which will correspond to three AnimationCurveNode's:
+ // one each for translation, rotation and scale.
+ // The data for each of these will be put in 9 AnimationCurve's,
+ // T.X, T.Y, T.Z, R.X, R.Y, R.Z, etc.
+
+ // AnimationStack / aiAnimation
+ std::vector<int64_t> animation_stack_uids(mScene->mNumAnimations);
+ for (size_t ai = 0; ai < mScene->mNumAnimations; ++ai) {
+ int64_t animstack_uid = generate_uid();
+ animation_stack_uids[ai] = animstack_uid;
+ const aiAnimation* anim = mScene->mAnimations[ai];
+
+ FBX::Node asnode("AnimationStack");
+ std::string name = anim->mName.C_Str() + FBX::SEPARATOR + "AnimStack";
+ asnode.AddProperties(animstack_uid, name, "");
+ FBX::Node p("Properties70");
+ p.AddP70time("LocalStart", 0); // assimp doesn't store this
+ p.AddP70time("LocalStop", to_ktime(anim->mDuration, anim));
+ p.AddP70time("ReferenceStart", 0);
+ p.AddP70time("ReferenceStop", to_ktime(anim->mDuration, anim));
+ asnode.AddChild(p);
+
+ // this node absurdly always pretends it has children
+ // (in this case it does, but just in case...)
+ asnode.force_has_children = true;
+ asnode.Dump(outstream, binary, indent);
+
+ // note: animation stacks are not connected to anything
+ }
+
+ // AnimationLayer - one per aiAnimation
+ std::vector<int64_t> animation_layer_uids(mScene->mNumAnimations);
+ for (size_t ai = 0; ai < mScene->mNumAnimations; ++ai) {
+ int64_t animlayer_uid = generate_uid();
+ animation_layer_uids[ai] = animlayer_uid;
+ FBX::Node alnode("AnimationLayer");
+ alnode.AddProperties(animlayer_uid, FBX::SEPARATOR + "AnimLayer", "");
+
+ // this node absurdly always pretends it has children
+ alnode.force_has_children = true;
+ alnode.Dump(outstream, binary, indent);
+
+ // connect to the relevant animstack
+ connections.emplace_back(
+ "C", "OO", animlayer_uid, animation_stack_uids[ai]
+ );
+ }
+
+ // AnimCurveNode - three per aiNodeAnim
+ std::vector<std::vector<std::array<int64_t,3>>> curve_node_uids;
+ for (size_t ai = 0; ai < mScene->mNumAnimations; ++ai) {
+ const aiAnimation* anim = mScene->mAnimations[ai];
+ const int64_t layer_uid = animation_layer_uids[ai];
+ std::vector<std::array<int64_t,3>> nodeanim_uids;
+ for (size_t nai = 0; nai < anim->mNumChannels; ++nai) {
+ const aiNodeAnim* na = anim->mChannels[nai];
+ // get the corresponding aiNode
+ const aiNode* node = mScene->mRootNode->FindNode(na->mNodeName);
+ // and its transform
+ const aiMatrix4x4 node_xfm = get_world_transform(node, mScene);
+ aiVector3D T, R, S;
+ node_xfm.Decompose(S, R, T);
+
+ // AnimationCurveNode uids
+ std::array<int64_t,3> ids;
+ ids[0] = generate_uid(); // T
+ ids[1] = generate_uid(); // R
+ ids[2] = generate_uid(); // S
+
+ // translation
+ WriteAnimationCurveNode(outstream,
+ ids[0], "T", T, "Lcl Translation",
+ layer_uid, node_uids[node]
+ );
+
+ // rotation
+ WriteAnimationCurveNode(outstream,
+ ids[1], "R", R, "Lcl Rotation",
+ layer_uid, node_uids[node]
+ );
+
+ // scale
+ WriteAnimationCurveNode(outstream,
+ ids[2], "S", S, "Lcl Scale",
+ layer_uid, node_uids[node]
+ );
+
+ // store the uids for later use
+ nodeanim_uids.push_back(ids);
+ }
+ curve_node_uids.push_back(nodeanim_uids);
+ }
+
+ // AnimCurve - defines actual keyframe data.
+ // there's a separate curve for every component of every vector,
+ // for example a transform curvenode will have separate X/Y/Z AnimCurve's
+ for (size_t ai = 0; ai < mScene->mNumAnimations; ++ai) {
+ const aiAnimation* anim = mScene->mAnimations[ai];
+ for (size_t nai = 0; nai < anim->mNumChannels; ++nai) {
+ const aiNodeAnim* na = anim->mChannels[nai];
+ // get the corresponding aiNode
+ const aiNode* node = mScene->mRootNode->FindNode(na->mNodeName);
+ // and its transform
+ const aiMatrix4x4 node_xfm = get_world_transform(node, mScene);
+ aiVector3D T, R, S;
+ node_xfm.Decompose(S, R, T);
+ const std::array<int64_t,3>& ids = curve_node_uids[ai][nai];
+
+ std::vector<int64_t> times;
+ std::vector<float> xval, yval, zval;
+
+ // position/translation
+ for (size_t ki = 0; ki < na->mNumPositionKeys; ++ki) {
+ const aiVectorKey& k = na->mPositionKeys[ki];
+ times.push_back(to_ktime(k.mTime));
+ xval.push_back(k.mValue.x);
+ yval.push_back(k.mValue.y);
+ zval.push_back(k.mValue.z);
+ }
+ // one curve each for X, Y, Z
+ WriteAnimationCurve(outstream, T.x, times, xval, ids[0], "d|X");
+ WriteAnimationCurve(outstream, T.y, times, yval, ids[0], "d|Y");
+ WriteAnimationCurve(outstream, T.z, times, zval, ids[0], "d|Z");
+
+ // rotation
+ times.clear(); xval.clear(); yval.clear(); zval.clear();
+ for (size_t ki = 0; ki < na->mNumRotationKeys; ++ki) {
+ const aiQuatKey& k = na->mRotationKeys[ki];
+ times.push_back(to_ktime(k.mTime));
+ // TODO: aiQuaternion method to convert to Euler...
+ aiMatrix4x4 m(k.mValue.GetMatrix());
+ aiVector3D qs, qr, qt;
+ m.Decompose(qs, qr, qt);
+ qr *= DEG;
+ xval.push_back(qr.x);
+ yval.push_back(qr.y);
+ zval.push_back(qr.z);
+ }
+ WriteAnimationCurve(outstream, R.x, times, xval, ids[1], "d|X");
+ WriteAnimationCurve(outstream, R.y, times, yval, ids[1], "d|Y");
+ WriteAnimationCurve(outstream, R.z, times, zval, ids[1], "d|Z");
+
+ // scaling/scale
+ times.clear(); xval.clear(); yval.clear(); zval.clear();
+ for (size_t ki = 0; ki < na->mNumScalingKeys; ++ki) {
+ const aiVectorKey& k = na->mScalingKeys[ki];
+ times.push_back(to_ktime(k.mTime));
+ xval.push_back(k.mValue.x);
+ yval.push_back(k.mValue.y);
+ zval.push_back(k.mValue.z);
+ }
+ WriteAnimationCurve(outstream, S.x, times, xval, ids[2], "d|X");
+ WriteAnimationCurve(outstream, S.y, times, yval, ids[2], "d|Y");
+ WriteAnimationCurve(outstream, S.z, times, zval, ids[2], "d|Z");
+ }
+ }
+
+ indent = 0;
+ object_node.End(outstream, binary, indent, true);
+}
+
+// convenience map of magic node name strings to FBX properties,
+// including the expected type of transform.
+const std::map<std::string,std::pair<std::string,char>> transform_types = {
+ {"Translation", {"Lcl Translation", 't'}},
+ {"RotationOffset", {"RotationOffset", 't'}},
+ {"RotationPivot", {"RotationPivot", 't'}},
+ {"PreRotation", {"PreRotation", 'r'}},
+ {"Rotation", {"Lcl Rotation", 'r'}},
+ {"PostRotation", {"PostRotation", 'r'}},
+ {"RotationPivotInverse", {"RotationPivotInverse", 'i'}},
+ {"ScalingOffset", {"ScalingOffset", 't'}},
+ {"ScalingPivot", {"ScalingPivot", 't'}},
+ {"Scaling", {"Lcl Scaling", 's'}},
+ {"ScalingPivotInverse", {"ScalingPivotInverse", 'i'}},
+ {"GeometricScaling", {"GeometricScaling", 's'}},
+ {"GeometricRotation", {"GeometricRotation", 'r'}},
+ {"GeometricTranslation", {"GeometricTranslation", 't'}},
+ {"GeometricTranslationInverse", {"GeometricTranslationInverse", 'i'}},
+ {"GeometricRotationInverse", {"GeometricRotationInverse", 'i'}},
+ {"GeometricScalingInverse", {"GeometricScalingInverse", 'i'}}
+};
+
+// write a single model node to the stream
+void FBXExporter::WriteModelNode(
+ StreamWriterLE& outstream,
+ bool binary,
+ const aiNode* node,
+ int64_t node_uid,
+ const std::string& type,
+ const std::vector<std::pair<std::string,aiVector3D>>& transform_chain,
+ TransformInheritance inherit_type
+){
+ const aiVector3D zero = {0, 0, 0};
+ const aiVector3D one = {1, 1, 1};
+ FBX::Node m("Model");
+ std::string name = node->mName.C_Str() + FBX::SEPARATOR + "Model";
+ m.AddProperties(node_uid, name, type);
+ m.AddChild("Version", int32_t(232));
+ FBX::Node p("Properties70");
+ p.AddP70bool("RotationActive", 1);
+ p.AddP70int("DefaultAttributeIndex", 0);
+ p.AddP70enum("InheritType", inherit_type);
+ if (transform_chain.empty()) {
+ // decompose 4x4 transform matrix into TRS
+ aiVector3D t, r, s;
+ node->mTransformation.Decompose(s, r, t);
+ if (t != zero) {
+ p.AddP70(
+ "Lcl Translation", "Lcl Translation", "", "A",
+ double(t.x), double(t.y), double(t.z)
+ );
+ }
+ if (r != zero) {
+ p.AddP70(
+ "Lcl Rotation", "Lcl Rotation", "", "A",
+ double(DEG*r.x), double(DEG*r.y), double(DEG*r.z)
+ );
+ }
+ if (s != one) {
+ p.AddP70(
+ "Lcl Scaling", "Lcl Scaling", "", "A",
+ double(s.x), double(s.y), double(s.z)
+ );
+ }
+ } else {
+ // apply the transformation chain.
+ // these transformation elements are created when importing FBX,
+ // which has a complex transformation hierarchy for each node.
+ // as such we can bake the hierarchy back into the node on export.
+ for (auto &item : transform_chain) {
+ auto elem = transform_types.find(item.first);
+ if (elem == transform_types.end()) {
+ // then this is a bug
+ std::stringstream err;
+ err << "unrecognized FBX transformation type: ";
+ err << item.first;
+ throw DeadlyExportError(err.str());
+ }
+ const std::string &name = elem->second.first;
+ const aiVector3D &v = item.second;
+ if (name.compare(0, 4, "Lcl ") == 0) {
+ // special handling for animatable properties
+ p.AddP70(
+ name, name, "", "A",
+ double(v.x), double(v.y), double(v.z)
+ );
+ } else {
+ p.AddP70vector(name, v.x, v.y, v.z);
+ }
+ }
+ }
+ m.AddChild(p);
+
+ // not sure what these are for,
+ // but they seem to be omnipresent
+ m.AddChild("Shading", Property(true));
+ m.AddChild("Culling", Property("CullingOff"));
+
+ m.Dump(outstream, binary, 1);
+}
+
+// wrapper for WriteModelNodes to create and pass a blank transform chain
+void FBXExporter::WriteModelNodes(
+ StreamWriterLE& s,
+ const aiNode* node,
+ int64_t parent_uid,
+ const std::unordered_set<const aiNode*>& limbnodes
+) {
+ std::vector<std::pair<std::string,aiVector3D>> chain;
+ WriteModelNodes(s, node, parent_uid, limbnodes, chain);
+}
+
+void FBXExporter::WriteModelNodes(
+ StreamWriterLE& outstream,
+ const aiNode* node,
+ int64_t parent_uid,
+ const std::unordered_set<const aiNode*>& limbnodes,
+ std::vector<std::pair<std::string,aiVector3D>>& transform_chain
+) {
+ // first collapse any expanded transformation chains created by FBX import.
+ std::string node_name(node->mName.C_Str());
+ if (node_name.find(MAGIC_NODE_TAG) != std::string::npos) {
+ auto pos = node_name.find(MAGIC_NODE_TAG) + MAGIC_NODE_TAG.size() + 1;
+ std::string type_name = node_name.substr(pos);
+ auto elem = transform_types.find(type_name);
+ if (elem == transform_types.end()) {
+ // then this is a bug and should be fixed
+ std::stringstream err;
+ err << "unrecognized FBX transformation node";
+ err << " of type " << type_name << " in node " << node_name;
+ throw DeadlyExportError(err.str());
+ }
+ aiVector3D t, r, s;
+ node->mTransformation.Decompose(s, r, t);
+ switch (elem->second.second) {
+ case 'i': // inverse
+ // we don't need to worry about the inverse matrices
+ break;
+ case 't': // translation
+ transform_chain.emplace_back(elem->first, t);
+ break;
+ case 'r': // rotation
+ r *= float(DEG);
+ transform_chain.emplace_back(elem->first, r);
+ break;
+ case 's': // scale
+ transform_chain.emplace_back(elem->first, s);
+ break;
+ default:
+ // this should never happen
+ std::stringstream err;
+ err << "unrecognized FBX transformation type code: ";
+ err << elem->second.second;
+ throw DeadlyExportError(err.str());
+ }
+ // now continue on to any child nodes
+ for (unsigned i = 0; i < node->mNumChildren; ++i) {
+ WriteModelNodes(
+ outstream,
+ node->mChildren[i],
+ parent_uid,
+ limbnodes,
+ transform_chain
+ );
+ }
+ return;
+ }
+
+ int64_t node_uid = 0;
+ // generate uid and connect to parent, if not the root node,
+ if (node != mScene->mRootNode) {
+ auto elem = node_uids.find(node);
+ if (elem != node_uids.end()) {
+ node_uid = elem->second;
+ } else {
+ node_uid = generate_uid();
+ node_uids[node] = node_uid;
+ }
+ connections.emplace_back("C", "OO", node_uid, parent_uid);
+ }
+
+ // what type of node is this?
+ if (node == mScene->mRootNode) {
+ // handled later
+ } else if (node->mNumMeshes == 1) {
+ // connect to child mesh, which should have been written previously
+ connections.emplace_back(
+ "C", "OO", mesh_uids[node->mMeshes[0]], node_uid
+ );
+ // also connect to the material for the child mesh
+ connections.emplace_back(
+ "C", "OO",
+ material_uids[mScene->mMeshes[node->mMeshes[0]]->mMaterialIndex],
+ node_uid
+ );
+ // write model node
+ WriteModelNode(
+ outstream, binary, node, node_uid, "Mesh", transform_chain
+ );
+ } else if (limbnodes.count(node)) {
+ WriteModelNode(
+ outstream, binary, node, node_uid, "LimbNode", transform_chain
+ );
+ // we also need to write a nodeattribute to mark it as a skeleton
+ int64_t node_attribute_uid = generate_uid();
+ FBX::Node na("NodeAttribute");
+ na.AddProperties(
+ node_attribute_uid, FBX::SEPARATOR + "NodeAttribute", "LimbNode"
+ );
+ na.AddChild("TypeFlags", Property("Skeleton"));
+ na.Dump(outstream, binary, 1);
+ // and connect them
+ connections.emplace_back("C", "OO", node_attribute_uid, node_uid);
+ } else {
+ // generate a null node so we can add children to it
+ WriteModelNode(
+ outstream, binary, node, node_uid, "Null", transform_chain
+ );
+ }
+
+ // if more than one child mesh, make nodes for each mesh
+ if (node->mNumMeshes > 1 || node == mScene->mRootNode) {
+ for (size_t i = 0; i < node->mNumMeshes; ++i) {
+ // make a new model node
+ int64_t new_node_uid = generate_uid();
+ // connect to parent node
+ connections.emplace_back("C", "OO", new_node_uid, node_uid);
+ // connect to child mesh, which should have been written previously
+ connections.emplace_back(
+ "C", "OO", mesh_uids[node->mMeshes[i]], new_node_uid
+ );
+ // also connect to the material for the child mesh
+ connections.emplace_back(
+ "C", "OO",
+ material_uids[
+ mScene->mMeshes[node->mMeshes[i]]->mMaterialIndex
+ ],
+ new_node_uid
+ );
+ // write model node
+ FBX::Node m("Model");
+ // take name from mesh name, if it exists
+ std::string name = mScene->mMeshes[node->mMeshes[i]]->mName.C_Str();
+ name += FBX::SEPARATOR + "Model";
+ m.AddProperties(new_node_uid, name, "Mesh");
+ m.AddChild("Version", int32_t(232));
+ FBX::Node p("Properties70");
+ p.AddP70enum("InheritType", 1);
+ m.AddChild(p);
+ m.Dump(outstream, binary, 1);
+ }
+ }
+
+ // now recurse into children
+ for (size_t i = 0; i < node->mNumChildren; ++i) {
+ WriteModelNodes(
+ outstream, node->mChildren[i], node_uid, limbnodes
+ );
+ }
+}
+
+
+void FBXExporter::WriteAnimationCurveNode(
+ StreamWriterLE& outstream,
+ int64_t uid,
+ std::string name, // "T", "R", or "S"
+ aiVector3D default_value,
+ std::string property_name, // "Lcl Translation" etc
+ int64_t layer_uid,
+ int64_t node_uid
+) {
+ FBX::Node n("AnimationCurveNode");
+ n.AddProperties(uid, name + FBX::SEPARATOR + "AnimCurveNode", "");
+ FBX::Node p("Properties70");
+ p.AddP70numberA("d|X", default_value.x);
+ p.AddP70numberA("d|Y", default_value.y);
+ p.AddP70numberA("d|Z", default_value.z);
+ n.AddChild(p);
+ n.Dump(outstream, binary, 1);
+ // connect to layer
+ this->connections.emplace_back("C", "OO", uid, layer_uid);
+ // connect to bone
+ this->connections.emplace_back("C", "OP", uid, node_uid, property_name);
+}
+
+
+void FBXExporter::WriteAnimationCurve(
+ StreamWriterLE& outstream,
+ double default_value,
+ const std::vector<int64_t>& times,
+ const std::vector<float>& values,
+ int64_t curvenode_uid,
+ const std::string& property_link // "d|X", "d|Y", etc
+) {
+ FBX::Node n("AnimationCurve");
+ int64_t curve_uid = generate_uid();
+ n.AddProperties(curve_uid, FBX::SEPARATOR + "AnimCurve", "");
+ n.AddChild("Default", default_value);
+ n.AddChild("KeyVer", int32_t(4009));
+ n.AddChild("KeyTime", times);
+ n.AddChild("KeyValueFloat", values);
+ // TODO: keyattr flags and data (STUB for now)
+ n.AddChild("KeyAttrFlags", std::vector<int32_t>{0});
+ n.AddChild("KeyAttrDataFloat", std::vector<float>{0,0,0,0});
+ n.AddChild(
+ "KeyAttrRefCount",
+ std::vector<int32_t>{static_cast<int32_t>(times.size())}
+ );
+ n.Dump(outstream, binary, 1);
+ this->connections.emplace_back(
+ "C", "OP", curve_uid, curvenode_uid, property_link
+ );
+}
+
+
+void FBXExporter::WriteConnections ()
+{
+ // we should have completed the connection graph already,
+ // so basically just dump it here
+ if (!binary) {
+ WriteAsciiSectionHeader("Object connections");
+ }
+ // TODO: comments with names in the ascii version
+ FBX::Node conn("Connections");
+ StreamWriterLE outstream(outfile);
+ conn.Begin(outstream, binary, 0);
+ conn.BeginChildren(outstream, binary, 0);
+ for (auto &n : connections) {
+ n.Dump(outstream, binary, 1);
+ }
+ conn.End(outstream, binary, 0, !connections.empty());
+ connections.clear();
+}
+
+#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
+#endif // ASSIMP_BUILD_NO_EXPORT
diff --git a/thirdparty/assimp/code/FBXExporter.h b/thirdparty/assimp/code/FBXExporter.h
new file mode 100644
index 0000000000..71fb55c57f
--- /dev/null
+++ b/thirdparty/assimp/code/FBXExporter.h
@@ -0,0 +1,178 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file FBXExporter.h
+* Declares the exporter class to write a scene to an fbx file
+*/
+#ifndef AI_FBXEXPORTER_H_INC
+#define AI_FBXEXPORTER_H_INC
+
+#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
+
+#include "FBXExportNode.h" // FBX::Node
+#include "FBXCommon.h" // FBX::TransformInheritance
+
+#include <assimp/types.h>
+//#include <assimp/material.h>
+#include <assimp/StreamWriter.h> // StreamWriterLE
+#include <assimp/Exceptional.h> // DeadlyExportError
+
+#include <vector>
+#include <map>
+#include <unordered_set>
+#include <memory> // shared_ptr
+#include <sstream> // stringstream
+
+struct aiScene;
+struct aiNode;
+//struct aiMaterial;
+
+namespace Assimp
+{
+ class IOSystem;
+ class IOStream;
+ class ExportProperties;
+
+ // ---------------------------------------------------------------------
+ /** Helper class to export a given scene to an FBX file. */
+ // ---------------------------------------------------------------------
+ class FBXExporter
+ {
+ public:
+ /// Constructor for a specific scene to export
+ FBXExporter(const aiScene* pScene, const ExportProperties* pProperties);
+
+ // call one of these methods to export
+ void ExportBinary(const char* pFile, IOSystem* pIOSystem);
+ void ExportAscii(const char* pFile, IOSystem* pIOSystem);
+
+ private:
+ bool binary; // whether current export is in binary or ascii format
+ const aiScene* mScene; // the scene to export
+ const ExportProperties* mProperties; // currently unused
+ std::shared_ptr<IOStream> outfile; // file to write to
+
+ std::vector<FBX::Node> connections; // connection storage
+
+ std::vector<int64_t> mesh_uids;
+ std::vector<int64_t> material_uids;
+ std::map<const aiNode*,int64_t> node_uids;
+
+ // this crude unique-ID system is actually fine
+ int64_t last_uid = 999999;
+ int64_t generate_uid() { return ++last_uid; }
+
+ // binary files have a specific header and footer,
+ // in addition to the actual data
+ void WriteBinaryHeader();
+ void WriteBinaryFooter();
+
+ // ascii files have a comment at the top
+ void WriteAsciiHeader();
+
+ // WriteAllNodes does the actual export.
+ // It just calls all the Write<Section> methods below in order.
+ void WriteAllNodes();
+
+ // Methods to write individual sections.
+ // The order here matches the order inside an FBX file.
+ // Each method corresponds to a top-level FBX section,
+ // except WriteHeader which also includes some binary-only sections
+ // and WriteFooter which is binary data only.
+ void WriteHeaderExtension();
+ // WriteFileId(); // binary-only, included in WriteHeader
+ // WriteCreationTime(); // binary-only, included in WriteHeader
+ // WriteCreator(); // binary-only, included in WriteHeader
+ void WriteGlobalSettings();
+ void WriteDocuments();
+ void WriteReferences();
+ void WriteDefinitions();
+ void WriteObjects();
+ void WriteConnections();
+ // WriteTakes(); // deprecated since at least 2015 (fbx 7.4)
+
+ // helpers
+ void WriteAsciiSectionHeader(const std::string& title);
+ void WriteModelNodes(
+ Assimp::StreamWriterLE& s,
+ const aiNode* node,
+ int64_t parent_uid,
+ const std::unordered_set<const aiNode*>& limbnodes
+ );
+ void WriteModelNodes( // usually don't call this directly
+ StreamWriterLE& s,
+ const aiNode* node,
+ int64_t parent_uid,
+ const std::unordered_set<const aiNode*>& limbnodes,
+ std::vector<std::pair<std::string,aiVector3D>>& transform_chain
+ );
+ void WriteModelNode( // nor this
+ StreamWriterLE& s,
+ bool binary,
+ const aiNode* node,
+ int64_t node_uid,
+ const std::string& type,
+ const std::vector<std::pair<std::string,aiVector3D>>& xfm_chain,
+ FBX::TransformInheritance ti_type=FBX::TransformInheritance_RSrs
+ );
+ void WriteAnimationCurveNode(
+ StreamWriterLE& outstream,
+ int64_t uid,
+ std::string name, // "T", "R", or "S"
+ aiVector3D default_value,
+ std::string property_name, // "Lcl Translation" etc
+ int64_t animation_layer_uid,
+ int64_t node_uid
+ );
+ void WriteAnimationCurve(
+ StreamWriterLE& outstream,
+ double default_value,
+ const std::vector<int64_t>& times,
+ const std::vector<float>& values,
+ int64_t curvenode_id,
+ const std::string& property_link // "d|X", "d|Y", etc
+ );
+ };
+}
+
+#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
+
+#endif // AI_FBXEXPORTER_H_INC
diff --git a/thirdparty/assimp/code/FBXImportSettings.h b/thirdparty/assimp/code/FBXImportSettings.h
new file mode 100644
index 0000000000..d5e1c20608
--- /dev/null
+++ b/thirdparty/assimp/code/FBXImportSettings.h
@@ -0,0 +1,153 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file FBXImportSettings.h
+ * @brief FBX importer runtime configuration
+ */
+#ifndef INCLUDED_AI_FBX_IMPORTSETTINGS_H
+#define INCLUDED_AI_FBX_IMPORTSETTINGS_H
+
+namespace Assimp {
+namespace FBX {
+
+/** FBX import settings, parts of which are publicly accessible via their corresponding AI_CONFIG constants */
+struct ImportSettings
+{
+ ImportSettings()
+ : strictMode(true)
+ , readAllLayers(true)
+ , readAllMaterials(false)
+ , readMaterials(true)
+ , readTextures(true)
+ , readCameras(true)
+ , readLights(true)
+ , readAnimations(true)
+ , readWeights(true)
+ , preservePivots(true)
+ , optimizeEmptyAnimationCurves(true)
+ , useLegacyEmbeddedTextureNaming(false)
+ {}
+
+
+ /** enable strict mode:
+ * - only accept fbx 2012, 2013 files
+ * - on the slightest error, give up.
+ *
+ * Basically, strict mode means that the fbx file will actually
+ * be validated. Strict mode is off by default. */
+ bool strictMode;
+
+ /** specifies whether all geometry layers are read and scanned for
+ * usable data channels. The FBX spec indicates that many readers
+ * will only read the first channel and that this is in some way
+ * the recommended way- in reality, however, it happens a lot that
+ * vertex data is spread among multiple layers. The default
+ * value for this option is true.*/
+ bool readAllLayers;
+
+ /** specifies whether all materials are read, or only those that
+ * are referenced by at least one mesh. Reading all materials
+ * may make FBX reading a lot slower since all objects
+ * need to be processed .
+ * This bit is ignored unless readMaterials=true*/
+ bool readAllMaterials;
+
+
+ /** import materials (true) or skip them and assign a default
+ * material. The default value is true.*/
+ bool readMaterials;
+
+ /** import embedded textures? Default value is true.*/
+ bool readTextures;
+
+ /** import cameras? Default value is true.*/
+ bool readCameras;
+
+ /** import light sources? Default value is true.*/
+ bool readLights;
+
+ /** import animations (i.e. animation curves, the node
+ * skeleton is always imported). Default value is true. */
+ bool readAnimations;
+
+ /** read bones (vertex weights and deform info).
+ * Default value is true. */
+ bool readWeights;
+
+ /** preserve transformation pivots and offsets. Since these can
+ * not directly be represented in assimp, additional dummy
+ * nodes will be generated. Note that settings this to false
+ * can make animation import a lot slower. The default value
+ * is true.
+ *
+ * The naming scheme for the generated nodes is:
+ * <OriginalName>_$AssimpFbx$_<TransformName>
+ *
+ * where <TransformName> is one of
+ * RotationPivot
+ * RotationOffset
+ * PreRotation
+ * PostRotation
+ * ScalingPivot
+ * ScalingOffset
+ * Translation
+ * Scaling
+ * Rotation
+ **/
+ bool preservePivots;
+
+ /** do not import animation curves that specify a constant
+ * values matching the corresponding node transformation.
+ * The default value is true. */
+ bool optimizeEmptyAnimationCurves;
+
+ /** use legacy naming for embedded textures eg: (*0, *1, *2)
+ **/
+ bool useLegacyEmbeddedTextureNaming;
+};
+
+
+} // !FBX
+} // !Assimp
+
+#endif
+
diff --git a/thirdparty/assimp/code/FBXImporter.cpp b/thirdparty/assimp/code/FBXImporter.cpp
new file mode 100644
index 0000000000..2cc8bffc29
--- /dev/null
+++ b/thirdparty/assimp/code/FBXImporter.cpp
@@ -0,0 +1,197 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+r
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file FBXImporter.cpp
+ * @brief Implementation of the FBX importer.
+ */
+
+#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
+
+#include "FBXImporter.h"
+
+#include "FBXTokenizer.h"
+#include "FBXParser.h"
+#include "FBXUtil.h"
+#include "FBXDocument.h"
+#include "FBXConverter.h"
+
+#include <assimp/StreamReader.h>
+#include <assimp/MemoryIOWrapper.h>
+#include <assimp/Importer.hpp>
+#include <assimp/importerdesc.h>
+
+namespace Assimp {
+
+template<>
+const char* LogFunctions<FBXImporter>::Prefix() {
+ static auto prefix = "FBX: ";
+ return prefix;
+}
+
+}
+
+using namespace Assimp;
+using namespace Assimp::Formatter;
+using namespace Assimp::FBX;
+
+namespace {
+
+static const aiImporterDesc desc = {
+ "Autodesk FBX Importer",
+ "",
+ "",
+ "",
+ aiImporterFlags_SupportTextFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "fbx"
+};
+}
+
+// ------------------------------------------------------------------------------------------------
+// Constructor to be privately used by #Importer
+FBXImporter::FBXImporter()
+{
+}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor, private as well
+FBXImporter::~FBXImporter()
+{
+}
+
+// ------------------------------------------------------------------------------------------------
+// Returns whether the class can handle the format of the given file.
+bool FBXImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
+{
+ const std::string& extension = GetExtension(pFile);
+ if (extension == std::string( desc.mFileExtensions ) ) {
+ return true;
+ }
+
+ else if ((!extension.length() || checkSig) && pIOHandler) {
+ // at least ASCII-FBX files usually have a 'FBX' somewhere in their head
+ const char* tokens[] = {"fbx"};
+ return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
+ }
+ return false;
+}
+
+// ------------------------------------------------------------------------------------------------
+// List all extensions handled by this loader
+const aiImporterDesc* FBXImporter::GetInfo () const
+{
+ return &desc;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Setup configuration properties for the loader
+void FBXImporter::SetupProperties(const Importer* pImp)
+{
+ settings.readAllLayers = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_GEOMETRY_LAYERS, true);
+ settings.readAllMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_MATERIALS, false);
+ settings.readMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_MATERIALS, true);
+ settings.readTextures = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_TEXTURES, true);
+ settings.readCameras = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_CAMERAS, true);
+ settings.readLights = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_LIGHTS, true);
+ settings.readAnimations = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ANIMATIONS, true);
+ settings.strictMode = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_STRICT_MODE, false);
+ settings.preservePivots = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, true);
+ settings.optimizeEmptyAnimationCurves = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES, true);
+ settings.useLegacyEmbeddedTextureNaming = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING, false);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Imports the given file into the given scene structure.
+void FBXImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
+{
+ std::unique_ptr<IOStream> stream(pIOHandler->Open(pFile,"rb"));
+ if (!stream) {
+ ThrowException("Could not open file for reading");
+ }
+
+ // read entire file into memory - no streaming for this, fbx
+ // files can grow large, but the assimp output data structure
+ // then becomes very large, too. Assimp doesn't support
+ // streaming for its output data structures so the net win with
+ // streaming input data would be very low.
+ std::vector<char> contents;
+ contents.resize(stream->FileSize()+1);
+ stream->Read( &*contents.begin(), 1, contents.size()-1 );
+ contents[ contents.size() - 1 ] = 0;
+ const char* const begin = &*contents.begin();
+
+ // broadphase tokenizing pass in which we identify the core
+ // syntax elements of FBX (brackets, commas, key:value mappings)
+ TokenList tokens;
+ try {
+
+ bool is_binary = false;
+ if (!strncmp(begin,"Kaydara FBX Binary",18)) {
+ is_binary = true;
+ TokenizeBinary(tokens,begin,static_cast<unsigned int>(contents.size()));
+ }
+ else {
+ Tokenize(tokens,begin);
+ }
+
+ // use this information to construct a very rudimentary
+ // parse-tree representing the FBX scope structure
+ Parser parser(tokens, is_binary);
+
+ // take the raw parse-tree and convert it to a FBX DOM
+ Document doc(parser,settings);
+
+ // convert the FBX DOM to aiScene
+ ConvertToAssimpScene(pScene,doc);
+
+ std::for_each(tokens.begin(),tokens.end(),Util::delete_fun<Token>());
+ }
+ catch(std::exception&) {
+ std::for_each(tokens.begin(),tokens.end(),Util::delete_fun<Token>());
+ throw;
+ }
+}
+
+#endif // !ASSIMP_BUILD_NO_FBX_IMPORTER
diff --git a/thirdparty/assimp/code/FBXImporter.h b/thirdparty/assimp/code/FBXImporter.h
new file mode 100644
index 0000000000..c365b2cddf
--- /dev/null
+++ b/thirdparty/assimp/code/FBXImporter.h
@@ -0,0 +1,100 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file FBXImporter.h
+ * @brief Declaration of the FBX main importer class
+ */
+#ifndef INCLUDED_AI_FBX_IMPORTER_H
+#define INCLUDED_AI_FBX_IMPORTER_H
+
+#include <assimp/BaseImporter.h>
+#include <assimp/LogAux.h>
+
+#include "FBXImportSettings.h"
+
+namespace Assimp {
+
+// TinyFormatter.h
+namespace Formatter {
+ template <typename T,typename TR, typename A> class basic_formatter;
+ typedef class basic_formatter< char, std::char_traits<char>, std::allocator<char> > format;
+}
+
+// -------------------------------------------------------------------------------------------
+/** Load the Autodesk FBX file format.
+
+ See http://en.wikipedia.org/wiki/FBX
+*/
+// -------------------------------------------------------------------------------------------
+class FBXImporter : public BaseImporter, public LogFunctions<FBXImporter>
+{
+public:
+ FBXImporter();
+ virtual ~FBXImporter();
+
+ // --------------------
+ bool CanRead( const std::string& pFile,
+ IOSystem* pIOHandler,
+ bool checkSig
+ ) const;
+
+protected:
+
+ // --------------------
+ const aiImporterDesc* GetInfo () const;
+
+ // --------------------
+ void SetupProperties(const Importer* pImp);
+
+ // --------------------
+ void InternReadFile( const std::string& pFile,
+ aiScene* pScene,
+ IOSystem* pIOHandler
+ );
+
+private:
+ FBX::ImportSettings settings;
+}; // !class FBXImporter
+
+} // end of namespace Assimp
+#endif // !INCLUDED_AI_FBX_IMPORTER_H
+
diff --git a/thirdparty/assimp/code/FBXMaterial.cpp b/thirdparty/assimp/code/FBXMaterial.cpp
new file mode 100644
index 0000000000..f16f134404
--- /dev/null
+++ b/thirdparty/assimp/code/FBXMaterial.cpp
@@ -0,0 +1,381 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file FBXMaterial.cpp
+ * @brief Assimp::FBX::Material and Assimp::FBX::Texture implementation
+ */
+
+#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
+
+#include "FBXParser.h"
+#include "FBXDocument.h"
+#include "FBXImporter.h"
+#include "FBXImportSettings.h"
+#include "FBXDocumentUtil.h"
+#include "FBXProperties.h"
+#include <assimp/ByteSwapper.h>
+
+#include <algorithm> // std::transform
+#include "FBXUtil.h"
+
+namespace Assimp {
+namespace FBX {
+
+ using namespace Util;
+
+// ------------------------------------------------------------------------------------------------
+Material::Material(uint64_t id, const Element& element, const Document& doc, const std::string& name)
+: Object(id,element,name)
+{
+ const Scope& sc = GetRequiredScope(element);
+
+ const Element* const ShadingModel = sc["ShadingModel"];
+ const Element* const MultiLayer = sc["MultiLayer"];
+
+ if(MultiLayer) {
+ multilayer = !!ParseTokenAsInt(GetRequiredToken(*MultiLayer,0));
+ }
+
+ if(ShadingModel) {
+ shading = ParseTokenAsString(GetRequiredToken(*ShadingModel,0));
+ }
+ else {
+ DOMWarning("shading mode not specified, assuming phong",&element);
+ shading = "phong";
+ }
+
+ std::string templateName;
+
+ // lower-case shading because Blender (for example) writes "Phong"
+ std::transform(shading.begin(), shading.end(), shading.begin(), ::tolower);
+ if(shading == "phong") {
+ templateName = "Material.FbxSurfacePhong";
+ }
+ else if(shading == "lambert") {
+ templateName = "Material.FbxSurfaceLambert";
+ }
+ else {
+ DOMWarning("shading mode not recognized: " + shading,&element);
+ }
+
+ props = GetPropertyTable(doc,templateName,element,sc);
+
+ // resolve texture links
+ const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID());
+ for(const Connection* con : conns) {
+
+ // texture link to properties, not objects
+ if (!con->PropertyName().length()) {
+ continue;
+ }
+
+ const Object* const ob = con->SourceObject();
+ if(!ob) {
+ DOMWarning("failed to read source object for texture link, ignoring",&element);
+ continue;
+ }
+
+ const Texture* const tex = dynamic_cast<const Texture*>(ob);
+ if(!tex) {
+ const LayeredTexture* const layeredTexture = dynamic_cast<const LayeredTexture*>(ob);
+ if(!layeredTexture) {
+ DOMWarning("source object for texture link is not a texture or layered texture, ignoring",&element);
+ continue;
+ }
+ const std::string& prop = con->PropertyName();
+ if (layeredTextures.find(prop) != layeredTextures.end()) {
+ DOMWarning("duplicate layered texture link: " + prop,&element);
+ }
+
+ layeredTextures[prop] = layeredTexture;
+ ((LayeredTexture*)layeredTexture)->fillTexture(doc);
+ }
+ else
+ {
+ const std::string& prop = con->PropertyName();
+ if (textures.find(prop) != textures.end()) {
+ DOMWarning("duplicate texture link: " + prop,&element);
+ }
+
+ textures[prop] = tex;
+ }
+
+ }
+}
+
+
+// ------------------------------------------------------------------------------------------------
+Material::~Material()
+{
+}
+
+
+// ------------------------------------------------------------------------------------------------
+Texture::Texture(uint64_t id, const Element& element, const Document& doc, const std::string& name)
+: Object(id,element,name)
+, uvScaling(1.0f,1.0f)
+, media(0)
+{
+ const Scope& sc = GetRequiredScope(element);
+
+ const Element* const Type = sc["Type"];
+ const Element* const FileName = sc["FileName"];
+ const Element* const RelativeFilename = sc["RelativeFilename"];
+ const Element* const ModelUVTranslation = sc["ModelUVTranslation"];
+ const Element* const ModelUVScaling = sc["ModelUVScaling"];
+ const Element* const Texture_Alpha_Source = sc["Texture_Alpha_Source"];
+ const Element* const Cropping = sc["Cropping"];
+
+ if(Type) {
+ type = ParseTokenAsString(GetRequiredToken(*Type,0));
+ }
+
+ if(FileName) {
+ fileName = ParseTokenAsString(GetRequiredToken(*FileName,0));
+ }
+
+ if(RelativeFilename) {
+ relativeFileName = ParseTokenAsString(GetRequiredToken(*RelativeFilename,0));
+ }
+
+ if(ModelUVTranslation) {
+ uvTrans = aiVector2D(ParseTokenAsFloat(GetRequiredToken(*ModelUVTranslation,0)),
+ ParseTokenAsFloat(GetRequiredToken(*ModelUVTranslation,1))
+ );
+ }
+
+ if(ModelUVScaling) {
+ uvScaling = aiVector2D(ParseTokenAsFloat(GetRequiredToken(*ModelUVScaling,0)),
+ ParseTokenAsFloat(GetRequiredToken(*ModelUVScaling,1))
+ );
+ }
+
+ if(Cropping) {
+ crop[0] = ParseTokenAsInt(GetRequiredToken(*Cropping,0));
+ crop[1] = ParseTokenAsInt(GetRequiredToken(*Cropping,1));
+ crop[2] = ParseTokenAsInt(GetRequiredToken(*Cropping,2));
+ crop[3] = ParseTokenAsInt(GetRequiredToken(*Cropping,3));
+ }
+ else {
+ // vc8 doesn't support the crop() syntax in initialization lists
+ // (and vc9 WARNS about the new (i.e. compliant) behaviour).
+ crop[0] = crop[1] = crop[2] = crop[3] = 0;
+ }
+
+ if(Texture_Alpha_Source) {
+ alphaSource = ParseTokenAsString(GetRequiredToken(*Texture_Alpha_Source,0));
+ }
+
+ props = GetPropertyTable(doc,"Texture.FbxFileTexture",element,sc);
+
+ // 3DS Max and FBX SDK use "Scaling" and "Translation" instead of "ModelUVScaling" and "ModelUVTranslation". Use these properties if available.
+ bool ok;
+ const aiVector3D& scaling = PropertyGet<aiVector3D>(*props, "Scaling", ok);
+ if (ok) {
+ uvScaling.x = scaling.x;
+ uvScaling.y = scaling.y;
+ }
+
+ const aiVector3D& trans = PropertyGet<aiVector3D>(*props, "Translation", ok);
+ if (ok) {
+ uvTrans.x = trans.x;
+ uvTrans.y = trans.y;
+ }
+
+ // resolve video links
+ if(doc.Settings().readTextures) {
+ const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID());
+ for(const Connection* con : conns) {
+ const Object* const ob = con->SourceObject();
+ if(!ob) {
+ DOMWarning("failed to read source object for texture link, ignoring",&element);
+ continue;
+ }
+
+ const Video* const video = dynamic_cast<const Video*>(ob);
+ if(video) {
+ media = video;
+ }
+ }
+ }
+}
+
+
+Texture::~Texture()
+{
+
+}
+
+LayeredTexture::LayeredTexture(uint64_t id, const Element& element, const Document& /*doc*/, const std::string& name)
+: Object(id,element,name)
+,blendMode(BlendMode_Modulate)
+,alpha(1)
+{
+ const Scope& sc = GetRequiredScope(element);
+
+ const Element* const BlendModes = sc["BlendModes"];
+ const Element* const Alphas = sc["Alphas"];
+
+
+ if(BlendModes!=0)
+ {
+ blendMode = (BlendMode)ParseTokenAsInt(GetRequiredToken(*BlendModes,0));
+ }
+ if(Alphas!=0)
+ {
+ alpha = ParseTokenAsFloat(GetRequiredToken(*Alphas,0));
+ }
+}
+
+LayeredTexture::~LayeredTexture()
+{
+
+}
+
+void LayeredTexture::fillTexture(const Document& doc)
+{
+ const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID());
+ for(size_t i = 0; i < conns.size();++i)
+ {
+ const Connection* con = conns.at(i);
+
+ const Object* const ob = con->SourceObject();
+ if(!ob) {
+ DOMWarning("failed to read source object for texture link, ignoring",&element);
+ continue;
+ }
+
+ const Texture* const tex = dynamic_cast<const Texture*>(ob);
+
+ textures.push_back(tex);
+ }
+}
+
+
+// ------------------------------------------------------------------------------------------------
+Video::Video(uint64_t id, const Element& element, const Document& doc, const std::string& name)
+: Object(id,element,name)
+, contentLength(0)
+, content(0)
+{
+ const Scope& sc = GetRequiredScope(element);
+
+ const Element* const Type = sc["Type"];
+ const Element* const FileName = sc.FindElementCaseInsensitive("FileName"); //some files retain the information as "Filename", others "FileName", who knows
+ const Element* const RelativeFilename = sc["RelativeFilename"];
+ const Element* const Content = sc["Content"];
+
+ if(Type) {
+ type = ParseTokenAsString(GetRequiredToken(*Type,0));
+ }
+
+ if(FileName) {
+ fileName = ParseTokenAsString(GetRequiredToken(*FileName,0));
+ }
+
+ if(RelativeFilename) {
+ relativeFileName = ParseTokenAsString(GetRequiredToken(*RelativeFilename,0));
+ }
+
+ if(Content) {
+ //this field is omitted when the embedded texture is already loaded, let's ignore if it's not found
+ try {
+ const Token& token = GetRequiredToken(*Content, 0);
+ const char* data = token.begin();
+ if (!token.IsBinary()) {
+ if (*data != '"') {
+ DOMError("embedded content is not surrounded by quotation marks", &element);
+ }
+ else {
+ const char* encodedData = data + 1;
+ size_t encodedDataLen = static_cast<size_t>(token.end() - token.begin());
+ // search for last quotation mark
+ while (encodedDataLen > 1 && encodedData[encodedDataLen] != '"')
+ encodedDataLen--;
+ if (encodedDataLen % 4 != 0) {
+ DOMError("embedded content is invalid, needs to be in base64", &element);
+ }
+ else {
+ contentLength = Util::DecodeBase64(encodedData, encodedDataLen, content);
+ }
+ }
+ }
+ else if (static_cast<size_t>(token.end() - data) < 5) {
+ DOMError("binary data array is too short, need five (5) bytes for type signature and element count", &element);
+ }
+ else if (*data != 'R') {
+ DOMWarning("video content is not raw binary data, ignoring", &element);
+ }
+ else {
+ // read number of elements
+ uint32_t len = 0;
+ ::memcpy(&len, data + 1, sizeof(len));
+ AI_SWAP4(len);
+
+ contentLength = len;
+
+ content = new uint8_t[len];
+ ::memcpy(content, data + 5, len);
+ }
+ } catch (const runtime_error& runtimeError)
+ {
+ //we don't need the content data for contents that has already been loaded
+ ASSIMP_LOG_DEBUG_F("Caught exception in FBXMaterial (likely because content was already loaded): ",
+ runtimeError.what());
+ }
+ }
+
+ props = GetPropertyTable(doc,"Video.FbxVideo",element,sc);
+}
+
+
+Video::~Video()
+{
+ if(content) {
+ delete[] content;
+ }
+}
+
+} //!FBX
+} //!Assimp
+
+#endif
diff --git a/thirdparty/assimp/code/FBXMeshGeometry.cpp b/thirdparty/assimp/code/FBXMeshGeometry.cpp
new file mode 100644
index 0000000000..d75476b826
--- /dev/null
+++ b/thirdparty/assimp/code/FBXMeshGeometry.cpp
@@ -0,0 +1,711 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file FBXMeshGeometry.cpp
+ * @brief Assimp::FBX::MeshGeometry implementation
+ */
+
+#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
+
+#include <functional>
+
+#include "FBXMeshGeometry.h"
+#include "FBXDocument.h"
+#include "FBXImporter.h"
+#include "FBXImportSettings.h"
+#include "FBXDocumentUtil.h"
+
+
+namespace Assimp {
+namespace FBX {
+
+using namespace Util;
+
+// ------------------------------------------------------------------------------------------------
+Geometry::Geometry(uint64_t id, const Element& element, const std::string& name, const Document& doc)
+ : Object(id, element, name)
+ , skin()
+{
+ const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"Deformer");
+ for(const Connection* con : conns) {
+ const Skin* const sk = ProcessSimpleConnection<Skin>(*con, false, "Skin -> Geometry", element);
+ if(sk) {
+ skin = sk;
+ }
+ const BlendShape* const bsp = ProcessSimpleConnection<BlendShape>(*con, false, "BlendShape -> Geometry", element);
+ if (bsp) {
+ blendShapes.push_back(bsp);
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+Geometry::~Geometry()
+{
+ // empty
+}
+
+// ------------------------------------------------------------------------------------------------
+const std::vector<const BlendShape*>& Geometry::GetBlendShapes() const {
+ return blendShapes;
+}
+
+// ------------------------------------------------------------------------------------------------
+const Skin* Geometry::DeformerSkin() const {
+ return skin;
+}
+
+// ------------------------------------------------------------------------------------------------
+MeshGeometry::MeshGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc)
+: Geometry(id, element,name, doc)
+{
+ const Scope* sc = element.Compound();
+ if (!sc) {
+ DOMError("failed to read Geometry object (class: Mesh), no data scope found");
+ }
+
+ // must have Mesh elements:
+ const Element& Vertices = GetRequiredElement(*sc,"Vertices",&element);
+ const Element& PolygonVertexIndex = GetRequiredElement(*sc,"PolygonVertexIndex",&element);
+
+ // optional Mesh elements:
+ const ElementCollection& Layer = sc->GetCollection("Layer");
+
+ std::vector<aiVector3D> tempVerts;
+ ParseVectorDataArray(tempVerts,Vertices);
+
+ if(tempVerts.empty()) {
+ FBXImporter::LogWarn("encountered mesh with no vertices");
+ return;
+ }
+
+ std::vector<int> tempFaces;
+ ParseVectorDataArray(tempFaces,PolygonVertexIndex);
+
+ if(tempFaces.empty()) {
+ FBXImporter::LogWarn("encountered mesh with no faces");
+ return;
+ }
+
+ m_vertices.reserve(tempFaces.size());
+ m_faces.reserve(tempFaces.size() / 3);
+
+ m_mapping_offsets.resize(tempVerts.size());
+ m_mapping_counts.resize(tempVerts.size(),0);
+ m_mappings.resize(tempFaces.size());
+
+ const size_t vertex_count = tempVerts.size();
+
+ // generate output vertices, computing an adjacency table to
+ // preserve the mapping from fbx indices to *this* indexing.
+ unsigned int count = 0;
+ for(int index : tempFaces) {
+ const int absi = index < 0 ? (-index - 1) : index;
+ if(static_cast<size_t>(absi) >= vertex_count) {
+ DOMError("polygon vertex index out of range",&PolygonVertexIndex);
+ }
+
+ m_vertices.push_back(tempVerts[absi]);
+ ++count;
+
+ ++m_mapping_counts[absi];
+
+ if (index < 0) {
+ m_faces.push_back(count);
+ count = 0;
+ }
+ }
+
+ unsigned int cursor = 0;
+ for (size_t i = 0, e = tempVerts.size(); i < e; ++i) {
+ m_mapping_offsets[i] = cursor;
+ cursor += m_mapping_counts[i];
+
+ m_mapping_counts[i] = 0;
+ }
+
+ cursor = 0;
+ for(int index : tempFaces) {
+ const int absi = index < 0 ? (-index - 1) : index;
+ m_mappings[m_mapping_offsets[absi] + m_mapping_counts[absi]++] = cursor++;
+ }
+
+ // if settings.readAllLayers is true:
+ // * read all layers, try to load as many vertex channels as possible
+ // if settings.readAllLayers is false:
+ // * read only the layer with index 0, but warn about any further layers
+ for (ElementMap::const_iterator it = Layer.first; it != Layer.second; ++it) {
+ const TokenList& tokens = (*it).second->Tokens();
+
+ const char* err;
+ const int index = ParseTokenAsInt(*tokens[0], err);
+ if(err) {
+ DOMError(err,&element);
+ }
+
+ if(doc.Settings().readAllLayers || index == 0) {
+ const Scope& layer = GetRequiredScope(*(*it).second);
+ ReadLayer(layer);
+ }
+ else {
+ FBXImporter::LogWarn("ignoring additional geometry layers");
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+MeshGeometry::~MeshGeometry() {
+ // empty
+}
+
+// ------------------------------------------------------------------------------------------------
+const std::vector<aiVector3D>& MeshGeometry::GetVertices() const {
+ return m_vertices;
+}
+
+// ------------------------------------------------------------------------------------------------
+const std::vector<aiVector3D>& MeshGeometry::GetNormals() const {
+ return m_normals;
+}
+
+// ------------------------------------------------------------------------------------------------
+const std::vector<aiVector3D>& MeshGeometry::GetTangents() const {
+ return m_tangents;
+}
+
+// ------------------------------------------------------------------------------------------------
+const std::vector<aiVector3D>& MeshGeometry::GetBinormals() const {
+ return m_binormals;
+}
+
+// ------------------------------------------------------------------------------------------------
+const std::vector<unsigned int>& MeshGeometry::GetFaceIndexCounts() const {
+ return m_faces;
+}
+
+// ------------------------------------------------------------------------------------------------
+const std::vector<aiVector2D>& MeshGeometry::GetTextureCoords( unsigned int index ) const {
+ static const std::vector<aiVector2D> empty;
+ return index >= AI_MAX_NUMBER_OF_TEXTURECOORDS ? empty : m_uvs[ index ];
+}
+
+std::string MeshGeometry::GetTextureCoordChannelName( unsigned int index ) const {
+ return index >= AI_MAX_NUMBER_OF_TEXTURECOORDS ? "" : m_uvNames[ index ];
+}
+
+const std::vector<aiColor4D>& MeshGeometry::GetVertexColors( unsigned int index ) const {
+ static const std::vector<aiColor4D> empty;
+ return index >= AI_MAX_NUMBER_OF_COLOR_SETS ? empty : m_colors[ index ];
+}
+
+const MatIndexArray& MeshGeometry::GetMaterialIndices() const {
+ return m_materials;
+}
+// ------------------------------------------------------------------------------------------------
+const unsigned int* MeshGeometry::ToOutputVertexIndex( unsigned int in_index, unsigned int& count ) const {
+ if ( in_index >= m_mapping_counts.size() ) {
+ return NULL;
+ }
+
+ ai_assert( m_mapping_counts.size() == m_mapping_offsets.size() );
+ count = m_mapping_counts[ in_index ];
+
+ ai_assert( m_mapping_offsets[ in_index ] + count <= m_mappings.size() );
+
+ return &m_mappings[ m_mapping_offsets[ in_index ] ];
+}
+
+// ------------------------------------------------------------------------------------------------
+unsigned int MeshGeometry::FaceForVertexIndex( unsigned int in_index ) const {
+ ai_assert( in_index < m_vertices.size() );
+
+ // in the current conversion pattern this will only be needed if
+ // weights are present, so no need to always pre-compute this table
+ if ( m_facesVertexStartIndices.empty() ) {
+ m_facesVertexStartIndices.resize( m_faces.size() + 1, 0 );
+
+ std::partial_sum( m_faces.begin(), m_faces.end(), m_facesVertexStartIndices.begin() + 1 );
+ m_facesVertexStartIndices.pop_back();
+ }
+
+ ai_assert( m_facesVertexStartIndices.size() == m_faces.size() );
+ const std::vector<unsigned int>::iterator it = std::upper_bound(
+ m_facesVertexStartIndices.begin(),
+ m_facesVertexStartIndices.end(),
+ in_index
+ );
+
+ return static_cast< unsigned int >( std::distance( m_facesVertexStartIndices.begin(), it - 1 ) );
+}
+
+// ------------------------------------------------------------------------------------------------
+void MeshGeometry::ReadLayer(const Scope& layer)
+{
+ const ElementCollection& LayerElement = layer.GetCollection("LayerElement");
+ for (ElementMap::const_iterator eit = LayerElement.first; eit != LayerElement.second; ++eit) {
+ const Scope& elayer = GetRequiredScope(*(*eit).second);
+
+ ReadLayerElement(elayer);
+ }
+}
+
+
+// ------------------------------------------------------------------------------------------------
+void MeshGeometry::ReadLayerElement(const Scope& layerElement)
+{
+ const Element& Type = GetRequiredElement(layerElement,"Type");
+ const Element& TypedIndex = GetRequiredElement(layerElement,"TypedIndex");
+
+ const std::string& type = ParseTokenAsString(GetRequiredToken(Type,0));
+ const int typedIndex = ParseTokenAsInt(GetRequiredToken(TypedIndex,0));
+
+ const Scope& top = GetRequiredScope(element);
+ const ElementCollection candidates = top.GetCollection(type);
+
+ for (ElementMap::const_iterator it = candidates.first; it != candidates.second; ++it) {
+ const int index = ParseTokenAsInt(GetRequiredToken(*(*it).second,0));
+ if(index == typedIndex) {
+ ReadVertexData(type,typedIndex,GetRequiredScope(*(*it).second));
+ return;
+ }
+ }
+
+ FBXImporter::LogError(Formatter::format("failed to resolve vertex layer element: ")
+ << type << ", index: " << typedIndex);
+}
+
+// ------------------------------------------------------------------------------------------------
+void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scope& source)
+{
+ const std::string& MappingInformationType = ParseTokenAsString(GetRequiredToken(
+ GetRequiredElement(source,"MappingInformationType"),0)
+ );
+
+ const std::string& ReferenceInformationType = ParseTokenAsString(GetRequiredToken(
+ GetRequiredElement(source,"ReferenceInformationType"),0)
+ );
+
+ if (type == "LayerElementUV") {
+ if(index >= AI_MAX_NUMBER_OF_TEXTURECOORDS) {
+ FBXImporter::LogError(Formatter::format("ignoring UV layer, maximum number of UV channels exceeded: ")
+ << index << " (limit is " << AI_MAX_NUMBER_OF_TEXTURECOORDS << ")" );
+ return;
+ }
+
+ const Element* Name = source["Name"];
+ m_uvNames[index] = "";
+ if(Name) {
+ m_uvNames[index] = ParseTokenAsString(GetRequiredToken(*Name,0));
+ }
+
+ ReadVertexDataUV(m_uvs[index],source,
+ MappingInformationType,
+ ReferenceInformationType
+ );
+ }
+ else if (type == "LayerElementMaterial") {
+ if (m_materials.size() > 0) {
+ FBXImporter::LogError("ignoring additional material layer");
+ return;
+ }
+
+ std::vector<int> temp_materials;
+
+ ReadVertexDataMaterials(temp_materials,source,
+ MappingInformationType,
+ ReferenceInformationType
+ );
+
+ // sometimes, there will be only negative entries. Drop the material
+ // layer in such a case (I guess it means a default material should
+ // be used). This is what the converter would do anyway, and it
+ // avoids losing the material if there are more material layers
+ // coming of which at least one contains actual data (did observe
+ // that with one test file).
+ const size_t count_neg = std::count_if(temp_materials.begin(),temp_materials.end(),[](int n) { return n < 0; });
+ if(count_neg == temp_materials.size()) {
+ FBXImporter::LogWarn("ignoring dummy material layer (all entries -1)");
+ return;
+ }
+
+ std::swap(temp_materials, m_materials);
+ }
+ else if (type == "LayerElementNormal") {
+ if (m_normals.size() > 0) {
+ FBXImporter::LogError("ignoring additional normal layer");
+ return;
+ }
+
+ ReadVertexDataNormals(m_normals,source,
+ MappingInformationType,
+ ReferenceInformationType
+ );
+ }
+ else if (type == "LayerElementTangent") {
+ if (m_tangents.size() > 0) {
+ FBXImporter::LogError("ignoring additional tangent layer");
+ return;
+ }
+
+ ReadVertexDataTangents(m_tangents,source,
+ MappingInformationType,
+ ReferenceInformationType
+ );
+ }
+ else if (type == "LayerElementBinormal") {
+ if (m_binormals.size() > 0) {
+ FBXImporter::LogError("ignoring additional binormal layer");
+ return;
+ }
+
+ ReadVertexDataBinormals(m_binormals,source,
+ MappingInformationType,
+ ReferenceInformationType
+ );
+ }
+ else if (type == "LayerElementColor") {
+ if(index >= AI_MAX_NUMBER_OF_COLOR_SETS) {
+ FBXImporter::LogError(Formatter::format("ignoring vertex color layer, maximum number of color sets exceeded: ")
+ << index << " (limit is " << AI_MAX_NUMBER_OF_COLOR_SETS << ")" );
+ return;
+ }
+
+ ReadVertexDataColors(m_colors[index],source,
+ MappingInformationType,
+ ReferenceInformationType
+ );
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Lengthy utility function to read and resolve a FBX vertex data array - that is, the
+// output is in polygon vertex order. This logic is used for reading normals, UVs, colors,
+// tangents ..
+template <typename T>
+void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
+ const std::string& MappingInformationType,
+ const std::string& ReferenceInformationType,
+ const char* dataElementName,
+ const char* indexDataElementName,
+ size_t vertex_count,
+ const std::vector<unsigned int>& mapping_counts,
+ const std::vector<unsigned int>& mapping_offsets,
+ const std::vector<unsigned int>& mappings)
+{
+ bool isDirect = ReferenceInformationType == "Direct";
+ bool isIndexToDirect = ReferenceInformationType == "IndexToDirect";
+
+ // fall-back to direct data if there is no index data element
+ if ( isIndexToDirect && !HasElement( source, indexDataElementName ) ) {
+ isDirect = true;
+ isIndexToDirect = false;
+ }
+
+ // handle permutations of Mapping and Reference type - it would be nice to
+ // deal with this more elegantly and with less redundancy, but right
+ // now it seems unavoidable.
+ if (MappingInformationType == "ByVertice" && isDirect) {
+ if (!HasElement(source, dataElementName)) {
+ return;
+ }
+ std::vector<T> tempData;
+ ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
+
+ data_out.resize(vertex_count);
+ for (size_t i = 0, e = tempData.size(); i < e; ++i) {
+
+ const unsigned int istart = mapping_offsets[i], iend = istart + mapping_counts[i];
+ for (unsigned int j = istart; j < iend; ++j) {
+ data_out[mappings[j]] = tempData[i];
+ }
+ }
+ }
+ else if (MappingInformationType == "ByVertice" && isIndexToDirect) {
+ std::vector<T> tempData;
+ ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
+
+ data_out.resize(vertex_count);
+
+ std::vector<int> uvIndices;
+ ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName));
+ for (size_t i = 0, e = uvIndices.size(); i < e; ++i) {
+
+ const unsigned int istart = mapping_offsets[i], iend = istart + mapping_counts[i];
+ for (unsigned int j = istart; j < iend; ++j) {
+ if (static_cast<size_t>(uvIndices[i]) >= tempData.size()) {
+ DOMError("index out of range",&GetRequiredElement(source,indexDataElementName));
+ }
+ data_out[mappings[j]] = tempData[uvIndices[i]];
+ }
+ }
+ }
+ else if (MappingInformationType == "ByPolygonVertex" && isDirect) {
+ std::vector<T> tempData;
+ ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
+
+ if (tempData.size() != vertex_count) {
+ FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygon mapping: ")
+ << tempData.size() << ", expected " << vertex_count
+ );
+ return;
+ }
+
+ data_out.swap(tempData);
+ }
+ else if (MappingInformationType == "ByPolygonVertex" && isIndexToDirect) {
+ std::vector<T> tempData;
+ ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
+
+ data_out.resize(vertex_count);
+
+ std::vector<int> uvIndices;
+ ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName));
+
+ if (uvIndices.size() != vertex_count) {
+ FBXImporter::LogError("length of input data unexpected for ByPolygonVertex mapping");
+ return;
+ }
+
+ const T empty;
+ unsigned int next = 0;
+ for(int i : uvIndices) {
+ if ( -1 == i ) {
+ data_out[ next++ ] = empty;
+ continue;
+ }
+ if (static_cast<size_t>(i) >= tempData.size()) {
+ DOMError("index out of range",&GetRequiredElement(source,indexDataElementName));
+ }
+
+ data_out[next++] = tempData[i];
+ }
+ }
+ else {
+ FBXImporter::LogError(Formatter::format("ignoring vertex data channel, access type not implemented: ")
+ << MappingInformationType << "," << ReferenceInformationType);
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+void MeshGeometry::ReadVertexDataNormals(std::vector<aiVector3D>& normals_out, const Scope& source,
+ const std::string& MappingInformationType,
+ const std::string& ReferenceInformationType)
+{
+ ResolveVertexDataArray(normals_out,source,MappingInformationType,ReferenceInformationType,
+ "Normals",
+ "NormalsIndex",
+ m_vertices.size(),
+ m_mapping_counts,
+ m_mapping_offsets,
+ m_mappings);
+}
+
+// ------------------------------------------------------------------------------------------------
+void MeshGeometry::ReadVertexDataUV(std::vector<aiVector2D>& uv_out, const Scope& source,
+ const std::string& MappingInformationType,
+ const std::string& ReferenceInformationType)
+{
+ ResolveVertexDataArray(uv_out,source,MappingInformationType,ReferenceInformationType,
+ "UV",
+ "UVIndex",
+ m_vertices.size(),
+ m_mapping_counts,
+ m_mapping_offsets,
+ m_mappings);
+}
+
+// ------------------------------------------------------------------------------------------------
+void MeshGeometry::ReadVertexDataColors(std::vector<aiColor4D>& colors_out, const Scope& source,
+ const std::string& MappingInformationType,
+ const std::string& ReferenceInformationType)
+{
+ ResolveVertexDataArray(colors_out,source,MappingInformationType,ReferenceInformationType,
+ "Colors",
+ "ColorIndex",
+ m_vertices.size(),
+ m_mapping_counts,
+ m_mapping_offsets,
+ m_mappings);
+}
+
+// ------------------------------------------------------------------------------------------------
+static const std::string TangentIndexToken = "TangentIndex";
+static const std::string TangentsIndexToken = "TangentsIndex";
+
+void MeshGeometry::ReadVertexDataTangents(std::vector<aiVector3D>& tangents_out, const Scope& source,
+ const std::string& MappingInformationType,
+ const std::string& ReferenceInformationType)
+{
+ const char * str = source.Elements().count( "Tangents" ) > 0 ? "Tangents" : "Tangent";
+ const char * strIdx = source.Elements().count( "Tangents" ) > 0 ? TangentsIndexToken.c_str() : TangentIndexToken.c_str();
+ ResolveVertexDataArray(tangents_out,source,MappingInformationType,ReferenceInformationType,
+ str,
+ strIdx,
+ m_vertices.size(),
+ m_mapping_counts,
+ m_mapping_offsets,
+ m_mappings);
+}
+
+// ------------------------------------------------------------------------------------------------
+static const std::string BinormalIndexToken = "BinormalIndex";
+static const std::string BinormalsIndexToken = "BinormalsIndex";
+
+void MeshGeometry::ReadVertexDataBinormals(std::vector<aiVector3D>& binormals_out, const Scope& source,
+ const std::string& MappingInformationType,
+ const std::string& ReferenceInformationType)
+{
+ const char * str = source.Elements().count( "Binormals" ) > 0 ? "Binormals" : "Binormal";
+ const char * strIdx = source.Elements().count( "Binormals" ) > 0 ? BinormalsIndexToken.c_str() : BinormalIndexToken.c_str();
+ ResolveVertexDataArray(binormals_out,source,MappingInformationType,ReferenceInformationType,
+ str,
+ strIdx,
+ m_vertices.size(),
+ m_mapping_counts,
+ m_mapping_offsets,
+ m_mappings);
+}
+
+
+// ------------------------------------------------------------------------------------------------
+void MeshGeometry::ReadVertexDataMaterials(std::vector<int>& materials_out, const Scope& source,
+ const std::string& MappingInformationType,
+ const std::string& ReferenceInformationType)
+{
+ const size_t face_count = m_faces.size();
+ ai_assert(face_count);
+
+ // materials are handled separately. First of all, they are assigned per-face
+ // and not per polyvert. Secondly, ReferenceInformationType=IndexToDirect
+ // has a slightly different meaning for materials.
+ ParseVectorDataArray(materials_out,GetRequiredElement(source,"Materials"));
+
+ if (MappingInformationType == "AllSame") {
+ // easy - same material for all faces
+ if (materials_out.empty()) {
+ FBXImporter::LogError(Formatter::format("expected material index, ignoring"));
+ return;
+ }
+ else if (materials_out.size() > 1) {
+ FBXImporter::LogWarn(Formatter::format("expected only a single material index, ignoring all except the first one"));
+ materials_out.clear();
+ }
+
+ m_materials.assign(m_vertices.size(),materials_out[0]);
+ }
+ else if (MappingInformationType == "ByPolygon" && ReferenceInformationType == "IndexToDirect") {
+ m_materials.resize(face_count);
+
+ if(materials_out.size() != face_count) {
+ FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygon mapping: ")
+ << materials_out.size() << ", expected " << face_count
+ );
+ return;
+ }
+ }
+ else {
+ FBXImporter::LogError(Formatter::format("ignoring material assignments, access type not implemented: ")
+ << MappingInformationType << "," << ReferenceInformationType);
+ }
+}
+// ------------------------------------------------------------------------------------------------
+ShapeGeometry::ShapeGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc)
+ : Geometry(id, element, name, doc)
+{
+ const Scope* sc = element.Compound();
+ if (!sc) {
+ DOMError("failed to read Geometry object (class: Shape), no data scope found");
+ }
+ const Element& Indexes = GetRequiredElement(*sc, "Indexes", &element);
+ const Element& Normals = GetRequiredElement(*sc, "Normals", &element);
+ const Element& Vertices = GetRequiredElement(*sc, "Vertices", &element);
+ ParseVectorDataArray(m_indices, Indexes);
+ ParseVectorDataArray(m_vertices, Vertices);
+ ParseVectorDataArray(m_normals, Normals);
+}
+
+// ------------------------------------------------------------------------------------------------
+ShapeGeometry::~ShapeGeometry() {
+ // empty
+}
+// ------------------------------------------------------------------------------------------------
+const std::vector<aiVector3D>& ShapeGeometry::GetVertices() const {
+ return m_vertices;
+}
+// ------------------------------------------------------------------------------------------------
+const std::vector<aiVector3D>& ShapeGeometry::GetNormals() const {
+ return m_normals;
+}
+// ------------------------------------------------------------------------------------------------
+const std::vector<unsigned int>& ShapeGeometry::GetIndices() const {
+ return m_indices;
+}
+// ------------------------------------------------------------------------------------------------
+LineGeometry::LineGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc)
+ : Geometry(id, element, name, doc)
+{
+ const Scope* sc = element.Compound();
+ if (!sc) {
+ DOMError("failed to read Geometry object (class: Line), no data scope found");
+ }
+ const Element& Points = GetRequiredElement(*sc, "Points", &element);
+ const Element& PointsIndex = GetRequiredElement(*sc, "PointsIndex", &element);
+ ParseVectorDataArray(m_vertices, Points);
+ ParseVectorDataArray(m_indices, PointsIndex);
+}
+
+// ------------------------------------------------------------------------------------------------
+LineGeometry::~LineGeometry() {
+ // empty
+}
+// ------------------------------------------------------------------------------------------------
+const std::vector<aiVector3D>& LineGeometry::GetVertices() const {
+ return m_vertices;
+}
+// ------------------------------------------------------------------------------------------------
+const std::vector<int>& LineGeometry::GetIndices() const {
+ return m_indices;
+}
+} // !FBX
+} // !Assimp
+#endif
+
diff --git a/thirdparty/assimp/code/FBXMeshGeometry.h b/thirdparty/assimp/code/FBXMeshGeometry.h
new file mode 100644
index 0000000000..d6d4512177
--- /dev/null
+++ b/thirdparty/assimp/code/FBXMeshGeometry.h
@@ -0,0 +1,235 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file FBXImporter.h
+* @brief Declaration of the FBX main importer class
+*/
+#ifndef INCLUDED_AI_FBX_MESHGEOMETRY_H
+#define INCLUDED_AI_FBX_MESHGEOMETRY_H
+
+#include "FBXParser.h"
+#include "FBXDocument.h"
+
+namespace Assimp {
+namespace FBX {
+
+/**
+ * DOM base class for all kinds of FBX geometry
+ */
+class Geometry : public Object
+{
+public:
+ Geometry( uint64_t id, const Element& element, const std::string& name, const Document& doc );
+ virtual ~Geometry();
+
+ /** Get the Skin attached to this geometry or NULL */
+ const Skin* DeformerSkin() const;
+
+ /** Get the BlendShape attached to this geometry or NULL */
+ const std::vector<const BlendShape*>& GetBlendShapes() const;
+
+private:
+ const Skin* skin;
+ std::vector<const BlendShape*> blendShapes;
+
+};
+
+typedef std::vector<int> MatIndexArray;
+
+
+/**
+ * DOM class for FBX geometry of type "Mesh"
+ */
+class MeshGeometry : public Geometry
+{
+public:
+ /** The class constructor */
+ MeshGeometry( uint64_t id, const Element& element, const std::string& name, const Document& doc );
+
+ /** The class destructor */
+ virtual ~MeshGeometry();
+
+ /** Get a list of all vertex points, non-unique*/
+ const std::vector<aiVector3D>& GetVertices() const;
+
+ /** Get a list of all vertex normals or an empty array if
+ * no normals are specified. */
+ const std::vector<aiVector3D>& GetNormals() const;
+
+ /** Get a list of all vertex tangents or an empty array
+ * if no tangents are specified */
+ const std::vector<aiVector3D>& GetTangents() const;
+
+ /** Get a list of all vertex bi-normals or an empty array
+ * if no bi-normals are specified */
+ const std::vector<aiVector3D>& GetBinormals() const;
+
+ /** Return list of faces - each entry denotes a face and specifies
+ * how many vertices it has. Vertices are taken from the
+ * vertex data arrays in sequential order. */
+ const std::vector<unsigned int>& GetFaceIndexCounts() const;
+
+ /** Get a UV coordinate slot, returns an empty array if
+ * the requested slot does not exist. */
+ const std::vector<aiVector2D>& GetTextureCoords( unsigned int index ) const;
+
+ /** Get a UV coordinate slot, returns an empty array if
+ * the requested slot does not exist. */
+ std::string GetTextureCoordChannelName( unsigned int index ) const;
+
+ /** Get a vertex color coordinate slot, returns an empty array if
+ * the requested slot does not exist. */
+ const std::vector<aiColor4D>& GetVertexColors( unsigned int index ) const;
+
+ /** Get per-face-vertex material assignments */
+ const MatIndexArray& GetMaterialIndices() const;
+
+ /** Convert from a fbx file vertex index (for example from a #Cluster weight) or NULL
+ * if the vertex index is not valid. */
+ const unsigned int* ToOutputVertexIndex( unsigned int in_index, unsigned int& count ) const;
+
+ /** Determine the face to which a particular output vertex index belongs.
+ * This mapping is always unique. */
+ unsigned int FaceForVertexIndex( unsigned int in_index ) const;
+private:
+ void ReadLayer( const Scope& layer );
+ void ReadLayerElement( const Scope& layerElement );
+ void ReadVertexData( const std::string& type, int index, const Scope& source );
+
+ void ReadVertexDataUV( std::vector<aiVector2D>& uv_out, const Scope& source,
+ const std::string& MappingInformationType,
+ const std::string& ReferenceInformationType );
+
+ void ReadVertexDataNormals( std::vector<aiVector3D>& normals_out, const Scope& source,
+ const std::string& MappingInformationType,
+ const std::string& ReferenceInformationType );
+
+ void ReadVertexDataColors( std::vector<aiColor4D>& colors_out, const Scope& source,
+ const std::string& MappingInformationType,
+ const std::string& ReferenceInformationType );
+
+ void ReadVertexDataTangents( std::vector<aiVector3D>& tangents_out, const Scope& source,
+ const std::string& MappingInformationType,
+ const std::string& ReferenceInformationType );
+
+ void ReadVertexDataBinormals( std::vector<aiVector3D>& binormals_out, const Scope& source,
+ const std::string& MappingInformationType,
+ const std::string& ReferenceInformationType );
+
+ void ReadVertexDataMaterials( MatIndexArray& materials_out, const Scope& source,
+ const std::string& MappingInformationType,
+ const std::string& ReferenceInformationType );
+
+private:
+ // cached data arrays
+ MatIndexArray m_materials;
+ std::vector<aiVector3D> m_vertices;
+ std::vector<unsigned int> m_faces;
+ mutable std::vector<unsigned int> m_facesVertexStartIndices;
+ std::vector<aiVector3D> m_tangents;
+ std::vector<aiVector3D> m_binormals;
+ std::vector<aiVector3D> m_normals;
+
+ std::string m_uvNames[ AI_MAX_NUMBER_OF_TEXTURECOORDS ];
+ std::vector<aiVector2D> m_uvs[ AI_MAX_NUMBER_OF_TEXTURECOORDS ];
+ std::vector<aiColor4D> m_colors[ AI_MAX_NUMBER_OF_COLOR_SETS ];
+
+ std::vector<unsigned int> m_mapping_counts;
+ std::vector<unsigned int> m_mapping_offsets;
+ std::vector<unsigned int> m_mappings;
+};
+
+/**
+* DOM class for FBX geometry of type "Shape"
+*/
+class ShapeGeometry : public Geometry
+{
+public:
+ /** The class constructor */
+ ShapeGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc);
+
+ /** The class destructor */
+ virtual ~ShapeGeometry();
+
+ /** Get a list of all vertex points, non-unique*/
+ const std::vector<aiVector3D>& GetVertices() const;
+
+ /** Get a list of all vertex normals or an empty array if
+ * no normals are specified. */
+ const std::vector<aiVector3D>& GetNormals() const;
+
+ /** Return list of vertex indices. */
+ const std::vector<unsigned int>& GetIndices() const;
+
+private:
+ std::vector<aiVector3D> m_vertices;
+ std::vector<aiVector3D> m_normals;
+ std::vector<unsigned int> m_indices;
+};
+/**
+* DOM class for FBX geometry of type "Line"
+*/
+class LineGeometry : public Geometry
+{
+public:
+ /** The class constructor */
+ LineGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc);
+
+ /** The class destructor */
+ virtual ~LineGeometry();
+
+ /** Get a list of all vertex points, non-unique*/
+ const std::vector<aiVector3D>& GetVertices() const;
+
+ /** Return list of vertex indices. */
+ const std::vector<int>& GetIndices() const;
+
+private:
+ std::vector<aiVector3D> m_vertices;
+ std::vector<int> m_indices;
+};
+
+}
+}
+
+#endif // INCLUDED_AI_FBX_MESHGEOMETRY_H
+
diff --git a/thirdparty/assimp/code/FBXModel.cpp b/thirdparty/assimp/code/FBXModel.cpp
new file mode 100644
index 0000000000..589af36ac7
--- /dev/null
+++ b/thirdparty/assimp/code/FBXModel.cpp
@@ -0,0 +1,153 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file FBXModel.cpp
+ * @brief Assimp::FBX::Model implementation
+ */
+
+#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
+
+#include "FBXParser.h"
+#include "FBXMeshGeometry.h"
+#include "FBXDocument.h"
+#include "FBXImporter.h"
+#include "FBXDocumentUtil.h"
+
+namespace Assimp {
+namespace FBX {
+
+using namespace Util;
+
+// ------------------------------------------------------------------------------------------------
+Model::Model(uint64_t id, const Element& element, const Document& doc, const std::string& name)
+ : Object(id,element,name)
+ , shading("Y")
+{
+ const Scope& sc = GetRequiredScope(element);
+ const Element* const Shading = sc["Shading"];
+ const Element* const Culling = sc["Culling"];
+
+ if(Shading) {
+ shading = GetRequiredToken(*Shading,0).StringContents();
+ }
+
+ if (Culling) {
+ culling = ParseTokenAsString(GetRequiredToken(*Culling,0));
+ }
+
+ props = GetPropertyTable(doc,"Model.FbxNode",element,sc);
+ ResolveLinks(element,doc);
+}
+
+// ------------------------------------------------------------------------------------------------
+Model::~Model()
+{
+
+}
+
+// ------------------------------------------------------------------------------------------------
+void Model::ResolveLinks(const Element& element, const Document& doc)
+{
+ const char* const arr[] = {"Geometry","Material","NodeAttribute"};
+
+ // resolve material
+ const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),arr, 3);
+
+ materials.reserve(conns.size());
+ geometry.reserve(conns.size());
+ attributes.reserve(conns.size());
+ for(const Connection* con : conns) {
+
+ // material and geometry links should be Object-Object connections
+ if (con->PropertyName().length()) {
+ continue;
+ }
+
+ const Object* const ob = con->SourceObject();
+ if(!ob) {
+ DOMWarning("failed to read source object for incoming Model link, ignoring",&element);
+ continue;
+ }
+
+ const Material* const mat = dynamic_cast<const Material*>(ob);
+ if(mat) {
+ materials.push_back(mat);
+ continue;
+ }
+
+ const Geometry* const geo = dynamic_cast<const Geometry*>(ob);
+ if(geo) {
+ geometry.push_back(geo);
+ continue;
+ }
+
+ const NodeAttribute* const att = dynamic_cast<const NodeAttribute*>(ob);
+ if(att) {
+ attributes.push_back(att);
+ continue;
+ }
+
+ DOMWarning("source object for model link is neither Material, NodeAttribute nor Geometry, ignoring",&element);
+ continue;
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+bool Model::IsNull() const
+{
+ const std::vector<const NodeAttribute*>& attrs = GetAttributes();
+ for(const NodeAttribute* att : attrs) {
+
+ const Null* null_tag = dynamic_cast<const Null*>(att);
+ if(null_tag) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+} //!FBX
+} //!Assimp
+
+#endif
diff --git a/thirdparty/assimp/code/FBXNodeAttribute.cpp b/thirdparty/assimp/code/FBXNodeAttribute.cpp
new file mode 100644
index 0000000000..b72e5637ee
--- /dev/null
+++ b/thirdparty/assimp/code/FBXNodeAttribute.cpp
@@ -0,0 +1,170 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file FBXNoteAttribute.cpp
+ * @brief Assimp::FBX::NodeAttribute (and subclasses) implementation
+ */
+
+#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
+
+#include "FBXParser.h"
+#include "FBXDocument.h"
+#include "FBXImporter.h"
+#include "FBXDocumentUtil.h"
+
+namespace Assimp {
+namespace FBX {
+
+using namespace Util;
+
+// ------------------------------------------------------------------------------------------------
+NodeAttribute::NodeAttribute(uint64_t id, const Element& element, const Document& doc, const std::string& name)
+: Object(id,element,name)
+, props()
+{
+ const Scope& sc = GetRequiredScope(element);
+
+ const std::string& classname = ParseTokenAsString(GetRequiredToken(element,2));
+
+ // hack on the deriving type but Null/LimbNode attributes are the only case in which
+ // the property table is by design absent and no warning should be generated
+ // for it.
+ const bool is_null_or_limb = !strcmp(classname.c_str(), "Null") || !strcmp(classname.c_str(), "LimbNode");
+ props = GetPropertyTable(doc,"NodeAttribute.Fbx" + classname,element,sc, is_null_or_limb);
+}
+
+
+// ------------------------------------------------------------------------------------------------
+NodeAttribute::~NodeAttribute()
+{
+ // empty
+}
+
+
+// ------------------------------------------------------------------------------------------------
+CameraSwitcher::CameraSwitcher(uint64_t id, const Element& element, const Document& doc, const std::string& name)
+ : NodeAttribute(id,element,doc,name)
+{
+ const Scope& sc = GetRequiredScope(element);
+ const Element* const CameraId = sc["CameraId"];
+ const Element* const CameraName = sc["CameraName"];
+ const Element* const CameraIndexName = sc["CameraIndexName"];
+
+ if(CameraId) {
+ cameraId = ParseTokenAsInt(GetRequiredToken(*CameraId,0));
+ }
+
+ if(CameraName) {
+ cameraName = GetRequiredToken(*CameraName,0).StringContents();
+ }
+
+ if(CameraIndexName && CameraIndexName->Tokens().size()) {
+ cameraIndexName = GetRequiredToken(*CameraIndexName,0).StringContents();
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+CameraSwitcher::~CameraSwitcher()
+{
+ // empty
+}
+
+// ------------------------------------------------------------------------------------------------
+Camera::Camera(uint64_t id, const Element& element, const Document& doc, const std::string& name)
+: NodeAttribute(id,element,doc,name)
+{
+ // empty
+}
+
+// ------------------------------------------------------------------------------------------------
+Camera::~Camera()
+{
+ // empty
+}
+
+// ------------------------------------------------------------------------------------------------
+Light::Light(uint64_t id, const Element& element, const Document& doc, const std::string& name)
+: NodeAttribute(id,element,doc,name)
+{
+ // empty
+}
+
+
+// ------------------------------------------------------------------------------------------------
+Light::~Light()
+{
+}
+
+
+// ------------------------------------------------------------------------------------------------
+Null::Null(uint64_t id, const Element& element, const Document& doc, const std::string& name)
+: NodeAttribute(id,element,doc,name)
+{
+
+}
+
+
+// ------------------------------------------------------------------------------------------------
+Null::~Null()
+{
+
+}
+
+
+// ------------------------------------------------------------------------------------------------
+LimbNode::LimbNode(uint64_t id, const Element& element, const Document& doc, const std::string& name)
+: NodeAttribute(id,element,doc,name)
+{
+
+}
+
+
+// ------------------------------------------------------------------------------------------------
+LimbNode::~LimbNode()
+{
+
+}
+
+}
+}
+
+#endif
diff --git a/thirdparty/assimp/code/FBXParser.cpp b/thirdparty/assimp/code/FBXParser.cpp
new file mode 100644
index 0000000000..b255c47347
--- /dev/null
+++ b/thirdparty/assimp/code/FBXParser.cpp
@@ -0,0 +1,1313 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file FBXParser.cpp
+ * @brief Implementation of the FBX parser and the rudimentary DOM that we use
+ */
+
+#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
+
+#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
+# include <zlib.h>
+#else
+# include "../contrib/zlib/zlib.h"
+#endif
+
+#include "FBXTokenizer.h"
+#include "FBXParser.h"
+#include "FBXUtil.h"
+
+#include <assimp/ParsingUtils.h>
+#include <assimp/fast_atof.h>
+#include <assimp/ByteSwapper.h>
+
+#include <iostream>
+
+using namespace Assimp;
+using namespace Assimp::FBX;
+
+namespace {
+
+ // ------------------------------------------------------------------------------------------------
+ // signal parse error, this is always unrecoverable. Throws DeadlyImportError.
+ AI_WONT_RETURN void ParseError(const std::string& message, const Token& token) AI_WONT_RETURN_SUFFIX;
+ AI_WONT_RETURN void ParseError(const std::string& message, const Token& token)
+ {
+ throw DeadlyImportError(Util::AddTokenText("FBX-Parser",message,&token));
+ }
+
+ // ------------------------------------------------------------------------------------------------
+ AI_WONT_RETURN void ParseError(const std::string& message, const Element* element = NULL) AI_WONT_RETURN_SUFFIX;
+ AI_WONT_RETURN void ParseError(const std::string& message, const Element* element)
+ {
+ if(element) {
+ ParseError(message,element->KeyToken());
+ }
+ throw DeadlyImportError("FBX-Parser " + message);
+ }
+
+
+ // ------------------------------------------------------------------------------------------------
+ void ParseError(const std::string& message, TokenPtr token)
+ {
+ if(token) {
+ ParseError(message, *token);
+ }
+ ParseError(message);
+ }
+
+ // Initially, we did reinterpret_cast, breaking strict aliasing rules.
+ // This actually caused trouble on Android, so let's be safe this time.
+ // https://github.com/assimp/assimp/issues/24
+ template <typename T>
+ T SafeParse(const char* data, const char* end) {
+ // Actual size validation happens during Tokenization so
+ // this is valid as an assertion.
+ (void)(end);
+ ai_assert(static_cast<size_t>(end - data) >= sizeof(T));
+ T result = static_cast<T>(0);
+ ::memcpy(&result, data, sizeof(T));
+ return result;
+ }
+}
+
+namespace Assimp {
+namespace FBX {
+
+// ------------------------------------------------------------------------------------------------
+Element::Element(const Token& key_token, Parser& parser)
+: key_token(key_token)
+{
+ TokenPtr n = NULL;
+ do {
+ n = parser.AdvanceToNextToken();
+ if(!n) {
+ ParseError("unexpected end of file, expected closing bracket",parser.LastToken());
+ }
+
+ if (n->Type() == TokenType_DATA) {
+ tokens.push_back(n);
+ TokenPtr prev = n;
+ n = parser.AdvanceToNextToken();
+ if(!n) {
+ ParseError("unexpected end of file, expected bracket, comma or key",parser.LastToken());
+ }
+
+ const TokenType ty = n->Type();
+
+ // some exporters are missing a comma on the next line
+ if (ty == TokenType_DATA && prev->Type() == TokenType_DATA && (n->Line() == prev->Line() + 1)) {
+ tokens.push_back(n);
+ continue;
+ }
+
+ if (ty != TokenType_OPEN_BRACKET && ty != TokenType_CLOSE_BRACKET && ty != TokenType_COMMA && ty != TokenType_KEY) {
+ ParseError("unexpected token; expected bracket, comma or key",n);
+ }
+ }
+
+ if (n->Type() == TokenType_OPEN_BRACKET) {
+ compound.reset(new Scope(parser));
+
+ // current token should be a TOK_CLOSE_BRACKET
+ n = parser.CurrentToken();
+ ai_assert(n);
+
+ if (n->Type() != TokenType_CLOSE_BRACKET) {
+ ParseError("expected closing bracket",n);
+ }
+
+ parser.AdvanceToNextToken();
+ return;
+ }
+ }
+ while(n->Type() != TokenType_KEY && n->Type() != TokenType_CLOSE_BRACKET);
+}
+
+// ------------------------------------------------------------------------------------------------
+Element::~Element()
+{
+ // no need to delete tokens, they are owned by the parser
+}
+
+// ------------------------------------------------------------------------------------------------
+Scope::Scope(Parser& parser,bool topLevel)
+{
+ if(!topLevel) {
+ TokenPtr t = parser.CurrentToken();
+ if (t->Type() != TokenType_OPEN_BRACKET) {
+ ParseError("expected open bracket",t);
+ }
+ }
+
+ TokenPtr n = parser.AdvanceToNextToken();
+ if(n == NULL) {
+ ParseError("unexpected end of file");
+ }
+
+ // note: empty scopes are allowed
+ while(n->Type() != TokenType_CLOSE_BRACKET) {
+ if (n->Type() != TokenType_KEY) {
+ ParseError("unexpected token, expected TOK_KEY",n);
+ }
+
+ const std::string& str = n->StringContents();
+ elements.insert(ElementMap::value_type(str,new_Element(*n,parser)));
+
+ // Element() should stop at the next Key token (or right after a Close token)
+ n = parser.CurrentToken();
+ if(n == NULL) {
+ if (topLevel) {
+ return;
+ }
+ ParseError("unexpected end of file",parser.LastToken());
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+Scope::~Scope()
+{
+ for(ElementMap::value_type& v : elements) {
+ delete v.second;
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+Parser::Parser (const TokenList& tokens, bool is_binary)
+: tokens(tokens)
+, last()
+, current()
+, cursor(tokens.begin())
+, is_binary(is_binary)
+{
+ root.reset(new Scope(*this,true));
+}
+
+// ------------------------------------------------------------------------------------------------
+Parser::~Parser()
+{
+ // empty
+}
+
+// ------------------------------------------------------------------------------------------------
+TokenPtr Parser::AdvanceToNextToken()
+{
+ last = current;
+ if (cursor == tokens.end()) {
+ current = NULL;
+ } else {
+ current = *cursor++;
+ }
+ return current;
+}
+
+// ------------------------------------------------------------------------------------------------
+TokenPtr Parser::CurrentToken() const
+{
+ return current;
+}
+
+// ------------------------------------------------------------------------------------------------
+TokenPtr Parser::LastToken() const
+{
+ return last;
+}
+
+// ------------------------------------------------------------------------------------------------
+uint64_t ParseTokenAsID(const Token& t, const char*& err_out)
+{
+ err_out = NULL;
+
+ if (t.Type() != TokenType_DATA) {
+ err_out = "expected TOK_DATA token";
+ return 0L;
+ }
+
+ if(t.IsBinary())
+ {
+ const char* data = t.begin();
+ if (data[0] != 'L') {
+ err_out = "failed to parse ID, unexpected data type, expected L(ong) (binary)";
+ return 0L;
+ }
+
+ BE_NCONST uint64_t id = SafeParse<uint64_t>(data+1, t.end());
+ AI_SWAP8(id);
+ return id;
+ }
+
+ // XXX: should use size_t here
+ unsigned int length = static_cast<unsigned int>(t.end() - t.begin());
+ ai_assert(length > 0);
+
+ const char* out = nullptr;
+ const uint64_t id = strtoul10_64(t.begin(),&out,&length);
+ if (out > t.end()) {
+ err_out = "failed to parse ID (text)";
+ return 0L;
+ }
+
+ return id;
+}
+
+// ------------------------------------------------------------------------------------------------
+size_t ParseTokenAsDim(const Token& t, const char*& err_out)
+{
+ // same as ID parsing, except there is a trailing asterisk
+ err_out = NULL;
+
+ if (t.Type() != TokenType_DATA) {
+ err_out = "expected TOK_DATA token";
+ return 0;
+ }
+
+ if(t.IsBinary())
+ {
+ const char* data = t.begin();
+ if (data[0] != 'L') {
+ err_out = "failed to parse ID, unexpected data type, expected L(ong) (binary)";
+ return 0;
+ }
+
+ BE_NCONST uint64_t id = SafeParse<uint64_t>(data+1, t.end());
+ AI_SWAP8(id);
+ return static_cast<size_t>(id);
+ }
+
+ if(*t.begin() != '*') {
+ err_out = "expected asterisk before array dimension";
+ return 0;
+ }
+
+ // XXX: should use size_t here
+ unsigned int length = static_cast<unsigned int>(t.end() - t.begin());
+ if(length == 0) {
+ err_out = "expected valid integer number after asterisk";
+ return 0;
+ }
+
+ const char* out = nullptr;
+ const size_t id = static_cast<size_t>(strtoul10_64(t.begin() + 1,&out,&length));
+ if (out > t.end()) {
+ err_out = "failed to parse ID";
+ return 0;
+ }
+
+ return id;
+}
+
+
+// ------------------------------------------------------------------------------------------------
+float ParseTokenAsFloat(const Token& t, const char*& err_out)
+{
+ err_out = NULL;
+
+ if (t.Type() != TokenType_DATA) {
+ err_out = "expected TOK_DATA token";
+ return 0.0f;
+ }
+
+ if(t.IsBinary())
+ {
+ const char* data = t.begin();
+ if (data[0] != 'F' && data[0] != 'D') {
+ err_out = "failed to parse F(loat) or D(ouble), unexpected data type (binary)";
+ return 0.0f;
+ }
+
+ if (data[0] == 'F') {
+ return SafeParse<float>(data+1, t.end());
+ }
+ else {
+ return static_cast<float>( SafeParse<double>(data+1, t.end()) );
+ }
+ }
+
+ // need to copy the input string to a temporary buffer
+ // first - next in the fbx token stream comes ',',
+ // which fast_atof could interpret as decimal point.
+#define MAX_FLOAT_LENGTH 31
+ char temp[MAX_FLOAT_LENGTH + 1];
+ const size_t length = static_cast<size_t>(t.end()-t.begin());
+ std::copy(t.begin(),t.end(),temp);
+ temp[std::min(static_cast<size_t>(MAX_FLOAT_LENGTH),length)] = '\0';
+
+ return fast_atof(temp);
+}
+
+
+// ------------------------------------------------------------------------------------------------
+int ParseTokenAsInt(const Token& t, const char*& err_out)
+{
+ err_out = NULL;
+
+ if (t.Type() != TokenType_DATA) {
+ err_out = "expected TOK_DATA token";
+ return 0;
+ }
+
+ if(t.IsBinary())
+ {
+ const char* data = t.begin();
+ if (data[0] != 'I') {
+ err_out = "failed to parse I(nt), unexpected data type (binary)";
+ return 0;
+ }
+
+ BE_NCONST int32_t ival = SafeParse<int32_t>(data+1, t.end());
+ AI_SWAP4(ival);
+ return static_cast<int>(ival);
+ }
+
+ ai_assert(static_cast<size_t>(t.end() - t.begin()) > 0);
+
+ const char* out;
+ const int intval = strtol10(t.begin(),&out);
+ if (out != t.end()) {
+ err_out = "failed to parse ID";
+ return 0;
+ }
+
+ return intval;
+}
+
+
+// ------------------------------------------------------------------------------------------------
+int64_t ParseTokenAsInt64(const Token& t, const char*& err_out)
+{
+ err_out = NULL;
+
+ if (t.Type() != TokenType_DATA) {
+ err_out = "expected TOK_DATA token";
+ return 0L;
+ }
+
+ if (t.IsBinary())
+ {
+ const char* data = t.begin();
+ if (data[0] != 'L') {
+ err_out = "failed to parse Int64, unexpected data type";
+ return 0L;
+ }
+
+ BE_NCONST int64_t id = SafeParse<int64_t>(data + 1, t.end());
+ AI_SWAP8(id);
+ return id;
+ }
+
+ // XXX: should use size_t here
+ unsigned int length = static_cast<unsigned int>(t.end() - t.begin());
+ ai_assert(length > 0);
+
+ const char* out = nullptr;
+ const int64_t id = strtol10_64(t.begin(), &out, &length);
+ if (out > t.end()) {
+ err_out = "failed to parse Int64 (text)";
+ return 0L;
+ }
+
+ return id;
+}
+
+// ------------------------------------------------------------------------------------------------
+std::string ParseTokenAsString(const Token& t, const char*& err_out)
+{
+ err_out = NULL;
+
+ if (t.Type() != TokenType_DATA) {
+ err_out = "expected TOK_DATA token";
+ return "";
+ }
+
+ if(t.IsBinary())
+ {
+ const char* data = t.begin();
+ if (data[0] != 'S') {
+ err_out = "failed to parse S(tring), unexpected data type (binary)";
+ return "";
+ }
+
+ // read string length
+ BE_NCONST int32_t len = SafeParse<int32_t>(data+1, t.end());
+ AI_SWAP4(len);
+
+ ai_assert(t.end() - data == 5 + len);
+ return std::string(data + 5, len);
+ }
+
+ const size_t length = static_cast<size_t>(t.end() - t.begin());
+ if(length < 2) {
+ err_out = "token is too short to hold a string";
+ return "";
+ }
+
+ const char* s = t.begin(), *e = t.end() - 1;
+ if (*s != '\"' || *e != '\"') {
+ err_out = "expected double quoted string";
+ return "";
+ }
+
+ return std::string(s+1,length-2);
+}
+
+
+namespace {
+
+// ------------------------------------------------------------------------------------------------
+// read the type code and element count of a binary data array and stop there
+void ReadBinaryDataArrayHead(const char*& data, const char* end, char& type, uint32_t& count,
+ const Element& el)
+{
+ if (static_cast<size_t>(end-data) < 5) {
+ ParseError("binary data array is too short, need five (5) bytes for type signature and element count",&el);
+ }
+
+ // data type
+ type = *data;
+
+ // read number of elements
+ BE_NCONST uint32_t len = SafeParse<uint32_t>(data+1, end);
+ AI_SWAP4(len);
+
+ count = len;
+ data += 5;
+}
+
+
+// ------------------------------------------------------------------------------------------------
+// read binary data array, assume cursor points to the 'compression mode' field (i.e. behind the header)
+void ReadBinaryDataArray(char type, uint32_t count, const char*& data, const char* end,
+ std::vector<char>& buff,
+ const Element& /*el*/)
+{
+ BE_NCONST uint32_t encmode = SafeParse<uint32_t>(data, end);
+ AI_SWAP4(encmode);
+ data += 4;
+
+ // next comes the compressed length
+ BE_NCONST uint32_t comp_len = SafeParse<uint32_t>(data, end);
+ AI_SWAP4(comp_len);
+ data += 4;
+
+ ai_assert(data + comp_len == end);
+
+ // determine the length of the uncompressed data by looking at the type signature
+ uint32_t stride = 0;
+ switch(type)
+ {
+ case 'f':
+ case 'i':
+ stride = 4;
+ break;
+
+ case 'd':
+ case 'l':
+ stride = 8;
+ break;
+
+ default:
+ ai_assert(false);
+ };
+
+ const uint32_t full_length = stride * count;
+ buff.resize(full_length);
+
+ if(encmode == 0) {
+ ai_assert(full_length == comp_len);
+
+ // plain data, no compression
+ std::copy(data, end, buff.begin());
+ }
+ else if(encmode == 1) {
+ // zlib/deflate, next comes ZIP head (0x78 0x01)
+ // see http://www.ietf.org/rfc/rfc1950.txt
+
+ z_stream zstream;
+ zstream.opaque = Z_NULL;
+ zstream.zalloc = Z_NULL;
+ zstream.zfree = Z_NULL;
+ zstream.data_type = Z_BINARY;
+
+ // http://hewgill.com/journal/entries/349-how-to-decompress-gzip-stream-with-zlib
+ if(Z_OK != inflateInit(&zstream)) {
+ ParseError("failure initializing zlib");
+ }
+
+ zstream.next_in = reinterpret_cast<Bytef*>( const_cast<char*>(data) );
+ zstream.avail_in = comp_len;
+
+ zstream.avail_out = static_cast<uInt>(buff.size());
+ zstream.next_out = reinterpret_cast<Bytef*>(&*buff.begin());
+ const int ret = inflate(&zstream, Z_FINISH);
+
+ if (ret != Z_STREAM_END && ret != Z_OK) {
+ ParseError("failure decompressing compressed data section");
+ }
+
+ // terminate zlib
+ inflateEnd(&zstream);
+ }
+#ifdef ASSIMP_BUILD_DEBUG
+ else {
+ // runtime check for this happens at tokenization stage
+ ai_assert(false);
+ }
+#endif
+
+ data += comp_len;
+ ai_assert(data == end);
+}
+
+} // !anon
+
+
+// ------------------------------------------------------------------------------------------------
+// read an array of float3 tuples
+void ParseVectorDataArray(std::vector<aiVector3D>& out, const Element& el)
+{
+ out.resize( 0 );
+
+ const TokenList& tok = el.Tokens();
+ if(tok.empty()) {
+ ParseError("unexpected empty element",&el);
+ }
+
+ if(tok[0]->IsBinary()) {
+ const char* data = tok[0]->begin(), *end = tok[0]->end();
+
+ char type;
+ uint32_t count;
+ ReadBinaryDataArrayHead(data, end, type, count, el);
+
+ if(count % 3 != 0) {
+ ParseError("number of floats is not a multiple of three (3) (binary)",&el);
+ }
+
+ if(!count) {
+ return;
+ }
+
+ if (type != 'd' && type != 'f') {
+ ParseError("expected float or double array (binary)",&el);
+ }
+
+ std::vector<char> buff;
+ ReadBinaryDataArray(type, count, data, end, buff, el);
+
+ ai_assert(data == end);
+ ai_assert(buff.size() == count * (type == 'd' ? 8 : 4));
+
+ const uint32_t count3 = count / 3;
+ out.reserve(count3);
+
+ if (type == 'd') {
+ const double* d = reinterpret_cast<const double*>(&buff[0]);
+ for (unsigned int i = 0; i < count3; ++i, d += 3) {
+ out.push_back(aiVector3D(static_cast<float>(d[0]),
+ static_cast<float>(d[1]),
+ static_cast<float>(d[2])));
+ }
+ // for debugging
+ /*for ( size_t i = 0; i < out.size(); i++ ) {
+ aiVector3D vec3( out[ i ] );
+ std::stringstream stream;
+ stream << " vec3.x = " << vec3.x << " vec3.y = " << vec3.y << " vec3.z = " << vec3.z << std::endl;
+ DefaultLogger::get()->info( stream.str() );
+ }*/
+ }
+ else if (type == 'f') {
+ const float* f = reinterpret_cast<const float*>(&buff[0]);
+ for (unsigned int i = 0; i < count3; ++i, f += 3) {
+ out.push_back(aiVector3D(f[0],f[1],f[2]));
+ }
+ }
+
+ return;
+ }
+
+ const size_t dim = ParseTokenAsDim(*tok[0]);
+
+ // may throw bad_alloc if the input is rubbish, but this need
+ // not to be prevented - importing would fail but we wouldn't
+ // crash since assimp handles this case properly.
+ out.reserve(dim);
+
+ const Scope& scope = GetRequiredScope(el);
+ const Element& a = GetRequiredElement(scope,"a",&el);
+
+ if (a.Tokens().size() % 3 != 0) {
+ ParseError("number of floats is not a multiple of three (3)",&el);
+ }
+ for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) {
+ aiVector3D v;
+ v.x = ParseTokenAsFloat(**it++);
+ v.y = ParseTokenAsFloat(**it++);
+ v.z = ParseTokenAsFloat(**it++);
+
+ out.push_back(v);
+ }
+}
+
+
+// ------------------------------------------------------------------------------------------------
+// read an array of color4 tuples
+void ParseVectorDataArray(std::vector<aiColor4D>& out, const Element& el)
+{
+ out.resize( 0 );
+ const TokenList& tok = el.Tokens();
+ if(tok.empty()) {
+ ParseError("unexpected empty element",&el);
+ }
+
+ if(tok[0]->IsBinary()) {
+ const char* data = tok[0]->begin(), *end = tok[0]->end();
+
+ char type;
+ uint32_t count;
+ ReadBinaryDataArrayHead(data, end, type, count, el);
+
+ if(count % 4 != 0) {
+ ParseError("number of floats is not a multiple of four (4) (binary)",&el);
+ }
+
+ if(!count) {
+ return;
+ }
+
+ if (type != 'd' && type != 'f') {
+ ParseError("expected float or double array (binary)",&el);
+ }
+
+ std::vector<char> buff;
+ ReadBinaryDataArray(type, count, data, end, buff, el);
+
+ ai_assert(data == end);
+ ai_assert(buff.size() == count * (type == 'd' ? 8 : 4));
+
+ const uint32_t count4 = count / 4;
+ out.reserve(count4);
+
+ if (type == 'd') {
+ const double* d = reinterpret_cast<const double*>(&buff[0]);
+ for (unsigned int i = 0; i < count4; ++i, d += 4) {
+ out.push_back(aiColor4D(static_cast<float>(d[0]),
+ static_cast<float>(d[1]),
+ static_cast<float>(d[2]),
+ static_cast<float>(d[3])));
+ }
+ }
+ else if (type == 'f') {
+ const float* f = reinterpret_cast<const float*>(&buff[0]);
+ for (unsigned int i = 0; i < count4; ++i, f += 4) {
+ out.push_back(aiColor4D(f[0],f[1],f[2],f[3]));
+ }
+ }
+ return;
+ }
+
+ const size_t dim = ParseTokenAsDim(*tok[0]);
+
+ // see notes in ParseVectorDataArray() above
+ out.reserve(dim);
+
+ const Scope& scope = GetRequiredScope(el);
+ const Element& a = GetRequiredElement(scope,"a",&el);
+
+ if (a.Tokens().size() % 4 != 0) {
+ ParseError("number of floats is not a multiple of four (4)",&el);
+ }
+ for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) {
+ aiColor4D v;
+ v.r = ParseTokenAsFloat(**it++);
+ v.g = ParseTokenAsFloat(**it++);
+ v.b = ParseTokenAsFloat(**it++);
+ v.a = ParseTokenAsFloat(**it++);
+
+ out.push_back(v);
+ }
+}
+
+
+// ------------------------------------------------------------------------------------------------
+// read an array of float2 tuples
+void ParseVectorDataArray(std::vector<aiVector2D>& out, const Element& el)
+{
+ out.resize( 0 );
+ const TokenList& tok = el.Tokens();
+ if(tok.empty()) {
+ ParseError("unexpected empty element",&el);
+ }
+
+ if(tok[0]->IsBinary()) {
+ const char* data = tok[0]->begin(), *end = tok[0]->end();
+
+ char type;
+ uint32_t count;
+ ReadBinaryDataArrayHead(data, end, type, count, el);
+
+ if(count % 2 != 0) {
+ ParseError("number of floats is not a multiple of two (2) (binary)",&el);
+ }
+
+ if(!count) {
+ return;
+ }
+
+ if (type != 'd' && type != 'f') {
+ ParseError("expected float or double array (binary)",&el);
+ }
+
+ std::vector<char> buff;
+ ReadBinaryDataArray(type, count, data, end, buff, el);
+
+ ai_assert(data == end);
+ ai_assert(buff.size() == count * (type == 'd' ? 8 : 4));
+
+ const uint32_t count2 = count / 2;
+ out.reserve(count2);
+
+ if (type == 'd') {
+ const double* d = reinterpret_cast<const double*>(&buff[0]);
+ for (unsigned int i = 0; i < count2; ++i, d += 2) {
+ out.push_back(aiVector2D(static_cast<float>(d[0]),
+ static_cast<float>(d[1])));
+ }
+ }
+ else if (type == 'f') {
+ const float* f = reinterpret_cast<const float*>(&buff[0]);
+ for (unsigned int i = 0; i < count2; ++i, f += 2) {
+ out.push_back(aiVector2D(f[0],f[1]));
+ }
+ }
+
+ return;
+ }
+
+ const size_t dim = ParseTokenAsDim(*tok[0]);
+
+ // see notes in ParseVectorDataArray() above
+ out.reserve(dim);
+
+ const Scope& scope = GetRequiredScope(el);
+ const Element& a = GetRequiredElement(scope,"a",&el);
+
+ if (a.Tokens().size() % 2 != 0) {
+ ParseError("number of floats is not a multiple of two (2)",&el);
+ }
+ for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) {
+ aiVector2D v;
+ v.x = ParseTokenAsFloat(**it++);
+ v.y = ParseTokenAsFloat(**it++);
+
+ out.push_back(v);
+ }
+}
+
+
+// ------------------------------------------------------------------------------------------------
+// read an array of ints
+void ParseVectorDataArray(std::vector<int>& out, const Element& el)
+{
+ out.resize( 0 );
+ const TokenList& tok = el.Tokens();
+ if(tok.empty()) {
+ ParseError("unexpected empty element",&el);
+ }
+
+ if(tok[0]->IsBinary()) {
+ const char* data = tok[0]->begin(), *end = tok[0]->end();
+
+ char type;
+ uint32_t count;
+ ReadBinaryDataArrayHead(data, end, type, count, el);
+
+ if(!count) {
+ return;
+ }
+
+ if (type != 'i') {
+ ParseError("expected int array (binary)",&el);
+ }
+
+ std::vector<char> buff;
+ ReadBinaryDataArray(type, count, data, end, buff, el);
+
+ ai_assert(data == end);
+ ai_assert(buff.size() == count * 4);
+
+ out.reserve(count);
+
+ const int32_t* ip = reinterpret_cast<const int32_t*>(&buff[0]);
+ for (unsigned int i = 0; i < count; ++i, ++ip) {
+ BE_NCONST int32_t val = *ip;
+ AI_SWAP4(val);
+ out.push_back(val);
+ }
+
+ return;
+ }
+
+ const size_t dim = ParseTokenAsDim(*tok[0]);
+
+ // see notes in ParseVectorDataArray()
+ out.reserve(dim);
+
+ const Scope& scope = GetRequiredScope(el);
+ const Element& a = GetRequiredElement(scope,"a",&el);
+
+ for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) {
+ const int ival = ParseTokenAsInt(**it++);
+ out.push_back(ival);
+ }
+}
+
+
+// ------------------------------------------------------------------------------------------------
+// read an array of floats
+void ParseVectorDataArray(std::vector<float>& out, const Element& el)
+{
+ out.resize( 0 );
+ const TokenList& tok = el.Tokens();
+ if(tok.empty()) {
+ ParseError("unexpected empty element",&el);
+ }
+
+ if(tok[0]->IsBinary()) {
+ const char* data = tok[0]->begin(), *end = tok[0]->end();
+
+ char type;
+ uint32_t count;
+ ReadBinaryDataArrayHead(data, end, type, count, el);
+
+ if(!count) {
+ return;
+ }
+
+ if (type != 'd' && type != 'f') {
+ ParseError("expected float or double array (binary)",&el);
+ }
+
+ std::vector<char> buff;
+ ReadBinaryDataArray(type, count, data, end, buff, el);
+
+ ai_assert(data == end);
+ ai_assert(buff.size() == count * (type == 'd' ? 8 : 4));
+
+ if (type == 'd') {
+ const double* d = reinterpret_cast<const double*>(&buff[0]);
+ for (unsigned int i = 0; i < count; ++i, ++d) {
+ out.push_back(static_cast<float>(*d));
+ }
+ }
+ else if (type == 'f') {
+ const float* f = reinterpret_cast<const float*>(&buff[0]);
+ for (unsigned int i = 0; i < count; ++i, ++f) {
+ out.push_back(*f);
+ }
+ }
+
+ return;
+ }
+
+ const size_t dim = ParseTokenAsDim(*tok[0]);
+
+ // see notes in ParseVectorDataArray()
+ out.reserve(dim);
+
+ const Scope& scope = GetRequiredScope(el);
+ const Element& a = GetRequiredElement(scope,"a",&el);
+
+ for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) {
+ const float ival = ParseTokenAsFloat(**it++);
+ out.push_back(ival);
+ }
+}
+
+
+// ------------------------------------------------------------------------------------------------
+// read an array of uints
+void ParseVectorDataArray(std::vector<unsigned int>& out, const Element& el)
+{
+ out.resize( 0 );
+ const TokenList& tok = el.Tokens();
+ if(tok.empty()) {
+ ParseError("unexpected empty element",&el);
+ }
+
+ if(tok[0]->IsBinary()) {
+ const char* data = tok[0]->begin(), *end = tok[0]->end();
+
+ char type;
+ uint32_t count;
+ ReadBinaryDataArrayHead(data, end, type, count, el);
+
+ if(!count) {
+ return;
+ }
+
+ if (type != 'i') {
+ ParseError("expected (u)int array (binary)",&el);
+ }
+
+ std::vector<char> buff;
+ ReadBinaryDataArray(type, count, data, end, buff, el);
+
+ ai_assert(data == end);
+ ai_assert(buff.size() == count * 4);
+
+ out.reserve(count);
+
+ const int32_t* ip = reinterpret_cast<const int32_t*>(&buff[0]);
+ for (unsigned int i = 0; i < count; ++i, ++ip) {
+ BE_NCONST int32_t val = *ip;
+ if(val < 0) {
+ ParseError("encountered negative integer index (binary)");
+ }
+
+ AI_SWAP4(val);
+ out.push_back(val);
+ }
+
+ return;
+ }
+
+ const size_t dim = ParseTokenAsDim(*tok[0]);
+
+ // see notes in ParseVectorDataArray()
+ out.reserve(dim);
+
+ const Scope& scope = GetRequiredScope(el);
+ const Element& a = GetRequiredElement(scope,"a",&el);
+
+ for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) {
+ const int ival = ParseTokenAsInt(**it++);
+ if(ival < 0) {
+ ParseError("encountered negative integer index");
+ }
+ out.push_back(static_cast<unsigned int>(ival));
+ }
+}
+
+
+// ------------------------------------------------------------------------------------------------
+// read an array of uint64_ts
+void ParseVectorDataArray(std::vector<uint64_t>& out, const Element& el)
+{
+ out.resize( 0 );
+ const TokenList& tok = el.Tokens();
+ if(tok.empty()) {
+ ParseError("unexpected empty element",&el);
+ }
+
+ if(tok[0]->IsBinary()) {
+ const char* data = tok[0]->begin(), *end = tok[0]->end();
+
+ char type;
+ uint32_t count;
+ ReadBinaryDataArrayHead(data, end, type, count, el);
+
+ if(!count) {
+ return;
+ }
+
+ if (type != 'l') {
+ ParseError("expected long array (binary)",&el);
+ }
+
+ std::vector<char> buff;
+ ReadBinaryDataArray(type, count, data, end, buff, el);
+
+ ai_assert(data == end);
+ ai_assert(buff.size() == count * 8);
+
+ out.reserve(count);
+
+ const uint64_t* ip = reinterpret_cast<const uint64_t*>(&buff[0]);
+ for (unsigned int i = 0; i < count; ++i, ++ip) {
+ BE_NCONST uint64_t val = *ip;
+ AI_SWAP8(val);
+ out.push_back(val);
+ }
+
+ return;
+ }
+
+ const size_t dim = ParseTokenAsDim(*tok[0]);
+
+ // see notes in ParseVectorDataArray()
+ out.reserve(dim);
+
+ const Scope& scope = GetRequiredScope(el);
+ const Element& a = GetRequiredElement(scope,"a",&el);
+
+ for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) {
+ const uint64_t ival = ParseTokenAsID(**it++);
+
+ out.push_back(ival);
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// read an array of int64_ts
+void ParseVectorDataArray(std::vector<int64_t>& out, const Element& el)
+{
+ out.resize( 0 );
+ const TokenList& tok = el.Tokens();
+ if (tok.empty()) {
+ ParseError("unexpected empty element", &el);
+ }
+
+ if (tok[0]->IsBinary()) {
+ const char* data = tok[0]->begin(), *end = tok[0]->end();
+
+ char type;
+ uint32_t count;
+ ReadBinaryDataArrayHead(data, end, type, count, el);
+
+ if (!count) {
+ return;
+ }
+
+ if (type != 'l') {
+ ParseError("expected long array (binary)", &el);
+ }
+
+ std::vector<char> buff;
+ ReadBinaryDataArray(type, count, data, end, buff, el);
+
+ ai_assert(data == end);
+ ai_assert(buff.size() == count * 8);
+
+ out.reserve(count);
+
+ const int64_t* ip = reinterpret_cast<const int64_t*>(&buff[0]);
+ for (unsigned int i = 0; i < count; ++i, ++ip) {
+ BE_NCONST int64_t val = *ip;
+ AI_SWAP8(val);
+ out.push_back(val);
+ }
+
+ return;
+ }
+
+ const size_t dim = ParseTokenAsDim(*tok[0]);
+
+ // see notes in ParseVectorDataArray()
+ out.reserve(dim);
+
+ const Scope& scope = GetRequiredScope(el);
+ const Element& a = GetRequiredElement(scope, "a", &el);
+
+ for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end;) {
+ const int64_t ival = ParseTokenAsInt64(**it++);
+
+ out.push_back(ival);
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+aiMatrix4x4 ReadMatrix(const Element& element)
+{
+ std::vector<float> values;
+ ParseVectorDataArray(values,element);
+
+ if(values.size() != 16) {
+ ParseError("expected 16 matrix elements");
+ }
+
+ aiMatrix4x4 result;
+
+
+ result.a1 = values[0];
+ result.a2 = values[1];
+ result.a3 = values[2];
+ result.a4 = values[3];
+
+ result.b1 = values[4];
+ result.b2 = values[5];
+ result.b3 = values[6];
+ result.b4 = values[7];
+
+ result.c1 = values[8];
+ result.c2 = values[9];
+ result.c3 = values[10];
+ result.c4 = values[11];
+
+ result.d1 = values[12];
+ result.d2 = values[13];
+ result.d3 = values[14];
+ result.d4 = values[15];
+
+ result.Transpose();
+ return result;
+}
+
+
+// ------------------------------------------------------------------------------------------------
+// wrapper around ParseTokenAsString() with ParseError handling
+std::string ParseTokenAsString(const Token& t)
+{
+ const char* err;
+ const std::string& i = ParseTokenAsString(t,err);
+ if(err) {
+ ParseError(err,t);
+ }
+ return i;
+}
+
+bool HasElement( const Scope& sc, const std::string& index ) {
+ const Element* el = sc[ index ];
+ if ( nullptr == el ) {
+ return false;
+ }
+
+ return true;
+}
+
+// ------------------------------------------------------------------------------------------------
+// extract a required element from a scope, abort if the element cannot be found
+const Element& GetRequiredElement(const Scope& sc, const std::string& index, const Element* element /*= NULL*/)
+{
+ const Element* el = sc[index];
+ if(!el) {
+ ParseError("did not find required element \"" + index + "\"",element);
+ }
+ return *el;
+}
+
+
+// ------------------------------------------------------------------------------------------------
+// extract required compound scope
+const Scope& GetRequiredScope(const Element& el)
+{
+ const Scope* const s = el.Compound();
+ if(!s) {
+ ParseError("expected compound scope",&el);
+ }
+
+ return *s;
+}
+
+
+// ------------------------------------------------------------------------------------------------
+// get token at a particular index
+const Token& GetRequiredToken(const Element& el, unsigned int index)
+{
+ const TokenList& t = el.Tokens();
+ if(index >= t.size()) {
+ ParseError(Formatter::format( "missing token at index " ) << index,&el);
+ }
+
+ return *t[index];
+}
+
+
+// ------------------------------------------------------------------------------------------------
+// wrapper around ParseTokenAsID() with ParseError handling
+uint64_t ParseTokenAsID(const Token& t)
+{
+ const char* err;
+ const uint64_t i = ParseTokenAsID(t,err);
+ if(err) {
+ ParseError(err,t);
+ }
+ return i;
+}
+
+
+// ------------------------------------------------------------------------------------------------
+// wrapper around ParseTokenAsDim() with ParseError handling
+size_t ParseTokenAsDim(const Token& t)
+{
+ const char* err;
+ const size_t i = ParseTokenAsDim(t,err);
+ if(err) {
+ ParseError(err,t);
+ }
+ return i;
+}
+
+
+// ------------------------------------------------------------------------------------------------
+// wrapper around ParseTokenAsFloat() with ParseError handling
+float ParseTokenAsFloat(const Token& t)
+{
+ const char* err;
+ const float i = ParseTokenAsFloat(t,err);
+ if(err) {
+ ParseError(err,t);
+ }
+ return i;
+}
+
+
+// ------------------------------------------------------------------------------------------------
+// wrapper around ParseTokenAsInt() with ParseError handling
+int ParseTokenAsInt(const Token& t)
+{
+ const char* err;
+ const int i = ParseTokenAsInt(t,err);
+ if(err) {
+ ParseError(err,t);
+ }
+ return i;
+}
+
+
+
+// ------------------------------------------------------------------------------------------------
+// wrapper around ParseTokenAsInt64() with ParseError handling
+int64_t ParseTokenAsInt64(const Token& t)
+{
+ const char* err;
+ const int64_t i = ParseTokenAsInt64(t, err);
+ if (err) {
+ ParseError(err, t);
+ }
+ return i;
+}
+
+} // !FBX
+} // !Assimp
+
+#endif
diff --git a/thirdparty/assimp/code/FBXParser.h b/thirdparty/assimp/code/FBXParser.h
new file mode 100644
index 0000000000..7b0cf72039
--- /dev/null
+++ b/thirdparty/assimp/code/FBXParser.h
@@ -0,0 +1,235 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file FBXParser.h
+ * @brief FBX parsing code
+ */
+#ifndef INCLUDED_AI_FBX_PARSER_H
+#define INCLUDED_AI_FBX_PARSER_H
+
+#include <stdint.h>
+#include <map>
+#include <memory>
+#include <assimp/LogAux.h>
+#include <assimp/fast_atof.h>
+
+#include "FBXCompileConfig.h"
+#include "FBXTokenizer.h"
+
+namespace Assimp {
+namespace FBX {
+
+class Scope;
+class Parser;
+class Element;
+
+// XXX should use C++11's unique_ptr - but assimp's need to keep working with 03
+typedef std::vector< Scope* > ScopeList;
+typedef std::fbx_unordered_multimap< std::string, Element* > ElementMap;
+
+typedef std::pair<ElementMap::const_iterator,ElementMap::const_iterator> ElementCollection;
+
+# define new_Scope new Scope
+# define new_Element new Element
+
+
+/** FBX data entity that consists of a key:value tuple.
+ *
+ * Example:
+ * @verbatim
+ * AnimationCurve: 23, "AnimCurve::", "" {
+ * [..]
+ * }
+ * @endverbatim
+ *
+ * As can be seen in this sample, elements can contain nested #Scope
+ * as their trailing member. **/
+class Element
+{
+public:
+ Element(const Token& key_token, Parser& parser);
+ ~Element();
+
+ const Scope* Compound() const {
+ return compound.get();
+ }
+
+ const Token& KeyToken() const {
+ return key_token;
+ }
+
+ const TokenList& Tokens() const {
+ return tokens;
+ }
+
+private:
+ const Token& key_token;
+ TokenList tokens;
+ std::unique_ptr<Scope> compound;
+};
+
+/** FBX data entity that consists of a 'scope', a collection
+ * of not necessarily unique #Element instances.
+ *
+ * Example:
+ * @verbatim
+ * GlobalSettings: {
+ * Version: 1000
+ * Properties70:
+ * [...]
+ * }
+ * @endverbatim */
+class Scope
+{
+public:
+ Scope(Parser& parser, bool topLevel = false);
+ ~Scope();
+
+ const Element* operator[] (const std::string& index) const {
+ ElementMap::const_iterator it = elements.find(index);
+ return it == elements.end() ? NULL : (*it).second;
+ }
+
+ const Element* FindElementCaseInsensitive(const std::string& elementName) const {
+ const char* elementNameCStr = elementName.c_str();
+ for (auto element = elements.begin(); element != elements.end(); ++element)
+ {
+ if (!ASSIMP_strincmp(element->first.c_str(), elementNameCStr, MAXLEN)) {
+ return element->second;
+ }
+ }
+ return NULL;
+ }
+
+ ElementCollection GetCollection(const std::string& index) const {
+ return elements.equal_range(index);
+ }
+
+ const ElementMap& Elements() const {
+ return elements;
+ }
+
+private:
+ ElementMap elements;
+};
+
+/** FBX parsing class, takes a list of input tokens and generates a hierarchy
+ * of nested #Scope instances, representing the fbx DOM.*/
+class Parser
+{
+public:
+ /** Parse given a token list. Does not take ownership of the tokens -
+ * the objects must persist during the entire parser lifetime */
+ Parser (const TokenList& tokens,bool is_binary);
+ ~Parser();
+
+ const Scope& GetRootScope() const {
+ return *root.get();
+ }
+
+ bool IsBinary() const {
+ return is_binary;
+ }
+
+private:
+ friend class Scope;
+ friend class Element;
+
+ TokenPtr AdvanceToNextToken();
+ TokenPtr LastToken() const;
+ TokenPtr CurrentToken() const;
+
+private:
+ const TokenList& tokens;
+
+ TokenPtr last, current;
+ TokenList::const_iterator cursor;
+ std::unique_ptr<Scope> root;
+
+ const bool is_binary;
+};
+
+
+/* token parsing - this happens when building the DOM out of the parse-tree*/
+uint64_t ParseTokenAsID(const Token& t, const char*& err_out);
+size_t ParseTokenAsDim(const Token& t, const char*& err_out);
+
+float ParseTokenAsFloat(const Token& t, const char*& err_out);
+int ParseTokenAsInt(const Token& t, const char*& err_out);
+int64_t ParseTokenAsInt64(const Token& t, const char*& err_out);
+std::string ParseTokenAsString(const Token& t, const char*& err_out);
+
+/* wrapper around ParseTokenAsXXX() with DOMError handling */
+uint64_t ParseTokenAsID(const Token& t);
+size_t ParseTokenAsDim(const Token& t);
+float ParseTokenAsFloat(const Token& t);
+int ParseTokenAsInt(const Token& t);
+int64_t ParseTokenAsInt64(const Token& t);
+std::string ParseTokenAsString(const Token& t);
+
+/* read data arrays */
+void ParseVectorDataArray(std::vector<aiVector3D>& out, const Element& el);
+void ParseVectorDataArray(std::vector<aiColor4D>& out, const Element& el);
+void ParseVectorDataArray(std::vector<aiVector2D>& out, const Element& el);
+void ParseVectorDataArray(std::vector<int>& out, const Element& el);
+void ParseVectorDataArray(std::vector<float>& out, const Element& el);
+void ParseVectorDataArray(std::vector<unsigned int>& out, const Element& el);
+void ParseVectorDataArray(std::vector<uint64_t>& out, const Element& e);
+void ParseVectorDataArray(std::vector<int64_t>& out, const Element& el);
+
+bool HasElement( const Scope& sc, const std::string& index );
+
+// extract a required element from a scope, abort if the element cannot be found
+const Element& GetRequiredElement(const Scope& sc, const std::string& index, const Element* element = NULL);
+
+// extract required compound scope
+const Scope& GetRequiredScope(const Element& el);
+// get token at a particular index
+const Token& GetRequiredToken(const Element& el, unsigned int index);
+
+// read a 4x4 matrix from an array of 16 floats
+aiMatrix4x4 ReadMatrix(const Element& element);
+
+} // ! FBX
+} // ! Assimp
+
+#endif // ! INCLUDED_AI_FBX_PARSER_H
diff --git a/thirdparty/assimp/code/FBXProperties.cpp b/thirdparty/assimp/code/FBXProperties.cpp
new file mode 100644
index 0000000000..8d7036b6a9
--- /dev/null
+++ b/thirdparty/assimp/code/FBXProperties.cpp
@@ -0,0 +1,235 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file FBXProperties.cpp
+ * @brief Implementation of the FBX dynamic properties system
+ */
+
+#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
+
+#include "FBXTokenizer.h"
+#include "FBXParser.h"
+#include "FBXDocument.h"
+#include "FBXDocumentUtil.h"
+#include "FBXProperties.h"
+
+namespace Assimp {
+namespace FBX {
+
+ using namespace Util;
+
+// ------------------------------------------------------------------------------------------------
+Property::Property()
+{
+}
+
+// ------------------------------------------------------------------------------------------------
+Property::~Property()
+{
+}
+
+namespace {
+
+// ------------------------------------------------------------------------------------------------
+// read a typed property out of a FBX element. The return value is NULL if the property cannot be read.
+Property* ReadTypedProperty(const Element& element)
+{
+ ai_assert(element.KeyToken().StringContents() == "P");
+
+ const TokenList& tok = element.Tokens();
+ ai_assert(tok.size() >= 5);
+
+ const std::string& s = ParseTokenAsString(*tok[1]);
+ const char* const cs = s.c_str();
+ if (!strcmp(cs,"KString")) {
+ return new TypedProperty<std::string>(ParseTokenAsString(*tok[4]));
+ }
+ else if (!strcmp(cs,"bool") || !strcmp(cs,"Bool")) {
+ return new TypedProperty<bool>(ParseTokenAsInt(*tok[4]) != 0);
+ }
+ else if (!strcmp(cs, "int") || !strcmp(cs, "Int") || !strcmp(cs, "enum") || !strcmp(cs, "Enum")) {
+ return new TypedProperty<int>(ParseTokenAsInt(*tok[4]));
+ }
+ else if (!strcmp(cs, "ULongLong")) {
+ return new TypedProperty<uint64_t>(ParseTokenAsID(*tok[4]));
+ }
+ else if (!strcmp(cs, "KTime")) {
+ return new TypedProperty<int64_t>(ParseTokenAsInt64(*tok[4]));
+ }
+ else if (!strcmp(cs,"Vector3D") ||
+ !strcmp(cs,"ColorRGB") ||
+ !strcmp(cs,"Vector") ||
+ !strcmp(cs,"Color") ||
+ !strcmp(cs,"Lcl Translation") ||
+ !strcmp(cs,"Lcl Rotation") ||
+ !strcmp(cs,"Lcl Scaling")
+ ) {
+ return new TypedProperty<aiVector3D>(aiVector3D(
+ ParseTokenAsFloat(*tok[4]),
+ ParseTokenAsFloat(*tok[5]),
+ ParseTokenAsFloat(*tok[6]))
+ );
+ }
+ else if (!strcmp(cs,"double") || !strcmp(cs,"Number") || !strcmp(cs,"Float") || !strcmp(cs,"FieldOfView") || !strcmp( cs, "UnitScaleFactor" ) ) {
+ return new TypedProperty<float>(ParseTokenAsFloat(*tok[4]));
+ }
+ return NULL;
+}
+
+
+// ------------------------------------------------------------------------------------------------
+// peek into an element and check if it contains a FBX property, if so return its name.
+std::string PeekPropertyName(const Element& element)
+{
+ ai_assert(element.KeyToken().StringContents() == "P");
+ const TokenList& tok = element.Tokens();
+ if(tok.size() < 4) {
+ return "";
+ }
+
+ return ParseTokenAsString(*tok[0]);
+}
+
+} //! anon
+
+
+// ------------------------------------------------------------------------------------------------
+PropertyTable::PropertyTable()
+: templateProps()
+, element()
+{
+}
+
+// ------------------------------------------------------------------------------------------------
+PropertyTable::PropertyTable(const Element& element, std::shared_ptr<const PropertyTable> templateProps)
+: templateProps(templateProps)
+, element(&element)
+{
+ const Scope& scope = GetRequiredScope(element);
+ for(const ElementMap::value_type& v : scope.Elements()) {
+ if(v.first != "P") {
+ DOMWarning("expected only P elements in property table",v.second);
+ continue;
+ }
+
+ const std::string& name = PeekPropertyName(*v.second);
+ if(!name.length()) {
+ DOMWarning("could not read property name",v.second);
+ continue;
+ }
+
+ LazyPropertyMap::const_iterator it = lazyProps.find(name);
+ if (it != lazyProps.end()) {
+ DOMWarning("duplicate property name, will hide previous value: " + name,v.second);
+ continue;
+ }
+
+ lazyProps[name] = v.second;
+ }
+}
+
+
+// ------------------------------------------------------------------------------------------------
+PropertyTable::~PropertyTable()
+{
+ for(PropertyMap::value_type& v : props) {
+ delete v.second;
+ }
+}
+
+
+// ------------------------------------------------------------------------------------------------
+const Property* PropertyTable::Get(const std::string& name) const
+{
+ PropertyMap::const_iterator it = props.find(name);
+ if (it == props.end()) {
+ // hasn't been parsed yet?
+ LazyPropertyMap::const_iterator lit = lazyProps.find(name);
+ if(lit != lazyProps.end()) {
+ props[name] = ReadTypedProperty(*(*lit).second);
+ it = props.find(name);
+
+ ai_assert(it != props.end());
+ }
+
+ if (it == props.end()) {
+ // check property template
+ if(templateProps) {
+ return templateProps->Get(name);
+ }
+
+ return NULL;
+ }
+ }
+
+ return (*it).second;
+}
+
+DirectPropertyMap PropertyTable::GetUnparsedProperties() const
+{
+ DirectPropertyMap result;
+
+ // Loop through all the lazy properties (which is all the properties)
+ for(const LazyPropertyMap::value_type& element : lazyProps) {
+
+ // Skip parsed properties
+ if (props.end() != props.find(element.first)) continue;
+
+ // Read the element's value.
+ // Wrap the naked pointer (since the call site is required to acquire ownership)
+ // std::unique_ptr from C++11 would be preferred both as a wrapper and a return value.
+ std::shared_ptr<Property> prop = std::shared_ptr<Property>(ReadTypedProperty(*element.second));
+
+ // Element could not be read. Skip it.
+ if (!prop) continue;
+
+ // Add to result
+ result[element.first] = prop;
+ }
+
+ return result;
+}
+
+} //! FBX
+} //! Assimp
+
+#endif
diff --git a/thirdparty/assimp/code/FBXProperties.h b/thirdparty/assimp/code/FBXProperties.h
new file mode 100644
index 0000000000..58755542fc
--- /dev/null
+++ b/thirdparty/assimp/code/FBXProperties.h
@@ -0,0 +1,185 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file FBXProperties.h
+ * @brief FBX dynamic properties
+ */
+#ifndef INCLUDED_AI_FBX_PROPERTIES_H
+#define INCLUDED_AI_FBX_PROPERTIES_H
+
+#include "FBXCompileConfig.h"
+#include <memory>
+#include <string>
+
+namespace Assimp {
+namespace FBX {
+
+// Forward declarations
+class Element;
+
+/** Represents a dynamic property. Type info added by deriving classes,
+ * see #TypedProperty.
+ Example:
+ @verbatim
+ P: "ShininessExponent", "double", "Number", "",0.5
+ @endvebatim
+*/
+class Property {
+protected:
+ Property();
+
+public:
+ virtual ~Property();
+
+public:
+ template <typename T>
+ const T* As() const {
+ return dynamic_cast<const T*>(this);
+ }
+};
+
+template<typename T>
+class TypedProperty : public Property {
+public:
+ explicit TypedProperty(const T& value)
+ : value(value) {
+ // empty
+ }
+
+ const T& Value() const {
+ return value;
+ }
+
+private:
+ T value;
+};
+
+
+typedef std::fbx_unordered_map<std::string,std::shared_ptr<Property> > DirectPropertyMap;
+typedef std::fbx_unordered_map<std::string,const Property*> PropertyMap;
+typedef std::fbx_unordered_map<std::string,const Element*> LazyPropertyMap;
+
+/**
+ * Represents a property table as can be found in the newer FBX files (Properties60, Properties70)
+ */
+class PropertyTable {
+public:
+ // in-memory property table with no source element
+ PropertyTable();
+ PropertyTable(const Element& element, std::shared_ptr<const PropertyTable> templateProps);
+ ~PropertyTable();
+
+ const Property* Get(const std::string& name) const;
+
+ // PropertyTable's need not be coupled with FBX elements so this can be NULL
+ const Element* GetElement() const {
+ return element;
+ }
+
+ const PropertyTable* TemplateProps() const {
+ return templateProps.get();
+ }
+
+ DirectPropertyMap GetUnparsedProperties() const;
+
+private:
+ LazyPropertyMap lazyProps;
+ mutable PropertyMap props;
+ const std::shared_ptr<const PropertyTable> templateProps;
+ const Element* const element;
+};
+
+// ------------------------------------------------------------------------------------------------
+template <typename T>
+inline
+T PropertyGet(const PropertyTable& in, const std::string& name, const T& defaultValue) {
+ const Property* const prop = in.Get(name);
+ if( nullptr == prop) {
+ return defaultValue;
+ }
+
+ // strong typing, no need to be lenient
+ const TypedProperty<T>* const tprop = prop->As< TypedProperty<T> >();
+ if( nullptr == tprop) {
+ return defaultValue;
+ }
+
+ return tprop->Value();
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename T>
+inline
+T PropertyGet(const PropertyTable& in, const std::string& name, bool& result, bool useTemplate=false ) {
+ const Property* prop = in.Get(name);
+ if( nullptr == prop) {
+ if ( ! useTemplate ) {
+ result = false;
+ return T();
+ }
+ const PropertyTable* templ = in.TemplateProps();
+ if ( nullptr == templ ) {
+ result = false;
+ return T();
+ }
+ prop = templ->Get(name);
+ if ( nullptr == prop ) {
+ result = false;
+ return T();
+ }
+ }
+
+ // strong typing, no need to be lenient
+ const TypedProperty<T>* const tprop = prop->As< TypedProperty<T> >();
+ if( nullptr == tprop) {
+ result = false;
+ return T();
+ }
+
+ result = true;
+ return tprop->Value();
+}
+
+} //! FBX
+} //! Assimp
+
+#endif // INCLUDED_AI_FBX_PROPERTIES_H
diff --git a/thirdparty/assimp/code/FBXTokenizer.cpp b/thirdparty/assimp/code/FBXTokenizer.cpp
new file mode 100644
index 0000000000..252cce3557
--- /dev/null
+++ b/thirdparty/assimp/code/FBXTokenizer.cpp
@@ -0,0 +1,248 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file FBXTokenizer.cpp
+ * @brief Implementation of the FBX broadphase lexer
+ */
+
+#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
+
+// tab width for logging columns
+#define ASSIMP_FBX_TAB_WIDTH 4
+
+#include <assimp/ParsingUtils.h>
+
+#include "FBXTokenizer.h"
+#include "FBXUtil.h"
+#include <assimp/Exceptional.h>
+
+namespace Assimp {
+namespace FBX {
+
+// ------------------------------------------------------------------------------------------------
+Token::Token(const char* sbegin, const char* send, TokenType type, unsigned int line, unsigned int column)
+ :
+#ifdef DEBUG
+ contents(sbegin, static_cast<size_t>(send-sbegin)),
+#endif
+ sbegin(sbegin)
+ , send(send)
+ , type(type)
+ , line(line)
+ , column(column)
+{
+ ai_assert(sbegin);
+ ai_assert(send);
+
+ // tokens must be of non-zero length
+ ai_assert(static_cast<size_t>(send-sbegin) > 0);
+}
+
+// ------------------------------------------------------------------------------------------------
+Token::~Token()
+{
+}
+
+namespace {
+
+// ------------------------------------------------------------------------------------------------
+// signal tokenization error, this is always unrecoverable. Throws DeadlyImportError.
+AI_WONT_RETURN void TokenizeError(const std::string& message, unsigned int line, unsigned int column) AI_WONT_RETURN_SUFFIX;
+AI_WONT_RETURN void TokenizeError(const std::string& message, unsigned int line, unsigned int column)
+{
+ throw DeadlyImportError(Util::AddLineAndColumn("FBX-Tokenize",message,line,column));
+}
+
+
+// process a potential data token up to 'cur', adding it to 'output_tokens'.
+// ------------------------------------------------------------------------------------------------
+void ProcessDataToken( TokenList& output_tokens, const char*& start, const char*& end,
+ unsigned int line,
+ unsigned int column,
+ TokenType type = TokenType_DATA,
+ bool must_have_token = false)
+{
+ if (start && end) {
+ // sanity check:
+ // tokens should have no whitespace outside quoted text and [start,end] should
+ // properly delimit the valid range.
+ bool in_double_quotes = false;
+ for (const char* c = start; c != end + 1; ++c) {
+ if (*c == '\"') {
+ in_double_quotes = !in_double_quotes;
+ }
+
+ if (!in_double_quotes && IsSpaceOrNewLine(*c)) {
+ TokenizeError("unexpected whitespace in token", line, column);
+ }
+ }
+
+ if (in_double_quotes) {
+ TokenizeError("non-terminated double quotes", line, column);
+ }
+
+ output_tokens.push_back(new_Token(start,end + 1,type,line,column));
+ }
+ else if (must_have_token) {
+ TokenizeError("unexpected character, expected data token", line, column);
+ }
+
+ start = end = NULL;
+}
+
+}
+
+// ------------------------------------------------------------------------------------------------
+void Tokenize(TokenList& output_tokens, const char* input)
+{
+ ai_assert(input);
+
+ // line and column numbers numbers are one-based
+ unsigned int line = 1;
+ unsigned int column = 1;
+
+ bool comment = false;
+ bool in_double_quotes = false;
+ bool pending_data_token = false;
+
+ const char* token_begin = NULL, *token_end = NULL;
+ for (const char* cur = input;*cur;column += (*cur == '\t' ? ASSIMP_FBX_TAB_WIDTH : 1), ++cur) {
+ const char c = *cur;
+
+ if (IsLineEnd(c)) {
+ comment = false;
+
+ column = 0;
+ ++line;
+ }
+
+ if(comment) {
+ continue;
+ }
+
+ if(in_double_quotes) {
+ if (c == '\"') {
+ in_double_quotes = false;
+ token_end = cur;
+
+ ProcessDataToken(output_tokens,token_begin,token_end,line,column);
+ pending_data_token = false;
+ }
+ continue;
+ }
+
+ switch(c)
+ {
+ case '\"':
+ if (token_begin) {
+ TokenizeError("unexpected double-quote", line, column);
+ }
+ token_begin = cur;
+ in_double_quotes = true;
+ continue;
+
+ case ';':
+ ProcessDataToken(output_tokens,token_begin,token_end,line,column);
+ comment = true;
+ continue;
+
+ case '{':
+ ProcessDataToken(output_tokens,token_begin,token_end, line, column);
+ output_tokens.push_back(new_Token(cur,cur+1,TokenType_OPEN_BRACKET,line,column));
+ continue;
+
+ case '}':
+ ProcessDataToken(output_tokens,token_begin,token_end,line,column);
+ output_tokens.push_back(new_Token(cur,cur+1,TokenType_CLOSE_BRACKET,line,column));
+ continue;
+
+ case ',':
+ if (pending_data_token) {
+ ProcessDataToken(output_tokens,token_begin,token_end,line,column,TokenType_DATA,true);
+ }
+ output_tokens.push_back(new_Token(cur,cur+1,TokenType_COMMA,line,column));
+ continue;
+
+ case ':':
+ if (pending_data_token) {
+ ProcessDataToken(output_tokens,token_begin,token_end,line,column,TokenType_KEY,true);
+ }
+ else {
+ TokenizeError("unexpected colon", line, column);
+ }
+ continue;
+ }
+
+ if (IsSpaceOrNewLine(c)) {
+
+ if (token_begin) {
+ // peek ahead and check if the next token is a colon in which
+ // case this counts as KEY token.
+ TokenType type = TokenType_DATA;
+ for (const char* peek = cur; *peek && IsSpaceOrNewLine(*peek); ++peek) {
+ if (*peek == ':') {
+ type = TokenType_KEY;
+ cur = peek;
+ break;
+ }
+ }
+
+ ProcessDataToken(output_tokens,token_begin,token_end,line,column,type);
+ }
+
+ pending_data_token = false;
+ }
+ else {
+ token_end = cur;
+ if (!token_begin) {
+ token_begin = cur;
+ }
+
+ pending_data_token = true;
+ }
+ }
+}
+
+} // !FBX
+} // !Assimp
+
+#endif
diff --git a/thirdparty/assimp/code/FBXTokenizer.h b/thirdparty/assimp/code/FBXTokenizer.h
new file mode 100644
index 0000000000..2af29743f4
--- /dev/null
+++ b/thirdparty/assimp/code/FBXTokenizer.h
@@ -0,0 +1,187 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file FBXTokenizer.h
+ * @brief FBX lexer
+ */
+#ifndef INCLUDED_AI_FBX_TOKENIZER_H
+#define INCLUDED_AI_FBX_TOKENIZER_H
+
+#include "FBXCompileConfig.h"
+#include <assimp/ai_assert.h>
+#include <vector>
+#include <string>
+
+namespace Assimp {
+namespace FBX {
+
+/** Rough classification for text FBX tokens used for constructing the
+ * basic scope hierarchy. */
+enum TokenType
+{
+ // {
+ TokenType_OPEN_BRACKET = 0,
+
+ // }
+ TokenType_CLOSE_BRACKET,
+
+ // '"blablubb"', '2', '*14' - very general token class,
+ // further processing happens at a later stage.
+ TokenType_DATA,
+
+ //
+ TokenType_BINARY_DATA,
+
+ // ,
+ TokenType_COMMA,
+
+ // blubb:
+ TokenType_KEY
+};
+
+
+/** Represents a single token in a FBX file. Tokens are
+ * classified by the #TokenType enumerated types.
+ *
+ * Offers iterator protocol. Tokens are immutable. */
+class Token
+{
+private:
+ static const unsigned int BINARY_MARKER = static_cast<unsigned int>(-1);
+
+public:
+ /** construct a textual token */
+ Token(const char* sbegin, const char* send, TokenType type, unsigned int line, unsigned int column);
+
+ /** construct a binary token */
+ Token(const char* sbegin, const char* send, TokenType type, unsigned int offset);
+
+ ~Token();
+
+public:
+ std::string StringContents() const {
+ return std::string(begin(),end());
+ }
+
+ bool IsBinary() const {
+ return column == BINARY_MARKER;
+ }
+
+ const char* begin() const {
+ return sbegin;
+ }
+
+ const char* end() const {
+ return send;
+ }
+
+ TokenType Type() const {
+ return type;
+ }
+
+ unsigned int Offset() const {
+ ai_assert(IsBinary());
+ return offset;
+ }
+
+ unsigned int Line() const {
+ ai_assert(!IsBinary());
+ return line;
+ }
+
+ unsigned int Column() const {
+ ai_assert(!IsBinary());
+ return column;
+ }
+
+private:
+
+#ifdef DEBUG
+ // full string copy for the sole purpose that it nicely appears
+ // in msvc's debugger window.
+ const std::string contents;
+#endif
+
+
+ const char* const sbegin;
+ const char* const send;
+ const TokenType type;
+
+ union {
+ const unsigned int line;
+ unsigned int offset;
+ };
+ const unsigned int column;
+};
+
+// XXX should use C++11's unique_ptr - but assimp's need to keep working with 03
+typedef const Token* TokenPtr;
+typedef std::vector< TokenPtr > TokenList;
+
+#define new_Token new Token
+
+
+/** Main FBX tokenizer function. Transform input buffer into a list of preprocessed tokens.
+ *
+ * Skips over comments and generates line and column numbers.
+ *
+ * @param output_tokens Receives a list of all tokens in the input data.
+ * @param input_buffer Textual input buffer to be processed, 0-terminated.
+ * @throw DeadlyImportError if something goes wrong */
+void Tokenize(TokenList& output_tokens, const char* input);
+
+
+/** Tokenizer function for binary FBX files.
+ *
+ * Emits a token list suitable for direct parsing.
+ *
+ * @param output_tokens Receives a list of all tokens in the input data.
+ * @param input_buffer Binary input buffer to be processed.
+ * @param length Length of input buffer, in bytes. There is no 0-terminal.
+ * @throw DeadlyImportError if something goes wrong */
+void TokenizeBinary(TokenList& output_tokens, const char* input, unsigned int length);
+
+
+} // ! FBX
+} // ! Assimp
+
+#endif // ! INCLUDED_AI_FBX_PARSER_H
diff --git a/thirdparty/assimp/code/FBXUtil.cpp b/thirdparty/assimp/code/FBXUtil.cpp
new file mode 100644
index 0000000000..fb483161b2
--- /dev/null
+++ b/thirdparty/assimp/code/FBXUtil.cpp
@@ -0,0 +1,164 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file FBXUtil.cpp
+ * @brief Implementation of internal FBX utility functions
+ */
+
+#include "FBXUtil.h"
+#include "FBXTokenizer.h"
+
+#include <assimp/TinyFormatter.h>
+#include <string>
+#include <cstring>
+
+#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
+
+namespace Assimp {
+namespace FBX {
+namespace Util {
+
+// ------------------------------------------------------------------------------------------------
+const char* TokenTypeString(TokenType t)
+{
+ switch(t) {
+ case TokenType_OPEN_BRACKET:
+ return "TOK_OPEN_BRACKET";
+
+ case TokenType_CLOSE_BRACKET:
+ return "TOK_CLOSE_BRACKET";
+
+ case TokenType_DATA:
+ return "TOK_DATA";
+
+ case TokenType_COMMA:
+ return "TOK_COMMA";
+
+ case TokenType_KEY:
+ return "TOK_KEY";
+
+ case TokenType_BINARY_DATA:
+ return "TOK_BINARY_DATA";
+ }
+
+ ai_assert(false);
+ return "";
+}
+
+
+// ------------------------------------------------------------------------------------------------
+std::string AddOffset(const std::string& prefix, const std::string& text, unsigned int offset)
+{
+ return static_cast<std::string>( (Formatter::format() << prefix << " (offset 0x" << std::hex << offset << ") " << text) );
+}
+
+// ------------------------------------------------------------------------------------------------
+std::string AddLineAndColumn(const std::string& prefix, const std::string& text, unsigned int line, unsigned int column)
+{
+ return static_cast<std::string>( (Formatter::format() << prefix << " (line " << line << " << col " << column << ") " << text) );
+}
+
+// ------------------------------------------------------------------------------------------------
+std::string AddTokenText(const std::string& prefix, const std::string& text, const Token* tok)
+{
+ if(tok->IsBinary()) {
+ return static_cast<std::string>( (Formatter::format() << prefix <<
+ " (" << TokenTypeString(tok->Type()) <<
+ ", offset 0x" << std::hex << tok->Offset() << ") " <<
+ text) );
+ }
+
+ return static_cast<std::string>( (Formatter::format() << prefix <<
+ " (" << TokenTypeString(tok->Type()) <<
+ ", line " << tok->Line() <<
+ ", col " << tok->Column() << ") " <<
+ text) );
+}
+
+static const uint8_t base64DecodeTable[128] = {
+ 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, 62, 0, 0, 0, 63,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 64, 0, 0,
+ 0, 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, 0, 0, 0, 0, 0,
+ 0, 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, 0, 0, 0, 0, 0
+};
+
+uint8_t DecodeBase64(char ch)
+{
+ return base64DecodeTable[size_t(ch)];
+}
+
+size_t DecodeBase64(const char* in, size_t inLength, uint8_t*& out)
+{
+ if (inLength < 4) {
+ out = 0;
+ return 0;
+ }
+
+ const size_t outLength = (inLength * 3) / 4;
+ out = new uint8_t[outLength];
+ memset(out, 0, outLength);
+
+ size_t i = 0;
+ size_t j = 0;
+ for (i = 0; i < inLength - 4; i += 4)
+ {
+ uint8_t b0 = Util::DecodeBase64(in[i]);
+ uint8_t b1 = Util::DecodeBase64(in[i + 1]);
+ uint8_t b2 = Util::DecodeBase64(in[i + 2]);
+ uint8_t b3 = Util::DecodeBase64(in[i + 3]);
+
+ out[j++] = (uint8_t)((b0 << 2) | (b1 >> 4));
+ out[j++] = (uint8_t)((b1 << 4) | (b2 >> 2));
+ out[j++] = (uint8_t)((b2 << 6) | b3);
+ }
+ return outLength;
+}
+
+} // !Util
+} // !FBX
+} // !Assimp
+
+#endif
diff --git a/thirdparty/assimp/code/FBXUtil.h b/thirdparty/assimp/code/FBXUtil.h
new file mode 100644
index 0000000000..6890e015ba
--- /dev/null
+++ b/thirdparty/assimp/code/FBXUtil.h
@@ -0,0 +1,120 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file FBXUtil.h
+ * @brief FBX utility functions for internal use
+ */
+#ifndef INCLUDED_AI_FBX_UTIL_H
+#define INCLUDED_AI_FBX_UTIL_H
+
+#include "FBXCompileConfig.h"
+#include "FBXTokenizer.h"
+#include <stdint.h>
+
+namespace Assimp {
+namespace FBX {
+
+
+namespace Util {
+
+
+/** helper for std::for_each to delete all heap-allocated items in a container */
+template<typename T>
+struct delete_fun
+{
+ void operator()(const volatile T* del) {
+ delete del;
+ }
+};
+
+/** Get a string representation for a #TokenType. */
+const char* TokenTypeString(TokenType t);
+
+
+
+/** Format log/error messages using a given offset in the source binary file
+ *
+ * @param prefix Message prefix to be preprended to the location info.
+ * @param text Message text
+ * @param line Line index, 1-based
+ * @param column Column index, 1-based
+ * @return A string of the following format: {prefix} (offset 0x{offset}) {text}*/
+std::string AddOffset(const std::string& prefix, const std::string& text, unsigned int offset);
+
+
+/** Format log/error messages using a given line location in the source file.
+ *
+ * @param prefix Message prefix to be preprended to the location info.
+ * @param text Message text
+ * @param line Line index, 1-based
+ * @param column Column index, 1-based
+ * @return A string of the following format: {prefix} (line {line}, col {column}) {text}*/
+std::string AddLineAndColumn(const std::string& prefix, const std::string& text, unsigned int line, unsigned int column);
+
+
+/** Format log/error messages using a given cursor token.
+ *
+ * @param prefix Message prefix to be preprended to the location info.
+ * @param text Message text
+ * @param tok Token where parsing/processing stopped
+ * @return A string of the following format: {prefix} ({token-type}, line {line}, col {column}) {text}*/
+std::string AddTokenText(const std::string& prefix, const std::string& text, const Token* tok);
+
+/** Decode a single Base64-encoded character.
+*
+* @param ch Character to decode (from base64 to binary).
+* @return decoded byte value*/
+uint8_t DecodeBase64(char ch);
+
+/** Decode a Base64-encoded string
+*
+* @param in Characters to decode.
+* @param inLength Number of characters to decode.
+* @param out Reference to pointer where we will store the decoded data.
+* @return size of the decoded data (number of bytes)*/
+size_t DecodeBase64(const char* in, size_t inLength, uint8_t*& out);
+
+}
+}
+}
+
+#endif // ! INCLUDED_AI_FBX_UTIL_H
diff --git a/thirdparty/assimp/code/FIReader.cpp b/thirdparty/assimp/code/FIReader.cpp
new file mode 100644
index 0000000000..2116316ca3
--- /dev/null
+++ b/thirdparty/assimp/code/FIReader.cpp
@@ -0,0 +1,1834 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+/// \file FIReader.cpp
+/// \brief Reader for Fast Infoset encoded binary XML files.
+/// \date 2017
+/// \author Patrick Daehne
+
+#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
+
+#include "FIReader.hpp"
+#include <assimp/StringUtils.h>
+
+// Workaround for issue #1361
+// https://github.com/assimp/assimp/issues/1361
+#ifdef __ANDROID__
+# define _GLIBCXX_USE_C99 1
+#endif
+
+#include <assimp/Exceptional.h>
+#include <assimp/IOStream.hpp>
+#include <assimp/types.h>
+#include <assimp/MemoryIOWrapper.h>
+#include <assimp/irrXMLWrapper.h>
+#include "../contrib/utf8cpp/source/utf8.h"
+#include <assimp/fast_atof.h>
+#include <stack>
+#include <map>
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+
+namespace Assimp {
+
+static const std::string parseErrorMessage = "Fast Infoset parse error";
+
+static const char *xmlDeclarations[] = {
+ "<?xml encoding='finf'?>",
+ "<?xml encoding='finf' standalone='yes'?>",
+ "<?xml encoding='finf' standalone='no'?>",
+ "<?xml version='1.0' encoding='finf'?>",
+ "<?xml version='1.0' encoding='finf' standalone='yes'?>",
+ "<?xml version='1.0' encoding='finf' standalone='no'?>",
+ "<?xml version='1.1' encoding='finf'?>",
+ "<?xml version='1.1' encoding='finf' standalone='yes'?>",
+ "<?xml version='1.1' encoding='finf' standalone='no'?>"
+};
+
+static size_t parseMagic(const uint8_t *data, const uint8_t *dataEnd) {
+ if (dataEnd - data < 4) {
+ return 0;
+ }
+ uint32_t magic = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
+ switch (magic) {
+ case 0xe0000001:
+ return 4;
+ case 0x3c3f786d: // "<?xm"
+ {
+ size_t xmlDeclarationsLength = sizeof(xmlDeclarations) / sizeof(xmlDeclarations[0]);
+ for (size_t i = 0; i < xmlDeclarationsLength; ++i) {
+ auto xmlDeclaration = xmlDeclarations[i];
+ ptrdiff_t xmlDeclarationLength = strlen(xmlDeclaration);
+ if ((dataEnd - data >= xmlDeclarationLength) && (memcmp(xmlDeclaration, data, xmlDeclarationLength) == 0)) {
+ data += xmlDeclarationLength;
+ if (dataEnd - data < 4) {
+ return 0;
+ }
+ magic = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
+ return magic == 0xe0000001 ? xmlDeclarationLength + 4 : 0;
+ }
+ }
+ return 0;
+ }
+ default:
+ return 0;
+ }
+}
+
+static std::string parseUTF8String(const uint8_t *data, size_t len) {
+ return std::string((char*)data, len);
+}
+
+static std::string parseUTF16String(const uint8_t *data, size_t len) {
+ if (len & 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ size_t numShorts = len / 2;
+ std::vector<short> utf16;
+ utf16.reserve(numShorts);
+ for (size_t i = 0; i < numShorts; ++i) {
+ short v = (data[0] << 8) | data[1];
+ utf16.push_back(v);
+ data += 2;
+ }
+ std::string result;
+ utf8::utf16to8(utf16.begin(), utf16.end(), back_inserter(result));
+ return result;
+}
+
+struct FIStringValueImpl: public FIStringValue {
+ inline FIStringValueImpl(std::string &&value_) { value = std::move(value_); }
+ virtual const std::string &toString() const /*override*/ { return value; }
+};
+
+std::shared_ptr<FIStringValue> FIStringValue::create(std::string &&value) {
+ return std::make_shared<FIStringValueImpl>(std::move(value));
+}
+
+struct FIHexValueImpl: public FIHexValue {
+ mutable std::string strValue;
+ mutable bool strValueValid;
+ inline FIHexValueImpl(std::vector<uint8_t> &&value_): strValueValid(false) { value = std::move(value_); }
+ virtual const std::string &toString() const /*override*/ {
+ if (!strValueValid) {
+ strValueValid = true;
+ std::ostringstream os;
+ os << std::hex << std::uppercase << std::setfill('0');
+ std::for_each(value.begin(), value.end(), [&](uint8_t c) { os << std::setw(2) << static_cast<int>(c); });
+ strValue = os.str();
+ }
+ return strValue;
+ };
+};
+
+std::shared_ptr<FIHexValue> FIHexValue::create(std::vector<uint8_t> &&value) {
+ return std::make_shared<FIHexValueImpl>(std::move(value));
+}
+
+struct FIBase64ValueImpl: public FIBase64Value {
+ mutable std::string strValue;
+ mutable bool strValueValid;
+ inline FIBase64ValueImpl(std::vector<uint8_t> &&value_): strValueValid(false) { value = std::move(value_); }
+ virtual const std::string &toString() const /*override*/ {
+ if (!strValueValid) {
+ strValueValid = true;
+ std::ostringstream os;
+ uint8_t c1 = 0, c2;
+ int imod3 = 0;
+ std::vector<uint8_t>::size_type valueSize = value.size();
+ for (std::vector<uint8_t>::size_type i = 0; i < valueSize; ++i) {
+ c2 = value[i];
+ switch (imod3) {
+ case 0:
+ os << basis_64[c2 >> 2];
+ imod3 = 1;
+ break;
+ case 1:
+ os << basis_64[((c1 & 0x03) << 4) | ((c2 & 0xf0) >> 4)];
+ imod3 = 2;
+ break;
+ case 2:
+ os << basis_64[((c1 & 0x0f) << 2) | ((c2 & 0xc0) >> 6)] << basis_64[c2 & 0x3f];
+ imod3 = 0;
+ break;
+ }
+ c1 = c2;
+ }
+ switch (imod3) {
+ case 1:
+ os << basis_64[(c1 & 0x03) << 4] << "==";
+ break;
+ case 2:
+ os << basis_64[(c1 & 0x0f) << 2] << '=';
+ break;
+ }
+ strValue = os.str();
+ }
+ return strValue;
+ };
+ static const char basis_64[];
+};
+
+const char FIBase64ValueImpl::basis_64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+std::shared_ptr<FIBase64Value> FIBase64Value::create(std::vector<uint8_t> &&value) {
+ return std::make_shared<FIBase64ValueImpl>(std::move(value));
+}
+
+struct FIShortValueImpl: public FIShortValue {
+ mutable std::string strValue;
+ mutable bool strValueValid;
+ inline FIShortValueImpl(std::vector<int16_t> &&value_): strValueValid(false) { value = std::move(value_); }
+ virtual const std::string &toString() const /*override*/ {
+ if (!strValueValid) {
+ strValueValid = true;
+ std::ostringstream os;
+ int n = 0;
+ std::for_each(value.begin(), value.end(), [&](int16_t s) { if (++n > 1) os << ' '; os << s; });
+ strValue = os.str();
+ }
+ return strValue;
+ }
+};
+
+std::shared_ptr<FIShortValue> FIShortValue::create(std::vector<int16_t> &&value) {
+ return std::make_shared<FIShortValueImpl>(std::move(value));
+}
+
+struct FIIntValueImpl: public FIIntValue {
+ mutable std::string strValue;
+ mutable bool strValueValid;
+ inline FIIntValueImpl(std::vector<int32_t> &&value_): strValueValid(false) { value = std::move(value_); }
+ virtual const std::string &toString() const /*override*/ {
+ if (!strValueValid) {
+ strValueValid = true;
+ std::ostringstream os;
+ int n = 0;
+ std::for_each(value.begin(), value.end(), [&](int32_t i) { if (++n > 1) os << ' '; os << i; });
+ strValue = os.str();
+ }
+ return strValue;
+ };
+};
+
+std::shared_ptr<FIIntValue> FIIntValue::create(std::vector<int32_t> &&value) {
+ return std::make_shared<FIIntValueImpl>(std::move(value));
+}
+
+struct FILongValueImpl: public FILongValue {
+ mutable std::string strValue;
+ mutable bool strValueValid;
+ inline FILongValueImpl(std::vector<int64_t> &&value_): strValueValid(false) { value = std::move(value_); }
+ virtual const std::string &toString() const /*override*/ {
+ if (!strValueValid) {
+ strValueValid = true;
+ std::ostringstream os;
+ int n = 0;
+ std::for_each(value.begin(), value.end(), [&](int64_t l) { if (++n > 1) os << ' '; os << l; });
+ strValue = os.str();
+ }
+ return strValue;
+ };
+};
+
+std::shared_ptr<FILongValue> FILongValue::create(std::vector<int64_t> &&value) {
+ return std::make_shared<FILongValueImpl>(std::move(value));
+}
+
+struct FIBoolValueImpl: public FIBoolValue {
+ mutable std::string strValue;
+ mutable bool strValueValid;
+ inline FIBoolValueImpl(std::vector<bool> &&value_): strValueValid(false) { value = std::move(value_); }
+ virtual const std::string &toString() const /*override*/ {
+ if (!strValueValid) {
+ strValueValid = true;
+ std::ostringstream os;
+ os << std::boolalpha;
+ int n = 0;
+ std::for_each(value.begin(), value.end(), [&](bool b) { if (++n > 1) os << ' '; os << b; });
+ strValue = os.str();
+ }
+ return strValue;
+ };
+};
+
+std::shared_ptr<FIBoolValue> FIBoolValue::create(std::vector<bool> &&value) {
+ return std::make_shared<FIBoolValueImpl>(std::move(value));
+}
+
+struct FIFloatValueImpl: public FIFloatValue {
+ mutable std::string strValue;
+ mutable bool strValueValid;
+ inline FIFloatValueImpl(std::vector<float> &&value_): strValueValid(false) { value = std::move(value_); }
+ virtual const std::string &toString() const /*override*/ {
+ if (!strValueValid) {
+ strValueValid = true;
+ std::ostringstream os;
+ int n = 0;
+ std::for_each(value.begin(), value.end(), [&](float f) { if (++n > 1) os << ' '; os << f; });
+ strValue = os.str();
+ }
+ return strValue;
+ }
+};
+
+std::shared_ptr<FIFloatValue> FIFloatValue::create(std::vector<float> &&value) {
+ return std::make_shared<FIFloatValueImpl>(std::move(value));
+}
+
+struct FIDoubleValueImpl: public FIDoubleValue {
+ mutable std::string strValue;
+ mutable bool strValueValid;
+ inline FIDoubleValueImpl(std::vector<double> &&value_): strValueValid(false) { value = std::move(value_); }
+ virtual const std::string &toString() const /*override*/ {
+ if (!strValueValid) {
+ strValueValid = true;
+ std::ostringstream os;
+ int n = 0;
+ std::for_each(value.begin(), value.end(), [&](double d) { if (++n > 1) os << ' '; os << d; });
+ strValue = os.str();
+ }
+ return strValue;
+ }
+};
+
+std::shared_ptr<FIDoubleValue> FIDoubleValue::create(std::vector<double> &&value) {
+ return std::make_shared<FIDoubleValueImpl>(std::move(value));
+}
+
+struct FIUUIDValueImpl: public FIUUIDValue {
+ mutable std::string strValue;
+ mutable bool strValueValid;
+ inline FIUUIDValueImpl(std::vector<uint8_t> &&value_): strValueValid(false) { value = std::move(value_); }
+ virtual const std::string &toString() const /*override*/ {
+ if (!strValueValid) {
+ strValueValid = true;
+ std::ostringstream os;
+ os << std::hex << std::uppercase << std::setfill('0');
+ std::vector<uint8_t>::size_type valueSize = value.size();
+ for (std::vector<uint8_t>::size_type i = 0; i < valueSize; ++i) {
+ switch (i & 15) {
+ case 0:
+ if (i > 0) {
+ os << ' ';
+ }
+ os << std::setw(2) << static_cast<int>(value[i]);
+ break;
+ case 4:
+ case 6:
+ case 8:
+ case 10:
+ os << '-';
+ // intentionally fall through!
+ case 1:
+ case 2:
+ case 3:
+ case 5:
+ case 7:
+ case 9:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ os << std::setw(2) << static_cast<int>(value[i]);
+ break;
+ }
+ }
+ strValue = os.str();
+ }
+ return strValue;
+ };
+};
+
+std::shared_ptr<FIUUIDValue> FIUUIDValue::create(std::vector<uint8_t> &&value) {
+ return std::make_shared<FIUUIDValueImpl>(std::move(value));
+}
+
+struct FICDATAValueImpl: public FICDATAValue {
+ inline FICDATAValueImpl(std::string &&value_) { value = std::move(value_); }
+ virtual const std::string &toString() const /*override*/ { return value; }
+};
+
+std::shared_ptr<FICDATAValue> FICDATAValue::create(std::string &&value) {
+ return std::make_shared<FICDATAValueImpl>(std::move(value));
+}
+
+struct FIHexDecoder: public FIDecoder {
+ virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) /*override*/ {
+ return FIHexValue::create(std::vector<uint8_t>(data, data + len));
+ }
+};
+
+struct FIBase64Decoder: public FIDecoder {
+ virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) /*override*/ {
+ return FIBase64Value::create(std::vector<uint8_t>(data, data + len));
+ }
+};
+
+struct FIShortDecoder: public FIDecoder {
+ virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) /*override*/ {
+ if (len & 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ std::vector<int16_t> value;
+ size_t numShorts = len / 2;
+ value.reserve(numShorts);
+ for (size_t i = 0; i < numShorts; ++i) {
+ int16_t v = (data[0] << 8) | data[1];
+ value.push_back(v);
+ data += 2;
+ }
+ return FIShortValue::create(std::move(value));
+ }
+};
+
+struct FIIntDecoder: public FIDecoder {
+ virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) /*override*/ {
+ if (len & 3) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ std::vector<int32_t> value;
+ size_t numInts = len / 4;
+ value.reserve(numInts);
+ for (size_t i = 0; i < numInts; ++i) {
+ int32_t v = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
+ value.push_back(v);
+ data += 4;
+ }
+ return FIIntValue::create(std::move(value));
+ }
+};
+
+struct FILongDecoder: public FIDecoder {
+ virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) /*override*/ {
+ if (len & 7) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ std::vector<int64_t> value;
+ size_t numLongs = len / 8;
+ value.reserve(numLongs);
+ for (size_t i = 0; i < numLongs; ++i) {
+ int64_t b0 = data[0], b1 = data[1], b2 = data[2], b3 = data[3], b4 = data[4], b5 = data[5], b6 = data[6], b7 = data[7];
+ int64_t v = (b0 << 56) | (b1 << 48) | (b2 << 40) | (b3 << 32) | (b4 << 24) | (b5 << 16) | (b6 << 8) | b7;
+ value.push_back(v);
+ data += 8;
+ }
+ return FILongValue::create(std::move(value));
+ }
+};
+
+struct FIBoolDecoder: public FIDecoder {
+ virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) /*override*/ {
+ if (len < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ std::vector<bool> value;
+ uint8_t b = *data++;
+ size_t unusedBits = b >> 4;
+ size_t numBools = (len * 8) - 4 - unusedBits;
+ value.reserve(numBools);
+ uint8_t mask = 1 << 3;
+ for (size_t i = 0; i < numBools; ++i) {
+ if (!mask) {
+ mask = 1 << 7;
+ b = *data++;
+ }
+ value.push_back((b & mask) != 0);
+ }
+ return FIBoolValue::create(std::move(value));
+ }
+};
+
+struct FIFloatDecoder: public FIDecoder {
+ virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) /*override*/ {
+ if (len & 3) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ std::vector<float> value;
+ size_t numFloats = len / 4;
+ value.reserve(numFloats);
+ for (size_t i = 0; i < numFloats; ++i) {
+ int v = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
+ float f;
+ memcpy(&f, &v, 4);
+ value.push_back(f);
+ data += 4;
+ }
+ return FIFloatValue::create(std::move(value));
+ }
+};
+
+struct FIDoubleDecoder: public FIDecoder {
+ virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) /*override*/ {
+ if (len & 7) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ std::vector<double> value;
+ size_t numDoubles = len / 8;
+ value.reserve(numDoubles);
+ for (size_t i = 0; i < numDoubles; ++i) {
+ long long b0 = data[0], b1 = data[1], b2 = data[2], b3 = data[3], b4 = data[4], b5 = data[5], b6 = data[6], b7 = data[7];
+ long long v = (b0 << 56) | (b1 << 48) | (b2 << 40) | (b3 << 32) | (b4 << 24) | (b5 << 16) | (b6 << 8) | b7;
+ double f;
+ memcpy(&f, &v, 8);
+ value.push_back(f);
+ data += 8;
+ }
+ return FIDoubleValue::create(std::move(value));
+ }
+};
+
+struct FIUUIDDecoder: public FIDecoder {
+ virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) /*override*/ {
+ if (len & 15) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ return FIUUIDValue::create(std::vector<uint8_t>(data, data + len));
+ }
+};
+
+struct FICDATADecoder: public FIDecoder {
+ virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) /*override*/ {
+ return FICDATAValue::create(parseUTF8String(data, len));
+ }
+};
+
+class CFIReaderImpl: public FIReader {
+public:
+
+ CFIReaderImpl(std::unique_ptr<uint8_t[]> data_, size_t size):
+ data(std::move(data_)), dataP(data.get()), dataEnd(data.get() + size), currentNodeType(irr::io::EXN_NONE),
+ emptyElement(false), headerPending(true), terminatorPending(false)
+ {}
+
+ virtual ~CFIReaderImpl() {}
+
+ virtual bool read() /*override*/ {
+ if (headerPending) {
+ headerPending = false;
+ parseHeader();
+ }
+ if (terminatorPending) {
+ terminatorPending = false;
+ if (elementStack.empty()) {
+ return false;
+ }
+ else {
+ nodeName = elementStack.top();
+ elementStack.pop();
+ currentNodeType = nodeName.empty() ? irr::io::EXN_UNKNOWN : irr::io::EXN_ELEMENT_END;
+ return true;
+ }
+ }
+ if (dataP >= dataEnd) {
+ return false;
+ }
+ uint8_t b = *dataP;
+ if (b < 0x80) { // Element (C.2.11.2, C.3.7.2)
+ // C.3
+ parseElement();
+ return true;
+ }
+ else if (b < 0xc0) { // Characters (C.3.7.5)
+ // C.7
+ auto chars = parseNonIdentifyingStringOrIndex3(vocabulary.charactersTable);
+ nodeName = chars->toString();
+ currentNodeType = irr::io::EXN_TEXT;
+ return true;
+ }
+ else if (b < 0xe0) {
+ if ((b & 0xfc) == 0xc4) { // DTD (C.2.11.5)
+ // C.9
+ ++dataP;
+ if (b & 0x02) {
+ /*const std::string &systemID =*/ parseIdentifyingStringOrIndex(vocabulary.otherURITable);
+ }
+ if (b & 0x01) {
+ /*const std::string &publicID =*/ parseIdentifyingStringOrIndex(vocabulary.otherURITable);
+ }
+ elementStack.push(EmptyString);
+ currentNodeType = irr::io::EXN_UNKNOWN;
+ return true;
+ }
+ else if ((b & 0xfc) == 0xc8) { // Unexpanded entity reference (C.3.7.4)
+ // C.6
+ ++dataP;
+ /*const std::string &name =*/ parseIdentifyingStringOrIndex(vocabulary.otherNCNameTable);
+ if (b & 0x02) {
+ /*const std::string &systemID =*/ parseIdentifyingStringOrIndex(vocabulary.otherURITable);
+ }
+ if (b & 0x01) {
+ /*const std::string &publicID =*/ parseIdentifyingStringOrIndex(vocabulary.otherURITable);
+ }
+ currentNodeType = irr::io::EXN_UNKNOWN;
+ return true;
+ }
+ }
+ else if (b < 0xf0) {
+ if (b == 0xe1) { // Processing instruction (C.2.11.3, C.3.7.3)
+ // C.5
+ ++dataP;
+ /*const std::string &target =*/ parseIdentifyingStringOrIndex(vocabulary.otherNCNameTable);
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ /*std::shared_ptr<const FIValue> data =*/ parseNonIdentifyingStringOrIndex1(vocabulary.otherStringTable);
+ currentNodeType = irr::io::EXN_UNKNOWN;
+ return true;
+ }
+ else if (b == 0xe2) { // Comment (C.2.11.4, C.3.7.6)
+ // C.8
+ ++dataP;
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ std::shared_ptr<const FIValue> comment = parseNonIdentifyingStringOrIndex1(vocabulary.otherStringTable);
+ nodeName = comment->toString();
+ currentNodeType = irr::io::EXN_COMMENT;
+ return true;
+ }
+ }
+ else { // Terminator (C.2.12, C.3.8)
+ ++dataP;
+ if (b == 0xff) {
+ terminatorPending = true;
+ }
+ if (elementStack.empty()) {
+ return false;
+ }
+ else {
+ nodeName = elementStack.top();
+ elementStack.pop();
+ currentNodeType = nodeName.empty() ? irr::io::EXN_UNKNOWN : irr::io::EXN_ELEMENT_END;
+ return true;
+ }
+ }
+ throw DeadlyImportError(parseErrorMessage);
+ }
+
+ virtual irr::io::EXML_NODE getNodeType() const /*override*/ {
+ return currentNodeType;
+ }
+
+ virtual int getAttributeCount() const /*override*/ {
+ return static_cast<int>(attributes.size());
+ }
+
+ virtual const char* getAttributeName(int idx) const /*override*/ {
+ if (idx < 0 || idx >= (int)attributes.size()) {
+ return nullptr;
+ }
+ return attributes[idx].name.c_str();
+ }
+
+ virtual const char* getAttributeValue(int idx) const /*override*/ {
+ if (idx < 0 || idx >= (int)attributes.size()) {
+ return nullptr;
+ }
+ return attributes[idx].value->toString().c_str();
+ }
+
+ virtual const char* getAttributeValue(const char* name) const /*override*/ {
+ const Attribute* attr = getAttributeByName(name);
+ if (!attr) {
+ return nullptr;
+ }
+ return attr->value->toString().c_str();
+ }
+
+ virtual const char* getAttributeValueSafe(const char* name) const /*override*/ {
+ const Attribute* attr = getAttributeByName(name);
+ if (!attr) {
+ return EmptyString.c_str();
+ }
+ return attr->value->toString().c_str();
+ }
+
+ virtual int getAttributeValueAsInt(const char* name) const /*override*/ {
+ const Attribute* attr = getAttributeByName(name);
+ if (!attr) {
+ return 0;
+ }
+ std::shared_ptr<const FIIntValue> intValue = std::dynamic_pointer_cast<const FIIntValue>(attr->value);
+ if (intValue) {
+ return intValue->value.size() == 1 ? intValue->value.front() : 0;
+ }
+ return atoi(attr->value->toString().c_str());
+ }
+
+ virtual int getAttributeValueAsInt(int idx) const /*override*/ {
+ if (idx < 0 || idx >= (int)attributes.size()) {
+ return 0;
+ }
+ std::shared_ptr<const FIIntValue> intValue = std::dynamic_pointer_cast<const FIIntValue>(attributes[idx].value);
+ if (intValue) {
+ return intValue->value.size() == 1 ? intValue->value.front() : 0;
+ }
+ return atoi(attributes[idx].value->toString().c_str());
+ }
+
+ virtual float getAttributeValueAsFloat(const char* name) const /*override*/ {
+ const Attribute* attr = getAttributeByName(name);
+ if (!attr) {
+ return 0;
+ }
+ std::shared_ptr<const FIFloatValue> floatValue = std::dynamic_pointer_cast<const FIFloatValue>(attr->value);
+ if (floatValue) {
+ return floatValue->value.size() == 1 ? floatValue->value.front() : 0;
+ }
+
+ return fast_atof(attr->value->toString().c_str());
+ }
+
+ virtual float getAttributeValueAsFloat(int idx) const /*override*/ {
+ if (idx < 0 || idx >= (int)attributes.size()) {
+ return 0;
+ }
+ std::shared_ptr<const FIFloatValue> floatValue = std::dynamic_pointer_cast<const FIFloatValue>(attributes[idx].value);
+ if (floatValue) {
+ return floatValue->value.size() == 1 ? floatValue->value.front() : 0;
+ }
+ return fast_atof(attributes[idx].value->toString().c_str());
+ }
+
+ virtual const char* getNodeName() const /*override*/ {
+ return nodeName.c_str();
+ }
+
+ virtual const char* getNodeData() const /*override*/ {
+ return nodeName.c_str();
+ }
+
+ virtual bool isEmptyElement() const /*override*/ {
+ return emptyElement;
+ }
+
+ virtual irr::io::ETEXT_FORMAT getSourceFormat() const /*override*/ {
+ return irr::io::ETF_UTF8;
+ }
+
+ virtual irr::io::ETEXT_FORMAT getParserFormat() const /*override*/ {
+ return irr::io::ETF_UTF8;
+ }
+
+ virtual std::shared_ptr<const FIValue> getAttributeEncodedValue(int idx) const /*override*/ {
+ if (idx < 0 || idx >= (int)attributes.size()) {
+ return nullptr;
+ }
+ return attributes[idx].value;
+ }
+
+ virtual std::shared_ptr<const FIValue> getAttributeEncodedValue(const char* name) const /*override*/ {
+ const Attribute* attr = getAttributeByName(name);
+ if (!attr) {
+ return nullptr;
+ }
+ return attr->value;
+ }
+
+ virtual void registerDecoder(const std::string &algorithmUri, std::unique_ptr<FIDecoder> decoder) /*override*/ {
+ decoderMap[algorithmUri] = std::move(decoder);
+ }
+
+ virtual void registerVocabulary(const std::string &vocabularyUri, const FIVocabulary *vocabulary) /*override*/ {
+ vocabularyMap[vocabularyUri] = vocabulary;
+ }
+
+private:
+
+ struct QName {
+ std::string prefix;
+ std::string uri;
+ std::string name;
+ inline QName() {}
+ inline QName(const FIQName &qname): prefix(qname.prefix ? qname.prefix : ""), uri(qname.uri ? qname.uri : ""), name(qname.name) {}
+ };
+
+ struct Attribute {
+ QName qname;
+ std::string name;
+ std::shared_ptr<const FIValue> value;
+ };
+
+ struct Vocabulary {
+ std::vector<std::string> restrictedAlphabetTable;
+ std::vector<std::string> encodingAlgorithmTable;
+ std::vector<std::string> prefixTable;
+ std::vector<std::string> namespaceNameTable;
+ std::vector<std::string> localNameTable;
+ std::vector<std::string> otherNCNameTable;
+ std::vector<std::string> otherURITable;
+ std::vector<std::shared_ptr<const FIValue>> attributeValueTable;
+ std::vector<std::shared_ptr<const FIValue>> charactersTable;
+ std::vector<std::shared_ptr<const FIValue>> otherStringTable;
+ std::vector<QName> elementNameTable;
+ std::vector<QName> attributeNameTable;
+ Vocabulary() {
+ prefixTable.push_back("xml");
+ namespaceNameTable.push_back("http://www.w3.org/XML/1998/namespace");
+ }
+ };
+
+ const Attribute* getAttributeByName(const char* name) const {
+ if (!name) {
+ return 0;
+ }
+ std::string n = name;
+ for (int i=0; i<(int)attributes.size(); ++i) {
+ if (attributes[i].name == n) {
+ return &attributes[i];
+ }
+ }
+ return 0;
+ }
+
+ size_t parseInt2() { // C.25
+ uint8_t b = *dataP++;
+ if (!(b & 0x40)) { // x0...... (C.25.2)
+ return b & 0x3f;
+ }
+ else if ((b & 0x60) == 0x40) { // x10..... ........ (C.25.3)
+ if (dataEnd - dataP > 0) {
+ return (((b & 0x1f) << 8) | *dataP++) + 0x40;
+ }
+ }
+ else if ((b & 0x70) == 0x60) { // x110.... ........ ........ (C.25.4)
+ if (dataEnd - dataP > 1) {
+ size_t result = (((b & 0x0f) << 16) | (dataP[0] << 8) | dataP[1]) + 0x2040;
+ dataP += 2;
+ return result;
+ }
+ }
+ throw DeadlyImportError(parseErrorMessage);
+ }
+
+ size_t parseInt3() { // C.27
+ uint8_t b = *dataP++;
+ if (!(b & 0x20)) { // xx0..... (C.27.2)
+ return b & 0x1f;
+ }
+ else if ((b & 0x38) == 0x20) { // xx100... ........ (C.27.3)
+ if (dataEnd - dataP > 0) {
+ return (((b & 0x07) << 8) | *dataP++) + 0x20;
+ }
+ }
+ else if ((b & 0x38) == 0x28) { // xx101... ........ ........ (C.27.4)
+ if (dataEnd - dataP > 1) {
+ size_t result = (((b & 0x07) << 16) | (dataP[0] << 8) | dataP[1]) + 0x820;
+ dataP += 2;
+ return result;
+ }
+ }
+ else if ((b & 0x3f) == 0x30) { // xx110000 0000.... ........ ........ (C.27.5)
+ if ((dataEnd - dataP > 2) && !(dataP[0] & 0xf0)) {
+ size_t result = (((dataP[0] & 0x0f) << 16) | (dataP[1] << 8) | dataP[2]) + 0x80820;
+ dataP += 3;
+ return result;
+ }
+ }
+ throw DeadlyImportError(parseErrorMessage);
+ }
+
+ size_t parseInt4() { // C.28
+ uint8_t b = *dataP++;
+ if (!(b & 0x10)) { // xxx0.... (C.28.2)
+ return b & 0x0f;
+ }
+ else if ((b & 0x1c) == 0x10) { // xxx100.. ........ (C.28.3)
+ if (dataEnd - dataP > 0) {
+ return (((b & 0x03) << 8) | *dataP++) + 0x10;
+ }
+ }
+ else if ((b & 0x1c) == 0x14) { // xxx101.. ........ ........ (C.28.4)
+ if (dataEnd - dataP > 1) {
+ size_t result = (((b & 0x03) << 16) | (dataP[0] << 8) | dataP[1]) + 0x410;
+ dataP += 2;
+ return result;
+ }
+ }
+ else if ((b & 0x1f) == 0x18) { // xxx11000 0000.... ........ ........ (C.28.5)
+ if ((dataEnd - dataP > 2) && !(dataP[0] & 0xf0)) {
+ size_t result = (((dataP[0] & 0x0f) << 16) | (dataP[1] << 8) | dataP[2]) + 0x40410;
+ dataP += 3;
+ return result;
+ }
+ }
+ throw DeadlyImportError(parseErrorMessage);
+ }
+
+ size_t parseSequenceLen() { // C.21
+ if (dataEnd - dataP > 0) {
+ uint8_t b = *dataP++;
+ if (b < 0x80) { // 0....... (C.21.2)
+ return b;
+ }
+ else if ((b & 0xf0) == 0x80) { // 1000.... ........ ........ (C.21.3)
+ if (dataEnd - dataP > 1) {
+ size_t result = (((b & 0x0f) << 16) | (dataP[0] << 8) | dataP[1]) + 0x80;
+ dataP += 2;
+ return result;
+ }
+ }
+ }
+ throw DeadlyImportError(parseErrorMessage);
+ }
+
+ std::string parseNonEmptyOctetString2() { // C.22
+ // Parse the length of the string
+ uint8_t b = *dataP++ & 0x7f;
+ size_t len;
+ if (!(b & 0x40)) { // x0...... (C.22.3.1)
+ len = b + 1;
+ }
+ else if (b == 0x40) { // x1000000 ........ (C.22.3.2)
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ len = *dataP++ + 0x41;
+ }
+ else if (b == 0x60) { // x1100000 ........ ........ ........ ........ (C.22.3.3)
+ if (dataEnd - dataP < 4) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ len = ((dataP[0] << 24) | (dataP[1] << 16) | (dataP[2] << 8) | dataP[3]) + 0x141;
+ dataP += 4;
+ }
+ else {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+
+ // Parse the string (C.22.4)
+ if (dataEnd - dataP < static_cast<ptrdiff_t>(len)) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ std::string s = parseUTF8String(dataP, len);
+ dataP += len;
+
+ return s;
+ }
+
+ size_t parseNonEmptyOctetString5Length() { // C.23
+ // Parse the length of the string
+ size_t b = *dataP++ & 0x0f;
+ if (!(b & 0x08)) { // xxxx0... (C.23.3.1)
+ return b + 1;
+ }
+ else if (b == 0x08) { // xxxx1000 ........ (C.23.3.2)
+ if (dataEnd - dataP > 0) {
+ return *dataP++ + 0x09;
+ }
+ }
+ else if (b == 0x0c) { // xxxx1100 ........ ........ ........ ........ (C.23.3.3)
+ if (dataEnd - dataP > 3) {
+ size_t result = ((dataP[0] << 24) | (dataP[1] << 16) | (dataP[2] << 8) | dataP[3]) + 0x109;
+ dataP += 4;
+ return result;
+ }
+ }
+ throw DeadlyImportError(parseErrorMessage);
+ }
+
+ size_t parseNonEmptyOctetString7Length() { // C.24
+ // Parse the length of the string
+ size_t b = *dataP++ & 0x03;
+ if (!(b & 0x02)) { // xxxxxx0. (C.24.3.1)
+ return b + 1;
+ }
+ else if (b == 0x02) { // xxxxxx10 ........ (C.24.3.2)
+ if (dataEnd - dataP > 0) {
+ return *dataP++ + 0x3;
+ }
+ }
+ else if (b == 0x03) { // xxxxxx11 ........ ........ ........ ........ (C.24.3.3)
+ if (dataEnd - dataP > 3) {
+ size_t result = ((dataP[0] << 24) | (dataP[1] << 16) | (dataP[2] << 8) | dataP[3]) + 0x103;
+ dataP += 4;
+ return result;
+ }
+ }
+ throw DeadlyImportError(parseErrorMessage);
+ }
+
+ std::shared_ptr<const FIValue> parseEncodedData(size_t index, size_t len) {
+ if (index < 32) {
+ FIDecoder *decoder = defaultDecoder[index];
+ if (!decoder) {
+ throw DeadlyImportError("Invalid encoding algorithm index " + to_string(index));
+ }
+ return decoder->decode(dataP, len);
+ }
+ else {
+ if (index - 32 >= vocabulary.encodingAlgorithmTable.size()) {
+ throw DeadlyImportError("Invalid encoding algorithm index " + to_string(index));
+ }
+ std::string uri = vocabulary.encodingAlgorithmTable[index - 32];
+ auto it = decoderMap.find(uri);
+ if (it == decoderMap.end()) {
+ throw DeadlyImportError("Unsupported encoding algorithm " + uri);
+ }
+ else {
+ return it->second->decode(dataP, len);
+ }
+ }
+ }
+
+ std::shared_ptr<const FIValue> parseRestrictedAlphabet(size_t index, size_t len) {
+ std::string alphabet;
+ if (index < 16) {
+ switch (index) {
+ case 0: // numeric
+ alphabet = "0123456789-+.e ";
+ break;
+ case 1: // date and time
+ alphabet = "0123456789-:TZ ";
+ break;
+ default:
+ throw DeadlyImportError("Invalid restricted alphabet index " + to_string(index));
+ }
+ }
+ else {
+ if (index - 16 >= vocabulary.restrictedAlphabetTable.size()) {
+ throw DeadlyImportError("Invalid restricted alphabet index " + to_string(index));
+ }
+ alphabet = vocabulary.restrictedAlphabetTable[index - 16];
+ }
+ std::vector<uint32_t> alphabetUTF32;
+ utf8::utf8to32(alphabet.begin(), alphabet.end(), back_inserter(alphabetUTF32));
+ std::string::size_type alphabetLength = alphabetUTF32.size();
+ if (alphabetLength < 2) {
+ throw DeadlyImportError("Invalid restricted alphabet length " + to_string(alphabetLength));
+ }
+ std::string::size_type bitsPerCharacter = 1;
+ while ((1ull << bitsPerCharacter) <= alphabetLength) {
+ ++bitsPerCharacter;
+ }
+ size_t bitsAvail = 0;
+ uint8_t mask = (1 << bitsPerCharacter) - 1;
+ uint32_t bits = 0;
+ std::string s;
+ for (size_t i = 0; i < len; ++i) {
+ bits = (bits << 8) | dataP[i];
+ bitsAvail += 8;
+ while (bitsAvail >= bitsPerCharacter) {
+ bitsAvail -= bitsPerCharacter;
+ size_t charIndex = (bits >> bitsAvail) & mask;
+ if (charIndex < alphabetLength) {
+ s.push_back(alphabetUTF32[charIndex]);
+ }
+ else if (charIndex != mask) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ }
+ }
+ return FIStringValue::create(std::move(s));
+ }
+
+ std::shared_ptr<const FIValue> parseEncodedCharacterString3() { // C.19
+ std::shared_ptr<const FIValue> result;
+ size_t len;
+ uint8_t b = *dataP;
+ if (b & 0x20) {
+ ++dataP;
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ size_t index = ((b & 0x0f) << 4) | ((*dataP & 0xf0) >> 4); // C.29
+ len = parseNonEmptyOctetString5Length();
+ if (dataEnd - dataP < static_cast<ptrdiff_t>(len)) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ if (b & 0x10) {
+ // encoding algorithm (C.19.3.4)
+ result = parseEncodedData(index, len);
+ }
+ else {
+ // Restricted alphabet (C.19.3.3)
+ result = parseRestrictedAlphabet(index, len);
+ }
+ }
+ else {
+ len = parseNonEmptyOctetString5Length();
+ if (dataEnd - dataP < static_cast<ptrdiff_t>(len)) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ if (b & 0x10) {
+ // UTF-16 (C.19.3.2)
+ if (len & 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ result = FIStringValue::create(parseUTF16String(dataP, len));
+ }
+ else {
+ // UTF-8 (C.19.3.1)
+ result = FIStringValue::create(parseUTF8String(dataP, len));
+ }
+ }
+ dataP += len;
+ return result;
+ }
+
+ std::shared_ptr<const FIValue> parseEncodedCharacterString5() { // C.20
+ std::shared_ptr<const FIValue> result;
+ size_t len;
+ uint8_t b = *dataP;
+ if (b & 0x08) {
+ ++dataP;
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ size_t index = ((b & 0x03) << 6) | ((*dataP & 0xfc) >> 2); /* C.29 */
+ len = parseNonEmptyOctetString7Length();
+ if (dataEnd - dataP < static_cast<ptrdiff_t>(len)) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ if (b & 0x04) {
+ // encoding algorithm (C.20.3.4)
+ result = parseEncodedData(index, len);
+ }
+ else {
+ // Restricted alphabet (C.20.3.3)
+ result = parseRestrictedAlphabet(index, len);
+ }
+ }
+ else {
+ len = parseNonEmptyOctetString7Length();
+ if (dataEnd - dataP < static_cast<ptrdiff_t>(len)) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ if (b & 0x04) {
+ // UTF-16 (C.20.3.2)
+ if (len & 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ result = FIStringValue::create(parseUTF16String(dataP, len));
+ }
+ else {
+ // UTF-8 (C.20.3.1)
+ result = FIStringValue::create(parseUTF8String(dataP, len));
+ }
+ }
+ dataP += len;
+ return result;
+ }
+
+ const std::string &parseIdentifyingStringOrIndex(std::vector<std::string> &stringTable) { // C.13
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ uint8_t b = *dataP;
+ if (b & 0x80) {
+ // We have an index (C.13.4)
+ size_t index = parseInt2();
+ if (index >= stringTable.size()) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ return stringTable[index];
+ }
+ else {
+ // We have a string (C.13.3)
+ stringTable.push_back(parseNonEmptyOctetString2());
+ return stringTable.back();
+ }
+ }
+
+ QName parseNameSurrogate() { // C.16
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ uint8_t b = *dataP++;
+ if (b & 0xfc) { // Padding '000000' C.2.5.5
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ QName result;
+ size_t index;
+ if (b & 0x02) { // prefix (C.16.3)
+ if ((dataEnd - dataP < 1) || (*dataP & 0x80)) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ index = parseInt2();
+ if (index >= vocabulary.prefixTable.size()) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ result.prefix = vocabulary.prefixTable[index];
+ }
+ if (b & 0x01) { // namespace-name (C.16.4)
+ if ((dataEnd - dataP < 1) || (*dataP & 0x80)) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ index = parseInt2();
+ if (index >= vocabulary.namespaceNameTable.size()) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ result.uri = vocabulary.namespaceNameTable[index];
+ }
+ // local-name
+ if ((dataEnd - dataP < 1) || (*dataP & 0x80)) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ index = parseInt2();
+ if (index >= vocabulary.localNameTable.size()) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ result.name = vocabulary.localNameTable[index];
+ return result;
+ }
+
+ const QName &parseQualifiedNameOrIndex2(std::vector<QName> &qNameTable) { // C.17
+ uint8_t b = *dataP;
+ if ((b & 0x7c) == 0x78) { // x11110..
+ // We have a literal (C.17.3)
+ ++dataP;
+ QName result;
+ // prefix (C.17.3.1)
+ result.prefix = b & 0x02 ? parseIdentifyingStringOrIndex(vocabulary.prefixTable) : std::string();
+ // namespace-name (C.17.3.1)
+ result.uri = b & 0x01 ? parseIdentifyingStringOrIndex(vocabulary.namespaceNameTable) : std::string();
+ // local-name
+ result.name = parseIdentifyingStringOrIndex(vocabulary.localNameTable);
+ qNameTable.push_back(result);
+ return qNameTable.back();
+ }
+ else {
+ // We have an index (C.17.4)
+ size_t index = parseInt2();
+ if (index >= qNameTable.size()) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ return qNameTable[index];
+ }
+ }
+
+ const QName &parseQualifiedNameOrIndex3(std::vector<QName> &qNameTable) { // C.18
+ uint8_t b = *dataP;
+ if ((b & 0x3c) == 0x3c) { // xx1111..
+ // We have a literal (C.18.3)
+ ++dataP;
+ QName result;
+ // prefix (C.18.3.1)
+ result.prefix = b & 0x02 ? parseIdentifyingStringOrIndex(vocabulary.prefixTable) : std::string();
+ // namespace-name (C.18.3.1)
+ result.uri = b & 0x01 ? parseIdentifyingStringOrIndex(vocabulary.namespaceNameTable) : std::string();
+ // local-name
+ result.name = parseIdentifyingStringOrIndex(vocabulary.localNameTable);
+ qNameTable.push_back(result);
+ return qNameTable.back();
+ }
+ else {
+ // We have an index (C.18.4)
+ size_t index = parseInt3();
+ if (index >= qNameTable.size()) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ return qNameTable[index];
+ }
+ }
+
+ std::shared_ptr<const FIValue> parseNonIdentifyingStringOrIndex1(std::vector<std::shared_ptr<const FIValue>> &valueTable) { // C.14
+ uint8_t b = *dataP;
+ if (b == 0xff) { // C.26.2
+ // empty string
+ ++dataP;
+ return EmptyFIString;
+ }
+ else if (b & 0x80) { // C.14.4
+ // We have an index
+ size_t index = parseInt2();
+ if (index >= valueTable.size()) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ return valueTable[index];
+ }
+ else { // C.14.3
+ // We have a literal
+ std::shared_ptr<const FIValue> result = parseEncodedCharacterString3();
+ if (b & 0x40) { // C.14.3.1
+ valueTable.push_back(result);
+ }
+ return result;
+ }
+ }
+
+ std::shared_ptr<const FIValue> parseNonIdentifyingStringOrIndex3(std::vector<std::shared_ptr<const FIValue>> &valueTable) { // C.15
+ uint8_t b = *dataP;
+ if (b & 0x20) { // C.15.4
+ // We have an index
+ size_t index = parseInt4();
+ if (index >= valueTable.size()) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ return valueTable[index];
+ }
+ else { // C.15.3
+ // We have a literal
+ std::shared_ptr<const FIValue> result = parseEncodedCharacterString5();
+ if (b & 0x10) { // C.15.3.1
+ valueTable.push_back(result);
+ }
+ return result;
+ }
+ }
+
+ void parseElement() {
+ // C.3
+
+ attributes.clear();
+
+ uint8_t b = *dataP;
+ bool hasAttributes = (b & 0x40) != 0; // C.3.3
+ if ((b & 0x3f) == 0x38) { // C.3.4.1
+ // Parse namespaces
+ ++dataP;
+ for (;;) {
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ b = *dataP++;
+ if (b == 0xf0) { // C.3.4.3
+ break;
+ }
+ if ((b & 0xfc) != 0xcc) { // C.3.4.2
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ // C.12
+ Attribute attr;
+ attr.qname.prefix = "xmlns";
+ attr.qname.name = b & 0x02 ? parseIdentifyingStringOrIndex(vocabulary.prefixTable) : std::string();
+ attr.qname.uri = b & 0x01 ? parseIdentifyingStringOrIndex(vocabulary.namespaceNameTable) : std::string();
+ attr.name = attr.qname.name.empty() ? "xmlns" : "xmlns:" + attr.qname.name;
+ attr.value = FIStringValue::create(std::string(attr.qname.uri));
+ attributes.push_back(attr);
+ }
+ if ((dataEnd - dataP < 1) || (*dataP & 0xc0)) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ }
+
+ // Parse Element name (C.3.5)
+ const QName &elemName = parseQualifiedNameOrIndex3(vocabulary.elementNameTable);
+ nodeName = elemName.prefix.empty() ? elemName.name : elemName.prefix + ':' + elemName.name;
+
+ if (hasAttributes) {
+ for (;;) {
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ b = *dataP;
+ if (b < 0x80) { // C.3.6.1
+ // C.4
+ Attribute attr;
+ attr.qname = parseQualifiedNameOrIndex2(vocabulary.attributeNameTable);
+ attr.name = attr.qname.prefix.empty() ? attr.qname.name : attr.qname.prefix + ':' + attr.qname.name;
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ attr.value = parseNonIdentifyingStringOrIndex1(vocabulary.attributeValueTable);
+ attributes.push_back(attr);
+ }
+ else {
+ if ((b & 0xf0) != 0xf0) { // C.3.6.2
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ emptyElement = b == 0xff; // C.3.6.2, C.3.8
+ ++dataP;
+ break;
+ }
+ }
+ }
+ else {
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ b = *dataP;
+ switch (b) {
+ case 0xff:
+ terminatorPending = true;
+ // Intentionally fall through
+ case 0xf0:
+ emptyElement = true;
+ ++dataP;
+ break;
+ default:
+ emptyElement = false;
+ }
+ }
+ if (!emptyElement) {
+ elementStack.push(nodeName);
+ }
+
+ currentNodeType = irr::io::EXN_ELEMENT;
+ }
+
+ void parseHeader() {
+ // Parse header (C.1.3)
+ size_t magicSize = parseMagic(dataP, dataEnd);
+ if (!magicSize) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ dataP += magicSize;
+ // C.2.3
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ uint8_t b = *dataP++;
+ if (b & 0x40) {
+ // Parse additional data (C.2.4)
+ size_t len = parseSequenceLen();
+ for (size_t i = 0; i < len; ++i) {
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ /*std::string id =*/ parseNonEmptyOctetString2();
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ /*std::string data =*/ parseNonEmptyOctetString2();
+ }
+ }
+ if (b & 0x20) {
+ // Parse initial vocabulary (C.2.5)
+ if (dataEnd - dataP < 2) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ uint16_t b1 = (dataP[0] << 8) | dataP[1];
+ dataP += 2;
+ if (b1 & 0x1000) {
+ // External vocabulary (C.2.5.2)
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ std::string uri = parseNonEmptyOctetString2();
+ auto it = vocabularyMap.find(uri);
+ if (it == vocabularyMap.end()) {
+ throw DeadlyImportError("Unknown vocabulary " + uri);
+ }
+ const FIVocabulary *externalVocabulary = it->second;
+ if (externalVocabulary->restrictedAlphabetTable) {
+ std::copy(externalVocabulary->restrictedAlphabetTable, externalVocabulary->restrictedAlphabetTable + externalVocabulary->restrictedAlphabetTableSize, std::back_inserter(vocabulary.restrictedAlphabetTable));
+ }
+ if (externalVocabulary->encodingAlgorithmTable) {
+ std::copy(externalVocabulary->encodingAlgorithmTable, externalVocabulary->encodingAlgorithmTable + externalVocabulary->encodingAlgorithmTableSize, std::back_inserter(vocabulary.encodingAlgorithmTable));
+ }
+ if (externalVocabulary->prefixTable) {
+ std::copy(externalVocabulary->prefixTable, externalVocabulary->prefixTable + externalVocabulary->prefixTableSize, std::back_inserter(vocabulary.prefixTable));
+ }
+ if (externalVocabulary->namespaceNameTable) {
+ std::copy(externalVocabulary->namespaceNameTable, externalVocabulary->namespaceNameTable + externalVocabulary->namespaceNameTableSize, std::back_inserter(vocabulary.namespaceNameTable));
+ }
+ if (externalVocabulary->localNameTable) {
+ std::copy(externalVocabulary->localNameTable, externalVocabulary->localNameTable + externalVocabulary->localNameTableSize, std::back_inserter(vocabulary.localNameTable));
+ }
+ if (externalVocabulary->otherNCNameTable) {
+ std::copy(externalVocabulary->otherNCNameTable, externalVocabulary->otherNCNameTable + externalVocabulary->otherNCNameTableSize, std::back_inserter(vocabulary.otherNCNameTable));
+ }
+ if (externalVocabulary->otherURITable) {
+ std::copy(externalVocabulary->otherURITable, externalVocabulary->otherURITable + externalVocabulary->otherURITableSize, std::back_inserter(vocabulary.otherURITable));
+ }
+ if (externalVocabulary->attributeValueTable) {
+ std::copy(externalVocabulary->attributeValueTable, externalVocabulary->attributeValueTable + externalVocabulary->attributeValueTableSize, std::back_inserter(vocabulary.attributeValueTable));
+ }
+ if (externalVocabulary->charactersTable) {
+ std::copy(externalVocabulary->charactersTable, externalVocabulary->charactersTable + externalVocabulary->charactersTableSize, std::back_inserter(vocabulary.charactersTable));
+ }
+ if (externalVocabulary->otherStringTable) {
+ std::copy(externalVocabulary->otherStringTable, externalVocabulary->otherStringTable + externalVocabulary->otherStringTableSize, std::back_inserter(vocabulary.otherStringTable));
+ }
+ if (externalVocabulary->elementNameTable) {
+ std::copy(externalVocabulary->elementNameTable, externalVocabulary->elementNameTable + externalVocabulary->elementNameTableSize, std::back_inserter(vocabulary.elementNameTable));
+ }
+ if (externalVocabulary->attributeNameTable) {
+ std::copy(externalVocabulary->attributeNameTable, externalVocabulary->attributeNameTable + externalVocabulary->attributeNameTableSize, std::back_inserter(vocabulary.attributeNameTable));
+ }
+ }
+ if (b1 & 0x0800) {
+ // Parse restricted alphabets (C.2.5.3)
+ for (size_t len = parseSequenceLen(); len > 0; --len) {
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ vocabulary.restrictedAlphabetTable.push_back(parseNonEmptyOctetString2());
+ }
+ }
+ if (b1 & 0x0400) {
+ // Parse encoding algorithms (C.2.5.3)
+ for (size_t len = parseSequenceLen(); len > 0; --len) {
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ vocabulary.encodingAlgorithmTable.push_back(parseNonEmptyOctetString2());
+ }
+ }
+ if (b1 & 0x0200) {
+ // Parse prefixes (C.2.5.3)
+ for (size_t len = parseSequenceLen(); len > 0; --len) {
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ vocabulary.prefixTable.push_back(parseNonEmptyOctetString2());
+ }
+ }
+ if (b1 & 0x0100) {
+ // Parse namespace names (C.2.5.3)
+ for (size_t len = parseSequenceLen(); len > 0; --len) {
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ vocabulary.namespaceNameTable.push_back(parseNonEmptyOctetString2());
+ }
+ }
+ if (b1 & 0x0080) {
+ // Parse local names (C.2.5.3)
+ for (size_t len = parseSequenceLen(); len > 0; --len) {
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ vocabulary.localNameTable.push_back(parseNonEmptyOctetString2());
+ }
+ }
+ if (b1 & 0x0040) {
+ // Parse other ncnames (C.2.5.3)
+ for (size_t len = parseSequenceLen(); len > 0; --len) {
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ vocabulary.otherNCNameTable.push_back(parseNonEmptyOctetString2());
+ }
+ }
+ if (b1 & 0x0020) {
+ // Parse other uris (C.2.5.3)
+ for (size_t len = parseSequenceLen(); len > 0; --len) {
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ vocabulary.otherURITable.push_back(parseNonEmptyOctetString2());
+ }
+ }
+ if (b1 & 0x0010) {
+ // Parse attribute values (C.2.5.4)
+ for (size_t len = parseSequenceLen(); len > 0; --len) {
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ vocabulary.attributeValueTable.push_back(parseEncodedCharacterString3());
+ }
+ }
+ if (b1 & 0x0008) {
+ // Parse content character chunks (C.2.5.4)
+ for (size_t len = parseSequenceLen(); len > 0; --len) {
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ vocabulary.charactersTable.push_back(parseEncodedCharacterString3());
+ }
+ }
+ if (b1 & 0x0004) {
+ // Parse other strings (C.2.5.4)
+ for (size_t len = parseSequenceLen(); len > 0; --len) {
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ vocabulary.otherStringTable.push_back(parseEncodedCharacterString3());
+ }
+ }
+ if (b1 & 0x0002) {
+ // Parse element name surrogates (C.2.5.5)
+ for (size_t len = parseSequenceLen(); len > 0; --len) {
+ vocabulary.elementNameTable.push_back(parseNameSurrogate());
+ }
+ }
+ if (b1 & 0x0001) {
+ // Parse attribute name surrogates (C.2.5.5)
+ for (size_t len = parseSequenceLen(); len > 0; --len) {
+ vocabulary.attributeNameTable.push_back(parseNameSurrogate());
+ }
+ }
+ }
+ if (b & 0x10) {
+ // Parse notations (C.2.6)
+ for (;;) {
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ uint8_t b1 = *dataP++;
+ if (b1 == 0xf0) {
+ break;
+ }
+ if ((b1 & 0xfc) != 0xc0) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ /* C.11 */
+ /*const std::string &name =*/ parseIdentifyingStringOrIndex(vocabulary.otherNCNameTable);
+ if (b1 & 0x02) {
+ /*const std::string &systemId =*/ parseIdentifyingStringOrIndex(vocabulary.otherURITable);
+ }
+ if (b1 & 0x01) {
+ /*const std::string &publicId =*/ parseIdentifyingStringOrIndex(vocabulary.otherURITable);
+ }
+ }
+ }
+ if (b & 0x08) {
+ // Parse unparsed entities (C.2.7)
+ for (;;) {
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ uint8_t b1 = *dataP++;
+ if (b1 == 0xf0) {
+ break;
+ }
+ if ((b1 & 0xfe) != 0xd0) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ /* C.10 */
+ /*const std::string &name =*/ parseIdentifyingStringOrIndex(vocabulary.otherNCNameTable);
+ /*const std::string &systemId =*/ parseIdentifyingStringOrIndex(vocabulary.otherURITable);
+ if (b1 & 0x01) {
+ /*const std::string &publicId =*/ parseIdentifyingStringOrIndex(vocabulary.otherURITable);
+ }
+ /*const std::string &notationName =*/ parseIdentifyingStringOrIndex(vocabulary.otherNCNameTable);
+ }
+ }
+ if (b & 0x04) {
+ // Parse character encoding scheme (C.2.8)
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ /*std::string characterEncodingScheme =*/ parseNonEmptyOctetString2();
+ }
+ if (b & 0x02) {
+ // Parse standalone flag (C.2.9)
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ uint8_t b1 = *dataP++;
+ if (b1 & 0xfe) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ //bool standalone = b1 & 0x01;
+ }
+ if (b & 0x01) {
+ // Parse version (C.2.10)
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ /*std::shared_ptr<const FIValue> version =*/ parseNonIdentifyingStringOrIndex1(vocabulary.otherStringTable);
+ }
+ }
+
+ std::unique_ptr<uint8_t[]> data;
+ uint8_t *dataP, *dataEnd;
+ irr::io::EXML_NODE currentNodeType;
+ bool emptyElement;
+ bool headerPending;
+ bool terminatorPending;
+ Vocabulary vocabulary;
+ std::vector<Attribute> attributes;
+ std::stack<std::string> elementStack;
+ std::string nodeName;
+ std::map<std::string, std::unique_ptr<FIDecoder>> decoderMap;
+ std::map<std::string, const FIVocabulary*> vocabularyMap;
+
+ static const std::string EmptyString;
+ static std::shared_ptr<const FIValue> EmptyFIString;
+
+ static FIHexDecoder hexDecoder;
+ static FIBase64Decoder base64Decoder;
+ static FIShortDecoder shortDecoder;
+ static FIIntDecoder intDecoder;
+ static FILongDecoder longDecoder;
+ static FIBoolDecoder boolDecoder;
+ static FIFloatDecoder floatDecoder;
+ static FIDoubleDecoder doubleDecoder;
+ static FIUUIDDecoder uuidDecoder;
+ static FICDATADecoder cdataDecoder;
+ static FIDecoder *defaultDecoder[32];
+};
+
+const std::string CFIReaderImpl::EmptyString;
+std::shared_ptr<const FIValue> CFIReaderImpl::EmptyFIString = FIStringValue::create(std::string());
+
+FIHexDecoder CFIReaderImpl::hexDecoder;
+FIBase64Decoder CFIReaderImpl::base64Decoder;
+FIShortDecoder CFIReaderImpl::shortDecoder;
+FIIntDecoder CFIReaderImpl::intDecoder;
+FILongDecoder CFIReaderImpl::longDecoder;
+FIBoolDecoder CFIReaderImpl::boolDecoder;
+FIFloatDecoder CFIReaderImpl::floatDecoder;
+FIDoubleDecoder CFIReaderImpl::doubleDecoder;
+FIUUIDDecoder CFIReaderImpl::uuidDecoder;
+FICDATADecoder CFIReaderImpl::cdataDecoder;
+
+FIDecoder *CFIReaderImpl::defaultDecoder[32] = {
+ &hexDecoder,
+ &base64Decoder,
+ &shortDecoder,
+ &intDecoder,
+ &longDecoder,
+ &boolDecoder,
+ &floatDecoder,
+ &doubleDecoder,
+ &uuidDecoder,
+ &cdataDecoder
+};
+
+class CXMLReaderImpl : public FIReader
+{
+public:
+
+ //! Constructor
+ CXMLReaderImpl(std::unique_ptr<irr::io::IIrrXMLReader<char, irr::io::IXMLBase>> reader_)
+ : reader(std::move(reader_))
+ {}
+
+ virtual ~CXMLReaderImpl() {}
+
+ virtual bool read() /*override*/ {
+ return reader->read();
+ }
+
+ virtual irr::io::EXML_NODE getNodeType() const /*override*/ {
+ return reader->getNodeType();
+ }
+
+ virtual int getAttributeCount() const /*override*/ {
+ return reader->getAttributeCount();
+ }
+
+ virtual const char* getAttributeName(int idx) const /*override*/ {
+ return reader->getAttributeName(idx);
+ }
+
+ virtual const char* getAttributeValue(int idx) const /*override*/ {
+ return reader->getAttributeValue(idx);
+ }
+
+ virtual const char* getAttributeValue(const char* name) const /*override*/ {
+ return reader->getAttributeValue(name);
+ }
+
+ virtual const char* getAttributeValueSafe(const char* name) const /*override*/ {
+ return reader->getAttributeValueSafe(name);
+ }
+
+ virtual int getAttributeValueAsInt(const char* name) const /*override*/ {
+ return reader->getAttributeValueAsInt(name);
+ }
+
+ virtual int getAttributeValueAsInt(int idx) const /*override*/ {
+ return reader->getAttributeValueAsInt(idx);
+ }
+
+ virtual float getAttributeValueAsFloat(const char* name) const /*override*/ {
+ return reader->getAttributeValueAsFloat(name);
+ }
+
+ virtual float getAttributeValueAsFloat(int idx) const /*override*/ {
+ return reader->getAttributeValueAsFloat(idx);
+ }
+
+ virtual const char* getNodeName() const /*override*/ {
+ return reader->getNodeName();
+ }
+
+ virtual const char* getNodeData() const /*override*/ {
+ return reader->getNodeData();
+ }
+
+ virtual bool isEmptyElement() const /*override*/ {
+ return reader->isEmptyElement();
+ }
+
+ virtual irr::io::ETEXT_FORMAT getSourceFormat() const /*override*/ {
+ return reader->getSourceFormat();
+ }
+
+ virtual irr::io::ETEXT_FORMAT getParserFormat() const /*override*/ {
+ return reader->getParserFormat();
+ }
+
+ virtual std::shared_ptr<const FIValue> getAttributeEncodedValue(int /*idx*/) const /*override*/ {
+ return nullptr;
+ }
+
+ virtual std::shared_ptr<const FIValue> getAttributeEncodedValue(const char* /*name*/) const /*override*/ {
+ return nullptr;
+ }
+
+ virtual void registerDecoder(const std::string & /*algorithmUri*/, std::unique_ptr<FIDecoder> /*decoder*/) /*override*/ {}
+
+
+ virtual void registerVocabulary(const std::string &/*vocabularyUri*/, const FIVocabulary * /*vocabulary*/) /*override*/ {}
+
+private:
+
+ std::unique_ptr<irr::io::IIrrXMLReader<char, irr::io::IXMLBase>> reader;
+};
+
+static std::unique_ptr<uint8_t[]> readFile(IOStream *stream, size_t &size, bool &isFI) {
+ size = stream->FileSize();
+ std::unique_ptr<uint8_t[]> data = std::unique_ptr<uint8_t[]>(new uint8_t[size]);
+ if (stream->Read(data.get(), size, 1) != 1) {
+ size = 0;
+ data.reset();
+ }
+ isFI = parseMagic(data.get(), data.get() + size) > 0;
+ return data;
+}
+
+std::unique_ptr<FIReader> FIReader::create(IOStream *stream)
+{
+ size_t size;
+ bool isFI;
+ auto data = readFile(stream, size, isFI);
+ if (isFI) {
+ return std::unique_ptr<FIReader>(new CFIReaderImpl(std::move(data), size));
+ }
+ else {
+ auto memios = std::unique_ptr<MemoryIOStream>(new MemoryIOStream(data.release(), size, true));
+ auto callback = std::unique_ptr<CIrrXML_IOStreamReader>(new CIrrXML_IOStreamReader(memios.get()));
+ return std::unique_ptr<FIReader>(new CXMLReaderImpl(std::unique_ptr<irr::io::IIrrXMLReader<char, irr::io::IXMLBase>>(createIrrXMLReader(callback.get()))));
+ }
+}
+
+}// namespace Assimp
+
+#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
diff --git a/thirdparty/assimp/code/FileLogStream.h b/thirdparty/assimp/code/FileLogStream.h
new file mode 100644
index 0000000000..740c503192
--- /dev/null
+++ b/thirdparty/assimp/code/FileLogStream.h
@@ -0,0 +1,107 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+/** @file FileLofStream.h
+*/
+#ifndef ASSIMP_FILELOGSTREAM_H_INC
+#define ASSIMP_FILELOGSTREAM_H_INC
+
+#include <assimp/LogStream.hpp>
+#include <assimp/IOStream.hpp>
+#include <assimp/DefaultIOSystem.h>
+
+namespace Assimp {
+
+// ----------------------------------------------------------------------------------
+/** @class FileLogStream
+ * @brief Logstream to write into a file.
+ */
+class FileLogStream :
+ public LogStream
+{
+public:
+ FileLogStream( const char* file, IOSystem* io = NULL );
+ ~FileLogStream();
+ void write( const char* message );
+
+private:
+ IOStream *m_pStream;
+};
+
+// ----------------------------------------------------------------------------------
+// Constructor
+inline FileLogStream::FileLogStream( const char* file, IOSystem* io ) :
+ m_pStream(NULL)
+{
+ if ( !file || 0 == *file )
+ return;
+
+ // If no IOSystem is specified: take a default one
+ if (!io)
+ {
+ DefaultIOSystem FileSystem;
+ m_pStream = FileSystem.Open( file, "wt");
+ }
+ else m_pStream = io->Open( file, "wt" );
+}
+
+// ----------------------------------------------------------------------------------
+// Destructor
+inline FileLogStream::~FileLogStream()
+{
+ // The virtual d'tor should destroy the underlying file
+ delete m_pStream;
+}
+
+// ----------------------------------------------------------------------------------
+// Write method
+inline void FileLogStream::write( const char* message )
+{
+ if (m_pStream != NULL)
+ {
+ m_pStream->Write(message, sizeof(char), ::strlen(message));
+ m_pStream->Flush();
+ }
+}
+
+// ----------------------------------------------------------------------------------
+} // !Namespace Assimp
+
+#endif // !! ASSIMP_FILELOGSTREAM_H_INC
diff --git a/thirdparty/assimp/code/FileSystemFilter.h b/thirdparty/assimp/code/FileSystemFilter.h
new file mode 100644
index 0000000000..9923cdbdd3
--- /dev/null
+++ b/thirdparty/assimp/code/FileSystemFilter.h
@@ -0,0 +1,345 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, assimp team
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file FileSystemFilter.h
+ * Implements a filter system to filter calls to Exists() and Open()
+ * in order to improve the success rate of file opening ...
+ */
+#pragma once
+#ifndef AI_FILESYSTEMFILTER_H_INC
+#define AI_FILESYSTEMFILTER_H_INC
+
+#include <assimp/IOSystem.hpp>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/fast_atof.h>
+#include <assimp/ParsingUtils.h>
+
+namespace Assimp {
+
+inline bool IsHex(char s) {
+ return (s>='0' && s<='9') || (s>='a' && s<='f') || (s>='A' && s<='F');
+}
+
+// ---------------------------------------------------------------------------
+/** File system filter
+ */
+class FileSystemFilter : public IOSystem
+{
+public:
+ /** Constructor. */
+ FileSystemFilter(const std::string& file, IOSystem* old)
+ : mWrapped (old)
+ , mSrc_file(file)
+ , mSep(mWrapped->getOsSeparator()) {
+ ai_assert(nullptr != mWrapped);
+
+ // Determine base directory
+ mBase = mSrc_file;
+ std::string::size_type ss2;
+ if (std::string::npos != (ss2 = mBase.find_last_of("\\/"))) {
+ mBase.erase(ss2,mBase.length()-ss2);
+ } else {
+ mBase = "";
+ }
+
+ // make sure the directory is terminated properly
+ char s;
+
+ if ( mBase.empty() ) {
+ mBase = ".";
+ mBase += getOsSeparator();
+ } else if ((s = *(mBase.end()-1)) != '\\' && s != '/') {
+ mBase += getOsSeparator();
+ }
+
+ DefaultLogger::get()->info("Import root directory is \'" + mBase + "\'");
+ }
+
+ /** Destructor. */
+ ~FileSystemFilter() {
+ // empty
+ }
+
+ // -------------------------------------------------------------------
+ /** Tests for the existence of a file at the given path. */
+ bool Exists( const char* pFile) const {
+ ai_assert( nullptr != mWrapped );
+
+ std::string tmp = pFile;
+
+ // Currently this IOSystem is also used to open THE ONE FILE.
+ if (tmp != mSrc_file) {
+ BuildPath(tmp);
+ Cleanup(tmp);
+ }
+
+ return mWrapped->Exists(tmp);
+ }
+
+ // -------------------------------------------------------------------
+ /** Returns the directory separator. */
+ char getOsSeparator() const {
+ return mSep;
+ }
+
+ // -------------------------------------------------------------------
+ /** Open a new file with a given path. */
+ IOStream* Open( const char* pFile, const char* pMode = "rb") {
+ ai_assert( nullptr != mWrapped );
+ if ( nullptr == pFile || nullptr == pMode ) {
+ return nullptr;
+ }
+
+ ai_assert( nullptr != pFile );
+ ai_assert( nullptr != pMode );
+
+ // First try the unchanged path
+ IOStream* s = mWrapped->Open(pFile,pMode);
+
+ if (nullptr == s) {
+ std::string tmp = pFile;
+
+ // Try to convert between absolute and relative paths
+ BuildPath(tmp);
+ s = mWrapped->Open(tmp,pMode);
+
+ if (nullptr == s) {
+ // Finally, look for typical issues with paths
+ // and try to correct them. This is our last
+ // resort.
+ tmp = pFile;
+ Cleanup(tmp);
+ BuildPath(tmp);
+ s = mWrapped->Open(tmp,pMode);
+ }
+ }
+
+ return s;
+ }
+
+ // -------------------------------------------------------------------
+ /** Closes the given file and releases all resources associated with it. */
+ void Close( IOStream* pFile) {
+ ai_assert( nullptr != mWrapped );
+ return mWrapped->Close(pFile);
+ }
+
+ // -------------------------------------------------------------------
+ /** Compare two paths */
+ bool ComparePaths (const char* one, const char* second) const {
+ ai_assert( nullptr != mWrapped );
+ return mWrapped->ComparePaths (one,second);
+ }
+
+ // -------------------------------------------------------------------
+ /** Pushes a new directory onto the directory stack. */
+ bool PushDirectory(const std::string &path ) {
+ ai_assert( nullptr != mWrapped );
+ return mWrapped->PushDirectory(path);
+ }
+
+ // -------------------------------------------------------------------
+ /** Returns the top directory from the stack. */
+ const std::string &CurrentDirectory() const {
+ ai_assert( nullptr != mWrapped );
+ return mWrapped->CurrentDirectory();
+ }
+
+ // -------------------------------------------------------------------
+ /** Returns the number of directories stored on the stack. */
+ size_t StackSize() const {
+ ai_assert( nullptr != mWrapped );
+ return mWrapped->StackSize();
+ }
+
+ // -------------------------------------------------------------------
+ /** Pops the top directory from the stack. */
+ bool PopDirectory() {
+ ai_assert( nullptr != mWrapped );
+ return mWrapped->PopDirectory();
+ }
+
+ // -------------------------------------------------------------------
+ /** Creates an new directory at the given path. */
+ bool CreateDirectory(const std::string &path) {
+ ai_assert( nullptr != mWrapped );
+ return mWrapped->CreateDirectory(path);
+ }
+
+ // -------------------------------------------------------------------
+ /** Will change the current directory to the given path. */
+ bool ChangeDirectory(const std::string &path) {
+ ai_assert( nullptr != mWrapped );
+ return mWrapped->ChangeDirectory(path);
+ }
+
+ // -------------------------------------------------------------------
+ /** Delete file. */
+ bool DeleteFile(const std::string &file) {
+ ai_assert( nullptr != mWrapped );
+ return mWrapped->DeleteFile(file);
+ }
+
+private:
+ // -------------------------------------------------------------------
+ /** Build a valid path from a given relative or absolute path.
+ */
+ void BuildPath (std::string& in) const {
+ ai_assert( nullptr != mWrapped );
+ // if we can already access the file, great.
+ if (in.length() < 3 || mWrapped->Exists(in)) {
+ return;
+ }
+
+ // Determine whether this is a relative path (Windows-specific - most assets are packaged on Windows).
+ if (in[1] != ':') {
+
+ // append base path and try
+ const std::string tmp = mBase + in;
+ if (mWrapped->Exists(tmp)) {
+ in = tmp;
+ return;
+ }
+ }
+
+ // Chop of the file name and look in the model directory, if
+ // this fails try all sub paths of the given path, i.e.
+ // if the given path is foo/bar/something.lwo, try
+ // <base>/something.lwo
+ // <base>/bar/something.lwo
+ // <base>/foo/bar/something.lwo
+ std::string::size_type pos = in.rfind('/');
+ if (std::string::npos == pos) {
+ pos = in.rfind('\\');
+ }
+
+ if (std::string::npos != pos) {
+ std::string tmp;
+ std::string::size_type last_dirsep = std::string::npos;
+
+ while(true) {
+ tmp = mBase;
+ tmp += mSep;
+
+ std::string::size_type dirsep = in.rfind('/', last_dirsep);
+ if (std::string::npos == dirsep) {
+ dirsep = in.rfind('\\', last_dirsep);
+ }
+
+ if (std::string::npos == dirsep || dirsep == 0) {
+ // we did try this already.
+ break;
+ }
+
+ last_dirsep = dirsep-1;
+
+ tmp += in.substr(dirsep+1, in.length()-pos);
+ if (mWrapped->Exists(tmp)) {
+ in = tmp;
+ return;
+ }
+ }
+ }
+
+ // hopefully the underlying file system has another few tricks to access this file ...
+ }
+
+ // -------------------------------------------------------------------
+ /** Cleanup the given path
+ */
+ void Cleanup (std::string& in) const {
+ if(in.empty()) {
+ return;
+ }
+
+ // Remove a very common issue when we're parsing file names: spaces at the
+ // beginning of the path.
+ char last = 0;
+ std::string::iterator it = in.begin();
+ while (IsSpaceOrNewLine( *it ))++it;
+ if (it != in.begin()) {
+ in.erase(in.begin(),it+1);
+ }
+
+ const char separator = getOsSeparator();
+ for (it = in.begin(); it != in.end(); ++it) {
+ // Exclude :// and \\, which remain untouched.
+ // https://sourceforge.net/tracker/?func=detail&aid=3031725&group_id=226462&atid=1067632
+ if ( !strncmp(&*it, "://", 3 )) {
+ it += 3;
+ continue;
+ }
+ if (it == in.begin() && !strncmp(&*it, "\\\\", 2)) {
+ it += 2;
+ continue;
+ }
+
+ // Cleanup path delimiters
+ if (*it == '/' || (*it) == '\\') {
+ *it = separator;
+
+ // And we're removing double delimiters, frequent issue with
+ // incorrectly composited paths ...
+ if (last == *it) {
+ it = in.erase(it);
+ --it;
+ }
+ } else if (*it == '%' && in.end() - it > 2) {
+ // Hex sequence in URIs
+ if( IsHex((&*it)[0]) && IsHex((&*it)[1]) ) {
+ *it = HexOctetToDecimal(&*it);
+ it = in.erase(it+1,it+2);
+ --it;
+ }
+ }
+
+ last = *it;
+ }
+ }
+
+private:
+ IOSystem *mWrapped;
+ std::string mSrc_file, mBase;
+ char mSep;
+};
+
+} //!ns Assimp
+
+#endif //AI_DEFAULTIOSYSTEM_H_INC
diff --git a/thirdparty/assimp/code/FindDegenerates.cpp b/thirdparty/assimp/code/FindDegenerates.cpp
new file mode 100644
index 0000000000..365f5d7447
--- /dev/null
+++ b/thirdparty/assimp/code/FindDegenerates.cpp
@@ -0,0 +1,300 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file FindDegenerates.cpp
+ * @brief Implementation of the FindDegenerates post-process step.
+*/
+
+
+
+// internal headers
+#include "ProcessHelper.h"
+#include "FindDegenerates.h"
+#include <assimp/Exceptional.h>
+
+using namespace Assimp;
+
+//remove mesh at position 'index' from the scene
+static void removeMesh(aiScene* pScene, unsigned const index);
+//correct node indices to meshes and remove references to deleted mesh
+static void updateSceneGraph(aiNode* pNode, unsigned const index);
+
+// ------------------------------------------------------------------------------------------------
+// Constructor to be privately used by Importer
+FindDegeneratesProcess::FindDegeneratesProcess()
+: mConfigRemoveDegenerates( false )
+, mConfigCheckAreaOfTriangle( false ){
+ // empty
+}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor, private as well
+FindDegeneratesProcess::~FindDegeneratesProcess() {
+ // nothing to do here
+}
+
+// ------------------------------------------------------------------------------------------------
+// Returns whether the processing step is present in the given flag field.
+bool FindDegeneratesProcess::IsActive( unsigned int pFlags) const {
+ return 0 != (pFlags & aiProcess_FindDegenerates);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Setup import configuration
+void FindDegeneratesProcess::SetupProperties(const Importer* pImp) {
+ // Get the current value of AI_CONFIG_PP_FD_REMOVE
+ mConfigRemoveDegenerates = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_FD_REMOVE,0));
+ mConfigCheckAreaOfTriangle = ( 0 != pImp->GetPropertyInteger(AI_CONFIG_PP_FD_CHECKAREA) );
+}
+
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+void FindDegeneratesProcess::Execute( aiScene* pScene) {
+ ASSIMP_LOG_DEBUG("FindDegeneratesProcess begin");
+ for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
+ {
+ //Do not process point cloud, ExecuteOnMesh works only with faces data
+ if ((pScene->mMeshes[i]->mPrimitiveTypes != aiPrimitiveType::aiPrimitiveType_POINT) && ExecuteOnMesh(pScene->mMeshes[i])) {
+ removeMesh(pScene, i);
+ --i; //the current i is removed, do not skip the next one
+ }
+ }
+ ASSIMP_LOG_DEBUG("FindDegeneratesProcess finished");
+}
+
+static void removeMesh(aiScene* pScene, unsigned const index) {
+ //we start at index and copy the pointers one position forward
+ //save the mesh pointer to delete it later
+ auto delete_me = pScene->mMeshes[index];
+ for (unsigned i = index; i < pScene->mNumMeshes - 1; ++i) {
+ pScene->mMeshes[i] = pScene->mMeshes[i+1];
+ }
+ pScene->mMeshes[pScene->mNumMeshes - 1] = nullptr;
+ --(pScene->mNumMeshes);
+ delete delete_me;
+
+ //removing a mesh also requires updating all references to it in the scene graph
+ updateSceneGraph(pScene->mRootNode, index);
+}
+
+static void updateSceneGraph(aiNode* pNode, unsigned const index) {
+ for (unsigned i = 0; i < pNode->mNumMeshes; ++i) {
+ if (pNode->mMeshes[i] > index) {
+ --(pNode->mMeshes[i]);
+ continue;
+ }
+ if (pNode->mMeshes[i] == index) {
+ for (unsigned j = i; j < pNode->mNumMeshes -1; ++j) {
+ pNode->mMeshes[j] = pNode->mMeshes[j+1];
+ }
+ --(pNode->mNumMeshes);
+ --i;
+ continue;
+ }
+ }
+ //recurse to all children
+ for (unsigned i = 0; i < pNode->mNumChildren; ++i) {
+ updateSceneGraph(pNode->mChildren[i], index);
+ }
+}
+
+static ai_real heron( ai_real a, ai_real b, ai_real c ) {
+ ai_real s = (a + b + c) / 2;
+ ai_real area = pow((s * ( s - a ) * ( s - b ) * ( s - c ) ), (ai_real)0.5 );
+ return area;
+}
+
+static ai_real distance3D( const aiVector3D &vA, aiVector3D &vB ) {
+ const ai_real lx = ( vB.x - vA.x );
+ const ai_real ly = ( vB.y - vA.y );
+ const ai_real lz = ( vB.z - vA.z );
+ ai_real a = lx*lx + ly*ly + lz*lz;
+ ai_real d = pow( a, (ai_real)0.5 );
+
+ return d;
+}
+
+static ai_real calculateAreaOfTriangle( const aiFace& face, aiMesh* mesh ) {
+ ai_real area = 0;
+
+ aiVector3D vA( mesh->mVertices[ face.mIndices[ 0 ] ] );
+ aiVector3D vB( mesh->mVertices[ face.mIndices[ 1 ] ] );
+ aiVector3D vC( mesh->mVertices[ face.mIndices[ 2 ] ] );
+
+ ai_real a( distance3D( vA, vB ) );
+ ai_real b( distance3D( vB, vC ) );
+ ai_real c( distance3D( vC, vA ) );
+ area = heron( a, b, c );
+
+ return area;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported mesh
+bool FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) {
+ mesh->mPrimitiveTypes = 0;
+
+ std::vector<bool> remove_me;
+ if (mConfigRemoveDegenerates) {
+ remove_me.resize( mesh->mNumFaces, false );
+ }
+
+ unsigned int deg = 0, limit;
+ for ( unsigned int a = 0; a < mesh->mNumFaces; ++a ) {
+ aiFace& face = mesh->mFaces[a];
+ bool first = true;
+
+ // check whether the face contains degenerated entries
+ for (unsigned int i = 0; i < face.mNumIndices; ++i) {
+ // Polygons with more than 4 points are allowed to have double points, that is
+ // simulating polygons with holes just with concave polygons. However,
+ // double points may not come directly after another.
+ limit = face.mNumIndices;
+ if (face.mNumIndices > 4) {
+ limit = std::min( limit, i+2 );
+ }
+
+ for (unsigned int t = i+1; t < limit; ++t) {
+ if (mesh->mVertices[face.mIndices[ i ] ] == mesh->mVertices[ face.mIndices[ t ] ]) {
+ // we have found a matching vertex position
+ // remove the corresponding index from the array
+ --face.mNumIndices;
+ --limit;
+ for (unsigned int m = t; m < face.mNumIndices; ++m) {
+ face.mIndices[ m ] = face.mIndices[ m+1 ];
+ }
+ --t;
+
+ // NOTE: we set the removed vertex index to an unique value
+ // to make sure the developer gets notified when his
+ // application attempts to access this data.
+ face.mIndices[ face.mNumIndices ] = 0xdeadbeef;
+
+ if(first) {
+ ++deg;
+ first = false;
+ }
+
+ if ( mConfigRemoveDegenerates ) {
+ remove_me[ a ] = true;
+ goto evil_jump_outside; // hrhrhrh ... yeah, this rocks baby!
+ }
+ }
+ }
+
+ if ( mConfigCheckAreaOfTriangle ) {
+ if ( face.mNumIndices == 3 ) {
+ ai_real area = calculateAreaOfTriangle( face, mesh );
+ if ( area < 1e-6 ) {
+ if ( mConfigRemoveDegenerates ) {
+ remove_me[ a ] = true;
+ goto evil_jump_outside;
+ }
+
+ // todo: check for index which is corrupt.
+ }
+ }
+ }
+ }
+
+ // We need to update the primitive flags array of the mesh.
+ switch (face.mNumIndices)
+ {
+ case 1u:
+ mesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
+ break;
+ case 2u:
+ mesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
+ break;
+ case 3u:
+ mesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
+ break;
+ default:
+ mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
+ break;
+ };
+evil_jump_outside:
+ continue;
+ }
+
+ // If AI_CONFIG_PP_FD_REMOVE is true, remove degenerated faces from the import
+ if (mConfigRemoveDegenerates && deg) {
+ unsigned int n = 0;
+ for (unsigned int a = 0; a < mesh->mNumFaces; ++a)
+ {
+ aiFace& face_src = mesh->mFaces[a];
+ if (!remove_me[a]) {
+ aiFace& face_dest = mesh->mFaces[n++];
+
+ // Do a manual copy, keep the index array
+ face_dest.mNumIndices = face_src.mNumIndices;
+ face_dest.mIndices = face_src.mIndices;
+
+ if (&face_src != &face_dest) {
+ // clear source
+ face_src.mNumIndices = 0;
+ face_src.mIndices = nullptr;
+ }
+ }
+ else {
+ // Otherwise delete it if we don't need this face
+ delete[] face_src.mIndices;
+ face_src.mIndices = nullptr;
+ face_src.mNumIndices = 0;
+ }
+ }
+ // Just leave the rest of the array unreferenced, we don't care for now
+ mesh->mNumFaces = n;
+ if (!mesh->mNumFaces) {
+ //The whole mesh consists of degenerated faces
+ //signal upward, that this mesh should be deleted.
+ ASSIMP_LOG_DEBUG("FindDegeneratesProcess removed a mesh full of degenerated primitives");
+ return true;
+ }
+ }
+
+ if (deg && !DefaultLogger::isNullLogger()) {
+ ASSIMP_LOG_WARN_F( "Found ", deg, " degenerated primitives");
+ }
+ return false;
+}
diff --git a/thirdparty/assimp/code/FindDegenerates.h b/thirdparty/assimp/code/FindDegenerates.h
new file mode 100644
index 0000000000..880f5f16a2
--- /dev/null
+++ b/thirdparty/assimp/code/FindDegenerates.h
@@ -0,0 +1,129 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file Defines a post processing step to search all meshes for
+ degenerated faces */
+#ifndef AI_FINDDEGENERATESPROCESS_H_INC
+#define AI_FINDDEGENERATESPROCESS_H_INC
+
+#include "BaseProcess.h"
+#include <assimp/mesh.h>
+
+class FindDegeneratesProcessTest;
+namespace Assimp {
+
+
+// ---------------------------------------------------------------------------
+/** FindDegeneratesProcess: Searches a mesh for degenerated triangles.
+*/
+class ASSIMP_API FindDegeneratesProcess : public BaseProcess {
+public:
+ FindDegeneratesProcess();
+ ~FindDegeneratesProcess();
+
+ // -------------------------------------------------------------------
+ // Check whether step is active
+ bool IsActive( unsigned int pFlags) const;
+
+ // -------------------------------------------------------------------
+ // Execute step on a given scene
+ void Execute( aiScene* pScene);
+
+ // -------------------------------------------------------------------
+ // Setup import settings
+ void SetupProperties(const Importer* pImp);
+
+ // -------------------------------------------------------------------
+ // Execute step on a given mesh
+ ///@returns true if the current mesh should be deleted, false otherwise
+ bool ExecuteOnMesh( aiMesh* mesh);
+
+ // -------------------------------------------------------------------
+ /// @brief Enable the instant removal of degenerated primitives
+ /// @param enabled true for enabled.
+ void EnableInstantRemoval(bool enabled);
+
+ // -------------------------------------------------------------------
+ /// @brief Check whether instant removal is currently enabled
+ /// @return The instant removal state.
+ bool IsInstantRemoval() const;
+
+ // -------------------------------------------------------------------
+ /// @brief Enable the area check for triangles.
+ /// @param enabled true for enabled.
+ void EnableAreaCheck( bool enabled );
+
+ // -------------------------------------------------------------------
+ /// @brief Check whether the area check is enabled.
+ /// @return The area check state.
+ bool isAreaCheckEnabled() const;
+
+private:
+ //! Configuration option: remove degenerates faces immediately
+ bool mConfigRemoveDegenerates;
+ //! Configuration option: check for area
+ bool mConfigCheckAreaOfTriangle;
+};
+
+inline
+void FindDegeneratesProcess::EnableInstantRemoval(bool enabled) {
+ mConfigRemoveDegenerates = enabled;
+}
+
+inline
+bool FindDegeneratesProcess::IsInstantRemoval() const {
+ return mConfigRemoveDegenerates;
+}
+
+inline
+void FindDegeneratesProcess::EnableAreaCheck( bool enabled ) {
+ mConfigCheckAreaOfTriangle = enabled;
+}
+
+inline
+bool FindDegeneratesProcess::isAreaCheckEnabled() const {
+ return mConfigCheckAreaOfTriangle;
+}
+
+} // Namespace Assimp
+
+#endif // !! AI_FINDDEGENERATESPROCESS_H_INC
diff --git a/thirdparty/assimp/code/FindInstancesProcess.cpp b/thirdparty/assimp/code/FindInstancesProcess.cpp
new file mode 100644
index 0000000000..be1138116e
--- /dev/null
+++ b/thirdparty/assimp/code/FindInstancesProcess.cpp
@@ -0,0 +1,277 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file FindInstancesProcess.cpp
+ * @brief Implementation of the aiProcess_FindInstances postprocessing step
+*/
+
+
+#include "FindInstancesProcess.h"
+#include <memory>
+#include <stdio.h>
+
+using namespace Assimp;
+
+// ------------------------------------------------------------------------------------------------
+// Constructor to be privately used by Importer
+FindInstancesProcess::FindInstancesProcess()
+: configSpeedFlag (false)
+{}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor, private as well
+FindInstancesProcess::~FindInstancesProcess()
+{}
+
+// ------------------------------------------------------------------------------------------------
+// Returns whether the processing step is present in the given flag field.
+bool FindInstancesProcess::IsActive( unsigned int pFlags) const
+{
+ // FindInstances makes absolutely no sense together with PreTransformVertices
+ // fixme: spawn error message somewhere else?
+ return 0 != (pFlags & aiProcess_FindInstances) && 0 == (pFlags & aiProcess_PreTransformVertices);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Setup properties for the step
+void FindInstancesProcess::SetupProperties(const Importer* pImp)
+{
+ // AI_CONFIG_FAVOUR_SPEED
+ configSpeedFlag = (0 != pImp->GetPropertyInteger(AI_CONFIG_FAVOUR_SPEED,0));
+}
+
+// ------------------------------------------------------------------------------------------------
+// Compare the bones of two meshes
+bool CompareBones(const aiMesh* orig, const aiMesh* inst)
+{
+ for (unsigned int i = 0; i < orig->mNumBones;++i) {
+ aiBone* aha = orig->mBones[i];
+ aiBone* oha = inst->mBones[i];
+
+ if (aha->mNumWeights != oha->mNumWeights ||
+ aha->mOffsetMatrix != oha->mOffsetMatrix) {
+ return false;
+ }
+
+ // compare weight per weight ---
+ for (unsigned int n = 0; n < aha->mNumWeights;++n) {
+ if (aha->mWeights[n].mVertexId != oha->mWeights[n].mVertexId ||
+ (aha->mWeights[n].mWeight - oha->mWeights[n].mWeight) < 10e-3f) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Update mesh indices in the node graph
+void UpdateMeshIndices(aiNode* node, unsigned int* lookup)
+{
+ for (unsigned int n = 0; n < node->mNumMeshes;++n)
+ node->mMeshes[n] = lookup[node->mMeshes[n]];
+
+ for (unsigned int n = 0; n < node->mNumChildren;++n)
+ UpdateMeshIndices(node->mChildren[n],lookup);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+void FindInstancesProcess::Execute( aiScene* pScene)
+{
+ ASSIMP_LOG_DEBUG("FindInstancesProcess begin");
+ if (pScene->mNumMeshes) {
+
+ // use a pseudo hash for all meshes in the scene to quickly find
+ // the ones which are possibly equal. This step is executed early
+ // in the pipeline, so we could, depending on the file format,
+ // have several thousand small meshes. That's too much for a brute
+ // everyone-against-everyone check involving up to 10 comparisons
+ // each.
+ std::unique_ptr<uint64_t[]> hashes (new uint64_t[pScene->mNumMeshes]);
+ std::unique_ptr<unsigned int[]> remapping (new unsigned int[pScene->mNumMeshes]);
+
+ unsigned int numMeshesOut = 0;
+ for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
+
+ aiMesh* inst = pScene->mMeshes[i];
+ hashes[i] = GetMeshHash(inst);
+
+ for (int a = i-1; a >= 0; --a) {
+ if (hashes[i] == hashes[a])
+ {
+ aiMesh* orig = pScene->mMeshes[a];
+ if (!orig)
+ continue;
+
+ // check for hash collision .. we needn't check
+ // the vertex format, it *must* match due to the
+ // (brilliant) construction of the hash
+ if (orig->mNumBones != inst->mNumBones ||
+ orig->mNumFaces != inst->mNumFaces ||
+ orig->mNumVertices != inst->mNumVertices ||
+ orig->mMaterialIndex != inst->mMaterialIndex ||
+ orig->mPrimitiveTypes != inst->mPrimitiveTypes)
+ continue;
+
+ // up to now the meshes are equal. find an appropriate
+ // epsilon to compare position differences against
+ float epsilon = ComputePositionEpsilon(inst);
+ epsilon *= epsilon;
+
+ // now compare vertex positions, normals,
+ // tangents and bitangents using this epsilon.
+ if (orig->HasPositions()) {
+ if(!CompareArrays(orig->mVertices,inst->mVertices,orig->mNumVertices,epsilon))
+ continue;
+ }
+ if (orig->HasNormals()) {
+ if(!CompareArrays(orig->mNormals,inst->mNormals,orig->mNumVertices,epsilon))
+ continue;
+ }
+ if (orig->HasTangentsAndBitangents()) {
+ if (!CompareArrays(orig->mTangents,inst->mTangents,orig->mNumVertices,epsilon) ||
+ !CompareArrays(orig->mBitangents,inst->mBitangents,orig->mNumVertices,epsilon))
+ continue;
+ }
+
+ // use a constant epsilon for colors and UV coordinates
+ static const float uvEpsilon = 10e-4f;
+ {
+ unsigned int j, end = orig->GetNumUVChannels();
+ for(j = 0; j < end; ++j) {
+ if (!orig->mTextureCoords[j]) {
+ continue;
+ }
+ if(!CompareArrays(orig->mTextureCoords[j],inst->mTextureCoords[j],orig->mNumVertices,uvEpsilon)) {
+ break;
+ }
+ }
+ if (j != end) {
+ continue;
+ }
+ }
+ {
+ unsigned int j, end = orig->GetNumColorChannels();
+ for(j = 0; j < end; ++j) {
+ if (!orig->mColors[j]) {
+ continue;
+ }
+ if(!CompareArrays(orig->mColors[j],inst->mColors[j],orig->mNumVertices,uvEpsilon)) {
+ break;
+ }
+ }
+ if (j != end) {
+ continue;
+ }
+ }
+
+ // These two checks are actually quite expensive and almost *never* required.
+ // Almost. That's why they're still here. But there's no reason to do them
+ // in speed-targeted imports.
+ if (!configSpeedFlag) {
+
+ // It seems to be strange, but we really need to check whether the
+ // bones are identical too. Although it's extremely unprobable
+ // that they're not if control reaches here, we need to deal
+ // with unprobable cases, too. It could still be that there are
+ // equal shapes which are deformed differently.
+ if (!CompareBones(orig,inst))
+ continue;
+
+ // For completeness ... compare even the index buffers for equality
+ // face order & winding order doesn't care. Input data is in verbose format.
+ std::unique_ptr<unsigned int[]> ftbl_orig(new unsigned int[orig->mNumVertices]);
+ std::unique_ptr<unsigned int[]> ftbl_inst(new unsigned int[orig->mNumVertices]);
+
+ for (unsigned int tt = 0; tt < orig->mNumFaces;++tt) {
+ aiFace& f = orig->mFaces[tt];
+ for (unsigned int nn = 0; nn < f.mNumIndices;++nn)
+ ftbl_orig[f.mIndices[nn]] = tt;
+
+ aiFace& f2 = inst->mFaces[tt];
+ for (unsigned int nn = 0; nn < f2.mNumIndices;++nn)
+ ftbl_inst[f2.mIndices[nn]] = tt;
+ }
+ if (0 != ::memcmp(ftbl_inst.get(),ftbl_orig.get(),orig->mNumVertices*sizeof(unsigned int)))
+ continue;
+ }
+
+ // We're still here. Or in other words: 'inst' is an instance of 'orig'.
+ // Place a marker in our list that we can easily update mesh indices.
+ remapping[i] = remapping[a];
+
+ // Delete the instanced mesh, we don't need it anymore
+ delete inst;
+ pScene->mMeshes[i] = NULL;
+ break;
+ }
+ }
+
+ // If we didn't find a match for the current mesh: keep it
+ if (pScene->mMeshes[i]) {
+ remapping[i] = numMeshesOut++;
+ }
+ }
+ ai_assert(0 != numMeshesOut);
+ if (numMeshesOut != pScene->mNumMeshes) {
+
+ // Collapse the meshes array by removing all NULL entries
+ for (unsigned int real = 0, i = 0; real < numMeshesOut; ++i) {
+ if (pScene->mMeshes[i])
+ pScene->mMeshes[real++] = pScene->mMeshes[i];
+ }
+
+ // And update the node graph with our nice lookup table
+ UpdateMeshIndices(pScene->mRootNode,remapping.get());
+
+ // write to log
+ if (!DefaultLogger::isNullLogger()) {
+ ASSIMP_LOG_INFO_F( "FindInstancesProcess finished. Found ", (pScene->mNumMeshes - numMeshesOut), " instances" );
+ }
+ pScene->mNumMeshes = numMeshesOut;
+ } else {
+ ASSIMP_LOG_DEBUG("FindInstancesProcess finished. No instanced meshes found");
+ }
+ }
+}
diff --git a/thirdparty/assimp/code/FindInstancesProcess.h b/thirdparty/assimp/code/FindInstancesProcess.h
new file mode 100644
index 0000000000..ab4a371c71
--- /dev/null
+++ b/thirdparty/assimp/code/FindInstancesProcess.h
@@ -0,0 +1,137 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file FindInstancesProcess.h
+ * @brief Declares the aiProcess_FindInstances post-process step
+ */
+#ifndef AI_FINDINSTANCES_H_INC
+#define AI_FINDINSTANCES_H_INC
+
+#include "BaseProcess.h"
+#include "ProcessHelper.h"
+
+class FindInstancesProcessTest;
+namespace Assimp {
+
+// -------------------------------------------------------------------------------
+/** @brief Get a pseudo(!)-hash representing a mesh.
+ *
+ * The hash is built from number of vertices, faces, primitive types,
+ * .... but *not* from the real mesh data. The funcction is not a perfect hash.
+ * @param in Input mesh
+ * @return Hash.
+ */
+inline
+uint64_t GetMeshHash(aiMesh* in) {
+ ai_assert(nullptr != in);
+
+ // ... get an unique value representing the vertex format of the mesh
+ const unsigned int fhash = GetMeshVFormatUnique(in);
+
+ // and bake it with number of vertices/faces/bones/matidx/ptypes
+ return ((uint64_t)fhash << 32u) | ((
+ (in->mNumBones << 16u) ^ (in->mNumVertices) ^
+ (in->mNumFaces<<4u) ^ (in->mMaterialIndex<<15) ^
+ (in->mPrimitiveTypes<<28)) & 0xffffffff );
+}
+
+// -------------------------------------------------------------------------------
+/** @brief Perform a component-wise comparison of two arrays
+ *
+ * @param first First array
+ * @param second Second array
+ * @param size Size of both arrays
+ * @param e Epsilon
+ * @return true if the arrays are identical
+ */
+inline
+bool CompareArrays(const aiVector3D* first, const aiVector3D* second,
+ unsigned int size, float e) {
+ for (const aiVector3D* end = first+size; first != end; ++first,++second) {
+ if ( (*first - *second).SquareLength() >= e)
+ return false;
+ }
+ return true;
+}
+
+// and the same for colors ...
+inline bool CompareArrays(const aiColor4D* first, const aiColor4D* second,
+ unsigned int size, float e)
+{
+ for (const aiColor4D* end = first+size; first != end; ++first,++second) {
+ if ( GetColorDifference(*first,*second) >= e)
+ return false;
+ }
+ return true;
+}
+
+// ---------------------------------------------------------------------------
+/** @brief A post-processing steps to search for instanced meshes
+*/
+class FindInstancesProcess : public BaseProcess
+{
+public:
+
+ FindInstancesProcess();
+ ~FindInstancesProcess();
+
+public:
+ // -------------------------------------------------------------------
+ // Check whether step is active in given flags combination
+ bool IsActive( unsigned int pFlags) const;
+
+ // -------------------------------------------------------------------
+ // Execute step on a given scene
+ void Execute( aiScene* pScene);
+
+ // -------------------------------------------------------------------
+ // Setup properties prior to executing the process
+ void SetupProperties(const Importer* pImp);
+
+private:
+
+ bool configSpeedFlag;
+
+}; // ! end class FindInstancesProcess
+} // ! end namespace Assimp
+
+#endif // !! AI_FINDINSTANCES_H_INC
diff --git a/thirdparty/assimp/code/FindInvalidDataProcess.cpp b/thirdparty/assimp/code/FindInvalidDataProcess.cpp
new file mode 100644
index 0000000000..433f042448
--- /dev/null
+++ b/thirdparty/assimp/code/FindInvalidDataProcess.cpp
@@ -0,0 +1,424 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file Defines a post processing step to search an importer's output
+ for data that is obviously invalid */
+
+
+
+#ifndef ASSIMP_BUILD_NO_FINDINVALIDDATA_PROCESS
+
+// internal headers
+#include "FindInvalidDataProcess.h"
+#include "ProcessHelper.h"
+
+#include <assimp/Macros.h>
+#include <assimp/Exceptional.h>
+#include <assimp/qnan.h>
+
+using namespace Assimp;
+
+// ------------------------------------------------------------------------------------------------
+// Constructor to be privately used by Importer
+FindInvalidDataProcess::FindInvalidDataProcess()
+: configEpsilon(0.0)
+, mIgnoreTexCoods( false ){
+ // nothing to do here
+}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor, private as well
+FindInvalidDataProcess::~FindInvalidDataProcess() {
+ // nothing to do here
+}
+
+// ------------------------------------------------------------------------------------------------
+// Returns whether the processing step is present in the given flag field.
+bool FindInvalidDataProcess::IsActive( unsigned int pFlags) const {
+ return 0 != (pFlags & aiProcess_FindInvalidData);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Setup import configuration
+void FindInvalidDataProcess::SetupProperties(const Importer* pImp) {
+ // Get the current value of AI_CONFIG_PP_FID_ANIM_ACCURACY
+ configEpsilon = (0 != pImp->GetPropertyFloat(AI_CONFIG_PP_FID_ANIM_ACCURACY,0.f));
+ mIgnoreTexCoods = pImp->GetPropertyBool(AI_CONFIG_PP_FID_IGNORE_TEXTURECOORDS, false);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Update mesh references in the node graph
+void UpdateMeshReferences(aiNode* node, const std::vector<unsigned int>& meshMapping) {
+ if (node->mNumMeshes) {
+ unsigned int out = 0;
+ for (unsigned int a = 0; a < node->mNumMeshes;++a) {
+
+ unsigned int ref = node->mMeshes[a];
+ if (UINT_MAX != (ref = meshMapping[ref])) {
+ node->mMeshes[out++] = ref;
+ }
+ }
+ // just let the members that are unused, that's much cheaper
+ // than a full array realloc'n'copy party ...
+ if(!(node->mNumMeshes = out)) {
+
+ delete[] node->mMeshes;
+ node->mMeshes = NULL;
+ }
+ }
+ // recursively update all children
+ for (unsigned int i = 0; i < node->mNumChildren;++i) {
+ UpdateMeshReferences(node->mChildren[i],meshMapping);
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+void FindInvalidDataProcess::Execute( aiScene* pScene) {
+ ASSIMP_LOG_DEBUG("FindInvalidDataProcess begin");
+
+ bool out = false;
+ std::vector<unsigned int> meshMapping(pScene->mNumMeshes);
+ unsigned int real = 0;
+
+ // Process meshes
+ for( unsigned int a = 0; a < pScene->mNumMeshes; a++) {
+
+ int result;
+ if ((result = ProcessMesh( pScene->mMeshes[a]))) {
+ out = true;
+
+ if (2 == result) {
+ // remove this mesh
+ delete pScene->mMeshes[a];
+ AI_DEBUG_INVALIDATE_PTR(pScene->mMeshes[a]);
+
+ meshMapping[a] = UINT_MAX;
+ continue;
+ }
+ }
+ pScene->mMeshes[real] = pScene->mMeshes[a];
+ meshMapping[a] = real++;
+ }
+
+ // Process animations
+ for (unsigned int a = 0; a < pScene->mNumAnimations;++a) {
+ ProcessAnimation( pScene->mAnimations[a]);
+ }
+
+
+ if (out) {
+ if ( real != pScene->mNumMeshes) {
+ if (!real) {
+ throw DeadlyImportError("No meshes remaining");
+ }
+
+ // we need to remove some meshes.
+ // therefore we'll also need to remove all references
+ // to them from the scenegraph
+ UpdateMeshReferences(pScene->mRootNode,meshMapping);
+ pScene->mNumMeshes = real;
+ }
+
+ ASSIMP_LOG_INFO("FindInvalidDataProcess finished. Found issues ...");
+ } else {
+ ASSIMP_LOG_DEBUG("FindInvalidDataProcess finished. Everything seems to be OK.");
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename T>
+inline
+const char* ValidateArrayContents(const T* /*arr*/, unsigned int /*size*/,
+ const std::vector<bool>& /*dirtyMask*/, bool /*mayBeIdentical = false*/, bool /*mayBeZero = true*/)
+{
+ return nullptr;
+}
+
+// ------------------------------------------------------------------------------------------------
+template <>
+inline
+const char* ValidateArrayContents<aiVector3D>(const aiVector3D* arr, unsigned int size,
+ const std::vector<bool>& dirtyMask, bool mayBeIdentical , bool mayBeZero ) {
+ bool b = false;
+ unsigned int cnt = 0;
+ for (unsigned int i = 0; i < size;++i) {
+
+ if (dirtyMask.size() && dirtyMask[i]) {
+ continue;
+ }
+ ++cnt;
+
+ const aiVector3D& v = arr[i];
+ if (is_special_float(v.x) || is_special_float(v.y) || is_special_float(v.z)) {
+ return "INF/NAN was found in a vector component";
+ }
+ if (!mayBeZero && !v.x && !v.y && !v.z ) {
+ return "Found zero-length vector";
+ }
+ if (i && v != arr[i-1])b = true;
+ }
+ if (cnt > 1 && !b && !mayBeIdentical) {
+ return "All vectors are identical";
+ }
+ return nullptr;
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename T>
+inline
+bool ProcessArray(T*& in, unsigned int num,const char* name,
+ const std::vector<bool>& dirtyMask, bool mayBeIdentical = false, bool mayBeZero = true) {
+ const char* err = ValidateArrayContents(in,num,dirtyMask,mayBeIdentical,mayBeZero);
+ if (err) {
+ ASSIMP_LOG_ERROR_F( "FindInvalidDataProcess fails on mesh ", name, ": ", err);
+ delete[] in;
+ in = NULL;
+ return true;
+ }
+ return false;
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename T>
+AI_FORCE_INLINE bool EpsilonCompare(const T& n, const T& s, ai_real epsilon);
+
+// ------------------------------------------------------------------------------------------------
+AI_FORCE_INLINE bool EpsilonCompare(ai_real n, ai_real s, ai_real epsilon) {
+ return std::fabs(n-s)>epsilon;
+}
+
+// ------------------------------------------------------------------------------------------------
+template <>
+bool EpsilonCompare<aiVectorKey>(const aiVectorKey& n, const aiVectorKey& s, ai_real epsilon) {
+ return
+ EpsilonCompare(n.mValue.x,s.mValue.x,epsilon) &&
+ EpsilonCompare(n.mValue.y,s.mValue.y,epsilon) &&
+ EpsilonCompare(n.mValue.z,s.mValue.z,epsilon);
+}
+
+// ------------------------------------------------------------------------------------------------
+template <>
+bool EpsilonCompare<aiQuatKey>(const aiQuatKey& n, const aiQuatKey& s, ai_real epsilon) {
+ return
+ EpsilonCompare(n.mValue.x,s.mValue.x,epsilon) &&
+ EpsilonCompare(n.mValue.y,s.mValue.y,epsilon) &&
+ EpsilonCompare(n.mValue.z,s.mValue.z,epsilon) &&
+ EpsilonCompare(n.mValue.w,s.mValue.w,epsilon);
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename T>
+inline
+bool AllIdentical(T* in, unsigned int num, ai_real epsilon) {
+ if (num <= 1) {
+ return true;
+ }
+
+ if (fabs(epsilon) > 0.f) {
+ for (unsigned int i = 0; i < num-1;++i) {
+ if (!EpsilonCompare(in[i],in[i+1],epsilon)) {
+ return false;
+ }
+ }
+ } else {
+ for (unsigned int i = 0; i < num-1;++i) {
+ if (in[i] != in[i+1]) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Search an animation for invalid content
+void FindInvalidDataProcess::ProcessAnimation (aiAnimation* anim) {
+ // Process all animation channels
+ for ( unsigned int a = 0; a < anim->mNumChannels; ++a ) {
+ ProcessAnimationChannel( anim->mChannels[a]);
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+void FindInvalidDataProcess::ProcessAnimationChannel (aiNodeAnim* anim) {
+ ai_assert( nullptr != anim );
+ if (anim->mNumPositionKeys == 0 && anim->mNumRotationKeys == 0 && anim->mNumScalingKeys == 0) {
+ ai_assert_entry();
+ return;
+ }
+
+ // Check whether all values in a tracks are identical - in this case
+ // we can remove al keys except one.
+ // POSITIONS
+ int i = 0;
+ if (anim->mNumPositionKeys > 1 && AllIdentical(anim->mPositionKeys,anim->mNumPositionKeys,configEpsilon)) {
+ aiVectorKey v = anim->mPositionKeys[0];
+
+ // Reallocate ... we need just ONE element, it makes no sense to reuse the array
+ delete[] anim->mPositionKeys;
+ anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys = 1];
+ anim->mPositionKeys[0] = v;
+ i = 1;
+ }
+
+ // ROTATIONS
+ if (anim->mNumRotationKeys > 1 && AllIdentical(anim->mRotationKeys,anim->mNumRotationKeys,configEpsilon)) {
+ aiQuatKey v = anim->mRotationKeys[0];
+
+ // Reallocate ... we need just ONE element, it makes no sense to reuse the array
+ delete[] anim->mRotationKeys;
+ anim->mRotationKeys = new aiQuatKey[anim->mNumRotationKeys = 1];
+ anim->mRotationKeys[0] = v;
+ i = 1;
+ }
+
+ // SCALINGS
+ if (anim->mNumScalingKeys > 1 && AllIdentical(anim->mScalingKeys,anim->mNumScalingKeys,configEpsilon)) {
+ aiVectorKey v = anim->mScalingKeys[0];
+
+ // Reallocate ... we need just ONE element, it makes no sense to reuse the array
+ delete[] anim->mScalingKeys;
+ anim->mScalingKeys = new aiVectorKey[anim->mNumScalingKeys = 1];
+ anim->mScalingKeys[0] = v;
+ i = 1;
+ }
+ if ( 1 == i ) {
+ ASSIMP_LOG_WARN("Simplified dummy tracks with just one key");
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Search a mesh for invalid contents
+int FindInvalidDataProcess::ProcessMesh(aiMesh* pMesh)
+{
+ bool ret = false;
+ std::vector<bool> dirtyMask(pMesh->mNumVertices, pMesh->mNumFaces != 0);
+
+ // Ignore elements that are not referenced by vertices.
+ // (they are, for example, caused by the FindDegenerates step)
+ for (unsigned int m = 0; m < pMesh->mNumFaces; ++m) {
+ const aiFace& f = pMesh->mFaces[m];
+
+ for (unsigned int i = 0; i < f.mNumIndices; ++i) {
+ dirtyMask[f.mIndices[i]] = false;
+ }
+ }
+
+ // Process vertex positions
+ if (pMesh->mVertices && ProcessArray(pMesh->mVertices, pMesh->mNumVertices, "positions", dirtyMask)) {
+ ASSIMP_LOG_ERROR("Deleting mesh: Unable to continue without vertex positions");
+
+ return 2;
+ }
+
+ // process texture coordinates
+ if (!mIgnoreTexCoods) {
+ for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS && pMesh->mTextureCoords[i]; ++i) {
+ if (ProcessArray(pMesh->mTextureCoords[i], pMesh->mNumVertices, "uvcoords", dirtyMask)) {
+ pMesh->mNumUVComponents[i] = 0;
+
+ // delete all subsequent texture coordinate sets.
+ for (unsigned int a = i + 1; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) {
+ delete[] pMesh->mTextureCoords[a];
+ pMesh->mTextureCoords[a] = NULL;
+ pMesh->mNumUVComponents[a] = 0;
+ }
+
+ ret = true;
+ }
+ }
+ }
+
+ // -- we don't validate vertex colors, it's difficult to say whether
+ // they are invalid or not.
+
+ // Normals and tangents are undefined for point and line faces.
+ if (pMesh->mNormals || pMesh->mTangents) {
+
+ if (aiPrimitiveType_POINT & pMesh->mPrimitiveTypes ||
+ aiPrimitiveType_LINE & pMesh->mPrimitiveTypes)
+ {
+ if (aiPrimitiveType_TRIANGLE & pMesh->mPrimitiveTypes ||
+ aiPrimitiveType_POLYGON & pMesh->mPrimitiveTypes)
+ {
+ // We need to update the lookup-table
+ for (unsigned int m = 0; m < pMesh->mNumFaces;++m) {
+ const aiFace& f = pMesh->mFaces[ m ];
+
+ if (f.mNumIndices < 3) {
+ dirtyMask[f.mIndices[0]] = true;
+ if (f.mNumIndices == 2) {
+ dirtyMask[f.mIndices[1]] = true;
+ }
+ }
+ }
+ }
+ // Normals, tangents and bitangents are undefined for
+ // the whole mesh (and should not even be there)
+ else {
+ return ret;
+ }
+ }
+
+ // Process mesh normals
+ if (pMesh->mNormals && ProcessArray(pMesh->mNormals,pMesh->mNumVertices,
+ "normals",dirtyMask,true,false))
+ ret = true;
+
+ // Process mesh tangents
+ if (pMesh->mTangents && ProcessArray(pMesh->mTangents,pMesh->mNumVertices,"tangents",dirtyMask)) {
+ delete[] pMesh->mBitangents; pMesh->mBitangents = NULL;
+ ret = true;
+ }
+
+ // Process mesh bitangents
+ if (pMesh->mBitangents && ProcessArray(pMesh->mBitangents,pMesh->mNumVertices,"bitangents",dirtyMask)) {
+ delete[] pMesh->mTangents; pMesh->mTangents = NULL;
+ ret = true;
+ }
+ }
+ return ret ? 1 : 0;
+}
+
+#endif // !! ASSIMP_BUILD_NO_FINDINVALIDDATA_PROCESS
diff --git a/thirdparty/assimp/code/FindInvalidDataProcess.h b/thirdparty/assimp/code/FindInvalidDataProcess.h
new file mode 100644
index 0000000000..8504fb7b1f
--- /dev/null
+++ b/thirdparty/assimp/code/FindInvalidDataProcess.h
@@ -0,0 +1,105 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file Defines a post processing step to search an importer's output
+ * for data that is obviously invalid
+ */
+#ifndef AI_FINDINVALIDDATA_H_INC
+#define AI_FINDINVALIDDATA_H_INC
+
+#include "BaseProcess.h"
+#include <assimp/types.h>
+#include <assimp/anim.h>
+
+struct aiMesh;
+
+class FindInvalidDataProcessTest;
+
+namespace Assimp {
+
+// ---------------------------------------------------------------------------
+/** The FindInvalidData post-processing step. It searches the mesh data
+ * for parts that are obviously invalid and removes them.
+ *
+ * Originally this was a workaround for some models written by Blender
+ * which have zero normal vectors. */
+class ASSIMP_API FindInvalidDataProcess : public BaseProcess {
+public:
+ FindInvalidDataProcess();
+ ~FindInvalidDataProcess();
+
+ // -------------------------------------------------------------------
+ //
+ bool IsActive( unsigned int pFlags) const;
+
+ // -------------------------------------------------------------------
+ // Setup import settings
+ void SetupProperties(const Importer* pImp);
+
+ // -------------------------------------------------------------------
+ // Run the step
+ void Execute( aiScene* pScene);
+
+ // -------------------------------------------------------------------
+ /** Executes the post-processing step on the given mesh
+ * @param pMesh The mesh to process.
+ * @return 0 - nothing, 1 - removed sth, 2 - please delete me */
+ int ProcessMesh( aiMesh* pMesh);
+
+ // -------------------------------------------------------------------
+ /** Executes the post-processing step on the given animation
+ * @param anim The animation to process. */
+ void ProcessAnimation (aiAnimation* anim);
+
+ // -------------------------------------------------------------------
+ /** Executes the post-processing step on the given anim channel
+ * @param anim The animation channel to process.*/
+ void ProcessAnimationChannel (aiNodeAnim* anim);
+
+private:
+ ai_real configEpsilon;
+ bool mIgnoreTexCoods;
+};
+
+} // end of namespace Assimp
+
+#endif // AI_AI_FINDINVALIDDATA_H_INC
diff --git a/thirdparty/assimp/code/FixNormalsStep.cpp b/thirdparty/assimp/code/FixNormalsStep.cpp
new file mode 100644
index 0000000000..bbbe6899b4
--- /dev/null
+++ b/thirdparty/assimp/code/FixNormalsStep.cpp
@@ -0,0 +1,184 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file Implementation of the post processing step to invert
+ * all normals in meshes with infacing normals.
+ */
+
+// internal headers
+#include "FixNormalsStep.h"
+#include <assimp/StringUtils.h>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/postprocess.h>
+#include <assimp/scene.h>
+#include <stdio.h>
+
+
+using namespace Assimp;
+
+
+// ------------------------------------------------------------------------------------------------
+// Constructor to be privately used by Importer
+FixInfacingNormalsProcess::FixInfacingNormalsProcess()
+{
+ // nothing to do here
+}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor, private as well
+FixInfacingNormalsProcess::~FixInfacingNormalsProcess()
+{
+ // nothing to do here
+}
+
+// ------------------------------------------------------------------------------------------------
+// Returns whether the processing step is present in the given flag field.
+bool FixInfacingNormalsProcess::IsActive( unsigned int pFlags) const
+{
+ return (pFlags & aiProcess_FixInfacingNormals) != 0;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+void FixInfacingNormalsProcess::Execute( aiScene* pScene)
+{
+ ASSIMP_LOG_DEBUG("FixInfacingNormalsProcess begin");
+
+ bool bHas( false );
+ for (unsigned int a = 0; a < pScene->mNumMeshes; ++a) {
+ if (ProcessMesh(pScene->mMeshes[a], a)) {
+ bHas = true;
+ }
+ }
+
+ if (bHas) {
+ ASSIMP_LOG_DEBUG("FixInfacingNormalsProcess finished. Found issues.");
+ } else {
+ ASSIMP_LOG_DEBUG("FixInfacingNormalsProcess finished. No changes to the scene.");
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Apply the step to the mesh
+bool FixInfacingNormalsProcess::ProcessMesh( aiMesh* pcMesh, unsigned int index)
+{
+ ai_assert(nullptr != pcMesh);
+
+ // Nothing to do if there are no model normals
+ if (!pcMesh->HasNormals()) {
+ return false;
+ }
+
+ // Compute the bounding box of both the model vertices + normals and
+ // the unmodified model vertices. Then check whether the first BB
+ // is smaller than the second. In this case we can assume that the
+ // normals need to be flipped, although there are a few special cases ..
+ // convex, concave, planar models ...
+
+ aiVector3D vMin0 (1e10f,1e10f,1e10f);
+ aiVector3D vMin1 (1e10f,1e10f,1e10f);
+ aiVector3D vMax0 (-1e10f,-1e10f,-1e10f);
+ aiVector3D vMax1 (-1e10f,-1e10f,-1e10f);
+
+ for (unsigned int i = 0; i < pcMesh->mNumVertices;++i)
+ {
+ vMin1.x = std::min(vMin1.x,pcMesh->mVertices[i].x);
+ vMin1.y = std::min(vMin1.y,pcMesh->mVertices[i].y);
+ vMin1.z = std::min(vMin1.z,pcMesh->mVertices[i].z);
+
+ vMax1.x = std::max(vMax1.x,pcMesh->mVertices[i].x);
+ vMax1.y = std::max(vMax1.y,pcMesh->mVertices[i].y);
+ vMax1.z = std::max(vMax1.z,pcMesh->mVertices[i].z);
+
+ const aiVector3D vWithNormal = pcMesh->mVertices[i] + pcMesh->mNormals[i];
+
+ vMin0.x = std::min(vMin0.x,vWithNormal.x);
+ vMin0.y = std::min(vMin0.y,vWithNormal.y);
+ vMin0.z = std::min(vMin0.z,vWithNormal.z);
+
+ vMax0.x = std::max(vMax0.x,vWithNormal.x);
+ vMax0.y = std::max(vMax0.y,vWithNormal.y);
+ vMax0.z = std::max(vMax0.z,vWithNormal.z);
+ }
+
+ const float fDelta0_x = (vMax0.x - vMin0.x);
+ const float fDelta0_y = (vMax0.y - vMin0.y);
+ const float fDelta0_z = (vMax0.z - vMin0.z);
+
+ const float fDelta1_x = (vMax1.x - vMin1.x);
+ const float fDelta1_y = (vMax1.y - vMin1.y);
+ const float fDelta1_z = (vMax1.z - vMin1.z);
+
+ // Check whether the boxes are overlapping
+ if ((fDelta0_x > 0.0f) != (fDelta1_x > 0.0f))return false;
+ if ((fDelta0_y > 0.0f) != (fDelta1_y > 0.0f))return false;
+ if ((fDelta0_z > 0.0f) != (fDelta1_z > 0.0f))return false;
+
+ // Check whether this is a planar surface
+ const float fDelta1_yz = fDelta1_y * fDelta1_z;
+
+ if (fDelta1_x < 0.05f * std::sqrt( fDelta1_yz ))return false;
+ if (fDelta1_y < 0.05f * std::sqrt( fDelta1_z * fDelta1_x ))return false;
+ if (fDelta1_z < 0.05f * std::sqrt( fDelta1_y * fDelta1_x ))return false;
+
+ // now compare the volumes of the bounding boxes
+ if (std::fabs(fDelta0_x * fDelta0_y * fDelta0_z) < std::fabs(fDelta1_x * fDelta1_yz)) {
+ if (!DefaultLogger::isNullLogger()) {
+ ASSIMP_LOG_INFO_F("Mesh ", index, ": Normals are facing inwards (or the mesh is planar)", index);
+ }
+
+ // Invert normals
+ for (unsigned int i = 0; i < pcMesh->mNumVertices;++i)
+ pcMesh->mNormals[i] *= -1.0f;
+
+ // ... and flip faces
+ for (unsigned int i = 0; i < pcMesh->mNumFaces;++i)
+ {
+ aiFace& face = pcMesh->mFaces[i];
+ for( unsigned int b = 0; b < face.mNumIndices / 2; b++)
+ std::swap( face.mIndices[b], face.mIndices[ face.mNumIndices - 1 - b]);
+ }
+ return true;
+ }
+ return false;
+}
diff --git a/thirdparty/assimp/code/FixNormalsStep.h b/thirdparty/assimp/code/FixNormalsStep.h
new file mode 100644
index 0000000000..6be27faef6
--- /dev/null
+++ b/thirdparty/assimp/code/FixNormalsStep.h
@@ -0,0 +1,91 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+
+/** @file Defines a post processing step to fix infacing normals */
+#ifndef AI_FIXNORMALSPROCESS_H_INC
+#define AI_FIXNORMALSPROCESS_H_INC
+
+#include "BaseProcess.h"
+
+struct aiMesh;
+
+namespace Assimp
+{
+
+// ---------------------------------------------------------------------------
+/** The FixInfacingNormalsProcess tries to determine whether the normal
+ * vectors of an object are facing inwards. In this case they will be
+ * flipped.
+ */
+class FixInfacingNormalsProcess : public BaseProcess {
+public:
+ FixInfacingNormalsProcess();
+ ~FixInfacingNormalsProcess();
+
+ // -------------------------------------------------------------------
+ /** Returns whether the processing step is present in the given flag field.
+ * @param pFlags The processing flags the importer was called with. A bitwise
+ * combination of #aiPostProcessSteps.
+ * @return true if the process is present in this flag fields, false if not.
+ */
+ bool IsActive( unsigned int pFlags) const;
+
+ // -------------------------------------------------------------------
+ /** Executes the post processing step on the given imported data.
+ * At the moment a process is not supposed to fail.
+ * @param pScene The imported data to work at.
+ */
+ void Execute( aiScene* pScene);
+
+protected:
+
+ // -------------------------------------------------------------------
+ /** Executes the step on the given mesh
+ * @param pMesh The mesh to process.
+ */
+ bool ProcessMesh( aiMesh* pMesh, unsigned int index);
+};
+
+} // end of namespace Assimp
+
+#endif // AI_FIXNORMALSPROCESS_H_INC
diff --git a/thirdparty/assimp/code/GenFaceNormalsProcess.cpp b/thirdparty/assimp/code/GenFaceNormalsProcess.cpp
new file mode 100644
index 0000000000..028334dec7
--- /dev/null
+++ b/thirdparty/assimp/code/GenFaceNormalsProcess.cpp
@@ -0,0 +1,146 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file Implementation of the post processing step to generate face
+* normals for all imported faces.
+*/
+
+
+#include "GenFaceNormalsProcess.h"
+#include <assimp/postprocess.h>
+#include <assimp/scene.h>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/Exceptional.h>
+#include <assimp/qnan.h>
+
+
+using namespace Assimp;
+
+// ------------------------------------------------------------------------------------------------
+// Constructor to be privately used by Importer
+GenFaceNormalsProcess::GenFaceNormalsProcess()
+{
+ // nothing to do here
+}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor, private as well
+GenFaceNormalsProcess::~GenFaceNormalsProcess()
+{
+ // nothing to do here
+}
+
+// ------------------------------------------------------------------------------------------------
+// Returns whether the processing step is present in the given flag field.
+bool GenFaceNormalsProcess::IsActive( unsigned int pFlags) const {
+ force_ = (pFlags & aiProcess_ForceGenNormals) != 0;
+ return (pFlags & aiProcess_GenNormals) != 0;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+void GenFaceNormalsProcess::Execute( aiScene* pScene) {
+ ASSIMP_LOG_DEBUG("GenFaceNormalsProcess begin");
+
+ if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) {
+ throw DeadlyImportError("Post-processing order mismatch: expecting pseudo-indexed (\"verbose\") vertices here");
+ }
+
+ bool bHas = false;
+ for( unsigned int a = 0; a < pScene->mNumMeshes; a++) {
+ if(this->GenMeshFaceNormals( pScene->mMeshes[a])) {
+ bHas = true;
+ }
+ }
+ if (bHas) {
+ ASSIMP_LOG_INFO("GenFaceNormalsProcess finished. "
+ "Face normals have been calculated");
+ } else {
+ ASSIMP_LOG_DEBUG("GenFaceNormalsProcess finished. "
+ "Normals are already there");
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+bool GenFaceNormalsProcess::GenMeshFaceNormals (aiMesh* pMesh)
+{
+ if (NULL != pMesh->mNormals) {
+ if (force_) delete[] pMesh->mNormals;
+ else return false;
+ }
+
+ // If the mesh consists of lines and/or points but not of
+ // triangles or higher-order polygons the normal vectors
+ // are undefined.
+ if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON))) {
+ ASSIMP_LOG_INFO("Normal vectors are undefined for line and point meshes");
+ return false;
+ }
+
+ // allocate an array to hold the output normals
+ pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
+ const float qnan = get_qnan();
+
+ // iterate through all faces and compute per-face normals but store them per-vertex.
+ for( unsigned int a = 0; a < pMesh->mNumFaces; a++) {
+ const aiFace& face = pMesh->mFaces[a];
+ if (face.mNumIndices < 3) {
+ // either a point or a line -> no well-defined normal vector
+ for (unsigned int i = 0;i < face.mNumIndices;++i) {
+ pMesh->mNormals[face.mIndices[i]] = aiVector3D(qnan);
+ }
+ continue;
+ }
+
+ const aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]];
+ const aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]];
+ const aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices-1]];
+ const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).NormalizeSafe();
+
+ for (unsigned int i = 0;i < face.mNumIndices;++i) {
+ pMesh->mNormals[face.mIndices[i]] = vNor;
+ }
+ }
+ return true;
+}
diff --git a/thirdparty/assimp/code/GenFaceNormalsProcess.h b/thirdparty/assimp/code/GenFaceNormalsProcess.h
new file mode 100644
index 0000000000..c80ec9fddc
--- /dev/null
+++ b/thirdparty/assimp/code/GenFaceNormalsProcess.h
@@ -0,0 +1,87 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file Defines a post processing step to compute face normals for all loaded faces*/
+#ifndef AI_GENFACENORMALPROCESS_H_INC
+#define AI_GENFACENORMALPROCESS_H_INC
+
+#include "BaseProcess.h"
+#include <assimp/mesh.h>
+
+namespace Assimp
+{
+
+// ---------------------------------------------------------------------------
+/** The GenFaceNormalsProcess computes face normals for all faces of all meshes
+*/
+class ASSIMP_API_WINONLY GenFaceNormalsProcess : public BaseProcess
+{
+public:
+
+ GenFaceNormalsProcess();
+ ~GenFaceNormalsProcess();
+
+public:
+ // -------------------------------------------------------------------
+ /** Returns whether the processing step is present in the given flag field.
+ * @param pFlags The processing flags the importer was called with. A bitwise
+ * combination of #aiPostProcessSteps.
+ * @return true if the process is present in this flag fields, false if not.
+ */
+ bool IsActive( unsigned int pFlags) const;
+
+ // -------------------------------------------------------------------
+ /** Executes the post processing step on the given imported data.
+ * At the moment a process is not supposed to fail.
+ * @param pScene The imported data to work at.
+ */
+ void Execute( aiScene* pScene);
+
+
+private:
+ bool GenMeshFaceNormals(aiMesh* pcMesh);
+ mutable bool force_ = false;
+};
+
+} // end of namespace Assimp
+
+#endif // !!AI_GENFACENORMALPROCESS_H_INC
diff --git a/thirdparty/assimp/code/GenVertexNormalsProcess.cpp b/thirdparty/assimp/code/GenVertexNormalsProcess.cpp
new file mode 100644
index 0000000000..3f6c2f86bd
--- /dev/null
+++ b/thirdparty/assimp/code/GenVertexNormalsProcess.cpp
@@ -0,0 +1,239 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file Implementation of the post processing step to generate face
+* normals for all imported faces.
+*/
+
+
+
+// internal headers
+#include "GenVertexNormalsProcess.h"
+#include "ProcessHelper.h"
+#include <assimp/Exceptional.h>
+#include <assimp/qnan.h>
+
+using namespace Assimp;
+
+// ------------------------------------------------------------------------------------------------
+// Constructor to be privately used by Importer
+GenVertexNormalsProcess::GenVertexNormalsProcess()
+: configMaxAngle( AI_DEG_TO_RAD( 175.f ) ) {
+ // empty
+}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor, private as well
+GenVertexNormalsProcess::~GenVertexNormalsProcess() {
+ // nothing to do here
+}
+
+// ------------------------------------------------------------------------------------------------
+// Returns whether the processing step is present in the given flag field.
+bool GenVertexNormalsProcess::IsActive( unsigned int pFlags) const
+{
+ force_ = (pFlags & aiProcess_ForceGenNormals) != 0;
+ return (pFlags & aiProcess_GenSmoothNormals) != 0;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+void GenVertexNormalsProcess::SetupProperties(const Importer* pImp)
+{
+ // Get the current value of the AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE property
+ configMaxAngle = pImp->GetPropertyFloat(AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE,(ai_real)175.0);
+ configMaxAngle = AI_DEG_TO_RAD(std::max(std::min(configMaxAngle,(ai_real)175.0),(ai_real)0.0));
+}
+
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+void GenVertexNormalsProcess::Execute( aiScene* pScene)
+{
+ ASSIMP_LOG_DEBUG("GenVertexNormalsProcess begin");
+
+ if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) {
+ throw DeadlyImportError("Post-processing order mismatch: expecting pseudo-indexed (\"verbose\") vertices here");
+ }
+
+ bool bHas = false;
+ for( unsigned int a = 0; a < pScene->mNumMeshes; ++a) {
+ if(GenMeshVertexNormals( pScene->mMeshes[a],a))
+ bHas = true;
+ }
+
+ if (bHas) {
+ ASSIMP_LOG_INFO("GenVertexNormalsProcess finished. "
+ "Vertex normals have been calculated");
+ } else {
+ ASSIMP_LOG_DEBUG("GenVertexNormalsProcess finished. "
+ "Normals are already there");
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int meshIndex)
+{
+ if (NULL != pMesh->mNormals) {
+ if (force_) delete[] pMesh->mNormals;
+ else return false;
+ }
+
+ // If the mesh consists of lines and/or points but not of
+ // triangles or higher-order polygons the normal vectors
+ // are undefined.
+ if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON)))
+ {
+ ASSIMP_LOG_INFO("Normal vectors are undefined for line and point meshes");
+ return false;
+ }
+
+ // Allocate the array to hold the output normals
+ const float qnan = std::numeric_limits<ai_real>::quiet_NaN();
+ pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
+
+ // Compute per-face normals but store them per-vertex
+ for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
+ {
+ const aiFace& face = pMesh->mFaces[a];
+ if (face.mNumIndices < 3)
+ {
+ // either a point or a line -> no normal vector
+ for (unsigned int i = 0;i < face.mNumIndices;++i) {
+ pMesh->mNormals[face.mIndices[i]] = aiVector3D(qnan);
+ }
+
+ continue;
+ }
+
+ const aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]];
+ const aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]];
+ const aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices-1]];
+ const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).NormalizeSafe();
+
+ for (unsigned int i = 0;i < face.mNumIndices;++i) {
+ pMesh->mNormals[face.mIndices[i]] = vNor;
+ }
+ }
+
+ // Set up a SpatialSort to quickly find all vertices close to a given position
+ // check whether we can reuse the SpatialSort of a previous step.
+ SpatialSort* vertexFinder = NULL;
+ SpatialSort _vertexFinder;
+ ai_real posEpsilon = ai_real( 1e-5 );
+ if (shared) {
+ std::vector<std::pair<SpatialSort,ai_real> >* avf;
+ shared->GetProperty(AI_SPP_SPATIAL_SORT,avf);
+ if (avf)
+ {
+ std::pair<SpatialSort,ai_real>& blubb = avf->operator [] (meshIndex);
+ vertexFinder = &blubb.first;
+ posEpsilon = blubb.second;
+ }
+ }
+ if (!vertexFinder) {
+ _vertexFinder.Fill(pMesh->mVertices, pMesh->mNumVertices, sizeof( aiVector3D));
+ vertexFinder = &_vertexFinder;
+ posEpsilon = ComputePositionEpsilon(pMesh);
+ }
+ std::vector<unsigned int> verticesFound;
+ aiVector3D* pcNew = new aiVector3D[pMesh->mNumVertices];
+
+ if (configMaxAngle >= AI_DEG_TO_RAD( 175.f )) {
+ // There is no angle limit. Thus all vertices with positions close
+ // to each other will receive the same vertex normal. This allows us
+ // to optimize the whole algorithm a little bit ...
+ std::vector<bool> abHad(pMesh->mNumVertices,false);
+ for (unsigned int i = 0; i < pMesh->mNumVertices;++i) {
+ if (abHad[i]) {
+ continue;
+ }
+
+ // Get all vertices that share this one ...
+ vertexFinder->FindPositions( pMesh->mVertices[i], posEpsilon, verticesFound);
+
+ aiVector3D pcNor;
+ for (unsigned int a = 0; a < verticesFound.size(); ++a) {
+ const aiVector3D& v = pMesh->mNormals[verticesFound[a]];
+ if (is_not_qnan(v.x))pcNor += v;
+ }
+ pcNor.NormalizeSafe();
+
+ // Write the smoothed normal back to all affected normals
+ for (unsigned int a = 0; a < verticesFound.size(); ++a)
+ {
+ unsigned int vidx = verticesFound[a];
+ pcNew[vidx] = pcNor;
+ abHad[vidx] = true;
+ }
+ }
+ }
+ // Slower code path if a smooth angle is set. There are many ways to achieve
+ // the effect, this one is the most straightforward one.
+ else {
+ const ai_real fLimit = std::cos(configMaxAngle);
+ for (unsigned int i = 0; i < pMesh->mNumVertices;++i) {
+ // Get all vertices that share this one ...
+ vertexFinder->FindPositions( pMesh->mVertices[i] , posEpsilon, verticesFound);
+
+ aiVector3D vr = pMesh->mNormals[i];
+
+ aiVector3D pcNor;
+ for (unsigned int a = 0; a < verticesFound.size(); ++a) {
+ aiVector3D v = pMesh->mNormals[verticesFound[a]];
+
+ // Check whether the angle between the two normals is not too large.
+ // Skip the angle check on our own normal to avoid false negatives
+ // (v*v is not guaranteed to be 1.0 for all unit vectors v)
+ if (is_not_qnan(v.x) && (verticesFound[a] == i || (v * vr >= fLimit)))
+ pcNor += v;
+ }
+ pcNew[i] = pcNor.NormalizeSafe();
+ }
+ }
+
+ delete[] pMesh->mNormals;
+ pMesh->mNormals = pcNew;
+
+ return true;
+}
diff --git a/thirdparty/assimp/code/GenVertexNormalsProcess.h b/thirdparty/assimp/code/GenVertexNormalsProcess.h
new file mode 100644
index 0000000000..9142ad26f5
--- /dev/null
+++ b/thirdparty/assimp/code/GenVertexNormalsProcess.h
@@ -0,0 +1,115 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file Defines a post processing step to compute vertex normals
+ for all loaded vertizes */
+#ifndef AI_GENVERTEXNORMALPROCESS_H_INC
+#define AI_GENVERTEXNORMALPROCESS_H_INC
+
+#include "BaseProcess.h"
+#include <assimp/mesh.h>
+
+class GenNormalsTest;
+
+namespace Assimp {
+
+// ---------------------------------------------------------------------------
+/** The GenFaceNormalsProcess computes vertex normals for all vertizes
+*/
+class ASSIMP_API GenVertexNormalsProcess : public BaseProcess
+{
+public:
+
+ GenVertexNormalsProcess();
+ ~GenVertexNormalsProcess();
+
+public:
+ // -------------------------------------------------------------------
+ /** Returns whether the processing step is present in the given flag.
+ * @param pFlags The processing flags the importer was called with.
+ * A bitwise combination of #aiPostProcessSteps.
+ * @return true if the process is present in this flag fields,
+ * false if not.
+ */
+ bool IsActive( unsigned int pFlags) const;
+
+ // -------------------------------------------------------------------
+ /** Called prior to ExecuteOnScene().
+ * The function is a request to the process to update its configuration
+ * basing on the Importer's configuration property list.
+ */
+ void SetupProperties(const Importer* pImp);
+
+ // -------------------------------------------------------------------
+ /** Executes the post processing step on the given imported data.
+ * At the moment a process is not supposed to fail.
+ * @param pScene The imported data to work at.
+ */
+ void Execute( aiScene* pScene);
+
+
+ // setter for configMaxAngle
+ inline void SetMaxSmoothAngle(ai_real f)
+ {
+ configMaxAngle =f;
+ }
+
+public:
+
+ // -------------------------------------------------------------------
+ /** Computes normals for a specific mesh
+ * @param pcMesh Mesh
+ * @param meshIndex Index of the mesh
+ * @return true if vertex normals have been computed
+ */
+ bool GenMeshVertexNormals (aiMesh* pcMesh, unsigned int meshIndex);
+
+private:
+
+ /** Configuration option: maximum smoothing angle, in radians*/
+ ai_real configMaxAngle;
+ mutable bool force_ = false;
+};
+
+} // end of namespace Assimp
+
+#endif // !!AI_GENVERTEXNORMALPROCESS_H_INC
diff --git a/thirdparty/assimp/code/Importer.cpp b/thirdparty/assimp/code/Importer.cpp
new file mode 100644
index 0000000000..65b16471cc
--- /dev/null
+++ b/thirdparty/assimp/code/Importer.cpp
@@ -0,0 +1,1171 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file Importer.cpp
+ * @brief Implementation of the CPP-API class #Importer
+ */
+
+#include <assimp/version.h>
+#include <assimp/config.h>
+#include <assimp/importerdesc.h>
+
+// ------------------------------------------------------------------------------------------------
+/* Uncomment this line to prevent Assimp from catching unknown exceptions.
+ *
+ * Note that any Exception except DeadlyImportError may lead to
+ * undefined behaviour -> loaders could remain in an unusable state and
+ * further imports with the same Importer instance could fail/crash/burn ...
+ */
+// ------------------------------------------------------------------------------------------------
+#ifndef ASSIMP_BUILD_DEBUG
+# define ASSIMP_CATCH_GLOBAL_EXCEPTIONS
+#endif
+
+// ------------------------------------------------------------------------------------------------
+// Internal headers
+// ------------------------------------------------------------------------------------------------
+#include "Importer.h"
+#include <assimp/BaseImporter.h>
+#include "BaseProcess.h"
+
+#include "DefaultProgressHandler.h"
+#include <assimp/GenericProperty.h>
+#include "ProcessHelper.h"
+#include "ScenePreprocessor.h"
+#include "ScenePrivate.h"
+#include <assimp/MemoryIOWrapper.h>
+#include <assimp/Profiler.h>
+#include <assimp/TinyFormatter.h>
+#include <assimp/Exceptional.h>
+#include <assimp/Profiler.h>
+#include <set>
+#include <memory>
+#include <cctype>
+
+#include <assimp/DefaultIOStream.h>
+#include <assimp/DefaultIOSystem.h>
+
+#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
+# include "ValidateDataStructure.h"
+#endif
+
+using namespace Assimp::Profiling;
+using namespace Assimp::Formatter;
+
+namespace Assimp {
+ // ImporterRegistry.cpp
+ void GetImporterInstanceList(std::vector< BaseImporter* >& out);
+ void DeleteImporterInstanceList(std::vector< BaseImporter* >& out);
+
+ // PostStepRegistry.cpp
+ void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out);
+}
+
+using namespace Assimp;
+using namespace Assimp::Intern;
+
+// ------------------------------------------------------------------------------------------------
+// Intern::AllocateFromAssimpHeap serves as abstract base class. It overrides
+// new and delete (and their array counterparts) of public API classes (e.g. Logger) to
+// utilize our DLL heap.
+// See http://www.gotw.ca/publications/mill15.htm
+// ------------------------------------------------------------------------------------------------
+void* AllocateFromAssimpHeap::operator new ( size_t num_bytes) {
+ return ::operator new(num_bytes);
+}
+
+void* AllocateFromAssimpHeap::operator new ( size_t num_bytes, const std::nothrow_t& ) throw() {
+ try {
+ return AllocateFromAssimpHeap::operator new( num_bytes );
+ }
+ catch( ... ) {
+ return NULL;
+ }
+}
+
+void AllocateFromAssimpHeap::operator delete ( void* data) {
+ return ::operator delete(data);
+}
+
+void* AllocateFromAssimpHeap::operator new[] ( size_t num_bytes) {
+ return ::operator new[](num_bytes);
+}
+
+void* AllocateFromAssimpHeap::operator new[] ( size_t num_bytes, const std::nothrow_t& ) throw() {
+ try {
+ return AllocateFromAssimpHeap::operator new[]( num_bytes );
+ }
+ catch( ... ) {
+ return NULL;
+ }
+}
+
+void AllocateFromAssimpHeap::operator delete[] ( void* data) {
+ return ::operator delete[](data);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Importer constructor.
+Importer::Importer()
+ : pimpl( new ImporterPimpl ) {
+ pimpl->mScene = NULL;
+ pimpl->mErrorString = "";
+
+ // Allocate a default IO handler
+ pimpl->mIOHandler = new DefaultIOSystem;
+ pimpl->mIsDefaultHandler = true;
+ pimpl->bExtraVerbose = false; // disable extra verbose mode by default
+
+ pimpl->mProgressHandler = new DefaultProgressHandler();
+ pimpl->mIsDefaultProgressHandler = true;
+
+ GetImporterInstanceList(pimpl->mImporter);
+ GetPostProcessingStepInstanceList(pimpl->mPostProcessingSteps);
+
+ // Allocate a SharedPostProcessInfo object and store pointers to it in all post-process steps in the list.
+ pimpl->mPPShared = new SharedPostProcessInfo();
+ for (std::vector<BaseProcess*>::iterator it = pimpl->mPostProcessingSteps.begin();
+ it != pimpl->mPostProcessingSteps.end();
+ ++it) {
+
+ (*it)->SetSharedData(pimpl->mPPShared);
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor of Importer
+Importer::~Importer()
+{
+ // Delete all import plugins
+ DeleteImporterInstanceList(pimpl->mImporter);
+
+ // Delete all post-processing plug-ins
+ for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++)
+ delete pimpl->mPostProcessingSteps[a];
+
+ // Delete the assigned IO and progress handler
+ delete pimpl->mIOHandler;
+ delete pimpl->mProgressHandler;
+
+ // Kill imported scene. Destructor's should do that recursively
+ delete pimpl->mScene;
+
+ // Delete shared post-processing data
+ delete pimpl->mPPShared;
+
+ // and finally the pimpl itself
+ delete pimpl;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Register a custom post-processing step
+aiReturn Importer::RegisterPPStep(BaseProcess* pImp)
+{
+ ai_assert(NULL != pImp);
+ ASSIMP_BEGIN_EXCEPTION_REGION();
+
+ pimpl->mPostProcessingSteps.push_back(pImp);
+ ASSIMP_LOG_INFO("Registering custom post-processing step");
+
+ ASSIMP_END_EXCEPTION_REGION(aiReturn);
+ return AI_SUCCESS;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Register a custom loader plugin
+aiReturn Importer::RegisterLoader(BaseImporter* pImp)
+{
+ ai_assert(NULL != pImp);
+ ASSIMP_BEGIN_EXCEPTION_REGION();
+
+ // --------------------------------------------------------------------
+ // Check whether we would have two loaders for the same file extension
+ // This is absolutely OK, but we should warn the developer of the new
+ // loader that his code will probably never be called if the first
+ // loader is a bit too lazy in his file checking.
+ // --------------------------------------------------------------------
+ std::set<std::string> st;
+ std::string baked;
+ pImp->GetExtensionList(st);
+
+ for(std::set<std::string>::const_iterator it = st.begin(); it != st.end(); ++it) {
+
+#ifdef ASSIMP_BUILD_DEBUG
+ if (IsExtensionSupported(*it)) {
+ ASSIMP_LOG_WARN_F("The file extension ", *it, " is already in use");
+ }
+#endif
+ baked += *it;
+ }
+
+ // add the loader
+ pimpl->mImporter.push_back(pImp);
+ ASSIMP_LOG_INFO_F("Registering custom importer for these file extensions: ", baked);
+ ASSIMP_END_EXCEPTION_REGION(aiReturn);
+ return AI_SUCCESS;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Unregister a custom loader plugin
+aiReturn Importer::UnregisterLoader(BaseImporter* pImp)
+{
+ if(!pImp) {
+ // unregistering a NULL importer is no problem for us ... really!
+ return AI_SUCCESS;
+ }
+
+ ASSIMP_BEGIN_EXCEPTION_REGION();
+ std::vector<BaseImporter*>::iterator it = std::find(pimpl->mImporter.begin(),
+ pimpl->mImporter.end(),pImp);
+
+ if (it != pimpl->mImporter.end()) {
+ pimpl->mImporter.erase(it);
+ ASSIMP_LOG_INFO("Unregistering custom importer: ");
+ return AI_SUCCESS;
+ }
+ ASSIMP_LOG_WARN("Unable to remove custom importer: I can't find you ...");
+ ASSIMP_END_EXCEPTION_REGION(aiReturn);
+ return AI_FAILURE;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Unregister a custom loader plugin
+aiReturn Importer::UnregisterPPStep(BaseProcess* pImp)
+{
+ if(!pImp) {
+ // unregistering a NULL ppstep is no problem for us ... really!
+ return AI_SUCCESS;
+ }
+
+ ASSIMP_BEGIN_EXCEPTION_REGION();
+ std::vector<BaseProcess*>::iterator it = std::find(pimpl->mPostProcessingSteps.begin(),
+ pimpl->mPostProcessingSteps.end(),pImp);
+
+ if (it != pimpl->mPostProcessingSteps.end()) {
+ pimpl->mPostProcessingSteps.erase(it);
+ ASSIMP_LOG_INFO("Unregistering custom post-processing step");
+ return AI_SUCCESS;
+ }
+ ASSIMP_LOG_WARN("Unable to remove custom post-processing step: I can't find you ..");
+ ASSIMP_END_EXCEPTION_REGION(aiReturn);
+ return AI_FAILURE;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Supplies a custom IO handler to the importer to open and access files.
+void Importer::SetIOHandler( IOSystem* pIOHandler)
+{
+ ASSIMP_BEGIN_EXCEPTION_REGION();
+ // If the new handler is zero, allocate a default IO implementation.
+ if (!pIOHandler)
+ {
+ // Release pointer in the possession of the caller
+ pimpl->mIOHandler = new DefaultIOSystem();
+ pimpl->mIsDefaultHandler = true;
+ }
+ // Otherwise register the custom handler
+ else if (pimpl->mIOHandler != pIOHandler)
+ {
+ delete pimpl->mIOHandler;
+ pimpl->mIOHandler = pIOHandler;
+ pimpl->mIsDefaultHandler = false;
+ }
+ ASSIMP_END_EXCEPTION_REGION(void);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Get the currently set IO handler
+IOSystem* Importer::GetIOHandler() const {
+ return pimpl->mIOHandler;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Check whether a custom IO handler is currently set
+bool Importer::IsDefaultIOHandler() const {
+ return pimpl->mIsDefaultHandler;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Supplies a custom progress handler to get regular callbacks during importing
+void Importer::SetProgressHandler ( ProgressHandler* pHandler ) {
+ ASSIMP_BEGIN_EXCEPTION_REGION();
+ // If the new handler is zero, allocate a default implementation.
+ if (!pHandler)
+ {
+ // Release pointer in the possession of the caller
+ pimpl->mProgressHandler = new DefaultProgressHandler();
+ pimpl->mIsDefaultProgressHandler = true;
+ }
+ // Otherwise register the custom handler
+ else if (pimpl->mProgressHandler != pHandler)
+ {
+ delete pimpl->mProgressHandler;
+ pimpl->mProgressHandler = pHandler;
+ pimpl->mIsDefaultProgressHandler = false;
+ }
+ ASSIMP_END_EXCEPTION_REGION(void);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Get the currently set progress handler
+ProgressHandler* Importer::GetProgressHandler() const {
+ return pimpl->mProgressHandler;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Check whether a custom progress handler is currently set
+bool Importer::IsDefaultProgressHandler() const {
+ return pimpl->mIsDefaultProgressHandler;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Validate post process step flags
+bool _ValidateFlags(unsigned int pFlags)
+{
+ if (pFlags & aiProcess_GenSmoothNormals && pFlags & aiProcess_GenNormals) {
+ ASSIMP_LOG_ERROR("#aiProcess_GenSmoothNormals and #aiProcess_GenNormals are incompatible");
+ return false;
+ }
+ if (pFlags & aiProcess_OptimizeGraph && pFlags & aiProcess_PreTransformVertices) {
+ ASSIMP_LOG_ERROR("#aiProcess_OptimizeGraph and #aiProcess_PreTransformVertices are incompatible");
+ return false;
+ }
+ return true;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Free the current scene
+void Importer::FreeScene( )
+{
+ ASSIMP_BEGIN_EXCEPTION_REGION();
+
+ delete pimpl->mScene;
+ pimpl->mScene = NULL;
+
+ pimpl->mErrorString = "";
+ ASSIMP_END_EXCEPTION_REGION(void);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Get the current error string, if any
+const char* Importer::GetErrorString() const
+{
+ /* Must remain valid as long as ReadFile() or FreeFile() are not called */
+ return pimpl->mErrorString.c_str();
+}
+
+// ------------------------------------------------------------------------------------------------
+// Enable extra-verbose mode
+void Importer::SetExtraVerbose(bool bDo)
+{
+ pimpl->bExtraVerbose = bDo;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Get the current scene
+const aiScene* Importer::GetScene() const
+{
+ return pimpl->mScene;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Orphan the current scene and return it.
+aiScene* Importer::GetOrphanedScene()
+{
+ aiScene* s = pimpl->mScene;
+
+ ASSIMP_BEGIN_EXCEPTION_REGION();
+ pimpl->mScene = NULL;
+
+ pimpl->mErrorString = ""; /* reset error string */
+ ASSIMP_END_EXCEPTION_REGION(aiScene*);
+ return s;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Validate post-processing flags
+bool Importer::ValidateFlags(unsigned int pFlags) const
+{
+ ASSIMP_BEGIN_EXCEPTION_REGION();
+ // run basic checks for mutually exclusive flags
+ if(!_ValidateFlags(pFlags)) {
+ return false;
+ }
+
+ // ValidateDS does not anymore occur in the pp list, it plays an awesome extra role ...
+#ifdef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
+ if (pFlags & aiProcess_ValidateDataStructure) {
+ return false;
+ }
+#endif
+ pFlags &= ~aiProcess_ValidateDataStructure;
+
+ // Now iterate through all bits which are set in the flags and check whether we find at least
+ // one pp plugin which handles it.
+ for (unsigned int mask = 1; mask < (1u << (sizeof(unsigned int)*8-1));mask <<= 1) {
+
+ if (pFlags & mask) {
+
+ bool have = false;
+ for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
+ if (pimpl->mPostProcessingSteps[a]-> IsActive(mask) ) {
+
+ have = true;
+ break;
+ }
+ }
+ if (!have) {
+ return false;
+ }
+ }
+ }
+ ASSIMP_END_EXCEPTION_REGION(bool);
+ return true;
+}
+
+// ------------------------------------------------------------------------------------------------
+const aiScene* Importer::ReadFileFromMemory( const void* pBuffer,
+ size_t pLength,
+ unsigned int pFlags,
+ const char* pHint /*= ""*/)
+{
+ ASSIMP_BEGIN_EXCEPTION_REGION();
+ if (!pHint) {
+ pHint = "";
+ }
+
+ if (!pBuffer || !pLength || strlen(pHint) > MaxLenHint ) {
+ pimpl->mErrorString = "Invalid parameters passed to ReadFileFromMemory()";
+ return NULL;
+ }
+
+ // prevent deletion of the previous IOHandler
+ IOSystem* io = pimpl->mIOHandler;
+ pimpl->mIOHandler = NULL;
+
+ SetIOHandler(new MemoryIOSystem((const uint8_t*)pBuffer,pLength,io));
+
+ // read the file and recover the previous IOSystem
+ static const size_t BufSize(Importer::MaxLenHint + 28);
+ char fbuff[BufSize];
+ ai_snprintf(fbuff, BufSize, "%s.%s",AI_MEMORYIO_MAGIC_FILENAME,pHint);
+
+ ReadFile(fbuff,pFlags);
+ SetIOHandler(io);
+
+ ASSIMP_END_EXCEPTION_REGION(const aiScene*);
+ return pimpl->mScene;
+}
+
+// ------------------------------------------------------------------------------------------------
+void WriteLogOpening(const std::string& file)
+{
+ ASSIMP_LOG_INFO_F("Load ", file);
+
+ // print a full version dump. This is nice because we don't
+ // need to ask the authors of incoming bug reports for
+ // the library version they're using - a log dump is
+ // sufficient.
+ const unsigned int flags( aiGetCompileFlags() );
+ std::stringstream stream;
+ stream << "Assimp " << aiGetVersionMajor() << "." << aiGetVersionMinor() << "." << aiGetVersionRevision() << " "
+#if defined(ASSIMP_BUILD_ARCHITECTURE)
+ << ASSIMP_BUILD_ARCHITECTURE
+#elif defined(_M_IX86) || defined(__x86_32__) || defined(__i386__)
+ << "x86"
+#elif defined(_M_X64) || defined(__x86_64__)
+ << "amd64"
+#elif defined(_M_IA64) || defined(__ia64__)
+ << "itanium"
+#elif defined(__ppc__) || defined(__powerpc__)
+ << "ppc32"
+#elif defined(__powerpc64__)
+ << "ppc64"
+#elif defined(__arm__)
+ << "arm"
+#else
+ << "<unknown architecture>"
+#endif
+ << " "
+#if defined(ASSIMP_BUILD_COMPILER)
+ << ( ASSIMP_BUILD_COMPILER )
+#elif defined(_MSC_VER)
+ << "msvc"
+#elif defined(__GNUC__)
+ << "gcc"
+#else
+ << "<unknown compiler>"
+#endif
+
+#ifdef ASSIMP_BUILD_DEBUG
+ << " debug"
+#endif
+
+ << (flags & ASSIMP_CFLAGS_NOBOOST ? " noboost" : "")
+ << (flags & ASSIMP_CFLAGS_SHARED ? " shared" : "")
+ << (flags & ASSIMP_CFLAGS_SINGLETHREADED ? " singlethreaded" : "");
+
+ ASSIMP_LOG_DEBUG(stream.str());
+}
+
+// ------------------------------------------------------------------------------------------------
+// Reads the given file and returns its contents if successful.
+const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
+{
+ ASSIMP_BEGIN_EXCEPTION_REGION();
+ const std::string pFile(_pFile);
+
+ // ----------------------------------------------------------------------
+ // Put a large try block around everything to catch all std::exception's
+ // that might be thrown by STL containers or by new().
+ // ImportErrorException's are throw by ourselves and caught elsewhere.
+ //-----------------------------------------------------------------------
+
+ WriteLogOpening(pFile);
+
+#ifdef ASSIMP_CATCH_GLOBAL_EXCEPTIONS
+ try
+#endif // ! ASSIMP_CATCH_GLOBAL_EXCEPTIONS
+ {
+ // Check whether this Importer instance has already loaded
+ // a scene. In this case we need to delete the old one
+ if (pimpl->mScene) {
+
+ ASSIMP_LOG_DEBUG("(Deleting previous scene)");
+ FreeScene();
+ }
+
+ // First check if the file is accessible at all
+ if( !pimpl->mIOHandler->Exists( pFile)) {
+
+ pimpl->mErrorString = "Unable to open file \"" + pFile + "\".";
+ ASSIMP_LOG_ERROR(pimpl->mErrorString);
+ return NULL;
+ }
+
+ std::unique_ptr<Profiler> profiler(GetPropertyInteger(AI_CONFIG_GLOB_MEASURE_TIME,0)?new Profiler():NULL);
+ if (profiler) {
+ profiler->BeginRegion("total");
+ }
+
+ // Find an worker class which can handle the file
+ BaseImporter* imp = NULL;
+ for( unsigned int a = 0; a < pimpl->mImporter.size(); a++) {
+
+ if( pimpl->mImporter[a]->CanRead( pFile, pimpl->mIOHandler, false)) {
+ imp = pimpl->mImporter[a];
+ break;
+ }
+ }
+
+ if (!imp) {
+ // not so bad yet ... try format auto detection.
+ const std::string::size_type s = pFile.find_last_of('.');
+ if (s != std::string::npos) {
+ ASSIMP_LOG_INFO("File extension not known, trying signature-based detection");
+ for( unsigned int a = 0; a < pimpl->mImporter.size(); a++) {
+ if( pimpl->mImporter[a]->CanRead( pFile, pimpl->mIOHandler, true)) {
+ imp = pimpl->mImporter[a];
+ break;
+ }
+ }
+ }
+ // Put a proper error message if no suitable importer was found
+ if( !imp) {
+ pimpl->mErrorString = "No suitable reader found for the file format of file \"" + pFile + "\".";
+ ASSIMP_LOG_ERROR(pimpl->mErrorString);
+ return NULL;
+ }
+ }
+
+ // Get file size for progress handler
+ IOStream * fileIO = pimpl->mIOHandler->Open( pFile );
+ uint32_t fileSize = 0;
+ if (fileIO)
+ {
+ fileSize = static_cast<uint32_t>(fileIO->FileSize());
+ pimpl->mIOHandler->Close( fileIO );
+ }
+
+ // Dispatch the reading to the worker class for this format
+ const aiImporterDesc *desc( imp->GetInfo() );
+ std::string ext( "unknown" );
+ if ( NULL != desc ) {
+ ext = desc->mName;
+ }
+ ASSIMP_LOG_INFO("Found a matching importer for this file format: " + ext + "." );
+ pimpl->mProgressHandler->UpdateFileRead( 0, fileSize );
+
+ if (profiler) {
+ profiler->BeginRegion("import");
+ }
+
+ pimpl->mScene = imp->ReadFile( this, pFile, pimpl->mIOHandler);
+ pimpl->mProgressHandler->UpdateFileRead( fileSize, fileSize );
+
+ if (profiler) {
+ profiler->EndRegion("import");
+ }
+
+ SetPropertyString("sourceFilePath", pFile);
+
+ // If successful, apply all active post processing steps to the imported data
+ if( pimpl->mScene) {
+
+#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
+ // The ValidateDS process is an exception. It is executed first, even before ScenePreprocessor is called.
+ if (pFlags & aiProcess_ValidateDataStructure)
+ {
+ ValidateDSProcess ds;
+ ds.ExecuteOnScene (this);
+ if (!pimpl->mScene) {
+ return NULL;
+ }
+ }
+#endif // no validation
+
+ // Preprocess the scene and prepare it for post-processing
+ if (profiler) {
+ profiler->BeginRegion("preprocess");
+ }
+
+ ScenePreprocessor pre(pimpl->mScene);
+ pre.ProcessScene();
+
+ if (profiler) {
+ profiler->EndRegion("preprocess");
+ }
+
+ // Ensure that the validation process won't be called twice
+ ApplyPostProcessing(pFlags & (~aiProcess_ValidateDataStructure));
+ }
+ // if failed, extract the error string
+ else if( !pimpl->mScene) {
+ pimpl->mErrorString = imp->GetErrorText();
+ }
+
+ // clear any data allocated by post-process steps
+ pimpl->mPPShared->Clean();
+
+ if (profiler) {
+ profiler->EndRegion("total");
+ }
+ }
+#ifdef ASSIMP_CATCH_GLOBAL_EXCEPTIONS
+ catch (std::exception &e)
+ {
+#if (defined _MSC_VER) && (defined _CPPRTTI)
+ // if we have RTTI get the full name of the exception that occurred
+ pimpl->mErrorString = std::string(typeid( e ).name()) + ": " + e.what();
+#else
+ pimpl->mErrorString = std::string("std::exception: ") + e.what();
+#endif
+
+ ASSIMP_LOG_ERROR(pimpl->mErrorString);
+ delete pimpl->mScene; pimpl->mScene = NULL;
+ }
+#endif // ! ASSIMP_CATCH_GLOBAL_EXCEPTIONS
+
+ // either successful or failure - the pointer expresses it anyways
+ ASSIMP_END_EXCEPTION_REGION(const aiScene*);
+ return pimpl->mScene;
+}
+
+
+// ------------------------------------------------------------------------------------------------
+// Apply post-processing to the currently bound scene
+const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags)
+{
+ ASSIMP_BEGIN_EXCEPTION_REGION();
+ // Return immediately if no scene is active
+ if (!pimpl->mScene) {
+ return NULL;
+ }
+
+ // If no flags are given, return the current scene with no further action
+ if (!pFlags) {
+ return pimpl->mScene;
+ }
+
+ // In debug builds: run basic flag validation
+ ai_assert(_ValidateFlags(pFlags));
+ ASSIMP_LOG_INFO("Entering post processing pipeline");
+
+#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
+ // The ValidateDS process plays an exceptional role. It isn't contained in the global
+ // list of post-processing steps, so we need to call it manually.
+ if (pFlags & aiProcess_ValidateDataStructure)
+ {
+ ValidateDSProcess ds;
+ ds.ExecuteOnScene (this);
+ if (!pimpl->mScene) {
+ return NULL;
+ }
+ }
+#endif // no validation
+#ifdef ASSIMP_BUILD_DEBUG
+ if (pimpl->bExtraVerbose)
+ {
+#ifdef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
+ ASSIMP_LOG_ERROR("Verbose Import is not available due to build settings");
+#endif // no validation
+ pFlags |= aiProcess_ValidateDataStructure;
+ }
+#else
+ if (pimpl->bExtraVerbose) {
+ ASSIMP_LOG_WARN("Not a debug build, ignoring extra verbose setting");
+ }
+#endif // ! DEBUG
+
+ std::unique_ptr<Profiler> profiler(GetPropertyInteger(AI_CONFIG_GLOB_MEASURE_TIME,0)?new Profiler():NULL);
+ for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
+
+ BaseProcess* process = pimpl->mPostProcessingSteps[a];
+ pimpl->mProgressHandler->UpdatePostProcess(static_cast<int>(a), static_cast<int>(pimpl->mPostProcessingSteps.size()) );
+ if( process->IsActive( pFlags)) {
+
+ if (profiler) {
+ profiler->BeginRegion("postprocess");
+ }
+
+ process->ExecuteOnScene ( this );
+
+ if (profiler) {
+ profiler->EndRegion("postprocess");
+ }
+ }
+ if( !pimpl->mScene) {
+ break;
+ }
+#ifdef ASSIMP_BUILD_DEBUG
+
+#ifdef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
+ continue;
+#endif // no validation
+
+ // If the extra verbose mode is active, execute the ValidateDataStructureStep again - after each step
+ if (pimpl->bExtraVerbose) {
+ ASSIMP_LOG_DEBUG("Verbose Import: re-validating data structures");
+
+ ValidateDSProcess ds;
+ ds.ExecuteOnScene (this);
+ if( !pimpl->mScene) {
+ ASSIMP_LOG_ERROR("Verbose Import: failed to re-validate data structures");
+ break;
+ }
+ }
+#endif // ! DEBUG
+ }
+ pimpl->mProgressHandler->UpdatePostProcess( static_cast<int>(pimpl->mPostProcessingSteps.size()),
+ static_cast<int>(pimpl->mPostProcessingSteps.size()) );
+
+ // update private scene flags
+ if( pimpl->mScene )
+ ScenePriv(pimpl->mScene)->mPPStepsApplied |= pFlags;
+
+ // clear any data allocated by post-process steps
+ pimpl->mPPShared->Clean();
+ ASSIMP_LOG_INFO("Leaving post processing pipeline");
+
+ ASSIMP_END_EXCEPTION_REGION(const aiScene*);
+ return pimpl->mScene;
+}
+
+// ------------------------------------------------------------------------------------------------
+const aiScene* Importer::ApplyCustomizedPostProcessing( BaseProcess *rootProcess, bool requestValidation ) {
+ ASSIMP_BEGIN_EXCEPTION_REGION();
+
+ // Return immediately if no scene is active
+ if ( NULL == pimpl->mScene ) {
+ return NULL;
+ }
+
+ // If no flags are given, return the current scene with no further action
+ if ( NULL == rootProcess ) {
+ return pimpl->mScene;
+ }
+
+ // In debug builds: run basic flag validation
+ ASSIMP_LOG_INFO( "Entering customized post processing pipeline" );
+
+#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
+ // The ValidateDS process plays an exceptional role. It isn't contained in the global
+ // list of post-processing steps, so we need to call it manually.
+ if ( requestValidation )
+ {
+ ValidateDSProcess ds;
+ ds.ExecuteOnScene( this );
+ if ( !pimpl->mScene ) {
+ return NULL;
+ }
+ }
+#endif // no validation
+#ifdef ASSIMP_BUILD_DEBUG
+ if ( pimpl->bExtraVerbose )
+ {
+#ifdef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
+ ASSIMP_LOG_ERROR( "Verbose Import is not available due to build settings" );
+#endif // no validation
+ }
+#else
+ if ( pimpl->bExtraVerbose ) {
+ ASSIMP_LOG_WARN( "Not a debug build, ignoring extra verbose setting" );
+ }
+#endif // ! DEBUG
+
+ std::unique_ptr<Profiler> profiler( GetPropertyInteger( AI_CONFIG_GLOB_MEASURE_TIME, 0 ) ? new Profiler() : NULL );
+
+ if ( profiler ) {
+ profiler->BeginRegion( "postprocess" );
+ }
+
+ rootProcess->ExecuteOnScene( this );
+
+ if ( profiler ) {
+ profiler->EndRegion( "postprocess" );
+ }
+
+ // If the extra verbose mode is active, execute the ValidateDataStructureStep again - after each step
+ if ( pimpl->bExtraVerbose || requestValidation ) {
+ ASSIMP_LOG_DEBUG( "Verbose Import: revalidating data structures" );
+
+ ValidateDSProcess ds;
+ ds.ExecuteOnScene( this );
+ if ( !pimpl->mScene ) {
+ ASSIMP_LOG_ERROR( "Verbose Import: failed to revalidate data structures" );
+ }
+ }
+
+ // clear any data allocated by post-process steps
+ pimpl->mPPShared->Clean();
+ ASSIMP_LOG_INFO( "Leaving customized post processing pipeline" );
+
+ ASSIMP_END_EXCEPTION_REGION( const aiScene* );
+
+ return pimpl->mScene;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Helper function to check whether an extension is supported by ASSIMP
+bool Importer::IsExtensionSupported(const char* szExtension) const
+{
+ return nullptr != GetImporter(szExtension);
+}
+
+// ------------------------------------------------------------------------------------------------
+size_t Importer::GetImporterCount() const
+{
+ return pimpl->mImporter.size();
+}
+
+// ------------------------------------------------------------------------------------------------
+const aiImporterDesc* Importer::GetImporterInfo(size_t index) const
+{
+ if (index >= pimpl->mImporter.size()) {
+ return NULL;
+ }
+ return pimpl->mImporter[index]->GetInfo();
+}
+
+
+// ------------------------------------------------------------------------------------------------
+BaseImporter* Importer::GetImporter (size_t index) const
+{
+ if (index >= pimpl->mImporter.size()) {
+ return NULL;
+ }
+ return pimpl->mImporter[index];
+}
+
+// ------------------------------------------------------------------------------------------------
+// Find a loader plugin for a given file extension
+BaseImporter* Importer::GetImporter (const char* szExtension) const
+{
+ return GetImporter(GetImporterIndex(szExtension));
+}
+
+// ------------------------------------------------------------------------------------------------
+// Find a loader plugin for a given file extension
+size_t Importer::GetImporterIndex (const char* szExtension) const {
+ ai_assert(nullptr != szExtension);
+
+ ASSIMP_BEGIN_EXCEPTION_REGION();
+
+ // skip over wildcard and dot characters at string head --
+ for ( ; *szExtension == '*' || *szExtension == '.'; ++szExtension );
+
+ std::string ext(szExtension);
+ if (ext.empty()) {
+ return static_cast<size_t>(-1);
+ }
+ std::transform( ext.begin(), ext.end(), ext.begin(), ToLower<char> );
+
+ std::set<std::string> str;
+ for (std::vector<BaseImporter*>::const_iterator i = pimpl->mImporter.begin();i != pimpl->mImporter.end();++i) {
+ str.clear();
+
+ (*i)->GetExtensionList(str);
+ for (std::set<std::string>::const_iterator it = str.begin(); it != str.end(); ++it) {
+ if (ext == *it) {
+ return std::distance(static_cast< std::vector<BaseImporter*>::const_iterator >(pimpl->mImporter.begin()), i);
+ }
+ }
+ }
+ ASSIMP_END_EXCEPTION_REGION(size_t);
+ return static_cast<size_t>(-1);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Helper function to build a list of all file extensions supported by ASSIMP
+void Importer::GetExtensionList(aiString& szOut) const
+{
+ ASSIMP_BEGIN_EXCEPTION_REGION();
+ std::set<std::string> str;
+ for (std::vector<BaseImporter*>::const_iterator i = pimpl->mImporter.begin();i != pimpl->mImporter.end();++i) {
+ (*i)->GetExtensionList(str);
+ }
+
+ // List can be empty
+ if( !str.empty() ) {
+ for (std::set<std::string>::const_iterator it = str.begin();; ) {
+ szOut.Append("*.");
+ szOut.Append((*it).c_str());
+
+ if (++it == str.end()) {
+ break;
+ }
+ szOut.Append(";");
+ }
+ }
+ ASSIMP_END_EXCEPTION_REGION(void);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Set a configuration property
+bool Importer::SetPropertyInteger(const char* szName, int iValue)
+{
+ bool existing;
+ ASSIMP_BEGIN_EXCEPTION_REGION();
+ existing = SetGenericProperty<int>(pimpl->mIntProperties, szName,iValue);
+ ASSIMP_END_EXCEPTION_REGION(bool);
+ return existing;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Set a configuration property
+bool Importer::SetPropertyFloat(const char* szName, ai_real iValue)
+{
+ bool existing;
+ ASSIMP_BEGIN_EXCEPTION_REGION();
+ existing = SetGenericProperty<ai_real>(pimpl->mFloatProperties, szName,iValue);
+ ASSIMP_END_EXCEPTION_REGION(bool);
+ return existing;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Set a configuration property
+bool Importer::SetPropertyString(const char* szName, const std::string& value)
+{
+ bool existing;
+ ASSIMP_BEGIN_EXCEPTION_REGION();
+ existing = SetGenericProperty<std::string>(pimpl->mStringProperties, szName,value);
+ ASSIMP_END_EXCEPTION_REGION(bool);
+ return existing;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Set a configuration property
+bool Importer::SetPropertyMatrix(const char* szName, const aiMatrix4x4& value)
+{
+ bool existing;
+ ASSIMP_BEGIN_EXCEPTION_REGION();
+ existing = SetGenericProperty<aiMatrix4x4>(pimpl->mMatrixProperties, szName,value);
+ ASSIMP_END_EXCEPTION_REGION(bool);
+ return existing;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Get a configuration property
+int Importer::GetPropertyInteger(const char* szName,
+ int iErrorReturn /*= 0xffffffff*/) const
+{
+ return GetGenericProperty<int>(pimpl->mIntProperties,szName,iErrorReturn);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Get a configuration property
+ai_real Importer::GetPropertyFloat(const char* szName,
+ ai_real iErrorReturn /*= 10e10*/) const
+{
+ return GetGenericProperty<ai_real>(pimpl->mFloatProperties,szName,iErrorReturn);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Get a configuration property
+const std::string Importer::GetPropertyString(const char* szName,
+ const std::string& iErrorReturn /*= ""*/) const
+{
+ return GetGenericProperty<std::string>(pimpl->mStringProperties,szName,iErrorReturn);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Get a configuration property
+const aiMatrix4x4 Importer::GetPropertyMatrix(const char* szName,
+ const aiMatrix4x4& iErrorReturn /*= aiMatrix4x4()*/) const
+{
+ return GetGenericProperty<aiMatrix4x4>(pimpl->mMatrixProperties,szName,iErrorReturn);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Get the memory requirements of a single node
+inline void AddNodeWeight(unsigned int& iScene,const aiNode* pcNode)
+{
+ iScene += sizeof(aiNode);
+ iScene += sizeof(unsigned int) * pcNode->mNumMeshes;
+ iScene += sizeof(void*) * pcNode->mNumChildren;
+
+ for (unsigned int i = 0; i < pcNode->mNumChildren;++i) {
+ AddNodeWeight(iScene,pcNode->mChildren[i]);
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Get the memory requirements of the scene
+void Importer::GetMemoryRequirements(aiMemoryInfo& in) const
+{
+ in = aiMemoryInfo();
+ aiScene* mScene = pimpl->mScene;
+
+ // return if we have no scene loaded
+ if (!pimpl->mScene)
+ return;
+
+
+ in.total = sizeof(aiScene);
+
+ // add all meshes
+ for (unsigned int i = 0; i < mScene->mNumMeshes;++i)
+ {
+ in.meshes += sizeof(aiMesh);
+ if (mScene->mMeshes[i]->HasPositions()) {
+ in.meshes += sizeof(aiVector3D) * mScene->mMeshes[i]->mNumVertices;
+ }
+
+ if (mScene->mMeshes[i]->HasNormals()) {
+ in.meshes += sizeof(aiVector3D) * mScene->mMeshes[i]->mNumVertices;
+ }
+
+ if (mScene->mMeshes[i]->HasTangentsAndBitangents()) {
+ in.meshes += sizeof(aiVector3D) * mScene->mMeshes[i]->mNumVertices * 2;
+ }
+
+ for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS;++a) {
+ if (mScene->mMeshes[i]->HasVertexColors(a)) {
+ in.meshes += sizeof(aiColor4D) * mScene->mMeshes[i]->mNumVertices;
+ }
+ else break;
+ }
+ for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS;++a) {
+ if (mScene->mMeshes[i]->HasTextureCoords(a)) {
+ in.meshes += sizeof(aiVector3D) * mScene->mMeshes[i]->mNumVertices;
+ }
+ else break;
+ }
+ if (mScene->mMeshes[i]->HasBones()) {
+ in.meshes += sizeof(void*) * mScene->mMeshes[i]->mNumBones;
+ for (unsigned int p = 0; p < mScene->mMeshes[i]->mNumBones;++p) {
+ in.meshes += sizeof(aiBone);
+ in.meshes += mScene->mMeshes[i]->mBones[p]->mNumWeights * sizeof(aiVertexWeight);
+ }
+ }
+ in.meshes += (sizeof(aiFace) + 3 * sizeof(unsigned int))*mScene->mMeshes[i]->mNumFaces;
+ }
+ in.total += in.meshes;
+
+ // add all embedded textures
+ for (unsigned int i = 0; i < mScene->mNumTextures;++i) {
+ const aiTexture* pc = mScene->mTextures[i];
+ in.textures += sizeof(aiTexture);
+ if (pc->mHeight) {
+ in.textures += 4 * pc->mHeight * pc->mWidth;
+ }
+ else in.textures += pc->mWidth;
+ }
+ in.total += in.textures;
+
+ // add all animations
+ for (unsigned int i = 0; i < mScene->mNumAnimations;++i) {
+ const aiAnimation* pc = mScene->mAnimations[i];
+ in.animations += sizeof(aiAnimation);
+
+ // add all bone anims
+ for (unsigned int a = 0; a < pc->mNumChannels; ++a) {
+ const aiNodeAnim* pc2 = pc->mChannels[i];
+ in.animations += sizeof(aiNodeAnim);
+ in.animations += pc2->mNumPositionKeys * sizeof(aiVectorKey);
+ in.animations += pc2->mNumScalingKeys * sizeof(aiVectorKey);
+ in.animations += pc2->mNumRotationKeys * sizeof(aiQuatKey);
+ }
+ }
+ in.total += in.animations;
+
+ // add all cameras and all lights
+ in.total += in.cameras = sizeof(aiCamera) * mScene->mNumCameras;
+ in.total += in.lights = sizeof(aiLight) * mScene->mNumLights;
+
+ // add all nodes
+ AddNodeWeight(in.nodes,mScene->mRootNode);
+ in.total += in.nodes;
+
+ // add all materials
+ for (unsigned int i = 0; i < mScene->mNumMaterials;++i) {
+ const aiMaterial* pc = mScene->mMaterials[i];
+ in.materials += sizeof(aiMaterial);
+ in.materials += pc->mNumAllocated * sizeof(void*);
+
+ for (unsigned int a = 0; a < pc->mNumProperties;++a) {
+ in.materials += pc->mProperties[a]->mDataLength;
+ }
+ }
+ in.total += in.materials;
+}
diff --git a/thirdparty/assimp/code/Importer.h b/thirdparty/assimp/code/Importer.h
new file mode 100644
index 0000000000..a439d99c2f
--- /dev/null
+++ b/thirdparty/assimp/code/Importer.h
@@ -0,0 +1,247 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file Importer.h mostly internal stuff for use by #Assimp::Importer */
+#pragma once
+#ifndef INCLUDED_AI_IMPORTER_H
+#define INCLUDED_AI_IMPORTER_H
+
+#include <map>
+#include <vector>
+#include <string>
+#include <assimp/matrix4x4.h>
+
+struct aiScene;
+
+namespace Assimp {
+ class ProgressHandler;
+ class IOSystem;
+ class BaseImporter;
+ class BaseProcess;
+ class SharedPostProcessInfo;
+
+
+//! @cond never
+// ---------------------------------------------------------------------------
+/** @brief Internal PIMPL implementation for Assimp::Importer
+ *
+ * Using this idiom here allows us to drop the dependency from
+ * std::vector and std::map in the public headers. Furthermore we are dropping
+ * any STL interface problems caused by mismatching STL settings. All
+ * size calculation are now done by us, not the app heap. */
+class ImporterPimpl {
+public:
+ // Data type to store the key hash
+ typedef unsigned int KeyType;
+
+ // typedefs for our four configuration maps.
+ // We don't need more, so there is no need for a generic solution
+ typedef std::map<KeyType, int> IntPropertyMap;
+ typedef std::map<KeyType, ai_real> FloatPropertyMap;
+ typedef std::map<KeyType, std::string> StringPropertyMap;
+ typedef std::map<KeyType, aiMatrix4x4> MatrixPropertyMap;
+
+ /** IO handler to use for all file accesses. */
+ IOSystem* mIOHandler;
+ bool mIsDefaultHandler;
+
+ /** Progress handler for feedback. */
+ ProgressHandler* mProgressHandler;
+ bool mIsDefaultProgressHandler;
+
+ /** Format-specific importer worker objects - one for each format we can read.*/
+ std::vector< BaseImporter* > mImporter;
+
+ /** Post processing steps we can apply at the imported data. */
+ std::vector< BaseProcess* > mPostProcessingSteps;
+
+ /** The imported data, if ReadFile() was successful, NULL otherwise. */
+ aiScene* mScene;
+
+ /** The error description, if there was one. */
+ std::string mErrorString;
+
+ /** List of integer properties */
+ IntPropertyMap mIntProperties;
+
+ /** List of floating-point properties */
+ FloatPropertyMap mFloatProperties;
+
+ /** List of string properties */
+ StringPropertyMap mStringProperties;
+
+ /** List of Matrix properties */
+ MatrixPropertyMap mMatrixProperties;
+
+ /** Used for testing - extra verbose mode causes the ValidateDataStructure-Step
+ * to be executed before and after every single post-process step */
+ bool bExtraVerbose;
+
+ /** Used by post-process steps to share data */
+ SharedPostProcessInfo* mPPShared;
+
+ /// The default class constructor.
+ ImporterPimpl() AI_NO_EXCEPT;
+};
+
+inline
+ImporterPimpl::ImporterPimpl() AI_NO_EXCEPT
+: mIOHandler( nullptr )
+, mIsDefaultHandler( false )
+, mProgressHandler( nullptr )
+, mIsDefaultProgressHandler( false )
+, mImporter()
+, mPostProcessingSteps()
+, mScene( nullptr )
+, mErrorString()
+, mIntProperties()
+, mFloatProperties()
+, mStringProperties()
+, mMatrixProperties()
+, bExtraVerbose( false )
+, mPPShared( nullptr ) {
+ // empty
+}
+//! @endcond
+
+
+struct BatchData;
+
+// ---------------------------------------------------------------------------
+/** FOR IMPORTER PLUGINS ONLY: A helper class to the pleasure of importers
+ * that need to load many external meshes recursively.
+ *
+ * The class uses several threads to load these meshes (or at least it
+ * could, this has not yet been implemented at the moment).
+ *
+ * @note The class may not be used by more than one thread*/
+class ASSIMP_API BatchLoader
+{
+ // friend of Importer
+
+public:
+ //! @cond never
+ // -------------------------------------------------------------------
+ /** Wraps a full list of configuration properties for an importer.
+ * Properties can be set using SetGenericProperty */
+ struct PropertyMap
+ {
+ ImporterPimpl::IntPropertyMap ints;
+ ImporterPimpl::FloatPropertyMap floats;
+ ImporterPimpl::StringPropertyMap strings;
+ ImporterPimpl::MatrixPropertyMap matrices;
+
+ bool operator == (const PropertyMap& prop) const {
+ // fixme: really isocpp? gcc complains
+ return ints == prop.ints && floats == prop.floats && strings == prop.strings && matrices == prop.matrices;
+ }
+
+ bool empty () const {
+ return ints.empty() && floats.empty() && strings.empty() && matrices.empty();
+ }
+ };
+ //! @endcond
+
+public:
+ // -------------------------------------------------------------------
+ /** Construct a batch loader from a given IO system to be used
+ * to access external files
+ */
+ explicit BatchLoader(IOSystem* pIO, bool validate = false );
+
+ // -------------------------------------------------------------------
+ /** The class destructor.
+ */
+ ~BatchLoader();
+
+ // -------------------------------------------------------------------
+ /** Sets the validation step. True for enable validation during postprocess.
+ * @param enable True for validation.
+ */
+ void setValidation( bool enabled );
+
+ // -------------------------------------------------------------------
+ /** Returns the current validation step.
+ * @return The current validation step.
+ */
+ bool getValidation() const;
+
+ // -------------------------------------------------------------------
+ /** Add a new file to the list of files to be loaded.
+ * @param file File to be loaded
+ * @param steps Post-processing steps to be executed on the file
+ * @param map Optional configuration properties
+ * @return 'Load request channel' - an unique ID that can later
+ * be used to access the imported file data.
+ * @see GetImport */
+ unsigned int AddLoadRequest (
+ const std::string& file,
+ unsigned int steps = 0,
+ const PropertyMap* map = NULL
+ );
+
+ // -------------------------------------------------------------------
+ /** Get an imported scene.
+ * This polls the import from the internal request list.
+ * If an import is requested several times, this function
+ * can be called several times, too.
+ *
+ * @param which LRWC returned by AddLoadRequest().
+ * @return NULL if there is no scene with this file name
+ * in the queue of the scene hasn't been loaded yet. */
+ aiScene* GetImport(
+ unsigned int which
+ );
+
+ // -------------------------------------------------------------------
+ /** Waits until all scenes have been loaded. This returns
+ * immediately if no scenes are queued.*/
+ void LoadAll();
+
+private:
+ // No need to have that in the public API ...
+ BatchData *m_data;
+};
+
+} // Namespace Assimp
+
+#endif // INCLUDED_AI_IMPORTER_H
diff --git a/thirdparty/assimp/code/ImporterRegistry.cpp b/thirdparty/assimp/code/ImporterRegistry.cpp
new file mode 100644
index 0000000000..747815fa6f
--- /dev/null
+++ b/thirdparty/assimp/code/ImporterRegistry.cpp
@@ -0,0 +1,371 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file ImporterRegistry.cpp
+
+Central registry for all importers available. Do not edit this file
+directly (unless you are adding new loaders), instead use the
+corresponding preprocessor flag to selectively disable formats.
+*/
+
+#include <vector>
+#include <assimp/BaseImporter.h>
+
+// ------------------------------------------------------------------------------------------------
+// Importers
+// (include_new_importers_here)
+// ------------------------------------------------------------------------------------------------
+#ifndef ASSIMP_BUILD_NO_X_IMPORTER
+# include "XFileImporter.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_AMF_IMPORTER
+# include "AMFImporter.hpp"
+#endif
+#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
+# include "3DSLoader.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_MD3_IMPORTER
+# include "MD3Loader.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_MDL_IMPORTER
+# include "MDLLoader.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_MD2_IMPORTER
+# include "MD2Loader.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_PLY_IMPORTER
+# include "PlyLoader.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_ASE_IMPORTER
+# include "ASELoader.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_OBJ_IMPORTER
+# include "ObjFileImporter.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_HMP_IMPORTER
+# include "HMPLoader.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_SMD_IMPORTER
+# include "SMDLoader.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_MDC_IMPORTER
+# include "MDCLoader.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_MD5_IMPORTER
+# include "MD5Loader.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_STL_IMPORTER
+# include "STLLoader.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_LWO_IMPORTER
+# include "LWOLoader.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_DXF_IMPORTER
+# include "DXFLoader.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_NFF_IMPORTER
+# include "NFFLoader.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_RAW_IMPORTER
+# include "RawLoader.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_SIB_IMPORTER
+# include "SIBImporter.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_OFF_IMPORTER
+# include "OFFLoader.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_AC_IMPORTER
+# include "ACLoader.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_BVH_IMPORTER
+# include "BVHLoader.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_IRRMESH_IMPORTER
+# include "IRRMeshLoader.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_IRR_IMPORTER
+# include "IRRLoader.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_Q3D_IMPORTER
+# include "Q3DLoader.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_B3D_IMPORTER
+# include "B3DImporter.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_COLLADA_IMPORTER
+# include "ColladaLoader.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_TERRAGEN_IMPORTER
+# include "TerragenLoader.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_CSM_IMPORTER
+# include "CSMLoader.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_3D_IMPORTER
+# include "UnrealLoader.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_LWS_IMPORTER
+# include "LWSLoader.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
+# include "OgreImporter.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_OPENGEX_IMPORTER
+# include "OpenGEXImporter.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_MS3D_IMPORTER
+# include "MS3DLoader.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_COB_IMPORTER
+# include "COBLoader.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
+# include "BlenderLoader.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER
+# include "Q3BSPFileImporter.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_NDO_IMPORTER
+# include "NDOLoader.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
+# include "Importer/IFC/IFCLoader.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_XGL_IMPORTER
+# include "XGLLoader.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
+# include "FBXImporter.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER
+# include "AssbinLoader.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER
+# include "glTFImporter.h"
+# include "glTF2Importer.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_C4D_IMPORTER
+# include "C4DImporter.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_3MF_IMPORTER
+# include "D3MFImporter.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
+# include "X3DImporter.hpp"
+#endif
+#ifndef ASSIMP_BUILD_NO_MMD_IMPORTER
+# include "MMDImporter.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_STEP_IMPORTER
+# include "Importer/StepFile/StepFileImporter.h"
+#endif
+
+namespace Assimp {
+
+// ------------------------------------------------------------------------------------------------
+void GetImporterInstanceList(std::vector< BaseImporter* >& out)
+{
+ // ----------------------------------------------------------------------------
+ // Add an instance of each worker class here
+ // (register_new_importers_here)
+ // ----------------------------------------------------------------------------
+ out.reserve(64);
+#if (!defined ASSIMP_BUILD_NO_X_IMPORTER)
+ out.push_back( new XFileImporter());
+#endif
+#if (!defined ASSIMP_BUILD_NO_OBJ_IMPORTER)
+ out.push_back( new ObjFileImporter());
+#endif
+#ifndef ASSIMP_BUILD_NO_AMF_IMPORTER
+ out.push_back( new AMFImporter() );
+#endif
+#if (!defined ASSIMP_BUILD_NO_3DS_IMPORTER)
+ out.push_back( new Discreet3DSImporter());
+#endif
+#if (!defined ASSIMP_BUILD_NO_MD3_IMPORTER)
+ out.push_back( new MD3Importer());
+#endif
+#if (!defined ASSIMP_BUILD_NO_MD2_IMPORTER)
+ out.push_back( new MD2Importer());
+#endif
+#if (!defined ASSIMP_BUILD_NO_PLY_IMPORTER)
+ out.push_back( new PLYImporter());
+#endif
+#if (!defined ASSIMP_BUILD_NO_MDL_IMPORTER)
+ out.push_back( new MDLImporter());
+#endif
+#if (!defined ASSIMP_BUILD_NO_ASE_IMPORTER)
+ #if (!defined ASSIMP_BUILD_NO_3DS_IMPORTER)
+ out.push_back( new ASEImporter());
+# endif
+#endif
+#if (!defined ASSIMP_BUILD_NO_HMP_IMPORTER)
+ out.push_back( new HMPImporter());
+#endif
+#if (!defined ASSIMP_BUILD_NO_SMD_IMPORTER)
+ out.push_back( new SMDImporter());
+#endif
+#if (!defined ASSIMP_BUILD_NO_MDC_IMPORTER)
+ out.push_back( new MDCImporter());
+#endif
+#if (!defined ASSIMP_BUILD_NO_MD5_IMPORTER)
+ out.push_back( new MD5Importer());
+#endif
+#if (!defined ASSIMP_BUILD_NO_STL_IMPORTER)
+ out.push_back( new STLImporter());
+#endif
+#if (!defined ASSIMP_BUILD_NO_LWO_IMPORTER)
+ out.push_back( new LWOImporter());
+#endif
+#if (!defined ASSIMP_BUILD_NO_DXF_IMPORTER)
+ out.push_back( new DXFImporter());
+#endif
+#if (!defined ASSIMP_BUILD_NO_NFF_IMPORTER)
+ out.push_back( new NFFImporter());
+#endif
+#if (!defined ASSIMP_BUILD_NO_RAW_IMPORTER)
+ out.push_back( new RAWImporter());
+#endif
+#if (!defined ASSIMP_BUILD_NO_SIB_IMPORTER)
+ out.push_back( new SIBImporter());
+#endif
+#if (!defined ASSIMP_BUILD_NO_OFF_IMPORTER)
+ out.push_back( new OFFImporter());
+#endif
+#if (!defined ASSIMP_BUILD_NO_AC_IMPORTER)
+ out.push_back( new AC3DImporter());
+#endif
+#if (!defined ASSIMP_BUILD_NO_BVH_IMPORTER)
+ out.push_back( new BVHLoader());
+#endif
+#if (!defined ASSIMP_BUILD_NO_IRRMESH_IMPORTER)
+ out.push_back( new IRRMeshImporter());
+#endif
+#if (!defined ASSIMP_BUILD_NO_IRR_IMPORTER)
+ out.push_back( new IRRImporter());
+#endif
+#if (!defined ASSIMP_BUILD_NO_Q3D_IMPORTER)
+ out.push_back( new Q3DImporter());
+#endif
+#if (!defined ASSIMP_BUILD_NO_B3D_IMPORTER)
+ out.push_back( new B3DImporter());
+#endif
+#if (!defined ASSIMP_BUILD_NO_COLLADA_IMPORTER)
+ out.push_back( new ColladaLoader());
+#endif
+#if (!defined ASSIMP_BUILD_NO_TERRAGEN_IMPORTER)
+ out.push_back( new TerragenImporter());
+#endif
+#if (!defined ASSIMP_BUILD_NO_CSM_IMPORTER)
+ out.push_back( new CSMImporter());
+#endif
+#if (!defined ASSIMP_BUILD_NO_3D_IMPORTER)
+ out.push_back( new UnrealImporter());
+#endif
+#if (!defined ASSIMP_BUILD_NO_LWS_IMPORTER)
+ out.push_back( new LWSImporter());
+#endif
+#if (!defined ASSIMP_BUILD_NO_OGRE_IMPORTER)
+ out.push_back( new Ogre::OgreImporter());
+#endif
+#if (!defined ASSIMP_BUILD_NO_OPENGEX_IMPORTER )
+ out.push_back( new OpenGEX::OpenGEXImporter() );
+#endif
+#if (!defined ASSIMP_BUILD_NO_MS3D_IMPORTER)
+ out.push_back( new MS3DImporter());
+#endif
+#if (!defined ASSIMP_BUILD_NO_COB_IMPORTER)
+ out.push_back( new COBImporter());
+#endif
+#if (!defined ASSIMP_BUILD_NO_BLEND_IMPORTER)
+ out.push_back( new BlenderImporter());
+#endif
+#if (!defined ASSIMP_BUILD_NO_Q3BSP_IMPORTER)
+ out.push_back( new Q3BSPFileImporter() );
+#endif
+#if (!defined ASSIMP_BUILD_NO_NDO_IMPORTER)
+ out.push_back( new NDOImporter() );
+#endif
+#if (!defined ASSIMP_BUILD_NO_IFC_IMPORTER)
+ out.push_back( new IFCImporter() );
+#endif
+#if ( !defined ASSIMP_BUILD_NO_XGL_IMPORTER )
+ out.push_back( new XGLImporter() );
+#endif
+#if ( !defined ASSIMP_BUILD_NO_FBX_IMPORTER )
+ out.push_back( new FBXImporter() );
+#endif
+#if ( !defined ASSIMP_BUILD_NO_ASSBIN_IMPORTER )
+ out.push_back( new AssbinImporter() );
+#endif
+#if ( !defined ASSIMP_BUILD_NO_GLTF_IMPORTER )
+ out.push_back( new glTFImporter() );
+ out.push_back( new glTF2Importer() );
+#endif
+#if ( !defined ASSIMP_BUILD_NO_C4D_IMPORTER )
+ out.push_back( new C4DImporter() );
+#endif
+#if ( !defined ASSIMP_BUILD_NO_3MF_IMPORTER )
+ out.push_back( new D3MFImporter() );
+#endif
+#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
+ out.push_back( new X3DImporter() );
+#endif
+#ifndef ASSIMP_BUILD_NO_MMD_IMPORTER
+ out.push_back( new MMDImporter() );
+#endif
+#ifndef ASSIMP_BUILD_NO_STEP_IMPORTER
+ out.push_back(new StepFile::StepFileImporter());
+#endif
+}
+
+/** will delete all registered importers. */
+void DeleteImporterInstanceList(std::vector< BaseImporter* >& deleteList){
+ for(size_t i= 0; i<deleteList.size();++i){
+ delete deleteList[i];
+ deleteList[i]=NULL;
+ }//for
+}
+
+} // namespace Assimp
diff --git a/thirdparty/assimp/code/ImproveCacheLocality.cpp b/thirdparty/assimp/code/ImproveCacheLocality.cpp
new file mode 100644
index 0000000000..ace9d95ff8
--- /dev/null
+++ b/thirdparty/assimp/code/ImproveCacheLocality.cpp
@@ -0,0 +1,386 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file Implementation of the post processing step to improve the cache locality of a mesh.
+ * <br>
+ * The algorithm is roughly basing on this paper:
+ * http://www.cs.princeton.edu/gfx/pubs/Sander_2007_%3ETR/tipsy.pdf
+ * .. although overdraw rduction isn't implemented yet ...
+ */
+
+
+
+// internal headers
+#include "ImproveCacheLocality.h"
+#include "VertexTriangleAdjacency.h"
+#include <assimp/StringUtils.h>
+#include <assimp/postprocess.h>
+#include <assimp/scene.h>
+#include <assimp/DefaultLogger.hpp>
+#include <stdio.h>
+#include <stack>
+
+using namespace Assimp;
+
+// ------------------------------------------------------------------------------------------------
+// Constructor to be privately used by Importer
+ImproveCacheLocalityProcess::ImproveCacheLocalityProcess() {
+ configCacheDepth = PP_ICL_PTCACHE_SIZE;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor, private as well
+ImproveCacheLocalityProcess::~ImproveCacheLocalityProcess()
+{
+ // nothing to do here
+}
+
+// ------------------------------------------------------------------------------------------------
+// Returns whether the processing step is present in the given flag field.
+bool ImproveCacheLocalityProcess::IsActive( unsigned int pFlags) const
+{
+ return (pFlags & aiProcess_ImproveCacheLocality) != 0;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Setup configuration
+void ImproveCacheLocalityProcess::SetupProperties(const Importer* pImp)
+{
+ // AI_CONFIG_PP_ICL_PTCACHE_SIZE controls the target cache size for the optimizer
+ configCacheDepth = pImp->GetPropertyInteger(AI_CONFIG_PP_ICL_PTCACHE_SIZE,PP_ICL_PTCACHE_SIZE);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+void ImproveCacheLocalityProcess::Execute( aiScene* pScene)
+{
+ if (!pScene->mNumMeshes) {
+ ASSIMP_LOG_DEBUG("ImproveCacheLocalityProcess skipped; there are no meshes");
+ return;
+ }
+
+ ASSIMP_LOG_DEBUG("ImproveCacheLocalityProcess begin");
+
+ float out = 0.f;
+ unsigned int numf = 0, numm = 0;
+ for( unsigned int a = 0; a < pScene->mNumMeshes; a++){
+ const float res = ProcessMesh( pScene->mMeshes[a],a);
+ if (res) {
+ numf += pScene->mMeshes[a]->mNumFaces;
+ out += res;
+ ++numm;
+ }
+ }
+ if (!DefaultLogger::isNullLogger()) {
+ if (numf > 0) {
+ ASSIMP_LOG_INFO_F("Cache relevant are ", numm, " meshes (", numf, " faces). Average output ACMR is ", out / numf);
+ }
+ ASSIMP_LOG_DEBUG("ImproveCacheLocalityProcess finished. ");
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Improves the cache coherency of a specific mesh
+float ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshNum)
+{
+ // TODO: rewrite this to use std::vector or boost::shared_array
+ ai_assert(NULL != pMesh);
+
+ // Check whether the input data is valid
+ // - there must be vertices and faces
+ // - all faces must be triangulated or we can't operate on them
+ if (!pMesh->HasFaces() || !pMesh->HasPositions())
+ return 0.f;
+
+ if (pMesh->mPrimitiveTypes != aiPrimitiveType_TRIANGLE) {
+ ASSIMP_LOG_ERROR("This algorithm works on triangle meshes only");
+ return 0.f;
+ }
+
+ if(pMesh->mNumVertices <= configCacheDepth) {
+ return 0.f;
+ }
+
+ float fACMR = 3.f;
+ const aiFace* const pcEnd = pMesh->mFaces+pMesh->mNumFaces;
+
+ // Input ACMR is for logging purposes only
+ if (!DefaultLogger::isNullLogger()) {
+
+ unsigned int* piFIFOStack = new unsigned int[configCacheDepth];
+ memset(piFIFOStack,0xff,configCacheDepth*sizeof(unsigned int));
+ unsigned int* piCur = piFIFOStack;
+ const unsigned int* const piCurEnd = piFIFOStack + configCacheDepth;
+
+ // count the number of cache misses
+ unsigned int iCacheMisses = 0;
+ for (const aiFace* pcFace = pMesh->mFaces;pcFace != pcEnd;++pcFace) {
+
+ for (unsigned int qq = 0; qq < 3;++qq) {
+ bool bInCache = false;
+
+ for (unsigned int* pp = piFIFOStack;pp < piCurEnd;++pp) {
+ if (*pp == pcFace->mIndices[qq]) {
+ // the vertex is in cache
+ bInCache = true;
+ break;
+ }
+ }
+ if (!bInCache) {
+ ++iCacheMisses;
+ if (piCurEnd == piCur) {
+ piCur = piFIFOStack;
+ }
+ *piCur++ = pcFace->mIndices[qq];
+ }
+ }
+ }
+ delete[] piFIFOStack;
+ fACMR = (float)iCacheMisses / pMesh->mNumFaces;
+ if (3.0 == fACMR) {
+ char szBuff[128]; // should be sufficiently large in every case
+
+ // the JoinIdenticalVertices process has not been executed on this
+ // mesh, otherwise this value would normally be at least minimally
+ // smaller than 3.0 ...
+ ai_snprintf(szBuff,128,"Mesh %u: Not suitable for vcache optimization",meshNum);
+ ASSIMP_LOG_WARN(szBuff);
+ return 0.f;
+ }
+ }
+
+ // first we need to build a vertex-triangle adjacency list
+ VertexTriangleAdjacency adj(pMesh->mFaces,pMesh->mNumFaces, pMesh->mNumVertices,true);
+
+ // build a list to store per-vertex caching time stamps
+ unsigned int* const piCachingStamps = new unsigned int[pMesh->mNumVertices];
+ memset(piCachingStamps,0x0,pMesh->mNumVertices*sizeof(unsigned int));
+
+ // allocate an empty output index buffer. We store the output indices in one large array.
+ // Since the number of triangles won't change the input faces can be reused. This is how
+ // we save thousands of redundant mini allocations for aiFace::mIndices
+ const unsigned int iIdxCnt = pMesh->mNumFaces*3;
+ unsigned int* const piIBOutput = new unsigned int[iIdxCnt];
+ unsigned int* piCSIter = piIBOutput;
+
+ // allocate the flag array to hold the information
+ // whether a face has already been emitted or not
+ std::vector<bool> abEmitted(pMesh->mNumFaces,false);
+
+ // dead-end vertex index stack
+ std::stack<unsigned int, std::vector<unsigned int> > sDeadEndVStack;
+
+ // create a copy of the piNumTriPtr buffer
+ unsigned int* const piNumTriPtr = adj.mLiveTriangles;
+ const std::vector<unsigned int> piNumTriPtrNoModify(piNumTriPtr, piNumTriPtr + pMesh->mNumVertices);
+
+ // get the largest number of referenced triangles and allocate the "candidate buffer"
+ unsigned int iMaxRefTris = 0; {
+ const unsigned int* piCur = adj.mLiveTriangles;
+ const unsigned int* const piCurEnd = adj.mLiveTriangles+pMesh->mNumVertices;
+ for (;piCur != piCurEnd;++piCur) {
+ iMaxRefTris = std::max(iMaxRefTris,*piCur);
+ }
+ }
+ ai_assert(iMaxRefTris > 0);
+ unsigned int* piCandidates = new unsigned int[iMaxRefTris*3];
+ unsigned int iCacheMisses = 0;
+
+ // ...................................................................................
+ /** PSEUDOCODE for the algorithm
+
+ A = Build-Adjacency(I) Vertex-triangle adjacency
+ L = Get-Triangle-Counts(A) Per-vertex live triangle counts
+ C = Zero(Vertex-Count(I)) Per-vertex caching time stamps
+ D = Empty-Stack() Dead-end vertex stack
+ E = False(Triangle-Count(I)) Per triangle emitted flag
+ O = Empty-Index-Buffer() Empty output buffer
+ f = 0 Arbitrary starting vertex
+ s = k+1, i = 1 Time stamp and cursor
+ while f >= 0 For all valid fanning vertices
+ N = Empty-Set() 1-ring of next candidates
+ for each Triangle t in Neighbors(A, f)
+ if !Emitted(E,t)
+ for each Vertex v in t
+ Append(O,v) Output vertex
+ Push(D,v) Add to dead-end stack
+ Insert(N,v) Register as candidate
+ L[v] = L[v]-1 Decrease live triangle count
+ if s-C[v] > k If not in cache
+ C[v] = s Set time stamp
+ s = s+1 Increment time stamp
+ E[t] = true Flag triangle as emitted
+ Select next fanning vertex
+ f = Get-Next-Vertex(I,i,k,N,C,s,L,D)
+ return O
+ */
+ // ...................................................................................
+
+ int ivdx = 0;
+ int ics = 1;
+ int iStampCnt = configCacheDepth+1;
+ while (ivdx >= 0) {
+
+ unsigned int icnt = piNumTriPtrNoModify[ivdx];
+ unsigned int* piList = adj.GetAdjacentTriangles(ivdx);
+ unsigned int* piCurCandidate = piCandidates;
+
+ // get all triangles in the neighborhood
+ for (unsigned int tri = 0; tri < icnt;++tri) {
+
+ // if they have not yet been emitted, add them to the output IB
+ const unsigned int fidx = *piList++;
+ if (!abEmitted[fidx]) {
+
+ // so iterate through all vertices of the current triangle
+ const aiFace* pcFace = &pMesh->mFaces[ fidx ];
+ unsigned nind = pcFace->mNumIndices;
+ for (unsigned ind = 0; ind < nind; ind++) {
+ unsigned dp = pcFace->mIndices[ind];
+
+ // the current vertex won't have any free triangles after this step
+ if (ivdx != (int)dp) {
+ // append the vertex to the dead-end stack
+ sDeadEndVStack.push(dp);
+
+ // register as candidate for the next step
+ *piCurCandidate++ = dp;
+
+ // decrease the per-vertex triangle counts
+ piNumTriPtr[dp]--;
+ }
+
+ // append the vertex to the output index buffer
+ *piCSIter++ = dp;
+
+ // if the vertex is not yet in cache, set its cache count
+ if (iStampCnt-piCachingStamps[dp] > configCacheDepth) {
+ piCachingStamps[dp] = iStampCnt++;
+ ++iCacheMisses;
+ }
+ }
+ // flag triangle as emitted
+ abEmitted[fidx] = true;
+ }
+ }
+
+ // the vertex has now no living adjacent triangles anymore
+ piNumTriPtr[ivdx] = 0;
+
+ // get next fanning vertex
+ ivdx = -1;
+ int max_priority = -1;
+ for (unsigned int* piCur = piCandidates;piCur != piCurCandidate;++piCur) {
+ const unsigned int dp = *piCur;
+
+ // must have live triangles
+ if (piNumTriPtr[dp] > 0) {
+ int priority = 0;
+
+ // will the vertex be in cache, even after fanning occurs?
+ unsigned int tmp;
+ if ((tmp = iStampCnt-piCachingStamps[dp]) + 2*piNumTriPtr[dp] <= configCacheDepth) {
+ priority = tmp;
+ }
+
+ // keep best candidate
+ if (priority > max_priority) {
+ max_priority = priority;
+ ivdx = dp;
+ }
+ }
+ }
+ // did we reach a dead end?
+ if (-1 == ivdx) {
+ // need to get a non-local vertex for which we have a good chance that it is still
+ // in the cache ...
+ while (!sDeadEndVStack.empty()) {
+ unsigned int iCachedIdx = sDeadEndVStack.top();
+ sDeadEndVStack.pop();
+ if (piNumTriPtr[ iCachedIdx ] > 0) {
+ ivdx = iCachedIdx;
+ break;
+ }
+ }
+
+ if (-1 == ivdx) {
+ // well, there isn't such a vertex. Simply get the next vertex in input order and
+ // hope it is not too bad ...
+ while (ics < (int)pMesh->mNumVertices) {
+ ++ics;
+ if (piNumTriPtr[ics] > 0) {
+ ivdx = ics;
+ break;
+ }
+ }
+ }
+ }
+ }
+ float fACMR2 = 0.0f;
+ if (!DefaultLogger::isNullLogger()) {
+ fACMR2 = (float)iCacheMisses / pMesh->mNumFaces;
+
+ // very intense verbose logging ... prepare for much text if there are many meshes
+ if ( DefaultLogger::get()->getLogSeverity() == Logger::VERBOSE) {
+ ASSIMP_LOG_DEBUG_F("Mesh %u | ACMR in: ", meshNum, " out: ", fACMR, " | ~", fACMR2, ((fACMR - fACMR2) / fACMR) * 100.f);
+ }
+
+ fACMR2 *= pMesh->mNumFaces;
+ }
+ // sort the output index buffer back to the input array
+ piCSIter = piIBOutput;
+ for (aiFace* pcFace = pMesh->mFaces; pcFace != pcEnd;++pcFace) {
+ unsigned nind = pcFace->mNumIndices;
+ unsigned * ind = pcFace->mIndices;
+ if (nind > 0) ind[0] = *piCSIter++;
+ if (nind > 1) ind[1] = *piCSIter++;
+ if (nind > 2) ind[2] = *piCSIter++;
+ }
+
+ // delete temporary storage
+ delete[] piCachingStamps;
+ delete[] piIBOutput;
+ delete[] piCandidates;
+
+ return fACMR2;
+}
diff --git a/thirdparty/assimp/code/ImproveCacheLocality.h b/thirdparty/assimp/code/ImproveCacheLocality.h
new file mode 100644
index 0000000000..1b29ee0d6e
--- /dev/null
+++ b/thirdparty/assimp/code/ImproveCacheLocality.h
@@ -0,0 +1,100 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file Defines a post processing step to reorder faces for
+ better cache locality*/
+#ifndef AI_IMPROVECACHELOCALITY_H_INC
+#define AI_IMPROVECACHELOCALITY_H_INC
+
+#include "BaseProcess.h"
+#include <assimp/types.h>
+
+struct aiMesh;
+
+namespace Assimp
+{
+
+// ---------------------------------------------------------------------------
+/** The ImproveCacheLocalityProcess reorders all faces for improved vertex
+ * cache locality. It tries to arrange all faces to fans and to render
+ * faces which share vertices directly one after the other.
+ *
+ * @note This step expects triagulated input data.
+ */
+class ImproveCacheLocalityProcess : public BaseProcess
+{
+public:
+
+ ImproveCacheLocalityProcess();
+ ~ImproveCacheLocalityProcess();
+
+public:
+
+ // -------------------------------------------------------------------
+ // Check whether the pp step is active
+ bool IsActive( unsigned int pFlags) const;
+
+ // -------------------------------------------------------------------
+ // Executes the pp step on a given scene
+ void Execute( aiScene* pScene);
+
+ // -------------------------------------------------------------------
+ // Configures the pp step
+ void SetupProperties(const Importer* pImp);
+
+protected:
+ // -------------------------------------------------------------------
+ /** Executes the postprocessing step on the given mesh
+ * @param pMesh The mesh to process.
+ * @param meshNum Index of the mesh to process
+ */
+ float ProcessMesh( aiMesh* pMesh, unsigned int meshNum);
+
+private:
+ //! Configuration parameter: specifies the size of the cache to
+ //! optimize the vertex data for.
+ unsigned int configCacheDepth;
+};
+
+} // end of namespace Assimp
+
+#endif // AI_IMPROVECACHELOCALITY_H_INC
diff --git a/thirdparty/assimp/code/JoinVerticesProcess.cpp b/thirdparty/assimp/code/JoinVerticesProcess.cpp
new file mode 100644
index 0000000000..914ec05b46
--- /dev/null
+++ b/thirdparty/assimp/code/JoinVerticesProcess.cpp
@@ -0,0 +1,463 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file Implementation of the post processing step to join identical vertices
+ * for all imported meshes
+ */
+
+
+#ifndef ASSIMP_BUILD_NO_JOINVERTICES_PROCESS
+
+#include "JoinVerticesProcess.h"
+#include "ProcessHelper.h"
+#include <assimp/Vertex.h>
+#include <assimp/TinyFormatter.h>
+#include <stdio.h>
+#include <unordered_set>
+
+using namespace Assimp;
+// ------------------------------------------------------------------------------------------------
+// Constructor to be privately used by Importer
+JoinVerticesProcess::JoinVerticesProcess()
+{
+ // nothing to do here
+}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor, private as well
+JoinVerticesProcess::~JoinVerticesProcess()
+{
+ // nothing to do here
+}
+
+// ------------------------------------------------------------------------------------------------
+// Returns whether the processing step is present in the given flag field.
+bool JoinVerticesProcess::IsActive( unsigned int pFlags) const
+{
+ return (pFlags & aiProcess_JoinIdenticalVertices) != 0;
+}
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+void JoinVerticesProcess::Execute( aiScene* pScene)
+{
+ ASSIMP_LOG_DEBUG("JoinVerticesProcess begin");
+
+ // get the total number of vertices BEFORE the step is executed
+ int iNumOldVertices = 0;
+ if (!DefaultLogger::isNullLogger()) {
+ for( unsigned int a = 0; a < pScene->mNumMeshes; a++) {
+ iNumOldVertices += pScene->mMeshes[a]->mNumVertices;
+ }
+ }
+
+ // execute the step
+ int iNumVertices = 0;
+ for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
+ iNumVertices += ProcessMesh( pScene->mMeshes[a],a);
+
+ // if logging is active, print detailed statistics
+ if (!DefaultLogger::isNullLogger()) {
+ if (iNumOldVertices == iNumVertices) {
+ ASSIMP_LOG_DEBUG("JoinVerticesProcess finished ");
+ } else {
+ ASSIMP_LOG_INFO_F("JoinVerticesProcess finished | Verts in: ", iNumOldVertices,
+ " out: ", iNumVertices, " | ~",
+ ((iNumOldVertices - iNumVertices) / (float)iNumOldVertices) * 100.f );
+ }
+ }
+
+ pScene->mFlags |= AI_SCENE_FLAGS_NON_VERBOSE_FORMAT;
+}
+
+namespace {
+
+bool areVerticesEqual(const Vertex &lhs, const Vertex &rhs, bool complex)
+{
+ // A little helper to find locally close vertices faster.
+ // Try to reuse the lookup table from the last step.
+ const static float epsilon = 1e-5f;
+ // Squared because we check against squared length of the vector difference
+ static const float squareEpsilon = epsilon * epsilon;
+
+ // Square compare is useful for animeshes vertices compare
+ if ((lhs.position - rhs.position).SquareLength() > squareEpsilon) {
+ return false;
+ }
+
+ // We just test the other attributes even if they're not present in the mesh.
+ // In this case they're initialized to 0 so the comparison succeeds.
+ // By this method the non-present attributes are effectively ignored in the comparison.
+ if ((lhs.normal - rhs.normal).SquareLength() > squareEpsilon) {
+ return false;
+ }
+
+ if ((lhs.texcoords[0] - rhs.texcoords[0]).SquareLength() > squareEpsilon) {
+ return false;
+ }
+
+ if ((lhs.tangent - rhs.tangent).SquareLength() > squareEpsilon) {
+ return false;
+ }
+
+ if ((lhs.bitangent - rhs.bitangent).SquareLength() > squareEpsilon) {
+ return false;
+ }
+
+ // Usually we won't have vertex colors or multiple UVs, so we can skip from here
+ // Actually this increases runtime performance slightly, at least if branch
+ // prediction is on our side.
+ if (complex) {
+ for (int i = 0; i < 8; i++) {
+ if (i > 0 && (lhs.texcoords[i] - rhs.texcoords[i]).SquareLength() > squareEpsilon) {
+ return false;
+ }
+ if (GetColorDifference(lhs.colors[i], rhs.colors[i]) > squareEpsilon) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+template<class XMesh>
+void updateXMeshVertices(XMesh *pMesh, std::vector<Vertex> &uniqueVertices) {
+ // replace vertex data with the unique data sets
+ pMesh->mNumVertices = (unsigned int)uniqueVertices.size();
+
+ // ----------------------------------------------------------------------------
+ // NOTE - we're *not* calling Vertex::SortBack() because it would check for
+ // presence of every single vertex component once PER VERTEX. And our CPU
+ // dislikes branches, even if they're easily predictable.
+ // ----------------------------------------------------------------------------
+
+ // Position, if present (check made for aiAnimMesh)
+ if (pMesh->mVertices)
+ {
+ delete [] pMesh->mVertices;
+ pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
+ for (unsigned int a = 0; a < pMesh->mNumVertices; a++) {
+ pMesh->mVertices[a] = uniqueVertices[a].position;
+ }
+ }
+
+ // Normals, if present
+ if (pMesh->mNormals)
+ {
+ delete [] pMesh->mNormals;
+ pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
+ for( unsigned int a = 0; a < pMesh->mNumVertices; a++) {
+ pMesh->mNormals[a] = uniqueVertices[a].normal;
+ }
+ }
+ // Tangents, if present
+ if (pMesh->mTangents)
+ {
+ delete [] pMesh->mTangents;
+ pMesh->mTangents = new aiVector3D[pMesh->mNumVertices];
+ for (unsigned int a = 0; a < pMesh->mNumVertices; a++) {
+ pMesh->mTangents[a] = uniqueVertices[a].tangent;
+ }
+ }
+ // Bitangents as well
+ if (pMesh->mBitangents)
+ {
+ delete [] pMesh->mBitangents;
+ pMesh->mBitangents = new aiVector3D[pMesh->mNumVertices];
+ for (unsigned int a = 0; a < pMesh->mNumVertices; a++) {
+ pMesh->mBitangents[a] = uniqueVertices[a].bitangent;
+ }
+ }
+ // Vertex colors
+ for (unsigned int a = 0; pMesh->HasVertexColors(a); a++)
+ {
+ delete [] pMesh->mColors[a];
+ pMesh->mColors[a] = new aiColor4D[pMesh->mNumVertices];
+ for( unsigned int b = 0; b < pMesh->mNumVertices; b++) {
+ pMesh->mColors[a][b] = uniqueVertices[b].colors[a];
+ }
+ }
+ // Texture coords
+ for (unsigned int a = 0; pMesh->HasTextureCoords(a); a++)
+ {
+ delete [] pMesh->mTextureCoords[a];
+ pMesh->mTextureCoords[a] = new aiVector3D[pMesh->mNumVertices];
+ for (unsigned int b = 0; b < pMesh->mNumVertices; b++) {
+ pMesh->mTextureCoords[a][b] = uniqueVertices[b].texcoords[a];
+ }
+ }
+}
+} // namespace
+
+// ------------------------------------------------------------------------------------------------
+// Unites identical vertices in the given mesh
+int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
+{
+ static_assert( AI_MAX_NUMBER_OF_COLOR_SETS == 8, "AI_MAX_NUMBER_OF_COLOR_SETS == 8");
+ static_assert( AI_MAX_NUMBER_OF_TEXTURECOORDS == 8, "AI_MAX_NUMBER_OF_TEXTURECOORDS == 8");
+
+ // Return early if we don't have any positions
+ if (!pMesh->HasPositions() || !pMesh->HasFaces()) {
+ return 0;
+ }
+
+ // We should care only about used vertices, not all of them
+ // (this can happen due to original file vertices buffer being used by
+ // multiple meshes)
+ std::unordered_set<unsigned int> usedVertexIndices;
+ usedVertexIndices.reserve(pMesh->mNumVertices);
+ for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
+ {
+ aiFace& face = pMesh->mFaces[a];
+ for( unsigned int b = 0; b < face.mNumIndices; b++) {
+ usedVertexIndices.insert(face.mIndices[b]);
+ }
+ }
+
+ // We'll never have more vertices afterwards.
+ std::vector<Vertex> uniqueVertices;
+ uniqueVertices.reserve( pMesh->mNumVertices);
+
+ // For each vertex the index of the vertex it was replaced by.
+ // Since the maximal number of vertices is 2^31-1, the most significand bit can be used to mark
+ // whether a new vertex was created for the index (true) or if it was replaced by an existing
+ // unique vertex (false). This saves an additional std::vector<bool> and greatly enhances
+ // branching performance.
+ static_assert(AI_MAX_VERTICES == 0x7fffffff, "AI_MAX_VERTICES == 0x7fffffff");
+ std::vector<unsigned int> replaceIndex( pMesh->mNumVertices, 0xffffffff);
+
+ // float posEpsilonSqr;
+ SpatialSort* vertexFinder = NULL;
+ SpatialSort _vertexFinder;
+
+ typedef std::pair<SpatialSort,float> SpatPair;
+ if (shared) {
+ std::vector<SpatPair >* avf;
+ shared->GetProperty(AI_SPP_SPATIAL_SORT,avf);
+ if (avf) {
+ SpatPair& blubb = (*avf)[meshIndex];
+ vertexFinder = &blubb.first;
+ // posEpsilonSqr = blubb.second;
+ }
+ }
+ if (!vertexFinder) {
+ // bad, need to compute it.
+ _vertexFinder.Fill(pMesh->mVertices, pMesh->mNumVertices, sizeof( aiVector3D));
+ vertexFinder = &_vertexFinder;
+ // posEpsilonSqr = ComputePositionEpsilon(pMesh);
+ }
+
+ // Again, better waste some bytes than a realloc ...
+ std::vector<unsigned int> verticesFound;
+ verticesFound.reserve(10);
+
+ // Run an optimized code path if we don't have multiple UVs or vertex colors.
+ // This should yield false in more than 99% of all imports ...
+ const bool complex = ( pMesh->GetNumColorChannels() > 0 || pMesh->GetNumUVChannels() > 1);
+ const bool hasAnimMeshes = pMesh->mNumAnimMeshes > 0;
+
+ // We'll never have more vertices afterwards.
+ std::vector<std::vector<Vertex>> uniqueAnimatedVertices;
+ if (hasAnimMeshes) {
+ uniqueAnimatedVertices.resize(pMesh->mNumAnimMeshes);
+ for (unsigned int animMeshIndex = 0; animMeshIndex < pMesh->mNumAnimMeshes; animMeshIndex++) {
+ uniqueAnimatedVertices[animMeshIndex].reserve(pMesh->mNumVertices);
+ }
+ }
+
+ // Now check each vertex if it brings something new to the table
+ for( unsigned int a = 0; a < pMesh->mNumVertices; a++) {
+ if (usedVertexIndices.find(a) == usedVertexIndices.end()) {
+ continue;
+ }
+
+ // collect the vertex data
+ Vertex v(pMesh,a);
+
+ // collect all vertices that are close enough to the given position
+ vertexFinder->FindIdenticalPositions( v.position, verticesFound);
+ unsigned int matchIndex = 0xffffffff;
+
+ // check all unique vertices close to the position if this vertex is already present among them
+ for( unsigned int b = 0; b < verticesFound.size(); b++) {
+ const unsigned int vidx = verticesFound[b];
+ const unsigned int uidx = replaceIndex[ vidx];
+ if( uidx & 0x80000000)
+ continue;
+
+ const Vertex& uv = uniqueVertices[ uidx];
+
+ if (!areVerticesEqual(v, uv, complex)) {
+ continue;
+ }
+
+ if (hasAnimMeshes) {
+ // If given vertex is animated, then it has to be preserver 1 to 1 (base mesh and animated mesh require same topology)
+ // NOTE: not doing this totaly breaks anim meshes as they don't have their own faces (they use pMesh->mFaces)
+ bool breaksAnimMesh = false;
+ for (unsigned int animMeshIndex = 0; animMeshIndex < pMesh->mNumAnimMeshes; animMeshIndex++) {
+ const Vertex& animatedUV = uniqueAnimatedVertices[animMeshIndex][ uidx];
+ Vertex aniMeshVertex(pMesh->mAnimMeshes[animMeshIndex], a);
+ if (!areVerticesEqual(aniMeshVertex, animatedUV, complex)) {
+ breaksAnimMesh = true;
+ break;
+ }
+ }
+ if (breaksAnimMesh) {
+ continue;
+ }
+ }
+
+ // we're still here -> this vertex perfectly matches our given vertex
+ matchIndex = uidx;
+ break;
+ }
+
+ // found a replacement vertex among the uniques?
+ if( matchIndex != 0xffffffff)
+ {
+ // store where to found the matching unique vertex
+ replaceIndex[a] = matchIndex | 0x80000000;
+ }
+ else
+ {
+ // no unique vertex matches it up to now -> so add it
+ replaceIndex[a] = (unsigned int)uniqueVertices.size();
+ uniqueVertices.push_back( v);
+ if (hasAnimMeshes) {
+ for (unsigned int animMeshIndex = 0; animMeshIndex < pMesh->mNumAnimMeshes; animMeshIndex++) {
+ Vertex aniMeshVertex(pMesh->mAnimMeshes[animMeshIndex], a);
+ uniqueAnimatedVertices[animMeshIndex].push_back(aniMeshVertex);
+ }
+ }
+ }
+ }
+
+ if (!DefaultLogger::isNullLogger() && DefaultLogger::get()->getLogSeverity() == Logger::VERBOSE) {
+ ASSIMP_LOG_DEBUG_F(
+ "Mesh ",meshIndex,
+ " (",
+ (pMesh->mName.length ? pMesh->mName.data : "unnamed"),
+ ") | Verts in: ",pMesh->mNumVertices,
+ " out: ",
+ uniqueVertices.size(),
+ " | ~",
+ ((pMesh->mNumVertices - uniqueVertices.size()) / (float)pMesh->mNumVertices) * 100.f,
+ "%"
+ );
+ }
+
+ updateXMeshVertices(pMesh, uniqueVertices);
+ if (hasAnimMeshes) {
+ for (unsigned int animMeshIndex = 0; animMeshIndex < pMesh->mNumAnimMeshes; animMeshIndex++) {
+ updateXMeshVertices(pMesh->mAnimMeshes[animMeshIndex], uniqueAnimatedVertices[animMeshIndex]);
+ }
+ }
+
+ // adjust the indices in all faces
+ for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
+ {
+ aiFace& face = pMesh->mFaces[a];
+ for( unsigned int b = 0; b < face.mNumIndices; b++) {
+ face.mIndices[b] = replaceIndex[face.mIndices[b]] & ~0x80000000;
+ }
+ }
+
+ // adjust bone vertex weights.
+ for( int a = 0; a < (int)pMesh->mNumBones; a++) {
+ aiBone* bone = pMesh->mBones[a];
+ std::vector<aiVertexWeight> newWeights;
+ newWeights.reserve( bone->mNumWeights);
+
+ if ( NULL != bone->mWeights ) {
+ for ( unsigned int b = 0; b < bone->mNumWeights; b++ ) {
+ const aiVertexWeight& ow = bone->mWeights[ b ];
+ // if the vertex is a unique one, translate it
+ if ( !( replaceIndex[ ow.mVertexId ] & 0x80000000 ) ) {
+ aiVertexWeight nw;
+ nw.mVertexId = replaceIndex[ ow.mVertexId ];
+ nw.mWeight = ow.mWeight;
+ newWeights.push_back( nw );
+ }
+ }
+ } else {
+ ASSIMP_LOG_ERROR( "X-Export: aiBone shall contain weights, but pointer to them is NULL." );
+ }
+
+ if (newWeights.size() > 0) {
+ // kill the old and replace them with the translated weights
+ delete [] bone->mWeights;
+ bone->mNumWeights = (unsigned int)newWeights.size();
+
+ bone->mWeights = new aiVertexWeight[bone->mNumWeights];
+ memcpy( bone->mWeights, &newWeights[0], bone->mNumWeights * sizeof( aiVertexWeight));
+ }
+ else {
+
+ /* NOTE:
+ *
+ * In the algorithm above we're assuming that there are no vertices
+ * with a different bone weight setup at the same position. That wouldn't
+ * make sense, but it is not absolutely impossible. SkeletonMeshBuilder
+ * for example generates such input data if two skeleton points
+ * share the same position. Again this doesn't make sense but is
+ * reality for some model formats (MD5 for example uses these special
+ * nodes as attachment tags for its weapons).
+ *
+ * Then it is possible that a bone has no weights anymore .... as a quick
+ * workaround, we're just removing these bones. If they're animated,
+ * model geometry might be modified but at least there's no risk of a crash.
+ */
+ delete bone;
+ --pMesh->mNumBones;
+ for (unsigned int n = a; n < pMesh->mNumBones; ++n) {
+ pMesh->mBones[n] = pMesh->mBones[n+1];
+ }
+
+ --a;
+ ASSIMP_LOG_WARN("Removing bone -> no weights remaining");
+ }
+ }
+ return pMesh->mNumVertices;
+}
+
+#endif // !! ASSIMP_BUILD_NO_JOINVERTICES_PROCESS
diff --git a/thirdparty/assimp/code/JoinVerticesProcess.h b/thirdparty/assimp/code/JoinVerticesProcess.h
new file mode 100644
index 0000000000..66fa362de2
--- /dev/null
+++ b/thirdparty/assimp/code/JoinVerticesProcess.h
@@ -0,0 +1,99 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file Defines a post processing step to join identical vertices
+ on all imported meshes.*/
+#ifndef AI_JOINVERTICESPROCESS_H_INC
+#define AI_JOINVERTICESPROCESS_H_INC
+
+#include "BaseProcess.h"
+#include <assimp/types.h>
+
+struct aiMesh;
+
+namespace Assimp
+{
+
+// ---------------------------------------------------------------------------
+/** The JoinVerticesProcess unites identical vertices in all imported meshes.
+ * By default the importer returns meshes where each face addressed its own
+ * set of vertices even if that means that identical vertices are stored multiple
+ * times. The JoinVerticesProcess finds these identical vertices and
+ * erases all but one of the copies. This usually reduces the number of vertices
+ * in a mesh by a serious amount and is the standard form to render a mesh.
+ */
+class ASSIMP_API JoinVerticesProcess : public BaseProcess
+{
+public:
+ JoinVerticesProcess();
+ ~JoinVerticesProcess();
+
+public:
+ // -------------------------------------------------------------------
+ /** Returns whether the processing step is present in the given flag field.
+ * @param pFlags The processing flags the importer was called with. A bitwise
+ * combination of #aiPostProcessSteps.
+ * @return true if the process is present in this flag fields, false if not.
+ */
+ bool IsActive( unsigned int pFlags) const;
+
+ // -------------------------------------------------------------------
+ /** Executes the post processing step on the given imported data.
+ * At the moment a process is not supposed to fail.
+ * @param pScene The imported data to work at.
+ */
+ void Execute( aiScene* pScene);
+
+public:
+ // -------------------------------------------------------------------
+ /** Unites identical vertices in the given mesh.
+ * @param pMesh The mesh to process.
+ * @param meshIndex Index of the mesh to process
+ */
+ int ProcessMesh( aiMesh* pMesh, unsigned int meshIndex);
+
+private:
+};
+
+} // end of namespace Assimp
+
+#endif // AI_CALCTANGENTSPROCESS_H_INC
diff --git a/thirdparty/assimp/code/LimitBoneWeightsProcess.cpp b/thirdparty/assimp/code/LimitBoneWeightsProcess.cpp
new file mode 100644
index 0000000000..d560f19287
--- /dev/null
+++ b/thirdparty/assimp/code/LimitBoneWeightsProcess.cpp
@@ -0,0 +1,201 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** Implementation of the LimitBoneWeightsProcess post processing step */
+
+
+#include "LimitBoneWeightsProcess.h"
+#include <assimp/StringUtils.h>
+#include <assimp/postprocess.h>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/scene.h>
+#include <stdio.h>
+
+using namespace Assimp;
+
+
+// ------------------------------------------------------------------------------------------------
+// Constructor to be privately used by Importer
+LimitBoneWeightsProcess::LimitBoneWeightsProcess()
+{
+ mMaxWeights = AI_LMW_MAX_WEIGHTS;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor, private as well
+LimitBoneWeightsProcess::~LimitBoneWeightsProcess()
+{
+ // nothing to do here
+}
+
+// ------------------------------------------------------------------------------------------------
+// Returns whether the processing step is present in the given flag field.
+bool LimitBoneWeightsProcess::IsActive( unsigned int pFlags) const
+{
+ return (pFlags & aiProcess_LimitBoneWeights) != 0;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+void LimitBoneWeightsProcess::Execute( aiScene* pScene) {
+ ASSIMP_LOG_DEBUG("LimitBoneWeightsProcess begin");
+ for (unsigned int a = 0; a < pScene->mNumMeshes; ++a ) {
+ ProcessMesh(pScene->mMeshes[a]);
+ }
+
+ ASSIMP_LOG_DEBUG("LimitBoneWeightsProcess end");
+}
+
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+void LimitBoneWeightsProcess::SetupProperties(const Importer* pImp)
+{
+ // get the current value of the property
+ this->mMaxWeights = pImp->GetPropertyInteger(AI_CONFIG_PP_LBW_MAX_WEIGHTS,AI_LMW_MAX_WEIGHTS);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Unites identical vertices in the given mesh
+void LimitBoneWeightsProcess::ProcessMesh( aiMesh* pMesh)
+{
+ if( !pMesh->HasBones())
+ return;
+
+ // collect all bone weights per vertex
+ typedef std::vector< std::vector< Weight > > WeightsPerVertex;
+ WeightsPerVertex vertexWeights( pMesh->mNumVertices);
+
+ // collect all weights per vertex
+ for( unsigned int a = 0; a < pMesh->mNumBones; a++)
+ {
+ const aiBone* bone = pMesh->mBones[a];
+ for( unsigned int b = 0; b < bone->mNumWeights; b++)
+ {
+ const aiVertexWeight& w = bone->mWeights[b];
+ vertexWeights[w.mVertexId].push_back( Weight( a, w.mWeight));
+ }
+ }
+
+ unsigned int removed = 0, old_bones = pMesh->mNumBones;
+
+ // now cut the weight count if it exceeds the maximum
+ bool bChanged = false;
+ for( WeightsPerVertex::iterator vit = vertexWeights.begin(); vit != vertexWeights.end(); ++vit)
+ {
+ if( vit->size() <= mMaxWeights)
+ continue;
+
+ bChanged = true;
+
+ // more than the defined maximum -> first sort by weight in descending order. That's
+ // why we defined the < operator in such a weird way.
+ std::sort( vit->begin(), vit->end());
+
+ // now kill everything beyond the maximum count
+ unsigned int m = static_cast<unsigned int>(vit->size());
+ vit->erase( vit->begin() + mMaxWeights, vit->end());
+ removed += static_cast<unsigned int>(m-vit->size());
+
+ // and renormalize the weights
+ float sum = 0.0f;
+ for( std::vector<Weight>::const_iterator it = vit->begin(); it != vit->end(); ++it ) {
+ sum += it->mWeight;
+ }
+ if( 0.0f != sum ) {
+ const float invSum = 1.0f / sum;
+ for( std::vector<Weight>::iterator it = vit->begin(); it != vit->end(); ++it ) {
+ it->mWeight *= invSum;
+ }
+ }
+ }
+
+ if (bChanged) {
+ // rebuild the vertex weight array for all bones
+ typedef std::vector< std::vector< aiVertexWeight > > WeightsPerBone;
+ WeightsPerBone boneWeights( pMesh->mNumBones);
+ for( unsigned int a = 0; a < vertexWeights.size(); a++)
+ {
+ const std::vector<Weight>& vw = vertexWeights[a];
+ for( std::vector<Weight>::const_iterator it = vw.begin(); it != vw.end(); ++it)
+ boneWeights[it->mBone].push_back( aiVertexWeight( a, it->mWeight));
+ }
+
+ // and finally copy the vertex weight list over to the mesh's bones
+ std::vector<bool> abNoNeed(pMesh->mNumBones,false);
+ bChanged = false;
+
+ for( unsigned int a = 0; a < pMesh->mNumBones; a++)
+ {
+ const std::vector<aiVertexWeight>& bw = boneWeights[a];
+ aiBone* bone = pMesh->mBones[a];
+
+ if ( bw.empty() )
+ {
+ abNoNeed[a] = bChanged = true;
+ continue;
+ }
+
+ // copy the weight list. should always be less weights than before, so we don't need a new allocation
+ ai_assert( bw.size() <= bone->mNumWeights);
+ bone->mNumWeights = static_cast<unsigned int>( bw.size() );
+ ::memcpy( bone->mWeights, &bw[0], bw.size() * sizeof( aiVertexWeight));
+ }
+
+ if (bChanged) {
+ // the number of new bones is smaller than before, so we can reuse the old array
+ aiBone** ppcCur = pMesh->mBones;aiBone** ppcSrc = ppcCur;
+
+ for (std::vector<bool>::const_iterator iter = abNoNeed.begin();iter != abNoNeed.end() ;++iter) {
+ if (*iter) {
+ delete *ppcSrc;
+ --pMesh->mNumBones;
+ }
+ else *ppcCur++ = *ppcSrc;
+ ++ppcSrc;
+ }
+ }
+
+ if (!DefaultLogger::isNullLogger()) {
+ ASSIMP_LOG_INFO_F("Removed ", removed, " weights. Input bones: ", old_bones, ". Output bones: ", pMesh->mNumBones );
+ }
+ }
+}
diff --git a/thirdparty/assimp/code/LimitBoneWeightsProcess.h b/thirdparty/assimp/code/LimitBoneWeightsProcess.h
new file mode 100644
index 0000000000..3602fd8edf
--- /dev/null
+++ b/thirdparty/assimp/code/LimitBoneWeightsProcess.h
@@ -0,0 +1,148 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** Defines a post processing step to limit the number of bones affecting a single vertex. */
+#ifndef AI_LIMITBONEWEIGHTSPROCESS_H_INC
+#define AI_LIMITBONEWEIGHTSPROCESS_H_INC
+
+#include "BaseProcess.h"
+
+struct aiMesh;
+
+class LimitBoneWeightsTest;
+
+namespace Assimp
+{
+
+// NOTE: If you change these limits, don't forget to change the
+// corresponding values in all Assimp ports
+
+// **********************************************************
+// Java: ConfigProperty.java,
+// ConfigProperty.DEFAULT_BONE_WEIGHT_LIMIT
+// **********************************************************
+
+#if (!defined AI_LMW_MAX_WEIGHTS)
+# define AI_LMW_MAX_WEIGHTS 0x4
+#endif // !! AI_LMW_MAX_WEIGHTS
+
+// ---------------------------------------------------------------------------
+/** This post processing step limits the number of bones affecting a vertex
+* to a certain maximum value. If a vertex is affected by more than that number
+* of bones, the bone weight with the least influence on this vertex are removed.
+* The other weights on this bone are then renormalized to assure the sum weight
+* to be 1.
+*/
+class ASSIMP_API LimitBoneWeightsProcess : public BaseProcess
+{
+public:
+
+ LimitBoneWeightsProcess();
+ ~LimitBoneWeightsProcess();
+
+public:
+ // -------------------------------------------------------------------
+ /** Returns whether the processing step is present in the given flag.
+ * @param pFlags The processing flags the importer was called with.
+ * A bitwise combination of #aiPostProcessSteps.
+ * @return true if the process is present in this flag fields,
+ * false if not.
+ */
+ bool IsActive( unsigned int pFlags) const;
+
+ // -------------------------------------------------------------------
+ /** Called prior to ExecuteOnScene().
+ * The function is a request to the process to update its configuration
+ * basing on the Importer's configuration property list.
+ */
+ void SetupProperties(const Importer* pImp);
+
+public:
+
+ // -------------------------------------------------------------------
+ /** Limits the bone weight count for all vertices in the given mesh.
+ * @param pMesh The mesh to process.
+ */
+ void ProcessMesh( aiMesh* pMesh);
+
+ // -------------------------------------------------------------------
+ /** Executes the post processing step on the given imported data.
+ * At the moment a process is not supposed to fail.
+ * @param pScene The imported data to work at.
+ */
+ void Execute( aiScene* pScene);
+
+
+public:
+
+ // -------------------------------------------------------------------
+ /** Describes a bone weight on a vertex */
+ struct Weight
+ {
+ unsigned int mBone; ///< Index of the bone
+ float mWeight; ///< Weight of that bone on this vertex
+ Weight() AI_NO_EXCEPT
+ : mBone(0)
+ , mWeight(0.0f)
+ { }
+
+ Weight( unsigned int pBone, float pWeight)
+ {
+ mBone = pBone;
+ mWeight = pWeight;
+ }
+
+ /** Comparison operator to sort bone weights by descending weight */
+ bool operator < (const Weight& pWeight) const
+ {
+ return mWeight > pWeight.mWeight;
+ }
+ };
+
+public:
+ /** Maximum number of bones influencing any single vertex. */
+ unsigned int mMaxWeights;
+};
+
+} // end of namespace Assimp
+
+#endif // AI_LIMITBONEWEIGHTSPROCESS_H_INC
diff --git a/thirdparty/assimp/code/MMDCpp14.h b/thirdparty/assimp/code/MMDCpp14.h
new file mode 100644
index 0000000000..638b0bfd2f
--- /dev/null
+++ b/thirdparty/assimp/code/MMDCpp14.h
@@ -0,0 +1,83 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+#pragma once
+
+#ifndef MMD_CPP14_H
+#define MMD_CPP14_H
+
+#include <cstddef>
+#include <memory>
+#include <type_traits>
+#include <utility>
+
+namespace mmd {
+ template<class T> struct _Unique_if {
+ typedef std::unique_ptr<T> _Single_object;
+ };
+
+ template<class T> struct _Unique_if<T[]> {
+ typedef std::unique_ptr<T[]> _Unknown_bound;
+ };
+
+ template<class T, size_t N> struct _Unique_if<T[N]> {
+ typedef void _Known_bound;
+ };
+
+ template<class T, class... Args>
+ typename _Unique_if<T>::_Single_object
+ make_unique(Args&&... args) {
+ return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
+ }
+
+ template<class T>
+ typename _Unique_if<T>::_Unknown_bound
+ make_unique(size_t n) {
+ typedef typename std::remove_extent<T>::type U;
+ return std::unique_ptr<T>(new U[n]());
+ }
+
+ template<class T, class... Args>
+ typename _Unique_if<T>::_Known_bound
+ make_unique(Args&&...) = delete;
+}
+
+#endif
diff --git a/thirdparty/assimp/code/MMDImporter.cpp b/thirdparty/assimp/code/MMDImporter.cpp
new file mode 100644
index 0000000000..84b9e35a6b
--- /dev/null
+++ b/thirdparty/assimp/code/MMDImporter.cpp
@@ -0,0 +1,370 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2016, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+#ifndef ASSIMP_BUILD_NO_MMD_IMPORTER
+
+#include "MMDImporter.h"
+#include "MMDPmdParser.h"
+#include "MMDPmxParser.h"
+#include "MMDVmdParser.h"
+#include "ConvertToLHProcess.h"
+#include <assimp/DefaultIOSystem.h>
+#include <assimp/Importer.hpp>
+#include <assimp/ai_assert.h>
+#include <assimp/scene.h>
+#include <fstream>
+#include <iomanip>
+#include <memory>
+
+static const aiImporterDesc desc = {"MMD Importer",
+ "",
+ "",
+ "surfaces supported?",
+ aiImporterFlags_SupportTextFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "pmx"};
+
+namespace Assimp {
+
+using namespace std;
+
+// ------------------------------------------------------------------------------------------------
+// Default constructor
+MMDImporter::MMDImporter()
+: m_Buffer()
+, m_strAbsPath("") {
+ DefaultIOSystem io;
+ m_strAbsPath = io.getOsSeparator();
+}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor.
+MMDImporter::~MMDImporter() {
+ // empty
+}
+
+// ------------------------------------------------------------------------------------------------
+// Returns true, if file is an pmx file.
+bool MMDImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler,
+ bool checkSig) const {
+ if (!checkSig) // Check File Extension
+ {
+ return SimpleExtensionCheck(pFile, "pmx");
+ } else // Check file Header
+ {
+ static const char *pTokens[] = {"PMX "};
+ return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, pTokens, 1);
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+const aiImporterDesc *MMDImporter::GetInfo() const { return &desc; }
+
+// ------------------------------------------------------------------------------------------------
+// MMD import implementation
+void MMDImporter::InternReadFile(const std::string &file, aiScene *pScene,
+ IOSystem * /*pIOHandler*/) {
+ // Read file by istream
+ std::filebuf fb;
+ if (!fb.open(file, std::ios::in | std::ios::binary)) {
+ throw DeadlyImportError("Failed to open file " + file + ".");
+ }
+
+ std::istream fileStream(&fb);
+
+ // Get the file-size and validate it, throwing an exception when fails
+ fileStream.seekg(0, fileStream.end);
+ size_t fileSize = static_cast<size_t>(fileStream.tellg());
+ fileStream.seekg(0, fileStream.beg);
+
+ if (fileSize < sizeof(pmx::PmxModel)) {
+ throw DeadlyImportError(file + " is too small.");
+ }
+
+ pmx::PmxModel model;
+ model.Read(&fileStream);
+
+ CreateDataFromImport(&model, pScene);
+}
+
+// ------------------------------------------------------------------------------------------------
+void MMDImporter::CreateDataFromImport(const pmx::PmxModel *pModel,
+ aiScene *pScene) {
+ if (pModel == NULL) {
+ return;
+ }
+
+ aiNode *pNode = new aiNode;
+ if (!pModel->model_name.empty()) {
+ pNode->mName.Set(pModel->model_name);
+ }
+
+ pScene->mRootNode = pNode;
+
+ pNode = new aiNode;
+ pScene->mRootNode->addChildren(1, &pNode);
+ pNode->mName.Set(string(pModel->model_name) + string("_mesh"));
+
+ // split mesh by materials
+ pNode->mNumMeshes = pModel->material_count;
+ pNode->mMeshes = new unsigned int[pNode->mNumMeshes];
+ for (unsigned int index = 0; index < pNode->mNumMeshes; index++) {
+ pNode->mMeshes[index] = index;
+ }
+
+ pScene->mNumMeshes = pModel->material_count;
+ pScene->mMeshes = new aiMesh *[pScene->mNumMeshes];
+ for (unsigned int i = 0, indexStart = 0; i < pScene->mNumMeshes; i++) {
+ const int indexCount = pModel->materials[i].index_count;
+
+ pScene->mMeshes[i] = CreateMesh(pModel, indexStart, indexCount);
+ pScene->mMeshes[i]->mName = pModel->materials[i].material_name;
+ pScene->mMeshes[i]->mMaterialIndex = i;
+ indexStart += indexCount;
+ }
+
+ // create node hierarchy for bone position
+ std::unique_ptr<aiNode *[]> ppNode(new aiNode *[pModel->bone_count]);
+ for (auto i = 0; i < pModel->bone_count; i++) {
+ ppNode[i] = new aiNode(pModel->bones[i].bone_name);
+ }
+
+ for (auto i = 0; i < pModel->bone_count; i++) {
+ const pmx::PmxBone &bone = pModel->bones[i];
+
+ if (bone.parent_index < 0) {
+ pScene->mRootNode->addChildren(1, ppNode.get() + i);
+ } else {
+ ppNode[bone.parent_index]->addChildren(1, ppNode.get() + i);
+
+ aiVector3D v3 = aiVector3D(
+ bone.position[0] - pModel->bones[bone.parent_index].position[0],
+ bone.position[1] - pModel->bones[bone.parent_index].position[1],
+ bone.position[2] - pModel->bones[bone.parent_index].position[2]);
+ aiMatrix4x4::Translation(v3, ppNode[i]->mTransformation);
+ }
+ }
+
+ // create materials
+ pScene->mNumMaterials = pModel->material_count;
+ pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials];
+ for (unsigned int i = 0; i < pScene->mNumMaterials; i++) {
+ pScene->mMaterials[i] = CreateMaterial(&pModel->materials[i], pModel);
+ }
+
+ // Convert everything to OpenGL space
+ MakeLeftHandedProcess convertProcess;
+ convertProcess.Execute(pScene);
+
+ FlipUVsProcess uvFlipper;
+ uvFlipper.Execute(pScene);
+
+ FlipWindingOrderProcess windingFlipper;
+ windingFlipper.Execute(pScene);
+}
+
+// ------------------------------------------------------------------------------------------------
+aiMesh *MMDImporter::CreateMesh(const pmx::PmxModel *pModel,
+ const int indexStart, const int indexCount) {
+ aiMesh *pMesh = new aiMesh;
+
+ pMesh->mNumVertices = indexCount;
+
+ pMesh->mNumFaces = indexCount / 3;
+ pMesh->mFaces = new aiFace[pMesh->mNumFaces];
+
+ const int numIndices = 3; // triangular face
+ for (unsigned int index = 0; index < pMesh->mNumFaces; index++) {
+ pMesh->mFaces[index].mNumIndices = numIndices;
+ unsigned int *indices = new unsigned int[numIndices];
+ indices[0] = numIndices * index;
+ indices[1] = numIndices * index + 1;
+ indices[2] = numIndices * index + 2;
+ pMesh->mFaces[index].mIndices = indices;
+ }
+
+ pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
+ pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
+ pMesh->mTextureCoords[0] = new aiVector3D[pMesh->mNumVertices];
+ pMesh->mNumUVComponents[0] = 2;
+
+ // additional UVs
+ for (int i = 1; i <= pModel->setting.uv; i++) {
+ pMesh->mTextureCoords[i] = new aiVector3D[pMesh->mNumVertices];
+ pMesh->mNumUVComponents[i] = 4;
+ }
+
+ map<int, vector<aiVertexWeight>> bone_vertex_map;
+
+ // fill in contents and create bones
+ for (int index = 0; index < indexCount; index++) {
+ const pmx::PmxVertex *v =
+ &pModel->vertices[pModel->indices[indexStart + index]];
+ const float *position = v->position;
+ pMesh->mVertices[index].Set(position[0], position[1], position[2]);
+ const float *normal = v->normal;
+
+ pMesh->mNormals[index].Set(normal[0], normal[1], normal[2]);
+ pMesh->mTextureCoords[0][index].x = v->uv[0];
+ pMesh->mTextureCoords[0][index].y = v->uv[1];
+
+ for (int i = 1; i <= pModel->setting.uv; i++) {
+ // TODO: wrong here? use quaternion transform?
+ pMesh->mTextureCoords[i][index].x = v->uva[i][0];
+ pMesh->mTextureCoords[i][index].y = v->uva[i][1];
+ }
+
+ // handle bone map
+ const auto vsBDEF1_ptr =
+ dynamic_cast<pmx::PmxVertexSkinningBDEF1 *>(v->skinning.get());
+ const auto vsBDEF2_ptr =
+ dynamic_cast<pmx::PmxVertexSkinningBDEF2 *>(v->skinning.get());
+ const auto vsBDEF4_ptr =
+ dynamic_cast<pmx::PmxVertexSkinningBDEF4 *>(v->skinning.get());
+ const auto vsSDEF_ptr =
+ dynamic_cast<pmx::PmxVertexSkinningSDEF *>(v->skinning.get());
+ switch (v->skinning_type) {
+ case pmx::PmxVertexSkinningType::BDEF1:
+ bone_vertex_map[vsBDEF1_ptr->bone_index].push_back(
+ aiVertexWeight(index, 1.0));
+ break;
+ case pmx::PmxVertexSkinningType::BDEF2:
+ bone_vertex_map[vsBDEF2_ptr->bone_index1].push_back(
+ aiVertexWeight(index, vsBDEF2_ptr->bone_weight));
+ bone_vertex_map[vsBDEF2_ptr->bone_index2].push_back(
+ aiVertexWeight(index, 1.0f - vsBDEF2_ptr->bone_weight));
+ break;
+ case pmx::PmxVertexSkinningType::BDEF4:
+ bone_vertex_map[vsBDEF4_ptr->bone_index1].push_back(
+ aiVertexWeight(index, vsBDEF4_ptr->bone_weight1));
+ bone_vertex_map[vsBDEF4_ptr->bone_index2].push_back(
+ aiVertexWeight(index, vsBDEF4_ptr->bone_weight2));
+ bone_vertex_map[vsBDEF4_ptr->bone_index3].push_back(
+ aiVertexWeight(index, vsBDEF4_ptr->bone_weight3));
+ bone_vertex_map[vsBDEF4_ptr->bone_index4].push_back(
+ aiVertexWeight(index, vsBDEF4_ptr->bone_weight4));
+ break;
+ case pmx::PmxVertexSkinningType::SDEF: // TODO: how to use sdef_c, sdef_r0,
+ // sdef_r1?
+ bone_vertex_map[vsSDEF_ptr->bone_index1].push_back(
+ aiVertexWeight(index, vsSDEF_ptr->bone_weight));
+ bone_vertex_map[vsSDEF_ptr->bone_index2].push_back(
+ aiVertexWeight(index, 1.0f - vsSDEF_ptr->bone_weight));
+ break;
+ case pmx::PmxVertexSkinningType::QDEF:
+ const auto vsQDEF_ptr =
+ dynamic_cast<pmx::PmxVertexSkinningQDEF *>(v->skinning.get());
+ bone_vertex_map[vsQDEF_ptr->bone_index1].push_back(
+ aiVertexWeight(index, vsQDEF_ptr->bone_weight1));
+ bone_vertex_map[vsQDEF_ptr->bone_index2].push_back(
+ aiVertexWeight(index, vsQDEF_ptr->bone_weight2));
+ bone_vertex_map[vsQDEF_ptr->bone_index3].push_back(
+ aiVertexWeight(index, vsQDEF_ptr->bone_weight3));
+ bone_vertex_map[vsQDEF_ptr->bone_index4].push_back(
+ aiVertexWeight(index, vsQDEF_ptr->bone_weight4));
+ break;
+ }
+ }
+
+ // make all bones for each mesh
+ // assign bone weights to skinned bones (otherwise just initialize)
+ auto bone_ptr_ptr = new aiBone *[pModel->bone_count];
+ pMesh->mNumBones = pModel->bone_count;
+ pMesh->mBones = bone_ptr_ptr;
+ for (auto ii = 0; ii < pModel->bone_count; ++ii) {
+ auto pBone = new aiBone;
+ const auto &pmxBone = pModel->bones[ii];
+ pBone->mName = pmxBone.bone_name;
+ aiVector3D pos(pmxBone.position[0], pmxBone.position[1], pmxBone.position[2]);
+ aiMatrix4x4::Translation(-pos, pBone->mOffsetMatrix);
+ auto it = bone_vertex_map.find(ii);
+ if (it != bone_vertex_map.end()) {
+ pBone->mNumWeights = static_cast<unsigned int>(it->second.size());
+ pBone->mWeights = new aiVertexWeight[pBone->mNumWeights];
+ for (unsigned int j = 0; j < pBone->mNumWeights; j++) {
+ pBone->mWeights[j] = it->second[j];
+ }
+ }
+ bone_ptr_ptr[ii] = pBone;
+ }
+
+ return pMesh;
+}
+
+// ------------------------------------------------------------------------------------------------
+aiMaterial *MMDImporter::CreateMaterial(const pmx::PmxMaterial *pMat,
+ const pmx::PmxModel *pModel) {
+ aiMaterial *mat = new aiMaterial();
+ aiString name(pMat->material_english_name);
+ mat->AddProperty(&name, AI_MATKEY_NAME);
+
+ aiColor3D diffuse(pMat->diffuse[0], pMat->diffuse[1], pMat->diffuse[2]);
+ mat->AddProperty(&diffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
+ aiColor3D specular(pMat->specular[0], pMat->specular[1], pMat->specular[2]);
+ mat->AddProperty(&specular, 1, AI_MATKEY_COLOR_SPECULAR);
+ aiColor3D ambient(pMat->ambient[0], pMat->ambient[1], pMat->ambient[2]);
+ mat->AddProperty(&ambient, 1, AI_MATKEY_COLOR_AMBIENT);
+
+ float opacity = pMat->diffuse[3];
+ mat->AddProperty(&opacity, 1, AI_MATKEY_OPACITY);
+ float shininess = pMat->specularlity;
+ mat->AddProperty(&shininess, 1, AI_MATKEY_SHININESS_STRENGTH);
+
+ if(pMat->diffuse_texture_index >= 0) {
+ aiString texture_path(pModel->textures[pMat->diffuse_texture_index]);
+ mat->AddProperty(&texture_path, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));
+ }
+
+ int mapping_uvwsrc = 0;
+ mat->AddProperty(&mapping_uvwsrc, 1,
+ AI_MATKEY_UVWSRC(aiTextureType_DIFFUSE, 0));
+
+ return mat;
+}
+
+// ------------------------------------------------------------------------------------------------
+
+} // Namespace Assimp
+
+#endif // !! ASSIMP_BUILD_NO_MMD_IMPORTER
diff --git a/thirdparty/assimp/code/MMDImporter.h b/thirdparty/assimp/code/MMDImporter.h
new file mode 100644
index 0000000000..4ee94eeb00
--- /dev/null
+++ b/thirdparty/assimp/code/MMDImporter.h
@@ -0,0 +1,96 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2016, assimp team
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+#ifndef MMD_FILE_IMPORTER_H_INC
+#define MMD_FILE_IMPORTER_H_INC
+
+#include <assimp/BaseImporter.h>
+#include "MMDPmxParser.h"
+#include <assimp/material.h>
+#include <vector>
+
+struct aiMesh;
+
+namespace Assimp {
+
+// ------------------------------------------------------------------------------------------------
+/// \class MMDImporter
+/// \brief Imports MMD a pmx/pmd/vmd file
+// ------------------------------------------------------------------------------------------------
+class MMDImporter : public BaseImporter {
+public:
+ /// \brief Default constructor
+ MMDImporter();
+
+ /// \brief Destructor
+ ~MMDImporter();
+
+public:
+ /// \brief Returns whether the class can handle the format of the given file.
+ /// \remark See BaseImporter::CanRead() for details.
+ bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const;
+
+private:
+ //! \brief Appends the supported extension.
+ const aiImporterDesc* GetInfo () const;
+
+ //! \brief File import implementation.
+ void InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
+
+ //! \brief Create the data from imported content.
+ void CreateDataFromImport(const pmx::PmxModel* pModel, aiScene* pScene);
+
+ //! \brief Create the mesh
+ aiMesh* CreateMesh(const pmx::PmxModel* pModel, const int indexStart, const int indexCount);
+
+ //! \brief Create the material
+ aiMaterial* CreateMaterial(const pmx::PmxMaterial* pMat, const pmx::PmxModel* pModel);
+
+private:
+ //! Data buffer
+ std::vector<char> m_Buffer;
+ //! Absolute pathname of model in file system
+ std::string m_strAbsPath;
+};
+
+// ------------------------------------------------------------------------------------------------
+
+} // Namespace Assimp
+
+#endif \ No newline at end of file
diff --git a/thirdparty/assimp/code/MMDPmdParser.h b/thirdparty/assimp/code/MMDPmdParser.h
new file mode 100644
index 0000000000..d2f2224aa1
--- /dev/null
+++ b/thirdparty/assimp/code/MMDPmdParser.h
@@ -0,0 +1,597 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+#pragma once
+
+#include <vector>
+#include <string>
+#include <memory>
+#include <iostream>
+#include <fstream>
+#include "MMDCpp14.h"
+
+namespace pmd
+{
+ class PmdHeader
+ {
+ public:
+ std::string name;
+ std::string name_english;
+ std::string comment;
+ std::string comment_english;
+
+ bool Read(std::ifstream* stream)
+ {
+ char buffer[256];
+ stream->read(buffer, 20);
+ name = std::string(buffer);
+ stream->read(buffer, 256);
+ comment = std::string(buffer);
+ return true;
+ }
+
+ bool ReadExtension(std::ifstream* stream)
+ {
+ char buffer[256];
+ stream->read(buffer, 20);
+ name_english = std::string(buffer);
+ stream->read(buffer, 256);
+ comment_english = std::string(buffer);
+ return true;
+ }
+ };
+
+ class PmdVertex
+ {
+ public:
+ float position[3];
+
+ float normal[3];
+
+ float uv[2];
+
+ uint16_t bone_index[2];
+
+ uint8_t bone_weight;
+
+ bool edge_invisible;
+
+ bool Read(std::ifstream* stream)
+ {
+ stream->read((char*) position, sizeof(float) * 3);
+ stream->read((char*) normal, sizeof(float) * 3);
+ stream->read((char*) uv, sizeof(float) * 2);
+ stream->read((char*) bone_index, sizeof(uint16_t) * 2);
+ stream->read((char*) &bone_weight, sizeof(uint8_t));
+ stream->read((char*) &edge_invisible, sizeof(uint8_t));
+ return true;
+ }
+ };
+
+ class PmdMaterial
+ {
+ public:
+ float diffuse[4];
+ float power;
+ float specular[3];
+ float ambient[3];
+ uint8_t toon_index;
+ uint8_t edge_flag;
+ uint32_t index_count;
+ std::string texture_filename;
+ std::string sphere_filename;
+
+ bool Read(std::ifstream* stream)
+ {
+ char buffer[20];
+ stream->read((char*) &diffuse, sizeof(float) * 4);
+ stream->read((char*) &power, sizeof(float));
+ stream->read((char*) &specular, sizeof(float) * 3);
+ stream->read((char*) &ambient, sizeof(float) * 3);
+ stream->read((char*) &toon_index, sizeof(uint8_t));
+ stream->read((char*) &edge_flag, sizeof(uint8_t));
+ stream->read((char*) &index_count, sizeof(uint32_t));
+ stream->read((char*) &buffer, sizeof(char) * 20);
+ char* pstar = strchr(buffer, '*');
+ if (NULL == pstar)
+ {
+ texture_filename = std::string(buffer);
+ sphere_filename.clear();
+ }
+ else {
+ *pstar = 0;
+ texture_filename = std::string(buffer);
+ sphere_filename = std::string(pstar+1);
+ }
+ return true;
+ }
+ };
+
+ enum class BoneType : uint8_t
+ {
+ Rotation,
+ RotationAndMove,
+ IkEffector,
+ Unknown,
+ IkEffectable,
+ RotationEffectable,
+ IkTarget,
+ Invisible,
+ Twist,
+ RotationMovement
+ };
+
+ class PmdBone
+ {
+ public:
+ std::string name;
+ std::string name_english;
+ uint16_t parent_bone_index;
+ uint16_t tail_pos_bone_index;
+ BoneType bone_type;
+ uint16_t ik_parent_bone_index;
+ float bone_head_pos[3];
+
+ void Read(std::istream *stream)
+ {
+ char buffer[20];
+ stream->read(buffer, 20);
+ name = std::string(buffer);
+ stream->read((char*) &parent_bone_index, sizeof(uint16_t));
+ stream->read((char*) &tail_pos_bone_index, sizeof(uint16_t));
+ stream->read((char*) &bone_type, sizeof(uint8_t));
+ stream->read((char*) &ik_parent_bone_index, sizeof(uint16_t));
+ stream->read((char*) &bone_head_pos, sizeof(float) * 3);
+ }
+
+ void ReadExpantion(std::istream *stream)
+ {
+ char buffer[20];
+ stream->read(buffer, 20);
+ name_english = std::string(buffer);
+ }
+ };
+
+ class PmdIk
+ {
+ public:
+ uint16_t ik_bone_index;
+ uint16_t target_bone_index;
+ uint16_t interations;
+ float angle_limit;
+ std::vector<uint16_t> ik_child_bone_index;
+
+ void Read(std::istream *stream)
+ {
+ stream->read((char *) &ik_bone_index, sizeof(uint16_t));
+ stream->read((char *) &target_bone_index, sizeof(uint16_t));
+ uint8_t ik_chain_length;
+ stream->read((char*) &ik_chain_length, sizeof(uint8_t));
+ stream->read((char *) &interations, sizeof(uint16_t));
+ stream->read((char *) &angle_limit, sizeof(float));
+ ik_child_bone_index.resize(ik_chain_length);
+ for (int i = 0; i < ik_chain_length; i++)
+ {
+ stream->read((char *) &ik_child_bone_index[i], sizeof(uint16_t));
+ }
+ }
+ };
+
+ class PmdFaceVertex
+ {
+ public:
+ int vertex_index;
+ float position[3];
+
+ void Read(std::istream *stream)
+ {
+ stream->read((char *) &vertex_index, sizeof(int));
+ stream->read((char *) position, sizeof(float) * 3);
+ }
+ };
+
+ enum class FaceCategory : uint8_t
+ {
+ Base,
+ Eyebrow,
+ Eye,
+ Mouth,
+ Other
+ };
+
+ class PmdFace
+ {
+ public:
+ std::string name;
+ FaceCategory type;
+ std::vector<PmdFaceVertex> vertices;
+ std::string name_english;
+
+ void Read(std::istream *stream)
+ {
+ char buffer[20];
+ stream->read(buffer, 20);
+ name = std::string(buffer);
+ int vertex_count;
+ stream->read((char*) &vertex_count, sizeof(int));
+ stream->read((char*) &type, sizeof(uint8_t));
+ vertices.resize(vertex_count);
+ for (int i = 0; i < vertex_count; i++)
+ {
+ vertices[i].Read(stream);
+ }
+ }
+
+ void ReadExpantion(std::istream *stream)
+ {
+ char buffer[20];
+ stream->read(buffer, 20);
+ name_english = std::string(buffer);
+ }
+ };
+
+ class PmdBoneDispName
+ {
+ public:
+ std::string bone_disp_name;
+ std::string bone_disp_name_english;
+
+ void Read(std::istream *stream)
+ {
+ char buffer[50];
+ stream->read(buffer, 50);
+ bone_disp_name = std::string(buffer);
+ bone_disp_name_english.clear();
+ }
+ void ReadExpantion(std::istream *stream)
+ {
+ char buffer[50];
+ stream->read(buffer, 50);
+ bone_disp_name_english = std::string(buffer);
+ }
+ };
+
+ class PmdBoneDisp
+ {
+ public:
+ uint16_t bone_index;
+ uint8_t bone_disp_index;
+
+ void Read(std::istream *stream)
+ {
+ stream->read((char*) &bone_index, sizeof(uint16_t));
+ stream->read((char*) &bone_disp_index, sizeof(uint8_t));
+ }
+ };
+
+ enum class RigidBodyShape : uint8_t
+ {
+ Sphere = 0,
+ Box = 1,
+ Cpusel = 2
+ };
+
+ enum class RigidBodyType : uint8_t
+ {
+ BoneConnected = 0,
+ Physics = 1,
+ ConnectedPhysics = 2
+ };
+
+ class PmdRigidBody
+ {
+ public:
+ std::string name;
+ uint16_t related_bone_index;
+ uint8_t group_index;
+ uint16_t mask;
+ RigidBodyShape shape;
+ float size[3];
+ float position[3];
+ float orientation[3];
+ float weight;
+ float linear_damping;
+ float anglar_damping;
+ float restitution;
+ float friction;
+ RigidBodyType rigid_type;
+
+ void Read(std::istream *stream)
+ {
+ char buffer[20];
+ stream->read(buffer, sizeof(char) * 20);
+ name = (std::string(buffer));
+ stream->read((char*) &related_bone_index, sizeof(uint16_t));
+ stream->read((char*) &group_index, sizeof(uint8_t));
+ stream->read((char*) &mask, sizeof(uint16_t));
+ stream->read((char*) &shape, sizeof(uint8_t));
+ stream->read((char*) size, sizeof(float) * 3);
+ stream->read((char*) position, sizeof(float) * 3);
+ stream->read((char*) orientation, sizeof(float) * 3);
+ stream->read((char*) &weight, sizeof(float));
+ stream->read((char*) &linear_damping, sizeof(float));
+ stream->read((char*) &anglar_damping, sizeof(float));
+ stream->read((char*) &restitution, sizeof(float));
+ stream->read((char*) &friction, sizeof(float));
+ stream->read((char*) &rigid_type, sizeof(char));
+ }
+ };
+
+ class PmdConstraint
+ {
+ public:
+ std::string name;
+ uint32_t rigid_body_index_a;
+ uint32_t rigid_body_index_b;
+ float position[3];
+ float orientation[3];
+ float linear_lower_limit[3];
+ float linear_upper_limit[3];
+ float angular_lower_limit[3];
+ float angular_upper_limit[3];
+ float linear_stiffness[3];
+ float angular_stiffness[3];
+
+ void Read(std::istream *stream)
+ {
+ char buffer[20];
+ stream->read(buffer, 20);
+ name = std::string(buffer);
+ stream->read((char *) &rigid_body_index_a, sizeof(uint32_t));
+ stream->read((char *) &rigid_body_index_b, sizeof(uint32_t));
+ stream->read((char *) position, sizeof(float) * 3);
+ stream->read((char *) orientation, sizeof(float) * 3);
+ stream->read((char *) linear_lower_limit, sizeof(float) * 3);
+ stream->read((char *) linear_upper_limit, sizeof(float) * 3);
+ stream->read((char *) angular_lower_limit, sizeof(float) * 3);
+ stream->read((char *) angular_upper_limit, sizeof(float) * 3);
+ stream->read((char *) linear_stiffness, sizeof(float) * 3);
+ stream->read((char *) angular_stiffness, sizeof(float) * 3);
+ }
+ };
+
+ class PmdModel
+ {
+ public:
+ float version;
+ PmdHeader header;
+ std::vector<PmdVertex> vertices;
+ std::vector<uint16_t> indices;
+ std::vector<PmdMaterial> materials;
+ std::vector<PmdBone> bones;
+ std::vector<PmdIk> iks;
+ std::vector<PmdFace> faces;
+ std::vector<uint16_t> faces_indices;
+ std::vector<PmdBoneDispName> bone_disp_name;
+ std::vector<PmdBoneDisp> bone_disp;
+ std::vector<std::string> toon_filenames;
+ std::vector<PmdRigidBody> rigid_bodies;
+ std::vector<PmdConstraint> constraints;
+
+ static std::unique_ptr<PmdModel> LoadFromFile(const char *filename)
+ {
+ std::ifstream stream(filename, std::ios::binary);
+ if (stream.fail())
+ {
+ std::cerr << "could not open \"" << filename << "\"" << std::endl;
+ return nullptr;
+ }
+ auto result = LoadFromStream(&stream);
+ stream.close();
+ return result;
+ }
+
+ static std::unique_ptr<PmdModel> LoadFromStream(std::ifstream *stream)
+ {
+ auto result = mmd::make_unique<PmdModel>();
+ char buffer[100];
+
+ // magic
+ char magic[3];
+ stream->read(magic, 3);
+ if (magic[0] != 'P' || magic[1] != 'm' || magic[2] != 'd')
+ {
+ std::cerr << "invalid file" << std::endl;
+ return nullptr;
+ }
+
+ // version
+ stream->read((char*) &(result->version), sizeof(float));
+ if (result ->version != 1.0f)
+ {
+ std::cerr << "invalid version" << std::endl;
+ return nullptr;
+ }
+
+ // header
+ result->header.Read(stream);
+
+ // vertices
+ uint32_t vertex_num;
+ stream->read((char*) &vertex_num, sizeof(uint32_t));
+ result->vertices.resize(vertex_num);
+ for (uint32_t i = 0; i < vertex_num; i++)
+ {
+ result->vertices[i].Read(stream);
+ }
+
+ // indices
+ uint32_t index_num;
+ stream->read((char*) &index_num, sizeof(uint32_t));
+ result->indices.resize(index_num);
+ for (uint32_t i = 0; i < index_num; i++)
+ {
+ stream->read((char*) &result->indices[i], sizeof(uint16_t));
+ }
+
+ // materials
+ uint32_t material_num;
+ stream->read((char*) &material_num, sizeof(uint32_t));
+ result->materials.resize(material_num);
+ for (uint32_t i = 0; i < material_num; i++)
+ {
+ result->materials[i].Read(stream);
+ }
+
+ // bones
+ uint16_t bone_num;
+ stream->read((char*) &bone_num, sizeof(uint16_t));
+ result->bones.resize(bone_num);
+ for (uint32_t i = 0; i < bone_num; i++)
+ {
+ result->bones[i].Read(stream);
+ }
+
+ // iks
+ uint16_t ik_num;
+ stream->read((char*) &ik_num, sizeof(uint16_t));
+ result->iks.resize(ik_num);
+ for (uint32_t i = 0; i < ik_num; i++)
+ {
+ result->iks[i].Read(stream);
+ }
+
+ // faces
+ uint16_t face_num;
+ stream->read((char*) &face_num, sizeof(uint16_t));
+ result->faces.resize(face_num);
+ for (uint32_t i = 0; i < face_num; i++)
+ {
+ result->faces[i].Read(stream);
+ }
+
+ // face frames
+ uint8_t face_frame_num;
+ stream->read((char*) &face_frame_num, sizeof(uint8_t));
+ result->faces_indices.resize(face_frame_num);
+ for (uint32_t i = 0; i < face_frame_num; i++)
+ {
+ stream->read((char*) &result->faces_indices[i], sizeof(uint16_t));
+ }
+
+ // bone names
+ uint8_t bone_disp_num;
+ stream->read((char*) &bone_disp_num, sizeof(uint8_t));
+ result->bone_disp_name.resize(bone_disp_num);
+ for (uint32_t i = 0; i < bone_disp_num; i++)
+ {
+ result->bone_disp_name[i].Read(stream);
+ }
+
+ // bone frame
+ uint32_t bone_frame_num;
+ stream->read((char*) &bone_frame_num, sizeof(uint32_t));
+ result->bone_disp.resize(bone_frame_num);
+ for (uint32_t i = 0; i < bone_frame_num; i++)
+ {
+ result->bone_disp[i].Read(stream);
+ }
+
+ // english name
+ bool english;
+ stream->read((char*) &english, sizeof(char));
+ if (english)
+ {
+ result->header.ReadExtension(stream);
+ for (uint32_t i = 0; i < bone_num; i++)
+ {
+ result->bones[i].ReadExpantion(stream);
+ }
+ for (uint32_t i = 0; i < face_num; i++)
+ {
+ if (result->faces[i].type == pmd::FaceCategory::Base)
+ {
+ continue;
+ }
+ result->faces[i].ReadExpantion(stream);
+ }
+ for (uint32_t i = 0; i < result->bone_disp_name.size(); i++)
+ {
+ result->bone_disp_name[i].ReadExpantion(stream);
+ }
+ }
+
+ // toon textures
+ if (stream->peek() == std::ios::traits_type::eof())
+ {
+ result->toon_filenames.clear();
+ }
+ else {
+ result->toon_filenames.resize(10);
+ for (uint32_t i = 0; i < 10; i++)
+ {
+ stream->read(buffer, 100);
+ result->toon_filenames[i] = std::string(buffer);
+ }
+ }
+
+ // physics
+ if (stream->peek() == std::ios::traits_type::eof())
+ {
+ result->rigid_bodies.clear();
+ result->constraints.clear();
+ }
+ else {
+ uint32_t rigid_body_num;
+ stream->read((char*) &rigid_body_num, sizeof(uint32_t));
+ result->rigid_bodies.resize(rigid_body_num);
+ for (uint32_t i = 0; i < rigid_body_num; i++)
+ {
+ result->rigid_bodies[i].Read(stream);
+ }
+ uint32_t constraint_num;
+ stream->read((char*) &constraint_num, sizeof(uint32_t));
+ result->constraints.resize(constraint_num);
+ for (uint32_t i = 0; i < constraint_num; i++)
+ {
+ result->constraints[i].Read(stream);
+ }
+ }
+
+ if (stream->peek() != std::ios::traits_type::eof())
+ {
+ std::cerr << "there is unknown data" << std::endl;
+ }
+
+ return result;
+ }
+ };
+}
diff --git a/thirdparty/assimp/code/MMDPmxParser.cpp b/thirdparty/assimp/code/MMDPmxParser.cpp
new file mode 100644
index 0000000000..7425ceac22
--- /dev/null
+++ b/thirdparty/assimp/code/MMDPmxParser.cpp
@@ -0,0 +1,604 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+#include <utility>
+#include "MMDPmxParser.h"
+#include <assimp/StringUtils.h>
+#include "../contrib/utf8cpp/source/utf8.h"
+#include <assimp/Exceptional.h>
+
+namespace pmx
+{
+ int ReadIndex(std::istream *stream, int size)
+ {
+ switch (size)
+ {
+ case 1:
+ uint8_t tmp8;
+ stream->read((char*) &tmp8, sizeof(uint8_t));
+ if (255 == tmp8)
+ {
+ return -1;
+ }
+ else {
+ return (int) tmp8;
+ }
+ case 2:
+ uint16_t tmp16;
+ stream->read((char*) &tmp16, sizeof(uint16_t));
+ if (65535 == tmp16)
+ {
+ return -1;
+ }
+ else {
+ return (int) tmp16;
+ }
+ case 4:
+ int tmp32;
+ stream->read((char*) &tmp32, sizeof(int));
+ return tmp32;
+ default:
+ return -1;
+ }
+ }
+
+ std::string ReadString(std::istream *stream, uint8_t encoding)
+ {
+ int size;
+ stream->read((char*) &size, sizeof(int));
+ std::vector<char> buffer;
+ if (size == 0)
+ {
+ return std::string("");
+ }
+ buffer.reserve(size);
+ stream->read((char*) buffer.data(), size);
+ if (encoding == 0)
+ {
+ // UTF16 to UTF8
+ const uint16_t* sourceStart = (uint16_t*)buffer.data();
+ const unsigned int targetSize = size * 3; // enough to encode
+ char *targetStart = new char[targetSize];
+ std::memset(targetStart, 0, targetSize * sizeof(char));
+
+ utf8::utf16to8( sourceStart, sourceStart + size/2, targetStart );
+
+ std::string result(targetStart);
+ delete [] targetStart;
+ return result;
+ }
+ else
+ {
+ // the name is already UTF8
+ return std::string((const char*)buffer.data(), size);
+ }
+ }
+
+ void PmxSetting::Read(std::istream *stream)
+ {
+ uint8_t count;
+ stream->read((char*) &count, sizeof(uint8_t));
+ if (count < 8)
+ {
+ throw DeadlyImportError("MMD: invalid size");
+ }
+ stream->read((char*) &encoding, sizeof(uint8_t));
+ stream->read((char*) &uv, sizeof(uint8_t));
+ stream->read((char*) &vertex_index_size, sizeof(uint8_t));
+ stream->read((char*) &texture_index_size, sizeof(uint8_t));
+ stream->read((char*) &material_index_size, sizeof(uint8_t));
+ stream->read((char*) &bone_index_size, sizeof(uint8_t));
+ stream->read((char*) &morph_index_size, sizeof(uint8_t));
+ stream->read((char*) &rigidbody_index_size, sizeof(uint8_t));
+ uint8_t temp;
+ for (int i = 8; i < count; i++)
+ {
+ stream->read((char*)&temp, sizeof(uint8_t));
+ }
+ }
+
+ void PmxVertexSkinningBDEF1::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->bone_index = ReadIndex(stream, setting->bone_index_size);
+ }
+
+ void PmxVertexSkinningBDEF2::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->bone_index1 = ReadIndex(stream, setting->bone_index_size);
+ this->bone_index2 = ReadIndex(stream, setting->bone_index_size);
+ stream->read((char*) &this->bone_weight, sizeof(float));
+ }
+
+ void PmxVertexSkinningBDEF4::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->bone_index1 = ReadIndex(stream, setting->bone_index_size);
+ this->bone_index2 = ReadIndex(stream, setting->bone_index_size);
+ this->bone_index3 = ReadIndex(stream, setting->bone_index_size);
+ this->bone_index4 = ReadIndex(stream, setting->bone_index_size);
+ stream->read((char*) &this->bone_weight1, sizeof(float));
+ stream->read((char*) &this->bone_weight2, sizeof(float));
+ stream->read((char*) &this->bone_weight3, sizeof(float));
+ stream->read((char*) &this->bone_weight4, sizeof(float));
+ }
+
+ void PmxVertexSkinningSDEF::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->bone_index1 = ReadIndex(stream, setting->bone_index_size);
+ this->bone_index2 = ReadIndex(stream, setting->bone_index_size);
+ stream->read((char*) &this->bone_weight, sizeof(float));
+ stream->read((char*) this->sdef_c, sizeof(float) * 3);
+ stream->read((char*) this->sdef_r0, sizeof(float) * 3);
+ stream->read((char*) this->sdef_r1, sizeof(float) * 3);
+ }
+
+ void PmxVertexSkinningQDEF::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->bone_index1 = ReadIndex(stream, setting->bone_index_size);
+ this->bone_index2 = ReadIndex(stream, setting->bone_index_size);
+ this->bone_index3 = ReadIndex(stream, setting->bone_index_size);
+ this->bone_index4 = ReadIndex(stream, setting->bone_index_size);
+ stream->read((char*) &this->bone_weight1, sizeof(float));
+ stream->read((char*) &this->bone_weight2, sizeof(float));
+ stream->read((char*) &this->bone_weight3, sizeof(float));
+ stream->read((char*) &this->bone_weight4, sizeof(float));
+ }
+
+ void PmxVertex::Read(std::istream *stream, PmxSetting *setting)
+ {
+ stream->read((char*) this->position, sizeof(float) * 3);
+ stream->read((char*) this->normal, sizeof(float) * 3);
+ stream->read((char*) this->uv, sizeof(float) * 2);
+ for (int i = 0; i < setting->uv; ++i)
+ {
+ stream->read((char*) this->uva[i], sizeof(float) * 4);
+ }
+ stream->read((char*) &this->skinning_type, sizeof(PmxVertexSkinningType));
+ switch (this->skinning_type)
+ {
+ case PmxVertexSkinningType::BDEF1:
+ this->skinning = mmd::make_unique<PmxVertexSkinningBDEF1>();
+ break;
+ case PmxVertexSkinningType::BDEF2:
+ this->skinning = mmd::make_unique<PmxVertexSkinningBDEF2>();
+ break;
+ case PmxVertexSkinningType::BDEF4:
+ this->skinning = mmd::make_unique<PmxVertexSkinningBDEF4>();
+ break;
+ case PmxVertexSkinningType::SDEF:
+ this->skinning = mmd::make_unique<PmxVertexSkinningSDEF>();
+ break;
+ case PmxVertexSkinningType::QDEF:
+ this->skinning = mmd::make_unique<PmxVertexSkinningQDEF>();
+ break;
+ default:
+ throw "invalid skinning type";
+ }
+ this->skinning->Read(stream, setting);
+ stream->read((char*) &this->edge, sizeof(float));
+ }
+
+ void PmxMaterial::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->material_name = ReadString(stream, setting->encoding);
+ this->material_english_name = ReadString(stream, setting->encoding);
+ stream->read((char*) this->diffuse, sizeof(float) * 4);
+ stream->read((char*) this->specular, sizeof(float) * 3);
+ stream->read((char*) &this->specularlity, sizeof(float));
+ stream->read((char*) this->ambient, sizeof(float) * 3);
+ stream->read((char*) &this->flag, sizeof(uint8_t));
+ stream->read((char*) this->edge_color, sizeof(float) * 4);
+ stream->read((char*) &this->edge_size, sizeof(float));
+ this->diffuse_texture_index = ReadIndex(stream, setting->texture_index_size);
+ this->sphere_texture_index = ReadIndex(stream, setting->texture_index_size);
+ stream->read((char*) &this->sphere_op_mode, sizeof(uint8_t));
+ stream->read((char*) &this->common_toon_flag, sizeof(uint8_t));
+ if (this->common_toon_flag)
+ {
+ stream->read((char*) &this->toon_texture_index, sizeof(uint8_t));
+ }
+ else {
+ this->toon_texture_index = ReadIndex(stream, setting->texture_index_size);
+ }
+ this->memo = ReadString(stream, setting->encoding);
+ stream->read((char*) &this->index_count, sizeof(int));
+ }
+
+ void PmxIkLink::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->link_target = ReadIndex(stream, setting->bone_index_size);
+ stream->read((char*) &this->angle_lock, sizeof(uint8_t));
+ if (angle_lock == 1)
+ {
+ stream->read((char*) this->max_radian, sizeof(float) * 3);
+ stream->read((char*) this->min_radian, sizeof(float) * 3);
+ }
+ }
+
+ void PmxBone::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->bone_name = ReadString(stream, setting->encoding);
+ this->bone_english_name = ReadString(stream, setting->encoding);
+ stream->read((char*) this->position, sizeof(float) * 3);
+ this->parent_index = ReadIndex(stream, setting->bone_index_size);
+ stream->read((char*) &this->level, sizeof(int));
+ stream->read((char*) &this->bone_flag, sizeof(uint16_t));
+ if (this->bone_flag & 0x0001) {
+ this->target_index = ReadIndex(stream, setting->bone_index_size);
+ }
+ else {
+ stream->read((char*)this->offset, sizeof(float) * 3);
+ }
+ if (this->bone_flag & (0x0100 | 0x0200)) {
+ this->grant_parent_index = ReadIndex(stream, setting->bone_index_size);
+ stream->read((char*) &this->grant_weight, sizeof(float));
+ }
+ if (this->bone_flag & 0x0400) {
+ stream->read((char*)this->lock_axis_orientation, sizeof(float) * 3);
+ }
+ if (this->bone_flag & 0x0800) {
+ stream->read((char*)this->local_axis_x_orientation, sizeof(float) * 3);
+ stream->read((char*)this->local_axis_y_orientation, sizeof(float) * 3);
+ }
+ if (this->bone_flag & 0x2000) {
+ stream->read((char*) &this->key, sizeof(int));
+ }
+ if (this->bone_flag & 0x0020) {
+ this->ik_target_bone_index = ReadIndex(stream, setting->bone_index_size);
+ stream->read((char*) &ik_loop, sizeof(int));
+ stream->read((char*) &ik_loop_angle_limit, sizeof(float));
+ stream->read((char*) &ik_link_count, sizeof(int));
+ this->ik_links = mmd::make_unique<PmxIkLink []>(ik_link_count);
+ for (int i = 0; i < ik_link_count; i++) {
+ ik_links[i].Read(stream, setting);
+ }
+ }
+ }
+
+ void PmxMorphVertexOffset::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->vertex_index = ReadIndex(stream, setting->vertex_index_size);
+ stream->read((char*)this->position_offset, sizeof(float) * 3);
+ }
+
+ void PmxMorphUVOffset::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->vertex_index = ReadIndex(stream, setting->vertex_index_size);
+ stream->read((char*)this->uv_offset, sizeof(float) * 4);
+ }
+
+ void PmxMorphBoneOffset::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->bone_index = ReadIndex(stream, setting->bone_index_size);
+ stream->read((char*)this->translation, sizeof(float) * 3);
+ stream->read((char*)this->rotation, sizeof(float) * 4);
+ }
+
+ void PmxMorphMaterialOffset::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->material_index = ReadIndex(stream, setting->material_index_size);
+ stream->read((char*) &this->offset_operation, sizeof(uint8_t));
+ stream->read((char*)this->diffuse, sizeof(float) * 4);
+ stream->read((char*)this->specular, sizeof(float) * 3);
+ stream->read((char*) &this->specularity, sizeof(float));
+ stream->read((char*)this->ambient, sizeof(float) * 3);
+ stream->read((char*)this->edge_color, sizeof(float) * 4);
+ stream->read((char*) &this->edge_size, sizeof(float));
+ stream->read((char*)this->texture_argb, sizeof(float) * 4);
+ stream->read((char*)this->sphere_texture_argb, sizeof(float) * 4);
+ stream->read((char*)this->toon_texture_argb, sizeof(float) * 4);
+ }
+
+ void PmxMorphGroupOffset::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->morph_index = ReadIndex(stream, setting->morph_index_size);
+ stream->read((char*) &this->morph_weight, sizeof(float));
+ }
+
+ void PmxMorphFlipOffset::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->morph_index = ReadIndex(stream, setting->morph_index_size);
+ stream->read((char*) &this->morph_value, sizeof(float));
+ }
+
+ void PmxMorphImplusOffset::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->rigid_body_index = ReadIndex(stream, setting->rigidbody_index_size);
+ stream->read((char*) &this->is_local, sizeof(uint8_t));
+ stream->read((char*)this->velocity, sizeof(float) * 3);
+ stream->read((char*)this->angular_torque, sizeof(float) * 3);
+ }
+
+ void PmxMorph::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->morph_name = ReadString(stream, setting->encoding);
+ this->morph_english_name = ReadString(stream, setting->encoding);
+ stream->read((char*) &category, sizeof(MorphCategory));
+ stream->read((char*) &morph_type, sizeof(MorphType));
+ stream->read((char*) &this->offset_count, sizeof(int));
+ switch (this->morph_type)
+ {
+ case MorphType::Group:
+ group_offsets = mmd::make_unique<PmxMorphGroupOffset []>(this->offset_count);
+ for (int i = 0; i < offset_count; i++)
+ {
+ group_offsets[i].Read(stream, setting);
+ }
+ break;
+ case MorphType::Vertex:
+ vertex_offsets = mmd::make_unique<PmxMorphVertexOffset []>(this->offset_count);
+ for (int i = 0; i < offset_count; i++)
+ {
+ vertex_offsets[i].Read(stream, setting);
+ }
+ break;
+ case MorphType::Bone:
+ bone_offsets = mmd::make_unique<PmxMorphBoneOffset []>(this->offset_count);
+ for (int i = 0; i < offset_count; i++)
+ {
+ bone_offsets[i].Read(stream, setting);
+ }
+ break;
+ case MorphType::Matrial:
+ material_offsets = mmd::make_unique<PmxMorphMaterialOffset []>(this->offset_count);
+ for (int i = 0; i < offset_count; i++)
+ {
+ material_offsets[i].Read(stream, setting);
+ }
+ break;
+ case MorphType::UV:
+ case MorphType::AdditionalUV1:
+ case MorphType::AdditionalUV2:
+ case MorphType::AdditionalUV3:
+ case MorphType::AdditionalUV4:
+ uv_offsets = mmd::make_unique<PmxMorphUVOffset []>(this->offset_count);
+ for (int i = 0; i < offset_count; i++)
+ {
+ uv_offsets[i].Read(stream, setting);
+ }
+ break;
+ default:
+ throw DeadlyImportError("MMD: unknown morth type");
+ }
+ }
+
+ void PmxFrameElement::Read(std::istream *stream, PmxSetting *setting)
+ {
+ stream->read((char*) &this->element_target, sizeof(uint8_t));
+ if (this->element_target == 0x00)
+ {
+ this->index = ReadIndex(stream, setting->bone_index_size);
+ }
+ else {
+ this->index = ReadIndex(stream, setting->morph_index_size);
+ }
+ }
+
+ void PmxFrame::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->frame_name = ReadString(stream, setting->encoding);
+ this->frame_english_name = ReadString(stream, setting->encoding);
+ stream->read((char*) &this->frame_flag, sizeof(uint8_t));
+ stream->read((char*) &this->element_count, sizeof(int));
+ this->elements = mmd::make_unique<PmxFrameElement []>(this->element_count);
+ for (int i = 0; i < this->element_count; i++)
+ {
+ this->elements[i].Read(stream, setting);
+ }
+ }
+
+ void PmxRigidBody::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->girid_body_name = ReadString(stream, setting->encoding);
+ this->girid_body_english_name = ReadString(stream, setting->encoding);
+ this->target_bone = ReadIndex(stream, setting->bone_index_size);
+ stream->read((char*) &this->group, sizeof(uint8_t));
+ stream->read((char*) &this->mask, sizeof(uint16_t));
+ stream->read((char*) &this->shape, sizeof(uint8_t));
+ stream->read((char*) this->size, sizeof(float) * 3);
+ stream->read((char*) this->position, sizeof(float) * 3);
+ stream->read((char*) this->orientation, sizeof(float) * 3);
+ stream->read((char*) &this->mass, sizeof(float));
+ stream->read((char*) &this->move_attenuation, sizeof(float));
+ stream->read((char*) &this->rotation_attenuation, sizeof(float));
+ stream->read((char*) &this->repulsion, sizeof(float));
+ stream->read((char*) &this->friction, sizeof(float));
+ stream->read((char*) &this->physics_calc_type, sizeof(uint8_t));
+ }
+
+ void PmxJointParam::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->rigid_body1 = ReadIndex(stream, setting->rigidbody_index_size);
+ this->rigid_body2 = ReadIndex(stream, setting->rigidbody_index_size);
+ stream->read((char*) this->position, sizeof(float) * 3);
+ stream->read((char*) this->orientaiton, sizeof(float) * 3);
+ stream->read((char*) this->move_limitation_min, sizeof(float) * 3);
+ stream->read((char*) this->move_limitation_max, sizeof(float) * 3);
+ stream->read((char*) this->rotation_limitation_min, sizeof(float) * 3);
+ stream->read((char*) this->rotation_limitation_max, sizeof(float) * 3);
+ stream->read((char*) this->spring_move_coefficient, sizeof(float) * 3);
+ stream->read((char*) this->spring_rotation_coefficient, sizeof(float) * 3);
+ }
+
+ void PmxJoint::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->joint_name = ReadString(stream, setting->encoding);
+ this->joint_english_name = ReadString(stream, setting->encoding);
+ stream->read((char*) &this->joint_type, sizeof(uint8_t));
+ this->param.Read(stream, setting);
+ }
+
+ void PmxAncherRigidBody::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->related_rigid_body = ReadIndex(stream, setting->rigidbody_index_size);
+ this->related_vertex = ReadIndex(stream, setting->vertex_index_size);
+ stream->read((char*) &this->is_near, sizeof(uint8_t));
+ }
+
+ void PmxSoftBody::Read(std::istream * /*stream*/, PmxSetting * /*setting*/)
+ {
+ std::cerr << "Not Implemented Exception" << std::endl;
+ throw DeadlyImportError("MMD: Not Implemented Exception");
+ }
+
+ void PmxModel::Init()
+ {
+ this->version = 0.0f;
+ this->model_name.clear();
+ this->model_english_name.clear();
+ this->model_comment.clear();
+ this->model_english_comment.clear();
+ this->vertex_count = 0;
+ this->vertices = nullptr;
+ this->index_count = 0;
+ this->indices = nullptr;
+ this->texture_count = 0;
+ this->textures = nullptr;
+ this->material_count = 0;
+ this->materials = nullptr;
+ this->bone_count = 0;
+ this->bones = nullptr;
+ this->morph_count = 0;
+ this->morphs = nullptr;
+ this->frame_count = 0;
+ this->frames = nullptr;
+ this->rigid_body_count = 0;
+ this->rigid_bodies = nullptr;
+ this->joint_count = 0;
+ this->joints = nullptr;
+ this->soft_body_count = 0;
+ this->soft_bodies = nullptr;
+ }
+
+ void PmxModel::Read(std::istream *stream)
+ {
+ char magic[4];
+ stream->read((char*) magic, sizeof(char) * 4);
+ if (magic[0] != 0x50 || magic[1] != 0x4d || magic[2] != 0x58 || magic[3] != 0x20)
+ {
+ std::cerr << "invalid magic number." << std::endl;
+ throw DeadlyImportError("MMD: invalid magic number.");
+ }
+ stream->read((char*) &version, sizeof(float));
+ if (version != 2.0f && version != 2.1f)
+ {
+ std::cerr << "this is not ver2.0 or ver2.1 but " << version << "." << std::endl;
+ throw DeadlyImportError("MMD: this is not ver2.0 or ver2.1 but " + to_string(version));
+ }
+ this->setting.Read(stream);
+
+ this->model_name = ReadString(stream, setting.encoding);
+ this->model_english_name = ReadString(stream, setting.encoding);
+ this->model_comment = ReadString(stream, setting.encoding);
+ this->model_english_comment = ReadString(stream, setting.encoding);
+
+ // read vertices
+ stream->read((char*) &vertex_count, sizeof(int));
+ this->vertices = mmd::make_unique<PmxVertex []>(vertex_count);
+ for (int i = 0; i < vertex_count; i++)
+ {
+ vertices[i].Read(stream, &setting);
+ }
+
+ // read indices
+ stream->read((char*) &index_count, sizeof(int));
+ this->indices = mmd::make_unique<int []>(index_count);
+ for (int i = 0; i < index_count; i++)
+ {
+ this->indices[i] = ReadIndex(stream, setting.vertex_index_size);
+ }
+
+ // read texture names
+ stream->read((char*) &texture_count, sizeof(int));
+ this->textures = mmd::make_unique<std::string []>(texture_count);
+ for (int i = 0; i < texture_count; i++)
+ {
+ this->textures[i] = ReadString(stream, setting.encoding);
+ }
+
+ // read materials
+ stream->read((char*) &material_count, sizeof(int));
+ this->materials = mmd::make_unique<PmxMaterial []>(material_count);
+ for (int i = 0; i < material_count; i++)
+ {
+ this->materials[i].Read(stream, &setting);
+ }
+
+ // read bones
+ stream->read((char*) &this->bone_count, sizeof(int));
+ this->bones = mmd::make_unique<PmxBone []>(this->bone_count);
+ for (int i = 0; i < this->bone_count; i++)
+ {
+ this->bones[i].Read(stream, &setting);
+ }
+
+ // read morphs
+ stream->read((char*) &this->morph_count, sizeof(int));
+ this->morphs = mmd::make_unique<PmxMorph []>(this->morph_count);
+ for (int i = 0; i < this->morph_count; i++)
+ {
+ this->morphs[i].Read(stream, &setting);
+ }
+
+ // read display frames
+ stream->read((char*) &this->frame_count, sizeof(int));
+ this->frames = mmd::make_unique<PmxFrame []>(this->frame_count);
+ for (int i = 0; i < this->frame_count; i++)
+ {
+ this->frames[i].Read(stream, &setting);
+ }
+
+ // read rigid bodies
+ stream->read((char*) &this->rigid_body_count, sizeof(int));
+ this->rigid_bodies = mmd::make_unique<PmxRigidBody []>(this->rigid_body_count);
+ for (int i = 0; i < this->rigid_body_count; i++)
+ {
+ this->rigid_bodies[i].Read(stream, &setting);
+ }
+
+ // read joints
+ stream->read((char*) &this->joint_count, sizeof(int));
+ this->joints = mmd::make_unique<PmxJoint []>(this->joint_count);
+ for (int i = 0; i < this->joint_count; i++)
+ {
+ this->joints[i].Read(stream, &setting);
+ }
+ }
+}
diff --git a/thirdparty/assimp/code/MMDPmxParser.h b/thirdparty/assimp/code/MMDPmxParser.h
new file mode 100644
index 0000000000..cf523a1298
--- /dev/null
+++ b/thirdparty/assimp/code/MMDPmxParser.h
@@ -0,0 +1,782 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+#pragma once
+
+#include <vector>
+#include <string>
+#include <iostream>
+#include <fstream>
+#include <memory>
+#include "MMDCpp14.h"
+
+namespace pmx
+{
+ class PmxSetting
+ {
+ public:
+ PmxSetting()
+ : encoding(0)
+ , uv(0)
+ , vertex_index_size(0)
+ , texture_index_size(0)
+ , material_index_size(0)
+ , bone_index_size(0)
+ , morph_index_size(0)
+ , rigidbody_index_size(0)
+ {}
+
+ uint8_t encoding;
+ uint8_t uv;
+ uint8_t vertex_index_size;
+ uint8_t texture_index_size;
+ uint8_t material_index_size;
+ uint8_t bone_index_size;
+ uint8_t morph_index_size;
+ uint8_t rigidbody_index_size;
+ void Read(std::istream *stream);
+ };
+
+ enum class PmxVertexSkinningType : uint8_t
+ {
+ BDEF1 = 0,
+ BDEF2 = 1,
+ BDEF4 = 2,
+ SDEF = 3,
+ QDEF = 4,
+ };
+
+ class PmxVertexSkinning
+ {
+ public:
+ virtual void Read(std::istream *stream, PmxSetting *setting) = 0;
+ virtual ~PmxVertexSkinning() {}
+ };
+
+ class PmxVertexSkinningBDEF1 : public PmxVertexSkinning
+ {
+ public:
+ PmxVertexSkinningBDEF1()
+ : bone_index(0)
+ {}
+
+ int bone_index;
+ void Read(std::istream *stresam, PmxSetting *setting);
+ };
+
+ class PmxVertexSkinningBDEF2 : public PmxVertexSkinning
+ {
+ public:
+ PmxVertexSkinningBDEF2()
+ : bone_index1(0)
+ , bone_index2(0)
+ , bone_weight(0.0f)
+ {}
+
+ int bone_index1;
+ int bone_index2;
+ float bone_weight;
+ void Read(std::istream *stresam, PmxSetting *setting);
+ };
+
+ class PmxVertexSkinningBDEF4 : public PmxVertexSkinning
+ {
+ public:
+ PmxVertexSkinningBDEF4()
+ : bone_index1(0)
+ , bone_index2(0)
+ , bone_index3(0)
+ , bone_index4(0)
+ , bone_weight1(0.0f)
+ , bone_weight2(0.0f)
+ , bone_weight3(0.0f)
+ , bone_weight4(0.0f)
+ {}
+
+ int bone_index1;
+ int bone_index2;
+ int bone_index3;
+ int bone_index4;
+ float bone_weight1;
+ float bone_weight2;
+ float bone_weight3;
+ float bone_weight4;
+ void Read(std::istream *stresam, PmxSetting *setting);
+ };
+
+ class PmxVertexSkinningSDEF : public PmxVertexSkinning
+ {
+ public:
+ PmxVertexSkinningSDEF()
+ : bone_index1(0)
+ , bone_index2(0)
+ , bone_weight(0.0f)
+ {
+ for (int i = 0; i < 3; ++i) {
+ sdef_c[i] = 0.0f;
+ sdef_r0[i] = 0.0f;
+ sdef_r1[i] = 0.0f;
+ }
+ }
+
+ int bone_index1;
+ int bone_index2;
+ float bone_weight;
+ float sdef_c[3];
+ float sdef_r0[3];
+ float sdef_r1[3];
+ void Read(std::istream *stresam, PmxSetting *setting);
+ };
+
+ class PmxVertexSkinningQDEF : public PmxVertexSkinning
+ {
+ public:
+ PmxVertexSkinningQDEF()
+ : bone_index1(0)
+ , bone_index2(0)
+ , bone_index3(0)
+ , bone_index4(0)
+ , bone_weight1(0.0f)
+ , bone_weight2(0.0f)
+ , bone_weight3(0.0f)
+ , bone_weight4(0.0f)
+ {}
+
+ int bone_index1;
+ int bone_index2;
+ int bone_index3;
+ int bone_index4;
+ float bone_weight1;
+ float bone_weight2;
+ float bone_weight3;
+ float bone_weight4;
+ void Read(std::istream *stresam, PmxSetting *setting);
+ };
+
+ class PmxVertex
+ {
+ public:
+ PmxVertex()
+ : edge(0.0f)
+ {
+ uv[0] = uv[1] = 0.0f;
+ for (int i = 0; i < 3; ++i) {
+ position[i] = 0.0f;
+ normal[i] = 0.0f;
+ }
+ for (int i = 0; i < 4; ++i) {
+ for (int k = 0; k < 4; ++k) {
+ uva[i][k] = 0.0f;
+ }
+ }
+ }
+
+ float position[3];
+ float normal[3];
+ float uv[2];
+ float uva[4][4];
+ PmxVertexSkinningType skinning_type;
+ std::unique_ptr<PmxVertexSkinning> skinning;
+ float edge;
+ void Read(std::istream *stream, PmxSetting *setting);
+ };
+
+ class PmxMaterial
+ {
+ public:
+ PmxMaterial()
+ : specularlity(0.0f)
+ , flag(0)
+ , edge_size(0.0f)
+ , diffuse_texture_index(0)
+ , sphere_texture_index(0)
+ , sphere_op_mode(0)
+ , common_toon_flag(0)
+ , toon_texture_index(0)
+ , index_count(0)
+ {
+ for (int i = 0; i < 3; ++i) {
+ specular[i] = 0.0f;
+ ambient[i] = 0.0f;
+ edge_color[i] = 0.0f;
+ }
+ for (int i = 0; i < 4; ++i) {
+ diffuse[i] = 0.0f;
+ }
+ }
+
+ std::string material_name;
+ std::string material_english_name;
+ float diffuse[4];
+ float specular[3];
+ float specularlity;
+ float ambient[3];
+ uint8_t flag;
+ float edge_color[4];
+ float edge_size;
+ int diffuse_texture_index;
+ int sphere_texture_index;
+ uint8_t sphere_op_mode;
+ uint8_t common_toon_flag;
+ int toon_texture_index;
+ std::string memo;
+ int index_count;
+ void Read(std::istream *stream, PmxSetting *setting);
+ };
+
+ class PmxIkLink
+ {
+ public:
+ PmxIkLink()
+ : link_target(0)
+ , angle_lock(0)
+ {
+ for (int i = 0; i < 3; ++i) {
+ max_radian[i] = 0.0f;
+ min_radian[i] = 0.0f;
+ }
+ }
+
+ int link_target;
+ uint8_t angle_lock;
+ float max_radian[3];
+ float min_radian[3];
+ void Read(std::istream *stream, PmxSetting *settingn);
+ };
+
+ class PmxBone
+ {
+ public:
+ PmxBone()
+ : parent_index(0)
+ , level(0)
+ , bone_flag(0)
+ , target_index(0)
+ , grant_parent_index(0)
+ , grant_weight(0.0f)
+ , key(0)
+ , ik_target_bone_index(0)
+ , ik_loop(0)
+ , ik_loop_angle_limit(0.0f)
+ , ik_link_count(0)
+ {
+ for (int i = 0; i < 3; ++i) {
+ position[i] = 0.0f;
+ offset[i] = 0.0f;
+ lock_axis_orientation[i] = 0.0f;
+ local_axis_x_orientation[i] = 0.0f;
+ local_axis_y_orientation[i] = 0.0f;
+ }
+ }
+
+ std::string bone_name;
+ std::string bone_english_name;
+ float position[3];
+ int parent_index;
+ int level;
+ uint16_t bone_flag;
+ float offset[3];
+ int target_index;
+ int grant_parent_index;
+ float grant_weight;
+ float lock_axis_orientation[3];
+ float local_axis_x_orientation[3];
+ float local_axis_y_orientation[3];
+ int key;
+ int ik_target_bone_index;
+ int ik_loop;
+ float ik_loop_angle_limit;
+ int ik_link_count;
+ std::unique_ptr<PmxIkLink []> ik_links;
+ void Read(std::istream *stream, PmxSetting *setting);
+ };
+
+ enum class MorphType : uint8_t
+ {
+ Group = 0,
+ Vertex = 1,
+ Bone = 2,
+ UV = 3,
+ AdditionalUV1 = 4,
+ AdditionalUV2 = 5,
+ AdditionalUV3 = 6,
+ AdditionalUV4 = 7,
+ Matrial = 8,
+ Flip = 9,
+ Implus = 10,
+ };
+
+ enum class MorphCategory : uint8_t
+ {
+ ReservedCategory = 0,
+ Eyebrow = 1,
+ Eye = 2,
+ Mouth = 3,
+ Other = 4,
+ };
+
+ class PmxMorphOffset
+ {
+ public:
+ void virtual Read(std::istream *stream, PmxSetting *setting) = 0;
+ };
+
+ class PmxMorphVertexOffset : public PmxMorphOffset
+ {
+ public:
+ PmxMorphVertexOffset()
+ : vertex_index(0)
+ {
+ for (int i = 0; i < 3; ++i) {
+ position_offset[i] = 0.0f;
+ }
+ }
+ int vertex_index;
+ float position_offset[3];
+ void Read(std::istream *stream, PmxSetting *setting); //override;
+ };
+
+ class PmxMorphUVOffset : public PmxMorphOffset
+ {
+ public:
+ PmxMorphUVOffset()
+ : vertex_index(0)
+ {
+ for (int i = 0; i < 4; ++i) {
+ uv_offset[i] = 0.0f;
+ }
+ }
+ int vertex_index;
+ float uv_offset[4];
+ void Read(std::istream *stream, PmxSetting *setting); //override;
+ };
+
+ class PmxMorphBoneOffset : public PmxMorphOffset
+ {
+ public:
+ PmxMorphBoneOffset()
+ : bone_index(0)
+ {
+ for (int i = 0; i < 3; ++i) {
+ translation[i] = 0.0f;
+ }
+ for (int i = 0; i < 4; ++i) {
+ rotation[i] = 0.0f;
+ }
+ }
+ int bone_index;
+ float translation[3];
+ float rotation[4];
+ void Read(std::istream *stream, PmxSetting *setting); //override;
+ };
+
+ class PmxMorphMaterialOffset : public PmxMorphOffset
+ {
+ public:
+ PmxMorphMaterialOffset()
+ : specularity(0.0f)
+ , edge_size(0.0f)
+ {
+ for (int i = 0; i < 3; ++i) {
+ specular[i] = 0.0f;
+ ambient[i] = 0.0f;
+ }
+ for (int i = 0; i < 4; ++i) {
+ diffuse[i] = 0.0f;
+ edge_color[i] = 0.0f;
+ texture_argb[i] = 0.0f;
+ sphere_texture_argb[i] = 0.0f;
+ toon_texture_argb[i] = 0.0f;
+ }
+ }
+ int material_index;
+ uint8_t offset_operation;
+ float diffuse[4];
+ float specular[3];
+ float specularity;
+ float ambient[3];
+ float edge_color[4];
+ float edge_size;
+ float texture_argb[4];
+ float sphere_texture_argb[4];
+ float toon_texture_argb[4];
+ void Read(std::istream *stream, PmxSetting *setting); //override;
+ };
+
+ class PmxMorphGroupOffset : public PmxMorphOffset
+ {
+ public:
+ PmxMorphGroupOffset()
+ : morph_index(0)
+ , morph_weight(0.0f)
+ {}
+ int morph_index;
+ float morph_weight;
+ void Read(std::istream *stream, PmxSetting *setting); //override;
+ };
+
+ class PmxMorphFlipOffset : public PmxMorphOffset
+ {
+ public:
+ PmxMorphFlipOffset()
+ : morph_index(0)
+ , morph_value(0.0f)
+ {}
+ int morph_index;
+ float morph_value;
+ void Read(std::istream *stream, PmxSetting *setting); //override;
+ };
+
+ class PmxMorphImplusOffset : public PmxMorphOffset
+ {
+ public:
+ PmxMorphImplusOffset()
+ : rigid_body_index(0)
+ , is_local(0)
+ {
+ for (int i = 0; i < 3; ++i) {
+ velocity[i] = 0.0f;
+ angular_torque[i] = 0.0f;
+ }
+ }
+ int rigid_body_index;
+ uint8_t is_local;
+ float velocity[3];
+ float angular_torque[3];
+ void Read(std::istream *stream, PmxSetting *setting); //override;
+ };
+
+ class PmxMorph
+ {
+ public:
+ PmxMorph()
+ : offset_count(0)
+ {
+ }
+ std::string morph_name;
+ std::string morph_english_name;
+ MorphCategory category;
+ MorphType morph_type;
+ int offset_count;
+ std::unique_ptr<PmxMorphVertexOffset []> vertex_offsets;
+ std::unique_ptr<PmxMorphUVOffset []> uv_offsets;
+ std::unique_ptr<PmxMorphBoneOffset []> bone_offsets;
+ std::unique_ptr<PmxMorphMaterialOffset []> material_offsets;
+ std::unique_ptr<PmxMorphGroupOffset []> group_offsets;
+ std::unique_ptr<PmxMorphFlipOffset []> flip_offsets;
+ std::unique_ptr<PmxMorphImplusOffset []> implus_offsets;
+ void Read(std::istream *stream, PmxSetting *setting);
+ };
+
+ class PmxFrameElement
+ {
+ public:
+ PmxFrameElement()
+ : element_target(0)
+ , index(0)
+ {
+ }
+ uint8_t element_target;
+ int index;
+ void Read(std::istream *stream, PmxSetting *setting);
+ };
+
+ class PmxFrame
+ {
+ public:
+ PmxFrame()
+ : frame_flag(0)
+ , element_count(0)
+ {
+ }
+ std::string frame_name;
+ std::string frame_english_name;
+ uint8_t frame_flag;
+ int element_count;
+ std::unique_ptr<PmxFrameElement []> elements;
+ void Read(std::istream *stream, PmxSetting *setting);
+ };
+
+ class PmxRigidBody
+ {
+ public:
+ PmxRigidBody()
+ : target_bone(0)
+ , group(0)
+ , mask(0)
+ , shape(0)
+ , mass(0.0f)
+ , move_attenuation(0.0f)
+ , rotation_attenuation(0.0f)
+ , repulsion(0.0f)
+ , friction(0.0f)
+ , physics_calc_type(0)
+ {
+ for (int i = 0; i < 3; ++i) {
+ size[i] = 0.0f;
+ position[i] = 0.0f;
+ orientation[i] = 0.0f;
+ }
+ }
+ std::string girid_body_name;
+ std::string girid_body_english_name;
+ int target_bone;
+ uint8_t group;
+ uint16_t mask;
+ uint8_t shape;
+ float size[3];
+ float position[3];
+ float orientation[3];
+ float mass;
+ float move_attenuation;
+ float rotation_attenuation;
+ float repulsion;
+ float friction;
+ uint8_t physics_calc_type;
+ void Read(std::istream *stream, PmxSetting *setting);
+ };
+
+ enum class PmxJointType : uint8_t
+ {
+ Generic6DofSpring = 0,
+ Generic6Dof = 1,
+ Point2Point = 2,
+ ConeTwist = 3,
+ Slider = 5,
+ Hinge = 6
+ };
+
+ class PmxJointParam
+ {
+ public:
+ PmxJointParam()
+ : rigid_body1(0)
+ , rigid_body2(0)
+ {
+ for (int i = 0; i < 3; ++i) {
+ position[i] = 0.0f;
+ orientaiton[i] = 0.0f;
+ move_limitation_min[i] = 0.0f;
+ move_limitation_max[i] = 0.0f;
+ rotation_limitation_min[i] = 0.0f;
+ rotation_limitation_max[i] = 0.0f;
+ spring_move_coefficient[i] = 0.0f;
+ spring_rotation_coefficient[i] = 0.0f;
+ }
+ }
+ int rigid_body1;
+ int rigid_body2;
+ float position[3];
+ float orientaiton[3];
+ float move_limitation_min[3];
+ float move_limitation_max[3];
+ float rotation_limitation_min[3];
+ float rotation_limitation_max[3];
+ float spring_move_coefficient[3];
+ float spring_rotation_coefficient[3];
+ void Read(std::istream *stream, PmxSetting *setting);
+ };
+
+ class PmxJoint
+ {
+ public:
+ std::string joint_name;
+ std::string joint_english_name;
+ PmxJointType joint_type;
+ PmxJointParam param;
+ void Read(std::istream *stream, PmxSetting *setting);
+ };
+
+ enum PmxSoftBodyFlag : uint8_t
+ {
+ BLink = 0x01,
+ Cluster = 0x02,
+ Link = 0x04
+ };
+
+ class PmxAncherRigidBody
+ {
+ public:
+ PmxAncherRigidBody()
+ : related_rigid_body(0)
+ , related_vertex(0)
+ , is_near(false)
+ {}
+ int related_rigid_body;
+ int related_vertex;
+ bool is_near;
+ void Read(std::istream *stream, PmxSetting *setting);
+ };
+
+ class PmxSoftBody
+ {
+ public:
+ PmxSoftBody()
+ : shape(0)
+ , target_material(0)
+ , group(0)
+ , mask(0)
+ , blink_distance(0)
+ , cluster_count(0)
+ , mass(0.0)
+ , collisioni_margin(0.0)
+ , aero_model(0)
+ , VCF(0.0f)
+ , DP(0.0f)
+ , DG(0.0f)
+ , LF(0.0f)
+ , PR(0.0f)
+ , VC(0.0f)
+ , DF(0.0f)
+ , MT(0.0f)
+ , CHR(0.0f)
+ , KHR(0.0f)
+ , SHR(0.0f)
+ , AHR(0.0f)
+ , SRHR_CL(0.0f)
+ , SKHR_CL(0.0f)
+ , SSHR_CL(0.0f)
+ , SR_SPLT_CL(0.0f)
+ , SK_SPLT_CL(0.0f)
+ , SS_SPLT_CL(0.0f)
+ , V_IT(0)
+ , P_IT(0)
+ , D_IT(0)
+ , C_IT(0)
+ , LST(0.0f)
+ , AST(0.0f)
+ , VST(0.0f)
+ , anchor_count(0)
+ , pin_vertex_count(0)
+ {}
+ std::string soft_body_name;
+ std::string soft_body_english_name;
+ uint8_t shape;
+ int target_material;
+ uint8_t group;
+ uint16_t mask;
+ PmxSoftBodyFlag flag;
+ int blink_distance;
+ int cluster_count;
+ float mass;
+ float collisioni_margin;
+ int aero_model;
+ float VCF;
+ float DP;
+ float DG;
+ float LF;
+ float PR;
+ float VC;
+ float DF;
+ float MT;
+ float CHR;
+ float KHR;
+ float SHR;
+ float AHR;
+ float SRHR_CL;
+ float SKHR_CL;
+ float SSHR_CL;
+ float SR_SPLT_CL;
+ float SK_SPLT_CL;
+ float SS_SPLT_CL;
+ int V_IT;
+ int P_IT;
+ int D_IT;
+ int C_IT;
+ float LST;
+ float AST;
+ float VST;
+ int anchor_count;
+ std::unique_ptr<PmxAncherRigidBody []> anchers;
+ int pin_vertex_count;
+ std::unique_ptr<int []> pin_vertices;
+ void Read(std::istream *stream, PmxSetting *setting);
+ };
+
+ class PmxModel
+ {
+ public:
+ PmxModel()
+ : version(0.0f)
+ , vertex_count(0)
+ , index_count(0)
+ , texture_count(0)
+ , material_count(0)
+ , bone_count(0)
+ , morph_count(0)
+ , frame_count(0)
+ , rigid_body_count(0)
+ , joint_count(0)
+ , soft_body_count(0)
+ {}
+
+ float version;
+ PmxSetting setting;
+ std::string model_name;
+ std::string model_english_name;
+ std::string model_comment;
+ std::string model_english_comment;
+ int vertex_count;
+ std::unique_ptr<PmxVertex []> vertices;
+ int index_count;
+ std::unique_ptr<int []> indices;
+ int texture_count;
+ std::unique_ptr< std::string []> textures;
+ int material_count;
+ std::unique_ptr<PmxMaterial []> materials;
+ int bone_count;
+ std::unique_ptr<PmxBone []> bones;
+ int morph_count;
+ std::unique_ptr<PmxMorph []> morphs;
+ int frame_count;
+ std::unique_ptr<PmxFrame [] > frames;
+ int rigid_body_count;
+ std::unique_ptr<PmxRigidBody []> rigid_bodies;
+ int joint_count;
+ std::unique_ptr<PmxJoint []> joints;
+ int soft_body_count;
+ std::unique_ptr<PmxSoftBody []> soft_bodies;
+ void Init();
+ void Read(std::istream *stream);
+ //static std::unique_ptr<PmxModel> ReadFromFile(const char *filename);
+ //static std::unique_ptr<PmxModel> ReadFromStream(std::istream *stream);
+ };
+}
diff --git a/thirdparty/assimp/code/MMDVmdParser.h b/thirdparty/assimp/code/MMDVmdParser.h
new file mode 100644
index 0000000000..947c3a2422
--- /dev/null
+++ b/thirdparty/assimp/code/MMDVmdParser.h
@@ -0,0 +1,376 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+#pragma once
+
+#include <vector>
+#include <string>
+#include <memory>
+#include <iostream>
+#include <fstream>
+#include <ostream>
+#include "MMDCpp14.h"
+
+namespace vmd
+{
+ class VmdBoneFrame
+ {
+ public:
+ std::string name;
+ int frame;
+ float position[3];
+ float orientation[4];
+ char interpolation[4][4][4];
+
+ void Read(std::istream* stream)
+ {
+ char buffer[15];
+ stream->read((char*) buffer, sizeof(char)*15);
+ name = std::string(buffer);
+ stream->read((char*) &frame, sizeof(int));
+ stream->read((char*) position, sizeof(float)*3);
+ stream->read((char*) orientation, sizeof(float)*4);
+ stream->read((char*) interpolation, sizeof(char) * 4 * 4 * 4);
+ }
+
+ void Write(std::ostream* stream)
+ {
+ stream->write((char*)name.c_str(), sizeof(char) * 15);
+ stream->write((char*)&frame, sizeof(int));
+ stream->write((char*)position, sizeof(float) * 3);
+ stream->write((char*)orientation, sizeof(float) * 4);
+ stream->write((char*)interpolation, sizeof(char) * 4 * 4 * 4);
+ }
+ };
+
+ class VmdFaceFrame
+ {
+ public:
+ std::string face_name;
+ float weight;
+ uint32_t frame;
+
+ void Read(std::istream* stream)
+ {
+ char buffer[15];
+ stream->read((char*) &buffer, sizeof(char) * 15);
+ face_name = std::string(buffer);
+ stream->read((char*) &frame, sizeof(int));
+ stream->read((char*) &weight, sizeof(float));
+ }
+
+ void Write(std::ostream* stream)
+ {
+ stream->write((char*)face_name.c_str(), sizeof(char) * 15);
+ stream->write((char*)&frame, sizeof(int));
+ stream->write((char*)&weight, sizeof(float));
+ }
+ };
+
+ class VmdCameraFrame
+ {
+ public:
+ int frame;
+ float distance;
+ float position[3];
+ float orientation[3];
+ char interpolation[6][4];
+ float angle;
+ char unknown[3];
+
+ void Read(std::istream *stream)
+ {
+ stream->read((char*) &frame, sizeof(int));
+ stream->read((char*) &distance, sizeof(float));
+ stream->read((char*) position, sizeof(float) * 3);
+ stream->read((char*) orientation, sizeof(float) * 3);
+ stream->read((char*) interpolation, sizeof(char) * 24);
+ stream->read((char*) &angle, sizeof(float));
+ stream->read((char*) unknown, sizeof(char) * 3);
+ }
+
+ void Write(std::ostream *stream)
+ {
+ stream->write((char*)&frame, sizeof(int));
+ stream->write((char*)&distance, sizeof(float));
+ stream->write((char*)position, sizeof(float) * 3);
+ stream->write((char*)orientation, sizeof(float) * 3);
+ stream->write((char*)interpolation, sizeof(char) * 24);
+ stream->write((char*)&angle, sizeof(float));
+ stream->write((char*)unknown, sizeof(char) * 3);
+ }
+ };
+
+ class VmdLightFrame
+ {
+ public:
+ int frame;
+ float color[3];
+ float position[3];
+
+ void Read(std::istream* stream)
+ {
+ stream->read((char*) &frame, sizeof(int));
+ stream->read((char*) color, sizeof(float) * 3);
+ stream->read((char*) position, sizeof(float) * 3);
+ }
+
+ void Write(std::ostream* stream)
+ {
+ stream->write((char*)&frame, sizeof(int));
+ stream->write((char*)color, sizeof(float) * 3);
+ stream->write((char*)position, sizeof(float) * 3);
+ }
+ };
+
+ class VmdIkEnable
+ {
+ public:
+ std::string ik_name;
+ bool enable;
+ };
+
+ class VmdIkFrame
+ {
+ public:
+ int frame;
+ bool display;
+ std::vector<VmdIkEnable> ik_enable;
+
+ void Read(std::istream *stream)
+ {
+ char buffer[20];
+ stream->read((char*) &frame, sizeof(int));
+ stream->read((char*) &display, sizeof(uint8_t));
+ int ik_count;
+ stream->read((char*) &ik_count, sizeof(int));
+ ik_enable.resize(ik_count);
+ for (int i = 0; i < ik_count; i++)
+ {
+ stream->read(buffer, 20);
+ ik_enable[i].ik_name = std::string(buffer);
+ stream->read((char*) &ik_enable[i].enable, sizeof(uint8_t));
+ }
+ }
+
+ void Write(std::ostream *stream)
+ {
+ stream->write((char*)&frame, sizeof(int));
+ stream->write((char*)&display, sizeof(uint8_t));
+ int ik_count = static_cast<int>(ik_enable.size());
+ stream->write((char*)&ik_count, sizeof(int));
+ for (int i = 0; i < ik_count; i++)
+ {
+ const VmdIkEnable& ik_enable = this->ik_enable.at(i);
+ stream->write(ik_enable.ik_name.c_str(), 20);
+ stream->write((char*)&ik_enable.enable, sizeof(uint8_t));
+ }
+ }
+ };
+
+ class VmdMotion
+ {
+ public:
+ std::string model_name;
+ int version;
+ std::vector<VmdBoneFrame> bone_frames;
+ std::vector<VmdFaceFrame> face_frames;
+ std::vector<VmdCameraFrame> camera_frames;
+ std::vector<VmdLightFrame> light_frames;
+ std::vector<VmdIkFrame> ik_frames;
+
+ static std::unique_ptr<VmdMotion> LoadFromFile(char const *filename)
+ {
+ std::ifstream stream(filename, std::ios::binary);
+ auto result = LoadFromStream(&stream);
+ stream.close();
+ return result;
+ }
+
+ static std::unique_ptr<VmdMotion> LoadFromStream(std::ifstream *stream)
+ {
+
+ char buffer[30];
+ auto result = mmd::make_unique<VmdMotion>();
+
+ // magic and version
+ stream->read((char*) buffer, 30);
+ if (strncmp(buffer, "Vocaloid Motion Data", 20))
+ {
+ std::cerr << "invalid vmd file." << std::endl;
+ return nullptr;
+ }
+ result->version = std::atoi(buffer + 20);
+
+ // name
+ stream->read(buffer, 20);
+ result->model_name = std::string(buffer);
+
+ // bone frames
+ int bone_frame_num;
+ stream->read((char*) &bone_frame_num, sizeof(int));
+ result->bone_frames.resize(bone_frame_num);
+ for (int i = 0; i < bone_frame_num; i++)
+ {
+ result->bone_frames[i].Read(stream);
+ }
+
+ // face frames
+ int face_frame_num;
+ stream->read((char*) &face_frame_num, sizeof(int));
+ result->face_frames.resize(face_frame_num);
+ for (int i = 0; i < face_frame_num; i++)
+ {
+ result->face_frames[i].Read(stream);
+ }
+
+ // camera frames
+ int camera_frame_num;
+ stream->read((char*) &camera_frame_num, sizeof(int));
+ result->camera_frames.resize(camera_frame_num);
+ for (int i = 0; i < camera_frame_num; i++)
+ {
+ result->camera_frames[i].Read(stream);
+ }
+
+ // light frames
+ int light_frame_num;
+ stream->read((char*) &light_frame_num, sizeof(int));
+ result->light_frames.resize(light_frame_num);
+ for (int i = 0; i < light_frame_num; i++)
+ {
+ result->light_frames[i].Read(stream);
+ }
+
+ // unknown2
+ stream->read(buffer, 4);
+
+ // ik frames
+ if (stream->peek() != std::ios::traits_type::eof())
+ {
+ int ik_num;
+ stream->read((char*) &ik_num, sizeof(int));
+ result->ik_frames.resize(ik_num);
+ for (int i = 0; i < ik_num; i++)
+ {
+ result->ik_frames[i].Read(stream);
+ }
+ }
+
+ if (stream->peek() != std::ios::traits_type::eof())
+ {
+ std::cerr << "vmd stream has unknown data." << std::endl;
+ }
+
+ return result;
+ }
+
+ bool SaveToFile(const std::u16string& /*filename*/)
+ {
+ // TODO: How to adapt u16string to string?
+ /*
+ std::ofstream stream(filename.c_str(), std::ios::binary);
+ auto result = SaveToStream(&stream);
+ stream.close();
+ return result;
+ */
+ return false;
+ }
+
+ bool SaveToStream(std::ofstream *stream)
+ {
+ std::string magic = "Vocaloid Motion Data 0002\0";
+ magic.resize(30);
+
+ // magic and version
+ stream->write(magic.c_str(), 30);
+
+ // name
+ stream->write(model_name.c_str(), 20);
+
+ // bone frames
+ const int bone_frame_num = static_cast<int>(bone_frames.size());
+ stream->write(reinterpret_cast<const char*>(&bone_frame_num), sizeof(int));
+ for (int i = 0; i < bone_frame_num; i++)
+ {
+ bone_frames[i].Write(stream);
+ }
+
+ // face frames
+ const int face_frame_num = static_cast<int>(face_frames.size());
+ stream->write(reinterpret_cast<const char*>(&face_frame_num), sizeof(int));
+ for (int i = 0; i < face_frame_num; i++)
+ {
+ face_frames[i].Write(stream);
+ }
+
+ // camera frames
+ const int camera_frame_num = static_cast<int>(camera_frames.size());
+ stream->write(reinterpret_cast<const char*>(&camera_frame_num), sizeof(int));
+ for (int i = 0; i < camera_frame_num; i++)
+ {
+ camera_frames[i].Write(stream);
+ }
+
+ // light frames
+ const int light_frame_num = static_cast<int>(light_frames.size());
+ stream->write(reinterpret_cast<const char*>(&light_frame_num), sizeof(int));
+ for (int i = 0; i < light_frame_num; i++)
+ {
+ light_frames[i].Write(stream);
+ }
+
+ // self shadow datas
+ const int self_shadow_num = 0;
+ stream->write(reinterpret_cast<const char*>(&self_shadow_num), sizeof(int));
+
+ // ik frames
+ const int ik_num = static_cast<int>(ik_frames.size());
+ stream->write(reinterpret_cast<const char*>(&ik_num), sizeof(int));
+ for (int i = 0; i < ik_num; i++)
+ {
+ ik_frames[i].Write(stream);
+ }
+
+ return true;
+ }
+ };
+}
diff --git a/thirdparty/assimp/code/MakeVerboseFormat.cpp b/thirdparty/assimp/code/MakeVerboseFormat.cpp
new file mode 100644
index 0000000000..50ff5ed93d
--- /dev/null
+++ b/thirdparty/assimp/code/MakeVerboseFormat.cpp
@@ -0,0 +1,226 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+/** @file Implementation of the post processing step "MakeVerboseFormat"
+*/
+
+
+#include "MakeVerboseFormat.h"
+#include <assimp/scene.h>
+#include <assimp/DefaultLogger.hpp>
+
+using namespace Assimp;
+
+// ------------------------------------------------------------------------------------------------
+MakeVerboseFormatProcess::MakeVerboseFormatProcess()
+{
+ // nothing to do here
+}
+// ------------------------------------------------------------------------------------------------
+MakeVerboseFormatProcess::~MakeVerboseFormatProcess()
+{
+ // nothing to do here
+}
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+void MakeVerboseFormatProcess::Execute( aiScene* pScene)
+{
+ ai_assert(NULL != pScene);
+ ASSIMP_LOG_DEBUG("MakeVerboseFormatProcess begin");
+
+ bool bHas = false;
+ for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
+ {
+ if( MakeVerboseFormat( pScene->mMeshes[a]))
+ bHas = true;
+ }
+ if (bHas) {
+ ASSIMP_LOG_INFO("MakeVerboseFormatProcess finished. There was much work to do ...");
+ } else {
+ ASSIMP_LOG_DEBUG("MakeVerboseFormatProcess. There was nothing to do.");
+ }
+
+ pScene->mFlags &= ~AI_SCENE_FLAGS_NON_VERBOSE_FORMAT;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh* pcMesh)
+{
+ ai_assert(NULL != pcMesh);
+
+ unsigned int iOldNumVertices = pcMesh->mNumVertices;
+ const unsigned int iNumVerts = pcMesh->mNumFaces*3;
+
+ aiVector3D* pvPositions = new aiVector3D[ iNumVerts ];
+
+ aiVector3D* pvNormals = NULL;
+ if (pcMesh->HasNormals())
+ {
+ pvNormals = new aiVector3D[iNumVerts];
+ }
+ aiVector3D* pvTangents = NULL, *pvBitangents = NULL;
+ if (pcMesh->HasTangentsAndBitangents())
+ {
+ pvTangents = new aiVector3D[iNumVerts];
+ pvBitangents = new aiVector3D[iNumVerts];
+ }
+
+ aiVector3D* apvTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS] = {0};
+ aiColor4D* apvColorSets[AI_MAX_NUMBER_OF_COLOR_SETS] = {0};
+
+ unsigned int p = 0;
+ while (pcMesh->HasTextureCoords(p))
+ apvTextureCoords[p++] = new aiVector3D[iNumVerts];
+
+ p = 0;
+ while (pcMesh->HasVertexColors(p))
+ apvColorSets[p++] = new aiColor4D[iNumVerts];
+
+ // allocate enough memory to hold output bones and vertex weights ...
+ std::vector<aiVertexWeight>* newWeights = new std::vector<aiVertexWeight>[pcMesh->mNumBones];
+ for (unsigned int i = 0;i < pcMesh->mNumBones;++i) {
+ newWeights[i].reserve(pcMesh->mBones[i]->mNumWeights*3);
+ }
+
+ // iterate through all faces and build a clean list
+ unsigned int iIndex = 0;
+ for (unsigned int a = 0; a< pcMesh->mNumFaces;++a)
+ {
+ aiFace* pcFace = &pcMesh->mFaces[a];
+ for (unsigned int q = 0; q < pcFace->mNumIndices;++q,++iIndex)
+ {
+ // need to build a clean list of bones, too
+ for (unsigned int i = 0;i < pcMesh->mNumBones;++i)
+ {
+ for (unsigned int a = 0; a < pcMesh->mBones[i]->mNumWeights;a++)
+ {
+ const aiVertexWeight& w = pcMesh->mBones[i]->mWeights[a];
+ if(pcFace->mIndices[q] == w.mVertexId)
+ {
+ aiVertexWeight wNew;
+ wNew.mVertexId = iIndex;
+ wNew.mWeight = w.mWeight;
+ newWeights[i].push_back(wNew);
+ }
+ }
+ }
+
+ pvPositions[iIndex] = pcMesh->mVertices[pcFace->mIndices[q]];
+
+ if (pcMesh->HasNormals())
+ {
+ pvNormals[iIndex] = pcMesh->mNormals[pcFace->mIndices[q]];
+ }
+ if (pcMesh->HasTangentsAndBitangents())
+ {
+ pvTangents[iIndex] = pcMesh->mTangents[pcFace->mIndices[q]];
+ pvBitangents[iIndex] = pcMesh->mBitangents[pcFace->mIndices[q]];
+ }
+
+ unsigned int p = 0;
+ while (pcMesh->HasTextureCoords(p))
+ {
+ apvTextureCoords[p][iIndex] = pcMesh->mTextureCoords[p][pcFace->mIndices[q]];
+ ++p;
+ }
+ p = 0;
+ while (pcMesh->HasVertexColors(p))
+ {
+ apvColorSets[p][iIndex] = pcMesh->mColors[p][pcFace->mIndices[q]];
+ ++p;
+ }
+ pcFace->mIndices[q] = iIndex;
+ }
+ }
+
+
+
+ // build output vertex weights
+ for (unsigned int i = 0;i < pcMesh->mNumBones;++i)
+ {
+ delete [] pcMesh->mBones[i]->mWeights;
+ if (!newWeights[i].empty()) {
+ pcMesh->mBones[i]->mWeights = new aiVertexWeight[newWeights[i].size()];
+ aiVertexWeight *weightToCopy = &( newWeights[i][0] );
+ memcpy(pcMesh->mBones[i]->mWeights, weightToCopy,
+ sizeof(aiVertexWeight) * newWeights[i].size());
+ } else {
+ pcMesh->mBones[i]->mWeights = NULL;
+ }
+ }
+ delete[] newWeights;
+
+ // delete the old members
+ delete[] pcMesh->mVertices;
+ pcMesh->mVertices = pvPositions;
+
+ p = 0;
+ while (pcMesh->HasTextureCoords(p))
+ {
+ delete[] pcMesh->mTextureCoords[p];
+ pcMesh->mTextureCoords[p] = apvTextureCoords[p];
+ ++p;
+ }
+ p = 0;
+ while (pcMesh->HasVertexColors(p))
+ {
+ delete[] pcMesh->mColors[p];
+ pcMesh->mColors[p] = apvColorSets[p];
+ ++p;
+ }
+ pcMesh->mNumVertices = iNumVerts;
+
+ if (pcMesh->HasNormals())
+ {
+ delete[] pcMesh->mNormals;
+ pcMesh->mNormals = pvNormals;
+ }
+ if (pcMesh->HasTangentsAndBitangents())
+ {
+ delete[] pcMesh->mTangents;
+ pcMesh->mTangents = pvTangents;
+ delete[] pcMesh->mBitangents;
+ pcMesh->mBitangents = pvBitangents;
+ }
+ return (pcMesh->mNumVertices != iOldNumVertices);
+}
diff --git a/thirdparty/assimp/code/MakeVerboseFormat.h b/thirdparty/assimp/code/MakeVerboseFormat.h
new file mode 100644
index 0000000000..d12db63ae1
--- /dev/null
+++ b/thirdparty/assimp/code/MakeVerboseFormat.h
@@ -0,0 +1,105 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file Defines a post processing step to bring a given scene
+ into the verbose format that is expected by most postprocess steps.
+ This is the inverse of the "JoinIdenticalVertices" step. */
+#ifndef AI_MAKEVERBOSEFORMAT_H_INC
+#define AI_MAKEVERBOSEFORMAT_H_INC
+
+#include "BaseProcess.h"
+struct aiMesh;
+
+namespace Assimp {
+
+// ---------------------------------------------------------------------------
+/** MakeVerboseFormatProcess: Class to convert an asset to the verbose
+ * format which is expected by most postprocess steps.
+ *
+ * This is the inverse of what the "JoinIdenticalVertices" step is doing.
+ * This step has no official flag (since it wouldn't make sense to run it
+ * during import). It is intended for applications intending to modify the
+ * returned aiScene. After this step has been executed, they can execute
+ * other postprocess steps on the data. The code might also be useful to
+ * quickly adapt code that doesn't result in a verbose representation of
+ * the scene data.
+ * The step has been added because it was required by the viewer, however
+ * it has been moved to the main library since others might find it
+ * useful, too. */
+class ASSIMP_API_WINONLY MakeVerboseFormatProcess : public BaseProcess
+{
+public:
+
+
+ MakeVerboseFormatProcess();
+ ~MakeVerboseFormatProcess();
+
+public:
+
+ // -------------------------------------------------------------------
+ /** Returns whether the processing step is present in the given flag field.
+ * @param pFlags The processing flags the importer was called with. A bitwise
+ * combination of #aiPostProcessSteps.
+ * @return true if the process is present in this flag fields, false if not */
+ bool IsActive( unsigned int /*pFlags*/ ) const
+ {
+ // NOTE: There is no direct flag that corresponds to
+ // this postprocess step.
+ return false;
+ }
+
+ // -------------------------------------------------------------------
+ /** Executes the post processing step on the given imported data.
+ * At the moment a process is not supposed to fail.
+ * @param pScene The imported data to work at. */
+ void Execute( aiScene* pScene);
+
+
+private:
+
+ //! Apply the postprocess step to a given submesh
+ bool MakeVerboseFormat (aiMesh* pcMesh);
+};
+
+} // end of namespace Assimp
+
+#endif // !!AI_KILLNORMALPROCESS_H_INC
diff --git a/thirdparty/assimp/code/MaterialSystem.cpp b/thirdparty/assimp/code/MaterialSystem.cpp
new file mode 100644
index 0000000000..03d5a18a34
--- /dev/null
+++ b/thirdparty/assimp/code/MaterialSystem.cpp
@@ -0,0 +1,647 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file MaterialSystem.cpp
+ * @brief Implementation of the material system of the library
+ */
+
+#include <assimp/Hash.h>
+#include <assimp/fast_atof.h>
+#include <assimp/ParsingUtils.h>
+#include "MaterialSystem.h"
+#include <assimp/types.h>
+#include <assimp/material.h>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/Macros.h>
+
+using namespace Assimp;
+
+// ------------------------------------------------------------------------------------------------
+// Get a specific property from a material
+aiReturn aiGetMaterialProperty(const aiMaterial* pMat,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index,
+ const aiMaterialProperty** pPropOut)
+{
+ ai_assert( pMat != NULL );
+ ai_assert( pKey != NULL );
+ ai_assert( pPropOut != NULL );
+
+ /* Just search for a property with exactly this name ..
+ * could be improved by hashing, but it's possibly
+ * no worth the effort (we're bound to C structures,
+ * thus std::map or derivates are not applicable. */
+ for ( unsigned int i = 0; i < pMat->mNumProperties; ++i ) {
+ aiMaterialProperty* prop = pMat->mProperties[i];
+
+ if (prop /* just for safety ... */
+ && 0 == strcmp( prop->mKey.data, pKey )
+ && (UINT_MAX == type || prop->mSemantic == type) /* UINT_MAX is a wild-card, but this is undocumented :-) */
+ && (UINT_MAX == index || prop->mIndex == index))
+ {
+ *pPropOut = pMat->mProperties[i];
+ return AI_SUCCESS;
+ }
+ }
+ *pPropOut = NULL;
+ return AI_FAILURE;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Get an array of floating-point values from the material.
+aiReturn aiGetMaterialFloatArray(const aiMaterial* pMat,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index,
+ ai_real* pOut,
+ unsigned int* pMax)
+{
+ ai_assert( pOut != NULL );
+ ai_assert( pMat != NULL );
+
+ const aiMaterialProperty* prop;
+ aiGetMaterialProperty(pMat,pKey,type,index, (const aiMaterialProperty**) &prop);
+ if (!prop) {
+ return AI_FAILURE;
+ }
+
+ // data is given in floats, convert to ai_real
+ unsigned int iWrite = 0;
+ if( aiPTI_Float == prop->mType || aiPTI_Buffer == prop->mType) {
+ iWrite = prop->mDataLength / sizeof(float);
+ if (pMax) {
+ iWrite = std::min(*pMax,iWrite); ;
+ }
+ for (unsigned int a = 0; a < iWrite;++a) {
+ pOut[a] = static_cast<ai_real> ( reinterpret_cast<float*>(prop->mData)[a] );
+ }
+ if (pMax) {
+ *pMax = iWrite;
+ }
+ }
+ // data is given in doubles, convert to float
+ else if( aiPTI_Double == prop->mType) {
+ iWrite = prop->mDataLength / sizeof(double);
+ if (pMax) {
+ iWrite = std::min(*pMax,iWrite); ;
+ }
+ for (unsigned int a = 0; a < iWrite;++a) {
+ pOut[a] = static_cast<ai_real> ( reinterpret_cast<double*>(prop->mData)[a] );
+ }
+ if (pMax) {
+ *pMax = iWrite;
+ }
+ }
+ // data is given in ints, convert to float
+ else if( aiPTI_Integer == prop->mType) {
+ iWrite = prop->mDataLength / sizeof(int32_t);
+ if (pMax) {
+ iWrite = std::min(*pMax,iWrite); ;
+ }
+ for (unsigned int a = 0; a < iWrite;++a) {
+ pOut[a] = static_cast<ai_real> ( reinterpret_cast<int32_t*>(prop->mData)[a] );
+ }
+ if (pMax) {
+ *pMax = iWrite;
+ }
+ }
+ // a string ... read floats separated by spaces
+ else {
+ if (pMax) {
+ iWrite = *pMax;
+ }
+ // strings are zero-terminated with a 32 bit length prefix, so this is safe
+ const char *cur = prop->mData + 4;
+ ai_assert( prop->mDataLength >= 5 );
+ ai_assert( !prop->mData[ prop->mDataLength - 1 ] );
+ for ( unsigned int a = 0; ;++a) {
+ cur = fast_atoreal_move<ai_real>(cur,pOut[a]);
+ if ( a==iWrite-1 ) {
+ break;
+ }
+ if ( !IsSpace(*cur) ) {
+ ASSIMP_LOG_ERROR("Material property" + std::string(pKey) +
+ " is a string; failed to parse a float array out of it.");
+ return AI_FAILURE;
+ }
+ }
+
+ if (pMax) {
+ *pMax = iWrite;
+ }
+ }
+ return AI_SUCCESS;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Get an array if integers from the material
+aiReturn aiGetMaterialIntegerArray(const aiMaterial* pMat,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index,
+ int* pOut,
+ unsigned int* pMax)
+{
+ ai_assert( pOut != NULL );
+ ai_assert( pMat != NULL );
+
+ const aiMaterialProperty* prop;
+ aiGetMaterialProperty(pMat,pKey,type,index,(const aiMaterialProperty**) &prop);
+ if (!prop) {
+ return AI_FAILURE;
+ }
+
+ // data is given in ints, simply copy it
+ unsigned int iWrite = 0;
+ if( aiPTI_Integer == prop->mType || aiPTI_Buffer == prop->mType) {
+ iWrite = std::max(static_cast<unsigned int>(prop->mDataLength / sizeof(int32_t)), 1u);
+ if (pMax) {
+ iWrite = std::min(*pMax,iWrite);
+ }
+ if (1 == prop->mDataLength) {
+ // bool type, 1 byte
+ *pOut = static_cast<int>(*prop->mData);
+ }
+ else {
+ for (unsigned int a = 0; a < iWrite;++a) {
+ pOut[a] = static_cast<int>(reinterpret_cast<int32_t*>(prop->mData)[a]);
+ }
+ }
+ if (pMax) {
+ *pMax = iWrite;
+ }
+ }
+ // data is given in floats convert to int
+ else if( aiPTI_Float == prop->mType) {
+ iWrite = prop->mDataLength / sizeof(float);
+ if (pMax) {
+ iWrite = std::min(*pMax,iWrite); ;
+ }
+ for (unsigned int a = 0; a < iWrite;++a) {
+ pOut[a] = static_cast<int>(reinterpret_cast<float*>(prop->mData)[a]);
+ }
+ if (pMax) {
+ *pMax = iWrite;
+ }
+ }
+ // it is a string ... no way to read something out of this
+ else {
+ if (pMax) {
+ iWrite = *pMax;
+ }
+ // strings are zero-terminated with a 32 bit length prefix, so this is safe
+ const char *cur = prop->mData+4;
+ ai_assert( prop->mDataLength >= 5 );
+ ai_assert( !prop->mData[ prop->mDataLength - 1 ] );
+ for (unsigned int a = 0; ;++a) {
+ pOut[a] = strtol10(cur,&cur);
+ if(a==iWrite-1) {
+ break;
+ }
+ if(!IsSpace(*cur)) {
+ ASSIMP_LOG_ERROR("Material property" + std::string(pKey) +
+ " is a string; failed to parse an integer array out of it.");
+ return AI_FAILURE;
+ }
+ }
+
+ if (pMax) {
+ *pMax = iWrite;
+ }
+ }
+ return AI_SUCCESS;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Get a color (3 or 4 floats) from the material
+aiReturn aiGetMaterialColor(const aiMaterial* pMat,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index,
+ aiColor4D* pOut)
+{
+ unsigned int iMax = 4;
+ const aiReturn eRet = aiGetMaterialFloatArray(pMat,pKey,type,index,(ai_real*)pOut,&iMax);
+
+ // if no alpha channel is defined: set it to 1.0
+ if (3 == iMax) {
+ pOut->a = 1.0;
+ }
+
+ return eRet;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Get a aiUVTransform (4 floats) from the material
+aiReturn aiGetMaterialUVTransform(const aiMaterial* pMat,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index,
+ aiUVTransform* pOut)
+{
+ unsigned int iMax = 4;
+ return aiGetMaterialFloatArray(pMat,pKey,type,index,(ai_real*)pOut,&iMax);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Get a string from the material
+aiReturn aiGetMaterialString(const aiMaterial* pMat,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index,
+ aiString* pOut)
+{
+ ai_assert (pOut != NULL);
+
+ const aiMaterialProperty* prop;
+ aiGetMaterialProperty(pMat,pKey,type,index,(const aiMaterialProperty**)&prop);
+ if (!prop) {
+ return AI_FAILURE;
+ }
+
+ if( aiPTI_String == prop->mType) {
+ ai_assert(prop->mDataLength>=5);
+
+ // The string is stored as 32 but length prefix followed by zero-terminated UTF8 data
+ pOut->length = static_cast<unsigned int>(*reinterpret_cast<uint32_t*>(prop->mData));
+
+ ai_assert( pOut->length+1+4==prop->mDataLength );
+ ai_assert( !prop->mData[ prop->mDataLength - 1 ] );
+ memcpy(pOut->data,prop->mData+4,pOut->length+1);
+ }
+ else {
+ // TODO - implement lexical cast as well
+ ASSIMP_LOG_ERROR("Material property" + std::string(pKey) +
+ " was found, but is no string" );
+ return AI_FAILURE;
+ }
+ return AI_SUCCESS;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Get the number of textures on a particular texture stack
+unsigned int aiGetMaterialTextureCount(const C_STRUCT aiMaterial* pMat,
+ C_ENUM aiTextureType type)
+{
+ ai_assert (pMat != NULL);
+
+ // Textures are always stored with ascending indices (ValidateDS provides a check, so we don't need to do it again)
+ unsigned int max = 0;
+ for (unsigned int i = 0; i < pMat->mNumProperties;++i) {
+ aiMaterialProperty* prop = pMat->mProperties[i];
+
+ if ( prop /* just a sanity check ... */
+ && 0 == strcmp( prop->mKey.data, _AI_MATKEY_TEXTURE_BASE )
+ && prop->mSemantic == type) {
+
+ max = std::max(max,prop->mIndex+1);
+ }
+ }
+ return max;
+}
+
+// ------------------------------------------------------------------------------------------------
+aiReturn aiGetMaterialTexture(const C_STRUCT aiMaterial* mat,
+ aiTextureType type,
+ unsigned int index,
+ C_STRUCT aiString* path,
+ aiTextureMapping* _mapping /*= NULL*/,
+ unsigned int* uvindex /*= NULL*/,
+ ai_real* blend /*= NULL*/,
+ aiTextureOp* op /*= NULL*/,
+ aiTextureMapMode* mapmode /*= NULL*/,
+ unsigned int* flags /*= NULL*/
+ )
+{
+ ai_assert( NULL != mat );
+ ai_assert( NULL != path );
+
+ // Get the path to the texture
+ if (AI_SUCCESS != aiGetMaterialString(mat,AI_MATKEY_TEXTURE(type,index),path)) {
+ return AI_FAILURE;
+ }
+
+ // Determine mapping type
+ int mapping_ = static_cast<int>(aiTextureMapping_UV);
+ aiGetMaterialInteger(mat,AI_MATKEY_MAPPING(type,index), &mapping_);
+ aiTextureMapping mapping = static_cast<aiTextureMapping>(mapping_);
+ if (_mapping)
+ *_mapping = mapping;
+
+ // Get UV index
+ if (aiTextureMapping_UV == mapping && uvindex) {
+ aiGetMaterialInteger(mat,AI_MATKEY_UVWSRC(type,index),(int*)uvindex);
+ }
+ // Get blend factor
+ if (blend) {
+ aiGetMaterialFloat(mat,AI_MATKEY_TEXBLEND(type,index),blend);
+ }
+ // Get texture operation
+ if (op){
+ aiGetMaterialInteger(mat,AI_MATKEY_TEXOP(type,index),(int*)op);
+ }
+ // Get texture mapping modes
+ if (mapmode) {
+ aiGetMaterialInteger(mat,AI_MATKEY_MAPPINGMODE_U(type,index),(int*)&mapmode[0]);
+ aiGetMaterialInteger(mat,AI_MATKEY_MAPPINGMODE_V(type,index),(int*)&mapmode[1]);
+ }
+ // Get texture flags
+ if (flags){
+ aiGetMaterialInteger(mat,AI_MATKEY_TEXFLAGS(type,index),(int*)flags);
+ }
+
+ return AI_SUCCESS;
+}
+
+
+static const unsigned int DefaultNumAllocated = 5;
+
+// ------------------------------------------------------------------------------------------------
+// Construction. Actually the one and only way to get an aiMaterial instance
+aiMaterial::aiMaterial()
+: mProperties( nullptr )
+, mNumProperties( 0 )
+, mNumAllocated( DefaultNumAllocated ) {
+ // Allocate 5 entries by default
+ mProperties = new aiMaterialProperty*[ DefaultNumAllocated ];
+}
+
+// ------------------------------------------------------------------------------------------------
+aiMaterial::~aiMaterial()
+{
+ Clear();
+
+ delete[] mProperties;
+}
+
+// ------------------------------------------------------------------------------------------------
+aiString aiMaterial::GetName() {
+ aiString name;
+ Get(AI_MATKEY_NAME, name);
+
+ return name;
+}
+
+// ------------------------------------------------------------------------------------------------
+void aiMaterial::Clear()
+{
+ for ( unsigned int i = 0; i < mNumProperties; ++i ) {
+ // delete this entry
+ delete mProperties[ i ];
+ AI_DEBUG_INVALIDATE_PTR(mProperties[i]);
+ }
+ mNumProperties = 0;
+
+ // The array remains allocated, we just invalidated its contents
+}
+
+// ------------------------------------------------------------------------------------------------
+aiReturn aiMaterial::RemoveProperty ( const char* pKey,unsigned int type, unsigned int index )
+{
+ ai_assert( nullptr != pKey );
+
+ for (unsigned int i = 0; i < mNumProperties;++i) {
+ aiMaterialProperty* prop = mProperties[i];
+
+ if (prop && !strcmp( prop->mKey.data, pKey ) &&
+ prop->mSemantic == type && prop->mIndex == index)
+ {
+ // Delete this entry
+ delete mProperties[i];
+
+ // collapse the array behind --.
+ --mNumProperties;
+ for (unsigned int a = i; a < mNumProperties;++a) {
+ mProperties[a] = mProperties[a+1];
+ }
+ return AI_SUCCESS;
+ }
+ }
+
+ return AI_FAILURE;
+}
+
+// ------------------------------------------------------------------------------------------------
+aiReturn aiMaterial::AddBinaryProperty (const void* pInput,
+ unsigned int pSizeInBytes,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index,
+ aiPropertyTypeInfo pType
+ )
+{
+ ai_assert( pInput != NULL );
+ ai_assert( pKey != NULL );
+ ai_assert( 0 != pSizeInBytes );
+
+ if ( 0 == pSizeInBytes ) {
+
+ }
+
+ // first search the list whether there is already an entry with this key
+ unsigned int iOutIndex( UINT_MAX );
+ for ( unsigned int i = 0; i < mNumProperties; ++i ) {
+ aiMaterialProperty *prop( mProperties[ i ] );
+
+ if (prop /* just for safety */ && !strcmp( prop->mKey.data, pKey ) &&
+ prop->mSemantic == type && prop->mIndex == index){
+
+ delete mProperties[i];
+ iOutIndex = i;
+ }
+ }
+
+ // Allocate a new material property
+ aiMaterialProperty* pcNew = new aiMaterialProperty();
+
+ // .. and fill it
+ pcNew->mType = pType;
+ pcNew->mSemantic = type;
+ pcNew->mIndex = index;
+
+ pcNew->mDataLength = pSizeInBytes;
+ pcNew->mData = new char[pSizeInBytes];
+ memcpy (pcNew->mData,pInput,pSizeInBytes);
+
+ pcNew->mKey.length = ::strlen(pKey);
+ ai_assert ( MAXLEN > pcNew->mKey.length);
+ strcpy( pcNew->mKey.data, pKey );
+
+ if (UINT_MAX != iOutIndex) {
+ mProperties[iOutIndex] = pcNew;
+ return AI_SUCCESS;
+ }
+
+ // resize the array ... double the storage allocated
+ if (mNumProperties == mNumAllocated) {
+ const unsigned int iOld = mNumAllocated;
+ mNumAllocated *= 2;
+
+ aiMaterialProperty** ppTemp;
+ try {
+ ppTemp = new aiMaterialProperty*[mNumAllocated];
+ } catch (std::bad_alloc&) {
+ delete pcNew;
+ return AI_OUTOFMEMORY;
+ }
+
+ // just copy all items over; then replace the old array
+ memcpy (ppTemp,mProperties,iOld * sizeof(void*));
+
+ delete[] mProperties;
+ mProperties = ppTemp;
+ }
+ // push back ...
+ mProperties[mNumProperties++] = pcNew;
+
+ return AI_SUCCESS;
+}
+
+// ------------------------------------------------------------------------------------------------
+aiReturn aiMaterial::AddProperty (const aiString* pInput,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index)
+{
+ // We don't want to add the whole buffer .. write a 32 bit length
+ // prefix followed by the zero-terminated UTF8 string.
+ // (HACK) I don't want to break the ABI now, but we definitely
+ // ought to change aiString::mLength to uint32_t one day.
+ if (sizeof(size_t) == 8) {
+ aiString copy = *pInput;
+ uint32_t* s = reinterpret_cast<uint32_t*>(&copy.length);
+ s[1] = static_cast<uint32_t>(pInput->length);
+
+ return AddBinaryProperty(s+1,
+ static_cast<unsigned int>(pInput->length+1+4),
+ pKey,
+ type,
+ index,
+ aiPTI_String);
+ }
+ ai_assert(sizeof(size_t)==4);
+ return AddBinaryProperty(pInput,
+ static_cast<unsigned int>(pInput->length+1+4),
+ pKey,
+ type,
+ index,
+ aiPTI_String);
+}
+
+// ------------------------------------------------------------------------------------------------
+uint32_t Assimp::ComputeMaterialHash(const aiMaterial* mat, bool includeMatName /*= false*/)
+{
+ uint32_t hash = 1503; // magic start value, chosen to be my birthday :-)
+ for ( unsigned int i = 0; i < mat->mNumProperties; ++i ) {
+ aiMaterialProperty* prop;
+
+ // Exclude all properties whose first character is '?' from the hash
+ // See doc for aiMaterialProperty.
+ if ((prop = mat->mProperties[i]) && (includeMatName || prop->mKey.data[0] != '?')) {
+
+ hash = SuperFastHash(prop->mKey.data,(unsigned int)prop->mKey.length,hash);
+ hash = SuperFastHash(prop->mData,prop->mDataLength,hash);
+
+ // Combine the semantic and the index with the hash
+ hash = SuperFastHash((const char*)&prop->mSemantic,sizeof(unsigned int),hash);
+ hash = SuperFastHash((const char*)&prop->mIndex,sizeof(unsigned int),hash);
+ }
+ }
+ return hash;
+}
+
+// ------------------------------------------------------------------------------------------------
+void aiMaterial::CopyPropertyList(aiMaterial* pcDest,
+ const aiMaterial* pcSrc
+ )
+{
+ ai_assert(NULL != pcDest);
+ ai_assert(NULL != pcSrc);
+
+ unsigned int iOldNum = pcDest->mNumProperties;
+ pcDest->mNumAllocated += pcSrc->mNumAllocated;
+ pcDest->mNumProperties += pcSrc->mNumProperties;
+
+ aiMaterialProperty** pcOld = pcDest->mProperties;
+ pcDest->mProperties = new aiMaterialProperty*[pcDest->mNumAllocated];
+
+ if (iOldNum && pcOld) {
+ for (unsigned int i = 0; i < iOldNum;++i) {
+ pcDest->mProperties[i] = pcOld[i];
+ }
+ }
+
+ if ( pcOld ) {
+ delete[] pcOld;
+ }
+
+ for (unsigned int i = iOldNum; i< pcDest->mNumProperties;++i) {
+ aiMaterialProperty* propSrc = pcSrc->mProperties[i];
+
+ // search whether we have already a property with this name -> if yes, overwrite it
+ aiMaterialProperty* prop;
+ for ( unsigned int q = 0; q < iOldNum; ++q ) {
+ prop = pcDest->mProperties[q];
+ if (prop /* just for safety */ && prop->mKey == propSrc->mKey && prop->mSemantic == propSrc->mSemantic
+ && prop->mIndex == propSrc->mIndex) {
+ delete prop;
+
+ // collapse the whole array ...
+ memmove(&pcDest->mProperties[q],&pcDest->mProperties[q+1],i-q);
+ i--;
+ pcDest->mNumProperties--;
+ }
+ }
+
+ // Allocate the output property and copy the source property
+ prop = pcDest->mProperties[i] = new aiMaterialProperty();
+ prop->mKey = propSrc->mKey;
+ prop->mDataLength = propSrc->mDataLength;
+ prop->mType = propSrc->mType;
+ prop->mSemantic = propSrc->mSemantic;
+ prop->mIndex = propSrc->mIndex;
+
+ prop->mData = new char[propSrc->mDataLength];
+ memcpy(prop->mData,propSrc->mData,prop->mDataLength);
+ }
+}
diff --git a/thirdparty/assimp/code/MaterialSystem.h b/thirdparty/assimp/code/MaterialSystem.h
new file mode 100644
index 0000000000..67d53578cb
--- /dev/null
+++ b/thirdparty/assimp/code/MaterialSystem.h
@@ -0,0 +1,72 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file MaterialSystem.h
+ * Now that #MaterialHelper is gone, this file only contains some
+ * internal material utility functions.
+ */
+#ifndef AI_MATERIALSYSTEM_H_INC
+#define AI_MATERIALSYSTEM_H_INC
+
+#include <stdint.h>
+
+struct aiMaterial;
+
+namespace Assimp {
+
+// ------------------------------------------------------------------------------
+/** Computes a hash (hopefully unique) from all material properties
+ * The hash value reflects the current property state, so if you add any
+ * property and call this method again, the resulting hash value will be
+ * different. The hash is not persistent across different builds and platforms.
+ *
+ * @param includeMatName Set to 'true' to take all properties with
+ * '?' as initial character in their name into account.
+ * Currently #AI_MATKEY_NAME is the only example.
+ * @return 32 Bit jash value for the material
+ */
+uint32_t ComputeMaterialHash(const aiMaterial* mat, bool includeMatName = false);
+
+
+} // ! namespace Assimp
+
+#endif //!! AI_MATERIALSYSTEM_H_INC
diff --git a/thirdparty/assimp/code/OptimizeGraph.cpp b/thirdparty/assimp/code/OptimizeGraph.cpp
new file mode 100644
index 0000000000..add9ab79e1
--- /dev/null
+++ b/thirdparty/assimp/code/OptimizeGraph.cpp
@@ -0,0 +1,353 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file OptimizeGraph.cpp
+ * @brief Implementation of the aiProcess_OptimizGraph step
+ */
+
+
+#ifndef ASSIMP_BUILD_NO_OPTIMIZEGRAPH_PROCESS
+
+#include "OptimizeGraph.h"
+#include "ProcessHelper.h"
+#include <assimp/SceneCombiner.h>
+#include <assimp/Exceptional.h>
+#include <stdio.h>
+
+using namespace Assimp;
+
+#define AI_RESERVED_NODE_NAME "$Reserved_And_Evil"
+
+/* AI_OG_USE_HASHING enables the use of hashing to speed-up std::set lookups.
+ * The unhashed variant should be faster, except for *very* large data sets
+ */
+#ifdef AI_OG_USE_HASHING
+ // Use our standard hashing function to compute the hash
+# define AI_OG_GETKEY(str) SuperFastHash(str.data,str.length)
+#else
+ // Otherwise hope that std::string will utilize a static buffer
+ // for shorter node names. This would avoid endless heap copying.
+# define AI_OG_GETKEY(str) std::string(str.data)
+#endif
+
+// ------------------------------------------------------------------------------------------------
+// Constructor to be privately used by Importer
+OptimizeGraphProcess::OptimizeGraphProcess()
+: mScene()
+, nodes_in()
+, nodes_out()
+, count_merged() {
+ // empty
+}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor, private as well
+OptimizeGraphProcess::~OptimizeGraphProcess() {
+ // empty
+}
+
+// ------------------------------------------------------------------------------------------------
+// Returns whether the processing step is present in the given flag field.
+bool OptimizeGraphProcess::IsActive( unsigned int pFlags) const {
+ return (0 != (pFlags & aiProcess_OptimizeGraph));
+}
+
+// ------------------------------------------------------------------------------------------------
+// Setup properties for the post-processing step
+void OptimizeGraphProcess::SetupProperties(const Importer* pImp) {
+ // Get value of AI_CONFIG_PP_OG_EXCLUDE_LIST
+ std::string tmp = pImp->GetPropertyString(AI_CONFIG_PP_OG_EXCLUDE_LIST,"");
+ AddLockedNodeList(tmp);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Collect new children
+void OptimizeGraphProcess::CollectNewChildren(aiNode* nd, std::list<aiNode*>& nodes) {
+ nodes_in += nd->mNumChildren;
+
+ // Process children
+ std::list<aiNode*> child_nodes;
+ for (unsigned int i = 0; i < nd->mNumChildren; ++i) {
+ CollectNewChildren(nd->mChildren[i],child_nodes);
+ nd->mChildren[i] = nullptr;
+ }
+
+ // Check whether we need this node; if not we can replace it by our own children (warn, danger of incest).
+ if (locked.find(AI_OG_GETKEY(nd->mName)) == locked.end() ) {
+ for (std::list<aiNode*>::iterator it = child_nodes.begin(); it != child_nodes.end();) {
+
+ if (locked.find(AI_OG_GETKEY((*it)->mName)) == locked.end()) {
+ (*it)->mTransformation = nd->mTransformation * (*it)->mTransformation;
+ nodes.push_back(*it);
+
+ it = child_nodes.erase(it);
+ continue;
+ }
+ ++it;
+ }
+
+ if (nd->mNumMeshes || !child_nodes.empty()) {
+ nodes.push_back(nd);
+ } else {
+ delete nd; /* bye, node */
+ return;
+ }
+ } else {
+
+ // Retain our current position in the hierarchy
+ nodes.push_back(nd);
+
+ // Now check for possible optimizations in our list of child nodes. join as many as possible
+ aiNode* join_master = NULL;
+ aiMatrix4x4 inv;
+
+ const LockedSetType::const_iterator end = locked.end();
+
+ std::list<aiNode*> join;
+ for (std::list<aiNode*>::iterator it = child_nodes.begin(); it != child_nodes.end();) {
+ aiNode* child = *it;
+ if (child->mNumChildren == 0 && locked.find(AI_OG_GETKEY(child->mName)) == end) {
+
+ // There may be no instanced meshes
+ unsigned int n = 0;
+ for (; n < child->mNumMeshes;++n) {
+ if (meshes[child->mMeshes[n]] > 1) {
+ break;
+ }
+ }
+ if (n == child->mNumMeshes) {
+ if (!join_master) {
+ join_master = child;
+ inv = join_master->mTransformation;
+ inv.Inverse();
+ } else {
+ child->mTransformation = inv * child->mTransformation ;
+
+ join.push_back(child);
+ it = child_nodes.erase(it);
+ continue;
+ }
+ }
+ }
+ ++it;
+ }
+ if (join_master && !join.empty()) {
+ join_master->mName.length = ::ai_snprintf(join_master->mName.data, MAXLEN, "$MergedNode_%i",count_merged++);
+
+ unsigned int out_meshes = 0;
+ for (std::list<aiNode*>::iterator it = join.begin(); it != join.end(); ++it) {
+ out_meshes += (*it)->mNumMeshes;
+ }
+
+ // copy all mesh references in one array
+ if (out_meshes) {
+ unsigned int* meshes = new unsigned int[out_meshes+join_master->mNumMeshes], *tmp = meshes;
+ for (unsigned int n = 0; n < join_master->mNumMeshes;++n) {
+ *tmp++ = join_master->mMeshes[n];
+ }
+
+ for (std::list<aiNode*>::iterator it = join.begin(); it != join.end(); ++it) {
+ for (unsigned int n = 0; n < (*it)->mNumMeshes; ++n) {
+
+ *tmp = (*it)->mMeshes[n];
+ aiMesh* mesh = mScene->mMeshes[*tmp++];
+
+ // manually move the mesh into the right coordinate system
+ const aiMatrix3x3 IT = aiMatrix3x3( (*it)->mTransformation ).Inverse().Transpose();
+ for (unsigned int a = 0; a < mesh->mNumVertices; ++a) {
+
+ mesh->mVertices[a] *= (*it)->mTransformation;
+
+ if (mesh->HasNormals())
+ mesh->mNormals[a] *= IT;
+
+ if (mesh->HasTangentsAndBitangents()) {
+ mesh->mTangents[a] *= IT;
+ mesh->mBitangents[a] *= IT;
+ }
+ }
+ }
+ delete *it; // bye, node
+ }
+ delete[] join_master->mMeshes;
+ join_master->mMeshes = meshes;
+ join_master->mNumMeshes += out_meshes;
+ }
+ }
+ }
+ // reassign children if something changed
+ if (child_nodes.empty() || child_nodes.size() > nd->mNumChildren) {
+
+ delete[] nd->mChildren;
+
+ if (!child_nodes.empty()) {
+ nd->mChildren = new aiNode*[child_nodes.size()];
+ }
+ else nd->mChildren = nullptr;
+ }
+
+ nd->mNumChildren = static_cast<unsigned int>(child_nodes.size());
+
+ if (nd->mChildren) {
+ aiNode** tmp = nd->mChildren;
+ for (std::list<aiNode*>::iterator it = child_nodes.begin(); it != child_nodes.end(); ++it) {
+ aiNode* node = *tmp++ = *it;
+ node->mParent = nd;
+ }
+ }
+
+ nodes_out += static_cast<unsigned int>(child_nodes.size());
+}
+
+// ------------------------------------------------------------------------------------------------
+// Execute the post-processing step on the given scene
+void OptimizeGraphProcess::Execute( aiScene* pScene) {
+ ASSIMP_LOG_DEBUG("OptimizeGraphProcess begin");
+ nodes_in = nodes_out = count_merged = 0;
+ mScene = pScene;
+
+ meshes.resize(pScene->mNumMeshes,0);
+ FindInstancedMeshes(pScene->mRootNode);
+
+ // build a blacklist of identifiers. If the name of a node matches one of these, we won't touch it
+ locked.clear();
+ for (std::list<std::string>::const_iterator it = locked_nodes.begin(); it != locked_nodes.end(); ++it) {
+#ifdef AI_OG_USE_HASHING
+ locked.insert(SuperFastHash((*it).c_str()));
+#else
+ locked.insert(*it);
+#endif
+ }
+
+ for (unsigned int i = 0; i < pScene->mNumAnimations; ++i) {
+ for (unsigned int a = 0; a < pScene->mAnimations[i]->mNumChannels; ++a) {
+ aiNodeAnim* anim = pScene->mAnimations[i]->mChannels[a];
+ locked.insert(AI_OG_GETKEY(anim->mNodeName));
+ }
+ }
+
+ for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
+ for (unsigned int a = 0; a < pScene->mMeshes[i]->mNumBones; ++a) {
+
+ aiBone* bone = pScene->mMeshes[i]->mBones[a];
+ locked.insert(AI_OG_GETKEY(bone->mName));
+
+ // HACK: Meshes referencing bones may not be transformed; we need to look them.
+ // The easiest way to do this is to increase their reference counters ...
+ meshes[i] += 2;
+ }
+ }
+
+ for (unsigned int i = 0; i < pScene->mNumCameras; ++i) {
+ aiCamera* cam = pScene->mCameras[i];
+ locked.insert(AI_OG_GETKEY(cam->mName));
+ }
+
+ for (unsigned int i = 0; i < pScene->mNumLights; ++i) {
+ aiLight* lgh = pScene->mLights[i];
+ locked.insert(AI_OG_GETKEY(lgh->mName));
+ }
+
+ // Insert a dummy master node and make it read-only
+ aiNode* dummy_root = new aiNode(AI_RESERVED_NODE_NAME);
+ locked.insert(AI_OG_GETKEY(dummy_root->mName));
+
+ const aiString prev = pScene->mRootNode->mName;
+ pScene->mRootNode->mParent = dummy_root;
+
+ dummy_root->mChildren = new aiNode*[dummy_root->mNumChildren = 1];
+ dummy_root->mChildren[0] = pScene->mRootNode;
+
+ // Do our recursive processing of scenegraph nodes. For each node collect
+ // a fully new list of children and allow their children to place themselves
+ // on the same hierarchy layer as their parents.
+ std::list<aiNode*> nodes;
+ CollectNewChildren (dummy_root,nodes);
+
+ ai_assert(nodes.size() == 1);
+
+ if (dummy_root->mNumChildren == 0) {
+ pScene->mRootNode = NULL;
+ throw DeadlyImportError("After optimizing the scene graph, no data remains");
+ }
+
+ if (dummy_root->mNumChildren > 1) {
+ pScene->mRootNode = dummy_root;
+
+ // Keep the dummy node but assign the name of the old root node to it
+ pScene->mRootNode->mName = prev;
+ }
+ else {
+
+ // Remove the dummy root node again.
+ pScene->mRootNode = dummy_root->mChildren[0];
+
+ dummy_root->mChildren[0] = NULL;
+ delete dummy_root;
+ }
+
+ pScene->mRootNode->mParent = NULL;
+ if (!DefaultLogger::isNullLogger()) {
+ if ( nodes_in != nodes_out) {
+ ASSIMP_LOG_INFO_F("OptimizeGraphProcess finished; Input nodes: ", nodes_in, ", Output nodes: ", nodes_out);
+ } else {
+ ASSIMP_LOG_DEBUG("OptimizeGraphProcess finished");
+ }
+ }
+ meshes.clear();
+ locked.clear();
+}
+
+// ------------------------------------------------------------------------------------------------
+// Build a LUT of all instanced meshes
+void OptimizeGraphProcess::FindInstancedMeshes (aiNode* pNode)
+{
+ for (unsigned int i = 0; i < pNode->mNumMeshes;++i) {
+ ++meshes[pNode->mMeshes[i]];
+ }
+
+ for (unsigned int i = 0; i < pNode->mNumChildren; ++i)
+ FindInstancedMeshes(pNode->mChildren[i]);
+}
+
+#endif // !! ASSIMP_BUILD_NO_OPTIMIZEGRAPH_PROCESS
diff --git a/thirdparty/assimp/code/OptimizeGraph.h b/thirdparty/assimp/code/OptimizeGraph.h
new file mode 100644
index 0000000000..e5bbed7679
--- /dev/null
+++ b/thirdparty/assimp/code/OptimizeGraph.h
@@ -0,0 +1,145 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file OptimizeGraph.h
+ * @brief Declares a post processing step to optimize the scenegraph
+ */
+#ifndef AI_OPTIMIZEGRAPHPROCESS_H_INC
+#define AI_OPTIMIZEGRAPHPROCESS_H_INC
+
+#include "BaseProcess.h"
+#include "ProcessHelper.h"
+#include <assimp/types.h>
+#include <set>
+
+struct aiMesh;
+class OptimizeGraphProcessTest;
+namespace Assimp {
+
+// -----------------------------------------------------------------------------
+/** @brief Postprocessing step to optimize the scenegraph
+ *
+ * The implementation tries to merge nodes, even if they use different
+ * transformations. Animations are preserved.
+ *
+ * @see aiProcess_OptimizeGraph for a detailed description of the
+ * algorithm being applied.
+ */
+class OptimizeGraphProcess : public BaseProcess
+{
+public:
+
+ OptimizeGraphProcess();
+ ~OptimizeGraphProcess();
+
+public:
+ // -------------------------------------------------------------------
+ bool IsActive( unsigned int pFlags) const;
+
+ // -------------------------------------------------------------------
+ void Execute( aiScene* pScene);
+
+ // -------------------------------------------------------------------
+ void SetupProperties(const Importer* pImp);
+
+
+ // -------------------------------------------------------------------
+ /** @brief Add a list of node names to be locked and not modified.
+ * @param in List of nodes. See #AI_CONFIG_PP_OG_EXCLUDE_LIST for
+ * format explanations.
+ */
+ inline void AddLockedNodeList(std::string& in)
+ {
+ ConvertListToStrings (in,locked_nodes);
+ }
+
+ // -------------------------------------------------------------------
+ /** @brief Add another node to be locked and not modified.
+ * @param name Name to be locked
+ */
+ inline void AddLockedNode(std::string& name)
+ {
+ locked_nodes.push_back(name);
+ }
+
+ // -------------------------------------------------------------------
+ /** @brief Remove a node from the list of locked nodes.
+ * @param name Name to be unlocked
+ */
+ inline void RemoveLockedNode(std::string& name)
+ {
+ locked_nodes.remove(name);
+ }
+
+protected:
+
+ void CollectNewChildren(aiNode* nd, std::list<aiNode*>& nodes);
+ void FindInstancedMeshes (aiNode* pNode);
+
+private:
+
+#ifdef AI_OG_USE_HASHING
+ typedef std::set<unsigned int> LockedSetType;
+#else
+ typedef std::set<std::string> LockedSetType;
+#endif
+
+
+ //! Scene we're working with
+ aiScene* mScene;
+
+ //! List of locked names. Stored is the hash of the name
+ LockedSetType locked;
+
+ //! List of nodes to be locked in addition to those with animations, lights or cameras assigned.
+ std::list<std::string> locked_nodes;
+
+ //! Node counters for logging purposes
+ unsigned int nodes_in,nodes_out, count_merged;
+
+ //! Reference counters for meshes
+ std::vector<unsigned int> meshes;
+};
+
+} // end of namespace Assimp
+
+#endif // AI_OPTIMIZEGRAPHPROCESS_H_INC
diff --git a/thirdparty/assimp/code/OptimizeMeshes.cpp b/thirdparty/assimp/code/OptimizeMeshes.cpp
new file mode 100644
index 0000000000..3f6765f6ca
--- /dev/null
+++ b/thirdparty/assimp/code/OptimizeMeshes.cpp
@@ -0,0 +1,256 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file OptimizeMeshes.cpp
+ * @brief Implementation of the aiProcess_OptimizeMeshes step
+ */
+
+
+#ifndef ASSIMP_BUILD_NO_OPTIMIZEMESHES_PROCESS
+
+
+#include "OptimizeMeshes.h"
+#include "ProcessHelper.h"
+#include <assimp/SceneCombiner.h>
+#include <assimp/Exceptional.h>
+
+using namespace Assimp;
+
+static const unsigned int NotSet = 0xffffffff;
+static const unsigned int DeadBeef = 0xdeadbeef;
+
+// ------------------------------------------------------------------------------------------------
+// Constructor to be privately used by Importer
+OptimizeMeshesProcess::OptimizeMeshesProcess()
+ : mScene()
+ , pts(false)
+ , max_verts( NotSet )
+ , max_faces( NotSet ) {
+ // empty
+}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor, private as well
+OptimizeMeshesProcess::~OptimizeMeshesProcess() {
+ // empty
+}
+
+// ------------------------------------------------------------------------------------------------
+// Returns whether the processing step is present in the given flag field.
+bool OptimizeMeshesProcess::IsActive( unsigned int pFlags) const
+{
+ // Our behaviour needs to be different if the SortByPType or SplitLargeMeshes
+ // steps are active. Thus we need to query their flags here and store the
+ // information, although we're breaking const-correctness.
+ // That's a serious design flaw, consider redesign.
+ if( 0 != (pFlags & aiProcess_OptimizeMeshes) ) {
+ pts = (0 != (pFlags & aiProcess_SortByPType));
+ max_verts = ( 0 != ( pFlags & aiProcess_SplitLargeMeshes ) ) ? DeadBeef : max_verts;
+ return true;
+ }
+ return false;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Setup properties for the post-processing step
+void OptimizeMeshesProcess::SetupProperties(const Importer* pImp)
+{
+ if( max_verts == DeadBeef /* magic hack */ ) {
+ max_faces = pImp->GetPropertyInteger(AI_CONFIG_PP_SLM_TRIANGLE_LIMIT,AI_SLM_DEFAULT_MAX_TRIANGLES);
+ max_verts = pImp->GetPropertyInteger(AI_CONFIG_PP_SLM_VERTEX_LIMIT,AI_SLM_DEFAULT_MAX_VERTICES);
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Execute step
+void OptimizeMeshesProcess::Execute( aiScene* pScene)
+{
+ const unsigned int num_old = pScene->mNumMeshes;
+ if (num_old <= 1) {
+ ASSIMP_LOG_DEBUG("Skipping OptimizeMeshesProcess");
+ return;
+ }
+
+ ASSIMP_LOG_DEBUG("OptimizeMeshesProcess begin");
+ mScene = pScene;
+
+ // need to clear persistent members from previous runs
+ merge_list.resize( 0 );
+ output.resize( 0 );
+
+ // ensure we have the right sizes
+ merge_list.reserve(pScene->mNumMeshes);
+ output.reserve(pScene->mNumMeshes);
+
+ // Prepare lookup tables
+ meshes.resize(pScene->mNumMeshes);
+ FindInstancedMeshes(pScene->mRootNode);
+ if( max_verts == DeadBeef ) /* undo the magic hack */
+ max_verts = NotSet;
+
+ // ... instanced meshes are immediately processed and added to the output list
+ for (unsigned int i = 0, n = 0; i < pScene->mNumMeshes;++i) {
+ meshes[i].vertex_format = GetMeshVFormatUnique(pScene->mMeshes[i]);
+
+ if (meshes[i].instance_cnt > 1 && meshes[i].output_id == NotSet ) {
+ meshes[i].output_id = n++;
+ output.push_back(mScene->mMeshes[i]);
+ }
+ }
+
+ // and process all nodes in the scenegraph recursively
+ ProcessNode(pScene->mRootNode);
+ if (!output.size()) {
+ throw DeadlyImportError("OptimizeMeshes: No meshes remaining; there's definitely something wrong");
+ }
+
+ meshes.resize( 0 );
+ ai_assert(output.size() <= num_old);
+
+ mScene->mNumMeshes = static_cast<unsigned int>(output.size());
+ std::copy(output.begin(),output.end(),mScene->mMeshes);
+
+ if (output.size() != num_old) {
+ ASSIMP_LOG_DEBUG_F("OptimizeMeshesProcess finished. Input meshes: ", num_old, ", Output meshes: ", pScene->mNumMeshes);
+ } else {
+ ASSIMP_LOG_DEBUG( "OptimizeMeshesProcess finished" );
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Process meshes for a single node
+void OptimizeMeshesProcess::ProcessNode( aiNode* pNode)
+{
+ for (unsigned int i = 0; i < pNode->mNumMeshes;++i) {
+ unsigned int& im = pNode->mMeshes[i];
+
+ if (meshes[im].instance_cnt > 1) {
+ im = meshes[im].output_id;
+ }
+ else {
+ merge_list.resize( 0 );
+ unsigned int verts = 0, faces = 0;
+
+ // Find meshes to merge with us
+ for (unsigned int a = i+1; a < pNode->mNumMeshes;++a) {
+ unsigned int am = pNode->mMeshes[a];
+ if (meshes[am].instance_cnt == 1 && CanJoin(im,am,verts,faces)) {
+
+ merge_list.push_back(mScene->mMeshes[am]);
+ verts += mScene->mMeshes[am]->mNumVertices;
+ faces += mScene->mMeshes[am]->mNumFaces;
+
+ pNode->mMeshes[a] = pNode->mMeshes[pNode->mNumMeshes - 1];
+ --pNode->mNumMeshes;
+ --a;
+ }
+ }
+
+ // and merge all meshes which we found, replace the old ones
+ if (!merge_list.empty()) {
+ merge_list.push_back(mScene->mMeshes[im]);
+
+ aiMesh* out;
+ SceneCombiner::MergeMeshes(&out,0,merge_list.begin(),merge_list.end());
+ output.push_back(out);
+ } else {
+ output.push_back(mScene->mMeshes[im]);
+ }
+ im = static_cast<unsigned int>(output.size()-1);
+ }
+ }
+
+
+ for( unsigned int i = 0; i < pNode->mNumChildren; ++i ) {
+ ProcessNode( pNode->mChildren[ i ] );
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Check whether two meshes can be joined
+bool OptimizeMeshesProcess::CanJoin ( unsigned int a, unsigned int b, unsigned int verts, unsigned int faces )
+{
+ if (meshes[a].vertex_format != meshes[b].vertex_format)
+ return false;
+
+ aiMesh* ma = mScene->mMeshes[a], *mb = mScene->mMeshes[b];
+
+ if ((NotSet != max_verts && verts+mb->mNumVertices > max_verts) ||
+ (NotSet != max_faces && faces+mb->mNumFaces > max_faces)) {
+ return false;
+ }
+
+ // Never merge unskinned meshes with skinned meshes
+ if (ma->mMaterialIndex != mb->mMaterialIndex || ma->HasBones() != mb->HasBones())
+ return false;
+
+ // Never merge meshes with different kinds of primitives if SortByPType did already
+ // do its work. We would destroy everything again ...
+ if (pts && ma->mPrimitiveTypes != mb->mPrimitiveTypes)
+ return false;
+
+ // If both meshes are skinned, check whether we have many bones defined in both meshes.
+ // If yes, we can join them.
+ if (ma->HasBones()) {
+ // TODO
+ return false;
+ }
+ return true;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Build a LUT of all instanced meshes
+void OptimizeMeshesProcess::FindInstancedMeshes (aiNode* pNode)
+{
+ for( unsigned int i = 0; i < pNode->mNumMeshes; ++i ) {
+ ++meshes[ pNode->mMeshes[ i ] ].instance_cnt;
+ }
+
+ for( unsigned int i = 0; i < pNode->mNumChildren; ++i ) {
+ FindInstancedMeshes( pNode->mChildren[ i ] );
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+
+#endif // !! ASSIMP_BUILD_NO_OPTIMIZEMESHES_PROCESS
diff --git a/thirdparty/assimp/code/OptimizeMeshes.h b/thirdparty/assimp/code/OptimizeMeshes.h
new file mode 100644
index 0000000000..9f46f349b4
--- /dev/null
+++ b/thirdparty/assimp/code/OptimizeMeshes.h
@@ -0,0 +1,186 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file OptimizeMeshes.h
+ * @brief Declares a post processing step to join meshes, if possible
+ */
+#ifndef AI_OPTIMIZEMESHESPROCESS_H_INC
+#define AI_OPTIMIZEMESHESPROCESS_H_INC
+
+#include "BaseProcess.h"
+#include <assimp/types.h>
+#include <vector>
+
+struct aiMesh;
+struct aiNode;
+class OptimizeMeshesProcessTest;
+
+namespace Assimp {
+
+// ---------------------------------------------------------------------------
+/** @brief Postprocessing step to optimize mesh usage
+ *
+ * The implementation looks for meshes that could be joined and joins them.
+ * Usually this will reduce the number of drawcalls.
+ *
+ * @note Instanced meshes are currently not processed.
+ */
+class OptimizeMeshesProcess : public BaseProcess
+{
+public:
+ /// @brief The class constructor.
+ OptimizeMeshesProcess();
+
+ /// @brief The class destcructor,
+ ~OptimizeMeshesProcess();
+
+
+ /** @brief Internal utility to store additional mesh info
+ */
+ struct MeshInfo {
+ MeshInfo() AI_NO_EXCEPT
+ : instance_cnt(0)
+ , vertex_format(0)
+ , output_id(0xffffffff) {
+ // empty
+ }
+
+ //! Number of times this mesh is referenced
+ unsigned int instance_cnt;
+
+ //! Vertex format id
+ unsigned int vertex_format;
+
+ //! Output ID
+ unsigned int output_id;
+ };
+
+public:
+ // -------------------------------------------------------------------
+ bool IsActive( unsigned int pFlags) const;
+
+ // -------------------------------------------------------------------
+ void Execute( aiScene* pScene);
+
+ // -------------------------------------------------------------------
+ void SetupProperties(const Importer* pImp);
+
+
+ // -------------------------------------------------------------------
+ /** @brief Specify whether you want meshes with different
+ * primitive types to be merged as well.
+ *
+ * IsActive() sets this property automatically to true if the
+ * aiProcess_SortByPType flag is found.
+ */
+ void EnablePrimitiveTypeSorting(bool enable) {
+ pts = enable;
+ }
+
+ // Getter
+ bool IsPrimitiveTypeSortingEnabled () const {
+ return pts;
+ }
+
+
+ // -------------------------------------------------------------------
+ /** @brief Specify a maximum size of a single output mesh.
+ *
+ * If a single input mesh already exceeds this limit, it won't
+ * be split.
+ * @param verts Maximum number of vertices per mesh
+ * @param faces Maximum number of faces per mesh
+ */
+ void SetPreferredMeshSizeLimit (unsigned int verts, unsigned int faces)
+ {
+ max_verts = verts;
+ max_faces = faces;
+ }
+
+
+protected:
+
+ // -------------------------------------------------------------------
+ /** @brief Do the actual optimization on all meshes of this node
+ * @param pNode Node we're working with
+ */
+ void ProcessNode( aiNode* pNode);
+
+ // -------------------------------------------------------------------
+ /** @brief Returns true if b can be joined with a
+ *
+ * @param verts Number of output verts up to now
+ * @param faces Number of output faces up to now
+ */
+ bool CanJoin ( unsigned int a, unsigned int b,
+ unsigned int verts, unsigned int faces );
+
+ // -------------------------------------------------------------------
+ /** @brief Find instanced meshes, for the moment we're excluding
+ * them from all optimizations
+ */
+ void FindInstancedMeshes (aiNode* pNode);
+
+private:
+
+ //! Scene we're working with
+ aiScene* mScene;
+
+ //! Per mesh info
+ std::vector<MeshInfo> meshes;
+
+ //! Output meshes
+ std::vector<aiMesh*> output;
+
+ //! @see EnablePrimitiveTypeSorting
+ mutable bool pts;
+
+ //! @see SetPreferredMeshSizeLimit
+ mutable unsigned int max_verts,max_faces;
+
+ //! Temporary storage
+ std::vector<aiMesh*> merge_list;
+};
+
+} // end of namespace Assimp
+
+#endif // AI_CALCTANGENTSPROCESS_H_INC
diff --git a/thirdparty/assimp/code/PolyTools.h b/thirdparty/assimp/code/PolyTools.h
new file mode 100644
index 0000000000..fbbda0e7d1
--- /dev/null
+++ b/thirdparty/assimp/code/PolyTools.h
@@ -0,0 +1,229 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file PolyTools.h, various utilities for our dealings with arbitrary polygons */
+
+#ifndef AI_POLYTOOLS_H_INCLUDED
+#define AI_POLYTOOLS_H_INCLUDED
+
+#include <assimp/material.h>
+#include <assimp/ai_assert.h>
+
+namespace Assimp {
+
+// -------------------------------------------------------------------------------
+/** Compute the signed area of a triangle.
+ * The function accepts an unconstrained template parameter for use with
+ * both aiVector3D and aiVector2D, but generally ignores the third coordinate.*/
+template <typename T>
+inline double GetArea2D(const T& v1, const T& v2, const T& v3)
+{
+ return 0.5 * (v1.x * ((double)v3.y - v2.y) + v2.x * ((double)v1.y - v3.y) + v3.x * ((double)v2.y - v1.y));
+}
+
+// -------------------------------------------------------------------------------
+/** Test if a given point p2 is on the left side of the line formed by p0-p1.
+ * The function accepts an unconstrained template parameter for use with
+ * both aiVector3D and aiVector2D, but generally ignores the third coordinate.*/
+template <typename T>
+inline bool OnLeftSideOfLine2D(const T& p0, const T& p1,const T& p2)
+{
+ return GetArea2D(p0,p2,p1) > 0;
+}
+
+// -------------------------------------------------------------------------------
+/** Test if a given point is inside a given triangle in R2.
+ * The function accepts an unconstrained template parameter for use with
+ * both aiVector3D and aiVector2D, but generally ignores the third coordinate.*/
+template <typename T>
+inline bool PointInTriangle2D(const T& p0, const T& p1,const T& p2, const T& pp)
+{
+ // Point in triangle test using baryzentric coordinates
+ const aiVector2D v0 = p1 - p0;
+ const aiVector2D v1 = p2 - p0;
+ const aiVector2D v2 = pp - p0;
+
+ double dot00 = v0 * v0;
+ double dot01 = v0 * v1;
+ double dot02 = v0 * v2;
+ double dot11 = v1 * v1;
+ double dot12 = v1 * v2;
+
+ const double invDenom = 1 / (dot00 * dot11 - dot01 * dot01);
+ dot11 = (dot11 * dot02 - dot01 * dot12) * invDenom;
+ dot00 = (dot00 * dot12 - dot01 * dot02) * invDenom;
+
+ return (dot11 > 0) && (dot00 > 0) && (dot11 + dot00 < 1);
+}
+
+
+// -------------------------------------------------------------------------------
+/** Check whether the winding order of a given polygon is counter-clockwise.
+ * The function accepts an unconstrained template parameter, but is intended
+ * to be used only with aiVector2D and aiVector3D (z axis is ignored, only
+ * x and y are taken into account).
+ * @note Code taken from http://cgm.cs.mcgill.ca/~godfried/teaching/cg-projects/97/Ian/applet1.html and translated to C++
+ */
+template <typename T>
+inline bool IsCCW(T* in, size_t npoints) {
+ double aa, bb, cc, b, c, theta;
+ double convex_turn;
+ double convex_sum = 0;
+
+ ai_assert(npoints >= 3);
+
+ for (size_t i = 0; i < npoints - 2; i++) {
+ aa = ((in[i+2].x - in[i].x) * (in[i+2].x - in[i].x)) +
+ ((-in[i+2].y + in[i].y) * (-in[i+2].y + in[i].y));
+
+ bb = ((in[i+1].x - in[i].x) * (in[i+1].x - in[i].x)) +
+ ((-in[i+1].y + in[i].y) * (-in[i+1].y + in[i].y));
+
+ cc = ((in[i+2].x - in[i+1].x) *
+ (in[i+2].x - in[i+1].x)) +
+ ((-in[i+2].y + in[i+1].y) *
+ (-in[i+2].y + in[i+1].y));
+
+ b = std::sqrt(bb);
+ c = std::sqrt(cc);
+ theta = std::acos((bb + cc - aa) / (2 * b * c));
+
+ if (OnLeftSideOfLine2D(in[i],in[i+2],in[i+1])) {
+ // if (convex(in[i].x, in[i].y,
+ // in[i+1].x, in[i+1].y,
+ // in[i+2].x, in[i+2].y)) {
+ convex_turn = AI_MATH_PI_F - theta;
+ convex_sum += convex_turn;
+ }
+ else {
+ convex_sum -= AI_MATH_PI_F - theta;
+ }
+ }
+ aa = ((in[1].x - in[npoints-2].x) *
+ (in[1].x - in[npoints-2].x)) +
+ ((-in[1].y + in[npoints-2].y) *
+ (-in[1].y + in[npoints-2].y));
+
+ bb = ((in[0].x - in[npoints-2].x) *
+ (in[0].x - in[npoints-2].x)) +
+ ((-in[0].y + in[npoints-2].y) *
+ (-in[0].y + in[npoints-2].y));
+
+ cc = ((in[1].x - in[0].x) * (in[1].x - in[0].x)) +
+ ((-in[1].y + in[0].y) * (-in[1].y + in[0].y));
+
+ b = std::sqrt(bb);
+ c = std::sqrt(cc);
+ theta = std::acos((bb + cc - aa) / (2 * b * c));
+
+ //if (convex(in[npoints-2].x, in[npoints-2].y,
+ // in[0].x, in[0].y,
+ // in[1].x, in[1].y)) {
+ if (OnLeftSideOfLine2D(in[npoints-2],in[1],in[0])) {
+ convex_turn = AI_MATH_PI_F - theta;
+ convex_sum += convex_turn;
+ }
+ else {
+ convex_sum -= AI_MATH_PI_F - theta;
+ }
+
+ return convex_sum >= (2 * AI_MATH_PI_F);
+}
+
+
+// -------------------------------------------------------------------------------
+/** Compute the normal of an arbitrary polygon in R3.
+ *
+ * The code is based on Newell's formula, that is a polygons normal is the ratio
+ * of its area when projected onto the three coordinate axes.
+ *
+ * @param out Receives the output normal
+ * @param num Number of input vertices
+ * @param x X data source. x[ofs_x*n] is the n'th element.
+ * @param y Y data source. y[ofs_y*n] is the y'th element
+ * @param z Z data source. z[ofs_z*n] is the z'th element
+ *
+ * @note The data arrays must have storage for at least num+2 elements. Using
+ * this method is much faster than the 'other' NewellNormal()
+ */
+template <int ofs_x, int ofs_y, int ofs_z, typename TReal>
+inline void NewellNormal (aiVector3t<TReal>& out, int num, TReal* x, TReal* y, TReal* z)
+{
+ // Duplicate the first two vertices at the end
+ x[(num+0)*ofs_x] = x[0];
+ x[(num+1)*ofs_x] = x[ofs_x];
+
+ y[(num+0)*ofs_y] = y[0];
+ y[(num+1)*ofs_y] = y[ofs_y];
+
+ z[(num+0)*ofs_z] = z[0];
+ z[(num+1)*ofs_z] = z[ofs_z];
+
+ TReal sum_xy = 0.0, sum_yz = 0.0, sum_zx = 0.0;
+
+ TReal *xptr = x +ofs_x, *xlow = x, *xhigh = x + ofs_x*2;
+ TReal *yptr = y +ofs_y, *ylow = y, *yhigh = y + ofs_y*2;
+ TReal *zptr = z +ofs_z, *zlow = z, *zhigh = z + ofs_z*2;
+
+ for (int tmp=0; tmp < num; tmp++) {
+ sum_xy += (*xptr) * ( (*yhigh) - (*ylow) );
+ sum_yz += (*yptr) * ( (*zhigh) - (*zlow) );
+ sum_zx += (*zptr) * ( (*xhigh) - (*xlow) );
+
+ xptr += ofs_x;
+ xlow += ofs_x;
+ xhigh += ofs_x;
+
+ yptr += ofs_y;
+ ylow += ofs_y;
+ yhigh += ofs_y;
+
+ zptr += ofs_z;
+ zlow += ofs_z;
+ zhigh += ofs_z;
+ }
+ out = aiVector3t<TReal>(sum_yz,sum_zx,sum_xy);
+}
+
+} // ! Assimp
+
+#endif
diff --git a/thirdparty/assimp/code/PostStepRegistry.cpp b/thirdparty/assimp/code/PostStepRegistry.cpp
new file mode 100644
index 0000000000..15b4a28843
--- /dev/null
+++ b/thirdparty/assimp/code/PostStepRegistry.cpp
@@ -0,0 +1,251 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file ImporterRegistry.cpp
+
+Central registry for all postprocessing steps available. Do not edit this file
+directly (unless you are adding new steps), instead use the
+corresponding preprocessor flag to selectively disable steps.
+*/
+
+#include "ProcessHelper.h"
+
+#ifndef ASSIMP_BUILD_NO_CALCTANGENTS_PROCESS
+# include "CalcTangentsProcess.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_JOINVERTICES_PROCESS
+# include "JoinVerticesProcess.h"
+#endif
+#if !(defined ASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS && defined ASSIMP_BUILD_NO_FLIPUVS_PROCESS && defined ASSIMP_BUILD_NO_FLIPWINDINGORDER_PROCESS)
+# include "ConvertToLHProcess.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_TRIANGULATE_PROCESS
+# include "TriangulateProcess.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_DROPFACENORMALS_PROCESS
+# include "DropFaceNormalsProcess.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_GENFACENORMALS_PROCESS
+# include "GenFaceNormalsProcess.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_GENVERTEXNORMALS_PROCESS
+# include "GenVertexNormalsProcess.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_REMOVEVC_PROCESS
+# include "RemoveVCProcess.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_SPLITLARGEMESHES_PROCESS
+# include "SplitLargeMeshes.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_PRETRANSFORMVERTICES_PROCESS
+# include "PretransformVertices.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_LIMITBONEWEIGHTS_PROCESS
+# include "LimitBoneWeightsProcess.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
+# include "ValidateDataStructure.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_IMPROVECACHELOCALITY_PROCESS
+# include "ImproveCacheLocality.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_FIXINFACINGNORMALS_PROCESS
+# include "FixNormalsStep.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_REMOVE_REDUNDANTMATERIALS_PROCESS
+# include "RemoveRedundantMaterials.h"
+#endif
+#if (!defined ASSIMP_BUILD_NO_EMBEDTEXTURES_PROCESS)
+# include "EmbedTexturesProcess.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_FINDINVALIDDATA_PROCESS
+# include "FindInvalidDataProcess.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_FINDDEGENERATES_PROCESS
+# include "FindDegenerates.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_SORTBYPTYPE_PROCESS
+# include "SortByPTypeProcess.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_GENUVCOORDS_PROCESS
+# include "ComputeUVMappingProcess.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_TRANSFORMTEXCOORDS_PROCESS
+# include "TextureTransform.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_FINDINSTANCES_PROCESS
+# include "FindInstancesProcess.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_OPTIMIZEMESHES_PROCESS
+# include "OptimizeMeshes.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_OPTIMIZEGRAPH_PROCESS
+# include "OptimizeGraph.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_SPLITBYBONECOUNT_PROCESS
+# include "SplitByBoneCountProcess.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_DEBONE_PROCESS
+# include "DeboneProcess.h"
+#endif
+#if (!defined ASSIMP_BUILD_NO_GLOBALSCALE_PROCESS)
+# include "ScaleProcess.h"
+#endif
+
+namespace Assimp {
+
+// ------------------------------------------------------------------------------------------------
+void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out)
+{
+ // ----------------------------------------------------------------------------
+ // Add an instance of each post processing step here in the order
+ // of sequence it is executed. Steps that are added here are not
+ // validated - as RegisterPPStep() does - all dependencies must be given.
+ // ----------------------------------------------------------------------------
+ out.reserve(31);
+#if (!defined ASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS)
+ out.push_back( new MakeLeftHandedProcess());
+#endif
+#if (!defined ASSIMP_BUILD_NO_FLIPUVS_PROCESS)
+ out.push_back( new FlipUVsProcess());
+#endif
+#if (!defined ASSIMP_BUILD_NO_FLIPWINDINGORDER_PROCESS)
+ out.push_back( new FlipWindingOrderProcess());
+#endif
+#if (!defined ASSIMP_BUILD_NO_REMOVEVC_PROCESS)
+ out.push_back( new RemoveVCProcess());
+#endif
+#if (!defined ASSIMP_BUILD_NO_REMOVE_REDUNDANTMATERIALS_PROCESS)
+ out.push_back( new RemoveRedundantMatsProcess());
+#endif
+#if (!defined ASSIMP_BUILD_NO_EMBEDTEXTURES_PROCESS)
+ out.push_back( new EmbedTexturesProcess());
+#endif
+#if (!defined ASSIMP_BUILD_NO_FINDINSTANCES_PROCESS)
+ out.push_back( new FindInstancesProcess());
+#endif
+#if (!defined ASSIMP_BUILD_NO_OPTIMIZEGRAPH_PROCESS)
+ out.push_back( new OptimizeGraphProcess());
+#endif
+#ifndef ASSIMP_BUILD_NO_GENUVCOORDS_PROCESS
+ out.push_back( new ComputeUVMappingProcess());
+#endif
+#ifndef ASSIMP_BUILD_NO_TRANSFORMTEXCOORDS_PROCESS
+ out.push_back( new TextureTransformStep());
+#endif
+#if (!defined ASSIMP_BUILD_NO_GLOBALSCALE_PROCESS)
+ out.push_back( new ScaleProcess());
+#endif
+#if (!defined ASSIMP_BUILD_NO_PRETRANSFORMVERTICES_PROCESS)
+ out.push_back( new PretransformVertices());
+#endif
+#if (!defined ASSIMP_BUILD_NO_TRIANGULATE_PROCESS)
+ out.push_back( new TriangulateProcess());
+#endif
+#if (!defined ASSIMP_BUILD_NO_FINDDEGENERATES_PROCESS)
+ //find degenerates should run after triangulation (to sort out small
+ //generated triangles) but before sort by p types (in case there are lines
+ //and points generated and inserted into a mesh)
+ out.push_back( new FindDegeneratesProcess());
+#endif
+#if (!defined ASSIMP_BUILD_NO_SORTBYPTYPE_PROCESS)
+ out.push_back( new SortByPTypeProcess());
+#endif
+#if (!defined ASSIMP_BUILD_NO_FINDINVALIDDATA_PROCESS)
+ out.push_back( new FindInvalidDataProcess());
+#endif
+#if (!defined ASSIMP_BUILD_NO_OPTIMIZEMESHES_PROCESS)
+ out.push_back( new OptimizeMeshesProcess());
+#endif
+#if (!defined ASSIMP_BUILD_NO_FIXINFACINGNORMALS_PROCESS)
+ out.push_back( new FixInfacingNormalsProcess());
+#endif
+#if (!defined ASSIMP_BUILD_NO_SPLITBYBONECOUNT_PROCESS)
+ out.push_back( new SplitByBoneCountProcess());
+#endif
+#if (!defined ASSIMP_BUILD_NO_SPLITLARGEMESHES_PROCESS)
+ out.push_back( new SplitLargeMeshesProcess_Triangle());
+#endif
+#if (!defined ASSIMP_BUILD_NO_GENFACENORMALS_PROCESS)
+ out.push_back( new DropFaceNormalsProcess());
+#endif
+#if (!defined ASSIMP_BUILD_NO_GENFACENORMALS_PROCESS)
+ out.push_back( new GenFaceNormalsProcess());
+#endif
+ // .........................................................................
+ // DON'T change the order of these five ..
+ // XXX this is actually a design weakness that dates back to the time
+ // when Importer would maintain the postprocessing step list exclusively.
+ // Now that others access it too, we need a better solution.
+ out.push_back( new ComputeSpatialSortProcess());
+ // .........................................................................
+
+#if (!defined ASSIMP_BUILD_NO_GENVERTEXNORMALS_PROCESS)
+ out.push_back( new GenVertexNormalsProcess());
+#endif
+#if (!defined ASSIMP_BUILD_NO_CALCTANGENTS_PROCESS)
+ out.push_back( new CalcTangentsProcess());
+#endif
+#if (!defined ASSIMP_BUILD_NO_JOINVERTICES_PROCESS)
+ out.push_back( new JoinVerticesProcess());
+#endif
+
+ // .........................................................................
+ out.push_back( new DestroySpatialSortProcess());
+ // .........................................................................
+
+#if (!defined ASSIMP_BUILD_NO_SPLITLARGEMESHES_PROCESS)
+ out.push_back( new SplitLargeMeshesProcess_Vertex());
+#endif
+#if (!defined ASSIMP_BUILD_NO_DEBONE_PROCESS)
+ out.push_back( new DeboneProcess());
+#endif
+#if (!defined ASSIMP_BUILD_NO_LIMITBONEWEIGHTS_PROCESS)
+ out.push_back( new LimitBoneWeightsProcess());
+#endif
+#if (!defined ASSIMP_BUILD_NO_IMPROVECACHELOCALITY_PROCESS)
+ out.push_back( new ImproveCacheLocalityProcess());
+#endif
+}
+
+}
diff --git a/thirdparty/assimp/code/PretransformVertices.cpp b/thirdparty/assimp/code/PretransformVertices.cpp
new file mode 100644
index 0000000000..52001a0578
--- /dev/null
+++ b/thirdparty/assimp/code/PretransformVertices.cpp
@@ -0,0 +1,728 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file PretransformVertices.cpp
+ * @brief Implementation of the "PretransformVertices" post processing step
+*/
+
+
+#include "PretransformVertices.h"
+#include "ProcessHelper.h"
+#include <assimp/SceneCombiner.h>
+#include <assimp/Exceptional.h>
+
+using namespace Assimp;
+
+// some array offsets
+#define AI_PTVS_VERTEX 0x0
+#define AI_PTVS_FACE 0x1
+
+// ------------------------------------------------------------------------------------------------
+// Constructor to be privately used by Importer
+PretransformVertices::PretransformVertices()
+: configKeepHierarchy (false)
+, configNormalize(false)
+, configTransform(false)
+, configTransformation()
+, mConfigPointCloud( false ) {
+ // empty
+}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor, private as well
+PretransformVertices::~PretransformVertices() {
+ // nothing to do here
+}
+
+// ------------------------------------------------------------------------------------------------
+// Returns whether the processing step is present in the given flag field.
+bool PretransformVertices::IsActive( unsigned int pFlags) const
+{
+ return (pFlags & aiProcess_PreTransformVertices) != 0;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Setup import configuration
+void PretransformVertices::SetupProperties(const Importer* pImp)
+{
+ // Get the current value of AI_CONFIG_PP_PTV_KEEP_HIERARCHY, AI_CONFIG_PP_PTV_NORMALIZE,
+ // AI_CONFIG_PP_PTV_ADD_ROOT_TRANSFORMATION and AI_CONFIG_PP_PTV_ROOT_TRANSFORMATION
+ configKeepHierarchy = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_KEEP_HIERARCHY,0));
+ configNormalize = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_NORMALIZE,0));
+ configTransform = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_ADD_ROOT_TRANSFORMATION,0));
+
+ configTransformation = pImp->GetPropertyMatrix(AI_CONFIG_PP_PTV_ROOT_TRANSFORMATION, aiMatrix4x4());
+
+ mConfigPointCloud = pImp->GetPropertyBool(AI_CONFIG_EXPORT_POINT_CLOUDS);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Count the number of nodes
+unsigned int PretransformVertices::CountNodes( aiNode* pcNode )
+{
+ unsigned int iRet = 1;
+ for (unsigned int i = 0;i < pcNode->mNumChildren;++i)
+ {
+ iRet += CountNodes(pcNode->mChildren[i]);
+ }
+ return iRet;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Get a bitwise combination identifying the vertex format of a mesh
+unsigned int PretransformVertices::GetMeshVFormat( aiMesh* pcMesh )
+{
+ // the vertex format is stored in aiMesh::mBones for later retrieval.
+ // there isn't a good reason to compute it a few hundred times
+ // from scratch. The pointer is unused as animations are lost
+ // during PretransformVertices.
+ if (pcMesh->mBones)
+ return (unsigned int)(uint64_t)pcMesh->mBones;
+
+
+ const unsigned int iRet = GetMeshVFormatUnique(pcMesh);
+
+ // store the value for later use
+ pcMesh->mBones = (aiBone**)(uint64_t)iRet;
+ return iRet;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Count the number of vertices in the whole scene and a given
+// material index
+void PretransformVertices::CountVerticesAndFaces( aiScene* pcScene, aiNode* pcNode, unsigned int iMat,
+ unsigned int iVFormat, unsigned int* piFaces, unsigned int* piVertices)
+{
+ for (unsigned int i = 0; i < pcNode->mNumMeshes;++i)
+ {
+ aiMesh* pcMesh = pcScene->mMeshes[ pcNode->mMeshes[i] ];
+ if (iMat == pcMesh->mMaterialIndex && iVFormat == GetMeshVFormat(pcMesh))
+ {
+ *piVertices += pcMesh->mNumVertices;
+ *piFaces += pcMesh->mNumFaces;
+ }
+ }
+ for (unsigned int i = 0;i < pcNode->mNumChildren;++i)
+ {
+ CountVerticesAndFaces(pcScene,pcNode->mChildren[i],iMat,
+ iVFormat,piFaces,piVertices);
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Collect vertex/face data
+void PretransformVertices::CollectData( aiScene* pcScene, aiNode* pcNode, unsigned int iMat,
+ unsigned int iVFormat, aiMesh* pcMeshOut,
+ unsigned int aiCurrent[2], unsigned int* num_refs)
+{
+ // No need to multiply if there's no transformation
+ const bool identity = pcNode->mTransformation.IsIdentity();
+ for (unsigned int i = 0; i < pcNode->mNumMeshes;++i)
+ {
+ aiMesh* pcMesh = pcScene->mMeshes[ pcNode->mMeshes[i] ];
+ if (iMat == pcMesh->mMaterialIndex && iVFormat == GetMeshVFormat(pcMesh))
+ {
+ // Decrement mesh reference counter
+ unsigned int& num_ref = num_refs[pcNode->mMeshes[i]];
+ ai_assert(0 != num_ref);
+ --num_ref;
+ // Save the name of the last mesh
+ if (num_ref==0)
+ {
+ pcMeshOut->mName = pcMesh->mName;
+ }
+
+ if (identity) {
+ // copy positions without modifying them
+ ::memcpy(pcMeshOut->mVertices + aiCurrent[AI_PTVS_VERTEX],
+ pcMesh->mVertices,
+ pcMesh->mNumVertices * sizeof(aiVector3D));
+
+ if (iVFormat & 0x2) {
+ // copy normals without modifying them
+ ::memcpy(pcMeshOut->mNormals + aiCurrent[AI_PTVS_VERTEX],
+ pcMesh->mNormals,
+ pcMesh->mNumVertices * sizeof(aiVector3D));
+ }
+ if (iVFormat & 0x4)
+ {
+ // copy tangents without modifying them
+ ::memcpy(pcMeshOut->mTangents + aiCurrent[AI_PTVS_VERTEX],
+ pcMesh->mTangents,
+ pcMesh->mNumVertices * sizeof(aiVector3D));
+ // copy bitangents without modifying them
+ ::memcpy(pcMeshOut->mBitangents + aiCurrent[AI_PTVS_VERTEX],
+ pcMesh->mBitangents,
+ pcMesh->mNumVertices * sizeof(aiVector3D));
+ }
+ }
+ else
+ {
+ // copy positions, transform them to worldspace
+ for (unsigned int n = 0; n < pcMesh->mNumVertices;++n) {
+ pcMeshOut->mVertices[aiCurrent[AI_PTVS_VERTEX]+n] = pcNode->mTransformation * pcMesh->mVertices[n];
+ }
+ aiMatrix4x4 mWorldIT = pcNode->mTransformation;
+ mWorldIT.Inverse().Transpose();
+
+ // TODO: implement Inverse() for aiMatrix3x3
+ aiMatrix3x3 m = aiMatrix3x3(mWorldIT);
+
+ if (iVFormat & 0x2)
+ {
+ // copy normals, transform them to worldspace
+ for (unsigned int n = 0; n < pcMesh->mNumVertices;++n) {
+ pcMeshOut->mNormals[aiCurrent[AI_PTVS_VERTEX]+n] =
+ (m * pcMesh->mNormals[n]).Normalize();
+ }
+ }
+ if (iVFormat & 0x4)
+ {
+ // copy tangents and bitangents, transform them to worldspace
+ for (unsigned int n = 0; n < pcMesh->mNumVertices;++n) {
+ pcMeshOut->mTangents [aiCurrent[AI_PTVS_VERTEX]+n] = (m * pcMesh->mTangents[n]).Normalize();
+ pcMeshOut->mBitangents[aiCurrent[AI_PTVS_VERTEX]+n] = (m * pcMesh->mBitangents[n]).Normalize();
+ }
+ }
+ }
+ unsigned int p = 0;
+ while (iVFormat & (0x100 << p))
+ {
+ // copy texture coordinates
+ memcpy(pcMeshOut->mTextureCoords[p] + aiCurrent[AI_PTVS_VERTEX],
+ pcMesh->mTextureCoords[p],
+ pcMesh->mNumVertices * sizeof(aiVector3D));
+ ++p;
+ }
+ p = 0;
+ while (iVFormat & (0x1000000 << p))
+ {
+ // copy vertex colors
+ memcpy(pcMeshOut->mColors[p] + aiCurrent[AI_PTVS_VERTEX],
+ pcMesh->mColors[p],
+ pcMesh->mNumVertices * sizeof(aiColor4D));
+ ++p;
+ }
+ // now we need to copy all faces. since we will delete the source mesh afterwards,
+ // we don't need to reallocate the array of indices except if this mesh is
+ // referenced multiple times.
+ for (unsigned int planck = 0;planck < pcMesh->mNumFaces;++planck)
+ {
+ aiFace& f_src = pcMesh->mFaces[planck];
+ aiFace& f_dst = pcMeshOut->mFaces[aiCurrent[AI_PTVS_FACE]+planck];
+
+ const unsigned int num_idx = f_src.mNumIndices;
+
+ f_dst.mNumIndices = num_idx;
+
+ unsigned int* pi;
+ if (!num_ref) { /* if last time the mesh is referenced -> no reallocation */
+ pi = f_dst.mIndices = f_src.mIndices;
+
+ // offset all vertex indices
+ for (unsigned int hahn = 0; hahn < num_idx;++hahn){
+ pi[hahn] += aiCurrent[AI_PTVS_VERTEX];
+ }
+ }
+ else {
+ pi = f_dst.mIndices = new unsigned int[num_idx];
+
+ // copy and offset all vertex indices
+ for (unsigned int hahn = 0; hahn < num_idx;++hahn){
+ pi[hahn] = f_src.mIndices[hahn] + aiCurrent[AI_PTVS_VERTEX];
+ }
+ }
+
+ // Update the mPrimitiveTypes member of the mesh
+ switch (pcMesh->mFaces[planck].mNumIndices)
+ {
+ case 0x1:
+ pcMeshOut->mPrimitiveTypes |= aiPrimitiveType_POINT;
+ break;
+ case 0x2:
+ pcMeshOut->mPrimitiveTypes |= aiPrimitiveType_LINE;
+ break;
+ case 0x3:
+ pcMeshOut->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
+ break;
+ default:
+ pcMeshOut->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
+ break;
+ };
+ }
+ aiCurrent[AI_PTVS_VERTEX] += pcMesh->mNumVertices;
+ aiCurrent[AI_PTVS_FACE] += pcMesh->mNumFaces;
+ }
+ }
+
+ // append all children of us
+ for (unsigned int i = 0;i < pcNode->mNumChildren;++i) {
+ CollectData(pcScene,pcNode->mChildren[i],iMat,
+ iVFormat,pcMeshOut,aiCurrent,num_refs);
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Get a list of all vertex formats that occur for a given material index
+// The output list contains duplicate elements
+void PretransformVertices::GetVFormatList( aiScene* pcScene, unsigned int iMat,
+ std::list<unsigned int>& aiOut)
+{
+ for (unsigned int i = 0; i < pcScene->mNumMeshes;++i)
+ {
+ aiMesh* pcMesh = pcScene->mMeshes[ i ];
+ if (iMat == pcMesh->mMaterialIndex) {
+ aiOut.push_back(GetMeshVFormat(pcMesh));
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Compute the absolute transformation matrices of each node
+void PretransformVertices::ComputeAbsoluteTransform( aiNode* pcNode )
+{
+ if (pcNode->mParent) {
+ pcNode->mTransformation = pcNode->mParent->mTransformation*pcNode->mTransformation;
+ }
+
+ for (unsigned int i = 0;i < pcNode->mNumChildren;++i) {
+ ComputeAbsoluteTransform(pcNode->mChildren[i]);
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Apply the node transformation to a mesh
+void PretransformVertices::ApplyTransform(aiMesh* mesh, const aiMatrix4x4& mat)
+{
+ // Check whether we need to transform the coordinates at all
+ if (!mat.IsIdentity()) {
+
+ if (mesh->HasPositions()) {
+ for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
+ mesh->mVertices[i] = mat * mesh->mVertices[i];
+ }
+ }
+ if (mesh->HasNormals() || mesh->HasTangentsAndBitangents()) {
+ aiMatrix4x4 mWorldIT = mat;
+ mWorldIT.Inverse().Transpose();
+
+ // TODO: implement Inverse() for aiMatrix3x3
+ aiMatrix3x3 m = aiMatrix3x3(mWorldIT);
+
+ if (mesh->HasNormals()) {
+ for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
+ mesh->mNormals[i] = (m * mesh->mNormals[i]).Normalize();
+ }
+ }
+ if (mesh->HasTangentsAndBitangents()) {
+ for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
+ mesh->mTangents[i] = (m * mesh->mTangents[i]).Normalize();
+ mesh->mBitangents[i] = (m * mesh->mBitangents[i]).Normalize();
+ }
+ }
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Simple routine to build meshes in worldspace, no further optimization
+void PretransformVertices::BuildWCSMeshes(std::vector<aiMesh*>& out, aiMesh** in,
+ unsigned int numIn, aiNode* node)
+{
+ // NOTE:
+ // aiMesh::mNumBones store original source mesh, or UINT_MAX if not a copy
+ // aiMesh::mBones store reference to abs. transform we multiplied with
+
+ // process meshes
+ for (unsigned int i = 0; i < node->mNumMeshes;++i) {
+ aiMesh* mesh = in[node->mMeshes[i]];
+
+ // check whether we can operate on this mesh
+ if (!mesh->mBones || *reinterpret_cast<aiMatrix4x4*>(mesh->mBones) == node->mTransformation) {
+ // yes, we can.
+ mesh->mBones = reinterpret_cast<aiBone**> (&node->mTransformation);
+ mesh->mNumBones = UINT_MAX;
+ }
+ else {
+
+ // try to find us in the list of newly created meshes
+ for (unsigned int n = 0; n < out.size(); ++n) {
+ aiMesh* ctz = out[n];
+ if (ctz->mNumBones == node->mMeshes[i] && *reinterpret_cast<aiMatrix4x4*>(ctz->mBones) == node->mTransformation) {
+
+ // ok, use this one. Update node mesh index
+ node->mMeshes[i] = numIn + n;
+ }
+ }
+ if (node->mMeshes[i] < numIn) {
+ // Worst case. Need to operate on a full copy of the mesh
+ ASSIMP_LOG_INFO("PretransformVertices: Copying mesh due to mismatching transforms");
+ aiMesh* ntz;
+
+ const unsigned int tmp = mesh->mNumBones; //
+ mesh->mNumBones = 0;
+ SceneCombiner::Copy(&ntz,mesh);
+ mesh->mNumBones = tmp;
+
+ ntz->mNumBones = node->mMeshes[i];
+ ntz->mBones = reinterpret_cast<aiBone**> (&node->mTransformation);
+
+ out.push_back(ntz);
+
+ node->mMeshes[i] = static_cast<unsigned int>(numIn + out.size() - 1);
+ }
+ }
+ }
+
+ // call children
+ for (unsigned int i = 0; i < node->mNumChildren;++i)
+ BuildWCSMeshes(out,in,numIn,node->mChildren[i]);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Reset transformation matrices to identity
+void PretransformVertices::MakeIdentityTransform(aiNode* nd)
+{
+ nd->mTransformation = aiMatrix4x4();
+
+ // call children
+ for (unsigned int i = 0; i < nd->mNumChildren;++i)
+ MakeIdentityTransform(nd->mChildren[i]);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Build reference counters for all meshes
+void PretransformVertices::BuildMeshRefCountArray(aiNode* nd, unsigned int * refs)
+{
+ for (unsigned int i = 0; i< nd->mNumMeshes;++i)
+ refs[nd->mMeshes[i]]++;
+
+ // call children
+ for (unsigned int i = 0; i < nd->mNumChildren;++i)
+ BuildMeshRefCountArray(nd->mChildren[i],refs);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+void PretransformVertices::Execute( aiScene* pScene)
+{
+ ASSIMP_LOG_DEBUG("PretransformVerticesProcess begin");
+
+ // Return immediately if we have no meshes
+ if (!pScene->mNumMeshes)
+ return;
+
+ const unsigned int iOldMeshes = pScene->mNumMeshes;
+ const unsigned int iOldAnimationChannels = pScene->mNumAnimations;
+ const unsigned int iOldNodes = CountNodes(pScene->mRootNode);
+
+ if(configTransform) {
+ pScene->mRootNode->mTransformation = configTransformation;
+ }
+
+ // first compute absolute transformation matrices for all nodes
+ ComputeAbsoluteTransform(pScene->mRootNode);
+
+ // Delete aiMesh::mBones for all meshes. The bones are
+ // removed during this step and we need the pointer as
+ // temporary storage
+ for (unsigned int i = 0; i < pScene->mNumMeshes;++i) {
+ aiMesh* mesh = pScene->mMeshes[i];
+
+ for (unsigned int a = 0; a < mesh->mNumBones;++a)
+ delete mesh->mBones[a];
+
+ delete[] mesh->mBones;
+ mesh->mBones = NULL;
+ }
+
+ // now build a list of output meshes
+ std::vector<aiMesh*> apcOutMeshes;
+
+ // Keep scene hierarchy? It's an easy job in this case ...
+ // we go on and transform all meshes, if one is referenced by nodes
+ // with different absolute transformations a depth copy of the mesh
+ // is required.
+ if( configKeepHierarchy ) {
+
+ // Hack: store the matrix we're transforming a mesh with in aiMesh::mBones
+ BuildWCSMeshes(apcOutMeshes,pScene->mMeshes,pScene->mNumMeshes, pScene->mRootNode);
+
+ // ... if new meshes have been generated, append them to the end of the scene
+ if (apcOutMeshes.size() > 0) {
+ aiMesh** npp = new aiMesh*[pScene->mNumMeshes + apcOutMeshes.size()];
+
+ memcpy(npp,pScene->mMeshes,sizeof(aiMesh*)*pScene->mNumMeshes);
+ memcpy(npp+pScene->mNumMeshes,&apcOutMeshes[0],sizeof(aiMesh*)*apcOutMeshes.size());
+
+ pScene->mNumMeshes += static_cast<unsigned int>(apcOutMeshes.size());
+ delete[] pScene->mMeshes; pScene->mMeshes = npp;
+ }
+
+ // now iterate through all meshes and transform them to worldspace
+ for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
+ ApplyTransform(pScene->mMeshes[i],*reinterpret_cast<aiMatrix4x4*>( pScene->mMeshes[i]->mBones ));
+
+ // prevent improper destruction
+ pScene->mMeshes[i]->mBones = NULL;
+ pScene->mMeshes[i]->mNumBones = 0;
+ }
+ } else {
+ apcOutMeshes.reserve(pScene->mNumMaterials<<1u);
+ std::list<unsigned int> aiVFormats;
+
+ std::vector<unsigned int> s(pScene->mNumMeshes,0);
+ BuildMeshRefCountArray(pScene->mRootNode,&s[0]);
+
+ for (unsigned int i = 0; i < pScene->mNumMaterials;++i) {
+ // get the list of all vertex formats for this material
+ aiVFormats.clear();
+ GetVFormatList(pScene,i,aiVFormats);
+ aiVFormats.sort();
+ aiVFormats.unique();
+ for (std::list<unsigned int>::const_iterator j = aiVFormats.begin();j != aiVFormats.end();++j) {
+ unsigned int iVertices = 0;
+ unsigned int iFaces = 0;
+ CountVerticesAndFaces(pScene,pScene->mRootNode,i,*j,&iFaces,&iVertices);
+ if (0 != iFaces && 0 != iVertices)
+ {
+ apcOutMeshes.push_back(new aiMesh());
+ aiMesh* pcMesh = apcOutMeshes.back();
+ pcMesh->mNumFaces = iFaces;
+ pcMesh->mNumVertices = iVertices;
+ pcMesh->mFaces = new aiFace[iFaces];
+ pcMesh->mVertices = new aiVector3D[iVertices];
+ pcMesh->mMaterialIndex = i;
+ if ((*j) & 0x2)pcMesh->mNormals = new aiVector3D[iVertices];
+ if ((*j) & 0x4)
+ {
+ pcMesh->mTangents = new aiVector3D[iVertices];
+ pcMesh->mBitangents = new aiVector3D[iVertices];
+ }
+ iFaces = 0;
+ while ((*j) & (0x100 << iFaces))
+ {
+ pcMesh->mTextureCoords[iFaces] = new aiVector3D[iVertices];
+ if ((*j) & (0x10000 << iFaces))pcMesh->mNumUVComponents[iFaces] = 3;
+ else pcMesh->mNumUVComponents[iFaces] = 2;
+ iFaces++;
+ }
+ iFaces = 0;
+ while ((*j) & (0x1000000 << iFaces))
+ pcMesh->mColors[iFaces++] = new aiColor4D[iVertices];
+
+ // fill the mesh ...
+ unsigned int aiTemp[2] = {0,0};
+ CollectData(pScene,pScene->mRootNode,i,*j,pcMesh,aiTemp,&s[0]);
+ }
+ }
+ }
+
+ // If no meshes are referenced in the node graph it is possible that we get no output meshes.
+ if (apcOutMeshes.empty()) {
+
+ throw DeadlyImportError("No output meshes: all meshes are orphaned and are not referenced by any nodes");
+ }
+ else
+ {
+ // now delete all meshes in the scene and build a new mesh list
+ for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
+ {
+ aiMesh* mesh = pScene->mMeshes[i];
+ mesh->mNumBones = 0;
+ mesh->mBones = NULL;
+
+ // we're reusing the face index arrays. avoid destruction
+ for (unsigned int a = 0; a < mesh->mNumFaces; ++a) {
+ mesh->mFaces[a].mNumIndices = 0;
+ mesh->mFaces[a].mIndices = NULL;
+ }
+
+ delete mesh;
+
+ // Invalidate the contents of the old mesh array. We will most
+ // likely have less output meshes now, so the last entries of
+ // the mesh array are not overridden. We set them to NULL to
+ // make sure the developer gets notified when his application
+ // attempts to access these fields ...
+ mesh = NULL;
+ }
+
+ // It is impossible that we have more output meshes than
+ // input meshes, so we can easily reuse the old mesh array
+ pScene->mNumMeshes = (unsigned int)apcOutMeshes.size();
+ for (unsigned int i = 0; i < pScene->mNumMeshes;++i) {
+ pScene->mMeshes[i] = apcOutMeshes[i];
+ }
+ }
+ }
+
+ // remove all animations from the scene
+ for (unsigned int i = 0; i < pScene->mNumAnimations;++i)
+ delete pScene->mAnimations[i];
+ delete[] pScene->mAnimations;
+
+ pScene->mAnimations = NULL;
+ pScene->mNumAnimations = 0;
+
+ // --- we need to keep all cameras and lights
+ for (unsigned int i = 0; i < pScene->mNumCameras;++i)
+ {
+ aiCamera* cam = pScene->mCameras[i];
+ const aiNode* nd = pScene->mRootNode->FindNode(cam->mName);
+ ai_assert(NULL != nd);
+
+ // multiply all properties of the camera with the absolute
+ // transformation of the corresponding node
+ cam->mPosition = nd->mTransformation * cam->mPosition;
+ cam->mLookAt = aiMatrix3x3( nd->mTransformation ) * cam->mLookAt;
+ cam->mUp = aiMatrix3x3( nd->mTransformation ) * cam->mUp;
+ }
+
+ for (unsigned int i = 0; i < pScene->mNumLights;++i)
+ {
+ aiLight* l = pScene->mLights[i];
+ const aiNode* nd = pScene->mRootNode->FindNode(l->mName);
+ ai_assert(NULL != nd);
+
+ // multiply all properties of the camera with the absolute
+ // transformation of the corresponding node
+ l->mPosition = nd->mTransformation * l->mPosition;
+ l->mDirection = aiMatrix3x3( nd->mTransformation ) * l->mDirection;
+ l->mUp = aiMatrix3x3( nd->mTransformation ) * l->mUp;
+ }
+
+ if( !configKeepHierarchy ) {
+
+ // now delete all nodes in the scene and build a new
+ // flat node graph with a root node and some level 1 children
+ aiNode* newRoot = new aiNode();
+ newRoot->mName = pScene->mRootNode->mName;
+ delete pScene->mRootNode;
+ pScene->mRootNode = newRoot;
+
+ if (1 == pScene->mNumMeshes && !pScene->mNumLights && !pScene->mNumCameras)
+ {
+ pScene->mRootNode->mNumMeshes = 1;
+ pScene->mRootNode->mMeshes = new unsigned int[1];
+ pScene->mRootNode->mMeshes[0] = 0;
+ }
+ else
+ {
+ pScene->mRootNode->mNumChildren = pScene->mNumMeshes+pScene->mNumLights+pScene->mNumCameras;
+ aiNode** nodes = pScene->mRootNode->mChildren = new aiNode*[pScene->mRootNode->mNumChildren];
+
+ // generate mesh nodes
+ for (unsigned int i = 0; i < pScene->mNumMeshes;++i,++nodes)
+ {
+ aiNode* pcNode = new aiNode();
+ *nodes = pcNode;
+ pcNode->mParent = pScene->mRootNode;
+ pcNode->mName = pScene->mMeshes[i]->mName;
+
+ // setup mesh indices
+ pcNode->mNumMeshes = 1;
+ pcNode->mMeshes = new unsigned int[1];
+ pcNode->mMeshes[0] = i;
+ }
+ // generate light nodes
+ for (unsigned int i = 0; i < pScene->mNumLights;++i,++nodes)
+ {
+ aiNode* pcNode = new aiNode();
+ *nodes = pcNode;
+ pcNode->mParent = pScene->mRootNode;
+ pcNode->mName.length = ai_snprintf(pcNode->mName.data, MAXLEN, "light_%u",i);
+ pScene->mLights[i]->mName = pcNode->mName;
+ }
+ // generate camera nodes
+ for (unsigned int i = 0; i < pScene->mNumCameras;++i,++nodes)
+ {
+ aiNode* pcNode = new aiNode();
+ *nodes = pcNode;
+ pcNode->mParent = pScene->mRootNode;
+ pcNode->mName.length = ::ai_snprintf(pcNode->mName.data,MAXLEN,"cam_%u",i);
+ pScene->mCameras[i]->mName = pcNode->mName;
+ }
+ }
+ }
+ else {
+ // ... and finally set the transformation matrix of all nodes to identity
+ MakeIdentityTransform(pScene->mRootNode);
+ }
+
+ if (configNormalize) {
+ // compute the boundary of all meshes
+ aiVector3D min,max;
+ MinMaxChooser<aiVector3D> ()(min,max);
+
+ for (unsigned int a = 0; a < pScene->mNumMeshes; ++a) {
+ aiMesh* m = pScene->mMeshes[a];
+ for (unsigned int i = 0; i < m->mNumVertices;++i) {
+ min = std::min(m->mVertices[i],min);
+ max = std::max(m->mVertices[i],max);
+ }
+ }
+
+ // find the dominant axis
+ aiVector3D d = max-min;
+ const ai_real div = std::max(d.x,std::max(d.y,d.z))*ai_real( 0.5);
+
+ d = min + d * (ai_real)0.5;
+ for (unsigned int a = 0; a < pScene->mNumMeshes; ++a) {
+ aiMesh* m = pScene->mMeshes[a];
+ for (unsigned int i = 0; i < m->mNumVertices;++i) {
+ m->mVertices[i] = (m->mVertices[i]-d)/div;
+ }
+ }
+ }
+
+ // print statistics
+ if (!DefaultLogger::isNullLogger()) {
+ ASSIMP_LOG_DEBUG("PretransformVerticesProcess finished");
+
+ ASSIMP_LOG_INFO_F("Removed ", iOldNodes, " nodes and ", iOldAnimationChannels, " animation channels (",
+ CountNodes(pScene->mRootNode) ," output nodes)" );
+ ASSIMP_LOG_INFO_F("Kept ", pScene->mNumLights, " lights and ", pScene->mNumCameras, " cameras." );
+ ASSIMP_LOG_INFO_F("Moved ", iOldMeshes, " meshes to WCS (number of output meshes: ", pScene->mNumMeshes, ")");
+ }
+}
diff --git a/thirdparty/assimp/code/PretransformVertices.h b/thirdparty/assimp/code/PretransformVertices.h
new file mode 100644
index 0000000000..b7329af130
--- /dev/null
+++ b/thirdparty/assimp/code/PretransformVertices.h
@@ -0,0 +1,163 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file PretransformVertices.h
+ * @brief Defines a post processing step to pretransform all
+ * vertices in the scenegraph
+ */
+#ifndef AI_PRETRANSFORMVERTICES_H_INC
+#define AI_PRETRANSFORMVERTICES_H_INC
+
+#include "BaseProcess.h"
+#include <assimp/mesh.h>
+#include <list>
+#include <vector>
+
+struct aiNode;
+class PretransformVerticesTest;
+namespace Assimp {
+
+// ---------------------------------------------------------------------------
+/** The PretransformVertices pre-transforms all vertices in the node tree
+ * and removes the whole graph. The output is a list of meshes, one for
+ * each material.
+*/
+class ASSIMP_API PretransformVertices : public BaseProcess {
+public:
+ PretransformVertices ();
+ ~PretransformVertices ();
+
+ // -------------------------------------------------------------------
+ // Check whether step is active
+ bool IsActive( unsigned int pFlags) const;
+
+ // -------------------------------------------------------------------
+ // Execute step on a given scene
+ void Execute( aiScene* pScene);
+
+ // -------------------------------------------------------------------
+ // Setup import settings
+ void SetupProperties(const Importer* pImp);
+
+ // -------------------------------------------------------------------
+ /** @brief Toggle the 'keep hierarchy' option
+ * @param d hm ... difficult to guess what this means, hu!?
+ */
+ void KeepHierarchy(bool d) {
+ configKeepHierarchy = d;
+ }
+
+ // -------------------------------------------------------------------
+ /** @brief Check whether 'keep hierarchy' is currently enabled.
+ * @return ...
+ */
+ bool IsHierarchyKept() const {
+ return configKeepHierarchy;
+ }
+
+private:
+ // -------------------------------------------------------------------
+ // Count the number of nodes
+ unsigned int CountNodes( aiNode* pcNode );
+
+ // -------------------------------------------------------------------
+ // Get a bitwise combination identifying the vertex format of a mesh
+ unsigned int GetMeshVFormat(aiMesh* pcMesh);
+
+ // -------------------------------------------------------------------
+ // Count the number of vertices in the whole scene and a given
+ // material index
+ void CountVerticesAndFaces( aiScene* pcScene, aiNode* pcNode,
+ unsigned int iMat,
+ unsigned int iVFormat,
+ unsigned int* piFaces,
+ unsigned int* piVertices);
+
+ // -------------------------------------------------------------------
+ // Collect vertex/face data
+ void CollectData( aiScene* pcScene, aiNode* pcNode,
+ unsigned int iMat,
+ unsigned int iVFormat,
+ aiMesh* pcMeshOut,
+ unsigned int aiCurrent[2],
+ unsigned int* num_refs);
+
+ // -------------------------------------------------------------------
+ // Get a list of all vertex formats that occur for a given material
+ // The output list contains duplicate elements
+ void GetVFormatList( aiScene* pcScene, unsigned int iMat,
+ std::list<unsigned int>& aiOut);
+
+ // -------------------------------------------------------------------
+ // Compute the absolute transformation matrices of each node
+ void ComputeAbsoluteTransform( aiNode* pcNode );
+
+ // -------------------------------------------------------------------
+ // Simple routine to build meshes in worldspace, no further optimization
+ void BuildWCSMeshes(std::vector<aiMesh*>& out, aiMesh** in,
+ unsigned int numIn, aiNode* node);
+
+ // -------------------------------------------------------------------
+ // Apply the node transformation to a mesh
+ void ApplyTransform(aiMesh* mesh, const aiMatrix4x4& mat);
+
+ // -------------------------------------------------------------------
+ // Reset transformation matrices to identity
+ void MakeIdentityTransform(aiNode* nd);
+
+ // -------------------------------------------------------------------
+ // Build reference counters for all meshes
+ void BuildMeshRefCountArray(aiNode* nd, unsigned int * refs);
+
+
+
+ //! Configuration option: keep scene hierarchy as long as possible
+ bool configKeepHierarchy;
+ bool configNormalize;
+ bool configTransform;
+ aiMatrix4x4 configTransformation;
+ bool mConfigPointCloud;
+};
+
+} // end of namespace Assimp
+
+#endif // !!AI_GENFACENORMALPROCESS_H_INC
diff --git a/thirdparty/assimp/code/ProcessHelper.cpp b/thirdparty/assimp/code/ProcessHelper.cpp
new file mode 100644
index 0000000000..59869fdff7
--- /dev/null
+++ b/thirdparty/assimp/code/ProcessHelper.cpp
@@ -0,0 +1,443 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/// @file ProcessHelper.cpp
+/** Implement shared utility functions for postprocessing steps */
+
+
+#include "ProcessHelper.h"
+
+
+#include <limits>
+
+namespace Assimp {
+
+// -------------------------------------------------------------------------------
+void ConvertListToStrings(const std::string& in, std::list<std::string>& out)
+{
+ const char* s = in.c_str();
+ while (*s) {
+ SkipSpacesAndLineEnd(&s);
+ if (*s == '\'') {
+ const char* base = ++s;
+ while (*s != '\'') {
+ ++s;
+ if (*s == '\0') {
+ ASSIMP_LOG_ERROR("ConvertListToString: String list is ill-formatted");
+ return;
+ }
+ }
+ out.push_back(std::string(base,(size_t)(s-base)));
+ ++s;
+ }
+ else {
+ out.push_back(GetNextToken(s));
+ }
+ }
+}
+
+// -------------------------------------------------------------------------------
+void FindAABBTransformed (const aiMesh* mesh, aiVector3D& min, aiVector3D& max,
+ const aiMatrix4x4& m)
+{
+ min = aiVector3D ( ai_real( 10e10 ), ai_real( 10e10 ), ai_real( 10e10 ) );
+ max = aiVector3D ( ai_real( -10e10 ), ai_real( -10e10 ), ai_real( -10e10 ) );
+ for (unsigned int i = 0;i < mesh->mNumVertices;++i)
+ {
+ const aiVector3D v = m * mesh->mVertices[i];
+ min = std::min(v,min);
+ max = std::max(v,max);
+ }
+}
+
+// -------------------------------------------------------------------------------
+void FindMeshCenter (aiMesh* mesh, aiVector3D& out, aiVector3D& min, aiVector3D& max)
+{
+ ArrayBounds(mesh->mVertices,mesh->mNumVertices, min,max);
+ out = min + (max-min)*(ai_real)0.5;
+}
+
+// -------------------------------------------------------------------------------
+void FindSceneCenter (aiScene* scene, aiVector3D& out, aiVector3D& min, aiVector3D& max) {
+ if ( NULL == scene ) {
+ return;
+ }
+
+ if ( 0 == scene->mNumMeshes ) {
+ return;
+ }
+ FindMeshCenter(scene->mMeshes[0], out, min, max);
+ for (unsigned int i = 1; i < scene->mNumMeshes; ++i) {
+ aiVector3D tout, tmin, tmax;
+ FindMeshCenter(scene->mMeshes[i], tout, tmin, tmax);
+ if (min[0] > tmin[0]) min[0] = tmin[0];
+ if (min[1] > tmin[1]) min[1] = tmin[1];
+ if (min[2] > tmin[2]) min[2] = tmin[2];
+ if (max[0] < tmax[0]) max[0] = tmax[0];
+ if (max[1] < tmax[1]) max[1] = tmax[1];
+ if (max[2] < tmax[2]) max[2] = tmax[2];
+ }
+ out = min + (max-min)*(ai_real)0.5;
+}
+
+
+// -------------------------------------------------------------------------------
+void FindMeshCenterTransformed (aiMesh* mesh, aiVector3D& out, aiVector3D& min,
+ aiVector3D& max, const aiMatrix4x4& m)
+{
+ FindAABBTransformed(mesh,min,max,m);
+ out = min + (max-min)*(ai_real)0.5;
+}
+
+// -------------------------------------------------------------------------------
+void FindMeshCenter (aiMesh* mesh, aiVector3D& out)
+{
+ aiVector3D min,max;
+ FindMeshCenter(mesh,out,min,max);
+}
+
+// -------------------------------------------------------------------------------
+void FindMeshCenterTransformed (aiMesh* mesh, aiVector3D& out,
+ const aiMatrix4x4& m)
+{
+ aiVector3D min,max;
+ FindMeshCenterTransformed(mesh,out,min,max,m);
+}
+
+// -------------------------------------------------------------------------------
+ai_real ComputePositionEpsilon(const aiMesh* pMesh)
+{
+ const ai_real epsilon = ai_real( 1e-4 );
+
+ // calculate the position bounds so we have a reliable epsilon to check position differences against
+ aiVector3D minVec, maxVec;
+ ArrayBounds(pMesh->mVertices,pMesh->mNumVertices,minVec,maxVec);
+ return (maxVec - minVec).Length() * epsilon;
+}
+
+// -------------------------------------------------------------------------------
+ai_real ComputePositionEpsilon(const aiMesh* const* pMeshes, size_t num)
+{
+ ai_assert( NULL != pMeshes );
+
+ const ai_real epsilon = ai_real( 1e-4 );
+
+ // calculate the position bounds so we have a reliable epsilon to check position differences against
+ aiVector3D minVec, maxVec, mi, ma;
+ MinMaxChooser<aiVector3D>()(minVec,maxVec);
+
+ for (size_t a = 0; a < num; ++a) {
+ const aiMesh* pMesh = pMeshes[a];
+ ArrayBounds(pMesh->mVertices,pMesh->mNumVertices,mi,ma);
+
+ minVec = std::min(minVec,mi);
+ maxVec = std::max(maxVec,ma);
+ }
+ return (maxVec - minVec).Length() * epsilon;
+}
+
+
+// -------------------------------------------------------------------------------
+unsigned int GetMeshVFormatUnique(const aiMesh* pcMesh)
+{
+ ai_assert(NULL != pcMesh);
+
+ // FIX: the hash may never be 0. Otherwise a comparison against
+ // nullptr could be successful
+ unsigned int iRet = 1;
+
+ // normals
+ if (pcMesh->HasNormals())iRet |= 0x2;
+ // tangents and bitangents
+ if (pcMesh->HasTangentsAndBitangents())iRet |= 0x4;
+
+#ifdef BOOST_STATIC_ASSERT
+ BOOST_STATIC_ASSERT(8 >= AI_MAX_NUMBER_OF_COLOR_SETS);
+ BOOST_STATIC_ASSERT(8 >= AI_MAX_NUMBER_OF_TEXTURECOORDS);
+#endif
+
+ // texture coordinates
+ unsigned int p = 0;
+ while (pcMesh->HasTextureCoords(p))
+ {
+ iRet |= (0x100 << p);
+ if (3 == pcMesh->mNumUVComponents[p])
+ iRet |= (0x10000 << p);
+
+ ++p;
+ }
+ // vertex colors
+ p = 0;
+ while (pcMesh->HasVertexColors(p))iRet |= (0x1000000 << p++);
+ return iRet;
+}
+
+// -------------------------------------------------------------------------------
+VertexWeightTable* ComputeVertexBoneWeightTable(const aiMesh* pMesh)
+{
+ if (!pMesh || !pMesh->mNumVertices || !pMesh->mNumBones) {
+ return NULL;
+ }
+
+ VertexWeightTable* avPerVertexWeights = new VertexWeightTable[pMesh->mNumVertices];
+ for (unsigned int i = 0; i < pMesh->mNumBones;++i) {
+
+ aiBone* bone = pMesh->mBones[i];
+ for (unsigned int a = 0; a < bone->mNumWeights;++a) {
+ const aiVertexWeight& weight = bone->mWeights[a];
+ avPerVertexWeights[weight.mVertexId].push_back( std::pair<unsigned int,float>(i,weight.mWeight) );
+ }
+ }
+ return avPerVertexWeights;
+}
+
+
+// -------------------------------------------------------------------------------
+const char* TextureTypeToString(aiTextureType in)
+{
+ switch (in)
+ {
+ case aiTextureType_NONE:
+ return "n/a";
+ case aiTextureType_DIFFUSE:
+ return "Diffuse";
+ case aiTextureType_SPECULAR:
+ return "Specular";
+ case aiTextureType_AMBIENT:
+ return "Ambient";
+ case aiTextureType_EMISSIVE:
+ return "Emissive";
+ case aiTextureType_OPACITY:
+ return "Opacity";
+ case aiTextureType_NORMALS:
+ return "Normals";
+ case aiTextureType_HEIGHT:
+ return "Height";
+ case aiTextureType_SHININESS:
+ return "Shininess";
+ case aiTextureType_DISPLACEMENT:
+ return "Displacement";
+ case aiTextureType_LIGHTMAP:
+ return "Lightmap";
+ case aiTextureType_REFLECTION:
+ return "Reflection";
+ case aiTextureType_UNKNOWN:
+ return "Unknown";
+ default:
+ break;
+ }
+
+ ai_assert(false);
+ return "BUG";
+}
+
+// -------------------------------------------------------------------------------
+const char* MappingTypeToString(aiTextureMapping in)
+{
+ switch (in)
+ {
+ case aiTextureMapping_UV:
+ return "UV";
+ case aiTextureMapping_BOX:
+ return "Box";
+ case aiTextureMapping_SPHERE:
+ return "Sphere";
+ case aiTextureMapping_CYLINDER:
+ return "Cylinder";
+ case aiTextureMapping_PLANE:
+ return "Plane";
+ case aiTextureMapping_OTHER:
+ return "Other";
+ default:
+ break;
+ }
+
+ ai_assert(false);
+ return "BUG";
+}
+
+
+// -------------------------------------------------------------------------------
+aiMesh* MakeSubmesh(const aiMesh *pMesh, const std::vector<unsigned int> &subMeshFaces, unsigned int subFlags)
+{
+ aiMesh *oMesh = new aiMesh();
+ std::vector<unsigned int> vMap(pMesh->mNumVertices,UINT_MAX);
+
+ size_t numSubVerts = 0;
+ size_t numSubFaces = subMeshFaces.size();
+
+ for(unsigned int i=0;i<numSubFaces;i++) {
+ const aiFace &f = pMesh->mFaces[subMeshFaces[i]];
+
+ for(unsigned int j=0;j<f.mNumIndices;j++) {
+ if(vMap[f.mIndices[j]]==UINT_MAX) {
+ vMap[f.mIndices[j]] = static_cast<unsigned int>(numSubVerts++);
+ }
+ }
+ }
+
+ oMesh->mName = pMesh->mName;
+
+ oMesh->mMaterialIndex = pMesh->mMaterialIndex;
+ oMesh->mPrimitiveTypes = pMesh->mPrimitiveTypes;
+
+ // create all the arrays for this mesh if the old mesh contained them
+
+ oMesh->mNumFaces = static_cast<unsigned int>(subMeshFaces.size());
+ oMesh->mNumVertices = static_cast<unsigned int>(numSubVerts);
+ oMesh->mVertices = new aiVector3D[numSubVerts];
+ if( pMesh->HasNormals() ) {
+ oMesh->mNormals = new aiVector3D[numSubVerts];
+ }
+
+ if( pMesh->HasTangentsAndBitangents() ) {
+ oMesh->mTangents = new aiVector3D[numSubVerts];
+ oMesh->mBitangents = new aiVector3D[numSubVerts];
+ }
+
+ for( size_t a = 0; pMesh->HasTextureCoords(static_cast<unsigned int>(a)) ; ++a ) {
+ oMesh->mTextureCoords[a] = new aiVector3D[numSubVerts];
+ oMesh->mNumUVComponents[a] = pMesh->mNumUVComponents[a];
+ }
+
+ for( size_t a = 0; pMesh->HasVertexColors( static_cast<unsigned int>(a)); ++a ) {
+ oMesh->mColors[a] = new aiColor4D[numSubVerts];
+ }
+
+ // and copy over the data, generating faces with linear indices along the way
+ oMesh->mFaces = new aiFace[numSubFaces];
+
+ for(unsigned int a = 0; a < numSubFaces; ++a ) {
+
+ const aiFace& srcFace = pMesh->mFaces[subMeshFaces[a]];
+ aiFace& dstFace = oMesh->mFaces[a];
+ dstFace.mNumIndices = srcFace.mNumIndices;
+ dstFace.mIndices = new unsigned int[dstFace.mNumIndices];
+
+ // accumulate linearly all the vertices of the source face
+ for( size_t b = 0; b < dstFace.mNumIndices; ++b ) {
+ dstFace.mIndices[b] = vMap[srcFace.mIndices[b]];
+ }
+ }
+
+ for(unsigned int srcIndex = 0; srcIndex < pMesh->mNumVertices; ++srcIndex ) {
+ unsigned int nvi = vMap[srcIndex];
+ if(nvi==UINT_MAX) {
+ continue;
+ }
+
+ oMesh->mVertices[nvi] = pMesh->mVertices[srcIndex];
+ if( pMesh->HasNormals() ) {
+ oMesh->mNormals[nvi] = pMesh->mNormals[srcIndex];
+ }
+
+ if( pMesh->HasTangentsAndBitangents() ) {
+ oMesh->mTangents[nvi] = pMesh->mTangents[srcIndex];
+ oMesh->mBitangents[nvi] = pMesh->mBitangents[srcIndex];
+ }
+ for( size_t c = 0, cc = pMesh->GetNumUVChannels(); c < cc; ++c ) {
+ oMesh->mTextureCoords[c][nvi] = pMesh->mTextureCoords[c][srcIndex];
+ }
+ for( size_t c = 0, cc = pMesh->GetNumColorChannels(); c < cc; ++c ) {
+ oMesh->mColors[c][nvi] = pMesh->mColors[c][srcIndex];
+ }
+ }
+
+ if(~subFlags&AI_SUBMESH_FLAGS_SANS_BONES) {
+ std::vector<unsigned int> subBones(pMesh->mNumBones,0);
+
+ for(unsigned int a=0;a<pMesh->mNumBones;++a) {
+ const aiBone* bone = pMesh->mBones[a];
+
+ for(unsigned int b=0;b<bone->mNumWeights;b++) {
+ unsigned int v = vMap[bone->mWeights[b].mVertexId];
+
+ if(v!=UINT_MAX) {
+ subBones[a]++;
+ }
+ }
+ }
+
+ for(unsigned int a=0;a<pMesh->mNumBones;++a) {
+ if(subBones[a]>0) {
+ oMesh->mNumBones++;
+ }
+ }
+
+ if(oMesh->mNumBones) {
+ oMesh->mBones = new aiBone*[oMesh->mNumBones]();
+ unsigned int nbParanoia = oMesh->mNumBones;
+
+ oMesh->mNumBones = 0; //rewind
+
+ for(unsigned int a=0;a<pMesh->mNumBones;++a) {
+ if(subBones[a]==0) {
+ continue;
+ }
+ aiBone *newBone = new aiBone;
+ oMesh->mBones[oMesh->mNumBones++] = newBone;
+
+ const aiBone* bone = pMesh->mBones[a];
+
+ newBone->mName = bone->mName;
+ newBone->mOffsetMatrix = bone->mOffsetMatrix;
+ newBone->mWeights = new aiVertexWeight[subBones[a]];
+
+ for(unsigned int b=0;b<bone->mNumWeights;b++) {
+ const unsigned int v = vMap[bone->mWeights[b].mVertexId];
+
+ if(v!=UINT_MAX) {
+ aiVertexWeight w(v,bone->mWeights[b].mWeight);
+ newBone->mWeights[newBone->mNumWeights++] = w;
+ }
+ }
+ }
+
+ ai_assert(nbParanoia==oMesh->mNumBones);
+ (void)nbParanoia; // remove compiler warning on release build
+ }
+ }
+
+ return oMesh;
+}
+
+} // namespace Assimp
diff --git a/thirdparty/assimp/code/ProcessHelper.h b/thirdparty/assimp/code/ProcessHelper.h
new file mode 100644
index 0000000000..c59f3217bf
--- /dev/null
+++ b/thirdparty/assimp/code/ProcessHelper.h
@@ -0,0 +1,386 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+#ifndef AI_PROCESS_HELPER_H_INCLUDED
+#define AI_PROCESS_HELPER_H_INCLUDED
+
+#include <assimp/postprocess.h>
+#include <assimp/anim.h>
+#include <assimp/mesh.h>
+#include <assimp/material.h>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/scene.h>
+
+#include <assimp/SpatialSort.h>
+#include "BaseProcess.h"
+#include <assimp/ParsingUtils.h>
+
+#include <list>
+
+// -------------------------------------------------------------------------------
+// Some extensions to std namespace. Mainly std::min and std::max for all
+// flat data types in the aiScene. They're used to quickly determine the
+// min/max bounds of data arrays.
+#ifdef __cplusplus
+namespace std {
+
+ // std::min for aiVector3D
+ template <typename TReal>
+ inline ::aiVector3t<TReal> min (const ::aiVector3t<TReal>& a, const ::aiVector3t<TReal>& b) {
+ return ::aiVector3t<TReal> (min(a.x,b.x),min(a.y,b.y),min(a.z,b.z));
+ }
+
+ // std::max for aiVector3t<TReal>
+ template <typename TReal>
+ inline ::aiVector3t<TReal> max (const ::aiVector3t<TReal>& a, const ::aiVector3t<TReal>& b) {
+ return ::aiVector3t<TReal> (max(a.x,b.x),max(a.y,b.y),max(a.z,b.z));
+ }
+
+ // std::min for aiVector2t<TReal>
+ template <typename TReal>
+ inline ::aiVector2t<TReal> min (const ::aiVector2t<TReal>& a, const ::aiVector2t<TReal>& b) {
+ return ::aiVector2t<TReal> (min(a.x,b.x),min(a.y,b.y));
+ }
+
+ // std::max for aiVector2t<TReal>
+ template <typename TReal>
+ inline ::aiVector2t<TReal> max (const ::aiVector2t<TReal>& a, const ::aiVector2t<TReal>& b) {
+ return ::aiVector2t<TReal> (max(a.x,b.x),max(a.y,b.y));
+ }
+
+ // std::min for aiColor4D
+ template <typename TReal>
+ inline ::aiColor4t<TReal> min (const ::aiColor4t<TReal>& a, const ::aiColor4t<TReal>& b) {
+ return ::aiColor4t<TReal> (min(a.r,b.r),min(a.g,b.g),min(a.b,b.b),min(a.a,b.a));
+ }
+
+ // std::max for aiColor4D
+ template <typename TReal>
+ inline ::aiColor4t<TReal> max (const ::aiColor4t<TReal>& a, const ::aiColor4t<TReal>& b) {
+ return ::aiColor4t<TReal> (max(a.r,b.r),max(a.g,b.g),max(a.b,b.b),max(a.a,b.a));
+ }
+
+
+ // std::min for aiQuaterniont<TReal>
+ template <typename TReal>
+ inline ::aiQuaterniont<TReal> min (const ::aiQuaterniont<TReal>& a, const ::aiQuaterniont<TReal>& b) {
+ return ::aiQuaterniont<TReal> (min(a.w,b.w),min(a.x,b.x),min(a.y,b.y),min(a.z,b.z));
+ }
+
+ // std::max for aiQuaterniont<TReal>
+ template <typename TReal>
+ inline ::aiQuaterniont<TReal> max (const ::aiQuaterniont<TReal>& a, const ::aiQuaterniont<TReal>& b) {
+ return ::aiQuaterniont<TReal> (max(a.w,b.w),max(a.x,b.x),max(a.y,b.y),max(a.z,b.z));
+ }
+
+
+
+ // std::min for aiVectorKey
+ inline ::aiVectorKey min (const ::aiVectorKey& a, const ::aiVectorKey& b) {
+ return ::aiVectorKey (min(a.mTime,b.mTime),min(a.mValue,b.mValue));
+ }
+
+ // std::max for aiVectorKey
+ inline ::aiVectorKey max (const ::aiVectorKey& a, const ::aiVectorKey& b) {
+ return ::aiVectorKey (max(a.mTime,b.mTime),max(a.mValue,b.mValue));
+ }
+
+ // std::min for aiQuatKey
+ inline ::aiQuatKey min (const ::aiQuatKey& a, const ::aiQuatKey& b) {
+ return ::aiQuatKey (min(a.mTime,b.mTime),min(a.mValue,b.mValue));
+ }
+
+ // std::max for aiQuatKey
+ inline ::aiQuatKey max (const ::aiQuatKey& a, const ::aiQuatKey& b) {
+ return ::aiQuatKey (max(a.mTime,b.mTime),max(a.mValue,b.mValue));
+ }
+
+ // std::min for aiVertexWeight
+ inline ::aiVertexWeight min (const ::aiVertexWeight& a, const ::aiVertexWeight& b) {
+ return ::aiVertexWeight (min(a.mVertexId,b.mVertexId),min(a.mWeight,b.mWeight));
+ }
+
+ // std::max for aiVertexWeight
+ inline ::aiVertexWeight max (const ::aiVertexWeight& a, const ::aiVertexWeight& b) {
+ return ::aiVertexWeight (max(a.mVertexId,b.mVertexId),max(a.mWeight,b.mWeight));
+ }
+
+} // end namespace std
+#endif // !! C++
+
+namespace Assimp {
+
+// -------------------------------------------------------------------------------
+// Start points for ArrayBounds<T> for all supported Ts
+template <typename T>
+struct MinMaxChooser;
+
+template <> struct MinMaxChooser<float> {
+ void operator ()(float& min,float& max) {
+ max = -1e10f;
+ min = 1e10f;
+}};
+template <> struct MinMaxChooser<double> {
+ void operator ()(double& min,double& max) {
+ max = -1e10;
+ min = 1e10;
+}};
+template <> struct MinMaxChooser<unsigned int> {
+ void operator ()(unsigned int& min,unsigned int& max) {
+ max = 0;
+ min = (1u<<(sizeof(unsigned int)*8-1));
+}};
+
+template <typename T> struct MinMaxChooser< aiVector3t<T> > {
+ void operator ()(aiVector3t<T>& min,aiVector3t<T>& max) {
+ max = aiVector3t<T>(-1e10f,-1e10f,-1e10f);
+ min = aiVector3t<T>( 1e10f, 1e10f, 1e10f);
+}};
+template <typename T> struct MinMaxChooser< aiVector2t<T> > {
+ void operator ()(aiVector2t<T>& min,aiVector2t<T>& max) {
+ max = aiVector2t<T>(-1e10f,-1e10f);
+ min = aiVector2t<T>( 1e10f, 1e10f);
+ }};
+template <typename T> struct MinMaxChooser< aiColor4t<T> > {
+ void operator ()(aiColor4t<T>& min,aiColor4t<T>& max) {
+ max = aiColor4t<T>(-1e10f,-1e10f,-1e10f,-1e10f);
+ min = aiColor4t<T>( 1e10f, 1e10f, 1e10f, 1e10f);
+}};
+
+template <typename T> struct MinMaxChooser< aiQuaterniont<T> > {
+ void operator ()(aiQuaterniont<T>& min,aiQuaterniont<T>& max) {
+ max = aiQuaterniont<T>(-1e10f,-1e10f,-1e10f,-1e10f);
+ min = aiQuaterniont<T>( 1e10f, 1e10f, 1e10f, 1e10f);
+}};
+
+template <> struct MinMaxChooser<aiVectorKey> {
+ void operator ()(aiVectorKey& min,aiVectorKey& max) {
+ MinMaxChooser<double>()(min.mTime,max.mTime);
+ MinMaxChooser<aiVector3D>()(min.mValue,max.mValue);
+}};
+template <> struct MinMaxChooser<aiQuatKey> {
+ void operator ()(aiQuatKey& min,aiQuatKey& max) {
+ MinMaxChooser<double>()(min.mTime,max.mTime);
+ MinMaxChooser<aiQuaternion>()(min.mValue,max.mValue);
+}};
+
+template <> struct MinMaxChooser<aiVertexWeight> {
+ void operator ()(aiVertexWeight& min,aiVertexWeight& max) {
+ MinMaxChooser<unsigned int>()(min.mVertexId,max.mVertexId);
+ MinMaxChooser<float>()(min.mWeight,max.mWeight);
+}};
+
+// -------------------------------------------------------------------------------
+/** @brief Find the min/max values of an array of Ts
+ * @param in Input array
+ * @param size Number of elements to process
+ * @param[out] min minimum value
+ * @param[out] max maximum value
+ */
+template <typename T>
+inline void ArrayBounds(const T* in, unsigned int size, T& min, T& max)
+{
+ MinMaxChooser<T> ()(min,max);
+ for (unsigned int i = 0; i < size;++i) {
+ min = std::min(in[i],min);
+ max = std::max(in[i],max);
+ }
+}
+
+
+// -------------------------------------------------------------------------------
+/** Little helper function to calculate the quadratic difference
+ * of two colours.
+ * @param pColor1 First color
+ * @param pColor2 second color
+ * @return Quadratic color difference */
+inline ai_real GetColorDifference( const aiColor4D& pColor1, const aiColor4D& pColor2)
+{
+ const aiColor4D c (pColor1.r - pColor2.r, pColor1.g - pColor2.g, pColor1.b - pColor2.b, pColor1.a - pColor2.a);
+ return c.r*c.r + c.g*c.g + c.b*c.b + c.a*c.a;
+}
+
+
+// -------------------------------------------------------------------------------
+/** @brief Extract single strings from a list of identifiers
+ * @param in Input string list.
+ * @param out Receives a list of clean output strings
+ * @sdee #AI_CONFIG_PP_OG_EXCLUDE_LIST */
+void ConvertListToStrings(const std::string& in, std::list<std::string>& out);
+
+
+// -------------------------------------------------------------------------------
+/** @brief Compute the AABB of a mesh after applying a given transform
+ * @param mesh Input mesh
+ * @param[out] min Receives minimum transformed vertex
+ * @param[out] max Receives maximum transformed vertex
+ * @param m Transformation matrix to be applied */
+void FindAABBTransformed (const aiMesh* mesh, aiVector3D& min, aiVector3D& max, const aiMatrix4x4& m);
+
+
+// -------------------------------------------------------------------------------
+/** @brief Helper function to determine the 'real' center of a mesh
+ *
+ * That is the center of its axis-aligned bounding box.
+ * @param mesh Input mesh
+ * @param[out] min Minimum vertex of the mesh
+ * @param[out] max maximum vertex of the mesh
+ * @param[out] out Center point */
+void FindMeshCenter (aiMesh* mesh, aiVector3D& out, aiVector3D& min, aiVector3D& max);
+
+// -------------------------------------------------------------------------------
+/** @brief Helper function to determine the 'real' center of a scene
+ *
+ * That is the center of its axis-aligned bounding box.
+ * @param scene Input scene
+ * @param[out] min Minimum vertex of the scene
+ * @param[out] max maximum vertex of the scene
+ * @param[out] out Center point */
+void FindSceneCenter (aiScene* scene, aiVector3D& out, aiVector3D& min, aiVector3D& max);
+
+
+// -------------------------------------------------------------------------------
+// Helper function to determine the 'real' center of a mesh after applying a given transform
+void FindMeshCenterTransformed (aiMesh* mesh, aiVector3D& out, aiVector3D& min,aiVector3D& max, const aiMatrix4x4& m);
+
+
+// -------------------------------------------------------------------------------
+// Helper function to determine the 'real' center of a mesh
+void FindMeshCenter (aiMesh* mesh, aiVector3D& out);
+
+
+// -------------------------------------------------------------------------------
+// Helper function to determine the 'real' center of a mesh after applying a given transform
+void FindMeshCenterTransformed (aiMesh* mesh, aiVector3D& out,const aiMatrix4x4& m);
+
+
+// -------------------------------------------------------------------------------
+// Compute a good epsilon value for position comparisons on a mesh
+ai_real ComputePositionEpsilon(const aiMesh* pMesh);
+
+
+// -------------------------------------------------------------------------------
+// Compute a good epsilon value for position comparisons on a array of meshes
+ai_real ComputePositionEpsilon(const aiMesh* const* pMeshes, size_t num);
+
+
+// -------------------------------------------------------------------------------
+// Compute an unique value for the vertex format of a mesh
+unsigned int GetMeshVFormatUnique(const aiMesh* pcMesh);
+
+
+// defs for ComputeVertexBoneWeightTable()
+typedef std::pair <unsigned int,float> PerVertexWeight;
+typedef std::vector <PerVertexWeight> VertexWeightTable;
+
+// -------------------------------------------------------------------------------
+// Compute a per-vertex bone weight table
+VertexWeightTable* ComputeVertexBoneWeightTable(const aiMesh* pMesh);
+
+
+// -------------------------------------------------------------------------------
+// Get a string for a given aiTextureType
+const char* TextureTypeToString(aiTextureType in);
+
+
+// -------------------------------------------------------------------------------
+// Get a string for a given aiTextureMapping
+const char* MappingTypeToString(aiTextureMapping in);
+
+
+// flags for MakeSubmesh()
+#define AI_SUBMESH_FLAGS_SANS_BONES 0x1
+
+// -------------------------------------------------------------------------------
+// Split a mesh given a list of faces to be contained in the sub mesh
+aiMesh* MakeSubmesh(const aiMesh *superMesh, const std::vector<unsigned int> &subMeshFaces, unsigned int subFlags);
+
+// -------------------------------------------------------------------------------
+// Utility postprocess step to share the spatial sort tree between
+// all steps which use it to speedup its computations.
+class ComputeSpatialSortProcess : public BaseProcess
+{
+ bool IsActive( unsigned int pFlags) const
+ {
+ return NULL != shared && 0 != (pFlags & (aiProcess_CalcTangentSpace |
+ aiProcess_GenNormals | aiProcess_JoinIdenticalVertices));
+ }
+
+ void Execute( aiScene* pScene)
+ {
+ typedef std::pair<SpatialSort, ai_real> _Type;
+ ASSIMP_LOG_DEBUG("Generate spatially-sorted vertex cache");
+
+ std::vector<_Type>* p = new std::vector<_Type>(pScene->mNumMeshes);
+ std::vector<_Type>::iterator it = p->begin();
+
+ for (unsigned int i = 0; i < pScene->mNumMeshes; ++i, ++it) {
+ aiMesh* mesh = pScene->mMeshes[i];
+ _Type& blubb = *it;
+ blubb.first.Fill(mesh->mVertices,mesh->mNumVertices,sizeof(aiVector3D));
+ blubb.second = ComputePositionEpsilon(mesh);
+ }
+
+ shared->AddProperty(AI_SPP_SPATIAL_SORT,p);
+ }
+};
+
+// -------------------------------------------------------------------------------
+// ... and the same again to cleanup the whole stuff
+class DestroySpatialSortProcess : public BaseProcess
+{
+ bool IsActive( unsigned int pFlags) const
+ {
+ return NULL != shared && 0 != (pFlags & (aiProcess_CalcTangentSpace |
+ aiProcess_GenNormals | aiProcess_JoinIdenticalVertices));
+ }
+
+ void Execute( aiScene* /*pScene*/)
+ {
+ shared->RemoveProperty(AI_SPP_SPATIAL_SORT);
+ }
+};
+
+
+
+} // ! namespace Assimp
+#endif // !! AI_PROCESS_HELPER_H_INCLUDED
diff --git a/thirdparty/assimp/code/RawLoader.cpp b/thirdparty/assimp/code/RawLoader.cpp
new file mode 100644
index 0000000000..d0da247e47
--- /dev/null
+++ b/thirdparty/assimp/code/RawLoader.cpp
@@ -0,0 +1,331 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file RawLoader.cpp
+ * @brief Implementation of the RAW importer class
+ */
+
+
+#ifndef ASSIMP_BUILD_NO_RAW_IMPORTER
+
+// internal headers
+#include "RawLoader.h"
+#include <assimp/ParsingUtils.h>
+#include <assimp/fast_atof.h>
+#include <memory>
+#include <assimp/IOSystem.hpp>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/scene.h>
+#include <assimp/importerdesc.h>
+
+using namespace Assimp;
+
+static const aiImporterDesc desc = {
+ "Raw Importer",
+ "",
+ "",
+ "",
+ aiImporterFlags_SupportTextFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "raw"
+};
+
+// ------------------------------------------------------------------------------------------------
+// Constructor to be privately used by Importer
+RAWImporter::RAWImporter()
+{}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor, private as well
+RAWImporter::~RAWImporter()
+{}
+
+// ------------------------------------------------------------------------------------------------
+// Returns whether the class can handle the format of the given file.
+bool RAWImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const
+{
+ return SimpleExtensionCheck(pFile,"raw");
+}
+
+// ------------------------------------------------------------------------------------------------
+const aiImporterDesc* RAWImporter::GetInfo () const
+{
+ return &desc;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Imports the given file into the given scene structure.
+void RAWImporter::InternReadFile( const std::string& pFile,
+ aiScene* pScene, IOSystem* pIOHandler)
+{
+ std::unique_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
+
+ // Check whether we can read from the file
+ if( file.get() == NULL) {
+ throw DeadlyImportError( "Failed to open RAW file " + pFile + ".");
+ }
+
+ // allocate storage and copy the contents of the file to a memory buffer
+ // (terminate it with zero)
+ std::vector<char> mBuffer2;
+ TextFileToBuffer(file.get(),mBuffer2);
+ const char* buffer = &mBuffer2[0];
+
+ // list of groups loaded from the file
+ std::vector< GroupInformation > outGroups(1,GroupInformation("<default>"));
+ std::vector< GroupInformation >::iterator curGroup = outGroups.begin();
+
+ // now read all lines
+ char line[4096];
+ while (GetNextLine(buffer,line))
+ {
+ // if the line starts with a non-numeric identifier, it marks
+ // the beginning of a new group
+ const char* sz = line;SkipSpaces(&sz);
+ if (IsLineEnd(*sz))continue;
+ if (!IsNumeric(*sz))
+ {
+ const char* sz2 = sz;
+ while (!IsSpaceOrNewLine(*sz2))++sz2;
+ const unsigned int length = (unsigned int)(sz2-sz);
+
+ // find an existing group with this name
+ for (std::vector< GroupInformation >::iterator it = outGroups.begin(), end = outGroups.end();
+ it != end;++it)
+ {
+ if (length == (*it).name.length() && !::strcmp(sz,(*it).name.c_str()))
+ {
+ curGroup = it;sz2 = NULL;
+ break;
+ }
+ }
+ if (sz2)
+ {
+ outGroups.push_back(GroupInformation(std::string(sz,length)));
+ curGroup = outGroups.end()-1;
+ }
+ }
+ else
+ {
+ // there can be maximally 12 floats plus an extra texture file name
+ float data[12];
+ unsigned int num;
+ for (num = 0; num < 12;++num)
+ {
+ if(!SkipSpaces(&sz) || !IsNumeric(*sz))break;
+ sz = fast_atoreal_move<float>(sz,data[num]);
+ }
+ if (num != 12 && num != 9)
+ {
+ ASSIMP_LOG_ERROR("A line may have either 9 or 12 floats and an optional texture");
+ continue;
+ }
+
+ MeshInformation* output = NULL;
+
+ const char* sz2 = sz;
+ unsigned int length;
+ if (!IsLineEnd(*sz))
+ {
+ while (!IsSpaceOrNewLine(*sz2))++sz2;
+ length = (unsigned int)(sz2-sz);
+ }
+ else if (9 == num)
+ {
+ sz = "%default%";
+ length = 9;
+ }
+ else
+ {
+ sz = "";
+ length = 0;
+ }
+
+ // search in the list of meshes whether we have one with this texture
+ for (auto &mesh : (*curGroup).meshes)
+ {
+ if (length == mesh.name.length() && (length ? !::strcmp(sz, mesh.name.c_str()) : true))
+ {
+ output = &mesh;
+ break;
+ }
+ }
+ // if we don't have the mesh, create it
+ if (!output)
+ {
+ (*curGroup).meshes.push_back(MeshInformation(std::string(sz,length)));
+ output = &((*curGroup).meshes.back());
+ }
+ if (12 == num)
+ {
+ aiColor4D v(data[0],data[1],data[2],1.0f);
+ output->colors.push_back(v);
+ output->colors.push_back(v);
+ output->colors.push_back(v);
+
+ output->vertices.push_back(aiVector3D(data[3],data[4],data[5]));
+ output->vertices.push_back(aiVector3D(data[6],data[7],data[8]));
+ output->vertices.push_back(aiVector3D(data[9],data[10],data[11]));
+ }
+ else
+ {
+ output->vertices.push_back(aiVector3D(data[0],data[1],data[2]));
+ output->vertices.push_back(aiVector3D(data[3],data[4],data[5]));
+ output->vertices.push_back(aiVector3D(data[6],data[7],data[8]));
+ }
+ }
+ }
+
+ pScene->mRootNode = new aiNode();
+ pScene->mRootNode->mName.Set("<RawRoot>");
+
+ // count the number of valid groups
+ // (meshes can't be empty)
+ for (auto & outGroup : outGroups)
+ {
+ if (!outGroup.meshes.empty())
+ {
+ ++pScene->mRootNode->mNumChildren;
+ pScene->mNumMeshes += (unsigned int) outGroup.meshes.size();
+ }
+ }
+
+ if (!pScene->mNumMeshes)
+ {
+ throw DeadlyImportError("RAW: No meshes loaded. The file seems to be corrupt or empty.");
+ }
+
+ pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
+ aiNode** cc;
+ if (1 == pScene->mRootNode->mNumChildren)
+ {
+ cc = &pScene->mRootNode;
+ pScene->mRootNode->mNumChildren = 0;
+ } else {
+ cc = new aiNode*[pScene->mRootNode->mNumChildren];
+ memset(cc, 0, sizeof(aiNode*) * pScene->mRootNode->mNumChildren);
+ pScene->mRootNode->mChildren = cc;
+ }
+
+ pScene->mNumMaterials = pScene->mNumMeshes;
+ aiMaterial** mats = pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
+
+ unsigned int meshIdx = 0;
+ for (auto & outGroup : outGroups)
+ {
+ if (outGroup.meshes.empty())continue;
+
+ aiNode* node;
+ if (pScene->mRootNode->mNumChildren)
+ {
+ node = *cc = new aiNode();
+ node->mParent = pScene->mRootNode;
+ }
+ else node = *cc;
+ node->mName.Set(outGroup.name);
+
+ // add all meshes
+ node->mNumMeshes = (unsigned int) outGroup.meshes.size();
+ unsigned int* pi = node->mMeshes = new unsigned int[ node->mNumMeshes ];
+ for (std::vector< MeshInformation >::iterator it2 = outGroup.meshes.begin(),
+ end2 = outGroup.meshes.end(); it2 != end2; ++it2)
+ {
+ ai_assert(!(*it2).vertices.empty());
+
+ // allocate the mesh
+ *pi++ = meshIdx;
+ aiMesh* mesh = pScene->mMeshes[meshIdx] = new aiMesh();
+ mesh->mMaterialIndex = meshIdx++;
+
+ mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
+
+ // allocate storage for the vertex components and copy them
+ mesh->mNumVertices = (unsigned int)(*it2).vertices.size();
+ mesh->mVertices = new aiVector3D[ mesh->mNumVertices ];
+ ::memcpy(mesh->mVertices,&(*it2).vertices[0],sizeof(aiVector3D)*mesh->mNumVertices);
+
+ if ((*it2).colors.size())
+ {
+ ai_assert((*it2).colors.size() == mesh->mNumVertices);
+
+ mesh->mColors[0] = new aiColor4D[ mesh->mNumVertices ];
+ ::memcpy(mesh->mColors[0],&(*it2).colors[0],sizeof(aiColor4D)*mesh->mNumVertices);
+ }
+
+ // generate triangles
+ ai_assert(0 == mesh->mNumVertices % 3);
+ aiFace* fc = mesh->mFaces = new aiFace[ mesh->mNumFaces = mesh->mNumVertices/3 ];
+ aiFace* const fcEnd = fc + mesh->mNumFaces;
+ unsigned int n = 0;
+ while (fc != fcEnd)
+ {
+ aiFace& f = *fc++;
+ f.mIndices = new unsigned int[f.mNumIndices = 3];
+ for (unsigned int m = 0; m < 3;++m)
+ f.mIndices[m] = n++;
+ }
+
+ // generate a material for the mesh
+ aiMaterial* mat = new aiMaterial();
+
+ aiColor4D clr(1.0f,1.0f,1.0f,1.0f);
+ if ("%default%" == (*it2).name) // a gray default material
+ {
+ clr.r = clr.g = clr.b = 0.6f;
+ }
+ else if ((*it2).name.length() > 0) // a texture
+ {
+ aiString s;
+ s.Set((*it2).name);
+ mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(0));
+ }
+ mat->AddProperty<aiColor4D>(&clr,1,AI_MATKEY_COLOR_DIFFUSE);
+ *mats++ = mat;
+ }
+ }
+}
+
+#endif // !! ASSIMP_BUILD_NO_RAW_IMPORTER
diff --git a/thirdparty/assimp/code/RemoveComments.cpp b/thirdparty/assimp/code/RemoveComments.cpp
new file mode 100644
index 0000000000..91700a7699
--- /dev/null
+++ b/thirdparty/assimp/code/RemoveComments.cpp
@@ -0,0 +1,113 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file RemoveComments.cpp
+ * @brief Defines the CommentRemover utility class
+ */
+
+#include <assimp/RemoveComments.h>
+#include <assimp/ParsingUtils.h>
+
+namespace Assimp {
+
+// ------------------------------------------------------------------------------------------------
+// Remove line comments from a file
+void CommentRemover::RemoveLineComments(const char* szComment,
+ char* szBuffer, char chReplacement /* = ' ' */)
+{
+ // validate parameters
+ ai_assert(NULL != szComment && NULL != szBuffer && *szComment);
+
+ const size_t len = strlen(szComment);
+ while (*szBuffer) {
+
+ // skip over quotes
+ if (*szBuffer == '\"' || *szBuffer == '\'')
+ while (*szBuffer++ && *szBuffer != '\"' && *szBuffer != '\'');
+
+ if (!strncmp(szBuffer,szComment,len)) {
+ while (!IsLineEnd(*szBuffer))
+ *szBuffer++ = chReplacement;
+
+ if (!*szBuffer) {
+ break;
+ }
+ }
+ ++szBuffer;
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Remove multi-line comments from a file
+void CommentRemover::RemoveMultiLineComments(const char* szCommentStart,
+ const char* szCommentEnd,char* szBuffer,
+ char chReplacement)
+{
+ // validate parameters
+ ai_assert(NULL != szCommentStart && NULL != szCommentEnd &&
+ NULL != szBuffer && *szCommentStart && *szCommentEnd);
+
+ const size_t len = strlen(szCommentEnd);
+ const size_t len2 = strlen(szCommentStart);
+
+ while (*szBuffer) {
+ // skip over quotes
+ if (*szBuffer == '\"' || *szBuffer == '\'')
+ while (*szBuffer++ && *szBuffer != '\"' && *szBuffer != '\'');
+
+ if (!strncmp(szBuffer,szCommentStart,len2)) {
+ while (*szBuffer) {
+ if (!::strncmp(szBuffer,szCommentEnd,len)) {
+ for (unsigned int i = 0; i < len;++i)
+ *szBuffer++ = chReplacement;
+
+ break;
+ }
+ *szBuffer++ = chReplacement;
+ }
+ continue;
+ }
+ ++szBuffer;
+ }
+}
+
+} // !! Assimp
diff --git a/thirdparty/assimp/code/RemoveRedundantMaterials.cpp b/thirdparty/assimp/code/RemoveRedundantMaterials.cpp
new file mode 100644
index 0000000000..632bdca3fe
--- /dev/null
+++ b/thirdparty/assimp/code/RemoveRedundantMaterials.cpp
@@ -0,0 +1,221 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+/** @file RemoveRedundantMaterials.cpp
+ * @brief Implementation of the "RemoveRedundantMaterials" post processing step
+*/
+
+// internal headers
+
+#include "RemoveRedundantMaterials.h"
+#include <assimp/ParsingUtils.h>
+#include "ProcessHelper.h"
+#include "MaterialSystem.h"
+#include <stdio.h>
+
+using namespace Assimp;
+
+// ------------------------------------------------------------------------------------------------
+// Constructor to be privately used by Importer
+RemoveRedundantMatsProcess::RemoveRedundantMatsProcess()
+: configFixedMaterials() {
+ // nothing to do here
+}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor, private as well
+RemoveRedundantMatsProcess::~RemoveRedundantMatsProcess()
+{
+ // nothing to do here
+}
+
+// ------------------------------------------------------------------------------------------------
+// Returns whether the processing step is present in the given flag field.
+bool RemoveRedundantMatsProcess::IsActive( unsigned int pFlags) const
+{
+ return (pFlags & aiProcess_RemoveRedundantMaterials) != 0;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Setup import properties
+void RemoveRedundantMatsProcess::SetupProperties(const Importer* pImp)
+{
+ // Get value of AI_CONFIG_PP_RRM_EXCLUDE_LIST
+ configFixedMaterials = pImp->GetPropertyString(AI_CONFIG_PP_RRM_EXCLUDE_LIST,"");
+}
+
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+void RemoveRedundantMatsProcess::Execute( aiScene* pScene)
+{
+ ASSIMP_LOG_DEBUG("RemoveRedundantMatsProcess begin");
+
+ unsigned int redundantRemoved = 0, unreferencedRemoved = 0;
+ if (pScene->mNumMaterials)
+ {
+ // Find out which materials are referenced by meshes
+ std::vector<bool> abReferenced(pScene->mNumMaterials,false);
+ for (unsigned int i = 0;i < pScene->mNumMeshes;++i)
+ abReferenced[pScene->mMeshes[i]->mMaterialIndex] = true;
+
+ // If a list of materials to be excluded was given, match the list with
+ // our imported materials and 'salt' all positive matches to ensure that
+ // we get unique hashes later.
+ if (configFixedMaterials.length()) {
+
+ std::list<std::string> strings;
+ ConvertListToStrings(configFixedMaterials,strings);
+
+ for (unsigned int i = 0; i < pScene->mNumMaterials;++i) {
+ aiMaterial* mat = pScene->mMaterials[i];
+
+ aiString name;
+ mat->Get(AI_MATKEY_NAME,name);
+
+ if (name.length) {
+ std::list<std::string>::const_iterator it = std::find(strings.begin(), strings.end(), name.data);
+ if (it != strings.end()) {
+
+ // Our brilliant 'salt': A single material property with ~ as first
+ // character to mark it as internal and temporary.
+ const int dummy = 1;
+ ((aiMaterial*)mat)->AddProperty(&dummy,1,"~RRM.UniqueMaterial",0,0);
+
+ // Keep this material even if no mesh references it
+ abReferenced[i] = true;
+ ASSIMP_LOG_DEBUG_F( "Found positive match in exclusion list: \'", name.data, "\'");
+ }
+ }
+ }
+ }
+
+ // TODO: re-implement this algorithm to work in-place
+ unsigned int *aiMappingTable = new unsigned int[pScene->mNumMaterials];
+ for ( unsigned int i=0; i<pScene->mNumMaterials; i++ ) {
+ aiMappingTable[ i ] = 0;
+ }
+ unsigned int iNewNum = 0;
+
+ // Iterate through all materials and calculate a hash for them
+ // store all hashes in a list and so a quick search whether
+ // we do already have a specific hash. This allows us to
+ // determine which materials are identical.
+ uint32_t *aiHashes = new uint32_t[ pScene->mNumMaterials ];;
+ for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
+ {
+ // No mesh is referencing this material, remove it.
+ if (!abReferenced[i]) {
+ ++unreferencedRemoved;
+ delete pScene->mMaterials[i];
+ pScene->mMaterials[i] = nullptr;
+ continue;
+ }
+
+ // Check all previously mapped materials for a matching hash.
+ // On a match we can delete this material and just make it ref to the same index.
+ uint32_t me = aiHashes[i] = ComputeMaterialHash(pScene->mMaterials[i]);
+ for (unsigned int a = 0; a < i;++a)
+ {
+ if (abReferenced[a] && me == aiHashes[a]) {
+ ++redundantRemoved;
+ me = 0;
+ aiMappingTable[i] = aiMappingTable[a];
+ delete pScene->mMaterials[i];
+ pScene->mMaterials[i] = nullptr;
+ break;
+ }
+ }
+ // This is a new material that is referenced, add to the map.
+ if (me) {
+ aiMappingTable[i] = iNewNum++;
+ }
+ }
+ // If the new material count differs from the original,
+ // we need to rebuild the material list and remap mesh material indexes.
+ if (iNewNum != pScene->mNumMaterials) {
+ ai_assert(iNewNum > 0);
+ aiMaterial** ppcMaterials = new aiMaterial*[iNewNum];
+ ::memset(ppcMaterials,0,sizeof(void*)*iNewNum);
+ for (unsigned int p = 0; p < pScene->mNumMaterials;++p)
+ {
+ // if the material is not referenced ... remove it
+ if (!abReferenced[p]) {
+ continue;
+ }
+
+ // generate new names for modified materials that had no names
+ const unsigned int idx = aiMappingTable[p];
+ if (ppcMaterials[idx]) {
+ aiString sz;
+ if( ppcMaterials[idx]->Get(AI_MATKEY_NAME, sz) != AI_SUCCESS ) {
+ sz.length = ::ai_snprintf(sz.data,MAXLEN,"JoinedMaterial_#%u",p);
+ ((aiMaterial*)ppcMaterials[idx])->AddProperty(&sz,AI_MATKEY_NAME);
+ }
+ } else {
+ ppcMaterials[idx] = pScene->mMaterials[p];
+ }
+ }
+ // update all material indices
+ for (unsigned int p = 0; p < pScene->mNumMeshes;++p) {
+ aiMesh* mesh = pScene->mMeshes[p];
+ ai_assert( NULL!=mesh );
+ mesh->mMaterialIndex = aiMappingTable[mesh->mMaterialIndex];
+ }
+ // delete the old material list
+ delete[] pScene->mMaterials;
+ pScene->mMaterials = ppcMaterials;
+ pScene->mNumMaterials = iNewNum;
+ }
+ // delete temporary storage
+ delete[] aiHashes;
+ delete[] aiMappingTable;
+ }
+ if (redundantRemoved == 0 && unreferencedRemoved == 0)
+ {
+ ASSIMP_LOG_DEBUG("RemoveRedundantMatsProcess finished ");
+ }
+ else
+ {
+ ASSIMP_LOG_INFO_F("RemoveRedundantMatsProcess finished. Removed ", redundantRemoved, " redundant and ",
+ unreferencedRemoved, " unused materials.");
+ }
+}
diff --git a/thirdparty/assimp/code/RemoveRedundantMaterials.h b/thirdparty/assimp/code/RemoveRedundantMaterials.h
new file mode 100644
index 0000000000..dbd4d44cc0
--- /dev/null
+++ b/thirdparty/assimp/code/RemoveRedundantMaterials.h
@@ -0,0 +1,107 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file RemoveRedundantMaterials.h
+ * @brief Defines a post processing step to remove redundant materials
+ */
+#ifndef AI_REMOVEREDUNDANTMATERIALS_H_INC
+#define AI_REMOVEREDUNDANTMATERIALS_H_INC
+
+#include "BaseProcess.h"
+#include <assimp/mesh.h>
+
+class RemoveRedundantMatsTest;
+
+namespace Assimp {
+
+// ---------------------------------------------------------------------------
+/** RemoveRedundantMatsProcess: Post-processing step to remove redundant
+ * materials from the imported scene.
+ */
+class ASSIMP_API RemoveRedundantMatsProcess : public BaseProcess
+{
+public:
+ /// The default class constructor.
+ RemoveRedundantMatsProcess();
+
+ /// The class destructor.
+ ~RemoveRedundantMatsProcess();
+
+public:
+ // -------------------------------------------------------------------
+ // Check whether step is active
+ bool IsActive( unsigned int pFlags) const;
+
+ // -------------------------------------------------------------------
+ // Execute step on a given scene
+ void Execute( aiScene* pScene);
+
+ // -------------------------------------------------------------------
+ // Setup import settings
+ void SetupProperties(const Importer* pImp);
+
+
+ // -------------------------------------------------------------------
+ /** @brief Set list of fixed (unmutable) materials
+ * @param fixed See #AI_CONFIG_PP_RRM_EXCLUDE_LIST
+ */
+ void SetFixedMaterialsString(const std::string& fixed = "") {
+ configFixedMaterials = fixed;
+ }
+
+ // -------------------------------------------------------------------
+ /** @brief Get list of fixed (unmutable) materials
+ * @return See #AI_CONFIG_PP_RRM_EXCLUDE_LIST
+ */
+ const std::string& GetFixedMaterialsString() const {
+ return configFixedMaterials;
+ }
+
+private:
+
+ //! Configuration option: list of all fixed materials
+ std::string configFixedMaterials;
+};
+
+} // end of namespace Assimp
+
+#endif // !!AI_REMOVEREDUNDANTMATERIALS_H_INC
diff --git a/thirdparty/assimp/code/RemoveVCProcess.cpp b/thirdparty/assimp/code/RemoveVCProcess.cpp
new file mode 100644
index 0000000000..99fd47a3aa
--- /dev/null
+++ b/thirdparty/assimp/code/RemoveVCProcess.cpp
@@ -0,0 +1,337 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+/** @file Implementation of the post processing step to remove
+ * any parts of the mesh structure from the imported data.
+*/
+
+
+#include "RemoveVCProcess.h"
+#include <assimp/postprocess.h>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/scene.h>
+
+using namespace Assimp;
+
+// ------------------------------------------------------------------------------------------------
+// Constructor to be privately used by Importer
+RemoveVCProcess::RemoveVCProcess() :
+ configDeleteFlags()
+ , mScene()
+{}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor, private as well
+RemoveVCProcess::~RemoveVCProcess()
+{}
+
+// ------------------------------------------------------------------------------------------------
+// Returns whether the processing step is present in the given flag field.
+bool RemoveVCProcess::IsActive( unsigned int pFlags) const
+{
+ return (pFlags & aiProcess_RemoveComponent) != 0;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Small helper function to delete all elements in a T** aray using delete
+template <typename T>
+inline void ArrayDelete(T**& in, unsigned int& num)
+{
+ for (unsigned int i = 0; i < num; ++i)
+ delete in[i];
+
+ delete[] in;
+ in = NULL;
+ num = 0;
+}
+
+#if 0
+// ------------------------------------------------------------------------------------------------
+// Updates the node graph - removes all nodes which have the "remove" flag set and the
+// "don't remove" flag not set. Nodes with meshes are never deleted.
+bool UpdateNodeGraph(aiNode* node,std::list<aiNode*>& childsOfParent,bool root)
+{
+ bool b = false;
+
+ std::list<aiNode*> mine;
+ for (unsigned int i = 0; i < node->mNumChildren;++i)
+ {
+ if(UpdateNodeGraph(node->mChildren[i],mine,false))
+ b = true;
+ }
+
+ // somewhat tricky ... mNumMeshes must be originally 0 and MSB2 may not be set,
+ // so we can do a simple comparison against MSB here
+ if (!root && AI_RC_UINT_MSB == node->mNumMeshes )
+ {
+ // this node needs to be removed
+ if(node->mNumChildren)
+ {
+ childsOfParent.insert(childsOfParent.end(),mine.begin(),mine.end());
+
+ // set all children to NULL to make sure they are not deleted when we delete ourself
+ for (unsigned int i = 0; i < node->mNumChildren;++i)
+ node->mChildren[i] = NULL;
+ }
+ b = true;
+ delete node;
+ }
+ else
+ {
+ AI_RC_UNMASK(node->mNumMeshes);
+ childsOfParent.push_back(node);
+
+ if (b)
+ {
+ // reallocate the array of our children here
+ node->mNumChildren = (unsigned int)mine.size();
+ aiNode** const children = new aiNode*[mine.size()];
+ aiNode** ptr = children;
+
+ for (std::list<aiNode*>::iterator it = mine.begin(), end = mine.end();
+ it != end; ++it)
+ {
+ *ptr++ = *it;
+ }
+ delete[] node->mChildren;
+ node->mChildren = children;
+ return false;
+ }
+ }
+ return b;
+}
+#endif
+
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+void RemoveVCProcess::Execute( aiScene* pScene)
+{
+ ASSIMP_LOG_DEBUG("RemoveVCProcess begin");
+ bool bHas = false; //,bMasked = false;
+
+ mScene = pScene;
+
+ // handle animations
+ if ( configDeleteFlags & aiComponent_ANIMATIONS)
+ {
+
+ bHas = true;
+ ArrayDelete(pScene->mAnimations,pScene->mNumAnimations);
+ }
+
+ // handle textures
+ if ( configDeleteFlags & aiComponent_TEXTURES)
+ {
+ bHas = true;
+ ArrayDelete(pScene->mTextures,pScene->mNumTextures);
+ }
+
+ // handle materials
+ if ( configDeleteFlags & aiComponent_MATERIALS && pScene->mNumMaterials)
+ {
+ bHas = true;
+ for (unsigned int i = 1;i < pScene->mNumMaterials;++i)
+ delete pScene->mMaterials[i];
+
+ pScene->mNumMaterials = 1;
+ aiMaterial* helper = (aiMaterial*) pScene->mMaterials[0];
+ ai_assert(NULL != helper);
+ helper->Clear();
+
+ // gray
+ aiColor3D clr(0.6f,0.6f,0.6f);
+ helper->AddProperty(&clr,1,AI_MATKEY_COLOR_DIFFUSE);
+
+ // add a small ambient color value
+ clr = aiColor3D(0.05f,0.05f,0.05f);
+ helper->AddProperty(&clr,1,AI_MATKEY_COLOR_AMBIENT);
+
+ aiString s;
+ s.Set("Dummy_MaterialsRemoved");
+ helper->AddProperty(&s,AI_MATKEY_NAME);
+ }
+
+ // handle light sources
+ if ( configDeleteFlags & aiComponent_LIGHTS)
+ {
+ bHas = true;
+ ArrayDelete(pScene->mLights,pScene->mNumLights);
+ }
+
+ // handle camneras
+ if ( configDeleteFlags & aiComponent_CAMERAS)
+ {
+ bHas = true;
+ ArrayDelete(pScene->mCameras,pScene->mNumCameras);
+ }
+
+ // handle meshes
+ if (configDeleteFlags & aiComponent_MESHES)
+ {
+ bHas = true;
+ ArrayDelete(pScene->mMeshes,pScene->mNumMeshes);
+ }
+ else
+ {
+ for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
+ {
+ if( ProcessMesh( pScene->mMeshes[a]))
+ bHas = true;
+ }
+ }
+
+
+ // now check whether the result is still a full scene
+ if (!pScene->mNumMeshes || !pScene->mNumMaterials)
+ {
+ pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
+ ASSIMP_LOG_DEBUG("Setting AI_SCENE_FLAGS_INCOMPLETE flag");
+
+ // If we have no meshes anymore we should also clear another flag ...
+ if (!pScene->mNumMeshes)
+ pScene->mFlags &= ~AI_SCENE_FLAGS_NON_VERBOSE_FORMAT;
+ }
+
+ if (bHas) {
+ ASSIMP_LOG_INFO("RemoveVCProcess finished. Data structure cleanup has been done.");
+ } else {
+ ASSIMP_LOG_DEBUG("RemoveVCProcess finished. Nothing to be done ...");
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Setup configuration properties for the step
+void RemoveVCProcess::SetupProperties(const Importer* pImp)
+{
+ configDeleteFlags = pImp->GetPropertyInteger(AI_CONFIG_PP_RVC_FLAGS,0x0);
+ if (!configDeleteFlags)
+ {
+ ASSIMP_LOG_WARN("RemoveVCProcess: AI_CONFIG_PP_RVC_FLAGS is zero.");
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+bool RemoveVCProcess::ProcessMesh(aiMesh* pMesh)
+{
+ bool ret = false;
+
+ // if all materials have been deleted let the material
+ // index of the mesh point to the created default material
+ if ( configDeleteFlags & aiComponent_MATERIALS)
+ pMesh->mMaterialIndex = 0;
+
+ // handle normals
+ if (configDeleteFlags & aiComponent_NORMALS && pMesh->mNormals)
+ {
+ delete[] pMesh->mNormals;
+ pMesh->mNormals = NULL;
+ ret = true;
+ }
+
+ // handle tangents and bitangents
+ if (configDeleteFlags & aiComponent_TANGENTS_AND_BITANGENTS && pMesh->mTangents)
+ {
+ delete[] pMesh->mTangents;
+ pMesh->mTangents = NULL;
+
+ delete[] pMesh->mBitangents;
+ pMesh->mBitangents = NULL;
+ ret = true;
+ }
+
+ // handle texture coordinates
+ bool b = (0 != (configDeleteFlags & aiComponent_TEXCOORDS));
+ for (unsigned int i = 0, real = 0; real < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++real)
+ {
+ if (!pMesh->mTextureCoords[i])break;
+ if (configDeleteFlags & aiComponent_TEXCOORDSn(real) || b)
+ {
+ delete [] pMesh->mTextureCoords[i];
+ pMesh->mTextureCoords[i] = NULL;
+ ret = true;
+
+ if (!b)
+ {
+ // collapse the rest of the array
+ for (unsigned int a = i+1; a < AI_MAX_NUMBER_OF_TEXTURECOORDS;++a)
+ pMesh->mTextureCoords[a-1] = pMesh->mTextureCoords[a];
+
+ pMesh->mTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS-1] = NULL;
+ continue;
+ }
+ }
+ ++i;
+ }
+
+ // handle vertex colors
+ b = (0 != (configDeleteFlags & aiComponent_COLORS));
+ for (unsigned int i = 0, real = 0; real < AI_MAX_NUMBER_OF_COLOR_SETS; ++real)
+ {
+ if (!pMesh->mColors[i])break;
+ if (configDeleteFlags & aiComponent_COLORSn(i) || b)
+ {
+ delete [] pMesh->mColors[i];
+ pMesh->mColors[i] = NULL;
+ ret = true;
+
+ if (!b)
+ {
+ // collapse the rest of the array
+ for (unsigned int a = i+1; a < AI_MAX_NUMBER_OF_COLOR_SETS;++a)
+ pMesh->mColors[a-1] = pMesh->mColors[a];
+
+ pMesh->mColors[AI_MAX_NUMBER_OF_COLOR_SETS-1] = NULL;
+ continue;
+ }
+ }
+ ++i;
+ }
+
+ // handle bones
+ if (configDeleteFlags & aiComponent_BONEWEIGHTS && pMesh->mBones)
+ {
+ ArrayDelete(pMesh->mBones,pMesh->mNumBones);
+ ret = true;
+ }
+ return ret;
+}
diff --git a/thirdparty/assimp/code/RemoveVCProcess.h b/thirdparty/assimp/code/RemoveVCProcess.h
new file mode 100644
index 0000000000..617d7b9b20
--- /dev/null
+++ b/thirdparty/assimp/code/RemoveVCProcess.h
@@ -0,0 +1,123 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file Defines a post processing step to remove specific parts of the scene */
+#ifndef AI_REMOVEVCPROCESS_H_INCLUDED
+#define AI_REMOVEVCPROCESS_H_INCLUDED
+
+#include "BaseProcess.h"
+#include <assimp/mesh.h>
+
+class RemoveVCProcessTest;
+
+namespace Assimp {
+
+// ---------------------------------------------------------------------------
+/** RemoveVCProcess: Class to exclude specific parts of the data structure
+ * from further processing by removing them,
+*/
+class ASSIMP_API RemoveVCProcess : public BaseProcess {
+public:
+ /// The default class constructor.
+ RemoveVCProcess();
+
+ /// The class destructor.
+ ~RemoveVCProcess();
+
+ // -------------------------------------------------------------------
+ /** Returns whether the processing step is present in the given flag field.
+ * @param pFlags The processing flags the importer was called with. A bitwise
+ * combination of #aiPostProcessSteps.
+ * @return true if the process is present in this flag fields, false if not.
+ */
+ bool IsActive( unsigned int pFlags) const;
+
+ // -------------------------------------------------------------------
+ /** Executes the post processing step on the given imported data.
+ * At the moment a process is not supposed to fail.
+ * @param pScene The imported data to work at.
+ */
+ void Execute( aiScene* pScene);
+
+ // -------------------------------------------------------------------
+ /** Called prior to ExecuteOnScene().
+ * The function is a request to the process to update its configuration
+ * basing on the Importer's configuration property list.
+ */
+ virtual void SetupProperties(const Importer* pImp);
+
+ // -------------------------------------------------------------------
+ /** Manually setup the configuration flags for the step
+ *
+ * @param Bitwise combination of the #aiComponent enumerated values.
+ */
+ void SetDeleteFlags(unsigned int f)
+ {
+ configDeleteFlags = f;
+ }
+
+ // -------------------------------------------------------------------
+ /** Query the current configuration.
+ */
+ unsigned int GetDeleteFlags() const
+ {
+ return configDeleteFlags;
+ }
+
+private:
+
+ bool ProcessMesh (aiMesh* pcMesh);
+
+ /** Configuration flag
+ */
+ unsigned int configDeleteFlags;
+
+ /** The scene we're working with
+ */
+ aiScene* mScene;
+};
+
+// ---------------------------------------------------------------------------
+
+} // end of namespace Assimp
+
+#endif // !!AI_REMOVEVCPROCESS_H_INCLUDED
diff --git a/thirdparty/assimp/code/SGSpatialSort.cpp b/thirdparty/assimp/code/SGSpatialSort.cpp
new file mode 100644
index 0000000000..120070b0aa
--- /dev/null
+++ b/thirdparty/assimp/code/SGSpatialSort.cpp
@@ -0,0 +1,168 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file Implementation of the helper class to quickly find
+vertices close to a given position. Special implementation for
+the 3ds loader handling smooth groups correctly */
+
+#include <assimp/SGSpatialSort.h>
+
+using namespace Assimp;
+
+// ------------------------------------------------------------------------------------------------
+SGSpatialSort::SGSpatialSort()
+{
+ // define the reference plane. We choose some arbitrary vector away from all basic axises
+ // in the hope that no model spreads all its vertices along this plane.
+ mPlaneNormal.Set( 0.8523f, 0.34321f, 0.5736f);
+ mPlaneNormal.Normalize();
+}
+// ------------------------------------------------------------------------------------------------
+// Destructor
+SGSpatialSort::~SGSpatialSort()
+{
+ // nothing to do here, everything destructs automatically
+}
+// ------------------------------------------------------------------------------------------------
+void SGSpatialSort::Add(const aiVector3D& vPosition, unsigned int index,
+ unsigned int smoothingGroup)
+{
+ // store position by index and distance
+ float distance = vPosition * mPlaneNormal;
+ mPositions.push_back( Entry( index, vPosition,
+ distance, smoothingGroup));
+}
+// ------------------------------------------------------------------------------------------------
+void SGSpatialSort::Prepare()
+{
+ // now sort the array ascending by distance.
+ std::sort( this->mPositions.begin(), this->mPositions.end());
+}
+// ------------------------------------------------------------------------------------------------
+// Returns an iterator for all positions close to the given position.
+void SGSpatialSort::FindPositions( const aiVector3D& pPosition,
+ uint32_t pSG,
+ float pRadius,
+ std::vector<unsigned int>& poResults,
+ bool exactMatch /*= false*/) const
+{
+ float dist = pPosition * mPlaneNormal;
+ float minDist = dist - pRadius, maxDist = dist + pRadius;
+
+ // clear the array
+ poResults.clear();
+
+ // quick check for positions outside the range
+ if( mPositions.empty() )
+ return;
+ if( maxDist < mPositions.front().mDistance)
+ return;
+ if( minDist > mPositions.back().mDistance)
+ return;
+
+ // do a binary search for the minimal distance to start the iteration there
+ unsigned int index = (unsigned int)mPositions.size() / 2;
+ unsigned int binaryStepSize = (unsigned int)mPositions.size() / 4;
+ while( binaryStepSize > 1)
+ {
+ if( mPositions[index].mDistance < minDist)
+ index += binaryStepSize;
+ else
+ index -= binaryStepSize;
+
+ binaryStepSize /= 2;
+ }
+
+ // depending on the direction of the last step we need to single step a bit back or forth
+ // to find the actual beginning element of the range
+ while( index > 0 && mPositions[index].mDistance > minDist)
+ index--;
+ while( index < (mPositions.size() - 1) && mPositions[index].mDistance < minDist)
+ index++;
+
+ // Mow start iterating from there until the first position lays outside of the distance range.
+ // Add all positions inside the distance range within the given radius to the result aray
+
+ float squareEpsilon = pRadius * pRadius;
+ std::vector<Entry>::const_iterator it = mPositions.begin() + index;
+ std::vector<Entry>::const_iterator end = mPositions.end();
+
+ if (exactMatch)
+ {
+ while( it->mDistance < maxDist)
+ {
+ if((it->mPosition - pPosition).SquareLength() < squareEpsilon && it->mSmoothGroups == pSG)
+ {
+ poResults.push_back( it->mIndex);
+ }
+ ++it;
+ if( end == it )break;
+ }
+ }
+ else
+ {
+ // if the given smoothing group is 0, we'll return all surrounding vertices
+ if (!pSG)
+ {
+ while( it->mDistance < maxDist)
+ {
+ if((it->mPosition - pPosition).SquareLength() < squareEpsilon)
+ poResults.push_back( it->mIndex);
+ ++it;
+ if( end == it)break;
+ }
+ }
+ else while( it->mDistance < maxDist)
+ {
+ if((it->mPosition - pPosition).SquareLength() < squareEpsilon &&
+ (it->mSmoothGroups & pSG || !it->mSmoothGroups))
+ {
+ poResults.push_back( it->mIndex);
+ }
+ ++it;
+ if( end == it)break;
+ }
+ }
+}
+
+
diff --git a/thirdparty/assimp/code/ScaleProcess.cpp b/thirdparty/assimp/code/ScaleProcess.cpp
new file mode 100644
index 0000000000..6d458c4b11
--- /dev/null
+++ b/thirdparty/assimp/code/ScaleProcess.cpp
@@ -0,0 +1,103 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+#ifndef ASSIMP_BUILD_NO_GLOBALSCALE_PROCESS
+
+#include "ScaleProcess.h"
+
+#include <assimp/scene.h>
+#include <assimp/postprocess.h>
+
+namespace Assimp {
+
+ScaleProcess::ScaleProcess()
+: BaseProcess()
+, mScale( AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT ) {
+ // empty
+}
+
+ScaleProcess::~ScaleProcess() {
+ // empty
+}
+
+void ScaleProcess::setScale( ai_real scale ) {
+ mScale = scale;
+}
+
+ai_real ScaleProcess::getScale() const {
+ return mScale;
+}
+
+bool ScaleProcess::IsActive( unsigned int pFlags ) const {
+ return ( pFlags & aiProcess_GlobalScale ) != 0;
+}
+
+void ScaleProcess::SetupProperties( const Importer* pImp ) {
+ mScale = pImp->GetPropertyFloat( AI_CONFIG_GLOBAL_SCALE_FACTOR_KEY, 0 );
+}
+
+void ScaleProcess::Execute( aiScene* pScene ) {
+ if ( nullptr == pScene ) {
+ return;
+ }
+
+ if ( nullptr == pScene->mRootNode ) {
+ return;
+ }
+
+ traverseNodes( pScene->mRootNode );
+}
+
+void ScaleProcess::traverseNodes( aiNode *node ) {
+ applyScaling( node );
+}
+
+void ScaleProcess::applyScaling( aiNode *currentNode ) {
+ if ( nullptr != currentNode ) {
+ currentNode->mTransformation.a1 = currentNode->mTransformation.a1 * mScale;
+ currentNode->mTransformation.b2 = currentNode->mTransformation.b2 * mScale;
+ currentNode->mTransformation.c3 = currentNode->mTransformation.c3 * mScale;
+ }
+}
+
+} // Namespace Assimp
+
+#endif // !! ASSIMP_BUILD_NO_GLOBALSCALE_PROCESS
diff --git a/thirdparty/assimp/code/ScaleProcess.h b/thirdparty/assimp/code/ScaleProcess.h
new file mode 100644
index 0000000000..55146ae064
--- /dev/null
+++ b/thirdparty/assimp/code/ScaleProcess.h
@@ -0,0 +1,88 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+#pragma once
+
+#include "BaseProcess.h"
+
+struct aiNode;
+
+#if (!defined AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT)
+# define AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT 1.0f
+#endif // !! AI_DEBONE_THRESHOLD
+
+namespace Assimp {
+
+// ---------------------------------------------------------------------------
+/** ScaleProcess: Class to rescale the whole model.
+*/
+class ASSIMP_API ScaleProcess : public BaseProcess {
+public:
+ /// The default class constructor.
+ ScaleProcess();
+
+ /// The class destructor.
+ virtual ~ScaleProcess();
+
+ /// Will set the scale manually.
+ void setScale( ai_real scale );
+
+ /// Returns the current scaling value.
+ ai_real getScale() const;
+
+ /// Overwritten, @see BaseProcess
+ virtual bool IsActive( unsigned int pFlags ) const;
+
+ /// Overwritten, @see BaseProcess
+ virtual void SetupProperties( const Importer* pImp );
+
+ /// Overwritten, @see BaseProcess
+ virtual void Execute( aiScene* pScene );
+
+private:
+ void traverseNodes( aiNode *currentNode );
+ void applyScaling( aiNode *currentNode );
+
+private:
+ ai_real mScale;
+};
+
+} // Namespace Assimp
diff --git a/thirdparty/assimp/code/SceneCombiner.cpp b/thirdparty/assimp/code/SceneCombiner.cpp
new file mode 100644
index 0000000000..e445bd7434
--- /dev/null
+++ b/thirdparty/assimp/code/SceneCombiner.cpp
@@ -0,0 +1,1300 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+// TODO: refactor entire file to get rid of the "flat-copy" first approach
+// to copying structures. This easily breaks in the most unintuitive way
+// possible as new fields are added to assimp structures.
+
+// ----------------------------------------------------------------------------
+/**
+ * @file Implements Assimp::SceneCombiner. This is a smart utility
+ * class that combines multiple scenes, meshes, ... into one. Currently
+ * these utilities are used by the IRR and LWS loaders and the
+ * OptimizeGraph step.
+ */
+// ----------------------------------------------------------------------------
+#include <assimp/SceneCombiner.h>
+#include <assimp/StringUtils.h>
+#include <assimp/fast_atof.h>
+#include <assimp/metadata.h>
+#include <assimp/Hash.h>
+#include "time.h"
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/scene.h>
+#include <assimp/mesh.h>
+#include <stdio.h>
+#include "ScenePrivate.h"
+
+namespace Assimp {
+
+// ------------------------------------------------------------------------------------------------
+// Add a prefix to a string
+inline
+void PrefixString(aiString& string,const char* prefix, unsigned int len) {
+ // If the string is already prefixed, we won't prefix it a second time
+ if (string.length >= 1 && string.data[0] == '$')
+ return;
+
+ if (len+string.length>=MAXLEN-1) {
+ ASSIMP_LOG_DEBUG("Can't add an unique prefix because the string is too long");
+ ai_assert(false);
+ return;
+ }
+
+ // Add the prefix
+ ::memmove(string.data+len,string.data,string.length+1);
+ ::memcpy (string.data, prefix, len);
+
+ // And update the string's length
+ string.length += len;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Add node identifiers to a hashing set
+void SceneCombiner::AddNodeHashes(aiNode* node, std::set<unsigned int>& hashes) {
+ // Add node name to hashing set if it is non-empty - empty nodes are allowed
+ // and they can't have any anims assigned so its absolutely safe to duplicate them.
+ if (node->mName.length) {
+ hashes.insert( SuperFastHash(node->mName.data, static_cast<uint32_t>(node->mName.length)) );
+ }
+
+ // Process all children recursively
+ for (unsigned int i = 0; i < node->mNumChildren;++i)
+ AddNodeHashes(node->mChildren[i],hashes);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Add a name prefix to all nodes in a hierarchy
+void SceneCombiner::AddNodePrefixes(aiNode* node, const char* prefix, unsigned int len) {
+ ai_assert(NULL != prefix);
+ PrefixString(node->mName,prefix,len);
+
+ // Process all children recursively
+ for ( unsigned int i = 0; i < node->mNumChildren; ++i ) {
+ AddNodePrefixes( node->mChildren[ i ], prefix, len );
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Search for matching names
+bool SceneCombiner::FindNameMatch(const aiString& name, std::vector<SceneHelper>& input, unsigned int cur) {
+ const unsigned int hash = SuperFastHash(name.data, static_cast<uint32_t>(name.length));
+
+ // Check whether we find a positive match in one of the given sets
+ for (unsigned int i = 0; i < input.size(); ++i) {
+ if (cur != i && input[i].hashes.find(hash) != input[i].hashes.end()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Add a name prefix to all nodes in a hierarchy if a hash match is found
+void SceneCombiner::AddNodePrefixesChecked(aiNode* node, const char* prefix, unsigned int len,
+ std::vector<SceneHelper>& input, unsigned int cur) {
+ ai_assert(NULL != prefix);
+ const unsigned int hash = SuperFastHash(node->mName.data, static_cast<uint32_t>(node->mName.length));
+
+ // Check whether we find a positive match in one of the given sets
+ for (unsigned int i = 0; i < input.size(); ++i) {
+ if (cur != i && input[i].hashes.find(hash) != input[i].hashes.end()) {
+ PrefixString(node->mName,prefix,len);
+ break;
+ }
+ }
+
+ // Process all children recursively
+ for (unsigned int i = 0; i < node->mNumChildren;++i)
+ AddNodePrefixesChecked(node->mChildren[i],prefix,len,input,cur);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Add an offset to all mesh indices in a node graph
+void SceneCombiner::OffsetNodeMeshIndices (aiNode* node, unsigned int offset) {
+ for (unsigned int i = 0; i < node->mNumMeshes;++i)
+ node->mMeshes[i] += offset;
+
+ for ( unsigned int i = 0; i < node->mNumChildren; ++i ) {
+ OffsetNodeMeshIndices( node->mChildren[ i ], offset );
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Merges two scenes. Currently only used by the LWS loader.
+void SceneCombiner::MergeScenes(aiScene** _dest,std::vector<aiScene*>& src, unsigned int flags) {
+ if ( nullptr == _dest ) {
+ return;
+ }
+
+ // if _dest points to NULL allocate a new scene. Otherwise clear the old and reuse it
+ if (src.empty()) {
+ if (*_dest) {
+ (*_dest)->~aiScene();
+ SceneCombiner::CopySceneFlat(_dest,src[0]);
+ }
+ else *_dest = src[0];
+ return;
+ }
+ if (*_dest)(*_dest)->~aiScene();
+ else *_dest = new aiScene();
+
+ // Create a dummy scene to serve as master for the others
+ aiScene* master = new aiScene();
+ master->mRootNode = new aiNode();
+ master->mRootNode->mName.Set("<MergeRoot>");
+
+ std::vector<AttachmentInfo> srcList (src.size());
+ for (unsigned int i = 0; i < srcList.size();++i) {
+ srcList[i] = AttachmentInfo(src[i],master->mRootNode);
+ }
+
+ // 'master' will be deleted afterwards
+ MergeScenes (_dest, master, srcList, flags);
+}
+
+// ------------------------------------------------------------------------------------------------
+void SceneCombiner::AttachToGraph (aiNode* attach, std::vector<NodeAttachmentInfo>& srcList) {
+ unsigned int cnt;
+ for ( cnt = 0; cnt < attach->mNumChildren; ++cnt ) {
+ AttachToGraph( attach->mChildren[ cnt ], srcList );
+ }
+
+ cnt = 0;
+ for (std::vector<NodeAttachmentInfo>::iterator it = srcList.begin();
+ it != srcList.end(); ++it)
+ {
+ if ((*it).attachToNode == attach && !(*it).resolved)
+ ++cnt;
+ }
+
+ if (cnt) {
+ aiNode** n = new aiNode*[cnt+attach->mNumChildren];
+ if (attach->mNumChildren) {
+ ::memcpy(n,attach->mChildren,sizeof(void*)*attach->mNumChildren);
+ delete[] attach->mChildren;
+ }
+ attach->mChildren = n;
+
+ n += attach->mNumChildren;
+ attach->mNumChildren += cnt;
+
+ for (unsigned int i = 0; i < srcList.size();++i) {
+ NodeAttachmentInfo& att = srcList[i];
+ if (att.attachToNode == attach && !att.resolved) {
+ *n = att.node;
+ (**n).mParent = attach;
+ ++n;
+
+ // mark this attachment as resolved
+ att.resolved = true;
+ }
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+void SceneCombiner::AttachToGraph ( aiScene* master, std::vector<NodeAttachmentInfo>& src) {
+ ai_assert(NULL != master);
+ AttachToGraph(master->mRootNode,src);
+}
+
+// ------------------------------------------------------------------------------------------------
+void SceneCombiner::MergeScenes(aiScene** _dest, aiScene* master, std::vector<AttachmentInfo>& srcList, unsigned int flags) {
+ if ( nullptr == _dest ) {
+ return;
+ }
+
+ // if _dest points to NULL allocate a new scene. Otherwise clear the old and reuse it
+ if (srcList.empty()) {
+ if (*_dest) {
+ SceneCombiner::CopySceneFlat(_dest,master);
+ }
+ else *_dest = master;
+ return;
+ }
+ if (*_dest) {
+ (*_dest)->~aiScene();
+ new (*_dest) aiScene();
+ }
+ else *_dest = new aiScene();
+
+ aiScene* dest = *_dest;
+
+ std::vector<SceneHelper> src (srcList.size()+1);
+ src[0].scene = master;
+ for (unsigned int i = 0; i < srcList.size();++i) {
+ src[i+1] = SceneHelper( srcList[i].scene );
+ }
+
+ // this helper array specifies which scenes are duplicates of others
+ std::vector<unsigned int> duplicates(src.size(),UINT_MAX);
+
+ // this helper array is used as lookup table several times
+ std::vector<unsigned int> offset(src.size());
+
+ // Find duplicate scenes
+ for (unsigned int i = 0; i < src.size();++i) {
+ if (duplicates[i] != i && duplicates[i] != UINT_MAX) {
+ continue;
+ }
+
+ duplicates[i] = i;
+ for ( unsigned int a = i+1; a < src.size(); ++a) {
+ if (src[i].scene == src[a].scene) {
+ duplicates[a] = i;
+ }
+ }
+ }
+
+ // Generate unique names for all named stuff?
+ if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES)
+ {
+#if 0
+ // Construct a proper random number generator
+ boost::mt19937 rng( );
+ boost::uniform_int<> dist(1u,1 << 24u);
+ boost::variate_generator<boost::mt19937&, boost::uniform_int<> > rndGen(rng, dist);
+#endif
+ for (unsigned int i = 1; i < src.size();++i)
+ {
+ //if (i != duplicates[i])
+ //{
+ // // duplicate scenes share the same UID
+ // ::strcpy( src[i].id, src[duplicates[i]].id );
+ // src[i].idlen = src[duplicates[i]].idlen;
+
+ // continue;
+ //}
+
+ src[i].idlen = ai_snprintf(src[i].id, 32, "$%.6X$_",i);
+
+ if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY) {
+
+ // Compute hashes for all identifiers in this scene and store them
+ // in a sorted table (for convenience I'm using std::set). We hash
+ // just the node and animation channel names, all identifiers except
+ // the material names should be caught by doing this.
+ AddNodeHashes(src[i]->mRootNode,src[i].hashes);
+
+ for (unsigned int a = 0; a < src[i]->mNumAnimations;++a) {
+ aiAnimation* anim = src[i]->mAnimations[a];
+ src[i].hashes.insert(SuperFastHash(anim->mName.data,static_cast<uint32_t>(anim->mName.length)));
+ }
+ }
+ }
+ }
+
+ unsigned int cnt;
+
+ // First find out how large the respective output arrays must be
+ for ( unsigned int n = 0; n < src.size();++n )
+ {
+ SceneHelper* cur = &src[n];
+
+ if (n == duplicates[n] || flags & AI_INT_MERGE_SCENE_DUPLICATES_DEEP_CPY) {
+ dest->mNumTextures += (*cur)->mNumTextures;
+ dest->mNumMaterials += (*cur)->mNumMaterials;
+ dest->mNumMeshes += (*cur)->mNumMeshes;
+ }
+
+ dest->mNumLights += (*cur)->mNumLights;
+ dest->mNumCameras += (*cur)->mNumCameras;
+ dest->mNumAnimations += (*cur)->mNumAnimations;
+
+ // Combine the flags of all scenes
+ // We need to process them flag-by-flag here to get correct results
+ // dest->mFlags ; //|= (*cur)->mFlags;
+ if ((*cur)->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) {
+ dest->mFlags |= AI_SCENE_FLAGS_NON_VERBOSE_FORMAT;
+ }
+ }
+
+ // generate the output texture list + an offset table for all texture indices
+ if (dest->mNumTextures)
+ {
+ aiTexture** pip = dest->mTextures = new aiTexture*[dest->mNumMaterials];
+ cnt = 0;
+ for ( unsigned int n = 0; n < src.size();++n )
+ {
+ SceneHelper* cur = &src[n];
+ for (unsigned int i = 0; i < (*cur)->mNumTextures;++i)
+ {
+ if (n != duplicates[n])
+ {
+ if ( flags & AI_INT_MERGE_SCENE_DUPLICATES_DEEP_CPY)
+ Copy(pip,(*cur)->mTextures[i]);
+
+ else continue;
+ }
+ else *pip = (*cur)->mTextures[i];
+ ++pip;
+ }
+
+ offset[n] = cnt;
+ cnt = (unsigned int)(pip - dest->mTextures);
+ }
+ }
+
+ // generate the output material list + an offset table for all material indices
+ if (dest->mNumMaterials)
+ {
+ aiMaterial** pip = dest->mMaterials = new aiMaterial*[dest->mNumMaterials];
+ cnt = 0;
+ for ( unsigned int n = 0; n < src.size();++n ) {
+ SceneHelper* cur = &src[n];
+ for (unsigned int i = 0; i < (*cur)->mNumMaterials;++i)
+ {
+ if (n != duplicates[n])
+ {
+ if ( flags & AI_INT_MERGE_SCENE_DUPLICATES_DEEP_CPY)
+ Copy(pip,(*cur)->mMaterials[i]);
+
+ else continue;
+ }
+ else *pip = (*cur)->mMaterials[i];
+
+ if ((*cur)->mNumTextures != dest->mNumTextures) {
+ // We need to update all texture indices of the mesh. So we need to search for
+ // a material property called '$tex.file'
+
+ for (unsigned int a = 0; a < (*pip)->mNumProperties;++a)
+ {
+ aiMaterialProperty* prop = (*pip)->mProperties[a];
+ if (!strncmp(prop->mKey.data,"$tex.file",9))
+ {
+ // Check whether this texture is an embedded texture.
+ // In this case the property looks like this: *<n>,
+ // where n is the index of the texture.
+ aiString& s = *((aiString*)prop->mData);
+ if ('*' == s.data[0]) {
+ // Offset the index and write it back ..
+ const unsigned int idx = strtoul10(&s.data[1]) + offset[n];
+ ASSIMP_itoa10(&s.data[1],sizeof(s.data)-1,idx);
+ }
+ }
+
+ // Need to generate new, unique material names?
+ else if (!::strcmp( prop->mKey.data,"$mat.name" ) && flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES)
+ {
+ aiString* pcSrc = (aiString*) prop->mData;
+ PrefixString(*pcSrc, (*cur).id, (*cur).idlen);
+ }
+ }
+ }
+ ++pip;
+ }
+
+ offset[n] = cnt;
+ cnt = (unsigned int)(pip - dest->mMaterials);
+ }
+ }
+
+ // generate the output mesh list + again an offset table for all mesh indices
+ if (dest->mNumMeshes)
+ {
+ aiMesh** pip = dest->mMeshes = new aiMesh*[dest->mNumMeshes];
+ cnt = 0;
+ for ( unsigned int n = 0; n < src.size();++n )
+ {
+ SceneHelper* cur = &src[n];
+ for (unsigned int i = 0; i < (*cur)->mNumMeshes;++i)
+ {
+ if (n != duplicates[n]) {
+ if ( flags & AI_INT_MERGE_SCENE_DUPLICATES_DEEP_CPY)
+ Copy(pip, (*cur)->mMeshes[i]);
+
+ else continue;
+ }
+ else *pip = (*cur)->mMeshes[i];
+
+ // update the material index of the mesh
+ (*pip)->mMaterialIndex += offset[n];
+ ++pip;
+ }
+
+ // reuse the offset array - store now the mesh offset in it
+ offset[n] = cnt;
+ cnt = (unsigned int)(pip - dest->mMeshes);
+ }
+ }
+
+ std::vector <NodeAttachmentInfo> nodes;
+ nodes.reserve(srcList.size());
+
+ // ----------------------------------------------------------------------------
+ // Now generate the output node graph. We need to make those
+ // names in the graph that are referenced by anims or lights
+ // or cameras unique. So we add a prefix to them ... $<rand>_
+ // We could also use a counter, but using a random value allows us to
+ // use just one prefix if we are joining multiple scene hierarchies recursively.
+ // Chances are quite good we don't collide, so we try that ...
+ // ----------------------------------------------------------------------------
+
+ // Allocate space for light sources, cameras and animations
+ aiLight** ppLights = dest->mLights = (dest->mNumLights
+ ? new aiLight*[dest->mNumLights] : NULL);
+
+ aiCamera** ppCameras = dest->mCameras = (dest->mNumCameras
+ ? new aiCamera*[dest->mNumCameras] : NULL);
+
+ aiAnimation** ppAnims = dest->mAnimations = (dest->mNumAnimations
+ ? new aiAnimation*[dest->mNumAnimations] : NULL);
+
+ for ( int n = static_cast<int>(src.size()-1); n >= 0 ;--n ) /* !!! important !!! */
+ {
+ SceneHelper* cur = &src[n];
+ aiNode* node;
+
+ // To offset or not to offset, this is the question
+ if (n != (int)duplicates[n])
+ {
+ // Get full scene-graph copy
+ Copy( &node, (*cur)->mRootNode );
+ OffsetNodeMeshIndices(node,offset[duplicates[n]]);
+
+ if (flags & AI_INT_MERGE_SCENE_DUPLICATES_DEEP_CPY) {
+ // (note:) they are already 'offseted' by offset[duplicates[n]]
+ OffsetNodeMeshIndices(node,offset[n] - offset[duplicates[n]]);
+ }
+ }
+ else // if (n == duplicates[n])
+ {
+ node = (*cur)->mRootNode;
+ OffsetNodeMeshIndices(node,offset[n]);
+ }
+ if (n) // src[0] is the master node
+ nodes.push_back(NodeAttachmentInfo( node,srcList[n-1].attachToNode,n ));
+
+ // add name prefixes?
+ if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES) {
+
+ // or the whole scenegraph
+ if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY) {
+ AddNodePrefixesChecked(node,(*cur).id,(*cur).idlen,src,n);
+ }
+ else AddNodePrefixes(node,(*cur).id,(*cur).idlen);
+
+ // meshes
+ for (unsigned int i = 0; i < (*cur)->mNumMeshes;++i) {
+ aiMesh* mesh = (*cur)->mMeshes[i];
+
+ // rename all bones
+ for (unsigned int a = 0; a < mesh->mNumBones;++a) {
+ if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY) {
+ if (!FindNameMatch(mesh->mBones[a]->mName,src,n))
+ continue;
+ }
+ PrefixString(mesh->mBones[a]->mName,(*cur).id,(*cur).idlen);
+ }
+ }
+ }
+
+ // --------------------------------------------------------------------
+ // Copy light sources
+ for (unsigned int i = 0; i < (*cur)->mNumLights;++i,++ppLights)
+ {
+ if (n != (int)duplicates[n]) // duplicate scene?
+ {
+ Copy(ppLights, (*cur)->mLights[i]);
+ }
+ else *ppLights = (*cur)->mLights[i];
+
+
+ // Add name prefixes?
+ if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES) {
+ if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY) {
+ if (!FindNameMatch((*ppLights)->mName,src,n))
+ continue;
+ }
+
+ PrefixString((*ppLights)->mName,(*cur).id,(*cur).idlen);
+ }
+ }
+
+ // --------------------------------------------------------------------
+ // Copy cameras
+ for (unsigned int i = 0; i < (*cur)->mNumCameras;++i,++ppCameras) {
+ if (n != (int)duplicates[n]) // duplicate scene?
+ {
+ Copy(ppCameras, (*cur)->mCameras[i]);
+ }
+ else *ppCameras = (*cur)->mCameras[i];
+
+ // Add name prefixes?
+ if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES) {
+ if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY) {
+ if (!FindNameMatch((*ppCameras)->mName,src,n))
+ continue;
+ }
+
+ PrefixString((*ppCameras)->mName,(*cur).id,(*cur).idlen);
+ }
+ }
+
+ // --------------------------------------------------------------------
+ // Copy animations
+ for (unsigned int i = 0; i < (*cur)->mNumAnimations;++i,++ppAnims) {
+ if (n != (int)duplicates[n]) // duplicate scene?
+ {
+ Copy(ppAnims, (*cur)->mAnimations[i]);
+ }
+ else *ppAnims = (*cur)->mAnimations[i];
+
+ // Add name prefixes?
+ if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES) {
+ if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY) {
+ if (!FindNameMatch((*ppAnims)->mName,src,n))
+ continue;
+ }
+
+ PrefixString((*ppAnims)->mName,(*cur).id,(*cur).idlen);
+
+ // don't forget to update all node animation channels
+ for (unsigned int a = 0; a < (*ppAnims)->mNumChannels;++a) {
+ if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY) {
+ if (!FindNameMatch((*ppAnims)->mChannels[a]->mNodeName,src,n))
+ continue;
+ }
+
+ PrefixString((*ppAnims)->mChannels[a]->mNodeName,(*cur).id,(*cur).idlen);
+ }
+ }
+ }
+ }
+
+ // Now build the output graph
+ AttachToGraph ( master, nodes);
+ dest->mRootNode = master->mRootNode;
+
+ // Check whether we succeeded at building the output graph
+ for (std::vector <NodeAttachmentInfo> ::iterator it = nodes.begin();
+ it != nodes.end(); ++it)
+ {
+ if (!(*it).resolved) {
+ if (flags & AI_INT_MERGE_SCENE_RESOLVE_CROSS_ATTACHMENTS) {
+ // search for this attachment point in all other imported scenes, too.
+ for ( unsigned int n = 0; n < src.size();++n ) {
+ if (n != (*it).src_idx) {
+ AttachToGraph(src[n].scene,nodes);
+ if ((*it).resolved)
+ break;
+ }
+ }
+ }
+ if (!(*it).resolved) {
+ ASSIMP_LOG_ERROR_F( "SceneCombiner: Failed to resolve attachment ", (*it).node->mName.data,
+ " ", (*it).attachToNode->mName.data );
+ }
+ }
+ }
+
+ // now delete all input scenes. Make sure duplicate scenes aren't
+ // deleted more than one time
+ for ( unsigned int n = 0; n < src.size();++n ) {
+ if (n != duplicates[n]) // duplicate scene?
+ continue;
+
+ aiScene* deleteMe = src[n].scene;
+
+ // We need to delete the arrays before the destructor is called -
+ // we are reusing the array members
+ delete[] deleteMe->mMeshes; deleteMe->mMeshes = NULL;
+ delete[] deleteMe->mCameras; deleteMe->mCameras = NULL;
+ delete[] deleteMe->mLights; deleteMe->mLights = NULL;
+ delete[] deleteMe->mMaterials; deleteMe->mMaterials = NULL;
+ delete[] deleteMe->mAnimations; deleteMe->mAnimations = NULL;
+
+ deleteMe->mRootNode = NULL;
+
+ // Now we can safely delete the scene
+ delete deleteMe;
+ }
+
+ // Check flags
+ if (!dest->mNumMeshes || !dest->mNumMaterials) {
+ dest->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
+ }
+
+ // We're finished
+}
+
+// ------------------------------------------------------------------------------------------------
+// Build a list of unique bones
+void SceneCombiner::BuildUniqueBoneList(std::list<BoneWithHash>& asBones,
+ std::vector<aiMesh*>::const_iterator it,
+ std::vector<aiMesh*>::const_iterator end)
+{
+ unsigned int iOffset = 0;
+ for (; it != end;++it) {
+ for (unsigned int l = 0; l < (*it)->mNumBones;++l) {
+ aiBone* p = (*it)->mBones[l];
+ uint32_t itml = SuperFastHash(p->mName.data,(unsigned int)p->mName.length);
+
+ std::list<BoneWithHash>::iterator it2 = asBones.begin();
+ std::list<BoneWithHash>::iterator end2 = asBones.end();
+
+ for (;it2 != end2;++it2) {
+ if ((*it2).first == itml) {
+ (*it2).pSrcBones.push_back(BoneSrcIndex(p,iOffset));
+ break;
+ }
+ }
+ if (end2 == it2) {
+ // need to begin a new bone entry
+ asBones.push_back(BoneWithHash());
+ BoneWithHash& btz = asBones.back();
+
+ // setup members
+ btz.first = itml;
+ btz.second = &p->mName;
+ btz.pSrcBones.push_back(BoneSrcIndex(p,iOffset));
+ }
+ }
+ iOffset += (*it)->mNumVertices;
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Merge a list of bones
+void SceneCombiner::MergeBones(aiMesh* out,std::vector<aiMesh*>::const_iterator it,
+ std::vector<aiMesh*>::const_iterator end)
+{
+ if ( nullptr == out || out->mNumBones == 0 ) {
+ return;
+ }
+
+ // find we need to build an unique list of all bones.
+ // we work with hashes to make the comparisons MUCH faster,
+ // at least if we have many bones.
+ std::list<BoneWithHash> asBones;
+ BuildUniqueBoneList( asBones, it, end );
+
+ // now create the output bones
+ out->mNumBones = 0;
+ out->mBones = new aiBone*[asBones.size()];
+
+ for (std::list<BoneWithHash>::const_iterator boneIt = asBones.begin(),boneEnd = asBones.end(); boneIt != boneEnd; ++boneIt ) {
+ // Allocate a bone and setup it's name
+ aiBone* pc = out->mBones[out->mNumBones++] = new aiBone();
+ pc->mName = aiString( *( boneIt->second ));
+
+ std::vector< BoneSrcIndex >::const_iterator wend = boneIt->pSrcBones.end();
+
+ // Loop through all bones to be joined for this bone
+ for (std::vector< BoneSrcIndex >::const_iterator wmit = boneIt->pSrcBones.begin(); wmit != wend; ++wmit) {
+ pc->mNumWeights += (*wmit).first->mNumWeights;
+
+ // NOTE: different offset matrices for bones with equal names
+ // are - at the moment - not handled correctly.
+ if (wmit != boneIt->pSrcBones.begin() && pc->mOffsetMatrix != wmit->first->mOffsetMatrix) {
+ ASSIMP_LOG_WARN("Bones with equal names but different offset matrices can't be joined at the moment");
+ continue;
+ }
+ pc->mOffsetMatrix = wmit->first->mOffsetMatrix;
+ }
+
+ // Allocate the vertex weight array
+ aiVertexWeight* avw = pc->mWeights = new aiVertexWeight[pc->mNumWeights];
+
+ // And copy the final weights - adjust the vertex IDs by the
+ // face index offset of the corresponding mesh.
+ for (std::vector< BoneSrcIndex >::const_iterator wmit = (*boneIt).pSrcBones.begin(); wmit != (*boneIt).pSrcBones.end(); ++wmit) {
+ if (wmit == wend) {
+ break;
+ }
+
+ aiBone* pip = (*wmit).first;
+ for (unsigned int mp = 0; mp < pip->mNumWeights;++mp,++avw) {
+ const aiVertexWeight& vfi = pip->mWeights[mp];
+ avw->mWeight = vfi.mWeight;
+ avw->mVertexId = vfi.mVertexId + (*wmit).second;
+ }
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Merge a list of meshes
+void SceneCombiner::MergeMeshes(aiMesh** _out, unsigned int /*flags*/,
+ std::vector<aiMesh*>::const_iterator begin,
+ std::vector<aiMesh*>::const_iterator end)
+{
+ if ( nullptr == _out ) {
+ return;
+ }
+
+ if (begin == end) {
+ *_out = NULL; // no meshes ...
+ return;
+ }
+
+ // Allocate the output mesh
+ aiMesh* out = *_out = new aiMesh();
+ out->mMaterialIndex = (*begin)->mMaterialIndex;
+
+ std::string name;
+ // Find out how much output storage we'll need
+ for (std::vector<aiMesh*>::const_iterator it = begin; it != end; ++it) {
+ const char *meshName( (*it)->mName.C_Str() );
+ name += std::string( meshName );
+ if ( it != end - 1 ) {
+ name += ".";
+ }
+ out->mNumVertices += (*it)->mNumVertices;
+ out->mNumFaces += (*it)->mNumFaces;
+ out->mNumBones += (*it)->mNumBones;
+
+ // combine primitive type flags
+ out->mPrimitiveTypes |= (*it)->mPrimitiveTypes;
+ }
+ out->mName.Set( name.c_str() );
+
+ if (out->mNumVertices) {
+ aiVector3D* pv2;
+
+ // copy vertex positions
+ if ((**begin).HasPositions()) {
+
+ pv2 = out->mVertices = new aiVector3D[out->mNumVertices];
+ for (std::vector<aiMesh*>::const_iterator it = begin; it != end; ++it) {
+ if ((*it)->mVertices) {
+ ::memcpy(pv2,(*it)->mVertices,(*it)->mNumVertices*sizeof(aiVector3D));
+ }
+ else ASSIMP_LOG_WARN("JoinMeshes: Positions expected but input mesh contains no positions");
+ pv2 += (*it)->mNumVertices;
+ }
+ }
+ // copy normals
+ if ((**begin).HasNormals()) {
+
+ pv2 = out->mNormals = new aiVector3D[out->mNumVertices];
+ for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) {
+ if ((*it)->mNormals) {
+ ::memcpy(pv2,(*it)->mNormals,(*it)->mNumVertices*sizeof(aiVector3D));
+ } else {
+ ASSIMP_LOG_WARN( "JoinMeshes: Normals expected but input mesh contains no normals" );
+ }
+ pv2 += (*it)->mNumVertices;
+ }
+ }
+ // copy tangents and bi-tangents
+ if ((**begin).HasTangentsAndBitangents()) {
+
+ pv2 = out->mTangents = new aiVector3D[out->mNumVertices];
+ aiVector3D* pv2b = out->mBitangents = new aiVector3D[out->mNumVertices];
+
+ for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) {
+ if ((*it)->mTangents) {
+ ::memcpy(pv2, (*it)->mTangents, (*it)->mNumVertices*sizeof(aiVector3D));
+ ::memcpy(pv2b,(*it)->mBitangents,(*it)->mNumVertices*sizeof(aiVector3D));
+ } else {
+ ASSIMP_LOG_WARN( "JoinMeshes: Tangents expected but input mesh contains no tangents" );
+ }
+ pv2 += (*it)->mNumVertices;
+ pv2b += (*it)->mNumVertices;
+ }
+ }
+ // copy texture coordinates
+ unsigned int n = 0;
+ while ((**begin).HasTextureCoords(n)) {
+ out->mNumUVComponents[n] = (*begin)->mNumUVComponents[n];
+
+ pv2 = out->mTextureCoords[n] = new aiVector3D[out->mNumVertices];
+ for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) {
+ if ((*it)->mTextureCoords[n]) {
+ ::memcpy(pv2,(*it)->mTextureCoords[n],(*it)->mNumVertices*sizeof(aiVector3D));
+ } else {
+ ASSIMP_LOG_WARN( "JoinMeshes: UVs expected but input mesh contains no UVs" );
+ }
+ pv2 += (*it)->mNumVertices;
+ }
+ ++n;
+ }
+ // copy vertex colors
+ n = 0;
+ while ((**begin).HasVertexColors(n)) {
+ aiColor4D *pVec2 = out->mColors[n] = new aiColor4D[out->mNumVertices];
+ for ( std::vector<aiMesh*>::const_iterator it = begin; it != end; ++it ) {
+ if ((*it)->mColors[n]) {
+ ::memcpy( pVec2, (*it)->mColors[ n ], (*it)->mNumVertices * sizeof( aiColor4D ) ) ;
+ } else {
+ ASSIMP_LOG_WARN( "JoinMeshes: VCs expected but input mesh contains no VCs" );
+ }
+ pVec2 += (*it)->mNumVertices;
+ }
+ ++n;
+ }
+ }
+
+ if (out->mNumFaces) // just for safety
+ {
+ // copy faces
+ out->mFaces = new aiFace[out->mNumFaces];
+ aiFace* pf2 = out->mFaces;
+
+ unsigned int ofs = 0;
+ for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) {
+ for (unsigned int m = 0; m < (*it)->mNumFaces;++m,++pf2) {
+ aiFace& face = (*it)->mFaces[m];
+ pf2->mNumIndices = face.mNumIndices;
+ pf2->mIndices = face.mIndices;
+
+ if (ofs) {
+ // add the offset to the vertex
+ for (unsigned int q = 0; q < face.mNumIndices; ++q)
+ face.mIndices[q] += ofs;
+ }
+ face.mIndices = NULL;
+ }
+ ofs += (*it)->mNumVertices;
+ }
+ }
+
+ // bones - as this is quite lengthy, I moved the code to a separate function
+ if (out->mNumBones)
+ MergeBones(out,begin,end);
+
+ // delete all source meshes
+ for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it)
+ delete *it;
+}
+
+// ------------------------------------------------------------------------------------------------
+void SceneCombiner::MergeMaterials(aiMaterial** dest,
+ std::vector<aiMaterial*>::const_iterator begin,
+ std::vector<aiMaterial*>::const_iterator end)
+{
+ if ( nullptr == dest ) {
+ return;
+ }
+
+ if (begin == end) {
+ *dest = NULL; // no materials ...
+ return;
+ }
+
+ // Allocate the output material
+ aiMaterial* out = *dest = new aiMaterial();
+
+ // Get the maximal number of properties
+ unsigned int size = 0;
+ for (std::vector<aiMaterial*>::const_iterator it = begin; it != end; ++it) {
+ size += (*it)->mNumProperties;
+ }
+
+ out->Clear();
+ delete[] out->mProperties;
+
+ out->mNumAllocated = size;
+ out->mNumProperties = 0;
+ out->mProperties = new aiMaterialProperty*[out->mNumAllocated];
+
+ for (std::vector<aiMaterial*>::const_iterator it = begin; it != end; ++it) {
+ for(unsigned int i = 0; i < (*it)->mNumProperties; ++i) {
+ aiMaterialProperty* sprop = (*it)->mProperties[i];
+
+ // Test if we already have a matching property
+ const aiMaterialProperty* prop_exist;
+ if(aiGetMaterialProperty(out, sprop->mKey.C_Str(), sprop->mSemantic, sprop->mIndex, &prop_exist) != AI_SUCCESS) {
+ // If not, we add it to the new material
+ aiMaterialProperty* prop = out->mProperties[out->mNumProperties] = new aiMaterialProperty();
+
+ prop->mDataLength = sprop->mDataLength;
+ prop->mData = new char[prop->mDataLength];
+ ::memcpy(prop->mData, sprop->mData, prop->mDataLength);
+
+ prop->mIndex = sprop->mIndex;
+ prop->mSemantic = sprop->mSemantic;
+ prop->mKey = sprop->mKey;
+ prop->mType = sprop->mType;
+
+ out->mNumProperties++;
+ }
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename Type>
+inline
+void CopyPtrArray (Type**& dest, const Type* const * src, ai_uint num) {
+ if (!num) {
+ dest = NULL;
+ return;
+ }
+ dest = new Type*[num];
+ for (ai_uint i = 0; i < num;++i) {
+ SceneCombiner::Copy(&dest[i],src[i]);
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename Type>
+inline
+void GetArrayCopy(Type*& dest, ai_uint num ) {
+ if ( !dest ) {
+ return;
+ }
+ Type* old = dest;
+
+ dest = new Type[num];
+ ::memcpy(dest, old, sizeof(Type) * num);
+}
+
+// ------------------------------------------------------------------------------------------------
+void SceneCombiner::CopySceneFlat(aiScene** _dest,const aiScene* src) {
+ if ( nullptr == _dest || nullptr == src ) {
+ return;
+ }
+
+ // reuse the old scene or allocate a new?
+ if (*_dest) {
+ (*_dest)->~aiScene();
+ new (*_dest) aiScene();
+ } else {
+ *_dest = new aiScene();
+ }
+
+ ::memcpy(*_dest,src,sizeof(aiScene));
+}
+
+// ------------------------------------------------------------------------------------------------
+void SceneCombiner::CopyScene(aiScene** _dest,const aiScene* src,bool allocate) {
+ if ( nullptr == _dest || nullptr == src ) {
+ return;
+ }
+
+ if (allocate) {
+ *_dest = new aiScene();
+ }
+ aiScene* dest = *_dest;
+ ai_assert(nullptr != dest);
+
+ // copy metadata
+ if ( nullptr != src->mMetaData ) {
+ dest->mMetaData = new aiMetadata( *src->mMetaData );
+ }
+
+ // copy animations
+ dest->mNumAnimations = src->mNumAnimations;
+ CopyPtrArray(dest->mAnimations,src->mAnimations,
+ dest->mNumAnimations);
+
+ // copy textures
+ dest->mNumTextures = src->mNumTextures;
+ CopyPtrArray(dest->mTextures,src->mTextures,
+ dest->mNumTextures);
+
+ // copy materials
+ dest->mNumMaterials = src->mNumMaterials;
+ CopyPtrArray(dest->mMaterials,src->mMaterials,
+ dest->mNumMaterials);
+
+ // copy lights
+ dest->mNumLights = src->mNumLights;
+ CopyPtrArray(dest->mLights,src->mLights,
+ dest->mNumLights);
+
+ // copy cameras
+ dest->mNumCameras = src->mNumCameras;
+ CopyPtrArray(dest->mCameras,src->mCameras,
+ dest->mNumCameras);
+
+ // copy meshes
+ dest->mNumMeshes = src->mNumMeshes;
+ CopyPtrArray(dest->mMeshes,src->mMeshes,
+ dest->mNumMeshes);
+
+ // now - copy the root node of the scene (deep copy, too)
+ Copy( &dest->mRootNode, src->mRootNode);
+
+ // and keep the flags ...
+ dest->mFlags = src->mFlags;
+
+ // source private data might be NULL if the scene is user-allocated (i.e. for use with the export API)
+ if (dest->mPrivate != NULL) {
+ ScenePriv(dest)->mPPStepsApplied = ScenePriv(src) ? ScenePriv(src)->mPPStepsApplied : 0;
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+void SceneCombiner::Copy( aiMesh** _dest, const aiMesh* src ) {
+ if ( nullptr == _dest || nullptr == src ) {
+ return;
+ }
+
+ aiMesh* dest = *_dest = new aiMesh();
+
+ // get a flat copy
+ ::memcpy(dest,src,sizeof(aiMesh));
+
+ // and reallocate all arrays
+ GetArrayCopy( dest->mVertices, dest->mNumVertices );
+ GetArrayCopy( dest->mNormals , dest->mNumVertices );
+ GetArrayCopy( dest->mTangents, dest->mNumVertices );
+ GetArrayCopy( dest->mBitangents, dest->mNumVertices );
+
+ unsigned int n = 0;
+ while (dest->HasTextureCoords(n))
+ GetArrayCopy( dest->mTextureCoords[n++], dest->mNumVertices );
+
+ n = 0;
+ while (dest->HasVertexColors(n))
+ GetArrayCopy( dest->mColors[n++], dest->mNumVertices );
+
+ // make a deep copy of all bones
+ CopyPtrArray(dest->mBones,dest->mBones,dest->mNumBones);
+
+ // make a deep copy of all faces
+ GetArrayCopy(dest->mFaces,dest->mNumFaces);
+ for (unsigned int i = 0; i < dest->mNumFaces;++i) {
+ aiFace& f = dest->mFaces[i];
+ GetArrayCopy(f.mIndices,f.mNumIndices);
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+void SceneCombiner::Copy (aiMaterial** _dest, const aiMaterial* src) {
+ if ( nullptr == _dest || nullptr == src ) {
+ return;
+ }
+
+ aiMaterial* dest = (aiMaterial*) ( *_dest = new aiMaterial() );
+
+ dest->Clear();
+ delete[] dest->mProperties;
+
+ dest->mNumAllocated = src->mNumAllocated;
+ dest->mNumProperties = src->mNumProperties;
+ dest->mProperties = new aiMaterialProperty* [dest->mNumAllocated];
+
+ for (unsigned int i = 0; i < dest->mNumProperties;++i)
+ {
+ aiMaterialProperty* prop = dest->mProperties[i] = new aiMaterialProperty();
+ aiMaterialProperty* sprop = src->mProperties[i];
+
+ prop->mDataLength = sprop->mDataLength;
+ prop->mData = new char[prop->mDataLength];
+ ::memcpy(prop->mData,sprop->mData,prop->mDataLength);
+
+ prop->mIndex = sprop->mIndex;
+ prop->mSemantic = sprop->mSemantic;
+ prop->mKey = sprop->mKey;
+ prop->mType = sprop->mType;
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+void SceneCombiner::Copy(aiTexture** _dest, const aiTexture* src) {
+ if ( nullptr == _dest || nullptr == src ) {
+ return;
+ }
+
+ aiTexture* dest = *_dest = new aiTexture();
+
+ // get a flat copy
+ ::memcpy(dest,src,sizeof(aiTexture));
+
+ // and reallocate all arrays. We must do it manually here
+ const char* old = (const char*)dest->pcData;
+ if (old)
+ {
+ unsigned int cpy;
+ if (!dest->mHeight)cpy = dest->mWidth;
+ else cpy = dest->mHeight * dest->mWidth * sizeof(aiTexel);
+
+ if (!cpy)
+ {
+ dest->pcData = NULL;
+ return;
+ }
+ // the cast is legal, the aiTexel c'tor does nothing important
+ dest->pcData = (aiTexel*) new char[cpy];
+ ::memcpy(dest->pcData, old, cpy);
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+void SceneCombiner::Copy( aiAnimation** _dest, const aiAnimation* src ) {
+ if ( nullptr == _dest || nullptr == src ) {
+ return;
+ }
+
+ aiAnimation* dest = *_dest = new aiAnimation();
+
+ // get a flat copy
+ ::memcpy(dest,src,sizeof(aiAnimation));
+
+ // and reallocate all arrays
+ CopyPtrArray( dest->mChannels, src->mChannels, dest->mNumChannels );
+}
+
+// ------------------------------------------------------------------------------------------------
+void SceneCombiner::Copy(aiNodeAnim** _dest, const aiNodeAnim* src) {
+ if ( nullptr == _dest || nullptr == src ) {
+ return;
+ }
+
+ aiNodeAnim* dest = *_dest = new aiNodeAnim();
+
+ // get a flat copy
+ ::memcpy(dest,src,sizeof(aiNodeAnim));
+
+ // and reallocate all arrays
+ GetArrayCopy( dest->mPositionKeys, dest->mNumPositionKeys );
+ GetArrayCopy( dest->mScalingKeys, dest->mNumScalingKeys );
+ GetArrayCopy( dest->mRotationKeys, dest->mNumRotationKeys );
+}
+
+// ------------------------------------------------------------------------------------------------
+void SceneCombiner::Copy( aiCamera** _dest,const aiCamera* src) {
+ if ( nullptr == _dest || nullptr == src ) {
+ return;
+ }
+
+ aiCamera* dest = *_dest = new aiCamera();
+
+ // get a flat copy, that's already OK
+ ::memcpy(dest,src,sizeof(aiCamera));
+}
+
+// ------------------------------------------------------------------------------------------------
+void SceneCombiner::Copy(aiLight** _dest, const aiLight* src) {
+ if ( nullptr == _dest || nullptr == src ) {
+ return;
+ }
+
+ aiLight* dest = *_dest = new aiLight();
+
+ // get a flat copy, that's already OK
+ ::memcpy(dest,src,sizeof(aiLight));
+}
+
+// ------------------------------------------------------------------------------------------------
+void SceneCombiner::Copy(aiBone** _dest, const aiBone* src) {
+ if ( nullptr == _dest || nullptr == src ) {
+ return;
+ }
+
+ aiBone* dest = *_dest = new aiBone();
+
+ // get a flat copy
+ ::memcpy(dest,src,sizeof(aiBone));
+
+ // and reallocate all arrays
+ GetArrayCopy( dest->mWeights, dest->mNumWeights );
+}
+
+// ------------------------------------------------------------------------------------------------
+void SceneCombiner::Copy (aiNode** _dest, const aiNode* src)
+{
+ ai_assert(NULL != _dest && NULL != src);
+
+ aiNode* dest = *_dest = new aiNode();
+
+ // get a flat copy
+ ::memcpy(dest,src,sizeof(aiNode));
+
+ if (src->mMetaData) {
+ Copy(&dest->mMetaData, src->mMetaData);
+ }
+
+ // and reallocate all arrays
+ GetArrayCopy( dest->mMeshes, dest->mNumMeshes );
+ CopyPtrArray( dest->mChildren, src->mChildren,dest->mNumChildren);
+
+ // need to set the mParent fields to the created aiNode.
+ for( unsigned int i = 0; i < dest->mNumChildren; i ++ ) {
+ dest->mChildren[i]->mParent = dest;
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+void SceneCombiner::Copy(aiMetadata** _dest, const aiMetadata* src) {
+ if ( nullptr == _dest || nullptr == src ) {
+ return;
+ }
+
+ if ( 0 == src->mNumProperties ) {
+ return;
+ }
+
+ aiMetadata* dest = *_dest = aiMetadata::Alloc( src->mNumProperties );
+ std::copy(src->mKeys, src->mKeys + src->mNumProperties, dest->mKeys);
+
+ dest->mValues = new aiMetadataEntry[src->mNumProperties];
+ for (unsigned int i = 0; i < src->mNumProperties; ++i) {
+ aiMetadataEntry& in = src->mValues[i];
+ aiMetadataEntry& out = dest->mValues[i];
+ out.mType = in.mType;
+ switch (dest->mValues[i].mType) {
+ case AI_BOOL:
+ out.mData = new bool(*static_cast<bool*>(in.mData));
+ break;
+ case AI_INT32:
+ out.mData = new int32_t(*static_cast<int32_t*>(in.mData));
+ break;
+ case AI_UINT64:
+ out.mData = new uint64_t(*static_cast<uint64_t*>(in.mData));
+ break;
+ case AI_FLOAT:
+ out.mData = new float(*static_cast<float*>(in.mData));
+ break;
+ case AI_DOUBLE:
+ out.mData = new double(*static_cast<double*>(in.mData));
+ break;
+ case AI_AISTRING:
+ out.mData = new aiString(*static_cast<aiString*>(in.mData));
+ break;
+ case AI_AIVECTOR3D:
+ out.mData = new aiVector3D(*static_cast<aiVector3D*>(in.mData));
+ break;
+ default:
+ ai_assert(false);
+ break;
+ }
+ }
+}
+
+} // Namespace Assimp
+
diff --git a/thirdparty/assimp/code/ScenePreprocessor.cpp b/thirdparty/assimp/code/ScenePreprocessor.cpp
new file mode 100644
index 0000000000..432a3d7666
--- /dev/null
+++ b/thirdparty/assimp/code/ScenePreprocessor.cpp
@@ -0,0 +1,261 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+#include "ScenePreprocessor.h"
+#include <assimp/ai_assert.h>
+#include <assimp/scene.h>
+#include <assimp/DefaultLogger.hpp>
+
+
+using namespace Assimp;
+
+// ---------------------------------------------------------------------------------------------
+void ScenePreprocessor::ProcessScene ()
+{
+ ai_assert(scene != NULL);
+
+ // Process all meshes
+ for (unsigned int i = 0; i < scene->mNumMeshes;++i)
+ ProcessMesh(scene->mMeshes[i]);
+
+ // - nothing to do for nodes for the moment
+ // - nothing to do for textures for the moment
+ // - nothing to do for lights for the moment
+ // - nothing to do for cameras for the moment
+
+ // Process all animations
+ for (unsigned int i = 0; i < scene->mNumAnimations;++i)
+ ProcessAnimation(scene->mAnimations[i]);
+
+ // Generate a default material if none was specified
+ if (!scene->mNumMaterials && scene->mNumMeshes) {
+ scene->mMaterials = new aiMaterial*[2];
+ aiMaterial* helper;
+
+ aiString name;
+
+ scene->mMaterials[scene->mNumMaterials] = helper = new aiMaterial();
+ aiColor3D clr(0.6f,0.6f,0.6f);
+ helper->AddProperty(&clr,1,AI_MATKEY_COLOR_DIFFUSE);
+
+ // setup the default name to make this material identifiable
+ name.Set(AI_DEFAULT_MATERIAL_NAME);
+ helper->AddProperty(&name,AI_MATKEY_NAME);
+
+ ASSIMP_LOG_DEBUG("ScenePreprocessor: Adding default material \'" AI_DEFAULT_MATERIAL_NAME "\'");
+
+ for (unsigned int i = 0; i < scene->mNumMeshes;++i) {
+ scene->mMeshes[i]->mMaterialIndex = scene->mNumMaterials;
+ }
+
+ scene->mNumMaterials++;
+ }
+}
+
+// ---------------------------------------------------------------------------------------------
+void ScenePreprocessor::ProcessMesh (aiMesh* mesh)
+{
+ // If aiMesh::mNumUVComponents is *not* set assign the default value of 2
+ for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
+ if (!mesh->mTextureCoords[i]) {
+ mesh->mNumUVComponents[i] = 0;
+ } else {
+ if (!mesh->mNumUVComponents[i])
+ mesh->mNumUVComponents[i] = 2;
+
+ aiVector3D* p = mesh->mTextureCoords[i], *end = p+mesh->mNumVertices;
+
+ // Ensure unused components are zeroed. This will make 1D texture channels work
+ // as if they were 2D channels .. just in case an application doesn't handle
+ // this case
+ if (2 == mesh->mNumUVComponents[i]) {
+ for (; p != end; ++p)
+ p->z = 0.f;
+ }
+ else if (1 == mesh->mNumUVComponents[i]) {
+ for (; p != end; ++p)
+ p->z = p->y = 0.f;
+ }
+ else if (3 == mesh->mNumUVComponents[i]) {
+ // Really 3D coordinates? Check whether the third coordinate is != 0 for at least one element
+ for (; p != end; ++p) {
+ if (p->z != 0)
+ break;
+ }
+ if (p == end) {
+ ASSIMP_LOG_WARN("ScenePreprocessor: UVs are declared to be 3D but they're obviously not. Reverting to 2D.");
+ mesh->mNumUVComponents[i] = 2;
+ }
+ }
+ }
+ }
+
+ // If the information which primitive types are there in the
+ // mesh is currently not available, compute it.
+ if (!mesh->mPrimitiveTypes) {
+ for (unsigned int a = 0; a < mesh->mNumFaces; ++a) {
+ aiFace& face = mesh->mFaces[a];
+ switch (face.mNumIndices)
+ {
+ case 3u:
+ mesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
+ break;
+
+ case 2u:
+ mesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
+ break;
+
+ case 1u:
+ mesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
+ break;
+
+ default:
+ mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
+ break;
+ }
+ }
+ }
+
+ // If tangents and normals are given but no bitangents compute them
+ if (mesh->mTangents && mesh->mNormals && !mesh->mBitangents) {
+
+ mesh->mBitangents = new aiVector3D[mesh->mNumVertices];
+ for (unsigned int i = 0; i < mesh->mNumVertices;++i) {
+ mesh->mBitangents[i] = mesh->mNormals[i] ^ mesh->mTangents[i];
+ }
+ }
+}
+
+// ---------------------------------------------------------------------------------------------
+void ScenePreprocessor::ProcessAnimation (aiAnimation* anim)
+{
+ double first = 10e10, last = -10e10;
+ for (unsigned int i = 0; i < anim->mNumChannels;++i) {
+ aiNodeAnim* channel = anim->mChannels[i];
+
+ /* If the exact duration of the animation is not given
+ * compute it now.
+ */
+ if (anim->mDuration == -1.) {
+
+ // Position keys
+ for (unsigned int j = 0; j < channel->mNumPositionKeys;++j) {
+ aiVectorKey& key = channel->mPositionKeys[j];
+ first = std::min (first, key.mTime);
+ last = std::max (last, key.mTime);
+ }
+
+ // Scaling keys
+ for (unsigned int j = 0; j < channel->mNumScalingKeys;++j ) {
+ aiVectorKey& key = channel->mScalingKeys[j];
+ first = std::min (first, key.mTime);
+ last = std::max (last, key.mTime);
+ }
+
+ // Rotation keys
+ for (unsigned int j = 0; j < channel->mNumRotationKeys;++j ) {
+ aiQuatKey& key = channel->mRotationKeys[ j ];
+ first = std::min (first, key.mTime);
+ last = std::max (last, key.mTime);
+ }
+ }
+
+ /* Check whether the animation channel has no rotation
+ * or position tracks. In this case we generate a dummy
+ * track from the information we have in the transformation
+ * matrix of the corresponding node.
+ */
+ if (!channel->mNumRotationKeys || !channel->mNumPositionKeys || !channel->mNumScalingKeys) {
+ // Find the node that belongs to this animation
+ aiNode* node = scene->mRootNode->FindNode(channel->mNodeName);
+ if (node) // ValidateDS will complain later if 'node' is NULL
+ {
+ // Decompose the transformation matrix of the node
+ aiVector3D scaling, position;
+ aiQuaternion rotation;
+
+ node->mTransformation.Decompose(scaling, rotation,position);
+
+ // No rotation keys? Generate a dummy track
+ if (!channel->mNumRotationKeys) {
+ channel->mNumRotationKeys = 1;
+ channel->mRotationKeys = new aiQuatKey[1];
+ aiQuatKey& q = channel->mRotationKeys[0];
+
+ q.mTime = 0.;
+ q.mValue = rotation;
+
+ ASSIMP_LOG_DEBUG("ScenePreprocessor: Dummy rotation track has been generated");
+ }
+
+ // No scaling keys? Generate a dummy track
+ if (!channel->mNumScalingKeys) {
+ channel->mNumScalingKeys = 1;
+ channel->mScalingKeys = new aiVectorKey[1];
+ aiVectorKey& q = channel->mScalingKeys[0];
+
+ q.mTime = 0.;
+ q.mValue = scaling;
+
+ ASSIMP_LOG_DEBUG("ScenePreprocessor: Dummy scaling track has been generated");
+ }
+
+ // No position keys? Generate a dummy track
+ if (!channel->mNumPositionKeys) {
+ channel->mNumPositionKeys = 1;
+ channel->mPositionKeys = new aiVectorKey[1];
+ aiVectorKey& q = channel->mPositionKeys[0];
+
+ q.mTime = 0.;
+ q.mValue = position;
+
+ ASSIMP_LOG_DEBUG("ScenePreprocessor: Dummy position track has been generated");
+ }
+ }
+ }
+ }
+
+ if (anim->mDuration == -1.) {
+ ASSIMP_LOG_DEBUG("ScenePreprocessor: Setting animation duration");
+ anim->mDuration = last - std::min( first, 0. );
+ }
+}
diff --git a/thirdparty/assimp/code/ScenePreprocessor.h b/thirdparty/assimp/code/ScenePreprocessor.h
new file mode 100644
index 0000000000..3f4c8d7c3f
--- /dev/null
+++ b/thirdparty/assimp/code/ScenePreprocessor.h
@@ -0,0 +1,125 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file Defines a post processing step to search all meshes for
+ degenerated faces */
+#ifndef AI_SCENE_PREPROCESSOR_H_INC
+#define AI_SCENE_PREPROCESSOR_H_INC
+
+#include <assimp/defs.h>
+#include <stddef.h>
+
+struct aiScene;
+struct aiAnimation;
+struct aiMesh;
+
+class ScenePreprocessorTest;
+namespace Assimp {
+
+// ----------------------------------------------------------------------------------
+/** ScenePreprocessor: Preprocess a scene before any post-processing
+ * steps are executed.
+ *
+ * The step computes data that needn't necessarily be provided by the
+ * importer, such as aiMesh::mPrimitiveTypes.
+*/
+// ----------------------------------------------------------------------------------
+class ASSIMP_API ScenePreprocessor
+{
+ // Make ourselves a friend of the corresponding test unit.
+ friend class ::ScenePreprocessorTest;
+public:
+
+ // ----------------------------------------------------------------
+ /** Default c'tpr. Use SetScene() to assign a scene to the object.
+ */
+ ScenePreprocessor()
+ : scene (NULL)
+ {}
+
+ /** Constructs the object and assigns a specific scene to it
+ */
+ ScenePreprocessor(aiScene* _scene)
+ : scene (_scene)
+ {}
+
+ // ----------------------------------------------------------------
+ /** Assign a (new) scene to the object.
+ *
+ * One 'SceneProcessor' can be used for multiple scenes.
+ * Call ProcessScene to have the scene preprocessed.
+ * @param sc Scene to be processed.
+ */
+ void SetScene (aiScene* sc) {
+ scene = sc;
+ }
+
+ // ----------------------------------------------------------------
+ /** Preprocess the current scene
+ */
+ void ProcessScene ();
+
+protected:
+
+ // ----------------------------------------------------------------
+ /** Preprocess an animation in the scene
+ * @param anim Anim to be preprocessed.
+ */
+ void ProcessAnimation (aiAnimation* anim);
+
+
+ // ----------------------------------------------------------------
+ /** Preprocess a mesh in the scene
+ * @param mesh Mesh to be preprocessed.
+ */
+ void ProcessMesh (aiMesh* mesh);
+
+protected:
+
+ //! Scene we're currently working on
+ aiScene* scene;
+};
+
+
+} // ! end namespace Assimp
+
+#endif // include guard
diff --git a/thirdparty/assimp/code/ScenePrivate.h b/thirdparty/assimp/code/ScenePrivate.h
new file mode 100644
index 0000000000..f336aafc9a
--- /dev/null
+++ b/thirdparty/assimp/code/ScenePrivate.h
@@ -0,0 +1,105 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file Stuff to deal with aiScene::mPrivate
+ */
+#pragma once
+#ifndef AI_SCENEPRIVATE_H_INCLUDED
+#define AI_SCENEPRIVATE_H_INCLUDED
+
+#include <assimp/ai_assert.h>
+#include <assimp/scene.h>
+
+namespace Assimp {
+
+// Forward declarations
+class Importer;
+
+struct ScenePrivateData {
+ // The struct constructor.
+ ScenePrivateData() AI_NO_EXCEPT;
+
+ // Importer that originally loaded the scene though the C-API
+ // If set, this object is owned by this private data instance.
+ Assimp::Importer* mOrigImporter;
+
+ // List of post-processing steps already applied to the scene.
+ unsigned int mPPStepsApplied;
+
+ // true if the scene is a copy made with aiCopyScene()
+ // or the corresponding C++ API. This means that user code
+ // may have made modifications to it, so mPPStepsApplied
+ // and mOrigImporter are no longer safe to rely on and only
+ // serve informative purposes.
+ bool mIsCopy;
+};
+
+inline
+ScenePrivateData::ScenePrivateData() AI_NO_EXCEPT
+: mOrigImporter( nullptr )
+, mPPStepsApplied( 0 )
+, mIsCopy( false ) {
+ // empty
+}
+
+// Access private data stored in the scene
+inline
+ScenePrivateData* ScenePriv(aiScene* in) {
+ ai_assert( nullptr != in );
+ if ( nullptr == in ) {
+ return nullptr;
+ }
+ return static_cast<ScenePrivateData*>(in->mPrivate);
+}
+
+inline
+const ScenePrivateData* ScenePriv(const aiScene* in) {
+ ai_assert( nullptr != in );
+ if ( nullptr == in ) {
+ return nullptr;
+ }
+ return static_cast<const ScenePrivateData*>(in->mPrivate);
+}
+
+} // Namespace Assimp
+
+#endif // AI_SCENEPRIVATE_H_INCLUDED
diff --git a/thirdparty/assimp/code/SkeletonMeshBuilder.cpp b/thirdparty/assimp/code/SkeletonMeshBuilder.cpp
new file mode 100644
index 0000000000..06cfe034e9
--- /dev/null
+++ b/thirdparty/assimp/code/SkeletonMeshBuilder.cpp
@@ -0,0 +1,270 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file SkeletonMeshBuilder.cpp
+ * @brief Implementation of a little class to construct a dummy mesh for a skeleton
+ */
+
+#include <assimp/scene.h>
+#include <assimp/SkeletonMeshBuilder.h>
+
+using namespace Assimp;
+
+// ------------------------------------------------------------------------------------------------
+// The constructor processes the given scene and adds a mesh there.
+SkeletonMeshBuilder::SkeletonMeshBuilder( aiScene* pScene, aiNode* root, bool bKnobsOnly)
+{
+ // nothing to do if there's mesh data already present at the scene
+ if( pScene->mNumMeshes > 0 || pScene->mRootNode == NULL)
+ return;
+
+ if (!root)
+ root = pScene->mRootNode;
+
+ mKnobsOnly = bKnobsOnly;
+
+ // build some faces around each node
+ CreateGeometry( root );
+
+ // create a mesh to hold all the generated faces
+ pScene->mNumMeshes = 1;
+ pScene->mMeshes = new aiMesh*[1];
+ pScene->mMeshes[0] = CreateMesh();
+ // and install it at the root node
+ root->mNumMeshes = 1;
+ root->mMeshes = new unsigned int[1];
+ root->mMeshes[0] = 0;
+
+ // create a dummy material for the mesh
+ if(pScene->mNumMaterials==0){
+ pScene->mNumMaterials = 1;
+ pScene->mMaterials = new aiMaterial*[1];
+ pScene->mMaterials[0] = CreateMaterial();
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Recursively builds a simple mesh representation for the given node
+void SkeletonMeshBuilder::CreateGeometry( const aiNode* pNode)
+{
+ // add a joint entry for the node.
+ const unsigned int vertexStartIndex = static_cast<unsigned int>(mVertices.size());
+
+ // now build the geometry.
+ if( pNode->mNumChildren > 0 && !mKnobsOnly)
+ {
+ // If the node has children, we build little pointers to each of them
+ for( unsigned int a = 0; a < pNode->mNumChildren; a++)
+ {
+ // find a suitable coordinate system
+ const aiMatrix4x4& childTransform = pNode->mChildren[a]->mTransformation;
+ aiVector3D childpos( childTransform.a4, childTransform.b4, childTransform.c4);
+ ai_real distanceToChild = childpos.Length();
+ if( distanceToChild < 0.0001)
+ continue;
+ aiVector3D up = aiVector3D( childpos).Normalize();
+
+ aiVector3D orth( 1.0, 0.0, 0.0);
+ if( std::fabs( orth * up) > 0.99)
+ orth.Set( 0.0, 1.0, 0.0);
+
+ aiVector3D front = (up ^ orth).Normalize();
+ aiVector3D side = (front ^ up).Normalize();
+
+ unsigned int localVertexStart = static_cast<unsigned int>(mVertices.size());
+ mVertices.push_back( -front * distanceToChild * (ai_real)0.1);
+ mVertices.push_back( childpos);
+ mVertices.push_back( -side * distanceToChild * (ai_real)0.1);
+ mVertices.push_back( -side * distanceToChild * (ai_real)0.1);
+ mVertices.push_back( childpos);
+ mVertices.push_back( front * distanceToChild * (ai_real)0.1);
+ mVertices.push_back( front * distanceToChild * (ai_real)0.1);
+ mVertices.push_back( childpos);
+ mVertices.push_back( side * distanceToChild * (ai_real)0.1);
+ mVertices.push_back( side * distanceToChild * (ai_real)0.1);
+ mVertices.push_back( childpos);
+ mVertices.push_back( -front * distanceToChild * (ai_real)0.1);
+
+ mFaces.push_back( Face( localVertexStart + 0, localVertexStart + 1, localVertexStart + 2));
+ mFaces.push_back( Face( localVertexStart + 3, localVertexStart + 4, localVertexStart + 5));
+ mFaces.push_back( Face( localVertexStart + 6, localVertexStart + 7, localVertexStart + 8));
+ mFaces.push_back( Face( localVertexStart + 9, localVertexStart + 10, localVertexStart + 11));
+ }
+ }
+ else
+ {
+ // if the node has no children, it's an end node. Put a little knob there instead
+ aiVector3D ownpos( pNode->mTransformation.a4, pNode->mTransformation.b4, pNode->mTransformation.c4);
+ ai_real sizeEstimate = ownpos.Length() * ai_real( 0.18 );
+
+ mVertices.push_back( aiVector3D( -sizeEstimate, 0.0, 0.0));
+ mVertices.push_back( aiVector3D( 0.0, sizeEstimate, 0.0));
+ mVertices.push_back( aiVector3D( 0.0, 0.0, -sizeEstimate));
+ mVertices.push_back( aiVector3D( 0.0, sizeEstimate, 0.0));
+ mVertices.push_back( aiVector3D( sizeEstimate, 0.0, 0.0));
+ mVertices.push_back( aiVector3D( 0.0, 0.0, -sizeEstimate));
+ mVertices.push_back( aiVector3D( sizeEstimate, 0.0, 0.0));
+ mVertices.push_back( aiVector3D( 0.0, -sizeEstimate, 0.0));
+ mVertices.push_back( aiVector3D( 0.0, 0.0, -sizeEstimate));
+ mVertices.push_back( aiVector3D( 0.0, -sizeEstimate, 0.0));
+ mVertices.push_back( aiVector3D( -sizeEstimate, 0.0, 0.0));
+ mVertices.push_back( aiVector3D( 0.0, 0.0, -sizeEstimate));
+
+ mVertices.push_back( aiVector3D( -sizeEstimate, 0.0, 0.0));
+ mVertices.push_back( aiVector3D( 0.0, 0.0, sizeEstimate));
+ mVertices.push_back( aiVector3D( 0.0, sizeEstimate, 0.0));
+ mVertices.push_back( aiVector3D( 0.0, sizeEstimate, 0.0));
+ mVertices.push_back( aiVector3D( 0.0, 0.0, sizeEstimate));
+ mVertices.push_back( aiVector3D( sizeEstimate, 0.0, 0.0));
+ mVertices.push_back( aiVector3D( sizeEstimate, 0.0, 0.0));
+ mVertices.push_back( aiVector3D( 0.0, 0.0, sizeEstimate));
+ mVertices.push_back( aiVector3D( 0.0, -sizeEstimate, 0.0));
+ mVertices.push_back( aiVector3D( 0.0, -sizeEstimate, 0.0));
+ mVertices.push_back( aiVector3D( 0.0, 0.0, sizeEstimate));
+ mVertices.push_back( aiVector3D( -sizeEstimate, 0.0, 0.0));
+
+ mFaces.push_back( Face( vertexStartIndex + 0, vertexStartIndex + 1, vertexStartIndex + 2));
+ mFaces.push_back( Face( vertexStartIndex + 3, vertexStartIndex + 4, vertexStartIndex + 5));
+ mFaces.push_back( Face( vertexStartIndex + 6, vertexStartIndex + 7, vertexStartIndex + 8));
+ mFaces.push_back( Face( vertexStartIndex + 9, vertexStartIndex + 10, vertexStartIndex + 11));
+ mFaces.push_back( Face( vertexStartIndex + 12, vertexStartIndex + 13, vertexStartIndex + 14));
+ mFaces.push_back( Face( vertexStartIndex + 15, vertexStartIndex + 16, vertexStartIndex + 17));
+ mFaces.push_back( Face( vertexStartIndex + 18, vertexStartIndex + 19, vertexStartIndex + 20));
+ mFaces.push_back( Face( vertexStartIndex + 21, vertexStartIndex + 22, vertexStartIndex + 23));
+ }
+
+ unsigned int numVertices = static_cast<unsigned int>(mVertices.size() - vertexStartIndex);
+ if( numVertices > 0)
+ {
+ // create a bone affecting all the newly created vertices
+ aiBone* bone = new aiBone;
+ mBones.push_back( bone);
+ bone->mName = pNode->mName;
+
+ // calculate the bone offset matrix by concatenating the inverse transformations of all parents
+ bone->mOffsetMatrix = aiMatrix4x4( pNode->mTransformation).Inverse();
+ for( aiNode* parent = pNode->mParent; parent != NULL; parent = parent->mParent)
+ bone->mOffsetMatrix = aiMatrix4x4( parent->mTransformation).Inverse() * bone->mOffsetMatrix;
+
+ // add all the vertices to the bone's influences
+ bone->mNumWeights = numVertices;
+ bone->mWeights = new aiVertexWeight[numVertices];
+ for( unsigned int a = 0; a < numVertices; a++)
+ bone->mWeights[a] = aiVertexWeight( vertexStartIndex + a, 1.0);
+
+ // HACK: (thom) transform all vertices to the bone's local space. Should be done before adding
+ // them to the array, but I'm tired now and I'm annoyed.
+ aiMatrix4x4 boneToMeshTransform = aiMatrix4x4( bone->mOffsetMatrix).Inverse();
+ for( unsigned int a = vertexStartIndex; a < mVertices.size(); a++)
+ mVertices[a] = boneToMeshTransform * mVertices[a];
+ }
+
+ // and finally recurse into the children list
+ for( unsigned int a = 0; a < pNode->mNumChildren; a++)
+ CreateGeometry( pNode->mChildren[a]);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Creates the mesh from the internally accumulated stuff and returns it.
+aiMesh* SkeletonMeshBuilder::CreateMesh()
+{
+ aiMesh* mesh = new aiMesh();
+
+ // add points
+ mesh->mNumVertices = static_cast<unsigned int>(mVertices.size());
+ mesh->mVertices = new aiVector3D[mesh->mNumVertices];
+ std::copy( mVertices.begin(), mVertices.end(), mesh->mVertices);
+
+ mesh->mNormals = new aiVector3D[mesh->mNumVertices];
+
+ // add faces
+ mesh->mNumFaces = static_cast<unsigned int>(mFaces.size());
+ mesh->mFaces = new aiFace[mesh->mNumFaces];
+ for( unsigned int a = 0; a < mesh->mNumFaces; a++)
+ {
+ const Face& inface = mFaces[a];
+ aiFace& outface = mesh->mFaces[a];
+ outface.mNumIndices = 3;
+ outface.mIndices = new unsigned int[3];
+ outface.mIndices[0] = inface.mIndices[0];
+ outface.mIndices[1] = inface.mIndices[1];
+ outface.mIndices[2] = inface.mIndices[2];
+
+ // Compute per-face normals ... we don't want the bones to be smoothed ... they're built to visualize
+ // the skeleton, so it's good if there's a visual difference to the rest of the geometry
+ aiVector3D nor = ((mVertices[inface.mIndices[2]] - mVertices[inface.mIndices[0]]) ^
+ (mVertices[inface.mIndices[1]] - mVertices[inface.mIndices[0]]));
+
+ if (nor.Length() < 1e-5) /* ensure that FindInvalidData won't remove us ...*/
+ nor = aiVector3D(1.0,0.0,0.0);
+
+ for (unsigned int n = 0; n < 3; ++n)
+ mesh->mNormals[inface.mIndices[n]] = nor;
+ }
+
+ // add the bones
+ mesh->mNumBones = static_cast<unsigned int>(mBones.size());
+ mesh->mBones = new aiBone*[mesh->mNumBones];
+ std::copy( mBones.begin(), mBones.end(), mesh->mBones);
+
+ // default
+ mesh->mMaterialIndex = 0;
+
+ return mesh;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Creates a dummy material and returns it.
+aiMaterial* SkeletonMeshBuilder::CreateMaterial()
+{
+ aiMaterial* matHelper = new aiMaterial;
+
+ // Name
+ aiString matName( std::string( "SkeletonMaterial"));
+ matHelper->AddProperty( &matName, AI_MATKEY_NAME);
+
+ // Prevent backface culling
+ const int no_cull = 1;
+ matHelper->AddProperty(&no_cull,1,AI_MATKEY_TWOSIDED);
+
+ return matHelper;
+}
diff --git a/thirdparty/assimp/code/SortByPTypeProcess.cpp b/thirdparty/assimp/code/SortByPTypeProcess.cpp
new file mode 100644
index 0000000000..2e0cc54004
--- /dev/null
+++ b/thirdparty/assimp/code/SortByPTypeProcess.cpp
@@ -0,0 +1,403 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file Implementation of the DeterminePTypeHelperProcess and
+ * SortByPTypeProcess post-process steps.
+*/
+
+
+
+// internal headers
+#include "ProcessHelper.h"
+#include "SortByPTypeProcess.h"
+#include <assimp/Exceptional.h>
+
+using namespace Assimp;
+
+// ------------------------------------------------------------------------------------------------
+// Constructor to be privately used by Importer
+SortByPTypeProcess::SortByPTypeProcess()
+{
+ configRemoveMeshes = 0;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor, private as well
+SortByPTypeProcess::~SortByPTypeProcess()
+{
+ // nothing to do here
+}
+
+// ------------------------------------------------------------------------------------------------
+// Returns whether the processing step is present in the given flag field.
+bool SortByPTypeProcess::IsActive( unsigned int pFlags) const
+{
+ return (pFlags & aiProcess_SortByPType) != 0;
+}
+
+// ------------------------------------------------------------------------------------------------
+void SortByPTypeProcess::SetupProperties(const Importer* pImp)
+{
+ configRemoveMeshes = pImp->GetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE,0);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Update changed meshes in all nodes
+void UpdateNodes(const std::vector<unsigned int>& replaceMeshIndex, aiNode* node)
+{
+ if (node->mNumMeshes)
+ {
+ unsigned int newSize = 0;
+ for (unsigned int m = 0; m< node->mNumMeshes; ++m)
+ {
+ unsigned int add = node->mMeshes[m]<<2;
+ for (unsigned int i = 0; i < 4;++i)
+ {
+ if (UINT_MAX != replaceMeshIndex[add+i])++newSize;
+ }
+ }
+ if (!newSize)
+ {
+ delete[] node->mMeshes;
+ node->mNumMeshes = 0;
+ node->mMeshes = NULL;
+ }
+ else
+ {
+ // Try to reuse the old array if possible
+ unsigned int* newMeshes = (newSize > node->mNumMeshes
+ ? new unsigned int[newSize] : node->mMeshes);
+
+ for (unsigned int m = 0; m< node->mNumMeshes; ++m)
+ {
+ unsigned int add = node->mMeshes[m]<<2;
+ for (unsigned int i = 0; i < 4;++i)
+ {
+ if (UINT_MAX != replaceMeshIndex[add+i])
+ *newMeshes++ = replaceMeshIndex[add+i];
+ }
+ }
+ if (newSize > node->mNumMeshes)
+ delete[] node->mMeshes;
+
+ node->mMeshes = newMeshes-(node->mNumMeshes = newSize);
+ }
+ }
+
+ // call all subnodes recursively
+ for (unsigned int m = 0; m < node->mNumChildren; ++m)
+ UpdateNodes(replaceMeshIndex,node->mChildren[m]);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+void SortByPTypeProcess::Execute( aiScene* pScene) {
+ if ( 0 == pScene->mNumMeshes) {
+ ASSIMP_LOG_DEBUG("SortByPTypeProcess skipped, there are no meshes");
+ return;
+ }
+
+ ASSIMP_LOG_DEBUG("SortByPTypeProcess begin");
+
+ unsigned int aiNumMeshesPerPType[4] = {0,0,0,0};
+
+ std::vector<aiMesh*> outMeshes;
+ outMeshes.reserve(pScene->mNumMeshes<<1u);
+
+ bool bAnyChanges = false;
+
+ std::vector<unsigned int> replaceMeshIndex(pScene->mNumMeshes*4,UINT_MAX);
+ std::vector<unsigned int>::iterator meshIdx = replaceMeshIndex.begin();
+ for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
+ aiMesh* const mesh = pScene->mMeshes[i];
+ ai_assert(0 != mesh->mPrimitiveTypes);
+
+ // if there's just one primitive type in the mesh there's nothing to do for us
+ unsigned int num = 0;
+ if (mesh->mPrimitiveTypes & aiPrimitiveType_POINT) {
+ ++aiNumMeshesPerPType[0];
+ ++num;
+ }
+ if (mesh->mPrimitiveTypes & aiPrimitiveType_LINE) {
+ ++aiNumMeshesPerPType[1];
+ ++num;
+ }
+ if (mesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE) {
+ ++aiNumMeshesPerPType[2];
+ ++num;
+ }
+ if (mesh->mPrimitiveTypes & aiPrimitiveType_POLYGON) {
+ ++aiNumMeshesPerPType[3];
+ ++num;
+ }
+
+ if (1 == num) {
+ if (!(configRemoveMeshes & mesh->mPrimitiveTypes)) {
+ *meshIdx = static_cast<unsigned int>( outMeshes.size() );
+ outMeshes.push_back(mesh);
+ } else {
+ delete mesh;
+ pScene->mMeshes[ i ] = nullptr;
+ bAnyChanges = true;
+ }
+
+ meshIdx += 4;
+ continue;
+ }
+ bAnyChanges = true;
+
+ // reuse our current mesh arrays for the submesh
+ // with the largest number of primitives
+ unsigned int aiNumPerPType[4] = {0,0,0,0};
+ aiFace* pFirstFace = mesh->mFaces;
+ aiFace* const pLastFace = pFirstFace + mesh->mNumFaces;
+
+ unsigned int numPolyVerts = 0;
+ for (;pFirstFace != pLastFace; ++pFirstFace) {
+ if (pFirstFace->mNumIndices <= 3)
+ ++aiNumPerPType[pFirstFace->mNumIndices-1];
+ else
+ {
+ ++aiNumPerPType[3];
+ numPolyVerts += pFirstFace-> mNumIndices;
+ }
+ }
+
+ VertexWeightTable* avw = ComputeVertexBoneWeightTable(mesh);
+ for (unsigned int real = 0; real < 4; ++real,++meshIdx)
+ {
+ if ( !aiNumPerPType[real] || configRemoveMeshes & (1u << real))
+ {
+ continue;
+ }
+
+ *meshIdx = (unsigned int) outMeshes.size();
+ outMeshes.push_back(new aiMesh());
+ aiMesh* out = outMeshes.back();
+
+ // the name carries the adjacency information between the meshes
+ out->mName = mesh->mName;
+
+ // copy data members
+ out->mPrimitiveTypes = 1u << real;
+ out->mMaterialIndex = mesh->mMaterialIndex;
+
+ // allocate output storage
+ out->mNumFaces = aiNumPerPType[real];
+ aiFace* outFaces = out->mFaces = new aiFace[out->mNumFaces];
+
+ out->mNumVertices = (3 == real ? numPolyVerts : out->mNumFaces * (real+1));
+
+ aiVector3D *vert(nullptr), *nor(nullptr), *tan(nullptr), *bit(nullptr);
+ aiVector3D *uv [AI_MAX_NUMBER_OF_TEXTURECOORDS];
+ aiColor4D *cols [AI_MAX_NUMBER_OF_COLOR_SETS];
+
+ if (mesh->mVertices) {
+ vert = out->mVertices = new aiVector3D[out->mNumVertices];
+ }
+
+ if (mesh->mNormals) {
+ nor = out->mNormals = new aiVector3D[out->mNumVertices];
+ }
+
+ if (mesh->mTangents) {
+ tan = out->mTangents = new aiVector3D[out->mNumVertices];
+ bit = out->mBitangents = new aiVector3D[out->mNumVertices];
+ }
+
+ for (unsigned int j = 0; j < AI_MAX_NUMBER_OF_TEXTURECOORDS;++j) {
+ uv[j] = nullptr;
+ if (mesh->mTextureCoords[j]) {
+ uv[j] = out->mTextureCoords[j] = new aiVector3D[out->mNumVertices];
+ }
+
+ out->mNumUVComponents[j] = mesh->mNumUVComponents[j];
+ }
+
+ for (unsigned int j = 0; j < AI_MAX_NUMBER_OF_COLOR_SETS;++j) {
+ cols[j] = nullptr;
+ if (mesh->mColors[j]) {
+ cols[j] = out->mColors[j] = new aiColor4D[out->mNumVertices];
+ }
+ }
+
+ typedef std::vector< aiVertexWeight > TempBoneInfo;
+ std::vector< TempBoneInfo > tempBones(mesh->mNumBones);
+
+ // try to guess how much storage we'll need
+ for (unsigned int q = 0; q < mesh->mNumBones;++q)
+ {
+ tempBones[q].reserve(mesh->mBones[q]->mNumWeights / (num-1));
+ }
+
+ unsigned int outIdx = 0;
+ for (unsigned int m = 0; m < mesh->mNumFaces; ++m)
+ {
+ aiFace& in = mesh->mFaces[m];
+ if ((real == 3 && in.mNumIndices <= 3) || (real != 3 && in.mNumIndices != real+1))
+ {
+ continue;
+ }
+
+ outFaces->mNumIndices = in.mNumIndices;
+ outFaces->mIndices = in.mIndices;
+
+ for (unsigned int q = 0; q < in.mNumIndices; ++q)
+ {
+ unsigned int idx = in.mIndices[q];
+
+ // process all bones of this index
+ if (avw)
+ {
+ VertexWeightTable& tbl = avw[idx];
+ for (VertexWeightTable::const_iterator it = tbl.begin(), end = tbl.end();
+ it != end; ++it)
+ {
+ tempBones[ (*it).first ].push_back( aiVertexWeight(outIdx, (*it).second) );
+ }
+ }
+
+ if (vert)
+ {
+ *vert++ = mesh->mVertices[idx];
+ //mesh->mVertices[idx].x = get_qnan();
+ }
+ if (nor )*nor++ = mesh->mNormals[idx];
+ if (tan )
+ {
+ *tan++ = mesh->mTangents[idx];
+ *bit++ = mesh->mBitangents[idx];
+ }
+
+ for (unsigned int pp = 0; pp < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++pp)
+ {
+ if (!uv[pp])break;
+ *uv[pp]++ = mesh->mTextureCoords[pp][idx];
+ }
+
+ for (unsigned int pp = 0; pp < AI_MAX_NUMBER_OF_COLOR_SETS; ++pp)
+ {
+ if (!cols[pp])break;
+ *cols[pp]++ = mesh->mColors[pp][idx];
+ }
+
+ in.mIndices[q] = outIdx++;
+ }
+
+ in.mIndices = nullptr;
+ ++outFaces;
+ }
+ ai_assert(outFaces == out->mFaces + out->mNumFaces);
+
+ // now generate output bones
+ for (unsigned int q = 0; q < mesh->mNumBones;++q)
+ if (!tempBones[q].empty())++out->mNumBones;
+
+ if (out->mNumBones)
+ {
+ out->mBones = new aiBone*[out->mNumBones];
+ for (unsigned int q = 0, real = 0; q < mesh->mNumBones;++q)
+ {
+ TempBoneInfo& in = tempBones[q];
+ if (in.empty())continue;
+
+ aiBone* srcBone = mesh->mBones[q];
+ aiBone* bone = out->mBones[real] = new aiBone();
+
+ bone->mName = srcBone->mName;
+ bone->mOffsetMatrix = srcBone->mOffsetMatrix;
+
+ bone->mNumWeights = (unsigned int)in.size();
+ bone->mWeights = new aiVertexWeight[bone->mNumWeights];
+
+ ::memcpy(bone->mWeights,&in[0],bone->mNumWeights*sizeof(aiVertexWeight));
+
+ ++real;
+ }
+ }
+ }
+
+ // delete the per-vertex bone weights table
+ delete[] avw;
+
+ // delete the input mesh
+ delete mesh;
+
+ // avoid invalid pointer
+ pScene->mMeshes[i] = NULL;
+ }
+
+ if (outMeshes.empty())
+ {
+ // This should not occur
+ throw DeadlyImportError("No meshes remaining");
+ }
+
+ // If we added at least one mesh process all nodes in the node
+ // graph and update their respective mesh indices.
+ if (bAnyChanges)
+ {
+ UpdateNodes(replaceMeshIndex,pScene->mRootNode);
+ }
+
+ if (outMeshes.size() != pScene->mNumMeshes)
+ {
+ delete[] pScene->mMeshes;
+ pScene->mNumMeshes = (unsigned int)outMeshes.size();
+ pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
+ }
+ ::memcpy(pScene->mMeshes,&outMeshes[0],pScene->mNumMeshes*sizeof(void*));
+
+ if (!DefaultLogger::isNullLogger())
+ {
+ char buffer[1024];
+ ::ai_snprintf(buffer,1024,"Points: %u%s, Lines: %u%s, Triangles: %u%s, Polygons: %u%s (Meshes, X = removed)",
+ aiNumMeshesPerPType[0], ((configRemoveMeshes & aiPrimitiveType_POINT) ? "X" : ""),
+ aiNumMeshesPerPType[1], ((configRemoveMeshes & aiPrimitiveType_LINE) ? "X" : ""),
+ aiNumMeshesPerPType[2], ((configRemoveMeshes & aiPrimitiveType_TRIANGLE) ? "X" : ""),
+ aiNumMeshesPerPType[3], ((configRemoveMeshes & aiPrimitiveType_POLYGON) ? "X" : ""));
+ ASSIMP_LOG_INFO(buffer);
+ ASSIMP_LOG_DEBUG("SortByPTypeProcess finished");
+ }
+}
+
diff --git a/thirdparty/assimp/code/SortByPTypeProcess.h b/thirdparty/assimp/code/SortByPTypeProcess.h
new file mode 100644
index 0000000000..c9d9924d8f
--- /dev/null
+++ b/thirdparty/assimp/code/SortByPTypeProcess.h
@@ -0,0 +1,85 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file Defines a post processing step to sort meshes by the types
+ of primitives they contain */
+#ifndef AI_SORTBYPTYPEPROCESS_H_INC
+#define AI_SORTBYPTYPEPROCESS_H_INC
+
+#include "BaseProcess.h"
+#include <assimp/mesh.h>
+
+class SortByPTypeProcessTest;
+namespace Assimp {
+
+
+// ---------------------------------------------------------------------------
+/** SortByPTypeProcess: Sorts meshes by the types of primitives they contain.
+ * A mesh with 5 lines, 3 points and 145 triangles would be split in 3
+ * submeshes.
+*/
+class ASSIMP_API SortByPTypeProcess : public BaseProcess
+{
+public:
+
+ SortByPTypeProcess();
+ ~SortByPTypeProcess();
+
+public:
+ // -------------------------------------------------------------------
+ bool IsActive( unsigned int pFlags) const;
+
+ // -------------------------------------------------------------------
+ void Execute( aiScene* pScene);
+
+ // -------------------------------------------------------------------
+ void SetupProperties(const Importer* pImp);
+
+private:
+
+ int configRemoveMeshes;
+};
+
+
+} // end of namespace Assimp
+
+#endif // !!AI_SORTBYPTYPEPROCESS_H_INC
diff --git a/thirdparty/assimp/code/SpatialSort.cpp b/thirdparty/assimp/code/SpatialSort.cpp
new file mode 100644
index 0000000000..a4f3a4e4b8
--- /dev/null
+++ b/thirdparty/assimp/code/SpatialSort.cpp
@@ -0,0 +1,342 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file Implementation of the helper class to quickly find vertices close to a given position */
+
+#include <assimp/SpatialSort.h>
+#include <assimp/ai_assert.h>
+
+using namespace Assimp;
+
+// CHAR_BIT seems to be defined under MVSC, but not under GCC. Pray that the correct value is 8.
+#ifndef CHAR_BIT
+# define CHAR_BIT 8
+#endif
+
+// ------------------------------------------------------------------------------------------------
+// Constructs a spatially sorted representation from the given position array.
+SpatialSort::SpatialSort( const aiVector3D* pPositions, unsigned int pNumPositions,
+ unsigned int pElementOffset)
+
+ // define the reference plane. We choose some arbitrary vector away from all basic axises
+ // in the hope that no model spreads all its vertices along this plane.
+ : mPlaneNormal(0.8523f, 0.34321f, 0.5736f)
+{
+ mPlaneNormal.Normalize();
+ Fill(pPositions,pNumPositions,pElementOffset);
+}
+
+// ------------------------------------------------------------------------------------------------
+SpatialSort :: SpatialSort()
+: mPlaneNormal(0.8523f, 0.34321f, 0.5736f)
+{
+ mPlaneNormal.Normalize();
+}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor
+SpatialSort::~SpatialSort()
+{
+ // nothing to do here, everything destructs automatically
+}
+
+// ------------------------------------------------------------------------------------------------
+void SpatialSort::Fill( const aiVector3D* pPositions, unsigned int pNumPositions,
+ unsigned int pElementOffset,
+ bool pFinalize /*= true */)
+{
+ mPositions.clear();
+ Append(pPositions,pNumPositions,pElementOffset,pFinalize);
+}
+
+// ------------------------------------------------------------------------------------------------
+void SpatialSort :: Finalize()
+{
+ std::sort( mPositions.begin(), mPositions.end());
+}
+
+// ------------------------------------------------------------------------------------------------
+void SpatialSort::Append( const aiVector3D* pPositions, unsigned int pNumPositions,
+ unsigned int pElementOffset,
+ bool pFinalize /*= true */)
+{
+ // store references to all given positions along with their distance to the reference plane
+ const size_t initial = mPositions.size();
+ mPositions.reserve(initial + (pFinalize?pNumPositions:pNumPositions*2));
+ for( unsigned int a = 0; a < pNumPositions; a++)
+ {
+ const char* tempPointer = reinterpret_cast<const char*> (pPositions);
+ const aiVector3D* vec = reinterpret_cast<const aiVector3D*> (tempPointer + a * pElementOffset);
+
+ // store position by index and distance
+ ai_real distance = *vec * mPlaneNormal;
+ mPositions.push_back( Entry( static_cast<unsigned int>(a+initial), *vec, distance));
+ }
+
+ if (pFinalize) {
+ // now sort the array ascending by distance.
+ Finalize();
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Returns an iterator for all positions close to the given position.
+void SpatialSort::FindPositions( const aiVector3D& pPosition,
+ ai_real pRadius, std::vector<unsigned int>& poResults) const
+{
+ const ai_real dist = pPosition * mPlaneNormal;
+ const ai_real minDist = dist - pRadius, maxDist = dist + pRadius;
+
+ // clear the array
+ poResults.clear();
+
+ // quick check for positions outside the range
+ if( mPositions.size() == 0)
+ return;
+ if( maxDist < mPositions.front().mDistance)
+ return;
+ if( minDist > mPositions.back().mDistance)
+ return;
+
+ // do a binary search for the minimal distance to start the iteration there
+ unsigned int index = (unsigned int)mPositions.size() / 2;
+ unsigned int binaryStepSize = (unsigned int)mPositions.size() / 4;
+ while( binaryStepSize > 1)
+ {
+ if( mPositions[index].mDistance < minDist)
+ index += binaryStepSize;
+ else
+ index -= binaryStepSize;
+
+ binaryStepSize /= 2;
+ }
+
+ // depending on the direction of the last step we need to single step a bit back or forth
+ // to find the actual beginning element of the range
+ while( index > 0 && mPositions[index].mDistance > minDist)
+ index--;
+ while( index < (mPositions.size() - 1) && mPositions[index].mDistance < minDist)
+ index++;
+
+ // Mow start iterating from there until the first position lays outside of the distance range.
+ // Add all positions inside the distance range within the given radius to the result aray
+ std::vector<Entry>::const_iterator it = mPositions.begin() + index;
+ const ai_real pSquared = pRadius*pRadius;
+ while( it->mDistance < maxDist)
+ {
+ if( (it->mPosition - pPosition).SquareLength() < pSquared)
+ poResults.push_back( it->mIndex);
+ ++it;
+ if( it == mPositions.end())
+ break;
+ }
+
+ // that's it
+}
+
+namespace {
+
+ // Binary, signed-integer representation of a single-precision floating-point value.
+ // IEEE 754 says: "If two floating-point numbers in the same format are ordered then they are
+ // ordered the same way when their bits are reinterpreted as sign-magnitude integers."
+ // This allows us to convert all floating-point numbers to signed integers of arbitrary size
+ // and then use them to work with ULPs (Units in the Last Place, for high-precision
+ // computations) or to compare them (integer comparisons are faster than floating-point
+ // comparisons on many platforms).
+ typedef ai_int BinFloat;
+
+ // --------------------------------------------------------------------------------------------
+ // Converts the bit pattern of a floating-point number to its signed integer representation.
+ BinFloat ToBinary( const ai_real & pValue) {
+
+ // If this assertion fails, signed int is not big enough to store a float on your platform.
+ // Please correct the declaration of BinFloat a few lines above - but do it in a portable,
+ // #ifdef'd manner!
+ static_assert( sizeof(BinFloat) >= sizeof(ai_real), "sizeof(BinFloat) >= sizeof(ai_real)");
+
+ #if defined( _MSC_VER)
+ // If this assertion fails, Visual C++ has finally moved to ILP64. This means that this
+ // code has just become legacy code! Find out the current value of _MSC_VER and modify
+ // the #if above so it evaluates false on the current and all upcoming VC versions (or
+ // on the current platform, if LP64 or LLP64 are still used on other platforms).
+ static_assert( sizeof(BinFloat) == sizeof(ai_real), "sizeof(BinFloat) == sizeof(ai_real)");
+
+ // This works best on Visual C++, but other compilers have their problems with it.
+ const BinFloat binValue = reinterpret_cast<BinFloat const &>(pValue);
+ #else
+ // On many compilers, reinterpreting a float address as an integer causes aliasing
+ // problems. This is an ugly but more or less safe way of doing it.
+ union {
+ ai_real asFloat;
+ BinFloat asBin;
+ } conversion;
+ conversion.asBin = 0; // zero empty space in case sizeof(BinFloat) > sizeof(float)
+ conversion.asFloat = pValue;
+ const BinFloat binValue = conversion.asBin;
+ #endif
+
+ // floating-point numbers are of sign-magnitude format, so find out what signed number
+ // representation we must convert negative values to.
+ // See http://en.wikipedia.org/wiki/Signed_number_representations.
+
+ // Two's complement?
+ if( (-42 == (~42 + 1)) && (binValue & 0x80000000))
+ return BinFloat(1 << (CHAR_BIT * sizeof(BinFloat) - 1)) - binValue;
+ // One's complement?
+ else if ( (-42 == ~42) && (binValue & 0x80000000))
+ return BinFloat(-0) - binValue;
+ // Sign-magnitude?
+ else if( (-42 == (42 | (-0))) && (binValue & 0x80000000)) // -0 = 1000... binary
+ return binValue;
+ else
+ return binValue;
+ }
+
+} // namespace
+
+// ------------------------------------------------------------------------------------------------
+// Fills an array with indices of all positions identical to the given position. In opposite to
+// FindPositions(), not an epsilon is used but a (very low) tolerance of four floating-point units.
+void SpatialSort::FindIdenticalPositions( const aiVector3D& pPosition,
+ std::vector<unsigned int>& poResults) const
+{
+ // Epsilons have a huge disadvantage: they are of constant precision, while floating-point
+ // values are of log2 precision. If you apply e=0.01 to 100, the epsilon is rather small, but
+ // if you apply it to 0.001, it is enormous.
+
+ // The best way to overcome this is the unit in the last place (ULP). A precision of 2 ULPs
+ // tells us that a float does not differ more than 2 bits from the "real" value. ULPs are of
+ // logarithmic precision - around 1, they are 1*(2^24) and around 10000, they are 0.00125.
+
+ // For standard C math, we can assume a precision of 0.5 ULPs according to IEEE 754. The
+ // incoming vertex positions might have already been transformed, probably using rather
+ // inaccurate SSE instructions, so we assume a tolerance of 4 ULPs to safely identify
+ // identical vertex positions.
+ static const int toleranceInULPs = 4;
+ // An interesting point is that the inaccuracy grows linear with the number of operations:
+ // multiplying to numbers, each inaccurate to four ULPs, results in an inaccuracy of four ULPs
+ // plus 0.5 ULPs for the multiplication.
+ // To compute the distance to the plane, a dot product is needed - that is a multiplication and
+ // an addition on each number.
+ static const int distanceToleranceInULPs = toleranceInULPs + 1;
+ // The squared distance between two 3D vectors is computed the same way, but with an additional
+ // subtraction.
+ static const int distance3DToleranceInULPs = distanceToleranceInULPs + 1;
+
+ // Convert the plane distance to its signed integer representation so the ULPs tolerance can be
+ // applied. For some reason, VC won't optimize two calls of the bit pattern conversion.
+ const BinFloat minDistBinary = ToBinary( pPosition * mPlaneNormal) - distanceToleranceInULPs;
+ const BinFloat maxDistBinary = minDistBinary + 2 * distanceToleranceInULPs;
+
+ // clear the array in this strange fashion because a simple clear() would also deallocate
+ // the array which we want to avoid
+ poResults.resize( 0 );
+
+ // do a binary search for the minimal distance to start the iteration there
+ unsigned int index = (unsigned int)mPositions.size() / 2;
+ unsigned int binaryStepSize = (unsigned int)mPositions.size() / 4;
+ while( binaryStepSize > 1)
+ {
+ // Ugly, but conditional jumps are faster with integers than with floats
+ if( minDistBinary > ToBinary(mPositions[index].mDistance))
+ index += binaryStepSize;
+ else
+ index -= binaryStepSize;
+
+ binaryStepSize /= 2;
+ }
+
+ // depending on the direction of the last step we need to single step a bit back or forth
+ // to find the actual beginning element of the range
+ while( index > 0 && minDistBinary < ToBinary(mPositions[index].mDistance) )
+ index--;
+ while( index < (mPositions.size() - 1) && minDistBinary > ToBinary(mPositions[index].mDistance))
+ index++;
+
+ // Now start iterating from there until the first position lays outside of the distance range.
+ // Add all positions inside the distance range within the tolerance to the result array
+ std::vector<Entry>::const_iterator it = mPositions.begin() + index;
+ while( ToBinary(it->mDistance) < maxDistBinary)
+ {
+ if( distance3DToleranceInULPs >= ToBinary((it->mPosition - pPosition).SquareLength()))
+ poResults.push_back(it->mIndex);
+ ++it;
+ if( it == mPositions.end())
+ break;
+ }
+
+ // that's it
+}
+
+// ------------------------------------------------------------------------------------------------
+unsigned int SpatialSort::GenerateMappingTable(std::vector<unsigned int>& fill, ai_real pRadius) const
+{
+ fill.resize(mPositions.size(),UINT_MAX);
+ ai_real dist, maxDist;
+
+ unsigned int t=0;
+ const ai_real pSquared = pRadius*pRadius;
+ for (size_t i = 0; i < mPositions.size();) {
+ dist = mPositions[i].mPosition * mPlaneNormal;
+ maxDist = dist + pRadius;
+
+ fill[mPositions[i].mIndex] = t;
+ const aiVector3D& oldpos = mPositions[i].mPosition;
+ for (++i; i < fill.size() && mPositions[i].mDistance < maxDist
+ && (mPositions[i].mPosition - oldpos).SquareLength() < pSquared; ++i)
+ {
+ fill[mPositions[i].mIndex] = t;
+ }
+ ++t;
+ }
+
+#ifdef ASSIMP_BUILD_DEBUG
+
+ // debug invariant: mPositions[i].mIndex values must range from 0 to mPositions.size()-1
+ for (size_t i = 0; i < fill.size(); ++i) {
+ ai_assert(fill[i]<mPositions.size());
+ }
+
+#endif
+ return t;
+}
diff --git a/thirdparty/assimp/code/SplitByBoneCountProcess.cpp b/thirdparty/assimp/code/SplitByBoneCountProcess.cpp
new file mode 100644
index 0000000000..2ef66a9afc
--- /dev/null
+++ b/thirdparty/assimp/code/SplitByBoneCountProcess.cpp
@@ -0,0 +1,407 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+
+/// @file SplitByBoneCountProcess.cpp
+/// Implementation of the SplitByBoneCount postprocessing step
+
+// internal headers of the post-processing framework
+#include "SplitByBoneCountProcess.h"
+#include <assimp/postprocess.h>
+#include <assimp/DefaultLogger.hpp>
+
+#include <limits>
+#include <assimp/TinyFormatter.h>
+
+using namespace Assimp;
+using namespace Assimp::Formatter;
+
+// ------------------------------------------------------------------------------------------------
+// Constructor
+SplitByBoneCountProcess::SplitByBoneCountProcess()
+{
+ // set default, might be overridden by importer config
+ mMaxBoneCount = AI_SBBC_DEFAULT_MAX_BONES;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor
+SplitByBoneCountProcess::~SplitByBoneCountProcess()
+{
+ // nothing to do here
+}
+
+// ------------------------------------------------------------------------------------------------
+// Returns whether the processing step is present in the given flag.
+bool SplitByBoneCountProcess::IsActive( unsigned int pFlags) const
+{
+ return !!(pFlags & aiProcess_SplitByBoneCount);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Updates internal properties
+void SplitByBoneCountProcess::SetupProperties(const Importer* pImp)
+{
+ mMaxBoneCount = pImp->GetPropertyInteger(AI_CONFIG_PP_SBBC_MAX_BONES,AI_SBBC_DEFAULT_MAX_BONES);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+void SplitByBoneCountProcess::Execute( aiScene* pScene)
+{
+ ASSIMP_LOG_DEBUG("SplitByBoneCountProcess begin");
+
+ // early out
+ bool isNecessary = false;
+ for( unsigned int a = 0; a < pScene->mNumMeshes; ++a)
+ if( pScene->mMeshes[a]->mNumBones > mMaxBoneCount )
+ isNecessary = true;
+
+ if( !isNecessary )
+ {
+ ASSIMP_LOG_DEBUG( format() << "SplitByBoneCountProcess early-out: no meshes with more than " << mMaxBoneCount << " bones." );
+ return;
+ }
+
+ // we need to do something. Let's go.
+ mSubMeshIndices.clear();
+ mSubMeshIndices.resize( pScene->mNumMeshes);
+
+ // build a new array of meshes for the scene
+ std::vector<aiMesh*> meshes;
+
+ for( unsigned int a = 0; a < pScene->mNumMeshes; ++a)
+ {
+ aiMesh* srcMesh = pScene->mMeshes[a];
+
+ std::vector<aiMesh*> newMeshes;
+ SplitMesh( pScene->mMeshes[a], newMeshes);
+
+ // mesh was split
+ if( !newMeshes.empty() )
+ {
+ // store new meshes and indices of the new meshes
+ for( unsigned int b = 0; b < newMeshes.size(); ++b)
+ {
+ mSubMeshIndices[a].push_back( static_cast<unsigned int>(meshes.size()));
+ meshes.push_back( newMeshes[b]);
+ }
+
+ // and destroy the source mesh. It should be completely contained inside the new submeshes
+ delete srcMesh;
+ }
+ else
+ {
+ // Mesh is kept unchanged - store it's new place in the mesh array
+ mSubMeshIndices[a].push_back( static_cast<unsigned int>(meshes.size()));
+ meshes.push_back( srcMesh);
+ }
+ }
+
+ // rebuild the scene's mesh array
+ pScene->mNumMeshes = static_cast<unsigned int>(meshes.size());
+ delete [] pScene->mMeshes;
+ pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
+ std::copy( meshes.begin(), meshes.end(), pScene->mMeshes);
+
+ // recurse through all nodes and translate the node's mesh indices to fit the new mesh array
+ UpdateNode( pScene->mRootNode);
+
+ ASSIMP_LOG_DEBUG( format() << "SplitByBoneCountProcess end: split " << mSubMeshIndices.size() << " meshes into " << meshes.size() << " submeshes." );
+}
+
+// ------------------------------------------------------------------------------------------------
+// Splits the given mesh by bone count.
+void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh*>& poNewMeshes) const
+{
+ // skip if not necessary
+ if( pMesh->mNumBones <= mMaxBoneCount )
+ return;
+
+ // necessary optimisation: build a list of all affecting bones for each vertex
+ // TODO: (thom) maybe add a custom allocator here to avoid allocating tens of thousands of small arrays
+ typedef std::pair<unsigned int, float> BoneWeight;
+ std::vector< std::vector<BoneWeight> > vertexBones( pMesh->mNumVertices);
+ for( unsigned int a = 0; a < pMesh->mNumBones; ++a)
+ {
+ const aiBone* bone = pMesh->mBones[a];
+ for( unsigned int b = 0; b < bone->mNumWeights; ++b)
+ vertexBones[ bone->mWeights[b].mVertexId ].push_back( BoneWeight( a, bone->mWeights[b].mWeight));
+ }
+
+ unsigned int numFacesHandled = 0;
+ std::vector<bool> isFaceHandled( pMesh->mNumFaces, false);
+ while( numFacesHandled < pMesh->mNumFaces )
+ {
+ // which bones are used in the current submesh
+ unsigned int numBones = 0;
+ std::vector<bool> isBoneUsed( pMesh->mNumBones, false);
+ // indices of the faces which are going to go into this submesh
+ std::vector<unsigned int> subMeshFaces;
+ subMeshFaces.reserve( pMesh->mNumFaces);
+ // accumulated vertex count of all the faces in this submesh
+ unsigned int numSubMeshVertices = 0;
+ // a small local array of new bones for the current face. State of all used bones for that face
+ // can only be updated AFTER the face is completely analysed. Thanks to imre for the fix.
+ std::vector<unsigned int> newBonesAtCurrentFace;
+
+ // add faces to the new submesh as long as all bones affecting the faces' vertices fit in the limit
+ for( unsigned int a = 0; a < pMesh->mNumFaces; ++a)
+ {
+ // skip if the face is already stored in a submesh
+ if( isFaceHandled[a] )
+ continue;
+
+ const aiFace& face = pMesh->mFaces[a];
+ // check every vertex if its bones would still fit into the current submesh
+ for( unsigned int b = 0; b < face.mNumIndices; ++b )
+ {
+ const std::vector<BoneWeight>& vb = vertexBones[face.mIndices[b]];
+ for( unsigned int c = 0; c < vb.size(); ++c)
+ {
+ unsigned int boneIndex = vb[c].first;
+ // if the bone is already used in this submesh, it's ok
+ if( isBoneUsed[boneIndex] )
+ continue;
+
+ // if it's not used, yet, we would need to add it. Store its bone index
+ if( std::find( newBonesAtCurrentFace.begin(), newBonesAtCurrentFace.end(), boneIndex) == newBonesAtCurrentFace.end() )
+ newBonesAtCurrentFace.push_back( boneIndex);
+ }
+ }
+
+ // leave out the face if the new bones required for this face don't fit the bone count limit anymore
+ if( numBones + newBonesAtCurrentFace.size() > mMaxBoneCount )
+ continue;
+
+ // mark all new bones as necessary
+ while( !newBonesAtCurrentFace.empty() )
+ {
+ unsigned int newIndex = newBonesAtCurrentFace.back();
+ newBonesAtCurrentFace.pop_back(); // this also avoids the deallocation which comes with a clear()
+ if( isBoneUsed[newIndex] )
+ continue;
+
+ isBoneUsed[newIndex] = true;
+ numBones++;
+ }
+
+ // store the face index and the vertex count
+ subMeshFaces.push_back( a);
+ numSubMeshVertices += face.mNumIndices;
+
+ // remember that this face is handled
+ isFaceHandled[a] = true;
+ numFacesHandled++;
+ }
+
+ // create a new mesh to hold this subset of the source mesh
+ aiMesh* newMesh = new aiMesh;
+ if( pMesh->mName.length > 0 )
+ newMesh->mName.Set( format() << pMesh->mName.data << "_sub" << poNewMeshes.size());
+ newMesh->mMaterialIndex = pMesh->mMaterialIndex;
+ newMesh->mPrimitiveTypes = pMesh->mPrimitiveTypes;
+ poNewMeshes.push_back( newMesh);
+
+ // create all the arrays for this mesh if the old mesh contained them
+ newMesh->mNumVertices = numSubMeshVertices;
+ newMesh->mNumFaces = static_cast<unsigned int>(subMeshFaces.size());
+ newMesh->mVertices = new aiVector3D[newMesh->mNumVertices];
+ if( pMesh->HasNormals() )
+ newMesh->mNormals = new aiVector3D[newMesh->mNumVertices];
+ if( pMesh->HasTangentsAndBitangents() )
+ {
+ newMesh->mTangents = new aiVector3D[newMesh->mNumVertices];
+ newMesh->mBitangents = new aiVector3D[newMesh->mNumVertices];
+ }
+ for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a )
+ {
+ if( pMesh->HasTextureCoords( a) )
+ newMesh->mTextureCoords[a] = new aiVector3D[newMesh->mNumVertices];
+ newMesh->mNumUVComponents[a] = pMesh->mNumUVComponents[a];
+ }
+ for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a )
+ {
+ if( pMesh->HasVertexColors( a) )
+ newMesh->mColors[a] = new aiColor4D[newMesh->mNumVertices];
+ }
+
+ // and copy over the data, generating faces with linear indices along the way
+ newMesh->mFaces = new aiFace[subMeshFaces.size()];
+ unsigned int nvi = 0; // next vertex index
+ std::vector<unsigned int> previousVertexIndices( numSubMeshVertices, std::numeric_limits<unsigned int>::max()); // per new vertex: its index in the source mesh
+ for( unsigned int a = 0; a < subMeshFaces.size(); ++a )
+ {
+ const aiFace& srcFace = pMesh->mFaces[subMeshFaces[a]];
+ aiFace& dstFace = newMesh->mFaces[a];
+ dstFace.mNumIndices = srcFace.mNumIndices;
+ dstFace.mIndices = new unsigned int[dstFace.mNumIndices];
+
+ // accumulate linearly all the vertices of the source face
+ for( unsigned int b = 0; b < dstFace.mNumIndices; ++b )
+ {
+ unsigned int srcIndex = srcFace.mIndices[b];
+ dstFace.mIndices[b] = nvi;
+ previousVertexIndices[nvi] = srcIndex;
+
+ newMesh->mVertices[nvi] = pMesh->mVertices[srcIndex];
+ if( pMesh->HasNormals() )
+ newMesh->mNormals[nvi] = pMesh->mNormals[srcIndex];
+ if( pMesh->HasTangentsAndBitangents() )
+ {
+ newMesh->mTangents[nvi] = pMesh->mTangents[srcIndex];
+ newMesh->mBitangents[nvi] = pMesh->mBitangents[srcIndex];
+ }
+ for( unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++c )
+ {
+ if( pMesh->HasTextureCoords( c) )
+ newMesh->mTextureCoords[c][nvi] = pMesh->mTextureCoords[c][srcIndex];
+ }
+ for( unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS; ++c )
+ {
+ if( pMesh->HasVertexColors( c) )
+ newMesh->mColors[c][nvi] = pMesh->mColors[c][srcIndex];
+ }
+
+ nvi++;
+ }
+ }
+
+ ai_assert( nvi == numSubMeshVertices );
+
+ // Create the bones for the new submesh: first create the bone array
+ newMesh->mNumBones = 0;
+ newMesh->mBones = new aiBone*[numBones];
+
+ std::vector<unsigned int> mappedBoneIndex( pMesh->mNumBones, std::numeric_limits<unsigned int>::max());
+ for( unsigned int a = 0; a < pMesh->mNumBones; ++a )
+ {
+ if( !isBoneUsed[a] )
+ continue;
+
+ // create the new bone
+ const aiBone* srcBone = pMesh->mBones[a];
+ aiBone* dstBone = new aiBone;
+ mappedBoneIndex[a] = newMesh->mNumBones;
+ newMesh->mBones[newMesh->mNumBones++] = dstBone;
+ dstBone->mName = srcBone->mName;
+ dstBone->mOffsetMatrix = srcBone->mOffsetMatrix;
+ dstBone->mNumWeights = 0;
+ }
+
+ ai_assert( newMesh->mNumBones == numBones );
+
+ // iterate over all new vertices and count which bones affected its old vertex in the source mesh
+ for( unsigned int a = 0; a < numSubMeshVertices; ++a )
+ {
+ unsigned int oldIndex = previousVertexIndices[a];
+ const std::vector<BoneWeight>& bonesOnThisVertex = vertexBones[oldIndex];
+
+ for( unsigned int b = 0; b < bonesOnThisVertex.size(); ++b )
+ {
+ unsigned int newBoneIndex = mappedBoneIndex[ bonesOnThisVertex[b].first ];
+ if( newBoneIndex != std::numeric_limits<unsigned int>::max() )
+ newMesh->mBones[newBoneIndex]->mNumWeights++;
+ }
+ }
+
+ // allocate all bone weight arrays accordingly
+ for( unsigned int a = 0; a < newMesh->mNumBones; ++a )
+ {
+ aiBone* bone = newMesh->mBones[a];
+ ai_assert( bone->mNumWeights > 0 );
+ bone->mWeights = new aiVertexWeight[bone->mNumWeights];
+ bone->mNumWeights = 0; // for counting up in the next step
+ }
+
+ // now copy all the bone vertex weights for all the vertices which made it into the new submesh
+ for( unsigned int a = 0; a < numSubMeshVertices; ++a)
+ {
+ // find the source vertex for it in the source mesh
+ unsigned int previousIndex = previousVertexIndices[a];
+ // these bones were affecting it
+ const std::vector<BoneWeight>& bonesOnThisVertex = vertexBones[previousIndex];
+ // all of the bones affecting it should be present in the new submesh, or else
+ // the face it comprises shouldn't be present
+ for( unsigned int b = 0; b < bonesOnThisVertex.size(); ++b)
+ {
+ unsigned int newBoneIndex = mappedBoneIndex[ bonesOnThisVertex[b].first ];
+ ai_assert( newBoneIndex != std::numeric_limits<unsigned int>::max() );
+ aiVertexWeight* dstWeight = newMesh->mBones[newBoneIndex]->mWeights + newMesh->mBones[newBoneIndex]->mNumWeights;
+ newMesh->mBones[newBoneIndex]->mNumWeights++;
+
+ dstWeight->mVertexId = a;
+ dstWeight->mWeight = bonesOnThisVertex[b].second;
+ }
+ }
+
+ // I have the strange feeling that this will break apart at some point in time...
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Recursively updates the node's mesh list to account for the changed mesh list
+void SplitByBoneCountProcess::UpdateNode( aiNode* pNode) const
+{
+ // rebuild the node's mesh index list
+ if( pNode->mNumMeshes > 0 )
+ {
+ std::vector<unsigned int> newMeshList;
+ for( unsigned int a = 0; a < pNode->mNumMeshes; ++a)
+ {
+ unsigned int srcIndex = pNode->mMeshes[a];
+ const std::vector<unsigned int>& replaceMeshes = mSubMeshIndices[srcIndex];
+ newMeshList.insert( newMeshList.end(), replaceMeshes.begin(), replaceMeshes.end());
+ }
+
+ delete [] pNode->mMeshes;
+ pNode->mNumMeshes = static_cast<unsigned int>(newMeshList.size());
+ pNode->mMeshes = new unsigned int[pNode->mNumMeshes];
+ std::copy( newMeshList.begin(), newMeshList.end(), pNode->mMeshes);
+ }
+
+ // do that also recursively for all children
+ for( unsigned int a = 0; a < pNode->mNumChildren; ++a )
+ {
+ UpdateNode( pNode->mChildren[a]);
+ }
+}
diff --git a/thirdparty/assimp/code/SplitByBoneCountProcess.h b/thirdparty/assimp/code/SplitByBoneCountProcess.h
new file mode 100644
index 0000000000..6c904a9df4
--- /dev/null
+++ b/thirdparty/assimp/code/SplitByBoneCountProcess.h
@@ -0,0 +1,111 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/// @file SplitByBoneCountProcess.h
+/// Defines a post processing step to split meshes with many bones into submeshes
+#ifndef AI_SPLITBYBONECOUNTPROCESS_H_INC
+#define AI_SPLITBYBONECOUNTPROCESS_H_INC
+
+#include <vector>
+#include "BaseProcess.h"
+
+#include <assimp/mesh.h>
+#include <assimp/scene.h>
+
+namespace Assimp
+{
+
+
+/** Postprocessing filter to split meshes with many bones into submeshes
+ * so that each submesh has a certain max bone count.
+ *
+ * Applied BEFORE the JoinVertices-Step occurs.
+ * Returns NON-UNIQUE vertices, splits by bone count.
+*/
+class SplitByBoneCountProcess : public BaseProcess
+{
+public:
+
+ SplitByBoneCountProcess();
+ ~SplitByBoneCountProcess();
+
+public:
+ /** Returns whether the processing step is present in the given flag.
+ * @param pFlags The processing flags the importer was called with. A
+ * bitwise combination of #aiPostProcessSteps.
+ * @return true if the process is present in this flag fields,
+ * false if not.
+ */
+ bool IsActive( unsigned int pFlags) const;
+
+ /** Called prior to ExecuteOnScene().
+ * The function is a request to the process to update its configuration
+ * basing on the Importer's configuration property list.
+ */
+ virtual void SetupProperties(const Importer* pImp);
+
+protected:
+ /** Executes the post processing step on the given imported data.
+ * At the moment a process is not supposed to fail.
+ * @param pScene The imported data to work at.
+ */
+ void Execute( aiScene* pScene);
+
+ /// Splits the given mesh by bone count.
+ /// @param pMesh the Mesh to split. Is not changed at all, but might be superfluous in case it was split.
+ /// @param poNewMeshes Array of submeshes created in the process. Empty if splitting was not necessary.
+ void SplitMesh( const aiMesh* pMesh, std::vector<aiMesh*>& poNewMeshes) const;
+
+ /// Recursively updates the node's mesh list to account for the changed mesh list
+ void UpdateNode( aiNode* pNode) const;
+
+public:
+ /// Max bone count. Splitting occurs if a mesh has more than that number of bones.
+ size_t mMaxBoneCount;
+
+ /// Per mesh index: Array of indices of the new submeshes.
+ std::vector< std::vector<unsigned int> > mSubMeshIndices;
+};
+
+} // end of namespace Assimp
+
+#endif // !!AI_SPLITBYBONECOUNTPROCESS_H_INC
diff --git a/thirdparty/assimp/code/SplitLargeMeshes.cpp b/thirdparty/assimp/code/SplitLargeMeshes.cpp
new file mode 100644
index 0000000000..1797b28d5a
--- /dev/null
+++ b/thirdparty/assimp/code/SplitLargeMeshes.cpp
@@ -0,0 +1,623 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/**
+ * @file Implementation of the SplitLargeMeshes postprocessing step
+ */
+
+// internal headers of the post-processing framework
+#include "SplitLargeMeshes.h"
+#include "ProcessHelper.h"
+
+using namespace Assimp;
+
+// ------------------------------------------------------------------------------------------------
+SplitLargeMeshesProcess_Triangle::SplitLargeMeshesProcess_Triangle() {
+ LIMIT = AI_SLM_DEFAULT_MAX_TRIANGLES;
+}
+
+// ------------------------------------------------------------------------------------------------
+SplitLargeMeshesProcess_Triangle::~SplitLargeMeshesProcess_Triangle() {
+ // nothing to do here
+}
+
+// ------------------------------------------------------------------------------------------------
+// Returns whether the processing step is present in the given flag field.
+bool SplitLargeMeshesProcess_Triangle::IsActive( unsigned int pFlags) const {
+ return (pFlags & aiProcess_SplitLargeMeshes) != 0;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+void SplitLargeMeshesProcess_Triangle::Execute( aiScene* pScene) {
+ if (0xffffffff == this->LIMIT || nullptr == pScene ) {
+ return;
+ }
+
+ ASSIMP_LOG_DEBUG("SplitLargeMeshesProcess_Triangle begin");
+ std::vector<std::pair<aiMesh*, unsigned int> > avList;
+
+ for( unsigned int a = 0; a < pScene->mNumMeshes; ++a) {
+ this->SplitMesh(a, pScene->mMeshes[a],avList);
+ }
+
+ if (avList.size() != pScene->mNumMeshes) {
+ // it seems something has been split. rebuild the mesh list
+ delete[] pScene->mMeshes;
+ pScene->mNumMeshes = (unsigned int)avList.size();
+ pScene->mMeshes = new aiMesh*[avList.size()];
+
+ for (unsigned int i = 0; i < avList.size();++i) {
+ pScene->mMeshes[i] = avList[i].first;
+ }
+
+ // now we need to update all nodes
+ this->UpdateNode(pScene->mRootNode,avList);
+ ASSIMP_LOG_INFO("SplitLargeMeshesProcess_Triangle finished. Meshes have been split");
+ } else {
+ ASSIMP_LOG_DEBUG("SplitLargeMeshesProcess_Triangle finished. There was nothing to do");
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Setup properties
+void SplitLargeMeshesProcess_Triangle::SetupProperties( const Importer* pImp) {
+ // get the current value of the split property
+ this->LIMIT = pImp->GetPropertyInteger(AI_CONFIG_PP_SLM_TRIANGLE_LIMIT,AI_SLM_DEFAULT_MAX_TRIANGLES);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Update a node after some meshes have been split
+void SplitLargeMeshesProcess_Triangle::UpdateNode(aiNode* pcNode,
+ const std::vector<std::pair<aiMesh*, unsigned int> >& avList) {
+ // for every index in out list build a new entry
+ std::vector<unsigned int> aiEntries;
+ aiEntries.reserve(pcNode->mNumMeshes + 1);
+ for (unsigned int i = 0; i < pcNode->mNumMeshes;++i) {
+ for (unsigned int a = 0; a < avList.size();++a) {
+ if (avList[a].second == pcNode->mMeshes[i]) {
+ aiEntries.push_back(a);
+ }
+ }
+ }
+
+ // now build the new list
+ delete[] pcNode->mMeshes;
+ pcNode->mNumMeshes = (unsigned int)aiEntries.size();
+ pcNode->mMeshes = new unsigned int[pcNode->mNumMeshes];
+
+ for (unsigned int b = 0; b < pcNode->mNumMeshes;++b) {
+ pcNode->mMeshes[b] = aiEntries[b];
+ }
+
+ // recusively update all other nodes
+ for (unsigned int i = 0; i < pcNode->mNumChildren;++i) {
+ UpdateNode ( pcNode->mChildren[i], avList );
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+void SplitLargeMeshesProcess_Triangle::SplitMesh(
+ unsigned int a,
+ aiMesh* pMesh,
+ std::vector<std::pair<aiMesh*, unsigned int> >& avList) {
+ if (pMesh->mNumFaces > SplitLargeMeshesProcess_Triangle::LIMIT) {
+ ASSIMP_LOG_INFO("Mesh exceeds the triangle limit. It will be split ...");
+
+ // we need to split this mesh into sub meshes
+ // determine the size of a submesh
+ const unsigned int iSubMeshes = (pMesh->mNumFaces / LIMIT) + 1;
+
+ const unsigned int iOutFaceNum = pMesh->mNumFaces / iSubMeshes;
+ const unsigned int iOutVertexNum = iOutFaceNum * 3;
+
+ // now generate all submeshes
+ for (unsigned int i = 0; i < iSubMeshes;++i) {
+ aiMesh* pcMesh = new aiMesh;
+ pcMesh->mNumFaces = iOutFaceNum;
+ pcMesh->mMaterialIndex = pMesh->mMaterialIndex;
+
+ // the name carries the adjacency information between the meshes
+ pcMesh->mName = pMesh->mName;
+
+ if (i == iSubMeshes-1) {
+ pcMesh->mNumFaces = iOutFaceNum + (
+ pMesh->mNumFaces - iOutFaceNum * iSubMeshes);
+ }
+ // copy the list of faces
+ pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
+
+ const unsigned int iBase = iOutFaceNum * i;
+
+ // get the total number of indices
+ unsigned int iCnt = 0;
+ for (unsigned int p = iBase; p < pcMesh->mNumFaces + iBase;++p) {
+ iCnt += pMesh->mFaces[p].mNumIndices;
+ }
+ pcMesh->mNumVertices = iCnt;
+
+ // allocate storage
+ if (pMesh->mVertices != nullptr) {
+ pcMesh->mVertices = new aiVector3D[iCnt];
+ }
+
+ if (pMesh->HasNormals()) {
+ pcMesh->mNormals = new aiVector3D[iCnt];
+ }
+
+ if (pMesh->HasTangentsAndBitangents()) {
+ pcMesh->mTangents = new aiVector3D[iCnt];
+ pcMesh->mBitangents = new aiVector3D[iCnt];
+ }
+
+ // texture coordinates
+ for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) {
+ pcMesh->mNumUVComponents[c] = pMesh->mNumUVComponents[c];
+ if (pMesh->HasTextureCoords( c)) {
+ pcMesh->mTextureCoords[c] = new aiVector3D[iCnt];
+ }
+ }
+
+ // vertex colors
+ for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS;++c) {
+ if (pMesh->HasVertexColors( c)) {
+ pcMesh->mColors[c] = new aiColor4D[iCnt];
+ }
+ }
+
+ if (pMesh->HasBones()) {
+ // assume the number of bones won't change in most cases
+ pcMesh->mBones = new aiBone*[pMesh->mNumBones];
+
+ // iterate through all bones of the mesh and find those which
+ // need to be copied to the split mesh
+ std::vector<aiVertexWeight> avTempWeights;
+ for (unsigned int p = 0; p < pcMesh->mNumBones;++p) {
+ aiBone* const bone = pcMesh->mBones[p];
+ avTempWeights.clear();
+ avTempWeights.reserve(bone->mNumWeights / iSubMeshes);
+
+ for (unsigned int q = 0; q < bone->mNumWeights;++q) {
+ aiVertexWeight& weight = bone->mWeights[q];
+ if(weight.mVertexId >= iBase && weight.mVertexId < iBase + iOutVertexNum) {
+ avTempWeights.push_back(weight);
+ weight = avTempWeights.back();
+ weight.mVertexId -= iBase;
+ }
+ }
+
+ if (!avTempWeights.empty()) {
+ // we'll need this bone. Copy it ...
+ aiBone* pc = new aiBone();
+ pcMesh->mBones[pcMesh->mNumBones++] = pc;
+ pc->mName = aiString(bone->mName);
+ pc->mNumWeights = (unsigned int)avTempWeights.size();
+ pc->mOffsetMatrix = bone->mOffsetMatrix;
+
+ // no need to reallocate the array for the last submesh.
+ // Here we can reuse the (large) source array, although
+ // we'll waste some memory
+ if (iSubMeshes-1 == i) {
+ pc->mWeights = bone->mWeights;
+ bone->mWeights = nullptr;
+ } else {
+ pc->mWeights = new aiVertexWeight[pc->mNumWeights];
+ }
+
+ // copy the weights
+ ::memcpy(pc->mWeights,&avTempWeights[0],sizeof(aiVertexWeight)*pc->mNumWeights);
+ }
+ }
+ }
+
+ // (we will also need to copy the array of indices)
+ unsigned int iCurrent = 0;
+ for (unsigned int p = 0; p < pcMesh->mNumFaces;++p) {
+ pcMesh->mFaces[p].mNumIndices = 3;
+ // allocate a new array
+ const unsigned int iTemp = p + iBase;
+ const unsigned int iNumIndices = pMesh->mFaces[iTemp].mNumIndices;
+
+ // setup face type and number of indices
+ pcMesh->mFaces[p].mNumIndices = iNumIndices;
+ unsigned int* pi = pMesh->mFaces[iTemp].mIndices;
+ unsigned int* piOut = pcMesh->mFaces[p].mIndices = new unsigned int[iNumIndices];
+
+ // need to update the output primitive types
+ switch (iNumIndices) {
+ case 1:
+ pcMesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
+ break;
+ case 2:
+ pcMesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
+ break;
+ case 3:
+ pcMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
+ break;
+ default:
+ pcMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
+ }
+
+ // and copy the contents of the old array, offset by current base
+ for (unsigned int v = 0; v < iNumIndices;++v) {
+ unsigned int iIndex = pi[v];
+ unsigned int iIndexOut = iCurrent++;
+ piOut[v] = iIndexOut;
+
+ // copy positions
+ if (pMesh->mVertices != nullptr) {
+ pcMesh->mVertices[iIndexOut] = pMesh->mVertices[iIndex];
+ }
+
+ // copy normals
+ if (pMesh->HasNormals()) {
+ pcMesh->mNormals[iIndexOut] = pMesh->mNormals[iIndex];
+ }
+
+ // copy tangents/bitangents
+ if (pMesh->HasTangentsAndBitangents()) {
+ pcMesh->mTangents[iIndexOut] = pMesh->mTangents[iIndex];
+ pcMesh->mBitangents[iIndexOut] = pMesh->mBitangents[iIndex];
+ }
+
+ // texture coordinates
+ for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) {
+ if (pMesh->HasTextureCoords( c ) ) {
+ pcMesh->mTextureCoords[c][iIndexOut] = pMesh->mTextureCoords[c][iIndex];
+ }
+ }
+ // vertex colors
+ for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS;++c) {
+ if (pMesh->HasVertexColors( c)) {
+ pcMesh->mColors[c][iIndexOut] = pMesh->mColors[c][iIndex];
+ }
+ }
+ }
+ }
+
+ // add the newly created mesh to the list
+ avList.push_back(std::pair<aiMesh*, unsigned int>(pcMesh,a));
+ }
+
+ // now delete the old mesh data
+ delete pMesh;
+ } else {
+ avList.push_back(std::pair<aiMesh*, unsigned int>(pMesh,a));
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+SplitLargeMeshesProcess_Vertex::SplitLargeMeshesProcess_Vertex() {
+ LIMIT = AI_SLM_DEFAULT_MAX_VERTICES;
+}
+
+// ------------------------------------------------------------------------------------------------
+SplitLargeMeshesProcess_Vertex::~SplitLargeMeshesProcess_Vertex() {
+ // nothing to do here
+}
+
+// ------------------------------------------------------------------------------------------------
+// Returns whether the processing step is present in the given flag field.
+bool SplitLargeMeshesProcess_Vertex::IsActive( unsigned int pFlags) const {
+ return (pFlags & aiProcess_SplitLargeMeshes) != 0;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+void SplitLargeMeshesProcess_Vertex::Execute( aiScene* pScene) {
+ if (0xffffffff == this->LIMIT || nullptr == pScene ) {
+ return;
+ }
+
+ ASSIMP_LOG_DEBUG("SplitLargeMeshesProcess_Vertex begin");
+
+ std::vector<std::pair<aiMesh*, unsigned int> > avList;
+
+ //Check for point cloud first,
+ //Do not process point cloud, splitMesh works only with faces data
+ for (unsigned int a = 0; a < pScene->mNumMeshes; a++) {
+ if ( pScene->mMeshes[a]->mPrimitiveTypes == aiPrimitiveType_POINT ) {
+ return;
+ }
+ }
+
+ for( unsigned int a = 0; a < pScene->mNumMeshes; ++a ) {
+ this->SplitMesh(a, pScene->mMeshes[a], avList);
+ }
+
+ if (avList.size() != pScene->mNumMeshes) {
+ // it seems something has been split. rebuild the mesh list
+ delete[] pScene->mMeshes;
+ pScene->mNumMeshes = (unsigned int)avList.size();
+ pScene->mMeshes = new aiMesh*[avList.size()];
+
+ for (unsigned int i = 0; i < avList.size();++i) {
+ pScene->mMeshes[i] = avList[i].first;
+ }
+
+ // now we need to update all nodes
+ SplitLargeMeshesProcess_Triangle::UpdateNode(pScene->mRootNode,avList);
+ ASSIMP_LOG_INFO("SplitLargeMeshesProcess_Vertex finished. Meshes have been split");
+ } else {
+ ASSIMP_LOG_DEBUG("SplitLargeMeshesProcess_Vertex finished. There was nothing to do");
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Setup properties
+void SplitLargeMeshesProcess_Vertex::SetupProperties( const Importer* pImp) {
+ this->LIMIT = pImp->GetPropertyInteger(AI_CONFIG_PP_SLM_VERTEX_LIMIT,AI_SLM_DEFAULT_MAX_VERTICES);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+void SplitLargeMeshesProcess_Vertex::SplitMesh(
+ unsigned int a,
+ aiMesh* pMesh,
+ std::vector<std::pair<aiMesh*, unsigned int> >& avList) {
+ if (pMesh->mNumVertices > SplitLargeMeshesProcess_Vertex::LIMIT) {
+ typedef std::vector< std::pair<unsigned int,float> > VertexWeightTable;
+
+ // build a per-vertex weight list if necessary
+ VertexWeightTable* avPerVertexWeights = ComputeVertexBoneWeightTable(pMesh);
+
+ // we need to split this mesh into sub meshes
+ // determine the estimated size of a submesh
+ // (this could be too large. Max waste is a single digit percentage)
+ const unsigned int iSubMeshes = (pMesh->mNumVertices / SplitLargeMeshesProcess_Vertex::LIMIT) + 1;
+
+ // create a std::vector<unsigned int> to indicate which vertices
+ // have already been copied
+ std::vector<unsigned int> avWasCopied;
+ avWasCopied.resize(pMesh->mNumVertices,0xFFFFFFFF);
+
+ // try to find a good estimate for the number of output faces
+ // per mesh. Add 12.5% as buffer
+ unsigned int iEstimatedSize = pMesh->mNumFaces / iSubMeshes;
+ iEstimatedSize += iEstimatedSize >> 3;
+
+ // now generate all submeshes
+ unsigned int iBase( 0 );
+ while (true) {
+ const unsigned int iOutVertexNum = SplitLargeMeshesProcess_Vertex::LIMIT;
+ aiMesh* pcMesh = new aiMesh;
+ pcMesh->mNumVertices = 0;
+ pcMesh->mMaterialIndex = pMesh->mMaterialIndex;
+
+ // the name carries the adjacency information between the meshes
+ pcMesh->mName = pMesh->mName;
+
+ typedef std::vector<aiVertexWeight> BoneWeightList;
+ if (pMesh->HasBones()) {
+ pcMesh->mBones = new aiBone*[pMesh->mNumBones];
+ ::memset(pcMesh->mBones,0,sizeof(void*)*pMesh->mNumBones);
+ }
+
+ // clear the temporary helper array
+ if (iBase) {
+ // we can't use memset here we unsigned int needn' be 32 bits
+ for (auto &elem : avWasCopied) {
+ elem = 0xffffffff;
+ }
+ }
+
+ // output vectors
+ std::vector<aiFace> vFaces;
+
+ // reserve enough storage for most cases
+ if (pMesh->HasPositions()) {
+ pcMesh->mVertices = new aiVector3D[iOutVertexNum];
+ }
+ if (pMesh->HasNormals()) {
+ pcMesh->mNormals = new aiVector3D[iOutVertexNum];
+ }
+ if (pMesh->HasTangentsAndBitangents()) {
+ pcMesh->mTangents = new aiVector3D[iOutVertexNum];
+ pcMesh->mBitangents = new aiVector3D[iOutVertexNum];
+ }
+ for (unsigned int c = 0; pMesh->HasVertexColors(c);++c) {
+ pcMesh->mColors[c] = new aiColor4D[iOutVertexNum];
+ }
+ for (unsigned int c = 0; pMesh->HasTextureCoords(c);++c) {
+ pcMesh->mNumUVComponents[c] = pMesh->mNumUVComponents[c];
+ pcMesh->mTextureCoords[c] = new aiVector3D[iOutVertexNum];
+ }
+ vFaces.reserve(iEstimatedSize);
+
+ // (we will also need to copy the array of indices)
+ while (iBase < pMesh->mNumFaces) {
+ // allocate a new array
+ const unsigned int iNumIndices = pMesh->mFaces[iBase].mNumIndices;
+
+ // doesn't catch degenerates but is quite fast
+ unsigned int iNeed = 0;
+ for (unsigned int v = 0; v < iNumIndices;++v) {
+ unsigned int iIndex = pMesh->mFaces[iBase].mIndices[v];
+
+ // check whether we do already have this vertex
+ if (0xFFFFFFFF == avWasCopied[iIndex]) {
+ iNeed++;
+ }
+ }
+ if (pcMesh->mNumVertices + iNeed > iOutVertexNum) {
+ // don't use this face
+ break;
+ }
+
+ vFaces.push_back(aiFace());
+ aiFace& rFace = vFaces.back();
+
+ // setup face type and number of indices
+ rFace.mNumIndices = iNumIndices;
+ rFace.mIndices = new unsigned int[iNumIndices];
+
+ // need to update the output primitive types
+ switch (rFace.mNumIndices) {
+ case 1:
+ pcMesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
+ break;
+ case 2:
+ pcMesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
+ break;
+ case 3:
+ pcMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
+ break;
+ default:
+ pcMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
+ }
+
+ // and copy the contents of the old array, offset by current base
+ for (unsigned int v = 0; v < iNumIndices;++v) {
+ unsigned int iIndex = pMesh->mFaces[iBase].mIndices[v];
+
+ // check whether we do already have this vertex
+ if (0xFFFFFFFF != avWasCopied[iIndex]) {
+ rFace.mIndices[v] = avWasCopied[iIndex];
+ continue;
+ }
+
+ // copy positions
+ pcMesh->mVertices[pcMesh->mNumVertices] = (pMesh->mVertices[iIndex]);
+
+ // copy normals
+ if (pMesh->HasNormals()) {
+ pcMesh->mNormals[pcMesh->mNumVertices] = (pMesh->mNormals[iIndex]);
+ }
+
+ // copy tangents/bitangents
+ if (pMesh->HasTangentsAndBitangents()) {
+ pcMesh->mTangents[pcMesh->mNumVertices] = (pMesh->mTangents[iIndex]);
+ pcMesh->mBitangents[pcMesh->mNumVertices] = (pMesh->mBitangents[iIndex]);
+ }
+
+ // texture coordinates
+ for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) {
+ if (pMesh->HasTextureCoords( c)) {
+ pcMesh->mTextureCoords[c][pcMesh->mNumVertices] = pMesh->mTextureCoords[c][iIndex];
+ }
+ }
+ // vertex colors
+ for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS;++c) {
+ if (pMesh->HasVertexColors( c)) {
+ pcMesh->mColors[c][pcMesh->mNumVertices] = pMesh->mColors[c][iIndex];
+ }
+ }
+ // check whether we have bone weights assigned to this vertex
+ rFace.mIndices[v] = pcMesh->mNumVertices;
+ if (avPerVertexWeights) {
+ VertexWeightTable& table = avPerVertexWeights[ pcMesh->mNumVertices ];
+ if( !table.empty() ) {
+ for (VertexWeightTable::const_iterator iter = table.begin();
+ iter != table.end();++iter) {
+ // allocate the bone weight array if necessary
+ BoneWeightList* pcWeightList = (BoneWeightList*)pcMesh->mBones[(*iter).first];
+ if (nullptr == pcWeightList) {
+ pcMesh->mBones[(*iter).first] = (aiBone*)(pcWeightList = new BoneWeightList());
+ }
+ pcWeightList->push_back(aiVertexWeight(pcMesh->mNumVertices,(*iter).second));
+ }
+ }
+ }
+
+ avWasCopied[iIndex] = pcMesh->mNumVertices;
+ pcMesh->mNumVertices++;
+ }
+ ++iBase;
+ if(pcMesh->mNumVertices == iOutVertexNum) {
+ // break here. The face is only added if it was complete
+ break;
+ }
+ }
+
+ // check which bones we'll need to create for this submesh
+ if (pMesh->HasBones()) {
+ aiBone** ppCurrent = pcMesh->mBones;
+ for (unsigned int k = 0; k < pMesh->mNumBones;++k) {
+ // check whether the bone is existing
+ BoneWeightList* pcWeightList;
+ if ((pcWeightList = (BoneWeightList*)pcMesh->mBones[k])) {
+ aiBone* pcOldBone = pMesh->mBones[k];
+ aiBone* pcOut( nullptr );
+ *ppCurrent++ = pcOut = new aiBone();
+ pcOut->mName = aiString(pcOldBone->mName);
+ pcOut->mOffsetMatrix = pcOldBone->mOffsetMatrix;
+ pcOut->mNumWeights = (unsigned int)pcWeightList->size();
+ pcOut->mWeights = new aiVertexWeight[pcOut->mNumWeights];
+
+ // copy the vertex weights
+ ::memcpy(pcOut->mWeights,&pcWeightList->operator[](0),
+ pcOut->mNumWeights * sizeof(aiVertexWeight));
+
+ // delete the temporary bone weight list
+ delete pcWeightList;
+ pcMesh->mNumBones++;
+ }
+ }
+ }
+
+ // copy the face list to the mesh
+ pcMesh->mFaces = new aiFace[vFaces.size()];
+ pcMesh->mNumFaces = (unsigned int)vFaces.size();
+
+ for (unsigned int p = 0; p < pcMesh->mNumFaces;++p) {
+ pcMesh->mFaces[p] = vFaces[p];
+ }
+
+ // add the newly created mesh to the list
+ avList.push_back(std::pair<aiMesh*, unsigned int>(pcMesh,a));
+
+ if (iBase == pMesh->mNumFaces) {
+ // have all faces ... finish the outer loop, too
+ break;
+ }
+ }
+
+ // delete the per-vertex weight list again
+ delete[] avPerVertexWeights;
+
+ // now delete the old mesh data
+ delete pMesh;
+ return;
+ }
+ avList.push_back(std::pair<aiMesh*, unsigned int>(pMesh,a));
+}
diff --git a/thirdparty/assimp/code/SplitLargeMeshes.h b/thirdparty/assimp/code/SplitLargeMeshes.h
new file mode 100644
index 0000000000..77f089ce7e
--- /dev/null
+++ b/thirdparty/assimp/code/SplitLargeMeshes.h
@@ -0,0 +1,210 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file Defines a post processing step to split large meshes into submeshes
+ */
+#ifndef AI_SPLITLARGEMESHES_H_INC
+#define AI_SPLITLARGEMESHES_H_INC
+
+#include <vector>
+#include "BaseProcess.h"
+
+#include <assimp/mesh.h>
+#include <assimp/scene.h>
+
+class SplitLargeMeshesTest;
+
+namespace Assimp
+{
+
+class SplitLargeMeshesProcess_Triangle;
+class SplitLargeMeshesProcess_Vertex;
+
+// NOTE: If you change these limits, don't forget to change the
+// corresponding values in all Assimp ports
+
+// **********************************************************
+// Java: ConfigProperty.java,
+// ConfigProperty.DEFAULT_VERTEX_SPLIT_LIMIT
+// ConfigProperty.DEFAULT_TRIANGLE_SPLIT_LIMIT
+// **********************************************************
+
+// default limit for vertices
+#if (!defined AI_SLM_DEFAULT_MAX_VERTICES)
+# define AI_SLM_DEFAULT_MAX_VERTICES 1000000
+#endif
+
+// default limit for triangles
+#if (!defined AI_SLM_DEFAULT_MAX_TRIANGLES)
+# define AI_SLM_DEFAULT_MAX_TRIANGLES 1000000
+#endif
+
+// ---------------------------------------------------------------------------
+/** Post-processing filter to split large meshes into sub-meshes
+ *
+ * Applied BEFORE the JoinVertices-Step occurs.
+ * Returns NON-UNIQUE vertices, splits by triangle number.
+*/
+class ASSIMP_API SplitLargeMeshesProcess_Triangle : public BaseProcess
+{
+ friend class SplitLargeMeshesProcess_Vertex;
+
+public:
+
+ SplitLargeMeshesProcess_Triangle();
+ ~SplitLargeMeshesProcess_Triangle();
+
+public:
+ // -------------------------------------------------------------------
+ /** Returns whether the processing step is present in the given flag.
+ * @param pFlags The processing flags the importer was called with. A
+ * bitwise combination of #aiPostProcessSteps.
+ * @return true if the process is present in this flag fields,
+ * false if not.
+ */
+ bool IsActive( unsigned int pFlags) const;
+
+
+ // -------------------------------------------------------------------
+ /** Called prior to ExecuteOnScene().
+ * The function is a request to the process to update its configuration
+ * basing on the Importer's configuration property list.
+ */
+ virtual void SetupProperties(const Importer* pImp);
+
+
+ //! Set the split limit - needed for unit testing
+ inline void SetLimit(unsigned int l)
+ {LIMIT = l;}
+
+ //! Get the split limit
+ inline unsigned int GetLimit() const
+ {return LIMIT;}
+
+public:
+
+ // -------------------------------------------------------------------
+ /** Executes the post processing step on the given imported data.
+ * At the moment a process is not supposed to fail.
+ * @param pScene The imported data to work at.
+ */
+ void Execute( aiScene* pScene);
+
+ // -------------------------------------------------------------------
+ //! Apply the algorithm to a given mesh
+ void SplitMesh (unsigned int a, aiMesh* pcMesh,
+ std::vector<std::pair<aiMesh*, unsigned int> >& avList);
+
+ // -------------------------------------------------------------------
+ //! Update a node in the asset after a few of its meshes
+ //! have been split
+ static void UpdateNode(aiNode* pcNode,
+ const std::vector<std::pair<aiMesh*, unsigned int> >& avList);
+
+public:
+ //! Triangle limit
+ unsigned int LIMIT;
+};
+
+
+// ---------------------------------------------------------------------------
+/** Post-processing filter to split large meshes into sub-meshes
+ *
+ * Applied AFTER the JoinVertices-Step occurs.
+ * Returns UNIQUE vertices, splits by vertex number.
+*/
+class ASSIMP_API SplitLargeMeshesProcess_Vertex : public BaseProcess
+{
+public:
+
+ SplitLargeMeshesProcess_Vertex();
+ ~SplitLargeMeshesProcess_Vertex();
+
+public:
+ // -------------------------------------------------------------------
+ /** Returns whether the processing step is present in the given flag field.
+ * @param pFlags The processing flags the importer was called with. A bitwise
+ * combination of #aiPostProcessSteps.
+ * @return true if the process is present in this flag fields, false if not.
+ */
+ bool IsActive( unsigned int pFlags) const;
+
+ // -------------------------------------------------------------------
+ /** Called prior to ExecuteOnScene().
+ * The function is a request to the process to update its configuration
+ * basing on the Importer's configuration property list.
+ */
+ virtual void SetupProperties(const Importer* pImp);
+
+
+ //! Set the split limit - needed for unit testing
+ inline void SetLimit(unsigned int l)
+ {LIMIT = l;}
+
+ //! Get the split limit
+ inline unsigned int GetLimit() const
+ {return LIMIT;}
+
+public:
+
+ // -------------------------------------------------------------------
+ /** Executes the post processing step on the given imported data.
+ * At the moment a process is not supposed to fail.
+ * @param pScene The imported data to work at.
+ */
+ void Execute( aiScene* pScene);
+
+ // -------------------------------------------------------------------
+ //! Apply the algorithm to a given mesh
+ void SplitMesh (unsigned int a, aiMesh* pcMesh,
+ std::vector<std::pair<aiMesh*, unsigned int> >& avList);
+
+ // NOTE: Reuse SplitLargeMeshesProcess_Triangle::UpdateNode()
+
+public:
+ //! Triangle limit
+ unsigned int LIMIT;
+};
+
+} // end of namespace Assimp
+
+#endif // !!AI_SPLITLARGEMESHES_H_INC
diff --git a/thirdparty/assimp/code/StandardShapes.cpp b/thirdparty/assimp/code/StandardShapes.cpp
new file mode 100644
index 0000000000..2e5100130f
--- /dev/null
+++ b/thirdparty/assimp/code/StandardShapes.cpp
@@ -0,0 +1,507 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file StandardShapes.cpp
+ * @brief Implementation of the StandardShapes class
+ *
+ * The primitive geometry data comes from
+ * http://geometrictools.com/Documentation/PlatonicSolids.pdf.
+ */
+
+#include <assimp/StandardShapes.h>
+#include <assimp/StringComparison.h>
+#include <stddef.h>
+#include <assimp/Defines.h>
+#include <assimp/mesh.h>
+
+namespace Assimp {
+
+
+# define ADD_TRIANGLE(n0,n1,n2) \
+ positions.push_back(n0); \
+ positions.push_back(n1); \
+ positions.push_back(n2);
+
+# define ADD_PENTAGON(n0,n1,n2,n3,n4) \
+ if (polygons) \
+ { \
+ positions.push_back(n0); \
+ positions.push_back(n1); \
+ positions.push_back(n2); \
+ positions.push_back(n3); \
+ positions.push_back(n4); \
+ } \
+ else \
+ { \
+ ADD_TRIANGLE(n0, n1, n2) \
+ ADD_TRIANGLE(n0, n2, n3) \
+ ADD_TRIANGLE(n0, n3, n4) \
+ }
+
+# define ADD_QUAD(n0,n1,n2,n3) \
+ if (polygons) \
+ { \
+ positions.push_back(n0); \
+ positions.push_back(n1); \
+ positions.push_back(n2); \
+ positions.push_back(n3); \
+ } \
+ else \
+ { \
+ ADD_TRIANGLE(n0, n1, n2) \
+ ADD_TRIANGLE(n0, n2, n3) \
+ }
+
+
+// ------------------------------------------------------------------------------------------------
+// Fast subdivision for a mesh whose verts have a magnitude of 1
+void Subdivide(std::vector<aiVector3D>& positions)
+{
+ // assume this to be constant - (fixme: must be 1.0? I think so)
+ const ai_real fl1 = positions[0].Length();
+
+ unsigned int origSize = (unsigned int)positions.size();
+ for (unsigned int i = 0 ; i < origSize ; i+=3)
+ {
+ aiVector3D& tv0 = positions[i];
+ aiVector3D& tv1 = positions[i+1];
+ aiVector3D& tv2 = positions[i+2];
+
+ aiVector3D a = tv0, b = tv1, c = tv2;
+ aiVector3D v1 = aiVector3D(a.x+b.x, a.y+b.y, a.z+b.z).Normalize()*fl1;
+ aiVector3D v2 = aiVector3D(a.x+c.x, a.y+c.y, a.z+c.z).Normalize()*fl1;
+ aiVector3D v3 = aiVector3D(b.x+c.x, b.y+c.y, b.z+c.z).Normalize()*fl1;
+
+ tv0 = v1; tv1 = v3; tv2 = v2; // overwrite the original
+ ADD_TRIANGLE(v1, v2, a);
+ ADD_TRIANGLE(v2, v3, c);
+ ADD_TRIANGLE(v3, v1, b);
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Construct a mesh from given vertex positions
+aiMesh* StandardShapes::MakeMesh(const std::vector<aiVector3D>& positions,
+ unsigned int numIndices)
+{
+ if (positions.empty() || !numIndices) return NULL;
+
+ // Determine which kinds of primitives the mesh consists of
+ aiMesh* out = new aiMesh();
+ switch (numIndices) {
+ case 1:
+ out->mPrimitiveTypes = aiPrimitiveType_POINT;
+ break;
+ case 2:
+ out->mPrimitiveTypes = aiPrimitiveType_LINE;
+ break;
+ case 3:
+ out->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
+ break;
+ default:
+ out->mPrimitiveTypes = aiPrimitiveType_POLYGON;
+ break;
+ };
+
+ out->mNumFaces = (unsigned int)positions.size() / numIndices;
+ out->mFaces = new aiFace[out->mNumFaces];
+ for (unsigned int i = 0, a = 0; i < out->mNumFaces;++i) {
+ aiFace& f = out->mFaces[i];
+ f.mNumIndices = numIndices;
+ f.mIndices = new unsigned int[numIndices];
+ for (unsigned int j = 0; i < numIndices; ++i, ++a) {
+ f.mIndices[j] = a;
+ }
+ }
+ out->mNumVertices = (unsigned int)positions.size();
+ out->mVertices = new aiVector3D[out->mNumVertices];
+ ::memcpy(out->mVertices,&positions[0],out->mNumVertices*sizeof(aiVector3D));
+
+ return out;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Construct a mesh with a specific shape (callback)
+aiMesh* StandardShapes::MakeMesh ( unsigned int (*GenerateFunc)(
+ std::vector<aiVector3D>&))
+{
+ std::vector<aiVector3D> temp;
+ unsigned num = (*GenerateFunc)(temp);
+ return MakeMesh(temp,num);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Construct a mesh with a specific shape (callback)
+aiMesh* StandardShapes::MakeMesh ( unsigned int (*GenerateFunc)(
+ std::vector<aiVector3D>&, bool))
+{
+ std::vector<aiVector3D> temp;
+ unsigned num = (*GenerateFunc)(temp,true);
+ return MakeMesh(temp,num);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Construct a mesh with a specific shape (callback)
+aiMesh* StandardShapes::MakeMesh (unsigned int num, void (*GenerateFunc)(
+ unsigned int,std::vector<aiVector3D>&))
+{
+ std::vector<aiVector3D> temp;
+ (*GenerateFunc)(num,temp);
+ return MakeMesh(temp,3);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Build an incosahedron with points.magnitude == 1
+unsigned int StandardShapes::MakeIcosahedron(std::vector<aiVector3D>& positions)
+{
+ positions.reserve(positions.size()+60);
+
+ const ai_real t = ( ai_real( 1.0 )+ ai_real( 2.236067977 ) ) / ai_real( 2.0 );
+ const ai_real s = std::sqrt(ai_real(1.0) + t*t);
+
+ const aiVector3D v0 = aiVector3D(t,1.0, 0.0)/s;
+ const aiVector3D v1 = aiVector3D(-t,1.0, 0.0)/s;
+ const aiVector3D v2 = aiVector3D(t,-1.0, 0.0)/s;
+ const aiVector3D v3 = aiVector3D(-t,-1.0, 0.0)/s;
+ const aiVector3D v4 = aiVector3D(1.0, 0.0, t)/s;
+ const aiVector3D v5 = aiVector3D(1.0, 0.0,-t)/s;
+ const aiVector3D v6 = aiVector3D(-1.0, 0.0,t)/s;
+ const aiVector3D v7 = aiVector3D(-1.0, 0.0,-t)/s;
+ const aiVector3D v8 = aiVector3D(0.0, t, 1.0)/s;
+ const aiVector3D v9 = aiVector3D(0.0,-t, 1.0)/s;
+ const aiVector3D v10 = aiVector3D(0.0, t,-1.0)/s;
+ const aiVector3D v11 = aiVector3D(0.0,-t,-1.0)/s;
+
+ ADD_TRIANGLE(v0,v8,v4);
+ ADD_TRIANGLE(v0,v5,v10);
+ ADD_TRIANGLE(v2,v4,v9);
+ ADD_TRIANGLE(v2,v11,v5);
+
+ ADD_TRIANGLE(v1,v6,v8);
+ ADD_TRIANGLE(v1,v10,v7);
+ ADD_TRIANGLE(v3,v9,v6);
+ ADD_TRIANGLE(v3,v7,v11);
+
+ ADD_TRIANGLE(v0,v10,v8);
+ ADD_TRIANGLE(v1,v8,v10);
+ ADD_TRIANGLE(v2,v9,v11);
+ ADD_TRIANGLE(v3,v11,v9);
+
+ ADD_TRIANGLE(v4,v2,v0);
+ ADD_TRIANGLE(v5,v0,v2);
+ ADD_TRIANGLE(v6,v1,v3);
+ ADD_TRIANGLE(v7,v3,v1);
+
+ ADD_TRIANGLE(v8,v6,v4);
+ ADD_TRIANGLE(v9,v4,v6);
+ ADD_TRIANGLE(v10,v5,v7);
+ ADD_TRIANGLE(v11,v7,v5);
+ return 3;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Build a dodecahedron with points.magnitude == 1
+unsigned int StandardShapes::MakeDodecahedron(std::vector<aiVector3D>& positions,
+ bool polygons /*= false*/)
+{
+ positions.reserve(positions.size()+108);
+
+ const ai_real a = ai_real( 1.0 ) / ai_real(1.7320508);
+ const ai_real b = std::sqrt(( ai_real( 3.0 )- ai_real( 2.23606797))/ ai_real( 6.0) );
+ const ai_real c = std::sqrt(( ai_real( 3.0 )+ ai_real( 2.23606797f))/ ai_real( 6.0) );
+
+ const aiVector3D v0 = aiVector3D(a,a,a);
+ const aiVector3D v1 = aiVector3D(a,a,-a);
+ const aiVector3D v2 = aiVector3D(a,-a,a);
+ const aiVector3D v3 = aiVector3D(a,-a,-a);
+ const aiVector3D v4 = aiVector3D(-a,a,a);
+ const aiVector3D v5 = aiVector3D(-a,a,-a);
+ const aiVector3D v6 = aiVector3D(-a,-a,a);
+ const aiVector3D v7 = aiVector3D(-a,-a,-a);
+ const aiVector3D v8 = aiVector3D(b,c,0.0);
+ const aiVector3D v9 = aiVector3D(-b,c,0.0);
+ const aiVector3D v10 = aiVector3D(b,-c,0.0);
+ const aiVector3D v11 = aiVector3D(-b,-c,0.0);
+ const aiVector3D v12 = aiVector3D(c, 0.0, b);
+ const aiVector3D v13 = aiVector3D(c, 0.0, -b);
+ const aiVector3D v14 = aiVector3D(-c, 0.0, b);
+ const aiVector3D v15 = aiVector3D(-c, 0.0, -b);
+ const aiVector3D v16 = aiVector3D(0.0, b, c);
+ const aiVector3D v17 = aiVector3D(0.0, -b, c);
+ const aiVector3D v18 = aiVector3D(0.0, b, -c);
+ const aiVector3D v19 = aiVector3D(0.0, -b, -c);
+
+ ADD_PENTAGON(v0, v8, v9, v4, v16);
+ ADD_PENTAGON(v0, v12, v13, v1, v8);
+ ADD_PENTAGON(v0, v16, v17, v2, v12);
+ ADD_PENTAGON(v8, v1, v18, v5, v9);
+ ADD_PENTAGON(v12, v2, v10, v3, v13);
+ ADD_PENTAGON(v16, v4, v14, v6, v17);
+ ADD_PENTAGON(v9, v5, v15, v14, v4);
+
+ ADD_PENTAGON(v6, v11, v10, v2, v17);
+ ADD_PENTAGON(v3, v19, v18, v1, v13);
+ ADD_PENTAGON(v7, v15, v5, v18, v19);
+ ADD_PENTAGON(v7, v11, v6, v14, v15);
+ ADD_PENTAGON(v7, v19, v3, v10, v11);
+ return (polygons ? 5 : 3);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Build an octahedron with points.magnitude == 1
+unsigned int StandardShapes::MakeOctahedron(std::vector<aiVector3D>& positions)
+{
+ positions.reserve(positions.size()+24);
+
+ const aiVector3D v0 = aiVector3D(1.0, 0.0, 0.0) ;
+ const aiVector3D v1 = aiVector3D(-1.0, 0.0, 0.0);
+ const aiVector3D v2 = aiVector3D(0.0, 1.0, 0.0);
+ const aiVector3D v3 = aiVector3D(0.0, -1.0, 0.0);
+ const aiVector3D v4 = aiVector3D(0.0, 0.0, 1.0);
+ const aiVector3D v5 = aiVector3D(0.0, 0.0, -1.0);
+
+ ADD_TRIANGLE(v4,v0,v2);
+ ADD_TRIANGLE(v4,v2,v1);
+ ADD_TRIANGLE(v4,v1,v3);
+ ADD_TRIANGLE(v4,v3,v0);
+
+ ADD_TRIANGLE(v5,v2,v0);
+ ADD_TRIANGLE(v5,v1,v2);
+ ADD_TRIANGLE(v5,v3,v1);
+ ADD_TRIANGLE(v5,v0,v3);
+ return 3;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Build a tetrahedron with points.magnitude == 1
+unsigned int StandardShapes::MakeTetrahedron(std::vector<aiVector3D>& positions)
+{
+ positions.reserve(positions.size()+9);
+
+ const ai_real invThree = ai_real( 1.0 ) / ai_real( 3.0 );
+ const ai_real a = ai_real( 1.41421 ) * invThree;
+ const ai_real b = ai_real( 2.4494 ) * invThree;
+
+ const aiVector3D v0 = aiVector3D(0.0,0.0,1.0);
+ const aiVector3D v1 = aiVector3D(2*a,0,-invThree );
+ const aiVector3D v2 = aiVector3D(-a,b,-invThree );
+ const aiVector3D v3 = aiVector3D(-a,-b,-invThree );
+
+ ADD_TRIANGLE(v0,v1,v2);
+ ADD_TRIANGLE(v0,v2,v3);
+ ADD_TRIANGLE(v0,v3,v1);
+ ADD_TRIANGLE(v1,v3,v2);
+ return 3;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Build a hexahedron with points.magnitude == 1
+unsigned int StandardShapes::MakeHexahedron(std::vector<aiVector3D>& positions,
+ bool polygons /*= false*/)
+{
+ positions.reserve(positions.size()+36);
+ const ai_real length = ai_real(1.0)/ai_real(1.73205080);
+
+ const aiVector3D v0 = aiVector3D(-1.0,-1.0,-1.0)*length;
+ const aiVector3D v1 = aiVector3D(1.0,-1.0,-1.0)*length;
+ const aiVector3D v2 = aiVector3D(1.0,1.0,-1.0)*length;
+ const aiVector3D v3 = aiVector3D(-1.0,1.0,-1.0)*length;
+ const aiVector3D v4 = aiVector3D(-1.0,-1.0,1.0)*length;
+ const aiVector3D v5 = aiVector3D(1.0,-1.0,1.0)*length;
+ const aiVector3D v6 = aiVector3D(1.0,1.0,1.0)*length;
+ const aiVector3D v7 = aiVector3D(-1.0,1.0,1.0)*length;
+
+ ADD_QUAD(v0,v3,v2,v1);
+ ADD_QUAD(v0,v1,v5,v4);
+ ADD_QUAD(v0,v4,v7,v3);
+ ADD_QUAD(v6,v5,v1,v2);
+ ADD_QUAD(v6,v2,v3,v7);
+ ADD_QUAD(v6,v7,v4,v5);
+ return (polygons ? 4 : 3);
+}
+
+// Cleanup ...
+#undef ADD_TRIANGLE
+#undef ADD_QUAD
+#undef ADD_PENTAGON
+
+// ------------------------------------------------------------------------------------------------
+// Create a subdivision sphere
+void StandardShapes::MakeSphere(unsigned int tess,
+ std::vector<aiVector3D>& positions)
+{
+ // Reserve enough storage. Every subdivision
+ // splits each triangle in 4, the icosahedron consists of 60 verts
+ positions.reserve(positions.size()+60 * integer_pow(4, tess));
+
+ // Construct an icosahedron to start with
+ MakeIcosahedron(positions);
+
+ // ... and subdivide it until the requested output
+ // tessellation is reached
+ for (unsigned int i = 0; i<tess;++i)
+ Subdivide(positions);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Build a cone
+void StandardShapes::MakeCone(ai_real height,ai_real radius1,
+ ai_real radius2,unsigned int tess,
+ std::vector<aiVector3D>& positions,bool bOpen /*= false */)
+{
+ // Sorry, a cone with less than 3 segments makes ABSOLUTELY NO SENSE
+ if (tess < 3 || !height)
+ return;
+
+ size_t old = positions.size();
+
+ // No negative radii
+ radius1 = std::fabs(radius1);
+ radius2 = std::fabs(radius2);
+
+ ai_real halfHeight = height / ai_real(2.0);
+
+ // radius1 is always the smaller one
+ if (radius2 > radius1)
+ {
+ std::swap(radius2,radius1);
+ halfHeight = -halfHeight;
+ }
+ else old = SIZE_MAX;
+
+ // Use a large epsilon to check whether the cone is pointy
+ if (radius1 < (radius2-radius1)*10e-3)radius1 = 0.0;
+
+ // We will need 3*2 verts per segment + 3*2 verts per segment
+ // if the cone is closed
+ const unsigned int mem = tess*6 + (!bOpen ? tess*3 * (radius1 ? 2 : 1) : 0);
+ positions.reserve(positions.size () + mem);
+
+ // Now construct all segments
+ const ai_real angle_delta = (ai_real)AI_MATH_TWO_PI / tess;
+ const ai_real angle_max = (ai_real)AI_MATH_TWO_PI;
+
+ ai_real s = 1.0; // std::cos(angle == 0);
+ ai_real t = 0.0; // std::sin(angle == 0);
+
+ for (ai_real angle = 0.0; angle < angle_max; )
+ {
+ const aiVector3D v1 = aiVector3D (s * radius1, -halfHeight, t * radius1 );
+ const aiVector3D v2 = aiVector3D (s * radius2, halfHeight, t * radius2 );
+
+ const ai_real next = angle + angle_delta;
+ ai_real s2 = std::cos(next);
+ ai_real t2 = std::sin(next);
+
+ const aiVector3D v3 = aiVector3D (s2 * radius2, halfHeight, t2 * radius2 );
+ const aiVector3D v4 = aiVector3D (s2 * radius1, -halfHeight, t2 * radius1 );
+
+ positions.push_back(v1);
+ positions.push_back(v2);
+ positions.push_back(v3);
+ positions.push_back(v4);
+ positions.push_back(v1);
+ positions.push_back(v3);
+
+ if (!bOpen)
+ {
+ // generate the end 'cap'
+ positions.push_back(aiVector3D(s * radius2, halfHeight, t * radius2 ));
+ positions.push_back(aiVector3D(s2 * radius2, halfHeight, t2 * radius2 ));
+ positions.push_back(aiVector3D(0.0, halfHeight, 0.0));
+
+
+ if (radius1)
+ {
+ // generate the other end 'cap'
+ positions.push_back(aiVector3D(s * radius1, -halfHeight, t * radius1 ));
+ positions.push_back(aiVector3D(s2 * radius1, -halfHeight, t2 * radius1 ));
+ positions.push_back(aiVector3D(0.0, -halfHeight, 0.0));
+
+ }
+ }
+ s = s2;
+ t = t2;
+ angle = next;
+ }
+
+ // Need to flip face order?
+ if ( SIZE_MAX != old ) {
+ for (size_t p = old; p < positions.size();p += 3) {
+ std::swap(positions[p],positions[p+1]);
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Build a circle
+void StandardShapes::MakeCircle(ai_real radius, unsigned int tess,
+ std::vector<aiVector3D>& positions)
+{
+ // Sorry, a circle with less than 3 segments makes ABSOLUTELY NO SENSE
+ if (tess < 3 || !radius)
+ return;
+
+ radius = std::fabs(radius);
+
+ // We will need 3 vertices per segment
+ positions.reserve(positions.size()+tess*3);
+
+ const ai_real angle_delta = (ai_real)AI_MATH_TWO_PI / tess;
+ const ai_real angle_max = (ai_real)AI_MATH_TWO_PI;
+
+ ai_real s = 1.0; // std::cos(angle == 0);
+ ai_real t = 0.0; // std::sin(angle == 0);
+
+ for (ai_real angle = 0.0; angle < angle_max; )
+ {
+ positions.push_back(aiVector3D(s * radius,0.0,t * radius));
+ angle += angle_delta;
+ s = std::cos(angle);
+ t = std::sin(angle);
+ positions.push_back(aiVector3D(s * radius,0.0,t * radius));
+
+ positions.push_back(aiVector3D(0.0,0.0,0.0));
+ }
+}
+
+} // ! Assimp
diff --git a/thirdparty/assimp/code/StdOStreamLogStream.h b/thirdparty/assimp/code/StdOStreamLogStream.h
new file mode 100644
index 0000000000..893e261a2b
--- /dev/null
+++ b/thirdparty/assimp/code/StdOStreamLogStream.h
@@ -0,0 +1,101 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file StdOStreamLogStream.h
+* @brief Implementation of StdOStreamLogStream
+*/
+
+#ifndef AI_STROSTREAMLOGSTREAM_H_INC
+#define AI_STROSTREAMLOGSTREAM_H_INC
+
+#include <assimp/LogStream.hpp>
+#include <ostream>
+
+namespace Assimp {
+
+// ---------------------------------------------------------------------------
+/** @class StdOStreamLogStream
+ * @brief Logs into a std::ostream
+ */
+class StdOStreamLogStream : public LogStream {
+public:
+ /** @brief Construction from an existing std::ostream
+ * @param _ostream Output stream to be used
+ */
+ explicit StdOStreamLogStream(std::ostream& _ostream);
+
+ /** @brief Destructor */
+ ~StdOStreamLogStream();
+
+ /** @brief Writer */
+ void write(const char* message);
+
+private:
+ std::ostream& mOstream;
+};
+
+// ---------------------------------------------------------------------------
+// Default constructor
+inline StdOStreamLogStream::StdOStreamLogStream(std::ostream& _ostream)
+: mOstream (_ostream){
+ // empty
+}
+
+// ---------------------------------------------------------------------------
+// Default constructor
+inline StdOStreamLogStream::~StdOStreamLogStream() {
+ // empty
+}
+
+// ---------------------------------------------------------------------------
+// Write method
+inline void StdOStreamLogStream::write(const char* message) {
+ mOstream << message;
+ mOstream.flush();
+}
+
+// ---------------------------------------------------------------------------
+
+} // Namespace Assimp
+
+#endif // guard
diff --git a/thirdparty/assimp/code/Subdivision.cpp b/thirdparty/assimp/code/Subdivision.cpp
new file mode 100644
index 0000000000..19db223a55
--- /dev/null
+++ b/thirdparty/assimp/code/Subdivision.cpp
@@ -0,0 +1,588 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+#include <assimp/Subdivision.h>
+#include <assimp/SceneCombiner.h>
+#include <assimp/SpatialSort.h>
+#include "ProcessHelper.h"
+#include <assimp/Vertex.h>
+#include <assimp/ai_assert.h>
+#include <stdio.h>
+
+using namespace Assimp;
+void mydummy() {}
+
+// ------------------------------------------------------------------------------------------------
+/** Subdivider stub class to implement the Catmull-Clarke subdivision algorithm. The
+ * implementation is basing on recursive refinement. Directly evaluating the result is also
+ * possible and much quicker, but it depends on lengthy matrix lookup tables. */
+// ------------------------------------------------------------------------------------------------
+class CatmullClarkSubdivider : public Subdivider
+{
+public:
+ void Subdivide (aiMesh* mesh, aiMesh*& out, unsigned int num, bool discard_input);
+ void Subdivide (aiMesh** smesh, size_t nmesh,
+ aiMesh** out, unsigned int num, bool discard_input);
+
+ // ---------------------------------------------------------------------------
+ /** Intermediate description of an edge between two corners of a polygon*/
+ // ---------------------------------------------------------------------------
+ struct Edge
+ {
+ Edge()
+ : ref(0)
+ {}
+ Vertex edge_point, midpoint;
+ unsigned int ref;
+ };
+
+ typedef std::vector<unsigned int> UIntVector;
+ typedef std::map<uint64_t,Edge> EdgeMap;
+
+ // ---------------------------------------------------------------------------
+ // Hashing function to derive an index into an #EdgeMap from two given
+ // 'unsigned int' vertex coordinates (!!distinct coordinates - same
+ // vertex position == same index!!).
+ // NOTE - this leads to rare hash collisions if a) sizeof(unsigned int)>4
+ // and (id[0]>2^32-1 or id[0]>2^32-1).
+ // MAKE_EDGE_HASH() uses temporaries, so INIT_EDGE_HASH() needs to be put
+ // at the head of every function which is about to use MAKE_EDGE_HASH().
+ // Reason is that the hash is that hash construction needs to hold the
+ // invariant id0<id1 to identify an edge - else two hashes would refer
+ // to the same edge.
+ // ---------------------------------------------------------------------------
+#define MAKE_EDGE_HASH(id0,id1) (eh_tmp0__=id0,eh_tmp1__=id1,\
+ (eh_tmp0__<eh_tmp1__?std::swap(eh_tmp0__,eh_tmp1__):mydummy()),(uint64_t)eh_tmp0__^((uint64_t)eh_tmp1__<<32u))
+
+
+#define INIT_EDGE_HASH_TEMPORARIES()\
+ unsigned int eh_tmp0__, eh_tmp1__;
+
+private:
+ void InternSubdivide (const aiMesh* const * smesh,
+ size_t nmesh,aiMesh** out, unsigned int num);
+};
+
+
+// ------------------------------------------------------------------------------------------------
+// Construct a subdivider of a specific type
+Subdivider* Subdivider::Create (Algorithm algo)
+{
+ switch (algo)
+ {
+ case CATMULL_CLARKE:
+ return new CatmullClarkSubdivider();
+ };
+
+ ai_assert(false);
+ return NULL; // shouldn't happen
+}
+
+// ------------------------------------------------------------------------------------------------
+// Call the Catmull Clark subdivision algorithm for one mesh
+void CatmullClarkSubdivider::Subdivide (
+ aiMesh* mesh,
+ aiMesh*& out,
+ unsigned int num,
+ bool discard_input
+ )
+{
+ ai_assert(mesh != out);
+
+ Subdivide(&mesh,1,&out,num,discard_input);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Call the Catmull Clark subdivision algorithm for multiple meshes
+void CatmullClarkSubdivider::Subdivide (
+ aiMesh** smesh,
+ size_t nmesh,
+ aiMesh** out,
+ unsigned int num,
+ bool discard_input
+ )
+{
+ ai_assert( NULL != smesh );
+ ai_assert( NULL != out );
+
+ // course, both regions may not overlap
+ ai_assert(smesh<out || smesh+nmesh>out+nmesh);
+ if (!num) {
+ // No subdivision at all. Need to copy all the meshes .. argh.
+ if (discard_input) {
+ for (size_t s = 0; s < nmesh; ++s) {
+ out[s] = smesh[s];
+ smesh[s] = NULL;
+ }
+ }
+ else {
+ for (size_t s = 0; s < nmesh; ++s) {
+ SceneCombiner::Copy(out+s,smesh[s]);
+ }
+ }
+ return;
+ }
+
+ std::vector<aiMesh*> inmeshes;
+ std::vector<aiMesh*> outmeshes;
+ std::vector<unsigned int> maptbl;
+
+ inmeshes.reserve(nmesh);
+ outmeshes.reserve(nmesh);
+ maptbl.reserve(nmesh);
+
+ // Remove pure line and point meshes from the working set to reduce the
+ // number of edge cases the subdivider is forced to deal with. Line and
+ // point meshes are simply passed through.
+ for (size_t s = 0; s < nmesh; ++s) {
+ aiMesh* i = smesh[s];
+ // FIX - mPrimitiveTypes might not yet be initialized
+ if (i->mPrimitiveTypes && (i->mPrimitiveTypes & (aiPrimitiveType_LINE|aiPrimitiveType_POINT))==i->mPrimitiveTypes) {
+ ASSIMP_LOG_DEBUG("Catmull-Clark Subdivider: Skipping pure line/point mesh");
+
+ if (discard_input) {
+ out[s] = i;
+ smesh[s] = NULL;
+ }
+ else {
+ SceneCombiner::Copy(out+s,i);
+ }
+ continue;
+ }
+
+ outmeshes.push_back(NULL);inmeshes.push_back(i);
+ maptbl.push_back(static_cast<unsigned int>(s));
+ }
+
+ // Do the actual subdivision on the preallocated storage. InternSubdivide
+ // *always* assumes that enough storage is available, it does not bother
+ // checking any ranges.
+ ai_assert(inmeshes.size()==outmeshes.size()&&inmeshes.size()==maptbl.size());
+ if (inmeshes.empty()) {
+ ASSIMP_LOG_WARN("Catmull-Clark Subdivider: Pure point/line scene, I can't do anything");
+ return;
+ }
+ InternSubdivide(&inmeshes.front(),inmeshes.size(),&outmeshes.front(),num);
+ for (unsigned int i = 0; i < maptbl.size(); ++i) {
+ ai_assert(nullptr != outmeshes[i]);
+ out[maptbl[i]] = outmeshes[i];
+ }
+
+ if (discard_input) {
+ for (size_t s = 0; s < nmesh; ++s) {
+ delete smesh[s];
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Note - this is an implementation of the standard (recursive) Cm-Cl algorithm without further
+// optimizations (except we're using some nice LUTs). A description of the algorithm can be found
+// here: http://en.wikipedia.org/wiki/Catmull-Clark_subdivision_surface
+//
+// The code is mostly O(n), however parts are O(nlogn) which is therefore the algorithm's
+// expected total runtime complexity. The implementation is able to work in-place on the same
+// mesh arrays. Calling #InternSubdivide() directly is not encouraged. The code can operate
+// in-place unless 'smesh' and 'out' are equal (no strange overlaps or reorderings).
+// Previous data is replaced/deleted then.
+// ------------------------------------------------------------------------------------------------
+void CatmullClarkSubdivider::InternSubdivide (
+ const aiMesh* const * smesh,
+ size_t nmesh,
+ aiMesh** out,
+ unsigned int num
+ )
+{
+ ai_assert(NULL != smesh && NULL != out);
+ INIT_EDGE_HASH_TEMPORARIES();
+
+ // no subdivision requested or end of recursive refinement
+ if (!num) {
+ return;
+ }
+
+ UIntVector maptbl;
+ SpatialSort spatial;
+
+ // ---------------------------------------------------------------------
+ // 0. Offset table to index all meshes continuously, generate a spatially
+ // sorted representation of all vertices in all meshes.
+ // ---------------------------------------------------------------------
+ typedef std::pair<unsigned int,unsigned int> IntPair;
+ std::vector<IntPair> moffsets(nmesh);
+ unsigned int totfaces = 0, totvert = 0;
+ for (size_t t = 0; t < nmesh; ++t) {
+ const aiMesh* mesh = smesh[t];
+
+ spatial.Append(mesh->mVertices,mesh->mNumVertices,sizeof(aiVector3D),false);
+ moffsets[t] = IntPair(totfaces,totvert);
+
+ totfaces += mesh->mNumFaces;
+ totvert += mesh->mNumVertices;
+ }
+
+ spatial.Finalize();
+ const unsigned int num_unique = spatial.GenerateMappingTable(maptbl,ComputePositionEpsilon(smesh,nmesh));
+
+
+#define FLATTEN_VERTEX_IDX(mesh_idx, vert_idx) (moffsets[mesh_idx].second+vert_idx)
+#define FLATTEN_FACE_IDX(mesh_idx, face_idx) (moffsets[mesh_idx].first+face_idx)
+
+ // ---------------------------------------------------------------------
+ // 1. Compute the centroid point for all faces
+ // ---------------------------------------------------------------------
+ std::vector<Vertex> centroids(totfaces);
+ unsigned int nfacesout = 0;
+ for (size_t t = 0, n = 0; t < nmesh; ++t) {
+ const aiMesh* mesh = smesh[t];
+ for (unsigned int i = 0; i < mesh->mNumFaces;++i,++n)
+ {
+ const aiFace& face = mesh->mFaces[i];
+ Vertex& c = centroids[n];
+
+ for (unsigned int a = 0; a < face.mNumIndices;++a) {
+ c += Vertex(mesh,face.mIndices[a]);
+ }
+
+ c /= static_cast<float>(face.mNumIndices);
+ nfacesout += face.mNumIndices;
+ }
+ }
+
+ {
+ // we want edges to go away before the recursive calls so begin a new scope
+ EdgeMap edges;
+
+ // ---------------------------------------------------------------------
+ // 2. Set each edge point to be the average of all neighbouring
+ // face points and original points. Every edge exists twice
+ // if there is a neighboring face.
+ // ---------------------------------------------------------------------
+ for (size_t t = 0; t < nmesh; ++t) {
+ const aiMesh* mesh = smesh[t];
+
+ for (unsigned int i = 0; i < mesh->mNumFaces;++i) {
+ const aiFace& face = mesh->mFaces[i];
+
+ for (unsigned int p =0; p< face.mNumIndices; ++p) {
+ const unsigned int id[] = {
+ face.mIndices[p],
+ face.mIndices[p==face.mNumIndices-1?0:p+1]
+ };
+ const unsigned int mp[] = {
+ maptbl[FLATTEN_VERTEX_IDX(t,id[0])],
+ maptbl[FLATTEN_VERTEX_IDX(t,id[1])]
+ };
+
+ Edge& e = edges[MAKE_EDGE_HASH(mp[0],mp[1])];
+ e.ref++;
+ if (e.ref<=2) {
+ if (e.ref==1) { // original points (end points) - add only once
+ e.edge_point = e.midpoint = Vertex(mesh,id[0])+Vertex(mesh,id[1]);
+ e.midpoint *= 0.5f;
+ }
+ e.edge_point += centroids[FLATTEN_FACE_IDX(t,i)];
+ }
+ }
+ }
+ }
+
+ // ---------------------------------------------------------------------
+ // 3. Normalize edge points
+ // ---------------------------------------------------------------------
+ {unsigned int bad_cnt = 0;
+ for (EdgeMap::iterator it = edges.begin(); it != edges.end(); ++it) {
+ if ((*it).second.ref < 2) {
+ ai_assert((*it).second.ref);
+ ++bad_cnt;
+ }
+ (*it).second.edge_point *= 1.f/((*it).second.ref+2.f);
+ }
+
+ if (bad_cnt) {
+ // Report the number of bad edges. bad edges are referenced by less than two
+ // faces in the mesh. They occur at outer model boundaries in non-closed
+ // shapes.
+ ASSIMP_LOG_DEBUG_F("Catmull-Clark Subdivider: got ", bad_cnt, " bad edges touching only one face (totally ",
+ static_cast<unsigned int>(edges.size()), " edges). ");
+ }}
+
+ // ---------------------------------------------------------------------
+ // 4. Compute a vertex-face adjacency table. We can't reuse the code
+ // from VertexTriangleAdjacency because we need the table for multiple
+ // meshes and out vertex indices need to be mapped to distinct values
+ // first.
+ // ---------------------------------------------------------------------
+ UIntVector faceadjac(nfacesout), cntadjfac(maptbl.size(),0), ofsadjvec(maptbl.size()+1,0); {
+ for (size_t t = 0; t < nmesh; ++t) {
+ const aiMesh* const minp = smesh[t];
+ for (unsigned int i = 0; i < minp->mNumFaces; ++i) {
+
+ const aiFace& f = minp->mFaces[i];
+ for (unsigned int n = 0; n < f.mNumIndices; ++n) {
+ ++cntadjfac[maptbl[FLATTEN_VERTEX_IDX(t,f.mIndices[n])]];
+ }
+ }
+ }
+ unsigned int cur = 0;
+ for (size_t i = 0; i < cntadjfac.size(); ++i) {
+ ofsadjvec[i+1] = cur;
+ cur += cntadjfac[i];
+ }
+ for (size_t t = 0; t < nmesh; ++t) {
+ const aiMesh* const minp = smesh[t];
+ for (unsigned int i = 0; i < minp->mNumFaces; ++i) {
+
+ const aiFace& f = minp->mFaces[i];
+ for (unsigned int n = 0; n < f.mNumIndices; ++n) {
+ faceadjac[ofsadjvec[1+maptbl[FLATTEN_VERTEX_IDX(t,f.mIndices[n])]]++] = FLATTEN_FACE_IDX(t,i);
+ }
+ }
+ }
+
+ // check the other way round for consistency
+#ifdef ASSIMP_BUILD_DEBUG
+
+ for (size_t t = 0; t < ofsadjvec.size()-1; ++t) {
+ for (unsigned int m = 0; m < cntadjfac[t]; ++m) {
+ const unsigned int fidx = faceadjac[ofsadjvec[t]+m];
+ ai_assert(fidx < totfaces);
+ for (size_t n = 1; n < nmesh; ++n) {
+
+ if (moffsets[n].first > fidx) {
+ const aiMesh* msh = smesh[--n];
+ const aiFace& f = msh->mFaces[fidx-moffsets[n].first];
+
+ bool haveit = false;
+ for (unsigned int i = 0; i < f.mNumIndices; ++i) {
+ if (maptbl[FLATTEN_VERTEX_IDX(n,f.mIndices[i])]==(unsigned int)t) {
+ haveit = true;
+ break;
+ }
+ }
+ ai_assert(haveit);
+ if (!haveit) {
+ ASSIMP_LOG_DEBUG("Catmull-Clark Subdivider: Index not used");
+ }
+ break;
+ }
+ }
+ }
+ }
+
+#endif
+ }
+
+#define GET_ADJACENT_FACES_AND_CNT(vidx,fstartout,numout) \
+ fstartout = &faceadjac[ofsadjvec[vidx]], numout = cntadjfac[vidx]
+
+ typedef std::pair<bool,Vertex> TouchedOVertex;
+ std::vector<TouchedOVertex > new_points(num_unique,TouchedOVertex(false,Vertex()));
+ // ---------------------------------------------------------------------
+ // 5. Spawn a quad from each face point to the corresponding edge points
+ // the original points being the fourth quad points.
+ // ---------------------------------------------------------------------
+ for (size_t t = 0; t < nmesh; ++t) {
+ const aiMesh* const minp = smesh[t];
+ aiMesh* const mout = out[t] = new aiMesh();
+
+ for (unsigned int a = 0; a < minp->mNumFaces; ++a) {
+ mout->mNumFaces += minp->mFaces[a].mNumIndices;
+ }
+
+ // We need random access to the old face buffer, so reuse is not possible.
+ mout->mFaces = new aiFace[mout->mNumFaces];
+
+ mout->mNumVertices = mout->mNumFaces*4;
+ mout->mVertices = new aiVector3D[mout->mNumVertices];
+
+ // quads only, keep material index
+ mout->mPrimitiveTypes = aiPrimitiveType_POLYGON;
+ mout->mMaterialIndex = minp->mMaterialIndex;
+
+ if (minp->HasNormals()) {
+ mout->mNormals = new aiVector3D[mout->mNumVertices];
+ }
+
+ if (minp->HasTangentsAndBitangents()) {
+ mout->mTangents = new aiVector3D[mout->mNumVertices];
+ mout->mBitangents = new aiVector3D[mout->mNumVertices];
+ }
+
+ for(unsigned int i = 0; minp->HasTextureCoords(i); ++i) {
+ mout->mTextureCoords[i] = new aiVector3D[mout->mNumVertices];
+ mout->mNumUVComponents[i] = minp->mNumUVComponents[i];
+ }
+
+ for(unsigned int i = 0; minp->HasVertexColors(i); ++i) {
+ mout->mColors[i] = new aiColor4D[mout->mNumVertices];
+ }
+
+ mout->mNumVertices = mout->mNumFaces<<2u;
+ for (unsigned int i = 0, v = 0, n = 0; i < minp->mNumFaces;++i) {
+
+ const aiFace& face = minp->mFaces[i];
+ for (unsigned int a = 0; a < face.mNumIndices;++a) {
+
+ // Get a clean new face.
+ aiFace& faceOut = mout->mFaces[n++];
+ faceOut.mIndices = new unsigned int [faceOut.mNumIndices = 4];
+
+ // Spawn a new quadrilateral (ccw winding) for this original point between:
+ // a) face centroid
+ centroids[FLATTEN_FACE_IDX(t,i)].SortBack(mout,faceOut.mIndices[0]=v++);
+
+ // b) adjacent edge on the left, seen from the centroid
+ const Edge& e0 = edges[MAKE_EDGE_HASH(maptbl[FLATTEN_VERTEX_IDX(t,face.mIndices[a])],
+ maptbl[FLATTEN_VERTEX_IDX(t,face.mIndices[a==face.mNumIndices-1?0:a+1])
+ ])]; // fixme: replace with mod face.mNumIndices?
+
+ // c) adjacent edge on the right, seen from the centroid
+ const Edge& e1 = edges[MAKE_EDGE_HASH(maptbl[FLATTEN_VERTEX_IDX(t,face.mIndices[a])],
+ maptbl[FLATTEN_VERTEX_IDX(t,face.mIndices[!a?face.mNumIndices-1:a-1])
+ ])]; // fixme: replace with mod face.mNumIndices?
+
+ e0.edge_point.SortBack(mout,faceOut.mIndices[3]=v++);
+ e1.edge_point.SortBack(mout,faceOut.mIndices[1]=v++);
+
+ // d= original point P with distinct index i
+ // F := 0
+ // R := 0
+ // n := 0
+ // for each face f containing i
+ // F := F+ centroid of f
+ // R := R+ midpoint of edge of f from i to i+1
+ // n := n+1
+ //
+ // (F+2R+(n-3)P)/n
+ const unsigned int org = maptbl[FLATTEN_VERTEX_IDX(t,face.mIndices[a])];
+ TouchedOVertex& ov = new_points[org];
+
+ if (!ov.first) {
+ ov.first = true;
+
+ const unsigned int* adj; unsigned int cnt;
+ GET_ADJACENT_FACES_AND_CNT(org,adj,cnt);
+
+ if (cnt < 3) {
+ ov.second = Vertex(minp,face.mIndices[a]);
+ }
+ else {
+
+ Vertex F,R;
+ for (unsigned int o = 0; o < cnt; ++o) {
+ ai_assert(adj[o] < totfaces);
+ F += centroids[adj[o]];
+
+ // adj[0] is a global face index - search the face in the mesh list
+ const aiMesh* mp = NULL;
+ size_t nidx;
+
+ if (adj[o] < moffsets[0].first) {
+ mp = smesh[nidx=0];
+ }
+ else {
+ for (nidx = 1; nidx<= nmesh; ++nidx) {
+ if (nidx == nmesh ||moffsets[nidx].first > adj[o]) {
+ mp = smesh[--nidx];
+ break;
+ }
+ }
+ }
+
+ ai_assert(adj[o]-moffsets[nidx].first < mp->mNumFaces);
+ const aiFace& f = mp->mFaces[adj[o]-moffsets[nidx].first];
+ bool haveit = false;
+
+ // find our original point in the face
+ for (unsigned int m = 0; m < f.mNumIndices; ++m) {
+ if (maptbl[FLATTEN_VERTEX_IDX(nidx,f.mIndices[m])] == org) {
+
+ // add *both* edges. this way, we can be sure that we add
+ // *all* adjacent edges to R. In a closed shape, every
+ // edge is added twice - so we simply leave out the
+ // factor 2.f in the amove formula and get the right
+ // result.
+
+ const Edge& c0 = edges[MAKE_EDGE_HASH(org,maptbl[FLATTEN_VERTEX_IDX(
+ nidx,f.mIndices[!m?f.mNumIndices-1:m-1])])];
+ // fixme: replace with mod face.mNumIndices?
+
+ const Edge& c1 = edges[MAKE_EDGE_HASH(org,maptbl[FLATTEN_VERTEX_IDX(
+ nidx,f.mIndices[m==f.mNumIndices-1?0:m+1])])];
+ // fixme: replace with mod face.mNumIndices?
+ R += c0.midpoint+c1.midpoint;
+
+ haveit = true;
+ break;
+ }
+ }
+
+ // this invariant *must* hold if the vertex-to-face adjacency table is valid
+ ai_assert(haveit);
+ if ( !haveit ) {
+ ASSIMP_LOG_WARN( "OBJ: no name for material library specified." );
+ }
+ }
+
+ const float div = static_cast<float>(cnt), divsq = 1.f/(div*div);
+ ov.second = Vertex(minp,face.mIndices[a])*((div-3.f) / div) + R*divsq + F*divsq;
+ }
+ }
+ ov.second.SortBack(mout,faceOut.mIndices[2]=v++);
+ }
+ }
+ }
+ } // end of scope for edges, freeing its memory
+
+ // ---------------------------------------------------------------------
+ // 7. Apply the next subdivision step.
+ // ---------------------------------------------------------------------
+ if (num != 1) {
+ std::vector<aiMesh*> tmp(nmesh);
+ InternSubdivide (out,nmesh,&tmp.front(),num-1);
+ for (size_t i = 0; i < nmesh; ++i) {
+ delete out[i];
+ out[i] = tmp[i];
+ }
+ }
+}
diff --git a/thirdparty/assimp/code/TargetAnimation.cpp b/thirdparty/assimp/code/TargetAnimation.cpp
new file mode 100644
index 0000000000..b8062499ff
--- /dev/null
+++ b/thirdparty/assimp/code/TargetAnimation.cpp
@@ -0,0 +1,248 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+#include "TargetAnimation.h"
+#include <algorithm>
+#include <assimp/ai_assert.h>
+
+using namespace Assimp;
+
+
+// ------------------------------------------------------------------------------------------------
+KeyIterator::KeyIterator(const std::vector<aiVectorKey>* _objPos,
+ const std::vector<aiVectorKey>* _targetObjPos,
+ const aiVector3D* defaultObjectPos /*= NULL*/,
+ const aiVector3D* defaultTargetPos /*= NULL*/)
+
+ : reachedEnd (false)
+ , curTime (-1.)
+ , objPos (_objPos)
+ , targetObjPos (_targetObjPos)
+ , nextObjPos (0)
+ , nextTargetObjPos(0)
+{
+ // Generate default transformation tracks if necessary
+ if (!objPos || objPos->empty())
+ {
+ defaultObjPos.resize(1);
+ defaultObjPos.front().mTime = 10e10;
+
+ if (defaultObjectPos)
+ defaultObjPos.front().mValue = *defaultObjectPos;
+
+ objPos = & defaultObjPos;
+ }
+ if (!targetObjPos || targetObjPos->empty())
+ {
+ defaultTargetObjPos.resize(1);
+ defaultTargetObjPos.front().mTime = 10e10;
+
+ if (defaultTargetPos)
+ defaultTargetObjPos.front().mValue = *defaultTargetPos;
+
+ targetObjPos = & defaultTargetObjPos;
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+template <class T>
+inline T Interpolate(const T& one, const T& two, ai_real val)
+{
+ return one + (two-one)*val;
+}
+
+// ------------------------------------------------------------------------------------------------
+void KeyIterator::operator ++()
+{
+ // If we are already at the end of all keyframes, return
+ if (reachedEnd) {
+ return;
+ }
+
+ // Now search in all arrays for the time value closest
+ // to our current position on the time line
+ double d0,d1;
+
+ d0 = objPos->at ( std::min ( nextObjPos, static_cast<unsigned int>(objPos->size()-1)) ).mTime;
+ d1 = targetObjPos->at( std::min ( nextTargetObjPos, static_cast<unsigned int>(targetObjPos->size()-1)) ).mTime;
+
+ // Easiest case - all are identical. In this
+ // case we don't need to interpolate so we can
+ // return earlier
+ if ( d0 == d1 )
+ {
+ curTime = d0;
+ curPosition = objPos->at(nextObjPos).mValue;
+ curTargetPosition = targetObjPos->at(nextTargetObjPos).mValue;
+
+ // increment counters
+ if (objPos->size() != nextObjPos-1)
+ ++nextObjPos;
+
+ if (targetObjPos->size() != nextTargetObjPos-1)
+ ++nextTargetObjPos;
+ }
+
+ // An object position key is closest to us
+ else if (d0 < d1)
+ {
+ curTime = d0;
+
+ // interpolate the other
+ if (1 == targetObjPos->size() || !nextTargetObjPos) {
+ curTargetPosition = targetObjPos->at(0).mValue;
+ }
+ else
+ {
+ const aiVectorKey& last = targetObjPos->at(nextTargetObjPos);
+ const aiVectorKey& first = targetObjPos->at(nextTargetObjPos-1);
+
+ curTargetPosition = Interpolate(first.mValue, last.mValue, (ai_real) (
+ (curTime-first.mTime) / (last.mTime-first.mTime) ));
+ }
+
+ if (objPos->size() != nextObjPos-1)
+ ++nextObjPos;
+ }
+ // A target position key is closest to us
+ else
+ {
+ curTime = d1;
+
+ // interpolate the other
+ if (1 == objPos->size() || !nextObjPos) {
+ curPosition = objPos->at(0).mValue;
+ }
+ else
+ {
+ const aiVectorKey& last = objPos->at(nextObjPos);
+ const aiVectorKey& first = objPos->at(nextObjPos-1);
+
+ curPosition = Interpolate(first.mValue, last.mValue, (ai_real) (
+ (curTime-first.mTime) / (last.mTime-first.mTime)));
+ }
+
+ if (targetObjPos->size() != nextTargetObjPos-1)
+ ++nextTargetObjPos;
+ }
+
+ if (nextObjPos >= objPos->size()-1 &&
+ nextTargetObjPos >= targetObjPos->size()-1)
+ {
+ // We reached the very last keyframe
+ reachedEnd = true;
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+void TargetAnimationHelper::SetTargetAnimationChannel (
+ const std::vector<aiVectorKey>* _targetPositions)
+{
+ ai_assert(NULL != _targetPositions);
+ targetPositions = _targetPositions;
+}
+
+// ------------------------------------------------------------------------------------------------
+void TargetAnimationHelper::SetMainAnimationChannel (
+ const std::vector<aiVectorKey>* _objectPositions)
+{
+ ai_assert(NULL != _objectPositions);
+ objectPositions = _objectPositions;
+}
+
+// ------------------------------------------------------------------------------------------------
+void TargetAnimationHelper::SetFixedMainAnimationChannel(
+ const aiVector3D& fixed)
+{
+ objectPositions = NULL; // just to avoid confusion
+ fixedMain = fixed;
+}
+
+// ------------------------------------------------------------------------------------------------
+void TargetAnimationHelper::Process(std::vector<aiVectorKey>* distanceTrack)
+{
+ ai_assert(NULL != targetPositions && NULL != distanceTrack);
+
+ // TODO: in most cases we won't need the extra array
+ std::vector<aiVectorKey> real;
+
+ std::vector<aiVectorKey>* fill = (distanceTrack == objectPositions ? &real : distanceTrack);
+ fill->reserve(std::max( objectPositions->size(), targetPositions->size() ));
+
+ // Iterate through all object keys and interpolate their values if necessary.
+ // Then get the corresponding target position, compute the difference
+ // vector between object and target position. Then compute a rotation matrix
+ // that rotates the base vector of the object coordinate system at that time
+ // to match the diff vector.
+
+ KeyIterator iter(objectPositions,targetPositions,&fixedMain);
+ for (;!iter.Finished();++iter)
+ {
+ const aiVector3D& position = iter.GetCurPosition();
+ const aiVector3D& tposition = iter.GetCurTargetPosition();
+
+ // diff vector
+ aiVector3D diff = tposition - position;
+ ai_real f = diff.Length();
+
+ // output distance vector
+ if (f)
+ {
+ fill->push_back(aiVectorKey());
+ aiVectorKey& v = fill->back();
+ v.mTime = iter.GetCurTime();
+ v.mValue = diff;
+
+ diff /= f;
+ }
+ else
+ {
+ // FIXME: handle this
+ }
+
+ // diff is now the vector in which our camera is pointing
+ }
+
+ if (real.size()) {
+ *distanceTrack = real;
+ }
+}
diff --git a/thirdparty/assimp/code/TargetAnimation.h b/thirdparty/assimp/code/TargetAnimation.h
new file mode 100644
index 0000000000..91634ab5aa
--- /dev/null
+++ b/thirdparty/assimp/code/TargetAnimation.h
@@ -0,0 +1,183 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file Defines a helper class for the ASE and 3DS loaders to
+ help them compute camera and spot light animation channels */
+#ifndef AI_TARGET_ANIMATION_H_INC
+#define AI_TARGET_ANIMATION_H_INC
+
+#include <assimp/anim.h>
+#include <vector>
+
+namespace Assimp {
+
+
+
+// ---------------------------------------------------------------------------
+/** Helper class to iterate through all keys in an animation channel.
+ *
+ * Missing tracks are interpolated. This is a helper class for
+ * TargetAnimationHelper, but it can be freely used for other purposes.
+*/
+class KeyIterator
+{
+public:
+
+
+ // ------------------------------------------------------------------
+ /** Constructs a new key iterator
+ *
+ * @param _objPos Object position track. May be NULL.
+ * @param _targetObjPos Target object position track. May be NULL.
+ * @param defaultObjectPos Default object position to be used if
+ * no animated track is available. May be NULL.
+ * @param defaultTargetPos Default target position to be used if
+ * no animated track is available. May be NULL.
+ */
+ KeyIterator(const std::vector<aiVectorKey>* _objPos,
+ const std::vector<aiVectorKey>* _targetObjPos,
+ const aiVector3D* defaultObjectPos = NULL,
+ const aiVector3D* defaultTargetPos = NULL);
+
+ // ------------------------------------------------------------------
+ /** Returns true if all keys have been processed
+ */
+ bool Finished() const
+ {return reachedEnd;}
+
+ // ------------------------------------------------------------------
+ /** Increment the iterator
+ */
+ void operator++();
+ inline void operator++(int)
+ {return ++(*this);}
+
+
+
+ // ------------------------------------------------------------------
+ /** Getters to retrieve the current state of the iterator
+ */
+ inline const aiVector3D& GetCurPosition() const
+ {return curPosition;}
+
+ inline const aiVector3D& GetCurTargetPosition() const
+ {return curTargetPosition;}
+
+ inline double GetCurTime() const
+ {return curTime;}
+
+private:
+
+ //! Did we reach the end?
+ bool reachedEnd;
+
+ //! Represents the current position of the iterator
+ aiVector3D curPosition, curTargetPosition;
+
+ double curTime;
+
+ //! Input tracks and the next key to process
+ const std::vector<aiVectorKey>* objPos,*targetObjPos;
+
+ unsigned int nextObjPos, nextTargetObjPos;
+ std::vector<aiVectorKey> defaultObjPos,defaultTargetObjPos;
+};
+
+// ---------------------------------------------------------------------------
+/** Helper class for the 3DS and ASE loaders to compute camera and spot light
+ * animations.
+ *
+ * 3DS and ASE store the differently to Assimp - there is an animation
+ * channel for the camera/spot light itself and a separate position
+ * animation channels specifying the position of the camera/spot light
+ * look-at target */
+class TargetAnimationHelper
+{
+public:
+
+ TargetAnimationHelper()
+ : targetPositions (NULL)
+ , objectPositions (NULL)
+ {}
+
+
+ // ------------------------------------------------------------------
+ /** Sets the target animation channel
+ *
+ * This channel specifies the position of the camera/spot light
+ * target at a specific position.
+ *
+ * @param targetPositions Translation channel*/
+ void SetTargetAnimationChannel (const
+ std::vector<aiVectorKey>* targetPositions);
+
+
+ // ------------------------------------------------------------------
+ /** Sets the main animation channel
+ *
+ * @param objectPositions Translation channel */
+ void SetMainAnimationChannel ( const
+ std::vector<aiVectorKey>* objectPositions);
+
+ // ------------------------------------------------------------------
+ /** Sets the main animation channel to a fixed value
+ *
+ * @param fixed Fixed value for the main animation channel*/
+ void SetFixedMainAnimationChannel(const aiVector3D& fixed);
+
+
+ // ------------------------------------------------------------------
+ /** Computes final animation channels
+ * @param distanceTrack Receive camera translation keys ... != NULL. */
+ void Process( std::vector<aiVectorKey>* distanceTrack );
+
+
+private:
+
+ const std::vector<aiVectorKey>* targetPositions,*objectPositions;
+ aiVector3D fixedMain;
+};
+
+
+} // ! end namespace Assimp
+
+#endif // include guard
diff --git a/thirdparty/assimp/code/TextureTransform.cpp b/thirdparty/assimp/code/TextureTransform.cpp
new file mode 100644
index 0000000000..8ae2ba7218
--- /dev/null
+++ b/thirdparty/assimp/code/TextureTransform.cpp
@@ -0,0 +1,566 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file A helper class that processes texture transformations */
+
+
+
+#include <assimp/Importer.hpp>
+#include <assimp/postprocess.h>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/scene.h>
+
+#include "TextureTransform.h"
+#include <assimp/StringUtils.h>
+
+using namespace Assimp;
+
+// ------------------------------------------------------------------------------------------------
+// Constructor to be privately used by Importer
+TextureTransformStep::TextureTransformStep() :
+ configFlags()
+{
+ // nothing to do here
+}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor, private as well
+TextureTransformStep::~TextureTransformStep()
+{
+ // nothing to do here
+}
+
+// ------------------------------------------------------------------------------------------------
+// Returns whether the processing step is present in the given flag field.
+bool TextureTransformStep::IsActive( unsigned int pFlags) const
+{
+ return (pFlags & aiProcess_TransformUVCoords) != 0;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Setup properties
+void TextureTransformStep::SetupProperties(const Importer* pImp)
+{
+ configFlags = pImp->GetPropertyInteger(AI_CONFIG_PP_TUV_EVALUATE,AI_UVTRAFO_ALL);
+}
+
+// ------------------------------------------------------------------------------------------------
+void TextureTransformStep::PreProcessUVTransform(STransformVecInfo& info)
+{
+ /* This function tries to simplify the input UV transformation.
+ * That's very important as it allows us to reduce the number
+ * of output UV channels. The order in which the transformations
+ * are applied is - as always - scaling, rotation, translation.
+ */
+
+ char szTemp[512];
+ int rounded = 0;
+
+
+ /* Optimize the rotation angle. That's slightly difficult as
+ * we have an inprecise floating-point number (when comparing
+ * UV transformations we'll take that into account by using
+ * an epsilon of 5 degrees). If there is a rotation value, we can't
+ * perform any further optimizations.
+ */
+ if (info.mRotation)
+ {
+ float out = info.mRotation;
+ if ((rounded = static_cast<int>((info.mRotation / static_cast<float>(AI_MATH_TWO_PI)))))
+ {
+ out -= rounded * static_cast<float>(AI_MATH_PI);
+ ASSIMP_LOG_INFO_F("Texture coordinate rotation ", info.mRotation, " can be simplified to ", out);
+ }
+
+ // Next step - convert negative rotation angles to positives
+ if (out < 0.f)
+ out = (float)AI_MATH_TWO_PI * 2 + out;
+
+ info.mRotation = out;
+ return;
+ }
+
+
+ /* Optimize UV translation in the U direction. To determine whether
+ * or not we can optimize we need to look at the requested mapping
+ * type (e.g. if mirroring is active there IS a difference between
+ * offset 2 and 3)
+ */
+ if ((rounded = (int)info.mTranslation.x)) {
+ float out = 0.0f;
+ szTemp[0] = 0;
+ if (aiTextureMapMode_Wrap == info.mapU) {
+ // Wrap - simple take the fraction of the field
+ out = info.mTranslation.x-(float)rounded;
+ ai_snprintf(szTemp, 512, "[w] UV U offset %f can be simplified to %f", info.mTranslation.x, out);
+ }
+ else if (aiTextureMapMode_Mirror == info.mapU && 1 != rounded) {
+ // Mirror
+ if (rounded % 2)
+ rounded--;
+ out = info.mTranslation.x-(float)rounded;
+
+ ai_snprintf(szTemp,512,"[m/d] UV U offset %f can be simplified to %f",info.mTranslation.x,out);
+ }
+ else if (aiTextureMapMode_Clamp == info.mapU || aiTextureMapMode_Decal == info.mapU) {
+ // Clamp - translations beyond 1,1 are senseless
+ ai_snprintf(szTemp,512,"[c] UV U offset %f can be clamped to 1.0f",info.mTranslation.x);
+
+ out = 1.f;
+ }
+ if (szTemp[0]) {
+ ASSIMP_LOG_INFO(szTemp);
+ info.mTranslation.x = out;
+ }
+ }
+
+ /* Optimize UV translation in the V direction. To determine whether
+ * or not we can optimize we need to look at the requested mapping
+ * type (e.g. if mirroring is active there IS a difference between
+ * offset 2 and 3)
+ */
+ if ((rounded = (int)info.mTranslation.y)) {
+ float out = 0.0f;
+ szTemp[0] = 0;
+ if (aiTextureMapMode_Wrap == info.mapV) {
+ // Wrap - simple take the fraction of the field
+ out = info.mTranslation.y-(float)rounded;
+ ::ai_snprintf(szTemp,512,"[w] UV V offset %f can be simplified to %f",info.mTranslation.y,out);
+ }
+ else if (aiTextureMapMode_Mirror == info.mapV && 1 != rounded) {
+ // Mirror
+ if (rounded % 2)
+ rounded--;
+ out = info.mTranslation.x-(float)rounded;
+
+ ::ai_snprintf(szTemp,512,"[m/d] UV V offset %f can be simplified to %f",info.mTranslation.y,out);
+ }
+ else if (aiTextureMapMode_Clamp == info.mapV || aiTextureMapMode_Decal == info.mapV) {
+ // Clamp - translations beyond 1,1 are senseless
+ ::ai_snprintf(szTemp,512,"[c] UV V offset %f canbe clamped to 1.0f",info.mTranslation.y);
+
+ out = 1.f;
+ }
+ if (szTemp[0]) {
+ ASSIMP_LOG_INFO(szTemp);
+ info.mTranslation.y = out;
+ }
+ }
+ return;
+}
+
+// ------------------------------------------------------------------------------------------------
+void UpdateUVIndex(const std::list<TTUpdateInfo>& l, unsigned int n)
+{
+ // Don't set if == 0 && wasn't set before
+ for (std::list<TTUpdateInfo>::const_iterator it = l.begin();it != l.end(); ++it) {
+ const TTUpdateInfo& info = *it;
+
+ if (info.directShortcut)
+ *info.directShortcut = n;
+ else if (!n)
+ {
+ info.mat->AddProperty<int>((int*)&n,1,AI_MATKEY_UVWSRC(info.semantic,info.index));
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+inline const char* MappingModeToChar(aiTextureMapMode map)
+{
+ if (aiTextureMapMode_Wrap == map)
+ return "-w";
+
+ if (aiTextureMapMode_Mirror == map)
+ return "-m";
+
+ return "-c";
+}
+
+// ------------------------------------------------------------------------------------------------
+void TextureTransformStep::Execute( aiScene* pScene)
+{
+ ASSIMP_LOG_DEBUG("TransformUVCoordsProcess begin");
+
+
+ /* We build a per-mesh list of texture transformations we'll need
+ * to apply. To achieve this, we iterate through all materials,
+ * find all textures and get their transformations and UV indices.
+ * Then we search for all meshes using this material.
+ */
+ typedef std::list<STransformVecInfo> MeshTrafoList;
+ std::vector<MeshTrafoList> meshLists(pScene->mNumMeshes);
+
+ for (unsigned int i = 0; i < pScene->mNumMaterials;++i) {
+
+ aiMaterial* mat = pScene->mMaterials[i];
+ for (unsigned int a = 0; a < mat->mNumProperties;++a) {
+
+ aiMaterialProperty* prop = mat->mProperties[a];
+ if (!::strcmp( prop->mKey.data, "$tex.file")) {
+ STransformVecInfo info;
+
+ // Setup a shortcut structure to allow for a fast updating
+ // of the UV index later
+ TTUpdateInfo update;
+ update.mat = (aiMaterial*) mat;
+ update.semantic = prop->mSemantic;
+ update.index = prop->mIndex;
+
+ // Get textured properties and transform
+ for (unsigned int a2 = 0; a2 < mat->mNumProperties;++a2) {
+ aiMaterialProperty* prop2 = mat->mProperties[a2];
+ if (prop2->mSemantic != prop->mSemantic || prop2->mIndex != prop->mIndex) {
+ continue;
+ }
+
+ if ( !::strcmp( prop2->mKey.data, "$tex.uvwsrc")) {
+ info.uvIndex = *((int*)prop2->mData);
+
+ // Store a direct pointer for later use
+ update.directShortcut = (unsigned int*) prop2->mData;
+ }
+
+ else if ( !::strcmp( prop2->mKey.data, "$tex.mapmodeu")) {
+ info.mapU = *((aiTextureMapMode*)prop2->mData);
+ }
+ else if ( !::strcmp( prop2->mKey.data, "$tex.mapmodev")) {
+ info.mapV = *((aiTextureMapMode*)prop2->mData);
+ }
+ else if ( !::strcmp( prop2->mKey.data, "$tex.uvtrafo")) {
+ // ValidateDS should check this
+ ai_assert(prop2->mDataLength >= 20);
+ ::memcpy(&info.mTranslation.x,prop2->mData,sizeof(float)*5);
+
+ // Directly remove this property from the list
+ mat->mNumProperties--;
+ for (unsigned int a3 = a2; a3 < mat->mNumProperties;++a3) {
+ mat->mProperties[a3] = mat->mProperties[a3+1];
+ }
+
+ delete prop2;
+
+ // Warn: could be an underflow, but this does not invoke undefined behaviour
+ --a2;
+ }
+ }
+
+ // Find out which transformations are to be evaluated
+ if (!(configFlags & AI_UVTRAFO_ROTATION)) {
+ info.mRotation = 0.f;
+ }
+ if (!(configFlags & AI_UVTRAFO_SCALING)) {
+ info.mScaling = aiVector2D(1.f,1.f);
+ }
+ if (!(configFlags & AI_UVTRAFO_TRANSLATION)) {
+ info.mTranslation = aiVector2D(0.f,0.f);
+ }
+
+ // Do some preprocessing
+ PreProcessUVTransform(info);
+ info.uvIndex = std::min(info.uvIndex,AI_MAX_NUMBER_OF_TEXTURECOORDS -1u);
+
+ // Find out whether this material is used by more than
+ // one mesh. This will make our task much, much more difficult!
+ unsigned int cnt = 0;
+ for (unsigned int n = 0; n < pScene->mNumMeshes;++n) {
+ if (pScene->mMeshes[n]->mMaterialIndex == i)
+ ++cnt;
+ }
+
+ if (!cnt)
+ continue;
+ else if (1 != cnt) {
+ // This material is referenced by more than one mesh!
+ // So we need to make sure the UV index for the texture
+ // is identical for each of it ...
+ info.lockedPos = AI_TT_UV_IDX_LOCK_TBD;
+ }
+
+ // Get all corresponding meshes
+ for (unsigned int n = 0; n < pScene->mNumMeshes;++n) {
+ aiMesh* mesh = pScene->mMeshes[n];
+ if (mesh->mMaterialIndex != i || !mesh->mTextureCoords[0])
+ continue;
+
+ unsigned int uv = info.uvIndex;
+ if (!mesh->mTextureCoords[uv]) {
+ // If the requested UV index is not available, take the first one instead.
+ uv = 0;
+ }
+
+ if (mesh->mNumUVComponents[info.uvIndex] >= 3){
+ ASSIMP_LOG_WARN("UV transformations on 3D mapping channels are not supported");
+ continue;
+ }
+
+ MeshTrafoList::iterator it;
+
+ // Check whether we have this transform setup already
+ for (it = meshLists[n].begin();it != meshLists[n].end(); ++it) {
+
+ if ((*it) == info && (*it).uvIndex == uv) {
+ (*it).updateList.push_back(update);
+ break;
+ }
+ }
+
+ if (it == meshLists[n].end()) {
+ meshLists[n].push_back(info);
+ meshLists[n].back().uvIndex = uv;
+ meshLists[n].back().updateList.push_back(update);
+ }
+ }
+ }
+ }
+ }
+
+ char buffer[1024]; // should be sufficiently large
+ unsigned int outChannels = 0, inChannels = 0, transformedChannels = 0;
+
+ // Now process all meshes. Important: we don't remove unreferenced UV channels.
+ // This is a job for the RemoveUnreferencedData-Step.
+ for (unsigned int q = 0; q < pScene->mNumMeshes;++q) {
+
+ aiMesh* mesh = pScene->mMeshes[q];
+ MeshTrafoList& trafo = meshLists[q];
+
+ inChannels += mesh->GetNumUVChannels();
+
+ if (!mesh->mTextureCoords[0] || trafo.empty() || (trafo.size() == 1 && trafo.begin()->IsUntransformed())) {
+ outChannels += mesh->GetNumUVChannels();
+ continue;
+ }
+
+ // Move untransformed UV channels to the first position in the list ....
+ // except if we need a new locked index which should be as small as possible
+ bool veto = false, need = false;
+ unsigned int cnt = 0;
+ unsigned int untransformed = 0;
+
+ MeshTrafoList::iterator it,it2;
+ for (it = trafo.begin();it != trafo.end(); ++it,++cnt) {
+
+ if (!(*it).IsUntransformed()) {
+ need = true;
+ }
+
+ if ((*it).lockedPos == AI_TT_UV_IDX_LOCK_TBD) {
+ // Lock this index and make sure it won't be changed
+ (*it).lockedPos = cnt;
+ veto = true;
+ continue;
+ }
+
+ if (!veto && it != trafo.begin() && (*it).IsUntransformed()) {
+ for (it2 = trafo.begin();it2 != it; ++it2) {
+ if (!(*it2).IsUntransformed())
+ break;
+ }
+ trafo.insert(it2,*it);
+ trafo.erase(it);
+ break;
+ }
+ }
+ if (!need)
+ continue;
+
+ // Find all that are not at their 'locked' position and move them to it.
+ // Conflicts are possible but quite unlikely.
+ cnt = 0;
+ for (it = trafo.begin();it != trafo.end(); ++it,++cnt) {
+ if ((*it).lockedPos != AI_TT_UV_IDX_LOCK_NONE && (*it).lockedPos != cnt) {
+ it2 = trafo.begin();unsigned int t = 0;
+ while (t != (*it).lockedPos)
+ ++it2;
+
+ if ((*it2).lockedPos != AI_TT_UV_IDX_LOCK_NONE) {
+ ASSIMP_LOG_ERROR("Channel mismatch, can't compute all transformations properly [design bug]");
+ continue;
+ }
+
+ std::swap(*it2,*it);
+ if ((*it).lockedPos == untransformed)
+ untransformed = cnt;
+ }
+ }
+
+ // ... and add dummies for all unreferenced channels
+ // at the end of the list
+ bool ref[AI_MAX_NUMBER_OF_TEXTURECOORDS];
+ for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n)
+ ref[n] = (!mesh->mTextureCoords[n] ? true : false);
+
+ for (it = trafo.begin();it != trafo.end(); ++it)
+ ref[(*it).uvIndex] = true;
+
+ for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) {
+ if (ref[n])
+ continue;
+ trafo.push_back(STransformVecInfo());
+ trafo.back().uvIndex = n;
+ }
+
+ // Then check whether this list breaks the channel limit.
+ // The unimportant ones are at the end of the list, so
+ // it shouldn't be too worse if we remove them.
+ unsigned int size = (unsigned int)trafo.size();
+ if (size > AI_MAX_NUMBER_OF_TEXTURECOORDS) {
+
+ if (!DefaultLogger::isNullLogger()) {
+ ASSIMP_LOG_ERROR_F(static_cast<unsigned int>(trafo.size()), " UV channels required but just ",
+ AI_MAX_NUMBER_OF_TEXTURECOORDS, " available");
+ }
+ size = AI_MAX_NUMBER_OF_TEXTURECOORDS;
+ }
+
+
+ aiVector3D* old[AI_MAX_NUMBER_OF_TEXTURECOORDS];
+ for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n)
+ old[n] = mesh->mTextureCoords[n];
+
+ // Now continue and generate the output channels. Channels
+ // that we're not going to need later can be overridden.
+ it = trafo.begin();
+ for (unsigned int n = 0; n < trafo.size();++n,++it) {
+
+ if (n >= size) {
+ // Try to use an untransformed channel for all channels we threw over board
+ UpdateUVIndex((*it).updateList,untransformed);
+ continue;
+ }
+
+ outChannels++;
+
+ // Write to the log
+ if (!DefaultLogger::isNullLogger()) {
+ ::ai_snprintf(buffer,1024,"Mesh %u, channel %u: t(%.3f,%.3f), s(%.3f,%.3f), r(%.3f), %s%s",
+ q,n,
+ (*it).mTranslation.x,
+ (*it).mTranslation.y,
+ (*it).mScaling.x,
+ (*it).mScaling.y,
+ AI_RAD_TO_DEG( (*it).mRotation),
+ MappingModeToChar ((*it).mapU),
+ MappingModeToChar ((*it).mapV));
+
+ ASSIMP_LOG_INFO(buffer);
+ }
+
+ // Check whether we need a new buffer here
+ if (mesh->mTextureCoords[n]) {
+
+ it2 = it;++it2;
+ for (unsigned int m = n+1; m < size;++m, ++it2) {
+
+ if ((*it2).uvIndex == n){
+ it2 = trafo.begin();
+ break;
+ }
+ }
+ if (it2 == trafo.begin()){
+ mesh->mTextureCoords[n] = new aiVector3D[mesh->mNumVertices];
+ }
+ }
+ else mesh->mTextureCoords[n] = new aiVector3D[mesh->mNumVertices];
+
+ aiVector3D* src = old[(*it).uvIndex];
+ aiVector3D* dest, *end;
+ dest = mesh->mTextureCoords[n];
+
+ ai_assert(NULL != src);
+
+ // Copy the data to the destination array
+ if (dest != src)
+ ::memcpy(dest,src,sizeof(aiVector3D)*mesh->mNumVertices);
+
+ end = dest + mesh->mNumVertices;
+
+ // Build a transformation matrix and transform all UV coords with it
+ if (!(*it).IsUntransformed()) {
+ const aiVector2D& trl = (*it).mTranslation;
+ const aiVector2D& scl = (*it).mScaling;
+
+ // fixme: simplify ..
+ ++transformedChannels;
+ aiMatrix3x3 matrix;
+
+ aiMatrix3x3 m2,m3,m4,m5;
+
+ m4.a1 = scl.x;
+ m4.b2 = scl.y;
+
+ m2.a3 = m2.b3 = 0.5f;
+ m3.a3 = m3.b3 = -0.5f;
+
+ if ((*it).mRotation > AI_TT_ROTATION_EPSILON )
+ aiMatrix3x3::RotationZ((*it).mRotation,matrix);
+
+ m5.a3 += trl.x; m5.b3 += trl.y;
+ matrix = m2 * m4 * matrix * m3 * m5;
+
+ for (src = dest; src != end; ++src) { /* manual homogenious divide */
+ src->z = 1.f;
+ *src = matrix * *src;
+ src->x /= src->z;
+ src->y /= src->z;
+ src->z = 0.f;
+ }
+ }
+
+ // Update all UV indices
+ UpdateUVIndex((*it).updateList,n);
+ }
+ }
+
+ // Print some detailed statistics into the log
+ if (!DefaultLogger::isNullLogger()) {
+
+ if (transformedChannels) {
+ ASSIMP_LOG_INFO_F("TransformUVCoordsProcess end: ", outChannels, " output channels (in: ", inChannels, ", modified: ", transformedChannels,")");
+ } else {
+ ASSIMP_LOG_DEBUG("TransformUVCoordsProcess finished");
+ }
+ }
+}
+
+
diff --git a/thirdparty/assimp/code/TextureTransform.h b/thirdparty/assimp/code/TextureTransform.h
new file mode 100644
index 0000000000..c556ff5d8c
--- /dev/null
+++ b/thirdparty/assimp/code/TextureTransform.h
@@ -0,0 +1,232 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file Definition of a helper step that processes texture transformations */
+#ifndef AI_TEXTURE_TRANSFORM_H_INCLUDED
+#define AI_TEXTURE_TRANSFORM_H_INCLUDED
+
+#include <assimp/BaseImporter.h>
+#include "BaseProcess.h"
+
+#include <assimp/material.h>
+#include <list>
+
+struct aiNode;
+struct aiMaterial;
+
+namespace Assimp {
+
+#define AI_TT_UV_IDX_LOCK_TBD 0xffffffff
+#define AI_TT_UV_IDX_LOCK_NONE 0xeeeeeeee
+
+
+#define AI_TT_ROTATION_EPSILON ((float)AI_DEG_TO_RAD(0.5))
+
+// ---------------------------------------------------------------------------
+/** Small helper structure representing a shortcut into the material list
+ * to be able to update some values quickly.
+*/
+struct TTUpdateInfo {
+ TTUpdateInfo() AI_NO_EXCEPT
+ : directShortcut(nullptr)
+ , mat(nullptr)
+ , semantic(0)
+ , index(0) {
+ // empty
+ }
+
+ //! Direct shortcut, if available
+ unsigned int* directShortcut;
+
+ //! Material
+ aiMaterial *mat;
+
+ //! Texture type and index
+ unsigned int semantic, index;
+};
+
+
+// ---------------------------------------------------------------------------
+/** Helper class representing texture coordinate transformations
+*/
+struct STransformVecInfo : public aiUVTransform {
+ STransformVecInfo() AI_NO_EXCEPT
+ : uvIndex(0)
+ , mapU(aiTextureMapMode_Wrap)
+ , mapV(aiTextureMapMode_Wrap)
+ , lockedPos(AI_TT_UV_IDX_LOCK_NONE) {
+ // empty
+ }
+
+ //! Source texture coordinate index
+ unsigned int uvIndex;
+
+ //! Texture mapping mode in the u, v direction
+ aiTextureMapMode mapU,mapV;
+
+ //! Locked destination UV index
+ //! AI_TT_UV_IDX_LOCK_TBD - to be determined
+ //! AI_TT_UV_IDX_LOCK_NONE - none (default)
+ unsigned int lockedPos;
+
+ //! Update info - shortcuts into all materials
+ //! that are referencing this transform setup
+ std::list<TTUpdateInfo> updateList;
+
+
+ // -------------------------------------------------------------------
+ /** Compare two transform setups
+ */
+ inline bool operator== (const STransformVecInfo& other) const
+ {
+ // We use a small epsilon here
+ const static float epsilon = 0.05f;
+
+ if (std::fabs( mTranslation.x - other.mTranslation.x ) > epsilon ||
+ std::fabs( mTranslation.y - other.mTranslation.y ) > epsilon)
+ {
+ return false;
+ }
+
+ if (std::fabs( mScaling.x - other.mScaling.x ) > epsilon ||
+ std::fabs( mScaling.y - other.mScaling.y ) > epsilon)
+ {
+ return false;
+ }
+
+ if (std::fabs( mRotation - other.mRotation) > epsilon)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ inline bool operator!= (const STransformVecInfo& other) const
+ {
+ return !(*this == other);
+ }
+
+
+ // -------------------------------------------------------------------
+ /** Returns whether this is an untransformed texture coordinate set
+ */
+ inline bool IsUntransformed() const
+ {
+ return (1.0f == mScaling.x && 1.f == mScaling.y &&
+ !mTranslation.x && !mTranslation.y &&
+ mRotation < AI_TT_ROTATION_EPSILON);
+ }
+
+ // -------------------------------------------------------------------
+ /** Build a 3x3 matrix from the transformations
+ */
+ inline void GetMatrix(aiMatrix3x3& mOut)
+ {
+ mOut = aiMatrix3x3();
+
+ if (1.0f != mScaling.x || 1.0f != mScaling.y)
+ {
+ aiMatrix3x3 mScale;
+ mScale.a1 = mScaling.x;
+ mScale.b2 = mScaling.y;
+ mOut = mScale;
+ }
+ if (mRotation)
+ {
+ aiMatrix3x3 mRot;
+ mRot.a1 = mRot.b2 = std::cos(mRotation);
+ mRot.a2 = mRot.b1 = std::sin(mRotation);
+ mRot.a2 = -mRot.a2;
+ mOut *= mRot;
+ }
+ if (mTranslation.x || mTranslation.y)
+ {
+ aiMatrix3x3 mTrans;
+ mTrans.a3 = mTranslation.x;
+ mTrans.b3 = mTranslation.y;
+ mOut *= mTrans;
+ }
+ }
+};
+
+
+// ---------------------------------------------------------------------------
+/** Helper step to compute final UV coordinate sets if there are scalings
+ * or rotations in the original data read from the file.
+*/
+class TextureTransformStep : public BaseProcess
+{
+public:
+
+ TextureTransformStep();
+ ~TextureTransformStep();
+
+public:
+
+ // -------------------------------------------------------------------
+ bool IsActive( unsigned int pFlags) const;
+
+ // -------------------------------------------------------------------
+ void Execute( aiScene* pScene);
+
+ // -------------------------------------------------------------------
+ void SetupProperties(const Importer* pImp);
+
+
+protected:
+
+
+ // -------------------------------------------------------------------
+ /** Preprocess a specific UV transformation setup
+ *
+ * @param info Transformation setup to be preprocessed.
+ */
+ void PreProcessUVTransform(STransformVecInfo& info);
+
+private:
+
+ unsigned int configFlags;
+};
+
+}
+
+#endif //! AI_TEXTURE_TRANSFORM_H_INCLUDED
diff --git a/thirdparty/assimp/code/TriangulateProcess.cpp b/thirdparty/assimp/code/TriangulateProcess.cpp
new file mode 100644
index 0000000000..0f68f47ddb
--- /dev/null
+++ b/thirdparty/assimp/code/TriangulateProcess.cpp
@@ -0,0 +1,530 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file TriangulateProcess.cpp
+ * @brief Implementation of the post processing step to split up
+ * all faces with more than three indices into triangles.
+ *
+ *
+ * The triangulation algorithm will handle concave or convex polygons.
+ * Self-intersecting or non-planar polygons are not rejected, but
+ * they're probably not triangulated correctly.
+ *
+ * DEBUG SWITCHES - do not enable any of them in release builds:
+ *
+ * AI_BUILD_TRIANGULATE_COLOR_FACE_WINDING
+ * - generates vertex colors to represent the face winding order.
+ * the first vertex of a polygon becomes red, the last blue.
+ * AI_BUILD_TRIANGULATE_DEBUG_POLYS
+ * - dump all polygons and their triangulation sequences to
+ * a file
+ */
+#ifndef ASSIMP_BUILD_NO_TRIANGULATE_PROCESS
+#include "TriangulateProcess.h"
+#include "ProcessHelper.h"
+#include "PolyTools.h"
+#include <memory>
+
+//#define AI_BUILD_TRIANGULATE_COLOR_FACE_WINDING
+//#define AI_BUILD_TRIANGULATE_DEBUG_POLYS
+
+#define POLY_GRID_Y 40
+#define POLY_GRID_X 70
+#define POLY_GRID_XPAD 20
+#define POLY_OUTPUT_FILE "assimp_polygons_debug.txt"
+
+using namespace Assimp;
+
+// ------------------------------------------------------------------------------------------------
+// Constructor to be privately used by Importer
+TriangulateProcess::TriangulateProcess()
+{
+ // nothing to do here
+}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor, private as well
+TriangulateProcess::~TriangulateProcess()
+{
+ // nothing to do here
+}
+
+// ------------------------------------------------------------------------------------------------
+// Returns whether the processing step is present in the given flag field.
+bool TriangulateProcess::IsActive( unsigned int pFlags) const
+{
+ return (pFlags & aiProcess_Triangulate) != 0;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+void TriangulateProcess::Execute( aiScene* pScene)
+{
+ ASSIMP_LOG_DEBUG("TriangulateProcess begin");
+
+ bool bHas = false;
+ for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
+ {
+ if (pScene->mMeshes[ a ]) {
+ if ( TriangulateMesh( pScene->mMeshes[ a ] ) ) {
+ bHas = true;
+ }
+ }
+ }
+ if ( bHas ) {
+ ASSIMP_LOG_INFO( "TriangulateProcess finished. All polygons have been triangulated." );
+ } else {
+ ASSIMP_LOG_DEBUG( "TriangulateProcess finished. There was nothing to be done." );
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Triangulates the given mesh.
+bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
+{
+ // Now we have aiMesh::mPrimitiveTypes, so this is only here for test cases
+ if (!pMesh->mPrimitiveTypes) {
+ bool bNeed = false;
+
+ for( unsigned int a = 0; a < pMesh->mNumFaces; a++) {
+ const aiFace& face = pMesh->mFaces[a];
+
+ if( face.mNumIndices != 3) {
+ bNeed = true;
+ }
+ }
+ if (!bNeed)
+ return false;
+ }
+ else if (!(pMesh->mPrimitiveTypes & aiPrimitiveType_POLYGON)) {
+ return false;
+ }
+
+ // Find out how many output faces we'll get
+ unsigned int numOut = 0, max_out = 0;
+ bool get_normals = true;
+ for( unsigned int a = 0; a < pMesh->mNumFaces; a++) {
+ aiFace& face = pMesh->mFaces[a];
+ if (face.mNumIndices <= 4) {
+ get_normals = false;
+ }
+ if( face.mNumIndices <= 3) {
+ numOut++;
+
+ }
+ else {
+ numOut += face.mNumIndices-2;
+ max_out = std::max(max_out,face.mNumIndices);
+ }
+ }
+
+ // Just another check whether aiMesh::mPrimitiveTypes is correct
+ ai_assert(numOut != pMesh->mNumFaces);
+
+ aiVector3D* nor_out = NULL;
+
+ // if we don't have normals yet, but expect them to be a cheap side
+ // product of triangulation anyway, allocate storage for them.
+ if (!pMesh->mNormals && get_normals) {
+ // XXX need a mechanism to inform the GenVertexNormals process to treat these normals as preprocessed per-face normals
+ // nor_out = pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
+ }
+
+ // the output mesh will contain triangles, but no polys anymore
+ pMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
+ pMesh->mPrimitiveTypes &= ~aiPrimitiveType_POLYGON;
+
+ aiFace* out = new aiFace[numOut](), *curOut = out;
+ std::vector<aiVector3D> temp_verts3d(max_out+2); /* temporary storage for vertices */
+ std::vector<aiVector2D> temp_verts(max_out+2);
+
+ // Apply vertex colors to represent the face winding?
+#ifdef AI_BUILD_TRIANGULATE_COLOR_FACE_WINDING
+ if (!pMesh->mColors[0])
+ pMesh->mColors[0] = new aiColor4D[pMesh->mNumVertices];
+ else
+ new(pMesh->mColors[0]) aiColor4D[pMesh->mNumVertices];
+
+ aiColor4D* clr = pMesh->mColors[0];
+#endif
+
+#ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS
+ FILE* fout = fopen(POLY_OUTPUT_FILE,"a");
+#endif
+
+ const aiVector3D* verts = pMesh->mVertices;
+
+ // use std::unique_ptr to avoid slow std::vector<bool> specialiations
+ std::unique_ptr<bool[]> done(new bool[max_out]);
+ for( unsigned int a = 0; a < pMesh->mNumFaces; a++) {
+ aiFace& face = pMesh->mFaces[a];
+
+ unsigned int* idx = face.mIndices;
+ int num = (int)face.mNumIndices, ear = 0, tmp, prev = num-1, next = 0, max = num;
+
+ // Apply vertex colors to represent the face winding?
+#ifdef AI_BUILD_TRIANGULATE_COLOR_FACE_WINDING
+ for (unsigned int i = 0; i < face.mNumIndices; ++i) {
+ aiColor4D& c = clr[idx[i]];
+ c.r = (i+1) / (float)max;
+ c.b = 1.f - c.r;
+ }
+#endif
+
+ aiFace* const last_face = curOut;
+
+ // if it's a simple point,line or triangle: just copy it
+ if( face.mNumIndices <= 3)
+ {
+ aiFace& nface = *curOut++;
+ nface.mNumIndices = face.mNumIndices;
+ nface.mIndices = face.mIndices;
+
+ face.mIndices = NULL;
+ continue;
+ }
+ // optimized code for quadrilaterals
+ else if ( face.mNumIndices == 4) {
+
+ // quads can have at maximum one concave vertex. Determine
+ // this vertex (if it exists) and start tri-fanning from
+ // it.
+ unsigned int start_vertex = 0;
+ for (unsigned int i = 0; i < 4; ++i) {
+ const aiVector3D& v0 = verts[face.mIndices[(i+3) % 4]];
+ const aiVector3D& v1 = verts[face.mIndices[(i+2) % 4]];
+ const aiVector3D& v2 = verts[face.mIndices[(i+1) % 4]];
+
+ const aiVector3D& v = verts[face.mIndices[i]];
+
+ aiVector3D left = (v0-v);
+ aiVector3D diag = (v1-v);
+ aiVector3D right = (v2-v);
+
+ left.Normalize();
+ diag.Normalize();
+ right.Normalize();
+
+ const float angle = std::acos(left*diag) + std::acos(right*diag);
+ if (angle > AI_MATH_PI_F) {
+ // this is the concave point
+ start_vertex = i;
+ break;
+ }
+ }
+
+ const unsigned int temp[] = {face.mIndices[0], face.mIndices[1], face.mIndices[2], face.mIndices[3]};
+
+ aiFace& nface = *curOut++;
+ nface.mNumIndices = 3;
+ nface.mIndices = face.mIndices;
+
+ nface.mIndices[0] = temp[start_vertex];
+ nface.mIndices[1] = temp[(start_vertex + 1) % 4];
+ nface.mIndices[2] = temp[(start_vertex + 2) % 4];
+
+ aiFace& sface = *curOut++;
+ sface.mNumIndices = 3;
+ sface.mIndices = new unsigned int[3];
+
+ sface.mIndices[0] = temp[start_vertex];
+ sface.mIndices[1] = temp[(start_vertex + 2) % 4];
+ sface.mIndices[2] = temp[(start_vertex + 3) % 4];
+
+ // prevent double deletion of the indices field
+ face.mIndices = NULL;
+ continue;
+ }
+ else
+ {
+ // A polygon with more than 3 vertices can be either concave or convex.
+ // Usually everything we're getting is convex and we could easily
+ // triangulate by tri-fanning. However, LightWave is probably the only
+ // modeling suite to make extensive use of highly concave, monster polygons ...
+ // so we need to apply the full 'ear cutting' algorithm to get it right.
+
+ // RERQUIREMENT: polygon is expected to be simple and *nearly* planar.
+ // We project it onto a plane to get a 2d triangle.
+
+ // Collect all vertices of of the polygon.
+ for (tmp = 0; tmp < max; ++tmp) {
+ temp_verts3d[tmp] = verts[idx[tmp]];
+ }
+
+ // Get newell normal of the polygon. Store it for future use if it's a polygon-only mesh
+ aiVector3D n;
+ NewellNormal<3,3,3>(n,max,&temp_verts3d.front().x,&temp_verts3d.front().y,&temp_verts3d.front().z);
+ if (nor_out) {
+ for (tmp = 0; tmp < max; ++tmp)
+ nor_out[idx[tmp]] = n;
+ }
+
+ // Select largest normal coordinate to ignore for projection
+ const float ax = (n.x>0 ? n.x : -n.x);
+ const float ay = (n.y>0 ? n.y : -n.y);
+ const float az = (n.z>0 ? n.z : -n.z);
+
+ unsigned int ac = 0, bc = 1; /* no z coord. projection to xy */
+ float inv = n.z;
+ if (ax > ay) {
+ if (ax > az) { /* no x coord. projection to yz */
+ ac = 1; bc = 2;
+ inv = n.x;
+ }
+ }
+ else if (ay > az) { /* no y coord. projection to zy */
+ ac = 2; bc = 0;
+ inv = n.y;
+ }
+
+ // Swap projection axes to take the negated projection vector into account
+ if (inv < 0.f) {
+ std::swap(ac,bc);
+ }
+
+ for (tmp =0; tmp < max; ++tmp) {
+ temp_verts[tmp].x = verts[idx[tmp]][ac];
+ temp_verts[tmp].y = verts[idx[tmp]][bc];
+ done[tmp] = false;
+ }
+
+#ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS
+ // plot the plane onto which we mapped the polygon to a 2D ASCII pic
+ aiVector2D bmin,bmax;
+ ArrayBounds(&temp_verts[0],max,bmin,bmax);
+
+ char grid[POLY_GRID_Y][POLY_GRID_X+POLY_GRID_XPAD];
+ std::fill_n((char*)grid,POLY_GRID_Y*(POLY_GRID_X+POLY_GRID_XPAD),' ');
+
+ for (int i =0; i < max; ++i) {
+ const aiVector2D& v = (temp_verts[i] - bmin) / (bmax-bmin);
+ const size_t x = static_cast<size_t>(v.x*(POLY_GRID_X-1)), y = static_cast<size_t>(v.y*(POLY_GRID_Y-1));
+ char* loc = grid[y]+x;
+ if (grid[y][x] != ' ') {
+ for(;*loc != ' '; ++loc);
+ *loc++ = '_';
+ }
+ *(loc+::ai_snprintf(loc, POLY_GRID_XPAD,"%i",i)) = ' ';
+ }
+
+
+ for(size_t y = 0; y < POLY_GRID_Y; ++y) {
+ grid[y][POLY_GRID_X+POLY_GRID_XPAD-1] = '\0';
+ fprintf(fout,"%s\n",grid[y]);
+ }
+
+ fprintf(fout,"\ntriangulation sequence: ");
+#endif
+
+ //
+ // FIXME: currently this is the slow O(kn) variant with a worst case
+ // complexity of O(n^2) (I think). Can be done in O(n).
+ while (num > 3) {
+
+ // Find the next ear of the polygon
+ int num_found = 0;
+ for (ear = next;;prev = ear,ear = next) {
+
+ // break after we looped two times without a positive match
+ for (next=ear+1;done[(next>=max?next=0:next)];++next);
+ if (next < ear) {
+ if (++num_found == 2) {
+ break;
+ }
+ }
+ const aiVector2D* pnt1 = &temp_verts[ear],
+ *pnt0 = &temp_verts[prev],
+ *pnt2 = &temp_verts[next];
+
+ // Must be a convex point. Assuming ccw winding, it must be on the right of the line between p-1 and p+1.
+ if (OnLeftSideOfLine2D(*pnt0,*pnt2,*pnt1)) {
+ continue;
+ }
+
+ // and no other point may be contained in this triangle
+ for ( tmp = 0; tmp < max; ++tmp) {
+
+ // We need to compare the actual values because it's possible that multiple indexes in
+ // the polygon are referring to the same position. concave_polygon.obj is a sample
+ //
+ // FIXME: Use 'epsiloned' comparisons instead? Due to numeric inaccuracies in
+ // PointInTriangle() I'm guessing that it's actually possible to construct
+ // input data that would cause us to end up with no ears. The problem is,
+ // which epsilon? If we chose a too large value, we'd get wrong results
+ const aiVector2D& vtmp = temp_verts[tmp];
+ if ( vtmp != *pnt1 && vtmp != *pnt2 && vtmp != *pnt0 && PointInTriangle2D(*pnt0,*pnt1,*pnt2,vtmp)) {
+ break;
+ }
+ }
+ if (tmp != max) {
+ continue;
+ }
+
+ // this vertex is an ear
+ break;
+ }
+ if (num_found == 2) {
+
+ // Due to the 'two ear theorem', every simple polygon with more than three points must
+ // have 2 'ears'. Here's definitely something wrong ... but we don't give up yet.
+ //
+
+ // Instead we're continuing with the standard tri-fanning algorithm which we'd
+ // use if we had only convex polygons. That's life.
+ ASSIMP_LOG_ERROR("Failed to triangulate polygon (no ear found). Probably not a simple polygon?");
+
+#ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS
+ fprintf(fout,"critical error here, no ear found! ");
+#endif
+ num = 0;
+ break;
+
+ curOut -= (max-num); /* undo all previous work */
+ for (tmp = 0; tmp < max-2; ++tmp) {
+ aiFace& nface = *curOut++;
+
+ nface.mNumIndices = 3;
+ if (!nface.mIndices)
+ nface.mIndices = new unsigned int[3];
+
+ nface.mIndices[0] = 0;
+ nface.mIndices[1] = tmp+1;
+ nface.mIndices[2] = tmp+2;
+
+ }
+ num = 0;
+ break;
+ }
+
+ aiFace& nface = *curOut++;
+ nface.mNumIndices = 3;
+
+ if (!nface.mIndices) {
+ nface.mIndices = new unsigned int[3];
+ }
+
+ // setup indices for the new triangle ...
+ nface.mIndices[0] = prev;
+ nface.mIndices[1] = ear;
+ nface.mIndices[2] = next;
+
+ // exclude the ear from most further processing
+ done[ear] = true;
+ --num;
+ }
+ if (num > 0) {
+ // We have three indices forming the last 'ear' remaining. Collect them.
+ aiFace& nface = *curOut++;
+ nface.mNumIndices = 3;
+ if (!nface.mIndices) {
+ nface.mIndices = new unsigned int[3];
+ }
+
+ for (tmp = 0; done[tmp]; ++tmp);
+ nface.mIndices[0] = tmp;
+
+ for (++tmp; done[tmp]; ++tmp);
+ nface.mIndices[1] = tmp;
+
+ for (++tmp; done[tmp]; ++tmp);
+ nface.mIndices[2] = tmp;
+
+ }
+ }
+
+#ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS
+
+ for(aiFace* f = last_face; f != curOut; ++f) {
+ unsigned int* i = f->mIndices;
+ fprintf(fout," (%i %i %i)",i[0],i[1],i[2]);
+ }
+
+ fprintf(fout,"\n*********************************************************************\n");
+ fflush(fout);
+
+#endif
+
+ for(aiFace* f = last_face; f != curOut; ) {
+ unsigned int* i = f->mIndices;
+
+ // drop dumb 0-area triangles - deactivated for now:
+ //FindDegenerates post processing step can do the same thing
+ //if (std::fabs(GetArea2D(temp_verts[i[0]],temp_verts[i[1]],temp_verts[i[2]])) < 1e-5f) {
+ // ASSIMP_LOG_DEBUG("Dropping triangle with area 0");
+ // --curOut;
+
+ // delete[] f->mIndices;
+ // f->mIndices = nullptr;
+
+ // for(aiFace* ff = f; ff != curOut; ++ff) {
+ // ff->mNumIndices = (ff+1)->mNumIndices;
+ // ff->mIndices = (ff+1)->mIndices;
+ // (ff+1)->mIndices = nullptr;
+ // }
+ // continue;
+ //}
+
+ i[0] = idx[i[0]];
+ i[1] = idx[i[1]];
+ i[2] = idx[i[2]];
+ ++f;
+ }
+
+ delete[] face.mIndices;
+ face.mIndices = NULL;
+ }
+
+#ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS
+ fclose(fout);
+#endif
+
+ // kill the old faces
+ delete [] pMesh->mFaces;
+
+ // ... and store the new ones
+ pMesh->mFaces = out;
+ pMesh->mNumFaces = (unsigned int)(curOut-out); /* not necessarily equal to numOut */
+ return true;
+}
+
+#endif // !! ASSIMP_BUILD_NO_TRIANGULATE_PROCESS
diff --git a/thirdparty/assimp/code/TriangulateProcess.h b/thirdparty/assimp/code/TriangulateProcess.h
new file mode 100644
index 0000000000..47bd2115ad
--- /dev/null
+++ b/thirdparty/assimp/code/TriangulateProcess.h
@@ -0,0 +1,95 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file Defines a post processing step to triangulate all faces
+ with more than three vertices.
+ */
+#ifndef AI_TRIANGULATEPROCESS_H_INC
+#define AI_TRIANGULATEPROCESS_H_INC
+
+#include "BaseProcess.h"
+
+struct aiMesh;
+
+class TriangulateProcessTest;
+
+namespace Assimp {
+
+// ---------------------------------------------------------------------------
+/** The TriangulateProcess splits up all faces with more than three indices
+ * into triangles. You usually want this to happen because the graphics cards
+ * need their data as triangles.
+ */
+class ASSIMP_API TriangulateProcess : public BaseProcess
+{
+public:
+
+ TriangulateProcess();
+ ~TriangulateProcess();
+
+public:
+ // -------------------------------------------------------------------
+ /** Returns whether the processing step is present in the given flag field.
+ * @param pFlags The processing flags the importer was called with. A bitwise
+ * combination of #aiPostProcessSteps.
+ * @return true if the process is present in this flag fields, false if not.
+ */
+ bool IsActive( unsigned int pFlags) const;
+
+ // -------------------------------------------------------------------
+ /** Executes the post processing step on the given imported data.
+ * At the moment a process is not supposed to fail.
+ * @param pScene The imported data to work at.
+ */
+ void Execute( aiScene* pScene);
+
+public:
+ // -------------------------------------------------------------------
+ /** Triangulates the given mesh.
+ * @param pMesh The mesh to triangulate.
+ */
+ bool TriangulateMesh( aiMesh* pMesh);
+};
+
+} // end of namespace Assimp
+
+#endif // AI_TRIANGULATEPROCESS_H_INC
diff --git a/thirdparty/assimp/code/ValidateDataStructure.cpp b/thirdparty/assimp/code/ValidateDataStructure.cpp
new file mode 100644
index 0000000000..657b0361b7
--- /dev/null
+++ b/thirdparty/assimp/code/ValidateDataStructure.cpp
@@ -0,0 +1,986 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file ValidateDataStructure.cpp
+ * @brief Implementation of the post processing step to validate
+ * the data structure returned by Assimp.
+ */
+
+
+
+// internal headers
+#include "ValidateDataStructure.h"
+#include <assimp/BaseImporter.h>
+#include <assimp/fast_atof.h>
+#include "ProcessHelper.h"
+#include <memory>
+
+// CRT headers
+#include <stdarg.h>
+
+using namespace Assimp;
+
+// ------------------------------------------------------------------------------------------------
+// Constructor to be privately used by Importer
+ValidateDSProcess::ValidateDSProcess() :
+ mScene()
+{}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor, private as well
+ValidateDSProcess::~ValidateDSProcess()
+{}
+
+// ------------------------------------------------------------------------------------------------
+// Returns whether the processing step is present in the given flag field.
+bool ValidateDSProcess::IsActive( unsigned int pFlags) const
+{
+ return (pFlags & aiProcess_ValidateDataStructure) != 0;
+}
+// ------------------------------------------------------------------------------------------------
+AI_WONT_RETURN void ValidateDSProcess::ReportError(const char* msg,...)
+{
+ ai_assert(NULL != msg);
+
+ va_list args;
+ va_start(args,msg);
+
+ char szBuffer[3000];
+ const int iLen = vsprintf(szBuffer,msg,args);
+ ai_assert(iLen > 0);
+
+ va_end(args);
+
+ throw DeadlyImportError("Validation failed: " + std::string(szBuffer,iLen));
+}
+// ------------------------------------------------------------------------------------------------
+void ValidateDSProcess::ReportWarning(const char* msg,...)
+{
+ ai_assert(NULL != msg);
+
+ va_list args;
+ va_start(args,msg);
+
+ char szBuffer[3000];
+ const int iLen = vsprintf(szBuffer,msg,args);
+ ai_assert(iLen > 0);
+
+ va_end(args);
+ ASSIMP_LOG_WARN("Validation warning: " + std::string(szBuffer,iLen));
+}
+
+// ------------------------------------------------------------------------------------------------
+inline int HasNameMatch(const aiString& in, aiNode* node)
+{
+ int result = (node->mName == in ? 1 : 0 );
+ for (unsigned int i = 0; i < node->mNumChildren;++i) {
+ result += HasNameMatch(in,node->mChildren[i]);
+ }
+ return result;
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename T>
+inline void ValidateDSProcess::DoValidation(T** parray, unsigned int size,
+ const char* firstName, const char* secondName)
+{
+ // validate all entries
+ if (size)
+ {
+ if (!parray)
+ {
+ ReportError("aiScene::%s is NULL (aiScene::%s is %i)",
+ firstName, secondName, size);
+ }
+ for (unsigned int i = 0; i < size;++i)
+ {
+ if (!parray[i])
+ {
+ ReportError("aiScene::%s[%i] is NULL (aiScene::%s is %i)",
+ firstName,i,secondName,size);
+ }
+ Validate(parray[i]);
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename T>
+inline void ValidateDSProcess::DoValidationEx(T** parray, unsigned int size,
+ const char* firstName, const char* secondName)
+{
+ // validate all entries
+ if (size)
+ {
+ if (!parray) {
+ ReportError("aiScene::%s is NULL (aiScene::%s is %i)",
+ firstName, secondName, size);
+ }
+ for (unsigned int i = 0; i < size;++i)
+ {
+ if (!parray[i])
+ {
+ ReportError("aiScene::%s[%u] is NULL (aiScene::%s is %u)",
+ firstName,i,secondName,size);
+ }
+ Validate(parray[i]);
+
+ // check whether there are duplicate names
+ for (unsigned int a = i+1; a < size;++a)
+ {
+ if (parray[i]->mName == parray[a]->mName)
+ {
+ ReportError("aiScene::%s[%u] has the same name as "
+ "aiScene::%s[%u]",firstName, i,secondName, a);
+ }
+ }
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename T>
+inline
+void ValidateDSProcess::DoValidationWithNameCheck(T** array, unsigned int size, const char* firstName, const char* secondName) {
+ // validate all entries
+ DoValidationEx(array,size,firstName,secondName);
+
+ for (unsigned int i = 0; i < size;++i) {
+ int res = HasNameMatch(array[i]->mName,mScene->mRootNode);
+ if (0 == res) {
+ const std::string name = static_cast<char*>(array[i]->mName.data);
+ ReportError("aiScene::%s[%i] has no corresponding node in the scene graph (%s)",
+ firstName,i, name.c_str());
+ } else if (1 != res) {
+ const std::string name = static_cast<char*>(array[i]->mName.data);
+ ReportError("aiScene::%s[%i]: there are more than one nodes with %s as name",
+ firstName,i, name.c_str());
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+void ValidateDSProcess::Execute( aiScene* pScene)
+{
+ this->mScene = pScene;
+ ASSIMP_LOG_DEBUG("ValidateDataStructureProcess begin");
+
+ // validate the node graph of the scene
+ Validate(pScene->mRootNode);
+
+ // validate all meshes
+ if (pScene->mNumMeshes) {
+ DoValidation(pScene->mMeshes,pScene->mNumMeshes,"mMeshes","mNumMeshes");
+ }
+ else if (!(mScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE)) {
+ ReportError("aiScene::mNumMeshes is 0. At least one mesh must be there");
+ }
+ else if (pScene->mMeshes) {
+ ReportError("aiScene::mMeshes is non-null although there are no meshes");
+ }
+
+ // validate all animations
+ if (pScene->mNumAnimations) {
+ DoValidation(pScene->mAnimations,pScene->mNumAnimations,
+ "mAnimations","mNumAnimations");
+ }
+ else if (pScene->mAnimations) {
+ ReportError("aiScene::mAnimations is non-null although there are no animations");
+ }
+
+ // validate all cameras
+ if (pScene->mNumCameras) {
+ DoValidationWithNameCheck(pScene->mCameras,pScene->mNumCameras,
+ "mCameras","mNumCameras");
+ }
+ else if (pScene->mCameras) {
+ ReportError("aiScene::mCameras is non-null although there are no cameras");
+ }
+
+ // validate all lights
+ if (pScene->mNumLights) {
+ DoValidationWithNameCheck(pScene->mLights,pScene->mNumLights,
+ "mLights","mNumLights");
+ }
+ else if (pScene->mLights) {
+ ReportError("aiScene::mLights is non-null although there are no lights");
+ }
+
+ // validate all textures
+ if (pScene->mNumTextures) {
+ DoValidation(pScene->mTextures,pScene->mNumTextures,
+ "mTextures","mNumTextures");
+ }
+ else if (pScene->mTextures) {
+ ReportError("aiScene::mTextures is non-null although there are no textures");
+ }
+
+ // validate all materials
+ if (pScene->mNumMaterials) {
+ DoValidation(pScene->mMaterials,pScene->mNumMaterials,"mMaterials","mNumMaterials");
+ }
+#if 0
+ // NOTE: ScenePreprocessor generates a default material if none is there
+ else if (!(mScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE)) {
+ ReportError("aiScene::mNumMaterials is 0. At least one material must be there");
+ }
+#endif
+ else if (pScene->mMaterials) {
+ ReportError("aiScene::mMaterials is non-null although there are no materials");
+ }
+
+// if (!has)ReportError("The aiScene data structure is empty");
+ ASSIMP_LOG_DEBUG("ValidateDataStructureProcess end");
+}
+
+// ------------------------------------------------------------------------------------------------
+void ValidateDSProcess::Validate( const aiLight* pLight)
+{
+ if (pLight->mType == aiLightSource_UNDEFINED)
+ ReportWarning("aiLight::mType is aiLightSource_UNDEFINED");
+
+ if (!pLight->mAttenuationConstant &&
+ !pLight->mAttenuationLinear &&
+ !pLight->mAttenuationQuadratic) {
+ ReportWarning("aiLight::mAttenuationXXX - all are zero");
+ }
+
+ if (pLight->mAngleInnerCone > pLight->mAngleOuterCone)
+ ReportError("aiLight::mAngleInnerCone is larger than aiLight::mAngleOuterCone");
+
+ if (pLight->mColorDiffuse.IsBlack() && pLight->mColorAmbient.IsBlack()
+ && pLight->mColorSpecular.IsBlack())
+ {
+ ReportWarning("aiLight::mColorXXX - all are black and won't have any influence");
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+void ValidateDSProcess::Validate( const aiCamera* pCamera)
+{
+ if (pCamera->mClipPlaneFar <= pCamera->mClipPlaneNear)
+ ReportError("aiCamera::mClipPlaneFar must be >= aiCamera::mClipPlaneNear");
+
+ // FIX: there are many 3ds files with invalid FOVs. No reason to
+ // reject them at all ... a warning is appropriate.
+ if (!pCamera->mHorizontalFOV || pCamera->mHorizontalFOV >= (float)AI_MATH_PI)
+ ReportWarning("%f is not a valid value for aiCamera::mHorizontalFOV",pCamera->mHorizontalFOV);
+}
+
+// ------------------------------------------------------------------------------------------------
+void ValidateDSProcess::Validate( const aiMesh* pMesh)
+{
+ // validate the material index of the mesh
+ if (mScene->mNumMaterials && pMesh->mMaterialIndex >= mScene->mNumMaterials)
+ {
+ ReportError("aiMesh::mMaterialIndex is invalid (value: %i maximum: %i)",
+ pMesh->mMaterialIndex,mScene->mNumMaterials-1);
+ }
+
+ Validate(&pMesh->mName);
+
+ for (unsigned int i = 0; i < pMesh->mNumFaces; ++i)
+ {
+ aiFace& face = pMesh->mFaces[i];
+
+ if (pMesh->mPrimitiveTypes)
+ {
+ switch (face.mNumIndices)
+ {
+ case 0:
+ ReportError("aiMesh::mFaces[%i].mNumIndices is 0",i);
+ break;
+ case 1:
+ if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_POINT))
+ {
+ ReportError("aiMesh::mFaces[%i] is a POINT but aiMesh::mPrimitiveTypes "
+ "does not report the POINT flag",i);
+ }
+ break;
+ case 2:
+ if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_LINE))
+ {
+ ReportError("aiMesh::mFaces[%i] is a LINE but aiMesh::mPrimitiveTypes "
+ "does not report the LINE flag",i);
+ }
+ break;
+ case 3:
+ if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE))
+ {
+ ReportError("aiMesh::mFaces[%i] is a TRIANGLE but aiMesh::mPrimitiveTypes "
+ "does not report the TRIANGLE flag",i);
+ }
+ break;
+ default:
+ if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_POLYGON))
+ {
+ this->ReportError("aiMesh::mFaces[%i] is a POLYGON but aiMesh::mPrimitiveTypes "
+ "does not report the POLYGON flag",i);
+ }
+ break;
+ };
+ }
+
+ if (!face.mIndices)
+ ReportError("aiMesh::mFaces[%i].mIndices is NULL",i);
+ }
+
+ // positions must always be there ...
+ if (!pMesh->mNumVertices || (!pMesh->mVertices && !mScene->mFlags)) {
+ ReportError("The mesh %s contains no vertices", pMesh->mName.C_Str());
+ }
+
+ if (pMesh->mNumVertices > AI_MAX_VERTICES) {
+ ReportError("Mesh has too many vertices: %u, but the limit is %u",pMesh->mNumVertices,AI_MAX_VERTICES);
+ }
+ if (pMesh->mNumFaces > AI_MAX_FACES) {
+ ReportError("Mesh has too many faces: %u, but the limit is %u",pMesh->mNumFaces,AI_MAX_FACES);
+ }
+
+ // if tangents are there there must also be bitangent vectors ...
+ if ((pMesh->mTangents != NULL) != (pMesh->mBitangents != NULL)) {
+ ReportError("If there are tangents, bitangent vectors must be present as well");
+ }
+
+ // faces, too
+ if (!pMesh->mNumFaces || (!pMesh->mFaces && !mScene->mFlags)) {
+ ReportError("Mesh %s contains no faces", pMesh->mName.C_Str());
+ }
+
+ // now check whether the face indexing layout is correct:
+ // unique vertices, pseudo-indexed.
+ std::vector<bool> abRefList;
+ abRefList.resize(pMesh->mNumVertices,false);
+ for (unsigned int i = 0; i < pMesh->mNumFaces;++i)
+ {
+ aiFace& face = pMesh->mFaces[i];
+ if (face.mNumIndices > AI_MAX_FACE_INDICES) {
+ ReportError("Face %u has too many faces: %u, but the limit is %u",i,face.mNumIndices,AI_MAX_FACE_INDICES);
+ }
+
+ for (unsigned int a = 0; a < face.mNumIndices;++a)
+ {
+ if (face.mIndices[a] >= pMesh->mNumVertices) {
+ ReportError("aiMesh::mFaces[%i]::mIndices[%i] is out of range",i,a);
+ }
+ // the MSB flag is temporarily used by the extra verbose
+ // mode to tell us that the JoinVerticesProcess might have
+ // been executed already.
+ /*if ( !(this->mScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT ) && !(this->mScene->mFlags & AI_SCENE_FLAGS_ALLOW_SHARED) &&
+ abRefList[face.mIndices[a]])
+ {
+ ReportError("aiMesh::mVertices[%i] is referenced twice - second "
+ "time by aiMesh::mFaces[%i]::mIndices[%i]",face.mIndices[a],i,a);
+ }*/
+ abRefList[face.mIndices[a]] = true;
+ }
+ }
+
+ // check whether there are vertices that aren't referenced by a face
+ bool b = false;
+ for (unsigned int i = 0; i < pMesh->mNumVertices;++i) {
+ if (!abRefList[i])b = true;
+ }
+ abRefList.clear();
+ if (b) {
+ ReportWarning("There are unreferenced vertices");
+ }
+
+ // texture channel 2 may not be set if channel 1 is zero ...
+ {
+ unsigned int i = 0;
+ for (;i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
+ {
+ if (!pMesh->HasTextureCoords(i))break;
+ }
+ for (;i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
+ if (pMesh->HasTextureCoords(i))
+ {
+ ReportError("Texture coordinate channel %i exists "
+ "although the previous channel was NULL.",i);
+ }
+ }
+ // the same for the vertex colors
+ {
+ unsigned int i = 0;
+ for (;i < AI_MAX_NUMBER_OF_COLOR_SETS;++i)
+ {
+ if (!pMesh->HasVertexColors(i))break;
+ }
+ for (;i < AI_MAX_NUMBER_OF_COLOR_SETS;++i)
+ if (pMesh->HasVertexColors(i))
+ {
+ ReportError("Vertex color channel %i is exists "
+ "although the previous channel was NULL.",i);
+ }
+ }
+
+
+ // now validate all bones
+ if (pMesh->mNumBones)
+ {
+ if (!pMesh->mBones)
+ {
+ ReportError("aiMesh::mBones is NULL (aiMesh::mNumBones is %i)",
+ pMesh->mNumBones);
+ }
+ std::unique_ptr<float[]> afSum(nullptr);
+ if (pMesh->mNumVertices)
+ {
+ afSum.reset(new float[pMesh->mNumVertices]);
+ for (unsigned int i = 0; i < pMesh->mNumVertices;++i)
+ afSum[i] = 0.0f;
+ }
+
+ // check whether there are duplicate bone names
+ for (unsigned int i = 0; i < pMesh->mNumBones;++i)
+ {
+ const aiBone* bone = pMesh->mBones[i];
+ if (bone->mNumWeights > AI_MAX_BONE_WEIGHTS) {
+ ReportError("Bone %u has too many weights: %u, but the limit is %u",i,bone->mNumWeights,AI_MAX_BONE_WEIGHTS);
+ }
+
+ if (!pMesh->mBones[i])
+ {
+ ReportError("aiMesh::mBones[%i] is NULL (aiMesh::mNumBones is %i)",
+ i,pMesh->mNumBones);
+ }
+ Validate(pMesh,pMesh->mBones[i],afSum.get());
+
+ for (unsigned int a = i+1; a < pMesh->mNumBones;++a)
+ {
+ if (pMesh->mBones[i]->mName == pMesh->mBones[a]->mName)
+ {
+ const char *name = "unknown";
+ if (nullptr != pMesh->mBones[ i ]->mName.C_Str()) {
+ name = pMesh->mBones[ i ]->mName.C_Str();
+ }
+ ReportError("aiMesh::mBones[%i], name = \"%s\" has the same name as "
+ "aiMesh::mBones[%i]", i, name, a );
+ }
+ }
+ }
+ // check whether all bone weights for a vertex sum to 1.0 ...
+ for (unsigned int i = 0; i < pMesh->mNumVertices;++i)
+ {
+ if (afSum[i] && (afSum[i] <= 0.94 || afSum[i] >= 1.05)) {
+ ReportWarning("aiMesh::mVertices[%i]: bone weight sum != 1.0 (sum is %f)",i,afSum[i]);
+ }
+ }
+ }
+ else if (pMesh->mBones)
+ {
+ ReportError("aiMesh::mBones is non-null although there are no bones");
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+void ValidateDSProcess::Validate( const aiMesh* pMesh,
+ const aiBone* pBone,float* afSum)
+{
+ this->Validate(&pBone->mName);
+
+ if (!pBone->mNumWeights) {
+ ReportError("aiBone::mNumWeights is zero");
+ }
+
+ // check whether all vertices affected by this bone are valid
+ for (unsigned int i = 0; i < pBone->mNumWeights;++i)
+ {
+ if (pBone->mWeights[i].mVertexId >= pMesh->mNumVertices) {
+ ReportError("aiBone::mWeights[%i].mVertexId is out of range",i);
+ }
+ else if (!pBone->mWeights[i].mWeight || pBone->mWeights[i].mWeight > 1.0f) {
+ ReportWarning("aiBone::mWeights[%i].mWeight has an invalid value",i);
+ }
+ afSum[pBone->mWeights[i].mVertexId] += pBone->mWeights[i].mWeight;
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+void ValidateDSProcess::Validate( const aiAnimation* pAnimation)
+{
+ Validate(&pAnimation->mName);
+
+ // validate all materials
+ if (pAnimation->mNumChannels)
+ {
+ if (!pAnimation->mChannels) {
+ ReportError("aiAnimation::mChannels is NULL (aiAnimation::mNumChannels is %i)",
+ pAnimation->mNumChannels);
+ }
+ for (unsigned int i = 0; i < pAnimation->mNumChannels;++i)
+ {
+ if (!pAnimation->mChannels[i])
+ {
+ ReportError("aiAnimation::mChannels[%i] is NULL (aiAnimation::mNumChannels is %i)",
+ i, pAnimation->mNumChannels);
+ }
+ Validate(pAnimation, pAnimation->mChannels[i]);
+ }
+ }
+ else {
+ ReportError("aiAnimation::mNumChannels is 0. At least one node animation channel must be there.");
+ }
+
+ // Animation duration is allowed to be zero in cases where the anim contains only a single key frame.
+ // if (!pAnimation->mDuration)this->ReportError("aiAnimation::mDuration is zero");
+}
+
+// ------------------------------------------------------------------------------------------------
+void ValidateDSProcess::SearchForInvalidTextures(const aiMaterial* pMaterial,
+ aiTextureType type)
+{
+ const char* szType = TextureTypeToString(type);
+
+ // ****************************************************************************
+ // Search all keys of the material ...
+ // textures must be specified with ascending indices
+ // (e.g. diffuse #2 may not be specified if diffuse #1 is not there ...)
+ // ****************************************************************************
+
+ int iNumIndices = 0;
+ int iIndex = -1;
+ for (unsigned int i = 0; i < pMaterial->mNumProperties;++i) {
+ aiMaterialProperty* prop = pMaterial->mProperties[ i ];
+ ai_assert(nullptr != prop);
+ if ( !::strcmp(prop->mKey.data,"$tex.file") && prop->mSemantic == static_cast<unsigned int>(type)) {
+ iIndex = std::max(iIndex, (int) prop->mIndex);
+ ++iNumIndices;
+
+ if (aiPTI_String != prop->mType) {
+ ReportError("Material property %s is expected to be a string", prop->mKey.data);
+ }
+ }
+ }
+ if (iIndex +1 != iNumIndices) {
+ ReportError("%s #%i is set, but there are only %i %s textures",
+ szType,iIndex,iNumIndices,szType);
+ }
+ if (!iNumIndices)return;
+ std::vector<aiTextureMapping> mappings(iNumIndices);
+
+ // Now check whether all UV indices are valid ...
+ bool bNoSpecified = true;
+ for (unsigned int i = 0; i < pMaterial->mNumProperties;++i)
+ {
+ aiMaterialProperty* prop = pMaterial->mProperties[i];
+ if (prop->mSemantic != type)continue;
+
+ if ((int)prop->mIndex >= iNumIndices)
+ {
+ ReportError("Found texture property with index %i, although there "
+ "are only %i textures of type %s",
+ prop->mIndex, iNumIndices, szType);
+ }
+
+ if (!::strcmp(prop->mKey.data,"$tex.mapping")) {
+ if (aiPTI_Integer != prop->mType || prop->mDataLength < sizeof(aiTextureMapping))
+ {
+ ReportError("Material property %s%i is expected to be an integer (size is %i)",
+ prop->mKey.data,prop->mIndex,prop->mDataLength);
+ }
+ mappings[prop->mIndex] = *((aiTextureMapping*)prop->mData);
+ }
+ else if (!::strcmp(prop->mKey.data,"$tex.uvtrafo")) {
+ if (aiPTI_Float != prop->mType || prop->mDataLength < sizeof(aiUVTransform))
+ {
+ ReportError("Material property %s%i is expected to be 5 floats large (size is %i)",
+ prop->mKey.data,prop->mIndex, prop->mDataLength);
+ }
+ mappings[prop->mIndex] = *((aiTextureMapping*)prop->mData);
+ }
+ else if (!::strcmp(prop->mKey.data,"$tex.uvwsrc")) {
+ if (aiPTI_Integer != prop->mType || sizeof(int) > prop->mDataLength)
+ {
+ ReportError("Material property %s%i is expected to be an integer (size is %i)",
+ prop->mKey.data,prop->mIndex,prop->mDataLength);
+ }
+ bNoSpecified = false;
+
+ // Ignore UV indices for texture channels that are not there ...
+
+ // Get the value
+ iIndex = *((unsigned int*)prop->mData);
+
+ // Check whether there is a mesh using this material
+ // which has not enough UV channels ...
+ for (unsigned int a = 0; a < mScene->mNumMeshes;++a)
+ {
+ aiMesh* mesh = this->mScene->mMeshes[a];
+ if(mesh->mMaterialIndex == (unsigned int)i)
+ {
+ int iChannels = 0;
+ while (mesh->HasTextureCoords(iChannels))++iChannels;
+ if (iIndex >= iChannels)
+ {
+ ReportWarning("Invalid UV index: %i (key %s). Mesh %i has only %i UV channels",
+ iIndex,prop->mKey.data,a,iChannels);
+ }
+ }
+ }
+ }
+ }
+ if (bNoSpecified)
+ {
+ // Assume that all textures are using the first UV channel
+ for (unsigned int a = 0; a < mScene->mNumMeshes;++a)
+ {
+ aiMesh* mesh = mScene->mMeshes[a];
+ if(mesh->mMaterialIndex == (unsigned int)iIndex && mappings[0] == aiTextureMapping_UV)
+ {
+ if (!mesh->mTextureCoords[0])
+ {
+ // This is a special case ... it could be that the
+ // original mesh format intended the use of a special
+ // mapping here.
+ ReportWarning("UV-mapped texture, but there are no UV coords");
+ }
+ }
+ }
+ }
+}
+// ------------------------------------------------------------------------------------------------
+void ValidateDSProcess::Validate( const aiMaterial* pMaterial)
+{
+ // check whether there are material keys that are obviously not legal
+ for (unsigned int i = 0; i < pMaterial->mNumProperties;++i)
+ {
+ const aiMaterialProperty* prop = pMaterial->mProperties[i];
+ if (!prop) {
+ ReportError("aiMaterial::mProperties[%i] is NULL (aiMaterial::mNumProperties is %i)",
+ i,pMaterial->mNumProperties);
+ }
+ if (!prop->mDataLength || !prop->mData) {
+ ReportError("aiMaterial::mProperties[%i].mDataLength or "
+ "aiMaterial::mProperties[%i].mData is 0",i,i);
+ }
+ // check all predefined types
+ if (aiPTI_String == prop->mType) {
+ // FIX: strings are now stored in a less expensive way, but we can't use the
+ // validation routine for 'normal' aiStrings
+ if (prop->mDataLength < 5 || prop->mDataLength < 4 + (*reinterpret_cast<uint32_t*>(prop->mData)) + 1) {
+ ReportError("aiMaterial::mProperties[%i].mDataLength is "
+ "too small to contain a string (%i, needed: %i)",
+ i,prop->mDataLength,static_cast<int>(sizeof(aiString)));
+ }
+ if(prop->mData[prop->mDataLength-1]) {
+ ReportError("Missing null-terminator in string material property");
+ }
+ // Validate((const aiString*)prop->mData);
+ }
+ else if (aiPTI_Float == prop->mType) {
+ if (prop->mDataLength < sizeof(float)) {
+ ReportError("aiMaterial::mProperties[%i].mDataLength is "
+ "too small to contain a float (%i, needed: %i)",
+ i,prop->mDataLength, static_cast<int>(sizeof(float)));
+ }
+ }
+ else if (aiPTI_Integer == prop->mType) {
+ if (prop->mDataLength < sizeof(int)) {
+ ReportError("aiMaterial::mProperties[%i].mDataLength is "
+ "too small to contain an integer (%i, needed: %i)",
+ i,prop->mDataLength, static_cast<int>(sizeof(int)));
+ }
+ }
+ // TODO: check whether there is a key with an unknown name ...
+ }
+
+ // make some more specific tests
+ ai_real fTemp;
+ int iShading;
+ if (AI_SUCCESS == aiGetMaterialInteger( pMaterial,AI_MATKEY_SHADING_MODEL,&iShading)) {
+ switch ((aiShadingMode)iShading)
+ {
+ case aiShadingMode_Blinn:
+ case aiShadingMode_CookTorrance:
+ case aiShadingMode_Phong:
+
+ if (AI_SUCCESS != aiGetMaterialFloat(pMaterial,AI_MATKEY_SHININESS,&fTemp)) {
+ ReportWarning("A specular shading model is specified but there is no "
+ "AI_MATKEY_SHININESS key");
+ }
+ if (AI_SUCCESS == aiGetMaterialFloat(pMaterial,AI_MATKEY_SHININESS_STRENGTH,&fTemp) && !fTemp) {
+ ReportWarning("A specular shading model is specified but the value of the "
+ "AI_MATKEY_SHININESS_STRENGTH key is 0.0");
+ }
+ break;
+ default: ;
+ };
+ }
+
+ if (AI_SUCCESS == aiGetMaterialFloat( pMaterial,AI_MATKEY_OPACITY,&fTemp) && (!fTemp || fTemp > 1.01)) {
+ ReportWarning("Invalid opacity value (must be 0 < opacity < 1.0)");
+ }
+
+ // Check whether there are invalid texture keys
+ // TODO: that's a relict of the past, where texture type and index were baked
+ // into the material string ... we could do that in one single pass.
+ SearchForInvalidTextures(pMaterial,aiTextureType_DIFFUSE);
+ SearchForInvalidTextures(pMaterial,aiTextureType_SPECULAR);
+ SearchForInvalidTextures(pMaterial,aiTextureType_AMBIENT);
+ SearchForInvalidTextures(pMaterial,aiTextureType_EMISSIVE);
+ SearchForInvalidTextures(pMaterial,aiTextureType_OPACITY);
+ SearchForInvalidTextures(pMaterial,aiTextureType_SHININESS);
+ SearchForInvalidTextures(pMaterial,aiTextureType_HEIGHT);
+ SearchForInvalidTextures(pMaterial,aiTextureType_NORMALS);
+ SearchForInvalidTextures(pMaterial,aiTextureType_DISPLACEMENT);
+ SearchForInvalidTextures(pMaterial,aiTextureType_LIGHTMAP);
+ SearchForInvalidTextures(pMaterial,aiTextureType_REFLECTION);
+}
+
+// ------------------------------------------------------------------------------------------------
+void ValidateDSProcess::Validate( const aiTexture* pTexture)
+{
+ // the data section may NEVER be NULL
+ if (!pTexture->pcData) {
+ ReportError("aiTexture::pcData is NULL");
+ }
+ if (pTexture->mHeight)
+ {
+ if (!pTexture->mWidth){
+ ReportError("aiTexture::mWidth is zero (aiTexture::mHeight is %i, uncompressed texture)",
+ pTexture->mHeight);
+ }
+ }
+ else
+ {
+ if (!pTexture->mWidth) {
+ ReportError("aiTexture::mWidth is zero (compressed texture)");
+ }
+ if ('\0' != pTexture->achFormatHint[3]) {
+ ReportWarning("aiTexture::achFormatHint must be zero-terminated");
+ }
+ else if ('.' == pTexture->achFormatHint[0]) {
+ ReportWarning("aiTexture::achFormatHint should contain a file extension "
+ "without a leading dot (format hint: %s).",pTexture->achFormatHint);
+ }
+ }
+
+ const char* sz = pTexture->achFormatHint;
+ if ((sz[0] >= 'A' && sz[0] <= 'Z') ||
+ (sz[1] >= 'A' && sz[1] <= 'Z') ||
+ (sz[2] >= 'A' && sz[2] <= 'Z') ||
+ (sz[3] >= 'A' && sz[3] <= 'Z')) {
+ ReportError("aiTexture::achFormatHint contains non-lowercase letters");
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+void ValidateDSProcess::Validate( const aiAnimation* pAnimation,
+ const aiNodeAnim* pNodeAnim)
+{
+ Validate(&pNodeAnim->mNodeName);
+
+ if (!pNodeAnim->mNumPositionKeys && !pNodeAnim->mScalingKeys && !pNodeAnim->mNumRotationKeys) {
+ ReportError("Empty node animation channel");
+ }
+ // otherwise check whether one of the keys exceeds the total duration of the animation
+ if (pNodeAnim->mNumPositionKeys)
+ {
+ if (!pNodeAnim->mPositionKeys)
+ {
+ ReportError("aiNodeAnim::mPositionKeys is NULL (aiNodeAnim::mNumPositionKeys is %i)",
+ pNodeAnim->mNumPositionKeys);
+ }
+ double dLast = -10e10;
+ for (unsigned int i = 0; i < pNodeAnim->mNumPositionKeys;++i)
+ {
+ // ScenePreprocessor will compute the duration if still the default value
+ // (Aramis) Add small epsilon, comparison tended to fail if max_time == duration,
+ // seems to be due the compilers register usage/width.
+ if (pAnimation->mDuration > 0. && pNodeAnim->mPositionKeys[i].mTime > pAnimation->mDuration+0.001)
+ {
+ ReportError("aiNodeAnim::mPositionKeys[%i].mTime (%.5f) is larger "
+ "than aiAnimation::mDuration (which is %.5f)",i,
+ (float)pNodeAnim->mPositionKeys[i].mTime,
+ (float)pAnimation->mDuration);
+ }
+ if (i && pNodeAnim->mPositionKeys[i].mTime <= dLast)
+ {
+ ReportWarning("aiNodeAnim::mPositionKeys[%i].mTime (%.5f) is smaller "
+ "than aiAnimation::mPositionKeys[%i] (which is %.5f)",i,
+ (float)pNodeAnim->mPositionKeys[i].mTime,
+ i-1, (float)dLast);
+ }
+ dLast = pNodeAnim->mPositionKeys[i].mTime;
+ }
+ }
+ // rotation keys
+ if (pNodeAnim->mNumRotationKeys)
+ {
+ if (!pNodeAnim->mRotationKeys)
+ {
+ ReportError("aiNodeAnim::mRotationKeys is NULL (aiNodeAnim::mNumRotationKeys is %i)",
+ pNodeAnim->mNumRotationKeys);
+ }
+ double dLast = -10e10;
+ for (unsigned int i = 0; i < pNodeAnim->mNumRotationKeys;++i)
+ {
+ if (pAnimation->mDuration > 0. && pNodeAnim->mRotationKeys[i].mTime > pAnimation->mDuration+0.001)
+ {
+ ReportError("aiNodeAnim::mRotationKeys[%i].mTime (%.5f) is larger "
+ "than aiAnimation::mDuration (which is %.5f)",i,
+ (float)pNodeAnim->mRotationKeys[i].mTime,
+ (float)pAnimation->mDuration);
+ }
+ if (i && pNodeAnim->mRotationKeys[i].mTime <= dLast)
+ {
+ ReportWarning("aiNodeAnim::mRotationKeys[%i].mTime (%.5f) is smaller "
+ "than aiAnimation::mRotationKeys[%i] (which is %.5f)",i,
+ (float)pNodeAnim->mRotationKeys[i].mTime,
+ i-1, (float)dLast);
+ }
+ dLast = pNodeAnim->mRotationKeys[i].mTime;
+ }
+ }
+ // scaling keys
+ if (pNodeAnim->mNumScalingKeys)
+ {
+ if (!pNodeAnim->mScalingKeys) {
+ ReportError("aiNodeAnim::mScalingKeys is NULL (aiNodeAnim::mNumScalingKeys is %i)",
+ pNodeAnim->mNumScalingKeys);
+ }
+ double dLast = -10e10;
+ for (unsigned int i = 0; i < pNodeAnim->mNumScalingKeys;++i)
+ {
+ if (pAnimation->mDuration > 0. && pNodeAnim->mScalingKeys[i].mTime > pAnimation->mDuration+0.001)
+ {
+ ReportError("aiNodeAnim::mScalingKeys[%i].mTime (%.5f) is larger "
+ "than aiAnimation::mDuration (which is %.5f)",i,
+ (float)pNodeAnim->mScalingKeys[i].mTime,
+ (float)pAnimation->mDuration);
+ }
+ if (i && pNodeAnim->mScalingKeys[i].mTime <= dLast)
+ {
+ ReportWarning("aiNodeAnim::mScalingKeys[%i].mTime (%.5f) is smaller "
+ "than aiAnimation::mScalingKeys[%i] (which is %.5f)",i,
+ (float)pNodeAnim->mScalingKeys[i].mTime,
+ i-1, (float)dLast);
+ }
+ dLast = pNodeAnim->mScalingKeys[i].mTime;
+ }
+ }
+
+ if (!pNodeAnim->mNumScalingKeys && !pNodeAnim->mNumRotationKeys &&
+ !pNodeAnim->mNumPositionKeys)
+ {
+ ReportError("A node animation channel must have at least one subtrack");
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+void ValidateDSProcess::Validate( const aiNode* pNode)
+{
+ if (!pNode) {
+ ReportError("A node of the scenegraph is NULL");
+ }
+ // Validate node name string first so that it's safe to use in below expressions
+ this->Validate(&pNode->mName);
+ const char* nodeName = (&pNode->mName)->C_Str();
+ if (pNode != mScene->mRootNode && !pNode->mParent){
+ ReportError("Non-root node %s lacks a valid parent (aiNode::mParent is NULL) ", nodeName);
+ }
+
+ // validate all meshes
+ if (pNode->mNumMeshes)
+ {
+ if (!pNode->mMeshes)
+ {
+ ReportError("aiNode::mMeshes is NULL for node %s (aiNode::mNumMeshes is %i)",
+ nodeName, pNode->mNumMeshes);
+ }
+ std::vector<bool> abHadMesh;
+ abHadMesh.resize(mScene->mNumMeshes,false);
+ for (unsigned int i = 0; i < pNode->mNumMeshes;++i)
+ {
+ if (pNode->mMeshes[i] >= mScene->mNumMeshes)
+ {
+ ReportError("aiNode::mMeshes[%i] is out of range for node %s (maximum is %i)",
+ pNode->mMeshes[i], nodeName, mScene->mNumMeshes-1);
+ }
+ if (abHadMesh[pNode->mMeshes[i]])
+ {
+ ReportError("aiNode::mMeshes[%i] is already referenced by this node %s (value: %i)",
+ i, nodeName, pNode->mMeshes[i]);
+ }
+ abHadMesh[pNode->mMeshes[i]] = true;
+ }
+ }
+ if (pNode->mNumChildren)
+ {
+ if (!pNode->mChildren) {
+ ReportError("aiNode::mChildren is NULL for node %s (aiNode::mNumChildren is %i)",
+ nodeName, pNode->mNumChildren);
+ }
+ for (unsigned int i = 0; i < pNode->mNumChildren;++i) {
+ Validate(pNode->mChildren[i]);
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+void ValidateDSProcess::Validate( const aiString* pString)
+{
+ if (pString->length > MAXLEN)
+ {
+ ReportError("aiString::length is too large (%lu, maximum is %lu)",
+ pString->length,MAXLEN);
+ }
+ const char* sz = pString->data;
+ while (true)
+ {
+ if ('\0' == *sz)
+ {
+ if (pString->length != (unsigned int)(sz-pString->data)) {
+ ReportError("aiString::data is invalid: the terminal zero is at a wrong offset");
+ }
+ break;
+ }
+ else if (sz >= &pString->data[MAXLEN]) {
+ ReportError("aiString::data is invalid. There is no terminal character");
+ }
+ ++sz;
+ }
+}
diff --git a/thirdparty/assimp/code/ValidateDataStructure.h b/thirdparty/assimp/code/ValidateDataStructure.h
new file mode 100644
index 0000000000..bd21e88545
--- /dev/null
+++ b/thirdparty/assimp/code/ValidateDataStructure.h
@@ -0,0 +1,188 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file Defines a (dummy) post processing step to validate the loader's
+ * output data structure (for debugging)
+ */
+#ifndef AI_VALIDATEPROCESS_H_INC
+#define AI_VALIDATEPROCESS_H_INC
+
+#include <assimp/types.h>
+#include <assimp/material.h>
+#include "BaseProcess.h"
+
+struct aiBone;
+struct aiMesh;
+struct aiAnimation;
+struct aiNodeAnim;
+struct aiTexture;
+struct aiMaterial;
+struct aiNode;
+struct aiString;
+struct aiCamera;
+struct aiLight;
+
+namespace Assimp {
+
+// --------------------------------------------------------------------------------------
+/** Validates the whole ASSIMP scene data structure for correctness.
+ * ImportErrorException is thrown of the scene is corrupt.*/
+// --------------------------------------------------------------------------------------
+class ValidateDSProcess : public BaseProcess
+{
+public:
+
+ ValidateDSProcess();
+ ~ValidateDSProcess();
+
+public:
+ // -------------------------------------------------------------------
+ bool IsActive( unsigned int pFlags) const;
+
+ // -------------------------------------------------------------------
+ void Execute( aiScene* pScene);
+
+protected:
+
+ // -------------------------------------------------------------------
+ /** Report a validation error. This will throw an exception,
+ * control won't return.
+ * @param msg Format string for sprintf().*/
+ AI_WONT_RETURN void ReportError(const char* msg,...) AI_WONT_RETURN_SUFFIX;
+
+
+ // -------------------------------------------------------------------
+ /** Report a validation warning. This won't throw an exception,
+ * control will return to the caller.
+ * @param msg Format string for sprintf().*/
+ void ReportWarning(const char* msg,...);
+
+
+ // -------------------------------------------------------------------
+ /** Validates a mesh
+ * @param pMesh Input mesh*/
+ void Validate( const aiMesh* pMesh);
+
+ // -------------------------------------------------------------------
+ /** Validates a bone
+ * @param pMesh Input mesh
+ * @param pBone Input bone*/
+ void Validate( const aiMesh* pMesh,const aiBone* pBone,float* afSum);
+
+ // -------------------------------------------------------------------
+ /** Validates an animation
+ * @param pAnimation Input animation*/
+ void Validate( const aiAnimation* pAnimation);
+
+ // -------------------------------------------------------------------
+ /** Validates a material
+ * @param pMaterial Input material*/
+ void Validate( const aiMaterial* pMaterial);
+
+ // -------------------------------------------------------------------
+ /** Search the material data structure for invalid or corrupt
+ * texture keys.
+ * @param pMaterial Input material
+ * @param type Type of the texture*/
+ void SearchForInvalidTextures(const aiMaterial* pMaterial,
+ aiTextureType type);
+
+ // -------------------------------------------------------------------
+ /** Validates a texture
+ * @param pTexture Input texture*/
+ void Validate( const aiTexture* pTexture);
+
+ // -------------------------------------------------------------------
+ /** Validates a light source
+ * @param pLight Input light
+ */
+ void Validate( const aiLight* pLight);
+
+ // -------------------------------------------------------------------
+ /** Validates a camera
+ * @param pCamera Input camera*/
+ void Validate( const aiCamera* pCamera);
+
+ // -------------------------------------------------------------------
+ /** Validates a bone animation channel
+ * @param pAnimation Animation channel.
+ * @param pBoneAnim Input bone animation */
+ void Validate( const aiAnimation* pAnimation,
+ const aiNodeAnim* pBoneAnim);
+
+ // -------------------------------------------------------------------
+ /** Validates a node and all of its subnodes
+ * @param Node Input node*/
+ void Validate( const aiNode* pNode);
+
+ // -------------------------------------------------------------------
+ /** Validates a string
+ * @param pString Input string*/
+ void Validate( const aiString* pString);
+
+private:
+
+ // template to validate one of the aiScene::mXXX arrays
+ template <typename T>
+ inline void DoValidation(T** array, unsigned int size,
+ const char* firstName, const char* secondName);
+
+ // extended version: checks whether T::mName occurs twice
+ template <typename T>
+ inline void DoValidationEx(T** array, unsigned int size,
+ const char* firstName, const char* secondName);
+
+ // extension to the first template which does also search
+ // the nodegraph for an item with the same name
+ template <typename T>
+ inline void DoValidationWithNameCheck(T** array, unsigned int size,
+ const char* firstName, const char* secondName);
+
+ aiScene* mScene;
+};
+
+
+
+
+} // end of namespace Assimp
+
+#endif // AI_VALIDATEPROCESS_H_INC
diff --git a/thirdparty/assimp/code/Version.cpp b/thirdparty/assimp/code/Version.cpp
new file mode 100644
index 0000000000..0381037ff1
--- /dev/null
+++ b/thirdparty/assimp/code/Version.cpp
@@ -0,0 +1,185 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+// Actually just a dummy, used by the compiler to build the precompiled header.
+
+#include <assimp/version.h>
+#include <assimp/scene.h>
+#include "ScenePrivate.h"
+
+static const unsigned int MajorVersion = 4;
+static const unsigned int MinorVersion = 1;
+
+// --------------------------------------------------------------------------------
+// Legal information string - don't remove this.
+static const char* LEGAL_INFORMATION =
+
+"Open Asset Import Library (Assimp).\n"
+"A free C/C++ library to import various 3D file formats into applications\n\n"
+
+"(c) 2008-2017, assimp team\n"
+"License under the terms and conditions of the 3-clause BSD license\n"
+"http://assimp.sourceforge.net\n"
+;
+
+// ------------------------------------------------------------------------------------------------
+// Get legal string
+ASSIMP_API const char* aiGetLegalString () {
+ return LEGAL_INFORMATION;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Get Assimp minor version
+ASSIMP_API unsigned int aiGetVersionMinor () {
+ return MinorVersion;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Get Assimp major version
+ASSIMP_API unsigned int aiGetVersionMajor () {
+ return MajorVersion;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Get flags used for compilation
+ASSIMP_API unsigned int aiGetCompileFlags () {
+
+ unsigned int flags = 0;
+
+#ifdef ASSIMP_BUILD_BOOST_WORKAROUND
+ flags |= ASSIMP_CFLAGS_NOBOOST;
+#endif
+#ifdef ASSIMP_BUILD_SINGLETHREADED
+ flags |= ASSIMP_CFLAGS_SINGLETHREADED;
+#endif
+#ifdef ASSIMP_BUILD_DEBUG
+ flags |= ASSIMP_CFLAGS_DEBUG;
+#endif
+#ifdef ASSIMP_BUILD_DLL_EXPORT
+ flags |= ASSIMP_CFLAGS_SHARED;
+#endif
+#ifdef _STLPORT_VERSION
+ flags |= ASSIMP_CFLAGS_STLPORT;
+#endif
+
+ return flags;
+}
+
+// include current build revision, which is even updated from time to time -- :-)
+#include "revision.h"
+
+// ------------------------------------------------------------------------------------------------
+ASSIMP_API unsigned int aiGetVersionRevision() {
+ return GitVersion;
+}
+
+ASSIMP_API const char *aiGetBranchName() {
+ return GitBranch;
+}
+
+// ------------------------------------------------------------------------------------------------
+ASSIMP_API aiScene::aiScene()
+: mFlags(0)
+, mRootNode(nullptr)
+, mNumMeshes(0)
+, mMeshes(nullptr)
+, mNumMaterials(0)
+, mMaterials(nullptr)
+, mNumAnimations(0)
+, mAnimations(nullptr)
+, mNumTextures(0)
+, mTextures(nullptr)
+, mNumLights(0)
+, mLights(nullptr)
+, mNumCameras(0)
+, mCameras(nullptr)
+, mMetaData(nullptr)
+, mPrivate(new Assimp::ScenePrivateData()) {
+ // empty
+}
+
+// ------------------------------------------------------------------------------------------------
+ASSIMP_API aiScene::~aiScene() {
+ // delete all sub-objects recursively
+ delete mRootNode;
+
+ // To make sure we won't crash if the data is invalid it's
+ // much better to check whether both mNumXXX and mXXX are
+ // valid instead of relying on just one of them.
+ if (mNumMeshes && mMeshes)
+ for( unsigned int a = 0; a < mNumMeshes; a++)
+ delete mMeshes[a];
+ delete [] mMeshes;
+
+ if (mNumMaterials && mMaterials) {
+ for (unsigned int a = 0; a < mNumMaterials; ++a ) {
+ delete mMaterials[ a ];
+ }
+ }
+ delete [] mMaterials;
+
+ if (mNumAnimations && mAnimations)
+ for( unsigned int a = 0; a < mNumAnimations; a++)
+ delete mAnimations[a];
+ delete [] mAnimations;
+
+ if (mNumTextures && mTextures)
+ for( unsigned int a = 0; a < mNumTextures; a++)
+ delete mTextures[a];
+ delete [] mTextures;
+
+ if (mNumLights && mLights)
+ for( unsigned int a = 0; a < mNumLights; a++)
+ delete mLights[a];
+ delete [] mLights;
+
+ if (mNumCameras && mCameras)
+ for( unsigned int a = 0; a < mNumCameras; a++)
+ delete mCameras[a];
+ delete [] mCameras;
+
+ aiMetadata::Dealloc(mMetaData);
+ mMetaData = nullptr;
+
+ delete static_cast<Assimp::ScenePrivateData*>( mPrivate );
+}
+
diff --git a/thirdparty/assimp/code/VertexTriangleAdjacency.cpp b/thirdparty/assimp/code/VertexTriangleAdjacency.cpp
new file mode 100644
index 0000000000..7cfd1a3505
--- /dev/null
+++ b/thirdparty/assimp/code/VertexTriangleAdjacency.cpp
@@ -0,0 +1,134 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file Implementation of the VertexTriangleAdjacency helper class
+ */
+
+// internal headers
+#include "VertexTriangleAdjacency.h"
+#include <assimp/mesh.h>
+
+using namespace Assimp;
+
+// ------------------------------------------------------------------------------------------------
+VertexTriangleAdjacency::VertexTriangleAdjacency(aiFace *pcFaces,
+ unsigned int iNumFaces,
+ unsigned int iNumVertices /*= 0*/,
+ bool bComputeNumTriangles /*= false*/)
+{
+ // compute the number of referenced vertices if it wasn't specified by the caller
+ const aiFace* const pcFaceEnd = pcFaces + iNumFaces;
+ if (!iNumVertices) {
+ for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace) {
+ ai_assert( nullptr != pcFace );
+ ai_assert(3 == pcFace->mNumIndices);
+ iNumVertices = std::max(iNumVertices,pcFace->mIndices[0]);
+ iNumVertices = std::max(iNumVertices,pcFace->mIndices[1]);
+ iNumVertices = std::max(iNumVertices,pcFace->mIndices[2]);
+ }
+ }
+
+ mNumVertices = iNumVertices;
+
+ unsigned int* pi;
+
+ // allocate storage
+ if (bComputeNumTriangles) {
+ pi = mLiveTriangles = new unsigned int[iNumVertices+1];
+ ::memset(mLiveTriangles,0,sizeof(unsigned int)*(iNumVertices+1));
+ mOffsetTable = new unsigned int[iNumVertices+2]+1;
+ } else {
+ pi = mOffsetTable = new unsigned int[iNumVertices+2]+1;
+ ::memset(mOffsetTable,0,sizeof(unsigned int)*(iNumVertices+1));
+ mLiveTriangles = NULL; // important, otherwise the d'tor would crash
+ }
+
+ // get a pointer to the end of the buffer
+ unsigned int* piEnd = pi+iNumVertices;
+ *piEnd++ = 0u;
+
+ // first pass: compute the number of faces referencing each vertex
+ for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace)
+ {
+ unsigned nind = pcFace->mNumIndices;
+ unsigned * ind = pcFace->mIndices;
+ if (nind > 0) pi[ind[0]]++;
+ if (nind > 1) pi[ind[1]]++;
+ if (nind > 2) pi[ind[2]]++;
+ }
+
+ // second pass: compute the final offset table
+ unsigned int iSum = 0;
+ unsigned int* piCurOut = this->mOffsetTable;
+ for (unsigned int* piCur = pi; piCur != piEnd;++piCur,++piCurOut) {
+
+ unsigned int iLastSum = iSum;
+ iSum += *piCur;
+ *piCurOut = iLastSum;
+ }
+ pi = this->mOffsetTable;
+
+ // third pass: compute the final table
+ this->mAdjacencyTable = new unsigned int[iSum];
+ iSum = 0;
+ for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace,++iSum) {
+ unsigned nind = pcFace->mNumIndices;
+ unsigned * ind = pcFace->mIndices;
+
+ if (nind > 0) mAdjacencyTable[pi[ind[0]]++] = iSum;
+ if (nind > 1) mAdjacencyTable[pi[ind[1]]++] = iSum;
+ if (nind > 2) mAdjacencyTable[pi[ind[2]]++] = iSum;
+ }
+ // fourth pass: undo the offset computations made during the third pass
+ // We could do this in a separate buffer, but this would be TIMES slower.
+ --mOffsetTable;
+ *mOffsetTable = 0u;
+}
+// ------------------------------------------------------------------------------------------------
+VertexTriangleAdjacency::~VertexTriangleAdjacency()
+{
+ // delete allocated storage
+ delete[] mOffsetTable;
+ delete[] mAdjacencyTable;
+ delete[] mLiveTriangles;
+}
diff --git a/thirdparty/assimp/code/VertexTriangleAdjacency.h b/thirdparty/assimp/code/VertexTriangleAdjacency.h
new file mode 100644
index 0000000000..f3be47612d
--- /dev/null
+++ b/thirdparty/assimp/code/VertexTriangleAdjacency.h
@@ -0,0 +1,117 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file Defines a helper class to compute a vertex-triangle adjacency map */
+#ifndef AI_VTADJACENCY_H_INC
+#define AI_VTADJACENCY_H_INC
+
+#include "BaseProcess.h"
+#include <assimp/types.h>
+#include <assimp/ai_assert.h>
+
+struct aiMesh;
+struct aiFace;
+
+namespace Assimp {
+
+// --------------------------------------------------------------------------------------------
+/** @brief The VertexTriangleAdjacency class computes a vertex-triangle
+ * adjacency map from a given index buffer.
+ *
+ * @note Although it is called #VertexTriangleAdjacency, the current version does also
+ * support arbitrary polygons. */
+// --------------------------------------------------------------------------------------------
+class ASSIMP_API VertexTriangleAdjacency {
+public:
+ // ----------------------------------------------------------------------------
+ /** @brief Construction from an existing index buffer
+ * @param pcFaces Index buffer
+ * @param iNumFaces Number of faces in the buffer
+ * @param iNumVertices Number of referenced vertices. This value
+ * is computed automatically if 0 is specified.
+ * @param bComputeNumTriangles If you want the class to compute
+ * a list containing the number of referenced triangles per vertex
+ * per vertex - pass true. */
+ VertexTriangleAdjacency(aiFace* pcFaces,unsigned int iNumFaces,
+ unsigned int iNumVertices = 0,
+ bool bComputeNumTriangles = true);
+
+ // ----------------------------------------------------------------------------
+ /** @brief Destructor */
+ ~VertexTriangleAdjacency();
+
+ // ----------------------------------------------------------------------------
+ /** @brief Get all triangles adjacent to a vertex
+ * @param iVertIndex Index of the vertex
+ * @return A pointer to the adjacency list. */
+ unsigned int* GetAdjacentTriangles(unsigned int iVertIndex) const {
+ ai_assert(iVertIndex < mNumVertices);
+ return &mAdjacencyTable[ mOffsetTable[iVertIndex]];
+ }
+
+ // ----------------------------------------------------------------------------
+ /** @brief Get the number of triangles that are referenced by
+ * a vertex. This function returns a reference that can be modified
+ * @param iVertIndex Index of the vertex
+ * @return Number of referenced triangles */
+ unsigned int& GetNumTrianglesPtr(unsigned int iVertIndex) {
+ ai_assert( iVertIndex < mNumVertices );
+ ai_assert( nullptr != mLiveTriangles );
+ return mLiveTriangles[iVertIndex];
+ }
+
+ //! Offset table
+ unsigned int* mOffsetTable;
+
+ //! Adjacency table
+ unsigned int* mAdjacencyTable;
+
+ //! Table containing the number of referenced triangles per vertex
+ unsigned int* mLiveTriangles;
+
+ //! Debug: Number of referenced vertices
+ unsigned int mNumVertices;
+};
+
+} //! ns Assimp
+
+#endif // !! AI_VTADJACENCY_H_INC
diff --git a/thirdparty/assimp/code/Win32DebugLogStream.h b/thirdparty/assimp/code/Win32DebugLogStream.h
new file mode 100644
index 0000000000..a6063a261e
--- /dev/null
+++ b/thirdparty/assimp/code/Win32DebugLogStream.h
@@ -0,0 +1,95 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file Win32DebugLogStream.h
+* @brief Implementation of Win32DebugLogStream
+*/
+#ifndef AI_WIN32DEBUGLOGSTREAM_H_INC
+#define AI_WIN32DEBUGLOGSTREAM_H_INC
+
+#ifdef _WIN32
+
+#include <assimp/LogStream.hpp>
+#include "windows.h"
+
+namespace Assimp {
+
+// ---------------------------------------------------------------------------
+/** @class Win32DebugLogStream
+ * @brief Logs into the debug stream from win32.
+ */
+class Win32DebugLogStream : public LogStream {
+public:
+ /** @brief Default constructor */
+ Win32DebugLogStream();
+
+ /** @brief Destructor */
+ ~Win32DebugLogStream();
+
+ /** @brief Writer */
+ void write(const char* messgae);
+};
+
+// ---------------------------------------------------------------------------
+inline
+Win32DebugLogStream::Win32DebugLogStream(){
+ // empty
+}
+
+// ---------------------------------------------------------------------------
+inline
+Win32DebugLogStream::~Win32DebugLogStream(){
+ // empty
+}
+
+// ---------------------------------------------------------------------------
+inline
+void Win32DebugLogStream::write(const char* message) {
+ ::OutputDebugStringA( message);
+}
+
+// ---------------------------------------------------------------------------
+} // Namespace Assimp
+
+#endif // ! _WIN32
+#endif // guard
diff --git a/thirdparty/assimp/code/revision.h b/thirdparty/assimp/code/revision.h
new file mode 100644
index 0000000000..88872aef22
--- /dev/null
+++ b/thirdparty/assimp/code/revision.h
@@ -0,0 +1,7 @@
+#ifndef ASSIMP_REVISION_H_INC
+#define ASSIMP_REVISION_H_INC
+
+#define GitVersion 0x00000000
+#define GitBranch "master"
+
+#endif // ASSIMP_REVISION_H_INC
diff --git a/thirdparty/assimp/code/scene.cpp b/thirdparty/assimp/code/scene.cpp
new file mode 100644
index 0000000000..2acb348d81
--- /dev/null
+++ b/thirdparty/assimp/code/scene.cpp
@@ -0,0 +1,140 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+#include <assimp/scene.h>
+
+aiNode::aiNode()
+: mName("")
+, mParent(NULL)
+, mNumChildren(0)
+, mChildren(NULL)
+, mNumMeshes(0)
+, mMeshes(NULL)
+, mMetaData(NULL) {
+ // empty
+}
+
+aiNode::aiNode(const std::string& name)
+: mName(name)
+, mParent(NULL)
+, mNumChildren(0)
+, mChildren(NULL)
+, mNumMeshes(0)
+, mMeshes(NULL)
+, mMetaData(NULL) {
+ // empty
+}
+
+/** Destructor */
+aiNode::~aiNode() {
+ // delete all children recursively
+ // to make sure we won't crash if the data is invalid ...
+ if (mChildren && mNumChildren)
+ {
+ for (unsigned int a = 0; a < mNumChildren; a++)
+ delete mChildren[a];
+ }
+ delete[] mChildren;
+ delete[] mMeshes;
+ delete mMetaData;
+}
+
+const aiNode *aiNode::FindNode(const char* name) const {
+ if (nullptr == name) {
+ return nullptr;
+ }
+ if (!::strcmp(mName.data, name)) {
+ return this;
+ }
+ for (unsigned int i = 0; i < mNumChildren; ++i) {
+ const aiNode* const p = mChildren[i]->FindNode(name);
+ if (p) {
+ return p;
+ }
+ }
+ // there is definitely no sub-node with this name
+ return nullptr;
+}
+
+aiNode *aiNode::FindNode(const char* name) {
+ if (!::strcmp(mName.data, name))return this;
+ for (unsigned int i = 0; i < mNumChildren; ++i)
+ {
+ aiNode* const p = mChildren[i]->FindNode(name);
+ if (p) {
+ return p;
+ }
+ }
+ // there is definitely no sub-node with this name
+ return nullptr;
+}
+
+void aiNode::addChildren(unsigned int numChildren, aiNode **children) {
+ if (nullptr == children || 0 == numChildren) {
+ return;
+ }
+
+ for (unsigned int i = 0; i < numChildren; i++) {
+ aiNode *child = children[i];
+ if (nullptr != child) {
+ child->mParent = this;
+ }
+ }
+
+ if (mNumChildren > 0) {
+ aiNode **tmp = new aiNode*[mNumChildren];
+ ::memcpy(tmp, mChildren, sizeof(aiNode*) * mNumChildren);
+ delete[] mChildren;
+ mChildren = new aiNode*[mNumChildren + numChildren];
+ ::memcpy(mChildren, tmp, sizeof(aiNode*) * mNumChildren);
+ ::memcpy(&mChildren[mNumChildren], children, sizeof(aiNode*)* numChildren);
+ mNumChildren += numChildren;
+ delete[] tmp;
+ }
+ else {
+ mChildren = new aiNode*[numChildren];
+ for (unsigned int i = 0; i < numChildren; i++) {
+ mChildren[i] = children[i];
+ }
+ mNumChildren = numChildren;
+ }
+}
diff --git a/thirdparty/assimp/code/simd.cpp b/thirdparty/assimp/code/simd.cpp
new file mode 100644
index 0000000000..04615f408e
--- /dev/null
+++ b/thirdparty/assimp/code/simd.cpp
@@ -0,0 +1,79 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+#include "simd.h"
+
+namespace Assimp {
+
+bool CPUSupportsSSE2() {
+#if defined(__x86_64__) || defined(_M_X64)
+ //* x86_64 always has SSE2 instructions */
+ return true;
+#elif defined(__GNUC__) && defined(i386)
+ // for GCC x86 we check cpuid
+ unsigned int d;
+ __asm__(
+ "pushl %%ebx\n\t"
+ "cpuid\n\t"
+ "popl %%ebx\n\t"
+ : "=d" ( d )
+ :"a" ( 1 ) );
+ return ( d & 0x04000000 ) != 0;
+#elif (defined(_MSC_VER) && defined(_M_IX86))
+ // also check cpuid for MSVC x86
+ unsigned int d;
+ __asm {
+ xor eax, eax
+ inc eax
+ push ebx
+ cpuid
+ pop ebx
+ mov d, edx
+ }
+ return ( d & 0x04000000 ) != 0;
+#else
+ return false;
+#endif
+}
+
+
+} // Namespace Assimp
diff --git a/thirdparty/assimp/code/simd.h b/thirdparty/assimp/code/simd.h
new file mode 100644
index 0000000000..3eecdd4581
--- /dev/null
+++ b/thirdparty/assimp/code/simd.h
@@ -0,0 +1,53 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+#pragma once
+
+#include <assimp/defs.h>
+
+namespace Assimp {
+
+/// @brief Checks if the platform supports SSE2 optimization
+/// @return true, if SSE2 is supported. false if SSE2 is not supported.
+bool ASSIMP_API CPUSupportsSSE2();
+
+} // Namespace Assimp
diff --git a/thirdparty/assimp/contrib/utf8cpp/source/utf8.h b/thirdparty/assimp/contrib/utf8cpp/source/utf8.h
new file mode 100644
index 0000000000..82b13f59f9
--- /dev/null
+++ b/thirdparty/assimp/contrib/utf8cpp/source/utf8.h
@@ -0,0 +1,34 @@
+// Copyright 2006 Nemanja Trifunovic
+
+/*
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+*/
+
+
+#ifndef UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731
+#define UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731
+
+#include "utf8/checked.h"
+#include "utf8/unchecked.h"
+
+#endif // header guard
diff --git a/thirdparty/assimp/contrib/utf8cpp/source/utf8/checked.h b/thirdparty/assimp/contrib/utf8cpp/source/utf8/checked.h
new file mode 100644
index 0000000000..1331155138
--- /dev/null
+++ b/thirdparty/assimp/contrib/utf8cpp/source/utf8/checked.h
@@ -0,0 +1,327 @@
+// Copyright 2006 Nemanja Trifunovic
+
+/*
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+*/
+
+
+#ifndef UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+#define UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+
+#include "core.h"
+#include <stdexcept>
+
+namespace utf8
+{
+ // Base for the exceptions that may be thrown from the library
+ class exception : public ::std::exception {
+ };
+
+ // Exceptions that may be thrown from the library functions.
+ class invalid_code_point : public exception {
+ uint32_t cp;
+ public:
+ invalid_code_point(uint32_t cp) : cp(cp) {}
+ virtual const char* what() const throw() { return "Invalid code point"; }
+ uint32_t code_point() const {return cp;}
+ };
+
+ class invalid_utf8 : public exception {
+ uint8_t u8;
+ public:
+ invalid_utf8 (uint8_t u) : u8(u) {}
+ virtual const char* what() const throw() { return "Invalid UTF-8"; }
+ uint8_t utf8_octet() const {return u8;}
+ };
+
+ class invalid_utf16 : public exception {
+ uint16_t u16;
+ public:
+ invalid_utf16 (uint16_t u) : u16(u) {}
+ virtual const char* what() const throw() { return "Invalid UTF-16"; }
+ uint16_t utf16_word() const {return u16;}
+ };
+
+ class not_enough_room : public exception {
+ public:
+ virtual const char* what() const throw() { return "Not enough space"; }
+ };
+
+ /// The library API - functions intended to be called by the users
+
+ template <typename octet_iterator>
+ octet_iterator append(uint32_t cp, octet_iterator result)
+ {
+ if (!utf8::internal::is_code_point_valid(cp))
+ throw invalid_code_point(cp);
+
+ if (cp < 0x80) // one octet
+ *(result++) = static_cast<uint8_t>(cp);
+ else if (cp < 0x800) { // two octets
+ *(result++) = static_cast<uint8_t>((cp >> 6) | 0xc0);
+ *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
+ }
+ else if (cp < 0x10000) { // three octets
+ *(result++) = static_cast<uint8_t>((cp >> 12) | 0xe0);
+ *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
+ *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
+ }
+ else { // four octets
+ *(result++) = static_cast<uint8_t>((cp >> 18) | 0xf0);
+ *(result++) = static_cast<uint8_t>(((cp >> 12) & 0x3f) | 0x80);
+ *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
+ *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
+ }
+ return result;
+ }
+
+ template <typename octet_iterator, typename output_iterator>
+ output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement)
+ {
+ while (start != end) {
+ octet_iterator sequence_start = start;
+ internal::utf_error err_code = utf8::internal::validate_next(start, end);
+ switch (err_code) {
+ case internal::UTF8_OK :
+ for (octet_iterator it = sequence_start; it != start; ++it)
+ *out++ = *it;
+ break;
+ case internal::NOT_ENOUGH_ROOM:
+ throw not_enough_room();
+ case internal::INVALID_LEAD:
+ out = utf8::append (replacement, out);
+ ++start;
+ break;
+ case internal::INCOMPLETE_SEQUENCE:
+ case internal::OVERLONG_SEQUENCE:
+ case internal::INVALID_CODE_POINT:
+ out = utf8::append (replacement, out);
+ ++start;
+ // just one replacement mark for the sequence
+ while (start != end && utf8::internal::is_trail(*start))
+ ++start;
+ break;
+ }
+ }
+ return out;
+ }
+
+ template <typename octet_iterator, typename output_iterator>
+ inline output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out)
+ {
+ static const uint32_t replacement_marker = utf8::internal::mask16(0xfffd);
+ return utf8::replace_invalid(start, end, out, replacement_marker);
+ }
+
+ template <typename octet_iterator>
+ uint32_t next(octet_iterator& it, octet_iterator end)
+ {
+ uint32_t cp = 0;
+ internal::utf_error err_code = utf8::internal::validate_next(it, end, cp);
+ switch (err_code) {
+ case internal::UTF8_OK :
+ break;
+ case internal::NOT_ENOUGH_ROOM :
+ throw not_enough_room();
+ case internal::INVALID_LEAD :
+ case internal::INCOMPLETE_SEQUENCE :
+ case internal::OVERLONG_SEQUENCE :
+ throw invalid_utf8(*it);
+ case internal::INVALID_CODE_POINT :
+ throw invalid_code_point(cp);
+ }
+ return cp;
+ }
+
+ template <typename octet_iterator>
+ uint32_t peek_next(octet_iterator it, octet_iterator end)
+ {
+ return utf8::next(it, end);
+ }
+
+ template <typename octet_iterator>
+ uint32_t prior(octet_iterator& it, octet_iterator start)
+ {
+ // can't do much if it == start
+ if (it == start)
+ throw not_enough_room();
+
+ octet_iterator end = it;
+ // Go back until we hit either a lead octet or start
+ while (utf8::internal::is_trail(*(--it)))
+ if (it == start)
+ throw invalid_utf8(*it); // error - no lead byte in the sequence
+ return utf8::peek_next(it, end);
+ }
+
+ /// Deprecated in versions that include "prior"
+ template <typename octet_iterator>
+ uint32_t previous(octet_iterator& it, octet_iterator pass_start)
+ {
+ octet_iterator end = it;
+ while (utf8::internal::is_trail(*(--it)))
+ if (it == pass_start)
+ throw invalid_utf8(*it); // error - no lead byte in the sequence
+ octet_iterator temp = it;
+ return utf8::next(temp, end);
+ }
+
+ template <typename octet_iterator, typename distance_type>
+ void advance (octet_iterator& it, distance_type n, octet_iterator end)
+ {
+ for (distance_type i = 0; i < n; ++i)
+ utf8::next(it, end);
+ }
+
+ template <typename octet_iterator>
+ typename std::iterator_traits<octet_iterator>::difference_type
+ distance (octet_iterator first, octet_iterator last)
+ {
+ typename std::iterator_traits<octet_iterator>::difference_type dist;
+ for (dist = 0; first < last; ++dist)
+ utf8::next(first, last);
+ return dist;
+ }
+
+ template <typename u16bit_iterator, typename octet_iterator>
+ octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result)
+ {
+ while (start != end) {
+ uint32_t cp = utf8::internal::mask16(*start++);
+ // Take care of surrogate pairs first
+ if (utf8::internal::is_lead_surrogate(cp)) {
+ if (start != end) {
+ uint32_t trail_surrogate = utf8::internal::mask16(*start++);
+ if (utf8::internal::is_trail_surrogate(trail_surrogate))
+ cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET;
+ else
+ throw invalid_utf16(static_cast<uint16_t>(trail_surrogate));
+ }
+ else
+ throw invalid_utf16(static_cast<uint16_t>(cp));
+
+ }
+ // Lone trail surrogate
+ else if (utf8::internal::is_trail_surrogate(cp))
+ throw invalid_utf16(static_cast<uint16_t>(cp));
+
+ result = utf8::append(cp, result);
+ }
+ return result;
+ }
+
+ template <typename u16bit_iterator, typename octet_iterator>
+ u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result)
+ {
+ while (start != end) {
+ uint32_t cp = utf8::next(start, end);
+ if (cp > 0xffff) { //make a surrogate pair
+ *result++ = static_cast<uint16_t>((cp >> 10) + internal::LEAD_OFFSET);
+ *result++ = static_cast<uint16_t>((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN);
+ }
+ else
+ *result++ = static_cast<uint16_t>(cp);
+ }
+ return result;
+ }
+
+ template <typename octet_iterator, typename u32bit_iterator>
+ octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result)
+ {
+ while (start != end)
+ result = utf8::append(*(start++), result);
+
+ return result;
+ }
+
+ template <typename octet_iterator, typename u32bit_iterator>
+ u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result)
+ {
+ while (start != end)
+ (*result++) = utf8::next(start, end);
+
+ return result;
+ }
+
+ // The iterator class
+ template <typename octet_iterator>
+ class iterator : public std::iterator <std::bidirectional_iterator_tag, uint32_t> {
+ octet_iterator it;
+ octet_iterator range_start;
+ octet_iterator range_end;
+ public:
+ iterator () {}
+ explicit iterator (const octet_iterator& octet_it,
+ const octet_iterator& range_start,
+ const octet_iterator& range_end) :
+ it(octet_it), range_start(range_start), range_end(range_end)
+ {
+ if (it < range_start || it > range_end)
+ throw std::out_of_range("Invalid utf-8 iterator position");
+ }
+ // the default "big three" are OK
+ octet_iterator base () const { return it; }
+ uint32_t operator * () const
+ {
+ octet_iterator temp = it;
+ return utf8::next(temp, range_end);
+ }
+ bool operator == (const iterator& rhs) const
+ {
+ if (range_start != rhs.range_start || range_end != rhs.range_end)
+ throw std::logic_error("Comparing utf-8 iterators defined with different ranges");
+ return (it == rhs.it);
+ }
+ bool operator != (const iterator& rhs) const
+ {
+ return !(operator == (rhs));
+ }
+ iterator& operator ++ ()
+ {
+ utf8::next(it, range_end);
+ return *this;
+ }
+ iterator operator ++ (int)
+ {
+ iterator temp = *this;
+ utf8::next(it, range_end);
+ return temp;
+ }
+ iterator& operator -- ()
+ {
+ utf8::prior(it, range_start);
+ return *this;
+ }
+ iterator operator -- (int)
+ {
+ iterator temp = *this;
+ utf8::prior(it, range_start);
+ return temp;
+ }
+ }; // class iterator
+
+} // namespace utf8
+
+#endif //header guard
+
+
diff --git a/thirdparty/assimp/contrib/utf8cpp/source/utf8/core.h b/thirdparty/assimp/contrib/utf8cpp/source/utf8/core.h
new file mode 100644
index 0000000000..693d388c07
--- /dev/null
+++ b/thirdparty/assimp/contrib/utf8cpp/source/utf8/core.h
@@ -0,0 +1,329 @@
+// Copyright 2006 Nemanja Trifunovic
+
+/*
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+*/
+
+
+#ifndef UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+#define UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+
+#include <iterator>
+
+namespace utf8
+{
+ // The typedefs for 8-bit, 16-bit and 32-bit unsigned integers
+ // You may need to change them to match your system.
+ // These typedefs have the same names as ones from cstdint, or boost/cstdint
+ typedef unsigned char uint8_t;
+ typedef unsigned short uint16_t;
+ typedef unsigned int uint32_t;
+
+// Helper code - not intended to be directly called by the library users. May be changed at any time
+namespace internal
+{
+ // Unicode constants
+ // Leading (high) surrogates: 0xd800 - 0xdbff
+ // Trailing (low) surrogates: 0xdc00 - 0xdfff
+ const uint16_t LEAD_SURROGATE_MIN = 0xd800u;
+ const uint16_t LEAD_SURROGATE_MAX = 0xdbffu;
+ const uint16_t TRAIL_SURROGATE_MIN = 0xdc00u;
+ const uint16_t TRAIL_SURROGATE_MAX = 0xdfffu;
+ const uint16_t LEAD_OFFSET = LEAD_SURROGATE_MIN - (0x10000 >> 10);
+ const uint32_t SURROGATE_OFFSET = 0x10000u - (LEAD_SURROGATE_MIN << 10) - TRAIL_SURROGATE_MIN;
+
+ // Maximum valid value for a Unicode code point
+ const uint32_t CODE_POINT_MAX = 0x0010ffffu;
+
+ template<typename octet_type>
+ inline uint8_t mask8(octet_type oc)
+ {
+ return static_cast<uint8_t>(0xff & oc);
+ }
+ template<typename u16_type>
+ inline uint16_t mask16(u16_type oc)
+ {
+ return static_cast<uint16_t>(0xffff & oc);
+ }
+ template<typename octet_type>
+ inline bool is_trail(octet_type oc)
+ {
+ return ((utf8::internal::mask8(oc) >> 6) == 0x2);
+ }
+
+ template <typename u16>
+ inline bool is_lead_surrogate(u16 cp)
+ {
+ return (cp >= LEAD_SURROGATE_MIN && cp <= LEAD_SURROGATE_MAX);
+ }
+
+ template <typename u16>
+ inline bool is_trail_surrogate(u16 cp)
+ {
+ return (cp >= TRAIL_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX);
+ }
+
+ template <typename u16>
+ inline bool is_surrogate(u16 cp)
+ {
+ return (cp >= LEAD_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX);
+ }
+
+ template <typename u32>
+ inline bool is_code_point_valid(u32 cp)
+ {
+ return (cp <= CODE_POINT_MAX && !utf8::internal::is_surrogate(cp));
+ }
+
+ template <typename octet_iterator>
+ inline typename std::iterator_traits<octet_iterator>::difference_type
+ sequence_length(octet_iterator lead_it)
+ {
+ uint8_t lead = utf8::internal::mask8(*lead_it);
+ if (lead < 0x80)
+ return 1;
+ else if ((lead >> 5) == 0x6)
+ return 2;
+ else if ((lead >> 4) == 0xe)
+ return 3;
+ else if ((lead >> 3) == 0x1e)
+ return 4;
+ else
+ return 0;
+ }
+
+ template <typename octet_difference_type>
+ inline bool is_overlong_sequence(uint32_t cp, octet_difference_type length)
+ {
+ if (cp < 0x80) {
+ if (length != 1)
+ return true;
+ }
+ else if (cp < 0x800) {
+ if (length != 2)
+ return true;
+ }
+ else if (cp < 0x10000) {
+ if (length != 3)
+ return true;
+ }
+
+ return false;
+ }
+
+ enum utf_error {UTF8_OK, NOT_ENOUGH_ROOM, INVALID_LEAD, INCOMPLETE_SEQUENCE, OVERLONG_SEQUENCE, INVALID_CODE_POINT};
+
+ /// Helper for get_sequence_x
+ template <typename octet_iterator>
+ utf_error increase_safely(octet_iterator& it, octet_iterator end)
+ {
+ if (++it == end)
+ return NOT_ENOUGH_ROOM;
+
+ if (!utf8::internal::is_trail(*it))
+ return INCOMPLETE_SEQUENCE;
+
+ return UTF8_OK;
+ }
+
+ #define UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(IT, END) {utf_error ret = increase_safely(IT, END); if (ret != UTF8_OK) return ret;}
+
+ /// get_sequence_x functions decode utf-8 sequences of the length x
+ template <typename octet_iterator>
+ utf_error get_sequence_1(octet_iterator& it, octet_iterator end, uint32_t& code_point)
+ {
+ if (it == end)
+ return NOT_ENOUGH_ROOM;
+
+ code_point = utf8::internal::mask8(*it);
+
+ return UTF8_OK;
+ }
+
+ template <typename octet_iterator>
+ utf_error get_sequence_2(octet_iterator& it, octet_iterator end, uint32_t& code_point)
+ {
+ if (it == end)
+ return NOT_ENOUGH_ROOM;
+
+ code_point = utf8::internal::mask8(*it);
+
+ UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+ code_point = ((code_point << 6) & 0x7ff) + ((*it) & 0x3f);
+
+ return UTF8_OK;
+ }
+
+ template <typename octet_iterator>
+ utf_error get_sequence_3(octet_iterator& it, octet_iterator end, uint32_t& code_point)
+ {
+ if (it == end)
+ return NOT_ENOUGH_ROOM;
+
+ code_point = utf8::internal::mask8(*it);
+
+ UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+ code_point = ((code_point << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff);
+
+ UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+ code_point += (*it) & 0x3f;
+
+ return UTF8_OK;
+ }
+
+ template <typename octet_iterator>
+ utf_error get_sequence_4(octet_iterator& it, octet_iterator end, uint32_t& code_point)
+ {
+ if (it == end)
+ return NOT_ENOUGH_ROOM;
+
+ code_point = utf8::internal::mask8(*it);
+
+ UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+ code_point = ((code_point << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff);
+
+ UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+ code_point += (utf8::internal::mask8(*it) << 6) & 0xfff;
+
+ UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+ code_point += (*it) & 0x3f;
+
+ return UTF8_OK;
+ }
+
+ #undef UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR
+
+ template <typename octet_iterator>
+ utf_error validate_next(octet_iterator& it, octet_iterator end, uint32_t& code_point)
+ {
+ // Save the original value of it so we can go back in case of failure
+ // Of course, it does not make much sense with i.e. stream iterators
+ octet_iterator original_it = it;
+
+ uint32_t cp = 0;
+ // Determine the sequence length based on the lead octet
+ typedef typename std::iterator_traits<octet_iterator>::difference_type octet_difference_type;
+ const octet_difference_type length = utf8::internal::sequence_length(it);
+
+ // Get trail octets and calculate the code point
+ utf_error err = UTF8_OK;
+ switch (length) {
+ case 0:
+ return INVALID_LEAD;
+ case 1:
+ err = utf8::internal::get_sequence_1(it, end, cp);
+ break;
+ case 2:
+ err = utf8::internal::get_sequence_2(it, end, cp);
+ break;
+ case 3:
+ err = utf8::internal::get_sequence_3(it, end, cp);
+ break;
+ case 4:
+ err = utf8::internal::get_sequence_4(it, end, cp);
+ break;
+ }
+
+ if (err == UTF8_OK) {
+ // Decoding succeeded. Now, security checks...
+ if (utf8::internal::is_code_point_valid(cp)) {
+ if (!utf8::internal::is_overlong_sequence(cp, length)){
+ // Passed! Return here.
+ code_point = cp;
+ ++it;
+ return UTF8_OK;
+ }
+ else
+ err = OVERLONG_SEQUENCE;
+ }
+ else
+ err = INVALID_CODE_POINT;
+ }
+
+ // Failure branch - restore the original value of the iterator
+ it = original_it;
+ return err;
+ }
+
+ template <typename octet_iterator>
+ inline utf_error validate_next(octet_iterator& it, octet_iterator end) {
+ uint32_t ignored;
+ return utf8::internal::validate_next(it, end, ignored);
+ }
+
+} // namespace internal
+
+ /// The library API - functions intended to be called by the users
+
+ // Byte order mark
+ const uint8_t bom[] = {0xef, 0xbb, 0xbf};
+
+ template <typename octet_iterator>
+ octet_iterator find_invalid(octet_iterator start, octet_iterator end)
+ {
+ octet_iterator result = start;
+ while (result != end) {
+ utf8::internal::utf_error err_code = utf8::internal::validate_next(result, end);
+ if (err_code != internal::UTF8_OK)
+ return result;
+ }
+ return result;
+ }
+
+ template <typename octet_iterator>
+ inline bool is_valid(octet_iterator start, octet_iterator end)
+ {
+ return (utf8::find_invalid(start, end) == end);
+ }
+
+ template <typename octet_iterator>
+ inline bool starts_with_bom (octet_iterator it, octet_iterator end)
+ {
+ return (
+ ((it != end) && (utf8::internal::mask8(*it++)) == bom[0]) &&
+ ((it != end) && (utf8::internal::mask8(*it++)) == bom[1]) &&
+ ((it != end) && (utf8::internal::mask8(*it)) == bom[2])
+ );
+ }
+
+ //Deprecated in release 2.3
+ template <typename octet_iterator>
+ inline bool is_bom (octet_iterator it)
+ {
+ return (
+ (utf8::internal::mask8(*it++)) == bom[0] &&
+ (utf8::internal::mask8(*it++)) == bom[1] &&
+ (utf8::internal::mask8(*it)) == bom[2]
+ );
+ }
+} // namespace utf8
+
+#endif // header guard
+
+
diff --git a/thirdparty/assimp/contrib/utf8cpp/source/utf8/unchecked.h b/thirdparty/assimp/contrib/utf8cpp/source/utf8/unchecked.h
new file mode 100644
index 0000000000..cb2427166b
--- /dev/null
+++ b/thirdparty/assimp/contrib/utf8cpp/source/utf8/unchecked.h
@@ -0,0 +1,228 @@
+// Copyright 2006 Nemanja Trifunovic
+
+/*
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+*/
+
+
+#ifndef UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+#define UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+
+#include "core.h"
+
+namespace utf8
+{
+ namespace unchecked
+ {
+ template <typename octet_iterator>
+ octet_iterator append(uint32_t cp, octet_iterator result)
+ {
+ if (cp < 0x80) // one octet
+ *(result++) = static_cast<uint8_t>(cp);
+ else if (cp < 0x800) { // two octets
+ *(result++) = static_cast<uint8_t>((cp >> 6) | 0xc0);
+ *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
+ }
+ else if (cp < 0x10000) { // three octets
+ *(result++) = static_cast<uint8_t>((cp >> 12) | 0xe0);
+ *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
+ *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
+ }
+ else { // four octets
+ *(result++) = static_cast<uint8_t>((cp >> 18) | 0xf0);
+ *(result++) = static_cast<uint8_t>(((cp >> 12) & 0x3f)| 0x80);
+ *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
+ *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
+ }
+ return result;
+ }
+
+ template <typename octet_iterator>
+ uint32_t next(octet_iterator& it)
+ {
+ uint32_t cp = utf8::internal::mask8(*it);
+ typename std::iterator_traits<octet_iterator>::difference_type length = utf8::internal::sequence_length(it);
+ switch (length) {
+ case 1:
+ break;
+ case 2:
+ it++;
+ cp = ((cp << 6) & 0x7ff) + ((*it) & 0x3f);
+ break;
+ case 3:
+ ++it;
+ cp = ((cp << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff);
+ ++it;
+ cp += (*it) & 0x3f;
+ break;
+ case 4:
+ ++it;
+ cp = ((cp << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff);
+ ++it;
+ cp += (utf8::internal::mask8(*it) << 6) & 0xfff;
+ ++it;
+ cp += (*it) & 0x3f;
+ break;
+ }
+ ++it;
+ return cp;
+ }
+
+ template <typename octet_iterator>
+ uint32_t peek_next(octet_iterator it)
+ {
+ return utf8::unchecked::next(it);
+ }
+
+ template <typename octet_iterator>
+ uint32_t prior(octet_iterator& it)
+ {
+ while (utf8::internal::is_trail(*(--it))) ;
+ octet_iterator temp = it;
+ return utf8::unchecked::next(temp);
+ }
+
+ // Deprecated in versions that include prior, but only for the sake of consistency (see utf8::previous)
+ template <typename octet_iterator>
+ inline uint32_t previous(octet_iterator& it)
+ {
+ return utf8::unchecked::prior(it);
+ }
+
+ template <typename octet_iterator, typename distance_type>
+ void advance (octet_iterator& it, distance_type n)
+ {
+ for (distance_type i = 0; i < n; ++i)
+ utf8::unchecked::next(it);
+ }
+
+ template <typename octet_iterator>
+ typename std::iterator_traits<octet_iterator>::difference_type
+ distance (octet_iterator first, octet_iterator last)
+ {
+ typename std::iterator_traits<octet_iterator>::difference_type dist;
+ for (dist = 0; first < last; ++dist)
+ utf8::unchecked::next(first);
+ return dist;
+ }
+
+ template <typename u16bit_iterator, typename octet_iterator>
+ octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result)
+ {
+ while (start != end) {
+ uint32_t cp = utf8::internal::mask16(*start++);
+ // Take care of surrogate pairs first
+ if (utf8::internal::is_lead_surrogate(cp)) {
+ uint32_t trail_surrogate = utf8::internal::mask16(*start++);
+ cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET;
+ }
+ result = utf8::unchecked::append(cp, result);
+ }
+ return result;
+ }
+
+ template <typename u16bit_iterator, typename octet_iterator>
+ u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result)
+ {
+ while (start < end) {
+ uint32_t cp = utf8::unchecked::next(start);
+ if (cp > 0xffff) { //make a surrogate pair
+ *result++ = static_cast<uint16_t>((cp >> 10) + internal::LEAD_OFFSET);
+ *result++ = static_cast<uint16_t>((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN);
+ }
+ else
+ *result++ = static_cast<uint16_t>(cp);
+ }
+ return result;
+ }
+
+ template <typename octet_iterator, typename u32bit_iterator>
+ octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result)
+ {
+ while (start != end)
+ result = utf8::unchecked::append(*(start++), result);
+
+ return result;
+ }
+
+ template <typename octet_iterator, typename u32bit_iterator>
+ u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result)
+ {
+ while (start < end)
+ (*result++) = utf8::unchecked::next(start);
+
+ return result;
+ }
+
+ // The iterator class
+ template <typename octet_iterator>
+ class iterator : public std::iterator <std::bidirectional_iterator_tag, uint32_t> {
+ octet_iterator it;
+ public:
+ iterator () {}
+ explicit iterator (const octet_iterator& octet_it): it(octet_it) {}
+ // the default "big three" are OK
+ octet_iterator base () const { return it; }
+ uint32_t operator * () const
+ {
+ octet_iterator temp = it;
+ return utf8::unchecked::next(temp);
+ }
+ bool operator == (const iterator& rhs) const
+ {
+ return (it == rhs.it);
+ }
+ bool operator != (const iterator& rhs) const
+ {
+ return !(operator == (rhs));
+ }
+ iterator& operator ++ ()
+ {
+ ::std::advance(it, utf8::internal::sequence_length(it));
+ return *this;
+ }
+ iterator operator ++ (int)
+ {
+ iterator temp = *this;
+ ::std::advance(it, utf8::internal::sequence_length(it));
+ return temp;
+ }
+ iterator& operator -- ()
+ {
+ utf8::unchecked::prior(it);
+ return *this;
+ }
+ iterator operator -- (int)
+ {
+ iterator temp = *this;
+ utf8::unchecked::prior(it);
+ return temp;
+ }
+ }; // class iterator
+
+ } // namespace utf8::unchecked
+} // namespace utf8
+
+
+#endif // header guard
+
diff --git a/thirdparty/assimp/include/assimp/.editorconfig b/thirdparty/assimp/include/assimp/.editorconfig
new file mode 100644
index 0000000000..9ea66423ad
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/.editorconfig
@@ -0,0 +1,8 @@
+# See <http://EditorConfig.org> for details
+
+[*.{h,hpp,inl}]
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+indent_size = 4
+indent_style = space
diff --git a/thirdparty/assimp/include/assimp/BaseImporter.h b/thirdparty/assimp/include/assimp/BaseImporter.h
new file mode 100644
index 0000000000..48dfc8ed8b
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/BaseImporter.h
@@ -0,0 +1,361 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file Definition of the base class for all importer worker classes. */
+#ifndef INCLUDED_AI_BASEIMPORTER_H
+#define INCLUDED_AI_BASEIMPORTER_H
+
+#include "Exceptional.h"
+
+#include <vector>
+#include <set>
+#include <assimp/types.h>
+#include <assimp/ProgressHandler.hpp>
+
+struct aiScene;
+struct aiImporterDesc;
+
+namespace Assimp {
+
+class Importer;
+class IOSystem;
+class BaseProcess;
+class SharedPostProcessInfo;
+class IOStream;
+
+// utility to do char4 to uint32 in a portable manner
+#define AI_MAKE_MAGIC(string) ((uint32_t)((string[0] << 24) + \
+ (string[1] << 16) + (string[2] << 8) + string[3]))
+
+
+// ---------------------------------------------------------------------------
+/** FOR IMPORTER PLUGINS ONLY: The BaseImporter defines a common interface
+ * for all importer worker classes.
+ *
+ * The interface defines two functions: CanRead() is used to check if the
+ * importer can handle the format of the given file. If an implementation of
+ * this function returns true, the importer then calls ReadFile() which
+ * imports the given file. ReadFile is not overridable, it just calls
+ * InternReadFile() and catches any ImportErrorException that might occur.
+ */
+class ASSIMP_API BaseImporter {
+ friend class Importer;
+
+public:
+
+ /** Constructor to be privately used by #Importer */
+ BaseImporter() AI_NO_EXCEPT;
+
+ /** Destructor, private as well */
+ virtual ~BaseImporter();
+
+ // -------------------------------------------------------------------
+ /** Returns whether the class can handle the format of the given file.
+ *
+ * The implementation should be as quick as possible. A check for
+ * the file extension is enough. If no suitable loader is found with
+ * this strategy, CanRead() is called again, the 'checkSig' parameter
+ * set to true this time. Now the implementation is expected to
+ * perform a full check of the file structure, possibly searching the
+ * first bytes of the file for magic identifiers or keywords.
+ *
+ * @param pFile Path and file name of the file to be examined.
+ * @param pIOHandler The IO handler to use for accessing any file.
+ * @param checkSig Set to true if this method is called a second time.
+ * This time, the implementation may take more time to examine the
+ * contents of the file to be loaded for magic bytes, keywords, etc
+ * to be able to load files with unknown/not existent file extensions.
+ * @return true if the class can read this file, false if not.
+ */
+ virtual bool CanRead(
+ const std::string& pFile,
+ IOSystem* pIOHandler,
+ bool checkSig
+ ) const = 0;
+
+ // -------------------------------------------------------------------
+ /** Imports the given file and returns the imported data.
+ * If the import succeeds, ownership of the data is transferred to
+ * the caller. If the import fails, NULL is returned. The function
+ * takes care that any partially constructed data is destroyed
+ * beforehand.
+ *
+ * @param pImp #Importer object hosting this loader.
+ * @param pFile Path of the file to be imported.
+ * @param pIOHandler IO-Handler used to open this and possible other files.
+ * @return The imported data or NULL if failed. If it failed a
+ * human-readable error description can be retrieved by calling
+ * GetErrorText()
+ *
+ * @note This function is not intended to be overridden. Implement
+ * InternReadFile() to do the import. If an exception is thrown somewhere
+ * in InternReadFile(), this function will catch it and transform it into
+ * a suitable response to the caller.
+ */
+ aiScene* ReadFile(
+ const Importer* pImp,
+ const std::string& pFile,
+ IOSystem* pIOHandler
+ );
+
+ // -------------------------------------------------------------------
+ /** Returns the error description of the last error that occurred.
+ * @return A description of the last error that occurred. An empty
+ * string if there was no error.
+ */
+ const std::string& GetErrorText() const {
+ return m_ErrorText;
+ }
+
+ // -------------------------------------------------------------------
+ /** Called prior to ReadFile().
+ * The function is a request to the importer to update its configuration
+ * basing on the Importer's configuration property list.
+ * @param pImp Importer instance
+ */
+ virtual void SetupProperties(
+ const Importer* pImp
+ );
+
+ // -------------------------------------------------------------------
+ /** Called by #Importer::GetImporterInfo to get a description of
+ * some loader features. Importers must provide this information. */
+ virtual const aiImporterDesc* GetInfo() const = 0;
+
+ // -------------------------------------------------------------------
+ /** Called by #Importer::GetExtensionList for each loaded importer.
+ * Take the extension list contained in the structure returned by
+ * #GetInfo and insert all file extensions into the given set.
+ * @param extension set to collect file extensions in*/
+ void GetExtensionList(std::set<std::string>& extensions);
+
+protected:
+
+ // -------------------------------------------------------------------
+ /** Imports the given file into the given scene structure. The
+ * function is expected to throw an ImportErrorException if there is
+ * an error. If it terminates normally, the data in aiScene is
+ * expected to be correct. Override this function to implement the
+ * actual importing.
+ * <br>
+ * The output scene must meet the following requirements:<br>
+ * <ul>
+ * <li>At least a root node must be there, even if its only purpose
+ * is to reference one mesh.</li>
+ * <li>aiMesh::mPrimitiveTypes may be 0. The types of primitives
+ * in the mesh are determined automatically in this case.</li>
+ * <li>the vertex data is stored in a pseudo-indexed "verbose" format.
+ * In fact this means that every vertex that is referenced by
+ * a face is unique. Or the other way round: a vertex index may
+ * not occur twice in a single aiMesh.</li>
+ * <li>aiAnimation::mDuration may be -1. Assimp determines the length
+ * of the animation automatically in this case as the length of
+ * the longest animation channel.</li>
+ * <li>aiMesh::mBitangents may be NULL if tangents and normals are
+ * given. In this case bitangents are computed as the cross product
+ * between normal and tangent.</li>
+ * <li>There needn't be a material. If none is there a default material
+ * is generated. However, it is recommended practice for loaders
+ * to generate a default material for yourself that matches the
+ * default material setting for the file format better than Assimp's
+ * generic default material. Note that default materials *should*
+ * be named AI_DEFAULT_MATERIAL_NAME if they're just color-shaded
+ * or AI_DEFAULT_TEXTURED_MATERIAL_NAME if they define a (dummy)
+ * texture. </li>
+ * </ul>
+ * If the AI_SCENE_FLAGS_INCOMPLETE-Flag is <b>not</b> set:<ul>
+ * <li> at least one mesh must be there</li>
+ * <li> there may be no meshes with 0 vertices or faces</li>
+ * </ul>
+ * This won't be checked (except by the validation step): Assimp will
+ * crash if one of the conditions is not met!
+ *
+ * @param pFile Path of the file to be imported.
+ * @param pScene The scene object to hold the imported data.
+ * NULL is not a valid parameter.
+ * @param pIOHandler The IO handler to use for any file access.
+ * NULL is not a valid parameter. */
+ virtual void InternReadFile(
+ const std::string& pFile,
+ aiScene* pScene,
+ IOSystem* pIOHandler
+ ) = 0;
+
+public: // static utilities
+
+ // -------------------------------------------------------------------
+ /** A utility for CanRead().
+ *
+ * The function searches the header of a file for a specific token
+ * and returns true if this token is found. This works for text
+ * files only. There is a rudimentary handling of UNICODE files.
+ * The comparison is case independent.
+ *
+ * @param pIOSystem IO System to work with
+ * @param file File name of the file
+ * @param tokens List of tokens to search for
+ * @param numTokens Size of the token array
+ * @param searchBytes Number of bytes to be searched for the tokens.
+ */
+ static bool SearchFileHeaderForToken(
+ IOSystem* pIOSystem,
+ const std::string& file,
+ const char** tokens,
+ unsigned int numTokens,
+ unsigned int searchBytes = 200,
+ bool tokensSol = false,
+ bool noAlphaBeforeTokens = false);
+
+ // -------------------------------------------------------------------
+ /** @brief Check whether a file has a specific file extension
+ * @param pFile Input file
+ * @param ext0 Extension to check for. Lowercase characters only, no dot!
+ * @param ext1 Optional second extension
+ * @param ext2 Optional third extension
+ * @note Case-insensitive
+ */
+ static bool SimpleExtensionCheck (
+ const std::string& pFile,
+ const char* ext0,
+ const char* ext1 = NULL,
+ const char* ext2 = NULL);
+
+ // -------------------------------------------------------------------
+ /** @brief Extract file extension from a string
+ * @param pFile Input file
+ * @return Extension without trailing dot, all lowercase
+ */
+ static std::string GetExtension (
+ const std::string& pFile);
+
+ // -------------------------------------------------------------------
+ /** @brief Check whether a file starts with one or more magic tokens
+ * @param pFile Input file
+ * @param pIOHandler IO system to be used
+ * @param magic n magic tokens
+ * @params num Size of magic
+ * @param offset Offset from file start where tokens are located
+ * @param Size of one token, in bytes. Maximally 16 bytes.
+ * @return true if one of the given tokens was found
+ *
+ * @note For convenience, the check is also performed for the
+ * byte-swapped variant of all tokens (big endian). Only for
+ * tokens of size 2,4.
+ */
+ static bool CheckMagicToken(
+ IOSystem* pIOHandler,
+ const std::string& pFile,
+ const void* magic,
+ unsigned int num,
+ unsigned int offset = 0,
+ unsigned int size = 4);
+
+ // -------------------------------------------------------------------
+ /** An utility for all text file loaders. It converts a file to our
+ * UTF8 character set. Errors are reported, but ignored.
+ *
+ * @param data File buffer to be converted to UTF8 data. The buffer
+ * is resized as appropriate. */
+ static void ConvertToUTF8(
+ std::vector<char>& data);
+
+ // -------------------------------------------------------------------
+ /** An utility for all text file loaders. It converts a file from our
+ * UTF8 character set back to ISO-8859-1. Errors are reported, but ignored.
+ *
+ * @param data File buffer to be converted from UTF8 to ISO-8859-1. The buffer
+ * is resized as appropriate. */
+ static void ConvertUTF8toISO8859_1(
+ std::string& data);
+
+ // -------------------------------------------------------------------
+ /// @brief Enum to define, if empty files are ok or not.
+ enum TextFileMode {
+ ALLOW_EMPTY,
+ FORBID_EMPTY
+ };
+
+ // -------------------------------------------------------------------
+ /** Utility for text file loaders which copies the contents of the
+ * file into a memory buffer and converts it to our UTF8
+ * representation.
+ * @param stream Stream to read from.
+ * @param data Output buffer to be resized and filled with the
+ * converted text file data. The buffer is terminated with
+ * a binary 0.
+ * @param mode Whether it is OK to load empty text files. */
+ static void TextFileToBuffer(
+ IOStream* stream,
+ std::vector<char>& data,
+ TextFileMode mode = FORBID_EMPTY);
+
+ // -------------------------------------------------------------------
+ /** Utility function to move a std::vector into a aiScene array
+ * @param vec The vector to be moved
+ * @param out The output pointer to the allocated array.
+ * @param numOut The output count of elements copied. */
+ template<typename T>
+ AI_FORCE_INLINE
+ static void CopyVector(
+ std::vector<T>& vec,
+ T*& out,
+ unsigned int& outLength)
+ {
+ outLength = unsigned(vec.size());
+ if (outLength) {
+ out = new T[outLength];
+ std::swap_ranges(vec.begin(), vec.end(), out);
+ }
+ }
+
+protected:
+ /// Error description in case there was one.
+ std::string m_ErrorText;
+ /// Currently set progress handler.
+ ProgressHandler* m_progress;
+};
+
+
+
+} // end of namespace Assimp
+
+#endif // AI_BASEIMPORTER_H_INC
diff --git a/thirdparty/assimp/include/assimp/Bitmap.h b/thirdparty/assimp/include/assimp/Bitmap.h
new file mode 100644
index 0000000000..e6b5fb1327
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/Bitmap.h
@@ -0,0 +1,125 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file Bitmap.h
+ * @brief Defines bitmap format helper for textures
+ *
+ * Used for file formats which embed their textures into the model file.
+ */
+
+#ifndef AI_BITMAP_H_INC
+#define AI_BITMAP_H_INC
+
+#include "defs.h"
+#include <stdint.h>
+#include <cstddef>
+
+struct aiTexture;
+
+namespace Assimp {
+
+class IOStream;
+
+class ASSIMP_API Bitmap {
+protected:
+
+ struct Header {
+ uint16_t type;
+ uint32_t size;
+ uint16_t reserved1;
+ uint16_t reserved2;
+ uint32_t offset;
+
+ // We define the struct size because sizeof(Header) might return a wrong result because of structure padding.
+ // Moreover, we must use this ugly and error prone syntax because Visual Studio neither support constexpr or sizeof(name_of_field).
+ static const std::size_t header_size =
+ sizeof(uint16_t) + // type
+ sizeof(uint32_t) + // size
+ sizeof(uint16_t) + // reserved1
+ sizeof(uint16_t) + // reserved2
+ sizeof(uint32_t); // offset
+ };
+
+ struct DIB {
+ uint32_t size;
+ int32_t width;
+ int32_t height;
+ uint16_t planes;
+ uint16_t bits_per_pixel;
+ uint32_t compression;
+ uint32_t image_size;
+ int32_t x_resolution;
+ int32_t y_resolution;
+ uint32_t nb_colors;
+ uint32_t nb_important_colors;
+
+ // We define the struct size because sizeof(DIB) might return a wrong result because of structure padding.
+ // Moreover, we must use this ugly and error prone syntax because Visual Studio neither support constexpr or sizeof(name_of_field).
+ static const std::size_t dib_size =
+ sizeof(uint32_t) + // size
+ sizeof(int32_t) + // width
+ sizeof(int32_t) + // height
+ sizeof(uint16_t) + // planes
+ sizeof(uint16_t) + // bits_per_pixel
+ sizeof(uint32_t) + // compression
+ sizeof(uint32_t) + // image_size
+ sizeof(int32_t) + // x_resolution
+ sizeof(int32_t) + // y_resolution
+ sizeof(uint32_t) + // nb_colors
+ sizeof(uint32_t); // nb_important_colors
+ };
+
+ static const std::size_t mBytesPerPixel = 4;
+
+public:
+ static void Save(aiTexture* texture, IOStream* file);
+
+protected:
+ static void WriteHeader(Header& header, IOStream* file);
+ static void WriteDIB(DIB& dib, IOStream* file);
+ static void WriteData(aiTexture* texture, IOStream* file);
+};
+
+}
+
+#endif // AI_BITMAP_H_INC
diff --git a/thirdparty/assimp/include/assimp/BlobIOSystem.h b/thirdparty/assimp/include/assimp/BlobIOSystem.h
new file mode 100644
index 0000000000..d005e5c119
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/BlobIOSystem.h
@@ -0,0 +1,338 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file Provides cheat implementations for IOSystem and IOStream to
+ * redirect exporter output to a blob chain.*/
+
+#ifndef AI_BLOBIOSYSTEM_H_INCLUDED
+#define AI_BLOBIOSYSTEM_H_INCLUDED
+
+#include <assimp/IOStream.hpp>
+#include <assimp/cexport.h>
+#include <assimp/IOSystem.hpp>
+#include <assimp/DefaultLogger.hpp>
+#include <stdint.h>
+#include <set>
+#include <vector>
+
+namespace Assimp {
+ class BlobIOSystem;
+
+// --------------------------------------------------------------------------------------------
+/** Redirect IOStream to a blob */
+// --------------------------------------------------------------------------------------------
+class BlobIOStream : public IOStream
+{
+public:
+
+ BlobIOStream(BlobIOSystem* creator, const std::string& file, size_t initial = 4096)
+ : buffer()
+ , cur_size()
+ , file_size()
+ , cursor()
+ , initial(initial)
+ , file(file)
+ , creator(creator)
+ {
+ }
+
+
+ virtual ~BlobIOStream();
+
+public:
+
+ // -------------------------------------------------------------------
+ aiExportDataBlob* GetBlob()
+ {
+ aiExportDataBlob* blob = new aiExportDataBlob();
+ blob->size = file_size;
+ blob->data = buffer;
+
+ buffer = NULL;
+
+ return blob;
+ }
+
+
+public:
+
+
+ // -------------------------------------------------------------------
+ virtual size_t Read( void *,
+ size_t,
+ size_t )
+ {
+ return 0;
+ }
+
+ // -------------------------------------------------------------------
+ virtual size_t Write(const void* pvBuffer,
+ size_t pSize,
+ size_t pCount)
+ {
+ pSize *= pCount;
+ if (cursor + pSize > cur_size) {
+ Grow(cursor + pSize);
+ }
+
+ memcpy(buffer+cursor, pvBuffer, pSize);
+ cursor += pSize;
+
+ file_size = std::max(file_size,cursor);
+ return pCount;
+ }
+
+ // -------------------------------------------------------------------
+ virtual aiReturn Seek(size_t pOffset,
+ aiOrigin pOrigin)
+ {
+ switch(pOrigin)
+ {
+ case aiOrigin_CUR:
+ cursor += pOffset;
+ break;
+
+ case aiOrigin_END:
+ cursor = file_size - pOffset;
+ break;
+
+ case aiOrigin_SET:
+ cursor = pOffset;
+ break;
+
+ default:
+ return AI_FAILURE;
+ }
+
+ if (cursor > file_size) {
+ Grow(cursor);
+ }
+
+ file_size = std::max(cursor,file_size);
+ return AI_SUCCESS;
+ }
+
+ // -------------------------------------------------------------------
+ virtual size_t Tell() const
+ {
+ return cursor;
+ }
+
+ // -------------------------------------------------------------------
+ virtual size_t FileSize() const
+ {
+ return file_size;
+ }
+
+ // -------------------------------------------------------------------
+ virtual void Flush()
+ {
+ // ignore
+ }
+
+
+
+private:
+
+ // -------------------------------------------------------------------
+ void Grow(size_t need = 0)
+ {
+ // 1.5 and phi are very heap-friendly growth factors (the first
+ // allows for frequent re-use of heap blocks, the second
+ // forms a fibonacci sequence with similar characteristics -
+ // since this heavily depends on the heap implementation
+ // and other factors as well, i'll just go with 1.5 since
+ // it is quicker to compute).
+ size_t new_size = std::max(initial, std::max( need, cur_size+(cur_size>>1) ));
+
+ const uint8_t* const old = buffer;
+ buffer = new uint8_t[new_size];
+
+ if (old) {
+ memcpy(buffer,old,cur_size);
+ delete[] old;
+ }
+
+ cur_size = new_size;
+ }
+
+private:
+
+ uint8_t* buffer;
+ size_t cur_size,file_size, cursor, initial;
+
+ const std::string file;
+ BlobIOSystem* const creator;
+};
+
+
+#define AI_BLOBIO_MAGIC "$blobfile"
+
+// --------------------------------------------------------------------------------------------
+/** Redirect IOSystem to a blob */
+// --------------------------------------------------------------------------------------------
+class BlobIOSystem : public IOSystem
+{
+
+ friend class BlobIOStream;
+ typedef std::pair<std::string, aiExportDataBlob*> BlobEntry;
+
+public:
+
+ BlobIOSystem()
+ {
+ }
+
+ virtual ~BlobIOSystem()
+ {
+ for(BlobEntry& blobby : blobs) {
+ delete blobby.second;
+ }
+ }
+
+public:
+
+ // -------------------------------------------------------------------
+ const char* GetMagicFileName() const
+ {
+ return AI_BLOBIO_MAGIC;
+ }
+
+
+ // -------------------------------------------------------------------
+ aiExportDataBlob* GetBlobChain()
+ {
+ // one must be the master
+ aiExportDataBlob* master = NULL, *cur;
+ for(const BlobEntry& blobby : blobs) {
+ if (blobby.first == AI_BLOBIO_MAGIC) {
+ master = blobby.second;
+ break;
+ }
+ }
+ if (!master) {
+ ASSIMP_LOG_ERROR("BlobIOSystem: no data written or master file was not closed properly.");
+ return NULL;
+ }
+
+ master->name.Set("");
+
+ cur = master;
+ for(const BlobEntry& blobby : blobs) {
+ if (blobby.second == master) {
+ continue;
+ }
+
+ cur->next = blobby.second;
+ cur = cur->next;
+
+ // extract the file extension from the file written
+ const std::string::size_type s = blobby.first.find_first_of('.');
+ cur->name.Set(s == std::string::npos ? blobby.first : blobby.first.substr(s+1));
+ }
+
+ // give up blob ownership
+ blobs.clear();
+ return master;
+ }
+
+public:
+
+ // -------------------------------------------------------------------
+ virtual bool Exists( const char* pFile) const {
+ return created.find(std::string(pFile)) != created.end();
+ }
+
+
+ // -------------------------------------------------------------------
+ virtual char getOsSeparator() const {
+ return '/';
+ }
+
+
+ // -------------------------------------------------------------------
+ virtual IOStream* Open(const char* pFile,
+ const char* pMode)
+ {
+ if (pMode[0] != 'w') {
+ return NULL;
+ }
+
+ created.insert(std::string(pFile));
+ return new BlobIOStream(this,std::string(pFile));
+ }
+
+ // -------------------------------------------------------------------
+ virtual void Close( IOStream* pFile)
+ {
+ delete pFile;
+ }
+
+private:
+
+ // -------------------------------------------------------------------
+ void OnDestruct(const std::string& filename, BlobIOStream* child)
+ {
+ // we don't know in which the files are closed, so we
+ // can't reliably say that the first must be the master
+ // file ...
+ blobs.push_back( BlobEntry(filename,child->GetBlob()) );
+ }
+
+private:
+ std::set<std::string> created;
+ std::vector< BlobEntry > blobs;
+};
+
+
+// --------------------------------------------------------------------------------------------
+BlobIOStream :: ~BlobIOStream()
+{
+ creator->OnDestruct(file,this);
+ delete[] buffer;
+}
+
+
+} // end Assimp
+
+#endif
diff --git a/thirdparty/assimp/include/assimp/ByteSwapper.h b/thirdparty/assimp/include/assimp/ByteSwapper.h
new file mode 100644
index 0000000000..20a2463fb8
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/ByteSwapper.h
@@ -0,0 +1,287 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file Helper class tp perform various byte oder swappings
+ (e.g. little to big endian) */
+#ifndef AI_BYTESWAPPER_H_INC
+#define AI_BYTESWAPPER_H_INC
+
+#include <assimp/ai_assert.h>
+#include <assimp/types.h>
+#include <stdint.h>
+
+#if _MSC_VER >= 1400
+#include <stdlib.h>
+#endif
+
+namespace Assimp {
+// --------------------------------------------------------------------------------------
+/** Defines some useful byte order swap routines.
+ *
+ * This is required to read big-endian model formats on little-endian machines,
+ * and vice versa. Direct use of this class is DEPRECATED. Use #StreamReader instead. */
+// --------------------------------------------------------------------------------------
+class ByteSwap {
+ ByteSwap() AI_NO_EXCEPT {}
+
+public:
+
+ // ----------------------------------------------------------------------
+ /** Swap two bytes of data
+ * @param[inout] _szOut A void* to save the reintcasts for the caller. */
+ static inline void Swap2(void* _szOut)
+ {
+ ai_assert(_szOut);
+
+#if _MSC_VER >= 1400
+ uint16_t* const szOut = reinterpret_cast<uint16_t*>(_szOut);
+ *szOut = _byteswap_ushort(*szOut);
+#else
+ uint8_t* const szOut = reinterpret_cast<uint8_t*>(_szOut);
+ std::swap(szOut[0],szOut[1]);
+#endif
+ }
+
+ // ----------------------------------------------------------------------
+ /** Swap four bytes of data
+ * @param[inout] _szOut A void* to save the reintcasts for the caller. */
+ static inline void Swap4(void* _szOut)
+ {
+ ai_assert(_szOut);
+
+#if _MSC_VER >= 1400
+ uint32_t* const szOut = reinterpret_cast<uint32_t*>(_szOut);
+ *szOut = _byteswap_ulong(*szOut);
+#else
+ uint8_t* const szOut = reinterpret_cast<uint8_t*>(_szOut);
+ std::swap(szOut[0],szOut[3]);
+ std::swap(szOut[1],szOut[2]);
+#endif
+ }
+
+ // ----------------------------------------------------------------------
+ /** Swap eight bytes of data
+ * @param[inout] _szOut A void* to save the reintcasts for the caller. */
+ static inline void Swap8(void* _szOut)
+ {
+ ai_assert(_szOut);
+
+#if _MSC_VER >= 1400
+ uint64_t* const szOut = reinterpret_cast<uint64_t*>(_szOut);
+ *szOut = _byteswap_uint64(*szOut);
+#else
+ uint8_t* const szOut = reinterpret_cast<uint8_t*>(_szOut);
+ std::swap(szOut[0],szOut[7]);
+ std::swap(szOut[1],szOut[6]);
+ std::swap(szOut[2],szOut[5]);
+ std::swap(szOut[3],szOut[4]);
+#endif
+ }
+
+ // ----------------------------------------------------------------------
+ /** ByteSwap a float. Not a joke.
+ * @param[inout] fOut ehm. .. */
+ static inline void Swap(float* fOut) {
+ Swap4(fOut);
+ }
+
+ // ----------------------------------------------------------------------
+ /** ByteSwap a double. Not a joke.
+ * @param[inout] fOut ehm. .. */
+ static inline void Swap(double* fOut) {
+ Swap8(fOut);
+ }
+
+
+ // ----------------------------------------------------------------------
+ /** ByteSwap an int16t. Not a joke.
+ * @param[inout] fOut ehm. .. */
+ static inline void Swap(int16_t* fOut) {
+ Swap2(fOut);
+ }
+
+ static inline void Swap(uint16_t* fOut) {
+ Swap2(fOut);
+ }
+
+ // ----------------------------------------------------------------------
+ /** ByteSwap an int32t. Not a joke.
+ * @param[inout] fOut ehm. .. */
+ static inline void Swap(int32_t* fOut){
+ Swap4(fOut);
+ }
+
+ static inline void Swap(uint32_t* fOut){
+ Swap4(fOut);
+ }
+
+ // ----------------------------------------------------------------------
+ /** ByteSwap an int64t. Not a joke.
+ * @param[inout] fOut ehm. .. */
+ static inline void Swap(int64_t* fOut) {
+ Swap8(fOut);
+ }
+
+ static inline void Swap(uint64_t* fOut) {
+ Swap8(fOut);
+ }
+
+ // ----------------------------------------------------------------------
+ //! Templatized ByteSwap
+ //! \returns param tOut as swapped
+ template<typename Type>
+ static inline Type Swapped(Type tOut)
+ {
+ return _swapper<Type,sizeof(Type)>()(tOut);
+ }
+
+private:
+
+ template <typename T, size_t size> struct _swapper;
+};
+
+template <typename T> struct ByteSwap::_swapper<T,2> {
+ T operator() (T tOut) {
+ Swap2(&tOut);
+ return tOut;
+ }
+};
+
+template <typename T> struct ByteSwap::_swapper<T,4> {
+ T operator() (T tOut) {
+ Swap4(&tOut);
+ return tOut;
+ }
+};
+
+template <typename T> struct ByteSwap::_swapper<T,8> {
+ T operator() (T tOut) {
+ Swap8(&tOut);
+ return tOut;
+ }
+};
+
+
+// --------------------------------------------------------------------------------------
+// ByteSwap macros for BigEndian/LittleEndian support
+// --------------------------------------------------------------------------------------
+#if (defined AI_BUILD_BIG_ENDIAN)
+# define AI_LE(t) (t)
+# define AI_BE(t) ByteSwap::Swapped(t)
+# define AI_LSWAP2(p)
+# define AI_LSWAP4(p)
+# define AI_LSWAP8(p)
+# define AI_LSWAP2P(p)
+# define AI_LSWAP4P(p)
+# define AI_LSWAP8P(p)
+# define LE_NCONST const
+# define AI_SWAP2(p) ByteSwap::Swap2(&(p))
+# define AI_SWAP4(p) ByteSwap::Swap4(&(p))
+# define AI_SWAP8(p) ByteSwap::Swap8(&(p))
+# define AI_SWAP2P(p) ByteSwap::Swap2((p))
+# define AI_SWAP4P(p) ByteSwap::Swap4((p))
+# define AI_SWAP8P(p) ByteSwap::Swap8((p))
+# define BE_NCONST
+#else
+# define AI_BE(t) (t)
+# define AI_LE(t) ByteSwap::Swapped(t)
+# define AI_SWAP2(p)
+# define AI_SWAP4(p)
+# define AI_SWAP8(p)
+# define AI_SWAP2P(p)
+# define AI_SWAP4P(p)
+# define AI_SWAP8P(p)
+# define BE_NCONST const
+# define AI_LSWAP2(p) ByteSwap::Swap2(&(p))
+# define AI_LSWAP4(p) ByteSwap::Swap4(&(p))
+# define AI_LSWAP8(p) ByteSwap::Swap8(&(p))
+# define AI_LSWAP2P(p) ByteSwap::Swap2((p))
+# define AI_LSWAP4P(p) ByteSwap::Swap4((p))
+# define AI_LSWAP8P(p) ByteSwap::Swap8((p))
+# define LE_NCONST
+#endif
+
+
+namespace Intern {
+
+// --------------------------------------------------------------------------------------------
+template <typename T, bool doit>
+struct ByteSwapper {
+ void operator() (T* inout) {
+ ByteSwap::Swap(inout);
+ }
+};
+
+template <typename T>
+struct ByteSwapper<T,false> {
+ void operator() (T*) {
+ }
+};
+
+// --------------------------------------------------------------------------------------------
+template <bool SwapEndianess, typename T, bool RuntimeSwitch>
+struct Getter {
+ void operator() (T* inout, bool le) {
+#ifdef AI_BUILD_BIG_ENDIAN
+ le = le;
+#else
+ le = !le;
+#endif
+ if (le) {
+ ByteSwapper<T,(sizeof(T)>1?true:false)> () (inout);
+ }
+ else ByteSwapper<T,false> () (inout);
+ }
+};
+
+template <bool SwapEndianess, typename T>
+struct Getter<SwapEndianess,T,false> {
+
+ void operator() (T* inout, bool /*le*/) {
+ // static branch
+ ByteSwapper<T,(SwapEndianess && sizeof(T)>1)> () (inout);
+ }
+};
+} // end Intern
+} // end Assimp
+
+#endif //!! AI_BYTESWAPPER_H_INC
diff --git a/thirdparty/assimp/include/assimp/Compiler/poppack1.h b/thirdparty/assimp/include/assimp/Compiler/poppack1.h
new file mode 100644
index 0000000000..e033bc1472
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/Compiler/poppack1.h
@@ -0,0 +1,22 @@
+
+// ===============================================================================
+// May be included multiple times - resets structure packing to the defaults
+// for all supported compilers. Reverts the changes made by #include <pushpack1.h>
+//
+// Currently this works on the following compilers:
+// MSVC 7,8,9
+// GCC
+// BORLAND (complains about 'pack state changed but not reverted', but works)
+// ===============================================================================
+
+#ifndef AI_PUSHPACK_IS_DEFINED
+# error pushpack1.h must be included after poppack1.h
+#endif
+
+// reset packing to the original value
+#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
+# pragma pack( pop )
+#endif
+#undef PACK_STRUCT
+
+#undef AI_PUSHPACK_IS_DEFINED
diff --git a/thirdparty/assimp/include/assimp/Compiler/pstdint.h b/thirdparty/assimp/include/assimp/Compiler/pstdint.h
new file mode 100644
index 0000000000..4de4ce2a90
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/Compiler/pstdint.h
@@ -0,0 +1,912 @@
+/* A portable stdint.h
+ ****************************************************************************
+ * BSD License:
+ ****************************************************************************
+ *
+ * Copyright (c) 2005-2016 Paul Hsieh
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ *
+ ****************************************************************************
+ *
+ * Version 0.1.15.4
+ *
+ * The ANSI C standard committee, for the C99 standard, specified the
+ * inclusion of a new standard include file called stdint.h. This is
+ * a very useful and long desired include file which contains several
+ * very precise definitions for integer scalar types that is
+ * critically important for making portable several classes of
+ * applications including cryptography, hashing, variable length
+ * integer libraries and so on. But for most developers its likely
+ * useful just for programming sanity.
+ *
+ * The problem is that some compiler vendors chose to ignore the C99
+ * standard and some older compilers have no opportunity to be updated.
+ * Because of this situation, simply including stdint.h in your code
+ * makes it unportable.
+ *
+ * So that's what this file is all about. Its an attempt to build a
+ * single universal include file that works on as many platforms as
+ * possible to deliver what stdint.h is supposed to. Even compilers
+ * that already come with stdint.h can use this file instead without
+ * any loss of functionality. A few things that should be noted about
+ * this file:
+ *
+ * 1) It is not guaranteed to be portable and/or present an identical
+ * interface on all platforms. The extreme variability of the
+ * ANSI C standard makes this an impossibility right from the
+ * very get go. Its really only meant to be useful for the vast
+ * majority of platforms that possess the capability of
+ * implementing usefully and precisely defined, standard sized
+ * integer scalars. Systems which are not intrinsically 2s
+ * complement may produce invalid constants.
+ *
+ * 2) There is an unavoidable use of non-reserved symbols.
+ *
+ * 3) Other standard include files are invoked.
+ *
+ * 4) This file may come in conflict with future platforms that do
+ * include stdint.h. The hope is that one or the other can be
+ * used with no real difference.
+ *
+ * 5) In the current version, if your platform can't represent
+ * int32_t, int16_t and int8_t, it just dumps out with a compiler
+ * error.
+ *
+ * 6) 64 bit integers may or may not be defined. Test for their
+ * presence with the test: #ifdef INT64_MAX or #ifdef UINT64_MAX.
+ * Note that this is different from the C99 specification which
+ * requires the existence of 64 bit support in the compiler. If
+ * this is not defined for your platform, yet it is capable of
+ * dealing with 64 bits then it is because this file has not yet
+ * been extended to cover all of your system's capabilities.
+ *
+ * 7) (u)intptr_t may or may not be defined. Test for its presence
+ * with the test: #ifdef PTRDIFF_MAX. If this is not defined
+ * for your platform, then it is because this file has not yet
+ * been extended to cover all of your system's capabilities, not
+ * because its optional.
+ *
+ * 8) The following might not been defined even if your platform is
+ * capable of defining it:
+ *
+ * WCHAR_MIN
+ * WCHAR_MAX
+ * (u)int64_t
+ * PTRDIFF_MIN
+ * PTRDIFF_MAX
+ * (u)intptr_t
+ *
+ * 9) The following have not been defined:
+ *
+ * WINT_MIN
+ * WINT_MAX
+ *
+ * 10) The criteria for defining (u)int_least(*)_t isn't clear,
+ * except for systems which don't have a type that precisely
+ * defined 8, 16, or 32 bit types (which this include file does
+ * not support anyways). Default definitions have been given.
+ *
+ * 11) The criteria for defining (u)int_fast(*)_t isn't something I
+ * would trust to any particular compiler vendor or the ANSI C
+ * committee. It is well known that "compatible systems" are
+ * commonly created that have very different performance
+ * characteristics from the systems they are compatible with,
+ * especially those whose vendors make both the compiler and the
+ * system. Default definitions have been given, but its strongly
+ * recommended that users never use these definitions for any
+ * reason (they do *NOT* deliver any serious guarantee of
+ * improved performance -- not in this file, nor any vendor's
+ * stdint.h).
+ *
+ * 12) The following macros:
+ *
+ * PRINTF_INTMAX_MODIFIER
+ * PRINTF_INT64_MODIFIER
+ * PRINTF_INT32_MODIFIER
+ * PRINTF_INT16_MODIFIER
+ * PRINTF_LEAST64_MODIFIER
+ * PRINTF_LEAST32_MODIFIER
+ * PRINTF_LEAST16_MODIFIER
+ * PRINTF_INTPTR_MODIFIER
+ *
+ * are strings which have been defined as the modifiers required
+ * for the "d", "u" and "x" printf formats to correctly output
+ * (u)intmax_t, (u)int64_t, (u)int32_t, (u)int16_t, (u)least64_t,
+ * (u)least32_t, (u)least16_t and (u)intptr_t types respectively.
+ * PRINTF_INTPTR_MODIFIER is not defined for some systems which
+ * provide their own stdint.h. PRINTF_INT64_MODIFIER is not
+ * defined if INT64_MAX is not defined. These are an extension
+ * beyond what C99 specifies must be in stdint.h.
+ *
+ * In addition, the following macros are defined:
+ *
+ * PRINTF_INTMAX_HEX_WIDTH
+ * PRINTF_INT64_HEX_WIDTH
+ * PRINTF_INT32_HEX_WIDTH
+ * PRINTF_INT16_HEX_WIDTH
+ * PRINTF_INT8_HEX_WIDTH
+ * PRINTF_INTMAX_DEC_WIDTH
+ * PRINTF_INT64_DEC_WIDTH
+ * PRINTF_INT32_DEC_WIDTH
+ * PRINTF_INT16_DEC_WIDTH
+ * PRINTF_UINT8_DEC_WIDTH
+ * PRINTF_UINTMAX_DEC_WIDTH
+ * PRINTF_UINT64_DEC_WIDTH
+ * PRINTF_UINT32_DEC_WIDTH
+ * PRINTF_UINT16_DEC_WIDTH
+ * PRINTF_UINT8_DEC_WIDTH
+ *
+ * Which specifies the maximum number of characters required to
+ * print the number of that type in either hexadecimal or decimal.
+ * These are an extension beyond what C99 specifies must be in
+ * stdint.h.
+ *
+ * Compilers tested (all with 0 warnings at their highest respective
+ * settings): Borland Turbo C 2.0, WATCOM C/C++ 11.0 (16 bits and 32
+ * bits), Microsoft Visual C++ 6.0 (32 bit), Microsoft Visual Studio
+ * .net (VC7), Intel C++ 4.0, GNU gcc v3.3.3
+ *
+ * This file should be considered a work in progress. Suggestions for
+ * improvements, especially those which increase coverage are strongly
+ * encouraged.
+ *
+ * Acknowledgements
+ *
+ * The following people have made significant contributions to the
+ * development and testing of this file:
+ *
+ * Chris Howie
+ * John Steele Scott
+ * Dave Thorup
+ * John Dill
+ * Florian Wobbe
+ * Christopher Sean Morrison
+ * Mikkel Fahnoe Jorgensen
+ *
+ */
+
+#include <stddef.h>
+#include <limits.h>
+#include <signal.h>
+
+/*
+ * For gcc with _STDINT_H, fill in the PRINTF_INT*_MODIFIER macros, and
+ * do nothing else. On the Mac OS X version of gcc this is _STDINT_H_.
+ */
+
+#if ((defined(__SUNPRO_C) && __SUNPRO_C >= 0x570) || (defined(_MSC_VER) && _MSC_VER >= 1600) || (defined(__STDC__) && __STDC__ && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || (defined (__WATCOMC__) && (defined (_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (__GNUC__ > 3 || defined(_STDINT_H) || defined(_STDINT_H_) || defined (__UINT_FAST64_TYPE__)) )) && !defined (_PSTDINT_H_INCLUDED)
+#include <stdint.h>
+#define _PSTDINT_H_INCLUDED
+# if defined(__GNUC__) && (defined(__x86_64__) || defined(__ppc64__)) && !(defined(__APPLE__) && defined(__MACH__))
+# ifndef PRINTF_INT64_MODIFIER
+# define PRINTF_INT64_MODIFIER "l"
+# endif
+# ifndef PRINTF_INT32_MODIFIER
+# define PRINTF_INT32_MODIFIER ""
+# endif
+# else
+# ifndef PRINTF_INT64_MODIFIER
+# define PRINTF_INT64_MODIFIER "ll"
+# endif
+# ifndef PRINTF_INT32_MODIFIER
+# if (UINT_MAX == UINT32_MAX)
+# define PRINTF_INT32_MODIFIER ""
+# else
+# define PRINTF_INT32_MODIFIER "l"
+# endif
+# endif
+# endif
+# ifndef PRINTF_INT16_MODIFIER
+# define PRINTF_INT16_MODIFIER "h"
+# endif
+# ifndef PRINTF_INTMAX_MODIFIER
+# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER
+# endif
+# ifndef PRINTF_INT64_HEX_WIDTH
+# define PRINTF_INT64_HEX_WIDTH "16"
+# endif
+# ifndef PRINTF_UINT64_HEX_WIDTH
+# define PRINTF_UINT64_HEX_WIDTH "16"
+# endif
+# ifndef PRINTF_INT32_HEX_WIDTH
+# define PRINTF_INT32_HEX_WIDTH "8"
+# endif
+# ifndef PRINTF_UINT32_HEX_WIDTH
+# define PRINTF_UINT32_HEX_WIDTH "8"
+# endif
+# ifndef PRINTF_INT16_HEX_WIDTH
+# define PRINTF_INT16_HEX_WIDTH "4"
+# endif
+# ifndef PRINTF_UINT16_HEX_WIDTH
+# define PRINTF_UINT16_HEX_WIDTH "4"
+# endif
+# ifndef PRINTF_INT8_HEX_WIDTH
+# define PRINTF_INT8_HEX_WIDTH "2"
+# endif
+# ifndef PRINTF_UINT8_HEX_WIDTH
+# define PRINTF_UINT8_HEX_WIDTH "2"
+# endif
+# ifndef PRINTF_INT64_DEC_WIDTH
+# define PRINTF_INT64_DEC_WIDTH "19"
+# endif
+# ifndef PRINTF_UINT64_DEC_WIDTH
+# define PRINTF_UINT64_DEC_WIDTH "20"
+# endif
+# ifndef PRINTF_INT32_DEC_WIDTH
+# define PRINTF_INT32_DEC_WIDTH "10"
+# endif
+# ifndef PRINTF_UINT32_DEC_WIDTH
+# define PRINTF_UINT32_DEC_WIDTH "10"
+# endif
+# ifndef PRINTF_INT16_DEC_WIDTH
+# define PRINTF_INT16_DEC_WIDTH "5"
+# endif
+# ifndef PRINTF_UINT16_DEC_WIDTH
+# define PRINTF_UINT16_DEC_WIDTH "5"
+# endif
+# ifndef PRINTF_INT8_DEC_WIDTH
+# define PRINTF_INT8_DEC_WIDTH "3"
+# endif
+# ifndef PRINTF_UINT8_DEC_WIDTH
+# define PRINTF_UINT8_DEC_WIDTH "3"
+# endif
+# ifndef PRINTF_INTMAX_HEX_WIDTH
+# define PRINTF_INTMAX_HEX_WIDTH PRINTF_UINT64_HEX_WIDTH
+# endif
+# ifndef PRINTF_UINTMAX_HEX_WIDTH
+# define PRINTF_UINTMAX_HEX_WIDTH PRINTF_UINT64_HEX_WIDTH
+# endif
+# ifndef PRINTF_INTMAX_DEC_WIDTH
+# define PRINTF_INTMAX_DEC_WIDTH PRINTF_UINT64_DEC_WIDTH
+# endif
+# ifndef PRINTF_UINTMAX_DEC_WIDTH
+# define PRINTF_UINTMAX_DEC_WIDTH PRINTF_UINT64_DEC_WIDTH
+# endif
+
+/*
+ * Something really weird is going on with Open Watcom. Just pull some of
+ * these duplicated definitions from Open Watcom's stdint.h file for now.
+ */
+
+# if defined (__WATCOMC__) && __WATCOMC__ >= 1250
+# if !defined (INT64_C)
+# define INT64_C(x) (x + (INT64_MAX - INT64_MAX))
+# endif
+# if !defined (UINT64_C)
+# define UINT64_C(x) (x + (UINT64_MAX - UINT64_MAX))
+# endif
+# if !defined (INT32_C)
+# define INT32_C(x) (x + (INT32_MAX - INT32_MAX))
+# endif
+# if !defined (UINT32_C)
+# define UINT32_C(x) (x + (UINT32_MAX - UINT32_MAX))
+# endif
+# if !defined (INT16_C)
+# define INT16_C(x) (x)
+# endif
+# if !defined (UINT16_C)
+# define UINT16_C(x) (x)
+# endif
+# if !defined (INT8_C)
+# define INT8_C(x) (x)
+# endif
+# if !defined (UINT8_C)
+# define UINT8_C(x) (x)
+# endif
+# if !defined (UINT64_MAX)
+# define UINT64_MAX 18446744073709551615ULL
+# endif
+# if !defined (INT64_MAX)
+# define INT64_MAX 9223372036854775807LL
+# endif
+# if !defined (UINT32_MAX)
+# define UINT32_MAX 4294967295UL
+# endif
+# if !defined (INT32_MAX)
+# define INT32_MAX 2147483647L
+# endif
+# if !defined (INTMAX_MAX)
+# define INTMAX_MAX INT64_MAX
+# endif
+# if !defined (INTMAX_MIN)
+# define INTMAX_MIN INT64_MIN
+# endif
+# endif
+#endif
+
+/*
+ * I have no idea what is the truly correct thing to do on older Solaris.
+ * From some online discussions, this seems to be what is being
+ * recommended. For people who actually are developing on older Solaris,
+ * what I would like to know is, does this define all of the relevant
+ * macros of a complete stdint.h? Remember, in pstdint.h 64 bit is
+ * considered optional.
+ */
+
+#if (defined(__SUNPRO_C) && __SUNPRO_C >= 0x420) && !defined(_PSTDINT_H_INCLUDED)
+#include <sys/inttypes.h>
+#define _PSTDINT_H_INCLUDED
+#endif
+
+#ifndef _PSTDINT_H_INCLUDED
+#define _PSTDINT_H_INCLUDED
+
+#ifndef SIZE_MAX
+# define SIZE_MAX (~(size_t)0)
+#endif
+
+/*
+ * Deduce the type assignments from limits.h under the assumption that
+ * integer sizes in bits are powers of 2, and follow the ANSI
+ * definitions.
+ */
+
+#ifndef UINT8_MAX
+# define UINT8_MAX 0xff
+#endif
+#if !defined(uint8_t) && !defined(_UINT8_T) && !defined(vxWorks)
+# if (UCHAR_MAX == UINT8_MAX) || defined (S_SPLINT_S)
+ typedef unsigned char uint8_t;
+# define UINT8_C(v) ((uint8_t) v)
+# else
+# error "Platform not supported"
+# endif
+#endif
+
+#ifndef INT8_MAX
+# define INT8_MAX 0x7f
+#endif
+#ifndef INT8_MIN
+# define INT8_MIN INT8_C(0x80)
+#endif
+#if !defined(int8_t) && !defined(_INT8_T) && !defined(vxWorks)
+# if (SCHAR_MAX == INT8_MAX) || defined (S_SPLINT_S)
+ typedef signed char int8_t;
+# define INT8_C(v) ((int8_t) v)
+# else
+# error "Platform not supported"
+# endif
+#endif
+
+#ifndef UINT16_MAX
+# define UINT16_MAX 0xffff
+#endif
+#if !defined(uint16_t) && !defined(_UINT16_T) && !defined(vxWorks)
+#if (UINT_MAX == UINT16_MAX) || defined (S_SPLINT_S)
+ typedef unsigned int uint16_t;
+# ifndef PRINTF_INT16_MODIFIER
+# define PRINTF_INT16_MODIFIER ""
+# endif
+# define UINT16_C(v) ((uint16_t) (v))
+#elif (USHRT_MAX == UINT16_MAX)
+ typedef unsigned short uint16_t;
+# define UINT16_C(v) ((uint16_t) (v))
+# ifndef PRINTF_INT16_MODIFIER
+# define PRINTF_INT16_MODIFIER "h"
+# endif
+#else
+#error "Platform not supported"
+#endif
+#endif
+
+#ifndef INT16_MAX
+# define INT16_MAX 0x7fff
+#endif
+#ifndef INT16_MIN
+# define INT16_MIN INT16_C(0x8000)
+#endif
+#if !defined(int16_t) && !defined(_INT16_T) && !defined(vxWorks)
+#if (INT_MAX == INT16_MAX) || defined (S_SPLINT_S)
+ typedef signed int int16_t;
+# define INT16_C(v) ((int16_t) (v))
+# ifndef PRINTF_INT16_MODIFIER
+# define PRINTF_INT16_MODIFIER ""
+# endif
+#elif (SHRT_MAX == INT16_MAX)
+ typedef signed short int16_t;
+# define INT16_C(v) ((int16_t) (v))
+# ifndef PRINTF_INT16_MODIFIER
+# define PRINTF_INT16_MODIFIER "h"
+# endif
+#else
+#error "Platform not supported"
+#endif
+#endif
+
+#ifndef UINT32_MAX
+# define UINT32_MAX (0xffffffffUL)
+#endif
+#if !defined(uint32_t) && !defined(_UINT32_T) && !defined(vxWorks)
+#if (ULONG_MAX == UINT32_MAX) || defined (S_SPLINT_S)
+ typedef unsigned long uint32_t;
+# define UINT32_C(v) v ## UL
+# ifndef PRINTF_INT32_MODIFIER
+# define PRINTF_INT32_MODIFIER "l"
+# endif
+#elif (UINT_MAX == UINT32_MAX)
+ typedef unsigned int uint32_t;
+# ifndef PRINTF_INT32_MODIFIER
+# define PRINTF_INT32_MODIFIER ""
+# endif
+# define UINT32_C(v) v ## U
+#elif (USHRT_MAX == UINT32_MAX)
+ typedef unsigned short uint32_t;
+# define UINT32_C(v) ((unsigned short) (v))
+# ifndef PRINTF_INT32_MODIFIER
+# define PRINTF_INT32_MODIFIER ""
+# endif
+#else
+#error "Platform not supported"
+#endif
+#endif
+
+#ifndef INT32_MAX
+# define INT32_MAX (0x7fffffffL)
+#endif
+#ifndef INT32_MIN
+# define INT32_MIN INT32_C(0x80000000)
+#endif
+#if !defined(int32_t) && !defined(_INT32_T) && !defined(vxWorks)
+#if (LONG_MAX == INT32_MAX) || defined (S_SPLINT_S)
+ typedef signed long int32_t;
+# define INT32_C(v) v ## L
+# ifndef PRINTF_INT32_MODIFIER
+# define PRINTF_INT32_MODIFIER "l"
+# endif
+#elif (INT_MAX == INT32_MAX)
+ typedef signed int int32_t;
+# define INT32_C(v) v
+# ifndef PRINTF_INT32_MODIFIER
+# define PRINTF_INT32_MODIFIER ""
+# endif
+#elif (SHRT_MAX == INT32_MAX)
+ typedef signed short int32_t;
+# define INT32_C(v) ((short) (v))
+# ifndef PRINTF_INT32_MODIFIER
+# define PRINTF_INT32_MODIFIER ""
+# endif
+#else
+#error "Platform not supported"
+#endif
+#endif
+
+/*
+ * The macro stdint_int64_defined is temporarily used to record
+ * whether or not 64 integer support is available. It must be
+ * defined for any 64 integer extensions for new platforms that are
+ * added.
+ */
+
+#undef stdint_int64_defined
+#if (defined(__STDC__) && defined(__STDC_VERSION__)) || defined (S_SPLINT_S)
+# if (__STDC__ && __STDC_VERSION__ >= 199901L) || defined (S_SPLINT_S)
+# define stdint_int64_defined
+ typedef long long int64_t;
+ typedef unsigned long long uint64_t;
+# define UINT64_C(v) v ## ULL
+# define INT64_C(v) v ## LL
+# ifndef PRINTF_INT64_MODIFIER
+# define PRINTF_INT64_MODIFIER "ll"
+# endif
+# endif
+#endif
+
+#if !defined (stdint_int64_defined)
+# if defined(__GNUC__) && !defined(vxWorks)
+# define stdint_int64_defined
+ __extension__ typedef long long int64_t;
+ __extension__ typedef unsigned long long uint64_t;
+# define UINT64_C(v) v ## ULL
+# define INT64_C(v) v ## LL
+# ifndef PRINTF_INT64_MODIFIER
+# define PRINTF_INT64_MODIFIER "ll"
+# endif
+# elif defined(__MWERKS__) || defined (__SUNPRO_C) || defined (__SUNPRO_CC) || defined (__APPLE_CC__) || defined (_LONG_LONG) || defined (_CRAYC) || defined (S_SPLINT_S)
+# define stdint_int64_defined
+ typedef long long int64_t;
+ typedef unsigned long long uint64_t;
+# define UINT64_C(v) v ## ULL
+# define INT64_C(v) v ## LL
+# ifndef PRINTF_INT64_MODIFIER
+# define PRINTF_INT64_MODIFIER "ll"
+# endif
+# elif (defined(__WATCOMC__) && defined(__WATCOM_INT64__)) || (defined(_MSC_VER) && _INTEGRAL_MAX_BITS >= 64) || (defined (__BORLANDC__) && __BORLANDC__ > 0x460) || defined (__alpha) || defined (__DECC)
+# define stdint_int64_defined
+ typedef __int64 int64_t;
+ typedef unsigned __int64 uint64_t;
+# define UINT64_C(v) v ## UI64
+# define INT64_C(v) v ## I64
+# ifndef PRINTF_INT64_MODIFIER
+# define PRINTF_INT64_MODIFIER "I64"
+# endif
+# endif
+#endif
+
+#if !defined (LONG_LONG_MAX) && defined (INT64_C)
+# define LONG_LONG_MAX INT64_C (9223372036854775807)
+#endif
+#ifndef ULONG_LONG_MAX
+# define ULONG_LONG_MAX UINT64_C (18446744073709551615)
+#endif
+
+#if !defined (INT64_MAX) && defined (INT64_C)
+# define INT64_MAX INT64_C (9223372036854775807)
+#endif
+#if !defined (INT64_MIN) && defined (INT64_C)
+# define INT64_MIN INT64_C (-9223372036854775808)
+#endif
+#if !defined (UINT64_MAX) && defined (INT64_C)
+# define UINT64_MAX UINT64_C (18446744073709551615)
+#endif
+
+/*
+ * Width of hexadecimal for number field.
+ */
+
+#ifndef PRINTF_INT64_HEX_WIDTH
+# define PRINTF_INT64_HEX_WIDTH "16"
+#endif
+#ifndef PRINTF_INT32_HEX_WIDTH
+# define PRINTF_INT32_HEX_WIDTH "8"
+#endif
+#ifndef PRINTF_INT16_HEX_WIDTH
+# define PRINTF_INT16_HEX_WIDTH "4"
+#endif
+#ifndef PRINTF_INT8_HEX_WIDTH
+# define PRINTF_INT8_HEX_WIDTH "2"
+#endif
+#ifndef PRINTF_INT64_DEC_WIDTH
+# define PRINTF_INT64_DEC_WIDTH "19"
+#endif
+#ifndef PRINTF_INT32_DEC_WIDTH
+# define PRINTF_INT32_DEC_WIDTH "10"
+#endif
+#ifndef PRINTF_INT16_DEC_WIDTH
+# define PRINTF_INT16_DEC_WIDTH "5"
+#endif
+#ifndef PRINTF_INT8_DEC_WIDTH
+# define PRINTF_INT8_DEC_WIDTH "3"
+#endif
+#ifndef PRINTF_UINT64_DEC_WIDTH
+# define PRINTF_UINT64_DEC_WIDTH "20"
+#endif
+#ifndef PRINTF_UINT32_DEC_WIDTH
+# define PRINTF_UINT32_DEC_WIDTH "10"
+#endif
+#ifndef PRINTF_UINT16_DEC_WIDTH
+# define PRINTF_UINT16_DEC_WIDTH "5"
+#endif
+#ifndef PRINTF_UINT8_DEC_WIDTH
+# define PRINTF_UINT8_DEC_WIDTH "3"
+#endif
+
+/*
+ * Ok, lets not worry about 128 bit integers for now. Moore's law says
+ * we don't need to worry about that until about 2040 at which point
+ * we'll have bigger things to worry about.
+ */
+
+#ifdef stdint_int64_defined
+ typedef int64_t intmax_t;
+ typedef uint64_t uintmax_t;
+# define INTMAX_MAX INT64_MAX
+# define INTMAX_MIN INT64_MIN
+# define UINTMAX_MAX UINT64_MAX
+# define UINTMAX_C(v) UINT64_C(v)
+# define INTMAX_C(v) INT64_C(v)
+# ifndef PRINTF_INTMAX_MODIFIER
+# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER
+# endif
+# ifndef PRINTF_INTMAX_HEX_WIDTH
+# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH
+# endif
+# ifndef PRINTF_INTMAX_DEC_WIDTH
+# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH
+# endif
+#else
+ typedef int32_t intmax_t;
+ typedef uint32_t uintmax_t;
+# define INTMAX_MAX INT32_MAX
+# define UINTMAX_MAX UINT32_MAX
+# define UINTMAX_C(v) UINT32_C(v)
+# define INTMAX_C(v) INT32_C(v)
+# ifndef PRINTF_INTMAX_MODIFIER
+# define PRINTF_INTMAX_MODIFIER PRINTF_INT32_MODIFIER
+# endif
+# ifndef PRINTF_INTMAX_HEX_WIDTH
+# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT32_HEX_WIDTH
+# endif
+# ifndef PRINTF_INTMAX_DEC_WIDTH
+# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT32_DEC_WIDTH
+# endif
+#endif
+
+/*
+ * Because this file currently only supports platforms which have
+ * precise powers of 2 as bit sizes for the default integers, the
+ * least definitions are all trivial. Its possible that a future
+ * version of this file could have different definitions.
+ */
+
+#ifndef stdint_least_defined
+ typedef int8_t int_least8_t;
+ typedef uint8_t uint_least8_t;
+ typedef int16_t int_least16_t;
+ typedef uint16_t uint_least16_t;
+ typedef int32_t int_least32_t;
+ typedef uint32_t uint_least32_t;
+# define PRINTF_LEAST32_MODIFIER PRINTF_INT32_MODIFIER
+# define PRINTF_LEAST16_MODIFIER PRINTF_INT16_MODIFIER
+# define UINT_LEAST8_MAX UINT8_MAX
+# define INT_LEAST8_MAX INT8_MAX
+# define UINT_LEAST16_MAX UINT16_MAX
+# define INT_LEAST16_MAX INT16_MAX
+# define UINT_LEAST32_MAX UINT32_MAX
+# define INT_LEAST32_MAX INT32_MAX
+# define INT_LEAST8_MIN INT8_MIN
+# define INT_LEAST16_MIN INT16_MIN
+# define INT_LEAST32_MIN INT32_MIN
+# ifdef stdint_int64_defined
+ typedef int64_t int_least64_t;
+ typedef uint64_t uint_least64_t;
+# define PRINTF_LEAST64_MODIFIER PRINTF_INT64_MODIFIER
+# define UINT_LEAST64_MAX UINT64_MAX
+# define INT_LEAST64_MAX INT64_MAX
+# define INT_LEAST64_MIN INT64_MIN
+# endif
+#endif
+#undef stdint_least_defined
+
+/*
+ * The ANSI C committee pretending to know or specify anything about
+ * performance is the epitome of misguided arrogance. The mandate of
+ * this file is to *ONLY* ever support that absolute minimum
+ * definition of the fast integer types, for compatibility purposes.
+ * No extensions, and no attempt to suggest what may or may not be a
+ * faster integer type will ever be made in this file. Developers are
+ * warned to stay away from these types when using this or any other
+ * stdint.h.
+ */
+
+typedef int_least8_t int_fast8_t;
+typedef uint_least8_t uint_fast8_t;
+typedef int_least16_t int_fast16_t;
+typedef uint_least16_t uint_fast16_t;
+typedef int_least32_t int_fast32_t;
+typedef uint_least32_t uint_fast32_t;
+#define UINT_FAST8_MAX UINT_LEAST8_MAX
+#define INT_FAST8_MAX INT_LEAST8_MAX
+#define UINT_FAST16_MAX UINT_LEAST16_MAX
+#define INT_FAST16_MAX INT_LEAST16_MAX
+#define UINT_FAST32_MAX UINT_LEAST32_MAX
+#define INT_FAST32_MAX INT_LEAST32_MAX
+#define INT_FAST8_MIN INT_LEAST8_MIN
+#define INT_FAST16_MIN INT_LEAST16_MIN
+#define INT_FAST32_MIN INT_LEAST32_MIN
+#ifdef stdint_int64_defined
+ typedef int_least64_t int_fast64_t;
+ typedef uint_least64_t uint_fast64_t;
+# define UINT_FAST64_MAX UINT_LEAST64_MAX
+# define INT_FAST64_MAX INT_LEAST64_MAX
+# define INT_FAST64_MIN INT_LEAST64_MIN
+#endif
+
+#undef stdint_int64_defined
+
+/*
+ * Whatever piecemeal, per compiler thing we can do about the wchar_t
+ * type limits.
+ */
+
+#if defined(__WATCOMC__) || defined(_MSC_VER) || defined (__GNUC__) && !defined(vxWorks)
+# include <wchar.h>
+# ifndef WCHAR_MIN
+# define WCHAR_MIN 0
+# endif
+# ifndef WCHAR_MAX
+# define WCHAR_MAX ((wchar_t)-1)
+# endif
+#endif
+
+/*
+ * Whatever piecemeal, per compiler/platform thing we can do about the
+ * (u)intptr_t types and limits.
+ */
+
+#if (defined (_MSC_VER) && defined (_UINTPTR_T_DEFINED)) || defined (_UINTPTR_T)
+# define STDINT_H_UINTPTR_T_DEFINED
+#endif
+
+#ifndef STDINT_H_UINTPTR_T_DEFINED
+# if defined (__alpha__) || defined (__ia64__) || defined (__x86_64__) || defined (_WIN64) || defined (__ppc64__)
+# define stdint_intptr_bits 64
+# elif defined (__WATCOMC__) || defined (__TURBOC__)
+# if defined(__TINY__) || defined(__SMALL__) || defined(__MEDIUM__)
+# define stdint_intptr_bits 16
+# else
+# define stdint_intptr_bits 32
+# endif
+# elif defined (__i386__) || defined (_WIN32) || defined (WIN32) || defined (__ppc64__)
+# define stdint_intptr_bits 32
+# elif defined (__INTEL_COMPILER)
+/* TODO -- what did Intel do about x86-64? */
+# else
+/* #error "This platform might not be supported yet" */
+# endif
+
+# ifdef stdint_intptr_bits
+# define stdint_intptr_glue3_i(a,b,c) a##b##c
+# define stdint_intptr_glue3(a,b,c) stdint_intptr_glue3_i(a,b,c)
+# ifndef PRINTF_INTPTR_MODIFIER
+# define PRINTF_INTPTR_MODIFIER stdint_intptr_glue3(PRINTF_INT,stdint_intptr_bits,_MODIFIER)
+# endif
+# ifndef PTRDIFF_MAX
+# define PTRDIFF_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX)
+# endif
+# ifndef PTRDIFF_MIN
+# define PTRDIFF_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN)
+# endif
+# ifndef UINTPTR_MAX
+# define UINTPTR_MAX stdint_intptr_glue3(UINT,stdint_intptr_bits,_MAX)
+# endif
+# ifndef INTPTR_MAX
+# define INTPTR_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX)
+# endif
+# ifndef INTPTR_MIN
+# define INTPTR_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN)
+# endif
+# ifndef INTPTR_C
+# define INTPTR_C(x) stdint_intptr_glue3(INT,stdint_intptr_bits,_C)(x)
+# endif
+# ifndef UINTPTR_C
+# define UINTPTR_C(x) stdint_intptr_glue3(UINT,stdint_intptr_bits,_C)(x)
+# endif
+ typedef stdint_intptr_glue3(uint,stdint_intptr_bits,_t) uintptr_t;
+ typedef stdint_intptr_glue3( int,stdint_intptr_bits,_t) intptr_t;
+# else
+/* TODO -- This following is likely wrong for some platforms, and does
+ nothing for the definition of uintptr_t. */
+ typedef ptrdiff_t intptr_t;
+# endif
+# define STDINT_H_UINTPTR_T_DEFINED
+#endif
+
+/*
+ * Assumes sig_atomic_t is signed and we have a 2s complement machine.
+ */
+
+#ifndef SIG_ATOMIC_MAX
+# define SIG_ATOMIC_MAX ((((sig_atomic_t) 1) << (sizeof (sig_atomic_t)*CHAR_BIT-1)) - 1)
+#endif
+
+#endif
+
+#if defined (__TEST_PSTDINT_FOR_CORRECTNESS)
+
+/*
+ * Please compile with the maximum warning settings to make sure macros are
+ * not defined more than once.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#define glue3_aux(x,y,z) x ## y ## z
+#define glue3(x,y,z) glue3_aux(x,y,z)
+
+#define DECLU(bits) glue3(uint,bits,_t) glue3(u,bits,) = glue3(UINT,bits,_C) (0);
+#define DECLI(bits) glue3(int,bits,_t) glue3(i,bits,) = glue3(INT,bits,_C) (0);
+
+#define DECL(us,bits) glue3(DECL,us,) (bits)
+
+#define TESTUMAX(bits) glue3(u,bits,) = ~glue3(u,bits,); if (glue3(UINT,bits,_MAX) != glue3(u,bits,)) printf ("Something wrong with UINT%d_MAX\n", bits)
+
+#define REPORTERROR(msg) { err_n++; if (err_first <= 0) err_first = __LINE__; printf msg; }
+
+int main () {
+ int err_n = 0;
+ int err_first = 0;
+ DECL(I,8)
+ DECL(U,8)
+ DECL(I,16)
+ DECL(U,16)
+ DECL(I,32)
+ DECL(U,32)
+#ifdef INT64_MAX
+ DECL(I,64)
+ DECL(U,64)
+#endif
+ intmax_t imax = INTMAX_C(0);
+ uintmax_t umax = UINTMAX_C(0);
+ char str0[256], str1[256];
+
+ sprintf (str0, "%" PRINTF_INT32_MODIFIER "d", INT32_C(2147483647));
+ if (0 != strcmp (str0, "2147483647")) REPORTERROR (("Something wrong with PRINTF_INT32_MODIFIER : %s\n", str0));
+ if (atoi(PRINTF_INT32_DEC_WIDTH) != (int) strlen(str0)) REPORTERROR (("Something wrong with PRINTF_INT32_DEC_WIDTH : %s\n", PRINTF_INT32_DEC_WIDTH));
+ sprintf (str0, "%" PRINTF_INT32_MODIFIER "u", UINT32_C(4294967295));
+ if (0 != strcmp (str0, "4294967295")) REPORTERROR (("Something wrong with PRINTF_INT32_MODIFIER : %s\n", str0));
+ if (atoi(PRINTF_UINT32_DEC_WIDTH) != (int) strlen(str0)) REPORTERROR (("Something wrong with PRINTF_UINT32_DEC_WIDTH : %s\n", PRINTF_UINT32_DEC_WIDTH));
+#ifdef INT64_MAX
+ sprintf (str1, "%" PRINTF_INT64_MODIFIER "d", INT64_C(9223372036854775807));
+ if (0 != strcmp (str1, "9223372036854775807")) REPORTERROR (("Something wrong with PRINTF_INT32_MODIFIER : %s\n", str1));
+ if (atoi(PRINTF_INT64_DEC_WIDTH) != (int) strlen(str1)) REPORTERROR (("Something wrong with PRINTF_INT64_DEC_WIDTH : %s, %d\n", PRINTF_INT64_DEC_WIDTH, (int) strlen(str1)));
+ sprintf (str1, "%" PRINTF_INT64_MODIFIER "u", UINT64_C(18446744073709550591));
+ if (0 != strcmp (str1, "18446744073709550591")) REPORTERROR (("Something wrong with PRINTF_INT32_MODIFIER : %s\n", str1));
+ if (atoi(PRINTF_UINT64_DEC_WIDTH) != (int) strlen(str1)) REPORTERROR (("Something wrong with PRINTF_UINT64_DEC_WIDTH : %s, %d\n", PRINTF_UINT64_DEC_WIDTH, (int) strlen(str1)));
+#endif
+
+ sprintf (str0, "%d %x\n", 0, ~0);
+
+ sprintf (str1, "%d %x\n", i8, ~0);
+ if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with i8 : %s\n", str1));
+ sprintf (str1, "%u %x\n", u8, ~0);
+ if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with u8 : %s\n", str1));
+ sprintf (str1, "%d %x\n", i16, ~0);
+ if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with i16 : %s\n", str1));
+ sprintf (str1, "%u %x\n", u16, ~0);
+ if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with u16 : %s\n", str1));
+ sprintf (str1, "%" PRINTF_INT32_MODIFIER "d %x\n", i32, ~0);
+ if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with i32 : %s\n", str1));
+ sprintf (str1, "%" PRINTF_INT32_MODIFIER "u %x\n", u32, ~0);
+ if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with u32 : %s\n", str1));
+#ifdef INT64_MAX
+ sprintf (str1, "%" PRINTF_INT64_MODIFIER "d %x\n", i64, ~0);
+ if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with i64 : %s\n", str1));
+#endif
+ sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "d %x\n", imax, ~0);
+ if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with imax : %s\n", str1));
+ sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "u %x\n", umax, ~0);
+ if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with umax : %s\n", str1));
+
+ TESTUMAX(8);
+ TESTUMAX(16);
+ TESTUMAX(32);
+#ifdef INT64_MAX
+ TESTUMAX(64);
+#endif
+
+#define STR(v) #v
+#define Q(v) printf ("sizeof " STR(v) " = %u\n", (unsigned) sizeof (v));
+ if (err_n) {
+ printf ("pstdint.h is not correct. Please use sizes below to correct it:\n");
+ }
+
+ Q(int)
+ Q(unsigned)
+ Q(long int)
+ Q(short int)
+ Q(int8_t)
+ Q(int16_t)
+ Q(int32_t)
+#ifdef INT64_MAX
+ Q(int64_t)
+#endif
+
+ return EXIT_SUCCESS;
+}
+
+#endif
diff --git a/thirdparty/assimp/include/assimp/Compiler/pushpack1.h b/thirdparty/assimp/include/assimp/Compiler/pushpack1.h
new file mode 100644
index 0000000000..4c9fbb857f
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/Compiler/pushpack1.h
@@ -0,0 +1,43 @@
+
+
+// ===============================================================================
+// May be included multiple times - sets structure packing to 1
+// for all supported compilers. #include <poppack1.h> reverts the changes.
+//
+// Currently this works on the following compilers:
+// MSVC 7,8,9
+// GCC
+// BORLAND (complains about 'pack state changed but not reverted', but works)
+// Clang
+//
+//
+// USAGE:
+//
+// struct StructToBePacked {
+// } PACK_STRUCT;
+//
+// ===============================================================================
+
+#ifdef AI_PUSHPACK_IS_DEFINED
+# error poppack1.h must be included after pushpack1.h
+#endif
+
+#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
+# pragma pack(push,1)
+# define PACK_STRUCT
+#elif defined( __GNUC__ ) || defined(__clang__)
+# if !defined(HOST_MINGW)
+# define PACK_STRUCT __attribute__((__packed__))
+# else
+# define PACK_STRUCT __attribute__((gcc_struct, __packed__))
+# endif
+#else
+# error Compiler not supported
+#endif
+
+#if defined(_MSC_VER)
+// C4103: Packing was changed after the inclusion of the header, probably missing #pragma pop
+# pragma warning (disable : 4103)
+#endif
+
+#define AI_PUSHPACK_IS_DEFINED
diff --git a/thirdparty/assimp/include/assimp/CreateAnimMesh.h b/thirdparty/assimp/include/assimp/CreateAnimMesh.h
new file mode 100644
index 0000000000..a60173588f
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/CreateAnimMesh.h
@@ -0,0 +1,58 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file CreateAnimMesh.h
+ * Create AnimMesh from Mesh
+ */
+#ifndef INCLUDED_AI_CREATE_ANIM_MESH_H
+#define INCLUDED_AI_CREATE_ANIM_MESH_H
+
+#include <assimp/mesh.h>
+
+namespace Assimp {
+
+/** Create aiAnimMesh from aiMesh. */
+ASSIMP_API aiAnimMesh *aiCreateAnimMesh(const aiMesh *mesh);
+
+} // end of namespace Assimp
+#endif // INCLUDED_AI_CREATE_ANIM_MESH_H
+
diff --git a/thirdparty/assimp/include/assimp/DefaultIOStream.h b/thirdparty/assimp/include/assimp/DefaultIOStream.h
new file mode 100644
index 0000000000..994d728ff5
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/DefaultIOStream.h
@@ -0,0 +1,140 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file Default file I/O using fXXX()-family of functions */
+#ifndef AI_DEFAULTIOSTREAM_H_INC
+#define AI_DEFAULTIOSTREAM_H_INC
+
+#include <stdio.h>
+#include <assimp/IOStream.hpp>
+#include <assimp/importerdesc.h>
+#include <assimp/Defines.h>
+
+namespace Assimp {
+
+// ----------------------------------------------------------------------------------
+//! @class DefaultIOStream
+//! @brief Default IO implementation, use standard IO operations
+//! @note An instance of this class can exist without a valid file handle
+//! attached to it. All calls fail, but the instance can nevertheless be
+//! used with no restrictions.
+class ASSIMP_API DefaultIOStream : public IOStream
+{
+ friend class DefaultIOSystem;
+#if __ANDROID__
+# if __ANDROID_API__ > 9
+# if defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT)
+ friend class AndroidJNIIOSystem;
+# endif // defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT)
+# endif // __ANDROID_API__ > 9
+#endif // __ANDROID__
+
+protected:
+ DefaultIOStream() AI_NO_EXCEPT;
+ DefaultIOStream(FILE* pFile, const std::string &strFilename);
+
+public:
+ /** Destructor public to allow simple deletion to close the file. */
+ ~DefaultIOStream ();
+
+ // -------------------------------------------------------------------
+ /// Read from stream
+ size_t Read(void* pvBuffer,
+ size_t pSize,
+ size_t pCount);
+
+
+ // -------------------------------------------------------------------
+ /// Write to stream
+ size_t Write(const void* pvBuffer,
+ size_t pSize,
+ size_t pCount);
+
+ // -------------------------------------------------------------------
+ /// Seek specific position
+ aiReturn Seek(size_t pOffset,
+ aiOrigin pOrigin);
+
+ // -------------------------------------------------------------------
+ /// Get current seek position
+ size_t Tell() const;
+
+ // -------------------------------------------------------------------
+ /// Get size of file
+ size_t FileSize() const;
+
+ // -------------------------------------------------------------------
+ /// Flush file contents
+ void Flush();
+
+private:
+ // File data-structure, using clib
+ FILE* mFile;
+ // Filename
+ std::string mFilename;
+ // Cached file size
+ mutable size_t mCachedSize;
+};
+
+// ----------------------------------------------------------------------------------
+inline
+DefaultIOStream::DefaultIOStream() AI_NO_EXCEPT
+: mFile(nullptr)
+, mFilename("")
+, mCachedSize(SIZE_MAX) {
+ // empty
+}
+
+// ----------------------------------------------------------------------------------
+inline
+DefaultIOStream::DefaultIOStream (FILE* pFile, const std::string &strFilename)
+: mFile(pFile)
+, mFilename(strFilename)
+, mCachedSize(SIZE_MAX) {
+ // empty
+}
+// ----------------------------------------------------------------------------------
+
+} // ns assimp
+
+#endif //!!AI_DEFAULTIOSTREAM_H_INC
+
diff --git a/thirdparty/assimp/include/assimp/DefaultIOSystem.h b/thirdparty/assimp/include/assimp/DefaultIOSystem.h
new file mode 100644
index 0000000000..2dd5c801b5
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/DefaultIOSystem.h
@@ -0,0 +1,93 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file Default implementation of IOSystem using the standard C file functions */
+#ifndef AI_DEFAULTIOSYSTEM_H_INC
+#define AI_DEFAULTIOSYSTEM_H_INC
+
+#include <assimp/IOSystem.hpp>
+
+namespace Assimp {
+
+// ---------------------------------------------------------------------------
+/** Default implementation of IOSystem using the standard C file functions */
+class ASSIMP_API DefaultIOSystem : public IOSystem {
+public:
+ // -------------------------------------------------------------------
+ /** Tests for the existence of a file at the given path. */
+ bool Exists( const char* pFile) const;
+
+ // -------------------------------------------------------------------
+ /** Returns the directory separator. */
+ char getOsSeparator() const;
+
+ // -------------------------------------------------------------------
+ /** Open a new file with a given path. */
+ IOStream* Open( const char* pFile, const char* pMode = "rb");
+
+ // -------------------------------------------------------------------
+ /** Closes the given file and releases all resources associated with it. */
+ void Close( IOStream* pFile);
+
+ // -------------------------------------------------------------------
+ /** Compare two paths */
+ bool ComparePaths (const char* one, const char* second) const;
+
+ /** @brief get the file name of a full filepath
+ * example: /tmp/archive.tar.gz -> archive.tar.gz
+ */
+ static std::string fileName( const std::string &path );
+
+ /** @brief get the complete base name of a full filepath
+ * example: /tmp/archive.tar.gz -> archive.tar
+ */
+ static std::string completeBaseName( const std::string &path);
+
+ /** @brief get the path of a full filepath
+ * example: /tmp/archive.tar.gz -> /tmp/
+ */
+ static std::string absolutePath( const std::string &path);
+};
+
+} //!ns Assimp
+
+#endif //AI_DEFAULTIOSYSTEM_H_INC
diff --git a/thirdparty/assimp/include/assimp/DefaultLogger.hpp b/thirdparty/assimp/include/assimp/DefaultLogger.hpp
new file mode 100644
index 0000000000..1946e250a6
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/DefaultLogger.hpp
@@ -0,0 +1,188 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+/** @file DefaultLogger.hpp
+*/
+
+#ifndef INCLUDED_AI_DEFAULTLOGGER
+#define INCLUDED_AI_DEFAULTLOGGER
+
+#include "Logger.hpp"
+#include "LogStream.hpp"
+#include "NullLogger.hpp"
+#include <vector>
+
+namespace Assimp {
+// ------------------------------------------------------------------------------------
+class IOStream;
+struct LogStreamInfo;
+
+/** default name of logfile */
+#define ASSIMP_DEFAULT_LOG_NAME "AssimpLog.txt"
+
+// ------------------------------------------------------------------------------------
+/** @brief CPP-API: Primary logging facility of Assimp.
+ *
+ * The library stores its primary #Logger as a static member of this class.
+ * #get() returns this primary logger. By default the underlying implementation is
+ * just a #NullLogger which rejects all log messages. By calling #create(), logging
+ * is turned on. To capture the log output multiple log streams (#LogStream) can be
+ * attach to the logger. Some default streams for common streaming locations (such as
+ * a file, std::cout, OutputDebugString()) are also provided.
+ *
+ * If you wish to customize the logging at an even deeper level supply your own
+ * implementation of #Logger to #set().
+ * @note The whole logging stuff causes a small extra overhead for all imports. */
+class ASSIMP_API DefaultLogger :
+ public Logger {
+
+public:
+
+ // ----------------------------------------------------------------------
+ /** @brief Creates a logging instance.
+ * @param name Name for log file. Only valid in combination
+ * with the aiDefaultLogStream_FILE flag.
+ * @param severity Log severity, VERBOSE turns on debug messages
+ * @param defStreams Default log streams to be attached. Any bitwise
+ * combination of the aiDefaultLogStream enumerated values.
+ * If #aiDefaultLogStream_FILE is specified but an empty string is
+ * passed for 'name', no log file is created at all.
+ * @param io IOSystem to be used to open external files (such as the
+ * log file). Pass NULL to rely on the default implementation.
+ * This replaces the default #NullLogger with a #DefaultLogger instance. */
+ static Logger *create(const char* name = ASSIMP_DEFAULT_LOG_NAME,
+ LogSeverity severity = NORMAL,
+ unsigned int defStreams = aiDefaultLogStream_DEBUGGER | aiDefaultLogStream_FILE,
+ IOSystem* io = NULL);
+
+ // ----------------------------------------------------------------------
+ /** @brief Setup a custom #Logger implementation.
+ *
+ * Use this if the provided #DefaultLogger class doesn't fit into
+ * your needs. If the provided message formatting is OK for you,
+ * it's much easier to use #create() and to attach your own custom
+ * output streams to it.
+ * @param logger Pass NULL to setup a default NullLogger*/
+ static void set (Logger *logger);
+
+ // ----------------------------------------------------------------------
+ /** @brief Getter for singleton instance
+ * @return Only instance. This is never null, but it could be a
+ * NullLogger. Use isNullLogger to check this.*/
+ static Logger *get();
+
+ // ----------------------------------------------------------------------
+ /** @brief Return whether a #NullLogger is currently active
+ * @return true if the current logger is a #NullLogger.
+ * Use create() or set() to setup a logger that does actually do
+ * something else than just rejecting all log messages. */
+ static bool isNullLogger();
+
+ // ----------------------------------------------------------------------
+ /** @brief Kills the current singleton logger and replaces it with a
+ * #NullLogger instance. */
+ static void kill();
+
+ // ----------------------------------------------------------------------
+ /** @copydoc Logger::attachStream */
+ bool attachStream(LogStream *pStream,
+ unsigned int severity);
+
+ // ----------------------------------------------------------------------
+ /** @copydoc Logger::detatchStream */
+ bool detatchStream(LogStream *pStream,
+ unsigned int severity);
+
+private:
+ // ----------------------------------------------------------------------
+ /** @briefPrivate construction for internal use by create().
+ * @param severity Logging granularity */
+ explicit DefaultLogger(LogSeverity severity);
+
+ // ----------------------------------------------------------------------
+ /** @briefDestructor */
+ ~DefaultLogger();
+
+ /** @brief Logs debug infos, only been written when severity level VERBOSE is set */
+ void OnDebug(const char* message);
+
+ /** @brief Logs an info message */
+ void OnInfo(const char* message);
+
+ /** @brief Logs a warning message */
+ void OnWarn(const char* message);
+
+ /** @brief Logs an error message */
+ void OnError(const char* message);
+
+ // ----------------------------------------------------------------------
+ /** @brief Writes a message to all streams */
+ void WriteToStreams(const char* message, ErrorSeverity ErrorSev );
+
+ // ----------------------------------------------------------------------
+ /** @brief Returns the thread id.
+ * @note This is an OS specific feature, if not supported, a
+ * zero will be returned.
+ */
+ unsigned int GetThreadID();
+
+private:
+ // Aliases for stream container
+ typedef std::vector<LogStreamInfo*> StreamArray;
+ typedef std::vector<LogStreamInfo*>::iterator StreamIt;
+ typedef std::vector<LogStreamInfo*>::const_iterator ConstStreamIt;
+
+ //! only logging instance
+ static Logger *m_pLogger;
+ static NullLogger s_pNullLogger;
+
+ //! Attached streams
+ StreamArray m_StreamArray;
+
+ bool noRepeatMsg;
+ char lastMsg[MAX_LOG_MESSAGE_LENGTH*2];
+ size_t lastLen;
+};
+// ------------------------------------------------------------------------------------
+
+} // Namespace Assimp
+
+#endif // !! INCLUDED_AI_DEFAULTLOGGER
diff --git a/thirdparty/assimp/include/assimp/Defines.h b/thirdparty/assimp/include/assimp/Defines.h
new file mode 100644
index 0000000000..15e1d83c26
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/Defines.h
@@ -0,0 +1,49 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+// We need those constants, workaround for any platforms where nobody defined them yet
+#if (!defined SIZE_MAX)
+# define SIZE_MAX (~((size_t)0))
+#endif
+
+#if (!defined UINT_MAX)
+# define UINT_MAX (~((unsigned int)0))
+#endif
+
diff --git a/thirdparty/assimp/include/assimp/Exceptional.h b/thirdparty/assimp/include/assimp/Exceptional.h
new file mode 100644
index 0000000000..5109b8f077
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/Exceptional.h
@@ -0,0 +1,125 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, assimp team
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+#ifndef INCLUDED_EXCEPTIONAL_H
+#define INCLUDED_EXCEPTIONAL_H
+
+#include <stdexcept>
+#include <assimp/DefaultIOStream.h>
+using std::runtime_error;
+
+#ifdef _MSC_VER
+# pragma warning(disable : 4275)
+#endif
+
+// ---------------------------------------------------------------------------
+/** FOR IMPORTER PLUGINS ONLY: Simple exception class to be thrown if an
+ * unrecoverable error occurs while importing. Loading APIs return
+ * NULL instead of a valid aiScene then. */
+class DeadlyImportError
+ : public runtime_error
+{
+public:
+ /** Constructor with arguments */
+ explicit DeadlyImportError( const std::string& errorText)
+ : runtime_error(errorText)
+ {
+ }
+
+private:
+};
+
+typedef DeadlyImportError DeadlyExportError;
+
+#ifdef _MSC_VER
+# pragma warning(default : 4275)
+#endif
+
+// ---------------------------------------------------------------------------
+template <typename T>
+struct ExceptionSwallower {
+ T operator ()() const {
+ return T();
+ }
+};
+
+// ---------------------------------------------------------------------------
+template <typename T>
+struct ExceptionSwallower<T*> {
+ T* operator ()() const {
+ return NULL;
+ }
+};
+
+// ---------------------------------------------------------------------------
+template <>
+struct ExceptionSwallower<aiReturn> {
+ aiReturn operator ()() const {
+ try {
+ throw;
+ }
+ catch (std::bad_alloc&) {
+ return aiReturn_OUTOFMEMORY;
+ }
+ catch (...) {
+ return aiReturn_FAILURE;
+ }
+ }
+};
+
+// ---------------------------------------------------------------------------
+template <>
+struct ExceptionSwallower<void> {
+ void operator ()() const {
+ return;
+ }
+};
+
+#define ASSIMP_BEGIN_EXCEPTION_REGION()\
+{\
+ try {
+
+#define ASSIMP_END_EXCEPTION_REGION(type)\
+ } catch(...) {\
+ return ExceptionSwallower<type>()();\
+ }\
+}
+
+#endif // INCLUDED_EXCEPTIONAL_H
diff --git a/thirdparty/assimp/include/assimp/Exporter.hpp b/thirdparty/assimp/include/assimp/Exporter.hpp
new file mode 100644
index 0000000000..bf0096e7e9
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/Exporter.hpp
@@ -0,0 +1,505 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file Exporter.hpp
+* @brief Defines the CPP-API for the Assimp export interface
+*/
+#pragma once
+#ifndef AI_EXPORT_HPP_INC
+#define AI_EXPORT_HPP_INC
+
+#ifndef ASSIMP_BUILD_NO_EXPORT
+
+#include "cexport.h"
+#include <map>
+
+namespace Assimp {
+
+class ExporterPimpl;
+class IOSystem;
+class ProgressHandler;
+
+// ----------------------------------------------------------------------------------
+/** CPP-API: The Exporter class forms an C++ interface to the export functionality
+ * of the Open Asset Import Library. Note that the export interface is available
+ * only if Assimp has been built with ASSIMP_BUILD_NO_EXPORT not defined.
+ *
+ * The interface is modeled after the importer interface and mostly
+ * symmetric. The same rules for threading etc. apply.
+ *
+ * In a nutshell, there are two export interfaces: #Export, which writes the
+ * output file(s) either to the regular file system or to a user-supplied
+ * #IOSystem, and #ExportToBlob which returns a linked list of memory
+ * buffers (blob), each referring to one output file (in most cases
+ * there will be only one output file of course, but this extra complexity is
+ * needed since Assimp aims at supporting a wide range of file formats).
+ *
+ * #ExportToBlob is especially useful if you intend to work
+ * with the data in-memory.
+*/
+class ASSIMP_API ExportProperties;
+
+class ASSIMP_API Exporter {
+public:
+ /** Function pointer type of a Export worker function */
+ typedef void (*fpExportFunc)(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+
+ /** Internal description of an Assimp export format option */
+ struct ExportFormatEntry {
+ /// Public description structure to be returned by aiGetExportFormatDescription()
+ aiExportFormatDesc mDescription;
+
+ // Worker function to do the actual exporting
+ fpExportFunc mExportFunction;
+
+ // Post-processing steps to be executed PRIOR to invoking mExportFunction
+ unsigned int mEnforcePP;
+
+ // Constructor to fill all entries
+ ExportFormatEntry( const char* pId, const char* pDesc, const char* pExtension, fpExportFunc pFunction, unsigned int pEnforcePP = 0u)
+ {
+ mDescription.id = pId;
+ mDescription.description = pDesc;
+ mDescription.fileExtension = pExtension;
+ mExportFunction = pFunction;
+ mEnforcePP = pEnforcePP;
+ }
+
+ ExportFormatEntry() :
+ mExportFunction()
+ , mEnforcePP()
+ {
+ mDescription.id = NULL;
+ mDescription.description = NULL;
+ mDescription.fileExtension = NULL;
+ }
+ };
+
+ /**
+ * @brief The class constructor.
+ */
+ Exporter();
+
+ /**
+ * @brief The class destructor.
+ */
+ ~Exporter();
+
+ // -------------------------------------------------------------------
+ /** Supplies a custom IO handler to the exporter to use to open and
+ * access files.
+ *
+ * If you need #Export to use custom IO logic to access the files,
+ * you need to supply a custom implementation of IOSystem and
+ * IOFile to the exporter.
+ *
+ * #Exporter takes ownership of the object and will destroy it
+ * afterwards. The previously assigned handler will be deleted.
+ * Pass NULL to take again ownership of your IOSystem and reset Assimp
+ * to use its default implementation, which uses plain file IO.
+ *
+ * @param pIOHandler The IO handler to be used in all file accesses
+ * of the Importer. */
+ void SetIOHandler( IOSystem* pIOHandler);
+
+ // -------------------------------------------------------------------
+ /** Retrieves the IO handler that is currently set.
+ * You can use #IsDefaultIOHandler() to check whether the returned
+ * interface is the default IO handler provided by ASSIMP. The default
+ * handler is active as long the application doesn't supply its own
+ * custom IO handler via #SetIOHandler().
+ * @return A valid IOSystem interface, never NULL. */
+ IOSystem* GetIOHandler() const;
+
+ // -------------------------------------------------------------------
+ /** Checks whether a default IO handler is active
+ * A default handler is active as long the application doesn't
+ * supply its own custom IO handler via #SetIOHandler().
+ * @return true by default */
+ bool IsDefaultIOHandler() const;
+
+ // -------------------------------------------------------------------
+ /** Supplies a custom progress handler to the exporter. This
+ * interface exposes an #Update() callback, which is called
+ * more or less periodically (please don't sue us if it
+ * isn't as periodically as you'd like it to have ...).
+ * This can be used to implement progress bars and loading
+ * timeouts.
+ * @param pHandler Progress callback interface. Pass nullptr to
+ * disable progress reporting.
+ * @note Progress handlers can be used to abort the loading
+ * at almost any time.*/
+ void SetProgressHandler(ProgressHandler* pHandler);
+
+ // -------------------------------------------------------------------
+ /** Exports the given scene to a chosen file format. Returns the exported
+ * data as a binary blob which you can write into a file or something.
+ * When you're done with the data, simply let the #Exporter instance go
+ * out of scope to have it released automatically.
+ * @param pScene The scene to export. Stays in possession of the caller,
+ * is not changed by the function.
+ * @param pFormatId ID string to specify to which format you want to
+ * export to. Use
+ * #GetExportFormatCount / #GetExportFormatDescription to learn which
+ * export formats are available.
+ * @param pPreprocessing See the documentation for #Export
+ * @return the exported data or NULL in case of error.
+ * @note If the Exporter instance did already hold a blob from
+ * a previous call to #ExportToBlob, it will be disposed.
+ * Any IO handlers set via #SetIOHandler are ignored here.
+ * @note Use aiCopyScene() to get a modifiable copy of a previously
+ * imported scene. */
+ const aiExportDataBlob* ExportToBlob(const aiScene* pScene, const char* pFormatId,
+ unsigned int pPreprocessing = 0u, const ExportProperties* = nullptr);
+ const aiExportDataBlob* ExportToBlob( const aiScene* pScene, const std::string& pFormatId,
+ unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = nullptr);
+
+ // -------------------------------------------------------------------
+ /** Convenience function to export directly to a file. Use
+ * #SetIOSystem to supply a custom IOSystem to gain fine-grained control
+ * about the output data flow of the export process.
+ * @param pBlob A data blob obtained from a previous call to #aiExportScene. Must not be NULL.
+ * @param pPath Full target file name. Target must be accessible.
+ * @param pPreprocessing Accepts any choice of the #aiPostProcessSteps enumerated
+ * flags, but in reality only a subset of them makes sense here. Specifying
+ * 'preprocessing' flags is useful if the input scene does not conform to
+ * Assimp's default conventions as specified in the @link data Data Structures Page @endlink.
+ * In short, this means the geometry data should use a right-handed coordinate systems, face
+ * winding should be counter-clockwise and the UV coordinate origin is assumed to be in
+ * the upper left. The #aiProcess_MakeLeftHanded, #aiProcess_FlipUVs and
+ * #aiProcess_FlipWindingOrder flags are used in the import side to allow users
+ * to have those defaults automatically adapted to their conventions. Specifying those flags
+ * for exporting has the opposite effect, respectively. Some other of the
+ * #aiPostProcessSteps enumerated values may be useful as well, but you'll need
+ * to try out what their effect on the exported file is. Many formats impose
+ * their own restrictions on the structure of the geometry stored therein,
+ * so some preprocessing may have little or no effect at all, or may be
+ * redundant as exporters would apply them anyhow. A good example
+ * is triangulation - whilst you can enforce it by specifying
+ * the #aiProcess_Triangulate flag, most export formats support only
+ * triangulate data so they would run the step even if it wasn't requested.
+ *
+ * If assimp detects that the input scene was directly taken from the importer side of
+ * the library (i.e. not copied using aiCopyScene and potentially modified afterwards),
+ * any post-processing steps already applied to the scene will not be applied again, unless
+ * they show non-idempotent behavior (#aiProcess_MakeLeftHanded, #aiProcess_FlipUVs and
+ * #aiProcess_FlipWindingOrder).
+ * @return AI_SUCCESS if everything was fine.
+ * @note Use aiCopyScene() to get a modifiable copy of a previously
+ * imported scene.*/
+ aiReturn Export( const aiScene* pScene, const char* pFormatId, const char* pPath,
+ unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = nullptr);
+ aiReturn Export( const aiScene* pScene, const std::string& pFormatId, const std::string& pPath,
+ unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = nullptr);
+
+ // -------------------------------------------------------------------
+ /** Returns an error description of an error that occurred in #Export
+ * or #ExportToBlob
+ *
+ * Returns an empty string if no error occurred.
+ * @return A description of the last error, an empty string if no
+ * error occurred. The string is never NULL.
+ *
+ * @note The returned function remains valid until one of the
+ * following methods is called: #Export, #ExportToBlob, #FreeBlob */
+ const char* GetErrorString() const;
+
+ // -------------------------------------------------------------------
+ /** Return the blob obtained from the last call to #ExportToBlob */
+ const aiExportDataBlob* GetBlob() const;
+
+ // -------------------------------------------------------------------
+ /** Orphan the blob from the last call to #ExportToBlob. This means
+ * the caller takes ownership and is thus responsible for calling
+ * the C API function #aiReleaseExportBlob to release it. */
+ const aiExportDataBlob* GetOrphanedBlob() const;
+
+ // -------------------------------------------------------------------
+ /** Frees the current blob.
+ *
+ * The function does nothing if no blob has previously been
+ * previously produced via #ExportToBlob. #FreeBlob is called
+ * automatically by the destructor. The only reason to call
+ * it manually would be to reclaim as much storage as possible
+ * without giving up the #Exporter instance yet. */
+ void FreeBlob( );
+
+ // -------------------------------------------------------------------
+ /** Returns the number of export file formats available in the current
+ * Assimp build. Use #Exporter::GetExportFormatDescription to
+ * retrieve infos of a specific export format.
+ *
+ * This includes built-in exporters as well as exporters registered
+ * using #RegisterExporter.
+ **/
+ size_t GetExportFormatCount() const;
+
+ // -------------------------------------------------------------------
+ /** Returns a description of the nth export file format. Use #
+ * #Exporter::GetExportFormatCount to learn how many export
+ * formats are supported.
+ *
+ * The returned pointer is of static storage duration if the
+ * pIndex pertains to a built-in exporter (i.e. one not registered
+ * via #RegistrerExporter). It is restricted to the life-time of the
+ * #Exporter instance otherwise.
+ *
+ * @param pIndex Index of the export format to retrieve information
+ * for. Valid range is 0 to #Exporter::GetExportFormatCount
+ * @return A description of that specific export format.
+ * NULL if pIndex is out of range. */
+ const aiExportFormatDesc* GetExportFormatDescription( size_t pIndex ) const;
+
+ // -------------------------------------------------------------------
+ /** Register a custom exporter. Custom export formats are limited to
+ * to the current #Exporter instance and do not affect the
+ * library globally. The indexes under which the format's
+ * export format description can be queried are assigned
+ * monotonously.
+ * @param desc Exporter description.
+ * @return aiReturn_SUCCESS if the export format was successfully
+ * registered. A common cause that would prevent an exporter
+ * from being registered is that its format id is already
+ * occupied by another format. */
+ aiReturn RegisterExporter(const ExportFormatEntry& desc);
+
+ // -------------------------------------------------------------------
+ /** Remove an export format previously registered with #RegisterExporter
+ * from the #Exporter instance (this can also be used to drop
+ * built-in exporters because those are implicitly registered
+ * using #RegisterExporter).
+ * @param id Format id to be unregistered, this refers to the
+ * 'id' field of #aiExportFormatDesc.
+ * @note Calling this method on a format description not yet registered
+ * has no effect.*/
+ void UnregisterExporter(const char* id);
+
+protected:
+ // Just because we don't want you to know how we're hacking around.
+ ExporterPimpl* pimpl;
+};
+
+class ASSIMP_API ExportProperties {
+public:
+ // Data type to store the key hash
+ typedef unsigned int KeyType;
+
+ // typedefs for our four configuration maps.
+ // We don't need more, so there is no need for a generic solution
+ typedef std::map<KeyType, int> IntPropertyMap;
+ typedef std::map<KeyType, ai_real> FloatPropertyMap;
+ typedef std::map<KeyType, std::string> StringPropertyMap;
+ typedef std::map<KeyType, aiMatrix4x4> MatrixPropertyMap;
+
+public:
+ /** Standard constructor
+ * @see ExportProperties()
+ */
+ ExportProperties();
+
+ // -------------------------------------------------------------------
+ /** Copy constructor.
+ *
+ * This copies the configuration properties of another ExportProperties.
+ * @see ExportProperties(const ExportProperties& other)
+ */
+ ExportProperties(const ExportProperties& other);
+
+ // -------------------------------------------------------------------
+ /** Set an integer configuration property.
+ * @param szName Name of the property. All supported properties
+ * are defined in the aiConfig.g header (all constants share the
+ * prefix AI_CONFIG_XXX and are simple strings).
+ * @param iValue New value of the property
+ * @return true if the property was set before. The new value replaces
+ * the previous value in this case.
+ * @note Property of different types (float, int, string ..) are kept
+ * on different stacks, so calling SetPropertyInteger() for a
+ * floating-point property has no effect - the loader will call
+ * GetPropertyFloat() to read the property, but it won't be there.
+ */
+ bool SetPropertyInteger(const char* szName, int iValue);
+
+ // -------------------------------------------------------------------
+ /** Set a boolean configuration property. Boolean properties
+ * are stored on the integer stack internally so it's possible
+ * to set them via #SetPropertyBool and query them with
+ * #GetPropertyBool and vice versa.
+ * @see SetPropertyInteger()
+ */
+ bool SetPropertyBool(const char* szName, bool value) {
+ return SetPropertyInteger(szName,value);
+ }
+
+ // -------------------------------------------------------------------
+ /** Set a floating-point configuration property.
+ * @see SetPropertyInteger()
+ */
+ bool SetPropertyFloat(const char* szName, ai_real fValue);
+
+ // -------------------------------------------------------------------
+ /** Set a string configuration property.
+ * @see SetPropertyInteger()
+ */
+ bool SetPropertyString(const char* szName, const std::string& sValue);
+
+ // -------------------------------------------------------------------
+ /** Set a matrix configuration property.
+ * @see SetPropertyInteger()
+ */
+ bool SetPropertyMatrix(const char* szName, const aiMatrix4x4& sValue);
+
+ // -------------------------------------------------------------------
+ /** Get a configuration property.
+ * @param szName Name of the property. All supported properties
+ * are defined in the aiConfig.g header (all constants share the
+ * prefix AI_CONFIG_XXX).
+ * @param iErrorReturn Value that is returned if the property
+ * is not found.
+ * @return Current value of the property
+ * @note Property of different types (float, int, string ..) are kept
+ * on different lists, so calling SetPropertyInteger() for a
+ * floating-point property has no effect - the loader will call
+ * GetPropertyFloat() to read the property, but it won't be there.
+ */
+ int GetPropertyInteger(const char* szName,
+ int iErrorReturn = 0xffffffff) const;
+
+ // -------------------------------------------------------------------
+ /** Get a boolean configuration property. Boolean properties
+ * are stored on the integer stack internally so it's possible
+ * to set them via #SetPropertyBool and query them with
+ * #GetPropertyBool and vice versa.
+ * @see GetPropertyInteger()
+ */
+ bool GetPropertyBool(const char* szName, bool bErrorReturn = false) const {
+ return GetPropertyInteger(szName,bErrorReturn)!=0;
+ }
+
+ // -------------------------------------------------------------------
+ /** Get a floating-point configuration property
+ * @see GetPropertyInteger()
+ */
+ ai_real GetPropertyFloat(const char* szName,
+ ai_real fErrorReturn = 10e10f) const;
+
+ // -------------------------------------------------------------------
+ /** Get a string configuration property
+ *
+ * The return value remains valid until the property is modified.
+ * @see GetPropertyInteger()
+ */
+ const std::string GetPropertyString(const char* szName,
+ const std::string& sErrorReturn = "") const;
+
+ // -------------------------------------------------------------------
+ /** Get a matrix configuration property
+ *
+ * The return value remains valid until the property is modified.
+ * @see GetPropertyInteger()
+ */
+ const aiMatrix4x4 GetPropertyMatrix(const char* szName,
+ const aiMatrix4x4& sErrorReturn = aiMatrix4x4()) const;
+
+ // -------------------------------------------------------------------
+ /** Determine a integer configuration property has been set.
+ * @see HasPropertyInteger()
+ */
+ bool HasPropertyInteger(const char* szName) const;
+
+ /** Determine a boolean configuration property has been set.
+ * @see HasPropertyBool()
+ */
+ bool HasPropertyBool(const char* szName) const;
+
+ /** Determine a boolean configuration property has been set.
+ * @see HasPropertyFloat()
+ */
+ bool HasPropertyFloat(const char* szName) const;
+
+ /** Determine a String configuration property has been set.
+ * @see HasPropertyString()
+ */
+ bool HasPropertyString(const char* szName) const;
+
+ /** Determine a Matrix configuration property has been set.
+ * @see HasPropertyMatrix()
+ */
+ bool HasPropertyMatrix(const char* szName) const;
+
+protected:
+
+ /** List of integer properties */
+ IntPropertyMap mIntProperties;
+
+ /** List of floating-point properties */
+ FloatPropertyMap mFloatProperties;
+
+ /** List of string properties */
+ StringPropertyMap mStringProperties;
+
+ /** List of Matrix properties */
+ MatrixPropertyMap mMatrixProperties;
+};
+
+// ----------------------------------------------------------------------------------
+inline
+const aiExportDataBlob* Exporter::ExportToBlob( const aiScene* pScene, const std::string& pFormatId,
+ unsigned int pPreprocessing, const ExportProperties* pProperties)
+{
+ return ExportToBlob(pScene,pFormatId.c_str(),pPreprocessing, pProperties);
+}
+
+// ----------------------------------------------------------------------------------
+inline
+aiReturn Exporter :: Export( const aiScene* pScene, const std::string& pFormatId,
+ const std::string& pPath, unsigned int pPreprocessing,
+ const ExportProperties* pProperties)
+{
+ return Export(pScene,pFormatId.c_str(),pPath.c_str(),pPreprocessing, pProperties);
+}
+
+} // namespace Assimp
+
+#endif // ASSIMP_BUILD_NO_EXPORT
+#endif // AI_EXPORT_HPP_INC
diff --git a/thirdparty/assimp/include/assimp/GenericProperty.h b/thirdparty/assimp/include/assimp/GenericProperty.h
new file mode 100644
index 0000000000..183ecd5197
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/GenericProperty.h
@@ -0,0 +1,133 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+#ifndef AI_GENERIC_PROPERTY_H_INCLUDED
+#define AI_GENERIC_PROPERTY_H_INCLUDED
+
+#include <assimp/Importer.hpp>
+#include <assimp/ai_assert.h>
+#include "Hash.h"
+
+#include <map>
+
+// ------------------------------------------------------------------------------------------------
+template <class T>
+inline
+bool SetGenericProperty(std::map< unsigned int, T >& list,
+ const char* szName, const T& value) {
+ ai_assert(nullptr != szName);
+ const uint32_t hash = SuperFastHash(szName);
+
+ typename std::map<unsigned int, T>::iterator it = list.find(hash);
+ if (it == list.end()) {
+ list.insert(std::pair<unsigned int, T>( hash, value ));
+ return false;
+ }
+ (*it).second = value;
+
+ return true;
+}
+
+// ------------------------------------------------------------------------------------------------
+template <class T>
+inline
+const T& GetGenericProperty(const std::map< unsigned int, T >& list,
+ const char* szName, const T& errorReturn) {
+ ai_assert(nullptr != szName);
+ const uint32_t hash = SuperFastHash(szName);
+
+ typename std::map<unsigned int, T>::const_iterator it = list.find(hash);
+ if (it == list.end()) {
+ return errorReturn;
+ }
+
+ return (*it).second;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Special version for pointer types - they will be deleted when replaced with another value
+// passing NULL removes the whole property
+template <class T>
+inline
+void SetGenericPropertyPtr(std::map< unsigned int, T* >& list,
+ const char* szName, T* value, bool* bWasExisting = nullptr ) {
+ ai_assert(nullptr != szName);
+ const uint32_t hash = SuperFastHash(szName);
+
+ typename std::map<unsigned int, T*>::iterator it = list.find(hash);
+ if (it == list.end()) {
+ if (bWasExisting) {
+ *bWasExisting = false;
+ }
+
+ list.insert(std::pair<unsigned int,T*>( hash, value ));
+ return;
+ }
+ if ((*it).second != value) {
+ delete (*it).second;
+ (*it).second = value;
+ }
+ if (!value) {
+ list.erase(it);
+ }
+ if (bWasExisting) {
+ *bWasExisting = true;
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+template <class T>
+inline
+bool HasGenericProperty(const std::map< unsigned int, T >& list,
+ const char* szName) {
+ ai_assert(nullptr != szName);
+ const uint32_t hash = SuperFastHash(szName);
+
+ typename std::map<unsigned int, T>::const_iterator it = list.find(hash);
+ if (it == list.end()) {
+ return false;
+ }
+
+ return true;
+}
+
+#endif // !! AI_GENERIC_PROPERTY_H_INCLUDED
diff --git a/thirdparty/assimp/include/assimp/Hash.h b/thirdparty/assimp/include/assimp/Hash.h
new file mode 100644
index 0000000000..30657be198
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/Hash.h
@@ -0,0 +1,118 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+#ifndef AI_HASH_H_INCLUDED
+#define AI_HASH_H_INCLUDED
+
+#include <stdint.h>
+#include <string.h>
+
+// ------------------------------------------------------------------------------------------------
+// Hashing function taken from
+// http://www.azillionmonkeys.com/qed/hash.html
+// (incremental version)
+//
+// This code is Copyright 2004-2008 by Paul Hsieh. It is used here in the belief that
+// Assimp's license is considered compatible with Pauls's derivative license as specified
+// on his web page.
+//
+// (stdint.h should have been been included here)
+// ------------------------------------------------------------------------------------------------
+#undef get16bits
+#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
+ || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
+#define get16bits(d) (*((const uint16_t *) (d)))
+#endif
+
+#if !defined (get16bits)
+#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\
+ +(uint32_t)(((const uint8_t *)(d))[0]) )
+#endif
+
+// ------------------------------------------------------------------------------------------------
+inline uint32_t SuperFastHash (const char * data, uint32_t len = 0, uint32_t hash = 0) {
+uint32_t tmp;
+int rem;
+
+ if (!data) return 0;
+ if (!len)len = (uint32_t)::strlen(data);
+
+ rem = len & 3;
+ len >>= 2;
+
+ /* Main loop */
+ for (;len > 0; len--) {
+ hash += get16bits (data);
+ tmp = (get16bits (data+2) << 11) ^ hash;
+ hash = (hash << 16) ^ tmp;
+ data += 2*sizeof (uint16_t);
+ hash += hash >> 11;
+ }
+
+ /* Handle end cases */
+ switch (rem) {
+ case 3: hash += get16bits (data);
+ hash ^= hash << 16;
+ hash ^= data[sizeof (uint16_t)] << 18;
+ hash += hash >> 11;
+ break;
+ case 2: hash += get16bits (data);
+ hash ^= hash << 11;
+ hash += hash >> 17;
+ break;
+ case 1: hash += *data;
+ hash ^= hash << 10;
+ hash += hash >> 1;
+ }
+
+ /* Force "avalanching" of final 127 bits */
+ hash ^= hash << 3;
+ hash += hash >> 5;
+ hash ^= hash << 4;
+ hash += hash >> 17;
+ hash ^= hash << 25;
+ hash += hash >> 6;
+
+ return hash;
+}
+
+#endif // !! AI_HASH_H_INCLUDED
diff --git a/thirdparty/assimp/include/assimp/IOStream.hpp b/thirdparty/assimp/include/assimp/IOStream.hpp
new file mode 100644
index 0000000000..0623d0f70b
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/IOStream.hpp
@@ -0,0 +1,142 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+/** @file IOStream.hpp
+ * @brief File I/O wrappers for C++.
+ */
+
+#pragma once
+#ifndef AI_IOSTREAM_H_INC
+#define AI_IOSTREAM_H_INC
+
+#include "types.h"
+
+#ifndef __cplusplus
+# error This header requires C++ to be used. aiFileIO.h is the \
+ corresponding C interface.
+#endif
+
+namespace Assimp {
+
+// ----------------------------------------------------------------------------------
+/** @brief CPP-API: Class to handle file I/O for C++
+ *
+ * Derive an own implementation from this interface to provide custom IO handling
+ * to the Importer. If you implement this interface, be sure to also provide an
+ * implementation for IOSystem that creates instances of your custom IO class.
+*/
+class ASSIMP_API IOStream
+#ifndef SWIG
+ : public Intern::AllocateFromAssimpHeap
+#endif
+{
+protected:
+ /** Constructor protected, use IOSystem::Open() to create an instance. */
+ IOStream() AI_NO_EXCEPT;
+
+public:
+ // -------------------------------------------------------------------
+ /** @brief Destructor. Deleting the object closes the underlying file,
+ * alternatively you may use IOSystem::Close() to release the file.
+ */
+ virtual ~IOStream();
+
+ // -------------------------------------------------------------------
+ /** @brief Read from the file
+ *
+ * See fread() for more details
+ * This fails for write-only files */
+ virtual size_t Read(void* pvBuffer,
+ size_t pSize,
+ size_t pCount) = 0;
+
+ // -------------------------------------------------------------------
+ /** @brief Write to the file
+ *
+ * See fwrite() for more details
+ * This fails for read-only files */
+ virtual size_t Write(const void* pvBuffer,
+ size_t pSize,
+ size_t pCount) = 0;
+
+ // -------------------------------------------------------------------
+ /** @brief Set the read/write cursor of the file
+ *
+ * Note that the offset is _negative_ for aiOrigin_END.
+ * See fseek() for more details */
+ virtual aiReturn Seek(size_t pOffset,
+ aiOrigin pOrigin) = 0;
+
+ // -------------------------------------------------------------------
+ /** @brief Get the current position of the read/write cursor
+ *
+ * See ftell() for more details */
+ virtual size_t Tell() const = 0;
+
+ // -------------------------------------------------------------------
+ /** @brief Returns filesize
+ * Returns the filesize. */
+ virtual size_t FileSize() const = 0;
+
+ // -------------------------------------------------------------------
+ /** @brief Flush the contents of the file buffer (for writers)
+ * See fflush() for more details.
+ */
+ virtual void Flush() = 0;
+}; //! class IOStream
+
+// ----------------------------------------------------------------------------------
+inline
+IOStream::IOStream() AI_NO_EXCEPT {
+ // empty
+}
+
+// ----------------------------------------------------------------------------------
+inline
+IOStream::~IOStream() {
+ // empty
+}
+// ----------------------------------------------------------------------------------
+
+} //!namespace Assimp
+
+#endif //!!AI_IOSTREAM_H_INC
diff --git a/thirdparty/assimp/include/assimp/IOStreamBuffer.h b/thirdparty/assimp/include/assimp/IOStreamBuffer.h
new file mode 100644
index 0000000000..58abd97a02
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/IOStreamBuffer.h
@@ -0,0 +1,355 @@
+#pragma once
+
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+#include <assimp/types.h>
+#include <assimp/IOStream.hpp>
+
+#include "ParsingUtils.h"
+
+#include <vector>
+
+namespace Assimp {
+
+// ---------------------------------------------------------------------------
+/**
+ * Implementation of a cached stream buffer.
+ */
+template<class T>
+class IOStreamBuffer {
+public:
+ /// @brief The class constructor.
+ IOStreamBuffer( size_t cache = 4096 * 4096 );
+
+ /// @brief The class destructor.
+ ~IOStreamBuffer();
+
+ /// @brief Will open the cached access for a given stream.
+ /// @param stream The stream to cache.
+ /// @return true if successful.
+ bool open( IOStream *stream );
+
+ /// @brief Will close the cached access.
+ /// @return true if successful.
+ bool close();
+
+ /// @brief Returns the file-size.
+ /// @return The file-size.
+ size_t size() const;
+
+ /// @brief Returns the cache size.
+ /// @return The cache size.
+ size_t cacheSize() const;
+
+ /// @brief Will read the next block.
+ /// @return true if successful.
+ bool readNextBlock();
+
+ /// @brief Returns the number of blocks to read.
+ /// @return The number of blocks.
+ size_t getNumBlocks() const;
+
+ /// @brief Returns the current block index.
+ /// @return The current block index.
+ size_t getCurrentBlockIndex() const;
+
+ /// @brief Returns the current file pos.
+ /// @return The current file pos.
+ size_t getFilePos() const;
+
+ /// @brief Will read the next line.
+ /// @param buffer The buffer for the next line.
+ /// @return true if successful.
+ bool getNextDataLine( std::vector<T> &buffer, T continuationToken );
+
+ /// @brief Will read the next line ascii or binary end line char.
+ /// @param buffer The buffer for the next line.
+ /// @return true if successful.
+ bool getNextLine(std::vector<T> &buffer);
+
+ /// @brief Will read the next block.
+ /// @param buffer The buffer for the next block.
+ /// @return true if successful.
+ bool getNextBlock( std::vector<T> &buffer );
+
+private:
+ IOStream *m_stream;
+ size_t m_filesize;
+ size_t m_cacheSize;
+ size_t m_numBlocks;
+ size_t m_blockIdx;
+ std::vector<T> m_cache;
+ size_t m_cachePos;
+ size_t m_filePos;
+};
+
+template<class T>
+inline
+IOStreamBuffer<T>::IOStreamBuffer( size_t cache )
+: m_stream( nullptr )
+, m_filesize( 0 )
+, m_cacheSize( cache )
+, m_numBlocks( 0 )
+, m_blockIdx( 0 )
+, m_cachePos( 0 )
+, m_filePos( 0 ) {
+ m_cache.resize( cache );
+ std::fill( m_cache.begin(), m_cache.end(), '\n' );
+}
+
+template<class T>
+inline
+IOStreamBuffer<T>::~IOStreamBuffer() {
+ // empty
+}
+
+template<class T>
+inline
+bool IOStreamBuffer<T>::open( IOStream *stream ) {
+ // file still opened!
+ if ( nullptr != m_stream ) {
+ return false;
+ }
+
+ // Invalid stream pointer
+ if ( nullptr == stream ) {
+ return false;
+ }
+
+ m_stream = stream;
+ m_filesize = m_stream->FileSize();
+ if ( m_filesize == 0 ) {
+ return false;
+ }
+ if ( m_filesize < m_cacheSize ) {
+ m_cacheSize = m_filesize;
+ }
+
+ m_numBlocks = m_filesize / m_cacheSize;
+ if ( ( m_filesize % m_cacheSize ) > 0 ) {
+ m_numBlocks++;
+ }
+
+ return true;
+}
+
+template<class T>
+inline
+bool IOStreamBuffer<T>::close() {
+ if ( nullptr == m_stream ) {
+ return false;
+ }
+
+ // init counters and state vars
+ m_stream = nullptr;
+ m_filesize = 0;
+ m_numBlocks = 0;
+ m_blockIdx = 0;
+ m_cachePos = 0;
+ m_filePos = 0;
+
+ return true;
+}
+
+template<class T>
+inline
+size_t IOStreamBuffer<T>::size() const {
+ return m_filesize;
+}
+
+template<class T>
+inline
+size_t IOStreamBuffer<T>::cacheSize() const {
+ return m_cacheSize;
+}
+
+template<class T>
+inline
+bool IOStreamBuffer<T>::readNextBlock() {
+ m_stream->Seek( m_filePos, aiOrigin_SET );
+ size_t readLen = m_stream->Read( &m_cache[ 0 ], sizeof( T ), m_cacheSize );
+ if ( readLen == 0 ) {
+ return false;
+ }
+ if ( readLen < m_cacheSize ) {
+ m_cacheSize = readLen;
+ }
+ m_filePos += m_cacheSize;
+ m_cachePos = 0;
+ m_blockIdx++;
+
+ return true;
+}
+
+template<class T>
+inline
+size_t IOStreamBuffer<T>::getNumBlocks() const {
+ return m_numBlocks;
+}
+
+template<class T>
+inline
+size_t IOStreamBuffer<T>::getCurrentBlockIndex() const {
+ return m_blockIdx;
+}
+
+template<class T>
+inline
+size_t IOStreamBuffer<T>::getFilePos() const {
+ return m_filePos;
+}
+
+template<class T>
+inline
+bool IOStreamBuffer<T>::getNextDataLine( std::vector<T> &buffer, T continuationToken ) {
+ buffer.resize( m_cacheSize );
+ if ( m_cachePos >= m_cacheSize || 0 == m_filePos ) {
+ if ( !readNextBlock() ) {
+ return false;
+ }
+ }
+
+ bool continuationFound( false );
+ size_t i = 0;
+ for( ;; ) {
+ if ( continuationToken == m_cache[ m_cachePos ] ) {
+ continuationFound = true;
+ ++m_cachePos;
+ }
+ if ( IsLineEnd( m_cache[ m_cachePos ] ) ) {
+ if ( !continuationFound ) {
+ // the end of the data line
+ break;
+ } else {
+ // skip line end
+ while ( m_cache[m_cachePos] != '\n') {
+ ++m_cachePos;
+ }
+ ++m_cachePos;
+ continuationFound = false;
+ }
+ }
+
+ buffer[ i ] = m_cache[ m_cachePos ];
+ ++m_cachePos;
+ ++i;
+ if (m_cachePos >= size()) {
+ break;
+ }
+ if ( m_cachePos >= m_cacheSize ) {
+ if ( !readNextBlock() ) {
+ return false;
+ }
+ }
+ }
+
+ buffer[ i ] = '\n';
+ ++m_cachePos;
+
+ return true;
+}
+
+static inline
+bool isEndOfCache( size_t pos, size_t cacheSize ) {
+ return ( pos == cacheSize );
+}
+
+template<class T>
+inline
+bool IOStreamBuffer<T>::getNextLine(std::vector<T> &buffer) {
+ buffer.resize(m_cacheSize);
+ if ( isEndOfCache( m_cachePos, m_cacheSize ) || 0 == m_filePos) {
+ if (!readNextBlock()) {
+ return false;
+ }
+ }
+
+ if (IsLineEnd(m_cache[m_cachePos])) {
+ // skip line end
+ while (m_cache[m_cachePos] != '\n') {
+ ++m_cachePos;
+ }
+ ++m_cachePos;
+ if ( isEndOfCache( m_cachePos, m_cacheSize ) ) {
+ if ( !readNextBlock() ) {
+ return false;
+ }
+ }
+ }
+
+ size_t i( 0 );
+ while (!IsLineEnd(m_cache[ m_cachePos ])) {
+ buffer[i] = m_cache[ m_cachePos ];
+ ++m_cachePos;
+ ++i;
+ if (m_cachePos >= m_cacheSize) {
+ if (!readNextBlock()) {
+ return false;
+ }
+ }
+ }
+ buffer[i] = '\n';
+ ++m_cachePos;
+
+ return true;
+}
+
+template<class T>
+inline
+bool IOStreamBuffer<T>::getNextBlock( std::vector<T> &buffer) {
+ // Return the last block-value if getNextLine was used before
+ if ( 0 != m_cachePos ) {
+ buffer = std::vector<T>( m_cache.begin() + m_cachePos, m_cache.end() );
+ m_cachePos = 0;
+ } else {
+ if ( !readNextBlock() ) {
+ return false;
+ }
+
+ buffer = std::vector<T>(m_cache.begin(), m_cache.end());
+ }
+
+ return true;
+}
+
+} // !ns Assimp
diff --git a/thirdparty/assimp/include/assimp/IOSystem.hpp b/thirdparty/assimp/include/assimp/IOSystem.hpp
new file mode 100644
index 0000000000..78139c2839
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/IOSystem.hpp
@@ -0,0 +1,357 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file IOSystem.hpp
+ * @brief File system wrapper for C++. Inherit this class to supply
+ * custom file handling logic to the Import library.
+*/
+
+#pragma once
+#ifndef AI_IOSYSTEM_H_INC
+#define AI_IOSYSTEM_H_INC
+
+#ifndef __cplusplus
+# error This header requires C++ to be used. aiFileIO.h is the \
+ corresponding C interface.
+#endif
+
+#include "types.h"
+
+#ifdef _WIN32
+# include <direct.h>
+# include <stdlib.h>
+# include <stdio.h>
+#else
+# include <sys/stat.h>
+# include <sys/types.h>
+# include <unistd.h>
+#endif // _WIN32
+
+#include <vector>
+
+namespace Assimp {
+
+ class IOStream;
+
+// ---------------------------------------------------------------------------
+/** @brief CPP-API: Interface to the file system.
+ *
+ * Derive an own implementation from this interface to supply custom file handling
+ * to the importer library. If you implement this interface, you also want to
+ * supply a custom implementation for IOStream.
+ *
+ * @see Importer::SetIOHandler()
+ */
+class ASSIMP_API IOSystem
+#ifndef SWIG
+ : public Intern::AllocateFromAssimpHeap
+#endif
+{
+public:
+
+ // -------------------------------------------------------------------
+ /** @brief Default constructor.
+ *
+ * Create an instance of your derived class and assign it to an
+ * #Assimp::Importer instance by calling Importer::SetIOHandler().
+ */
+ IOSystem() AI_NO_EXCEPT;
+
+ // -------------------------------------------------------------------
+ /** @brief Virtual destructor.
+ *
+ * It is safe to be called from within DLL Assimp, we're constructed
+ * on Assimp's heap.
+ */
+ virtual ~IOSystem();
+
+ // -------------------------------------------------------------------
+ /** @brief For backward compatibility
+ * @see Exists(const char*)
+ */
+ AI_FORCE_INLINE bool Exists( const std::string& pFile) const;
+
+ // -------------------------------------------------------------------
+ /** @brief Tests for the existence of a file at the given path.
+ *
+ * @param pFile Path to the file
+ * @return true if there is a file with this path, else false.
+ */
+ virtual bool Exists( const char* pFile) const = 0;
+
+ // -------------------------------------------------------------------
+ /** @brief Returns the system specific directory separator
+ * @return System specific directory separator
+ */
+ virtual char getOsSeparator() const = 0;
+
+ // -------------------------------------------------------------------
+ /** @brief Open a new file with a given path.
+ *
+ * When the access to the file is finished, call Close() to release
+ * all associated resources (or the virtual dtor of the IOStream).
+ *
+ * @param pFile Path to the file
+ * @param pMode Desired file I/O mode. Required are: "wb", "w", "wt",
+ * "rb", "r", "rt".
+ *
+ * @return New IOStream interface allowing the lib to access
+ * the underlying file.
+ * @note When implementing this class to provide custom IO handling,
+ * you probably have to supply an own implementation of IOStream as well.
+ */
+ virtual IOStream* Open(const char* pFile,
+ const char* pMode = "rb") = 0;
+
+ // -------------------------------------------------------------------
+ /** @brief For backward compatibility
+ * @see Open(const char*, const char*)
+ */
+ inline IOStream* Open(const std::string& pFile,
+ const std::string& pMode = std::string("rb"));
+
+ // -------------------------------------------------------------------
+ /** @brief Closes the given file and releases all resources
+ * associated with it.
+ * @param pFile The file instance previously created by Open().
+ */
+ virtual void Close( IOStream* pFile) = 0;
+
+ // -------------------------------------------------------------------
+ /** @brief Compares two paths and check whether the point to
+ * identical files.
+ *
+ * The dummy implementation of this virtual member performs a
+ * case-insensitive comparison of the given strings. The default IO
+ * system implementation uses OS mechanisms to convert relative into
+ * absolute paths, so the result can be trusted.
+ * @param one First file
+ * @param second Second file
+ * @return true if the paths point to the same file. The file needn't
+ * be existing, however.
+ */
+ virtual bool ComparePaths (const char* one,
+ const char* second) const;
+
+ // -------------------------------------------------------------------
+ /** @brief For backward compatibility
+ * @see ComparePaths(const char*, const char*)
+ */
+ inline bool ComparePaths (const std::string& one,
+ const std::string& second) const;
+
+ // -------------------------------------------------------------------
+ /** @brief Pushes a new directory onto the directory stack.
+ * @param path Path to push onto the stack.
+ * @return True, when push was successful, false if path is empty.
+ */
+ virtual bool PushDirectory( const std::string &path );
+
+ // -------------------------------------------------------------------
+ /** @brief Returns the top directory from the stack.
+ * @return The directory on the top of the stack.
+ * Returns empty when no directory was pushed to the stack.
+ */
+ virtual const std::string &CurrentDirectory() const;
+
+ // -------------------------------------------------------------------
+ /** @brief Returns the number of directories stored on the stack.
+ * @return The number of directories of the stack.
+ */
+ virtual size_t StackSize() const;
+
+ // -------------------------------------------------------------------
+ /** @brief Pops the top directory from the stack.
+ * @return True, when a directory was on the stack. False if no
+ * directory was on the stack.
+ */
+ virtual bool PopDirectory();
+
+ // -------------------------------------------------------------------
+ /** @brief CReates an new directory at the given path.
+ * @param path [in] The path to create.
+ * @return True, when a directory was created. False if the directory
+ * cannot be created.
+ */
+ virtual bool CreateDirectory( const std::string &path );
+
+ // -------------------------------------------------------------------
+ /** @brief Will change the current directory to the given path.
+ * @param path [in] The path to change to.
+ * @return True, when the directory has changed successfully.
+ */
+ virtual bool ChangeDirectory( const std::string &path );
+
+ virtual bool DeleteFile( const std::string &file );
+
+private:
+ std::vector<std::string> m_pathStack;
+};
+
+// ----------------------------------------------------------------------------
+AI_FORCE_INLINE
+IOSystem::IOSystem() AI_NO_EXCEPT
+: m_pathStack() {
+ // empty
+}
+
+// ----------------------------------------------------------------------------
+AI_FORCE_INLINE
+IOSystem::~IOSystem() {
+ // empty
+}
+
+// ----------------------------------------------------------------------------
+// For compatibility, the interface of some functions taking a std::string was
+// changed to const char* to avoid crashes between binary incompatible STL
+// versions. This code her is inlined, so it shouldn't cause any problems.
+// ----------------------------------------------------------------------------
+
+// ----------------------------------------------------------------------------
+AI_FORCE_INLINE
+IOStream* IOSystem::Open(const std::string& pFile, const std::string& pMode) {
+ // NOTE:
+ // For compatibility, interface was changed to const char* to
+ // avoid crashes between binary incompatible STL versions
+ return Open(pFile.c_str(),pMode.c_str());
+}
+
+// ----------------------------------------------------------------------------
+AI_FORCE_INLINE
+bool IOSystem::Exists( const std::string& pFile) const {
+ // NOTE:
+ // For compatibility, interface was changed to const char* to
+ // avoid crashes between binary incompatible STL versions
+ return Exists(pFile.c_str());
+}
+
+// ----------------------------------------------------------------------------
+AI_FORCE_INLINE
+bool IOSystem::ComparePaths (const std::string& one, const std::string& second) const {
+ // NOTE:
+ // For compatibility, interface was changed to const char* to
+ // avoid crashes between binary incompatible STL versions
+ return ComparePaths(one.c_str(),second.c_str());
+}
+
+// ----------------------------------------------------------------------------
+AI_FORCE_INLINE
+bool IOSystem::PushDirectory( const std::string &path ) {
+ if ( path.empty() ) {
+ return false;
+ }
+
+ m_pathStack.push_back( path );
+
+ return true;
+}
+
+// ----------------------------------------------------------------------------
+AI_FORCE_INLINE
+const std::string &IOSystem::CurrentDirectory() const {
+ if ( m_pathStack.empty() ) {
+ static const std::string Dummy("");
+ return Dummy;
+ }
+ return m_pathStack[ m_pathStack.size()-1 ];
+}
+
+// ----------------------------------------------------------------------------
+AI_FORCE_INLINE
+size_t IOSystem::StackSize() const {
+ return m_pathStack.size();
+}
+
+// ----------------------------------------------------------------------------
+AI_FORCE_INLINE
+bool IOSystem::PopDirectory() {
+ if ( m_pathStack.empty() ) {
+ return false;
+ }
+
+ m_pathStack.pop_back();
+
+ return true;
+}
+
+// ----------------------------------------------------------------------------
+AI_FORCE_INLINE
+bool IOSystem::CreateDirectory( const std::string &path ) {
+ if ( path.empty() ) {
+ return false;
+ }
+
+#ifdef _WIN32
+ return 0 != ::_mkdir( path.c_str() );
+#else
+ return 0 != ::mkdir( path.c_str(), 0777 );
+#endif // _WIN32
+}
+
+// ----------------------------------------------------------------------------
+AI_FORCE_INLINE
+bool IOSystem::ChangeDirectory( const std::string &path ) {
+ if ( path.empty() ) {
+ return false;
+ }
+
+#ifdef _WIN32
+ return 0 != ::_chdir( path.c_str() );
+#else
+ return 0 != ::chdir( path.c_str() );
+#endif // _WIN32
+}
+
+
+// ----------------------------------------------------------------------------
+AI_FORCE_INLINE
+bool IOSystem::DeleteFile( const std::string &file ) {
+ if ( file.empty() ) {
+ return false;
+ }
+ const int retCode( ::remove( file.c_str() ) );
+ return ( 0 == retCode );
+}
+} //!ns Assimp
+
+#endif //AI_IOSYSTEM_H_INC
diff --git a/thirdparty/assimp/include/assimp/Importer.hpp b/thirdparty/assimp/include/assimp/Importer.hpp
new file mode 100644
index 0000000000..4941df4122
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/Importer.hpp
@@ -0,0 +1,659 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file Importer.hpp
+ * @brief Defines the C++-API to the Open Asset Import Library.
+ */
+#pragma once
+#ifndef AI_ASSIMP_HPP_INC
+#define AI_ASSIMP_HPP_INC
+
+#ifndef __cplusplus
+# error This header requires C++ to be used. Use assimp.h for plain C.
+#endif // __cplusplus
+
+// Public ASSIMP data structures
+#include <assimp/types.h>
+
+namespace Assimp {
+ // =======================================================================
+ // Public interface to Assimp
+ class Importer;
+ class IOStream;
+ class IOSystem;
+ class ProgressHandler;
+
+ // =======================================================================
+ // Plugin development
+ //
+ // Include the following headers for the declarations:
+ // BaseImporter.h
+ // BaseProcess.h
+ class BaseImporter;
+ class BaseProcess;
+ class SharedPostProcessInfo;
+ class BatchLoader;
+
+ // =======================================================================
+ // Holy stuff, only for members of the high council of the Jedi.
+ class ImporterPimpl;
+} //! namespace Assimp
+
+#define AI_PROPERTY_WAS_NOT_EXISTING 0xffffffff
+
+struct aiScene;
+
+// importerdesc.h
+struct aiImporterDesc;
+
+/** @namespace Assimp Assimp's CPP-API and all internal APIs */
+namespace Assimp {
+
+// ----------------------------------------------------------------------------------
+/** CPP-API: The Importer class forms an C++ interface to the functionality of the
+* Open Asset Import Library.
+*
+* Create an object of this class and call ReadFile() to import a file.
+* If the import succeeds, the function returns a pointer to the imported data.
+* The data remains property of the object, it is intended to be accessed
+* read-only. The imported data will be destroyed along with the Importer
+* object. If the import fails, ReadFile() returns a NULL pointer. In this
+* case you can retrieve a human-readable error description be calling
+* GetErrorString(). You can call ReadFile() multiple times with a single Importer
+* instance. Actually, constructing Importer objects involves quite many
+* allocations and may take some time, so it's better to reuse them as often as
+* possible.
+*
+* If you need the Importer to do custom file handling to access the files,
+* implement IOSystem and IOStream and supply an instance of your custom
+* IOSystem implementation by calling SetIOHandler() before calling ReadFile().
+* If you do not assign a custion IO handler, a default handler using the
+* standard C++ IO logic will be used.
+*
+* @note One Importer instance is not thread-safe. If you use multiple
+* threads for loading, each thread should maintain its own Importer instance.
+*/
+class ASSIMP_API Importer {
+public:
+ /**
+ * @brief The upper limit for hints.
+ */
+ static const unsigned int MaxLenHint = 200;
+
+public:
+
+ // -------------------------------------------------------------------
+ /** Constructor. Creates an empty importer object.
+ *
+ * Call ReadFile() to start the import process. The configuration
+ * property table is initially empty.
+ */
+ Importer();
+
+ // -------------------------------------------------------------------
+ /** Copy constructor.
+ *
+ * This copies the configuration properties of another Importer.
+ * If this Importer owns a scene it won't be copied.
+ * Call ReadFile() to start the import process.
+ */
+ Importer(const Importer& other)=delete;
+
+ // -------------------------------------------------------------------
+ /** Assignment operator has been deleted
+ */
+ Importer &operator=(const Importer &) = delete;
+
+ // -------------------------------------------------------------------
+ /** Destructor. The object kept ownership of the imported data,
+ * which now will be destroyed along with the object.
+ */
+ ~Importer();
+
+
+ // -------------------------------------------------------------------
+ /** Registers a new loader.
+ *
+ * @param pImp Importer to be added. The Importer instance takes
+ * ownership of the pointer, so it will be automatically deleted
+ * with the Importer instance.
+ * @return AI_SUCCESS if the loader has been added. The registration
+ * fails if there is already a loader for a specific file extension.
+ */
+ aiReturn RegisterLoader(BaseImporter* pImp);
+
+ // -------------------------------------------------------------------
+ /** Unregisters a loader.
+ *
+ * @param pImp Importer to be unregistered.
+ * @return AI_SUCCESS if the loader has been removed. The function
+ * fails if the loader is currently in use (this could happen
+ * if the #Importer instance is used by more than one thread) or
+ * if it has not yet been registered.
+ */
+ aiReturn UnregisterLoader(BaseImporter* pImp);
+
+ // -------------------------------------------------------------------
+ /** Registers a new post-process step.
+ *
+ * At the moment, there's a small limitation: new post processing
+ * steps are added to end of the list, or in other words, executed
+ * last, after all built-in steps.
+ * @param pImp Post-process step to be added. The Importer instance
+ * takes ownership of the pointer, so it will be automatically
+ * deleted with the Importer instance.
+ * @return AI_SUCCESS if the step has been added correctly.
+ */
+ aiReturn RegisterPPStep(BaseProcess* pImp);
+
+ // -------------------------------------------------------------------
+ /** Unregisters a post-process step.
+ *
+ * @param pImp Step to be unregistered.
+ * @return AI_SUCCESS if the step has been removed. The function
+ * fails if the step is currently in use (this could happen
+ * if the #Importer instance is used by more than one thread) or
+ * if it has not yet been registered.
+ */
+ aiReturn UnregisterPPStep(BaseProcess* pImp);
+
+ // -------------------------------------------------------------------
+ /** Set an integer configuration property.
+ * @param szName Name of the property. All supported properties
+ * are defined in the aiConfig.g header (all constants share the
+ * prefix AI_CONFIG_XXX and are simple strings).
+ * @param iValue New value of the property
+ * @return true if the property was set before. The new value replaces
+ * the previous value in this case.
+ * @note Property of different types (float, int, string ..) are kept
+ * on different stacks, so calling SetPropertyInteger() for a
+ * floating-point property has no effect - the loader will call
+ * GetPropertyFloat() to read the property, but it won't be there.
+ */
+ bool SetPropertyInteger(const char* szName, int iValue);
+
+ // -------------------------------------------------------------------
+ /** Set a boolean configuration property. Boolean properties
+ * are stored on the integer stack internally so it's possible
+ * to set them via #SetPropertyBool and query them with
+ * #GetPropertyBool and vice versa.
+ * @see SetPropertyInteger()
+ */
+ bool SetPropertyBool(const char* szName, bool value) {
+ return SetPropertyInteger(szName,value);
+ }
+
+ // -------------------------------------------------------------------
+ /** Set a floating-point configuration property.
+ * @see SetPropertyInteger()
+ */
+ bool SetPropertyFloat(const char* szName, ai_real fValue);
+
+ // -------------------------------------------------------------------
+ /** Set a string configuration property.
+ * @see SetPropertyInteger()
+ */
+ bool SetPropertyString(const char* szName, const std::string& sValue);
+
+ // -------------------------------------------------------------------
+ /** Set a matrix configuration property.
+ * @see SetPropertyInteger()
+ */
+ bool SetPropertyMatrix(const char* szName, const aiMatrix4x4& sValue);
+
+ // -------------------------------------------------------------------
+ /** Get a configuration property.
+ * @param szName Name of the property. All supported properties
+ * are defined in the aiConfig.g header (all constants share the
+ * prefix AI_CONFIG_XXX).
+ * @param iErrorReturn Value that is returned if the property
+ * is not found.
+ * @return Current value of the property
+ * @note Property of different types (float, int, string ..) are kept
+ * on different lists, so calling SetPropertyInteger() for a
+ * floating-point property has no effect - the loader will call
+ * GetPropertyFloat() to read the property, but it won't be there.
+ */
+ int GetPropertyInteger(const char* szName,
+ int iErrorReturn = 0xffffffff) const;
+
+ // -------------------------------------------------------------------
+ /** Get a boolean configuration property. Boolean properties
+ * are stored on the integer stack internally so it's possible
+ * to set them via #SetPropertyBool and query them with
+ * #GetPropertyBool and vice versa.
+ * @see GetPropertyInteger()
+ */
+ bool GetPropertyBool(const char* szName, bool bErrorReturn = false) const {
+ return GetPropertyInteger(szName,bErrorReturn)!=0;
+ }
+
+ // -------------------------------------------------------------------
+ /** Get a floating-point configuration property
+ * @see GetPropertyInteger()
+ */
+ ai_real GetPropertyFloat(const char* szName,
+ ai_real fErrorReturn = 10e10) const;
+
+ // -------------------------------------------------------------------
+ /** Get a string configuration property
+ *
+ * The return value remains valid until the property is modified.
+ * @see GetPropertyInteger()
+ */
+ const std::string GetPropertyString(const char* szName,
+ const std::string& sErrorReturn = "") const;
+
+ // -------------------------------------------------------------------
+ /** Get a matrix configuration property
+ *
+ * The return value remains valid until the property is modified.
+ * @see GetPropertyInteger()
+ */
+ const aiMatrix4x4 GetPropertyMatrix(const char* szName,
+ const aiMatrix4x4& sErrorReturn = aiMatrix4x4()) const;
+
+ // -------------------------------------------------------------------
+ /** Supplies a custom IO handler to the importer to use to open and
+ * access files. If you need the importer to use custom IO logic to
+ * access the files, you need to provide a custom implementation of
+ * IOSystem and IOFile to the importer. Then create an instance of
+ * your custom IOSystem implementation and supply it by this function.
+ *
+ * The Importer takes ownership of the object and will destroy it
+ * afterwards. The previously assigned handler will be deleted.
+ * Pass NULL to take again ownership of your IOSystem and reset Assimp
+ * to use its default implementation.
+ *
+ * @param pIOHandler The IO handler to be used in all file accesses
+ * of the Importer.
+ */
+ void SetIOHandler( IOSystem* pIOHandler);
+
+ // -------------------------------------------------------------------
+ /** Retrieves the IO handler that is currently set.
+ * You can use #IsDefaultIOHandler() to check whether the returned
+ * interface is the default IO handler provided by ASSIMP. The default
+ * handler is active as long the application doesn't supply its own
+ * custom IO handler via #SetIOHandler().
+ * @return A valid IOSystem interface, never NULL.
+ */
+ IOSystem* GetIOHandler() const;
+
+ // -------------------------------------------------------------------
+ /** Checks whether a default IO handler is active
+ * A default handler is active as long the application doesn't
+ * supply its own custom IO handler via #SetIOHandler().
+ * @return true by default
+ */
+ bool IsDefaultIOHandler() const;
+
+ // -------------------------------------------------------------------
+ /** Supplies a custom progress handler to the importer. This
+ * interface exposes an #Update() callback, which is called
+ * more or less periodically (please don't sue us if it
+ * isn't as periodically as you'd like it to have ...).
+ * This can be used to implement progress bars and loading
+ * timeouts.
+ * @param pHandler Progress callback interface. Pass NULL to
+ * disable progress reporting.
+ * @note Progress handlers can be used to abort the loading
+ * at almost any time.*/
+ void SetProgressHandler ( ProgressHandler* pHandler );
+
+ // -------------------------------------------------------------------
+ /** Retrieves the progress handler that is currently set.
+ * You can use #IsDefaultProgressHandler() to check whether the returned
+ * interface is the default handler provided by ASSIMP. The default
+ * handler is active as long the application doesn't supply its own
+ * custom handler via #SetProgressHandler().
+ * @return A valid ProgressHandler interface, never NULL.
+ */
+ ProgressHandler* GetProgressHandler() const;
+
+ // -------------------------------------------------------------------
+ /** Checks whether a default progress handler is active
+ * A default handler is active as long the application doesn't
+ * supply its own custom progress handler via #SetProgressHandler().
+ * @return true by default
+ */
+ bool IsDefaultProgressHandler() const;
+
+ // -------------------------------------------------------------------
+ /** @brief Check whether a given set of post-processing flags
+ * is supported.
+ *
+ * Some flags are mutually exclusive, others are probably
+ * not available because your excluded them from your
+ * Assimp builds. Calling this function is recommended if
+ * you're unsure.
+ *
+ * @param pFlags Bitwise combination of the aiPostProcess flags.
+ * @return true if this flag combination is fine.
+ */
+ bool ValidateFlags(unsigned int pFlags) const;
+
+ // -------------------------------------------------------------------
+ /** Reads the given file and returns its contents if successful.
+ *
+ * If the call succeeds, the contents of the file are returned as a
+ * pointer to an aiScene object. The returned data is intended to be
+ * read-only, the importer object keeps ownership of the data and will
+ * destroy it upon destruction. If the import fails, NULL is returned.
+ * A human-readable error description can be retrieved by calling
+ * GetErrorString(). The previous scene will be deleted during this call.
+ * @param pFile Path and filename to the file to be imported.
+ * @param pFlags Optional post processing steps to be executed after
+ * a successful import. Provide a bitwise combination of the
+ * #aiPostProcessSteps flags. If you wish to inspect the imported
+ * scene first in order to fine-tune your post-processing setup,
+ * consider to use #ApplyPostProcessing().
+ * @return A pointer to the imported data, NULL if the import failed.
+ * The pointer to the scene remains in possession of the Importer
+ * instance. Use GetOrphanedScene() to take ownership of it.
+ *
+ * @note Assimp is able to determine the file format of a file
+ * automatically.
+ */
+ const aiScene* ReadFile(
+ const char* pFile,
+ unsigned int pFlags);
+
+ // -------------------------------------------------------------------
+ /** Reads the given file from a memory buffer and returns its
+ * contents if successful.
+ *
+ * If the call succeeds, the contents of the file are returned as a
+ * pointer to an aiScene object. The returned data is intended to be
+ * read-only, the importer object keeps ownership of the data and will
+ * destroy it upon destruction. If the import fails, NULL is returned.
+ * A human-readable error description can be retrieved by calling
+ * GetErrorString(). The previous scene will be deleted during this call.
+ * Calling this method doesn't affect the active IOSystem.
+ * @param pBuffer Pointer to the file data
+ * @param pLength Length of pBuffer, in bytes
+ * @param pFlags Optional post processing steps to be executed after
+ * a successful import. Provide a bitwise combination of the
+ * #aiPostProcessSteps flags. If you wish to inspect the imported
+ * scene first in order to fine-tune your post-processing setup,
+ * consider to use #ApplyPostProcessing().
+ * @param pHint An additional hint to the library. If this is a non
+ * empty string, the library looks for a loader to support
+ * the file extension specified by pHint and passes the file to
+ * the first matching loader. If this loader is unable to completely
+ * the request, the library continues and tries to determine the
+ * file format on its own, a task that may or may not be successful.
+ * Check the return value, and you'll know ...
+ * @return A pointer to the imported data, NULL if the import failed.
+ * The pointer to the scene remains in possession of the Importer
+ * instance. Use GetOrphanedScene() to take ownership of it.
+ *
+ * @note This is a straightforward way to decode models from memory
+ * buffers, but it doesn't handle model formats that spread their
+ * data across multiple files or even directories. Examples include
+ * OBJ or MD3, which outsource parts of their material info into
+ * external scripts. If you need full functionality, provide
+ * a custom IOSystem to make Assimp find these files and use
+ * the regular ReadFile() API.
+ */
+ const aiScene* ReadFileFromMemory(
+ const void* pBuffer,
+ size_t pLength,
+ unsigned int pFlags,
+ const char* pHint = "");
+
+ // -------------------------------------------------------------------
+ /** Apply post-processing to an already-imported scene.
+ *
+ * This is strictly equivalent to calling #ReadFile() with the same
+ * flags. However, you can use this separate function to inspect
+ * the imported scene first to fine-tune your post-processing setup.
+ * @param pFlags Provide a bitwise combination of the
+ * #aiPostProcessSteps flags.
+ * @return A pointer to the post-processed data. This is still the
+ * same as the pointer returned by #ReadFile(). However, if
+ * post-processing fails, the scene could now be NULL.
+ * That's quite a rare case, post processing steps are not really
+ * designed to 'fail'. To be exact, the #aiProcess_ValidateDS
+ * flag is currently the only post processing step which can actually
+ * cause the scene to be reset to NULL.
+ *
+ * @note The method does nothing if no scene is currently bound
+ * to the #Importer instance. */
+ const aiScene* ApplyPostProcessing(unsigned int pFlags);
+
+ const aiScene* ApplyCustomizedPostProcessing( BaseProcess *rootProcess, bool requestValidation );
+
+ // -------------------------------------------------------------------
+ /** @brief Reads the given file and returns its contents if successful.
+ *
+ * This function is provided for backward compatibility.
+ * See the const char* version for detailed docs.
+ * @see ReadFile(const char*, pFlags) */
+ const aiScene* ReadFile(
+ const std::string& pFile,
+ unsigned int pFlags);
+
+ // -------------------------------------------------------------------
+ /** Frees the current scene.
+ *
+ * The function does nothing if no scene has previously been
+ * read via ReadFile(). FreeScene() is called automatically by the
+ * destructor and ReadFile() itself. */
+ void FreeScene( );
+
+ // -------------------------------------------------------------------
+ /** Returns an error description of an error that occurred in ReadFile().
+ *
+ * Returns an empty string if no error occurred.
+ * @return A description of the last error, an empty string if no
+ * error occurred. The string is never NULL.
+ *
+ * @note The returned function remains valid until one of the
+ * following methods is called: #ReadFile(), #FreeScene(). */
+ const char* GetErrorString() const;
+
+ // -------------------------------------------------------------------
+ /** Returns the scene loaded by the last successful call to ReadFile()
+ *
+ * @return Current scene or NULL if there is currently no scene loaded */
+ const aiScene* GetScene() const;
+
+ // -------------------------------------------------------------------
+ /** Returns the scene loaded by the last successful call to ReadFile()
+ * and releases the scene from the ownership of the Importer
+ * instance. The application is now responsible for deleting the
+ * scene. Any further calls to GetScene() or GetOrphanedScene()
+ * will return NULL - until a new scene has been loaded via ReadFile().
+ *
+ * @return Current scene or NULL if there is currently no scene loaded
+ * @note Use this method with maximal caution, and only if you have to.
+ * By design, aiScene's are exclusively maintained, allocated and
+ * deallocated by Assimp and no one else. The reasoning behind this
+ * is the golden rule that deallocations should always be done
+ * by the module that did the original allocation because heaps
+ * are not necessarily shared. GetOrphanedScene() enforces you
+ * to delete the returned scene by yourself, but this will only
+ * be fine if and only if you're using the same heap as assimp.
+ * On Windows, it's typically fine provided everything is linked
+ * against the multithreaded-dll version of the runtime library.
+ * It will work as well for static linkage with Assimp.*/
+ aiScene* GetOrphanedScene();
+
+ // -------------------------------------------------------------------
+ /** Returns whether a given file extension is supported by ASSIMP.
+ *
+ * @param szExtension Extension to be checked.
+ * Must include a trailing dot '.'. Example: ".3ds", ".md3".
+ * Cases-insensitive.
+ * @return true if the extension is supported, false otherwise */
+ bool IsExtensionSupported(const char* szExtension) const;
+
+ // -------------------------------------------------------------------
+ /** @brief Returns whether a given file extension is supported by ASSIMP.
+ *
+ * This function is provided for backward compatibility.
+ * See the const char* version for detailed and up-to-date docs.
+ * @see IsExtensionSupported(const char*) */
+ inline bool IsExtensionSupported(const std::string& szExtension) const;
+
+ // -------------------------------------------------------------------
+ /** Get a full list of all file extensions supported by ASSIMP.
+ *
+ * If a file extension is contained in the list this does of course not
+ * mean that ASSIMP is able to load all files with this extension ---
+ * it simply means there is an importer loaded which claims to handle
+ * files with this file extension.
+ * @param szOut String to receive the extension list.
+ * Format of the list: "*.3ds;*.obj;*.dae". This is useful for
+ * use with the WinAPI call GetOpenFileName(Ex). */
+ void GetExtensionList(aiString& szOut) const;
+
+ // -------------------------------------------------------------------
+ /** @brief Get a full list of all file extensions supported by ASSIMP.
+ *
+ * This function is provided for backward compatibility.
+ * See the aiString version for detailed and up-to-date docs.
+ * @see GetExtensionList(aiString&)*/
+ inline void GetExtensionList(std::string& szOut) const;
+
+ // -------------------------------------------------------------------
+ /** Get the number of importers currently registered with Assimp. */
+ size_t GetImporterCount() const;
+
+ // -------------------------------------------------------------------
+ /** Get meta data for the importer corresponding to a specific index..
+ *
+ * For the declaration of #aiImporterDesc, include <assimp/importerdesc.h>.
+ * @param index Index to query, must be within [0,GetImporterCount())
+ * @return Importer meta data structure, NULL if the index does not
+ * exist or if the importer doesn't offer meta information (
+ * importers may do this at the cost of being hated by their peers).*/
+ const aiImporterDesc* GetImporterInfo(size_t index) const;
+
+ // -------------------------------------------------------------------
+ /** Find the importer corresponding to a specific index.
+ *
+ * @param index Index to query, must be within [0,GetImporterCount())
+ * @return Importer instance. NULL if the index does not
+ * exist. */
+ BaseImporter* GetImporter(size_t index) const;
+
+ // -------------------------------------------------------------------
+ /** Find the importer corresponding to a specific file extension.
+ *
+ * This is quite similar to #IsExtensionSupported except a
+ * BaseImporter instance is returned.
+ * @param szExtension Extension to check for. The following formats
+ * are recognized (BAH being the file extension): "BAH" (comparison
+ * is case-insensitive), ".bah", "*.bah" (wild card and dot
+ * characters at the beginning of the extension are skipped).
+ * @return NULL if no importer is found*/
+ BaseImporter* GetImporter (const char* szExtension) const;
+
+ // -------------------------------------------------------------------
+ /** Find the importer index corresponding to a specific file extension.
+ *
+ * @param szExtension Extension to check for. The following formats
+ * are recognized (BAH being the file extension): "BAH" (comparison
+ * is case-insensitive), ".bah", "*.bah" (wild card and dot
+ * characters at the beginning of the extension are skipped).
+ * @return (size_t)-1 if no importer is found */
+ size_t GetImporterIndex (const char* szExtension) const;
+
+ // -------------------------------------------------------------------
+ /** Returns the storage allocated by ASSIMP to hold the scene data
+ * in memory.
+ *
+ * This refers to the currently loaded file, see #ReadFile().
+ * @param in Data structure to be filled.
+ * @note The returned memory statistics refer to the actual
+ * size of the use data of the aiScene. Heap-related overhead
+ * is (naturally) not included.*/
+ void GetMemoryRequirements(aiMemoryInfo& in) const;
+
+ // -------------------------------------------------------------------
+ /** Enables "extra verbose" mode.
+ *
+ * 'Extra verbose' means the data structure is validated after *every*
+ * single post processing step to make sure everyone modifies the data
+ * structure in a well-defined manner. This is a debug feature and not
+ * intended for use in production environments. */
+ void SetExtraVerbose(bool bDo);
+
+ // -------------------------------------------------------------------
+ /** Private, do not use. */
+ ImporterPimpl* Pimpl() { return pimpl; }
+ const ImporterPimpl* Pimpl() const { return pimpl; }
+
+protected:
+
+ // Just because we don't want you to know how we're hacking around.
+ ImporterPimpl* pimpl;
+}; //! class Importer
+
+
+// ----------------------------------------------------------------------------
+// For compatibility, the interface of some functions taking a std::string was
+// changed to const char* to avoid crashes between binary incompatible STL
+// versions. This code her is inlined, so it shouldn't cause any problems.
+// ----------------------------------------------------------------------------
+
+// ----------------------------------------------------------------------------
+AI_FORCE_INLINE const aiScene* Importer::ReadFile( const std::string& pFile,unsigned int pFlags){
+ return ReadFile(pFile.c_str(),pFlags);
+}
+// ----------------------------------------------------------------------------
+AI_FORCE_INLINE void Importer::GetExtensionList(std::string& szOut) const {
+ aiString s;
+ GetExtensionList(s);
+ szOut = s.data;
+}
+// ----------------------------------------------------------------------------
+AI_FORCE_INLINE bool Importer::IsExtensionSupported(const std::string& szExtension) const {
+ return IsExtensionSupported(szExtension.c_str());
+}
+
+} // !namespace Assimp
+
+#endif // AI_ASSIMP_HPP_INC
diff --git a/thirdparty/assimp/include/assimp/LineSplitter.h b/thirdparty/assimp/include/assimp/LineSplitter.h
new file mode 100644
index 0000000000..4afe45b92a
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/LineSplitter.h
@@ -0,0 +1,285 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file LineSplitter.h
+ * @brief LineSplitter, a helper class to iterate through all lines
+ * of a file easily. Works with StreamReader.
+ */
+#pragma once
+#ifndef INCLUDED_LINE_SPLITTER_H
+#define INCLUDED_LINE_SPLITTER_H
+
+#include <stdexcept>
+#include "StreamReader.h"
+#include "ParsingUtils.h"
+
+namespace Assimp {
+
+// ------------------------------------------------------------------------------------------------
+/** Usage:
+@code
+for(LineSplitter splitter(stream);splitter;++splitter) {
+
+ if (*splitter == "hi!") {
+ ...
+ }
+ else if (splitter->substr(0,5) == "hello") {
+ ...
+ // access the third token in the line (tokens are space-separated)
+ if (strtol(splitter[2]) > 5) { .. }
+ }
+
+ std::cout << "Current line is: " << splitter.get_index() << std::endl;
+}
+@endcode
+*/
+// ------------------------------------------------------------------------------------------------
+class LineSplitter {
+public:
+ typedef size_t line_idx;
+
+ // -----------------------------------------
+ /** construct from existing stream reader
+ note: trim is *always* assumed true if skyp_empty_lines==true
+ */
+ LineSplitter(StreamReaderLE& stream, bool skip_empty_lines = true, bool trim = true);
+
+ ~LineSplitter();
+
+ // -----------------------------------------
+ /** pseudo-iterator increment */
+ LineSplitter& operator++();
+
+ // -----------------------------------------
+ LineSplitter& operator++(int);
+
+ // -----------------------------------------
+ /** get a pointer to the beginning of a particular token */
+ const char* operator[] (size_t idx) const;
+
+ // -----------------------------------------
+ /** extract the start positions of N tokens from the current line*/
+ template <size_t N>
+ void get_tokens(const char* (&tokens)[N]) const;
+
+ // -----------------------------------------
+ /** member access */
+ const std::string* operator -> () const;
+
+ std::string operator* () const;
+
+ // -----------------------------------------
+ /** boolean context */
+ operator bool() const;
+
+ // -----------------------------------------
+ /** line indices are zero-based, empty lines are included */
+ operator line_idx() const;
+
+ line_idx get_index() const;
+
+ // -----------------------------------------
+ /** access the underlying stream object */
+ StreamReaderLE& get_stream();
+
+ // -----------------------------------------
+ /** !strcmp((*this)->substr(0,strlen(check)),check) */
+ bool match_start(const char* check);
+
+ // -----------------------------------------
+ /** swallow the next call to ++, return the previous value. */
+ void swallow_next_increment();
+
+ LineSplitter( const LineSplitter & ) = delete;
+ LineSplitter(LineSplitter &&) = delete;
+ LineSplitter &operator = ( const LineSplitter & ) = delete;
+
+private:
+ line_idx mIdx;
+ std::string mCur;
+ StreamReaderLE& mStream;
+ bool mSwallow, mSkip_empty_lines, mTrim;
+};
+
+inline
+LineSplitter::LineSplitter(StreamReaderLE& stream, bool skip_empty_lines, bool trim )
+: mIdx(0)
+, mCur()
+, mStream(stream)
+, mSwallow()
+, mSkip_empty_lines(skip_empty_lines)
+, mTrim(trim) {
+ mCur.reserve(1024);
+ operator++();
+ mIdx = 0;
+}
+
+inline
+LineSplitter::~LineSplitter() {
+ // empty
+}
+
+inline
+LineSplitter& LineSplitter::operator++() {
+ if (mSwallow) {
+ mSwallow = false;
+ return *this;
+ }
+
+ if (!*this) {
+ throw std::logic_error("End of file, no more lines to be retrieved.");
+ }
+
+ char s;
+ mCur.clear();
+ while (mStream.GetRemainingSize() && (s = mStream.GetI1(), 1)) {
+ if (s == '\n' || s == '\r') {
+ if (mSkip_empty_lines) {
+ while (mStream.GetRemainingSize() && ((s = mStream.GetI1()) == ' ' || s == '\r' || s == '\n'));
+ if (mStream.GetRemainingSize()) {
+ mStream.IncPtr(-1);
+ }
+ } else {
+ // skip both potential line terminators but don't read past this line.
+ if (mStream.GetRemainingSize() && (s == '\r' && mStream.GetI1() != '\n')) {
+ mStream.IncPtr(-1);
+ }
+ if (mTrim) {
+ while (mStream.GetRemainingSize() && ((s = mStream.GetI1()) == ' ' || s == '\t'));
+ if (mStream.GetRemainingSize()) {
+ mStream.IncPtr(-1);
+ }
+ }
+ }
+ break;
+ }
+ mCur += s;
+ }
+ ++mIdx;
+
+ return *this;
+}
+
+inline
+LineSplitter &LineSplitter::operator++(int) {
+ return ++(*this);
+}
+
+inline
+const char *LineSplitter::operator[] (size_t idx) const {
+ const char* s = operator->()->c_str();
+
+ SkipSpaces(&s);
+ for (size_t i = 0; i < idx; ++i) {
+
+ for (; !IsSpace(*s); ++s) {
+ if (IsLineEnd(*s)) {
+ throw std::range_error("Token index out of range, EOL reached");
+ }
+ }
+ SkipSpaces(&s);
+ }
+ return s;
+}
+
+template <size_t N>
+inline
+void LineSplitter::get_tokens(const char* (&tokens)[N]) const {
+ const char* s = operator->()->c_str();
+
+ SkipSpaces(&s);
+ for (size_t i = 0; i < N; ++i) {
+ if (IsLineEnd(*s)) {
+ throw std::range_error("Token count out of range, EOL reached");
+ }
+ tokens[i] = s;
+
+ for (; *s && !IsSpace(*s); ++s);
+ SkipSpaces(&s);
+ }
+}
+
+inline
+const std::string* LineSplitter::operator -> () const {
+ return &mCur;
+}
+
+inline
+std::string LineSplitter::operator* () const {
+ return mCur;
+}
+
+inline
+LineSplitter::operator bool() const {
+ return mStream.GetRemainingSize() > 0;
+}
+
+inline
+LineSplitter::operator line_idx() const {
+ return mIdx;
+}
+
+inline
+LineSplitter::line_idx LineSplitter::get_index() const {
+ return mIdx;
+}
+
+inline
+StreamReaderLE &LineSplitter::get_stream() {
+ return mStream;
+}
+
+inline
+bool LineSplitter::match_start(const char* check) {
+ const size_t len = ::strlen(check);
+
+ return len <= mCur.length() && std::equal(check, check + len, mCur.begin());
+}
+
+inline
+void LineSplitter::swallow_next_increment() {
+ mSwallow = true;
+}
+
+} // Namespace Assimp
+
+#endif // INCLUDED_LINE_SPLITTER_H
diff --git a/thirdparty/assimp/include/assimp/LogAux.h b/thirdparty/assimp/include/assimp/LogAux.h
new file mode 100644
index 0000000000..558485272e
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/LogAux.h
@@ -0,0 +1,131 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file LogAux.h
+ * @brief Common logging usage patterns for importer implementations
+ */
+#ifndef INCLUDED_AI_LOGAUX_H
+#define INCLUDED_AI_LOGAUX_H
+
+#include <assimp/TinyFormatter.h>
+#include <assimp/Exceptional.h>
+#include <assimp/DefaultLogger.hpp>
+
+namespace Assimp {
+
+template<class TDeriving>
+class LogFunctions {
+public:
+ // ------------------------------------------------------------------------------------------------
+ static void ThrowException(const std::string& msg)
+ {
+ throw DeadlyImportError(Prefix()+msg);
+ }
+
+ // ------------------------------------------------------------------------------------------------
+ static void LogWarn(const Formatter::format& message) {
+ if (!DefaultLogger::isNullLogger()) {
+ ASSIMP_LOG_WARN(Prefix()+(std::string)message);
+ }
+ }
+
+ // ------------------------------------------------------------------------------------------------
+ static void LogError(const Formatter::format& message) {
+ if (!DefaultLogger::isNullLogger()) {
+ ASSIMP_LOG_ERROR(Prefix()+(std::string)message);
+ }
+ }
+
+ // ------------------------------------------------------------------------------------------------
+ static void LogInfo(const Formatter::format& message) {
+ if (!DefaultLogger::isNullLogger()) {
+ ASSIMP_LOG_INFO(Prefix()+(std::string)message);
+ }
+ }
+
+ // ------------------------------------------------------------------------------------------------
+ static void LogDebug(const Formatter::format& message) {
+ if (!DefaultLogger::isNullLogger()) {
+ ASSIMP_LOG_DEBUG(Prefix()+(std::string)message);
+ }
+ }
+
+ // https://sourceforge.net/tracker/?func=detail&atid=1067632&aid=3358562&group_id=226462
+#if !defined(__GNUC__) || !defined(__APPLE__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
+
+ // ------------------------------------------------------------------------------------------------
+ static void LogWarn (const char* message) {
+ if (!DefaultLogger::isNullLogger()) {
+ LogWarn(Formatter::format(message));
+ }
+ }
+
+ // ------------------------------------------------------------------------------------------------
+ static void LogError (const char* message) {
+ if (!DefaultLogger::isNullLogger()) {
+ LogError(Formatter::format(message));
+ }
+ }
+
+ // ------------------------------------------------------------------------------------------------
+ static void LogInfo (const char* message) {
+ if (!DefaultLogger::isNullLogger()) {
+ LogInfo(Formatter::format(message));
+ }
+ }
+
+ // ------------------------------------------------------------------------------------------------
+ static void LogDebug (const char* message) {
+ if (!DefaultLogger::isNullLogger()) {
+ LogDebug(Formatter::format(message));
+ }
+ }
+
+#endif
+
+private:
+ static const char* Prefix();
+
+};
+} // ! Assimp
+
+#endif
diff --git a/thirdparty/assimp/include/assimp/LogStream.hpp b/thirdparty/assimp/include/assimp/LogStream.hpp
new file mode 100644
index 0000000000..d0281e2d02
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/LogStream.hpp
@@ -0,0 +1,111 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file LogStream.hpp
+ * @brief Abstract base class 'LogStream', representing an output log stream.
+ */
+#ifndef INCLUDED_AI_LOGSTREAM_H
+#define INCLUDED_AI_LOGSTREAM_H
+
+#include "types.h"
+
+namespace Assimp {
+
+class IOSystem;
+
+// ------------------------------------------------------------------------------------
+/** @brief CPP-API: Abstract interface for log stream implementations.
+ *
+ * Several default implementations are provided, see #aiDefaultLogStream for more
+ * details. Writing your own implementation of LogStream is just necessary if these
+ * are not enough for your purpose. */
+class ASSIMP_API LogStream
+#ifndef SWIG
+ : public Intern::AllocateFromAssimpHeap
+#endif
+{
+protected:
+ /** @brief Default constructor */
+ LogStream() AI_NO_EXCEPT;
+
+public:
+ /** @brief Virtual destructor */
+ virtual ~LogStream();
+
+ // -------------------------------------------------------------------
+ /** @brief Overwrite this for your own output methods
+ *
+ * Log messages *may* consist of multiple lines and you shouldn't
+ * expect a consistent formatting. If you want custom formatting
+ * (e.g. generate HTML), supply a custom instance of Logger to
+ * #DefaultLogger:set(). Usually you can *expect* that a log message
+ * is exactly one line and terminated with a single \n character.
+ * @param message Message to be written */
+ virtual void write(const char* message) = 0;
+
+ // -------------------------------------------------------------------
+ /** @brief Creates a default log stream
+ * @param streams Type of the default stream
+ * @param name For aiDefaultLogStream_FILE: name of the output file
+ * @param io For aiDefaultLogStream_FILE: IOSystem to be used to open the output
+ * file. Pass NULL for the default implementation.
+ * @return New LogStream instance. */
+ static LogStream* createDefaultStream(aiDefaultLogStream stream,
+ const char* name = "AssimpLog.txt",
+ IOSystem* io = nullptr );
+
+}; // !class LogStream
+
+inline
+LogStream::LogStream() AI_NO_EXCEPT {
+ // empty
+}
+
+inline
+LogStream::~LogStream() {
+ // empty
+}
+
+// ------------------------------------------------------------------------------------
+} // Namespace Assimp
+
+#endif
diff --git a/thirdparty/assimp/include/assimp/Logger.hpp b/thirdparty/assimp/include/assimp/Logger.hpp
new file mode 100644
index 0000000000..89cade6c33
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/Logger.hpp
@@ -0,0 +1,305 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file Logger.hpp
+ * @brief Abstract base class 'Logger', base of the logging system.
+ */
+#ifndef INCLUDED_AI_LOGGER_H
+#define INCLUDED_AI_LOGGER_H
+
+#include <assimp/types.h>
+#include <assimp/TinyFormatter.h>
+
+namespace Assimp {
+
+class LogStream;
+
+// Maximum length of a log message. Longer messages are rejected.
+#define MAX_LOG_MESSAGE_LENGTH 1024u
+
+// ----------------------------------------------------------------------------------
+/** @brief CPP-API: Abstract interface for logger implementations.
+ * Assimp provides a default implementation and uses it for almost all
+ * logging stuff ('DefaultLogger'). This class defines just basic logging
+ * behavior and is not of interest for you. Instead, take a look at #DefaultLogger. */
+class ASSIMP_API Logger
+#ifndef SWIG
+ : public Intern::AllocateFromAssimpHeap
+#endif
+{
+public:
+
+ // ----------------------------------------------------------------------
+ /** @enum LogSeverity
+ * @brief Log severity to describe the granularity of logging.
+ */
+ enum LogSeverity {
+ NORMAL, //!< Normal granularity of logging
+ VERBOSE //!< Debug infos will be logged, too
+ };
+
+ // ----------------------------------------------------------------------
+ /** @enum ErrorSeverity
+ * @brief Description for severity of a log message.
+ *
+ * Every LogStream has a bitwise combination of these flags.
+ * A LogStream doesn't receive any messages of a specific type
+ * if it doesn't specify the corresponding ErrorSeverity flag.
+ */
+ enum ErrorSeverity {
+ Debugging = 1, //!< Debug log message
+ Info = 2, //!< Info log message
+ Warn = 4, //!< Warn log message
+ Err = 8 //!< Error log message
+ };
+
+public:
+
+ /** @brief Virtual destructor */
+ virtual ~Logger();
+
+ // ----------------------------------------------------------------------
+ /** @brief Writes a debug message
+ * @param message Debug message*/
+ void debug(const char* message);
+ void debug(const std::string &message);
+
+ // ----------------------------------------------------------------------
+ /** @brief Writes a info message
+ * @param message Info message*/
+ void info(const char* message);
+ void info(const std::string &message);
+
+ // ----------------------------------------------------------------------
+ /** @brief Writes a warning message
+ * @param message Warn message*/
+ void warn(const char* message);
+ void warn(const std::string &message);
+
+ // ----------------------------------------------------------------------
+ /** @brief Writes an error message
+ * @param message Error message*/
+ void error(const char* message);
+ void error(const std::string &message);
+
+ // ----------------------------------------------------------------------
+ /** @brief Set a new log severity.
+ * @param log_severity New severity for logging*/
+ void setLogSeverity(LogSeverity log_severity);
+
+ // ----------------------------------------------------------------------
+ /** @brief Get the current log severity*/
+ LogSeverity getLogSeverity() const;
+
+ // ----------------------------------------------------------------------
+ /** @brief Attach a new log-stream
+ *
+ * The logger takes ownership of the stream and is responsible
+ * for its destruction (which is done using ::delete when the logger
+ * itself is destroyed). Call detachStream to detach a stream and to
+ * gain ownership of it again.
+ * @param pStream Log-stream to attach
+ * @param severity Message filter, specified which types of log
+ * messages are dispatched to the stream. Provide a bitwise
+ * combination of the ErrorSeverity flags.
+ * @return true if the stream has been attached, false otherwise.*/
+ virtual bool attachStream(LogStream *pStream,
+ unsigned int severity = Debugging | Err | Warn | Info) = 0;
+
+ // ----------------------------------------------------------------------
+ /** @brief Detach a still attached stream from the logger (or
+ * modify the filter flags bits)
+ * @param pStream Log-stream instance for detaching
+ * @param severity Provide a bitwise combination of the ErrorSeverity
+ * flags. This value is &~ed with the current flags of the stream,
+ * if the result is 0 the stream is detached from the Logger and
+ * the caller retakes the possession of the stream.
+ * @return true if the stream has been detached, false otherwise.*/
+ virtual bool detatchStream(LogStream *pStream,
+ unsigned int severity = Debugging | Err | Warn | Info) = 0;
+
+protected:
+ /**
+ * Default constructor
+ */
+ Logger() AI_NO_EXCEPT;
+
+ /**
+ * Construction with a given log severity
+ */
+ explicit Logger(LogSeverity severity);
+
+ // ----------------------------------------------------------------------
+ /**
+ * @brief Called as a request to write a specific debug message
+ * @param message Debug message. Never longer than
+ * MAX_LOG_MESSAGE_LENGTH characters (excluding the '0').
+ * @note The message string is only valid until the scope of
+ * the function is left.
+ */
+ virtual void OnDebug(const char* message)= 0;
+
+ // ----------------------------------------------------------------------
+ /**
+ * @brief Called as a request to write a specific info message
+ * @param message Info message. Never longer than
+ * MAX_LOG_MESSAGE_LENGTH characters (ecxluding the '0').
+ * @note The message string is only valid until the scope of
+ * the function is left.
+ */
+ virtual void OnInfo(const char* message) = 0;
+
+ // ----------------------------------------------------------------------
+ /**
+ * @brief Called as a request to write a specific warn message
+ * @param message Warn message. Never longer than
+ * MAX_LOG_MESSAGE_LENGTH characters (exluding the '0').
+ * @note The message string is only valid until the scope of
+ * the function is left.
+ */
+ virtual void OnWarn(const char* essage) = 0;
+
+ // ----------------------------------------------------------------------
+ /**
+ * @brief Called as a request to write a specific error message
+ * @param message Error message. Never longer than
+ * MAX_LOG_MESSAGE_LENGTH characters (exluding the '0').
+ * @note The message string is only valid until the scope of
+ * the function is left.
+ */
+ virtual void OnError(const char* message) = 0;
+
+protected:
+ LogSeverity m_Severity;
+};
+
+// ----------------------------------------------------------------------------------
+// Default constructor
+inline
+Logger::Logger() AI_NO_EXCEPT
+: m_Severity(NORMAL) {
+ // empty
+}
+
+// ----------------------------------------------------------------------------------
+// Virtual destructor
+inline
+Logger::~Logger() {
+ // empty
+}
+
+// ----------------------------------------------------------------------------------
+// Construction with given logging severity
+inline
+Logger::Logger(LogSeverity severity)
+: m_Severity(severity) {
+ // empty
+}
+
+// ----------------------------------------------------------------------------------
+// Log severity setter
+inline
+void Logger::setLogSeverity(LogSeverity log_severity){
+ m_Severity = log_severity;
+}
+
+// ----------------------------------------------------------------------------------
+// Log severity getter
+inline
+Logger::LogSeverity Logger::getLogSeverity() const {
+ return m_Severity;
+}
+
+// ----------------------------------------------------------------------------------
+inline
+void Logger::debug(const std::string &message) {
+ return debug(message.c_str());
+}
+
+// ----------------------------------------------------------------------------------
+inline
+void Logger::error(const std::string &message) {
+ return error(message.c_str());
+}
+
+// ----------------------------------------------------------------------------------
+inline
+void Logger::warn(const std::string &message) {
+ return warn(message.c_str());
+}
+
+// ----------------------------------------------------------------------------------
+inline
+void Logger::info(const std::string &message) {
+ return info(message.c_str());
+}
+
+// ------------------------------------------------------------------------------------------------
+#define ASSIMP_LOG_WARN_F(string,...)\
+ DefaultLogger::get()->warn((Formatter::format(string),__VA_ARGS__))
+
+#define ASSIMP_LOG_ERROR_F(string,...)\
+ DefaultLogger::get()->error((Formatter::format(string),__VA_ARGS__))
+
+#define ASSIMP_LOG_DEBUG_F(string,...)\
+ DefaultLogger::get()->debug((Formatter::format(string),__VA_ARGS__))
+
+#define ASSIMP_LOG_INFO_F(string,...)\
+ DefaultLogger::get()->info((Formatter::format(string),__VA_ARGS__))
+
+
+#define ASSIMP_LOG_WARN(string)\
+ DefaultLogger::get()->warn(string)
+
+#define ASSIMP_LOG_ERROR(string)\
+ DefaultLogger::get()->error(string)
+
+#define ASSIMP_LOG_DEBUG(string)\
+ DefaultLogger::get()->debug(string)
+
+#define ASSIMP_LOG_INFO(string)\
+ DefaultLogger::get()->info(string)
+
+
+} // Namespace Assimp
+
+#endif // !! INCLUDED_AI_LOGGER_H
diff --git a/thirdparty/assimp/include/assimp/Macros.h b/thirdparty/assimp/include/assimp/Macros.h
new file mode 100644
index 0000000000..6515303372
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/Macros.h
@@ -0,0 +1,49 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/* Helper macro to set a pointer to NULL in debug builds
+ */
+#if (defined ASSIMP_BUILD_DEBUG)
+# define AI_DEBUG_INVALIDATE_PTR(x) x = NULL;
+#else
+# define AI_DEBUG_INVALIDATE_PTR(x)
+#endif
+
diff --git a/thirdparty/assimp/include/assimp/MathFunctions.h b/thirdparty/assimp/include/assimp/MathFunctions.h
new file mode 100644
index 0000000000..cb3b696076
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/MathFunctions.h
@@ -0,0 +1,77 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2016, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file MathFunctions.h
+ * @brief Implementation of the math functions (gcd and lcm)
+ *
+ * Copied from BoostWorkaround/math
+ */
+
+namespace Assimp {
+namespace Math {
+
+// TODO: use binary GCD for unsigned integers ....
+template < typename IntegerType >
+IntegerType gcd( IntegerType a, IntegerType b )
+{
+ const IntegerType zero = (IntegerType)0;
+ while ( true )
+ {
+ if ( a == zero )
+ return b;
+ b %= a;
+
+ if ( b == zero )
+ return a;
+ a %= b;
+ }
+}
+
+template < typename IntegerType >
+IntegerType lcm( IntegerType a, IntegerType b )
+{
+ const IntegerType t = gcd (a,b);
+ if (!t)return t;
+ return a / t * b;
+}
+
+}
+}
diff --git a/thirdparty/assimp/include/assimp/MemoryIOWrapper.h b/thirdparty/assimp/include/assimp/MemoryIOWrapper.h
new file mode 100644
index 0000000000..c522787184
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/MemoryIOWrapper.h
@@ -0,0 +1,244 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file MemoryIOWrapper.h
+ * Handy IOStream/IOSystem implemetation to read directly from a memory buffer */
+#ifndef AI_MEMORYIOSTREAM_H_INC
+#define AI_MEMORYIOSTREAM_H_INC
+
+#include <assimp/IOStream.hpp>
+#include <assimp/IOSystem.hpp>
+#include <assimp/ai_assert.h>
+#include <stdint.h>
+
+namespace Assimp {
+
+#define AI_MEMORYIO_MAGIC_FILENAME "$$$___magic___$$$"
+#define AI_MEMORYIO_MAGIC_FILENAME_LENGTH 17
+
+// ----------------------------------------------------------------------------------
+/** Implementation of IOStream to read directly from a memory buffer */
+// ----------------------------------------------------------------------------------
+class MemoryIOStream : public IOStream {
+public:
+ MemoryIOStream (const uint8_t* buff, size_t len, bool own = false)
+ : buffer (buff)
+ , length(len)
+ , pos((size_t)0)
+ , own(own) {
+ // empty
+ }
+
+ ~MemoryIOStream () {
+ if(own) {
+ delete[] buffer;
+ }
+ }
+
+ // -------------------------------------------------------------------
+ // Read from stream
+ size_t Read(void* pvBuffer, size_t pSize, size_t pCount) {
+ ai_assert(nullptr != pvBuffer);
+ ai_assert(0 != pSize);
+
+ const size_t cnt = std::min( pCount, (length-pos) / pSize);
+ const size_t ofs = pSize * cnt;
+
+ ::memcpy(pvBuffer,buffer+pos,ofs);
+ pos += ofs;
+
+ return cnt;
+ }
+
+ // -------------------------------------------------------------------
+ // Write to stream
+ size_t Write(const void* /*pvBuffer*/, size_t /*pSize*/,size_t /*pCount*/) {
+ ai_assert(false); // won't be needed
+ return 0;
+ }
+
+ // -------------------------------------------------------------------
+ // Seek specific position
+ aiReturn Seek(size_t pOffset, aiOrigin pOrigin) {
+ if (aiOrigin_SET == pOrigin) {
+ if (pOffset > length) {
+ return AI_FAILURE;
+ }
+ pos = pOffset;
+ } else if (aiOrigin_END == pOrigin) {
+ if (pOffset > length) {
+ return AI_FAILURE;
+ }
+ pos = length-pOffset;
+ } else {
+ if (pOffset+pos > length) {
+ return AI_FAILURE;
+ }
+ pos += pOffset;
+ }
+ return AI_SUCCESS;
+ }
+
+ // -------------------------------------------------------------------
+ // Get current seek position
+ size_t Tell() const {
+ return pos;
+ }
+
+ // -------------------------------------------------------------------
+ // Get size of file
+ size_t FileSize() const {
+ return length;
+ }
+
+ // -------------------------------------------------------------------
+ // Flush file contents
+ void Flush() {
+ ai_assert(false); // won't be needed
+ }
+
+private:
+ const uint8_t* buffer;
+ size_t length,pos;
+ bool own;
+};
+
+// ---------------------------------------------------------------------------
+/** Dummy IO system to read from a memory buffer */
+class MemoryIOSystem : public IOSystem {
+public:
+ /** Constructor. */
+ MemoryIOSystem(const uint8_t* buff, size_t len, IOSystem* io)
+ : buffer(buff)
+ , length(len)
+ , existing_io(io)
+ , created_streams() {
+ // empty
+ }
+
+ /** Destructor. */
+ ~MemoryIOSystem() {
+ }
+
+ // -------------------------------------------------------------------
+ /** Tests for the existence of a file at the given path. */
+ bool Exists(const char* pFile) const override {
+ if (0 == strncmp( pFile, AI_MEMORYIO_MAGIC_FILENAME, AI_MEMORYIO_MAGIC_FILENAME_LENGTH ) ) {
+ return true;
+ }
+ return existing_io ? existing_io->Exists(pFile) : false;
+ }
+
+ // -------------------------------------------------------------------
+ /** Returns the directory separator. */
+ char getOsSeparator() const override {
+ return existing_io ? existing_io->getOsSeparator()
+ : '/'; // why not? it doesn't care
+ }
+
+ // -------------------------------------------------------------------
+ /** Open a new file with a given path. */
+ IOStream* Open(const char* pFile, const char* pMode = "rb") override {
+ if ( 0 == strncmp( pFile, AI_MEMORYIO_MAGIC_FILENAME, AI_MEMORYIO_MAGIC_FILENAME_LENGTH ) ) {
+ created_streams.emplace_back(new MemoryIOStream(buffer, length));
+ return created_streams.back();
+ }
+ return existing_io ? existing_io->Open(pFile, pMode) : NULL;
+ }
+
+ // -------------------------------------------------------------------
+ /** Closes the given file and releases all resources associated with it. */
+ void Close( IOStream* pFile) override {
+ auto it = std::find(created_streams.begin(), created_streams.end(), pFile);
+ if (it != created_streams.end()) {
+ delete pFile;
+ created_streams.erase(it);
+ } else if (existing_io) {
+ existing_io->Close(pFile);
+ }
+ }
+
+ // -------------------------------------------------------------------
+ /** Compare two paths */
+ bool ComparePaths(const char* one, const char* second) const override {
+ return existing_io ? existing_io->ComparePaths(one, second) : false;
+ }
+
+ bool PushDirectory( const std::string &path ) override {
+ return existing_io ? existing_io->PushDirectory(path) : false;
+ }
+
+ const std::string &CurrentDirectory() const override {
+ static std::string empty;
+ return existing_io ? existing_io->CurrentDirectory() : empty;
+ }
+
+ size_t StackSize() const override {
+ return existing_io ? existing_io->StackSize() : 0;
+ }
+
+ bool PopDirectory() override {
+ return existing_io ? existing_io->PopDirectory() : false;
+ }
+
+ bool CreateDirectory( const std::string &path ) override {
+ return existing_io ? existing_io->CreateDirectory(path) : false;
+ }
+
+ bool ChangeDirectory( const std::string &path ) override {
+ return existing_io ? existing_io->ChangeDirectory(path) : false;
+ }
+
+ bool DeleteFile( const std::string &file ) override {
+ return existing_io ? existing_io->DeleteFile(file) : false;
+ }
+
+private:
+ const uint8_t* buffer;
+ size_t length;
+ IOSystem* existing_io;
+ std::vector<IOStream*> created_streams;
+};
+
+} // end namespace Assimp
+
+#endif
diff --git a/thirdparty/assimp/include/assimp/NullLogger.hpp b/thirdparty/assimp/include/assimp/NullLogger.hpp
new file mode 100644
index 0000000000..c45d01bd48
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/NullLogger.hpp
@@ -0,0 +1,99 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file NullLogger.hpp
+ * @brief Dummy logger
+*/
+
+#ifndef INCLUDED_AI_NULLLOGGER_H
+#define INCLUDED_AI_NULLLOGGER_H
+
+#include "Logger.hpp"
+
+namespace Assimp {
+
+// ---------------------------------------------------------------------------
+/** @brief CPP-API: Empty logging implementation.
+ *
+ * Does nothing! Used by default if the application hasn't requested a
+ * custom logger via #DefaultLogger::set() or #DefaultLogger::create(); */
+class ASSIMP_API NullLogger
+ : public Logger {
+
+public:
+
+ /** @brief Logs a debug message */
+ void OnDebug(const char* message) {
+ (void)message; //this avoids compiler warnings
+ }
+
+ /** @brief Logs an info message */
+ void OnInfo(const char* message) {
+ (void)message; //this avoids compiler warnings
+ }
+
+ /** @brief Logs a warning message */
+ void OnWarn(const char* message) {
+ (void)message; //this avoids compiler warnings
+ }
+
+ /** @brief Logs an error message */
+ void OnError(const char* message) {
+ (void)message; //this avoids compiler warnings
+ }
+
+ /** @brief Detach a still attached stream from logger */
+ bool attachStream(LogStream *pStream, unsigned int severity) {
+ (void)pStream; (void)severity; //this avoids compiler warnings
+ return false;
+ }
+
+ /** @brief Detach a still attached stream from logger */
+ bool detatchStream(LogStream *pStream, unsigned int severity) {
+ (void)pStream; (void)severity; //this avoids compiler warnings
+ return false;
+ }
+
+private:
+};
+}
+#endif // !! AI_NULLLOGGER_H_INCLUDED
diff --git a/thirdparty/assimp/include/assimp/ParsingUtils.h b/thirdparty/assimp/include/assimp/ParsingUtils.h
new file mode 100644
index 0000000000..ca30ce13b0
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/ParsingUtils.h
@@ -0,0 +1,260 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+
+/** @file ParsingUtils.h
+ * @brief Defines helper functions for text parsing
+ */
+#ifndef AI_PARSING_UTILS_H_INC
+#define AI_PARSING_UTILS_H_INC
+
+#include "StringComparison.h"
+#include "StringUtils.h"
+#include <assimp/defs.h>
+
+namespace Assimp {
+
+// NOTE: the functions below are mostly intended as replacement for
+// std::upper, std::lower, std::isupper, std::islower, std::isspace.
+// we don't bother of locales. We don't want them. We want reliable
+// (i.e. identical) results across all locales.
+
+// The functions below accept any character type, but know only
+// about ASCII. However, UTF-32 is the only safe ASCII superset to
+// use since it doesn't have multi-byte sequences.
+
+static const unsigned int BufferSize = 4096;
+
+// ---------------------------------------------------------------------------------
+template <class char_t>
+AI_FORCE_INLINE
+char_t ToLower( char_t in ) {
+ return (in >= (char_t)'A' && in <= (char_t)'Z') ? (char_t)(in+0x20) : in;
+}
+
+// ---------------------------------------------------------------------------------
+template <class char_t>
+AI_FORCE_INLINE
+char_t ToUpper( char_t in) {
+ return (in >= (char_t)'a' && in <= (char_t)'z') ? (char_t)(in-0x20) : in;
+}
+
+// ---------------------------------------------------------------------------------
+template <class char_t>
+AI_FORCE_INLINE
+bool IsUpper( char_t in) {
+ return (in >= (char_t)'A' && in <= (char_t)'Z');
+}
+
+// ---------------------------------------------------------------------------------
+template <class char_t>
+AI_FORCE_INLINE
+bool IsLower( char_t in) {
+ return (in >= (char_t)'a' && in <= (char_t)'z');
+}
+
+// ---------------------------------------------------------------------------------
+template <class char_t>
+AI_FORCE_INLINE
+bool IsSpace( char_t in) {
+ return (in == (char_t)' ' || in == (char_t)'\t');
+}
+
+// ---------------------------------------------------------------------------------
+template <class char_t>
+AI_FORCE_INLINE
+bool IsLineEnd( char_t in) {
+ return (in==(char_t)'\r'||in==(char_t)'\n'||in==(char_t)'\0'||in==(char_t)'\f');
+}
+
+// ---------------------------------------------------------------------------------
+template <class char_t>
+AI_FORCE_INLINE
+bool IsSpaceOrNewLine( char_t in) {
+ return IsSpace<char_t>(in) || IsLineEnd<char_t>(in);
+}
+
+// ---------------------------------------------------------------------------------
+template <class char_t>
+AI_FORCE_INLINE
+bool SkipSpaces( const char_t* in, const char_t** out) {
+ while( *in == ( char_t )' ' || *in == ( char_t )'\t' ) {
+ ++in;
+ }
+ *out = in;
+ return !IsLineEnd<char_t>(*in);
+}
+
+// ---------------------------------------------------------------------------------
+template <class char_t>
+AI_FORCE_INLINE
+bool SkipSpaces( const char_t** inout) {
+ return SkipSpaces<char_t>(*inout,inout);
+}
+
+// ---------------------------------------------------------------------------------
+template <class char_t>
+AI_FORCE_INLINE
+bool SkipLine( const char_t* in, const char_t** out) {
+ while( *in != ( char_t )'\r' && *in != ( char_t )'\n' && *in != ( char_t )'\0' ) {
+ ++in;
+ }
+
+ // files are opened in binary mode. Ergo there are both NL and CR
+ while( *in == ( char_t )'\r' || *in == ( char_t )'\n' ) {
+ ++in;
+ }
+ *out = in;
+ return *in != (char_t)'\0';
+}
+
+// ---------------------------------------------------------------------------------
+template <class char_t>
+AI_FORCE_INLINE
+bool SkipLine( const char_t** inout) {
+ return SkipLine<char_t>(*inout,inout);
+}
+
+// ---------------------------------------------------------------------------------
+template <class char_t>
+AI_FORCE_INLINE
+bool SkipSpacesAndLineEnd( const char_t* in, const char_t** out) {
+ while( *in == ( char_t )' ' || *in == ( char_t )'\t' || *in == ( char_t )'\r' || *in == ( char_t )'\n' ) {
+ ++in;
+ }
+ *out = in;
+ return *in != '\0';
+}
+
+// ---------------------------------------------------------------------------------
+template <class char_t>
+AI_FORCE_INLINE
+bool SkipSpacesAndLineEnd( const char_t** inout) {
+ return SkipSpacesAndLineEnd<char_t>(*inout,inout);
+}
+
+// ---------------------------------------------------------------------------------
+template <class char_t>
+AI_FORCE_INLINE
+bool GetNextLine( const char_t*& buffer, char_t out[ BufferSize ] ) {
+ if( ( char_t )'\0' == *buffer ) {
+ return false;
+ }
+
+ char* _out = out;
+ char* const end = _out + BufferSize;
+ while( !IsLineEnd( *buffer ) && _out < end ) {
+ *_out++ = *buffer++;
+ }
+ *_out = (char_t)'\0';
+
+ while( IsLineEnd( *buffer ) && '\0' != *buffer ) {
+ ++buffer;
+ }
+
+ return true;
+}
+
+// ---------------------------------------------------------------------------------
+template <class char_t>
+AI_FORCE_INLINE bool IsNumeric( char_t in)
+{
+ return ( in >= '0' && in <= '9' ) || '-' == in || '+' == in;
+}
+
+// ---------------------------------------------------------------------------------
+template <class char_t>
+AI_FORCE_INLINE
+bool TokenMatch(char_t*& in, const char* token, unsigned int len)
+{
+ if (!::strncmp(token,in,len) && IsSpaceOrNewLine(in[len])) {
+ if (in[len] != '\0') {
+ in += len+1;
+ } else {
+ // If EOF after the token make sure we don't go past end of buffer
+ in += len;
+ }
+ return true;
+ }
+
+ return false;
+}
+// ---------------------------------------------------------------------------------
+/** @brief Case-ignoring version of TokenMatch
+ * @param in Input
+ * @param token Token to check for
+ * @param len Number of characters to check
+ */
+AI_FORCE_INLINE
+bool TokenMatchI(const char*& in, const char* token, unsigned int len) {
+ if (!ASSIMP_strincmp(token,in,len) && IsSpaceOrNewLine(in[len])) {
+ in += len+1;
+ return true;
+ }
+ return false;
+}
+
+// ---------------------------------------------------------------------------------
+AI_FORCE_INLINE
+void SkipToken(const char*& in) {
+ SkipSpaces(&in);
+ while ( !IsSpaceOrNewLine( *in ) ) {
+ ++in;
+ }
+}
+
+// ---------------------------------------------------------------------------------
+AI_FORCE_INLINE
+std::string GetNextToken(const char*& in) {
+ SkipSpacesAndLineEnd(&in);
+ const char* cur = in;
+ while ( !IsSpaceOrNewLine( *in ) ) {
+ ++in;
+ }
+ return std::string(cur,(size_t)(in-cur));
+}
+
+// ---------------------------------------------------------------------------------
+
+} // ! namespace Assimp
+
+#endif // ! AI_PARSING_UTILS_H_INC
diff --git a/thirdparty/assimp/include/assimp/Profiler.h b/thirdparty/assimp/include/assimp/Profiler.h
new file mode 100644
index 0000000000..6ff9d41c0a
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/Profiler.h
@@ -0,0 +1,99 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file Profiler.h
+ * @brief Utility to measure the respective runtime of each import step
+ */
+#ifndef INCLUDED_PROFILER_H
+#define INCLUDED_PROFILER_H
+
+#include <chrono>
+#include <assimp/DefaultLogger.hpp>
+#include "TinyFormatter.h"
+
+#include <map>
+
+namespace Assimp {
+namespace Profiling {
+
+using namespace Formatter;
+
+// ------------------------------------------------------------------------------------------------
+/** Simple wrapper around boost::timer to simplify reporting. Timings are automatically
+ * dumped to the log file.
+ */
+class Profiler {
+public:
+ Profiler() {
+ // empty
+ }
+
+public:
+
+ /** Start a named timer */
+ void BeginRegion(const std::string& region) {
+ regions[region] = std::chrono::system_clock::now();
+ ASSIMP_LOG_DEBUG((format("START `"),region,"`"));
+ }
+
+
+ /** End a specific named timer and write its end time to the log */
+ void EndRegion(const std::string& region) {
+ RegionMap::const_iterator it = regions.find(region);
+ if (it == regions.end()) {
+ return;
+ }
+
+ std::chrono::duration<double> elapsedSeconds = std::chrono::system_clock::now() - regions[region];
+ ASSIMP_LOG_DEBUG((format("END `"),region,"`, dt= ", elapsedSeconds.count()," s"));
+ }
+
+private:
+ typedef std::map<std::string,std::chrono::time_point<std::chrono::system_clock>> RegionMap;
+ RegionMap regions;
+};
+
+}
+}
+
+#endif
+
diff --git a/thirdparty/assimp/include/assimp/ProgressHandler.hpp b/thirdparty/assimp/include/assimp/ProgressHandler.hpp
new file mode 100644
index 0000000000..4e47f1d0a6
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/ProgressHandler.hpp
@@ -0,0 +1,145 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file ProgressHandler.hpp
+ * @brief Abstract base class 'ProgressHandler'.
+ */
+#pragma once
+#ifndef AI_PROGRESSHANDLER_H_INC
+#define AI_PROGRESSHANDLER_H_INC
+
+#include "types.h"
+
+namespace Assimp {
+
+// ------------------------------------------------------------------------------------
+/** @brief CPP-API: Abstract interface for custom progress report receivers.
+ *
+ * Each #Importer instance maintains its own #ProgressHandler. The default
+ * implementation provided by Assimp doesn't do anything at all. */
+class ASSIMP_API ProgressHandler
+#ifndef SWIG
+ : public Intern::AllocateFromAssimpHeap
+#endif
+{
+protected:
+ /// @brief Default constructor
+ ProgressHandler () AI_NO_EXCEPT {
+ // empty
+ }
+
+public:
+ /// @brief Virtual destructor.
+ virtual ~ProgressHandler () {
+ }
+
+ // -------------------------------------------------------------------
+ /** @brief Progress callback.
+ * @param percentage An estimate of the current loading progress,
+ * in percent. Or -1.f if such an estimate is not available.
+ *
+ * There are restriction on what you may do from within your
+ * implementation of this method: no exceptions may be thrown and no
+ * non-const #Importer methods may be called. It is
+ * not generally possible to predict the number of callbacks
+ * fired during a single import.
+ *
+ * @return Return false to abort loading at the next possible
+ * occasion (loaders and Assimp are generally allowed to perform
+ * all needed cleanup tasks prior to returning control to the
+ * caller). If the loading is aborted, #Importer::ReadFile()
+ * returns always NULL.
+ * */
+ virtual bool Update(float percentage = -1.f) = 0;
+
+ // -------------------------------------------------------------------
+ /** @brief Progress callback for file loading steps
+ * @param numberOfSteps The number of total post-processing
+ * steps
+ * @param currentStep The index of the current post-processing
+ * step that will run, or equal to numberOfSteps if all of
+ * them has finished. This number is always strictly monotone
+ * increasing, although not necessarily linearly.
+ *
+ * @note This is currently only used at the start and the end
+ * of the file parsing.
+ * */
+ virtual void UpdateFileRead(int currentStep /*= 0*/, int numberOfSteps /*= 0*/) {
+ float f = numberOfSteps ? currentStep / (float)numberOfSteps : 1.0f;
+ Update( f * 0.5f );
+ }
+
+ // -------------------------------------------------------------------
+ /** @brief Progress callback for post-processing steps
+ * @param numberOfSteps The number of total post-processing
+ * steps
+ * @param currentStep The index of the current post-processing
+ * step that will run, or equal to numberOfSteps if all of
+ * them has finished. This number is always strictly monotone
+ * increasing, although not necessarily linearly.
+ * */
+ virtual void UpdatePostProcess(int currentStep /*= 0*/, int numberOfSteps /*= 0*/) {
+ float f = numberOfSteps ? currentStep / (float)numberOfSteps : 1.0f;
+ Update( f * 0.5f + 0.5f );
+ }
+
+
+ // -------------------------------------------------------------------
+ /** @brief Progress callback for export steps.
+ * @param numberOfSteps The number of total processing
+ * steps
+ * @param currentStep The index of the current post-processing
+ * step that will run, or equal to numberOfSteps if all of
+ * them has finished. This number is always strictly monotone
+ * increasing, although not necessarily linearly.
+ * */
+ virtual void UpdateFileWrite(int currentStep /*= 0*/, int numberOfSteps /*= 0*/) {
+ float f = numberOfSteps ? currentStep / (float)numberOfSteps : 1.0f;
+ Update(f * 0.5f);
+ }
+}; // !class ProgressHandler
+
+// ------------------------------------------------------------------------------------
+
+} // Namespace Assimp
+
+#endif // AI_PROGRESSHANDLER_H_INC
diff --git a/thirdparty/assimp/include/assimp/RemoveComments.h b/thirdparty/assimp/include/assimp/RemoveComments.h
new file mode 100644
index 0000000000..404b496719
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/RemoveComments.h
@@ -0,0 +1,91 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file Declares a helper class, "CommentRemover", which can be
+ * used to remove comments (single and multi line) from a text file.
+ */
+#ifndef AI_REMOVE_COMMENTS_H_INC
+#define AI_REMOVE_COMMENTS_H_INC
+
+
+#include <assimp/defs.h>
+
+namespace Assimp {
+
+// ---------------------------------------------------------------------------
+/** \brief Helper class to remove single and multi line comments from a file
+ *
+ * Some mesh formats like MD5 have comments that are quite similar
+ * to those in C or C++ so this code has been moved to a separate
+ * module.
+ */
+class ASSIMP_API CommentRemover
+{
+ // class cannot be instanced
+ CommentRemover() {}
+
+public:
+
+ //! Remove single-line comments. The end of a line is
+ //! expected to be either NL or CR or NLCR.
+ //! \param szComment The start sequence of the comment, e.g. "//"
+ //! \param szBuffer Buffer to work with
+ //! \param chReplacement Character to be used as replacement
+ //! for commented lines. By default this is ' '
+ static void RemoveLineComments(const char* szComment,
+ char* szBuffer, char chReplacement = ' ');
+
+ //! Remove multi-line comments. The end of a line is
+ //! expected to be either NL or CR or NLCR. Multi-line comments
+ //! may not be nested (as in C).
+ //! \param szCommentStart The start sequence of the comment, e.g. "/*"
+ //! \param szCommentEnd The end sequence of the comment, e.g. "*/"
+ //! \param szBuffer Buffer to work with
+ //! \param chReplacement Character to be used as replacement
+ //! for commented lines. By default this is ' '
+ static void RemoveMultiLineComments(const char* szCommentStart,
+ const char* szCommentEnd,char* szBuffer,
+ char chReplacement = ' ');
+};
+} // ! Assimp
+
+#endif // !! AI_REMOVE_COMMENTS_H_INC
diff --git a/thirdparty/assimp/include/assimp/SGSpatialSort.h b/thirdparty/assimp/include/assimp/SGSpatialSort.h
new file mode 100644
index 0000000000..5b4f3f41f2
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/SGSpatialSort.h
@@ -0,0 +1,150 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** Small helper classes to optimize finding vertices close to a given location
+ */
+#ifndef AI_D3DSSPATIALSORT_H_INC
+#define AI_D3DSSPATIALSORT_H_INC
+
+#include <assimp/types.h>
+#include <vector>
+#include <stdint.h>
+
+namespace Assimp {
+
+// ----------------------------------------------------------------------------------
+/** Specialized version of SpatialSort to support smoothing groups
+ * This is used in by the 3DS, ASE and LWO loaders. 3DS and ASE share their
+ * normal computation code in SmoothingGroups.inl, the LWO loader has its own
+ * implementation to handle all details of its file format correctly.
+ */
+// ----------------------------------------------------------------------------------
+class ASSIMP_API SGSpatialSort
+{
+public:
+
+ SGSpatialSort();
+
+ // -------------------------------------------------------------------
+ /** Construction from a given face array, handling smoothing groups
+ * properly
+ */
+ explicit SGSpatialSort(const std::vector<aiVector3D>& vPositions);
+
+ // -------------------------------------------------------------------
+ /** Add a vertex to the spatial sort
+ * @param vPosition Vertex position to be added
+ * @param index Index of the vrtex
+ * @param smoothingGroup SmoothingGroup for this vertex
+ */
+ void Add(const aiVector3D& vPosition, unsigned int index,
+ unsigned int smoothingGroup);
+
+ // -------------------------------------------------------------------
+ /** Prepare the spatial sorter for use. This step runs in O(logn)
+ */
+ void Prepare();
+
+ /** Destructor */
+ ~SGSpatialSort();
+
+ // -------------------------------------------------------------------
+ /** Returns an iterator for all positions close to the given position.
+ * @param pPosition The position to look for vertices.
+ * @param pSG Only included vertices with at least one shared smooth group
+ * @param pRadius Maximal distance from the position a vertex may have
+ * to be counted in.
+ * @param poResults The container to store the indices of the found
+ * positions. Will be emptied by the call so it may contain anything.
+ * @param exactMatch Specifies whether smoothing groups are bit masks
+ * (false) or integral values (true). In the latter case, a vertex
+ * cannot belong to more than one smoothing group.
+ * @return An iterator to iterate over all vertices in the given area.
+ */
+ // -------------------------------------------------------------------
+ void FindPositions( const aiVector3D& pPosition, uint32_t pSG,
+ float pRadius, std::vector<unsigned int>& poResults,
+ bool exactMatch = false) const;
+
+protected:
+ /** Normal of the sorting plane, normalized. The center is always at (0, 0, 0) */
+ aiVector3D mPlaneNormal;
+
+ // -------------------------------------------------------------------
+ /** An entry in a spatially sorted position array. Consists of a
+ * vertex index, its position and its pre-calculated distance from
+ * the reference plane */
+ // -------------------------------------------------------------------
+ struct Entry {
+ unsigned int mIndex; ///< The vertex referred by this entry
+ aiVector3D mPosition; ///< Position
+ uint32_t mSmoothGroups;
+ float mDistance; ///< Distance of this vertex to the sorting plane
+
+ Entry() AI_NO_EXCEPT
+ : mIndex(0)
+ , mPosition()
+ , mSmoothGroups(0)
+ , mDistance(0.0f) {
+ // empty
+ }
+
+ Entry( unsigned int pIndex, const aiVector3D& pPosition, float pDistance,uint32_t pSG)
+ : mIndex( pIndex)
+ , mPosition( pPosition)
+ , mSmoothGroups(pSG)
+ , mDistance( pDistance) {
+ // empty
+ }
+
+ bool operator < (const Entry& e) const {
+ return mDistance < e.mDistance;
+ }
+ };
+
+ // all positions, sorted by distance to the sorting plane
+ std::vector<Entry> mPositions;
+};
+
+} // end of namespace Assimp
+
+#endif // AI_SPATIALSORT_H_INC
diff --git a/thirdparty/assimp/include/assimp/SceneCombiner.h b/thirdparty/assimp/include/assimp/SceneCombiner.h
new file mode 100644
index 0000000000..679a2acea4
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/SceneCombiner.h
@@ -0,0 +1,401 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file Declares a helper class, "SceneCombiner" providing various
+ * utilities to merge scenes.
+ */
+#ifndef AI_SCENE_COMBINER_H_INC
+#define AI_SCENE_COMBINER_H_INC
+
+#include <assimp/ai_assert.h>
+#include <assimp/types.h>
+#include <assimp/Defines.h>
+#include <stddef.h>
+#include <set>
+#include <list>
+#include <stdint.h>
+
+#include <vector>
+
+struct aiScene;
+struct aiNode;
+struct aiMaterial;
+struct aiTexture;
+struct aiCamera;
+struct aiLight;
+struct aiMetadata;
+struct aiBone;
+struct aiMesh;
+struct aiAnimation;
+struct aiNodeAnim;
+
+namespace Assimp {
+
+// ---------------------------------------------------------------------------
+/** \brief Helper data structure for SceneCombiner.
+ *
+ * Describes to which node a scene must be attached to.
+ */
+struct AttachmentInfo
+{
+ AttachmentInfo()
+ : scene (NULL)
+ , attachToNode (NULL)
+ {}
+
+ AttachmentInfo(aiScene* _scene, aiNode* _attachToNode)
+ : scene (_scene)
+ , attachToNode (_attachToNode)
+ {}
+
+ aiScene* scene;
+ aiNode* attachToNode;
+};
+
+// ---------------------------------------------------------------------------
+struct NodeAttachmentInfo
+{
+ NodeAttachmentInfo()
+ : node (NULL)
+ , attachToNode (NULL)
+ , resolved (false)
+ , src_idx (SIZE_MAX)
+ {}
+
+ NodeAttachmentInfo(aiNode* _scene, aiNode* _attachToNode,size_t idx)
+ : node (_scene)
+ , attachToNode (_attachToNode)
+ , resolved (false)
+ , src_idx (idx)
+ {}
+
+ aiNode* node;
+ aiNode* attachToNode;
+ bool resolved;
+ size_t src_idx;
+};
+
+// ---------------------------------------------------------------------------
+/** @def AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES
+ * Generate unique names for all named scene items
+ */
+#define AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES 0x1
+
+/** @def AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES
+ * Generate unique names for materials, too.
+ * This is not absolutely required to pass the validation.
+ */
+#define AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES 0x2
+
+/** @def AI_INT_MERGE_SCENE_DUPLICATES_DEEP_CPY
+ * Use deep copies of duplicate scenes
+ */
+#define AI_INT_MERGE_SCENE_DUPLICATES_DEEP_CPY 0x4
+
+/** @def AI_INT_MERGE_SCENE_RESOLVE_CROSS_ATTACHMENTS
+ * If attachment nodes are not found in the given master scene,
+ * search the other imported scenes for them in an any order.
+ */
+#define AI_INT_MERGE_SCENE_RESOLVE_CROSS_ATTACHMENTS 0x8
+
+/** @def AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY
+ * Can be combined with AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES.
+ * Unique names are generated, but only if this is absolutely
+ * required to avoid name conflicts.
+ */
+#define AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY 0x10
+
+typedef std::pair<aiBone*,unsigned int> BoneSrcIndex;
+
+// ---------------------------------------------------------------------------
+/** @brief Helper data structure for SceneCombiner::MergeBones.
+ */
+struct BoneWithHash : public std::pair<uint32_t,aiString*> {
+ std::vector<BoneSrcIndex> pSrcBones;
+};
+
+// ---------------------------------------------------------------------------
+/** @brief Utility for SceneCombiner
+ */
+struct SceneHelper
+{
+ SceneHelper ()
+ : scene (NULL)
+ , idlen (0)
+ {
+ id[0] = 0;
+ }
+
+ explicit SceneHelper (aiScene* _scene)
+ : scene (_scene)
+ , idlen (0)
+ {
+ id[0] = 0;
+ }
+
+ AI_FORCE_INLINE aiScene* operator-> () const
+ {
+ return scene;
+ }
+
+ // scene we're working on
+ aiScene* scene;
+
+ // prefix to be added to all identifiers in the scene ...
+ char id [32];
+
+ // and its strlen()
+ unsigned int idlen;
+
+ // hash table to quickly check whether a name is contained in the scene
+ std::set<unsigned int> hashes;
+};
+
+// ---------------------------------------------------------------------------
+/** \brief Static helper class providing various utilities to merge two
+ * scenes. It is intended as internal utility and NOT for use by
+ * applications.
+ *
+ * The class is currently being used by various postprocessing steps
+ * and loaders (ie. LWS).
+ */
+class ASSIMP_API SceneCombiner {
+ // class cannot be instanced
+ SceneCombiner() {
+ // empty
+ }
+
+ ~SceneCombiner() {
+ // empty
+ }
+
+public:
+ // -------------------------------------------------------------------
+ /** Merges two or more scenes.
+ *
+ * @param dest Receives a pointer to the destination scene. If the
+ * pointer doesn't point to NULL when the function is called, the
+ * existing scene is cleared and refilled.
+ * @param src Non-empty list of scenes to be merged. The function
+ * deletes the input scenes afterwards. There may be duplicate scenes.
+ * @param flags Combination of the AI_INT_MERGE_SCENE flags defined above
+ */
+ static void MergeScenes(aiScene** dest,std::vector<aiScene*>& src,
+ unsigned int flags = 0);
+
+ // -------------------------------------------------------------------
+ /** Merges two or more scenes and attaches all scenes to a specific
+ * position in the node graph of the master scene.
+ *
+ * @param dest Receives a pointer to the destination scene. If the
+ * pointer doesn't point to NULL when the function is called, the
+ * existing scene is cleared and refilled.
+ * @param master Master scene. It will be deleted afterwards. All
+ * other scenes will be inserted in its node graph.
+ * @param src Non-empty list of scenes to be merged along with their
+ * corresponding attachment points in the master scene. The function
+ * deletes the input scenes afterwards. There may be duplicate scenes.
+ * @param flags Combination of the AI_INT_MERGE_SCENE flags defined above
+ */
+ static void MergeScenes(aiScene** dest, aiScene* master,
+ std::vector<AttachmentInfo>& src,
+ unsigned int flags = 0);
+
+ // -------------------------------------------------------------------
+ /** Merges two or more meshes
+ *
+ * The meshes should have equal vertex formats. Only components
+ * that are provided by ALL meshes will be present in the output mesh.
+ * An exception is made for VColors - they are set to black. The
+ * meshes should have the same material indices, too. The output
+ * material index is always the material index of the first mesh.
+ *
+ * @param dest Destination mesh. Must be empty.
+ * @param flags Currently no parameters
+ * @param begin First mesh to be processed
+ * @param end Points to the mesh after the last mesh to be processed
+ */
+ static void MergeMeshes(aiMesh** dest,unsigned int flags,
+ std::vector<aiMesh*>::const_iterator begin,
+ std::vector<aiMesh*>::const_iterator end);
+
+ // -------------------------------------------------------------------
+ /** Merges two or more bones
+ *
+ * @param out Mesh to receive the output bone list
+ * @param flags Currently no parameters
+ * @param begin First mesh to be processed
+ * @param end Points to the mesh after the last mesh to be processed
+ */
+ static void MergeBones(aiMesh* out,std::vector<aiMesh*>::const_iterator it,
+ std::vector<aiMesh*>::const_iterator end);
+
+ // -------------------------------------------------------------------
+ /** Merges two or more materials
+ *
+ * The materials should be complementary as much as possible. In case
+ * of a property present in different materials, the first occurrence
+ * is used.
+ *
+ * @param dest Destination material. Must be empty.
+ * @param begin First material to be processed
+ * @param end Points to the material after the last material to be processed
+ */
+ static void MergeMaterials(aiMaterial** dest,
+ std::vector<aiMaterial*>::const_iterator begin,
+ std::vector<aiMaterial*>::const_iterator end);
+
+ // -------------------------------------------------------------------
+ /** Builds a list of uniquely named bones in a mesh list
+ *
+ * @param asBones Receives the output list
+ * @param it First mesh to be processed
+ * @param end Last mesh to be processed
+ */
+ static void BuildUniqueBoneList(std::list<BoneWithHash>& asBones,
+ std::vector<aiMesh*>::const_iterator it,
+ std::vector<aiMesh*>::const_iterator end);
+
+ // -------------------------------------------------------------------
+ /** Add a name prefix to all nodes in a scene.
+ *
+ * @param Current node. This function is called recursively.
+ * @param prefix Prefix to be added to all nodes
+ * @param len STring length
+ */
+ static void AddNodePrefixes(aiNode* node, const char* prefix,
+ unsigned int len);
+
+ // -------------------------------------------------------------------
+ /** Add an offset to all mesh indices in a node graph
+ *
+ * @param Current node. This function is called recursively.
+ * @param offset Offset to be added to all mesh indices
+ */
+ static void OffsetNodeMeshIndices (aiNode* node, unsigned int offset);
+
+ // -------------------------------------------------------------------
+ /** Attach a list of node graphs to well-defined nodes in a master
+ * graph. This is a helper for MergeScenes()
+ *
+ * @param master Master scene
+ * @param srcList List of source scenes along with their attachment
+ * points. If an attachment point is NULL (or does not exist in
+ * the master graph), a scene is attached to the root of the master
+ * graph (as an additional child node)
+ * @duplicates List of duplicates. If elem[n] == n the scene is not
+ * a duplicate. Otherwise elem[n] links scene n to its first occurrence.
+ */
+ static void AttachToGraph ( aiScene* master,
+ std::vector<NodeAttachmentInfo>& srcList);
+
+ static void AttachToGraph (aiNode* attach,
+ std::vector<NodeAttachmentInfo>& srcList);
+
+
+ // -------------------------------------------------------------------
+ /** Get a deep copy of a scene
+ *
+ * @param dest Receives a pointer to the destination scene
+ * @param src Source scene - remains unmodified.
+ */
+ static void CopyScene(aiScene** dest,const aiScene* source,bool allocate = true);
+
+
+ // -------------------------------------------------------------------
+ /** Get a flat copy of a scene
+ *
+ * Only the first hierarchy layer is copied. All pointer members of
+ * aiScene are shared by source and destination scene. If the
+ * pointer doesn't point to NULL when the function is called, the
+ * existing scene is cleared and refilled.
+ * @param dest Receives a pointer to the destination scene
+ * @param src Source scene - remains unmodified.
+ */
+ static void CopySceneFlat(aiScene** dest,const aiScene* source);
+
+
+ // -------------------------------------------------------------------
+ /** Get a deep copy of a mesh
+ *
+ * @param dest Receives a pointer to the destination mesh
+ * @param src Source mesh - remains unmodified.
+ */
+ static void Copy (aiMesh** dest, const aiMesh* src);
+
+ // similar to Copy():
+ static void Copy (aiMaterial** dest, const aiMaterial* src);
+ static void Copy (aiTexture** dest, const aiTexture* src);
+ static void Copy (aiAnimation** dest, const aiAnimation* src);
+ static void Copy (aiCamera** dest, const aiCamera* src);
+ static void Copy (aiBone** dest, const aiBone* src);
+ static void Copy (aiLight** dest, const aiLight* src);
+ static void Copy (aiNodeAnim** dest, const aiNodeAnim* src);
+ static void Copy (aiMetadata** dest, const aiMetadata* src);
+
+ // recursive, of course
+ static void Copy (aiNode** dest, const aiNode* src);
+
+
+private:
+
+ // -------------------------------------------------------------------
+ // Same as AddNodePrefixes, but with an additional check
+ static void AddNodePrefixesChecked(aiNode* node, const char* prefix,
+ unsigned int len,
+ std::vector<SceneHelper>& input,
+ unsigned int cur);
+
+ // -------------------------------------------------------------------
+ // Add node identifiers to a hashing set
+ static void AddNodeHashes(aiNode* node, std::set<unsigned int>& hashes);
+
+
+ // -------------------------------------------------------------------
+ // Search for duplicate names
+ static bool FindNameMatch(const aiString& name,
+ std::vector<SceneHelper>& input, unsigned int cur);
+};
+
+}
+
+#endif // !! AI_SCENE_COMBINER_H_INC
diff --git a/thirdparty/assimp/include/assimp/SkeletonMeshBuilder.h b/thirdparty/assimp/include/assimp/SkeletonMeshBuilder.h
new file mode 100644
index 0000000000..f9b8d9f55c
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/SkeletonMeshBuilder.h
@@ -0,0 +1,125 @@
+/** Helper class to construct a dummy mesh for file formats containing only motion data */
+
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file SkeletonMeshBuilder.h
+ * Declares SkeletonMeshBuilder, a tiny utility to build dummy meshes
+ * for animation skeletons.
+ */
+
+#ifndef AI_SKELETONMESHBUILDER_H_INC
+#define AI_SKELETONMESHBUILDER_H_INC
+
+#include <vector>
+#include <assimp/mesh.h>
+
+struct aiMaterial;
+struct aiScene;
+struct aiNode;
+
+namespace Assimp {
+
+// ---------------------------------------------------------------------------
+/**
+ * This little helper class constructs a dummy mesh for a given scene
+ * the resembles the node hierarchy. This is useful for file formats
+ * that don't carry any mesh data but only animation data.
+ */
+class ASSIMP_API SkeletonMeshBuilder
+{
+public:
+
+ // -------------------------------------------------------------------
+ /** The constructor processes the given scene and adds a mesh there.
+ *
+ * Does nothing if the scene already has mesh data.
+ * @param pScene The scene for which a skeleton mesh should be constructed.
+ * @param root The node to start with. NULL is the scene root
+ * @param bKnobsOnly Set this to true if you don't want the connectors
+ * between the knobs representing the nodes.
+ */
+ SkeletonMeshBuilder( aiScene* pScene, aiNode* root = NULL,
+ bool bKnobsOnly = false);
+
+protected:
+
+ // -------------------------------------------------------------------
+ /** Recursively builds a simple mesh representation for the given node
+ * and also creates a joint for the node that affects this part of
+ * the mesh.
+ * @param pNode The node to build geometry for.
+ */
+ void CreateGeometry( const aiNode* pNode);
+
+ // -------------------------------------------------------------------
+ /** Creates the mesh from the internally accumulated stuff and returns it.
+ */
+ aiMesh* CreateMesh();
+
+ // -------------------------------------------------------------------
+ /** Creates a dummy material and returns it. */
+ aiMaterial* CreateMaterial();
+
+protected:
+ /** space to assemble the mesh data: points */
+ std::vector<aiVector3D> mVertices;
+
+ /** faces */
+ struct Face
+ {
+ unsigned int mIndices[3];
+ Face();
+ Face( unsigned int p0, unsigned int p1, unsigned int p2)
+ { mIndices[0] = p0; mIndices[1] = p1; mIndices[2] = p2; }
+ };
+ std::vector<Face> mFaces;
+
+ /** bones */
+ std::vector<aiBone*> mBones;
+
+ bool mKnobsOnly;
+};
+
+} // end of namespace Assimp
+
+#endif // AI_SKELETONMESHBUILDER_H_INC
diff --git a/thirdparty/assimp/include/assimp/SmoothingGroups.h b/thirdparty/assimp/include/assimp/SmoothingGroups.h
new file mode 100644
index 0000000000..92d65cea02
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/SmoothingGroups.h
@@ -0,0 +1,108 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file Defines the helper data structures for importing 3DS files.
+http://www.jalix.org/ressources/graphics/3DS/_unofficials/3ds-unofficial.txt */
+
+#ifndef AI_SMOOTHINGGROUPS_H_INC
+#define AI_SMOOTHINGGROUPS_H_INC
+
+#include <assimp/vector3.h>
+#include <stdint.h>
+#include <vector>
+
+// ---------------------------------------------------------------------------
+/** Helper structure representing a face with smoothing groups assigned */
+struct FaceWithSmoothingGroup {
+ FaceWithSmoothingGroup() AI_NO_EXCEPT
+ : mIndices()
+ , iSmoothGroup(0) {
+ // in debug builds set all indices to a common magic value
+#ifdef ASSIMP_BUILD_DEBUG
+ this->mIndices[0] = 0xffffffff;
+ this->mIndices[1] = 0xffffffff;
+ this->mIndices[2] = 0xffffffff;
+#endif
+ }
+
+
+ //! Indices. .3ds is using uint16. However, after
+ //! an unique vertex set has been generated,
+ //! individual index values might exceed 2^16
+ uint32_t mIndices[3];
+
+ //! specifies to which smoothing group the face belongs to
+ uint32_t iSmoothGroup;
+};
+
+// ---------------------------------------------------------------------------
+/** Helper structure representing a mesh whose faces have smoothing
+ groups assigned. This allows us to reuse the code for normal computations
+ from smoothings groups for several loaders (3DS, ASE). All of them
+ use face structures which inherit from #FaceWithSmoothingGroup,
+ but as they add extra members and need to be copied by value we
+ need to use a template here.
+ */
+template <class T>
+struct MeshWithSmoothingGroups
+{
+ //! Vertex positions
+ std::vector<aiVector3D> mPositions;
+
+ //! Face lists
+ std::vector<T> mFaces;
+
+ //! List of normal vectors
+ std::vector<aiVector3D> mNormals;
+};
+
+// ---------------------------------------------------------------------------
+/** Computes normal vectors for the mesh
+ */
+template <class T>
+void ComputeNormalsWithSmoothingsGroups(MeshWithSmoothingGroups<T>& sMesh);
+
+
+// include implementations
+#include "SmoothingGroups.inl"
+
+#endif // !! AI_SMOOTHINGGROUPS_H_INC
diff --git a/thirdparty/assimp/include/assimp/SmoothingGroups.inl b/thirdparty/assimp/include/assimp/SmoothingGroups.inl
new file mode 100644
index 0000000000..84ea4a1b00
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/SmoothingGroups.inl
@@ -0,0 +1,138 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file Generation of normal vectors basing on smoothing groups */
+
+#ifndef AI_SMOOTHINGGROUPS_INL_INCLUDED
+#define AI_SMOOTHINGGROUPS_INL_INCLUDED
+
+// internal headers
+#include <assimp/SGSpatialSort.h>
+
+// CRT header
+#include <algorithm>
+
+using namespace Assimp;
+
+// ------------------------------------------------------------------------------------------------
+template <class T>
+void ComputeNormalsWithSmoothingsGroups(MeshWithSmoothingGroups<T>& sMesh)
+{
+ // First generate face normals
+ sMesh.mNormals.resize(sMesh.mPositions.size(),aiVector3D());
+ for( unsigned int a = 0; a < sMesh.mFaces.size(); a++)
+ {
+ T& face = sMesh.mFaces[a];
+
+ aiVector3D* pV1 = &sMesh.mPositions[face.mIndices[0]];
+ aiVector3D* pV2 = &sMesh.mPositions[face.mIndices[1]];
+ aiVector3D* pV3 = &sMesh.mPositions[face.mIndices[2]];
+
+ aiVector3D pDelta1 = *pV2 - *pV1;
+ aiVector3D pDelta2 = *pV3 - *pV1;
+ aiVector3D vNor = pDelta1 ^ pDelta2;
+
+ for (unsigned int c = 0; c < 3;++c)
+ sMesh.mNormals[face.mIndices[c]] = vNor;
+ }
+
+ // calculate the position bounds so we have a reliable epsilon to check position differences against
+ aiVector3D minVec( 1e10f, 1e10f, 1e10f), maxVec( -1e10f, -1e10f, -1e10f);
+ for( unsigned int a = 0; a < sMesh.mPositions.size(); a++)
+ {
+ minVec.x = std::min( minVec.x, sMesh.mPositions[a].x);
+ minVec.y = std::min( minVec.y, sMesh.mPositions[a].y);
+ minVec.z = std::min( minVec.z, sMesh.mPositions[a].z);
+ maxVec.x = std::max( maxVec.x, sMesh.mPositions[a].x);
+ maxVec.y = std::max( maxVec.y, sMesh.mPositions[a].y);
+ maxVec.z = std::max( maxVec.z, sMesh.mPositions[a].z);
+ }
+ const float posEpsilon = (maxVec - minVec).Length() * 1e-5f;
+ std::vector<aiVector3D> avNormals;
+ avNormals.resize(sMesh.mNormals.size());
+
+ // now generate the spatial sort tree
+ SGSpatialSort sSort;
+ for( typename std::vector<T>::iterator i = sMesh.mFaces.begin();
+ i != sMesh.mFaces.end();++i)
+ {
+ for (unsigned int c = 0; c < 3;++c)
+ sSort.Add(sMesh.mPositions[(*i).mIndices[c]],(*i).mIndices[c],(*i).iSmoothGroup);
+ }
+ sSort.Prepare();
+
+ std::vector<bool> vertexDone(sMesh.mPositions.size(),false);
+ for( typename std::vector<T>::iterator i = sMesh.mFaces.begin();
+ i != sMesh.mFaces.end();++i)
+ {
+ std::vector<unsigned int> poResult;
+ for (unsigned int c = 0; c < 3;++c)
+ {
+ unsigned int idx = (*i).mIndices[c];
+ if (vertexDone[idx])continue;
+
+ sSort.FindPositions(sMesh.mPositions[idx],(*i).iSmoothGroup,
+ posEpsilon,poResult);
+
+ aiVector3D vNormals;
+ for (std::vector<unsigned int>::const_iterator
+ a = poResult.begin();
+ a != poResult.end();++a)
+ {
+ vNormals += sMesh.mNormals[(*a)];
+ }
+ vNormals.NormalizeSafe();
+
+ // write back into all affected normals
+ for (std::vector<unsigned int>::const_iterator
+ a = poResult.begin();
+ a != poResult.end();++a)
+ {
+ idx = *a;
+ avNormals [idx] = vNormals;
+ vertexDone[idx] = true;
+ }
+ }
+ }
+ sMesh.mNormals = avNormals;
+}
+
+#endif // !! AI_SMOOTHINGGROUPS_INL_INCLUDED
diff --git a/thirdparty/assimp/include/assimp/SpatialSort.h b/thirdparty/assimp/include/assimp/SpatialSort.h
new file mode 100644
index 0000000000..61b345bcbf
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/SpatialSort.h
@@ -0,0 +1,174 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** Small helper classes to optimise finding vertizes close to a given location */
+#ifndef AI_SPATIALSORT_H_INC
+#define AI_SPATIALSORT_H_INC
+
+#include <vector>
+#include <assimp/types.h>
+
+namespace Assimp {
+
+// ------------------------------------------------------------------------------------------------
+/** A little helper class to quickly find all vertices in the epsilon environment of a given
+ * position. Construct an instance with an array of positions. The class stores the given positions
+ * by their indices and sorts them by their distance to an arbitrary chosen plane.
+ * You can then query the instance for all vertices close to a given position in an average O(log n)
+ * time, with O(n) worst case complexity when all vertices lay on the plane. The plane is chosen
+ * so that it avoids common planes in usual data sets. */
+// ------------------------------------------------------------------------------------------------
+class ASSIMP_API SpatialSort
+{
+public:
+
+ SpatialSort();
+
+ // ------------------------------------------------------------------------------------
+ /** Constructs a spatially sorted representation from the given position array.
+ * Supply the positions in its layout in memory, the class will only refer to them
+ * by index.
+ * @param pPositions Pointer to the first position vector of the array.
+ * @param pNumPositions Number of vectors to expect in that array.
+ * @param pElementOffset Offset in bytes from the beginning of one vector in memory
+ * to the beginning of the next vector. */
+ SpatialSort( const aiVector3D* pPositions, unsigned int pNumPositions,
+ unsigned int pElementOffset);
+
+ /** Destructor */
+ ~SpatialSort();
+
+public:
+
+ // ------------------------------------------------------------------------------------
+ /** Sets the input data for the SpatialSort. This replaces existing data, if any.
+ * The new data receives new indices in ascending order.
+ *
+ * @param pPositions Pointer to the first position vector of the array.
+ * @param pNumPositions Number of vectors to expect in that array.
+ * @param pElementOffset Offset in bytes from the beginning of one vector in memory
+ * to the beginning of the next vector.
+ * @param pFinalize Specifies whether the SpatialSort's internal representation
+ * is finalized after the new data has been added. Finalization is
+ * required in order to use #FindPosition() or #GenerateMappingTable().
+ * If you don't finalize yet, you can use #Append() to add data from
+ * other sources.*/
+ void Fill( const aiVector3D* pPositions, unsigned int pNumPositions,
+ unsigned int pElementOffset,
+ bool pFinalize = true);
+
+
+ // ------------------------------------------------------------------------------------
+ /** Same as #Fill(), except the method appends to existing data in the #SpatialSort. */
+ void Append( const aiVector3D* pPositions, unsigned int pNumPositions,
+ unsigned int pElementOffset,
+ bool pFinalize = true);
+
+
+ // ------------------------------------------------------------------------------------
+ /** Finalize the spatial hash data structure. This can be useful after
+ * multiple calls to #Append() with the pFinalize parameter set to false.
+ * This is finally required before one of #FindPositions() and #GenerateMappingTable()
+ * can be called to query the spatial sort.*/
+ void Finalize();
+
+ // ------------------------------------------------------------------------------------
+ /** Returns an iterator for all positions close to the given position.
+ * @param pPosition The position to look for vertices.
+ * @param pRadius Maximal distance from the position a vertex may have to be counted in.
+ * @param poResults The container to store the indices of the found positions.
+ * Will be emptied by the call so it may contain anything.
+ * @return An iterator to iterate over all vertices in the given area.*/
+ void FindPositions( const aiVector3D& pPosition, ai_real pRadius,
+ std::vector<unsigned int>& poResults) const;
+
+ // ------------------------------------------------------------------------------------
+ /** Fills an array with indices of all positions identical to the given position. In
+ * opposite to FindPositions(), not an epsilon is used but a (very low) tolerance of
+ * four floating-point units.
+ * @param pPosition The position to look for vertices.
+ * @param poResults The container to store the indices of the found positions.
+ * Will be emptied by the call so it may contain anything.*/
+ void FindIdenticalPositions( const aiVector3D& pPosition,
+ std::vector<unsigned int>& poResults) const;
+
+ // ------------------------------------------------------------------------------------
+ /** Compute a table that maps each vertex ID referring to a spatially close
+ * enough position to the same output ID. Output IDs are assigned in ascending order
+ * from 0...n.
+ * @param fill Will be filled with numPositions entries.
+ * @param pRadius Maximal distance from the position a vertex may have to
+ * be counted in.
+ * @return Number of unique vertices (n). */
+ unsigned int GenerateMappingTable(std::vector<unsigned int>& fill,
+ ai_real pRadius) const;
+
+protected:
+ /** Normal of the sorting plane, normalized. The center is always at (0, 0, 0) */
+ aiVector3D mPlaneNormal;
+
+ /** An entry in a spatially sorted position array. Consists of a vertex index,
+ * its position and its pre-calculated distance from the reference plane */
+ struct Entry {
+ unsigned int mIndex; ///< The vertex referred by this entry
+ aiVector3D mPosition; ///< Position
+ ai_real mDistance; ///< Distance of this vertex to the sorting plane
+
+ Entry() AI_NO_EXCEPT
+ : mIndex( 999999999 ), mPosition(), mDistance( 99999. ) {
+ // empty
+ }
+ Entry( unsigned int pIndex, const aiVector3D& pPosition, ai_real pDistance)
+ : mIndex( pIndex), mPosition( pPosition), mDistance( pDistance) {
+ // empty
+ }
+
+ bool operator < (const Entry& e) const { return mDistance < e.mDistance; }
+ };
+
+ // all positions, sorted by distance to the sorting plane
+ std::vector<Entry> mPositions;
+};
+
+} // end of namespace Assimp
+
+#endif // AI_SPATIALSORT_H_INC
diff --git a/thirdparty/assimp/include/assimp/StandardShapes.h b/thirdparty/assimp/include/assimp/StandardShapes.h
new file mode 100644
index 0000000000..3791569b83
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/StandardShapes.h
@@ -0,0 +1,200 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file Declares a helper class, "StandardShapes" which generates
+ * vertices for standard shapes, such as cylnders, cones, spheres ..
+ */
+#ifndef AI_STANDARD_SHAPES_H_INC
+#define AI_STANDARD_SHAPES_H_INC
+
+#include <assimp/vector3.h>
+#include <vector>
+
+struct aiMesh;
+
+namespace Assimp {
+
+// ---------------------------------------------------------------------------
+/** \brief Helper class to generate vertex buffers for standard geometric
+ * shapes, such as cylinders, cones, boxes, spheres, elipsoids ... .
+ */
+class ASSIMP_API StandardShapes
+{
+ // class cannot be instanced
+ StandardShapes() {}
+
+public:
+
+
+ // ----------------------------------------------------------------
+ /** Generates a mesh from an array of vertex positions.
+ *
+ * @param positions List of vertex positions
+ * @param numIndices Number of indices per primitive
+ * @return Output mesh
+ */
+ static aiMesh* MakeMesh(const std::vector<aiVector3D>& positions,
+ unsigned int numIndices);
+
+
+ static aiMesh* MakeMesh ( unsigned int (*GenerateFunc)
+ (std::vector<aiVector3D>&));
+
+ static aiMesh* MakeMesh ( unsigned int (*GenerateFunc)
+ (std::vector<aiVector3D>&, bool));
+
+ static aiMesh* MakeMesh ( unsigned int n, void (*GenerateFunc)
+ (unsigned int,std::vector<aiVector3D>&));
+
+ // ----------------------------------------------------------------
+ /** @brief Generates a hexahedron (cube)
+ *
+ * Hexahedrons can be scaled on all axes.
+ * @param positions Receives output triangles.
+ * @param polygons If you pass true here quads will be returned
+ * @return Number of vertices per face
+ */
+ static unsigned int MakeHexahedron(
+ std::vector<aiVector3D>& positions,
+ bool polygons = false);
+
+ // ----------------------------------------------------------------
+ /** @brief Generates an icosahedron
+ *
+ * @param positions Receives output triangles.
+ * @return Number of vertices per face
+ */
+ static unsigned int MakeIcosahedron(
+ std::vector<aiVector3D>& positions);
+
+
+ // ----------------------------------------------------------------
+ /** @brief Generates a dodecahedron
+ *
+ * @param positions Receives output triangles
+ * @param polygons If you pass true here pentagons will be returned
+ * @return Number of vertices per face
+ */
+ static unsigned int MakeDodecahedron(
+ std::vector<aiVector3D>& positions,
+ bool polygons = false);
+
+
+ // ----------------------------------------------------------------
+ /** @brief Generates an octahedron
+ *
+ * @param positions Receives output triangles.
+ * @return Number of vertices per face
+ */
+ static unsigned int MakeOctahedron(
+ std::vector<aiVector3D>& positions);
+
+
+ // ----------------------------------------------------------------
+ /** @brief Generates a tetrahedron
+ *
+ * @param positions Receives output triangles.
+ * @return Number of vertices per face
+ */
+ static unsigned int MakeTetrahedron(
+ std::vector<aiVector3D>& positions);
+
+
+
+ // ----------------------------------------------------------------
+ /** @brief Generates a sphere
+ *
+ * @param tess Number of subdivions - 0 generates a octahedron
+ * @param positions Receives output triangles.
+ */
+ static void MakeSphere(unsigned int tess,
+ std::vector<aiVector3D>& positions);
+
+
+ // ----------------------------------------------------------------
+ /** @brief Generates a cone or a cylinder, either open or closed.
+ *
+ * @code
+ *
+ * |-----| <- radius 1
+ *
+ * __x__ <- ] ^
+ * / \ | height |
+ * / \ | Y
+ * / \ |
+ * / \ |
+ * /______x______\ <- ] <- end cap
+ *
+ * |-------------| <- radius 2
+ *
+ * @endcode
+ *
+ * @param height Height of the cone
+ * @param radius1 First radius
+ * @param radius2 Second radius
+ * @param tess Number of triangles.
+ * @param bOpened true for an open cone/cylinder. An open shape has
+ * no 'end caps'
+ * @param positions Receives output triangles
+ */
+ static void MakeCone(ai_real height,ai_real radius1,
+ ai_real radius2,unsigned int tess,
+ std::vector<aiVector3D>& positions,bool bOpen= false);
+
+
+ // ----------------------------------------------------------------
+ /** @brief Generates a flat circle
+ *
+ * The circle is constructed in the planned formed by the x,z
+ * axes of the cartesian coordinate system.
+ *
+ * @param radius Radius of the circle
+ * @param tess Number of segments.
+ * @param positions Receives output triangles.
+ */
+ static void MakeCircle(ai_real radius, unsigned int tess,
+ std::vector<aiVector3D>& positions);
+
+};
+} // ! Assimp
+
+#endif // !! AI_STANDARD_SHAPES_H_INC
diff --git a/thirdparty/assimp/include/assimp/StreamReader.h b/thirdparty/assimp/include/assimp/StreamReader.h
new file mode 100644
index 0000000000..9116c14261
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/StreamReader.h
@@ -0,0 +1,343 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file Defines the StreamReader class which reads data from
+ * a binary stream with a well-defined endianness.
+ */
+
+#ifndef AI_STREAMREADER_H_INCLUDED
+#define AI_STREAMREADER_H_INCLUDED
+
+#include <assimp/IOStream.hpp>
+#include <assimp/Defines.h>
+
+#include "ByteSwapper.h"
+#include "Exceptional.h"
+#include <memory>
+
+namespace Assimp {
+
+// --------------------------------------------------------------------------------------------
+/** Wrapper class around IOStream to allow for consistent reading of binary data in both
+ * little and big endian format. Don't attempt to instance the template directly. Use
+ * StreamReaderLE to read from a little-endian stream and StreamReaderBE to read from a
+ * BE stream. The class expects that the endianness of any input data is known at
+ * compile-time, which should usually be true (#BaseImporter::ConvertToUTF8 implements
+ * runtime endianness conversions for text files).
+ *
+ * XXX switch from unsigned int for size types to size_t? or ptrdiff_t?*/
+// --------------------------------------------------------------------------------------------
+template <bool SwapEndianess = false, bool RuntimeSwitch = false>
+class StreamReader {
+public:
+ // FIXME: use these data types throughout the whole library,
+ // then change them to 64 bit values :-)
+ using diff = int;
+ using pos = unsigned int;
+
+ // ---------------------------------------------------------------------
+ /** Construction from a given stream with a well-defined endianness.
+ *
+ * The StreamReader holds a permanent strong reference to the
+ * stream, which is released upon destruction.
+ * @param stream Input stream. The stream is not restarted if
+ * its file pointer is not at 0. Instead, the stream reader
+ * reads from the current position to the end of the stream.
+ * @param le If @c RuntimeSwitch is true: specifies whether the
+ * stream is in little endian byte order. Otherwise the
+ * endianness information is contained in the @c SwapEndianess
+ * template parameter and this parameter is meaningless. */
+ StreamReader(std::shared_ptr<IOStream> stream, bool le = false)
+ : stream(stream)
+ , le(le)
+ {
+ ai_assert(stream);
+ InternBegin();
+ }
+
+ // ---------------------------------------------------------------------
+ StreamReader(IOStream* stream, bool le = false)
+ : stream(std::shared_ptr<IOStream>(stream))
+ , le(le)
+ {
+ ai_assert(stream);
+ InternBegin();
+ }
+
+ // ---------------------------------------------------------------------
+ ~StreamReader() {
+ delete[] buffer;
+ }
+
+ // deprecated, use overloaded operator>> instead
+
+ // ---------------------------------------------------------------------
+ /** Read a float from the stream */
+ float GetF4()
+ {
+ return Get<float>();
+ }
+
+ // ---------------------------------------------------------------------
+ /** Read a double from the stream */
+ double GetF8() {
+ return Get<double>();
+ }
+
+ // ---------------------------------------------------------------------
+ /** Read a signed 16 bit integer from the stream */
+ int16_t GetI2() {
+ return Get<int16_t>();
+ }
+
+ // ---------------------------------------------------------------------
+ /** Read a signed 8 bit integer from the stream */
+ int8_t GetI1() {
+ return Get<int8_t>();
+ }
+
+ // ---------------------------------------------------------------------
+ /** Read an signed 32 bit integer from the stream */
+ int32_t GetI4() {
+ return Get<int32_t>();
+ }
+
+ // ---------------------------------------------------------------------
+ /** Read a signed 64 bit integer from the stream */
+ int64_t GetI8() {
+ return Get<int64_t>();
+ }
+
+ // ---------------------------------------------------------------------
+ /** Read a unsigned 16 bit integer from the stream */
+ uint16_t GetU2() {
+ return Get<uint16_t>();
+ }
+
+ // ---------------------------------------------------------------------
+ /** Read a unsigned 8 bit integer from the stream */
+ uint8_t GetU1() {
+ return Get<uint8_t>();
+ }
+
+ // ---------------------------------------------------------------------
+ /** Read an unsigned 32 bit integer from the stream */
+ uint32_t GetU4() {
+ return Get<uint32_t>();
+ }
+
+ // ---------------------------------------------------------------------
+ /** Read a unsigned 64 bit integer from the stream */
+ uint64_t GetU8() {
+ return Get<uint64_t>();
+ }
+
+ // ---------------------------------------------------------------------
+ /** Get the remaining stream size (to the end of the stream) */
+ unsigned int GetRemainingSize() const {
+ return (unsigned int)(end - current);
+ }
+
+ // ---------------------------------------------------------------------
+ /** Get the remaining stream size (to the current read limit). The
+ * return value is the remaining size of the stream if no custom
+ * read limit has been set. */
+ unsigned int GetRemainingSizeToLimit() const {
+ return (unsigned int)(limit - current);
+ }
+
+ // ---------------------------------------------------------------------
+ /** Increase the file pointer (relative seeking) */
+ void IncPtr(intptr_t plus) {
+ current += plus;
+ if (current > limit) {
+ throw DeadlyImportError("End of file or read limit was reached");
+ }
+ }
+
+ // ---------------------------------------------------------------------
+ /** Get the current file pointer */
+ int8_t* GetPtr() const {
+ return current;
+ }
+
+ // ---------------------------------------------------------------------
+ /** Set current file pointer (Get it from #GetPtr). This is if you
+ * prefer to do pointer arithmetics on your own or want to copy
+ * large chunks of data at once.
+ * @param p The new pointer, which is validated against the size
+ * limit and buffer boundaries. */
+ void SetPtr(int8_t* p) {
+ current = p;
+ if (current > limit || current < buffer) {
+ throw DeadlyImportError("End of file or read limit was reached");
+ }
+ }
+
+ // ---------------------------------------------------------------------
+ /** Copy n bytes to an external buffer
+ * @param out Destination for copying
+ * @param bytes Number of bytes to copy */
+ void CopyAndAdvance(void* out, size_t bytes) {
+ int8_t* ur = GetPtr();
+ SetPtr(ur+bytes); // fire exception if eof
+
+ ::memcpy(out,ur,bytes);
+ }
+
+ // ---------------------------------------------------------------------
+ /** Get the current offset from the beginning of the file */
+ int GetCurrentPos() const {
+ return (unsigned int)(current - buffer);
+ }
+
+ void SetCurrentPos(size_t pos) {
+ SetPtr(buffer + pos);
+ }
+
+ // ---------------------------------------------------------------------
+ /** Setup a temporary read limit
+ *
+ * @param limit Maximum number of bytes to be read from
+ * the beginning of the file. Specifying UINT_MAX
+ * resets the limit to the original end of the stream.
+ * Returns the previously set limit. */
+ unsigned int SetReadLimit(unsigned int _limit) {
+ unsigned int prev = GetReadLimit();
+ if (UINT_MAX == _limit) {
+ limit = end;
+ return prev;
+ }
+
+ limit = buffer + _limit;
+ if (limit > end) {
+ throw DeadlyImportError("StreamReader: Invalid read limit");
+ }
+ return prev;
+ }
+
+ // ---------------------------------------------------------------------
+ /** Get the current read limit in bytes. Reading over this limit
+ * accidentally raises an exception. */
+ unsigned int GetReadLimit() const {
+ return (unsigned int)(limit - buffer);
+ }
+
+ // ---------------------------------------------------------------------
+ /** Skip to the read limit in bytes. Reading over this limit
+ * accidentally raises an exception. */
+ void SkipToReadLimit() {
+ current = limit;
+ }
+
+ // ---------------------------------------------------------------------
+ /** overload operator>> and allow chaining of >> ops. */
+ template <typename T>
+ StreamReader& operator >> (T& f) {
+ f = Get<T>();
+ return *this;
+ }
+
+ // ---------------------------------------------------------------------
+ /** Generic read method. ByteSwap::Swap(T*) *must* be defined */
+ template <typename T>
+ T Get() {
+ if ( current + sizeof(T) > limit) {
+ throw DeadlyImportError("End of file or stream limit was reached");
+ }
+
+ T f;
+ ::memcpy (&f, current, sizeof(T));
+ Intern::Getter<SwapEndianess,T,RuntimeSwitch>() (&f,le);
+ current += sizeof(T);
+
+ return f;
+ }
+
+private:
+ // ---------------------------------------------------------------------
+ void InternBegin() {
+ if (!stream) {
+ // in case someone wonders: StreamReader is frequently invoked with
+ // no prior validation whether the input stream is valid. Since
+ // no one bothers changing the error message, this message here
+ // is passed down to the caller and 'unable to open file'
+ // simply describes best what happened.
+ throw DeadlyImportError("StreamReader: Unable to open file");
+ }
+
+ const size_t s = stream->FileSize() - stream->Tell();
+ if (!s) {
+ throw DeadlyImportError("StreamReader: File is empty or EOF is already reached");
+ }
+
+ current = buffer = new int8_t[s];
+ const size_t read = stream->Read(current,1,s);
+ // (read < s) can only happen if the stream was opened in text mode, in which case FileSize() is not reliable
+ ai_assert(read <= s);
+ end = limit = &buffer[read-1] + 1;
+ }
+
+private:
+ std::shared_ptr<IOStream> stream;
+ int8_t *buffer, *current, *end, *limit;
+ bool le;
+};
+
+// --------------------------------------------------------------------------------------------
+// `static` StreamReaders. Their byte order is fixed and they might be a little bit faster.
+#ifdef AI_BUILD_BIG_ENDIAN
+ typedef StreamReader<true> StreamReaderLE;
+ typedef StreamReader<false> StreamReaderBE;
+#else
+ typedef StreamReader<true> StreamReaderBE;
+ typedef StreamReader<false> StreamReaderLE;
+#endif
+
+// `dynamic` StreamReader. The byte order of the input data is specified in the
+// c'tor. This involves runtime branching and might be a little bit slower.
+typedef StreamReader<true,true> StreamReaderAny;
+
+} // end namespace Assimp
+
+#endif // !! AI_STREAMREADER_H_INCLUDED
diff --git a/thirdparty/assimp/include/assimp/StreamWriter.h b/thirdparty/assimp/include/assimp/StreamWriter.h
new file mode 100644
index 0000000000..c7cf6c0d74
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/StreamWriter.h
@@ -0,0 +1,303 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file Defines the StreamWriter class which writes data to
+ * a binary stream with a well-defined endianness. */
+
+#ifndef AI_STREAMWRITER_H_INCLUDED
+#define AI_STREAMWRITER_H_INCLUDED
+
+#include "ByteSwapper.h"
+#include <assimp/IOStream.hpp>
+
+#include <memory>
+#include <vector>
+
+namespace Assimp {
+
+// --------------------------------------------------------------------------------------------
+/** Wrapper class around IOStream to allow for consistent writing of binary data in both
+ * little and big endian format. Don't attempt to instance the template directly. Use
+ * StreamWriterLE to write to a little-endian stream and StreamWriterBE to write to a
+ * BE stream. Alternatively, there is StreamWriterAny if the endianness of the output
+ * stream is to be determined at runtime.
+ */
+// --------------------------------------------------------------------------------------------
+template <bool SwapEndianess = false, bool RuntimeSwitch = false>
+class StreamWriter
+{
+ enum {
+ INITIAL_CAPACITY = 1024
+ };
+
+public:
+
+ // ---------------------------------------------------------------------
+ /** Construction from a given stream with a well-defined endianness.
+ *
+ * The StreamReader holds a permanent strong reference to the
+ * stream, which is released upon destruction.
+ * @param stream Input stream. The stream is not re-seeked and writing
+ continues at the current position of the stream cursor.
+ * @param le If @c RuntimeSwitch is true: specifies whether the
+ * stream is in little endian byte order. Otherwise the
+ * endianness information is defined by the @c SwapEndianess
+ * template parameter and this parameter is meaningless. */
+ StreamWriter(std::shared_ptr<IOStream> stream, bool le = false)
+ : stream(stream)
+ , le(le)
+ , cursor()
+ {
+ ai_assert(stream);
+ buffer.reserve(INITIAL_CAPACITY);
+ }
+
+ // ---------------------------------------------------------------------
+ StreamWriter(IOStream* stream, bool le = false)
+ : stream(std::shared_ptr<IOStream>(stream))
+ , le(le)
+ , cursor()
+ {
+ ai_assert(stream);
+ buffer.reserve(INITIAL_CAPACITY);
+ }
+
+ // ---------------------------------------------------------------------
+ ~StreamWriter() {
+ stream->Write(buffer.data(), 1, buffer.size());
+ stream->Flush();
+ }
+
+public:
+
+ // ---------------------------------------------------------------------
+ /** Flush the contents of the internal buffer, and the output IOStream */
+ void Flush()
+ {
+ stream->Write(buffer.data(), 1, buffer.size());
+ stream->Flush();
+ buffer.clear();
+ cursor = 0;
+ }
+
+ // ---------------------------------------------------------------------
+ /** Seek to the given offset / origin in the output IOStream.
+ *
+ * Flushes the internal buffer and the output IOStream prior to seeking. */
+ aiReturn Seek(size_t pOffset, aiOrigin pOrigin=aiOrigin_SET)
+ {
+ Flush();
+ return stream->Seek(pOffset, pOrigin);
+ }
+
+ // ---------------------------------------------------------------------
+ /** Tell the current position in the output IOStream.
+ *
+ * First flushes the internal buffer and the output IOStream. */
+ size_t Tell()
+ {
+ Flush();
+ return stream->Tell();
+ }
+
+public:
+
+ // ---------------------------------------------------------------------
+ /** Write a float to the stream */
+ void PutF4(float f)
+ {
+ Put(f);
+ }
+
+ // ---------------------------------------------------------------------
+ /** Write a double to the stream */
+ void PutF8(double d) {
+ Put(d);
+ }
+
+ // ---------------------------------------------------------------------
+ /** Write a signed 16 bit integer to the stream */
+ void PutI2(int16_t n) {
+ Put(n);
+ }
+
+ // ---------------------------------------------------------------------
+ /** Write a signed 8 bit integer to the stream */
+ void PutI1(int8_t n) {
+ Put(n);
+ }
+
+ // ---------------------------------------------------------------------
+ /** Write an signed 32 bit integer to the stream */
+ void PutI4(int32_t n) {
+ Put(n);
+ }
+
+ // ---------------------------------------------------------------------
+ /** Write a signed 64 bit integer to the stream */
+ void PutI8(int64_t n) {
+ Put(n);
+ }
+
+ // ---------------------------------------------------------------------
+ /** Write a unsigned 16 bit integer to the stream */
+ void PutU2(uint16_t n) {
+ Put(n);
+ }
+
+ // ---------------------------------------------------------------------
+ /** Write a unsigned 8 bit integer to the stream */
+ void PutU1(uint8_t n) {
+ Put(n);
+ }
+
+ // ---------------------------------------------------------------------
+ /** Write an unsigned 32 bit integer to the stream */
+ void PutU4(uint32_t n) {
+ Put(n);
+ }
+
+ // ---------------------------------------------------------------------
+ /** Write a unsigned 64 bit integer to the stream */
+ void PutU8(uint64_t n) {
+ Put(n);
+ }
+
+ // ---------------------------------------------------------------------
+ /** Write a single character to the stream */
+ void PutChar(char c) {
+ Put(c);
+ }
+
+ // ---------------------------------------------------------------------
+ /** Write an aiString to the stream */
+ void PutString(const aiString& s)
+ {
+ // as Put(T f) below
+ if (cursor + s.length >= buffer.size()) {
+ buffer.resize(cursor + s.length);
+ }
+ void* dest = &buffer[cursor];
+ ::memcpy(dest, s.C_Str(), s.length);
+ cursor += s.length;
+ }
+
+ // ---------------------------------------------------------------------
+ /** Write a std::string to the stream */
+ void PutString(const std::string& s)
+ {
+ // as Put(T f) below
+ if (cursor + s.size() >= buffer.size()) {
+ buffer.resize(cursor + s.size());
+ }
+ void* dest = &buffer[cursor];
+ ::memcpy(dest, s.c_str(), s.size());
+ cursor += s.size();
+ }
+
+public:
+
+ // ---------------------------------------------------------------------
+ /** overload operator<< and allow chaining of MM ops. */
+ template <typename T>
+ StreamWriter& operator << (T f) {
+ Put(f);
+ return *this;
+ }
+
+ // ---------------------------------------------------------------------
+ std::size_t GetCurrentPos() const {
+ return cursor;
+ }
+
+ // ---------------------------------------------------------------------
+ void SetCurrentPos(std::size_t new_cursor) {
+ cursor = new_cursor;
+ }
+
+ // ---------------------------------------------------------------------
+ /** Generic write method. ByteSwap::Swap(T*) *must* be defined */
+ template <typename T>
+ void Put(T f) {
+ Intern :: Getter<SwapEndianess,T,RuntimeSwitch>() (&f, le);
+
+ if (cursor + sizeof(T) >= buffer.size()) {
+ buffer.resize(cursor + sizeof(T));
+ }
+
+ void* dest = &buffer[cursor];
+
+ // reinterpret_cast + assignment breaks strict aliasing rules
+ // and generally causes trouble on platforms such as ARM that
+ // do not silently ignore alignment faults.
+ ::memcpy(dest, &f, sizeof(T));
+ cursor += sizeof(T);
+ }
+
+private:
+
+ std::shared_ptr<IOStream> stream;
+ bool le;
+
+ std::vector<uint8_t> buffer;
+ std::size_t cursor;
+};
+
+
+// --------------------------------------------------------------------------------------------
+// `static` StreamWriter. Their byte order is fixed and they might be a little bit faster.
+#ifdef AI_BUILD_BIG_ENDIAN
+ typedef StreamWriter<true> StreamWriterLE;
+ typedef StreamWriter<false> StreamWriterBE;
+#else
+ typedef StreamWriter<true> StreamWriterBE;
+ typedef StreamWriter<false> StreamWriterLE;
+#endif
+
+// `dynamic` StreamWriter. The byte order of the input data is specified in the
+// c'tor. This involves runtime branching and might be a little bit slower.
+typedef StreamWriter<true,true> StreamWriterAny;
+
+} // end namespace Assimp
+
+#endif // !! AI_STREAMWriter_H_INCLUDED
diff --git a/thirdparty/assimp/include/assimp/StringComparison.h b/thirdparty/assimp/include/assimp/StringComparison.h
new file mode 100644
index 0000000000..8acef277b9
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/StringComparison.h
@@ -0,0 +1,233 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file Definition of platform independent string workers:
+
+ ASSIMP_itoa10
+ ASSIMP_stricmp
+ ASSIMP_strincmp
+
+ These functions are not consistently available on all platforms,
+ or the provided implementations behave too differently.
+*/
+#ifndef INCLUDED_AI_STRING_WORKERS_H
+#define INCLUDED_AI_STRING_WORKERS_H
+
+#include <assimp/ai_assert.h>
+#include <assimp/defs.h>
+#include "StringComparison.h"
+
+#include <string.h>
+#include <stdint.h>
+#include <string>
+
+namespace Assimp {
+
+// -------------------------------------------------------------------------------
+/** @brief itoa with a fixed base 10
+ * 'itoa' is not consistently available on all platforms so it is quite useful
+ * to have a small replacement function here. No need to use a full sprintf()
+ * if we just want to print a number ...
+ * @param out Output buffer
+ * @param max Maximum number of characters to be written, including '\0'.
+ * This parameter may not be 0.
+ * @param number Number to be written
+ * @return Length of the output string, excluding the '\0'
+ */
+AI_FORCE_INLINE
+unsigned int ASSIMP_itoa10( char* out, unsigned int max, int32_t number) {
+ ai_assert(NULL != out);
+
+ // write the unary minus to indicate we have a negative number
+ unsigned int written = 1u;
+ if (number < 0 && written < max) {
+ *out++ = '-';
+ ++written;
+ number = -number;
+ }
+
+ // We begin with the largest number that is not zero.
+ int32_t cur = 1000000000; // 2147483648
+ bool mustPrint = false;
+ while (written < max) {
+
+ const unsigned int digit = number / cur;
+ if (mustPrint || digit > 0 || 1 == cur) {
+ // print all future zeroe's from now
+ mustPrint = true;
+
+ *out++ = '0'+static_cast<char>(digit);
+
+ ++written;
+ number -= digit*cur;
+ if (1 == cur) {
+ break;
+ }
+ }
+ cur /= 10;
+ }
+
+ // append a terminal zero
+ *out++ = '\0';
+ return written-1;
+}
+
+// -------------------------------------------------------------------------------
+/** @brief itoa with a fixed base 10 (Secure template overload)
+ * The compiler should choose this function if he or she is able to determine the
+ * size of the array automatically.
+ */
+template <size_t length>
+AI_FORCE_INLINE
+unsigned int ASSIMP_itoa10( char(& out)[length], int32_t number) {
+ return ASSIMP_itoa10(out,length,number);
+}
+
+// -------------------------------------------------------------------------------
+/** @brief Helper function to do platform independent string comparison.
+ *
+ * This is required since stricmp() is not consistently available on
+ * all platforms. Some platforms use the '_' prefix, others don't even
+ * have such a function.
+ *
+ * @param s1 First input string
+ * @param s2 Second input string
+ * @return 0 if the given strings are identical
+ */
+AI_FORCE_INLINE
+int ASSIMP_stricmp(const char *s1, const char *s2) {
+ ai_assert( NULL != s1 );
+ ai_assert( NULL != s2 );
+
+#if (defined _MSC_VER)
+
+ return ::_stricmp(s1,s2);
+#elif defined( __GNUC__ )
+
+ return ::strcasecmp(s1,s2);
+#else
+
+ char c1, c2;
+ do {
+ c1 = tolower(*s1++);
+ c2 = tolower(*s2++);
+ }
+ while ( c1 && (c1 == c2) );
+ return c1 - c2;
+#endif
+}
+
+// -------------------------------------------------------------------------------
+/** @brief Case independent comparison of two std::strings
+ *
+ * @param a First string
+ * @param b Second string
+ * @return 0 if a == b
+ */
+AI_FORCE_INLINE
+int ASSIMP_stricmp(const std::string& a, const std::string& b) {
+ int i = (int)b.length()-(int)a.length();
+ return (i ? i : ASSIMP_stricmp(a.c_str(),b.c_str()));
+}
+
+// -------------------------------------------------------------------------------
+/** @brief Helper function to do platform independent string comparison.
+ *
+ * This is required since strincmp() is not consistently available on
+ * all platforms. Some platforms use the '_' prefix, others don't even
+ * have such a function.
+ *
+ * @param s1 First input string
+ * @param s2 Second input string
+ * @param n Macimum number of characters to compare
+ * @return 0 if the given strings are identical
+ */
+AI_FORCE_INLINE
+int ASSIMP_strincmp(const char *s1, const char *s2, unsigned int n) {
+ ai_assert( NULL != s1 );
+ ai_assert( NULL != s2 );
+ if ( !n ) {
+ return 0;
+ }
+
+#if (defined _MSC_VER)
+
+ return ::_strnicmp(s1,s2,n);
+
+#elif defined( __GNUC__ )
+
+ return ::strncasecmp(s1,s2, n);
+
+#else
+ char c1, c2;
+ unsigned int p = 0;
+ do
+ {
+ if (p++ >= n)return 0;
+ c1 = tolower(*s1++);
+ c2 = tolower(*s2++);
+ }
+ while ( c1 && (c1 == c2) );
+
+ return c1 - c2;
+#endif
+}
+
+
+// -------------------------------------------------------------------------------
+/** @brief Evaluates an integer power
+ *
+ * todo: move somewhere where it fits better in than here
+ */
+AI_FORCE_INLINE
+unsigned int integer_pow( unsigned int base, unsigned int power ) {
+ unsigned int res = 1;
+ for ( unsigned int i = 0; i < power; ++i ) {
+ res *= base;
+ }
+
+ return res;
+}
+
+} // end of namespace
+
+#endif // ! AI_STRINGCOMPARISON_H_INC
diff --git a/thirdparty/assimp/include/assimp/StringUtils.h b/thirdparty/assimp/include/assimp/StringUtils.h
new file mode 100644
index 0000000000..d68b7fa479
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/StringUtils.h
@@ -0,0 +1,143 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+#ifndef INCLUDED_AI_STRINGUTILS_H
+#define INCLUDED_AI_STRINGUTILS_H
+
+#include <assimp/defs.h>
+
+#include <sstream>
+#include <stdarg.h>
+#include <cstdlib>
+
+/// @fn ai_snprintf
+/// @brief The portable version of the function snprintf ( C99 standard ), which works on visual studio compilers 2013 and earlier.
+/// @param outBuf The buffer to write in
+/// @param size The buffer size
+/// @param format The format string
+/// @param ap The additional arguments.
+/// @return The number of written characters if the buffer size was big enough. If an encoding error occurs, a negative number is returned.
+#if defined(_MSC_VER) && _MSC_VER < 1900
+
+ AI_FORCE_INLINE
+ int c99_ai_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap) {
+ int count(-1);
+ if (0 != size) {
+ count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap);
+ }
+ if (count == -1) {
+ count = _vscprintf(format, ap);
+ }
+
+ return count;
+ }
+
+ AI_FORCE_INLINE
+ int ai_snprintf(char *outBuf, size_t size, const char *format, ...) {
+ int count;
+ va_list ap;
+
+ va_start(ap, format);
+ count = c99_ai_vsnprintf(outBuf, size, format, ap);
+ va_end(ap);
+
+ return count;
+ }
+
+#else
+# define ai_snprintf snprintf
+#endif
+
+/// @fn to_string
+/// @brief The portable version of to_string ( some gcc-versions on embedded devices are not supporting this).
+/// @param value The value to write into the std::string.
+/// @return The value as a std::string
+template <typename T>
+AI_FORCE_INLINE
+std::string to_string( T value ) {
+ std::ostringstream os;
+ os << value;
+
+ return os.str();
+}
+
+/// @fn ai_strtof
+/// @brief The portable version of strtof.
+/// @param begin The first character of the string.
+/// @param end The last character
+/// @return The float value, 0.0f in cas of an error.
+AI_FORCE_INLINE
+float ai_strtof( const char *begin, const char *end ) {
+ if ( nullptr == begin ) {
+ return 0.0f;
+ }
+ float val( 0.0f );
+ if ( nullptr == end ) {
+ val = static_cast< float >( ::atof( begin ) );
+ } else {
+ std::string::size_type len( end - begin );
+ std::string token( begin, len );
+ val = static_cast< float >( ::atof( token.c_str() ) );
+ }
+
+ return val;
+}
+
+/// @fn DecimalToHexa
+/// @brief The portable to convert a decimal value into a hexadecimal string.
+/// @param toConvert Value to convert
+/// @return The hexadecimal string, is empty in case of an error.
+template<class T>
+AI_FORCE_INLINE
+std::string DecimalToHexa( T toConvert ) {
+ std::string result;
+ std::stringstream ss;
+ ss << std::hex << toConvert;
+ ss >> result;
+
+ for ( size_t i = 0; i < result.size(); ++i ) {
+ result[ i ] = toupper( result[ i ] );
+ }
+
+ return result;
+}
+
+#endif // INCLUDED_AI_STRINGUTILS_H
diff --git a/thirdparty/assimp/include/assimp/Subdivision.h b/thirdparty/assimp/include/assimp/Subdivision.h
new file mode 100644
index 0000000000..43feb73b30
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/Subdivision.h
@@ -0,0 +1,131 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file Defines a helper class to evaluate subdivision surfaces.*/
+#pragma once
+#ifndef AI_SUBDISIVION_H_INC
+#define AI_SUBDISIVION_H_INC
+
+#include <cstddef>
+#include <assimp/types.h>
+
+struct aiMesh;
+
+namespace Assimp {
+
+// ------------------------------------------------------------------------------
+/** Helper class to evaluate subdivision surfaces. Different algorithms
+ * are provided for choice. */
+// ------------------------------------------------------------------------------
+class ASSIMP_API Subdivider {
+public:
+
+ /** Enumerates all supported subvidision algorithms */
+ enum Algorithm {
+ CATMULL_CLARKE = 0x1
+ };
+
+ virtual ~Subdivider();
+
+ // ---------------------------------------------------------------
+ /** Create a subdivider of a specific type
+ *
+ * @param algo Algorithm to be used for subdivision
+ * @return Subdivider instance. */
+ static Subdivider* Create (Algorithm algo);
+
+ // ---------------------------------------------------------------
+ /** Subdivide a mesh using the selected algorithm
+ *
+ * @param mesh First mesh to be subdivided. Must be in verbose
+ * format.
+ * @param out Receives the output mesh, allocated by me.
+ * @param num Number of subdivisions to perform.
+ * @param discard_input If true is passed, the input mesh is
+ * deleted after the subdivision is complete. This can
+ * improve performance because it allows the optimization
+ * to reuse the existing mesh for intermediate results.
+ * @pre out!=mesh*/
+ virtual void Subdivide ( aiMesh* mesh,
+ aiMesh*& out, unsigned int num,
+ bool discard_input = false) = 0;
+
+ // ---------------------------------------------------------------
+ /** Subdivide multiple meshes using the selected algorithm. This
+ * avoids erroneous smoothing on objects consisting of multiple
+ * per-material meshes. Usually, most 3d modellers smooth on a
+ * per-object base, regardless the materials assigned to the
+ * meshes.
+ *
+ * @param smesh Array of meshes to be subdivided. Must be in
+ * verbose format.
+ * @param nmesh Number of meshes in smesh.
+ * @param out Receives the output meshes. The array must be
+ * sufficiently large (at least @c nmesh elements) and may not
+ * overlap the input array. Output meshes map one-to-one to
+ * their corresponding input meshes. The meshes are allocated
+ * by the function.
+ * @param discard_input If true is passed, input meshes are
+ * deleted after the subdivision is complete. This can
+ * improve performance because it allows the optimization
+ * of reusing existing meshes for intermediate results.
+ * @param num Number of subdivisions to perform.
+ * @pre nmesh != 0, smesh and out may not overlap*/
+ virtual void Subdivide (
+ aiMesh** smesh,
+ size_t nmesh,
+ aiMesh** out,
+ unsigned int num,
+ bool discard_input = false) = 0;
+
+};
+
+inline
+Subdivider::~Subdivider() {
+ // empty
+}
+
+} // end namespace Assimp
+
+
+#endif // !! AI_SUBDISIVION_H_INC
+
diff --git a/thirdparty/assimp/include/assimp/TinyFormatter.h b/thirdparty/assimp/include/assimp/TinyFormatter.h
new file mode 100644
index 0000000000..1226b482e6
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/TinyFormatter.h
@@ -0,0 +1,166 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file TinyFormatter.h
+ * @brief Utility to format log messages more easily. Introduced
+ * to get rid of the boost::format dependency. Much slinker,
+ * basically just extends stringstream.
+ */
+#ifndef INCLUDED_TINY_FORMATTER_H
+#define INCLUDED_TINY_FORMATTER_H
+
+#include <sstream>
+
+namespace Assimp {
+namespace Formatter {
+
+// ------------------------------------------------------------------------------------------------
+/** stringstream utility. Usage:
+ * @code
+ * void writelog(const std::string&s);
+ * void writelog(const std::wstring&s);
+ * ...
+ * writelog(format()<< "hi! this is a number: " << 4);
+ * writelog(wformat()<< L"hi! this is a number: " << 4);
+ *
+ * @endcode */
+template < typename T,
+ typename CharTraits = std::char_traits<T>,
+ typename Allocator = std::allocator<T>
+>
+class basic_formatter
+{
+
+public:
+
+ typedef class std::basic_string<
+ T,CharTraits,Allocator
+ > string;
+
+ typedef class std::basic_ostringstream<
+ T,CharTraits,Allocator
+ > stringstream;
+
+public:
+
+ basic_formatter() {}
+
+ /* Allow basic_formatter<T>'s to be used almost interchangeably
+ * with std::(w)string or const (w)char* arguments because the
+ * conversion c'tor is called implicitly. */
+ template <typename TT>
+ basic_formatter(const TT& sin) {
+ underlying << sin;
+ }
+
+
+ // The problem described here:
+ // https://sourceforge.net/tracker/?func=detail&atid=1067632&aid=3358562&group_id=226462
+ // can also cause trouble here. Apparently, older gcc versions sometimes copy temporaries
+ // being bound to const ref& function parameters. Copying streams is not permitted, though.
+ // This workaround avoids this by manually specifying a copy ctor.
+#if !defined(__GNUC__) || !defined(__APPLE__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
+ explicit basic_formatter(const basic_formatter& other) {
+ underlying << (string)other;
+ }
+#endif
+
+
+public:
+
+ operator string () const {
+ return underlying.str();
+ }
+
+
+ /* note - this is declared const because binding temporaries does only
+ * work for const references, so many function prototypes will
+ * include const basic_formatter<T>& s but might still want to
+ * modify the formatted string without the need for a full copy.*/
+ template <typename TToken>
+ const basic_formatter& operator << (const TToken& s) const {
+ underlying << s;
+ return *this;
+ }
+
+ template <typename TToken>
+ basic_formatter& operator << (const TToken& s) {
+ underlying << s;
+ return *this;
+ }
+
+
+ // comma operator overloaded as well, choose your preferred way.
+ template <typename TToken>
+ const basic_formatter& operator, (const TToken& s) const {
+ underlying << s;
+ return *this;
+ }
+
+ template <typename TToken>
+ basic_formatter& operator, (const TToken& s) {
+ underlying << s;
+ return *this;
+ }
+
+ // Fix for MSVC8
+ // See https://sourceforge.net/projects/assimp/forums/forum/817654/topic/4372824
+ template <typename TToken>
+ basic_formatter& operator, (TToken& s) {
+ underlying << s;
+ return *this;
+ }
+
+
+private:
+ mutable stringstream underlying;
+};
+
+
+typedef basic_formatter< char > format;
+typedef basic_formatter< wchar_t > wformat;
+
+} // ! namespace Formatter
+
+} // ! namespace Assimp
+
+#endif
diff --git a/thirdparty/assimp/include/assimp/Vertex.h b/thirdparty/assimp/include/assimp/Vertex.h
new file mode 100644
index 0000000000..2a7f0256ad
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/Vertex.h
@@ -0,0 +1,348 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+/** @file Defines a helper class to represent an interleaved vertex
+ along with arithmetic operations to support vertex operations
+ such as subdivision, smoothing etc.
+
+ While the code is kept as general as possible, arithmetic operations
+ that are not currently well-defined (and would cause compile errors
+ due to missing operators in the math library), are commented.
+ */
+#ifndef AI_VERTEX_H_INC
+#define AI_VERTEX_H_INC
+
+#include <assimp/vector3.h>
+#include <assimp/mesh.h>
+#include <assimp/ai_assert.h>
+#include <functional>
+
+namespace Assimp {
+
+ ///////////////////////////////////////////////////////////////////////////
+ // std::plus-family operates on operands with identical types - we need to
+ // support all the (vectype op float) combinations in vector maths.
+ // Providing T(float) would open the way to endless implicit conversions.
+ ///////////////////////////////////////////////////////////////////////////
+ namespace Intern {
+ template <typename T0, typename T1, typename TRES = T0> struct plus {
+ TRES operator() (const T0& t0, const T1& t1) const {
+ return t0+t1;
+ }
+ };
+ template <typename T0, typename T1, typename TRES = T0> struct minus {
+ TRES operator() (const T0& t0, const T1& t1) const {
+ return t0-t1;
+ }
+ };
+ template <typename T0, typename T1, typename TRES = T0> struct multiplies {
+ TRES operator() (const T0& t0, const T1& t1) const {
+ return t0*t1;
+ }
+ };
+ template <typename T0, typename T1, typename TRES = T0> struct divides {
+ TRES operator() (const T0& t0, const T1& t1) const {
+ return t0/t1;
+ }
+ };
+ }
+
+// ------------------------------------------------------------------------------------------------
+/** Intermediate description a vertex with all possible components. Defines a full set of
+ * operators, so you may use such a 'Vertex' in basic arithmetics. All operators are applied
+ * to *all* vertex components equally. This is useful for stuff like interpolation
+ * or subdivision, but won't work if special handling is required for some vertex components. */
+// ------------------------------------------------------------------------------------------------
+class Vertex
+{
+ friend Vertex operator + (const Vertex&,const Vertex&);
+ friend Vertex operator - (const Vertex&,const Vertex&);
+
+// friend Vertex operator + (const Vertex&,ai_real);
+// friend Vertex operator - (const Vertex&,ai_real);
+ friend Vertex operator * (const Vertex&,ai_real);
+ friend Vertex operator / (const Vertex&,ai_real);
+
+// friend Vertex operator + (ai_real, const Vertex&);
+// friend Vertex operator - (ai_real, const Vertex&);
+ friend Vertex operator * (ai_real, const Vertex&);
+// friend Vertex operator / (ai_real, const Vertex&);
+
+public:
+
+ Vertex() {}
+
+ // ----------------------------------------------------------------------------
+ /** Extract a particular vertex from a mesh and interleave all components */
+ explicit Vertex(const aiMesh* msh, unsigned int idx) {
+ ai_assert(idx < msh->mNumVertices);
+ position = msh->mVertices[idx];
+
+ if (msh->HasNormals()) {
+ normal = msh->mNormals[idx];
+ }
+
+ if (msh->HasTangentsAndBitangents()) {
+ tangent = msh->mTangents[idx];
+ bitangent = msh->mBitangents[idx];
+ }
+
+ for (unsigned int i = 0; msh->HasTextureCoords(i); ++i) {
+ texcoords[i] = msh->mTextureCoords[i][idx];
+ }
+
+ for (unsigned int i = 0; msh->HasVertexColors(i); ++i) {
+ colors[i] = msh->mColors[i][idx];
+ }
+ }
+
+ // ----------------------------------------------------------------------------
+ /** Extract a particular vertex from a anim mesh and interleave all components */
+ explicit Vertex(const aiAnimMesh* msh, unsigned int idx) {
+ ai_assert(idx < msh->mNumVertices);
+ position = msh->mVertices[idx];
+
+ if (msh->HasNormals()) {
+ normal = msh->mNormals[idx];
+ }
+
+ if (msh->HasTangentsAndBitangents()) {
+ tangent = msh->mTangents[idx];
+ bitangent = msh->mBitangents[idx];
+ }
+
+ for (unsigned int i = 0; msh->HasTextureCoords(i); ++i) {
+ texcoords[i] = msh->mTextureCoords[i][idx];
+ }
+
+ for (unsigned int i = 0; msh->HasVertexColors(i); ++i) {
+ colors[i] = msh->mColors[i][idx];
+ }
+ }
+
+public:
+
+ Vertex& operator += (const Vertex& v) {
+ *this = *this+v;
+ return *this;
+ }
+
+ Vertex& operator -= (const Vertex& v) {
+ *this = *this-v;
+ return *this;
+ }
+
+
+/*
+ Vertex& operator += (ai_real v) {
+ *this = *this+v;
+ return *this;
+ }
+
+ Vertex& operator -= (ai_real v) {
+ *this = *this-v;
+ return *this;
+ }
+*/
+ Vertex& operator *= (ai_real v) {
+ *this = *this*v;
+ return *this;
+ }
+
+ Vertex& operator /= (ai_real v) {
+ *this = *this/v;
+ return *this;
+ }
+
+public:
+
+ // ----------------------------------------------------------------------------
+ /** Convert back to non-interleaved storage */
+ void SortBack(aiMesh* out, unsigned int idx) const {
+
+ ai_assert(idx<out->mNumVertices);
+ out->mVertices[idx] = position;
+
+ if (out->HasNormals()) {
+ out->mNormals[idx] = normal;
+ }
+
+ if (out->HasTangentsAndBitangents()) {
+ out->mTangents[idx] = tangent;
+ out->mBitangents[idx] = bitangent;
+ }
+
+ for(unsigned int i = 0; out->HasTextureCoords(i); ++i) {
+ out->mTextureCoords[i][idx] = texcoords[i];
+ }
+
+ for(unsigned int i = 0; out->HasVertexColors(i); ++i) {
+ out->mColors[i][idx] = colors[i];
+ }
+ }
+
+private:
+
+ // ----------------------------------------------------------------------------
+ /** Construct from two operands and a binary operation to combine them */
+ template <template <typename t> class op> static Vertex BinaryOp(const Vertex& v0, const Vertex& v1) {
+ // this is a heavy task for the compiler to optimize ... *pray*
+
+ Vertex res;
+ res.position = op<aiVector3D>()(v0.position,v1.position);
+ res.normal = op<aiVector3D>()(v0.normal,v1.normal);
+ res.tangent = op<aiVector3D>()(v0.tangent,v1.tangent);
+ res.bitangent = op<aiVector3D>()(v0.bitangent,v1.bitangent);
+
+ for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
+ res.texcoords[i] = op<aiVector3D>()(v0.texcoords[i],v1.texcoords[i]);
+ }
+ for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) {
+ res.colors[i] = op<aiColor4D>()(v0.colors[i],v1.colors[i]);
+ }
+ return res;
+ }
+
+ // ----------------------------------------------------------------------------
+ /** This time binary arithmetics of v0 with a floating-point number */
+ template <template <typename, typename, typename> class op> static Vertex BinaryOp(const Vertex& v0, ai_real f) {
+ // this is a heavy task for the compiler to optimize ... *pray*
+
+ Vertex res;
+ res.position = op<aiVector3D,ai_real,aiVector3D>()(v0.position,f);
+ res.normal = op<aiVector3D,ai_real,aiVector3D>()(v0.normal,f);
+ res.tangent = op<aiVector3D,ai_real,aiVector3D>()(v0.tangent,f);
+ res.bitangent = op<aiVector3D,ai_real,aiVector3D>()(v0.bitangent,f);
+
+ for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
+ res.texcoords[i] = op<aiVector3D,ai_real,aiVector3D>()(v0.texcoords[i],f);
+ }
+ for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) {
+ res.colors[i] = op<aiColor4D,ai_real,aiColor4D>()(v0.colors[i],f);
+ }
+ return res;
+ }
+
+ // ----------------------------------------------------------------------------
+ /** This time binary arithmetics of v0 with a floating-point number */
+ template <template <typename, typename, typename> class op> static Vertex BinaryOp(ai_real f, const Vertex& v0) {
+ // this is a heavy task for the compiler to optimize ... *pray*
+
+ Vertex res;
+ res.position = op<ai_real,aiVector3D,aiVector3D>()(f,v0.position);
+ res.normal = op<ai_real,aiVector3D,aiVector3D>()(f,v0.normal);
+ res.tangent = op<ai_real,aiVector3D,aiVector3D>()(f,v0.tangent);
+ res.bitangent = op<ai_real,aiVector3D,aiVector3D>()(f,v0.bitangent);
+
+ for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
+ res.texcoords[i] = op<ai_real,aiVector3D,aiVector3D>()(f,v0.texcoords[i]);
+ }
+ for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) {
+ res.colors[i] = op<ai_real,aiColor4D,aiColor4D>()(f,v0.colors[i]);
+ }
+ return res;
+ }
+
+public:
+
+ aiVector3D position;
+ aiVector3D normal;
+ aiVector3D tangent, bitangent;
+
+ aiVector3D texcoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
+ aiColor4D colors[AI_MAX_NUMBER_OF_COLOR_SETS];
+};
+
+
+
+// ------------------------------------------------------------------------------------------------
+AI_FORCE_INLINE Vertex operator + (const Vertex& v0,const Vertex& v1) {
+ return Vertex::BinaryOp<std::plus>(v0,v1);
+}
+
+AI_FORCE_INLINE Vertex operator - (const Vertex& v0,const Vertex& v1) {
+ return Vertex::BinaryOp<std::minus>(v0,v1);
+}
+
+
+// ------------------------------------------------------------------------------------------------
+/*
+AI_FORCE_INLINE Vertex operator + (const Vertex& v0,ai_real f) {
+ return Vertex::BinaryOp<Intern::plus>(v0,f);
+}
+
+AI_FORCE_INLINE Vertex operator - (const Vertex& v0,ai_real f) {
+ return Vertex::BinaryOp<Intern::minus>(v0,f);
+}
+
+*/
+
+AI_FORCE_INLINE Vertex operator * (const Vertex& v0,ai_real f) {
+ return Vertex::BinaryOp<Intern::multiplies>(v0,f);
+}
+
+AI_FORCE_INLINE Vertex operator / (const Vertex& v0,ai_real f) {
+ return Vertex::BinaryOp<Intern::multiplies>(v0,1.f/f);
+}
+
+// ------------------------------------------------------------------------------------------------
+/*
+AI_FORCE_INLINE Vertex operator + (ai_real f,const Vertex& v0) {
+ return Vertex::BinaryOp<Intern::plus>(f,v0);
+}
+
+AI_FORCE_INLINE Vertex operator - (ai_real f,const Vertex& v0) {
+ return Vertex::BinaryOp<Intern::minus>(f,v0);
+}
+*/
+
+AI_FORCE_INLINE Vertex operator * (ai_real f,const Vertex& v0) {
+ return Vertex::BinaryOp<Intern::multiplies>(f,v0);
+}
+
+/*
+AI_FORCE_INLINE Vertex operator / (ai_real f,const Vertex& v0) {
+ return Vertex::BinaryOp<Intern::divides>(f,v0);
+}
+*/
+
+}
+#endif
diff --git a/thirdparty/assimp/include/assimp/XMLTools.h b/thirdparty/assimp/include/assimp/XMLTools.h
new file mode 100644
index 0000000000..b0d3276873
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/XMLTools.h
@@ -0,0 +1,83 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+#ifndef INCLUDED_ASSIMP_XML_TOOLS_H
+#define INCLUDED_ASSIMP_XML_TOOLS_H
+
+#include <string>
+
+namespace Assimp {
+ // XML escape the 5 XML special characters (",',<,> and &) in |data|
+ // Based on http://stackoverflow.com/questions/5665231
+ std::string XMLEscape(const std::string& data) {
+ std::string buffer;
+
+ const size_t size = data.size();
+ buffer.reserve(size + size / 8);
+ for(size_t i = 0; i < size; ++i) {
+ const char c = data[i];
+ switch(c) {
+ case '&' :
+ buffer.append("&amp;");
+ break;
+ case '\"':
+ buffer.append("&quot;");
+ break;
+ case '\'':
+ buffer.append("&apos;");
+ break;
+ case '<' :
+ buffer.append("&lt;");
+ break;
+ case '>' :
+ buffer.append("&gt;");
+ break;
+ default:
+ buffer.append(&c, 1);
+ break;
+ }
+ }
+ return buffer;
+ }
+}
+
+#endif // INCLUDED_ASSIMP_XML_TOOLS_H
diff --git a/thirdparty/assimp/include/assimp/ai_assert.h b/thirdparty/assimp/include/assimp/ai_assert.h
new file mode 100644
index 0000000000..e5de5d3f36
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/ai_assert.h
@@ -0,0 +1,57 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+#pragma once
+#ifndef AI_ASSERT_H_INC
+#define AI_ASSERT_H_INC
+
+#ifdef ASSIMP_BUILD_DEBUG
+# include <assert.h>
+# define ai_assert(expression) assert( expression )
+# define ai_assert_entry() assert( false )
+#else
+# define ai_assert(expression)
+# define ai_assert_entry()
+#endif // ASSIMP_BUILD_DEBUG
+
+#endif // AI_ASSERT_H_INC
+
diff --git a/thirdparty/assimp/include/assimp/anim.h b/thirdparty/assimp/include/assimp/anim.h
new file mode 100644
index 0000000000..02e92739ec
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/anim.h
@@ -0,0 +1,577 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/**
+ * @file anim.h
+ * @brief Defines the data structures in which the imported animations
+ * are returned.
+ */
+#pragma once
+#ifndef AI_ANIM_H_INC
+#define AI_ANIM_H_INC
+
+#include <assimp/types.h>
+#include <assimp/quaternion.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// ---------------------------------------------------------------------------
+/** A time-value pair specifying a certain 3D vector for the given time. */
+struct aiVectorKey
+{
+ /** The time of this key */
+ double mTime;
+
+ /** The value of this key */
+ C_STRUCT aiVector3D mValue;
+
+#ifdef __cplusplus
+
+ /// @brief The default constructor.
+ aiVectorKey() AI_NO_EXCEPT
+ : mTime( 0.0 )
+ , mValue() {
+ // empty
+ }
+
+ /// @brief Construction from a given time and key value.
+
+ aiVectorKey(double time, const aiVector3D& value)
+ : mTime( time )
+ , mValue( value ) {
+ // empty
+ }
+
+ typedef aiVector3D elem_type;
+
+ // Comparison operators. For use with std::find();
+ bool operator == (const aiVectorKey& rhs) const {
+ return rhs.mValue == this->mValue;
+ }
+ bool operator != (const aiVectorKey& rhs ) const {
+ return rhs.mValue != this->mValue;
+ }
+
+ // Relational operators. For use with std::sort();
+ bool operator < (const aiVectorKey& rhs ) const {
+ return mTime < rhs.mTime;
+ }
+ bool operator > (const aiVectorKey& rhs ) const {
+ return mTime > rhs.mTime;
+ }
+#endif // __cplusplus
+};
+
+// ---------------------------------------------------------------------------
+/** A time-value pair specifying a rotation for the given time.
+ * Rotations are expressed with quaternions. */
+struct aiQuatKey
+{
+ /** The time of this key */
+ double mTime;
+
+ /** The value of this key */
+ C_STRUCT aiQuaternion mValue;
+
+#ifdef __cplusplus
+ aiQuatKey() AI_NO_EXCEPT
+ : mTime( 0.0 )
+ , mValue() {
+ // empty
+ }
+
+ /** Construction from a given time and key value */
+ aiQuatKey(double time, const aiQuaternion& value)
+ : mTime (time)
+ , mValue (value)
+ {}
+
+ typedef aiQuaternion elem_type;
+
+ // Comparison operators. For use with std::find();
+ bool operator == (const aiQuatKey& rhs ) const {
+ return rhs.mValue == this->mValue;
+ }
+ bool operator != (const aiQuatKey& rhs ) const {
+ return rhs.mValue != this->mValue;
+ }
+
+ // Relational operators. For use with std::sort();
+ bool operator < (const aiQuatKey& rhs ) const {
+ return mTime < rhs.mTime;
+ }
+ bool operator > (const aiQuatKey& rhs ) const {
+ return mTime > rhs.mTime;
+ }
+#endif
+};
+
+// ---------------------------------------------------------------------------
+/** Binds a anim-mesh to a specific point in time. */
+struct aiMeshKey
+{
+ /** The time of this key */
+ double mTime;
+
+ /** Index into the aiMesh::mAnimMeshes array of the
+ * mesh corresponding to the #aiMeshAnim hosting this
+ * key frame. The referenced anim mesh is evaluated
+ * according to the rules defined in the docs for #aiAnimMesh.*/
+ unsigned int mValue;
+
+#ifdef __cplusplus
+
+ aiMeshKey() AI_NO_EXCEPT
+ : mTime(0.0)
+ , mValue(0)
+ {
+ }
+
+ /** Construction from a given time and key value */
+ aiMeshKey(double time, const unsigned int value)
+ : mTime (time)
+ , mValue (value)
+ {}
+
+ typedef unsigned int elem_type;
+
+ // Comparison operators. For use with std::find();
+ bool operator == (const aiMeshKey& o) const {
+ return o.mValue == this->mValue;
+ }
+ bool operator != (const aiMeshKey& o) const {
+ return o.mValue != this->mValue;
+ }
+
+ // Relational operators. For use with std::sort();
+ bool operator < (const aiMeshKey& o) const {
+ return mTime < o.mTime;
+ }
+ bool operator > (const aiMeshKey& o) const {
+ return mTime > o.mTime;
+ }
+
+#endif
+};
+
+// ---------------------------------------------------------------------------
+/** Binds a morph anim mesh to a specific point in time. */
+struct aiMeshMorphKey
+{
+ /** The time of this key */
+ double mTime;
+
+ /** The values and weights at the time of this key */
+ unsigned int *mValues;
+ double *mWeights;
+
+ /** The number of values and weights */
+ unsigned int mNumValuesAndWeights;
+#ifdef __cplusplus
+ aiMeshMorphKey() AI_NO_EXCEPT
+ : mTime(0.0)
+ , mValues(nullptr)
+ , mWeights(nullptr)
+ , mNumValuesAndWeights(0)
+ {
+
+ }
+
+ ~aiMeshMorphKey()
+ {
+ if (mNumValuesAndWeights && mValues && mWeights) {
+ delete [] mValues;
+ delete [] mWeights;
+ }
+ }
+#endif
+};
+
+// ---------------------------------------------------------------------------
+/** Defines how an animation channel behaves outside the defined time
+ * range. This corresponds to aiNodeAnim::mPreState and
+ * aiNodeAnim::mPostState.*/
+enum aiAnimBehaviour
+{
+ /** The value from the default node transformation is taken*/
+ aiAnimBehaviour_DEFAULT = 0x0,
+
+ /** The nearest key value is used without interpolation */
+ aiAnimBehaviour_CONSTANT = 0x1,
+
+ /** The value of the nearest two keys is linearly
+ * extrapolated for the current time value.*/
+ aiAnimBehaviour_LINEAR = 0x2,
+
+ /** The animation is repeated.
+ *
+ * If the animation key go from n to m and the current
+ * time is t, use the value at (t-n) % (|m-n|).*/
+ aiAnimBehaviour_REPEAT = 0x3,
+
+ /** This value is not used, it is just here to force the
+ * the compiler to map this enum to a 32 Bit integer */
+#ifndef SWIG
+ _aiAnimBehaviour_Force32Bit = INT_MAX
+#endif
+};
+
+// ---------------------------------------------------------------------------
+/** Describes the animation of a single node. The name specifies the
+ * bone/node which is affected by this animation channel. The keyframes
+ * are given in three separate series of values, one each for position,
+ * rotation and scaling. The transformation matrix computed from these
+ * values replaces the node's original transformation matrix at a
+ * specific time.
+ * This means all keys are absolute and not relative to the bone default pose.
+ * The order in which the transformations are applied is
+ * - as usual - scaling, rotation, translation.
+ *
+ * @note All keys are returned in their correct, chronological order.
+ * Duplicate keys don't pass the validation step. Most likely there
+ * will be no negative time values, but they are not forbidden also ( so
+ * implementations need to cope with them! ) */
+struct aiNodeAnim {
+ /** The name of the node affected by this animation. The node
+ * must exist and it must be unique.*/
+ C_STRUCT aiString mNodeName;
+
+ /** The number of position keys */
+ unsigned int mNumPositionKeys;
+
+ /** The position keys of this animation channel. Positions are
+ * specified as 3D vector. The array is mNumPositionKeys in size.
+ *
+ * If there are position keys, there will also be at least one
+ * scaling and one rotation key.*/
+ C_STRUCT aiVectorKey* mPositionKeys;
+
+ /** The number of rotation keys */
+ unsigned int mNumRotationKeys;
+
+ /** The rotation keys of this animation channel. Rotations are
+ * given as quaternions, which are 4D vectors. The array is
+ * mNumRotationKeys in size.
+ *
+ * If there are rotation keys, there will also be at least one
+ * scaling and one position key. */
+ C_STRUCT aiQuatKey* mRotationKeys;
+
+ /** The number of scaling keys */
+ unsigned int mNumScalingKeys;
+
+ /** The scaling keys of this animation channel. Scalings are
+ * specified as 3D vector. The array is mNumScalingKeys in size.
+ *
+ * If there are scaling keys, there will also be at least one
+ * position and one rotation key.*/
+ C_STRUCT aiVectorKey* mScalingKeys;
+
+ /** Defines how the animation behaves before the first
+ * key is encountered.
+ *
+ * The default value is aiAnimBehaviour_DEFAULT (the original
+ * transformation matrix of the affected node is used).*/
+ C_ENUM aiAnimBehaviour mPreState;
+
+ /** Defines how the animation behaves after the last
+ * key was processed.
+ *
+ * The default value is aiAnimBehaviour_DEFAULT (the original
+ * transformation matrix of the affected node is taken).*/
+ C_ENUM aiAnimBehaviour mPostState;
+
+#ifdef __cplusplus
+ aiNodeAnim() AI_NO_EXCEPT
+ : mNumPositionKeys( 0 )
+ , mPositionKeys( nullptr )
+ , mNumRotationKeys( 0 )
+ , mRotationKeys( nullptr )
+ , mNumScalingKeys( 0 )
+ , mScalingKeys( nullptr )
+ , mPreState( aiAnimBehaviour_DEFAULT )
+ , mPostState( aiAnimBehaviour_DEFAULT ) {
+ // empty
+ }
+
+ ~aiNodeAnim() {
+ delete [] mPositionKeys;
+ delete [] mRotationKeys;
+ delete [] mScalingKeys;
+ }
+#endif // __cplusplus
+};
+
+// ---------------------------------------------------------------------------
+/** Describes vertex-based animations for a single mesh or a group of
+ * meshes. Meshes carry the animation data for each frame in their
+ * aiMesh::mAnimMeshes array. The purpose of aiMeshAnim is to
+ * define keyframes linking each mesh attachment to a particular
+ * point in time. */
+struct aiMeshAnim
+{
+ /** Name of the mesh to be animated. An empty string is not allowed,
+ * animated meshes need to be named (not necessarily uniquely,
+ * the name can basically serve as wild-card to select a group
+ * of meshes with similar animation setup)*/
+ C_STRUCT aiString mName;
+
+ /** Size of the #mKeys array. Must be 1, at least. */
+ unsigned int mNumKeys;
+
+ /** Key frames of the animation. May not be NULL. */
+ C_STRUCT aiMeshKey* mKeys;
+
+#ifdef __cplusplus
+
+ aiMeshAnim() AI_NO_EXCEPT
+ : mNumKeys()
+ , mKeys()
+ {}
+
+ ~aiMeshAnim()
+ {
+ delete[] mKeys;
+ }
+
+#endif
+};
+
+// ---------------------------------------------------------------------------
+/** Describes a morphing animation of a given mesh. */
+struct aiMeshMorphAnim
+{
+ /** Name of the mesh to be animated. An empty string is not allowed,
+ * animated meshes need to be named (not necessarily uniquely,
+ * the name can basically serve as wildcard to select a group
+ * of meshes with similar animation setup)*/
+ C_STRUCT aiString mName;
+
+ /** Size of the #mKeys array. Must be 1, at least. */
+ unsigned int mNumKeys;
+
+ /** Key frames of the animation. May not be NULL. */
+ C_STRUCT aiMeshMorphKey* mKeys;
+
+#ifdef __cplusplus
+
+ aiMeshMorphAnim() AI_NO_EXCEPT
+ : mNumKeys()
+ , mKeys()
+ {}
+
+ ~aiMeshMorphAnim()
+ {
+ delete[] mKeys;
+ }
+
+#endif
+};
+
+// ---------------------------------------------------------------------------
+/** An animation consists of key-frame data for a number of nodes. For
+ * each node affected by the animation a separate series of data is given.*/
+struct aiAnimation {
+ /** The name of the animation. If the modeling package this data was
+ * exported from does support only a single animation channel, this
+ * name is usually empty (length is zero). */
+ C_STRUCT aiString mName;
+
+ /** Duration of the animation in ticks. */
+ double mDuration;
+
+ /** Ticks per second. 0 if not specified in the imported file */
+ double mTicksPerSecond;
+
+ /** The number of bone animation channels. Each channel affects
+ * a single node. */
+ unsigned int mNumChannels;
+
+ /** The node animation channels. Each channel affects a single node.
+ * The array is mNumChannels in size. */
+ C_STRUCT aiNodeAnim** mChannels;
+
+
+ /** The number of mesh animation channels. Each channel affects
+ * a single mesh and defines vertex-based animation. */
+ unsigned int mNumMeshChannels;
+
+ /** The mesh animation channels. Each channel affects a single mesh.
+ * The array is mNumMeshChannels in size. */
+ C_STRUCT aiMeshAnim** mMeshChannels;
+
+ /** The number of mesh animation channels. Each channel affects
+ * a single mesh and defines morphing animation. */
+ unsigned int mNumMorphMeshChannels;
+
+ /** The morph mesh animation channels. Each channel affects a single mesh.
+ * The array is mNumMorphMeshChannels in size. */
+ C_STRUCT aiMeshMorphAnim **mMorphMeshChannels;
+
+#ifdef __cplusplus
+ aiAnimation() AI_NO_EXCEPT
+ : mDuration(-1.)
+ , mTicksPerSecond(0.)
+ , mNumChannels(0)
+ , mChannels(nullptr)
+ , mNumMeshChannels(0)
+ , mMeshChannels(nullptr)
+ , mNumMorphMeshChannels(0)
+ , mMorphMeshChannels(nullptr) {
+ // empty
+ }
+
+ ~aiAnimation() {
+ // DO NOT REMOVE THIS ADDITIONAL CHECK
+ if ( mNumChannels && mChannels ) {
+ for( unsigned int a = 0; a < mNumChannels; a++) {
+ delete mChannels[ a ];
+ }
+
+ delete [] mChannels;
+ }
+ if (mNumMeshChannels && mMeshChannels) {
+ for( unsigned int a = 0; a < mNumMeshChannels; a++) {
+ delete mMeshChannels[a];
+ }
+
+ delete [] mMeshChannels;
+ }
+ if (mNumMorphMeshChannels && mMorphMeshChannels) {
+ for( unsigned int a = 0; a < mNumMorphMeshChannels; a++) {
+ delete mMorphMeshChannels[a];
+ }
+
+ delete [] mMorphMeshChannels;
+ }
+ }
+#endif // __cplusplus
+};
+
+#ifdef __cplusplus
+
+}
+
+/// @brief Some C++ utilities for inter- and extrapolation
+namespace Assimp {
+
+// ---------------------------------------------------------------------------
+/**
+ * @brief CPP-API: Utility class to simplify interpolations of various data types.
+ *
+ * The type of interpolation is chosen automatically depending on the
+ * types of the arguments.
+ */
+template <typename T>
+struct Interpolator
+{
+ // ------------------------------------------------------------------
+ /** @brief Get the result of the interpolation between a,b.
+ *
+ * The interpolation algorithm depends on the type of the operands.
+ * aiQuaternion's and aiQuatKey's SLERP, the rest does a simple
+ * linear interpolation. */
+ void operator () (T& out,const T& a, const T& b, ai_real d) const {
+ out = a + (b-a)*d;
+ }
+}; // ! Interpolator <T>
+
+//! @cond Never
+
+template <>
+struct Interpolator <aiQuaternion> {
+ void operator () (aiQuaternion& out,const aiQuaternion& a,
+ const aiQuaternion& b, ai_real d) const
+ {
+ aiQuaternion::Interpolate(out,a,b,d);
+ }
+}; // ! Interpolator <aiQuaternion>
+
+template <>
+struct Interpolator <unsigned int> {
+ void operator () (unsigned int& out,unsigned int a,
+ unsigned int b, ai_real d) const
+ {
+ out = d>0.5f ? b : a;
+ }
+}; // ! Interpolator <aiQuaternion>
+
+template <>
+struct Interpolator<aiVectorKey> {
+ void operator () (aiVector3D& out,const aiVectorKey& a,
+ const aiVectorKey& b, ai_real d) const
+ {
+ Interpolator<aiVector3D> ipl;
+ ipl(out,a.mValue,b.mValue,d);
+ }
+}; // ! Interpolator <aiVectorKey>
+
+template <>
+struct Interpolator<aiQuatKey> {
+ void operator () (aiQuaternion& out, const aiQuatKey& a,
+ const aiQuatKey& b, ai_real d) const
+ {
+ Interpolator<aiQuaternion> ipl;
+ ipl(out,a.mValue,b.mValue,d);
+ }
+}; // ! Interpolator <aiQuatKey>
+
+template <>
+struct Interpolator<aiMeshKey> {
+ void operator () (unsigned int& out, const aiMeshKey& a,
+ const aiMeshKey& b, ai_real d) const
+ {
+ Interpolator<unsigned int> ipl;
+ ipl(out,a.mValue,b.mValue,d);
+ }
+}; // ! Interpolator <aiQuatKey>
+
+//! @endcond
+
+} // ! end namespace Assimp
+
+#endif // __cplusplus
+
+#endif // AI_ANIM_H_INC
diff --git a/thirdparty/assimp/include/assimp/camera.h b/thirdparty/assimp/include/assimp/camera.h
new file mode 100644
index 0000000000..99daf69934
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/camera.h
@@ -0,0 +1,226 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file camera.h
+ * @brief Defines the aiCamera data structure
+ */
+
+#pragma once
+#ifndef AI_CAMERA_H_INC
+#define AI_CAMERA_H_INC
+
+#include "types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// ---------------------------------------------------------------------------
+/** Helper structure to describe a virtual camera.
+ *
+ * Cameras have a representation in the node graph and can be animated.
+ * An important aspect is that the camera itself is also part of the
+ * scenegraph. This means, any values such as the look-at vector are not
+ * *absolute*, they're <b>relative</b> to the coordinate system defined
+ * by the node which corresponds to the camera. This allows for camera
+ * animations. For static cameras parameters like the 'look-at' or 'up' vectors
+ * are usually specified directly in aiCamera, but beware, they could also
+ * be encoded in the node transformation. The following (pseudo)code sample
+ * shows how to do it: <br><br>
+ * @code
+ * // Get the camera matrix for a camera at a specific time
+ * // if the node hierarchy for the camera does not contain
+ * // at least one animated node this is a static computation
+ * get-camera-matrix (node sceneRoot, camera cam) : matrix
+ * {
+ * node cnd = find-node-for-camera(cam)
+ * matrix cmt = identity()
+ *
+ * // as usual - get the absolute camera transformation for this frame
+ * for each node nd in hierarchy from sceneRoot to cnd
+ * matrix cur
+ * if (is-animated(nd))
+ * cur = eval-animation(nd)
+ * else cur = nd->mTransformation;
+ * cmt = mult-matrices( cmt, cur )
+ * end for
+ *
+ * // now multiply with the camera's own local transform
+ * cam = mult-matrices (cam, get-camera-matrix(cmt) )
+ * }
+ * @endcode
+ *
+ * @note some file formats (such as 3DS, ASE) export a "target point" -
+ * the point the camera is looking at (it can even be animated). Assimp
+ * writes the target point as a subnode of the camera's main node,
+ * called "<camName>.Target". However this is just additional information
+ * then the transformation tracks of the camera main node make the
+ * camera already look in the right direction.
+ *
+*/
+struct aiCamera
+{
+ /** The name of the camera.
+ *
+ * There must be a node in the scenegraph with the same name.
+ * This node specifies the position of the camera in the scene
+ * hierarchy and can be animated.
+ */
+ C_STRUCT aiString mName;
+
+ /** Position of the camera relative to the coordinate space
+ * defined by the corresponding node.
+ *
+ * The default value is 0|0|0.
+ */
+ C_STRUCT aiVector3D mPosition;
+
+
+ /** 'Up' - vector of the camera coordinate system relative to
+ * the coordinate space defined by the corresponding node.
+ *
+ * The 'right' vector of the camera coordinate system is
+ * the cross product of the up and lookAt vectors.
+ * The default value is 0|1|0. The vector
+ * may be normalized, but it needn't.
+ */
+ C_STRUCT aiVector3D mUp;
+
+
+ /** 'LookAt' - vector of the camera coordinate system relative to
+ * the coordinate space defined by the corresponding node.
+ *
+ * This is the viewing direction of the user.
+ * The default value is 0|0|1. The vector
+ * may be normalized, but it needn't.
+ */
+ C_STRUCT aiVector3D mLookAt;
+
+
+ /** Half horizontal field of view angle, in radians.
+ *
+ * The field of view angle is the angle between the center
+ * line of the screen and the left or right border.
+ * The default value is 1/4PI.
+ */
+ float mHorizontalFOV;
+
+ /** Distance of the near clipping plane from the camera.
+ *
+ * The value may not be 0.f (for arithmetic reasons to prevent
+ * a division through zero). The default value is 0.1f.
+ */
+ float mClipPlaneNear;
+
+ /** Distance of the far clipping plane from the camera.
+ *
+ * The far clipping plane must, of course, be further away than the
+ * near clipping plane. The default value is 1000.f. The ratio
+ * between the near and the far plane should not be too
+ * large (between 1000-10000 should be ok) to avoid floating-point
+ * inaccuracies which could lead to z-fighting.
+ */
+ float mClipPlaneFar;
+
+
+ /** Screen aspect ratio.
+ *
+ * This is the ration between the width and the height of the
+ * screen. Typical values are 4/3, 1/2 or 1/1. This value is
+ * 0 if the aspect ratio is not defined in the source file.
+ * 0 is also the default value.
+ */
+ float mAspect;
+
+#ifdef __cplusplus
+
+ aiCamera() AI_NO_EXCEPT
+ : mUp (0.f,1.f,0.f)
+ , mLookAt (0.f,0.f,1.f)
+ , mHorizontalFOV (0.25f * (float)AI_MATH_PI)
+ , mClipPlaneNear (0.1f)
+ , mClipPlaneFar (1000.f)
+ , mAspect (0.f)
+ {}
+
+ /** @brief Get a *right-handed* camera matrix from me
+ * @param out Camera matrix to be filled
+ */
+ void GetCameraMatrix (aiMatrix4x4& out) const
+ {
+ /** todo: test ... should work, but i'm not absolutely sure */
+
+ /** We don't know whether these vectors are already normalized ...*/
+ aiVector3D zaxis = mLookAt; zaxis.Normalize();
+ aiVector3D yaxis = mUp; yaxis.Normalize();
+ aiVector3D xaxis = mUp^mLookAt; xaxis.Normalize();
+
+ out.a4 = -(xaxis * mPosition);
+ out.b4 = -(yaxis * mPosition);
+ out.c4 = -(zaxis * mPosition);
+
+ out.a1 = xaxis.x;
+ out.a2 = xaxis.y;
+ out.a3 = xaxis.z;
+
+ out.b1 = yaxis.x;
+ out.b2 = yaxis.y;
+ out.b3 = yaxis.z;
+
+ out.c1 = zaxis.x;
+ out.c2 = zaxis.y;
+ out.c3 = zaxis.z;
+
+ out.d1 = out.d2 = out.d3 = 0.f;
+ out.d4 = 1.f;
+ }
+
+#endif
+};
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // AI_CAMERA_H_INC
diff --git a/thirdparty/assimp/include/assimp/cexport.h b/thirdparty/assimp/include/assimp/cexport.h
new file mode 100644
index 0000000000..1d62dc26b3
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/cexport.h
@@ -0,0 +1,261 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2011, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file cexport.h
+* @brief Defines the C-API for the Assimp export interface
+*/
+#pragma once
+#ifndef AI_EXPORT_H_INC
+#define AI_EXPORT_H_INC
+
+#ifndef ASSIMP_BUILD_NO_EXPORT
+
+// Public ASSIMP data structures
+#include <assimp/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct aiScene; // aiScene.h
+struct aiFileIO; // aiFileIO.h
+
+// --------------------------------------------------------------------------------
+/** Describes an file format which Assimp can export to. Use #aiGetExportFormatCount() to
+* learn how many export formats the current Assimp build supports and #aiGetExportFormatDescription()
+* to retrieve a description of an export format option.
+*/
+struct aiExportFormatDesc
+{
+ /// a short string ID to uniquely identify the export format. Use this ID string to
+ /// specify which file format you want to export to when calling #aiExportScene().
+ /// Example: "dae" or "obj"
+ const char* id;
+
+ /// A short description of the file format to present to users. Useful if you want
+ /// to allow the user to select an export format.
+ const char* description;
+
+ /// Recommended file extension for the exported file in lower case.
+ const char* fileExtension;
+};
+
+
+// --------------------------------------------------------------------------------
+/** Returns the number of export file formats available in the current Assimp build.
+ * Use aiGetExportFormatDescription() to retrieve infos of a specific export format.
+ */
+ASSIMP_API size_t aiGetExportFormatCount(void);
+
+// --------------------------------------------------------------------------------
+/** Returns a description of the nth export file format. Use #aiGetExportFormatCount()
+ * to learn how many export formats are supported. The description must be released by
+ * calling aiReleaseExportFormatDescription afterwards.
+ * @param pIndex Index of the export format to retrieve information for. Valid range is
+ * 0 to #aiGetExportFormatCount()
+ * @return A description of that specific export format. NULL if pIndex is out of range.
+ */
+ASSIMP_API const C_STRUCT aiExportFormatDesc* aiGetExportFormatDescription( size_t pIndex);
+
+// --------------------------------------------------------------------------------
+/** Release a description of the nth export file format. Must be returned by
+* aiGetExportFormatDescription
+* @param desc Pointer to the description
+*/
+ASSIMP_API void aiReleaseExportFormatDescription( const C_STRUCT aiExportFormatDesc *desc );
+
+// --------------------------------------------------------------------------------
+/** Create a modifiable copy of a scene.
+ * This is useful to import files via Assimp, change their topology and
+ * export them again. Since the scene returned by the various importer functions
+ * is const, a modifiable copy is needed.
+ * @param pIn Valid scene to be copied
+ * @param pOut Receives a modifyable copy of the scene. Use aiFreeScene() to
+ * delete it again.
+ */
+ASSIMP_API void aiCopyScene(const C_STRUCT aiScene* pIn,
+ C_STRUCT aiScene** pOut);
+
+
+// --------------------------------------------------------------------------------
+/** Frees a scene copy created using aiCopyScene() */
+ASSIMP_API void aiFreeScene(const C_STRUCT aiScene* pIn);
+
+// --------------------------------------------------------------------------------
+/** Exports the given scene to a chosen file format and writes the result file(s) to disk.
+* @param pScene The scene to export. Stays in possession of the caller, is not changed by the function.
+* The scene is expected to conform to Assimp's Importer output format as specified
+* in the @link data Data Structures Page @endlink. In short, this means the model data
+* should use a right-handed coordinate systems, face winding should be counter-clockwise
+* and the UV coordinate origin is assumed to be in the upper left. If your input data
+* uses different conventions, have a look at the last parameter.
+* @param pFormatId ID string to specify to which format you want to export to. Use
+* aiGetExportFormatCount() / aiGetExportFormatDescription() to learn which export formats are available.
+* @param pFileName Output file to write
+* @param pPreprocessing Accepts any choice of the #aiPostProcessSteps enumerated
+* flags, but in reality only a subset of them makes sense here. Specifying
+* 'preprocessing' flags is useful if the input scene does not conform to
+* Assimp's default conventions as specified in the @link data Data Structures Page @endlink.
+* In short, this means the geometry data should use a right-handed coordinate systems, face
+* winding should be counter-clockwise and the UV coordinate origin is assumed to be in
+* the upper left. The #aiProcess_MakeLeftHanded, #aiProcess_FlipUVs and
+* #aiProcess_FlipWindingOrder flags are used in the import side to allow users
+* to have those defaults automatically adapted to their conventions. Specifying those flags
+* for exporting has the opposite effect, respectively. Some other of the
+* #aiPostProcessSteps enumerated values may be useful as well, but you'll need
+* to try out what their effect on the exported file is. Many formats impose
+* their own restrictions on the structure of the geometry stored therein,
+* so some preprocessing may have little or no effect at all, or may be
+* redundant as exporters would apply them anyhow. A good example
+* is triangulation - whilst you can enforce it by specifying
+* the #aiProcess_Triangulate flag, most export formats support only
+* triangulate data so they would run the step anyway.
+*
+* If assimp detects that the input scene was directly taken from the importer side of
+* the library (i.e. not copied using aiCopyScene and potetially modified afterwards),
+* any postprocessing steps already applied to the scene will not be applied again, unless
+* they show non-idempotent behaviour (#aiProcess_MakeLeftHanded, #aiProcess_FlipUVs and
+* #aiProcess_FlipWindingOrder).
+* @return a status code indicating the result of the export
+* @note Use aiCopyScene() to get a modifiable copy of a previously
+* imported scene.
+*/
+ASSIMP_API aiReturn aiExportScene( const C_STRUCT aiScene* pScene,
+ const char* pFormatId,
+ const char* pFileName,
+ unsigned int pPreprocessing);
+
+
+// --------------------------------------------------------------------------------
+/** Exports the given scene to a chosen file format using custom IO logic supplied by you.
+* @param pScene The scene to export. Stays in possession of the caller, is not changed by the function.
+* @param pFormatId ID string to specify to which format you want to export to. Use
+* aiGetExportFormatCount() / aiGetExportFormatDescription() to learn which export formats are available.
+* @param pFileName Output file to write
+* @param pIO custom IO implementation to be used. Use this if you use your own storage methods.
+* If none is supplied, a default implementation using standard file IO is used. Note that
+* #aiExportSceneToBlob is provided as convenience function to export to memory buffers.
+* @param pPreprocessing Please see the documentation for #aiExportScene
+* @return a status code indicating the result of the export
+* @note Include <aiFileIO.h> for the definition of #aiFileIO.
+* @note Use aiCopyScene() to get a modifiable copy of a previously
+* imported scene.
+*/
+ASSIMP_API aiReturn aiExportSceneEx( const C_STRUCT aiScene* pScene,
+ const char* pFormatId,
+ const char* pFileName,
+ C_STRUCT aiFileIO* pIO,
+ unsigned int pPreprocessing );
+
+// --------------------------------------------------------------------------------
+/** Describes a blob of exported scene data. Use #aiExportSceneToBlob() to create a blob containing an
+* exported scene. The memory referred by this structure is owned by Assimp.
+* to free its resources. Don't try to free the memory on your side - it will crash for most build configurations
+* due to conflicting heaps.
+*
+* Blobs can be nested - each blob may reference another blob, which may in turn reference another blob and so on.
+* This is used when exporters write more than one output file for a given #aiScene. See the remarks for
+* #aiExportDataBlob::name for more information.
+*/
+struct aiExportDataBlob
+{
+ /// Size of the data in bytes
+ size_t size;
+
+ /// The data.
+ void* data;
+
+ /** Name of the blob. An empty string always
+ indicates the first (and primary) blob,
+ which contains the actual file data.
+ Any other blobs are auxiliary files produced
+ by exporters (i.e. material files). Existence
+ of such files depends on the file format. Most
+ formats don't split assets across multiple files.
+
+ If used, blob names usually contain the file
+ extension that should be used when writing
+ the data to disc.
+ */
+ C_STRUCT aiString name;
+
+ /** Pointer to the next blob in the chain or NULL if there is none. */
+ C_STRUCT aiExportDataBlob * next;
+
+#ifdef __cplusplus
+ /// Default constructor
+ aiExportDataBlob() { size = 0; data = next = NULL; }
+ /// Releases the data
+ ~aiExportDataBlob() { delete [] static_cast<unsigned char*>( data ); delete next; }
+
+private:
+ // no copying
+ aiExportDataBlob(const aiExportDataBlob& );
+ aiExportDataBlob& operator= (const aiExportDataBlob& );
+#endif // __cplusplus
+};
+
+// --------------------------------------------------------------------------------
+/** Exports the given scene to a chosen file format. Returns the exported data as a binary blob which
+* you can write into a file or something. When you're done with the data, use #aiReleaseExportBlob()
+* to free the resources associated with the export.
+* @param pScene The scene to export. Stays in possession of the caller, is not changed by the function.
+* @param pFormatId ID string to specify to which format you want to export to. Use
+* #aiGetExportFormatCount() / #aiGetExportFormatDescription() to learn which export formats are available.
+* @param pPreprocessing Please see the documentation for #aiExportScene
+* @return the exported data or NULL in case of error
+*/
+ASSIMP_API const C_STRUCT aiExportDataBlob* aiExportSceneToBlob( const C_STRUCT aiScene* pScene, const char* pFormatId,
+ unsigned int pPreprocessing );
+
+// --------------------------------------------------------------------------------
+/** Releases the memory associated with the given exported data. Use this function to free a data blob
+* returned by aiExportScene().
+* @param pData the data blob returned by #aiExportSceneToBlob
+*/
+ASSIMP_API void aiReleaseExportBlob( const C_STRUCT aiExportDataBlob* pData );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // ASSIMP_BUILD_NO_EXPORT
+#endif // AI_EXPORT_H_INC
diff --git a/thirdparty/assimp/include/assimp/cfileio.h b/thirdparty/assimp/include/assimp/cfileio.h
new file mode 100644
index 0000000000..8f7ca45469
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/cfileio.h
@@ -0,0 +1,138 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file cfileio.h
+ * @brief Defines generic C routines to access memory-mapped files
+ */
+#pragma once
+#ifndef AI_FILEIO_H_INC
+#define AI_FILEIO_H_INC
+
+#include <assimp/types.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+struct aiFileIO;
+struct aiFile;
+
+// aiFile callbacks
+typedef size_t (*aiFileWriteProc) (C_STRUCT aiFile*, const char*, size_t, size_t);
+typedef size_t (*aiFileReadProc) (C_STRUCT aiFile*, char*, size_t,size_t);
+typedef size_t (*aiFileTellProc) (C_STRUCT aiFile*);
+typedef void (*aiFileFlushProc) (C_STRUCT aiFile*);
+typedef C_ENUM aiReturn (*aiFileSeek) (C_STRUCT aiFile*, size_t, C_ENUM aiOrigin);
+
+// aiFileIO callbacks
+typedef C_STRUCT aiFile* (*aiFileOpenProc) (C_STRUCT aiFileIO*, const char*, const char*);
+typedef void (*aiFileCloseProc) (C_STRUCT aiFileIO*, C_STRUCT aiFile*);
+
+// Represents user-defined data
+typedef char* aiUserData;
+
+// ----------------------------------------------------------------------------------
+/** @brief C-API: File system callbacks
+ *
+ * Provided are functions to open and close files. Supply a custom structure to
+ * the import function. If you don't, a default implementation is used. Use custom
+ * file systems to enable reading from other sources, such as ZIPs
+ * or memory locations. */
+struct aiFileIO
+{
+ /** Function used to open a new file
+ */
+ aiFileOpenProc OpenProc;
+
+ /** Function used to close an existing file
+ */
+ aiFileCloseProc CloseProc;
+
+ /** User-defined, opaque data */
+ aiUserData UserData;
+};
+
+// ----------------------------------------------------------------------------------
+/** @brief C-API: File callbacks
+ *
+ * Actually, it's a data structure to wrap a set of fXXXX (e.g fopen)
+ * replacement functions.
+ *
+ * The default implementation of the functions utilizes the fXXX functions from
+ * the CRT. However, you can supply a custom implementation to Assimp by
+ * delivering a custom aiFileIO. Use this to enable reading from other sources,
+ * such as ZIP archives or memory locations. */
+struct aiFile
+{
+ /** Callback to read from a file */
+ aiFileReadProc ReadProc;
+
+ /** Callback to write to a file */
+ aiFileWriteProc WriteProc;
+
+ /** Callback to retrieve the current position of
+ * the file cursor (ftell())
+ */
+ aiFileTellProc TellProc;
+
+ /** Callback to retrieve the size of the file,
+ * in bytes
+ */
+ aiFileTellProc FileSizeProc;
+
+ /** Callback to set the current position
+ * of the file cursor (fseek())
+ */
+ aiFileSeek SeekProc;
+
+ /** Callback to flush the file contents
+ */
+ aiFileFlushProc FlushProc;
+
+ /** User-defined, opaque data
+ */
+ aiUserData UserData;
+};
+
+#ifdef __cplusplus
+}
+#endif
+#endif // AI_FILEIO_H_INC
diff --git a/thirdparty/assimp/include/assimp/cimport.h b/thirdparty/assimp/include/assimp/cimport.h
new file mode 100644
index 0000000000..dbd10f1370
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/cimport.h
@@ -0,0 +1,565 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file cimport.h
+ * @brief Defines the C-API to the Open Asset Import Library.
+ */
+#pragma once
+#ifndef AI_ASSIMP_H_INC
+#define AI_ASSIMP_H_INC
+
+#include <assimp/types.h>
+#include "importerdesc.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct aiScene; // aiScene.h
+struct aiFileIO; // aiFileIO.h
+typedef void (*aiLogStreamCallback)(const char* /* message */, char* /* user */);
+
+// --------------------------------------------------------------------------------
+/** C-API: Represents a log stream. A log stream receives all log messages and
+ * streams them _somewhere_.
+ * @see aiGetPredefinedLogStream
+ * @see aiAttachLogStream
+ * @see aiDetachLogStream */
+// --------------------------------------------------------------------------------
+struct aiLogStream
+{
+ /** callback to be called */
+ aiLogStreamCallback callback;
+
+ /** user data to be passed to the callback */
+ char* user;
+};
+
+
+// --------------------------------------------------------------------------------
+/** C-API: Represents an opaque set of settings to be used during importing.
+ * @see aiCreatePropertyStore
+ * @see aiReleasePropertyStore
+ * @see aiImportFileExWithProperties
+ * @see aiSetPropertyInteger
+ * @see aiSetPropertyFloat
+ * @see aiSetPropertyString
+ * @see aiSetPropertyMatrix
+ */
+// --------------------------------------------------------------------------------
+struct aiPropertyStore { char sentinel; };
+
+/** Our own C boolean type */
+typedef int aiBool;
+
+#define AI_FALSE 0
+#define AI_TRUE 1
+
+// --------------------------------------------------------------------------------
+/** Reads the given file and returns its content.
+ *
+ * If the call succeeds, the imported data is returned in an aiScene structure.
+ * The data is intended to be read-only, it stays property of the ASSIMP
+ * library and will be stable until aiReleaseImport() is called. After you're
+ * done with it, call aiReleaseImport() to free the resources associated with
+ * this file. If the import fails, NULL is returned instead. Call
+ * aiGetErrorString() to retrieve a human-readable error text.
+ * @param pFile Path and filename of the file to be imported,
+ * expected to be a null-terminated c-string. NULL is not a valid value.
+ * @param pFlags Optional post processing steps to be executed after
+ * a successful import. Provide a bitwise combination of the
+ * #aiPostProcessSteps flags.
+ * @return Pointer to the imported data or NULL if the import failed.
+ */
+ASSIMP_API const C_STRUCT aiScene* aiImportFile(
+ const char* pFile,
+ unsigned int pFlags);
+
+// --------------------------------------------------------------------------------
+/** Reads the given file using user-defined I/O functions and returns
+ * its content.
+ *
+ * If the call succeeds, the imported data is returned in an aiScene structure.
+ * The data is intended to be read-only, it stays property of the ASSIMP
+ * library and will be stable until aiReleaseImport() is called. After you're
+ * done with it, call aiReleaseImport() to free the resources associated with
+ * this file. If the import fails, NULL is returned instead. Call
+ * aiGetErrorString() to retrieve a human-readable error text.
+ * @param pFile Path and filename of the file to be imported,
+ * expected to be a null-terminated c-string. NULL is not a valid value.
+ * @param pFlags Optional post processing steps to be executed after
+ * a successful import. Provide a bitwise combination of the
+ * #aiPostProcessSteps flags.
+ * @param pFS aiFileIO structure. Will be used to open the model file itself
+ * and any other files the loader needs to open. Pass NULL to use the default
+ * implementation.
+ * @return Pointer to the imported data or NULL if the import failed.
+ * @note Include <aiFileIO.h> for the definition of #aiFileIO.
+ */
+ASSIMP_API const C_STRUCT aiScene* aiImportFileEx(
+ const char* pFile,
+ unsigned int pFlags,
+ C_STRUCT aiFileIO* pFS);
+
+// --------------------------------------------------------------------------------
+/** Same as #aiImportFileEx, but adds an extra parameter containing importer settings.
+ *
+ * @param pFile Path and filename of the file to be imported,
+ * expected to be a null-terminated c-string. NULL is not a valid value.
+ * @param pFlags Optional post processing steps to be executed after
+ * a successful import. Provide a bitwise combination of the
+ * #aiPostProcessSteps flags.
+ * @param pFS aiFileIO structure. Will be used to open the model file itself
+ * and any other files the loader needs to open. Pass NULL to use the default
+ * implementation.
+ * @param pProps #aiPropertyStore instance containing import settings.
+ * @return Pointer to the imported data or NULL if the import failed.
+ * @note Include <aiFileIO.h> for the definition of #aiFileIO.
+ * @see aiImportFileEx
+ */
+ASSIMP_API const C_STRUCT aiScene* aiImportFileExWithProperties(
+ const char* pFile,
+ unsigned int pFlags,
+ C_STRUCT aiFileIO* pFS,
+ const C_STRUCT aiPropertyStore* pProps);
+
+// --------------------------------------------------------------------------------
+/** Reads the given file from a given memory buffer,
+ *
+ * If the call succeeds, the contents of the file are returned as a pointer to an
+ * aiScene object. The returned data is intended to be read-only, the importer keeps
+ * ownership of the data and will destroy it upon destruction. If the import fails,
+ * NULL is returned.
+ * A human-readable error description can be retrieved by calling aiGetErrorString().
+ * @param pBuffer Pointer to the file data
+ * @param pLength Length of pBuffer, in bytes
+ * @param pFlags Optional post processing steps to be executed after
+ * a successful import. Provide a bitwise combination of the
+ * #aiPostProcessSteps flags. If you wish to inspect the imported
+ * scene first in order to fine-tune your post-processing setup,
+ * consider to use #aiApplyPostProcessing().
+ * @param pHint An additional hint to the library. If this is a non empty string,
+ * the library looks for a loader to support the file extension specified by pHint
+ * and passes the file to the first matching loader. If this loader is unable to
+ * completely the request, the library continues and tries to determine the file
+ * format on its own, a task that may or may not be successful.
+ * Check the return value, and you'll know ...
+ * @return A pointer to the imported data, NULL if the import failed.
+ *
+ * @note This is a straightforward way to decode models from memory
+ * buffers, but it doesn't handle model formats that spread their
+ * data across multiple files or even directories. Examples include
+ * OBJ or MD3, which outsource parts of their material info into
+ * external scripts. If you need full functionality, provide
+ * a custom IOSystem to make Assimp find these files and use
+ * the regular aiImportFileEx()/aiImportFileExWithProperties() API.
+ */
+ASSIMP_API const C_STRUCT aiScene* aiImportFileFromMemory(
+ const char* pBuffer,
+ unsigned int pLength,
+ unsigned int pFlags,
+ const char* pHint);
+
+// --------------------------------------------------------------------------------
+/** Same as #aiImportFileFromMemory, but adds an extra parameter containing importer settings.
+ *
+ * @param pBuffer Pointer to the file data
+ * @param pLength Length of pBuffer, in bytes
+ * @param pFlags Optional post processing steps to be executed after
+ * a successful import. Provide a bitwise combination of the
+ * #aiPostProcessSteps flags. If you wish to inspect the imported
+ * scene first in order to fine-tune your post-processing setup,
+ * consider to use #aiApplyPostProcessing().
+ * @param pHint An additional hint to the library. If this is a non empty string,
+ * the library looks for a loader to support the file extension specified by pHint
+ * and passes the file to the first matching loader. If this loader is unable to
+ * completely the request, the library continues and tries to determine the file
+ * format on its own, a task that may or may not be successful.
+ * Check the return value, and you'll know ...
+ * @param pProps #aiPropertyStore instance containing import settings.
+ * @return A pointer to the imported data, NULL if the import failed.
+ *
+ * @note This is a straightforward way to decode models from memory
+ * buffers, but it doesn't handle model formats that spread their
+ * data across multiple files or even directories. Examples include
+ * OBJ or MD3, which outsource parts of their material info into
+ * external scripts. If you need full functionality, provide
+ * a custom IOSystem to make Assimp find these files and use
+ * the regular aiImportFileEx()/aiImportFileExWithProperties() API.
+ * @see aiImportFileFromMemory
+ */
+ASSIMP_API const C_STRUCT aiScene* aiImportFileFromMemoryWithProperties(
+ const char* pBuffer,
+ unsigned int pLength,
+ unsigned int pFlags,
+ const char* pHint,
+ const C_STRUCT aiPropertyStore* pProps);
+
+// --------------------------------------------------------------------------------
+/** Apply post-processing to an already-imported scene.
+ *
+ * This is strictly equivalent to calling #aiImportFile()/#aiImportFileEx with the
+ * same flags. However, you can use this separate function to inspect the imported
+ * scene first to fine-tune your post-processing setup.
+ * @param pScene Scene to work on.
+ * @param pFlags Provide a bitwise combination of the #aiPostProcessSteps flags.
+ * @return A pointer to the post-processed data. Post processing is done in-place,
+ * meaning this is still the same #aiScene which you passed for pScene. However,
+ * _if_ post-processing failed, the scene could now be NULL. That's quite a rare
+ * case, post processing steps are not really designed to 'fail'. To be exact,
+ * the #aiProcess_ValidateDataStructure flag is currently the only post processing step
+ * which can actually cause the scene to be reset to NULL.
+ */
+ASSIMP_API const C_STRUCT aiScene* aiApplyPostProcessing(
+ const C_STRUCT aiScene* pScene,
+ unsigned int pFlags);
+
+// --------------------------------------------------------------------------------
+/** Get one of the predefine log streams. This is the quick'n'easy solution to
+ * access Assimp's log system. Attaching a log stream can slightly reduce Assimp's
+ * overall import performance.
+ *
+ * Usage is rather simple (this will stream the log to a file, named log.txt, and
+ * the stdout stream of the process:
+ * @code
+ * struct aiLogStream c;
+ * c = aiGetPredefinedLogStream(aiDefaultLogStream_FILE,"log.txt");
+ * aiAttachLogStream(&c);
+ * c = aiGetPredefinedLogStream(aiDefaultLogStream_STDOUT,NULL);
+ * aiAttachLogStream(&c);
+ * @endcode
+ *
+ * @param pStreams One of the #aiDefaultLogStream enumerated values.
+ * @param file Solely for the #aiDefaultLogStream_FILE flag: specifies the file to write to.
+ * Pass NULL for all other flags.
+ * @return The log stream. callback is set to NULL if something went wrong.
+ */
+ASSIMP_API C_STRUCT aiLogStream aiGetPredefinedLogStream(
+ C_ENUM aiDefaultLogStream pStreams,
+ const char* file);
+
+// --------------------------------------------------------------------------------
+/** Attach a custom log stream to the libraries' logging system.
+ *
+ * Attaching a log stream can slightly reduce Assimp's overall import
+ * performance. Multiple log-streams can be attached.
+ * @param stream Describes the new log stream.
+ * @note To ensure proper destruction of the logging system, you need to manually
+ * call aiDetachLogStream() on every single log stream you attach.
+ * Alternatively (for the lazy folks) #aiDetachAllLogStreams is provided.
+ */
+ASSIMP_API void aiAttachLogStream(
+ const C_STRUCT aiLogStream* stream);
+
+// --------------------------------------------------------------------------------
+/** Enable verbose logging. Verbose logging includes debug-related stuff and
+ * detailed import statistics. This can have severe impact on import performance
+ * and memory consumption. However, it might be useful to find out why a file
+ * didn't read correctly.
+ * @param d AI_TRUE or AI_FALSE, your decision.
+ */
+ASSIMP_API void aiEnableVerboseLogging(aiBool d);
+
+// --------------------------------------------------------------------------------
+/** Detach a custom log stream from the libraries' logging system.
+ *
+ * This is the counterpart of #aiAttachLogStream. If you attached a stream,
+ * don't forget to detach it again.
+ * @param stream The log stream to be detached.
+ * @return AI_SUCCESS if the log stream has been detached successfully.
+ * @see aiDetachAllLogStreams
+ */
+ASSIMP_API C_ENUM aiReturn aiDetachLogStream(
+ const C_STRUCT aiLogStream* stream);
+
+// --------------------------------------------------------------------------------
+/** Detach all active log streams from the libraries' logging system.
+ * This ensures that the logging system is terminated properly and all
+ * resources allocated by it are actually freed. If you attached a stream,
+ * don't forget to detach it again.
+ * @see aiAttachLogStream
+ * @see aiDetachLogStream
+ */
+ASSIMP_API void aiDetachAllLogStreams(void);
+
+// --------------------------------------------------------------------------------
+/** Releases all resources associated with the given import process.
+ *
+ * Call this function after you're done with the imported data.
+ * @param pScene The imported data to release. NULL is a valid value.
+ */
+ASSIMP_API void aiReleaseImport(
+ const C_STRUCT aiScene* pScene);
+
+// --------------------------------------------------------------------------------
+/** Returns the error text of the last failed import process.
+ *
+ * @return A textual description of the error that occurred at the last
+ * import process. NULL if there was no error. There can't be an error if you
+ * got a non-NULL #aiScene from #aiImportFile/#aiImportFileEx/#aiApplyPostProcessing.
+ */
+ASSIMP_API const char* aiGetErrorString(void);
+
+// --------------------------------------------------------------------------------
+/** Returns whether a given file extension is supported by ASSIMP
+ *
+ * @param szExtension Extension for which the function queries support for.
+ * Must include a leading dot '.'. Example: ".3ds", ".md3"
+ * @return AI_TRUE if the file extension is supported.
+ */
+ASSIMP_API aiBool aiIsExtensionSupported(
+ const char* szExtension);
+
+// --------------------------------------------------------------------------------
+/** Get a list of all file extensions supported by ASSIMP.
+ *
+ * If a file extension is contained in the list this does, of course, not
+ * mean that ASSIMP is able to load all files with this extension.
+ * @param szOut String to receive the extension list.
+ * Format of the list: "*.3ds;*.obj;*.dae". NULL is not a valid parameter.
+ */
+ASSIMP_API void aiGetExtensionList(
+ C_STRUCT aiString* szOut);
+
+// --------------------------------------------------------------------------------
+/** Get the approximated storage required by an imported asset
+ * @param pIn Input asset.
+ * @param in Data structure to be filled.
+ */
+ASSIMP_API void aiGetMemoryRequirements(
+ const C_STRUCT aiScene* pIn,
+ C_STRUCT aiMemoryInfo* in);
+
+
+
+// --------------------------------------------------------------------------------
+/** Create an empty property store. Property stores are used to collect import
+ * settings.
+ * @return New property store. Property stores need to be manually destroyed using
+ * the #aiReleasePropertyStore API function.
+ */
+ASSIMP_API C_STRUCT aiPropertyStore* aiCreatePropertyStore(void);
+
+// --------------------------------------------------------------------------------
+/** Delete a property store.
+ * @param p Property store to be deleted.
+ */
+ASSIMP_API void aiReleasePropertyStore(C_STRUCT aiPropertyStore* p);
+
+// --------------------------------------------------------------------------------
+/** Set an integer property.
+ *
+ * This is the C-version of #Assimp::Importer::SetPropertyInteger(). In the C
+ * interface, properties are always shared by all imports. It is not possible to
+ * specify them per import.
+ *
+ * @param store Store to modify. Use #aiCreatePropertyStore to obtain a store.
+ * @param szName Name of the configuration property to be set. All supported
+ * public properties are defined in the config.h header file (AI_CONFIG_XXX).
+ * @param value New value for the property
+ */
+ASSIMP_API void aiSetImportPropertyInteger(
+ C_STRUCT aiPropertyStore* store,
+ const char* szName,
+ int value);
+
+// --------------------------------------------------------------------------------
+/** Set a floating-point property.
+ *
+ * This is the C-version of #Assimp::Importer::SetPropertyFloat(). In the C
+ * interface, properties are always shared by all imports. It is not possible to
+ * specify them per import.
+ *
+ * @param store Store to modify. Use #aiCreatePropertyStore to obtain a store.
+ * @param szName Name of the configuration property to be set. All supported
+ * public properties are defined in the config.h header file (AI_CONFIG_XXX).
+ * @param value New value for the property
+ */
+ASSIMP_API void aiSetImportPropertyFloat(
+ C_STRUCT aiPropertyStore* store,
+ const char* szName,
+ ai_real value);
+
+// --------------------------------------------------------------------------------
+/** Set a string property.
+ *
+ * This is the C-version of #Assimp::Importer::SetPropertyString(). In the C
+ * interface, properties are always shared by all imports. It is not possible to
+ * specify them per import.
+ *
+ * @param store Store to modify. Use #aiCreatePropertyStore to obtain a store.
+ * @param szName Name of the configuration property to be set. All supported
+ * public properties are defined in the config.h header file (AI_CONFIG_XXX).
+ * @param st New value for the property
+ */
+ASSIMP_API void aiSetImportPropertyString(
+ C_STRUCT aiPropertyStore* store,
+ const char* szName,
+ const C_STRUCT aiString* st);
+
+// --------------------------------------------------------------------------------
+/** Set a matrix property.
+ *
+ * This is the C-version of #Assimp::Importer::SetPropertyMatrix(). In the C
+ * interface, properties are always shared by all imports. It is not possible to
+ * specify them per import.
+ *
+ * @param store Store to modify. Use #aiCreatePropertyStore to obtain a store.
+ * @param szName Name of the configuration property to be set. All supported
+ * public properties are defined in the config.h header file (AI_CONFIG_XXX).
+ * @param mat New value for the property
+ */
+ASSIMP_API void aiSetImportPropertyMatrix(
+ C_STRUCT aiPropertyStore* store,
+ const char* szName,
+ const C_STRUCT aiMatrix4x4* mat);
+
+// --------------------------------------------------------------------------------
+/** Construct a quaternion from a 3x3 rotation matrix.
+ * @param quat Receives the output quaternion.
+ * @param mat Matrix to 'quaternionize'.
+ * @see aiQuaternion(const aiMatrix3x3& pRotMatrix)
+ */
+ASSIMP_API void aiCreateQuaternionFromMatrix(
+ C_STRUCT aiQuaternion* quat,
+ const C_STRUCT aiMatrix3x3* mat);
+
+// --------------------------------------------------------------------------------
+/** Decompose a transformation matrix into its rotational, translational and
+ * scaling components.
+ *
+ * @param mat Matrix to decompose
+ * @param scaling Receives the scaling component
+ * @param rotation Receives the rotational component
+ * @param position Receives the translational component.
+ * @see aiMatrix4x4::Decompose (aiVector3D&, aiQuaternion&, aiVector3D&) const;
+ */
+ASSIMP_API void aiDecomposeMatrix(
+ const C_STRUCT aiMatrix4x4* mat,
+ C_STRUCT aiVector3D* scaling,
+ C_STRUCT aiQuaternion* rotation,
+ C_STRUCT aiVector3D* position);
+
+// --------------------------------------------------------------------------------
+/** Transpose a 4x4 matrix.
+ * @param mat Pointer to the matrix to be transposed
+ */
+ASSIMP_API void aiTransposeMatrix4(
+ C_STRUCT aiMatrix4x4* mat);
+
+// --------------------------------------------------------------------------------
+/** Transpose a 3x3 matrix.
+ * @param mat Pointer to the matrix to be transposed
+ */
+ASSIMP_API void aiTransposeMatrix3(
+ C_STRUCT aiMatrix3x3* mat);
+
+// --------------------------------------------------------------------------------
+/** Transform a vector by a 3x3 matrix
+ * @param vec Vector to be transformed.
+ * @param mat Matrix to transform the vector with.
+ */
+ASSIMP_API void aiTransformVecByMatrix3(
+ C_STRUCT aiVector3D* vec,
+ const C_STRUCT aiMatrix3x3* mat);
+
+// --------------------------------------------------------------------------------
+/** Transform a vector by a 4x4 matrix
+ * @param vec Vector to be transformed.
+ * @param mat Matrix to transform the vector with.
+ */
+ASSIMP_API void aiTransformVecByMatrix4(
+ C_STRUCT aiVector3D* vec,
+ const C_STRUCT aiMatrix4x4* mat);
+
+// --------------------------------------------------------------------------------
+/** Multiply two 4x4 matrices.
+ * @param dst First factor, receives result.
+ * @param src Matrix to be multiplied with 'dst'.
+ */
+ASSIMP_API void aiMultiplyMatrix4(
+ C_STRUCT aiMatrix4x4* dst,
+ const C_STRUCT aiMatrix4x4* src);
+
+// --------------------------------------------------------------------------------
+/** Multiply two 3x3 matrices.
+ * @param dst First factor, receives result.
+ * @param src Matrix to be multiplied with 'dst'.
+ */
+ASSIMP_API void aiMultiplyMatrix3(
+ C_STRUCT aiMatrix3x3* dst,
+ const C_STRUCT aiMatrix3x3* src);
+
+// --------------------------------------------------------------------------------
+/** Get a 3x3 identity matrix.
+ * @param mat Matrix to receive its personal identity
+ */
+ASSIMP_API void aiIdentityMatrix3(
+ C_STRUCT aiMatrix3x3* mat);
+
+// --------------------------------------------------------------------------------
+/** Get a 4x4 identity matrix.
+ * @param mat Matrix to receive its personal identity
+ */
+ASSIMP_API void aiIdentityMatrix4(
+ C_STRUCT aiMatrix4x4* mat);
+
+// --------------------------------------------------------------------------------
+/** Returns the number of import file formats available in the current Assimp build.
+ * Use aiGetImportFormatDescription() to retrieve infos of a specific import format.
+ */
+ASSIMP_API size_t aiGetImportFormatCount(void);
+
+// --------------------------------------------------------------------------------
+/** Returns a description of the nth import file format. Use #aiGetImportFormatCount()
+ * to learn how many import formats are supported.
+ * @param pIndex Index of the import format to retrieve information for. Valid range is
+ * 0 to #aiGetImportFormatCount()
+ * @return A description of that specific import format. NULL if pIndex is out of range.
+ */
+ASSIMP_API const C_STRUCT aiImporterDesc* aiGetImportFormatDescription( size_t pIndex);
+#ifdef __cplusplus
+}
+#endif
+
+#endif // AI_ASSIMP_H_INC
diff --git a/thirdparty/assimp/include/assimp/color4.h b/thirdparty/assimp/include/assimp/color4.h
new file mode 100644
index 0000000000..3c97c8eda2
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/color4.h
@@ -0,0 +1,104 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+/** @file color4.h
+ * @brief RGBA color structure, including operators when compiling in C++
+ */
+#pragma once
+#ifndef AI_COLOR4D_H_INC
+#define AI_COLOR4D_H_INC
+
+#include "defs.h"
+
+#ifdef __cplusplus
+
+// ----------------------------------------------------------------------------------
+/** Represents a color in Red-Green-Blue space including an
+* alpha component. Color values range from 0 to 1. */
+// ----------------------------------------------------------------------------------
+template <typename TReal>
+class aiColor4t
+{
+public:
+ aiColor4t() AI_NO_EXCEPT : r(), g(), b(), a() {}
+ aiColor4t (TReal _r, TReal _g, TReal _b, TReal _a)
+ : r(_r), g(_g), b(_b), a(_a) {}
+ explicit aiColor4t (TReal _r) : r(_r), g(_r), b(_r), a(_r) {}
+ aiColor4t (const aiColor4t& o) = default;
+
+public:
+ // combined operators
+ const aiColor4t& operator += (const aiColor4t& o);
+ const aiColor4t& operator -= (const aiColor4t& o);
+ const aiColor4t& operator *= (TReal f);
+ const aiColor4t& operator /= (TReal f);
+
+public:
+ // comparison
+ bool operator == (const aiColor4t& other) const;
+ bool operator != (const aiColor4t& other) const;
+ bool operator < (const aiColor4t& other) const;
+
+ // color tuple access, rgba order
+ inline TReal operator[](unsigned int i) const;
+ inline TReal& operator[](unsigned int i);
+
+ /** check whether a color is (close to) black */
+ inline bool IsBlack() const;
+
+public:
+
+ // Red, green, blue and alpha color values
+ TReal r, g, b, a;
+}; // !struct aiColor4D
+
+typedef aiColor4t<ai_real> aiColor4D;
+
+#else
+
+struct aiColor4D {
+ ai_real r, g, b, a;
+};
+
+#endif // __cplusplus
+
+#endif // AI_COLOR4D_H_INC
diff --git a/thirdparty/assimp/include/assimp/color4.inl b/thirdparty/assimp/include/assimp/color4.inl
new file mode 100644
index 0000000000..3192d55f39
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/color4.inl
@@ -0,0 +1,205 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file color4.inl
+ * @brief Inline implementation of aiColor4t<TReal> operators
+ */
+#pragma once
+#ifndef AI_COLOR4D_INL_INC
+#define AI_COLOR4D_INL_INC
+
+#ifdef __cplusplus
+#include "color4.h"
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE const aiColor4t<TReal>& aiColor4t<TReal>::operator += (const aiColor4t<TReal>& o) {
+ r += o.r; g += o.g; b += o.b; a += o.a;
+ return *this;
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE const aiColor4t<TReal>& aiColor4t<TReal>::operator -= (const aiColor4t<TReal>& o) {
+ r -= o.r; g -= o.g; b -= o.b; a -= o.a;
+ return *this;
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE const aiColor4t<TReal>& aiColor4t<TReal>::operator *= (TReal f) {
+ r *= f; g *= f; b *= f; a *= f;
+ return *this;
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE const aiColor4t<TReal>& aiColor4t<TReal>::operator /= (TReal f) {
+ r /= f; g /= f; b /= f; a /= f;
+ return *this;
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE TReal aiColor4t<TReal>::operator[](unsigned int i) const {
+ switch ( i ) {
+ case 0:
+ return r;
+ case 1:
+ return g;
+ case 2:
+ return b;
+ default:
+ break;
+ }
+ return r;
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE TReal& aiColor4t<TReal>::operator[](unsigned int i) {
+ switch ( i ) {
+ case 0:
+ return r;
+ case 1:
+ return g;
+ case 2:
+ return b;
+ default:
+ break;
+ }
+ return r;
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE bool aiColor4t<TReal>::operator== (const aiColor4t<TReal>& other) const {
+ return r == other.r && g == other.g && b == other.b && a == other.a;
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE bool aiColor4t<TReal>::operator!= (const aiColor4t<TReal>& other) const {
+ return r != other.r || g != other.g || b != other.b || a != other.a;
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE bool aiColor4t<TReal>::operator< (const aiColor4t<TReal>& other) const {
+ return r < other.r || (
+ r == other.r && (
+ g < other.g || (
+ g == other.g && (
+ b < other.b || (
+ b == other.b && (
+ a < other.a
+ )
+ )
+ )
+ )
+ )
+ );
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE aiColor4t<TReal> operator + (const aiColor4t<TReal>& v1, const aiColor4t<TReal>& v2) {
+ return aiColor4t<TReal>( v1.r + v2.r, v1.g + v2.g, v1.b + v2.b, v1.a + v2.a);
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE aiColor4t<TReal> operator - (const aiColor4t<TReal>& v1, const aiColor4t<TReal>& v2) {
+ return aiColor4t<TReal>( v1.r - v2.r, v1.g - v2.g, v1.b - v2.b, v1.a - v2.a);
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE aiColor4t<TReal> operator * (const aiColor4t<TReal>& v1, const aiColor4t<TReal>& v2) {
+ return aiColor4t<TReal>( v1.r * v2.r, v1.g * v2.g, v1.b * v2.b, v1.a * v2.a);
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE aiColor4t<TReal> operator / (const aiColor4t<TReal>& v1, const aiColor4t<TReal>& v2) {
+ return aiColor4t<TReal>( v1.r / v2.r, v1.g / v2.g, v1.b / v2.b, v1.a / v2.a);
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE aiColor4t<TReal> operator * ( TReal f, const aiColor4t<TReal>& v) {
+ return aiColor4t<TReal>( f*v.r, f*v.g, f*v.b, f*v.a);
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE aiColor4t<TReal> operator * ( const aiColor4t<TReal>& v, TReal f) {
+ return aiColor4t<TReal>( f*v.r, f*v.g, f*v.b, f*v.a);
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE aiColor4t<TReal> operator / ( const aiColor4t<TReal>& v, TReal f) {
+ return v * (1/f);
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE aiColor4t<TReal> operator / ( TReal f,const aiColor4t<TReal>& v) {
+ return aiColor4t<TReal>(f,f,f,f)/v;
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE aiColor4t<TReal> operator + ( const aiColor4t<TReal>& v, TReal f) {
+ return aiColor4t<TReal>( f+v.r, f+v.g, f+v.b, f+v.a);
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE aiColor4t<TReal> operator - ( const aiColor4t<TReal>& v, TReal f) {
+ return aiColor4t<TReal>( v.r-f, v.g-f, v.b-f, v.a-f);
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE aiColor4t<TReal> operator + ( TReal f, const aiColor4t<TReal>& v) {
+ return aiColor4t<TReal>( f+v.r, f+v.g, f+v.b, f+v.a);
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE aiColor4t<TReal> operator - ( TReal f, const aiColor4t<TReal>& v) {
+ return aiColor4t<TReal>( f-v.r, f-v.g, f-v.b, f-v.a);
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+inline bool aiColor4t<TReal> :: IsBlack() const {
+ // The alpha component doesn't care here. black is black.
+ static const TReal epsilon = 10e-3f;
+ return std::fabs( r ) < epsilon && std::fabs( g ) < epsilon && std::fabs( b ) < epsilon;
+}
+
+#endif // __cplusplus
+#endif // AI_VECTOR3D_INL_INC
diff --git a/thirdparty/assimp/include/assimp/config.h.in b/thirdparty/assimp/include/assimp/config.h.in
new file mode 100644
index 0000000000..a37ff0b8c8
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/config.h.in
@@ -0,0 +1,992 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2018, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file config.h
+ * @brief Defines constants for configurable properties for the library
+ *
+ * Typically these properties are set via
+ * #Assimp::Importer::SetPropertyFloat,
+ * #Assimp::Importer::SetPropertyInteger or
+ * #Assimp::Importer::SetPropertyString,
+ * depending on the data type of a property. All properties have a
+ * default value. See the doc for the mentioned methods for more details.
+ *
+ * <br><br>
+ * The corresponding functions for use with the plain-c API are:
+ * #aiSetImportPropertyInteger,
+ * #aiSetImportPropertyFloat,
+ * #aiSetImportPropertyString
+ */
+#pragma once
+#ifndef AI_CONFIG_H_INC
+#define AI_CONFIG_H_INC
+
+
+// ###########################################################################
+// LIBRARY SETTINGS
+// General, global settings
+// ###########################################################################
+
+// ---------------------------------------------------------------------------
+/** @brief Enables time measurements.
+ *
+ * If enabled, measures the time needed for each part of the loading
+ * process (i.e. IO time, importing, postprocessing, ..) and dumps
+ * these timings to the DefaultLogger. See the @link perf Performance
+ * Page@endlink for more information on this topic.
+ *
+ * Property type: bool. Default value: false.
+ */
+#define AI_CONFIG_GLOB_MEASURE_TIME \
+ "GLOB_MEASURE_TIME"
+
+
+// ---------------------------------------------------------------------------
+/** @brief Global setting to disable generation of skeleton dummy meshes
+ *
+ * Skeleton dummy meshes are generated as a visualization aid in cases which
+ * the input data contains no geometry, but only animation data.
+ * Property data type: bool. Default value: false
+ */
+// ---------------------------------------------------------------------------
+#define AI_CONFIG_IMPORT_NO_SKELETON_MESHES \
+ "IMPORT_NO_SKELETON_MESHES"
+
+
+
+# if 0 // not implemented yet
+// ---------------------------------------------------------------------------
+/** @brief Set Assimp's multithreading policy.
+ *
+ * This setting is ignored if Assimp was built without boost.thread
+ * support (ASSIMP_BUILD_NO_THREADING, which is implied by ASSIMP_BUILD_BOOST_WORKAROUND).
+ * Possible values are: -1 to let Assimp decide what to do, 0 to disable
+ * multithreading entirely and any number larger than 0 to force a specific
+ * number of threads. Assimp is always free to ignore this settings, which is
+ * merely a hint. Usually, the default value (-1) will be fine. However, if
+ * Assimp is used concurrently from multiple user threads, it might be useful
+ * to limit each Importer instance to a specific number of cores.
+ *
+ * For more information, see the @link threading Threading page@endlink.
+ * Property type: int, default value: -1.
+ */
+#define AI_CONFIG_GLOB_MULTITHREADING \
+ "GLOB_MULTITHREADING"
+#endif
+
+// ###########################################################################
+// POST PROCESSING SETTINGS
+// Various stuff to fine-tune the behavior of a specific post processing step.
+// ###########################################################################
+
+
+// ---------------------------------------------------------------------------
+/** @brief Maximum bone count per mesh for the SplitbyBoneCount step.
+ *
+ * Meshes are split until the maximum number of bones is reached. The default
+ * value is AI_SBBC_DEFAULT_MAX_BONES, which may be altered at
+ * compile-time.
+ * Property data type: integer.
+ */
+// ---------------------------------------------------------------------------
+#define AI_CONFIG_PP_SBBC_MAX_BONES \
+ "PP_SBBC_MAX_BONES"
+
+
+// default limit for bone count
+#if (!defined AI_SBBC_DEFAULT_MAX_BONES)
+# define AI_SBBC_DEFAULT_MAX_BONES 60
+#endif
+
+
+// ---------------------------------------------------------------------------
+/** @brief Specifies the maximum angle that may be between two vertex tangents
+ * that their tangents and bi-tangents are smoothed.
+ *
+ * This applies to the CalcTangentSpace-Step. The angle is specified
+ * in degrees. The maximum value is 175.
+ * Property type: float. Default value: 45 degrees
+ */
+#define AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE \
+ "PP_CT_MAX_SMOOTHING_ANGLE"
+
+// ---------------------------------------------------------------------------
+/** @brief Source UV channel for tangent space computation.
+ *
+ * The specified channel must exist or an error will be raised.
+ * Property type: integer. Default value: 0
+ */
+// ---------------------------------------------------------------------------
+#define AI_CONFIG_PP_CT_TEXTURE_CHANNEL_INDEX \
+ "PP_CT_TEXTURE_CHANNEL_INDEX"
+
+// ---------------------------------------------------------------------------
+/** @brief Specifies the maximum angle that may be between two face normals
+ * at the same vertex position that their are smoothed together.
+ *
+ * Sometimes referred to as 'crease angle'.
+ * This applies to the GenSmoothNormals-Step. The angle is specified
+ * in degrees, so 180 is PI. The default value is 175 degrees (all vertex
+ * normals are smoothed). The maximum value is 175, too. Property type: float.
+ * Warning: setting this option may cause a severe loss of performance. The
+ * performance is unaffected if the #AI_CONFIG_FAVOUR_SPEED flag is set but
+ * the output quality may be reduced.
+ */
+#define AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE \
+ "PP_GSN_MAX_SMOOTHING_ANGLE"
+
+
+// ---------------------------------------------------------------------------
+/** @brief Sets the colormap (= palette) to be used to decode embedded
+ * textures in MDL (Quake or 3DGS) files.
+ *
+ * This must be a valid path to a file. The file is 768 (256*3) bytes
+ * large and contains RGB triplets for each of the 256 palette entries.
+ * The default value is colormap.lmp. If the file is not found,
+ * a default palette (from Quake 1) is used.
+ * Property type: string.
+ */
+#define AI_CONFIG_IMPORT_MDL_COLORMAP \
+ "IMPORT_MDL_COLORMAP"
+
+// ---------------------------------------------------------------------------
+/** @brief Configures the #aiProcess_RemoveRedundantMaterials step to
+ * keep materials matching a name in a given list.
+ *
+ * This is a list of 1 to n strings, ' ' serves as delimiter character.
+ * Identifiers containing whitespaces must be enclosed in *single*
+ * quotation marks. For example:<tt>
+ * "keep-me and_me_to anotherMaterialToBeKept \'name with whitespace\'"</tt>.
+ * If a material matches on of these names, it will not be modified or
+ * removed by the postprocessing step nor will other materials be replaced
+ * by a reference to it. <br>
+ * This option might be useful if you are using some magic material names
+ * to pass additional semantics through the content pipeline. This ensures
+ * they won't be optimized away, but a general optimization is still
+ * performed for materials not contained in the list.
+ * Property type: String. Default value: n/a
+ * @note Linefeeds, tabs or carriage returns are treated as whitespace.
+ * Material names are case sensitive.
+ */
+#define AI_CONFIG_PP_RRM_EXCLUDE_LIST \
+ "PP_RRM_EXCLUDE_LIST"
+
+// ---------------------------------------------------------------------------
+/** @brief Configures the #aiProcess_PreTransformVertices step to
+ * keep the scene hierarchy. Meshes are moved to worldspace, but
+ * no optimization is performed (read: meshes with equal materials are not
+ * joined. The total number of meshes won't change).
+ *
+ * This option could be of use for you if the scene hierarchy contains
+ * important additional information which you intend to parse.
+ * For rendering, you can still render all meshes in the scene without
+ * any transformations.
+ * Property type: bool. Default value: false.
+ */
+#define AI_CONFIG_PP_PTV_KEEP_HIERARCHY \
+ "PP_PTV_KEEP_HIERARCHY"
+
+// ---------------------------------------------------------------------------
+/** @brief Configures the #aiProcess_PreTransformVertices step to normalize
+ * all vertex components into the [-1,1] range. That is, a bounding box
+ * for the whole scene is computed, the maximum component is taken and all
+ * meshes are scaled appropriately (uniformly of course!).
+ * This might be useful if you don't know the spatial dimension of the input
+ * data*/
+#define AI_CONFIG_PP_PTV_NORMALIZE \
+ "PP_PTV_NORMALIZE"
+
+// ---------------------------------------------------------------------------
+/** @brief Configures the #aiProcess_PreTransformVertices step to use
+ * a users defined matrix as the scene root node transformation before
+ * transforming vertices.
+ * Property type: bool. Default value: false.
+ */
+#define AI_CONFIG_PP_PTV_ADD_ROOT_TRANSFORMATION \
+ "PP_PTV_ADD_ROOT_TRANSFORMATION"
+
+// ---------------------------------------------------------------------------
+/** @brief Configures the #aiProcess_PreTransformVertices step to use
+ * a users defined matrix as the scene root node transformation before
+ * transforming vertices. This property correspond to the 'a1' component
+ * of the transformation matrix.
+ * Property type: aiMatrix4x4.
+ */
+#define AI_CONFIG_PP_PTV_ROOT_TRANSFORMATION \
+ "PP_PTV_ROOT_TRANSFORMATION"
+
+// ---------------------------------------------------------------------------
+/** @brief Configures the #aiProcess_FindDegenerates step to
+ * remove degenerated primitives from the import - immediately.
+ *
+ * The default behaviour converts degenerated triangles to lines and
+ * degenerated lines to points. See the documentation to the
+ * #aiProcess_FindDegenerates step for a detailed example of the various ways
+ * to get rid of these lines and points if you don't want them.
+ * Property type: bool. Default value: false.
+ */
+#define AI_CONFIG_PP_FD_REMOVE \
+ "PP_FD_REMOVE"
+
+// ---------------------------------------------------------------------------
+/**
+ * @brief Configures the #aiProcess_FindDegenerates to check the area of a
+ * trinagle to be greates than e-6. If this is not the case the triangle will
+ * be removed if #AI_CONFIG_PP_FD_REMOVE is set to true.
+ */
+#define AI_CONFIG_PP_FD_CHECKAREA \
+ "PP_FD_CHECKAREA"
+
+// ---------------------------------------------------------------------------
+/** @brief Configures the #aiProcess_OptimizeGraph step to preserve nodes
+ * matching a name in a given list.
+ *
+ * This is a list of 1 to n strings, ' ' serves as delimiter character.
+ * Identifiers containing whitespaces must be enclosed in *single*
+ * quotation marks. For example:<tt>
+ * "keep-me and_me_to anotherNodeToBeKept \'name with whitespace\'"</tt>.
+ * If a node matches on of these names, it will not be modified or
+ * removed by the postprocessing step.<br>
+ * This option might be useful if you are using some magic node names
+ * to pass additional semantics through the content pipeline. This ensures
+ * they won't be optimized away, but a general optimization is still
+ * performed for nodes not contained in the list.
+ * Property type: String. Default value: n/a
+ * @note Linefeeds, tabs or carriage returns are treated as whitespace.
+ * Node names are case sensitive.
+ */
+#define AI_CONFIG_PP_OG_EXCLUDE_LIST \
+ "PP_OG_EXCLUDE_LIST"
+
+// ---------------------------------------------------------------------------
+/** @brief Set the maximum number of triangles in a mesh.
+ *
+ * This is used by the "SplitLargeMeshes" PostProcess-Step to determine
+ * whether a mesh must be split or not.
+ * @note The default value is AI_SLM_DEFAULT_MAX_TRIANGLES
+ * Property type: integer.
+ */
+#define AI_CONFIG_PP_SLM_TRIANGLE_LIMIT \
+ "PP_SLM_TRIANGLE_LIMIT"
+
+// default value for AI_CONFIG_PP_SLM_TRIANGLE_LIMIT
+#if (!defined AI_SLM_DEFAULT_MAX_TRIANGLES)
+# define AI_SLM_DEFAULT_MAX_TRIANGLES 1000000
+#endif
+
+// ---------------------------------------------------------------------------
+/** @brief Set the maximum number of vertices in a mesh.
+ *
+ * This is used by the "SplitLargeMeshes" PostProcess-Step to determine
+ * whether a mesh must be split or not.
+ * @note The default value is AI_SLM_DEFAULT_MAX_VERTICES
+ * Property type: integer.
+ */
+#define AI_CONFIG_PP_SLM_VERTEX_LIMIT \
+ "PP_SLM_VERTEX_LIMIT"
+
+// default value for AI_CONFIG_PP_SLM_VERTEX_LIMIT
+#if (!defined AI_SLM_DEFAULT_MAX_VERTICES)
+# define AI_SLM_DEFAULT_MAX_VERTICES 1000000
+#endif
+
+// ---------------------------------------------------------------------------
+/** @brief Set the maximum number of bones affecting a single vertex
+ *
+ * This is used by the #aiProcess_LimitBoneWeights PostProcess-Step.
+ * @note The default value is AI_LMW_MAX_WEIGHTS
+ * Property type: integer.*/
+#define AI_CONFIG_PP_LBW_MAX_WEIGHTS \
+ "PP_LBW_MAX_WEIGHTS"
+
+// default value for AI_CONFIG_PP_LBW_MAX_WEIGHTS
+#if (!defined AI_LMW_MAX_WEIGHTS)
+# define AI_LMW_MAX_WEIGHTS 0x4
+#endif // !! AI_LMW_MAX_WEIGHTS
+
+// ---------------------------------------------------------------------------
+/** @brief Lower the deboning threshold in order to remove more bones.
+ *
+ * This is used by the #aiProcess_Debone PostProcess-Step.
+ * @note The default value is AI_DEBONE_THRESHOLD
+ * Property type: float.*/
+#define AI_CONFIG_PP_DB_THRESHOLD \
+ "PP_DB_THRESHOLD"
+
+// default value for AI_CONFIG_PP_LBW_MAX_WEIGHTS
+#if (!defined AI_DEBONE_THRESHOLD)
+# define AI_DEBONE_THRESHOLD 1.0f
+#endif // !! AI_DEBONE_THRESHOLD
+
+// ---------------------------------------------------------------------------
+/** @brief Require all bones qualify for deboning before removing any
+ *
+ * This is used by the #aiProcess_Debone PostProcess-Step.
+ * @note The default value is 0
+ * Property type: bool.*/
+#define AI_CONFIG_PP_DB_ALL_OR_NONE \
+ "PP_DB_ALL_OR_NONE"
+
+/** @brief Default value for the #AI_CONFIG_PP_ICL_PTCACHE_SIZE property
+ */
+#ifndef PP_ICL_PTCACHE_SIZE
+# define PP_ICL_PTCACHE_SIZE 12
+#endif
+
+// ---------------------------------------------------------------------------
+/** @brief Set the size of the post-transform vertex cache to optimize the
+ * vertices for. This configures the #aiProcess_ImproveCacheLocality step.
+ *
+ * The size is given in vertices. Of course you can't know how the vertex
+ * format will exactly look like after the import returns, but you can still
+ * guess what your meshes will probably have.
+ * @note The default value is #PP_ICL_PTCACHE_SIZE. That results in slight
+ * performance improvements for most nVidia/AMD cards since 2002.
+ * Property type: integer.
+ */
+#define AI_CONFIG_PP_ICL_PTCACHE_SIZE "PP_ICL_PTCACHE_SIZE"
+
+// ---------------------------------------------------------------------------
+/** @brief Enumerates components of the aiScene and aiMesh data structures
+ * that can be excluded from the import using the #aiProcess_RemoveComponent step.
+ *
+ * See the documentation to #aiProcess_RemoveComponent for more details.
+ */
+enum aiComponent
+{
+ /** Normal vectors */
+#ifdef SWIG
+ aiComponent_NORMALS = 0x2,
+#else
+ aiComponent_NORMALS = 0x2u,
+#endif
+
+ /** Tangents and bitangents go always together ... */
+#ifdef SWIG
+ aiComponent_TANGENTS_AND_BITANGENTS = 0x4,
+#else
+ aiComponent_TANGENTS_AND_BITANGENTS = 0x4u,
+#endif
+
+ /** ALL color sets
+ * Use aiComponent_COLORn(N) to specify the N'th set */
+ aiComponent_COLORS = 0x8,
+
+ /** ALL texture UV sets
+ * aiComponent_TEXCOORDn(N) to specify the N'th set */
+ aiComponent_TEXCOORDS = 0x10,
+
+ /** Removes all bone weights from all meshes.
+ * The scenegraph nodes corresponding to the bones are NOT removed.
+ * use the #aiProcess_OptimizeGraph step to do this */
+ aiComponent_BONEWEIGHTS = 0x20,
+
+ /** Removes all node animations (aiScene::mAnimations).
+ * The corresponding scenegraph nodes are NOT removed.
+ * use the #aiProcess_OptimizeGraph step to do this */
+ aiComponent_ANIMATIONS = 0x40,
+
+ /** Removes all embedded textures (aiScene::mTextures) */
+ aiComponent_TEXTURES = 0x80,
+
+ /** Removes all light sources (aiScene::mLights).
+ * The corresponding scenegraph nodes are NOT removed.
+ * use the #aiProcess_OptimizeGraph step to do this */
+ aiComponent_LIGHTS = 0x100,
+
+ /** Removes all cameras (aiScene::mCameras).
+ * The corresponding scenegraph nodes are NOT removed.
+ * use the #aiProcess_OptimizeGraph step to do this */
+ aiComponent_CAMERAS = 0x200,
+
+ /** Removes all meshes (aiScene::mMeshes). */
+ aiComponent_MESHES = 0x400,
+
+ /** Removes all materials. One default material will
+ * be generated, so aiScene::mNumMaterials will be 1. */
+ aiComponent_MATERIALS = 0x800,
+
+
+ /** This value is not used. It is just there to force the
+ * compiler to map this enum to a 32 Bit integer. */
+#ifndef SWIG
+ _aiComponent_Force32Bit = 0x9fffffff
+#endif
+};
+
+// Remove a specific color channel 'n'
+#define aiComponent_COLORSn(n) (1u << (n+20u))
+
+// Remove a specific UV channel 'n'
+#define aiComponent_TEXCOORDSn(n) (1u << (n+25u))
+
+// ---------------------------------------------------------------------------
+/** @brief Input parameter to the #aiProcess_RemoveComponent step:
+ * Specifies the parts of the data structure to be removed.
+ *
+ * See the documentation to this step for further details. The property
+ * is expected to be an integer, a bitwise combination of the
+ * #aiComponent flags defined above in this header. The default
+ * value is 0. Important: if no valid mesh is remaining after the
+ * step has been executed (e.g you thought it was funny to specify ALL
+ * of the flags defined above) the import FAILS. Mainly because there is
+ * no data to work on anymore ...
+ */
+#define AI_CONFIG_PP_RVC_FLAGS \
+ "PP_RVC_FLAGS"
+
+// ---------------------------------------------------------------------------
+/** @brief Input parameter to the #aiProcess_SortByPType step:
+ * Specifies which primitive types are removed by the step.
+ *
+ * This is a bitwise combination of the aiPrimitiveType flags.
+ * Specifying all of them is illegal, of course. A typical use would
+ * be to exclude all line and point meshes from the import. This
+ * is an integer property, its default value is 0.
+ */
+#define AI_CONFIG_PP_SBP_REMOVE \
+ "PP_SBP_REMOVE"
+
+// ---------------------------------------------------------------------------
+/** @brief Input parameter to the #aiProcess_FindInvalidData step:
+ * Specifies the floating-point accuracy for animation values. The step
+ * checks for animation tracks where all frame values are absolutely equal
+ * and removes them. This tweakable controls the epsilon for floating-point
+ * comparisons - two keys are considered equal if the invariant
+ * abs(n0-n1)>epsilon holds true for all vector respectively quaternion
+ * components. The default value is 0.f - comparisons are exact then.
+ */
+#define AI_CONFIG_PP_FID_ANIM_ACCURACY \
+ "PP_FID_ANIM_ACCURACY"
+
+// ---------------------------------------------------------------------------
+/** @brief Input parameter to the #aiProcess_FindInvalidData step:
+ * Set to true to ignore texture coordinates. This may be useful if you have
+ * to assign different kind of textures like one for the summer or one for the winter.
+ */
+#define AI_CONFIG_PP_FID_IGNORE_TEXTURECOORDS \
+ "PP_FID_IGNORE_TEXTURECOORDS"
+
+// TransformUVCoords evaluates UV scalings
+#define AI_UVTRAFO_SCALING 0x1
+
+// TransformUVCoords evaluates UV rotations
+#define AI_UVTRAFO_ROTATION 0x2
+
+// TransformUVCoords evaluates UV translation
+#define AI_UVTRAFO_TRANSLATION 0x4
+
+// Everything baked together -> default value
+#define AI_UVTRAFO_ALL (AI_UVTRAFO_SCALING | AI_UVTRAFO_ROTATION | AI_UVTRAFO_TRANSLATION)
+
+// ---------------------------------------------------------------------------
+/** @brief Input parameter to the #aiProcess_TransformUVCoords step:
+ * Specifies which UV transformations are evaluated.
+ *
+ * This is a bitwise combination of the AI_UVTRAFO_XXX flags (integer
+ * property, of course). By default all transformations are enabled
+ * (AI_UVTRAFO_ALL).
+ */
+#define AI_CONFIG_PP_TUV_EVALUATE \
+ "PP_TUV_EVALUATE"
+
+// ---------------------------------------------------------------------------
+/** @brief A hint to assimp to favour speed against import quality.
+ *
+ * Enabling this option may result in faster loading, but it needn't.
+ * It represents just a hint to loaders and post-processing steps to use
+ * faster code paths, if possible.
+ * This property is expected to be an integer, != 0 stands for true.
+ * The default value is 0.
+ */
+#define AI_CONFIG_FAVOUR_SPEED \
+ "FAVOUR_SPEED"
+
+
+// ###########################################################################
+// IMPORTER SETTINGS
+// Various stuff to fine-tune the behaviour of specific importer plugins.
+// ###########################################################################
+
+
+// ---------------------------------------------------------------------------
+/** @brief Set whether the fbx importer will merge all geometry layers present
+ * in the source file or take only the first.
+ *
+ * The default value is true (1)
+ * Property type: bool
+ */
+#define AI_CONFIG_IMPORT_FBX_READ_ALL_GEOMETRY_LAYERS \
+ "IMPORT_FBX_READ_ALL_GEOMETRY_LAYERS"
+
+// ---------------------------------------------------------------------------
+/** @brief Set whether the fbx importer will read all materials present in the
+ * source file or take only the referenced materials.
+ *
+ * This is void unless IMPORT_FBX_READ_MATERIALS=1.
+ *
+ * The default value is false (0)
+ * Property type: bool
+ */
+#define AI_CONFIG_IMPORT_FBX_READ_ALL_MATERIALS \
+ "IMPORT_FBX_READ_ALL_MATERIALS"
+
+// ---------------------------------------------------------------------------
+/** @brief Set whether the fbx importer will read materials.
+ *
+ * The default value is true (1)
+ * Property type: bool
+ */
+#define AI_CONFIG_IMPORT_FBX_READ_MATERIALS \
+ "IMPORT_FBX_READ_MATERIALS"
+
+// ---------------------------------------------------------------------------
+/** @brief Set whether the fbx importer will read embedded textures.
+ *
+ * The default value is true (1)
+ * Property type: bool
+ */
+#define AI_CONFIG_IMPORT_FBX_READ_TEXTURES \
+ "IMPORT_FBX_READ_TEXTURES"
+
+// ---------------------------------------------------------------------------
+/** @brief Set whether the fbx importer will read cameras.
+ *
+ * The default value is true (1)
+ * Property type: bool
+ */
+#define AI_CONFIG_IMPORT_FBX_READ_CAMERAS \
+ "IMPORT_FBX_READ_CAMERAS"
+
+// ---------------------------------------------------------------------------
+/** @brief Set whether the fbx importer will read light sources.
+ *
+ * The default value is true (1)
+ * Property type: bool
+ */
+#define AI_CONFIG_IMPORT_FBX_READ_LIGHTS \
+ "IMPORT_FBX_READ_LIGHTS"
+
+// ---------------------------------------------------------------------------
+/** @brief Set whether the fbx importer will read animations.
+ *
+ * The default value is true (1)
+ * Property type: bool
+ */
+#define AI_CONFIG_IMPORT_FBX_READ_ANIMATIONS \
+ "IMPORT_FBX_READ_ANIMATIONS"
+
+// ---------------------------------------------------------------------------
+/** @brief Set whether the fbx importer will act in strict mode in which only
+ * FBX 2013 is supported and any other sub formats are rejected. FBX 2013
+ * is the primary target for the importer, so this format is best
+ * supported and well-tested.
+ *
+ * The default value is false (0)
+ * Property type: bool
+ */
+#define AI_CONFIG_IMPORT_FBX_STRICT_MODE \
+ "IMPORT_FBX_STRICT_MODE"
+
+// ---------------------------------------------------------------------------
+/** @brief Set whether the fbx importer will preserve pivot points for
+ * transformations (as extra nodes). If set to false, pivots and offsets
+ * will be evaluated whenever possible.
+ *
+ * The default value is true (1)
+ * Property type: bool
+ */
+#define AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS \
+ "IMPORT_FBX_PRESERVE_PIVOTS"
+
+// ---------------------------------------------------------------------------
+/** @brief Specifies whether the importer will drop empty animation curves or
+ * animation curves which match the bind pose transformation over their
+ * entire defined range.
+ *
+ * The default value is true (1)
+ * Property type: bool
+ */
+#define AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES \
+ "IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES"
+
+// ---------------------------------------------------------------------------
+/** @brief Set whether the fbx importer will use the legacy embedded texture naming.
+*
+* The default value is false (0)
+* Property type: bool
+*/
+#define AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING \
+ "AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING"
+
+// ---------------------------------------------------------------------------
+/** @brief Set the vertex animation keyframe to be imported
+ *
+ * ASSIMP does not support vertex keyframes (only bone animation is supported).
+ * The library reads only one frame of models with vertex animations.
+ * By default this is the first frame.
+ * \note The default value is 0. This option applies to all importers.
+ * However, it is also possible to override the global setting
+ * for a specific loader. You can use the AI_CONFIG_IMPORT_XXX_KEYFRAME
+ * options (where XXX is a placeholder for the file format for which you
+ * want to override the global setting).
+ * Property type: integer.
+ */
+#define AI_CONFIG_IMPORT_GLOBAL_KEYFRAME "IMPORT_GLOBAL_KEYFRAME"
+
+#define AI_CONFIG_IMPORT_MD3_KEYFRAME "IMPORT_MD3_KEYFRAME"
+#define AI_CONFIG_IMPORT_MD2_KEYFRAME "IMPORT_MD2_KEYFRAME"
+#define AI_CONFIG_IMPORT_MDL_KEYFRAME "IMPORT_MDL_KEYFRAME"
+#define AI_CONFIG_IMPORT_MDC_KEYFRAME "IMPORT_MDC_KEYFRAME"
+#define AI_CONFIG_IMPORT_SMD_KEYFRAME "IMPORT_SMD_KEYFRAME"
+#define AI_CONFIG_IMPORT_UNREAL_KEYFRAME "IMPORT_UNREAL_KEYFRAME"
+
+// ---------------------------------------------------------------------------
+/** Smd load multiple animations
+ *
+ * Property type: bool. Default value: true.
+ */
+#define AI_CONFIG_IMPORT_SMD_LOAD_ANIMATION_LIST "IMPORT_SMD_LOAD_ANIMATION_LIST"
+
+// ---------------------------------------------------------------------------
+/** @brief Configures the AC loader to collect all surfaces which have the
+ * "Backface cull" flag set in separate meshes.
+ *
+ * Property type: bool. Default value: true.
+ */
+#define AI_CONFIG_IMPORT_AC_SEPARATE_BFCULL \
+ "IMPORT_AC_SEPARATE_BFCULL"
+
+// ---------------------------------------------------------------------------
+/** @brief Configures whether the AC loader evaluates subdivision surfaces (
+ * indicated by the presence of the 'subdiv' attribute in the file). By
+ * default, Assimp performs the subdivision using the standard
+ * Catmull-Clark algorithm
+ *
+ * * Property type: bool. Default value: true.
+ */
+#define AI_CONFIG_IMPORT_AC_EVAL_SUBDIVISION \
+ "IMPORT_AC_EVAL_SUBDIVISION"
+
+// ---------------------------------------------------------------------------
+/** @brief Configures the UNREAL 3D loader to separate faces with different
+ * surface flags (e.g. two-sided vs. single-sided).
+ *
+ * * Property type: bool. Default value: true.
+ */
+#define AI_CONFIG_IMPORT_UNREAL_HANDLE_FLAGS \
+ "UNREAL_HANDLE_FLAGS"
+
+// ---------------------------------------------------------------------------
+/** @brief Configures the terragen import plugin to compute uv's for
+ * terrains, if not given. Furthermore a default texture is assigned.
+ *
+ * UV coordinates for terrains are so simple to compute that you'll usually
+ * want to compute them on your own, if you need them. This option is intended
+ * for model viewers which want to offer an easy way to apply textures to
+ * terrains.
+ * * Property type: bool. Default value: false.
+ */
+#define AI_CONFIG_IMPORT_TER_MAKE_UVS \
+ "IMPORT_TER_MAKE_UVS"
+
+// ---------------------------------------------------------------------------
+/** @brief Configures the ASE loader to always reconstruct normal vectors
+ * basing on the smoothing groups loaded from the file.
+ *
+ * Some ASE files have carry invalid normals, other don't.
+ * * Property type: bool. Default value: true.
+ */
+#define AI_CONFIG_IMPORT_ASE_RECONSTRUCT_NORMALS \
+ "IMPORT_ASE_RECONSTRUCT_NORMALS"
+
+// ---------------------------------------------------------------------------
+/** @brief Configures the M3D loader to detect and process multi-part
+ * Quake player models.
+ *
+ * These models usually consist of 3 files, lower.md3, upper.md3 and
+ * head.md3. If this property is set to true, Assimp will try to load and
+ * combine all three files if one of them is loaded.
+ * Property type: bool. Default value: true.
+ */
+#define AI_CONFIG_IMPORT_MD3_HANDLE_MULTIPART \
+ "IMPORT_MD3_HANDLE_MULTIPART"
+
+// ---------------------------------------------------------------------------
+/** @brief Tells the MD3 loader which skin files to load.
+ *
+ * When loading MD3 files, Assimp checks whether a file
+ * [md3_file_name]_[skin_name].skin is existing. These files are used by
+ * Quake III to be able to assign different skins (e.g. red and blue team)
+ * to models. 'default', 'red', 'blue' are typical skin names.
+ * Property type: String. Default value: "default".
+ */
+#define AI_CONFIG_IMPORT_MD3_SKIN_NAME \
+ "IMPORT_MD3_SKIN_NAME"
+
+// ---------------------------------------------------------------------------
+/** @brief Specify the Quake 3 shader file to be used for a particular
+ * MD3 file. This can also be a search path.
+ *
+ * By default Assimp's behaviour is as follows: If a MD3 file
+ * <tt>any_path/models/any_q3_subdir/model_name/file_name.md3</tt> is
+ * loaded, the library tries to locate the corresponding shader file in
+ * <tt>any_path/scripts/model_name.shader</tt>. This property overrides this
+ * behaviour. It can either specify a full path to the shader to be loaded
+ * or alternatively the path (relative or absolute) to the directory where
+ * the shaders for all MD3s to be loaded reside. Assimp attempts to open
+ * <tt>IMPORT_MD3_SHADER_SRC/model_name.shader</tt> first, <tt>IMPORT_MD3_SHADER_SRC/file_name.shader</tt>
+ * is the fallback file. Note that IMPORT_MD3_SHADER_SRC should have a terminal (back)slash.
+ * Property type: String. Default value: n/a.
+ */
+#define AI_CONFIG_IMPORT_MD3_SHADER_SRC \
+ "IMPORT_MD3_SHADER_SRC"
+
+// ---------------------------------------------------------------------------
+/** @brief Configures the LWO loader to load just one layer from the model.
+ *
+ * LWO files consist of layers and in some cases it could be useful to load
+ * only one of them. This property can be either a string - which specifies
+ * the name of the layer - or an integer - the index of the layer. If the
+ * property is not set the whole LWO model is loaded. Loading fails if the
+ * requested layer is not available. The layer index is zero-based and the
+ * layer name may not be empty.<br>
+ * Property type: Integer. Default value: all layers are loaded.
+ */
+#define AI_CONFIG_IMPORT_LWO_ONE_LAYER_ONLY \
+ "IMPORT_LWO_ONE_LAYER_ONLY"
+
+// ---------------------------------------------------------------------------
+/** @brief Configures the MD5 loader to not load the MD5ANIM file for
+ * a MD5MESH file automatically.
+ *
+ * The default strategy is to look for a file with the same name but the
+ * MD5ANIM extension in the same directory. If it is found, it is loaded
+ * and combined with the MD5MESH file. This configuration option can be
+ * used to disable this behaviour.
+ *
+ * * Property type: bool. Default value: false.
+ */
+#define AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD \
+ "IMPORT_MD5_NO_ANIM_AUTOLOAD"
+
+// ---------------------------------------------------------------------------
+/** @brief Defines the begin of the time range for which the LWS loader
+ * evaluates animations and computes aiNodeAnim's.
+ *
+ * Assimp provides full conversion of LightWave's envelope system, including
+ * pre and post conditions. The loader computes linearly subsampled animation
+ * chanels with the frame rate given in the LWS file. This property defines
+ * the start time. Note: animation channels are only generated if a node
+ * has at least one envelope with more tan one key assigned. This property.
+ * is given in frames, '0' is the first frame. By default, if this property
+ * is not set, the importer takes the animation start from the input LWS
+ * file ('FirstFrame' line)<br>
+ * Property type: Integer. Default value: taken from file.
+ *
+ * @see AI_CONFIG_IMPORT_LWS_ANIM_END - end of the imported time range
+ */
+#define AI_CONFIG_IMPORT_LWS_ANIM_START \
+ "IMPORT_LWS_ANIM_START"
+#define AI_CONFIG_IMPORT_LWS_ANIM_END \
+ "IMPORT_LWS_ANIM_END"
+
+// ---------------------------------------------------------------------------
+/** @brief Defines the output frame rate of the IRR loader.
+ *
+ * IRR animations are difficult to convert for Assimp and there will
+ * always be a loss of quality. This setting defines how many keys per second
+ * are returned by the converter.<br>
+ * Property type: integer. Default value: 100
+ */
+#define AI_CONFIG_IMPORT_IRR_ANIM_FPS \
+ "IMPORT_IRR_ANIM_FPS"
+
+// ---------------------------------------------------------------------------
+/** @brief Ogre Importer will try to find referenced materials from this file.
+ *
+ * Ogre meshes reference with material names, this does not tell Assimp the file
+ * where it is located in. Assimp will try to find the source file in the following
+ * order: <material-name>.material, <mesh-filename-base>.material and
+ * lastly the material name defined by this config property.
+ * <br>
+ * Property type: String. Default value: Scene.material.
+ */
+#define AI_CONFIG_IMPORT_OGRE_MATERIAL_FILE \
+ "IMPORT_OGRE_MATERIAL_FILE"
+
+// ---------------------------------------------------------------------------
+/** @brief Ogre Importer detect the texture usage from its filename.
+ *
+ * Ogre material texture units do not define texture type, the textures usage
+ * depends on the used shader or Ogre's fixed pipeline. If this config property
+ * is true Assimp will try to detect the type from the textures filename postfix:
+ * _n, _nrm, _nrml, _normal, _normals and _normalmap for normal map, _s, _spec,
+ * _specular and _specularmap for specular map, _l, _light, _lightmap, _occ
+ * and _occlusion for light map, _disp and _displacement for displacement map.
+ * The matching is case insensitive. Post fix is taken between the last
+ * underscore and the last period.
+ * Default behavior is to detect type from lower cased texture unit name by
+ * matching against: normalmap, specularmap, lightmap and displacementmap.
+ * For both cases if no match is found aiTextureType_DIFFUSE is used.
+ * <br>
+ * Property type: Bool. Default value: false.
+ */
+#define AI_CONFIG_IMPORT_OGRE_TEXTURETYPE_FROM_FILENAME \
+ "IMPORT_OGRE_TEXTURETYPE_FROM_FILENAME"
+
+ /** @brief Specifies whether the Android JNI asset extraction is supported.
+ *
+ * Turn on this option if you want to manage assets in native
+ * Android application without having to keep the internal directory and asset
+ * manager pointer.
+ */
+ #define AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT "AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT"
+
+// ---------------------------------------------------------------------------
+/** @brief Specifies whether the IFC loader skips over IfcSpace elements.
+ *
+ * IfcSpace elements (and their geometric representations) are used to
+ * represent, well, free space in a building storey.<br>
+ * Property type: Bool. Default value: true.
+ */
+#define AI_CONFIG_IMPORT_IFC_SKIP_SPACE_REPRESENTATIONS "IMPORT_IFC_SKIP_SPACE_REPRESENTATIONS"
+
+// ---------------------------------------------------------------------------
+/** @brief Specifies whether the IFC loader will use its own, custom triangulation
+ * algorithm to triangulate wall and floor meshes.
+ *
+ * If this property is set to false, walls will be either triangulated by
+ * #aiProcess_Triangulate or will be passed through as huge polygons with
+ * faked holes (i.e. holes that are connected with the outer boundary using
+ * a dummy edge). It is highly recommended to set this property to true
+ * if you want triangulated data because #aiProcess_Triangulate is known to
+ * have problems with the kind of polygons that the IFC loader spits out for
+ * complicated meshes.
+ * Property type: Bool. Default value: true.
+ */
+#define AI_CONFIG_IMPORT_IFC_CUSTOM_TRIANGULATION "IMPORT_IFC_CUSTOM_TRIANGULATION"
+
+// ---------------------------------------------------------------------------
+/** @brief Set the tessellation conic angle for IFC smoothing curves.
+ *
+ * This is used by the IFC importer to determine the tessellation parameter
+ * for smoothing curves.
+ * @note The default value is AI_IMPORT_IFC_DEFAULT_SMOOTHING_ANGLE and the
+ * accepted values are in range [5.0, 120.0].
+ * Property type: Float.
+ */
+#define AI_CONFIG_IMPORT_IFC_SMOOTHING_ANGLE "IMPORT_IFC_SMOOTHING_ANGLE"
+
+// default value for AI_CONFIG_IMPORT_IFC_SMOOTHING_ANGLE
+#if (!defined AI_IMPORT_IFC_DEFAULT_SMOOTHING_ANGLE)
+# define AI_IMPORT_IFC_DEFAULT_SMOOTHING_ANGLE 10.0f
+#endif
+
+// ---------------------------------------------------------------------------
+/** @brief Set the tessellation for IFC cylindrical shapes.
+ *
+ * This is used by the IFC importer to determine the tessellation parameter
+ * for cylindrical shapes, i.e. the number of segments used to approximate a circle.
+ * @note The default value is AI_IMPORT_IFC_DEFAULT_CYLINDRICAL_TESSELLATION and the
+ * accepted values are in range [3, 180].
+ * Property type: Integer.
+ */
+#define AI_CONFIG_IMPORT_IFC_CYLINDRICAL_TESSELLATION "IMPORT_IFC_CYLINDRICAL_TESSELLATION"
+
+// default value for AI_CONFIG_IMPORT_IFC_CYLINDRICAL_TESSELLATION
+#if (!defined AI_IMPORT_IFC_DEFAULT_CYLINDRICAL_TESSELLATION)
+# define AI_IMPORT_IFC_DEFAULT_CYLINDRICAL_TESSELLATION 32
+#endif
+
+// ---------------------------------------------------------------------------
+/** @brief Specifies whether the Collada loader will ignore the provided up direction.
+ *
+ * If this property is set to true, the up direction provided in the file header will
+ * be ignored and the file will be loaded as is.
+ * Property type: Bool. Default value: false.
+ */
+#define AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION "IMPORT_COLLADA_IGNORE_UP_DIRECTION"
+
+// ---------------------------------------------------------------------------
+/** @brief Specifies whether the Collada loader should use Collada names as node names.
+ *
+ * If this property is set to true, the Collada names will be used as the
+ * node name. The default is to use the id tag (resp. sid tag, if no id tag is present)
+ * instead.
+ * Property type: Bool. Default value: false.
+ */
+#define AI_CONFIG_IMPORT_COLLADA_USE_COLLADA_NAMES "IMPORT_COLLADA_USE_COLLADA_NAMES"
+
+// ---------- All the Export defines ------------
+
+/** @brief Specifies the xfile use double for real values of float
+ *
+ * Property type: Bool. Default value: false.
+ */
+
+#define AI_CONFIG_EXPORT_XFILE_64BIT "EXPORT_XFILE_64BIT"
+
+/**
+ *
+ */
+#define AI_CONFIG_EXPORT_POINT_CLOUDS "EXPORT_POINT_CLOUDS"
+
+/**
+ * @brief Specifies a gobal key factor for scale, float value
+ */
+#define AI_CONFIG_GLOBAL_SCALE_FACTOR_KEY "GLOBAL_SCALE_FACTOR"
+
+#if (!defined AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT)
+# define AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT 1.0f
+#endif // !! AI_DEBONE_THRESHOLD
+
+// ---------- All the Build/Compile-time defines ------------
+
+/** @brief Specifies if double precision is supported inside assimp
+ *
+ * Property type: Bool. Default value: undefined.
+ */
+
+#cmakedefine ASSIMP_DOUBLE_PRECISION 1
+
+#endif // !! AI_CONFIG_H_INC
diff --git a/thirdparty/assimp/include/assimp/defs.h b/thirdparty/assimp/include/assimp/defs.h
new file mode 100644
index 0000000000..4a177e3c3e
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/defs.h
@@ -0,0 +1,303 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file defs.h
+ * @brief Assimp build configuration setup. See the notes in the comment
+ * blocks to find out how to customize _your_ Assimp build.
+ */
+
+#pragma once
+#ifndef AI_DEFINES_H_INC
+#define AI_DEFINES_H_INC
+
+#include <assimp/config.h>
+
+//////////////////////////////////////////////////////////////////////////
+/* Define ASSIMP_BUILD_NO_XX_IMPORTER to disable a specific
+ * file format loader. The loader is be excluded from the
+ * build in this case. 'XX' stands for the most common file
+ * extension of the file format. E.g.:
+ * ASSIMP_BUILD_NO_X_IMPORTER disables the X loader.
+ *
+ * If you're unsure about that, take a look at the implementation of the
+ * import plugin you wish to disable. You'll find the right define in the
+ * first lines of the corresponding unit.
+ *
+ * Other (mixed) configuration switches are listed here:
+ * ASSIMP_BUILD_NO_COMPRESSED_X
+ * - Disable support for compressed X files (zip)
+ * ASSIMP_BUILD_NO_COMPRESSED_BLEND
+ * - Disable support for compressed Blender files (zip)
+ * ASSIMP_BUILD_NO_COMPRESSED_IFC
+ * - Disable support for IFCZIP files (unzip)
+ */
+//////////////////////////////////////////////////////////////////////////
+
+#ifndef ASSIMP_BUILD_NO_COMPRESSED_X
+# define ASSIMP_BUILD_NEED_Z_INFLATE
+#endif
+
+#ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND
+# define ASSIMP_BUILD_NEED_Z_INFLATE
+#endif
+
+#ifndef ASSIMP_BUILD_NO_COMPRESSED_IFC
+# define ASSIMP_BUILD_NEED_Z_INFLATE
+# define ASSIMP_BUILD_NEED_UNZIP
+#endif
+
+#ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER
+# define ASSIMP_BUILD_NEED_Z_INFLATE
+# define ASSIMP_BUILD_NEED_UNZIP
+#endif
+
+//////////////////////////////////////////////////////////////////////////
+/* Define ASSIMP_BUILD_NO_XX_PROCESS to disable a specific
+ * post processing step. This is the current list of process names ('XX'):
+ * CALCTANGENTS
+ * JOINVERTICES
+ * TRIANGULATE
+ * DROPFACENORMALS
+ * GENFACENORMALS
+ * GENVERTEXNORMALS
+ * REMOVEVC
+ * SPLITLARGEMESHES
+ * PRETRANSFORMVERTICES
+ * LIMITBONEWEIGHTS
+ * VALIDATEDS
+ * IMPROVECACHELOCALITY
+ * FIXINFACINGNORMALS
+ * REMOVE_REDUNDANTMATERIALS
+ * OPTIMIZEGRAPH
+ * SORTBYPTYPE
+ * FINDINVALIDDATA
+ * TRANSFORMTEXCOORDS
+ * GENUVCOORDS
+ * ENTITYMESHBUILDER
+ * EMBEDTEXTURES
+ * MAKELEFTHANDED
+ * FLIPUVS
+ * FLIPWINDINGORDER
+ * OPTIMIZEMESHES
+ * OPTIMIZEANIMS
+ * OPTIMIZEGRAPH
+ * GENENTITYMESHES
+ * FIXTEXTUREPATHS */
+//////////////////////////////////////////////////////////////////////////
+
+#ifdef _MSC_VER
+# undef ASSIMP_API
+
+ //////////////////////////////////////////////////////////////////////////
+ /* Define 'ASSIMP_BUILD_DLL_EXPORT' to build a DLL of the library */
+ //////////////////////////////////////////////////////////////////////////
+# ifdef ASSIMP_BUILD_DLL_EXPORT
+# define ASSIMP_API __declspec(dllexport)
+# define ASSIMP_API_WINONLY __declspec(dllexport)
+# pragma warning (disable : 4251)
+
+ //////////////////////////////////////////////////////////////////////////
+ /* Define 'ASSIMP_DLL' before including Assimp to link to ASSIMP in
+ * an external DLL under Windows. Default is static linkage. */
+ //////////////////////////////////////////////////////////////////////////
+# elif (defined ASSIMP_DLL)
+# define ASSIMP_API __declspec(dllimport)
+# define ASSIMP_API_WINONLY __declspec(dllimport)
+# else
+# define ASSIMP_API
+# define ASSIMP_API_WINONLY
+# endif
+
+ /* Force the compiler to inline a function, if possible
+ */
+# define AI_FORCE_INLINE __forceinline
+
+ /* Tells the compiler that a function never returns. Used in code analysis
+ * to skip dead paths (e.g. after an assertion evaluated to false). */
+# define AI_WONT_RETURN __declspec(noreturn)
+
+#elif defined(SWIG)
+
+ /* Do nothing, the relevant defines are all in AssimpSwigPort.i */
+
+#else
+
+# define AI_WONT_RETURN
+
+# define ASSIMP_API __attribute__ ((visibility("default")))
+# define ASSIMP_API_WINONLY
+# define AI_FORCE_INLINE inline
+#endif // (defined _MSC_VER)
+
+#ifdef __GNUC__
+# define AI_WONT_RETURN_SUFFIX __attribute__((noreturn))
+#else
+# define AI_WONT_RETURN_SUFFIX
+#endif // (defined __clang__)
+
+#ifdef __cplusplus
+ /* No explicit 'struct' and 'enum' tags for C++, this keeps showing up
+ * in doxydocs.
+ */
+# define C_STRUCT
+# define C_ENUM
+#else
+ //////////////////////////////////////////////////////////////////////////
+ /* To build the documentation, make sure ASSIMP_DOXYGEN_BUILD
+ * is defined by Doxygen's preprocessor. The corresponding
+ * entries in the DOXYFILE are: */
+ //////////////////////////////////////////////////////////////////////////
+#if 0
+ ENABLE_PREPROCESSING = YES
+ MACRO_EXPANSION = YES
+ EXPAND_ONLY_PREDEF = YES
+ SEARCH_INCLUDES = YES
+ INCLUDE_PATH =
+ INCLUDE_FILE_PATTERNS =
+ PREDEFINED = ASSIMP_DOXYGEN_BUILD=1
+ EXPAND_AS_DEFINED = C_STRUCT C_ENUM
+ SKIP_FUNCTION_MACROS = YES
+#endif
+ //////////////////////////////////////////////////////////////////////////
+ /* Doxygen gets confused if we use c-struct typedefs to avoid
+ * the explicit 'struct' notation. This trick here has the same
+ * effect as the TYPEDEF_HIDES_STRUCT option, but we don't need
+ * to typedef all structs/enums. */
+ //////////////////////////////////////////////////////////////////////////
+# if (defined ASSIMP_DOXYGEN_BUILD)
+# define C_STRUCT
+# define C_ENUM
+# else
+# define C_STRUCT struct
+# define C_ENUM enum
+# endif
+#endif
+
+#if (defined(__BORLANDC__) || defined (__BCPLUSPLUS__))
+#error Currently, Borland is unsupported. Feel free to port Assimp.
+
+// "W8059 Packgröße der Struktur geändert"
+
+#endif
+
+
+ //////////////////////////////////////////////////////////////////////////
+ /* Define ASSIMP_BUILD_SINGLETHREADED to compile assimp
+ * without threading support. The library doesn't utilize
+ * threads then and is itself not threadsafe. */
+ //////////////////////////////////////////////////////////////////////////
+#ifndef ASSIMP_BUILD_SINGLETHREADED
+# define ASSIMP_BUILD_SINGLETHREADED
+#endif
+
+#if defined(_DEBUG) || ! defined(NDEBUG)
+# define ASSIMP_BUILD_DEBUG
+#endif
+
+ //////////////////////////////////////////////////////////////////////////
+ /* Define ASSIMP_DOUBLE_PRECISION to compile assimp
+ * with double precision support (64-bit). */
+ //////////////////////////////////////////////////////////////////////////
+
+#ifdef ASSIMP_DOUBLE_PRECISION
+ typedef double ai_real;
+ typedef signed long long int ai_int;
+ typedef unsigned long long int ai_uint;
+#else // ASSIMP_DOUBLE_PRECISION
+ typedef float ai_real;
+ typedef signed int ai_int;
+ typedef unsigned int ai_uint;
+#endif // ASSIMP_DOUBLE_PRECISION
+
+ //////////////////////////////////////////////////////////////////////////
+ /* Useful constants */
+ //////////////////////////////////////////////////////////////////////////
+
+/* This is PI. Hi PI. */
+#define AI_MATH_PI (3.141592653589793238462643383279 )
+#define AI_MATH_TWO_PI (AI_MATH_PI * 2.0)
+#define AI_MATH_HALF_PI (AI_MATH_PI * 0.5)
+
+/* And this is to avoid endless casts to float */
+#define AI_MATH_PI_F (3.1415926538f)
+#define AI_MATH_TWO_PI_F (AI_MATH_PI_F * 2.0f)
+#define AI_MATH_HALF_PI_F (AI_MATH_PI_F * 0.5f)
+
+/* Tiny macro to convert from radians to degrees and back */
+#define AI_DEG_TO_RAD(x) ((x)*(ai_real)0.0174532925)
+#define AI_RAD_TO_DEG(x) ((x)*(ai_real)57.2957795)
+
+/* Support for big-endian builds */
+#if defined(__BYTE_ORDER__)
+# if (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+# if !defined(__BIG_ENDIAN__)
+# define __BIG_ENDIAN__
+# endif
+# else /* little endian */
+# if defined (__BIG_ENDIAN__)
+# undef __BIG_ENDIAN__
+# endif
+# endif
+#endif
+#if defined(__BIG_ENDIAN__)
+# define AI_BUILD_BIG_ENDIAN
+#endif
+
+
+/* To avoid running out of memory
+ * This can be adjusted for specific use cases
+ * It's NOT a total limit, just a limit for individual allocations
+ */
+#define AI_MAX_ALLOC(type) ((256U * 1024 * 1024) / sizeof(type))
+
+#ifndef _MSC_VER
+# define AI_NO_EXCEPT noexcept
+#else
+# if (_MSC_VER == 1915 )
+# define AI_NO_EXCEPT noexcept
+# else
+# define AI_NO_EXCEPT
+# endif
+#endif
+
+#endif // !! AI_DEFINES_H_INC
diff --git a/thirdparty/assimp/include/assimp/fast_atof.h b/thirdparty/assimp/include/assimp/fast_atof.h
new file mode 100644
index 0000000000..62ea969e97
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/fast_atof.h
@@ -0,0 +1,373 @@
+#pragma once
+
+// Copyright (C) 2002-2007 Nikolaus Gebhardt
+// This file is part of the "Irrlicht Engine" and the "irrXML" project.
+// For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h
+
+// ------------------------------------------------------------------------------------
+// Original description: (Schrompf)
+// Adapted to the ASSIMP library because the builtin atof indeed takes AGES to parse a
+// float inside a large string. Before parsing, it does a strlen on the given point.
+// Changes:
+// 22nd October 08 (Aramis_acg): Added temporary cast to double, added strtoul10_64
+// to ensure long numbers are handled correctly
+// ------------------------------------------------------------------------------------
+
+
+#ifndef FAST_A_TO_F_H_INCLUDED
+#define FAST_A_TO_F_H_INCLUDED
+
+#include <cmath>
+#include <limits>
+#include <stdint.h>
+#include <stdexcept>
+#include <assimp/defs.h>
+
+#include "StringComparison.h"
+#include <assimp/DefaultLogger.hpp>
+
+#ifdef _MSC_VER
+# include <stdint.h>
+#else
+# include <assimp/Compiler/pstdint.h>
+#endif
+
+namespace Assimp {
+
+const double fast_atof_table[16] = { // we write [16] here instead of [] to work around a swig bug
+ 0.0,
+ 0.1,
+ 0.01,
+ 0.001,
+ 0.0001,
+ 0.00001,
+ 0.000001,
+ 0.0000001,
+ 0.00000001,
+ 0.000000001,
+ 0.0000000001,
+ 0.00000000001,
+ 0.000000000001,
+ 0.0000000000001,
+ 0.00000000000001,
+ 0.000000000000001
+};
+
+
+// ------------------------------------------------------------------------------------
+// Convert a string in decimal format to a number
+// ------------------------------------------------------------------------------------
+inline
+unsigned int strtoul10( const char* in, const char** out=0) {
+ unsigned int value = 0;
+
+ for ( ;; ) {
+ if ( *in < '0' || *in > '9' ) {
+ break;
+ }
+
+ value = ( value * 10 ) + ( *in - '0' );
+ ++in;
+ }
+ if ( out ) {
+ *out = in;
+ }
+ return value;
+}
+
+// ------------------------------------------------------------------------------------
+// Convert a string in octal format to a number
+// ------------------------------------------------------------------------------------
+inline
+unsigned int strtoul8( const char* in, const char** out=0) {
+ unsigned int value( 0 );
+ for ( ;; ) {
+ if ( *in < '0' || *in > '7' ) {
+ break;
+ }
+
+ value = ( value << 3 ) + ( *in - '0' );
+ ++in;
+ }
+ if ( out ) {
+ *out = in;
+ }
+ return value;
+}
+
+// ------------------------------------------------------------------------------------
+// Convert a string in hex format to a number
+// ------------------------------------------------------------------------------------
+inline
+unsigned int strtoul16( const char* in, const char** out=0) {
+ unsigned int value( 0 );
+ for ( ;; ) {
+ if ( *in >= '0' && *in <= '9' ) {
+ value = ( value << 4u ) + ( *in - '0' );
+ } else if (*in >= 'A' && *in <= 'F') {
+ value = ( value << 4u ) + ( *in - 'A' ) + 10;
+ } else if (*in >= 'a' && *in <= 'f') {
+ value = ( value << 4u ) + ( *in - 'a' ) + 10;
+ } else {
+ break;
+ }
+ ++in;
+ }
+ if ( out ) {
+ *out = in;
+ }
+ return value;
+}
+
+// ------------------------------------------------------------------------------------
+// Convert just one hex digit
+// Return value is UINT_MAX if the input character is not a hex digit.
+// ------------------------------------------------------------------------------------
+inline
+unsigned int HexDigitToDecimal(char in) {
+ unsigned int out( UINT_MAX );
+ if ( in >= '0' && in <= '9' ) {
+ out = in - '0';
+ } else if ( in >= 'a' && in <= 'f' ) {
+ out = 10u + in - 'a';
+ } else if ( in >= 'A' && in <= 'F' ) {
+ out = 10u + in - 'A';
+ }
+
+ // return value is UINT_MAX if the input is not a hex digit
+ return out;
+}
+
+// ------------------------------------------------------------------------------------
+// Convert a hex-encoded octet (2 characters, i.e. df or 1a).
+// ------------------------------------------------------------------------------------
+inline
+uint8_t HexOctetToDecimal(const char* in) {
+ return ((uint8_t)HexDigitToDecimal(in[0])<<4)+(uint8_t)HexDigitToDecimal(in[1]);
+}
+
+// ------------------------------------------------------------------------------------
+// signed variant of strtoul10
+// ------------------------------------------------------------------------------------
+inline
+int strtol10( const char* in, const char** out=0) {
+ bool inv = (*in=='-');
+ if ( inv || *in == '+' ) {
+ ++in;
+ }
+
+ int value = strtoul10(in,out);
+ if (inv) {
+ value = -value;
+ }
+ return value;
+}
+
+// ------------------------------------------------------------------------------------
+// Parse a C++-like integer literal - hex and oct prefixes.
+// 0xNNNN - hex
+// 0NNN - oct
+// NNN - dec
+// ------------------------------------------------------------------------------------
+inline
+unsigned int strtoul_cppstyle( const char* in, const char** out=0) {
+ if ('0' == in[0]) {
+ return 'x' == in[1] ? strtoul16(in+2,out) : strtoul8(in+1,out);
+ }
+ return strtoul10(in, out);
+}
+
+// ------------------------------------------------------------------------------------
+// Special version of the function, providing higher accuracy and safety
+// It is mainly used by fast_atof to prevent ugly and unwanted integer overflows.
+// ------------------------------------------------------------------------------------
+inline
+uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int* max_inout=0) {
+ unsigned int cur = 0;
+ uint64_t value = 0;
+
+ if ( *in < '0' || *in > '9' ) {
+ throw std::invalid_argument( std::string( "The string \"" ) + in + "\" cannot be converted into a value." );
+ }
+
+ for ( ;; ) {
+ if ( *in < '0' || *in > '9' ) {
+ break;
+ }
+
+ const uint64_t new_value = ( value * (uint64_t) 10 ) + ( (uint64_t) ( *in - '0' ) );
+
+ // numeric overflow, we rely on you
+ if ( new_value < value ) {
+ ASSIMP_LOG_WARN_F( "Converting the string \"", in, "\" into a value resulted in overflow." );
+ return 0;
+ }
+
+ value = new_value;
+
+ ++in;
+ ++cur;
+
+ if (max_inout && *max_inout == cur) {
+ if (out) { /* skip to end */
+ while ( *in >= '0' && *in <= '9' ) {
+ ++in;
+ }
+ *out = in;
+ }
+
+ return value;
+ }
+ }
+ if ( out ) {
+ *out = in;
+ }
+
+ if ( max_inout ) {
+ *max_inout = cur;
+ }
+
+ return value;
+}
+
+// ------------------------------------------------------------------------------------
+// signed variant of strtoul10_64
+// ------------------------------------------------------------------------------------
+inline
+int64_t strtol10_64(const char* in, const char** out = 0, unsigned int* max_inout = 0) {
+ bool inv = (*in == '-');
+ if ( inv || *in == '+' ) {
+ ++in;
+ }
+
+ int64_t value = strtoul10_64(in, out, max_inout);
+ if (inv) {
+ value = -value;
+ }
+ return value;
+}
+
+// Number of relevant decimals for floating-point parsing.
+#define AI_FAST_ATOF_RELAVANT_DECIMALS 15
+
+// ------------------------------------------------------------------------------------
+//! Provides a fast function for converting a string into a float,
+//! about 6 times faster than atof in win32.
+// If you find any bugs, please send them to me, niko (at) irrlicht3d.org.
+// ------------------------------------------------------------------------------------
+template<typename Real>
+inline
+const char* fast_atoreal_move(const char* c, Real& out, bool check_comma = true) {
+ Real f = 0;
+
+ bool inv = (*c == '-');
+ if (inv || *c == '+') {
+ ++c;
+ }
+
+ if ((c[0] == 'N' || c[0] == 'n') && ASSIMP_strincmp(c, "nan", 3) == 0) {
+ out = std::numeric_limits<Real>::quiet_NaN();
+ c += 3;
+ return c;
+ }
+
+ if ((c[0] == 'I' || c[0] == 'i') && ASSIMP_strincmp(c, "inf", 3) == 0) {
+ out = std::numeric_limits<Real>::infinity();
+ if (inv) {
+ out = -out;
+ }
+ c += 3;
+ if ((c[0] == 'I' || c[0] == 'i') && ASSIMP_strincmp(c, "inity", 5) == 0) {
+ c += 5;
+ }
+ return c;
+ }
+
+ if (!(c[0] >= '0' && c[0] <= '9') &&
+ !((c[0] == '.' || (check_comma && c[0] == ',')) && c[1] >= '0' && c[1] <= '9')) {
+ throw std::invalid_argument("Cannot parse string "
+ "as real number: does not start with digit "
+ "or decimal point followed by digit.");
+ }
+
+ if (*c != '.' && (! check_comma || c[0] != ',')) {
+ f = static_cast<Real>( strtoul10_64 ( c, &c) );
+ }
+
+ if ((*c == '.' || (check_comma && c[0] == ',')) && c[1] >= '0' && c[1] <= '9') {
+ ++c;
+
+ // NOTE: The original implementation is highly inaccurate here. The precision of a single
+ // IEEE 754 float is not high enough, everything behind the 6th digit tends to be more
+ // inaccurate than it would need to be. Casting to double seems to solve the problem.
+ // strtol_64 is used to prevent integer overflow.
+
+ // Another fix: this tends to become 0 for long numbers if we don't limit the maximum
+ // number of digits to be read. AI_FAST_ATOF_RELAVANT_DECIMALS can be a value between
+ // 1 and 15.
+ unsigned int diff = AI_FAST_ATOF_RELAVANT_DECIMALS;
+ double pl = static_cast<double>( strtoul10_64 ( c, &c, &diff ));
+
+ pl *= fast_atof_table[diff];
+ f += static_cast<Real>( pl );
+ }
+ // For backwards compatibility: eat trailing dots, but not trailing commas.
+ else if (*c == '.') {
+ ++c;
+ }
+
+ // A major 'E' must be allowed. Necessary for proper reading of some DXF files.
+ // Thanks to Zhao Lei to point out that this if() must be outside the if (*c == '.' ..)
+ if (*c == 'e' || *c == 'E') {
+ ++c;
+ const bool einv = (*c=='-');
+ if (einv || *c=='+') {
+ ++c;
+ }
+
+ // The reason float constants are used here is that we've seen cases where compilers
+ // would perform such casts on compile-time constants at runtime, which would be
+ // bad considering how frequently fast_atoreal_move<float> is called in Assimp.
+ Real exp = static_cast<Real>( strtoul10_64(c, &c) );
+ if (einv) {
+ exp = -exp;
+ }
+ f *= std::pow(static_cast<Real>(10.0), exp);
+ }
+
+ if (inv) {
+ f = -f;
+ }
+ out = f;
+ return c;
+}
+
+// ------------------------------------------------------------------------------------
+// The same but more human.
+inline
+ai_real fast_atof(const char* c) {
+ ai_real ret(0.0);
+ fast_atoreal_move<ai_real>(c, ret);
+
+ return ret;
+}
+
+inline
+ai_real fast_atof( const char* c, const char** cout) {
+ ai_real ret(0.0);
+ *cout = fast_atoreal_move<ai_real>(c, ret);
+
+ return ret;
+}
+
+inline
+ai_real fast_atof( const char** inout) {
+ ai_real ret(0.0);
+ *inout = fast_atoreal_move<ai_real>(*inout, ret);
+
+ return ret;
+}
+
+} //! namespace Assimp
+
+#endif // FAST_A_TO_F_H_INCLUDED
diff --git a/thirdparty/assimp/include/assimp/importerdesc.h b/thirdparty/assimp/include/assimp/importerdesc.h
new file mode 100644
index 0000000000..36e387f011
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/importerdesc.h
@@ -0,0 +1,146 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file importerdesc.h
+ * @brief #aiImporterFlags, aiImporterDesc implementation.
+ */
+#pragma once
+#ifndef AI_IMPORTER_DESC_H_INC
+#define AI_IMPORTER_DESC_H_INC
+
+
+/** Mixed set of flags for #aiImporterDesc, indicating some features
+ * common to many importers*/
+enum aiImporterFlags
+{
+ /** Indicates that there is a textual encoding of the
+ * file format; and that it is supported.*/
+ aiImporterFlags_SupportTextFlavour = 0x1,
+
+ /** Indicates that there is a binary encoding of the
+ * file format; and that it is supported.*/
+ aiImporterFlags_SupportBinaryFlavour = 0x2,
+
+ /** Indicates that there is a compressed encoding of the
+ * file format; and that it is supported.*/
+ aiImporterFlags_SupportCompressedFlavour = 0x4,
+
+ /** Indicates that the importer reads only a very particular
+ * subset of the file format. This happens commonly for
+ * declarative or procedural formats which cannot easily
+ * be mapped to #aiScene */
+ aiImporterFlags_LimitedSupport = 0x8,
+
+ /** Indicates that the importer is highly experimental and
+ * should be used with care. This only happens for trunk
+ * (i.e. SVN) versions, experimental code is not included
+ * in releases. */
+ aiImporterFlags_Experimental = 0x10
+};
+
+
+/** Meta information about a particular importer. Importers need to fill
+ * this structure, but they can freely decide how talkative they are.
+ * A common use case for loader meta info is a user interface
+ * in which the user can choose between various import/export file
+ * formats. Building such an UI by hand means a lot of maintenance
+ * as importers/exporters are added to Assimp, so it might be useful
+ * to have a common mechanism to query some rough importer
+ * characteristics. */
+struct aiImporterDesc
+{
+ /** Full name of the importer (i.e. Blender3D importer)*/
+ const char* mName;
+
+ /** Original author (left blank if unknown or whole assimp team) */
+ const char* mAuthor;
+
+ /** Current maintainer, left blank if the author maintains */
+ const char* mMaintainer;
+
+ /** Implementation comments, i.e. unimplemented features*/
+ const char* mComments;
+
+ /** These flags indicate some characteristics common to many
+ importers. */
+ unsigned int mFlags;
+
+ /** Minimum format version that can be loaded im major.minor format,
+ both are set to 0 if there is either no version scheme
+ or if the loader doesn't care. */
+ unsigned int mMinMajor;
+ unsigned int mMinMinor;
+
+ /** Maximum format version that can be loaded im major.minor format,
+ both are set to 0 if there is either no version scheme
+ or if the loader doesn't care. Loaders that expect to be
+ forward-compatible to potential future format versions should
+ indicate zero, otherwise they should specify the current
+ maximum version.*/
+ unsigned int mMaxMajor;
+ unsigned int mMaxMinor;
+
+ /** List of file extensions this importer can handle.
+ List entries are separated by space characters.
+ All entries are lower case without a leading dot (i.e.
+ "xml dae" would be a valid value. Note that multiple
+ importers may respond to the same file extension -
+ assimp calls all importers in the order in which they
+ are registered and each importer gets the opportunity
+ to load the file until one importer "claims" the file. Apart
+ from file extension checks, importers typically use
+ other methods to quickly reject files (i.e. magic
+ words) so this does not mean that common or generic
+ file extensions such as XML would be tediously slow. */
+ const char* mFileExtensions;
+};
+
+/** \brief Returns the Importer description for a given extension.
+
+Will return a NULL-pointer if no assigned importer desc. was found for the given extension
+ \param extension [in] The extension to look for
+ \return A pointer showing to the ImporterDesc, \see aiImporterDesc.
+*/
+ASSIMP_API const C_STRUCT aiImporterDesc* aiGetImporterDesc( const char *extension );
+
+#endif // AI_IMPORTER_DESC_H_INC
diff --git a/thirdparty/assimp/include/assimp/irrXMLWrapper.h b/thirdparty/assimp/include/assimp/irrXMLWrapper.h
new file mode 100644
index 0000000000..ec8ee7c76e
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/irrXMLWrapper.h
@@ -0,0 +1,144 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+#ifndef INCLUDED_AI_IRRXML_WRAPPER
+#define INCLUDED_AI_IRRXML_WRAPPER
+
+// some long includes ....
+#include <irrXML.h>
+#include "IOStream.hpp"
+#include "BaseImporter.h"
+#include <vector>
+
+namespace Assimp {
+
+// ---------------------------------------------------------------------------------
+/** @brief Utility class to make IrrXML work together with our custom IO system
+ * See the IrrXML docs for more details.
+ *
+ * Construct IrrXML-Reader in BaseImporter::InternReadFile():
+ * @code
+ * // open the file
+ * std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
+ * if( file.get() == NULL) {
+ * throw DeadlyImportError( "Failed to open file " + pFile + ".");
+ * }
+ *
+ * // generate a XML reader for it
+ * std::unique_ptr<CIrrXML_IOStreamReader> mIOWrapper( new CIrrXML_IOStreamReader( file.get()));
+ * mReader = irr::io::createIrrXMLReader( mIOWrapper.get());
+ * if( !mReader) {
+ * ThrowException( "xxxx: Unable to open file.");
+ * }
+ * @endcode
+ **/
+class CIrrXML_IOStreamReader : public irr::io::IFileReadCallBack {
+public:
+
+ // ----------------------------------------------------------------------------------
+ //! Construction from an existing IOStream
+ explicit CIrrXML_IOStreamReader(IOStream* _stream)
+ : stream (_stream)
+ , t (0)
+ {
+
+ // Map the buffer into memory and convert it to UTF8. IrrXML provides its
+ // own conversion, which is merely a cast from uintNN_t to uint8_t. Thus,
+ // it is not suitable for our purposes and we have to do it BEFORE IrrXML
+ // gets the buffer. Sadly, this forces us to map the whole file into
+ // memory.
+
+ data.resize(stream->FileSize());
+ stream->Read(&data[0],data.size(),1);
+
+ // Remove null characters from the input sequence otherwise the parsing will utterly fail
+ unsigned int size = 0;
+ unsigned int size_max = static_cast<unsigned int>(data.size());
+ for(unsigned int i = 0; i < size_max; i++) {
+ if(data[i] != '\0') {
+ data[size++] = data[i];
+ }
+ }
+ data.resize(size);
+
+ BaseImporter::ConvertToUTF8(data);
+ }
+
+ // ----------------------------------------------------------------------------------
+ //! Virtual destructor
+ virtual ~CIrrXML_IOStreamReader() {}
+
+ // ----------------------------------------------------------------------------------
+ //! Reads an amount of bytes from the file.
+ /** @param buffer: Pointer to output buffer.
+ * @param sizeToRead: Amount of bytes to read
+ * @return Returns how much bytes were read. */
+ virtual int read(void* buffer, int sizeToRead) {
+ if(sizeToRead<0) {
+ return 0;
+ }
+ if(t+sizeToRead>data.size()) {
+ sizeToRead = static_cast<int>(data.size()-t);
+ }
+
+ memcpy(buffer,&data.front()+t,sizeToRead);
+
+ t += sizeToRead;
+ return sizeToRead;
+ }
+
+ // ----------------------------------------------------------------------------------
+ //! Returns size of file in bytes
+ virtual int getSize() {
+ return (int)data.size();
+ }
+
+private:
+ IOStream* stream;
+ std::vector<char> data;
+ size_t t;
+
+}; // ! class CIrrXML_IOStreamReader
+
+} // ! Assimp
+
+#endif // !! INCLUDED_AI_IRRXML_WRAPPER
diff --git a/thirdparty/assimp/include/assimp/light.h b/thirdparty/assimp/include/assimp/light.h
new file mode 100644
index 0000000000..1667cfb8c1
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/light.h
@@ -0,0 +1,259 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file light.h
+ * @brief Defines the aiLight data structure
+ */
+
+#pragma once
+#ifndef AI_LIGHT_H_INC
+#define AI_LIGHT_H_INC
+
+#include "types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// ---------------------------------------------------------------------------
+/** Enumerates all supported types of light sources.
+ */
+enum aiLightSourceType
+{
+ aiLightSource_UNDEFINED = 0x0,
+
+ //! A directional light source has a well-defined direction
+ //! but is infinitely far away. That's quite a good
+ //! approximation for sun light.
+ aiLightSource_DIRECTIONAL = 0x1,
+
+ //! A point light source has a well-defined position
+ //! in space but no direction - it emits light in all
+ //! directions. A normal bulb is a point light.
+ aiLightSource_POINT = 0x2,
+
+ //! A spot light source emits light in a specific
+ //! angle. It has a position and a direction it is pointing to.
+ //! A good example for a spot light is a light spot in
+ //! sport arenas.
+ aiLightSource_SPOT = 0x3,
+
+ //! The generic light level of the world, including the bounces
+ //! of all other light sources.
+ //! Typically, there's at most one ambient light in a scene.
+ //! This light type doesn't have a valid position, direction, or
+ //! other properties, just a color.
+ aiLightSource_AMBIENT = 0x4,
+
+ //! An area light is a rectangle with predefined size that uniformly
+ //! emits light from one of its sides. The position is center of the
+ //! rectangle and direction is its normal vector.
+ aiLightSource_AREA = 0x5,
+
+ /** This value is not used. It is just there to force the
+ * compiler to map this enum to a 32 Bit integer.
+ */
+#ifndef SWIG
+ _aiLightSource_Force32Bit = INT_MAX
+#endif
+};
+
+// ---------------------------------------------------------------------------
+/** Helper structure to describe a light source.
+ *
+ * Assimp supports multiple sorts of light sources, including
+ * directional, point and spot lights. All of them are defined with just
+ * a single structure and distinguished by their parameters.
+ * Note - some file formats (such as 3DS, ASE) export a "target point" -
+ * the point a spot light is looking at (it can even be animated). Assimp
+ * writes the target point as a subnode of a spotlights's main node,
+ * called "<spotName>.Target". However, this is just additional information
+ * then, the transformation tracks of the main node make the
+ * spot light already point in the right direction.
+*/
+struct aiLight
+{
+ /** The name of the light source.
+ *
+ * There must be a node in the scenegraph with the same name.
+ * This node specifies the position of the light in the scene
+ * hierarchy and can be animated.
+ */
+ C_STRUCT aiString mName;
+
+ /** The type of the light source.
+ *
+ * aiLightSource_UNDEFINED is not a valid value for this member.
+ */
+ C_ENUM aiLightSourceType mType;
+
+ /** Position of the light source in space. Relative to the
+ * transformation of the node corresponding to the light.
+ *
+ * The position is undefined for directional lights.
+ */
+ C_STRUCT aiVector3D mPosition;
+
+ /** Direction of the light source in space. Relative to the
+ * transformation of the node corresponding to the light.
+ *
+ * The direction is undefined for point lights. The vector
+ * may be normalized, but it needn't.
+ */
+ C_STRUCT aiVector3D mDirection;
+
+ /** Up direction of the light source in space. Relative to the
+ * transformation of the node corresponding to the light.
+ *
+ * The direction is undefined for point lights. The vector
+ * may be normalized, but it needn't.
+ */
+ C_STRUCT aiVector3D mUp;
+
+ /** Constant light attenuation factor.
+ *
+ * The intensity of the light source at a given distance 'd' from
+ * the light's position is
+ * @code
+ * Atten = 1/( att0 + att1 * d + att2 * d*d)
+ * @endcode
+ * This member corresponds to the att0 variable in the equation.
+ * Naturally undefined for directional lights.
+ */
+ float mAttenuationConstant;
+
+ /** Linear light attenuation factor.
+ *
+ * The intensity of the light source at a given distance 'd' from
+ * the light's position is
+ * @code
+ * Atten = 1/( att0 + att1 * d + att2 * d*d)
+ * @endcode
+ * This member corresponds to the att1 variable in the equation.
+ * Naturally undefined for directional lights.
+ */
+ float mAttenuationLinear;
+
+ /** Quadratic light attenuation factor.
+ *
+ * The intensity of the light source at a given distance 'd' from
+ * the light's position is
+ * @code
+ * Atten = 1/( att0 + att1 * d + att2 * d*d)
+ * @endcode
+ * This member corresponds to the att2 variable in the equation.
+ * Naturally undefined for directional lights.
+ */
+ float mAttenuationQuadratic;
+
+ /** Diffuse color of the light source
+ *
+ * The diffuse light color is multiplied with the diffuse
+ * material color to obtain the final color that contributes
+ * to the diffuse shading term.
+ */
+ C_STRUCT aiColor3D mColorDiffuse;
+
+ /** Specular color of the light source
+ *
+ * The specular light color is multiplied with the specular
+ * material color to obtain the final color that contributes
+ * to the specular shading term.
+ */
+ C_STRUCT aiColor3D mColorSpecular;
+
+ /** Ambient color of the light source
+ *
+ * The ambient light color is multiplied with the ambient
+ * material color to obtain the final color that contributes
+ * to the ambient shading term. Most renderers will ignore
+ * this value it, is just a remaining of the fixed-function pipeline
+ * that is still supported by quite many file formats.
+ */
+ C_STRUCT aiColor3D mColorAmbient;
+
+ /** Inner angle of a spot light's light cone.
+ *
+ * The spot light has maximum influence on objects inside this
+ * angle. The angle is given in radians. It is 2PI for point
+ * lights and undefined for directional lights.
+ */
+ float mAngleInnerCone;
+
+ /** Outer angle of a spot light's light cone.
+ *
+ * The spot light does not affect objects outside this angle.
+ * The angle is given in radians. It is 2PI for point lights and
+ * undefined for directional lights. The outer angle must be
+ * greater than or equal to the inner angle.
+ * It is assumed that the application uses a smooth
+ * interpolation between the inner and the outer cone of the
+ * spot light.
+ */
+ float mAngleOuterCone;
+
+ /** Size of area light source. */
+ C_STRUCT aiVector2D mSize;
+
+#ifdef __cplusplus
+
+ aiLight() AI_NO_EXCEPT
+ : mType (aiLightSource_UNDEFINED)
+ , mAttenuationConstant (0.f)
+ , mAttenuationLinear (1.f)
+ , mAttenuationQuadratic (0.f)
+ , mAngleInnerCone ((float)AI_MATH_TWO_PI)
+ , mAngleOuterCone ((float)AI_MATH_TWO_PI)
+ , mSize (0.f, 0.f)
+ {
+ }
+
+#endif
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif // !! AI_LIGHT_H_INC
diff --git a/thirdparty/assimp/include/assimp/material.h b/thirdparty/assimp/include/assimp/material.h
new file mode 100644
index 0000000000..4b5a1293dd
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/material.h
@@ -0,0 +1,1580 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file material.h
+ * @brief Defines the material system of the library
+ */
+#pragma once
+#ifndef AI_MATERIAL_H_INC
+#define AI_MATERIAL_H_INC
+
+#include "types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Name for default materials (2nd is used if meshes have UV coords)
+#define AI_DEFAULT_MATERIAL_NAME "DefaultMaterial"
+
+// ---------------------------------------------------------------------------
+/** @brief Defines how the Nth texture of a specific type is combined with
+ * the result of all previous layers.
+ *
+ * Example (left: key, right: value): <br>
+ * @code
+ * DiffColor0 - gray
+ * DiffTextureOp0 - aiTextureOpMultiply
+ * DiffTexture0 - tex1.png
+ * DiffTextureOp0 - aiTextureOpAdd
+ * DiffTexture1 - tex2.png
+ * @endcode
+ * Written as equation, the final diffuse term for a specific pixel would be:
+ * @code
+ * diffFinal = DiffColor0 * sampleTex(DiffTexture0,UV0) +
+ * sampleTex(DiffTexture1,UV0) * diffContrib;
+ * @endcode
+ * where 'diffContrib' is the intensity of the incoming light for that pixel.
+ */
+enum aiTextureOp
+{
+ /** T = T1 * T2 */
+ aiTextureOp_Multiply = 0x0,
+
+ /** T = T1 + T2 */
+ aiTextureOp_Add = 0x1,
+
+ /** T = T1 - T2 */
+ aiTextureOp_Subtract = 0x2,
+
+ /** T = T1 / T2 */
+ aiTextureOp_Divide = 0x3,
+
+ /** T = (T1 + T2) - (T1 * T2) */
+ aiTextureOp_SmoothAdd = 0x4,
+
+ /** T = T1 + (T2-0.5) */
+ aiTextureOp_SignedAdd = 0x5,
+
+
+#ifndef SWIG
+ _aiTextureOp_Force32Bit = INT_MAX
+#endif
+};
+
+// ---------------------------------------------------------------------------
+/** @brief Defines how UV coordinates outside the [0...1] range are handled.
+ *
+ * Commonly referred to as 'wrapping mode'.
+ */
+enum aiTextureMapMode
+{
+ /** A texture coordinate u|v is translated to u%1|v%1
+ */
+ aiTextureMapMode_Wrap = 0x0,
+
+ /** Texture coordinates outside [0...1]
+ * are clamped to the nearest valid value.
+ */
+ aiTextureMapMode_Clamp = 0x1,
+
+ /** If the texture coordinates for a pixel are outside [0...1]
+ * the texture is not applied to that pixel
+ */
+ aiTextureMapMode_Decal = 0x3,
+
+ /** A texture coordinate u|v becomes u%1|v%1 if (u-(u%1))%2 is zero and
+ * 1-(u%1)|1-(v%1) otherwise
+ */
+ aiTextureMapMode_Mirror = 0x2,
+
+#ifndef SWIG
+ _aiTextureMapMode_Force32Bit = INT_MAX
+#endif
+};
+
+// ---------------------------------------------------------------------------
+/** @brief Defines how the mapping coords for a texture are generated.
+ *
+ * Real-time applications typically require full UV coordinates, so the use of
+ * the aiProcess_GenUVCoords step is highly recommended. It generates proper
+ * UV channels for non-UV mapped objects, as long as an accurate description
+ * how the mapping should look like (e.g spherical) is given.
+ * See the #AI_MATKEY_MAPPING property for more details.
+ */
+enum aiTextureMapping
+{
+ /** The mapping coordinates are taken from an UV channel.
+ *
+ * The #AI_MATKEY_UVWSRC key specifies from which UV channel
+ * the texture coordinates are to be taken from (remember,
+ * meshes can have more than one UV channel).
+ */
+ aiTextureMapping_UV = 0x0,
+
+ /** Spherical mapping */
+ aiTextureMapping_SPHERE = 0x1,
+
+ /** Cylindrical mapping */
+ aiTextureMapping_CYLINDER = 0x2,
+
+ /** Cubic mapping */
+ aiTextureMapping_BOX = 0x3,
+
+ /** Planar mapping */
+ aiTextureMapping_PLANE = 0x4,
+
+ /** Undefined mapping. Have fun. */
+ aiTextureMapping_OTHER = 0x5,
+
+
+#ifndef SWIG
+ _aiTextureMapping_Force32Bit = INT_MAX
+#endif
+};
+
+// ---------------------------------------------------------------------------
+/** @brief Defines the purpose of a texture
+ *
+ * This is a very difficult topic. Different 3D packages support different
+ * kinds of textures. For very common texture types, such as bumpmaps, the
+ * rendering results depend on implementation details in the rendering
+ * pipelines of these applications. Assimp loads all texture references from
+ * the model file and tries to determine which of the predefined texture
+ * types below is the best choice to match the original use of the texture
+ * as closely as possible.<br>
+ *
+ * In content pipelines you'll usually define how textures have to be handled,
+ * and the artists working on models have to conform to this specification,
+ * regardless which 3D tool they're using.
+ */
+enum aiTextureType
+{
+ /** Dummy value.
+ *
+ * No texture, but the value to be used as 'texture semantic'
+ * (#aiMaterialProperty::mSemantic) for all material properties
+ * *not* related to textures.
+ */
+ aiTextureType_NONE = 0x0,
+
+ /** The texture is combined with the result of the diffuse
+ * lighting equation.
+ */
+ aiTextureType_DIFFUSE = 0x1,
+
+ /** The texture is combined with the result of the specular
+ * lighting equation.
+ */
+ aiTextureType_SPECULAR = 0x2,
+
+ /** The texture is combined with the result of the ambient
+ * lighting equation.
+ */
+ aiTextureType_AMBIENT = 0x3,
+
+ /** The texture is added to the result of the lighting
+ * calculation. It isn't influenced by incoming light.
+ */
+ aiTextureType_EMISSIVE = 0x4,
+
+ /** The texture is a height map.
+ *
+ * By convention, higher gray-scale values stand for
+ * higher elevations from the base height.
+ */
+ aiTextureType_HEIGHT = 0x5,
+
+ /** The texture is a (tangent space) normal-map.
+ *
+ * Again, there are several conventions for tangent-space
+ * normal maps. Assimp does (intentionally) not
+ * distinguish here.
+ */
+ aiTextureType_NORMALS = 0x6,
+
+ /** The texture defines the glossiness of the material.
+ *
+ * The glossiness is in fact the exponent of the specular
+ * (phong) lighting equation. Usually there is a conversion
+ * function defined to map the linear color values in the
+ * texture to a suitable exponent. Have fun.
+ */
+ aiTextureType_SHININESS = 0x7,
+
+ /** The texture defines per-pixel opacity.
+ *
+ * Usually 'white' means opaque and 'black' means
+ * 'transparency'. Or quite the opposite. Have fun.
+ */
+ aiTextureType_OPACITY = 0x8,
+
+ /** Displacement texture
+ *
+ * The exact purpose and format is application-dependent.
+ * Higher color values stand for higher vertex displacements.
+ */
+ aiTextureType_DISPLACEMENT = 0x9,
+
+ /** Lightmap texture (aka Ambient Occlusion)
+ *
+ * Both 'Lightmaps' and dedicated 'ambient occlusion maps' are
+ * covered by this material property. The texture contains a
+ * scaling value for the final color value of a pixel. Its
+ * intensity is not affected by incoming light.
+ */
+ aiTextureType_LIGHTMAP = 0xA,
+
+ /** Reflection texture
+ *
+ * Contains the color of a perfect mirror reflection.
+ * Rarely used, almost never for real-time applications.
+ */
+ aiTextureType_REFLECTION = 0xB,
+
+ /** Unknown texture
+ *
+ * A texture reference that does not match any of the definitions
+ * above is considered to be 'unknown'. It is still imported,
+ * but is excluded from any further post-processing.
+ */
+ aiTextureType_UNKNOWN = 0xC,
+
+
+#ifndef SWIG
+ _aiTextureType_Force32Bit = INT_MAX
+#endif
+};
+
+#define AI_TEXTURE_TYPE_MAX aiTextureType_UNKNOWN
+
+// ---------------------------------------------------------------------------
+/** @brief Defines all shading models supported by the library
+ *
+ * The list of shading modes has been taken from Blender.
+ * See Blender documentation for more information. The API does
+ * not distinguish between "specular" and "diffuse" shaders (thus the
+ * specular term for diffuse shading models like Oren-Nayar remains
+ * undefined). <br>
+ * Again, this value is just a hint. Assimp tries to select the shader whose
+ * most common implementation matches the original rendering results of the
+ * 3D modeller which wrote a particular model as closely as possible.
+ */
+enum aiShadingMode
+{
+ /** Flat shading. Shading is done on per-face base,
+ * diffuse only. Also known as 'faceted shading'.
+ */
+ aiShadingMode_Flat = 0x1,
+
+ /** Simple Gouraud shading.
+ */
+ aiShadingMode_Gouraud = 0x2,
+
+ /** Phong-Shading -
+ */
+ aiShadingMode_Phong = 0x3,
+
+ /** Phong-Blinn-Shading
+ */
+ aiShadingMode_Blinn = 0x4,
+
+ /** Toon-Shading per pixel
+ *
+ * Also known as 'comic' shader.
+ */
+ aiShadingMode_Toon = 0x5,
+
+ /** OrenNayar-Shading per pixel
+ *
+ * Extension to standard Lambertian shading, taking the
+ * roughness of the material into account
+ */
+ aiShadingMode_OrenNayar = 0x6,
+
+ /** Minnaert-Shading per pixel
+ *
+ * Extension to standard Lambertian shading, taking the
+ * "darkness" of the material into account
+ */
+ aiShadingMode_Minnaert = 0x7,
+
+ /** CookTorrance-Shading per pixel
+ *
+ * Special shader for metallic surfaces.
+ */
+ aiShadingMode_CookTorrance = 0x8,
+
+ /** No shading at all. Constant light influence of 1.0.
+ */
+ aiShadingMode_NoShading = 0x9,
+
+ /** Fresnel shading
+ */
+ aiShadingMode_Fresnel = 0xa,
+
+
+#ifndef SWIG
+ _aiShadingMode_Force32Bit = INT_MAX
+#endif
+};
+
+
+// ---------------------------------------------------------------------------
+/** @brief Defines some mixed flags for a particular texture.
+ *
+ * Usually you'll instruct your cg artists how textures have to look like ...
+ * and how they will be processed in your application. However, if you use
+ * Assimp for completely generic loading purposes you might also need to
+ * process these flags in order to display as many 'unknown' 3D models as
+ * possible correctly.
+ *
+ * This corresponds to the #AI_MATKEY_TEXFLAGS property.
+*/
+enum aiTextureFlags
+{
+ /** The texture's color values have to be inverted (component-wise 1-n)
+ */
+ aiTextureFlags_Invert = 0x1,
+
+ /** Explicit request to the application to process the alpha channel
+ * of the texture.
+ *
+ * Mutually exclusive with #aiTextureFlags_IgnoreAlpha. These
+ * flags are set if the library can say for sure that the alpha
+ * channel is used/is not used. If the model format does not
+ * define this, it is left to the application to decide whether
+ * the texture alpha channel - if any - is evaluated or not.
+ */
+ aiTextureFlags_UseAlpha = 0x2,
+
+ /** Explicit request to the application to ignore the alpha channel
+ * of the texture.
+ *
+ * Mutually exclusive with #aiTextureFlags_UseAlpha.
+ */
+ aiTextureFlags_IgnoreAlpha = 0x4,
+
+#ifndef SWIG
+ _aiTextureFlags_Force32Bit = INT_MAX
+#endif
+};
+
+
+// ---------------------------------------------------------------------------
+/** @brief Defines alpha-blend flags.
+ *
+ * If you're familiar with OpenGL or D3D, these flags aren't new to you.
+ * They define *how* the final color value of a pixel is computed, basing
+ * on the previous color at that pixel and the new color value from the
+ * material.
+ * The blend formula is:
+ * @code
+ * SourceColor * SourceBlend + DestColor * DestBlend
+ * @endcode
+ * where DestColor is the previous color in the framebuffer at this
+ * position and SourceColor is the material color before the transparency
+ * calculation.<br>
+ * This corresponds to the #AI_MATKEY_BLEND_FUNC property.
+*/
+enum aiBlendMode
+{
+ /**
+ * Formula:
+ * @code
+ * SourceColor*SourceAlpha + DestColor*(1-SourceAlpha)
+ * @endcode
+ */
+ aiBlendMode_Default = 0x0,
+
+ /** Additive blending
+ *
+ * Formula:
+ * @code
+ * SourceColor*1 + DestColor*1
+ * @endcode
+ */
+ aiBlendMode_Additive = 0x1,
+
+ // we don't need more for the moment, but we might need them
+ // in future versions ...
+
+#ifndef SWIG
+ _aiBlendMode_Force32Bit = INT_MAX
+#endif
+};
+
+
+#include "./Compiler/pushpack1.h"
+
+// ---------------------------------------------------------------------------
+/** @brief Defines how an UV channel is transformed.
+ *
+ * This is just a helper structure for the #AI_MATKEY_UVTRANSFORM key.
+ * See its documentation for more details.
+ *
+ * Typically you'll want to build a matrix of this information. However,
+ * we keep separate scaling/translation/rotation values to make it
+ * easier to process and optimize UV transformations internally.
+ */
+struct aiUVTransform
+{
+ /** Translation on the u and v axes.
+ *
+ * The default value is (0|0).
+ */
+ C_STRUCT aiVector2D mTranslation;
+
+ /** Scaling on the u and v axes.
+ *
+ * The default value is (1|1).
+ */
+ C_STRUCT aiVector2D mScaling;
+
+ /** Rotation - in counter-clockwise direction.
+ *
+ * The rotation angle is specified in radians. The
+ * rotation center is 0.5f|0.5f. The default value
+ * 0.f.
+ */
+ ai_real mRotation;
+
+
+#ifdef __cplusplus
+ aiUVTransform() AI_NO_EXCEPT
+ : mTranslation (0.0,0.0)
+ , mScaling (1.0,1.0)
+ , mRotation (0.0)
+ {
+ // nothing to be done here ...
+ }
+#endif
+
+};
+
+#include "./Compiler/poppack1.h"
+
+//! @cond AI_DOX_INCLUDE_INTERNAL
+// ---------------------------------------------------------------------------
+/** @brief A very primitive RTTI system for the contents of material
+ * properties.
+ */
+enum aiPropertyTypeInfo
+{
+ /** Array of single-precision (32 Bit) floats
+ *
+ * It is possible to use aiGetMaterialInteger[Array]() (or the C++-API
+ * aiMaterial::Get()) to query properties stored in floating-point format.
+ * The material system performs the type conversion automatically.
+ */
+ aiPTI_Float = 0x1,
+
+ /** Array of double-precision (64 Bit) floats
+ *
+ * It is possible to use aiGetMaterialInteger[Array]() (or the C++-API
+ * aiMaterial::Get()) to query properties stored in floating-point format.
+ * The material system performs the type conversion automatically.
+ */
+ aiPTI_Double = 0x2,
+
+ /** The material property is an aiString.
+ *
+ * Arrays of strings aren't possible, aiGetMaterialString() (or the
+ * C++-API aiMaterial::Get()) *must* be used to query a string property.
+ */
+ aiPTI_String = 0x3,
+
+ /** Array of (32 Bit) integers
+ *
+ * It is possible to use aiGetMaterialFloat[Array]() (or the C++-API
+ * aiMaterial::Get()) to query properties stored in integer format.
+ * The material system performs the type conversion automatically.
+ */
+ aiPTI_Integer = 0x4,
+
+
+ /** Simple binary buffer, content undefined. Not convertible to anything.
+ */
+ aiPTI_Buffer = 0x5,
+
+
+ /** This value is not used. It is just there to force the
+ * compiler to map this enum to a 32 Bit integer.
+ */
+#ifndef SWIG
+ _aiPTI_Force32Bit = INT_MAX
+#endif
+};
+
+// ---------------------------------------------------------------------------
+/** @brief Data structure for a single material property
+ *
+ * As an user, you'll probably never need to deal with this data structure.
+ * Just use the provided aiGetMaterialXXX() or aiMaterial::Get() family
+ * of functions to query material properties easily. Processing them
+ * manually is faster, but it is not the recommended way. It isn't worth
+ * the effort. <br>
+ * Material property names follow a simple scheme:
+ * @code
+ * $<name>
+ * ?<name>
+ * A public property, there must be corresponding AI_MATKEY_XXX define
+ * 2nd: Public, but ignored by the #aiProcess_RemoveRedundantMaterials
+ * post-processing step.
+ * ~<name>
+ * A temporary property for internal use.
+ * @endcode
+ * @see aiMaterial
+ */
+struct aiMaterialProperty
+{
+ /** Specifies the name of the property (key)
+ * Keys are generally case insensitive.
+ */
+ C_STRUCT aiString mKey;
+
+ /** Textures: Specifies their exact usage semantic.
+ * For non-texture properties, this member is always 0
+ * (or, better-said, #aiTextureType_NONE).
+ */
+ unsigned int mSemantic;
+
+ /** Textures: Specifies the index of the texture.
+ * For non-texture properties, this member is always 0.
+ */
+ unsigned int mIndex;
+
+ /** Size of the buffer mData is pointing to, in bytes.
+ * This value may not be 0.
+ */
+ unsigned int mDataLength;
+
+ /** Type information for the property.
+ *
+ * Defines the data layout inside the data buffer. This is used
+ * by the library internally to perform debug checks and to
+ * utilize proper type conversions.
+ * (It's probably a hacky solution, but it works.)
+ */
+ C_ENUM aiPropertyTypeInfo mType;
+
+ /** Binary buffer to hold the property's value.
+ * The size of the buffer is always mDataLength.
+ */
+ char* mData;
+
+#ifdef __cplusplus
+
+ aiMaterialProperty() AI_NO_EXCEPT
+ : mSemantic( 0 )
+ , mIndex( 0 )
+ , mDataLength( 0 )
+ , mType( aiPTI_Float )
+ , mData(nullptr) {
+ // empty
+ }
+
+ ~aiMaterialProperty() {
+ delete[] mData;
+ mData = nullptr;
+ }
+
+#endif
+};
+//! @endcond
+
+#ifdef __cplusplus
+} // We need to leave the "C" block here to allow template member functions
+#endif
+
+// ---------------------------------------------------------------------------
+/** @brief Data structure for a material
+*
+* Material data is stored using a key-value structure. A single key-value
+* pair is called a 'material property'. C++ users should use the provided
+* member functions of aiMaterial to process material properties, C users
+* have to stick with the aiMaterialGetXXX family of unbound functions.
+* The library defines a set of standard keys (AI_MATKEY_XXX).
+*/
+#ifdef __cplusplus
+struct ASSIMP_API aiMaterial
+#else
+struct aiMaterial
+#endif
+{
+
+#ifdef __cplusplus
+
+public:
+
+ aiMaterial();
+ ~aiMaterial();
+
+ // -------------------------------------------------------------------
+ /**
+ * @brief Returns the name of the material.
+ * @return The name of the material.
+ */
+ // -------------------------------------------------------------------
+ aiString GetName();
+
+ // -------------------------------------------------------------------
+ /** @brief Retrieve an array of Type values with a specific key
+ * from the material
+ *
+ * @param pKey Key to search for. One of the AI_MATKEY_XXX constants.
+ * @param type .. set by AI_MATKEY_XXX
+ * @param idx .. set by AI_MATKEY_XXX
+ * @param pOut Pointer to a buffer to receive the result.
+ * @param pMax Specifies the size of the given buffer, in Type's.
+ * Receives the number of values (not bytes!) read.
+ * NULL is a valid value for this parameter.
+ */
+ template <typename Type>
+ aiReturn Get(const char* pKey,unsigned int type,
+ unsigned int idx, Type* pOut, unsigned int* pMax) const;
+
+ aiReturn Get(const char* pKey,unsigned int type,
+ unsigned int idx, int* pOut, unsigned int* pMax) const;
+
+ aiReturn Get(const char* pKey,unsigned int type,
+ unsigned int idx, ai_real* pOut, unsigned int* pMax) const;
+
+ // -------------------------------------------------------------------
+ /** @brief Retrieve a Type value with a specific key
+ * from the material
+ *
+ * @param pKey Key to search for. One of the AI_MATKEY_XXX constants.
+ * @param type Specifies the type of the texture to be retrieved (
+ * e.g. diffuse, specular, height map ...)
+ * @param idx Index of the texture to be retrieved.
+ * @param pOut Reference to receive the output value
+ */
+ template <typename Type>
+ aiReturn Get(const char* pKey,unsigned int type,
+ unsigned int idx,Type& pOut) const;
+
+
+ aiReturn Get(const char* pKey,unsigned int type,
+ unsigned int idx, int& pOut) const;
+
+ aiReturn Get(const char* pKey,unsigned int type,
+ unsigned int idx, ai_real& pOut) const;
+
+ aiReturn Get(const char* pKey,unsigned int type,
+ unsigned int idx, aiString& pOut) const;
+
+ aiReturn Get(const char* pKey,unsigned int type,
+ unsigned int idx, aiColor3D& pOut) const;
+
+ aiReturn Get(const char* pKey,unsigned int type,
+ unsigned int idx, aiColor4D& pOut) const;
+
+ aiReturn Get(const char* pKey,unsigned int type,
+ unsigned int idx, aiUVTransform& pOut) const;
+
+ // -------------------------------------------------------------------
+ /** Get the number of textures for a particular texture type.
+ * @param type Texture type to check for
+ * @return Number of textures for this type.
+ * @note A texture can be easily queried using #GetTexture() */
+ unsigned int GetTextureCount(aiTextureType type) const;
+
+ // -------------------------------------------------------------------
+ /** Helper function to get all parameters pertaining to a
+ * particular texture slot from a material.
+ *
+ * This function is provided just for convenience, you could also
+ * read the single material properties manually.
+ * @param type Specifies the type of the texture to be retrieved (
+ * e.g. diffuse, specular, height map ...)
+ * @param index Index of the texture to be retrieved. The function fails
+ * if there is no texture of that type with this index.
+ * #GetTextureCount() can be used to determine the number of textures
+ * per texture type.
+ * @param path Receives the path to the texture.
+ * If the texture is embedded, receives a '*' followed by the id of
+ * the texture (for the textures stored in the corresponding scene) which
+ * can be converted to an int using a function like atoi.
+ * NULL is a valid value.
+ * @param mapping The texture mapping.
+ * NULL is allowed as value.
+ * @param uvindex Receives the UV index of the texture.
+ * NULL is a valid value.
+ * @param blend Receives the blend factor for the texture
+ * NULL is a valid value.
+ * @param op Receives the texture operation to be performed between
+ * this texture and the previous texture. NULL is allowed as value.
+ * @param mapmode Receives the mapping modes to be used for the texture.
+ * The parameter may be NULL but if it is a valid pointer it MUST
+ * point to an array of 3 aiTextureMapMode's (one for each
+ * axis: UVW order (=XYZ)).
+ */
+ // -------------------------------------------------------------------
+ aiReturn GetTexture(aiTextureType type,
+ unsigned int index,
+ C_STRUCT aiString* path,
+ aiTextureMapping* mapping = NULL,
+ unsigned int* uvindex = NULL,
+ ai_real* blend = NULL,
+ aiTextureOp* op = NULL,
+ aiTextureMapMode* mapmode = NULL) const;
+
+
+ // Setters
+
+
+ // ------------------------------------------------------------------------------
+ /** @brief Add a property with a given key and type info to the material
+ * structure
+ *
+ * @param pInput Pointer to input data
+ * @param pSizeInBytes Size of input data
+ * @param pKey Key/Usage of the property (AI_MATKEY_XXX)
+ * @param type Set by the AI_MATKEY_XXX macro
+ * @param index Set by the AI_MATKEY_XXX macro
+ * @param pType Type information hint */
+ aiReturn AddBinaryProperty (const void* pInput,
+ unsigned int pSizeInBytes,
+ const char* pKey,
+ unsigned int type ,
+ unsigned int index ,
+ aiPropertyTypeInfo pType);
+
+ // ------------------------------------------------------------------------------
+ /** @brief Add a string property with a given key and type info to the
+ * material structure
+ *
+ * @param pInput Input string
+ * @param pKey Key/Usage of the property (AI_MATKEY_XXX)
+ * @param type Set by the AI_MATKEY_XXX macro
+ * @param index Set by the AI_MATKEY_XXX macro */
+ aiReturn AddProperty (const aiString* pInput,
+ const char* pKey,
+ unsigned int type = 0,
+ unsigned int index = 0);
+
+ // ------------------------------------------------------------------------------
+ /** @brief Add a property with a given key to the material structure
+ * @param pInput Pointer to the input data
+ * @param pNumValues Number of values in the array
+ * @param pKey Key/Usage of the property (AI_MATKEY_XXX)
+ * @param type Set by the AI_MATKEY_XXX macro
+ * @param index Set by the AI_MATKEY_XXX macro */
+ template<class TYPE>
+ aiReturn AddProperty (const TYPE* pInput,
+ unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type = 0,
+ unsigned int index = 0);
+
+ aiReturn AddProperty (const aiVector3D* pInput,
+ unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type = 0,
+ unsigned int index = 0);
+
+ aiReturn AddProperty (const aiColor3D* pInput,
+ unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type = 0,
+ unsigned int index = 0);
+
+ aiReturn AddProperty (const aiColor4D* pInput,
+ unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type = 0,
+ unsigned int index = 0);
+
+ aiReturn AddProperty (const int* pInput,
+ unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type = 0,
+ unsigned int index = 0);
+
+ aiReturn AddProperty (const float* pInput,
+ unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type = 0,
+ unsigned int index = 0);
+
+ aiReturn AddProperty (const double* pInput,
+ unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type = 0,
+ unsigned int index = 0);
+
+ aiReturn AddProperty (const aiUVTransform* pInput,
+ unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type = 0,
+ unsigned int index = 0);
+
+ // ------------------------------------------------------------------------------
+ /** @brief Remove a given key from the list.
+ *
+ * The function fails if the key isn't found
+ * @param pKey Key to be deleted
+ * @param type Set by the AI_MATKEY_XXX macro
+ * @param index Set by the AI_MATKEY_XXX macro */
+ aiReturn RemoveProperty (const char* pKey,
+ unsigned int type = 0,
+ unsigned int index = 0);
+
+ // ------------------------------------------------------------------------------
+ /** @brief Removes all properties from the material.
+ *
+ * The data array remains allocated so adding new properties is quite fast. */
+ void Clear();
+
+ // ------------------------------------------------------------------------------
+ /** Copy the property list of a material
+ * @param pcDest Destination material
+ * @param pcSrc Source material
+ */
+ static void CopyPropertyList(aiMaterial* pcDest,
+ const aiMaterial* pcSrc);
+
+
+#endif
+
+ /** List of all material properties loaded. */
+ C_STRUCT aiMaterialProperty** mProperties;
+
+ /** Number of properties in the data base */
+ unsigned int mNumProperties;
+
+ /** Storage allocated */
+ unsigned int mNumAllocated;
+};
+
+// Go back to extern "C" again
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// ---------------------------------------------------------------------------
+#define AI_MATKEY_NAME "?mat.name",0,0
+#define AI_MATKEY_TWOSIDED "$mat.twosided",0,0
+#define AI_MATKEY_SHADING_MODEL "$mat.shadingm",0,0
+#define AI_MATKEY_ENABLE_WIREFRAME "$mat.wireframe",0,0
+#define AI_MATKEY_BLEND_FUNC "$mat.blend",0,0
+#define AI_MATKEY_OPACITY "$mat.opacity",0,0
+#define AI_MATKEY_TRANSPARENCYFACTOR "$mat.transparencyfactor",0,0
+#define AI_MATKEY_BUMPSCALING "$mat.bumpscaling",0,0
+#define AI_MATKEY_SHININESS "$mat.shininess",0,0
+#define AI_MATKEY_REFLECTIVITY "$mat.reflectivity",0,0
+#define AI_MATKEY_SHININESS_STRENGTH "$mat.shinpercent",0,0
+#define AI_MATKEY_REFRACTI "$mat.refracti",0,0
+#define AI_MATKEY_COLOR_DIFFUSE "$clr.diffuse",0,0
+#define AI_MATKEY_COLOR_AMBIENT "$clr.ambient",0,0
+#define AI_MATKEY_COLOR_SPECULAR "$clr.specular",0,0
+#define AI_MATKEY_COLOR_EMISSIVE "$clr.emissive",0,0
+#define AI_MATKEY_COLOR_TRANSPARENT "$clr.transparent",0,0
+#define AI_MATKEY_COLOR_REFLECTIVE "$clr.reflective",0,0
+#define AI_MATKEY_GLOBAL_BACKGROUND_IMAGE "?bg.global",0,0
+#define AI_MATKEY_GLOBAL_SHADERLANG "?sh.lang",0,0
+#define AI_MATKEY_SHADER_VERTEX "?sh.vs",0,0
+#define AI_MATKEY_SHADER_FRAGMENT "?sh.fs",0,0
+#define AI_MATKEY_SHADER_GEO "?sh.gs",0,0
+#define AI_MATKEY_SHADER_TESSELATION "?sh.ts",0,0
+#define AI_MATKEY_SHADER_PRIMITIVE "?sh.ps",0,0
+#define AI_MATKEY_SHADER_COMPUTE "?sh.cs",0,0
+
+// ---------------------------------------------------------------------------
+// Pure key names for all texture-related properties
+//! @cond MATS_DOC_FULL
+#define _AI_MATKEY_TEXTURE_BASE "$tex.file"
+#define _AI_MATKEY_UVWSRC_BASE "$tex.uvwsrc"
+#define _AI_MATKEY_TEXOP_BASE "$tex.op"
+#define _AI_MATKEY_MAPPING_BASE "$tex.mapping"
+#define _AI_MATKEY_TEXBLEND_BASE "$tex.blend"
+#define _AI_MATKEY_MAPPINGMODE_U_BASE "$tex.mapmodeu"
+#define _AI_MATKEY_MAPPINGMODE_V_BASE "$tex.mapmodev"
+#define _AI_MATKEY_TEXMAP_AXIS_BASE "$tex.mapaxis"
+#define _AI_MATKEY_UVTRANSFORM_BASE "$tex.uvtrafo"
+#define _AI_MATKEY_TEXFLAGS_BASE "$tex.flags"
+//! @endcond
+
+// ---------------------------------------------------------------------------
+#define AI_MATKEY_TEXTURE(type, N) _AI_MATKEY_TEXTURE_BASE,type,N
+
+// For backward compatibility and simplicity
+//! @cond MATS_DOC_FULL
+#define AI_MATKEY_TEXTURE_DIFFUSE(N) \
+ AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE,N)
+
+#define AI_MATKEY_TEXTURE_SPECULAR(N) \
+ AI_MATKEY_TEXTURE(aiTextureType_SPECULAR,N)
+
+#define AI_MATKEY_TEXTURE_AMBIENT(N) \
+ AI_MATKEY_TEXTURE(aiTextureType_AMBIENT,N)
+
+#define AI_MATKEY_TEXTURE_EMISSIVE(N) \
+ AI_MATKEY_TEXTURE(aiTextureType_EMISSIVE,N)
+
+#define AI_MATKEY_TEXTURE_NORMALS(N) \
+ AI_MATKEY_TEXTURE(aiTextureType_NORMALS,N)
+
+#define AI_MATKEY_TEXTURE_HEIGHT(N) \
+ AI_MATKEY_TEXTURE(aiTextureType_HEIGHT,N)
+
+#define AI_MATKEY_TEXTURE_SHININESS(N) \
+ AI_MATKEY_TEXTURE(aiTextureType_SHININESS,N)
+
+#define AI_MATKEY_TEXTURE_OPACITY(N) \
+ AI_MATKEY_TEXTURE(aiTextureType_OPACITY,N)
+
+#define AI_MATKEY_TEXTURE_DISPLACEMENT(N) \
+ AI_MATKEY_TEXTURE(aiTextureType_DISPLACEMENT,N)
+
+#define AI_MATKEY_TEXTURE_LIGHTMAP(N) \
+ AI_MATKEY_TEXTURE(aiTextureType_LIGHTMAP,N)
+
+#define AI_MATKEY_TEXTURE_REFLECTION(N) \
+ AI_MATKEY_TEXTURE(aiTextureType_REFLECTION,N)
+
+//! @endcond
+
+// ---------------------------------------------------------------------------
+#define AI_MATKEY_UVWSRC(type, N) _AI_MATKEY_UVWSRC_BASE,type,N
+
+// For backward compatibility and simplicity
+//! @cond MATS_DOC_FULL
+#define AI_MATKEY_UVWSRC_DIFFUSE(N) \
+ AI_MATKEY_UVWSRC(aiTextureType_DIFFUSE,N)
+
+#define AI_MATKEY_UVWSRC_SPECULAR(N) \
+ AI_MATKEY_UVWSRC(aiTextureType_SPECULAR,N)
+
+#define AI_MATKEY_UVWSRC_AMBIENT(N) \
+ AI_MATKEY_UVWSRC(aiTextureType_AMBIENT,N)
+
+#define AI_MATKEY_UVWSRC_EMISSIVE(N) \
+ AI_MATKEY_UVWSRC(aiTextureType_EMISSIVE,N)
+
+#define AI_MATKEY_UVWSRC_NORMALS(N) \
+ AI_MATKEY_UVWSRC(aiTextureType_NORMALS,N)
+
+#define AI_MATKEY_UVWSRC_HEIGHT(N) \
+ AI_MATKEY_UVWSRC(aiTextureType_HEIGHT,N)
+
+#define AI_MATKEY_UVWSRC_SHININESS(N) \
+ AI_MATKEY_UVWSRC(aiTextureType_SHININESS,N)
+
+#define AI_MATKEY_UVWSRC_OPACITY(N) \
+ AI_MATKEY_UVWSRC(aiTextureType_OPACITY,N)
+
+#define AI_MATKEY_UVWSRC_DISPLACEMENT(N) \
+ AI_MATKEY_UVWSRC(aiTextureType_DISPLACEMENT,N)
+
+#define AI_MATKEY_UVWSRC_LIGHTMAP(N) \
+ AI_MATKEY_UVWSRC(aiTextureType_LIGHTMAP,N)
+
+#define AI_MATKEY_UVWSRC_REFLECTION(N) \
+ AI_MATKEY_UVWSRC(aiTextureType_REFLECTION,N)
+
+//! @endcond
+// ---------------------------------------------------------------------------
+#define AI_MATKEY_TEXOP(type, N) _AI_MATKEY_TEXOP_BASE,type,N
+
+// For backward compatibility and simplicity
+//! @cond MATS_DOC_FULL
+#define AI_MATKEY_TEXOP_DIFFUSE(N) \
+ AI_MATKEY_TEXOP(aiTextureType_DIFFUSE,N)
+
+#define AI_MATKEY_TEXOP_SPECULAR(N) \
+ AI_MATKEY_TEXOP(aiTextureType_SPECULAR,N)
+
+#define AI_MATKEY_TEXOP_AMBIENT(N) \
+ AI_MATKEY_TEXOP(aiTextureType_AMBIENT,N)
+
+#define AI_MATKEY_TEXOP_EMISSIVE(N) \
+ AI_MATKEY_TEXOP(aiTextureType_EMISSIVE,N)
+
+#define AI_MATKEY_TEXOP_NORMALS(N) \
+ AI_MATKEY_TEXOP(aiTextureType_NORMALS,N)
+
+#define AI_MATKEY_TEXOP_HEIGHT(N) \
+ AI_MATKEY_TEXOP(aiTextureType_HEIGHT,N)
+
+#define AI_MATKEY_TEXOP_SHININESS(N) \
+ AI_MATKEY_TEXOP(aiTextureType_SHININESS,N)
+
+#define AI_MATKEY_TEXOP_OPACITY(N) \
+ AI_MATKEY_TEXOP(aiTextureType_OPACITY,N)
+
+#define AI_MATKEY_TEXOP_DISPLACEMENT(N) \
+ AI_MATKEY_TEXOP(aiTextureType_DISPLACEMENT,N)
+
+#define AI_MATKEY_TEXOP_LIGHTMAP(N) \
+ AI_MATKEY_TEXOP(aiTextureType_LIGHTMAP,N)
+
+#define AI_MATKEY_TEXOP_REFLECTION(N) \
+ AI_MATKEY_TEXOP(aiTextureType_REFLECTION,N)
+
+//! @endcond
+// ---------------------------------------------------------------------------
+#define AI_MATKEY_MAPPING(type, N) _AI_MATKEY_MAPPING_BASE,type,N
+
+// For backward compatibility and simplicity
+//! @cond MATS_DOC_FULL
+#define AI_MATKEY_MAPPING_DIFFUSE(N) \
+ AI_MATKEY_MAPPING(aiTextureType_DIFFUSE,N)
+
+#define AI_MATKEY_MAPPING_SPECULAR(N) \
+ AI_MATKEY_MAPPING(aiTextureType_SPECULAR,N)
+
+#define AI_MATKEY_MAPPING_AMBIENT(N) \
+ AI_MATKEY_MAPPING(aiTextureType_AMBIENT,N)
+
+#define AI_MATKEY_MAPPING_EMISSIVE(N) \
+ AI_MATKEY_MAPPING(aiTextureType_EMISSIVE,N)
+
+#define AI_MATKEY_MAPPING_NORMALS(N) \
+ AI_MATKEY_MAPPING(aiTextureType_NORMALS,N)
+
+#define AI_MATKEY_MAPPING_HEIGHT(N) \
+ AI_MATKEY_MAPPING(aiTextureType_HEIGHT,N)
+
+#define AI_MATKEY_MAPPING_SHININESS(N) \
+ AI_MATKEY_MAPPING(aiTextureType_SHININESS,N)
+
+#define AI_MATKEY_MAPPING_OPACITY(N) \
+ AI_MATKEY_MAPPING(aiTextureType_OPACITY,N)
+
+#define AI_MATKEY_MAPPING_DISPLACEMENT(N) \
+ AI_MATKEY_MAPPING(aiTextureType_DISPLACEMENT,N)
+
+#define AI_MATKEY_MAPPING_LIGHTMAP(N) \
+ AI_MATKEY_MAPPING(aiTextureType_LIGHTMAP,N)
+
+#define AI_MATKEY_MAPPING_REFLECTION(N) \
+ AI_MATKEY_MAPPING(aiTextureType_REFLECTION,N)
+
+//! @endcond
+// ---------------------------------------------------------------------------
+#define AI_MATKEY_TEXBLEND(type, N) _AI_MATKEY_TEXBLEND_BASE,type,N
+
+// For backward compatibility and simplicity
+//! @cond MATS_DOC_FULL
+#define AI_MATKEY_TEXBLEND_DIFFUSE(N) \
+ AI_MATKEY_TEXBLEND(aiTextureType_DIFFUSE,N)
+
+#define AI_MATKEY_TEXBLEND_SPECULAR(N) \
+ AI_MATKEY_TEXBLEND(aiTextureType_SPECULAR,N)
+
+#define AI_MATKEY_TEXBLEND_AMBIENT(N) \
+ AI_MATKEY_TEXBLEND(aiTextureType_AMBIENT,N)
+
+#define AI_MATKEY_TEXBLEND_EMISSIVE(N) \
+ AI_MATKEY_TEXBLEND(aiTextureType_EMISSIVE,N)
+
+#define AI_MATKEY_TEXBLEND_NORMALS(N) \
+ AI_MATKEY_TEXBLEND(aiTextureType_NORMALS,N)
+
+#define AI_MATKEY_TEXBLEND_HEIGHT(N) \
+ AI_MATKEY_TEXBLEND(aiTextureType_HEIGHT,N)
+
+#define AI_MATKEY_TEXBLEND_SHININESS(N) \
+ AI_MATKEY_TEXBLEND(aiTextureType_SHININESS,N)
+
+#define AI_MATKEY_TEXBLEND_OPACITY(N) \
+ AI_MATKEY_TEXBLEND(aiTextureType_OPACITY,N)
+
+#define AI_MATKEY_TEXBLEND_DISPLACEMENT(N) \
+ AI_MATKEY_TEXBLEND(aiTextureType_DISPLACEMENT,N)
+
+#define AI_MATKEY_TEXBLEND_LIGHTMAP(N) \
+ AI_MATKEY_TEXBLEND(aiTextureType_LIGHTMAP,N)
+
+#define AI_MATKEY_TEXBLEND_REFLECTION(N) \
+ AI_MATKEY_TEXBLEND(aiTextureType_REFLECTION,N)
+
+//! @endcond
+// ---------------------------------------------------------------------------
+#define AI_MATKEY_MAPPINGMODE_U(type, N) _AI_MATKEY_MAPPINGMODE_U_BASE,type,N
+
+// For backward compatibility and simplicity
+//! @cond MATS_DOC_FULL
+#define AI_MATKEY_MAPPINGMODE_U_DIFFUSE(N) \
+ AI_MATKEY_MAPPINGMODE_U(aiTextureType_DIFFUSE,N)
+
+#define AI_MATKEY_MAPPINGMODE_U_SPECULAR(N) \
+ AI_MATKEY_MAPPINGMODE_U(aiTextureType_SPECULAR,N)
+
+#define AI_MATKEY_MAPPINGMODE_U_AMBIENT(N) \
+ AI_MATKEY_MAPPINGMODE_U(aiTextureType_AMBIENT,N)
+
+#define AI_MATKEY_MAPPINGMODE_U_EMISSIVE(N) \
+ AI_MATKEY_MAPPINGMODE_U(aiTextureType_EMISSIVE,N)
+
+#define AI_MATKEY_MAPPINGMODE_U_NORMALS(N) \
+ AI_MATKEY_MAPPINGMODE_U(aiTextureType_NORMALS,N)
+
+#define AI_MATKEY_MAPPINGMODE_U_HEIGHT(N) \
+ AI_MATKEY_MAPPINGMODE_U(aiTextureType_HEIGHT,N)
+
+#define AI_MATKEY_MAPPINGMODE_U_SHININESS(N) \
+ AI_MATKEY_MAPPINGMODE_U(aiTextureType_SHININESS,N)
+
+#define AI_MATKEY_MAPPINGMODE_U_OPACITY(N) \
+ AI_MATKEY_MAPPINGMODE_U(aiTextureType_OPACITY,N)
+
+#define AI_MATKEY_MAPPINGMODE_U_DISPLACEMENT(N) \
+ AI_MATKEY_MAPPINGMODE_U(aiTextureType_DISPLACEMENT,N)
+
+#define AI_MATKEY_MAPPINGMODE_U_LIGHTMAP(N) \
+ AI_MATKEY_MAPPINGMODE_U(aiTextureType_LIGHTMAP,N)
+
+#define AI_MATKEY_MAPPINGMODE_U_REFLECTION(N) \
+ AI_MATKEY_MAPPINGMODE_U(aiTextureType_REFLECTION,N)
+
+//! @endcond
+// ---------------------------------------------------------------------------
+#define AI_MATKEY_MAPPINGMODE_V(type, N) _AI_MATKEY_MAPPINGMODE_V_BASE,type,N
+
+// For backward compatibility and simplicity
+//! @cond MATS_DOC_FULL
+#define AI_MATKEY_MAPPINGMODE_V_DIFFUSE(N) \
+ AI_MATKEY_MAPPINGMODE_V(aiTextureType_DIFFUSE,N)
+
+#define AI_MATKEY_MAPPINGMODE_V_SPECULAR(N) \
+ AI_MATKEY_MAPPINGMODE_V(aiTextureType_SPECULAR,N)
+
+#define AI_MATKEY_MAPPINGMODE_V_AMBIENT(N) \
+ AI_MATKEY_MAPPINGMODE_V(aiTextureType_AMBIENT,N)
+
+#define AI_MATKEY_MAPPINGMODE_V_EMISSIVE(N) \
+ AI_MATKEY_MAPPINGMODE_V(aiTextureType_EMISSIVE,N)
+
+#define AI_MATKEY_MAPPINGMODE_V_NORMALS(N) \
+ AI_MATKEY_MAPPINGMODE_V(aiTextureType_NORMALS,N)
+
+#define AI_MATKEY_MAPPINGMODE_V_HEIGHT(N) \
+ AI_MATKEY_MAPPINGMODE_V(aiTextureType_HEIGHT,N)
+
+#define AI_MATKEY_MAPPINGMODE_V_SHININESS(N) \
+ AI_MATKEY_MAPPINGMODE_V(aiTextureType_SHININESS,N)
+
+#define AI_MATKEY_MAPPINGMODE_V_OPACITY(N) \
+ AI_MATKEY_MAPPINGMODE_V(aiTextureType_OPACITY,N)
+
+#define AI_MATKEY_MAPPINGMODE_V_DISPLACEMENT(N) \
+ AI_MATKEY_MAPPINGMODE_V(aiTextureType_DISPLACEMENT,N)
+
+#define AI_MATKEY_MAPPINGMODE_V_LIGHTMAP(N) \
+ AI_MATKEY_MAPPINGMODE_V(aiTextureType_LIGHTMAP,N)
+
+#define AI_MATKEY_MAPPINGMODE_V_REFLECTION(N) \
+ AI_MATKEY_MAPPINGMODE_V(aiTextureType_REFLECTION,N)
+
+//! @endcond
+// ---------------------------------------------------------------------------
+#define AI_MATKEY_TEXMAP_AXIS(type, N) _AI_MATKEY_TEXMAP_AXIS_BASE,type,N
+
+// For backward compatibility and simplicity
+//! @cond MATS_DOC_FULL
+#define AI_MATKEY_TEXMAP_AXIS_DIFFUSE(N) \
+ AI_MATKEY_TEXMAP_AXIS(aiTextureType_DIFFUSE,N)
+
+#define AI_MATKEY_TEXMAP_AXIS_SPECULAR(N) \
+ AI_MATKEY_TEXMAP_AXIS(aiTextureType_SPECULAR,N)
+
+#define AI_MATKEY_TEXMAP_AXIS_AMBIENT(N) \
+ AI_MATKEY_TEXMAP_AXIS(aiTextureType_AMBIENT,N)
+
+#define AI_MATKEY_TEXMAP_AXIS_EMISSIVE(N) \
+ AI_MATKEY_TEXMAP_AXIS(aiTextureType_EMISSIVE,N)
+
+#define AI_MATKEY_TEXMAP_AXIS_NORMALS(N) \
+ AI_MATKEY_TEXMAP_AXIS(aiTextureType_NORMALS,N)
+
+#define AI_MATKEY_TEXMAP_AXIS_HEIGHT(N) \
+ AI_MATKEY_TEXMAP_AXIS(aiTextureType_HEIGHT,N)
+
+#define AI_MATKEY_TEXMAP_AXIS_SHININESS(N) \
+ AI_MATKEY_TEXMAP_AXIS(aiTextureType_SHININESS,N)
+
+#define AI_MATKEY_TEXMAP_AXIS_OPACITY(N) \
+ AI_MATKEY_TEXMAP_AXIS(aiTextureType_OPACITY,N)
+
+#define AI_MATKEY_TEXMAP_AXIS_DISPLACEMENT(N) \
+ AI_MATKEY_TEXMAP_AXIS(aiTextureType_DISPLACEMENT,N)
+
+#define AI_MATKEY_TEXMAP_AXIS_LIGHTMAP(N) \
+ AI_MATKEY_TEXMAP_AXIS(aiTextureType_LIGHTMAP,N)
+
+#define AI_MATKEY_TEXMAP_AXIS_REFLECTION(N) \
+ AI_MATKEY_TEXMAP_AXIS(aiTextureType_REFLECTION,N)
+
+//! @endcond
+// ---------------------------------------------------------------------------
+#define AI_MATKEY_UVTRANSFORM(type, N) _AI_MATKEY_UVTRANSFORM_BASE,type,N
+
+// For backward compatibility and simplicity
+//! @cond MATS_DOC_FULL
+#define AI_MATKEY_UVTRANSFORM_DIFFUSE(N) \
+ AI_MATKEY_UVTRANSFORM(aiTextureType_DIFFUSE,N)
+
+#define AI_MATKEY_UVTRANSFORM_SPECULAR(N) \
+ AI_MATKEY_UVTRANSFORM(aiTextureType_SPECULAR,N)
+
+#define AI_MATKEY_UVTRANSFORM_AMBIENT(N) \
+ AI_MATKEY_UVTRANSFORM(aiTextureType_AMBIENT,N)
+
+#define AI_MATKEY_UVTRANSFORM_EMISSIVE(N) \
+ AI_MATKEY_UVTRANSFORM(aiTextureType_EMISSIVE,N)
+
+#define AI_MATKEY_UVTRANSFORM_NORMALS(N) \
+ AI_MATKEY_UVTRANSFORM(aiTextureType_NORMALS,N)
+
+#define AI_MATKEY_UVTRANSFORM_HEIGHT(N) \
+ AI_MATKEY_UVTRANSFORM(aiTextureType_HEIGHT,N)
+
+#define AI_MATKEY_UVTRANSFORM_SHININESS(N) \
+ AI_MATKEY_UVTRANSFORM(aiTextureType_SHININESS,N)
+
+#define AI_MATKEY_UVTRANSFORM_OPACITY(N) \
+ AI_MATKEY_UVTRANSFORM(aiTextureType_OPACITY,N)
+
+#define AI_MATKEY_UVTRANSFORM_DISPLACEMENT(N) \
+ AI_MATKEY_UVTRANSFORM(aiTextureType_DISPLACEMENT,N)
+
+#define AI_MATKEY_UVTRANSFORM_LIGHTMAP(N) \
+ AI_MATKEY_UVTRANSFORM(aiTextureType_LIGHTMAP,N)
+
+#define AI_MATKEY_UVTRANSFORM_REFLECTION(N) \
+ AI_MATKEY_UVTRANSFORM(aiTextureType_REFLECTION,N)
+
+#define AI_MATKEY_UVTRANSFORM_UNKNOWN(N) \
+ AI_MATKEY_UVTRANSFORM(aiTextureType_UNKNOWN,N)
+
+//! @endcond
+// ---------------------------------------------------------------------------
+#define AI_MATKEY_TEXFLAGS(type, N) _AI_MATKEY_TEXFLAGS_BASE,type,N
+
+// For backward compatibility and simplicity
+//! @cond MATS_DOC_FULL
+#define AI_MATKEY_TEXFLAGS_DIFFUSE(N) \
+ AI_MATKEY_TEXFLAGS(aiTextureType_DIFFUSE,N)
+
+#define AI_MATKEY_TEXFLAGS_SPECULAR(N) \
+ AI_MATKEY_TEXFLAGS(aiTextureType_SPECULAR,N)
+
+#define AI_MATKEY_TEXFLAGS_AMBIENT(N) \
+ AI_MATKEY_TEXFLAGS(aiTextureType_AMBIENT,N)
+
+#define AI_MATKEY_TEXFLAGS_EMISSIVE(N) \
+ AI_MATKEY_TEXFLAGS(aiTextureType_EMISSIVE,N)
+
+#define AI_MATKEY_TEXFLAGS_NORMALS(N) \
+ AI_MATKEY_TEXFLAGS(aiTextureType_NORMALS,N)
+
+#define AI_MATKEY_TEXFLAGS_HEIGHT(N) \
+ AI_MATKEY_TEXFLAGS(aiTextureType_HEIGHT,N)
+
+#define AI_MATKEY_TEXFLAGS_SHININESS(N) \
+ AI_MATKEY_TEXFLAGS(aiTextureType_SHININESS,N)
+
+#define AI_MATKEY_TEXFLAGS_OPACITY(N) \
+ AI_MATKEY_TEXFLAGS(aiTextureType_OPACITY,N)
+
+#define AI_MATKEY_TEXFLAGS_DISPLACEMENT(N) \
+ AI_MATKEY_TEXFLAGS(aiTextureType_DISPLACEMENT,N)
+
+#define AI_MATKEY_TEXFLAGS_LIGHTMAP(N) \
+ AI_MATKEY_TEXFLAGS(aiTextureType_LIGHTMAP,N)
+
+#define AI_MATKEY_TEXFLAGS_REFLECTION(N) \
+ AI_MATKEY_TEXFLAGS(aiTextureType_REFLECTION,N)
+
+#define AI_MATKEY_TEXFLAGS_UNKNOWN(N) \
+ AI_MATKEY_TEXFLAGS(aiTextureType_UNKNOWN,N)
+
+//! @endcond
+//!
+// ---------------------------------------------------------------------------
+/** @brief Retrieve a material property with a specific key from the material
+ *
+ * @param pMat Pointer to the input material. May not be NULL
+ * @param pKey Key to search for. One of the AI_MATKEY_XXX constants.
+ * @param type Specifies the type of the texture to be retrieved (
+ * e.g. diffuse, specular, height map ...)
+ * @param index Index of the texture to be retrieved.
+ * @param pPropOut Pointer to receive a pointer to a valid aiMaterialProperty
+ * structure or NULL if the key has not been found. */
+// ---------------------------------------------------------------------------
+ASSIMP_API C_ENUM aiReturn aiGetMaterialProperty(
+ const C_STRUCT aiMaterial* pMat,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index,
+ const C_STRUCT aiMaterialProperty** pPropOut);
+
+// ---------------------------------------------------------------------------
+/** @brief Retrieve an array of float values with a specific key
+ * from the material
+ *
+ * Pass one of the AI_MATKEY_XXX constants for the last three parameters (the
+ * example reads the #AI_MATKEY_UVTRANSFORM property of the first diffuse texture)
+ * @code
+ * aiUVTransform trafo;
+ * unsigned int max = sizeof(aiUVTransform);
+ * if (AI_SUCCESS != aiGetMaterialFloatArray(mat, AI_MATKEY_UVTRANSFORM(aiTextureType_DIFFUSE,0),
+ * (float*)&trafo, &max) || sizeof(aiUVTransform) != max)
+ * {
+ * // error handling
+ * }
+ * @endcode
+ *
+ * @param pMat Pointer to the input material. May not be NULL
+ * @param pKey Key to search for. One of the AI_MATKEY_XXX constants.
+ * @param pOut Pointer to a buffer to receive the result.
+ * @param pMax Specifies the size of the given buffer, in float's.
+ * Receives the number of values (not bytes!) read.
+ * @param type (see the code sample above)
+ * @param index (see the code sample above)
+ * @return Specifies whether the key has been found. If not, the output
+ * arrays remains unmodified and pMax is set to 0.*/
+// ---------------------------------------------------------------------------
+ASSIMP_API C_ENUM aiReturn aiGetMaterialFloatArray(
+ const C_STRUCT aiMaterial* pMat,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index,
+ ai_real* pOut,
+ unsigned int* pMax);
+
+
+#ifdef __cplusplus
+
+// ---------------------------------------------------------------------------
+/** @brief Retrieve a single float property with a specific key from the material.
+*
+* Pass one of the AI_MATKEY_XXX constants for the last three parameters (the
+* example reads the #AI_MATKEY_SHININESS_STRENGTH property of the first diffuse texture)
+* @code
+* float specStrength = 1.f; // default value, remains unmodified if we fail.
+* aiGetMaterialFloat(mat, AI_MATKEY_SHININESS_STRENGTH,
+* (float*)&specStrength);
+* @endcode
+*
+* @param pMat Pointer to the input material. May not be NULL
+* @param pKey Key to search for. One of the AI_MATKEY_XXX constants.
+* @param pOut Receives the output float.
+* @param type (see the code sample above)
+* @param index (see the code sample above)
+* @return Specifies whether the key has been found. If not, the output
+* float remains unmodified.*/
+// ---------------------------------------------------------------------------
+inline aiReturn aiGetMaterialFloat(const aiMaterial* pMat,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index,
+ ai_real* pOut)
+{
+ return aiGetMaterialFloatArray(pMat,pKey,type,index,pOut,(unsigned int*)0x0);
+}
+
+#else
+
+// Use our friend, the C preprocessor
+#define aiGetMaterialFloat (pMat, type, index, pKey, pOut) \
+ aiGetMaterialFloatArray(pMat, type, index, pKey, pOut, NULL)
+
+#endif //!__cplusplus
+
+
+// ---------------------------------------------------------------------------
+/** @brief Retrieve an array of integer values with a specific key
+ * from a material
+ *
+ * See the sample for aiGetMaterialFloatArray for more information.*/
+ASSIMP_API C_ENUM aiReturn aiGetMaterialIntegerArray(const C_STRUCT aiMaterial* pMat,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index,
+ int* pOut,
+ unsigned int* pMax);
+
+
+#ifdef __cplusplus
+
+// ---------------------------------------------------------------------------
+/** @brief Retrieve an integer property with a specific key from a material
+ *
+ * See the sample for aiGetMaterialFloat for more information.*/
+// ---------------------------------------------------------------------------
+inline aiReturn aiGetMaterialInteger(const C_STRUCT aiMaterial* pMat,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index,
+ int* pOut)
+{
+ return aiGetMaterialIntegerArray(pMat,pKey,type,index,pOut,(unsigned int*)0x0);
+}
+
+#else
+
+// use our friend, the C preprocessor
+#define aiGetMaterialInteger (pMat, type, index, pKey, pOut) \
+ aiGetMaterialIntegerArray(pMat, type, index, pKey, pOut, NULL)
+
+#endif //!__cplusplus
+
+// ---------------------------------------------------------------------------
+/** @brief Retrieve a color value from the material property table
+*
+* See the sample for aiGetMaterialFloat for more information*/
+// ---------------------------------------------------------------------------
+ASSIMP_API C_ENUM aiReturn aiGetMaterialColor(const C_STRUCT aiMaterial* pMat,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index,
+ C_STRUCT aiColor4D* pOut);
+
+
+// ---------------------------------------------------------------------------
+/** @brief Retrieve a aiUVTransform value from the material property table
+*
+* See the sample for aiGetMaterialFloat for more information*/
+// ---------------------------------------------------------------------------
+ASSIMP_API C_ENUM aiReturn aiGetMaterialUVTransform(const C_STRUCT aiMaterial* pMat,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index,
+ C_STRUCT aiUVTransform* pOut);
+
+
+// ---------------------------------------------------------------------------
+/** @brief Retrieve a string from the material property table
+*
+* See the sample for aiGetMaterialFloat for more information.*/
+// ---------------------------------------------------------------------------
+ASSIMP_API C_ENUM aiReturn aiGetMaterialString(const C_STRUCT aiMaterial* pMat,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index,
+ C_STRUCT aiString* pOut);
+
+// ---------------------------------------------------------------------------
+/** Get the number of textures for a particular texture type.
+ * @param[in] pMat Pointer to the input material. May not be NULL
+ * @param type Texture type to check for
+ * @return Number of textures for this type.
+ * @note A texture can be easily queried using #aiGetMaterialTexture() */
+// ---------------------------------------------------------------------------
+ASSIMP_API unsigned int aiGetMaterialTextureCount(const C_STRUCT aiMaterial* pMat,
+ C_ENUM aiTextureType type);
+
+// ---------------------------------------------------------------------------
+/** @brief Helper function to get all values pertaining to a particular
+ * texture slot from a material structure.
+ *
+ * This function is provided just for convenience. You could also read the
+ * texture by parsing all of its properties manually. This function bundles
+ * all of them in a huge function monster.
+ *
+ * @param[in] mat Pointer to the input material. May not be NULL
+ * @param[in] type Specifies the texture stack to read from (e.g. diffuse,
+ * specular, height map ...).
+ * @param[in] index Index of the texture. The function fails if the
+ * requested index is not available for this texture type.
+ * #aiGetMaterialTextureCount() can be used to determine the number of
+ * textures in a particular texture stack.
+ * @param[out] path Receives the output path
+ * If the texture is embedded, receives a '*' followed by the id of
+ * the texture (for the textures stored in the corresponding scene) which
+ * can be converted to an int using a function like atoi.
+ * This parameter must be non-null.
+ * @param mapping The texture mapping mode to be used.
+ * Pass NULL if you're not interested in this information.
+ * @param[out] uvindex For UV-mapped textures: receives the index of the UV
+ * source channel. Unmodified otherwise.
+ * Pass NULL if you're not interested in this information.
+ * @param[out] blend Receives the blend factor for the texture
+ * Pass NULL if you're not interested in this information.
+ * @param[out] op Receives the texture blend operation to be perform between
+ * this texture and the previous texture.
+ * Pass NULL if you're not interested in this information.
+ * @param[out] mapmode Receives the mapping modes to be used for the texture.
+ * Pass NULL if you're not interested in this information. Otherwise,
+ * pass a pointer to an array of two aiTextureMapMode's (one for each
+ * axis, UV order).
+ * @param[out] flags Receives the the texture flags.
+ * @return AI_SUCCESS on success, otherwise something else. Have fun.*/
+// ---------------------------------------------------------------------------
+#ifdef __cplusplus
+ASSIMP_API aiReturn aiGetMaterialTexture(const C_STRUCT aiMaterial* mat,
+ aiTextureType type,
+ unsigned int index,
+ aiString* path,
+ aiTextureMapping* mapping = NULL,
+ unsigned int* uvindex = NULL,
+ ai_real* blend = NULL,
+ aiTextureOp* op = NULL,
+ aiTextureMapMode* mapmode = NULL,
+ unsigned int* flags = NULL);
+#else
+C_ENUM aiReturn aiGetMaterialTexture(const C_STRUCT aiMaterial* mat,
+ C_ENUM aiTextureType type,
+ unsigned int index,
+ C_STRUCT aiString* path,
+ C_ENUM aiTextureMapping* mapping /*= NULL*/,
+ unsigned int* uvindex /*= NULL*/,
+ ai_real* blend /*= NULL*/,
+ C_ENUM aiTextureOp* op /*= NULL*/,
+ C_ENUM aiTextureMapMode* mapmode /*= NULL*/,
+ unsigned int* flags /*= NULL*/);
+#endif // !#ifdef __cplusplus
+
+
+#ifdef __cplusplus
+}
+
+#include "material.inl"
+
+#endif //!__cplusplus
+
+#endif //!!AI_MATERIAL_H_INC
diff --git a/thirdparty/assimp/include/assimp/material.inl b/thirdparty/assimp/include/assimp/material.inl
new file mode 100644
index 0000000000..b05d6af6c3
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/material.inl
@@ -0,0 +1,390 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file material.inl
+ * @brief Defines the C++ getters for the material system
+ */
+
+#pragma once
+#ifndef AI_MATERIAL_INL_INC
+#define AI_MATERIAL_INL_INC
+
+// ---------------------------------------------------------------------------
+inline aiPropertyTypeInfo ai_real_to_property_type_info(float)
+{
+ return aiPTI_Float;
+}
+
+inline aiPropertyTypeInfo ai_real_to_property_type_info(double)
+{
+ return aiPTI_Double;
+}
+// ---------------------------------------------------------------------------
+
+//! @cond never
+
+// ---------------------------------------------------------------------------
+inline aiReturn aiMaterial::GetTexture( aiTextureType type,
+ unsigned int index,
+ C_STRUCT aiString* path,
+ aiTextureMapping* mapping /*= NULL*/,
+ unsigned int* uvindex /*= NULL*/,
+ ai_real* blend /*= NULL*/,
+ aiTextureOp* op /*= NULL*/,
+ aiTextureMapMode* mapmode /*= NULL*/) const
+{
+ return ::aiGetMaterialTexture(this,type,index,path,mapping,uvindex,blend,op,mapmode);
+}
+
+// ---------------------------------------------------------------------------
+inline unsigned int aiMaterial::GetTextureCount(aiTextureType type) const
+{
+ return ::aiGetMaterialTextureCount(this,type);
+}
+
+// ---------------------------------------------------------------------------
+template <typename Type>
+inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
+ unsigned int idx, Type* pOut,
+ unsigned int* pMax) const
+{
+ unsigned int iNum = pMax ? *pMax : 1;
+
+ const aiMaterialProperty* prop;
+ const aiReturn ret = ::aiGetMaterialProperty(this,pKey,type,idx,
+ (const aiMaterialProperty**)&prop);
+ if ( AI_SUCCESS == ret ) {
+
+ if (prop->mDataLength < sizeof(Type)*iNum) {
+ return AI_FAILURE;
+ }
+
+ if (prop->mType != aiPTI_Buffer) {
+ return AI_FAILURE;
+ }
+
+ iNum = std::min((size_t)iNum,prop->mDataLength / sizeof(Type));
+ ::memcpy(pOut,prop->mData,iNum * sizeof(Type));
+ if (pMax) {
+ *pMax = iNum;
+ }
+ }
+ return ret;
+}
+
+// ---------------------------------------------------------------------------
+template <typename Type>
+inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
+ unsigned int idx,Type& pOut) const
+{
+ const aiMaterialProperty* prop;
+ const aiReturn ret = ::aiGetMaterialProperty(this,pKey,type,idx,
+ (const aiMaterialProperty**)&prop);
+ if ( AI_SUCCESS == ret ) {
+
+ if (prop->mDataLength < sizeof(Type)) {
+ return AI_FAILURE;
+ }
+
+ if (prop->mType != aiPTI_Buffer) {
+ return AI_FAILURE;
+ }
+
+ ::memcpy( &pOut, prop->mData, sizeof( Type ) );
+ }
+ return ret;
+}
+
+// ---------------------------------------------------------------------------
+inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
+ unsigned int idx,ai_real* pOut,
+ unsigned int* pMax) const
+{
+ return ::aiGetMaterialFloatArray(this,pKey,type,idx,pOut,pMax);
+}
+// ---------------------------------------------------------------------------
+inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
+ unsigned int idx,int* pOut,
+ unsigned int* pMax) const
+{
+ return ::aiGetMaterialIntegerArray(this,pKey,type,idx,pOut,pMax);
+}
+// ---------------------------------------------------------------------------
+inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
+ unsigned int idx,ai_real& pOut) const
+{
+ return aiGetMaterialFloat(this,pKey,type,idx,&pOut);
+}
+// ---------------------------------------------------------------------------
+inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
+ unsigned int idx,int& pOut) const
+{
+ return aiGetMaterialInteger(this,pKey,type,idx,&pOut);
+}
+// ---------------------------------------------------------------------------
+inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
+ unsigned int idx,aiColor4D& pOut) const
+{
+ return aiGetMaterialColor(this,pKey,type,idx,&pOut);
+}
+// ---------------------------------------------------------------------------
+inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
+ unsigned int idx,aiColor3D& pOut) const
+{
+ aiColor4D c;
+ const aiReturn ret = aiGetMaterialColor(this,pKey,type,idx,&c);
+ pOut = aiColor3D(c.r,c.g,c.b);
+ return ret;
+}
+// ---------------------------------------------------------------------------
+inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
+ unsigned int idx,aiString& pOut) const
+{
+ return aiGetMaterialString(this,pKey,type,idx,&pOut);
+}
+// ---------------------------------------------------------------------------
+inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
+ unsigned int idx,aiUVTransform& pOut) const
+{
+ return aiGetMaterialUVTransform(this,pKey,type,idx,&pOut);
+}
+
+
+// ---------------------------------------------------------------------------
+template<class TYPE>
+aiReturn aiMaterial::AddProperty (const TYPE* pInput,
+ const unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index)
+{
+ return AddBinaryProperty((const void*)pInput,
+ pNumValues * sizeof(TYPE),
+ pKey,type,index,aiPTI_Buffer);
+}
+
+// ---------------------------------------------------------------------------
+inline aiReturn aiMaterial::AddProperty(const float* pInput,
+ const unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index)
+{
+ return AddBinaryProperty((const void*)pInput,
+ pNumValues * sizeof(float),
+ pKey,type,index,aiPTI_Float);
+}
+
+// ---------------------------------------------------------------------------
+inline aiReturn aiMaterial::AddProperty(const double* pInput,
+ const unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index)
+{
+ return AddBinaryProperty((const void*)pInput,
+ pNumValues * sizeof(double),
+ pKey,type,index,aiPTI_Double);
+}
+
+// ---------------------------------------------------------------------------
+inline aiReturn aiMaterial::AddProperty(const aiUVTransform* pInput,
+ const unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index)
+{
+ return AddBinaryProperty((const void*)pInput,
+ pNumValues * sizeof(aiUVTransform),
+ pKey,type,index,ai_real_to_property_type_info(pInput->mRotation));
+}
+
+// ---------------------------------------------------------------------------
+inline aiReturn aiMaterial::AddProperty(const aiColor4D* pInput,
+ const unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index)
+{
+ return AddBinaryProperty((const void*)pInput,
+ pNumValues * sizeof(aiColor4D),
+ pKey,type,index,ai_real_to_property_type_info(pInput->a));
+}
+
+// ---------------------------------------------------------------------------
+inline aiReturn aiMaterial::AddProperty(const aiColor3D* pInput,
+ const unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index)
+{
+ return AddBinaryProperty((const void*)pInput,
+ pNumValues * sizeof(aiColor3D),
+ pKey,type,index,ai_real_to_property_type_info(pInput->b));
+}
+
+// ---------------------------------------------------------------------------
+inline aiReturn aiMaterial::AddProperty(const aiVector3D* pInput,
+ const unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index)
+{
+ return AddBinaryProperty((const void*)pInput,
+ pNumValues * sizeof(aiVector3D),
+ pKey,type,index,ai_real_to_property_type_info(pInput->x));
+}
+
+// ---------------------------------------------------------------------------
+inline aiReturn aiMaterial::AddProperty(const int* pInput,
+ const unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index)
+{
+ return AddBinaryProperty((const void*)pInput,
+ pNumValues * sizeof(int),
+ pKey,type,index,aiPTI_Integer);
+}
+
+
+// ---------------------------------------------------------------------------
+// The template specializations below are for backwards compatibility.
+// The recommended way to add material properties is using the non-template
+// overloads.
+// ---------------------------------------------------------------------------
+
+// ---------------------------------------------------------------------------
+template<>
+inline aiReturn aiMaterial::AddProperty<float>(const float* pInput,
+ const unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index)
+{
+ return AddBinaryProperty((const void*)pInput,
+ pNumValues * sizeof(float),
+ pKey,type,index,aiPTI_Float);
+}
+
+// ---------------------------------------------------------------------------
+template<>
+inline aiReturn aiMaterial::AddProperty<double>(const double* pInput,
+ const unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index)
+{
+ return AddBinaryProperty((const void*)pInput,
+ pNumValues * sizeof(double),
+ pKey,type,index,aiPTI_Double);
+}
+
+// ---------------------------------------------------------------------------
+template<>
+inline aiReturn aiMaterial::AddProperty<aiUVTransform>(const aiUVTransform* pInput,
+ const unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index)
+{
+ return AddBinaryProperty((const void*)pInput,
+ pNumValues * sizeof(aiUVTransform),
+ pKey,type,index,aiPTI_Float);
+}
+
+// ---------------------------------------------------------------------------
+template<>
+inline aiReturn aiMaterial::AddProperty<aiColor4D>(const aiColor4D* pInput,
+ const unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index)
+{
+ return AddBinaryProperty((const void*)pInput,
+ pNumValues * sizeof(aiColor4D),
+ pKey,type,index,aiPTI_Float);
+}
+
+// ---------------------------------------------------------------------------
+template<>
+inline aiReturn aiMaterial::AddProperty<aiColor3D>(const aiColor3D* pInput,
+ const unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index)
+{
+ return AddBinaryProperty((const void*)pInput,
+ pNumValues * sizeof(aiColor3D),
+ pKey,type,index,aiPTI_Float);
+}
+
+// ---------------------------------------------------------------------------
+template<>
+inline aiReturn aiMaterial::AddProperty<aiVector3D>(const aiVector3D* pInput,
+ const unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index)
+{
+ return AddBinaryProperty((const void*)pInput,
+ pNumValues * sizeof(aiVector3D),
+ pKey,type,index,aiPTI_Float);
+}
+
+// ---------------------------------------------------------------------------
+template<>
+inline aiReturn aiMaterial::AddProperty<int>(const int* pInput,
+ const unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index)
+{
+ return AddBinaryProperty((const void*)pInput,
+ pNumValues * sizeof(int),
+ pKey,type,index,aiPTI_Integer);
+}
+
+//! @endcond
+
+#endif //! AI_MATERIAL_INL_INC
diff --git a/thirdparty/assimp/include/assimp/matrix3x3.h b/thirdparty/assimp/include/assimp/matrix3x3.h
new file mode 100644
index 0000000000..22b69561ff
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/matrix3x3.h
@@ -0,0 +1,183 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file matrix3x3.h
+ * @brief Definition of a 3x3 matrix, including operators when compiling in C++
+ */
+#pragma once
+#ifndef AI_MATRIX3X3_H_INC
+#define AI_MATRIX3X3_H_INC
+
+#include "defs.h"
+
+#ifdef __cplusplus
+
+template <typename T> class aiMatrix4x4t;
+template <typename T> class aiVector2t;
+
+// ---------------------------------------------------------------------------
+/** @brief Represents a row-major 3x3 matrix
+ *
+ * There's much confusion about matrix layouts (column vs. row order).
+ * This is *always* a row-major matrix. Not even with the
+ * #aiProcess_ConvertToLeftHanded flag, which absolutely does not affect
+ * matrix order - it just affects the handedness of the coordinate system
+ * defined thereby.
+ */
+template <typename TReal>
+class aiMatrix3x3t
+{
+public:
+
+ aiMatrix3x3t() AI_NO_EXCEPT :
+ a1(static_cast<TReal>(1.0f)), a2(), a3(),
+ b1(), b2(static_cast<TReal>(1.0f)), b3(),
+ c1(), c2(), c3(static_cast<TReal>(1.0f)) {}
+
+ aiMatrix3x3t ( TReal _a1, TReal _a2, TReal _a3,
+ TReal _b1, TReal _b2, TReal _b3,
+ TReal _c1, TReal _c2, TReal _c3) :
+ a1(_a1), a2(_a2), a3(_a3),
+ b1(_b1), b2(_b2), b3(_b3),
+ c1(_c1), c2(_c2), c3(_c3)
+ {}
+
+public:
+
+ // matrix multiplication.
+ aiMatrix3x3t& operator *= (const aiMatrix3x3t& m);
+ aiMatrix3x3t operator * (const aiMatrix3x3t& m) const;
+
+ // array access operators
+ TReal* operator[] (unsigned int p_iIndex);
+ const TReal* operator[] (unsigned int p_iIndex) const;
+
+ // comparison operators
+ bool operator== (const aiMatrix4x4t<TReal>& m) const;
+ bool operator!= (const aiMatrix4x4t<TReal>& m) const;
+
+ bool Equal(const aiMatrix4x4t<TReal>& m, TReal epsilon = 1e-6) const;
+
+ template <typename TOther>
+ operator aiMatrix3x3t<TOther> () const;
+
+public:
+
+ // -------------------------------------------------------------------
+ /** @brief Construction from a 4x4 matrix. The remaining parts
+ * of the matrix are ignored.
+ */
+ explicit aiMatrix3x3t( const aiMatrix4x4t<TReal>& pMatrix);
+
+ // -------------------------------------------------------------------
+ /** @brief Transpose the matrix
+ */
+ aiMatrix3x3t& Transpose();
+
+ // -------------------------------------------------------------------
+ /** @brief Invert the matrix.
+ * If the matrix is not invertible all elements are set to qnan.
+ * Beware, use (f != f) to check whether a TReal f is qnan.
+ */
+ aiMatrix3x3t& Inverse();
+ TReal Determinant() const;
+
+public:
+ // -------------------------------------------------------------------
+ /** @brief Returns a rotation matrix for a rotation around z
+ * @param a Rotation angle, in radians
+ * @param out Receives the output matrix
+ * @return Reference to the output matrix
+ */
+ static aiMatrix3x3t& RotationZ(TReal a, aiMatrix3x3t& out);
+
+ // -------------------------------------------------------------------
+ /** @brief Returns a rotation matrix for a rotation around
+ * an arbitrary axis.
+ *
+ * @param a Rotation angle, in radians
+ * @param axis Axis to rotate around
+ * @param out To be filled
+ */
+ static aiMatrix3x3t& Rotation( TReal a,
+ const aiVector3t<TReal>& axis, aiMatrix3x3t& out);
+
+ // -------------------------------------------------------------------
+ /** @brief Returns a translation matrix
+ * @param v Translation vector
+ * @param out Receives the output matrix
+ * @return Reference to the output matrix
+ */
+ static aiMatrix3x3t& Translation( const aiVector2t<TReal>& v, aiMatrix3x3t& out);
+
+ // -------------------------------------------------------------------
+ /** @brief A function for creating a rotation matrix that rotates a
+ * vector called "from" into another vector called "to".
+ * Input : from[3], to[3] which both must be *normalized* non-zero vectors
+ * Output: mtx[3][3] -- a 3x3 matrix in column-major form
+ * Authors: Tomas Möller, John Hughes
+ * "Efficiently Building a Matrix to Rotate One Vector to Another"
+ * Journal of Graphics Tools, 4(4):1-4, 1999
+ */
+ static aiMatrix3x3t& FromToMatrix(const aiVector3t<TReal>& from,
+ const aiVector3t<TReal>& to, aiMatrix3x3t& out);
+
+public:
+ TReal a1, a2, a3;
+ TReal b1, b2, b3;
+ TReal c1, c2, c3;
+};
+
+typedef aiMatrix3x3t<ai_real> aiMatrix3x3;
+
+#else
+
+struct aiMatrix3x3 {
+ ai_real a1, a2, a3;
+ ai_real b1, b2, b3;
+ ai_real c1, c2, c3;
+};
+
+#endif // __cplusplus
+
+#endif // AI_MATRIX3X3_H_INC
diff --git a/thirdparty/assimp/include/assimp/matrix3x3.inl b/thirdparty/assimp/include/assimp/matrix3x3.inl
new file mode 100644
index 0000000000..d9d45a3e92
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/matrix3x3.inl
@@ -0,0 +1,357 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file matrix3x3.inl
+ * @brief Inline implementation of the 3x3 matrix operators
+ */
+#pragma once
+#ifndef AI_MATRIX3X3_INL_INC
+#define AI_MATRIX3X3_INL_INC
+
+#ifdef __cplusplus
+#include "matrix3x3.h"
+
+#include "matrix4x4.h"
+#include <algorithm>
+#include <cmath>
+#include <limits>
+
+// ------------------------------------------------------------------------------------------------
+// Construction from a 4x4 matrix. The remaining parts of the matrix are ignored.
+template <typename TReal>
+inline aiMatrix3x3t<TReal>::aiMatrix3x3t( const aiMatrix4x4t<TReal>& pMatrix)
+{
+ a1 = pMatrix.a1; a2 = pMatrix.a2; a3 = pMatrix.a3;
+ b1 = pMatrix.b1; b2 = pMatrix.b2; b3 = pMatrix.b3;
+ c1 = pMatrix.c1; c2 = pMatrix.c2; c3 = pMatrix.c3;
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+inline aiMatrix3x3t<TReal>& aiMatrix3x3t<TReal>::operator *= (const aiMatrix3x3t<TReal>& m)
+{
+ *this = aiMatrix3x3t<TReal>(m.a1 * a1 + m.b1 * a2 + m.c1 * a3,
+ m.a2 * a1 + m.b2 * a2 + m.c2 * a3,
+ m.a3 * a1 + m.b3 * a2 + m.c3 * a3,
+ m.a1 * b1 + m.b1 * b2 + m.c1 * b3,
+ m.a2 * b1 + m.b2 * b2 + m.c2 * b3,
+ m.a3 * b1 + m.b3 * b2 + m.c3 * b3,
+ m.a1 * c1 + m.b1 * c2 + m.c1 * c3,
+ m.a2 * c1 + m.b2 * c2 + m.c2 * c3,
+ m.a3 * c1 + m.b3 * c2 + m.c3 * c3);
+ return *this;
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+template <typename TOther>
+aiMatrix3x3t<TReal>::operator aiMatrix3x3t<TOther> () const
+{
+ return aiMatrix3x3t<TOther>(static_cast<TOther>(a1),static_cast<TOther>(a2),static_cast<TOther>(a3),
+ static_cast<TOther>(b1),static_cast<TOther>(b2),static_cast<TOther>(b3),
+ static_cast<TOther>(c1),static_cast<TOther>(c2),static_cast<TOther>(c3));
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+inline aiMatrix3x3t<TReal> aiMatrix3x3t<TReal>::operator* (const aiMatrix3x3t<TReal>& m) const
+{
+ aiMatrix3x3t<TReal> temp( *this);
+ temp *= m;
+ return temp;
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+inline TReal* aiMatrix3x3t<TReal>::operator[] (unsigned int p_iIndex) {
+ switch ( p_iIndex ) {
+ case 0:
+ return &a1;
+ case 1:
+ return &b1;
+ case 2:
+ return &c1;
+ default:
+ break;
+ }
+ return &a1;
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+inline const TReal* aiMatrix3x3t<TReal>::operator[] (unsigned int p_iIndex) const {
+ switch ( p_iIndex ) {
+ case 0:
+ return &a1;
+ case 1:
+ return &b1;
+ case 2:
+ return &c1;
+ default:
+ break;
+ }
+ return &a1;
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+inline bool aiMatrix3x3t<TReal>::operator== (const aiMatrix4x4t<TReal>& m) const
+{
+ return a1 == m.a1 && a2 == m.a2 && a3 == m.a3 &&
+ b1 == m.b1 && b2 == m.b2 && b3 == m.b3 &&
+ c1 == m.c1 && c2 == m.c2 && c3 == m.c3;
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+inline bool aiMatrix3x3t<TReal>::operator!= (const aiMatrix4x4t<TReal>& m) const
+{
+ return !(*this == m);
+}
+
+// ---------------------------------------------------------------------------
+template<typename TReal>
+inline bool aiMatrix3x3t<TReal>::Equal(const aiMatrix4x4t<TReal>& m, TReal epsilon) const {
+ return
+ std::abs(a1 - m.a1) <= epsilon &&
+ std::abs(a2 - m.a2) <= epsilon &&
+ std::abs(a3 - m.a3) <= epsilon &&
+ std::abs(b1 - m.b1) <= epsilon &&
+ std::abs(b2 - m.b2) <= epsilon &&
+ std::abs(b3 - m.b3) <= epsilon &&
+ std::abs(c1 - m.c1) <= epsilon &&
+ std::abs(c2 - m.c2) <= epsilon &&
+ std::abs(c3 - m.c3) <= epsilon;
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+inline aiMatrix3x3t<TReal>& aiMatrix3x3t<TReal>::Transpose()
+{
+ // (TReal&) don't remove, GCC complains cause of packed fields
+ std::swap( (TReal&)a2, (TReal&)b1);
+ std::swap( (TReal&)a3, (TReal&)c1);
+ std::swap( (TReal&)b3, (TReal&)c2);
+ return *this;
+}
+
+// ----------------------------------------------------------------------------------------
+template <typename TReal>
+inline TReal aiMatrix3x3t<TReal>::Determinant() const
+{
+ return a1*b2*c3 - a1*b3*c2 + a2*b3*c1 - a2*b1*c3 + a3*b1*c2 - a3*b2*c1;
+}
+
+// ----------------------------------------------------------------------------------------
+template <typename TReal>
+inline aiMatrix3x3t<TReal>& aiMatrix3x3t<TReal>::Inverse()
+{
+ // Compute the reciprocal determinant
+ TReal det = Determinant();
+ if(det == static_cast<TReal>(0.0))
+ {
+ // Matrix not invertible. Setting all elements to nan is not really
+ // correct in a mathematical sense; but at least qnans are easy to
+ // spot. XXX we might throw an exception instead, which would
+ // be even much better to spot :/.
+ const TReal nan = std::numeric_limits<TReal>::quiet_NaN();
+ *this = aiMatrix3x3t<TReal>( nan,nan,nan,nan,nan,nan,nan,nan,nan);
+
+ return *this;
+ }
+
+ TReal invdet = static_cast<TReal>(1.0) / det;
+
+ aiMatrix3x3t<TReal> res;
+ res.a1 = invdet * (b2 * c3 - b3 * c2);
+ res.a2 = -invdet * (a2 * c3 - a3 * c2);
+ res.a3 = invdet * (a2 * b3 - a3 * b2);
+ res.b1 = -invdet * (b1 * c3 - b3 * c1);
+ res.b2 = invdet * (a1 * c3 - a3 * c1);
+ res.b3 = -invdet * (a1 * b3 - a3 * b1);
+ res.c1 = invdet * (b1 * c2 - b2 * c1);
+ res.c2 = -invdet * (a1 * c2 - a2 * c1);
+ res.c3 = invdet * (a1 * b2 - a2 * b1);
+ *this = res;
+
+ return *this;
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+inline aiMatrix3x3t<TReal>& aiMatrix3x3t<TReal>::RotationZ(TReal a, aiMatrix3x3t<TReal>& out)
+{
+ out.a1 = out.b2 = std::cos(a);
+ out.b1 = std::sin(a);
+ out.a2 = - out.b1;
+
+ out.a3 = out.b3 = out.c1 = out.c2 = 0.f;
+ out.c3 = 1.f;
+
+ return out;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Returns a rotation matrix for a rotation around an arbitrary axis.
+template <typename TReal>
+inline aiMatrix3x3t<TReal>& aiMatrix3x3t<TReal>::Rotation( TReal a, const aiVector3t<TReal>& axis, aiMatrix3x3t<TReal>& out)
+{
+ TReal c = std::cos( a), s = std::sin( a), t = 1 - c;
+ TReal x = axis.x, y = axis.y, z = axis.z;
+
+ // Many thanks to MathWorld and Wikipedia
+ out.a1 = t*x*x + c; out.a2 = t*x*y - s*z; out.a3 = t*x*z + s*y;
+ out.b1 = t*x*y + s*z; out.b2 = t*y*y + c; out.b3 = t*y*z - s*x;
+ out.c1 = t*x*z - s*y; out.c2 = t*y*z + s*x; out.c3 = t*z*z + c;
+
+ return out;
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+inline aiMatrix3x3t<TReal>& aiMatrix3x3t<TReal>::Translation( const aiVector2t<TReal>& v, aiMatrix3x3t<TReal>& out)
+{
+ out = aiMatrix3x3t<TReal>();
+ out.a3 = v.x;
+ out.b3 = v.y;
+ return out;
+}
+
+// ----------------------------------------------------------------------------------------
+/** A function for creating a rotation matrix that rotates a vector called
+ * "from" into another vector called "to".
+ * Input : from[3], to[3] which both must be *normalized* non-zero vectors
+ * Output: mtx[3][3] -- a 3x3 matrix in colum-major form
+ * Authors: Tomas Möller, John Hughes
+ * "Efficiently Building a Matrix to Rotate One Vector to Another"
+ * Journal of Graphics Tools, 4(4):1-4, 1999
+ */
+// ----------------------------------------------------------------------------------------
+template <typename TReal>
+inline aiMatrix3x3t<TReal>& aiMatrix3x3t<TReal>::FromToMatrix(const aiVector3t<TReal>& from,
+ const aiVector3t<TReal>& to, aiMatrix3x3t<TReal>& mtx)
+{
+ const TReal e = from * to;
+ const TReal f = (e < 0)? -e:e;
+
+ if (f > static_cast<TReal>(1.0) - static_cast<TReal>(0.00001)) /* "from" and "to"-vector almost parallel */
+ {
+ aiVector3D u,v; /* temporary storage vectors */
+ aiVector3D x; /* vector most nearly orthogonal to "from" */
+
+ x.x = (from.x > 0.0)? from.x : -from.x;
+ x.y = (from.y > 0.0)? from.y : -from.y;
+ x.z = (from.z > 0.0)? from.z : -from.z;
+
+ if (x.x < x.y)
+ {
+ if (x.x < x.z)
+ {
+ x.x = static_cast<TReal>(1.0);
+ x.y = x.z = static_cast<TReal>(0.0);
+ }
+ else
+ {
+ x.z = static_cast<TReal>(1.0);
+ x.x = x.y = static_cast<TReal>(0.0);
+ }
+ }
+ else
+ {
+ if (x.y < x.z)
+ {
+ x.y = static_cast<TReal>(1.0);
+ x.x = x.z = static_cast<TReal>(0.0);
+ }
+ else
+ {
+ x.z = static_cast<TReal>(1.0);
+ x.x = x.y = static_cast<TReal>(0.0);
+ }
+ }
+
+ u.x = x.x - from.x; u.y = x.y - from.y; u.z = x.z - from.z;
+ v.x = x.x - to.x; v.y = x.y - to.y; v.z = x.z - to.z;
+
+ const TReal c1_ = static_cast<TReal>(2.0) / (u * u);
+ const TReal c2_ = static_cast<TReal>(2.0) / (v * v);
+ const TReal c3_ = c1_ * c2_ * (u * v);
+
+ for (unsigned int i = 0; i < 3; i++)
+ {
+ for (unsigned int j = 0; j < 3; j++)
+ {
+ mtx[i][j] = - c1_ * u[i] * u[j] - c2_ * v[i] * v[j]
+ + c3_ * v[i] * u[j];
+ }
+ mtx[i][i] += static_cast<TReal>(1.0);
+ }
+ }
+ else /* the most common case, unless "from"="to", or "from"=-"to" */
+ {
+ const aiVector3D v = from ^ to;
+ /* ... use this hand optimized version (9 mults less) */
+ const TReal h = static_cast<TReal>(1.0)/(static_cast<TReal>(1.0) + e); /* optimization by Gottfried Chen */
+ const TReal hvx = h * v.x;
+ const TReal hvz = h * v.z;
+ const TReal hvxy = hvx * v.y;
+ const TReal hvxz = hvx * v.z;
+ const TReal hvyz = hvz * v.y;
+ mtx[0][0] = e + hvx * v.x;
+ mtx[0][1] = hvxy - v.z;
+ mtx[0][2] = hvxz + v.y;
+
+ mtx[1][0] = hvxy + v.z;
+ mtx[1][1] = e + h * v.y * v.y;
+ mtx[1][2] = hvyz - v.x;
+
+ mtx[2][0] = hvxz - v.y;
+ mtx[2][1] = hvyz + v.x;
+ mtx[2][2] = e + hvz * v.z;
+ }
+ return mtx;
+}
+
+
+#endif // __cplusplus
+#endif // AI_MATRIX3X3_INL_INC
diff --git a/thirdparty/assimp/include/assimp/matrix4x4.h b/thirdparty/assimp/include/assimp/matrix4x4.h
new file mode 100644
index 0000000000..046bb535f2
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/matrix4x4.h
@@ -0,0 +1,280 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+/** @file matrix4x4.h
+ * @brief 4x4 matrix structure, including operators when compiling in C++
+ */
+#pragma once
+#ifndef AI_MATRIX4X4_H_INC
+#define AI_MATRIX4X4_H_INC
+
+#include "vector3.h"
+#include "defs.h"
+
+#ifdef __cplusplus
+
+template<typename TReal> class aiMatrix3x3t;
+template<typename TReal> class aiQuaterniont;
+
+// ---------------------------------------------------------------------------
+/** @brief Represents a row-major 4x4 matrix, use this for homogeneous
+ * coordinates.
+ *
+ * There's much confusion about matrix layouts (column vs. row order).
+ * This is *always* a row-major matrix. Not even with the
+ * #aiProcess_ConvertToLeftHanded flag, which absolutely does not affect
+ * matrix order - it just affects the handedness of the coordinate system
+ * defined thereby.
+ */
+template<typename TReal>
+class aiMatrix4x4t
+{
+public:
+
+ /** set to identity */
+ aiMatrix4x4t() AI_NO_EXCEPT;
+
+ /** construction from single values */
+ aiMatrix4x4t ( TReal _a1, TReal _a2, TReal _a3, TReal _a4,
+ TReal _b1, TReal _b2, TReal _b3, TReal _b4,
+ TReal _c1, TReal _c2, TReal _c3, TReal _c4,
+ TReal _d1, TReal _d2, TReal _d3, TReal _d4);
+
+
+ /** construction from 3x3 matrix, remaining elements are set to identity */
+ explicit aiMatrix4x4t( const aiMatrix3x3t<TReal>& m);
+
+ /** construction from position, rotation and scaling components
+ * @param scaling The scaling for the x,y,z axes
+ * @param rotation The rotation as a hamilton quaternion
+ * @param position The position for the x,y,z axes
+ */
+ aiMatrix4x4t(const aiVector3t<TReal>& scaling, const aiQuaterniont<TReal>& rotation,
+ const aiVector3t<TReal>& position);
+
+public:
+
+ // array access operators
+ /** @fn TReal* operator[] (unsigned int p_iIndex)
+ * @param [in] p_iIndex - index of the row.
+ * @return pointer to pointed row.
+ */
+ TReal* operator[] (unsigned int p_iIndex);
+
+ /** @fn const TReal* operator[] (unsigned int p_iIndex) const
+ * @overload TReal* operator[] (unsigned int p_iIndex)
+ */
+ const TReal* operator[] (unsigned int p_iIndex) const;
+
+ // comparison operators
+ bool operator== (const aiMatrix4x4t& m) const;
+ bool operator!= (const aiMatrix4x4t& m) const;
+
+ bool Equal(const aiMatrix4x4t& m, TReal epsilon = 1e-6) const;
+
+ // matrix multiplication.
+ aiMatrix4x4t& operator *= (const aiMatrix4x4t& m);
+ aiMatrix4x4t operator * (const aiMatrix4x4t& m) const;
+ aiMatrix4x4t operator * (const TReal& aFloat) const;
+ aiMatrix4x4t operator + (const aiMatrix4x4t& aMatrix) const;
+
+ template <typename TOther>
+ operator aiMatrix4x4t<TOther> () const;
+
+public:
+
+ // -------------------------------------------------------------------
+ /** @brief Transpose the matrix */
+ aiMatrix4x4t& Transpose();
+
+ // -------------------------------------------------------------------
+ /** @brief Invert the matrix.
+ * If the matrix is not invertible all elements are set to qnan.
+ * Beware, use (f != f) to check whether a TReal f is qnan.
+ */
+ aiMatrix4x4t& Inverse();
+ TReal Determinant() const;
+
+
+ // -------------------------------------------------------------------
+ /** @brief Returns true of the matrix is the identity matrix.
+ * The check is performed against a not so small epsilon.
+ */
+ inline bool IsIdentity() const;
+
+ // -------------------------------------------------------------------
+ /** @brief Decompose a trafo matrix into its original components
+ * @param scaling Receives the output scaling for the x,y,z axes
+ * @param rotation Receives the output rotation as a hamilton
+ * quaternion
+ * @param position Receives the output position for the x,y,z axes
+ */
+ void Decompose (aiVector3t<TReal>& scaling, aiQuaterniont<TReal>& rotation,
+ aiVector3t<TReal>& position) const;
+
+ // -------------------------------------------------------------------
+ /** @fn void Decompose(aiVector3t<TReal>& pScaling, aiVector3t<TReal>& pRotation, aiVector3t<TReal>& pPosition) const
+ * @brief Decompose a trafo matrix into its original components.
+ * Thx to good FAQ at http://www.gamedev.ru/code/articles/faq_matrix_quat
+ * @param [out] pScaling - Receives the output scaling for the x,y,z axes.
+ * @param [out] pRotation - Receives the output rotation as a Euler angles.
+ * @param [out] pPosition - Receives the output position for the x,y,z axes.
+ */
+ void Decompose(aiVector3t<TReal>& pScaling, aiVector3t<TReal>& pRotation, aiVector3t<TReal>& pPosition) const;
+
+ // -------------------------------------------------------------------
+ /** @fn void Decompose(aiVector3t<TReal>& pScaling, aiVector3t<TReal>& pRotationAxis, TReal& pRotationAngle, aiVector3t<TReal>& pPosition) const
+ * @brief Decompose a trafo matrix into its original components
+ * Thx to good FAQ at http://www.gamedev.ru/code/articles/faq_matrix_quat
+ * @param [out] pScaling - Receives the output scaling for the x,y,z axes.
+ * @param [out] pRotationAxis - Receives the output rotation axis.
+ * @param [out] pRotationAngle - Receives the output rotation angle for @ref pRotationAxis.
+ * @param [out] pPosition - Receives the output position for the x,y,z axes.
+ */
+ void Decompose(aiVector3t<TReal>& pScaling, aiVector3t<TReal>& pRotationAxis, TReal& pRotationAngle, aiVector3t<TReal>& pPosition) const;
+
+ // -------------------------------------------------------------------
+ /** @brief Decompose a trafo matrix with no scaling into its
+ * original components
+ * @param rotation Receives the output rotation as a hamilton
+ * quaternion
+ * @param position Receives the output position for the x,y,z axes
+ */
+ void DecomposeNoScaling (aiQuaterniont<TReal>& rotation,
+ aiVector3t<TReal>& position) const;
+
+
+ // -------------------------------------------------------------------
+ /** @brief Creates a trafo matrix from a set of euler angles
+ * @param x Rotation angle for the x-axis, in radians
+ * @param y Rotation angle for the y-axis, in radians
+ * @param z Rotation angle for the z-axis, in radians
+ */
+ aiMatrix4x4t& FromEulerAnglesXYZ(TReal x, TReal y, TReal z);
+ aiMatrix4x4t& FromEulerAnglesXYZ(const aiVector3t<TReal>& blubb);
+
+public:
+ // -------------------------------------------------------------------
+ /** @brief Returns a rotation matrix for a rotation around the x axis
+ * @param a Rotation angle, in radians
+ * @param out Receives the output matrix
+ * @return Reference to the output matrix
+ */
+ static aiMatrix4x4t& RotationX(TReal a, aiMatrix4x4t& out);
+
+ // -------------------------------------------------------------------
+ /** @brief Returns a rotation matrix for a rotation around the y axis
+ * @param a Rotation angle, in radians
+ * @param out Receives the output matrix
+ * @return Reference to the output matrix
+ */
+ static aiMatrix4x4t& RotationY(TReal a, aiMatrix4x4t& out);
+
+ // -------------------------------------------------------------------
+ /** @brief Returns a rotation matrix for a rotation around the z axis
+ * @param a Rotation angle, in radians
+ * @param out Receives the output matrix
+ * @return Reference to the output matrix
+ */
+ static aiMatrix4x4t& RotationZ(TReal a, aiMatrix4x4t& out);
+
+ // -------------------------------------------------------------------
+ /** Returns a rotation matrix for a rotation around an arbitrary axis.
+ * @param a Rotation angle, in radians
+ * @param axis Rotation axis, should be a normalized vector.
+ * @param out Receives the output matrix
+ * @return Reference to the output matrix
+ */
+ static aiMatrix4x4t& Rotation(TReal a, const aiVector3t<TReal>& axis,
+ aiMatrix4x4t& out);
+
+ // -------------------------------------------------------------------
+ /** @brief Returns a translation matrix
+ * @param v Translation vector
+ * @param out Receives the output matrix
+ * @return Reference to the output matrix
+ */
+ static aiMatrix4x4t& Translation( const aiVector3t<TReal>& v,
+ aiMatrix4x4t& out);
+
+ // -------------------------------------------------------------------
+ /** @brief Returns a scaling matrix
+ * @param v Scaling vector
+ * @param out Receives the output matrix
+ * @return Reference to the output matrix
+ */
+ static aiMatrix4x4t& Scaling( const aiVector3t<TReal>& v, aiMatrix4x4t& out);
+
+ // -------------------------------------------------------------------
+ /** @brief A function for creating a rotation matrix that rotates a
+ * vector called "from" into another vector called "to".
+ * Input : from[3], to[3] which both must be *normalized* non-zero vectors
+ * Output: mtx[3][3] -- a 3x3 matrix in column-major form
+ * Authors: Tomas Mueller, John Hughes
+ * "Efficiently Building a Matrix to Rotate One Vector to Another"
+ * Journal of Graphics Tools, 4(4):1-4, 1999
+ */
+ static aiMatrix4x4t& FromToMatrix(const aiVector3t<TReal>& from,
+ const aiVector3t<TReal>& to, aiMatrix4x4t& out);
+
+public:
+ TReal a1, a2, a3, a4;
+ TReal b1, b2, b3, b4;
+ TReal c1, c2, c3, c4;
+ TReal d1, d2, d3, d4;
+};
+
+typedef aiMatrix4x4t<ai_real> aiMatrix4x4;
+
+#else
+
+struct aiMatrix4x4 {
+ ai_real a1, a2, a3, a4;
+ ai_real b1, b2, b3, b4;
+ ai_real c1, c2, c3, c4;
+ ai_real d1, d2, d3, d4;
+};
+
+
+#endif // __cplusplus
+
+#endif // AI_MATRIX4X4_H_INC
diff --git a/thirdparty/assimp/include/assimp/matrix4x4.inl b/thirdparty/assimp/include/assimp/matrix4x4.inl
new file mode 100644
index 0000000000..ebc67a06ec
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/matrix4x4.inl
@@ -0,0 +1,686 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file matrix4x4.inl
+ * @brief Inline implementation of the 4x4 matrix operators
+ */
+#pragma once
+#ifndef AI_MATRIX4X4_INL_INC
+#define AI_MATRIX4X4_INL_INC
+
+#ifdef __cplusplus
+
+#include "matrix4x4.h"
+#include "matrix3x3.h"
+#include "quaternion.h"
+
+#include <algorithm>
+#include <limits>
+#include <cmath>
+
+// ----------------------------------------------------------------------------------------
+template <typename TReal>
+aiMatrix4x4t<TReal>::aiMatrix4x4t() AI_NO_EXCEPT :
+ a1(1.0f), a2(), a3(), a4(),
+ b1(), b2(1.0f), b3(), b4(),
+ c1(), c2(), c3(1.0f), c4(),
+ d1(), d2(), d3(), d4(1.0f)
+{
+
+}
+
+// ----------------------------------------------------------------------------------------
+template <typename TReal>
+aiMatrix4x4t<TReal>::aiMatrix4x4t (TReal _a1, TReal _a2, TReal _a3, TReal _a4,
+ TReal _b1, TReal _b2, TReal _b3, TReal _b4,
+ TReal _c1, TReal _c2, TReal _c3, TReal _c4,
+ TReal _d1, TReal _d2, TReal _d3, TReal _d4) :
+ a1(_a1), a2(_a2), a3(_a3), a4(_a4),
+ b1(_b1), b2(_b2), b3(_b3), b4(_b4),
+ c1(_c1), c2(_c2), c3(_c3), c4(_c4),
+ d1(_d1), d2(_d2), d3(_d3), d4(_d4)
+{
+
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+template <typename TOther>
+aiMatrix4x4t<TReal>::operator aiMatrix4x4t<TOther> () const
+{
+ return aiMatrix4x4t<TOther>(static_cast<TOther>(a1),static_cast<TOther>(a2),static_cast<TOther>(a3),static_cast<TOther>(a4),
+ static_cast<TOther>(b1),static_cast<TOther>(b2),static_cast<TOther>(b3),static_cast<TOther>(b4),
+ static_cast<TOther>(c1),static_cast<TOther>(c2),static_cast<TOther>(c3),static_cast<TOther>(c4),
+ static_cast<TOther>(d1),static_cast<TOther>(d2),static_cast<TOther>(d3),static_cast<TOther>(d4));
+}
+
+
+// ----------------------------------------------------------------------------------------
+template <typename TReal>
+inline aiMatrix4x4t<TReal>::aiMatrix4x4t (const aiMatrix3x3t<TReal>& m)
+{
+ a1 = m.a1; a2 = m.a2; a3 = m.a3; a4 = static_cast<TReal>(0.0);
+ b1 = m.b1; b2 = m.b2; b3 = m.b3; b4 = static_cast<TReal>(0.0);
+ c1 = m.c1; c2 = m.c2; c3 = m.c3; c4 = static_cast<TReal>(0.0);
+ d1 = static_cast<TReal>(0.0); d2 = static_cast<TReal>(0.0); d3 = static_cast<TReal>(0.0); d4 = static_cast<TReal>(1.0);
+}
+
+// ----------------------------------------------------------------------------------------
+template <typename TReal>
+inline aiMatrix4x4t<TReal>::aiMatrix4x4t (const aiVector3t<TReal>& scaling, const aiQuaterniont<TReal>& rotation, const aiVector3t<TReal>& position)
+{
+ // build a 3x3 rotation matrix
+ aiMatrix3x3t<TReal> m = rotation.GetMatrix();
+
+ a1 = m.a1 * scaling.x;
+ a2 = m.a2 * scaling.x;
+ a3 = m.a3 * scaling.x;
+ a4 = position.x;
+
+ b1 = m.b1 * scaling.y;
+ b2 = m.b2 * scaling.y;
+ b3 = m.b3 * scaling.y;
+ b4 = position.y;
+
+ c1 = m.c1 * scaling.z;
+ c2 = m.c2 * scaling.z;
+ c3 = m.c3 * scaling.z;
+ c4= position.z;
+
+ d1 = static_cast<TReal>(0.0);
+ d2 = static_cast<TReal>(0.0);
+ d3 = static_cast<TReal>(0.0);
+ d4 = static_cast<TReal>(1.0);
+}
+
+// ----------------------------------------------------------------------------------------
+template <typename TReal>
+inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::operator *= (const aiMatrix4x4t<TReal>& m)
+{
+ *this = aiMatrix4x4t<TReal>(
+ m.a1 * a1 + m.b1 * a2 + m.c1 * a3 + m.d1 * a4,
+ m.a2 * a1 + m.b2 * a2 + m.c2 * a3 + m.d2 * a4,
+ m.a3 * a1 + m.b3 * a2 + m.c3 * a3 + m.d3 * a4,
+ m.a4 * a1 + m.b4 * a2 + m.c4 * a3 + m.d4 * a4,
+ m.a1 * b1 + m.b1 * b2 + m.c1 * b3 + m.d1 * b4,
+ m.a2 * b1 + m.b2 * b2 + m.c2 * b3 + m.d2 * b4,
+ m.a3 * b1 + m.b3 * b2 + m.c3 * b3 + m.d3 * b4,
+ m.a4 * b1 + m.b4 * b2 + m.c4 * b3 + m.d4 * b4,
+ m.a1 * c1 + m.b1 * c2 + m.c1 * c3 + m.d1 * c4,
+ m.a2 * c1 + m.b2 * c2 + m.c2 * c3 + m.d2 * c4,
+ m.a3 * c1 + m.b3 * c2 + m.c3 * c3 + m.d3 * c4,
+ m.a4 * c1 + m.b4 * c2 + m.c4 * c3 + m.d4 * c4,
+ m.a1 * d1 + m.b1 * d2 + m.c1 * d3 + m.d1 * d4,
+ m.a2 * d1 + m.b2 * d2 + m.c2 * d3 + m.d2 * d4,
+ m.a3 * d1 + m.b3 * d2 + m.c3 * d3 + m.d3 * d4,
+ m.a4 * d1 + m.b4 * d2 + m.c4 * d3 + m.d4 * d4);
+ return *this;
+}
+
+// ----------------------------------------------------------------------------------------
+template <typename TReal>
+inline aiMatrix4x4t<TReal> aiMatrix4x4t<TReal>::operator* (const TReal& aFloat) const
+{
+ aiMatrix4x4t<TReal> temp(
+ a1 * aFloat,
+ a2 * aFloat,
+ a3 * aFloat,
+ a4 * aFloat,
+ b1 * aFloat,
+ b2 * aFloat,
+ b3 * aFloat,
+ b4 * aFloat,
+ c1 * aFloat,
+ c2 * aFloat,
+ c3 * aFloat,
+ c4 * aFloat,
+ d1 * aFloat,
+ d2 * aFloat,
+ d3 * aFloat,
+ d4 * aFloat);
+ return temp;
+}
+
+// ----------------------------------------------------------------------------------------
+template <typename TReal>
+inline aiMatrix4x4t<TReal> aiMatrix4x4t<TReal>::operator+ (const aiMatrix4x4t<TReal>& m) const
+{
+ aiMatrix4x4t<TReal> temp(
+ m.a1 + a1,
+ m.a2 + a2,
+ m.a3 + a3,
+ m.a4 + a4,
+ m.b1 + b1,
+ m.b2 + b2,
+ m.b3 + b3,
+ m.b4 + b4,
+ m.c1 + c1,
+ m.c2 + c2,
+ m.c3 + c3,
+ m.c4 + c4,
+ m.d1 + d1,
+ m.d2 + d2,
+ m.d3 + d3,
+ m.d4 + d4);
+ return temp;
+}
+
+// ----------------------------------------------------------------------------------------
+template <typename TReal>
+inline aiMatrix4x4t<TReal> aiMatrix4x4t<TReal>::operator* (const aiMatrix4x4t<TReal>& m) const
+{
+ aiMatrix4x4t<TReal> temp( *this);
+ temp *= m;
+ return temp;
+}
+
+
+// ----------------------------------------------------------------------------------------
+template <typename TReal>
+inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::Transpose()
+{
+ // (TReal&) don't remove, GCC complains cause of packed fields
+ std::swap( (TReal&)b1, (TReal&)a2);
+ std::swap( (TReal&)c1, (TReal&)a3);
+ std::swap( (TReal&)c2, (TReal&)b3);
+ std::swap( (TReal&)d1, (TReal&)a4);
+ std::swap( (TReal&)d2, (TReal&)b4);
+ std::swap( (TReal&)d3, (TReal&)c4);
+ return *this;
+}
+
+
+// ----------------------------------------------------------------------------------------
+template <typename TReal>
+inline TReal aiMatrix4x4t<TReal>::Determinant() const
+{
+ return a1*b2*c3*d4 - a1*b2*c4*d3 + a1*b3*c4*d2 - a1*b3*c2*d4
+ + a1*b4*c2*d3 - a1*b4*c3*d2 - a2*b3*c4*d1 + a2*b3*c1*d4
+ - a2*b4*c1*d3 + a2*b4*c3*d1 - a2*b1*c3*d4 + a2*b1*c4*d3
+ + a3*b4*c1*d2 - a3*b4*c2*d1 + a3*b1*c2*d4 - a3*b1*c4*d2
+ + a3*b2*c4*d1 - a3*b2*c1*d4 - a4*b1*c2*d3 + a4*b1*c3*d2
+ - a4*b2*c3*d1 + a4*b2*c1*d3 - a4*b3*c1*d2 + a4*b3*c2*d1;
+}
+
+// ----------------------------------------------------------------------------------------
+template <typename TReal>
+inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::Inverse()
+{
+ // Compute the reciprocal determinant
+ const TReal det = Determinant();
+ if(det == static_cast<TReal>(0.0))
+ {
+ // Matrix not invertible. Setting all elements to nan is not really
+ // correct in a mathematical sense but it is easy to debug for the
+ // programmer.
+ const TReal nan = std::numeric_limits<TReal>::quiet_NaN();
+ *this = aiMatrix4x4t<TReal>(
+ nan,nan,nan,nan,
+ nan,nan,nan,nan,
+ nan,nan,nan,nan,
+ nan,nan,nan,nan);
+
+ return *this;
+ }
+
+ const TReal invdet = static_cast<TReal>(1.0) / det;
+
+ aiMatrix4x4t<TReal> res;
+ res.a1 = invdet * (b2 * (c3 * d4 - c4 * d3) + b3 * (c4 * d2 - c2 * d4) + b4 * (c2 * d3 - c3 * d2));
+ res.a2 = -invdet * (a2 * (c3 * d4 - c4 * d3) + a3 * (c4 * d2 - c2 * d4) + a4 * (c2 * d3 - c3 * d2));
+ res.a3 = invdet * (a2 * (b3 * d4 - b4 * d3) + a3 * (b4 * d2 - b2 * d4) + a4 * (b2 * d3 - b3 * d2));
+ res.a4 = -invdet * (a2 * (b3 * c4 - b4 * c3) + a3 * (b4 * c2 - b2 * c4) + a4 * (b2 * c3 - b3 * c2));
+ res.b1 = -invdet * (b1 * (c3 * d4 - c4 * d3) + b3 * (c4 * d1 - c1 * d4) + b4 * (c1 * d3 - c3 * d1));
+ res.b2 = invdet * (a1 * (c3 * d4 - c4 * d3) + a3 * (c4 * d1 - c1 * d4) + a4 * (c1 * d3 - c3 * d1));
+ res.b3 = -invdet * (a1 * (b3 * d4 - b4 * d3) + a3 * (b4 * d1 - b1 * d4) + a4 * (b1 * d3 - b3 * d1));
+ res.b4 = invdet * (a1 * (b3 * c4 - b4 * c3) + a3 * (b4 * c1 - b1 * c4) + a4 * (b1 * c3 - b3 * c1));
+ res.c1 = invdet * (b1 * (c2 * d4 - c4 * d2) + b2 * (c4 * d1 - c1 * d4) + b4 * (c1 * d2 - c2 * d1));
+ res.c2 = -invdet * (a1 * (c2 * d4 - c4 * d2) + a2 * (c4 * d1 - c1 * d4) + a4 * (c1 * d2 - c2 * d1));
+ res.c3 = invdet * (a1 * (b2 * d4 - b4 * d2) + a2 * (b4 * d1 - b1 * d4) + a4 * (b1 * d2 - b2 * d1));
+ res.c4 = -invdet * (a1 * (b2 * c4 - b4 * c2) + a2 * (b4 * c1 - b1 * c4) + a4 * (b1 * c2 - b2 * c1));
+ res.d1 = -invdet * (b1 * (c2 * d3 - c3 * d2) + b2 * (c3 * d1 - c1 * d3) + b3 * (c1 * d2 - c2 * d1));
+ res.d2 = invdet * (a1 * (c2 * d3 - c3 * d2) + a2 * (c3 * d1 - c1 * d3) + a3 * (c1 * d2 - c2 * d1));
+ res.d3 = -invdet * (a1 * (b2 * d3 - b3 * d2) + a2 * (b3 * d1 - b1 * d3) + a3 * (b1 * d2 - b2 * d1));
+ res.d4 = invdet * (a1 * (b2 * c3 - b3 * c2) + a2 * (b3 * c1 - b1 * c3) + a3 * (b1 * c2 - b2 * c1));
+ *this = res;
+
+ return *this;
+}
+
+// ----------------------------------------------------------------------------------------
+template <typename TReal>
+inline TReal* aiMatrix4x4t<TReal>::operator[](unsigned int p_iIndex) {
+ if (p_iIndex > 3) {
+ return NULL;
+ }
+ switch ( p_iIndex ) {
+ case 0:
+ return &a1;
+ case 1:
+ return &b1;
+ case 2:
+ return &c1;
+ case 3:
+ return &d1;
+ default:
+ break;
+ }
+ return &a1;
+}
+
+// ----------------------------------------------------------------------------------------
+template <typename TReal>
+inline const TReal* aiMatrix4x4t<TReal>::operator[](unsigned int p_iIndex) const {
+ if (p_iIndex > 3) {
+ return NULL;
+ }
+
+ switch ( p_iIndex ) {
+ case 0:
+ return &a1;
+ case 1:
+ return &b1;
+ case 2:
+ return &c1;
+ case 3:
+ return &d1;
+ default:
+ break;
+ }
+ return &a1;
+}
+
+// ----------------------------------------------------------------------------------------
+template <typename TReal>
+inline bool aiMatrix4x4t<TReal>::operator== (const aiMatrix4x4t<TReal>& m) const
+{
+ return (a1 == m.a1 && a2 == m.a2 && a3 == m.a3 && a4 == m.a4 &&
+ b1 == m.b1 && b2 == m.b2 && b3 == m.b3 && b4 == m.b4 &&
+ c1 == m.c1 && c2 == m.c2 && c3 == m.c3 && c4 == m.c4 &&
+ d1 == m.d1 && d2 == m.d2 && d3 == m.d3 && d4 == m.d4);
+}
+
+// ----------------------------------------------------------------------------------------
+template <typename TReal>
+inline bool aiMatrix4x4t<TReal>::operator!= (const aiMatrix4x4t<TReal>& m) const
+{
+ return !(*this == m);
+}
+
+// ---------------------------------------------------------------------------
+template<typename TReal>
+inline bool aiMatrix4x4t<TReal>::Equal(const aiMatrix4x4t<TReal>& m, TReal epsilon) const {
+ return
+ std::abs(a1 - m.a1) <= epsilon &&
+ std::abs(a2 - m.a2) <= epsilon &&
+ std::abs(a3 - m.a3) <= epsilon &&
+ std::abs(a4 - m.a4) <= epsilon &&
+ std::abs(b1 - m.b1) <= epsilon &&
+ std::abs(b2 - m.b2) <= epsilon &&
+ std::abs(b3 - m.b3) <= epsilon &&
+ std::abs(b4 - m.b4) <= epsilon &&
+ std::abs(c1 - m.c1) <= epsilon &&
+ std::abs(c2 - m.c2) <= epsilon &&
+ std::abs(c3 - m.c3) <= epsilon &&
+ std::abs(c4 - m.c4) <= epsilon &&
+ std::abs(d1 - m.d1) <= epsilon &&
+ std::abs(d2 - m.d2) <= epsilon &&
+ std::abs(d3 - m.d3) <= epsilon &&
+ std::abs(d4 - m.d4) <= epsilon;
+}
+
+// ----------------------------------------------------------------------------------------
+
+#define ASSIMP_MATRIX4_4_DECOMPOSE_PART \
+ const aiMatrix4x4t<TReal>& _this = *this;/* Create alias for conveniance. */ \
+ \
+ /* extract translation */ \
+ pPosition.x = _this[0][3]; \
+ pPosition.y = _this[1][3]; \
+ pPosition.z = _this[2][3]; \
+ \
+ /* extract the columns of the matrix. */ \
+ aiVector3t<TReal> vCols[3] = { \
+ aiVector3t<TReal>(_this[0][0],_this[1][0],_this[2][0]), \
+ aiVector3t<TReal>(_this[0][1],_this[1][1],_this[2][1]), \
+ aiVector3t<TReal>(_this[0][2],_this[1][2],_this[2][2]) \
+ }; \
+ \
+ /* extract the scaling factors */ \
+ pScaling.x = vCols[0].Length(); \
+ pScaling.y = vCols[1].Length(); \
+ pScaling.z = vCols[2].Length(); \
+ \
+ /* and the sign of the scaling */ \
+ if (Determinant() < 0) pScaling = -pScaling; \
+ \
+ /* and remove all scaling from the matrix */ \
+ if(pScaling.x) vCols[0] /= pScaling.x; \
+ if(pScaling.y) vCols[1] /= pScaling.y; \
+ if(pScaling.z) vCols[2] /= pScaling.z; \
+ \
+ do {} while(false)
+
+
+
+
+template <typename TReal>
+inline void aiMatrix4x4t<TReal>::Decompose (aiVector3t<TReal>& pScaling, aiQuaterniont<TReal>& pRotation,
+ aiVector3t<TReal>& pPosition) const
+{
+ ASSIMP_MATRIX4_4_DECOMPOSE_PART;
+
+ // build a 3x3 rotation matrix
+ aiMatrix3x3t<TReal> m(vCols[0].x,vCols[1].x,vCols[2].x,
+ vCols[0].y,vCols[1].y,vCols[2].y,
+ vCols[0].z,vCols[1].z,vCols[2].z);
+
+ // and generate the rotation quaternion from it
+ pRotation = aiQuaterniont<TReal>(m);
+}
+
+template <typename TReal>
+inline void aiMatrix4x4t<TReal>::Decompose(aiVector3t<TReal>& pScaling, aiVector3t<TReal>& pRotation, aiVector3t<TReal>& pPosition) const
+{
+ ASSIMP_MATRIX4_4_DECOMPOSE_PART;
+
+ /*
+ assuming a right-handed coordinate system
+ and post-multiplication of column vectors,
+ the rotation matrix for an euler XYZ rotation is M = Rz * Ry * Rx.
+ combining gives:
+
+ | CE BDE-AF ADE+BF 0 |
+ M = | CF BDF+AE ADF-BE 0 |
+ | -D CB AC 0 |
+ | 0 0 0 1 |
+
+ where
+ A = cos(angle_x), B = sin(angle_x);
+ C = cos(angle_y), D = sin(angle_y);
+ E = cos(angle_z), F = sin(angle_z);
+ */
+
+ // Use a small epsilon to solve floating-point inaccuracies
+ const TReal epsilon = 10e-3f;
+
+ pRotation.y = std::asin(-vCols[0].z);// D. Angle around oY.
+
+ TReal C = std::cos(pRotation.y);
+
+ if(std::fabs(C) > epsilon)
+ {
+ // Finding angle around oX.
+ TReal tan_x = vCols[2].z / C;// A
+ TReal tan_y = vCols[1].z / C;// B
+
+ pRotation.x = std::atan2(tan_y, tan_x);
+ // Finding angle around oZ.
+ tan_x = vCols[0].x / C;// E
+ tan_y = vCols[0].y / C;// F
+ pRotation.z = std::atan2(tan_y, tan_x);
+ }
+ else
+ {// oY is fixed.
+ pRotation.x = 0;// Set angle around oX to 0. => A == 1, B == 0, C == 0, D == 1.
+
+ // And finding angle around oZ.
+ TReal tan_x = vCols[1].y;// BDF+AE => E
+ TReal tan_y = -vCols[1].x;// BDE-AF => F
+
+ pRotation.z = std::atan2(tan_y, tan_x);
+ }
+}
+
+#undef ASSIMP_MATRIX4_4_DECOMPOSE_PART
+
+template <typename TReal>
+inline void aiMatrix4x4t<TReal>::Decompose(aiVector3t<TReal>& pScaling, aiVector3t<TReal>& pRotationAxis, TReal& pRotationAngle,
+ aiVector3t<TReal>& pPosition) const
+{
+aiQuaterniont<TReal> pRotation;
+
+ Decompose(pScaling, pRotation, pPosition);
+ pRotation.Normalize();
+
+ TReal angle_cos = pRotation.w;
+ TReal angle_sin = std::sqrt(1.0f - angle_cos * angle_cos);
+
+ pRotationAngle = std::acos(angle_cos) * 2;
+
+ // Use a small epsilon to solve floating-point inaccuracies
+ const TReal epsilon = 10e-3f;
+
+ if(std::fabs(angle_sin) < epsilon) angle_sin = 1;
+
+ pRotationAxis.x = pRotation.x / angle_sin;
+ pRotationAxis.y = pRotation.y / angle_sin;
+ pRotationAxis.z = pRotation.z / angle_sin;
+}
+
+// ----------------------------------------------------------------------------------------
+template <typename TReal>
+inline void aiMatrix4x4t<TReal>::DecomposeNoScaling (aiQuaterniont<TReal>& rotation,
+ aiVector3t<TReal>& position) const
+{
+ const aiMatrix4x4t<TReal>& _this = *this;
+
+ // extract translation
+ position.x = _this[0][3];
+ position.y = _this[1][3];
+ position.z = _this[2][3];
+
+ // extract rotation
+ rotation = aiQuaterniont<TReal>((aiMatrix3x3t<TReal>)_this);
+}
+
+// ----------------------------------------------------------------------------------------
+template <typename TReal>
+inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::FromEulerAnglesXYZ(const aiVector3t<TReal>& blubb)
+{
+ return FromEulerAnglesXYZ(blubb.x,blubb.y,blubb.z);
+}
+
+// ----------------------------------------------------------------------------------------
+template <typename TReal>
+inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::FromEulerAnglesXYZ(TReal x, TReal y, TReal z)
+{
+ aiMatrix4x4t<TReal>& _this = *this;
+
+ TReal cx = std::cos(x);
+ TReal sx = std::sin(x);
+ TReal cy = std::cos(y);
+ TReal sy = std::sin(y);
+ TReal cz = std::cos(z);
+ TReal sz = std::sin(z);
+
+ // mz*my*mx
+ _this.a1 = cz * cy;
+ _this.a2 = cz * sy * sx - sz * cx;
+ _this.a3 = sz * sx + cz * sy * cx;
+
+ _this.b1 = sz * cy;
+ _this.b2 = cz * cx + sz * sy * sx;
+ _this.b3 = sz * sy * cx - cz * sx;
+
+ _this.c1 = -sy;
+ _this.c2 = cy * sx;
+ _this.c3 = cy * cx;
+
+ return *this;
+}
+
+// ----------------------------------------------------------------------------------------
+template <typename TReal>
+inline bool aiMatrix4x4t<TReal>::IsIdentity() const
+{
+ // Use a small epsilon to solve floating-point inaccuracies
+ const static TReal epsilon = 10e-3f;
+
+ return (a2 <= epsilon && a2 >= -epsilon &&
+ a3 <= epsilon && a3 >= -epsilon &&
+ a4 <= epsilon && a4 >= -epsilon &&
+ b1 <= epsilon && b1 >= -epsilon &&
+ b3 <= epsilon && b3 >= -epsilon &&
+ b4 <= epsilon && b4 >= -epsilon &&
+ c1 <= epsilon && c1 >= -epsilon &&
+ c2 <= epsilon && c2 >= -epsilon &&
+ c4 <= epsilon && c4 >= -epsilon &&
+ d1 <= epsilon && d1 >= -epsilon &&
+ d2 <= epsilon && d2 >= -epsilon &&
+ d3 <= epsilon && d3 >= -epsilon &&
+ a1 <= 1.f+epsilon && a1 >= 1.f-epsilon &&
+ b2 <= 1.f+epsilon && b2 >= 1.f-epsilon &&
+ c3 <= 1.f+epsilon && c3 >= 1.f-epsilon &&
+ d4 <= 1.f+epsilon && d4 >= 1.f-epsilon);
+}
+
+// ----------------------------------------------------------------------------------------
+template <typename TReal>
+inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::RotationX(TReal a, aiMatrix4x4t<TReal>& out)
+{
+ /*
+ | 1 0 0 0 |
+ M = | 0 cos(A) -sin(A) 0 |
+ | 0 sin(A) cos(A) 0 |
+ | 0 0 0 1 | */
+ out = aiMatrix4x4t<TReal>();
+ out.b2 = out.c3 = std::cos(a);
+ out.b3 = -(out.c2 = std::sin(a));
+ return out;
+}
+
+// ----------------------------------------------------------------------------------------
+template <typename TReal>
+inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::RotationY(TReal a, aiMatrix4x4t<TReal>& out)
+{
+ /*
+ | cos(A) 0 sin(A) 0 |
+ M = | 0 1 0 0 |
+ | -sin(A) 0 cos(A) 0 |
+ | 0 0 0 1 |
+ */
+ out = aiMatrix4x4t<TReal>();
+ out.a1 = out.c3 = std::cos(a);
+ out.c1 = -(out.a3 = std::sin(a));
+ return out;
+}
+
+// ----------------------------------------------------------------------------------------
+template <typename TReal>
+inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::RotationZ(TReal a, aiMatrix4x4t<TReal>& out)
+{
+ /*
+ | cos(A) -sin(A) 0 0 |
+ M = | sin(A) cos(A) 0 0 |
+ | 0 0 1 0 |
+ | 0 0 0 1 | */
+ out = aiMatrix4x4t<TReal>();
+ out.a1 = out.b2 = std::cos(a);
+ out.a2 = -(out.b1 = std::sin(a));
+ return out;
+}
+
+// ----------------------------------------------------------------------------------------
+// Returns a rotation matrix for a rotation around an arbitrary axis.
+template <typename TReal>
+inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::Rotation( TReal a, const aiVector3t<TReal>& axis, aiMatrix4x4t<TReal>& out)
+{
+ TReal c = std::cos( a), s = std::sin( a), t = 1 - c;
+ TReal x = axis.x, y = axis.y, z = axis.z;
+
+ // Many thanks to MathWorld and Wikipedia
+ out.a1 = t*x*x + c; out.a2 = t*x*y - s*z; out.a3 = t*x*z + s*y;
+ out.b1 = t*x*y + s*z; out.b2 = t*y*y + c; out.b3 = t*y*z - s*x;
+ out.c1 = t*x*z - s*y; out.c2 = t*y*z + s*x; out.c3 = t*z*z + c;
+ out.a4 = out.b4 = out.c4 = static_cast<TReal>(0.0);
+ out.d1 = out.d2 = out.d3 = static_cast<TReal>(0.0);
+ out.d4 = static_cast<TReal>(1.0);
+
+ return out;
+}
+
+// ----------------------------------------------------------------------------------------
+template <typename TReal>
+inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::Translation( const aiVector3t<TReal>& v, aiMatrix4x4t<TReal>& out)
+{
+ out = aiMatrix4x4t<TReal>();
+ out.a4 = v.x;
+ out.b4 = v.y;
+ out.c4 = v.z;
+ return out;
+}
+
+// ----------------------------------------------------------------------------------------
+template <typename TReal>
+inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::Scaling( const aiVector3t<TReal>& v, aiMatrix4x4t<TReal>& out)
+{
+ out = aiMatrix4x4t<TReal>();
+ out.a1 = v.x;
+ out.b2 = v.y;
+ out.c3 = v.z;
+ return out;
+}
+
+// ----------------------------------------------------------------------------------------
+/** A function for creating a rotation matrix that rotates a vector called
+ * "from" into another vector called "to".
+ * Input : from[3], to[3] which both must be *normalized* non-zero vectors
+ * Output: mtx[3][3] -- a 3x3 matrix in colum-major form
+ * Authors: Tomas Möller, John Hughes
+ * "Efficiently Building a Matrix to Rotate One Vector to Another"
+ * Journal of Graphics Tools, 4(4):1-4, 1999
+ */
+// ----------------------------------------------------------------------------------------
+template <typename TReal>
+inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::FromToMatrix(const aiVector3t<TReal>& from,
+ const aiVector3t<TReal>& to, aiMatrix4x4t<TReal>& mtx)
+{
+ aiMatrix3x3t<TReal> m3;
+ aiMatrix3x3t<TReal>::FromToMatrix(from,to,m3);
+ mtx = aiMatrix4x4t<TReal>(m3);
+ return mtx;
+}
+
+#endif // __cplusplus
+#endif // AI_MATRIX4X4_INL_INC
diff --git a/thirdparty/assimp/include/assimp/mesh.h b/thirdparty/assimp/include/assimp/mesh.h
new file mode 100644
index 0000000000..36f3ed2afd
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/mesh.h
@@ -0,0 +1,852 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file mesh.h
+ * @brief Declares the data structures in which the imported geometry is
+ returned by ASSIMP: aiMesh, aiFace and aiBone data structures.
+ */
+#pragma once
+#ifndef AI_MESH_H_INC
+#define AI_MESH_H_INC
+
+#include "types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// ---------------------------------------------------------------------------
+// Limits. These values are required to match the settings Assimp was
+// compiled against. Therefore, do not redefine them unless you build the
+// library from source using the same definitions.
+// ---------------------------------------------------------------------------
+
+/** @def AI_MAX_FACE_INDICES
+ * Maximum number of indices per face (polygon). */
+
+#ifndef AI_MAX_FACE_INDICES
+# define AI_MAX_FACE_INDICES 0x7fff
+#endif
+
+/** @def AI_MAX_BONE_WEIGHTS
+ * Maximum number of indices per face (polygon). */
+
+#ifndef AI_MAX_BONE_WEIGHTS
+# define AI_MAX_BONE_WEIGHTS 0x7fffffff
+#endif
+
+/** @def AI_MAX_VERTICES
+ * Maximum number of vertices per mesh. */
+
+#ifndef AI_MAX_VERTICES
+# define AI_MAX_VERTICES 0x7fffffff
+#endif
+
+/** @def AI_MAX_FACES
+ * Maximum number of faces per mesh. */
+
+#ifndef AI_MAX_FACES
+# define AI_MAX_FACES 0x7fffffff
+#endif
+
+/** @def AI_MAX_NUMBER_OF_COLOR_SETS
+ * Supported number of vertex color sets per mesh. */
+
+#ifndef AI_MAX_NUMBER_OF_COLOR_SETS
+# define AI_MAX_NUMBER_OF_COLOR_SETS 0x8
+#endif // !! AI_MAX_NUMBER_OF_COLOR_SETS
+
+/** @def AI_MAX_NUMBER_OF_TEXTURECOORDS
+ * Supported number of texture coord sets (UV(W) channels) per mesh */
+
+#ifndef AI_MAX_NUMBER_OF_TEXTURECOORDS
+# define AI_MAX_NUMBER_OF_TEXTURECOORDS 0x8
+#endif // !! AI_MAX_NUMBER_OF_TEXTURECOORDS
+
+// ---------------------------------------------------------------------------
+/** @brief A single face in a mesh, referring to multiple vertices.
+ *
+ * If mNumIndices is 3, we call the face 'triangle', for mNumIndices > 3
+ * it's called 'polygon' (hey, that's just a definition!).
+ * <br>
+ * aiMesh::mPrimitiveTypes can be queried to quickly examine which types of
+ * primitive are actually present in a mesh. The #aiProcess_SortByPType flag
+ * executes a special post-processing algorithm which splits meshes with
+ * *different* primitive types mixed up (e.g. lines and triangles) in several
+ * 'clean' submeshes. Furthermore there is a configuration option (
+ * #AI_CONFIG_PP_SBP_REMOVE) to force #aiProcess_SortByPType to remove
+ * specific kinds of primitives from the imported scene, completely and forever.
+ * In many cases you'll probably want to set this setting to
+ * @code
+ * aiPrimitiveType_LINE|aiPrimitiveType_POINT
+ * @endcode
+ * Together with the #aiProcess_Triangulate flag you can then be sure that
+ * #aiFace::mNumIndices is always 3.
+ * @note Take a look at the @link data Data Structures page @endlink for
+ * more information on the layout and winding order of a face.
+ */
+struct aiFace
+{
+ //! Number of indices defining this face.
+ //! The maximum value for this member is #AI_MAX_FACE_INDICES.
+ unsigned int mNumIndices;
+
+ //! Pointer to the indices array. Size of the array is given in numIndices.
+ unsigned int* mIndices;
+
+#ifdef __cplusplus
+
+ //! Default constructor
+ aiFace() AI_NO_EXCEPT
+ : mNumIndices( 0 )
+ , mIndices( nullptr ) {
+ // empty
+ }
+
+ //! Default destructor. Delete the index array
+ ~aiFace()
+ {
+ delete [] mIndices;
+ }
+
+ //! Copy constructor. Copy the index array
+ aiFace( const aiFace& o)
+ : mNumIndices(0)
+ , mIndices( nullptr ) {
+ *this = o;
+ }
+
+ //! Assignment operator. Copy the index array
+ aiFace& operator = ( const aiFace& o) {
+ if (&o == this) {
+ return *this;
+ }
+
+ delete[] mIndices;
+ mNumIndices = o.mNumIndices;
+ if (mNumIndices) {
+ mIndices = new unsigned int[mNumIndices];
+ ::memcpy( mIndices, o.mIndices, mNumIndices * sizeof( unsigned int));
+ } else {
+ mIndices = nullptr;
+ }
+
+ return *this;
+ }
+
+ //! Comparison operator. Checks whether the index array
+ //! of two faces is identical
+ bool operator== (const aiFace& o) const {
+ if (mIndices == o.mIndices) {
+ return true;
+ }
+
+ if (nullptr != mIndices && mNumIndices != o.mNumIndices) {
+ return false;
+ }
+
+ if (nullptr == mIndices) {
+ return false;
+ }
+
+ for (unsigned int i = 0; i < this->mNumIndices; ++i) {
+ if (mIndices[i] != o.mIndices[i]) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ //! Inverse comparison operator. Checks whether the index
+ //! array of two faces is NOT identical
+ bool operator != (const aiFace& o) const {
+ return !(*this == o);
+ }
+#endif // __cplusplus
+}; // struct aiFace
+
+
+// ---------------------------------------------------------------------------
+/** @brief A single influence of a bone on a vertex.
+ */
+struct aiVertexWeight {
+ //! Index of the vertex which is influenced by the bone.
+ unsigned int mVertexId;
+
+ //! The strength of the influence in the range (0...1).
+ //! The influence from all bones at one vertex amounts to 1.
+ float mWeight;
+
+#ifdef __cplusplus
+
+ //! Default constructor
+ aiVertexWeight() AI_NO_EXCEPT
+ : mVertexId(0)
+ , mWeight(0.0f) {
+ // empty
+ }
+
+ //! Initialization from a given index and vertex weight factor
+ //! \param pID ID
+ //! \param pWeight Vertex weight factor
+ aiVertexWeight( unsigned int pID, float pWeight )
+ : mVertexId( pID )
+ , mWeight( pWeight ) {
+ // empty
+ }
+
+ bool operator == ( const aiVertexWeight &rhs ) const {
+ return ( mVertexId == rhs.mVertexId && mWeight == rhs.mWeight );
+ }
+
+ bool operator != ( const aiVertexWeight &rhs ) const {
+ return ( *this == rhs );
+ }
+
+#endif // __cplusplus
+};
+
+
+// ---------------------------------------------------------------------------
+/** @brief A single bone of a mesh.
+ *
+ * A bone has a name by which it can be found in the frame hierarchy and by
+ * which it can be addressed by animations. In addition it has a number of
+ * influences on vertices, and a matrix relating the mesh position to the
+ * position of the bone at the time of binding.
+ */
+struct aiBone {
+ //! The name of the bone.
+ C_STRUCT aiString mName;
+
+ //! The number of vertices affected by this bone.
+ //! The maximum value for this member is #AI_MAX_BONE_WEIGHTS.
+ unsigned int mNumWeights;
+
+ //! The influence weights of this bone, by vertex index.
+ C_STRUCT aiVertexWeight* mWeights;
+
+ /** Matrix that transforms from bone space to mesh space in bind pose.
+ *
+ * This matrix describes the position of the mesh
+ * in the local space of this bone when the skeleton was bound.
+ * Thus it can be used directly to determine a desired vertex position,
+ * given the world-space transform of the bone when animated,
+ * and the position of the vertex in mesh space.
+ *
+ * It is sometimes called an inverse-bind matrix,
+ * or inverse bind pose matrix.
+ */
+ C_STRUCT aiMatrix4x4 mOffsetMatrix;
+
+#ifdef __cplusplus
+
+ //! Default constructor
+ aiBone() AI_NO_EXCEPT
+ : mName()
+ , mNumWeights( 0 )
+ , mWeights( nullptr )
+ , mOffsetMatrix() {
+ // empty
+ }
+
+ //! Copy constructor
+ aiBone(const aiBone& other)
+ : mName( other.mName )
+ , mNumWeights( other.mNumWeights )
+ , mWeights(nullptr)
+ , mOffsetMatrix( other.mOffsetMatrix ) {
+ if (other.mWeights && other.mNumWeights) {
+ mWeights = new aiVertexWeight[mNumWeights];
+ ::memcpy(mWeights,other.mWeights,mNumWeights * sizeof(aiVertexWeight));
+ }
+ }
+
+
+ //! Assignment operator
+ aiBone &operator=(const aiBone& other) {
+ if (this == &other) {
+ return *this;
+ }
+
+ mName = other.mName;
+ mNumWeights = other.mNumWeights;
+ mOffsetMatrix = other.mOffsetMatrix;
+
+ if (other.mWeights && other.mNumWeights)
+ {
+ if (mWeights) {
+ delete[] mWeights;
+ }
+
+ mWeights = new aiVertexWeight[mNumWeights];
+ ::memcpy(mWeights,other.mWeights,mNumWeights * sizeof(aiVertexWeight));
+ }
+
+ return *this;
+ }
+
+ bool operator == ( const aiBone &rhs ) const {
+ if ( mName != rhs.mName || mNumWeights != rhs.mNumWeights ) {
+ return false;
+ }
+
+ for ( size_t i = 0; i < mNumWeights; ++i ) {
+ if ( mWeights[ i ] != rhs.mWeights[ i ] ) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ //! Destructor - deletes the array of vertex weights
+ ~aiBone() {
+ delete [] mWeights;
+ }
+#endif // __cplusplus
+};
+
+
+// ---------------------------------------------------------------------------
+/** @brief Enumerates the types of geometric primitives supported by Assimp.
+ *
+ * @see aiFace Face data structure
+ * @see aiProcess_SortByPType Per-primitive sorting of meshes
+ * @see aiProcess_Triangulate Automatic triangulation
+ * @see AI_CONFIG_PP_SBP_REMOVE Removal of specific primitive types.
+ */
+enum aiPrimitiveType
+{
+ /** A point primitive.
+ *
+ * This is just a single vertex in the virtual world,
+ * #aiFace contains just one index for such a primitive.
+ */
+ aiPrimitiveType_POINT = 0x1,
+
+ /** A line primitive.
+ *
+ * This is a line defined through a start and an end position.
+ * #aiFace contains exactly two indices for such a primitive.
+ */
+ aiPrimitiveType_LINE = 0x2,
+
+ /** A triangular primitive.
+ *
+ * A triangle consists of three indices.
+ */
+ aiPrimitiveType_TRIANGLE = 0x4,
+
+ /** A higher-level polygon with more than 3 edges.
+ *
+ * A triangle is a polygon, but polygon in this context means
+ * "all polygons that are not triangles". The "Triangulate"-Step
+ * is provided for your convenience, it splits all polygons in
+ * triangles (which are much easier to handle).
+ */
+ aiPrimitiveType_POLYGON = 0x8,
+
+
+ /** This value is not used. It is just here to force the
+ * compiler to map this enum to a 32 Bit integer.
+ */
+#ifndef SWIG
+ _aiPrimitiveType_Force32Bit = INT_MAX
+#endif
+}; //! enum aiPrimitiveType
+
+// Get the #aiPrimitiveType flag for a specific number of face indices
+#define AI_PRIMITIVE_TYPE_FOR_N_INDICES(n) \
+ ((n) > 3 ? aiPrimitiveType_POLYGON : (aiPrimitiveType)(1u << ((n)-1)))
+
+
+
+// ---------------------------------------------------------------------------
+/** @brief An AnimMesh is an attachment to an #aiMesh stores per-vertex
+ * animations for a particular frame.
+ *
+ * You may think of an #aiAnimMesh as a `patch` for the host mesh, which
+ * replaces only certain vertex data streams at a particular time.
+ * Each mesh stores n attached attached meshes (#aiMesh::mAnimMeshes).
+ * The actual relationship between the time line and anim meshes is
+ * established by #aiMeshAnim, which references singular mesh attachments
+ * by their ID and binds them to a time offset.
+*/
+struct aiAnimMesh
+{
+ /**Anim Mesh name */
+ C_STRUCT aiString mName;
+
+ /** Replacement for aiMesh::mVertices. If this array is non-NULL,
+ * it *must* contain mNumVertices entries. The corresponding
+ * array in the host mesh must be non-NULL as well - animation
+ * meshes may neither add or nor remove vertex components (if
+ * a replacement array is NULL and the corresponding source
+ * array is not, the source data is taken instead)*/
+ C_STRUCT aiVector3D* mVertices;
+
+ /** Replacement for aiMesh::mNormals. */
+ C_STRUCT aiVector3D* mNormals;
+
+ /** Replacement for aiMesh::mTangents. */
+ C_STRUCT aiVector3D* mTangents;
+
+ /** Replacement for aiMesh::mBitangents. */
+ C_STRUCT aiVector3D* mBitangents;
+
+ /** Replacement for aiMesh::mColors */
+ C_STRUCT aiColor4D* mColors[AI_MAX_NUMBER_OF_COLOR_SETS];
+
+ /** Replacement for aiMesh::mTextureCoords */
+ C_STRUCT aiVector3D* mTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
+
+ /** The number of vertices in the aiAnimMesh, and thus the length of all
+ * the member arrays.
+ *
+ * This has always the same value as the mNumVertices property in the
+ * corresponding aiMesh. It is duplicated here merely to make the length
+ * of the member arrays accessible even if the aiMesh is not known, e.g.
+ * from language bindings.
+ */
+ unsigned int mNumVertices;
+
+ /**
+ * Weight of the AnimMesh.
+ */
+ float mWeight;
+
+#ifdef __cplusplus
+
+ aiAnimMesh() AI_NO_EXCEPT
+ : mVertices( nullptr )
+ , mNormals(nullptr)
+ , mTangents(nullptr)
+ , mBitangents(nullptr)
+ , mColors()
+ , mTextureCoords()
+ , mNumVertices( 0 )
+ , mWeight( 0.0f )
+ {
+ // fixme consider moving this to the ctor initializer list as well
+ for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++){
+ mTextureCoords[a] = nullptr;
+ }
+ for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; a++) {
+ mColors[a] = nullptr;
+ }
+ }
+
+ ~aiAnimMesh()
+ {
+ delete [] mVertices;
+ delete [] mNormals;
+ delete [] mTangents;
+ delete [] mBitangents;
+ for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++) {
+ delete [] mTextureCoords[a];
+ }
+ for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; a++) {
+ delete [] mColors[a];
+ }
+ }
+
+ /** Check whether the anim mesh overrides the vertex positions
+ * of its host mesh*/
+ bool HasPositions() const {
+ return mVertices != nullptr;
+ }
+
+ /** Check whether the anim mesh overrides the vertex normals
+ * of its host mesh*/
+ bool HasNormals() const {
+ return mNormals != nullptr;
+ }
+
+ /** Check whether the anim mesh overrides the vertex tangents
+ * and bitangents of its host mesh. As for aiMesh,
+ * tangents and bitangents always go together. */
+ bool HasTangentsAndBitangents() const {
+ return mTangents != nullptr;
+ }
+
+ /** Check whether the anim mesh overrides a particular
+ * set of vertex colors on his host mesh.
+ * @param pIndex 0<index<AI_MAX_NUMBER_OF_COLOR_SETS */
+ bool HasVertexColors( unsigned int pIndex) const {
+ return pIndex >= AI_MAX_NUMBER_OF_COLOR_SETS ? false : mColors[pIndex] != nullptr;
+ }
+
+ /** Check whether the anim mesh overrides a particular
+ * set of texture coordinates on his host mesh.
+ * @param pIndex 0<index<AI_MAX_NUMBER_OF_TEXTURECOORDS */
+ bool HasTextureCoords( unsigned int pIndex) const {
+ return pIndex >= AI_MAX_NUMBER_OF_TEXTURECOORDS ? false : mTextureCoords[pIndex] != nullptr;
+ }
+
+#endif
+};
+
+// ---------------------------------------------------------------------------
+/** @brief Enumerates the methods of mesh morphing supported by Assimp.
+ */
+enum aiMorphingMethod
+{
+ /** Interpolation between morph targets */
+ aiMorphingMethod_VERTEX_BLEND = 0x1,
+
+ /** Normalized morphing between morph targets */
+ aiMorphingMethod_MORPH_NORMALIZED = 0x2,
+
+ /** Relative morphing between morph targets */
+ aiMorphingMethod_MORPH_RELATIVE = 0x3,
+
+ /** This value is not used. It is just here to force the
+ * compiler to map this enum to a 32 Bit integer.
+ */
+#ifndef SWIG
+ _aiMorphingMethod_Force32Bit = INT_MAX
+#endif
+}; //! enum aiMorphingMethod
+
+// ---------------------------------------------------------------------------
+/** @brief A mesh represents a geometry or model with a single material.
+*
+* It usually consists of a number of vertices and a series of primitives/faces
+* referencing the vertices. In addition there might be a series of bones, each
+* of them addressing a number of vertices with a certain weight. Vertex data
+* is presented in channels with each channel containing a single per-vertex
+* information such as a set of texture coords or a normal vector.
+* If a data pointer is non-null, the corresponding data stream is present.
+* From C++-programs you can also use the comfort functions Has*() to
+* test for the presence of various data streams.
+*
+* A Mesh uses only a single material which is referenced by a material ID.
+* @note The mPositions member is usually not optional. However, vertex positions
+* *could* be missing if the #AI_SCENE_FLAGS_INCOMPLETE flag is set in
+* @code
+* aiScene::mFlags
+* @endcode
+*/
+struct aiMesh
+{
+ /** Bitwise combination of the members of the #aiPrimitiveType enum.
+ * This specifies which types of primitives are present in the mesh.
+ * The "SortByPrimitiveType"-Step can be used to make sure the
+ * output meshes consist of one primitive type each.
+ */
+ unsigned int mPrimitiveTypes;
+
+ /** The number of vertices in this mesh.
+ * This is also the size of all of the per-vertex data arrays.
+ * The maximum value for this member is #AI_MAX_VERTICES.
+ */
+ unsigned int mNumVertices;
+
+ /** The number of primitives (triangles, polygons, lines) in this mesh.
+ * This is also the size of the mFaces array.
+ * The maximum value for this member is #AI_MAX_FACES.
+ */
+ unsigned int mNumFaces;
+
+ /** Vertex positions.
+ * This array is always present in a mesh. The array is
+ * mNumVertices in size.
+ */
+ C_STRUCT aiVector3D* mVertices;
+
+ /** Vertex normals.
+ * The array contains normalized vectors, NULL if not present.
+ * The array is mNumVertices in size. Normals are undefined for
+ * point and line primitives. A mesh consisting of points and
+ * lines only may not have normal vectors. Meshes with mixed
+ * primitive types (i.e. lines and triangles) may have normals,
+ * but the normals for vertices that are only referenced by
+ * point or line primitives are undefined and set to QNaN (WARN:
+ * qNaN compares to inequal to *everything*, even to qNaN itself.
+ * Using code like this to check whether a field is qnan is:
+ * @code
+ * #define IS_QNAN(f) (f != f)
+ * @endcode
+ * still dangerous because even 1.f == 1.f could evaluate to false! (
+ * remember the subtleties of IEEE754 artithmetics). Use stuff like
+ * @c fpclassify instead.
+ * @note Normal vectors computed by Assimp are always unit-length.
+ * However, this needn't apply for normals that have been taken
+ * directly from the model file.
+ */
+ C_STRUCT aiVector3D* mNormals;
+
+ /** Vertex tangents.
+ * The tangent of a vertex points in the direction of the positive
+ * X texture axis. The array contains normalized vectors, NULL if
+ * not present. The array is mNumVertices in size. A mesh consisting
+ * of points and lines only may not have normal vectors. Meshes with
+ * mixed primitive types (i.e. lines and triangles) may have
+ * normals, but the normals for vertices that are only referenced by
+ * point or line primitives are undefined and set to qNaN. See
+ * the #mNormals member for a detailed discussion of qNaNs.
+ * @note If the mesh contains tangents, it automatically also
+ * contains bitangents.
+ */
+ C_STRUCT aiVector3D* mTangents;
+
+ /** Vertex bitangents.
+ * The bitangent of a vertex points in the direction of the positive
+ * Y texture axis. The array contains normalized vectors, NULL if not
+ * present. The array is mNumVertices in size.
+ * @note If the mesh contains tangents, it automatically also contains
+ * bitangents.
+ */
+ C_STRUCT aiVector3D* mBitangents;
+
+ /** Vertex color sets.
+ * A mesh may contain 0 to #AI_MAX_NUMBER_OF_COLOR_SETS vertex
+ * colors per vertex. NULL if not present. Each array is
+ * mNumVertices in size if present.
+ */
+ C_STRUCT aiColor4D* mColors[AI_MAX_NUMBER_OF_COLOR_SETS];
+
+ /** Vertex texture coords, also known as UV channels.
+ * A mesh may contain 0 to AI_MAX_NUMBER_OF_TEXTURECOORDS per
+ * vertex. NULL if not present. The array is mNumVertices in size.
+ */
+ C_STRUCT aiVector3D* mTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
+
+ /** Specifies the number of components for a given UV channel.
+ * Up to three channels are supported (UVW, for accessing volume
+ * or cube maps). If the value is 2 for a given channel n, the
+ * component p.z of mTextureCoords[n][p] is set to 0.0f.
+ * If the value is 1 for a given channel, p.y is set to 0.0f, too.
+ * @note 4D coords are not supported
+ */
+ unsigned int mNumUVComponents[AI_MAX_NUMBER_OF_TEXTURECOORDS];
+
+ /** The faces the mesh is constructed from.
+ * Each face refers to a number of vertices by their indices.
+ * This array is always present in a mesh, its size is given
+ * in mNumFaces. If the #AI_SCENE_FLAGS_NON_VERBOSE_FORMAT
+ * is NOT set each face references an unique set of vertices.
+ */
+ C_STRUCT aiFace* mFaces;
+
+ /** The number of bones this mesh contains.
+ * Can be 0, in which case the mBones array is NULL.
+ */
+ unsigned int mNumBones;
+
+ /** The bones of this mesh.
+ * A bone consists of a name by which it can be found in the
+ * frame hierarchy and a set of vertex weights.
+ */
+ C_STRUCT aiBone** mBones;
+
+ /** The material used by this mesh.
+ * A mesh uses only a single material. If an imported model uses
+ * multiple materials, the import splits up the mesh. Use this value
+ * as index into the scene's material list.
+ */
+ unsigned int mMaterialIndex;
+
+ /** Name of the mesh. Meshes can be named, but this is not a
+ * requirement and leaving this field empty is totally fine.
+ * There are mainly three uses for mesh names:
+ * - some formats name nodes and meshes independently.
+ * - importers tend to split meshes up to meet the
+ * one-material-per-mesh requirement. Assigning
+ * the same (dummy) name to each of the result meshes
+ * aids the caller at recovering the original mesh
+ * partitioning.
+ * - Vertex animations refer to meshes by their names.
+ **/
+ C_STRUCT aiString mName;
+
+
+ /** The number of attachment meshes. Note! Currently only works with Collada loader. */
+ unsigned int mNumAnimMeshes;
+
+ /** Attachment meshes for this mesh, for vertex-based animation.
+ * Attachment meshes carry replacement data for some of the
+ * mesh'es vertex components (usually positions, normals).
+ * Note! Currently only works with Collada loader.*/
+ C_STRUCT aiAnimMesh** mAnimMeshes;
+
+ /**
+ * Method of morphing when animeshes are specified.
+ */
+ unsigned int mMethod;
+
+#ifdef __cplusplus
+
+ //! Default constructor. Initializes all members to 0
+ aiMesh() AI_NO_EXCEPT
+ : mPrimitiveTypes( 0 )
+ , mNumVertices( 0 )
+ , mNumFaces( 0 )
+ , mVertices( nullptr )
+ , mNormals(nullptr)
+ , mTangents(nullptr)
+ , mBitangents(nullptr)
+ , mColors()
+ , mTextureCoords()
+ , mNumUVComponents()
+ , mFaces(nullptr)
+ , mNumBones( 0 )
+ , mBones(nullptr)
+ , mMaterialIndex( 0 )
+ , mNumAnimMeshes( 0 )
+ , mAnimMeshes(nullptr)
+ , mMethod( 0 ) {
+ for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a ) {
+ mNumUVComponents[a] = 0;
+ mTextureCoords[a] = nullptr;
+ }
+
+ for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a) {
+ mColors[a] = nullptr;
+ }
+ }
+
+ //! Deletes all storage allocated for the mesh
+ ~aiMesh() {
+ delete [] mVertices;
+ delete [] mNormals;
+ delete [] mTangents;
+ delete [] mBitangents;
+ for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++) {
+ delete [] mTextureCoords[a];
+ }
+ for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; a++) {
+ delete [] mColors[a];
+ }
+
+ // DO NOT REMOVE THIS ADDITIONAL CHECK
+ if (mNumBones && mBones) {
+ for( unsigned int a = 0; a < mNumBones; a++) {
+ delete mBones[a];
+ }
+ delete [] mBones;
+ }
+
+ if (mNumAnimMeshes && mAnimMeshes) {
+ for( unsigned int a = 0; a < mNumAnimMeshes; a++) {
+ delete mAnimMeshes[a];
+ }
+ delete [] mAnimMeshes;
+ }
+
+ delete [] mFaces;
+ }
+
+ //! Check whether the mesh contains positions. Provided no special
+ //! scene flags are set, this will always be true
+ bool HasPositions() const
+ { return mVertices != nullptr && mNumVertices > 0; }
+
+ //! Check whether the mesh contains faces. If no special scene flags
+ //! are set this should always return true
+ bool HasFaces() const
+ { return mFaces != nullptr && mNumFaces > 0; }
+
+ //! Check whether the mesh contains normal vectors
+ bool HasNormals() const
+ { return mNormals != nullptr && mNumVertices > 0; }
+
+ //! Check whether the mesh contains tangent and bitangent vectors
+ //! It is not possible that it contains tangents and no bitangents
+ //! (or the other way round). The existence of one of them
+ //! implies that the second is there, too.
+ bool HasTangentsAndBitangents() const
+ { return mTangents != nullptr && mBitangents != nullptr && mNumVertices > 0; }
+
+ //! Check whether the mesh contains a vertex color set
+ //! \param pIndex Index of the vertex color set
+ bool HasVertexColors( unsigned int pIndex) const {
+ if (pIndex >= AI_MAX_NUMBER_OF_COLOR_SETS) {
+ return false;
+ } else {
+ return mColors[pIndex] != nullptr && mNumVertices > 0;
+ }
+ }
+
+ //! Check whether the mesh contains a texture coordinate set
+ //! \param pIndex Index of the texture coordinates set
+ bool HasTextureCoords( unsigned int pIndex) const {
+ if (pIndex >= AI_MAX_NUMBER_OF_TEXTURECOORDS) {
+ return false;
+ } else {
+ return mTextureCoords[pIndex] != nullptr && mNumVertices > 0;
+ }
+ }
+
+ //! Get the number of UV channels the mesh contains
+ unsigned int GetNumUVChannels() const {
+ unsigned int n( 0 );
+ while (n < AI_MAX_NUMBER_OF_TEXTURECOORDS && mTextureCoords[n]) {
+ ++n;
+ }
+
+ return n;
+ }
+
+ //! Get the number of vertex color channels the mesh contains
+ unsigned int GetNumColorChannels() const {
+ unsigned int n(0);
+ while (n < AI_MAX_NUMBER_OF_COLOR_SETS && mColors[n]) {
+ ++n;
+ }
+ return n;
+ }
+
+ //! Check whether the mesh contains bones
+ bool HasBones() const {
+ return mBones != nullptr && mNumBones > 0;
+ }
+
+#endif // __cplusplus
+};
+
+#ifdef __cplusplus
+}
+#endif //! extern "C"
+#endif // AI_MESH_H_INC
+
diff --git a/thirdparty/assimp/include/assimp/metadata.h b/thirdparty/assimp/include/assimp/metadata.h
new file mode 100644
index 0000000000..3a1dd1442a
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/metadata.h
@@ -0,0 +1,380 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file metadata.h
+ * @brief Defines the data structures for holding node meta information.
+ */
+#pragma once
+#ifndef AI_METADATA_H_INC
+#define AI_METADATA_H_INC
+
+#if defined(_MSC_VER) && (_MSC_VER <= 1500)
+# include "Compiler/pstdint.h"
+#else
+# include <stdint.h>
+#endif
+
+// -------------------------------------------------------------------------------
+/**
+ * Enum used to distinguish data types
+ */
+ // -------------------------------------------------------------------------------
+typedef enum aiMetadataType {
+ AI_BOOL = 0,
+ AI_INT32 = 1,
+ AI_UINT64 = 2,
+ AI_FLOAT = 3,
+ AI_DOUBLE = 4,
+ AI_AISTRING = 5,
+ AI_AIVECTOR3D = 6,
+ AI_META_MAX = 7,
+
+#ifndef SWIG
+ FORCE_32BIT = INT_MAX
+#endif
+} aiMetadataType;
+
+// -------------------------------------------------------------------------------
+/**
+ * Metadata entry
+ *
+ * The type field uniquely identifies the underlying type of the data field
+ */
+ // -------------------------------------------------------------------------------
+struct aiMetadataEntry {
+ aiMetadataType mType;
+ void* mData;
+};
+
+#ifdef __cplusplus
+
+#include <string>
+
+// -------------------------------------------------------------------------------
+/**
+ * Helper functions to get the aiType enum entry for a type
+ */
+ // -------------------------------------------------------------------------------
+
+inline aiMetadataType GetAiType( bool ) { return AI_BOOL; }
+inline aiMetadataType GetAiType( int32_t ) { return AI_INT32; }
+inline aiMetadataType GetAiType( uint64_t ) { return AI_UINT64; }
+inline aiMetadataType GetAiType( float ) { return AI_FLOAT; }
+inline aiMetadataType GetAiType( double ) { return AI_DOUBLE; }
+inline aiMetadataType GetAiType( const aiString & ) { return AI_AISTRING; }
+inline aiMetadataType GetAiType( const aiVector3D & ) { return AI_AIVECTOR3D; }
+
+#endif // __cplusplus
+
+// -------------------------------------------------------------------------------
+/**
+ * Container for holding metadata.
+ *
+ * Metadata is a key-value store using string keys and values.
+ */
+ // -------------------------------------------------------------------------------
+struct aiMetadata {
+ /** Length of the mKeys and mValues arrays, respectively */
+ unsigned int mNumProperties;
+
+ /** Arrays of keys, may not be NULL. Entries in this array may not be NULL as well. */
+ C_STRUCT aiString* mKeys;
+
+ /** Arrays of values, may not be NULL. Entries in this array may be NULL if the
+ * corresponding property key has no assigned value. */
+ C_STRUCT aiMetadataEntry* mValues;
+
+#ifdef __cplusplus
+
+ /**
+ * @brief The default constructor, set all members to zero by default.
+ */
+ aiMetadata() AI_NO_EXCEPT
+ : mNumProperties(0)
+ , mKeys(nullptr)
+ , mValues(nullptr) {
+ // empty
+ }
+
+ aiMetadata( const aiMetadata &rhs )
+ : mNumProperties( rhs.mNumProperties )
+ , mKeys( nullptr )
+ , mValues( nullptr ) {
+ mKeys = new aiString[ mNumProperties ];
+ for ( size_t i = 0; i < static_cast<size_t>( mNumProperties ); ++i ) {
+ mKeys[ i ] = rhs.mKeys[ i ];
+ }
+ mValues = new aiMetadataEntry[ mNumProperties ];
+ for ( size_t i = 0; i < static_cast<size_t>(mNumProperties); ++i ) {
+ mValues[ i ].mType = rhs.mValues[ i ].mType;
+ switch ( rhs.mValues[ i ].mType ) {
+ case AI_BOOL:
+ mValues[ i ].mData = new bool;
+ ::memcpy( mValues[ i ].mData, rhs.mValues[ i ].mData, sizeof(bool) );
+ break;
+ case AI_INT32: {
+ int32_t v;
+ ::memcpy( &v, rhs.mValues[ i ].mData, sizeof( int32_t ) );
+ mValues[ i ].mData = new int32_t( v );
+ }
+ break;
+ case AI_UINT64: {
+ uint64_t v;
+ ::memcpy( &v, rhs.mValues[ i ].mData, sizeof( uint64_t ) );
+ mValues[ i ].mData = new uint64_t( v );
+ }
+ break;
+ case AI_FLOAT: {
+ float v;
+ ::memcpy( &v, rhs.mValues[ i ].mData, sizeof( float ) );
+ mValues[ i ].mData = new float( v );
+ }
+ break;
+ case AI_DOUBLE: {
+ double v;
+ ::memcpy( &v, rhs.mValues[ i ].mData, sizeof( double ) );
+ mValues[ i ].mData = new double( v );
+ }
+ break;
+ case AI_AISTRING: {
+ aiString v;
+ rhs.Get<aiString>( mKeys[ i ], v );
+ mValues[ i ].mData = new aiString( v );
+ }
+ break;
+ case AI_AIVECTOR3D: {
+ aiVector3D v;
+ rhs.Get<aiVector3D>( mKeys[ i ], v );
+ mValues[ i ].mData = new aiVector3D( v );
+ }
+ break;
+#ifndef SWIG
+ case FORCE_32BIT:
+#endif
+ default:
+ break;
+ }
+
+ }
+ }
+
+ /**
+ * @brief The destructor.
+ */
+ ~aiMetadata() {
+ delete [] mKeys;
+ mKeys = nullptr;
+ if (mValues) {
+ // Delete each metadata entry
+ for (unsigned i=0; i<mNumProperties; ++i) {
+ void* data = mValues[i].mData;
+ switch (mValues[i].mType) {
+ case AI_BOOL:
+ delete static_cast< bool* >( data );
+ break;
+ case AI_INT32:
+ delete static_cast< int32_t* >( data );
+ break;
+ case AI_UINT64:
+ delete static_cast< uint64_t* >( data );
+ break;
+ case AI_FLOAT:
+ delete static_cast< float* >( data );
+ break;
+ case AI_DOUBLE:
+ delete static_cast< double* >( data );
+ break;
+ case AI_AISTRING:
+ delete static_cast< aiString* >( data );
+ break;
+ case AI_AIVECTOR3D:
+ delete static_cast< aiVector3D* >( data );
+ break;
+#ifndef SWIG
+ case FORCE_32BIT:
+#endif
+ default:
+ break;
+ }
+ }
+
+ // Delete the metadata array
+ delete [] mValues;
+ mValues = nullptr;
+ }
+ }
+
+ /**
+ * @brief Allocates property fields + keys.
+ * @param numProperties Number of requested properties.
+ */
+ static inline
+ aiMetadata *Alloc( unsigned int numProperties ) {
+ if ( 0 == numProperties ) {
+ return nullptr;
+ }
+
+ aiMetadata *data = new aiMetadata;
+ data->mNumProperties = numProperties;
+ data->mKeys = new aiString[ data->mNumProperties ]();
+ data->mValues = new aiMetadataEntry[ data->mNumProperties ]();
+
+ return data;
+ }
+
+ /**
+ * @brief Deallocates property fields + keys.
+ */
+ static inline
+ void Dealloc( aiMetadata *metadata ) {
+ delete metadata;
+ }
+
+ template<typename T>
+ inline
+ void Add(const std::string& key, const T& value) {
+ aiString* new_keys = new aiString[mNumProperties + 1];
+ aiMetadataEntry* new_values = new aiMetadataEntry[mNumProperties + 1];
+
+ for(unsigned int i = 0; i < mNumProperties; ++i)
+ {
+ new_keys[i] = mKeys[i];
+ new_values[i] = mValues[i];
+ }
+
+ delete mKeys;
+ delete mValues;
+
+ mKeys = new_keys;
+ mValues = new_values;
+
+ mNumProperties++;
+
+ Set(mNumProperties - 1, key, value);
+ }
+
+ template<typename T>
+ inline
+ bool Set( unsigned index, const std::string& key, const T& value ) {
+ // In range assertion
+ if ( index >= mNumProperties ) {
+ return false;
+ }
+
+ // Ensure that we have a valid key.
+ if ( key.empty() ) {
+ return false;
+ }
+
+ // Set metadata key
+ mKeys[index] = key;
+
+ // Set metadata type
+ mValues[index].mType = GetAiType(value);
+ // Copy the given value to the dynamic storage
+ mValues[index].mData = new T(value);
+
+ return true;
+ }
+
+ template<typename T>
+ inline
+ bool Get( unsigned index, T& value ) const {
+ // In range assertion
+ if ( index >= mNumProperties ) {
+ return false;
+ }
+
+ // Return false if the output data type does
+ // not match the found value's data type
+ if ( GetAiType( value ) != mValues[ index ].mType ) {
+ return false;
+ }
+
+ // Otherwise, output the found value and
+ // return true
+ value = *static_cast<T*>(mValues[index].mData);
+
+ return true;
+ }
+
+ template<typename T>
+ inline
+ bool Get( const aiString& key, T& value ) const {
+ // Search for the given key
+ for ( unsigned int i = 0; i < mNumProperties; ++i ) {
+ if ( mKeys[ i ] == key ) {
+ return Get( i, value );
+ }
+ }
+ return false;
+ }
+
+ template<typename T>
+ inline
+ bool Get( const std::string& key, T& value ) const {
+ return Get(aiString(key), value);
+ }
+
+ /// Return metadata entry for analyzing it by user.
+ /// \param [in] pIndex - index of the entry.
+ /// \param [out] pKey - pointer to the key value.
+ /// \param [out] pEntry - pointer to the entry: type and value.
+ /// \return false - if pIndex is out of range, else - true.
+ inline
+ bool Get(size_t index, const aiString*& key, const aiMetadataEntry*& entry) const {
+ if ( index >= mNumProperties ) {
+ return false;
+ }
+
+ key = &mKeys[index];
+ entry = &mValues[index];
+
+ return true;
+ }
+
+#endif // __cplusplus
+
+};
+
+#endif // AI_METADATA_H_INC
diff --git a/thirdparty/assimp/include/assimp/pbrmaterial.h b/thirdparty/assimp/include/assimp/pbrmaterial.h
new file mode 100644
index 0000000000..ce5f822173
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/pbrmaterial.h
@@ -0,0 +1,77 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file pbrmaterial.h
+ * @brief Defines the material system of the library
+ */
+#ifndef AI_PBRMATERIAL_H_INC
+#define AI_PBRMATERIAL_H_INC
+
+#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_FACTOR "$mat.gltf.pbrMetallicRoughness.baseColorFactor", 0, 0
+#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR "$mat.gltf.pbrMetallicRoughness.metallicFactor", 0, 0
+#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR "$mat.gltf.pbrMetallicRoughness.roughnessFactor", 0, 0
+#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_TEXTURE aiTextureType_DIFFUSE, 1
+#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE aiTextureType_UNKNOWN, 0
+#define AI_MATKEY_GLTF_ALPHAMODE "$mat.gltf.alphaMode", 0, 0
+#define AI_MATKEY_GLTF_ALPHACUTOFF "$mat.gltf.alphaCutoff", 0, 0
+#define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS "$mat.gltf.pbrSpecularGlossiness", 0, 0
+#define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR "$mat.gltf.pbrMetallicRoughness.glossinessFactor", 0, 0
+#define AI_MATKEY_GLTF_UNLIT "$mat.gltf.unlit", 0, 0
+
+#define _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE "$tex.file.texCoord"
+#define _AI_MATKEY_GLTF_MAPPINGNAME_BASE "$tex.mappingname"
+#define _AI_MATKEY_GLTF_MAPPINGID_BASE "$tex.mappingid"
+#define _AI_MATKEY_GLTF_MAPPINGFILTER_MAG_BASE "$tex.mappingfiltermag"
+#define _AI_MATKEY_GLTF_MAPPINGFILTER_MIN_BASE "$tex.mappingfiltermin"
+#define _AI_MATKEY_GLTF_SCALE_BASE "$tex.scale"
+#define _AI_MATKEY_GLTF_STRENGTH_BASE "$tex.strength"
+
+#define AI_MATKEY_GLTF_TEXTURE_TEXCOORD(type, N) _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE, type, N
+#define AI_MATKEY_GLTF_MAPPINGNAME(type, N) _AI_MATKEY_GLTF_MAPPINGNAME_BASE, type, N
+#define AI_MATKEY_GLTF_MAPPINGID(type, N) _AI_MATKEY_GLTF_MAPPINGID_BASE, type, N
+#define AI_MATKEY_GLTF_MAPPINGFILTER_MAG(type, N) _AI_MATKEY_GLTF_MAPPINGFILTER_MAG_BASE, type, N
+#define AI_MATKEY_GLTF_MAPPINGFILTER_MIN(type, N) _AI_MATKEY_GLTF_MAPPINGFILTER_MIN_BASE, type, N
+#define AI_MATKEY_GLTF_TEXTURE_SCALE(type, N) _AI_MATKEY_GLTF_SCALE_BASE, type, N
+#define AI_MATKEY_GLTF_TEXTURE_STRENGTH(type, N) _AI_MATKEY_GLTF_STRENGTH_BASE, type, N
+
+#endif //!!AI_PBRMATERIAL_H_INC
diff --git a/thirdparty/assimp/include/assimp/port/AndroidJNI/AndroidJNIIOSystem.h b/thirdparty/assimp/include/assimp/port/AndroidJNI/AndroidJNIIOSystem.h
new file mode 100644
index 0000000000..41d8004877
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/port/AndroidJNI/AndroidJNIIOSystem.h
@@ -0,0 +1,92 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2016, assimp team
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file Android implementation of IOSystem using the standard C file functions.
+ * Aimed to ease the access to android assets */
+
+#if __ANDROID__ and __ANDROID_API__ > 9 and defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT)
+#ifndef AI_ANDROIDJNIIOSYSTEM_H_INC
+#define AI_ANDROIDJNIIOSYSTEM_H_INC
+
+#include <assimp/DefaultIOSystem.h>
+#include <android/asset_manager.h>
+#include <android/asset_manager_jni.h>
+#include <android/native_activity.h>
+
+namespace Assimp {
+
+// ---------------------------------------------------------------------------
+/** Android extension to DefaultIOSystem using the standard C file functions */
+class ASSIMP_API AndroidJNIIOSystem : public DefaultIOSystem
+{
+public:
+
+ /** Initialize android activity data */
+ std::string mApkWorkspacePath;
+ AAssetManager* mApkAssetManager;
+
+ /** Constructor. */
+ AndroidJNIIOSystem(ANativeActivity* activity);
+
+ /** Destructor. */
+ ~AndroidJNIIOSystem();
+
+ // -------------------------------------------------------------------
+ /** Tests for the existence of a file at the given path. */
+ bool Exists( const char* pFile) const;
+
+ // -------------------------------------------------------------------
+ /** Opens a file at the given path, with given mode */
+ IOStream* Open( const char* strFile, const char* strMode);
+
+ // ------------------------------------------------------------------------------------------------
+ // Inits Android extractor
+ void AndroidActivityInit(ANativeActivity* activity);
+
+ // ------------------------------------------------------------------------------------------------
+ // Extracts android asset
+ bool AndroidExtractAsset(std::string name);
+
+};
+
+} //!ns Assimp
+
+#endif //AI_ANDROIDJNIIOSYSTEM_H_INC
+#endif //__ANDROID__ and __ANDROID_API__ > 9 and defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT)
diff --git a/thirdparty/assimp/include/assimp/postprocess.h b/thirdparty/assimp/include/assimp/postprocess.h
new file mode 100644
index 0000000000..c23a5490a5
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/postprocess.h
@@ -0,0 +1,679 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file postprocess.h
+ * @brief Definitions for import post processing steps
+ */
+#pragma once
+#ifndef AI_POSTPROCESS_H_INC
+#define AI_POSTPROCESS_H_INC
+
+#include "types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// -----------------------------------------------------------------------------------
+/** @enum aiPostProcessSteps
+ * @brief Defines the flags for all possible post processing steps.
+ *
+ * @note Some steps are influenced by properties set on the Assimp::Importer itself
+ *
+ * @see Assimp::Importer::ReadFile()
+ * @see Assimp::Importer::SetPropertyInteger()
+ * @see aiImportFile
+ * @see aiImportFileEx
+ */
+// -----------------------------------------------------------------------------------
+enum aiPostProcessSteps
+{
+
+ // -------------------------------------------------------------------------
+ /** <hr>Calculates the tangents and bitangents for the imported meshes.
+ *
+ * Does nothing if a mesh does not have normals. You might want this post
+ * processing step to be executed if you plan to use tangent space calculations
+ * such as normal mapping applied to the meshes. There's an importer property,
+ * <tt>#AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE</tt>, which allows you to specify
+ * a maximum smoothing angle for the algorithm. However, usually you'll
+ * want to leave it at the default value.
+ */
+ aiProcess_CalcTangentSpace = 0x1,
+
+ // -------------------------------------------------------------------------
+ /** <hr>Identifies and joins identical vertex data sets within all
+ * imported meshes.
+ *
+ * After this step is run, each mesh contains unique vertices,
+ * so a vertex may be used by multiple faces. You usually want
+ * to use this post processing step. If your application deals with
+ * indexed geometry, this step is compulsory or you'll just waste rendering
+ * time. <b>If this flag is not specified</b>, no vertices are referenced by
+ * more than one face and <b>no index buffer is required</b> for rendering.
+ */
+ aiProcess_JoinIdenticalVertices = 0x2,
+
+ // -------------------------------------------------------------------------
+ /** <hr>Converts all the imported data to a left-handed coordinate space.
+ *
+ * By default the data is returned in a right-handed coordinate space (which
+ * OpenGL prefers). In this space, +X points to the right,
+ * +Z points towards the viewer, and +Y points upwards. In the DirectX
+ * coordinate space +X points to the right, +Y points upwards, and +Z points
+ * away from the viewer.
+ *
+ * You'll probably want to consider this flag if you use Direct3D for
+ * rendering. The #aiProcess_ConvertToLeftHanded flag supersedes this
+ * setting and bundles all conversions typically required for D3D-based
+ * applications.
+ */
+ aiProcess_MakeLeftHanded = 0x4,
+
+ // -------------------------------------------------------------------------
+ /** <hr>Triangulates all faces of all meshes.
+ *
+ * By default the imported mesh data might contain faces with more than 3
+ * indices. For rendering you'll usually want all faces to be triangles.
+ * This post processing step splits up faces with more than 3 indices into
+ * triangles. Line and point primitives are *not* modified! If you want
+ * 'triangles only' with no other kinds of primitives, try the following
+ * solution:
+ * <ul>
+ * <li>Specify both #aiProcess_Triangulate and #aiProcess_SortByPType </li>
+ * <li>Ignore all point and line meshes when you process assimp's output</li>
+ * </ul>
+ */
+ aiProcess_Triangulate = 0x8,
+
+ // -------------------------------------------------------------------------
+ /** <hr>Removes some parts of the data structure (animations, materials,
+ * light sources, cameras, textures, vertex components).
+ *
+ * The components to be removed are specified in a separate
+ * importer property, <tt>#AI_CONFIG_PP_RVC_FLAGS</tt>. This is quite useful
+ * if you don't need all parts of the output structure. Vertex colors
+ * are rarely used today for example... Calling this step to remove unneeded
+ * data from the pipeline as early as possible results in increased
+ * performance and a more optimized output data structure.
+ * This step is also useful if you want to force Assimp to recompute
+ * normals or tangents. The corresponding steps don't recompute them if
+ * they're already there (loaded from the source asset). By using this
+ * step you can make sure they are NOT there.
+ *
+ * This flag is a poor one, mainly because its purpose is usually
+ * misunderstood. Consider the following case: a 3D model has been exported
+ * from a CAD app, and it has per-face vertex colors. Vertex positions can't be
+ * shared, thus the #aiProcess_JoinIdenticalVertices step fails to
+ * optimize the data because of these nasty little vertex colors.
+ * Most apps don't even process them, so it's all for nothing. By using
+ * this step, unneeded components are excluded as early as possible
+ * thus opening more room for internal optimizations.
+ */
+ aiProcess_RemoveComponent = 0x10,
+
+ // -------------------------------------------------------------------------
+ /** <hr>Generates normals for all faces of all meshes.
+ *
+ * This is ignored if normals are already there at the time this flag
+ * is evaluated. Model importers try to load them from the source file, so
+ * they're usually already there. Face normals are shared between all points
+ * of a single face, so a single point can have multiple normals, which
+ * forces the library to duplicate vertices in some cases.
+ * #aiProcess_JoinIdenticalVertices is *senseless* then.
+ *
+ * This flag may not be specified together with #aiProcess_GenSmoothNormals.
+ */
+ aiProcess_GenNormals = 0x20,
+
+ // -------------------------------------------------------------------------
+ /** <hr>Generates smooth normals for all vertices in the mesh.
+ *
+ * This is ignored if normals are already there at the time this flag
+ * is evaluated. Model importers try to load them from the source file, so
+ * they're usually already there.
+ *
+ * This flag may not be specified together with
+ * #aiProcess_GenNormals. There's a importer property,
+ * <tt>#AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE</tt> which allows you to specify
+ * an angle maximum for the normal smoothing algorithm. Normals exceeding
+ * this limit are not smoothed, resulting in a 'hard' seam between two faces.
+ * Using a decent angle here (e.g. 80 degrees) results in very good visual
+ * appearance.
+ */
+ aiProcess_GenSmoothNormals = 0x40,
+
+ // -------------------------------------------------------------------------
+ /** <hr>Splits large meshes into smaller sub-meshes.
+ *
+ * This is quite useful for real-time rendering, where the number of triangles
+ * which can be maximally processed in a single draw-call is limited
+ * by the video driver/hardware. The maximum vertex buffer is usually limited
+ * too. Both requirements can be met with this step: you may specify both a
+ * triangle and vertex limit for a single mesh.
+ *
+ * The split limits can (and should!) be set through the
+ * <tt>#AI_CONFIG_PP_SLM_VERTEX_LIMIT</tt> and <tt>#AI_CONFIG_PP_SLM_TRIANGLE_LIMIT</tt>
+ * importer properties. The default values are <tt>#AI_SLM_DEFAULT_MAX_VERTICES</tt> and
+ * <tt>#AI_SLM_DEFAULT_MAX_TRIANGLES</tt>.
+ *
+ * Note that splitting is generally a time-consuming task, but only if there's
+ * something to split. The use of this step is recommended for most users.
+ */
+ aiProcess_SplitLargeMeshes = 0x80,
+
+ // -------------------------------------------------------------------------
+ /** <hr>Removes the node graph and pre-transforms all vertices with
+ * the local transformation matrices of their nodes.
+ *
+ * The output scene still contains nodes, however there is only a
+ * root node with children, each one referencing only one mesh,
+ * and each mesh referencing one material. For rendering, you can
+ * simply render all meshes in order - you don't need to pay
+ * attention to local transformations and the node hierarchy.
+ * Animations are removed during this step.
+ * This step is intended for applications without a scenegraph.
+ * The step CAN cause some problems: if e.g. a mesh of the asset
+ * contains normals and another, using the same material index, does not,
+ * they will be brought together, but the first meshes's part of
+ * the normal list is zeroed. However, these artifacts are rare.
+ * @note The <tt>#AI_CONFIG_PP_PTV_NORMALIZE</tt> configuration property
+ * can be set to normalize the scene's spatial dimension to the -1...1
+ * range.
+ */
+ aiProcess_PreTransformVertices = 0x100,
+
+ // -------------------------------------------------------------------------
+ /** <hr>Limits the number of bones simultaneously affecting a single vertex
+ * to a maximum value.
+ *
+ * If any vertex is affected by more than the maximum number of bones, the least
+ * important vertex weights are removed and the remaining vertex weights are
+ * renormalized so that the weights still sum up to 1.
+ * The default bone weight limit is 4 (defined as <tt>#AI_LMW_MAX_WEIGHTS</tt> in
+ * config.h), but you can use the <tt>#AI_CONFIG_PP_LBW_MAX_WEIGHTS</tt> importer
+ * property to supply your own limit to the post processing step.
+ *
+ * If you intend to perform the skinning in hardware, this post processing
+ * step might be of interest to you.
+ */
+ aiProcess_LimitBoneWeights = 0x200,
+
+ // -------------------------------------------------------------------------
+ /** <hr>Validates the imported scene data structure.
+ * This makes sure that all indices are valid, all animations and
+ * bones are linked correctly, all material references are correct .. etc.
+ *
+ * It is recommended that you capture Assimp's log output if you use this flag,
+ * so you can easily find out what's wrong if a file fails the
+ * validation. The validator is quite strict and will find *all*
+ * inconsistencies in the data structure... It is recommended that plugin
+ * developers use it to debug their loaders. There are two types of
+ * validation failures:
+ * <ul>
+ * <li>Error: There's something wrong with the imported data. Further
+ * postprocessing is not possible and the data is not usable at all.
+ * The import fails. #Importer::GetErrorString() or #aiGetErrorString()
+ * carry the error message around.</li>
+ * <li>Warning: There are some minor issues (e.g. 1000000 animation
+ * keyframes with the same time), but further postprocessing and use
+ * of the data structure is still safe. Warning details are written
+ * to the log file, <tt>#AI_SCENE_FLAGS_VALIDATION_WARNING</tt> is set
+ * in #aiScene::mFlags</li>
+ * </ul>
+ *
+ * This post-processing step is not time-consuming. Its use is not
+ * compulsory, but recommended.
+ */
+ aiProcess_ValidateDataStructure = 0x400,
+
+ // -------------------------------------------------------------------------
+ /** <hr>Reorders triangles for better vertex cache locality.
+ *
+ * The step tries to improve the ACMR (average post-transform vertex cache
+ * miss ratio) for all meshes. The implementation runs in O(n) and is
+ * roughly based on the 'tipsify' algorithm (see <a href="
+ * http://www.cs.princeton.edu/gfx/pubs/Sander_2007_%3ETR/tipsy.pdf">this
+ * paper</a>).
+ *
+ * If you intend to render huge models in hardware, this step might
+ * be of interest to you. The <tt>#AI_CONFIG_PP_ICL_PTCACHE_SIZE</tt>
+ * importer property can be used to fine-tune the cache optimization.
+ */
+ aiProcess_ImproveCacheLocality = 0x800,
+
+ // -------------------------------------------------------------------------
+ /** <hr>Searches for redundant/unreferenced materials and removes them.
+ *
+ * This is especially useful in combination with the
+ * #aiProcess_PreTransformVertices and #aiProcess_OptimizeMeshes flags.
+ * Both join small meshes with equal characteristics, but they can't do
+ * their work if two meshes have different materials. Because several
+ * material settings are lost during Assimp's import filters,
+ * (and because many exporters don't check for redundant materials), huge
+ * models often have materials which are are defined several times with
+ * exactly the same settings.
+ *
+ * Several material settings not contributing to the final appearance of
+ * a surface are ignored in all comparisons (e.g. the material name).
+ * So, if you're passing additional information through the
+ * content pipeline (probably using *magic* material names), don't
+ * specify this flag. Alternatively take a look at the
+ * <tt>#AI_CONFIG_PP_RRM_EXCLUDE_LIST</tt> importer property.
+ */
+ aiProcess_RemoveRedundantMaterials = 0x1000,
+
+ // -------------------------------------------------------------------------
+ /** <hr>This step tries to determine which meshes have normal vectors
+ * that are facing inwards and inverts them.
+ *
+ * The algorithm is simple but effective:
+ * the bounding box of all vertices + their normals is compared against
+ * the volume of the bounding box of all vertices without their normals.
+ * This works well for most objects, problems might occur with planar
+ * surfaces. However, the step tries to filter such cases.
+ * The step inverts all in-facing normals. Generally it is recommended
+ * to enable this step, although the result is not always correct.
+ */
+ aiProcess_FixInfacingNormals = 0x2000,
+
+ // -------------------------------------------------------------------------
+ /** <hr>This step splits meshes with more than one primitive type in
+ * homogeneous sub-meshes.
+ *
+ * The step is executed after the triangulation step. After the step
+ * returns, just one bit is set in aiMesh::mPrimitiveTypes. This is
+ * especially useful for real-time rendering where point and line
+ * primitives are often ignored or rendered separately.
+ * You can use the <tt>#AI_CONFIG_PP_SBP_REMOVE</tt> importer property to
+ * specify which primitive types you need. This can be used to easily
+ * exclude lines and points, which are rarely used, from the import.
+ */
+ aiProcess_SortByPType = 0x8000,
+
+ // -------------------------------------------------------------------------
+ /** <hr>This step searches all meshes for degenerate primitives and
+ * converts them to proper lines or points.
+ *
+ * A face is 'degenerate' if one or more of its points are identical.
+ * To have the degenerate stuff not only detected and collapsed but
+ * removed, try one of the following procedures:
+ * <br><b>1.</b> (if you support lines and points for rendering but don't
+ * want the degenerates)<br>
+ * <ul>
+ * <li>Specify the #aiProcess_FindDegenerates flag.
+ * </li>
+ * <li>Set the <tt>#AI_CONFIG_PP_FD_REMOVE</tt> importer property to
+ * 1. This will cause the step to remove degenerate triangles from the
+ * import as soon as they're detected. They won't pass any further
+ * pipeline steps.
+ * </li>
+ * </ul>
+ * <br><b>2.</b>(if you don't support lines and points at all)<br>
+ * <ul>
+ * <li>Specify the #aiProcess_FindDegenerates flag.
+ * </li>
+ * <li>Specify the #aiProcess_SortByPType flag. This moves line and
+ * point primitives to separate meshes.
+ * </li>
+ * <li>Set the <tt>#AI_CONFIG_PP_SBP_REMOVE</tt> importer property to
+ * @code aiPrimitiveType_POINTS | aiPrimitiveType_LINES
+ * @endcode to cause SortByPType to reject point
+ * and line meshes from the scene.
+ * </li>
+ * </ul>
+ *
+ * This step also removes very small triangles with a surface area smaller
+ * than 10^-6. If you rely on having these small triangles, or notice holes
+ * in your model, set the property <tt>#AI_CONFIG_PP_FD_CHECKAREA</tt> to
+ * false.
+ * @note Degenerate polygons are not necessarily evil and that's why
+ * they're not removed by default. There are several file formats which
+ * don't support lines or points, and some exporters bypass the
+ * format specification and write them as degenerate triangles instead.
+ */
+ aiProcess_FindDegenerates = 0x10000,
+
+ // -------------------------------------------------------------------------
+ /** <hr>This step searches all meshes for invalid data, such as zeroed
+ * normal vectors or invalid UV coords and removes/fixes them. This is
+ * intended to get rid of some common exporter errors.
+ *
+ * This is especially useful for normals. If they are invalid, and
+ * the step recognizes this, they will be removed and can later
+ * be recomputed, i.e. by the #aiProcess_GenSmoothNormals flag.<br>
+ * The step will also remove meshes that are infinitely small and reduce
+ * animation tracks consisting of hundreds if redundant keys to a single
+ * key. The <tt>AI_CONFIG_PP_FID_ANIM_ACCURACY</tt> config property decides
+ * the accuracy of the check for duplicate animation tracks.
+ */
+ aiProcess_FindInvalidData = 0x20000,
+
+ // -------------------------------------------------------------------------
+ /** <hr>This step converts non-UV mappings (such as spherical or
+ * cylindrical mapping) to proper texture coordinate channels.
+ *
+ * Most applications will support UV mapping only, so you will
+ * probably want to specify this step in every case. Note that Assimp is not
+ * always able to match the original mapping implementation of the
+ * 3D app which produced a model perfectly. It's always better to let the
+ * modelling app compute the UV channels - 3ds max, Maya, Blender,
+ * LightWave, and Modo do this for example.
+ *
+ * @note If this step is not requested, you'll need to process the
+ * <tt>#AI_MATKEY_MAPPING</tt> material property in order to display all assets
+ * properly.
+ */
+ aiProcess_GenUVCoords = 0x40000,
+
+ // -------------------------------------------------------------------------
+ /** <hr>This step applies per-texture UV transformations and bakes
+ * them into stand-alone vtexture coordinate channels.
+ *
+ * UV transformations are specified per-texture - see the
+ * <tt>#AI_MATKEY_UVTRANSFORM</tt> material key for more information.
+ * This step processes all textures with
+ * transformed input UV coordinates and generates a new (pre-transformed) UV channel
+ * which replaces the old channel. Most applications won't support UV
+ * transformations, so you will probably want to specify this step.
+ *
+ * @note UV transformations are usually implemented in real-time apps by
+ * transforming texture coordinates at vertex shader stage with a 3x3
+ * (homogenous) transformation matrix.
+ */
+ aiProcess_TransformUVCoords = 0x80000,
+
+ // -------------------------------------------------------------------------
+ /** <hr>This step searches for duplicate meshes and replaces them
+ * with references to the first mesh.
+ *
+ * This step takes a while, so don't use it if speed is a concern.
+ * Its main purpose is to workaround the fact that many export
+ * file formats don't support instanced meshes, so exporters need to
+ * duplicate meshes. This step removes the duplicates again. Please
+ * note that Assimp does not currently support per-node material
+ * assignment to meshes, which means that identical meshes with
+ * different materials are currently *not* joined, although this is
+ * planned for future versions.
+ */
+ aiProcess_FindInstances = 0x100000,
+
+ // -------------------------------------------------------------------------
+ /** <hr>A postprocessing step to reduce the number of meshes.
+ *
+ * This will, in fact, reduce the number of draw calls.
+ *
+ * This is a very effective optimization and is recommended to be used
+ * together with #aiProcess_OptimizeGraph, if possible. The flag is fully
+ * compatible with both #aiProcess_SplitLargeMeshes and #aiProcess_SortByPType.
+ */
+ aiProcess_OptimizeMeshes = 0x200000,
+
+
+ // -------------------------------------------------------------------------
+ /** <hr>A postprocessing step to optimize the scene hierarchy.
+ *
+ * Nodes without animations, bones, lights or cameras assigned are
+ * collapsed and joined.
+ *
+ * Node names can be lost during this step. If you use special 'tag nodes'
+ * to pass additional information through your content pipeline, use the
+ * <tt>#AI_CONFIG_PP_OG_EXCLUDE_LIST</tt> importer property to specify a
+ * list of node names you want to be kept. Nodes matching one of the names
+ * in this list won't be touched or modified.
+ *
+ * Use this flag with caution. Most simple files will be collapsed to a
+ * single node, so complex hierarchies are usually completely lost. This is not
+ * useful for editor environments, but probably a very effective
+ * optimization if you just want to get the model data, convert it to your
+ * own format, and render it as fast as possible.
+ *
+ * This flag is designed to be used with #aiProcess_OptimizeMeshes for best
+ * results.
+ *
+ * @note 'Crappy' scenes with thousands of extremely small meshes packed
+ * in deeply nested nodes exist for almost all file formats.
+ * #aiProcess_OptimizeMeshes in combination with #aiProcess_OptimizeGraph
+ * usually fixes them all and makes them renderable.
+ */
+ aiProcess_OptimizeGraph = 0x400000,
+
+ // -------------------------------------------------------------------------
+ /** <hr>This step flips all UV coordinates along the y-axis and adjusts
+ * material settings and bitangents accordingly.
+ *
+ * <b>Output UV coordinate system:</b>
+ * @code
+ * 0y|0y ---------- 1x|0y
+ * | |
+ * | |
+ * | |
+ * 0x|1y ---------- 1x|1y
+ * @endcode
+ *
+ * You'll probably want to consider this flag if you use Direct3D for
+ * rendering. The #aiProcess_ConvertToLeftHanded flag supersedes this
+ * setting and bundles all conversions typically required for D3D-based
+ * applications.
+ */
+ aiProcess_FlipUVs = 0x800000,
+
+ // -------------------------------------------------------------------------
+ /** <hr>This step adjusts the output face winding order to be CW.
+ *
+ * The default face winding order is counter clockwise (CCW).
+ *
+ * <b>Output face order:</b>
+ * @code
+ * x2
+ *
+ * x0
+ * x1
+ * @endcode
+ */
+ aiProcess_FlipWindingOrder = 0x1000000,
+
+ // -------------------------------------------------------------------------
+ /** <hr>This step splits meshes with many bones into sub-meshes so that each
+ * su-bmesh has fewer or as many bones as a given limit.
+ */
+ aiProcess_SplitByBoneCount = 0x2000000,
+
+ // -------------------------------------------------------------------------
+ /** <hr>This step removes bones losslessly or according to some threshold.
+ *
+ * In some cases (i.e. formats that require it) exporters are forced to
+ * assign dummy bone weights to otherwise static meshes assigned to
+ * animated meshes. Full, weight-based skinning is expensive while
+ * animating nodes is extremely cheap, so this step is offered to clean up
+ * the data in that regard.
+ *
+ * Use <tt>#AI_CONFIG_PP_DB_THRESHOLD</tt> to control this.
+ * Use <tt>#AI_CONFIG_PP_DB_ALL_OR_NONE</tt> if you want bones removed if and
+ * only if all bones within the scene qualify for removal.
+ */
+ aiProcess_Debone = 0x4000000,
+
+ // -------------------------------------------------------------------------
+ /** <hr>This step will perform a global scale of the model.
+ *
+ * Some importers are providing a mechanism to define a scaling unit for the
+ * model. This post processing step can be used to do so. You need to get the
+ * global scaling from your importer settings like in FBX. Use the flag
+ * AI_CONFIG_GLOBAL_SCALE_FACTOR_KEY from the global property table to configure this.
+ *
+ * Use <tt>#AI_CONFIG_GLOBAL_SCALE_FACTOR_KEY</tt> to setup the global scaing factor.
+ */
+ aiProcess_GlobalScale = 0x8000000,
+
+ // -------------------------------------------------------------------------
+ /** <hr>A postprocessing step to embed of textures.
+ *
+ * This will remove external data dependencies for textures.
+ * If a texture's file does not exist at the specified path
+ * (due, for instance, to an absolute path generated on another system),
+ * it will check if a file with the same name exists at the root folder
+ * of the imported model. And if so, it uses that.
+ */
+ aiProcess_EmbedTextures = 0x10000000,
+
+ // aiProcess_GenEntityMeshes = 0x100000,
+ // aiProcess_OptimizeAnimations = 0x200000
+ // aiProcess_FixTexturePaths = 0x200000
+
+
+ aiProcess_ForceGenNormals = 0x20000000,
+
+ // -------------------------------------------------------------------------
+ /** <hr>Drops normals for all faces of all meshes.
+ *
+ * This is ignored if no normals are present.
+ * Face normals are shared between all points of a single face,
+ * so a single point can have multiple normals, which
+ * forces the library to duplicate vertices in some cases.
+ * #aiProcess_JoinIdenticalVertices is *senseless* then.
+ * This process gives sense back to aiProcess_JoinIdenticalVertices
+ */
+ aiProcess_DropNormals = 0x40000000,
+};
+
+
+// ---------------------------------------------------------------------------------------
+/** @def aiProcess_ConvertToLeftHanded
+ * @brief Shortcut flag for Direct3D-based applications.
+ *
+ * Supersedes the #aiProcess_MakeLeftHanded and #aiProcess_FlipUVs and
+ * #aiProcess_FlipWindingOrder flags.
+ * The output data matches Direct3D's conventions: left-handed geometry, upper-left
+ * origin for UV coordinates and finally clockwise face order, suitable for CCW culling.
+ *
+ * @deprecated
+ */
+#define aiProcess_ConvertToLeftHanded ( \
+ aiProcess_MakeLeftHanded | \
+ aiProcess_FlipUVs | \
+ aiProcess_FlipWindingOrder | \
+ 0 )
+
+
+// ---------------------------------------------------------------------------------------
+/** @def aiProcessPreset_TargetRealtime_Fast
+ * @brief Default postprocess configuration optimizing the data for real-time rendering.
+ *
+ * Applications would want to use this preset to load models on end-user PCs,
+ * maybe for direct use in game.
+ *
+ * If you're using DirectX, don't forget to combine this value with
+ * the #aiProcess_ConvertToLeftHanded step. If you don't support UV transformations
+ * in your application apply the #aiProcess_TransformUVCoords step, too.
+ * @note Please take the time to read the docs for the steps enabled by this preset.
+ * Some of them offer further configurable properties, while some of them might not be of
+ * use for you so it might be better to not specify them.
+ */
+#define aiProcessPreset_TargetRealtime_Fast ( \
+ aiProcess_CalcTangentSpace | \
+ aiProcess_GenNormals | \
+ aiProcess_JoinIdenticalVertices | \
+ aiProcess_Triangulate | \
+ aiProcess_GenUVCoords | \
+ aiProcess_SortByPType | \
+ 0 )
+
+ // ---------------------------------------------------------------------------------------
+ /** @def aiProcessPreset_TargetRealtime_Quality
+ * @brief Default postprocess configuration optimizing the data for real-time rendering.
+ *
+ * Unlike #aiProcessPreset_TargetRealtime_Fast, this configuration
+ * performs some extra optimizations to improve rendering speed and
+ * to minimize memory usage. It could be a good choice for a level editor
+ * environment where import speed is not so important.
+ *
+ * If you're using DirectX, don't forget to combine this value with
+ * the #aiProcess_ConvertToLeftHanded step. If you don't support UV transformations
+ * in your application apply the #aiProcess_TransformUVCoords step, too.
+ * @note Please take the time to read the docs for the steps enabled by this preset.
+ * Some of them offer further configurable properties, while some of them might not be
+ * of use for you so it might be better to not specify them.
+ */
+#define aiProcessPreset_TargetRealtime_Quality ( \
+ aiProcess_CalcTangentSpace | \
+ aiProcess_GenSmoothNormals | \
+ aiProcess_JoinIdenticalVertices | \
+ aiProcess_ImproveCacheLocality | \
+ aiProcess_LimitBoneWeights | \
+ aiProcess_RemoveRedundantMaterials | \
+ aiProcess_SplitLargeMeshes | \
+ aiProcess_Triangulate | \
+ aiProcess_GenUVCoords | \
+ aiProcess_SortByPType | \
+ aiProcess_FindDegenerates | \
+ aiProcess_FindInvalidData | \
+ 0 )
+
+ // ---------------------------------------------------------------------------------------
+ /** @def aiProcessPreset_TargetRealtime_MaxQuality
+ * @brief Default postprocess configuration optimizing the data for real-time rendering.
+ *
+ * This preset enables almost every optimization step to achieve perfectly
+ * optimized data. It's your choice for level editor environments where import speed
+ * is not important.
+ *
+ * If you're using DirectX, don't forget to combine this value with
+ * the #aiProcess_ConvertToLeftHanded step. If you don't support UV transformations
+ * in your application, apply the #aiProcess_TransformUVCoords step, too.
+ * @note Please take the time to read the docs for the steps enabled by this preset.
+ * Some of them offer further configurable properties, while some of them might not be
+ * of use for you so it might be better to not specify them.
+ */
+#define aiProcessPreset_TargetRealtime_MaxQuality ( \
+ aiProcessPreset_TargetRealtime_Quality | \
+ aiProcess_FindInstances | \
+ aiProcess_ValidateDataStructure | \
+ aiProcess_OptimizeMeshes | \
+ 0 )
+
+
+#ifdef __cplusplus
+} // end of extern "C"
+#endif
+
+#endif // AI_POSTPROCESS_H_INC
diff --git a/thirdparty/assimp/include/assimp/qnan.h b/thirdparty/assimp/include/assimp/qnan.h
new file mode 100644
index 0000000000..0918bde5e7
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/qnan.h
@@ -0,0 +1,165 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file qnan.h
+ * @brief Some utilities for our dealings with qnans.
+ *
+ * @note Some loaders use qnans to mark invalid values tempoarily, also
+ * Assimp explicitly enforces undefined normals to be set to qnan.
+ * qnan utilities are available in standard libraries (C99 for example)
+ * but last time I checked compiler coverage was so bad that I decided
+ * to reinvent the wheel.
+ */
+
+#ifndef AI_QNAN_H_INCLUDED
+#define AI_QNAN_H_INCLUDED
+
+#include <assimp/defs.h>
+#include <limits>
+#include <stdint.h>
+
+// ---------------------------------------------------------------------------
+/** Data structure to represent the bit pattern of a 32 Bit
+ * IEEE 754 floating-point number. */
+union _IEEESingle
+{
+ float Float;
+ struct
+ {
+ uint32_t Frac : 23;
+ uint32_t Exp : 8;
+ uint32_t Sign : 1;
+ } IEEE;
+};
+
+// ---------------------------------------------------------------------------
+/** Data structure to represent the bit pattern of a 64 Bit
+ * IEEE 754 floating-point number. */
+union _IEEEDouble
+{
+ double Double;
+ struct
+ {
+ uint64_t Frac : 52;
+ uint64_t Exp : 11;
+ uint64_t Sign : 1;
+ } IEEE;
+};
+
+// ---------------------------------------------------------------------------
+/** Check whether a given float is qNaN.
+ * @param in Input value */
+AI_FORCE_INLINE bool is_qnan(float in)
+{
+ // the straightforward solution does not work:
+ // return (in != in);
+ // compiler generates code like this
+ // load <in> to <register-with-different-width>
+ // compare <register-with-different-width> against <in>
+
+ // FIXME: Use <float> stuff instead? I think fpclassify needs C99
+ _IEEESingle temp;
+ memcpy(&temp, &in, sizeof(float));
+ return (temp.IEEE.Exp == (1u << 8)-1 &&
+ temp.IEEE.Frac);
+}
+
+// ---------------------------------------------------------------------------
+/** Check whether a given double is qNaN.
+ * @param in Input value */
+AI_FORCE_INLINE bool is_qnan(double in)
+{
+ // the straightforward solution does not work:
+ // return (in != in);
+ // compiler generates code like this
+ // load <in> to <register-with-different-width>
+ // compare <register-with-different-width> against <in>
+
+ // FIXME: Use <float> stuff instead? I think fpclassify needs C99
+ _IEEEDouble temp;
+ memcpy(&temp, &in, sizeof(in));
+ return (temp.IEEE.Exp == (1u << 11)-1 &&
+ temp.IEEE.Frac);
+}
+
+// ---------------------------------------------------------------------------
+/** @brief check whether a float is either NaN or (+/-) INF.
+ *
+ * Denorms return false, they're treated like normal values.
+ * @param in Input value */
+AI_FORCE_INLINE bool is_special_float(float in)
+{
+ _IEEESingle temp;
+ memcpy(&temp, &in, sizeof(float));
+ return (temp.IEEE.Exp == (1u << 8)-1);
+}
+
+// ---------------------------------------------------------------------------
+/** @brief check whether a double is either NaN or (+/-) INF.
+ *
+ * Denorms return false, they're treated like normal values.
+ * @param in Input value */
+AI_FORCE_INLINE bool is_special_float(double in)
+{
+ _IEEESingle temp;
+ memcpy(&temp, &in, sizeof(float));
+ return (temp.IEEE.Exp == (1u << 11)-1);
+}
+
+// ---------------------------------------------------------------------------
+/** Check whether a float is NOT qNaN.
+ * @param in Input value */
+template<class TReal>
+AI_FORCE_INLINE bool is_not_qnan(TReal in)
+{
+ return !is_qnan(in);
+}
+
+// ---------------------------------------------------------------------------
+/** @brief Get a fresh qnan. */
+AI_FORCE_INLINE ai_real get_qnan()
+{
+ return std::numeric_limits<ai_real>::quiet_NaN();
+}
+
+#endif // !! AI_QNAN_H_INCLUDED
diff --git a/thirdparty/assimp/include/assimp/quaternion.h b/thirdparty/assimp/include/assimp/quaternion.h
new file mode 100644
index 0000000000..96574d24b9
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/quaternion.h
@@ -0,0 +1,130 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file quaternion.h
+ * @brief Quaternion structure, including operators when compiling in C++
+ */
+#pragma once
+#ifndef AI_QUATERNION_H_INC
+#define AI_QUATERNION_H_INC
+
+#ifdef __cplusplus
+
+#include "defs.h"
+
+template <typename TReal> class aiVector3t;
+template <typename TReal> class aiMatrix3x3t;
+
+// ---------------------------------------------------------------------------
+/** Represents a quaternion in a 4D vector. */
+template <typename TReal>
+class aiQuaterniont
+{
+public:
+ aiQuaterniont() AI_NO_EXCEPT : w(1.0), x(), y(), z() {}
+ aiQuaterniont(TReal pw, TReal px, TReal py, TReal pz)
+ : w(pw), x(px), y(py), z(pz) {}
+
+ /** Construct from rotation matrix. Result is undefined if the matrix is not orthonormal. */
+ explicit aiQuaterniont( const aiMatrix3x3t<TReal>& pRotMatrix);
+
+ /** Construct from euler angles */
+ aiQuaterniont( TReal rotx, TReal roty, TReal rotz);
+
+ /** Construct from an axis-angle pair */
+ aiQuaterniont( aiVector3t<TReal> axis, TReal angle);
+
+ /** Construct from a normalized quaternion stored in a vec3 */
+ explicit aiQuaterniont( aiVector3t<TReal> normalized);
+
+ /** Returns a matrix representation of the quaternion */
+ aiMatrix3x3t<TReal> GetMatrix() const;
+
+public:
+
+ bool operator== (const aiQuaterniont& o) const;
+ bool operator!= (const aiQuaterniont& o) const;
+
+ bool Equal(const aiQuaterniont& o, TReal epsilon = 1e-6) const;
+
+public:
+
+ /** Normalize the quaternion */
+ aiQuaterniont& Normalize();
+
+ /** Compute quaternion conjugate */
+ aiQuaterniont& Conjugate ();
+
+ /** Rotate a point by this quaternion */
+ aiVector3t<TReal> Rotate (const aiVector3t<TReal>& in);
+
+ /** Multiply two quaternions */
+ aiQuaterniont operator* (const aiQuaterniont& two) const;
+
+public:
+
+ /** Performs a spherical interpolation between two quaternions and writes the result into the third.
+ * @param pOut Target object to received the interpolated rotation.
+ * @param pStart Start rotation of the interpolation at factor == 0.
+ * @param pEnd End rotation, factor == 1.
+ * @param pFactor Interpolation factor between 0 and 1. Values outside of this range yield undefined results.
+ */
+ static void Interpolate( aiQuaterniont& pOut, const aiQuaterniont& pStart,
+ const aiQuaterniont& pEnd, TReal pFactor);
+
+public:
+
+ //! w,x,y,z components of the quaternion
+ TReal w, x, y, z;
+} ;
+
+typedef aiQuaterniont<ai_real> aiQuaternion;
+
+#else
+
+struct aiQuaternion {
+ ai_real w, x, y, z;
+};
+
+#endif
+
+#endif // AI_QUATERNION_H_INC
diff --git a/thirdparty/assimp/include/assimp/quaternion.inl b/thirdparty/assimp/include/assimp/quaternion.inl
new file mode 100644
index 0000000000..c26648215e
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/quaternion.inl
@@ -0,0 +1,286 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file quaternion.inl
+ * @brief Inline implementation of aiQuaterniont<TReal> operators
+ */
+#pragma once
+#ifndef AI_QUATERNION_INL_INC
+#define AI_QUATERNION_INL_INC
+
+#ifdef __cplusplus
+#include "quaternion.h"
+
+#include <cmath>
+
+// ---------------------------------------------------------------------------
+template<typename TReal>
+bool aiQuaterniont<TReal>::operator== (const aiQuaterniont& o) const
+{
+ return x == o.x && y == o.y && z == o.z && w == o.w;
+}
+
+// ---------------------------------------------------------------------------
+template<typename TReal>
+bool aiQuaterniont<TReal>::operator!= (const aiQuaterniont& o) const
+{
+ return !(*this == o);
+}
+
+// ---------------------------------------------------------------------------
+template<typename TReal>
+inline bool aiQuaterniont<TReal>::Equal(const aiQuaterniont& o, TReal epsilon) const {
+ return
+ std::abs(x - o.x) <= epsilon &&
+ std::abs(y - o.y) <= epsilon &&
+ std::abs(z - o.z) <= epsilon &&
+ std::abs(w - o.w) <= epsilon;
+}
+
+// ---------------------------------------------------------------------------
+// Constructs a quaternion from a rotation matrix
+template<typename TReal>
+inline aiQuaterniont<TReal>::aiQuaterniont( const aiMatrix3x3t<TReal> &pRotMatrix)
+{
+ TReal t = pRotMatrix.a1 + pRotMatrix.b2 + pRotMatrix.c3;
+
+ // large enough
+ if( t > static_cast<TReal>(0))
+ {
+ TReal s = std::sqrt(1 + t) * static_cast<TReal>(2.0);
+ x = (pRotMatrix.c2 - pRotMatrix.b3) / s;
+ y = (pRotMatrix.a3 - pRotMatrix.c1) / s;
+ z = (pRotMatrix.b1 - pRotMatrix.a2) / s;
+ w = static_cast<TReal>(0.25) * s;
+ } // else we have to check several cases
+ else if( pRotMatrix.a1 > pRotMatrix.b2 && pRotMatrix.a1 > pRotMatrix.c3 )
+ {
+ // Column 0:
+ TReal s = std::sqrt( static_cast<TReal>(1.0) + pRotMatrix.a1 - pRotMatrix.b2 - pRotMatrix.c3) * static_cast<TReal>(2.0);
+ x = static_cast<TReal>(0.25) * s;
+ y = (pRotMatrix.b1 + pRotMatrix.a2) / s;
+ z = (pRotMatrix.a3 + pRotMatrix.c1) / s;
+ w = (pRotMatrix.c2 - pRotMatrix.b3) / s;
+ }
+ else if( pRotMatrix.b2 > pRotMatrix.c3)
+ {
+ // Column 1:
+ TReal s = std::sqrt( static_cast<TReal>(1.0) + pRotMatrix.b2 - pRotMatrix.a1 - pRotMatrix.c3) * static_cast<TReal>(2.0);
+ x = (pRotMatrix.b1 + pRotMatrix.a2) / s;
+ y = static_cast<TReal>(0.25) * s;
+ z = (pRotMatrix.c2 + pRotMatrix.b3) / s;
+ w = (pRotMatrix.a3 - pRotMatrix.c1) / s;
+ } else
+ {
+ // Column 2:
+ TReal s = std::sqrt( static_cast<TReal>(1.0) + pRotMatrix.c3 - pRotMatrix.a1 - pRotMatrix.b2) * static_cast<TReal>(2.0);
+ x = (pRotMatrix.a3 + pRotMatrix.c1) / s;
+ y = (pRotMatrix.c2 + pRotMatrix.b3) / s;
+ z = static_cast<TReal>(0.25) * s;
+ w = (pRotMatrix.b1 - pRotMatrix.a2) / s;
+ }
+}
+
+// ---------------------------------------------------------------------------
+// Construction from euler angles
+template<typename TReal>
+inline aiQuaterniont<TReal>::aiQuaterniont( TReal fPitch, TReal fYaw, TReal fRoll )
+{
+ const TReal fSinPitch(std::sin(fPitch*static_cast<TReal>(0.5)));
+ const TReal fCosPitch(std::cos(fPitch*static_cast<TReal>(0.5)));
+ const TReal fSinYaw(std::sin(fYaw*static_cast<TReal>(0.5)));
+ const TReal fCosYaw(std::cos(fYaw*static_cast<TReal>(0.5)));
+ const TReal fSinRoll(std::sin(fRoll*static_cast<TReal>(0.5)));
+ const TReal fCosRoll(std::cos(fRoll*static_cast<TReal>(0.5)));
+ const TReal fCosPitchCosYaw(fCosPitch*fCosYaw);
+ const TReal fSinPitchSinYaw(fSinPitch*fSinYaw);
+ x = fSinRoll * fCosPitchCosYaw - fCosRoll * fSinPitchSinYaw;
+ y = fCosRoll * fSinPitch * fCosYaw + fSinRoll * fCosPitch * fSinYaw;
+ z = fCosRoll * fCosPitch * fSinYaw - fSinRoll * fSinPitch * fCosYaw;
+ w = fCosRoll * fCosPitchCosYaw + fSinRoll * fSinPitchSinYaw;
+}
+
+// ---------------------------------------------------------------------------
+// Returns a matrix representation of the quaternion
+template<typename TReal>
+inline aiMatrix3x3t<TReal> aiQuaterniont<TReal>::GetMatrix() const
+{
+ aiMatrix3x3t<TReal> resMatrix;
+ resMatrix.a1 = static_cast<TReal>(1.0) - static_cast<TReal>(2.0) * (y * y + z * z);
+ resMatrix.a2 = static_cast<TReal>(2.0) * (x * y - z * w);
+ resMatrix.a3 = static_cast<TReal>(2.0) * (x * z + y * w);
+ resMatrix.b1 = static_cast<TReal>(2.0) * (x * y + z * w);
+ resMatrix.b2 = static_cast<TReal>(1.0) - static_cast<TReal>(2.0) * (x * x + z * z);
+ resMatrix.b3 = static_cast<TReal>(2.0) * (y * z - x * w);
+ resMatrix.c1 = static_cast<TReal>(2.0) * (x * z - y * w);
+ resMatrix.c2 = static_cast<TReal>(2.0) * (y * z + x * w);
+ resMatrix.c3 = static_cast<TReal>(1.0) - static_cast<TReal>(2.0) * (x * x + y * y);
+
+ return resMatrix;
+}
+
+// ---------------------------------------------------------------------------
+// Construction from an axis-angle pair
+template<typename TReal>
+inline aiQuaterniont<TReal>::aiQuaterniont( aiVector3t<TReal> axis, TReal angle)
+{
+ axis.Normalize();
+
+ const TReal sin_a = std::sin( angle / 2 );
+ const TReal cos_a = std::cos( angle / 2 );
+ x = axis.x * sin_a;
+ y = axis.y * sin_a;
+ z = axis.z * sin_a;
+ w = cos_a;
+}
+// ---------------------------------------------------------------------------
+// Construction from am existing, normalized quaternion
+template<typename TReal>
+inline aiQuaterniont<TReal>::aiQuaterniont( aiVector3t<TReal> normalized)
+{
+ x = normalized.x;
+ y = normalized.y;
+ z = normalized.z;
+
+ const TReal t = static_cast<TReal>(1.0) - (x*x) - (y*y) - (z*z);
+
+ if (t < static_cast<TReal>(0.0)) {
+ w = static_cast<TReal>(0.0);
+ }
+ else w = std::sqrt (t);
+}
+
+// ---------------------------------------------------------------------------
+// Performs a spherical interpolation between two quaternions
+// Implementation adopted from the gmtl project. All others I found on the net fail in some cases.
+// Congrats, gmtl!
+template<typename TReal>
+inline void aiQuaterniont<TReal>::Interpolate( aiQuaterniont& pOut, const aiQuaterniont& pStart, const aiQuaterniont& pEnd, TReal pFactor)
+{
+ // calc cosine theta
+ TReal cosom = pStart.x * pEnd.x + pStart.y * pEnd.y + pStart.z * pEnd.z + pStart.w * pEnd.w;
+
+ // adjust signs (if necessary)
+ aiQuaterniont end = pEnd;
+ if( cosom < static_cast<TReal>(0.0))
+ {
+ cosom = -cosom;
+ end.x = -end.x; // Reverse all signs
+ end.y = -end.y;
+ end.z = -end.z;
+ end.w = -end.w;
+ }
+
+ // Calculate coefficients
+ TReal sclp, sclq;
+ if( (static_cast<TReal>(1.0) - cosom) > static_cast<TReal>(0.0001)) // 0.0001 -> some epsillon
+ {
+ // Standard case (slerp)
+ TReal omega, sinom;
+ omega = std::acos( cosom); // extract theta from dot product's cos theta
+ sinom = std::sin( omega);
+ sclp = std::sin( (static_cast<TReal>(1.0) - pFactor) * omega) / sinom;
+ sclq = std::sin( pFactor * omega) / sinom;
+ } else
+ {
+ // Very close, do linear interp (because it's faster)
+ sclp = static_cast<TReal>(1.0) - pFactor;
+ sclq = pFactor;
+ }
+
+ pOut.x = sclp * pStart.x + sclq * end.x;
+ pOut.y = sclp * pStart.y + sclq * end.y;
+ pOut.z = sclp * pStart.z + sclq * end.z;
+ pOut.w = sclp * pStart.w + sclq * end.w;
+}
+
+// ---------------------------------------------------------------------------
+template<typename TReal>
+inline aiQuaterniont<TReal>& aiQuaterniont<TReal>::Normalize()
+{
+ // compute the magnitude and divide through it
+ const TReal mag = std::sqrt(x*x + y*y + z*z + w*w);
+ if (mag)
+ {
+ const TReal invMag = static_cast<TReal>(1.0)/mag;
+ x *= invMag;
+ y *= invMag;
+ z *= invMag;
+ w *= invMag;
+ }
+ return *this;
+}
+
+// ---------------------------------------------------------------------------
+template<typename TReal>
+inline aiQuaterniont<TReal> aiQuaterniont<TReal>::operator* (const aiQuaterniont& t) const
+{
+ return aiQuaterniont(w*t.w - x*t.x - y*t.y - z*t.z,
+ w*t.x + x*t.w + y*t.z - z*t.y,
+ w*t.y + y*t.w + z*t.x - x*t.z,
+ w*t.z + z*t.w + x*t.y - y*t.x);
+}
+
+// ---------------------------------------------------------------------------
+template<typename TReal>
+inline aiQuaterniont<TReal>& aiQuaterniont<TReal>::Conjugate ()
+{
+ x = -x;
+ y = -y;
+ z = -z;
+ return *this;
+}
+
+// ---------------------------------------------------------------------------
+template<typename TReal>
+inline aiVector3t<TReal> aiQuaterniont<TReal>::Rotate (const aiVector3t<TReal>& v)
+{
+ aiQuaterniont q2(0.f,v.x,v.y,v.z), q = *this, qinv = q;
+ qinv.Conjugate();
+
+ q = q*q2*qinv;
+ return aiVector3t<TReal>(q.x,q.y,q.z);
+}
+
+#endif
+#endif // AI_QUATERNION_INL_INC
diff --git a/thirdparty/assimp/include/assimp/scene.h b/thirdparty/assimp/include/assimp/scene.h
new file mode 100644
index 0000000000..de0239702d
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/scene.h
@@ -0,0 +1,416 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file scene.h
+ * @brief Defines the data structures in which the imported scene is returned.
+ */
+#pragma once
+#ifndef AI_SCENE_H_INC
+#define AI_SCENE_H_INC
+
+#include "types.h"
+#include "texture.h"
+#include "mesh.h"
+#include "light.h"
+#include "camera.h"
+#include "material.h"
+#include "anim.h"
+#include "metadata.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wattributes"
+#endif
+
+// -------------------------------------------------------------------------------
+/**
+ * A node in the imported hierarchy.
+ *
+ * Each node has name, a parent node (except for the root node),
+ * a transformation relative to its parent and possibly several child nodes.
+ * Simple file formats don't support hierarchical structures - for these formats
+ * the imported scene does consist of only a single root node without children.
+ */
+// -------------------------------------------------------------------------------
+struct ASSIMP_API aiNode
+{
+ /** The name of the node.
+ *
+ * The name might be empty (length of zero) but all nodes which
+ * need to be referenced by either bones or animations are named.
+ * Multiple nodes may have the same name, except for nodes which are referenced
+ * by bones (see #aiBone and #aiMesh::mBones). Their names *must* be unique.
+ *
+ * Cameras and lights reference a specific node by name - if there
+ * are multiple nodes with this name, they are assigned to each of them.
+ * <br>
+ * There are no limitations with regard to the characters contained in
+ * the name string as it is usually taken directly from the source file.
+ *
+ * Implementations should be able to handle tokens such as whitespace, tabs,
+ * line feeds, quotation marks, ampersands etc.
+ *
+ * Sometimes assimp introduces new nodes not present in the source file
+ * into the hierarchy (usually out of necessity because sometimes the
+ * source hierarchy format is simply not compatible). Their names are
+ * surrounded by @verbatim <> @endverbatim e.g.
+ * @verbatim<DummyRootNode> @endverbatim.
+ */
+ C_STRUCT aiString mName;
+
+ /** The transformation relative to the node's parent. */
+ C_STRUCT aiMatrix4x4 mTransformation;
+
+ /** Parent node. NULL if this node is the root node. */
+ C_STRUCT aiNode* mParent;
+
+ /** The number of child nodes of this node. */
+ unsigned int mNumChildren;
+
+ /** The child nodes of this node. NULL if mNumChildren is 0. */
+ C_STRUCT aiNode** mChildren;
+
+ /** The number of meshes of this node. */
+ unsigned int mNumMeshes;
+
+ /** The meshes of this node. Each entry is an index into the
+ * mesh list of the #aiScene.
+ */
+ unsigned int* mMeshes;
+
+ /** Metadata associated with this node or NULL if there is no metadata.
+ * Whether any metadata is generated depends on the source file format. See the
+ * @link importer_notes @endlink page for more information on every source file
+ * format. Importers that don't document any metadata don't write any.
+ */
+ C_STRUCT aiMetadata* mMetaData;
+
+#ifdef __cplusplus
+ /** Constructor */
+ aiNode();
+
+ /** Construction from a specific name */
+ explicit aiNode(const std::string& name);
+
+ /** Destructor */
+ ~aiNode();
+
+ /** Searches for a node with a specific name, beginning at this
+ * nodes. Normally you will call this method on the root node
+ * of the scene.
+ *
+ * @param name Name to search for
+ * @return NULL or a valid Node if the search was successful.
+ */
+ inline
+ const aiNode* FindNode(const aiString& name) const {
+ return FindNode(name.data);
+ }
+
+ inline
+ aiNode* FindNode(const aiString& name) {
+ return FindNode(name.data);
+ }
+
+ const aiNode* FindNode(const char* name) const;
+
+ aiNode* FindNode(const char* name);
+
+ /**
+ * @brief Will add new children.
+ * @param numChildren Number of children to add.
+ * @param children The array with pointers showing to the children.
+ */
+ void addChildren(unsigned int numChildren, aiNode **children);
+#endif // __cplusplus
+};
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
+// -------------------------------------------------------------------------------
+/**
+ * Specifies that the scene data structure that was imported is not complete.
+ * This flag bypasses some internal validations and allows the import
+ * of animation skeletons, material libraries or camera animation paths
+ * using Assimp. Most applications won't support such data.
+ */
+#define AI_SCENE_FLAGS_INCOMPLETE 0x1
+
+/**
+ * This flag is set by the validation postprocess-step (aiPostProcess_ValidateDS)
+ * if the validation is successful. In a validated scene you can be sure that
+ * any cross references in the data structure (e.g. vertex indices) are valid.
+ */
+#define AI_SCENE_FLAGS_VALIDATED 0x2
+
+/**
+ * This flag is set by the validation postprocess-step (aiPostProcess_ValidateDS)
+ * if the validation is successful but some issues have been found.
+ * This can for example mean that a texture that does not exist is referenced
+ * by a material or that the bone weights for a vertex don't sum to 1.0 ... .
+ * In most cases you should still be able to use the import. This flag could
+ * be useful for applications which don't capture Assimp's log output.
+ */
+#define AI_SCENE_FLAGS_VALIDATION_WARNING 0x4
+
+/**
+ * This flag is currently only set by the aiProcess_JoinIdenticalVertices step.
+ * It indicates that the vertices of the output meshes aren't in the internal
+ * verbose format anymore. In the verbose format all vertices are unique,
+ * no vertex is ever referenced by more than one face.
+ */
+#define AI_SCENE_FLAGS_NON_VERBOSE_FORMAT 0x8
+
+ /**
+ * Denotes pure height-map terrain data. Pure terrains usually consist of quads,
+ * sometimes triangles, in a regular grid. The x,y coordinates of all vertex
+ * positions refer to the x,y coordinates on the terrain height map, the z-axis
+ * stores the elevation at a specific point.
+ *
+ * TER (Terragen) and HMP (3D Game Studio) are height map formats.
+ * @note Assimp is probably not the best choice for loading *huge* terrains -
+ * fully triangulated data takes extremely much free store and should be avoided
+ * as long as possible (typically you'll do the triangulation when you actually
+ * need to render it).
+ */
+#define AI_SCENE_FLAGS_TERRAIN 0x10
+
+ /**
+ * Specifies that the scene data can be shared between structures. For example:
+ * one vertex in few faces. \ref AI_SCENE_FLAGS_NON_VERBOSE_FORMAT can not be
+ * used for this because \ref AI_SCENE_FLAGS_NON_VERBOSE_FORMAT has internal
+ * meaning about postprocessing steps.
+ */
+#define AI_SCENE_FLAGS_ALLOW_SHARED 0x20
+
+// -------------------------------------------------------------------------------
+/** The root structure of the imported data.
+ *
+ * Everything that was imported from the given file can be accessed from here.
+ * Objects of this class are generally maintained and owned by Assimp, not
+ * by the caller. You shouldn't want to instance it, nor should you ever try to
+ * delete a given scene on your own.
+ */
+// -------------------------------------------------------------------------------
+struct aiScene
+{
+ /** Any combination of the AI_SCENE_FLAGS_XXX flags. By default
+ * this value is 0, no flags are set. Most applications will
+ * want to reject all scenes with the AI_SCENE_FLAGS_INCOMPLETE
+ * bit set.
+ */
+ unsigned int mFlags;
+
+ /** The root node of the hierarchy.
+ *
+ * There will always be at least the root node if the import
+ * was successful (and no special flags have been set).
+ * Presence of further nodes depends on the format and content
+ * of the imported file.
+ */
+ C_STRUCT aiNode* mRootNode;
+
+ /** The number of meshes in the scene. */
+ unsigned int mNumMeshes;
+
+ /** The array of meshes.
+ *
+ * Use the indices given in the aiNode structure to access
+ * this array. The array is mNumMeshes in size. If the
+ * AI_SCENE_FLAGS_INCOMPLETE flag is not set there will always
+ * be at least ONE material.
+ */
+ C_STRUCT aiMesh** mMeshes;
+
+ /** The number of materials in the scene. */
+ unsigned int mNumMaterials;
+
+ /** The array of materials.
+ *
+ * Use the index given in each aiMesh structure to access this
+ * array. The array is mNumMaterials in size. If the
+ * AI_SCENE_FLAGS_INCOMPLETE flag is not set there will always
+ * be at least ONE material.
+ */
+ C_STRUCT aiMaterial** mMaterials;
+
+ /** The number of animations in the scene. */
+ unsigned int mNumAnimations;
+
+ /** The array of animations.
+ *
+ * All animations imported from the given file are listed here.
+ * The array is mNumAnimations in size.
+ */
+ C_STRUCT aiAnimation** mAnimations;
+
+ /** The number of textures embedded into the file */
+ unsigned int mNumTextures;
+
+ /** The array of embedded textures.
+ *
+ * Not many file formats embed their textures into the file.
+ * An example is Quake's MDL format (which is also used by
+ * some GameStudio versions)
+ */
+ C_STRUCT aiTexture** mTextures;
+
+ /** The number of light sources in the scene. Light sources
+ * are fully optional, in most cases this attribute will be 0
+ */
+ unsigned int mNumLights;
+
+ /** The array of light sources.
+ *
+ * All light sources imported from the given file are
+ * listed here. The array is mNumLights in size.
+ */
+ C_STRUCT aiLight** mLights;
+
+ /** The number of cameras in the scene. Cameras
+ * are fully optional, in most cases this attribute will be 0
+ */
+ unsigned int mNumCameras;
+
+ /** The array of cameras.
+ *
+ * All cameras imported from the given file are listed here.
+ * The array is mNumCameras in size. The first camera in the
+ * array (if existing) is the default camera view into
+ * the scene.
+ */
+ C_STRUCT aiCamera** mCameras;
+
+ /**
+ * @brief The global metadata assigned to the scene itself.
+ *
+ * This data contains global metadata which belongs to the scene like
+ * unit-conversions, versions, vendors or other model-specific data. This
+ * can be used to store format-specific metadata as well.
+ */
+ C_STRUCT aiMetadata* mMetaData;
+
+
+#ifdef __cplusplus
+
+ //! Default constructor - set everything to 0/NULL
+ ASSIMP_API aiScene();
+
+ //! Destructor
+ ASSIMP_API ~aiScene();
+
+ //! Check whether the scene contains meshes
+ //! Unless no special scene flags are set this will always be true.
+ inline bool HasMeshes() const {
+ return mMeshes != NULL && mNumMeshes > 0;
+ }
+
+ //! Check whether the scene contains materials
+ //! Unless no special scene flags are set this will always be true.
+ inline bool HasMaterials() const {
+ return mMaterials != NULL && mNumMaterials > 0;
+ }
+
+ //! Check whether the scene contains lights
+ inline bool HasLights() const {
+ return mLights != NULL && mNumLights > 0;
+ }
+
+ //! Check whether the scene contains textures
+ inline bool HasTextures() const {
+ return mTextures != NULL && mNumTextures > 0;
+ }
+
+ //! Check whether the scene contains cameras
+ inline bool HasCameras() const {
+ return mCameras != NULL && mNumCameras > 0;
+ }
+
+ //! Check whether the scene contains animations
+ inline bool HasAnimations() const {
+ return mAnimations != NULL && mNumAnimations > 0;
+ }
+
+ //! Returns a short filename from a full path
+ static const char* GetShortFilename(const char* filename) {
+ const char* lastSlash = strrchr(filename, '/');
+ if (lastSlash == nullptr) {
+ lastSlash = strrchr(filename, '\\');
+ }
+ const char* shortFilename = lastSlash != nullptr ? lastSlash + 1 : filename;
+ return shortFilename;
+ }
+
+ //! Returns an embedded texture
+ const aiTexture* GetEmbeddedTexture(const char* filename) const {
+ const char* shortFilename = GetShortFilename(filename);
+ for (unsigned int i = 0; i < mNumTextures; i++) {
+ const char* shortTextureFilename = GetShortFilename(mTextures[i]->mFilename.C_Str());
+ if (strcmp(shortTextureFilename, shortFilename) == 0) {
+ return mTextures[i];
+ }
+ }
+ return nullptr;
+ }
+#endif // __cplusplus
+
+ /** Internal data, do not touch */
+#ifdef __cplusplus
+ void* mPrivate;
+#else
+ char* mPrivate;
+#endif
+
+};
+
+#ifdef __cplusplus
+} //! namespace Assimp
+#endif
+
+#endif // AI_SCENE_H_INC
diff --git a/thirdparty/assimp/include/assimp/texture.h b/thirdparty/assimp/include/assimp/texture.h
new file mode 100644
index 0000000000..dc6cbef65c
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/texture.h
@@ -0,0 +1,227 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file texture.h
+ * @brief Defines texture helper structures for the library
+ *
+ * Used for file formats which embed their textures into the model file.
+ * Supported are both normal textures, which are stored as uncompressed
+ * pixels, and "compressed" textures, which are stored in a file format
+ * such as PNG or TGA.
+ */
+#pragma once
+#ifndef AI_TEXTURE_H_INC
+#define AI_TEXTURE_H_INC
+
+#include "types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+// --------------------------------------------------------------------------------
+
+/** \def AI_EMBEDDED_TEXNAME_PREFIX
+ * \ref AI_MAKE_EMBEDDED_TEXNAME
+ */
+#ifndef AI_EMBEDDED_TEXNAME_PREFIX
+# define AI_EMBEDDED_TEXNAME_PREFIX "*"
+#endif
+
+/** @def AI_MAKE_EMBEDDED_TEXNAME
+ * Used to build the reserved path name used by the material system to
+ * reference textures that are embedded into their corresponding
+ * model files. The parameter specifies the index of the texture
+ * (zero-based, in the aiScene::mTextures array)
+ */
+#if (!defined AI_MAKE_EMBEDDED_TEXNAME)
+# define AI_MAKE_EMBEDDED_TEXNAME(_n_) AI_EMBEDDED_TEXNAME_PREFIX # _n_
+#endif
+
+
+#include "./Compiler/pushpack1.h"
+
+// --------------------------------------------------------------------------------
+/** @brief Helper structure to represent a texel in a ARGB8888 format
+*
+* Used by aiTexture.
+*/
+struct aiTexel
+{
+ unsigned char b,g,r,a;
+
+#ifdef __cplusplus
+ //! Comparison operator
+ bool operator== (const aiTexel& other) const
+ {
+ return b == other.b && r == other.r &&
+ g == other.g && a == other.a;
+ }
+
+ //! Inverse comparison operator
+ bool operator!= (const aiTexel& other) const
+ {
+ return b != other.b || r != other.r ||
+ g != other.g || a != other.a;
+ }
+
+ //! Conversion to a floating-point 4d color
+ operator aiColor4D() const
+ {
+ return aiColor4D(r/255.f,g/255.f,b/255.f,a/255.f);
+ }
+#endif // __cplusplus
+
+} PACK_STRUCT;
+
+#include "./Compiler/poppack1.h"
+
+#define HINTMAXTEXTURELEN 9
+
+// --------------------------------------------------------------------------------
+/** Helper structure to describe an embedded texture
+ *
+ * Normally textures are contained in external files but some file formats embed
+ * them directly in the model file. There are two types of embedded textures:
+ * 1. Uncompressed textures. The color data is given in an uncompressed format.
+ * 2. Compressed textures stored in a file format like png or jpg. The raw file
+ * bytes are given so the application must utilize an image decoder (e.g. DevIL) to
+ * get access to the actual color data.
+ *
+ * Embedded textures are referenced from materials using strings like "*0", "*1", etc.
+ * as the texture paths (a single asterisk character followed by the
+ * zero-based index of the texture in the aiScene::mTextures array).
+ */
+struct aiTexture {
+ /** Width of the texture, in pixels
+ *
+ * If mHeight is zero the texture is compressed in a format
+ * like JPEG. In this case mWidth specifies the size of the
+ * memory area pcData is pointing to, in bytes.
+ */
+ unsigned int mWidth;
+
+ /** Height of the texture, in pixels
+ *
+ * If this value is zero, pcData points to an compressed texture
+ * in any format (e.g. JPEG).
+ */
+ unsigned int mHeight;
+
+ /** A hint from the loader to make it easier for applications
+ * to determine the type of embedded textures.
+ *
+ * If mHeight != 0 this member is show how data is packed. Hint will consist of
+ * two parts: channel order and channel bitness (count of the bits for every
+ * color channel). For simple parsing by the viewer it's better to not omit
+ * absent color channel and just use 0 for bitness. For example:
+ * 1. Image contain RGBA and 8 bit per channel, achFormatHint == "rgba8888";
+ * 2. Image contain ARGB and 8 bit per channel, achFormatHint == "argb8888";
+ * 3. Image contain RGB and 5 bit for R and B channels and 6 bit for G channel, achFormatHint == "rgba5650";
+ * 4. One color image with B channel and 1 bit for it, achFormatHint == "rgba0010";
+ * If mHeight == 0 then achFormatHint is set set to '\\0\\0\\0\\0' if the loader has no additional
+ * information about the texture file format used OR the
+ * file extension of the format without a trailing dot. If there
+ * are multiple file extensions for a format, the shortest
+ * extension is chosen (JPEG maps to 'jpg', not to 'jpeg').
+ * E.g. 'dds\\0', 'pcx\\0', 'jpg\\0'. All characters are lower-case.
+ * The fourth character will always be '\\0'.
+ */
+ char achFormatHint[ HINTMAXTEXTURELEN ];// 8 for string + 1 for terminator.
+
+ /** Data of the texture.
+ *
+ * Points to an array of mWidth * mHeight aiTexel's.
+ * The format of the texture data is always ARGB8888 to
+ * make the implementation for user of the library as easy
+ * as possible. If mHeight = 0 this is a pointer to a memory
+ * buffer of size mWidth containing the compressed texture
+ * data. Good luck, have fun!
+ */
+ C_STRUCT aiTexel* pcData;
+
+ /** Texture original filename
+ *
+ * Used to get the texture reference
+ */
+ C_STRUCT aiString mFilename;
+
+#ifdef __cplusplus
+
+ //! For compressed textures (mHeight == 0): compare the
+ //! format hint against a given string.
+ //! @param s Input string. 3 characters are maximally processed.
+ //! Example values: "jpg", "png"
+ //! @return true if the given string matches the format hint
+ bool CheckFormat(const char* s) const {
+ if (nullptr == s) {
+ return false;
+ }
+
+ return (0 == ::strncmp(achFormatHint, s, sizeof(achFormatHint)));
+ }
+
+ // Construction
+ aiTexture() AI_NO_EXCEPT
+ : mWidth(0)
+ , mHeight(0)
+ , pcData(nullptr)
+ , mFilename() {
+ achFormatHint[0] = achFormatHint[1] = 0;
+ achFormatHint[2] = achFormatHint[3] = 0;
+ }
+
+ // Destruction
+ ~aiTexture () {
+ delete[] pcData;
+ }
+#endif
+};
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // AI_TEXTURE_H_INC
diff --git a/thirdparty/assimp/include/assimp/types.h b/thirdparty/assimp/include/assimp/types.h
new file mode 100644
index 0000000000..748e4851f3
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/types.h
@@ -0,0 +1,529 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file types.h
+ * Basic data types and primitives, such as vectors or colors.
+ */
+#pragma once
+#ifndef AI_TYPES_H_INC
+#define AI_TYPES_H_INC
+
+// Some runtime headers
+#include <sys/types.h>
+#include <stddef.h>
+#include <string.h>
+#include <limits.h>
+
+// Our compile configuration
+#include "defs.h"
+
+// Some types moved to separate header due to size of operators
+#include "vector3.h"
+#include "vector2.h"
+#include "color4.h"
+#include "matrix3x3.h"
+#include "matrix4x4.h"
+#include "quaternion.h"
+
+#ifdef __cplusplus
+#include <cstring>
+#include <new> // for std::nothrow_t
+#include <string> // for aiString::Set(const std::string&)
+
+namespace Assimp {
+ //! @cond never
+namespace Intern {
+ // --------------------------------------------------------------------
+ /** @brief Internal helper class to utilize our internal new/delete
+ * routines for allocating object of this and derived classes.
+ *
+ * By doing this you can safely share class objects between Assimp
+ * and the application - it works even over DLL boundaries. A good
+ * example is the #IOSystem where the application allocates its custom
+ * #IOSystem, then calls #Importer::SetIOSystem(). When the Importer
+ * destructs, Assimp calls operator delete on the stored #IOSystem.
+ * If it lies on a different heap than Assimp is working with,
+ * the application is determined to crash.
+ */
+ // --------------------------------------------------------------------
+#ifndef SWIG
+ struct ASSIMP_API AllocateFromAssimpHeap {
+ // http://www.gotw.ca/publications/mill15.htm
+
+ // new/delete overload
+ void *operator new ( size_t num_bytes) /* throw( std::bad_alloc ) */;
+ void *operator new ( size_t num_bytes, const std::nothrow_t& ) throw();
+ void operator delete ( void* data);
+
+ // array new/delete overload
+ void *operator new[] ( size_t num_bytes) /* throw( std::bad_alloc ) */;
+ void *operator new[] ( size_t num_bytes, const std::nothrow_t& ) throw();
+ void operator delete[] ( void* data);
+
+ }; // struct AllocateFromAssimpHeap
+#endif
+} // namespace Intern
+ //! @endcond
+} // namespace Assimp
+
+extern "C" {
+#endif
+
+/** Maximum dimension for strings, ASSIMP strings are zero terminated. */
+#ifdef __cplusplus
+ static const size_t MAXLEN = 1024;
+#else
+# define MAXLEN 1024
+#endif
+
+// ----------------------------------------------------------------------------------
+/** Represents a plane in a three-dimensional, euclidean space
+*/
+struct aiPlane {
+#ifdef __cplusplus
+ aiPlane () AI_NO_EXCEPT : a(0.f), b(0.f), c(0.f), d(0.f) {}
+ aiPlane (ai_real _a, ai_real _b, ai_real _c, ai_real _d)
+ : a(_a), b(_b), c(_c), d(_d) {}
+
+ aiPlane (const aiPlane& o) : a(o.a), b(o.b), c(o.c), d(o.d) {}
+
+#endif // !__cplusplus
+
+ //! Plane equation
+ ai_real a,b,c,d;
+}; // !struct aiPlane
+
+// ----------------------------------------------------------------------------------
+/** Represents a ray
+*/
+struct aiRay {
+#ifdef __cplusplus
+ aiRay () AI_NO_EXCEPT {}
+ aiRay (const aiVector3D& _pos, const aiVector3D& _dir)
+ : pos(_pos), dir(_dir) {}
+
+ aiRay (const aiRay& o) : pos (o.pos), dir (o.dir) {}
+
+#endif // !__cplusplus
+
+ //! Position and direction of the ray
+ C_STRUCT aiVector3D pos, dir;
+}; // !struct aiRay
+
+// ----------------------------------------------------------------------------------
+/** Represents a color in Red-Green-Blue space.
+*/
+struct aiColor3D
+{
+#ifdef __cplusplus
+ aiColor3D () AI_NO_EXCEPT : r(0.0f), g(0.0f), b(0.0f) {}
+ aiColor3D (ai_real _r, ai_real _g, ai_real _b) : r(_r), g(_g), b(_b) {}
+ explicit aiColor3D (ai_real _r) : r(_r), g(_r), b(_r) {}
+ aiColor3D (const aiColor3D& o) : r(o.r), g(o.g), b(o.b) {}
+
+ /** Component-wise comparison */
+ // TODO: add epsilon?
+ bool operator == (const aiColor3D& other) const
+ {return r == other.r && g == other.g && b == other.b;}
+
+ /** Component-wise inverse comparison */
+ // TODO: add epsilon?
+ bool operator != (const aiColor3D& other) const
+ {return r != other.r || g != other.g || b != other.b;}
+
+ /** Component-wise comparison */
+ // TODO: add epsilon?
+ bool operator < (const aiColor3D& other) const {
+ return r < other.r || ( r == other.r && (g < other.g || (g == other.g && b < other.b ) ) );
+ }
+
+ /** Component-wise addition */
+ aiColor3D operator+(const aiColor3D& c) const {
+ return aiColor3D(r+c.r,g+c.g,b+c.b);
+ }
+
+ /** Component-wise subtraction */
+ aiColor3D operator-(const aiColor3D& c) const {
+ return aiColor3D(r-c.r,g-c.g,b-c.b);
+ }
+
+ /** Component-wise multiplication */
+ aiColor3D operator*(const aiColor3D& c) const {
+ return aiColor3D(r*c.r,g*c.g,b*c.b);
+ }
+
+ /** Multiply with a scalar */
+ aiColor3D operator*(ai_real f) const {
+ return aiColor3D(r*f,g*f,b*f);
+ }
+
+ /** Access a specific color component */
+ ai_real operator[](unsigned int i) const {
+ return *(&r + i);
+ }
+
+ /** Access a specific color component */
+ ai_real& operator[](unsigned int i) {
+ if ( 0 == i ) {
+ return r;
+ } else if ( 1 == i ) {
+ return g;
+ } else if ( 2 == i ) {
+ return b;
+ }
+ return r;
+ }
+
+ /** Check whether a color is black */
+ bool IsBlack() const {
+ static const ai_real epsilon = ai_real(10e-3);
+ return std::fabs( r ) < epsilon && std::fabs( g ) < epsilon && std::fabs( b ) < epsilon;
+ }
+
+#endif // !__cplusplus
+
+ //! Red, green and blue color values
+ ai_real r, g, b;
+}; // !struct aiColor3D
+
+// ----------------------------------------------------------------------------------
+/** Represents an UTF-8 string, zero byte terminated.
+ *
+ * The character set of an aiString is explicitly defined to be UTF-8. This Unicode
+ * transformation was chosen in the belief that most strings in 3d files are limited
+ * to ASCII, thus the character set needed to be strictly ASCII compatible.
+ *
+ * Most text file loaders provide proper Unicode input file handling, special unicode
+ * characters are correctly transcoded to UTF8 and are kept throughout the libraries'
+ * import pipeline.
+ *
+ * For most applications, it will be absolutely sufficient to interpret the
+ * aiString as ASCII data and work with it as one would work with a plain char*.
+ * Windows users in need of proper support for i.e asian characters can use the
+ * MultiByteToWideChar(), WideCharToMultiByte() WinAPI functionality to convert the
+ * UTF-8 strings to their working character set (i.e. MBCS, WideChar).
+ *
+ * We use this representation instead of std::string to be C-compatible. The
+ * (binary) length of such a string is limited to MAXLEN characters (including the
+ * the terminating zero).
+*/
+struct aiString
+{
+#ifdef __cplusplus
+ /** Default constructor, the string is set to have zero length */
+ aiString() AI_NO_EXCEPT
+ : length( 0 ) {
+ data[0] = '\0';
+
+#ifdef ASSIMP_BUILD_DEBUG
+ // Debug build: overwrite the string on its full length with ESC (27)
+ memset(data+1,27,MAXLEN-1);
+#endif
+ }
+
+ /** Copy constructor */
+ aiString(const aiString& rOther) :
+ length(rOther.length)
+ {
+ // Crop the string to the maximum length
+ length = length>=MAXLEN?MAXLEN-1:length;
+ memcpy( data, rOther.data, length);
+ data[length] = '\0';
+ }
+
+ /** Constructor from std::string */
+ explicit aiString(const std::string& pString) :
+ length(pString.length())
+ {
+ length = length>=MAXLEN?MAXLEN-1:length;
+ memcpy( data, pString.c_str(), length);
+ data[length] = '\0';
+ }
+
+ /** Copy a std::string to the aiString */
+ void Set( const std::string& pString) {
+ if( pString.length() > MAXLEN - 1) {
+ return;
+ }
+ length = pString.length();
+ memcpy( data, pString.c_str(), length);
+ data[length] = 0;
+ }
+
+ /** Copy a const char* to the aiString */
+ void Set( const char* sz) {
+ const size_t len = ::strlen(sz);
+ if( len > MAXLEN - 1) {
+ return;
+ }
+ length = len;
+ memcpy( data, sz, len);
+ data[len] = 0;
+ }
+
+
+ /** Assignment operator */
+ aiString& operator = (const aiString &rOther) {
+ if (this == &rOther) {
+ return *this;
+ }
+
+ length = rOther.length;;
+ memcpy( data, rOther.data, length);
+ data[length] = '\0';
+ return *this;
+ }
+
+
+ /** Assign a const char* to the string */
+ aiString& operator = (const char* sz) {
+ Set(sz);
+ return *this;
+ }
+
+ /** Assign a cstd::string to the string */
+ aiString& operator = ( const std::string& pString) {
+ Set(pString);
+ return *this;
+ }
+
+ /** Comparison operator */
+ bool operator==(const aiString& other) const {
+ return (length == other.length && 0 == memcmp(data,other.data,length));
+ }
+
+ /** Inverse comparison operator */
+ bool operator!=(const aiString& other) const {
+ return (length != other.length || 0 != memcmp(data,other.data,length));
+ }
+
+ /** Append a string to the string */
+ void Append (const char* app) {
+ const size_t len = ::strlen(app);
+ if (!len) {
+ return;
+ }
+ if (length + len >= MAXLEN) {
+ return;
+ }
+
+ memcpy(&data[length],app,len+1);
+ length += len;
+ }
+
+ /** Clear the string - reset its length to zero */
+ void Clear () {
+ length = 0;
+ data[0] = '\0';
+
+#ifdef ASSIMP_BUILD_DEBUG
+ // Debug build: overwrite the string on its full length with ESC (27)
+ memset(data+1,27,MAXLEN-1);
+#endif
+ }
+
+ /** Returns a pointer to the underlying zero-terminated array of characters */
+ const char* C_Str() const {
+ return data;
+ }
+
+#endif // !__cplusplus
+
+ /** Binary length of the string excluding the terminal 0. This is NOT the
+ * logical length of strings containing UTF-8 multi-byte sequences! It's
+ * the number of bytes from the beginning of the string to its end.*/
+ size_t length;
+
+ /** String buffer. Size limit is MAXLEN */
+ char data[MAXLEN];
+} ; // !struct aiString
+
+
+// ----------------------------------------------------------------------------------
+/** Standard return type for some library functions.
+ * Rarely used, and if, mostly in the C API.
+ */
+typedef enum aiReturn
+{
+ /** Indicates that a function was successful */
+ aiReturn_SUCCESS = 0x0,
+
+ /** Indicates that a function failed */
+ aiReturn_FAILURE = -0x1,
+
+ /** Indicates that not enough memory was available
+ * to perform the requested operation
+ */
+ aiReturn_OUTOFMEMORY = -0x3,
+
+ /** @cond never
+ * Force 32-bit size enum
+ */
+ _AI_ENFORCE_ENUM_SIZE = 0x7fffffff
+
+ /// @endcond
+} aiReturn; // !enum aiReturn
+
+// just for backwards compatibility, don't use these constants anymore
+#define AI_SUCCESS aiReturn_SUCCESS
+#define AI_FAILURE aiReturn_FAILURE
+#define AI_OUTOFMEMORY aiReturn_OUTOFMEMORY
+
+// ----------------------------------------------------------------------------------
+/** Seek origins (for the virtual file system API).
+ * Much cooler than using SEEK_SET, SEEK_CUR or SEEK_END.
+ */
+enum aiOrigin
+{
+ /** Beginning of the file */
+ aiOrigin_SET = 0x0,
+
+ /** Current position of the file pointer */
+ aiOrigin_CUR = 0x1,
+
+ /** End of the file, offsets must be negative */
+ aiOrigin_END = 0x2,
+
+ /** @cond never
+ * Force 32-bit size enum
+ */
+ _AI_ORIGIN_ENFORCE_ENUM_SIZE = 0x7fffffff
+
+ /// @endcond
+}; // !enum aiOrigin
+
+// ----------------------------------------------------------------------------------
+/** @brief Enumerates predefined log streaming destinations.
+ * Logging to these streams can be enabled with a single call to
+ * #LogStream::createDefaultStream.
+ */
+enum aiDefaultLogStream
+{
+ /** Stream the log to a file */
+ aiDefaultLogStream_FILE = 0x1,
+
+ /** Stream the log to std::cout */
+ aiDefaultLogStream_STDOUT = 0x2,
+
+ /** Stream the log to std::cerr */
+ aiDefaultLogStream_STDERR = 0x4,
+
+ /** MSVC only: Stream the log the the debugger
+ * (this relies on OutputDebugString from the Win32 SDK)
+ */
+ aiDefaultLogStream_DEBUGGER = 0x8,
+
+ /** @cond never
+ * Force 32-bit size enum
+ */
+ _AI_DLS_ENFORCE_ENUM_SIZE = 0x7fffffff
+ /// @endcond
+}; // !enum aiDefaultLogStream
+
+// just for backwards compatibility, don't use these constants anymore
+#define DLS_FILE aiDefaultLogStream_FILE
+#define DLS_STDOUT aiDefaultLogStream_STDOUT
+#define DLS_STDERR aiDefaultLogStream_STDERR
+#define DLS_DEBUGGER aiDefaultLogStream_DEBUGGER
+
+// ----------------------------------------------------------------------------------
+/** Stores the memory requirements for different components (e.g. meshes, materials,
+ * animations) of an import. All sizes are in bytes.
+ * @see Importer::GetMemoryRequirements()
+*/
+struct aiMemoryInfo
+{
+#ifdef __cplusplus
+
+ /** Default constructor */
+ aiMemoryInfo() AI_NO_EXCEPT
+ : textures (0)
+ , materials (0)
+ , meshes (0)
+ , nodes (0)
+ , animations (0)
+ , cameras (0)
+ , lights (0)
+ , total (0)
+ {}
+
+#endif
+
+ /** Storage allocated for texture data */
+ unsigned int textures;
+
+ /** Storage allocated for material data */
+ unsigned int materials;
+
+ /** Storage allocated for mesh data */
+ unsigned int meshes;
+
+ /** Storage allocated for node data */
+ unsigned int nodes;
+
+ /** Storage allocated for animation data */
+ unsigned int animations;
+
+ /** Storage allocated for camera data */
+ unsigned int cameras;
+
+ /** Storage allocated for light data */
+ unsigned int lights;
+
+ /** Total storage allocated for the full import. */
+ unsigned int total;
+}; // !struct aiMemoryInfo
+
+#ifdef __cplusplus
+}
+#endif //! __cplusplus
+
+// Include implementation files
+#include "vector2.inl"
+#include "vector3.inl"
+#include "color4.inl"
+#include "quaternion.inl"
+#include "matrix3x3.inl"
+#include "matrix4x4.inl"
+
+#endif // AI_TYPES_H_INC
diff --git a/thirdparty/assimp/include/assimp/vector2.h b/thirdparty/assimp/include/assimp/vector2.h
new file mode 100644
index 0000000000..d5ef001542
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/vector2.h
@@ -0,0 +1,107 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+/** @file vector2.h
+ * @brief 2D vector structure, including operators when compiling in C++
+ */
+#pragma once
+#ifndef AI_VECTOR2D_H_INC
+#define AI_VECTOR2D_H_INC
+
+#ifdef __cplusplus
+# include <cmath>
+#else
+# include <math.h>
+#endif
+
+#include "defs.h"
+
+// ----------------------------------------------------------------------------------
+/** Represents a two-dimensional vector.
+ */
+
+#ifdef __cplusplus
+template <typename TReal>
+class aiVector2t {
+public:
+ aiVector2t () : x(), y() {}
+ aiVector2t (TReal _x, TReal _y) : x(_x), y(_y) {}
+ explicit aiVector2t (TReal _xyz) : x(_xyz), y(_xyz) {}
+ aiVector2t (const aiVector2t& o) = default;
+
+ void Set( TReal pX, TReal pY);
+ TReal SquareLength() const ;
+ TReal Length() const ;
+ aiVector2t& Normalize();
+
+ const aiVector2t& operator += (const aiVector2t& o);
+ const aiVector2t& operator -= (const aiVector2t& o);
+ const aiVector2t& operator *= (TReal f);
+ const aiVector2t& operator /= (TReal f);
+
+ TReal operator[](unsigned int i) const;
+
+ bool operator== (const aiVector2t& other) const;
+ bool operator!= (const aiVector2t& other) const;
+
+ bool Equal(const aiVector2t& other, TReal epsilon = 1e-6) const;
+
+ aiVector2t& operator= (TReal f);
+ const aiVector2t SymMul(const aiVector2t& o);
+
+ template <typename TOther>
+ operator aiVector2t<TOther> () const;
+
+ TReal x, y;
+};
+
+typedef aiVector2t<ai_real> aiVector2D;
+
+#else
+
+struct aiVector2D {
+ ai_real x, y;
+};
+
+#endif // __cplusplus
+
+#endif // AI_VECTOR2D_H_INC
diff --git a/thirdparty/assimp/include/assimp/vector2.inl b/thirdparty/assimp/include/assimp/vector2.inl
new file mode 100644
index 0000000000..3b7a7beabb
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/vector2.inl
@@ -0,0 +1,244 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file vector2.inl
+ * @brief Inline implementation of aiVector2t<TReal> operators
+ */
+#pragma once
+#ifndef AI_VECTOR2D_INL_INC
+#define AI_VECTOR2D_INL_INC
+
+#ifdef __cplusplus
+#include "vector2.h"
+
+#include <cmath>
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+template <typename TOther>
+aiVector2t<TReal>::operator aiVector2t<TOther> () const {
+ return aiVector2t<TOther>(static_cast<TOther>(x),static_cast<TOther>(y));
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+inline
+void aiVector2t<TReal>::Set( TReal pX, TReal pY) {
+ x = pX; y = pY;
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+inline
+TReal aiVector2t<TReal>::SquareLength() const {
+ return x*x + y*y;
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+inline
+TReal aiVector2t<TReal>::Length() const {
+ return std::sqrt( SquareLength());
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+inline
+aiVector2t<TReal>& aiVector2t<TReal>::Normalize() {
+ *this /= Length();
+ return *this;
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+inline
+const aiVector2t<TReal>& aiVector2t<TReal>::operator += (const aiVector2t& o) {
+ x += o.x; y += o.y;
+ return *this;
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+inline
+const aiVector2t<TReal>& aiVector2t<TReal>::operator -= (const aiVector2t& o) {
+ x -= o.x; y -= o.y;
+ return *this;
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+inline
+const aiVector2t<TReal>& aiVector2t<TReal>::operator *= (TReal f) {
+ x *= f; y *= f;
+ return *this;
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+inline
+const aiVector2t<TReal>& aiVector2t<TReal>::operator /= (TReal f) {
+ x /= f; y /= f;
+ return *this;
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+inline
+TReal aiVector2t<TReal>::operator[](unsigned int i) const {
+ switch (i) {
+ case 0:
+ return x;
+ case 1:
+ return y;
+ default:
+ break;
+
+ }
+ return x;
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+inline
+bool aiVector2t<TReal>::operator== (const aiVector2t& other) const {
+ return x == other.x && y == other.y;
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+inline
+bool aiVector2t<TReal>::operator!= (const aiVector2t& other) const {
+ return x != other.x || y != other.y;
+}
+
+// ---------------------------------------------------------------------------
+template<typename TReal>
+inline
+bool aiVector2t<TReal>::Equal(const aiVector2t& other, TReal epsilon) const {
+ return
+ std::abs(x - other.x) <= epsilon &&
+ std::abs(y - other.y) <= epsilon;
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+inline
+aiVector2t<TReal>& aiVector2t<TReal>::operator= (TReal f) {
+ x = y = f;
+ return *this;
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+inline
+const aiVector2t<TReal> aiVector2t<TReal>::SymMul(const aiVector2t& o) {
+ return aiVector2t(x*o.x,y*o.y);
+}
+
+
+// ------------------------------------------------------------------------------------------------
+// symmetric addition
+template <typename TReal>
+inline
+aiVector2t<TReal> operator + (const aiVector2t<TReal>& v1, const aiVector2t<TReal>& v2) {
+ return aiVector2t<TReal>( v1.x + v2.x, v1.y + v2.y);
+}
+
+// ------------------------------------------------------------------------------------------------
+// symmetric subtraction
+template <typename TReal>
+inline
+aiVector2t<TReal> operator - (const aiVector2t<TReal>& v1, const aiVector2t<TReal>& v2) {
+ return aiVector2t<TReal>( v1.x - v2.x, v1.y - v2.y);
+}
+
+// ------------------------------------------------------------------------------------------------
+// scalar product
+template <typename TReal>
+inline
+TReal operator * (const aiVector2t<TReal>& v1, const aiVector2t<TReal>& v2) {
+ return v1.x*v2.x + v1.y*v2.y;
+}
+
+// ------------------------------------------------------------------------------------------------
+// scalar multiplication
+template <typename TReal>
+inline
+aiVector2t<TReal> operator * ( TReal f, const aiVector2t<TReal>& v) {
+ return aiVector2t<TReal>( f*v.x, f*v.y);
+}
+
+// ------------------------------------------------------------------------------------------------
+// and the other way around
+template <typename TReal>
+inline
+aiVector2t<TReal> operator * ( const aiVector2t<TReal>& v, TReal f) {
+ return aiVector2t<TReal>( f*v.x, f*v.y);
+}
+
+// ------------------------------------------------------------------------------------------------
+// scalar division
+template <typename TReal>
+inline
+aiVector2t<TReal> operator / ( const aiVector2t<TReal>& v, TReal f) {
+ return v * (1/f);
+}
+
+// ------------------------------------------------------------------------------------------------
+// vector division
+template <typename TReal>
+inline
+aiVector2t<TReal> operator / ( const aiVector2t<TReal>& v, const aiVector2t<TReal>& v2) {
+ return aiVector2t<TReal>(v.x / v2.x,v.y / v2.y);
+}
+
+// ------------------------------------------------------------------------------------------------
+// vector negation
+template <typename TReal>
+inline
+aiVector2t<TReal> operator - ( const aiVector2t<TReal>& v) {
+ return aiVector2t<TReal>( -v.x, -v.y);
+}
+
+#endif
+
+#endif // AI_VECTOR2D_INL_INC
diff --git a/thirdparty/assimp/include/assimp/vector3.h b/thirdparty/assimp/include/assimp/vector3.h
new file mode 100644
index 0000000000..7ff25cf0ad
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/vector3.h
@@ -0,0 +1,146 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+/** @file vector3.h
+ * @brief 3D vector structure, including operators when compiling in C++
+ */
+#pragma once
+#ifndef AI_VECTOR3D_H_INC
+#define AI_VECTOR3D_H_INC
+
+#ifdef __cplusplus
+# include <cmath>
+#else
+# include <math.h>
+#endif
+
+#include "defs.h"
+
+#ifdef __cplusplus
+
+template<typename TReal> class aiMatrix3x3t;
+template<typename TReal> class aiMatrix4x4t;
+
+// ---------------------------------------------------------------------------
+/** Represents a three-dimensional vector. */
+template <typename TReal>
+class aiVector3t
+{
+public:
+ aiVector3t() AI_NO_EXCEPT : x(), y(), z() {}
+ aiVector3t(TReal _x, TReal _y, TReal _z) : x(_x), y(_y), z(_z) {}
+ explicit aiVector3t (TReal _xyz ) : x(_xyz), y(_xyz), z(_xyz) {}
+ aiVector3t( const aiVector3t& o ) = default;
+
+public:
+
+ // combined operators
+ const aiVector3t& operator += (const aiVector3t& o);
+ const aiVector3t& operator -= (const aiVector3t& o);
+ const aiVector3t& operator *= (TReal f);
+ const aiVector3t& operator /= (TReal f);
+
+ // transform vector by matrix
+ aiVector3t& operator *= (const aiMatrix3x3t<TReal>& mat);
+ aiVector3t& operator *= (const aiMatrix4x4t<TReal>& mat);
+
+ // access a single element
+ TReal operator[](unsigned int i) const;
+ TReal& operator[](unsigned int i);
+
+ // comparison
+ bool operator== (const aiVector3t& other) const;
+ bool operator!= (const aiVector3t& other) const;
+ bool operator < (const aiVector3t& other) const;
+
+ bool Equal(const aiVector3t& other, TReal epsilon = 1e-6) const;
+
+ template <typename TOther>
+ operator aiVector3t<TOther> () const;
+
+public:
+ /** @brief Set the components of a vector
+ * @param pX X component
+ * @param pY Y component
+ * @param pZ Z component */
+ void Set( TReal pX, TReal pY, TReal pZ);
+
+ /** @brief Get the squared length of the vector
+ * @return Square length */
+ TReal SquareLength() const;
+
+ /** @brief Get the length of the vector
+ * @return length */
+ TReal Length() const;
+
+
+ /** @brief Normalize the vector */
+ aiVector3t& Normalize();
+
+ /** @brief Normalize the vector with extra check for zero vectors */
+ aiVector3t& NormalizeSafe();
+
+ /** @brief Componentwise multiplication of two vectors
+ *
+ * Note that vec*vec yields the dot product.
+ * @param o Second factor */
+ const aiVector3t SymMul(const aiVector3t& o);
+
+ TReal x, y, z;
+};
+
+
+typedef aiVector3t<ai_real> aiVector3D;
+
+#else
+
+struct aiVector3D {
+ ai_real x, y, z;
+};
+
+#endif // __cplusplus
+
+#ifdef __cplusplus
+
+#endif // __cplusplus
+
+#endif // AI_VECTOR3D_H_INC
diff --git a/thirdparty/assimp/include/assimp/vector3.inl b/thirdparty/assimp/include/assimp/vector3.inl
new file mode 100644
index 0000000000..2fce6eddee
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/vector3.inl
@@ -0,0 +1,309 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file vector3.inl
+ * @brief Inline implementation of aiVector3t<TReal> operators
+ */
+#pragma once
+#ifndef AI_VECTOR3D_INL_INC
+#define AI_VECTOR3D_INL_INC
+
+#ifdef __cplusplus
+#include "vector3.h"
+
+#include <cmath>
+
+// ------------------------------------------------------------------------------------------------
+/** Transformation of a vector by a 3x3 matrix */
+template <typename TReal>
+AI_FORCE_INLINE
+aiVector3t<TReal> operator * (const aiMatrix3x3t<TReal>& pMatrix, const aiVector3t<TReal>& pVector) {
+ aiVector3t<TReal> res;
+ res.x = pMatrix.a1 * pVector.x + pMatrix.a2 * pVector.y + pMatrix.a3 * pVector.z;
+ res.y = pMatrix.b1 * pVector.x + pMatrix.b2 * pVector.y + pMatrix.b3 * pVector.z;
+ res.z = pMatrix.c1 * pVector.x + pMatrix.c2 * pVector.y + pMatrix.c3 * pVector.z;
+ return res;
+}
+
+// ------------------------------------------------------------------------------------------------
+/** Transformation of a vector by a 4x4 matrix */
+template <typename TReal>
+AI_FORCE_INLINE
+aiVector3t<TReal> operator * (const aiMatrix4x4t<TReal>& pMatrix, const aiVector3t<TReal>& pVector) {
+ aiVector3t<TReal> res;
+ res.x = pMatrix.a1 * pVector.x + pMatrix.a2 * pVector.y + pMatrix.a3 * pVector.z + pMatrix.a4;
+ res.y = pMatrix.b1 * pVector.x + pMatrix.b2 * pVector.y + pMatrix.b3 * pVector.z + pMatrix.b4;
+ res.z = pMatrix.c1 * pVector.x + pMatrix.c2 * pVector.y + pMatrix.c3 * pVector.z + pMatrix.c4;
+ return res;
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+template <typename TOther>
+aiVector3t<TReal>::operator aiVector3t<TOther> () const {
+ return aiVector3t<TOther>(static_cast<TOther>(x),static_cast<TOther>(y),static_cast<TOther>(z));
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE
+void aiVector3t<TReal>::Set( TReal pX, TReal pY, TReal pZ) {
+ x = pX;
+ y = pY;
+ z = pZ;
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE
+TReal aiVector3t<TReal>::SquareLength() const {
+ return x*x + y*y + z*z;
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE
+TReal aiVector3t<TReal>::Length() const {
+ return std::sqrt( SquareLength());
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE
+aiVector3t<TReal>& aiVector3t<TReal>::Normalize() {
+ *this /= Length();
+
+ return *this;
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE
+aiVector3t<TReal>& aiVector3t<TReal>::NormalizeSafe() {
+ TReal len = Length();
+ if ( len > static_cast< TReal >( 0 ) ) {
+ *this /= len;
+ }
+ return *this;
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE
+const aiVector3t<TReal>& aiVector3t<TReal>::operator += (const aiVector3t<TReal>& o) {
+ x += o.x;
+ y += o.y;
+ z += o.z;
+
+ return *this;
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE
+const aiVector3t<TReal>& aiVector3t<TReal>::operator -= (const aiVector3t<TReal>& o) {
+ x -= o.x;
+ y -= o.y;
+ z -= o.z;
+
+ return *this;
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE
+const aiVector3t<TReal>& aiVector3t<TReal>::operator *= (TReal f) {
+ x *= f;
+ y *= f;
+ z *= f;
+
+ return *this;
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE
+const aiVector3t<TReal>& aiVector3t<TReal>::operator /= (TReal f) {
+ const TReal invF = (TReal) 1.0 / f;
+ x *= invF;
+ y *= invF;
+ z *= invF;
+
+ return *this;
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE
+aiVector3t<TReal>& aiVector3t<TReal>::operator *= (const aiMatrix3x3t<TReal>& mat){
+ return (*this = mat * (*this));
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE
+aiVector3t<TReal>& aiVector3t<TReal>::operator *= (const aiMatrix4x4t<TReal>& mat){
+ return (*this = mat * (*this));
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE
+TReal aiVector3t<TReal>::operator[](unsigned int i) const {
+ switch (i) {
+ case 0:
+ return x;
+ case 1:
+ return y;
+ case 2:
+ return z;
+ default:
+ break;
+ }
+ return x;
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE
+TReal& aiVector3t<TReal>::operator[](unsigned int i) {
+// return *(&x + i);
+ switch (i) {
+ case 0:
+ return x;
+ case 1:
+ return y;
+ case 2:
+ return z;
+ default:
+ break;
+ }
+ return x;
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE
+bool aiVector3t<TReal>::operator== (const aiVector3t<TReal>& other) const {
+ return x == other.x && y == other.y && z == other.z;
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE
+bool aiVector3t<TReal>::operator!= (const aiVector3t<TReal>& other) const {
+ return x != other.x || y != other.y || z != other.z;
+}
+// ---------------------------------------------------------------------------
+template<typename TReal>
+AI_FORCE_INLINE
+bool aiVector3t<TReal>::Equal(const aiVector3t<TReal>& other, TReal epsilon) const {
+ return
+ std::abs(x - other.x) <= epsilon &&
+ std::abs(y - other.y) <= epsilon &&
+ std::abs(z - other.z) <= epsilon;
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE
+bool aiVector3t<TReal>::operator < (const aiVector3t<TReal>& other) const {
+ return x != other.x ? x < other.x : y != other.y ? y < other.y : z < other.z;
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE
+const aiVector3t<TReal> aiVector3t<TReal>::SymMul(const aiVector3t<TReal>& o) {
+ return aiVector3t<TReal>(x*o.x,y*o.y,z*o.z);
+}
+// ------------------------------------------------------------------------------------------------
+// symmetric addition
+template <typename TReal>
+AI_FORCE_INLINE
+aiVector3t<TReal> operator + (const aiVector3t<TReal>& v1, const aiVector3t<TReal>& v2) {
+ return aiVector3t<TReal>( v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
+}
+// ------------------------------------------------------------------------------------------------
+// symmetric subtraction
+template <typename TReal>
+AI_FORCE_INLINE
+aiVector3t<TReal> operator - (const aiVector3t<TReal>& v1, const aiVector3t<TReal>& v2) {
+ return aiVector3t<TReal>( v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
+}
+// ------------------------------------------------------------------------------------------------
+// scalar product
+template <typename TReal>
+AI_FORCE_INLINE
+TReal operator * (const aiVector3t<TReal>& v1, const aiVector3t<TReal>& v2) {
+ return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z;
+}
+// ------------------------------------------------------------------------------------------------
+// scalar multiplication
+template <typename TReal>
+AI_FORCE_INLINE
+aiVector3t<TReal> operator * ( TReal f, const aiVector3t<TReal>& v) {
+ return aiVector3t<TReal>( f*v.x, f*v.y, f*v.z);
+}
+// ------------------------------------------------------------------------------------------------
+// and the other way around
+template <typename TReal>
+AI_FORCE_INLINE
+aiVector3t<TReal> operator * ( const aiVector3t<TReal>& v, TReal f) {
+ return aiVector3t<TReal>( f*v.x, f*v.y, f*v.z);
+}
+// ------------------------------------------------------------------------------------------------
+// scalar division
+template <typename TReal>
+AI_FORCE_INLINE
+aiVector3t<TReal> operator / ( const aiVector3t<TReal>& v, TReal f) {
+ return v * (1/f);
+}
+// ------------------------------------------------------------------------------------------------
+// vector division
+template <typename TReal>
+AI_FORCE_INLINE
+aiVector3t<TReal> operator / ( const aiVector3t<TReal>& v, const aiVector3t<TReal>& v2) {
+ return aiVector3t<TReal>(v.x / v2.x,v.y / v2.y,v.z / v2.z);
+}
+// ------------------------------------------------------------------------------------------------
+// cross product
+template<typename TReal>
+AI_FORCE_INLINE
+aiVector3t<TReal> operator ^ ( const aiVector3t<TReal>& v1, const aiVector3t<TReal>& v2) {
+ return aiVector3t<TReal>( v1.y*v2.z - v1.z*v2.y, v1.z*v2.x - v1.x*v2.z, v1.x*v2.y - v1.y*v2.x);
+}
+// ------------------------------------------------------------------------------------------------
+// vector negation
+template<typename TReal>
+AI_FORCE_INLINE
+aiVector3t<TReal> operator - ( const aiVector3t<TReal>& v) {
+ return aiVector3t<TReal>( -v.x, -v.y, -v.z);
+}
+
+// ------------------------------------------------------------------------------------------------
+
+#endif // __cplusplus
+#endif // AI_VECTOR3D_INL_INC
diff --git a/thirdparty/assimp/include/assimp/version.h b/thirdparty/assimp/include/assimp/version.h
new file mode 100644
index 0000000000..c62a40e118
--- /dev/null
+++ b/thirdparty/assimp/include/assimp/version.h
@@ -0,0 +1,115 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file version.h
+ * @brief Functions to query the version of the Assimp runtime, check
+ * compile flags, ...
+ */
+#pragma once
+#ifndef AI_VERSION_H_INC
+#define AI_VERSION_H_INC
+
+#include "defs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// ---------------------------------------------------------------------------
+/** @brief Returns a string with legal copyright and licensing information
+ * about Assimp. The string may include multiple lines.
+ * @return Pointer to static string.
+ */
+ASSIMP_API const char* aiGetLegalString (void);
+
+// ---------------------------------------------------------------------------
+/** @brief Returns the current minor version number of Assimp.
+ * @return Minor version of the Assimp runtime the application was
+ * linked/built against
+ */
+ASSIMP_API unsigned int aiGetVersionMinor (void);
+
+// ---------------------------------------------------------------------------
+/** @brief Returns the current major version number of Assimp.
+ * @return Major version of the Assimp runtime the application was
+ * linked/built against
+ */
+ASSIMP_API unsigned int aiGetVersionMajor (void);
+
+// ---------------------------------------------------------------------------
+/** @brief Returns the repository revision of the Assimp runtime.
+ * @return SVN Repository revision number of the Assimp runtime the
+ * application was linked/built against.
+ */
+ASSIMP_API unsigned int aiGetVersionRevision (void);
+
+// ---------------------------------------------------------------------------
+/** @brief Returns the branchname of the Assimp runtime.
+ * @return The current branch name.
+ */
+ASSIMP_API const char *aiGetBranchName();
+
+//! Assimp was compiled as a shared object (Windows: DLL)
+#define ASSIMP_CFLAGS_SHARED 0x1
+//! Assimp was compiled against STLport
+#define ASSIMP_CFLAGS_STLPORT 0x2
+//! Assimp was compiled as a debug build
+#define ASSIMP_CFLAGS_DEBUG 0x4
+
+//! Assimp was compiled with ASSIMP_BUILD_BOOST_WORKAROUND defined
+#define ASSIMP_CFLAGS_NOBOOST 0x8
+//! Assimp was compiled with ASSIMP_BUILD_SINGLETHREADED defined
+#define ASSIMP_CFLAGS_SINGLETHREADED 0x10
+
+// ---------------------------------------------------------------------------
+/** @brief Returns assimp's compile flags
+ * @return Any bitwise combination of the ASSIMP_CFLAGS_xxx constants.
+ */
+ASSIMP_API unsigned int aiGetCompileFlags (void);
+
+#ifdef __cplusplus
+} // end extern "C"
+#endif
+
+#endif // !! #ifndef AI_VERSION_H_INC
+
diff --git a/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3BroadphaseCallback.h b/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3BroadphaseCallback.h
index 1bc56cf80a..bec0800a6f 100644
--- a/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3BroadphaseCallback.h
+++ b/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3BroadphaseCallback.h
@@ -19,22 +19,20 @@ subject to the following restrictions:
#include "Bullet3Common/b3Vector3.h"
struct b3BroadphaseProxy;
-
-struct b3BroadphaseAabbCallback
+struct b3BroadphaseAabbCallback
{
virtual ~b3BroadphaseAabbCallback() {}
- virtual bool process(const b3BroadphaseProxy* proxy) = 0;
+ virtual bool process(const b3BroadphaseProxy* proxy) = 0;
};
-
-struct b3BroadphaseRayCallback : public b3BroadphaseAabbCallback
+struct b3BroadphaseRayCallback : public b3BroadphaseAabbCallback
{
///added some cached data to accelerate ray-AABB tests
- b3Vector3 m_rayDirectionInverse;
- unsigned int m_signs[3];
- b3Scalar m_lambda_max;
+ b3Vector3 m_rayDirectionInverse;
+ unsigned int m_signs[3];
+ b3Scalar m_lambda_max;
virtual ~b3BroadphaseRayCallback() {}
};
-#endif //B3_BROADPHASE_CALLBACK_H
+#endif //B3_BROADPHASE_CALLBACK_H
diff --git a/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.cpp b/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.cpp
index 0f04efe331..a0dc1da95d 100644
--- a/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.cpp
+++ b/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.cpp
@@ -17,209 +17,224 @@ subject to the following restrictions:
#include "b3DynamicBvh.h"
//
-typedef b3AlignedObjectArray<b3DbvtNode*> b3NodeArray;
-typedef b3AlignedObjectArray<const b3DbvtNode*> b3ConstNodeArray;
+typedef b3AlignedObjectArray<b3DbvtNode*> b3NodeArray;
+typedef b3AlignedObjectArray<const b3DbvtNode*> b3ConstNodeArray;
//
struct b3DbvtNodeEnumerator : b3DynamicBvh::ICollide
{
- b3ConstNodeArray nodes;
+ b3ConstNodeArray nodes;
void Process(const b3DbvtNode* n) { nodes.push_back(n); }
};
//
-static B3_DBVT_INLINE int b3IndexOf(const b3DbvtNode* node)
+static B3_DBVT_INLINE int b3IndexOf(const b3DbvtNode* node)
{
- return(node->parent->childs[1]==node);
+ return (node->parent->childs[1] == node);
}
//
-static B3_DBVT_INLINE b3DbvtVolume b3Merge( const b3DbvtVolume& a,
- const b3DbvtVolume& b)
+static B3_DBVT_INLINE b3DbvtVolume b3Merge(const b3DbvtVolume& a,
+ const b3DbvtVolume& b)
{
-#if (B3_DBVT_MERGE_IMPL==B3_DBVT_IMPL_SSE)
+#if (B3_DBVT_MERGE_IMPL == B3_DBVT_IMPL_SSE)
B3_ATTRIBUTE_ALIGNED16(char locals[sizeof(b3DbvtAabbMm)]);
- b3DbvtVolume& res=*(b3DbvtVolume*)locals;
+ b3DbvtVolume& res = *(b3DbvtVolume*)locals;
#else
- b3DbvtVolume res;
+ b3DbvtVolume res;
#endif
- b3Merge(a,b,res);
- return(res);
+ b3Merge(a, b, res);
+ return (res);
}
// volume+edge lengths
-static B3_DBVT_INLINE b3Scalar b3Size(const b3DbvtVolume& a)
+static B3_DBVT_INLINE b3Scalar b3Size(const b3DbvtVolume& a)
{
- const b3Vector3 edges=a.Lengths();
- return( edges.x*edges.y*edges.z+
- edges.x+edges.y+edges.z);
+ const b3Vector3 edges = a.Lengths();
+ return (edges.x * edges.y * edges.z +
+ edges.x + edges.y + edges.z);
}
//
-static void b3GetMaxDepth(const b3DbvtNode* node,int depth,int& maxdepth)
+static void b3GetMaxDepth(const b3DbvtNode* node, int depth, int& maxdepth)
{
- if(node->isinternal())
+ if (node->isinternal())
{
- b3GetMaxDepth(node->childs[0],depth+1,maxdepth);
- b3GetMaxDepth(node->childs[1],depth+1,maxdepth);
- } else maxdepth=b3Max(maxdepth,depth);
+ b3GetMaxDepth(node->childs[0], depth + 1, maxdepth);
+ b3GetMaxDepth(node->childs[1], depth + 1, maxdepth);
+ }
+ else
+ maxdepth = b3Max(maxdepth, depth);
}
//
-static B3_DBVT_INLINE void b3DeleteNode( b3DynamicBvh* pdbvt,
- b3DbvtNode* node)
+static B3_DBVT_INLINE void b3DeleteNode(b3DynamicBvh* pdbvt,
+ b3DbvtNode* node)
{
b3AlignedFree(pdbvt->m_free);
- pdbvt->m_free=node;
+ pdbvt->m_free = node;
}
//
-static void b3RecurseDeleteNode( b3DynamicBvh* pdbvt,
- b3DbvtNode* node)
+static void b3RecurseDeleteNode(b3DynamicBvh* pdbvt,
+ b3DbvtNode* node)
{
- if(!node->isleaf())
+ if (!node->isleaf())
{
- b3RecurseDeleteNode(pdbvt,node->childs[0]);
- b3RecurseDeleteNode(pdbvt,node->childs[1]);
+ b3RecurseDeleteNode(pdbvt, node->childs[0]);
+ b3RecurseDeleteNode(pdbvt, node->childs[1]);
}
- if(node==pdbvt->m_root) pdbvt->m_root=0;
- b3DeleteNode(pdbvt,node);
+ if (node == pdbvt->m_root) pdbvt->m_root = 0;
+ b3DeleteNode(pdbvt, node);
}
//
-static B3_DBVT_INLINE b3DbvtNode* b3CreateNode( b3DynamicBvh* pdbvt,
- b3DbvtNode* parent,
- void* data)
+static B3_DBVT_INLINE b3DbvtNode* b3CreateNode(b3DynamicBvh* pdbvt,
+ b3DbvtNode* parent,
+ void* data)
{
- b3DbvtNode* node;
- if(pdbvt->m_free)
- { node=pdbvt->m_free;pdbvt->m_free=0; }
+ b3DbvtNode* node;
+ if (pdbvt->m_free)
+ {
+ node = pdbvt->m_free;
+ pdbvt->m_free = 0;
+ }
else
- { node=new(b3AlignedAlloc(sizeof(b3DbvtNode),16)) b3DbvtNode(); }
- node->parent = parent;
- node->data = data;
- node->childs[1] = 0;
- return(node);
+ {
+ node = new (b3AlignedAlloc(sizeof(b3DbvtNode), 16)) b3DbvtNode();
+ }
+ node->parent = parent;
+ node->data = data;
+ node->childs[1] = 0;
+ return (node);
}
//
-static B3_DBVT_INLINE b3DbvtNode* b3CreateNode( b3DynamicBvh* pdbvt,
- b3DbvtNode* parent,
- const b3DbvtVolume& volume,
- void* data)
+static B3_DBVT_INLINE b3DbvtNode* b3CreateNode(b3DynamicBvh* pdbvt,
+ b3DbvtNode* parent,
+ const b3DbvtVolume& volume,
+ void* data)
{
- b3DbvtNode* node=b3CreateNode(pdbvt,parent,data);
- node->volume=volume;
- return(node);
+ b3DbvtNode* node = b3CreateNode(pdbvt, parent, data);
+ node->volume = volume;
+ return (node);
}
//
-static B3_DBVT_INLINE b3DbvtNode* b3CreateNode( b3DynamicBvh* pdbvt,
- b3DbvtNode* parent,
- const b3DbvtVolume& volume0,
- const b3DbvtVolume& volume1,
- void* data)
+static B3_DBVT_INLINE b3DbvtNode* b3CreateNode(b3DynamicBvh* pdbvt,
+ b3DbvtNode* parent,
+ const b3DbvtVolume& volume0,
+ const b3DbvtVolume& volume1,
+ void* data)
{
- b3DbvtNode* node=b3CreateNode(pdbvt,parent,data);
- b3Merge(volume0,volume1,node->volume);
- return(node);
+ b3DbvtNode* node = b3CreateNode(pdbvt, parent, data);
+ b3Merge(volume0, volume1, node->volume);
+ return (node);
}
//
-static void b3InsertLeaf( b3DynamicBvh* pdbvt,
- b3DbvtNode* root,
- b3DbvtNode* leaf)
+static void b3InsertLeaf(b3DynamicBvh* pdbvt,
+ b3DbvtNode* root,
+ b3DbvtNode* leaf)
{
- if(!pdbvt->m_root)
+ if (!pdbvt->m_root)
{
- pdbvt->m_root = leaf;
- leaf->parent = 0;
+ pdbvt->m_root = leaf;
+ leaf->parent = 0;
}
else
{
- if(!root->isleaf())
+ if (!root->isleaf())
{
- do {
- root=root->childs[b3Select( leaf->volume,
- root->childs[0]->volume,
- root->childs[1]->volume)];
- } while(!root->isleaf());
+ do
+ {
+ root = root->childs[b3Select(leaf->volume,
+ root->childs[0]->volume,
+ root->childs[1]->volume)];
+ } while (!root->isleaf());
}
- b3DbvtNode* prev=root->parent;
- b3DbvtNode* node=b3CreateNode(pdbvt,prev,leaf->volume,root->volume,0);
- if(prev)
+ b3DbvtNode* prev = root->parent;
+ b3DbvtNode* node = b3CreateNode(pdbvt, prev, leaf->volume, root->volume, 0);
+ if (prev)
{
- prev->childs[b3IndexOf(root)] = node;
- node->childs[0] = root;root->parent=node;
- node->childs[1] = leaf;leaf->parent=node;
- do {
- if(!prev->volume.Contain(node->volume))
- b3Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume);
+ prev->childs[b3IndexOf(root)] = node;
+ node->childs[0] = root;
+ root->parent = node;
+ node->childs[1] = leaf;
+ leaf->parent = node;
+ do
+ {
+ if (!prev->volume.Contain(node->volume))
+ b3Merge(prev->childs[0]->volume, prev->childs[1]->volume, prev->volume);
else
break;
- node=prev;
- } while(0!=(prev=node->parent));
+ node = prev;
+ } while (0 != (prev = node->parent));
}
else
{
- node->childs[0] = root;root->parent=node;
- node->childs[1] = leaf;leaf->parent=node;
- pdbvt->m_root = node;
+ node->childs[0] = root;
+ root->parent = node;
+ node->childs[1] = leaf;
+ leaf->parent = node;
+ pdbvt->m_root = node;
}
}
}
//
-static b3DbvtNode* b3RemoveLeaf( b3DynamicBvh* pdbvt,
- b3DbvtNode* leaf)
+static b3DbvtNode* b3RemoveLeaf(b3DynamicBvh* pdbvt,
+ b3DbvtNode* leaf)
{
- if(leaf==pdbvt->m_root)
+ if (leaf == pdbvt->m_root)
{
- pdbvt->m_root=0;
- return(0);
+ pdbvt->m_root = 0;
+ return (0);
}
else
{
- b3DbvtNode* parent=leaf->parent;
- b3DbvtNode* prev=parent->parent;
- b3DbvtNode* sibling=parent->childs[1-b3IndexOf(leaf)];
- if(prev)
+ b3DbvtNode* parent = leaf->parent;
+ b3DbvtNode* prev = parent->parent;
+ b3DbvtNode* sibling = parent->childs[1 - b3IndexOf(leaf)];
+ if (prev)
{
- prev->childs[b3IndexOf(parent)]=sibling;
- sibling->parent=prev;
- b3DeleteNode(pdbvt,parent);
- while(prev)
+ prev->childs[b3IndexOf(parent)] = sibling;
+ sibling->parent = prev;
+ b3DeleteNode(pdbvt, parent);
+ while (prev)
{
- const b3DbvtVolume pb=prev->volume;
- b3Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume);
- if(b3NotEqual(pb,prev->volume))
+ const b3DbvtVolume pb = prev->volume;
+ b3Merge(prev->childs[0]->volume, prev->childs[1]->volume, prev->volume);
+ if (b3NotEqual(pb, prev->volume))
{
- prev=prev->parent;
- } else break;
+ prev = prev->parent;
+ }
+ else
+ break;
}
- return(prev?prev:pdbvt->m_root);
+ return (prev ? prev : pdbvt->m_root);
}
else
- {
- pdbvt->m_root=sibling;
- sibling->parent=0;
- b3DeleteNode(pdbvt,parent);
- return(pdbvt->m_root);
- }
+ {
+ pdbvt->m_root = sibling;
+ sibling->parent = 0;
+ b3DeleteNode(pdbvt, parent);
+ return (pdbvt->m_root);
+ }
}
}
//
-static void b3FetchLeaves(b3DynamicBvh* pdbvt,
- b3DbvtNode* root,
- b3NodeArray& leaves,
- int depth=-1)
+static void b3FetchLeaves(b3DynamicBvh* pdbvt,
+ b3DbvtNode* root,
+ b3NodeArray& leaves,
+ int depth = -1)
{
- if(root->isinternal()&&depth)
+ if (root->isinternal() && depth)
{
- b3FetchLeaves(pdbvt,root->childs[0],leaves,depth-1);
- b3FetchLeaves(pdbvt,root->childs[1],leaves,depth-1);
- b3DeleteNode(pdbvt,root);
+ b3FetchLeaves(pdbvt, root->childs[0], leaves, depth - 1);
+ b3FetchLeaves(pdbvt, root->childs[1], leaves, depth - 1);
+ b3DeleteNode(pdbvt, root);
}
else
{
@@ -227,50 +242,50 @@ static void b3FetchLeaves(b3DynamicBvh* pdbvt,
}
}
-static bool b3LeftOfAxis( const b3DbvtNode* node,
- const b3Vector3& org,
- const b3Vector3& axis)
+static bool b3LeftOfAxis(const b3DbvtNode* node,
+ const b3Vector3& org,
+ const b3Vector3& axis)
{
- return b3Dot(axis,node->volume.Center()-org) <= 0;
+ return b3Dot(axis, node->volume.Center() - org) <= 0;
}
// Partitions leaves such that leaves[0, n) are on the
// left of axis, and leaves[n, count) are on the right
// of axis. returns N.
-static int b3Split( b3DbvtNode** leaves,
- int count,
- const b3Vector3& org,
- const b3Vector3& axis)
+static int b3Split(b3DbvtNode** leaves,
+ int count,
+ const b3Vector3& org,
+ const b3Vector3& axis)
{
- int begin=0;
- int end=count;
- for(;;)
+ int begin = 0;
+ int end = count;
+ for (;;)
{
- while(begin!=end && b3LeftOfAxis(leaves[begin],org,axis))
+ while (begin != end && b3LeftOfAxis(leaves[begin], org, axis))
{
++begin;
}
- if(begin==end)
+ if (begin == end)
{
break;
}
- while(begin!=end && !b3LeftOfAxis(leaves[end-1],org,axis))
+ while (begin != end && !b3LeftOfAxis(leaves[end - 1], org, axis))
{
--end;
}
- if(begin==end)
+ if (begin == end)
{
break;
}
// swap out of place nodes
--end;
- b3DbvtNode* temp=leaves[begin];
- leaves[begin]=leaves[end];
- leaves[end]=temp;
+ b3DbvtNode* temp = leaves[begin];
+ leaves[begin] = leaves[end];
+ leaves[end] = temp;
++begin;
}
@@ -278,149 +293,152 @@ static int b3Split( b3DbvtNode** leaves,
}
//
-static b3DbvtVolume b3Bounds( b3DbvtNode** leaves,
- int count)
+static b3DbvtVolume b3Bounds(b3DbvtNode** leaves,
+ int count)
{
-#if B3_DBVT_MERGE_IMPL==B3_DBVT_IMPL_SSE
- B3_ATTRIBUTE_ALIGNED16(char locals[sizeof(b3DbvtVolume)]);
- b3DbvtVolume& volume=*(b3DbvtVolume*)locals;
- volume=leaves[0]->volume;
+#if B3_DBVT_MERGE_IMPL == B3_DBVT_IMPL_SSE
+ B3_ATTRIBUTE_ALIGNED16(char locals[sizeof(b3DbvtVolume)]);
+ b3DbvtVolume& volume = *(b3DbvtVolume*)locals;
+ volume = leaves[0]->volume;
#else
- b3DbvtVolume volume=leaves[0]->volume;
+ b3DbvtVolume volume = leaves[0]->volume;
#endif
- for(int i=1,ni=count;i<ni;++i)
+ for (int i = 1, ni = count; i < ni; ++i)
{
- b3Merge(volume,leaves[i]->volume,volume);
+ b3Merge(volume, leaves[i]->volume, volume);
}
- return(volume);
+ return (volume);
}
//
-static void b3BottomUp( b3DynamicBvh* pdbvt,
- b3DbvtNode** leaves,
- int count)
+static void b3BottomUp(b3DynamicBvh* pdbvt,
+ b3DbvtNode** leaves,
+ int count)
{
- while(count>1)
+ while (count > 1)
{
- b3Scalar minsize=B3_INFINITY;
- int minidx[2]={-1,-1};
- for(int i=0;i<count;++i)
+ b3Scalar minsize = B3_INFINITY;
+ int minidx[2] = {-1, -1};
+ for (int i = 0; i < count; ++i)
{
- for(int j=i+1;j<count;++j)
+ for (int j = i + 1; j < count; ++j)
{
- const b3Scalar sz=b3Size(b3Merge(leaves[i]->volume,leaves[j]->volume));
- if(sz<minsize)
+ const b3Scalar sz = b3Size(b3Merge(leaves[i]->volume, leaves[j]->volume));
+ if (sz < minsize)
{
- minsize = sz;
- minidx[0] = i;
- minidx[1] = j;
+ minsize = sz;
+ minidx[0] = i;
+ minidx[1] = j;
}
}
}
- b3DbvtNode* n[] = {leaves[minidx[0]],leaves[minidx[1]]};
- b3DbvtNode* p = b3CreateNode(pdbvt,0,n[0]->volume,n[1]->volume,0);
- p->childs[0] = n[0];
- p->childs[1] = n[1];
- n[0]->parent = p;
- n[1]->parent = p;
- leaves[minidx[0]] = p;
- leaves[minidx[1]] = leaves[count-1];
+ b3DbvtNode* n[] = {leaves[minidx[0]], leaves[minidx[1]]};
+ b3DbvtNode* p = b3CreateNode(pdbvt, 0, n[0]->volume, n[1]->volume, 0);
+ p->childs[0] = n[0];
+ p->childs[1] = n[1];
+ n[0]->parent = p;
+ n[1]->parent = p;
+ leaves[minidx[0]] = p;
+ leaves[minidx[1]] = leaves[count - 1];
--count;
}
}
//
-static b3DbvtNode* b3TopDown(b3DynamicBvh* pdbvt,
- b3DbvtNode** leaves,
- int count,
- int bu_treshold)
+static b3DbvtNode* b3TopDown(b3DynamicBvh* pdbvt,
+ b3DbvtNode** leaves,
+ int count,
+ int bu_treshold)
{
- static const b3Vector3 axis[]={b3MakeVector3(1,0,0),
- b3MakeVector3(0,1,0),
- b3MakeVector3(0,0,1)};
- b3Assert(bu_treshold>1);
- if(count>1)
+ static const b3Vector3 axis[] = {b3MakeVector3(1, 0, 0),
+ b3MakeVector3(0, 1, 0),
+ b3MakeVector3(0, 0, 1)};
+ b3Assert(bu_treshold > 1);
+ if (count > 1)
{
- if(count>bu_treshold)
+ if (count > bu_treshold)
{
- const b3DbvtVolume vol=b3Bounds(leaves,count);
- const b3Vector3 org=vol.Center();
- int partition;
- int bestaxis=-1;
- int bestmidp=count;
- int splitcount[3][2]={{0,0},{0,0},{0,0}};
+ const b3DbvtVolume vol = b3Bounds(leaves, count);
+ const b3Vector3 org = vol.Center();
+ int partition;
+ int bestaxis = -1;
+ int bestmidp = count;
+ int splitcount[3][2] = {{0, 0}, {0, 0}, {0, 0}};
int i;
- for( i=0;i<count;++i)
+ for (i = 0; i < count; ++i)
{
- const b3Vector3 x=leaves[i]->volume.Center()-org;
- for(int j=0;j<3;++j)
+ const b3Vector3 x = leaves[i]->volume.Center() - org;
+ for (int j = 0; j < 3; ++j)
{
- ++splitcount[j][b3Dot(x,axis[j])>0?1:0];
+ ++splitcount[j][b3Dot(x, axis[j]) > 0 ? 1 : 0];
}
}
- for( i=0;i<3;++i)
+ for (i = 0; i < 3; ++i)
{
- if((splitcount[i][0]>0)&&(splitcount[i][1]>0))
+ if ((splitcount[i][0] > 0) && (splitcount[i][1] > 0))
{
- const int midp=(int)b3Fabs(b3Scalar(splitcount[i][0]-splitcount[i][1]));
- if(midp<bestmidp)
+ const int midp = (int)b3Fabs(b3Scalar(splitcount[i][0] - splitcount[i][1]));
+ if (midp < bestmidp)
{
- bestaxis=i;
- bestmidp=midp;
+ bestaxis = i;
+ bestmidp = midp;
}
}
}
- if(bestaxis>=0)
+ if (bestaxis >= 0)
{
- partition=b3Split(leaves,count,org,axis[bestaxis]);
- b3Assert(partition!=0 && partition!=count);
+ partition = b3Split(leaves, count, org, axis[bestaxis]);
+ b3Assert(partition != 0 && partition != count);
}
else
{
- partition=count/2+1;
+ partition = count / 2 + 1;
}
- b3DbvtNode* node=b3CreateNode(pdbvt,0,vol,0);
- node->childs[0]=b3TopDown(pdbvt,&leaves[0],partition,bu_treshold);
- node->childs[1]=b3TopDown(pdbvt,&leaves[partition],count-partition,bu_treshold);
- node->childs[0]->parent=node;
- node->childs[1]->parent=node;
- return(node);
+ b3DbvtNode* node = b3CreateNode(pdbvt, 0, vol, 0);
+ node->childs[0] = b3TopDown(pdbvt, &leaves[0], partition, bu_treshold);
+ node->childs[1] = b3TopDown(pdbvt, &leaves[partition], count - partition, bu_treshold);
+ node->childs[0]->parent = node;
+ node->childs[1]->parent = node;
+ return (node);
}
else
{
- b3BottomUp(pdbvt,leaves,count);
- return(leaves[0]);
+ b3BottomUp(pdbvt, leaves, count);
+ return (leaves[0]);
}
}
- return(leaves[0]);
+ return (leaves[0]);
}
//
-static B3_DBVT_INLINE b3DbvtNode* b3Sort(b3DbvtNode* n,b3DbvtNode*& r)
+static B3_DBVT_INLINE b3DbvtNode* b3Sort(b3DbvtNode* n, b3DbvtNode*& r)
{
- b3DbvtNode* p=n->parent;
+ b3DbvtNode* p = n->parent;
b3Assert(n->isinternal());
- if(p>n)
+ if (p > n)
{
- const int i=b3IndexOf(n);
- const int j=1-i;
- b3DbvtNode* s=p->childs[j];
- b3DbvtNode* q=p->parent;
- b3Assert(n==p->childs[i]);
- if(q) q->childs[b3IndexOf(p)]=n; else r=n;
- s->parent=n;
- p->parent=n;
- n->parent=q;
- p->childs[0]=n->childs[0];
- p->childs[1]=n->childs[1];
- n->childs[0]->parent=p;
- n->childs[1]->parent=p;
- n->childs[i]=p;
- n->childs[j]=s;
- b3Swap(p->volume,n->volume);
- return(p);
+ const int i = b3IndexOf(n);
+ const int j = 1 - i;
+ b3DbvtNode* s = p->childs[j];
+ b3DbvtNode* q = p->parent;
+ b3Assert(n == p->childs[i]);
+ if (q)
+ q->childs[b3IndexOf(p)] = n;
+ else
+ r = n;
+ s->parent = n;
+ p->parent = n;
+ n->parent = q;
+ p->childs[0] = n->childs[0];
+ p->childs[1] = n->childs[1];
+ n->childs[0]->parent = p;
+ n->childs[1]->parent = p;
+ n->childs[i] = p;
+ n->childs[j] = s;
+ b3Swap(p->volume, n->volume);
+ return (p);
}
- return(n);
+ return (n);
}
#if 0
@@ -438,11 +456,11 @@ static B3_DBVT_INLINE b3DbvtNode* walkup(b3DbvtNode* n,int count)
//
b3DynamicBvh::b3DynamicBvh()
{
- m_root = 0;
- m_free = 0;
- m_lkhd = -1;
- m_leaves = 0;
- m_opath = 0;
+ m_root = 0;
+ m_free = 0;
+ m_lkhd = -1;
+ m_leaves = 0;
+ m_opath = 0;
}
//
@@ -452,228 +470,233 @@ b3DynamicBvh::~b3DynamicBvh()
}
//
-void b3DynamicBvh::clear()
+void b3DynamicBvh::clear()
{
- if(m_root)
- b3RecurseDeleteNode(this,m_root);
+ if (m_root)
+ b3RecurseDeleteNode(this, m_root);
b3AlignedFree(m_free);
- m_free=0;
- m_lkhd = -1;
+ m_free = 0;
+ m_lkhd = -1;
m_stkStack.clear();
- m_opath = 0;
-
+ m_opath = 0;
}
//
-void b3DynamicBvh::optimizeBottomUp()
+void b3DynamicBvh::optimizeBottomUp()
{
- if(m_root)
+ if (m_root)
{
b3NodeArray leaves;
leaves.reserve(m_leaves);
- b3FetchLeaves(this,m_root,leaves);
- b3BottomUp(this,&leaves[0],leaves.size());
- m_root=leaves[0];
+ b3FetchLeaves(this, m_root, leaves);
+ b3BottomUp(this, &leaves[0], leaves.size());
+ m_root = leaves[0];
}
}
//
-void b3DynamicBvh::optimizeTopDown(int bu_treshold)
+void b3DynamicBvh::optimizeTopDown(int bu_treshold)
{
- if(m_root)
+ if (m_root)
{
- b3NodeArray leaves;
+ b3NodeArray leaves;
leaves.reserve(m_leaves);
- b3FetchLeaves(this,m_root,leaves);
- m_root=b3TopDown(this,&leaves[0],leaves.size(),bu_treshold);
+ b3FetchLeaves(this, m_root, leaves);
+ m_root = b3TopDown(this, &leaves[0], leaves.size(), bu_treshold);
}
}
//
-void b3DynamicBvh::optimizeIncremental(int passes)
+void b3DynamicBvh::optimizeIncremental(int passes)
{
- if(passes<0) passes=m_leaves;
- if(m_root&&(passes>0))
+ if (passes < 0) passes = m_leaves;
+ if (m_root && (passes > 0))
{
- do {
- b3DbvtNode* node=m_root;
- unsigned bit=0;
- while(node->isinternal())
+ do
+ {
+ b3DbvtNode* node = m_root;
+ unsigned bit = 0;
+ while (node->isinternal())
{
- node=b3Sort(node,m_root)->childs[(m_opath>>bit)&1];
- bit=(bit+1)&(sizeof(unsigned)*8-1);
+ node = b3Sort(node, m_root)->childs[(m_opath >> bit) & 1];
+ bit = (bit + 1) & (sizeof(unsigned) * 8 - 1);
}
update(node);
++m_opath;
- } while(--passes);
+ } while (--passes);
}
}
//
-b3DbvtNode* b3DynamicBvh::insert(const b3DbvtVolume& volume,void* data)
+b3DbvtNode* b3DynamicBvh::insert(const b3DbvtVolume& volume, void* data)
{
- b3DbvtNode* leaf=b3CreateNode(this,0,volume,data);
- b3InsertLeaf(this,m_root,leaf);
+ b3DbvtNode* leaf = b3CreateNode(this, 0, volume, data);
+ b3InsertLeaf(this, m_root, leaf);
++m_leaves;
- return(leaf);
+ return (leaf);
}
//
-void b3DynamicBvh::update(b3DbvtNode* leaf,int lookahead)
+void b3DynamicBvh::update(b3DbvtNode* leaf, int lookahead)
{
- b3DbvtNode* root=b3RemoveLeaf(this,leaf);
- if(root)
+ b3DbvtNode* root = b3RemoveLeaf(this, leaf);
+ if (root)
{
- if(lookahead>=0)
+ if (lookahead >= 0)
{
- for(int i=0;(i<lookahead)&&root->parent;++i)
+ for (int i = 0; (i < lookahead) && root->parent; ++i)
{
- root=root->parent;
+ root = root->parent;
}
- } else root=m_root;
+ }
+ else
+ root = m_root;
}
- b3InsertLeaf(this,root,leaf);
+ b3InsertLeaf(this, root, leaf);
}
//
-void b3DynamicBvh::update(b3DbvtNode* leaf,b3DbvtVolume& volume)
+void b3DynamicBvh::update(b3DbvtNode* leaf, b3DbvtVolume& volume)
{
- b3DbvtNode* root=b3RemoveLeaf(this,leaf);
- if(root)
+ b3DbvtNode* root = b3RemoveLeaf(this, leaf);
+ if (root)
{
- if(m_lkhd>=0)
+ if (m_lkhd >= 0)
{
- for(int i=0;(i<m_lkhd)&&root->parent;++i)
+ for (int i = 0; (i < m_lkhd) && root->parent; ++i)
{
- root=root->parent;
+ root = root->parent;
}
- } else root=m_root;
+ }
+ else
+ root = m_root;
}
- leaf->volume=volume;
- b3InsertLeaf(this,root,leaf);
+ leaf->volume = volume;
+ b3InsertLeaf(this, root, leaf);
}
//
-bool b3DynamicBvh::update(b3DbvtNode* leaf,b3DbvtVolume& volume,const b3Vector3& velocity,b3Scalar margin)
+bool b3DynamicBvh::update(b3DbvtNode* leaf, b3DbvtVolume& volume, const b3Vector3& velocity, b3Scalar margin)
{
- if(leaf->volume.Contain(volume)) return(false);
- volume.Expand(b3MakeVector3(margin,margin,margin));
+ if (leaf->volume.Contain(volume)) return (false);
+ volume.Expand(b3MakeVector3(margin, margin, margin));
volume.SignedExpand(velocity);
- update(leaf,volume);
- return(true);
+ update(leaf, volume);
+ return (true);
}
//
-bool b3DynamicBvh::update(b3DbvtNode* leaf,b3DbvtVolume& volume,const b3Vector3& velocity)
+bool b3DynamicBvh::update(b3DbvtNode* leaf, b3DbvtVolume& volume, const b3Vector3& velocity)
{
- if(leaf->volume.Contain(volume)) return(false);
+ if (leaf->volume.Contain(volume)) return (false);
volume.SignedExpand(velocity);
- update(leaf,volume);
- return(true);
+ update(leaf, volume);
+ return (true);
}
//
-bool b3DynamicBvh::update(b3DbvtNode* leaf,b3DbvtVolume& volume,b3Scalar margin)
+bool b3DynamicBvh::update(b3DbvtNode* leaf, b3DbvtVolume& volume, b3Scalar margin)
{
- if(leaf->volume.Contain(volume)) return(false);
- volume.Expand(b3MakeVector3(margin,margin,margin));
- update(leaf,volume);
- return(true);
+ if (leaf->volume.Contain(volume)) return (false);
+ volume.Expand(b3MakeVector3(margin, margin, margin));
+ update(leaf, volume);
+ return (true);
}
//
-void b3DynamicBvh::remove(b3DbvtNode* leaf)
+void b3DynamicBvh::remove(b3DbvtNode* leaf)
{
- b3RemoveLeaf(this,leaf);
- b3DeleteNode(this,leaf);
+ b3RemoveLeaf(this, leaf);
+ b3DeleteNode(this, leaf);
--m_leaves;
}
//
-void b3DynamicBvh::write(IWriter* iwriter) const
+void b3DynamicBvh::write(IWriter* iwriter) const
{
- b3DbvtNodeEnumerator nodes;
- nodes.nodes.reserve(m_leaves*2);
- enumNodes(m_root,nodes);
- iwriter->Prepare(m_root,nodes.nodes.size());
- for(int i=0;i<nodes.nodes.size();++i)
+ b3DbvtNodeEnumerator nodes;
+ nodes.nodes.reserve(m_leaves * 2);
+ enumNodes(m_root, nodes);
+ iwriter->Prepare(m_root, nodes.nodes.size());
+ for (int i = 0; i < nodes.nodes.size(); ++i)
{
- const b3DbvtNode* n=nodes.nodes[i];
- int p=-1;
- if(n->parent) p=nodes.nodes.findLinearSearch(n->parent);
- if(n->isinternal())
+ const b3DbvtNode* n = nodes.nodes[i];
+ int p = -1;
+ if (n->parent) p = nodes.nodes.findLinearSearch(n->parent);
+ if (n->isinternal())
{
- const int c0=nodes.nodes.findLinearSearch(n->childs[0]);
- const int c1=nodes.nodes.findLinearSearch(n->childs[1]);
- iwriter->WriteNode(n,i,p,c0,c1);
+ const int c0 = nodes.nodes.findLinearSearch(n->childs[0]);
+ const int c1 = nodes.nodes.findLinearSearch(n->childs[1]);
+ iwriter->WriteNode(n, i, p, c0, c1);
}
else
{
- iwriter->WriteLeaf(n,i,p);
- }
+ iwriter->WriteLeaf(n, i, p);
+ }
}
}
//
-void b3DynamicBvh::clone(b3DynamicBvh& dest,IClone* iclone) const
+void b3DynamicBvh::clone(b3DynamicBvh& dest, IClone* iclone) const
{
dest.clear();
- if(m_root!=0)
- {
- b3AlignedObjectArray<sStkCLN> stack;
+ if (m_root != 0)
+ {
+ b3AlignedObjectArray<sStkCLN> stack;
stack.reserve(m_leaves);
- stack.push_back(sStkCLN(m_root,0));
- do {
- const int i=stack.size()-1;
- const sStkCLN e=stack[i];
- b3DbvtNode* n=b3CreateNode(&dest,e.parent,e.node->volume,e.node->data);
+ stack.push_back(sStkCLN(m_root, 0));
+ do
+ {
+ const int i = stack.size() - 1;
+ const sStkCLN e = stack[i];
+ b3DbvtNode* n = b3CreateNode(&dest, e.parent, e.node->volume, e.node->data);
stack.pop_back();
- if(e.parent!=0)
- e.parent->childs[i&1]=n;
+ if (e.parent != 0)
+ e.parent->childs[i & 1] = n;
else
- dest.m_root=n;
- if(e.node->isinternal())
+ dest.m_root = n;
+ if (e.node->isinternal())
{
- stack.push_back(sStkCLN(e.node->childs[0],n));
- stack.push_back(sStkCLN(e.node->childs[1],n));
+ stack.push_back(sStkCLN(e.node->childs[0], n));
+ stack.push_back(sStkCLN(e.node->childs[1], n));
}
else
{
iclone->CloneLeaf(n);
}
- } while(stack.size()>0);
+ } while (stack.size() > 0);
}
}
//
-int b3DynamicBvh::maxdepth(const b3DbvtNode* node)
+int b3DynamicBvh::maxdepth(const b3DbvtNode* node)
{
- int depth=0;
- if(node) b3GetMaxDepth(node,1,depth);
- return(depth);
+ int depth = 0;
+ if (node) b3GetMaxDepth(node, 1, depth);
+ return (depth);
}
//
-int b3DynamicBvh::countLeaves(const b3DbvtNode* node)
+int b3DynamicBvh::countLeaves(const b3DbvtNode* node)
{
- if(node->isinternal())
- return(countLeaves(node->childs[0])+countLeaves(node->childs[1]));
+ if (node->isinternal())
+ return (countLeaves(node->childs[0]) + countLeaves(node->childs[1]));
else
- return(1);
+ return (1);
}
//
-void b3DynamicBvh::extractLeaves(const b3DbvtNode* node,b3AlignedObjectArray<const b3DbvtNode*>& leaves)
+void b3DynamicBvh::extractLeaves(const b3DbvtNode* node, b3AlignedObjectArray<const b3DbvtNode*>& leaves)
{
- if(node->isinternal())
+ if (node->isinternal())
{
- extractLeaves(node->childs[0],leaves);
- extractLeaves(node->childs[1],leaves);
+ extractLeaves(node->childs[0], leaves);
+ extractLeaves(node->childs[1], leaves);
}
else
{
leaves.push_back(node);
- }
+ }
}
//
@@ -682,7 +705,6 @@ void b3DynamicBvh::extractLeaves(const b3DbvtNode* node,b3AlignedObjectArray<c
#include <stdio.h>
#include <stdlib.h>
-
/*
q6600,2.4ghz
@@ -722,603 +744,608 @@ struct b3DbvtBenchmark
{
struct NilPolicy : b3DynamicBvh::ICollide
{
- NilPolicy() : m_pcount(0),m_depth(-B3_INFINITY),m_checksort(true) {}
- void Process(const b3DbvtNode*,const b3DbvtNode*) { ++m_pcount; }
- void Process(const b3DbvtNode*) { ++m_pcount; }
- void Process(const b3DbvtNode*,b3Scalar depth)
+ NilPolicy() : m_pcount(0), m_depth(-B3_INFINITY), m_checksort(true) {}
+ void Process(const b3DbvtNode*, const b3DbvtNode*) { ++m_pcount; }
+ void Process(const b3DbvtNode*) { ++m_pcount; }
+ void Process(const b3DbvtNode*, b3Scalar depth)
{
++m_pcount;
- if(m_checksort)
- { if(depth>=m_depth) m_depth=depth; else printf("wrong depth: %f (should be >= %f)\r\n",depth,m_depth); }
+ if (m_checksort)
+ {
+ if (depth >= m_depth)
+ m_depth = depth;
+ else
+ printf("wrong depth: %f (should be >= %f)\r\n", depth, m_depth);
+ }
}
- int m_pcount;
- b3Scalar m_depth;
- bool m_checksort;
+ int m_pcount;
+ b3Scalar m_depth;
+ bool m_checksort;
};
struct P14 : b3DynamicBvh::ICollide
{
struct Node
{
- const b3DbvtNode* leaf;
- b3Scalar depth;
+ const b3DbvtNode* leaf;
+ b3Scalar depth;
};
- void Process(const b3DbvtNode* leaf,b3Scalar depth)
+ void Process(const b3DbvtNode* leaf, b3Scalar depth)
{
- Node n;
- n.leaf = leaf;
- n.depth = depth;
+ Node n;
+ n.leaf = leaf;
+ n.depth = depth;
}
- static int sortfnc(const Node& a,const Node& b)
+ static int sortfnc(const Node& a, const Node& b)
{
- if(a.depth<b.depth) return(+1);
- if(a.depth>b.depth) return(-1);
- return(0);
+ if (a.depth < b.depth) return (+1);
+ if (a.depth > b.depth) return (-1);
+ return (0);
}
- b3AlignedObjectArray<Node> m_nodes;
+ b3AlignedObjectArray<Node> m_nodes;
};
struct P15 : b3DynamicBvh::ICollide
{
struct Node
{
- const b3DbvtNode* leaf;
- b3Scalar depth;
+ const b3DbvtNode* leaf;
+ b3Scalar depth;
};
void Process(const b3DbvtNode* leaf)
{
- Node n;
- n.leaf = leaf;
- n.depth = dot(leaf->volume.Center(),m_axis);
+ Node n;
+ n.leaf = leaf;
+ n.depth = dot(leaf->volume.Center(), m_axis);
}
- static int sortfnc(const Node& a,const Node& b)
+ static int sortfnc(const Node& a, const Node& b)
{
- if(a.depth<b.depth) return(+1);
- if(a.depth>b.depth) return(-1);
- return(0);
+ if (a.depth < b.depth) return (+1);
+ if (a.depth > b.depth) return (-1);
+ return (0);
}
- b3AlignedObjectArray<Node> m_nodes;
- b3Vector3 m_axis;
+ b3AlignedObjectArray<Node> m_nodes;
+ b3Vector3 m_axis;
};
- static b3Scalar RandUnit()
+ static b3Scalar RandUnit()
{
- return(rand()/(b3Scalar)RAND_MAX);
+ return (rand() / (b3Scalar)RAND_MAX);
}
- static b3Vector3 RandVector3()
+ static b3Vector3 RandVector3()
{
- return(b3Vector3(RandUnit(),RandUnit(),RandUnit()));
+ return (b3Vector3(RandUnit(), RandUnit(), RandUnit()));
}
- static b3Vector3 RandVector3(b3Scalar cs)
+ static b3Vector3 RandVector3(b3Scalar cs)
{
- return(RandVector3()*cs-b3Vector3(cs,cs,cs)/2);
+ return (RandVector3() * cs - b3Vector3(cs, cs, cs) / 2);
}
- static b3DbvtVolume RandVolume(b3Scalar cs,b3Scalar eb,b3Scalar es)
+ static b3DbvtVolume RandVolume(b3Scalar cs, b3Scalar eb, b3Scalar es)
{
- return(b3DbvtVolume::FromCE(RandVector3(cs),b3Vector3(eb,eb,eb)+RandVector3()*es));
+ return (b3DbvtVolume::FromCE(RandVector3(cs), b3Vector3(eb, eb, eb) + RandVector3() * es));
}
- static b3Transform RandTransform(b3Scalar cs)
+ static b3Transform RandTransform(b3Scalar cs)
{
- b3Transform t;
+ b3Transform t;
t.setOrigin(RandVector3(cs));
- t.setRotation(b3Quaternion(RandUnit()*B3_PI*2,RandUnit()*B3_PI*2,RandUnit()*B3_PI*2).normalized());
- return(t);
+ t.setRotation(b3Quaternion(RandUnit() * B3_PI * 2, RandUnit() * B3_PI * 2, RandUnit() * B3_PI * 2).normalized());
+ return (t);
}
- static void RandTree(b3Scalar cs,b3Scalar eb,b3Scalar es,int leaves,b3DynamicBvh& dbvt)
+ static void RandTree(b3Scalar cs, b3Scalar eb, b3Scalar es, int leaves, b3DynamicBvh& dbvt)
{
dbvt.clear();
- for(int i=0;i<leaves;++i)
+ for (int i = 0; i < leaves; ++i)
{
- dbvt.insert(RandVolume(cs,eb,es),0);
+ dbvt.insert(RandVolume(cs, eb, es), 0);
}
}
};
-void b3DynamicBvh::benchmark()
+void b3DynamicBvh::benchmark()
{
- static const b3Scalar cfgVolumeCenterScale = 100;
- static const b3Scalar cfgVolumeExentsBase = 1;
- static const b3Scalar cfgVolumeExentsScale = 4;
- static const int cfgLeaves = 8192;
- static const bool cfgEnable = true;
+ static const b3Scalar cfgVolumeCenterScale = 100;
+ static const b3Scalar cfgVolumeExentsBase = 1;
+ static const b3Scalar cfgVolumeExentsScale = 4;
+ static const int cfgLeaves = 8192;
+ static const bool cfgEnable = true;
//[1] b3DbvtVolume intersections
- bool cfgBenchmark1_Enable = cfgEnable;
- static const int cfgBenchmark1_Iterations = 8;
- static const int cfgBenchmark1_Reference = 3499;
+ bool cfgBenchmark1_Enable = cfgEnable;
+ static const int cfgBenchmark1_Iterations = 8;
+ static const int cfgBenchmark1_Reference = 3499;
//[2] b3DbvtVolume merges
- bool cfgBenchmark2_Enable = cfgEnable;
- static const int cfgBenchmark2_Iterations = 4;
- static const int cfgBenchmark2_Reference = 1945;
+ bool cfgBenchmark2_Enable = cfgEnable;
+ static const int cfgBenchmark2_Iterations = 4;
+ static const int cfgBenchmark2_Reference = 1945;
//[3] b3DynamicBvh::collideTT
- bool cfgBenchmark3_Enable = cfgEnable;
- static const int cfgBenchmark3_Iterations = 512;
- static const int cfgBenchmark3_Reference = 5485;
+ bool cfgBenchmark3_Enable = cfgEnable;
+ static const int cfgBenchmark3_Iterations = 512;
+ static const int cfgBenchmark3_Reference = 5485;
//[4] b3DynamicBvh::collideTT self
- bool cfgBenchmark4_Enable = cfgEnable;
- static const int cfgBenchmark4_Iterations = 512;
- static const int cfgBenchmark4_Reference = 2814;
+ bool cfgBenchmark4_Enable = cfgEnable;
+ static const int cfgBenchmark4_Iterations = 512;
+ static const int cfgBenchmark4_Reference = 2814;
//[5] b3DynamicBvh::collideTT xform
- bool cfgBenchmark5_Enable = cfgEnable;
- static const int cfgBenchmark5_Iterations = 512;
- static const b3Scalar cfgBenchmark5_OffsetScale = 2;
- static const int cfgBenchmark5_Reference = 7379;
+ bool cfgBenchmark5_Enable = cfgEnable;
+ static const int cfgBenchmark5_Iterations = 512;
+ static const b3Scalar cfgBenchmark5_OffsetScale = 2;
+ static const int cfgBenchmark5_Reference = 7379;
//[6] b3DynamicBvh::collideTT xform,self
- bool cfgBenchmark6_Enable = cfgEnable;
- static const int cfgBenchmark6_Iterations = 512;
- static const b3Scalar cfgBenchmark6_OffsetScale = 2;
- static const int cfgBenchmark6_Reference = 7270;
+ bool cfgBenchmark6_Enable = cfgEnable;
+ static const int cfgBenchmark6_Iterations = 512;
+ static const b3Scalar cfgBenchmark6_OffsetScale = 2;
+ static const int cfgBenchmark6_Reference = 7270;
//[7] b3DynamicBvh::rayTest
- bool cfgBenchmark7_Enable = cfgEnable;
- static const int cfgBenchmark7_Passes = 32;
- static const int cfgBenchmark7_Iterations = 65536;
- static const int cfgBenchmark7_Reference = 6307;
+ bool cfgBenchmark7_Enable = cfgEnable;
+ static const int cfgBenchmark7_Passes = 32;
+ static const int cfgBenchmark7_Iterations = 65536;
+ static const int cfgBenchmark7_Reference = 6307;
//[8] insert/remove
- bool cfgBenchmark8_Enable = cfgEnable;
- static const int cfgBenchmark8_Passes = 32;
- static const int cfgBenchmark8_Iterations = 65536;
- static const int cfgBenchmark8_Reference = 2105;
+ bool cfgBenchmark8_Enable = cfgEnable;
+ static const int cfgBenchmark8_Passes = 32;
+ static const int cfgBenchmark8_Iterations = 65536;
+ static const int cfgBenchmark8_Reference = 2105;
//[9] updates (teleport)
- bool cfgBenchmark9_Enable = cfgEnable;
- static const int cfgBenchmark9_Passes = 32;
- static const int cfgBenchmark9_Iterations = 65536;
- static const int cfgBenchmark9_Reference = 1879;
+ bool cfgBenchmark9_Enable = cfgEnable;
+ static const int cfgBenchmark9_Passes = 32;
+ static const int cfgBenchmark9_Iterations = 65536;
+ static const int cfgBenchmark9_Reference = 1879;
//[10] updates (jitter)
- bool cfgBenchmark10_Enable = cfgEnable;
- static const b3Scalar cfgBenchmark10_Scale = cfgVolumeCenterScale/10000;
- static const int cfgBenchmark10_Passes = 32;
- static const int cfgBenchmark10_Iterations = 65536;
- static const int cfgBenchmark10_Reference = 1244;
+ bool cfgBenchmark10_Enable = cfgEnable;
+ static const b3Scalar cfgBenchmark10_Scale = cfgVolumeCenterScale / 10000;
+ static const int cfgBenchmark10_Passes = 32;
+ static const int cfgBenchmark10_Iterations = 65536;
+ static const int cfgBenchmark10_Reference = 1244;
//[11] optimize (incremental)
- bool cfgBenchmark11_Enable = cfgEnable;
- static const int cfgBenchmark11_Passes = 64;
- static const int cfgBenchmark11_Iterations = 65536;
- static const int cfgBenchmark11_Reference = 2510;
+ bool cfgBenchmark11_Enable = cfgEnable;
+ static const int cfgBenchmark11_Passes = 64;
+ static const int cfgBenchmark11_Iterations = 65536;
+ static const int cfgBenchmark11_Reference = 2510;
//[12] b3DbvtVolume notequal
- bool cfgBenchmark12_Enable = cfgEnable;
- static const int cfgBenchmark12_Iterations = 32;
- static const int cfgBenchmark12_Reference = 3677;
+ bool cfgBenchmark12_Enable = cfgEnable;
+ static const int cfgBenchmark12_Iterations = 32;
+ static const int cfgBenchmark12_Reference = 3677;
//[13] culling(OCL+fullsort)
- bool cfgBenchmark13_Enable = cfgEnable;
- static const int cfgBenchmark13_Iterations = 1024;
- static const int cfgBenchmark13_Reference = 2231;
+ bool cfgBenchmark13_Enable = cfgEnable;
+ static const int cfgBenchmark13_Iterations = 1024;
+ static const int cfgBenchmark13_Reference = 2231;
//[14] culling(OCL+qsort)
- bool cfgBenchmark14_Enable = cfgEnable;
- static const int cfgBenchmark14_Iterations = 8192;
- static const int cfgBenchmark14_Reference = 3500;
+ bool cfgBenchmark14_Enable = cfgEnable;
+ static const int cfgBenchmark14_Iterations = 8192;
+ static const int cfgBenchmark14_Reference = 3500;
//[15] culling(KDOP+qsort)
- bool cfgBenchmark15_Enable = cfgEnable;
- static const int cfgBenchmark15_Iterations = 8192;
- static const int cfgBenchmark15_Reference = 1151;
+ bool cfgBenchmark15_Enable = cfgEnable;
+ static const int cfgBenchmark15_Iterations = 8192;
+ static const int cfgBenchmark15_Reference = 1151;
//[16] insert/remove batch
- bool cfgBenchmark16_Enable = cfgEnable;
- static const int cfgBenchmark16_BatchCount = 256;
- static const int cfgBenchmark16_Passes = 16384;
- static const int cfgBenchmark16_Reference = 5138;
+ bool cfgBenchmark16_Enable = cfgEnable;
+ static const int cfgBenchmark16_BatchCount = 256;
+ static const int cfgBenchmark16_Passes = 16384;
+ static const int cfgBenchmark16_Reference = 5138;
//[17] select
- bool cfgBenchmark17_Enable = cfgEnable;
- static const int cfgBenchmark17_Iterations = 4;
- static const int cfgBenchmark17_Reference = 3390;
+ bool cfgBenchmark17_Enable = cfgEnable;
+ static const int cfgBenchmark17_Iterations = 4;
+ static const int cfgBenchmark17_Reference = 3390;
- b3Clock wallclock;
+ b3Clock wallclock;
printf("Benchmarking dbvt...\r\n");
- printf("\tWorld scale: %f\r\n",cfgVolumeCenterScale);
- printf("\tExtents base: %f\r\n",cfgVolumeExentsBase);
- printf("\tExtents range: %f\r\n",cfgVolumeExentsScale);
- printf("\tLeaves: %u\r\n",cfgLeaves);
- printf("\tsizeof(b3DbvtVolume): %u bytes\r\n",sizeof(b3DbvtVolume));
- printf("\tsizeof(b3DbvtNode): %u bytes\r\n",sizeof(b3DbvtNode));
- if(cfgBenchmark1_Enable)
- {// Benchmark 1
+ printf("\tWorld scale: %f\r\n", cfgVolumeCenterScale);
+ printf("\tExtents base: %f\r\n", cfgVolumeExentsBase);
+ printf("\tExtents range: %f\r\n", cfgVolumeExentsScale);
+ printf("\tLeaves: %u\r\n", cfgLeaves);
+ printf("\tsizeof(b3DbvtVolume): %u bytes\r\n", sizeof(b3DbvtVolume));
+ printf("\tsizeof(b3DbvtNode): %u bytes\r\n", sizeof(b3DbvtNode));
+ if (cfgBenchmark1_Enable)
+ { // Benchmark 1
srand(380843);
- b3AlignedObjectArray<b3DbvtVolume> volumes;
- b3AlignedObjectArray<bool> results;
+ b3AlignedObjectArray<b3DbvtVolume> volumes;
+ b3AlignedObjectArray<bool> results;
volumes.resize(cfgLeaves);
results.resize(cfgLeaves);
- for(int i=0;i<cfgLeaves;++i)
+ for (int i = 0; i < cfgLeaves; ++i)
{
- volumes[i]=b3DbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
+ volumes[i] = b3DbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale);
}
printf("[1] b3DbvtVolume intersections: ");
wallclock.reset();
- for(int i=0;i<cfgBenchmark1_Iterations;++i)
+ for (int i = 0; i < cfgBenchmark1_Iterations; ++i)
{
- for(int j=0;j<cfgLeaves;++j)
+ for (int j = 0; j < cfgLeaves; ++j)
{
- for(int k=0;k<cfgLeaves;++k)
+ for (int k = 0; k < cfgLeaves; ++k)
{
- results[k]=Intersect(volumes[j],volumes[k]);
+ results[k] = Intersect(volumes[j], volumes[k]);
}
}
}
- const int time=(int)wallclock.getTimeMilliseconds();
- printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark1_Reference)*100/time);
+ const int time = (int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark1_Reference) * 100 / time);
}
- if(cfgBenchmark2_Enable)
- {// Benchmark 2
+ if (cfgBenchmark2_Enable)
+ { // Benchmark 2
srand(380843);
- b3AlignedObjectArray<b3DbvtVolume> volumes;
- b3AlignedObjectArray<b3DbvtVolume> results;
+ b3AlignedObjectArray<b3DbvtVolume> volumes;
+ b3AlignedObjectArray<b3DbvtVolume> results;
volumes.resize(cfgLeaves);
results.resize(cfgLeaves);
- for(int i=0;i<cfgLeaves;++i)
+ for (int i = 0; i < cfgLeaves; ++i)
{
- volumes[i]=b3DbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
+ volumes[i] = b3DbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale);
}
printf("[2] b3DbvtVolume merges: ");
wallclock.reset();
- for(int i=0;i<cfgBenchmark2_Iterations;++i)
+ for (int i = 0; i < cfgBenchmark2_Iterations; ++i)
{
- for(int j=0;j<cfgLeaves;++j)
+ for (int j = 0; j < cfgLeaves; ++j)
{
- for(int k=0;k<cfgLeaves;++k)
+ for (int k = 0; k < cfgLeaves; ++k)
{
- Merge(volumes[j],volumes[k],results[k]);
+ Merge(volumes[j], volumes[k], results[k]);
}
}
}
- const int time=(int)wallclock.getTimeMilliseconds();
- printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark2_Reference)*100/time);
+ const int time = (int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark2_Reference) * 100 / time);
}
- if(cfgBenchmark3_Enable)
- {// Benchmark 3
+ if (cfgBenchmark3_Enable)
+ { // Benchmark 3
srand(380843);
- b3DynamicBvh dbvt[2];
- b3DbvtBenchmark::NilPolicy policy;
- b3DbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[0]);
- b3DbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[1]);
+ b3DynamicBvh dbvt[2];
+ b3DbvtBenchmark::NilPolicy policy;
+ b3DbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt[0]);
+ b3DbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt[1]);
dbvt[0].optimizeTopDown();
dbvt[1].optimizeTopDown();
printf("[3] b3DynamicBvh::collideTT: ");
wallclock.reset();
- for(int i=0;i<cfgBenchmark3_Iterations;++i)
+ for (int i = 0; i < cfgBenchmark3_Iterations; ++i)
{
- b3DynamicBvh::collideTT(dbvt[0].m_root,dbvt[1].m_root,policy);
+ b3DynamicBvh::collideTT(dbvt[0].m_root, dbvt[1].m_root, policy);
}
- const int time=(int)wallclock.getTimeMilliseconds();
- printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark3_Reference)*100/time);
+ const int time = (int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark3_Reference) * 100 / time);
}
- if(cfgBenchmark4_Enable)
- {// Benchmark 4
+ if (cfgBenchmark4_Enable)
+ { // Benchmark 4
srand(380843);
- b3DynamicBvh dbvt;
- b3DbvtBenchmark::NilPolicy policy;
- b3DbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ b3DynamicBvh dbvt;
+ b3DbvtBenchmark::NilPolicy policy;
+ b3DbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
dbvt.optimizeTopDown();
printf("[4] b3DynamicBvh::collideTT self: ");
wallclock.reset();
- for(int i=0;i<cfgBenchmark4_Iterations;++i)
+ for (int i = 0; i < cfgBenchmark4_Iterations; ++i)
{
- b3DynamicBvh::collideTT(dbvt.m_root,dbvt.m_root,policy);
+ b3DynamicBvh::collideTT(dbvt.m_root, dbvt.m_root, policy);
}
- const int time=(int)wallclock.getTimeMilliseconds();
- printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark4_Reference)*100/time);
+ const int time = (int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark4_Reference) * 100 / time);
}
- if(cfgBenchmark5_Enable)
- {// Benchmark 5
+ if (cfgBenchmark5_Enable)
+ { // Benchmark 5
srand(380843);
- b3DynamicBvh dbvt[2];
- b3AlignedObjectArray<b3Transform> transforms;
- b3DbvtBenchmark::NilPolicy policy;
+ b3DynamicBvh dbvt[2];
+ b3AlignedObjectArray<b3Transform> transforms;
+ b3DbvtBenchmark::NilPolicy policy;
transforms.resize(cfgBenchmark5_Iterations);
- for(int i=0;i<transforms.size();++i)
+ for (int i = 0; i < transforms.size(); ++i)
{
- transforms[i]=b3DbvtBenchmark::RandTransform(cfgVolumeCenterScale*cfgBenchmark5_OffsetScale);
+ transforms[i] = b3DbvtBenchmark::RandTransform(cfgVolumeCenterScale * cfgBenchmark5_OffsetScale);
}
- b3DbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[0]);
- b3DbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[1]);
+ b3DbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt[0]);
+ b3DbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt[1]);
dbvt[0].optimizeTopDown();
dbvt[1].optimizeTopDown();
printf("[5] b3DynamicBvh::collideTT xform: ");
wallclock.reset();
- for(int i=0;i<cfgBenchmark5_Iterations;++i)
+ for (int i = 0; i < cfgBenchmark5_Iterations; ++i)
{
- b3DynamicBvh::collideTT(dbvt[0].m_root,dbvt[1].m_root,transforms[i],policy);
+ b3DynamicBvh::collideTT(dbvt[0].m_root, dbvt[1].m_root, transforms[i], policy);
}
- const int time=(int)wallclock.getTimeMilliseconds();
- printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark5_Reference)*100/time);
+ const int time = (int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark5_Reference) * 100 / time);
}
- if(cfgBenchmark6_Enable)
- {// Benchmark 6
+ if (cfgBenchmark6_Enable)
+ { // Benchmark 6
srand(380843);
- b3DynamicBvh dbvt;
- b3AlignedObjectArray<b3Transform> transforms;
- b3DbvtBenchmark::NilPolicy policy;
+ b3DynamicBvh dbvt;
+ b3AlignedObjectArray<b3Transform> transforms;
+ b3DbvtBenchmark::NilPolicy policy;
transforms.resize(cfgBenchmark6_Iterations);
- for(int i=0;i<transforms.size();++i)
+ for (int i = 0; i < transforms.size(); ++i)
{
- transforms[i]=b3DbvtBenchmark::RandTransform(cfgVolumeCenterScale*cfgBenchmark6_OffsetScale);
+ transforms[i] = b3DbvtBenchmark::RandTransform(cfgVolumeCenterScale * cfgBenchmark6_OffsetScale);
}
- b3DbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ b3DbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
dbvt.optimizeTopDown();
printf("[6] b3DynamicBvh::collideTT xform,self: ");
wallclock.reset();
- for(int i=0;i<cfgBenchmark6_Iterations;++i)
+ for (int i = 0; i < cfgBenchmark6_Iterations; ++i)
{
- b3DynamicBvh::collideTT(dbvt.m_root,dbvt.m_root,transforms[i],policy);
+ b3DynamicBvh::collideTT(dbvt.m_root, dbvt.m_root, transforms[i], policy);
}
- const int time=(int)wallclock.getTimeMilliseconds();
- printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark6_Reference)*100/time);
+ const int time = (int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark6_Reference) * 100 / time);
}
- if(cfgBenchmark7_Enable)
- {// Benchmark 7
+ if (cfgBenchmark7_Enable)
+ { // Benchmark 7
srand(380843);
- b3DynamicBvh dbvt;
- b3AlignedObjectArray<b3Vector3> rayorg;
- b3AlignedObjectArray<b3Vector3> raydir;
- b3DbvtBenchmark::NilPolicy policy;
+ b3DynamicBvh dbvt;
+ b3AlignedObjectArray<b3Vector3> rayorg;
+ b3AlignedObjectArray<b3Vector3> raydir;
+ b3DbvtBenchmark::NilPolicy policy;
rayorg.resize(cfgBenchmark7_Iterations);
raydir.resize(cfgBenchmark7_Iterations);
- for(int i=0;i<rayorg.size();++i)
+ for (int i = 0; i < rayorg.size(); ++i)
{
- rayorg[i]=b3DbvtBenchmark::RandVector3(cfgVolumeCenterScale*2);
- raydir[i]=b3DbvtBenchmark::RandVector3(cfgVolumeCenterScale*2);
+ rayorg[i] = b3DbvtBenchmark::RandVector3(cfgVolumeCenterScale * 2);
+ raydir[i] = b3DbvtBenchmark::RandVector3(cfgVolumeCenterScale * 2);
}
- b3DbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ b3DbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
dbvt.optimizeTopDown();
printf("[7] b3DynamicBvh::rayTest: ");
wallclock.reset();
- for(int i=0;i<cfgBenchmark7_Passes;++i)
+ for (int i = 0; i < cfgBenchmark7_Passes; ++i)
{
- for(int j=0;j<cfgBenchmark7_Iterations;++j)
+ for (int j = 0; j < cfgBenchmark7_Iterations; ++j)
{
- b3DynamicBvh::rayTest(dbvt.m_root,rayorg[j],rayorg[j]+raydir[j],policy);
+ b3DynamicBvh::rayTest(dbvt.m_root, rayorg[j], rayorg[j] + raydir[j], policy);
}
}
- const int time=(int)wallclock.getTimeMilliseconds();
- unsigned rays=cfgBenchmark7_Passes*cfgBenchmark7_Iterations;
- printf("%u ms (%i%%),(%u r/s)\r\n",time,(time-cfgBenchmark7_Reference)*100/time,(rays*1000)/time);
+ const int time = (int)wallclock.getTimeMilliseconds();
+ unsigned rays = cfgBenchmark7_Passes * cfgBenchmark7_Iterations;
+ printf("%u ms (%i%%),(%u r/s)\r\n", time, (time - cfgBenchmark7_Reference) * 100 / time, (rays * 1000) / time);
}
- if(cfgBenchmark8_Enable)
- {// Benchmark 8
+ if (cfgBenchmark8_Enable)
+ { // Benchmark 8
srand(380843);
- b3DynamicBvh dbvt;
- b3DbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ b3DynamicBvh dbvt;
+ b3DbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
dbvt.optimizeTopDown();
printf("[8] insert/remove: ");
wallclock.reset();
- for(int i=0;i<cfgBenchmark8_Passes;++i)
+ for (int i = 0; i < cfgBenchmark8_Passes; ++i)
{
- for(int j=0;j<cfgBenchmark8_Iterations;++j)
+ for (int j = 0; j < cfgBenchmark8_Iterations; ++j)
{
- dbvt.remove(dbvt.insert(b3DbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale),0));
+ dbvt.remove(dbvt.insert(b3DbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale), 0));
}
}
- const int time=(int)wallclock.getTimeMilliseconds();
- const int ir=cfgBenchmark8_Passes*cfgBenchmark8_Iterations;
- printf("%u ms (%i%%),(%u ir/s)\r\n",time,(time-cfgBenchmark8_Reference)*100/time,ir*1000/time);
+ const int time = (int)wallclock.getTimeMilliseconds();
+ const int ir = cfgBenchmark8_Passes * cfgBenchmark8_Iterations;
+ printf("%u ms (%i%%),(%u ir/s)\r\n", time, (time - cfgBenchmark8_Reference) * 100 / time, ir * 1000 / time);
}
- if(cfgBenchmark9_Enable)
- {// Benchmark 9
+ if (cfgBenchmark9_Enable)
+ { // Benchmark 9
srand(380843);
- b3DynamicBvh dbvt;
- b3AlignedObjectArray<const b3DbvtNode*> leaves;
- b3DbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ b3DynamicBvh dbvt;
+ b3AlignedObjectArray<const b3DbvtNode*> leaves;
+ b3DbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
dbvt.optimizeTopDown();
- dbvt.extractLeaves(dbvt.m_root,leaves);
+ dbvt.extractLeaves(dbvt.m_root, leaves);
printf("[9] updates (teleport): ");
wallclock.reset();
- for(int i=0;i<cfgBenchmark9_Passes;++i)
+ for (int i = 0; i < cfgBenchmark9_Passes; ++i)
{
- for(int j=0;j<cfgBenchmark9_Iterations;++j)
+ for (int j = 0; j < cfgBenchmark9_Iterations; ++j)
{
- dbvt.update(const_cast<b3DbvtNode*>(leaves[rand()%cfgLeaves]),
- b3DbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale));
+ dbvt.update(const_cast<b3DbvtNode*>(leaves[rand() % cfgLeaves]),
+ b3DbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale));
}
}
- const int time=(int)wallclock.getTimeMilliseconds();
- const int up=cfgBenchmark9_Passes*cfgBenchmark9_Iterations;
- printf("%u ms (%i%%),(%u u/s)\r\n",time,(time-cfgBenchmark9_Reference)*100/time,up*1000/time);
+ const int time = (int)wallclock.getTimeMilliseconds();
+ const int up = cfgBenchmark9_Passes * cfgBenchmark9_Iterations;
+ printf("%u ms (%i%%),(%u u/s)\r\n", time, (time - cfgBenchmark9_Reference) * 100 / time, up * 1000 / time);
}
- if(cfgBenchmark10_Enable)
- {// Benchmark 10
+ if (cfgBenchmark10_Enable)
+ { // Benchmark 10
srand(380843);
- b3DynamicBvh dbvt;
- b3AlignedObjectArray<const b3DbvtNode*> leaves;
- b3AlignedObjectArray<b3Vector3> vectors;
+ b3DynamicBvh dbvt;
+ b3AlignedObjectArray<const b3DbvtNode*> leaves;
+ b3AlignedObjectArray<b3Vector3> vectors;
vectors.resize(cfgBenchmark10_Iterations);
- for(int i=0;i<vectors.size();++i)
+ for (int i = 0; i < vectors.size(); ++i)
{
- vectors[i]=(b3DbvtBenchmark::RandVector3()*2-b3Vector3(1,1,1))*cfgBenchmark10_Scale;
+ vectors[i] = (b3DbvtBenchmark::RandVector3() * 2 - b3Vector3(1, 1, 1)) * cfgBenchmark10_Scale;
}
- b3DbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ b3DbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
dbvt.optimizeTopDown();
- dbvt.extractLeaves(dbvt.m_root,leaves);
+ dbvt.extractLeaves(dbvt.m_root, leaves);
printf("[10] updates (jitter): ");
wallclock.reset();
- for(int i=0;i<cfgBenchmark10_Passes;++i)
+ for (int i = 0; i < cfgBenchmark10_Passes; ++i)
{
- for(int j=0;j<cfgBenchmark10_Iterations;++j)
- {
- const b3Vector3& d=vectors[j];
- b3DbvtNode* l=const_cast<b3DbvtNode*>(leaves[rand()%cfgLeaves]);
- b3DbvtVolume v=b3DbvtVolume::FromMM(l->volume.Mins()+d,l->volume.Maxs()+d);
- dbvt.update(l,v);
+ for (int j = 0; j < cfgBenchmark10_Iterations; ++j)
+ {
+ const b3Vector3& d = vectors[j];
+ b3DbvtNode* l = const_cast<b3DbvtNode*>(leaves[rand() % cfgLeaves]);
+ b3DbvtVolume v = b3DbvtVolume::FromMM(l->volume.Mins() + d, l->volume.Maxs() + d);
+ dbvt.update(l, v);
}
}
- const int time=(int)wallclock.getTimeMilliseconds();
- const int up=cfgBenchmark10_Passes*cfgBenchmark10_Iterations;
- printf("%u ms (%i%%),(%u u/s)\r\n",time,(time-cfgBenchmark10_Reference)*100/time,up*1000/time);
+ const int time = (int)wallclock.getTimeMilliseconds();
+ const int up = cfgBenchmark10_Passes * cfgBenchmark10_Iterations;
+ printf("%u ms (%i%%),(%u u/s)\r\n", time, (time - cfgBenchmark10_Reference) * 100 / time, up * 1000 / time);
}
- if(cfgBenchmark11_Enable)
- {// Benchmark 11
+ if (cfgBenchmark11_Enable)
+ { // Benchmark 11
srand(380843);
- b3DynamicBvh dbvt;
- b3DbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ b3DynamicBvh dbvt;
+ b3DbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
dbvt.optimizeTopDown();
printf("[11] optimize (incremental): ");
- wallclock.reset();
- for(int i=0;i<cfgBenchmark11_Passes;++i)
+ wallclock.reset();
+ for (int i = 0; i < cfgBenchmark11_Passes; ++i)
{
dbvt.optimizeIncremental(cfgBenchmark11_Iterations);
}
- const int time=(int)wallclock.getTimeMilliseconds();
- const int op=cfgBenchmark11_Passes*cfgBenchmark11_Iterations;
- printf("%u ms (%i%%),(%u o/s)\r\n",time,(time-cfgBenchmark11_Reference)*100/time,op/time*1000);
+ const int time = (int)wallclock.getTimeMilliseconds();
+ const int op = cfgBenchmark11_Passes * cfgBenchmark11_Iterations;
+ printf("%u ms (%i%%),(%u o/s)\r\n", time, (time - cfgBenchmark11_Reference) * 100 / time, op / time * 1000);
}
- if(cfgBenchmark12_Enable)
- {// Benchmark 12
+ if (cfgBenchmark12_Enable)
+ { // Benchmark 12
srand(380843);
- b3AlignedObjectArray<b3DbvtVolume> volumes;
- b3AlignedObjectArray<bool> results;
+ b3AlignedObjectArray<b3DbvtVolume> volumes;
+ b3AlignedObjectArray<bool> results;
volumes.resize(cfgLeaves);
results.resize(cfgLeaves);
- for(int i=0;i<cfgLeaves;++i)
+ for (int i = 0; i < cfgLeaves; ++i)
{
- volumes[i]=b3DbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
+ volumes[i] = b3DbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale);
}
printf("[12] b3DbvtVolume notequal: ");
wallclock.reset();
- for(int i=0;i<cfgBenchmark12_Iterations;++i)
+ for (int i = 0; i < cfgBenchmark12_Iterations; ++i)
{
- for(int j=0;j<cfgLeaves;++j)
+ for (int j = 0; j < cfgLeaves; ++j)
{
- for(int k=0;k<cfgLeaves;++k)
+ for (int k = 0; k < cfgLeaves; ++k)
{
- results[k]=NotEqual(volumes[j],volumes[k]);
+ results[k] = NotEqual(volumes[j], volumes[k]);
}
}
}
- const int time=(int)wallclock.getTimeMilliseconds();
- printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark12_Reference)*100/time);
+ const int time = (int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark12_Reference) * 100 / time);
}
- if(cfgBenchmark13_Enable)
- {// Benchmark 13
+ if (cfgBenchmark13_Enable)
+ { // Benchmark 13
srand(380843);
- b3DynamicBvh dbvt;
- b3AlignedObjectArray<b3Vector3> vectors;
- b3DbvtBenchmark::NilPolicy policy;
+ b3DynamicBvh dbvt;
+ b3AlignedObjectArray<b3Vector3> vectors;
+ b3DbvtBenchmark::NilPolicy policy;
vectors.resize(cfgBenchmark13_Iterations);
- for(int i=0;i<vectors.size();++i)
+ for (int i = 0; i < vectors.size(); ++i)
{
- vectors[i]=(b3DbvtBenchmark::RandVector3()*2-b3Vector3(1,1,1)).normalized();
+ vectors[i] = (b3DbvtBenchmark::RandVector3() * 2 - b3Vector3(1, 1, 1)).normalized();
}
- b3DbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ b3DbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
dbvt.optimizeTopDown();
printf("[13] culling(OCL+fullsort): ");
- wallclock.reset();
- for(int i=0;i<cfgBenchmark13_Iterations;++i)
+ wallclock.reset();
+ for (int i = 0; i < cfgBenchmark13_Iterations; ++i)
{
- static const b3Scalar offset=0;
- policy.m_depth=-B3_INFINITY;
- dbvt.collideOCL(dbvt.m_root,&vectors[i],&offset,vectors[i],1,policy);
+ static const b3Scalar offset = 0;
+ policy.m_depth = -B3_INFINITY;
+ dbvt.collideOCL(dbvt.m_root, &vectors[i], &offset, vectors[i], 1, policy);
}
- const int time=(int)wallclock.getTimeMilliseconds();
- const int t=cfgBenchmark13_Iterations;
- printf("%u ms (%i%%),(%u t/s)\r\n",time,(time-cfgBenchmark13_Reference)*100/time,(t*1000)/time);
+ const int time = (int)wallclock.getTimeMilliseconds();
+ const int t = cfgBenchmark13_Iterations;
+ printf("%u ms (%i%%),(%u t/s)\r\n", time, (time - cfgBenchmark13_Reference) * 100 / time, (t * 1000) / time);
}
- if(cfgBenchmark14_Enable)
- {// Benchmark 14
+ if (cfgBenchmark14_Enable)
+ { // Benchmark 14
srand(380843);
- b3DynamicBvh dbvt;
- b3AlignedObjectArray<b3Vector3> vectors;
- b3DbvtBenchmark::P14 policy;
+ b3DynamicBvh dbvt;
+ b3AlignedObjectArray<b3Vector3> vectors;
+ b3DbvtBenchmark::P14 policy;
vectors.resize(cfgBenchmark14_Iterations);
- for(int i=0;i<vectors.size();++i)
+ for (int i = 0; i < vectors.size(); ++i)
{
- vectors[i]=(b3DbvtBenchmark::RandVector3()*2-b3Vector3(1,1,1)).normalized();
+ vectors[i] = (b3DbvtBenchmark::RandVector3() * 2 - b3Vector3(1, 1, 1)).normalized();
}
- b3DbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ b3DbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
dbvt.optimizeTopDown();
policy.m_nodes.reserve(cfgLeaves);
printf("[14] culling(OCL+qsort): ");
- wallclock.reset();
- for(int i=0;i<cfgBenchmark14_Iterations;++i)
+ wallclock.reset();
+ for (int i = 0; i < cfgBenchmark14_Iterations; ++i)
{
- static const b3Scalar offset=0;
+ static const b3Scalar offset = 0;
policy.m_nodes.resize(0);
- dbvt.collideOCL(dbvt.m_root,&vectors[i],&offset,vectors[i],1,policy,false);
+ dbvt.collideOCL(dbvt.m_root, &vectors[i], &offset, vectors[i], 1, policy, false);
policy.m_nodes.quickSort(b3DbvtBenchmark::P14::sortfnc);
}
- const int time=(int)wallclock.getTimeMilliseconds();
- const int t=cfgBenchmark14_Iterations;
- printf("%u ms (%i%%),(%u t/s)\r\n",time,(time-cfgBenchmark14_Reference)*100/time,(t*1000)/time);
+ const int time = (int)wallclock.getTimeMilliseconds();
+ const int t = cfgBenchmark14_Iterations;
+ printf("%u ms (%i%%),(%u t/s)\r\n", time, (time - cfgBenchmark14_Reference) * 100 / time, (t * 1000) / time);
}
- if(cfgBenchmark15_Enable)
- {// Benchmark 15
+ if (cfgBenchmark15_Enable)
+ { // Benchmark 15
srand(380843);
- b3DynamicBvh dbvt;
- b3AlignedObjectArray<b3Vector3> vectors;
- b3DbvtBenchmark::P15 policy;
+ b3DynamicBvh dbvt;
+ b3AlignedObjectArray<b3Vector3> vectors;
+ b3DbvtBenchmark::P15 policy;
vectors.resize(cfgBenchmark15_Iterations);
- for(int i=0;i<vectors.size();++i)
+ for (int i = 0; i < vectors.size(); ++i)
{
- vectors[i]=(b3DbvtBenchmark::RandVector3()*2-b3Vector3(1,1,1)).normalized();
+ vectors[i] = (b3DbvtBenchmark::RandVector3() * 2 - b3Vector3(1, 1, 1)).normalized();
}
- b3DbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ b3DbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
dbvt.optimizeTopDown();
policy.m_nodes.reserve(cfgLeaves);
printf("[15] culling(KDOP+qsort): ");
- wallclock.reset();
- for(int i=0;i<cfgBenchmark15_Iterations;++i)
+ wallclock.reset();
+ for (int i = 0; i < cfgBenchmark15_Iterations; ++i)
{
- static const b3Scalar offset=0;
+ static const b3Scalar offset = 0;
policy.m_nodes.resize(0);
- policy.m_axis=vectors[i];
- dbvt.collideKDOP(dbvt.m_root,&vectors[i],&offset,1,policy);
+ policy.m_axis = vectors[i];
+ dbvt.collideKDOP(dbvt.m_root, &vectors[i], &offset, 1, policy);
policy.m_nodes.quickSort(b3DbvtBenchmark::P15::sortfnc);
}
- const int time=(int)wallclock.getTimeMilliseconds();
- const int t=cfgBenchmark15_Iterations;
- printf("%u ms (%i%%),(%u t/s)\r\n",time,(time-cfgBenchmark15_Reference)*100/time,(t*1000)/time);
+ const int time = (int)wallclock.getTimeMilliseconds();
+ const int t = cfgBenchmark15_Iterations;
+ printf("%u ms (%i%%),(%u t/s)\r\n", time, (time - cfgBenchmark15_Reference) * 100 / time, (t * 1000) / time);
}
- if(cfgBenchmark16_Enable)
- {// Benchmark 16
+ if (cfgBenchmark16_Enable)
+ { // Benchmark 16
srand(380843);
- b3DynamicBvh dbvt;
- b3AlignedObjectArray<b3DbvtNode*> batch;
- b3DbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ b3DynamicBvh dbvt;
+ b3AlignedObjectArray<b3DbvtNode*> batch;
+ b3DbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
dbvt.optimizeTopDown();
batch.reserve(cfgBenchmark16_BatchCount);
- printf("[16] insert/remove batch(%u): ",cfgBenchmark16_BatchCount);
+ printf("[16] insert/remove batch(%u): ", cfgBenchmark16_BatchCount);
wallclock.reset();
- for(int i=0;i<cfgBenchmark16_Passes;++i)
+ for (int i = 0; i < cfgBenchmark16_Passes; ++i)
{
- for(int j=0;j<cfgBenchmark16_BatchCount;++j)
+ for (int j = 0; j < cfgBenchmark16_BatchCount; ++j)
{
- batch.push_back(dbvt.insert(b3DbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale),0));
+ batch.push_back(dbvt.insert(b3DbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale), 0));
}
- for(int j=0;j<cfgBenchmark16_BatchCount;++j)
+ for (int j = 0; j < cfgBenchmark16_BatchCount; ++j)
{
dbvt.remove(batch[j]);
}
batch.resize(0);
}
- const int time=(int)wallclock.getTimeMilliseconds();
- const int ir=cfgBenchmark16_Passes*cfgBenchmark16_BatchCount;
- printf("%u ms (%i%%),(%u bir/s)\r\n",time,(time-cfgBenchmark16_Reference)*100/time,int(ir*1000.0/time));
+ const int time = (int)wallclock.getTimeMilliseconds();
+ const int ir = cfgBenchmark16_Passes * cfgBenchmark16_BatchCount;
+ printf("%u ms (%i%%),(%u bir/s)\r\n", time, (time - cfgBenchmark16_Reference) * 100 / time, int(ir * 1000.0 / time));
}
- if(cfgBenchmark17_Enable)
- {// Benchmark 17
+ if (cfgBenchmark17_Enable)
+ { // Benchmark 17
srand(380843);
- b3AlignedObjectArray<b3DbvtVolume> volumes;
- b3AlignedObjectArray<int> results;
- b3AlignedObjectArray<int> indices;
+ b3AlignedObjectArray<b3DbvtVolume> volumes;
+ b3AlignedObjectArray<int> results;
+ b3AlignedObjectArray<int> indices;
volumes.resize(cfgLeaves);
results.resize(cfgLeaves);
indices.resize(cfgLeaves);
- for(int i=0;i<cfgLeaves;++i)
+ for (int i = 0; i < cfgLeaves; ++i)
{
- indices[i]=i;
- volumes[i]=b3DbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
+ indices[i] = i;
+ volumes[i] = b3DbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale);
}
- for(int i=0;i<cfgLeaves;++i)
+ for (int i = 0; i < cfgLeaves; ++i)
{
- b3Swap(indices[i],indices[rand()%cfgLeaves]);
+ b3Swap(indices[i], indices[rand() % cfgLeaves]);
}
printf("[17] b3DbvtVolume select: ");
wallclock.reset();
- for(int i=0;i<cfgBenchmark17_Iterations;++i)
+ for (int i = 0; i < cfgBenchmark17_Iterations; ++i)
{
- for(int j=0;j<cfgLeaves;++j)
+ for (int j = 0; j < cfgLeaves; ++j)
{
- for(int k=0;k<cfgLeaves;++k)
+ for (int k = 0; k < cfgLeaves; ++k)
{
- const int idx=indices[k];
- results[idx]=Select(volumes[idx],volumes[j],volumes[k]);
+ const int idx = indices[k];
+ results[idx] = Select(volumes[idx], volumes[j], volumes[k]);
}
}
}
- const int time=(int)wallclock.getTimeMilliseconds();
- printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark17_Reference)*100/time);
+ const int time = (int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark17_Reference) * 100 / time);
}
printf("\r\n\r\n");
}
diff --git a/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.h b/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.h
index c004b9130f..f44e3377fe 100644
--- a/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.h
+++ b/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.h
@@ -26,50 +26,49 @@ subject to the following restrictions:
// Compile time configuration
//
-
// Implementation profiles
-#define B3_DBVT_IMPL_GENERIC 0 // Generic implementation
-#define B3_DBVT_IMPL_SSE 1 // SSE
+#define B3_DBVT_IMPL_GENERIC 0 // Generic implementation
+#define B3_DBVT_IMPL_SSE 1 // SSE
// Template implementation of ICollide
#ifdef _WIN32
-#if (defined (_MSC_VER) && _MSC_VER >= 1400)
-#define B3_DBVT_USE_TEMPLATE 1
+#if (defined(_MSC_VER) && _MSC_VER >= 1400)
+#define B3_DBVT_USE_TEMPLATE 1
#else
-#define B3_DBVT_USE_TEMPLATE 0
+#define B3_DBVT_USE_TEMPLATE 0
#endif
#else
-#define B3_DBVT_USE_TEMPLATE 0
+#define B3_DBVT_USE_TEMPLATE 0
#endif
// Use only intrinsics instead of inline asm
-#define B3_DBVT_USE_INTRINSIC_SSE 1
+#define B3_DBVT_USE_INTRINSIC_SSE 1
// Using memmov for collideOCL
-#define B3_DBVT_USE_MEMMOVE 1
+#define B3_DBVT_USE_MEMMOVE 1
// Enable benchmarking code
-#define B3_DBVT_ENABLE_BENCHMARK 0
+#define B3_DBVT_ENABLE_BENCHMARK 0
// Inlining
-#define B3_DBVT_INLINE B3_FORCE_INLINE
+#define B3_DBVT_INLINE B3_FORCE_INLINE
// Specific methods implementation
//SSE gives errors on a MSVC 7.1
-#if defined (B3_USE_SSE) //&& defined (_WIN32)
-#define B3_DBVT_SELECT_IMPL B3_DBVT_IMPL_SSE
-#define B3_DBVT_MERGE_IMPL B3_DBVT_IMPL_SSE
-#define B3_DBVT_INT0_IMPL B3_DBVT_IMPL_SSE
+#if defined(B3_USE_SSE) //&& defined (_WIN32)
+#define B3_DBVT_SELECT_IMPL B3_DBVT_IMPL_SSE
+#define B3_DBVT_MERGE_IMPL B3_DBVT_IMPL_SSE
+#define B3_DBVT_INT0_IMPL B3_DBVT_IMPL_SSE
#else
-#define B3_DBVT_SELECT_IMPL B3_DBVT_IMPL_GENERIC
-#define B3_DBVT_MERGE_IMPL B3_DBVT_IMPL_GENERIC
-#define B3_DBVT_INT0_IMPL B3_DBVT_IMPL_GENERIC
+#define B3_DBVT_SELECT_IMPL B3_DBVT_IMPL_GENERIC
+#define B3_DBVT_MERGE_IMPL B3_DBVT_IMPL_GENERIC
+#define B3_DBVT_INT0_IMPL B3_DBVT_IMPL_GENERIC
#endif
-#if (B3_DBVT_SELECT_IMPL==B3_DBVT_IMPL_SSE)|| \
- (B3_DBVT_MERGE_IMPL==B3_DBVT_IMPL_SSE)|| \
- (B3_DBVT_INT0_IMPL==B3_DBVT_IMPL_SSE)
+#if (B3_DBVT_SELECT_IMPL == B3_DBVT_IMPL_SSE) || \
+ (B3_DBVT_MERGE_IMPL == B3_DBVT_IMPL_SSE) || \
+ (B3_DBVT_INT0_IMPL == B3_DBVT_IMPL_SSE)
#include <emmintrin.h>
#endif
@@ -78,21 +77,24 @@ subject to the following restrictions:
//
#if B3_DBVT_USE_TEMPLATE
-#define B3_DBVT_VIRTUAL
+#define B3_DBVT_VIRTUAL
#define B3_DBVT_VIRTUAL_DTOR(a)
-#define B3_DBVT_PREFIX template <typename T>
-#define B3_DBVT_IPOLICY T& policy
-#define B3_DBVT_CHECKTYPE static const ICollide& typechecker=*(T*)1;(void)typechecker;
+#define B3_DBVT_PREFIX template <typename T>
+#define B3_DBVT_IPOLICY T& policy
+#define B3_DBVT_CHECKTYPE \
+ static const ICollide& typechecker = *(T*)1; \
+ (void)typechecker;
#else
-#define B3_DBVT_VIRTUAL_DTOR(a) virtual ~a() {}
-#define B3_DBVT_VIRTUAL virtual
+#define B3_DBVT_VIRTUAL_DTOR(a) \
+ virtual ~a() {}
+#define B3_DBVT_VIRTUAL virtual
#define B3_DBVT_PREFIX
-#define B3_DBVT_IPOLICY ICollide& policy
+#define B3_DBVT_IPOLICY ICollide& policy
#define B3_DBVT_CHECKTYPE
#endif
#if B3_DBVT_USE_MEMMOVE
-#if !defined( __CELLOS_LV2__) && !defined(__MWERKS__)
+#if !defined(__CELLOS_LV2__) && !defined(__MWERKS__)
#include <memory.h>
#endif
#include <string.h>
@@ -126,187 +128,188 @@ subject to the following restrictions:
// Defaults volumes
//
-/* b3DbvtAabbMm */
-struct b3DbvtAabbMm
+/* b3DbvtAabbMm */
+struct b3DbvtAabbMm
{
- B3_DBVT_INLINE b3Vector3 Center() const { return((mi+mx)/2); }
- B3_DBVT_INLINE b3Vector3 Lengths() const { return(mx-mi); }
- B3_DBVT_INLINE b3Vector3 Extents() const { return((mx-mi)/2); }
- B3_DBVT_INLINE const b3Vector3& Mins() const { return(mi); }
- B3_DBVT_INLINE const b3Vector3& Maxs() const { return(mx); }
- static inline b3DbvtAabbMm FromCE(const b3Vector3& c,const b3Vector3& e);
- static inline b3DbvtAabbMm FromCR(const b3Vector3& c,b3Scalar r);
- static inline b3DbvtAabbMm FromMM(const b3Vector3& mi,const b3Vector3& mx);
- static inline b3DbvtAabbMm FromPoints(const b3Vector3* pts,int n);
- static inline b3DbvtAabbMm FromPoints(const b3Vector3** ppts,int n);
- B3_DBVT_INLINE void Expand(const b3Vector3& e);
- B3_DBVT_INLINE void SignedExpand(const b3Vector3& e);
- B3_DBVT_INLINE bool Contain(const b3DbvtAabbMm& a) const;
- B3_DBVT_INLINE int Classify(const b3Vector3& n,b3Scalar o,int s) const;
- B3_DBVT_INLINE b3Scalar ProjectMinimum(const b3Vector3& v,unsigned signs) const;
- B3_DBVT_INLINE friend bool b3Intersect( const b3DbvtAabbMm& a,
- const b3DbvtAabbMm& b);
-
- B3_DBVT_INLINE friend bool b3Intersect( const b3DbvtAabbMm& a,
- const b3Vector3& b);
-
- B3_DBVT_INLINE friend b3Scalar b3Proximity( const b3DbvtAabbMm& a,
- const b3DbvtAabbMm& b);
- B3_DBVT_INLINE friend int b3Select( const b3DbvtAabbMm& o,
- const b3DbvtAabbMm& a,
- const b3DbvtAabbMm& b);
- B3_DBVT_INLINE friend void b3Merge( const b3DbvtAabbMm& a,
- const b3DbvtAabbMm& b,
- b3DbvtAabbMm& r);
- B3_DBVT_INLINE friend bool b3NotEqual( const b3DbvtAabbMm& a,
- const b3DbvtAabbMm& b);
-
- B3_DBVT_INLINE b3Vector3& tMins() { return(mi); }
- B3_DBVT_INLINE b3Vector3& tMaxs() { return(mx); }
-
+ B3_DBVT_INLINE b3Vector3 Center() const { return ((mi + mx) / 2); }
+ B3_DBVT_INLINE b3Vector3 Lengths() const { return (mx - mi); }
+ B3_DBVT_INLINE b3Vector3 Extents() const { return ((mx - mi) / 2); }
+ B3_DBVT_INLINE const b3Vector3& Mins() const { return (mi); }
+ B3_DBVT_INLINE const b3Vector3& Maxs() const { return (mx); }
+ static inline b3DbvtAabbMm FromCE(const b3Vector3& c, const b3Vector3& e);
+ static inline b3DbvtAabbMm FromCR(const b3Vector3& c, b3Scalar r);
+ static inline b3DbvtAabbMm FromMM(const b3Vector3& mi, const b3Vector3& mx);
+ static inline b3DbvtAabbMm FromPoints(const b3Vector3* pts, int n);
+ static inline b3DbvtAabbMm FromPoints(const b3Vector3** ppts, int n);
+ B3_DBVT_INLINE void Expand(const b3Vector3& e);
+ B3_DBVT_INLINE void SignedExpand(const b3Vector3& e);
+ B3_DBVT_INLINE bool Contain(const b3DbvtAabbMm& a) const;
+ B3_DBVT_INLINE int Classify(const b3Vector3& n, b3Scalar o, int s) const;
+ B3_DBVT_INLINE b3Scalar ProjectMinimum(const b3Vector3& v, unsigned signs) const;
+ B3_DBVT_INLINE friend bool b3Intersect(const b3DbvtAabbMm& a,
+ const b3DbvtAabbMm& b);
+
+ B3_DBVT_INLINE friend bool b3Intersect(const b3DbvtAabbMm& a,
+ const b3Vector3& b);
+
+ B3_DBVT_INLINE friend b3Scalar b3Proximity(const b3DbvtAabbMm& a,
+ const b3DbvtAabbMm& b);
+ B3_DBVT_INLINE friend int b3Select(const b3DbvtAabbMm& o,
+ const b3DbvtAabbMm& a,
+ const b3DbvtAabbMm& b);
+ B3_DBVT_INLINE friend void b3Merge(const b3DbvtAabbMm& a,
+ const b3DbvtAabbMm& b,
+ b3DbvtAabbMm& r);
+ B3_DBVT_INLINE friend bool b3NotEqual(const b3DbvtAabbMm& a,
+ const b3DbvtAabbMm& b);
+
+ B3_DBVT_INLINE b3Vector3& tMins() { return (mi); }
+ B3_DBVT_INLINE b3Vector3& tMaxs() { return (mx); }
+
private:
- B3_DBVT_INLINE void AddSpan(const b3Vector3& d,b3Scalar& smi,b3Scalar& smx) const;
+ B3_DBVT_INLINE void AddSpan(const b3Vector3& d, b3Scalar& smi, b3Scalar& smx) const;
+
private:
- b3Vector3 mi,mx;
+ b3Vector3 mi, mx;
};
-// Types
-typedef b3DbvtAabbMm b3DbvtVolume;
+// Types
+typedef b3DbvtAabbMm b3DbvtVolume;
-/* b3DbvtNode */
-struct b3DbvtNode
+/* b3DbvtNode */
+struct b3DbvtNode
{
- b3DbvtVolume volume;
- b3DbvtNode* parent;
- B3_DBVT_INLINE bool isleaf() const { return(childs[1]==0); }
- B3_DBVT_INLINE bool isinternal() const { return(!isleaf()); }
- union
- {
- b3DbvtNode* childs[2];
- void* data;
- int dataAsInt;
+ b3DbvtVolume volume;
+ b3DbvtNode* parent;
+ B3_DBVT_INLINE bool isleaf() const { return (childs[1] == 0); }
+ B3_DBVT_INLINE bool isinternal() const { return (!isleaf()); }
+ union {
+ b3DbvtNode* childs[2];
+ void* data;
+ int dataAsInt;
};
};
///The b3DynamicBvh class implements a fast dynamic bounding volume tree based on axis aligned bounding boxes (aabb tree).
///This b3DynamicBvh is used for soft body collision detection and for the b3DynamicBvhBroadphase. It has a fast insert, remove and update of nodes.
///Unlike the b3QuantizedBvh, nodes can be dynamically moved around, which allows for change in topology of the underlying data structure.
-struct b3DynamicBvh
+struct b3DynamicBvh
{
- /* Stack element */
- struct sStkNN
+ /* Stack element */
+ struct sStkNN
{
- const b3DbvtNode* a;
- const b3DbvtNode* b;
+ const b3DbvtNode* a;
+ const b3DbvtNode* b;
sStkNN() {}
- sStkNN(const b3DbvtNode* na,const b3DbvtNode* nb) : a(na),b(nb) {}
+ sStkNN(const b3DbvtNode* na, const b3DbvtNode* nb) : a(na), b(nb) {}
};
- struct sStkNP
+ struct sStkNP
{
- const b3DbvtNode* node;
- int mask;
- sStkNP(const b3DbvtNode* n,unsigned m) : node(n),mask(m) {}
+ const b3DbvtNode* node;
+ int mask;
+ sStkNP(const b3DbvtNode* n, unsigned m) : node(n), mask(m) {}
};
- struct sStkNPS
+ struct sStkNPS
{
- const b3DbvtNode* node;
- int mask;
- b3Scalar value;
+ const b3DbvtNode* node;
+ int mask;
+ b3Scalar value;
sStkNPS() {}
- sStkNPS(const b3DbvtNode* n,unsigned m,b3Scalar v) : node(n),mask(m),value(v) {}
+ sStkNPS(const b3DbvtNode* n, unsigned m, b3Scalar v) : node(n), mask(m), value(v) {}
};
- struct sStkCLN
+ struct sStkCLN
{
- const b3DbvtNode* node;
- b3DbvtNode* parent;
- sStkCLN(const b3DbvtNode* n,b3DbvtNode* p) : node(n),parent(p) {}
+ const b3DbvtNode* node;
+ b3DbvtNode* parent;
+ sStkCLN(const b3DbvtNode* n, b3DbvtNode* p) : node(n), parent(p) {}
};
// Policies/Interfaces
- /* ICollide */
- struct ICollide
- {
+ /* ICollide */
+ struct ICollide
+ {
B3_DBVT_VIRTUAL_DTOR(ICollide)
- B3_DBVT_VIRTUAL void Process(const b3DbvtNode*,const b3DbvtNode*) {}
- B3_DBVT_VIRTUAL void Process(const b3DbvtNode*) {}
- B3_DBVT_VIRTUAL void Process(const b3DbvtNode* n,b3Scalar) { Process(n); }
- B3_DBVT_VIRTUAL bool Descent(const b3DbvtNode*) { return(true); }
- B3_DBVT_VIRTUAL bool AllLeaves(const b3DbvtNode*) { return(true); }
+ B3_DBVT_VIRTUAL void Process(const b3DbvtNode*, const b3DbvtNode*) {}
+ B3_DBVT_VIRTUAL void Process(const b3DbvtNode*) {}
+ B3_DBVT_VIRTUAL void Process(const b3DbvtNode* n, b3Scalar) { Process(n); }
+ B3_DBVT_VIRTUAL bool Descent(const b3DbvtNode*) { return (true); }
+ B3_DBVT_VIRTUAL bool AllLeaves(const b3DbvtNode*) { return (true); }
};
- /* IWriter */
- struct IWriter
+ /* IWriter */
+ struct IWriter
{
virtual ~IWriter() {}
- virtual void Prepare(const b3DbvtNode* root,int numnodes)=0;
- virtual void WriteNode(const b3DbvtNode*,int index,int parent,int child0,int child1)=0;
- virtual void WriteLeaf(const b3DbvtNode*,int index,int parent)=0;
+ virtual void Prepare(const b3DbvtNode* root, int numnodes) = 0;
+ virtual void WriteNode(const b3DbvtNode*, int index, int parent, int child0, int child1) = 0;
+ virtual void WriteLeaf(const b3DbvtNode*, int index, int parent) = 0;
};
- /* IClone */
- struct IClone
+ /* IClone */
+ struct IClone
{
- virtual ~IClone() {}
- virtual void CloneLeaf(b3DbvtNode*) {}
+ virtual ~IClone() {}
+ virtual void CloneLeaf(b3DbvtNode*) {}
};
// Constants
- enum {
- B3_SIMPLE_STACKSIZE = 64,
- B3_DOUBLE_STACKSIZE = B3_SIMPLE_STACKSIZE*2
+ enum
+ {
+ B3_SIMPLE_STACKSIZE = 64,
+ B3_DOUBLE_STACKSIZE = B3_SIMPLE_STACKSIZE * 2
};
// Fields
- b3DbvtNode* m_root;
- b3DbvtNode* m_free;
- int m_lkhd;
- int m_leaves;
- unsigned m_opath;
-
-
- b3AlignedObjectArray<sStkNN> m_stkStack;
- mutable b3AlignedObjectArray<const b3DbvtNode*> m_rayTestStack;
+ b3DbvtNode* m_root;
+ b3DbvtNode* m_free;
+ int m_lkhd;
+ int m_leaves;
+ unsigned m_opath;
+ b3AlignedObjectArray<sStkNN> m_stkStack;
+ mutable b3AlignedObjectArray<const b3DbvtNode*> m_rayTestStack;
// Methods
b3DynamicBvh();
~b3DynamicBvh();
- void clear();
- bool empty() const { return(0==m_root); }
- void optimizeBottomUp();
- void optimizeTopDown(int bu_treshold=128);
- void optimizeIncremental(int passes);
- b3DbvtNode* insert(const b3DbvtVolume& box,void* data);
- void update(b3DbvtNode* leaf,int lookahead=-1);
- void update(b3DbvtNode* leaf,b3DbvtVolume& volume);
- bool update(b3DbvtNode* leaf,b3DbvtVolume& volume,const b3Vector3& velocity,b3Scalar margin);
- bool update(b3DbvtNode* leaf,b3DbvtVolume& volume,const b3Vector3& velocity);
- bool update(b3DbvtNode* leaf,b3DbvtVolume& volume,b3Scalar margin);
- void remove(b3DbvtNode* leaf);
- void write(IWriter* iwriter) const;
- void clone(b3DynamicBvh& dest,IClone* iclone=0) const;
- static int maxdepth(const b3DbvtNode* node);
- static int countLeaves(const b3DbvtNode* node);
- static void extractLeaves(const b3DbvtNode* node,b3AlignedObjectArray<const b3DbvtNode*>& leaves);
+ void clear();
+ bool empty() const { return (0 == m_root); }
+ void optimizeBottomUp();
+ void optimizeTopDown(int bu_treshold = 128);
+ void optimizeIncremental(int passes);
+ b3DbvtNode* insert(const b3DbvtVolume& box, void* data);
+ void update(b3DbvtNode* leaf, int lookahead = -1);
+ void update(b3DbvtNode* leaf, b3DbvtVolume& volume);
+ bool update(b3DbvtNode* leaf, b3DbvtVolume& volume, const b3Vector3& velocity, b3Scalar margin);
+ bool update(b3DbvtNode* leaf, b3DbvtVolume& volume, const b3Vector3& velocity);
+ bool update(b3DbvtNode* leaf, b3DbvtVolume& volume, b3Scalar margin);
+ void remove(b3DbvtNode* leaf);
+ void write(IWriter* iwriter) const;
+ void clone(b3DynamicBvh& dest, IClone* iclone = 0) const;
+ static int maxdepth(const b3DbvtNode* node);
+ static int countLeaves(const b3DbvtNode* node);
+ static void extractLeaves(const b3DbvtNode* node, b3AlignedObjectArray<const b3DbvtNode*>& leaves);
#if B3_DBVT_ENABLE_BENCHMARK
- static void benchmark();
+ static void benchmark();
#else
- static void benchmark(){}
+ static void benchmark()
+ {
+ }
#endif
// B3_DBVT_IPOLICY must support ICollide policy/interface
B3_DBVT_PREFIX
- static void enumNodes( const b3DbvtNode* root,
- B3_DBVT_IPOLICY);
+ static void enumNodes(const b3DbvtNode* root,
+ B3_DBVT_IPOLICY);
B3_DBVT_PREFIX
- static void enumLeaves( const b3DbvtNode* root,
- B3_DBVT_IPOLICY);
+ static void enumLeaves(const b3DbvtNode* root,
+ B3_DBVT_IPOLICY);
B3_DBVT_PREFIX
- void collideTT( const b3DbvtNode* root0,
- const b3DbvtNode* root1,
- B3_DBVT_IPOLICY);
+ void collideTT(const b3DbvtNode* root0,
+ const b3DbvtNode* root1,
+ B3_DBVT_IPOLICY);
B3_DBVT_PREFIX
- void collideTTpersistentStack( const b3DbvtNode* root0,
- const b3DbvtNode* root1,
- B3_DBVT_IPOLICY);
+ void collideTTpersistentStack(const b3DbvtNode* root0,
+ const b3DbvtNode* root1,
+ B3_DBVT_IPOLICY);
#if 0
B3_DBVT_PREFIX
void collideTT( const b3DbvtNode* root0,
@@ -322,71 +325,81 @@ struct b3DynamicBvh
#endif
B3_DBVT_PREFIX
- void collideTV( const b3DbvtNode* root,
- const b3DbvtVolume& volume,
- B3_DBVT_IPOLICY) const;
+ void collideTV(const b3DbvtNode* root,
+ const b3DbvtVolume& volume,
+ B3_DBVT_IPOLICY) const;
///rayTest is a re-entrant ray test, and can be called in parallel as long as the b3AlignedAlloc is thread-safe (uses locking etc)
///rayTest is slower than rayTestInternal, because it builds a local stack, using memory allocations, and it recomputes signs/rayDirectionInverses each time
B3_DBVT_PREFIX
- static void rayTest( const b3DbvtNode* root,
- const b3Vector3& rayFrom,
- const b3Vector3& rayTo,
- B3_DBVT_IPOLICY);
+ static void rayTest(const b3DbvtNode* root,
+ const b3Vector3& rayFrom,
+ const b3Vector3& rayTo,
+ B3_DBVT_IPOLICY);
///rayTestInternal is faster than rayTest, because it uses a persistent stack (to reduce dynamic memory allocations to a minimum) and it uses precomputed signs/rayInverseDirections
///rayTestInternal is used by b3DynamicBvhBroadphase to accelerate world ray casts
B3_DBVT_PREFIX
- void rayTestInternal( const b3DbvtNode* root,
- const b3Vector3& rayFrom,
- const b3Vector3& rayTo,
- const b3Vector3& rayDirectionInverse,
- unsigned int signs[3],
- b3Scalar lambda_max,
- const b3Vector3& aabbMin,
- const b3Vector3& aabbMax,
- B3_DBVT_IPOLICY) const;
+ void rayTestInternal(const b3DbvtNode* root,
+ const b3Vector3& rayFrom,
+ const b3Vector3& rayTo,
+ const b3Vector3& rayDirectionInverse,
+ unsigned int signs[3],
+ b3Scalar lambda_max,
+ const b3Vector3& aabbMin,
+ const b3Vector3& aabbMax,
+ B3_DBVT_IPOLICY) const;
B3_DBVT_PREFIX
- static void collideKDOP(const b3DbvtNode* root,
- const b3Vector3* normals,
- const b3Scalar* offsets,
- int count,
- B3_DBVT_IPOLICY);
+ static void collideKDOP(const b3DbvtNode* root,
+ const b3Vector3* normals,
+ const b3Scalar* offsets,
+ int count,
+ B3_DBVT_IPOLICY);
B3_DBVT_PREFIX
- static void collideOCL( const b3DbvtNode* root,
- const b3Vector3* normals,
- const b3Scalar* offsets,
- const b3Vector3& sortaxis,
- int count,
- B3_DBVT_IPOLICY,
- bool fullsort=true);
+ static void collideOCL(const b3DbvtNode* root,
+ const b3Vector3* normals,
+ const b3Scalar* offsets,
+ const b3Vector3& sortaxis,
+ int count,
+ B3_DBVT_IPOLICY,
+ bool fullsort = true);
B3_DBVT_PREFIX
- static void collideTU( const b3DbvtNode* root,
- B3_DBVT_IPOLICY);
- // Helpers
- static B3_DBVT_INLINE int nearest(const int* i,const b3DynamicBvh::sStkNPS* a,b3Scalar v,int l,int h)
+ static void collideTU(const b3DbvtNode* root,
+ B3_DBVT_IPOLICY);
+ // Helpers
+ static B3_DBVT_INLINE int nearest(const int* i, const b3DynamicBvh::sStkNPS* a, b3Scalar v, int l, int h)
{
- int m=0;
- while(l<h)
+ int m = 0;
+ while (l < h)
{
- m=(l+h)>>1;
- if(a[i[m]].value>=v) l=m+1; else h=m;
+ m = (l + h) >> 1;
+ if (a[i[m]].value >= v)
+ l = m + 1;
+ else
+ h = m;
}
- return(h);
+ return (h);
}
- static B3_DBVT_INLINE int allocate( b3AlignedObjectArray<int>& ifree,
- b3AlignedObjectArray<sStkNPS>& stock,
- const sStkNPS& value)
+ static B3_DBVT_INLINE int allocate(b3AlignedObjectArray<int>& ifree,
+ b3AlignedObjectArray<sStkNPS>& stock,
+ const sStkNPS& value)
{
- int i;
- if(ifree.size()>0)
- { i=ifree[ifree.size()-1];ifree.pop_back();stock[i]=value; }
+ int i;
+ if (ifree.size() > 0)
+ {
+ i = ifree[ifree.size() - 1];
+ ifree.pop_back();
+ stock[i] = value;
+ }
else
- { i=stock.size();stock.push_back(value); }
- return(i);
+ {
+ i = stock.size();
+ stock.push_back(value);
+ }
+ return (i);
}
//
private:
- b3DynamicBvh(const b3DynamicBvh&) {}
+ b3DynamicBvh(const b3DynamicBvh&) {}
};
//
@@ -394,227 +407,252 @@ private:
//
//
-inline b3DbvtAabbMm b3DbvtAabbMm::FromCE(const b3Vector3& c,const b3Vector3& e)
+inline b3DbvtAabbMm b3DbvtAabbMm::FromCE(const b3Vector3& c, const b3Vector3& e)
{
b3DbvtAabbMm box;
- box.mi=c-e;box.mx=c+e;
- return(box);
+ box.mi = c - e;
+ box.mx = c + e;
+ return (box);
}
//
-inline b3DbvtAabbMm b3DbvtAabbMm::FromCR(const b3Vector3& c,b3Scalar r)
+inline b3DbvtAabbMm b3DbvtAabbMm::FromCR(const b3Vector3& c, b3Scalar r)
{
- return(FromCE(c,b3MakeVector3(r,r,r)));
+ return (FromCE(c, b3MakeVector3(r, r, r)));
}
//
-inline b3DbvtAabbMm b3DbvtAabbMm::FromMM(const b3Vector3& mi,const b3Vector3& mx)
+inline b3DbvtAabbMm b3DbvtAabbMm::FromMM(const b3Vector3& mi, const b3Vector3& mx)
{
b3DbvtAabbMm box;
- box.mi=mi;box.mx=mx;
- return(box);
+ box.mi = mi;
+ box.mx = mx;
+ return (box);
}
//
-inline b3DbvtAabbMm b3DbvtAabbMm::FromPoints(const b3Vector3* pts,int n)
+inline b3DbvtAabbMm b3DbvtAabbMm::FromPoints(const b3Vector3* pts, int n)
{
b3DbvtAabbMm box;
- box.mi=box.mx=pts[0];
- for(int i=1;i<n;++i)
+ box.mi = box.mx = pts[0];
+ for (int i = 1; i < n; ++i)
{
box.mi.setMin(pts[i]);
box.mx.setMax(pts[i]);
}
- return(box);
+ return (box);
}
//
-inline b3DbvtAabbMm b3DbvtAabbMm::FromPoints(const b3Vector3** ppts,int n)
+inline b3DbvtAabbMm b3DbvtAabbMm::FromPoints(const b3Vector3** ppts, int n)
{
b3DbvtAabbMm box;
- box.mi=box.mx=*ppts[0];
- for(int i=1;i<n;++i)
+ box.mi = box.mx = *ppts[0];
+ for (int i = 1; i < n; ++i)
{
box.mi.setMin(*ppts[i]);
box.mx.setMax(*ppts[i]);
}
- return(box);
+ return (box);
}
//
-B3_DBVT_INLINE void b3DbvtAabbMm::Expand(const b3Vector3& e)
+B3_DBVT_INLINE void b3DbvtAabbMm::Expand(const b3Vector3& e)
{
- mi-=e;mx+=e;
+ mi -= e;
+ mx += e;
}
//
-B3_DBVT_INLINE void b3DbvtAabbMm::SignedExpand(const b3Vector3& e)
+B3_DBVT_INLINE void b3DbvtAabbMm::SignedExpand(const b3Vector3& e)
{
- if(e.x>0) mx.setX(mx.x+e[0]); else mi.setX(mi.x+e[0]);
- if(e.y>0) mx.setY(mx.y+e[1]); else mi.setY(mi.y+e[1]);
- if(e.z>0) mx.setZ(mx.z+e[2]); else mi.setZ(mi.z+e[2]);
+ if (e.x > 0)
+ mx.setX(mx.x + e[0]);
+ else
+ mi.setX(mi.x + e[0]);
+ if (e.y > 0)
+ mx.setY(mx.y + e[1]);
+ else
+ mi.setY(mi.y + e[1]);
+ if (e.z > 0)
+ mx.setZ(mx.z + e[2]);
+ else
+ mi.setZ(mi.z + e[2]);
}
//
-B3_DBVT_INLINE bool b3DbvtAabbMm::Contain(const b3DbvtAabbMm& a) const
+B3_DBVT_INLINE bool b3DbvtAabbMm::Contain(const b3DbvtAabbMm& a) const
{
- return( (mi.x<=a.mi.x)&&
- (mi.y<=a.mi.y)&&
- (mi.z<=a.mi.z)&&
- (mx.x>=a.mx.x)&&
- (mx.y>=a.mx.y)&&
- (mx.z>=a.mx.z));
+ return ((mi.x <= a.mi.x) &&
+ (mi.y <= a.mi.y) &&
+ (mi.z <= a.mi.z) &&
+ (mx.x >= a.mx.x) &&
+ (mx.y >= a.mx.y) &&
+ (mx.z >= a.mx.z));
}
//
-B3_DBVT_INLINE int b3DbvtAabbMm::Classify(const b3Vector3& n,b3Scalar o,int s) const
+B3_DBVT_INLINE int b3DbvtAabbMm::Classify(const b3Vector3& n, b3Scalar o, int s) const
{
- b3Vector3 pi,px;
- switch(s)
+ b3Vector3 pi, px;
+ switch (s)
{
- case (0+0+0): px=b3MakeVector3(mi.x,mi.y,mi.z);
- pi=b3MakeVector3(mx.x,mx.y,mx.z);break;
- case (1+0+0): px=b3MakeVector3(mx.x,mi.y,mi.z);
- pi=b3MakeVector3(mi.x,mx.y,mx.z);break;
- case (0+2+0): px=b3MakeVector3(mi.x,mx.y,mi.z);
- pi=b3MakeVector3(mx.x,mi.y,mx.z);break;
- case (1+2+0): px=b3MakeVector3(mx.x,mx.y,mi.z);
- pi=b3MakeVector3(mi.x,mi.y,mx.z);break;
- case (0+0+4): px=b3MakeVector3(mi.x,mi.y,mx.z);
- pi=b3MakeVector3(mx.x,mx.y,mi.z);break;
- case (1+0+4): px=b3MakeVector3(mx.x,mi.y,mx.z);
- pi=b3MakeVector3(mi.x,mx.y,mi.z);break;
- case (0+2+4): px=b3MakeVector3(mi.x,mx.y,mx.z);
- pi=b3MakeVector3(mx.x,mi.y,mi.z);break;
- case (1+2+4): px=b3MakeVector3(mx.x,mx.y,mx.z);
- pi=b3MakeVector3(mi.x,mi.y,mi.z);break;
+ case (0 + 0 + 0):
+ px = b3MakeVector3(mi.x, mi.y, mi.z);
+ pi = b3MakeVector3(mx.x, mx.y, mx.z);
+ break;
+ case (1 + 0 + 0):
+ px = b3MakeVector3(mx.x, mi.y, mi.z);
+ pi = b3MakeVector3(mi.x, mx.y, mx.z);
+ break;
+ case (0 + 2 + 0):
+ px = b3MakeVector3(mi.x, mx.y, mi.z);
+ pi = b3MakeVector3(mx.x, mi.y, mx.z);
+ break;
+ case (1 + 2 + 0):
+ px = b3MakeVector3(mx.x, mx.y, mi.z);
+ pi = b3MakeVector3(mi.x, mi.y, mx.z);
+ break;
+ case (0 + 0 + 4):
+ px = b3MakeVector3(mi.x, mi.y, mx.z);
+ pi = b3MakeVector3(mx.x, mx.y, mi.z);
+ break;
+ case (1 + 0 + 4):
+ px = b3MakeVector3(mx.x, mi.y, mx.z);
+ pi = b3MakeVector3(mi.x, mx.y, mi.z);
+ break;
+ case (0 + 2 + 4):
+ px = b3MakeVector3(mi.x, mx.y, mx.z);
+ pi = b3MakeVector3(mx.x, mi.y, mi.z);
+ break;
+ case (1 + 2 + 4):
+ px = b3MakeVector3(mx.x, mx.y, mx.z);
+ pi = b3MakeVector3(mi.x, mi.y, mi.z);
+ break;
}
- if((b3Dot(n,px)+o)<0) return(-1);
- if((b3Dot(n,pi)+o)>=0) return(+1);
- return(0);
+ if ((b3Dot(n, px) + o) < 0) return (-1);
+ if ((b3Dot(n, pi) + o) >= 0) return (+1);
+ return (0);
}
//
-B3_DBVT_INLINE b3Scalar b3DbvtAabbMm::ProjectMinimum(const b3Vector3& v,unsigned signs) const
+B3_DBVT_INLINE b3Scalar b3DbvtAabbMm::ProjectMinimum(const b3Vector3& v, unsigned signs) const
{
- const b3Vector3* b[]={&mx,&mi};
- const b3Vector3 p = b3MakeVector3( b[(signs>>0)&1]->x,
- b[(signs>>1)&1]->y,
- b[(signs>>2)&1]->z);
- return(b3Dot(p,v));
+ const b3Vector3* b[] = {&mx, &mi};
+ const b3Vector3 p = b3MakeVector3(b[(signs >> 0) & 1]->x,
+ b[(signs >> 1) & 1]->y,
+ b[(signs >> 2) & 1]->z);
+ return (b3Dot(p, v));
}
//
-B3_DBVT_INLINE void b3DbvtAabbMm::AddSpan(const b3Vector3& d,b3Scalar& smi,b3Scalar& smx) const
+B3_DBVT_INLINE void b3DbvtAabbMm::AddSpan(const b3Vector3& d, b3Scalar& smi, b3Scalar& smx) const
{
- for(int i=0;i<3;++i)
+ for (int i = 0; i < 3; ++i)
{
- if(d[i]<0)
- { smi+=mx[i]*d[i];smx+=mi[i]*d[i]; }
+ if (d[i] < 0)
+ {
+ smi += mx[i] * d[i];
+ smx += mi[i] * d[i];
+ }
else
- { smi+=mi[i]*d[i];smx+=mx[i]*d[i]; }
+ {
+ smi += mi[i] * d[i];
+ smx += mx[i] * d[i];
+ }
}
}
//
-B3_DBVT_INLINE bool b3Intersect( const b3DbvtAabbMm& a,
- const b3DbvtAabbMm& b)
+B3_DBVT_INLINE bool b3Intersect(const b3DbvtAabbMm& a,
+ const b3DbvtAabbMm& b)
{
-#if B3_DBVT_INT0_IMPL == B3_DBVT_IMPL_SSE
- const __m128 rt(_mm_or_ps( _mm_cmplt_ps(_mm_load_ps(b.mx),_mm_load_ps(a.mi)),
- _mm_cmplt_ps(_mm_load_ps(a.mx),_mm_load_ps(b.mi))));
-#if defined (_WIN32)
- const __int32* pu((const __int32*)&rt);
+#if B3_DBVT_INT0_IMPL == B3_DBVT_IMPL_SSE
+ const __m128 rt(_mm_or_ps(_mm_cmplt_ps(_mm_load_ps(b.mx), _mm_load_ps(a.mi)),
+ _mm_cmplt_ps(_mm_load_ps(a.mx), _mm_load_ps(b.mi))));
+#if defined(_WIN32)
+ const __int32* pu((const __int32*)&rt);
#else
- const int* pu((const int*)&rt);
+ const int* pu((const int*)&rt);
#endif
- return((pu[0]|pu[1]|pu[2])==0);
+ return ((pu[0] | pu[1] | pu[2]) == 0);
#else
- return( (a.mi.x<=b.mx.x)&&
- (a.mx.x>=b.mi.x)&&
- (a.mi.y<=b.mx.y)&&
- (a.mx.y>=b.mi.y)&&
- (a.mi.z<=b.mx.z)&&
- (a.mx.z>=b.mi.z));
+ return ((a.mi.x <= b.mx.x) &&
+ (a.mx.x >= b.mi.x) &&
+ (a.mi.y <= b.mx.y) &&
+ (a.mx.y >= b.mi.y) &&
+ (a.mi.z <= b.mx.z) &&
+ (a.mx.z >= b.mi.z));
#endif
}
-
-
//
-B3_DBVT_INLINE bool b3Intersect( const b3DbvtAabbMm& a,
- const b3Vector3& b)
+B3_DBVT_INLINE bool b3Intersect(const b3DbvtAabbMm& a,
+ const b3Vector3& b)
{
- return( (b.x>=a.mi.x)&&
- (b.y>=a.mi.y)&&
- (b.z>=a.mi.z)&&
- (b.x<=a.mx.x)&&
- (b.y<=a.mx.y)&&
- (b.z<=a.mx.z));
+ return ((b.x >= a.mi.x) &&
+ (b.y >= a.mi.y) &&
+ (b.z >= a.mi.z) &&
+ (b.x <= a.mx.x) &&
+ (b.y <= a.mx.y) &&
+ (b.z <= a.mx.z));
}
-
-
-
-
//////////////////////////////////////
-
//
-B3_DBVT_INLINE b3Scalar b3Proximity( const b3DbvtAabbMm& a,
- const b3DbvtAabbMm& b)
+B3_DBVT_INLINE b3Scalar b3Proximity(const b3DbvtAabbMm& a,
+ const b3DbvtAabbMm& b)
{
- const b3Vector3 d=(a.mi+a.mx)-(b.mi+b.mx);
- return(b3Fabs(d.x)+b3Fabs(d.y)+b3Fabs(d.z));
+ const b3Vector3 d = (a.mi + a.mx) - (b.mi + b.mx);
+ return (b3Fabs(d.x) + b3Fabs(d.y) + b3Fabs(d.z));
}
-
-
//
-B3_DBVT_INLINE int b3Select( const b3DbvtAabbMm& o,
- const b3DbvtAabbMm& a,
- const b3DbvtAabbMm& b)
+B3_DBVT_INLINE int b3Select(const b3DbvtAabbMm& o,
+ const b3DbvtAabbMm& a,
+ const b3DbvtAabbMm& b)
{
-#if B3_DBVT_SELECT_IMPL == B3_DBVT_IMPL_SSE
-
-#if defined (_WIN32)
- static B3_ATTRIBUTE_ALIGNED16(const unsigned __int32) mask[]={0x7fffffff,0x7fffffff,0x7fffffff,0x7fffffff};
+#if B3_DBVT_SELECT_IMPL == B3_DBVT_IMPL_SSE
+
+#if defined(_WIN32)
+ static B3_ATTRIBUTE_ALIGNED16(const unsigned __int32) mask[] = {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff};
#else
- static B3_ATTRIBUTE_ALIGNED16(const unsigned int) mask[]={0x7fffffff,0x7fffffff,0x7fffffff,0x00000000 /*0x7fffffff*/};
+ static B3_ATTRIBUTE_ALIGNED16(const unsigned int) mask[] = {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x00000000 /*0x7fffffff*/};
#endif
///@todo: the intrinsic version is 11% slower
#if B3_DBVT_USE_INTRINSIC_SSE
- union b3SSEUnion ///NOTE: if we use more intrinsics, move b3SSEUnion into the LinearMath directory
+ union b3SSEUnion ///NOTE: if we use more intrinsics, move b3SSEUnion into the LinearMath directory
{
- __m128 ssereg;
- float floats[4];
- int ints[4];
+ __m128 ssereg;
+ float floats[4];
+ int ints[4];
};
- __m128 omi(_mm_load_ps(o.mi));
- omi=_mm_add_ps(omi,_mm_load_ps(o.mx));
- __m128 ami(_mm_load_ps(a.mi));
- ami=_mm_add_ps(ami,_mm_load_ps(a.mx));
- ami=_mm_sub_ps(ami,omi);
- ami=_mm_and_ps(ami,_mm_load_ps((const float*)mask));
- __m128 bmi(_mm_load_ps(b.mi));
- bmi=_mm_add_ps(bmi,_mm_load_ps(b.mx));
- bmi=_mm_sub_ps(bmi,omi);
- bmi=_mm_and_ps(bmi,_mm_load_ps((const float*)mask));
- __m128 t0(_mm_movehl_ps(ami,ami));
- ami=_mm_add_ps(ami,t0);
- ami=_mm_add_ss(ami,_mm_shuffle_ps(ami,ami,1));
- __m128 t1(_mm_movehl_ps(bmi,bmi));
- bmi=_mm_add_ps(bmi,t1);
- bmi=_mm_add_ss(bmi,_mm_shuffle_ps(bmi,bmi,1));
-
+ __m128 omi(_mm_load_ps(o.mi));
+ omi = _mm_add_ps(omi, _mm_load_ps(o.mx));
+ __m128 ami(_mm_load_ps(a.mi));
+ ami = _mm_add_ps(ami, _mm_load_ps(a.mx));
+ ami = _mm_sub_ps(ami, omi);
+ ami = _mm_and_ps(ami, _mm_load_ps((const float*)mask));
+ __m128 bmi(_mm_load_ps(b.mi));
+ bmi = _mm_add_ps(bmi, _mm_load_ps(b.mx));
+ bmi = _mm_sub_ps(bmi, omi);
+ bmi = _mm_and_ps(bmi, _mm_load_ps((const float*)mask));
+ __m128 t0(_mm_movehl_ps(ami, ami));
+ ami = _mm_add_ps(ami, t0);
+ ami = _mm_add_ss(ami, _mm_shuffle_ps(ami, ami, 1));
+ __m128 t1(_mm_movehl_ps(bmi, bmi));
+ bmi = _mm_add_ps(bmi, t1);
+ bmi = _mm_add_ss(bmi, _mm_shuffle_ps(bmi, bmi, 1));
+
b3SSEUnion tmp;
- tmp.ssereg = _mm_cmple_ss(bmi,ami);
- return tmp.ints[0]&1;
+ tmp.ssereg = _mm_cmple_ss(bmi, ami);
+ return tmp.ints[0] & 1;
#else
- B3_ATTRIBUTE_ALIGNED16(__int32 r[1]);
+ B3_ATTRIBUTE_ALIGNED16(__int32 r[1]);
__asm
{
mov eax,o
@@ -642,46 +680,52 @@ B3_DBVT_INLINE int b3Select( const b3DbvtAabbMm& o,
cmpless xmm2,xmm1
movss r,xmm2
}
- return(r[0]&1);
+ return (r[0] & 1);
#endif
#else
- return(b3Proximity(o,a)<b3Proximity(o,b)?0:1);
+ return (b3Proximity(o, a) < b3Proximity(o, b) ? 0 : 1);
#endif
}
//
-B3_DBVT_INLINE void b3Merge( const b3DbvtAabbMm& a,
- const b3DbvtAabbMm& b,
- b3DbvtAabbMm& r)
+B3_DBVT_INLINE void b3Merge(const b3DbvtAabbMm& a,
+ const b3DbvtAabbMm& b,
+ b3DbvtAabbMm& r)
{
-#if B3_DBVT_MERGE_IMPL==B3_DBVT_IMPL_SSE
- __m128 ami(_mm_load_ps(a.mi));
- __m128 amx(_mm_load_ps(a.mx));
- __m128 bmi(_mm_load_ps(b.mi));
- __m128 bmx(_mm_load_ps(b.mx));
- ami=_mm_min_ps(ami,bmi);
- amx=_mm_max_ps(amx,bmx);
- _mm_store_ps(r.mi,ami);
- _mm_store_ps(r.mx,amx);
+#if B3_DBVT_MERGE_IMPL == B3_DBVT_IMPL_SSE
+ __m128 ami(_mm_load_ps(a.mi));
+ __m128 amx(_mm_load_ps(a.mx));
+ __m128 bmi(_mm_load_ps(b.mi));
+ __m128 bmx(_mm_load_ps(b.mx));
+ ami = _mm_min_ps(ami, bmi);
+ amx = _mm_max_ps(amx, bmx);
+ _mm_store_ps(r.mi, ami);
+ _mm_store_ps(r.mx, amx);
#else
- for(int i=0;i<3;++i)
+ for (int i = 0; i < 3; ++i)
{
- if(a.mi[i]<b.mi[i]) r.mi[i]=a.mi[i]; else r.mi[i]=b.mi[i];
- if(a.mx[i]>b.mx[i]) r.mx[i]=a.mx[i]; else r.mx[i]=b.mx[i];
+ if (a.mi[i] < b.mi[i])
+ r.mi[i] = a.mi[i];
+ else
+ r.mi[i] = b.mi[i];
+ if (a.mx[i] > b.mx[i])
+ r.mx[i] = a.mx[i];
+ else
+ r.mx[i] = b.mx[i];
}
#endif
}
//
-B3_DBVT_INLINE bool b3NotEqual( const b3DbvtAabbMm& a,
- const b3DbvtAabbMm& b)
+B3_DBVT_INLINE bool b3NotEqual(const b3DbvtAabbMm& a,
+ const b3DbvtAabbMm& b)
{
- return( (a.mi.x!=b.mi.x)||
- (a.mi.y!=b.mi.y)||
- (a.mi.z!=b.mi.z)||
- (a.mx.x!=b.mx.x)||
- (a.mx.y!=b.mx.y)||
- (a.mx.z!=b.mx.z));
+ return ((a.mi.x != b.mi.x) ||
+ (a.mi.y != b.mi.y) ||
+ (a.mi.z != b.mi.z) ||
+ (a.mx.x != b.mx.x) ||
+ (a.mx.y != b.mx.y) ||
+ (a.mx.z != b.mx.z));
}
//
@@ -690,162 +734,162 @@ B3_DBVT_INLINE bool b3NotEqual( const b3DbvtAabbMm& a,
//
B3_DBVT_PREFIX
-inline void b3DynamicBvh::enumNodes( const b3DbvtNode* root,
- B3_DBVT_IPOLICY)
+inline void b3DynamicBvh::enumNodes(const b3DbvtNode* root,
+ B3_DBVT_IPOLICY)
{
B3_DBVT_CHECKTYPE
- policy.Process(root);
- if(root->isinternal())
+ policy.Process(root);
+ if (root->isinternal())
{
- enumNodes(root->childs[0],policy);
- enumNodes(root->childs[1],policy);
+ enumNodes(root->childs[0], policy);
+ enumNodes(root->childs[1], policy);
}
}
//
B3_DBVT_PREFIX
-inline void b3DynamicBvh::enumLeaves( const b3DbvtNode* root,
- B3_DBVT_IPOLICY)
+inline void b3DynamicBvh::enumLeaves(const b3DbvtNode* root,
+ B3_DBVT_IPOLICY)
{
B3_DBVT_CHECKTYPE
- if(root->isinternal())
- {
- enumLeaves(root->childs[0],policy);
- enumLeaves(root->childs[1],policy);
- }
- else
- {
- policy.Process(root);
- }
+ if (root->isinternal())
+ {
+ enumLeaves(root->childs[0], policy);
+ enumLeaves(root->childs[1], policy);
+ }
+ else
+ {
+ policy.Process(root);
+ }
}
//
B3_DBVT_PREFIX
-inline void b3DynamicBvh::collideTT( const b3DbvtNode* root0,
- const b3DbvtNode* root1,
- B3_DBVT_IPOLICY)
+inline void b3DynamicBvh::collideTT(const b3DbvtNode* root0,
+ const b3DbvtNode* root1,
+ B3_DBVT_IPOLICY)
{
B3_DBVT_CHECKTYPE
- if(root0&&root1)
+ if (root0 && root1)
+ {
+ int depth = 1;
+ int treshold = B3_DOUBLE_STACKSIZE - 4;
+ b3AlignedObjectArray<sStkNN> stkStack;
+ stkStack.resize(B3_DOUBLE_STACKSIZE);
+ stkStack[0] = sStkNN(root0, root1);
+ do
{
- int depth=1;
- int treshold=B3_DOUBLE_STACKSIZE-4;
- b3AlignedObjectArray<sStkNN> stkStack;
- stkStack.resize(B3_DOUBLE_STACKSIZE);
- stkStack[0]=sStkNN(root0,root1);
- do {
- sStkNN p=stkStack[--depth];
- if(depth>treshold)
+ sStkNN p = stkStack[--depth];
+ if (depth > treshold)
+ {
+ stkStack.resize(stkStack.size() * 2);
+ treshold = stkStack.size() - 4;
+ }
+ if (p.a == p.b)
+ {
+ if (p.a->isinternal())
{
- stkStack.resize(stkStack.size()*2);
- treshold=stkStack.size()-4;
+ stkStack[depth++] = sStkNN(p.a->childs[0], p.a->childs[0]);
+ stkStack[depth++] = sStkNN(p.a->childs[1], p.a->childs[1]);
+ stkStack[depth++] = sStkNN(p.a->childs[0], p.a->childs[1]);
}
- if(p.a==p.b)
+ }
+ else if (b3Intersect(p.a->volume, p.b->volume))
+ {
+ if (p.a->isinternal())
{
- if(p.a->isinternal())
+ if (p.b->isinternal())
{
- stkStack[depth++]=sStkNN(p.a->childs[0],p.a->childs[0]);
- stkStack[depth++]=sStkNN(p.a->childs[1],p.a->childs[1]);
- stkStack[depth++]=sStkNN(p.a->childs[0],p.a->childs[1]);
+ stkStack[depth++] = sStkNN(p.a->childs[0], p.b->childs[0]);
+ stkStack[depth++] = sStkNN(p.a->childs[1], p.b->childs[0]);
+ stkStack[depth++] = sStkNN(p.a->childs[0], p.b->childs[1]);
+ stkStack[depth++] = sStkNN(p.a->childs[1], p.b->childs[1]);
+ }
+ else
+ {
+ stkStack[depth++] = sStkNN(p.a->childs[0], p.b);
+ stkStack[depth++] = sStkNN(p.a->childs[1], p.b);
}
}
- else if(b3Intersect(p.a->volume,p.b->volume))
+ else
{
- if(p.a->isinternal())
+ if (p.b->isinternal())
{
- if(p.b->isinternal())
- {
- stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]);
- stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]);
- stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]);
- stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]);
- }
- else
- {
- stkStack[depth++]=sStkNN(p.a->childs[0],p.b);
- stkStack[depth++]=sStkNN(p.a->childs[1],p.b);
- }
+ stkStack[depth++] = sStkNN(p.a, p.b->childs[0]);
+ stkStack[depth++] = sStkNN(p.a, p.b->childs[1]);
}
else
{
- if(p.b->isinternal())
- {
- stkStack[depth++]=sStkNN(p.a,p.b->childs[0]);
- stkStack[depth++]=sStkNN(p.a,p.b->childs[1]);
- }
- else
- {
- policy.Process(p.a,p.b);
- }
+ policy.Process(p.a, p.b);
}
}
- } while(depth);
- }
+ }
+ } while (depth);
+ }
}
-
-
B3_DBVT_PREFIX
-inline void b3DynamicBvh::collideTTpersistentStack( const b3DbvtNode* root0,
- const b3DbvtNode* root1,
- B3_DBVT_IPOLICY)
+inline void b3DynamicBvh::collideTTpersistentStack(const b3DbvtNode* root0,
+ const b3DbvtNode* root1,
+ B3_DBVT_IPOLICY)
{
B3_DBVT_CHECKTYPE
- if(root0&&root1)
+ if (root0 && root1)
+ {
+ int depth = 1;
+ int treshold = B3_DOUBLE_STACKSIZE - 4;
+
+ m_stkStack.resize(B3_DOUBLE_STACKSIZE);
+ m_stkStack[0] = sStkNN(root0, root1);
+ do
{
- int depth=1;
- int treshold=B3_DOUBLE_STACKSIZE-4;
-
- m_stkStack.resize(B3_DOUBLE_STACKSIZE);
- m_stkStack[0]=sStkNN(root0,root1);
- do {
- sStkNN p=m_stkStack[--depth];
- if(depth>treshold)
+ sStkNN p = m_stkStack[--depth];
+ if (depth > treshold)
+ {
+ m_stkStack.resize(m_stkStack.size() * 2);
+ treshold = m_stkStack.size() - 4;
+ }
+ if (p.a == p.b)
+ {
+ if (p.a->isinternal())
{
- m_stkStack.resize(m_stkStack.size()*2);
- treshold=m_stkStack.size()-4;
+ m_stkStack[depth++] = sStkNN(p.a->childs[0], p.a->childs[0]);
+ m_stkStack[depth++] = sStkNN(p.a->childs[1], p.a->childs[1]);
+ m_stkStack[depth++] = sStkNN(p.a->childs[0], p.a->childs[1]);
}
- if(p.a==p.b)
+ }
+ else if (b3Intersect(p.a->volume, p.b->volume))
+ {
+ if (p.a->isinternal())
{
- if(p.a->isinternal())
+ if (p.b->isinternal())
+ {
+ m_stkStack[depth++] = sStkNN(p.a->childs[0], p.b->childs[0]);
+ m_stkStack[depth++] = sStkNN(p.a->childs[1], p.b->childs[0]);
+ m_stkStack[depth++] = sStkNN(p.a->childs[0], p.b->childs[1]);
+ m_stkStack[depth++] = sStkNN(p.a->childs[1], p.b->childs[1]);
+ }
+ else
{
- m_stkStack[depth++]=sStkNN(p.a->childs[0],p.a->childs[0]);
- m_stkStack[depth++]=sStkNN(p.a->childs[1],p.a->childs[1]);
- m_stkStack[depth++]=sStkNN(p.a->childs[0],p.a->childs[1]);
+ m_stkStack[depth++] = sStkNN(p.a->childs[0], p.b);
+ m_stkStack[depth++] = sStkNN(p.a->childs[1], p.b);
}
}
- else if(b3Intersect(p.a->volume,p.b->volume))
+ else
{
- if(p.a->isinternal())
+ if (p.b->isinternal())
{
- if(p.b->isinternal())
- {
- m_stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]);
- m_stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]);
- m_stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]);
- m_stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]);
- }
- else
- {
- m_stkStack[depth++]=sStkNN(p.a->childs[0],p.b);
- m_stkStack[depth++]=sStkNN(p.a->childs[1],p.b);
- }
+ m_stkStack[depth++] = sStkNN(p.a, p.b->childs[0]);
+ m_stkStack[depth++] = sStkNN(p.a, p.b->childs[1]);
}
else
{
- if(p.b->isinternal())
- {
- m_stkStack[depth++]=sStkNN(p.a,p.b->childs[0]);
- m_stkStack[depth++]=sStkNN(p.a,p.b->childs[1]);
- }
- else
- {
- policy.Process(p.a,p.b);
- }
+ policy.Process(p.a, p.b);
}
}
- } while(depth);
- }
+ }
+ } while (depth);
+ }
}
#if 0
@@ -915,337 +959,356 @@ inline void b3DynamicBvh::collideTT( const b3DbvtNode* root0,
const b3Transform xform=xform0.inverse()*xform1;
collideTT(root0,root1,xform,policy);
}
-#endif
+#endif
//
B3_DBVT_PREFIX
-inline void b3DynamicBvh::collideTV( const b3DbvtNode* root,
- const b3DbvtVolume& vol,
- B3_DBVT_IPOLICY) const
+inline void b3DynamicBvh::collideTV(const b3DbvtNode* root,
+ const b3DbvtVolume& vol,
+ B3_DBVT_IPOLICY) const
{
B3_DBVT_CHECKTYPE
- if(root)
+ if (root)
+ {
+ B3_ATTRIBUTE_ALIGNED16(b3DbvtVolume)
+ volume(vol);
+ b3AlignedObjectArray<const b3DbvtNode*> stack;
+ stack.resize(0);
+ stack.reserve(B3_SIMPLE_STACKSIZE);
+ stack.push_back(root);
+ do
{
- B3_ATTRIBUTE_ALIGNED16(b3DbvtVolume) volume(vol);
- b3AlignedObjectArray<const b3DbvtNode*> stack;
- stack.resize(0);
- stack.reserve(B3_SIMPLE_STACKSIZE);
- stack.push_back(root);
- do {
- const b3DbvtNode* n=stack[stack.size()-1];
- stack.pop_back();
- if(b3Intersect(n->volume,volume))
+ const b3DbvtNode* n = stack[stack.size() - 1];
+ stack.pop_back();
+ if (b3Intersect(n->volume, volume))
+ {
+ if (n->isinternal())
{
- if(n->isinternal())
- {
- stack.push_back(n->childs[0]);
- stack.push_back(n->childs[1]);
- }
- else
- {
- policy.Process(n);
- }
+ stack.push_back(n->childs[0]);
+ stack.push_back(n->childs[1]);
}
- } while(stack.size()>0);
- }
+ else
+ {
+ policy.Process(n);
+ }
+ }
+ } while (stack.size() > 0);
+ }
}
B3_DBVT_PREFIX
-inline void b3DynamicBvh::rayTestInternal( const b3DbvtNode* root,
- const b3Vector3& rayFrom,
- const b3Vector3& rayTo,
- const b3Vector3& rayDirectionInverse,
- unsigned int signs[3],
- b3Scalar lambda_max,
- const b3Vector3& aabbMin,
- const b3Vector3& aabbMax,
- B3_DBVT_IPOLICY) const
+inline void b3DynamicBvh::rayTestInternal(const b3DbvtNode* root,
+ const b3Vector3& rayFrom,
+ const b3Vector3& rayTo,
+ const b3Vector3& rayDirectionInverse,
+ unsigned int signs[3],
+ b3Scalar lambda_max,
+ const b3Vector3& aabbMin,
+ const b3Vector3& aabbMax,
+ B3_DBVT_IPOLICY) const
{
- (void) rayTo;
+ (void)rayTo;
B3_DBVT_CHECKTYPE
- if(root)
+ if (root)
{
- int depth=1;
- int treshold=B3_DOUBLE_STACKSIZE-2;
- b3AlignedObjectArray<const b3DbvtNode*>& stack = m_rayTestStack;
+ int depth = 1;
+ int treshold = B3_DOUBLE_STACKSIZE - 2;
+ b3AlignedObjectArray<const b3DbvtNode*>& stack = m_rayTestStack;
stack.resize(B3_DOUBLE_STACKSIZE);
- stack[0]=root;
+ stack[0] = root;
b3Vector3 bounds[2];
- do
+ do
{
- const b3DbvtNode* node=stack[--depth];
- bounds[0] = node->volume.Mins()-aabbMax;
- bounds[1] = node->volume.Maxs()-aabbMin;
- b3Scalar tmin=1.f,lambda_min=0.f;
- unsigned int result1=false;
- result1 = b3RayAabb2(rayFrom,rayDirectionInverse,signs,bounds,tmin,lambda_min,lambda_max);
- if(result1)
+ const b3DbvtNode* node = stack[--depth];
+ bounds[0] = node->volume.Mins() - aabbMax;
+ bounds[1] = node->volume.Maxs() - aabbMin;
+ b3Scalar tmin = 1.f, lambda_min = 0.f;
+ unsigned int result1 = false;
+ result1 = b3RayAabb2(rayFrom, rayDirectionInverse, signs, bounds, tmin, lambda_min, lambda_max);
+ if (result1)
{
- if(node->isinternal())
+ if (node->isinternal())
{
- if(depth>treshold)
+ if (depth > treshold)
{
- stack.resize(stack.size()*2);
- treshold=stack.size()-2;
+ stack.resize(stack.size() * 2);
+ treshold = stack.size() - 2;
}
- stack[depth++]=node->childs[0];
- stack[depth++]=node->childs[1];
+ stack[depth++] = node->childs[0];
+ stack[depth++] = node->childs[1];
}
else
{
policy.Process(node);
}
}
- } while(depth);
+ } while (depth);
}
}
//
B3_DBVT_PREFIX
-inline void b3DynamicBvh::rayTest( const b3DbvtNode* root,
- const b3Vector3& rayFrom,
- const b3Vector3& rayTo,
- B3_DBVT_IPOLICY)
+inline void b3DynamicBvh::rayTest(const b3DbvtNode* root,
+ const b3Vector3& rayFrom,
+ const b3Vector3& rayTo,
+ B3_DBVT_IPOLICY)
{
B3_DBVT_CHECKTYPE
- if(root)
- {
- b3Vector3 rayDir = (rayTo-rayFrom);
- rayDir.normalize ();
+ if (root)
+ {
+ b3Vector3 rayDir = (rayTo - rayFrom);
+ rayDir.normalize();
- ///what about division by zero? --> just set rayDirection[i] to INF/B3_LARGE_FLOAT
- b3Vector3 rayDirectionInverse;
- rayDirectionInverse[0] = rayDir[0] == b3Scalar(0.0) ? b3Scalar(B3_LARGE_FLOAT) : b3Scalar(1.0) / rayDir[0];
- rayDirectionInverse[1] = rayDir[1] == b3Scalar(0.0) ? b3Scalar(B3_LARGE_FLOAT) : b3Scalar(1.0) / rayDir[1];
- rayDirectionInverse[2] = rayDir[2] == b3Scalar(0.0) ? b3Scalar(B3_LARGE_FLOAT) : b3Scalar(1.0) / rayDir[2];
- unsigned int signs[3] = { rayDirectionInverse[0] < 0.0, rayDirectionInverse[1] < 0.0, rayDirectionInverse[2] < 0.0};
+ ///what about division by zero? --> just set rayDirection[i] to INF/B3_LARGE_FLOAT
+ b3Vector3 rayDirectionInverse;
+ rayDirectionInverse[0] = rayDir[0] == b3Scalar(0.0) ? b3Scalar(B3_LARGE_FLOAT) : b3Scalar(1.0) / rayDir[0];
+ rayDirectionInverse[1] = rayDir[1] == b3Scalar(0.0) ? b3Scalar(B3_LARGE_FLOAT) : b3Scalar(1.0) / rayDir[1];
+ rayDirectionInverse[2] = rayDir[2] == b3Scalar(0.0) ? b3Scalar(B3_LARGE_FLOAT) : b3Scalar(1.0) / rayDir[2];
+ unsigned int signs[3] = {rayDirectionInverse[0] < 0.0, rayDirectionInverse[1] < 0.0, rayDirectionInverse[2] < 0.0};
- b3Scalar lambda_max = rayDir.dot(rayTo-rayFrom);
+ b3Scalar lambda_max = rayDir.dot(rayTo - rayFrom);
#ifdef COMPARE_BTRAY_AABB2
- b3Vector3 resultNormal;
-#endif//COMPARE_BTRAY_AABB2
-
- b3AlignedObjectArray<const b3DbvtNode*> stack;
+ b3Vector3 resultNormal;
+#endif //COMPARE_BTRAY_AABB2
- int depth=1;
- int treshold=B3_DOUBLE_STACKSIZE-2;
+ b3AlignedObjectArray<const b3DbvtNode*> stack;
- stack.resize(B3_DOUBLE_STACKSIZE);
- stack[0]=root;
- b3Vector3 bounds[2];
- do {
- const b3DbvtNode* node=stack[--depth];
+ int depth = 1;
+ int treshold = B3_DOUBLE_STACKSIZE - 2;
- bounds[0] = node->volume.Mins();
- bounds[1] = node->volume.Maxs();
-
- b3Scalar tmin=1.f,lambda_min=0.f;
- unsigned int result1 = b3RayAabb2(rayFrom,rayDirectionInverse,signs,bounds,tmin,lambda_min,lambda_max);
+ stack.resize(B3_DOUBLE_STACKSIZE);
+ stack[0] = root;
+ b3Vector3 bounds[2];
+ do
+ {
+ const b3DbvtNode* node = stack[--depth];
+
+ bounds[0] = node->volume.Mins();
+ bounds[1] = node->volume.Maxs();
+
+ b3Scalar tmin = 1.f, lambda_min = 0.f;
+ unsigned int result1 = b3RayAabb2(rayFrom, rayDirectionInverse, signs, bounds, tmin, lambda_min, lambda_max);
#ifdef COMPARE_BTRAY_AABB2
- b3Scalar param=1.f;
- bool result2 = b3RayAabb(rayFrom,rayTo,node->volume.Mins(),node->volume.Maxs(),param,resultNormal);
- b3Assert(result1 == result2);
-#endif //TEST_BTRAY_AABB2
+ b3Scalar param = 1.f;
+ bool result2 = b3RayAabb(rayFrom, rayTo, node->volume.Mins(), node->volume.Maxs(), param, resultNormal);
+ b3Assert(result1 == result2);
+#endif //TEST_BTRAY_AABB2
- if(result1)
+ if (result1)
+ {
+ if (node->isinternal())
{
- if(node->isinternal())
- {
- if(depth>treshold)
- {
- stack.resize(stack.size()*2);
- treshold=stack.size()-2;
- }
- stack[depth++]=node->childs[0];
- stack[depth++]=node->childs[1];
- }
- else
+ if (depth > treshold)
{
- policy.Process(node);
+ stack.resize(stack.size() * 2);
+ treshold = stack.size() - 2;
}
+ stack[depth++] = node->childs[0];
+ stack[depth++] = node->childs[1];
}
- } while(depth);
-
- }
+ else
+ {
+ policy.Process(node);
+ }
+ }
+ } while (depth);
+ }
}
//
B3_DBVT_PREFIX
-inline void b3DynamicBvh::collideKDOP(const b3DbvtNode* root,
- const b3Vector3* normals,
- const b3Scalar* offsets,
- int count,
- B3_DBVT_IPOLICY)
+inline void b3DynamicBvh::collideKDOP(const b3DbvtNode* root,
+ const b3Vector3* normals,
+ const b3Scalar* offsets,
+ int count,
+ B3_DBVT_IPOLICY)
{
B3_DBVT_CHECKTYPE
- if(root)
+ if (root)
+ {
+ const int inside = (1 << count) - 1;
+ b3AlignedObjectArray<sStkNP> stack;
+ int signs[sizeof(unsigned) * 8];
+ b3Assert(count < int(sizeof(signs) / sizeof(signs[0])));
+ for (int i = 0; i < count; ++i)
{
- const int inside=(1<<count)-1;
- b3AlignedObjectArray<sStkNP> stack;
- int signs[sizeof(unsigned)*8];
- b3Assert(count<int (sizeof(signs)/sizeof(signs[0])));
- for(int i=0;i<count;++i)
+ signs[i] = ((normals[i].x >= 0) ? 1 : 0) +
+ ((normals[i].y >= 0) ? 2 : 0) +
+ ((normals[i].z >= 0) ? 4 : 0);
+ }
+ stack.reserve(B3_SIMPLE_STACKSIZE);
+ stack.push_back(sStkNP(root, 0));
+ do
+ {
+ sStkNP se = stack[stack.size() - 1];
+ bool out = false;
+ stack.pop_back();
+ for (int i = 0, j = 1; (!out) && (i < count); ++i, j <<= 1)
{
- signs[i]= ((normals[i].x>=0)?1:0)+
- ((normals[i].y>=0)?2:0)+
- ((normals[i].z>=0)?4:0);
- }
- stack.reserve(B3_SIMPLE_STACKSIZE);
- stack.push_back(sStkNP(root,0));
- do {
- sStkNP se=stack[stack.size()-1];
- bool out=false;
- stack.pop_back();
- for(int i=0,j=1;(!out)&&(i<count);++i,j<<=1)
+ if (0 == (se.mask & j))
{
- if(0==(se.mask&j))
+ const int side = se.node->volume.Classify(normals[i], offsets[i], signs[i]);
+ switch (side)
{
- const int side=se.node->volume.Classify(normals[i],offsets[i],signs[i]);
- switch(side)
- {
- case -1: out=true;break;
- case +1: se.mask|=j;break;
- }
+ case -1:
+ out = true;
+ break;
+ case +1:
+ se.mask |= j;
+ break;
}
}
- if(!out)
+ }
+ if (!out)
+ {
+ if ((se.mask != inside) && (se.node->isinternal()))
{
- if((se.mask!=inside)&&(se.node->isinternal()))
- {
- stack.push_back(sStkNP(se.node->childs[0],se.mask));
- stack.push_back(sStkNP(se.node->childs[1],se.mask));
- }
- else
- {
- if(policy.AllLeaves(se.node)) enumLeaves(se.node,policy);
- }
+ stack.push_back(sStkNP(se.node->childs[0], se.mask));
+ stack.push_back(sStkNP(se.node->childs[1], se.mask));
}
- } while(stack.size());
- }
+ else
+ {
+ if (policy.AllLeaves(se.node)) enumLeaves(se.node, policy);
+ }
+ }
+ } while (stack.size());
+ }
}
//
B3_DBVT_PREFIX
-inline void b3DynamicBvh::collideOCL( const b3DbvtNode* root,
- const b3Vector3* normals,
- const b3Scalar* offsets,
- const b3Vector3& sortaxis,
- int count,
- B3_DBVT_IPOLICY,
- bool fsort)
+inline void b3DynamicBvh::collideOCL(const b3DbvtNode* root,
+ const b3Vector3* normals,
+ const b3Scalar* offsets,
+ const b3Vector3& sortaxis,
+ int count,
+ B3_DBVT_IPOLICY,
+ bool fsort)
{
B3_DBVT_CHECKTYPE
- if(root)
+ if (root)
+ {
+ const unsigned srtsgns = (sortaxis[0] >= 0 ? 1 : 0) +
+ (sortaxis[1] >= 0 ? 2 : 0) +
+ (sortaxis[2] >= 0 ? 4 : 0);
+ const int inside = (1 << count) - 1;
+ b3AlignedObjectArray<sStkNPS> stock;
+ b3AlignedObjectArray<int> ifree;
+ b3AlignedObjectArray<int> stack;
+ int signs[sizeof(unsigned) * 8];
+ b3Assert(count < int(sizeof(signs) / sizeof(signs[0])));
+ for (int i = 0; i < count; ++i)
{
- const unsigned srtsgns=(sortaxis[0]>=0?1:0)+
- (sortaxis[1]>=0?2:0)+
- (sortaxis[2]>=0?4:0);
- const int inside=(1<<count)-1;
- b3AlignedObjectArray<sStkNPS> stock;
- b3AlignedObjectArray<int> ifree;
- b3AlignedObjectArray<int> stack;
- int signs[sizeof(unsigned)*8];
- b3Assert(count<int (sizeof(signs)/sizeof(signs[0])));
- for(int i=0;i<count;++i)
+ signs[i] = ((normals[i].x >= 0) ? 1 : 0) +
+ ((normals[i].y >= 0) ? 2 : 0) +
+ ((normals[i].z >= 0) ? 4 : 0);
+ }
+ stock.reserve(B3_SIMPLE_STACKSIZE);
+ stack.reserve(B3_SIMPLE_STACKSIZE);
+ ifree.reserve(B3_SIMPLE_STACKSIZE);
+ stack.push_back(allocate(ifree, stock, sStkNPS(root, 0, root->volume.ProjectMinimum(sortaxis, srtsgns))));
+ do
+ {
+ const int id = stack[stack.size() - 1];
+ sStkNPS se = stock[id];
+ stack.pop_back();
+ ifree.push_back(id);
+ if (se.mask != inside)
{
- signs[i]= ((normals[i].x>=0)?1:0)+
- ((normals[i].y>=0)?2:0)+
- ((normals[i].z>=0)?4:0);
- }
- stock.reserve(B3_SIMPLE_STACKSIZE);
- stack.reserve(B3_SIMPLE_STACKSIZE);
- ifree.reserve(B3_SIMPLE_STACKSIZE);
- stack.push_back(allocate(ifree,stock,sStkNPS(root,0,root->volume.ProjectMinimum(sortaxis,srtsgns))));
- do {
- const int id=stack[stack.size()-1];
- sStkNPS se=stock[id];
- stack.pop_back();ifree.push_back(id);
- if(se.mask!=inside)
+ bool out = false;
+ for (int i = 0, j = 1; (!out) && (i < count); ++i, j <<= 1)
{
- bool out=false;
- for(int i=0,j=1;(!out)&&(i<count);++i,j<<=1)
+ if (0 == (se.mask & j))
{
- if(0==(se.mask&j))
+ const int side = se.node->volume.Classify(normals[i], offsets[i], signs[i]);
+ switch (side)
{
- const int side=se.node->volume.Classify(normals[i],offsets[i],signs[i]);
- switch(side)
- {
- case -1: out=true;break;
- case +1: se.mask|=j;break;
- }
+ case -1:
+ out = true;
+ break;
+ case +1:
+ se.mask |= j;
+ break;
}
}
- if(out) continue;
}
- if(policy.Descent(se.node))
+ if (out) continue;
+ }
+ if (policy.Descent(se.node))
+ {
+ if (se.node->isinternal())
{
- if(se.node->isinternal())
+ const b3DbvtNode* pns[] = {se.node->childs[0], se.node->childs[1]};
+ sStkNPS nes[] = {sStkNPS(pns[0], se.mask, pns[0]->volume.ProjectMinimum(sortaxis, srtsgns)),
+ sStkNPS(pns[1], se.mask, pns[1]->volume.ProjectMinimum(sortaxis, srtsgns))};
+ const int q = nes[0].value < nes[1].value ? 1 : 0;
+ int j = stack.size();
+ if (fsort && (j > 0))
{
- const b3DbvtNode* pns[]={ se.node->childs[0],se.node->childs[1]};
- sStkNPS nes[]={ sStkNPS(pns[0],se.mask,pns[0]->volume.ProjectMinimum(sortaxis,srtsgns)),
- sStkNPS(pns[1],se.mask,pns[1]->volume.ProjectMinimum(sortaxis,srtsgns))};
- const int q=nes[0].value<nes[1].value?1:0;
- int j=stack.size();
- if(fsort&&(j>0))
- {
- /* Insert 0 */
- j=nearest(&stack[0],&stock[0],nes[q].value,0,stack.size());
- stack.push_back(0);
+ /* Insert 0 */
+ j = nearest(&stack[0], &stock[0], nes[q].value, 0, stack.size());
+ stack.push_back(0);
#if B3_DBVT_USE_MEMMOVE
- memmove(&stack[j+1],&stack[j],sizeof(int)*(stack.size()-j-1));
+ memmove(&stack[j + 1], &stack[j], sizeof(int) * (stack.size() - j - 1));
#else
- for(int k=stack.size()-1;k>j;--k) stack[k]=stack[k-1];
+ for (int k = stack.size() - 1; k > j; --k) stack[k] = stack[k - 1];
#endif
- stack[j]=allocate(ifree,stock,nes[q]);
- /* Insert 1 */
- j=nearest(&stack[0],&stock[0],nes[1-q].value,j,stack.size());
- stack.push_back(0);
+ stack[j] = allocate(ifree, stock, nes[q]);
+ /* Insert 1 */
+ j = nearest(&stack[0], &stock[0], nes[1 - q].value, j, stack.size());
+ stack.push_back(0);
#if B3_DBVT_USE_MEMMOVE
- memmove(&stack[j+1],&stack[j],sizeof(int)*(stack.size()-j-1));
+ memmove(&stack[j + 1], &stack[j], sizeof(int) * (stack.size() - j - 1));
#else
- for(int k=stack.size()-1;k>j;--k) stack[k]=stack[k-1];
+ for (int k = stack.size() - 1; k > j; --k) stack[k] = stack[k - 1];
#endif
- stack[j]=allocate(ifree,stock,nes[1-q]);
- }
- else
- {
- stack.push_back(allocate(ifree,stock,nes[q]));
- stack.push_back(allocate(ifree,stock,nes[1-q]));
- }
+ stack[j] = allocate(ifree, stock, nes[1 - q]);
}
else
{
- policy.Process(se.node,se.value);
+ stack.push_back(allocate(ifree, stock, nes[q]));
+ stack.push_back(allocate(ifree, stock, nes[1 - q]));
}
}
- } while(stack.size());
- }
+ else
+ {
+ policy.Process(se.node, se.value);
+ }
+ }
+ } while (stack.size());
+ }
}
//
B3_DBVT_PREFIX
-inline void b3DynamicBvh::collideTU( const b3DbvtNode* root,
- B3_DBVT_IPOLICY)
+inline void b3DynamicBvh::collideTU(const b3DbvtNode* root,
+ B3_DBVT_IPOLICY)
{
B3_DBVT_CHECKTYPE
- if(root)
+ if (root)
+ {
+ b3AlignedObjectArray<const b3DbvtNode*> stack;
+ stack.reserve(B3_SIMPLE_STACKSIZE);
+ stack.push_back(root);
+ do
{
- b3AlignedObjectArray<const b3DbvtNode*> stack;
- stack.reserve(B3_SIMPLE_STACKSIZE);
- stack.push_back(root);
- do {
- const b3DbvtNode* n=stack[stack.size()-1];
- stack.pop_back();
- if(policy.Descent(n))
+ const b3DbvtNode* n = stack[stack.size() - 1];
+ stack.pop_back();
+ if (policy.Descent(n))
+ {
+ if (n->isinternal())
{
- if(n->isinternal())
- { stack.push_back(n->childs[0]);stack.push_back(n->childs[1]); }
- else
- { policy.Process(n); }
+ stack.push_back(n->childs[0]);
+ stack.push_back(n->childs[1]);
}
- } while(stack.size()>0);
- }
+ else
+ {
+ policy.Process(n);
+ }
+ }
+ } while (stack.size() > 0);
+ }
}
//
diff --git a/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.cpp b/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.cpp
index bc150955b8..dea2ddb0f2 100644
--- a/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.cpp
+++ b/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.cpp
@@ -22,28 +22,27 @@ subject to the following restrictions:
// Profiling
//
-#if B3_DBVT_BP_PROFILE||B3_DBVT_BP_ENABLE_BENCHMARK
+#if B3_DBVT_BP_PROFILE || B3_DBVT_BP_ENABLE_BENCHMARK
#include <stdio.h>
#endif
#if B3_DBVT_BP_PROFILE
-struct b3ProfileScope
+struct b3ProfileScope
{
- __forceinline b3ProfileScope(b3Clock& clock,unsigned long& value) :
- m_clock(&clock),m_value(&value),m_base(clock.getTimeMicroseconds())
+ __forceinline b3ProfileScope(b3Clock& clock, unsigned long& value) : m_clock(&clock), m_value(&value), m_base(clock.getTimeMicroseconds())
{
}
__forceinline ~b3ProfileScope()
{
- (*m_value)+=m_clock->getTimeMicroseconds()-m_base;
+ (*m_value) += m_clock->getTimeMicroseconds() - m_base;
}
- b3Clock* m_clock;
- unsigned long* m_value;
- unsigned long m_base;
+ b3Clock* m_clock;
+ unsigned long* m_value;
+ unsigned long m_base;
};
-#define b3SPC(_value_) b3ProfileScope spc_scope(m_clock,_value_)
+#define b3SPC(_value_) b3ProfileScope spc_scope(m_clock, _value_)
#else
-#define b3SPC(_value_)
+#define b3SPC(_value_)
#endif
//
@@ -52,66 +51,75 @@ struct b3ProfileScope
//
template <typename T>
-static inline void b3ListAppend(T* item,T*& list)
+static inline void b3ListAppend(T* item, T*& list)
{
- item->links[0]=0;
- item->links[1]=list;
- if(list) list->links[0]=item;
- list=item;
+ item->links[0] = 0;
+ item->links[1] = list;
+ if (list) list->links[0] = item;
+ list = item;
}
//
template <typename T>
-static inline void b3ListRemove(T* item,T*& list)
+static inline void b3ListRemove(T* item, T*& list)
{
- if(item->links[0]) item->links[0]->links[1]=item->links[1]; else list=item->links[1];
- if(item->links[1]) item->links[1]->links[0]=item->links[0];
+ if (item->links[0])
+ item->links[0]->links[1] = item->links[1];
+ else
+ list = item->links[1];
+ if (item->links[1]) item->links[1]->links[0] = item->links[0];
}
//
template <typename T>
-static inline int b3ListCount(T* root)
+static inline int b3ListCount(T* root)
{
- int n=0;
- while(root) { ++n;root=root->links[1]; }
- return(n);
+ int n = 0;
+ while (root)
+ {
+ ++n;
+ root = root->links[1];
+ }
+ return (n);
}
//
template <typename T>
-static inline void b3Clear(T& value)
+static inline void b3Clear(T& value)
{
- static const struct ZeroDummy : T {} zerodummy;
- value=zerodummy;
+ static const struct ZeroDummy : T
+ {
+ } zerodummy;
+ value = zerodummy;
}
//
// Colliders
//
-/* Tree collider */
-struct b3DbvtTreeCollider : b3DynamicBvh::ICollide
+/* Tree collider */
+struct b3DbvtTreeCollider : b3DynamicBvh::ICollide
{
- b3DynamicBvhBroadphase* pbp;
- b3DbvtProxy* proxy;
+ b3DynamicBvhBroadphase* pbp;
+ b3DbvtProxy* proxy;
b3DbvtTreeCollider(b3DynamicBvhBroadphase* p) : pbp(p) {}
- void Process(const b3DbvtNode* na,const b3DbvtNode* nb)
+ void Process(const b3DbvtNode* na, const b3DbvtNode* nb)
{
- if(na!=nb)
+ if (na != nb)
{
- b3DbvtProxy* pa=(b3DbvtProxy*)na->data;
- b3DbvtProxy* pb=(b3DbvtProxy*)nb->data;
+ b3DbvtProxy* pa = (b3DbvtProxy*)na->data;
+ b3DbvtProxy* pb = (b3DbvtProxy*)nb->data;
#if B3_DBVT_BP_SORTPAIRS
- if(pa->m_uniqueId>pb->m_uniqueId)
- b3Swap(pa,pb);
+ if (pa->m_uniqueId > pb->m_uniqueId)
+ b3Swap(pa, pb);
#endif
- pbp->m_paircache->addOverlappingPair(pa->getUid(),pb->getUid());
+ pbp->m_paircache->addOverlappingPair(pa->getUid(), pb->getUid());
++pbp->m_newpairs;
}
}
- void Process(const b3DbvtNode* n)
+ void Process(const b3DbvtNode* n)
{
- Process(n,proxy->leaf);
+ Process(n, proxy->leaf);
}
};
@@ -122,26 +130,26 @@ struct b3DbvtTreeCollider : b3DynamicBvh::ICollide
//
b3DynamicBvhBroadphase::b3DynamicBvhBroadphase(int proxyCapacity, b3OverlappingPairCache* paircache)
{
- m_deferedcollide = false;
- m_needcleanup = true;
- m_releasepaircache = (paircache!=0)?false:true;
- m_prediction = 0;
- m_stageCurrent = 0;
- m_fixedleft = 0;
- m_fupdates = 1;
- m_dupdates = 0;
- m_cupdates = 10;
- m_newpairs = 1;
- m_updates_call = 0;
- m_updates_done = 0;
- m_updates_ratio = 0;
- m_paircache = paircache? paircache : new(b3AlignedAlloc(sizeof(b3HashedOverlappingPairCache),16)) b3HashedOverlappingPairCache();
-
- m_pid = 0;
- m_cid = 0;
- for(int i=0;i<=STAGECOUNT;++i)
+ m_deferedcollide = false;
+ m_needcleanup = true;
+ m_releasepaircache = (paircache != 0) ? false : true;
+ m_prediction = 0;
+ m_stageCurrent = 0;
+ m_fixedleft = 0;
+ m_fupdates = 1;
+ m_dupdates = 0;
+ m_cupdates = 10;
+ m_newpairs = 1;
+ m_updates_call = 0;
+ m_updates_done = 0;
+ m_updates_ratio = 0;
+ m_paircache = paircache ? paircache : new (b3AlignedAlloc(sizeof(b3HashedOverlappingPairCache), 16)) b3HashedOverlappingPairCache();
+
+ m_pid = 0;
+ m_cid = 0;
+ for (int i = 0; i <= STAGECOUNT; ++i)
{
- m_stageRoots[i]=0;
+ m_stageRoots[i] = 0;
}
#if B3_DBVT_BP_PROFILE
b3Clear(m_profiling);
@@ -152,7 +160,7 @@ b3DynamicBvhBroadphase::b3DynamicBvhBroadphase(int proxyCapacity, b3OverlappingP
//
b3DynamicBvhBroadphase::~b3DynamicBvhBroadphase()
{
- if(m_releasepaircache)
+ if (m_releasepaircache)
{
m_paircache->~b3OverlappingPairCache();
b3AlignedFree(m_paircache);
@@ -160,53 +168,53 @@ b3DynamicBvhBroadphase::~b3DynamicBvhBroadphase()
}
//
-b3BroadphaseProxy* b3DynamicBvhBroadphase::createProxy( const b3Vector3& aabbMin,
- const b3Vector3& aabbMax,
- int objectId,
- void* userPtr,
- int collisionFilterGroup,
- int collisionFilterMask)
+b3BroadphaseProxy* b3DynamicBvhBroadphase::createProxy(const b3Vector3& aabbMin,
+ const b3Vector3& aabbMax,
+ int objectId,
+ void* userPtr,
+ int collisionFilterGroup,
+ int collisionFilterMask)
{
b3DbvtProxy* mem = &m_proxies[objectId];
- b3DbvtProxy* proxy=new(mem) b3DbvtProxy( aabbMin,aabbMax,userPtr,
- collisionFilterGroup,
- collisionFilterMask);
+ b3DbvtProxy* proxy = new (mem) b3DbvtProxy(aabbMin, aabbMax, userPtr,
+ collisionFilterGroup,
+ collisionFilterMask);
- b3DbvtAabbMm aabb = b3DbvtVolume::FromMM(aabbMin,aabbMax);
+ b3DbvtAabbMm aabb = b3DbvtVolume::FromMM(aabbMin, aabbMax);
//bproxy->aabb = b3DbvtVolume::FromMM(aabbMin,aabbMax);
- proxy->stage = m_stageCurrent;
- proxy->m_uniqueId = objectId;
- proxy->leaf = m_sets[0].insert(aabb,proxy);
- b3ListAppend(proxy,m_stageRoots[m_stageCurrent]);
- if(!m_deferedcollide)
+ proxy->stage = m_stageCurrent;
+ proxy->m_uniqueId = objectId;
+ proxy->leaf = m_sets[0].insert(aabb, proxy);
+ b3ListAppend(proxy, m_stageRoots[m_stageCurrent]);
+ if (!m_deferedcollide)
{
- b3DbvtTreeCollider collider(this);
- collider.proxy=proxy;
- m_sets[0].collideTV(m_sets[0].m_root,aabb,collider);
- m_sets[1].collideTV(m_sets[1].m_root,aabb,collider);
+ b3DbvtTreeCollider collider(this);
+ collider.proxy = proxy;
+ m_sets[0].collideTV(m_sets[0].m_root, aabb, collider);
+ m_sets[1].collideTV(m_sets[1].m_root, aabb, collider);
}
- return(proxy);
+ return (proxy);
}
//
-void b3DynamicBvhBroadphase::destroyProxy( b3BroadphaseProxy* absproxy,
- b3Dispatcher* dispatcher)
+void b3DynamicBvhBroadphase::destroyProxy(b3BroadphaseProxy* absproxy,
+ b3Dispatcher* dispatcher)
{
- b3DbvtProxy* proxy=(b3DbvtProxy*)absproxy;
- if(proxy->stage==STAGECOUNT)
+ b3DbvtProxy* proxy = (b3DbvtProxy*)absproxy;
+ if (proxy->stage == STAGECOUNT)
m_sets[1].remove(proxy->leaf);
else
m_sets[0].remove(proxy->leaf);
- b3ListRemove(proxy,m_stageRoots[proxy->stage]);
- m_paircache->removeOverlappingPairsContainingProxy(proxy->getUid(),dispatcher);
-
- m_needcleanup=true;
+ b3ListRemove(proxy, m_stageRoots[proxy->stage]);
+ m_paircache->removeOverlappingPairsContainingProxy(proxy->getUid(), dispatcher);
+
+ m_needcleanup = true;
}
-void b3DynamicBvhBroadphase::getAabb(int objectId,b3Vector3& aabbMin, b3Vector3& aabbMax ) const
+void b3DynamicBvhBroadphase::getAabb(int objectId, b3Vector3& aabbMin, b3Vector3& aabbMax) const
{
- const b3DbvtProxy* proxy=&m_proxies[objectId];
+ const b3DbvtProxy* proxy = &m_proxies[objectId];
aabbMin = proxy->m_aabbMin;
aabbMax = proxy->m_aabbMax;
}
@@ -219,235 +227,223 @@ void b3DynamicBvhBroadphase::getAabb(b3BroadphaseProxy* absproxy,b3Vector3& aabb
}
*/
-
-struct BroadphaseRayTester : b3DynamicBvh::ICollide
+struct BroadphaseRayTester : b3DynamicBvh::ICollide
{
b3BroadphaseRayCallback& m_rayCallback;
BroadphaseRayTester(b3BroadphaseRayCallback& orgCallback)
- :m_rayCallback(orgCallback)
+ : m_rayCallback(orgCallback)
{
}
- void Process(const b3DbvtNode* leaf)
+ void Process(const b3DbvtNode* leaf)
{
- b3DbvtProxy* proxy=(b3DbvtProxy*)leaf->data;
+ b3DbvtProxy* proxy = (b3DbvtProxy*)leaf->data;
m_rayCallback.process(proxy);
}
-};
+};
-void b3DynamicBvhBroadphase::rayTest(const b3Vector3& rayFrom,const b3Vector3& rayTo, b3BroadphaseRayCallback& rayCallback,const b3Vector3& aabbMin,const b3Vector3& aabbMax)
+void b3DynamicBvhBroadphase::rayTest(const b3Vector3& rayFrom, const b3Vector3& rayTo, b3BroadphaseRayCallback& rayCallback, const b3Vector3& aabbMin, const b3Vector3& aabbMax)
{
BroadphaseRayTester callback(rayCallback);
- m_sets[0].rayTestInternal( m_sets[0].m_root,
- rayFrom,
- rayTo,
- rayCallback.m_rayDirectionInverse,
- rayCallback.m_signs,
- rayCallback.m_lambda_max,
- aabbMin,
- aabbMax,
- callback);
-
- m_sets[1].rayTestInternal( m_sets[1].m_root,
- rayFrom,
- rayTo,
- rayCallback.m_rayDirectionInverse,
- rayCallback.m_signs,
- rayCallback.m_lambda_max,
- aabbMin,
- aabbMax,
- callback);
-
+ m_sets[0].rayTestInternal(m_sets[0].m_root,
+ rayFrom,
+ rayTo,
+ rayCallback.m_rayDirectionInverse,
+ rayCallback.m_signs,
+ rayCallback.m_lambda_max,
+ aabbMin,
+ aabbMax,
+ callback);
+
+ m_sets[1].rayTestInternal(m_sets[1].m_root,
+ rayFrom,
+ rayTo,
+ rayCallback.m_rayDirectionInverse,
+ rayCallback.m_signs,
+ rayCallback.m_lambda_max,
+ aabbMin,
+ aabbMax,
+ callback);
}
-
-struct BroadphaseAabbTester : b3DynamicBvh::ICollide
+struct BroadphaseAabbTester : b3DynamicBvh::ICollide
{
b3BroadphaseAabbCallback& m_aabbCallback;
BroadphaseAabbTester(b3BroadphaseAabbCallback& orgCallback)
- :m_aabbCallback(orgCallback)
+ : m_aabbCallback(orgCallback)
{
}
- void Process(const b3DbvtNode* leaf)
+ void Process(const b3DbvtNode* leaf)
{
- b3DbvtProxy* proxy=(b3DbvtProxy*)leaf->data;
+ b3DbvtProxy* proxy = (b3DbvtProxy*)leaf->data;
m_aabbCallback.process(proxy);
}
-};
+};
-void b3DynamicBvhBroadphase::aabbTest(const b3Vector3& aabbMin,const b3Vector3& aabbMax,b3BroadphaseAabbCallback& aabbCallback)
+void b3DynamicBvhBroadphase::aabbTest(const b3Vector3& aabbMin, const b3Vector3& aabbMax, b3BroadphaseAabbCallback& aabbCallback)
{
BroadphaseAabbTester callback(aabbCallback);
- const B3_ATTRIBUTE_ALIGNED16(b3DbvtVolume) bounds=b3DbvtVolume::FromMM(aabbMin,aabbMax);
- //process all children, that overlap with the given AABB bounds
- m_sets[0].collideTV(m_sets[0].m_root,bounds,callback);
- m_sets[1].collideTV(m_sets[1].m_root,bounds,callback);
-
+ const B3_ATTRIBUTE_ALIGNED16(b3DbvtVolume) bounds = b3DbvtVolume::FromMM(aabbMin, aabbMax);
+ //process all children, that overlap with the given AABB bounds
+ m_sets[0].collideTV(m_sets[0].m_root, bounds, callback);
+ m_sets[1].collideTV(m_sets[1].m_root, bounds, callback);
}
-
-
//
-void b3DynamicBvhBroadphase::setAabb(int objectId,
- const b3Vector3& aabbMin,
- const b3Vector3& aabbMax,
- b3Dispatcher* /*dispatcher*/)
+void b3DynamicBvhBroadphase::setAabb(int objectId,
+ const b3Vector3& aabbMin,
+ const b3Vector3& aabbMax,
+ b3Dispatcher* /*dispatcher*/)
{
- b3DbvtProxy* proxy=&m_proxies[objectId];
-// b3DbvtProxy* proxy=(b3DbvtProxy*)absproxy;
- B3_ATTRIBUTE_ALIGNED16(b3DbvtVolume) aabb=b3DbvtVolume::FromMM(aabbMin,aabbMax);
+ b3DbvtProxy* proxy = &m_proxies[objectId];
+ // b3DbvtProxy* proxy=(b3DbvtProxy*)absproxy;
+ B3_ATTRIBUTE_ALIGNED16(b3DbvtVolume)
+ aabb = b3DbvtVolume::FromMM(aabbMin, aabbMax);
#if B3_DBVT_BP_PREVENTFALSEUPDATE
- if(b3NotEqual(aabb,proxy->leaf->volume))
+ if (b3NotEqual(aabb, proxy->leaf->volume))
#endif
{
- bool docollide=false;
- if(proxy->stage==STAGECOUNT)
- {/* fixed -> dynamic set */
+ bool docollide = false;
+ if (proxy->stage == STAGECOUNT)
+ { /* fixed -> dynamic set */
m_sets[1].remove(proxy->leaf);
- proxy->leaf=m_sets[0].insert(aabb,proxy);
- docollide=true;
+ proxy->leaf = m_sets[0].insert(aabb, proxy);
+ docollide = true;
}
else
- {/* dynamic set */
+ { /* dynamic set */
++m_updates_call;
- if(b3Intersect(proxy->leaf->volume,aabb))
- {/* Moving */
-
- const b3Vector3 delta=aabbMin-proxy->m_aabbMin;
- b3Vector3 velocity(((proxy->m_aabbMax-proxy->m_aabbMin)/2)*m_prediction);
- if(delta[0]<0) velocity[0]=-velocity[0];
- if(delta[1]<0) velocity[1]=-velocity[1];
- if(delta[2]<0) velocity[2]=-velocity[2];
- if (
-#ifdef B3_DBVT_BP_MARGIN
- m_sets[0].update(proxy->leaf,aabb,velocity,B3_DBVT_BP_MARGIN)
+ if (b3Intersect(proxy->leaf->volume, aabb))
+ { /* Moving */
+
+ const b3Vector3 delta = aabbMin - proxy->m_aabbMin;
+ b3Vector3 velocity(((proxy->m_aabbMax - proxy->m_aabbMin) / 2) * m_prediction);
+ if (delta[0] < 0) velocity[0] = -velocity[0];
+ if (delta[1] < 0) velocity[1] = -velocity[1];
+ if (delta[2] < 0) velocity[2] = -velocity[2];
+ if (
+#ifdef B3_DBVT_BP_MARGIN
+ m_sets[0].update(proxy->leaf, aabb, velocity, B3_DBVT_BP_MARGIN)
#else
- m_sets[0].update(proxy->leaf,aabb,velocity)
+ m_sets[0].update(proxy->leaf, aabb, velocity)
#endif
- )
+ )
{
++m_updates_done;
- docollide=true;
+ docollide = true;
}
}
else
- {/* Teleporting */
- m_sets[0].update(proxy->leaf,aabb);
+ { /* Teleporting */
+ m_sets[0].update(proxy->leaf, aabb);
++m_updates_done;
- docollide=true;
- }
+ docollide = true;
+ }
}
- b3ListRemove(proxy,m_stageRoots[proxy->stage]);
+ b3ListRemove(proxy, m_stageRoots[proxy->stage]);
proxy->m_aabbMin = aabbMin;
proxy->m_aabbMax = aabbMax;
- proxy->stage = m_stageCurrent;
- b3ListAppend(proxy,m_stageRoots[m_stageCurrent]);
- if(docollide)
+ proxy->stage = m_stageCurrent;
+ b3ListAppend(proxy, m_stageRoots[m_stageCurrent]);
+ if (docollide)
{
- m_needcleanup=true;
- if(!m_deferedcollide)
+ m_needcleanup = true;
+ if (!m_deferedcollide)
{
- b3DbvtTreeCollider collider(this);
- m_sets[1].collideTTpersistentStack(m_sets[1].m_root,proxy->leaf,collider);
- m_sets[0].collideTTpersistentStack(m_sets[0].m_root,proxy->leaf,collider);
+ b3DbvtTreeCollider collider(this);
+ m_sets[1].collideTTpersistentStack(m_sets[1].m_root, proxy->leaf, collider);
+ m_sets[0].collideTTpersistentStack(m_sets[0].m_root, proxy->leaf, collider);
}
- }
+ }
}
}
-
//
-void b3DynamicBvhBroadphase::setAabbForceUpdate( b3BroadphaseProxy* absproxy,
- const b3Vector3& aabbMin,
- const b3Vector3& aabbMax,
- b3Dispatcher* /*dispatcher*/)
+void b3DynamicBvhBroadphase::setAabbForceUpdate(b3BroadphaseProxy* absproxy,
+ const b3Vector3& aabbMin,
+ const b3Vector3& aabbMax,
+ b3Dispatcher* /*dispatcher*/)
{
- b3DbvtProxy* proxy=(b3DbvtProxy*)absproxy;
- B3_ATTRIBUTE_ALIGNED16(b3DbvtVolume) aabb=b3DbvtVolume::FromMM(aabbMin,aabbMax);
- bool docollide=false;
- if(proxy->stage==STAGECOUNT)
- {/* fixed -> dynamic set */
+ b3DbvtProxy* proxy = (b3DbvtProxy*)absproxy;
+ B3_ATTRIBUTE_ALIGNED16(b3DbvtVolume)
+ aabb = b3DbvtVolume::FromMM(aabbMin, aabbMax);
+ bool docollide = false;
+ if (proxy->stage == STAGECOUNT)
+ { /* fixed -> dynamic set */
m_sets[1].remove(proxy->leaf);
- proxy->leaf=m_sets[0].insert(aabb,proxy);
- docollide=true;
+ proxy->leaf = m_sets[0].insert(aabb, proxy);
+ docollide = true;
}
else
- {/* dynamic set */
+ { /* dynamic set */
++m_updates_call;
- /* Teleporting */
- m_sets[0].update(proxy->leaf,aabb);
+ /* Teleporting */
+ m_sets[0].update(proxy->leaf, aabb);
++m_updates_done;
- docollide=true;
+ docollide = true;
}
- b3ListRemove(proxy,m_stageRoots[proxy->stage]);
+ b3ListRemove(proxy, m_stageRoots[proxy->stage]);
proxy->m_aabbMin = aabbMin;
proxy->m_aabbMax = aabbMax;
- proxy->stage = m_stageCurrent;
- b3ListAppend(proxy,m_stageRoots[m_stageCurrent]);
- if(docollide)
+ proxy->stage = m_stageCurrent;
+ b3ListAppend(proxy, m_stageRoots[m_stageCurrent]);
+ if (docollide)
{
- m_needcleanup=true;
- if(!m_deferedcollide)
+ m_needcleanup = true;
+ if (!m_deferedcollide)
{
- b3DbvtTreeCollider collider(this);
- m_sets[1].collideTTpersistentStack(m_sets[1].m_root,proxy->leaf,collider);
- m_sets[0].collideTTpersistentStack(m_sets[0].m_root,proxy->leaf,collider);
+ b3DbvtTreeCollider collider(this);
+ m_sets[1].collideTTpersistentStack(m_sets[1].m_root, proxy->leaf, collider);
+ m_sets[0].collideTTpersistentStack(m_sets[0].m_root, proxy->leaf, collider);
}
- }
+ }
}
//
-void b3DynamicBvhBroadphase::calculateOverlappingPairs(b3Dispatcher* dispatcher)
+void b3DynamicBvhBroadphase::calculateOverlappingPairs(b3Dispatcher* dispatcher)
{
collide(dispatcher);
#if B3_DBVT_BP_PROFILE
- if(0==(m_pid%B3_DBVT_BP_PROFILING_RATE))
- {
- printf("fixed(%u) dynamics(%u) pairs(%u)\r\n",m_sets[1].m_leaves,m_sets[0].m_leaves,m_paircache->getNumOverlappingPairs());
- unsigned int total=m_profiling.m_total;
- if(total<=0) total=1;
- printf("ddcollide: %u%% (%uus)\r\n",(50+m_profiling.m_ddcollide*100)/total,m_profiling.m_ddcollide/B3_DBVT_BP_PROFILING_RATE);
- printf("fdcollide: %u%% (%uus)\r\n",(50+m_profiling.m_fdcollide*100)/total,m_profiling.m_fdcollide/B3_DBVT_BP_PROFILING_RATE);
- printf("cleanup: %u%% (%uus)\r\n",(50+m_profiling.m_cleanup*100)/total,m_profiling.m_cleanup/B3_DBVT_BP_PROFILING_RATE);
- printf("total: %uus\r\n",total/B3_DBVT_BP_PROFILING_RATE);
- const unsigned long sum=m_profiling.m_ddcollide+
- m_profiling.m_fdcollide+
- m_profiling.m_cleanup;
- printf("leaked: %u%% (%uus)\r\n",100-((50+sum*100)/total),(total-sum)/B3_DBVT_BP_PROFILING_RATE);
- printf("job counts: %u%%\r\n",(m_profiling.m_jobcount*100)/((m_sets[0].m_leaves+m_sets[1].m_leaves)*B3_DBVT_BP_PROFILING_RATE));
+ if (0 == (m_pid % B3_DBVT_BP_PROFILING_RATE))
+ {
+ printf("fixed(%u) dynamics(%u) pairs(%u)\r\n", m_sets[1].m_leaves, m_sets[0].m_leaves, m_paircache->getNumOverlappingPairs());
+ unsigned int total = m_profiling.m_total;
+ if (total <= 0) total = 1;
+ printf("ddcollide: %u%% (%uus)\r\n", (50 + m_profiling.m_ddcollide * 100) / total, m_profiling.m_ddcollide / B3_DBVT_BP_PROFILING_RATE);
+ printf("fdcollide: %u%% (%uus)\r\n", (50 + m_profiling.m_fdcollide * 100) / total, m_profiling.m_fdcollide / B3_DBVT_BP_PROFILING_RATE);
+ printf("cleanup: %u%% (%uus)\r\n", (50 + m_profiling.m_cleanup * 100) / total, m_profiling.m_cleanup / B3_DBVT_BP_PROFILING_RATE);
+ printf("total: %uus\r\n", total / B3_DBVT_BP_PROFILING_RATE);
+ const unsigned long sum = m_profiling.m_ddcollide +
+ m_profiling.m_fdcollide +
+ m_profiling.m_cleanup;
+ printf("leaked: %u%% (%uus)\r\n", 100 - ((50 + sum * 100) / total), (total - sum) / B3_DBVT_BP_PROFILING_RATE);
+ printf("job counts: %u%%\r\n", (m_profiling.m_jobcount * 100) / ((m_sets[0].m_leaves + m_sets[1].m_leaves) * B3_DBVT_BP_PROFILING_RATE));
b3Clear(m_profiling);
m_clock.reset();
}
#endif
performDeferredRemoval(dispatcher);
-
}
void b3DynamicBvhBroadphase::performDeferredRemoval(b3Dispatcher* dispatcher)
{
-
if (m_paircache->hasDeferredRemoval())
{
-
- b3BroadphasePairArray& overlappingPairArray = m_paircache->getOverlappingPairArray();
+ b3BroadphasePairArray& overlappingPairArray = m_paircache->getOverlappingPairArray();
//perform a sort, to find duplicates and to sort 'invalid' pairs to the end
overlappingPairArray.quickSort(b3BroadphasePairSortPredicate());
int invalidPair = 0;
-
int i;
- b3BroadphasePair previousPair = b3MakeBroadphasePair(-1,-1);
-
-
-
- for (i=0;i<overlappingPairArray.size();i++)
+ b3BroadphasePair previousPair = b3MakeBroadphasePair(-1, -1);
+
+ for (i = 0; i < overlappingPairArray.size(); i++)
{
-
b3BroadphasePair& pair = overlappingPairArray[i];
bool isDuplicate = (pair == previousPair);
@@ -459,33 +455,34 @@ void b3DynamicBvhBroadphase::performDeferredRemoval(b3Dispatcher* dispatcher)
if (!isDuplicate)
{
//important to perform AABB check that is consistent with the broadphase
- b3DbvtProxy* pa=&m_proxies[pair.x];
- b3DbvtProxy* pb=&m_proxies[pair.y];
- bool hasOverlap = b3Intersect(pa->leaf->volume,pb->leaf->volume);
+ b3DbvtProxy* pa = &m_proxies[pair.x];
+ b3DbvtProxy* pb = &m_proxies[pair.y];
+ bool hasOverlap = b3Intersect(pa->leaf->volume, pb->leaf->volume);
if (hasOverlap)
{
needsRemoval = false;
- } else
+ }
+ else
{
needsRemoval = true;
}
- } else
+ }
+ else
{
//remove duplicate
needsRemoval = true;
//should have no algorithm
}
-
+
if (needsRemoval)
{
- m_paircache->cleanOverlappingPair(pair,dispatcher);
+ m_paircache->cleanOverlappingPair(pair, dispatcher);
pair.x = -1;
pair.y = -1;
invalidPair++;
- }
-
+ }
}
//perform a sort, to sort 'invalid' pairs to the end
@@ -495,7 +492,7 @@ void b3DynamicBvhBroadphase::performDeferredRemoval(b3Dispatcher* dispatcher)
}
//
-void b3DynamicBvhBroadphase::collide(b3Dispatcher* dispatcher)
+void b3DynamicBvhBroadphase::collide(b3Dispatcher* dispatcher)
{
/*printf("---------------------------------------------------------\n");
printf("m_sets[0].m_leaves=%d\n",m_sets[0].m_leaves);
@@ -512,285 +509,293 @@ void b3DynamicBvhBroadphase::collide(b3Dispatcher* dispatcher)
}
*/
-
-
b3SPC(m_profiling.m_total);
- /* optimize */
- m_sets[0].optimizeIncremental(1+(m_sets[0].m_leaves*m_dupdates)/100);
- if(m_fixedleft)
+ /* optimize */
+ m_sets[0].optimizeIncremental(1 + (m_sets[0].m_leaves * m_dupdates) / 100);
+ if (m_fixedleft)
{
- const int count=1+(m_sets[1].m_leaves*m_fupdates)/100;
- m_sets[1].optimizeIncremental(1+(m_sets[1].m_leaves*m_fupdates)/100);
- m_fixedleft=b3Max<int>(0,m_fixedleft-count);
+ const int count = 1 + (m_sets[1].m_leaves * m_fupdates) / 100;
+ m_sets[1].optimizeIncremental(1 + (m_sets[1].m_leaves * m_fupdates) / 100);
+ m_fixedleft = b3Max<int>(0, m_fixedleft - count);
}
- /* dynamic -> fixed set */
- m_stageCurrent=(m_stageCurrent+1)%STAGECOUNT;
- b3DbvtProxy* current=m_stageRoots[m_stageCurrent];
- if(current)
+ /* dynamic -> fixed set */
+ m_stageCurrent = (m_stageCurrent + 1) % STAGECOUNT;
+ b3DbvtProxy* current = m_stageRoots[m_stageCurrent];
+ if (current)
{
- b3DbvtTreeCollider collider(this);
- do {
- b3DbvtProxy* next=current->links[1];
- b3ListRemove(current,m_stageRoots[current->stage]);
- b3ListAppend(current,m_stageRoots[STAGECOUNT]);
+ b3DbvtTreeCollider collider(this);
+ do
+ {
+ b3DbvtProxy* next = current->links[1];
+ b3ListRemove(current, m_stageRoots[current->stage]);
+ b3ListAppend(current, m_stageRoots[STAGECOUNT]);
#if B3_DBVT_BP_ACCURATESLEEPING
- m_paircache->removeOverlappingPairsContainingProxy(current,dispatcher);
- collider.proxy=current;
- b3DynamicBvh::collideTV(m_sets[0].m_root,current->aabb,collider);
- b3DynamicBvh::collideTV(m_sets[1].m_root,current->aabb,collider);
+ m_paircache->removeOverlappingPairsContainingProxy(current, dispatcher);
+ collider.proxy = current;
+ b3DynamicBvh::collideTV(m_sets[0].m_root, current->aabb, collider);
+ b3DynamicBvh::collideTV(m_sets[1].m_root, current->aabb, collider);
#endif
m_sets[0].remove(current->leaf);
- B3_ATTRIBUTE_ALIGNED16(b3DbvtVolume) curAabb=b3DbvtVolume::FromMM(current->m_aabbMin,current->m_aabbMax);
- current->leaf = m_sets[1].insert(curAabb,current);
- current->stage = STAGECOUNT;
- current = next;
- } while(current);
- m_fixedleft=m_sets[1].m_leaves;
- m_needcleanup=true;
+ B3_ATTRIBUTE_ALIGNED16(b3DbvtVolume)
+ curAabb = b3DbvtVolume::FromMM(current->m_aabbMin, current->m_aabbMax);
+ current->leaf = m_sets[1].insert(curAabb, current);
+ current->stage = STAGECOUNT;
+ current = next;
+ } while (current);
+ m_fixedleft = m_sets[1].m_leaves;
+ m_needcleanup = true;
}
- /* collide dynamics */
+ /* collide dynamics */
{
- b3DbvtTreeCollider collider(this);
- if(m_deferedcollide)
+ b3DbvtTreeCollider collider(this);
+ if (m_deferedcollide)
{
b3SPC(m_profiling.m_fdcollide);
- m_sets[0].collideTTpersistentStack(m_sets[0].m_root,m_sets[1].m_root,collider);
+ m_sets[0].collideTTpersistentStack(m_sets[0].m_root, m_sets[1].m_root, collider);
}
- if(m_deferedcollide)
+ if (m_deferedcollide)
{
b3SPC(m_profiling.m_ddcollide);
- m_sets[0].collideTTpersistentStack(m_sets[0].m_root,m_sets[0].m_root,collider);
+ m_sets[0].collideTTpersistentStack(m_sets[0].m_root, m_sets[0].m_root, collider);
}
}
- /* clean up */
- if(m_needcleanup)
+ /* clean up */
+ if (m_needcleanup)
{
b3SPC(m_profiling.m_cleanup);
- b3BroadphasePairArray& pairs=m_paircache->getOverlappingPairArray();
- if(pairs.size()>0)
+ b3BroadphasePairArray& pairs = m_paircache->getOverlappingPairArray();
+ if (pairs.size() > 0)
{
-
- int ni=b3Min(pairs.size(),b3Max<int>(m_newpairs,(pairs.size()*m_cupdates)/100));
- for(int i=0;i<ni;++i)
+ int ni = b3Min(pairs.size(), b3Max<int>(m_newpairs, (pairs.size() * m_cupdates) / 100));
+ for (int i = 0; i < ni; ++i)
{
- b3BroadphasePair& p=pairs[(m_cid+i)%pairs.size()];
- b3DbvtProxy* pa=&m_proxies[p.x];
- b3DbvtProxy* pb=&m_proxies[p.y];
- if(!b3Intersect(pa->leaf->volume,pb->leaf->volume))
+ b3BroadphasePair& p = pairs[(m_cid + i) % pairs.size()];
+ b3DbvtProxy* pa = &m_proxies[p.x];
+ b3DbvtProxy* pb = &m_proxies[p.y];
+ if (!b3Intersect(pa->leaf->volume, pb->leaf->volume))
{
#if B3_DBVT_BP_SORTPAIRS
- if(pa->m_uniqueId>pb->m_uniqueId)
- b3Swap(pa,pb);
+ if (pa->m_uniqueId > pb->m_uniqueId)
+ b3Swap(pa, pb);
#endif
- m_paircache->removeOverlappingPair(pa->getUid(),pb->getUid(),dispatcher);
- --ni;--i;
+ m_paircache->removeOverlappingPair(pa->getUid(), pb->getUid(), dispatcher);
+ --ni;
+ --i;
}
}
- if(pairs.size()>0) m_cid=(m_cid+ni)%pairs.size(); else m_cid=0;
+ if (pairs.size() > 0)
+ m_cid = (m_cid + ni) % pairs.size();
+ else
+ m_cid = 0;
}
}
++m_pid;
- m_newpairs=1;
- m_needcleanup=false;
- if(m_updates_call>0)
- { m_updates_ratio=m_updates_done/(b3Scalar)m_updates_call; }
+ m_newpairs = 1;
+ m_needcleanup = false;
+ if (m_updates_call > 0)
+ {
+ m_updates_ratio = m_updates_done / (b3Scalar)m_updates_call;
+ }
else
- { m_updates_ratio=0; }
- m_updates_done/=2;
- m_updates_call/=2;
+ {
+ m_updates_ratio = 0;
+ }
+ m_updates_done /= 2;
+ m_updates_call /= 2;
}
//
-void b3DynamicBvhBroadphase::optimize()
+void b3DynamicBvhBroadphase::optimize()
{
m_sets[0].optimizeTopDown();
m_sets[1].optimizeTopDown();
}
//
-b3OverlappingPairCache* b3DynamicBvhBroadphase::getOverlappingPairCache()
+b3OverlappingPairCache* b3DynamicBvhBroadphase::getOverlappingPairCache()
{
- return(m_paircache);
+ return (m_paircache);
}
//
-const b3OverlappingPairCache* b3DynamicBvhBroadphase::getOverlappingPairCache() const
+const b3OverlappingPairCache* b3DynamicBvhBroadphase::getOverlappingPairCache() const
{
- return(m_paircache);
+ return (m_paircache);
}
//
-void b3DynamicBvhBroadphase::getBroadphaseAabb(b3Vector3& aabbMin,b3Vector3& aabbMax) const
+void b3DynamicBvhBroadphase::getBroadphaseAabb(b3Vector3& aabbMin, b3Vector3& aabbMax) const
{
+ B3_ATTRIBUTE_ALIGNED16(b3DbvtVolume)
+ bounds;
- B3_ATTRIBUTE_ALIGNED16(b3DbvtVolume) bounds;
-
- if(!m_sets[0].empty())
- if(!m_sets[1].empty()) b3Merge( m_sets[0].m_root->volume,
- m_sets[1].m_root->volume,bounds);
+ if (!m_sets[0].empty())
+ if (!m_sets[1].empty())
+ b3Merge(m_sets[0].m_root->volume,
+ m_sets[1].m_root->volume, bounds);
else
- bounds=m_sets[0].m_root->volume;
- else if(!m_sets[1].empty()) bounds=m_sets[1].m_root->volume;
+ bounds = m_sets[0].m_root->volume;
+ else if (!m_sets[1].empty())
+ bounds = m_sets[1].m_root->volume;
else
- bounds=b3DbvtVolume::FromCR(b3MakeVector3(0,0,0),0);
- aabbMin=bounds.Mins();
- aabbMax=bounds.Maxs();
+ bounds = b3DbvtVolume::FromCR(b3MakeVector3(0, 0, 0), 0);
+ aabbMin = bounds.Mins();
+ aabbMax = bounds.Maxs();
}
void b3DynamicBvhBroadphase::resetPool(b3Dispatcher* dispatcher)
{
-
int totalObjects = m_sets[0].m_leaves + m_sets[1].m_leaves;
if (!totalObjects)
{
//reset internal dynamic tree data structures
m_sets[0].clear();
m_sets[1].clear();
-
- m_deferedcollide = false;
- m_needcleanup = true;
- m_stageCurrent = 0;
- m_fixedleft = 0;
- m_fupdates = 1;
- m_dupdates = 0;
- m_cupdates = 10;
- m_newpairs = 1;
- m_updates_call = 0;
- m_updates_done = 0;
- m_updates_ratio = 0;
-
- m_pid = 0;
- m_cid = 0;
- for(int i=0;i<=STAGECOUNT;++i)
+
+ m_deferedcollide = false;
+ m_needcleanup = true;
+ m_stageCurrent = 0;
+ m_fixedleft = 0;
+ m_fupdates = 1;
+ m_dupdates = 0;
+ m_cupdates = 10;
+ m_newpairs = 1;
+ m_updates_call = 0;
+ m_updates_done = 0;
+ m_updates_ratio = 0;
+
+ m_pid = 0;
+ m_cid = 0;
+ for (int i = 0; i <= STAGECOUNT; ++i)
{
- m_stageRoots[i]=0;
+ m_stageRoots[i] = 0;
}
}
}
//
-void b3DynamicBvhBroadphase::printStats()
-{}
+void b3DynamicBvhBroadphase::printStats()
+{
+}
//
#if B3_DBVT_BP_ENABLE_BENCHMARK
-struct b3BroadphaseBenchmark
+struct b3BroadphaseBenchmark
{
- struct Experiment
+ struct Experiment
{
- const char* name;
- int object_count;
- int update_count;
- int spawn_count;
- int iterations;
- b3Scalar speed;
- b3Scalar amplitude;
+ const char* name;
+ int object_count;
+ int update_count;
+ int spawn_count;
+ int iterations;
+ b3Scalar speed;
+ b3Scalar amplitude;
};
- struct Object
+ struct Object
{
- b3Vector3 center;
- b3Vector3 extents;
- b3BroadphaseProxy* proxy;
- b3Scalar time;
- void update(b3Scalar speed,b3Scalar amplitude,b3BroadphaseInterface* pbi)
+ b3Vector3 center;
+ b3Vector3 extents;
+ b3BroadphaseProxy* proxy;
+ b3Scalar time;
+ void update(b3Scalar speed, b3Scalar amplitude, b3BroadphaseInterface* pbi)
{
- time += speed;
- center[0] = b3Cos(time*(b3Scalar)2.17)*amplitude+
- b3Sin(time)*amplitude/2;
- center[1] = b3Cos(time*(b3Scalar)1.38)*amplitude+
- b3Sin(time)*amplitude;
- center[2] = b3Sin(time*(b3Scalar)0.777)*amplitude;
- pbi->setAabb(proxy,center-extents,center+extents,0);
+ time += speed;
+ center[0] = b3Cos(time * (b3Scalar)2.17) * amplitude +
+ b3Sin(time) * amplitude / 2;
+ center[1] = b3Cos(time * (b3Scalar)1.38) * amplitude +
+ b3Sin(time) * amplitude;
+ center[2] = b3Sin(time * (b3Scalar)0.777) * amplitude;
+ pbi->setAabb(proxy, center - extents, center + extents, 0);
}
};
- static int UnsignedRand(int range=RAND_MAX-1) { return(rand()%(range+1)); }
- static b3Scalar UnitRand() { return(UnsignedRand(16384)/(b3Scalar)16384); }
- static void OutputTime(const char* name,b3Clock& c,unsigned count=0)
+ static int UnsignedRand(int range = RAND_MAX - 1) { return (rand() % (range + 1)); }
+ static b3Scalar UnitRand() { return (UnsignedRand(16384) / (b3Scalar)16384); }
+ static void OutputTime(const char* name, b3Clock& c, unsigned count = 0)
{
- const unsigned long us=c.getTimeMicroseconds();
- const unsigned long ms=(us+500)/1000;
- const b3Scalar sec=us/(b3Scalar)(1000*1000);
- if(count>0)
- printf("%s : %u us (%u ms), %.2f/s\r\n",name,us,ms,count/sec);
+ const unsigned long us = c.getTimeMicroseconds();
+ const unsigned long ms = (us + 500) / 1000;
+ const b3Scalar sec = us / (b3Scalar)(1000 * 1000);
+ if (count > 0)
+ printf("%s : %u us (%u ms), %.2f/s\r\n", name, us, ms, count / sec);
else
- printf("%s : %u us (%u ms)\r\n",name,us,ms);
+ printf("%s : %u us (%u ms)\r\n", name, us, ms);
}
};
-void b3DynamicBvhBroadphase::benchmark(b3BroadphaseInterface* pbi)
+void b3DynamicBvhBroadphase::benchmark(b3BroadphaseInterface* pbi)
{
- static const b3BroadphaseBenchmark::Experiment experiments[]=
- {
- {"1024o.10%",1024,10,0,8192,(b3Scalar)0.005,(b3Scalar)100},
- /*{"4096o.10%",4096,10,0,8192,(b3Scalar)0.005,(b3Scalar)100},
+ static const b3BroadphaseBenchmark::Experiment experiments[] =
+ {
+ {"1024o.10%", 1024, 10, 0, 8192, (b3Scalar)0.005, (b3Scalar)100},
+ /*{"4096o.10%",4096,10,0,8192,(b3Scalar)0.005,(b3Scalar)100},
{"8192o.10%",8192,10,0,8192,(b3Scalar)0.005,(b3Scalar)100},*/
- };
- static const int nexperiments=sizeof(experiments)/sizeof(experiments[0]);
- b3AlignedObjectArray<b3BroadphaseBenchmark::Object*> objects;
- b3Clock wallclock;
- /* Begin */
- for(int iexp=0;iexp<nexperiments;++iexp)
+ };
+ static const int nexperiments = sizeof(experiments) / sizeof(experiments[0]);
+ b3AlignedObjectArray<b3BroadphaseBenchmark::Object*> objects;
+ b3Clock wallclock;
+ /* Begin */
+ for (int iexp = 0; iexp < nexperiments; ++iexp)
{
- const b3BroadphaseBenchmark::Experiment& experiment=experiments[iexp];
- const int object_count=experiment.object_count;
- const int update_count=(object_count*experiment.update_count)/100;
- const int spawn_count=(object_count*experiment.spawn_count)/100;
- const b3Scalar speed=experiment.speed;
- const b3Scalar amplitude=experiment.amplitude;
- printf("Experiment #%u '%s':\r\n",iexp,experiment.name);
- printf("\tObjects: %u\r\n",object_count);
- printf("\tUpdate: %u\r\n",update_count);
- printf("\tSpawn: %u\r\n",spawn_count);
- printf("\tSpeed: %f\r\n",speed);
- printf("\tAmplitude: %f\r\n",amplitude);
+ const b3BroadphaseBenchmark::Experiment& experiment = experiments[iexp];
+ const int object_count = experiment.object_count;
+ const int update_count = (object_count * experiment.update_count) / 100;
+ const int spawn_count = (object_count * experiment.spawn_count) / 100;
+ const b3Scalar speed = experiment.speed;
+ const b3Scalar amplitude = experiment.amplitude;
+ printf("Experiment #%u '%s':\r\n", iexp, experiment.name);
+ printf("\tObjects: %u\r\n", object_count);
+ printf("\tUpdate: %u\r\n", update_count);
+ printf("\tSpawn: %u\r\n", spawn_count);
+ printf("\tSpeed: %f\r\n", speed);
+ printf("\tAmplitude: %f\r\n", amplitude);
srand(180673);
- /* Create objects */
+ /* Create objects */
wallclock.reset();
objects.reserve(object_count);
- for(int i=0;i<object_count;++i)
+ for (int i = 0; i < object_count; ++i)
{
- b3BroadphaseBenchmark::Object* po=new b3BroadphaseBenchmark::Object();
- po->center[0]=b3BroadphaseBenchmark::UnitRand()*50;
- po->center[1]=b3BroadphaseBenchmark::UnitRand()*50;
- po->center[2]=b3BroadphaseBenchmark::UnitRand()*50;
- po->extents[0]=b3BroadphaseBenchmark::UnitRand()*2+2;
- po->extents[1]=b3BroadphaseBenchmark::UnitRand()*2+2;
- po->extents[2]=b3BroadphaseBenchmark::UnitRand()*2+2;
- po->time=b3BroadphaseBenchmark::UnitRand()*2000;
- po->proxy=pbi->createProxy(po->center-po->extents,po->center+po->extents,0,po,1,1,0,0);
+ b3BroadphaseBenchmark::Object* po = new b3BroadphaseBenchmark::Object();
+ po->center[0] = b3BroadphaseBenchmark::UnitRand() * 50;
+ po->center[1] = b3BroadphaseBenchmark::UnitRand() * 50;
+ po->center[2] = b3BroadphaseBenchmark::UnitRand() * 50;
+ po->extents[0] = b3BroadphaseBenchmark::UnitRand() * 2 + 2;
+ po->extents[1] = b3BroadphaseBenchmark::UnitRand() * 2 + 2;
+ po->extents[2] = b3BroadphaseBenchmark::UnitRand() * 2 + 2;
+ po->time = b3BroadphaseBenchmark::UnitRand() * 2000;
+ po->proxy = pbi->createProxy(po->center - po->extents, po->center + po->extents, 0, po, 1, 1, 0, 0);
objects.push_back(po);
}
- b3BroadphaseBenchmark::OutputTime("\tInitialization",wallclock);
- /* First update */
+ b3BroadphaseBenchmark::OutputTime("\tInitialization", wallclock);
+ /* First update */
wallclock.reset();
- for(int i=0;i<objects.size();++i)
+ for (int i = 0; i < objects.size(); ++i)
{
- objects[i]->update(speed,amplitude,pbi);
+ objects[i]->update(speed, amplitude, pbi);
}
- b3BroadphaseBenchmark::OutputTime("\tFirst update",wallclock);
- /* Updates */
+ b3BroadphaseBenchmark::OutputTime("\tFirst update", wallclock);
+ /* Updates */
wallclock.reset();
- for(int i=0;i<experiment.iterations;++i)
+ for (int i = 0; i < experiment.iterations; ++i)
{
- for(int j=0;j<update_count;++j)
- {
- objects[j]->update(speed,amplitude,pbi);
+ for (int j = 0; j < update_count; ++j)
+ {
+ objects[j]->update(speed, amplitude, pbi);
}
pbi->calculateOverlappingPairs(0);
}
- b3BroadphaseBenchmark::OutputTime("\tUpdate",wallclock,experiment.iterations);
- /* Clean up */
+ b3BroadphaseBenchmark::OutputTime("\tUpdate", wallclock, experiment.iterations);
+ /* Clean up */
wallclock.reset();
- for(int i=0;i<objects.size();++i)
+ for (int i = 0; i < objects.size(); ++i)
{
- pbi->destroyProxy(objects[i]->proxy,0);
+ pbi->destroyProxy(objects[i]->proxy, 0);
delete objects[i];
}
objects.resize(0);
- b3BroadphaseBenchmark::OutputTime("\tRelease",wallclock);
+ b3BroadphaseBenchmark::OutputTime("\tRelease", wallclock);
}
-
}
#else
/*void b3DynamicBvhBroadphase::benchmark(b3BroadphaseInterface*)
@@ -799,6 +804,5 @@ void b3DynamicBvhBroadphase::benchmark(b3BroadphaseInterface* pbi)
#endif
#if B3_DBVT_BP_PROFILE
-#undef b3SPC
+#undef b3SPC
#endif
-
diff --git a/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.h b/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.h
index 7ac085d90c..c235e40148 100644
--- a/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.h
+++ b/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.h
@@ -27,46 +27,43 @@ subject to the following restrictions:
// Compile time config
//
-#define B3_DBVT_BP_PROFILE 0
+#define B3_DBVT_BP_PROFILE 0
//#define B3_DBVT_BP_SORTPAIRS 1
-#define B3_DBVT_BP_PREVENTFALSEUPDATE 0
-#define B3_DBVT_BP_ACCURATESLEEPING 0
-#define B3_DBVT_BP_ENABLE_BENCHMARK 0
-#define B3_DBVT_BP_MARGIN (b3Scalar)0.05
+#define B3_DBVT_BP_PREVENTFALSEUPDATE 0
+#define B3_DBVT_BP_ACCURATESLEEPING 0
+#define B3_DBVT_BP_ENABLE_BENCHMARK 0
+#define B3_DBVT_BP_MARGIN (b3Scalar)0.05
#if B3_DBVT_BP_PROFILE
-#define B3_DBVT_BP_PROFILING_RATE 256
+#define B3_DBVT_BP_PROFILING_RATE 256
#endif
-
-
-
-B3_ATTRIBUTE_ALIGNED16(struct) b3BroadphaseProxy
+B3_ATTRIBUTE_ALIGNED16(struct)
+b3BroadphaseProxy
{
+ B3_DECLARE_ALIGNED_ALLOCATOR();
-B3_DECLARE_ALIGNED_ALLOCATOR();
-
///optional filtering to cull potential collisions
enum CollisionFilterGroups
{
- DefaultFilter = 1,
- StaticFilter = 2,
- KinematicFilter = 4,
- DebrisFilter = 8,
- SensorTrigger = 16,
- CharacterFilter = 32,
- AllFilter = -1 //all bits sets: DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorTrigger
+ DefaultFilter = 1,
+ StaticFilter = 2,
+ KinematicFilter = 4,
+ DebrisFilter = 8,
+ SensorTrigger = 16,
+ CharacterFilter = 32,
+ AllFilter = -1 //all bits sets: DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorTrigger
};
//Usually the client b3CollisionObject or Rigidbody class
- void* m_clientObject;
+ void* m_clientObject;
int m_collisionFilterGroup;
int m_collisionFilterMask;
- int m_uniqueId;//m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc.
+ int m_uniqueId; //m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc.
- b3Vector3 m_aabbMin;
- b3Vector3 m_aabbMax;
+ b3Vector3 m_aabbMin;
+ b3Vector3 m_aabbMax;
B3_FORCE_INLINE int getUid() const
{
@@ -74,116 +71,112 @@ B3_DECLARE_ALIGNED_ALLOCATOR();
}
//used for memory pools
- b3BroadphaseProxy() :m_clientObject(0)
+ b3BroadphaseProxy() : m_clientObject(0)
{
}
- b3BroadphaseProxy(const b3Vector3& aabbMin,const b3Vector3& aabbMax,void* userPtr, int collisionFilterGroup, int collisionFilterMask)
- :m_clientObject(userPtr),
- m_collisionFilterGroup(collisionFilterGroup),
- m_collisionFilterMask(collisionFilterMask),
- m_aabbMin(aabbMin),
- m_aabbMax(aabbMax)
+ b3BroadphaseProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, void* userPtr, int collisionFilterGroup, int collisionFilterMask)
+ : m_clientObject(userPtr),
+ m_collisionFilterGroup(collisionFilterGroup),
+ m_collisionFilterMask(collisionFilterMask),
+ m_aabbMin(aabbMin),
+ m_aabbMax(aabbMax)
{
}
};
-
-
-
-
//
// b3DbvtProxy
//
struct b3DbvtProxy : b3BroadphaseProxy
{
- /* Fields */
+ /* Fields */
//b3DbvtAabbMm aabb;
- b3DbvtNode* leaf;
- b3DbvtProxy* links[2];
- int stage;
- /* ctor */
+ b3DbvtNode* leaf;
+ b3DbvtProxy* links[2];
+ int stage;
+ /* ctor */
explicit b3DbvtProxy() {}
- b3DbvtProxy(const b3Vector3& aabbMin,const b3Vector3& aabbMax,void* userPtr, int collisionFilterGroup, int collisionFilterMask) :
- b3BroadphaseProxy(aabbMin,aabbMax,userPtr,collisionFilterGroup,collisionFilterMask)
+ b3DbvtProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, void* userPtr, int collisionFilterGroup, int collisionFilterMask) : b3BroadphaseProxy(aabbMin, aabbMax, userPtr, collisionFilterGroup, collisionFilterMask)
{
- links[0]=links[1]=0;
+ links[0] = links[1] = 0;
}
};
-typedef b3AlignedObjectArray<b3DbvtProxy*> b3DbvtProxyArray;
+typedef b3AlignedObjectArray<b3DbvtProxy*> b3DbvtProxyArray;
///The b3DynamicBvhBroadphase implements a broadphase using two dynamic AABB bounding volume hierarchies/trees (see b3DynamicBvh).
///One tree is used for static/non-moving objects, and another tree is used for dynamic objects. Objects can move from one tree to the other.
///This is a very fast broadphase, especially for very dynamic worlds where many objects are moving. Its insert/add and remove of objects is generally faster than the sweep and prune broadphases b3AxisSweep3 and b332BitAxisSweep3.
-struct b3DynamicBvhBroadphase
+struct b3DynamicBvhBroadphase
{
- /* Config */
- enum {
- DYNAMIC_SET = 0, /* Dynamic set index */
- FIXED_SET = 1, /* Fixed set index */
- STAGECOUNT = 2 /* Number of stages */
+ /* Config */
+ enum
+ {
+ DYNAMIC_SET = 0, /* Dynamic set index */
+ FIXED_SET = 1, /* Fixed set index */
+ STAGECOUNT = 2 /* Number of stages */
};
- /* Fields */
- b3DynamicBvh m_sets[2]; // Dbvt sets
- b3DbvtProxy* m_stageRoots[STAGECOUNT+1]; // Stages list
-
- b3AlignedObjectArray<b3DbvtProxy> m_proxies;
- b3OverlappingPairCache* m_paircache; // Pair cache
- b3Scalar m_prediction; // Velocity prediction
- int m_stageCurrent; // Current stage
- int m_fupdates; // % of fixed updates per frame
- int m_dupdates; // % of dynamic updates per frame
- int m_cupdates; // % of cleanup updates per frame
- int m_newpairs; // Number of pairs created
- int m_fixedleft; // Fixed optimization left
- unsigned m_updates_call; // Number of updates call
- unsigned m_updates_done; // Number of updates done
- b3Scalar m_updates_ratio; // m_updates_done/m_updates_call
- int m_pid; // Parse id
- int m_cid; // Cleanup index
- bool m_releasepaircache; // Release pair cache on delete
- bool m_deferedcollide; // Defere dynamic/static collision to collide call
- bool m_needcleanup; // Need to run cleanup?
+ /* Fields */
+ b3DynamicBvh m_sets[2]; // Dbvt sets
+ b3DbvtProxy* m_stageRoots[STAGECOUNT + 1]; // Stages list
+
+ b3AlignedObjectArray<b3DbvtProxy> m_proxies;
+ b3OverlappingPairCache* m_paircache; // Pair cache
+ b3Scalar m_prediction; // Velocity prediction
+ int m_stageCurrent; // Current stage
+ int m_fupdates; // % of fixed updates per frame
+ int m_dupdates; // % of dynamic updates per frame
+ int m_cupdates; // % of cleanup updates per frame
+ int m_newpairs; // Number of pairs created
+ int m_fixedleft; // Fixed optimization left
+ unsigned m_updates_call; // Number of updates call
+ unsigned m_updates_done; // Number of updates done
+ b3Scalar m_updates_ratio; // m_updates_done/m_updates_call
+ int m_pid; // Parse id
+ int m_cid; // Cleanup index
+ bool m_releasepaircache; // Release pair cache on delete
+ bool m_deferedcollide; // Defere dynamic/static collision to collide call
+ bool m_needcleanup; // Need to run cleanup?
#if B3_DBVT_BP_PROFILE
- b3Clock m_clock;
- struct {
- unsigned long m_total;
- unsigned long m_ddcollide;
- unsigned long m_fdcollide;
- unsigned long m_cleanup;
- unsigned long m_jobcount;
- } m_profiling;
+ b3Clock m_clock;
+ struct
+ {
+ unsigned long m_total;
+ unsigned long m_ddcollide;
+ unsigned long m_fdcollide;
+ unsigned long m_cleanup;
+ unsigned long m_jobcount;
+ } m_profiling;
#endif
- /* Methods */
- b3DynamicBvhBroadphase(int proxyCapacity, b3OverlappingPairCache* paircache=0);
+ /* Methods */
+ b3DynamicBvhBroadphase(int proxyCapacity, b3OverlappingPairCache* paircache = 0);
virtual ~b3DynamicBvhBroadphase();
- void collide(b3Dispatcher* dispatcher);
- void optimize();
-
+ void collide(b3Dispatcher* dispatcher);
+ void optimize();
+
/* b3BroadphaseInterface Implementation */
- b3BroadphaseProxy* createProxy(const b3Vector3& aabbMin,const b3Vector3& aabbMax,int objectIndex,void* userPtr, int collisionFilterGroup, int collisionFilterMask);
- virtual void destroyProxy(b3BroadphaseProxy* proxy,b3Dispatcher* dispatcher);
- virtual void setAabb(int objectId,const b3Vector3& aabbMin,const b3Vector3& aabbMax,b3Dispatcher* dispatcher);
- virtual void rayTest(const b3Vector3& rayFrom,const b3Vector3& rayTo, b3BroadphaseRayCallback& rayCallback, const b3Vector3& aabbMin=b3MakeVector3(0,0,0), const b3Vector3& aabbMax = b3MakeVector3(0,0,0));
- virtual void aabbTest(const b3Vector3& aabbMin, const b3Vector3& aabbMax, b3BroadphaseAabbCallback& callback);
+ b3BroadphaseProxy* createProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int objectIndex, void* userPtr, int collisionFilterGroup, int collisionFilterMask);
+ virtual void destroyProxy(b3BroadphaseProxy* proxy, b3Dispatcher* dispatcher);
+ virtual void setAabb(int objectId, const b3Vector3& aabbMin, const b3Vector3& aabbMax, b3Dispatcher* dispatcher);
+ virtual void rayTest(const b3Vector3& rayFrom, const b3Vector3& rayTo, b3BroadphaseRayCallback& rayCallback, const b3Vector3& aabbMin = b3MakeVector3(0, 0, 0), const b3Vector3& aabbMax = b3MakeVector3(0, 0, 0));
+ virtual void aabbTest(const b3Vector3& aabbMin, const b3Vector3& aabbMax, b3BroadphaseAabbCallback& callback);
//virtual void getAabb(b3BroadphaseProxy* proxy,b3Vector3& aabbMin, b3Vector3& aabbMax ) const;
- virtual void getAabb(int objectId,b3Vector3& aabbMin, b3Vector3& aabbMax ) const;
- virtual void calculateOverlappingPairs(b3Dispatcher* dispatcher=0);
- virtual b3OverlappingPairCache* getOverlappingPairCache();
- virtual const b3OverlappingPairCache* getOverlappingPairCache() const;
- virtual void getBroadphaseAabb(b3Vector3& aabbMin,b3Vector3& aabbMax) const;
- virtual void printStats();
-
+ virtual void getAabb(int objectId, b3Vector3& aabbMin, b3Vector3& aabbMax) const;
+ virtual void calculateOverlappingPairs(b3Dispatcher* dispatcher = 0);
+ virtual b3OverlappingPairCache* getOverlappingPairCache();
+ virtual const b3OverlappingPairCache* getOverlappingPairCache() const;
+ virtual void getBroadphaseAabb(b3Vector3& aabbMin, b3Vector3& aabbMax) const;
+ virtual void printStats();
///reset broadphase internal structures, to ensure determinism/reproducability
virtual void resetPool(b3Dispatcher* dispatcher);
- void performDeferredRemoval(b3Dispatcher* dispatcher);
-
- void setVelocityPrediction(b3Scalar prediction)
+ void performDeferredRemoval(b3Dispatcher* dispatcher);
+
+ void setVelocityPrediction(b3Scalar prediction)
{
m_prediction = prediction;
}
@@ -192,15 +185,13 @@ struct b3DynamicBvhBroadphase
return m_prediction;
}
- ///this setAabbForceUpdate is similar to setAabb but always forces the aabb update.
+ ///this setAabbForceUpdate is similar to setAabb but always forces the aabb update.
///it is not part of the b3BroadphaseInterface but specific to b3DynamicBvhBroadphase.
///it bypasses certain optimizations that prevent aabb updates (when the aabb shrinks), see
///http://code.google.com/p/bullet/issues/detail?id=223
- void setAabbForceUpdate( b3BroadphaseProxy* absproxy,const b3Vector3& aabbMin,const b3Vector3& aabbMax,b3Dispatcher* /*dispatcher*/);
+ void setAabbForceUpdate(b3BroadphaseProxy* absproxy, const b3Vector3& aabbMin, const b3Vector3& aabbMax, b3Dispatcher* /*dispatcher*/);
//static void benchmark(b3BroadphaseInterface*);
-
-
};
#endif
diff --git a/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3OverlappingPair.h b/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3OverlappingPair.h
index 39bf27de3e..4ff9ebae81 100644
--- a/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3OverlappingPair.h
+++ b/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3OverlappingPair.h
@@ -23,20 +23,20 @@ subject to the following restrictions:
typedef b3Int4 b3BroadphasePair;
-inline b3Int4 b3MakeBroadphasePair(int xx,int yy)
+inline b3Int4 b3MakeBroadphasePair(int xx, int yy)
{
b3Int4 pair;
if (xx < yy)
- {
- pair.x = xx;
- pair.y = yy;
- }
- else
- {
+ {
+ pair.x = xx;
+ pair.y = yy;
+ }
+ else
+ {
pair.x = yy;
- pair.y = xx;
- }
+ pair.y = xx;
+ }
pair.z = B3_NEW_PAIR_MARKER;
pair.w = B3_NEW_PAIR_MARKER;
return pair;
@@ -51,22 +51,20 @@ inline b3Int4 b3MakeBroadphasePair(int xx,int yy)
class b3BroadphasePairSortPredicate
{
- public:
-
- bool operator() ( const b3BroadphasePair& a, const b3BroadphasePair& b ) const
- {
- const int uidA0 = a.x;
- const int uidB0 = b.x;
- const int uidA1 = a.y;
- const int uidB1 = b.y;
- return uidA0 > uidB0 || (uidA0 == uidB0 && uidA1 > uidB1);
- }
+public:
+ bool operator()(const b3BroadphasePair& a, const b3BroadphasePair& b) const
+ {
+ const int uidA0 = a.x;
+ const int uidB0 = b.x;
+ const int uidA1 = a.y;
+ const int uidB1 = b.y;
+ return uidA0 > uidB0 || (uidA0 == uidB0 && uidA1 > uidB1);
+ }
};
-B3_FORCE_INLINE bool operator==(const b3BroadphasePair& a, const b3BroadphasePair& b)
+B3_FORCE_INLINE bool operator==(const b3BroadphasePair& a, const b3BroadphasePair& b)
{
- return (a.x == b.x ) && (a.y == b.y );
+ return (a.x == b.x) && (a.y == b.y);
}
-#endif //B3_OVERLAPPING_PAIR_H
-
+#endif //B3_OVERLAPPING_PAIR_H
diff --git a/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3OverlappingPairCache.cpp b/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3OverlappingPairCache.cpp
index e4bda61624..19773244be 100644
--- a/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3OverlappingPairCache.cpp
+++ b/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3OverlappingPairCache.cpp
@@ -13,8 +13,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
-
#include "b3OverlappingPairCache.h"
//#include "b3Dispatcher.h"
@@ -23,35 +21,26 @@ subject to the following restrictions:
#include <stdio.h>
-int b3g_overlappingPairs = 0;
-int b3g_removePairs =0;
-int b3g_addedPairs =0;
-int b3g_findPairs =0;
-
-
-
+int b3g_overlappingPairs = 0;
+int b3g_removePairs = 0;
+int b3g_addedPairs = 0;
+int b3g_findPairs = 0;
-b3HashedOverlappingPairCache::b3HashedOverlappingPairCache():
- m_overlapFilterCallback(0)
+b3HashedOverlappingPairCache::b3HashedOverlappingPairCache() : m_overlapFilterCallback(0)
//, m_blockedForChanges(false)
{
- int initialAllocatedSize= 2;
+ int initialAllocatedSize = 2;
m_overlappingPairArray.reserve(initialAllocatedSize);
growTables();
}
-
-
-
b3HashedOverlappingPairCache::~b3HashedOverlappingPairCache()
{
}
-
-
-void b3HashedOverlappingPairCache::cleanOverlappingPair(b3BroadphasePair& pair,b3Dispatcher* dispatcher)
+void b3HashedOverlappingPairCache::cleanOverlappingPair(b3BroadphasePair& pair, b3Dispatcher* dispatcher)
{
-/* if (pair.m_algorithm)
+ /* if (pair.m_algorithm)
{
{
pair.m_algorithm->~b3CollisionAlgorithm();
@@ -60,91 +49,74 @@ void b3HashedOverlappingPairCache::cleanOverlappingPair(b3BroadphasePair& pair,b
}
}
*/
-
}
-
-
-
-void b3HashedOverlappingPairCache::cleanProxyFromPairs(int proxy,b3Dispatcher* dispatcher)
+void b3HashedOverlappingPairCache::cleanProxyFromPairs(int proxy, b3Dispatcher* dispatcher)
{
-
- class CleanPairCallback : public b3OverlapCallback
+ class CleanPairCallback : public b3OverlapCallback
{
int m_cleanProxy;
- b3OverlappingPairCache* m_pairCache;
+ b3OverlappingPairCache* m_pairCache;
b3Dispatcher* m_dispatcher;
public:
- CleanPairCallback(int cleanProxy,b3OverlappingPairCache* pairCache,b3Dispatcher* dispatcher)
- :m_cleanProxy(cleanProxy),
- m_pairCache(pairCache),
- m_dispatcher(dispatcher)
+ CleanPairCallback(int cleanProxy, b3OverlappingPairCache* pairCache, b3Dispatcher* dispatcher)
+ : m_cleanProxy(cleanProxy),
+ m_pairCache(pairCache),
+ m_dispatcher(dispatcher)
{
}
- virtual bool processOverlap(b3BroadphasePair& pair)
+ virtual bool processOverlap(b3BroadphasePair& pair)
{
if ((pair.x == m_cleanProxy) ||
(pair.y == m_cleanProxy))
{
- m_pairCache->cleanOverlappingPair(pair,m_dispatcher);
+ m_pairCache->cleanOverlappingPair(pair, m_dispatcher);
}
return false;
}
-
};
- CleanPairCallback cleanPairs(proxy,this,dispatcher);
-
- processAllOverlappingPairs(&cleanPairs,dispatcher);
+ CleanPairCallback cleanPairs(proxy, this, dispatcher);
+ processAllOverlappingPairs(&cleanPairs, dispatcher);
}
-
-
-
-void b3HashedOverlappingPairCache::removeOverlappingPairsContainingProxy(int proxy,b3Dispatcher* dispatcher)
+void b3HashedOverlappingPairCache::removeOverlappingPairsContainingProxy(int proxy, b3Dispatcher* dispatcher)
{
-
- class RemovePairCallback : public b3OverlapCallback
+ class RemovePairCallback : public b3OverlapCallback
{
int m_obsoleteProxy;
public:
RemovePairCallback(int obsoleteProxy)
- :m_obsoleteProxy(obsoleteProxy)
+ : m_obsoleteProxy(obsoleteProxy)
{
}
- virtual bool processOverlap(b3BroadphasePair& pair)
+ virtual bool processOverlap(b3BroadphasePair& pair)
{
return ((pair.x == m_obsoleteProxy) ||
- (pair.y == m_obsoleteProxy));
+ (pair.y == m_obsoleteProxy));
}
-
};
-
RemovePairCallback removeCallback(proxy);
- processAllOverlappingPairs(&removeCallback,dispatcher);
+ processAllOverlappingPairs(&removeCallback, dispatcher);
}
-
-
-
-
b3BroadphasePair* b3HashedOverlappingPairCache::findPair(int proxy0, int proxy1)
{
b3g_findPairs++;
- if(proxy0 >proxy1)
- b3Swap(proxy0,proxy1);
+ if (proxy0 > proxy1)
+ b3Swap(proxy0, proxy1);
int proxyId1 = proxy0;
int proxyId2 = proxy1;
/*if (proxyId1 > proxyId2)
b3Swap(proxyId1, proxyId2);*/
- int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1), static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1));
+ int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1), static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity() - 1));
if (hash >= m_hashTable.size())
{
@@ -169,9 +141,8 @@ b3BroadphasePair* b3HashedOverlappingPairCache::findPair(int proxy0, int proxy1)
//#include <stdio.h>
-void b3HashedOverlappingPairCache::growTables()
+void b3HashedOverlappingPairCache::growTables()
{
-
int newCapacity = m_overlappingPairArray.capacity();
if (m_hashTable.size() < newCapacity)
@@ -182,10 +153,9 @@ void b3HashedOverlappingPairCache::growTables()
m_hashTable.resize(newCapacity);
m_next.resize(newCapacity);
-
int i;
- for (i= 0; i < newCapacity; ++i)
+ for (i = 0; i < newCapacity; ++i)
{
m_hashTable[i] = B3_NULL_PAIR;
}
@@ -194,35 +164,31 @@ void b3HashedOverlappingPairCache::growTables()
m_next[i] = B3_NULL_PAIR;
}
- for(i=0;i<curHashtableSize;i++)
+ for (i = 0; i < curHashtableSize; i++)
{
-
const b3BroadphasePair& pair = m_overlappingPairArray[i];
int proxyId1 = pair.x;
int proxyId2 = pair.y;
/*if (proxyId1 > proxyId2)
b3Swap(proxyId1, proxyId2);*/
- int hashValue = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask
+ int hashValue = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1), static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity() - 1)); // New hash value with new mask
m_next[i] = m_hashTable[hashValue];
m_hashTable[hashValue] = i;
}
-
-
}
}
b3BroadphasePair* b3HashedOverlappingPairCache::internalAddPair(int proxy0, int proxy1)
{
- if(proxy0>proxy1)
- b3Swap(proxy0,proxy1);
+ if (proxy0 > proxy1)
+ b3Swap(proxy0, proxy1);
int proxyId1 = proxy0;
int proxyId2 = proxy1;
/*if (proxyId1 > proxyId2)
b3Swap(proxyId1, proxyId2);*/
- int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask
-
+ int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1), static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity() - 1)); // New hash value with new mask
b3BroadphasePair* pair = internalFindPair(proxy0, proxy1, hash);
if (pair != NULL)
@@ -243,8 +209,8 @@ b3BroadphasePair* b3HashedOverlappingPairCache::internalAddPair(int proxy0, int
pair = &m_overlappingPairArray.expandNonInitializing();
//this is where we add an actual pair, so also call the 'ghost'
-// if (m_ghostPairCallback)
-// m_ghostPairCallback->addOverlappingPair(proxy0,proxy1);
+ // if (m_ghostPairCallback)
+ // m_ghostPairCallback->addOverlappingPair(proxy0,proxy1);
int newCapacity = m_overlappingPairArray.capacity();
@@ -252,16 +218,15 @@ b3BroadphasePair* b3HashedOverlappingPairCache::internalAddPair(int proxy0, int
{
growTables();
//hash with new capacity
- hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1));
+ hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1), static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity() - 1));
}
-
- *pair = b3MakeBroadphasePair(proxy0,proxy1);
-
-// pair->m_pProxy0 = proxy0;
-// pair->m_pProxy1 = proxy1;
+
+ *pair = b3MakeBroadphasePair(proxy0, proxy1);
+
+ // pair->m_pProxy0 = proxy0;
+ // pair->m_pProxy1 = proxy1;
//pair->m_algorithm = 0;
//pair->m_internalTmpValue = 0;
-
m_next[count] = m_hashTable[hash];
m_hashTable[hash] = count;
@@ -269,20 +234,18 @@ b3BroadphasePair* b3HashedOverlappingPairCache::internalAddPair(int proxy0, int
return pair;
}
-
-
-void* b3HashedOverlappingPairCache::removeOverlappingPair(int proxy0, int proxy1,b3Dispatcher* dispatcher)
+void* b3HashedOverlappingPairCache::removeOverlappingPair(int proxy0, int proxy1, b3Dispatcher* dispatcher)
{
b3g_removePairs++;
- if(proxy0>proxy1)
- b3Swap(proxy0,proxy1);
+ if (proxy0 > proxy1)
+ b3Swap(proxy0, proxy1);
int proxyId1 = proxy0;
int proxyId2 = proxy1;
/*if (proxyId1 > proxyId2)
b3Swap(proxyId1, proxyId2);*/
- int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1));
+ int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1), static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity() - 1));
b3BroadphasePair* pair = internalFindPair(proxy0, proxy1, hash);
if (pair == NULL)
@@ -290,9 +253,7 @@ void* b3HashedOverlappingPairCache::removeOverlappingPair(int proxy0, int proxy1
return 0;
}
- cleanOverlappingPair(*pair,dispatcher);
-
-
+ cleanOverlappingPair(*pair, dispatcher);
int pairIndex = int(pair - &m_overlappingPairArray[0]);
b3Assert(pairIndex < m_overlappingPairArray.size());
@@ -336,8 +297,8 @@ void* b3HashedOverlappingPairCache::removeOverlappingPair(int proxy0, int proxy1
// Remove the last pair from the hash table.
const b3BroadphasePair* last = &m_overlappingPairArray[lastPairIndex];
- /* missing swap here too, Nat. */
- int lastHash = static_cast<int>(getHash(static_cast<unsigned int>(last->x), static_cast<unsigned int>(last->y)) & (m_overlappingPairArray.capacity()-1));
+ /* missing swap here too, Nat. */
+ int lastHash = static_cast<int>(getHash(static_cast<unsigned int>(last->x), static_cast<unsigned int>(last->y)) & (m_overlappingPairArray.capacity() - 1));
index = m_hashTable[lastHash];
b3Assert(index != B3_NULL_PAIR);
@@ -372,47 +333,42 @@ void* b3HashedOverlappingPairCache::removeOverlappingPair(int proxy0, int proxy1
}
//#include <stdio.h>
-void b3HashedOverlappingPairCache::processAllOverlappingPairs(b3OverlapCallback* callback,b3Dispatcher* dispatcher)
+void b3HashedOverlappingPairCache::processAllOverlappingPairs(b3OverlapCallback* callback, b3Dispatcher* dispatcher)
{
-
int i;
-// printf("m_overlappingPairArray.size()=%d\n",m_overlappingPairArray.size());
- for (i=0;i<m_overlappingPairArray.size();)
+ // printf("m_overlappingPairArray.size()=%d\n",m_overlappingPairArray.size());
+ for (i = 0; i < m_overlappingPairArray.size();)
{
-
b3BroadphasePair* pair = &m_overlappingPairArray[i];
if (callback->processOverlap(*pair))
{
- removeOverlappingPair(pair->x,pair->y,dispatcher);
+ removeOverlappingPair(pair->x, pair->y, dispatcher);
b3g_overlappingPairs--;
- } else
+ }
+ else
{
i++;
}
}
}
-
-
-
-
-void b3HashedOverlappingPairCache::sortOverlappingPairs(b3Dispatcher* dispatcher)
+void b3HashedOverlappingPairCache::sortOverlappingPairs(b3Dispatcher* dispatcher)
{
///need to keep hashmap in sync with pair address, so rebuild all
b3BroadphasePairArray tmpPairs;
int i;
- for (i=0;i<m_overlappingPairArray.size();i++)
+ for (i = 0; i < m_overlappingPairArray.size(); i++)
{
tmpPairs.push_back(m_overlappingPairArray[i]);
}
- for (i=0;i<tmpPairs.size();i++)
+ for (i = 0; i < tmpPairs.size(); i++)
{
- removeOverlappingPair(tmpPairs[i].x,tmpPairs[i].y,dispatcher);
+ removeOverlappingPair(tmpPairs[i].x, tmpPairs[i].y, dispatcher);
}
-
+
for (i = 0; i < m_next.size(); i++)
{
m_next[i] = B3_NULL_PAIR;
@@ -420,33 +376,29 @@ void b3HashedOverlappingPairCache::sortOverlappingPairs(b3Dispatcher* dispatcher
tmpPairs.quickSort(b3BroadphasePairSortPredicate());
- for (i=0;i<tmpPairs.size();i++)
+ for (i = 0; i < tmpPairs.size(); i++)
{
- addOverlappingPair(tmpPairs[i].x ,tmpPairs[i].y);
+ addOverlappingPair(tmpPairs[i].x, tmpPairs[i].y);
}
-
-
}
-
-void* b3SortedOverlappingPairCache::removeOverlappingPair(int proxy0,int proxy1, b3Dispatcher* dispatcher )
+void* b3SortedOverlappingPairCache::removeOverlappingPair(int proxy0, int proxy1, b3Dispatcher* dispatcher)
{
if (!hasDeferredRemoval())
{
- b3BroadphasePair findPair = b3MakeBroadphasePair(proxy0,proxy1);
-
+ b3BroadphasePair findPair = b3MakeBroadphasePair(proxy0, proxy1);
int findIndex = m_overlappingPairArray.findLinearSearch(findPair);
if (findIndex < m_overlappingPairArray.size())
{
b3g_overlappingPairs--;
b3BroadphasePair& pair = m_overlappingPairArray[findIndex];
-
- cleanOverlappingPair(pair,dispatcher);
+
+ cleanOverlappingPair(pair, dispatcher);
//if (m_ghostPairCallback)
// m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1,dispatcher);
-
- m_overlappingPairArray.swap(findIndex,m_overlappingPairArray.capacity()-1);
+
+ m_overlappingPairArray.swap(findIndex, m_overlappingPairArray.capacity() - 1);
m_overlappingPairArray.pop_back();
return 0;
}
@@ -455,100 +407,77 @@ void* b3SortedOverlappingPairCache::removeOverlappingPair(int proxy0,int proxy1,
return 0;
}
-
-
-
-
-
-
-
-b3BroadphasePair* b3SortedOverlappingPairCache::addOverlappingPair(int proxy0,int proxy1)
+b3BroadphasePair* b3SortedOverlappingPairCache::addOverlappingPair(int proxy0, int proxy1)
{
//don't add overlap with own
b3Assert(proxy0 != proxy1);
- if (!needsBroadphaseCollision(proxy0,proxy1))
+ if (!needsBroadphaseCollision(proxy0, proxy1))
return 0;
-
+
b3BroadphasePair* pair = &m_overlappingPairArray.expandNonInitializing();
- *pair = b3MakeBroadphasePair(proxy0,proxy1);
-
-
+ *pair = b3MakeBroadphasePair(proxy0, proxy1);
+
b3g_overlappingPairs++;
b3g_addedPairs++;
-
-// if (m_ghostPairCallback)
-// m_ghostPairCallback->addOverlappingPair(proxy0, proxy1);
+
+ // if (m_ghostPairCallback)
+ // m_ghostPairCallback->addOverlappingPair(proxy0, proxy1);
return pair;
-
}
///this findPair becomes really slow. Either sort the list to speedup the query, or
///use a different solution. It is mainly used for Removing overlapping pairs. Removal could be delayed.
///we could keep a linked list in each proxy, and store pair in one of the proxies (with lowest memory address)
///Also we can use a 2D bitmap, which can be useful for a future GPU implementation
- b3BroadphasePair* b3SortedOverlappingPairCache::findPair(int proxy0,int proxy1)
+b3BroadphasePair* b3SortedOverlappingPairCache::findPair(int proxy0, int proxy1)
{
- if (!needsBroadphaseCollision(proxy0,proxy1))
+ if (!needsBroadphaseCollision(proxy0, proxy1))
return 0;
- b3BroadphasePair tmpPair = b3MakeBroadphasePair(proxy0,proxy1);
+ b3BroadphasePair tmpPair = b3MakeBroadphasePair(proxy0, proxy1);
int findIndex = m_overlappingPairArray.findLinearSearch(tmpPair);
if (findIndex < m_overlappingPairArray.size())
{
//b3Assert(it != m_overlappingPairSet.end());
- b3BroadphasePair* pair = &m_overlappingPairArray[findIndex];
+ b3BroadphasePair* pair = &m_overlappingPairArray[findIndex];
return pair;
}
return 0;
}
-
-
-
-
-
-
-
-
-
//#include <stdio.h>
-void b3SortedOverlappingPairCache::processAllOverlappingPairs(b3OverlapCallback* callback,b3Dispatcher* dispatcher)
+void b3SortedOverlappingPairCache::processAllOverlappingPairs(b3OverlapCallback* callback, b3Dispatcher* dispatcher)
{
-
int i;
- for (i=0;i<m_overlappingPairArray.size();)
+ for (i = 0; i < m_overlappingPairArray.size();)
{
-
b3BroadphasePair* pair = &m_overlappingPairArray[i];
if (callback->processOverlap(*pair))
{
- cleanOverlappingPair(*pair,dispatcher);
+ cleanOverlappingPair(*pair, dispatcher);
pair->x = -1;
pair->y = -1;
- m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
+ m_overlappingPairArray.swap(i, m_overlappingPairArray.size() - 1);
m_overlappingPairArray.pop_back();
b3g_overlappingPairs--;
- } else
+ }
+ else
{
i++;
}
}
}
-
-
-
-b3SortedOverlappingPairCache::b3SortedOverlappingPairCache():
- m_blockedForChanges(false),
- m_hasDeferredRemoval(true),
- m_overlapFilterCallback(0)
+b3SortedOverlappingPairCache::b3SortedOverlappingPairCache() : m_blockedForChanges(false),
+ m_hasDeferredRemoval(true),
+ m_overlapFilterCallback(0)
{
- int initialAllocatedSize= 2;
+ int initialAllocatedSize = 2;
m_overlappingPairArray.reserve(initialAllocatedSize);
}
@@ -556,9 +485,9 @@ b3SortedOverlappingPairCache::~b3SortedOverlappingPairCache()
{
}
-void b3SortedOverlappingPairCache::cleanOverlappingPair(b3BroadphasePair& pair,b3Dispatcher* dispatcher)
+void b3SortedOverlappingPairCache::cleanOverlappingPair(b3BroadphasePair& pair, b3Dispatcher* dispatcher)
{
-/* if (pair.m_algorithm)
+ /* if (pair.m_algorithm)
{
{
pair.m_algorithm->~b3CollisionAlgorithm();
@@ -570,69 +499,61 @@ void b3SortedOverlappingPairCache::cleanOverlappingPair(b3BroadphasePair& pair,b
*/
}
-
-void b3SortedOverlappingPairCache::cleanProxyFromPairs(int proxy,b3Dispatcher* dispatcher)
+void b3SortedOverlappingPairCache::cleanProxyFromPairs(int proxy, b3Dispatcher* dispatcher)
{
-
- class CleanPairCallback : public b3OverlapCallback
+ class CleanPairCallback : public b3OverlapCallback
{
int m_cleanProxy;
- b3OverlappingPairCache* m_pairCache;
+ b3OverlappingPairCache* m_pairCache;
b3Dispatcher* m_dispatcher;
public:
- CleanPairCallback(int cleanProxy,b3OverlappingPairCache* pairCache,b3Dispatcher* dispatcher)
- :m_cleanProxy(cleanProxy),
- m_pairCache(pairCache),
- m_dispatcher(dispatcher)
+ CleanPairCallback(int cleanProxy, b3OverlappingPairCache* pairCache, b3Dispatcher* dispatcher)
+ : m_cleanProxy(cleanProxy),
+ m_pairCache(pairCache),
+ m_dispatcher(dispatcher)
{
}
- virtual bool processOverlap(b3BroadphasePair& pair)
+ virtual bool processOverlap(b3BroadphasePair& pair)
{
if ((pair.x == m_cleanProxy) ||
(pair.y == m_cleanProxy))
{
- m_pairCache->cleanOverlappingPair(pair,m_dispatcher);
+ m_pairCache->cleanOverlappingPair(pair, m_dispatcher);
}
return false;
}
-
};
- CleanPairCallback cleanPairs(proxy,this,dispatcher);
-
- processAllOverlappingPairs(&cleanPairs,dispatcher);
+ CleanPairCallback cleanPairs(proxy, this, dispatcher);
+ processAllOverlappingPairs(&cleanPairs, dispatcher);
}
-
-void b3SortedOverlappingPairCache::removeOverlappingPairsContainingProxy(int proxy,b3Dispatcher* dispatcher)
+void b3SortedOverlappingPairCache::removeOverlappingPairsContainingProxy(int proxy, b3Dispatcher* dispatcher)
{
-
- class RemovePairCallback : public b3OverlapCallback
+ class RemovePairCallback : public b3OverlapCallback
{
int m_obsoleteProxy;
public:
RemovePairCallback(int obsoleteProxy)
- :m_obsoleteProxy(obsoleteProxy)
+ : m_obsoleteProxy(obsoleteProxy)
{
}
- virtual bool processOverlap(b3BroadphasePair& pair)
+ virtual bool processOverlap(b3BroadphasePair& pair)
{
return ((pair.x == m_obsoleteProxy) ||
- (pair.y == m_obsoleteProxy));
+ (pair.y == m_obsoleteProxy));
}
-
};
RemovePairCallback removeCallback(proxy);
- processAllOverlappingPairs(&removeCallback,dispatcher);
+ processAllOverlappingPairs(&removeCallback, dispatcher);
}
-void b3SortedOverlappingPairCache::sortOverlappingPairs(b3Dispatcher* dispatcher)
+void b3SortedOverlappingPairCache::sortOverlappingPairs(b3Dispatcher* dispatcher)
{
//should already be sorted
}
-
diff --git a/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3OverlappingPairCache.h b/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3OverlappingPairCache.h
index f67eb676f1..f1de1d94eb 100644
--- a/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3OverlappingPairCache.h
+++ b/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3OverlappingPairCache.h
@@ -22,152 +22,136 @@ subject to the following restrictions:
class b3Dispatcher;
#include "b3OverlappingPair.h"
+typedef b3AlignedObjectArray<b3BroadphasePair> b3BroadphasePairArray;
-
-typedef b3AlignedObjectArray<b3BroadphasePair> b3BroadphasePairArray;
-
-struct b3OverlapCallback
+struct b3OverlapCallback
{
virtual ~b3OverlapCallback()
- {}
+ {
+ }
//return true for deletion of the pair
- virtual bool processOverlap(b3BroadphasePair& pair) = 0;
-
+ virtual bool processOverlap(b3BroadphasePair& pair) = 0;
};
struct b3OverlapFilterCallback
{
virtual ~b3OverlapFilterCallback()
- {}
+ {
+ }
// return true when pairs need collision
- virtual bool needBroadphaseCollision(int proxy0,int proxy1) const = 0;
+ virtual bool needBroadphaseCollision(int proxy0, int proxy1) const = 0;
};
-
-
-
-
-
-
extern int b3g_removePairs;
extern int b3g_addedPairs;
extern int b3g_findPairs;
-const int B3_NULL_PAIR=0xffffffff;
+const int B3_NULL_PAIR = 0xffffffff;
///The b3OverlappingPairCache provides an interface for overlapping pair management (add, remove, storage), used by the b3BroadphaseInterface broadphases.
///The b3HashedOverlappingPairCache and b3SortedOverlappingPairCache classes are two implementations.
-class b3OverlappingPairCache
+class b3OverlappingPairCache
{
public:
- virtual ~b3OverlappingPairCache() {} // this is needed so we can get to the derived class destructor
+ virtual ~b3OverlappingPairCache() {} // this is needed so we can get to the derived class destructor
- virtual b3BroadphasePair* getOverlappingPairArrayPtr() = 0;
-
- virtual const b3BroadphasePair* getOverlappingPairArrayPtr() const = 0;
+ virtual b3BroadphasePair* getOverlappingPairArrayPtr() = 0;
- virtual b3BroadphasePairArray& getOverlappingPairArray() = 0;
+ virtual const b3BroadphasePair* getOverlappingPairArrayPtr() const = 0;
- virtual void cleanOverlappingPair(b3BroadphasePair& pair,b3Dispatcher* dispatcher) = 0;
+ virtual b3BroadphasePairArray& getOverlappingPairArray() = 0;
+
+ virtual void cleanOverlappingPair(b3BroadphasePair& pair, b3Dispatcher* dispatcher) = 0;
virtual int getNumOverlappingPairs() const = 0;
- virtual void cleanProxyFromPairs(int proxy,b3Dispatcher* dispatcher) = 0;
+ virtual void cleanProxyFromPairs(int proxy, b3Dispatcher* dispatcher) = 0;
- virtual void setOverlapFilterCallback(b3OverlapFilterCallback* callback) = 0;
+ virtual void setOverlapFilterCallback(b3OverlapFilterCallback* callback) = 0;
- virtual void processAllOverlappingPairs(b3OverlapCallback*,b3Dispatcher* dispatcher) = 0;
+ virtual void processAllOverlappingPairs(b3OverlapCallback*, b3Dispatcher* dispatcher) = 0;
virtual b3BroadphasePair* findPair(int proxy0, int proxy1) = 0;
- virtual bool hasDeferredRemoval() = 0;
+ virtual bool hasDeferredRemoval() = 0;
//virtual void setInternalGhostPairCallback(b3OverlappingPairCallback* ghostPairCallback)=0;
- virtual b3BroadphasePair* addOverlappingPair(int proxy0,int proxy1)=0;
- virtual void* removeOverlappingPair(int proxy0,int proxy1,b3Dispatcher* dispatcher)=0;
- virtual void removeOverlappingPairsContainingProxy(int /*proxy0*/,b3Dispatcher* /*dispatcher*/)=0;
-
- virtual void sortOverlappingPairs(b3Dispatcher* dispatcher) = 0;
-
+ virtual b3BroadphasePair* addOverlappingPair(int proxy0, int proxy1) = 0;
+ virtual void* removeOverlappingPair(int proxy0, int proxy1, b3Dispatcher* dispatcher) = 0;
+ virtual void removeOverlappingPairsContainingProxy(int /*proxy0*/, b3Dispatcher* /*dispatcher*/) = 0;
+ virtual void sortOverlappingPairs(b3Dispatcher* dispatcher) = 0;
};
/// Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman, Codercorner, http://codercorner.com
class b3HashedOverlappingPairCache : public b3OverlappingPairCache
{
- b3BroadphasePairArray m_overlappingPairArray;
+ b3BroadphasePairArray m_overlappingPairArray;
b3OverlapFilterCallback* m_overlapFilterCallback;
-// bool m_blockedForChanges;
-
+ // bool m_blockedForChanges;
public:
b3HashedOverlappingPairCache();
virtual ~b3HashedOverlappingPairCache();
-
- virtual void removeOverlappingPairsContainingProxy(int proxy,b3Dispatcher* dispatcher);
+ virtual void removeOverlappingPairsContainingProxy(int proxy, b3Dispatcher* dispatcher);
- virtual void* removeOverlappingPair(int proxy0,int proxy1,b3Dispatcher* dispatcher);
-
- B3_FORCE_INLINE bool needsBroadphaseCollision(int proxy0,int proxy1) const
+ virtual void* removeOverlappingPair(int proxy0, int proxy1, b3Dispatcher* dispatcher);
+
+ B3_FORCE_INLINE bool needsBroadphaseCollision(int proxy0, int proxy1) const
{
if (m_overlapFilterCallback)
- return m_overlapFilterCallback->needBroadphaseCollision(proxy0,proxy1);
+ return m_overlapFilterCallback->needBroadphaseCollision(proxy0, proxy1);
- bool collides = true;//(proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
+ bool collides = true; //(proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
//collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
-
+
return collides;
}
// Add a pair and return the new pair. If the pair already exists,
// no new pair is created and the old one is returned.
- virtual b3BroadphasePair* addOverlappingPair(int proxy0,int proxy1)
+ virtual b3BroadphasePair* addOverlappingPair(int proxy0, int proxy1)
{
b3g_addedPairs++;
- if (!needsBroadphaseCollision(proxy0,proxy1))
+ if (!needsBroadphaseCollision(proxy0, proxy1))
return 0;
- return internalAddPair(proxy0,proxy1);
+ return internalAddPair(proxy0, proxy1);
}
-
-
- void cleanProxyFromPairs(int proxy,b3Dispatcher* dispatcher);
+ void cleanProxyFromPairs(int proxy, b3Dispatcher* dispatcher);
-
- virtual void processAllOverlappingPairs(b3OverlapCallback*,b3Dispatcher* dispatcher);
+ virtual void processAllOverlappingPairs(b3OverlapCallback*, b3Dispatcher* dispatcher);
- virtual b3BroadphasePair* getOverlappingPairArrayPtr()
+ virtual b3BroadphasePair* getOverlappingPairArrayPtr()
{
return &m_overlappingPairArray[0];
}
- const b3BroadphasePair* getOverlappingPairArrayPtr() const
+ const b3BroadphasePair* getOverlappingPairArrayPtr() const
{
return &m_overlappingPairArray[0];
}
- b3BroadphasePairArray& getOverlappingPairArray()
+ b3BroadphasePairArray& getOverlappingPairArray()
{
return m_overlappingPairArray;
}
- const b3BroadphasePairArray& getOverlappingPairArray() const
+ const b3BroadphasePairArray& getOverlappingPairArray() const
{
return m_overlappingPairArray;
}
- void cleanOverlappingPair(b3BroadphasePair& pair,b3Dispatcher* dispatcher);
-
-
+ void cleanOverlappingPair(b3BroadphasePair& pair, b3Dispatcher* dispatcher);
b3BroadphasePair* findPair(int proxy0, int proxy1);
int GetCount() const { return m_overlappingPairArray.size(); }
-// b3BroadphasePair* GetPairs() { return m_pairs; }
+ // b3BroadphasePair* GetPairs() { return m_pairs; }
b3OverlapFilterCallback* getOverlapFilterCallback()
{
@@ -179,19 +163,19 @@ public:
m_overlapFilterCallback = callback;
}
- int getNumOverlappingPairs() const
+ int getNumOverlappingPairs() const
{
return m_overlappingPairArray.size();
}
+
private:
-
- b3BroadphasePair* internalAddPair(int proxy0,int proxy1);
+ b3BroadphasePair* internalAddPair(int proxy0, int proxy1);
- void growTables();
+ void growTables();
B3_FORCE_INLINE bool equalsPair(const b3BroadphasePair& pair, int proxyId1, int proxyId2)
- {
- return pair.x == proxyId1 && pair.y == proxyId2;
+ {
+ return pair.x == proxyId1 && pair.y == proxyId2;
}
/*
@@ -210,43 +194,37 @@ private:
}
*/
-
-
- B3_FORCE_INLINE unsigned int getHash(unsigned int proxyId1, unsigned int proxyId2)
+ B3_FORCE_INLINE unsigned int getHash(unsigned int proxyId1, unsigned int proxyId2)
{
- int key = static_cast<int>(((unsigned int)proxyId1) | (((unsigned int)proxyId2) <<16));
+ int key = static_cast<int>(((unsigned int)proxyId1) | (((unsigned int)proxyId2) << 16));
// Thomas Wang's hash
key += ~(key << 15);
- key ^= (key >> 10);
- key += (key << 3);
- key ^= (key >> 6);
+ key ^= (key >> 10);
+ key += (key << 3);
+ key ^= (key >> 6);
key += ~(key << 11);
- key ^= (key >> 16);
+ key ^= (key >> 16);
return static_cast<unsigned int>(key);
}
-
-
-
-
B3_FORCE_INLINE b3BroadphasePair* internalFindPair(int proxy0, int proxy1, int hash)
{
int proxyId1 = proxy0;
int proxyId2 = proxy1;
- #if 0 // wrong, 'equalsPair' use unsorted uids, copy-past devil striked again. Nat.
+#if 0 // wrong, 'equalsPair' use unsorted uids, copy-past devil striked again. Nat.
if (proxyId1 > proxyId2)
b3Swap(proxyId1, proxyId2);
- #endif
+#endif
int index = m_hashTable[hash];
-
- while( index != B3_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false)
+
+ while (index != B3_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false)
{
index = m_next[index];
}
- if ( index == B3_NULL_PAIR )
+ if (index == B3_NULL_PAIR)
{
return NULL;
}
@@ -256,161 +234,142 @@ private:
return &m_overlappingPairArray[index];
}
- virtual bool hasDeferredRemoval()
+ virtual bool hasDeferredRemoval()
{
return false;
}
-/* virtual void setInternalGhostPairCallback(b3OverlappingPairCallback* ghostPairCallback)
+ /* virtual void setInternalGhostPairCallback(b3OverlappingPairCallback* ghostPairCallback)
{
m_ghostPairCallback = ghostPairCallback;
}
*/
- virtual void sortOverlappingPairs(b3Dispatcher* dispatcher);
-
+ virtual void sortOverlappingPairs(b3Dispatcher* dispatcher);
protected:
-
- b3AlignedObjectArray<int> m_hashTable;
- b3AlignedObjectArray<int> m_next;
-// b3OverlappingPairCallback* m_ghostPairCallback;
-
+ b3AlignedObjectArray<int> m_hashTable;
+ b3AlignedObjectArray<int> m_next;
+ // b3OverlappingPairCallback* m_ghostPairCallback;
};
-
-
-
///b3SortedOverlappingPairCache maintains the objects with overlapping AABB
///Typically managed by the Broadphase, Axis3Sweep or b3SimpleBroadphase
-class b3SortedOverlappingPairCache : public b3OverlappingPairCache
+class b3SortedOverlappingPairCache : public b3OverlappingPairCache
{
- protected:
- //avoid brute-force finding all the time
- b3BroadphasePairArray m_overlappingPairArray;
+protected:
+ //avoid brute-force finding all the time
+ b3BroadphasePairArray m_overlappingPairArray;
- //during the dispatch, check that user doesn't destroy/create proxy
- bool m_blockedForChanges;
+ //during the dispatch, check that user doesn't destroy/create proxy
+ bool m_blockedForChanges;
- ///by default, do the removal during the pair traversal
- bool m_hasDeferredRemoval;
-
- //if set, use the callback instead of the built in filter in needBroadphaseCollision
- b3OverlapFilterCallback* m_overlapFilterCallback;
+ ///by default, do the removal during the pair traversal
+ bool m_hasDeferredRemoval;
-// b3OverlappingPairCallback* m_ghostPairCallback;
+ //if set, use the callback instead of the built in filter in needBroadphaseCollision
+ b3OverlapFilterCallback* m_overlapFilterCallback;
- public:
-
- b3SortedOverlappingPairCache();
- virtual ~b3SortedOverlappingPairCache();
+ // b3OverlappingPairCallback* m_ghostPairCallback;
- virtual void processAllOverlappingPairs(b3OverlapCallback*,b3Dispatcher* dispatcher);
+public:
+ b3SortedOverlappingPairCache();
+ virtual ~b3SortedOverlappingPairCache();
- void* removeOverlappingPair(int proxy0,int proxy1,b3Dispatcher* dispatcher);
+ virtual void processAllOverlappingPairs(b3OverlapCallback*, b3Dispatcher* dispatcher);
- void cleanOverlappingPair(b3BroadphasePair& pair,b3Dispatcher* dispatcher);
-
- b3BroadphasePair* addOverlappingPair(int proxy0,int proxy1);
+ void* removeOverlappingPair(int proxy0, int proxy1, b3Dispatcher* dispatcher);
- b3BroadphasePair* findPair(int proxy0,int proxy1);
-
-
- void cleanProxyFromPairs(int proxy,b3Dispatcher* dispatcher);
+ void cleanOverlappingPair(b3BroadphasePair& pair, b3Dispatcher* dispatcher);
- virtual void removeOverlappingPairsContainingProxy(int proxy,b3Dispatcher* dispatcher);
+ b3BroadphasePair* addOverlappingPair(int proxy0, int proxy1);
+ b3BroadphasePair* findPair(int proxy0, int proxy1);
- inline bool needsBroadphaseCollision(int proxy0,int proxy1) const
- {
- if (m_overlapFilterCallback)
- return m_overlapFilterCallback->needBroadphaseCollision(proxy0,proxy1);
+ void cleanProxyFromPairs(int proxy, b3Dispatcher* dispatcher);
- bool collides = true;//(proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
- //collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
-
- return collides;
- }
-
- b3BroadphasePairArray& getOverlappingPairArray()
- {
- return m_overlappingPairArray;
- }
+ virtual void removeOverlappingPairsContainingProxy(int proxy, b3Dispatcher* dispatcher);
- const b3BroadphasePairArray& getOverlappingPairArray() const
- {
- return m_overlappingPairArray;
- }
+ inline bool needsBroadphaseCollision(int proxy0, int proxy1) const
+ {
+ if (m_overlapFilterCallback)
+ return m_overlapFilterCallback->needBroadphaseCollision(proxy0, proxy1);
-
+ bool collides = true; //(proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
+ //collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
+ return collides;
+ }
- b3BroadphasePair* getOverlappingPairArrayPtr()
- {
- return &m_overlappingPairArray[0];
- }
+ b3BroadphasePairArray& getOverlappingPairArray()
+ {
+ return m_overlappingPairArray;
+ }
- const b3BroadphasePair* getOverlappingPairArrayPtr() const
- {
- return &m_overlappingPairArray[0];
- }
+ const b3BroadphasePairArray& getOverlappingPairArray() const
+ {
+ return m_overlappingPairArray;
+ }
- int getNumOverlappingPairs() const
- {
- return m_overlappingPairArray.size();
- }
-
- b3OverlapFilterCallback* getOverlapFilterCallback()
- {
- return m_overlapFilterCallback;
- }
+ b3BroadphasePair* getOverlappingPairArrayPtr()
+ {
+ return &m_overlappingPairArray[0];
+ }
- void setOverlapFilterCallback(b3OverlapFilterCallback* callback)
- {
- m_overlapFilterCallback = callback;
- }
+ const b3BroadphasePair* getOverlappingPairArrayPtr() const
+ {
+ return &m_overlappingPairArray[0];
+ }
- virtual bool hasDeferredRemoval()
- {
- return m_hasDeferredRemoval;
- }
+ int getNumOverlappingPairs() const
+ {
+ return m_overlappingPairArray.size();
+ }
+
+ b3OverlapFilterCallback* getOverlapFilterCallback()
+ {
+ return m_overlapFilterCallback;
+ }
-/* virtual void setInternalGhostPairCallback(b3OverlappingPairCallback* ghostPairCallback)
+ void setOverlapFilterCallback(b3OverlapFilterCallback* callback)
+ {
+ m_overlapFilterCallback = callback;
+ }
+
+ virtual bool hasDeferredRemoval()
+ {
+ return m_hasDeferredRemoval;
+ }
+
+ /* virtual void setInternalGhostPairCallback(b3OverlappingPairCallback* ghostPairCallback)
{
m_ghostPairCallback = ghostPairCallback;
}
*/
- virtual void sortOverlappingPairs(b3Dispatcher* dispatcher);
-
-
+ virtual void sortOverlappingPairs(b3Dispatcher* dispatcher);
};
-
-
///b3NullPairCache skips add/removal of overlapping pairs. Userful for benchmarking and unit testing.
class b3NullPairCache : public b3OverlappingPairCache
{
-
- b3BroadphasePairArray m_overlappingPairArray;
+ b3BroadphasePairArray m_overlappingPairArray;
public:
-
- virtual b3BroadphasePair* getOverlappingPairArrayPtr()
+ virtual b3BroadphasePair* getOverlappingPairArrayPtr()
{
return &m_overlappingPairArray[0];
}
- const b3BroadphasePair* getOverlappingPairArrayPtr() const
+ const b3BroadphasePair* getOverlappingPairArrayPtr() const
{
return &m_overlappingPairArray[0];
}
- b3BroadphasePairArray& getOverlappingPairArray()
+ b3BroadphasePairArray& getOverlappingPairArray()
{
return m_overlappingPairArray;
}
-
- virtual void cleanOverlappingPair(b3BroadphasePair& /*pair*/,b3Dispatcher* /*dispatcher*/)
- {
+ virtual void cleanOverlappingPair(b3BroadphasePair& /*pair*/, b3Dispatcher* /*dispatcher*/)
+ {
}
virtual int getNumOverlappingPairs() const
@@ -418,16 +377,15 @@ public:
return 0;
}
- virtual void cleanProxyFromPairs(int /*proxy*/,b3Dispatcher* /*dispatcher*/)
+ virtual void cleanProxyFromPairs(int /*proxy*/, b3Dispatcher* /*dispatcher*/)
{
-
}
- virtual void setOverlapFilterCallback(b3OverlapFilterCallback* /*callback*/)
+ virtual void setOverlapFilterCallback(b3OverlapFilterCallback* /*callback*/)
{
}
- virtual void processAllOverlappingPairs(b3OverlapCallback*,b3Dispatcher* /*dispatcher*/)
+ virtual void processAllOverlappingPairs(b3OverlapCallback*, b3Dispatcher* /*dispatcher*/)
{
}
@@ -436,39 +394,34 @@ public:
return 0;
}
- virtual bool hasDeferredRemoval()
+ virtual bool hasDeferredRemoval()
{
return true;
}
-// virtual void setInternalGhostPairCallback(b3OverlappingPairCallback* /* ghostPairCallback */)
-// {
-//
-// }
+ // virtual void setInternalGhostPairCallback(b3OverlappingPairCallback* /* ghostPairCallback */)
+ // {
+ //
+ // }
- virtual b3BroadphasePair* addOverlappingPair(int /*proxy0*/,int /*proxy1*/)
+ virtual b3BroadphasePair* addOverlappingPair(int /*proxy0*/, int /*proxy1*/)
{
return 0;
}
- virtual void* removeOverlappingPair(int /*proxy0*/,int /*proxy1*/,b3Dispatcher* /*dispatcher*/)
+ virtual void* removeOverlappingPair(int /*proxy0*/, int /*proxy1*/, b3Dispatcher* /*dispatcher*/)
{
return 0;
}
- virtual void removeOverlappingPairsContainingProxy(int /*proxy0*/,b3Dispatcher* /*dispatcher*/)
+ virtual void removeOverlappingPairsContainingProxy(int /*proxy0*/, b3Dispatcher* /*dispatcher*/)
{
}
-
- virtual void sortOverlappingPairs(b3Dispatcher* dispatcher)
+
+ virtual void sortOverlappingPairs(b3Dispatcher* dispatcher)
{
- (void) dispatcher;
+ (void)dispatcher;
}
-
-
};
-
-#endif //B3_OVERLAPPING_PAIR_CACHE_H
-
-
+#endif //B3_OVERLAPPING_PAIR_CACHE_H
diff --git a/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h b/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h
index 7f9bf990bf..343a2c0e21 100644
--- a/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h
+++ b/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h
@@ -2,7 +2,6 @@
#ifndef B3_AABB_H
#define B3_AABB_H
-
#include "Bullet3Common/shared/b3Float4.h"
#include "Bullet3Common/shared/b3Mat3x3.h"
@@ -10,44 +9,42 @@ typedef struct b3Aabb b3Aabb_t;
struct b3Aabb
{
- union
- {
+ union {
float m_min[4];
b3Float4 m_minVec;
int m_minIndices[4];
};
- union
- {
- float m_max[4];
+ union {
+ float m_max[4];
b3Float4 m_maxVec;
int m_signedMaxIndices[4];
};
};
-inline void b3TransformAabb2(b3Float4ConstArg localAabbMin,b3Float4ConstArg localAabbMax, float margin,
- b3Float4ConstArg pos,
- b3QuatConstArg orn,
- b3Float4* aabbMinOut,b3Float4* aabbMaxOut)
+inline void b3TransformAabb2(b3Float4ConstArg localAabbMin, b3Float4ConstArg localAabbMax, float margin,
+ b3Float4ConstArg pos,
+ b3QuatConstArg orn,
+ b3Float4* aabbMinOut, b3Float4* aabbMaxOut)
{
- b3Float4 localHalfExtents = 0.5f*(localAabbMax-localAabbMin);
- localHalfExtents+=b3MakeFloat4(margin,margin,margin,0.f);
- b3Float4 localCenter = 0.5f*(localAabbMax+localAabbMin);
- b3Mat3x3 m;
- m = b3QuatGetRotationMatrix(orn);
- b3Mat3x3 abs_b = b3AbsoluteMat3x3(m);
- b3Float4 center = b3TransformPoint(localCenter,pos,orn);
-
- b3Float4 extent = b3MakeFloat4(b3Dot3F4(localHalfExtents,b3GetRow(abs_b,0)),
- b3Dot3F4(localHalfExtents,b3GetRow(abs_b,1)),
- b3Dot3F4(localHalfExtents,b3GetRow(abs_b,2)),
- 0.f);
- *aabbMinOut = center-extent;
- *aabbMaxOut = center+extent;
+ b3Float4 localHalfExtents = 0.5f * (localAabbMax - localAabbMin);
+ localHalfExtents += b3MakeFloat4(margin, margin, margin, 0.f);
+ b3Float4 localCenter = 0.5f * (localAabbMax + localAabbMin);
+ b3Mat3x3 m;
+ m = b3QuatGetRotationMatrix(orn);
+ b3Mat3x3 abs_b = b3AbsoluteMat3x3(m);
+ b3Float4 center = b3TransformPoint(localCenter, pos, orn);
+
+ b3Float4 extent = b3MakeFloat4(b3Dot3F4(localHalfExtents, b3GetRow(abs_b, 0)),
+ b3Dot3F4(localHalfExtents, b3GetRow(abs_b, 1)),
+ b3Dot3F4(localHalfExtents, b3GetRow(abs_b, 2)),
+ 0.f);
+ *aabbMinOut = center - extent;
+ *aabbMaxOut = center + extent;
}
/// conservative test for overlap between two aabbs
-inline bool b3TestAabbAgainstAabb(b3Float4ConstArg aabbMin1,b3Float4ConstArg aabbMax1,
- b3Float4ConstArg aabbMin2, b3Float4ConstArg aabbMax2)
+inline bool b3TestAabbAgainstAabb(b3Float4ConstArg aabbMin1, b3Float4ConstArg aabbMax1,
+ b3Float4ConstArg aabbMin2, b3Float4ConstArg aabbMax2)
{
bool overlap = true;
overlap = (aabbMin1.x > aabbMax2.x || aabbMax1.x < aabbMin2.x) ? false : overlap;
@@ -56,4 +53,4 @@ inline bool b3TestAabbAgainstAabb(b3Float4ConstArg aabbMin1,b3Float4ConstArg aab
return overlap;
}
-#endif //B3_AABB_H
+#endif //B3_AABB_H
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3Config.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3Config.h
index 65d4a21613..518da89c54 100644
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3Config.h
+++ b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3Config.h
@@ -1,41 +1,39 @@
#ifndef B3_CONFIG_H
#define B3_CONFIG_H
-struct b3Config
+struct b3Config
{
- int m_maxConvexBodies;
- int m_maxConvexShapes;
- int m_maxBroadphasePairs;
+ int m_maxConvexBodies;
+ int m_maxConvexShapes;
+ int m_maxBroadphasePairs;
int m_maxContactCapacity;
int m_compoundPairCapacity;
int m_maxVerticesPerFace;
int m_maxFacesPerShape;
- int m_maxConvexVertices;
+ int m_maxConvexVertices;
int m_maxConvexIndices;
int m_maxConvexUniqueEdges;
-
- int m_maxCompoundChildShapes;
-
+
+ int m_maxCompoundChildShapes;
+
int m_maxTriConvexPairCapacity;
b3Config()
- :m_maxConvexBodies(128*1024),
- m_maxVerticesPerFace(64),
- m_maxFacesPerShape(12),
- m_maxConvexVertices(8192),
- m_maxConvexIndices(81920),
- m_maxConvexUniqueEdges(8192),
- m_maxCompoundChildShapes(8192),
- m_maxTriConvexPairCapacity(256*1024)
+ : m_maxConvexBodies(128 * 1024),
+ m_maxVerticesPerFace(64),
+ m_maxFacesPerShape(12),
+ m_maxConvexVertices(8192),
+ m_maxConvexIndices(81920),
+ m_maxConvexUniqueEdges(8192),
+ m_maxCompoundChildShapes(8192),
+ m_maxTriConvexPairCapacity(256 * 1024)
{
m_maxConvexShapes = m_maxConvexBodies;
- m_maxBroadphasePairs = 16*m_maxConvexBodies;
+ m_maxBroadphasePairs = 16 * m_maxConvexBodies;
m_maxContactCapacity = m_maxBroadphasePairs;
- m_compoundPairCapacity = 1024*1024;
+ m_compoundPairCapacity = 1024 * 1024;
}
};
-
-#endif//B3_CONFIG_H
-
+#endif //B3_CONFIG_H
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3Contact4.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3Contact4.h
index fb25165673..c2cd3c729b 100644
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3Contact4.h
+++ b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3Contact4.h
@@ -19,28 +19,37 @@ subject to the following restrictions:
#include "Bullet3Common/b3Vector3.h"
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
-B3_ATTRIBUTE_ALIGNED16(struct) b3Contact4 : public b3Contact4Data
+B3_ATTRIBUTE_ALIGNED16(struct)
+b3Contact4 : public b3Contact4Data
{
B3_DECLARE_ALIGNED_ALLOCATOR();
- int getBodyA()const {return abs(m_bodyAPtrAndSignBit);}
- int getBodyB()const {return abs(m_bodyBPtrAndSignBit);}
- bool isBodyAFixed()const { return m_bodyAPtrAndSignBit<0;}
- bool isBodyBFixed()const { return m_bodyBPtrAndSignBit<0;}
+ int getBodyA() const { return abs(m_bodyAPtrAndSignBit); }
+ int getBodyB() const { return abs(m_bodyBPtrAndSignBit); }
+ bool isBodyAFixed() const { return m_bodyAPtrAndSignBit < 0; }
+ bool isBodyBFixed() const { return m_bodyBPtrAndSignBit < 0; }
// todo. make it safer
int& getBatchIdx() { return m_batchIdx; }
const int& getBatchIdx() const { return m_batchIdx; }
- float getRestituitionCoeff() const { return ((float)m_restituitionCoeffCmp/(float)0xffff); }
- void setRestituitionCoeff( float c ) { b3Assert( c >= 0.f && c <= 1.f ); m_restituitionCoeffCmp = (unsigned short)(c*0xffff); }
- float getFrictionCoeff() const { return ((float)m_frictionCoeffCmp/(float)0xffff); }
- void setFrictionCoeff( float c ) { b3Assert( c >= 0.f && c <= 1.f ); m_frictionCoeffCmp = (unsigned short)(c*0xffff); }
+ float getRestituitionCoeff() const { return ((float)m_restituitionCoeffCmp / (float)0xffff); }
+ void setRestituitionCoeff(float c)
+ {
+ b3Assert(c >= 0.f && c <= 1.f);
+ m_restituitionCoeffCmp = (unsigned short)(c * 0xffff);
+ }
+ float getFrictionCoeff() const { return ((float)m_frictionCoeffCmp / (float)0xffff); }
+ void setFrictionCoeff(float c)
+ {
+ b3Assert(c >= 0.f && c <= 1.f);
+ m_frictionCoeffCmp = (unsigned short)(c * 0xffff);
+ }
//float& getNPoints() { return m_worldNormal[3]; }
- int getNPoints() const { return (int) m_worldNormalOnB.w; }
+ int getNPoints() const { return (int)m_worldNormalOnB.w; }
float getPenetration(int idx) const { return m_worldPosB[idx].w; }
- bool isInvalid() const { return (getBodyA()==0 || getBodyB()==0); }
+ bool isInvalid() const { return (getBodyA() == 0 || getBodyB() == 0); }
};
-#endif //B3_CONTACT4_H
+#endif //B3_CONTACT4_H
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.cpp b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.cpp
index 55706fa631..a5dab74a34 100644
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.cpp
+++ b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.cpp
@@ -13,52 +13,42 @@ subject to the following restrictions:
*/
//Originally written by Erwin Coumans
-
#include "b3ConvexUtility.h"
#include "Bullet3Geometry/b3ConvexHullComputer.h"
#include "Bullet3Geometry/b3GrahamScan2dConvexHull.h"
#include "Bullet3Common/b3Quaternion.h"
#include "Bullet3Common/b3HashMap.h"
-
-
-
-
b3ConvexUtility::~b3ConvexUtility()
{
}
-bool b3ConvexUtility::initializePolyhedralFeatures(const b3Vector3* orgVertices, int numPoints, bool mergeCoplanarTriangles)
+bool b3ConvexUtility::initializePolyhedralFeatures(const b3Vector3* orgVertices, int numPoints, bool mergeCoplanarTriangles)
{
-
-
-
b3ConvexHullComputer conv;
- conv.compute(&orgVertices[0].getX(), sizeof(b3Vector3),numPoints,0.f,0.f);
+ conv.compute(&orgVertices[0].getX(), sizeof(b3Vector3), numPoints, 0.f, 0.f);
b3AlignedObjectArray<b3Vector3> faceNormals;
int numFaces = conv.faces.size();
faceNormals.resize(numFaces);
b3ConvexHullComputer* convexUtil = &conv;
-
- b3AlignedObjectArray<b3MyFace> tmpFaces;
+ b3AlignedObjectArray<b3MyFace> tmpFaces;
tmpFaces.resize(numFaces);
int numVertices = convexUtil->vertices.size();
m_vertices.resize(numVertices);
- for (int p=0;p<numVertices;p++)
+ for (int p = 0; p < numVertices; p++)
{
m_vertices[p] = convexUtil->vertices[p];
}
-
- for (int i=0;i<numFaces;i++)
+ for (int i = 0; i < numFaces; i++)
{
int face = convexUtil->faces[i];
//printf("face=%d\n",face);
- const b3ConvexHullComputer::Edge* firstEdge = &convexUtil->edges[face];
- const b3ConvexHullComputer::Edge* edge = firstEdge;
+ const b3ConvexHullComputer::Edge* firstEdge = &convexUtil->edges[face];
+ const b3ConvexHullComputer::Edge* edge = firstEdge;
b3Vector3 edges[3];
int numEdges = 0;
@@ -66,25 +56,23 @@ bool b3ConvexUtility::initializePolyhedralFeatures(const b3Vector3* orgVertices,
do
{
-
int src = edge->getSourceVertex();
tmpFaces[i].m_indices.push_back(src);
int targ = edge->getTargetVertex();
b3Vector3 wa = convexUtil->vertices[src];
b3Vector3 wb = convexUtil->vertices[targ];
- b3Vector3 newEdge = wb-wa;
+ b3Vector3 newEdge = wb - wa;
newEdge.normalize();
- if (numEdges<2)
+ if (numEdges < 2)
edges[numEdges++] = newEdge;
edge = edge->getNextEdgeOfFace();
- } while (edge!=firstEdge);
+ } while (edge != firstEdge);
b3Scalar planeEq = 1e30f;
-
- if (numEdges==2)
+ if (numEdges == 2)
{
faceNormals[i] = edges[0].cross(edges[1]);
faceNormals[i].normalize();
@@ -92,20 +80,19 @@ bool b3ConvexUtility::initializePolyhedralFeatures(const b3Vector3* orgVertices,
tmpFaces[i].m_plane[1] = faceNormals[i].getY();
tmpFaces[i].m_plane[2] = faceNormals[i].getZ();
tmpFaces[i].m_plane[3] = planeEq;
-
}
else
{
- b3Assert(0);//degenerate?
+ b3Assert(0); //degenerate?
faceNormals[i].setZero();
}
- for (int v=0;v<tmpFaces[i].m_indices.size();v++)
+ for (int v = 0; v < tmpFaces[i].m_indices.size(); v++)
{
b3Scalar eq = m_vertices[tmpFaces[i].m_indices[v]].dot(faceNormals[i]);
- if (planeEq>eq)
+ if (planeEq > eq)
{
- planeEq=eq;
+ planeEq = eq;
}
}
tmpFaces[i].m_plane[3] = -planeEq;
@@ -113,89 +100,86 @@ bool b3ConvexUtility::initializePolyhedralFeatures(const b3Vector3* orgVertices,
//merge coplanar faces and copy them to m_polyhedron
- b3Scalar faceWeldThreshold= 0.999f;
+ b3Scalar faceWeldThreshold = 0.999f;
b3AlignedObjectArray<int> todoFaces;
- for (int i=0;i<tmpFaces.size();i++)
+ for (int i = 0; i < tmpFaces.size(); i++)
todoFaces.push_back(i);
while (todoFaces.size())
{
b3AlignedObjectArray<int> coplanarFaceGroup;
- int refFace = todoFaces[todoFaces.size()-1];
+ int refFace = todoFaces[todoFaces.size() - 1];
coplanarFaceGroup.push_back(refFace);
b3MyFace& faceA = tmpFaces[refFace];
todoFaces.pop_back();
- b3Vector3 faceNormalA = b3MakeVector3(faceA.m_plane[0],faceA.m_plane[1],faceA.m_plane[2]);
- for (int j=todoFaces.size()-1;j>=0;j--)
+ b3Vector3 faceNormalA = b3MakeVector3(faceA.m_plane[0], faceA.m_plane[1], faceA.m_plane[2]);
+ for (int j = todoFaces.size() - 1; j >= 0; j--)
{
int i = todoFaces[j];
b3MyFace& faceB = tmpFaces[i];
- b3Vector3 faceNormalB = b3MakeVector3(faceB.m_plane[0],faceB.m_plane[1],faceB.m_plane[2]);
- if (faceNormalA.dot(faceNormalB)>faceWeldThreshold)
+ b3Vector3 faceNormalB = b3MakeVector3(faceB.m_plane[0], faceB.m_plane[1], faceB.m_plane[2]);
+ if (faceNormalA.dot(faceNormalB) > faceWeldThreshold)
{
coplanarFaceGroup.push_back(i);
todoFaces.remove(i);
}
}
-
bool did_merge = false;
- if (coplanarFaceGroup.size()>1)
+ if (coplanarFaceGroup.size() > 1)
{
//do the merge: use Graham Scan 2d convex hull
b3AlignedObjectArray<b3GrahamVector3> orgpoints;
- b3Vector3 averageFaceNormal = b3MakeVector3(0,0,0);
+ b3Vector3 averageFaceNormal = b3MakeVector3(0, 0, 0);
- for (int i=0;i<coplanarFaceGroup.size();i++)
+ for (int i = 0; i < coplanarFaceGroup.size(); i++)
{
-// m_polyhedron->m_faces.push_back(tmpFaces[coplanarFaceGroup[i]]);
+ // m_polyhedron->m_faces.push_back(tmpFaces[coplanarFaceGroup[i]]);
b3MyFace& face = tmpFaces[coplanarFaceGroup[i]];
- b3Vector3 faceNormal = b3MakeVector3(face.m_plane[0],face.m_plane[1],face.m_plane[2]);
- averageFaceNormal+=faceNormal;
- for (int f=0;f<face.m_indices.size();f++)
+ b3Vector3 faceNormal = b3MakeVector3(face.m_plane[0], face.m_plane[1], face.m_plane[2]);
+ averageFaceNormal += faceNormal;
+ for (int f = 0; f < face.m_indices.size(); f++)
{
int orgIndex = face.m_indices[f];
b3Vector3 pt = m_vertices[orgIndex];
-
+
bool found = false;
- for (int i=0;i<orgpoints.size();i++)
+ for (int i = 0; i < orgpoints.size(); i++)
{
//if ((orgpoints[i].m_orgIndex == orgIndex) || ((rotatedPt-orgpoints[i]).length2()<0.0001))
if (orgpoints[i].m_orgIndex == orgIndex)
{
- found=true;
+ found = true;
break;
}
}
if (!found)
- orgpoints.push_back(b3GrahamVector3(pt,orgIndex));
+ orgpoints.push_back(b3GrahamVector3(pt, orgIndex));
}
}
-
-
b3MyFace combinedFace;
- for (int i=0;i<4;i++)
+ for (int i = 0; i < 4; i++)
combinedFace.m_plane[i] = tmpFaces[coplanarFaceGroup[0]].m_plane[i];
b3AlignedObjectArray<b3GrahamVector3> hull;
averageFaceNormal.normalize();
- b3GrahamScanConvexHull2D(orgpoints,hull,averageFaceNormal);
+ b3GrahamScanConvexHull2D(orgpoints, hull, averageFaceNormal);
- for (int i=0;i<hull.size();i++)
+ for (int i = 0; i < hull.size(); i++)
{
combinedFace.m_indices.push_back(hull[i].m_orgIndex);
- for(int k = 0; k < orgpoints.size(); k++)
+ for (int k = 0; k < orgpoints.size(); k++)
{
- if(orgpoints[k].m_orgIndex == hull[i].m_orgIndex)
+ if (orgpoints[k].m_orgIndex == hull[i].m_orgIndex)
{
- orgpoints[k].m_orgIndex = -1; // invalidate...
+ orgpoints[k].m_orgIndex = -1; // invalidate...
break;
}
}
@@ -203,38 +187,41 @@ bool b3ConvexUtility::initializePolyhedralFeatures(const b3Vector3* orgVertices,
// are there rejected vertices?
bool reject_merge = false;
-
-
- for(int i = 0; i < orgpoints.size(); i++) {
- if(orgpoints[i].m_orgIndex == -1)
- continue; // this is in the hull...
+ for (int i = 0; i < orgpoints.size(); i++)
+ {
+ if (orgpoints[i].m_orgIndex == -1)
+ continue; // this is in the hull...
// this vertex is rejected -- is anybody else using this vertex?
- for(int j = 0; j < tmpFaces.size(); j++) {
-
+ for (int j = 0; j < tmpFaces.size(); j++)
+ {
b3MyFace& face = tmpFaces[j];
// is this a face of the current coplanar group?
bool is_in_current_group = false;
- for(int k = 0; k < coplanarFaceGroup.size(); k++) {
- if(coplanarFaceGroup[k] == j) {
+ for (int k = 0; k < coplanarFaceGroup.size(); k++)
+ {
+ if (coplanarFaceGroup[k] == j)
+ {
is_in_current_group = true;
break;
}
}
- if(is_in_current_group) // ignore this face...
+ if (is_in_current_group) // ignore this face...
continue;
// does this face use this rejected vertex?
- for(int v = 0; v < face.m_indices.size(); v++) {
- if(face.m_indices[v] == orgpoints[i].m_orgIndex) {
+ for (int v = 0; v < face.m_indices.size(); v++)
+ {
+ if (face.m_indices[v] == orgpoints[i].m_orgIndex)
+ {
// this rejected vertex is used in another face -- reject merge
reject_merge = true;
break;
}
}
- if(reject_merge)
+ if (reject_merge)
break;
}
- if(reject_merge)
+ if (reject_merge)
break;
}
@@ -245,18 +232,14 @@ bool b3ConvexUtility::initializePolyhedralFeatures(const b3Vector3* orgVertices,
m_faces.push_back(combinedFace);
}
}
- if(!did_merge)
+ if (!did_merge)
{
- for (int i=0;i<coplanarFaceGroup.size();i++)
+ for (int i = 0; i < coplanarFaceGroup.size(); i++)
{
b3MyFace face = tmpFaces[coplanarFaceGroup[i]];
m_faces.push_back(face);
}
-
- }
-
-
-
+ }
}
initialize();
@@ -264,43 +247,38 @@ bool b3ConvexUtility::initializePolyhedralFeatures(const b3Vector3* orgVertices,
return true;
}
-
-
-
-
-
inline bool IsAlmostZero(const b3Vector3& v)
{
- if(fabsf(v.getX())>1e-6 || fabsf(v.getY())>1e-6 || fabsf(v.getZ())>1e-6) return false;
+ if (fabsf(v.getX()) > 1e-6 || fabsf(v.getY()) > 1e-6 || fabsf(v.getZ()) > 1e-6) return false;
return true;
}
struct b3InternalVertexPair
{
- b3InternalVertexPair(short int v0,short int v1)
- :m_v0(v0),
- m_v1(v1)
+ b3InternalVertexPair(short int v0, short int v1)
+ : m_v0(v0),
+ m_v1(v1)
{
- if (m_v1>m_v0)
- b3Swap(m_v0,m_v1);
+ if (m_v1 > m_v0)
+ b3Swap(m_v0, m_v1);
}
short int m_v0;
short int m_v1;
int getHash() const
{
- return m_v0+(m_v1<<16);
+ return m_v0 + (m_v1 << 16);
}
bool equals(const b3InternalVertexPair& other) const
{
- return m_v0==other.m_v0 && m_v1==other.m_v1;
+ return m_v0 == other.m_v0 && m_v1 == other.m_v1;
}
};
struct b3InternalEdge
{
b3InternalEdge()
- :m_face0(-1),
- m_face1(-1)
+ : m_face0(-1),
+ m_face1(-1)
{
}
short int m_face0;
@@ -312,23 +290,31 @@ struct b3InternalEdge
#ifdef TEST_INTERNAL_OBJECTS
bool b3ConvexUtility::testContainment() const
{
- for(int p=0;p<8;p++)
+ for (int p = 0; p < 8; p++)
{
b3Vector3 LocalPt;
- if(p==0) LocalPt = m_localCenter + b3Vector3(m_extents[0], m_extents[1], m_extents[2]);
- else if(p==1) LocalPt = m_localCenter + b3Vector3(m_extents[0], m_extents[1], -m_extents[2]);
- else if(p==2) LocalPt = m_localCenter + b3Vector3(m_extents[0], -m_extents[1], m_extents[2]);
- else if(p==3) LocalPt = m_localCenter + b3Vector3(m_extents[0], -m_extents[1], -m_extents[2]);
- else if(p==4) LocalPt = m_localCenter + b3Vector3(-m_extents[0], m_extents[1], m_extents[2]);
- else if(p==5) LocalPt = m_localCenter + b3Vector3(-m_extents[0], m_extents[1], -m_extents[2]);
- else if(p==6) LocalPt = m_localCenter + b3Vector3(-m_extents[0], -m_extents[1], m_extents[2]);
- else if(p==7) LocalPt = m_localCenter + b3Vector3(-m_extents[0], -m_extents[1], -m_extents[2]);
-
- for(int i=0;i<m_faces.size();i++)
+ if (p == 0)
+ LocalPt = m_localCenter + b3Vector3(m_extents[0], m_extents[1], m_extents[2]);
+ else if (p == 1)
+ LocalPt = m_localCenter + b3Vector3(m_extents[0], m_extents[1], -m_extents[2]);
+ else if (p == 2)
+ LocalPt = m_localCenter + b3Vector3(m_extents[0], -m_extents[1], m_extents[2]);
+ else if (p == 3)
+ LocalPt = m_localCenter + b3Vector3(m_extents[0], -m_extents[1], -m_extents[2]);
+ else if (p == 4)
+ LocalPt = m_localCenter + b3Vector3(-m_extents[0], m_extents[1], m_extents[2]);
+ else if (p == 5)
+ LocalPt = m_localCenter + b3Vector3(-m_extents[0], m_extents[1], -m_extents[2]);
+ else if (p == 6)
+ LocalPt = m_localCenter + b3Vector3(-m_extents[0], -m_extents[1], m_extents[2]);
+ else if (p == 7)
+ LocalPt = m_localCenter + b3Vector3(-m_extents[0], -m_extents[1], -m_extents[2]);
+
+ for (int i = 0; i < m_faces.size(); i++)
{
const b3Vector3 Normal(m_faces[i].m_plane[0], m_faces[i].m_plane[1], m_faces[i].m_plane[2]);
const b3Scalar d = LocalPt.dot(Normal) + m_faces[i].m_plane[3];
- if(d>0.0f)
+ if (d > 0.0f)
return false;
}
}
@@ -336,39 +322,38 @@ bool b3ConvexUtility::testContainment() const
}
#endif
-void b3ConvexUtility::initialize()
+void b3ConvexUtility::initialize()
{
-
- b3HashMap<b3InternalVertexPair,b3InternalEdge> edges;
+ b3HashMap<b3InternalVertexPair, b3InternalEdge> edges;
b3Scalar TotalArea = 0.0f;
-
+
m_localCenter.setValue(0, 0, 0);
- for(int i=0;i<m_faces.size();i++)
+ for (int i = 0; i < m_faces.size(); i++)
{
int numVertices = m_faces[i].m_indices.size();
int NbTris = numVertices;
- for(int j=0;j<NbTris;j++)
+ for (int j = 0; j < NbTris; j++)
{
- int k = (j+1)%numVertices;
- b3InternalVertexPair vp(m_faces[i].m_indices[j],m_faces[i].m_indices[k]);
+ int k = (j + 1) % numVertices;
+ b3InternalVertexPair vp(m_faces[i].m_indices[j], m_faces[i].m_indices[k]);
b3InternalEdge* edptr = edges.find(vp);
- b3Vector3 edge = m_vertices[vp.m_v1]-m_vertices[vp.m_v0];
+ b3Vector3 edge = m_vertices[vp.m_v1] - m_vertices[vp.m_v0];
edge.normalize();
bool found = false;
- b3Vector3 diff,diff2;
+ b3Vector3 diff, diff2;
- for (int p=0;p<m_uniqueEdges.size();p++)
+ for (int p = 0; p < m_uniqueEdges.size(); p++)
{
- diff = m_uniqueEdges[p]-edge;
- diff2 = m_uniqueEdges[p]+edge;
+ diff = m_uniqueEdges[p] - edge;
+ diff2 = m_uniqueEdges[p] + edge;
- // if ((diff.length2()==0.f) ||
+ // if ((diff.length2()==0.f) ||
// (diff2.length2()==0.f))
- if (IsAlmostZero(diff) ||
- IsAlmostZero(diff2))
+ if (IsAlmostZero(diff) ||
+ IsAlmostZero(diff2))
{
found = true;
break;
@@ -382,106 +367,101 @@ void b3ConvexUtility::initialize()
if (edptr)
{
- //TBD: figure out why I added this assert
-// b3Assert(edptr->m_face0>=0);
- // b3Assert(edptr->m_face1<0);
+ //TBD: figure out why I added this assert
+ // b3Assert(edptr->m_face0>=0);
+ // b3Assert(edptr->m_face1<0);
edptr->m_face1 = i;
- } else
+ }
+ else
{
b3InternalEdge ed;
ed.m_face0 = i;
- edges.insert(vp,ed);
+ edges.insert(vp, ed);
}
}
}
#ifdef USE_CONNECTED_FACES
- for(int i=0;i<m_faces.size();i++)
+ for (int i = 0; i < m_faces.size(); i++)
{
int numVertices = m_faces[i].m_indices.size();
m_faces[i].m_connectedFaces.resize(numVertices);
- for(int j=0;j<numVertices;j++)
+ for (int j = 0; j < numVertices; j++)
{
- int k = (j+1)%numVertices;
- b3InternalVertexPair vp(m_faces[i].m_indices[j],m_faces[i].m_indices[k]);
+ int k = (j + 1) % numVertices;
+ b3InternalVertexPair vp(m_faces[i].m_indices[j], m_faces[i].m_indices[k]);
b3InternalEdge* edptr = edges.find(vp);
b3Assert(edptr);
- b3Assert(edptr->m_face0>=0);
- b3Assert(edptr->m_face1>=0);
+ b3Assert(edptr->m_face0 >= 0);
+ b3Assert(edptr->m_face1 >= 0);
- int connectedFace = (edptr->m_face0==i)?edptr->m_face1:edptr->m_face0;
+ int connectedFace = (edptr->m_face0 == i) ? edptr->m_face1 : edptr->m_face0;
m_faces[i].m_connectedFaces[j] = connectedFace;
}
}
-#endif//USE_CONNECTED_FACES
+#endif //USE_CONNECTED_FACES
- for(int i=0;i<m_faces.size();i++)
+ for (int i = 0; i < m_faces.size(); i++)
{
int numVertices = m_faces[i].m_indices.size();
- int NbTris = numVertices-2;
-
+ int NbTris = numVertices - 2;
+
const b3Vector3& p0 = m_vertices[m_faces[i].m_indices[0]];
- for(int j=1;j<=NbTris;j++)
+ for (int j = 1; j <= NbTris; j++)
{
- int k = (j+1)%numVertices;
+ int k = (j + 1) % numVertices;
const b3Vector3& p1 = m_vertices[m_faces[i].m_indices[j]];
const b3Vector3& p2 = m_vertices[m_faces[i].m_indices[k]];
b3Scalar Area = ((p0 - p1).cross(p0 - p2)).length() * 0.5f;
- b3Vector3 Center = (p0+p1+p2)/3.0f;
+ b3Vector3 Center = (p0 + p1 + p2) / 3.0f;
m_localCenter += Area * Center;
TotalArea += Area;
}
}
m_localCenter /= TotalArea;
-
-
-
#ifdef TEST_INTERNAL_OBJECTS
- if(1)
+ if (1)
{
m_radius = FLT_MAX;
- for(int i=0;i<m_faces.size();i++)
+ for (int i = 0; i < m_faces.size(); i++)
{
const b3Vector3 Normal(m_faces[i].m_plane[0], m_faces[i].m_plane[1], m_faces[i].m_plane[2]);
const b3Scalar dist = b3Fabs(m_localCenter.dot(Normal) + m_faces[i].m_plane[3]);
- if(dist<m_radius)
+ if (dist < m_radius)
m_radius = dist;
}
-
b3Scalar MinX = FLT_MAX;
b3Scalar MinY = FLT_MAX;
b3Scalar MinZ = FLT_MAX;
b3Scalar MaxX = -FLT_MAX;
b3Scalar MaxY = -FLT_MAX;
b3Scalar MaxZ = -FLT_MAX;
- for(int i=0; i<m_vertices.size(); i++)
+ for (int i = 0; i < m_vertices.size(); i++)
{
const b3Vector3& pt = m_vertices[i];
- if(pt.getX()<MinX) MinX = pt.getX();
- if(pt.getX()>MaxX) MaxX = pt.getX();
- if(pt.getY()<MinY) MinY = pt.getY();
- if(pt.getY()>MaxY) MaxY = pt.getY();
- if(pt.getZ()<MinZ) MinZ = pt.getZ();
- if(pt.getZ()>MaxZ) MaxZ = pt.getZ();
+ if (pt.getX() < MinX) MinX = pt.getX();
+ if (pt.getX() > MaxX) MaxX = pt.getX();
+ if (pt.getY() < MinY) MinY = pt.getY();
+ if (pt.getY() > MaxY) MaxY = pt.getY();
+ if (pt.getZ() < MinZ) MinZ = pt.getZ();
+ if (pt.getZ() > MaxZ) MaxZ = pt.getZ();
}
- mC.setValue(MaxX+MinX, MaxY+MinY, MaxZ+MinZ);
- mE.setValue(MaxX-MinX, MaxY-MinY, MaxZ-MinZ);
-
-
+ mC.setValue(MaxX + MinX, MaxY + MinY, MaxZ + MinZ);
+ mE.setValue(MaxX - MinX, MaxY - MinY, MaxZ - MinZ);
-// const b3Scalar r = m_radius / sqrtf(2.0f);
+ // const b3Scalar r = m_radius / sqrtf(2.0f);
const b3Scalar r = m_radius / sqrtf(3.0f);
const int LargestExtent = mE.maxAxis();
- const b3Scalar Step = (mE[LargestExtent]*0.5f - r)/1024.0f;
+ const b3Scalar Step = (mE[LargestExtent] * 0.5f - r) / 1024.0f;
m_extents[0] = m_extents[1] = m_extents[2] = r;
- m_extents[LargestExtent] = mE[LargestExtent]*0.5f;
+ m_extents[LargestExtent] = mE[LargestExtent] * 0.5f;
bool FoundBox = false;
- for(int j=0;j<1024;j++)
+ for (int j = 0; j < 1024; j++)
{
- if(testContainment())
+ if (testContainment())
{
FoundBox = true;
break;
@@ -489,25 +469,25 @@ void b3ConvexUtility::initialize()
m_extents[LargestExtent] -= Step;
}
- if(!FoundBox)
+ if (!FoundBox)
{
m_extents[0] = m_extents[1] = m_extents[2] = r;
}
else
{
// Refine the box
- const b3Scalar Step = (m_radius - r)/1024.0f;
- const int e0 = (1<<LargestExtent) & 3;
- const int e1 = (1<<e0) & 3;
+ const b3Scalar Step = (m_radius - r) / 1024.0f;
+ const int e0 = (1 << LargestExtent) & 3;
+ const int e1 = (1 << e0) & 3;
- for(int j=0;j<1024;j++)
+ for (int j = 0; j < 1024; j++)
{
const b3Scalar Saved0 = m_extents[e0];
const b3Scalar Saved1 = m_extents[e1];
m_extents[e0] += Step;
m_extents[e1] += Step;
- if(!testContainment())
+ if (!testContainment())
{
m_extents[e0] = Saved0;
m_extents[e1] = Saved1;
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.h
index 86c4151f8c..4c8a88cbda 100644
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.h
+++ b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.h
@@ -20,43 +20,36 @@ subject to the following restrictions:
#include "Bullet3Common/b3AlignedObjectArray.h"
#include "Bullet3Common/b3Transform.h"
-
-
-
struct b3MyFace
{
- b3AlignedObjectArray<int> m_indices;
- b3Scalar m_plane[4];
+ b3AlignedObjectArray<int> m_indices;
+ b3Scalar m_plane[4];
};
-B3_ATTRIBUTE_ALIGNED16(class) b3ConvexUtility
+B3_ATTRIBUTE_ALIGNED16(class)
+b3ConvexUtility
{
- public:
+public:
B3_DECLARE_ALIGNED_ALLOCATOR();
- b3Vector3 m_localCenter;
- b3Vector3 m_extents;
- b3Vector3 mC;
- b3Vector3 mE;
- b3Scalar m_radius;
-
- b3AlignedObjectArray<b3Vector3> m_vertices;
- b3AlignedObjectArray<b3MyFace> m_faces;
+ b3Vector3 m_localCenter;
+ b3Vector3 m_extents;
+ b3Vector3 mC;
+ b3Vector3 mE;
+ b3Scalar m_radius;
+
+ b3AlignedObjectArray<b3Vector3> m_vertices;
+ b3AlignedObjectArray<b3MyFace> m_faces;
b3AlignedObjectArray<b3Vector3> m_uniqueEdges;
-
b3ConvexUtility()
{
}
virtual ~b3ConvexUtility();
- bool initializePolyhedralFeatures(const b3Vector3* orgVertices, int numVertices, bool mergeCoplanarTriangles=true);
-
- void initialize();
- bool testContainment() const;
-
-
+ bool initializePolyhedralFeatures(const b3Vector3* orgVertices, int numVertices, bool mergeCoplanarTriangles = true);
+ void initialize();
+ bool testContainment() const;
};
#endif
- \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3CpuNarrowPhase.cpp b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3CpuNarrowPhase.cpp
index c3134b2c65..e0b2161100 100644
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3CpuNarrowPhase.cpp
+++ b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3CpuNarrowPhase.cpp
@@ -5,15 +5,13 @@
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ContactConvexConvexSAT.h"
-
struct b3CpuNarrowPhaseInternalData
{
b3AlignedObjectArray<b3Aabb> m_localShapeAABBCPU;
- b3AlignedObjectArray<b3Collidable> m_collidablesCPU;
+ b3AlignedObjectArray<b3Collidable> m_collidablesCPU;
b3AlignedObjectArray<b3ConvexUtility*> m_convexData;
b3Config m_config;
-
b3AlignedObjectArray<b3ConvexPolyhedronData> m_convexPolyhedra;
b3AlignedObjectArray<b3Vector3> m_uniqueEdges;
b3AlignedObjectArray<b3Vector3> m_convexVertices;
@@ -22,10 +20,9 @@ struct b3CpuNarrowPhaseInternalData
b3AlignedObjectArray<b3Contact4Data> m_contacts;
- int m_numAcceleratedShapes;
+ int m_numAcceleratedShapes;
};
-
const b3AlignedObjectArray<b3Contact4Data>& b3CpuNarrowPhase::getContacts() const
{
return m_data->m_contacts;
@@ -41,7 +38,6 @@ const b3Collidable& b3CpuNarrowPhase::getCollidableCpu(int collidableIndex) cons
return m_data->m_collidablesCPU[collidableIndex];
}
-
b3CpuNarrowPhase::b3CpuNarrowPhase(const struct b3Config& config)
{
m_data = new b3CpuNarrowPhaseInternalData;
@@ -61,7 +57,7 @@ void b3CpuNarrowPhase::computeContacts(b3AlignedObjectArray<b3Int4>& pairs, b3Al
int maxContactCapacity = m_data->m_config.m_maxContactCapacity;
m_data->m_contacts.resize(maxContactCapacity);
- for (int i=0;i<nPairs;i++)
+ for (int i = 0; i < nPairs; i++)
{
int bodyIndexA = pairs[i].x;
int bodyIndexB = pairs[i].y;
@@ -71,64 +67,57 @@ void b3CpuNarrowPhase::computeContacts(b3AlignedObjectArray<b3Int4>& pairs, b3Al
if (m_data->m_collidablesCPU[collidableIndexA].m_shapeType == SHAPE_SPHERE &&
m_data->m_collidablesCPU[collidableIndexB].m_shapeType == SHAPE_CONVEX_HULL)
{
-// computeContactSphereConvex(i,bodyIndexA,bodyIndexB,collidableIndexA,collidableIndexB,&bodies[0],
-// &m_data->m_collidablesCPU[0],&hostConvexData[0],&hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
+ // computeContactSphereConvex(i,bodyIndexA,bodyIndexB,collidableIndexA,collidableIndexB,&bodies[0],
+ // &m_data->m_collidablesCPU[0],&hostConvexData[0],&hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
}
if (m_data->m_collidablesCPU[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&
m_data->m_collidablesCPU[collidableIndexB].m_shapeType == SHAPE_SPHERE)
{
-// computeContactSphereConvex(i,bodyIndexB,bodyIndexA,collidableIndexB,collidableIndexA,&bodies[0],
-// &m_data->m_collidablesCPU[0],&hostConvexData[0],&hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
+ // computeContactSphereConvex(i,bodyIndexB,bodyIndexA,collidableIndexB,collidableIndexA,&bodies[0],
+ // &m_data->m_collidablesCPU[0],&hostConvexData[0],&hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
//printf("convex-sphere\n");
-
}
if (m_data->m_collidablesCPU[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&
m_data->m_collidablesCPU[collidableIndexB].m_shapeType == SHAPE_PLANE)
{
-// computeContactPlaneConvex(i,bodyIndexB,bodyIndexA,collidableIndexB,collidableIndexA,&bodies[0],
-// &m_data->m_collidablesCPU[0],&hostConvexData[0],&hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
-// printf("convex-plane\n");
-
+ // computeContactPlaneConvex(i,bodyIndexB,bodyIndexA,collidableIndexB,collidableIndexA,&bodies[0],
+ // &m_data->m_collidablesCPU[0],&hostConvexData[0],&hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
+ // printf("convex-plane\n");
}
if (m_data->m_collidablesCPU[collidableIndexA].m_shapeType == SHAPE_PLANE &&
m_data->m_collidablesCPU[collidableIndexB].m_shapeType == SHAPE_CONVEX_HULL)
{
-// computeContactPlaneConvex(i,bodyIndexA,bodyIndexB,collidableIndexA,collidableIndexB,&bodies[0],
-// &m_data->m_collidablesCPU[0],&hostConvexData[0],&hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
-// printf("plane-convex\n");
-
+ // computeContactPlaneConvex(i,bodyIndexA,bodyIndexB,collidableIndexA,collidableIndexB,&bodies[0],
+ // &m_data->m_collidablesCPU[0],&hostConvexData[0],&hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
+ // printf("plane-convex\n");
}
- if (m_data->m_collidablesCPU[collidableIndexA].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS &&
+ if (m_data->m_collidablesCPU[collidableIndexA].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS &&
m_data->m_collidablesCPU[collidableIndexB].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS)
{
-// computeContactCompoundCompound(i,bodyIndexB,bodyIndexA,collidableIndexB,collidableIndexA,&bodies[0],
-// &m_data->m_collidablesCPU[0],&hostConvexData[0],&cpuChildShapes[0], hostAabbsWorldSpace,hostAabbsLocalSpace,hostVertices,hostUniqueEdges,hostIndices,hostFaces,&hostContacts[0],
-// nContacts,maxContactCapacity,treeNodesCPU,subTreesCPU,bvhInfoCPU);
-// printf("convex-plane\n");
-
+ // computeContactCompoundCompound(i,bodyIndexB,bodyIndexA,collidableIndexB,collidableIndexA,&bodies[0],
+ // &m_data->m_collidablesCPU[0],&hostConvexData[0],&cpuChildShapes[0], hostAabbsWorldSpace,hostAabbsLocalSpace,hostVertices,hostUniqueEdges,hostIndices,hostFaces,&hostContacts[0],
+ // nContacts,maxContactCapacity,treeNodesCPU,subTreesCPU,bvhInfoCPU);
+ // printf("convex-plane\n");
}
-
- if (m_data->m_collidablesCPU[collidableIndexA].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS &&
+ if (m_data->m_collidablesCPU[collidableIndexA].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS &&
m_data->m_collidablesCPU[collidableIndexB].m_shapeType == SHAPE_PLANE)
{
-// computeContactPlaneCompound(i,bodyIndexB,bodyIndexA,collidableIndexB,collidableIndexA,&bodies[0],
-// &m_data->m_collidablesCPU[0],&hostConvexData[0],&cpuChildShapes[0], &hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
-// printf("convex-plane\n");
-
+ // computeContactPlaneCompound(i,bodyIndexB,bodyIndexA,collidableIndexB,collidableIndexA,&bodies[0],
+ // &m_data->m_collidablesCPU[0],&hostConvexData[0],&cpuChildShapes[0], &hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
+ // printf("convex-plane\n");
}
if (m_data->m_collidablesCPU[collidableIndexA].m_shapeType == SHAPE_PLANE &&
m_data->m_collidablesCPU[collidableIndexB].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS)
{
-// computeContactPlaneCompound(i,bodyIndexA,bodyIndexB,collidableIndexA,collidableIndexB,&bodies[0],
-// &m_data->m_collidablesCPU[0],&hostConvexData[0],&cpuChildShapes[0],&hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
-// printf("plane-convex\n");
-
+ // computeContactPlaneCompound(i,bodyIndexA,bodyIndexB,collidableIndexA,collidableIndexB,&bodies[0],
+ // &m_data->m_collidablesCPU[0],&hostConvexData[0],&cpuChildShapes[0],&hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
+ // printf("plane-convex\n");
}
if (m_data->m_collidablesCPU[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&
@@ -137,54 +126,48 @@ void b3CpuNarrowPhase::computeContacts(b3AlignedObjectArray<b3Int4>& pairs, b3Al
//printf("pairs[i].z=%d\n",pairs[i].z);
//int contactIndex = computeContactConvexConvex2(i,bodyIndexA,bodyIndexB,collidableIndexA,collidableIndexB,bodies,
// m_data->m_collidablesCPU,hostConvexData,hostVertices,hostUniqueEdges,hostIndices,hostFaces,hostContacts,nContacts,maxContactCapacity,oldHostContacts);
- int contactIndex = b3ContactConvexConvexSAT(i,bodyIndexA,bodyIndexB,collidableIndexA,collidableIndexB,bodies,
- m_data->m_collidablesCPU,m_data->m_convexPolyhedra,m_data->m_convexVertices,m_data->m_uniqueEdges,m_data->m_convexIndices,m_data->m_convexFaces,m_data->m_contacts,numContacts,maxContactCapacity);
-
+ int contactIndex = b3ContactConvexConvexSAT(i, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB, bodies,
+ m_data->m_collidablesCPU, m_data->m_convexPolyhedra, m_data->m_convexVertices, m_data->m_uniqueEdges, m_data->m_convexIndices, m_data->m_convexFaces, m_data->m_contacts, numContacts, maxContactCapacity);
- if (contactIndex>=0)
+ if (contactIndex >= 0)
{
pairs[i].z = contactIndex;
}
-// printf("plane-convex\n");
-
+ // printf("plane-convex\n");
}
-
-
}
m_data->m_contacts.resize(numContacts);
}
-int b3CpuNarrowPhase::registerConvexHullShape(b3ConvexUtility* utilPtr)
+int b3CpuNarrowPhase::registerConvexHullShape(b3ConvexUtility* utilPtr)
{
int collidableIndex = allocateCollidable();
- if (collidableIndex<0)
+ if (collidableIndex < 0)
return collidableIndex;
-
b3Collidable& col = m_data->m_collidablesCPU[collidableIndex];
col.m_shapeType = SHAPE_CONVEX_HULL;
col.m_shapeIndex = -1;
-
-
+
{
- b3Vector3 localCenter=b3MakeVector3(0,0,0);
- for (int i=0;i<utilPtr->m_vertices.size();i++)
- localCenter+=utilPtr->m_vertices[i];
- localCenter*= (1.f/utilPtr->m_vertices.size());
+ b3Vector3 localCenter = b3MakeVector3(0, 0, 0);
+ for (int i = 0; i < utilPtr->m_vertices.size(); i++)
+ localCenter += utilPtr->m_vertices[i];
+ localCenter *= (1.f / utilPtr->m_vertices.size());
utilPtr->m_localCenter = localCenter;
- col.m_shapeIndex = registerConvexHullShapeInternal(utilPtr,col);
+ col.m_shapeIndex = registerConvexHullShapeInternal(utilPtr, col);
}
- if (col.m_shapeIndex>=0)
+ if (col.m_shapeIndex >= 0)
{
b3Aabb aabb;
-
- b3Vector3 myAabbMin=b3MakeVector3(1e30f,1e30f,1e30f);
- b3Vector3 myAabbMax=b3MakeVector3(-1e30f,-1e30f,-1e30f);
- for (int i=0;i<utilPtr->m_vertices.size();i++)
+ b3Vector3 myAabbMin = b3MakeVector3(1e30f, 1e30f, 1e30f);
+ b3Vector3 myAabbMax = b3MakeVector3(-1e30f, -1e30f, -1e30f);
+
+ for (int i = 0; i < utilPtr->m_vertices.size(); i++)
{
myAabbMin.setMin(utilPtr->m_vertices[i]);
myAabbMax.setMax(utilPtr->m_vertices[i]);
@@ -200,44 +183,42 @@ int b3CpuNarrowPhase::registerConvexHullShape(b3ConvexUtility* utilPtr)
aabb.m_signedMaxIndices[3] = 0;
m_data->m_localShapeAABBCPU.push_back(aabb);
-
}
-
+
return collidableIndex;
}
-int b3CpuNarrowPhase::allocateCollidable()
+int b3CpuNarrowPhase::allocateCollidable()
{
int curSize = m_data->m_collidablesCPU.size();
- if (curSize<m_data->m_config.m_maxConvexShapes)
+ if (curSize < m_data->m_config.m_maxConvexShapes)
{
m_data->m_collidablesCPU.expand();
return curSize;
}
else
{
- b3Error("allocateCollidable out-of-range %d\n",m_data->m_config.m_maxConvexShapes);
+ b3Error("allocateCollidable out-of-range %d\n", m_data->m_config.m_maxConvexShapes);
}
return -1;
-
}
-int b3CpuNarrowPhase::registerConvexHullShape(const float* vertices, int strideInBytes, int numVertices, const float* scaling)
+int b3CpuNarrowPhase::registerConvexHullShape(const float* vertices, int strideInBytes, int numVertices, const float* scaling)
{
b3AlignedObjectArray<b3Vector3> verts;
- unsigned char* vts = (unsigned char*) vertices;
- for (int i=0;i<numVertices;i++)
+ unsigned char* vts = (unsigned char*)vertices;
+ for (int i = 0; i < numVertices; i++)
{
- float* vertex = (float*) &vts[i*strideInBytes];
- verts.push_back(b3MakeVector3(vertex[0]*scaling[0],vertex[1]*scaling[1],vertex[2]*scaling[2]));
+ float* vertex = (float*)&vts[i * strideInBytes];
+ verts.push_back(b3MakeVector3(vertex[0] * scaling[0], vertex[1] * scaling[1], vertex[2] * scaling[2]));
}
b3ConvexUtility* utilPtr = new b3ConvexUtility();
bool merge = true;
if (numVertices)
{
- utilPtr->initializePolyhedralFeatures(&verts[0],verts.size(),merge);
+ utilPtr->initializePolyhedralFeatures(&verts[0], verts.size(), merge);
}
int collidableIndex = registerConvexHullShape(utilPtr);
@@ -246,74 +227,67 @@ int b3CpuNarrowPhase::registerConvexHullShape(const float* vertices, int strideI
return collidableIndex;
}
-
-int b3CpuNarrowPhase::registerConvexHullShapeInternal(b3ConvexUtility* convexPtr,b3Collidable& col)
+int b3CpuNarrowPhase::registerConvexHullShapeInternal(b3ConvexUtility* convexPtr, b3Collidable& col)
{
+ m_data->m_convexData.resize(m_data->m_numAcceleratedShapes + 1);
+ m_data->m_convexPolyhedra.resize(m_data->m_numAcceleratedShapes + 1);
- m_data->m_convexData.resize(m_data->m_numAcceleratedShapes+1);
- m_data->m_convexPolyhedra.resize(m_data->m_numAcceleratedShapes+1);
-
-
- b3ConvexPolyhedronData& convex = m_data->m_convexPolyhedra.at(m_data->m_convexPolyhedra.size()-1);
+ b3ConvexPolyhedronData& convex = m_data->m_convexPolyhedra.at(m_data->m_convexPolyhedra.size() - 1);
convex.mC = convexPtr->mC;
convex.mE = convexPtr->mE;
- convex.m_extents= convexPtr->m_extents;
+ convex.m_extents = convexPtr->m_extents;
convex.m_localCenter = convexPtr->m_localCenter;
convex.m_radius = convexPtr->m_radius;
-
+
convex.m_numUniqueEdges = convexPtr->m_uniqueEdges.size();
int edgeOffset = m_data->m_uniqueEdges.size();
convex.m_uniqueEdgesOffset = edgeOffset;
-
- m_data->m_uniqueEdges.resize(edgeOffset+convex.m_numUniqueEdges);
-
+
+ m_data->m_uniqueEdges.resize(edgeOffset + convex.m_numUniqueEdges);
+
//convex data here
int i;
- for ( i=0;i<convexPtr->m_uniqueEdges.size();i++)
+ for (i = 0; i < convexPtr->m_uniqueEdges.size(); i++)
{
- m_data->m_uniqueEdges[edgeOffset+i] = convexPtr->m_uniqueEdges[i];
+ m_data->m_uniqueEdges[edgeOffset + i] = convexPtr->m_uniqueEdges[i];
}
-
+
int faceOffset = m_data->m_convexFaces.size();
convex.m_faceOffset = faceOffset;
convex.m_numFaces = convexPtr->m_faces.size();
- m_data->m_convexFaces.resize(faceOffset+convex.m_numFaces);
-
+ m_data->m_convexFaces.resize(faceOffset + convex.m_numFaces);
- for (i=0;i<convexPtr->m_faces.size();i++)
+ for (i = 0; i < convexPtr->m_faces.size(); i++)
{
- m_data->m_convexFaces[convex.m_faceOffset+i].m_plane = b3MakeVector3(convexPtr->m_faces[i].m_plane[0],
- convexPtr->m_faces[i].m_plane[1],
- convexPtr->m_faces[i].m_plane[2],
- convexPtr->m_faces[i].m_plane[3]);
+ m_data->m_convexFaces[convex.m_faceOffset + i].m_plane = b3MakeVector3(convexPtr->m_faces[i].m_plane[0],
+ convexPtr->m_faces[i].m_plane[1],
+ convexPtr->m_faces[i].m_plane[2],
+ convexPtr->m_faces[i].m_plane[3]);
-
int indexOffset = m_data->m_convexIndices.size();
int numIndices = convexPtr->m_faces[i].m_indices.size();
- m_data->m_convexFaces[convex.m_faceOffset+i].m_numIndices = numIndices;
- m_data->m_convexFaces[convex.m_faceOffset+i].m_indexOffset = indexOffset;
- m_data->m_convexIndices.resize(indexOffset+numIndices);
- for (int p=0;p<numIndices;p++)
+ m_data->m_convexFaces[convex.m_faceOffset + i].m_numIndices = numIndices;
+ m_data->m_convexFaces[convex.m_faceOffset + i].m_indexOffset = indexOffset;
+ m_data->m_convexIndices.resize(indexOffset + numIndices);
+ for (int p = 0; p < numIndices; p++)
{
- m_data->m_convexIndices[indexOffset+p] = convexPtr->m_faces[i].m_indices[p];
+ m_data->m_convexIndices[indexOffset + p] = convexPtr->m_faces[i].m_indices[p];
}
}
-
+
convex.m_numVertices = convexPtr->m_vertices.size();
int vertexOffset = m_data->m_convexVertices.size();
- convex.m_vertexOffset =vertexOffset;
-
- m_data->m_convexVertices.resize(vertexOffset+convex.m_numVertices);
- for (int i=0;i<convexPtr->m_vertices.size();i++)
+ convex.m_vertexOffset = vertexOffset;
+
+ m_data->m_convexVertices.resize(vertexOffset + convex.m_numVertices);
+ for (int i = 0; i < convexPtr->m_vertices.size(); i++)
{
- m_data->m_convexVertices[vertexOffset+i] = convexPtr->m_vertices[i];
+ m_data->m_convexVertices[vertexOffset + i] = convexPtr->m_vertices[i];
}
(m_data->m_convexData)[m_data->m_numAcceleratedShapes] = convexPtr;
-
-
-
+
return m_data->m_numAcceleratedShapes++;
}
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3CpuNarrowPhase.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3CpuNarrowPhase.h
index 528be3346d..f02353c265 100644
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3CpuNarrowPhase.h
+++ b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3CpuNarrowPhase.h
@@ -12,66 +12,55 @@
class b3CpuNarrowPhase
{
protected:
-
- struct b3CpuNarrowPhaseInternalData* m_data;
+ struct b3CpuNarrowPhaseInternalData* m_data;
int m_acceleratedCompanionShapeIndex;
int m_planeBodyIndex;
- int m_static0Index;
+ int m_static0Index;
- int registerConvexHullShapeInternal(class b3ConvexUtility* convexPtr,b3Collidable& col);
+ int registerConvexHullShapeInternal(class b3ConvexUtility* convexPtr, b3Collidable& col);
int registerConcaveMeshShape(b3AlignedObjectArray<b3Vector3>* vertices, b3AlignedObjectArray<int>* indices, b3Collidable& col, const float* scaling);
public:
-
-
-
-
b3CpuNarrowPhase(const struct b3Config& config);
virtual ~b3CpuNarrowPhase(void);
- int registerSphereShape(float radius);
- int registerPlaneShape(const b3Vector3& planeNormal, float planeConstant);
+ int registerSphereShape(float radius);
+ int registerPlaneShape(const b3Vector3& planeNormal, float planeConstant);
int registerCompoundShape(b3AlignedObjectArray<b3GpuChildShape>* childShapes);
int registerFace(const b3Vector3& faceNormal, float faceConstant);
-
- int registerConcaveMesh(b3AlignedObjectArray<b3Vector3>* vertices, b3AlignedObjectArray<int>* indices,const float* scaling);
-
+
+ int registerConcaveMesh(b3AlignedObjectArray<b3Vector3>* vertices, b3AlignedObjectArray<int>* indices, const float* scaling);
+
//do they need to be merged?
-
- int registerConvexHullShape(b3ConvexUtility* utilPtr);
- int registerConvexHullShape(const float* vertices, int strideInBytes, int numVertices, const float* scaling);
+
+ int registerConvexHullShape(b3ConvexUtility* utilPtr);
+ int registerConvexHullShape(const float* vertices, int strideInBytes, int numVertices, const float* scaling);
//int registerRigidBody(int collidableIndex, float mass, const float* position, const float* orientation, const float* aabbMin, const float* aabbMax,bool writeToGpu);
- void setObjectTransform(const float* position, const float* orientation , int bodyIndex);
+ void setObjectTransform(const float* position, const float* orientation, int bodyIndex);
- void writeAllBodiesToGpu();
- void reset();
- void readbackAllBodiesToCpu();
- bool getObjectTransformFromCpu(float* position, float* orientation , int bodyIndex) const;
+ void writeAllBodiesToGpu();
+ void reset();
+ void readbackAllBodiesToCpu();
+ bool getObjectTransformFromCpu(float* position, float* orientation, int bodyIndex) const;
- void setObjectTransformCpu(float* position, float* orientation , int bodyIndex);
+ void setObjectTransformCpu(float* position, float* orientation, int bodyIndex);
void setObjectVelocityCpu(float* linVel, float* angVel, int bodyIndex);
-
//virtual void computeContacts(cl_mem broadphasePairs, int numBroadphasePairs, cl_mem aabbsWorldSpace, int numObjects);
virtual void computeContacts(b3AlignedObjectArray<b3Int4>& pairs, b3AlignedObjectArray<b3Aabb>& aabbsWorldSpace, b3AlignedObjectArray<b3RigidBodyData>& bodies);
-
-
const struct b3RigidBodyData* getBodiesCpu() const;
//struct b3RigidBodyData* getBodiesCpu();
- int getNumBodiesGpu() const;
+ int getNumBodiesGpu() const;
-
- int getNumBodyInertiasGpu() const;
+ int getNumBodyInertiasGpu() const;
-
const struct b3Collidable* getCollidablesCpu() const;
- int getNumCollidablesGpu() const;
-
+ int getNumCollidablesGpu() const;
/*const struct b3Contact4* getContactsCPU() const;
@@ -80,8 +69,7 @@ public:
*/
const b3AlignedObjectArray<b3Contact4Data>& getContacts() const;
-
-
+
int getNumRigidBodies() const;
int allocateCollidable();
@@ -93,13 +81,12 @@ public:
b3Collidable& getCollidableCpu(int collidableIndex);
const b3Collidable& getCollidableCpu(int collidableIndex) const;
- const b3CpuNarrowPhaseInternalData* getInternalData() const
+ const b3CpuNarrowPhaseInternalData* getInternalData() const
{
- return m_data;
+ return m_data;
}
const struct b3Aabb& getLocalSpaceAabb(int collidableIndex) const;
};
-#endif //B3_CPU_NARROWPHASE_H
-
+#endif //B3_CPU_NARROWPHASE_H
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3RaycastInfo.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3RaycastInfo.h
index fba8bd07a4..b50c0eca4f 100644
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3RaycastInfo.h
+++ b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3RaycastInfo.h
@@ -4,21 +4,22 @@
#include "Bullet3Common/b3Vector3.h"
-B3_ATTRIBUTE_ALIGNED16(struct) b3RayInfo
+B3_ATTRIBUTE_ALIGNED16(struct)
+b3RayInfo
{
b3Vector3 m_from;
b3Vector3 m_to;
};
-B3_ATTRIBUTE_ALIGNED16(struct) b3RayHit
+B3_ATTRIBUTE_ALIGNED16(struct)
+b3RayHit
{
- b3Scalar m_hitFraction;
- int m_hitBody;
- int m_hitResult1;
- int m_hitResult2;
- b3Vector3 m_hitPoint;
- b3Vector3 m_hitNormal;
+ b3Scalar m_hitFraction;
+ int m_hitBody;
+ int m_hitResult1;
+ int m_hitResult2;
+ b3Vector3 m_hitPoint;
+ b3Vector3 m_hitNormal;
};
-#endif //B3_RAYCAST_INFO_H
-
+#endif //B3_RAYCAST_INFO_H
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3RigidBodyCL.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3RigidBodyCL.h
index d58f71802f..be1be57f05 100644
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3RigidBodyCL.h
+++ b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3RigidBodyCL.h
@@ -20,11 +20,9 @@ subject to the following restrictions:
#include "Bullet3Common/b3Matrix3x3.h"
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
-
-inline float b3GetInvMass(const b3RigidBodyData& body)
+inline float b3GetInvMass(const b3RigidBodyData& body)
{
- return body.m_invMass;
+ return body.m_invMass;
}
-
-#endif//B3_RIGID_BODY_CL
+#endif //B3_RIGID_BODY_CL
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3BvhSubtreeInfoData.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3BvhSubtreeInfoData.h
index 8788ccbb47..d6beb662b5 100644
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3BvhSubtreeInfoData.h
+++ b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3BvhSubtreeInfoData.h
@@ -7,14 +7,13 @@ typedef struct b3BvhSubtreeInfoData b3BvhSubtreeInfoData_t;
struct b3BvhSubtreeInfoData
{
//12 bytes
- unsigned short int m_quantizedAabbMin[3];
- unsigned short int m_quantizedAabbMax[3];
+ unsigned short int m_quantizedAabbMin[3];
+ unsigned short int m_quantizedAabbMax[3];
//4 bytes, points to the root of the subtree
- int m_rootNodeIndex;
+ int m_rootNodeIndex;
//4 bytes
- int m_subtreeSize;
- int m_padding[3];
+ int m_subtreeSize;
+ int m_padding[3];
};
-#endif //B3_BVH_SUBTREE_INFO_DATA_H
-
+#endif //B3_BVH_SUBTREE_INFO_DATA_H
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3BvhTraversal.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3BvhTraversal.h
index 2618da24bc..7c2507cc98 100644
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3BvhTraversal.h
+++ b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3BvhTraversal.h
@@ -7,69 +7,64 @@
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3BvhSubtreeInfoData.h"
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3QuantizedBvhNodeData.h"
-
-
// work-in-progress
-void b3BvhTraversal( __global const b3Int4* pairs,
- __global const b3RigidBodyData* rigidBodies,
- __global const b3Collidable* collidables,
- __global b3Aabb* aabbs,
- __global b3Int4* concavePairsOut,
- __global volatile int* numConcavePairsOut,
- __global const b3BvhSubtreeInfo* subtreeHeadersRoot,
- __global const b3QuantizedBvhNode* quantizedNodesRoot,
- __global const b3BvhInfo* bvhInfos,
- int numPairs,
- int maxNumConcavePairsCapacity,
- int id)
+void b3BvhTraversal(__global const b3Int4* pairs,
+ __global const b3RigidBodyData* rigidBodies,
+ __global const b3Collidable* collidables,
+ __global b3Aabb* aabbs,
+ __global b3Int4* concavePairsOut,
+ __global volatile int* numConcavePairsOut,
+ __global const b3BvhSubtreeInfo* subtreeHeadersRoot,
+ __global const b3QuantizedBvhNode* quantizedNodesRoot,
+ __global const b3BvhInfo* bvhInfos,
+ int numPairs,
+ int maxNumConcavePairsCapacity,
+ int id)
{
-
int bodyIndexA = pairs[id].x;
int bodyIndexB = pairs[id].y;
int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
-
+
//once the broadphase avoids static-static pairs, we can remove this test
- if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))
+ if ((rigidBodies[bodyIndexA].m_invMass == 0) && (rigidBodies[bodyIndexB].m_invMass == 0))
{
return;
}
-
- if (collidables[collidableIndexA].m_shapeType!=SHAPE_CONCAVE_TRIMESH)
+
+ if (collidables[collidableIndexA].m_shapeType != SHAPE_CONCAVE_TRIMESH)
return;
int shapeTypeB = collidables[collidableIndexB].m_shapeType;
-
- if (shapeTypeB!=SHAPE_CONVEX_HULL &&
- shapeTypeB!=SHAPE_SPHERE &&
- shapeTypeB!=SHAPE_COMPOUND_OF_CONVEX_HULLS
- )
+
+ if (shapeTypeB != SHAPE_CONVEX_HULL &&
+ shapeTypeB != SHAPE_SPHERE &&
+ shapeTypeB != SHAPE_COMPOUND_OF_CONVEX_HULLS)
return;
b3BvhInfo bvhInfo = bvhInfos[collidables[collidableIndexA].m_numChildShapes];
- b3Float4 bvhAabbMin = bvhInfo.m_aabbMin;
- b3Float4 bvhAabbMax = bvhInfo.m_aabbMax;
- b3Float4 bvhQuantization = bvhInfo.m_quantization;
+ b3Float4 bvhAabbMin = bvhInfo.m_aabbMin;
+ b3Float4 bvhAabbMax = bvhInfo.m_aabbMax;
+ b3Float4 bvhQuantization = bvhInfo.m_quantization;
int numSubtreeHeaders = bvhInfo.m_numSubTrees;
__global const b3BvhSubtreeInfoData* subtreeHeaders = &subtreeHeadersRoot[bvhInfo.m_subTreeOffset];
__global const b3QuantizedBvhNodeData* quantizedNodes = &quantizedNodesRoot[bvhInfo.m_nodeOffset];
-
unsigned short int quantizedQueryAabbMin[3];
unsigned short int quantizedQueryAabbMax[3];
- b3QuantizeWithClamp(quantizedQueryAabbMin,aabbs[bodyIndexB].m_minVec,false,bvhAabbMin, bvhAabbMax,bvhQuantization);
- b3QuantizeWithClamp(quantizedQueryAabbMax,aabbs[bodyIndexB].m_maxVec,true ,bvhAabbMin, bvhAabbMax,bvhQuantization);
-
- for (int i=0;i<numSubtreeHeaders;i++)
+ b3QuantizeWithClamp(quantizedQueryAabbMin, aabbs[bodyIndexB].m_minVec, false, bvhAabbMin, bvhAabbMax, bvhQuantization);
+ b3QuantizeWithClamp(quantizedQueryAabbMax, aabbs[bodyIndexB].m_maxVec, true, bvhAabbMin, bvhAabbMax, bvhQuantization);
+
+ for (int i = 0; i < numSubtreeHeaders; i++)
{
b3BvhSubtreeInfoData subtree = subtreeHeaders[i];
-
- int overlap = b3TestQuantizedAabbAgainstQuantizedAabbSlow(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax);
+
+ int overlap = b3TestQuantizedAabbAgainstQuantizedAabbSlow(quantizedQueryAabbMin, quantizedQueryAabbMax, subtree.m_quantizedAabbMin, subtree.m_quantizedAabbMax);
if (overlap != 0)
{
int startNodeIndex = subtree.m_rootNodeIndex;
- int endNodeIndex = subtree.m_rootNodeIndex+subtree.m_subtreeSize;
+ int endNodeIndex = subtree.m_rootNodeIndex + subtree.m_subtreeSize;
int curIndex = startNodeIndex;
int escapeIndex;
int isLeafNode;
@@ -77,43 +72,46 @@ void b3BvhTraversal( __global const b3Int4* pairs,
while (curIndex < endNodeIndex)
{
b3QuantizedBvhNodeData rootNode = quantizedNodes[curIndex];
- aabbOverlap = b3TestQuantizedAabbAgainstQuantizedAabbSlow(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode.m_quantizedAabbMin,rootNode.m_quantizedAabbMax);
+ aabbOverlap = b3TestQuantizedAabbAgainstQuantizedAabbSlow(quantizedQueryAabbMin, quantizedQueryAabbMax, rootNode.m_quantizedAabbMin, rootNode.m_quantizedAabbMax);
isLeafNode = b3IsLeaf(&rootNode);
if (aabbOverlap)
{
if (isLeafNode)
{
int triangleIndex = b3GetTriangleIndex(&rootNode);
- if (shapeTypeB==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+ if (shapeTypeB == SHAPE_COMPOUND_OF_CONVEX_HULLS)
{
- int numChildrenB = collidables[collidableIndexB].m_numChildShapes;
- int pairIdx = b3AtomicAdd (numConcavePairsOut,numChildrenB);
- for (int b=0;b<numChildrenB;b++)
+ int numChildrenB = collidables[collidableIndexB].m_numChildShapes;
+ int pairIdx = b3AtomicAdd(numConcavePairsOut, numChildrenB);
+ for (int b = 0; b < numChildrenB; b++)
+ {
+ if ((pairIdx + b) < maxNumConcavePairsCapacity)
{
- if ((pairIdx+b)<maxNumConcavePairsCapacity)
- {
- int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex+b;
- b3Int4 newPair = b3MakeInt4(bodyIndexA,bodyIndexB,triangleIndex,childShapeIndexB);
- concavePairsOut[pairIdx+b] = newPair;
- }
+ int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex + b;
+ b3Int4 newPair = b3MakeInt4(bodyIndexA, bodyIndexB, triangleIndex, childShapeIndexB);
+ concavePairsOut[pairIdx + b] = newPair;
}
- } else
+ }
+ }
+ else
{
int pairIdx = b3AtomicInc(numConcavePairsOut);
- if (pairIdx<maxNumConcavePairsCapacity)
+ if (pairIdx < maxNumConcavePairsCapacity)
{
- b3Int4 newPair = b3MakeInt4(bodyIndexA,bodyIndexB,triangleIndex,0);
+ b3Int4 newPair = b3MakeInt4(bodyIndexA, bodyIndexB, triangleIndex, 0);
concavePairsOut[pairIdx] = newPair;
}
}
- }
+ }
curIndex++;
- } else
+ }
+ else
{
if (isLeafNode)
{
curIndex++;
- } else
+ }
+ else
{
escapeIndex = b3GetEscapeIndex(&rootNode);
curIndex += escapeIndex;
@@ -122,5 +120,4 @@ void b3BvhTraversal( __global const b3Int4* pairs,
}
}
}
-
} \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ClipFaces.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ClipFaces.h
index 8009e7d6e0..0d9b13f1d6 100644
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ClipFaces.h
+++ b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ClipFaces.h
@@ -1,7 +1,6 @@
#ifndef B3_CLIP_FACES_H
#define B3_CLIP_FACES_H
-
#include "Bullet3Common/shared/b3Int4.h"
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
@@ -10,38 +9,36 @@
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3QuantizedBvhNodeData.h"
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
-
-inline b3Float4 b3Lerp3(b3Float4ConstArg a,b3Float4ConstArg b, float t)
+inline b3Float4 b3Lerp3(b3Float4ConstArg a, b3Float4ConstArg b, float t)
{
- return b3MakeFloat4( a.x + (b.x - a.x) * t,
+ return b3MakeFloat4(a.x + (b.x - a.x) * t,
a.y + (b.y - a.y) * t,
a.z + (b.z - a.z) * t,
0.f);
}
// Clips a face to the back of a plane, return the number of vertices out, stored in ppVtxOut
-int clipFaceGlobal(__global const b3Float4* pVtxIn, int numVertsIn, b3Float4ConstArg planeNormalWS,float planeEqWS, __global b3Float4* ppVtxOut)
+int clipFaceGlobal(__global const b3Float4* pVtxIn, int numVertsIn, b3Float4ConstArg planeNormalWS, float planeEqWS, __global b3Float4* ppVtxOut)
{
-
int ve;
float ds, de;
int numVertsOut = 0;
- //double-check next test
- // if (numVertsIn < 2)
- // return 0;
-
- b3Float4 firstVertex=pVtxIn[numVertsIn-1];
+ //double-check next test
+ // if (numVertsIn < 2)
+ // return 0;
+
+ b3Float4 firstVertex = pVtxIn[numVertsIn - 1];
b3Float4 endVertex = pVtxIn[0];
-
- ds = b3Dot(planeNormalWS,firstVertex)+planeEqWS;
-
+
+ ds = b3Dot(planeNormalWS, firstVertex) + planeEqWS;
+
for (ve = 0; ve < numVertsIn; ve++)
{
- endVertex=pVtxIn[ve];
- de = b3Dot(planeNormalWS,endVertex)+planeEqWS;
- if (ds<0)
+ endVertex = pVtxIn[ve];
+ de = b3Dot(planeNormalWS, endVertex) + planeEqWS;
+ if (ds < 0)
{
- if (de<0)
+ if (de < 0)
{
// Start < 0, end < 0, so output endVertex
ppVtxOut[numVertsOut++] = endVertex;
@@ -49,15 +46,15 @@ int clipFaceGlobal(__global const b3Float4* pVtxIn, int numVertsIn, b3Float4Cons
else
{
// Start < 0, end >= 0, so output intersection
- ppVtxOut[numVertsOut++] = b3Lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );
+ ppVtxOut[numVertsOut++] = b3Lerp3(firstVertex, endVertex, (ds * 1.f / (ds - de)));
}
}
else
{
- if (de<0)
+ if (de < 0)
{
// Start >= 0, end < 0 so output intersection and end
- ppVtxOut[numVertsOut++] = b3Lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );
+ ppVtxOut[numVertsOut++] = b3Lerp3(firstVertex, endVertex, (ds * 1.f / (ds - de)));
ppVtxOut[numVertsOut++] = endVertex;
}
}
@@ -67,90 +64,81 @@ int clipFaceGlobal(__global const b3Float4* pVtxIn, int numVertsIn, b3Float4Cons
return numVertsOut;
}
-
-__kernel void clipFacesAndFindContactsKernel( __global const b3Float4* separatingNormals,
- __global const int* hasSeparatingAxis,
- __global b3Int4* clippingFacesOut,
- __global b3Float4* worldVertsA1,
- __global b3Float4* worldNormalsA1,
- __global b3Float4* worldVertsB1,
- __global b3Float4* worldVertsB2,
- int vertexFaceCapacity,
- int pairIndex
- )
+__kernel void clipFacesAndFindContactsKernel(__global const b3Float4* separatingNormals,
+ __global const int* hasSeparatingAxis,
+ __global b3Int4* clippingFacesOut,
+ __global b3Float4* worldVertsA1,
+ __global b3Float4* worldNormalsA1,
+ __global b3Float4* worldVertsB1,
+ __global b3Float4* worldVertsB2,
+ int vertexFaceCapacity,
+ int pairIndex)
{
-// int i = get_global_id(0);
+ // int i = get_global_id(0);
//int pairIndex = i;
int i = pairIndex;
-
+
float minDist = -1e30f;
float maxDist = 0.02f;
-
-// if (i<numPairs)
+
+ // if (i<numPairs)
{
-
if (hasSeparatingAxis[i])
{
-
-// int bodyIndexA = pairs[i].x;
- // int bodyIndexB = pairs[i].y;
-
- int numLocalContactsOut = 0;
-
- int capacityWorldVertsB2 = vertexFaceCapacity;
-
- __global b3Float4* pVtxIn = &worldVertsB1[pairIndex*capacityWorldVertsB2];
- __global b3Float4* pVtxOut = &worldVertsB2[pairIndex*capacityWorldVertsB2];
-
-
- {
- __global b3Int4* clippingFaces = clippingFacesOut;
-
-
- int closestFaceA = clippingFaces[pairIndex].x;
- // int closestFaceB = clippingFaces[pairIndex].y;
- int numVertsInA = clippingFaces[pairIndex].z;
- int numVertsInB = clippingFaces[pairIndex].w;
-
- int numVertsOut = 0;
-
- if (closestFaceA>=0)
- {
-
-
-
- // clip polygon to back of planes of all faces of hull A that are adjacent to witness face
-
- for(int e0=0;e0<numVertsInA;e0++)
- {
- const b3Float4 aw = worldVertsA1[pairIndex*capacityWorldVertsB2+e0];
- const b3Float4 bw = worldVertsA1[pairIndex*capacityWorldVertsB2+((e0+1)%numVertsInA)];
- const b3Float4 WorldEdge0 = aw - bw;
- b3Float4 worldPlaneAnormal1 = worldNormalsA1[pairIndex];
- b3Float4 planeNormalWS1 = -b3Cross(WorldEdge0,worldPlaneAnormal1);
- b3Float4 worldA1 = aw;
- float planeEqWS1 = -b3Dot(worldA1,planeNormalWS1);
- b3Float4 planeNormalWS = planeNormalWS1;
- float planeEqWS=planeEqWS1;
- numVertsOut = clipFaceGlobal(pVtxIn, numVertsInB, planeNormalWS,planeEqWS, pVtxOut);
- __global b3Float4* tmp = pVtxOut;
- pVtxOut = pVtxIn;
- pVtxIn = tmp;
- numVertsInB = numVertsOut;
- numVertsOut = 0;
- }
-
- b3Float4 planeNormalWS = worldNormalsA1[pairIndex];
- float planeEqWS=-b3Dot(planeNormalWS,worldVertsA1[pairIndex*capacityWorldVertsB2]);
-
- for (int i=0;i<numVertsInB;i++)
- {
- float depth = b3Dot(planeNormalWS,pVtxIn[i])+planeEqWS;
- if (depth <=minDist)
- {
- depth = minDist;
- }
-/*
+ // int bodyIndexA = pairs[i].x;
+ // int bodyIndexB = pairs[i].y;
+
+ int numLocalContactsOut = 0;
+
+ int capacityWorldVertsB2 = vertexFaceCapacity;
+
+ __global b3Float4* pVtxIn = &worldVertsB1[pairIndex * capacityWorldVertsB2];
+ __global b3Float4* pVtxOut = &worldVertsB2[pairIndex * capacityWorldVertsB2];
+
+ {
+ __global b3Int4* clippingFaces = clippingFacesOut;
+
+ int closestFaceA = clippingFaces[pairIndex].x;
+ // int closestFaceB = clippingFaces[pairIndex].y;
+ int numVertsInA = clippingFaces[pairIndex].z;
+ int numVertsInB = clippingFaces[pairIndex].w;
+
+ int numVertsOut = 0;
+
+ if (closestFaceA >= 0)
+ {
+ // clip polygon to back of planes of all faces of hull A that are adjacent to witness face
+
+ for (int e0 = 0; e0 < numVertsInA; e0++)
+ {
+ const b3Float4 aw = worldVertsA1[pairIndex * capacityWorldVertsB2 + e0];
+ const b3Float4 bw = worldVertsA1[pairIndex * capacityWorldVertsB2 + ((e0 + 1) % numVertsInA)];
+ const b3Float4 WorldEdge0 = aw - bw;
+ b3Float4 worldPlaneAnormal1 = worldNormalsA1[pairIndex];
+ b3Float4 planeNormalWS1 = -b3Cross(WorldEdge0, worldPlaneAnormal1);
+ b3Float4 worldA1 = aw;
+ float planeEqWS1 = -b3Dot(worldA1, planeNormalWS1);
+ b3Float4 planeNormalWS = planeNormalWS1;
+ float planeEqWS = planeEqWS1;
+ numVertsOut = clipFaceGlobal(pVtxIn, numVertsInB, planeNormalWS, planeEqWS, pVtxOut);
+ __global b3Float4* tmp = pVtxOut;
+ pVtxOut = pVtxIn;
+ pVtxIn = tmp;
+ numVertsInB = numVertsOut;
+ numVertsOut = 0;
+ }
+
+ b3Float4 planeNormalWS = worldNormalsA1[pairIndex];
+ float planeEqWS = -b3Dot(planeNormalWS, worldVertsA1[pairIndex * capacityWorldVertsB2]);
+
+ for (int i = 0; i < numVertsInB; i++)
+ {
+ float depth = b3Dot(planeNormalWS, pVtxIn[i]) + planeEqWS;
+ if (depth <= minDist)
+ {
+ depth = minDist;
+ }
+ /*
static float maxDepth = 0.f;
if (depth < maxDepth)
{
@@ -163,26 +151,21 @@ __kernel void clipFacesAndFindContactsKernel( __global const b3Float4* sepa
}
*/
- if (depth <=maxDist)
- {
- b3Float4 pointInWorld = pVtxIn[i];
- pVtxOut[numLocalContactsOut++] = b3MakeFloat4(pointInWorld.x,pointInWorld.y,pointInWorld.z,depth);
- }
- }
-
- }
- clippingFaces[pairIndex].w =numLocalContactsOut;
-
-
- }
-
- for (int i=0;i<numLocalContactsOut;i++)
- pVtxIn[i] = pVtxOut[i];
-
- }// if (hasSeparatingAxis[i])
- }// if (i<numPairs)
-
-}
+ if (depth <= maxDist)
+ {
+ b3Float4 pointInWorld = pVtxIn[i];
+ pVtxOut[numLocalContactsOut++] = b3MakeFloat4(pointInWorld.x, pointInWorld.y, pointInWorld.z, depth);
+ }
+ }
+ }
+ clippingFaces[pairIndex].w = numLocalContactsOut;
+ }
+
+ for (int i = 0; i < numLocalContactsOut; i++)
+ pVtxIn[i] = pVtxOut[i];
-#endif //B3_CLIP_FACES_H
+ } // if (hasSeparatingAxis[i])
+ } // if (i<numPairs)
+}
+#endif //B3_CLIP_FACES_H
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h
index 77cdc7b7a9..9a8c668af2 100644
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h
+++ b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h
@@ -2,40 +2,36 @@
#ifndef B3_COLLIDABLE_H
#define B3_COLLIDABLE_H
-
#include "Bullet3Common/shared/b3Float4.h"
#include "Bullet3Common/shared/b3Quat.h"
enum b3ShapeTypes
{
- SHAPE_HEIGHT_FIELD=1,
+ SHAPE_HEIGHT_FIELD = 1,
- SHAPE_CONVEX_HULL=3,
- SHAPE_PLANE=4,
- SHAPE_CONCAVE_TRIMESH=5,
- SHAPE_COMPOUND_OF_CONVEX_HULLS=6,
- SHAPE_SPHERE=7,
+ SHAPE_CONVEX_HULL = 3,
+ SHAPE_PLANE = 4,
+ SHAPE_CONCAVE_TRIMESH = 5,
+ SHAPE_COMPOUND_OF_CONVEX_HULLS = 6,
+ SHAPE_SPHERE = 7,
MAX_NUM_SHAPE_TYPES,
};
typedef struct b3Collidable b3Collidable_t;
-
struct b3Collidable
{
union {
int m_numChildShapes;
int m_bvhIndex;
};
- union
- {
+ union {
float m_radius;
- int m_compoundBvhIndex;
+ int m_compoundBvhIndex;
};
int m_shapeType;
- union
- {
+ union {
int m_shapeIndex;
float m_height;
};
@@ -44,33 +40,30 @@ struct b3Collidable
typedef struct b3GpuChildShape b3GpuChildShape_t;
struct b3GpuChildShape
{
- b3Float4 m_childPosition;
- b3Quat m_childOrientation;
- union
- {
- int m_shapeIndex;//used for SHAPE_COMPOUND_OF_CONVEX_HULLS
- int m_capsuleAxis;
+ b3Float4 m_childPosition;
+ b3Quat m_childOrientation;
+ union {
+ int m_shapeIndex; //used for SHAPE_COMPOUND_OF_CONVEX_HULLS
+ int m_capsuleAxis;
};
- union
- {
- float m_radius;//used for childshape of SHAPE_COMPOUND_OF_SPHERES or SHAPE_COMPOUND_OF_CAPSULES
- int m_numChildShapes;//used for compound shape
+ union {
+ float m_radius; //used for childshape of SHAPE_COMPOUND_OF_SPHERES or SHAPE_COMPOUND_OF_CAPSULES
+ int m_numChildShapes; //used for compound shape
};
- union
- {
- float m_height;//used for childshape of SHAPE_COMPOUND_OF_CAPSULES
- int m_collidableShapeIndex;
+ union {
+ float m_height; //used for childshape of SHAPE_COMPOUND_OF_CAPSULES
+ int m_collidableShapeIndex;
};
- int m_shapeType;
+ int m_shapeType;
};
struct b3CompoundOverlappingPair
{
int m_bodyIndexA;
int m_bodyIndexB;
-// int m_pairType;
+ // int m_pairType;
int m_childShapeIndexA;
int m_childShapeIndexB;
};
-#endif //B3_COLLIDABLE_H
+#endif //B3_COLLIDABLE_H
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h
index dfd45cc566..d5f6daa993 100644
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h
+++ b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h
@@ -3,26 +3,24 @@
#include "Bullet3Common/shared/b3Float4.h"
-typedef struct b3Contact4Data b3Contact4Data_t;
+typedef struct b3Contact4Data b3Contact4Data_t;
struct b3Contact4Data
{
- b3Float4 m_worldPosB[4];
-// b3Float4 m_localPosA[4];
-// b3Float4 m_localPosB[4];
- b3Float4 m_worldNormalOnB; // w: m_nPoints
- unsigned short m_restituitionCoeffCmp;
- unsigned short m_frictionCoeffCmp;
+ b3Float4 m_worldPosB[4];
+ // b3Float4 m_localPosA[4];
+ // b3Float4 m_localPosB[4];
+ b3Float4 m_worldNormalOnB; // w: m_nPoints
+ unsigned short m_restituitionCoeffCmp;
+ unsigned short m_frictionCoeffCmp;
int m_batchIdx;
- int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr
+ int m_bodyAPtrAndSignBit; //x:m_bodyAPtr, y:m_bodyBPtr
int m_bodyBPtrAndSignBit;
- int m_childIndexA;
- int m_childIndexB;
+ int m_childIndexA;
+ int m_childIndexB;
int m_unused1;
int m_unused2;
-
-
};
inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)
@@ -35,6 +33,4 @@ inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numP
contact->m_worldNormalOnB.w = (float)numPoints;
};
-
-
-#endif //B3_CONTACT4DATA_H \ No newline at end of file
+#endif //B3_CONTACT4DATA_H \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ContactConvexConvexSAT.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ContactConvexConvexSAT.h
index f295f01a6c..ca68f4bc4e 100644
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ContactConvexConvexSAT.h
+++ b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ContactConvexConvexSAT.h
@@ -2,48 +2,43 @@
#ifndef B3_CONTACT_CONVEX_CONVEX_SAT_H
#define B3_CONTACT_CONVEX_CONVEX_SAT_H
-
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3FindSeparatingAxis.h"
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ReduceContacts.h"
#define B3_MAX_VERTS 1024
-
-
-inline b3Float4 b3Lerp3(const b3Float4& a,const b3Float4& b, float t)
+inline b3Float4 b3Lerp3(const b3Float4& a, const b3Float4& b, float t)
{
- return b3MakeVector3( a.x + (b.x - a.x) * t,
- a.y + (b.y - a.y) * t,
- a.z + (b.z - a.z) * t,
- 0.f);
+ return b3MakeVector3(a.x + (b.x - a.x) * t,
+ a.y + (b.y - a.y) * t,
+ a.z + (b.z - a.z) * t,
+ 0.f);
}
-
// Clips a face to the back of a plane, return the number of vertices out, stored in ppVtxOut
-inline int b3ClipFace(const b3Float4* pVtxIn, int numVertsIn, b3Float4& planeNormalWS,float planeEqWS, b3Float4* ppVtxOut)
+inline int b3ClipFace(const b3Float4* pVtxIn, int numVertsIn, b3Float4& planeNormalWS, float planeEqWS, b3Float4* ppVtxOut)
{
-
int ve;
float ds, de;
int numVertsOut = 0;
if (numVertsIn < 2)
return 0;
- b3Float4 firstVertex=pVtxIn[numVertsIn-1];
+ b3Float4 firstVertex = pVtxIn[numVertsIn - 1];
b3Float4 endVertex = pVtxIn[0];
-
- ds = b3Dot3F4(planeNormalWS,firstVertex)+planeEqWS;
+
+ ds = b3Dot3F4(planeNormalWS, firstVertex) + planeEqWS;
for (ve = 0; ve < numVertsIn; ve++)
{
- endVertex=pVtxIn[ve];
+ endVertex = pVtxIn[ve];
- de = b3Dot3F4(planeNormalWS,endVertex)+planeEqWS;
+ de = b3Dot3F4(planeNormalWS, endVertex) + planeEqWS;
- if (ds<0)
+ if (ds < 0)
{
- if (de<0)
+ if (de < 0)
{
// Start < 0, end < 0, so output endVertex
ppVtxOut[numVertsOut++] = endVertex;
@@ -51,15 +46,15 @@ inline int b3ClipFace(const b3Float4* pVtxIn, int numVertsIn, b3Float4& planeNor
else
{
// Start < 0, end >= 0, so output intersection
- ppVtxOut[numVertsOut++] = b3Lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );
+ ppVtxOut[numVertsOut++] = b3Lerp3(firstVertex, endVertex, (ds * 1.f / (ds - de)));
}
}
else
{
- if (de<0)
+ if (de < 0)
{
// Start >= 0, end < 0 so output intersection and end
- ppVtxOut[numVertsOut++] = b3Lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );
+ ppVtxOut[numVertsOut++] = b3Lerp3(firstVertex, endVertex, (ds * 1.f / (ds - de)));
ppVtxOut[numVertsOut++] = endVertex;
}
}
@@ -69,36 +64,35 @@ inline int b3ClipFace(const b3Float4* pVtxIn, int numVertsIn, b3Float4& planeNor
return numVertsOut;
}
-
-inline int b3ClipFaceAgainstHull(const b3Float4& separatingNormal, const b3ConvexPolyhedronData* hullA,
- const b3Float4& posA, const b3Quaternion& ornA, b3Float4* worldVertsB1, int numWorldVertsB1,
- b3Float4* worldVertsB2, int capacityWorldVertsB2,
- const float minDist, float maxDist,
- const b3AlignedObjectArray<b3Float4>& verticesA, const b3AlignedObjectArray<b3GpuFace>& facesA, const b3AlignedObjectArray<int>& indicesA,
- //const b3Float4* verticesB, const b3GpuFace* facesB, const int* indicesB,
- b3Float4* contactsOut,
- int contactCapacity)
+inline int b3ClipFaceAgainstHull(const b3Float4& separatingNormal, const b3ConvexPolyhedronData* hullA,
+ const b3Float4& posA, const b3Quaternion& ornA, b3Float4* worldVertsB1, int numWorldVertsB1,
+ b3Float4* worldVertsB2, int capacityWorldVertsB2,
+ const float minDist, float maxDist,
+ const b3AlignedObjectArray<b3Float4>& verticesA, const b3AlignedObjectArray<b3GpuFace>& facesA, const b3AlignedObjectArray<int>& indicesA,
+ //const b3Float4* verticesB, const b3GpuFace* facesB, const int* indicesB,
+ b3Float4* contactsOut,
+ int contactCapacity)
{
int numContactsOut = 0;
b3Float4* pVtxIn = worldVertsB1;
b3Float4* pVtxOut = worldVertsB2;
-
+
int numVertsIn = numWorldVertsB1;
int numVertsOut = 0;
- int closestFaceA=-1;
+ int closestFaceA = -1;
{
float dmin = FLT_MAX;
- for(int face=0;face<hullA->m_numFaces;face++)
+ for (int face = 0; face < hullA->m_numFaces; face++)
{
const b3Float4 Normal = b3MakeVector3(
- facesA[hullA->m_faceOffset+face].m_plane.x,
- facesA[hullA->m_faceOffset+face].m_plane.y,
- facesA[hullA->m_faceOffset+face].m_plane.z,0.f);
- const b3Float4 faceANormalWS = b3QuatRotate(ornA,Normal);
-
- float d = b3Dot3F4(faceANormalWS,separatingNormal);
+ facesA[hullA->m_faceOffset + face].m_plane.x,
+ facesA[hullA->m_faceOffset + face].m_plane.y,
+ facesA[hullA->m_faceOffset + face].m_plane.z, 0.f);
+ const b3Float4 faceANormalWS = b3QuatRotate(ornA, Normal);
+
+ float d = b3Dot3F4(faceANormalWS, separatingNormal);
if (d < dmin)
{
dmin = d;
@@ -106,33 +100,33 @@ inline int b3ClipFaceAgainstHull(const b3Float4& separatingNormal, const b3Conve
}
}
}
- if (closestFaceA<0)
+ if (closestFaceA < 0)
return numContactsOut;
- b3GpuFace polyA = facesA[hullA->m_faceOffset+closestFaceA];
+ b3GpuFace polyA = facesA[hullA->m_faceOffset + closestFaceA];
// clip polygon to back of planes of all faces of hull A that are adjacent to witness face
//int numContacts = numWorldVertsB1;
int numVerticesA = polyA.m_numIndices;
- for(int e0=0;e0<numVerticesA;e0++)
+ for (int e0 = 0; e0 < numVerticesA; e0++)
{
- const b3Float4 a = verticesA[hullA->m_vertexOffset+indicesA[polyA.m_indexOffset+e0]];
- const b3Float4 b = verticesA[hullA->m_vertexOffset+indicesA[polyA.m_indexOffset+((e0+1)%numVerticesA)]];
+ const b3Float4 a = verticesA[hullA->m_vertexOffset + indicesA[polyA.m_indexOffset + e0]];
+ const b3Float4 b = verticesA[hullA->m_vertexOffset + indicesA[polyA.m_indexOffset + ((e0 + 1) % numVerticesA)]];
const b3Float4 edge0 = a - b;
- const b3Float4 WorldEdge0 = b3QuatRotate(ornA,edge0);
- b3Float4 planeNormalA = b3MakeFloat4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);
- b3Float4 worldPlaneAnormal1 = b3QuatRotate(ornA,planeNormalA);
-
- b3Float4 planeNormalWS1 = -b3Cross3(WorldEdge0,worldPlaneAnormal1);
- b3Float4 worldA1 = b3TransformPoint(a,posA,ornA);
- float planeEqWS1 = -b3Dot3F4(worldA1,planeNormalWS1);
-
+ const b3Float4 WorldEdge0 = b3QuatRotate(ornA, edge0);
+ b3Float4 planeNormalA = b3MakeFloat4(polyA.m_plane.x, polyA.m_plane.y, polyA.m_plane.z, 0.f);
+ b3Float4 worldPlaneAnormal1 = b3QuatRotate(ornA, planeNormalA);
+
+ b3Float4 planeNormalWS1 = -b3Cross3(WorldEdge0, worldPlaneAnormal1);
+ b3Float4 worldA1 = b3TransformPoint(a, posA, ornA);
+ float planeEqWS1 = -b3Dot3F4(worldA1, planeNormalWS1);
+
b3Float4 planeNormalWS = planeNormalWS1;
- float planeEqWS=planeEqWS1;
-
+ float planeEqWS = planeEqWS1;
+
//clip face
//clipFace(*pVtxIn, *pVtxOut,planeNormalWS,planeEqWS);
- numVertsOut = b3ClipFace(pVtxIn, numVertsIn, planeNormalWS,planeEqWS, pVtxOut);
+ numVertsOut = b3ClipFace(pVtxIn, numVertsIn, planeNormalWS, planeEqWS, pVtxOut);
//btSwap(pVtxIn,pVtxOut);
b3Float4* tmp = pVtxOut;
@@ -142,32 +136,32 @@ inline int b3ClipFaceAgainstHull(const b3Float4& separatingNormal, const b3Conve
numVertsOut = 0;
}
-
// only keep points that are behind the witness face
{
- b3Float4 localPlaneNormal = b3MakeFloat4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);
+ b3Float4 localPlaneNormal = b3MakeFloat4(polyA.m_plane.x, polyA.m_plane.y, polyA.m_plane.z, 0.f);
float localPlaneEq = polyA.m_plane.w;
- b3Float4 planeNormalWS = b3QuatRotate(ornA,localPlaneNormal);
- float planeEqWS=localPlaneEq-b3Dot3F4(planeNormalWS,posA);
- for (int i=0;i<numVertsIn;i++)
+ b3Float4 planeNormalWS = b3QuatRotate(ornA, localPlaneNormal);
+ float planeEqWS = localPlaneEq - b3Dot3F4(planeNormalWS, posA);
+ for (int i = 0; i < numVertsIn; i++)
{
- float depth = b3Dot3F4(planeNormalWS,pVtxIn[i])+planeEqWS;
- if (depth <=minDist)
+ float depth = b3Dot3F4(planeNormalWS, pVtxIn[i]) + planeEqWS;
+ if (depth <= minDist)
{
depth = minDist;
}
- if (numContactsOut<contactCapacity)
+ if (numContactsOut < contactCapacity)
{
- if (depth <=maxDist)
+ if (depth <= maxDist)
{
b3Float4 pointInWorld = pVtxIn[i];
//resultOut.addContactPoint(separatingNormal,point,depth);
- contactsOut[numContactsOut++] = b3MakeVector3(pointInWorld.x,pointInWorld.y,pointInWorld.z,depth);
+ contactsOut[numContactsOut++] = b3MakeVector3(pointInWorld.x, pointInWorld.y, pointInWorld.z, depth);
//printf("depth=%f\n",depth);
}
- } else
+ }
+ else
{
- b3Error("exceeding contact capacity (%d,%df)\n", numContactsOut,contactCapacity);
+ b3Error("exceeding contact capacity (%d,%df)\n", numContactsOut, contactCapacity);
}
}
}
@@ -175,62 +169,60 @@ inline int b3ClipFaceAgainstHull(const b3Float4& separatingNormal, const b3Conve
return numContactsOut;
}
+inline int b3ClipHullAgainstHull(const b3Float4& separatingNormal,
+ const b3ConvexPolyhedronData& hullA, const b3ConvexPolyhedronData& hullB,
+ const b3Float4& posA, const b3Quaternion& ornA, const b3Float4& posB, const b3Quaternion& ornB,
+ b3Float4* worldVertsB1, b3Float4* worldVertsB2, int capacityWorldVerts,
+ const float minDist, float maxDist,
+ const b3AlignedObjectArray<b3Float4>& verticesA, const b3AlignedObjectArray<b3GpuFace>& facesA, const b3AlignedObjectArray<int>& indicesA,
+ const b3AlignedObjectArray<b3Float4>& verticesB, const b3AlignedObjectArray<b3GpuFace>& facesB, const b3AlignedObjectArray<int>& indicesB,
-
-inline int b3ClipHullAgainstHull(const b3Float4& separatingNormal,
- const b3ConvexPolyhedronData& hullA, const b3ConvexPolyhedronData& hullB,
- const b3Float4& posA, const b3Quaternion& ornA,const b3Float4& posB, const b3Quaternion& ornB,
- b3Float4* worldVertsB1, b3Float4* worldVertsB2, int capacityWorldVerts,
- const float minDist, float maxDist,
- const b3AlignedObjectArray<b3Float4>& verticesA, const b3AlignedObjectArray<b3GpuFace>& facesA, const b3AlignedObjectArray<int>& indicesA,
- const b3AlignedObjectArray<b3Float4>& verticesB, const b3AlignedObjectArray<b3GpuFace>& facesB, const b3AlignedObjectArray<int>& indicesB,
-
- b3Float4* contactsOut,
- int contactCapacity)
+ b3Float4* contactsOut,
+ int contactCapacity)
{
int numContactsOut = 0;
- int numWorldVertsB1= 0;
-
+ int numWorldVertsB1 = 0;
+
B3_PROFILE("clipHullAgainstHull");
//float curMaxDist=maxDist;
- int closestFaceB=-1;
+ int closestFaceB = -1;
float dmax = -FLT_MAX;
{
//B3_PROFILE("closestFaceB");
- if (hullB.m_numFaces!=1)
+ if (hullB.m_numFaces != 1)
{
//printf("wtf\n");
}
static bool once = true;
//printf("separatingNormal=%f,%f,%f\n",separatingNormal.x,separatingNormal.y,separatingNormal.z);
-
- for(int face=0;face<hullB.m_numFaces;face++)
+
+ for (int face = 0; face < hullB.m_numFaces; face++)
{
#ifdef BT_DEBUG_SAT_FACE
if (once)
- printf("face %d\n",face);
- const b3GpuFace* faceB = &facesB[hullB.m_faceOffset+face];
+ printf("face %d\n", face);
+ const b3GpuFace* faceB = &facesB[hullB.m_faceOffset + face];
if (once)
{
- for (int i=0;i<faceB->m_numIndices;i++)
+ for (int i = 0; i < faceB->m_numIndices; i++)
{
- b3Float4 vert = verticesB[hullB.m_vertexOffset+indicesB[faceB->m_indexOffset+i]];
- printf("vert[%d] = %f,%f,%f\n",i,vert.x,vert.y,vert.z);
+ b3Float4 vert = verticesB[hullB.m_vertexOffset + indicesB[faceB->m_indexOffset + i]];
+ printf("vert[%d] = %f,%f,%f\n", i, vert.x, vert.y, vert.z);
}
}
-#endif //BT_DEBUG_SAT_FACE
- //if (facesB[hullB.m_faceOffset+face].m_numIndices>2)
+#endif //BT_DEBUG_SAT_FACE \
+ //if (facesB[hullB.m_faceOffset+face].m_numIndices>2)
{
- const b3Float4 Normal = b3MakeVector3(facesB[hullB.m_faceOffset+face].m_plane.x,
- facesB[hullB.m_faceOffset+face].m_plane.y, facesB[hullB.m_faceOffset+face].m_plane.z,0.f);
+ const b3Float4 Normal = b3MakeVector3(facesB[hullB.m_faceOffset + face].m_plane.x,
+ facesB[hullB.m_faceOffset + face].m_plane.y, facesB[hullB.m_faceOffset + face].m_plane.z, 0.f);
const b3Float4 WorldNormal = b3QuatRotate(ornB, Normal);
#ifdef BT_DEBUG_SAT_FACE
if (once)
- printf("faceNormal = %f,%f,%f\n",Normal.x,Normal.y,Normal.z);
+ printf("faceNormal = %f,%f,%f\n", Normal.x, Normal.y, Normal.z);
#endif
- float d = b3Dot3F4(WorldNormal,separatingNormal);
+ float d = b3Dot3F4(WorldNormal, separatingNormal);
if (d > dmax)
{
dmax = d;
@@ -241,79 +233,73 @@ inline int b3ClipHullAgainstHull(const b3Float4& separatingNormal,
once = false;
}
-
- b3Assert(closestFaceB>=0);
+ b3Assert(closestFaceB >= 0);
{
//B3_PROFILE("worldVertsB1");
- const b3GpuFace& polyB = facesB[hullB.m_faceOffset+closestFaceB];
+ const b3GpuFace& polyB = facesB[hullB.m_faceOffset + closestFaceB];
const int numVertices = polyB.m_numIndices;
- for(int e0=0;e0<numVertices;e0++)
+ for (int e0 = 0; e0 < numVertices; e0++)
{
- const b3Float4& b = verticesB[hullB.m_vertexOffset+indicesB[polyB.m_indexOffset+e0]];
- worldVertsB1[numWorldVertsB1++] = b3TransformPoint(b,posB,ornB);
+ const b3Float4& b = verticesB[hullB.m_vertexOffset + indicesB[polyB.m_indexOffset + e0]];
+ worldVertsB1[numWorldVertsB1++] = b3TransformPoint(b, posB, ornB);
}
}
- if (closestFaceB>=0)
+ if (closestFaceB >= 0)
{
//B3_PROFILE("clipFaceAgainstHull");
- numContactsOut = b3ClipFaceAgainstHull((b3Float4&)separatingNormal, &hullA,
- posA,ornA,
- worldVertsB1,numWorldVertsB1,worldVertsB2,capacityWorldVerts, minDist, maxDist,
- verticesA, facesA, indicesA,
- contactsOut,contactCapacity);
+ numContactsOut = b3ClipFaceAgainstHull((b3Float4&)separatingNormal, &hullA,
+ posA, ornA,
+ worldVertsB1, numWorldVertsB1, worldVertsB2, capacityWorldVerts, minDist, maxDist,
+ verticesA, facesA, indicesA,
+ contactsOut, contactCapacity);
}
return numContactsOut;
}
-
-
-
inline int b3ClipHullHullSingle(
- int bodyIndexA, int bodyIndexB,
- const b3Float4& posA,
- const b3Quaternion& ornA,
- const b3Float4& posB,
- const b3Quaternion& ornB,
-
- int collidableIndexA, int collidableIndexB,
-
- const b3AlignedObjectArray<b3RigidBodyData>* bodyBuf,
- b3AlignedObjectArray<b3Contact4Data>* globalContactOut,
- int& nContacts,
-
- const b3AlignedObjectArray<b3ConvexPolyhedronData>& hostConvexDataA,
- const b3AlignedObjectArray<b3ConvexPolyhedronData>& hostConvexDataB,
-
- const b3AlignedObjectArray<b3Vector3>& verticesA,
- const b3AlignedObjectArray<b3Vector3>& uniqueEdgesA,
- const b3AlignedObjectArray<b3GpuFace>& facesA,
- const b3AlignedObjectArray<int>& indicesA,
-
- const b3AlignedObjectArray<b3Vector3>& verticesB,
- const b3AlignedObjectArray<b3Vector3>& uniqueEdgesB,
- const b3AlignedObjectArray<b3GpuFace>& facesB,
- const b3AlignedObjectArray<int>& indicesB,
-
- const b3AlignedObjectArray<b3Collidable>& hostCollidablesA,
- const b3AlignedObjectArray<b3Collidable>& hostCollidablesB,
- const b3Vector3& sepNormalWorldSpace,
- int maxContactCapacity )
+ int bodyIndexA, int bodyIndexB,
+ const b3Float4& posA,
+ const b3Quaternion& ornA,
+ const b3Float4& posB,
+ const b3Quaternion& ornB,
+
+ int collidableIndexA, int collidableIndexB,
+
+ const b3AlignedObjectArray<b3RigidBodyData>* bodyBuf,
+ b3AlignedObjectArray<b3Contact4Data>* globalContactOut,
+ int& nContacts,
+
+ const b3AlignedObjectArray<b3ConvexPolyhedronData>& hostConvexDataA,
+ const b3AlignedObjectArray<b3ConvexPolyhedronData>& hostConvexDataB,
+
+ const b3AlignedObjectArray<b3Vector3>& verticesA,
+ const b3AlignedObjectArray<b3Vector3>& uniqueEdgesA,
+ const b3AlignedObjectArray<b3GpuFace>& facesA,
+ const b3AlignedObjectArray<int>& indicesA,
+
+ const b3AlignedObjectArray<b3Vector3>& verticesB,
+ const b3AlignedObjectArray<b3Vector3>& uniqueEdgesB,
+ const b3AlignedObjectArray<b3GpuFace>& facesB,
+ const b3AlignedObjectArray<int>& indicesB,
+
+ const b3AlignedObjectArray<b3Collidable>& hostCollidablesA,
+ const b3AlignedObjectArray<b3Collidable>& hostCollidablesB,
+ const b3Vector3& sepNormalWorldSpace,
+ int maxContactCapacity)
{
int contactIndex = -1;
b3ConvexPolyhedronData hullA, hullB;
-
- b3Collidable colA = hostCollidablesA[collidableIndexA];
- hullA = hostConvexDataA[colA.m_shapeIndex];
- //printf("numvertsA = %d\n",hullA.m_numVertices);
-
-
- b3Collidable colB = hostCollidablesB[collidableIndexB];
- hullB = hostConvexDataB[colB.m_shapeIndex];
- //printf("numvertsB = %d\n",hullB.m_numVertices);
-
-
+
+ b3Collidable colA = hostCollidablesA[collidableIndexA];
+ hullA = hostConvexDataA[colA.m_shapeIndex];
+ //printf("numvertsA = %d\n",hullA.m_numVertices);
+
+ b3Collidable colB = hostCollidablesB[collidableIndexB];
+ hullB = hostConvexDataB[colB.m_shapeIndex];
+ //printf("numvertsB = %d\n",hullB.m_numVertices);
+
b3Float4 contactsOut[B3_MAX_VERTS];
int localContactCapacity = B3_MAX_VERTS;
@@ -321,187 +307,168 @@ inline int b3ClipHullHullSingle(
b3Assert(_finite(bodyBuf->at(bodyIndexA).m_pos.x));
b3Assert(_finite(bodyBuf->at(bodyIndexB).m_pos.x));
#endif
-
-
+
{
-
b3Float4 worldVertsB1[B3_MAX_VERTS];
b3Float4 worldVertsB2[B3_MAX_VERTS];
int capacityWorldVerts = B3_MAX_VERTS;
- b3Float4 hostNormal = b3MakeFloat4(sepNormalWorldSpace.x,sepNormalWorldSpace.y,sepNormalWorldSpace.z,0.f);
+ b3Float4 hostNormal = b3MakeFloat4(sepNormalWorldSpace.x, sepNormalWorldSpace.y, sepNormalWorldSpace.z, 0.f);
int shapeA = hostCollidablesA[collidableIndexA].m_shapeIndex;
int shapeB = hostCollidablesB[collidableIndexB].m_shapeIndex;
b3Scalar minDist = -1;
b3Scalar maxDist = 0.;
-
-
- b3Transform trA,trB;
+ b3Transform trA, trB;
{
- //B3_PROFILE("b3TransformPoint computation");
- //trA.setIdentity();
- trA.setOrigin(b3MakeVector3(posA.x,posA.y,posA.z));
- trA.setRotation(b3Quaternion(ornA.x,ornA.y,ornA.z,ornA.w));
-
- //trB.setIdentity();
- trB.setOrigin(b3MakeVector3(posB.x,posB.y,posB.z));
- trB.setRotation(b3Quaternion(ornB.x,ornB.y,ornB.z,ornB.w));
+ //B3_PROFILE("b3TransformPoint computation");
+ //trA.setIdentity();
+ trA.setOrigin(b3MakeVector3(posA.x, posA.y, posA.z));
+ trA.setRotation(b3Quaternion(ornA.x, ornA.y, ornA.z, ornA.w));
+
+ //trB.setIdentity();
+ trB.setOrigin(b3MakeVector3(posB.x, posB.y, posB.z));
+ trB.setRotation(b3Quaternion(ornB.x, ornB.y, ornB.z, ornB.w));
}
b3Quaternion trAorn = trA.getRotation();
- b3Quaternion trBorn = trB.getRotation();
-
- int numContactsOut = b3ClipHullAgainstHull(hostNormal,
- hostConvexDataA.at(shapeA),
- hostConvexDataB.at(shapeB),
- (b3Float4&)trA.getOrigin(), (b3Quaternion&)trAorn,
- (b3Float4&)trB.getOrigin(), (b3Quaternion&)trBorn,
- worldVertsB1,worldVertsB2,capacityWorldVerts,
- minDist, maxDist,
- verticesA, facesA,indicesA,
- verticesB, facesB,indicesB,
-
- contactsOut,localContactCapacity);
-
- if (numContactsOut>0)
+ b3Quaternion trBorn = trB.getRotation();
+
+ int numContactsOut = b3ClipHullAgainstHull(hostNormal,
+ hostConvexDataA.at(shapeA),
+ hostConvexDataB.at(shapeB),
+ (b3Float4&)trA.getOrigin(), (b3Quaternion&)trAorn,
+ (b3Float4&)trB.getOrigin(), (b3Quaternion&)trBorn,
+ worldVertsB1, worldVertsB2, capacityWorldVerts,
+ minDist, maxDist,
+ verticesA, facesA, indicesA,
+ verticesB, facesB, indicesB,
+
+ contactsOut, localContactCapacity);
+
+ if (numContactsOut > 0)
{
B3_PROFILE("overlap");
b3Float4 normalOnSurfaceB = (b3Float4&)hostNormal;
-// b3Float4 centerOut;
-
+ // b3Float4 centerOut;
+
b3Int4 contactIdx;
contactIdx.x = 0;
contactIdx.y = 1;
contactIdx.z = 2;
contactIdx.w = 3;
-
+
int numPoints = 0;
-
+
{
B3_PROFILE("extractManifold");
- numPoints = b3ReduceContacts(contactsOut, numContactsOut, normalOnSurfaceB, &contactIdx);
+ numPoints = b3ReduceContacts(contactsOut, numContactsOut, normalOnSurfaceB, &contactIdx);
}
-
+
b3Assert(numPoints);
-
- if (nContacts<maxContactCapacity)
+
+ if (nContacts < maxContactCapacity)
{
contactIndex = nContacts;
globalContactOut->expand();
b3Contact4Data& contact = globalContactOut->at(nContacts);
- contact.m_batchIdx = 0;//i;
- contact.m_bodyAPtrAndSignBit = (bodyBuf->at(bodyIndexA).m_invMass==0)? -bodyIndexA:bodyIndexA;
- contact.m_bodyBPtrAndSignBit = (bodyBuf->at(bodyIndexB).m_invMass==0)? -bodyIndexB:bodyIndexB;
+ contact.m_batchIdx = 0; //i;
+ contact.m_bodyAPtrAndSignBit = (bodyBuf->at(bodyIndexA).m_invMass == 0) ? -bodyIndexA : bodyIndexA;
+ contact.m_bodyBPtrAndSignBit = (bodyBuf->at(bodyIndexB).m_invMass == 0) ? -bodyIndexB : bodyIndexB;
contact.m_frictionCoeffCmp = 45874;
contact.m_restituitionCoeffCmp = 0;
-
- // float distance = 0.f;
- for (int p=0;p<numPoints;p++)
+
+ // float distance = 0.f;
+ for (int p = 0; p < numPoints; p++)
{
- contact.m_worldPosB[p] = contactsOut[contactIdx.s[p]];//check if it is actually on B
- contact.m_worldNormalOnB = normalOnSurfaceB;
+ contact.m_worldPosB[p] = contactsOut[contactIdx.s[p]]; //check if it is actually on B
+ contact.m_worldNormalOnB = normalOnSurfaceB;
}
//printf("bodyIndexA %d,bodyIndexB %d,normal=%f,%f,%f numPoints %d\n",bodyIndexA,bodyIndexB,normalOnSurfaceB.x,normalOnSurfaceB.y,normalOnSurfaceB.z,numPoints);
contact.m_worldNormalOnB.w = (b3Scalar)numPoints;
nContacts++;
- } else
+ }
+ else
{
- b3Error("Error: exceeding contact capacity (%d/%d)\n", nContacts,maxContactCapacity);
+ b3Error("Error: exceeding contact capacity (%d/%d)\n", nContacts, maxContactCapacity);
}
}
}
return contactIndex;
}
-
-
-
-
inline int b3ContactConvexConvexSAT(
- int pairIndex,
- int bodyIndexA, int bodyIndexB,
- int collidableIndexA, int collidableIndexB,
- const b3AlignedObjectArray<b3RigidBodyData>& rigidBodies,
- const b3AlignedObjectArray<b3Collidable>& collidables,
- const b3AlignedObjectArray<b3ConvexPolyhedronData>& convexShapes,
- const b3AlignedObjectArray<b3Float4>& convexVertices,
- const b3AlignedObjectArray<b3Float4>& uniqueEdges,
- const b3AlignedObjectArray<int>& convexIndices,
- const b3AlignedObjectArray<b3GpuFace>& faces,
- b3AlignedObjectArray<b3Contact4Data>& globalContactsOut,
- int& nGlobalContactsOut,
- int maxContactCapacity)
+ int pairIndex,
+ int bodyIndexA, int bodyIndexB,
+ int collidableIndexA, int collidableIndexB,
+ const b3AlignedObjectArray<b3RigidBodyData>& rigidBodies,
+ const b3AlignedObjectArray<b3Collidable>& collidables,
+ const b3AlignedObjectArray<b3ConvexPolyhedronData>& convexShapes,
+ const b3AlignedObjectArray<b3Float4>& convexVertices,
+ const b3AlignedObjectArray<b3Float4>& uniqueEdges,
+ const b3AlignedObjectArray<int>& convexIndices,
+ const b3AlignedObjectArray<b3GpuFace>& faces,
+ b3AlignedObjectArray<b3Contact4Data>& globalContactsOut,
+ int& nGlobalContactsOut,
+ int maxContactCapacity)
{
int contactIndex = -1;
-
b3Float4 posA = rigidBodies[bodyIndexA].m_pos;
b3Quaternion ornA = rigidBodies[bodyIndexA].m_quat;
b3Float4 posB = rigidBodies[bodyIndexB].m_pos;
b3Quaternion ornB = rigidBodies[bodyIndexB].m_quat;
-
b3ConvexPolyhedronData hullA, hullB;
-
- b3Float4 sepNormalWorldSpace;
-
+ b3Float4 sepNormalWorldSpace;
- b3Collidable colA = collidables[collidableIndexA];
- hullA = convexShapes[colA.m_shapeIndex];
- //printf("numvertsA = %d\n",hullA.m_numVertices);
-
-
- b3Collidable colB = collidables[collidableIndexB];
- hullB = convexShapes[colB.m_shapeIndex];
- //printf("numvertsB = %d\n",hullB.m_numVertices);
-
-
+ b3Collidable colA = collidables[collidableIndexA];
+ hullA = convexShapes[colA.m_shapeIndex];
+ //printf("numvertsA = %d\n",hullA.m_numVertices);
+ b3Collidable colB = collidables[collidableIndexB];
+ hullB = convexShapes[colB.m_shapeIndex];
+ //printf("numvertsB = %d\n",hullB.m_numVertices);
#ifdef _WIN32
b3Assert(_finite(rigidBodies[bodyIndexA].m_pos.x));
b3Assert(_finite(rigidBodies[bodyIndexB].m_pos.x));
#endif
-
- bool foundSepAxis = b3FindSeparatingAxis(hullA,hullB,
- posA,
- ornA,
- posB,
- ornB,
-
- convexVertices,uniqueEdges,faces,convexIndices,
- convexVertices,uniqueEdges,faces,convexIndices,
-
- sepNormalWorldSpace
- );
-
-
+
+ bool foundSepAxis = b3FindSeparatingAxis(hullA, hullB,
+ posA,
+ ornA,
+ posB,
+ ornB,
+
+ convexVertices, uniqueEdges, faces, convexIndices,
+ convexVertices, uniqueEdges, faces, convexIndices,
+
+ sepNormalWorldSpace);
+
if (foundSepAxis)
{
-
-
contactIndex = b3ClipHullHullSingle(
bodyIndexA, bodyIndexB,
- posA,ornA,
- posB,ornB,
+ posA, ornA,
+ posB, ornB,
collidableIndexA, collidableIndexB,
- &rigidBodies,
+ &rigidBodies,
&globalContactsOut,
nGlobalContactsOut,
-
+
convexShapes,
convexShapes,
-
- convexVertices,
- uniqueEdges,
+
+ convexVertices,
+ uniqueEdges,
faces,
convexIndices,
-
+
convexVertices,
uniqueEdges,
faces,
@@ -511,10 +478,9 @@ inline int b3ContactConvexConvexSAT(
collidables,
sepNormalWorldSpace,
maxContactCapacity);
-
}
return contactIndex;
}
-#endif //B3_CONTACT_CONVEX_CONVEX_SAT_H
+#endif //B3_CONTACT_CONVEX_CONVEX_SAT_H
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ContactSphereSphere.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ContactSphereSphere.h
index a3fa82287b..acf7c1b180 100644
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ContactSphereSphere.h
+++ b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ContactSphereSphere.h
@@ -2,32 +2,24 @@
#ifndef B3_CONTACT_SPHERE_SPHERE_H
#define B3_CONTACT_SPHERE_SPHERE_H
-
-
-
-
-void computeContactSphereConvex(int pairIndex,
- int bodyIndexA, int bodyIndexB,
- int collidableIndexA, int collidableIndexB,
- const b3RigidBodyData* rigidBodies,
- const b3Collidable* collidables,
- const b3ConvexPolyhedronData* convexShapes,
- const b3Vector3* convexVertices,
- const int* convexIndices,
- const b3GpuFace* faces,
- b3Contact4* globalContactsOut,
- int& nGlobalContactsOut,
- int maxContactCapacity)
+void computeContactSphereConvex(int pairIndex,
+ int bodyIndexA, int bodyIndexB,
+ int collidableIndexA, int collidableIndexB,
+ const b3RigidBodyData* rigidBodies,
+ const b3Collidable* collidables,
+ const b3ConvexPolyhedronData* convexShapes,
+ const b3Vector3* convexVertices,
+ const int* convexIndices,
+ const b3GpuFace* faces,
+ b3Contact4* globalContactsOut,
+ int& nGlobalContactsOut,
+ int maxContactCapacity)
{
-
float radius = collidables[collidableIndexA].m_radius;
float4 spherePos1 = rigidBodies[bodyIndexA].m_pos;
b3Quaternion sphereOrn = rigidBodies[bodyIndexA].m_quat;
-
-
float4 pos = rigidBodies[bodyIndexB].m_pos;
-
b3Quaternion quat = rigidBodies[bodyIndexB].m_quat;
@@ -44,63 +36,64 @@ void computeContactSphereConvex(int pairIndex,
int numFaces = convexShapes[shapeIndex].m_numFaces;
float4 closestPnt = b3MakeVector3(0, 0, 0, 0);
float4 hitNormalWorld = b3MakeVector3(0, 0, 0, 0);
- float minDist = -1000000.f; // TODO: What is the largest/smallest float?
+ float minDist = -1000000.f; // TODO: What is the largest/smallest float?
bool bCollide = true;
int region = -1;
float4 localHitNormal;
- for ( int f = 0; f < numFaces; f++ )
+ for (int f = 0; f < numFaces; f++)
{
- b3GpuFace face = faces[convexShapes[shapeIndex].m_faceOffset+f];
+ b3GpuFace face = faces[convexShapes[shapeIndex].m_faceOffset + f];
float4 planeEqn;
- float4 localPlaneNormal = b3MakeVector3(face.m_plane.x,face.m_plane.y,face.m_plane.z,0.f);
- float4 n1 = localPlaneNormal;//quatRotate(quat,localPlaneNormal);
+ float4 localPlaneNormal = b3MakeVector3(face.m_plane.x, face.m_plane.y, face.m_plane.z, 0.f);
+ float4 n1 = localPlaneNormal; //quatRotate(quat,localPlaneNormal);
planeEqn = n1;
planeEqn[3] = face.m_plane.w;
float4 pntReturn;
float dist = signedDistanceFromPointToPlane(spherePos, planeEqn, &pntReturn);
- if ( dist > radius)
+ if (dist > radius)
{
bCollide = false;
break;
}
- if ( dist > 0 )
+ if (dist > 0)
{
//might hit an edge or vertex
b3Vector3 out;
bool isInPoly = IsPointInPolygon(spherePos,
- &face,
- &convexVertices[convexShapes[shapeIndex].m_vertexOffset],
- convexIndices,
- &out);
+ &face,
+ &convexVertices[convexShapes[shapeIndex].m_vertexOffset],
+ convexIndices,
+ &out);
if (isInPoly)
{
- if (dist>minDist)
+ if (dist > minDist)
{
minDist = dist;
closestPnt = pntReturn;
localHitNormal = planeEqn;
- region=1;
+ region = 1;
}
- } else
+ }
+ else
{
- b3Vector3 tmp = spherePos-out;
+ b3Vector3 tmp = spherePos - out;
b3Scalar l2 = tmp.length2();
- if (l2<radius*radius)
+ if (l2 < radius * radius)
{
- dist = b3Sqrt(l2);
- if (dist>minDist)
+ dist = b3Sqrt(l2);
+ if (dist > minDist)
{
minDist = dist;
closestPnt = out;
- localHitNormal = tmp/dist;
- region=2;
+ localHitNormal = tmp / dist;
+ region = 2;
}
-
- } else
+ }
+ else
{
bCollide = false;
break;
@@ -109,12 +102,12 @@ void computeContactSphereConvex(int pairIndex,
}
else
{
- if ( dist > minDist )
+ if (dist > minDist)
{
minDist = dist;
closestPnt = pntReturn;
localHitNormal = planeEqn;
- region=3;
+ region = 3;
}
}
}
@@ -123,40 +116,38 @@ void computeContactSphereConvex(int pairIndex,
if (bCollide && minDist > -10000)
{
-
- float4 normalOnSurfaceB1 = tr.getBasis()*localHitNormal;//-hitNormalWorld;
+ float4 normalOnSurfaceB1 = tr.getBasis() * localHitNormal; //-hitNormalWorld;
float4 pOnB1 = tr(closestPnt);
//printf("dist ,%f,",minDist);
- float actualDepth = minDist-radius;
- if (actualDepth<0)
- {
- //printf("actualDepth = ,%f,", actualDepth);
- //printf("normalOnSurfaceB1 = ,%f,%f,%f,", normalOnSurfaceB1.x,normalOnSurfaceB1.y,normalOnSurfaceB1.z);
- //printf("region=,%d,\n", region);
- pOnB1[3] = actualDepth;
-
- int dstIdx;
-// dstIdx = nGlobalContactsOut++;//AppendInc( nGlobalContactsOut, dstIdx );
-
- if (nGlobalContactsOut < maxContactCapacity)
+ float actualDepth = minDist - radius;
+ if (actualDepth < 0)
{
- dstIdx=nGlobalContactsOut;
- nGlobalContactsOut++;
-
- b3Contact4* c = &globalContactsOut[dstIdx];
- c->m_worldNormalOnB = normalOnSurfaceB1;
- c->setFrictionCoeff(0.7);
- c->setRestituitionCoeff(0.f);
-
- c->m_batchIdx = pairIndex;
- c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;
- c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;
- c->m_worldPosB[0] = pOnB1;
- int numPoints = 1;
- c->m_worldNormalOnB.w = (b3Scalar)numPoints;
- }//if (dstIdx < numPairs)
+ //printf("actualDepth = ,%f,", actualDepth);
+ //printf("normalOnSurfaceB1 = ,%f,%f,%f,", normalOnSurfaceB1.x,normalOnSurfaceB1.y,normalOnSurfaceB1.z);
+ //printf("region=,%d,\n", region);
+ pOnB1[3] = actualDepth;
+
+ int dstIdx;
+ // dstIdx = nGlobalContactsOut++;//AppendInc( nGlobalContactsOut, dstIdx );
+
+ if (nGlobalContactsOut < maxContactCapacity)
+ {
+ dstIdx = nGlobalContactsOut;
+ nGlobalContactsOut++;
+
+ b3Contact4* c = &globalContactsOut[dstIdx];
+ c->m_worldNormalOnB = normalOnSurfaceB1;
+ c->setFrictionCoeff(0.7);
+ c->setRestituitionCoeff(0.f);
+
+ c->m_batchIdx = pairIndex;
+ c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass == 0 ? -bodyIndexA : bodyIndexA;
+ c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass == 0 ? -bodyIndexB : bodyIndexB;
+ c->m_worldPosB[0] = pOnB1;
+ int numPoints = 1;
+ c->m_worldNormalOnB.w = (b3Scalar)numPoints;
+ } //if (dstIdx < numPairs)
}
- }//if (hasCollision)
-
+ } //if (hasCollision)
}
-#endif //B3_CONTACT_SPHERE_SPHERE_H
+#endif //B3_CONTACT_SPHERE_SPHERE_H
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h
index 5c5f4e297f..d5a73bd4f5 100644
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h
+++ b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h
@@ -2,8 +2,6 @@
#ifndef B3_CONVEX_POLYHEDRON_DATA_H
#define B3_CONVEX_POLYHEDRON_DATA_H
-
-
#include "Bullet3Common/shared/b3Float4.h"
#include "Bullet3Common/shared/b3Quat.h"
@@ -21,20 +19,20 @@ typedef struct b3ConvexPolyhedronData b3ConvexPolyhedronData_t;
struct b3ConvexPolyhedronData
{
- b3Float4 m_localCenter;
- b3Float4 m_extents;
- b3Float4 mC;
- b3Float4 mE;
+ b3Float4 m_localCenter;
+ b3Float4 m_extents;
+ b3Float4 mC;
+ b3Float4 mE;
- float m_radius;
- int m_faceOffset;
+ float m_radius;
+ int m_faceOffset;
int m_numFaces;
- int m_numVertices;
+ int m_numVertices;
int m_vertexOffset;
- int m_uniqueEdgesOffset;
- int m_numUniqueEdges;
+ int m_uniqueEdgesOffset;
+ int m_numUniqueEdges;
int m_unused;
};
-#endif //B3_CONVEX_POLYHEDRON_DATA_H
+#endif //B3_CONVEX_POLYHEDRON_DATA_H
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3FindConcaveSatAxis.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3FindConcaveSatAxis.h
index 89993f3565..983554eb2e 100644
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3FindConcaveSatAxis.h
+++ b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3FindConcaveSatAxis.h
@@ -3,7 +3,6 @@
#define B3_TRIANGLE_NUM_CONVEX_FACES 5
-
#include "Bullet3Common/shared/b3Int4.h"
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
@@ -12,25 +11,24 @@
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3QuantizedBvhNodeData.h"
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
-
-inline void b3Project(__global const b3ConvexPolyhedronData* hull, b3Float4ConstArg pos, b3QuatConstArg orn,
-const b3Float4* dir, __global const b3Float4* vertices, float* min, float* max)
+inline void b3Project(__global const b3ConvexPolyhedronData* hull, b3Float4ConstArg pos, b3QuatConstArg orn,
+ const b3Float4* dir, __global const b3Float4* vertices, float* min, float* max)
{
min[0] = FLT_MAX;
max[0] = -FLT_MAX;
int numVerts = hull->m_numVertices;
- const b3Float4 localDir = b3QuatRotate(b3QuatInverse(orn),*dir);
- float offset = b3Dot(pos,*dir);
- for(int i=0;i<numVerts;i++)
+ const b3Float4 localDir = b3QuatRotate(b3QuatInverse(orn), *dir);
+ float offset = b3Dot(pos, *dir);
+ for (int i = 0; i < numVerts; i++)
{
- float dp = b3Dot(vertices[hull->m_vertexOffset+i],localDir);
- if(dp < min[0])
+ float dp = b3Dot(vertices[hull->m_vertexOffset + i], localDir);
+ if (dp < min[0])
min[0] = dp;
- if(dp > max[0])
+ if (dp > max[0])
max[0] = dp;
}
- if(min[0]>max[0])
+ if (min[0] > max[0])
{
float tmp = min[0];
min[0] = max[0];
@@ -40,53 +38,49 @@ const b3Float4* dir, __global const b3Float4* vertices, float* min, float* max)
max[0] += offset;
}
-
-inline bool b3TestSepAxis(const b3ConvexPolyhedronData* hullA, __global const b3ConvexPolyhedronData* hullB,
- b3Float4ConstArg posA,b3QuatConstArg ornA,
- b3Float4ConstArg posB,b3QuatConstArg ornB,
- b3Float4* sep_axis, const b3Float4* verticesA, __global const b3Float4* verticesB,float* depth)
+inline bool b3TestSepAxis(const b3ConvexPolyhedronData* hullA, __global const b3ConvexPolyhedronData* hullB,
+ b3Float4ConstArg posA, b3QuatConstArg ornA,
+ b3Float4ConstArg posB, b3QuatConstArg ornB,
+ b3Float4* sep_axis, const b3Float4* verticesA, __global const b3Float4* verticesB, float* depth)
{
- float Min0,Max0;
- float Min1,Max1;
- b3Project(hullA,posA,ornA,sep_axis,verticesA, &Min0, &Max0);
- b3Project(hullB,posB,ornB, sep_axis,verticesB, &Min1, &Max1);
+ float Min0, Max0;
+ float Min1, Max1;
+ b3Project(hullA, posA, ornA, sep_axis, verticesA, &Min0, &Max0);
+ b3Project(hullB, posB, ornB, sep_axis, verticesB, &Min1, &Max1);
- if(Max0<Min1 || Max1<Min0)
+ if (Max0 < Min1 || Max1 < Min0)
return false;
float d0 = Max0 - Min1;
float d1 = Max1 - Min0;
- *depth = d0<d1 ? d0:d1;
+ *depth = d0 < d1 ? d0 : d1;
return true;
}
-
-bool b3FindSeparatingAxis( const b3ConvexPolyhedronData* hullA, __global const b3ConvexPolyhedronData* hullB,
- b3Float4ConstArg posA1,
- b3QuatConstArg ornA,
- b3Float4ConstArg posB1,
- b3QuatConstArg ornB,
- b3Float4ConstArg DeltaC2,
-
- const b3Float4* verticesA,
- const b3Float4* uniqueEdgesA,
- const b3GpuFace* facesA,
- const int* indicesA,
-
- __global const b3Float4* verticesB,
- __global const b3Float4* uniqueEdgesB,
- __global const b3GpuFace* facesB,
- __global const int* indicesB,
- b3Float4* sep,
- float* dmin)
+bool b3FindSeparatingAxis(const b3ConvexPolyhedronData* hullA, __global const b3ConvexPolyhedronData* hullB,
+ b3Float4ConstArg posA1,
+ b3QuatConstArg ornA,
+ b3Float4ConstArg posB1,
+ b3QuatConstArg ornB,
+ b3Float4ConstArg DeltaC2,
+
+ const b3Float4* verticesA,
+ const b3Float4* uniqueEdgesA,
+ const b3GpuFace* facesA,
+ const int* indicesA,
+
+ __global const b3Float4* verticesB,
+ __global const b3Float4* uniqueEdgesB,
+ __global const b3GpuFace* facesB,
+ __global const int* indicesB,
+ b3Float4* sep,
+ float* dmin)
{
-
-
b3Float4 posA = posA1;
posA.w = 0.f;
b3Float4 posB = posB1;
posB.w = 0.f;
-/*
+ /*
static int maxFaceVertex = 0;
int curFaceVertexAB = hullA->m_numFaces*hullB->m_numVertices;
@@ -102,300 +96,289 @@ bool b3FindSeparatingAxis( const b3ConvexPolyhedronData* hullA, __global const b
}
*/
- int curPlaneTests=0;
+ int curPlaneTests = 0;
{
int numFacesA = hullA->m_numFaces;
// Test normals from hullA
- for(int i=0;i<numFacesA;i++)
+ for (int i = 0; i < numFacesA; i++)
{
- const b3Float4 normal = facesA[hullA->m_faceOffset+i].m_plane;
- b3Float4 faceANormalWS = b3QuatRotate(ornA,normal);
- if (b3Dot(DeltaC2,faceANormalWS)<0)
- faceANormalWS*=-1.f;
+ const b3Float4 normal = facesA[hullA->m_faceOffset + i].m_plane;
+ b3Float4 faceANormalWS = b3QuatRotate(ornA, normal);
+ if (b3Dot(DeltaC2, faceANormalWS) < 0)
+ faceANormalWS *= -1.f;
curPlaneTests++;
float d;
- if(!b3TestSepAxis( hullA, hullB, posA,ornA,posB,ornB,&faceANormalWS, verticesA, verticesB,&d))
+ if (!b3TestSepAxis(hullA, hullB, posA, ornA, posB, ornB, &faceANormalWS, verticesA, verticesB, &d))
return false;
- if(d<*dmin)
+ if (d < *dmin)
{
*dmin = d;
*sep = faceANormalWS;
}
}
}
- if((b3Dot(-DeltaC2,*sep))>0.0f)
+ if ((b3Dot(-DeltaC2, *sep)) > 0.0f)
{
*sep = -(*sep);
}
return true;
}
-
-b3Vector3 unitSphere162[]=
-{
- b3MakeVector3(0.000000,-1.000000,0.000000),
-b3MakeVector3(0.203181,-0.967950,0.147618),
-b3MakeVector3(-0.077607,-0.967950,0.238853),
-b3MakeVector3(0.723607,-0.447220,0.525725),
-b3MakeVector3(0.609547,-0.657519,0.442856),
-b3MakeVector3(0.812729,-0.502301,0.295238),
-b3MakeVector3(-0.251147,-0.967949,0.000000),
-b3MakeVector3(-0.077607,-0.967950,-0.238853),
-b3MakeVector3(0.203181,-0.967950,-0.147618),
-b3MakeVector3(0.860698,-0.251151,0.442858),
-b3MakeVector3(-0.276388,-0.447220,0.850649),
-b3MakeVector3(-0.029639,-0.502302,0.864184),
-b3MakeVector3(-0.155215,-0.251152,0.955422),
-b3MakeVector3(-0.894426,-0.447216,0.000000),
-b3MakeVector3(-0.831051,-0.502299,0.238853),
-b3MakeVector3(-0.956626,-0.251149,0.147618),
-b3MakeVector3(-0.276388,-0.447220,-0.850649),
-b3MakeVector3(-0.483971,-0.502302,-0.716565),
-b3MakeVector3(-0.436007,-0.251152,-0.864188),
-b3MakeVector3(0.723607,-0.447220,-0.525725),
-b3MakeVector3(0.531941,-0.502302,-0.681712),
-b3MakeVector3(0.687159,-0.251152,-0.681715),
-b3MakeVector3(0.687159,-0.251152,0.681715),
-b3MakeVector3(-0.436007,-0.251152,0.864188),
-b3MakeVector3(-0.956626,-0.251149,-0.147618),
-b3MakeVector3(-0.155215,-0.251152,-0.955422),
-b3MakeVector3(0.860698,-0.251151,-0.442858),
-b3MakeVector3(0.276388,0.447220,0.850649),
-b3MakeVector3(0.483971,0.502302,0.716565),
-b3MakeVector3(0.232822,0.657519,0.716563),
-b3MakeVector3(-0.723607,0.447220,0.525725),
-b3MakeVector3(-0.531941,0.502302,0.681712),
-b3MakeVector3(-0.609547,0.657519,0.442856),
-b3MakeVector3(-0.723607,0.447220,-0.525725),
-b3MakeVector3(-0.812729,0.502301,-0.295238),
-b3MakeVector3(-0.609547,0.657519,-0.442856),
-b3MakeVector3(0.276388,0.447220,-0.850649),
-b3MakeVector3(0.029639,0.502302,-0.864184),
-b3MakeVector3(0.232822,0.657519,-0.716563),
-b3MakeVector3(0.894426,0.447216,0.000000),
-b3MakeVector3(0.831051,0.502299,-0.238853),
-b3MakeVector3(0.753442,0.657515,0.000000),
-b3MakeVector3(-0.232822,-0.657519,0.716563),
-b3MakeVector3(-0.162456,-0.850654,0.499995),
-b3MakeVector3(0.052790,-0.723612,0.688185),
-b3MakeVector3(0.138199,-0.894429,0.425321),
-b3MakeVector3(0.262869,-0.525738,0.809012),
-b3MakeVector3(0.361805,-0.723611,0.587779),
-b3MakeVector3(0.531941,-0.502302,0.681712),
-b3MakeVector3(0.425323,-0.850654,0.309011),
-b3MakeVector3(0.812729,-0.502301,-0.295238),
-b3MakeVector3(0.609547,-0.657519,-0.442856),
-b3MakeVector3(0.850648,-0.525736,0.000000),
-b3MakeVector3(0.670817,-0.723611,-0.162457),
-b3MakeVector3(0.670817,-0.723610,0.162458),
-b3MakeVector3(0.425323,-0.850654,-0.309011),
-b3MakeVector3(0.447211,-0.894428,0.000001),
-b3MakeVector3(-0.753442,-0.657515,0.000000),
-b3MakeVector3(-0.525730,-0.850652,0.000000),
-b3MakeVector3(-0.638195,-0.723609,0.262864),
-b3MakeVector3(-0.361801,-0.894428,0.262864),
-b3MakeVector3(-0.688189,-0.525736,0.499997),
-b3MakeVector3(-0.447211,-0.723610,0.525729),
-b3MakeVector3(-0.483971,-0.502302,0.716565),
-b3MakeVector3(-0.232822,-0.657519,-0.716563),
-b3MakeVector3(-0.162456,-0.850654,-0.499995),
-b3MakeVector3(-0.447211,-0.723611,-0.525727),
-b3MakeVector3(-0.361801,-0.894429,-0.262863),
-b3MakeVector3(-0.688189,-0.525736,-0.499997),
-b3MakeVector3(-0.638195,-0.723609,-0.262863),
-b3MakeVector3(-0.831051,-0.502299,-0.238853),
-b3MakeVector3(0.361804,-0.723612,-0.587779),
-b3MakeVector3(0.138197,-0.894429,-0.425321),
-b3MakeVector3(0.262869,-0.525738,-0.809012),
-b3MakeVector3(0.052789,-0.723611,-0.688186),
-b3MakeVector3(-0.029639,-0.502302,-0.864184),
-b3MakeVector3(0.956626,0.251149,0.147618),
-b3MakeVector3(0.956626,0.251149,-0.147618),
-b3MakeVector3(0.951058,-0.000000,0.309013),
-b3MakeVector3(1.000000,0.000000,0.000000),
-b3MakeVector3(0.947213,-0.276396,0.162458),
-b3MakeVector3(0.951058,0.000000,-0.309013),
-b3MakeVector3(0.947213,-0.276396,-0.162458),
-b3MakeVector3(0.155215,0.251152,0.955422),
-b3MakeVector3(0.436007,0.251152,0.864188),
-b3MakeVector3(-0.000000,-0.000000,1.000000),
-b3MakeVector3(0.309017,0.000000,0.951056),
-b3MakeVector3(0.138199,-0.276398,0.951055),
-b3MakeVector3(0.587786,0.000000,0.809017),
-b3MakeVector3(0.447216,-0.276398,0.850648),
-b3MakeVector3(-0.860698,0.251151,0.442858),
-b3MakeVector3(-0.687159,0.251152,0.681715),
-b3MakeVector3(-0.951058,-0.000000,0.309013),
-b3MakeVector3(-0.809018,0.000000,0.587783),
-b3MakeVector3(-0.861803,-0.276396,0.425324),
-b3MakeVector3(-0.587786,0.000000,0.809017),
-b3MakeVector3(-0.670819,-0.276397,0.688191),
-b3MakeVector3(-0.687159,0.251152,-0.681715),
-b3MakeVector3(-0.860698,0.251151,-0.442858),
-b3MakeVector3(-0.587786,-0.000000,-0.809017),
-b3MakeVector3(-0.809018,-0.000000,-0.587783),
-b3MakeVector3(-0.670819,-0.276397,-0.688191),
-b3MakeVector3(-0.951058,0.000000,-0.309013),
-b3MakeVector3(-0.861803,-0.276396,-0.425324),
-b3MakeVector3(0.436007,0.251152,-0.864188),
-b3MakeVector3(0.155215,0.251152,-0.955422),
-b3MakeVector3(0.587786,-0.000000,-0.809017),
-b3MakeVector3(0.309017,-0.000000,-0.951056),
-b3MakeVector3(0.447216,-0.276398,-0.850648),
-b3MakeVector3(0.000000,0.000000,-1.000000),
-b3MakeVector3(0.138199,-0.276398,-0.951055),
-b3MakeVector3(0.670820,0.276396,0.688190),
-b3MakeVector3(0.809019,-0.000002,0.587783),
-b3MakeVector3(0.688189,0.525736,0.499997),
-b3MakeVector3(0.861804,0.276394,0.425323),
-b3MakeVector3(0.831051,0.502299,0.238853),
-b3MakeVector3(-0.447216,0.276397,0.850649),
-b3MakeVector3(-0.309017,-0.000001,0.951056),
-b3MakeVector3(-0.262869,0.525738,0.809012),
-b3MakeVector3(-0.138199,0.276397,0.951055),
-b3MakeVector3(0.029639,0.502302,0.864184),
-b3MakeVector3(-0.947213,0.276396,-0.162458),
-b3MakeVector3(-1.000000,0.000001,0.000000),
-b3MakeVector3(-0.850648,0.525736,-0.000000),
-b3MakeVector3(-0.947213,0.276397,0.162458),
-b3MakeVector3(-0.812729,0.502301,0.295238),
-b3MakeVector3(-0.138199,0.276397,-0.951055),
-b3MakeVector3(-0.309016,-0.000000,-0.951057),
-b3MakeVector3(-0.262869,0.525738,-0.809012),
-b3MakeVector3(-0.447215,0.276397,-0.850649),
-b3MakeVector3(-0.531941,0.502302,-0.681712),
-b3MakeVector3(0.861804,0.276396,-0.425322),
-b3MakeVector3(0.809019,0.000000,-0.587782),
-b3MakeVector3(0.688189,0.525736,-0.499997),
-b3MakeVector3(0.670821,0.276397,-0.688189),
-b3MakeVector3(0.483971,0.502302,-0.716565),
-b3MakeVector3(0.077607,0.967950,0.238853),
-b3MakeVector3(0.251147,0.967949,0.000000),
-b3MakeVector3(0.000000,1.000000,0.000000),
-b3MakeVector3(0.162456,0.850654,0.499995),
-b3MakeVector3(0.361800,0.894429,0.262863),
-b3MakeVector3(0.447209,0.723612,0.525728),
-b3MakeVector3(0.525730,0.850652,0.000000),
-b3MakeVector3(0.638194,0.723610,0.262864),
-b3MakeVector3(-0.203181,0.967950,0.147618),
-b3MakeVector3(-0.425323,0.850654,0.309011),
-b3MakeVector3(-0.138197,0.894430,0.425320),
-b3MakeVector3(-0.361804,0.723612,0.587778),
-b3MakeVector3(-0.052790,0.723612,0.688185),
-b3MakeVector3(-0.203181,0.967950,-0.147618),
-b3MakeVector3(-0.425323,0.850654,-0.309011),
-b3MakeVector3(-0.447210,0.894429,0.000000),
-b3MakeVector3(-0.670817,0.723611,-0.162457),
-b3MakeVector3(-0.670817,0.723611,0.162457),
-b3MakeVector3(0.077607,0.967950,-0.238853),
-b3MakeVector3(0.162456,0.850654,-0.499995),
-b3MakeVector3(-0.138197,0.894430,-0.425320),
-b3MakeVector3(-0.052790,0.723612,-0.688185),
-b3MakeVector3(-0.361804,0.723612,-0.587778),
-b3MakeVector3(0.361800,0.894429,-0.262863),
-b3MakeVector3(0.638194,0.723610,-0.262864),
-b3MakeVector3(0.447209,0.723612,-0.525728)
-};
-
-
-bool b3FindSeparatingAxisEdgeEdge( const b3ConvexPolyhedronData* hullA, __global const b3ConvexPolyhedronData* hullB,
- b3Float4ConstArg posA1,
- b3QuatConstArg ornA,
- b3Float4ConstArg posB1,
- b3QuatConstArg ornB,
- b3Float4ConstArg DeltaC2,
- const b3Float4* verticesA,
- const b3Float4* uniqueEdgesA,
- const b3GpuFace* facesA,
- const int* indicesA,
- __global const b3Float4* verticesB,
- __global const b3Float4* uniqueEdgesB,
- __global const b3GpuFace* facesB,
- __global const int* indicesB,
- b3Float4* sep,
- float* dmin,
- bool searchAllEdgeEdge)
+b3Vector3 unitSphere162[] =
+ {
+ b3MakeVector3(0.000000, -1.000000, 0.000000),
+ b3MakeVector3(0.203181, -0.967950, 0.147618),
+ b3MakeVector3(-0.077607, -0.967950, 0.238853),
+ b3MakeVector3(0.723607, -0.447220, 0.525725),
+ b3MakeVector3(0.609547, -0.657519, 0.442856),
+ b3MakeVector3(0.812729, -0.502301, 0.295238),
+ b3MakeVector3(-0.251147, -0.967949, 0.000000),
+ b3MakeVector3(-0.077607, -0.967950, -0.238853),
+ b3MakeVector3(0.203181, -0.967950, -0.147618),
+ b3MakeVector3(0.860698, -0.251151, 0.442858),
+ b3MakeVector3(-0.276388, -0.447220, 0.850649),
+ b3MakeVector3(-0.029639, -0.502302, 0.864184),
+ b3MakeVector3(-0.155215, -0.251152, 0.955422),
+ b3MakeVector3(-0.894426, -0.447216, 0.000000),
+ b3MakeVector3(-0.831051, -0.502299, 0.238853),
+ b3MakeVector3(-0.956626, -0.251149, 0.147618),
+ b3MakeVector3(-0.276388, -0.447220, -0.850649),
+ b3MakeVector3(-0.483971, -0.502302, -0.716565),
+ b3MakeVector3(-0.436007, -0.251152, -0.864188),
+ b3MakeVector3(0.723607, -0.447220, -0.525725),
+ b3MakeVector3(0.531941, -0.502302, -0.681712),
+ b3MakeVector3(0.687159, -0.251152, -0.681715),
+ b3MakeVector3(0.687159, -0.251152, 0.681715),
+ b3MakeVector3(-0.436007, -0.251152, 0.864188),
+ b3MakeVector3(-0.956626, -0.251149, -0.147618),
+ b3MakeVector3(-0.155215, -0.251152, -0.955422),
+ b3MakeVector3(0.860698, -0.251151, -0.442858),
+ b3MakeVector3(0.276388, 0.447220, 0.850649),
+ b3MakeVector3(0.483971, 0.502302, 0.716565),
+ b3MakeVector3(0.232822, 0.657519, 0.716563),
+ b3MakeVector3(-0.723607, 0.447220, 0.525725),
+ b3MakeVector3(-0.531941, 0.502302, 0.681712),
+ b3MakeVector3(-0.609547, 0.657519, 0.442856),
+ b3MakeVector3(-0.723607, 0.447220, -0.525725),
+ b3MakeVector3(-0.812729, 0.502301, -0.295238),
+ b3MakeVector3(-0.609547, 0.657519, -0.442856),
+ b3MakeVector3(0.276388, 0.447220, -0.850649),
+ b3MakeVector3(0.029639, 0.502302, -0.864184),
+ b3MakeVector3(0.232822, 0.657519, -0.716563),
+ b3MakeVector3(0.894426, 0.447216, 0.000000),
+ b3MakeVector3(0.831051, 0.502299, -0.238853),
+ b3MakeVector3(0.753442, 0.657515, 0.000000),
+ b3MakeVector3(-0.232822, -0.657519, 0.716563),
+ b3MakeVector3(-0.162456, -0.850654, 0.499995),
+ b3MakeVector3(0.052790, -0.723612, 0.688185),
+ b3MakeVector3(0.138199, -0.894429, 0.425321),
+ b3MakeVector3(0.262869, -0.525738, 0.809012),
+ b3MakeVector3(0.361805, -0.723611, 0.587779),
+ b3MakeVector3(0.531941, -0.502302, 0.681712),
+ b3MakeVector3(0.425323, -0.850654, 0.309011),
+ b3MakeVector3(0.812729, -0.502301, -0.295238),
+ b3MakeVector3(0.609547, -0.657519, -0.442856),
+ b3MakeVector3(0.850648, -0.525736, 0.000000),
+ b3MakeVector3(0.670817, -0.723611, -0.162457),
+ b3MakeVector3(0.670817, -0.723610, 0.162458),
+ b3MakeVector3(0.425323, -0.850654, -0.309011),
+ b3MakeVector3(0.447211, -0.894428, 0.000001),
+ b3MakeVector3(-0.753442, -0.657515, 0.000000),
+ b3MakeVector3(-0.525730, -0.850652, 0.000000),
+ b3MakeVector3(-0.638195, -0.723609, 0.262864),
+ b3MakeVector3(-0.361801, -0.894428, 0.262864),
+ b3MakeVector3(-0.688189, -0.525736, 0.499997),
+ b3MakeVector3(-0.447211, -0.723610, 0.525729),
+ b3MakeVector3(-0.483971, -0.502302, 0.716565),
+ b3MakeVector3(-0.232822, -0.657519, -0.716563),
+ b3MakeVector3(-0.162456, -0.850654, -0.499995),
+ b3MakeVector3(-0.447211, -0.723611, -0.525727),
+ b3MakeVector3(-0.361801, -0.894429, -0.262863),
+ b3MakeVector3(-0.688189, -0.525736, -0.499997),
+ b3MakeVector3(-0.638195, -0.723609, -0.262863),
+ b3MakeVector3(-0.831051, -0.502299, -0.238853),
+ b3MakeVector3(0.361804, -0.723612, -0.587779),
+ b3MakeVector3(0.138197, -0.894429, -0.425321),
+ b3MakeVector3(0.262869, -0.525738, -0.809012),
+ b3MakeVector3(0.052789, -0.723611, -0.688186),
+ b3MakeVector3(-0.029639, -0.502302, -0.864184),
+ b3MakeVector3(0.956626, 0.251149, 0.147618),
+ b3MakeVector3(0.956626, 0.251149, -0.147618),
+ b3MakeVector3(0.951058, -0.000000, 0.309013),
+ b3MakeVector3(1.000000, 0.000000, 0.000000),
+ b3MakeVector3(0.947213, -0.276396, 0.162458),
+ b3MakeVector3(0.951058, 0.000000, -0.309013),
+ b3MakeVector3(0.947213, -0.276396, -0.162458),
+ b3MakeVector3(0.155215, 0.251152, 0.955422),
+ b3MakeVector3(0.436007, 0.251152, 0.864188),
+ b3MakeVector3(-0.000000, -0.000000, 1.000000),
+ b3MakeVector3(0.309017, 0.000000, 0.951056),
+ b3MakeVector3(0.138199, -0.276398, 0.951055),
+ b3MakeVector3(0.587786, 0.000000, 0.809017),
+ b3MakeVector3(0.447216, -0.276398, 0.850648),
+ b3MakeVector3(-0.860698, 0.251151, 0.442858),
+ b3MakeVector3(-0.687159, 0.251152, 0.681715),
+ b3MakeVector3(-0.951058, -0.000000, 0.309013),
+ b3MakeVector3(-0.809018, 0.000000, 0.587783),
+ b3MakeVector3(-0.861803, -0.276396, 0.425324),
+ b3MakeVector3(-0.587786, 0.000000, 0.809017),
+ b3MakeVector3(-0.670819, -0.276397, 0.688191),
+ b3MakeVector3(-0.687159, 0.251152, -0.681715),
+ b3MakeVector3(-0.860698, 0.251151, -0.442858),
+ b3MakeVector3(-0.587786, -0.000000, -0.809017),
+ b3MakeVector3(-0.809018, -0.000000, -0.587783),
+ b3MakeVector3(-0.670819, -0.276397, -0.688191),
+ b3MakeVector3(-0.951058, 0.000000, -0.309013),
+ b3MakeVector3(-0.861803, -0.276396, -0.425324),
+ b3MakeVector3(0.436007, 0.251152, -0.864188),
+ b3MakeVector3(0.155215, 0.251152, -0.955422),
+ b3MakeVector3(0.587786, -0.000000, -0.809017),
+ b3MakeVector3(0.309017, -0.000000, -0.951056),
+ b3MakeVector3(0.447216, -0.276398, -0.850648),
+ b3MakeVector3(0.000000, 0.000000, -1.000000),
+ b3MakeVector3(0.138199, -0.276398, -0.951055),
+ b3MakeVector3(0.670820, 0.276396, 0.688190),
+ b3MakeVector3(0.809019, -0.000002, 0.587783),
+ b3MakeVector3(0.688189, 0.525736, 0.499997),
+ b3MakeVector3(0.861804, 0.276394, 0.425323),
+ b3MakeVector3(0.831051, 0.502299, 0.238853),
+ b3MakeVector3(-0.447216, 0.276397, 0.850649),
+ b3MakeVector3(-0.309017, -0.000001, 0.951056),
+ b3MakeVector3(-0.262869, 0.525738, 0.809012),
+ b3MakeVector3(-0.138199, 0.276397, 0.951055),
+ b3MakeVector3(0.029639, 0.502302, 0.864184),
+ b3MakeVector3(-0.947213, 0.276396, -0.162458),
+ b3MakeVector3(-1.000000, 0.000001, 0.000000),
+ b3MakeVector3(-0.850648, 0.525736, -0.000000),
+ b3MakeVector3(-0.947213, 0.276397, 0.162458),
+ b3MakeVector3(-0.812729, 0.502301, 0.295238),
+ b3MakeVector3(-0.138199, 0.276397, -0.951055),
+ b3MakeVector3(-0.309016, -0.000000, -0.951057),
+ b3MakeVector3(-0.262869, 0.525738, -0.809012),
+ b3MakeVector3(-0.447215, 0.276397, -0.850649),
+ b3MakeVector3(-0.531941, 0.502302, -0.681712),
+ b3MakeVector3(0.861804, 0.276396, -0.425322),
+ b3MakeVector3(0.809019, 0.000000, -0.587782),
+ b3MakeVector3(0.688189, 0.525736, -0.499997),
+ b3MakeVector3(0.670821, 0.276397, -0.688189),
+ b3MakeVector3(0.483971, 0.502302, -0.716565),
+ b3MakeVector3(0.077607, 0.967950, 0.238853),
+ b3MakeVector3(0.251147, 0.967949, 0.000000),
+ b3MakeVector3(0.000000, 1.000000, 0.000000),
+ b3MakeVector3(0.162456, 0.850654, 0.499995),
+ b3MakeVector3(0.361800, 0.894429, 0.262863),
+ b3MakeVector3(0.447209, 0.723612, 0.525728),
+ b3MakeVector3(0.525730, 0.850652, 0.000000),
+ b3MakeVector3(0.638194, 0.723610, 0.262864),
+ b3MakeVector3(-0.203181, 0.967950, 0.147618),
+ b3MakeVector3(-0.425323, 0.850654, 0.309011),
+ b3MakeVector3(-0.138197, 0.894430, 0.425320),
+ b3MakeVector3(-0.361804, 0.723612, 0.587778),
+ b3MakeVector3(-0.052790, 0.723612, 0.688185),
+ b3MakeVector3(-0.203181, 0.967950, -0.147618),
+ b3MakeVector3(-0.425323, 0.850654, -0.309011),
+ b3MakeVector3(-0.447210, 0.894429, 0.000000),
+ b3MakeVector3(-0.670817, 0.723611, -0.162457),
+ b3MakeVector3(-0.670817, 0.723611, 0.162457),
+ b3MakeVector3(0.077607, 0.967950, -0.238853),
+ b3MakeVector3(0.162456, 0.850654, -0.499995),
+ b3MakeVector3(-0.138197, 0.894430, -0.425320),
+ b3MakeVector3(-0.052790, 0.723612, -0.688185),
+ b3MakeVector3(-0.361804, 0.723612, -0.587778),
+ b3MakeVector3(0.361800, 0.894429, -0.262863),
+ b3MakeVector3(0.638194, 0.723610, -0.262864),
+ b3MakeVector3(0.447209, 0.723612, -0.525728)};
+
+bool b3FindSeparatingAxisEdgeEdge(const b3ConvexPolyhedronData* hullA, __global const b3ConvexPolyhedronData* hullB,
+ b3Float4ConstArg posA1,
+ b3QuatConstArg ornA,
+ b3Float4ConstArg posB1,
+ b3QuatConstArg ornB,
+ b3Float4ConstArg DeltaC2,
+ const b3Float4* verticesA,
+ const b3Float4* uniqueEdgesA,
+ const b3GpuFace* facesA,
+ const int* indicesA,
+ __global const b3Float4* verticesB,
+ __global const b3Float4* uniqueEdgesB,
+ __global const b3GpuFace* facesB,
+ __global const int* indicesB,
+ b3Float4* sep,
+ float* dmin,
+ bool searchAllEdgeEdge)
{
-
-
b3Float4 posA = posA1;
posA.w = 0.f;
b3Float4 posB = posB1;
posB.w = 0.f;
-// int curPlaneTests=0;
+ // int curPlaneTests=0;
int curEdgeEdge = 0;
// Test edges
static int maxEdgeTests = 0;
int curEdgeTests = hullA->m_numUniqueEdges * hullB->m_numUniqueEdges;
- if (curEdgeTests >maxEdgeTests )
+ if (curEdgeTests > maxEdgeTests)
{
- maxEdgeTests = curEdgeTests ;
- printf("maxEdgeTests = %d\n",maxEdgeTests );
- printf("hullA->m_numUniqueEdges = %d\n",hullA->m_numUniqueEdges);
- printf("hullB->m_numUniqueEdges = %d\n",hullB->m_numUniqueEdges);
-
+ maxEdgeTests = curEdgeTests;
+ printf("maxEdgeTests = %d\n", maxEdgeTests);
+ printf("hullA->m_numUniqueEdges = %d\n", hullA->m_numUniqueEdges);
+ printf("hullB->m_numUniqueEdges = %d\n", hullB->m_numUniqueEdges);
}
-
if (searchAllEdgeEdge)
{
- for(int e0=0;e0<hullA->m_numUniqueEdges;e0++)
+ for (int e0 = 0; e0 < hullA->m_numUniqueEdges; e0++)
{
- const b3Float4 edge0 = uniqueEdgesA[hullA->m_uniqueEdgesOffset+e0];
- b3Float4 edge0World = b3QuatRotate(ornA,edge0);
+ const b3Float4 edge0 = uniqueEdgesA[hullA->m_uniqueEdgesOffset + e0];
+ b3Float4 edge0World = b3QuatRotate(ornA, edge0);
- for(int e1=0;e1<hullB->m_numUniqueEdges;e1++)
+ for (int e1 = 0; e1 < hullB->m_numUniqueEdges; e1++)
{
- const b3Float4 edge1 = uniqueEdgesB[hullB->m_uniqueEdgesOffset+e1];
- b3Float4 edge1World = b3QuatRotate(ornB,edge1);
-
+ const b3Float4 edge1 = uniqueEdgesB[hullB->m_uniqueEdgesOffset + e1];
+ b3Float4 edge1World = b3QuatRotate(ornB, edge1);
- b3Float4 crossje = b3Cross(edge0World,edge1World);
+ b3Float4 crossje = b3Cross(edge0World, edge1World);
curEdgeEdge++;
- if(!b3IsAlmostZero(crossje))
+ if (!b3IsAlmostZero(crossje))
{
crossje = b3Normalized(crossje);
- if (b3Dot(DeltaC2,crossje)<0)
+ if (b3Dot(DeltaC2, crossje) < 0)
crossje *= -1.f;
float dist;
bool result = true;
{
- float Min0,Max0;
- float Min1,Max1;
- b3Project(hullA,posA,ornA,&crossje,verticesA, &Min0, &Max0);
- b3Project(hullB,posB,ornB,&crossje,verticesB, &Min1, &Max1);
-
- if(Max0<Min1 || Max1<Min0)
+ float Min0, Max0;
+ float Min1, Max1;
+ b3Project(hullA, posA, ornA, &crossje, verticesA, &Min0, &Max0);
+ b3Project(hullB, posB, ornB, &crossje, verticesB, &Min1, &Max1);
+
+ if (Max0 < Min1 || Max1 < Min0)
return false;
-
+
float d0 = Max0 - Min1;
float d1 = Max1 - Min0;
- dist = d0<d1 ? d0:d1;
+ dist = d0 < d1 ? d0 : d1;
result = true;
-
}
-
- if(dist<*dmin)
+ if (dist < *dmin)
{
*dmin = dist;
*sep = crossje;
}
}
}
-
}
- } else
+ }
+ else
{
- int numDirections = sizeof(unitSphere162)/sizeof(b3Vector3);
+ int numDirections = sizeof(unitSphere162) / sizeof(b3Vector3);
//printf("numDirections =%d\n",numDirections );
-
- for(int i=0;i<numDirections;i++)
+ for (int i = 0; i < numDirections; i++)
{
b3Float4 crossje = unitSphere162[i];
{
@@ -404,23 +387,21 @@ bool b3FindSeparatingAxisEdgeEdge( const b3ConvexPolyhedronData* hullA, __global
float dist;
bool result = true;
{
- float Min0,Max0;
- float Min1,Max1;
- b3Project(hullA,posA,ornA,&crossje,verticesA, &Min0, &Max0);
- b3Project(hullB,posB,ornB,&crossje,verticesB, &Min1, &Max1);
-
- if(Max0<Min1 || Max1<Min0)
+ float Min0, Max0;
+ float Min1, Max1;
+ b3Project(hullA, posA, ornA, &crossje, verticesA, &Min0, &Max0);
+ b3Project(hullB, posB, ornB, &crossje, verticesB, &Min1, &Max1);
+
+ if (Max0 < Min1 || Max1 < Min0)
return false;
-
+
float d0 = Max0 - Min1;
float d1 = Max1 - Min0;
- dist = d0<d1 ? d0:d1;
+ dist = d0 < d1 ? d0 : d1;
result = true;
-
}
-
- if(dist<*dmin)
+ if (dist < *dmin)
{
*dmin = dist;
*sep = crossje;
@@ -428,50 +409,45 @@ bool b3FindSeparatingAxisEdgeEdge( const b3ConvexPolyhedronData* hullA, __global
}
}
}
-
}
-
- if((b3Dot(-DeltaC2,*sep))>0.0f)
+ if ((b3Dot(-DeltaC2, *sep)) > 0.0f)
{
*sep = -(*sep);
}
return true;
}
-
-
-inline int b3FindClippingFaces(b3Float4ConstArg separatingNormal,
- __global const b3ConvexPolyhedronData_t* hullA, __global const b3ConvexPolyhedronData_t* hullB,
- b3Float4ConstArg posA, b3QuatConstArg ornA,b3Float4ConstArg posB, b3QuatConstArg ornB,
- __global b3Float4* worldVertsA1,
- __global b3Float4* worldNormalsA1,
- __global b3Float4* worldVertsB1,
- int capacityWorldVerts,
- const float minDist, float maxDist,
- __global const b3Float4* verticesA,
- __global const b3GpuFace_t* facesA,
- __global const int* indicesA,
- __global const b3Float4* verticesB,
- __global const b3GpuFace_t* facesB,
- __global const int* indicesB,
-
- __global b3Int4* clippingFaces, int pairIndex)
+inline int b3FindClippingFaces(b3Float4ConstArg separatingNormal,
+ __global const b3ConvexPolyhedronData_t* hullA, __global const b3ConvexPolyhedronData_t* hullB,
+ b3Float4ConstArg posA, b3QuatConstArg ornA, b3Float4ConstArg posB, b3QuatConstArg ornB,
+ __global b3Float4* worldVertsA1,
+ __global b3Float4* worldNormalsA1,
+ __global b3Float4* worldVertsB1,
+ int capacityWorldVerts,
+ const float minDist, float maxDist,
+ __global const b3Float4* verticesA,
+ __global const b3GpuFace_t* facesA,
+ __global const int* indicesA,
+ __global const b3Float4* verticesB,
+ __global const b3GpuFace_t* facesB,
+ __global const int* indicesB,
+
+ __global b3Int4* clippingFaces, int pairIndex)
{
int numContactsOut = 0;
- int numWorldVertsB1= 0;
-
-
- int closestFaceB=-1;
+ int numWorldVertsB1 = 0;
+
+ int closestFaceB = -1;
float dmax = -FLT_MAX;
-
+
{
- for(int face=0;face<hullB->m_numFaces;face++)
+ for (int face = 0; face < hullB->m_numFaces; face++)
{
- const b3Float4 Normal = b3MakeFloat4(facesB[hullB->m_faceOffset+face].m_plane.x,
- facesB[hullB->m_faceOffset+face].m_plane.y, facesB[hullB->m_faceOffset+face].m_plane.z,0.f);
+ const b3Float4 Normal = b3MakeFloat4(facesB[hullB->m_faceOffset + face].m_plane.x,
+ facesB[hullB->m_faceOffset + face].m_plane.y, facesB[hullB->m_faceOffset + face].m_plane.z, 0.f);
const b3Float4 WorldNormal = b3QuatRotate(ornB, Normal);
- float d = b3Dot(WorldNormal,separatingNormal);
+ float d = b3Dot(WorldNormal, separatingNormal);
if (d > dmax)
{
dmax = d;
@@ -479,81 +455,76 @@ inline int b3FindClippingFaces(b3Float4ConstArg separatingNormal,
}
}
}
-
+
{
- const b3GpuFace_t polyB = facesB[hullB->m_faceOffset+closestFaceB];
+ const b3GpuFace_t polyB = facesB[hullB->m_faceOffset + closestFaceB];
const int numVertices = polyB.m_numIndices;
- for(int e0=0;e0<numVertices;e0++)
+ for (int e0 = 0; e0 < numVertices; e0++)
{
- const b3Float4 b = verticesB[hullB->m_vertexOffset+indicesB[polyB.m_indexOffset+e0]];
- worldVertsB1[pairIndex*capacityWorldVerts+numWorldVertsB1++] = b3TransformPoint(b,posB,ornB);
+ const b3Float4 b = verticesB[hullB->m_vertexOffset + indicesB[polyB.m_indexOffset + e0]];
+ worldVertsB1[pairIndex * capacityWorldVerts + numWorldVertsB1++] = b3TransformPoint(b, posB, ornB);
}
}
-
- int closestFaceA=-1;
+
+ int closestFaceA = -1;
{
float dmin = FLT_MAX;
- for(int face=0;face<hullA->m_numFaces;face++)
+ for (int face = 0; face < hullA->m_numFaces; face++)
{
const b3Float4 Normal = b3MakeFloat4(
- facesA[hullA->m_faceOffset+face].m_plane.x,
- facesA[hullA->m_faceOffset+face].m_plane.y,
- facesA[hullA->m_faceOffset+face].m_plane.z,
- 0.f);
- const b3Float4 faceANormalWS = b3QuatRotate(ornA,Normal);
-
- float d = b3Dot(faceANormalWS,separatingNormal);
+ facesA[hullA->m_faceOffset + face].m_plane.x,
+ facesA[hullA->m_faceOffset + face].m_plane.y,
+ facesA[hullA->m_faceOffset + face].m_plane.z,
+ 0.f);
+ const b3Float4 faceANormalWS = b3QuatRotate(ornA, Normal);
+
+ float d = b3Dot(faceANormalWS, separatingNormal);
if (d < dmin)
{
dmin = d;
closestFaceA = face;
- worldNormalsA1[pairIndex] = faceANormalWS;
+ worldNormalsA1[pairIndex] = faceANormalWS;
}
}
}
-
- int numVerticesA = facesA[hullA->m_faceOffset+closestFaceA].m_numIndices;
- for(int e0=0;e0<numVerticesA;e0++)
+
+ int numVerticesA = facesA[hullA->m_faceOffset + closestFaceA].m_numIndices;
+ for (int e0 = 0; e0 < numVerticesA; e0++)
{
- const b3Float4 a = verticesA[hullA->m_vertexOffset+indicesA[facesA[hullA->m_faceOffset+closestFaceA].m_indexOffset+e0]];
- worldVertsA1[pairIndex*capacityWorldVerts+e0] = b3TransformPoint(a, posA,ornA);
- }
-
- clippingFaces[pairIndex].x = closestFaceA;
- clippingFaces[pairIndex].y = closestFaceB;
- clippingFaces[pairIndex].z = numVerticesA;
- clippingFaces[pairIndex].w = numWorldVertsB1;
-
-
+ const b3Float4 a = verticesA[hullA->m_vertexOffset + indicesA[facesA[hullA->m_faceOffset + closestFaceA].m_indexOffset + e0]];
+ worldVertsA1[pairIndex * capacityWorldVerts + e0] = b3TransformPoint(a, posA, ornA);
+ }
+
+ clippingFaces[pairIndex].x = closestFaceA;
+ clippingFaces[pairIndex].y = closestFaceB;
+ clippingFaces[pairIndex].z = numVerticesA;
+ clippingFaces[pairIndex].w = numWorldVertsB1;
+
return numContactsOut;
}
-
-
-
-__kernel void b3FindConcaveSeparatingAxisKernel( __global b3Int4* concavePairs,
- __global const b3RigidBodyData* rigidBodies,
- __global const b3Collidable* collidables,
- __global const b3ConvexPolyhedronData* convexShapes,
- __global const b3Float4* vertices,
- __global const b3Float4* uniqueEdges,
- __global const b3GpuFace* faces,
- __global const int* indices,
- __global const b3GpuChildShape* gpuChildShapes,
- __global b3Aabb* aabbs,
- __global b3Float4* concaveSeparatingNormalsOut,
- __global b3Int4* clippingFacesOut,
- __global b3Vector3* worldVertsA1Out,
- __global b3Vector3* worldNormalsA1Out,
- __global b3Vector3* worldVertsB1Out,
- __global int* hasSeparatingNormals,
- int vertexFaceCapacity,
- int numConcavePairs,
- int pairIdx
- )
+__kernel void b3FindConcaveSeparatingAxisKernel(__global b3Int4* concavePairs,
+ __global const b3RigidBodyData* rigidBodies,
+ __global const b3Collidable* collidables,
+ __global const b3ConvexPolyhedronData* convexShapes,
+ __global const b3Float4* vertices,
+ __global const b3Float4* uniqueEdges,
+ __global const b3GpuFace* faces,
+ __global const int* indices,
+ __global const b3GpuChildShape* gpuChildShapes,
+ __global b3Aabb* aabbs,
+ __global b3Float4* concaveSeparatingNormalsOut,
+ __global b3Int4* clippingFacesOut,
+ __global b3Vector3* worldVertsA1Out,
+ __global b3Vector3* worldNormalsA1Out,
+ __global b3Vector3* worldVertsB1Out,
+ __global int* hasSeparatingNormals,
+ int vertexFaceCapacity,
+ int numConcavePairs,
+ int pairIdx)
{
int i = pairIdx;
-/* int i = get_global_id(0);
+ /* int i = get_global_id(0);
if (i>=numConcavePairs)
return;
int pairIdx = i;
@@ -568,8 +539,8 @@ __kernel void b3FindConcaveSeparatingAxisKernel( __global b3Int4* concavePairs
int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
- if (collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL&&
- collidables[collidableIndexB].m_shapeType!=SHAPE_COMPOUND_OF_CONVEX_HULLS)
+ if (collidables[collidableIndexB].m_shapeType != SHAPE_CONVEX_HULL &&
+ collidables[collidableIndexB].m_shapeType != SHAPE_COMPOUND_OF_CONVEX_HULLS)
{
concavePairs[pairIdx].w = -1;
return;
@@ -577,121 +548,119 @@ __kernel void b3FindConcaveSeparatingAxisKernel( __global b3Int4* concavePairs
hasSeparatingNormals[i] = 0;
-// int numFacesA = convexShapes[shapeIndexA].m_numFaces;
+ // int numFacesA = convexShapes[shapeIndexA].m_numFaces;
int numActualConcaveConvexTests = 0;
-
+
int f = concavePairs[i].z;
-
+
bool overlap = false;
-
+
b3ConvexPolyhedronData convexPolyhedronA;
//add 3 vertices of the triangle
convexPolyhedronA.m_numVertices = 3;
convexPolyhedronA.m_vertexOffset = 0;
- b3Float4 localCenter = b3MakeFloat4(0.f,0.f,0.f,0.f);
+ b3Float4 localCenter = b3MakeFloat4(0.f, 0.f, 0.f, 0.f);
- b3GpuFace face = faces[convexShapes[shapeIndexA].m_faceOffset+f];
+ b3GpuFace face = faces[convexShapes[shapeIndexA].m_faceOffset + f];
b3Aabb triAabb;
- triAabb.m_minVec = b3MakeFloat4(1e30f,1e30f,1e30f,0.f);
- triAabb.m_maxVec = b3MakeFloat4(-1e30f,-1e30f,-1e30f,0.f);
-
+ triAabb.m_minVec = b3MakeFloat4(1e30f, 1e30f, 1e30f, 0.f);
+ triAabb.m_maxVec = b3MakeFloat4(-1e30f, -1e30f, -1e30f, 0.f);
+
b3Float4 verticesA[3];
- for (int i=0;i<3;i++)
+ for (int i = 0; i < 3; i++)
{
- int index = indices[face.m_indexOffset+i];
- b3Float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];
+ int index = indices[face.m_indexOffset + i];
+ b3Float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset + index];
verticesA[i] = vert;
localCenter += vert;
-
- triAabb.m_minVec = b3MinFloat4(triAabb.m_minVec,vert);
- triAabb.m_maxVec = b3MaxFloat4(triAabb.m_maxVec,vert);
+ triAabb.m_minVec = b3MinFloat4(triAabb.m_minVec, vert);
+ triAabb.m_maxVec = b3MaxFloat4(triAabb.m_maxVec, vert);
}
overlap = true;
overlap = (triAabb.m_minVec.x > aabbs[bodyIndexB].m_maxVec.x || triAabb.m_maxVec.x < aabbs[bodyIndexB].m_minVec.x) ? false : overlap;
overlap = (triAabb.m_minVec.z > aabbs[bodyIndexB].m_maxVec.z || triAabb.m_maxVec.z < aabbs[bodyIndexB].m_minVec.z) ? false : overlap;
overlap = (triAabb.m_minVec.y > aabbs[bodyIndexB].m_maxVec.y || triAabb.m_maxVec.y < aabbs[bodyIndexB].m_minVec.y) ? false : overlap;
-
+
if (overlap)
{
float dmin = FLT_MAX;
- int hasSeparatingAxis=5;
- b3Float4 sepAxis=b3MakeFloat4(1,2,3,4);
+ int hasSeparatingAxis = 5;
+ b3Float4 sepAxis = b3MakeFloat4(1, 2, 3, 4);
- // int localCC=0;
+ // int localCC=0;
numActualConcaveConvexTests++;
//a triangle has 3 unique edges
convexPolyhedronA.m_numUniqueEdges = 3;
convexPolyhedronA.m_uniqueEdgesOffset = 0;
b3Float4 uniqueEdgesA[3];
-
- uniqueEdgesA[0] = (verticesA[1]-verticesA[0]);
- uniqueEdgesA[1] = (verticesA[2]-verticesA[1]);
- uniqueEdgesA[2] = (verticesA[0]-verticesA[2]);
+ uniqueEdgesA[0] = (verticesA[1] - verticesA[0]);
+ uniqueEdgesA[1] = (verticesA[2] - verticesA[1]);
+ uniqueEdgesA[2] = (verticesA[0] - verticesA[2]);
convexPolyhedronA.m_faceOffset = 0;
-
- b3Float4 normal = b3MakeFloat4(face.m_plane.x,face.m_plane.y,face.m_plane.z,0.f);
-
+
+ b3Float4 normal = b3MakeFloat4(face.m_plane.x, face.m_plane.y, face.m_plane.z, 0.f);
+
b3GpuFace facesA[B3_TRIANGLE_NUM_CONVEX_FACES];
- int indicesA[3+3+2+2+2];
- int curUsedIndices=0;
- int fidx=0;
+ int indicesA[3 + 3 + 2 + 2 + 2];
+ int curUsedIndices = 0;
+ int fidx = 0;
//front size of triangle
{
- facesA[fidx].m_indexOffset=curUsedIndices;
+ facesA[fidx].m_indexOffset = curUsedIndices;
indicesA[0] = 0;
indicesA[1] = 1;
indicesA[2] = 2;
- curUsedIndices+=3;
+ curUsedIndices += 3;
float c = face.m_plane.w;
facesA[fidx].m_plane.x = normal.x;
facesA[fidx].m_plane.y = normal.y;
facesA[fidx].m_plane.z = normal.z;
facesA[fidx].m_plane.w = c;
- facesA[fidx].m_numIndices=3;
+ facesA[fidx].m_numIndices = 3;
}
fidx++;
//back size of triangle
{
- facesA[fidx].m_indexOffset=curUsedIndices;
- indicesA[3]=2;
- indicesA[4]=1;
- indicesA[5]=0;
- curUsedIndices+=3;
- float c = b3Dot(normal,verticesA[0]);
- // float c1 = -face.m_plane.w;
+ facesA[fidx].m_indexOffset = curUsedIndices;
+ indicesA[3] = 2;
+ indicesA[4] = 1;
+ indicesA[5] = 0;
+ curUsedIndices += 3;
+ float c = b3Dot(normal, verticesA[0]);
+ // float c1 = -face.m_plane.w;
facesA[fidx].m_plane.x = -normal.x;
facesA[fidx].m_plane.y = -normal.y;
facesA[fidx].m_plane.z = -normal.z;
facesA[fidx].m_plane.w = c;
- facesA[fidx].m_numIndices=3;
+ facesA[fidx].m_numIndices = 3;
}
fidx++;
bool addEdgePlanes = true;
if (addEdgePlanes)
{
- int numVertices=3;
- int prevVertex = numVertices-1;
- for (int i=0;i<numVertices;i++)
+ int numVertices = 3;
+ int prevVertex = numVertices - 1;
+ for (int i = 0; i < numVertices; i++)
{
b3Float4 v0 = verticesA[i];
b3Float4 v1 = verticesA[prevVertex];
-
- b3Float4 edgeNormal = b3Normalized(b3Cross(normal,v1-v0));
- float c = -b3Dot(edgeNormal,v0);
+
+ b3Float4 edgeNormal = b3Normalized(b3Cross(normal, v1 - v0));
+ float c = -b3Dot(edgeNormal, v0);
facesA[fidx].m_numIndices = 2;
- facesA[fidx].m_indexOffset=curUsedIndices;
- indicesA[curUsedIndices++]=i;
- indicesA[curUsedIndices++]=prevVertex;
-
+ facesA[fidx].m_indexOffset = curUsedIndices;
+ indicesA[curUsedIndices++] = i;
+ indicesA[curUsedIndices++] = prevVertex;
+
facesA[fidx].m_plane.x = edgeNormal.x;
facesA[fidx].m_plane.y = edgeNormal.y;
facesA[fidx].m_plane.z = edgeNormal.z;
@@ -701,8 +670,7 @@ __kernel void b3FindConcaveSeparatingAxisKernel( __global b3Int4* concavePairs
}
}
convexPolyhedronA.m_numFaces = B3_TRIANGLE_NUM_CONVEX_FACES;
- convexPolyhedronA.m_localCenter = localCenter*(1.f/3.f);
-
+ convexPolyhedronA.m_localCenter = localCenter * (1.f / 3.f);
b3Float4 posA = rigidBodies[bodyIndexA].m_pos;
posA.w = 0.f;
@@ -710,23 +678,20 @@ __kernel void b3FindConcaveSeparatingAxisKernel( __global b3Int4* concavePairs
posB.w = 0.f;
b3Quaternion ornA = rigidBodies[bodyIndexA].m_quat;
- b3Quaternion ornB =rigidBodies[bodyIndexB].m_quat;
-
-
-
+ b3Quaternion ornB = rigidBodies[bodyIndexB].m_quat;
///////////////////
///compound shape support
- if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+ if (collidables[collidableIndexB].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS)
{
int compoundChild = concavePairs[pairIdx].w;
- int childShapeIndexB = compoundChild;//collidables[collidableIndexB].m_shapeIndex+compoundChild;
+ int childShapeIndexB = compoundChild; //collidables[collidableIndexB].m_shapeIndex+compoundChild;
int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
b3Float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
b3Quaternion childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
- b3Float4 newPosB = b3TransformPoint(childPosB,posB,ornB);
- b3Quaternion newOrnB = b3QuatMul(ornB,childOrnB);
+ b3Float4 newPosB = b3TransformPoint(childPosB, posB, ornB);
+ b3Quaternion newOrnB = b3QuatMul(ornB, childOrnB);
posB = newPosB;
ornB = newOrnB;
shapeIndexB = collidables[childColIndexB].m_shapeIndex;
@@ -736,59 +701,61 @@ __kernel void b3FindConcaveSeparatingAxisKernel( __global b3Int4* concavePairs
b3Float4 c0local = convexPolyhedronA.m_localCenter;
b3Float4 c0 = b3TransformPoint(c0local, posA, ornA);
b3Float4 c1local = convexShapes[shapeIndexB].m_localCenter;
- b3Float4 c1 = b3TransformPoint(c1local,posB,ornB);
+ b3Float4 c1 = b3TransformPoint(c1local, posB, ornB);
const b3Float4 DeltaC2 = c0 - c1;
-
- bool sepA = b3FindSeparatingAxis( &convexPolyhedronA, &convexShapes[shapeIndexB],
- posA,ornA,
- posB,ornB,
- DeltaC2,
- verticesA,uniqueEdgesA,facesA,indicesA,
- vertices,uniqueEdges,faces,indices,
- &sepAxis,&dmin);
+ bool sepA = b3FindSeparatingAxis(&convexPolyhedronA, &convexShapes[shapeIndexB],
+ posA, ornA,
+ posB, ornB,
+ DeltaC2,
+ verticesA, uniqueEdgesA, facesA, indicesA,
+ vertices, uniqueEdges, faces, indices,
+ &sepAxis, &dmin);
hasSeparatingAxis = 4;
if (!sepA)
{
hasSeparatingAxis = 0;
- } else
+ }
+ else
{
- bool sepB = b3FindSeparatingAxis( &convexShapes[shapeIndexB],&convexPolyhedronA,
- posB,ornB,
- posA,ornA,
- DeltaC2,
- vertices,uniqueEdges,faces,indices,
- verticesA,uniqueEdgesA,facesA,indicesA,
- &sepAxis,&dmin);
+ bool sepB = b3FindSeparatingAxis(&convexShapes[shapeIndexB], &convexPolyhedronA,
+ posB, ornB,
+ posA, ornA,
+ DeltaC2,
+ vertices, uniqueEdges, faces, indices,
+ verticesA, uniqueEdgesA, facesA, indicesA,
+ &sepAxis, &dmin);
if (!sepB)
{
hasSeparatingAxis = 0;
- } else
+ }
+ else
{
- bool sepEE = b3FindSeparatingAxisEdgeEdge( &convexPolyhedronA, &convexShapes[shapeIndexB],
- posA,ornA,
- posB,ornB,
- DeltaC2,
- verticesA,uniqueEdgesA,facesA,indicesA,
- vertices,uniqueEdges,faces,indices,
- &sepAxis,&dmin,true);
-
+ bool sepEE = b3FindSeparatingAxisEdgeEdge(&convexPolyhedronA, &convexShapes[shapeIndexB],
+ posA, ornA,
+ posB, ornB,
+ DeltaC2,
+ verticesA, uniqueEdgesA, facesA, indicesA,
+ vertices, uniqueEdges, faces, indices,
+ &sepAxis, &dmin, true);
+
if (!sepEE)
{
hasSeparatingAxis = 0;
- } else
+ }
+ else
{
hasSeparatingAxis = 1;
}
}
- }
-
+ }
+
if (hasSeparatingAxis)
{
- hasSeparatingNormals[i]=1;
+ hasSeparatingNormals[i] = 1;
sepAxis.w = dmin;
- concaveSeparatingNormalsOut[pairIdx]=sepAxis;
+ concaveSeparatingNormalsOut[pairIdx] = sepAxis;
//now compute clipping faces A and B, and world-space clipping vertices A and B...
@@ -796,37 +763,35 @@ __kernel void b3FindConcaveSeparatingAxisKernel( __global b3Int4* concavePairs
float maxDist = 0.02f;
b3FindClippingFaces(sepAxis,
- &convexPolyhedronA,
- &convexShapes[shapeIndexB],
- posA,ornA,
- posB,ornB,
- worldVertsA1Out,
- worldNormalsA1Out,
- worldVertsB1Out,
- vertexFaceCapacity,
- minDist, maxDist,
- verticesA,
- facesA,
- indicesA,
-
- vertices,
- faces,
- indices,
- clippingFacesOut, pairIdx);
-
- } else
- {
+ &convexPolyhedronA,
+ &convexShapes[shapeIndexB],
+ posA, ornA,
+ posB, ornB,
+ worldVertsA1Out,
+ worldNormalsA1Out,
+ worldVertsB1Out,
+ vertexFaceCapacity,
+ minDist, maxDist,
+ verticesA,
+ facesA,
+ indicesA,
+
+ vertices,
+ faces,
+ indices,
+ clippingFacesOut, pairIdx);
+ }
+ else
+ {
//mark this pair as in-active
concavePairs[pairIdx].w = -1;
}
}
else
- {
+ {
//mark this pair as in-active
concavePairs[pairIdx].w = -1;
}
}
-
-#endif //B3_FIND_CONCAVE_SEPARATING_AXIS_H
-
+#endif //B3_FIND_CONCAVE_SEPARATING_AXIS_H
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3FindSeparatingAxis.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3FindSeparatingAxis.h
index 332dbc278c..b4981ae654 100644
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3FindSeparatingAxis.h
+++ b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3FindSeparatingAxis.h
@@ -1,28 +1,27 @@
#ifndef B3_FIND_SEPARATING_AXIS_H
#define B3_FIND_SEPARATING_AXIS_H
-
-inline void b3ProjectAxis(const b3ConvexPolyhedronData& hull, const b3Float4& pos, const b3Quaternion& orn, const b3Float4& dir, const b3AlignedObjectArray<b3Vector3>& vertices, b3Scalar& min, b3Scalar& max)
+inline void b3ProjectAxis(const b3ConvexPolyhedronData& hull, const b3Float4& pos, const b3Quaternion& orn, const b3Float4& dir, const b3AlignedObjectArray<b3Vector3>& vertices, b3Scalar& min, b3Scalar& max)
{
min = FLT_MAX;
max = -FLT_MAX;
int numVerts = hull.m_numVertices;
- const b3Float4 localDir = b3QuatRotate(orn.inverse(),dir);
+ const b3Float4 localDir = b3QuatRotate(orn.inverse(), dir);
- b3Scalar offset = b3Dot3F4(pos,dir);
+ b3Scalar offset = b3Dot3F4(pos, dir);
- for(int i=0;i<numVerts;i++)
+ for (int i = 0; i < numVerts; i++)
{
//b3Vector3 pt = trans * vertices[m_vertexOffset+i];
//b3Scalar dp = pt.dot(dir);
//b3Vector3 vertex = vertices[hull.m_vertexOffset+i];
- b3Scalar dp = b3Dot3F4((b3Float4&)vertices[hull.m_vertexOffset+i],localDir);
+ b3Scalar dp = b3Dot3F4((b3Float4&)vertices[hull.m_vertexOffset + i], localDir);
//b3Assert(dp==dpL);
- if(dp < min) min = dp;
- if(dp > max) max = dp;
+ if (dp < min) min = dp;
+ if (dp > max) max = dp;
}
- if(min>max)
+ if (min > max)
{
b3Scalar tmp = min;
min = max;
@@ -32,44 +31,42 @@ inline void b3ProjectAxis(const b3ConvexPolyhedronData& hull, const b3Float4& p
max += offset;
}
-
-inline bool b3TestSepAxis(const b3ConvexPolyhedronData& hullA, const b3ConvexPolyhedronData& hullB,
- const b3Float4& posA,const b3Quaternion& ornA,
- const b3Float4& posB,const b3Quaternion& ornB,
- const b3Float4& sep_axis, const b3AlignedObjectArray<b3Vector3>& verticesA,const b3AlignedObjectArray<b3Vector3>& verticesB,b3Scalar& depth)
+inline bool b3TestSepAxis(const b3ConvexPolyhedronData& hullA, const b3ConvexPolyhedronData& hullB,
+ const b3Float4& posA, const b3Quaternion& ornA,
+ const b3Float4& posB, const b3Quaternion& ornB,
+ const b3Float4& sep_axis, const b3AlignedObjectArray<b3Vector3>& verticesA, const b3AlignedObjectArray<b3Vector3>& verticesB, b3Scalar& depth)
{
- b3Scalar Min0,Max0;
- b3Scalar Min1,Max1;
- b3ProjectAxis(hullA,posA,ornA,sep_axis,verticesA, Min0, Max0);
- b3ProjectAxis(hullB,posB,ornB, sep_axis,verticesB, Min1, Max1);
+ b3Scalar Min0, Max0;
+ b3Scalar Min1, Max1;
+ b3ProjectAxis(hullA, posA, ornA, sep_axis, verticesA, Min0, Max0);
+ b3ProjectAxis(hullB, posB, ornB, sep_axis, verticesB, Min1, Max1);
- if(Max0<Min1 || Max1<Min0)
+ if (Max0 < Min1 || Max1 < Min0)
return false;
b3Scalar d0 = Max0 - Min1;
- b3Assert(d0>=0.0f);
+ b3Assert(d0 >= 0.0f);
b3Scalar d1 = Max1 - Min0;
- b3Assert(d1>=0.0f);
- depth = d0<d1 ? d0:d1;
+ b3Assert(d1 >= 0.0f);
+ depth = d0 < d1 ? d0 : d1;
return true;
}
-
-inline bool b3FindSeparatingAxis( const b3ConvexPolyhedronData& hullA, const b3ConvexPolyhedronData& hullB,
- const b3Float4& posA1,
- const b3Quaternion& ornA,
- const b3Float4& posB1,
- const b3Quaternion& ornB,
- const b3AlignedObjectArray<b3Vector3>& verticesA,
- const b3AlignedObjectArray<b3Vector3>& uniqueEdgesA,
- const b3AlignedObjectArray<b3GpuFace>& facesA,
- const b3AlignedObjectArray<int>& indicesA,
- const b3AlignedObjectArray<b3Vector3>& verticesB,
- const b3AlignedObjectArray<b3Vector3>& uniqueEdgesB,
- const b3AlignedObjectArray<b3GpuFace>& facesB,
- const b3AlignedObjectArray<int>& indicesB,
-
- b3Vector3& sep)
+inline bool b3FindSeparatingAxis(const b3ConvexPolyhedronData& hullA, const b3ConvexPolyhedronData& hullB,
+ const b3Float4& posA1,
+ const b3Quaternion& ornA,
+ const b3Float4& posB1,
+ const b3Quaternion& ornB,
+ const b3AlignedObjectArray<b3Vector3>& verticesA,
+ const b3AlignedObjectArray<b3Vector3>& uniqueEdgesA,
+ const b3AlignedObjectArray<b3GpuFace>& facesA,
+ const b3AlignedObjectArray<int>& indicesA,
+ const b3AlignedObjectArray<b3Vector3>& verticesB,
+ const b3AlignedObjectArray<b3Vector3>& uniqueEdgesB,
+ const b3AlignedObjectArray<b3GpuFace>& facesB,
+ const b3AlignedObjectArray<int>& indicesB,
+
+ b3Vector3& sep)
{
B3_PROFILE("findSeparatingAxis");
@@ -77,42 +74,41 @@ inline bool b3FindSeparatingAxis( const b3ConvexPolyhedronData& hullA, const b3C
posA.w = 0.f;
b3Float4 posB = posB1;
posB.w = 0.f;
-//#ifdef TEST_INTERNAL_OBJECTS
+ //#ifdef TEST_INTERNAL_OBJECTS
b3Float4 c0local = (b3Float4&)hullA.m_localCenter;
b3Float4 c0 = b3TransformPoint(c0local, posA, ornA);
b3Float4 c1local = (b3Float4&)hullB.m_localCenter;
- b3Float4 c1 = b3TransformPoint(c1local,posB,ornB);
+ b3Float4 c1 = b3TransformPoint(c1local, posB, ornB);
const b3Float4 deltaC2 = c0 - c1;
-//#endif
+ //#endif
b3Scalar dmin = FLT_MAX;
- int curPlaneTests=0;
+ int curPlaneTests = 0;
int numFacesA = hullA.m_numFaces;
// Test normals from hullA
- for(int i=0;i<numFacesA;i++)
+ for (int i = 0; i < numFacesA; i++)
{
- const b3Float4& normal = (b3Float4&)facesA[hullA.m_faceOffset+i].m_plane;
- b3Float4 faceANormalWS = b3QuatRotate(ornA,normal);
+ const b3Float4& normal = (b3Float4&)facesA[hullA.m_faceOffset + i].m_plane;
+ b3Float4 faceANormalWS = b3QuatRotate(ornA, normal);
- if (b3Dot3F4(deltaC2,faceANormalWS)<0)
- faceANormalWS*=-1.f;
+ if (b3Dot3F4(deltaC2, faceANormalWS) < 0)
+ faceANormalWS *= -1.f;
curPlaneTests++;
#ifdef TEST_INTERNAL_OBJECTS
gExpectedNbTests++;
- if(gUseInternalObject && !TestInternalObjects(transA,transB, DeltaC2, faceANormalWS, hullA, hullB, dmin))
+ if (gUseInternalObject && !TestInternalObjects(transA, transB, DeltaC2, faceANormalWS, hullA, hullB, dmin))
continue;
gActualNbTests++;
#endif
-
b3Scalar d;
- if(!b3TestSepAxis( hullA, hullB, posA,ornA,posB,ornB,faceANormalWS, verticesA, verticesB,d))
+ if (!b3TestSepAxis(hullA, hullB, posA, ornA, posB, ornB, faceANormalWS, verticesA, verticesB, d))
return false;
- if(d<dmin)
+ if (d < dmin)
{
dmin = d;
sep = (b3Vector3&)faceANormalWS;
@@ -121,86 +117,81 @@ inline bool b3FindSeparatingAxis( const b3ConvexPolyhedronData& hullA, const b3C
int numFacesB = hullB.m_numFaces;
// Test normals from hullB
- for(int i=0;i<numFacesB;i++)
+ for (int i = 0; i < numFacesB; i++)
{
- b3Float4 normal = (b3Float4&)facesB[hullB.m_faceOffset+i].m_plane;
+ b3Float4 normal = (b3Float4&)facesB[hullB.m_faceOffset + i].m_plane;
b3Float4 WorldNormal = b3QuatRotate(ornB, normal);
- if (b3Dot3F4(deltaC2,WorldNormal)<0)
+ if (b3Dot3F4(deltaC2, WorldNormal) < 0)
{
- WorldNormal*=-1.f;
+ WorldNormal *= -1.f;
}
curPlaneTests++;
#ifdef TEST_INTERNAL_OBJECTS
gExpectedNbTests++;
- if(gUseInternalObject && !TestInternalObjects(transA,transB,DeltaC2, WorldNormal, hullA, hullB, dmin))
+ if (gUseInternalObject && !TestInternalObjects(transA, transB, DeltaC2, WorldNormal, hullA, hullB, dmin))
continue;
gActualNbTests++;
#endif
b3Scalar d;
- if(!b3TestSepAxis(hullA, hullB,posA,ornA,posB,ornB,WorldNormal,verticesA,verticesB,d))
+ if (!b3TestSepAxis(hullA, hullB, posA, ornA, posB, ornB, WorldNormal, verticesA, verticesB, d))
return false;
- if(d<dmin)
+ if (d < dmin)
{
dmin = d;
sep = (b3Vector3&)WorldNormal;
}
}
-// b3Vector3 edgeAstart,edgeAend,edgeBstart,edgeBend;
+ // b3Vector3 edgeAstart,edgeAend,edgeBstart,edgeBend;
int curEdgeEdge = 0;
// Test edges
- for(int e0=0;e0<hullA.m_numUniqueEdges;e0++)
+ for (int e0 = 0; e0 < hullA.m_numUniqueEdges; e0++)
{
- const b3Float4& edge0 = (b3Float4&) uniqueEdgesA[hullA.m_uniqueEdgesOffset+e0];
- b3Float4 edge0World = b3QuatRotate(ornA,(b3Float4&)edge0);
+ const b3Float4& edge0 = (b3Float4&)uniqueEdgesA[hullA.m_uniqueEdgesOffset + e0];
+ b3Float4 edge0World = b3QuatRotate(ornA, (b3Float4&)edge0);
- for(int e1=0;e1<hullB.m_numUniqueEdges;e1++)
+ for (int e1 = 0; e1 < hullB.m_numUniqueEdges; e1++)
{
- const b3Vector3 edge1 = uniqueEdgesB[hullB.m_uniqueEdgesOffset+e1];
- b3Float4 edge1World = b3QuatRotate(ornB,(b3Float4&)edge1);
-
+ const b3Vector3 edge1 = uniqueEdgesB[hullB.m_uniqueEdgesOffset + e1];
+ b3Float4 edge1World = b3QuatRotate(ornB, (b3Float4&)edge1);
- b3Float4 crossje = b3Cross3(edge0World,edge1World);
+ b3Float4 crossje = b3Cross3(edge0World, edge1World);
curEdgeEdge++;
- if(!b3IsAlmostZero((b3Vector3&)crossje))
+ if (!b3IsAlmostZero((b3Vector3&)crossje))
{
crossje = b3FastNormalized3(crossje);
- if (b3Dot3F4(deltaC2,crossje)<0)
- crossje*=-1.f;
-
+ if (b3Dot3F4(deltaC2, crossje) < 0)
+ crossje *= -1.f;
#ifdef TEST_INTERNAL_OBJECTS
gExpectedNbTests++;
- if(gUseInternalObject && !TestInternalObjects(transA,transB,DeltaC2, Cross, hullA, hullB, dmin))
+ if (gUseInternalObject && !TestInternalObjects(transA, transB, DeltaC2, Cross, hullA, hullB, dmin))
continue;
gActualNbTests++;
#endif
b3Scalar dist;
- if(!b3TestSepAxis( hullA, hullB, posA,ornA,posB,ornB,crossje, verticesA,verticesB,dist))
+ if (!b3TestSepAxis(hullA, hullB, posA, ornA, posB, ornB, crossje, verticesA, verticesB, dist))
return false;
- if(dist<dmin)
+ if (dist < dmin)
{
dmin = dist;
sep = (b3Vector3&)crossje;
}
}
}
-
}
-
- if((b3Dot3F4(-deltaC2,(b3Float4&)sep))>0.0f)
+ if ((b3Dot3F4(-deltaC2, (b3Float4&)sep)) > 0.0f)
sep = -sep;
return true;
}
-#endif //B3_FIND_SEPARATING_AXIS_H
-
+#endif //B3_FIND_SEPARATING_AXIS_H
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3MprPenetration.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3MprPenetration.h
index 6c3ad7c9dd..a3bfbf2995 100644
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3MprPenetration.h
+++ b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3MprPenetration.h
@@ -15,9 +15,6 @@
* See the License for more information.
*/
-
-
-
#ifndef B3_MPR_PENETRATION_H
#define B3_MPR_PENETRATION_H
@@ -27,9 +24,6 @@
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
-
-
-
#ifdef __cplusplus
#define B3_MPR_SQRT sqrtf
#else
@@ -41,196 +35,171 @@
#define B3_MPR_TOLERANCE 1E-6f
#define B3_MPR_MAX_ITERATIONS 1000
-struct _b3MprSupport_t
+struct _b3MprSupport_t
{
- b3Float4 v; //!< Support point in minkowski sum
- b3Float4 v1; //!< Support point in obj1
- b3Float4 v2; //!< Support point in obj2
+ b3Float4 v; //!< Support point in minkowski sum
+ b3Float4 v1; //!< Support point in obj1
+ b3Float4 v2; //!< Support point in obj2
};
typedef struct _b3MprSupport_t b3MprSupport_t;
-struct _b3MprSimplex_t
+struct _b3MprSimplex_t
{
- b3MprSupport_t ps[4];
- int last; //!< index of last added point
+ b3MprSupport_t ps[4];
+ int last; //!< index of last added point
};
typedef struct _b3MprSimplex_t b3MprSimplex_t;
-inline b3MprSupport_t* b3MprSimplexPointW(b3MprSimplex_t *s, int idx)
+inline b3MprSupport_t *b3MprSimplexPointW(b3MprSimplex_t *s, int idx)
{
- return &s->ps[idx];
+ return &s->ps[idx];
}
inline void b3MprSimplexSetSize(b3MprSimplex_t *s, int size)
{
- s->last = size - 1;
+ s->last = size - 1;
}
-
inline int b3MprSimplexSize(const b3MprSimplex_t *s)
{
- return s->last + 1;
+ return s->last + 1;
}
-
-inline const b3MprSupport_t* b3MprSimplexPoint(const b3MprSimplex_t* s, int idx)
+inline const b3MprSupport_t *b3MprSimplexPoint(const b3MprSimplex_t *s, int idx)
{
- // here is no check on boundaries
- return &s->ps[idx];
+ // here is no check on boundaries
+ return &s->ps[idx];
}
inline void b3MprSupportCopy(b3MprSupport_t *d, const b3MprSupport_t *s)
{
- *d = *s;
+ *d = *s;
}
inline void b3MprSimplexSet(b3MprSimplex_t *s, size_t pos, const b3MprSupport_t *a)
{
- b3MprSupportCopy(s->ps + pos, a);
+ b3MprSupportCopy(s->ps + pos, a);
}
-
inline void b3MprSimplexSwap(b3MprSimplex_t *s, size_t pos1, size_t pos2)
{
- b3MprSupport_t supp;
+ b3MprSupport_t supp;
- b3MprSupportCopy(&supp, &s->ps[pos1]);
- b3MprSupportCopy(&s->ps[pos1], &s->ps[pos2]);
- b3MprSupportCopy(&s->ps[pos2], &supp);
+ b3MprSupportCopy(&supp, &s->ps[pos1]);
+ b3MprSupportCopy(&s->ps[pos1], &s->ps[pos2]);
+ b3MprSupportCopy(&s->ps[pos2], &supp);
}
-
inline int b3MprIsZero(float val)
{
- return B3_MPR_FABS(val) < FLT_EPSILON;
+ return B3_MPR_FABS(val) < FLT_EPSILON;
}
-
-
inline int b3MprEq(float _a, float _b)
{
- float ab;
- float a, b;
+ float ab;
+ float a, b;
- ab = B3_MPR_FABS(_a - _b);
- if (B3_MPR_FABS(ab) < FLT_EPSILON)
- return 1;
+ ab = B3_MPR_FABS(_a - _b);
+ if (B3_MPR_FABS(ab) < FLT_EPSILON)
+ return 1;
- a = B3_MPR_FABS(_a);
- b = B3_MPR_FABS(_b);
- if (b > a){
- return ab < FLT_EPSILON * b;
- }else{
- return ab < FLT_EPSILON * a;
- }
+ a = B3_MPR_FABS(_a);
+ b = B3_MPR_FABS(_b);
+ if (b > a)
+ {
+ return ab < FLT_EPSILON * b;
+ }
+ else
+ {
+ return ab < FLT_EPSILON * a;
+ }
}
-
-inline int b3MprVec3Eq(const b3Float4* a, const b3Float4 *b)
+inline int b3MprVec3Eq(const b3Float4 *a, const b3Float4 *b)
{
- return b3MprEq((*a).x, (*b).x)
- && b3MprEq((*a).y, (*b).y)
- && b3MprEq((*a).z, (*b).z);
+ return b3MprEq((*a).x, (*b).x) && b3MprEq((*a).y, (*b).y) && b3MprEq((*a).z, (*b).z);
}
-
-
-inline b3Float4 b3LocalGetSupportVertex(b3Float4ConstArg supportVec,__global const b3ConvexPolyhedronData_t* hull, b3ConstArray(b3Float4) verticesA)
+inline b3Float4 b3LocalGetSupportVertex(b3Float4ConstArg supportVec, __global const b3ConvexPolyhedronData_t *hull, b3ConstArray(b3Float4) verticesA)
{
- b3Float4 supVec = b3MakeFloat4(0,0,0,0);
+ b3Float4 supVec = b3MakeFloat4(0, 0, 0, 0);
float maxDot = -B3_LARGE_FLOAT;
- if( 0 < hull->m_numVertices )
- {
- const b3Float4 scaled = supportVec;
+ if (0 < hull->m_numVertices)
+ {
+ const b3Float4 scaled = supportVec;
int index = b3MaxDot(scaled, &verticesA[hull->m_vertexOffset], hull->m_numVertices, &maxDot);
- return verticesA[hull->m_vertexOffset+index];
- }
-
- return supVec;
+ return verticesA[hull->m_vertexOffset + index];
+ }
+ return supVec;
}
-
-B3_STATIC void b3MprConvexSupport(int pairIndex,int bodyIndex, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf,
- b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData,
- b3ConstArray(b3Collidable_t) cpuCollidables,
- b3ConstArray(b3Float4) cpuVertices,
- __global b3Float4* sepAxis,
- const b3Float4* _dir, b3Float4* outp, int logme)
+B3_STATIC void b3MprConvexSupport(int pairIndex, int bodyIndex, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf,
+ b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData,
+ b3ConstArray(b3Collidable_t) cpuCollidables,
+ b3ConstArray(b3Float4) cpuVertices,
+ __global b3Float4 *sepAxis,
+ const b3Float4 *_dir, b3Float4 *outp, int logme)
{
//dir is in worldspace, move to local space
-
+
b3Float4 pos = cpuBodyBuf[bodyIndex].m_pos;
b3Quat orn = cpuBodyBuf[bodyIndex].m_quat;
-
- b3Float4 dir = b3MakeFloat4((*_dir).x,(*_dir).y,(*_dir).z,0.f);
-
- const b3Float4 localDir = b3QuatRotate(b3QuatInverse(orn),dir);
-
+
+ b3Float4 dir = b3MakeFloat4((*_dir).x, (*_dir).y, (*_dir).z, 0.f);
+
+ const b3Float4 localDir = b3QuatRotate(b3QuatInverse(orn), dir);
//find local support vertex
int colIndex = cpuBodyBuf[bodyIndex].m_collidableIdx;
-
- b3Assert(cpuCollidables[colIndex].m_shapeType==SHAPE_CONVEX_HULL);
- __global const b3ConvexPolyhedronData_t* hull = &cpuConvexData[cpuCollidables[colIndex].m_shapeIndex];
-
+
+ b3Assert(cpuCollidables[colIndex].m_shapeType == SHAPE_CONVEX_HULL);
+ __global const b3ConvexPolyhedronData_t *hull = &cpuConvexData[cpuCollidables[colIndex].m_shapeIndex];
+
b3Float4 pInA;
if (logme)
{
-
-
- // b3Float4 supVec = b3MakeFloat4(0,0,0,0);
+ // b3Float4 supVec = b3MakeFloat4(0,0,0,0);
float maxDot = -B3_LARGE_FLOAT;
- if( 0 < hull->m_numVertices )
+ if (0 < hull->m_numVertices)
{
const b3Float4 scaled = localDir;
int index = b3MaxDot(scaled, &cpuVertices[hull->m_vertexOffset], hull->m_numVertices, &maxDot);
- pInA = cpuVertices[hull->m_vertexOffset+index];
-
+ pInA = cpuVertices[hull->m_vertexOffset + index];
}
-
-
- } else
+ }
+ else
{
- pInA = b3LocalGetSupportVertex(localDir,hull,cpuVertices);
+ pInA = b3LocalGetSupportVertex(localDir, hull, cpuVertices);
}
//move vertex to world space
- *outp = b3TransformPoint(pInA,pos,orn);
-
+ *outp = b3TransformPoint(pInA, pos, orn);
}
-inline void b3MprSupport(int pairIndex,int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf,
- b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData,
- b3ConstArray(b3Collidable_t) cpuCollidables,
- b3ConstArray(b3Float4) cpuVertices,
- __global b3Float4* sepAxis,
- const b3Float4* _dir, b3MprSupport_t *supp)
+inline void b3MprSupport(int pairIndex, int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf,
+ b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData,
+ b3ConstArray(b3Collidable_t) cpuCollidables,
+ b3ConstArray(b3Float4) cpuVertices,
+ __global b3Float4 *sepAxis,
+ const b3Float4 *_dir, b3MprSupport_t *supp)
{
- b3Float4 dir;
+ b3Float4 dir;
dir = *_dir;
- b3MprConvexSupport(pairIndex,bodyIndexA,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices,sepAxis,&dir, &supp->v1,0);
- dir = *_dir*-1.f;
- b3MprConvexSupport(pairIndex,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices,sepAxis,&dir, &supp->v2,0);
- supp->v = supp->v1 - supp->v2;
+ b3MprConvexSupport(pairIndex, bodyIndexA, cpuBodyBuf, cpuConvexData, cpuCollidables, cpuVertices, sepAxis, &dir, &supp->v1, 0);
+ dir = *_dir * -1.f;
+ b3MprConvexSupport(pairIndex, bodyIndexB, cpuBodyBuf, cpuConvexData, cpuCollidables, cpuVertices, sepAxis, &dir, &supp->v2, 0);
+ supp->v = supp->v1 - supp->v2;
}
-
-
-
-
-
-
-
-
inline void b3FindOrigin(int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf, b3MprSupport_t *center)
{
-
- center->v1 = cpuBodyBuf[bodyIndexA].m_pos;
+ center->v1 = cpuBodyBuf[bodyIndexA].m_pos;
center->v2 = cpuBodyBuf[bodyIndexB].m_pos;
- center->v = center->v1 - center->v2;
+ center->v = center->v1 - center->v2;
}
inline void b3MprVec3Set(b3Float4 *v, float x, float y, float z)
@@ -243,48 +212,45 @@ inline void b3MprVec3Set(b3Float4 *v, float x, float y, float z)
inline void b3MprVec3Add(b3Float4 *v, const b3Float4 *w)
{
- (*v).x += (*w).x;
- (*v).y += (*w).y;
- (*v).z += (*w).z;
+ (*v).x += (*w).x;
+ (*v).y += (*w).y;
+ (*v).z += (*w).z;
}
inline void b3MprVec3Copy(b3Float4 *v, const b3Float4 *w)
{
- *v = *w;
+ *v = *w;
}
inline void b3MprVec3Scale(b3Float4 *d, float k)
{
- *d *= k;
+ *d *= k;
}
inline float b3MprVec3Dot(const b3Float4 *a, const b3Float4 *b)
{
- float dot;
+ float dot;
- dot = b3Dot3F4(*a,*b);
- return dot;
+ dot = b3Dot3F4(*a, *b);
+ return dot;
}
-
inline float b3MprVec3Len2(const b3Float4 *v)
{
- return b3MprVec3Dot(v, v);
+ return b3MprVec3Dot(v, v);
}
inline void b3MprVec3Normalize(b3Float4 *d)
{
- float k = 1.f / B3_MPR_SQRT(b3MprVec3Len2(d));
- b3MprVec3Scale(d, k);
+ float k = 1.f / B3_MPR_SQRT(b3MprVec3Len2(d));
+ b3MprVec3Scale(d, k);
}
inline void b3MprVec3Cross(b3Float4 *d, const b3Float4 *a, const b3Float4 *b)
{
- *d = b3Cross3(*a,*b);
-
+ *d = b3Cross3(*a, *b);
}
-
inline void b3MprVec3Sub2(b3Float4 *d, const b3Float4 *v, const b3Float4 *w)
{
*d = *v - *w;
@@ -292,629 +258,631 @@ inline void b3MprVec3Sub2(b3Float4 *d, const b3Float4 *v, const b3Float4 *w)
inline void b3PortalDir(const b3MprSimplex_t *portal, b3Float4 *dir)
{
- b3Float4 v2v1, v3v1;
+ b3Float4 v2v1, v3v1;
- b3MprVec3Sub2(&v2v1, &b3MprSimplexPoint(portal, 2)->v,
- &b3MprSimplexPoint(portal, 1)->v);
- b3MprVec3Sub2(&v3v1, &b3MprSimplexPoint(portal, 3)->v,
- &b3MprSimplexPoint(portal, 1)->v);
- b3MprVec3Cross(dir, &v2v1, &v3v1);
- b3MprVec3Normalize(dir);
+ b3MprVec3Sub2(&v2v1, &b3MprSimplexPoint(portal, 2)->v,
+ &b3MprSimplexPoint(portal, 1)->v);
+ b3MprVec3Sub2(&v3v1, &b3MprSimplexPoint(portal, 3)->v,
+ &b3MprSimplexPoint(portal, 1)->v);
+ b3MprVec3Cross(dir, &v2v1, &v3v1);
+ b3MprVec3Normalize(dir);
}
-
inline int portalEncapsulesOrigin(const b3MprSimplex_t *portal,
- const b3Float4 *dir)
+ const b3Float4 *dir)
{
- float dot;
- dot = b3MprVec3Dot(dir, &b3MprSimplexPoint(portal, 1)->v);
- return b3MprIsZero(dot) || dot > 0.f;
+ float dot;
+ dot = b3MprVec3Dot(dir, &b3MprSimplexPoint(portal, 1)->v);
+ return b3MprIsZero(dot) || dot > 0.f;
}
inline int portalReachTolerance(const b3MprSimplex_t *portal,
- const b3MprSupport_t *v4,
- const b3Float4 *dir)
+ const b3MprSupport_t *v4,
+ const b3Float4 *dir)
{
- float dv1, dv2, dv3, dv4;
- float dot1, dot2, dot3;
+ float dv1, dv2, dv3, dv4;
+ float dot1, dot2, dot3;
- // find the smallest dot product of dir and {v1-v4, v2-v4, v3-v4}
+ // find the smallest dot product of dir and {v1-v4, v2-v4, v3-v4}
- dv1 = b3MprVec3Dot(&b3MprSimplexPoint(portal, 1)->v, dir);
- dv2 = b3MprVec3Dot(&b3MprSimplexPoint(portal, 2)->v, dir);
- dv3 = b3MprVec3Dot(&b3MprSimplexPoint(portal, 3)->v, dir);
- dv4 = b3MprVec3Dot(&v4->v, dir);
+ dv1 = b3MprVec3Dot(&b3MprSimplexPoint(portal, 1)->v, dir);
+ dv2 = b3MprVec3Dot(&b3MprSimplexPoint(portal, 2)->v, dir);
+ dv3 = b3MprVec3Dot(&b3MprSimplexPoint(portal, 3)->v, dir);
+ dv4 = b3MprVec3Dot(&v4->v, dir);
- dot1 = dv4 - dv1;
- dot2 = dv4 - dv2;
- dot3 = dv4 - dv3;
+ dot1 = dv4 - dv1;
+ dot2 = dv4 - dv2;
+ dot3 = dv4 - dv3;
- dot1 = B3_MPR_FMIN(dot1, dot2);
- dot1 = B3_MPR_FMIN(dot1, dot3);
+ dot1 = B3_MPR_FMIN(dot1, dot2);
+ dot1 = B3_MPR_FMIN(dot1, dot3);
- return b3MprEq(dot1, B3_MPR_TOLERANCE) || dot1 < B3_MPR_TOLERANCE;
+ return b3MprEq(dot1, B3_MPR_TOLERANCE) || dot1 < B3_MPR_TOLERANCE;
}
-inline int portalCanEncapsuleOrigin(const b3MprSimplex_t *portal,
- const b3MprSupport_t *v4,
- const b3Float4 *dir)
+inline int portalCanEncapsuleOrigin(const b3MprSimplex_t *portal,
+ const b3MprSupport_t *v4,
+ const b3Float4 *dir)
{
- float dot;
- dot = b3MprVec3Dot(&v4->v, dir);
- return b3MprIsZero(dot) || dot > 0.f;
+ float dot;
+ dot = b3MprVec3Dot(&v4->v, dir);
+ return b3MprIsZero(dot) || dot > 0.f;
}
inline void b3ExpandPortal(b3MprSimplex_t *portal,
- const b3MprSupport_t *v4)
-{
- float dot;
- b3Float4 v4v0;
-
- b3MprVec3Cross(&v4v0, &v4->v, &b3MprSimplexPoint(portal, 0)->v);
- dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 1)->v, &v4v0);
- if (dot > 0.f){
- dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 2)->v, &v4v0);
- if (dot > 0.f){
- b3MprSimplexSet(portal, 1, v4);
- }else{
- b3MprSimplexSet(portal, 3, v4);
- }
- }else{
- dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 3)->v, &v4v0);
- if (dot > 0.f){
- b3MprSimplexSet(portal, 2, v4);
- }else{
- b3MprSimplexSet(portal, 1, v4);
- }
- }
-}
-
-
-
-B3_STATIC int b3DiscoverPortal(int pairIndex, int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf,
- b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData,
- b3ConstArray(b3Collidable_t) cpuCollidables,
- b3ConstArray(b3Float4) cpuVertices,
- __global b3Float4* sepAxis,
- __global int* hasSepAxis,
- b3MprSimplex_t *portal)
-{
- b3Float4 dir, va, vb;
- float dot;
- int cont;
-
-
-
- // vertex 0 is center of portal
- b3FindOrigin(bodyIndexA,bodyIndexB,cpuBodyBuf, b3MprSimplexPointW(portal, 0));
- // vertex 0 is center of portal
- b3MprSimplexSetSize(portal, 1);
-
-
-
- b3Float4 zero = b3MakeFloat4(0,0,0,0);
- b3Float4* b3mpr_vec3_origin = &zero;
-
- if (b3MprVec3Eq(&b3MprSimplexPoint(portal, 0)->v, b3mpr_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...
- b3MprVec3Set(&va, FLT_EPSILON * 10.f, 0.f, 0.f);
- b3MprVec3Add(&b3MprSimplexPointW(portal, 0)->v, &va);
- }
-
-
- // vertex 1 = support in direction of origin
- b3MprVec3Copy(&dir, &b3MprSimplexPoint(portal, 0)->v);
- b3MprVec3Scale(&dir, -1.f);
- b3MprVec3Normalize(&dir);
-
-
- b3MprSupport(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&dir, b3MprSimplexPointW(portal, 1));
-
- b3MprSimplexSetSize(portal, 2);
-
- // test if origin isn't outside of v1
- dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 1)->v, &dir);
-
-
- if (b3MprIsZero(dot) || dot < 0.f)
- return -1;
-
-
- // vertex 2
- b3MprVec3Cross(&dir, &b3MprSimplexPoint(portal, 0)->v,
- &b3MprSimplexPoint(portal, 1)->v);
- if (b3MprIsZero(b3MprVec3Len2(&dir))){
- if (b3MprVec3Eq(&b3MprSimplexPoint(portal, 1)->v, b3mpr_vec3_origin)){
- // origin lies on v1
- return 1;
- }else{
- // origin lies on v0-v1 segment
- return 2;
- }
- }
-
- b3MprVec3Normalize(&dir);
- b3MprSupport(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&dir, b3MprSimplexPointW(portal, 2));
-
- dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 2)->v, &dir);
- if (b3MprIsZero(dot) || dot < 0.f)
- return -1;
-
- b3MprSimplexSetSize(portal, 3);
-
- // vertex 3 direction
- b3MprVec3Sub2(&va, &b3MprSimplexPoint(portal, 1)->v,
- &b3MprSimplexPoint(portal, 0)->v);
- b3MprVec3Sub2(&vb, &b3MprSimplexPoint(portal, 2)->v,
- &b3MprSimplexPoint(portal, 0)->v);
- b3MprVec3Cross(&dir, &va, &vb);
- b3MprVec3Normalize(&dir);
-
- // it is better to form portal faces to be oriented "outside" origin
- dot = b3MprVec3Dot(&dir, &b3MprSimplexPoint(portal, 0)->v);
- if (dot > 0.f){
- b3MprSimplexSwap(portal, 1, 2);
- b3MprVec3Scale(&dir, -1.f);
- }
-
- while (b3MprSimplexSize(portal) < 4){
- b3MprSupport(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&dir, b3MprSimplexPointW(portal, 3));
-
- dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 3)->v, &dir);
- if (b3MprIsZero(dot) || dot < 0.f)
- return -1;
-
- cont = 0;
-
- // test if origin is outside (v1, v0, v3) - set v2 as v3 and
- // continue
- b3MprVec3Cross(&va, &b3MprSimplexPoint(portal, 1)->v,
- &b3MprSimplexPoint(portal, 3)->v);
- dot = b3MprVec3Dot(&va, &b3MprSimplexPoint(portal, 0)->v);
- if (dot < 0.f && !b3MprIsZero(dot)){
- b3MprSimplexSet(portal, 2, b3MprSimplexPoint(portal, 3));
- cont = 1;
- }
-
- if (!cont){
- // test if origin is outside (v3, v0, v2) - set v1 as v3 and
- // continue
- b3MprVec3Cross(&va, &b3MprSimplexPoint(portal, 3)->v,
- &b3MprSimplexPoint(portal, 2)->v);
- dot = b3MprVec3Dot(&va, &b3MprSimplexPoint(portal, 0)->v);
- if (dot < 0.f && !b3MprIsZero(dot)){
- b3MprSimplexSet(portal, 1, b3MprSimplexPoint(portal, 3));
- cont = 1;
- }
- }
-
- if (cont){
- b3MprVec3Sub2(&va, &b3MprSimplexPoint(portal, 1)->v,
- &b3MprSimplexPoint(portal, 0)->v);
- b3MprVec3Sub2(&vb, &b3MprSimplexPoint(portal, 2)->v,
- &b3MprSimplexPoint(portal, 0)->v);
- b3MprVec3Cross(&dir, &va, &vb);
- b3MprVec3Normalize(&dir);
- }else{
- b3MprSimplexSetSize(portal, 4);
- }
- }
-
- return 0;
-}
-
-
-B3_STATIC int b3RefinePortal(int pairIndex,int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf,
- b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData,
- b3ConstArray(b3Collidable_t) cpuCollidables,
- b3ConstArray(b3Float4) cpuVertices,
- __global b3Float4* sepAxis,
- b3MprSimplex_t *portal)
-{
- b3Float4 dir;
- b3MprSupport_t v4;
-
- for (int i=0;i<B3_MPR_MAX_ITERATIONS;i++)
- //while (1)
+ const b3MprSupport_t *v4)
+{
+ float dot;
+ b3Float4 v4v0;
+
+ b3MprVec3Cross(&v4v0, &v4->v, &b3MprSimplexPoint(portal, 0)->v);
+ dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 1)->v, &v4v0);
+ if (dot > 0.f)
{
- // compute direction outside the portal (from v0 throught v1,v2,v3
- // face)
- b3PortalDir(portal, &dir);
+ dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 2)->v, &v4v0);
+ if (dot > 0.f)
+ {
+ b3MprSimplexSet(portal, 1, v4);
+ }
+ else
+ {
+ b3MprSimplexSet(portal, 3, v4);
+ }
+ }
+ else
+ {
+ dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 3)->v, &v4v0);
+ if (dot > 0.f)
+ {
+ b3MprSimplexSet(portal, 2, v4);
+ }
+ else
+ {
+ b3MprSimplexSet(portal, 1, v4);
+ }
+ }
+}
- // test if origin is inside the portal
- if (portalEncapsulesOrigin(portal, &dir))
- return 0;
+B3_STATIC int b3DiscoverPortal(int pairIndex, int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf,
+ b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData,
+ b3ConstArray(b3Collidable_t) cpuCollidables,
+ b3ConstArray(b3Float4) cpuVertices,
+ __global b3Float4 *sepAxis,
+ __global int *hasSepAxis,
+ b3MprSimplex_t *portal)
+{
+ b3Float4 dir, va, vb;
+ float dot;
+ int cont;
- // get next support point
-
- b3MprSupport(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&dir, &v4);
+ // vertex 0 is center of portal
+ b3FindOrigin(bodyIndexA, bodyIndexB, cpuBodyBuf, b3MprSimplexPointW(portal, 0));
+ // vertex 0 is center of portal
+ b3MprSimplexSetSize(portal, 1);
+ b3Float4 zero = b3MakeFloat4(0, 0, 0, 0);
+ b3Float4 *b3mpr_vec3_origin = &zero;
- // 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))
+ if (b3MprVec3Eq(&b3MprSimplexPoint(portal, 0)->v, b3mpr_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...
+ b3MprVec3Set(&va, FLT_EPSILON * 10.f, 0.f, 0.f);
+ b3MprVec3Add(&b3MprSimplexPointW(portal, 0)->v, &va);
+ }
+
+ // vertex 1 = support in direction of origin
+ b3MprVec3Copy(&dir, &b3MprSimplexPoint(portal, 0)->v);
+ b3MprVec3Scale(&dir, -1.f);
+ b3MprVec3Normalize(&dir);
+
+ b3MprSupport(pairIndex, bodyIndexA, bodyIndexB, cpuBodyBuf, cpuConvexData, cpuCollidables, cpuVertices, sepAxis, &dir, b3MprSimplexPointW(portal, 1));
+
+ b3MprSimplexSetSize(portal, 2);
+
+ // test if origin isn't outside of v1
+ dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 1)->v, &dir);
+
+ if (b3MprIsZero(dot) || dot < 0.f)
+ return -1;
+
+ // vertex 2
+ b3MprVec3Cross(&dir, &b3MprSimplexPoint(portal, 0)->v,
+ &b3MprSimplexPoint(portal, 1)->v);
+ if (b3MprIsZero(b3MprVec3Len2(&dir)))
+ {
+ if (b3MprVec3Eq(&b3MprSimplexPoint(portal, 1)->v, b3mpr_vec3_origin))
{
- return -1;
- }
+ // origin lies on v1
+ return 1;
+ }
+ else
+ {
+ // origin lies on v0-v1 segment
+ return 2;
+ }
+ }
+
+ b3MprVec3Normalize(&dir);
+ b3MprSupport(pairIndex, bodyIndexA, bodyIndexB, cpuBodyBuf, cpuConvexData, cpuCollidables, cpuVertices, sepAxis, &dir, b3MprSimplexPointW(portal, 2));
+
+ dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 2)->v, &dir);
+ if (b3MprIsZero(dot) || dot < 0.f)
+ return -1;
+
+ b3MprSimplexSetSize(portal, 3);
+
+ // vertex 3 direction
+ b3MprVec3Sub2(&va, &b3MprSimplexPoint(portal, 1)->v,
+ &b3MprSimplexPoint(portal, 0)->v);
+ b3MprVec3Sub2(&vb, &b3MprSimplexPoint(portal, 2)->v,
+ &b3MprSimplexPoint(portal, 0)->v);
+ b3MprVec3Cross(&dir, &va, &vb);
+ b3MprVec3Normalize(&dir);
+
+ // it is better to form portal faces to be oriented "outside" origin
+ dot = b3MprVec3Dot(&dir, &b3MprSimplexPoint(portal, 0)->v);
+ if (dot > 0.f)
+ {
+ b3MprSimplexSwap(portal, 1, 2);
+ b3MprVec3Scale(&dir, -1.f);
+ }
+
+ while (b3MprSimplexSize(portal) < 4)
+ {
+ b3MprSupport(pairIndex, bodyIndexA, bodyIndexB, cpuBodyBuf, cpuConvexData, cpuCollidables, cpuVertices, sepAxis, &dir, b3MprSimplexPointW(portal, 3));
- // v1-v2-v3 triangle must be rearranged to face outside Minkowski
- // difference (direction from v0).
- b3ExpandPortal(portal, &v4);
- }
+ dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 3)->v, &dir);
+ if (b3MprIsZero(dot) || dot < 0.f)
+ return -1;
- return -1;
+ cont = 0;
+
+ // test if origin is outside (v1, v0, v3) - set v2 as v3 and
+ // continue
+ b3MprVec3Cross(&va, &b3MprSimplexPoint(portal, 1)->v,
+ &b3MprSimplexPoint(portal, 3)->v);
+ dot = b3MprVec3Dot(&va, &b3MprSimplexPoint(portal, 0)->v);
+ if (dot < 0.f && !b3MprIsZero(dot))
+ {
+ b3MprSimplexSet(portal, 2, b3MprSimplexPoint(portal, 3));
+ cont = 1;
+ }
+
+ if (!cont)
+ {
+ // test if origin is outside (v3, v0, v2) - set v1 as v3 and
+ // continue
+ b3MprVec3Cross(&va, &b3MprSimplexPoint(portal, 3)->v,
+ &b3MprSimplexPoint(portal, 2)->v);
+ dot = b3MprVec3Dot(&va, &b3MprSimplexPoint(portal, 0)->v);
+ if (dot < 0.f && !b3MprIsZero(dot))
+ {
+ b3MprSimplexSet(portal, 1, b3MprSimplexPoint(portal, 3));
+ cont = 1;
+ }
+ }
+
+ if (cont)
+ {
+ b3MprVec3Sub2(&va, &b3MprSimplexPoint(portal, 1)->v,
+ &b3MprSimplexPoint(portal, 0)->v);
+ b3MprVec3Sub2(&vb, &b3MprSimplexPoint(portal, 2)->v,
+ &b3MprSimplexPoint(portal, 0)->v);
+ b3MprVec3Cross(&dir, &va, &vb);
+ b3MprVec3Normalize(&dir);
+ }
+ else
+ {
+ b3MprSimplexSetSize(portal, 4);
+ }
+ }
+
+ return 0;
}
-B3_STATIC void b3FindPos(const b3MprSimplex_t *portal, b3Float4 *pos)
+B3_STATIC int b3RefinePortal(int pairIndex, int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf,
+ b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData,
+ b3ConstArray(b3Collidable_t) cpuCollidables,
+ b3ConstArray(b3Float4) cpuVertices,
+ __global b3Float4 *sepAxis,
+ b3MprSimplex_t *portal)
{
+ b3Float4 dir;
+ b3MprSupport_t v4;
- b3Float4 zero = b3MakeFloat4(0,0,0,0);
- b3Float4* b3mpr_vec3_origin = &zero;
+ for (int i = 0; i < B3_MPR_MAX_ITERATIONS; i++)
+ //while (1)
+ {
+ // compute direction outside the portal (from v0 throught v1,v2,v3
+ // face)
+ b3PortalDir(portal, &dir);
- b3Float4 dir;
- size_t i;
- float b[4], sum, inv;
- b3Float4 vec, p1, p2;
+ // test if origin is inside the portal
+ if (portalEncapsulesOrigin(portal, &dir))
+ return 0;
- b3PortalDir(portal, &dir);
+ // get next support point
- // use barycentric coordinates of tetrahedron to find origin
- b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 1)->v,
- &b3MprSimplexPoint(portal, 2)->v);
- b[0] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 3)->v);
+ b3MprSupport(pairIndex, bodyIndexA, bodyIndexB, cpuBodyBuf, cpuConvexData, cpuCollidables, cpuVertices, sepAxis, &dir, &v4);
- b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 3)->v,
- &b3MprSimplexPoint(portal, 2)->v);
- b[1] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 0)->v);
+ // 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))
+ {
+ return -1;
+ }
- b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 0)->v,
- &b3MprSimplexPoint(portal, 1)->v);
- b[2] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 3)->v);
+ // v1-v2-v3 triangle must be rearranged to face outside Minkowski
+ // difference (direction from v0).
+ b3ExpandPortal(portal, &v4);
+ }
- b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 2)->v,
- &b3MprSimplexPoint(portal, 1)->v);
- b[3] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 0)->v);
+ return -1;
+}
+
+B3_STATIC void b3FindPos(const b3MprSimplex_t *portal, b3Float4 *pos)
+{
+ b3Float4 zero = b3MakeFloat4(0, 0, 0, 0);
+ b3Float4 *b3mpr_vec3_origin = &zero;
+
+ b3Float4 dir;
+ size_t i;
+ float b[4], sum, inv;
+ b3Float4 vec, p1, p2;
+
+ b3PortalDir(portal, &dir);
+
+ // use barycentric coordinates of tetrahedron to find origin
+ b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 1)->v,
+ &b3MprSimplexPoint(portal, 2)->v);
+ b[0] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 3)->v);
+
+ b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 3)->v,
+ &b3MprSimplexPoint(portal, 2)->v);
+ b[1] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 0)->v);
+
+ b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 0)->v,
+ &b3MprSimplexPoint(portal, 1)->v);
+ b[2] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 3)->v);
+
+ b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 2)->v,
+ &b3MprSimplexPoint(portal, 1)->v);
+ b[3] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 0)->v);
sum = b[0] + b[1] + b[2] + b[3];
- if (b3MprIsZero(sum) || sum < 0.f){
+ if (b3MprIsZero(sum) || sum < 0.f)
+ {
b[0] = 0.f;
- b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 2)->v,
- &b3MprSimplexPoint(portal, 3)->v);
- b[1] = b3MprVec3Dot(&vec, &dir);
- b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 3)->v,
- &b3MprSimplexPoint(portal, 1)->v);
- b[2] = b3MprVec3Dot(&vec, &dir);
- b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 1)->v,
- &b3MprSimplexPoint(portal, 2)->v);
- b[3] = b3MprVec3Dot(&vec, &dir);
+ b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 2)->v,
+ &b3MprSimplexPoint(portal, 3)->v);
+ b[1] = b3MprVec3Dot(&vec, &dir);
+ b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 3)->v,
+ &b3MprSimplexPoint(portal, 1)->v);
+ b[2] = b3MprVec3Dot(&vec, &dir);
+ b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 1)->v,
+ &b3MprSimplexPoint(portal, 2)->v);
+ b[3] = b3MprVec3Dot(&vec, &dir);
sum = b[1] + b[2] + b[3];
}
inv = 1.f / sum;
- b3MprVec3Copy(&p1, b3mpr_vec3_origin);
- b3MprVec3Copy(&p2, b3mpr_vec3_origin);
- for (i = 0; i < 4; i++){
- b3MprVec3Copy(&vec, &b3MprSimplexPoint(portal, i)->v1);
- b3MprVec3Scale(&vec, b[i]);
- b3MprVec3Add(&p1, &vec);
+ b3MprVec3Copy(&p1, b3mpr_vec3_origin);
+ b3MprVec3Copy(&p2, b3mpr_vec3_origin);
+ for (i = 0; i < 4; i++)
+ {
+ b3MprVec3Copy(&vec, &b3MprSimplexPoint(portal, i)->v1);
+ b3MprVec3Scale(&vec, b[i]);
+ b3MprVec3Add(&p1, &vec);
- b3MprVec3Copy(&vec, &b3MprSimplexPoint(portal, i)->v2);
- b3MprVec3Scale(&vec, b[i]);
- b3MprVec3Add(&p2, &vec);
- }
- b3MprVec3Scale(&p1, inv);
- b3MprVec3Scale(&p2, inv);
+ b3MprVec3Copy(&vec, &b3MprSimplexPoint(portal, i)->v2);
+ b3MprVec3Scale(&vec, b[i]);
+ b3MprVec3Add(&p2, &vec);
+ }
+ b3MprVec3Scale(&p1, inv);
+ b3MprVec3Scale(&p2, inv);
- b3MprVec3Copy(pos, &p1);
- b3MprVec3Add(pos, &p2);
- b3MprVec3Scale(pos, 0.5);
+ b3MprVec3Copy(pos, &p1);
+ b3MprVec3Add(pos, &p2);
+ b3MprVec3Scale(pos, 0.5);
}
inline float b3MprVec3Dist2(const b3Float4 *a, const b3Float4 *b)
{
- b3Float4 ab;
- b3MprVec3Sub2(&ab, a, b);
- return b3MprVec3Len2(&ab);
+ b3Float4 ab;
+ b3MprVec3Sub2(&ab, a, b);
+ return b3MprVec3Len2(&ab);
}
inline float _b3MprVec3PointSegmentDist2(const b3Float4 *P,
- const b3Float4 *x0,
- const b3Float4 *b,
- b3Float4 *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.
-
- float dist, t;
- b3Float4 d, a;
-
- // direction of segment
- b3MprVec3Sub2(&d, b, x0);
-
- // precompute vector from P to x0
- b3MprVec3Sub2(&a, x0, P);
-
- t = -1.f * b3MprVec3Dot(&a, &d);
- t /= b3MprVec3Len2(&d);
-
- if (t < 0.f || b3MprIsZero(t)){
- dist = b3MprVec3Dist2(x0, P);
- if (witness)
- b3MprVec3Copy(witness, x0);
- }else if (t > 1.f || b3MprEq(t, 1.f)){
- dist = b3MprVec3Dist2(b, P);
- if (witness)
- b3MprVec3Copy(witness, b);
- }else{
- if (witness){
- b3MprVec3Copy(witness, &d);
- b3MprVec3Scale(witness, t);
- b3MprVec3Add(witness, x0);
- dist = b3MprVec3Dist2(witness, P);
- }else{
- // recycling variables
- b3MprVec3Scale(&d, t);
- b3MprVec3Add(&d, &a);
- dist = b3MprVec3Len2(&d);
- }
- }
-
- return dist;
-}
+ const b3Float4 *x0,
+ const b3Float4 *b,
+ b3Float4 *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.
+
+ float dist, t;
+ b3Float4 d, a;
+
+ // direction of segment
+ b3MprVec3Sub2(&d, b, x0);
+
+ // precompute vector from P to x0
+ b3MprVec3Sub2(&a, x0, P);
+
+ t = -1.f * b3MprVec3Dot(&a, &d);
+ t /= b3MprVec3Len2(&d);
+
+ if (t < 0.f || b3MprIsZero(t))
+ {
+ dist = b3MprVec3Dist2(x0, P);
+ if (witness)
+ b3MprVec3Copy(witness, x0);
+ }
+ else if (t > 1.f || b3MprEq(t, 1.f))
+ {
+ dist = b3MprVec3Dist2(b, P);
+ if (witness)
+ b3MprVec3Copy(witness, b);
+ }
+ else
+ {
+ if (witness)
+ {
+ b3MprVec3Copy(witness, &d);
+ b3MprVec3Scale(witness, t);
+ b3MprVec3Add(witness, x0);
+ dist = b3MprVec3Dist2(witness, P);
+ }
+ else
+ {
+ // recycling variables
+ b3MprVec3Scale(&d, t);
+ b3MprVec3Add(&d, &a);
+ dist = b3MprVec3Len2(&d);
+ }
+ }
+ return dist;
+}
inline float b3MprVec3PointTriDist2(const b3Float4 *P,
- const b3Float4 *x0, const b3Float4 *B,
- const b3Float4 *C,
- b3Float4 *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.
-
- b3Float4 d1, d2, a;
- float u, v, w, p, q, r;
- float s, t, dist, dist2;
- b3Float4 witness2;
-
- b3MprVec3Sub2(&d1, B, x0);
- b3MprVec3Sub2(&d2, C, x0);
- b3MprVec3Sub2(&a, x0, P);
-
- u = b3MprVec3Dot(&a, &a);
- v = b3MprVec3Dot(&d1, &d1);
- w = b3MprVec3Dot(&d2, &d2);
- p = b3MprVec3Dot(&a, &d1);
- q = b3MprVec3Dot(&a, &d2);
- r = b3MprVec3Dot(&d1, &d2);
-
- s = (q * r - w * p) / (w * v - r * r);
- t = (-s * r - q) / w;
-
- if ((b3MprIsZero(s) || s > 0.f)
- && (b3MprEq(s, 1.f) || s < 1.f)
- && (b3MprIsZero(t) || t > 0.f)
- && (b3MprEq(t, 1.f) || t < 1.f)
- && (b3MprEq(t + s, 1.f) || t + s < 1.f)){
-
- if (witness){
- b3MprVec3Scale(&d1, s);
- b3MprVec3Scale(&d2, t);
- b3MprVec3Copy(witness, x0);
- b3MprVec3Add(witness, &d1);
- b3MprVec3Add(witness, &d2);
-
- dist = b3MprVec3Dist2(witness, P);
- }else{
- dist = s * s * v;
- dist += t * t * w;
- dist += 2.f * s * t * r;
- dist += 2.f * s * p;
- dist += 2.f * t * q;
- dist += u;
- }
- }else{
- dist = _b3MprVec3PointSegmentDist2(P, x0, B, witness);
-
- dist2 = _b3MprVec3PointSegmentDist2(P, x0, C, &witness2);
- if (dist2 < dist){
- dist = dist2;
- if (witness)
- b3MprVec3Copy(witness, &witness2);
- }
-
- dist2 = _b3MprVec3PointSegmentDist2(P, B, C, &witness2);
- if (dist2 < dist){
- dist = dist2;
- if (witness)
- b3MprVec3Copy(witness, &witness2);
- }
- }
-
- return dist;
-}
-
-
-B3_STATIC void b3FindPenetr(int pairIndex,int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf,
- b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData,
- b3ConstArray(b3Collidable_t) cpuCollidables,
- b3ConstArray(b3Float4) cpuVertices,
- __global b3Float4* sepAxis,
- b3MprSimplex_t *portal,
- float *depth, b3Float4 *pdir, b3Float4 *pos)
-{
- b3Float4 dir;
- b3MprSupport_t v4;
- unsigned long iterations;
-
- b3Float4 zero = b3MakeFloat4(0,0,0,0);
- b3Float4* b3mpr_vec3_origin = &zero;
-
-
- iterations = 1UL;
- for (int i=0;i<B3_MPR_MAX_ITERATIONS;i++)
- //while (1)
+ const b3Float4 *x0, const b3Float4 *B,
+ const b3Float4 *C,
+ b3Float4 *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.
+
+ b3Float4 d1, d2, a;
+ float u, v, w, p, q, r;
+ float s, t, dist, dist2;
+ b3Float4 witness2;
+
+ b3MprVec3Sub2(&d1, B, x0);
+ b3MprVec3Sub2(&d2, C, x0);
+ b3MprVec3Sub2(&a, x0, P);
+
+ u = b3MprVec3Dot(&a, &a);
+ v = b3MprVec3Dot(&d1, &d1);
+ w = b3MprVec3Dot(&d2, &d2);
+ p = b3MprVec3Dot(&a, &d1);
+ q = b3MprVec3Dot(&a, &d2);
+ r = b3MprVec3Dot(&d1, &d2);
+
+ s = (q * r - w * p) / (w * v - r * r);
+ t = (-s * r - q) / w;
+
+ if ((b3MprIsZero(s) || s > 0.f) && (b3MprEq(s, 1.f) || s < 1.f) && (b3MprIsZero(t) || t > 0.f) && (b3MprEq(t, 1.f) || t < 1.f) && (b3MprEq(t + s, 1.f) || t + s < 1.f))
+ {
+ if (witness)
+ {
+ b3MprVec3Scale(&d1, s);
+ b3MprVec3Scale(&d2, t);
+ b3MprVec3Copy(witness, x0);
+ b3MprVec3Add(witness, &d1);
+ b3MprVec3Add(witness, &d2);
+
+ dist = b3MprVec3Dist2(witness, P);
+ }
+ else
+ {
+ dist = s * s * v;
+ dist += t * t * w;
+ dist += 2.f * s * t * r;
+ dist += 2.f * s * p;
+ dist += 2.f * t * q;
+ dist += u;
+ }
+ }
+ else
+ {
+ dist = _b3MprVec3PointSegmentDist2(P, x0, B, witness);
+
+ dist2 = _b3MprVec3PointSegmentDist2(P, x0, C, &witness2);
+ if (dist2 < dist)
+ {
+ dist = dist2;
+ if (witness)
+ b3MprVec3Copy(witness, &witness2);
+ }
+
+ dist2 = _b3MprVec3PointSegmentDist2(P, B, C, &witness2);
+ if (dist2 < dist)
+ {
+ dist = dist2;
+ if (witness)
+ b3MprVec3Copy(witness, &witness2);
+ }
+ }
+
+ return dist;
+}
+
+B3_STATIC void b3FindPenetr(int pairIndex, int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf,
+ b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData,
+ b3ConstArray(b3Collidable_t) cpuCollidables,
+ b3ConstArray(b3Float4) cpuVertices,
+ __global b3Float4 *sepAxis,
+ b3MprSimplex_t *portal,
+ float *depth, b3Float4 *pdir, b3Float4 *pos)
+{
+ b3Float4 dir;
+ b3MprSupport_t v4;
+ unsigned long iterations;
+
+ b3Float4 zero = b3MakeFloat4(0, 0, 0, 0);
+ b3Float4 *b3mpr_vec3_origin = &zero;
+
+ iterations = 1UL;
+ for (int i = 0; i < B3_MPR_MAX_ITERATIONS; i++)
+ //while (1)
{
- // compute portal direction and obtain next support point
- b3PortalDir(portal, &dir);
-
- b3MprSupport(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&dir, &v4);
+ // compute portal direction and obtain next support point
+ b3PortalDir(portal, &dir);
+ b3MprSupport(pairIndex, bodyIndexA, bodyIndexB, cpuBodyBuf, cpuConvexData, cpuCollidables, cpuVertices, sepAxis, &dir, &v4);
- // reached tolerance -> find penetration info
- if (portalReachTolerance(portal, &v4, &dir)
- || iterations ==B3_MPR_MAX_ITERATIONS)
+ // reached tolerance -> find penetration info
+ if (portalReachTolerance(portal, &v4, &dir) || iterations == B3_MPR_MAX_ITERATIONS)
{
- *depth = b3MprVec3PointTriDist2(b3mpr_vec3_origin,&b3MprSimplexPoint(portal, 1)->v,&b3MprSimplexPoint(portal, 2)->v,&b3MprSimplexPoint(portal, 3)->v,pdir);
- *depth = B3_MPR_SQRT(*depth);
-
+ *depth = b3MprVec3PointTriDist2(b3mpr_vec3_origin, &b3MprSimplexPoint(portal, 1)->v, &b3MprSimplexPoint(portal, 2)->v, &b3MprSimplexPoint(portal, 3)->v, pdir);
+ *depth = B3_MPR_SQRT(*depth);
+
if (b3MprIsZero((*pdir).x) && b3MprIsZero((*pdir).y) && b3MprIsZero((*pdir).z))
{
-
*pdir = dir;
- }
+ }
b3MprVec3Normalize(pdir);
-
- // barycentric coordinates:
- b3FindPos(portal, pos);
+ // barycentric coordinates:
+ b3FindPos(portal, pos);
- return;
- }
+ return;
+ }
- b3ExpandPortal(portal, &v4);
+ b3ExpandPortal(portal, &v4);
- iterations++;
- }
+ iterations++;
+ }
}
-B3_STATIC void b3FindPenetrTouch(b3MprSimplex_t *portal,float *depth, b3Float4 *dir, b3Float4 *pos)
+B3_STATIC void b3FindPenetrTouch(b3MprSimplex_t *portal, float *depth, b3Float4 *dir, b3Float4 *pos)
{
- // Touching contact on portal's v1 - so depth is zero and direction
- // is unimportant and pos can be guessed
- *depth = 0.f;
- b3Float4 zero = b3MakeFloat4(0,0,0,0);
- b3Float4* b3mpr_vec3_origin = &zero;
-
+ // Touching contact on portal's v1 - so depth is zero and direction
+ // is unimportant and pos can be guessed
+ *depth = 0.f;
+ b3Float4 zero = b3MakeFloat4(0, 0, 0, 0);
+ b3Float4 *b3mpr_vec3_origin = &zero;
b3MprVec3Copy(dir, b3mpr_vec3_origin);
- b3MprVec3Copy(pos, &b3MprSimplexPoint(portal, 1)->v1);
- b3MprVec3Add(pos, &b3MprSimplexPoint(portal, 1)->v2);
- b3MprVec3Scale(pos, 0.5);
+ b3MprVec3Copy(pos, &b3MprSimplexPoint(portal, 1)->v1);
+ b3MprVec3Add(pos, &b3MprSimplexPoint(portal, 1)->v2);
+ b3MprVec3Scale(pos, 0.5);
}
B3_STATIC void b3FindPenetrSegment(b3MprSimplex_t *portal,
- float *depth, b3Float4 *dir, b3Float4 *pos)
+ float *depth, b3Float4 *dir, b3Float4 *pos)
{
-
- // Origin lies on v0-v1 segment.
- // Depth is distance to v1, direction also and position must be
- // computed
+ // Origin lies on v0-v1 segment.
+ // Depth is distance to v1, direction also and position must be
+ // computed
- b3MprVec3Copy(pos, &b3MprSimplexPoint(portal, 1)->v1);
- b3MprVec3Add(pos, &b3MprSimplexPoint(portal, 1)->v2);
- b3MprVec3Scale(pos, 0.5f);
+ b3MprVec3Copy(pos, &b3MprSimplexPoint(portal, 1)->v1);
+ b3MprVec3Add(pos, &b3MprSimplexPoint(portal, 1)->v2);
+ b3MprVec3Scale(pos, 0.5f);
-
- b3MprVec3Copy(dir, &b3MprSimplexPoint(portal, 1)->v);
- *depth = B3_MPR_SQRT(b3MprVec3Len2(dir));
- b3MprVec3Normalize(dir);
+ b3MprVec3Copy(dir, &b3MprSimplexPoint(portal, 1)->v);
+ *depth = B3_MPR_SQRT(b3MprVec3Len2(dir));
+ b3MprVec3Normalize(dir);
}
-
-
inline int b3MprPenetration(int pairIndex, int bodyIndexA, int bodyIndexB,
- b3ConstArray(b3RigidBodyData_t) cpuBodyBuf,
- b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData,
- b3ConstArray(b3Collidable_t) cpuCollidables,
- b3ConstArray(b3Float4) cpuVertices,
- __global b3Float4* sepAxis,
- __global int* hasSepAxis,
- float *depthOut, b3Float4* dirOut, b3Float4* posOut)
-{
-
- b3MprSimplex_t portal;
-
-
-// if (!hasSepAxis[pairIndex])
+ b3ConstArray(b3RigidBodyData_t) cpuBodyBuf,
+ b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData,
+ b3ConstArray(b3Collidable_t) cpuCollidables,
+ b3ConstArray(b3Float4) cpuVertices,
+ __global b3Float4 *sepAxis,
+ __global int *hasSepAxis,
+ float *depthOut, b3Float4 *dirOut, b3Float4 *posOut)
+{
+ b3MprSimplex_t portal;
+
+ // if (!hasSepAxis[pairIndex])
// return -1;
-
+
hasSepAxis[pairIndex] = 0;
- int res;
+ int res;
+
+ // Phase 1: Portal discovery
+ res = b3DiscoverPortal(pairIndex, bodyIndexA, bodyIndexB, cpuBodyBuf, cpuConvexData, cpuCollidables, cpuVertices, sepAxis, hasSepAxis, &portal);
- // Phase 1: Portal discovery
- res = b3DiscoverPortal(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices,sepAxis,hasSepAxis, &portal);
-
-
//sepAxis[pairIndex] = *pdir;//or -dir?
switch (res)
{
- case 0:
+ case 0:
{
// Phase 2: Portal refinement
-
- res = b3RefinePortal(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&portal);
+
+ res = b3RefinePortal(pairIndex, bodyIndexA, bodyIndexB, cpuBodyBuf, cpuConvexData, cpuCollidables, cpuVertices, sepAxis, &portal);
if (res < 0)
return -1;
// Phase 3. Penetration info
- b3FindPenetr(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&portal, depthOut, dirOut, posOut);
+ b3FindPenetr(pairIndex, bodyIndexA, bodyIndexB, cpuBodyBuf, cpuConvexData, cpuCollidables, cpuVertices, sepAxis, &portal, depthOut, dirOut, posOut);
hasSepAxis[pairIndex] = 1;
sepAxis[pairIndex] = -*dirOut;
break;
}
- case 1:
+ case 1:
{
- // Touching contact on portal's v1.
+ // Touching contact on portal's v1.
b3FindPenetrTouch(&portal, depthOut, dirOut, posOut);
break;
}
- case 2:
+ case 2:
{
-
- b3FindPenetrSegment( &portal, depthOut, dirOut, posOut);
+ b3FindPenetrSegment(&portal, depthOut, dirOut, posOut);
break;
}
- default:
+ default:
{
- hasSepAxis[pairIndex]=0;
+ hasSepAxis[pairIndex] = 0;
//if (res < 0)
//{
- // Origin isn't inside portal - no collision.
- return -1;
+ // Origin isn't inside portal - no collision.
+ return -1;
//}
}
};
-
+
return 0;
};
-
-
-#endif //B3_MPR_PENETRATION_H
+#endif //B3_MPR_PENETRATION_H
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3NewContactReduction.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3NewContactReduction.h
index 718222ebca..6e991e14b0 100644
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3NewContactReduction.h
+++ b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3NewContactReduction.h
@@ -8,189 +8,168 @@
#define GET_NPOINTS(x) (x).m_worldNormalOnB.w
-
int b3ExtractManifoldSequentialGlobal(__global const b3Float4* p, int nPoints, b3Float4ConstArg nearNormal, b3Int4* contactIdx)
{
- if( nPoints == 0 )
- return 0;
-
- if (nPoints <=4)
- return nPoints;
-
-
- if (nPoints >64)
- nPoints = 64;
-
- b3Float4 center = b3MakeFloat4(0,0,0,0);
+ if (nPoints == 0)
+ return 0;
+
+ if (nPoints <= 4)
+ return nPoints;
+
+ if (nPoints > 64)
+ nPoints = 64;
+
+ b3Float4 center = b3MakeFloat4(0, 0, 0, 0);
{
-
- for (int i=0;i<nPoints;i++)
+ for (int i = 0; i < nPoints; i++)
center += p[i];
center /= (float)nPoints;
}
-
-
-
+
// sample 4 directions
-
- b3Float4 aVector = p[0] - center;
- b3Float4 u = b3Cross( nearNormal, aVector );
- b3Float4 v = b3Cross( nearNormal, u );
- u = b3Normalized( u );
- v = b3Normalized( v );
-
-
- //keep point with deepest penetration
- float minW= FLT_MAX;
-
- int minIndex=-1;
-
- b3Float4 maxDots;
- maxDots.x = FLT_MIN;
- maxDots.y = FLT_MIN;
- maxDots.z = FLT_MIN;
- maxDots.w = FLT_MIN;
-
- // idx, distance
- for(int ie = 0; ie<nPoints; ie++ )
- {
- if (p[ie].w<minW)
- {
- minW = p[ie].w;
- minIndex=ie;
- }
- float f;
- b3Float4 r = p[ie]-center;
- f = b3Dot( u, r );
- if (f<maxDots.x)
- {
- maxDots.x = f;
- contactIdx[0].x = ie;
- }
-
- f = b3Dot( -u, r );
- if (f<maxDots.y)
- {
- maxDots.y = f;
- contactIdx[0].y = ie;
- }
-
-
- f = b3Dot( v, r );
- if (f<maxDots.z)
- {
- maxDots.z = f;
- contactIdx[0].z = ie;
- }
-
- f = b3Dot( -v, r );
- if (f<maxDots.w)
- {
- maxDots.w = f;
- contactIdx[0].w = ie;
- }
-
- }
-
- if (contactIdx[0].x != minIndex && contactIdx[0].y != minIndex && contactIdx[0].z != minIndex && contactIdx[0].w != minIndex)
- {
- //replace the first contact with minimum (todo: replace contact with least penetration)
- contactIdx[0].x = minIndex;
- }
-
- return 4;
-
+
+ b3Float4 aVector = p[0] - center;
+ b3Float4 u = b3Cross(nearNormal, aVector);
+ b3Float4 v = b3Cross(nearNormal, u);
+ u = b3Normalized(u);
+ v = b3Normalized(v);
+
+ //keep point with deepest penetration
+ float minW = FLT_MAX;
+
+ int minIndex = -1;
+
+ b3Float4 maxDots;
+ maxDots.x = FLT_MIN;
+ maxDots.y = FLT_MIN;
+ maxDots.z = FLT_MIN;
+ maxDots.w = FLT_MIN;
+
+ // idx, distance
+ for (int ie = 0; ie < nPoints; ie++)
+ {
+ if (p[ie].w < minW)
+ {
+ minW = p[ie].w;
+ minIndex = ie;
+ }
+ float f;
+ b3Float4 r = p[ie] - center;
+ f = b3Dot(u, r);
+ if (f < maxDots.x)
+ {
+ maxDots.x = f;
+ contactIdx[0].x = ie;
+ }
+
+ f = b3Dot(-u, r);
+ if (f < maxDots.y)
+ {
+ maxDots.y = f;
+ contactIdx[0].y = ie;
+ }
+
+ f = b3Dot(v, r);
+ if (f < maxDots.z)
+ {
+ maxDots.z = f;
+ contactIdx[0].z = ie;
+ }
+
+ f = b3Dot(-v, r);
+ if (f < maxDots.w)
+ {
+ maxDots.w = f;
+ contactIdx[0].w = ie;
+ }
+ }
+
+ if (contactIdx[0].x != minIndex && contactIdx[0].y != minIndex && contactIdx[0].z != minIndex && contactIdx[0].w != minIndex)
+ {
+ //replace the first contact with minimum (todo: replace contact with least penetration)
+ contactIdx[0].x = minIndex;
+ }
+
+ return 4;
}
-__kernel void b3NewContactReductionKernel( __global b3Int4* pairs,
- __global const b3RigidBodyData_t* rigidBodies,
- __global const b3Float4* separatingNormals,
- __global const int* hasSeparatingAxis,
- __global struct b3Contact4Data* globalContactsOut,
- __global b3Int4* clippingFaces,
- __global b3Float4* worldVertsB2,
- volatile __global int* nGlobalContactsOut,
- int vertexFaceCapacity,
- int contactCapacity,
- int numPairs,
- int pairIndex
- )
+__kernel void b3NewContactReductionKernel(__global b3Int4* pairs,
+ __global const b3RigidBodyData_t* rigidBodies,
+ __global const b3Float4* separatingNormals,
+ __global const int* hasSeparatingAxis,
+ __global struct b3Contact4Data* globalContactsOut,
+ __global b3Int4* clippingFaces,
+ __global b3Float4* worldVertsB2,
+ volatile __global int* nGlobalContactsOut,
+ int vertexFaceCapacity,
+ int contactCapacity,
+ int numPairs,
+ int pairIndex)
{
-// int i = get_global_id(0);
+ // int i = get_global_id(0);
//int pairIndex = i;
int i = pairIndex;
- b3Int4 contactIdx;
- contactIdx=b3MakeInt4(0,1,2,3);
-
- if (i<numPairs)
+ b3Int4 contactIdx;
+ contactIdx = b3MakeInt4(0, 1, 2, 3);
+
+ if (i < numPairs)
{
-
if (hasSeparatingAxis[i])
{
-
-
-
-
int nPoints = clippingFaces[pairIndex].w;
-
- if (nPoints>0)
- {
-
- __global b3Float4* pointsIn = &worldVertsB2[pairIndex*vertexFaceCapacity];
- b3Float4 normal = -separatingNormals[i];
-
- int nReducedContacts = b3ExtractManifoldSequentialGlobal(pointsIn, nPoints, normal, &contactIdx);
-
- int dstIdx;
- dstIdx = b3AtomicInc( nGlobalContactsOut);
-
-//#if 0
- b3Assert(dstIdx < contactCapacity);
+
+ if (nPoints > 0)
+ {
+ __global b3Float4* pointsIn = &worldVertsB2[pairIndex * vertexFaceCapacity];
+ b3Float4 normal = -separatingNormals[i];
+
+ int nReducedContacts = b3ExtractManifoldSequentialGlobal(pointsIn, nPoints, normal, &contactIdx);
+
+ int dstIdx;
+ dstIdx = b3AtomicInc(nGlobalContactsOut);
+
+ //#if 0
+ b3Assert(dstIdx < contactCapacity);
if (dstIdx < contactCapacity)
{
-
__global struct b3Contact4Data* c = &globalContactsOut[dstIdx];
c->m_worldNormalOnB = -normal;
- c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
+ c->m_restituitionCoeffCmp = (0.f * 0xffff);
+ c->m_frictionCoeffCmp = (0.7f * 0xffff);
c->m_batchIdx = pairIndex;
int bodyA = pairs[pairIndex].x;
int bodyB = pairs[pairIndex].y;
pairs[pairIndex].w = dstIdx;
- c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;
- c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;
- c->m_childIndexA =-1;
- c->m_childIndexB =-1;
-
- switch (nReducedContacts)
- {
- case 4:
- c->m_worldPosB[3] = pointsIn[contactIdx.w];
- case 3:
- c->m_worldPosB[2] = pointsIn[contactIdx.z];
- case 2:
- c->m_worldPosB[1] = pointsIn[contactIdx.y];
- case 1:
- c->m_worldPosB[0] = pointsIn[contactIdx.x];
- default:
- {
- }
- };
-
+ c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass == 0 ? -bodyA : bodyA;
+ c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass == 0 ? -bodyB : bodyB;
+ c->m_childIndexA = -1;
+ c->m_childIndexB = -1;
+
+ switch (nReducedContacts)
+ {
+ case 4:
+ c->m_worldPosB[3] = pointsIn[contactIdx.w];
+ case 3:
+ c->m_worldPosB[2] = pointsIn[contactIdx.z];
+ case 2:
+ c->m_worldPosB[1] = pointsIn[contactIdx.y];
+ case 1:
+ c->m_worldPosB[0] = pointsIn[contactIdx.x];
+ default:
+ {
+ }
+ };
+
GET_NPOINTS(*c) = nReducedContacts;
-
- }
-
-
-//#endif
-
- }// if (numContactsOut>0)
- }// if (hasSeparatingAxis[i])
- }// if (i<numPairs)
-
-
-
+ }
+
+ //#endif
+
+ } // if (numContactsOut>0)
+ } // if (hasSeparatingAxis[i])
+ } // if (i<numPairs)
}
#endif
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3QuantizedBvhNodeData.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3QuantizedBvhNodeData.h
index 3661e43cf1..ba796eac72 100644
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3QuantizedBvhNodeData.h
+++ b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3QuantizedBvhNodeData.h
@@ -14,57 +14,56 @@ typedef struct b3QuantizedBvhNodeData b3QuantizedBvhNodeData_t;
struct b3QuantizedBvhNodeData
{
//12 bytes
- unsigned short int m_quantizedAabbMin[3];
- unsigned short int m_quantizedAabbMax[3];
+ unsigned short int m_quantizedAabbMin[3];
+ unsigned short int m_quantizedAabbMax[3];
//4 bytes
- int m_escapeIndexOrTriangleIndex;
+ int m_escapeIndexOrTriangleIndex;
};
-inline int b3GetTriangleIndex(const b3QuantizedBvhNodeData* rootNode)
+inline int b3GetTriangleIndex(const b3QuantizedBvhNodeData* rootNode)
{
- unsigned int x=0;
- unsigned int y = (~(x&0))<<(31-B3_MAX_NUM_PARTS_IN_BITS);
+ unsigned int x = 0;
+ unsigned int y = (~(x & 0)) << (31 - B3_MAX_NUM_PARTS_IN_BITS);
// Get only the lower bits where the triangle index is stored
- return (rootNode->m_escapeIndexOrTriangleIndex&~(y));
+ return (rootNode->m_escapeIndexOrTriangleIndex & ~(y));
}
inline int b3IsLeaf(const b3QuantizedBvhNodeData* rootNode)
{
//skipindex is negative (internal node), triangleindex >=0 (leafnode)
- return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;
+ return (rootNode->m_escapeIndexOrTriangleIndex >= 0) ? 1 : 0;
}
-
+
inline int b3GetEscapeIndex(const b3QuantizedBvhNodeData* rootNode)
{
return -rootNode->m_escapeIndexOrTriangleIndex;
}
-inline void b3QuantizeWithClamp(unsigned short* out, b3Float4ConstArg point2,int isMax, b3Float4ConstArg bvhAabbMin, b3Float4ConstArg bvhAabbMax, b3Float4ConstArg bvhQuantization)
+inline void b3QuantizeWithClamp(unsigned short* out, b3Float4ConstArg point2, int isMax, b3Float4ConstArg bvhAabbMin, b3Float4ConstArg bvhAabbMax, b3Float4ConstArg bvhQuantization)
{
- b3Float4 clampedPoint = b3MaxFloat4(point2,bvhAabbMin);
- clampedPoint = b3MinFloat4 (clampedPoint, bvhAabbMax);
+ b3Float4 clampedPoint = b3MaxFloat4(point2, bvhAabbMin);
+ clampedPoint = b3MinFloat4(clampedPoint, bvhAabbMax);
b3Float4 v = (clampedPoint - bvhAabbMin) * bvhQuantization;
if (isMax)
{
- out[0] = (unsigned short) (((unsigned short)(v.x+1.f) | 1));
- out[1] = (unsigned short) (((unsigned short)(v.y+1.f) | 1));
- out[2] = (unsigned short) (((unsigned short)(v.z+1.f) | 1));
- } else
+ out[0] = (unsigned short)(((unsigned short)(v.x + 1.f) | 1));
+ out[1] = (unsigned short)(((unsigned short)(v.y + 1.f) | 1));
+ out[2] = (unsigned short)(((unsigned short)(v.z + 1.f) | 1));
+ }
+ else
{
- out[0] = (unsigned short) (((unsigned short)(v.x) & 0xfffe));
- out[1] = (unsigned short) (((unsigned short)(v.y) & 0xfffe));
- out[2] = (unsigned short) (((unsigned short)(v.z) & 0xfffe));
+ out[0] = (unsigned short)(((unsigned short)(v.x) & 0xfffe));
+ out[1] = (unsigned short)(((unsigned short)(v.y) & 0xfffe));
+ out[2] = (unsigned short)(((unsigned short)(v.z) & 0xfffe));
}
-
}
-
inline int b3TestQuantizedAabbAgainstQuantizedAabbSlow(
- const unsigned short int* aabbMin1,
- const unsigned short int* aabbMax1,
- const unsigned short int* aabbMin2,
- const unsigned short int* aabbMax2)
+ const unsigned short int* aabbMin1,
+ const unsigned short int* aabbMax1,
+ const unsigned short int* aabbMin2,
+ const unsigned short int* aabbMax2)
{
//int overlap = 1;
if (aabbMin1[0] > aabbMax2[0])
@@ -86,5 +85,4 @@ inline int b3TestQuantizedAabbAgainstQuantizedAabbSlow(
//return overlap;
}
-
-#endif //B3_QUANTIZED_BVH_NODE_H
+#endif //B3_QUANTIZED_BVH_NODE_H
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ReduceContacts.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ReduceContacts.h
index 35b5197006..c108255b9f 100644
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ReduceContacts.h
+++ b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ReduceContacts.h
@@ -3,95 +3,87 @@
inline int b3ReduceContacts(const b3Float4* p, int nPoints, const b3Float4& nearNormal, b3Int4* contactIdx)
{
- if( nPoints == 0 )
- return 0;
-
- if (nPoints <=4)
- return nPoints;
-
-
- if (nPoints >64)
- nPoints = 64;
-
- b3Float4 center = b3MakeFloat4(0,0,0,0);
+ if (nPoints == 0)
+ return 0;
+
+ if (nPoints <= 4)
+ return nPoints;
+
+ if (nPoints > 64)
+ nPoints = 64;
+
+ b3Float4 center = b3MakeFloat4(0, 0, 0, 0);
{
-
- for (int i=0;i<nPoints;i++)
+ for (int i = 0; i < nPoints; i++)
center += p[i];
center /= (float)nPoints;
}
-
-
-
+
// sample 4 directions
-
- b3Float4 aVector = p[0] - center;
- b3Float4 u = b3Cross3( nearNormal, aVector );
- b3Float4 v = b3Cross3( nearNormal, u );
- u = b3FastNormalized3( u );
- v = b3FastNormalized3( v );
-
-
- //keep point with deepest penetration
- float minW= FLT_MAX;
-
- int minIndex=-1;
-
- b3Float4 maxDots;
- maxDots.x = FLT_MIN;
- maxDots.y = FLT_MIN;
- maxDots.z = FLT_MIN;
- maxDots.w = FLT_MIN;
-
- // idx, distance
- for(int ie = 0; ie<nPoints; ie++ )
- {
- if (p[ie].w<minW)
- {
- minW = p[ie].w;
- minIndex=ie;
- }
- float f;
- b3Float4 r = p[ie]-center;
- f = b3Dot3F4( u, r );
- if (f<maxDots.x)
- {
- maxDots.x = f;
- contactIdx[0].x = ie;
- }
-
- f = b3Dot3F4( -u, r );
- if (f<maxDots.y)
- {
- maxDots.y = f;
- contactIdx[0].y = ie;
- }
-
-
- f = b3Dot3F4( v, r );
- if (f<maxDots.z)
- {
- maxDots.z = f;
- contactIdx[0].z = ie;
- }
-
- f = b3Dot3F4( -v, r );
- if (f<maxDots.w)
- {
- maxDots.w = f;
- contactIdx[0].w = ie;
- }
-
- }
-
- if (contactIdx[0].x != minIndex && contactIdx[0].y != minIndex && contactIdx[0].z != minIndex && contactIdx[0].w != minIndex)
- {
- //replace the first contact with minimum (todo: replace contact with least penetration)
- contactIdx[0].x = minIndex;
- }
-
- return 4;
-
+
+ b3Float4 aVector = p[0] - center;
+ b3Float4 u = b3Cross3(nearNormal, aVector);
+ b3Float4 v = b3Cross3(nearNormal, u);
+ u = b3FastNormalized3(u);
+ v = b3FastNormalized3(v);
+
+ //keep point with deepest penetration
+ float minW = FLT_MAX;
+
+ int minIndex = -1;
+
+ b3Float4 maxDots;
+ maxDots.x = FLT_MIN;
+ maxDots.y = FLT_MIN;
+ maxDots.z = FLT_MIN;
+ maxDots.w = FLT_MIN;
+
+ // idx, distance
+ for (int ie = 0; ie < nPoints; ie++)
+ {
+ if (p[ie].w < minW)
+ {
+ minW = p[ie].w;
+ minIndex = ie;
+ }
+ float f;
+ b3Float4 r = p[ie] - center;
+ f = b3Dot3F4(u, r);
+ if (f < maxDots.x)
+ {
+ maxDots.x = f;
+ contactIdx[0].x = ie;
+ }
+
+ f = b3Dot3F4(-u, r);
+ if (f < maxDots.y)
+ {
+ maxDots.y = f;
+ contactIdx[0].y = ie;
+ }
+
+ f = b3Dot3F4(v, r);
+ if (f < maxDots.z)
+ {
+ maxDots.z = f;
+ contactIdx[0].z = ie;
+ }
+
+ f = b3Dot3F4(-v, r);
+ if (f < maxDots.w)
+ {
+ maxDots.w = f;
+ contactIdx[0].w = ie;
+ }
+ }
+
+ if (contactIdx[0].x != minIndex && contactIdx[0].y != minIndex && contactIdx[0].z != minIndex && contactIdx[0].w != minIndex)
+ {
+ //replace the first contact with minimum (todo: replace contact with least penetration)
+ contactIdx[0].x = minIndex;
+ }
+
+ return 4;
}
-#endif //B3_REDUCE_CONTACTS_H
+#endif //B3_REDUCE_CONTACTS_H
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h
index 50632c871f..663e946fc1 100644
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h
+++ b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h
@@ -7,18 +7,17 @@
typedef struct b3RigidBodyData b3RigidBodyData_t;
-
struct b3RigidBodyData
{
- b3Float4 m_pos;
- b3Quat m_quat;
- b3Float4 m_linVel;
- b3Float4 m_angVel;
-
- int m_collidableIdx;
- float m_invMass;
- float m_restituitionCoeff;
- float m_frictionCoeff;
+ b3Float4 m_pos;
+ b3Quat m_quat;
+ b3Float4 m_linVel;
+ b3Float4 m_angVel;
+
+ int m_collidableIdx;
+ float m_invMass;
+ float m_restituitionCoeff;
+ float m_frictionCoeff;
};
typedef struct b3InertiaData b3InertiaData_t;
@@ -29,6 +28,4 @@ struct b3InertiaData
b3Mat3x3 m_initInvInertia;
};
-
-#endif //B3_RIGIDBODY_DATA_H
- \ No newline at end of file
+#endif //B3_RIGIDBODY_DATA_H
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3UpdateAabbs.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3UpdateAabbs.h
index 8d40d19a03..e0c3a5cf97 100644
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3UpdateAabbs.h
+++ b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3UpdateAabbs.h
@@ -1,40 +1,35 @@
#ifndef B3_UPDATE_AABBS_H
#define B3_UPDATE_AABBS_H
-
-
#include "Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h"
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
-
-
-void b3ComputeWorldAabb( int bodyId, __global const b3RigidBodyData_t* bodies, __global const b3Collidable_t* collidables, __global const b3Aabb_t* localShapeAABB, __global b3Aabb_t* worldAabbs)
+void b3ComputeWorldAabb(int bodyId, __global const b3RigidBodyData_t* bodies, __global const b3Collidable_t* collidables, __global const b3Aabb_t* localShapeAABB, __global b3Aabb_t* worldAabbs)
{
__global const b3RigidBodyData_t* body = &bodies[bodyId];
b3Float4 position = body->m_pos;
- b3Quat orientation = body->m_quat;
-
+ b3Quat orientation = body->m_quat;
+
int collidableIndex = body->m_collidableIdx;
int shapeIndex = collidables[collidableIndex].m_shapeIndex;
-
- if (shapeIndex>=0)
+
+ if (shapeIndex >= 0)
{
-
b3Aabb_t localAabb = localShapeAABB[collidableIndex];
b3Aabb_t worldAabb;
-
- b3Float4 aabbAMinOut,aabbAMaxOut;
+
+ b3Float4 aabbAMinOut, aabbAMaxOut;
float margin = 0.f;
- b3TransformAabb2(localAabb.m_minVec,localAabb.m_maxVec,margin,position,orientation,&aabbAMinOut,&aabbAMaxOut);
-
- worldAabb.m_minVec =aabbAMinOut;
+ b3TransformAabb2(localAabb.m_minVec, localAabb.m_maxVec, margin, position, orientation, &aabbAMinOut, &aabbAMaxOut);
+
+ worldAabb.m_minVec = aabbAMinOut;
worldAabb.m_minIndices[3] = bodyId;
worldAabb.m_maxVec = aabbAMaxOut;
- worldAabb.m_signedMaxIndices[3] = body[bodyId].m_invMass==0.f? 0 : 1;
+ worldAabb.m_signedMaxIndices[3] = body[bodyId].m_invMass == 0.f ? 0 : 1;
worldAabbs[bodyId] = worldAabb;
}
}
-#endif //B3_UPDATE_AABBS_H
+#endif //B3_UPDATE_AABBS_H
diff --git a/thirdparty/bullet/Bullet3Common/b3AlignedAllocator.cpp b/thirdparty/bullet/Bullet3Common/b3AlignedAllocator.cpp
index b98e2b4d33..d546d5e066 100644
--- a/thirdparty/bullet/Bullet3Common/b3AlignedAllocator.cpp
+++ b/thirdparty/bullet/Bullet3Common/b3AlignedAllocator.cpp
@@ -15,9 +15,11 @@ subject to the following restrictions:
#include "b3AlignedAllocator.h"
+#ifdef B3_ALLOCATOR_STATISTICS
int b3g_numAlignedAllocs = 0;
int b3g_numAlignedFree = 0;
-int b3g_totalBytesAlignedAllocs = 0;//detect memory leaks
+int b3g_totalBytesAlignedAllocs = 0; //detect memory leaks
+#endif
static void *b3AllocDefault(size_t size)
{
@@ -29,12 +31,10 @@ static void b3FreeDefault(void *ptr)
free(ptr);
}
-static b3AllocFunc* b3s_allocFunc = b3AllocDefault;
-static b3FreeFunc* b3s_freeFunc = b3FreeDefault;
-
-
+static b3AllocFunc *b3s_allocFunc = b3AllocDefault;
+static b3FreeFunc *b3s_freeFunc = b3FreeDefault;
-#if defined (B3_HAS_ALIGNED_ALLOCATOR)
+#if defined(B3_HAS_ALIGNED_ALLOCATOR)
#include <malloc.h>
static void *b3AlignedAllocDefault(size_t size, int alignment)
{
@@ -59,123 +59,128 @@ static inline void b3AlignedFreeDefault(void *ptr)
}
#else
-
-
-
-
static inline void *b3AlignedAllocDefault(size_t size, int alignment)
{
- void *ret;
- char *real;
- real = (char *)b3s_allocFunc(size + sizeof(void *) + (alignment-1));
- if (real) {
- ret = b3AlignPointer(real + sizeof(void *),alignment);
- *((void **)(ret)-1) = (void *)(real);
- } else {
- ret = (void *)(real);
- }
- return (ret);
+ void *ret;
+ char *real;
+ real = (char *)b3s_allocFunc(size + sizeof(void *) + (alignment - 1));
+ if (real)
+ {
+ ret = b3AlignPointer(real + sizeof(void *), alignment);
+ *((void **)(ret)-1) = (void *)(real);
+ }
+ else
+ {
+ ret = (void *)(real);
+ }
+ return (ret);
}
static inline void b3AlignedFreeDefault(void *ptr)
{
- void* real;
+ void *real;
- if (ptr) {
- real = *((void **)(ptr)-1);
- b3s_freeFunc(real);
- }
+ if (ptr)
+ {
+ real = *((void **)(ptr)-1);
+ b3s_freeFunc(real);
+ }
}
#endif
-
-static b3AlignedAllocFunc* b3s_alignedAllocFunc = b3AlignedAllocDefault;
-static b3AlignedFreeFunc* b3s_alignedFreeFunc = b3AlignedFreeDefault;
+static b3AlignedAllocFunc *b3s_alignedAllocFunc = b3AlignedAllocDefault;
+static b3AlignedFreeFunc *b3s_alignedFreeFunc = b3AlignedFreeDefault;
void b3AlignedAllocSetCustomAligned(b3AlignedAllocFunc *allocFunc, b3AlignedFreeFunc *freeFunc)
{
- b3s_alignedAllocFunc = allocFunc ? allocFunc : b3AlignedAllocDefault;
- b3s_alignedFreeFunc = freeFunc ? freeFunc : b3AlignedFreeDefault;
+ b3s_alignedAllocFunc = allocFunc ? allocFunc : b3AlignedAllocDefault;
+ b3s_alignedFreeFunc = freeFunc ? freeFunc : b3AlignedFreeDefault;
}
void b3AlignedAllocSetCustom(b3AllocFunc *allocFunc, b3FreeFunc *freeFunc)
{
- b3s_allocFunc = allocFunc ? allocFunc : b3AllocDefault;
- b3s_freeFunc = freeFunc ? freeFunc : b3FreeDefault;
+ b3s_allocFunc = allocFunc ? allocFunc : b3AllocDefault;
+ b3s_freeFunc = freeFunc ? freeFunc : b3FreeDefault;
}
#ifdef B3_DEBUG_MEMORY_ALLOCATIONS
//this generic allocator provides the total allocated number of bytes
#include <stdio.h>
-void* b3AlignedAllocInternal (size_t size, int alignment,int line,char* filename)
+void *b3AlignedAllocInternal(size_t size, int alignment, int line, char *filename)
{
- void *ret;
- char *real;
-
- b3g_totalBytesAlignedAllocs += size;
- b3g_numAlignedAllocs++;
-
-
- real = (char *)b3s_allocFunc(size + 2*sizeof(void *) + (alignment-1));
- if (real) {
- ret = (void*) b3AlignPointer(real + 2*sizeof(void *), alignment);
- *((void **)(ret)-1) = (void *)(real);
- *((int*)(ret)-2) = size;
-
- } else {
- ret = (void *)(real);//??
- }
+ void *ret;
+ char *real;
+#ifdef B3_ALLOCATOR_STATISTICS
+ b3g_totalBytesAlignedAllocs += size;
+ b3g_numAlignedAllocs++;
+#endif
+ real = (char *)b3s_allocFunc(size + 2 * sizeof(void *) + (alignment - 1));
+ if (real)
+ {
+ ret = (void *)b3AlignPointer(real + 2 * sizeof(void *), alignment);
+ *((void **)(ret)-1) = (void *)(real);
+ *((int *)(ret)-2) = size;
+ }
+ else
+ {
+ ret = (void *)(real); //??
+ }
- b3Printf("allocation#%d at address %x, from %s,line %d, size %d\n",b3g_numAlignedAllocs,real, filename,line,size);
+ b3Printf("allocation#%d at address %x, from %s,line %d, size %d\n", b3g_numAlignedAllocs, real, filename, line, size);
- int* ptr = (int*)ret;
- *ptr = 12;
- return (ret);
+ int *ptr = (int *)ret;
+ *ptr = 12;
+ return (ret);
}
-void b3AlignedFreeInternal (void* ptr,int line,char* filename)
+void b3AlignedFreeInternal(void *ptr, int line, char *filename)
{
+ void *real;
+#ifdef B3_ALLOCATOR_STATISTICS
+ b3g_numAlignedFree++;
+#endif
+ if (ptr)
+ {
+ real = *((void **)(ptr)-1);
+ int size = *((int *)(ptr)-2);
+#ifdef B3_ALLOCATOR_STATISTICS
+ b3g_totalBytesAlignedAllocs -= size;
+#endif
+ b3Printf("free #%d at address %x, from %s,line %d, size %d\n", b3g_numAlignedFree, real, filename, line, size);
- void* real;
- b3g_numAlignedFree++;
-
- if (ptr) {
- real = *((void **)(ptr)-1);
- int size = *((int*)(ptr)-2);
- b3g_totalBytesAlignedAllocs -= size;
-
- b3Printf("free #%d at address %x, from %s,line %d, size %d\n",b3g_numAlignedFree,real, filename,line,size);
-
- b3s_freeFunc(real);
- } else
- {
- b3Printf("NULL ptr\n");
- }
+ b3s_freeFunc(real);
+ }
+ else
+ {
+ b3Printf("NULL ptr\n");
+ }
}
-#else //B3_DEBUG_MEMORY_ALLOCATIONS
+#else //B3_DEBUG_MEMORY_ALLOCATIONS
-void* b3AlignedAllocInternal (size_t size, int alignment)
+void *b3AlignedAllocInternal(size_t size, int alignment)
{
+#ifdef B3_ALLOCATOR_STATISTICS
b3g_numAlignedAllocs++;
- void* ptr;
+#endif
+ void *ptr;
ptr = b3s_alignedAllocFunc(size, alignment);
-// b3Printf("b3AlignedAllocInternal %d, %x\n",size,ptr);
+ // b3Printf("b3AlignedAllocInternal %d, %x\n",size,ptr);
return ptr;
}
-void b3AlignedFreeInternal (void* ptr)
+void b3AlignedFreeInternal(void *ptr)
{
if (!ptr)
{
return;
}
-
+#ifdef B3_ALLOCATOR_STATISTICS
b3g_numAlignedFree++;
-// b3Printf("b3AlignedFreeInternal %x\n",ptr);
+#endif
+ // b3Printf("b3AlignedFreeInternal %x\n",ptr);
b3s_alignedFreeFunc(ptr);
}
-#endif //B3_DEBUG_MEMORY_ALLOCATIONS
-
+#endif //B3_DEBUG_MEMORY_ALLOCATIONS
diff --git a/thirdparty/bullet/Bullet3Common/b3AlignedAllocator.h b/thirdparty/bullet/Bullet3Common/b3AlignedAllocator.h
index be418bd55f..bcff9f128e 100644
--- a/thirdparty/bullet/Bullet3Common/b3AlignedAllocator.h
+++ b/thirdparty/bullet/Bullet3Common/b3AlignedAllocator.h
@@ -24,84 +24,87 @@ subject to the following restrictions:
//#define B3_DEBUG_MEMORY_ALLOCATIONS 1
#ifdef B3_DEBUG_MEMORY_ALLOCATIONS
-#define b3AlignedAlloc(a,b) \
- b3AlignedAllocInternal(a,b,__LINE__,__FILE__)
+#define b3AlignedAlloc(a, b) \
+ b3AlignedAllocInternal(a, b, __LINE__, __FILE__)
#define b3AlignedFree(ptr) \
- b3AlignedFreeInternal(ptr,__LINE__,__FILE__)
+ b3AlignedFreeInternal(ptr, __LINE__, __FILE__)
-void* b3AlignedAllocInternal (size_t size, int alignment,int line,char* filename);
+void* b3AlignedAllocInternal(size_t size, int alignment, int line, char* filename);
-void b3AlignedFreeInternal (void* ptr,int line,char* filename);
+void b3AlignedFreeInternal(void* ptr, int line, char* filename);
#else
- void* b3AlignedAllocInternal (size_t size, int alignment);
- void b3AlignedFreeInternal (void* ptr);
+void* b3AlignedAllocInternal(size_t size, int alignment);
+void b3AlignedFreeInternal(void* ptr);
- #define b3AlignedAlloc(size,alignment) b3AlignedAllocInternal(size,alignment)
- #define b3AlignedFree(ptr) b3AlignedFreeInternal(ptr)
+#define b3AlignedAlloc(size, alignment) b3AlignedAllocInternal(size, alignment)
+#define b3AlignedFree(ptr) b3AlignedFreeInternal(ptr)
#endif
-typedef int btSizeType;
+typedef int btSizeType;
-typedef void *(b3AlignedAllocFunc)(size_t size, int alignment);
-typedef void (b3AlignedFreeFunc)(void *memblock);
-typedef void *(b3AllocFunc)(size_t size);
-typedef void (b3FreeFunc)(void *memblock);
+typedef void*(b3AlignedAllocFunc)(size_t size, int alignment);
+typedef void(b3AlignedFreeFunc)(void* memblock);
+typedef void*(b3AllocFunc)(size_t size);
+typedef void(b3FreeFunc)(void* memblock);
///The developer can let all Bullet memory allocations go through a custom memory allocator, using b3AlignedAllocSetCustom
-void b3AlignedAllocSetCustom(b3AllocFunc *allocFunc, b3FreeFunc *freeFunc);
+void b3AlignedAllocSetCustom(b3AllocFunc* allocFunc, b3FreeFunc* freeFunc);
///If the developer has already an custom aligned allocator, then b3AlignedAllocSetCustomAligned can be used. The default aligned allocator pre-allocates extra memory using the non-aligned allocator, and instruments it.
-void b3AlignedAllocSetCustomAligned(b3AlignedAllocFunc *allocFunc, b3AlignedFreeFunc *freeFunc);
-
+void b3AlignedAllocSetCustomAligned(b3AlignedAllocFunc* allocFunc, b3AlignedFreeFunc* freeFunc);
///The b3AlignedAllocator is a portable class for aligned memory allocations.
///Default implementations for unaligned and aligned allocations can be overridden by a custom allocator using b3AlignedAllocSetCustom and b3AlignedAllocSetCustomAligned.
-template < typename T , unsigned Alignment >
-class b3AlignedAllocator {
-
- typedef b3AlignedAllocator< T , Alignment > self_type;
-
-public:
+template <typename T, unsigned Alignment>
+class b3AlignedAllocator
+{
+ typedef b3AlignedAllocator<T, Alignment> self_type;
+public:
//just going down a list:
b3AlignedAllocator() {}
/*
b3AlignedAllocator( const self_type & ) {}
*/
- template < typename Other >
- b3AlignedAllocator( const b3AlignedAllocator< Other , Alignment > & ) {}
+ template <typename Other>
+ b3AlignedAllocator(const b3AlignedAllocator<Other, Alignment>&)
+ {
+ }
- typedef const T* const_pointer;
- typedef const T& const_reference;
- typedef T* pointer;
- typedef T& reference;
- typedef T value_type;
+ typedef const T* const_pointer;
+ typedef const T& const_reference;
+ typedef T* pointer;
+ typedef T& reference;
+ typedef T value_type;
- pointer address ( reference ref ) const { return &ref; }
- const_pointer address ( const_reference ref ) const { return &ref; }
- pointer allocate ( btSizeType n , const_pointer * hint = 0 ) {
+ pointer address(reference ref) const { return &ref; }
+ const_pointer address(const_reference ref) const { return &ref; }
+ pointer allocate(btSizeType n, const_pointer* hint = 0)
+ {
(void)hint;
- return reinterpret_cast< pointer >(b3AlignedAlloc( sizeof(value_type) * n , Alignment ));
+ return reinterpret_cast<pointer>(b3AlignedAlloc(sizeof(value_type) * n, Alignment));
}
- void construct ( pointer ptr , const value_type & value ) { new (ptr) value_type( value ); }
- void deallocate( pointer ptr ) {
- b3AlignedFree( reinterpret_cast< void * >( ptr ) );
+ void construct(pointer ptr, const value_type& value) { new (ptr) value_type(value); }
+ void deallocate(pointer ptr)
+ {
+ b3AlignedFree(reinterpret_cast<void*>(ptr));
}
- void destroy ( pointer ptr ) { ptr->~value_type(); }
-
+ void destroy(pointer ptr) { ptr->~value_type(); }
- template < typename O > struct rebind {
- typedef b3AlignedAllocator< O , Alignment > other;
+ template <typename O>
+ struct rebind
+ {
+ typedef b3AlignedAllocator<O, Alignment> other;
};
- template < typename O >
- self_type & operator=( const b3AlignedAllocator< O , Alignment > & ) { return *this; }
+ template <typename O>
+ self_type& operator=(const b3AlignedAllocator<O, Alignment>&)
+ {
+ return *this;
+ }
- friend bool operator==( const self_type & , const self_type & ) { return true; }
+ friend bool operator==(const self_type&, const self_type&) { return true; }
};
-
-
-#endif //B3_ALIGNED_ALLOCATOR
-
+#endif //B3_ALIGNED_ALLOCATOR
diff --git a/thirdparty/bullet/Bullet3Common/b3AlignedObjectArray.h b/thirdparty/bullet/Bullet3Common/b3AlignedObjectArray.h
index ef71016565..249e381bf1 100644
--- a/thirdparty/bullet/Bullet3Common/b3AlignedObjectArray.h
+++ b/thirdparty/bullet/Bullet3Common/b3AlignedObjectArray.h
@@ -13,11 +13,10 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#ifndef B3_OBJECT_ARRAY__
#define B3_OBJECT_ARRAY__
-#include "b3Scalar.h" // has definitions like B3_FORCE_INLINE
+#include "b3Scalar.h" // has definitions like B3_FORCE_INLINE
#include "b3AlignedAllocator.h"
///If the platform doesn't support placement new, you can disable B3_USE_PLACEMENT_NEW
@@ -28,402 +27,386 @@ subject to the following restrictions:
#define B3_USE_PLACEMENT_NEW 1
//#define B3_USE_MEMCPY 1 //disable, because it is cumbersome to find out for each platform where memcpy is defined. It can be in <memory.h> or <string.h> or otherwise...
-#define B3_ALLOW_ARRAY_COPY_OPERATOR // enabling this can accidently perform deep copies of data if you are not careful
+#define B3_ALLOW_ARRAY_COPY_OPERATOR // enabling this can accidently perform deep copies of data if you are not careful
#ifdef B3_USE_MEMCPY
#include <memory.h>
#include <string.h>
-#endif //B3_USE_MEMCPY
+#endif //B3_USE_MEMCPY
#ifdef B3_USE_PLACEMENT_NEW
-#include <new> //for placement new
-#endif //B3_USE_PLACEMENT_NEW
-
+#include <new> //for placement new
+#endif //B3_USE_PLACEMENT_NEW
///The b3AlignedObjectArray template class uses a subset of the stl::vector interface for its methods
///It is developed to replace stl::vector to avoid portability issues, including STL alignment issues to add SIMD/SSE data
-template <typename T>
-//template <class T>
+template <typename T>
+//template <class T>
class b3AlignedObjectArray
{
- b3AlignedAllocator<T , 16> m_allocator;
+ b3AlignedAllocator<T, 16> m_allocator;
- int m_size;
- int m_capacity;
- T* m_data;
+ int m_size;
+ int m_capacity;
+ T* m_data;
//PCK: added this line
- bool m_ownsMemory;
+ bool m_ownsMemory;
#ifdef B3_ALLOW_ARRAY_COPY_OPERATOR
public:
- B3_FORCE_INLINE b3AlignedObjectArray<T>& operator=(const b3AlignedObjectArray<T> &other)
+ B3_FORCE_INLINE b3AlignedObjectArray<T>& operator=(const b3AlignedObjectArray<T>& other)
{
copyFromArray(other);
return *this;
}
-#else//B3_ALLOW_ARRAY_COPY_OPERATOR
+#else //B3_ALLOW_ARRAY_COPY_OPERATOR
private:
- B3_FORCE_INLINE b3AlignedObjectArray<T>& operator=(const b3AlignedObjectArray<T> &other);
-#endif//B3_ALLOW_ARRAY_COPY_OPERATOR
+ B3_FORCE_INLINE b3AlignedObjectArray<T>& operator=(const b3AlignedObjectArray<T>& other);
+#endif //B3_ALLOW_ARRAY_COPY_OPERATOR
protected:
- B3_FORCE_INLINE int allocSize(int size)
- {
- return (size ? size*2 : 1);
- }
- B3_FORCE_INLINE void copy(int start,int end, T* dest) const
- {
- int i;
- for (i=start;i<end;++i)
+ B3_FORCE_INLINE int allocSize(int size)
+ {
+ return (size ? size * 2 : 1);
+ }
+ B3_FORCE_INLINE void copy(int start, int end, T* dest) const
+ {
+ int i;
+ for (i = start; i < end; ++i)
#ifdef B3_USE_PLACEMENT_NEW
- new (&dest[i]) T(m_data[i]);
+ new (&dest[i]) T(m_data[i]);
#else
- dest[i] = m_data[i];
-#endif //B3_USE_PLACEMENT_NEW
- }
+ dest[i] = m_data[i];
+#endif //B3_USE_PLACEMENT_NEW
+ }
- B3_FORCE_INLINE void init()
+ B3_FORCE_INLINE void init()
+ {
+ //PCK: added this line
+ m_ownsMemory = true;
+ m_data = 0;
+ m_size = 0;
+ m_capacity = 0;
+ }
+ B3_FORCE_INLINE void destroy(int first, int last)
+ {
+ int i;
+ for (i = first; i < last; i++)
{
- //PCK: added this line
- m_ownsMemory = true;
- m_data = 0;
- m_size = 0;
- m_capacity = 0;
+ m_data[i].~T();
}
- B3_FORCE_INLINE void destroy(int first,int last)
+ }
+
+ B3_FORCE_INLINE void* allocate(int size)
+ {
+ if (size)
+ return m_allocator.allocate(size);
+ return 0;
+ }
+
+ B3_FORCE_INLINE void deallocate()
+ {
+ if (m_data)
{
- int i;
- for (i=first; i<last;i++)
+ //PCK: enclosed the deallocation in this block
+ if (m_ownsMemory)
{
- m_data[i].~T();
+ m_allocator.deallocate(m_data);
}
+ m_data = 0;
}
+ }
- B3_FORCE_INLINE void* allocate(int size)
- {
- if (size)
- return m_allocator.allocate(size);
- return 0;
- }
+public:
+ b3AlignedObjectArray()
+ {
+ init();
+ }
- B3_FORCE_INLINE void deallocate()
- {
- if(m_data) {
- //PCK: enclosed the deallocation in this block
- if (m_ownsMemory)
- {
- m_allocator.deallocate(m_data);
- }
- m_data = 0;
- }
- }
+ ~b3AlignedObjectArray()
+ {
+ clear();
+ }
-
+ ///Generally it is best to avoid using the copy constructor of an b3AlignedObjectArray, and use a (const) reference to the array instead.
+ b3AlignedObjectArray(const b3AlignedObjectArray& otherArray)
+ {
+ init();
+ int otherSize = otherArray.size();
+ resize(otherSize);
+ otherArray.copy(0, otherSize, m_data);
+ }
- public:
-
- b3AlignedObjectArray()
- {
- init();
- }
+ /// return the number of elements in the array
+ B3_FORCE_INLINE int size() const
+ {
+ return m_size;
+ }
- ~b3AlignedObjectArray()
- {
- clear();
- }
+ B3_FORCE_INLINE const T& at(int n) const
+ {
+ b3Assert(n >= 0);
+ b3Assert(n < size());
+ return m_data[n];
+ }
- ///Generally it is best to avoid using the copy constructor of an b3AlignedObjectArray, and use a (const) reference to the array instead.
- b3AlignedObjectArray(const b3AlignedObjectArray& otherArray)
- {
- init();
+ B3_FORCE_INLINE T& at(int n)
+ {
+ b3Assert(n >= 0);
+ b3Assert(n < size());
+ return m_data[n];
+ }
- int otherSize = otherArray.size();
- resize (otherSize);
- otherArray.copy(0, otherSize, m_data);
- }
+ B3_FORCE_INLINE const T& operator[](int n) const
+ {
+ b3Assert(n >= 0);
+ b3Assert(n < size());
+ return m_data[n];
+ }
-
-
- /// return the number of elements in the array
- B3_FORCE_INLINE int size() const
- {
- return m_size;
- }
-
- B3_FORCE_INLINE const T& at(int n) const
- {
- b3Assert(n>=0);
- b3Assert(n<size());
- return m_data[n];
- }
+ B3_FORCE_INLINE T& operator[](int n)
+ {
+ b3Assert(n >= 0);
+ b3Assert(n < size());
+ return m_data[n];
+ }
- B3_FORCE_INLINE T& at(int n)
- {
- b3Assert(n>=0);
- b3Assert(n<size());
- return m_data[n];
- }
+ ///clear the array, deallocated memory. Generally it is better to use array.resize(0), to reduce performance overhead of run-time memory (de)allocations.
+ B3_FORCE_INLINE void clear()
+ {
+ destroy(0, size());
- B3_FORCE_INLINE const T& operator[](int n) const
- {
- b3Assert(n>=0);
- b3Assert(n<size());
- return m_data[n];
- }
+ deallocate();
- B3_FORCE_INLINE T& operator[](int n)
- {
- b3Assert(n>=0);
- b3Assert(n<size());
- return m_data[n];
- }
-
+ init();
+ }
- ///clear the array, deallocated memory. Generally it is better to use array.resize(0), to reduce performance overhead of run-time memory (de)allocations.
- B3_FORCE_INLINE void clear()
+ B3_FORCE_INLINE void pop_back()
+ {
+ b3Assert(m_size > 0);
+ m_size--;
+ m_data[m_size].~T();
+ }
+
+ ///resize changes the number of elements in the array. If the new size is larger, the new elements will be constructed using the optional second argument.
+ ///when the new number of elements is smaller, the destructor will be called, but memory will not be freed, to reduce performance overhead of run-time memory (de)allocations.
+ B3_FORCE_INLINE void resizeNoInitialize(int newsize)
+ {
+ int curSize = size();
+
+ if (newsize < curSize)
{
- destroy(0,size());
-
- deallocate();
-
- init();
}
-
- B3_FORCE_INLINE void pop_back()
+ else
{
- b3Assert(m_size>0);
- m_size--;
- m_data[m_size].~T();
+ if (newsize > size())
+ {
+ reserve(newsize);
+ }
+ //leave this uninitialized
}
+ m_size = newsize;
+ }
+ B3_FORCE_INLINE void resize(int newsize, const T& fillData = T())
+ {
+ int curSize = size();
- ///resize changes the number of elements in the array. If the new size is larger, the new elements will be constructed using the optional second argument.
- ///when the new number of elements is smaller, the destructor will be called, but memory will not be freed, to reduce performance overhead of run-time memory (de)allocations.
- B3_FORCE_INLINE void resizeNoInitialize(int newsize)
+ if (newsize < curSize)
{
- int curSize = size();
-
- if (newsize < curSize)
- {
- } else
+ for (int i = newsize; i < curSize; i++)
{
- if (newsize > size())
- {
- reserve(newsize);
- }
- //leave this uninitialized
+ m_data[i].~T();
}
- m_size = newsize;
}
-
- B3_FORCE_INLINE void resize(int newsize, const T& fillData=T())
+ else
{
- int curSize = size();
-
- if (newsize < curSize)
- {
- for(int i = newsize; i < curSize; i++)
- {
- m_data[i].~T();
- }
- } else
+ if (newsize > size())
{
- if (newsize > size())
- {
- reserve(newsize);
- }
-#ifdef B3_USE_PLACEMENT_NEW
- for (int i=curSize;i<newsize;i++)
- {
- new ( &m_data[i]) T(fillData);
- }
-#endif //B3_USE_PLACEMENT_NEW
-
+ reserve(newsize);
}
-
- m_size = newsize;
- }
- B3_FORCE_INLINE T& expandNonInitializing( )
- {
- int sz = size();
- if( sz == capacity() )
+#ifdef B3_USE_PLACEMENT_NEW
+ for (int i = curSize; i < newsize; i++)
{
- reserve( allocSize(size()) );
+ new (&m_data[i]) T(fillData);
}
- m_size++;
+#endif //B3_USE_PLACEMENT_NEW
+ }
- return m_data[sz];
+ m_size = newsize;
+ }
+ B3_FORCE_INLINE T& expandNonInitializing()
+ {
+ int sz = size();
+ if (sz == capacity())
+ {
+ reserve(allocSize(size()));
}
+ m_size++;
+ return m_data[sz];
+ }
- B3_FORCE_INLINE T& expand( const T& fillValue=T())
- {
- int sz = size();
- if( sz == capacity() )
- {
- reserve( allocSize(size()) );
- }
- m_size++;
+ B3_FORCE_INLINE T& expand(const T& fillValue = T())
+ {
+ int sz = size();
+ if (sz == capacity())
+ {
+ reserve(allocSize(size()));
+ }
+ m_size++;
#ifdef B3_USE_PLACEMENT_NEW
- new (&m_data[sz]) T(fillValue); //use the in-place new (not really allocating heap memory)
+ new (&m_data[sz]) T(fillValue); //use the in-place new (not really allocating heap memory)
#endif
- return m_data[sz];
- }
+ return m_data[sz];
+ }
+ B3_FORCE_INLINE void push_back(const T& _Val)
+ {
+ int sz = size();
+ if (sz == capacity())
+ {
+ reserve(allocSize(size()));
+ }
- B3_FORCE_INLINE void push_back(const T& _Val)
- {
- int sz = size();
- if( sz == capacity() )
- {
- reserve( allocSize(size()) );
- }
-
#ifdef B3_USE_PLACEMENT_NEW
- new ( &m_data[m_size] ) T(_Val);
+ new (&m_data[m_size]) T(_Val);
#else
- m_data[size()] = _Val;
-#endif //B3_USE_PLACEMENT_NEW
+ m_data[size()] = _Val;
+#endif //B3_USE_PLACEMENT_NEW
- m_size++;
- }
+ m_size++;
+ }
-
- /// return the pre-allocated (reserved) elements, this is at least as large as the total number of elements,see size() and reserve()
- B3_FORCE_INLINE int capacity() const
- {
- return m_capacity;
- }
-
- B3_FORCE_INLINE void reserve(int _Count)
- { // determine new minimum length of allocated storage
- if (capacity() < _Count)
- { // not enough room, reallocate
- T* s = (T*)allocate(_Count);
- b3Assert(s);
- if (s==0)
- {
- b3Error("b3AlignedObjectArray reserve out-of-memory\n");
- _Count=0;
- m_size=0;
- }
- copy(0, size(), s);
-
- destroy(0,size());
-
- deallocate();
-
- //PCK: added this line
- m_ownsMemory = true;
-
- m_data = s;
-
- m_capacity = _Count;
+ /// return the pre-allocated (reserved) elements, this is at least as large as the total number of elements,see size() and reserve()
+ B3_FORCE_INLINE int capacity() const
+ {
+ return m_capacity;
+ }
+ B3_FORCE_INLINE void reserve(int _Count)
+ { // determine new minimum length of allocated storage
+ if (capacity() < _Count)
+ { // not enough room, reallocate
+ T* s = (T*)allocate(_Count);
+ b3Assert(s);
+ if (s == 0)
+ {
+ b3Error("b3AlignedObjectArray reserve out-of-memory\n");
+ _Count = 0;
+ m_size = 0;
}
- }
+ copy(0, size(), s);
+ destroy(0, size());
- class less
- {
- public:
+ deallocate();
+
+ //PCK: added this line
+ m_ownsMemory = true;
+
+ m_data = s;
- bool operator() ( const T& a, const T& b )
- {
- return ( a < b );
- }
- };
-
+ m_capacity = _Count;
+ }
+ }
- template <typename L>
- void quickSortInternal(const L& CompareFunc,int lo, int hi)
+ class less
+ {
+ public:
+ bool operator()(const T& a, const T& b)
{
- // lo is the lower index, hi is the upper index
- // of the region of array a that is to be sorted
- int i=lo, j=hi;
- T x=m_data[(lo+hi)/2];
-
- // partition
- do
- {
- while (CompareFunc(m_data[i],x))
- i++;
- while (CompareFunc(x,m_data[j]))
- j--;
- if (i<=j)
- {
- swap(i,j);
- i++; j--;
- }
- } while (i<=j);
-
- // recursion
- if (lo<j)
- quickSortInternal( CompareFunc, lo, j);
- if (i<hi)
- quickSortInternal( CompareFunc, i, hi);
+ return (a < b);
}
+ };
+ template <typename L>
+ void quickSortInternal(const L& CompareFunc, int lo, int hi)
+ {
+ // lo is the lower index, hi is the upper index
+ // of the region of array a that is to be sorted
+ int i = lo, j = hi;
+ T x = m_data[(lo + hi) / 2];
- template <typename L>
- void quickSort(const L& CompareFunc)
+ // partition
+ do
{
- //don't sort 0 or 1 elements
- if (size()>1)
+ while (CompareFunc(m_data[i], x))
+ i++;
+ while (CompareFunc(x, m_data[j]))
+ j--;
+ if (i <= j)
{
- quickSortInternal(CompareFunc,0,size()-1);
+ swap(i, j);
+ i++;
+ j--;
}
+ } while (i <= j);
+
+ // recursion
+ if (lo < j)
+ quickSortInternal(CompareFunc, lo, j);
+ if (i < hi)
+ quickSortInternal(CompareFunc, i, hi);
+ }
+
+ template <typename L>
+ void quickSort(const L& CompareFunc)
+ {
+ //don't sort 0 or 1 elements
+ if (size() > 1)
+ {
+ quickSortInternal(CompareFunc, 0, size() - 1);
}
+ }
+ ///heap sort from http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Heap/
+ template <typename L>
+ void downHeap(T* pArr, int k, int n, const L& CompareFunc)
+ {
+ /* PRE: a[k+1..N] is a heap */
+ /* POST: a[k..N] is a heap */
- ///heap sort from http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Heap/
- template <typename L>
- void downHeap(T *pArr, int k, int n, const L& CompareFunc)
+ T temp = pArr[k - 1];
+ /* k has child(s) */
+ while (k <= n / 2)
{
- /* PRE: a[k+1..N] is a heap */
- /* POST: a[k..N] is a heap */
-
- T temp = pArr[k - 1];
- /* k has child(s) */
- while (k <= n/2)
+ int child = 2 * k;
+
+ if ((child < n) && CompareFunc(pArr[child - 1], pArr[child]))
+ {
+ child++;
+ }
+ /* pick larger child */
+ if (CompareFunc(temp, pArr[child - 1]))
{
- int child = 2*k;
-
- if ((child < n) && CompareFunc(pArr[child - 1] , pArr[child]))
- {
- child++;
- }
- /* pick larger child */
- if (CompareFunc(temp , pArr[child - 1]))
- {
- /* move child up */
- pArr[k - 1] = pArr[child - 1];
- k = child;
- }
- else
- {
- break;
- }
+ /* move child up */
+ pArr[k - 1] = pArr[child - 1];
+ k = child;
}
- pArr[k - 1] = temp;
- } /*downHeap*/
+ else
+ {
+ break;
+ }
+ }
+ pArr[k - 1] = temp;
+ } /*downHeap*/
- void swap(int index0,int index1)
- {
+ void swap(int index0, int index1)
+ {
#ifdef B3_USE_MEMCPY
- char temp[sizeof(T)];
- memcpy(temp,&m_data[index0],sizeof(T));
- memcpy(&m_data[index0],&m_data[index1],sizeof(T));
- memcpy(&m_data[index1],temp,sizeof(T));
+ char temp[sizeof(T)];
+ memcpy(temp, &m_data[index0], sizeof(T));
+ memcpy(&m_data[index0], &m_data[index1], sizeof(T));
+ memcpy(&m_data[index1], temp, sizeof(T));
#else
- T temp = m_data[index0];
- m_data[index0] = m_data[index1];
- m_data[index1] = temp;
-#endif //B3_USE_PLACEMENT_NEW
-
- }
+ T temp = m_data[index0];
+ m_data[index0] = m_data[index1];
+ m_data[index1] = temp;
+#endif //B3_USE_PLACEMENT_NEW
+ }
template <typename L>
void heapSort(const L& CompareFunc)
@@ -431,49 +414,48 @@ protected:
/* sort a[0..N-1], N.B. 0 to N-1 */
int k;
int n = m_size;
- for (k = n/2; k > 0; k--)
+ for (k = n / 2; k > 0; k--)
{
downHeap(m_data, k, n, CompareFunc);
}
/* a[1..N] is now a heap */
- while ( n>=1 )
+ while (n >= 1)
{
- swap(0,n-1); /* largest of a[0..n-1] */
-
+ swap(0, n - 1); /* largest of a[0..n-1] */
n = n - 1;
/* restore a[1..i-1] heap */
downHeap(m_data, 1, n, CompareFunc);
- }
+ }
}
///non-recursive binary search, assumes sorted array
- int findBinarySearch(const T& key) const
+ int findBinarySearch(const T& key) const
{
int first = 0;
- int last = size()-1;
+ int last = size() - 1;
//assume sorted array
- while (first <= last) {
+ while (first <= last)
+ {
int mid = (first + last) / 2; // compute mid point.
- if (key > m_data[mid])
+ if (key > m_data[mid])
first = mid + 1; // repeat search in top half.
- else if (key < m_data[mid])
- last = mid - 1; // repeat search in bottom half.
+ else if (key < m_data[mid])
+ last = mid - 1; // repeat search in bottom half.
else
- return mid; // found it. return position /////
+ return mid; // found it. return position /////
}
- return size(); // failed to find key
+ return size(); // failed to find key
}
-
- int findLinearSearch(const T& key) const
+ int findLinearSearch(const T& key) const
{
- int index=size();
+ int index = size();
int i;
- for (i=0;i<size();i++)
+ for (i = 0; i < size(); i++)
{
if (m_data[i] == key)
{
@@ -483,36 +465,35 @@ protected:
}
return index;
}
-
- int findLinearSearch2(const T& key) const
- {
- int index=-1;
- int i;
-
- for (i=0;i<size();i++)
- {
- if (m_data[i] == key)
- {
- index = i;
- break;
- }
- }
- return index;
- }
-
- void remove(const T& key)
+
+ int findLinearSearch2(const T& key) const
{
+ int index = -1;
+ int i;
+ for (i = 0; i < size(); i++)
+ {
+ if (m_data[i] == key)
+ {
+ index = i;
+ break;
+ }
+ }
+ return index;
+ }
+
+ void remove(const T& key)
+ {
int findIndex = findLinearSearch(key);
- if (findIndex<size())
+ if (findIndex < size())
{
- swap( findIndex,size()-1);
+ swap(findIndex, size() - 1);
pop_back();
}
}
//PCK: whole function
- void initializeFromBuffer(void *buffer, int size, int capacity)
+ void initializeFromBuffer(void* buffer, int size, int capacity)
{
clear();
m_ownsMemory = false;
@@ -524,18 +505,18 @@ protected:
void copyFromArray(const b3AlignedObjectArray& otherArray)
{
int otherSize = otherArray.size();
- resize (otherSize);
+ resize(otherSize);
otherArray.copy(0, otherSize, m_data);
}
void removeAtIndex(int index)
- {
- if (index<size())
- {
- swap( index,size()-1);
- pop_back();
- }
- }
+ {
+ if (index < size())
+ {
+ swap(index, size() - 1);
+ pop_back();
+ }
+ }
};
-#endif //B3_OBJECT_ARRAY__
+#endif //B3_OBJECT_ARRAY__
diff --git a/thirdparty/bullet/Bullet3Common/b3CommandLineArgs.h b/thirdparty/bullet/Bullet3Common/b3CommandLineArgs.h
index 38df8e2600..5fe4f25f8d 100644
--- a/thirdparty/bullet/Bullet3Common/b3CommandLineArgs.h
+++ b/thirdparty/bullet/Bullet3Common/b3CommandLineArgs.h
@@ -12,51 +12,54 @@
class b3CommandLineArgs
{
protected:
-
std::map<std::string, std::string> pairs;
public:
-
// Constructor
b3CommandLineArgs(int argc, char **argv)
{
- addArgs(argc,argv);
+ addArgs(argc, argv);
}
- void addArgs(int argc, char**argv)
+ void addArgs(int argc, char **argv)
{
- for (int i = 1; i < argc; i++)
- {
- std::string arg = argv[i];
+ for (int i = 1; i < argc; i++)
+ {
+ std::string arg = argv[i];
+
+ if ((arg.length() < 2) || (arg[0] != '-') || (arg[1] != '-'))
+ {
+ continue;
+ }
- if ((arg.length() < 2) || (arg[0] != '-') || (arg[1] != '-')) {
- continue;
- }
+ std::string::size_type pos;
+ std::string key, val;
+ if ((pos = arg.find('=')) == std::string::npos)
+ {
+ key = std::string(arg, 2, arg.length() - 2);
+ val = "";
+ }
+ else
+ {
+ key = std::string(arg, 2, pos - 2);
+ val = std::string(arg, pos + 1, arg.length() - 1);
+ }
- std::string::size_type pos;
- std::string key, val;
- if ((pos = arg.find( '=')) == std::string::npos) {
- key = std::string(arg, 2, arg.length() - 2);
- val = "";
- } else {
- key = std::string(arg, 2, pos - 2);
- val = std::string(arg, pos + 1, arg.length() - 1);
- }
-
//only add new keys, don't replace existing
- if(pairs.find(key) == pairs.end())
+ if (pairs.find(key) == pairs.end())
{
- pairs[key] = val;
+ pairs[key] = val;
}
- }
+ }
}
- bool CheckCmdLineFlag(const char* arg_name)
+ bool CheckCmdLineFlag(const char *arg_name)
{
std::map<std::string, std::string>::iterator itr;
- if ((itr = pairs.find(arg_name)) != pairs.end()) {
+ if ((itr = pairs.find(arg_name)) != pairs.end())
+ {
return true;
- }
+ }
return false;
}
@@ -73,29 +76,31 @@ template <typename T>
inline bool b3CommandLineArgs::GetCmdLineArgument(const char *arg_name, T &val)
{
std::map<std::string, std::string>::iterator itr;
- if ((itr = pairs.find(arg_name)) != pairs.end()) {
+ if ((itr = pairs.find(arg_name)) != pairs.end())
+ {
std::istringstream strstream(itr->second);
strstream >> val;
return true;
- }
+ }
return false;
}
template <>
-inline bool b3CommandLineArgs::GetCmdLineArgument<char*>(const char* arg_name, char* &val)
+inline bool b3CommandLineArgs::GetCmdLineArgument<char *>(const char *arg_name, char *&val)
{
std::map<std::string, std::string>::iterator itr;
- if ((itr = pairs.find(arg_name)) != pairs.end()) {
-
+ if ((itr = pairs.find(arg_name)) != pairs.end())
+ {
std::string s = itr->second;
- val = (char*) malloc(sizeof(char) * (s.length() + 1));
+ val = (char *)malloc(sizeof(char) * (s.length() + 1));
std::strcpy(val, s.c_str());
return true;
- } else {
- val = NULL;
+ }
+ else
+ {
+ val = NULL;
}
return false;
}
-
-#endif //COMMAND_LINE_ARGS_H
+#endif //COMMAND_LINE_ARGS_H
diff --git a/thirdparty/bullet/Bullet3Common/b3FileUtils.h b/thirdparty/bullet/Bullet3Common/b3FileUtils.h
index b5e8225cf0..9ded17eaaf 100644
--- a/thirdparty/bullet/Bullet3Common/b3FileUtils.h
+++ b/thirdparty/bullet/Bullet3Common/b3FileUtils.h
@@ -3,7 +3,7 @@
#include <stdio.h>
#include "b3Scalar.h"
-#include <stddef.h>//ptrdiff_h
+#include <stddef.h> //ptrdiff_h
#include <string.h>
struct b3FileUtils
@@ -17,42 +17,42 @@ struct b3FileUtils
static bool findFile(const char* orgFileName, char* relativeFileName, int maxRelativeFileNameMaxLen)
{
- FILE* f=0;
- f = fopen(orgFileName,"rb");
- if (f)
- {
+ FILE* f = 0;
+ f = fopen(orgFileName, "rb");
+ if (f)
+ {
//printf("original file found: [%s]\n", orgFileName);
- sprintf(relativeFileName,"%s", orgFileName);
+ sprintf(relativeFileName, "%s", orgFileName);
fclose(f);
return true;
}
- //printf("Trying various directories, relative to current working directory\n");
- const char* prefix[]={"./","./data/","../data/","../../data/","../../../data/","../../../../data/"};
- int numPrefixes = sizeof(prefix)/sizeof(const char*);
-
- f=0;
- bool fileFound = false;
+ //printf("Trying various directories, relative to current working directory\n");
+ const char* prefix[] = {"./", "./data/", "../data/", "../../data/", "../../../data/", "../../../../data/"};
+ int numPrefixes = sizeof(prefix) / sizeof(const char*);
- for (int i=0;!f && i<numPrefixes;i++)
- {
+ f = 0;
+ bool fileFound = false;
+
+ for (int i = 0; !f && i < numPrefixes; i++)
+ {
#ifdef _MSC_VER
- sprintf_s(relativeFileName,maxRelativeFileNameMaxLen,"%s%s",prefix[i],orgFileName);
+ sprintf_s(relativeFileName, maxRelativeFileNameMaxLen, "%s%s", prefix[i], orgFileName);
#else
- sprintf(relativeFileName,"%s%s",prefix[i],orgFileName);
+ sprintf(relativeFileName, "%s%s", prefix[i], orgFileName);
#endif
- f = fopen(relativeFileName,"rb");
- if (f)
- {
- fileFound = true;
- break;
- }
- }
+ f = fopen(relativeFileName, "rb");
if (f)
{
- fclose(f);
+ fileFound = true;
+ break;
}
-
+ }
+ if (f)
+ {
+ fclose(f);
+ }
+
return fileFound;
}
@@ -60,8 +60,8 @@ struct b3FileUtils
{
size_t const patlen = strlen(pattern);
size_t patcnt = 0;
- const char * oriptr;
- const char * patloc;
+ const char* oriptr;
+ const char* patloc;
// find how many times the pattern occurs in the original string
for (oriptr = name; (patloc = strstr(oriptr, pattern)); oriptr = patloc + patlen)
{
@@ -70,29 +70,27 @@ struct b3FileUtils
return oriptr;
}
-
-
static int extractPath(const char* fileName, char* path, int maxPathLength)
{
const char* stripped = strip2(fileName, "/");
stripped = strip2(stripped, "\\");
- ptrdiff_t len = stripped-fileName;
- b3Assert((len+1)<maxPathLength);
+ ptrdiff_t len = stripped - fileName;
+ b3Assert((len + 1) < maxPathLength);
- if (len && ((len+1)<maxPathLength))
+ if (len && ((len + 1) < maxPathLength))
{
-
- for (int i=0;i<len;i++)
+ for (int i = 0; i < len; i++)
{
path[i] = fileName[i];
}
- path[len]=0;
- } else
+ path[len] = 0;
+ }
+ else
{
len = 0;
- b3Assert(maxPathLength>0);
- if (maxPathLength>0)
+ b3Assert(maxPathLength > 0);
+ if (maxPathLength > 0)
{
path[len] = 0;
}
@@ -102,23 +100,21 @@ struct b3FileUtils
static char toLowerChar(const char t)
{
- if (t>=(char)'A' && t<=(char)'Z')
+ if (t >= (char)'A' && t <= (char)'Z')
return t + ((char)'a' - (char)'A');
else
return t;
}
-
static void toLower(char* str)
{
- int len=strlen(str);
- for (int i=0;i<len;i++)
+ int len = strlen(str);
+ for (int i = 0; i < len; i++)
{
str[i] = toLowerChar(str[i]);
}
}
-
/*static const char* strip2(const char* name, const char* pattern)
{
size_t const patlen = strlen(pattern);
@@ -133,6 +129,5 @@ struct b3FileUtils
return oriptr;
}
*/
-
};
-#endif //B3_FILE_UTILS_H
+#endif //B3_FILE_UTILS_H
diff --git a/thirdparty/bullet/Bullet3Common/b3HashMap.h b/thirdparty/bullet/Bullet3Common/b3HashMap.h
index 24a59d9baa..3009e2cf2f 100644
--- a/thirdparty/bullet/Bullet3Common/b3HashMap.h
+++ b/thirdparty/bullet/Bullet3Common/b3HashMap.h
@@ -13,86 +13,80 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#ifndef B3_HASH_MAP_H
#define B3_HASH_MAP_H
#include "b3AlignedObjectArray.h"
-
#include <string>
///very basic hashable string implementation, compatible with b3HashMap
struct b3HashString
{
std::string m_string;
- unsigned int m_hash;
+ unsigned int m_hash;
- B3_FORCE_INLINE unsigned int getHash()const
+ B3_FORCE_INLINE unsigned int getHash() const
{
return m_hash;
}
-
b3HashString(const char* name)
- :m_string(name)
+ : m_string(name)
{
-
/* magic numbers from http://www.isthe.com/chongo/tech/comp/fnv/ */
- static const unsigned int InitialFNV = 2166136261u;
+ static const unsigned int InitialFNV = 2166136261u;
static const unsigned int FNVMultiple = 16777619u;
/* Fowler / Noll / Vo (FNV) Hash */
unsigned int hash = InitialFNV;
int len = m_string.length();
- for(int i = 0; i<len; i++)
+ for (int i = 0; i < len; i++)
{
- hash = hash ^ (m_string[i]); /* xor the low 8 bits */
- hash = hash * FNVMultiple; /* multiply by the magic number */
+ hash = hash ^ (m_string[i]); /* xor the low 8 bits */
+ hash = hash * FNVMultiple; /* multiply by the magic number */
}
m_hash = hash;
}
- int portableStringCompare(const char* src, const char* dst) const
+ int portableStringCompare(const char* src, const char* dst) const
{
- int ret = 0 ;
+ int ret = 0;
- while( ! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)
- ++src, ++dst;
+ while (!(ret = *(unsigned char*)src - *(unsigned char*)dst) && *dst)
+ ++src, ++dst;
- if ( ret < 0 )
- ret = -1 ;
- else if ( ret > 0 )
- ret = 1 ;
+ if (ret < 0)
+ ret = -1;
+ else if (ret > 0)
+ ret = 1;
- return( ret );
+ return (ret);
}
bool equals(const b3HashString& other) const
{
return (m_string == other.m_string);
}
-
};
-
-const int B3_HASH_NULL=0xffffffff;
-
+const int B3_HASH_NULL = 0xffffffff;
class b3HashInt
{
- int m_uid;
+ int m_uid;
+
public:
- b3HashInt(int uid) :m_uid(uid)
+ b3HashInt(int uid) : m_uid(uid)
{
}
- int getUid1() const
+ int getUid1() const
{
return m_uid;
}
- void setUid1(int uid)
+ void setUid1(int uid)
{
m_uid = uid;
}
@@ -102,34 +96,34 @@ public:
return getUid1() == other.getUid1();
}
//to our success
- B3_FORCE_INLINE unsigned int getHash()const
+ B3_FORCE_INLINE unsigned int getHash() const
{
int key = m_uid;
// Thomas Wang's hash
- key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16);
+ key += ~(key << 15);
+ key ^= (key >> 10);
+ key += (key << 3);
+ key ^= (key >> 6);
+ key += ~(key << 11);
+ key ^= (key >> 16);
return key;
}
};
-
-
class b3HashPtr
{
-
- union
- {
- const void* m_pointer;
- int m_hashValues[2];
+ union {
+ const void* m_pointer;
+ int m_hashValues[2];
};
public:
-
b3HashPtr(const void* ptr)
- :m_pointer(ptr)
+ : m_pointer(ptr)
{
}
- const void* getPointer() const
+ const void* getPointer() const
{
return m_pointer;
}
@@ -140,65 +134,69 @@ public:
}
//to our success
- B3_FORCE_INLINE unsigned int getHash()const
+ B3_FORCE_INLINE unsigned int getHash() const
{
- const bool VOID_IS_8 = ((sizeof(void*)==8));
-
- int key = VOID_IS_8? m_hashValues[0]+m_hashValues[1] : m_hashValues[0];
-
+ const bool VOID_IS_8 = ((sizeof(void*) == 8));
+
+ int key = VOID_IS_8 ? m_hashValues[0] + m_hashValues[1] : m_hashValues[0];
+
// Thomas Wang's hash
- key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16);
+ key += ~(key << 15);
+ key ^= (key >> 10);
+ key += (key << 3);
+ key ^= (key >> 6);
+ key += ~(key << 11);
+ key ^= (key >> 16);
return key;
}
-
-
};
-
template <class Value>
class b3HashKeyPtr
{
- int m_uid;
+ int m_uid;
+
public:
+ b3HashKeyPtr(int uid) : m_uid(uid)
+ {
+ }
- b3HashKeyPtr(int uid) :m_uid(uid)
- {
- }
-
- int getUid1() const
- {
- return m_uid;
- }
-
- bool equals(const b3HashKeyPtr<Value>& other) const
- {
- return getUid1() == other.getUid1();
- }
-
- //to our success
- B3_FORCE_INLINE unsigned int getHash()const
- {
- int key = m_uid;
- // Thomas Wang's hash
- key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16);
- return key;
- }
-
-
-};
+ int getUid1() const
+ {
+ return m_uid;
+ }
+ bool equals(const b3HashKeyPtr<Value>& other) const
+ {
+ return getUid1() == other.getUid1();
+ }
+
+ //to our success
+ B3_FORCE_INLINE unsigned int getHash() const
+ {
+ int key = m_uid;
+ // Thomas Wang's hash
+ key += ~(key << 15);
+ key ^= (key >> 10);
+ key += (key << 3);
+ key ^= (key >> 6);
+ key += ~(key << 11);
+ key ^= (key >> 16);
+ return key;
+ }
+};
template <class Value>
class b3HashKey
{
- int m_uid;
-public:
+ int m_uid;
- b3HashKey(int uid) :m_uid(uid)
+public:
+ b3HashKey(int uid) : m_uid(uid)
{
}
- int getUid1() const
+ int getUid1() const
{
return m_uid;
}
@@ -208,30 +206,33 @@ public:
return getUid1() == other.getUid1();
}
//to our success
- B3_FORCE_INLINE unsigned int getHash()const
+ B3_FORCE_INLINE unsigned int getHash() const
{
int key = m_uid;
// Thomas Wang's hash
- key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16);
+ key += ~(key << 15);
+ key ^= (key >> 10);
+ key += (key << 3);
+ key ^= (key >> 6);
+ key += ~(key << 11);
+ key ^= (key >> 16);
return key;
}
};
-
///The b3HashMap template class implements a generic and lightweight hashmap.
///A basic sample of how to use b3HashMap is located in Demos\BasicDemo\main.cpp
template <class Key, class Value>
class b3HashMap
{
-
protected:
- b3AlignedObjectArray<int> m_hashTable;
- b3AlignedObjectArray<int> m_next;
-
- b3AlignedObjectArray<Value> m_valueArray;
- b3AlignedObjectArray<Key> m_keyArray;
+ b3AlignedObjectArray<int> m_hashTable;
+ b3AlignedObjectArray<int> m_next;
+
+ b3AlignedObjectArray<Value> m_valueArray;
+ b3AlignedObjectArray<Key> m_keyArray;
- void growTables(const Key& /*key*/)
+ void growTables(const Key& /*key*/)
{
int newCapacity = m_valueArray.capacity();
@@ -245,7 +246,7 @@ protected:
int i;
- for (i= 0; i < newCapacity; ++i)
+ for (i = 0; i < newCapacity; ++i)
{
m_hashTable[i] = B3_HASH_NULL;
}
@@ -254,30 +255,28 @@ protected:
m_next[i] = B3_HASH_NULL;
}
- for(i=0;i<curHashtableSize;i++)
+ for (i = 0; i < curHashtableSize; i++)
{
//const Value& value = m_valueArray[i];
//const Key& key = m_keyArray[i];
- int hashValue = m_keyArray[i].getHash() & (m_valueArray.capacity()-1); // New hash value with new mask
+ int hashValue = m_keyArray[i].getHash() & (m_valueArray.capacity() - 1); // New hash value with new mask
m_next[i] = m_hashTable[hashValue];
m_hashTable[hashValue] = i;
}
-
-
}
}
- public:
-
- void insert(const Key& key, const Value& value) {
- int hash = key.getHash() & (m_valueArray.capacity()-1);
+public:
+ void insert(const Key& key, const Value& value)
+ {
+ int hash = key.getHash() & (m_valueArray.capacity() - 1);
//replace value if the key is already there
int index = findIndex(key);
if (index != B3_HASH_NULL)
{
- m_valueArray[index]=value;
+ m_valueArray[index] = value;
return;
}
@@ -291,19 +290,19 @@ protected:
{
growTables(key);
//hash with new capacity
- hash = key.getHash() & (m_valueArray.capacity()-1);
+ hash = key.getHash() & (m_valueArray.capacity() - 1);
}
m_next[count] = m_hashTable[hash];
m_hashTable[hash] = count;
}
- void remove(const Key& key) {
-
- int hash = key.getHash() & (m_valueArray.capacity()-1);
+ void remove(const Key& key)
+ {
+ int hash = key.getHash() & (m_valueArray.capacity() - 1);
int pairIndex = findIndex(key);
-
- if (pairIndex ==B3_HASH_NULL)
+
+ if (pairIndex == B3_HASH_NULL)
{
return;
}
@@ -344,7 +343,7 @@ protected:
}
// Remove the last pair from the hash table.
- int lastHash = m_keyArray[lastPairIndex].getHash() & (m_valueArray.capacity()-1);
+ int lastHash = m_keyArray[lastPairIndex].getHash() & (m_valueArray.capacity() - 1);
index = m_hashTable[lastHash];
b3Assert(index != B3_HASH_NULL);
@@ -376,10 +375,8 @@ protected:
m_valueArray.pop_back();
m_keyArray.pop_back();
-
}
-
int size() const
{
return m_valueArray.size();
@@ -399,23 +396,24 @@ protected:
return &m_valueArray[index];
}
- Key getKeyAtIndex(int index)
- {
- b3Assert(index < m_keyArray.size());
- return m_keyArray[index];
- }
-
- const Key getKeyAtIndex(int index) const
- {
- b3Assert(index < m_keyArray.size());
- return m_keyArray[index];
- }
+ Key getKeyAtIndex(int index)
+ {
+ b3Assert(index < m_keyArray.size());
+ return m_keyArray[index];
+ }
+
+ const Key getKeyAtIndex(int index) const
+ {
+ b3Assert(index < m_keyArray.size());
+ return m_keyArray[index];
+ }
- Value* operator[](const Key& key) {
+ Value* operator[](const Key& key)
+ {
return find(key);
}
- const Value* find(const Key& key) const
+ const Value* find(const Key& key) const
{
int index = findIndex(key);
if (index == B3_HASH_NULL)
@@ -425,7 +423,7 @@ protected:
return &m_valueArray[index];
}
- Value* find(const Key& key)
+ Value* find(const Key& key)
{
int index = findIndex(key);
if (index == B3_HASH_NULL)
@@ -435,10 +433,9 @@ protected:
return &m_valueArray[index];
}
-
- int findIndex(const Key& key) const
+ int findIndex(const Key& key) const
{
- unsigned int hash = key.getHash() & (m_valueArray.capacity()-1);
+ unsigned int hash = key.getHash() & (m_valueArray.capacity() - 1);
if (hash >= (unsigned int)m_hashTable.size())
{
@@ -453,14 +450,13 @@ protected:
return index;
}
- void clear()
+ void clear()
{
m_hashTable.clear();
m_next.clear();
m_valueArray.clear();
m_keyArray.clear();
}
-
};
-#endif //B3_HASH_MAP_H
+#endif //B3_HASH_MAP_H
diff --git a/thirdparty/bullet/Bullet3Common/b3Logging.cpp b/thirdparty/bullet/Bullet3Common/b3Logging.cpp
index a8e9507155..9c9f7c09ea 100644
--- a/thirdparty/bullet/Bullet3Common/b3Logging.cpp
+++ b/thirdparty/bullet/Bullet3Common/b3Logging.cpp
@@ -20,17 +20,16 @@ subject to the following restrictions:
#ifdef _WIN32
#include <windows.h>
-#endif //_WIN32
-
+#endif //_WIN32
void b3PrintfFuncDefault(const char* msg)
{
#ifdef _WIN32
OutputDebugStringA(msg);
#endif
- printf("%s",msg);
- //is this portable?
- fflush(stdout);
+ printf("%s", msg);
+ //is this portable?
+ fflush(stdout);
}
void b3WarningMessageFuncDefault(const char* msg)
@@ -38,32 +37,26 @@ void b3WarningMessageFuncDefault(const char* msg)
#ifdef _WIN32
OutputDebugStringA(msg);
#endif
- printf("%s",msg);
- //is this portable?
- fflush(stdout);
-
+ printf("%s", msg);
+ //is this portable?
+ fflush(stdout);
}
-
void b3ErrorMessageFuncDefault(const char* msg)
{
#ifdef _WIN32
OutputDebugStringA(msg);
#endif
- printf("%s",msg);
+ printf("%s", msg);
- //is this portable?
- fflush(stdout);
-
+ //is this portable?
+ fflush(stdout);
}
-
-
static b3PrintfFunc* b3s_printfFunc = b3PrintfFuncDefault;
static b3WarningMessageFunc* b3s_warningMessageFunc = b3WarningMessageFuncDefault;
static b3ErrorMessageFunc* b3s_errorMessageFunc = b3ErrorMessageFuncDefault;
-
///The developer can route b3Printf output using their own implementation
void b3SetCustomPrintfFunc(b3PrintfFunc* printfFunc)
{
@@ -81,54 +74,50 @@ void b3SetCustomErrorMessageFunc(b3PrintfFunc* errorMessageFunc)
//#define B3_MAX_DEBUG_STRING_LENGTH 2048
#define B3_MAX_DEBUG_STRING_LENGTH 32768
-
-void b3OutputPrintfVarArgsInternal(const char *str, ...)
+void b3OutputPrintfVarArgsInternal(const char* str, ...)
{
- char strDebug[B3_MAX_DEBUG_STRING_LENGTH]={0};
- va_list argList;
- va_start(argList, str);
+ char strDebug[B3_MAX_DEBUG_STRING_LENGTH] = {0};
+ va_list argList;
+ va_start(argList, str);
#ifdef _MSC_VER
- vsprintf_s(strDebug,B3_MAX_DEBUG_STRING_LENGTH,str,argList);
+ vsprintf_s(strDebug, B3_MAX_DEBUG_STRING_LENGTH, str, argList);
#else
- vsnprintf(strDebug,B3_MAX_DEBUG_STRING_LENGTH,str,argList);
+ vsnprintf(strDebug, B3_MAX_DEBUG_STRING_LENGTH, str, argList);
#endif
- (b3s_printfFunc)(strDebug);
- va_end(argList);
+ (b3s_printfFunc)(strDebug);
+ va_end(argList);
}
-void b3OutputWarningMessageVarArgsInternal(const char *str, ...)
+void b3OutputWarningMessageVarArgsInternal(const char* str, ...)
{
- char strDebug[B3_MAX_DEBUG_STRING_LENGTH]={0};
- va_list argList;
- va_start(argList, str);
+ char strDebug[B3_MAX_DEBUG_STRING_LENGTH] = {0};
+ va_list argList;
+ va_start(argList, str);
#ifdef _MSC_VER
- vsprintf_s(strDebug,B3_MAX_DEBUG_STRING_LENGTH,str,argList);
+ vsprintf_s(strDebug, B3_MAX_DEBUG_STRING_LENGTH, str, argList);
#else
- vsnprintf(strDebug,B3_MAX_DEBUG_STRING_LENGTH,str,argList);
+ vsnprintf(strDebug, B3_MAX_DEBUG_STRING_LENGTH, str, argList);
#endif
- (b3s_warningMessageFunc)(strDebug);
- va_end(argList);
+ (b3s_warningMessageFunc)(strDebug);
+ va_end(argList);
}
-void b3OutputErrorMessageVarArgsInternal(const char *str, ...)
+void b3OutputErrorMessageVarArgsInternal(const char* str, ...)
{
-
- char strDebug[B3_MAX_DEBUG_STRING_LENGTH]={0};
- va_list argList;
- va_start(argList, str);
+ char strDebug[B3_MAX_DEBUG_STRING_LENGTH] = {0};
+ va_list argList;
+ va_start(argList, str);
#ifdef _MSC_VER
- vsprintf_s(strDebug,B3_MAX_DEBUG_STRING_LENGTH,str,argList);
+ vsprintf_s(strDebug, B3_MAX_DEBUG_STRING_LENGTH, str, argList);
#else
- vsnprintf(strDebug,B3_MAX_DEBUG_STRING_LENGTH,str,argList);
+ vsnprintf(strDebug, B3_MAX_DEBUG_STRING_LENGTH, str, argList);
#endif
- (b3s_errorMessageFunc)(strDebug);
- va_end(argList);
-
+ (b3s_errorMessageFunc)(strDebug);
+ va_end(argList);
}
-
-void b3EnterProfileZoneDefault(const char* name)
+void b3EnterProfileZoneDefault(const char* name)
{
}
-void b3LeaveProfileZoneDefault()
+void b3LeaveProfileZoneDefault()
{
}
static b3EnterProfileZoneFunc* b3s_enterFunc = b3EnterProfileZoneDefault;
@@ -151,10 +140,6 @@ void b3SetCustomLeaveProfileZoneFunc(b3LeaveProfileZoneFunc* leaveFunc)
b3s_leaveFunc = leaveFunc;
}
-
-
-
#ifndef _MSC_VER
#undef vsprintf_s
#endif
-
diff --git a/thirdparty/bullet/Bullet3Common/b3Logging.h b/thirdparty/bullet/Bullet3Common/b3Logging.h
index b302effe43..9c92b12ebb 100644
--- a/thirdparty/bullet/Bullet3Common/b3Logging.h
+++ b/thirdparty/bullet/Bullet3Common/b3Logging.h
@@ -3,75 +3,84 @@
#define B3_LOGGING_H
#ifdef __cplusplus
-extern "C" {
+extern "C"
+{
#endif
-
+
///We add the do/while so that the statement "if (condition) b3Printf("test"); else {...}" would fail
///You can also customize the message by uncommenting out a different line below
#define b3Printf(...) b3OutputPrintfVarArgsInternal(__VA_ARGS__)
-//#define b3Printf(...) do {b3OutputPrintfVarArgsInternal("b3Printf[%s,%d]:",__FILE__,__LINE__);b3OutputPrintfVarArgsInternal(__VA_ARGS__); } while(0)
-//#define b3Printf b3OutputPrintfVarArgsInternal
-//#define b3Printf(...) printf(__VA_ARGS__)
-//#define b3Printf(...)
-
-#define b3Warning(...) do {b3OutputWarningMessageVarArgsInternal("b3Warning[%s,%d]:\n",__FILE__,__LINE__);b3OutputWarningMessageVarArgsInternal(__VA_ARGS__); }while(0)
-#define b3Error(...) do {b3OutputErrorMessageVarArgsInternal("b3Error[%s,%d]:\n",__FILE__,__LINE__);b3OutputErrorMessageVarArgsInternal(__VA_ARGS__); } while(0)
-
+ //#define b3Printf(...) do {b3OutputPrintfVarArgsInternal("b3Printf[%s,%d]:",__FILE__,__LINE__);b3OutputPrintfVarArgsInternal(__VA_ARGS__); } while(0)
+ //#define b3Printf b3OutputPrintfVarArgsInternal
+ //#define b3Printf(...) printf(__VA_ARGS__)
+ //#define b3Printf(...)
+
+#define b3Warning(...) \
+ do \
+ { \
+ b3OutputWarningMessageVarArgsInternal("b3Warning[%s,%d]:\n", __FILE__, __LINE__); \
+ b3OutputWarningMessageVarArgsInternal(__VA_ARGS__); \
+ } while (0)
+#define b3Error(...) \
+ do \
+ { \
+ b3OutputErrorMessageVarArgsInternal("b3Error[%s,%d]:\n", __FILE__, __LINE__); \
+ b3OutputErrorMessageVarArgsInternal(__VA_ARGS__); \
+ } while (0)
#ifndef B3_NO_PROFILE
-void b3EnterProfileZone(const char* name);
-void b3LeaveProfileZone();
+ void b3EnterProfileZone(const char* name);
+ void b3LeaveProfileZone();
#ifdef __cplusplus
-class b3ProfileZone
-{
-public:
- b3ProfileZone(const char* name)
- {
- b3EnterProfileZone( name );
- }
-
- ~b3ProfileZone()
- {
- b3LeaveProfileZone();
- }
-};
-
-#define B3_PROFILE( name ) b3ProfileZone __profile( name )
+ class b3ProfileZone
+ {
+ public:
+ b3ProfileZone(const char* name)
+ {
+ b3EnterProfileZone(name);
+ }
+
+ ~b3ProfileZone()
+ {
+ b3LeaveProfileZone();
+ }
+ };
+
+#define B3_PROFILE(name) b3ProfileZone __profile(name)
#endif
-#else //B3_NO_PROFILE
+#else //B3_NO_PROFILE
-#define B3_PROFILE( name )
+#define B3_PROFILE(name)
#define b3StartProfile(a)
#define b3StopProfile
-#endif //#ifndef B3_NO_PROFILE
-
+#endif //#ifndef B3_NO_PROFILE
-typedef void (b3PrintfFunc)(const char* msg);
-typedef void (b3WarningMessageFunc)(const char* msg);
-typedef void (b3ErrorMessageFunc)(const char* msg);
-typedef void (b3EnterProfileZoneFunc)(const char* msg);
-typedef void (b3LeaveProfileZoneFunc)();
+ typedef void(b3PrintfFunc)(const char* msg);
+ typedef void(b3WarningMessageFunc)(const char* msg);
+ typedef void(b3ErrorMessageFunc)(const char* msg);
+ typedef void(b3EnterProfileZoneFunc)(const char* msg);
+ typedef void(b3LeaveProfileZoneFunc)();
-///The developer can route b3Printf output using their own implementation
-void b3SetCustomPrintfFunc(b3PrintfFunc* printfFunc);
-void b3SetCustomWarningMessageFunc(b3WarningMessageFunc* warningMsgFunc);
-void b3SetCustomErrorMessageFunc(b3ErrorMessageFunc* errorMsgFunc);
+ ///The developer can route b3Printf output using their own implementation
+ void b3SetCustomPrintfFunc(b3PrintfFunc* printfFunc);
+ void b3SetCustomWarningMessageFunc(b3WarningMessageFunc* warningMsgFunc);
+ void b3SetCustomErrorMessageFunc(b3ErrorMessageFunc* errorMsgFunc);
-///Set custom profile zone functions (zones can be nested)
-void b3SetCustomEnterProfileZoneFunc(b3EnterProfileZoneFunc* enterFunc);
-void b3SetCustomLeaveProfileZoneFunc(b3LeaveProfileZoneFunc* leaveFunc);
+ ///Set custom profile zone functions (zones can be nested)
+ void b3SetCustomEnterProfileZoneFunc(b3EnterProfileZoneFunc* enterFunc);
+ void b3SetCustomLeaveProfileZoneFunc(b3LeaveProfileZoneFunc* leaveFunc);
-///Don't use those internal functions directly, use the b3Printf or b3SetCustomPrintfFunc instead (or warning/error version)
-void b3OutputPrintfVarArgsInternal(const char *str, ...);
-void b3OutputWarningMessageVarArgsInternal(const char *str, ...);
-void b3OutputErrorMessageVarArgsInternal(const char *str, ...);
+ ///Don't use those internal functions directly, use the b3Printf or b3SetCustomPrintfFunc instead (or warning/error version)
+ void b3OutputPrintfVarArgsInternal(const char* str, ...);
+ void b3OutputWarningMessageVarArgsInternal(const char* str, ...);
+ void b3OutputErrorMessageVarArgsInternal(const char* str, ...);
#ifdef __cplusplus
- }
+}
#endif
-#endif//B3_LOGGING_H \ No newline at end of file
+#endif //B3_LOGGING_H \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3Common/b3Matrix3x3.h b/thirdparty/bullet/Bullet3Common/b3Matrix3x3.h
index 89b57cf59a..6c46536a81 100644
--- a/thirdparty/bullet/Bullet3Common/b3Matrix3x3.h
+++ b/thirdparty/bullet/Bullet3Common/b3Matrix3x3.h
@@ -12,8 +12,7 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
-#ifndef B3_MATRIX3x3_H
+#ifndef B3_MATRIX3x3_H
#define B3_MATRIX3x3_H
#include "b3Vector3.h"
@@ -32,22 +31,22 @@ const b3SimdFloat4 B3_ATTRIBUTE_ALIGNED16(b3v0010) = {0.0f, 0.0f, 1.0f, 0.0f};
#endif
#ifdef B3_USE_DOUBLE_PRECISION
-#define b3Matrix3x3Data b3Matrix3x3DoubleData
+#define b3Matrix3x3Data b3Matrix3x3DoubleData
#else
-#define b3Matrix3x3Data b3Matrix3x3FloatData
-#endif //B3_USE_DOUBLE_PRECISION
-
+#define b3Matrix3x3Data b3Matrix3x3FloatData
+#endif //B3_USE_DOUBLE_PRECISION
/**@brief The b3Matrix3x3 class implements a 3x3 rotation matrix, to perform linear algebra in combination with b3Quaternion, b3Transform and b3Vector3.
* Make sure to only include a pure orthogonal matrix without scaling. */
-B3_ATTRIBUTE_ALIGNED16(class) b3Matrix3x3 {
-
+B3_ATTRIBUTE_ALIGNED16(class)
+b3Matrix3x3
+{
///Data storage for the matrix, each vector is a row of the matrix
b3Vector3 m_el[3];
public:
/** @brief No initializaion constructor */
- b3Matrix3x3 () {}
+ b3Matrix3x3() {}
// explicit b3Matrix3x3(const b3Scalar *m) { setFromOpenGLSubMatrix(m); }
@@ -62,27 +61,27 @@ public:
*/
/** @brief Constructor with row major formatting */
b3Matrix3x3(const b3Scalar& xx, const b3Scalar& xy, const b3Scalar& xz,
- const b3Scalar& yx, const b3Scalar& yy, const b3Scalar& yz,
- const b3Scalar& zx, const b3Scalar& zy, const b3Scalar& zz)
- {
- setValue(xx, xy, xz,
- yx, yy, yz,
- zx, zy, zz);
+ const b3Scalar& yx, const b3Scalar& yy, const b3Scalar& yz,
+ const b3Scalar& zx, const b3Scalar& zy, const b3Scalar& zz)
+ {
+ setValue(xx, xy, xz,
+ yx, yy, yz,
+ zx, zy, zz);
}
-#if (defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE))|| defined (B3_USE_NEON)
- B3_FORCE_INLINE b3Matrix3x3 (const b3SimdFloat4 v0, const b3SimdFloat4 v1, const b3SimdFloat4 v2 )
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)) || defined(B3_USE_NEON)
+ B3_FORCE_INLINE b3Matrix3x3(const b3SimdFloat4 v0, const b3SimdFloat4 v1, const b3SimdFloat4 v2)
{
- m_el[0].mVec128 = v0;
- m_el[1].mVec128 = v1;
- m_el[2].mVec128 = v2;
+ m_el[0].mVec128 = v0;
+ m_el[1].mVec128 = v1;
+ m_el[2].mVec128 = v2;
}
- B3_FORCE_INLINE b3Matrix3x3 (const b3Vector3& v0, const b3Vector3& v1, const b3Vector3& v2 )
+ B3_FORCE_INLINE b3Matrix3x3(const b3Vector3& v0, const b3Vector3& v1, const b3Vector3& v2)
{
- m_el[0] = v0;
- m_el[1] = v1;
- m_el[2] = v2;
+ m_el[0] = v0;
+ m_el[1] = v1;
+ m_el[2] = v2;
}
// Copy constructor
@@ -94,25 +93,25 @@ public:
}
// Assignment Operator
- B3_FORCE_INLINE b3Matrix3x3& operator=(const b3Matrix3x3& m)
+ B3_FORCE_INLINE b3Matrix3x3& operator=(const b3Matrix3x3& m)
{
m_el[0].mVec128 = m.m_el[0].mVec128;
m_el[1].mVec128 = m.m_el[1].mVec128;
m_el[2].mVec128 = m.m_el[2].mVec128;
-
+
return *this;
}
#else
/** @brief Copy constructor */
- B3_FORCE_INLINE b3Matrix3x3 (const b3Matrix3x3& other)
+ B3_FORCE_INLINE b3Matrix3x3(const b3Matrix3x3& other)
{
m_el[0] = other.m_el[0];
m_el[1] = other.m_el[1];
m_el[2] = other.m_el[2];
}
-
+
/** @brief Assignment Operator */
B3_FORCE_INLINE b3Matrix3x3& operator=(const b3Matrix3x3& other)
{
@@ -128,10 +127,9 @@ public:
* @param i Column number 0 indexed */
B3_FORCE_INLINE b3Vector3 getColumn(int i) const
{
- return b3MakeVector3(m_el[0][i],m_el[1][i],m_el[2][i]);
+ return b3MakeVector3(m_el[0][i], m_el[1][i], m_el[2][i]);
}
-
/** @brief Get a row of the matrix as a vector
* @param i Row number 0 indexed */
B3_FORCE_INLINE const b3Vector3& getRow(int i) const
@@ -142,10 +140,10 @@ public:
/** @brief Get a mutable reference to a row of the matrix as a vector
* @param i Row number 0 indexed */
- B3_FORCE_INLINE b3Vector3& operator[](int i)
- {
+ B3_FORCE_INLINE b3Vector3& operator[](int i)
+ {
b3FullAssert(0 <= i && i < 3);
- return m_el[i];
+ return m_el[i];
}
/** @brief Get a const reference to a row of the matrix as a vector
@@ -153,32 +151,31 @@ public:
B3_FORCE_INLINE const b3Vector3& operator[](int i) const
{
b3FullAssert(0 <= i && i < 3);
- return m_el[i];
+ return m_el[i];
}
/** @brief Multiply by the target matrix on the right
* @param m Rotation matrix to be applied
* Equivilant to this = this * m */
- b3Matrix3x3& operator*=(const b3Matrix3x3& m);
+ b3Matrix3x3& operator*=(const b3Matrix3x3& m);
/** @brief Adds by the target matrix on the right
* @param m matrix to be applied
* Equivilant to this = this + m */
- b3Matrix3x3& operator+=(const b3Matrix3x3& m);
+ b3Matrix3x3& operator+=(const b3Matrix3x3& m);
/** @brief Substractss by the target matrix on the right
* @param m matrix to be applied
* Equivilant to this = this - m */
- b3Matrix3x3& operator-=(const b3Matrix3x3& m);
+ b3Matrix3x3& operator-=(const b3Matrix3x3& m);
/** @brief Set from the rotational part of a 4x4 OpenGL matrix
* @param m A pointer to the beginning of the array of scalars*/
- void setFromOpenGLSubMatrix(const b3Scalar *m)
+ void setFromOpenGLSubMatrix(const b3Scalar* m)
{
- m_el[0].setValue(m[0],m[4],m[8]);
- m_el[1].setValue(m[1],m[5],m[9]);
- m_el[2].setValue(m[2],m[6],m[10]);
-
+ m_el[0].setValue(m[0], m[4], m[8]);
+ m_el[1].setValue(m[1], m[5], m[9]);
+ m_el[2].setValue(m[2], m[6], m[10]);
}
/** @brief Set the values of the matrix explicitly (row major)
* @param xx Top left
@@ -190,93 +187,92 @@ public:
* @param zx Bottom Left
* @param zy Bottom Middle
* @param zz Bottom Right*/
- void setValue(const b3Scalar& xx, const b3Scalar& xy, const b3Scalar& xz,
- const b3Scalar& yx, const b3Scalar& yy, const b3Scalar& yz,
- const b3Scalar& zx, const b3Scalar& zy, const b3Scalar& zz)
+ void setValue(const b3Scalar& xx, const b3Scalar& xy, const b3Scalar& xz,
+ const b3Scalar& yx, const b3Scalar& yy, const b3Scalar& yz,
+ const b3Scalar& zx, const b3Scalar& zy, const b3Scalar& zz)
{
- m_el[0].setValue(xx,xy,xz);
- m_el[1].setValue(yx,yy,yz);
- m_el[2].setValue(zx,zy,zz);
+ m_el[0].setValue(xx, xy, xz);
+ m_el[1].setValue(yx, yy, yz);
+ m_el[2].setValue(zx, zy, zz);
}
/** @brief Set the matrix from a quaternion
- * @param q The Quaternion to match */
- void setRotation(const b3Quaternion& q)
+ * @param q The Quaternion to match */
+ void setRotation(const b3Quaternion& q)
{
b3Scalar d = q.length2();
b3FullAssert(d != b3Scalar(0.0));
b3Scalar s = b3Scalar(2.0) / d;
-
- #if defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
- __m128 vs, Q = q.get128();
+
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+ __m128 vs, Q = q.get128();
__m128i Qi = b3CastfTo128i(Q);
- __m128 Y, Z;
- __m128 V1, V2, V3;
- __m128 V11, V21, V31;
- __m128 NQ = _mm_xor_ps(Q, b3vMzeroMask);
+ __m128 Y, Z;
+ __m128 V1, V2, V3;
+ __m128 V11, V21, V31;
+ __m128 NQ = _mm_xor_ps(Q, b3vMzeroMask);
__m128i NQi = b3CastfTo128i(NQ);
-
- V1 = b3CastiTo128f(_mm_shuffle_epi32 (Qi, B3_SHUFFLE(1,0,2,3))); // Y X Z W
- V2 = _mm_shuffle_ps(NQ, Q, B3_SHUFFLE(0,0,1,3)); // -X -X Y W
- V3 = b3CastiTo128f(_mm_shuffle_epi32 (Qi, B3_SHUFFLE(2,1,0,3))); // Z Y X W
- V1 = _mm_xor_ps(V1, b3vMPPP); // change the sign of the first element
-
- V11 = b3CastiTo128f(_mm_shuffle_epi32 (Qi, B3_SHUFFLE(1,1,0,3))); // Y Y X W
- V21 = _mm_unpackhi_ps(Q, Q); // Z Z W W
- V31 = _mm_shuffle_ps(Q, NQ, B3_SHUFFLE(0,2,0,3)); // X Z -X -W
-
- V2 = V2 * V1; //
- V1 = V1 * V11; //
- V3 = V3 * V31; //
-
- V11 = _mm_shuffle_ps(NQ, Q, B3_SHUFFLE(2,3,1,3)); // -Z -W Y W
- V11 = V11 * V21; //
- V21 = _mm_xor_ps(V21, b3vMPPP); // change the sign of the first element
- V31 = _mm_shuffle_ps(Q, NQ, B3_SHUFFLE(3,3,1,3)); // W W -Y -W
- V31 = _mm_xor_ps(V31, b3vMPPP); // change the sign of the first element
- Y = b3CastiTo128f(_mm_shuffle_epi32 (NQi, B3_SHUFFLE(3,2,0,3))); // -W -Z -X -W
- Z = b3CastiTo128f(_mm_shuffle_epi32 (Qi, B3_SHUFFLE(1,0,1,3))); // Y X Y W
+
+ V1 = b3CastiTo128f(_mm_shuffle_epi32(Qi, B3_SHUFFLE(1, 0, 2, 3))); // Y X Z W
+ V2 = _mm_shuffle_ps(NQ, Q, B3_SHUFFLE(0, 0, 1, 3)); // -X -X Y W
+ V3 = b3CastiTo128f(_mm_shuffle_epi32(Qi, B3_SHUFFLE(2, 1, 0, 3))); // Z Y X W
+ V1 = _mm_xor_ps(V1, b3vMPPP); // change the sign of the first element
+
+ V11 = b3CastiTo128f(_mm_shuffle_epi32(Qi, B3_SHUFFLE(1, 1, 0, 3))); // Y Y X W
+ V21 = _mm_unpackhi_ps(Q, Q); // Z Z W W
+ V31 = _mm_shuffle_ps(Q, NQ, B3_SHUFFLE(0, 2, 0, 3)); // X Z -X -W
+
+ V2 = V2 * V1; //
+ V1 = V1 * V11; //
+ V3 = V3 * V31; //
+
+ V11 = _mm_shuffle_ps(NQ, Q, B3_SHUFFLE(2, 3, 1, 3)); // -Z -W Y W
+ V11 = V11 * V21; //
+ V21 = _mm_xor_ps(V21, b3vMPPP); // change the sign of the first element
+ V31 = _mm_shuffle_ps(Q, NQ, B3_SHUFFLE(3, 3, 1, 3)); // W W -Y -W
+ V31 = _mm_xor_ps(V31, b3vMPPP); // change the sign of the first element
+ Y = b3CastiTo128f(_mm_shuffle_epi32(NQi, B3_SHUFFLE(3, 2, 0, 3))); // -W -Z -X -W
+ Z = b3CastiTo128f(_mm_shuffle_epi32(Qi, B3_SHUFFLE(1, 0, 1, 3))); // Y X Y W
vs = _mm_load_ss(&s);
V21 = V21 * Y;
V31 = V31 * Z;
V1 = V1 + V11;
- V2 = V2 + V21;
- V3 = V3 + V31;
-
- vs = b3_splat3_ps(vs, 0);
- // s ready
- V1 = V1 * vs;
- V2 = V2 * vs;
- V3 = V3 * vs;
-
- V1 = V1 + b3v1000;
- V2 = V2 + b3v0100;
- V3 = V3 + b3v0010;
-
- m_el[0] = b3MakeVector3(V1);
- m_el[1] = b3MakeVector3(V2);
- m_el[2] = b3MakeVector3(V3);
- #else
- b3Scalar xs = q.getX() * s, ys = q.getY() * s, zs = q.getZ() * s;
- b3Scalar wx = q.getW() * xs, wy = q.getW() * ys, wz = q.getW() * zs;
- b3Scalar xx = q.getX() * xs, xy = q.getX() * ys, xz = q.getX() * zs;
- b3Scalar yy = q.getY() * ys, yz = q.getY() * zs, zz = q.getZ() * zs;
+ V2 = V2 + V21;
+ V3 = V3 + V31;
+
+ vs = b3_splat3_ps(vs, 0);
+ // s ready
+ V1 = V1 * vs;
+ V2 = V2 * vs;
+ V3 = V3 * vs;
+
+ V1 = V1 + b3v1000;
+ V2 = V2 + b3v0100;
+ V3 = V3 + b3v0010;
+
+ m_el[0] = b3MakeVector3(V1);
+ m_el[1] = b3MakeVector3(V2);
+ m_el[2] = b3MakeVector3(V3);
+#else
+ b3Scalar xs = q.getX() * s, ys = q.getY() * s, zs = q.getZ() * s;
+ b3Scalar wx = q.getW() * xs, wy = q.getW() * ys, wz = q.getW() * zs;
+ b3Scalar xx = q.getX() * xs, xy = q.getX() * ys, xz = q.getX() * zs;
+ b3Scalar yy = q.getY() * ys, yz = q.getY() * zs, zz = q.getZ() * zs;
setValue(
- b3Scalar(1.0) - (yy + zz), xy - wz, xz + wy,
+ b3Scalar(1.0) - (yy + zz), xy - wz, xz + wy,
xy + wz, b3Scalar(1.0) - (xx + zz), yz - wx,
xz - wy, yz + wx, b3Scalar(1.0) - (xx + yy));
- #endif
- }
-
+#endif
+ }
/** @brief Set the matrix from euler angles using YPR around YXZ respectively
* @param yaw Yaw about Y axis
* @param pitch Pitch about X axis
* @param roll Roll about Z axis
*/
- void setEulerYPR(const b3Scalar& yaw, const b3Scalar& pitch, const b3Scalar& roll)
+ void setEulerYPR(const b3Scalar& yaw, const b3Scalar& pitch, const b3Scalar& roll)
{
setEulerZYX(roll, pitch, yaw);
}
@@ -290,182 +286,197 @@ public:
* angles are applied in ZYX order. I.e a vector is first rotated
* about X then Y and then Z
**/
- void setEulerZYX(b3Scalar eulerX,b3Scalar eulerY,b3Scalar eulerZ) {
+ void setEulerZYX(b3Scalar eulerX, b3Scalar eulerY, b3Scalar eulerZ)
+ {
///@todo proposed to reverse this since it's labeled zyx but takes arguments xyz and it will match all other parts of the code
- b3Scalar ci ( b3Cos(eulerX));
- b3Scalar cj ( b3Cos(eulerY));
- b3Scalar ch ( b3Cos(eulerZ));
- b3Scalar si ( b3Sin(eulerX));
- b3Scalar sj ( b3Sin(eulerY));
- b3Scalar sh ( b3Sin(eulerZ));
- b3Scalar cc = ci * ch;
- b3Scalar cs = ci * sh;
- b3Scalar sc = si * ch;
+ b3Scalar ci(b3Cos(eulerX));
+ b3Scalar cj(b3Cos(eulerY));
+ b3Scalar ch(b3Cos(eulerZ));
+ b3Scalar si(b3Sin(eulerX));
+ b3Scalar sj(b3Sin(eulerY));
+ b3Scalar sh(b3Sin(eulerZ));
+ b3Scalar cc = ci * ch;
+ b3Scalar cs = ci * sh;
+ b3Scalar sc = si * ch;
b3Scalar ss = si * sh;
setValue(cj * ch, sj * sc - cs, sj * cc + ss,
- cj * sh, sj * ss + cc, sj * cs - sc,
- -sj, cj * si, cj * ci);
+ cj * sh, sj * ss + cc, sj * cs - sc,
+ -sj, cj * si, cj * ci);
}
/**@brief Set the matrix to the identity */
void setIdentity()
- {
-#if (defined(B3_USE_SSE_IN_API)&& defined (B3_USE_SSE)) || defined(B3_USE_NEON)
- m_el[0] = b3MakeVector3(b3v1000);
- m_el[1] = b3MakeVector3(b3v0100);
- m_el[2] = b3MakeVector3(b3v0010);
+ {
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)) || defined(B3_USE_NEON)
+ m_el[0] = b3MakeVector3(b3v1000);
+ m_el[1] = b3MakeVector3(b3v0100);
+ m_el[2] = b3MakeVector3(b3v0010);
#else
- setValue(b3Scalar(1.0), b3Scalar(0.0), b3Scalar(0.0),
- b3Scalar(0.0), b3Scalar(1.0), b3Scalar(0.0),
- b3Scalar(0.0), b3Scalar(0.0), b3Scalar(1.0));
+ setValue(b3Scalar(1.0), b3Scalar(0.0), b3Scalar(0.0),
+ b3Scalar(0.0), b3Scalar(1.0), b3Scalar(0.0),
+ b3Scalar(0.0), b3Scalar(0.0), b3Scalar(1.0));
#endif
}
- static const b3Matrix3x3& getIdentity()
+ static const b3Matrix3x3& getIdentity()
{
-#if (defined(B3_USE_SSE_IN_API)&& defined (B3_USE_SSE)) || defined(B3_USE_NEON)
- static const b3Matrix3x3
- identityMatrix(b3v1000, b3v0100, b3v0010);
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)) || defined(B3_USE_NEON)
+ static const b3Matrix3x3
+ identityMatrix(b3v1000, b3v0100, b3v0010);
#else
- static const b3Matrix3x3
- identityMatrix(
- b3Scalar(1.0), b3Scalar(0.0), b3Scalar(0.0),
- b3Scalar(0.0), b3Scalar(1.0), b3Scalar(0.0),
- b3Scalar(0.0), b3Scalar(0.0), b3Scalar(1.0));
+ static const b3Matrix3x3
+ identityMatrix(
+ b3Scalar(1.0), b3Scalar(0.0), b3Scalar(0.0),
+ b3Scalar(0.0), b3Scalar(1.0), b3Scalar(0.0),
+ b3Scalar(0.0), b3Scalar(0.0), b3Scalar(1.0));
#endif
return identityMatrix;
}
/**@brief Fill the rotational part of an OpenGL matrix and clear the shear/perspective
* @param m The array to be filled */
- void getOpenGLSubMatrix(b3Scalar *m) const
+ void getOpenGLSubMatrix(b3Scalar * m) const
{
-#if defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
- __m128 v0 = m_el[0].mVec128;
- __m128 v1 = m_el[1].mVec128;
- __m128 v2 = m_el[2].mVec128; // x2 y2 z2 w2
- __m128 *vm = (__m128 *)m;
- __m128 vT;
-
- v2 = _mm_and_ps(v2, b3vFFF0fMask); // x2 y2 z2 0
-
- vT = _mm_unpackhi_ps(v0, v1); // z0 z1 * *
- v0 = _mm_unpacklo_ps(v0, v1); // x0 x1 y0 y1
-
- v1 = _mm_shuffle_ps(v0, v2, B3_SHUFFLE(2, 3, 1, 3) ); // y0 y1 y2 0
- v0 = _mm_shuffle_ps(v0, v2, B3_SHUFFLE(0, 1, 0, 3) ); // x0 x1 x2 0
- v2 = b3CastdTo128f(_mm_move_sd(b3CastfTo128d(v2), b3CastfTo128d(vT))); // z0 z1 z2 0
-
- vm[0] = v0;
- vm[1] = v1;
- vm[2] = v2;
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+ __m128 v0 = m_el[0].mVec128;
+ __m128 v1 = m_el[1].mVec128;
+ __m128 v2 = m_el[2].mVec128; // x2 y2 z2 w2
+ __m128* vm = (__m128*)m;
+ __m128 vT;
+
+ v2 = _mm_and_ps(v2, b3vFFF0fMask); // x2 y2 z2 0
+
+ vT = _mm_unpackhi_ps(v0, v1); // z0 z1 * *
+ v0 = _mm_unpacklo_ps(v0, v1); // x0 x1 y0 y1
+
+ v1 = _mm_shuffle_ps(v0, v2, B3_SHUFFLE(2, 3, 1, 3)); // y0 y1 y2 0
+ v0 = _mm_shuffle_ps(v0, v2, B3_SHUFFLE(0, 1, 0, 3)); // x0 x1 x2 0
+ v2 = b3CastdTo128f(_mm_move_sd(b3CastfTo128d(v2), b3CastfTo128d(vT))); // z0 z1 z2 0
+
+ vm[0] = v0;
+ vm[1] = v1;
+ vm[2] = v2;
#elif defined(B3_USE_NEON)
- // note: zeros the w channel. We can preserve it at the cost of two more vtrn instructions.
- static const uint32x2_t zMask = (const uint32x2_t) {-1, 0 };
- float32x4_t *vm = (float32x4_t *)m;
- float32x4x2_t top = vtrnq_f32( m_el[0].mVec128, m_el[1].mVec128 ); // {x0 x1 z0 z1}, {y0 y1 w0 w1}
- float32x2x2_t bl = vtrn_f32( vget_low_f32(m_el[2].mVec128), vdup_n_f32(0.0f) ); // {x2 0 }, {y2 0}
- float32x4_t v0 = vcombine_f32( vget_low_f32(top.val[0]), bl.val[0] );
- float32x4_t v1 = vcombine_f32( vget_low_f32(top.val[1]), bl.val[1] );
- float32x2_t q = (float32x2_t) vand_u32( (uint32x2_t) vget_high_f32( m_el[2].mVec128), zMask );
- float32x4_t v2 = vcombine_f32( vget_high_f32(top.val[0]), q ); // z0 z1 z2 0
-
- vm[0] = v0;
- vm[1] = v1;
- vm[2] = v2;
+ // note: zeros the w channel. We can preserve it at the cost of two more vtrn instructions.
+ static const uint32x2_t zMask = (const uint32x2_t){-1, 0};
+ float32x4_t* vm = (float32x4_t*)m;
+ float32x4x2_t top = vtrnq_f32(m_el[0].mVec128, m_el[1].mVec128); // {x0 x1 z0 z1}, {y0 y1 w0 w1}
+ float32x2x2_t bl = vtrn_f32(vget_low_f32(m_el[2].mVec128), vdup_n_f32(0.0f)); // {x2 0 }, {y2 0}
+ float32x4_t v0 = vcombine_f32(vget_low_f32(top.val[0]), bl.val[0]);
+ float32x4_t v1 = vcombine_f32(vget_low_f32(top.val[1]), bl.val[1]);
+ float32x2_t q = (float32x2_t)vand_u32((uint32x2_t)vget_high_f32(m_el[2].mVec128), zMask);
+ float32x4_t v2 = vcombine_f32(vget_high_f32(top.val[0]), q); // z0 z1 z2 0
+
+ vm[0] = v0;
+ vm[1] = v1;
+ vm[2] = v2;
#else
- m[0] = b3Scalar(m_el[0].getX());
- m[1] = b3Scalar(m_el[1].getX());
- m[2] = b3Scalar(m_el[2].getX());
- m[3] = b3Scalar(0.0);
- m[4] = b3Scalar(m_el[0].getY());
- m[5] = b3Scalar(m_el[1].getY());
- m[6] = b3Scalar(m_el[2].getY());
- m[7] = b3Scalar(0.0);
- m[8] = b3Scalar(m_el[0].getZ());
- m[9] = b3Scalar(m_el[1].getZ());
+ m[0] = b3Scalar(m_el[0].getX());
+ m[1] = b3Scalar(m_el[1].getX());
+ m[2] = b3Scalar(m_el[2].getX());
+ m[3] = b3Scalar(0.0);
+ m[4] = b3Scalar(m_el[0].getY());
+ m[5] = b3Scalar(m_el[1].getY());
+ m[6] = b3Scalar(m_el[2].getY());
+ m[7] = b3Scalar(0.0);
+ m[8] = b3Scalar(m_el[0].getZ());
+ m[9] = b3Scalar(m_el[1].getZ());
m[10] = b3Scalar(m_el[2].getZ());
- m[11] = b3Scalar(0.0);
+ m[11] = b3Scalar(0.0);
#endif
}
/**@brief Get the matrix represented as a quaternion
* @param q The quaternion which will be set */
- void getRotation(b3Quaternion& q) const
+ void getRotation(b3Quaternion & q) const
{
-#if (defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE))|| defined (B3_USE_NEON)
- b3Scalar trace = m_el[0].getX() + m_el[1].getY() + m_el[2].getZ();
- b3Scalar s, x;
-
- union {
- b3SimdFloat4 vec;
- b3Scalar f[4];
- } temp;
-
- if (trace > b3Scalar(0.0))
- {
- x = trace + b3Scalar(1.0);
-
- temp.f[0]=m_el[2].getY() - m_el[1].getZ();
- temp.f[1]=m_el[0].getZ() - m_el[2].getX();
- temp.f[2]=m_el[1].getX() - m_el[0].getY();
- temp.f[3]=x;
- //temp.f[3]= s * b3Scalar(0.5);
- }
- else
- {
- int i, j, k;
- if(m_el[0].getX() < m_el[1].getY())
- {
- if( m_el[1].getY() < m_el[2].getZ() )
- { i = 2; j = 0; k = 1; }
- else
- { i = 1; j = 2; k = 0; }
- }
- else
- {
- if( m_el[0].getX() < m_el[2].getZ())
- { i = 2; j = 0; k = 1; }
- else
- { i = 0; j = 1; k = 2; }
- }
-
- x = m_el[i][i] - m_el[j][j] - m_el[k][k] + b3Scalar(1.0);
-
- temp.f[3] = (m_el[k][j] - m_el[j][k]);
- temp.f[j] = (m_el[j][i] + m_el[i][j]);
- temp.f[k] = (m_el[k][i] + m_el[i][k]);
- temp.f[i] = x;
- //temp.f[i] = s * b3Scalar(0.5);
- }
-
- s = b3Sqrt(x);
- q.set128(temp.vec);
- s = b3Scalar(0.5) / s;
-
- q *= s;
-#else
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)) || defined(B3_USE_NEON)
+ b3Scalar trace = m_el[0].getX() + m_el[1].getY() + m_el[2].getZ();
+ b3Scalar s, x;
+
+ union {
+ b3SimdFloat4 vec;
+ b3Scalar f[4];
+ } temp;
+
+ if (trace > b3Scalar(0.0))
+ {
+ x = trace + b3Scalar(1.0);
+
+ temp.f[0] = m_el[2].getY() - m_el[1].getZ();
+ temp.f[1] = m_el[0].getZ() - m_el[2].getX();
+ temp.f[2] = m_el[1].getX() - m_el[0].getY();
+ temp.f[3] = x;
+ //temp.f[3]= s * b3Scalar(0.5);
+ }
+ else
+ {
+ int i, j, k;
+ if (m_el[0].getX() < m_el[1].getY())
+ {
+ if (m_el[1].getY() < m_el[2].getZ())
+ {
+ i = 2;
+ j = 0;
+ k = 1;
+ }
+ else
+ {
+ i = 1;
+ j = 2;
+ k = 0;
+ }
+ }
+ else
+ {
+ if (m_el[0].getX() < m_el[2].getZ())
+ {
+ i = 2;
+ j = 0;
+ k = 1;
+ }
+ else
+ {
+ i = 0;
+ j = 1;
+ k = 2;
+ }
+ }
+
+ x = m_el[i][i] - m_el[j][j] - m_el[k][k] + b3Scalar(1.0);
+
+ temp.f[3] = (m_el[k][j] - m_el[j][k]);
+ temp.f[j] = (m_el[j][i] + m_el[i][j]);
+ temp.f[k] = (m_el[k][i] + m_el[i][k]);
+ temp.f[i] = x;
+ //temp.f[i] = s * b3Scalar(0.5);
+ }
+
+ s = b3Sqrt(x);
+ q.set128(temp.vec);
+ s = b3Scalar(0.5) / s;
+
+ q *= s;
+#else
b3Scalar trace = m_el[0].getX() + m_el[1].getY() + m_el[2].getZ();
b3Scalar temp[4];
- if (trace > b3Scalar(0.0))
+ if (trace > b3Scalar(0.0))
{
b3Scalar s = b3Sqrt(trace + b3Scalar(1.0));
- temp[3]=(s * b3Scalar(0.5));
+ temp[3] = (s * b3Scalar(0.5));
s = b3Scalar(0.5) / s;
- temp[0]=((m_el[2].getY() - m_el[1].getZ()) * s);
- temp[1]=((m_el[0].getZ() - m_el[2].getX()) * s);
- temp[2]=((m_el[1].getX() - m_el[0].getY()) * s);
- }
- else
+ temp[0] = ((m_el[2].getY() - m_el[1].getZ()) * s);
+ temp[1] = ((m_el[0].getZ() - m_el[2].getX()) * s);
+ temp[2] = ((m_el[1].getX() - m_el[0].getY()) * s);
+ }
+ else
{
- int i = m_el[0].getX() < m_el[1].getY() ?
- (m_el[1].getY() < m_el[2].getZ() ? 2 : 1) :
- (m_el[0].getX() < m_el[2].getZ() ? 2 : 0);
- int j = (i + 1) % 3;
+ int i = m_el[0].getX() < m_el[1].getY() ? (m_el[1].getY() < m_el[2].getZ() ? 2 : 1) : (m_el[0].getX() < m_el[2].getZ() ? 2 : 0);
+ int j = (i + 1) % 3;
int k = (i + 2) % 3;
b3Scalar s = b3Sqrt(m_el[i][i] - m_el[j][j] - m_el[k][k] + b3Scalar(1.0));
@@ -476,44 +487,42 @@ public:
temp[j] = (m_el[j][i] + m_el[i][j]) * s;
temp[k] = (m_el[k][i] + m_el[i][k]) * s;
}
- q.setValue(temp[0],temp[1],temp[2],temp[3]);
+ q.setValue(temp[0], temp[1], temp[2], temp[3]);
#endif
}
/**@brief Get the matrix represented as euler angles around YXZ, roundtrip with setEulerYPR
* @param yaw Yaw around Y axis
* @param pitch Pitch around X axis
- * @param roll around Z axis */
- void getEulerYPR(b3Scalar& yaw, b3Scalar& pitch, b3Scalar& roll) const
+ * @param roll around Z axis */
+ void getEulerYPR(b3Scalar & yaw, b3Scalar & pitch, b3Scalar & roll) const
{
-
// first use the normal calculus
yaw = b3Scalar(b3Atan2(m_el[1].getX(), m_el[0].getX()));
pitch = b3Scalar(b3Asin(-m_el[2].getX()));
roll = b3Scalar(b3Atan2(m_el[2].getY(), m_el[2].getZ()));
// on pitch = +/-HalfPI
- if (b3Fabs(pitch)==B3_HALF_PI)
+ if (b3Fabs(pitch) == B3_HALF_PI)
{
- if (yaw>0)
- yaw-=B3_PI;
+ if (yaw > 0)
+ yaw -= B3_PI;
else
- yaw+=B3_PI;
+ yaw += B3_PI;
- if (roll>0)
- roll-=B3_PI;
+ if (roll > 0)
+ roll -= B3_PI;
else
- roll+=B3_PI;
+ roll += B3_PI;
}
};
-
/**@brief Get the matrix represented as euler angles around ZYX
* @param yaw Yaw around X axis
* @param pitch Pitch around Y axis
* @param roll around X axis
- * @param solution_number Which solution of two possible solutions ( 1 or 2) are possible values*/
- void getEulerZYX(b3Scalar& yaw, b3Scalar& pitch, b3Scalar& roll, unsigned int solution_number = 1) const
+ * @param solution_number Which solution of two possible solutions ( 1 or 2) are possible values*/
+ void getEulerZYX(b3Scalar & yaw, b3Scalar & pitch, b3Scalar & roll, unsigned int solution_number = 1) const
{
struct Euler
{
@@ -523,7 +532,7 @@ public:
};
Euler euler_out;
- Euler euler_out2; //second solution
+ Euler euler_out2; //second solution
//get the pointer to the raw data
// Check that pitch is not at a singularity
@@ -533,7 +542,7 @@ public:
euler_out2.yaw = 0;
// From difference of angles formula
- b3Scalar delta = b3Atan2(m_el[0].getX(),m_el[0].getZ());
+ b3Scalar delta = b3Atan2(m_el[0].getX(), m_el[0].getZ());
if (m_el[2].getX() > 0) //gimbal locked up
{
euler_out.pitch = B3_PI / b3Scalar(2.0);
@@ -541,7 +550,7 @@ public:
euler_out.roll = euler_out.pitch + delta;
euler_out2.roll = euler_out.pitch + delta;
}
- else // gimbal locked down
+ else // gimbal locked down
{
euler_out.pitch = -B3_PI / b3Scalar(2.0);
euler_out2.pitch = -B3_PI / b3Scalar(2.0);
@@ -551,29 +560,29 @@ public:
}
else
{
- euler_out.pitch = - b3Asin(m_el[2].getX());
+ euler_out.pitch = -b3Asin(m_el[2].getX());
euler_out2.pitch = B3_PI - euler_out.pitch;
- euler_out.roll = b3Atan2(m_el[2].getY()/b3Cos(euler_out.pitch),
- m_el[2].getZ()/b3Cos(euler_out.pitch));
- euler_out2.roll = b3Atan2(m_el[2].getY()/b3Cos(euler_out2.pitch),
- m_el[2].getZ()/b3Cos(euler_out2.pitch));
+ euler_out.roll = b3Atan2(m_el[2].getY() / b3Cos(euler_out.pitch),
+ m_el[2].getZ() / b3Cos(euler_out.pitch));
+ euler_out2.roll = b3Atan2(m_el[2].getY() / b3Cos(euler_out2.pitch),
+ m_el[2].getZ() / b3Cos(euler_out2.pitch));
- euler_out.yaw = b3Atan2(m_el[1].getX()/b3Cos(euler_out.pitch),
- m_el[0].getX()/b3Cos(euler_out.pitch));
- euler_out2.yaw = b3Atan2(m_el[1].getX()/b3Cos(euler_out2.pitch),
- m_el[0].getX()/b3Cos(euler_out2.pitch));
+ euler_out.yaw = b3Atan2(m_el[1].getX() / b3Cos(euler_out.pitch),
+ m_el[0].getX() / b3Cos(euler_out.pitch));
+ euler_out2.yaw = b3Atan2(m_el[1].getX() / b3Cos(euler_out2.pitch),
+ m_el[0].getX() / b3Cos(euler_out2.pitch));
}
if (solution_number == 1)
- {
- yaw = euler_out.yaw;
+ {
+ yaw = euler_out.yaw;
pitch = euler_out.pitch;
roll = euler_out.roll;
}
else
- {
- yaw = euler_out2.yaw;
+ {
+ yaw = euler_out2.yaw;
pitch = euler_out2.pitch;
roll = euler_out2.roll;
}
@@ -584,18 +593,18 @@ public:
b3Matrix3x3 scaled(const b3Vector3& s) const
{
-#if (defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE))|| defined (B3_USE_NEON)
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)) || defined(B3_USE_NEON)
return b3Matrix3x3(m_el[0] * s, m_el[1] * s, m_el[2] * s);
-#else
+#else
return b3Matrix3x3(
- m_el[0].getX() * s.getX(), m_el[0].getY() * s.getY(), m_el[0].getZ() * s.getZ(),
+ m_el[0].getX() * s.getX(), m_el[0].getY() * s.getY(), m_el[0].getZ() * s.getZ(),
m_el[1].getX() * s.getX(), m_el[1].getY() * s.getY(), m_el[1].getZ() * s.getZ(),
m_el[2].getX() * s.getX(), m_el[2].getY() * s.getY(), m_el[2].getZ() * s.getZ());
#endif
}
/**@brief Return the determinant of the matrix */
- b3Scalar determinant() const;
+ b3Scalar determinant() const;
/**@brief Return the adjoint of the matrix */
b3Matrix3x3 adjoint() const;
/**@brief Return the matrix with all values non negative */
@@ -603,25 +612,24 @@ public:
/**@brief Return the transpose of the matrix */
b3Matrix3x3 transpose() const;
/**@brief Return the inverse of the matrix */
- b3Matrix3x3 inverse() const;
+ b3Matrix3x3 inverse() const;
b3Matrix3x3 transposeTimes(const b3Matrix3x3& m) const;
b3Matrix3x3 timesTranspose(const b3Matrix3x3& m) const;
- B3_FORCE_INLINE b3Scalar tdotx(const b3Vector3& v) const
+ B3_FORCE_INLINE b3Scalar tdotx(const b3Vector3& v) const
{
return m_el[0].getX() * v.getX() + m_el[1].getX() * v.getY() + m_el[2].getX() * v.getZ();
}
- B3_FORCE_INLINE b3Scalar tdoty(const b3Vector3& v) const
+ B3_FORCE_INLINE b3Scalar tdoty(const b3Vector3& v) const
{
return m_el[0].getY() * v.getX() + m_el[1].getY() * v.getY() + m_el[2].getY() * v.getZ();
}
- B3_FORCE_INLINE b3Scalar tdotz(const b3Vector3& v) const
+ B3_FORCE_INLINE b3Scalar tdotz(const b3Vector3& v) const
{
return m_el[0].getZ() * v.getX() + m_el[1].getZ() * v.getY() + m_el[2].getZ() * v.getZ();
}
-
/**@brief diagonalizes this matrix by the Jacobi method.
* @param rot stores the rotation from the coordinate system in which the matrix is diagonal to the original
* coordinate system, i.e., old_this = rot * new_this * rot^T.
@@ -631,7 +639,7 @@ public:
*
* Note that this matrix is assumed to be symmetric.
*/
- void diagonalize(b3Matrix3x3& rot, b3Scalar threshold, int maxSteps)
+ void diagonalize(b3Matrix3x3 & rot, b3Scalar threshold, int maxSteps)
{
rot.setIdentity();
for (int step = maxSteps; step > 0; step--)
@@ -667,7 +675,7 @@ public:
step = 1;
}
- // compute Jacobi rotation J which leads to a zero for element [p][q]
+ // compute Jacobi rotation J which leads to a zero for element [p][q]
b3Scalar mpq = m_el[p][q];
b3Scalar theta = (m_el[q][q] - m_el[p][p]) / (2 * mpq);
b3Scalar theta2 = theta * theta;
@@ -676,7 +684,7 @@ public:
if (theta2 * theta2 < b3Scalar(10 / B3_EPSILON))
{
t = (theta >= 0) ? 1 / (theta + b3Sqrt(1 + theta2))
- : 1 / (theta - b3Sqrt(1 + theta2));
+ : 1 / (theta - b3Sqrt(1 + theta2));
cos = 1 / b3Sqrt(1 + t * t);
sin = cos * t;
}
@@ -709,9 +717,6 @@ public:
}
}
-
-
-
/**@brief Calculate the matrix cofactor
* @param r1 The first row to use for calculating the cofactor
* @param c1 The first column to use for calculating the cofactor
@@ -719,304 +724,298 @@ public:
* @param c1 The second column to use for calculating the cofactor
* See http://en.wikipedia.org/wiki/Cofactor_(linear_algebra) for more details
*/
- b3Scalar cofac(int r1, int c1, int r2, int c2) const
+ b3Scalar cofac(int r1, int c1, int r2, int c2) const
{
return m_el[r1][c1] * m_el[r2][c2] - m_el[r1][c2] * m_el[r2][c1];
}
- void serialize(struct b3Matrix3x3Data& dataOut) const;
+ void serialize(struct b3Matrix3x3Data & dataOut) const;
- void serializeFloat(struct b3Matrix3x3FloatData& dataOut) const;
+ void serializeFloat(struct b3Matrix3x3FloatData & dataOut) const;
- void deSerialize(const struct b3Matrix3x3Data& dataIn);
+ void deSerialize(const struct b3Matrix3x3Data& dataIn);
- void deSerializeFloat(const struct b3Matrix3x3FloatData& dataIn);
-
- void deSerializeDouble(const struct b3Matrix3x3DoubleData& dataIn);
+ void deSerializeFloat(const struct b3Matrix3x3FloatData& dataIn);
+ void deSerializeDouble(const struct b3Matrix3x3DoubleData& dataIn);
};
-
-B3_FORCE_INLINE b3Matrix3x3&
+B3_FORCE_INLINE b3Matrix3x3&
b3Matrix3x3::operator*=(const b3Matrix3x3& m)
{
-#if defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
- __m128 rv00, rv01, rv02;
- __m128 rv10, rv11, rv12;
- __m128 rv20, rv21, rv22;
- __m128 mv0, mv1, mv2;
-
- rv02 = m_el[0].mVec128;
- rv12 = m_el[1].mVec128;
- rv22 = m_el[2].mVec128;
-
- mv0 = _mm_and_ps(m[0].mVec128, b3vFFF0fMask);
- mv1 = _mm_and_ps(m[1].mVec128, b3vFFF0fMask);
- mv2 = _mm_and_ps(m[2].mVec128, b3vFFF0fMask);
-
- // rv0
- rv00 = b3_splat_ps(rv02, 0);
- rv01 = b3_splat_ps(rv02, 1);
- rv02 = b3_splat_ps(rv02, 2);
-
- rv00 = _mm_mul_ps(rv00, mv0);
- rv01 = _mm_mul_ps(rv01, mv1);
- rv02 = _mm_mul_ps(rv02, mv2);
-
- // rv1
- rv10 = b3_splat_ps(rv12, 0);
- rv11 = b3_splat_ps(rv12, 1);
- rv12 = b3_splat_ps(rv12, 2);
-
- rv10 = _mm_mul_ps(rv10, mv0);
- rv11 = _mm_mul_ps(rv11, mv1);
- rv12 = _mm_mul_ps(rv12, mv2);
-
- // rv2
- rv20 = b3_splat_ps(rv22, 0);
- rv21 = b3_splat_ps(rv22, 1);
- rv22 = b3_splat_ps(rv22, 2);
-
- rv20 = _mm_mul_ps(rv20, mv0);
- rv21 = _mm_mul_ps(rv21, mv1);
- rv22 = _mm_mul_ps(rv22, mv2);
-
- rv00 = _mm_add_ps(rv00, rv01);
- rv10 = _mm_add_ps(rv10, rv11);
- rv20 = _mm_add_ps(rv20, rv21);
-
- m_el[0].mVec128 = _mm_add_ps(rv00, rv02);
- m_el[1].mVec128 = _mm_add_ps(rv10, rv12);
- m_el[2].mVec128 = _mm_add_ps(rv20, rv22);
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+ __m128 rv00, rv01, rv02;
+ __m128 rv10, rv11, rv12;
+ __m128 rv20, rv21, rv22;
+ __m128 mv0, mv1, mv2;
+
+ rv02 = m_el[0].mVec128;
+ rv12 = m_el[1].mVec128;
+ rv22 = m_el[2].mVec128;
+
+ mv0 = _mm_and_ps(m[0].mVec128, b3vFFF0fMask);
+ mv1 = _mm_and_ps(m[1].mVec128, b3vFFF0fMask);
+ mv2 = _mm_and_ps(m[2].mVec128, b3vFFF0fMask);
+
+ // rv0
+ rv00 = b3_splat_ps(rv02, 0);
+ rv01 = b3_splat_ps(rv02, 1);
+ rv02 = b3_splat_ps(rv02, 2);
+
+ rv00 = _mm_mul_ps(rv00, mv0);
+ rv01 = _mm_mul_ps(rv01, mv1);
+ rv02 = _mm_mul_ps(rv02, mv2);
+
+ // rv1
+ rv10 = b3_splat_ps(rv12, 0);
+ rv11 = b3_splat_ps(rv12, 1);
+ rv12 = b3_splat_ps(rv12, 2);
+
+ rv10 = _mm_mul_ps(rv10, mv0);
+ rv11 = _mm_mul_ps(rv11, mv1);
+ rv12 = _mm_mul_ps(rv12, mv2);
+
+ // rv2
+ rv20 = b3_splat_ps(rv22, 0);
+ rv21 = b3_splat_ps(rv22, 1);
+ rv22 = b3_splat_ps(rv22, 2);
+
+ rv20 = _mm_mul_ps(rv20, mv0);
+ rv21 = _mm_mul_ps(rv21, mv1);
+ rv22 = _mm_mul_ps(rv22, mv2);
+
+ rv00 = _mm_add_ps(rv00, rv01);
+ rv10 = _mm_add_ps(rv10, rv11);
+ rv20 = _mm_add_ps(rv20, rv21);
+
+ m_el[0].mVec128 = _mm_add_ps(rv00, rv02);
+ m_el[1].mVec128 = _mm_add_ps(rv10, rv12);
+ m_el[2].mVec128 = _mm_add_ps(rv20, rv22);
#elif defined(B3_USE_NEON)
- float32x4_t rv0, rv1, rv2;
- float32x4_t v0, v1, v2;
- float32x4_t mv0, mv1, mv2;
-
- v0 = m_el[0].mVec128;
- v1 = m_el[1].mVec128;
- v2 = m_el[2].mVec128;
-
- mv0 = (float32x4_t) vandq_s32((int32x4_t)m[0].mVec128, b3vFFF0Mask);
- mv1 = (float32x4_t) vandq_s32((int32x4_t)m[1].mVec128, b3vFFF0Mask);
- mv2 = (float32x4_t) vandq_s32((int32x4_t)m[2].mVec128, b3vFFF0Mask);
-
- rv0 = vmulq_lane_f32(mv0, vget_low_f32(v0), 0);
- rv1 = vmulq_lane_f32(mv0, vget_low_f32(v1), 0);
- rv2 = vmulq_lane_f32(mv0, vget_low_f32(v2), 0);
-
- rv0 = vmlaq_lane_f32(rv0, mv1, vget_low_f32(v0), 1);
- rv1 = vmlaq_lane_f32(rv1, mv1, vget_low_f32(v1), 1);
- rv2 = vmlaq_lane_f32(rv2, mv1, vget_low_f32(v2), 1);
-
- rv0 = vmlaq_lane_f32(rv0, mv2, vget_high_f32(v0), 0);
- rv1 = vmlaq_lane_f32(rv1, mv2, vget_high_f32(v1), 0);
- rv2 = vmlaq_lane_f32(rv2, mv2, vget_high_f32(v2), 0);
-
- m_el[0].mVec128 = rv0;
- m_el[1].mVec128 = rv1;
- m_el[2].mVec128 = rv2;
-#else
+ float32x4_t rv0, rv1, rv2;
+ float32x4_t v0, v1, v2;
+ float32x4_t mv0, mv1, mv2;
+
+ v0 = m_el[0].mVec128;
+ v1 = m_el[1].mVec128;
+ v2 = m_el[2].mVec128;
+
+ mv0 = (float32x4_t)vandq_s32((int32x4_t)m[0].mVec128, b3vFFF0Mask);
+ mv1 = (float32x4_t)vandq_s32((int32x4_t)m[1].mVec128, b3vFFF0Mask);
+ mv2 = (float32x4_t)vandq_s32((int32x4_t)m[2].mVec128, b3vFFF0Mask);
+
+ rv0 = vmulq_lane_f32(mv0, vget_low_f32(v0), 0);
+ rv1 = vmulq_lane_f32(mv0, vget_low_f32(v1), 0);
+ rv2 = vmulq_lane_f32(mv0, vget_low_f32(v2), 0);
+
+ rv0 = vmlaq_lane_f32(rv0, mv1, vget_low_f32(v0), 1);
+ rv1 = vmlaq_lane_f32(rv1, mv1, vget_low_f32(v1), 1);
+ rv2 = vmlaq_lane_f32(rv2, mv1, vget_low_f32(v2), 1);
+
+ rv0 = vmlaq_lane_f32(rv0, mv2, vget_high_f32(v0), 0);
+ rv1 = vmlaq_lane_f32(rv1, mv2, vget_high_f32(v1), 0);
+ rv2 = vmlaq_lane_f32(rv2, mv2, vget_high_f32(v2), 0);
+
+ m_el[0].mVec128 = rv0;
+ m_el[1].mVec128 = rv1;
+ m_el[2].mVec128 = rv2;
+#else
setValue(
- m.tdotx(m_el[0]), m.tdoty(m_el[0]), m.tdotz(m_el[0]),
+ m.tdotx(m_el[0]), m.tdoty(m_el[0]), m.tdotz(m_el[0]),
m.tdotx(m_el[1]), m.tdoty(m_el[1]), m.tdotz(m_el[1]),
m.tdotx(m_el[2]), m.tdoty(m_el[2]), m.tdotz(m_el[2]));
#endif
return *this;
}
-B3_FORCE_INLINE b3Matrix3x3&
+B3_FORCE_INLINE b3Matrix3x3&
b3Matrix3x3::operator+=(const b3Matrix3x3& m)
{
-#if (defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE))|| defined (B3_USE_NEON)
- m_el[0].mVec128 = m_el[0].mVec128 + m.m_el[0].mVec128;
- m_el[1].mVec128 = m_el[1].mVec128 + m.m_el[1].mVec128;
- m_el[2].mVec128 = m_el[2].mVec128 + m.m_el[2].mVec128;
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)) || defined(B3_USE_NEON)
+ m_el[0].mVec128 = m_el[0].mVec128 + m.m_el[0].mVec128;
+ m_el[1].mVec128 = m_el[1].mVec128 + m.m_el[1].mVec128;
+ m_el[2].mVec128 = m_el[2].mVec128 + m.m_el[2].mVec128;
#else
setValue(
- m_el[0][0]+m.m_el[0][0],
- m_el[0][1]+m.m_el[0][1],
- m_el[0][2]+m.m_el[0][2],
- m_el[1][0]+m.m_el[1][0],
- m_el[1][1]+m.m_el[1][1],
- m_el[1][2]+m.m_el[1][2],
- m_el[2][0]+m.m_el[2][0],
- m_el[2][1]+m.m_el[2][1],
- m_el[2][2]+m.m_el[2][2]);
+ m_el[0][0] + m.m_el[0][0],
+ m_el[0][1] + m.m_el[0][1],
+ m_el[0][2] + m.m_el[0][2],
+ m_el[1][0] + m.m_el[1][0],
+ m_el[1][1] + m.m_el[1][1],
+ m_el[1][2] + m.m_el[1][2],
+ m_el[2][0] + m.m_el[2][0],
+ m_el[2][1] + m.m_el[2][1],
+ m_el[2][2] + m.m_el[2][2]);
#endif
return *this;
}
B3_FORCE_INLINE b3Matrix3x3
-operator*(const b3Matrix3x3& m, const b3Scalar & k)
+operator*(const b3Matrix3x3& m, const b3Scalar& k)
{
-#if (defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE))
- __m128 vk = b3_splat_ps(_mm_load_ss((float *)&k), 0x80);
- return b3Matrix3x3(
- _mm_mul_ps(m[0].mVec128, vk),
- _mm_mul_ps(m[1].mVec128, vk),
- _mm_mul_ps(m[2].mVec128, vk));
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE))
+ __m128 vk = b3_splat_ps(_mm_load_ss((float*)&k), 0x80);
+ return b3Matrix3x3(
+ _mm_mul_ps(m[0].mVec128, vk),
+ _mm_mul_ps(m[1].mVec128, vk),
+ _mm_mul_ps(m[2].mVec128, vk));
#elif defined(B3_USE_NEON)
- return b3Matrix3x3(
- vmulq_n_f32(m[0].mVec128, k),
- vmulq_n_f32(m[1].mVec128, k),
- vmulq_n_f32(m[2].mVec128, k));
+ return b3Matrix3x3(
+ vmulq_n_f32(m[0].mVec128, k),
+ vmulq_n_f32(m[1].mVec128, k),
+ vmulq_n_f32(m[2].mVec128, k));
#else
return b3Matrix3x3(
- m[0].getX()*k,m[0].getY()*k,m[0].getZ()*k,
- m[1].getX()*k,m[1].getY()*k,m[1].getZ()*k,
- m[2].getX()*k,m[2].getY()*k,m[2].getZ()*k);
+ m[0].getX() * k, m[0].getY() * k, m[0].getZ() * k,
+ m[1].getX() * k, m[1].getY() * k, m[1].getZ() * k,
+ m[2].getX() * k, m[2].getY() * k, m[2].getZ() * k);
#endif
}
-B3_FORCE_INLINE b3Matrix3x3
+B3_FORCE_INLINE b3Matrix3x3
operator+(const b3Matrix3x3& m1, const b3Matrix3x3& m2)
{
-#if (defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE))|| defined (B3_USE_NEON)
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)) || defined(B3_USE_NEON)
return b3Matrix3x3(
- m1[0].mVec128 + m2[0].mVec128,
- m1[1].mVec128 + m2[1].mVec128,
- m1[2].mVec128 + m2[2].mVec128);
+ m1[0].mVec128 + m2[0].mVec128,
+ m1[1].mVec128 + m2[1].mVec128,
+ m1[2].mVec128 + m2[2].mVec128);
#else
return b3Matrix3x3(
- m1[0][0]+m2[0][0],
- m1[0][1]+m2[0][1],
- m1[0][2]+m2[0][2],
-
- m1[1][0]+m2[1][0],
- m1[1][1]+m2[1][1],
- m1[1][2]+m2[1][2],
-
- m1[2][0]+m2[2][0],
- m1[2][1]+m2[2][1],
- m1[2][2]+m2[2][2]);
-#endif
+ m1[0][0] + m2[0][0],
+ m1[0][1] + m2[0][1],
+ m1[0][2] + m2[0][2],
+
+ m1[1][0] + m2[1][0],
+ m1[1][1] + m2[1][1],
+ m1[1][2] + m2[1][2],
+
+ m1[2][0] + m2[2][0],
+ m1[2][1] + m2[2][1],
+ m1[2][2] + m2[2][2]);
+#endif
}
-B3_FORCE_INLINE b3Matrix3x3
+B3_FORCE_INLINE b3Matrix3x3
operator-(const b3Matrix3x3& m1, const b3Matrix3x3& m2)
{
-#if (defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE))|| defined (B3_USE_NEON)
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)) || defined(B3_USE_NEON)
return b3Matrix3x3(
- m1[0].mVec128 - m2[0].mVec128,
- m1[1].mVec128 - m2[1].mVec128,
- m1[2].mVec128 - m2[2].mVec128);
+ m1[0].mVec128 - m2[0].mVec128,
+ m1[1].mVec128 - m2[1].mVec128,
+ m1[2].mVec128 - m2[2].mVec128);
#else
return b3Matrix3x3(
- m1[0][0]-m2[0][0],
- m1[0][1]-m2[0][1],
- m1[0][2]-m2[0][2],
-
- m1[1][0]-m2[1][0],
- m1[1][1]-m2[1][1],
- m1[1][2]-m2[1][2],
-
- m1[2][0]-m2[2][0],
- m1[2][1]-m2[2][1],
- m1[2][2]-m2[2][2]);
+ m1[0][0] - m2[0][0],
+ m1[0][1] - m2[0][1],
+ m1[0][2] - m2[0][2],
+
+ m1[1][0] - m2[1][0],
+ m1[1][1] - m2[1][1],
+ m1[1][2] - m2[1][2],
+
+ m1[2][0] - m2[2][0],
+ m1[2][1] - m2[2][1],
+ m1[2][2] - m2[2][2]);
#endif
}
-
-B3_FORCE_INLINE b3Matrix3x3&
+B3_FORCE_INLINE b3Matrix3x3&
b3Matrix3x3::operator-=(const b3Matrix3x3& m)
{
-#if (defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE))|| defined (B3_USE_NEON)
- m_el[0].mVec128 = m_el[0].mVec128 - m.m_el[0].mVec128;
- m_el[1].mVec128 = m_el[1].mVec128 - m.m_el[1].mVec128;
- m_el[2].mVec128 = m_el[2].mVec128 - m.m_el[2].mVec128;
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)) || defined(B3_USE_NEON)
+ m_el[0].mVec128 = m_el[0].mVec128 - m.m_el[0].mVec128;
+ m_el[1].mVec128 = m_el[1].mVec128 - m.m_el[1].mVec128;
+ m_el[2].mVec128 = m_el[2].mVec128 - m.m_el[2].mVec128;
#else
setValue(
- m_el[0][0]-m.m_el[0][0],
- m_el[0][1]-m.m_el[0][1],
- m_el[0][2]-m.m_el[0][2],
- m_el[1][0]-m.m_el[1][0],
- m_el[1][1]-m.m_el[1][1],
- m_el[1][2]-m.m_el[1][2],
- m_el[2][0]-m.m_el[2][0],
- m_el[2][1]-m.m_el[2][1],
- m_el[2][2]-m.m_el[2][2]);
+ m_el[0][0] - m.m_el[0][0],
+ m_el[0][1] - m.m_el[0][1],
+ m_el[0][2] - m.m_el[0][2],
+ m_el[1][0] - m.m_el[1][0],
+ m_el[1][1] - m.m_el[1][1],
+ m_el[1][2] - m.m_el[1][2],
+ m_el[2][0] - m.m_el[2][0],
+ m_el[2][1] - m.m_el[2][1],
+ m_el[2][2] - m.m_el[2][2]);
#endif
return *this;
}
-
-B3_FORCE_INLINE b3Scalar
+B3_FORCE_INLINE b3Scalar
b3Matrix3x3::determinant() const
-{
+{
return b3Triple((*this)[0], (*this)[1], (*this)[2]);
}
-
-B3_FORCE_INLINE b3Matrix3x3
+B3_FORCE_INLINE b3Matrix3x3
b3Matrix3x3::absolute() const
{
-#if (defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE))
- return b3Matrix3x3(
- _mm_and_ps(m_el[0].mVec128, b3vAbsfMask),
- _mm_and_ps(m_el[1].mVec128, b3vAbsfMask),
- _mm_and_ps(m_el[2].mVec128, b3vAbsfMask));
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE))
+ return b3Matrix3x3(
+ _mm_and_ps(m_el[0].mVec128, b3vAbsfMask),
+ _mm_and_ps(m_el[1].mVec128, b3vAbsfMask),
+ _mm_and_ps(m_el[2].mVec128, b3vAbsfMask));
#elif defined(B3_USE_NEON)
- return b3Matrix3x3(
- (float32x4_t)vandq_s32((int32x4_t)m_el[0].mVec128, b3v3AbsMask),
- (float32x4_t)vandq_s32((int32x4_t)m_el[1].mVec128, b3v3AbsMask),
- (float32x4_t)vandq_s32((int32x4_t)m_el[2].mVec128, b3v3AbsMask));
-#else
return b3Matrix3x3(
- b3Fabs(m_el[0].getX()), b3Fabs(m_el[0].getY()), b3Fabs(m_el[0].getZ()),
- b3Fabs(m_el[1].getX()), b3Fabs(m_el[1].getY()), b3Fabs(m_el[1].getZ()),
- b3Fabs(m_el[2].getX()), b3Fabs(m_el[2].getY()), b3Fabs(m_el[2].getZ()));
+ (float32x4_t)vandq_s32((int32x4_t)m_el[0].mVec128, b3v3AbsMask),
+ (float32x4_t)vandq_s32((int32x4_t)m_el[1].mVec128, b3v3AbsMask),
+ (float32x4_t)vandq_s32((int32x4_t)m_el[2].mVec128, b3v3AbsMask));
+#else
+ return b3Matrix3x3(
+ b3Fabs(m_el[0].getX()), b3Fabs(m_el[0].getY()), b3Fabs(m_el[0].getZ()),
+ b3Fabs(m_el[1].getX()), b3Fabs(m_el[1].getY()), b3Fabs(m_el[1].getZ()),
+ b3Fabs(m_el[2].getX()), b3Fabs(m_el[2].getY()), b3Fabs(m_el[2].getZ()));
#endif
}
-B3_FORCE_INLINE b3Matrix3x3
-b3Matrix3x3::transpose() const
+B3_FORCE_INLINE b3Matrix3x3
+b3Matrix3x3::transpose() const
{
-#if (defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE))
- __m128 v0 = m_el[0].mVec128;
- __m128 v1 = m_el[1].mVec128;
- __m128 v2 = m_el[2].mVec128; // x2 y2 z2 w2
- __m128 vT;
-
- v2 = _mm_and_ps(v2, b3vFFF0fMask); // x2 y2 z2 0
-
- vT = _mm_unpackhi_ps(v0, v1); // z0 z1 * *
- v0 = _mm_unpacklo_ps(v0, v1); // x0 x1 y0 y1
-
- v1 = _mm_shuffle_ps(v0, v2, B3_SHUFFLE(2, 3, 1, 3) ); // y0 y1 y2 0
- v0 = _mm_shuffle_ps(v0, v2, B3_SHUFFLE(0, 1, 0, 3) ); // x0 x1 x2 0
- v2 = b3CastdTo128f(_mm_move_sd(b3CastfTo128d(v2), b3CastfTo128d(vT))); // z0 z1 z2 0
-
-
- return b3Matrix3x3( v0, v1, v2 );
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE))
+ __m128 v0 = m_el[0].mVec128;
+ __m128 v1 = m_el[1].mVec128;
+ __m128 v2 = m_el[2].mVec128; // x2 y2 z2 w2
+ __m128 vT;
+
+ v2 = _mm_and_ps(v2, b3vFFF0fMask); // x2 y2 z2 0
+
+ vT = _mm_unpackhi_ps(v0, v1); // z0 z1 * *
+ v0 = _mm_unpacklo_ps(v0, v1); // x0 x1 y0 y1
+
+ v1 = _mm_shuffle_ps(v0, v2, B3_SHUFFLE(2, 3, 1, 3)); // y0 y1 y2 0
+ v0 = _mm_shuffle_ps(v0, v2, B3_SHUFFLE(0, 1, 0, 3)); // x0 x1 x2 0
+ v2 = b3CastdTo128f(_mm_move_sd(b3CastfTo128d(v2), b3CastfTo128d(vT))); // z0 z1 z2 0
+
+ return b3Matrix3x3(v0, v1, v2);
#elif defined(B3_USE_NEON)
- // note: zeros the w channel. We can preserve it at the cost of two more vtrn instructions.
- static const uint32x2_t zMask = (const uint32x2_t) {-1, 0 };
- float32x4x2_t top = vtrnq_f32( m_el[0].mVec128, m_el[1].mVec128 ); // {x0 x1 z0 z1}, {y0 y1 w0 w1}
- float32x2x2_t bl = vtrn_f32( vget_low_f32(m_el[2].mVec128), vdup_n_f32(0.0f) ); // {x2 0 }, {y2 0}
- float32x4_t v0 = vcombine_f32( vget_low_f32(top.val[0]), bl.val[0] );
- float32x4_t v1 = vcombine_f32( vget_low_f32(top.val[1]), bl.val[1] );
- float32x2_t q = (float32x2_t) vand_u32( (uint32x2_t) vget_high_f32( m_el[2].mVec128), zMask );
- float32x4_t v2 = vcombine_f32( vget_high_f32(top.val[0]), q ); // z0 z1 z2 0
- return b3Matrix3x3( v0, v1, v2 );
+ // note: zeros the w channel. We can preserve it at the cost of two more vtrn instructions.
+ static const uint32x2_t zMask = (const uint32x2_t){-1, 0};
+ float32x4x2_t top = vtrnq_f32(m_el[0].mVec128, m_el[1].mVec128); // {x0 x1 z0 z1}, {y0 y1 w0 w1}
+ float32x2x2_t bl = vtrn_f32(vget_low_f32(m_el[2].mVec128), vdup_n_f32(0.0f)); // {x2 0 }, {y2 0}
+ float32x4_t v0 = vcombine_f32(vget_low_f32(top.val[0]), bl.val[0]);
+ float32x4_t v1 = vcombine_f32(vget_low_f32(top.val[1]), bl.val[1]);
+ float32x2_t q = (float32x2_t)vand_u32((uint32x2_t)vget_high_f32(m_el[2].mVec128), zMask);
+ float32x4_t v2 = vcombine_f32(vget_high_f32(top.val[0]), q); // z0 z1 z2 0
+ return b3Matrix3x3(v0, v1, v2);
#else
- return b3Matrix3x3( m_el[0].getX(), m_el[1].getX(), m_el[2].getX(),
- m_el[0].getY(), m_el[1].getY(), m_el[2].getY(),
- m_el[0].getZ(), m_el[1].getZ(), m_el[2].getZ());
+ return b3Matrix3x3(m_el[0].getX(), m_el[1].getX(), m_el[2].getX(),
+ m_el[0].getY(), m_el[1].getY(), m_el[2].getY(),
+ m_el[0].getZ(), m_el[1].getZ(), m_el[2].getZ());
#endif
}
-B3_FORCE_INLINE b3Matrix3x3
-b3Matrix3x3::adjoint() const
+B3_FORCE_INLINE b3Matrix3x3
+b3Matrix3x3::adjoint() const
{
return b3Matrix3x3(cofac(1, 1, 2, 2), cofac(0, 2, 2, 1), cofac(0, 1, 1, 2),
- cofac(1, 2, 2, 0), cofac(0, 0, 2, 2), cofac(0, 2, 1, 0),
- cofac(1, 0, 2, 1), cofac(0, 1, 2, 0), cofac(0, 0, 1, 1));
+ cofac(1, 2, 2, 0), cofac(0, 0, 2, 2), cofac(0, 2, 1, 0),
+ cofac(1, 0, 2, 1), cofac(0, 1, 2, 0), cofac(0, 0, 1, 1));
}
-B3_FORCE_INLINE b3Matrix3x3
+B3_FORCE_INLINE b3Matrix3x3
b3Matrix3x3::inverse() const
{
b3Vector3 co = b3MakeVector3(cofac(1, 1, 2, 2), cofac(1, 2, 2, 0), cofac(1, 0, 2, 1));
@@ -1024,54 +1023,54 @@ b3Matrix3x3::inverse() const
b3FullAssert(det != b3Scalar(0.0));
b3Scalar s = b3Scalar(1.0) / det;
return b3Matrix3x3(co.getX() * s, cofac(0, 2, 2, 1) * s, cofac(0, 1, 1, 2) * s,
- co.getY() * s, cofac(0, 0, 2, 2) * s, cofac(0, 2, 1, 0) * s,
- co.getZ() * s, cofac(0, 1, 2, 0) * s, cofac(0, 0, 1, 1) * s);
+ co.getY() * s, cofac(0, 0, 2, 2) * s, cofac(0, 2, 1, 0) * s,
+ co.getZ() * s, cofac(0, 1, 2, 0) * s, cofac(0, 0, 1, 1) * s);
}
-B3_FORCE_INLINE b3Matrix3x3
+B3_FORCE_INLINE b3Matrix3x3
b3Matrix3x3::transposeTimes(const b3Matrix3x3& m) const
{
-#if (defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE))
- // zeros w
-// static const __m128i xyzMask = (const __m128i){ -1ULL, 0xffffffffULL };
- __m128 row = m_el[0].mVec128;
- __m128 m0 = _mm_and_ps( m.getRow(0).mVec128, b3vFFF0fMask );
- __m128 m1 = _mm_and_ps( m.getRow(1).mVec128, b3vFFF0fMask);
- __m128 m2 = _mm_and_ps( m.getRow(2).mVec128, b3vFFF0fMask );
- __m128 r0 = _mm_mul_ps(m0, _mm_shuffle_ps(row, row, 0));
- __m128 r1 = _mm_mul_ps(m0, _mm_shuffle_ps(row, row, 0x55));
- __m128 r2 = _mm_mul_ps(m0, _mm_shuffle_ps(row, row, 0xaa));
- row = m_el[1].mVec128;
- r0 = _mm_add_ps( r0, _mm_mul_ps(m1, _mm_shuffle_ps(row, row, 0)));
- r1 = _mm_add_ps( r1, _mm_mul_ps(m1, _mm_shuffle_ps(row, row, 0x55)));
- r2 = _mm_add_ps( r2, _mm_mul_ps(m1, _mm_shuffle_ps(row, row, 0xaa)));
- row = m_el[2].mVec128;
- r0 = _mm_add_ps( r0, _mm_mul_ps(m2, _mm_shuffle_ps(row, row, 0)));
- r1 = _mm_add_ps( r1, _mm_mul_ps(m2, _mm_shuffle_ps(row, row, 0x55)));
- r2 = _mm_add_ps( r2, _mm_mul_ps(m2, _mm_shuffle_ps(row, row, 0xaa)));
- return b3Matrix3x3( r0, r1, r2 );
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE))
+ // zeros w
+ // static const __m128i xyzMask = (const __m128i){ -1ULL, 0xffffffffULL };
+ __m128 row = m_el[0].mVec128;
+ __m128 m0 = _mm_and_ps(m.getRow(0).mVec128, b3vFFF0fMask);
+ __m128 m1 = _mm_and_ps(m.getRow(1).mVec128, b3vFFF0fMask);
+ __m128 m2 = _mm_and_ps(m.getRow(2).mVec128, b3vFFF0fMask);
+ __m128 r0 = _mm_mul_ps(m0, _mm_shuffle_ps(row, row, 0));
+ __m128 r1 = _mm_mul_ps(m0, _mm_shuffle_ps(row, row, 0x55));
+ __m128 r2 = _mm_mul_ps(m0, _mm_shuffle_ps(row, row, 0xaa));
+ row = m_el[1].mVec128;
+ r0 = _mm_add_ps(r0, _mm_mul_ps(m1, _mm_shuffle_ps(row, row, 0)));
+ r1 = _mm_add_ps(r1, _mm_mul_ps(m1, _mm_shuffle_ps(row, row, 0x55)));
+ r2 = _mm_add_ps(r2, _mm_mul_ps(m1, _mm_shuffle_ps(row, row, 0xaa)));
+ row = m_el[2].mVec128;
+ r0 = _mm_add_ps(r0, _mm_mul_ps(m2, _mm_shuffle_ps(row, row, 0)));
+ r1 = _mm_add_ps(r1, _mm_mul_ps(m2, _mm_shuffle_ps(row, row, 0x55)));
+ r2 = _mm_add_ps(r2, _mm_mul_ps(m2, _mm_shuffle_ps(row, row, 0xaa)));
+ return b3Matrix3x3(r0, r1, r2);
#elif defined B3_USE_NEON
- // zeros w
- static const uint32x4_t xyzMask = (const uint32x4_t){ -1, -1, -1, 0 };
- float32x4_t m0 = (float32x4_t) vandq_u32( (uint32x4_t) m.getRow(0).mVec128, xyzMask );
- float32x4_t m1 = (float32x4_t) vandq_u32( (uint32x4_t) m.getRow(1).mVec128, xyzMask );
- float32x4_t m2 = (float32x4_t) vandq_u32( (uint32x4_t) m.getRow(2).mVec128, xyzMask );
- float32x4_t row = m_el[0].mVec128;
- float32x4_t r0 = vmulq_lane_f32( m0, vget_low_f32(row), 0);
- float32x4_t r1 = vmulq_lane_f32( m0, vget_low_f32(row), 1);
- float32x4_t r2 = vmulq_lane_f32( m0, vget_high_f32(row), 0);
- row = m_el[1].mVec128;
- r0 = vmlaq_lane_f32( r0, m1, vget_low_f32(row), 0);
- r1 = vmlaq_lane_f32( r1, m1, vget_low_f32(row), 1);
- r2 = vmlaq_lane_f32( r2, m1, vget_high_f32(row), 0);
- row = m_el[2].mVec128;
- r0 = vmlaq_lane_f32( r0, m2, vget_low_f32(row), 0);
- r1 = vmlaq_lane_f32( r1, m2, vget_low_f32(row), 1);
- r2 = vmlaq_lane_f32( r2, m2, vget_high_f32(row), 0);
- return b3Matrix3x3( r0, r1, r2 );
+ // zeros w
+ static const uint32x4_t xyzMask = (const uint32x4_t){-1, -1, -1, 0};
+ float32x4_t m0 = (float32x4_t)vandq_u32((uint32x4_t)m.getRow(0).mVec128, xyzMask);
+ float32x4_t m1 = (float32x4_t)vandq_u32((uint32x4_t)m.getRow(1).mVec128, xyzMask);
+ float32x4_t m2 = (float32x4_t)vandq_u32((uint32x4_t)m.getRow(2).mVec128, xyzMask);
+ float32x4_t row = m_el[0].mVec128;
+ float32x4_t r0 = vmulq_lane_f32(m0, vget_low_f32(row), 0);
+ float32x4_t r1 = vmulq_lane_f32(m0, vget_low_f32(row), 1);
+ float32x4_t r2 = vmulq_lane_f32(m0, vget_high_f32(row), 0);
+ row = m_el[1].mVec128;
+ r0 = vmlaq_lane_f32(r0, m1, vget_low_f32(row), 0);
+ r1 = vmlaq_lane_f32(r1, m1, vget_low_f32(row), 1);
+ r2 = vmlaq_lane_f32(r2, m1, vget_high_f32(row), 0);
+ row = m_el[2].mVec128;
+ r0 = vmlaq_lane_f32(r0, m2, vget_low_f32(row), 0);
+ r1 = vmlaq_lane_f32(r1, m2, vget_low_f32(row), 1);
+ r2 = vmlaq_lane_f32(r2, m2, vget_high_f32(row), 0);
+ return b3Matrix3x3(r0, r1, r2);
#else
- return b3Matrix3x3(
+ return b3Matrix3x3(
m_el[0].getX() * m[0].getX() + m_el[1].getX() * m[1].getX() + m_el[2].getX() * m[2].getX(),
m_el[0].getX() * m[0].getY() + m_el[1].getX() * m[1].getY() + m_el[2].getX() * m[2].getY(),
m_el[0].getX() * m[0].getZ() + m_el[1].getX() * m[1].getZ() + m_el[2].getX() * m[2].getZ(),
@@ -1084,51 +1083,51 @@ b3Matrix3x3::transposeTimes(const b3Matrix3x3& m) const
#endif
}
-B3_FORCE_INLINE b3Matrix3x3
+B3_FORCE_INLINE b3Matrix3x3
b3Matrix3x3::timesTranspose(const b3Matrix3x3& m) const
{
-#if (defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE))
- __m128 a0 = m_el[0].mVec128;
- __m128 a1 = m_el[1].mVec128;
- __m128 a2 = m_el[2].mVec128;
-
- b3Matrix3x3 mT = m.transpose(); // we rely on transpose() zeroing w channel so that we don't have to do it here
- __m128 mx = mT[0].mVec128;
- __m128 my = mT[1].mVec128;
- __m128 mz = mT[2].mVec128;
-
- __m128 r0 = _mm_mul_ps(mx, _mm_shuffle_ps(a0, a0, 0x00));
- __m128 r1 = _mm_mul_ps(mx, _mm_shuffle_ps(a1, a1, 0x00));
- __m128 r2 = _mm_mul_ps(mx, _mm_shuffle_ps(a2, a2, 0x00));
- r0 = _mm_add_ps(r0, _mm_mul_ps(my, _mm_shuffle_ps(a0, a0, 0x55)));
- r1 = _mm_add_ps(r1, _mm_mul_ps(my, _mm_shuffle_ps(a1, a1, 0x55)));
- r2 = _mm_add_ps(r2, _mm_mul_ps(my, _mm_shuffle_ps(a2, a2, 0x55)));
- r0 = _mm_add_ps(r0, _mm_mul_ps(mz, _mm_shuffle_ps(a0, a0, 0xaa)));
- r1 = _mm_add_ps(r1, _mm_mul_ps(mz, _mm_shuffle_ps(a1, a1, 0xaa)));
- r2 = _mm_add_ps(r2, _mm_mul_ps(mz, _mm_shuffle_ps(a2, a2, 0xaa)));
- return b3Matrix3x3( r0, r1, r2);
-
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE))
+ __m128 a0 = m_el[0].mVec128;
+ __m128 a1 = m_el[1].mVec128;
+ __m128 a2 = m_el[2].mVec128;
+
+ b3Matrix3x3 mT = m.transpose(); // we rely on transpose() zeroing w channel so that we don't have to do it here
+ __m128 mx = mT[0].mVec128;
+ __m128 my = mT[1].mVec128;
+ __m128 mz = mT[2].mVec128;
+
+ __m128 r0 = _mm_mul_ps(mx, _mm_shuffle_ps(a0, a0, 0x00));
+ __m128 r1 = _mm_mul_ps(mx, _mm_shuffle_ps(a1, a1, 0x00));
+ __m128 r2 = _mm_mul_ps(mx, _mm_shuffle_ps(a2, a2, 0x00));
+ r0 = _mm_add_ps(r0, _mm_mul_ps(my, _mm_shuffle_ps(a0, a0, 0x55)));
+ r1 = _mm_add_ps(r1, _mm_mul_ps(my, _mm_shuffle_ps(a1, a1, 0x55)));
+ r2 = _mm_add_ps(r2, _mm_mul_ps(my, _mm_shuffle_ps(a2, a2, 0x55)));
+ r0 = _mm_add_ps(r0, _mm_mul_ps(mz, _mm_shuffle_ps(a0, a0, 0xaa)));
+ r1 = _mm_add_ps(r1, _mm_mul_ps(mz, _mm_shuffle_ps(a1, a1, 0xaa)));
+ r2 = _mm_add_ps(r2, _mm_mul_ps(mz, _mm_shuffle_ps(a2, a2, 0xaa)));
+ return b3Matrix3x3(r0, r1, r2);
+
#elif defined B3_USE_NEON
- float32x4_t a0 = m_el[0].mVec128;
- float32x4_t a1 = m_el[1].mVec128;
- float32x4_t a2 = m_el[2].mVec128;
-
- b3Matrix3x3 mT = m.transpose(); // we rely on transpose() zeroing w channel so that we don't have to do it here
- float32x4_t mx = mT[0].mVec128;
- float32x4_t my = mT[1].mVec128;
- float32x4_t mz = mT[2].mVec128;
-
- float32x4_t r0 = vmulq_lane_f32( mx, vget_low_f32(a0), 0);
- float32x4_t r1 = vmulq_lane_f32( mx, vget_low_f32(a1), 0);
- float32x4_t r2 = vmulq_lane_f32( mx, vget_low_f32(a2), 0);
- r0 = vmlaq_lane_f32( r0, my, vget_low_f32(a0), 1);
- r1 = vmlaq_lane_f32( r1, my, vget_low_f32(a1), 1);
- r2 = vmlaq_lane_f32( r2, my, vget_low_f32(a2), 1);
- r0 = vmlaq_lane_f32( r0, mz, vget_high_f32(a0), 0);
- r1 = vmlaq_lane_f32( r1, mz, vget_high_f32(a1), 0);
- r2 = vmlaq_lane_f32( r2, mz, vget_high_f32(a2), 0);
- return b3Matrix3x3( r0, r1, r2 );
-
+ float32x4_t a0 = m_el[0].mVec128;
+ float32x4_t a1 = m_el[1].mVec128;
+ float32x4_t a2 = m_el[2].mVec128;
+
+ b3Matrix3x3 mT = m.transpose(); // we rely on transpose() zeroing w channel so that we don't have to do it here
+ float32x4_t mx = mT[0].mVec128;
+ float32x4_t my = mT[1].mVec128;
+ float32x4_t mz = mT[2].mVec128;
+
+ float32x4_t r0 = vmulq_lane_f32(mx, vget_low_f32(a0), 0);
+ float32x4_t r1 = vmulq_lane_f32(mx, vget_low_f32(a1), 0);
+ float32x4_t r2 = vmulq_lane_f32(mx, vget_low_f32(a2), 0);
+ r0 = vmlaq_lane_f32(r0, my, vget_low_f32(a0), 1);
+ r1 = vmlaq_lane_f32(r1, my, vget_low_f32(a1), 1);
+ r2 = vmlaq_lane_f32(r2, my, vget_low_f32(a2), 1);
+ r0 = vmlaq_lane_f32(r0, mz, vget_high_f32(a0), 0);
+ r1 = vmlaq_lane_f32(r1, mz, vget_high_f32(a1), 0);
+ r2 = vmlaq_lane_f32(r2, mz, vget_high_f32(a2), 0);
+ return b3Matrix3x3(r0, r1, r2);
+
#else
return b3Matrix3x3(
m_el[0].dot(m[0]), m_el[0].dot(m[1]), m_el[0].dot(m[2]),
@@ -1137,139 +1136,138 @@ b3Matrix3x3::timesTranspose(const b3Matrix3x3& m) const
#endif
}
-B3_FORCE_INLINE b3Vector3
-operator*(const b3Matrix3x3& m, const b3Vector3& v)
+B3_FORCE_INLINE b3Vector3
+operator*(const b3Matrix3x3& m, const b3Vector3& v)
{
-#if (defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE))|| defined (B3_USE_NEON)
- return v.dot3(m[0], m[1], m[2]);
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)) || defined(B3_USE_NEON)
+ return v.dot3(m[0], m[1], m[2]);
#else
return b3MakeVector3(m[0].dot(v), m[1].dot(v), m[2].dot(v));
#endif
}
-
B3_FORCE_INLINE b3Vector3
operator*(const b3Vector3& v, const b3Matrix3x3& m)
{
-#if (defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE))
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE))
- const __m128 vv = v.mVec128;
+ const __m128 vv = v.mVec128;
- __m128 c0 = b3_splat_ps( vv, 0);
- __m128 c1 = b3_splat_ps( vv, 1);
- __m128 c2 = b3_splat_ps( vv, 2);
+ __m128 c0 = b3_splat_ps(vv, 0);
+ __m128 c1 = b3_splat_ps(vv, 1);
+ __m128 c2 = b3_splat_ps(vv, 2);
- c0 = _mm_mul_ps(c0, _mm_and_ps(m[0].mVec128, b3vFFF0fMask) );
- c1 = _mm_mul_ps(c1, _mm_and_ps(m[1].mVec128, b3vFFF0fMask) );
- c0 = _mm_add_ps(c0, c1);
- c2 = _mm_mul_ps(c2, _mm_and_ps(m[2].mVec128, b3vFFF0fMask) );
-
- return b3MakeVector3(_mm_add_ps(c0, c2));
+ c0 = _mm_mul_ps(c0, _mm_and_ps(m[0].mVec128, b3vFFF0fMask));
+ c1 = _mm_mul_ps(c1, _mm_and_ps(m[1].mVec128, b3vFFF0fMask));
+ c0 = _mm_add_ps(c0, c1);
+ c2 = _mm_mul_ps(c2, _mm_and_ps(m[2].mVec128, b3vFFF0fMask));
+
+ return b3MakeVector3(_mm_add_ps(c0, c2));
#elif defined(B3_USE_NEON)
- const float32x4_t vv = v.mVec128;
- const float32x2_t vlo = vget_low_f32(vv);
- const float32x2_t vhi = vget_high_f32(vv);
-
- float32x4_t c0, c1, c2;
-
- c0 = (float32x4_t) vandq_s32((int32x4_t)m[0].mVec128, b3vFFF0Mask);
- c1 = (float32x4_t) vandq_s32((int32x4_t)m[1].mVec128, b3vFFF0Mask);
- c2 = (float32x4_t) vandq_s32((int32x4_t)m[2].mVec128, b3vFFF0Mask);
-
- c0 = vmulq_lane_f32(c0, vlo, 0);
- c1 = vmulq_lane_f32(c1, vlo, 1);
- c2 = vmulq_lane_f32(c2, vhi, 0);
- c0 = vaddq_f32(c0, c1);
- c0 = vaddq_f32(c0, c2);
-
- return b3MakeVector3(c0);
+ const float32x4_t vv = v.mVec128;
+ const float32x2_t vlo = vget_low_f32(vv);
+ const float32x2_t vhi = vget_high_f32(vv);
+
+ float32x4_t c0, c1, c2;
+
+ c0 = (float32x4_t)vandq_s32((int32x4_t)m[0].mVec128, b3vFFF0Mask);
+ c1 = (float32x4_t)vandq_s32((int32x4_t)m[1].mVec128, b3vFFF0Mask);
+ c2 = (float32x4_t)vandq_s32((int32x4_t)m[2].mVec128, b3vFFF0Mask);
+
+ c0 = vmulq_lane_f32(c0, vlo, 0);
+ c1 = vmulq_lane_f32(c1, vlo, 1);
+ c2 = vmulq_lane_f32(c2, vhi, 0);
+ c0 = vaddq_f32(c0, c1);
+ c0 = vaddq_f32(c0, c2);
+
+ return b3MakeVector3(c0);
#else
return b3MakeVector3(m.tdotx(v), m.tdoty(v), m.tdotz(v));
#endif
}
-B3_FORCE_INLINE b3Matrix3x3
+B3_FORCE_INLINE b3Matrix3x3
operator*(const b3Matrix3x3& m1, const b3Matrix3x3& m2)
{
-#if (defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE))
-
- __m128 m10 = m1[0].mVec128;
- __m128 m11 = m1[1].mVec128;
- __m128 m12 = m1[2].mVec128;
-
- __m128 m2v = _mm_and_ps(m2[0].mVec128, b3vFFF0fMask);
-
- __m128 c0 = b3_splat_ps( m10, 0);
- __m128 c1 = b3_splat_ps( m11, 0);
- __m128 c2 = b3_splat_ps( m12, 0);
-
- c0 = _mm_mul_ps(c0, m2v);
- c1 = _mm_mul_ps(c1, m2v);
- c2 = _mm_mul_ps(c2, m2v);
-
- m2v = _mm_and_ps(m2[1].mVec128, b3vFFF0fMask);
-
- __m128 c0_1 = b3_splat_ps( m10, 1);
- __m128 c1_1 = b3_splat_ps( m11, 1);
- __m128 c2_1 = b3_splat_ps( m12, 1);
-
- c0_1 = _mm_mul_ps(c0_1, m2v);
- c1_1 = _mm_mul_ps(c1_1, m2v);
- c2_1 = _mm_mul_ps(c2_1, m2v);
-
- m2v = _mm_and_ps(m2[2].mVec128, b3vFFF0fMask);
-
- c0 = _mm_add_ps(c0, c0_1);
- c1 = _mm_add_ps(c1, c1_1);
- c2 = _mm_add_ps(c2, c2_1);
-
- m10 = b3_splat_ps( m10, 2);
- m11 = b3_splat_ps( m11, 2);
- m12 = b3_splat_ps( m12, 2);
-
- m10 = _mm_mul_ps(m10, m2v);
- m11 = _mm_mul_ps(m11, m2v);
- m12 = _mm_mul_ps(m12, m2v);
-
- c0 = _mm_add_ps(c0, m10);
- c1 = _mm_add_ps(c1, m11);
- c2 = _mm_add_ps(c2, m12);
-
- return b3Matrix3x3(c0, c1, c2);
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE))
+
+ __m128 m10 = m1[0].mVec128;
+ __m128 m11 = m1[1].mVec128;
+ __m128 m12 = m1[2].mVec128;
+
+ __m128 m2v = _mm_and_ps(m2[0].mVec128, b3vFFF0fMask);
+
+ __m128 c0 = b3_splat_ps(m10, 0);
+ __m128 c1 = b3_splat_ps(m11, 0);
+ __m128 c2 = b3_splat_ps(m12, 0);
+
+ c0 = _mm_mul_ps(c0, m2v);
+ c1 = _mm_mul_ps(c1, m2v);
+ c2 = _mm_mul_ps(c2, m2v);
+
+ m2v = _mm_and_ps(m2[1].mVec128, b3vFFF0fMask);
+
+ __m128 c0_1 = b3_splat_ps(m10, 1);
+ __m128 c1_1 = b3_splat_ps(m11, 1);
+ __m128 c2_1 = b3_splat_ps(m12, 1);
+
+ c0_1 = _mm_mul_ps(c0_1, m2v);
+ c1_1 = _mm_mul_ps(c1_1, m2v);
+ c2_1 = _mm_mul_ps(c2_1, m2v);
+
+ m2v = _mm_and_ps(m2[2].mVec128, b3vFFF0fMask);
+
+ c0 = _mm_add_ps(c0, c0_1);
+ c1 = _mm_add_ps(c1, c1_1);
+ c2 = _mm_add_ps(c2, c2_1);
+
+ m10 = b3_splat_ps(m10, 2);
+ m11 = b3_splat_ps(m11, 2);
+ m12 = b3_splat_ps(m12, 2);
+
+ m10 = _mm_mul_ps(m10, m2v);
+ m11 = _mm_mul_ps(m11, m2v);
+ m12 = _mm_mul_ps(m12, m2v);
+
+ c0 = _mm_add_ps(c0, m10);
+ c1 = _mm_add_ps(c1, m11);
+ c2 = _mm_add_ps(c2, m12);
+
+ return b3Matrix3x3(c0, c1, c2);
#elif defined(B3_USE_NEON)
- float32x4_t rv0, rv1, rv2;
- float32x4_t v0, v1, v2;
- float32x4_t mv0, mv1, mv2;
-
- v0 = m1[0].mVec128;
- v1 = m1[1].mVec128;
- v2 = m1[2].mVec128;
-
- mv0 = (float32x4_t) vandq_s32((int32x4_t)m2[0].mVec128, b3vFFF0Mask);
- mv1 = (float32x4_t) vandq_s32((int32x4_t)m2[1].mVec128, b3vFFF0Mask);
- mv2 = (float32x4_t) vandq_s32((int32x4_t)m2[2].mVec128, b3vFFF0Mask);
-
- rv0 = vmulq_lane_f32(mv0, vget_low_f32(v0), 0);
- rv1 = vmulq_lane_f32(mv0, vget_low_f32(v1), 0);
- rv2 = vmulq_lane_f32(mv0, vget_low_f32(v2), 0);
-
- rv0 = vmlaq_lane_f32(rv0, mv1, vget_low_f32(v0), 1);
- rv1 = vmlaq_lane_f32(rv1, mv1, vget_low_f32(v1), 1);
- rv2 = vmlaq_lane_f32(rv2, mv1, vget_low_f32(v2), 1);
-
- rv0 = vmlaq_lane_f32(rv0, mv2, vget_high_f32(v0), 0);
- rv1 = vmlaq_lane_f32(rv1, mv2, vget_high_f32(v1), 0);
- rv2 = vmlaq_lane_f32(rv2, mv2, vget_high_f32(v2), 0);
+ float32x4_t rv0, rv1, rv2;
+ float32x4_t v0, v1, v2;
+ float32x4_t mv0, mv1, mv2;
+
+ v0 = m1[0].mVec128;
+ v1 = m1[1].mVec128;
+ v2 = m1[2].mVec128;
+
+ mv0 = (float32x4_t)vandq_s32((int32x4_t)m2[0].mVec128, b3vFFF0Mask);
+ mv1 = (float32x4_t)vandq_s32((int32x4_t)m2[1].mVec128, b3vFFF0Mask);
+ mv2 = (float32x4_t)vandq_s32((int32x4_t)m2[2].mVec128, b3vFFF0Mask);
+
+ rv0 = vmulq_lane_f32(mv0, vget_low_f32(v0), 0);
+ rv1 = vmulq_lane_f32(mv0, vget_low_f32(v1), 0);
+ rv2 = vmulq_lane_f32(mv0, vget_low_f32(v2), 0);
+
+ rv0 = vmlaq_lane_f32(rv0, mv1, vget_low_f32(v0), 1);
+ rv1 = vmlaq_lane_f32(rv1, mv1, vget_low_f32(v1), 1);
+ rv2 = vmlaq_lane_f32(rv2, mv1, vget_low_f32(v2), 1);
+
+ rv0 = vmlaq_lane_f32(rv0, mv2, vget_high_f32(v0), 0);
+ rv1 = vmlaq_lane_f32(rv1, mv2, vget_high_f32(v1), 0);
+ rv2 = vmlaq_lane_f32(rv2, mv2, vget_high_f32(v2), 0);
return b3Matrix3x3(rv0, rv1, rv2);
-
-#else
+
+#else
return b3Matrix3x3(
- m2.tdotx( m1[0]), m2.tdoty( m1[0]), m2.tdotz( m1[0]),
- m2.tdotx( m1[1]), m2.tdoty( m1[1]), m2.tdotz( m1[1]),
- m2.tdotx( m1[2]), m2.tdoty( m1[2]), m2.tdotz( m1[2]));
+ m2.tdotx(m1[0]), m2.tdoty(m1[0]), m2.tdotz(m1[0]),
+ m2.tdotx(m1[1]), m2.tdoty(m1[1]), m2.tdotz(m1[1]),
+ m2.tdotx(m1[2]), m2.tdoty(m1[2]), m2.tdotz(m1[2]));
#endif
}
@@ -1292,71 +1290,65 @@ m1[0][2] * m2[0][2] + m1[1][2] * m2[1][2] + m1[2][2] * m2[2][2]);
* It will test all elements are equal. */
B3_FORCE_INLINE bool operator==(const b3Matrix3x3& m1, const b3Matrix3x3& m2)
{
-#if (defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE))
-
- __m128 c0, c1, c2;
-
- c0 = _mm_cmpeq_ps(m1[0].mVec128, m2[0].mVec128);
- c1 = _mm_cmpeq_ps(m1[1].mVec128, m2[1].mVec128);
- c2 = _mm_cmpeq_ps(m1[2].mVec128, m2[2].mVec128);
-
- c0 = _mm_and_ps(c0, c1);
- c0 = _mm_and_ps(c0, c2);
-
- return (0x7 == _mm_movemask_ps((__m128)c0));
-#else
- return
- ( m1[0][0] == m2[0][0] && m1[1][0] == m2[1][0] && m1[2][0] == m2[2][0] &&
- m1[0][1] == m2[0][1] && m1[1][1] == m2[1][1] && m1[2][1] == m2[2][1] &&
- m1[0][2] == m2[0][2] && m1[1][2] == m2[1][2] && m1[2][2] == m2[2][2] );
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE))
+
+ __m128 c0, c1, c2;
+
+ c0 = _mm_cmpeq_ps(m1[0].mVec128, m2[0].mVec128);
+ c1 = _mm_cmpeq_ps(m1[1].mVec128, m2[1].mVec128);
+ c2 = _mm_cmpeq_ps(m1[2].mVec128, m2[2].mVec128);
+
+ c0 = _mm_and_ps(c0, c1);
+ c0 = _mm_and_ps(c0, c2);
+
+ return (0x7 == _mm_movemask_ps((__m128)c0));
+#else
+ return (m1[0][0] == m2[0][0] && m1[1][0] == m2[1][0] && m1[2][0] == m2[2][0] &&
+ m1[0][1] == m2[0][1] && m1[1][1] == m2[1][1] && m1[2][1] == m2[2][1] &&
+ m1[0][2] == m2[0][2] && m1[1][2] == m2[1][2] && m1[2][2] == m2[2][2]);
#endif
}
///for serialization
-struct b3Matrix3x3FloatData
+struct b3Matrix3x3FloatData
{
b3Vector3FloatData m_el[3];
};
///for serialization
-struct b3Matrix3x3DoubleData
+struct b3Matrix3x3DoubleData
{
b3Vector3DoubleData m_el[3];
};
-
-
-
-B3_FORCE_INLINE void b3Matrix3x3::serialize(struct b3Matrix3x3Data& dataOut) const
+B3_FORCE_INLINE void b3Matrix3x3::serialize(struct b3Matrix3x3Data& dataOut) const
{
- for (int i=0;i<3;i++)
+ for (int i = 0; i < 3; i++)
m_el[i].serialize(dataOut.m_el[i]);
}
-B3_FORCE_INLINE void b3Matrix3x3::serializeFloat(struct b3Matrix3x3FloatData& dataOut) const
+B3_FORCE_INLINE void b3Matrix3x3::serializeFloat(struct b3Matrix3x3FloatData& dataOut) const
{
- for (int i=0;i<3;i++)
+ for (int i = 0; i < 3; i++)
m_el[i].serializeFloat(dataOut.m_el[i]);
}
-
-B3_FORCE_INLINE void b3Matrix3x3::deSerialize(const struct b3Matrix3x3Data& dataIn)
+B3_FORCE_INLINE void b3Matrix3x3::deSerialize(const struct b3Matrix3x3Data& dataIn)
{
- for (int i=0;i<3;i++)
+ for (int i = 0; i < 3; i++)
m_el[i].deSerialize(dataIn.m_el[i]);
}
-B3_FORCE_INLINE void b3Matrix3x3::deSerializeFloat(const struct b3Matrix3x3FloatData& dataIn)
+B3_FORCE_INLINE void b3Matrix3x3::deSerializeFloat(const struct b3Matrix3x3FloatData& dataIn)
{
- for (int i=0;i<3;i++)
+ for (int i = 0; i < 3; i++)
m_el[i].deSerializeFloat(dataIn.m_el[i]);
}
-B3_FORCE_INLINE void b3Matrix3x3::deSerializeDouble(const struct b3Matrix3x3DoubleData& dataIn)
+B3_FORCE_INLINE void b3Matrix3x3::deSerializeDouble(const struct b3Matrix3x3DoubleData& dataIn)
{
- for (int i=0;i<3;i++)
+ for (int i = 0; i < 3; i++)
m_el[i].deSerializeDouble(dataIn.m_el[i]);
}
-#endif //B3_MATRIX3x3_H
-
+#endif //B3_MATRIX3x3_H
diff --git a/thirdparty/bullet/Bullet3Common/b3MinMax.h b/thirdparty/bullet/Bullet3Common/b3MinMax.h
index 73af23a4f9..c09c3db3f5 100644
--- a/thirdparty/bullet/Bullet3Common/b3MinMax.h
+++ b/thirdparty/bullet/Bullet3Common/b3MinMax.h
@@ -12,60 +12,58 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
-
#ifndef B3_GEN_MINMAX_H
#define B3_GEN_MINMAX_H
#include "b3Scalar.h"
template <class T>
-B3_FORCE_INLINE const T& b3Min(const T& a, const T& b)
+B3_FORCE_INLINE const T& b3Min(const T& a, const T& b)
{
- return a < b ? a : b ;
+ return a < b ? a : b;
}
template <class T>
-B3_FORCE_INLINE const T& b3Max(const T& a, const T& b)
+B3_FORCE_INLINE const T& b3Max(const T& a, const T& b)
{
- return a > b ? a : b;
+ return a > b ? a : b;
}
template <class T>
-B3_FORCE_INLINE const T& b3Clamped(const T& a, const T& lb, const T& ub)
+B3_FORCE_INLINE const T& b3Clamped(const T& a, const T& lb, const T& ub)
{
- return a < lb ? lb : (ub < a ? ub : a);
+ return a < lb ? lb : (ub < a ? ub : a);
}
template <class T>
-B3_FORCE_INLINE void b3SetMin(T& a, const T& b)
+B3_FORCE_INLINE void b3SetMin(T& a, const T& b)
{
- if (b < a)
+ if (b < a)
{
a = b;
}
}
template <class T>
-B3_FORCE_INLINE void b3SetMax(T& a, const T& b)
+B3_FORCE_INLINE void b3SetMax(T& a, const T& b)
{
- if (a < b)
+ if (a < b)
{
a = b;
}
}
template <class T>
-B3_FORCE_INLINE void b3Clamp(T& a, const T& lb, const T& ub)
+B3_FORCE_INLINE void b3Clamp(T& a, const T& lb, const T& ub)
{
- if (a < lb)
+ if (a < lb)
{
- a = lb;
+ a = lb;
}
- else if (ub < a)
+ else if (ub < a)
{
a = ub;
}
}
-#endif //B3_GEN_MINMAX_H
+#endif //B3_GEN_MINMAX_H
diff --git a/thirdparty/bullet/Bullet3Common/b3PoolAllocator.h b/thirdparty/bullet/Bullet3Common/b3PoolAllocator.h
index 2fcdcf5b24..ed56bc627d 100644
--- a/thirdparty/bullet/Bullet3Common/b3PoolAllocator.h
+++ b/thirdparty/bullet/Bullet3Common/b3PoolAllocator.h
@@ -12,7 +12,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#ifndef _BT_POOL_ALLOCATOR_H
#define _BT_POOL_ALLOCATOR_H
@@ -22,37 +21,37 @@ subject to the following restrictions:
///The b3PoolAllocator class allows to efficiently allocate a large pool of objects, instead of dynamically allocating them separately.
class b3PoolAllocator
{
- int m_elemSize;
- int m_maxElements;
- int m_freeCount;
- void* m_firstFree;
- unsigned char* m_pool;
+ int m_elemSize;
+ int m_maxElements;
+ int m_freeCount;
+ void* m_firstFree;
+ unsigned char* m_pool;
public:
-
b3PoolAllocator(int elemSize, int maxElements)
- :m_elemSize(elemSize),
- m_maxElements(maxElements)
+ : m_elemSize(elemSize),
+ m_maxElements(maxElements)
{
- m_pool = (unsigned char*) b3AlignedAlloc( static_cast<unsigned int>(m_elemSize*m_maxElements),16);
+ m_pool = (unsigned char*)b3AlignedAlloc(static_cast<unsigned int>(m_elemSize * m_maxElements), 16);
unsigned char* p = m_pool;
- m_firstFree = p;
- m_freeCount = m_maxElements;
- int count = m_maxElements;
- while (--count) {
- *(void**)p = (p + m_elemSize);
- p += m_elemSize;
- }
- *(void**)p = 0;
- }
+ m_firstFree = p;
+ m_freeCount = m_maxElements;
+ int count = m_maxElements;
+ while (--count)
+ {
+ *(void**)p = (p + m_elemSize);
+ p += m_elemSize;
+ }
+ *(void**)p = 0;
+ }
~b3PoolAllocator()
{
- b3AlignedFree( m_pool);
+ b3AlignedFree(m_pool);
}
- int getFreeCount() const
+ int getFreeCount() const
{
return m_freeCount;
}
@@ -67,21 +66,22 @@ public:
return m_maxElements;
}
- void* allocate(int size)
+ void* allocate(int size)
{
// release mode fix
(void)size;
- b3Assert(!size || size<=m_elemSize);
- b3Assert(m_freeCount>0);
- void* result = m_firstFree;
- m_firstFree = *(void**)m_firstFree;
- --m_freeCount;
- return result;
+ b3Assert(!size || size <= m_elemSize);
+ b3Assert(m_freeCount > 0);
+ void* result = m_firstFree;
+ m_firstFree = *(void**)m_firstFree;
+ --m_freeCount;
+ return result;
}
bool validPtr(void* ptr)
{
- if (ptr) {
+ if (ptr)
+ {
if (((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize))
{
return true;
@@ -90,32 +90,32 @@ public:
return false;
}
- void freeMemory(void* ptr)
+ void freeMemory(void* ptr)
{
- if (ptr) {
- b3Assert((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize);
+ if (ptr)
+ {
+ b3Assert((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize);
- *(void**)ptr = m_firstFree;
- m_firstFree = ptr;
- ++m_freeCount;
- }
+ *(void**)ptr = m_firstFree;
+ m_firstFree = ptr;
+ ++m_freeCount;
+ }
}
- int getElementSize() const
+ int getElementSize() const
{
return m_elemSize;
}
- unsigned char* getPoolAddress()
+ unsigned char* getPoolAddress()
{
return m_pool;
}
- const unsigned char* getPoolAddress() const
+ const unsigned char* getPoolAddress() const
{
return m_pool;
}
-
};
-#endif //_BT_POOL_ALLOCATOR_H
+#endif //_BT_POOL_ALLOCATOR_H
diff --git a/thirdparty/bullet/Bullet3Common/b3QuadWord.h b/thirdparty/bullet/Bullet3Common/b3QuadWord.h
index 65c9581977..0def305fac 100644
--- a/thirdparty/bullet/Bullet3Common/b3QuadWord.h
+++ b/thirdparty/bullet/Bullet3Common/b3QuadWord.h
@@ -12,18 +12,13 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#ifndef B3_SIMD_QUADWORD_H
#define B3_SIMD_QUADWORD_H
#include "b3Scalar.h"
#include "b3MinMax.h"
-
-
-
-
-#if defined (__CELLOS_LV2) && defined (__SPU__)
+#if defined(__CELLOS_LV2) && defined(__SPU__)
#include <altivec.h>
#endif
@@ -31,58 +26,64 @@ subject to the following restrictions:
* Some issues under PS3 Linux with IBM 2.1 SDK, gcc compiler prevent from using aligned quadword.
*/
#ifndef USE_LIBSPE2
-B3_ATTRIBUTE_ALIGNED16(class) b3QuadWord
+B3_ATTRIBUTE_ALIGNED16(class)
+b3QuadWord
#else
class b3QuadWord
#endif
{
protected:
-
-#if defined (__SPU__) && defined (__CELLOS_LV2__)
+#if defined(__SPU__) && defined(__CELLOS_LV2__)
union {
vec_float4 mVec128;
- b3Scalar m_floats[4];
+ b3Scalar m_floats[4];
};
+
public:
- vec_float4 get128() const
+ vec_float4 get128() const
{
return mVec128;
}
-#else //__CELLOS_LV2__ __SPU__
+#else //__CELLOS_LV2__ __SPU__
-#if defined(B3_USE_SSE) || defined(B3_USE_NEON)
+#if defined(B3_USE_SSE) || defined(B3_USE_NEON)
public:
union {
b3SimdFloat4 mVec128;
- b3Scalar m_floats[4];
- struct {b3Scalar x,y,z,w;};
+ b3Scalar m_floats[4];
+ struct
+ {
+ b3Scalar x, y, z, w;
+ };
};
+
public:
- B3_FORCE_INLINE b3SimdFloat4 get128() const
+ B3_FORCE_INLINE b3SimdFloat4 get128() const
{
return mVec128;
}
- B3_FORCE_INLINE void set128(b3SimdFloat4 v128)
+ B3_FORCE_INLINE void set128(b3SimdFloat4 v128)
{
mVec128 = v128;
}
#else
public:
- union
- {
- b3Scalar m_floats[4];
- struct {b3Scalar x,y,z,w;};
+ union {
+ b3Scalar m_floats[4];
+ struct
+ {
+ b3Scalar x, y, z, w;
+ };
};
-#endif // B3_USE_SSE
+#endif // B3_USE_SSE
-#endif //__CELLOS_LV2__ __SPU__
+#endif //__CELLOS_LV2__ __SPU__
- public:
-
+public:
#if defined(B3_USE_SSE) || defined(B3_USE_NEON)
- // Set Vector
+ // Set Vector
B3_FORCE_INLINE b3QuadWord(const b3SimdFloat4 vec)
{
mVec128 = vec;
@@ -95,151 +96,147 @@ public:
}
// Assignment Operator
- B3_FORCE_INLINE b3QuadWord&
- operator=(const b3QuadWord& v)
+ B3_FORCE_INLINE b3QuadWord&
+ operator=(const b3QuadWord& v)
{
mVec128 = v.mVec128;
-
+
return *this;
}
-
+
#endif
- /**@brief Return the x value */
- B3_FORCE_INLINE const b3Scalar& getX() const { return m_floats[0]; }
- /**@brief Return the y value */
- B3_FORCE_INLINE const b3Scalar& getY() const { return m_floats[1]; }
- /**@brief Return the z value */
- B3_FORCE_INLINE const b3Scalar& getZ() const { return m_floats[2]; }
- /**@brief Set the x value */
- B3_FORCE_INLINE void setX(b3Scalar _x) { m_floats[0] = _x;};
- /**@brief Set the y value */
- B3_FORCE_INLINE void setY(b3Scalar _y) { m_floats[1] = _y;};
- /**@brief Set the z value */
- B3_FORCE_INLINE void setZ(b3Scalar _z) { m_floats[2] = _z;};
- /**@brief Set the w value */
- B3_FORCE_INLINE void setW(b3Scalar _w) { m_floats[3] = _w;};
- /**@brief Return the x value */
-
-
- //B3_FORCE_INLINE b3Scalar& operator[](int i) { return (&m_floats[0])[i]; }
+ /**@brief Return the x value */
+ B3_FORCE_INLINE const b3Scalar& getX() const { return m_floats[0]; }
+ /**@brief Return the y value */
+ B3_FORCE_INLINE const b3Scalar& getY() const { return m_floats[1]; }
+ /**@brief Return the z value */
+ B3_FORCE_INLINE const b3Scalar& getZ() const { return m_floats[2]; }
+ /**@brief Set the x value */
+ B3_FORCE_INLINE void setX(b3Scalar _x) { m_floats[0] = _x; };
+ /**@brief Set the y value */
+ B3_FORCE_INLINE void setY(b3Scalar _y) { m_floats[1] = _y; };
+ /**@brief Set the z value */
+ B3_FORCE_INLINE void setZ(b3Scalar _z) { m_floats[2] = _z; };
+ /**@brief Set the w value */
+ B3_FORCE_INLINE void setW(b3Scalar _w) { m_floats[3] = _w; };
+ /**@brief Return the x value */
+
+ //B3_FORCE_INLINE b3Scalar& operator[](int i) { return (&m_floats[0])[i]; }
//B3_FORCE_INLINE const b3Scalar& operator[](int i) const { return (&m_floats[0])[i]; }
///operator b3Scalar*() replaces operator[], using implicit conversion. We added operator != and operator == to avoid pointer comparisons.
- B3_FORCE_INLINE operator b3Scalar *() { return &m_floats[0]; }
- B3_FORCE_INLINE operator const b3Scalar *() const { return &m_floats[0]; }
+ B3_FORCE_INLINE operator b3Scalar*() { return &m_floats[0]; }
+ B3_FORCE_INLINE operator const b3Scalar*() const { return &m_floats[0]; }
- B3_FORCE_INLINE bool operator==(const b3QuadWord& other) const
+ B3_FORCE_INLINE bool operator==(const b3QuadWord& other) const
{
#ifdef B3_USE_SSE
- return (0xf == _mm_movemask_ps((__m128)_mm_cmpeq_ps(mVec128, other.mVec128)));
-#else
- return ((m_floats[3]==other.m_floats[3]) &&
- (m_floats[2]==other.m_floats[2]) &&
- (m_floats[1]==other.m_floats[1]) &&
- (m_floats[0]==other.m_floats[0]));
+ return (0xf == _mm_movemask_ps((__m128)_mm_cmpeq_ps(mVec128, other.mVec128)));
+#else
+ return ((m_floats[3] == other.m_floats[3]) &&
+ (m_floats[2] == other.m_floats[2]) &&
+ (m_floats[1] == other.m_floats[1]) &&
+ (m_floats[0] == other.m_floats[0]));
#endif
}
- B3_FORCE_INLINE bool operator!=(const b3QuadWord& other) const
+ B3_FORCE_INLINE bool operator!=(const b3QuadWord& other) const
{
return !(*this == other);
}
- /**@brief Set x,y,z and zero w
+ /**@brief Set x,y,z and zero w
* @param x Value of x
* @param y Value of y
* @param z Value of z
*/
- B3_FORCE_INLINE void setValue(const b3Scalar& _x, const b3Scalar& _y, const b3Scalar& _z)
- {
- m_floats[0]=_x;
- m_floats[1]=_y;
- m_floats[2]=_z;
- m_floats[3] = 0.f;
- }
+ B3_FORCE_INLINE void setValue(const b3Scalar& _x, const b3Scalar& _y, const b3Scalar& _z)
+ {
+ m_floats[0] = _x;
+ m_floats[1] = _y;
+ m_floats[2] = _z;
+ m_floats[3] = 0.f;
+ }
-/* void getValue(b3Scalar *m) const
+ /* void getValue(b3Scalar *m) const
{
m[0] = m_floats[0];
m[1] = m_floats[1];
m[2] = m_floats[2];
}
*/
-/**@brief Set the values
+ /**@brief Set the values
* @param x Value of x
* @param y Value of y
* @param z Value of z
* @param w Value of w
*/
- B3_FORCE_INLINE void setValue(const b3Scalar& _x, const b3Scalar& _y, const b3Scalar& _z,const b3Scalar& _w)
- {
- m_floats[0]=_x;
- m_floats[1]=_y;
- m_floats[2]=_z;
- m_floats[3]=_w;
- }
- /**@brief No initialization constructor */
- B3_FORCE_INLINE b3QuadWord()
- // :m_floats[0](b3Scalar(0.)),m_floats[1](b3Scalar(0.)),m_floats[2](b3Scalar(0.)),m_floats[3](b3Scalar(0.))
- {
- }
-
- /**@brief Three argument constructor (zeros w)
+ B3_FORCE_INLINE void setValue(const b3Scalar& _x, const b3Scalar& _y, const b3Scalar& _z, const b3Scalar& _w)
+ {
+ m_floats[0] = _x;
+ m_floats[1] = _y;
+ m_floats[2] = _z;
+ m_floats[3] = _w;
+ }
+ /**@brief No initialization constructor */
+ B3_FORCE_INLINE b3QuadWord()
+ // :m_floats[0](b3Scalar(0.)),m_floats[1](b3Scalar(0.)),m_floats[2](b3Scalar(0.)),m_floats[3](b3Scalar(0.))
+ {
+ }
+
+ /**@brief Three argument constructor (zeros w)
* @param x Value of x
* @param y Value of y
* @param z Value of z
*/
- B3_FORCE_INLINE b3QuadWord(const b3Scalar& _x, const b3Scalar& _y, const b3Scalar& _z)
- {
- m_floats[0] = _x, m_floats[1] = _y, m_floats[2] = _z, m_floats[3] = 0.0f;
- }
+ B3_FORCE_INLINE b3QuadWord(const b3Scalar& _x, const b3Scalar& _y, const b3Scalar& _z)
+ {
+ m_floats[0] = _x, m_floats[1] = _y, m_floats[2] = _z, m_floats[3] = 0.0f;
+ }
-/**@brief Initializing constructor
+ /**@brief Initializing constructor
* @param x Value of x
* @param y Value of y
* @param z Value of z
* @param w Value of w
*/
- B3_FORCE_INLINE b3QuadWord(const b3Scalar& _x, const b3Scalar& _y, const b3Scalar& _z,const b3Scalar& _w)
- {
- m_floats[0] = _x, m_floats[1] = _y, m_floats[2] = _z, m_floats[3] = _w;
- }
+ B3_FORCE_INLINE b3QuadWord(const b3Scalar& _x, const b3Scalar& _y, const b3Scalar& _z, const b3Scalar& _w)
+ {
+ m_floats[0] = _x, m_floats[1] = _y, m_floats[2] = _z, m_floats[3] = _w;
+ }
- /**@brief Set each element to the max of the current values and the values of another b3QuadWord
+ /**@brief Set each element to the max of the current values and the values of another b3QuadWord
* @param other The other b3QuadWord to compare with
*/
- B3_FORCE_INLINE void setMax(const b3QuadWord& other)
- {
- #ifdef B3_USE_SSE
- mVec128 = _mm_max_ps(mVec128, other.mVec128);
- #elif defined(B3_USE_NEON)
- mVec128 = vmaxq_f32(mVec128, other.mVec128);
- #else
- b3SetMax(m_floats[0], other.m_floats[0]);
- b3SetMax(m_floats[1], other.m_floats[1]);
- b3SetMax(m_floats[2], other.m_floats[2]);
- b3SetMax(m_floats[3], other.m_floats[3]);
- #endif
- }
- /**@brief Set each element to the min of the current values and the values of another b3QuadWord
+ B3_FORCE_INLINE void setMax(const b3QuadWord& other)
+ {
+#ifdef B3_USE_SSE
+ mVec128 = _mm_max_ps(mVec128, other.mVec128);
+#elif defined(B3_USE_NEON)
+ mVec128 = vmaxq_f32(mVec128, other.mVec128);
+#else
+ b3SetMax(m_floats[0], other.m_floats[0]);
+ b3SetMax(m_floats[1], other.m_floats[1]);
+ b3SetMax(m_floats[2], other.m_floats[2]);
+ b3SetMax(m_floats[3], other.m_floats[3]);
+#endif
+ }
+ /**@brief Set each element to the min of the current values and the values of another b3QuadWord
* @param other The other b3QuadWord to compare with
*/
- B3_FORCE_INLINE void setMin(const b3QuadWord& other)
- {
- #ifdef B3_USE_SSE
- mVec128 = _mm_min_ps(mVec128, other.mVec128);
- #elif defined(B3_USE_NEON)
- mVec128 = vminq_f32(mVec128, other.mVec128);
- #else
- b3SetMin(m_floats[0], other.m_floats[0]);
- b3SetMin(m_floats[1], other.m_floats[1]);
- b3SetMin(m_floats[2], other.m_floats[2]);
- b3SetMin(m_floats[3], other.m_floats[3]);
- #endif
- }
-
-
-
+ B3_FORCE_INLINE void setMin(const b3QuadWord& other)
+ {
+#ifdef B3_USE_SSE
+ mVec128 = _mm_min_ps(mVec128, other.mVec128);
+#elif defined(B3_USE_NEON)
+ mVec128 = vminq_f32(mVec128, other.mVec128);
+#else
+ b3SetMin(m_floats[0], other.m_floats[0]);
+ b3SetMin(m_floats[1], other.m_floats[1]);
+ b3SetMin(m_floats[2], other.m_floats[2]);
+ b3SetMin(m_floats[3], other.m_floats[3]);
+#endif
+ }
};
-#endif //B3_SIMD_QUADWORD_H
+#endif //B3_SIMD_QUADWORD_H
diff --git a/thirdparty/bullet/Bullet3Common/b3Quaternion.h b/thirdparty/bullet/Bullet3Common/b3Quaternion.h
index ad20543348..9bd5ff7d90 100644
--- a/thirdparty/bullet/Bullet3Common/b3Quaternion.h
+++ b/thirdparty/bullet/Bullet3Common/b3Quaternion.h
@@ -12,19 +12,12 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
-
#ifndef B3_SIMD__QUATERNION_H_
#define B3_SIMD__QUATERNION_H_
-
#include "b3Vector3.h"
#include "b3QuadWord.h"
-
-
-
-
#ifdef B3_USE_SSE
const __m128 B3_ATTRIBUTE_ALIGNED16(b3vOnes) = {1.0f, 1.0f, 1.0f, 1.0f};
@@ -39,13 +32,14 @@ const b3SimdFloat4 B3_ATTRIBUTE_ALIGNED16(b3vPPPM) = {+0.0f, +0.0f, +0.0f, -0.0f
#endif
/**@brief The b3Quaternion implements quaternion to perform linear algebra rotations in combination with b3Matrix3x3, b3Vector3 and b3Transform. */
-class b3Quaternion : public b3QuadWord {
+class b3Quaternion : public b3QuadWord
+{
public:
- /**@brief No initialization constructor */
+ /**@brief No initialization constructor */
b3Quaternion() {}
-#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE))|| defined(B3_USE_NEON)
- // Set Vector
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)) || defined(B3_USE_NEON)
+ // Set Vector
B3_FORCE_INLINE b3Quaternion(const b3SimdFloat4 vec)
{
mVec128 = vec;
@@ -58,63 +52,70 @@ public:
}
// Assignment Operator
- B3_FORCE_INLINE b3Quaternion&
- operator=(const b3Quaternion& v)
+ B3_FORCE_INLINE b3Quaternion&
+ operator=(const b3Quaternion& v)
{
mVec128 = v.mVec128;
-
+
return *this;
}
-
+
#endif
// template <typename b3Scalar>
// explicit Quaternion(const b3Scalar *v) : Tuple4<b3Scalar>(v) {}
- /**@brief Constructor from scalars */
- b3Quaternion(const b3Scalar& _x, const b3Scalar& _y, const b3Scalar& _z, const b3Scalar& _w)
- : b3QuadWord(_x, _y, _z, _w)
+ /**@brief Constructor from scalars */
+ b3Quaternion(const b3Scalar& _x, const b3Scalar& _y, const b3Scalar& _z, const b3Scalar& _w)
+ : b3QuadWord(_x, _y, _z, _w)
{
//b3Assert(!((_x==1.f) && (_y==0.f) && (_z==0.f) && (_w==0.f)));
}
- /**@brief Axis angle Constructor
+ /**@brief Axis angle Constructor
* @param axis The axis which the rotation is around
* @param angle The magnitude of the rotation around the angle (Radians) */
- b3Quaternion(const b3Vector3& _axis, const b3Scalar& _angle)
- {
- setRotation(_axis, _angle);
+ b3Quaternion(const b3Vector3& _axis, const b3Scalar& _angle)
+ {
+ setRotation(_axis, _angle);
}
- /**@brief Constructor from Euler angles
+ /**@brief Constructor from Euler angles
* @param yaw Angle around Y unless B3_EULER_DEFAULT_ZYX defined then Z
* @param pitch Angle around X unless B3_EULER_DEFAULT_ZYX defined then Y
* @param roll Angle around Z unless B3_EULER_DEFAULT_ZYX defined then X */
b3Quaternion(const b3Scalar& yaw, const b3Scalar& pitch, const b3Scalar& roll)
- {
+ {
#ifndef B3_EULER_DEFAULT_ZYX
- setEuler(yaw, pitch, roll);
+ setEuler(yaw, pitch, roll);
#else
- setEulerZYX(yaw, pitch, roll);
-#endif
+ setEulerZYX(yaw, pitch, roll);
+#endif
}
- /**@brief Set the rotation using axis angle notation
+ /**@brief Set the rotation using axis angle notation
* @param axis The axis around which to rotate
* @param angle The magnitude of the rotation in Radians */
void setRotation(const b3Vector3& axis, const b3Scalar& _angle)
{
b3Scalar d = axis.length();
b3Assert(d != b3Scalar(0.0));
- b3Scalar s = b3Sin(_angle * b3Scalar(0.5)) / d;
- setValue(axis.getX() * s, axis.getY() * s, axis.getZ() * s,
- b3Cos(_angle * b3Scalar(0.5)));
+ if (d < B3_EPSILON)
+ {
+ setValue(0, 0, 0, 1);
+ }
+ else
+ {
+ b3Scalar s = b3Sin(_angle * b3Scalar(0.5)) / d;
+ setValue(axis.getX() * s, axis.getY() * s, axis.getZ() * s,
+ b3Cos(_angle * b3Scalar(0.5)));
+ }
}
- /**@brief Set the quaternion using Euler angles
+ /**@brief Set the quaternion using Euler angles
* @param yaw Angle around Y
* @param pitch Angle around X
* @param roll Angle around Z */
void setEuler(const b3Scalar& yaw, const b3Scalar& pitch, const b3Scalar& roll)
{
- b3Scalar halfYaw = b3Scalar(yaw) * b3Scalar(0.5);
- b3Scalar halfPitch = b3Scalar(pitch) * b3Scalar(0.5);
- b3Scalar halfRoll = b3Scalar(roll) * b3Scalar(0.5);
+ b3Scalar halfYaw = b3Scalar(yaw) * b3Scalar(0.5);
+ b3Scalar halfPitch = b3Scalar(pitch) * b3Scalar(0.5);
+ b3Scalar halfRoll = b3Scalar(roll) * b3Scalar(0.5);
b3Scalar cosYaw = b3Cos(halfYaw);
b3Scalar sinYaw = b3Sin(halfYaw);
b3Scalar cosPitch = b3Cos(halfPitch);
@@ -122,34 +123,34 @@ public:
b3Scalar cosRoll = b3Cos(halfRoll);
b3Scalar sinRoll = b3Sin(halfRoll);
setValue(cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw,
- cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw,
- sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw,
- cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw);
+ cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw,
+ sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw,
+ cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw);
}
-
+
/**@brief Set the quaternion using euler angles
* @param yaw Angle around Z
* @param pitch Angle around Y
* @param roll Angle around X */
void setEulerZYX(const b3Scalar& yawZ, const b3Scalar& pitchY, const b3Scalar& rollX)
{
- b3Scalar halfYaw = b3Scalar(yawZ) * b3Scalar(0.5);
- b3Scalar halfPitch = b3Scalar(pitchY) * b3Scalar(0.5);
- b3Scalar halfRoll = b3Scalar(rollX) * b3Scalar(0.5);
+ b3Scalar halfYaw = b3Scalar(yawZ) * b3Scalar(0.5);
+ b3Scalar halfPitch = b3Scalar(pitchY) * b3Scalar(0.5);
+ b3Scalar halfRoll = b3Scalar(rollX) * b3Scalar(0.5);
b3Scalar cosYaw = b3Cos(halfYaw);
b3Scalar sinYaw = b3Sin(halfYaw);
b3Scalar cosPitch = b3Cos(halfPitch);
b3Scalar sinPitch = b3Sin(halfPitch);
b3Scalar cosRoll = b3Cos(halfRoll);
b3Scalar sinRoll = b3Sin(halfRoll);
- setValue(sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw, //x
- cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw, //y
- cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw, //z
- cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw); //formerly yzx
+ setValue(sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw, //x
+ cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw, //y
+ cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw, //z
+ cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw); //formerly yzx
normalize();
}
- /**@brief Get the euler angles from this quaternion
+ /**@brief Get the euler angles from this quaternion
* @param yaw Angle around Z
* @param pitch Angle around Y
* @param roll Angle around X */
@@ -166,221 +167,221 @@ public:
squ = m_floats[3] * m_floats[3];
rollX = b3Atan2(2 * (m_floats[1] * m_floats[2] + m_floats[3] * m_floats[0]), squ - sqx - sqy + sqz);
sarg = b3Scalar(-2.) * (m_floats[0] * m_floats[2] - m_floats[3] * m_floats[1]);
- pitchY = sarg <= b3Scalar(-1.0) ? b3Scalar(-0.5) * B3_PI: (sarg >= b3Scalar(1.0) ? b3Scalar(0.5) * B3_PI : b3Asin(sarg));
+ pitchY = sarg <= b3Scalar(-1.0) ? b3Scalar(-0.5) * B3_PI : (sarg >= b3Scalar(1.0) ? b3Scalar(0.5) * B3_PI : b3Asin(sarg));
yawZ = b3Atan2(2 * (m_floats[0] * m_floats[1] + m_floats[3] * m_floats[2]), squ + sqx - sqy - sqz);
}
- /**@brief Add two quaternions
+ /**@brief Add two quaternions
* @param q The quaternion to add to this one */
- B3_FORCE_INLINE b3Quaternion& operator+=(const b3Quaternion& q)
+ B3_FORCE_INLINE b3Quaternion& operator+=(const b3Quaternion& q)
{
-#if defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
mVec128 = _mm_add_ps(mVec128, q.mVec128);
#elif defined(B3_USE_NEON)
mVec128 = vaddq_f32(mVec128, q.mVec128);
-#else
- m_floats[0] += q.getX();
- m_floats[1] += q.getY();
- m_floats[2] += q.getZ();
- m_floats[3] += q.m_floats[3];
+#else
+ m_floats[0] += q.getX();
+ m_floats[1] += q.getY();
+ m_floats[2] += q.getZ();
+ m_floats[3] += q.m_floats[3];
#endif
return *this;
}
- /**@brief Subtract out a quaternion
+ /**@brief Subtract out a quaternion
* @param q The quaternion to subtract from this one */
- b3Quaternion& operator-=(const b3Quaternion& q)
+ b3Quaternion& operator-=(const b3Quaternion& q)
{
-#if defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
mVec128 = _mm_sub_ps(mVec128, q.mVec128);
#elif defined(B3_USE_NEON)
mVec128 = vsubq_f32(mVec128, q.mVec128);
-#else
- m_floats[0] -= q.getX();
- m_floats[1] -= q.getY();
- m_floats[2] -= q.getZ();
- m_floats[3] -= q.m_floats[3];
+#else
+ m_floats[0] -= q.getX();
+ m_floats[1] -= q.getY();
+ m_floats[2] -= q.getZ();
+ m_floats[3] -= q.m_floats[3];
#endif
- return *this;
+ return *this;
}
- /**@brief Scale this quaternion
+ /**@brief Scale this quaternion
* @param s The scalar to scale by */
b3Quaternion& operator*=(const b3Scalar& s)
{
-#if defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
- __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
- vs = b3_pshufd_ps(vs, 0); // (S S S S)
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+ __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
+ vs = b3_pshufd_ps(vs, 0); // (S S S S)
mVec128 = _mm_mul_ps(mVec128, vs);
#elif defined(B3_USE_NEON)
mVec128 = vmulq_n_f32(mVec128, s);
#else
- m_floats[0] *= s;
- m_floats[1] *= s;
- m_floats[2] *= s;
- m_floats[3] *= s;
+ m_floats[0] *= s;
+ m_floats[1] *= s;
+ m_floats[2] *= s;
+ m_floats[3] *= s;
#endif
return *this;
}
- /**@brief Multiply this quaternion by q on the right
+ /**@brief Multiply this quaternion by q on the right
* @param q The other quaternion
* Equivilant to this = this * q */
b3Quaternion& operator*=(const b3Quaternion& q)
{
-#if defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
__m128 vQ2 = q.get128();
-
- __m128 A1 = b3_pshufd_ps(mVec128, B3_SHUFFLE(0,1,2,0));
- __m128 B1 = b3_pshufd_ps(vQ2, B3_SHUFFLE(3,3,3,0));
-
+
+ __m128 A1 = b3_pshufd_ps(mVec128, B3_SHUFFLE(0, 1, 2, 0));
+ __m128 B1 = b3_pshufd_ps(vQ2, B3_SHUFFLE(3, 3, 3, 0));
+
A1 = A1 * B1;
-
- __m128 A2 = b3_pshufd_ps(mVec128, B3_SHUFFLE(1,2,0,1));
- __m128 B2 = b3_pshufd_ps(vQ2, B3_SHUFFLE(2,0,1,1));
-
+
+ __m128 A2 = b3_pshufd_ps(mVec128, B3_SHUFFLE(1, 2, 0, 1));
+ __m128 B2 = b3_pshufd_ps(vQ2, B3_SHUFFLE(2, 0, 1, 1));
+
A2 = A2 * B2;
-
- B1 = b3_pshufd_ps(mVec128, B3_SHUFFLE(2,0,1,2));
- B2 = b3_pshufd_ps(vQ2, B3_SHUFFLE(1,2,0,2));
-
- B1 = B1 * B2; // A3 *= B3
-
- mVec128 = b3_splat_ps(mVec128, 3); // A0
- mVec128 = mVec128 * vQ2; // A0 * B0
-
- A1 = A1 + A2; // AB12
- mVec128 = mVec128 - B1; // AB03 = AB0 - AB3
- A1 = _mm_xor_ps(A1, b3vPPPM); // change sign of the last element
- mVec128 = mVec128+ A1; // AB03 + AB12
-
-#elif defined(B3_USE_NEON)
-
- float32x4_t vQ1 = mVec128;
- float32x4_t vQ2 = q.get128();
- float32x4_t A0, A1, B1, A2, B2, A3, B3;
- float32x2_t vQ1zx, vQ2wx, vQ1yz, vQ2zx, vQ2yz, vQ2xz;
-
- {
- float32x2x2_t tmp;
- tmp = vtrn_f32( vget_high_f32(vQ1), vget_low_f32(vQ1) ); // {z x}, {w y}
- vQ1zx = tmp.val[0];
-
- tmp = vtrn_f32( vget_high_f32(vQ2), vget_low_f32(vQ2) ); // {z x}, {w y}
- vQ2zx = tmp.val[0];
- }
- vQ2wx = vext_f32(vget_high_f32(vQ2), vget_low_f32(vQ2), 1);
-
- vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
-
- vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
- vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
-
- A1 = vcombine_f32(vget_low_f32(vQ1), vQ1zx); // X Y z x
- B1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ2), 1), vQ2wx); // W W W X
-
- A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1));
- B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
-
- A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z
- B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z
-
- A1 = vmulq_f32(A1, B1);
- A2 = vmulq_f32(A2, B2);
- A3 = vmulq_f32(A3, B3); // A3 *= B3
- A0 = vmulq_lane_f32(vQ2, vget_high_f32(vQ1), 1); // A0 * B0
-
- A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2
- A0 = vsubq_f32(A0, A3); // AB03 = AB0 - AB3
-
- // change the sign of the last element
- A1 = (b3SimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)b3vPPPM);
- A0 = vaddq_f32(A0, A1); // AB03 + AB12
-
- mVec128 = A0;
+
+ B1 = b3_pshufd_ps(mVec128, B3_SHUFFLE(2, 0, 1, 2));
+ B2 = b3_pshufd_ps(vQ2, B3_SHUFFLE(1, 2, 0, 2));
+
+ B1 = B1 * B2; // A3 *= B3
+
+ mVec128 = b3_splat_ps(mVec128, 3); // A0
+ mVec128 = mVec128 * vQ2; // A0 * B0
+
+ A1 = A1 + A2; // AB12
+ mVec128 = mVec128 - B1; // AB03 = AB0 - AB3
+ A1 = _mm_xor_ps(A1, b3vPPPM); // change sign of the last element
+ mVec128 = mVec128 + A1; // AB03 + AB12
+
+#elif defined(B3_USE_NEON)
+
+ float32x4_t vQ1 = mVec128;
+ float32x4_t vQ2 = q.get128();
+ float32x4_t A0, A1, B1, A2, B2, A3, B3;
+ float32x2_t vQ1zx, vQ2wx, vQ1yz, vQ2zx, vQ2yz, vQ2xz;
+
+ {
+ float32x2x2_t tmp;
+ tmp = vtrn_f32(vget_high_f32(vQ1), vget_low_f32(vQ1)); // {z x}, {w y}
+ vQ1zx = tmp.val[0];
+
+ tmp = vtrn_f32(vget_high_f32(vQ2), vget_low_f32(vQ2)); // {z x}, {w y}
+ vQ2zx = tmp.val[0];
+ }
+ vQ2wx = vext_f32(vget_high_f32(vQ2), vget_low_f32(vQ2), 1);
+
+ vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
+
+ vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
+ vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
+
+ A1 = vcombine_f32(vget_low_f32(vQ1), vQ1zx); // X Y z x
+ B1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ2), 1), vQ2wx); // W W W X
+
+ A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1));
+ B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
+
+ A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z
+ B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z
+
+ A1 = vmulq_f32(A1, B1);
+ A2 = vmulq_f32(A2, B2);
+ A3 = vmulq_f32(A3, B3); // A3 *= B3
+ A0 = vmulq_lane_f32(vQ2, vget_high_f32(vQ1), 1); // A0 * B0
+
+ A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2
+ A0 = vsubq_f32(A0, A3); // AB03 = AB0 - AB3
+
+ // change the sign of the last element
+ A1 = (b3SimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)b3vPPPM);
+ A0 = vaddq_f32(A0, A1); // AB03 + AB12
+
+ mVec128 = A0;
#else
setValue(
- m_floats[3] * q.getX() + m_floats[0] * q.m_floats[3] + m_floats[1] * q.getZ() - m_floats[2] * q.getY(),
+ m_floats[3] * q.getX() + m_floats[0] * q.m_floats[3] + m_floats[1] * q.getZ() - m_floats[2] * q.getY(),
m_floats[3] * q.getY() + m_floats[1] * q.m_floats[3] + m_floats[2] * q.getX() - m_floats[0] * q.getZ(),
m_floats[3] * q.getZ() + m_floats[2] * q.m_floats[3] + m_floats[0] * q.getY() - m_floats[1] * q.getX(),
m_floats[3] * q.m_floats[3] - m_floats[0] * q.getX() - m_floats[1] * q.getY() - m_floats[2] * q.getZ());
#endif
return *this;
}
- /**@brief Return the dot product between this quaternion and another
+ /**@brief Return the dot product between this quaternion and another
* @param q The other quaternion */
b3Scalar dot(const b3Quaternion& q) const
{
-#if defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
- __m128 vd;
-
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+ __m128 vd;
+
vd = _mm_mul_ps(mVec128, q.mVec128);
-
- __m128 t = _mm_movehl_ps(vd, vd);
+
+ __m128 t = _mm_movehl_ps(vd, vd);
vd = _mm_add_ps(vd, t);
t = _mm_shuffle_ps(vd, vd, 0x55);
vd = _mm_add_ss(vd, t);
-
- return _mm_cvtss_f32(vd);
+
+ return _mm_cvtss_f32(vd);
#elif defined(B3_USE_NEON)
float32x4_t vd = vmulq_f32(mVec128, q.mVec128);
- float32x2_t x = vpadd_f32(vget_low_f32(vd), vget_high_f32(vd));
+ float32x2_t x = vpadd_f32(vget_low_f32(vd), vget_high_f32(vd));
x = vpadd_f32(x, x);
return vget_lane_f32(x, 0);
-#else
- return m_floats[0] * q.getX() +
- m_floats[1] * q.getY() +
- m_floats[2] * q.getZ() +
- m_floats[3] * q.m_floats[3];
+#else
+ return m_floats[0] * q.getX() +
+ m_floats[1] * q.getY() +
+ m_floats[2] * q.getZ() +
+ m_floats[3] * q.m_floats[3];
#endif
}
- /**@brief Return the length squared of the quaternion */
+ /**@brief Return the length squared of the quaternion */
b3Scalar length2() const
{
return dot(*this);
}
- /**@brief Return the length of the quaternion */
+ /**@brief Return the length of the quaternion */
b3Scalar length() const
{
return b3Sqrt(length2());
}
- /**@brief Normalize the quaternion
+ /**@brief Normalize the quaternion
* Such that x^2 + y^2 + z^2 +w^2 = 1 */
- b3Quaternion& normalize()
+ b3Quaternion& normalize()
{
-#if defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
- __m128 vd;
-
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+ __m128 vd;
+
vd = _mm_mul_ps(mVec128, mVec128);
-
- __m128 t = _mm_movehl_ps(vd, vd);
+
+ __m128 t = _mm_movehl_ps(vd, vd);
vd = _mm_add_ps(vd, t);
t = _mm_shuffle_ps(vd, vd, 0x55);
vd = _mm_add_ss(vd, t);
vd = _mm_sqrt_ss(vd);
vd = _mm_div_ss(b3vOnes, vd);
- vd = b3_pshufd_ps(vd, 0); // splat
+ vd = b3_pshufd_ps(vd, 0); // splat
mVec128 = _mm_mul_ps(mVec128, vd);
-
+
return *this;
-#else
+#else
return *this /= length();
#endif
}
- /**@brief Return a scaled version of this quaternion
+ /**@brief Return a scaled version of this quaternion
* @param s The scale factor */
B3_FORCE_INLINE b3Quaternion
operator*(const b3Scalar& s) const
{
-#if defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
- __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
- vs = b3_pshufd_ps(vs, 0x00); // (S S S S)
-
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+ __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
+ vs = b3_pshufd_ps(vs, 0x00); // (S S S S)
+
return b3Quaternion(_mm_mul_ps(mVec128, vs));
#elif defined(B3_USE_NEON)
return b3Quaternion(vmulq_n_f32(mVec128, s));
@@ -389,7 +390,7 @@ public:
#endif
}
- /**@brief Return an inversely scaled versionof this quaternion
+ /**@brief Return an inversely scaled versionof this quaternion
* @param s The inverse scale factor */
b3Quaternion operator/(const b3Scalar& s) const
{
@@ -397,29 +398,29 @@ public:
return *this * (b3Scalar(1.0) / s);
}
- /**@brief Inversely scale this quaternion
+ /**@brief Inversely scale this quaternion
* @param s The scale factor */
- b3Quaternion& operator/=(const b3Scalar& s)
+ b3Quaternion& operator/=(const b3Scalar& s)
{
b3Assert(s != b3Scalar(0.0));
return *this *= b3Scalar(1.0) / s;
}
- /**@brief Return a normalized version of this quaternion */
- b3Quaternion normalized() const
+ /**@brief Return a normalized version of this quaternion */
+ b3Quaternion normalized() const
{
return *this / length();
- }
- /**@brief Return the angle between this quaternion and the other
+ }
+ /**@brief Return the angle between this quaternion and the other
* @param q The other quaternion */
- b3Scalar angle(const b3Quaternion& q) const
+ b3Scalar angle(const b3Quaternion& q) const
{
b3Scalar s = b3Sqrt(length2() * q.length2());
b3Assert(s != b3Scalar(0.0));
return b3Acos(dot(q) / s);
}
- /**@brief Return the angle of rotation represented by this quaternion */
- b3Scalar getAngle() const
+ /**@brief Return the angle of rotation represented by this quaternion */
+ b3Scalar getAngle() const
{
b3Scalar s = b3Scalar(2.) * b3Acos(m_floats[3]);
return s;
@@ -428,117 +429,116 @@ public:
/**@brief Return the axis of the rotation represented by this quaternion */
b3Vector3 getAxis() const
{
- b3Scalar s_squared = 1.f-m_floats[3]*m_floats[3];
-
- if (s_squared < b3Scalar(10.) * B3_EPSILON) //Check for divide by zero
- return b3MakeVector3(1.0, 0.0, 0.0); // Arbitrary
- b3Scalar s = 1.f/b3Sqrt(s_squared);
+ b3Scalar s_squared = 1.f - m_floats[3] * m_floats[3];
+
+ if (s_squared < b3Scalar(10.) * B3_EPSILON) //Check for divide by zero
+ return b3MakeVector3(1.0, 0.0, 0.0); // Arbitrary
+ b3Scalar s = 1.f / b3Sqrt(s_squared);
return b3MakeVector3(m_floats[0] * s, m_floats[1] * s, m_floats[2] * s);
}
/**@brief Return the inverse of this quaternion */
b3Quaternion inverse() const
{
-#if defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
return b3Quaternion(_mm_xor_ps(mVec128, b3vQInv));
#elif defined(B3_USE_NEON)
- return b3Quaternion((b3SimdFloat4)veorq_s32((int32x4_t)mVec128, (int32x4_t)b3vQInv));
-#else
+ return b3Quaternion((b3SimdFloat4)veorq_s32((int32x4_t)mVec128, (int32x4_t)b3vQInv));
+#else
return b3Quaternion(-m_floats[0], -m_floats[1], -m_floats[2], m_floats[3]);
#endif
}
- /**@brief Return the sum of this quaternion and the other
+ /**@brief Return the sum of this quaternion and the other
* @param q2 The other quaternion */
B3_FORCE_INLINE b3Quaternion
operator+(const b3Quaternion& q2) const
{
-#if defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
return b3Quaternion(_mm_add_ps(mVec128, q2.mVec128));
#elif defined(B3_USE_NEON)
- return b3Quaternion(vaddq_f32(mVec128, q2.mVec128));
-#else
+ return b3Quaternion(vaddq_f32(mVec128, q2.mVec128));
+#else
const b3Quaternion& q1 = *this;
return b3Quaternion(q1.getX() + q2.getX(), q1.getY() + q2.getY(), q1.getZ() + q2.getZ(), q1.m_floats[3] + q2.m_floats[3]);
#endif
}
- /**@brief Return the difference between this quaternion and the other
+ /**@brief Return the difference between this quaternion and the other
* @param q2 The other quaternion */
B3_FORCE_INLINE b3Quaternion
operator-(const b3Quaternion& q2) const
{
-#if defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
return b3Quaternion(_mm_sub_ps(mVec128, q2.mVec128));
#elif defined(B3_USE_NEON)
- return b3Quaternion(vsubq_f32(mVec128, q2.mVec128));
-#else
+ return b3Quaternion(vsubq_f32(mVec128, q2.mVec128));
+#else
const b3Quaternion& q1 = *this;
return b3Quaternion(q1.getX() - q2.getX(), q1.getY() - q2.getY(), q1.getZ() - q2.getZ(), q1.m_floats[3] - q2.m_floats[3]);
#endif
}
- /**@brief Return the negative of this quaternion
+ /**@brief Return the negative of this quaternion
* This simply negates each element */
B3_FORCE_INLINE b3Quaternion operator-() const
{
-#if defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
return b3Quaternion(_mm_xor_ps(mVec128, b3vMzeroMask));
#elif defined(B3_USE_NEON)
- return b3Quaternion((b3SimdFloat4)veorq_s32((int32x4_t)mVec128, (int32x4_t)b3vMzeroMask) );
-#else
+ return b3Quaternion((b3SimdFloat4)veorq_s32((int32x4_t)mVec128, (int32x4_t)b3vMzeroMask));
+#else
const b3Quaternion& q2 = *this;
- return b3Quaternion( - q2.getX(), - q2.getY(), - q2.getZ(), - q2.m_floats[3]);
+ return b3Quaternion(-q2.getX(), -q2.getY(), -q2.getZ(), -q2.m_floats[3]);
#endif
}
- /**@todo document this and it's use */
- B3_FORCE_INLINE b3Quaternion farthest( const b3Quaternion& qd) const
+ /**@todo document this and it's use */
+ B3_FORCE_INLINE b3Quaternion farthest(const b3Quaternion& qd) const
{
- b3Quaternion diff,sum;
+ b3Quaternion diff, sum;
diff = *this - qd;
sum = *this + qd;
- if( diff.dot(diff) > sum.dot(sum) )
+ if (diff.dot(diff) > sum.dot(sum))
return qd;
return (-qd);
}
/**@todo document this and it's use */
- B3_FORCE_INLINE b3Quaternion nearest( const b3Quaternion& qd) const
+ B3_FORCE_INLINE b3Quaternion nearest(const b3Quaternion& qd) const
{
- b3Quaternion diff,sum;
+ b3Quaternion diff, sum;
diff = *this - qd;
sum = *this + qd;
- if( diff.dot(diff) < sum.dot(sum) )
+ if (diff.dot(diff) < sum.dot(sum))
return qd;
return (-qd);
}
-
- /**@brief Return the quaternion which is the result of Spherical Linear Interpolation between this and the other quaternion
+ /**@brief Return the quaternion which is the result of Spherical Linear Interpolation between this and the other quaternion
* @param q The other quaternion to interpolate with
* @param t The ratio between this and q to interpolate. If t = 0 the result is this, if t=1 the result is q.
* Slerp interpolates assuming constant velocity. */
b3Quaternion slerp(const b3Quaternion& q, const b3Scalar& t) const
{
- b3Scalar magnitude = b3Sqrt(length2() * q.length2());
- b3Assert(magnitude > b3Scalar(0));
+ b3Scalar magnitude = b3Sqrt(length2() * q.length2());
+ b3Assert(magnitude > b3Scalar(0));
- b3Scalar product = dot(q) / magnitude;
- if (b3Fabs(product) < b3Scalar(1))
+ b3Scalar product = dot(q) / magnitude;
+ if (b3Fabs(product) < b3Scalar(1))
{
- // Take care of long angle case see http://en.wikipedia.org/wiki/Slerp
- const b3Scalar sign = (product < 0) ? b3Scalar(-1) : b3Scalar(1);
-
- const b3Scalar theta = b3Acos(sign * product);
- const b3Scalar s1 = b3Sin(sign * t * theta);
- const b3Scalar d = b3Scalar(1.0) / b3Sin(theta);
- const b3Scalar s0 = b3Sin((b3Scalar(1.0) - t) * theta);
-
- return b3Quaternion(
- (m_floats[0] * s0 + q.getX() * s1) * d,
- (m_floats[1] * s0 + q.getY() * s1) * d,
- (m_floats[2] * s0 + q.getZ() * s1) * d,
- (m_floats[3] * s0 + q.m_floats[3] * s1) * d);
+ // Take care of long angle case see http://en.wikipedia.org/wiki/Slerp
+ const b3Scalar sign = (product < 0) ? b3Scalar(-1) : b3Scalar(1);
+
+ const b3Scalar theta = b3Acos(sign * product);
+ const b3Scalar s1 = b3Sin(sign * t * theta);
+ const b3Scalar d = b3Scalar(1.0) / b3Sin(theta);
+ const b3Scalar s0 = b3Sin((b3Scalar(1.0) - t) * theta);
+
+ return b3Quaternion(
+ (m_floats[0] * s0 + q.getX() * s1) * d,
+ (m_floats[1] * s0 + q.getY() * s1) * d,
+ (m_floats[2] * s0 + q.getZ() * s1) * d,
+ (m_floats[3] * s0 + q.m_floats[3] * s1) * d);
}
else
{
@@ -546,301 +546,294 @@ public:
}
}
- static const b3Quaternion& getIdentity()
+ static const b3Quaternion& getIdentity()
{
- static const b3Quaternion identityQuat(b3Scalar(0.),b3Scalar(0.),b3Scalar(0.),b3Scalar(1.));
+ static const b3Quaternion identityQuat(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.), b3Scalar(1.));
return identityQuat;
}
B3_FORCE_INLINE const b3Scalar& getW() const { return m_floats[3]; }
-
-
};
-
-
-
-
/**@brief Return the product of two quaternions */
B3_FORCE_INLINE b3Quaternion
-operator*(const b3Quaternion& q1, const b3Quaternion& q2)
+operator*(const b3Quaternion& q1, const b3Quaternion& q2)
{
-#if defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
__m128 vQ1 = q1.get128();
__m128 vQ2 = q2.get128();
__m128 A0, A1, B1, A2, B2;
-
- A1 = b3_pshufd_ps(vQ1, B3_SHUFFLE(0,1,2,0)); // X Y z x // vtrn
- B1 = b3_pshufd_ps(vQ2, B3_SHUFFLE(3,3,3,0)); // W W W X // vdup vext
+
+ A1 = b3_pshufd_ps(vQ1, B3_SHUFFLE(0, 1, 2, 0)); // X Y z x // vtrn
+ B1 = b3_pshufd_ps(vQ2, B3_SHUFFLE(3, 3, 3, 0)); // W W W X // vdup vext
A1 = A1 * B1;
-
- A2 = b3_pshufd_ps(vQ1, B3_SHUFFLE(1,2,0,1)); // Y Z X Y // vext
- B2 = b3_pshufd_ps(vQ2, B3_SHUFFLE(2,0,1,1)); // z x Y Y // vtrn vdup
+
+ A2 = b3_pshufd_ps(vQ1, B3_SHUFFLE(1, 2, 0, 1)); // Y Z X Y // vext
+ B2 = b3_pshufd_ps(vQ2, B3_SHUFFLE(2, 0, 1, 1)); // z x Y Y // vtrn vdup
A2 = A2 * B2;
- B1 = b3_pshufd_ps(vQ1, B3_SHUFFLE(2,0,1,2)); // z x Y Z // vtrn vext
- B2 = b3_pshufd_ps(vQ2, B3_SHUFFLE(1,2,0,2)); // Y Z x z // vext vtrn
-
- B1 = B1 * B2; // A3 *= B3
+ B1 = b3_pshufd_ps(vQ1, B3_SHUFFLE(2, 0, 1, 2)); // z x Y Z // vtrn vext
+ B2 = b3_pshufd_ps(vQ2, B3_SHUFFLE(1, 2, 0, 2)); // Y Z x z // vext vtrn
+
+ B1 = B1 * B2; // A3 *= B3
- A0 = b3_splat_ps(vQ1, 3); // A0
- A0 = A0 * vQ2; // A0 * B0
+ A0 = b3_splat_ps(vQ1, 3); // A0
+ A0 = A0 * vQ2; // A0 * B0
+
+ A1 = A1 + A2; // AB12
+ A0 = A0 - B1; // AB03 = AB0 - AB3
+
+ A1 = _mm_xor_ps(A1, b3vPPPM); // change sign of the last element
+ A0 = A0 + A1; // AB03 + AB12
- A1 = A1 + A2; // AB12
- A0 = A0 - B1; // AB03 = AB0 - AB3
-
- A1 = _mm_xor_ps(A1, b3vPPPM); // change sign of the last element
- A0 = A0 + A1; // AB03 + AB12
-
return b3Quaternion(A0);
-#elif defined(B3_USE_NEON)
+#elif defined(B3_USE_NEON)
float32x4_t vQ1 = q1.get128();
float32x4_t vQ2 = q2.get128();
float32x4_t A0, A1, B1, A2, B2, A3, B3;
- float32x2_t vQ1zx, vQ2wx, vQ1yz, vQ2zx, vQ2yz, vQ2xz;
-
- {
- float32x2x2_t tmp;
- tmp = vtrn_f32( vget_high_f32(vQ1), vget_low_f32(vQ1) ); // {z x}, {w y}
- vQ1zx = tmp.val[0];
+ float32x2_t vQ1zx, vQ2wx, vQ1yz, vQ2zx, vQ2yz, vQ2xz;
+
+ {
+ float32x2x2_t tmp;
+ tmp = vtrn_f32(vget_high_f32(vQ1), vget_low_f32(vQ1)); // {z x}, {w y}
+ vQ1zx = tmp.val[0];
- tmp = vtrn_f32( vget_high_f32(vQ2), vget_low_f32(vQ2) ); // {z x}, {w y}
- vQ2zx = tmp.val[0];
- }
- vQ2wx = vext_f32(vget_high_f32(vQ2), vget_low_f32(vQ2), 1);
+ tmp = vtrn_f32(vget_high_f32(vQ2), vget_low_f32(vQ2)); // {z x}, {w y}
+ vQ2zx = tmp.val[0];
+ }
+ vQ2wx = vext_f32(vget_high_f32(vQ2), vget_low_f32(vQ2), 1);
- vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
+ vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
- vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
- vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
+ vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
+ vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
- A1 = vcombine_f32(vget_low_f32(vQ1), vQ1zx); // X Y z x
- B1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ2), 1), vQ2wx); // W W W X
+ A1 = vcombine_f32(vget_low_f32(vQ1), vQ1zx); // X Y z x
+ B1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ2), 1), vQ2wx); // W W W X
A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1));
- B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
+ B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
- A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z
- B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z
+ A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z
+ B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z
A1 = vmulq_f32(A1, B1);
A2 = vmulq_f32(A2, B2);
- A3 = vmulq_f32(A3, B3); // A3 *= B3
- A0 = vmulq_lane_f32(vQ2, vget_high_f32(vQ1), 1); // A0 * B0
-
- A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2
- A0 = vsubq_f32(A0, A3); // AB03 = AB0 - AB3
-
- // change the sign of the last element
- A1 = (b3SimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)b3vPPPM);
- A0 = vaddq_f32(A0, A1); // AB03 + AB12
-
+ A3 = vmulq_f32(A3, B3); // A3 *= B3
+ A0 = vmulq_lane_f32(vQ2, vget_high_f32(vQ1), 1); // A0 * B0
+
+ A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2
+ A0 = vsubq_f32(A0, A3); // AB03 = AB0 - AB3
+
+ // change the sign of the last element
+ A1 = (b3SimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)b3vPPPM);
+ A0 = vaddq_f32(A0, A1); // AB03 + AB12
+
return b3Quaternion(A0);
#else
return b3Quaternion(
- q1.getW() * q2.getX() + q1.getX() * q2.getW() + q1.getY() * q2.getZ() - q1.getZ() * q2.getY(),
+ q1.getW() * q2.getX() + q1.getX() * q2.getW() + q1.getY() * q2.getZ() - q1.getZ() * q2.getY(),
q1.getW() * q2.getY() + q1.getY() * q2.getW() + q1.getZ() * q2.getX() - q1.getX() * q2.getZ(),
q1.getW() * q2.getZ() + q1.getZ() * q2.getW() + q1.getX() * q2.getY() - q1.getY() * q2.getX(),
- q1.getW() * q2.getW() - q1.getX() * q2.getX() - q1.getY() * q2.getY() - q1.getZ() * q2.getZ());
+ q1.getW() * q2.getW() - q1.getX() * q2.getX() - q1.getY() * q2.getY() - q1.getZ() * q2.getZ());
#endif
}
B3_FORCE_INLINE b3Quaternion
operator*(const b3Quaternion& q, const b3Vector3& w)
{
-#if defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
__m128 vQ1 = q.get128();
__m128 vQ2 = w.get128();
__m128 A1, B1, A2, B2, A3, B3;
-
- A1 = b3_pshufd_ps(vQ1, B3_SHUFFLE(3,3,3,0));
- B1 = b3_pshufd_ps(vQ2, B3_SHUFFLE(0,1,2,0));
+
+ A1 = b3_pshufd_ps(vQ1, B3_SHUFFLE(3, 3, 3, 0));
+ B1 = b3_pshufd_ps(vQ2, B3_SHUFFLE(0, 1, 2, 0));
A1 = A1 * B1;
-
- A2 = b3_pshufd_ps(vQ1, B3_SHUFFLE(1,2,0,1));
- B2 = b3_pshufd_ps(vQ2, B3_SHUFFLE(2,0,1,1));
+
+ A2 = b3_pshufd_ps(vQ1, B3_SHUFFLE(1, 2, 0, 1));
+ B2 = b3_pshufd_ps(vQ2, B3_SHUFFLE(2, 0, 1, 1));
A2 = A2 * B2;
- A3 = b3_pshufd_ps(vQ1, B3_SHUFFLE(2,0,1,2));
- B3 = b3_pshufd_ps(vQ2, B3_SHUFFLE(1,2,0,2));
-
- A3 = A3 * B3; // A3 *= B3
+ A3 = b3_pshufd_ps(vQ1, B3_SHUFFLE(2, 0, 1, 2));
+ B3 = b3_pshufd_ps(vQ2, B3_SHUFFLE(1, 2, 0, 2));
+
+ A3 = A3 * B3; // A3 *= B3
+
+ A1 = A1 + A2; // AB12
+ A1 = _mm_xor_ps(A1, b3vPPPM); // change sign of the last element
+ A1 = A1 - A3; // AB123 = AB12 - AB3
- A1 = A1 + A2; // AB12
- A1 = _mm_xor_ps(A1, b3vPPPM); // change sign of the last element
- A1 = A1 - A3; // AB123 = AB12 - AB3
-
return b3Quaternion(A1);
-
-#elif defined(B3_USE_NEON)
+
+#elif defined(B3_USE_NEON)
float32x4_t vQ1 = q.get128();
float32x4_t vQ2 = w.get128();
float32x4_t A1, B1, A2, B2, A3, B3;
- float32x2_t vQ1wx, vQ2zx, vQ1yz, vQ2yz, vQ1zx, vQ2xz;
-
- vQ1wx = vext_f32(vget_high_f32(vQ1), vget_low_f32(vQ1), 1);
- {
- float32x2x2_t tmp;
+ float32x2_t vQ1wx, vQ2zx, vQ1yz, vQ2yz, vQ1zx, vQ2xz;
- tmp = vtrn_f32( vget_high_f32(vQ2), vget_low_f32(vQ2) ); // {z x}, {w y}
- vQ2zx = tmp.val[0];
+ vQ1wx = vext_f32(vget_high_f32(vQ1), vget_low_f32(vQ1), 1);
+ {
+ float32x2x2_t tmp;
- tmp = vtrn_f32( vget_high_f32(vQ1), vget_low_f32(vQ1) ); // {z x}, {w y}
- vQ1zx = tmp.val[0];
- }
+ tmp = vtrn_f32(vget_high_f32(vQ2), vget_low_f32(vQ2)); // {z x}, {w y}
+ vQ2zx = tmp.val[0];
- vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
+ tmp = vtrn_f32(vget_high_f32(vQ1), vget_low_f32(vQ1)); // {z x}, {w y}
+ vQ1zx = tmp.val[0];
+ }
+
+ vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
- vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
- vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
+ vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
+ vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
- A1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ1), 1), vQ1wx); // W W W X
- B1 = vcombine_f32(vget_low_f32(vQ2), vQ2zx); // X Y z x
+ A1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ1), 1), vQ1wx); // W W W X
+ B1 = vcombine_f32(vget_low_f32(vQ2), vQ2zx); // X Y z x
A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1));
- B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
+ B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
- A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z
- B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z
+ A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z
+ B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z
A1 = vmulq_f32(A1, B1);
A2 = vmulq_f32(A2, B2);
- A3 = vmulq_f32(A3, B3); // A3 *= B3
-
- A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2
-
- // change the sign of the last element
- A1 = (b3SimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)b3vPPPM);
-
- A1 = vsubq_f32(A1, A3); // AB123 = AB12 - AB3
-
+ A3 = vmulq_f32(A3, B3); // A3 *= B3
+
+ A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2
+
+ // change the sign of the last element
+ A1 = (b3SimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)b3vPPPM);
+
+ A1 = vsubq_f32(A1, A3); // AB123 = AB12 - AB3
+
return b3Quaternion(A1);
-
+
#else
- return b3Quaternion(
- q.getW() * w.getX() + q.getY() * w.getZ() - q.getZ() * w.getY(),
- q.getW() * w.getY() + q.getZ() * w.getX() - q.getX() * w.getZ(),
- q.getW() * w.getZ() + q.getX() * w.getY() - q.getY() * w.getX(),
- -q.getX() * w.getX() - q.getY() * w.getY() - q.getZ() * w.getZ());
+ return b3Quaternion(
+ q.getW() * w.getX() + q.getY() * w.getZ() - q.getZ() * w.getY(),
+ q.getW() * w.getY() + q.getZ() * w.getX() - q.getX() * w.getZ(),
+ q.getW() * w.getZ() + q.getX() * w.getY() - q.getY() * w.getX(),
+ -q.getX() * w.getX() - q.getY() * w.getY() - q.getZ() * w.getZ());
#endif
}
B3_FORCE_INLINE b3Quaternion
operator*(const b3Vector3& w, const b3Quaternion& q)
{
-#if defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
__m128 vQ1 = w.get128();
__m128 vQ2 = q.get128();
__m128 A1, B1, A2, B2, A3, B3;
-
- A1 = b3_pshufd_ps(vQ1, B3_SHUFFLE(0,1,2,0)); // X Y z x
- B1 = b3_pshufd_ps(vQ2, B3_SHUFFLE(3,3,3,0)); // W W W X
+
+ A1 = b3_pshufd_ps(vQ1, B3_SHUFFLE(0, 1, 2, 0)); // X Y z x
+ B1 = b3_pshufd_ps(vQ2, B3_SHUFFLE(3, 3, 3, 0)); // W W W X
A1 = A1 * B1;
-
- A2 = b3_pshufd_ps(vQ1, B3_SHUFFLE(1,2,0,1));
- B2 = b3_pshufd_ps(vQ2, B3_SHUFFLE(2,0,1,1));
- A2 = A2 *B2;
+ A2 = b3_pshufd_ps(vQ1, B3_SHUFFLE(1, 2, 0, 1));
+ B2 = b3_pshufd_ps(vQ2, B3_SHUFFLE(2, 0, 1, 1));
+
+ A2 = A2 * B2;
+
+ A3 = b3_pshufd_ps(vQ1, B3_SHUFFLE(2, 0, 1, 2));
+ B3 = b3_pshufd_ps(vQ2, B3_SHUFFLE(1, 2, 0, 2));
+
+ A3 = A3 * B3; // A3 *= B3
- A3 = b3_pshufd_ps(vQ1, B3_SHUFFLE(2,0,1,2));
- B3 = b3_pshufd_ps(vQ2, B3_SHUFFLE(1,2,0,2));
-
- A3 = A3 * B3; // A3 *= B3
+ A1 = A1 + A2; // AB12
+ A1 = _mm_xor_ps(A1, b3vPPPM); // change sign of the last element
+ A1 = A1 - A3; // AB123 = AB12 - AB3
- A1 = A1 + A2; // AB12
- A1 = _mm_xor_ps(A1, b3vPPPM); // change sign of the last element
- A1 = A1 - A3; // AB123 = AB12 - AB3
-
return b3Quaternion(A1);
-#elif defined(B3_USE_NEON)
+#elif defined(B3_USE_NEON)
float32x4_t vQ1 = w.get128();
float32x4_t vQ2 = q.get128();
- float32x4_t A1, B1, A2, B2, A3, B3;
- float32x2_t vQ1zx, vQ2wx, vQ1yz, vQ2zx, vQ2yz, vQ2xz;
-
- {
- float32x2x2_t tmp;
-
- tmp = vtrn_f32( vget_high_f32(vQ1), vget_low_f32(vQ1) ); // {z x}, {w y}
- vQ1zx = tmp.val[0];
+ float32x4_t A1, B1, A2, B2, A3, B3;
+ float32x2_t vQ1zx, vQ2wx, vQ1yz, vQ2zx, vQ2yz, vQ2xz;
- tmp = vtrn_f32( vget_high_f32(vQ2), vget_low_f32(vQ2) ); // {z x}, {w y}
- vQ2zx = tmp.val[0];
- }
- vQ2wx = vext_f32(vget_high_f32(vQ2), vget_low_f32(vQ2), 1);
+ {
+ float32x2x2_t tmp;
+
+ tmp = vtrn_f32(vget_high_f32(vQ1), vget_low_f32(vQ1)); // {z x}, {w y}
+ vQ1zx = tmp.val[0];
+
+ tmp = vtrn_f32(vget_high_f32(vQ2), vget_low_f32(vQ2)); // {z x}, {w y}
+ vQ2zx = tmp.val[0];
+ }
+ vQ2wx = vext_f32(vget_high_f32(vQ2), vget_low_f32(vQ2), 1);
- vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
+ vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
- vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
- vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
+ vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
+ vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
- A1 = vcombine_f32(vget_low_f32(vQ1), vQ1zx); // X Y z x
- B1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ2), 1), vQ2wx); // W W W X
+ A1 = vcombine_f32(vget_low_f32(vQ1), vQ1zx); // X Y z x
+ B1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ2), 1), vQ2wx); // W W W X
A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1));
- B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
+ B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
- A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z
- B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z
+ A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z
+ B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z
A1 = vmulq_f32(A1, B1);
A2 = vmulq_f32(A2, B2);
- A3 = vmulq_f32(A3, B3); // A3 *= B3
-
- A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2
-
- // change the sign of the last element
- A1 = (b3SimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)b3vPPPM);
-
- A1 = vsubq_f32(A1, A3); // AB123 = AB12 - AB3
-
+ A3 = vmulq_f32(A3, B3); // A3 *= B3
+
+ A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2
+
+ // change the sign of the last element
+ A1 = (b3SimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)b3vPPPM);
+
+ A1 = vsubq_f32(A1, A3); // AB123 = AB12 - AB3
+
return b3Quaternion(A1);
-
+
#else
- return b3Quaternion(
- +w.getX() * q.getW() + w.getY() * q.getZ() - w.getZ() * q.getY(),
+ return b3Quaternion(
+ +w.getX() * q.getW() + w.getY() * q.getZ() - w.getZ() * q.getY(),
+w.getY() * q.getW() + w.getZ() * q.getX() - w.getX() * q.getZ(),
+w.getZ() * q.getW() + w.getX() * q.getY() - w.getY() * q.getX(),
- -w.getX() * q.getX() - w.getY() * q.getY() - w.getZ() * q.getZ());
+ -w.getX() * q.getX() - w.getY() * q.getY() - w.getZ() * q.getZ());
#endif
}
/**@brief Calculate the dot product between two quaternions */
-B3_FORCE_INLINE b3Scalar
-b3Dot(const b3Quaternion& q1, const b3Quaternion& q2)
-{
- return q1.dot(q2);
+B3_FORCE_INLINE b3Scalar
+b3Dot(const b3Quaternion& q1, const b3Quaternion& q2)
+{
+ return q1.dot(q2);
}
-
/**@brief Return the length of a quaternion */
B3_FORCE_INLINE b3Scalar
-b3Length(const b3Quaternion& q)
-{
- return q.length();
+b3Length(const b3Quaternion& q)
+{
+ return q.length();
}
/**@brief Return the angle between two quaternions*/
B3_FORCE_INLINE b3Scalar
-b3Angle(const b3Quaternion& q1, const b3Quaternion& q2)
-{
- return q1.angle(q2);
+b3Angle(const b3Quaternion& q1, const b3Quaternion& q2)
+{
+ return q1.angle(q2);
}
/**@brief Return the inverse of a quaternion*/
B3_FORCE_INLINE b3Quaternion
-b3Inverse(const b3Quaternion& q)
+b3Inverse(const b3Quaternion& q)
{
return q.inverse();
}
@@ -851,7 +844,7 @@ b3Inverse(const b3Quaternion& q)
* @param t The ration between q1 and q2. t = 0 return q1, t=1 returns q2
* Slerp assumes constant velocity between positions. */
B3_FORCE_INLINE b3Quaternion
-b3Slerp(const b3Quaternion& q1, const b3Quaternion& q2, const b3Scalar& t)
+b3Slerp(const b3Quaternion& q1, const b3Quaternion& q2, const b3Scalar& t)
{
return q1.slerp(q2, t);
}
@@ -859,7 +852,7 @@ b3Slerp(const b3Quaternion& q1, const b3Quaternion& q2, const b3Scalar& t)
B3_FORCE_INLINE b3Quaternion
b3QuatMul(const b3Quaternion& rot0, const b3Quaternion& rot1)
{
- return rot0*rot1;
+ return rot0 * rot1;
}
B3_FORCE_INLINE b3Quaternion
@@ -868,51 +861,45 @@ b3QuatNormalized(const b3Quaternion& orn)
return orn.normalized();
}
-
-
-B3_FORCE_INLINE b3Vector3
-b3QuatRotate(const b3Quaternion& rotation, const b3Vector3& v)
+B3_FORCE_INLINE b3Vector3
+b3QuatRotate(const b3Quaternion& rotation, const b3Vector3& v)
{
b3Quaternion q = rotation * v;
q *= rotation.inverse();
-#if defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
return b3MakeVector3(_mm_and_ps(q.get128(), b3vFFF0fMask));
#elif defined(B3_USE_NEON)
- return b3MakeVector3((float32x4_t)vandq_s32((int32x4_t)q.get128(), b3vFFF0Mask));
-#else
- return b3MakeVector3(q.getX(),q.getY(),q.getZ());
+ return b3MakeVector3((float32x4_t)vandq_s32((int32x4_t)q.get128(), b3vFFF0Mask));
+#else
+ return b3MakeVector3(q.getX(), q.getY(), q.getZ());
#endif
}
-B3_FORCE_INLINE b3Quaternion
-b3ShortestArcQuat(const b3Vector3& v0, const b3Vector3& v1) // Game Programming Gems 2.10. make sure v0,v1 are normalized
+B3_FORCE_INLINE b3Quaternion
+b3ShortestArcQuat(const b3Vector3& v0, const b3Vector3& v1) // Game Programming Gems 2.10. make sure v0,v1 are normalized
{
b3Vector3 c = v0.cross(v1);
- b3Scalar d = v0.dot(v1);
+ b3Scalar d = v0.dot(v1);
if (d < -1.0 + B3_EPSILON)
{
- b3Vector3 n,unused;
- b3PlaneSpace1(v0,n,unused);
- return b3Quaternion(n.getX(),n.getY(),n.getZ(),0.0f); // just pick any vector that is orthogonal to v0
+ b3Vector3 n, unused;
+ b3PlaneSpace1(v0, n, unused);
+ return b3Quaternion(n.getX(), n.getY(), n.getZ(), 0.0f); // just pick any vector that is orthogonal to v0
}
- b3Scalar s = b3Sqrt((1.0f + d) * 2.0f);
+ b3Scalar s = b3Sqrt((1.0f + d) * 2.0f);
b3Scalar rs = 1.0f / s;
- return b3Quaternion(c.getX()*rs,c.getY()*rs,c.getZ()*rs,s * 0.5f);
-
+ return b3Quaternion(c.getX() * rs, c.getY() * rs, c.getZ() * rs, s * 0.5f);
}
-B3_FORCE_INLINE b3Quaternion
-b3ShortestArcQuatNormalize2(b3Vector3& v0,b3Vector3& v1)
+B3_FORCE_INLINE b3Quaternion
+b3ShortestArcQuatNormalize2(b3Vector3& v0, b3Vector3& v1)
{
v0.normalize();
v1.normalize();
- return b3ShortestArcQuat(v0,v1);
+ return b3ShortestArcQuat(v0, v1);
}
-#endif //B3_SIMD__QUATERNION_H_
-
-
-
+#endif //B3_SIMD__QUATERNION_H_
diff --git a/thirdparty/bullet/Bullet3Common/b3Random.h b/thirdparty/bullet/Bullet3Common/b3Random.h
index dc040f1562..c2e21496c7 100644
--- a/thirdparty/bullet/Bullet3Common/b3Random.h
+++ b/thirdparty/bullet/Bullet3Common/b3Random.h
@@ -12,8 +12,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
-
#ifndef B3_GEN_RANDOM_H
#define B3_GEN_RANDOM_H
@@ -26,8 +24,8 @@ subject to the following restrictions:
#define B3_RAND_MAX UINT_MAX
-B3_FORCE_INLINE void b3Srand(unsigned int seed) { init_genrand(seed); }
-B3_FORCE_INLINE unsigned int b3rand() { return genrand_int32(); }
+B3_FORCE_INLINE void b3Srand(unsigned int seed) { init_genrand(seed); }
+B3_FORCE_INLINE unsigned int b3rand() { return genrand_int32(); }
#else
@@ -35,8 +33,8 @@ B3_FORCE_INLINE unsigned int b3rand() { return genrand_int32()
#define B3_RAND_MAX RAND_MAX
-B3_FORCE_INLINE void b3Srand(unsigned int seed) { srand(seed); }
-B3_FORCE_INLINE unsigned int b3rand() { return rand(); }
+B3_FORCE_INLINE void b3Srand(unsigned int seed) { srand(seed); }
+B3_FORCE_INLINE unsigned int b3rand() { return rand(); }
#endif
@@ -45,6 +43,4 @@ inline b3Scalar b3RandRange(b3Scalar minRange, b3Scalar maxRange)
return (b3rand() / (b3Scalar(B3_RAND_MAX) + b3Scalar(1.0))) * (maxRange - minRange) + minRange;
}
-
-#endif //B3_GEN_RANDOM_H
-
+#endif //B3_GEN_RANDOM_H
diff --git a/thirdparty/bullet/Bullet3Common/b3ResizablePool.h b/thirdparty/bullet/Bullet3Common/b3ResizablePool.h
index 06ad8a778d..cafe3ff396 100644
--- a/thirdparty/bullet/Bullet3Common/b3ResizablePool.h
+++ b/thirdparty/bullet/Bullet3Common/b3ResizablePool.h
@@ -4,10 +4,10 @@
#include "Bullet3Common/b3AlignedObjectArray.h"
-enum
+enum
{
- B3_POOL_HANDLE_TERMINAL_FREE=-1,
- B3_POOL_HANDLE_TERMINAL_USED =-2
+ B3_POOL_HANDLE_TERMINAL_FREE = -1,
+ B3_POOL_HANDLE_TERMINAL_USED = -2
};
template <typename U>
@@ -20,25 +20,23 @@ struct b3PoolBodyHandle : public U
{
m_nextFreeHandle = next;
}
- int getNextFree() const
+ int getNextFree() const
{
return m_nextFreeHandle;
}
};
-template <typename T>
+template <typename T>
class b3ResizablePool
{
-
protected:
- b3AlignedObjectArray<T> m_bodyHandles;
- int m_numUsedHandles; // number of active handles
- int m_firstFreeHandle; // free handles list
+ b3AlignedObjectArray<T> m_bodyHandles;
+ int m_numUsedHandles; // number of active handles
+ int m_firstFreeHandle; // free handles list
T* getHandleInternal(int handle)
{
return &m_bodyHandles[handle];
-
}
const T* getHandleInternal(int handle) const
{
@@ -46,17 +44,16 @@ protected:
}
public:
-
b3ResizablePool()
{
initHandles();
}
-
+
virtual ~b3ResizablePool()
{
exitHandles();
}
-///handle management
+ ///handle management
int getNumHandles() const
{
@@ -65,44 +62,40 @@ public:
void getUsedHandles(b3AlignedObjectArray<int>& usedHandles) const
{
-
- for (int i=0;i<m_bodyHandles.size();i++)
+ for (int i = 0; i < m_bodyHandles.size(); i++)
{
- if (m_bodyHandles[i].getNextFree()==B3_POOL_HANDLE_TERMINAL_USED)
+ if (m_bodyHandles[i].getNextFree() == B3_POOL_HANDLE_TERMINAL_USED)
{
usedHandles.push_back(i);
}
}
}
-
-
T* getHandle(int handle)
{
- b3Assert(handle>=0);
- b3Assert(handle<m_bodyHandles.size());
- if ((handle<0) || (handle>=m_bodyHandles.size()))
+ b3Assert(handle >= 0);
+ b3Assert(handle < m_bodyHandles.size());
+ if ((handle < 0) || (handle >= m_bodyHandles.size()))
{
return 0;
}
- if (m_bodyHandles[handle].getNextFree()==B3_POOL_HANDLE_TERMINAL_USED)
+ if (m_bodyHandles[handle].getNextFree() == B3_POOL_HANDLE_TERMINAL_USED)
{
return &m_bodyHandles[handle];
}
return 0;
-
}
const T* getHandle(int handle) const
{
- b3Assert(handle>=0);
- b3Assert(handle<m_bodyHandles.size());
- if ((handle<0) || (handle>=m_bodyHandles.size()))
+ b3Assert(handle >= 0);
+ b3Assert(handle < m_bodyHandles.size());
+ if ((handle < 0) || (handle >= m_bodyHandles.size()))
{
return 0;
}
- if (m_bodyHandles[handle].getNextFree()==B3_POOL_HANDLE_TERMINAL_USED)
+ if (m_bodyHandles[handle].getNextFree() == B3_POOL_HANDLE_TERMINAL_USED)
{
return &m_bodyHandles[handle];
}
@@ -120,7 +113,6 @@ public:
for (int i = curCapacity; i < newCapacity; i++)
m_bodyHandles[i].setNextFree(i + 1);
-
m_bodyHandles[newCapacity - 1].setNextFree(-1);
}
m_firstFreeHandle = curCapacity;
@@ -142,19 +134,18 @@ public:
int allocHandle()
{
- b3Assert(m_firstFreeHandle>=0);
+ b3Assert(m_firstFreeHandle >= 0);
int handle = m_firstFreeHandle;
m_firstFreeHandle = getHandleInternal(handle)->getNextFree();
m_numUsedHandles++;
- if (m_firstFreeHandle<0)
+ if (m_firstFreeHandle < 0)
{
//int curCapacity = m_bodyHandles.size();
- int additionalCapacity= m_bodyHandles.size();
+ int additionalCapacity = m_bodyHandles.size();
increaseHandleCapacity(additionalCapacity);
-
getHandleInternal(handle)->setNextFree(m_firstFreeHandle);
}
getHandleInternal(handle)->setNextFree(B3_POOL_HANDLE_TERMINAL_USED);
@@ -162,12 +153,11 @@ public:
return handle;
}
-
void freeHandle(int handle)
{
b3Assert(handle >= 0);
- if (m_bodyHandles[handle].getNextFree()==B3_POOL_HANDLE_TERMINAL_USED)
+ if (m_bodyHandles[handle].getNextFree() == B3_POOL_HANDLE_TERMINAL_USED)
{
getHandleInternal(handle)->clear();
getHandleInternal(handle)->setNextFree(m_firstFreeHandle);
@@ -176,7 +166,6 @@ public:
}
}
};
- ///end handle management
-
- #endif //B3_RESIZABLE_POOL_H
- \ No newline at end of file
+///end handle management
+
+#endif //B3_RESIZABLE_POOL_H
diff --git a/thirdparty/bullet/Bullet3Common/b3Scalar.h b/thirdparty/bullet/Bullet3Common/b3Scalar.h
index dbc7fea397..0db5eb6f4f 100644
--- a/thirdparty/bullet/Bullet3Common/b3Scalar.h
+++ b/thirdparty/bullet/Bullet3Common/b3Scalar.h
@@ -12,8 +12,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
-
#ifndef B3_SCALAR_H
#define B3_SCALAR_H
@@ -22,238 +20,252 @@ subject to the following restrictions:
#pragma unmanaged
#endif
-
-
#include <math.h>
-#include <stdlib.h>//size_t for MSVC 6.0
+#include <stdlib.h> //size_t for MSVC 6.0
#include <float.h>
//Original repository is at http://github.com/erwincoumans/bullet3
#define B3_BULLET_VERSION 300
-inline int b3GetVersion()
+inline int b3GetVersion()
{
return B3_BULLET_VERSION;
}
-#if defined(DEBUG) || defined (_DEBUG)
+#if defined(DEBUG) || defined(_DEBUG)
#define B3_DEBUG
#endif
-#include "b3Logging.h"//for b3Error
-
+#include "b3Logging.h" //for b3Error
#ifdef _WIN32
- #if defined(__MINGW32__) || defined(__CYGWIN__) || (defined (_MSC_VER) && _MSC_VER < 1300)
+#if defined(__MINGW32__) || defined(__CYGWIN__) || (defined(_MSC_VER) && _MSC_VER < 1300)
- #define B3_FORCE_INLINE inline
- #define B3_ATTRIBUTE_ALIGNED16(a) a
- #define B3_ATTRIBUTE_ALIGNED64(a) a
- #define B3_ATTRIBUTE_ALIGNED128(a) a
- #else
- //#define B3_HAS_ALIGNED_ALLOCATOR
- #pragma warning(disable : 4324) // disable padding warning
+#define B3_FORCE_INLINE inline
+#define B3_ATTRIBUTE_ALIGNED16(a) a
+#define B3_ATTRIBUTE_ALIGNED64(a) a
+#define B3_ATTRIBUTE_ALIGNED128(a) a
+#else
+//#define B3_HAS_ALIGNED_ALLOCATOR
+#pragma warning(disable : 4324) // disable padding warning
// #pragma warning(disable:4530) // Disable the exception disable but used in MSCV Stl warning.
- #pragma warning(disable:4996) //Turn off warnings about deprecated C routines
+#pragma warning(disable : 4996) //Turn off warnings about deprecated C routines
// #pragma warning(disable:4786) // Disable the "debug name too long" warning
- #define B3_FORCE_INLINE __forceinline
- #define B3_ATTRIBUTE_ALIGNED16(a) __declspec(align(16)) a
- #define B3_ATTRIBUTE_ALIGNED64(a) __declspec(align(64)) a
- #define B3_ATTRIBUTE_ALIGNED128(a) __declspec (align(128)) a
- #ifdef _XBOX
- #define B3_USE_VMX128
-
- #include <ppcintrinsics.h>
- #define B3_HAVE_NATIVE_FSEL
- #define b3Fsel(a,b,c) __fsel((a),(b),(c))
- #else
-
-#if (defined (_WIN32) && (_MSC_VER) && _MSC_VER >= 1400) && (!defined (B3_USE_DOUBLE_PRECISION))
- #if (defined (_M_IX86) || defined (_M_X64))
- #define B3_USE_SSE
- #ifdef B3_USE_SSE
- //B3_USE_SSE_IN_API is disabled under Windows by default, because
- //it makes it harder to integrate Bullet into your application under Windows
- //(structured embedding Bullet structs/classes need to be 16-byte aligned)
- //with relatively little performance gain
- //If you are not embedded Bullet data in your classes, or make sure that you align those classes on 16-byte boundaries
- //you can manually enable this line or set it in the build system for a bit of performance gain (a few percent, dependent on usage)
- //#define B3_USE_SSE_IN_API
- #endif //B3_USE_SSE
- #include <emmintrin.h>
- #endif
+#define B3_FORCE_INLINE __forceinline
+#define B3_ATTRIBUTE_ALIGNED16(a) __declspec(align(16)) a
+#define B3_ATTRIBUTE_ALIGNED64(a) __declspec(align(64)) a
+#define B3_ATTRIBUTE_ALIGNED128(a) __declspec(align(128)) a
+#ifdef _XBOX
+#define B3_USE_VMX128
+
+#include <ppcintrinsics.h>
+#define B3_HAVE_NATIVE_FSEL
+#define b3Fsel(a, b, c) __fsel((a), (b), (c))
+#else
+
+#if (defined(_WIN32) && (_MSC_VER) && _MSC_VER >= 1400) && (!defined(B3_USE_DOUBLE_PRECISION))
+#if (defined(_M_IX86) || defined(_M_X64))
+#define B3_USE_SSE
+#ifdef B3_USE_SSE
+//B3_USE_SSE_IN_API is disabled under Windows by default, because
+//it makes it harder to integrate Bullet into your application under Windows
+//(structured embedding Bullet structs/classes need to be 16-byte aligned)
+//with relatively little performance gain
+//If you are not embedded Bullet data in your classes, or make sure that you align those classes on 16-byte boundaries
+//you can manually enable this line or set it in the build system for a bit of performance gain (a few percent, dependent on usage)
+//#define B3_USE_SSE_IN_API
+#endif //B3_USE_SSE
+#include <emmintrin.h>
+#endif
#endif
- #endif//_XBOX
+#endif //_XBOX
- #endif //__MINGW32__
+#endif //__MINGW32__
#ifdef B3_DEBUG
- #ifdef _MSC_VER
- #include <stdio.h>
- #define b3Assert(x) { if(!(x)){b3Error("Assert "__FILE__ ":%u ("#x")\n", __LINE__);__debugbreak(); }}
- #else//_MSC_VER
- #include <assert.h>
- #define b3Assert assert
- #endif//_MSC_VER
+#ifdef _MSC_VER
+#include <stdio.h>
+#define b3Assert(x) \
+ { \
+ if (!(x)) \
+ { \
+ b3Error( \
+ "Assert "__FILE__ \
+ ":%u (" #x ")\n", \
+ __LINE__); \
+ __debugbreak(); \
+ } \
+ }
+#else //_MSC_VER
+#include <assert.h>
+#define b3Assert assert
+#endif //_MSC_VER
#else
- #define b3Assert(x)
+#define b3Assert(x)
#endif
- //b3FullAssert is optional, slows down a lot
- #define b3FullAssert(x)
+//b3FullAssert is optional, slows down a lot
+#define b3FullAssert(x)
- #define b3Likely(_c) _c
- #define b3Unlikely(_c) _c
+#define b3Likely(_c) _c
+#define b3Unlikely(_c) _c
#else
-
-#if defined (__CELLOS_LV2__)
- #define B3_FORCE_INLINE inline __attribute__((always_inline))
- #define B3_ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16)))
- #define B3_ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64)))
- #define B3_ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128)))
- #ifndef assert
- #include <assert.h>
- #endif
+
+#if defined(__CELLOS_LV2__)
+#define B3_FORCE_INLINE inline __attribute__((always_inline))
+#define B3_ATTRIBUTE_ALIGNED16(a) a __attribute__((aligned(16)))
+#define B3_ATTRIBUTE_ALIGNED64(a) a __attribute__((aligned(64)))
+#define B3_ATTRIBUTE_ALIGNED128(a) a __attribute__((aligned(128)))
+#ifndef assert
+#include <assert.h>
+#endif
#ifdef B3_DEBUG
#ifdef __SPU__
#include <spu_printf.h>
#define printf spu_printf
- #define b3Assert(x) {if(!(x)){b3Error("Assert "__FILE__ ":%u ("#x")\n", __LINE__);spu_hcmpeq(0,0);}}
+#define b3Assert(x) \
+ { \
+ if (!(x)) \
+ { \
+ b3Error( \
+ "Assert "__FILE__ \
+ ":%u (" #x ")\n", \
+ __LINE__); \
+ spu_hcmpeq(0, 0); \
+ } \
+ }
#else
- #define b3Assert assert
+#define b3Assert assert
#endif
-
+
#else
- #define b3Assert(x)
+#define b3Assert(x)
#endif
- //b3FullAssert is optional, slows down a lot
- #define b3FullAssert(x)
+//b3FullAssert is optional, slows down a lot
+#define b3FullAssert(x)
- #define b3Likely(_c) _c
- #define b3Unlikely(_c) _c
+#define b3Likely(_c) _c
+#define b3Unlikely(_c) _c
#else
#ifdef USE_LIBSPE2
- #define B3_FORCE_INLINE __inline
- #define B3_ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16)))
- #define B3_ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64)))
- #define B3_ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128)))
- #ifndef assert
- #include <assert.h>
- #endif
+#define B3_FORCE_INLINE __inline
+#define B3_ATTRIBUTE_ALIGNED16(a) a __attribute__((aligned(16)))
+#define B3_ATTRIBUTE_ALIGNED64(a) a __attribute__((aligned(64)))
+#define B3_ATTRIBUTE_ALIGNED128(a) a __attribute__((aligned(128)))
+#ifndef assert
+#include <assert.h>
+#endif
#ifdef B3_DEBUG
- #define b3Assert assert
+#define b3Assert assert
#else
- #define b3Assert(x)
+#define b3Assert(x)
#endif
- //b3FullAssert is optional, slows down a lot
- #define b3FullAssert(x)
+//b3FullAssert is optional, slows down a lot
+#define b3FullAssert(x)
+#define b3Likely(_c) __builtin_expect((_c), 1)
+#define b3Unlikely(_c) __builtin_expect((_c), 0)
- #define b3Likely(_c) __builtin_expect((_c), 1)
- #define b3Unlikely(_c) __builtin_expect((_c), 0)
-
-
#else
- //non-windows systems
-
-#if (defined (__APPLE__) && (!defined (B3_USE_DOUBLE_PRECISION)))
- #if defined (__i386__) || defined (__x86_64__)
- #define B3_USE_SSE
- //B3_USE_SSE_IN_API is enabled on Mac OSX by default, because memory is automatically aligned on 16-byte boundaries
- //if apps run into issues, we will disable the next line
- #define B3_USE_SSE_IN_API
- #ifdef B3_USE_SSE
- // include appropriate SSE level
- #if defined (__SSE4_1__)
- #include <smmintrin.h>
- #elif defined (__SSSE3__)
- #include <tmmintrin.h>
- #elif defined (__SSE3__)
- #include <pmmintrin.h>
- #else
- #include <emmintrin.h>
- #endif
- #endif //B3_USE_SSE
- #elif defined( __armv7__ )
- #ifdef __clang__
- #define B3_USE_NEON 1
-
- #if defined B3_USE_NEON && defined (__clang__)
- #include <arm_neon.h>
- #endif//B3_USE_NEON
- #endif //__clang__
- #endif//__arm__
-
- #define B3_FORCE_INLINE inline __attribute__ ((always_inline))
+//non-windows systems
+
+#if (defined(__APPLE__) && (!defined(B3_USE_DOUBLE_PRECISION)))
+#if defined(__i386__) || defined(__x86_64__)
+#define B3_USE_SSE
+//B3_USE_SSE_IN_API is enabled on Mac OSX by default, because memory is automatically aligned on 16-byte boundaries
+//if apps run into issues, we will disable the next line
+#define B3_USE_SSE_IN_API
+#ifdef B3_USE_SSE
+// include appropriate SSE level
+#if defined(__SSE4_1__)
+#include <smmintrin.h>
+#elif defined(__SSSE3__)
+#include <tmmintrin.h>
+#elif defined(__SSE3__)
+#include <pmmintrin.h>
+#else
+#include <emmintrin.h>
+#endif
+#endif //B3_USE_SSE
+#elif defined(__armv7__)
+#ifdef __clang__
+#define B3_USE_NEON 1
+
+#if defined B3_USE_NEON && defined(__clang__)
+#include <arm_neon.h>
+#endif //B3_USE_NEON
+#endif //__clang__
+#endif //__arm__
+
+#define B3_FORCE_INLINE inline __attribute__((always_inline))
///@todo: check out alignment methods for other platforms/compilers
- #define B3_ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16)))
- #define B3_ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64)))
- #define B3_ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128)))
- #ifndef assert
- #include <assert.h>
- #endif
-
- #if defined(DEBUG) || defined (_DEBUG)
- #if defined (__i386__) || defined (__x86_64__)
- #include <stdio.h>
- #define b3Assert(x)\
- {\
- if(!(x))\
- {\
- b3Error("Assert %s in line %d, file %s\n",#x, __LINE__, __FILE__);\
- asm volatile ("int3");\
- }\
+#define B3_ATTRIBUTE_ALIGNED16(a) a __attribute__((aligned(16)))
+#define B3_ATTRIBUTE_ALIGNED64(a) a __attribute__((aligned(64)))
+#define B3_ATTRIBUTE_ALIGNED128(a) a __attribute__((aligned(128)))
+#ifndef assert
+#include <assert.h>
+#endif
+
+#if defined(DEBUG) || defined(_DEBUG)
+#if defined(__i386__) || defined(__x86_64__)
+#include <stdio.h>
+#define b3Assert(x) \
+ { \
+ if (!(x)) \
+ { \
+ b3Error("Assert %s in line %d, file %s\n", #x, __LINE__, __FILE__); \
+ asm volatile("int3"); \
+ } \
}
- #else//defined (__i386__) || defined (__x86_64__)
- #define b3Assert assert
- #endif//defined (__i386__) || defined (__x86_64__)
- #else//defined(DEBUG) || defined (_DEBUG)
- #define b3Assert(x)
- #endif//defined(DEBUG) || defined (_DEBUG)
-
- //b3FullAssert is optional, slows down a lot
- #define b3FullAssert(x)
- #define b3Likely(_c) _c
- #define b3Unlikely(_c) _c
+#else //defined (__i386__) || defined (__x86_64__)
+#define b3Assert assert
+#endif //defined (__i386__) || defined (__x86_64__)
+#else //defined(DEBUG) || defined (_DEBUG)
+#define b3Assert(x)
+#endif //defined(DEBUG) || defined (_DEBUG)
+
+//b3FullAssert is optional, slows down a lot
+#define b3FullAssert(x)
+#define b3Likely(_c) _c
+#define b3Unlikely(_c) _c
#else
- #define B3_FORCE_INLINE inline
- ///@todo: check out alignment methods for other platforms/compilers
- #define B3_ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16)))
- #define B3_ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64)))
- #define B3_ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128)))
- ///#define B3_ATTRIBUTE_ALIGNED16(a) a
- ///#define B3_ATTRIBUTE_ALIGNED64(a) a
- ///#define B3_ATTRIBUTE_ALIGNED128(a) a
- #ifndef assert
- #include <assert.h>
- #endif
-
-#if defined(DEBUG) || defined (_DEBUG)
- #define b3Assert assert
+#define B3_FORCE_INLINE inline
+///@todo: check out alignment methods for other platforms/compilers
+#define B3_ATTRIBUTE_ALIGNED16(a) a __attribute__((aligned(16)))
+#define B3_ATTRIBUTE_ALIGNED64(a) a __attribute__((aligned(64)))
+#define B3_ATTRIBUTE_ALIGNED128(a) a __attribute__((aligned(128)))
+///#define B3_ATTRIBUTE_ALIGNED16(a) a
+///#define B3_ATTRIBUTE_ALIGNED64(a) a
+///#define B3_ATTRIBUTE_ALIGNED128(a) a
+#ifndef assert
+#include <assert.h>
+#endif
+
+#if defined(DEBUG) || defined(_DEBUG)
+#define b3Assert assert
#else
- #define b3Assert(x)
+#define b3Assert(x)
#endif
- //b3FullAssert is optional, slows down a lot
- #define b3FullAssert(x)
- #define b3Likely(_c) _c
- #define b3Unlikely(_c) _c
-#endif //__APPLE__
+//b3FullAssert is optional, slows down a lot
+#define b3FullAssert(x)
+#define b3Likely(_c) _c
+#define b3Unlikely(_c) _c
+#endif //__APPLE__
-#endif // LIBSPE2
+#endif // LIBSPE2
-#endif //__CELLOS_LV2__
+#endif //__CELLOS_LV2__
#endif
-
///The b3Scalar type abstracts floating point numbers, to easily switch between double and single floating point precision.
#if defined(B3_USE_DOUBLE_PRECISION)
typedef double b3Scalar;
@@ -267,34 +279,34 @@ typedef float b3Scalar;
#ifdef B3_USE_SSE
typedef __m128 b3SimdFloat4;
-#endif//B3_USE_SSE
+#endif //B3_USE_SSE
-#if defined B3_USE_SSE_IN_API && defined (B3_USE_SSE)
+#if defined B3_USE_SSE_IN_API && defined(B3_USE_SSE)
#ifdef _WIN32
#ifndef B3_NAN
static int b3NanMask = 0x7F800001;
-#define B3_NAN (*(float*)&b3NanMask)
+#define B3_NAN (*(float *)&b3NanMask)
#endif
#ifndef B3_INFINITY_MASK
-static int b3InfinityMask = 0x7F800000;
-#define B3_INFINITY_MASK (*(float*)&b3InfinityMask)
+static int b3InfinityMask = 0x7F800000;
+#define B3_INFINITY_MASK (*(float *)&b3InfinityMask)
#endif
-inline __m128 operator + (const __m128 A, const __m128 B)
+inline __m128 operator+(const __m128 A, const __m128 B)
{
- return _mm_add_ps(A, B);
+ return _mm_add_ps(A, B);
}
-inline __m128 operator - (const __m128 A, const __m128 B)
+inline __m128 operator-(const __m128 A, const __m128 B)
{
- return _mm_sub_ps(A, B);
+ return _mm_sub_ps(A, B);
}
-inline __m128 operator * (const __m128 A, const __m128 B)
+inline __m128 operator*(const __m128 A, const __m128 B)
{
- return _mm_mul_ps(A, B);
+ return _mm_mul_ps(A, B);
}
#define b3CastfTo128i(a) (_mm_castps_si128(a))
@@ -302,18 +314,19 @@ inline __m128 operator * (const __m128 A, const __m128 B)
#define b3CastiTo128f(a) (_mm_castsi128_ps(a))
#define b3CastdTo128f(a) (_mm_castpd_ps(a))
#define b3CastdTo128i(a) (_mm_castpd_si128(a))
-#define b3Assign128(r0,r1,r2,r3) _mm_setr_ps(r0,r1,r2,r3)
+#define b3Assign128(r0, r1, r2, r3) _mm_setr_ps(r0, r1, r2, r3)
-#else//_WIN32
+#else //_WIN32
#define b3CastfTo128i(a) ((__m128i)(a))
#define b3CastfTo128d(a) ((__m128d)(a))
-#define b3CastiTo128f(a) ((__m128) (a))
-#define b3CastdTo128f(a) ((__m128) (a))
+#define b3CastiTo128f(a) ((__m128)(a))
+#define b3CastdTo128f(a) ((__m128)(a))
#define b3CastdTo128i(a) ((__m128i)(a))
-#define b3Assign128(r0,r1,r2,r3) (__m128){r0,r1,r2,r3}
-#endif//_WIN32
-#endif //B3_USE_SSE_IN_API
+#define b3Assign128(r0, r1, r2, r3) \
+ (__m128) { r0, r1, r2, r3 }
+#endif //_WIN32
+#endif //B3_USE_SSE_IN_API
#ifdef B3_USE_NEON
#include <arm_neon.h>
@@ -321,142 +334,160 @@ inline __m128 operator * (const __m128 A, const __m128 B)
typedef float32x4_t b3SimdFloat4;
#define B3_INFINITY INFINITY
#define B3_NAN NAN
-#define b3Assign128(r0,r1,r2,r3) (float32x4_t){r0,r1,r2,r3}
+#define b3Assign128(r0, r1, r2, r3) \
+ (float32x4_t) { r0, r1, r2, r3 }
#endif
-
-
-
-
-#define B3_DECLARE_ALIGNED_ALLOCATOR() \
- B3_FORCE_INLINE void* operator new(size_t sizeInBytes) { return b3AlignedAlloc(sizeInBytes,16); } \
- B3_FORCE_INLINE void operator delete(void* ptr) { b3AlignedFree(ptr); } \
- B3_FORCE_INLINE void* operator new(size_t, void* ptr) { return ptr; } \
- B3_FORCE_INLINE void operator delete(void*, void*) { } \
- B3_FORCE_INLINE void* operator new[](size_t sizeInBytes) { return b3AlignedAlloc(sizeInBytes,16); } \
- B3_FORCE_INLINE void operator delete[](void* ptr) { b3AlignedFree(ptr); } \
- B3_FORCE_INLINE void* operator new[](size_t, void* ptr) { return ptr; } \
- B3_FORCE_INLINE void operator delete[](void*, void*) { } \
-
-
+#define B3_DECLARE_ALIGNED_ALLOCATOR() \
+ B3_FORCE_INLINE void *operator new(size_t sizeInBytes) { return b3AlignedAlloc(sizeInBytes, 16); } \
+ B3_FORCE_INLINE void operator delete(void *ptr) { b3AlignedFree(ptr); } \
+ B3_FORCE_INLINE void *operator new(size_t, void *ptr) { return ptr; } \
+ B3_FORCE_INLINE void operator delete(void *, void *) {} \
+ B3_FORCE_INLINE void *operator new[](size_t sizeInBytes) { return b3AlignedAlloc(sizeInBytes, 16); } \
+ B3_FORCE_INLINE void operator delete[](void *ptr) { b3AlignedFree(ptr); } \
+ B3_FORCE_INLINE void *operator new[](size_t, void *ptr) { return ptr; } \
+ B3_FORCE_INLINE void operator delete[](void *, void *) {}
#if defined(B3_USE_DOUBLE_PRECISION) || defined(B3_FORCE_DOUBLE_FUNCTIONS)
-
-B3_FORCE_INLINE b3Scalar b3Sqrt(b3Scalar x) { return sqrt(x); }
+
+B3_FORCE_INLINE b3Scalar b3Sqrt(b3Scalar x)
+{
+ return sqrt(x);
+}
B3_FORCE_INLINE b3Scalar b3Fabs(b3Scalar x) { return fabs(x); }
B3_FORCE_INLINE b3Scalar b3Cos(b3Scalar x) { return cos(x); }
B3_FORCE_INLINE b3Scalar b3Sin(b3Scalar x) { return sin(x); }
B3_FORCE_INLINE b3Scalar b3Tan(b3Scalar x) { return tan(x); }
-B3_FORCE_INLINE b3Scalar b3Acos(b3Scalar x) { if (x<b3Scalar(-1)) x=b3Scalar(-1); if (x>b3Scalar(1)) x=b3Scalar(1); return acos(x); }
-B3_FORCE_INLINE b3Scalar b3Asin(b3Scalar x) { if (x<b3Scalar(-1)) x=b3Scalar(-1); if (x>b3Scalar(1)) x=b3Scalar(1); return asin(x); }
+B3_FORCE_INLINE b3Scalar b3Acos(b3Scalar x)
+{
+ if (x < b3Scalar(-1)) x = b3Scalar(-1);
+ if (x > b3Scalar(1)) x = b3Scalar(1);
+ return acos(x);
+}
+B3_FORCE_INLINE b3Scalar b3Asin(b3Scalar x)
+{
+ if (x < b3Scalar(-1)) x = b3Scalar(-1);
+ if (x > b3Scalar(1)) x = b3Scalar(1);
+ return asin(x);
+}
B3_FORCE_INLINE b3Scalar b3Atan(b3Scalar x) { return atan(x); }
B3_FORCE_INLINE b3Scalar b3Atan2(b3Scalar x, b3Scalar y) { return atan2(x, y); }
B3_FORCE_INLINE b3Scalar b3Exp(b3Scalar x) { return exp(x); }
B3_FORCE_INLINE b3Scalar b3Log(b3Scalar x) { return log(x); }
-B3_FORCE_INLINE b3Scalar b3Pow(b3Scalar x,b3Scalar y) { return pow(x,y); }
-B3_FORCE_INLINE b3Scalar b3Fmod(b3Scalar x,b3Scalar y) { return fmod(x,y); }
+B3_FORCE_INLINE b3Scalar b3Pow(b3Scalar x, b3Scalar y) { return pow(x, y); }
+B3_FORCE_INLINE b3Scalar b3Fmod(b3Scalar x, b3Scalar y) { return fmod(x, y); }
#else
-
-B3_FORCE_INLINE b3Scalar b3Sqrt(b3Scalar y)
-{
+
+B3_FORCE_INLINE b3Scalar b3Sqrt(b3Scalar y)
+{
#ifdef USE_APPROXIMATION
- double x, z, tempf;
- unsigned long *tfptr = ((unsigned long *)&tempf) + 1;
+ double x, z, tempf;
+ unsigned long *tfptr = ((unsigned long *)&tempf) + 1;
tempf = y;
- *tfptr = (0xbfcdd90a - *tfptr)>>1; /* estimate of 1/sqrt(y) */
- x = tempf;
- z = y*b3Scalar(0.5);
- x = (b3Scalar(1.5)*x)-(x*x)*(x*z); /* iteration formula */
- x = (b3Scalar(1.5)*x)-(x*x)*(x*z);
- x = (b3Scalar(1.5)*x)-(x*x)*(x*z);
- x = (b3Scalar(1.5)*x)-(x*x)*(x*z);
- x = (b3Scalar(1.5)*x)-(x*x)*(x*z);
- return x*y;
+ *tfptr = (0xbfcdd90a - *tfptr) >> 1; /* estimate of 1/sqrt(y) */
+ x = tempf;
+ z = y * b3Scalar(0.5);
+ x = (b3Scalar(1.5) * x) - (x * x) * (x * z); /* iteration formula */
+ x = (b3Scalar(1.5) * x) - (x * x) * (x * z);
+ x = (b3Scalar(1.5) * x) - (x * x) * (x * z);
+ x = (b3Scalar(1.5) * x) - (x * x) * (x * z);
+ x = (b3Scalar(1.5) * x) - (x * x) * (x * z);
+ return x * y;
#else
- return sqrtf(y);
+ return sqrtf(y);
#endif
}
B3_FORCE_INLINE b3Scalar b3Fabs(b3Scalar x) { return fabsf(x); }
B3_FORCE_INLINE b3Scalar b3Cos(b3Scalar x) { return cosf(x); }
B3_FORCE_INLINE b3Scalar b3Sin(b3Scalar x) { return sinf(x); }
B3_FORCE_INLINE b3Scalar b3Tan(b3Scalar x) { return tanf(x); }
-B3_FORCE_INLINE b3Scalar b3Acos(b3Scalar x) {
- if (x<b3Scalar(-1))
- x=b3Scalar(-1);
- if (x>b3Scalar(1))
- x=b3Scalar(1);
- return acosf(x);
+B3_FORCE_INLINE b3Scalar b3Acos(b3Scalar x)
+{
+ if (x < b3Scalar(-1))
+ x = b3Scalar(-1);
+ if (x > b3Scalar(1))
+ x = b3Scalar(1);
+ return acosf(x);
}
-B3_FORCE_INLINE b3Scalar b3Asin(b3Scalar x) {
- if (x<b3Scalar(-1))
- x=b3Scalar(-1);
- if (x>b3Scalar(1))
- x=b3Scalar(1);
- return asinf(x);
+B3_FORCE_INLINE b3Scalar b3Asin(b3Scalar x)
+{
+ if (x < b3Scalar(-1))
+ x = b3Scalar(-1);
+ if (x > b3Scalar(1))
+ x = b3Scalar(1);
+ return asinf(x);
}
B3_FORCE_INLINE b3Scalar b3Atan(b3Scalar x) { return atanf(x); }
B3_FORCE_INLINE b3Scalar b3Atan2(b3Scalar x, b3Scalar y) { return atan2f(x, y); }
B3_FORCE_INLINE b3Scalar b3Exp(b3Scalar x) { return expf(x); }
B3_FORCE_INLINE b3Scalar b3Log(b3Scalar x) { return logf(x); }
-B3_FORCE_INLINE b3Scalar b3Pow(b3Scalar x,b3Scalar y) { return powf(x,y); }
-B3_FORCE_INLINE b3Scalar b3Fmod(b3Scalar x,b3Scalar y) { return fmodf(x,y); }
-
+B3_FORCE_INLINE b3Scalar b3Pow(b3Scalar x, b3Scalar y) { return powf(x, y); }
+B3_FORCE_INLINE b3Scalar b3Fmod(b3Scalar x, b3Scalar y) { return fmodf(x, y); }
+
#endif
-#define B3_2_PI b3Scalar(6.283185307179586232)
-#define B3_PI (B3_2_PI * b3Scalar(0.5))
-#define B3_HALF_PI (B3_2_PI * b3Scalar(0.25))
+#define B3_2_PI b3Scalar(6.283185307179586232)
+#define B3_PI (B3_2_PI * b3Scalar(0.5))
+#define B3_HALF_PI (B3_2_PI * b3Scalar(0.25))
#define B3_RADS_PER_DEG (B3_2_PI / b3Scalar(360.0))
-#define B3_DEGS_PER_RAD (b3Scalar(360.0) / B3_2_PI)
+#define B3_DEGS_PER_RAD (b3Scalar(360.0) / B3_2_PI)
#define B3_SQRT12 b3Scalar(0.7071067811865475244008443621048490)
-#define b3RecipSqrt(x) ((b3Scalar)(b3Scalar(1.0)/b3Sqrt(b3Scalar(x)))) /* reciprocal square root */
-
+#define b3RecipSqrt(x) ((b3Scalar)(b3Scalar(1.0) / b3Sqrt(b3Scalar(x)))) /* reciprocal square root */
#ifdef B3_USE_DOUBLE_PRECISION
-#define B3_EPSILON DBL_EPSILON
-#define B3_INFINITY DBL_MAX
+#define B3_EPSILON DBL_EPSILON
+#define B3_INFINITY DBL_MAX
#else
-#define B3_EPSILON FLT_EPSILON
-#define B3_INFINITY FLT_MAX
+#define B3_EPSILON FLT_EPSILON
+#define B3_INFINITY FLT_MAX
#endif
-B3_FORCE_INLINE b3Scalar b3Atan2Fast(b3Scalar y, b3Scalar x)
+B3_FORCE_INLINE b3Scalar b3Atan2Fast(b3Scalar y, b3Scalar x)
{
b3Scalar coeff_1 = B3_PI / 4.0f;
b3Scalar coeff_2 = 3.0f * coeff_1;
b3Scalar abs_y = b3Fabs(y);
b3Scalar angle;
- if (x >= 0.0f) {
+ if (x >= 0.0f)
+ {
b3Scalar r = (x - abs_y) / (x + abs_y);
angle = coeff_1 - coeff_1 * r;
- } else {
+ }
+ else
+ {
b3Scalar r = (x + abs_y) / (abs_y - x);
angle = coeff_2 - coeff_1 * r;
}
return (y < 0.0f) ? -angle : angle;
}
-B3_FORCE_INLINE bool b3FuzzyZero(b3Scalar x) { return b3Fabs(x) < B3_EPSILON; }
+B3_FORCE_INLINE bool b3FuzzyZero(b3Scalar x) { return b3Fabs(x) < B3_EPSILON; }
-B3_FORCE_INLINE bool b3Equal(b3Scalar a, b3Scalar eps) {
+B3_FORCE_INLINE bool b3Equal(b3Scalar a, b3Scalar eps)
+{
return (((a) <= eps) && !((a) < -eps));
}
-B3_FORCE_INLINE bool b3GreaterEqual (b3Scalar a, b3Scalar eps) {
+B3_FORCE_INLINE bool b3GreaterEqual(b3Scalar a, b3Scalar eps)
+{
return (!((a) <= eps));
}
-
-B3_FORCE_INLINE int b3IsNegative(b3Scalar x) {
- return x < b3Scalar(0.0) ? 1 : 0;
+B3_FORCE_INLINE int b3IsNegative(b3Scalar x)
+{
+ return x < b3Scalar(0.0) ? 1 : 0;
}
B3_FORCE_INLINE b3Scalar b3Radians(b3Scalar x) { return x * B3_RADS_PER_DEG; }
B3_FORCE_INLINE b3Scalar b3Degrees(b3Scalar x) { return x * B3_DEGS_PER_RAD; }
-#define B3_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name
+#define B3_DECLARE_HANDLE(name) \
+ typedef struct name##__ \
+ { \
+ int unused; \
+ } * name
#ifndef b3Fsel
B3_FORCE_INLINE b3Scalar b3Fsel(b3Scalar a, b3Scalar b, b3Scalar c)
@@ -464,60 +495,57 @@ B3_FORCE_INLINE b3Scalar b3Fsel(b3Scalar a, b3Scalar b, b3Scalar c)
return a >= 0 ? b : c;
}
#endif
-#define b3Fsels(a,b,c) (b3Scalar)b3Fsel(a,b,c)
-
+#define b3Fsels(a, b, c) (b3Scalar) b3Fsel(a, b, c)
B3_FORCE_INLINE bool b3MachineIsLittleEndian()
{
- long int i = 1;
- const char *p = (const char *) &i;
- if (p[0] == 1) // Lowest address contains the least significant byte
- return true;
- else
- return false;
+ long int i = 1;
+ const char *p = (const char *)&i;
+ if (p[0] == 1) // Lowest address contains the least significant byte
+ return true;
+ else
+ return false;
}
-
-
///b3Select avoids branches, which makes performance much better for consoles like Playstation 3 and XBox 360
///Thanks Phil Knight. See also http://www.cellperformance.com/articles/2006/04/more_techniques_for_eliminatin_1.html
-B3_FORCE_INLINE unsigned b3Select(unsigned condition, unsigned valueIfConditionNonZero, unsigned valueIfConditionZero)
+B3_FORCE_INLINE unsigned b3Select(unsigned condition, unsigned valueIfConditionNonZero, unsigned valueIfConditionZero)
{
- // Set testNz to 0xFFFFFFFF if condition is nonzero, 0x00000000 if condition is zero
- // Rely on positive value or'ed with its negative having sign bit on
- // and zero value or'ed with its negative (which is still zero) having sign bit off
- // Use arithmetic shift right, shifting the sign bit through all 32 bits
- unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31);
- unsigned testEqz = ~testNz;
- return ((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz));
+ // Set testNz to 0xFFFFFFFF if condition is nonzero, 0x00000000 if condition is zero
+ // Rely on positive value or'ed with its negative having sign bit on
+ // and zero value or'ed with its negative (which is still zero) having sign bit off
+ // Use arithmetic shift right, shifting the sign bit through all 32 bits
+ unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31);
+ unsigned testEqz = ~testNz;
+ return ((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz));
}
B3_FORCE_INLINE int b3Select(unsigned condition, int valueIfConditionNonZero, int valueIfConditionZero)
{
- unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31);
- unsigned testEqz = ~testNz;
- return static_cast<int>((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz));
+ unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31);
+ unsigned testEqz = ~testNz;
+ return static_cast<int>((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz));
}
B3_FORCE_INLINE float b3Select(unsigned condition, float valueIfConditionNonZero, float valueIfConditionZero)
{
#ifdef B3_HAVE_NATIVE_FSEL
- return (float)b3Fsel((b3Scalar)condition - b3Scalar(1.0f), valueIfConditionNonZero, valueIfConditionZero);
+ return (float)b3Fsel((b3Scalar)condition - b3Scalar(1.0f), valueIfConditionNonZero, valueIfConditionZero);
#else
- return (condition != 0) ? valueIfConditionNonZero : valueIfConditionZero;
+ return (condition != 0) ? valueIfConditionNonZero : valueIfConditionZero;
#endif
}
-template<typename T> B3_FORCE_INLINE void b3Swap(T& a, T& b)
+template <typename T>
+B3_FORCE_INLINE void b3Swap(T &a, T &b)
{
T tmp = a;
a = b;
b = tmp;
}
-
//PCK: endian swapping functions
B3_FORCE_INLINE unsigned b3SwapEndian(unsigned val)
{
- return (((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24));
+ return (((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24));
}
B3_FORCE_INLINE unsigned short b3SwapEndian(unsigned short val)
@@ -532,87 +560,85 @@ B3_FORCE_INLINE unsigned b3SwapEndian(int val)
B3_FORCE_INLINE unsigned short b3SwapEndian(short val)
{
- return b3SwapEndian((unsigned short) val);
+ return b3SwapEndian((unsigned short)val);
}
///b3SwapFloat uses using char pointers to swap the endianness
////b3SwapFloat/b3SwapDouble will NOT return a float, because the machine might 'correct' invalid floating point values
-///Not all values of sign/exponent/mantissa are valid floating point numbers according to IEEE 754.
-///When a floating point unit is faced with an invalid value, it may actually change the value, or worse, throw an exception.
-///In most systems, running user mode code, you wouldn't get an exception, but instead the hardware/os/runtime will 'fix' the number for you.
+///Not all values of sign/exponent/mantissa are valid floating point numbers according to IEEE 754.
+///When a floating point unit is faced with an invalid value, it may actually change the value, or worse, throw an exception.
+///In most systems, running user mode code, you wouldn't get an exception, but instead the hardware/os/runtime will 'fix' the number for you.
///so instead of returning a float/double, we return integer/long long integer
-B3_FORCE_INLINE unsigned int b3SwapEndianFloat(float d)
+B3_FORCE_INLINE unsigned int b3SwapEndianFloat(float d)
{
- unsigned int a = 0;
- unsigned char *dst = (unsigned char *)&a;
- unsigned char *src = (unsigned char *)&d;
-
- dst[0] = src[3];
- dst[1] = src[2];
- dst[2] = src[1];
- dst[3] = src[0];
- return a;
+ unsigned int a = 0;
+ unsigned char *dst = (unsigned char *)&a;
+ unsigned char *src = (unsigned char *)&d;
+
+ dst[0] = src[3];
+ dst[1] = src[2];
+ dst[2] = src[1];
+ dst[3] = src[0];
+ return a;
}
// unswap using char pointers
-B3_FORCE_INLINE float b3UnswapEndianFloat(unsigned int a)
+B3_FORCE_INLINE float b3UnswapEndianFloat(unsigned int a)
{
- float d = 0.0f;
- unsigned char *src = (unsigned char *)&a;
- unsigned char *dst = (unsigned char *)&d;
+ float d = 0.0f;
+ unsigned char *src = (unsigned char *)&a;
+ unsigned char *dst = (unsigned char *)&d;
- dst[0] = src[3];
- dst[1] = src[2];
- dst[2] = src[1];
- dst[3] = src[0];
+ dst[0] = src[3];
+ dst[1] = src[2];
+ dst[2] = src[1];
+ dst[3] = src[0];
- return d;
+ return d;
}
-
// swap using char pointers
-B3_FORCE_INLINE void b3SwapEndianDouble(double d, unsigned char* dst)
+B3_FORCE_INLINE void b3SwapEndianDouble(double d, unsigned char *dst)
{
- unsigned char *src = (unsigned char *)&d;
-
- dst[0] = src[7];
- dst[1] = src[6];
- dst[2] = src[5];
- dst[3] = src[4];
- dst[4] = src[3];
- dst[5] = src[2];
- dst[6] = src[1];
- dst[7] = src[0];
-
+ unsigned char *src = (unsigned char *)&d;
+
+ dst[0] = src[7];
+ dst[1] = src[6];
+ dst[2] = src[5];
+ dst[3] = src[4];
+ dst[4] = src[3];
+ dst[5] = src[2];
+ dst[6] = src[1];
+ dst[7] = src[0];
}
// unswap using char pointers
-B3_FORCE_INLINE double b3UnswapEndianDouble(const unsigned char *src)
+B3_FORCE_INLINE double b3UnswapEndianDouble(const unsigned char *src)
{
- double d = 0.0;
- unsigned char *dst = (unsigned char *)&d;
-
- dst[0] = src[7];
- dst[1] = src[6];
- dst[2] = src[5];
- dst[3] = src[4];
- dst[4] = src[3];
- dst[5] = src[2];
- dst[6] = src[1];
- dst[7] = src[0];
+ double d = 0.0;
+ unsigned char *dst = (unsigned char *)&d;
+
+ dst[0] = src[7];
+ dst[1] = src[6];
+ dst[2] = src[5];
+ dst[3] = src[4];
+ dst[4] = src[3];
+ dst[5] = src[2];
+ dst[6] = src[1];
+ dst[7] = src[0];
return d;
}
// returns normalized value in range [-B3_PI, B3_PI]
-B3_FORCE_INLINE b3Scalar b3NormalizeAngle(b3Scalar angleInRadians)
+B3_FORCE_INLINE b3Scalar b3NormalizeAngle(b3Scalar angleInRadians)
{
angleInRadians = b3Fmod(angleInRadians, B3_2_PI);
- if(angleInRadians < -B3_PI)
+ if (angleInRadians < -B3_PI)
{
return angleInRadians + B3_2_PI;
}
- else if(angleInRadians > B3_PI)
+ else if (angleInRadians > B3_PI)
{
return angleInRadians - B3_2_PI;
}
@@ -626,38 +652,34 @@ B3_FORCE_INLINE b3Scalar b3NormalizeAngle(b3Scalar angleInRadians)
struct b3TypedObject
{
b3TypedObject(int objectType)
- :m_objectType(objectType)
+ : m_objectType(objectType)
{
}
- int m_objectType;
+ int m_objectType;
inline int getObjectType() const
{
return m_objectType;
}
};
-
-
///align a pointer to the provided alignment, upwards
-template <typename T>T* b3AlignPointer(T* unalignedPtr, size_t alignment)
+template <typename T>
+T *b3AlignPointer(T *unalignedPtr, size_t alignment)
{
-
struct b3ConvertPointerSizeT
{
- union
- {
- T* ptr;
- size_t integer;
+ union {
+ T *ptr;
+ size_t integer;
};
};
- b3ConvertPointerSizeT converter;
-
-
+ b3ConvertPointerSizeT converter;
+
const size_t bit_mask = ~(alignment - 1);
- converter.ptr = unalignedPtr;
- converter.integer += alignment-1;
+ converter.ptr = unalignedPtr;
+ converter.integer += alignment - 1;
converter.integer &= bit_mask;
return converter.ptr;
}
-#endif //B3_SCALAR_H
+#endif //B3_SCALAR_H
diff --git a/thirdparty/bullet/Bullet3Common/b3StackAlloc.h b/thirdparty/bullet/Bullet3Common/b3StackAlloc.h
index de7de056b5..4972236ac7 100644
--- a/thirdparty/bullet/Bullet3Common/b3StackAlloc.h
+++ b/thirdparty/bullet/Bullet3Common/b3StackAlloc.h
@@ -20,97 +20,99 @@ Nov.2006
#ifndef B3_STACK_ALLOC
#define B3_STACK_ALLOC
-#include "b3Scalar.h" //for b3Assert
+#include "b3Scalar.h" //for b3Assert
#include "b3AlignedAllocator.h"
///The b3Block class is an internal structure for the b3StackAlloc memory allocator.
struct b3Block
{
- b3Block* previous;
- unsigned char* address;
+ b3Block* previous;
+ unsigned char* address;
};
///The StackAlloc class provides some fast stack-based memory allocator (LIFO last-in first-out)
class b3StackAlloc
{
public:
+ b3StackAlloc(unsigned int size)
+ {
+ ctor();
+ create(size);
+ }
+ ~b3StackAlloc() { destroy(); }
- b3StackAlloc(unsigned int size) { ctor();create(size); }
- ~b3StackAlloc() { destroy(); }
-
- inline void create(unsigned int size)
+ inline void create(unsigned int size)
{
destroy();
- data = (unsigned char*) b3AlignedAlloc(size,16);
- totalsize = size;
+ data = (unsigned char*)b3AlignedAlloc(size, 16);
+ totalsize = size;
}
- inline void destroy()
+ inline void destroy()
{
- b3Assert(usedsize==0);
+ b3Assert(usedsize == 0);
//Raise(L"StackAlloc is still in use");
- if(usedsize==0)
+ if (usedsize == 0)
{
- if(!ischild && data)
+ if (!ischild && data)
b3AlignedFree(data);
- data = 0;
- usedsize = 0;
+ data = 0;
+ usedsize = 0;
}
-
}
- int getAvailableMemory() const
+ int getAvailableMemory() const
{
return static_cast<int>(totalsize - usedsize);
}
- unsigned char* allocate(unsigned int size)
+ unsigned char* allocate(unsigned int size)
{
- const unsigned int nus(usedsize+size);
- if(nus<totalsize)
+ const unsigned int nus(usedsize + size);
+ if (nus < totalsize)
{
- usedsize=nus;
- return(data+(usedsize-size));
+ usedsize = nus;
+ return (data + (usedsize - size));
}
b3Assert(0);
//&& (L"Not enough memory"));
-
- return(0);
+
+ return (0);
}
- B3_FORCE_INLINE b3Block* beginBlock()
+ B3_FORCE_INLINE b3Block* beginBlock()
{
- b3Block* pb = (b3Block*)allocate(sizeof(b3Block));
- pb->previous = current;
- pb->address = data+usedsize;
- current = pb;
- return(pb);
+ b3Block* pb = (b3Block*)allocate(sizeof(b3Block));
+ pb->previous = current;
+ pb->address = data + usedsize;
+ current = pb;
+ return (pb);
}
- B3_FORCE_INLINE void endBlock(b3Block* block)
+ B3_FORCE_INLINE void endBlock(b3Block* block)
{
- b3Assert(block==current);
+ b3Assert(block == current);
//Raise(L"Unmatched blocks");
- if(block==current)
+ if (block == current)
{
- current = block->previous;
- usedsize = (unsigned int)((block->address-data)-sizeof(b3Block));
+ current = block->previous;
+ usedsize = (unsigned int)((block->address - data) - sizeof(b3Block));
}
}
private:
- void ctor()
+ void ctor()
{
- data = 0;
- totalsize = 0;
- usedsize = 0;
- current = 0;
- ischild = false;
+ data = 0;
+ totalsize = 0;
+ usedsize = 0;
+ current = 0;
+ ischild = false;
}
- unsigned char* data;
- unsigned int totalsize;
- unsigned int usedsize;
- b3Block* current;
- bool ischild;
+ unsigned char* data;
+ unsigned int totalsize;
+ unsigned int usedsize;
+ b3Block* current;
+ bool ischild;
};
-#endif //B3_STACK_ALLOC
+#endif //B3_STACK_ALLOC
diff --git a/thirdparty/bullet/Bullet3Common/b3Transform.h b/thirdparty/bullet/Bullet3Common/b3Transform.h
index fa480759be..149da9d148 100644
--- a/thirdparty/bullet/Bullet3Common/b3Transform.h
+++ b/thirdparty/bullet/Bullet3Common/b3Transform.h
@@ -12,11 +12,9 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#ifndef B3_TRANSFORM_H
#define B3_TRANSFORM_H
-
#include "b3Matrix3x3.h"
#ifdef B3_USE_DOUBLE_PRECISION
@@ -25,46 +23,45 @@ subject to the following restrictions:
#define b3TransformData b3TransformFloatData
#endif
-
-
-
/**@brief The b3Transform class supports rigid transforms with only translation and rotation and no scaling/shear.
*It can be used in combination with b3Vector3, b3Quaternion and b3Matrix3x3 linear algebra classes. */
-B3_ATTRIBUTE_ALIGNED16(class) b3Transform {
-
- ///Storage for the rotation
+B3_ATTRIBUTE_ALIGNED16(class)
+b3Transform
+{
+ ///Storage for the rotation
b3Matrix3x3 m_basis;
- ///Storage for the translation
- b3Vector3 m_origin;
+ ///Storage for the translation
+ b3Vector3 m_origin;
public:
-
- /**@brief No initialization constructor */
+ /**@brief No initialization constructor */
b3Transform() {}
- /**@brief Constructor from b3Quaternion (optional b3Vector3 )
+ /**@brief Constructor from b3Quaternion (optional b3Vector3 )
* @param q Rotation from quaternion
* @param c Translation from Vector (default 0,0,0) */
- explicit B3_FORCE_INLINE b3Transform(const b3Quaternion& q,
- const b3Vector3& c = b3MakeVector3(b3Scalar(0), b3Scalar(0), b3Scalar(0)))
+ explicit B3_FORCE_INLINE b3Transform(const b3Quaternion& q,
+ const b3Vector3& c = b3MakeVector3(b3Scalar(0), b3Scalar(0), b3Scalar(0)))
: m_basis(q),
- m_origin(c)
- {}
+ m_origin(c)
+ {
+ }
- /**@brief Constructor from b3Matrix3x3 (optional b3Vector3)
+ /**@brief Constructor from b3Matrix3x3 (optional b3Vector3)
* @param b Rotation from Matrix
* @param c Translation from Vector default (0,0,0)*/
- explicit B3_FORCE_INLINE b3Transform(const b3Matrix3x3& b,
- const b3Vector3& c = b3MakeVector3(b3Scalar(0), b3Scalar(0), b3Scalar(0)))
+ explicit B3_FORCE_INLINE b3Transform(const b3Matrix3x3& b,
+ const b3Vector3& c = b3MakeVector3(b3Scalar(0), b3Scalar(0), b3Scalar(0)))
: m_basis(b),
- m_origin(c)
- {}
- /**@brief Copy constructor */
- B3_FORCE_INLINE b3Transform (const b3Transform& other)
+ m_origin(c)
+ {
+ }
+ /**@brief Copy constructor */
+ B3_FORCE_INLINE b3Transform(const b3Transform& other)
: m_basis(other.m_basis),
- m_origin(other.m_origin)
+ m_origin(other.m_origin)
{
}
- /**@brief Assignment Operator */
+ /**@brief Assignment Operator */
B3_FORCE_INLINE b3Transform& operator=(const b3Transform& other)
{
m_basis = other.m_basis;
@@ -72,70 +69,70 @@ public:
return *this;
}
-
- /**@brief Set the current transform as the value of the product of two transforms
+ /**@brief Set the current transform as the value of the product of two transforms
* @param t1 Transform 1
* @param t2 Transform 2
* This = Transform1 * Transform2 */
- B3_FORCE_INLINE void mult(const b3Transform& t1, const b3Transform& t2) {
- m_basis = t1.m_basis * t2.m_basis;
- m_origin = t1(t2.m_origin);
- }
+ B3_FORCE_INLINE void mult(const b3Transform& t1, const b3Transform& t2)
+ {
+ m_basis = t1.m_basis * t2.m_basis;
+ m_origin = t1(t2.m_origin);
+ }
-/* void multInverseLeft(const b3Transform& t1, const b3Transform& t2) {
+ /* void multInverseLeft(const b3Transform& t1, const b3Transform& t2) {
b3Vector3 v = t2.m_origin - t1.m_origin;
m_basis = b3MultTransposeLeft(t1.m_basis, t2.m_basis);
m_origin = v * t1.m_basis;
}
*/
-/**@brief Return the transform of the vector */
+ /**@brief Return the transform of the vector */
B3_FORCE_INLINE b3Vector3 operator()(const b3Vector3& x) const
{
- return x.dot3(m_basis[0], m_basis[1], m_basis[2]) + m_origin;
+ return x.dot3(m_basis[0], m_basis[1], m_basis[2]) + m_origin;
}
- /**@brief Return the transform of the vector */
+ /**@brief Return the transform of the vector */
B3_FORCE_INLINE b3Vector3 operator*(const b3Vector3& x) const
{
return (*this)(x);
}
- /**@brief Return the transform of the b3Quaternion */
+ /**@brief Return the transform of the b3Quaternion */
B3_FORCE_INLINE b3Quaternion operator*(const b3Quaternion& q) const
{
return getRotation() * q;
}
- /**@brief Return the basis matrix for the rotation */
- B3_FORCE_INLINE b3Matrix3x3& getBasis() { return m_basis; }
- /**@brief Return the basis matrix for the rotation */
- B3_FORCE_INLINE const b3Matrix3x3& getBasis() const { return m_basis; }
+ /**@brief Return the basis matrix for the rotation */
+ B3_FORCE_INLINE b3Matrix3x3& getBasis() { return m_basis; }
+ /**@brief Return the basis matrix for the rotation */
+ B3_FORCE_INLINE const b3Matrix3x3& getBasis() const { return m_basis; }
- /**@brief Return the origin vector translation */
- B3_FORCE_INLINE b3Vector3& getOrigin() { return m_origin; }
- /**@brief Return the origin vector translation */
- B3_FORCE_INLINE const b3Vector3& getOrigin() const { return m_origin; }
+ /**@brief Return the origin vector translation */
+ B3_FORCE_INLINE b3Vector3& getOrigin() { return m_origin; }
+ /**@brief Return the origin vector translation */
+ B3_FORCE_INLINE const b3Vector3& getOrigin() const { return m_origin; }
- /**@brief Return a quaternion representing the rotation */
- b3Quaternion getRotation() const {
+ /**@brief Return a quaternion representing the rotation */
+ b3Quaternion getRotation() const
+ {
b3Quaternion q;
m_basis.getRotation(q);
return q;
}
-
-
- /**@brief Set from an array
+
+ /**@brief Set from an array
* @param m A pointer to a 15 element array (12 rotation(row major padded on the right by 1), and 3 translation */
- void setFromOpenGLMatrix(const b3Scalar *m)
+ void setFromOpenGLMatrix(const b3Scalar* m)
{
m_basis.setFromOpenGLSubMatrix(m);
- m_origin.setValue(m[12],m[13],m[14]);
+ m_origin.setValue(m[12], m[13], m[14]);
}
- /**@brief Fill an array representation
+ /**@brief Fill an array representation
* @param m A pointer to a 15 element array (12 rotation(row major padded on the right by 1), and 3 translation */
- void getOpenGLMatrix(b3Scalar *m) const
+ void getOpenGLMatrix(b3Scalar * m) const
{
m_basis.getOpenGLSubMatrix(m);
m[12] = m_origin.getX();
@@ -144,80 +141,76 @@ public:
m[15] = b3Scalar(1.0);
}
- /**@brief Set the translational element
+ /**@brief Set the translational element
* @param origin The vector to set the translation to */
- B3_FORCE_INLINE void setOrigin(const b3Vector3& origin)
- {
+ B3_FORCE_INLINE void setOrigin(const b3Vector3& origin)
+ {
m_origin = origin;
}
B3_FORCE_INLINE b3Vector3 invXform(const b3Vector3& inVec) const;
-
- /**@brief Set the rotational element by b3Matrix3x3 */
+ /**@brief Set the rotational element by b3Matrix3x3 */
B3_FORCE_INLINE void setBasis(const b3Matrix3x3& basis)
- {
+ {
m_basis = basis;
}
- /**@brief Set the rotational element by b3Quaternion */
+ /**@brief Set the rotational element by b3Quaternion */
B3_FORCE_INLINE void setRotation(const b3Quaternion& q)
{
m_basis.setRotation(q);
}
-
- /**@brief Set this transformation to the identity */
+ /**@brief Set this transformation to the identity */
void setIdentity()
{
m_basis.setIdentity();
m_origin.setValue(b3Scalar(0.0), b3Scalar(0.0), b3Scalar(0.0));
}
- /**@brief Multiply this Transform by another(this = this * another)
+ /**@brief Multiply this Transform by another(this = this * another)
* @param t The other transform */
- b3Transform& operator*=(const b3Transform& t)
+ b3Transform& operator*=(const b3Transform& t)
{
m_origin += m_basis * t.m_origin;
m_basis *= t.m_basis;
return *this;
}
- /**@brief Return the inverse of this transform */
+ /**@brief Return the inverse of this transform */
b3Transform inverse() const
- {
+ {
b3Matrix3x3 inv = m_basis.transpose();
return b3Transform(inv, inv * -m_origin);
}
- /**@brief Return the inverse of this transform times the other transform
+ /**@brief Return the inverse of this transform times the other transform
* @param t The other transform
* return this.inverse() * the other */
- b3Transform inverseTimes(const b3Transform& t) const;
+ b3Transform inverseTimes(const b3Transform& t) const;
- /**@brief Return the product of this transform and the other */
+ /**@brief Return the product of this transform and the other */
b3Transform operator*(const b3Transform& t) const;
- /**@brief Return an identity transform */
- static const b3Transform& getIdentity()
+ /**@brief Return an identity transform */
+ static const b3Transform& getIdentity()
{
static const b3Transform identityTransform(b3Matrix3x3::getIdentity());
return identityTransform;
}
- void serialize(struct b3TransformData& dataOut) const;
-
- void serializeFloat(struct b3TransformFloatData& dataOut) const;
+ void serialize(struct b3TransformData & dataOut) const;
- void deSerialize(const struct b3TransformData& dataIn);
+ void serializeFloat(struct b3TransformFloatData & dataOut) const;
- void deSerializeDouble(const struct b3TransformDoubleData& dataIn);
+ void deSerialize(const struct b3TransformData& dataIn);
- void deSerializeFloat(const struct b3TransformFloatData& dataIn);
+ void deSerializeDouble(const struct b3TransformDoubleData& dataIn);
+ void deSerializeFloat(const struct b3TransformFloatData& dataIn);
};
-
B3_FORCE_INLINE b3Vector3
b3Transform::invXform(const b3Vector3& inVec) const
{
@@ -225,80 +218,69 @@ b3Transform::invXform(const b3Vector3& inVec) const
return (m_basis.transpose() * v);
}
-B3_FORCE_INLINE b3Transform
-b3Transform::inverseTimes(const b3Transform& t) const
+B3_FORCE_INLINE b3Transform
+b3Transform::inverseTimes(const b3Transform& t) const
{
b3Vector3 v = t.getOrigin() - m_origin;
- return b3Transform(m_basis.transposeTimes(t.m_basis),
- v * m_basis);
+ return b3Transform(m_basis.transposeTimes(t.m_basis),
+ v * m_basis);
}
-B3_FORCE_INLINE b3Transform
-b3Transform::operator*(const b3Transform& t) const
+B3_FORCE_INLINE b3Transform
+ b3Transform::operator*(const b3Transform& t) const
{
- return b3Transform(m_basis * t.m_basis,
- (*this)(t.m_origin));
+ return b3Transform(m_basis * t.m_basis,
+ (*this)(t.m_origin));
}
/**@brief Test if two transforms have all elements equal */
B3_FORCE_INLINE bool operator==(const b3Transform& t1, const b3Transform& t2)
{
- return ( t1.getBasis() == t2.getBasis() &&
- t1.getOrigin() == t2.getOrigin() );
+ return (t1.getBasis() == t2.getBasis() &&
+ t1.getOrigin() == t2.getOrigin());
}
-
///for serialization
-struct b3TransformFloatData
+struct b3TransformFloatData
{
- b3Matrix3x3FloatData m_basis;
- b3Vector3FloatData m_origin;
+ b3Matrix3x3FloatData m_basis;
+ b3Vector3FloatData m_origin;
};
-struct b3TransformDoubleData
+struct b3TransformDoubleData
{
- b3Matrix3x3DoubleData m_basis;
- b3Vector3DoubleData m_origin;
+ b3Matrix3x3DoubleData m_basis;
+ b3Vector3DoubleData m_origin;
};
-
-
-B3_FORCE_INLINE void b3Transform::serialize(b3TransformData& dataOut) const
+B3_FORCE_INLINE void b3Transform::serialize(b3TransformData& dataOut) const
{
m_basis.serialize(dataOut.m_basis);
m_origin.serialize(dataOut.m_origin);
}
-B3_FORCE_INLINE void b3Transform::serializeFloat(b3TransformFloatData& dataOut) const
+B3_FORCE_INLINE void b3Transform::serializeFloat(b3TransformFloatData& dataOut) const
{
m_basis.serializeFloat(dataOut.m_basis);
m_origin.serializeFloat(dataOut.m_origin);
}
-
-B3_FORCE_INLINE void b3Transform::deSerialize(const b3TransformData& dataIn)
+B3_FORCE_INLINE void b3Transform::deSerialize(const b3TransformData& dataIn)
{
m_basis.deSerialize(dataIn.m_basis);
m_origin.deSerialize(dataIn.m_origin);
}
-B3_FORCE_INLINE void b3Transform::deSerializeFloat(const b3TransformFloatData& dataIn)
+B3_FORCE_INLINE void b3Transform::deSerializeFloat(const b3TransformFloatData& dataIn)
{
m_basis.deSerializeFloat(dataIn.m_basis);
m_origin.deSerializeFloat(dataIn.m_origin);
}
-B3_FORCE_INLINE void b3Transform::deSerializeDouble(const b3TransformDoubleData& dataIn)
+B3_FORCE_INLINE void b3Transform::deSerializeDouble(const b3TransformDoubleData& dataIn)
{
m_basis.deSerializeDouble(dataIn.m_basis);
m_origin.deSerializeDouble(dataIn.m_origin);
}
-
-#endif //B3_TRANSFORM_H
-
-
-
-
-
-
+#endif //B3_TRANSFORM_H
diff --git a/thirdparty/bullet/Bullet3Common/b3TransformUtil.h b/thirdparty/bullet/Bullet3Common/b3TransformUtil.h
index 6ce580c132..1850a9be5f 100644
--- a/thirdparty/bullet/Bullet3Common/b3TransformUtil.h
+++ b/thirdparty/bullet/Bullet3Common/b3TransformUtil.h
@@ -12,204 +12,189 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#ifndef B3_TRANSFORM_UTIL_H
#define B3_TRANSFORM_UTIL_H
#include "b3Transform.h"
-#define B3_ANGULAR_MOTION_THRESHOLD b3Scalar(0.5)*B3_HALF_PI
-
-
-
+#define B3_ANGULAR_MOTION_THRESHOLD b3Scalar(0.5) * B3_HALF_PI
-B3_FORCE_INLINE b3Vector3 b3AabbSupport(const b3Vector3& halfExtents,const b3Vector3& supportDir)
+B3_FORCE_INLINE b3Vector3 b3AabbSupport(const b3Vector3& halfExtents, const b3Vector3& supportDir)
{
return b3MakeVector3(supportDir.getX() < b3Scalar(0.0) ? -halfExtents.getX() : halfExtents.getX(),
- supportDir.getY() < b3Scalar(0.0) ? -halfExtents.getY() : halfExtents.getY(),
- supportDir.getZ() < b3Scalar(0.0) ? -halfExtents.getZ() : halfExtents.getZ());
+ supportDir.getY() < b3Scalar(0.0) ? -halfExtents.getY() : halfExtents.getY(),
+ supportDir.getZ() < b3Scalar(0.0) ? -halfExtents.getZ() : halfExtents.getZ());
}
-
-
-
-
-
/// Utils related to temporal transforms
class b3TransformUtil
{
-
public:
-
- static void integrateTransform(const b3Transform& curTrans,const b3Vector3& linvel,const b3Vector3& angvel,b3Scalar timeStep,b3Transform& predictedTransform)
+ static void integrateTransform(const b3Transform& curTrans, const b3Vector3& linvel, const b3Vector3& angvel, b3Scalar timeStep, b3Transform& predictedTransform)
{
predictedTransform.setOrigin(curTrans.getOrigin() + linvel * timeStep);
-// #define QUATERNION_DERIVATIVE
- #ifdef QUATERNION_DERIVATIVE
+ // #define QUATERNION_DERIVATIVE
+#ifdef QUATERNION_DERIVATIVE
b3Quaternion predictedOrn = curTrans.getRotation();
predictedOrn += (angvel * predictedOrn) * (timeStep * b3Scalar(0.5));
predictedOrn.normalize();
- #else
+#else
//Exponential map
//google for "Practical Parameterization of Rotations Using the Exponential Map", F. Sebastian Grassia
b3Vector3 axis;
- b3Scalar fAngle = angvel.length();
+ b3Scalar fAngle = angvel.length();
//limit the angular motion
- if (fAngle*timeStep > B3_ANGULAR_MOTION_THRESHOLD)
+ if (fAngle * timeStep > B3_ANGULAR_MOTION_THRESHOLD)
{
fAngle = B3_ANGULAR_MOTION_THRESHOLD / timeStep;
}
- if ( fAngle < b3Scalar(0.001) )
+ if (fAngle < b3Scalar(0.001))
{
// use Taylor's expansions of sync function
- axis = angvel*( b3Scalar(0.5)*timeStep-(timeStep*timeStep*timeStep)*(b3Scalar(0.020833333333))*fAngle*fAngle );
+ axis = angvel * (b3Scalar(0.5) * timeStep - (timeStep * timeStep * timeStep) * (b3Scalar(0.020833333333)) * fAngle * fAngle);
}
else
{
// sync(fAngle) = sin(c*fAngle)/t
- axis = angvel*( b3Sin(b3Scalar(0.5)*fAngle*timeStep)/fAngle );
+ axis = angvel * (b3Sin(b3Scalar(0.5) * fAngle * timeStep) / fAngle);
}
- b3Quaternion dorn (axis.getX(),axis.getY(),axis.getZ(),b3Cos( fAngle*timeStep*b3Scalar(0.5) ));
+ b3Quaternion dorn(axis.getX(), axis.getY(), axis.getZ(), b3Cos(fAngle * timeStep * b3Scalar(0.5)));
b3Quaternion orn0 = curTrans.getRotation();
b3Quaternion predictedOrn = dorn * orn0;
predictedOrn.normalize();
- #endif
+#endif
predictedTransform.setRotation(predictedOrn);
}
- static void calculateVelocityQuaternion(const b3Vector3& pos0,const b3Vector3& pos1,const b3Quaternion& orn0,const b3Quaternion& orn1,b3Scalar timeStep,b3Vector3& linVel,b3Vector3& angVel)
+ static void calculateVelocityQuaternion(const b3Vector3& pos0, const b3Vector3& pos1, const b3Quaternion& orn0, const b3Quaternion& orn1, b3Scalar timeStep, b3Vector3& linVel, b3Vector3& angVel)
{
linVel = (pos1 - pos0) / timeStep;
b3Vector3 axis;
- b3Scalar angle;
+ b3Scalar angle;
if (orn0 != orn1)
{
- calculateDiffAxisAngleQuaternion(orn0,orn1,axis,angle);
+ calculateDiffAxisAngleQuaternion(orn0, orn1, axis, angle);
angVel = axis * angle / timeStep;
- } else
+ }
+ else
{
- angVel.setValue(0,0,0);
+ angVel.setValue(0, 0, 0);
}
}
- static void calculateDiffAxisAngleQuaternion(const b3Quaternion& orn0,const b3Quaternion& orn1a,b3Vector3& axis,b3Scalar& angle)
+ static void calculateDiffAxisAngleQuaternion(const b3Quaternion& orn0, const b3Quaternion& orn1a, b3Vector3& axis, b3Scalar& angle)
{
b3Quaternion orn1 = orn0.nearest(orn1a);
b3Quaternion dorn = orn1 * orn0.inverse();
angle = dorn.getAngle();
- axis = b3MakeVector3(dorn.getX(),dorn.getY(),dorn.getZ());
+ axis = b3MakeVector3(dorn.getX(), dorn.getY(), dorn.getZ());
axis[3] = b3Scalar(0.);
//check for axis length
b3Scalar len = axis.length2();
- if (len < B3_EPSILON*B3_EPSILON)
- axis = b3MakeVector3(b3Scalar(1.),b3Scalar(0.),b3Scalar(0.));
+ if (len < B3_EPSILON * B3_EPSILON)
+ axis = b3MakeVector3(b3Scalar(1.), b3Scalar(0.), b3Scalar(0.));
else
axis /= b3Sqrt(len);
}
- static void calculateVelocity(const b3Transform& transform0,const b3Transform& transform1,b3Scalar timeStep,b3Vector3& linVel,b3Vector3& angVel)
+ static void calculateVelocity(const b3Transform& transform0, const b3Transform& transform1, b3Scalar timeStep, b3Vector3& linVel, b3Vector3& angVel)
{
linVel = (transform1.getOrigin() - transform0.getOrigin()) / timeStep;
b3Vector3 axis;
- b3Scalar angle;
- calculateDiffAxisAngle(transform0,transform1,axis,angle);
+ b3Scalar angle;
+ calculateDiffAxisAngle(transform0, transform1, axis, angle);
angVel = axis * angle / timeStep;
}
- static void calculateDiffAxisAngle(const b3Transform& transform0,const b3Transform& transform1,b3Vector3& axis,b3Scalar& angle)
+ static void calculateDiffAxisAngle(const b3Transform& transform0, const b3Transform& transform1, b3Vector3& axis, b3Scalar& angle)
{
b3Matrix3x3 dmat = transform1.getBasis() * transform0.getBasis().inverse();
b3Quaternion dorn;
dmat.getRotation(dorn);
- ///floating point inaccuracy can lead to w component > 1..., which breaks
+ ///floating point inaccuracy can lead to w component > 1..., which breaks
dorn.normalize();
-
+
angle = dorn.getAngle();
- axis = b3MakeVector3(dorn.getX(),dorn.getY(),dorn.getZ());
+ axis = b3MakeVector3(dorn.getX(), dorn.getY(), dorn.getZ());
axis[3] = b3Scalar(0.);
//check for axis length
b3Scalar len = axis.length2();
- if (len < B3_EPSILON*B3_EPSILON)
- axis = b3MakeVector3(b3Scalar(1.),b3Scalar(0.),b3Scalar(0.));
+ if (len < B3_EPSILON * B3_EPSILON)
+ axis = b3MakeVector3(b3Scalar(1.), b3Scalar(0.), b3Scalar(0.));
else
axis /= b3Sqrt(len);
}
-
};
-
-///The b3ConvexSeparatingDistanceUtil can help speed up convex collision detection
+///The b3ConvexSeparatingDistanceUtil can help speed up convex collision detection
///by conservatively updating a cached separating distance/vector instead of re-calculating the closest distance
-class b3ConvexSeparatingDistanceUtil
+class b3ConvexSeparatingDistanceUtil
{
- b3Quaternion m_ornA;
- b3Quaternion m_ornB;
- b3Vector3 m_posA;
- b3Vector3 m_posB;
-
- b3Vector3 m_separatingNormal;
+ b3Quaternion m_ornA;
+ b3Quaternion m_ornB;
+ b3Vector3 m_posA;
+ b3Vector3 m_posB;
- b3Scalar m_boundingRadiusA;
- b3Scalar m_boundingRadiusB;
- b3Scalar m_separatingDistance;
+ b3Vector3 m_separatingNormal;
-public:
+ b3Scalar m_boundingRadiusA;
+ b3Scalar m_boundingRadiusB;
+ b3Scalar m_separatingDistance;
- b3ConvexSeparatingDistanceUtil(b3Scalar boundingRadiusA,b3Scalar boundingRadiusB)
- :m_boundingRadiusA(boundingRadiusA),
- m_boundingRadiusB(boundingRadiusB),
- m_separatingDistance(0.f)
+public:
+ b3ConvexSeparatingDistanceUtil(b3Scalar boundingRadiusA, b3Scalar boundingRadiusB)
+ : m_boundingRadiusA(boundingRadiusA),
+ m_boundingRadiusB(boundingRadiusB),
+ m_separatingDistance(0.f)
{
}
- b3Scalar getConservativeSeparatingDistance()
+ b3Scalar getConservativeSeparatingDistance()
{
return m_separatingDistance;
}
- void updateSeparatingDistance(const b3Transform& transA,const b3Transform& transB)
+ void updateSeparatingDistance(const b3Transform& transA, const b3Transform& transB)
{
const b3Vector3& toPosA = transA.getOrigin();
const b3Vector3& toPosB = transB.getOrigin();
b3Quaternion toOrnA = transA.getRotation();
b3Quaternion toOrnB = transB.getRotation();
- if (m_separatingDistance>0.f)
+ if (m_separatingDistance > 0.f)
{
-
-
- b3Vector3 linVelA,angVelA,linVelB,angVelB;
- b3TransformUtil::calculateVelocityQuaternion(m_posA,toPosA,m_ornA,toOrnA,b3Scalar(1.),linVelA,angVelA);
- b3TransformUtil::calculateVelocityQuaternion(m_posB,toPosB,m_ornB,toOrnB,b3Scalar(1.),linVelB,angVelB);
+ b3Vector3 linVelA, angVelA, linVelB, angVelB;
+ b3TransformUtil::calculateVelocityQuaternion(m_posA, toPosA, m_ornA, toOrnA, b3Scalar(1.), linVelA, angVelA);
+ b3TransformUtil::calculateVelocityQuaternion(m_posB, toPosB, m_ornB, toOrnB, b3Scalar(1.), linVelB, angVelB);
b3Scalar maxAngularProjectedVelocity = angVelA.length() * m_boundingRadiusA + angVelB.length() * m_boundingRadiusB;
- b3Vector3 relLinVel = (linVelB-linVelA);
+ b3Vector3 relLinVel = (linVelB - linVelA);
b3Scalar relLinVelocLength = relLinVel.dot(m_separatingNormal);
- if (relLinVelocLength<0.f)
+ if (relLinVelocLength < 0.f)
{
relLinVelocLength = 0.f;
}
-
- b3Scalar projectedMotion = maxAngularProjectedVelocity +relLinVelocLength;
+
+ b3Scalar projectedMotion = maxAngularProjectedVelocity + relLinVelocLength;
m_separatingDistance -= projectedMotion;
}
-
+
m_posA = toPosA;
m_posB = toPosB;
m_ornA = toOrnA;
m_ornB = toOrnB;
}
- void initSeparatingDistance(const b3Vector3& separatingVector,b3Scalar separatingDistance,const b3Transform& transA,const b3Transform& transB)
+ void initSeparatingDistance(const b3Vector3& separatingVector, b3Scalar separatingDistance, const b3Transform& transA, const b3Transform& transB)
{
m_separatingDistance = separatingDistance;
- if (m_separatingDistance>0.f)
+ if (m_separatingDistance > 0.f)
{
m_separatingNormal = separatingVector;
-
+
const b3Vector3& toPosA = transA.getOrigin();
const b3Vector3& toPosB = transB.getOrigin();
b3Quaternion toOrnA = transA.getRotation();
@@ -220,9 +205,6 @@ public:
m_ornB = toOrnB;
}
}
-
};
-
-#endif //B3_TRANSFORM_UTIL_H
-
+#endif //B3_TRANSFORM_UTIL_H
diff --git a/thirdparty/bullet/Bullet3Common/b3Vector3.cpp b/thirdparty/bullet/Bullet3Common/b3Vector3.cpp
index 5f5ac4ac04..100fb774c1 100644
--- a/thirdparty/bullet/Bullet3Common/b3Vector3.cpp
+++ b/thirdparty/bullet/Bullet3Common/b3Vector3.cpp
@@ -14,274 +14,281 @@
This source version has been altered.
*/
-#if defined (_WIN32) || defined (__i386__)
+#if defined(_WIN32) || defined(__i386__)
#define B3_USE_SSE_IN_API
#endif
#include "b3Vector3.h"
-#if defined (B3_USE_SSE) || defined (B3_USE_NEON)
+#if defined(B3_USE_SSE) || defined(B3_USE_NEON)
#ifdef __APPLE__
#include <stdint.h>
-typedef float float4 __attribute__ ((vector_size(16)));
+typedef float float4 __attribute__((vector_size(16)));
#else
#define float4 __m128
#endif
//typedef uint32_t uint4 __attribute__ ((vector_size(16)));
-
#if defined B3_USE_SSE || defined _WIN32
-#define LOG2_ARRAY_SIZE 6
-#define STACK_ARRAY_COUNT (1UL << LOG2_ARRAY_SIZE)
+#define LOG2_ARRAY_SIZE 6
+#define STACK_ARRAY_COUNT (1UL << LOG2_ARRAY_SIZE)
#include <emmintrin.h>
-long b3_maxdot_large( const float *vv, const float *vec, unsigned long count, float *dotResult );
-long b3_maxdot_large( const float *vv, const float *vec, unsigned long count, float *dotResult )
+long b3_maxdot_large(const float *vv, const float *vec, unsigned long count, float *dotResult);
+long b3_maxdot_large(const float *vv, const float *vec, unsigned long count, float *dotResult)
{
- const float4 *vertices = (const float4*) vv;
- static const unsigned char indexTable[16] = {(unsigned char)-1, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 };
- float4 dotMax = b3Assign128( -B3_INFINITY, -B3_INFINITY, -B3_INFINITY, -B3_INFINITY );
- float4 vvec = _mm_loadu_ps( vec );
- float4 vHi = b3CastiTo128f(_mm_shuffle_epi32( b3CastfTo128i( vvec), 0xaa )); /// zzzz
- float4 vLo = _mm_movelh_ps( vvec, vvec ); /// xyxy
+ const float4 *vertices = (const float4 *)vv;
+ static const unsigned char indexTable[16] = {(unsigned char)-1, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0};
+ float4 dotMax = b3Assign128(-B3_INFINITY, -B3_INFINITY, -B3_INFINITY, -B3_INFINITY);
+ float4 vvec = _mm_loadu_ps(vec);
+ float4 vHi = b3CastiTo128f(_mm_shuffle_epi32(b3CastfTo128i(vvec), 0xaa)); /// zzzz
+ float4 vLo = _mm_movelh_ps(vvec, vvec); /// xyxy
- long maxIndex = -1L;
+ long maxIndex = -1L;
- size_t segment = 0;
- float4 stack_array[ STACK_ARRAY_COUNT ];
+ size_t segment = 0;
+ float4 stack_array[STACK_ARRAY_COUNT];
#if DEBUG
- // memset( stack_array, -1, STACK_ARRAY_COUNT * sizeof(stack_array[0]) );
+ // memset( stack_array, -1, STACK_ARRAY_COUNT * sizeof(stack_array[0]) );
#endif
- size_t index;
- float4 max;
- // Faster loop without cleanup code for full tiles
- for ( segment = 0; segment + STACK_ARRAY_COUNT*4 <= count; segment += STACK_ARRAY_COUNT*4 )
- {
- max = dotMax;
-
- for( index = 0; index < STACK_ARRAY_COUNT; index+= 4 )
- { // do four dot products at a time. Carefully avoid touching the w element.
- float4 v0 = vertices[0];
- float4 v1 = vertices[1];
- float4 v2 = vertices[2];
- float4 v3 = vertices[3]; vertices += 4;
-
- float4 lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
- float4 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
- float4 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
- float4 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
-
- lo0 = lo0*vLo;
- lo1 = lo1*vLo;
- float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
- float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
- float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z*vHi;
- x = x+y;
- x = x+z;
- stack_array[index] = x;
- max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3]; vertices += 4;
-
- lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
-
- lo0 = lo0*vLo;
- lo1 = lo1*vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z*vHi;
- x = x+y;
- x = x+z;
- stack_array[index+1] = x;
- max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3]; vertices += 4;
-
- lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
-
- lo0 = lo0*vLo;
- lo1 = lo1*vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z*vHi;
- x = x+y;
- x = x+z;
- stack_array[index+2] = x;
- max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3]; vertices += 4;
-
- lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
-
- lo0 = lo0*vLo;
- lo1 = lo1*vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z*vHi;
- x = x+y;
- x = x+z;
- stack_array[index+3] = x;
- max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
-
- // It is too costly to keep the index of the max here. We will look for it again later. We save a lot of work this way.
- }
-
- // If we found a new max
- if( 0xf != _mm_movemask_ps( (float4) _mm_cmpeq_ps(max, dotMax)))
- {
- // copy the new max across all lanes of our max accumulator
- max = _mm_max_ps(max, (float4) _mm_shuffle_ps( max, max, 0x4e));
- max = _mm_max_ps(max, (float4) _mm_shuffle_ps( max, max, 0xb1));
-
- dotMax = max;
-
- // find first occurrence of that max
- size_t test;
- for( index = 0; 0 == (test=_mm_movemask_ps( _mm_cmpeq_ps( stack_array[index], max))); index++ ) // local_count must be a multiple of 4
- {}
- // record where it is.
- maxIndex = 4*index + segment + indexTable[test];
- }
- }
-
- // account for work we've already done
- count -= segment;
-
- // Deal with the last < STACK_ARRAY_COUNT vectors
- max = dotMax;
- index = 0;
-
-
- if( b3Unlikely( count > 16) )
- {
- for( ; index + 4 <= count / 4; index+=4 )
- { // do four dot products at a time. Carefully avoid touching the w element.
- float4 v0 = vertices[0];
- float4 v1 = vertices[1];
- float4 v2 = vertices[2];
- float4 v3 = vertices[3]; vertices += 4;
-
- float4 lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
- float4 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
- float4 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
- float4 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
-
- lo0 = lo0*vLo;
- lo1 = lo1*vLo;
- float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
- float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
- float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z*vHi;
- x = x+y;
- x = x+z;
- stack_array[index] = x;
- max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3]; vertices += 4;
-
- lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
-
- lo0 = lo0*vLo;
- lo1 = lo1*vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z*vHi;
- x = x+y;
- x = x+z;
- stack_array[index+1] = x;
- max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3]; vertices += 4;
-
- lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
-
- lo0 = lo0*vLo;
- lo1 = lo1*vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z*vHi;
- x = x+y;
- x = x+z;
- stack_array[index+2] = x;
- max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3]; vertices += 4;
-
- lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
-
- lo0 = lo0*vLo;
- lo1 = lo1*vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z*vHi;
- x = x+y;
- x = x+z;
- stack_array[index+3] = x;
- max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
-
- // It is too costly to keep the index of the max here. We will look for it again later. We save a lot of work this way.
- }
- }
-
- size_t localCount = (count & -4L) - 4*index;
- if( localCount )
- {
+ size_t index;
+ float4 max;
+ // Faster loop without cleanup code for full tiles
+ for (segment = 0; segment + STACK_ARRAY_COUNT * 4 <= count; segment += STACK_ARRAY_COUNT * 4)
+ {
+ max = dotMax;
+
+ for (index = 0; index < STACK_ARRAY_COUNT; index += 4)
+ { // do four dot products at a time. Carefully avoid touching the w element.
+ float4 v0 = vertices[0];
+ float4 v1 = vertices[1];
+ float4 v2 = vertices[2];
+ float4 v3 = vertices[3];
+ vertices += 4;
+
+ float4 lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
+ float4 hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
+ float4 lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
+ float4 hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
+
+ lo0 = lo0 * vLo;
+ lo1 = lo1 * vLo;
+ float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z * vHi;
+ x = x + y;
+ x = x + z;
+ stack_array[index] = x;
+ max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3];
+ vertices += 4;
+
+ lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
+
+ lo0 = lo0 * vLo;
+ lo1 = lo1 * vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z * vHi;
+ x = x + y;
+ x = x + z;
+ stack_array[index + 1] = x;
+ max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3];
+ vertices += 4;
+
+ lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
+
+ lo0 = lo0 * vLo;
+ lo1 = lo1 * vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z * vHi;
+ x = x + y;
+ x = x + z;
+ stack_array[index + 2] = x;
+ max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3];
+ vertices += 4;
+
+ lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
+
+ lo0 = lo0 * vLo;
+ lo1 = lo1 * vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z * vHi;
+ x = x + y;
+ x = x + z;
+ stack_array[index + 3] = x;
+ max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
+
+ // It is too costly to keep the index of the max here. We will look for it again later. We save a lot of work this way.
+ }
+
+ // If we found a new max
+ if (0xf != _mm_movemask_ps((float4)_mm_cmpeq_ps(max, dotMax)))
+ {
+ // copy the new max across all lanes of our max accumulator
+ max = _mm_max_ps(max, (float4)_mm_shuffle_ps(max, max, 0x4e));
+ max = _mm_max_ps(max, (float4)_mm_shuffle_ps(max, max, 0xb1));
+
+ dotMax = max;
+
+ // find first occurrence of that max
+ size_t test;
+ for (index = 0; 0 == (test = _mm_movemask_ps(_mm_cmpeq_ps(stack_array[index], max))); index++) // local_count must be a multiple of 4
+ {
+ }
+ // record where it is.
+ maxIndex = 4 * index + segment + indexTable[test];
+ }
+ }
+
+ // account for work we've already done
+ count -= segment;
+
+ // Deal with the last < STACK_ARRAY_COUNT vectors
+ max = dotMax;
+ index = 0;
+
+ if (b3Unlikely(count > 16))
+ {
+ for (; index + 4 <= count / 4; index += 4)
+ { // do four dot products at a time. Carefully avoid touching the w element.
+ float4 v0 = vertices[0];
+ float4 v1 = vertices[1];
+ float4 v2 = vertices[2];
+ float4 v3 = vertices[3];
+ vertices += 4;
+
+ float4 lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
+ float4 hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
+ float4 lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
+ float4 hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
+
+ lo0 = lo0 * vLo;
+ lo1 = lo1 * vLo;
+ float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z * vHi;
+ x = x + y;
+ x = x + z;
+ stack_array[index] = x;
+ max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3];
+ vertices += 4;
+
+ lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
+
+ lo0 = lo0 * vLo;
+ lo1 = lo1 * vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z * vHi;
+ x = x + y;
+ x = x + z;
+ stack_array[index + 1] = x;
+ max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3];
+ vertices += 4;
+
+ lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
+
+ lo0 = lo0 * vLo;
+ lo1 = lo1 * vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z * vHi;
+ x = x + y;
+ x = x + z;
+ stack_array[index + 2] = x;
+ max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3];
+ vertices += 4;
+
+ lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
+
+ lo0 = lo0 * vLo;
+ lo1 = lo1 * vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z * vHi;
+ x = x + y;
+ x = x + z;
+ stack_array[index + 3] = x;
+ max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
+
+ // It is too costly to keep the index of the max here. We will look for it again later. We save a lot of work this way.
+ }
+ }
+
+ size_t localCount = (count & -4L) - 4 * index;
+ if (localCount)
+ {
#ifdef __APPLE__
- float4 t0, t1, t2, t3, t4;
- float4 * sap = &stack_array[index + localCount / 4];
- vertices += localCount; // counter the offset
- size_t byteIndex = -(localCount) * sizeof(float);
- //AT&T Code style assembly
- asm volatile
- ( ".align 4 \n\
+ float4 t0, t1, t2, t3, t4;
+ float4 *sap = &stack_array[index + localCount / 4];
+ vertices += localCount; // counter the offset
+ size_t byteIndex = -(localCount) * sizeof(float);
+ //AT&T Code style assembly
+ asm volatile(
+ ".align 4 \n\
0: movaps %[max], %[t2] // move max out of the way to avoid propagating NaNs in max \n\
movaps (%[vertices], %[byteIndex], 4), %[t0] // vertices[0] \n\
movaps 16(%[vertices], %[byteIndex], 4), %[t1] // vertices[1] \n\
@@ -307,369 +314,375 @@ long b3_maxdot_large( const float *vv, const float *vec, unsigned long count, fl
add $16, %[byteIndex] // advance loop counter\n\
jnz 0b \n\
"
- : [max] "+x" (max), [t0] "=&x" (t0), [t1] "=&x" (t1), [t2] "=&x" (t2), [t3] "=&x" (t3), [t4] "=&x" (t4), [byteIndex] "+r" (byteIndex)
- : [vLo] "x" (vLo), [vHi] "x" (vHi), [vertices] "r" (vertices), [sap] "r" (sap)
- : "memory", "cc"
- );
- index += localCount/4;
+ : [max] "+x"(max), [t0] "=&x"(t0), [t1] "=&x"(t1), [t2] "=&x"(t2), [t3] "=&x"(t3), [t4] "=&x"(t4), [byteIndex] "+r"(byteIndex)
+ : [vLo] "x"(vLo), [vHi] "x"(vHi), [vertices] "r"(vertices), [sap] "r"(sap)
+ : "memory", "cc");
+ index += localCount / 4;
#else
- {
- for( unsigned int i=0; i<localCount/4; i++,index++)
- { // do four dot products at a time. Carefully avoid touching the w element.
- float4 v0 = vertices[0];
- float4 v1 = vertices[1];
- float4 v2 = vertices[2];
- float4 v3 = vertices[3];
- vertices += 4;
-
- float4 lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
- float4 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
- float4 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
- float4 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
-
- lo0 = lo0*vLo;
- lo1 = lo1*vLo;
- float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
- float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
- float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z*vHi;
- x = x+y;
- x = x+z;
- stack_array[index] = x;
- max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
- }
- }
-#endif //__APPLE__
- }
-
- // process the last few points
- if( count & 3 )
- {
- float4 v0, v1, v2, x, y, z;
- switch( count & 3 )
- {
- case 3:
- {
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
-
- // Calculate 3 dot products, transpose, duplicate v2
- float4 lo0 = _mm_movelh_ps( v0, v1); // xyxy.lo
- float4 hi0 = _mm_movehl_ps( v1, v0); // z?z?.lo
- lo0 = lo0*vLo;
- z = _mm_shuffle_ps(hi0, v2, 0xa8 ); // z0z1z2z2
- z = z*vHi;
- float4 lo1 = _mm_movelh_ps(v2, v2); // xyxy
- lo1 = lo1*vLo;
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- }
- break;
- case 2:
- {
- v0 = vertices[0];
- v1 = vertices[1];
- float4 xy = _mm_movelh_ps(v0, v1);
- z = _mm_movehl_ps(v1, v0);
- xy = xy*vLo;
- z = _mm_shuffle_ps( z, z, 0xa8);
- x = _mm_shuffle_ps( xy, xy, 0xa8);
- y = _mm_shuffle_ps( xy, xy, 0xfd);
- z = z*vHi;
- }
- break;
- case 1:
- {
- float4 xy = vertices[0];
- z = _mm_shuffle_ps( xy, xy, 0xaa);
- xy = xy*vLo;
- z = z*vHi;
- x = _mm_shuffle_ps(xy, xy, 0);
- y = _mm_shuffle_ps(xy, xy, 0x55);
- }
- break;
- }
- x = x+y;
- x = x+z;
- stack_array[index] = x;
- max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
- index++;
- }
-
- // if we found a new max.
- if( 0 == segment || 0xf != _mm_movemask_ps( (float4) _mm_cmpeq_ps(max, dotMax)))
- { // we found a new max. Search for it
- // find max across the max vector, place in all elements of max -- big latency hit here
- max = _mm_max_ps(max, (float4) _mm_shuffle_ps( max, max, 0x4e));
- max = _mm_max_ps(max, (float4) _mm_shuffle_ps( max, max, 0xb1));
-
- // It is slightly faster to do this part in scalar code when count < 8. However, the common case for
- // this where it actually makes a difference is handled in the early out at the top of the function,
- // so it is less than a 1% difference here. I opted for improved code size, fewer branches and reduced
- // complexity, and removed it.
-
- dotMax = max;
-
- // scan for the first occurence of max in the array
- size_t test;
- for( index = 0; 0 == (test=_mm_movemask_ps( _mm_cmpeq_ps( stack_array[index], max))); index++ ) // local_count must be a multiple of 4
- {}
- maxIndex = 4*index + segment + indexTable[test];
- }
-
- _mm_store_ss( dotResult, dotMax);
- return maxIndex;
+ {
+ for (unsigned int i = 0; i < localCount / 4; i++, index++)
+ { // do four dot products at a time. Carefully avoid touching the w element.
+ float4 v0 = vertices[0];
+ float4 v1 = vertices[1];
+ float4 v2 = vertices[2];
+ float4 v3 = vertices[3];
+ vertices += 4;
+
+ float4 lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
+ float4 hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
+ float4 lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
+ float4 hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
+
+ lo0 = lo0 * vLo;
+ lo1 = lo1 * vLo;
+ float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z * vHi;
+ x = x + y;
+ x = x + z;
+ stack_array[index] = x;
+ max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
+ }
+ }
+#endif //__APPLE__
+ }
+
+ // process the last few points
+ if (count & 3)
+ {
+ float4 v0, v1, v2, x, y, z;
+ switch (count & 3)
+ {
+ case 3:
+ {
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+
+ // Calculate 3 dot products, transpose, duplicate v2
+ float4 lo0 = _mm_movelh_ps(v0, v1); // xyxy.lo
+ float4 hi0 = _mm_movehl_ps(v1, v0); // z?z?.lo
+ lo0 = lo0 * vLo;
+ z = _mm_shuffle_ps(hi0, v2, 0xa8); // z0z1z2z2
+ z = z * vHi;
+ float4 lo1 = _mm_movelh_ps(v2, v2); // xyxy
+ lo1 = lo1 * vLo;
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ }
+ break;
+ case 2:
+ {
+ v0 = vertices[0];
+ v1 = vertices[1];
+ float4 xy = _mm_movelh_ps(v0, v1);
+ z = _mm_movehl_ps(v1, v0);
+ xy = xy * vLo;
+ z = _mm_shuffle_ps(z, z, 0xa8);
+ x = _mm_shuffle_ps(xy, xy, 0xa8);
+ y = _mm_shuffle_ps(xy, xy, 0xfd);
+ z = z * vHi;
+ }
+ break;
+ case 1:
+ {
+ float4 xy = vertices[0];
+ z = _mm_shuffle_ps(xy, xy, 0xaa);
+ xy = xy * vLo;
+ z = z * vHi;
+ x = _mm_shuffle_ps(xy, xy, 0);
+ y = _mm_shuffle_ps(xy, xy, 0x55);
+ }
+ break;
+ }
+ x = x + y;
+ x = x + z;
+ stack_array[index] = x;
+ max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
+ index++;
+ }
+
+ // if we found a new max.
+ if (0 == segment || 0xf != _mm_movemask_ps((float4)_mm_cmpeq_ps(max, dotMax)))
+ { // we found a new max. Search for it
+ // find max across the max vector, place in all elements of max -- big latency hit here
+ max = _mm_max_ps(max, (float4)_mm_shuffle_ps(max, max, 0x4e));
+ max = _mm_max_ps(max, (float4)_mm_shuffle_ps(max, max, 0xb1));
+
+ // It is slightly faster to do this part in scalar code when count < 8. However, the common case for
+ // this where it actually makes a difference is handled in the early out at the top of the function,
+ // so it is less than a 1% difference here. I opted for improved code size, fewer branches and reduced
+ // complexity, and removed it.
+
+ dotMax = max;
+
+ // scan for the first occurence of max in the array
+ size_t test;
+ for (index = 0; 0 == (test = _mm_movemask_ps(_mm_cmpeq_ps(stack_array[index], max))); index++) // local_count must be a multiple of 4
+ {
+ }
+ maxIndex = 4 * index + segment + indexTable[test];
+ }
+
+ _mm_store_ss(dotResult, dotMax);
+ return maxIndex;
}
-long b3_mindot_large( const float *vv, const float *vec, unsigned long count, float *dotResult );
+long b3_mindot_large(const float *vv, const float *vec, unsigned long count, float *dotResult);
-long b3_mindot_large( const float *vv, const float *vec, unsigned long count, float *dotResult )
+long b3_mindot_large(const float *vv, const float *vec, unsigned long count, float *dotResult)
{
- const float4 *vertices = (const float4*) vv;
- static const unsigned char indexTable[16] = {(unsigned char)-1, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 };
+ const float4 *vertices = (const float4 *)vv;
+ static const unsigned char indexTable[16] = {(unsigned char)-1, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0};
- float4 dotmin = b3Assign128( B3_INFINITY, B3_INFINITY, B3_INFINITY, B3_INFINITY );
- float4 vvec = _mm_loadu_ps( vec );
- float4 vHi = b3CastiTo128f(_mm_shuffle_epi32( b3CastfTo128i( vvec), 0xaa )); /// zzzz
- float4 vLo = _mm_movelh_ps( vvec, vvec ); /// xyxy
+ float4 dotmin = b3Assign128(B3_INFINITY, B3_INFINITY, B3_INFINITY, B3_INFINITY);
+ float4 vvec = _mm_loadu_ps(vec);
+ float4 vHi = b3CastiTo128f(_mm_shuffle_epi32(b3CastfTo128i(vvec), 0xaa)); /// zzzz
+ float4 vLo = _mm_movelh_ps(vvec, vvec); /// xyxy
- long minIndex = -1L;
+ long minIndex = -1L;
- size_t segment = 0;
- float4 stack_array[ STACK_ARRAY_COUNT ];
+ size_t segment = 0;
+ float4 stack_array[STACK_ARRAY_COUNT];
#if DEBUG
- // memset( stack_array, -1, STACK_ARRAY_COUNT * sizeof(stack_array[0]) );
+ // memset( stack_array, -1, STACK_ARRAY_COUNT * sizeof(stack_array[0]) );
#endif
- size_t index;
- float4 min;
- // Faster loop without cleanup code for full tiles
- for ( segment = 0; segment + STACK_ARRAY_COUNT*4 <= count; segment += STACK_ARRAY_COUNT*4 )
- {
- min = dotmin;
-
- for( index = 0; index < STACK_ARRAY_COUNT; index+= 4 )
- { // do four dot products at a time. Carefully avoid touching the w element.
- float4 v0 = vertices[0];
- float4 v1 = vertices[1];
- float4 v2 = vertices[2];
- float4 v3 = vertices[3]; vertices += 4;
-
- float4 lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
- float4 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
- float4 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
- float4 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
-
- lo0 = lo0*vLo;
- lo1 = lo1*vLo;
- float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
- float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
- float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z*vHi;
- x = x+y;
- x = x+z;
- stack_array[index] = x;
- min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3]; vertices += 4;
-
- lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
-
- lo0 = lo0*vLo;
- lo1 = lo1*vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z*vHi;
- x = x+y;
- x = x+z;
- stack_array[index+1] = x;
- min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3]; vertices += 4;
-
- lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
-
- lo0 = lo0*vLo;
- lo1 = lo1*vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z*vHi;
- x = x+y;
- x = x+z;
- stack_array[index+2] = x;
- min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3]; vertices += 4;
-
- lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
-
- lo0 = lo0*vLo;
- lo1 = lo1*vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z*vHi;
- x = x+y;
- x = x+z;
- stack_array[index+3] = x;
- min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
-
- // It is too costly to keep the index of the min here. We will look for it again later. We save a lot of work this way.
- }
-
- // If we found a new min
- if( 0xf != _mm_movemask_ps( (float4) _mm_cmpeq_ps(min, dotmin)))
- {
- // copy the new min across all lanes of our min accumulator
- min = _mm_min_ps(min, (float4) _mm_shuffle_ps( min, min, 0x4e));
- min = _mm_min_ps(min, (float4) _mm_shuffle_ps( min, min, 0xb1));
-
- dotmin = min;
-
- // find first occurrence of that min
- size_t test;
- for( index = 0; 0 == (test=_mm_movemask_ps( _mm_cmpeq_ps( stack_array[index], min))); index++ ) // local_count must be a multiple of 4
- {}
- // record where it is.
- minIndex = 4*index + segment + indexTable[test];
- }
- }
-
- // account for work we've already done
- count -= segment;
-
- // Deal with the last < STACK_ARRAY_COUNT vectors
- min = dotmin;
- index = 0;
-
-
- if(b3Unlikely( count > 16) )
- {
- for( ; index + 4 <= count / 4; index+=4 )
- { // do four dot products at a time. Carefully avoid touching the w element.
- float4 v0 = vertices[0];
- float4 v1 = vertices[1];
- float4 v2 = vertices[2];
- float4 v3 = vertices[3]; vertices += 4;
-
- float4 lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
- float4 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
- float4 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
- float4 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
-
- lo0 = lo0*vLo;
- lo1 = lo1*vLo;
- float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
- float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
- float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z*vHi;
- x = x+y;
- x = x+z;
- stack_array[index] = x;
- min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3]; vertices += 4;
-
- lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
-
- lo0 = lo0*vLo;
- lo1 = lo1*vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z*vHi;
- x = x+y;
- x = x+z;
- stack_array[index+1] = x;
- min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3]; vertices += 4;
-
- lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
-
- lo0 = lo0*vLo;
- lo1 = lo1*vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z*vHi;
- x = x+y;
- x = x+z;
- stack_array[index+2] = x;
- min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3]; vertices += 4;
-
- lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
-
- lo0 = lo0*vLo;
- lo1 = lo1*vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z*vHi;
- x = x+y;
- x = x+z;
- stack_array[index+3] = x;
- min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
-
- // It is too costly to keep the index of the min here. We will look for it again later. We save a lot of work this way.
- }
- }
-
- size_t localCount = (count & -4L) - 4*index;
- if( localCount )
- {
-
-
+ size_t index;
+ float4 min;
+ // Faster loop without cleanup code for full tiles
+ for (segment = 0; segment + STACK_ARRAY_COUNT * 4 <= count; segment += STACK_ARRAY_COUNT * 4)
+ {
+ min = dotmin;
+
+ for (index = 0; index < STACK_ARRAY_COUNT; index += 4)
+ { // do four dot products at a time. Carefully avoid touching the w element.
+ float4 v0 = vertices[0];
+ float4 v1 = vertices[1];
+ float4 v2 = vertices[2];
+ float4 v3 = vertices[3];
+ vertices += 4;
+
+ float4 lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
+ float4 hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
+ float4 lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
+ float4 hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
+
+ lo0 = lo0 * vLo;
+ lo1 = lo1 * vLo;
+ float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z * vHi;
+ x = x + y;
+ x = x + z;
+ stack_array[index] = x;
+ min = _mm_min_ps(x, min); // control the order here so that min is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3];
+ vertices += 4;
+
+ lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
+
+ lo0 = lo0 * vLo;
+ lo1 = lo1 * vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z * vHi;
+ x = x + y;
+ x = x + z;
+ stack_array[index + 1] = x;
+ min = _mm_min_ps(x, min); // control the order here so that min is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3];
+ vertices += 4;
+
+ lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
+
+ lo0 = lo0 * vLo;
+ lo1 = lo1 * vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z * vHi;
+ x = x + y;
+ x = x + z;
+ stack_array[index + 2] = x;
+ min = _mm_min_ps(x, min); // control the order here so that min is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3];
+ vertices += 4;
+
+ lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
+
+ lo0 = lo0 * vLo;
+ lo1 = lo1 * vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z * vHi;
+ x = x + y;
+ x = x + z;
+ stack_array[index + 3] = x;
+ min = _mm_min_ps(x, min); // control the order here so that min is never NaN even if x is nan
+
+ // It is too costly to keep the index of the min here. We will look for it again later. We save a lot of work this way.
+ }
+
+ // If we found a new min
+ if (0xf != _mm_movemask_ps((float4)_mm_cmpeq_ps(min, dotmin)))
+ {
+ // copy the new min across all lanes of our min accumulator
+ min = _mm_min_ps(min, (float4)_mm_shuffle_ps(min, min, 0x4e));
+ min = _mm_min_ps(min, (float4)_mm_shuffle_ps(min, min, 0xb1));
+
+ dotmin = min;
+
+ // find first occurrence of that min
+ size_t test;
+ for (index = 0; 0 == (test = _mm_movemask_ps(_mm_cmpeq_ps(stack_array[index], min))); index++) // local_count must be a multiple of 4
+ {
+ }
+ // record where it is.
+ minIndex = 4 * index + segment + indexTable[test];
+ }
+ }
+
+ // account for work we've already done
+ count -= segment;
+
+ // Deal with the last < STACK_ARRAY_COUNT vectors
+ min = dotmin;
+ index = 0;
+
+ if (b3Unlikely(count > 16))
+ {
+ for (; index + 4 <= count / 4; index += 4)
+ { // do four dot products at a time. Carefully avoid touching the w element.
+ float4 v0 = vertices[0];
+ float4 v1 = vertices[1];
+ float4 v2 = vertices[2];
+ float4 v3 = vertices[3];
+ vertices += 4;
+
+ float4 lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
+ float4 hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
+ float4 lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
+ float4 hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
+
+ lo0 = lo0 * vLo;
+ lo1 = lo1 * vLo;
+ float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z * vHi;
+ x = x + y;
+ x = x + z;
+ stack_array[index] = x;
+ min = _mm_min_ps(x, min); // control the order here so that min is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3];
+ vertices += 4;
+
+ lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
+
+ lo0 = lo0 * vLo;
+ lo1 = lo1 * vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z * vHi;
+ x = x + y;
+ x = x + z;
+ stack_array[index + 1] = x;
+ min = _mm_min_ps(x, min); // control the order here so that min is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3];
+ vertices += 4;
+
+ lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
+
+ lo0 = lo0 * vLo;
+ lo1 = lo1 * vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z * vHi;
+ x = x + y;
+ x = x + z;
+ stack_array[index + 2] = x;
+ min = _mm_min_ps(x, min); // control the order here so that min is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3];
+ vertices += 4;
+
+ lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
+
+ lo0 = lo0 * vLo;
+ lo1 = lo1 * vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z * vHi;
+ x = x + y;
+ x = x + z;
+ stack_array[index + 3] = x;
+ min = _mm_min_ps(x, min); // control the order here so that min is never NaN even if x is nan
+
+ // It is too costly to keep the index of the min here. We will look for it again later. We save a lot of work this way.
+ }
+ }
+
+ size_t localCount = (count & -4L) - 4 * index;
+ if (localCount)
+ {
#ifdef __APPLE__
- vertices += localCount; // counter the offset
- float4 t0, t1, t2, t3, t4;
- size_t byteIndex = -(localCount) * sizeof(float);
- float4 * sap = &stack_array[index + localCount / 4];
+ vertices += localCount; // counter the offset
+ float4 t0, t1, t2, t3, t4;
+ size_t byteIndex = -(localCount) * sizeof(float);
+ float4 *sap = &stack_array[index + localCount / 4];
- asm volatile
- ( ".align 4 \n\
+ asm volatile(
+ ".align 4 \n\
0: movaps %[min], %[t2] // move min out of the way to avoid propagating NaNs in min \n\
movaps (%[vertices], %[byteIndex], 4), %[t0] // vertices[0] \n\
movaps 16(%[vertices], %[byteIndex], 4), %[t1] // vertices[1] \n\
@@ -695,937 +708,930 @@ long b3_mindot_large( const float *vv, const float *vec, unsigned long count, fl
add $16, %[byteIndex] // advance loop counter\n\
jnz 0b \n\
"
- : [min] "+x" (min), [t0] "=&x" (t0), [t1] "=&x" (t1), [t2] "=&x" (t2), [t3] "=&x" (t3), [t4] "=&x" (t4), [byteIndex] "+r" (byteIndex)
- : [vLo] "x" (vLo), [vHi] "x" (vHi), [vertices] "r" (vertices), [sap] "r" (sap)
- : "memory", "cc"
- );
- index += localCount/4;
+ : [min] "+x"(min), [t0] "=&x"(t0), [t1] "=&x"(t1), [t2] "=&x"(t2), [t3] "=&x"(t3), [t4] "=&x"(t4), [byteIndex] "+r"(byteIndex)
+ : [vLo] "x"(vLo), [vHi] "x"(vHi), [vertices] "r"(vertices), [sap] "r"(sap)
+ : "memory", "cc");
+ index += localCount / 4;
#else
- {
- for( unsigned int i=0; i<localCount/4; i++,index++)
- { // do four dot products at a time. Carefully avoid touching the w element.
- float4 v0 = vertices[0];
- float4 v1 = vertices[1];
- float4 v2 = vertices[2];
- float4 v3 = vertices[3];
- vertices += 4;
-
- float4 lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
- float4 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
- float4 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
- float4 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
-
- lo0 = lo0*vLo;
- lo1 = lo1*vLo;
- float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
- float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
- float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z*vHi;
- x = x+y;
- x = x+z;
- stack_array[index] = x;
- min = _mm_min_ps( x, min ); // control the order here so that max is never NaN even if x is nan
- }
- }
+ {
+ for (unsigned int i = 0; i < localCount / 4; i++, index++)
+ { // do four dot products at a time. Carefully avoid touching the w element.
+ float4 v0 = vertices[0];
+ float4 v1 = vertices[1];
+ float4 v2 = vertices[2];
+ float4 v3 = vertices[3];
+ vertices += 4;
+
+ float4 lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
+ float4 hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
+ float4 lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
+ float4 hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
+
+ lo0 = lo0 * vLo;
+ lo1 = lo1 * vLo;
+ float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z * vHi;
+ x = x + y;
+ x = x + z;
+ stack_array[index] = x;
+ min = _mm_min_ps(x, min); // control the order here so that max is never NaN even if x is nan
+ }
+ }
#endif
- }
-
- // process the last few points
- if( count & 3 )
- {
- float4 v0, v1, v2, x, y, z;
- switch( count & 3 )
- {
- case 3:
- {
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
-
- // Calculate 3 dot products, transpose, duplicate v2
- float4 lo0 = _mm_movelh_ps( v0, v1); // xyxy.lo
- float4 hi0 = _mm_movehl_ps( v1, v0); // z?z?.lo
- lo0 = lo0*vLo;
- z = _mm_shuffle_ps(hi0, v2, 0xa8 ); // z0z1z2z2
- z = z*vHi;
- float4 lo1 = _mm_movelh_ps(v2, v2); // xyxy
- lo1 = lo1*vLo;
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- }
- break;
- case 2:
- {
- v0 = vertices[0];
- v1 = vertices[1];
- float4 xy = _mm_movelh_ps(v0, v1);
- z = _mm_movehl_ps(v1, v0);
- xy = xy*vLo;
- z = _mm_shuffle_ps( z, z, 0xa8);
- x = _mm_shuffle_ps( xy, xy, 0xa8);
- y = _mm_shuffle_ps( xy, xy, 0xfd);
- z = z*vHi;
- }
- break;
- case 1:
- {
- float4 xy = vertices[0];
- z = _mm_shuffle_ps( xy, xy, 0xaa);
- xy = xy*vLo;
- z = z*vHi;
- x = _mm_shuffle_ps(xy, xy, 0);
- y = _mm_shuffle_ps(xy, xy, 0x55);
- }
- break;
- }
- x = x+y;
- x = x+z;
- stack_array[index] = x;
- min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
- index++;
- }
-
- // if we found a new min.
- if( 0 == segment || 0xf != _mm_movemask_ps( (float4) _mm_cmpeq_ps(min, dotmin)))
- { // we found a new min. Search for it
- // find min across the min vector, place in all elements of min -- big latency hit here
- min = _mm_min_ps(min, (float4) _mm_shuffle_ps( min, min, 0x4e));
- min = _mm_min_ps(min, (float4) _mm_shuffle_ps( min, min, 0xb1));
-
- // It is slightly faster to do this part in scalar code when count < 8. However, the common case for
- // this where it actually makes a difference is handled in the early out at the top of the function,
- // so it is less than a 1% difference here. I opted for improved code size, fewer branches and reduced
- // complexity, and removed it.
-
- dotmin = min;
-
- // scan for the first occurence of min in the array
- size_t test;
- for( index = 0; 0 == (test=_mm_movemask_ps( _mm_cmpeq_ps( stack_array[index], min))); index++ ) // local_count must be a multiple of 4
- {}
- minIndex = 4*index + segment + indexTable[test];
- }
-
- _mm_store_ss( dotResult, dotmin);
- return minIndex;
+ }
+
+ // process the last few points
+ if (count & 3)
+ {
+ float4 v0, v1, v2, x, y, z;
+ switch (count & 3)
+ {
+ case 3:
+ {
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+
+ // Calculate 3 dot products, transpose, duplicate v2
+ float4 lo0 = _mm_movelh_ps(v0, v1); // xyxy.lo
+ float4 hi0 = _mm_movehl_ps(v1, v0); // z?z?.lo
+ lo0 = lo0 * vLo;
+ z = _mm_shuffle_ps(hi0, v2, 0xa8); // z0z1z2z2
+ z = z * vHi;
+ float4 lo1 = _mm_movelh_ps(v2, v2); // xyxy
+ lo1 = lo1 * vLo;
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ }
+ break;
+ case 2:
+ {
+ v0 = vertices[0];
+ v1 = vertices[1];
+ float4 xy = _mm_movelh_ps(v0, v1);
+ z = _mm_movehl_ps(v1, v0);
+ xy = xy * vLo;
+ z = _mm_shuffle_ps(z, z, 0xa8);
+ x = _mm_shuffle_ps(xy, xy, 0xa8);
+ y = _mm_shuffle_ps(xy, xy, 0xfd);
+ z = z * vHi;
+ }
+ break;
+ case 1:
+ {
+ float4 xy = vertices[0];
+ z = _mm_shuffle_ps(xy, xy, 0xaa);
+ xy = xy * vLo;
+ z = z * vHi;
+ x = _mm_shuffle_ps(xy, xy, 0);
+ y = _mm_shuffle_ps(xy, xy, 0x55);
+ }
+ break;
+ }
+ x = x + y;
+ x = x + z;
+ stack_array[index] = x;
+ min = _mm_min_ps(x, min); // control the order here so that min is never NaN even if x is nan
+ index++;
+ }
+
+ // if we found a new min.
+ if (0 == segment || 0xf != _mm_movemask_ps((float4)_mm_cmpeq_ps(min, dotmin)))
+ { // we found a new min. Search for it
+ // find min across the min vector, place in all elements of min -- big latency hit here
+ min = _mm_min_ps(min, (float4)_mm_shuffle_ps(min, min, 0x4e));
+ min = _mm_min_ps(min, (float4)_mm_shuffle_ps(min, min, 0xb1));
+
+ // It is slightly faster to do this part in scalar code when count < 8. However, the common case for
+ // this where it actually makes a difference is handled in the early out at the top of the function,
+ // so it is less than a 1% difference here. I opted for improved code size, fewer branches and reduced
+ // complexity, and removed it.
+
+ dotmin = min;
+
+ // scan for the first occurence of min in the array
+ size_t test;
+ for (index = 0; 0 == (test = _mm_movemask_ps(_mm_cmpeq_ps(stack_array[index], min))); index++) // local_count must be a multiple of 4
+ {
+ }
+ minIndex = 4 * index + segment + indexTable[test];
+ }
+
+ _mm_store_ss(dotResult, dotmin);
+ return minIndex;
}
-
#elif defined B3_USE_NEON
-#define ARM_NEON_GCC_COMPATIBILITY 1
+#define ARM_NEON_GCC_COMPATIBILITY 1
#include <arm_neon.h>
+static long b3_maxdot_large_v0(const float *vv, const float *vec, unsigned long count, float *dotResult);
+static long b3_maxdot_large_v1(const float *vv, const float *vec, unsigned long count, float *dotResult);
+static long b3_maxdot_large_sel(const float *vv, const float *vec, unsigned long count, float *dotResult);
+static long b3_mindot_large_v0(const float *vv, const float *vec, unsigned long count, float *dotResult);
+static long b3_mindot_large_v1(const float *vv, const float *vec, unsigned long count, float *dotResult);
+static long b3_mindot_large_sel(const float *vv, const float *vec, unsigned long count, float *dotResult);
-static long b3_maxdot_large_v0( const float *vv, const float *vec, unsigned long count, float *dotResult );
-static long b3_maxdot_large_v1( const float *vv, const float *vec, unsigned long count, float *dotResult );
-static long b3_maxdot_large_sel( const float *vv, const float *vec, unsigned long count, float *dotResult );
-static long b3_mindot_large_v0( const float *vv, const float *vec, unsigned long count, float *dotResult );
-static long b3_mindot_large_v1( const float *vv, const float *vec, unsigned long count, float *dotResult );
-static long b3_mindot_large_sel( const float *vv, const float *vec, unsigned long count, float *dotResult );
+long (*b3_maxdot_large)(const float *vv, const float *vec, unsigned long count, float *dotResult) = b3_maxdot_large_sel;
+long (*b3_mindot_large)(const float *vv, const float *vec, unsigned long count, float *dotResult) = b3_mindot_large_sel;
-long (*b3_maxdot_large)( const float *vv, const float *vec, unsigned long count, float *dotResult ) = b3_maxdot_large_sel;
-long (*b3_mindot_large)( const float *vv, const float *vec, unsigned long count, float *dotResult ) = b3_mindot_large_sel;
-
-extern "C" {int _get_cpu_capabilities( void );}
-
-static long b3_maxdot_large_sel( const float *vv, const float *vec, unsigned long count, float *dotResult )
+extern "C"
{
- if( _get_cpu_capabilities() & 0x2000 )
- b3_maxdot_large = _maxdot_large_v1;
- else
- b3_maxdot_large = _maxdot_large_v0;
-
- return b3_maxdot_large(vv, vec, count, dotResult);
+ int _get_cpu_capabilities(void);
}
-static long b3_mindot_large_sel( const float *vv, const float *vec, unsigned long count, float *dotResult )
+static long b3_maxdot_large_sel(const float *vv, const float *vec, unsigned long count, float *dotResult)
{
- if( _get_cpu_capabilities() & 0x2000 )
- b3_mindot_large = _mindot_large_v1;
- else
- b3_mindot_large = _mindot_large_v0;
+ if (_get_cpu_capabilities() & 0x2000)
+ b3_maxdot_large = _maxdot_large_v1;
+ else
+ b3_maxdot_large = _maxdot_large_v0;
- return b3_mindot_large(vv, vec, count, dotResult);
+ return b3_maxdot_large(vv, vec, count, dotResult);
}
+static long b3_mindot_large_sel(const float *vv, const float *vec, unsigned long count, float *dotResult)
+{
+ if (_get_cpu_capabilities() & 0x2000)
+ b3_mindot_large = _mindot_large_v1;
+ else
+ b3_mindot_large = _mindot_large_v0;
+ return b3_mindot_large(vv, vec, count, dotResult);
+}
-#define vld1q_f32_aligned_postincrement( _ptr ) ({ float32x4_t _r; asm( "vld1.f32 {%0}, [%1, :128]!\n" : "=w" (_r), "+r" (_ptr) ); /*return*/ _r; })
-
+#define vld1q_f32_aligned_postincrement(_ptr) ({ float32x4_t _r; asm( "vld1.f32 {%0}, [%1, :128]!\n" : "=w" (_r), "+r" (_ptr) ); /*return*/ _r; })
-long b3_maxdot_large_v0( const float *vv, const float *vec, unsigned long count, float *dotResult )
+long b3_maxdot_large_v0(const float *vv, const float *vec, unsigned long count, float *dotResult)
{
- unsigned long i = 0;
- float32x4_t vvec = vld1q_f32_aligned_postincrement( vec );
- float32x2_t vLo = vget_low_f32(vvec);
- float32x2_t vHi = vdup_lane_f32(vget_high_f32(vvec), 0);
- float32x2_t dotMaxLo = (float32x2_t) { -B3_INFINITY, -B3_INFINITY };
- float32x2_t dotMaxHi = (float32x2_t) { -B3_INFINITY, -B3_INFINITY };
- uint32x2_t indexLo = (uint32x2_t) {0, 1};
- uint32x2_t indexHi = (uint32x2_t) {2, 3};
- uint32x2_t iLo = (uint32x2_t) {-1, -1};
- uint32x2_t iHi = (uint32x2_t) {-1, -1};
- const uint32x2_t four = (uint32x2_t) {4,4};
-
- for( ; i+8 <= count; i+= 8 )
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
-
- float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
- float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
- float32x2_t xy2 = vmul_f32( vget_low_f32(v2), vLo);
- float32x2_t xy3 = vmul_f32( vget_low_f32(v3), vLo);
-
- float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
- float32x2x2_t z1 = vtrn_f32( vget_high_f32(v2), vget_high_f32(v3));
- float32x2_t zLo = vmul_f32( z0.val[0], vHi);
- float32x2_t zHi = vmul_f32( z1.val[0], vHi);
-
- float32x2_t rLo = vpadd_f32( xy0, xy1);
- float32x2_t rHi = vpadd_f32( xy2, xy3);
- rLo = vadd_f32(rLo, zLo);
- rHi = vadd_f32(rHi, zHi);
-
- uint32x2_t maskLo = vcgt_f32( rLo, dotMaxLo );
- uint32x2_t maskHi = vcgt_f32( rHi, dotMaxHi );
- dotMaxLo = vbsl_f32( maskLo, rLo, dotMaxLo);
- dotMaxHi = vbsl_f32( maskHi, rHi, dotMaxHi);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- iHi = vbsl_u32(maskHi, indexHi, iHi);
- indexLo = vadd_u32(indexLo, four);
- indexHi = vadd_u32(indexHi, four);
-
- v0 = vld1q_f32_aligned_postincrement( vv );
- v1 = vld1q_f32_aligned_postincrement( vv );
- v2 = vld1q_f32_aligned_postincrement( vv );
- v3 = vld1q_f32_aligned_postincrement( vv );
-
- xy0 = vmul_f32( vget_low_f32(v0), vLo);
- xy1 = vmul_f32( vget_low_f32(v1), vLo);
- xy2 = vmul_f32( vget_low_f32(v2), vLo);
- xy3 = vmul_f32( vget_low_f32(v3), vLo);
-
- z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
- z1 = vtrn_f32( vget_high_f32(v2), vget_high_f32(v3));
- zLo = vmul_f32( z0.val[0], vHi);
- zHi = vmul_f32( z1.val[0], vHi);
-
- rLo = vpadd_f32( xy0, xy1);
- rHi = vpadd_f32( xy2, xy3);
- rLo = vadd_f32(rLo, zLo);
- rHi = vadd_f32(rHi, zHi);
-
- maskLo = vcgt_f32( rLo, dotMaxLo );
- maskHi = vcgt_f32( rHi, dotMaxHi );
- dotMaxLo = vbsl_f32( maskLo, rLo, dotMaxLo);
- dotMaxHi = vbsl_f32( maskHi, rHi, dotMaxHi);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- iHi = vbsl_u32(maskHi, indexHi, iHi);
- indexLo = vadd_u32(indexLo, four);
- indexHi = vadd_u32(indexHi, four);
- }
-
- for( ; i+4 <= count; i+= 4 )
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
-
- float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
- float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
- float32x2_t xy2 = vmul_f32( vget_low_f32(v2), vLo);
- float32x2_t xy3 = vmul_f32( vget_low_f32(v3), vLo);
-
- float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
- float32x2x2_t z1 = vtrn_f32( vget_high_f32(v2), vget_high_f32(v3));
- float32x2_t zLo = vmul_f32( z0.val[0], vHi);
- float32x2_t zHi = vmul_f32( z1.val[0], vHi);
-
- float32x2_t rLo = vpadd_f32( xy0, xy1);
- float32x2_t rHi = vpadd_f32( xy2, xy3);
- rLo = vadd_f32(rLo, zLo);
- rHi = vadd_f32(rHi, zHi);
-
- uint32x2_t maskLo = vcgt_f32( rLo, dotMaxLo );
- uint32x2_t maskHi = vcgt_f32( rHi, dotMaxHi );
- dotMaxLo = vbsl_f32( maskLo, rLo, dotMaxLo);
- dotMaxHi = vbsl_f32( maskHi, rHi, dotMaxHi);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- iHi = vbsl_u32(maskHi, indexHi, iHi);
- indexLo = vadd_u32(indexLo, four);
- indexHi = vadd_u32(indexHi, four);
- }
-
- switch( count & 3 )
- {
- case 3:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
-
- float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
- float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
- float32x2_t xy2 = vmul_f32( vget_low_f32(v2), vLo);
-
- float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
- float32x2_t zLo = vmul_f32( z0.val[0], vHi);
- float32x2_t zHi = vmul_f32( vdup_lane_f32(vget_high_f32(v2), 0), vHi);
-
- float32x2_t rLo = vpadd_f32( xy0, xy1);
- float32x2_t rHi = vpadd_f32( xy2, xy2);
- rLo = vadd_f32(rLo, zLo);
- rHi = vadd_f32(rHi, zHi);
-
- uint32x2_t maskLo = vcgt_f32( rLo, dotMaxLo );
- uint32x2_t maskHi = vcgt_f32( rHi, dotMaxHi );
- dotMaxLo = vbsl_f32( maskLo, rLo, dotMaxLo);
- dotMaxHi = vbsl_f32( maskHi, rHi, dotMaxHi);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- iHi = vbsl_u32(maskHi, indexHi, iHi);
- }
- break;
- case 2:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
-
- float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
- float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
-
- float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
- float32x2_t zLo = vmul_f32( z0.val[0], vHi);
-
- float32x2_t rLo = vpadd_f32( xy0, xy1);
- rLo = vadd_f32(rLo, zLo);
-
- uint32x2_t maskLo = vcgt_f32( rLo, dotMaxLo );
- dotMaxLo = vbsl_f32( maskLo, rLo, dotMaxLo);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- }
- break;
- case 1:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
- float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
- float32x2_t z0 = vdup_lane_f32(vget_high_f32(v0), 0);
- float32x2_t zLo = vmul_f32( z0, vHi);
- float32x2_t rLo = vpadd_f32( xy0, xy0);
- rLo = vadd_f32(rLo, zLo);
- uint32x2_t maskLo = vcgt_f32( rLo, dotMaxLo );
- dotMaxLo = vbsl_f32( maskLo, rLo, dotMaxLo);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- }
- break;
-
- default:
- break;
- }
-
- // select best answer between hi and lo results
- uint32x2_t mask = vcgt_f32( dotMaxHi, dotMaxLo );
- dotMaxLo = vbsl_f32(mask, dotMaxHi, dotMaxLo);
- iLo = vbsl_u32(mask, iHi, iLo);
-
- // select best answer between even and odd results
- dotMaxHi = vdup_lane_f32(dotMaxLo, 1);
- iHi = vdup_lane_u32(iLo, 1);
- mask = vcgt_f32( dotMaxHi, dotMaxLo );
- dotMaxLo = vbsl_f32(mask, dotMaxHi, dotMaxLo);
- iLo = vbsl_u32(mask, iHi, iLo);
-
- *dotResult = vget_lane_f32( dotMaxLo, 0);
- return vget_lane_u32(iLo, 0);
+ unsigned long i = 0;
+ float32x4_t vvec = vld1q_f32_aligned_postincrement(vec);
+ float32x2_t vLo = vget_low_f32(vvec);
+ float32x2_t vHi = vdup_lane_f32(vget_high_f32(vvec), 0);
+ float32x2_t dotMaxLo = (float32x2_t){-B3_INFINITY, -B3_INFINITY};
+ float32x2_t dotMaxHi = (float32x2_t){-B3_INFINITY, -B3_INFINITY};
+ uint32x2_t indexLo = (uint32x2_t){0, 1};
+ uint32x2_t indexHi = (uint32x2_t){2, 3};
+ uint32x2_t iLo = (uint32x2_t){-1, -1};
+ uint32x2_t iHi = (uint32x2_t){-1, -1};
+ const uint32x2_t four = (uint32x2_t){4, 4};
+
+ for (; i + 8 <= count; i += 8)
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
+
+ float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
+ float32x2_t xy2 = vmul_f32(vget_low_f32(v2), vLo);
+ float32x2_t xy3 = vmul_f32(vget_low_f32(v3), vLo);
+
+ float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+ float32x2x2_t z1 = vtrn_f32(vget_high_f32(v2), vget_high_f32(v3));
+ float32x2_t zLo = vmul_f32(z0.val[0], vHi);
+ float32x2_t zHi = vmul_f32(z1.val[0], vHi);
+
+ float32x2_t rLo = vpadd_f32(xy0, xy1);
+ float32x2_t rHi = vpadd_f32(xy2, xy3);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ uint32x2_t maskLo = vcgt_f32(rLo, dotMaxLo);
+ uint32x2_t maskHi = vcgt_f32(rHi, dotMaxHi);
+ dotMaxLo = vbsl_f32(maskLo, rLo, dotMaxLo);
+ dotMaxHi = vbsl_f32(maskHi, rHi, dotMaxHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ indexLo = vadd_u32(indexLo, four);
+ indexHi = vadd_u32(indexHi, four);
+
+ v0 = vld1q_f32_aligned_postincrement(vv);
+ v1 = vld1q_f32_aligned_postincrement(vv);
+ v2 = vld1q_f32_aligned_postincrement(vv);
+ v3 = vld1q_f32_aligned_postincrement(vv);
+
+ xy0 = vmul_f32(vget_low_f32(v0), vLo);
+ xy1 = vmul_f32(vget_low_f32(v1), vLo);
+ xy2 = vmul_f32(vget_low_f32(v2), vLo);
+ xy3 = vmul_f32(vget_low_f32(v3), vLo);
+
+ z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+ z1 = vtrn_f32(vget_high_f32(v2), vget_high_f32(v3));
+ zLo = vmul_f32(z0.val[0], vHi);
+ zHi = vmul_f32(z1.val[0], vHi);
+
+ rLo = vpadd_f32(xy0, xy1);
+ rHi = vpadd_f32(xy2, xy3);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ maskLo = vcgt_f32(rLo, dotMaxLo);
+ maskHi = vcgt_f32(rHi, dotMaxHi);
+ dotMaxLo = vbsl_f32(maskLo, rLo, dotMaxLo);
+ dotMaxHi = vbsl_f32(maskHi, rHi, dotMaxHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ indexLo = vadd_u32(indexLo, four);
+ indexHi = vadd_u32(indexHi, four);
+ }
+
+ for (; i + 4 <= count; i += 4)
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
+
+ float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
+ float32x2_t xy2 = vmul_f32(vget_low_f32(v2), vLo);
+ float32x2_t xy3 = vmul_f32(vget_low_f32(v3), vLo);
+
+ float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+ float32x2x2_t z1 = vtrn_f32(vget_high_f32(v2), vget_high_f32(v3));
+ float32x2_t zLo = vmul_f32(z0.val[0], vHi);
+ float32x2_t zHi = vmul_f32(z1.val[0], vHi);
+
+ float32x2_t rLo = vpadd_f32(xy0, xy1);
+ float32x2_t rHi = vpadd_f32(xy2, xy3);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ uint32x2_t maskLo = vcgt_f32(rLo, dotMaxLo);
+ uint32x2_t maskHi = vcgt_f32(rHi, dotMaxHi);
+ dotMaxLo = vbsl_f32(maskLo, rLo, dotMaxLo);
+ dotMaxHi = vbsl_f32(maskHi, rHi, dotMaxHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ indexLo = vadd_u32(indexLo, four);
+ indexHi = vadd_u32(indexHi, four);
+ }
+
+ switch (count & 3)
+ {
+ case 3:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+
+ float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
+ float32x2_t xy2 = vmul_f32(vget_low_f32(v2), vLo);
+
+ float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+ float32x2_t zLo = vmul_f32(z0.val[0], vHi);
+ float32x2_t zHi = vmul_f32(vdup_lane_f32(vget_high_f32(v2), 0), vHi);
+
+ float32x2_t rLo = vpadd_f32(xy0, xy1);
+ float32x2_t rHi = vpadd_f32(xy2, xy2);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ uint32x2_t maskLo = vcgt_f32(rLo, dotMaxLo);
+ uint32x2_t maskHi = vcgt_f32(rHi, dotMaxHi);
+ dotMaxLo = vbsl_f32(maskLo, rLo, dotMaxLo);
+ dotMaxHi = vbsl_f32(maskHi, rHi, dotMaxHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ }
+ break;
+ case 2:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+
+ float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
+
+ float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+ float32x2_t zLo = vmul_f32(z0.val[0], vHi);
+
+ float32x2_t rLo = vpadd_f32(xy0, xy1);
+ rLo = vadd_f32(rLo, zLo);
+
+ uint32x2_t maskLo = vcgt_f32(rLo, dotMaxLo);
+ dotMaxLo = vbsl_f32(maskLo, rLo, dotMaxLo);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ }
+ break;
+ case 1:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+ float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+ float32x2_t z0 = vdup_lane_f32(vget_high_f32(v0), 0);
+ float32x2_t zLo = vmul_f32(z0, vHi);
+ float32x2_t rLo = vpadd_f32(xy0, xy0);
+ rLo = vadd_f32(rLo, zLo);
+ uint32x2_t maskLo = vcgt_f32(rLo, dotMaxLo);
+ dotMaxLo = vbsl_f32(maskLo, rLo, dotMaxLo);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ // select best answer between hi and lo results
+ uint32x2_t mask = vcgt_f32(dotMaxHi, dotMaxLo);
+ dotMaxLo = vbsl_f32(mask, dotMaxHi, dotMaxLo);
+ iLo = vbsl_u32(mask, iHi, iLo);
+
+ // select best answer between even and odd results
+ dotMaxHi = vdup_lane_f32(dotMaxLo, 1);
+ iHi = vdup_lane_u32(iLo, 1);
+ mask = vcgt_f32(dotMaxHi, dotMaxLo);
+ dotMaxLo = vbsl_f32(mask, dotMaxHi, dotMaxLo);
+ iLo = vbsl_u32(mask, iHi, iLo);
+
+ *dotResult = vget_lane_f32(dotMaxLo, 0);
+ return vget_lane_u32(iLo, 0);
}
-
-long b3_maxdot_large_v1( const float *vv, const float *vec, unsigned long count, float *dotResult )
+long b3_maxdot_large_v1(const float *vv, const float *vec, unsigned long count, float *dotResult)
{
- float32x4_t vvec = vld1q_f32_aligned_postincrement( vec );
- float32x4_t vLo = vcombine_f32(vget_low_f32(vvec), vget_low_f32(vvec));
- float32x4_t vHi = vdupq_lane_f32(vget_high_f32(vvec), 0);
- const uint32x4_t four = (uint32x4_t){ 4, 4, 4, 4 };
- uint32x4_t local_index = (uint32x4_t) {0, 1, 2, 3};
- uint32x4_t index = (uint32x4_t) { -1, -1, -1, -1 };
- float32x4_t maxDot = (float32x4_t) { -B3_INFINITY, -B3_INFINITY, -B3_INFINITY, -B3_INFINITY };
-
- unsigned long i = 0;
- for( ; i + 8 <= count; i += 8 )
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
- float32x4_t xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v3));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
- float32x4_t z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v3));
-
- xy0 = vmulq_f32(xy0, vLo);
- xy1 = vmulq_f32(xy1, vLo);
-
- float32x4x2_t zb = vuzpq_f32( z0, z1);
- float32x4_t z = vmulq_f32( zb.val[0], vHi);
- float32x4x2_t xy = vuzpq_f32( xy0, xy1);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcgtq_f32(x, maxDot);
- maxDot = vbslq_f32( mask, x, maxDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
-
- v0 = vld1q_f32_aligned_postincrement( vv );
- v1 = vld1q_f32_aligned_postincrement( vv );
- v2 = vld1q_f32_aligned_postincrement( vv );
- v3 = vld1q_f32_aligned_postincrement( vv );
-
- // the next two lines should resolve to a single vswp d, d
- xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
- xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v3));
- // the next two lines should resolve to a single vswp d, d
- z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
- z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v3));
-
- xy0 = vmulq_f32(xy0, vLo);
- xy1 = vmulq_f32(xy1, vLo);
-
- zb = vuzpq_f32( z0, z1);
- z = vmulq_f32( zb.val[0], vHi);
- xy = vuzpq_f32( xy0, xy1);
- x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- mask = vcgtq_f32(x, maxDot);
- maxDot = vbslq_f32( mask, x, maxDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
-
- for( ; i + 4 <= count; i += 4 )
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
- float32x4_t xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v3));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
- float32x4_t z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v3));
-
- xy0 = vmulq_f32(xy0, vLo);
- xy1 = vmulq_f32(xy1, vLo);
-
- float32x4x2_t zb = vuzpq_f32( z0, z1);
- float32x4_t z = vmulq_f32( zb.val[0], vHi);
- float32x4x2_t xy = vuzpq_f32( xy0, xy1);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcgtq_f32(x, maxDot);
- maxDot = vbslq_f32( mask, x, maxDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
-
- switch (count & 3) {
- case 3:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
- float32x4_t xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v2));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
- float32x4_t z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v2));
-
- xy0 = vmulq_f32(xy0, vLo);
- xy1 = vmulq_f32(xy1, vLo);
-
- float32x4x2_t zb = vuzpq_f32( z0, z1);
- float32x4_t z = vmulq_f32( zb.val[0], vHi);
- float32x4x2_t xy = vuzpq_f32( xy0, xy1);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcgtq_f32(x, maxDot);
- maxDot = vbslq_f32( mask, x, maxDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
- break;
-
- case 2:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
-
- xy0 = vmulq_f32(xy0, vLo);
-
- float32x4x2_t zb = vuzpq_f32( z0, z0);
- float32x4_t z = vmulq_f32( zb.val[0], vHi);
- float32x4x2_t xy = vuzpq_f32( xy0, xy0);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcgtq_f32(x, maxDot);
- maxDot = vbslq_f32( mask, x, maxDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
- break;
-
- case 1:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v0));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z = vdupq_lane_f32(vget_high_f32(v0), 0);
-
- xy0 = vmulq_f32(xy0, vLo);
-
- z = vmulq_f32( z, vHi);
- float32x4x2_t xy = vuzpq_f32( xy0, xy0);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcgtq_f32(x, maxDot);
- maxDot = vbslq_f32( mask, x, maxDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
- break;
-
- default:
- break;
- }
-
-
- // select best answer between hi and lo results
- uint32x2_t mask = vcgt_f32( vget_high_f32(maxDot), vget_low_f32(maxDot));
- float32x2_t maxDot2 = vbsl_f32(mask, vget_high_f32(maxDot), vget_low_f32(maxDot));
- uint32x2_t index2 = vbsl_u32(mask, vget_high_u32(index), vget_low_u32(index));
-
- // select best answer between even and odd results
- float32x2_t maxDotO = vdup_lane_f32(maxDot2, 1);
- uint32x2_t indexHi = vdup_lane_u32(index2, 1);
- mask = vcgt_f32( maxDotO, maxDot2 );
- maxDot2 = vbsl_f32(mask, maxDotO, maxDot2);
- index2 = vbsl_u32(mask, indexHi, index2);
-
- *dotResult = vget_lane_f32( maxDot2, 0);
- return vget_lane_u32(index2, 0);
-
+ float32x4_t vvec = vld1q_f32_aligned_postincrement(vec);
+ float32x4_t vLo = vcombine_f32(vget_low_f32(vvec), vget_low_f32(vvec));
+ float32x4_t vHi = vdupq_lane_f32(vget_high_f32(vvec), 0);
+ const uint32x4_t four = (uint32x4_t){4, 4, 4, 4};
+ uint32x4_t local_index = (uint32x4_t){0, 1, 2, 3};
+ uint32x4_t index = (uint32x4_t){-1, -1, -1, -1};
+ float32x4_t maxDot = (float32x4_t){-B3_INFINITY, -B3_INFINITY, -B3_INFINITY, -B3_INFINITY};
+
+ unsigned long i = 0;
+ for (; i + 8 <= count; i += 8)
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+ float32x4_t xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v3));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+ float32x4_t z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v3));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ float32x4x2_t zb = vuzpq_f32(z0, z1);
+ float32x4_t z = vmulq_f32(zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32(xy0, xy1);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcgtq_f32(x, maxDot);
+ maxDot = vbslq_f32(mask, x, maxDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+
+ v0 = vld1q_f32_aligned_postincrement(vv);
+ v1 = vld1q_f32_aligned_postincrement(vv);
+ v2 = vld1q_f32_aligned_postincrement(vv);
+ v3 = vld1q_f32_aligned_postincrement(vv);
+
+ // the next two lines should resolve to a single vswp d, d
+ xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+ xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v3));
+ // the next two lines should resolve to a single vswp d, d
+ z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+ z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v3));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ zb = vuzpq_f32(z0, z1);
+ z = vmulq_f32(zb.val[0], vHi);
+ xy = vuzpq_f32(xy0, xy1);
+ x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ mask = vcgtq_f32(x, maxDot);
+ maxDot = vbslq_f32(mask, x, maxDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+
+ for (; i + 4 <= count; i += 4)
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+ float32x4_t xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v3));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+ float32x4_t z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v3));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ float32x4x2_t zb = vuzpq_f32(z0, z1);
+ float32x4_t z = vmulq_f32(zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32(xy0, xy1);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcgtq_f32(x, maxDot);
+ maxDot = vbslq_f32(mask, x, maxDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+
+ switch (count & 3)
+ {
+ case 3:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+ float32x4_t xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v2));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+ float32x4_t z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v2));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ float32x4x2_t zb = vuzpq_f32(z0, z1);
+ float32x4_t z = vmulq_f32(zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32(xy0, xy1);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcgtq_f32(x, maxDot);
+ maxDot = vbslq_f32(mask, x, maxDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+ break;
+
+ case 2:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+
+ xy0 = vmulq_f32(xy0, vLo);
+
+ float32x4x2_t zb = vuzpq_f32(z0, z0);
+ float32x4_t z = vmulq_f32(zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32(xy0, xy0);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcgtq_f32(x, maxDot);
+ maxDot = vbslq_f32(mask, x, maxDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+ break;
+
+ case 1:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v0));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z = vdupq_lane_f32(vget_high_f32(v0), 0);
+
+ xy0 = vmulq_f32(xy0, vLo);
+
+ z = vmulq_f32(z, vHi);
+ float32x4x2_t xy = vuzpq_f32(xy0, xy0);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcgtq_f32(x, maxDot);
+ maxDot = vbslq_f32(mask, x, maxDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ // select best answer between hi and lo results
+ uint32x2_t mask = vcgt_f32(vget_high_f32(maxDot), vget_low_f32(maxDot));
+ float32x2_t maxDot2 = vbsl_f32(mask, vget_high_f32(maxDot), vget_low_f32(maxDot));
+ uint32x2_t index2 = vbsl_u32(mask, vget_high_u32(index), vget_low_u32(index));
+
+ // select best answer between even and odd results
+ float32x2_t maxDotO = vdup_lane_f32(maxDot2, 1);
+ uint32x2_t indexHi = vdup_lane_u32(index2, 1);
+ mask = vcgt_f32(maxDotO, maxDot2);
+ maxDot2 = vbsl_f32(mask, maxDotO, maxDot2);
+ index2 = vbsl_u32(mask, indexHi, index2);
+
+ *dotResult = vget_lane_f32(maxDot2, 0);
+ return vget_lane_u32(index2, 0);
}
-long b3_mindot_large_v0( const float *vv, const float *vec, unsigned long count, float *dotResult )
+long b3_mindot_large_v0(const float *vv, const float *vec, unsigned long count, float *dotResult)
{
- unsigned long i = 0;
- float32x4_t vvec = vld1q_f32_aligned_postincrement( vec );
- float32x2_t vLo = vget_low_f32(vvec);
- float32x2_t vHi = vdup_lane_f32(vget_high_f32(vvec), 0);
- float32x2_t dotMinLo = (float32x2_t) { B3_INFINITY, B3_INFINITY };
- float32x2_t dotMinHi = (float32x2_t) { B3_INFINITY, B3_INFINITY };
- uint32x2_t indexLo = (uint32x2_t) {0, 1};
- uint32x2_t indexHi = (uint32x2_t) {2, 3};
- uint32x2_t iLo = (uint32x2_t) {-1, -1};
- uint32x2_t iHi = (uint32x2_t) {-1, -1};
- const uint32x2_t four = (uint32x2_t) {4,4};
-
- for( ; i+8 <= count; i+= 8 )
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
-
- float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
- float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
- float32x2_t xy2 = vmul_f32( vget_low_f32(v2), vLo);
- float32x2_t xy3 = vmul_f32( vget_low_f32(v3), vLo);
-
- float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
- float32x2x2_t z1 = vtrn_f32( vget_high_f32(v2), vget_high_f32(v3));
- float32x2_t zLo = vmul_f32( z0.val[0], vHi);
- float32x2_t zHi = vmul_f32( z1.val[0], vHi);
-
- float32x2_t rLo = vpadd_f32( xy0, xy1);
- float32x2_t rHi = vpadd_f32( xy2, xy3);
- rLo = vadd_f32(rLo, zLo);
- rHi = vadd_f32(rHi, zHi);
-
- uint32x2_t maskLo = vclt_f32( rLo, dotMinLo );
- uint32x2_t maskHi = vclt_f32( rHi, dotMinHi );
- dotMinLo = vbsl_f32( maskLo, rLo, dotMinLo);
- dotMinHi = vbsl_f32( maskHi, rHi, dotMinHi);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- iHi = vbsl_u32(maskHi, indexHi, iHi);
- indexLo = vadd_u32(indexLo, four);
- indexHi = vadd_u32(indexHi, four);
-
- v0 = vld1q_f32_aligned_postincrement( vv );
- v1 = vld1q_f32_aligned_postincrement( vv );
- v2 = vld1q_f32_aligned_postincrement( vv );
- v3 = vld1q_f32_aligned_postincrement( vv );
-
- xy0 = vmul_f32( vget_low_f32(v0), vLo);
- xy1 = vmul_f32( vget_low_f32(v1), vLo);
- xy2 = vmul_f32( vget_low_f32(v2), vLo);
- xy3 = vmul_f32( vget_low_f32(v3), vLo);
-
- z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
- z1 = vtrn_f32( vget_high_f32(v2), vget_high_f32(v3));
- zLo = vmul_f32( z0.val[0], vHi);
- zHi = vmul_f32( z1.val[0], vHi);
-
- rLo = vpadd_f32( xy0, xy1);
- rHi = vpadd_f32( xy2, xy3);
- rLo = vadd_f32(rLo, zLo);
- rHi = vadd_f32(rHi, zHi);
-
- maskLo = vclt_f32( rLo, dotMinLo );
- maskHi = vclt_f32( rHi, dotMinHi );
- dotMinLo = vbsl_f32( maskLo, rLo, dotMinLo);
- dotMinHi = vbsl_f32( maskHi, rHi, dotMinHi);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- iHi = vbsl_u32(maskHi, indexHi, iHi);
- indexLo = vadd_u32(indexLo, four);
- indexHi = vadd_u32(indexHi, four);
- }
-
- for( ; i+4 <= count; i+= 4 )
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
-
- float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
- float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
- float32x2_t xy2 = vmul_f32( vget_low_f32(v2), vLo);
- float32x2_t xy3 = vmul_f32( vget_low_f32(v3), vLo);
-
- float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
- float32x2x2_t z1 = vtrn_f32( vget_high_f32(v2), vget_high_f32(v3));
- float32x2_t zLo = vmul_f32( z0.val[0], vHi);
- float32x2_t zHi = vmul_f32( z1.val[0], vHi);
-
- float32x2_t rLo = vpadd_f32( xy0, xy1);
- float32x2_t rHi = vpadd_f32( xy2, xy3);
- rLo = vadd_f32(rLo, zLo);
- rHi = vadd_f32(rHi, zHi);
-
- uint32x2_t maskLo = vclt_f32( rLo, dotMinLo );
- uint32x2_t maskHi = vclt_f32( rHi, dotMinHi );
- dotMinLo = vbsl_f32( maskLo, rLo, dotMinLo);
- dotMinHi = vbsl_f32( maskHi, rHi, dotMinHi);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- iHi = vbsl_u32(maskHi, indexHi, iHi);
- indexLo = vadd_u32(indexLo, four);
- indexHi = vadd_u32(indexHi, four);
- }
- switch( count & 3 )
- {
- case 3:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
-
- float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
- float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
- float32x2_t xy2 = vmul_f32( vget_low_f32(v2), vLo);
-
- float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
- float32x2_t zLo = vmul_f32( z0.val[0], vHi);
- float32x2_t zHi = vmul_f32( vdup_lane_f32(vget_high_f32(v2), 0), vHi);
-
- float32x2_t rLo = vpadd_f32( xy0, xy1);
- float32x2_t rHi = vpadd_f32( xy2, xy2);
- rLo = vadd_f32(rLo, zLo);
- rHi = vadd_f32(rHi, zHi);
-
- uint32x2_t maskLo = vclt_f32( rLo, dotMinLo );
- uint32x2_t maskHi = vclt_f32( rHi, dotMinHi );
- dotMinLo = vbsl_f32( maskLo, rLo, dotMinLo);
- dotMinHi = vbsl_f32( maskHi, rHi, dotMinHi);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- iHi = vbsl_u32(maskHi, indexHi, iHi);
- }
- break;
- case 2:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
-
- float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
- float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
-
- float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
- float32x2_t zLo = vmul_f32( z0.val[0], vHi);
-
- float32x2_t rLo = vpadd_f32( xy0, xy1);
- rLo = vadd_f32(rLo, zLo);
-
- uint32x2_t maskLo = vclt_f32( rLo, dotMinLo );
- dotMinLo = vbsl_f32( maskLo, rLo, dotMinLo);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- }
- break;
- case 1:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
- float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
- float32x2_t z0 = vdup_lane_f32(vget_high_f32(v0), 0);
- float32x2_t zLo = vmul_f32( z0, vHi);
- float32x2_t rLo = vpadd_f32( xy0, xy0);
- rLo = vadd_f32(rLo, zLo);
- uint32x2_t maskLo = vclt_f32( rLo, dotMinLo );
- dotMinLo = vbsl_f32( maskLo, rLo, dotMinLo);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- }
- break;
-
- default:
- break;
- }
-
- // select best answer between hi and lo results
- uint32x2_t mask = vclt_f32( dotMinHi, dotMinLo );
- dotMinLo = vbsl_f32(mask, dotMinHi, dotMinLo);
- iLo = vbsl_u32(mask, iHi, iLo);
-
- // select best answer between even and odd results
- dotMinHi = vdup_lane_f32(dotMinLo, 1);
- iHi = vdup_lane_u32(iLo, 1);
- mask = vclt_f32( dotMinHi, dotMinLo );
- dotMinLo = vbsl_f32(mask, dotMinHi, dotMinLo);
- iLo = vbsl_u32(mask, iHi, iLo);
-
- *dotResult = vget_lane_f32( dotMinLo, 0);
- return vget_lane_u32(iLo, 0);
+ unsigned long i = 0;
+ float32x4_t vvec = vld1q_f32_aligned_postincrement(vec);
+ float32x2_t vLo = vget_low_f32(vvec);
+ float32x2_t vHi = vdup_lane_f32(vget_high_f32(vvec), 0);
+ float32x2_t dotMinLo = (float32x2_t){B3_INFINITY, B3_INFINITY};
+ float32x2_t dotMinHi = (float32x2_t){B3_INFINITY, B3_INFINITY};
+ uint32x2_t indexLo = (uint32x2_t){0, 1};
+ uint32x2_t indexHi = (uint32x2_t){2, 3};
+ uint32x2_t iLo = (uint32x2_t){-1, -1};
+ uint32x2_t iHi = (uint32x2_t){-1, -1};
+ const uint32x2_t four = (uint32x2_t){4, 4};
+
+ for (; i + 8 <= count; i += 8)
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
+
+ float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
+ float32x2_t xy2 = vmul_f32(vget_low_f32(v2), vLo);
+ float32x2_t xy3 = vmul_f32(vget_low_f32(v3), vLo);
+
+ float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+ float32x2x2_t z1 = vtrn_f32(vget_high_f32(v2), vget_high_f32(v3));
+ float32x2_t zLo = vmul_f32(z0.val[0], vHi);
+ float32x2_t zHi = vmul_f32(z1.val[0], vHi);
+
+ float32x2_t rLo = vpadd_f32(xy0, xy1);
+ float32x2_t rHi = vpadd_f32(xy2, xy3);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ uint32x2_t maskLo = vclt_f32(rLo, dotMinLo);
+ uint32x2_t maskHi = vclt_f32(rHi, dotMinHi);
+ dotMinLo = vbsl_f32(maskLo, rLo, dotMinLo);
+ dotMinHi = vbsl_f32(maskHi, rHi, dotMinHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ indexLo = vadd_u32(indexLo, four);
+ indexHi = vadd_u32(indexHi, four);
+
+ v0 = vld1q_f32_aligned_postincrement(vv);
+ v1 = vld1q_f32_aligned_postincrement(vv);
+ v2 = vld1q_f32_aligned_postincrement(vv);
+ v3 = vld1q_f32_aligned_postincrement(vv);
+
+ xy0 = vmul_f32(vget_low_f32(v0), vLo);
+ xy1 = vmul_f32(vget_low_f32(v1), vLo);
+ xy2 = vmul_f32(vget_low_f32(v2), vLo);
+ xy3 = vmul_f32(vget_low_f32(v3), vLo);
+
+ z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+ z1 = vtrn_f32(vget_high_f32(v2), vget_high_f32(v3));
+ zLo = vmul_f32(z0.val[0], vHi);
+ zHi = vmul_f32(z1.val[0], vHi);
+
+ rLo = vpadd_f32(xy0, xy1);
+ rHi = vpadd_f32(xy2, xy3);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ maskLo = vclt_f32(rLo, dotMinLo);
+ maskHi = vclt_f32(rHi, dotMinHi);
+ dotMinLo = vbsl_f32(maskLo, rLo, dotMinLo);
+ dotMinHi = vbsl_f32(maskHi, rHi, dotMinHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ indexLo = vadd_u32(indexLo, four);
+ indexHi = vadd_u32(indexHi, four);
+ }
+
+ for (; i + 4 <= count; i += 4)
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
+
+ float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
+ float32x2_t xy2 = vmul_f32(vget_low_f32(v2), vLo);
+ float32x2_t xy3 = vmul_f32(vget_low_f32(v3), vLo);
+
+ float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+ float32x2x2_t z1 = vtrn_f32(vget_high_f32(v2), vget_high_f32(v3));
+ float32x2_t zLo = vmul_f32(z0.val[0], vHi);
+ float32x2_t zHi = vmul_f32(z1.val[0], vHi);
+
+ float32x2_t rLo = vpadd_f32(xy0, xy1);
+ float32x2_t rHi = vpadd_f32(xy2, xy3);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ uint32x2_t maskLo = vclt_f32(rLo, dotMinLo);
+ uint32x2_t maskHi = vclt_f32(rHi, dotMinHi);
+ dotMinLo = vbsl_f32(maskLo, rLo, dotMinLo);
+ dotMinHi = vbsl_f32(maskHi, rHi, dotMinHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ indexLo = vadd_u32(indexLo, four);
+ indexHi = vadd_u32(indexHi, four);
+ }
+ switch (count & 3)
+ {
+ case 3:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+
+ float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
+ float32x2_t xy2 = vmul_f32(vget_low_f32(v2), vLo);
+
+ float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+ float32x2_t zLo = vmul_f32(z0.val[0], vHi);
+ float32x2_t zHi = vmul_f32(vdup_lane_f32(vget_high_f32(v2), 0), vHi);
+
+ float32x2_t rLo = vpadd_f32(xy0, xy1);
+ float32x2_t rHi = vpadd_f32(xy2, xy2);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ uint32x2_t maskLo = vclt_f32(rLo, dotMinLo);
+ uint32x2_t maskHi = vclt_f32(rHi, dotMinHi);
+ dotMinLo = vbsl_f32(maskLo, rLo, dotMinLo);
+ dotMinHi = vbsl_f32(maskHi, rHi, dotMinHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ }
+ break;
+ case 2:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+
+ float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
+
+ float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+ float32x2_t zLo = vmul_f32(z0.val[0], vHi);
+
+ float32x2_t rLo = vpadd_f32(xy0, xy1);
+ rLo = vadd_f32(rLo, zLo);
+
+ uint32x2_t maskLo = vclt_f32(rLo, dotMinLo);
+ dotMinLo = vbsl_f32(maskLo, rLo, dotMinLo);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ }
+ break;
+ case 1:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+ float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+ float32x2_t z0 = vdup_lane_f32(vget_high_f32(v0), 0);
+ float32x2_t zLo = vmul_f32(z0, vHi);
+ float32x2_t rLo = vpadd_f32(xy0, xy0);
+ rLo = vadd_f32(rLo, zLo);
+ uint32x2_t maskLo = vclt_f32(rLo, dotMinLo);
+ dotMinLo = vbsl_f32(maskLo, rLo, dotMinLo);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ // select best answer between hi and lo results
+ uint32x2_t mask = vclt_f32(dotMinHi, dotMinLo);
+ dotMinLo = vbsl_f32(mask, dotMinHi, dotMinLo);
+ iLo = vbsl_u32(mask, iHi, iLo);
+
+ // select best answer between even and odd results
+ dotMinHi = vdup_lane_f32(dotMinLo, 1);
+ iHi = vdup_lane_u32(iLo, 1);
+ mask = vclt_f32(dotMinHi, dotMinLo);
+ dotMinLo = vbsl_f32(mask, dotMinHi, dotMinLo);
+ iLo = vbsl_u32(mask, iHi, iLo);
+
+ *dotResult = vget_lane_f32(dotMinLo, 0);
+ return vget_lane_u32(iLo, 0);
}
-long b3_mindot_large_v1( const float *vv, const float *vec, unsigned long count, float *dotResult )
+long b3_mindot_large_v1(const float *vv, const float *vec, unsigned long count, float *dotResult)
{
- float32x4_t vvec = vld1q_f32_aligned_postincrement( vec );
- float32x4_t vLo = vcombine_f32(vget_low_f32(vvec), vget_low_f32(vvec));
- float32x4_t vHi = vdupq_lane_f32(vget_high_f32(vvec), 0);
- const uint32x4_t four = (uint32x4_t){ 4, 4, 4, 4 };
- uint32x4_t local_index = (uint32x4_t) {0, 1, 2, 3};
- uint32x4_t index = (uint32x4_t) { -1, -1, -1, -1 };
- float32x4_t minDot = (float32x4_t) { B3_INFINITY, B3_INFINITY, B3_INFINITY, B3_INFINITY };
-
- unsigned long i = 0;
- for( ; i + 8 <= count; i += 8 )
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
- float32x4_t xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v3));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
- float32x4_t z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v3));
-
- xy0 = vmulq_f32(xy0, vLo);
- xy1 = vmulq_f32(xy1, vLo);
-
- float32x4x2_t zb = vuzpq_f32( z0, z1);
- float32x4_t z = vmulq_f32( zb.val[0], vHi);
- float32x4x2_t xy = vuzpq_f32( xy0, xy1);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcltq_f32(x, minDot);
- minDot = vbslq_f32( mask, x, minDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
-
- v0 = vld1q_f32_aligned_postincrement( vv );
- v1 = vld1q_f32_aligned_postincrement( vv );
- v2 = vld1q_f32_aligned_postincrement( vv );
- v3 = vld1q_f32_aligned_postincrement( vv );
-
- // the next two lines should resolve to a single vswp d, d
- xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
- xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v3));
- // the next two lines should resolve to a single vswp d, d
- z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
- z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v3));
-
- xy0 = vmulq_f32(xy0, vLo);
- xy1 = vmulq_f32(xy1, vLo);
-
- zb = vuzpq_f32( z0, z1);
- z = vmulq_f32( zb.val[0], vHi);
- xy = vuzpq_f32( xy0, xy1);
- x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- mask = vcltq_f32(x, minDot);
- minDot = vbslq_f32( mask, x, minDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
-
- for( ; i + 4 <= count; i += 4 )
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
- float32x4_t xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v3));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
- float32x4_t z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v3));
-
- xy0 = vmulq_f32(xy0, vLo);
- xy1 = vmulq_f32(xy1, vLo);
-
- float32x4x2_t zb = vuzpq_f32( z0, z1);
- float32x4_t z = vmulq_f32( zb.val[0], vHi);
- float32x4x2_t xy = vuzpq_f32( xy0, xy1);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcltq_f32(x, minDot);
- minDot = vbslq_f32( mask, x, minDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
-
- switch (count & 3) {
- case 3:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
- float32x4_t xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v2));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
- float32x4_t z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v2));
-
- xy0 = vmulq_f32(xy0, vLo);
- xy1 = vmulq_f32(xy1, vLo);
-
- float32x4x2_t zb = vuzpq_f32( z0, z1);
- float32x4_t z = vmulq_f32( zb.val[0], vHi);
- float32x4x2_t xy = vuzpq_f32( xy0, xy1);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcltq_f32(x, minDot);
- minDot = vbslq_f32( mask, x, minDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
- break;
-
- case 2:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
-
- xy0 = vmulq_f32(xy0, vLo);
-
- float32x4x2_t zb = vuzpq_f32( z0, z0);
- float32x4_t z = vmulq_f32( zb.val[0], vHi);
- float32x4x2_t xy = vuzpq_f32( xy0, xy0);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcltq_f32(x, minDot);
- minDot = vbslq_f32( mask, x, minDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
- break;
-
- case 1:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v0));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z = vdupq_lane_f32(vget_high_f32(v0), 0);
-
- xy0 = vmulq_f32(xy0, vLo);
-
- z = vmulq_f32( z, vHi);
- float32x4x2_t xy = vuzpq_f32( xy0, xy0);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcltq_f32(x, minDot);
- minDot = vbslq_f32( mask, x, minDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
- break;
-
- default:
- break;
- }
-
-
- // select best answer between hi and lo results
- uint32x2_t mask = vclt_f32( vget_high_f32(minDot), vget_low_f32(minDot));
- float32x2_t minDot2 = vbsl_f32(mask, vget_high_f32(minDot), vget_low_f32(minDot));
- uint32x2_t index2 = vbsl_u32(mask, vget_high_u32(index), vget_low_u32(index));
-
- // select best answer between even and odd results
- float32x2_t minDotO = vdup_lane_f32(minDot2, 1);
- uint32x2_t indexHi = vdup_lane_u32(index2, 1);
- mask = vclt_f32( minDotO, minDot2 );
- minDot2 = vbsl_f32(mask, minDotO, minDot2);
- index2 = vbsl_u32(mask, indexHi, index2);
-
- *dotResult = vget_lane_f32( minDot2, 0);
- return vget_lane_u32(index2, 0);
-
+ float32x4_t vvec = vld1q_f32_aligned_postincrement(vec);
+ float32x4_t vLo = vcombine_f32(vget_low_f32(vvec), vget_low_f32(vvec));
+ float32x4_t vHi = vdupq_lane_f32(vget_high_f32(vvec), 0);
+ const uint32x4_t four = (uint32x4_t){4, 4, 4, 4};
+ uint32x4_t local_index = (uint32x4_t){0, 1, 2, 3};
+ uint32x4_t index = (uint32x4_t){-1, -1, -1, -1};
+ float32x4_t minDot = (float32x4_t){B3_INFINITY, B3_INFINITY, B3_INFINITY, B3_INFINITY};
+
+ unsigned long i = 0;
+ for (; i + 8 <= count; i += 8)
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+ float32x4_t xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v3));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+ float32x4_t z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v3));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ float32x4x2_t zb = vuzpq_f32(z0, z1);
+ float32x4_t z = vmulq_f32(zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32(xy0, xy1);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcltq_f32(x, minDot);
+ minDot = vbslq_f32(mask, x, minDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+
+ v0 = vld1q_f32_aligned_postincrement(vv);
+ v1 = vld1q_f32_aligned_postincrement(vv);
+ v2 = vld1q_f32_aligned_postincrement(vv);
+ v3 = vld1q_f32_aligned_postincrement(vv);
+
+ // the next two lines should resolve to a single vswp d, d
+ xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+ xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v3));
+ // the next two lines should resolve to a single vswp d, d
+ z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+ z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v3));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ zb = vuzpq_f32(z0, z1);
+ z = vmulq_f32(zb.val[0], vHi);
+ xy = vuzpq_f32(xy0, xy1);
+ x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ mask = vcltq_f32(x, minDot);
+ minDot = vbslq_f32(mask, x, minDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+
+ for (; i + 4 <= count; i += 4)
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+ float32x4_t xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v3));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+ float32x4_t z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v3));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ float32x4x2_t zb = vuzpq_f32(z0, z1);
+ float32x4_t z = vmulq_f32(zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32(xy0, xy1);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcltq_f32(x, minDot);
+ minDot = vbslq_f32(mask, x, minDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+
+ switch (count & 3)
+ {
+ case 3:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+ float32x4_t xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v2));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+ float32x4_t z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v2));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ float32x4x2_t zb = vuzpq_f32(z0, z1);
+ float32x4_t z = vmulq_f32(zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32(xy0, xy1);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcltq_f32(x, minDot);
+ minDot = vbslq_f32(mask, x, minDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+ break;
+
+ case 2:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+
+ xy0 = vmulq_f32(xy0, vLo);
+
+ float32x4x2_t zb = vuzpq_f32(z0, z0);
+ float32x4_t z = vmulq_f32(zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32(xy0, xy0);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcltq_f32(x, minDot);
+ minDot = vbslq_f32(mask, x, minDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+ break;
+
+ case 1:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v0));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z = vdupq_lane_f32(vget_high_f32(v0), 0);
+
+ xy0 = vmulq_f32(xy0, vLo);
+
+ z = vmulq_f32(z, vHi);
+ float32x4x2_t xy = vuzpq_f32(xy0, xy0);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcltq_f32(x, minDot);
+ minDot = vbslq_f32(mask, x, minDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ // select best answer between hi and lo results
+ uint32x2_t mask = vclt_f32(vget_high_f32(minDot), vget_low_f32(minDot));
+ float32x2_t minDot2 = vbsl_f32(mask, vget_high_f32(minDot), vget_low_f32(minDot));
+ uint32x2_t index2 = vbsl_u32(mask, vget_high_u32(index), vget_low_u32(index));
+
+ // select best answer between even and odd results
+ float32x2_t minDotO = vdup_lane_f32(minDot2, 1);
+ uint32x2_t indexHi = vdup_lane_u32(index2, 1);
+ mask = vclt_f32(minDotO, minDot2);
+ minDot2 = vbsl_f32(mask, minDotO, minDot2);
+ index2 = vbsl_u32(mask, indexHi, index2);
+
+ *dotResult = vget_lane_f32(minDot2, 0);
+ return vget_lane_u32(index2, 0);
}
#else
- #error Unhandled __APPLE__ arch
+#error Unhandled __APPLE__ arch
#endif
-#endif /* __APPLE__ */
-
-
+#endif /* __APPLE__ */
diff --git a/thirdparty/bullet/Bullet3Common/b3Vector3.h b/thirdparty/bullet/Bullet3Common/b3Vector3.h
index 16ec02b0ed..56e6c13311 100644
--- a/thirdparty/bullet/Bullet3Common/b3Vector3.h
+++ b/thirdparty/bullet/Bullet3Common/b3Vector3.h
@@ -12,8 +12,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
-
#ifndef B3_VECTOR3_H
#define B3_VECTOR3_H
@@ -28,37 +26,34 @@ subject to the following restrictions:
#else
#define b3Vector3Data b3Vector3FloatData
#define b3Vector3DataName "b3Vector3FloatData"
-#endif //B3_USE_DOUBLE_PRECISION
+#endif //B3_USE_DOUBLE_PRECISION
#if defined B3_USE_SSE
//typedef uint32_t __m128i __attribute__ ((vector_size(16)));
#ifdef _MSC_VER
-#pragma warning(disable: 4556) // value of intrinsic immediate argument '4294967239' is out of range '0 - 255'
+#pragma warning(disable : 4556) // value of intrinsic immediate argument '4294967239' is out of range '0 - 255'
#endif
-
-#define B3_SHUFFLE(x,y,z,w) ((w)<<6 | (z)<<4 | (y)<<2 | (x))
+#define B3_SHUFFLE(x, y, z, w) ((w) << 6 | (z) << 4 | (y) << 2 | (x))
//#define b3_pshufd_ps( _a, _mask ) (__m128) _mm_shuffle_epi32((__m128i)(_a), (_mask) )
-#define b3_pshufd_ps( _a, _mask ) _mm_shuffle_ps((_a), (_a), (_mask) )
-#define b3_splat3_ps( _a, _i ) b3_pshufd_ps((_a), B3_SHUFFLE(_i,_i,_i, 3) )
-#define b3_splat_ps( _a, _i ) b3_pshufd_ps((_a), B3_SHUFFLE(_i,_i,_i,_i) )
+#define b3_pshufd_ps(_a, _mask) _mm_shuffle_ps((_a), (_a), (_mask))
+#define b3_splat3_ps(_a, _i) b3_pshufd_ps((_a), B3_SHUFFLE(_i, _i, _i, 3))
+#define b3_splat_ps(_a, _i) b3_pshufd_ps((_a), B3_SHUFFLE(_i, _i, _i, _i))
#define b3v3AbsiMask (_mm_set_epi32(0x00000000, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF))
-#define b3vAbsMask (_mm_set_epi32( 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF))
+#define b3vAbsMask (_mm_set_epi32(0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF))
#define b3vFFF0Mask (_mm_set_epi32(0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF))
#define b3v3AbsfMask b3CastiTo128f(b3v3AbsiMask)
#define b3vFFF0fMask b3CastiTo128f(b3vFFF0Mask)
#define b3vxyzMaskf b3vFFF0fMask
#define b3vAbsfMask b3CastiTo128f(b3vAbsMask)
-
-
const __m128 B3_ATTRIBUTE_ALIGNED16(b3vMzeroMask) = {-0.0f, -0.0f, -0.0f, -0.0f};
const __m128 B3_ATTRIBUTE_ALIGNED16(b3v1110) = {1.0f, 1.0f, 1.0f, 0.0f};
const __m128 B3_ATTRIBUTE_ALIGNED16(b3vHalf) = {0.5f, 0.5f, 0.5f, 0.5f};
-const __m128 B3_ATTRIBUTE_ALIGNED16(b3v1_5) = {1.5f, 1.5f, 1.5f, 1.5f};
+const __m128 B3_ATTRIBUTE_ALIGNED16(b3v1_5) = {1.5f, 1.5f, 1.5f, 1.5f};
#endif
@@ -74,70 +69,69 @@ const int32x4_t B3_ATTRIBUTE_ALIGNED16(b3v3AbsMask) = (int32x4_t){0x7FFFFFFF, 0x
class b3Vector3;
class b3Vector4;
-#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
//#if defined (B3_USE_SSE) || defined (B3_USE_NEON)
-inline b3Vector3 b3MakeVector3( b3SimdFloat4 v);
-inline b3Vector4 b3MakeVector4( b3SimdFloat4 vec);
+inline b3Vector3 b3MakeVector3(b3SimdFloat4 v);
+inline b3Vector4 b3MakeVector4(b3SimdFloat4 vec);
#endif
-inline b3Vector3 b3MakeVector3(b3Scalar x,b3Scalar y,b3Scalar z);
-inline b3Vector3 b3MakeVector3(b3Scalar x,b3Scalar y,b3Scalar z, b3Scalar w);
-inline b3Vector4 b3MakeVector4(b3Scalar x,b3Scalar y,b3Scalar z,b3Scalar w);
-
+inline b3Vector3 b3MakeVector3(b3Scalar x, b3Scalar y, b3Scalar z);
+inline b3Vector3 b3MakeVector3(b3Scalar x, b3Scalar y, b3Scalar z, b3Scalar w);
+inline b3Vector4 b3MakeVector4(b3Scalar x, b3Scalar y, b3Scalar z, b3Scalar w);
/**@brief b3Vector3 can be used to represent 3D points and vectors.
* It has an un-used w component to suit 16-byte alignment when b3Vector3 is stored in containers. This extra component can be used by derived classes (Quaternion?) or by user
* Ideally, this class should be replaced by a platform optimized SIMD version that keeps the data in registers
*/
-B3_ATTRIBUTE_ALIGNED16(class) b3Vector3
+B3_ATTRIBUTE_ALIGNED16(class)
+b3Vector3
{
public:
-#if defined (B3_USE_SSE) || defined(B3_USE_NEON) // _WIN32 || ARM
- union {
- b3SimdFloat4 mVec128;
- float m_floats[4];
- struct {float x,y,z,w;};
-
- };
+#if defined(B3_USE_SSE) || defined(B3_USE_NEON) // _WIN32 || ARM
+ union {
+ b3SimdFloat4 mVec128;
+ float m_floats[4];
+ struct
+ {
+ float x, y, z, w;
+ };
+ };
#else
- union
- {
- float m_floats[4];
- struct {float x,y,z,w;};
+ union {
+ float m_floats[4];
+ struct
+ {
+ float x, y, z, w;
+ };
};
#endif
-
public:
-
B3_DECLARE_ALIGNED_ALLOCATOR();
-#if defined (B3_USE_SSE) || defined(B3_USE_NEON) // _WIN32 || ARM
+#if defined(B3_USE_SSE) || defined(B3_USE_NEON) // _WIN32 || ARM
/*B3_FORCE_INLINE b3Vector3()
{
}
*/
- B3_FORCE_INLINE b3SimdFloat4 get128() const
- {
- return mVec128;
- }
- B3_FORCE_INLINE void set128(b3SimdFloat4 v128)
- {
- mVec128 = v128;
- }
+ B3_FORCE_INLINE b3SimdFloat4 get128() const
+ {
+ return mVec128;
+ }
+ B3_FORCE_INLINE void set128(b3SimdFloat4 v128)
+ {
+ mVec128 = v128;
+ }
#endif
- public:
-
-
-
-/**@brief Add a vector to this one
+public:
+ /**@brief Add a vector to this one
* @param The vector to add to this one */
B3_FORCE_INLINE b3Vector3& operator+=(const b3Vector3& v)
{
-#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
mVec128 = _mm_add_ps(mVec128, v.mVec128);
#elif defined(B3_USE_NEON)
mVec128 = vaddq_f32(mVec128, v.mVec128);
@@ -149,12 +143,11 @@ public:
return *this;
}
-
- /**@brief Subtract a vector from this one
+ /**@brief Subtract a vector from this one
* @param The vector to subtract */
B3_FORCE_INLINE b3Vector3& operator-=(const b3Vector3& v)
{
-#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
mVec128 = _mm_sub_ps(mVec128, v.mVec128);
#elif defined(B3_USE_NEON)
mVec128 = vsubq_f32(mVec128, v.mVec128);
@@ -166,13 +159,13 @@ public:
return *this;
}
- /**@brief Scale the vector
+ /**@brief Scale the vector
* @param s Scale factor */
B3_FORCE_INLINE b3Vector3& operator*=(const b3Scalar& s)
{
-#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
- __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
- vs = b3_pshufd_ps(vs, 0x80); // (S S S 0.0)
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+ __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
+ vs = b3_pshufd_ps(vs, 0x80); // (S S S 0.0)
mVec128 = _mm_mul_ps(mVec128, vs);
#elif defined(B3_USE_NEON)
mVec128 = vmulq_n_f32(mVec128, s);
@@ -184,13 +177,13 @@ public:
return *this;
}
- /**@brief Inversely scale the vector
+ /**@brief Inversely scale the vector
* @param s Scale factor to divide by */
B3_FORCE_INLINE b3Vector3& operator/=(const b3Scalar& s)
{
b3FullAssert(s != b3Scalar(0.0));
-#if 0 //defined(B3_USE_SSE_IN_API)
+#if 0 //defined(B3_USE_SSE_IN_API)
// this code is not faster !
__m128 vs = _mm_load_ss(&s);
vs = _mm_div_ss(b3v1110, vs);
@@ -204,11 +197,11 @@ public:
#endif
}
- /**@brief Return the dot product
+ /**@brief Return the dot product
* @param v The other vector in the dot product */
B3_FORCE_INLINE b3Scalar dot(const b3Vector3& v) const
{
-#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
__m128 vd = _mm_mul_ps(mVec128, v.mVec128);
__m128 z = _mm_movehl_ps(vd, vd);
__m128 y = _mm_shuffle_ps(vd, vd, 0x55);
@@ -221,29 +214,29 @@ public:
x = vadd_f32(x, vget_high_f32(vd));
return vget_lane_f32(x, 0);
#else
- return m_floats[0] * v.m_floats[0] +
- m_floats[1] * v.m_floats[1] +
- m_floats[2] * v.m_floats[2];
+ return m_floats[0] * v.m_floats[0] +
+ m_floats[1] * v.m_floats[1] +
+ m_floats[2] * v.m_floats[2];
#endif
}
- /**@brief Return the length of the vector squared */
+ /**@brief Return the length of the vector squared */
B3_FORCE_INLINE b3Scalar length2() const
{
return dot(*this);
}
- /**@brief Return the length of the vector */
+ /**@brief Return the length of the vector */
B3_FORCE_INLINE b3Scalar length() const
{
return b3Sqrt(length2());
}
- /**@brief Return the distance squared between the ends of this and another vector
+ /**@brief Return the distance squared between the ends of this and another vector
* This is symantically treating the vector like a point */
B3_FORCE_INLINE b3Scalar distance2(const b3Vector3& v) const;
- /**@brief Return the distance between the ends of this and another vector
+ /**@brief Return the distance between the ends of this and another vector
* This is symantically treating the vector like a point */
B3_FORCE_INLINE b3Scalar distance(const b3Vector3& v) const;
@@ -251,7 +244,7 @@ public:
{
b3Scalar l2 = length2();
//triNormal.normalize();
- if (l2 >= B3_EPSILON*B3_EPSILON)
+ if (l2 >= B3_EPSILON * B3_EPSILON)
{
(*this) /= b3Sqrt(l2);
}
@@ -262,43 +255,42 @@ public:
return *this;
}
- /**@brief Normalize this vector
+ /**@brief Normalize this vector
* x^2 + y^2 + z^2 = 1 */
B3_FORCE_INLINE b3Vector3& normalize()
{
-#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
- // dot product first
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+ // dot product first
__m128 vd = _mm_mul_ps(mVec128, mVec128);
__m128 z = _mm_movehl_ps(vd, vd);
__m128 y = _mm_shuffle_ps(vd, vd, 0x55);
vd = _mm_add_ss(vd, y);
vd = _mm_add_ss(vd, z);
- #if 0
+#if 0
vd = _mm_sqrt_ss(vd);
vd = _mm_div_ss(b3v1110, vd);
vd = b3_splat_ps(vd, 0x80);
mVec128 = _mm_mul_ps(mVec128, vd);
- #else
+#else
- // NR step 1/sqrt(x) - vd is x, y is output
- y = _mm_rsqrt_ss(vd); // estimate
+ // NR step 1/sqrt(x) - vd is x, y is output
+ y = _mm_rsqrt_ss(vd); // estimate
- // one step NR
- z = b3v1_5;
- vd = _mm_mul_ss(vd, b3vHalf); // vd * 0.5
- //x2 = vd;
- vd = _mm_mul_ss(vd, y); // vd * 0.5 * y0
- vd = _mm_mul_ss(vd, y); // vd * 0.5 * y0 * y0
- z = _mm_sub_ss(z, vd); // 1.5 - vd * 0.5 * y0 * y0
+ // one step NR
+ z = b3v1_5;
+ vd = _mm_mul_ss(vd, b3vHalf); // vd * 0.5
+ //x2 = vd;
+ vd = _mm_mul_ss(vd, y); // vd * 0.5 * y0
+ vd = _mm_mul_ss(vd, y); // vd * 0.5 * y0 * y0
+ z = _mm_sub_ss(z, vd); // 1.5 - vd * 0.5 * y0 * y0
- y = _mm_mul_ss(y, z); // y0 * (1.5 - vd * 0.5 * y0 * y0)
+ y = _mm_mul_ss(y, z); // y0 * (1.5 - vd * 0.5 * y0 * y0)
y = b3_splat_ps(y, 0x80);
mVec128 = _mm_mul_ps(mVec128, y);
- #endif
-
+#endif
return *this;
#else
@@ -306,15 +298,15 @@ public:
#endif
}
- /**@brief Return a normalized version of this vector */
+ /**@brief Return a normalized version of this vector */
B3_FORCE_INLINE b3Vector3 normalized() const;
- /**@brief Return a rotated version of this vector
+ /**@brief Return a rotated version of this vector
* @param wAxis The axis to rotate about
* @param angle The angle to rotate by */
- B3_FORCE_INLINE b3Vector3 rotate( const b3Vector3& wAxis, const b3Scalar angle ) const;
+ B3_FORCE_INLINE b3Vector3 rotate(const b3Vector3& wAxis, const b3Scalar angle) const;
- /**@brief Return the angle between this and another vector
+ /**@brief Return the angle between this and another vector
* @param v The other vector */
B3_FORCE_INLINE b3Scalar angle(const b3Vector3& v) const
{
@@ -323,10 +315,10 @@ public:
return b3Acos(dot(v) / s);
}
- /**@brief Return a vector will the absolute values of each element */
+ /**@brief Return a vector will the absolute values of each element */
B3_FORCE_INLINE b3Vector3 absolute() const
{
-#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
return b3MakeVector3(_mm_and_ps(mVec128, b3v3AbsfMask));
#elif defined(B3_USE_NEON)
return b3Vector3(vabsq_f32(mVec128));
@@ -338,15 +330,15 @@ public:
#endif
}
- /**@brief Return the cross product between this and another vector
+ /**@brief Return the cross product between this and another vector
* @param v The other vector */
B3_FORCE_INLINE b3Vector3 cross(const b3Vector3& v) const
{
-#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
- __m128 T, V;
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+ __m128 T, V;
- T = b3_pshufd_ps(mVec128, B3_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
- V = b3_pshufd_ps(v.mVec128, B3_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
+ T = b3_pshufd_ps(mVec128, B3_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
+ V = b3_pshufd_ps(v.mVec128, B3_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
V = _mm_mul_ps(V, mVec128);
T = _mm_mul_ps(T, v.mVec128);
@@ -381,10 +373,10 @@ public:
B3_FORCE_INLINE b3Scalar triple(const b3Vector3& v1, const b3Vector3& v2) const
{
-#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
// cross:
- __m128 T = _mm_shuffle_ps(v1.mVec128, v1.mVec128, B3_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
- __m128 V = _mm_shuffle_ps(v2.mVec128, v2.mVec128, B3_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
+ __m128 T = _mm_shuffle_ps(v1.mVec128, v1.mVec128, B3_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
+ __m128 V = _mm_shuffle_ps(v2.mVec128, v2.mVec128, B3_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
V = _mm_mul_ps(V, v1.mVec128);
T = _mm_mul_ps(T, v2.mVec128);
@@ -422,25 +414,24 @@ public:
x = vadd_f32(x, vget_high_f32(V));
return vget_lane_f32(x, 0);
#else
- return
- m_floats[0] * (v1.m_floats[1] * v2.m_floats[2] - v1.m_floats[2] * v2.m_floats[1]) +
- m_floats[1] * (v1.m_floats[2] * v2.m_floats[0] - v1.m_floats[0] * v2.m_floats[2]) +
- m_floats[2] * (v1.m_floats[0] * v2.m_floats[1] - v1.m_floats[1] * v2.m_floats[0]);
+ return m_floats[0] * (v1.m_floats[1] * v2.m_floats[2] - v1.m_floats[2] * v2.m_floats[1]) +
+ m_floats[1] * (v1.m_floats[2] * v2.m_floats[0] - v1.m_floats[0] * v2.m_floats[2]) +
+ m_floats[2] * (v1.m_floats[0] * v2.m_floats[1] - v1.m_floats[1] * v2.m_floats[0]);
#endif
}
- /**@brief Return the axis with the smallest value
+ /**@brief Return the axis with the smallest value
* Note return values are 0,1,2 for x, y, or z */
B3_FORCE_INLINE int minAxis() const
{
- return m_floats[0] < m_floats[1] ? (m_floats[0] <m_floats[2] ? 0 : 2) : (m_floats[1] <m_floats[2] ? 1 : 2);
+ return m_floats[0] < m_floats[1] ? (m_floats[0] < m_floats[2] ? 0 : 2) : (m_floats[1] < m_floats[2] ? 1 : 2);
}
- /**@brief Return the axis with the largest value
+ /**@brief Return the axis with the largest value
* Note return values are 0,1,2 for x, y, or z */
B3_FORCE_INLINE int maxAxis() const
{
- return m_floats[0] < m_floats[1] ? (m_floats[1] <m_floats[2] ? 2 : 1) : (m_floats[0] <m_floats[2] ? 2 : 0);
+ return m_floats[0] < m_floats[1] ? (m_floats[1] < m_floats[2] ? 2 : 1) : (m_floats[0] < m_floats[2] ? 2 : 0);
}
B3_FORCE_INLINE int furthestAxis() const
@@ -453,18 +444,17 @@ public:
return absolute().maxAxis();
}
-
B3_FORCE_INLINE void setInterpolate3(const b3Vector3& v0, const b3Vector3& v1, b3Scalar rt)
{
-#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
- __m128 vrt = _mm_load_ss(&rt); // (rt 0 0 0)
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+ __m128 vrt = _mm_load_ss(&rt); // (rt 0 0 0)
b3Scalar s = b3Scalar(1.0) - rt;
- __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
- vs = b3_pshufd_ps(vs, 0x80); // (S S S 0.0)
+ __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
+ vs = b3_pshufd_ps(vs, 0x80); // (S S S 0.0)
__m128 r0 = _mm_mul_ps(v0.mVec128, vs);
- vrt = b3_pshufd_ps(vrt, 0x80); // (rt rt rt 0.0)
+ vrt = b3_pshufd_ps(vrt, 0x80); // (rt rt rt 0.0)
__m128 r1 = _mm_mul_ps(v1.mVec128, vrt);
- __m128 tmp3 = _mm_add_ps(r0,r1);
+ __m128 tmp3 = _mm_add_ps(r0, r1);
mVec128 = tmp3;
#elif defined(B3_USE_NEON)
float32x4_t vl = vsubq_f32(v1.mVec128, v0.mVec128);
@@ -480,14 +470,14 @@ public:
#endif
}
- /**@brief Return the linear interpolation between this and another vector
+ /**@brief Return the linear interpolation between this and another vector
* @param v The other vector
* @param t The ration of this to v (t = 0 => return this, t=1 => return other) */
B3_FORCE_INLINE b3Vector3 lerp(const b3Vector3& v, const b3Scalar& t) const
{
-#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
- __m128 vt = _mm_load_ss(&t); // (t 0 0 0)
- vt = b3_pshufd_ps(vt, 0x80); // (rt rt rt 0.0)
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+ __m128 vt = _mm_load_ss(&t); // (t 0 0 0)
+ vt = b3_pshufd_ps(vt, 0x80); // (rt rt rt 0.0)
__m128 vl = _mm_sub_ps(v.mVec128, mVec128);
vl = _mm_mul_ps(vl, vt);
vl = _mm_add_ps(vl, mVec128);
@@ -500,18 +490,17 @@ public:
return b3Vector3(vl);
#else
- return
- b3MakeVector3( m_floats[0] + (v.m_floats[0] - m_floats[0]) * t,
- m_floats[1] + (v.m_floats[1] - m_floats[1]) * t,
- m_floats[2] + (v.m_floats[2] - m_floats[2]) * t);
+ return b3MakeVector3(m_floats[0] + (v.m_floats[0] - m_floats[0]) * t,
+ m_floats[1] + (v.m_floats[1] - m_floats[1]) * t,
+ m_floats[2] + (v.m_floats[2] - m_floats[2]) * t);
#endif
}
- /**@brief Elementwise multiply this vector by the other
+ /**@brief Elementwise multiply this vector by the other
* @param v The other vector */
B3_FORCE_INLINE b3Vector3& operator*=(const b3Vector3& v)
{
-#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
mVec128 = _mm_mul_ps(mVec128, v.mVec128);
#elif defined(B3_USE_NEON)
mVec128 = vmulq_f32(mVec128, v.mVec128);
@@ -523,53 +512,53 @@ public:
return *this;
}
- /**@brief Return the x value */
- B3_FORCE_INLINE const b3Scalar& getX() const { return m_floats[0]; }
- /**@brief Return the y value */
- B3_FORCE_INLINE const b3Scalar& getY() const { return m_floats[1]; }
- /**@brief Return the z value */
- B3_FORCE_INLINE const b3Scalar& getZ() const { return m_floats[2]; }
-/**@brief Return the w value */
- B3_FORCE_INLINE const b3Scalar& getW() const { return m_floats[3]; }
-
- /**@brief Set the x value */
- B3_FORCE_INLINE void setX(b3Scalar _x) { m_floats[0] = _x;};
- /**@brief Set the y value */
- B3_FORCE_INLINE void setY(b3Scalar _y) { m_floats[1] = _y;};
- /**@brief Set the z value */
- B3_FORCE_INLINE void setZ(b3Scalar _z) { m_floats[2] = _z;};
- /**@brief Set the w value */
- B3_FORCE_INLINE void setW(b3Scalar _w) { m_floats[3] = _w;};
+ /**@brief Return the x value */
+ B3_FORCE_INLINE const b3Scalar& getX() const { return m_floats[0]; }
+ /**@brief Return the y value */
+ B3_FORCE_INLINE const b3Scalar& getY() const { return m_floats[1]; }
+ /**@brief Return the z value */
+ B3_FORCE_INLINE const b3Scalar& getZ() const { return m_floats[2]; }
+ /**@brief Return the w value */
+ B3_FORCE_INLINE const b3Scalar& getW() const { return m_floats[3]; }
+
+ /**@brief Set the x value */
+ B3_FORCE_INLINE void setX(b3Scalar _x) { m_floats[0] = _x; };
+ /**@brief Set the y value */
+ B3_FORCE_INLINE void setY(b3Scalar _y) { m_floats[1] = _y; };
+ /**@brief Set the z value */
+ B3_FORCE_INLINE void setZ(b3Scalar _z) { m_floats[2] = _z; };
+ /**@brief Set the w value */
+ B3_FORCE_INLINE void setW(b3Scalar _w) { m_floats[3] = _w; };
//B3_FORCE_INLINE b3Scalar& operator[](int i) { return (&m_floats[0])[i]; }
//B3_FORCE_INLINE const b3Scalar& operator[](int i) const { return (&m_floats[0])[i]; }
///operator b3Scalar*() replaces operator[], using implicit conversion. We added operator != and operator == to avoid pointer comparisons.
- B3_FORCE_INLINE operator b3Scalar *() { return &m_floats[0]; }
- B3_FORCE_INLINE operator const b3Scalar *() const { return &m_floats[0]; }
+ B3_FORCE_INLINE operator b3Scalar*() { return &m_floats[0]; }
+ B3_FORCE_INLINE operator const b3Scalar*() const { return &m_floats[0]; }
- B3_FORCE_INLINE bool operator==(const b3Vector3& other) const
+ B3_FORCE_INLINE bool operator==(const b3Vector3& other) const
{
-#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
- return (0xf == _mm_movemask_ps((__m128)_mm_cmpeq_ps(mVec128, other.mVec128)));
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+ return (0xf == _mm_movemask_ps((__m128)_mm_cmpeq_ps(mVec128, other.mVec128)));
#else
- return ((m_floats[3]==other.m_floats[3]) &&
- (m_floats[2]==other.m_floats[2]) &&
- (m_floats[1]==other.m_floats[1]) &&
- (m_floats[0]==other.m_floats[0]));
+ return ((m_floats[3] == other.m_floats[3]) &&
+ (m_floats[2] == other.m_floats[2]) &&
+ (m_floats[1] == other.m_floats[1]) &&
+ (m_floats[0] == other.m_floats[0]));
#endif
}
- B3_FORCE_INLINE bool operator!=(const b3Vector3& other) const
+ B3_FORCE_INLINE bool operator!=(const b3Vector3& other) const
{
return !(*this == other);
}
- /**@brief Set each element to the max of the current values and the values of another b3Vector3
+ /**@brief Set each element to the max of the current values and the values of another b3Vector3
* @param other The other b3Vector3 to compare with
*/
- B3_FORCE_INLINE void setMax(const b3Vector3& other)
+ B3_FORCE_INLINE void setMax(const b3Vector3& other)
{
-#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
mVec128 = _mm_max_ps(mVec128, other.mVec128);
#elif defined(B3_USE_NEON)
mVec128 = vmaxq_f32(mVec128, other.mVec128);
@@ -581,12 +570,12 @@ public:
#endif
}
- /**@brief Set each element to the min of the current values and the values of another b3Vector3
+ /**@brief Set each element to the min of the current values and the values of another b3Vector3
* @param other The other b3Vector3 to compare with
*/
- B3_FORCE_INLINE void setMin(const b3Vector3& other)
+ B3_FORCE_INLINE void setMin(const b3Vector3& other)
{
-#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
mVec128 = _mm_min_ps(mVec128, other.mVec128);
#elif defined(B3_USE_NEON)
mVec128 = vminq_f32(mVec128, other.mVec128);
@@ -598,46 +587,46 @@ public:
#endif
}
- B3_FORCE_INLINE void setValue(const b3Scalar& _x, const b3Scalar& _y, const b3Scalar& _z)
+ B3_FORCE_INLINE void setValue(const b3Scalar& _x, const b3Scalar& _y, const b3Scalar& _z)
{
- m_floats[0]=_x;
- m_floats[1]=_y;
- m_floats[2]=_z;
+ m_floats[0] = _x;
+ m_floats[1] = _y;
+ m_floats[2] = _z;
m_floats[3] = b3Scalar(0.f);
}
- void getSkewSymmetricMatrix(b3Vector3* v0,b3Vector3* v1,b3Vector3* v2) const
+ void getSkewSymmetricMatrix(b3Vector3 * v0, b3Vector3 * v1, b3Vector3 * v2) const
{
-#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- __m128 V = _mm_and_ps(mVec128, b3vFFF0fMask);
+ __m128 V = _mm_and_ps(mVec128, b3vFFF0fMask);
__m128 V0 = _mm_xor_ps(b3vMzeroMask, V);
__m128 V2 = _mm_movelh_ps(V0, V);
__m128 V1 = _mm_shuffle_ps(V, V0, 0xCE);
- V0 = _mm_shuffle_ps(V0, V, 0xDB);
+ V0 = _mm_shuffle_ps(V0, V, 0xDB);
V2 = _mm_shuffle_ps(V2, V, 0xF9);
v0->mVec128 = V0;
v1->mVec128 = V1;
v2->mVec128 = V2;
#else
- v0->setValue(0. ,-getZ() ,getY());
- v1->setValue(getZ() ,0. ,-getX());
- v2->setValue(-getY() ,getX() ,0.);
+ v0->setValue(0., -getZ(), getY());
+ v1->setValue(getZ(), 0., -getX());
+ v2->setValue(-getY(), getX(), 0.);
#endif
}
void setZero()
{
-#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
mVec128 = (__m128)_mm_xor_ps(mVec128, mVec128);
#elif defined(B3_USE_NEON)
int32x4_t vi = vdupq_n_s32(0);
mVec128 = vreinterpretq_f32_s32(vi);
#else
- setValue(b3Scalar(0.),b3Scalar(0.),b3Scalar(0.));
+ setValue(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.));
#endif
}
@@ -651,76 +640,76 @@ public:
return length2() < B3_EPSILON;
}
- B3_FORCE_INLINE void serialize(struct b3Vector3Data& dataOut) const;
+ B3_FORCE_INLINE void serialize(struct b3Vector3Data & dataOut) const;
- B3_FORCE_INLINE void deSerialize(const struct b3Vector3Data& dataIn);
+ B3_FORCE_INLINE void deSerialize(const struct b3Vector3Data& dataIn);
- B3_FORCE_INLINE void serializeFloat(struct b3Vector3FloatData& dataOut) const;
+ B3_FORCE_INLINE void serializeFloat(struct b3Vector3FloatData & dataOut) const;
- B3_FORCE_INLINE void deSerializeFloat(const struct b3Vector3FloatData& dataIn);
+ B3_FORCE_INLINE void deSerializeFloat(const struct b3Vector3FloatData& dataIn);
- B3_FORCE_INLINE void serializeDouble(struct b3Vector3DoubleData& dataOut) const;
+ B3_FORCE_INLINE void serializeDouble(struct b3Vector3DoubleData & dataOut) const;
- B3_FORCE_INLINE void deSerializeDouble(const struct b3Vector3DoubleData& dataIn);
+ B3_FORCE_INLINE void deSerializeDouble(const struct b3Vector3DoubleData& dataIn);
- /**@brief returns index of maximum dot product between this and vectors in array[]
+ /**@brief returns index of maximum dot product between this and vectors in array[]
* @param array The other vectors
* @param array_count The number of other vectors
* @param dotOut The maximum dot product */
- B3_FORCE_INLINE long maxDot( const b3Vector3 *array, long array_count, b3Scalar &dotOut ) const;
+ B3_FORCE_INLINE long maxDot(const b3Vector3* array, long array_count, b3Scalar& dotOut) const;
- /**@brief returns index of minimum dot product between this and vectors in array[]
+ /**@brief returns index of minimum dot product between this and vectors in array[]
* @param array The other vectors
* @param array_count The number of other vectors
* @param dotOut The minimum dot product */
- B3_FORCE_INLINE long minDot( const b3Vector3 *array, long array_count, b3Scalar &dotOut ) const;
-
- /* create a vector as b3Vector3( this->dot( b3Vector3 v0 ), this->dot( b3Vector3 v1), this->dot( b3Vector3 v2 )) */
- B3_FORCE_INLINE b3Vector3 dot3( const b3Vector3 &v0, const b3Vector3 &v1, const b3Vector3 &v2 ) const
- {
-#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
-
- __m128 a0 = _mm_mul_ps( v0.mVec128, this->mVec128 );
- __m128 a1 = _mm_mul_ps( v1.mVec128, this->mVec128 );
- __m128 a2 = _mm_mul_ps( v2.mVec128, this->mVec128 );
- __m128 b0 = _mm_unpacklo_ps( a0, a1 );
- __m128 b1 = _mm_unpackhi_ps( a0, a1 );
- __m128 b2 = _mm_unpacklo_ps( a2, _mm_setzero_ps() );
- __m128 r = _mm_movelh_ps( b0, b2 );
- r = _mm_add_ps( r, _mm_movehl_ps( b2, b0 ));
- a2 = _mm_and_ps( a2, b3vxyzMaskf);
- r = _mm_add_ps( r, b3CastdTo128f (_mm_move_sd( b3CastfTo128d(a2), b3CastfTo128d(b1) )));
- return b3MakeVector3(r);
+ B3_FORCE_INLINE long minDot(const b3Vector3* array, long array_count, b3Scalar& dotOut) const;
+
+ /* create a vector as b3Vector3( this->dot( b3Vector3 v0 ), this->dot( b3Vector3 v1), this->dot( b3Vector3 v2 )) */
+ B3_FORCE_INLINE b3Vector3 dot3(const b3Vector3& v0, const b3Vector3& v1, const b3Vector3& v2) const
+ {
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+
+ __m128 a0 = _mm_mul_ps(v0.mVec128, this->mVec128);
+ __m128 a1 = _mm_mul_ps(v1.mVec128, this->mVec128);
+ __m128 a2 = _mm_mul_ps(v2.mVec128, this->mVec128);
+ __m128 b0 = _mm_unpacklo_ps(a0, a1);
+ __m128 b1 = _mm_unpackhi_ps(a0, a1);
+ __m128 b2 = _mm_unpacklo_ps(a2, _mm_setzero_ps());
+ __m128 r = _mm_movelh_ps(b0, b2);
+ r = _mm_add_ps(r, _mm_movehl_ps(b2, b0));
+ a2 = _mm_and_ps(a2, b3vxyzMaskf);
+ r = _mm_add_ps(r, b3CastdTo128f(_mm_move_sd(b3CastfTo128d(a2), b3CastfTo128d(b1))));
+ return b3MakeVector3(r);
#elif defined(B3_USE_NEON)
- static const uint32x4_t xyzMask = (const uint32x4_t){ -1, -1, -1, 0 };
- float32x4_t a0 = vmulq_f32( v0.mVec128, this->mVec128);
- float32x4_t a1 = vmulq_f32( v1.mVec128, this->mVec128);
- float32x4_t a2 = vmulq_f32( v2.mVec128, this->mVec128);
- float32x2x2_t zLo = vtrn_f32( vget_high_f32(a0), vget_high_f32(a1));
- a2 = (float32x4_t) vandq_u32((uint32x4_t) a2, xyzMask );
- float32x2_t b0 = vadd_f32( vpadd_f32( vget_low_f32(a0), vget_low_f32(a1)), zLo.val[0] );
- float32x2_t b1 = vpadd_f32( vpadd_f32( vget_low_f32(a2), vget_high_f32(a2)), vdup_n_f32(0.0f));
- return b3Vector3( vcombine_f32(b0, b1) );
+ static const uint32x4_t xyzMask = (const uint32x4_t){-1, -1, -1, 0};
+ float32x4_t a0 = vmulq_f32(v0.mVec128, this->mVec128);
+ float32x4_t a1 = vmulq_f32(v1.mVec128, this->mVec128);
+ float32x4_t a2 = vmulq_f32(v2.mVec128, this->mVec128);
+ float32x2x2_t zLo = vtrn_f32(vget_high_f32(a0), vget_high_f32(a1));
+ a2 = (float32x4_t)vandq_u32((uint32x4_t)a2, xyzMask);
+ float32x2_t b0 = vadd_f32(vpadd_f32(vget_low_f32(a0), vget_low_f32(a1)), zLo.val[0]);
+ float32x2_t b1 = vpadd_f32(vpadd_f32(vget_low_f32(a2), vget_high_f32(a2)), vdup_n_f32(0.0f));
+ return b3Vector3(vcombine_f32(b0, b1));
#else
- return b3MakeVector3( dot(v0), dot(v1), dot(v2));
+ return b3MakeVector3(dot(v0), dot(v1), dot(v2));
#endif
- }
+ }
};
/**@brief Return the sum of two vectors (Point symantics)*/
B3_FORCE_INLINE b3Vector3
operator+(const b3Vector3& v1, const b3Vector3& v2)
{
-#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
return b3MakeVector3(_mm_add_ps(v1.mVec128, v2.mVec128));
#elif defined(B3_USE_NEON)
return b3MakeVector3(vaddq_f32(v1.mVec128, v2.mVec128));
#else
return b3MakeVector3(
- v1.m_floats[0] + v2.m_floats[0],
- v1.m_floats[1] + v2.m_floats[1],
- v1.m_floats[2] + v2.m_floats[2]);
+ v1.m_floats[0] + v2.m_floats[0],
+ v1.m_floats[1] + v2.m_floats[1],
+ v1.m_floats[2] + v2.m_floats[2]);
#endif
}
@@ -728,15 +717,15 @@ operator+(const b3Vector3& v1, const b3Vector3& v2)
B3_FORCE_INLINE b3Vector3
operator*(const b3Vector3& v1, const b3Vector3& v2)
{
-#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
return b3MakeVector3(_mm_mul_ps(v1.mVec128, v2.mVec128));
#elif defined(B3_USE_NEON)
return b3MakeVector3(vmulq_f32(v1.mVec128, v2.mVec128));
#else
return b3MakeVector3(
- v1.m_floats[0] * v2.m_floats[0],
- v1.m_floats[1] * v2.m_floats[1],
- v1.m_floats[2] * v2.m_floats[2]);
+ v1.m_floats[0] * v2.m_floats[0],
+ v1.m_floats[1] * v2.m_floats[1],
+ v1.m_floats[2] * v2.m_floats[2]);
#endif
}
@@ -744,7 +733,7 @@ operator*(const b3Vector3& v1, const b3Vector3& v2)
B3_FORCE_INLINE b3Vector3
operator-(const b3Vector3& v1, const b3Vector3& v2)
{
-#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE))
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE))
// without _mm_and_ps this code causes slowdown in Concave moving
__m128 r = _mm_sub_ps(v1.mVec128, v2.mVec128);
@@ -754,9 +743,9 @@ operator-(const b3Vector3& v1, const b3Vector3& v2)
return b3MakeVector3((float32x4_t)vandq_s32((int32x4_t)r, b3vFFF0Mask));
#else
return b3MakeVector3(
- v1.m_floats[0] - v2.m_floats[0],
- v1.m_floats[1] - v2.m_floats[1],
- v1.m_floats[2] - v2.m_floats[2]);
+ v1.m_floats[0] - v2.m_floats[0],
+ v1.m_floats[1] - v2.m_floats[1],
+ v1.m_floats[2] - v2.m_floats[2]);
#endif
}
@@ -764,7 +753,7 @@ operator-(const b3Vector3& v1, const b3Vector3& v2)
B3_FORCE_INLINE b3Vector3
operator-(const b3Vector3& v)
{
-#if (defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE))
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE))
__m128 r = _mm_xor_ps(v.mVec128, b3vMzeroMask);
return b3MakeVector3(_mm_and_ps(r, b3vFFF0fMask));
#elif defined(B3_USE_NEON)
@@ -778,9 +767,9 @@ operator-(const b3Vector3& v)
B3_FORCE_INLINE b3Vector3
operator*(const b3Vector3& v, const b3Scalar& s)
{
-#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
- __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
- vs = b3_pshufd_ps(vs, 0x80); // (S S S 0.0)
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+ __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
+ vs = b3_pshufd_ps(vs, 0x80); // (S S S 0.0)
return b3MakeVector3(_mm_mul_ps(v.mVec128, vs));
#elif defined(B3_USE_NEON)
float32x4_t r = vmulq_n_f32(v.mVec128, s);
@@ -802,7 +791,7 @@ B3_FORCE_INLINE b3Vector3
operator/(const b3Vector3& v, const b3Scalar& s)
{
b3FullAssert(s != b3Scalar(0.0));
-#if 0 //defined(B3_USE_SSE_IN_API)
+#if 0 //defined(B3_USE_SSE_IN_API)
// this code is not faster !
__m128 vs = _mm_load_ss(&s);
vs = _mm_div_ss(b3v1110, vs);
@@ -818,7 +807,7 @@ operator/(const b3Vector3& v, const b3Scalar& s)
B3_FORCE_INLINE b3Vector3
operator/(const b3Vector3& v1, const b3Vector3& v2)
{
-#if (defined(B3_USE_SSE_IN_API)&& defined (B3_USE_SSE))
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE))
__m128 vec = _mm_div_ps(v1.mVec128, v2.mVec128);
vec = _mm_and_ps(vec, b3vFFF0fMask);
return b3MakeVector3(vec);
@@ -828,19 +817,19 @@ operator/(const b3Vector3& v1, const b3Vector3& v2)
x = v1.mVec128;
y = v2.mVec128;
- v = vrecpeq_f32(y); // v ~ 1/y
- m = vrecpsq_f32(y, v); // m = (2-v*y)
- v = vmulq_f32(v, m); // vv = v*m ~~ 1/y
- m = vrecpsq_f32(y, v); // mm = (2-vv*y)
- v = vmulq_f32(v, x); // x*vv
- v = vmulq_f32(v, m); // (x*vv)*(2-vv*y) = x*(vv(2-vv*y)) ~~~ x/y
+ v = vrecpeq_f32(y); // v ~ 1/y
+ m = vrecpsq_f32(y, v); // m = (2-v*y)
+ v = vmulq_f32(v, m); // vv = v*m ~~ 1/y
+ m = vrecpsq_f32(y, v); // mm = (2-vv*y)
+ v = vmulq_f32(v, x); // x*vv
+ v = vmulq_f32(v, m); // (x*vv)*(2-vv*y) = x*(vv(2-vv*y)) ~~~ x/y
return b3Vector3(v);
#else
return b3MakeVector3(
- v1.m_floats[0] / v2.m_floats[0],
- v1.m_floats[1] / v2.m_floats[1],
- v1.m_floats[2] / v2.m_floats[2]);
+ v1.m_floats[0] / v2.m_floats[0],
+ v1.m_floats[1] / v2.m_floats[1],
+ v1.m_floats[2] / v2.m_floats[2]);
#endif
}
@@ -851,7 +840,6 @@ b3Dot(const b3Vector3& v1, const b3Vector3& v2)
return v1.dot(v2);
}
-
/**@brief Return the distance squared between two vectors */
B3_FORCE_INLINE b3Scalar
b3Distance2(const b3Vector3& v1, const b3Vector3& v2)
@@ -859,7 +847,6 @@ b3Distance2(const b3Vector3& v1, const b3Vector3& v2)
return v1.distance2(v2);
}
-
/**@brief Return the distance between two vectors */
B3_FORCE_INLINE b3Scalar
b3Distance(const b3Vector3& v1, const b3Vector3& v2)
@@ -897,8 +884,6 @@ b3Lerp(const b3Vector3& v1, const b3Vector3& v2, const b3Scalar& t)
return v1.lerp(v2, t);
}
-
-
B3_FORCE_INLINE b3Scalar b3Vector3::distance2(const b3Vector3& v) const
{
return (v - *this).length2();
@@ -911,7 +896,7 @@ B3_FORCE_INLINE b3Scalar b3Vector3::distance(const b3Vector3& v) const
B3_FORCE_INLINE b3Vector3 b3Vector3::normalized() const
{
-#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
b3Vector3 norm = *this;
return norm.normalize();
@@ -920,143 +905,136 @@ B3_FORCE_INLINE b3Vector3 b3Vector3::normalized() const
#endif
}
-B3_FORCE_INLINE b3Vector3 b3Vector3::rotate( const b3Vector3& wAxis, const b3Scalar _angle ) const
+B3_FORCE_INLINE b3Vector3 b3Vector3::rotate(const b3Vector3& wAxis, const b3Scalar _angle) const
{
// wAxis must be a unit lenght vector
-#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- __m128 O = _mm_mul_ps(wAxis.mVec128, mVec128);
- b3Scalar ssin = b3Sin( _angle );
- __m128 C = wAxis.cross( b3MakeVector3(mVec128) ).mVec128;
+ __m128 O = _mm_mul_ps(wAxis.mVec128, mVec128);
+ b3Scalar ssin = b3Sin(_angle);
+ __m128 C = wAxis.cross(b3MakeVector3(mVec128)).mVec128;
O = _mm_and_ps(O, b3vFFF0fMask);
- b3Scalar scos = b3Cos( _angle );
+ b3Scalar scos = b3Cos(_angle);
- __m128 vsin = _mm_load_ss(&ssin); // (S 0 0 0)
- __m128 vcos = _mm_load_ss(&scos); // (S 0 0 0)
+ __m128 vsin = _mm_load_ss(&ssin); // (S 0 0 0)
+ __m128 vcos = _mm_load_ss(&scos); // (S 0 0 0)
- __m128 Y = b3_pshufd_ps(O, 0xC9); // (Y Z X 0)
- __m128 Z = b3_pshufd_ps(O, 0xD2); // (Z X Y 0)
+ __m128 Y = b3_pshufd_ps(O, 0xC9); // (Y Z X 0)
+ __m128 Z = b3_pshufd_ps(O, 0xD2); // (Z X Y 0)
O = _mm_add_ps(O, Y);
- vsin = b3_pshufd_ps(vsin, 0x80); // (S S S 0)
+ vsin = b3_pshufd_ps(vsin, 0x80); // (S S S 0)
O = _mm_add_ps(O, Z);
- vcos = b3_pshufd_ps(vcos, 0x80); // (S S S 0)
+ vcos = b3_pshufd_ps(vcos, 0x80); // (S S S 0)
- vsin = vsin * C;
+ vsin = vsin * C;
O = O * wAxis.mVec128;
__m128 X = mVec128 - O;
- O = O + vsin;
+ O = O + vsin;
vcos = vcos * X;
O = O + vcos;
return b3MakeVector3(O);
#else
- b3Vector3 o = wAxis * wAxis.dot( *this );
+ b3Vector3 o = wAxis * wAxis.dot(*this);
b3Vector3 _x = *this - o;
b3Vector3 _y;
- _y = wAxis.cross( *this );
+ _y = wAxis.cross(*this);
- return ( o + _x * b3Cos( _angle ) + _y * b3Sin( _angle ) );
+ return (o + _x * b3Cos(_angle) + _y * b3Sin(_angle));
#endif
}
-B3_FORCE_INLINE long b3Vector3::maxDot( const b3Vector3 *array, long array_count, b3Scalar &dotOut ) const
+B3_FORCE_INLINE long b3Vector3::maxDot(const b3Vector3* array, long array_count, b3Scalar& dotOut) const
{
-#if defined (B3_USE_SSE) || defined (B3_USE_NEON)
- #if defined _WIN32 || defined (B3_USE_SSE)
- const long scalar_cutoff = 10;
- long b3_maxdot_large( const float *array, const float *vec, unsigned long array_count, float *dotOut );
- #elif defined B3_USE_NEON
- const long scalar_cutoff = 4;
- extern long (*_maxdot_large)( const float *array, const float *vec, unsigned long array_count, float *dotOut );
- #endif
- if( array_count < scalar_cutoff )
+#if defined(B3_USE_SSE) || defined(B3_USE_NEON)
+#if defined _WIN32 || defined(B3_USE_SSE)
+ const long scalar_cutoff = 10;
+ long b3_maxdot_large(const float* array, const float* vec, unsigned long array_count, float* dotOut);
+#elif defined B3_USE_NEON
+ const long scalar_cutoff = 4;
+ extern long (*_maxdot_large)(const float* array, const float* vec, unsigned long array_count, float* dotOut);
+#endif
+ if (array_count < scalar_cutoff)
#else
-#endif//B3_USE_SSE || B3_USE_NEON
- {
- b3Scalar maxDot = -B3_INFINITY;
- int i = 0;
- int ptIndex = -1;
- for( i = 0; i < array_count; i++ )
- {
- b3Scalar dot = array[i].dot(*this);
-
- if( dot > maxDot )
- {
- maxDot = dot;
- ptIndex = i;
- }
- }
-
- b3Assert(ptIndex>=0);
- if (ptIndex<0)
+#endif //B3_USE_SSE || B3_USE_NEON
+ {
+ b3Scalar maxDot = -B3_INFINITY;
+ int i = 0;
+ int ptIndex = -1;
+ for (i = 0; i < array_count; i++)
+ {
+ b3Scalar dot = array[i].dot(*this);
+
+ if (dot > maxDot)
+ {
+ maxDot = dot;
+ ptIndex = i;
+ }
+ }
+
+ b3Assert(ptIndex >= 0);
+ if (ptIndex < 0)
{
ptIndex = 0;
}
- dotOut = maxDot;
- return ptIndex;
- }
-#if defined (B3_USE_SSE) || defined (B3_USE_NEON)
- return b3_maxdot_large( (float*) array, (float*) &m_floats[0], array_count, &dotOut );
+ dotOut = maxDot;
+ return ptIndex;
+ }
+#if defined(B3_USE_SSE) || defined(B3_USE_NEON)
+ return b3_maxdot_large((float*)array, (float*)&m_floats[0], array_count, &dotOut);
#endif
}
-B3_FORCE_INLINE long b3Vector3::minDot( const b3Vector3 *array, long array_count, b3Scalar &dotOut ) const
+B3_FORCE_INLINE long b3Vector3::minDot(const b3Vector3* array, long array_count, b3Scalar& dotOut) const
{
-#if defined (B3_USE_SSE) || defined (B3_USE_NEON)
- #if defined B3_USE_SSE
- const long scalar_cutoff = 10;
- long b3_mindot_large( const float *array, const float *vec, unsigned long array_count, float *dotOut );
- #elif defined B3_USE_NEON
- const long scalar_cutoff = 4;
- extern long (*b3_mindot_large)( const float *array, const float *vec, unsigned long array_count, float *dotOut );
- #else
- #error unhandled arch!
- #endif
-
- if( array_count < scalar_cutoff )
-#endif//B3_USE_SSE || B3_USE_NEON
- {
- b3Scalar minDot = B3_INFINITY;
- int i = 0;
- int ptIndex = -1;
-
- for( i = 0; i < array_count; i++ )
- {
- b3Scalar dot = array[i].dot(*this);
-
- if( dot < minDot )
- {
- minDot = dot;
- ptIndex = i;
- }
- }
-
- dotOut = minDot;
-
- return ptIndex;
- }
-#if defined (B3_USE_SSE) || defined (B3_USE_NEON)
- return b3_mindot_large( (float*) array, (float*) &m_floats[0], array_count, &dotOut );
+#if defined(B3_USE_SSE) || defined(B3_USE_NEON)
+#if defined B3_USE_SSE
+ const long scalar_cutoff = 10;
+ long b3_mindot_large(const float* array, const float* vec, unsigned long array_count, float* dotOut);
+#elif defined B3_USE_NEON
+ const long scalar_cutoff = 4;
+ extern long (*b3_mindot_large)(const float* array, const float* vec, unsigned long array_count, float* dotOut);
+#else
+#error unhandled arch!
#endif
-}
-
-
-class b3Vector4 : public b3Vector3
-{
-public:
+ if (array_count < scalar_cutoff)
+#endif //B3_USE_SSE || B3_USE_NEON
+ {
+ b3Scalar minDot = B3_INFINITY;
+ int i = 0;
+ int ptIndex = -1;
+ for (i = 0; i < array_count; i++)
+ {
+ b3Scalar dot = array[i].dot(*this);
+ if (dot < minDot)
+ {
+ minDot = dot;
+ ptIndex = i;
+ }
+ }
+ dotOut = minDot;
+ return ptIndex;
+ }
+#if defined(B3_USE_SSE) || defined(B3_USE_NEON)
+ return b3_mindot_large((float*)array, (float*)&m_floats[0], array_count, &dotOut);
+#endif
+}
+class b3Vector4 : public b3Vector3
+{
+public:
B3_FORCE_INLINE b3Vector4 absolute4() const
{
-#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
return b3MakeVector4(_mm_and_ps(mVec128, b3vAbsfMask));
#elif defined(B3_USE_NEON)
return b3Vector4(vabsq_f32(mVec128));
@@ -1069,11 +1047,9 @@ public:
#endif
}
+ b3Scalar getW() const { return m_floats[3]; }
- b3Scalar getW() const { return m_floats[3];}
-
-
- B3_FORCE_INLINE int maxAxis4() const
+ B3_FORCE_INLINE int maxAxis4() const
{
int maxIndex = -1;
b3Scalar maxVal = b3Scalar(-B3_LARGE_FLOAT);
@@ -1090,7 +1066,7 @@ public:
if (m_floats[2] > maxVal)
{
maxIndex = 2;
- maxVal =m_floats[2];
+ maxVal = m_floats[2];
}
if (m_floats[3] > maxVal)
{
@@ -1100,7 +1076,6 @@ public:
return maxIndex;
}
-
B3_FORCE_INLINE int minAxis4() const
{
int minIndex = -1;
@@ -1118,7 +1093,7 @@ public:
if (m_floats[2] < minVal)
{
minIndex = 2;
- minVal =m_floats[2];
+ minVal = m_floats[2];
}
if (m_floats[3] < minVal)
{
@@ -1129,216 +1104,200 @@ public:
return minIndex;
}
-
B3_FORCE_INLINE int closestAxis4() const
{
return absolute4().maxAxis4();
}
-
-
-
- /**@brief Set x,y,z and zero w
+ /**@brief Set x,y,z and zero w
* @param x Value of x
* @param y Value of y
* @param z Value of z
*/
-
-/* void getValue(b3Scalar *m) const
+ /* void getValue(b3Scalar *m) const
{
m[0] = m_floats[0];
m[1] = m_floats[1];
m[2] =m_floats[2];
}
*/
-/**@brief Set the values
+ /**@brief Set the values
* @param x Value of x
* @param y Value of y
* @param z Value of z
* @param w Value of w
*/
- B3_FORCE_INLINE void setValue(const b3Scalar& _x, const b3Scalar& _y, const b3Scalar& _z,const b3Scalar& _w)
- {
- m_floats[0]=_x;
- m_floats[1]=_y;
- m_floats[2]=_z;
- m_floats[3]=_w;
- }
-
-
+ B3_FORCE_INLINE void setValue(const b3Scalar& _x, const b3Scalar& _y, const b3Scalar& _z, const b3Scalar& _w)
+ {
+ m_floats[0] = _x;
+ m_floats[1] = _y;
+ m_floats[2] = _z;
+ m_floats[3] = _w;
+ }
};
-
///b3SwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization
-B3_FORCE_INLINE void b3SwapScalarEndian(const b3Scalar& sourceVal, b3Scalar& destVal)
+B3_FORCE_INLINE void b3SwapScalarEndian(const b3Scalar& sourceVal, b3Scalar& destVal)
{
- #ifdef B3_USE_DOUBLE_PRECISION
- unsigned char* dest = (unsigned char*) &destVal;
- unsigned char* src = (unsigned char*) &sourceVal;
+#ifdef B3_USE_DOUBLE_PRECISION
+ unsigned char* dest = (unsigned char*)&destVal;
+ unsigned char* src = (unsigned char*)&sourceVal;
dest[0] = src[7];
- dest[1] = src[6];
- dest[2] = src[5];
- dest[3] = src[4];
- dest[4] = src[3];
- dest[5] = src[2];
- dest[6] = src[1];
- dest[7] = src[0];
+ dest[1] = src[6];
+ dest[2] = src[5];
+ dest[3] = src[4];
+ dest[4] = src[3];
+ dest[5] = src[2];
+ dest[6] = src[1];
+ dest[7] = src[0];
#else
- unsigned char* dest = (unsigned char*) &destVal;
- unsigned char* src = (unsigned char*) &sourceVal;
+ unsigned char* dest = (unsigned char*)&destVal;
+ unsigned char* src = (unsigned char*)&sourceVal;
dest[0] = src[3];
- dest[1] = src[2];
- dest[2] = src[1];
- dest[3] = src[0];
-#endif //B3_USE_DOUBLE_PRECISION
+ dest[1] = src[2];
+ dest[2] = src[1];
+ dest[3] = src[0];
+#endif //B3_USE_DOUBLE_PRECISION
}
///b3SwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization
-B3_FORCE_INLINE void b3SwapVector3Endian(const b3Vector3& sourceVec, b3Vector3& destVec)
+B3_FORCE_INLINE void b3SwapVector3Endian(const b3Vector3& sourceVec, b3Vector3& destVec)
{
- for (int i=0;i<4;i++)
+ for (int i = 0; i < 4; i++)
{
- b3SwapScalarEndian(sourceVec[i],destVec[i]);
+ b3SwapScalarEndian(sourceVec[i], destVec[i]);
}
-
}
///b3UnSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization
-B3_FORCE_INLINE void b3UnSwapVector3Endian(b3Vector3& vector)
+B3_FORCE_INLINE void b3UnSwapVector3Endian(b3Vector3& vector)
{
-
- b3Vector3 swappedVec;
- for (int i=0;i<4;i++)
+ b3Vector3 swappedVec;
+ for (int i = 0; i < 4; i++)
{
- b3SwapScalarEndian(vector[i],swappedVec[i]);
+ b3SwapScalarEndian(vector[i], swappedVec[i]);
}
vector = swappedVec;
}
template <class T>
-B3_FORCE_INLINE void b3PlaneSpace1 (const T& n, T& p, T& q)
+B3_FORCE_INLINE void b3PlaneSpace1(const T& n, T& p, T& q)
{
- if (b3Fabs(n[2]) > B3_SQRT12) {
- // choose p in y-z plane
- b3Scalar a = n[1]*n[1] + n[2]*n[2];
- b3Scalar k = b3RecipSqrt (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
- b3Scalar a = n[0]*n[0] + n[1]*n[1];
- b3Scalar k = b3RecipSqrt (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;
- }
+ if (b3Fabs(n[2]) > B3_SQRT12)
+ {
+ // choose p in y-z plane
+ b3Scalar a = n[1] * n[1] + n[2] * n[2];
+ b3Scalar k = b3RecipSqrt(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
+ b3Scalar a = n[0] * n[0] + n[1] * n[1];
+ b3Scalar k = b3RecipSqrt(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;
+ }
}
-
-struct b3Vector3FloatData
+struct b3Vector3FloatData
{
- float m_floats[4];
+ float m_floats[4];
};
-struct b3Vector3DoubleData
+struct b3Vector3DoubleData
{
- double m_floats[4];
-
+ double m_floats[4];
};
-B3_FORCE_INLINE void b3Vector3::serializeFloat(struct b3Vector3FloatData& dataOut) const
+B3_FORCE_INLINE void b3Vector3::serializeFloat(struct b3Vector3FloatData& dataOut) const
{
///could also do a memcpy, check if it is worth it
- for (int i=0;i<4;i++)
+ for (int i = 0; i < 4; i++)
dataOut.m_floats[i] = float(m_floats[i]);
}
-B3_FORCE_INLINE void b3Vector3::deSerializeFloat(const struct b3Vector3FloatData& dataIn)
+B3_FORCE_INLINE void b3Vector3::deSerializeFloat(const struct b3Vector3FloatData& dataIn)
{
- for (int i=0;i<4;i++)
+ for (int i = 0; i < 4; i++)
m_floats[i] = b3Scalar(dataIn.m_floats[i]);
}
-
-B3_FORCE_INLINE void b3Vector3::serializeDouble(struct b3Vector3DoubleData& dataOut) const
+B3_FORCE_INLINE void b3Vector3::serializeDouble(struct b3Vector3DoubleData& dataOut) const
{
///could also do a memcpy, check if it is worth it
- for (int i=0;i<4;i++)
+ for (int i = 0; i < 4; i++)
dataOut.m_floats[i] = double(m_floats[i]);
}
-B3_FORCE_INLINE void b3Vector3::deSerializeDouble(const struct b3Vector3DoubleData& dataIn)
+B3_FORCE_INLINE void b3Vector3::deSerializeDouble(const struct b3Vector3DoubleData& dataIn)
{
- for (int i=0;i<4;i++)
+ for (int i = 0; i < 4; i++)
m_floats[i] = b3Scalar(dataIn.m_floats[i]);
}
-
-B3_FORCE_INLINE void b3Vector3::serialize(struct b3Vector3Data& dataOut) const
+B3_FORCE_INLINE void b3Vector3::serialize(struct b3Vector3Data& dataOut) const
{
///could also do a memcpy, check if it is worth it
- for (int i=0;i<4;i++)
+ for (int i = 0; i < 4; i++)
dataOut.m_floats[i] = m_floats[i];
}
-B3_FORCE_INLINE void b3Vector3::deSerialize(const struct b3Vector3Data& dataIn)
+B3_FORCE_INLINE void b3Vector3::deSerialize(const struct b3Vector3Data& dataIn)
{
- for (int i=0;i<4;i++)
+ for (int i = 0; i < 4; i++)
m_floats[i] = dataIn.m_floats[i];
}
-
-
-
-inline b3Vector3 b3MakeVector3(b3Scalar x,b3Scalar y,b3Scalar z)
+inline b3Vector3 b3MakeVector3(b3Scalar x, b3Scalar y, b3Scalar z)
{
- b3Vector3 tmp;
- tmp.setValue(x,y,z);
+ b3Vector3 tmp;
+ tmp.setValue(x, y, z);
return tmp;
}
-inline b3Vector3 b3MakeVector3(b3Scalar x,b3Scalar y,b3Scalar z, b3Scalar w)
+inline b3Vector3 b3MakeVector3(b3Scalar x, b3Scalar y, b3Scalar z, b3Scalar w)
{
- b3Vector3 tmp;
- tmp.setValue(x,y,z);
+ b3Vector3 tmp;
+ tmp.setValue(x, y, z);
tmp.w = w;
return tmp;
}
-inline b3Vector4 b3MakeVector4(b3Scalar x,b3Scalar y,b3Scalar z,b3Scalar w)
+inline b3Vector4 b3MakeVector4(b3Scalar x, b3Scalar y, b3Scalar z, b3Scalar w)
{
- b3Vector4 tmp;
- tmp.setValue(x,y,z,w);
+ b3Vector4 tmp;
+ tmp.setValue(x, y, z, w);
return tmp;
}
-#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
-inline b3Vector3 b3MakeVector3( b3SimdFloat4 v)
+inline b3Vector3 b3MakeVector3(b3SimdFloat4 v)
{
- b3Vector3 tmp;
- tmp.set128(v);
- return tmp;
+ b3Vector3 tmp;
+ tmp.set128(v);
+ return tmp;
}
inline b3Vector4 b3MakeVector4(b3SimdFloat4 vec)
{
- b3Vector4 tmp;
+ b3Vector4 tmp;
tmp.set128(vec);
return tmp;
}
#endif
-
-#endif //B3_VECTOR3_H
+#endif //B3_VECTOR3_H
diff --git a/thirdparty/bullet/Bullet3Common/shared/b3Float4.h b/thirdparty/bullet/Bullet3Common/shared/b3Float4.h
index 5e4b95bcee..d8a9f47411 100644
--- a/thirdparty/bullet/Bullet3Common/shared/b3Float4.h
+++ b/thirdparty/bullet/Bullet3Common/shared/b3Float4.h
@@ -4,94 +4,87 @@
#include "Bullet3Common/shared/b3PlatformDefinitions.h"
#ifdef __cplusplus
- #include "Bullet3Common/b3Vector3.h"
- #define b3Float4 b3Vector3
- #define b3Float4ConstArg const b3Vector3&
- #define b3Dot3F4 b3Dot
- #define b3Cross3 b3Cross
- #define b3MakeFloat4 b3MakeVector3
- inline b3Vector3 b3Normalized(const b3Vector3& vec)
- {
- return vec.normalized();
- }
-
- inline b3Float4 b3FastNormalized3(b3Float4ConstArg v)
- {
- return v.normalized();
- }
-
- inline b3Float4 b3MaxFloat4 (const b3Float4& a, const b3Float4& b)
- {
- b3Float4 tmp = a;
- tmp.setMax(b);
- return tmp;
- }
- inline b3Float4 b3MinFloat4 (const b3Float4& a, const b3Float4& b)
- {
- b3Float4 tmp = a;
- tmp.setMin(b);
- return tmp;
- }
+#include "Bullet3Common/b3Vector3.h"
+#define b3Float4 b3Vector3
+#define b3Float4ConstArg const b3Vector3&
+#define b3Dot3F4 b3Dot
+#define b3Cross3 b3Cross
+#define b3MakeFloat4 b3MakeVector3
+inline b3Vector3 b3Normalized(const b3Vector3& vec)
+{
+ return vec.normalized();
+}
+inline b3Float4 b3FastNormalized3(b3Float4ConstArg v)
+{
+ return v.normalized();
+}
+inline b3Float4 b3MaxFloat4(const b3Float4& a, const b3Float4& b)
+{
+ b3Float4 tmp = a;
+ tmp.setMax(b);
+ return tmp;
+}
+inline b3Float4 b3MinFloat4(const b3Float4& a, const b3Float4& b)
+{
+ b3Float4 tmp = a;
+ tmp.setMin(b);
+ return tmp;
+}
#else
- typedef float4 b3Float4;
- #define b3Float4ConstArg const b3Float4
- #define b3MakeFloat4 (float4)
- float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)
- {
- float4 a1 = b3MakeFloat4(v0.xyz,0.f);
- float4 b1 = b3MakeFloat4(v1.xyz,0.f);
- return dot(a1, b1);
- }
- b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)
- {
- float4 a1 = b3MakeFloat4(v0.xyz,0.f);
- float4 b1 = b3MakeFloat4(v1.xyz,0.f);
- return cross(a1, b1);
- }
- #define b3MinFloat4 min
- #define b3MaxFloat4 max
-
- #define b3Normalized(a) normalize(a)
+typedef float4 b3Float4;
+#define b3Float4ConstArg const b3Float4
+#define b3MakeFloat4 (float4)
+float b3Dot3F4(b3Float4ConstArg v0, b3Float4ConstArg v1)
+{
+ float4 a1 = b3MakeFloat4(v0.xyz, 0.f);
+ float4 b1 = b3MakeFloat4(v1.xyz, 0.f);
+ return dot(a1, b1);
+}
+b3Float4 b3Cross3(b3Float4ConstArg v0, b3Float4ConstArg v1)
+{
+ float4 a1 = b3MakeFloat4(v0.xyz, 0.f);
+ float4 b1 = b3MakeFloat4(v1.xyz, 0.f);
+ return cross(a1, b1);
+}
+#define b3MinFloat4 min
+#define b3MaxFloat4 max
-#endif
+#define b3Normalized(a) normalize(a)
+#endif
-
inline bool b3IsAlmostZero(b3Float4ConstArg v)
{
- if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6)
+ if (b3Fabs(v.x) > 1e-6 || b3Fabs(v.y) > 1e-6 || b3Fabs(v.z) > 1e-6)
return false;
return true;
}
-
-inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )
+inline int b3MaxDot(b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut)
{
- float maxDot = -B3_INFINITY;
- int i = 0;
- int ptIndex = -1;
- for( i = 0; i < vecLen; i++ )
- {
- float dot = b3Dot3F4(vecArray[i],vec);
-
- if( dot > maxDot )
- {
- maxDot = dot;
- ptIndex = i;
- }
- }
- b3Assert(ptIndex>=0);
- if (ptIndex<0)
+ float maxDot = -B3_INFINITY;
+ int i = 0;
+ int ptIndex = -1;
+ for (i = 0; i < vecLen; i++)
+ {
+ float dot = b3Dot3F4(vecArray[i], vec);
+
+ if (dot > maxDot)
+ {
+ maxDot = dot;
+ ptIndex = i;
+ }
+ }
+ b3Assert(ptIndex >= 0);
+ if (ptIndex < 0)
{
ptIndex = 0;
}
- *dotOut = maxDot;
- return ptIndex;
+ *dotOut = maxDot;
+ return ptIndex;
}
-
-
-#endif //B3_FLOAT4_H
+#endif //B3_FLOAT4_H
diff --git a/thirdparty/bullet/Bullet3Common/shared/b3Int2.h b/thirdparty/bullet/Bullet3Common/shared/b3Int2.h
index f1d01f81a5..7b84de4436 100644
--- a/thirdparty/bullet/Bullet3Common/shared/b3Int2.h
+++ b/thirdparty/bullet/Bullet3Common/shared/b3Int2.h
@@ -20,11 +20,10 @@ subject to the following restrictions:
struct b3UnsignedInt2
{
- union
- {
+ union {
struct
{
- unsigned int x,y;
+ unsigned int x, y;
};
struct
{
@@ -35,11 +34,10 @@ struct b3UnsignedInt2
struct b3Int2
{
- union
- {
+ union {
struct
{
- int x,y;
+ int x, y;
};
struct
{
@@ -51,7 +49,8 @@ struct b3Int2
inline b3Int2 b3MakeInt2(int x, int y)
{
b3Int2 v;
- v.s[0] = x; v.s[1] = y;
+ v.s[0] = x;
+ v.s[1] = y;
return v;
}
#else
@@ -60,5 +59,5 @@ inline b3Int2 b3MakeInt2(int x, int y)
#define b3Int2 int2
#define b3MakeInt2 (int2)
-#endif //__cplusplus
+#endif //__cplusplus
#endif \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3Common/shared/b3Int4.h b/thirdparty/bullet/Bullet3Common/shared/b3Int4.h
index aa02d6beef..f6a1754245 100644
--- a/thirdparty/bullet/Bullet3Common/shared/b3Int4.h
+++ b/thirdparty/bullet/Bullet3Common/shared/b3Int4.h
@@ -5,16 +5,15 @@
#include "Bullet3Common/b3Scalar.h"
-
-B3_ATTRIBUTE_ALIGNED16(struct) b3UnsignedInt4
+B3_ATTRIBUTE_ALIGNED16(struct)
+b3UnsignedInt4
{
B3_DECLARE_ALIGNED_ALLOCATOR();
- union
- {
+ union {
struct
{
- unsigned int x,y,z,w;
+ unsigned int x, y, z, w;
};
struct
{
@@ -23,15 +22,15 @@ B3_ATTRIBUTE_ALIGNED16(struct) b3UnsignedInt4
};
};
-B3_ATTRIBUTE_ALIGNED16(struct) b3Int4
+B3_ATTRIBUTE_ALIGNED16(struct)
+b3Int4
{
B3_DECLARE_ALIGNED_ALLOCATOR();
- union
- {
+ union {
struct
{
- int x,y,z,w;
+ int x, y, z, w;
};
struct
{
@@ -43,26 +42,30 @@ B3_ATTRIBUTE_ALIGNED16(struct) b3Int4
B3_FORCE_INLINE b3Int4 b3MakeInt4(int x, int y, int z, int w = 0)
{
b3Int4 v;
- v.s[0] = x; v.s[1] = y; v.s[2] = z; v.s[3] = w;
+ v.s[0] = x;
+ v.s[1] = y;
+ v.s[2] = z;
+ v.s[3] = w;
return v;
}
B3_FORCE_INLINE b3UnsignedInt4 b3MakeUnsignedInt4(unsigned int x, unsigned int y, unsigned int z, unsigned int w = 0)
{
b3UnsignedInt4 v;
- v.s[0] = x; v.s[1] = y; v.s[2] = z; v.s[3] = w;
+ v.s[0] = x;
+ v.s[1] = y;
+ v.s[2] = z;
+ v.s[3] = w;
return v;
}
#else
-
#define b3UnsignedInt4 uint4
#define b3Int4 int4
#define b3MakeInt4 (int4)
#define b3MakeUnsignedInt4 (uint4)
+#endif //__cplusplus
-#endif //__cplusplus
-
-#endif //B3_INT4_H
+#endif //B3_INT4_H
diff --git a/thirdparty/bullet/Bullet3Common/shared/b3Mat3x3.h b/thirdparty/bullet/Bullet3Common/shared/b3Mat3x3.h
index 7b1fef32f8..ce6482b5a6 100644
--- a/thirdparty/bullet/Bullet3Common/shared/b3Mat3x3.h
+++ b/thirdparty/bullet/Bullet3Common/shared/b3Mat3x3.h
@@ -4,7 +4,6 @@
#include "Bullet3Common/shared/b3Quat.h"
-
#ifdef __cplusplus
#include "Bullet3Common/b3Matrix3x3.h"
@@ -22,43 +21,41 @@ inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg mat)
return mat.absolute();
}
-#define b3GetRow(m,row) m.getRow(row)
+#define b3GetRow(m, row) m.getRow(row)
-__inline
-b3Float4 mtMul3(b3Float4ConstArg a, b3Mat3x3ConstArg b)
+__inline b3Float4 mtMul3(b3Float4ConstArg a, b3Mat3x3ConstArg b)
{
- return b*a;
+ return b * a;
}
-
#else
typedef struct
{
b3Float4 m_row[3];
-}b3Mat3x3;
+} b3Mat3x3;
#define b3Mat3x3ConstArg const b3Mat3x3
-#define b3GetRow(m,row) (m.m_row[row])
+#define b3GetRow(m, row) (m.m_row[row])
inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat)
{
- b3Float4 quat2 = (b3Float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);
+ b3Float4 quat2 = (b3Float4)(quat.x * quat.x, quat.y * quat.y, quat.z * quat.z, 0.f);
b3Mat3x3 out;
- out.m_row[0].x=1-2*quat2.y-2*quat2.z;
- out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;
- out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;
+ out.m_row[0].x = 1 - 2 * quat2.y - 2 * quat2.z;
+ out.m_row[0].y = 2 * quat.x * quat.y - 2 * quat.w * quat.z;
+ out.m_row[0].z = 2 * quat.x * quat.z + 2 * quat.w * quat.y;
out.m_row[0].w = 0.f;
- out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;
- out.m_row[1].y=1-2*quat2.x-2*quat2.z;
- out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;
+ out.m_row[1].x = 2 * quat.x * quat.y + 2 * quat.w * quat.z;
+ out.m_row[1].y = 1 - 2 * quat2.x - 2 * quat2.z;
+ out.m_row[1].z = 2 * quat.y * quat.z - 2 * quat.w * quat.x;
out.m_row[1].w = 0.f;
- out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;
- out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;
- out.m_row[2].z=1-2*quat2.x-2*quat2.y;
+ out.m_row[2].x = 2 * quat.x * quat.z - 2 * quat.w * quat.y;
+ out.m_row[2].y = 2 * quat.y * quat.z + 2 * quat.w * quat.x;
+ out.m_row[2].z = 1 - 2 * quat2.x - 2 * quat2.y;
out.m_row[2].w = 0.f;
return out;
@@ -73,27 +70,19 @@ inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn)
return out;
}
+__inline b3Mat3x3 mtZero();
-__inline
-b3Mat3x3 mtZero();
-
-__inline
-b3Mat3x3 mtIdentity();
+__inline b3Mat3x3 mtIdentity();
-__inline
-b3Mat3x3 mtTranspose(b3Mat3x3 m);
+__inline b3Mat3x3 mtTranspose(b3Mat3x3 m);
-__inline
-b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);
+__inline b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);
-__inline
-b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);
+__inline b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);
-__inline
-b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);
+__inline b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);
-__inline
-b3Mat3x3 mtZero()
+__inline b3Mat3x3 mtZero()
{
b3Mat3x3 m;
m.m_row[0] = (b3Float4)(0.f);
@@ -102,18 +91,16 @@ b3Mat3x3 mtZero()
return m;
}
-__inline
-b3Mat3x3 mtIdentity()
+__inline b3Mat3x3 mtIdentity()
{
b3Mat3x3 m;
- m.m_row[0] = (b3Float4)(1,0,0,0);
- m.m_row[1] = (b3Float4)(0,1,0,0);
- m.m_row[2] = (b3Float4)(0,0,1,0);
+ m.m_row[0] = (b3Float4)(1, 0, 0, 0);
+ m.m_row[1] = (b3Float4)(0, 1, 0, 0);
+ m.m_row[2] = (b3Float4)(0, 0, 1, 0);
return m;
}
-__inline
-b3Mat3x3 mtTranspose(b3Mat3x3 m)
+__inline b3Mat3x3 mtTranspose(b3Mat3x3 m)
{
b3Mat3x3 out;
out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);
@@ -122,58 +109,49 @@ b3Mat3x3 mtTranspose(b3Mat3x3 m)
return out;
}
-__inline
-b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)
+__inline b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)
{
b3Mat3x3 transB;
- transB = mtTranspose( b );
+ transB = mtTranspose(b);
b3Mat3x3 ans;
// why this doesn't run when 0ing in the for{}
a.m_row[0].w = 0.f;
a.m_row[1].w = 0.f;
a.m_row[2].w = 0.f;
- for(int i=0; i<3; i++)
+ for (int i = 0; i < 3; i++)
{
-// a.m_row[i].w = 0.f;
- ans.m_row[i].x = b3Dot3F4(a.m_row[i],transB.m_row[0]);
- ans.m_row[i].y = b3Dot3F4(a.m_row[i],transB.m_row[1]);
- ans.m_row[i].z = b3Dot3F4(a.m_row[i],transB.m_row[2]);
+ // a.m_row[i].w = 0.f;
+ ans.m_row[i].x = b3Dot3F4(a.m_row[i], transB.m_row[0]);
+ ans.m_row[i].y = b3Dot3F4(a.m_row[i], transB.m_row[1]);
+ ans.m_row[i].z = b3Dot3F4(a.m_row[i], transB.m_row[2]);
ans.m_row[i].w = 0.f;
}
return ans;
}
-__inline
-b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)
+__inline b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)
{
b3Float4 ans;
- ans.x = b3Dot3F4( a.m_row[0], b );
- ans.y = b3Dot3F4( a.m_row[1], b );
- ans.z = b3Dot3F4( a.m_row[2], b );
+ ans.x = b3Dot3F4(a.m_row[0], b);
+ ans.y = b3Dot3F4(a.m_row[1], b);
+ ans.z = b3Dot3F4(a.m_row[2], b);
ans.w = 0.f;
return ans;
}
-__inline
-b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)
+__inline b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)
{
b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);
b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);
b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);
b3Float4 ans;
- ans.x = b3Dot3F4( a, colx );
- ans.y = b3Dot3F4( a, coly );
- ans.z = b3Dot3F4( a, colz );
+ ans.x = b3Dot3F4(a, colx);
+ ans.y = b3Dot3F4(a, coly);
+ ans.z = b3Dot3F4(a, colz);
return ans;
}
-
#endif
-
-
-
-
-
-#endif //B3_MAT3x3_H
+#endif //B3_MAT3x3_H
diff --git a/thirdparty/bullet/Bullet3Common/shared/b3PlatformDefinitions.h b/thirdparty/bullet/Bullet3Common/shared/b3PlatformDefinitions.h
index 1c133fb088..b72bee9310 100644
--- a/thirdparty/bullet/Bullet3Common/shared/b3PlatformDefinitions.h
+++ b/thirdparty/bullet/Bullet3Common/shared/b3PlatformDefinitions.h
@@ -8,18 +8,18 @@ struct MyTest
#ifdef __cplusplus
//#define b3ConstArray(a) const b3AlignedObjectArray<a>&
-#define b3ConstArray(a) const a*
+#define b3ConstArray(a) const a *
#define b3AtomicInc(a) ((*a)++)
-inline int b3AtomicAdd (volatile int *p, int val)
+inline int b3AtomicAdd(volatile int *p, int val)
{
int oldValue = *p;
- int newValue = oldValue+val;
+ int newValue = oldValue + val;
*p = newValue;
return oldValue;
}
-#define __global
+#define __global
#define B3_STATIC static
#else
@@ -27,7 +27,7 @@ inline int b3AtomicAdd (volatile int *p, int val)
#define B3_LARGE_FLOAT 1e18f
#define B3_INFINITY 1e18f
#define b3Assert(a)
-#define b3ConstArray(a) __global const a*
+#define b3ConstArray(a) __global const a *
#define b3AtomicInc atomic_inc
#define b3AtomicAdd atomic_add
#define b3Fabs fabs
diff --git a/thirdparty/bullet/Bullet3Common/shared/b3Quat.h b/thirdparty/bullet/Bullet3Common/shared/b3Quat.h
index f262d5e08f..940610c77b 100644
--- a/thirdparty/bullet/Bullet3Common/shared/b3Quat.h
+++ b/thirdparty/bullet/Bullet3Common/shared/b3Quat.h
@@ -5,35 +5,34 @@
#include "Bullet3Common/shared/b3Float4.h"
#ifdef __cplusplus
- #include "Bullet3Common/b3Quaternion.h"
- #include "Bullet3Common/b3Transform.h"
+#include "Bullet3Common/b3Quaternion.h"
+#include "Bullet3Common/b3Transform.h"
- #define b3Quat b3Quaternion
- #define b3QuatConstArg const b3Quaternion&
- inline b3Quat b3QuatInverse(b3QuatConstArg orn)
- {
- return orn.inverse();
- }
+#define b3Quat b3Quaternion
+#define b3QuatConstArg const b3Quaternion&
+inline b3Quat b3QuatInverse(b3QuatConstArg orn)
+{
+ return orn.inverse();
+}
- inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation)
- {
- b3Transform tr;
- tr.setOrigin(translation);
- tr.setRotation(orientation);
- return tr(point);
- }
+inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation)
+{
+ b3Transform tr;
+ tr.setOrigin(translation);
+ tr.setRotation(orientation);
+ return tr(point);
+}
#else
- typedef float4 b3Quat;
- #define b3QuatConstArg const b3Quat
-
-
+typedef float4 b3Quat;
+#define b3QuatConstArg const b3Quat
+
inline float4 b3FastNormalize4(float4 v)
{
- v = (float4)(v.xyz,0.f);
+ v = (float4)(v.xyz, 0.f);
return fast_normalize(v);
}
-
+
inline b3Quat b3QuatMul(b3Quat a, b3Quat b);
inline b3Quat b3QuatNormalized(b3QuatConstArg in);
inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec);
@@ -43,20 +42,20 @@ inline b3Quat b3QuatInverse(b3QuatConstArg q);
inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b)
{
b3Quat ans;
- ans = b3Cross3( a, b );
- ans += a.w*b+b.w*a;
-// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);
- ans.w = a.w*b.w - b3Dot3F4(a, b);
+ ans = b3Cross3(a, b);
+ ans += a.w * b + b.w * a;
+ // ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);
+ ans.w = a.w * b.w - b3Dot3F4(a, b);
return ans;
}
inline b3Quat b3QuatNormalized(b3QuatConstArg in)
{
b3Quat q;
- q=in;
+ q = in;
//return b3FastNormalize4(in);
float len = native_sqrt(dot(q, q));
- if(len > 0.f)
+ if (len > 0.f)
{
q *= 1.f / len;
}
@@ -69,15 +68,13 @@ inline b3Quat b3QuatNormalized(b3QuatConstArg in)
}
inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec)
{
- b3Quat qInv = b3QuatInvert( q );
+ b3Quat qInv = b3QuatInvert(q);
float4 vcpy = vec;
vcpy.w = 0.f;
- float4 out = b3QuatMul(b3QuatMul(q,vcpy),qInv);
+ float4 out = b3QuatMul(b3QuatMul(q, vcpy), qInv);
return out;
}
-
-
inline b3Quat b3QuatInverse(b3QuatConstArg q)
{
return (b3Quat)(-q.xyz, q.w);
@@ -90,14 +87,14 @@ inline b3Quat b3QuatInvert(b3QuatConstArg q)
inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec)
{
- return b3QuatRotate( b3QuatInvert( q ), vec );
+ return b3QuatRotate(b3QuatInvert(q), vec);
}
-inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation)
+inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation)
{
- return b3QuatRotate( orientation, point ) + (translation);
+ return b3QuatRotate(orientation, point) + (translation);
}
-
-#endif
-#endif //B3_QUAT_H
+#endif
+
+#endif //B3_QUAT_H
diff --git a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3ContactSolverInfo.h b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3ContactSolverInfo.h
index 7a12257b33..049c9116fd 100644
--- a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3ContactSolverInfo.h
+++ b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3ContactSolverInfo.h
@@ -18,7 +18,7 @@ subject to the following restrictions:
#include "Bullet3Common/b3Scalar.h"
-enum b3SolverMode
+enum b3SolverMode
{
B3_SOLVER_RANDMIZE_ORDER = 1,
B3_SOLVER_FRICTION_SEPARATE = 2,
@@ -34,45 +34,38 @@ enum b3SolverMode
struct b3ContactSolverInfoData
{
-
-
- b3Scalar m_tau;
- b3Scalar m_damping;//global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'.
- b3Scalar m_friction;
- b3Scalar m_timeStep;
- b3Scalar m_restitution;
- int m_numIterations;
- b3Scalar m_maxErrorReduction;
- b3Scalar m_sor;
- b3Scalar m_erp;//used as Baumgarte factor
- b3Scalar m_erp2;//used in Split Impulse
- b3Scalar m_globalCfm;//constraint force mixing
- int m_splitImpulse;
- b3Scalar m_splitImpulsePenetrationThreshold;
- b3Scalar m_splitImpulseTurnErp;
- b3Scalar m_linearSlop;
- b3Scalar m_warmstartingFactor;
-
- int m_solverMode;
- int m_restingContactRestitutionThreshold;
- int m_minimumSolverBatchSize;
- b3Scalar m_maxGyroscopicForce;
- b3Scalar m_singleAxisRollingFrictionThreshold;
-
-
+ b3Scalar m_tau;
+ b3Scalar m_damping; //global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'.
+ b3Scalar m_friction;
+ b3Scalar m_timeStep;
+ b3Scalar m_restitution;
+ int m_numIterations;
+ b3Scalar m_maxErrorReduction;
+ b3Scalar m_sor;
+ b3Scalar m_erp; //used as Baumgarte factor
+ b3Scalar m_erp2; //used in Split Impulse
+ b3Scalar m_globalCfm; //constraint force mixing
+ int m_splitImpulse;
+ b3Scalar m_splitImpulsePenetrationThreshold;
+ b3Scalar m_splitImpulseTurnErp;
+ b3Scalar m_linearSlop;
+ b3Scalar m_warmstartingFactor;
+
+ int m_solverMode;
+ int m_restingContactRestitutionThreshold;
+ int m_minimumSolverBatchSize;
+ b3Scalar m_maxGyroscopicForce;
+ b3Scalar m_singleAxisRollingFrictionThreshold;
};
struct b3ContactSolverInfo : public b3ContactSolverInfoData
{
-
-
-
inline b3ContactSolverInfo()
{
m_tau = b3Scalar(0.6);
m_damping = b3Scalar(1.0);
m_friction = b3Scalar(0.3);
- m_timeStep = b3Scalar(1.f/60.f);
+ m_timeStep = b3Scalar(1.f / 60.f);
m_restitution = b3Scalar(0.);
m_maxErrorReduction = b3Scalar(20.);
m_numIterations = 10;
@@ -84,76 +77,73 @@ struct b3ContactSolverInfo : public b3ContactSolverInfoData
m_splitImpulsePenetrationThreshold = -.04f;
m_splitImpulseTurnErp = 0.1f;
m_linearSlop = b3Scalar(0.0);
- m_warmstartingFactor=b3Scalar(0.85);
+ m_warmstartingFactor = b3Scalar(0.85);
//m_solverMode = B3_SOLVER_USE_WARMSTARTING | B3_SOLVER_SIMD | B3_SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION|B3_SOLVER_USE_2_FRICTION_DIRECTIONS|B3_SOLVER_ENABLE_FRICTION_DIRECTION_CACHING;// | B3_SOLVER_RANDMIZE_ORDER;
- m_solverMode = B3_SOLVER_USE_WARMSTARTING | B3_SOLVER_SIMD;// | B3_SOLVER_RANDMIZE_ORDER;
- m_restingContactRestitutionThreshold = 2;//unused as of 2.81
- m_minimumSolverBatchSize = 128; //try to combine islands until the amount of constraints reaches this limit
- m_maxGyroscopicForce = 100.f; ///only used to clamp forces for bodies that have their B3_ENABLE_GYROPSCOPIC_FORCE flag set (using b3RigidBody::setFlag)
- m_singleAxisRollingFrictionThreshold = 1e30f;///if the velocity is above this threshold, it will use a single constraint row (axis), otherwise 3 rows.
+ m_solverMode = B3_SOLVER_USE_WARMSTARTING | B3_SOLVER_SIMD; // | B3_SOLVER_RANDMIZE_ORDER;
+ m_restingContactRestitutionThreshold = 2; //unused as of 2.81
+ m_minimumSolverBatchSize = 128; //try to combine islands until the amount of constraints reaches this limit
+ m_maxGyroscopicForce = 100.f; ///only used to clamp forces for bodies that have their B3_ENABLE_GYROPSCOPIC_FORCE flag set (using b3RigidBody::setFlag)
+ m_singleAxisRollingFrictionThreshold = 1e30f; ///if the velocity is above this threshold, it will use a single constraint row (axis), otherwise 3 rows.
}
};
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
struct b3ContactSolverInfoDoubleData
{
- double m_tau;
- double m_damping;//global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'.
- double m_friction;
- double m_timeStep;
- double m_restitution;
- double m_maxErrorReduction;
- double m_sor;
- double m_erp;//used as Baumgarte factor
- double m_erp2;//used in Split Impulse
- double m_globalCfm;//constraint force mixing
- double m_splitImpulsePenetrationThreshold;
- double m_splitImpulseTurnErp;
- double m_linearSlop;
- double m_warmstartingFactor;
- double m_maxGyroscopicForce;
- double m_singleAxisRollingFrictionThreshold;
-
- int m_numIterations;
- int m_solverMode;
- int m_restingContactRestitutionThreshold;
- int m_minimumSolverBatchSize;
- int m_splitImpulse;
- char m_padding[4];
-
+ double m_tau;
+ double m_damping; //global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'.
+ double m_friction;
+ double m_timeStep;
+ double m_restitution;
+ double m_maxErrorReduction;
+ double m_sor;
+ double m_erp; //used as Baumgarte factor
+ double m_erp2; //used in Split Impulse
+ double m_globalCfm; //constraint force mixing
+ double m_splitImpulsePenetrationThreshold;
+ double m_splitImpulseTurnErp;
+ double m_linearSlop;
+ double m_warmstartingFactor;
+ double m_maxGyroscopicForce;
+ double m_singleAxisRollingFrictionThreshold;
+
+ int m_numIterations;
+ int m_solverMode;
+ int m_restingContactRestitutionThreshold;
+ int m_minimumSolverBatchSize;
+ int m_splitImpulse;
+ char m_padding[4];
};
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
struct b3ContactSolverInfoFloatData
{
- float m_tau;
- float m_damping;//global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'.
- float m_friction;
- float m_timeStep;
-
- float m_restitution;
- float m_maxErrorReduction;
- float m_sor;
- float m_erp;//used as Baumgarte factor
-
- float m_erp2;//used in Split Impulse
- float m_globalCfm;//constraint force mixing
- float m_splitImpulsePenetrationThreshold;
- float m_splitImpulseTurnErp;
-
- float m_linearSlop;
- float m_warmstartingFactor;
- float m_maxGyroscopicForce;
- float m_singleAxisRollingFrictionThreshold;
-
- int m_numIterations;
- int m_solverMode;
- int m_restingContactRestitutionThreshold;
- int m_minimumSolverBatchSize;
-
- int m_splitImpulse;
- char m_padding[4];
+ float m_tau;
+ float m_damping; //global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'.
+ float m_friction;
+ float m_timeStep;
+
+ float m_restitution;
+ float m_maxErrorReduction;
+ float m_sor;
+ float m_erp; //used as Baumgarte factor
+
+ float m_erp2; //used in Split Impulse
+ float m_globalCfm; //constraint force mixing
+ float m_splitImpulsePenetrationThreshold;
+ float m_splitImpulseTurnErp;
+
+ float m_linearSlop;
+ float m_warmstartingFactor;
+ float m_maxGyroscopicForce;
+ float m_singleAxisRollingFrictionThreshold;
+
+ int m_numIterations;
+ int m_solverMode;
+ int m_restingContactRestitutionThreshold;
+ int m_minimumSolverBatchSize;
+
+ int m_splitImpulse;
+ char m_padding[4];
};
-
-
-#endif //B3_CONTACT_SOLVER_INFO
+#endif //B3_CONTACT_SOLVER_INFO
diff --git a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3FixedConstraint.cpp b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3FixedConstraint.cpp
index 5e11e74935..ace4b18388 100644
--- a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3FixedConstraint.cpp
+++ b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3FixedConstraint.cpp
@@ -4,105 +4,100 @@
#include "Bullet3Common/b3TransformUtil.h"
#include <new>
-
-b3FixedConstraint::b3FixedConstraint(int rbA,int rbB, const b3Transform& frameInA,const b3Transform& frameInB)
-:b3TypedConstraint(B3_FIXED_CONSTRAINT_TYPE,rbA,rbB)
+b3FixedConstraint::b3FixedConstraint(int rbA, int rbB, const b3Transform& frameInA, const b3Transform& frameInB)
+ : b3TypedConstraint(B3_FIXED_CONSTRAINT_TYPE, rbA, rbB)
{
m_pivotInA = frameInA.getOrigin();
m_pivotInB = frameInB.getOrigin();
- m_relTargetAB = frameInA.getRotation()*frameInB.getRotation().inverse();
-
+ m_relTargetAB = frameInA.getRotation() * frameInB.getRotation().inverse();
}
-b3FixedConstraint::~b3FixedConstraint ()
+b3FixedConstraint::~b3FixedConstraint()
{
}
-
-void b3FixedConstraint::getInfo1 (b3ConstraintInfo1* info,const b3RigidBodyData* bodies)
+void b3FixedConstraint::getInfo1(b3ConstraintInfo1* info, const b3RigidBodyData* bodies)
{
info->m_numConstraintRows = 6;
info->nub = 6;
}
-void b3FixedConstraint::getInfo2 (b3ConstraintInfo2* info, const b3RigidBodyData* bodies)
+void b3FixedConstraint::getInfo2(b3ConstraintInfo2* info, const b3RigidBodyData* bodies)
{
//fix the 3 linear degrees of freedom
const b3Vector3& worldPosA = bodies[m_rbA].m_pos;
const b3Quaternion& worldOrnA = bodies[m_rbA].m_quat;
- const b3Vector3& worldPosB= bodies[m_rbB].m_pos;
+ const b3Vector3& worldPosB = bodies[m_rbB].m_pos;
const b3Quaternion& worldOrnB = bodies[m_rbB].m_quat;
info->m_J1linearAxis[0] = 1;
- info->m_J1linearAxis[info->rowskip+1] = 1;
- info->m_J1linearAxis[2*info->rowskip+2] = 1;
+ info->m_J1linearAxis[info->rowskip + 1] = 1;
+ info->m_J1linearAxis[2 * info->rowskip + 2] = 1;
- b3Vector3 a1 = b3QuatRotate(worldOrnA,m_pivotInA);
+ b3Vector3 a1 = b3QuatRotate(worldOrnA, m_pivotInA);
{
b3Vector3* angular0 = (b3Vector3*)(info->m_J1angularAxis);
- b3Vector3* angular1 = (b3Vector3*)(info->m_J1angularAxis+info->rowskip);
- b3Vector3* angular2 = (b3Vector3*)(info->m_J1angularAxis+2*info->rowskip);
+ b3Vector3* angular1 = (b3Vector3*)(info->m_J1angularAxis + info->rowskip);
+ b3Vector3* angular2 = (b3Vector3*)(info->m_J1angularAxis + 2 * info->rowskip);
b3Vector3 a1neg = -a1;
- a1neg.getSkewSymmetricMatrix(angular0,angular1,angular2);
+ a1neg.getSkewSymmetricMatrix(angular0, angular1, angular2);
}
-
+
if (info->m_J2linearAxis)
{
info->m_J2linearAxis[0] = -1;
- info->m_J2linearAxis[info->rowskip+1] = -1;
- info->m_J2linearAxis[2*info->rowskip+2] = -1;
+ info->m_J2linearAxis[info->rowskip + 1] = -1;
+ info->m_J2linearAxis[2 * info->rowskip + 2] = -1;
}
-
- b3Vector3 a2 = b3QuatRotate(worldOrnB,m_pivotInB);
-
+
+ b3Vector3 a2 = b3QuatRotate(worldOrnB, m_pivotInB);
+
{
- // b3Vector3 a2n = -a2;
+ // b3Vector3 a2n = -a2;
b3Vector3* angular0 = (b3Vector3*)(info->m_J2angularAxis);
- b3Vector3* angular1 = (b3Vector3*)(info->m_J2angularAxis+info->rowskip);
- b3Vector3* angular2 = (b3Vector3*)(info->m_J2angularAxis+2*info->rowskip);
- a2.getSkewSymmetricMatrix(angular0,angular1,angular2);
+ b3Vector3* angular1 = (b3Vector3*)(info->m_J2angularAxis + info->rowskip);
+ b3Vector3* angular2 = (b3Vector3*)(info->m_J2angularAxis + 2 * info->rowskip);
+ a2.getSkewSymmetricMatrix(angular0, angular1, angular2);
}
- // set right hand side for the linear dofs
+ // set right hand side for the linear dofs
b3Scalar k = info->fps * info->erp;
- b3Vector3 linearError = k*(a2+worldPosB-a1-worldPosA);
- int j;
- for (j=0; j<3; j++)
- {
- info->m_constraintError[j*info->rowskip] = linearError[j];
+ b3Vector3 linearError = k * (a2 + worldPosB - a1 - worldPosA);
+ int j;
+ for (j = 0; j < 3; j++)
+ {
+ info->m_constraintError[j * info->rowskip] = linearError[j];
//printf("info->m_constraintError[%d]=%f\n",j,info->m_constraintError[j]);
- }
+ }
- //fix the 3 angular degrees of freedom
+ //fix the 3 angular degrees of freedom
int start_row = 3;
int s = info->rowskip;
- int start_index = start_row * s;
+ int start_index = start_row * s;
- // 3 rows to make body rotations equal
+ // 3 rows to make body rotations equal
info->m_J1angularAxis[start_index] = 1;
- info->m_J1angularAxis[start_index + s + 1] = 1;
- info->m_J1angularAxis[start_index + s*2+2] = 1;
- if ( info->m_J2angularAxis)
- {
- info->m_J2angularAxis[start_index] = -1;
- info->m_J2angularAxis[start_index + s+1] = -1;
- info->m_J2angularAxis[start_index + s*2+2] = -1;
- }
-
+ info->m_J1angularAxis[start_index + s + 1] = 1;
+ info->m_J1angularAxis[start_index + s * 2 + 2] = 1;
+ if (info->m_J2angularAxis)
+ {
+ info->m_J2angularAxis[start_index] = -1;
+ info->m_J2angularAxis[start_index + s + 1] = -1;
+ info->m_J2angularAxis[start_index + s * 2 + 2] = -1;
+ }
- // set right hand side for the angular dofs
+ // set right hand side for the angular dofs
b3Vector3 diff;
b3Scalar angle;
- b3Quaternion qrelCur = worldOrnA *worldOrnB.inverse();
-
- b3TransformUtil::calculateDiffAxisAngleQuaternion(m_relTargetAB,qrelCur,diff,angle);
- diff*=-angle;
- for (j=0; j<3; j++)
- {
- info->m_constraintError[(3+j)*info->rowskip] = k * diff[j];
- }
+ b3Quaternion qrelCur = worldOrnA * worldOrnB.inverse();
+ b3TransformUtil::calculateDiffAxisAngleQuaternion(m_relTargetAB, qrelCur, diff, angle);
+ diff *= -angle;
+ for (j = 0; j < 3; j++)
+ {
+ info->m_constraintError[(3 + j) * info->rowskip] = k * diff[j];
+ }
} \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3FixedConstraint.h b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3FixedConstraint.h
index e884a82912..64809666e4 100644
--- a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3FixedConstraint.h
+++ b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3FixedConstraint.h
@@ -4,32 +4,31 @@
#include "b3TypedConstraint.h"
-B3_ATTRIBUTE_ALIGNED16(class) b3FixedConstraint : public b3TypedConstraint
+B3_ATTRIBUTE_ALIGNED16(class)
+b3FixedConstraint : public b3TypedConstraint
{
b3Vector3 m_pivotInA;
b3Vector3 m_pivotInB;
b3Quaternion m_relTargetAB;
public:
- b3FixedConstraint(int rbA,int rbB, const b3Transform& frameInA,const b3Transform& frameInB);
-
+ b3FixedConstraint(int rbA, int rbB, const b3Transform& frameInA, const b3Transform& frameInB);
+
virtual ~b3FixedConstraint();
-
- virtual void getInfo1 (b3ConstraintInfo1* info,const b3RigidBodyData* bodies);
+ virtual void getInfo1(b3ConstraintInfo1 * info, const b3RigidBodyData* bodies);
- virtual void getInfo2 (b3ConstraintInfo2* info, const b3RigidBodyData* bodies);
+ virtual void getInfo2(b3ConstraintInfo2 * info, const b3RigidBodyData* bodies);
- virtual void setParam(int num, b3Scalar value, int axis = -1)
+ virtual void setParam(int num, b3Scalar value, int axis = -1)
{
b3Assert(0);
}
- virtual b3Scalar getParam(int num, int axis = -1) const
+ virtual b3Scalar getParam(int num, int axis = -1) const
{
b3Assert(0);
return 0.f;
}
-
};
-#endif //B3_FIXED_CONSTRAINT_H
+#endif //B3_FIXED_CONSTRAINT_H
diff --git a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3Generic6DofConstraint.cpp b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3Generic6DofConstraint.cpp
index 3ae2922e58..0d5bb2014b 100644
--- a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3Generic6DofConstraint.cpp
+++ b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3Generic6DofConstraint.cpp
@@ -26,69 +26,48 @@ http://gimpact.sf.net
#include "Bullet3Common/b3TransformUtil.h"
#include <new>
-
-
#define D6_USE_OBSOLETE_METHOD false
#define D6_USE_FRAME_OFFSET true
-
-
-
-
-
-b3Generic6DofConstraint::b3Generic6DofConstraint(int rbA,int rbB, const b3Transform& frameInA, const b3Transform& frameInB, bool useLinearReferenceFrameA, const b3RigidBodyData* bodies)
-: b3TypedConstraint(B3_D6_CONSTRAINT_TYPE, rbA, rbB)
-, m_frameInA(frameInA)
-, m_frameInB(frameInB),
-m_useLinearReferenceFrameA(useLinearReferenceFrameA),
-m_useOffsetForConstraintFrame(D6_USE_FRAME_OFFSET),
-m_flags(0)
+b3Generic6DofConstraint::b3Generic6DofConstraint(int rbA, int rbB, const b3Transform& frameInA, const b3Transform& frameInB, bool useLinearReferenceFrameA, const b3RigidBodyData* bodies)
+ : b3TypedConstraint(B3_D6_CONSTRAINT_TYPE, rbA, rbB), m_frameInA(frameInA), m_frameInB(frameInB), m_useLinearReferenceFrameA(useLinearReferenceFrameA), m_useOffsetForConstraintFrame(D6_USE_FRAME_OFFSET), m_flags(0)
{
calculateTransforms(bodies);
}
-
-
-
-
-
#define GENERIC_D6_DISABLE_WARMSTARTING 1
-
-
b3Scalar btGetMatrixElem(const b3Matrix3x3& mat, int index);
b3Scalar btGetMatrixElem(const b3Matrix3x3& mat, int index)
{
- int i = index%3;
- int j = index/3;
+ int i = index % 3;
+ int j = index / 3;
return mat[i][j];
}
-
-
///MatrixToEulerXYZ from http://www.geometrictools.com/LibFoundation/Mathematics/Wm4Matrix3.inl.html
-bool matrixToEulerXYZ(const b3Matrix3x3& mat,b3Vector3& xyz);
-bool matrixToEulerXYZ(const b3Matrix3x3& mat,b3Vector3& xyz)
+bool matrixToEulerXYZ(const b3Matrix3x3& mat, b3Vector3& xyz);
+bool matrixToEulerXYZ(const b3Matrix3x3& mat, b3Vector3& xyz)
{
// // rot = cy*cz -cy*sz sy
// // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx
// // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy
//
- b3Scalar fi = btGetMatrixElem(mat,2);
+ b3Scalar fi = btGetMatrixElem(mat, 2);
if (fi < b3Scalar(1.0f))
{
if (fi > b3Scalar(-1.0f))
{
- xyz[0] = b3Atan2(-btGetMatrixElem(mat,5),btGetMatrixElem(mat,8));
- xyz[1] = b3Asin(btGetMatrixElem(mat,2));
- xyz[2] = b3Atan2(-btGetMatrixElem(mat,1),btGetMatrixElem(mat,0));
+ xyz[0] = b3Atan2(-btGetMatrixElem(mat, 5), btGetMatrixElem(mat, 8));
+ xyz[1] = b3Asin(btGetMatrixElem(mat, 2));
+ xyz[2] = b3Atan2(-btGetMatrixElem(mat, 1), btGetMatrixElem(mat, 0));
return true;
}
else
{
// WARNING. Not unique. XA - ZA = -atan2(r10,r11)
- xyz[0] = -b3Atan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4));
+ xyz[0] = -b3Atan2(btGetMatrixElem(mat, 3), btGetMatrixElem(mat, 4));
xyz[1] = -B3_HALF_PI;
xyz[2] = b3Scalar(0.0);
return false;
@@ -97,7 +76,7 @@ bool matrixToEulerXYZ(const b3Matrix3x3& mat,b3Vector3& xyz)
else
{
// WARNING. Not unique. XAngle + ZAngle = atan2(r10,r11)
- xyz[0] = b3Atan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4));
+ xyz[0] = b3Atan2(btGetMatrixElem(mat, 3), btGetMatrixElem(mat, 4));
xyz[1] = B3_HALF_PI;
xyz[2] = 0.0;
}
@@ -108,85 +87,75 @@ bool matrixToEulerXYZ(const b3Matrix3x3& mat,b3Vector3& xyz)
int b3RotationalLimitMotor::testLimitValue(b3Scalar test_value)
{
- if(m_loLimit>m_hiLimit)
+ if (m_loLimit > m_hiLimit)
{
- m_currentLimit = 0;//Free from violation
+ m_currentLimit = 0; //Free from violation
return 0;
}
if (test_value < m_loLimit)
{
- m_currentLimit = 1;//low limit violation
- m_currentLimitError = test_value - m_loLimit;
- if(m_currentLimitError>B3_PI)
- m_currentLimitError-=B3_2_PI;
- else if(m_currentLimitError<-B3_PI)
- m_currentLimitError+=B3_2_PI;
+ m_currentLimit = 1; //low limit violation
+ m_currentLimitError = test_value - m_loLimit;
+ if (m_currentLimitError > B3_PI)
+ m_currentLimitError -= B3_2_PI;
+ else if (m_currentLimitError < -B3_PI)
+ m_currentLimitError += B3_2_PI;
return 1;
}
- else if (test_value> m_hiLimit)
+ else if (test_value > m_hiLimit)
{
- m_currentLimit = 2;//High limit violation
+ m_currentLimit = 2; //High limit violation
m_currentLimitError = test_value - m_hiLimit;
- if(m_currentLimitError>B3_PI)
- m_currentLimitError-=B3_2_PI;
- else if(m_currentLimitError<-B3_PI)
- m_currentLimitError+=B3_2_PI;
+ if (m_currentLimitError > B3_PI)
+ m_currentLimitError -= B3_2_PI;
+ else if (m_currentLimitError < -B3_PI)
+ m_currentLimitError += B3_2_PI;
return 2;
};
- m_currentLimit = 0;//Free from violation
+ m_currentLimit = 0; //Free from violation
return 0;
-
}
-
-
-
//////////////////////////// End b3RotationalLimitMotor ////////////////////////////////////
-
-
-
//////////////////////////// b3TranslationalLimitMotor ////////////////////////////////////
-
int b3TranslationalLimitMotor::testLimitValue(int limitIndex, b3Scalar test_value)
{
b3Scalar loLimit = m_lowerLimit[limitIndex];
b3Scalar hiLimit = m_upperLimit[limitIndex];
- if(loLimit > hiLimit)
+ if (loLimit > hiLimit)
{
- m_currentLimit[limitIndex] = 0;//Free from violation
+ m_currentLimit[limitIndex] = 0; //Free from violation
m_currentLimitError[limitIndex] = b3Scalar(0.f);
return 0;
}
if (test_value < loLimit)
{
- m_currentLimit[limitIndex] = 2;//low limit violation
- m_currentLimitError[limitIndex] = test_value - loLimit;
+ m_currentLimit[limitIndex] = 2; //low limit violation
+ m_currentLimitError[limitIndex] = test_value - loLimit;
return 2;
}
- else if (test_value> hiLimit)
+ else if (test_value > hiLimit)
{
- m_currentLimit[limitIndex] = 1;//High limit violation
+ m_currentLimit[limitIndex] = 1; //High limit violation
m_currentLimitError[limitIndex] = test_value - hiLimit;
return 1;
};
- m_currentLimit[limitIndex] = 0;//Free from violation
+ m_currentLimit[limitIndex] = 0; //Free from violation
m_currentLimitError[limitIndex] = b3Scalar(0.f);
return 0;
}
-
-
//////////////////////////// b3TranslationalLimitMotor ////////////////////////////////////
void b3Generic6DofConstraint::calculateAngleInfo()
{
- b3Matrix3x3 relative_frame = m_calculatedTransformA.getBasis().inverse()*m_calculatedTransformB.getBasis();
- matrixToEulerXYZ(relative_frame,m_calculatedAxisAngleDiff);
+ b3Matrix3x3 relative_frame = m_calculatedTransformA.getBasis().inverse() * m_calculatedTransformB.getBasis();
+ matrixToEulerXYZ(relative_frame, m_calculatedAxisAngleDiff);
// 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]) :
//
@@ -211,12 +180,11 @@ void b3Generic6DofConstraint::calculateAngleInfo()
m_calculatedAxis[0].normalize();
m_calculatedAxis[1].normalize();
m_calculatedAxis[2].normalize();
-
}
static b3Transform getCenterOfMassTransform(const b3RigidBodyData& body)
{
- b3Transform tr(body.m_quat,body.m_pos);
+ b3Transform tr(body.m_quat, body.m_pos);
return tr;
}
@@ -226,26 +194,26 @@ void b3Generic6DofConstraint::calculateTransforms(const b3RigidBodyData* bodies)
b3Transform transB;
transA = getCenterOfMassTransform(bodies[m_rbA]);
transB = getCenterOfMassTransform(bodies[m_rbB]);
- calculateTransforms(transA,transB,bodies);
+ calculateTransforms(transA, transB, bodies);
}
-void b3Generic6DofConstraint::calculateTransforms(const b3Transform& transA,const b3Transform& transB,const b3RigidBodyData* bodies)
+void b3Generic6DofConstraint::calculateTransforms(const b3Transform& transA, const b3Transform& transB, const b3RigidBodyData* bodies)
{
m_calculatedTransformA = transA * m_frameInA;
m_calculatedTransformB = transB * m_frameInB;
calculateLinearInfo();
calculateAngleInfo();
- if(m_useOffsetForConstraintFrame)
- { // get weight factors depending on masses
+ if (m_useOffsetForConstraintFrame)
+ { // get weight factors depending on masses
b3Scalar miA = bodies[m_rbA].m_invMass;
b3Scalar miB = bodies[m_rbB].m_invMass;
m_hasStaticBody = (miA < B3_EPSILON) || (miB < B3_EPSILON);
b3Scalar miS = miA + miB;
- if(miS > b3Scalar(0.f))
+ if (miS > b3Scalar(0.f))
{
m_factA = miB / miS;
}
- else
+ else
{
m_factA = b3Scalar(0.5f);
}
@@ -253,12 +221,6 @@ void b3Generic6DofConstraint::calculateTransforms(const b3Transform& transA,cons
}
}
-
-
-
-
-
-
bool b3Generic6DofConstraint::testAngularLimitMotor(int axis_index)
{
b3Scalar angle = m_calculatedAxisAngleDiff[axis_index];
@@ -269,48 +231,43 @@ bool b3Generic6DofConstraint::testAngularLimitMotor(int axis_index)
return m_angularLimits[axis_index].needApplyTorques();
}
-
-
-
-void b3Generic6DofConstraint::getInfo1 (b3ConstraintInfo1* info,const b3RigidBodyData* bodies)
+void b3Generic6DofConstraint::getInfo1(b3ConstraintInfo1* info, const b3RigidBodyData* bodies)
{
//prepare constraint
- calculateTransforms(getCenterOfMassTransform(bodies[m_rbA]),getCenterOfMassTransform(bodies[m_rbB]),bodies);
+ calculateTransforms(getCenterOfMassTransform(bodies[m_rbA]), getCenterOfMassTransform(bodies[m_rbB]), bodies);
info->m_numConstraintRows = 0;
info->nub = 6;
int i;
//test linear limits
- for(i = 0; i < 3; i++)
+ for (i = 0; i < 3; i++)
{
- if(m_linearLimits.needApplyForce(i))
+ if (m_linearLimits.needApplyForce(i))
{
info->m_numConstraintRows++;
info->nub--;
}
}
//test angular limits
- for (i=0;i<3 ;i++ )
+ for (i = 0; i < 3; i++)
{
- if(testAngularLimitMotor(i))
+ if (testAngularLimitMotor(i))
{
info->m_numConstraintRows++;
info->nub--;
}
}
-// printf("info->m_numConstraintRows=%d\n",info->m_numConstraintRows);
+ // printf("info->m_numConstraintRows=%d\n",info->m_numConstraintRows);
}
-void b3Generic6DofConstraint::getInfo1NonVirtual (b3ConstraintInfo1* info,const b3RigidBodyData* bodies)
+void b3Generic6DofConstraint::getInfo1NonVirtual(b3ConstraintInfo1* info, const b3RigidBodyData* bodies)
{
//pre-allocate all 6
info->m_numConstraintRows = 6;
info->nub = 0;
}
-
-void b3Generic6DofConstraint::getInfo2 (b3ConstraintInfo2* info,const b3RigidBodyData* bodies)
+void b3Generic6DofConstraint::getInfo2(b3ConstraintInfo2* info, const b3RigidBodyData* bodies)
{
-
b3Transform transA = getCenterOfMassTransform(bodies[m_rbA]);
b3Transform transB = getCenterOfMassTransform(bodies[m_rbB]);
const b3Vector3& linVelA = bodies[m_rbA].m_linVel;
@@ -318,136 +275,124 @@ void b3Generic6DofConstraint::getInfo2 (b3ConstraintInfo2* info,const b3RigidBod
const b3Vector3& angVelA = bodies[m_rbA].m_angVel;
const b3Vector3& angVelB = bodies[m_rbB].m_angVel;
- if(m_useOffsetForConstraintFrame)
- { // for stability better to solve angular limits first
- int row = setAngularLimits(info, 0,transA,transB,linVelA,linVelB,angVelA,angVelB);
- setLinearLimits(info, row, transA,transB,linVelA,linVelB,angVelA,angVelB);
+ if (m_useOffsetForConstraintFrame)
+ { // for stability better to solve angular limits first
+ int row = setAngularLimits(info, 0, transA, transB, linVelA, linVelB, angVelA, angVelB);
+ setLinearLimits(info, row, transA, transB, linVelA, linVelB, angVelA, angVelB);
}
else
- { // leave old version for compatibility
- int row = setLinearLimits(info, 0, transA,transB,linVelA,linVelB,angVelA,angVelB);
- setAngularLimits(info, row,transA,transB,linVelA,linVelB,angVelA,angVelB);
+ { // leave old version for compatibility
+ int row = setLinearLimits(info, 0, transA, transB, linVelA, linVelB, angVelA, angVelB);
+ setAngularLimits(info, row, transA, transB, linVelA, linVelB, angVelA, angVelB);
}
-
}
-
-void b3Generic6DofConstraint::getInfo2NonVirtual (b3ConstraintInfo2* info, const b3Transform& transA,const b3Transform& transB,const b3Vector3& linVelA,const b3Vector3& linVelB,const b3Vector3& angVelA,const b3Vector3& angVelB,const b3RigidBodyData* bodies)
+void b3Generic6DofConstraint::getInfo2NonVirtual(b3ConstraintInfo2* info, const b3Transform& transA, const b3Transform& transB, const b3Vector3& linVelA, const b3Vector3& linVelB, const b3Vector3& angVelA, const b3Vector3& angVelB, const b3RigidBodyData* bodies)
{
-
//prepare constraint
- calculateTransforms(transA,transB,bodies);
+ calculateTransforms(transA, transB, bodies);
int i;
- for (i=0;i<3 ;i++ )
+ for (i = 0; i < 3; i++)
{
testAngularLimitMotor(i);
}
- if(m_useOffsetForConstraintFrame)
- { // for stability better to solve angular limits first
- int row = setAngularLimits(info, 0,transA,transB,linVelA,linVelB,angVelA,angVelB);
- setLinearLimits(info, row, transA,transB,linVelA,linVelB,angVelA,angVelB);
+ if (m_useOffsetForConstraintFrame)
+ { // for stability better to solve angular limits first
+ int row = setAngularLimits(info, 0, transA, transB, linVelA, linVelB, angVelA, angVelB);
+ setLinearLimits(info, row, transA, transB, linVelA, linVelB, angVelA, angVelB);
}
else
- { // leave old version for compatibility
- int row = setLinearLimits(info, 0, transA,transB,linVelA,linVelB,angVelA,angVelB);
- setAngularLimits(info, row,transA,transB,linVelA,linVelB,angVelA,angVelB);
+ { // leave old version for compatibility
+ int row = setLinearLimits(info, 0, transA, transB, linVelA, linVelB, angVelA, angVelB);
+ setAngularLimits(info, row, transA, transB, linVelA, linVelB, angVelA, angVelB);
}
}
-
-
-int b3Generic6DofConstraint::setLinearLimits(b3ConstraintInfo2* info, int row, const b3Transform& transA,const b3Transform& transB,const b3Vector3& linVelA,const b3Vector3& linVelB,const b3Vector3& angVelA,const b3Vector3& angVelB)
+int b3Generic6DofConstraint::setLinearLimits(b3ConstraintInfo2* info, int row, const b3Transform& transA, const b3Transform& transB, const b3Vector3& linVelA, const b3Vector3& linVelB, const b3Vector3& angVelA, const b3Vector3& angVelB)
{
-// int row = 0;
+ // int row = 0;
//solve linear limits
b3RotationalLimitMotor limot;
- for (int i=0;i<3 ;i++ )
+ for (int i = 0; i < 3; i++)
{
- if(m_linearLimits.needApplyForce(i))
- { // re-use rotational motor code
+ if (m_linearLimits.needApplyForce(i))
+ { // re-use rotational motor code
limot.m_bounce = b3Scalar(0.f);
limot.m_currentLimit = m_linearLimits.m_currentLimit[i];
limot.m_currentPosition = m_linearLimits.m_currentLinearDiff[i];
- limot.m_currentLimitError = m_linearLimits.m_currentLimitError[i];
- limot.m_damping = m_linearLimits.m_damping;
- limot.m_enableMotor = m_linearLimits.m_enableMotor[i];
- limot.m_hiLimit = m_linearLimits.m_upperLimit[i];
- limot.m_limitSoftness = m_linearLimits.m_limitSoftness;
- limot.m_loLimit = m_linearLimits.m_lowerLimit[i];
- limot.m_maxLimitForce = b3Scalar(0.f);
- limot.m_maxMotorForce = m_linearLimits.m_maxMotorForce[i];
- limot.m_targetVelocity = m_linearLimits.m_targetVelocity[i];
+ limot.m_currentLimitError = m_linearLimits.m_currentLimitError[i];
+ limot.m_damping = m_linearLimits.m_damping;
+ limot.m_enableMotor = m_linearLimits.m_enableMotor[i];
+ limot.m_hiLimit = m_linearLimits.m_upperLimit[i];
+ limot.m_limitSoftness = m_linearLimits.m_limitSoftness;
+ limot.m_loLimit = m_linearLimits.m_lowerLimit[i];
+ limot.m_maxLimitForce = b3Scalar(0.f);
+ limot.m_maxMotorForce = m_linearLimits.m_maxMotorForce[i];
+ limot.m_targetVelocity = m_linearLimits.m_targetVelocity[i];
b3Vector3 axis = m_calculatedTransformA.getBasis().getColumn(i);
int flags = m_flags >> (i * B3_6DOF_FLAGS_AXIS_SHIFT);
- limot.m_normalCFM = (flags & B3_6DOF_FLAGS_CFM_NORM) ? m_linearLimits.m_normalCFM[i] : info->cfm[0];
- limot.m_stopCFM = (flags & B3_6DOF_FLAGS_CFM_STOP) ? m_linearLimits.m_stopCFM[i] : info->cfm[0];
- limot.m_stopERP = (flags & B3_6DOF_FLAGS_ERP_STOP) ? m_linearLimits.m_stopERP[i] : info->erp;
- if(m_useOffsetForConstraintFrame)
+ limot.m_normalCFM = (flags & B3_6DOF_FLAGS_CFM_NORM) ? m_linearLimits.m_normalCFM[i] : info->cfm[0];
+ limot.m_stopCFM = (flags & B3_6DOF_FLAGS_CFM_STOP) ? m_linearLimits.m_stopCFM[i] : info->cfm[0];
+ limot.m_stopERP = (flags & B3_6DOF_FLAGS_ERP_STOP) ? m_linearLimits.m_stopERP[i] : info->erp;
+ if (m_useOffsetForConstraintFrame)
{
int indx1 = (i + 1) % 3;
int indx2 = (i + 2) % 3;
- int rotAllowed = 1; // rotations around orthos to current axis
- if(m_angularLimits[indx1].m_currentLimit && m_angularLimits[indx2].m_currentLimit)
+ int rotAllowed = 1; // rotations around orthos to current axis
+ if (m_angularLimits[indx1].m_currentLimit && m_angularLimits[indx2].m_currentLimit)
{
rotAllowed = 0;
}
- row += get_limit_motor_info2(&limot, transA,transB,linVelA,linVelB,angVelA,angVelB, info, row, axis, 0, rotAllowed);
+ row += get_limit_motor_info2(&limot, transA, transB, linVelA, linVelB, angVelA, angVelB, info, row, axis, 0, rotAllowed);
}
else
{
- row += get_limit_motor_info2(&limot, transA,transB,linVelA,linVelB,angVelA,angVelB, info, row, axis, 0);
+ row += get_limit_motor_info2(&limot, transA, transB, linVelA, linVelB, angVelA, angVelB, info, row, axis, 0);
}
}
}
return row;
}
-
-
-int b3Generic6DofConstraint::setAngularLimits(b3ConstraintInfo2 *info, int row_offset, const b3Transform& transA,const b3Transform& transB,const b3Vector3& linVelA,const b3Vector3& linVelB,const b3Vector3& angVelA,const b3Vector3& angVelB)
+int b3Generic6DofConstraint::setAngularLimits(b3ConstraintInfo2* info, int row_offset, const b3Transform& transA, const b3Transform& transB, const b3Vector3& linVelA, const b3Vector3& linVelB, const b3Vector3& angVelA, const b3Vector3& angVelB)
{
- b3Generic6DofConstraint * d6constraint = this;
+ b3Generic6DofConstraint* d6constraint = this;
int row = row_offset;
//solve angular limits
- for (int i=0;i<3 ;i++ )
+ for (int i = 0; i < 3; i++)
{
- if(d6constraint->getRotationalLimitMotor(i)->needApplyTorques())
+ if (d6constraint->getRotationalLimitMotor(i)->needApplyTorques())
{
b3Vector3 axis = d6constraint->getAxis(i);
int flags = m_flags >> ((i + 3) * B3_6DOF_FLAGS_AXIS_SHIFT);
- if(!(flags & B3_6DOF_FLAGS_CFM_NORM))
+ if (!(flags & B3_6DOF_FLAGS_CFM_NORM))
{
m_angularLimits[i].m_normalCFM = info->cfm[0];
}
- if(!(flags & B3_6DOF_FLAGS_CFM_STOP))
+ if (!(flags & B3_6DOF_FLAGS_CFM_STOP))
{
m_angularLimits[i].m_stopCFM = info->cfm[0];
}
- if(!(flags & B3_6DOF_FLAGS_ERP_STOP))
+ if (!(flags & B3_6DOF_FLAGS_ERP_STOP))
{
m_angularLimits[i].m_stopERP = info->erp;
}
row += get_limit_motor_info2(d6constraint->getRotationalLimitMotor(i),
- transA,transB,linVelA,linVelB,angVelA,angVelB, info,row,axis,1);
+ transA, transB, linVelA, linVelB, angVelA, angVelB, info, row, axis, 1);
}
}
return row;
}
-
-
-
-void b3Generic6DofConstraint::updateRHS(b3Scalar timeStep)
+void b3Generic6DofConstraint::updateRHS(b3Scalar timeStep)
{
(void)timeStep;
-
}
-
-void b3Generic6DofConstraint::setFrames(const b3Transform& frameA, const b3Transform& frameB,const b3RigidBodyData* bodies)
+void b3Generic6DofConstraint::setFrames(const b3Transform& frameA, const b3Transform& frameB, const b3RigidBodyData* bodies)
{
m_frameInA = frameA;
m_frameInB = frameB;
@@ -455,33 +400,27 @@ void b3Generic6DofConstraint::setFrames(const b3Transform& frameA, const b3Trans
calculateTransforms(bodies);
}
-
-
b3Vector3 b3Generic6DofConstraint::getAxis(int axis_index) const
{
return m_calculatedAxis[axis_index];
}
-
-b3Scalar b3Generic6DofConstraint::getRelativePivotPosition(int axisIndex) const
+b3Scalar b3Generic6DofConstraint::getRelativePivotPosition(int axisIndex) const
{
return m_calculatedLinearDiff[axisIndex];
}
-
b3Scalar b3Generic6DofConstraint::getAngle(int axisIndex) const
{
return m_calculatedAxisAngleDiff[axisIndex];
}
-
-
void b3Generic6DofConstraint::calcAnchorPos(const b3RigidBodyData* bodies)
{
b3Scalar imA = bodies[m_rbA].m_invMass;
b3Scalar imB = bodies[m_rbB].m_invMass;
b3Scalar weight;
- if(imB == b3Scalar(0.0))
+ if (imB == b3Scalar(0.0))
{
weight = b3Scalar(1.0);
}
@@ -495,47 +434,43 @@ void b3Generic6DofConstraint::calcAnchorPos(const b3RigidBodyData* bodies)
return;
}
-
-
void b3Generic6DofConstraint::calculateLinearInfo()
{
m_calculatedLinearDiff = m_calculatedTransformB.getOrigin() - m_calculatedTransformA.getOrigin();
m_calculatedLinearDiff = m_calculatedTransformA.getBasis().inverse() * m_calculatedLinearDiff;
- for(int i = 0; i < 3; i++)
+ for (int i = 0; i < 3; i++)
{
m_linearLimits.m_currentLinearDiff[i] = m_calculatedLinearDiff[i];
m_linearLimits.testLimitValue(i, m_calculatedLinearDiff[i]);
}
}
-
-
int b3Generic6DofConstraint::get_limit_motor_info2(
- b3RotationalLimitMotor * limot,
- const b3Transform& transA,const b3Transform& transB,const b3Vector3& linVelA,const b3Vector3& linVelB,const b3Vector3& angVelA,const b3Vector3& angVelB,
- b3ConstraintInfo2 *info, int row, b3Vector3& ax1, int rotational,int rotAllowed)
+ b3RotationalLimitMotor* limot,
+ const b3Transform& transA, const b3Transform& transB, const b3Vector3& linVelA, const b3Vector3& linVelB, const b3Vector3& angVelA, const b3Vector3& angVelB,
+ b3ConstraintInfo2* info, int row, b3Vector3& ax1, int rotational, int rotAllowed)
{
- int srow = row * info->rowskip;
- bool powered = limot->m_enableMotor;
- int limit = limot->m_currentLimit;
- if (powered || limit)
- { // if the joint is powered, or has joint limits, add in the extra row
- b3Scalar *J1 = rotational ? info->m_J1angularAxis : info->m_J1linearAxis;
- b3Scalar *J2 = rotational ? info->m_J2angularAxis : info->m_J2linearAxis;
+ int srow = row * info->rowskip;
+ bool powered = limot->m_enableMotor;
+ int limit = limot->m_currentLimit;
+ if (powered || limit)
+ { // if the joint is powered, or has joint limits, add in the extra row
+ b3Scalar* J1 = rotational ? info->m_J1angularAxis : info->m_J1linearAxis;
+ b3Scalar* J2 = rotational ? info->m_J2angularAxis : info->m_J2linearAxis;
if (J1)
{
- J1[srow+0] = ax1[0];
- J1[srow+1] = ax1[1];
- J1[srow+2] = ax1[2];
+ J1[srow + 0] = ax1[0];
+ J1[srow + 1] = ax1[1];
+ J1[srow + 2] = ax1[2];
}
if (J2)
{
- J2[srow+0] = -ax1[0];
- J2[srow+1] = -ax1[1];
- J2[srow+2] = -ax1[2];
+ J2[srow + 0] = -ax1[0];
+ J2[srow + 1] = -ax1[1];
+ J2[srow + 2] = -ax1[2];
}
- if((!rotational))
- {
+ if ((!rotational))
+ {
if (m_useOffsetForConstraintFrame)
{
b3Vector3 tmpA, tmpB, relA, relB;
@@ -558,55 +493,56 @@ int b3Generic6DofConstraint::get_limit_motor_info2(
relB = orthoB - totalDist * m_factB;
tmpA = relA.cross(ax1);
tmpB = relB.cross(ax1);
- if(m_hasStaticBody && (!rotAllowed))
+ if (m_hasStaticBody && (!rotAllowed))
{
tmpA *= m_factA;
tmpB *= m_factB;
}
int i;
- for (i=0; i<3; i++) info->m_J1angularAxis[srow+i] = tmpA[i];
- for (i=0; i<3; i++) info->m_J2angularAxis[srow+i] = -tmpB[i];
- } else
+ for (i = 0; i < 3; i++) info->m_J1angularAxis[srow + i] = tmpA[i];
+ for (i = 0; i < 3; i++) info->m_J2angularAxis[srow + i] = -tmpB[i];
+ }
+ else
{
- b3Vector3 ltd; // Linear Torque Decoupling vector
+ b3Vector3 ltd; // Linear Torque Decoupling vector
b3Vector3 c = m_calculatedTransformB.getOrigin() - transA.getOrigin();
ltd = c.cross(ax1);
- info->m_J1angularAxis[srow+0] = ltd[0];
- info->m_J1angularAxis[srow+1] = ltd[1];
- info->m_J1angularAxis[srow+2] = ltd[2];
+ info->m_J1angularAxis[srow + 0] = ltd[0];
+ info->m_J1angularAxis[srow + 1] = ltd[1];
+ info->m_J1angularAxis[srow + 2] = ltd[2];
c = m_calculatedTransformB.getOrigin() - transB.getOrigin();
ltd = -c.cross(ax1);
- info->m_J2angularAxis[srow+0] = ltd[0];
- info->m_J2angularAxis[srow+1] = ltd[1];
- info->m_J2angularAxis[srow+2] = ltd[2];
+ info->m_J2angularAxis[srow + 0] = ltd[0];
+ info->m_J2angularAxis[srow + 1] = ltd[1];
+ info->m_J2angularAxis[srow + 2] = ltd[2];
}
- }
- // if we're limited low and high simultaneously, the joint motor is
- // ineffective
- if (limit && (limot->m_loLimit == limot->m_hiLimit)) powered = false;
- info->m_constraintError[srow] = b3Scalar(0.f);
- if (powered)
- {
+ }
+ // if we're limited low and high simultaneously, the joint motor is
+ // ineffective
+ if (limit && (limot->m_loLimit == limot->m_hiLimit)) powered = false;
+ info->m_constraintError[srow] = b3Scalar(0.f);
+ if (powered)
+ {
info->cfm[srow] = limot->m_normalCFM;
- if(!limit)
- {
+ if (!limit)
+ {
b3Scalar tag_vel = rotational ? limot->m_targetVelocity : -limot->m_targetVelocity;
- b3Scalar mot_fact = getMotorFactor( limot->m_currentPosition,
- limot->m_loLimit,
- limot->m_hiLimit,
- tag_vel,
- info->fps * limot->m_stopERP);
+ b3Scalar mot_fact = getMotorFactor(limot->m_currentPosition,
+ limot->m_loLimit,
+ limot->m_hiLimit,
+ tag_vel,
+ info->fps * limot->m_stopERP);
info->m_constraintError[srow] += mot_fact * limot->m_targetVelocity;
- info->m_lowerLimit[srow] = -limot->m_maxMotorForce / info->fps;
- info->m_upperLimit[srow] = limot->m_maxMotorForce / info->fps;
- }
- }
- if(limit)
- {
- b3Scalar k = info->fps * limot->m_stopERP;
- if(!rotational)
+ info->m_lowerLimit[srow] = -limot->m_maxMotorForce / info->fps;
+ info->m_upperLimit[srow] = limot->m_maxMotorForce / info->fps;
+ }
+ }
+ if (limit)
+ {
+ b3Scalar k = info->fps * limot->m_stopERP;
+ if (!rotational)
{
info->m_constraintError[srow] += k * limot->m_currentLimitError;
}
@@ -615,116 +551,112 @@ int b3Generic6DofConstraint::get_limit_motor_info2(
info->m_constraintError[srow] += -k * limot->m_currentLimitError;
}
info->cfm[srow] = limot->m_stopCFM;
- if (limot->m_loLimit == limot->m_hiLimit)
- { // limited low and high simultaneously
- info->m_lowerLimit[srow] = -B3_INFINITY;
- info->m_upperLimit[srow] = B3_INFINITY;
- }
- else
- {
- if (limit == 1)
- {
- info->m_lowerLimit[srow] = 0;
- info->m_upperLimit[srow] = B3_INFINITY;
- }
- else
- {
- info->m_lowerLimit[srow] = -B3_INFINITY;
- info->m_upperLimit[srow] = 0;
- }
- // deal with bounce
- if (limot->m_bounce > 0)
- {
- // calculate joint velocity
- b3Scalar vel;
- if (rotational)
- {
- vel = angVelA.dot(ax1);
-//make sure that if no body -> angVelB == zero vec
-// if (body1)
- vel -= angVelB.dot(ax1);
- }
- else
- {
- vel = linVelA.dot(ax1);
-//make sure that if no body -> angVelB == zero vec
-// if (body1)
- vel -= linVelB.dot(ax1);
- }
- // only apply bounce if the velocity is incoming, and if the
- // resulting c[] exceeds what we already have.
- if (limit == 1)
- {
- if (vel < 0)
- {
- b3Scalar newc = -limot->m_bounce* vel;
- if (newc > info->m_constraintError[srow])
+ if (limot->m_loLimit == limot->m_hiLimit)
+ { // limited low and high simultaneously
+ info->m_lowerLimit[srow] = -B3_INFINITY;
+ info->m_upperLimit[srow] = B3_INFINITY;
+ }
+ else
+ {
+ if (limit == 1)
+ {
+ info->m_lowerLimit[srow] = 0;
+ info->m_upperLimit[srow] = B3_INFINITY;
+ }
+ else
+ {
+ info->m_lowerLimit[srow] = -B3_INFINITY;
+ info->m_upperLimit[srow] = 0;
+ }
+ // deal with bounce
+ if (limot->m_bounce > 0)
+ {
+ // calculate joint velocity
+ b3Scalar vel;
+ if (rotational)
+ {
+ vel = angVelA.dot(ax1);
+ //make sure that if no body -> angVelB == zero vec
+ // if (body1)
+ vel -= angVelB.dot(ax1);
+ }
+ else
+ {
+ vel = linVelA.dot(ax1);
+ //make sure that if no body -> angVelB == zero vec
+ // if (body1)
+ vel -= linVelB.dot(ax1);
+ }
+ // only apply bounce if the velocity is incoming, and if the
+ // resulting c[] exceeds what we already have.
+ if (limit == 1)
+ {
+ if (vel < 0)
+ {
+ b3Scalar newc = -limot->m_bounce * vel;
+ if (newc > info->m_constraintError[srow])
info->m_constraintError[srow] = newc;
- }
- }
- else
- {
- if (vel > 0)
- {
- b3Scalar newc = -limot->m_bounce * vel;
- if (newc < info->m_constraintError[srow])
+ }
+ }
+ else
+ {
+ if (vel > 0)
+ {
+ b3Scalar newc = -limot->m_bounce * vel;
+ if (newc < info->m_constraintError[srow])
info->m_constraintError[srow] = newc;
- }
- }
- }
- }
- }
- return 1;
- }
- else return 0;
+ }
+ }
+ }
+ }
+ }
+ return 1;
+ }
+ else
+ return 0;
}
-
-
-
-
-
- ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
- ///If no axis is provided, it uses the default axis for this constraint.
+///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+///If no axis is provided, it uses the default axis for this constraint.
void b3Generic6DofConstraint::setParam(int num, b3Scalar value, int axis)
{
- if((axis >= 0) && (axis < 3))
+ if ((axis >= 0) && (axis < 3))
{
- switch(num)
+ switch (num)
{
- case B3_CONSTRAINT_STOP_ERP :
+ case B3_CONSTRAINT_STOP_ERP:
m_linearLimits.m_stopERP[axis] = value;
m_flags |= B3_6DOF_FLAGS_ERP_STOP << (axis * B3_6DOF_FLAGS_AXIS_SHIFT);
break;
- case B3_CONSTRAINT_STOP_CFM :
+ case B3_CONSTRAINT_STOP_CFM:
m_linearLimits.m_stopCFM[axis] = value;
m_flags |= B3_6DOF_FLAGS_CFM_STOP << (axis * B3_6DOF_FLAGS_AXIS_SHIFT);
break;
- case B3_CONSTRAINT_CFM :
+ case B3_CONSTRAINT_CFM:
m_linearLimits.m_normalCFM[axis] = value;
m_flags |= B3_6DOF_FLAGS_CFM_NORM << (axis * B3_6DOF_FLAGS_AXIS_SHIFT);
break;
- default :
+ default:
b3AssertConstrParams(0);
}
}
- else if((axis >=3) && (axis < 6))
+ else if ((axis >= 3) && (axis < 6))
{
- switch(num)
+ switch (num)
{
- case B3_CONSTRAINT_STOP_ERP :
+ case B3_CONSTRAINT_STOP_ERP:
m_angularLimits[axis - 3].m_stopERP = value;
m_flags |= B3_6DOF_FLAGS_ERP_STOP << (axis * B3_6DOF_FLAGS_AXIS_SHIFT);
break;
- case B3_CONSTRAINT_STOP_CFM :
+ case B3_CONSTRAINT_STOP_CFM:
m_angularLimits[axis - 3].m_stopCFM = value;
m_flags |= B3_6DOF_FLAGS_CFM_STOP << (axis * B3_6DOF_FLAGS_AXIS_SHIFT);
break;
- case B3_CONSTRAINT_CFM :
+ case B3_CONSTRAINT_CFM:
m_angularLimits[axis - 3].m_normalCFM = value;
m_flags |= B3_6DOF_FLAGS_CFM_NORM << (axis * B3_6DOF_FLAGS_AXIS_SHIFT);
break;
- default :
+ default:
b3AssertConstrParams(0);
}
}
@@ -734,47 +666,47 @@ void b3Generic6DofConstraint::setParam(int num, b3Scalar value, int axis)
}
}
- ///return the local value of parameter
-b3Scalar b3Generic6DofConstraint::getParam(int num, int axis) const
+///return the local value of parameter
+b3Scalar b3Generic6DofConstraint::getParam(int num, int axis) const
{
b3Scalar retVal = 0;
- if((axis >= 0) && (axis < 3))
+ if ((axis >= 0) && (axis < 3))
{
- switch(num)
+ switch (num)
{
- case B3_CONSTRAINT_STOP_ERP :
+ case B3_CONSTRAINT_STOP_ERP:
b3AssertConstrParams(m_flags & (B3_6DOF_FLAGS_ERP_STOP << (axis * B3_6DOF_FLAGS_AXIS_SHIFT)));
retVal = m_linearLimits.m_stopERP[axis];
break;
- case B3_CONSTRAINT_STOP_CFM :
+ case B3_CONSTRAINT_STOP_CFM:
b3AssertConstrParams(m_flags & (B3_6DOF_FLAGS_CFM_STOP << (axis * B3_6DOF_FLAGS_AXIS_SHIFT)));
retVal = m_linearLimits.m_stopCFM[axis];
break;
- case B3_CONSTRAINT_CFM :
+ case B3_CONSTRAINT_CFM:
b3AssertConstrParams(m_flags & (B3_6DOF_FLAGS_CFM_NORM << (axis * B3_6DOF_FLAGS_AXIS_SHIFT)));
retVal = m_linearLimits.m_normalCFM[axis];
break;
- default :
+ default:
b3AssertConstrParams(0);
}
}
- else if((axis >=3) && (axis < 6))
+ else if ((axis >= 3) && (axis < 6))
{
- switch(num)
+ switch (num)
{
- case B3_CONSTRAINT_STOP_ERP :
+ case B3_CONSTRAINT_STOP_ERP:
b3AssertConstrParams(m_flags & (B3_6DOF_FLAGS_ERP_STOP << (axis * B3_6DOF_FLAGS_AXIS_SHIFT)));
retVal = m_angularLimits[axis - 3].m_stopERP;
break;
- case B3_CONSTRAINT_STOP_CFM :
+ case B3_CONSTRAINT_STOP_CFM:
b3AssertConstrParams(m_flags & (B3_6DOF_FLAGS_CFM_STOP << (axis * B3_6DOF_FLAGS_AXIS_SHIFT)));
retVal = m_angularLimits[axis - 3].m_stopCFM;
break;
- case B3_CONSTRAINT_CFM :
+ case B3_CONSTRAINT_CFM:
b3AssertConstrParams(m_flags & (B3_6DOF_FLAGS_CFM_NORM << (axis * B3_6DOF_FLAGS_AXIS_SHIFT)));
retVal = m_angularLimits[axis - 3].m_normalCFM;
break;
- default :
+ default:
b3AssertConstrParams(0);
}
}
@@ -785,23 +717,21 @@ b3Scalar b3Generic6DofConstraint::getParam(int num, int axis) const
return retVal;
}
-
-
-void b3Generic6DofConstraint::setAxis(const b3Vector3& axis1,const b3Vector3& axis2, const b3RigidBodyData* bodies)
+void b3Generic6DofConstraint::setAxis(const b3Vector3& axis1, const b3Vector3& axis2, const b3RigidBodyData* bodies)
{
b3Vector3 zAxis = axis1.normalized();
b3Vector3 yAxis = axis2.normalized();
- b3Vector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system
-
+ b3Vector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system
+
b3Transform frameInW;
frameInW.setIdentity();
- frameInW.getBasis().setValue( xAxis[0], yAxis[0], zAxis[0],
- xAxis[1], yAxis[1], zAxis[1],
- xAxis[2], yAxis[2], zAxis[2]);
-
+ frameInW.getBasis().setValue(xAxis[0], yAxis[0], zAxis[0],
+ xAxis[1], yAxis[1], zAxis[1],
+ xAxis[2], yAxis[2], zAxis[2]);
+
// now get constraint frame in local coordinate systems
m_frameInA = getCenterOfMassTransform(bodies[m_rbA]).inverse() * frameInW;
m_frameInB = getCenterOfMassTransform(bodies[m_rbB]).inverse() * frameInW;
-
+
calculateTransforms(bodies);
}
diff --git a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3Generic6DofConstraint.h b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3Generic6DofConstraint.h
index 169b1b94ad..1597809db3 100644
--- a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3Generic6DofConstraint.h
+++ b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3Generic6DofConstraint.h
@@ -23,7 +23,6 @@ email: projectileman@yahoo.com
http://gimpact.sf.net
*/
-
#ifndef B3_GENERIC_6DOF_CONSTRAINT_H
#define B3_GENERIC_6DOF_CONSTRAINT_H
@@ -33,88 +32,83 @@ http://gimpact.sf.net
struct b3RigidBodyData;
-
-
-
//! Rotation Limit structure for generic joints
class b3RotationalLimitMotor
{
public:
- //! limit_parameters
- //!@{
- b3Scalar m_loLimit;//!< joint limit
- b3Scalar m_hiLimit;//!< joint limit
- b3Scalar m_targetVelocity;//!< target motor velocity
- b3Scalar m_maxMotorForce;//!< max force on motor
- b3Scalar m_maxLimitForce;//!< max force on limit
- b3Scalar m_damping;//!< Damping.
- b3Scalar m_limitSoftness;//! Relaxation factor
- b3Scalar m_normalCFM;//!< Constraint force mixing factor
- b3Scalar m_stopERP;//!< Error tolerance factor when joint is at limit
- b3Scalar m_stopCFM;//!< Constraint force mixing factor when joint is at limit
- b3Scalar m_bounce;//!< restitution factor
- bool m_enableMotor;
-
- //!@}
-
- //! temp_variables
- //!@{
- b3Scalar m_currentLimitError;//! How much is violated this limit
- b3Scalar m_currentPosition; //! current value of angle
- int m_currentLimit;//!< 0=free, 1=at lo limit, 2=at hi limit
- b3Scalar m_accumulatedImpulse;
- //!@}
-
- b3RotationalLimitMotor()
- {
- m_accumulatedImpulse = 0.f;
- m_targetVelocity = 0;
- m_maxMotorForce = 6.0f;
- m_maxLimitForce = 300.0f;
- m_loLimit = 1.0f;
- m_hiLimit = -1.0f;
+ //! limit_parameters
+ //!@{
+ b3Scalar m_loLimit; //!< joint limit
+ b3Scalar m_hiLimit; //!< joint limit
+ b3Scalar m_targetVelocity; //!< target motor velocity
+ b3Scalar m_maxMotorForce; //!< max force on motor
+ b3Scalar m_maxLimitForce; //!< max force on limit
+ b3Scalar m_damping; //!< Damping.
+ b3Scalar m_limitSoftness; //! Relaxation factor
+ b3Scalar m_normalCFM; //!< Constraint force mixing factor
+ b3Scalar m_stopERP; //!< Error tolerance factor when joint is at limit
+ b3Scalar m_stopCFM; //!< Constraint force mixing factor when joint is at limit
+ b3Scalar m_bounce; //!< restitution factor
+ bool m_enableMotor;
+
+ //!@}
+
+ //! temp_variables
+ //!@{
+ b3Scalar m_currentLimitError; //! How much is violated this limit
+ b3Scalar m_currentPosition; //! current value of angle
+ int m_currentLimit; //!< 0=free, 1=at lo limit, 2=at hi limit
+ b3Scalar m_accumulatedImpulse;
+ //!@}
+
+ b3RotationalLimitMotor()
+ {
+ m_accumulatedImpulse = 0.f;
+ m_targetVelocity = 0;
+ m_maxMotorForce = 6.0f;
+ m_maxLimitForce = 300.0f;
+ m_loLimit = 1.0f;
+ m_hiLimit = -1.0f;
m_normalCFM = 0.f;
m_stopERP = 0.2f;
m_stopCFM = 0.f;
- m_bounce = 0.0f;
- m_damping = 1.0f;
- m_limitSoftness = 0.5f;
- m_currentLimit = 0;
- m_currentLimitError = 0;
- m_enableMotor = false;
- }
-
- b3RotationalLimitMotor(const b3RotationalLimitMotor & limot)
- {
- m_targetVelocity = limot.m_targetVelocity;
- m_maxMotorForce = limot.m_maxMotorForce;
- m_limitSoftness = limot.m_limitSoftness;
- m_loLimit = limot.m_loLimit;
- m_hiLimit = limot.m_hiLimit;
+ m_bounce = 0.0f;
+ m_damping = 1.0f;
+ m_limitSoftness = 0.5f;
+ m_currentLimit = 0;
+ m_currentLimitError = 0;
+ m_enableMotor = false;
+ }
+
+ b3RotationalLimitMotor(const b3RotationalLimitMotor& limot)
+ {
+ m_targetVelocity = limot.m_targetVelocity;
+ m_maxMotorForce = limot.m_maxMotorForce;
+ m_limitSoftness = limot.m_limitSoftness;
+ m_loLimit = limot.m_loLimit;
+ m_hiLimit = limot.m_hiLimit;
m_normalCFM = limot.m_normalCFM;
m_stopERP = limot.m_stopERP;
- m_stopCFM = limot.m_stopCFM;
- m_bounce = limot.m_bounce;
- m_currentLimit = limot.m_currentLimit;
- m_currentLimitError = limot.m_currentLimitError;
- m_enableMotor = limot.m_enableMotor;
- }
-
-
+ m_stopCFM = limot.m_stopCFM;
+ m_bounce = limot.m_bounce;
+ m_currentLimit = limot.m_currentLimit;
+ m_currentLimitError = limot.m_currentLimitError;
+ m_enableMotor = limot.m_enableMotor;
+ }
//! Is limited
- bool isLimited()
- {
- if(m_loLimit > m_hiLimit) return false;
- return true;
- }
+ bool isLimited()
+ {
+ if (m_loLimit > m_hiLimit) return false;
+ return true;
+ }
//! Need apply correction
- bool needApplyTorques()
- {
- if(m_currentLimit == 0 && m_enableMotor == false) return false;
- return true;
- }
+ bool needApplyTorques()
+ {
+ if (m_currentLimit == 0 && m_enableMotor == false) return false;
+ return true;
+ }
//! calculates error
/*!
@@ -123,104 +117,98 @@ public:
int testLimitValue(b3Scalar test_value);
//! apply the correction impulses for two bodies
- b3Scalar solveAngularLimits(b3Scalar timeStep,b3Vector3& axis, b3Scalar jacDiagABInv,b3RigidBodyData * body0, b3RigidBodyData * body1);
-
+ b3Scalar solveAngularLimits(b3Scalar timeStep, b3Vector3& axis, b3Scalar jacDiagABInv, b3RigidBodyData* body0, b3RigidBodyData* body1);
};
-
-
class b3TranslationalLimitMotor
{
public:
- b3Vector3 m_lowerLimit;//!< the constraint lower limits
- b3Vector3 m_upperLimit;//!< the constraint upper limits
- b3Vector3 m_accumulatedImpulse;
- //! Linear_Limit_parameters
- //!@{
- b3Vector3 m_normalCFM;//!< Constraint force mixing factor
- b3Vector3 m_stopERP;//!< Error tolerance factor when joint is at limit
- b3Vector3 m_stopCFM;//!< Constraint force mixing factor when joint is at limit
- b3Vector3 m_targetVelocity;//!< target motor velocity
- b3Vector3 m_maxMotorForce;//!< max force on motor
- b3Vector3 m_currentLimitError;//! How much is violated this limit
- b3Vector3 m_currentLinearDiff;//! Current relative offset of constraint frames
- b3Scalar m_limitSoftness;//!< Softness for linear limit
- b3Scalar m_damping;//!< Damping for linear limit
- b3Scalar m_restitution;//! Bounce parameter for linear limit
+ b3Vector3 m_lowerLimit; //!< the constraint lower limits
+ b3Vector3 m_upperLimit; //!< the constraint upper limits
+ b3Vector3 m_accumulatedImpulse;
+ //! Linear_Limit_parameters
+ //!@{
+ b3Vector3 m_normalCFM; //!< Constraint force mixing factor
+ b3Vector3 m_stopERP; //!< Error tolerance factor when joint is at limit
+ b3Vector3 m_stopCFM; //!< Constraint force mixing factor when joint is at limit
+ b3Vector3 m_targetVelocity; //!< target motor velocity
+ b3Vector3 m_maxMotorForce; //!< max force on motor
+ b3Vector3 m_currentLimitError; //! How much is violated this limit
+ b3Vector3 m_currentLinearDiff; //! Current relative offset of constraint frames
+ b3Scalar m_limitSoftness; //!< Softness for linear limit
+ b3Scalar m_damping; //!< Damping for linear limit
+ b3Scalar m_restitution; //! Bounce parameter for linear limit
//!@}
- bool m_enableMotor[3];
- int m_currentLimit[3];//!< 0=free, 1=at lower limit, 2=at upper limit
-
- b3TranslationalLimitMotor()
- {
- m_lowerLimit.setValue(0.f,0.f,0.f);
- m_upperLimit.setValue(0.f,0.f,0.f);
- m_accumulatedImpulse.setValue(0.f,0.f,0.f);
+ bool m_enableMotor[3];
+ int m_currentLimit[3]; //!< 0=free, 1=at lower limit, 2=at upper limit
+
+ b3TranslationalLimitMotor()
+ {
+ m_lowerLimit.setValue(0.f, 0.f, 0.f);
+ m_upperLimit.setValue(0.f, 0.f, 0.f);
+ m_accumulatedImpulse.setValue(0.f, 0.f, 0.f);
m_normalCFM.setValue(0.f, 0.f, 0.f);
m_stopERP.setValue(0.2f, 0.2f, 0.2f);
m_stopCFM.setValue(0.f, 0.f, 0.f);
- m_limitSoftness = 0.7f;
- m_damping = b3Scalar(1.0f);
- m_restitution = b3Scalar(0.5f);
- for(int i=0; i < 3; i++)
+ m_limitSoftness = 0.7f;
+ m_damping = b3Scalar(1.0f);
+ m_restitution = b3Scalar(0.5f);
+ for (int i = 0; i < 3; i++)
{
m_enableMotor[i] = false;
m_targetVelocity[i] = b3Scalar(0.f);
m_maxMotorForce[i] = b3Scalar(0.f);
}
- }
+ }
- b3TranslationalLimitMotor(const b3TranslationalLimitMotor & other )
- {
- m_lowerLimit = other.m_lowerLimit;
- m_upperLimit = other.m_upperLimit;
- m_accumulatedImpulse = other.m_accumulatedImpulse;
+ b3TranslationalLimitMotor(const b3TranslationalLimitMotor& other)
+ {
+ m_lowerLimit = other.m_lowerLimit;
+ m_upperLimit = other.m_upperLimit;
+ m_accumulatedImpulse = other.m_accumulatedImpulse;
- m_limitSoftness = other.m_limitSoftness ;
- m_damping = other.m_damping;
- m_restitution = other.m_restitution;
+ m_limitSoftness = other.m_limitSoftness;
+ m_damping = other.m_damping;
+ m_restitution = other.m_restitution;
m_normalCFM = other.m_normalCFM;
m_stopERP = other.m_stopERP;
m_stopCFM = other.m_stopCFM;
- for(int i=0; i < 3; i++)
+ for (int i = 0; i < 3; i++)
{
m_enableMotor[i] = other.m_enableMotor[i];
m_targetVelocity[i] = other.m_targetVelocity[i];
m_maxMotorForce[i] = other.m_maxMotorForce[i];
}
- }
+ }
- //! Test limit
+ //! Test limit
/*!
- free means upper < lower,
- locked means upper == lower
- limited means upper > lower
- limitIndex: first 3 are linear, next 3 are angular
*/
- inline bool isLimited(int limitIndex)
- {
- return (m_upperLimit[limitIndex] >= m_lowerLimit[limitIndex]);
- }
- inline bool needApplyForce(int limitIndex)
- {
- if(m_currentLimit[limitIndex] == 0 && m_enableMotor[limitIndex] == false) return false;
- return true;
- }
+ inline bool isLimited(int limitIndex)
+ {
+ return (m_upperLimit[limitIndex] >= m_lowerLimit[limitIndex]);
+ }
+ inline bool needApplyForce(int limitIndex)
+ {
+ if (m_currentLimit[limitIndex] == 0 && m_enableMotor[limitIndex] == false) return false;
+ return true;
+ }
int testLimitValue(int limitIndex, b3Scalar test_value);
-
- b3Scalar solveLinearAxis(
- b3Scalar timeStep,
- b3Scalar jacDiagABInv,
- b3RigidBodyData& body1,const b3Vector3 &pointInA,
- b3RigidBodyData& body2,const b3Vector3 &pointInB,
- int limit_index,
- const b3Vector3 & axis_normal_on_a,
- const b3Vector3 & anchorPos);
-
-
+ b3Scalar solveLinearAxis(
+ b3Scalar timeStep,
+ b3Scalar jacDiagABInv,
+ b3RigidBodyData& body1, const b3Vector3& pointInA,
+ b3RigidBodyData& body2, const b3Vector3& pointInB,
+ int limit_index,
+ const b3Vector3& axis_normal_on_a,
+ const b3Vector3& anchorPos);
};
enum b36DofFlags
@@ -229,8 +217,7 @@ enum b36DofFlags
B3_6DOF_FLAGS_CFM_STOP = 2,
B3_6DOF_FLAGS_ERP_STOP = 4
};
-#define B3_6DOF_FLAGS_AXIS_SHIFT 3 // bits per axis
-
+#define B3_6DOF_FLAGS_AXIS_SHIFT 3 // bits per axis
/// b3Generic6DofConstraint between two rigidbodies each with a pivotpoint that descibes the axis location in local space
/*!
@@ -268,240 +255,229 @@ This brings support for limit parameters and motors. </li>
</ul>
*/
-B3_ATTRIBUTE_ALIGNED16(class) b3Generic6DofConstraint : public b3TypedConstraint
+B3_ATTRIBUTE_ALIGNED16(class)
+b3Generic6DofConstraint : public b3TypedConstraint
{
protected:
-
//! relative_frames
- //!@{
- b3Transform m_frameInA;//!< the constraint space w.r.t body A
- b3Transform m_frameInB;//!< the constraint space w.r.t body B
- //!@}
+ //!@{
+ b3Transform m_frameInA; //!< the constraint space w.r.t body A
+ b3Transform m_frameInB; //!< the constraint space w.r.t body B
+ //!@}
- //! Jacobians
- //!@{
-// b3JacobianEntry m_jacLinear[3];//!< 3 orthogonal linear constraints
-// b3JacobianEntry m_jacAng[3];//!< 3 orthogonal angular constraints
- //!@}
+ //! Jacobians
+ //!@{
+ // b3JacobianEntry m_jacLinear[3];//!< 3 orthogonal linear constraints
+ // b3JacobianEntry m_jacAng[3];//!< 3 orthogonal angular constraints
+ //!@}
//! Linear_Limit_parameters
- //!@{
- b3TranslationalLimitMotor m_linearLimits;
- //!@}
-
-
- //! hinge_parameters
- //!@{
- b3RotationalLimitMotor m_angularLimits[3];
+ //!@{
+ b3TranslationalLimitMotor m_linearLimits;
//!@}
+ //! hinge_parameters
+ //!@{
+ b3RotationalLimitMotor m_angularLimits[3];
+ //!@}
protected:
- //! temporal variables
- //!@{
- b3Transform m_calculatedTransformA;
- b3Transform m_calculatedTransformB;
- b3Vector3 m_calculatedAxisAngleDiff;
- b3Vector3 m_calculatedAxis[3];
- b3Vector3 m_calculatedLinearDiff;
- b3Scalar m_timeStep;
- b3Scalar m_factA;
- b3Scalar m_factB;
- bool m_hasStaticBody;
-
- b3Vector3 m_AnchorPos; // point betwen pivots of bodies A and B to solve linear axes
+ //! temporal variables
+ //!@{
+ b3Transform m_calculatedTransformA;
+ b3Transform m_calculatedTransformB;
+ b3Vector3 m_calculatedAxisAngleDiff;
+ b3Vector3 m_calculatedAxis[3];
+ b3Vector3 m_calculatedLinearDiff;
+ b3Scalar m_timeStep;
+ b3Scalar m_factA;
+ b3Scalar m_factB;
+ bool m_hasStaticBody;
- bool m_useLinearReferenceFrameA;
- bool m_useOffsetForConstraintFrame;
-
- int m_flags;
+ b3Vector3 m_AnchorPos; // point betwen pivots of bodies A and B to solve linear axes
- //!@}
+ bool m_useLinearReferenceFrameA;
+ bool m_useOffsetForConstraintFrame;
- b3Generic6DofConstraint& operator=(b3Generic6DofConstraint& other)
- {
- b3Assert(0);
- (void) other;
- return *this;
- }
+ int m_flags;
+ //!@}
- int setAngularLimits(b3ConstraintInfo2 *info, int row_offset,const b3Transform& transA,const b3Transform& transB,const b3Vector3& linVelA,const b3Vector3& linVelB,const b3Vector3& angVelA,const b3Vector3& angVelB);
+ b3Generic6DofConstraint& operator=(b3Generic6DofConstraint& other)
+ {
+ b3Assert(0);
+ (void)other;
+ return *this;
+ }
- int setLinearLimits(b3ConstraintInfo2 *info, int row, const b3Transform& transA,const b3Transform& transB,const b3Vector3& linVelA,const b3Vector3& linVelB,const b3Vector3& angVelA,const b3Vector3& angVelB);
+ int setAngularLimits(b3ConstraintInfo2 * info, int row_offset, const b3Transform& transA, const b3Transform& transB, const b3Vector3& linVelA, const b3Vector3& linVelB, const b3Vector3& angVelA, const b3Vector3& angVelB);
+ int setLinearLimits(b3ConstraintInfo2 * info, int row, const b3Transform& transA, const b3Transform& transB, const b3Vector3& linVelA, const b3Vector3& linVelB, const b3Vector3& angVelA, const b3Vector3& angVelB);
// tests linear limits
void calculateLinearInfo();
//! calcs the euler angles between the two bodies.
- void calculateAngleInfo();
-
-
+ void calculateAngleInfo();
public:
-
B3_DECLARE_ALIGNED_ALLOCATOR();
-
- b3Generic6DofConstraint(int rbA, int rbB, const b3Transform& frameInA, const b3Transform& frameInB ,bool useLinearReferenceFrameA,const b3RigidBodyData* bodies);
-
+
+ b3Generic6DofConstraint(int rbA, int rbB, const b3Transform& frameInA, const b3Transform& frameInB, bool useLinearReferenceFrameA, const b3RigidBodyData* bodies);
+
//! Calcs global transform of the offsets
/*!
Calcs the global transform for the joint offset for body A an B, and also calcs the agle differences between the bodies.
\sa b3Generic6DofConstraint.getCalculatedTransformA , b3Generic6DofConstraint.getCalculatedTransformB, b3Generic6DofConstraint.calculateAngleInfo
*/
- void calculateTransforms(const b3Transform& transA,const b3Transform& transB,const b3RigidBodyData* bodies);
+ void calculateTransforms(const b3Transform& transA, const b3Transform& transB, const b3RigidBodyData* bodies);
void calculateTransforms(const b3RigidBodyData* bodies);
//! Gets the global transform of the offset for body A
- /*!
+ /*!
\sa b3Generic6DofConstraint.getFrameOffsetA, b3Generic6DofConstraint.getFrameOffsetB, b3Generic6DofConstraint.calculateAngleInfo.
*/
- const b3Transform & getCalculatedTransformA() const
- {
- return m_calculatedTransformA;
- }
+ const b3Transform& getCalculatedTransformA() const
+ {
+ return m_calculatedTransformA;
+ }
- //! Gets the global transform of the offset for body B
- /*!
+ //! Gets the global transform of the offset for body B
+ /*!
\sa b3Generic6DofConstraint.getFrameOffsetA, b3Generic6DofConstraint.getFrameOffsetB, b3Generic6DofConstraint.calculateAngleInfo.
*/
- const b3Transform & getCalculatedTransformB() const
- {
- return m_calculatedTransformB;
- }
-
- const b3Transform & getFrameOffsetA() const
- {
- return m_frameInA;
- }
-
- const b3Transform & getFrameOffsetB() const
- {
- return m_frameInB;
- }
-
-
- b3Transform & getFrameOffsetA()
- {
- return m_frameInA;
- }
+ const b3Transform& getCalculatedTransformB() const
+ {
+ return m_calculatedTransformB;
+ }
- b3Transform & getFrameOffsetB()
- {
- return m_frameInB;
- }
+ const b3Transform& getFrameOffsetA() const
+ {
+ return m_frameInA;
+ }
+ const b3Transform& getFrameOffsetB() const
+ {
+ return m_frameInB;
+ }
+ b3Transform& getFrameOffsetA()
+ {
+ return m_frameInA;
+ }
- virtual void getInfo1 (b3ConstraintInfo1* info,const b3RigidBodyData* bodies);
+ b3Transform& getFrameOffsetB()
+ {
+ return m_frameInB;
+ }
- void getInfo1NonVirtual (b3ConstraintInfo1* info,const b3RigidBodyData* bodies);
+ virtual void getInfo1(b3ConstraintInfo1 * info, const b3RigidBodyData* bodies);
- virtual void getInfo2 (b3ConstraintInfo2* info,const b3RigidBodyData* bodies);
+ void getInfo1NonVirtual(b3ConstraintInfo1 * info, const b3RigidBodyData* bodies);
- void getInfo2NonVirtual (b3ConstraintInfo2* info,const b3Transform& transA,const b3Transform& transB,const b3Vector3& linVelA,const b3Vector3& linVelB,const b3Vector3& angVelA,const b3Vector3& angVelB,const b3RigidBodyData* bodies);
+ virtual void getInfo2(b3ConstraintInfo2 * info, const b3RigidBodyData* bodies);
+ void getInfo2NonVirtual(b3ConstraintInfo2 * info, const b3Transform& transA, const b3Transform& transB, const b3Vector3& linVelA, const b3Vector3& linVelB, const b3Vector3& angVelA, const b3Vector3& angVelB, const b3RigidBodyData* bodies);
- void updateRHS(b3Scalar timeStep);
+ void updateRHS(b3Scalar timeStep);
//! Get the rotation axis in global coordinates
- b3Vector3 getAxis(int axis_index) const;
+ b3Vector3 getAxis(int axis_index) const;
- //! Get the relative Euler angle
- /*!
+ //! Get the relative Euler angle
+ /*!
\pre b3Generic6DofConstraint::calculateTransforms() must be called previously.
*/
- b3Scalar getAngle(int axis_index) const;
+ b3Scalar getAngle(int axis_index) const;
//! Get the relative position of the constraint pivot
- /*!
+ /*!
\pre b3Generic6DofConstraint::calculateTransforms() must be called previously.
*/
b3Scalar getRelativePivotPosition(int axis_index) const;
- void setFrames(const b3Transform & frameA, const b3Transform & frameB, const b3RigidBodyData* bodies);
+ void setFrames(const b3Transform& frameA, const b3Transform& frameB, const b3RigidBodyData* bodies);
//! Test angular limit.
/*!
Calculates angular correction and returns true if limit needs to be corrected.
\pre b3Generic6DofConstraint::calculateTransforms() must be called previously.
*/
- bool testAngularLimitMotor(int axis_index);
+ bool testAngularLimitMotor(int axis_index);
- void setLinearLowerLimit(const b3Vector3& linearLower)
- {
- m_linearLimits.m_lowerLimit = linearLower;
- }
+ void setLinearLowerLimit(const b3Vector3& linearLower)
+ {
+ m_linearLimits.m_lowerLimit = linearLower;
+ }
- void getLinearLowerLimit(b3Vector3& linearLower)
+ void getLinearLowerLimit(b3Vector3 & linearLower)
{
linearLower = m_linearLimits.m_lowerLimit;
}
- void setLinearUpperLimit(const b3Vector3& linearUpper)
+ void setLinearUpperLimit(const b3Vector3& linearUpper)
{
m_linearLimits.m_upperLimit = linearUpper;
}
- void getLinearUpperLimit(b3Vector3& linearUpper)
+ void getLinearUpperLimit(b3Vector3 & linearUpper)
{
linearUpper = m_linearLimits.m_upperLimit;
}
- void setAngularLowerLimit(const b3Vector3& angularLower)
- {
- for(int i = 0; i < 3; i++)
+ void setAngularLowerLimit(const b3Vector3& angularLower)
+ {
+ for (int i = 0; i < 3; i++)
m_angularLimits[i].m_loLimit = b3NormalizeAngle(angularLower[i]);
- }
+ }
- void getAngularLowerLimit(b3Vector3& angularLower)
+ void getAngularLowerLimit(b3Vector3 & angularLower)
{
- for(int i = 0; i < 3; i++)
+ for (int i = 0; i < 3; i++)
angularLower[i] = m_angularLimits[i].m_loLimit;
}
- void setAngularUpperLimit(const b3Vector3& angularUpper)
- {
- for(int i = 0; i < 3; i++)
+ void setAngularUpperLimit(const b3Vector3& angularUpper)
+ {
+ for (int i = 0; i < 3; i++)
m_angularLimits[i].m_hiLimit = b3NormalizeAngle(angularUpper[i]);
- }
+ }
- void getAngularUpperLimit(b3Vector3& angularUpper)
+ void getAngularUpperLimit(b3Vector3 & angularUpper)
{
- for(int i = 0; i < 3; i++)
+ for (int i = 0; i < 3; i++)
angularUpper[i] = m_angularLimits[i].m_hiLimit;
}
//! Retrieves the angular limit informacion
- b3RotationalLimitMotor * getRotationalLimitMotor(int index)
- {
- return &m_angularLimits[index];
- }
-
- //! Retrieves the limit informacion
- b3TranslationalLimitMotor * getTranslationalLimitMotor()
- {
- return &m_linearLimits;
- }
-
- //first 3 are linear, next 3 are angular
- void setLimit(int axis, b3Scalar lo, b3Scalar hi)
- {
- if(axis<3)
- {
- m_linearLimits.m_lowerLimit[axis] = lo;
- m_linearLimits.m_upperLimit[axis] = hi;
- }
- else
- {
+ b3RotationalLimitMotor* getRotationalLimitMotor(int index)
+ {
+ return &m_angularLimits[index];
+ }
+
+ //! Retrieves the limit informacion
+ b3TranslationalLimitMotor* getTranslationalLimitMotor()
+ {
+ return &m_linearLimits;
+ }
+
+ //first 3 are linear, next 3 are angular
+ void setLimit(int axis, b3Scalar lo, b3Scalar hi)
+ {
+ if (axis < 3)
+ {
+ m_linearLimits.m_lowerLimit[axis] = lo;
+ m_linearLimits.m_upperLimit[axis] = hi;
+ }
+ else
+ {
lo = b3NormalizeAngle(lo);
hi = b3NormalizeAngle(hi);
- m_angularLimits[axis-3].m_loLimit = lo;
- m_angularLimits[axis-3].m_hiLimit = hi;
- }
- }
+ m_angularLimits[axis - 3].m_loLimit = lo;
+ m_angularLimits[axis - 3].m_hiLimit = hi;
+ }
+ }
//! Test limit
/*!
@@ -510,41 +486,32 @@ public:
- limited means upper > lower
- limitIndex: first 3 are linear, next 3 are angular
*/
- bool isLimited(int limitIndex)
- {
- if(limitIndex<3)
- {
+ bool isLimited(int limitIndex)
+ {
+ if (limitIndex < 3)
+ {
return m_linearLimits.isLimited(limitIndex);
+ }
+ return m_angularLimits[limitIndex - 3].isLimited();
+ }
- }
- return m_angularLimits[limitIndex-3].isLimited();
- }
-
- virtual void calcAnchorPos(const b3RigidBodyData* bodies); // overridable
+ virtual void calcAnchorPos(const b3RigidBodyData* bodies); // overridable
- int get_limit_motor_info2( b3RotationalLimitMotor * limot,
- const b3Transform& transA,const b3Transform& transB,const b3Vector3& linVelA,const b3Vector3& linVelB,const b3Vector3& angVelA,const b3Vector3& angVelB,
- b3ConstraintInfo2 *info, int row, b3Vector3& ax1, int rotational, int rotAllowed = false);
+ int get_limit_motor_info2(b3RotationalLimitMotor * limot,
+ const b3Transform& transA, const b3Transform& transB, const b3Vector3& linVelA, const b3Vector3& linVelB, const b3Vector3& angVelA, const b3Vector3& angVelB,
+ b3ConstraintInfo2* info, int row, b3Vector3& ax1, int rotational, int rotAllowed = false);
// access for UseFrameOffset
bool getUseFrameOffset() { return m_useOffsetForConstraintFrame; }
void setUseFrameOffset(bool frameOffsetOnOff) { m_useOffsetForConstraintFrame = frameOffsetOnOff; }
- ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+ ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
///If no axis is provided, it uses the default axis for this constraint.
- virtual void setParam(int num, b3Scalar value, int axis = -1);
+ virtual void setParam(int num, b3Scalar value, int axis = -1);
///return the local value of parameter
- virtual b3Scalar getParam(int num, int axis = -1) const;
-
- void setAxis( const b3Vector3& axis1, const b3Vector3& axis2,const b3RigidBodyData* bodies);
+ virtual b3Scalar getParam(int num, int axis = -1) const;
-
-
-
+ void setAxis(const b3Vector3& axis1, const b3Vector3& axis2, const b3RigidBodyData* bodies);
};
-
-
-
-
-#endif //B3_GENERIC_6DOF_CONSTRAINT_H
+#endif //B3_GENERIC_6DOF_CONSTRAINT_H
diff --git a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3JacobianEntry.h b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3JacobianEntry.h
index a55168eb38..13269debf6 100644
--- a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3JacobianEntry.h
+++ b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3JacobianEntry.h
@@ -18,7 +18,6 @@ subject to the following restrictions:
#include "Bullet3Common/b3Matrix3x3.h"
-
//notes:
// Another memory optimization would be to store m_1MinvJt in the remaining 3 w components
// which makes the b3JacobianEntry memory layout 16 bytes
@@ -27,25 +26,26 @@ subject to the following restrictions:
/// Jacobian entry is an abstraction that allows to describe constraints
/// it can be used in combination with a constraint solver
/// Can be used to relate the effect of an impulse to the constraint error
-B3_ATTRIBUTE_ALIGNED16(class) b3JacobianEntry
+B3_ATTRIBUTE_ALIGNED16(class)
+b3JacobianEntry
{
public:
- b3JacobianEntry() {};
+ b3JacobianEntry(){};
//constraint between two different rigidbodies
b3JacobianEntry(
const b3Matrix3x3& world2A,
const b3Matrix3x3& world2B,
- const b3Vector3& rel_pos1,const b3Vector3& rel_pos2,
+ const b3Vector3& rel_pos1, const b3Vector3& rel_pos2,
const b3Vector3& jointAxis,
- const b3Vector3& inertiaInvA,
+ const b3Vector3& inertiaInvA,
const b3Scalar massInvA,
const b3Vector3& inertiaInvB,
const b3Scalar massInvB)
- :m_linearJointAxis(jointAxis)
+ : m_linearJointAxis(jointAxis)
{
- m_aJ = world2A*(rel_pos1.cross(m_linearJointAxis));
- m_bJ = world2B*(rel_pos2.cross(-m_linearJointAxis));
- m_0MinvJt = inertiaInvA * m_aJ;
+ m_aJ = world2A * (rel_pos1.cross(m_linearJointAxis));
+ m_bJ = world2B * (rel_pos2.cross(-m_linearJointAxis));
+ m_0MinvJt = inertiaInvA * m_aJ;
m_1MinvJt = inertiaInvB * m_bJ;
m_Adiag = massInvA + m_0MinvJt.dot(m_aJ) + massInvB + m_1MinvJt.dot(m_bJ);
@@ -54,33 +54,31 @@ public:
//angular constraint between two different rigidbodies
b3JacobianEntry(const b3Vector3& jointAxis,
- const b3Matrix3x3& world2A,
- const b3Matrix3x3& world2B,
- const b3Vector3& inertiaInvA,
- const b3Vector3& inertiaInvB)
- :m_linearJointAxis(b3MakeVector3(b3Scalar(0.),b3Scalar(0.),b3Scalar(0.)))
+ const b3Matrix3x3& world2A,
+ const b3Matrix3x3& world2B,
+ const b3Vector3& inertiaInvA,
+ const b3Vector3& inertiaInvB)
+ : m_linearJointAxis(b3MakeVector3(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.)))
{
- m_aJ= world2A*jointAxis;
- m_bJ = world2B*-jointAxis;
- m_0MinvJt = inertiaInvA * m_aJ;
+ m_aJ = world2A * jointAxis;
+ m_bJ = world2B * -jointAxis;
+ m_0MinvJt = inertiaInvA * m_aJ;
m_1MinvJt = inertiaInvB * m_bJ;
- m_Adiag = m_0MinvJt.dot(m_aJ) + m_1MinvJt.dot(m_bJ);
+ m_Adiag = m_0MinvJt.dot(m_aJ) + m_1MinvJt.dot(m_bJ);
b3Assert(m_Adiag > b3Scalar(0.0));
}
//angular constraint between two different rigidbodies
b3JacobianEntry(const b3Vector3& axisInA,
- const b3Vector3& axisInB,
- const b3Vector3& inertiaInvA,
- const b3Vector3& inertiaInvB)
- : m_linearJointAxis(b3MakeVector3(b3Scalar(0.),b3Scalar(0.),b3Scalar(0.)))
- , m_aJ(axisInA)
- , m_bJ(-axisInB)
+ const b3Vector3& axisInB,
+ const b3Vector3& inertiaInvA,
+ const b3Vector3& inertiaInvB)
+ : m_linearJointAxis(b3MakeVector3(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.))), m_aJ(axisInA), m_bJ(-axisInB)
{
- m_0MinvJt = inertiaInvA * m_aJ;
+ m_0MinvJt = inertiaInvA * m_aJ;
m_1MinvJt = inertiaInvB * m_bJ;
- m_Adiag = m_0MinvJt.dot(m_aJ) + m_1MinvJt.dot(m_bJ);
+ m_Adiag = m_0MinvJt.dot(m_aJ) + m_1MinvJt.dot(m_bJ);
b3Assert(m_Adiag > b3Scalar(0.0));
}
@@ -88,25 +86,25 @@ public:
//constraint on one rigidbody
b3JacobianEntry(
const b3Matrix3x3& world2A,
- const b3Vector3& rel_pos1,const b3Vector3& rel_pos2,
+ const b3Vector3& rel_pos1, const b3Vector3& rel_pos2,
const b3Vector3& jointAxis,
- const b3Vector3& inertiaInvA,
+ const b3Vector3& inertiaInvA,
const b3Scalar massInvA)
- :m_linearJointAxis(jointAxis)
+ : m_linearJointAxis(jointAxis)
{
- m_aJ= world2A*(rel_pos1.cross(jointAxis));
- m_bJ = world2A*(rel_pos2.cross(-jointAxis));
- m_0MinvJt = inertiaInvA * m_aJ;
- m_1MinvJt = b3MakeVector3(b3Scalar(0.),b3Scalar(0.),b3Scalar(0.));
+ m_aJ = world2A * (rel_pos1.cross(jointAxis));
+ m_bJ = world2A * (rel_pos2.cross(-jointAxis));
+ m_0MinvJt = inertiaInvA * m_aJ;
+ m_1MinvJt = b3MakeVector3(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.));
m_Adiag = massInvA + m_0MinvJt.dot(m_aJ);
b3Assert(m_Adiag > b3Scalar(0.0));
}
- b3Scalar getDiagonal() const { return m_Adiag; }
+ b3Scalar getDiagonal() const { return m_Adiag; }
// for two constraints on the same rigidbody (for example vehicle friction)
- b3Scalar getNonDiagonal(const b3JacobianEntry& jacB, const b3Scalar massInvA) const
+ b3Scalar getNonDiagonal(const b3JacobianEntry& jacB, const b3Scalar massInvA) const
{
const b3JacobianEntry& jacA = *this;
b3Scalar lin = massInvA * jacA.m_linearJointAxis.dot(jacB.m_linearJointAxis);
@@ -114,42 +112,39 @@ public:
return lin + ang;
}
-
-
// for two constraints on sharing two same rigidbodies (for example two contact points between two rigidbodies)
- b3Scalar getNonDiagonal(const b3JacobianEntry& jacB,const b3Scalar massInvA,const b3Scalar massInvB) const
+ b3Scalar getNonDiagonal(const b3JacobianEntry& jacB, const b3Scalar massInvA, const b3Scalar massInvB) const
{
const b3JacobianEntry& jacA = *this;
b3Vector3 lin = jacA.m_linearJointAxis * jacB.m_linearJointAxis;
b3Vector3 ang0 = jacA.m_0MinvJt * jacB.m_aJ;
b3Vector3 ang1 = jacA.m_1MinvJt * jacB.m_bJ;
- b3Vector3 lin0 = massInvA * lin ;
+ b3Vector3 lin0 = massInvA * lin;
b3Vector3 lin1 = massInvB * lin;
- b3Vector3 sum = ang0+ang1+lin0+lin1;
- return sum[0]+sum[1]+sum[2];
+ b3Vector3 sum = ang0 + ang1 + lin0 + lin1;
+ return sum[0] + sum[1] + sum[2];
}
- b3Scalar getRelativeVelocity(const b3Vector3& linvelA,const b3Vector3& angvelA,const b3Vector3& linvelB,const b3Vector3& angvelB)
+ b3Scalar getRelativeVelocity(const b3Vector3& linvelA, const b3Vector3& angvelA, const b3Vector3& linvelB, const b3Vector3& angvelB)
{
b3Vector3 linrel = linvelA - linvelB;
- b3Vector3 angvela = angvelA * m_aJ;
- b3Vector3 angvelb = angvelB * m_bJ;
+ b3Vector3 angvela = angvelA * m_aJ;
+ b3Vector3 angvelb = angvelB * m_bJ;
linrel *= m_linearJointAxis;
angvela += angvelb;
angvela += linrel;
- b3Scalar rel_vel2 = angvela[0]+angvela[1]+angvela[2];
+ b3Scalar rel_vel2 = angvela[0] + angvela[1] + angvela[2];
return rel_vel2 + B3_EPSILON;
}
-//private:
+ //private:
- b3Vector3 m_linearJointAxis;
- b3Vector3 m_aJ;
- b3Vector3 m_bJ;
- b3Vector3 m_0MinvJt;
- b3Vector3 m_1MinvJt;
+ b3Vector3 m_linearJointAxis;
+ b3Vector3 m_aJ;
+ b3Vector3 m_bJ;
+ b3Vector3 m_0MinvJt;
+ b3Vector3 m_1MinvJt;
//Optimization: can be stored in the w/last component of one of the vectors
- b3Scalar m_Adiag;
-
+ b3Scalar m_Adiag;
};
-#endif //B3_JACOBIAN_ENTRY_H
+#endif //B3_JACOBIAN_ENTRY_H
diff --git a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3PgsJacobiSolver.cpp b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3PgsJacobiSolver.cpp
index de729d4556..b7050b1070 100644
--- a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3PgsJacobiSolver.cpp
+++ b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3PgsJacobiSolver.cpp
@@ -29,14 +29,13 @@ subject to the following restrictions:
//#include "b3SolverBody.h"
//#include "b3SolverConstraint.h"
#include "Bullet3Common/b3AlignedObjectArray.h"
-#include <string.h> //for memset
+#include <string.h> //for memset
//#include "../../dynamics/basic_demo/Stubs/AdlContact4.h"
#include "Bullet3Collision/NarrowPhaseCollision/b3Contact4.h"
-
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
-static b3Transform getWorldTransform(b3RigidBodyData* rb)
+static b3Transform getWorldTransform(b3RigidBodyData* rb)
{
b3Transform newTrans;
newTrans.setOrigin(rb->m_pos);
@@ -44,19 +43,17 @@ static b3Transform getWorldTransform(b3RigidBodyData* rb)
return newTrans;
}
-static const b3Matrix3x3& getInvInertiaTensorWorld(b3InertiaData* inertia)
+static const b3Matrix3x3& getInvInertiaTensorWorld(b3InertiaData* inertia)
{
return inertia->m_invInertiaWorld;
}
-
-
-static const b3Vector3& getLinearVelocity(b3RigidBodyData* rb)
+static const b3Vector3& getLinearVelocity(b3RigidBodyData* rb)
{
return rb->m_linVel;
}
-static const b3Vector3& getAngularVelocity(b3RigidBodyData* rb)
+static const b3Vector3& getAngularVelocity(b3RigidBodyData* rb)
{
return rb->m_angVel;
}
@@ -65,47 +62,46 @@ static b3Vector3 getVelocityInLocalPoint(b3RigidBodyData* rb, const b3Vector3& r
{
//we also calculate lin/ang velocity for kinematic objects
return getLinearVelocity(rb) + getAngularVelocity(rb).cross(rel_pos);
-
}
-struct b3ContactPoint
+struct b3ContactPoint
{
- b3Vector3 m_positionWorldOnA;
- b3Vector3 m_positionWorldOnB;
- b3Vector3 m_normalWorldOnB;
- b3Scalar m_appliedImpulse;
- b3Scalar m_distance;
- b3Scalar m_combinedRestitution;
+ b3Vector3 m_positionWorldOnA;
+ b3Vector3 m_positionWorldOnB;
+ b3Vector3 m_normalWorldOnB;
+ b3Scalar m_appliedImpulse;
+ b3Scalar m_distance;
+ b3Scalar m_combinedRestitution;
///information related to friction
- b3Scalar m_combinedFriction;
- b3Vector3 m_lateralFrictionDir1;
- b3Vector3 m_lateralFrictionDir2;
- b3Scalar m_appliedImpulseLateral1;
- b3Scalar m_appliedImpulseLateral2;
- b3Scalar m_combinedRollingFriction;
- b3Scalar m_contactMotion1;
- b3Scalar m_contactMotion2;
- b3Scalar m_contactCFM1;
- b3Scalar m_contactCFM2;
-
- bool m_lateralFrictionInitialized;
-
- b3Vector3 getPositionWorldOnA()
+ b3Scalar m_combinedFriction;
+ b3Vector3 m_lateralFrictionDir1;
+ b3Vector3 m_lateralFrictionDir2;
+ b3Scalar m_appliedImpulseLateral1;
+ b3Scalar m_appliedImpulseLateral2;
+ b3Scalar m_combinedRollingFriction;
+ b3Scalar m_contactMotion1;
+ b3Scalar m_contactMotion2;
+ b3Scalar m_contactCFM1;
+ b3Scalar m_contactCFM2;
+
+ bool m_lateralFrictionInitialized;
+
+ b3Vector3 getPositionWorldOnA()
{
return m_positionWorldOnA;
}
- b3Vector3 getPositionWorldOnB()
+ b3Vector3 getPositionWorldOnB()
{
return m_positionWorldOnB;
}
- b3Scalar getDistance()
+ b3Scalar getDistance()
{
return m_distance;
}
};
-void getContactPoint(b3Contact4* contact, int contactIndex, b3ContactPoint& pointOut)
+void getContactPoint(b3Contact4* contact, int contactIndex, b3ContactPoint& pointOut)
{
pointOut.m_appliedImpulse = 0.f;
pointOut.m_appliedImpulseLateral1 = 0.f;
@@ -117,160 +113,145 @@ void getContactPoint(b3Contact4* contact, int contactIndex, b3ContactPoint& poin
pointOut.m_contactCFM2 = 0.f;
pointOut.m_contactMotion1 = 0.f;
pointOut.m_contactMotion2 = 0.f;
- pointOut.m_distance = contact->getPenetration(contactIndex);//??0.01f
+ pointOut.m_distance = contact->getPenetration(contactIndex); //??0.01f
b3Vector3 normalOnB = contact->m_worldNormalOnB;
- normalOnB.normalize();//is this needed?
+ normalOnB.normalize(); //is this needed?
- b3Vector3 l1,l2;
- b3PlaneSpace1(normalOnB,l1,l2);
+ b3Vector3 l1, l2;
+ b3PlaneSpace1(normalOnB, l1, l2);
pointOut.m_normalWorldOnB = normalOnB;
//printf("normalOnB = %f,%f,%f\n",normalOnB.getX(),normalOnB.getY(),normalOnB.getZ());
pointOut.m_lateralFrictionDir1 = l1;
pointOut.m_lateralFrictionDir2 = l2;
pointOut.m_lateralFrictionInitialized = true;
-
-
+
b3Vector3 worldPosB = contact->m_worldPosB[contactIndex];
pointOut.m_positionWorldOnB = worldPosB;
- pointOut.m_positionWorldOnA = worldPosB+normalOnB*pointOut.m_distance;
+ pointOut.m_positionWorldOnA = worldPosB + normalOnB * pointOut.m_distance;
}
-int getNumContacts(b3Contact4* contact)
+int getNumContacts(b3Contact4* contact)
{
return contact->getNPoints();
}
b3PgsJacobiSolver::b3PgsJacobiSolver(bool usePgs)
-:m_usePgs(usePgs),
-m_numSplitImpulseRecoveries(0),
-m_btSeed2(0)
+ : m_usePgs(usePgs),
+ m_numSplitImpulseRecoveries(0),
+ m_btSeed2(0)
{
-
}
b3PgsJacobiSolver::~b3PgsJacobiSolver()
{
}
-void b3PgsJacobiSolver::solveContacts(int numBodies, b3RigidBodyData* bodies, b3InertiaData* inertias, int numContacts, b3Contact4* contacts, int numConstraints, b3TypedConstraint** constraints)
+void b3PgsJacobiSolver::solveContacts(int numBodies, b3RigidBodyData* bodies, b3InertiaData* inertias, int numContacts, b3Contact4* contacts, int numConstraints, b3TypedConstraint** constraints)
{
b3ContactSolverInfo infoGlobal;
infoGlobal.m_splitImpulse = false;
- infoGlobal.m_timeStep = 1.f/60.f;
- infoGlobal.m_numIterations = 4;//4;
-// infoGlobal.m_solverMode|=B3_SOLVER_USE_2_FRICTION_DIRECTIONS|B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS|B3_SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION;
+ infoGlobal.m_timeStep = 1.f / 60.f;
+ infoGlobal.m_numIterations = 4; //4;
+ // infoGlobal.m_solverMode|=B3_SOLVER_USE_2_FRICTION_DIRECTIONS|B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS|B3_SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION;
//infoGlobal.m_solverMode|=B3_SOLVER_USE_2_FRICTION_DIRECTIONS|B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS;
- infoGlobal.m_solverMode|=B3_SOLVER_USE_2_FRICTION_DIRECTIONS;
+ infoGlobal.m_solverMode |= B3_SOLVER_USE_2_FRICTION_DIRECTIONS;
//if (infoGlobal.m_solverMode & B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS)
//if ((infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & B3_SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION))
-
- solveGroup(bodies,inertias,numBodies,contacts,numContacts,constraints,numConstraints,infoGlobal);
+ solveGroup(bodies, inertias, numBodies, contacts, numContacts, constraints, numConstraints, infoGlobal);
if (!numContacts)
return;
}
-
-
-
/// b3PgsJacobiSolver Sequentially applies impulses
b3Scalar b3PgsJacobiSolver::solveGroup(b3RigidBodyData* bodies,
- b3InertiaData* inertias,
- int numBodies,
- b3Contact4* manifoldPtr,
- int numManifolds,
- b3TypedConstraint** constraints,
- int numConstraints,
- const b3ContactSolverInfo& infoGlobal)
+ b3InertiaData* inertias,
+ int numBodies,
+ b3Contact4* manifoldPtr,
+ int numManifolds,
+ b3TypedConstraint** constraints,
+ int numConstraints,
+ const b3ContactSolverInfo& infoGlobal)
{
-
B3_PROFILE("solveGroup");
//you need to provide at least some bodies
-
- solveGroupCacheFriendlySetup( bodies, inertias,numBodies, manifoldPtr, numManifolds,constraints, numConstraints,infoGlobal);
-
- solveGroupCacheFriendlyIterations(constraints, numConstraints,infoGlobal);
-
- solveGroupCacheFriendlyFinish(bodies, inertias,numBodies, infoGlobal);
-
- return 0.f;
-}
-
-
-
-
+ solveGroupCacheFriendlySetup(bodies, inertias, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal);
+ solveGroupCacheFriendlyIterations(constraints, numConstraints, infoGlobal);
+ solveGroupCacheFriendlyFinish(bodies, inertias, numBodies, infoGlobal);
+ return 0.f;
+}
#ifdef USE_SIMD
#include <emmintrin.h>
-#define b3VecSplat(x, e) _mm_shuffle_ps(x, x, _MM_SHUFFLE(e,e,e,e))
-static inline __m128 b3SimdDot3( __m128 vec0, __m128 vec1 )
+#define b3VecSplat(x, e) _mm_shuffle_ps(x, x, _MM_SHUFFLE(e, e, e, e))
+static inline __m128 b3SimdDot3(__m128 vec0, __m128 vec1)
{
- __m128 result = _mm_mul_ps( vec0, vec1);
- return _mm_add_ps( b3VecSplat( result, 0 ), _mm_add_ps( b3VecSplat( result, 1 ), b3VecSplat( result, 2 ) ) );
+ __m128 result = _mm_mul_ps(vec0, vec1);
+ return _mm_add_ps(b3VecSplat(result, 0), _mm_add_ps(b3VecSplat(result, 1), b3VecSplat(result, 2)));
}
-#endif//USE_SIMD
+#endif //USE_SIMD
// Project Gauss Seidel or the equivalent Sequential Impulse
-void b3PgsJacobiSolver::resolveSingleConstraintRowGenericSIMD(b3SolverBody& body1,b3SolverBody& body2,const b3SolverConstraint& c)
+void b3PgsJacobiSolver::resolveSingleConstraintRowGenericSIMD(b3SolverBody& body1, b3SolverBody& body2, const b3SolverConstraint& c)
{
#ifdef USE_SIMD
__m128 cpAppliedImp = _mm_set1_ps(c.m_appliedImpulse);
- __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
- __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
- __m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhs), _mm_mul_ps(_mm_set1_ps(c.m_appliedImpulse),_mm_set1_ps(c.m_cfm)));
- __m128 deltaVel1Dotn = _mm_add_ps(b3SimdDot3(c.m_contactNormal.mVec128,body1.internalGetDeltaLinearVelocity().mVec128), b3SimdDot3(c.m_relpos1CrossNormal.mVec128,body1.internalGetDeltaAngularVelocity().mVec128));
- __m128 deltaVel2Dotn = _mm_sub_ps(b3SimdDot3(c.m_relpos2CrossNormal.mVec128,body2.internalGetDeltaAngularVelocity().mVec128),b3SimdDot3((c.m_contactNormal).mVec128,body2.internalGetDeltaLinearVelocity().mVec128));
- deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel1Dotn,_mm_set1_ps(c.m_jacDiagABInv)));
- deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel2Dotn,_mm_set1_ps(c.m_jacDiagABInv)));
- b3SimdScalar sum = _mm_add_ps(cpAppliedImp,deltaImpulse);
- b3SimdScalar resultLowerLess,resultUpperLess;
- resultLowerLess = _mm_cmplt_ps(sum,lowerLimit1);
- resultUpperLess = _mm_cmplt_ps(sum,upperLimit1);
- __m128 lowMinApplied = _mm_sub_ps(lowerLimit1,cpAppliedImp);
- deltaImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse) );
- c.m_appliedImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum) );
- __m128 upperMinApplied = _mm_sub_ps(upperLimit1,cpAppliedImp);
- deltaImpulse = _mm_or_ps( _mm_and_ps(resultUpperLess, deltaImpulse), _mm_andnot_ps(resultUpperLess, upperMinApplied) );
- c.m_appliedImpulse = _mm_or_ps( _mm_and_ps(resultUpperLess, c.m_appliedImpulse), _mm_andnot_ps(resultUpperLess, upperLimit1) );
- __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal.mVec128,body1.internalGetInvMass().mVec128);
- __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal).mVec128,body2.internalGetInvMass().mVec128);
+ __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
+ __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
+ __m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhs), _mm_mul_ps(_mm_set1_ps(c.m_appliedImpulse), _mm_set1_ps(c.m_cfm)));
+ __m128 deltaVel1Dotn = _mm_add_ps(b3SimdDot3(c.m_contactNormal.mVec128, body1.internalGetDeltaLinearVelocity().mVec128), b3SimdDot3(c.m_relpos1CrossNormal.mVec128, body1.internalGetDeltaAngularVelocity().mVec128));
+ __m128 deltaVel2Dotn = _mm_sub_ps(b3SimdDot3(c.m_relpos2CrossNormal.mVec128, body2.internalGetDeltaAngularVelocity().mVec128), b3SimdDot3((c.m_contactNormal).mVec128, body2.internalGetDeltaLinearVelocity().mVec128));
+ deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel1Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
+ deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel2Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
+ b3SimdScalar sum = _mm_add_ps(cpAppliedImp, deltaImpulse);
+ b3SimdScalar resultLowerLess, resultUpperLess;
+ resultLowerLess = _mm_cmplt_ps(sum, lowerLimit1);
+ resultUpperLess = _mm_cmplt_ps(sum, upperLimit1);
+ __m128 lowMinApplied = _mm_sub_ps(lowerLimit1, cpAppliedImp);
+ deltaImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse));
+ c.m_appliedImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum));
+ __m128 upperMinApplied = _mm_sub_ps(upperLimit1, cpAppliedImp);
+ deltaImpulse = _mm_or_ps(_mm_and_ps(resultUpperLess, deltaImpulse), _mm_andnot_ps(resultUpperLess, upperMinApplied));
+ c.m_appliedImpulse = _mm_or_ps(_mm_and_ps(resultUpperLess, c.m_appliedImpulse), _mm_andnot_ps(resultUpperLess, upperLimit1));
+ __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal.mVec128, body1.internalGetInvMass().mVec128);
+ __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal).mVec128, body2.internalGetInvMass().mVec128);
__m128 impulseMagnitude = deltaImpulse;
- body1.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaLinearVelocity().mVec128,_mm_mul_ps(linearComponentA,impulseMagnitude));
- body1.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaAngularVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentA.mVec128,impulseMagnitude));
- body2.internalGetDeltaLinearVelocity().mVec128 = _mm_sub_ps(body2.internalGetDeltaLinearVelocity().mVec128,_mm_mul_ps(linearComponentB,impulseMagnitude));
- body2.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body2.internalGetDeltaAngularVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentB.mVec128,impulseMagnitude));
+ body1.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentA, impulseMagnitude));
+ body1.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentA.mVec128, impulseMagnitude));
+ body2.internalGetDeltaLinearVelocity().mVec128 = _mm_sub_ps(body2.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentB, impulseMagnitude));
+ body2.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body2.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentB.mVec128, impulseMagnitude));
#else
- resolveSingleConstraintRowGeneric(body1,body2,c);
+ resolveSingleConstraintRowGeneric(body1, body2, c);
#endif
}
// Project Gauss Seidel or the equivalent Sequential Impulse
- void b3PgsJacobiSolver::resolveSingleConstraintRowGeneric(b3SolverBody& body1,b3SolverBody& body2,const b3SolverConstraint& c)
+void b3PgsJacobiSolver::resolveSingleConstraintRowGeneric(b3SolverBody& body1, b3SolverBody& body2, const b3SolverConstraint& c)
{
- b3Scalar deltaImpulse = c.m_rhs-b3Scalar(c.m_appliedImpulse)*c.m_cfm;
- const b3Scalar deltaVel1Dotn = c.m_contactNormal.dot(body1.internalGetDeltaLinearVelocity()) + c.m_relpos1CrossNormal.dot(body1.internalGetDeltaAngularVelocity());
- const b3Scalar deltaVel2Dotn = -c.m_contactNormal.dot(body2.internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetDeltaAngularVelocity());
+ b3Scalar deltaImpulse = c.m_rhs - b3Scalar(c.m_appliedImpulse) * c.m_cfm;
+ const b3Scalar deltaVel1Dotn = c.m_contactNormal.dot(body1.internalGetDeltaLinearVelocity()) + c.m_relpos1CrossNormal.dot(body1.internalGetDeltaAngularVelocity());
+ const b3Scalar deltaVel2Dotn = -c.m_contactNormal.dot(body2.internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetDeltaAngularVelocity());
-// const b3Scalar delta_rel_vel = deltaVel1Dotn-deltaVel2Dotn;
- deltaImpulse -= deltaVel1Dotn*c.m_jacDiagABInv;
- deltaImpulse -= deltaVel2Dotn*c.m_jacDiagABInv;
+ // const b3Scalar delta_rel_vel = deltaVel1Dotn-deltaVel2Dotn;
+ deltaImpulse -= deltaVel1Dotn * c.m_jacDiagABInv;
+ deltaImpulse -= deltaVel2Dotn * c.m_jacDiagABInv;
const b3Scalar sum = b3Scalar(c.m_appliedImpulse) + deltaImpulse;
if (sum < c.m_lowerLimit)
{
- deltaImpulse = c.m_lowerLimit-c.m_appliedImpulse;
+ deltaImpulse = c.m_lowerLimit - c.m_appliedImpulse;
c.m_appliedImpulse = c.m_lowerLimit;
}
- else if (sum > c.m_upperLimit)
+ else if (sum > c.m_upperLimit)
{
- deltaImpulse = c.m_upperLimit-c.m_appliedImpulse;
+ deltaImpulse = c.m_upperLimit - c.m_appliedImpulse;
c.m_appliedImpulse = c.m_upperLimit;
}
else
@@ -278,94 +259,93 @@ void b3PgsJacobiSolver::resolveSingleConstraintRowGenericSIMD(b3SolverBody& body
c.m_appliedImpulse = sum;
}
- body1.internalApplyImpulse(c.m_contactNormal*body1.internalGetInvMass(),c.m_angularComponentA,deltaImpulse);
- body2.internalApplyImpulse(-c.m_contactNormal*body2.internalGetInvMass(),c.m_angularComponentB,deltaImpulse);
+ body1.internalApplyImpulse(c.m_contactNormal * body1.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
+ body2.internalApplyImpulse(-c.m_contactNormal * body2.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
}
- void b3PgsJacobiSolver::resolveSingleConstraintRowLowerLimitSIMD(b3SolverBody& body1,b3SolverBody& body2,const b3SolverConstraint& c)
+void b3PgsJacobiSolver::resolveSingleConstraintRowLowerLimitSIMD(b3SolverBody& body1, b3SolverBody& body2, const b3SolverConstraint& c)
{
#ifdef USE_SIMD
__m128 cpAppliedImp = _mm_set1_ps(c.m_appliedImpulse);
- __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
- __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
- __m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhs), _mm_mul_ps(_mm_set1_ps(c.m_appliedImpulse),_mm_set1_ps(c.m_cfm)));
- __m128 deltaVel1Dotn = _mm_add_ps(b3SimdDot3(c.m_contactNormal.mVec128,body1.internalGetDeltaLinearVelocity().mVec128), b3SimdDot3(c.m_relpos1CrossNormal.mVec128,body1.internalGetDeltaAngularVelocity().mVec128));
- __m128 deltaVel2Dotn = _mm_sub_ps(b3SimdDot3(c.m_relpos2CrossNormal.mVec128,body2.internalGetDeltaAngularVelocity().mVec128),b3SimdDot3((c.m_contactNormal).mVec128,body2.internalGetDeltaLinearVelocity().mVec128));
- deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel1Dotn,_mm_set1_ps(c.m_jacDiagABInv)));
- deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel2Dotn,_mm_set1_ps(c.m_jacDiagABInv)));
- b3SimdScalar sum = _mm_add_ps(cpAppliedImp,deltaImpulse);
- b3SimdScalar resultLowerLess,resultUpperLess;
- resultLowerLess = _mm_cmplt_ps(sum,lowerLimit1);
- resultUpperLess = _mm_cmplt_ps(sum,upperLimit1);
- __m128 lowMinApplied = _mm_sub_ps(lowerLimit1,cpAppliedImp);
- deltaImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse) );
- c.m_appliedImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum) );
- __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal.mVec128,body1.internalGetInvMass().mVec128);
- __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal).mVec128,body2.internalGetInvMass().mVec128);
+ __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
+ __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
+ __m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhs), _mm_mul_ps(_mm_set1_ps(c.m_appliedImpulse), _mm_set1_ps(c.m_cfm)));
+ __m128 deltaVel1Dotn = _mm_add_ps(b3SimdDot3(c.m_contactNormal.mVec128, body1.internalGetDeltaLinearVelocity().mVec128), b3SimdDot3(c.m_relpos1CrossNormal.mVec128, body1.internalGetDeltaAngularVelocity().mVec128));
+ __m128 deltaVel2Dotn = _mm_sub_ps(b3SimdDot3(c.m_relpos2CrossNormal.mVec128, body2.internalGetDeltaAngularVelocity().mVec128), b3SimdDot3((c.m_contactNormal).mVec128, body2.internalGetDeltaLinearVelocity().mVec128));
+ deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel1Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
+ deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel2Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
+ b3SimdScalar sum = _mm_add_ps(cpAppliedImp, deltaImpulse);
+ b3SimdScalar resultLowerLess, resultUpperLess;
+ resultLowerLess = _mm_cmplt_ps(sum, lowerLimit1);
+ resultUpperLess = _mm_cmplt_ps(sum, upperLimit1);
+ __m128 lowMinApplied = _mm_sub_ps(lowerLimit1, cpAppliedImp);
+ deltaImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse));
+ c.m_appliedImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum));
+ __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal.mVec128, body1.internalGetInvMass().mVec128);
+ __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal).mVec128, body2.internalGetInvMass().mVec128);
__m128 impulseMagnitude = deltaImpulse;
- body1.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaLinearVelocity().mVec128,_mm_mul_ps(linearComponentA,impulseMagnitude));
- body1.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaAngularVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentA.mVec128,impulseMagnitude));
- body2.internalGetDeltaLinearVelocity().mVec128 = _mm_sub_ps(body2.internalGetDeltaLinearVelocity().mVec128,_mm_mul_ps(linearComponentB,impulseMagnitude));
- body2.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body2.internalGetDeltaAngularVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentB.mVec128,impulseMagnitude));
+ body1.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentA, impulseMagnitude));
+ body1.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentA.mVec128, impulseMagnitude));
+ body2.internalGetDeltaLinearVelocity().mVec128 = _mm_sub_ps(body2.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentB, impulseMagnitude));
+ body2.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body2.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentB.mVec128, impulseMagnitude));
#else
- resolveSingleConstraintRowLowerLimit(body1,body2,c);
+ resolveSingleConstraintRowLowerLimit(body1, body2, c);
#endif
}
// Project Gauss Seidel or the equivalent Sequential Impulse
- void b3PgsJacobiSolver::resolveSingleConstraintRowLowerLimit(b3SolverBody& body1,b3SolverBody& body2,const b3SolverConstraint& c)
+void b3PgsJacobiSolver::resolveSingleConstraintRowLowerLimit(b3SolverBody& body1, b3SolverBody& body2, const b3SolverConstraint& c)
{
- b3Scalar deltaImpulse = c.m_rhs-b3Scalar(c.m_appliedImpulse)*c.m_cfm;
- const b3Scalar deltaVel1Dotn = c.m_contactNormal.dot(body1.internalGetDeltaLinearVelocity()) + c.m_relpos1CrossNormal.dot(body1.internalGetDeltaAngularVelocity());
- const b3Scalar deltaVel2Dotn = -c.m_contactNormal.dot(body2.internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetDeltaAngularVelocity());
+ b3Scalar deltaImpulse = c.m_rhs - b3Scalar(c.m_appliedImpulse) * c.m_cfm;
+ const b3Scalar deltaVel1Dotn = c.m_contactNormal.dot(body1.internalGetDeltaLinearVelocity()) + c.m_relpos1CrossNormal.dot(body1.internalGetDeltaAngularVelocity());
+ const b3Scalar deltaVel2Dotn = -c.m_contactNormal.dot(body2.internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetDeltaAngularVelocity());
- deltaImpulse -= deltaVel1Dotn*c.m_jacDiagABInv;
- deltaImpulse -= deltaVel2Dotn*c.m_jacDiagABInv;
+ deltaImpulse -= deltaVel1Dotn * c.m_jacDiagABInv;
+ deltaImpulse -= deltaVel2Dotn * c.m_jacDiagABInv;
const b3Scalar sum = b3Scalar(c.m_appliedImpulse) + deltaImpulse;
if (sum < c.m_lowerLimit)
{
- deltaImpulse = c.m_lowerLimit-c.m_appliedImpulse;
+ deltaImpulse = c.m_lowerLimit - c.m_appliedImpulse;
c.m_appliedImpulse = c.m_lowerLimit;
}
else
{
c.m_appliedImpulse = sum;
}
- body1.internalApplyImpulse(c.m_contactNormal*body1.internalGetInvMass(),c.m_angularComponentA,deltaImpulse);
- body2.internalApplyImpulse(-c.m_contactNormal*body2.internalGetInvMass(),c.m_angularComponentB,deltaImpulse);
+ body1.internalApplyImpulse(c.m_contactNormal * body1.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
+ body2.internalApplyImpulse(-c.m_contactNormal * body2.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
}
-
-void b3PgsJacobiSolver::resolveSplitPenetrationImpulseCacheFriendly(
- b3SolverBody& body1,
- b3SolverBody& body2,
- const b3SolverConstraint& c)
+void b3PgsJacobiSolver::resolveSplitPenetrationImpulseCacheFriendly(
+ b3SolverBody& body1,
+ b3SolverBody& body2,
+ const b3SolverConstraint& c)
{
- if (c.m_rhsPenetration)
- {
- m_numSplitImpulseRecoveries++;
- b3Scalar deltaImpulse = c.m_rhsPenetration-b3Scalar(c.m_appliedPushImpulse)*c.m_cfm;
- const b3Scalar deltaVel1Dotn = c.m_contactNormal.dot(body1.internalGetPushVelocity()) + c.m_relpos1CrossNormal.dot(body1.internalGetTurnVelocity());
- const b3Scalar deltaVel2Dotn = -c.m_contactNormal.dot(body2.internalGetPushVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetTurnVelocity());
-
- deltaImpulse -= deltaVel1Dotn*c.m_jacDiagABInv;
- deltaImpulse -= deltaVel2Dotn*c.m_jacDiagABInv;
- const b3Scalar sum = b3Scalar(c.m_appliedPushImpulse) + deltaImpulse;
- if (sum < c.m_lowerLimit)
- {
- deltaImpulse = c.m_lowerLimit-c.m_appliedPushImpulse;
- c.m_appliedPushImpulse = c.m_lowerLimit;
- }
- else
- {
- c.m_appliedPushImpulse = sum;
- }
- body1.internalApplyPushImpulse(c.m_contactNormal*body1.internalGetInvMass(),c.m_angularComponentA,deltaImpulse);
- body2.internalApplyPushImpulse(-c.m_contactNormal*body2.internalGetInvMass(),c.m_angularComponentB,deltaImpulse);
- }
+ if (c.m_rhsPenetration)
+ {
+ m_numSplitImpulseRecoveries++;
+ b3Scalar deltaImpulse = c.m_rhsPenetration - b3Scalar(c.m_appliedPushImpulse) * c.m_cfm;
+ const b3Scalar deltaVel1Dotn = c.m_contactNormal.dot(body1.internalGetPushVelocity()) + c.m_relpos1CrossNormal.dot(body1.internalGetTurnVelocity());
+ const b3Scalar deltaVel2Dotn = -c.m_contactNormal.dot(body2.internalGetPushVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetTurnVelocity());
+
+ deltaImpulse -= deltaVel1Dotn * c.m_jacDiagABInv;
+ deltaImpulse -= deltaVel2Dotn * c.m_jacDiagABInv;
+ const b3Scalar sum = b3Scalar(c.m_appliedPushImpulse) + deltaImpulse;
+ if (sum < c.m_lowerLimit)
+ {
+ deltaImpulse = c.m_lowerLimit - c.m_appliedPushImpulse;
+ c.m_appliedPushImpulse = c.m_lowerLimit;
+ }
+ else
+ {
+ c.m_appliedPushImpulse = sum;
+ }
+ body1.internalApplyPushImpulse(c.m_contactNormal * body1.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
+ body2.internalApplyPushImpulse(-c.m_contactNormal * body2.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
+ }
}
- void b3PgsJacobiSolver::resolveSplitPenetrationSIMD(b3SolverBody& body1,b3SolverBody& body2,const b3SolverConstraint& c)
+void b3PgsJacobiSolver::resolveSplitPenetrationSIMD(b3SolverBody& body1, b3SolverBody& body2, const b3SolverConstraint& c)
{
#ifdef USE_SIMD
if (!c.m_rhsPenetration)
@@ -374,44 +354,40 @@ void b3PgsJacobiSolver::resolveSplitPenetrationImpulseCacheFriendly(
m_numSplitImpulseRecoveries++;
__m128 cpAppliedImp = _mm_set1_ps(c.m_appliedPushImpulse);
- __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
- __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
- __m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhsPenetration), _mm_mul_ps(_mm_set1_ps(c.m_appliedPushImpulse),_mm_set1_ps(c.m_cfm)));
- __m128 deltaVel1Dotn = _mm_add_ps(b3SimdDot3(c.m_contactNormal.mVec128,body1.internalGetPushVelocity().mVec128), b3SimdDot3(c.m_relpos1CrossNormal.mVec128,body1.internalGetTurnVelocity().mVec128));
- __m128 deltaVel2Dotn = _mm_sub_ps(b3SimdDot3(c.m_relpos2CrossNormal.mVec128,body2.internalGetTurnVelocity().mVec128),b3SimdDot3((c.m_contactNormal).mVec128,body2.internalGetPushVelocity().mVec128));
- deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel1Dotn,_mm_set1_ps(c.m_jacDiagABInv)));
- deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel2Dotn,_mm_set1_ps(c.m_jacDiagABInv)));
- b3SimdScalar sum = _mm_add_ps(cpAppliedImp,deltaImpulse);
- b3SimdScalar resultLowerLess,resultUpperLess;
- resultLowerLess = _mm_cmplt_ps(sum,lowerLimit1);
- resultUpperLess = _mm_cmplt_ps(sum,upperLimit1);
- __m128 lowMinApplied = _mm_sub_ps(lowerLimit1,cpAppliedImp);
- deltaImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse) );
- c.m_appliedPushImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum) );
- __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal.mVec128,body1.internalGetInvMass().mVec128);
- __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal).mVec128,body2.internalGetInvMass().mVec128);
+ __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
+ __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
+ __m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhsPenetration), _mm_mul_ps(_mm_set1_ps(c.m_appliedPushImpulse), _mm_set1_ps(c.m_cfm)));
+ __m128 deltaVel1Dotn = _mm_add_ps(b3SimdDot3(c.m_contactNormal.mVec128, body1.internalGetPushVelocity().mVec128), b3SimdDot3(c.m_relpos1CrossNormal.mVec128, body1.internalGetTurnVelocity().mVec128));
+ __m128 deltaVel2Dotn = _mm_sub_ps(b3SimdDot3(c.m_relpos2CrossNormal.mVec128, body2.internalGetTurnVelocity().mVec128), b3SimdDot3((c.m_contactNormal).mVec128, body2.internalGetPushVelocity().mVec128));
+ deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel1Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
+ deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel2Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
+ b3SimdScalar sum = _mm_add_ps(cpAppliedImp, deltaImpulse);
+ b3SimdScalar resultLowerLess, resultUpperLess;
+ resultLowerLess = _mm_cmplt_ps(sum, lowerLimit1);
+ resultUpperLess = _mm_cmplt_ps(sum, upperLimit1);
+ __m128 lowMinApplied = _mm_sub_ps(lowerLimit1, cpAppliedImp);
+ deltaImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse));
+ c.m_appliedPushImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum));
+ __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal.mVec128, body1.internalGetInvMass().mVec128);
+ __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal).mVec128, body2.internalGetInvMass().mVec128);
__m128 impulseMagnitude = deltaImpulse;
- body1.internalGetPushVelocity().mVec128 = _mm_add_ps(body1.internalGetPushVelocity().mVec128,_mm_mul_ps(linearComponentA,impulseMagnitude));
- body1.internalGetTurnVelocity().mVec128 = _mm_add_ps(body1.internalGetTurnVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentA.mVec128,impulseMagnitude));
- body2.internalGetPushVelocity().mVec128 = _mm_sub_ps(body2.internalGetPushVelocity().mVec128,_mm_mul_ps(linearComponentB,impulseMagnitude));
- body2.internalGetTurnVelocity().mVec128 = _mm_add_ps(body2.internalGetTurnVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentB.mVec128,impulseMagnitude));
+ body1.internalGetPushVelocity().mVec128 = _mm_add_ps(body1.internalGetPushVelocity().mVec128, _mm_mul_ps(linearComponentA, impulseMagnitude));
+ body1.internalGetTurnVelocity().mVec128 = _mm_add_ps(body1.internalGetTurnVelocity().mVec128, _mm_mul_ps(c.m_angularComponentA.mVec128, impulseMagnitude));
+ body2.internalGetPushVelocity().mVec128 = _mm_sub_ps(body2.internalGetPushVelocity().mVec128, _mm_mul_ps(linearComponentB, impulseMagnitude));
+ body2.internalGetTurnVelocity().mVec128 = _mm_add_ps(body2.internalGetTurnVelocity().mVec128, _mm_mul_ps(c.m_angularComponentB.mVec128, impulseMagnitude));
#else
- resolveSplitPenetrationImpulseCacheFriendly(body1,body2,c);
+ resolveSplitPenetrationImpulseCacheFriendly(body1, body2, c);
#endif
}
-
-
unsigned long b3PgsJacobiSolver::b3Rand2()
{
- m_btSeed2 = (1664525L*m_btSeed2 + 1013904223L) & 0xffffffff;
+ m_btSeed2 = (1664525L * m_btSeed2 + 1013904223L) & 0xffffffff;
return m_btSeed2;
}
-
-
//See ODE: adam's all-int straightforward(?) dRandInt (0..n-1)
-int b3PgsJacobiSolver::b3RandInt2 (int n)
+int b3PgsJacobiSolver::b3RandInt2(int n)
{
// seems good; xor-fold and modulus
const unsigned long un = static_cast<unsigned long>(n);
@@ -419,15 +395,20 @@ int b3PgsJacobiSolver::b3RandInt2 (int n)
// 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) {
+ if (un <= 0x00010000UL)
+ {
r ^= (r >> 16);
- if (un <= 0x00000100UL) {
+ if (un <= 0x00000100UL)
+ {
r ^= (r >> 8);
- if (un <= 0x00000010UL) {
+ if (un <= 0x00000010UL)
+ {
r ^= (r >> 4);
- if (un <= 0x00000004UL) {
+ if (un <= 0x00000004UL)
+ {
r ^= (r >> 2);
- if (un <= 0x00000002UL) {
+ if (un <= 0x00000002UL)
+ {
r ^= (r >> 1);
}
}
@@ -435,62 +416,46 @@ int b3PgsJacobiSolver::b3RandInt2 (int n)
}
}
- return (int) (r % un);
+ return (int)(r % un);
}
-
-
-void b3PgsJacobiSolver::initSolverBody(int bodyIndex, b3SolverBody* solverBody, b3RigidBodyData* rb)
+void b3PgsJacobiSolver::initSolverBody(int bodyIndex, b3SolverBody* solverBody, b3RigidBodyData* rb)
{
-
- solverBody->m_deltaLinearVelocity.setValue(0.f,0.f,0.f);
- solverBody->m_deltaAngularVelocity.setValue(0.f,0.f,0.f);
- solverBody->internalGetPushVelocity().setValue(0.f,0.f,0.f);
- solverBody->internalGetTurnVelocity().setValue(0.f,0.f,0.f);
+ solverBody->m_deltaLinearVelocity.setValue(0.f, 0.f, 0.f);
+ solverBody->m_deltaAngularVelocity.setValue(0.f, 0.f, 0.f);
+ solverBody->internalGetPushVelocity().setValue(0.f, 0.f, 0.f);
+ solverBody->internalGetTurnVelocity().setValue(0.f, 0.f, 0.f);
if (rb)
{
solverBody->m_worldTransform = getWorldTransform(rb);
- solverBody->internalSetInvMass(b3MakeVector3(rb->m_invMass,rb->m_invMass,rb->m_invMass));
+ solverBody->internalSetInvMass(b3MakeVector3(rb->m_invMass, rb->m_invMass, rb->m_invMass));
solverBody->m_originalBodyIndex = bodyIndex;
- solverBody->m_angularFactor = b3MakeVector3(1,1,1);
- solverBody->m_linearFactor = b3MakeVector3(1,1,1);
+ solverBody->m_angularFactor = b3MakeVector3(1, 1, 1);
+ solverBody->m_linearFactor = b3MakeVector3(1, 1, 1);
solverBody->m_linearVelocity = getLinearVelocity(rb);
solverBody->m_angularVelocity = getAngularVelocity(rb);
- } else
+ }
+ else
{
solverBody->m_worldTransform.setIdentity();
- solverBody->internalSetInvMass(b3MakeVector3(0,0,0));
+ solverBody->internalSetInvMass(b3MakeVector3(0, 0, 0));
solverBody->m_originalBodyIndex = bodyIndex;
- solverBody->m_angularFactor.setValue(1,1,1);
- solverBody->m_linearFactor.setValue(1,1,1);
- solverBody->m_linearVelocity.setValue(0,0,0);
- solverBody->m_angularVelocity.setValue(0,0,0);
+ solverBody->m_angularFactor.setValue(1, 1, 1);
+ solverBody->m_linearFactor.setValue(1, 1, 1);
+ solverBody->m_linearVelocity.setValue(0, 0, 0);
+ solverBody->m_angularVelocity.setValue(0, 0, 0);
}
-
-
}
-
-
-
-
-
b3Scalar b3PgsJacobiSolver::restitutionCurve(b3Scalar rel_vel, b3Scalar restitution)
{
b3Scalar rest = restitution * -rel_vel;
return rest;
}
-
-
-
-
-
-void b3PgsJacobiSolver::setupFrictionConstraint(b3RigidBodyData* bodies,b3InertiaData* inertias, b3SolverConstraint& solverConstraint, const b3Vector3& normalAxis,int solverBodyIdA,int solverBodyIdB,b3ContactPoint& cp,const b3Vector3& rel_pos1,const b3Vector3& rel_pos2,b3RigidBodyData* colObj0,b3RigidBodyData* colObj1, b3Scalar relaxation, b3Scalar desiredVelocity, b3Scalar cfmSlip)
+void b3PgsJacobiSolver::setupFrictionConstraint(b3RigidBodyData* bodies, b3InertiaData* inertias, b3SolverConstraint& solverConstraint, const b3Vector3& normalAxis, int solverBodyIdA, int solverBodyIdB, b3ContactPoint& cp, const b3Vector3& rel_pos1, const b3Vector3& rel_pos2, b3RigidBodyData* colObj0, b3RigidBodyData* colObj1, b3Scalar relaxation, b3Scalar desiredVelocity, b3Scalar cfmSlip)
{
-
-
solverConstraint.m_contactNormal = normalAxis;
b3SolverBody& solverBodyA = m_tmpSolverBodyPool[solverBodyIdA];
b3SolverBody& solverBodyB = m_tmpSolverBodyPool[solverBodyIdB];
@@ -498,7 +463,6 @@ void b3PgsJacobiSolver::setupFrictionConstraint(b3RigidBodyData* bodies,b3Inerti
b3RigidBodyData* body0 = &bodies[solverBodyA.m_originalBodyIndex];
b3RigidBodyData* body1 = &bodies[solverBodyB.m_originalBodyIndex];
-
solverConstraint.m_solverBodyIdA = solverBodyIdA;
solverConstraint.m_solverBodyIdB = solverBodyIdB;
@@ -511,12 +475,12 @@ void b3PgsJacobiSolver::setupFrictionConstraint(b3RigidBodyData* bodies,b3Inerti
{
b3Vector3 ftorqueAxis1 = rel_pos1.cross(solverConstraint.m_contactNormal);
solverConstraint.m_relpos1CrossNormal = ftorqueAxis1;
- solverConstraint.m_angularComponentA = body0 ? getInvInertiaTensorWorld(&inertias[solverBodyA.m_originalBodyIndex])*ftorqueAxis1 : b3MakeVector3(0,0,0);
+ solverConstraint.m_angularComponentA = body0 ? getInvInertiaTensorWorld(&inertias[solverBodyA.m_originalBodyIndex]) * ftorqueAxis1 : b3MakeVector3(0, 0, 0);
}
{
b3Vector3 ftorqueAxis1 = rel_pos2.cross(-solverConstraint.m_contactNormal);
solverConstraint.m_relpos2CrossNormal = ftorqueAxis1;
- solverConstraint.m_angularComponentB = body1 ? getInvInertiaTensorWorld(&inertias[solverBodyB.m_originalBodyIndex])*ftorqueAxis1 : b3MakeVector3(0,0,0);
+ solverConstraint.m_angularComponentB = body1 ? getInvInertiaTensorWorld(&inertias[solverBodyB.m_originalBodyIndex]) * ftorqueAxis1 : b3MakeVector3(0, 0, 0);
}
b3Scalar scaledDenom;
@@ -527,72 +491,66 @@ void b3PgsJacobiSolver::setupFrictionConstraint(b3RigidBodyData* bodies,b3Inerti
b3Scalar denom1 = 0.f;
if (body0)
{
- vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1);
+ vec = (solverConstraint.m_angularComponentA).cross(rel_pos1);
denom0 = body0->m_invMass + normalAxis.dot(vec);
}
if (body1)
{
- vec = ( -solverConstraint.m_angularComponentB).cross(rel_pos2);
+ vec = (-solverConstraint.m_angularComponentB).cross(rel_pos2);
denom1 = body1->m_invMass + normalAxis.dot(vec);
}
b3Scalar denom;
if (m_usePgs)
{
- scaledDenom = denom = relaxation/(denom0+denom1);
- } else
+ scaledDenom = denom = relaxation / (denom0 + denom1);
+ }
+ else
{
- denom = relaxation/(denom0+denom1);
- b3Scalar countA = body0->m_invMass ? b3Scalar(m_bodyCount[solverBodyA.m_originalBodyIndex]): 1.f;
- b3Scalar countB = body1->m_invMass ? b3Scalar(m_bodyCount[solverBodyB.m_originalBodyIndex]): 1.f;
+ denom = relaxation / (denom0 + denom1);
+ b3Scalar countA = body0->m_invMass ? b3Scalar(m_bodyCount[solverBodyA.m_originalBodyIndex]) : 1.f;
+ b3Scalar countB = body1->m_invMass ? b3Scalar(m_bodyCount[solverBodyB.m_originalBodyIndex]) : 1.f;
- scaledDenom = relaxation/(denom0*countA+denom1*countB);
+ scaledDenom = relaxation / (denom0 * countA + denom1 * countB);
}
solverConstraint.m_jacDiagABInv = denom;
}
{
-
-
b3Scalar rel_vel;
- b3Scalar vel1Dotn = solverConstraint.m_contactNormal.dot(body0?solverBodyA.m_linearVelocity:b3MakeVector3(0,0,0))
- + solverConstraint.m_relpos1CrossNormal.dot(body0?solverBodyA.m_angularVelocity:b3MakeVector3(0,0,0));
- b3Scalar vel2Dotn = -solverConstraint.m_contactNormal.dot(body1?solverBodyB.m_linearVelocity:b3MakeVector3(0,0,0))
- + solverConstraint.m_relpos2CrossNormal.dot(body1?solverBodyB.m_angularVelocity:b3MakeVector3(0,0,0));
+ b3Scalar vel1Dotn = solverConstraint.m_contactNormal.dot(body0 ? solverBodyA.m_linearVelocity : b3MakeVector3(0, 0, 0)) + solverConstraint.m_relpos1CrossNormal.dot(body0 ? solverBodyA.m_angularVelocity : b3MakeVector3(0, 0, 0));
+ b3Scalar vel2Dotn = -solverConstraint.m_contactNormal.dot(body1 ? solverBodyB.m_linearVelocity : b3MakeVector3(0, 0, 0)) + solverConstraint.m_relpos2CrossNormal.dot(body1 ? solverBodyB.m_angularVelocity : b3MakeVector3(0, 0, 0));
- rel_vel = vel1Dotn+vel2Dotn;
+ rel_vel = vel1Dotn + vel2Dotn;
-// b3Scalar positionalError = 0.f;
+ // b3Scalar positionalError = 0.f;
- b3SimdScalar velocityError = desiredVelocity - rel_vel;
- b3SimdScalar velocityImpulse = velocityError * b3SimdScalar(scaledDenom);//solverConstraint.m_jacDiagABInv);
+ b3SimdScalar velocityError = desiredVelocity - rel_vel;
+ b3SimdScalar velocityImpulse = velocityError * b3SimdScalar(scaledDenom); //solverConstraint.m_jacDiagABInv);
solverConstraint.m_rhs = velocityImpulse;
solverConstraint.m_cfm = cfmSlip;
solverConstraint.m_lowerLimit = 0;
solverConstraint.m_upperLimit = 1e10f;
-
}
}
-b3SolverConstraint& b3PgsJacobiSolver::addFrictionConstraint(b3RigidBodyData* bodies,b3InertiaData* inertias, const b3Vector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,b3ContactPoint& cp,const b3Vector3& rel_pos1,const b3Vector3& rel_pos2,b3RigidBodyData* colObj0,b3RigidBodyData* colObj1, b3Scalar relaxation, b3Scalar desiredVelocity, b3Scalar cfmSlip)
+b3SolverConstraint& b3PgsJacobiSolver::addFrictionConstraint(b3RigidBodyData* bodies, b3InertiaData* inertias, const b3Vector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, b3ContactPoint& cp, const b3Vector3& rel_pos1, const b3Vector3& rel_pos2, b3RigidBodyData* colObj0, b3RigidBodyData* colObj1, b3Scalar relaxation, b3Scalar desiredVelocity, b3Scalar cfmSlip)
{
b3SolverConstraint& solverConstraint = m_tmpSolverContactFrictionConstraintPool.expandNonInitializing();
solverConstraint.m_frictionIndex = frictionIndex;
- setupFrictionConstraint(bodies,inertias,solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2,
+ setupFrictionConstraint(bodies, inertias, solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2,
colObj0, colObj1, relaxation, desiredVelocity, cfmSlip);
return solverConstraint;
}
-
-void b3PgsJacobiSolver::setupRollingFrictionConstraint(b3RigidBodyData* bodies,b3InertiaData* inertias, b3SolverConstraint& solverConstraint, const b3Vector3& normalAxis1,int solverBodyIdA,int solverBodyIdB,
- b3ContactPoint& cp,const b3Vector3& rel_pos1,const b3Vector3& rel_pos2,
- b3RigidBodyData* colObj0,b3RigidBodyData* colObj1, b3Scalar relaxation,
- b3Scalar desiredVelocity, b3Scalar cfmSlip)
+void b3PgsJacobiSolver::setupRollingFrictionConstraint(b3RigidBodyData* bodies, b3InertiaData* inertias, b3SolverConstraint& solverConstraint, const b3Vector3& normalAxis1, int solverBodyIdA, int solverBodyIdB,
+ b3ContactPoint& cp, const b3Vector3& rel_pos1, const b3Vector3& rel_pos2,
+ b3RigidBodyData* colObj0, b3RigidBodyData* colObj1, b3Scalar relaxation,
+ b3Scalar desiredVelocity, b3Scalar cfmSlip)
{
- b3Vector3 normalAxis=b3MakeVector3(0,0,0);
-
+ b3Vector3 normalAxis = b3MakeVector3(0, 0, 0);
solverConstraint.m_contactNormal = normalAxis;
b3SolverBody& solverBodyA = m_tmpSolverBodyPool[solverBodyIdA];
@@ -613,283 +571,256 @@ void b3PgsJacobiSolver::setupRollingFrictionConstraint(b3RigidBodyData* bodies,b
{
b3Vector3 ftorqueAxis1 = -normalAxis1;
solverConstraint.m_relpos1CrossNormal = ftorqueAxis1;
- solverConstraint.m_angularComponentA = body0 ? getInvInertiaTensorWorld(&inertias[solverBodyA.m_originalBodyIndex])*ftorqueAxis1 : b3MakeVector3(0,0,0);
+ solverConstraint.m_angularComponentA = body0 ? getInvInertiaTensorWorld(&inertias[solverBodyA.m_originalBodyIndex]) * ftorqueAxis1 : b3MakeVector3(0, 0, 0);
}
{
b3Vector3 ftorqueAxis1 = normalAxis1;
solverConstraint.m_relpos2CrossNormal = ftorqueAxis1;
- solverConstraint.m_angularComponentB = body1 ? getInvInertiaTensorWorld(&inertias[solverBodyB.m_originalBodyIndex])*ftorqueAxis1 : b3MakeVector3(0,0,0);
+ solverConstraint.m_angularComponentB = body1 ? getInvInertiaTensorWorld(&inertias[solverBodyB.m_originalBodyIndex]) * ftorqueAxis1 : b3MakeVector3(0, 0, 0);
}
-
{
- b3Vector3 iMJaA = body0?getInvInertiaTensorWorld(&inertias[solverBodyA.m_originalBodyIndex])*solverConstraint.m_relpos1CrossNormal:b3MakeVector3(0,0,0);
- b3Vector3 iMJaB = body1?getInvInertiaTensorWorld(&inertias[solverBodyB.m_originalBodyIndex])*solverConstraint.m_relpos2CrossNormal:b3MakeVector3(0,0,0);
+ b3Vector3 iMJaA = body0 ? getInvInertiaTensorWorld(&inertias[solverBodyA.m_originalBodyIndex]) * solverConstraint.m_relpos1CrossNormal : b3MakeVector3(0, 0, 0);
+ b3Vector3 iMJaB = body1 ? getInvInertiaTensorWorld(&inertias[solverBodyB.m_originalBodyIndex]) * solverConstraint.m_relpos2CrossNormal : b3MakeVector3(0, 0, 0);
b3Scalar sum = 0;
sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
- solverConstraint.m_jacDiagABInv = b3Scalar(1.)/sum;
+ solverConstraint.m_jacDiagABInv = b3Scalar(1.) / sum;
}
{
-
-
b3Scalar rel_vel;
- b3Scalar vel1Dotn = solverConstraint.m_contactNormal.dot(body0?solverBodyA.m_linearVelocity:b3MakeVector3(0,0,0))
- + solverConstraint.m_relpos1CrossNormal.dot(body0?solverBodyA.m_angularVelocity:b3MakeVector3(0,0,0));
- b3Scalar vel2Dotn = -solverConstraint.m_contactNormal.dot(body1?solverBodyB.m_linearVelocity:b3MakeVector3(0,0,0))
- + solverConstraint.m_relpos2CrossNormal.dot(body1?solverBodyB.m_angularVelocity:b3MakeVector3(0,0,0));
+ b3Scalar vel1Dotn = solverConstraint.m_contactNormal.dot(body0 ? solverBodyA.m_linearVelocity : b3MakeVector3(0, 0, 0)) + solverConstraint.m_relpos1CrossNormal.dot(body0 ? solverBodyA.m_angularVelocity : b3MakeVector3(0, 0, 0));
+ b3Scalar vel2Dotn = -solverConstraint.m_contactNormal.dot(body1 ? solverBodyB.m_linearVelocity : b3MakeVector3(0, 0, 0)) + solverConstraint.m_relpos2CrossNormal.dot(body1 ? solverBodyB.m_angularVelocity : b3MakeVector3(0, 0, 0));
- rel_vel = vel1Dotn+vel2Dotn;
+ rel_vel = vel1Dotn + vel2Dotn;
-// b3Scalar positionalError = 0.f;
+ // b3Scalar positionalError = 0.f;
- b3SimdScalar velocityError = desiredVelocity - rel_vel;
- b3SimdScalar velocityImpulse = velocityError * b3SimdScalar(solverConstraint.m_jacDiagABInv);
+ b3SimdScalar velocityError = desiredVelocity - rel_vel;
+ b3SimdScalar velocityImpulse = velocityError * b3SimdScalar(solverConstraint.m_jacDiagABInv);
solverConstraint.m_rhs = velocityImpulse;
solverConstraint.m_cfm = cfmSlip;
solverConstraint.m_lowerLimit = 0;
solverConstraint.m_upperLimit = 1e10f;
-
}
}
-
-
-
-
-
-
-
-b3SolverConstraint& b3PgsJacobiSolver::addRollingFrictionConstraint(b3RigidBodyData* bodies,b3InertiaData* inertias,const b3Vector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,b3ContactPoint& cp,const b3Vector3& rel_pos1,const b3Vector3& rel_pos2,b3RigidBodyData* colObj0,b3RigidBodyData* colObj1, b3Scalar relaxation, b3Scalar desiredVelocity, b3Scalar cfmSlip)
+b3SolverConstraint& b3PgsJacobiSolver::addRollingFrictionConstraint(b3RigidBodyData* bodies, b3InertiaData* inertias, const b3Vector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, b3ContactPoint& cp, const b3Vector3& rel_pos1, const b3Vector3& rel_pos2, b3RigidBodyData* colObj0, b3RigidBodyData* colObj1, b3Scalar relaxation, b3Scalar desiredVelocity, b3Scalar cfmSlip)
{
b3SolverConstraint& solverConstraint = m_tmpSolverContactRollingFrictionConstraintPool.expandNonInitializing();
solverConstraint.m_frictionIndex = frictionIndex;
- setupRollingFrictionConstraint(bodies,inertias,solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2,
- colObj0, colObj1, relaxation, desiredVelocity, cfmSlip);
+ setupRollingFrictionConstraint(bodies, inertias, solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2,
+ colObj0, colObj1, relaxation, desiredVelocity, cfmSlip);
return solverConstraint;
}
-
-int b3PgsJacobiSolver::getOrInitSolverBody(int bodyIndex, b3RigidBodyData* bodies,b3InertiaData* inertias)
+int b3PgsJacobiSolver::getOrInitSolverBody(int bodyIndex, b3RigidBodyData* bodies, b3InertiaData* inertias)
{
//b3Assert(bodyIndex< m_tmpSolverBodyPool.size());
b3RigidBodyData& body = bodies[bodyIndex];
int curIndex = -1;
- if (m_usePgs || body.m_invMass==0.f)
+ if (m_usePgs || body.m_invMass == 0.f)
{
- if (m_bodyCount[bodyIndex]<0)
+ if (m_bodyCount[bodyIndex] < 0)
{
curIndex = m_tmpSolverBodyPool.size();
b3SolverBody& solverBody = m_tmpSolverBodyPool.expand();
- initSolverBody(bodyIndex,&solverBody,&body);
+ initSolverBody(bodyIndex, &solverBody, &body);
solverBody.m_originalBodyIndex = bodyIndex;
m_bodyCount[bodyIndex] = curIndex;
- } else
+ }
+ else
{
curIndex = m_bodyCount[bodyIndex];
}
- } else
+ }
+ else
{
- b3Assert(m_bodyCount[bodyIndex]>0);
+ b3Assert(m_bodyCount[bodyIndex] > 0);
m_bodyCountCheck[bodyIndex]++;
curIndex = m_tmpSolverBodyPool.size();
b3SolverBody& solverBody = m_tmpSolverBodyPool.expand();
- initSolverBody(bodyIndex,&solverBody,&body);
+ initSolverBody(bodyIndex, &solverBody, &body);
solverBody.m_originalBodyIndex = bodyIndex;
}
- b3Assert(curIndex>=0);
+ b3Assert(curIndex >= 0);
return curIndex;
-
}
#include <stdio.h>
-
-void b3PgsJacobiSolver::setupContactConstraint(b3RigidBodyData* bodies, b3InertiaData* inertias,b3SolverConstraint& solverConstraint,
- int solverBodyIdA, int solverBodyIdB,
- b3ContactPoint& cp, const b3ContactSolverInfo& infoGlobal,
- b3Vector3& vel, b3Scalar& rel_vel, b3Scalar& relaxation,
- b3Vector3& rel_pos1, b3Vector3& rel_pos2)
+void b3PgsJacobiSolver::setupContactConstraint(b3RigidBodyData* bodies, b3InertiaData* inertias, b3SolverConstraint& solverConstraint,
+ int solverBodyIdA, int solverBodyIdB,
+ b3ContactPoint& cp, const b3ContactSolverInfo& infoGlobal,
+ b3Vector3& vel, b3Scalar& rel_vel, b3Scalar& relaxation,
+ b3Vector3& rel_pos1, b3Vector3& rel_pos2)
{
-
- const b3Vector3& pos1 = cp.getPositionWorldOnA();
- const b3Vector3& pos2 = cp.getPositionWorldOnB();
+ const b3Vector3& pos1 = cp.getPositionWorldOnA();
+ const b3Vector3& pos2 = cp.getPositionWorldOnB();
- b3SolverBody* bodyA = &m_tmpSolverBodyPool[solverBodyIdA];
- b3SolverBody* bodyB = &m_tmpSolverBodyPool[solverBodyIdB];
+ b3SolverBody* bodyA = &m_tmpSolverBodyPool[solverBodyIdA];
+ b3SolverBody* bodyB = &m_tmpSolverBodyPool[solverBodyIdB];
- b3RigidBodyData* rb0 = &bodies[bodyA->m_originalBodyIndex];
- b3RigidBodyData* rb1 = &bodies[bodyB->m_originalBodyIndex];
+ b3RigidBodyData* rb0 = &bodies[bodyA->m_originalBodyIndex];
+ b3RigidBodyData* rb1 = &bodies[bodyB->m_originalBodyIndex];
-// b3Vector3 rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin();
-// b3Vector3 rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin();
- rel_pos1 = pos1 - bodyA->getWorldTransform().getOrigin();
- rel_pos2 = pos2 - bodyB->getWorldTransform().getOrigin();
+ // b3Vector3 rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin();
+ // b3Vector3 rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin();
+ rel_pos1 = pos1 - bodyA->getWorldTransform().getOrigin();
+ rel_pos2 = pos2 - bodyB->getWorldTransform().getOrigin();
- relaxation = 1.f;
+ relaxation = 1.f;
- b3Vector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB);
- solverConstraint.m_angularComponentA = rb0 ? getInvInertiaTensorWorld(&inertias[bodyA->m_originalBodyIndex])*torqueAxis0 : b3MakeVector3(0,0,0);
- b3Vector3 torqueAxis1 = rel_pos2.cross(cp.m_normalWorldOnB);
- solverConstraint.m_angularComponentB = rb1 ? getInvInertiaTensorWorld(&inertias[bodyB->m_originalBodyIndex])*-torqueAxis1 : b3MakeVector3(0,0,0);
+ b3Vector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB);
+ solverConstraint.m_angularComponentA = rb0 ? getInvInertiaTensorWorld(&inertias[bodyA->m_originalBodyIndex]) * torqueAxis0 : b3MakeVector3(0, 0, 0);
+ b3Vector3 torqueAxis1 = rel_pos2.cross(cp.m_normalWorldOnB);
+ solverConstraint.m_angularComponentB = rb1 ? getInvInertiaTensorWorld(&inertias[bodyB->m_originalBodyIndex]) * -torqueAxis1 : b3MakeVector3(0, 0, 0);
- b3Scalar scaledDenom;
- {
+ b3Scalar scaledDenom;
+ {
#ifdef COMPUTE_IMPULSE_DENOM
- b3Scalar denom0 = rb0->computeImpulseDenominator(pos1,cp.m_normalWorldOnB);
- b3Scalar denom1 = rb1->computeImpulseDenominator(pos2,cp.m_normalWorldOnB);
-#else
- b3Vector3 vec;
- b3Scalar denom0 = 0.f;
- b3Scalar denom1 = 0.f;
- if (rb0)
- {
- vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1);
- denom0 = rb0->m_invMass + cp.m_normalWorldOnB.dot(vec);
- }
- if (rb1)
- {
- vec = ( -solverConstraint.m_angularComponentB).cross(rel_pos2);
- denom1 = rb1->m_invMass + cp.m_normalWorldOnB.dot(vec);
- }
-#endif //COMPUTE_IMPULSE_DENOM
-
-
- b3Scalar denom;
- if (m_usePgs)
- {
- scaledDenom = denom = relaxation/(denom0+denom1);
- } else
- {
- denom = relaxation/(denom0+denom1);
-
- b3Scalar countA = rb0->m_invMass? b3Scalar(m_bodyCount[bodyA->m_originalBodyIndex]) : 1.f;
- b3Scalar countB = rb1->m_invMass? b3Scalar(m_bodyCount[bodyB->m_originalBodyIndex]) : 1.f;
- scaledDenom = relaxation/(denom0*countA+denom1*countB);
- }
- solverConstraint.m_jacDiagABInv = denom;
- }
-
- solverConstraint.m_contactNormal = cp.m_normalWorldOnB;
- solverConstraint.m_relpos1CrossNormal = torqueAxis0;
- solverConstraint.m_relpos2CrossNormal = -torqueAxis1;
-
- b3Scalar restitution = 0.f;
- b3Scalar penetration = cp.getDistance()+infoGlobal.m_linearSlop;
-
- {
- b3Vector3 vel1,vel2;
+ b3Scalar denom0 = rb0->computeImpulseDenominator(pos1, cp.m_normalWorldOnB);
+ b3Scalar denom1 = rb1->computeImpulseDenominator(pos2, cp.m_normalWorldOnB);
+#else
+ b3Vector3 vec;
+ b3Scalar denom0 = 0.f;
+ b3Scalar denom1 = 0.f;
+ if (rb0)
+ {
+ vec = (solverConstraint.m_angularComponentA).cross(rel_pos1);
+ denom0 = rb0->m_invMass + cp.m_normalWorldOnB.dot(vec);
+ }
+ if (rb1)
+ {
+ vec = (-solverConstraint.m_angularComponentB).cross(rel_pos2);
+ denom1 = rb1->m_invMass + cp.m_normalWorldOnB.dot(vec);
+ }
+#endif //COMPUTE_IMPULSE_DENOM
- vel1 = rb0? getVelocityInLocalPoint(rb0,rel_pos1) : b3MakeVector3(0,0,0);
- vel2 = rb1? getVelocityInLocalPoint(rb1, rel_pos2) : b3MakeVector3(0,0,0);
+ b3Scalar denom;
+ if (m_usePgs)
+ {
+ scaledDenom = denom = relaxation / (denom0 + denom1);
+ }
+ else
+ {
+ denom = relaxation / (denom0 + denom1);
- // b3Vector3 vel2 = rb1 ? rb1->getVelocityInLocalPoint(rel_pos2) : b3Vector3(0,0,0);
- vel = vel1 - vel2;
- rel_vel = cp.m_normalWorldOnB.dot(vel);
+ b3Scalar countA = rb0->m_invMass ? b3Scalar(m_bodyCount[bodyA->m_originalBodyIndex]) : 1.f;
+ b3Scalar countB = rb1->m_invMass ? b3Scalar(m_bodyCount[bodyB->m_originalBodyIndex]) : 1.f;
+ scaledDenom = relaxation / (denom0 * countA + denom1 * countB);
+ }
+ solverConstraint.m_jacDiagABInv = denom;
+ }
-
+ solverConstraint.m_contactNormal = cp.m_normalWorldOnB;
+ solverConstraint.m_relpos1CrossNormal = torqueAxis0;
+ solverConstraint.m_relpos2CrossNormal = -torqueAxis1;
- solverConstraint.m_friction = cp.m_combinedFriction;
+ b3Scalar restitution = 0.f;
+ b3Scalar penetration = cp.getDistance() + infoGlobal.m_linearSlop;
-
- restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution);
- if (restitution <= b3Scalar(0.))
- {
- restitution = 0.f;
- };
- }
+ {
+ b3Vector3 vel1, vel2;
+ vel1 = rb0 ? getVelocityInLocalPoint(rb0, rel_pos1) : b3MakeVector3(0, 0, 0);
+ vel2 = rb1 ? getVelocityInLocalPoint(rb1, rel_pos2) : b3MakeVector3(0, 0, 0);
- ///warm starting (or zero if disabled)
- if (infoGlobal.m_solverMode & B3_SOLVER_USE_WARMSTARTING)
- {
- solverConstraint.m_appliedImpulse = cp.m_appliedImpulse * infoGlobal.m_warmstartingFactor;
- if (rb0)
- bodyA->internalApplyImpulse(solverConstraint.m_contactNormal*bodyA->internalGetInvMass(),solverConstraint.m_angularComponentA,solverConstraint.m_appliedImpulse);
- if (rb1)
- bodyB->internalApplyImpulse(solverConstraint.m_contactNormal*bodyB->internalGetInvMass(),-solverConstraint.m_angularComponentB,-(b3Scalar)solverConstraint.m_appliedImpulse);
- } else
- {
- solverConstraint.m_appliedImpulse = 0.f;
- }
+ // b3Vector3 vel2 = rb1 ? rb1->getVelocityInLocalPoint(rel_pos2) : b3Vector3(0,0,0);
+ vel = vel1 - vel2;
+ rel_vel = cp.m_normalWorldOnB.dot(vel);
- solverConstraint.m_appliedPushImpulse = 0.f;
+ solverConstraint.m_friction = cp.m_combinedFriction;
- {
- b3Scalar vel1Dotn = solverConstraint.m_contactNormal.dot(rb0?bodyA->m_linearVelocity:b3MakeVector3(0,0,0))
- + solverConstraint.m_relpos1CrossNormal.dot(rb0?bodyA->m_angularVelocity:b3MakeVector3(0,0,0));
- b3Scalar vel2Dotn = -solverConstraint.m_contactNormal.dot(rb1?bodyB->m_linearVelocity:b3MakeVector3(0,0,0))
- + solverConstraint.m_relpos2CrossNormal.dot(rb1?bodyB->m_angularVelocity:b3MakeVector3(0,0,0));
- b3Scalar rel_vel = vel1Dotn+vel2Dotn;
-
- b3Scalar positionalError = 0.f;
- b3Scalar velocityError = restitution - rel_vel;// * damping;
-
-
- b3Scalar erp = infoGlobal.m_erp2;
- if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
- {
- erp = infoGlobal.m_erp;
- }
+ restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution);
+ if (restitution <= b3Scalar(0.))
+ {
+ restitution = 0.f;
+ };
+ }
- if (penetration>0)
- {
- positionalError = 0;
+ ///warm starting (or zero if disabled)
+ if (infoGlobal.m_solverMode & B3_SOLVER_USE_WARMSTARTING)
+ {
+ solverConstraint.m_appliedImpulse = cp.m_appliedImpulse * infoGlobal.m_warmstartingFactor;
+ if (rb0)
+ bodyA->internalApplyImpulse(solverConstraint.m_contactNormal * bodyA->internalGetInvMass(), solverConstraint.m_angularComponentA, solverConstraint.m_appliedImpulse);
+ if (rb1)
+ bodyB->internalApplyImpulse(solverConstraint.m_contactNormal * bodyB->internalGetInvMass(), -solverConstraint.m_angularComponentB, -(b3Scalar)solverConstraint.m_appliedImpulse);
+ }
+ else
+ {
+ solverConstraint.m_appliedImpulse = 0.f;
+ }
- velocityError -= penetration / infoGlobal.m_timeStep;
- } else
- {
- positionalError = -penetration * erp/infoGlobal.m_timeStep;
- }
+ solverConstraint.m_appliedPushImpulse = 0.f;
- b3Scalar penetrationImpulse = positionalError*scaledDenom;//solverConstraint.m_jacDiagABInv;
- b3Scalar velocityImpulse = velocityError *scaledDenom;//solverConstraint.m_jacDiagABInv;
+ {
+ b3Scalar vel1Dotn = solverConstraint.m_contactNormal.dot(rb0 ? bodyA->m_linearVelocity : b3MakeVector3(0, 0, 0)) + solverConstraint.m_relpos1CrossNormal.dot(rb0 ? bodyA->m_angularVelocity : b3MakeVector3(0, 0, 0));
+ b3Scalar vel2Dotn = -solverConstraint.m_contactNormal.dot(rb1 ? bodyB->m_linearVelocity : b3MakeVector3(0, 0, 0)) + solverConstraint.m_relpos2CrossNormal.dot(rb1 ? bodyB->m_angularVelocity : b3MakeVector3(0, 0, 0));
+ b3Scalar rel_vel = vel1Dotn + vel2Dotn;
- if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
- {
- //combine position and velocity into rhs
- solverConstraint.m_rhs = penetrationImpulse+velocityImpulse;
- solverConstraint.m_rhsPenetration = 0.f;
+ b3Scalar positionalError = 0.f;
+ b3Scalar velocityError = restitution - rel_vel; // * damping;
- } else
- {
- //split position and velocity into rhs and m_rhsPenetration
- solverConstraint.m_rhs = velocityImpulse;
- solverConstraint.m_rhsPenetration = penetrationImpulse;
- }
- solverConstraint.m_cfm = 0.f;
- solverConstraint.m_lowerLimit = 0;
- solverConstraint.m_upperLimit = 1e10f;
- }
+ b3Scalar erp = infoGlobal.m_erp2;
+ if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
+ {
+ erp = infoGlobal.m_erp;
+ }
+ if (penetration > 0)
+ {
+ positionalError = 0;
+ velocityError -= penetration / infoGlobal.m_timeStep;
+ }
+ else
+ {
+ positionalError = -penetration * erp / infoGlobal.m_timeStep;
+ }
+ b3Scalar penetrationImpulse = positionalError * scaledDenom; //solverConstraint.m_jacDiagABInv;
+ b3Scalar velocityImpulse = velocityError * scaledDenom; //solverConstraint.m_jacDiagABInv;
+ if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
+ {
+ //combine position and velocity into rhs
+ solverConstraint.m_rhs = penetrationImpulse + velocityImpulse;
+ solverConstraint.m_rhsPenetration = 0.f;
+ }
+ else
+ {
+ //split position and velocity into rhs and m_rhsPenetration
+ solverConstraint.m_rhs = velocityImpulse;
+ solverConstraint.m_rhsPenetration = penetrationImpulse;
+ }
+ solverConstraint.m_cfm = 0.f;
+ solverConstraint.m_lowerLimit = 0;
+ solverConstraint.m_upperLimit = 1e10f;
+ }
}
-
-
-void b3PgsJacobiSolver::setFrictionConstraintImpulse( b3RigidBodyData* bodies, b3InertiaData* inertias,b3SolverConstraint& solverConstraint,
- int solverBodyIdA, int solverBodyIdB,
- b3ContactPoint& cp, const b3ContactSolverInfo& infoGlobal)
+void b3PgsJacobiSolver::setFrictionConstraintImpulse(b3RigidBodyData* bodies, b3InertiaData* inertias, b3SolverConstraint& solverConstraint,
+ int solverBodyIdA, int solverBodyIdB,
+ b3ContactPoint& cp, const b3ContactSolverInfo& infoGlobal)
{
-
b3SolverBody* bodyA = &m_tmpSolverBodyPool[solverBodyIdA];
b3SolverBody* bodyB = &m_tmpSolverBodyPool[solverBodyIdB];
-
{
b3SolverConstraint& frictionConstraint1 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex];
if (infoGlobal.m_solverMode & B3_SOLVER_USE_WARMSTARTING)
{
frictionConstraint1.m_appliedImpulse = cp.m_appliedImpulseLateral1 * infoGlobal.m_warmstartingFactor;
if (bodies[bodyA->m_originalBodyIndex].m_invMass)
- bodyA->internalApplyImpulse(frictionConstraint1.m_contactNormal*bodies[bodyA->m_originalBodyIndex].m_invMass,frictionConstraint1.m_angularComponentA,frictionConstraint1.m_appliedImpulse);
+ bodyA->internalApplyImpulse(frictionConstraint1.m_contactNormal * bodies[bodyA->m_originalBodyIndex].m_invMass, frictionConstraint1.m_angularComponentA, frictionConstraint1.m_appliedImpulse);
if (bodies[bodyB->m_originalBodyIndex].m_invMass)
- bodyB->internalApplyImpulse(frictionConstraint1.m_contactNormal*bodies[bodyB->m_originalBodyIndex].m_invMass,-frictionConstraint1.m_angularComponentB,-(b3Scalar)frictionConstraint1.m_appliedImpulse);
- } else
+ bodyB->internalApplyImpulse(frictionConstraint1.m_contactNormal * bodies[bodyB->m_originalBodyIndex].m_invMass, -frictionConstraint1.m_angularComponentB, -(b3Scalar)frictionConstraint1.m_appliedImpulse);
+ }
+ else
{
frictionConstraint1.m_appliedImpulse = 0.f;
}
@@ -897,51 +828,45 @@ void b3PgsJacobiSolver::setFrictionConstraintImpulse( b3RigidBodyData* bodies, b
if ((infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS))
{
- b3SolverConstraint& frictionConstraint2 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex+1];
+ b3SolverConstraint& frictionConstraint2 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex + 1];
if (infoGlobal.m_solverMode & B3_SOLVER_USE_WARMSTARTING)
{
- frictionConstraint2.m_appliedImpulse = cp.m_appliedImpulseLateral2 * infoGlobal.m_warmstartingFactor;
+ frictionConstraint2.m_appliedImpulse = cp.m_appliedImpulseLateral2 * infoGlobal.m_warmstartingFactor;
if (bodies[bodyA->m_originalBodyIndex].m_invMass)
- bodyA->internalApplyImpulse(frictionConstraint2.m_contactNormal*bodies[bodyA->m_originalBodyIndex].m_invMass,frictionConstraint2.m_angularComponentA,frictionConstraint2.m_appliedImpulse);
+ bodyA->internalApplyImpulse(frictionConstraint2.m_contactNormal * bodies[bodyA->m_originalBodyIndex].m_invMass, frictionConstraint2.m_angularComponentA, frictionConstraint2.m_appliedImpulse);
if (bodies[bodyB->m_originalBodyIndex].m_invMass)
- bodyB->internalApplyImpulse(frictionConstraint2.m_contactNormal*bodies[bodyB->m_originalBodyIndex].m_invMass,-frictionConstraint2.m_angularComponentB,-(b3Scalar)frictionConstraint2.m_appliedImpulse);
- } else
+ bodyB->internalApplyImpulse(frictionConstraint2.m_contactNormal * bodies[bodyB->m_originalBodyIndex].m_invMass, -frictionConstraint2.m_angularComponentB, -(b3Scalar)frictionConstraint2.m_appliedImpulse);
+ }
+ else
{
frictionConstraint2.m_appliedImpulse = 0.f;
}
}
}
-
-
-
-void b3PgsJacobiSolver::convertContact(b3RigidBodyData* bodies, b3InertiaData* inertias,b3Contact4* manifold,const b3ContactSolverInfo& infoGlobal)
+void b3PgsJacobiSolver::convertContact(b3RigidBodyData* bodies, b3InertiaData* inertias, b3Contact4* manifold, const b3ContactSolverInfo& infoGlobal)
{
- b3RigidBodyData* colObj0=0,*colObj1=0;
+ b3RigidBodyData *colObj0 = 0, *colObj1 = 0;
-
- int solverBodyIdA = getOrInitSolverBody(manifold->getBodyA(),bodies,inertias);
- int solverBodyIdB = getOrInitSolverBody(manifold->getBodyB(),bodies,inertias);
+ int solverBodyIdA = getOrInitSolverBody(manifold->getBodyA(), bodies, inertias);
+ int solverBodyIdB = getOrInitSolverBody(manifold->getBodyB(), bodies, inertias);
-// b3RigidBody* bodyA = b3RigidBody::upcast(colObj0);
-// b3RigidBody* bodyB = b3RigidBody::upcast(colObj1);
+ // b3RigidBody* bodyA = b3RigidBody::upcast(colObj0);
+ // b3RigidBody* bodyB = b3RigidBody::upcast(colObj1);
b3SolverBody* solverBodyA = &m_tmpSolverBodyPool[solverBodyIdA];
b3SolverBody* solverBodyB = &m_tmpSolverBodyPool[solverBodyIdB];
-
-
///avoid collision response between two static objects
if (solverBodyA->m_invMass.isZero() && solverBodyB->m_invMass.isZero())
return;
- int rollingFriction=1;
+ int rollingFriction = 1;
int numContacts = getNumContacts(manifold);
- for (int j=0;j<numContacts;j++)
+ for (int j = 0; j < numContacts; j++)
{
-
b3ContactPoint cp;
- getContactPoint(manifold,j,cp);
+ getContactPoint(manifold, j, cp);
if (cp.getDistance() <= getContactProcessingThreshold(manifold))
{
@@ -953,61 +878,60 @@ void b3PgsJacobiSolver::convertContact(b3RigidBodyData* bodies, b3InertiaData* i
int frictionIndex = m_tmpSolverContactConstraintPool.size();
b3SolverConstraint& solverConstraint = m_tmpSolverContactConstraintPool.expandNonInitializing();
-// b3RigidBody* rb0 = b3RigidBody::upcast(colObj0);
-// b3RigidBody* rb1 = b3RigidBody::upcast(colObj1);
+ // b3RigidBody* rb0 = b3RigidBody::upcast(colObj0);
+ // b3RigidBody* rb1 = b3RigidBody::upcast(colObj1);
solverConstraint.m_solverBodyIdA = solverBodyIdA;
solverConstraint.m_solverBodyIdB = solverBodyIdB;
solverConstraint.m_originalContactPoint = &cp;
- setupContactConstraint(bodies,inertias,solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal, vel, rel_vel, relaxation, rel_pos1, rel_pos2);
+ setupContactConstraint(bodies, inertias, solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal, vel, rel_vel, relaxation, rel_pos1, rel_pos2);
-// const b3Vector3& pos1 = cp.getPositionWorldOnA();
-// const b3Vector3& pos2 = cp.getPositionWorldOnB();
+ // const b3Vector3& pos1 = cp.getPositionWorldOnA();
+ // const b3Vector3& pos2 = cp.getPositionWorldOnB();
/////setup the friction constraints
solverConstraint.m_frictionIndex = m_tmpSolverContactFrictionConstraintPool.size();
- b3Vector3 angVelA,angVelB;
+ b3Vector3 angVelA, angVelB;
solverBodyA->getAngularVelocity(angVelA);
- solverBodyB->getAngularVelocity(angVelB);
- b3Vector3 relAngVel = angVelB-angVelA;
+ solverBodyB->getAngularVelocity(angVelB);
+ b3Vector3 relAngVel = angVelB - angVelA;
- if ((cp.m_combinedRollingFriction>0.f) && (rollingFriction>0))
+ if ((cp.m_combinedRollingFriction > 0.f) && (rollingFriction > 0))
{
//only a single rollingFriction per manifold
rollingFriction--;
- if (relAngVel.length()>infoGlobal.m_singleAxisRollingFrictionThreshold)
+ if (relAngVel.length() > infoGlobal.m_singleAxisRollingFrictionThreshold)
{
relAngVel.normalize();
- if (relAngVel.length()>0.001)
- addRollingFrictionConstraint(bodies,inertias,relAngVel,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
-
- } else
+ if (relAngVel.length() > 0.001)
+ addRollingFrictionConstraint(bodies, inertias, relAngVel, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
+ }
+ else
{
- addRollingFrictionConstraint(bodies,inertias,cp.m_normalWorldOnB,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
- b3Vector3 axis0,axis1;
- b3PlaneSpace1(cp.m_normalWorldOnB,axis0,axis1);
- if (axis0.length()>0.001)
- addRollingFrictionConstraint(bodies,inertias,axis0,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
- if (axis1.length()>0.001)
- addRollingFrictionConstraint(bodies,inertias,axis1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
-
+ addRollingFrictionConstraint(bodies, inertias, cp.m_normalWorldOnB, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
+ b3Vector3 axis0, axis1;
+ b3PlaneSpace1(cp.m_normalWorldOnB, axis0, axis1);
+ if (axis0.length() > 0.001)
+ addRollingFrictionConstraint(bodies, inertias, axis0, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
+ if (axis1.length() > 0.001)
+ addRollingFrictionConstraint(bodies, inertias, axis1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
}
}
///Bullet has several options to set the friction directions
- ///By default, each contact has only a single friction direction that is recomputed automatically very frame
+ ///By default, each contact has only a single friction direction that is recomputed automatically very frame
///based on the relative linear velocity.
///If the relative velocity it zero, it will automatically compute a friction direction.
-
+
///You can also enable two friction directions, using the B3_SOLVER_USE_2_FRICTION_DIRECTIONS.
///In that case, the second friction direction will be orthogonal to both contact normal and first friction direction.
///
///If you choose B3_SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION, then the friction will be independent from the relative projected velocity.
///
- ///The user can manually override the friction directions for certain contacts using a contact callback,
+ ///The user can manually override the friction directions for certain contacts using a contact callback,
///and set the cp.m_lateralFrictionInitialized to true
///In that case, you can set the target relative motion in each friction direction (cp.m_contactMotion1 and cp.m_contactMotion2)
///this will give a conveyor belt effect
@@ -1018,99 +942,91 @@ void b3PgsJacobiSolver::convertContact(b3RigidBodyData* bodies, b3InertiaData* i
b3Scalar lat_rel_vel = cp.m_lateralFrictionDir1.length2();
if (!(infoGlobal.m_solverMode & B3_SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION) && lat_rel_vel > B3_EPSILON)
{
- cp.m_lateralFrictionDir1 *= 1.f/b3Sqrt(lat_rel_vel);
- if((infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS))
+ cp.m_lateralFrictionDir1 *= 1.f / b3Sqrt(lat_rel_vel);
+ if ((infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS))
{
cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross(cp.m_normalWorldOnB);
- cp.m_lateralFrictionDir2.normalize();//??
- addFrictionConstraint(bodies,inertias,cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
-
+ cp.m_lateralFrictionDir2.normalize(); //??
+ addFrictionConstraint(bodies, inertias, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
}
- addFrictionConstraint(bodies,inertias,cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
-
- } else
+ addFrictionConstraint(bodies, inertias, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
+ }
+ else
{
- b3PlaneSpace1(cp.m_normalWorldOnB,cp.m_lateralFrictionDir1,cp.m_lateralFrictionDir2);
+ b3PlaneSpace1(cp.m_normalWorldOnB, cp.m_lateralFrictionDir1, cp.m_lateralFrictionDir2);
if ((infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS))
{
- addFrictionConstraint(bodies,inertias,cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
+ addFrictionConstraint(bodies, inertias, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
}
- addFrictionConstraint(bodies,inertias,cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
+ addFrictionConstraint(bodies, inertias, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
if ((infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & B3_SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION))
{
cp.m_lateralFrictionInitialized = true;
}
}
-
- } else
+ }
+ else
{
- addFrictionConstraint(bodies,inertias,cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation,cp.m_contactMotion1, cp.m_contactCFM1);
+ addFrictionConstraint(bodies, inertias, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, cp.m_contactMotion1, cp.m_contactCFM1);
if ((infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS))
- addFrictionConstraint(bodies,inertias,cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation, cp.m_contactMotion2, cp.m_contactCFM2);
+ addFrictionConstraint(bodies, inertias, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, cp.m_contactMotion2, cp.m_contactCFM2);
- setFrictionConstraintImpulse( bodies,inertias,solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal);
+ setFrictionConstraintImpulse(bodies, inertias, solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal);
}
-
-
-
-
}
}
}
-b3Scalar b3PgsJacobiSolver::solveGroupCacheFriendlySetup(b3RigidBodyData* bodies, b3InertiaData* inertias, int numBodies, b3Contact4* manifoldPtr, int numManifolds,b3TypedConstraint** constraints,int numConstraints,const b3ContactSolverInfo& infoGlobal)
+b3Scalar b3PgsJacobiSolver::solveGroupCacheFriendlySetup(b3RigidBodyData* bodies, b3InertiaData* inertias, int numBodies, b3Contact4* manifoldPtr, int numManifolds, b3TypedConstraint** constraints, int numConstraints, const b3ContactSolverInfo& infoGlobal)
{
B3_PROFILE("solveGroupCacheFriendlySetup");
-
m_maxOverrideNumSolverIterations = 0;
-
-
m_tmpSolverBodyPool.resize(0);
-
-
+
m_bodyCount.resize(0);
- m_bodyCount.resize(numBodies,0);
+ m_bodyCount.resize(numBodies, 0);
m_bodyCountCheck.resize(0);
- m_bodyCountCheck.resize(numBodies,0);
-
+ m_bodyCountCheck.resize(numBodies, 0);
+
m_deltaLinearVelocities.resize(0);
- m_deltaLinearVelocities.resize(numBodies,b3MakeVector3(0,0,0));
+ m_deltaLinearVelocities.resize(numBodies, b3MakeVector3(0, 0, 0));
m_deltaAngularVelocities.resize(0);
- m_deltaAngularVelocities.resize(numBodies,b3MakeVector3(0,0,0));
-
+ m_deltaAngularVelocities.resize(numBodies, b3MakeVector3(0, 0, 0));
+
//int totalBodies = 0;
- for (int i=0;i<numConstraints;i++)
+ for (int i = 0; i < numConstraints; i++)
{
int bodyIndexA = constraints[i]->getRigidBodyA();
int bodyIndexB = constraints[i]->getRigidBodyB();
if (m_usePgs)
{
- m_bodyCount[bodyIndexA]=-1;
- m_bodyCount[bodyIndexB]=-1;
- } else
+ m_bodyCount[bodyIndexA] = -1;
+ m_bodyCount[bodyIndexB] = -1;
+ }
+ else
{
//didn't implement joints with Jacobi version yet
b3Assert(0);
}
-
}
- for (int i=0;i<numManifolds;i++)
+ for (int i = 0; i < numManifolds; i++)
{
int bodyIndexA = manifoldPtr[i].getBodyA();
int bodyIndexB = manifoldPtr[i].getBodyB();
if (m_usePgs)
{
- m_bodyCount[bodyIndexA]=-1;
- m_bodyCount[bodyIndexB]=-1;
- } else
+ m_bodyCount[bodyIndexA] = -1;
+ m_bodyCount[bodyIndexB] = -1;
+ }
+ else
{
if (bodies[bodyIndexA].m_invMass)
{
@@ -1118,26 +1034,23 @@ b3Scalar b3PgsJacobiSolver::solveGroupCacheFriendlySetup(b3RigidBodyData* bodies
m_bodyCount[bodyIndexA]++;
}
else
- m_bodyCount[bodyIndexA]=-1;
+ m_bodyCount[bodyIndexA] = -1;
if (bodies[bodyIndexB].m_invMass)
- // m_bodyCount[bodyIndexB]+=manifoldPtr[i].getNPoints();
+ // m_bodyCount[bodyIndexB]+=manifoldPtr[i].getNPoints();
m_bodyCount[bodyIndexB]++;
else
- m_bodyCount[bodyIndexB]=-1;
+ m_bodyCount[bodyIndexB] = -1;
}
-
}
-
-
if (1)
{
int j;
- for (j=0;j<numConstraints;j++)
+ for (j = 0; j < numConstraints; j++)
{
b3TypedConstraint* constraint = constraints[j];
-
+
constraint->internalSetAppliedImpulse(0.0f);
}
}
@@ -1146,13 +1059,12 @@ b3Scalar b3PgsJacobiSolver::solveGroupCacheFriendlySetup(b3RigidBodyData* bodies
//if (1)
{
{
-
int totalNumRows = 0;
int i;
-
+
m_tmpConstraintSizesPool.resizeNoInitialize(numConstraints);
//calculate the total number of contraint rows
- for (i=0;i<numConstraints;i++)
+ for (i = 0; i < numConstraints; i++)
{
b3TypedConstraint::b3ConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
b3JointFeedback* fb = constraints[i]->getJointFeedback();
@@ -1169,8 +1081,9 @@ b3Scalar b3PgsJacobiSolver::solveGroupCacheFriendlySetup(b3RigidBodyData* bodies
}
if (constraints[i]->isEnabled())
{
- constraints[i]->getInfo1(&info1,bodies);
- } else
+ constraints[i]->getInfo1(&info1, bodies);
+ }
+ else
{
info1.m_numConstraintRows = 0;
info1.nub = 0;
@@ -1179,45 +1092,40 @@ b3Scalar b3PgsJacobiSolver::solveGroupCacheFriendlySetup(b3RigidBodyData* bodies
}
m_tmpSolverNonContactConstraintPool.resizeNoInitialize(totalNumRows);
-
#ifndef DISABLE_JOINTS
///setup the b3SolverConstraints
int currentRow = 0;
- for (i=0;i<numConstraints;i++)
+ for (i = 0; i < numConstraints; i++)
{
const b3TypedConstraint::b3ConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
-
+
if (info1.m_numConstraintRows)
{
- b3Assert(currentRow<totalNumRows);
+ b3Assert(currentRow < totalNumRows);
b3SolverConstraint* currentConstraintRow = &m_tmpSolverNonContactConstraintPool[currentRow];
b3TypedConstraint* constraint = constraints[i];
- b3RigidBodyData& rbA = bodies[ constraint->getRigidBodyA()];
+ b3RigidBodyData& rbA = bodies[constraint->getRigidBodyA()];
//b3RigidBody& rbA = constraint->getRigidBodyA();
- // b3RigidBody& rbB = constraint->getRigidBodyB();
- b3RigidBodyData& rbB = bodies[ constraint->getRigidBodyB()];
-
- int solverBodyIdA = getOrInitSolverBody(constraint->getRigidBodyA(),bodies,inertias);
- int solverBodyIdB = getOrInitSolverBody(constraint->getRigidBodyB(),bodies,inertias);
-
- b3SolverBody* bodyAPtr = &m_tmpSolverBodyPool[solverBodyIdA];
- b3SolverBody* bodyBPtr = &m_tmpSolverBodyPool[solverBodyIdB];
-
+ // b3RigidBody& rbB = constraint->getRigidBodyB();
+ b3RigidBodyData& rbB = bodies[constraint->getRigidBodyB()];
+ int solverBodyIdA = getOrInitSolverBody(constraint->getRigidBodyA(), bodies, inertias);
+ int solverBodyIdB = getOrInitSolverBody(constraint->getRigidBodyB(), bodies, inertias);
+ b3SolverBody* bodyAPtr = &m_tmpSolverBodyPool[solverBodyIdA];
+ b3SolverBody* bodyBPtr = &m_tmpSolverBodyPool[solverBodyIdB];
int overrideNumSolverIterations = constraint->getOverrideNumSolverIterations() > 0 ? constraint->getOverrideNumSolverIterations() : infoGlobal.m_numIterations;
- if (overrideNumSolverIterations>m_maxOverrideNumSolverIterations)
+ if (overrideNumSolverIterations > m_maxOverrideNumSolverIterations)
m_maxOverrideNumSolverIterations = overrideNumSolverIterations;
-
int j;
- for ( j=0;j<info1.m_numConstraintRows;j++)
+ for (j = 0; j < info1.m_numConstraintRows; j++)
{
- memset(&currentConstraintRow[j],0,sizeof(b3SolverConstraint));
+ memset(&currentConstraintRow[j], 0, sizeof(b3SolverConstraint));
currentConstraintRow[j].m_lowerLimit = -B3_INFINITY;
currentConstraintRow[j].m_upperLimit = B3_INFINITY;
currentConstraintRow[j].m_appliedImpulse = 0.f;
@@ -1227,26 +1135,25 @@ b3Scalar b3PgsJacobiSolver::solveGroupCacheFriendlySetup(b3RigidBodyData* bodies
currentConstraintRow[j].m_overrideNumSolverIterations = overrideNumSolverIterations;
}
- bodyAPtr->internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
- bodyAPtr->internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f);
- bodyAPtr->internalGetPushVelocity().setValue(0.f,0.f,0.f);
- bodyAPtr->internalGetTurnVelocity().setValue(0.f,0.f,0.f);
- bodyBPtr->internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
- bodyBPtr->internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f);
- bodyBPtr->internalGetPushVelocity().setValue(0.f,0.f,0.f);
- bodyBPtr->internalGetTurnVelocity().setValue(0.f,0.f,0.f);
-
+ bodyAPtr->internalGetDeltaLinearVelocity().setValue(0.f, 0.f, 0.f);
+ bodyAPtr->internalGetDeltaAngularVelocity().setValue(0.f, 0.f, 0.f);
+ bodyAPtr->internalGetPushVelocity().setValue(0.f, 0.f, 0.f);
+ bodyAPtr->internalGetTurnVelocity().setValue(0.f, 0.f, 0.f);
+ bodyBPtr->internalGetDeltaLinearVelocity().setValue(0.f, 0.f, 0.f);
+ bodyBPtr->internalGetDeltaAngularVelocity().setValue(0.f, 0.f, 0.f);
+ bodyBPtr->internalGetPushVelocity().setValue(0.f, 0.f, 0.f);
+ bodyBPtr->internalGetTurnVelocity().setValue(0.f, 0.f, 0.f);
b3TypedConstraint::b3ConstraintInfo2 info2;
- info2.fps = 1.f/infoGlobal.m_timeStep;
+ info2.fps = 1.f / infoGlobal.m_timeStep;
info2.erp = infoGlobal.m_erp;
info2.m_J1linearAxis = currentConstraintRow->m_contactNormal;
info2.m_J1angularAxis = currentConstraintRow->m_relpos1CrossNormal;
info2.m_J2linearAxis = 0;
info2.m_J2angularAxis = currentConstraintRow->m_relpos2CrossNormal;
- info2.rowskip = sizeof(b3SolverConstraint)/sizeof(b3Scalar);//check this
- ///the size of b3SolverConstraint needs be a multiple of b3Scalar
- b3Assert(info2.rowskip*sizeof(b3Scalar)== sizeof(b3SolverConstraint));
+ info2.rowskip = sizeof(b3SolverConstraint) / sizeof(b3Scalar); //check this
+ ///the size of b3SolverConstraint needs be a multiple of b3Scalar
+ b3Assert(info2.rowskip * sizeof(b3Scalar) == sizeof(b3SolverConstraint));
info2.m_constraintError = &currentConstraintRow->m_rhs;
currentConstraintRow->m_cfm = infoGlobal.m_globalCfm;
info2.m_damping = infoGlobal.m_damping;
@@ -1254,47 +1161,45 @@ b3Scalar b3PgsJacobiSolver::solveGroupCacheFriendlySetup(b3RigidBodyData* bodies
info2.m_lowerLimit = &currentConstraintRow->m_lowerLimit;
info2.m_upperLimit = &currentConstraintRow->m_upperLimit;
info2.m_numIterations = infoGlobal.m_numIterations;
- constraints[i]->getInfo2(&info2,bodies);
+ constraints[i]->getInfo2(&info2, bodies);
///finalize the constraint setup
- for ( j=0;j<info1.m_numConstraintRows;j++)
+ for (j = 0; j < info1.m_numConstraintRows; j++)
{
b3SolverConstraint& solverConstraint = currentConstraintRow[j];
- if (solverConstraint.m_upperLimit>=constraints[i]->getBreakingImpulseThreshold())
+ if (solverConstraint.m_upperLimit >= constraints[i]->getBreakingImpulseThreshold())
{
solverConstraint.m_upperLimit = constraints[i]->getBreakingImpulseThreshold();
}
- if (solverConstraint.m_lowerLimit<=-constraints[i]->getBreakingImpulseThreshold())
+ if (solverConstraint.m_lowerLimit <= -constraints[i]->getBreakingImpulseThreshold())
{
solverConstraint.m_lowerLimit = -constraints[i]->getBreakingImpulseThreshold();
}
solverConstraint.m_originalContactPoint = constraint;
-
- b3Matrix3x3& invInertiaWorldA= inertias[constraint->getRigidBodyA()].m_invInertiaWorld;
- {
+ b3Matrix3x3& invInertiaWorldA = inertias[constraint->getRigidBodyA()].m_invInertiaWorld;
+ {
//b3Vector3 angularFactorA(1,1,1);
const b3Vector3& ftorqueAxis1 = solverConstraint.m_relpos1CrossNormal;
- solverConstraint.m_angularComponentA = invInertiaWorldA*ftorqueAxis1;//*angularFactorA;
+ solverConstraint.m_angularComponentA = invInertiaWorldA * ftorqueAxis1; //*angularFactorA;
}
-
- b3Matrix3x3& invInertiaWorldB= inertias[constraint->getRigidBodyB()].m_invInertiaWorld;
- {
+ b3Matrix3x3& invInertiaWorldB = inertias[constraint->getRigidBodyB()].m_invInertiaWorld;
+ {
const b3Vector3& ftorqueAxis2 = solverConstraint.m_relpos2CrossNormal;
- solverConstraint.m_angularComponentB = invInertiaWorldB*ftorqueAxis2;//*constraint->getRigidBodyB().getAngularFactor();
+ solverConstraint.m_angularComponentB = invInertiaWorldB * ftorqueAxis2; //*constraint->getRigidBodyB().getAngularFactor();
}
{
//it is ok to use solverConstraint.m_contactNormal instead of -solverConstraint.m_contactNormal
//because it gets multiplied iMJlB
- b3Vector3 iMJlA = solverConstraint.m_contactNormal*rbA.m_invMass;
- b3Vector3 iMJaA = invInertiaWorldA*solverConstraint.m_relpos1CrossNormal;
- b3Vector3 iMJlB = solverConstraint.m_contactNormal*rbB.m_invMass;//sign of normal?
- b3Vector3 iMJaB = invInertiaWorldB*solverConstraint.m_relpos2CrossNormal;
+ b3Vector3 iMJlA = solverConstraint.m_contactNormal * rbA.m_invMass;
+ b3Vector3 iMJaA = invInertiaWorldA * solverConstraint.m_relpos1CrossNormal;
+ b3Vector3 iMJlB = solverConstraint.m_contactNormal * rbB.m_invMass; //sign of normal?
+ b3Vector3 iMJaB = invInertiaWorldB * solverConstraint.m_relpos2CrossNormal;
b3Scalar sum = iMJlA.dot(solverConstraint.m_contactNormal);
sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
@@ -1302,10 +1207,9 @@ b3Scalar b3PgsJacobiSolver::solveGroupCacheFriendlySetup(b3RigidBodyData* bodies
sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
b3Scalar fsum = b3Fabs(sum);
b3Assert(fsum > B3_EPSILON);
- solverConstraint.m_jacDiagABInv = fsum>B3_EPSILON?b3Scalar(1.)/sum : 0.f;
+ solverConstraint.m_jacDiagABInv = fsum > B3_EPSILON ? b3Scalar(1.) / sum : 0.f;
}
-
///fix rhs
///todo: add force/torque accelerators
{
@@ -1313,38 +1217,35 @@ b3Scalar b3PgsJacobiSolver::solveGroupCacheFriendlySetup(b3RigidBodyData* bodies
b3Scalar vel1Dotn = solverConstraint.m_contactNormal.dot(rbA.m_linVel) + solverConstraint.m_relpos1CrossNormal.dot(rbA.m_angVel);
b3Scalar vel2Dotn = -solverConstraint.m_contactNormal.dot(rbB.m_linVel) + solverConstraint.m_relpos2CrossNormal.dot(rbB.m_angVel);
- rel_vel = vel1Dotn+vel2Dotn;
+ rel_vel = vel1Dotn + vel2Dotn;
b3Scalar restitution = 0.f;
- b3Scalar positionalError = solverConstraint.m_rhs;//already filled in by getConstraintInfo2
- b3Scalar velocityError = restitution - rel_vel * info2.m_damping;
- b3Scalar penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv;
- b3Scalar velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv;
- solverConstraint.m_rhs = penetrationImpulse+velocityImpulse;
+ b3Scalar positionalError = solverConstraint.m_rhs; //already filled in by getConstraintInfo2
+ b3Scalar velocityError = restitution - rel_vel * info2.m_damping;
+ b3Scalar penetrationImpulse = positionalError * solverConstraint.m_jacDiagABInv;
+ b3Scalar velocityImpulse = velocityError * solverConstraint.m_jacDiagABInv;
+ solverConstraint.m_rhs = penetrationImpulse + velocityImpulse;
solverConstraint.m_appliedImpulse = 0.f;
-
}
}
}
- currentRow+=m_tmpConstraintSizesPool[i].m_numConstraintRows;
+ currentRow += m_tmpConstraintSizesPool[i].m_numConstraintRows;
}
-#endif //DISABLE_JOINTS
+#endif //DISABLE_JOINTS
}
-
{
int i;
- for (i=0;i<numManifolds;i++)
+ for (i = 0; i < numManifolds; i++)
{
b3Contact4& manifold = manifoldPtr[i];
- convertContact(bodies,inertias,&manifold,infoGlobal);
+ convertContact(bodies, inertias, &manifold, infoGlobal);
}
}
}
-// b3ContactSolverInfo info = infoGlobal;
-
+ // b3ContactSolverInfo info = infoGlobal;
int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
int numConstraintPool = m_tmpSolverContactConstraintPool.size();
@@ -1353,64 +1254,63 @@ b3Scalar b3PgsJacobiSolver::solveGroupCacheFriendlySetup(b3RigidBodyData* bodies
///@todo: use stack allocator for such temporarily memory, same for solver bodies/constraints
m_orderNonContactConstraintPool.resizeNoInitialize(numNonContactPool);
if ((infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS))
- m_orderTmpConstraintPool.resizeNoInitialize(numConstraintPool*2);
+ m_orderTmpConstraintPool.resizeNoInitialize(numConstraintPool * 2);
else
m_orderTmpConstraintPool.resizeNoInitialize(numConstraintPool);
m_orderFrictionConstraintPool.resizeNoInitialize(numFrictionPool);
{
int i;
- for (i=0;i<numNonContactPool;i++)
+ for (i = 0; i < numNonContactPool; i++)
{
m_orderNonContactConstraintPool[i] = i;
}
- for (i=0;i<numConstraintPool;i++)
+ for (i = 0; i < numConstraintPool; i++)
{
m_orderTmpConstraintPool[i] = i;
}
- for (i=0;i<numFrictionPool;i++)
+ for (i = 0; i < numFrictionPool; i++)
{
m_orderFrictionConstraintPool[i] = i;
}
}
return 0.f;
-
}
-
-b3Scalar b3PgsJacobiSolver::solveSingleIteration(int iteration,b3TypedConstraint** constraints,int numConstraints,const b3ContactSolverInfo& infoGlobal)
+b3Scalar b3PgsJacobiSolver::solveSingleIteration(int iteration, b3TypedConstraint** constraints, int numConstraints, const b3ContactSolverInfo& infoGlobal)
{
-
int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
int numConstraintPool = m_tmpSolverContactConstraintPool.size();
int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size();
-
+
if (infoGlobal.m_solverMode & B3_SOLVER_RANDMIZE_ORDER)
{
- if (1) // uncomment this for a bit less random ((iteration & 7) == 0)
+ if (1) // uncomment this for a bit less random ((iteration & 7) == 0)
{
-
- for (int j=0; j<numNonContactPool; ++j) {
+ for (int j = 0; j < numNonContactPool; ++j)
+ {
int tmp = m_orderNonContactConstraintPool[j];
- int swapi = b3RandInt2(j+1);
+ int swapi = b3RandInt2(j + 1);
m_orderNonContactConstraintPool[j] = m_orderNonContactConstraintPool[swapi];
m_orderNonContactConstraintPool[swapi] = tmp;
}
- //contact/friction constraints are not solved more than
- if (iteration< infoGlobal.m_numIterations)
+ //contact/friction constraints are not solved more than
+ if (iteration < infoGlobal.m_numIterations)
{
- for (int j=0; j<numConstraintPool; ++j) {
+ for (int j = 0; j < numConstraintPool; ++j)
+ {
int tmp = m_orderTmpConstraintPool[j];
- int swapi = b3RandInt2(j+1);
+ int swapi = b3RandInt2(j + 1);
m_orderTmpConstraintPool[j] = m_orderTmpConstraintPool[swapi];
m_orderTmpConstraintPool[swapi] = tmp;
}
- for (int j=0; j<numFrictionPool; ++j) {
+ for (int j = 0; j < numFrictionPool; ++j)
+ {
int tmp = m_orderFrictionConstraintPool[j];
- int swapi = b3RandInt2(j+1);
+ int swapi = b3RandInt2(j + 1);
m_orderFrictionConstraintPool[j] = m_orderFrictionConstraintPool[swapi];
m_orderFrictionConstraintPool[swapi] = tmp;
}
@@ -1421,173 +1321,163 @@ b3Scalar b3PgsJacobiSolver::solveSingleIteration(int iteration,b3TypedConstraint
if (infoGlobal.m_solverMode & B3_SOLVER_SIMD)
{
///solve all joint constraints, using SIMD, if available
- for (int j=0;j<m_tmpSolverNonContactConstraintPool.size();j++)
+ for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++)
{
b3SolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
if (iteration < constraint.m_overrideNumSolverIterations)
- resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[constraint.m_solverBodyIdA],m_tmpSolverBodyPool[constraint.m_solverBodyIdB],constraint);
+ resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[constraint.m_solverBodyIdA], m_tmpSolverBodyPool[constraint.m_solverBodyIdB], constraint);
}
- if (iteration< infoGlobal.m_numIterations)
+ if (iteration < infoGlobal.m_numIterations)
{
-
///solve all contact constraints using SIMD, if available
if (infoGlobal.m_solverMode & B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS)
{
int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
- int multiplier = (infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS)? 2 : 1;
+ int multiplier = (infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS) ? 2 : 1;
- for (int c=0;c<numPoolConstraints;c++)
+ for (int c = 0; c < numPoolConstraints; c++)
{
- b3Scalar totalImpulse =0;
+ b3Scalar totalImpulse = 0;
{
const b3SolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[c]];
- resolveSingleConstraintRowLowerLimitSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
+ resolveSingleConstraintRowLowerLimitSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
totalImpulse = solveManifold.m_appliedImpulse;
}
bool applyFriction = true;
if (applyFriction)
{
{
+ b3SolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c * multiplier]];
- b3SolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c*multiplier]];
-
- if (totalImpulse>b3Scalar(0))
+ if (totalImpulse > b3Scalar(0))
{
- solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
- solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
+ solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
+ solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
- resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
+ resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
}
}
if (infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS)
{
+ b3SolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c * multiplier + 1]];
- b3SolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c*multiplier+1]];
-
- if (totalImpulse>b3Scalar(0))
+ if (totalImpulse > b3Scalar(0))
{
- solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
- solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
+ solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
+ solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
- resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
+ resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
}
}
}
}
-
}
- else//B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS
+ else //B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS
{
//solve the friction constraints after all contact constraints, don't interleave them
int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
int j;
- for (j=0;j<numPoolConstraints;j++)
+ for (j = 0; j < numPoolConstraints; j++)
{
const b3SolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
- resolveSingleConstraintRowLowerLimitSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
-
+ resolveSingleConstraintRowLowerLimitSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
}
if (!m_usePgs)
averageVelocities();
-
///solve all friction constraints, using SIMD, if available
int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size();
- for (j=0;j<numFrictionPoolConstraints;j++)
+ for (j = 0; j < numFrictionPoolConstraints; j++)
{
b3SolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]];
b3Scalar totalImpulse = m_tmpSolverContactConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
- if (totalImpulse>b3Scalar(0))
+ if (totalImpulse > b3Scalar(0))
{
- solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
- solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
+ solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
+ solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
- resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
+ resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
}
}
-
int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size();
- for (j=0;j<numRollingFrictionPoolConstraints;j++)
+ for (j = 0; j < numRollingFrictionPoolConstraints; j++)
{
-
b3SolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
b3Scalar totalImpulse = m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse;
- if (totalImpulse>b3Scalar(0))
+ if (totalImpulse > b3Scalar(0))
{
- b3Scalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction*totalImpulse;
- if (rollingFrictionMagnitude>rollingFrictionConstraint.m_friction)
+ b3Scalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse;
+ if (rollingFrictionMagnitude > rollingFrictionConstraint.m_friction)
rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
- resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA],m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB],rollingFrictionConstraint);
+ resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint);
}
}
-
-
- }
+ }
}
- } else
+ }
+ else
{
//non-SIMD version
///solve all joint constraints
- for (int j=0;j<m_tmpSolverNonContactConstraintPool.size();j++)
+ for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++)
{
b3SolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
if (iteration < constraint.m_overrideNumSolverIterations)
- resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[constraint.m_solverBodyIdA],m_tmpSolverBodyPool[constraint.m_solverBodyIdB],constraint);
+ resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[constraint.m_solverBodyIdA], m_tmpSolverBodyPool[constraint.m_solverBodyIdB], constraint);
}
- if (iteration< infoGlobal.m_numIterations)
+ if (iteration < infoGlobal.m_numIterations)
{
-
///solve all contact constraints
int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
- for (int j=0;j<numPoolConstraints;j++)
+ for (int j = 0; j < numPoolConstraints; j++)
{
const b3SolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
- resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
+ resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
}
///solve all friction constraints
int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size();
- for (int j=0;j<numFrictionPoolConstraints;j++)
+ for (int j = 0; j < numFrictionPoolConstraints; j++)
{
b3SolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]];
b3Scalar totalImpulse = m_tmpSolverContactConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
- if (totalImpulse>b3Scalar(0))
+ if (totalImpulse > b3Scalar(0))
{
- solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
- solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
+ solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
+ solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
- resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
+ resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
}
}
int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size();
- for (int j=0;j<numRollingFrictionPoolConstraints;j++)
+ for (int j = 0; j < numRollingFrictionPoolConstraints; j++)
{
b3SolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
b3Scalar totalImpulse = m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse;
- if (totalImpulse>b3Scalar(0))
+ if (totalImpulse > b3Scalar(0))
{
- b3Scalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction*totalImpulse;
- if (rollingFrictionMagnitude>rollingFrictionConstraint.m_friction)
+ b3Scalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse;
+ if (rollingFrictionMagnitude > rollingFrictionConstraint.m_friction)
rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
- resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA],m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB],rollingFrictionConstraint);
+ resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint);
}
}
}
@@ -1595,40 +1485,39 @@ b3Scalar b3PgsJacobiSolver::solveSingleIteration(int iteration,b3TypedConstraint
return 0.f;
}
-
-void b3PgsJacobiSolver::solveGroupCacheFriendlySplitImpulseIterations(b3TypedConstraint** constraints,int numConstraints,const b3ContactSolverInfo& infoGlobal)
+void b3PgsJacobiSolver::solveGroupCacheFriendlySplitImpulseIterations(b3TypedConstraint** constraints, int numConstraints, const b3ContactSolverInfo& infoGlobal)
{
int iteration;
if (infoGlobal.m_splitImpulse)
{
if (infoGlobal.m_solverMode & B3_SOLVER_SIMD)
{
- for ( iteration = 0;iteration<infoGlobal.m_numIterations;iteration++)
+ for (iteration = 0; iteration < infoGlobal.m_numIterations; iteration++)
{
{
int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
int j;
- for (j=0;j<numPoolConstraints;j++)
+ for (j = 0; j < numPoolConstraints; j++)
{
const b3SolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
- resolveSplitPenetrationSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
+ resolveSplitPenetrationSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
}
}
}
}
else
{
- for ( iteration = 0;iteration<infoGlobal.m_numIterations;iteration++)
+ for (iteration = 0; iteration < infoGlobal.m_numIterations; iteration++)
{
{
int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
int j;
- for (j=0;j<numPoolConstraints;j++)
+ for (j = 0; j < numPoolConstraints; j++)
{
const b3SolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
- resolveSplitPenetrationImpulseCacheFriendly(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
+ resolveSplitPenetrationImpulseCacheFriendly(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
}
}
}
@@ -1636,100 +1525,95 @@ void b3PgsJacobiSolver::solveGroupCacheFriendlySplitImpulseIterations(b3TypedCon
}
}
-b3Scalar b3PgsJacobiSolver::solveGroupCacheFriendlyIterations(b3TypedConstraint** constraints,int numConstraints,const b3ContactSolverInfo& infoGlobal)
+b3Scalar b3PgsJacobiSolver::solveGroupCacheFriendlyIterations(b3TypedConstraint** constraints, int numConstraints, const b3ContactSolverInfo& infoGlobal)
{
B3_PROFILE("solveGroupCacheFriendlyIterations");
{
///this is a special step to resolve penetrations (just for contacts)
- solveGroupCacheFriendlySplitImpulseIterations(constraints,numConstraints,infoGlobal);
+ solveGroupCacheFriendlySplitImpulseIterations(constraints, numConstraints, infoGlobal);
- int maxIterations = m_maxOverrideNumSolverIterations > infoGlobal.m_numIterations? m_maxOverrideNumSolverIterations : infoGlobal.m_numIterations;
+ int maxIterations = m_maxOverrideNumSolverIterations > infoGlobal.m_numIterations ? m_maxOverrideNumSolverIterations : infoGlobal.m_numIterations;
- for ( int iteration = 0 ; iteration< maxIterations ; iteration++)
+ for (int iteration = 0; iteration < maxIterations; iteration++)
//for ( int iteration = maxIterations-1 ; iteration >= 0;iteration--)
- {
-
- solveSingleIteration(iteration, constraints,numConstraints,infoGlobal);
-
+ {
+ solveSingleIteration(iteration, constraints, numConstraints, infoGlobal);
if (!m_usePgs)
{
averageVelocities();
}
}
-
}
return 0.f;
}
-void b3PgsJacobiSolver::averageVelocities()
+void b3PgsJacobiSolver::averageVelocities()
{
B3_PROFILE("averaging");
//average the velocities
int numBodies = m_bodyCount.size();
m_deltaLinearVelocities.resize(0);
- m_deltaLinearVelocities.resize(numBodies,b3MakeVector3(0,0,0));
+ m_deltaLinearVelocities.resize(numBodies, b3MakeVector3(0, 0, 0));
m_deltaAngularVelocities.resize(0);
- m_deltaAngularVelocities.resize(numBodies,b3MakeVector3(0,0,0));
+ m_deltaAngularVelocities.resize(numBodies, b3MakeVector3(0, 0, 0));
- for (int i=0;i<m_tmpSolverBodyPool.size();i++)
+ for (int i = 0; i < m_tmpSolverBodyPool.size(); i++)
{
if (!m_tmpSolverBodyPool[i].m_invMass.isZero())
{
int orgBodyIndex = m_tmpSolverBodyPool[i].m_originalBodyIndex;
- m_deltaLinearVelocities[orgBodyIndex]+=m_tmpSolverBodyPool[i].getDeltaLinearVelocity();
- m_deltaAngularVelocities[orgBodyIndex]+=m_tmpSolverBodyPool[i].getDeltaAngularVelocity();
+ m_deltaLinearVelocities[orgBodyIndex] += m_tmpSolverBodyPool[i].getDeltaLinearVelocity();
+ m_deltaAngularVelocities[orgBodyIndex] += m_tmpSolverBodyPool[i].getDeltaAngularVelocity();
}
}
-
- for (int i=0;i<m_tmpSolverBodyPool.size();i++)
+
+ for (int i = 0; i < m_tmpSolverBodyPool.size(); i++)
{
int orgBodyIndex = m_tmpSolverBodyPool[i].m_originalBodyIndex;
if (!m_tmpSolverBodyPool[i].m_invMass.isZero())
{
-
b3Assert(m_bodyCount[orgBodyIndex] == m_bodyCountCheck[orgBodyIndex]);
-
- b3Scalar factor = 1.f/b3Scalar(m_bodyCount[orgBodyIndex]);
-
- m_tmpSolverBodyPool[i].m_deltaLinearVelocity = m_deltaLinearVelocities[orgBodyIndex]*factor;
- m_tmpSolverBodyPool[i].m_deltaAngularVelocity = m_deltaAngularVelocities[orgBodyIndex]*factor;
+ b3Scalar factor = 1.f / b3Scalar(m_bodyCount[orgBodyIndex]);
+
+ m_tmpSolverBodyPool[i].m_deltaLinearVelocity = m_deltaLinearVelocities[orgBodyIndex] * factor;
+ m_tmpSolverBodyPool[i].m_deltaAngularVelocity = m_deltaAngularVelocities[orgBodyIndex] * factor;
}
}
}
-b3Scalar b3PgsJacobiSolver::solveGroupCacheFriendlyFinish(b3RigidBodyData* bodies,b3InertiaData* inertias,int numBodies,const b3ContactSolverInfo& infoGlobal)
+b3Scalar b3PgsJacobiSolver::solveGroupCacheFriendlyFinish(b3RigidBodyData* bodies, b3InertiaData* inertias, int numBodies, const b3ContactSolverInfo& infoGlobal)
{
B3_PROFILE("solveGroupCacheFriendlyFinish");
int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
- int i,j;
+ int i, j;
if (infoGlobal.m_solverMode & B3_SOLVER_USE_WARMSTARTING)
{
- for (j=0;j<numPoolConstraints;j++)
+ for (j = 0; j < numPoolConstraints; j++)
{
const b3SolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[j];
- b3ContactPoint* pt = (b3ContactPoint*) solveManifold.m_originalContactPoint;
+ b3ContactPoint* pt = (b3ContactPoint*)solveManifold.m_originalContactPoint;
b3Assert(pt);
pt->m_appliedImpulse = solveManifold.m_appliedImpulse;
- // float f = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
+ // float f = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
// printf("pt->m_appliedImpulseLateral1 = %f\n", f);
pt->m_appliedImpulseLateral1 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
//printf("pt->m_appliedImpulseLateral1 = %f\n", pt->m_appliedImpulseLateral1);
if ((infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS))
{
- pt->m_appliedImpulseLateral2 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex+1].m_appliedImpulse;
+ pt->m_appliedImpulseLateral2 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex + 1].m_appliedImpulse;
}
//do a callback here?
}
}
numPoolConstraints = m_tmpSolverNonContactConstraintPool.size();
- for (j=0;j<numPoolConstraints;j++)
+ for (j = 0; j < numPoolConstraints; j++)
{
const b3SolverConstraint& solverConstr = m_tmpSolverNonContactConstraintPool[j];
b3TypedConstraint* constr = (b3TypedConstraint*)solverConstr.m_originalContactPoint;
@@ -1739,15 +1623,14 @@ b3Scalar b3PgsJacobiSolver::solveGroupCacheFriendlyFinish(b3RigidBodyData* bodie
b3SolverBody* bodyA = &m_tmpSolverBodyPool[solverConstr.m_solverBodyIdA];
b3SolverBody* bodyB = &m_tmpSolverBodyPool[solverConstr.m_solverBodyIdB];
- fb->m_appliedForceBodyA += solverConstr.m_contactNormal*solverConstr.m_appliedImpulse*bodyA->m_linearFactor/infoGlobal.m_timeStep;
- fb->m_appliedForceBodyB += -solverConstr.m_contactNormal*solverConstr.m_appliedImpulse*bodyB->m_linearFactor/infoGlobal.m_timeStep;
- fb->m_appliedTorqueBodyA += solverConstr.m_relpos1CrossNormal* bodyA->m_angularFactor*solverConstr.m_appliedImpulse/infoGlobal.m_timeStep;
- fb->m_appliedTorqueBodyB += -solverConstr.m_relpos1CrossNormal* bodyB->m_angularFactor*solverConstr.m_appliedImpulse/infoGlobal.m_timeStep;
-
+ fb->m_appliedForceBodyA += solverConstr.m_contactNormal * solverConstr.m_appliedImpulse * bodyA->m_linearFactor / infoGlobal.m_timeStep;
+ fb->m_appliedForceBodyB += -solverConstr.m_contactNormal * solverConstr.m_appliedImpulse * bodyB->m_linearFactor / infoGlobal.m_timeStep;
+ fb->m_appliedTorqueBodyA += solverConstr.m_relpos1CrossNormal * bodyA->m_angularFactor * solverConstr.m_appliedImpulse / infoGlobal.m_timeStep;
+ fb->m_appliedTorqueBodyB += -solverConstr.m_relpos1CrossNormal * bodyB->m_angularFactor * solverConstr.m_appliedImpulse / infoGlobal.m_timeStep;
}
constr->internalSetAppliedImpulse(solverConstr.m_appliedImpulse);
- if (b3Fabs(solverConstr.m_appliedImpulse)>=constr->getBreakingImpulseThreshold())
+ if (b3Fabs(solverConstr.m_appliedImpulse) >= constr->getBreakingImpulseThreshold())
{
constr->setEnabled(false);
}
@@ -1755,7 +1638,7 @@ b3Scalar b3PgsJacobiSolver::solveGroupCacheFriendlyFinish(b3RigidBodyData* bodie
{
B3_PROFILE("write back velocities and transforms");
- for ( i=0;i<m_tmpSolverBodyPool.size();i++)
+ for (i = 0; i < m_tmpSolverBodyPool.size(); i++)
{
int bodyIndex = m_tmpSolverBodyPool[i].m_originalBodyIndex;
//b3Assert(i==bodyIndex);
@@ -1772,12 +1655,13 @@ b3Scalar b3PgsJacobiSolver::solveGroupCacheFriendlyFinish(b3RigidBodyData* bodie
{
body->m_linVel = m_tmpSolverBodyPool[i].m_linearVelocity;
body->m_angVel = m_tmpSolverBodyPool[i].m_angularVelocity;
- } else
+ }
+ else
{
- b3Scalar factor = 1.f/b3Scalar(m_bodyCount[bodyIndex]);
+ b3Scalar factor = 1.f / b3Scalar(m_bodyCount[bodyIndex]);
- b3Vector3 deltaLinVel = m_deltaLinearVelocities[bodyIndex]*factor;
- b3Vector3 deltaAngVel = m_deltaAngularVelocities[bodyIndex]*factor;
+ b3Vector3 deltaLinVel = m_deltaLinearVelocities[bodyIndex] * factor;
+ b3Vector3 deltaAngVel = m_deltaAngularVelocities[bodyIndex] * factor;
//printf("body %d\n",bodyIndex);
//printf("deltaLinVel = %f,%f,%f\n",deltaLinVel.getX(),deltaLinVel.getY(),deltaLinVel.getZ());
//printf("deltaAngVel = %f,%f,%f\n",deltaAngVel.getX(),deltaAngVel.getY(),deltaAngVel.getZ());
@@ -1785,7 +1669,7 @@ b3Scalar b3PgsJacobiSolver::solveGroupCacheFriendlyFinish(b3RigidBodyData* bodie
body->m_linVel += deltaLinVel;
body->m_angVel += deltaAngVel;
}
-
+
if (infoGlobal.m_splitImpulse)
{
body->m_pos = m_tmpSolverBodyPool[i].m_worldTransform.getOrigin();
@@ -1797,7 +1681,6 @@ b3Scalar b3PgsJacobiSolver::solveGroupCacheFriendlyFinish(b3RigidBodyData* bodie
}
}
-
m_tmpSolverContactConstraintPool.resizeNoInitialize(0);
m_tmpSolverNonContactConstraintPool.resizeNoInitialize(0);
m_tmpSolverContactFrictionConstraintPool.resizeNoInitialize(0);
@@ -1807,9 +1690,7 @@ b3Scalar b3PgsJacobiSolver::solveGroupCacheFriendlyFinish(b3RigidBodyData* bodie
return 0.f;
}
-
-
-void b3PgsJacobiSolver::reset()
+void b3PgsJacobiSolver::reset()
{
m_btSeed2 = 0;
} \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3PgsJacobiSolver.h b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3PgsJacobiSolver.h
index d2ca307fab..5b616541d9 100644
--- a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3PgsJacobiSolver.h
+++ b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3PgsJacobiSolver.h
@@ -1,11 +1,9 @@
#ifndef B3_PGS_JACOBI_SOLVER
#define B3_PGS_JACOBI_SOLVER
-
struct b3Contact4;
struct b3ContactPoint;
-
class b3Dispatcher;
#include "b3TypedConstraint.h"
@@ -18,132 +16,118 @@ struct b3InertiaData;
class b3PgsJacobiSolver
{
-
protected:
- b3AlignedObjectArray<b3SolverBody> m_tmpSolverBodyPool;
- b3ConstraintArray m_tmpSolverContactConstraintPool;
- b3ConstraintArray m_tmpSolverNonContactConstraintPool;
- b3ConstraintArray m_tmpSolverContactFrictionConstraintPool;
- b3ConstraintArray m_tmpSolverContactRollingFrictionConstraintPool;
-
- b3AlignedObjectArray<int> m_orderTmpConstraintPool;
- b3AlignedObjectArray<int> m_orderNonContactConstraintPool;
- b3AlignedObjectArray<int> m_orderFrictionConstraintPool;
+ b3AlignedObjectArray<b3SolverBody> m_tmpSolverBodyPool;
+ b3ConstraintArray m_tmpSolverContactConstraintPool;
+ b3ConstraintArray m_tmpSolverNonContactConstraintPool;
+ b3ConstraintArray m_tmpSolverContactFrictionConstraintPool;
+ b3ConstraintArray m_tmpSolverContactRollingFrictionConstraintPool;
+
+ b3AlignedObjectArray<int> m_orderTmpConstraintPool;
+ b3AlignedObjectArray<int> m_orderNonContactConstraintPool;
+ b3AlignedObjectArray<int> m_orderFrictionConstraintPool;
b3AlignedObjectArray<b3TypedConstraint::b3ConstraintInfo1> m_tmpConstraintSizesPool;
-
- b3AlignedObjectArray<int> m_bodyCount;
- b3AlignedObjectArray<int> m_bodyCountCheck;
-
- b3AlignedObjectArray<b3Vector3> m_deltaLinearVelocities;
- b3AlignedObjectArray<b3Vector3> m_deltaAngularVelocities;
- bool m_usePgs;
- void averageVelocities();
+ b3AlignedObjectArray<int> m_bodyCount;
+ b3AlignedObjectArray<int> m_bodyCountCheck;
+
+ b3AlignedObjectArray<b3Vector3> m_deltaLinearVelocities;
+ b3AlignedObjectArray<b3Vector3> m_deltaAngularVelocities;
+
+ bool m_usePgs;
+ void averageVelocities();
- int m_maxOverrideNumSolverIterations;
+ int m_maxOverrideNumSolverIterations;
- int m_numSplitImpulseRecoveries;
+ int m_numSplitImpulseRecoveries;
- b3Scalar getContactProcessingThreshold(b3Contact4* contact)
+ b3Scalar getContactProcessingThreshold(b3Contact4* contact)
{
return 0.02f;
}
- void setupFrictionConstraint( b3RigidBodyData* bodies,b3InertiaData* inertias, b3SolverConstraint& solverConstraint, const b3Vector3& normalAxis,int solverBodyIdA,int solverBodyIdB,
- b3ContactPoint& cp,const b3Vector3& rel_pos1,const b3Vector3& rel_pos2,
- b3RigidBodyData* colObj0,b3RigidBodyData* colObj1, b3Scalar relaxation,
- b3Scalar desiredVelocity=0., b3Scalar cfmSlip=0.);
+ void setupFrictionConstraint(b3RigidBodyData* bodies, b3InertiaData* inertias, b3SolverConstraint& solverConstraint, const b3Vector3& normalAxis, int solverBodyIdA, int solverBodyIdB,
+ b3ContactPoint& cp, const b3Vector3& rel_pos1, const b3Vector3& rel_pos2,
+ b3RigidBodyData* colObj0, b3RigidBodyData* colObj1, b3Scalar relaxation,
+ b3Scalar desiredVelocity = 0., b3Scalar cfmSlip = 0.);
- void setupRollingFrictionConstraint(b3RigidBodyData* bodies,b3InertiaData* inertias, b3SolverConstraint& solverConstraint, const b3Vector3& normalAxis,int solverBodyIdA,int solverBodyIdB,
- b3ContactPoint& cp,const b3Vector3& rel_pos1,const b3Vector3& rel_pos2,
- b3RigidBodyData* colObj0,b3RigidBodyData* colObj1, b3Scalar relaxation,
- b3Scalar desiredVelocity=0., b3Scalar cfmSlip=0.);
-
- b3SolverConstraint& addFrictionConstraint(b3RigidBodyData* bodies,b3InertiaData* inertias,const b3Vector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,b3ContactPoint& cp,const b3Vector3& rel_pos1,const b3Vector3& rel_pos2,b3RigidBodyData* colObj0,b3RigidBodyData* colObj1, b3Scalar relaxation, b3Scalar desiredVelocity=0., b3Scalar cfmSlip=0.);
- b3SolverConstraint& addRollingFrictionConstraint(b3RigidBodyData* bodies,b3InertiaData* inertias,const b3Vector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,b3ContactPoint& cp,const b3Vector3& rel_pos1,const b3Vector3& rel_pos2,b3RigidBodyData* colObj0,b3RigidBodyData* colObj1, b3Scalar relaxation, b3Scalar desiredVelocity=0, b3Scalar cfmSlip=0.f);
+ void setupRollingFrictionConstraint(b3RigidBodyData* bodies, b3InertiaData* inertias, b3SolverConstraint& solverConstraint, const b3Vector3& normalAxis, int solverBodyIdA, int solverBodyIdB,
+ b3ContactPoint& cp, const b3Vector3& rel_pos1, const b3Vector3& rel_pos2,
+ b3RigidBodyData* colObj0, b3RigidBodyData* colObj1, b3Scalar relaxation,
+ b3Scalar desiredVelocity = 0., b3Scalar cfmSlip = 0.);
+ b3SolverConstraint& addFrictionConstraint(b3RigidBodyData* bodies, b3InertiaData* inertias, const b3Vector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, b3ContactPoint& cp, const b3Vector3& rel_pos1, const b3Vector3& rel_pos2, b3RigidBodyData* colObj0, b3RigidBodyData* colObj1, b3Scalar relaxation, b3Scalar desiredVelocity = 0., b3Scalar cfmSlip = 0.);
+ b3SolverConstraint& addRollingFrictionConstraint(b3RigidBodyData* bodies, b3InertiaData* inertias, const b3Vector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, b3ContactPoint& cp, const b3Vector3& rel_pos1, const b3Vector3& rel_pos2, b3RigidBodyData* colObj0, b3RigidBodyData* colObj1, b3Scalar relaxation, b3Scalar desiredVelocity = 0, b3Scalar cfmSlip = 0.f);
void setupContactConstraint(b3RigidBodyData* bodies, b3InertiaData* inertias,
- b3SolverConstraint& solverConstraint, int solverBodyIdA, int solverBodyIdB, b3ContactPoint& cp,
- const b3ContactSolverInfo& infoGlobal, b3Vector3& vel, b3Scalar& rel_vel, b3Scalar& relaxation,
+ b3SolverConstraint& solverConstraint, int solverBodyIdA, int solverBodyIdB, b3ContactPoint& cp,
+ const b3ContactSolverInfo& infoGlobal, b3Vector3& vel, b3Scalar& rel_vel, b3Scalar& relaxation,
b3Vector3& rel_pos1, b3Vector3& rel_pos2);
- void setFrictionConstraintImpulse( b3RigidBodyData* bodies, b3InertiaData* inertias,b3SolverConstraint& solverConstraint, int solverBodyIdA,int solverBodyIdB,
- b3ContactPoint& cp, const b3ContactSolverInfo& infoGlobal);
+ void setFrictionConstraintImpulse(b3RigidBodyData* bodies, b3InertiaData* inertias, b3SolverConstraint& solverConstraint, int solverBodyIdA, int solverBodyIdB,
+ b3ContactPoint& cp, const b3ContactSolverInfo& infoGlobal);
///m_btSeed2 is used for re-arranging the constraint rows. improves convergence/quality of friction
- unsigned long m_btSeed2;
+ unsigned long m_btSeed2;
-
b3Scalar restitutionCurve(b3Scalar rel_vel, b3Scalar restitution);
- void convertContact(b3RigidBodyData* bodies, b3InertiaData* inertias,b3Contact4* manifold,const b3ContactSolverInfo& infoGlobal);
-
+ void convertContact(b3RigidBodyData* bodies, b3InertiaData* inertias, b3Contact4* manifold, const b3ContactSolverInfo& infoGlobal);
- void resolveSplitPenetrationSIMD(
- b3SolverBody& bodyA,b3SolverBody& bodyB,
- const b3SolverConstraint& contactConstraint);
+ void resolveSplitPenetrationSIMD(
+ b3SolverBody& bodyA, b3SolverBody& bodyB,
+ const b3SolverConstraint& contactConstraint);
- void resolveSplitPenetrationImpulseCacheFriendly(
- b3SolverBody& bodyA,b3SolverBody& bodyB,
- const b3SolverConstraint& contactConstraint);
+ void resolveSplitPenetrationImpulseCacheFriendly(
+ b3SolverBody& bodyA, b3SolverBody& bodyB,
+ const b3SolverConstraint& contactConstraint);
//internal method
- int getOrInitSolverBody(int bodyIndex, b3RigidBodyData* bodies,b3InertiaData* inertias);
- void initSolverBody(int bodyIndex, b3SolverBody* solverBody, b3RigidBodyData* collisionObject);
+ int getOrInitSolverBody(int bodyIndex, b3RigidBodyData* bodies, b3InertiaData* inertias);
+ void initSolverBody(int bodyIndex, b3SolverBody* solverBody, b3RigidBodyData* collisionObject);
- void resolveSingleConstraintRowGeneric(b3SolverBody& bodyA,b3SolverBody& bodyB,const b3SolverConstraint& contactConstraint);
-
- void resolveSingleConstraintRowGenericSIMD(b3SolverBody& bodyA,b3SolverBody& bodyB,const b3SolverConstraint& contactConstraint);
-
- void resolveSingleConstraintRowLowerLimit(b3SolverBody& bodyA,b3SolverBody& bodyB,const b3SolverConstraint& contactConstraint);
-
- void resolveSingleConstraintRowLowerLimitSIMD(b3SolverBody& bodyA,b3SolverBody& bodyB,const b3SolverConstraint& contactConstraint);
-
-protected:
+ void resolveSingleConstraintRowGeneric(b3SolverBody& bodyA, b3SolverBody& bodyB, const b3SolverConstraint& contactConstraint);
- virtual b3Scalar solveGroupCacheFriendlySetup(b3RigidBodyData* bodies, b3InertiaData* inertias,int numBodies,b3Contact4* manifoldPtr, int numManifolds,b3TypedConstraint** constraints,int numConstraints,const b3ContactSolverInfo& infoGlobal);
+ void resolveSingleConstraintRowGenericSIMD(b3SolverBody& bodyA, b3SolverBody& bodyB, const b3SolverConstraint& contactConstraint);
+ void resolveSingleConstraintRowLowerLimit(b3SolverBody& bodyA, b3SolverBody& bodyB, const b3SolverConstraint& contactConstraint);
- virtual b3Scalar solveGroupCacheFriendlyIterations(b3TypedConstraint** constraints,int numConstraints,const b3ContactSolverInfo& infoGlobal);
- virtual void solveGroupCacheFriendlySplitImpulseIterations(b3TypedConstraint** constraints,int numConstraints,const b3ContactSolverInfo& infoGlobal);
- b3Scalar solveSingleIteration(int iteration, b3TypedConstraint** constraints,int numConstraints,const b3ContactSolverInfo& infoGlobal);
+ void resolveSingleConstraintRowLowerLimitSIMD(b3SolverBody& bodyA, b3SolverBody& bodyB, const b3SolverConstraint& contactConstraint);
+protected:
+ virtual b3Scalar solveGroupCacheFriendlySetup(b3RigidBodyData* bodies, b3InertiaData* inertias, int numBodies, b3Contact4* manifoldPtr, int numManifolds, b3TypedConstraint** constraints, int numConstraints, const b3ContactSolverInfo& infoGlobal);
- virtual b3Scalar solveGroupCacheFriendlyFinish(b3RigidBodyData* bodies, b3InertiaData* inertias,int numBodies,const b3ContactSolverInfo& infoGlobal);
+ virtual b3Scalar solveGroupCacheFriendlyIterations(b3TypedConstraint** constraints, int numConstraints, const b3ContactSolverInfo& infoGlobal);
+ virtual void solveGroupCacheFriendlySplitImpulseIterations(b3TypedConstraint** constraints, int numConstraints, const b3ContactSolverInfo& infoGlobal);
+ b3Scalar solveSingleIteration(int iteration, b3TypedConstraint** constraints, int numConstraints, const b3ContactSolverInfo& infoGlobal);
+ virtual b3Scalar solveGroupCacheFriendlyFinish(b3RigidBodyData* bodies, b3InertiaData* inertias, int numBodies, const b3ContactSolverInfo& infoGlobal);
public:
-
B3_DECLARE_ALIGNED_ALLOCATOR();
-
+
b3PgsJacobiSolver(bool usePgs);
virtual ~b3PgsJacobiSolver();
-// void solveContacts(int numBodies, b3RigidBodyData* bodies, b3InertiaData* inertias, int numContacts, b3Contact4* contacts);
- void solveContacts(int numBodies, b3RigidBodyData* bodies, b3InertiaData* inertias, int numContacts, b3Contact4* contacts, int numConstraints, b3TypedConstraint** constraints);
+ // void solveContacts(int numBodies, b3RigidBodyData* bodies, b3InertiaData* inertias, int numContacts, b3Contact4* contacts);
+ void solveContacts(int numBodies, b3RigidBodyData* bodies, b3InertiaData* inertias, int numContacts, b3Contact4* contacts, int numConstraints, b3TypedConstraint** constraints);
- b3Scalar solveGroup(b3RigidBodyData* bodies,b3InertiaData* inertias,int numBodies,b3Contact4* manifoldPtr, int numManifolds,b3TypedConstraint** constraints,int numConstraints,const b3ContactSolverInfo& infoGlobal);
+ b3Scalar solveGroup(b3RigidBodyData* bodies, b3InertiaData* inertias, int numBodies, b3Contact4* manifoldPtr, int numManifolds, b3TypedConstraint** constraints, int numConstraints, const b3ContactSolverInfo& infoGlobal);
///clear internal cached data and reset random seed
- virtual void reset();
-
+ virtual void reset();
+
unsigned long b3Rand2();
- int b3RandInt2 (int n);
+ int b3RandInt2(int n);
- void setRandSeed(unsigned long seed)
+ void setRandSeed(unsigned long seed)
{
m_btSeed2 = seed;
}
- unsigned long getRandSeed() const
+ unsigned long getRandSeed() const
{
return m_btSeed2;
}
-
-
-
-
};
-#endif //B3_PGS_JACOBI_SOLVER
-
+#endif //B3_PGS_JACOBI_SOLVER
diff --git a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3Point2PointConstraint.cpp b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3Point2PointConstraint.cpp
index 02c11db320..cfa7c7dd11 100644
--- a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3Point2PointConstraint.cpp
+++ b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3Point2PointConstraint.cpp
@@ -13,21 +13,14 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#include "b3Point2PointConstraint.h"
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
#include <new>
-
-
-
-
-b3Point2PointConstraint::b3Point2PointConstraint(int rbA,int rbB, const b3Vector3& pivotInA,const b3Vector3& pivotInB)
-:b3TypedConstraint(B3_POINT2POINT_CONSTRAINT_TYPE,rbA,rbB),m_pivotInA(pivotInA),m_pivotInB(pivotInB),
-m_flags(0)
+b3Point2PointConstraint::b3Point2PointConstraint(int rbA, int rbB, const b3Vector3& pivotInA, const b3Vector3& pivotInB)
+ : b3TypedConstraint(B3_POINT2POINT_CONSTRAINT_TYPE, rbA, rbB), m_pivotInA(pivotInA), m_pivotInB(pivotInB), m_flags(0)
{
-
}
/*
@@ -40,22 +33,18 @@ m_useSolveConstraintObsolete(false)
}
*/
-
-void b3Point2PointConstraint::getInfo1 (b3ConstraintInfo1* info,const b3RigidBodyData* bodies)
+void b3Point2PointConstraint::getInfo1(b3ConstraintInfo1* info, const b3RigidBodyData* bodies)
{
- getInfo1NonVirtual(info,bodies);
+ getInfo1NonVirtual(info, bodies);
}
-void b3Point2PointConstraint::getInfo1NonVirtual (b3ConstraintInfo1* info,const b3RigidBodyData* bodies)
+void b3Point2PointConstraint::getInfo1NonVirtual(b3ConstraintInfo1* info, const b3RigidBodyData* bodies)
{
- info->m_numConstraintRows = 3;
- info->nub = 3;
+ info->m_numConstraintRows = 3;
+ info->nub = 3;
}
-
-
-
-void b3Point2PointConstraint::getInfo2 (b3ConstraintInfo2* info, const b3RigidBodyData* bodies)
+void b3Point2PointConstraint::getInfo2(b3ConstraintInfo2* info, const b3RigidBodyData* bodies)
{
b3Transform trA;
trA.setIdentity();
@@ -67,143 +56,135 @@ void b3Point2PointConstraint::getInfo2 (b3ConstraintInfo2* info, const b3RigidBo
trB.setOrigin(bodies[m_rbB].m_pos);
trB.setRotation(bodies[m_rbB].m_quat);
- getInfo2NonVirtual(info, trA,trB);
+ getInfo2NonVirtual(info, trA, trB);
}
-void b3Point2PointConstraint::getInfo2NonVirtual (b3ConstraintInfo2* info, const b3Transform& body0_trans, const b3Transform& body1_trans)
+void b3Point2PointConstraint::getInfo2NonVirtual(b3ConstraintInfo2* info, const b3Transform& body0_trans, const b3Transform& body1_trans)
{
-
- //retrieve matrices
+ //retrieve matrices
// anchor points in global coordinates with respect to body PORs.
-
- // set jacobian
- info->m_J1linearAxis[0] = 1;
- info->m_J1linearAxis[info->rowskip+1] = 1;
- info->m_J1linearAxis[2*info->rowskip+2] = 1;
- b3Vector3 a1 = body0_trans.getBasis()*getPivotInA();
+ // set jacobian
+ info->m_J1linearAxis[0] = 1;
+ info->m_J1linearAxis[info->rowskip + 1] = 1;
+ info->m_J1linearAxis[2 * info->rowskip + 2] = 1;
+
+ b3Vector3 a1 = body0_trans.getBasis() * getPivotInA();
//b3Vector3 a1a = b3QuatRotate(body0_trans.getRotation(),getPivotInA());
{
b3Vector3* angular0 = (b3Vector3*)(info->m_J1angularAxis);
- b3Vector3* angular1 = (b3Vector3*)(info->m_J1angularAxis+info->rowskip);
- b3Vector3* angular2 = (b3Vector3*)(info->m_J1angularAxis+2*info->rowskip);
+ b3Vector3* angular1 = (b3Vector3*)(info->m_J1angularAxis + info->rowskip);
+ b3Vector3* angular2 = (b3Vector3*)(info->m_J1angularAxis + 2 * info->rowskip);
b3Vector3 a1neg = -a1;
- a1neg.getSkewSymmetricMatrix(angular0,angular1,angular2);
+ a1neg.getSkewSymmetricMatrix(angular0, angular1, angular2);
}
-
+
if (info->m_J2linearAxis)
{
info->m_J2linearAxis[0] = -1;
- info->m_J2linearAxis[info->rowskip+1] = -1;
- info->m_J2linearAxis[2*info->rowskip+2] = -1;
+ info->m_J2linearAxis[info->rowskip + 1] = -1;
+ info->m_J2linearAxis[2 * info->rowskip + 2] = -1;
}
-
- b3Vector3 a2 = body1_trans.getBasis()*getPivotInB();
-
+
+ b3Vector3 a2 = body1_trans.getBasis() * getPivotInB();
+
{
- // b3Vector3 a2n = -a2;
+ // b3Vector3 a2n = -a2;
b3Vector3* angular0 = (b3Vector3*)(info->m_J2angularAxis);
- b3Vector3* angular1 = (b3Vector3*)(info->m_J2angularAxis+info->rowskip);
- b3Vector3* angular2 = (b3Vector3*)(info->m_J2angularAxis+2*info->rowskip);
- a2.getSkewSymmetricMatrix(angular0,angular1,angular2);
+ b3Vector3* angular1 = (b3Vector3*)(info->m_J2angularAxis + info->rowskip);
+ b3Vector3* angular2 = (b3Vector3*)(info->m_J2angularAxis + 2 * info->rowskip);
+ a2.getSkewSymmetricMatrix(angular0, angular1, angular2);
}
-
-
- // set right hand side
+ // set right hand side
b3Scalar currERP = (m_flags & B3_P2P_FLAGS_ERP) ? m_erp : info->erp;
- b3Scalar k = info->fps * currERP;
- int j;
- for (j=0; j<3; j++)
- {
- info->m_constraintError[j*info->rowskip] = k * (a2[j] + body1_trans.getOrigin()[j] - a1[j] - body0_trans.getOrigin()[j]);
+ b3Scalar k = info->fps * currERP;
+ int j;
+ for (j = 0; j < 3; j++)
+ {
+ info->m_constraintError[j * info->rowskip] = k * (a2[j] + body1_trans.getOrigin()[j] - a1[j] - body0_trans.getOrigin()[j]);
//printf("info->m_constraintError[%d]=%f\n",j,info->m_constraintError[j]);
- }
- if(m_flags & B3_P2P_FLAGS_CFM)
+ }
+ if (m_flags & B3_P2P_FLAGS_CFM)
{
- for (j=0; j<3; j++)
+ for (j = 0; j < 3; j++)
{
- info->cfm[j*info->rowskip] = m_cfm;
+ info->cfm[j * info->rowskip] = m_cfm;
}
}
- b3Scalar impulseClamp = m_setting.m_impulseClamp;//
- for (j=0; j<3; j++)
- {
+ b3Scalar impulseClamp = m_setting.m_impulseClamp; //
+ for (j = 0; j < 3; j++)
+ {
if (m_setting.m_impulseClamp > 0)
{
- info->m_lowerLimit[j*info->rowskip] = -impulseClamp;
- info->m_upperLimit[j*info->rowskip] = impulseClamp;
+ info->m_lowerLimit[j * info->rowskip] = -impulseClamp;
+ info->m_upperLimit[j * info->rowskip] = impulseClamp;
}
}
info->m_damping = m_setting.m_damping;
-
}
-
-
-void b3Point2PointConstraint::updateRHS(b3Scalar timeStep)
+void b3Point2PointConstraint::updateRHS(b3Scalar timeStep)
{
(void)timeStep;
-
}
-///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
///If no axis is provided, it uses the default axis for this constraint.
void b3Point2PointConstraint::setParam(int num, b3Scalar value, int axis)
{
- if(axis != -1)
+ if (axis != -1)
{
b3AssertConstrParams(0);
}
else
{
- switch(num)
+ switch (num)
{
- case B3_CONSTRAINT_ERP :
- case B3_CONSTRAINT_STOP_ERP :
- m_erp = value;
+ case B3_CONSTRAINT_ERP:
+ case B3_CONSTRAINT_STOP_ERP:
+ m_erp = value;
m_flags |= B3_P2P_FLAGS_ERP;
break;
- case B3_CONSTRAINT_CFM :
- case B3_CONSTRAINT_STOP_CFM :
- m_cfm = value;
+ case B3_CONSTRAINT_CFM:
+ case B3_CONSTRAINT_STOP_CFM:
+ m_cfm = value;
m_flags |= B3_P2P_FLAGS_CFM;
break;
- default:
+ default:
b3AssertConstrParams(0);
}
}
}
///return the local value of parameter
-b3Scalar b3Point2PointConstraint::getParam(int num, int axis) const
+b3Scalar b3Point2PointConstraint::getParam(int num, int axis) const
{
b3Scalar retVal(B3_INFINITY);
- if(axis != -1)
+ if (axis != -1)
{
b3AssertConstrParams(0);
}
else
{
- switch(num)
+ switch (num)
{
- case B3_CONSTRAINT_ERP :
- case B3_CONSTRAINT_STOP_ERP :
+ case B3_CONSTRAINT_ERP:
+ case B3_CONSTRAINT_STOP_ERP:
b3AssertConstrParams(m_flags & B3_P2P_FLAGS_ERP);
- retVal = m_erp;
+ retVal = m_erp;
break;
- case B3_CONSTRAINT_CFM :
- case B3_CONSTRAINT_STOP_CFM :
+ case B3_CONSTRAINT_CFM:
+ case B3_CONSTRAINT_STOP_CFM:
b3AssertConstrParams(m_flags & B3_P2P_FLAGS_CFM);
- retVal = m_cfm;
+ retVal = m_cfm;
break;
- default:
+ default:
b3AssertConstrParams(0);
}
}
return retVal;
}
-
diff --git a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3Point2PointConstraint.h b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3Point2PointConstraint.h
index 681b487334..14762a3e35 100644
--- a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3Point2PointConstraint.h
+++ b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3Point2PointConstraint.h
@@ -22,26 +22,24 @@ subject to the following restrictions:
class b3RigidBody;
-
#ifdef B3_USE_DOUBLE_PRECISION
-#define b3Point2PointConstraintData b3Point2PointConstraintDoubleData
-#define b3Point2PointConstraintDataName "b3Point2PointConstraintDoubleData"
+#define b3Point2PointConstraintData b3Point2PointConstraintDoubleData
+#define b3Point2PointConstraintDataName "b3Point2PointConstraintDoubleData"
#else
-#define b3Point2PointConstraintData b3Point2PointConstraintFloatData
-#define b3Point2PointConstraintDataName "b3Point2PointConstraintFloatData"
-#endif //B3_USE_DOUBLE_PRECISION
+#define b3Point2PointConstraintData b3Point2PointConstraintFloatData
+#define b3Point2PointConstraintDataName "b3Point2PointConstraintFloatData"
+#endif //B3_USE_DOUBLE_PRECISION
-struct b3ConstraintSetting
+struct b3ConstraintSetting
{
- b3ConstraintSetting() :
- m_tau(b3Scalar(0.3)),
- m_damping(b3Scalar(1.)),
- m_impulseClamp(b3Scalar(0.))
+ b3ConstraintSetting() : m_tau(b3Scalar(0.3)),
+ m_damping(b3Scalar(1.)),
+ m_impulseClamp(b3Scalar(0.))
{
}
- b3Scalar m_tau;
- b3Scalar m_damping;
- b3Scalar m_impulseClamp;
+ b3Scalar m_tau;
+ b3Scalar m_damping;
+ b3Scalar m_impulseClamp;
};
enum b3Point2PointFlags
@@ -51,47 +49,45 @@ enum b3Point2PointFlags
};
/// point to point constraint between two rigidbodies each with a pivotpoint that descibes the 'ballsocket' location in local space
-B3_ATTRIBUTE_ALIGNED16(class) b3Point2PointConstraint : public b3TypedConstraint
+B3_ATTRIBUTE_ALIGNED16(class)
+b3Point2PointConstraint : public b3TypedConstraint
{
#ifdef IN_PARALLELL_SOLVER
public:
#endif
-
- b3Vector3 m_pivotInA;
- b3Vector3 m_pivotInB;
-
- int m_flags;
- b3Scalar m_erp;
- b3Scalar m_cfm;
-
-public:
- B3_DECLARE_ALIGNED_ALLOCATOR();
+ b3Vector3 m_pivotInA;
+ b3Vector3 m_pivotInB;
- b3ConstraintSetting m_setting;
+ int m_flags;
+ b3Scalar m_erp;
+ b3Scalar m_cfm;
- b3Point2PointConstraint(int rbA,int rbB, const b3Vector3& pivotInA,const b3Vector3& pivotInB);
+public:
+ B3_DECLARE_ALIGNED_ALLOCATOR();
- //b3Point2PointConstraint(int rbA,const b3Vector3& pivotInA);
+ b3ConstraintSetting m_setting;
+ b3Point2PointConstraint(int rbA, int rbB, const b3Vector3& pivotInA, const b3Vector3& pivotInB);
+ //b3Point2PointConstraint(int rbA,const b3Vector3& pivotInA);
- virtual void getInfo1 (b3ConstraintInfo1* info,const b3RigidBodyData* bodies);
+ virtual void getInfo1(b3ConstraintInfo1 * info, const b3RigidBodyData* bodies);
- void getInfo1NonVirtual (b3ConstraintInfo1* info,const b3RigidBodyData* bodies);
+ void getInfo1NonVirtual(b3ConstraintInfo1 * info, const b3RigidBodyData* bodies);
- virtual void getInfo2 (b3ConstraintInfo2* info, const b3RigidBodyData* bodies);
+ virtual void getInfo2(b3ConstraintInfo2 * info, const b3RigidBodyData* bodies);
- void getInfo2NonVirtual (b3ConstraintInfo2* info, const b3Transform& body0_trans, const b3Transform& body1_trans);
+ void getInfo2NonVirtual(b3ConstraintInfo2 * info, const b3Transform& body0_trans, const b3Transform& body1_trans);
- void updateRHS(b3Scalar timeStep);
+ void updateRHS(b3Scalar timeStep);
- void setPivotA(const b3Vector3& pivotA)
+ void setPivotA(const b3Vector3& pivotA)
{
m_pivotInA = pivotA;
}
- void setPivotB(const b3Vector3& pivotB)
+ void setPivotB(const b3Vector3& pivotB)
{
m_pivotInB = pivotB;
}
@@ -106,34 +102,32 @@ public:
return m_pivotInB;
}
- ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+ ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
///If no axis is provided, it uses the default axis for this constraint.
- virtual void setParam(int num, b3Scalar value, int axis = -1);
+ virtual void setParam(int num, b3Scalar value, int axis = -1);
///return the local value of parameter
- virtual b3Scalar getParam(int num, int axis = -1) const;
+ virtual b3Scalar getParam(int num, int axis = -1) const;
-// virtual int calculateSerializeBufferSize() const;
+ // virtual int calculateSerializeBufferSize() const;
///fills the dataBuffer and returns the struct name (and 0 on failure)
-// virtual const char* serialize(void* dataBuffer, b3Serializer* serializer) const;
-
-
+ // virtual const char* serialize(void* dataBuffer, b3Serializer* serializer) const;
};
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct b3Point2PointConstraintFloatData
+struct b3Point2PointConstraintFloatData
{
- b3TypedConstraintData m_typeConstraintData;
- b3Vector3FloatData m_pivotInA;
- b3Vector3FloatData m_pivotInB;
+ b3TypedConstraintData m_typeConstraintData;
+ b3Vector3FloatData m_pivotInA;
+ b3Vector3FloatData m_pivotInB;
};
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct b3Point2PointConstraintDoubleData
+struct b3Point2PointConstraintDoubleData
{
- b3TypedConstraintData m_typeConstraintData;
- b3Vector3DoubleData m_pivotInA;
- b3Vector3DoubleData m_pivotInB;
+ b3TypedConstraintData m_typeConstraintData;
+ b3Vector3DoubleData m_pivotInA;
+ b3Vector3DoubleData m_pivotInB;
};
/*
@@ -156,4 +150,4 @@ B3_FORCE_INLINE const char* b3Point2PointConstraint::serialize(void* dataBuffer,
}
*/
-#endif //B3_POINT2POINTCONSTRAINT_H
+#endif //B3_POINT2POINTCONSTRAINT_H
diff --git a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3SolverBody.h b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3SolverBody.h
index 0049317d98..196d0e5793 100644
--- a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3SolverBody.h
+++ b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3SolverBody.h
@@ -16,7 +16,6 @@ subject to the following restrictions:
#ifndef B3_SOLVER_BODY_H
#define B3_SOLVER_BODY_H
-
#include "Bullet3Common/b3Vector3.h"
#include "Bullet3Common/b3Matrix3x3.h"
@@ -26,110 +25,104 @@ subject to the following restrictions:
///Until we get other contributions, only use SIMD on Windows, when using Visual Studio 2008 or later, and not double precision
#ifdef B3_USE_SSE
#define USE_SIMD 1
-#endif //
-
+#endif //
#ifdef USE_SIMD
-struct b3SimdScalar
+struct b3SimdScalar
{
- B3_FORCE_INLINE b3SimdScalar()
+ B3_FORCE_INLINE b3SimdScalar()
{
-
}
- B3_FORCE_INLINE b3SimdScalar(float fl)
- :m_vec128 (_mm_set1_ps(fl))
+ B3_FORCE_INLINE b3SimdScalar(float fl)
+ : m_vec128(_mm_set1_ps(fl))
{
}
- B3_FORCE_INLINE b3SimdScalar(__m128 v128)
- :m_vec128(v128)
+ B3_FORCE_INLINE b3SimdScalar(__m128 v128)
+ : m_vec128(v128)
{
}
- union
- {
- __m128 m_vec128;
- float m_floats[4];
- float x,y,z,w;
- int m_ints[4];
- b3Scalar m_unusedPadding;
+ union {
+ __m128 m_vec128;
+ float m_floats[4];
+ float x, y, z, w;
+ int m_ints[4];
+ b3Scalar m_unusedPadding;
};
- B3_FORCE_INLINE __m128 get128()
+ B3_FORCE_INLINE __m128 get128()
{
return m_vec128;
}
- B3_FORCE_INLINE const __m128 get128() const
+ B3_FORCE_INLINE const __m128 get128() const
{
return m_vec128;
}
- B3_FORCE_INLINE void set128(__m128 v128)
+ B3_FORCE_INLINE void set128(__m128 v128)
{
m_vec128 = v128;
}
- B3_FORCE_INLINE operator __m128()
- {
- return m_vec128;
- }
- B3_FORCE_INLINE operator const __m128() const
- {
- return m_vec128;
+ B3_FORCE_INLINE operator __m128()
+ {
+ return m_vec128;
}
-
- B3_FORCE_INLINE operator float() const
- {
- return m_floats[0];
+ B3_FORCE_INLINE operator const __m128() const
+ {
+ return m_vec128;
}
+ B3_FORCE_INLINE operator float() const
+ {
+ return m_floats[0];
+ }
};
///@brief Return the elementwise product of two b3SimdScalar
-B3_FORCE_INLINE b3SimdScalar
-operator*(const b3SimdScalar& v1, const b3SimdScalar& v2)
+B3_FORCE_INLINE b3SimdScalar
+operator*(const b3SimdScalar& v1, const b3SimdScalar& v2)
{
- return b3SimdScalar(_mm_mul_ps(v1.get128(),v2.get128()));
+ return b3SimdScalar(_mm_mul_ps(v1.get128(), v2.get128()));
}
///@brief Return the elementwise product of two b3SimdScalar
-B3_FORCE_INLINE b3SimdScalar
-operator+(const b3SimdScalar& v1, const b3SimdScalar& v2)
+B3_FORCE_INLINE b3SimdScalar
+operator+(const b3SimdScalar& v1, const b3SimdScalar& v2)
{
- return b3SimdScalar(_mm_add_ps(v1.get128(),v2.get128()));
+ return b3SimdScalar(_mm_add_ps(v1.get128(), v2.get128()));
}
-
#else
#define b3SimdScalar b3Scalar
#endif
///The b3SolverBody is an internal datastructure for the constraint solver. Only necessary data is packed to increase cache coherence/performance.
-B3_ATTRIBUTE_ALIGNED16 (struct) b3SolverBody
+B3_ATTRIBUTE_ALIGNED16(struct)
+b3SolverBody
{
B3_DECLARE_ALIGNED_ALLOCATOR();
- b3Transform m_worldTransform;
- b3Vector3 m_deltaLinearVelocity;
- b3Vector3 m_deltaAngularVelocity;
- b3Vector3 m_angularFactor;
- b3Vector3 m_linearFactor;
- b3Vector3 m_invMass;
- b3Vector3 m_pushVelocity;
- b3Vector3 m_turnVelocity;
- b3Vector3 m_linearVelocity;
- b3Vector3 m_angularVelocity;
-
- union
- {
- void* m_originalBody;
- int m_originalBodyIndex;
+ b3Transform m_worldTransform;
+ b3Vector3 m_deltaLinearVelocity;
+ b3Vector3 m_deltaAngularVelocity;
+ b3Vector3 m_angularFactor;
+ b3Vector3 m_linearFactor;
+ b3Vector3 m_invMass;
+ b3Vector3 m_pushVelocity;
+ b3Vector3 m_turnVelocity;
+ b3Vector3 m_linearVelocity;
+ b3Vector3 m_angularVelocity;
+
+ union {
+ void* m_originalBody;
+ int m_originalBodyIndex;
};
int padding[3];
-
- void setWorldTransform(const b3Transform& worldTransform)
+ void setWorldTransform(const b3Transform& worldTransform)
{
m_worldTransform = worldTransform;
}
@@ -138,45 +131,42 @@ B3_ATTRIBUTE_ALIGNED16 (struct) b3SolverBody
{
return m_worldTransform;
}
-
- B3_FORCE_INLINE void getVelocityInLocalPointObsolete(const b3Vector3& rel_pos, b3Vector3& velocity ) const
+
+ B3_FORCE_INLINE void getVelocityInLocalPointObsolete(const b3Vector3& rel_pos, b3Vector3& velocity) const
{
if (m_originalBody)
- velocity = m_linearVelocity+m_deltaLinearVelocity + (m_angularVelocity+m_deltaAngularVelocity).cross(rel_pos);
+ velocity = m_linearVelocity + m_deltaLinearVelocity + (m_angularVelocity + m_deltaAngularVelocity).cross(rel_pos);
else
- velocity.setValue(0,0,0);
+ velocity.setValue(0, 0, 0);
}
- B3_FORCE_INLINE void getAngularVelocity(b3Vector3& angVel) const
+ B3_FORCE_INLINE void getAngularVelocity(b3Vector3 & angVel) const
{
if (m_originalBody)
- angVel =m_angularVelocity+m_deltaAngularVelocity;
+ angVel = m_angularVelocity + m_deltaAngularVelocity;
else
- angVel.setValue(0,0,0);
+ angVel.setValue(0, 0, 0);
}
-
//Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position
- B3_FORCE_INLINE void applyImpulse(const b3Vector3& linearComponent, const b3Vector3& angularComponent,const b3Scalar impulseMagnitude)
+ B3_FORCE_INLINE void applyImpulse(const b3Vector3& linearComponent, const b3Vector3& angularComponent, const b3Scalar impulseMagnitude)
{
if (m_originalBody)
{
- m_deltaLinearVelocity += linearComponent*impulseMagnitude*m_linearFactor;
- m_deltaAngularVelocity += angularComponent*(impulseMagnitude*m_angularFactor);
+ m_deltaLinearVelocity += linearComponent * impulseMagnitude * m_linearFactor;
+ m_deltaAngularVelocity += angularComponent * (impulseMagnitude * m_angularFactor);
}
}
- B3_FORCE_INLINE void internalApplyPushImpulse(const b3Vector3& linearComponent, const b3Vector3& angularComponent,b3Scalar impulseMagnitude)
+ B3_FORCE_INLINE void internalApplyPushImpulse(const b3Vector3& linearComponent, const b3Vector3& angularComponent, b3Scalar impulseMagnitude)
{
if (m_originalBody)
{
- m_pushVelocity += linearComponent*impulseMagnitude*m_linearFactor;
- m_turnVelocity += angularComponent*(impulseMagnitude*m_angularFactor);
+ m_pushVelocity += linearComponent * impulseMagnitude * m_linearFactor;
+ m_turnVelocity += angularComponent * (impulseMagnitude * m_angularFactor);
}
}
-
-
const b3Vector3& getDeltaLinearVelocity() const
{
return m_deltaLinearVelocity;
@@ -187,20 +177,19 @@ B3_ATTRIBUTE_ALIGNED16 (struct) b3SolverBody
return m_deltaAngularVelocity;
}
- const b3Vector3& getPushVelocity() const
+ const b3Vector3& getPushVelocity() const
{
return m_pushVelocity;
}
- const b3Vector3& getTurnVelocity() const
+ const b3Vector3& getTurnVelocity() const
{
return m_turnVelocity;
}
-
////////////////////////////////////////////////
///some internal methods, don't use them
-
+
b3Vector3& internalGetDeltaLinearVelocity()
{
return m_deltaLinearVelocity;
@@ -225,7 +214,7 @@ B3_ATTRIBUTE_ALIGNED16 (struct) b3SolverBody
{
m_invMass = invMass;
}
-
+
b3Vector3& internalGetPushVelocity()
{
return m_pushVelocity;
@@ -236,67 +225,57 @@ B3_ATTRIBUTE_ALIGNED16 (struct) b3SolverBody
return m_turnVelocity;
}
- B3_FORCE_INLINE void internalGetVelocityInLocalPointObsolete(const b3Vector3& rel_pos, b3Vector3& velocity ) const
+ B3_FORCE_INLINE void internalGetVelocityInLocalPointObsolete(const b3Vector3& rel_pos, b3Vector3& velocity) const
{
- velocity = m_linearVelocity+m_deltaLinearVelocity + (m_angularVelocity+m_deltaAngularVelocity).cross(rel_pos);
+ velocity = m_linearVelocity + m_deltaLinearVelocity + (m_angularVelocity + m_deltaAngularVelocity).cross(rel_pos);
}
- B3_FORCE_INLINE void internalGetAngularVelocity(b3Vector3& angVel) const
+ B3_FORCE_INLINE void internalGetAngularVelocity(b3Vector3 & angVel) const
{
- angVel = m_angularVelocity+m_deltaAngularVelocity;
+ angVel = m_angularVelocity + m_deltaAngularVelocity;
}
-
//Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position
- B3_FORCE_INLINE void internalApplyImpulse(const b3Vector3& linearComponent, const b3Vector3& angularComponent,const b3Scalar impulseMagnitude)
+ B3_FORCE_INLINE void internalApplyImpulse(const b3Vector3& linearComponent, const b3Vector3& angularComponent, const b3Scalar impulseMagnitude)
{
//if (m_originalBody)
{
- m_deltaLinearVelocity += linearComponent*impulseMagnitude*m_linearFactor;
- m_deltaAngularVelocity += angularComponent*(impulseMagnitude*m_angularFactor);
+ m_deltaLinearVelocity += linearComponent * impulseMagnitude * m_linearFactor;
+ m_deltaAngularVelocity += angularComponent * (impulseMagnitude * m_angularFactor);
}
}
-
-
-
- void writebackVelocity()
+ void writebackVelocity()
{
//if (m_originalBody>=0)
{
- m_linearVelocity +=m_deltaLinearVelocity;
+ m_linearVelocity += m_deltaLinearVelocity;
m_angularVelocity += m_deltaAngularVelocity;
-
+
//m_originalBody->setCompanionId(-1);
}
}
-
- void writebackVelocityAndTransform(b3Scalar timeStep, b3Scalar splitImpulseTurnErp)
+ void writebackVelocityAndTransform(b3Scalar timeStep, b3Scalar splitImpulseTurnErp)
{
- (void) timeStep;
+ (void)timeStep;
if (m_originalBody)
{
m_linearVelocity += m_deltaLinearVelocity;
m_angularVelocity += m_deltaAngularVelocity;
-
+
//correct the position/orientation based on push/turn recovery
b3Transform newTransform;
- if (m_pushVelocity[0]!=0.f || m_pushVelocity[1]!=0 || m_pushVelocity[2]!=0 || m_turnVelocity[0]!=0.f || m_turnVelocity[1]!=0 || m_turnVelocity[2]!=0)
+ if (m_pushVelocity[0] != 0.f || m_pushVelocity[1] != 0 || m_pushVelocity[2] != 0 || m_turnVelocity[0] != 0.f || m_turnVelocity[1] != 0 || m_turnVelocity[2] != 0)
{
- // b3Quaternion orn = m_worldTransform.getRotation();
- b3TransformUtil::integrateTransform(m_worldTransform,m_pushVelocity,m_turnVelocity*splitImpulseTurnErp,timeStep,newTransform);
+ // b3Quaternion orn = m_worldTransform.getRotation();
+ b3TransformUtil::integrateTransform(m_worldTransform, m_pushVelocity, m_turnVelocity * splitImpulseTurnErp, timeStep, newTransform);
m_worldTransform = newTransform;
}
//m_worldTransform.setRotation(orn);
//m_originalBody->setCompanionId(-1);
}
}
-
-
-
};
-#endif //B3_SOLVER_BODY_H
-
-
+#endif //B3_SOLVER_BODY_H
diff --git a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3SolverConstraint.h b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3SolverConstraint.h
index bce83d4608..4927ae4288 100644
--- a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3SolverConstraint.h
+++ b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3SolverConstraint.h
@@ -16,7 +16,6 @@ subject to the following restrictions:
#ifndef B3_SOLVER_CONSTRAINT_H
#define B3_SOLVER_CONSTRAINT_H
-
#include "Bullet3Common/b3Vector3.h"
#include "Bullet3Common/b3Matrix3x3.h"
//#include "b3JacobianEntry.h"
@@ -25,56 +24,50 @@ subject to the following restrictions:
//#define NO_FRICTION_TANGENTIALS 1
#include "b3SolverBody.h"
-
///1D constraint along a normal axis between bodyA and bodyB. It can be combined to solve contact and friction constraints.
-B3_ATTRIBUTE_ALIGNED16 (struct) b3SolverConstraint
+B3_ATTRIBUTE_ALIGNED16(struct)
+b3SolverConstraint
{
B3_DECLARE_ALIGNED_ALLOCATOR();
- b3Vector3 m_relpos1CrossNormal;
- b3Vector3 m_contactNormal;
+ b3Vector3 m_relpos1CrossNormal;
+ b3Vector3 m_contactNormal;
- b3Vector3 m_relpos2CrossNormal;
+ b3Vector3 m_relpos2CrossNormal;
//b3Vector3 m_contactNormal2;//usually m_contactNormal2 == -m_contactNormal
- b3Vector3 m_angularComponentA;
- b3Vector3 m_angularComponentB;
-
- mutable b3SimdScalar m_appliedPushImpulse;
- mutable b3SimdScalar m_appliedImpulse;
+ b3Vector3 m_angularComponentA;
+ b3Vector3 m_angularComponentB;
+
+ mutable b3SimdScalar m_appliedPushImpulse;
+ mutable b3SimdScalar m_appliedImpulse;
int m_padding1;
int m_padding2;
- b3Scalar m_friction;
- b3Scalar m_jacDiagABInv;
- b3Scalar m_rhs;
- b3Scalar m_cfm;
-
- b3Scalar m_lowerLimit;
- b3Scalar m_upperLimit;
- b3Scalar m_rhsPenetration;
- union
- {
- void* m_originalContactPoint;
- b3Scalar m_unusedPadding4;
+ b3Scalar m_friction;
+ b3Scalar m_jacDiagABInv;
+ b3Scalar m_rhs;
+ b3Scalar m_cfm;
+
+ b3Scalar m_lowerLimit;
+ b3Scalar m_upperLimit;
+ b3Scalar m_rhsPenetration;
+ union {
+ void* m_originalContactPoint;
+ b3Scalar m_unusedPadding4;
};
- int m_overrideNumSolverIterations;
- int m_frictionIndex;
+ int m_overrideNumSolverIterations;
+ int m_frictionIndex;
int m_solverBodyIdA;
int m_solverBodyIdB;
-
- enum b3SolverConstraintType
+ enum b3SolverConstraintType
{
B3_SOLVER_CONTACT_1D = 0,
B3_SOLVER_FRICTION_1D
};
};
-typedef b3AlignedObjectArray<b3SolverConstraint> b3ConstraintArray;
-
-
-#endif //B3_SOLVER_CONSTRAINT_H
-
-
+typedef b3AlignedObjectArray<b3SolverConstraint> b3ConstraintArray;
+#endif //B3_SOLVER_CONSTRAINT_H
diff --git a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.cpp b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.cpp
index 699c481d64..885e277d8c 100644
--- a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.cpp
+++ b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.cpp
@@ -13,53 +13,46 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#include "b3TypedConstraint.h"
//#include "Bullet3Common/b3Serializer.h"
-
#define B3_DEFAULT_DEBUGDRAW_SIZE b3Scalar(0.3f)
-
-
-b3TypedConstraint::b3TypedConstraint(b3TypedConstraintType type, int rbA,int rbB)
-:b3TypedObject(type),
-m_userConstraintType(-1),
-m_userConstraintPtr((void*)-1),
-m_breakingImpulseThreshold(B3_INFINITY),
-m_isEnabled(true),
-m_needsFeedback(false),
-m_overrideNumSolverIterations(-1),
-m_rbA(rbA),
-m_rbB(rbB),
-m_appliedImpulse(b3Scalar(0.)),
-m_dbgDrawSize(B3_DEFAULT_DEBUGDRAW_SIZE),
-m_jointFeedback(0)
+b3TypedConstraint::b3TypedConstraint(b3TypedConstraintType type, int rbA, int rbB)
+ : b3TypedObject(type),
+ m_userConstraintType(-1),
+ m_userConstraintPtr((void*)-1),
+ m_breakingImpulseThreshold(B3_INFINITY),
+ m_isEnabled(true),
+ m_needsFeedback(false),
+ m_overrideNumSolverIterations(-1),
+ m_rbA(rbA),
+ m_rbB(rbB),
+ m_appliedImpulse(b3Scalar(0.)),
+ m_dbgDrawSize(B3_DEFAULT_DEBUGDRAW_SIZE),
+ m_jointFeedback(0)
{
}
-
-
-
b3Scalar b3TypedConstraint::getMotorFactor(b3Scalar pos, b3Scalar lowLim, b3Scalar uppLim, b3Scalar vel, b3Scalar timeFact)
{
- if(lowLim > uppLim)
+ if (lowLim > uppLim)
{
return b3Scalar(1.0f);
}
- else if(lowLim == uppLim)
+ else if (lowLim == uppLim)
{
return b3Scalar(0.0f);
}
b3Scalar lim_fact = b3Scalar(1.0f);
b3Scalar delta_max = vel / timeFact;
- if(delta_max < b3Scalar(0.0f))
+ if (delta_max < b3Scalar(0.0f))
{
- if((pos >= lowLim) && (pos < (lowLim - delta_max)))
+ if ((pos >= lowLim) && (pos < (lowLim - delta_max)))
{
lim_fact = (lowLim - pos) / delta_max;
}
- else if(pos < lowLim)
+ else if (pos < lowLim)
{
lim_fact = b3Scalar(0.0f);
}
@@ -68,13 +61,13 @@ b3Scalar b3TypedConstraint::getMotorFactor(b3Scalar pos, b3Scalar lowLim, b3Scal
lim_fact = b3Scalar(1.0f);
}
}
- else if(delta_max > b3Scalar(0.0f))
+ else if (delta_max > b3Scalar(0.0f))
{
- if((pos <= uppLim) && (pos > (uppLim - delta_max)))
+ if ((pos <= uppLim) && (pos > (uppLim - delta_max)))
{
lim_fact = (uppLim - pos) / delta_max;
}
- else if(pos > uppLim)
+ else if (pos > uppLim)
{
lim_fact = b3Scalar(0.0f);
}
@@ -85,18 +78,16 @@ b3Scalar b3TypedConstraint::getMotorFactor(b3Scalar pos, b3Scalar lowLim, b3Scal
}
else
{
- lim_fact = b3Scalar(0.0f);
+ lim_fact = b3Scalar(0.0f);
}
return lim_fact;
}
-
-
void b3AngularLimit::set(b3Scalar low, b3Scalar high, b3Scalar _softness, b3Scalar _biasFactor, b3Scalar _relaxationFactor)
{
m_halfRange = (high - low) / 2.0f;
m_center = b3NormalizeAngle(low + m_halfRange);
- m_softness = _softness;
+ m_softness = _softness;
m_biasFactor = _biasFactor;
m_relaxationFactor = _relaxationFactor;
}
@@ -113,7 +104,7 @@ void b3AngularLimit::test(const b3Scalar angle)
if (deviation < -m_halfRange)
{
m_solveLimit = true;
- m_correction = - (deviation + m_halfRange);
+ m_correction = -(deviation + m_halfRange);
m_sign = +1.0f;
}
else if (deviation > m_halfRange)
@@ -125,7 +116,6 @@ void b3AngularLimit::test(const b3Scalar angle)
}
}
-
b3Scalar b3AngularLimit::getError() const
{
return m_correction * m_sign;
diff --git a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.h b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.h
index cf9cec0d5e..f74aec4d3c 100644
--- a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.h
+++ b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.h
@@ -16,7 +16,6 @@ subject to the following restrictions:
#ifndef B3_TYPED_CONSTRAINT_H
#define B3_TYPED_CONSTRAINT_H
-
#include "Bullet3Common/b3Scalar.h"
#include "b3SolverConstraint.h"
@@ -25,7 +24,7 @@ class b3Serializer;
//Don't change any of the existing enum values, so add enum types at the end for serialization compatibility
enum b3TypedConstraintType
{
- B3_POINT2POINT_CONSTRAINT_TYPE=3,
+ B3_POINT2POINT_CONSTRAINT_TYPE = 3,
B3_HINGE_CONSTRAINT_TYPE,
B3_CONETWIST_CONSTRAINT_TYPE,
B3_D6_CONSTRAINT_TYPE,
@@ -37,92 +36,86 @@ enum b3TypedConstraintType
B3_MAX_CONSTRAINT_TYPE
};
-
enum b3ConstraintParams
{
- B3_CONSTRAINT_ERP=1,
+ B3_CONSTRAINT_ERP = 1,
B3_CONSTRAINT_STOP_ERP,
B3_CONSTRAINT_CFM,
B3_CONSTRAINT_STOP_CFM
};
#if 1
- #define b3AssertConstrParams(_par) b3Assert(_par)
+#define b3AssertConstrParams(_par) b3Assert(_par)
#else
- #define b3AssertConstrParams(_par)
+#define b3AssertConstrParams(_par)
#endif
-
-B3_ATTRIBUTE_ALIGNED16(struct) b3JointFeedback
+B3_ATTRIBUTE_ALIGNED16(struct)
+b3JointFeedback
{
- b3Vector3 m_appliedForceBodyA;
- b3Vector3 m_appliedTorqueBodyA;
- b3Vector3 m_appliedForceBodyB;
- b3Vector3 m_appliedTorqueBodyB;
+ b3Vector3 m_appliedForceBodyA;
+ b3Vector3 m_appliedTorqueBodyA;
+ b3Vector3 m_appliedForceBodyB;
+ b3Vector3 m_appliedTorqueBodyB;
};
-
struct b3RigidBodyData;
-
///TypedConstraint is the baseclass for Bullet constraints and vehicles
-B3_ATTRIBUTE_ALIGNED16(class) b3TypedConstraint : public b3TypedObject
+B3_ATTRIBUTE_ALIGNED16(class)
+b3TypedConstraint : public b3TypedObject
{
- int m_userConstraintType;
+ int m_userConstraintType;
- union
- {
- int m_userConstraintId;
+ union {
+ int m_userConstraintId;
void* m_userConstraintPtr;
};
- b3Scalar m_breakingImpulseThreshold;
- bool m_isEnabled;
- bool m_needsFeedback;
- int m_overrideNumSolverIterations;
+ b3Scalar m_breakingImpulseThreshold;
+ bool m_isEnabled;
+ bool m_needsFeedback;
+ int m_overrideNumSolverIterations;
-
- b3TypedConstraint& operator=(b3TypedConstraint& other)
+ b3TypedConstraint& operator=(b3TypedConstraint& other)
{
b3Assert(0);
- (void) other;
+ (void)other;
return *this;
}
protected:
- int m_rbA;
- int m_rbB;
- b3Scalar m_appliedImpulse;
- b3Scalar m_dbgDrawSize;
- b3JointFeedback* m_jointFeedback;
+ int m_rbA;
+ int m_rbB;
+ b3Scalar m_appliedImpulse;
+ b3Scalar m_dbgDrawSize;
+ b3JointFeedback* m_jointFeedback;
///internal method used by the constraint solver, don't use them directly
b3Scalar getMotorFactor(b3Scalar pos, b3Scalar lowLim, b3Scalar uppLim, b3Scalar vel, b3Scalar timeFact);
-
public:
-
B3_DECLARE_ALIGNED_ALLOCATOR();
- virtual ~b3TypedConstraint() {};
- b3TypedConstraint(b3TypedConstraintType type, int bodyA,int bodyB);
+ virtual ~b3TypedConstraint(){};
+ b3TypedConstraint(b3TypedConstraintType type, int bodyA, int bodyB);
- struct b3ConstraintInfo1 {
- int m_numConstraintRows,nub;
+ struct b3ConstraintInfo1
+ {
+ int m_numConstraintRows, nub;
};
-
-
- struct b3ConstraintInfo2 {
+ struct b3ConstraintInfo2
+ {
// integrator parameters: frames per second (1/stepsize), default error
// reduction parameter (0..1).
- b3Scalar fps,erp;
+ b3Scalar fps, erp;
// 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.
- b3Scalar *m_J1linearAxis,*m_J1angularAxis,*m_J2linearAxis,*m_J2angularAxis;
+ b3Scalar *m_J1linearAxis, *m_J1angularAxis, *m_J2linearAxis, *m_J2angularAxis;
// elements to jump from one row to the next in J's
int rowskip;
@@ -130,24 +123,24 @@ public:
// 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.
- b3Scalar *m_constraintError,*cfm;
+ b3Scalar *m_constraintError, *cfm;
// lo and hi limits for variables (set to -/+ infinity on entry).
- b3Scalar *m_lowerLimit,*m_upperLimit;
+ b3Scalar *m_lowerLimit, *m_upperLimit;
// 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;
+ int* findex;
// number of solver iterations
int m_numIterations;
//damping of the velocity
- b3Scalar m_damping;
+ b3Scalar m_damping;
};
- int getOverrideNumSolverIterations() const
+ int getOverrideNumSolverIterations() const
{
return m_overrideNumSolverIterations;
}
@@ -159,59 +152,55 @@ public:
m_overrideNumSolverIterations = overideNumIterations;
}
-
///internal method used by the constraint solver, don't use them directly
- virtual void setupSolverConstraint(b3ConstraintArray& ca, int solverBodyA,int solverBodyB, b3Scalar timeStep)
+ virtual void setupSolverConstraint(b3ConstraintArray & ca, int solverBodyA, int solverBodyB, b3Scalar timeStep)
{
- (void)ca;
- (void)solverBodyA;
- (void)solverBodyB;
- (void)timeStep;
+ (void)ca;
+ (void)solverBodyA;
+ (void)solverBodyB;
+ (void)timeStep;
}
-
+
///internal method used by the constraint solver, don't use them directly
- virtual void getInfo1 (b3ConstraintInfo1* info,const b3RigidBodyData* bodies)=0;
+ virtual void getInfo1(b3ConstraintInfo1 * info, const b3RigidBodyData* bodies) = 0;
///internal method used by the constraint solver, don't use them directly
- virtual void getInfo2 (b3ConstraintInfo2* info, const b3RigidBodyData* bodies)=0;
+ virtual void getInfo2(b3ConstraintInfo2 * info, const b3RigidBodyData* bodies) = 0;
///internal method used by the constraint solver, don't use them directly
- void internalSetAppliedImpulse(b3Scalar appliedImpulse)
+ void internalSetAppliedImpulse(b3Scalar appliedImpulse)
{
m_appliedImpulse = appliedImpulse;
}
///internal method used by the constraint solver, don't use them directly
- b3Scalar internalGetAppliedImpulse()
+ b3Scalar internalGetAppliedImpulse()
{
return m_appliedImpulse;
}
-
- b3Scalar getBreakingImpulseThreshold() const
+ b3Scalar getBreakingImpulseThreshold() const
{
- return m_breakingImpulseThreshold;
+ return m_breakingImpulseThreshold;
}
- void setBreakingImpulseThreshold(b3Scalar threshold)
+ void setBreakingImpulseThreshold(b3Scalar threshold)
{
m_breakingImpulseThreshold = threshold;
}
- bool isEnabled() const
+ bool isEnabled() const
{
return m_isEnabled;
}
- void setEnabled(bool enabled)
+ void setEnabled(bool enabled)
{
- m_isEnabled=enabled;
+ m_isEnabled = enabled;
}
-
///internal method used by the constraint solver, don't use them directly
- virtual void solveConstraintObsolete(b3SolverBody& /*bodyA*/,b3SolverBody& /*bodyB*/,b3Scalar /*timeStep*/) {};
+ virtual void solveConstraintObsolete(b3SolverBody& /*bodyA*/, b3SolverBody& /*bodyB*/, b3Scalar /*timeStep*/){};
-
int getRigidBodyA() const
{
return m_rbA;
@@ -221,8 +210,7 @@ public:
return m_rbB;
}
-
- int getRigidBodyA()
+ int getRigidBodyA()
{
return m_rbA;
}
@@ -233,15 +221,15 @@ public:
int getUserConstraintType() const
{
- return m_userConstraintType ;
+ return m_userConstraintType;
}
- void setUserConstraintType(int userConstraintType)
+ void setUserConstraintType(int userConstraintType)
{
m_userConstraintType = userConstraintType;
};
- void setUserConstraintId(int uid)
+ void setUserConstraintId(int uid)
{
m_userConstraintId = uid;
}
@@ -251,17 +239,17 @@ public:
return m_userConstraintId;
}
- void setUserConstraintPtr(void* ptr)
+ void setUserConstraintPtr(void* ptr)
{
m_userConstraintPtr = ptr;
}
- void* getUserConstraintPtr()
+ void* getUserConstraintPtr()
{
return m_userConstraintPtr;
}
- void setJointFeedback(b3JointFeedback* jointFeedback)
+ void setJointFeedback(b3JointFeedback * jointFeedback)
{
m_jointFeedback = jointFeedback;
}
@@ -276,37 +264,36 @@ public:
return m_jointFeedback;
}
-
int getUid() const
{
- return m_userConstraintId;
- }
+ return m_userConstraintId;
+ }
- bool needsFeedback() const
+ bool needsFeedback() const
{
return m_needsFeedback;
}
///enableFeedback will allow to read the applied linear and angular impulse
///use getAppliedImpulse, getAppliedLinearImpulse and getAppliedAngularImpulse to read feedback information
- void enableFeedback(bool needsFeedback)
+ void enableFeedback(bool needsFeedback)
{
m_needsFeedback = needsFeedback;
}
- ///getAppliedImpulse is an estimated total applied impulse.
+ ///getAppliedImpulse is an estimated total applied impulse.
///This feedback could be used to determine breaking constraints or playing sounds.
- b3Scalar getAppliedImpulse() const
+ b3Scalar getAppliedImpulse() const
{
b3Assert(m_needsFeedback);
return m_appliedImpulse;
}
- b3TypedConstraintType getConstraintType () const
+ b3TypedConstraintType getConstraintType() const
{
return b3TypedConstraintType(m_objectType);
}
-
+
void setDbgDrawSize(b3Scalar dbgDrawSize)
{
m_dbgDrawSize = dbgDrawSize;
@@ -316,35 +303,34 @@ public:
return m_dbgDrawSize;
}
- ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+ ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
///If no axis is provided, it uses the default axis for this constraint.
- virtual void setParam(int num, b3Scalar value, int axis = -1) = 0;
+ virtual void setParam(int num, b3Scalar value, int axis = -1) = 0;
///return the local value of parameter
- virtual b3Scalar getParam(int num, int axis = -1) const = 0;
-
-// virtual int calculateSerializeBufferSize() const;
+ virtual b3Scalar getParam(int num, int axis = -1) const = 0;
+
+ // virtual int calculateSerializeBufferSize() const;
///fills the dataBuffer and returns the struct name (and 0 on failure)
//virtual const char* serialize(void* dataBuffer, b3Serializer* serializer) const;
-
};
-// returns angle in range [-B3_2_PI, B3_2_PI], closest to one of the limits
+// returns angle in range [-B3_2_PI, B3_2_PI], closest to one of the limits
// all arguments should be normalized angles (i.e. in range [-B3_PI, B3_PI])
B3_FORCE_INLINE b3Scalar b3AdjustAngleToLimits(b3Scalar angleInRadians, b3Scalar angleLowerLimitInRadians, b3Scalar angleUpperLimitInRadians)
{
- if(angleLowerLimitInRadians >= angleUpperLimitInRadians)
+ if (angleLowerLimitInRadians >= angleUpperLimitInRadians)
{
return angleInRadians;
}
- else if(angleInRadians < angleLowerLimitInRadians)
+ else if (angleInRadians < angleLowerLimitInRadians)
{
b3Scalar diffLo = b3Fabs(b3NormalizeAngle(angleLowerLimitInRadians - angleInRadians));
b3Scalar diffHi = b3Fabs(b3NormalizeAngle(angleUpperLimitInRadians - angleInRadians));
return (diffLo < diffHi) ? angleInRadians : (angleInRadians + B3_2_PI);
}
- else if(angleInRadians > angleUpperLimitInRadians)
+ else if (angleInRadians > angleUpperLimitInRadians)
{
b3Scalar diffHi = b3Fabs(b3NormalizeAngle(angleInRadians - angleUpperLimitInRadians));
b3Scalar diffLo = b3Fabs(b3NormalizeAngle(angleInRadians - angleLowerLimitInRadians));
@@ -356,6 +342,7 @@ B3_FORCE_INLINE b3Scalar b3AdjustAngleToLimits(b3Scalar angleInRadians, b3Scalar
}
}
+// clang-format off
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
struct b3TypedConstraintData
{
@@ -379,17 +366,18 @@ struct b3TypedConstraintData
};
+// clang-format on
+
/*B3_FORCE_INLINE int b3TypedConstraint::calculateSerializeBufferSize() const
{
return sizeof(b3TypedConstraintData);
}
*/
-
class b3AngularLimit
{
private:
- b3Scalar
+ b3Scalar
m_center,
m_halfRange,
m_softness,
@@ -404,15 +392,16 @@ private:
public:
/// Default constructor initializes limit as inactive, allowing free constraint movement
b3AngularLimit()
- :m_center(0.0f),
- m_halfRange(-1.0f),
- m_softness(0.9f),
- m_biasFactor(0.3f),
- m_relaxationFactor(1.0f),
- m_correction(0.0f),
- m_sign(0.0f),
- m_solveLimit(false)
- {}
+ : m_center(0.0f),
+ m_halfRange(-1.0f),
+ m_softness(0.9f),
+ m_biasFactor(0.3f),
+ m_relaxationFactor(1.0f),
+ m_correction(0.0f),
+ m_sign(0.0f),
+ m_solveLimit(false)
+ {
+ }
/// Sets all limit's parameters.
/// When low > high limit becomes inactive.
@@ -441,13 +430,13 @@ public:
return m_relaxationFactor;
}
- /// Returns correction value evaluated when test() was invoked
+ /// Returns correction value evaluated when test() was invoked
inline b3Scalar getCorrection() const
{
return m_correction;
}
- /// Returns sign value evaluated when test() was invoked
+ /// Returns sign value evaluated when test() was invoked
inline b3Scalar getSign() const
{
return m_sign;
@@ -475,9 +464,6 @@ public:
b3Scalar getLow() const;
b3Scalar getHigh() const;
-
};
-
-
-#endif //B3_TYPED_CONSTRAINT_H
+#endif //B3_TYPED_CONSTRAINT_H
diff --git a/thirdparty/bullet/Bullet3Dynamics/b3CpuRigidBodyPipeline.cpp b/thirdparty/bullet/Bullet3Dynamics/b3CpuRigidBodyPipeline.cpp
index fbc84cc28d..f1080d9d5e 100644
--- a/thirdparty/bullet/Bullet3Dynamics/b3CpuRigidBodyPipeline.cpp
+++ b/thirdparty/bullet/Bullet3Dynamics/b3CpuRigidBodyPipeline.cpp
@@ -11,7 +11,6 @@
#include "Bullet3Dynamics/shared/b3ContactConstraint4.h"
#include "Bullet3Dynamics/shared/b3Inertia.h"
-
struct b3CpuRigidBodyPipelineInternalData
{
b3AlignedObjectArray<b3RigidBodyData> m_rigidBodies;
@@ -22,7 +21,6 @@ struct b3CpuRigidBodyPipelineInternalData
b3CpuNarrowPhase* m_np;
b3Config m_config;
};
-
b3CpuRigidBodyPipeline::b3CpuRigidBodyPipeline(class b3CpuNarrowPhase* narrowphase, struct b3DynamicBvhBroadphase* broadphaseDbvt, const b3Config& config)
{
@@ -39,49 +37,43 @@ b3CpuRigidBodyPipeline::~b3CpuRigidBodyPipeline()
void b3CpuRigidBodyPipeline::updateAabbWorldSpace()
{
-
- for (int i=0;i<this->getNumBodies();i++)
+ for (int i = 0; i < this->getNumBodies(); i++)
{
b3RigidBodyData* body = &m_data->m_rigidBodies[i];
b3Float4 position = body->m_pos;
- b3Quat orientation = body->m_quat;
+ b3Quat orientation = body->m_quat;
int collidableIndex = body->m_collidableIdx;
b3Collidable& collidable = m_data->m_np->getCollidableCpu(collidableIndex);
int shapeIndex = collidable.m_shapeIndex;
-
- if (shapeIndex>=0)
- {
-
+ if (shapeIndex >= 0)
+ {
b3Aabb localAabb = m_data->m_np->getLocalSpaceAabb(shapeIndex);
b3Aabb& worldAabb = m_data->m_aabbWorldSpace[i];
- float margin=0.f;
- b3TransformAabb2(localAabb.m_minVec,localAabb.m_maxVec,margin,position,orientation,&worldAabb.m_minVec,&worldAabb.m_maxVec);
- m_data->m_bp->setAabb(i,worldAabb.m_minVec,worldAabb.m_maxVec,0);
+ float margin = 0.f;
+ b3TransformAabb2(localAabb.m_minVec, localAabb.m_maxVec, margin, position, orientation, &worldAabb.m_minVec, &worldAabb.m_maxVec);
+ m_data->m_bp->setAabb(i, worldAabb.m_minVec, worldAabb.m_maxVec, 0);
}
}
}
-void b3CpuRigidBodyPipeline::computeOverlappingPairs()
+void b3CpuRigidBodyPipeline::computeOverlappingPairs()
{
int numPairs = m_data->m_bp->getOverlappingPairCache()->getNumOverlappingPairs();
m_data->m_bp->calculateOverlappingPairs();
numPairs = m_data->m_bp->getOverlappingPairCache()->getNumOverlappingPairs();
- printf("numPairs=%d\n",numPairs);
+ printf("numPairs=%d\n", numPairs);
}
void b3CpuRigidBodyPipeline::computeContactPoints()
{
-
b3AlignedObjectArray<b3Int4>& pairs = m_data->m_bp->getOverlappingPairCache()->getOverlappingPairArray();
-
- m_data->m_np->computeContacts(pairs,m_data->m_aabbWorldSpace, m_data->m_rigidBodies);
+ m_data->m_np->computeContacts(pairs, m_data->m_aabbWorldSpace, m_data->m_rigidBodies);
}
-void b3CpuRigidBodyPipeline::stepSimulation(float deltaTime)
+void b3CpuRigidBodyPipeline::stepSimulation(float deltaTime)
{
-
//update world space aabb's
updateAabbWorldSpace();
@@ -92,73 +84,71 @@ void b3CpuRigidBodyPipeline::stepSimulation(float deltaTime)
computeContactPoints();
//solve contacts
-
+
//update transforms
integrate(deltaTime);
-
-
}
-
-static inline float b3CalcRelVel(const b3Vector3& l0, const b3Vector3& l1, const b3Vector3& a0, const b3Vector3& a1,
- const b3Vector3& linVel0, const b3Vector3& angVel0, const b3Vector3& linVel1, const b3Vector3& angVel1)
+static inline float b3CalcRelVel(const b3Vector3& l0, const b3Vector3& l1, const b3Vector3& a0, const b3Vector3& a1,
+ const b3Vector3& linVel0, const b3Vector3& angVel0, const b3Vector3& linVel1, const b3Vector3& angVel1)
{
return b3Dot(l0, linVel0) + b3Dot(a0, angVel0) + b3Dot(l1, linVel1) + b3Dot(a1, angVel1);
}
-
-static inline void b3SetLinearAndAngular(const b3Vector3& n, const b3Vector3& r0, const b3Vector3& r1,
- b3Vector3& linear, b3Vector3& angular0, b3Vector3& angular1)
+static inline void b3SetLinearAndAngular(const b3Vector3& n, const b3Vector3& r0, const b3Vector3& r1,
+ b3Vector3& linear, b3Vector3& angular0, b3Vector3& angular1)
{
linear = -n;
angular0 = -b3Cross(r0, n);
angular1 = b3Cross(r1, n);
}
-
-
-static inline void b3SolveContact(b3ContactConstraint4& cs,
- const b3Vector3& posA, b3Vector3& linVelA, b3Vector3& angVelA, float invMassA, const b3Matrix3x3& invInertiaA,
- const b3Vector3& posB, b3Vector3& linVelB, b3Vector3& angVelB, float invMassB, const b3Matrix3x3& invInertiaB,
- float maxRambdaDt[4], float minRambdaDt[4])
+static inline void b3SolveContact(b3ContactConstraint4& cs,
+ const b3Vector3& posA, b3Vector3& linVelA, b3Vector3& angVelA, float invMassA, const b3Matrix3x3& invInertiaA,
+ const b3Vector3& posB, b3Vector3& linVelB, b3Vector3& angVelB, float invMassB, const b3Matrix3x3& invInertiaB,
+ float maxRambdaDt[4], float minRambdaDt[4])
{
-
- b3Vector3 dLinVelA; dLinVelA.setZero();
- b3Vector3 dAngVelA; dAngVelA.setZero();
- b3Vector3 dLinVelB; dLinVelB.setZero();
- b3Vector3 dAngVelB; dAngVelB.setZero();
-
- for(int ic=0; ic<4; ic++)
+ b3Vector3 dLinVelA;
+ dLinVelA.setZero();
+ b3Vector3 dAngVelA;
+ dAngVelA.setZero();
+ b3Vector3 dLinVelB;
+ dLinVelB.setZero();
+ b3Vector3 dAngVelB;
+ dAngVelB.setZero();
+
+ for (int ic = 0; ic < 4; ic++)
{
// dont necessary because this makes change to 0
- if( cs.m_jacCoeffInv[ic] == 0.f ) continue;
+ if (cs.m_jacCoeffInv[ic] == 0.f) continue;
{
b3Vector3 angular0, angular1, linear;
b3Vector3 r0 = cs.m_worldPos[ic] - (b3Vector3&)posA;
b3Vector3 r1 = cs.m_worldPos[ic] - (b3Vector3&)posB;
- b3SetLinearAndAngular( (const b3Vector3 &)-cs.m_linear, (const b3Vector3 &)r0, (const b3Vector3 &)r1, linear, angular0, angular1 );
+ b3SetLinearAndAngular((const b3Vector3&)-cs.m_linear, (const b3Vector3&)r0, (const b3Vector3&)r1, linear, angular0, angular1);
- float rambdaDt = b3CalcRelVel((const b3Vector3 &)cs.m_linear,(const b3Vector3 &) -cs.m_linear, angular0, angular1,
- linVelA, angVelA, linVelB, angVelB ) + cs.m_b[ic];
+ float rambdaDt = b3CalcRelVel((const b3Vector3&)cs.m_linear, (const b3Vector3&)-cs.m_linear, angular0, angular1,
+ linVelA, angVelA, linVelB, angVelB) +
+ cs.m_b[ic];
rambdaDt *= cs.m_jacCoeffInv[ic];
{
float prevSum = cs.m_appliedRambdaDt[ic];
float updated = prevSum;
updated += rambdaDt;
- updated = b3Max( updated, minRambdaDt[ic] );
- updated = b3Min( updated, maxRambdaDt[ic] );
+ updated = b3Max(updated, minRambdaDt[ic]);
+ updated = b3Min(updated, maxRambdaDt[ic]);
rambdaDt = updated - prevSum;
cs.m_appliedRambdaDt[ic] = updated;
}
- b3Vector3 linImp0 = invMassA*linear*rambdaDt;
- b3Vector3 linImp1 = invMassB*(-linear)*rambdaDt;
- b3Vector3 angImp0 = (invInertiaA* angular0)*rambdaDt;
- b3Vector3 angImp1 = (invInertiaB* angular1)*rambdaDt;
+ b3Vector3 linImp0 = invMassA * linear * rambdaDt;
+ b3Vector3 linImp1 = invMassB * (-linear) * rambdaDt;
+ b3Vector3 angImp0 = (invInertiaA * angular0) * rambdaDt;
+ b3Vector3 angImp1 = (invInertiaB * angular1) * rambdaDt;
#ifdef _WIN32
- b3Assert(_finite(linImp0.getX()));
+ b3Assert(_finite(linImp0.getX()));
b3Assert(_finite(linImp1.getX()));
#endif
{
@@ -169,53 +159,46 @@ static inline void b3SolveContact(b3ContactConstraint4& cs,
}
}
}
-
-
}
-
-
-
-
-static inline void b3SolveFriction(b3ContactConstraint4& cs,
- const b3Vector3& posA, b3Vector3& linVelA, b3Vector3& angVelA, float invMassA, const b3Matrix3x3& invInertiaA,
- const b3Vector3& posB, b3Vector3& linVelB, b3Vector3& angVelB, float invMassB, const b3Matrix3x3& invInertiaB,
- float maxRambdaDt[4], float minRambdaDt[4])
+static inline void b3SolveFriction(b3ContactConstraint4& cs,
+ const b3Vector3& posA, b3Vector3& linVelA, b3Vector3& angVelA, float invMassA, const b3Matrix3x3& invInertiaA,
+ const b3Vector3& posB, b3Vector3& linVelB, b3Vector3& angVelB, float invMassB, const b3Matrix3x3& invInertiaB,
+ float maxRambdaDt[4], float minRambdaDt[4])
{
-
- if( cs.m_fJacCoeffInv[0] == 0 && cs.m_fJacCoeffInv[0] == 0 ) return;
+ if (cs.m_fJacCoeffInv[0] == 0 && cs.m_fJacCoeffInv[0] == 0) return;
const b3Vector3& center = (const b3Vector3&)cs.m_center;
b3Vector3 n = -(const b3Vector3&)cs.m_linear;
b3Vector3 tangent[2];
- b3PlaneSpace1 (n, tangent[0],tangent[1]);
+ b3PlaneSpace1(n, tangent[0], tangent[1]);
b3Vector3 angular0, angular1, linear;
b3Vector3 r0 = center - posA;
b3Vector3 r1 = center - posB;
- for(int i=0; i<2; i++)
+ for (int i = 0; i < 2; i++)
{
- b3SetLinearAndAngular( tangent[i], r0, r1, linear, angular0, angular1 );
+ b3SetLinearAndAngular(tangent[i], r0, r1, linear, angular0, angular1);
float rambdaDt = b3CalcRelVel(linear, -linear, angular0, angular1,
- linVelA, angVelA, linVelB, angVelB );
+ linVelA, angVelA, linVelB, angVelB);
rambdaDt *= cs.m_fJacCoeffInv[i];
- {
- float prevSum = cs.m_fAppliedRambdaDt[i];
- float updated = prevSum;
- updated += rambdaDt;
- updated = b3Max( updated, minRambdaDt[i] );
- updated = b3Min( updated, maxRambdaDt[i] );
- rambdaDt = updated - prevSum;
- cs.m_fAppliedRambdaDt[i] = updated;
- }
+ {
+ float prevSum = cs.m_fAppliedRambdaDt[i];
+ float updated = prevSum;
+ updated += rambdaDt;
+ updated = b3Max(updated, minRambdaDt[i]);
+ updated = b3Min(updated, maxRambdaDt[i]);
+ rambdaDt = updated - prevSum;
+ cs.m_fAppliedRambdaDt[i] = updated;
+ }
- b3Vector3 linImp0 = invMassA*linear*rambdaDt;
- b3Vector3 linImp1 = invMassB*(-linear)*rambdaDt;
- b3Vector3 angImp0 = (invInertiaA* angular0)*rambdaDt;
- b3Vector3 angImp1 = (invInertiaB* angular1)*rambdaDt;
+ b3Vector3 linImp0 = invMassA * linear * rambdaDt;
+ b3Vector3 linImp1 = invMassB * (-linear) * rambdaDt;
+ b3Vector3 angImp0 = (invInertiaA * angular0) * rambdaDt;
+ b3Vector3 angImp1 = (invInertiaB * angular1) * rambdaDt;
#ifdef _WIN32
b3Assert(_finite(linImp0.getX()));
b3Assert(_finite(linImp1.getX()));
@@ -226,57 +209,45 @@ static inline void b3SolveFriction(b3ContactConstraint4& cs,
angVelB += angImp1;
}
- { // angular damping for point constraint
- b3Vector3 ab = ( posB - posA ).normalized();
- b3Vector3 ac = ( center - posA ).normalized();
- if( b3Dot( ab, ac ) > 0.95f || (invMassA == 0.f || invMassB == 0.f))
+ { // angular damping for point constraint
+ b3Vector3 ab = (posB - posA).normalized();
+ b3Vector3 ac = (center - posA).normalized();
+ if (b3Dot(ab, ac) > 0.95f || (invMassA == 0.f || invMassB == 0.f))
{
- float angNA = b3Dot( n, angVelA );
- float angNB = b3Dot( n, angVelB );
+ float angNA = b3Dot(n, angVelA);
+ float angNB = b3Dot(n, angVelB);
- angVelA -= (angNA*0.1f)*n;
- angVelB -= (angNB*0.1f)*n;
+ angVelA -= (angNA * 0.1f) * n;
+ angVelB -= (angNB * 0.1f) * n;
}
}
-
}
-
-
-
-
-struct b3SolveTask// : public ThreadPool::Task
+struct b3SolveTask // : public ThreadPool::Task
{
- b3SolveTask(b3AlignedObjectArray<b3RigidBodyData>& bodies,
- b3AlignedObjectArray<b3Inertia>& shapes,
+ b3SolveTask(b3AlignedObjectArray<b3RigidBodyData>& bodies,
+ b3AlignedObjectArray<b3Inertia>& shapes,
b3AlignedObjectArray<b3ContactConstraint4>& constraints,
int start, int nConstraints,
int maxNumBatches,
- b3AlignedObjectArray<int>* wgUsedBodies, int curWgidx
- )
- : m_bodies( bodies ), m_shapes( shapes ), m_constraints( constraints ),
- m_wgUsedBodies(wgUsedBodies),m_curWgidx(curWgidx),
-m_start( start ),
- m_nConstraints( nConstraints ),
- m_solveFriction( true ),
- m_maxNumBatches(maxNumBatches)
- {}
-
- unsigned short int getType(){ return 0; }
+ b3AlignedObjectArray<int>* wgUsedBodies, int curWgidx)
+ : m_bodies(bodies), m_shapes(shapes), m_constraints(constraints), m_wgUsedBodies(wgUsedBodies), m_curWgidx(curWgidx), m_start(start), m_nConstraints(nConstraints), m_solveFriction(true), m_maxNumBatches(maxNumBatches)
+ {
+ }
+
+ unsigned short int getType() { return 0; }
void run(int tIdx)
{
b3AlignedObjectArray<int> usedBodies;
//printf("run..............\n");
-
- for (int bb=0;bb<m_maxNumBatches;bb++)
+ for (int bb = 0; bb < m_maxNumBatches; bb++)
{
usedBodies.resize(0);
- for(int ic=m_nConstraints-1; ic>=0; ic--)
+ for (int ic = m_nConstraints - 1; ic >= 0; ic--)
//for(int ic=0; ic<m_nConstraints; ic++)
{
-
int i = m_start + ic;
if (m_constraints[i].m_batchIdx != bb)
continue;
@@ -298,87 +269,80 @@ m_start( start ),
//printf("ic(b)=%d, localBatch=%d\n",ic,localBatch);
}
#endif
- if (aIdx==10)
+ if (aIdx == 10)
{
//printf("ic(a)=%d, localBatch=%d\n",ic,localBatch);
}
- if (usedBodies.size()<(aIdx+1))
+ if (usedBodies.size() < (aIdx + 1))
{
- usedBodies.resize(aIdx+1,0);
+ usedBodies.resize(aIdx + 1, 0);
}
-
- if (usedBodies.size()<(bIdx+1))
+
+ if (usedBodies.size() < (bIdx + 1))
{
- usedBodies.resize(bIdx+1,0);
+ usedBodies.resize(bIdx + 1, 0);
}
if (bodyA.m_invMass)
{
- b3Assert(usedBodies[aIdx]==0);
+ b3Assert(usedBodies[aIdx] == 0);
usedBodies[aIdx]++;
}
-
+
if (bodyB.m_invMass)
{
- b3Assert(usedBodies[bIdx]==0);
+ b3Assert(usedBodies[bIdx] == 0);
usedBodies[bIdx]++;
}
-
- if( !m_solveFriction )
+ if (!m_solveFriction)
{
- float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};
- float minRambdaDt[4] = {0.f,0.f,0.f,0.f};
-
- b3SolveContact( m_constraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass, (const b3Matrix3x3 &)m_shapes[aIdx].m_invInertiaWorld,
- (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass, (const b3Matrix3x3 &)m_shapes[bIdx].m_invInertiaWorld,
- maxRambdaDt, minRambdaDt );
+ float maxRambdaDt[4] = {FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX};
+ float minRambdaDt[4] = {0.f, 0.f, 0.f, 0.f};
+ b3SolveContact(m_constraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass, (const b3Matrix3x3&)m_shapes[aIdx].m_invInertiaWorld,
+ (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass, (const b3Matrix3x3&)m_shapes[bIdx].m_invInertiaWorld,
+ maxRambdaDt, minRambdaDt);
}
else
{
- float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};
- float minRambdaDt[4] = {0.f,0.f,0.f,0.f};
+ float maxRambdaDt[4] = {FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX};
+ float minRambdaDt[4] = {0.f, 0.f, 0.f, 0.f};
float sum = 0;
- for(int j=0; j<4; j++)
+ for (int j = 0; j < 4; j++)
{
- sum +=m_constraints[i].m_appliedRambdaDt[j];
+ sum += m_constraints[i].m_appliedRambdaDt[j];
}
frictionCoeff = 0.7f;
- for(int j=0; j<4; j++)
+ for (int j = 0; j < 4; j++)
{
- maxRambdaDt[j] = frictionCoeff*sum;
+ maxRambdaDt[j] = frictionCoeff * sum;
minRambdaDt[j] = -maxRambdaDt[j];
}
- b3SolveFriction( m_constraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass,(const b3Matrix3x3 &) m_shapes[aIdx].m_invInertiaWorld,
- (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass,(const b3Matrix3x3 &) m_shapes[bIdx].m_invInertiaWorld,
- maxRambdaDt, minRambdaDt );
-
+ b3SolveFriction(m_constraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass, (const b3Matrix3x3&)m_shapes[aIdx].m_invInertiaWorld,
+ (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass, (const b3Matrix3x3&)m_shapes[bIdx].m_invInertiaWorld,
+ maxRambdaDt, minRambdaDt);
}
}
if (m_wgUsedBodies)
{
- if (m_wgUsedBodies[m_curWgidx].size()<usedBodies.size())
+ if (m_wgUsedBodies[m_curWgidx].size() < usedBodies.size())
{
m_wgUsedBodies[m_curWgidx].resize(usedBodies.size());
}
- for (int i=0;i<usedBodies.size();i++)
+ for (int i = 0; i < usedBodies.size(); i++)
{
if (usedBodies[i])
{
//printf("cell %d uses body %d\n", m_curWgidx,i);
- m_wgUsedBodies[m_curWgidx][i]=1;
+ m_wgUsedBodies[m_curWgidx][i] = 1;
}
}
}
-
}
-
-
-
}
b3AlignedObjectArray<b3RigidBodyData>& m_bodies;
@@ -397,24 +361,22 @@ void b3CpuRigidBodyPipeline::solveContactConstraints()
int m_nIterations = 4;
b3AlignedObjectArray<b3ContactConstraint4> contactConstraints;
-// const b3AlignedObjectArray<b3Contact4Data>& contacts = m_data->m_np->getContacts();
+ // const b3AlignedObjectArray<b3Contact4Data>& contacts = m_data->m_np->getContacts();
int n = contactConstraints.size();
//convert contacts...
-
-
int maxNumBatches = 250;
- for(int iter=0; iter<m_nIterations; iter++)
+ for (int iter = 0; iter < m_nIterations; iter++)
{
- b3SolveTask task( m_data->m_rigidBodies, m_data->m_inertias, contactConstraints, 0, n ,maxNumBatches,0,0);
+ b3SolveTask task(m_data->m_rigidBodies, m_data->m_inertias, contactConstraints, 0, n, maxNumBatches, 0, 0);
task.m_solveFriction = false;
task.run(0);
}
- for(int iter=0; iter<m_nIterations; iter++)
+ for (int iter = 0; iter < m_nIterations; iter++)
{
- b3SolveTask task( m_data->m_rigidBodies, m_data->m_inertias, contactConstraints, 0, n ,maxNumBatches,0,0);
+ b3SolveTask task(m_data->m_rigidBodies, m_data->m_inertias, contactConstraints, 0, n, maxNumBatches, 0, 0);
task.m_solveFriction = true;
task.run(0);
}
@@ -422,53 +384,51 @@ void b3CpuRigidBodyPipeline::solveContactConstraints()
void b3CpuRigidBodyPipeline::integrate(float deltaTime)
{
- float angDamping=0.f;
- b3Vector3 gravityAcceleration=b3MakeVector3(0,-9,0);
+ float angDamping = 0.f;
+ b3Vector3 gravityAcceleration = b3MakeVector3(0, -9, 0);
//integrate transforms (external forces/gravity should be moved into constraint solver)
- for (int i=0;i<m_data->m_rigidBodies.size();i++)
+ for (int i = 0; i < m_data->m_rigidBodies.size(); i++)
{
- b3IntegrateTransform(&m_data->m_rigidBodies[i],deltaTime,angDamping,gravityAcceleration);
+ b3IntegrateTransform(&m_data->m_rigidBodies[i], deltaTime, angDamping, gravityAcceleration);
}
-
}
-int b3CpuRigidBodyPipeline::registerPhysicsInstance(float mass, const float* position, const float* orientation, int collidableIndex, int userData)
+int b3CpuRigidBodyPipeline::registerPhysicsInstance(float mass, const float* position, const float* orientation, int collidableIndex, int userData)
{
b3RigidBodyData body;
int bodyIndex = m_data->m_rigidBodies.size();
- body.m_invMass = mass ? 1.f/mass : 0.f;
- body.m_angVel.setValue(0,0,0);
+ body.m_invMass = mass ? 1.f / mass : 0.f;
+ body.m_angVel.setValue(0, 0, 0);
body.m_collidableIdx = collidableIndex;
body.m_frictionCoeff = 0.3f;
- body.m_linVel.setValue(0,0,0);
- body.m_pos.setValue(position[0],position[1],position[2]);
- body.m_quat.setValue(orientation[0],orientation[1],orientation[2],orientation[3]);
+ body.m_linVel.setValue(0, 0, 0);
+ body.m_pos.setValue(position[0], position[1], position[2]);
+ body.m_quat.setValue(orientation[0], orientation[1], orientation[2], orientation[3]);
body.m_restituitionCoeff = 0.f;
m_data->m_rigidBodies.push_back(body);
-
- if (collidableIndex>=0)
+ if (collidableIndex >= 0)
{
b3Aabb& worldAabb = m_data->m_aabbWorldSpace.expand();
b3Aabb localAabb = m_data->m_np->getLocalSpaceAabb(collidableIndex);
- b3Vector3 localAabbMin=b3MakeVector3(localAabb.m_min[0],localAabb.m_min[1],localAabb.m_min[2]);
- b3Vector3 localAabbMax=b3MakeVector3(localAabb.m_max[0],localAabb.m_max[1],localAabb.m_max[2]);
-
+ b3Vector3 localAabbMin = b3MakeVector3(localAabb.m_min[0], localAabb.m_min[1], localAabb.m_min[2]);
+ b3Vector3 localAabbMax = b3MakeVector3(localAabb.m_max[0], localAabb.m_max[1], localAabb.m_max[2]);
+
b3Scalar margin = 0.01f;
b3Transform t;
t.setIdentity();
- t.setOrigin(b3MakeVector3(position[0],position[1],position[2]));
- t.setRotation(b3Quaternion(orientation[0],orientation[1],orientation[2],orientation[3]));
- b3TransformAabb(localAabbMin,localAabbMax, margin,t,worldAabb.m_minVec,worldAabb.m_maxVec);
-
- m_data->m_bp->createProxy(worldAabb.m_minVec,worldAabb.m_maxVec,bodyIndex,0,1,1);
-// b3Vector3 aabbMin,aabbMax;
- // m_data->m_bp->getAabb(bodyIndex,aabbMin,aabbMax);
+ t.setOrigin(b3MakeVector3(position[0], position[1], position[2]));
+ t.setRotation(b3Quaternion(orientation[0], orientation[1], orientation[2], orientation[3]));
+ b3TransformAabb(localAabbMin, localAabbMax, margin, t, worldAabb.m_minVec, worldAabb.m_maxVec);
- } else
+ m_data->m_bp->createProxy(worldAabb.m_minVec, worldAabb.m_maxVec, bodyIndex, 0, 1, 1);
+ // b3Vector3 aabbMin,aabbMax;
+ // m_data->m_bp->getAabb(bodyIndex,aabbMin,aabbMax);
+ }
+ else
{
b3Error("registerPhysicsInstance using invalid collidableIndex\n");
}
@@ -476,13 +436,12 @@ int b3CpuRigidBodyPipeline::registerPhysicsInstance(float mass, const float* po
return bodyIndex;
}
-
const struct b3RigidBodyData* b3CpuRigidBodyPipeline::getBodyBuffer() const
{
return m_data->m_rigidBodies.size() ? &m_data->m_rigidBodies[0] : 0;
}
-int b3CpuRigidBodyPipeline::getNumBodies() const
+int b3CpuRigidBodyPipeline::getNumBodies() const
{
return m_data->m_rigidBodies.size();
}
diff --git a/thirdparty/bullet/Bullet3Dynamics/b3CpuRigidBodyPipeline.h b/thirdparty/bullet/Bullet3Dynamics/b3CpuRigidBodyPipeline.h
index 2f3c2ae77e..9c65419f26 100644
--- a/thirdparty/bullet/Bullet3Dynamics/b3CpuRigidBodyPipeline.h
+++ b/thirdparty/bullet/Bullet3Dynamics/b3CpuRigidBodyPipeline.h
@@ -16,52 +16,47 @@ subject to the following restrictions:
#ifndef B3_CPU_RIGIDBODY_PIPELINE_H
#define B3_CPU_RIGIDBODY_PIPELINE_H
-
-
#include "Bullet3Common/b3AlignedObjectArray.h"
#include "Bullet3Collision/NarrowPhaseCollision/b3RaycastInfo.h"
class b3CpuRigidBodyPipeline
{
protected:
- struct b3CpuRigidBodyPipelineInternalData* m_data;
+ struct b3CpuRigidBodyPipelineInternalData* m_data;
int allocateCollidable();
public:
-
-
b3CpuRigidBodyPipeline(class b3CpuNarrowPhase* narrowphase, struct b3DynamicBvhBroadphase* broadphaseDbvt, const struct b3Config& config);
virtual ~b3CpuRigidBodyPipeline();
- virtual void stepSimulation(float deltaTime);
- virtual void integrate(float timeStep);
- virtual void updateAabbWorldSpace();
- virtual void computeOverlappingPairs();
- virtual void computeContactPoints();
- virtual void solveContactConstraints();
-
- int registerConvexPolyhedron(class b3ConvexUtility* convex);
-
- int registerPhysicsInstance(float mass, const float* position, const float* orientation, int collisionShapeIndex, int userData);
- void writeAllInstancesToGpu();
- void copyConstraintsToHost();
- void setGravity(const float* grav);
- void reset();
-
- int createPoint2PointConstraint(int bodyA, int bodyB, const float* pivotInA, const float* pivotInB,float breakingThreshold);
+ virtual void stepSimulation(float deltaTime);
+ virtual void integrate(float timeStep);
+ virtual void updateAabbWorldSpace();
+ virtual void computeOverlappingPairs();
+ virtual void computeContactPoints();
+ virtual void solveContactConstraints();
+
+ int registerConvexPolyhedron(class b3ConvexUtility* convex);
+
+ int registerPhysicsInstance(float mass, const float* position, const float* orientation, int collisionShapeIndex, int userData);
+ void writeAllInstancesToGpu();
+ void copyConstraintsToHost();
+ void setGravity(const float* grav);
+ void reset();
+
+ int createPoint2PointConstraint(int bodyA, int bodyB, const float* pivotInA, const float* pivotInB, float breakingThreshold);
int createFixedConstraint(int bodyA, int bodyB, const float* pivotInA, const float* pivotInB, const float* relTargetAB, float breakingThreshold);
void removeConstraintByUid(int uid);
- void addConstraint(class b3TypedConstraint* constraint);
- void removeConstraint(b3TypedConstraint* constraint);
+ void addConstraint(class b3TypedConstraint* constraint);
+ void removeConstraint(b3TypedConstraint* constraint);
- void castRays(const b3AlignedObjectArray<b3RayInfo>& rays, b3AlignedObjectArray<b3RayHit>& hitResults);
+ void castRays(const b3AlignedObjectArray<b3RayInfo>& rays, b3AlignedObjectArray<b3RayHit>& hitResults);
const struct b3RigidBodyData* getBodyBuffer() const;
- int getNumBodies() const;
-
+ int getNumBodies() const;
};
-#endif //B3_CPU_RIGIDBODY_PIPELINE_H \ No newline at end of file
+#endif //B3_CPU_RIGIDBODY_PIPELINE_H \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3Dynamics/shared/b3ContactConstraint4.h b/thirdparty/bullet/Bullet3Dynamics/shared/b3ContactConstraint4.h
index 68cf65e312..cf2eed0e7c 100644
--- a/thirdparty/bullet/Bullet3Dynamics/shared/b3ContactConstraint4.h
+++ b/thirdparty/bullet/Bullet3Dynamics/shared/b3ContactConstraint4.h
@@ -5,30 +5,27 @@
typedef struct b3ContactConstraint4 b3ContactConstraint4_t;
-
struct b3ContactConstraint4
{
-
- b3Float4 m_linear;//normal?
+ b3Float4 m_linear; //normal?
b3Float4 m_worldPos[4];
- b3Float4 m_center; // friction
+ b3Float4 m_center; // friction
float m_jacCoeffInv[4];
float m_b[4];
float m_appliedRambdaDt[4];
- float m_fJacCoeffInv[2]; // friction
- float m_fAppliedRambdaDt[2]; // friction
+ float m_fJacCoeffInv[2]; // friction
+ float m_fAppliedRambdaDt[2]; // friction
unsigned int m_bodyA;
unsigned int m_bodyB;
- int m_batchIdx;
+ int m_batchIdx;
unsigned int m_paddings;
-
};
//inline void setFrictionCoeff(float value) { m_linear[3] = value; }
-inline float b3GetFrictionCoeff(b3ContactConstraint4_t* constraint)
+inline float b3GetFrictionCoeff(b3ContactConstraint4_t* constraint)
{
- return constraint->m_linear.w;
+ return constraint->m_linear.w;
}
-#endif //B3_CONTACT_CONSTRAINT5_H
+#endif //B3_CONTACT_CONSTRAINT5_H
diff --git a/thirdparty/bullet/Bullet3Dynamics/shared/b3ConvertConstraint4.h b/thirdparty/bullet/Bullet3Dynamics/shared/b3ConvertConstraint4.h
index 805a2bd3ea..3e72f1c3f2 100644
--- a/thirdparty/bullet/Bullet3Dynamics/shared/b3ConvertConstraint4.h
+++ b/thirdparty/bullet/Bullet3Dynamics/shared/b3ConvertConstraint4.h
@@ -4,89 +4,84 @@
#include "Bullet3Dynamics/shared/b3ContactConstraint4.h"
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
-
-void b3PlaneSpace1 (b3Float4ConstArg n, b3Float4* p, b3Float4* q);
- void b3PlaneSpace1 (b3Float4ConstArg n, b3Float4* p, b3Float4* q)
+void b3PlaneSpace1(b3Float4ConstArg n, b3Float4* p, b3Float4* q);
+void b3PlaneSpace1(b3Float4ConstArg n, b3Float4* p, b3Float4* q)
{
- if (b3Fabs(n.z) > 0.70710678f) {
- // choose p in y-z plane
- float a = n.y*n.y + n.z*n.z;
- float k = 1.f/sqrt(a);
- p[0].x = 0;
- p[0].y = -n.z*k;
- p[0].z = n.y*k;
- // set q = n x p
- q[0].x = a*k;
- q[0].y = -n.x*p[0].z;
- q[0].z = n.x*p[0].y;
- }
- else {
- // choose p in x-y plane
- float a = n.x*n.x + n.y*n.y;
- float k = 1.f/sqrt(a);
- p[0].x = -n.y*k;
- p[0].y = n.x*k;
- p[0].z = 0;
- // set q = n x p
- q[0].x = -n.z*p[0].y;
- q[0].y = n.z*p[0].x;
- q[0].z = a*k;
- }
+ if (b3Fabs(n.z) > 0.70710678f)
+ {
+ // choose p in y-z plane
+ float a = n.y * n.y + n.z * n.z;
+ float k = 1.f / sqrt(a);
+ p[0].x = 0;
+ p[0].y = -n.z * k;
+ p[0].z = n.y * k;
+ // set q = n x p
+ q[0].x = a * k;
+ q[0].y = -n.x * p[0].z;
+ q[0].z = n.x * p[0].y;
+ }
+ else
+ {
+ // choose p in x-y plane
+ float a = n.x * n.x + n.y * n.y;
+ float k = 1.f / sqrt(a);
+ p[0].x = -n.y * k;
+ p[0].y = n.x * k;
+ p[0].z = 0;
+ // set q = n x p
+ q[0].x = -n.z * p[0].y;
+ q[0].y = n.z * p[0].x;
+ q[0].z = a * k;
+ }
}
-
-
-void setLinearAndAngular( b3Float4ConstArg n, b3Float4ConstArg r0, b3Float4ConstArg r1, b3Float4* linear, b3Float4* angular0, b3Float4* angular1)
+void setLinearAndAngular(b3Float4ConstArg n, b3Float4ConstArg r0, b3Float4ConstArg r1, b3Float4* linear, b3Float4* angular0, b3Float4* angular1)
{
- *linear = b3MakeFloat4(n.x,n.y,n.z,0.f);
+ *linear = b3MakeFloat4(n.x, n.y, n.z, 0.f);
*angular0 = b3Cross3(r0, n);
*angular1 = -b3Cross3(r1, n);
}
-
-float calcRelVel( b3Float4ConstArg l0, b3Float4ConstArg l1, b3Float4ConstArg a0, b3Float4ConstArg a1, b3Float4ConstArg linVel0,
- b3Float4ConstArg angVel0, b3Float4ConstArg linVel1, b3Float4ConstArg angVel1 )
+float calcRelVel(b3Float4ConstArg l0, b3Float4ConstArg l1, b3Float4ConstArg a0, b3Float4ConstArg a1, b3Float4ConstArg linVel0,
+ b3Float4ConstArg angVel0, b3Float4ConstArg linVel1, b3Float4ConstArg angVel1)
{
return b3Dot3F4(l0, linVel0) + b3Dot3F4(a0, angVel0) + b3Dot3F4(l1, linVel1) + b3Dot3F4(a1, angVel1);
}
-
float calcJacCoeff(b3Float4ConstArg linear0, b3Float4ConstArg linear1, b3Float4ConstArg angular0, b3Float4ConstArg angular1,
- float invMass0, const b3Mat3x3* invInertia0, float invMass1, const b3Mat3x3* invInertia1)
+ float invMass0, const b3Mat3x3* invInertia0, float invMass1, const b3Mat3x3* invInertia1)
{
// linear0,1 are normlized
- float jmj0 = invMass0;//b3Dot3F4(linear0, linear0)*invMass0;
- float jmj1 = b3Dot3F4(mtMul3(angular0,*invInertia0), angular0);
- float jmj2 = invMass1;//b3Dot3F4(linear1, linear1)*invMass1;
- float jmj3 = b3Dot3F4(mtMul3(angular1,*invInertia1), angular1);
- return -1.f/(jmj0+jmj1+jmj2+jmj3);
+ float jmj0 = invMass0; //b3Dot3F4(linear0, linear0)*invMass0;
+ float jmj1 = b3Dot3F4(mtMul3(angular0, *invInertia0), angular0);
+ float jmj2 = invMass1; //b3Dot3F4(linear1, linear1)*invMass1;
+ float jmj3 = b3Dot3F4(mtMul3(angular1, *invInertia1), angular1);
+ return -1.f / (jmj0 + jmj1 + jmj2 + jmj3);
}
-
-void setConstraint4( b3Float4ConstArg posA, b3Float4ConstArg linVelA, b3Float4ConstArg angVelA, float invMassA, b3Mat3x3ConstArg invInertiaA,
- b3Float4ConstArg posB, b3Float4ConstArg linVelB, b3Float4ConstArg angVelB, float invMassB, b3Mat3x3ConstArg invInertiaB,
- __global struct b3Contact4Data* src, float dt, float positionDrift, float positionConstraintCoeff,
- b3ContactConstraint4_t* dstC )
+void setConstraint4(b3Float4ConstArg posA, b3Float4ConstArg linVelA, b3Float4ConstArg angVelA, float invMassA, b3Mat3x3ConstArg invInertiaA,
+ b3Float4ConstArg posB, b3Float4ConstArg linVelB, b3Float4ConstArg angVelB, float invMassB, b3Mat3x3ConstArg invInertiaB,
+ __global struct b3Contact4Data* src, float dt, float positionDrift, float positionConstraintCoeff,
+ b3ContactConstraint4_t* dstC)
{
dstC->m_bodyA = abs(src->m_bodyAPtrAndSignBit);
dstC->m_bodyB = abs(src->m_bodyBPtrAndSignBit);
- float dtInv = 1.f/dt;
- for(int ic=0; ic<4; ic++)
+ float dtInv = 1.f / dt;
+ for (int ic = 0; ic < 4; ic++)
{
dstC->m_appliedRambdaDt[ic] = 0.f;
}
dstC->m_fJacCoeffInv[0] = dstC->m_fJacCoeffInv[1] = 0.f;
-
dstC->m_linear = src->m_worldNormalOnB;
- dstC->m_linear.w = 0.7f ;//src->getFrictionCoeff() );
- for(int ic=0; ic<4; ic++)
+ dstC->m_linear.w = 0.7f; //src->getFrictionCoeff() );
+ for (int ic = 0; ic < 4; ic++)
{
b3Float4 r0 = src->m_worldPosB[ic] - posA;
b3Float4 r1 = src->m_worldPosB[ic] - posB;
- if( ic >= src->m_worldNormalOnB.w )//npoints
+ if (ic >= src->m_worldNormalOnB.w) //npoints
{
dstC->m_jacCoeffInv[ic] = 0.f;
continue;
@@ -98,56 +93,56 @@ void setConstraint4( b3Float4ConstArg posA, b3Float4ConstArg linVelA, b3Float4Co
setLinearAndAngular(src->m_worldNormalOnB, r0, r1, &linear, &angular0, &angular1);
dstC->m_jacCoeffInv[ic] = calcJacCoeff(linear, -linear, angular0, angular1,
- invMassA, &invInertiaA, invMassB, &invInertiaB );
+ invMassA, &invInertiaA, invMassB, &invInertiaB);
relVelN = calcRelVel(linear, -linear, angular0, angular1,
- linVelA, angVelA, linVelB, angVelB);
+ linVelA, angVelA, linVelB, angVelB);
- float e = 0.f;//src->getRestituitionCoeff();
- if( relVelN*relVelN < 0.004f ) e = 0.f;
+ float e = 0.f; //src->getRestituitionCoeff();
+ if (relVelN * relVelN < 0.004f) e = 0.f;
- dstC->m_b[ic] = e*relVelN;
+ dstC->m_b[ic] = e * relVelN;
//float penetration = src->m_worldPosB[ic].w;
- dstC->m_b[ic] += (src->m_worldPosB[ic].w + positionDrift)*positionConstraintCoeff*dtInv;
+ dstC->m_b[ic] += (src->m_worldPosB[ic].w + positionDrift) * positionConstraintCoeff * dtInv;
dstC->m_appliedRambdaDt[ic] = 0.f;
}
}
- if( src->m_worldNormalOnB.w > 0 )//npoints
- { // prepare friction
- b3Float4 center = b3MakeFloat4(0.f,0.f,0.f,0.f);
- for(int i=0; i<src->m_worldNormalOnB.w; i++)
+ if (src->m_worldNormalOnB.w > 0) //npoints
+ { // prepare friction
+ b3Float4 center = b3MakeFloat4(0.f, 0.f, 0.f, 0.f);
+ for (int i = 0; i < src->m_worldNormalOnB.w; i++)
center += src->m_worldPosB[i];
center /= (float)src->m_worldNormalOnB.w;
b3Float4 tangent[2];
- b3PlaneSpace1(src->m_worldNormalOnB,&tangent[0],&tangent[1]);
-
+ b3PlaneSpace1(src->m_worldNormalOnB, &tangent[0], &tangent[1]);
+
b3Float4 r[2];
r[0] = center - posA;
r[1] = center - posB;
- for(int i=0; i<2; i++)
+ for (int i = 0; i < 2; i++)
{
b3Float4 linear, angular0, angular1;
setLinearAndAngular(tangent[i], r[0], r[1], &linear, &angular0, &angular1);
dstC->m_fJacCoeffInv[i] = calcJacCoeff(linear, -linear, angular0, angular1,
- invMassA, &invInertiaA, invMassB, &invInertiaB );
+ invMassA, &invInertiaA, invMassB, &invInertiaB);
dstC->m_fAppliedRambdaDt[i] = 0.f;
}
dstC->m_center = center;
}
- for(int i=0; i<4; i++)
+ for (int i = 0; i < 4; i++)
{
- if( i<src->m_worldNormalOnB.w )
+ if (i < src->m_worldNormalOnB.w)
{
dstC->m_worldPos[i] = src->m_worldPosB[i];
}
else
{
- dstC->m_worldPos[i] = b3MakeFloat4(0.f,0.f,0.f,0.f);
+ dstC->m_worldPos[i] = b3MakeFloat4(0.f, 0.f, 0.f, 0.f);
}
}
}
diff --git a/thirdparty/bullet/Bullet3Dynamics/shared/b3Inertia.h b/thirdparty/bullet/Bullet3Dynamics/shared/b3Inertia.h
index 96fe9f8b39..602a1335aa 100644
--- a/thirdparty/bullet/Bullet3Dynamics/shared/b3Inertia.h
+++ b/thirdparty/bullet/Bullet3Dynamics/shared/b3Inertia.h
@@ -11,5 +11,4 @@ struct b3Inertia
b3Mat3x3 m_initInvInertia;
};
-
-#endif //B3_INERTIA_H \ No newline at end of file
+#endif //B3_INERTIA_H \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3Dynamics/shared/b3IntegrateTransforms.h b/thirdparty/bullet/Bullet3Dynamics/shared/b3IntegrateTransforms.h
index e96f90d3f3..56d9118f95 100644
--- a/thirdparty/bullet/Bullet3Dynamics/shared/b3IntegrateTransforms.h
+++ b/thirdparty/bullet/Bullet3Dynamics/shared/b3IntegrateTransforms.h
@@ -2,11 +2,8 @@
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
-
-
-inline void integrateSingleTransform( __global b3RigidBodyData_t* bodies,int nodeID, float timeStep, float angularDamping, b3Float4ConstArg gravityAcceleration)
+inline void integrateSingleTransform(__global b3RigidBodyData_t* bodies, int nodeID, float timeStep, float angularDamping, b3Float4ConstArg gravityAcceleration)
{
-
if (bodies[nodeID].m_invMass != 0.f)
{
float BT_GPU_ANGULAR_MOTION_THRESHOLD = (0.25f * 3.14159254f);
@@ -18,27 +15,27 @@ inline void integrateSingleTransform( __global b3RigidBodyData_t* bodies,int nod
bodies[nodeID].m_angVel.x *= angularDamping;
bodies[nodeID].m_angVel.y *= angularDamping;
bodies[nodeID].m_angVel.z *= angularDamping;
-
+
b3Float4 angvel = bodies[nodeID].m_angVel;
float fAngle = b3Sqrt(b3Dot3F4(angvel, angvel));
-
+
//limit the angular motion
- if(fAngle*timeStep > BT_GPU_ANGULAR_MOTION_THRESHOLD)
+ if (fAngle * timeStep > BT_GPU_ANGULAR_MOTION_THRESHOLD)
{
fAngle = BT_GPU_ANGULAR_MOTION_THRESHOLD / timeStep;
}
- if(fAngle < 0.001f)
+ if (fAngle < 0.001f)
{
// use Taylor's expansions of sync function
- axis = angvel * (0.5f*timeStep-(timeStep*timeStep*timeStep)*0.020833333333f * fAngle * fAngle);
+ axis = angvel * (0.5f * timeStep - (timeStep * timeStep * timeStep) * 0.020833333333f * fAngle * fAngle);
}
else
{
// sync(fAngle) = sin(c*fAngle)/t
- axis = angvel * ( b3Sin(0.5f * fAngle * timeStep) / fAngle);
+ axis = angvel * (b3Sin(0.5f * fAngle * timeStep) / fAngle);
}
-
+
b3Quat dorn;
dorn.x = axis.x;
dorn.y = axis.y;
@@ -47,23 +44,21 @@ inline void integrateSingleTransform( __global b3RigidBodyData_t* bodies,int nod
b3Quat orn0 = bodies[nodeID].m_quat;
b3Quat predictedOrn = b3QuatMul(dorn, orn0);
predictedOrn = b3QuatNormalized(predictedOrn);
- bodies[nodeID].m_quat=predictedOrn;
+ bodies[nodeID].m_quat = predictedOrn;
}
- //linear velocity
- bodies[nodeID].m_pos += bodies[nodeID].m_linVel * timeStep;
-
+ //linear velocity
+ bodies[nodeID].m_pos += bodies[nodeID].m_linVel * timeStep;
+
//apply gravity
bodies[nodeID].m_linVel += gravityAcceleration * timeStep;
-
}
-
}
-inline void b3IntegrateTransform( __global b3RigidBodyData_t* body, float timeStep, float angularDamping, b3Float4ConstArg gravityAcceleration)
+inline void b3IntegrateTransform(__global b3RigidBodyData_t* body, float timeStep, float angularDamping, b3Float4ConstArg gravityAcceleration)
{
float BT_GPU_ANGULAR_MOTION_THRESHOLD = (0.25f * 3.14159254f);
-
- if( (body->m_invMass != 0.f))
+
+ if ((body->m_invMass != 0.f))
{
//angular velocity
{
@@ -72,23 +67,23 @@ inline void b3IntegrateTransform( __global b3RigidBodyData_t* body, float timeSt
body->m_angVel.x *= angularDamping;
body->m_angVel.y *= angularDamping;
body->m_angVel.z *= angularDamping;
-
+
b3Float4 angvel = body->m_angVel;
float fAngle = b3Sqrt(b3Dot3F4(angvel, angvel));
//limit the angular motion
- if(fAngle*timeStep > BT_GPU_ANGULAR_MOTION_THRESHOLD)
+ if (fAngle * timeStep > BT_GPU_ANGULAR_MOTION_THRESHOLD)
{
fAngle = BT_GPU_ANGULAR_MOTION_THRESHOLD / timeStep;
}
- if(fAngle < 0.001f)
+ if (fAngle < 0.001f)
{
// use Taylor's expansions of sync function
- axis = angvel * (0.5f*timeStep-(timeStep*timeStep*timeStep)*0.020833333333f * fAngle * fAngle);
+ axis = angvel * (0.5f * timeStep - (timeStep * timeStep * timeStep) * 0.020833333333f * fAngle * fAngle);
}
else
{
// sync(fAngle) = sin(c*fAngle)/t
- axis = angvel * ( b3Sin(0.5f * fAngle * timeStep) / fAngle);
+ axis = angvel * (b3Sin(0.5f * fAngle * timeStep) / fAngle);
}
b3Quat dorn;
dorn.x = axis.x;
@@ -99,15 +94,13 @@ inline void b3IntegrateTransform( __global b3RigidBodyData_t* body, float timeSt
b3Quat predictedOrn = b3QuatMul(dorn, orn0);
predictedOrn = b3QuatNormalized(predictedOrn);
- body->m_quat=predictedOrn;
+ body->m_quat = predictedOrn;
}
//apply gravity
body->m_linVel += gravityAcceleration * timeStep;
- //linear velocity
- body->m_pos += body->m_linVel * timeStep;
-
+ //linear velocity
+ body->m_pos += body->m_linVel * timeStep;
}
-
}
diff --git a/thirdparty/bullet/Bullet3Geometry/b3AabbUtil.h b/thirdparty/bullet/Bullet3Geometry/b3AabbUtil.h
index 4c72d5bbfc..396a401450 100644
--- a/thirdparty/bullet/Bullet3Geometry/b3AabbUtil.h
+++ b/thirdparty/bullet/Bullet3Geometry/b3AabbUtil.h
@@ -12,8 +12,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
-
#ifndef B3_AABB_UTIL2
#define B3_AABB_UTIL2
@@ -21,20 +19,18 @@ subject to the following restrictions:
#include "Bullet3Common/b3Vector3.h"
#include "Bullet3Common/b3MinMax.h"
-
-
-B3_FORCE_INLINE void b3AabbExpand (b3Vector3& aabbMin,
- b3Vector3& aabbMax,
- const b3Vector3& expansionMin,
- const b3Vector3& expansionMax)
+B3_FORCE_INLINE void b3AabbExpand(b3Vector3& aabbMin,
+ b3Vector3& aabbMax,
+ const b3Vector3& expansionMin,
+ const b3Vector3& expansionMax)
{
aabbMin = aabbMin + expansionMin;
aabbMax = aabbMax + expansionMax;
}
/// conservative test for overlap between two aabbs
-B3_FORCE_INLINE bool b3TestPointAgainstAabb2(const b3Vector3 &aabbMin1, const b3Vector3 &aabbMax1,
- const b3Vector3 &point)
+B3_FORCE_INLINE bool b3TestPointAgainstAabb2(const b3Vector3& aabbMin1, const b3Vector3& aabbMax1,
+ const b3Vector3& point)
{
bool overlap = true;
overlap = (aabbMin1.getX() > point.getX() || aabbMax1.getX() < point.getX()) ? false : overlap;
@@ -43,10 +39,9 @@ B3_FORCE_INLINE bool b3TestPointAgainstAabb2(const b3Vector3 &aabbMin1, const b3
return overlap;
}
-
/// conservative test for overlap between two aabbs
-B3_FORCE_INLINE bool b3TestAabbAgainstAabb2(const b3Vector3 &aabbMin1, const b3Vector3 &aabbMax1,
- const b3Vector3 &aabbMin2, const b3Vector3 &aabbMax2)
+B3_FORCE_INLINE bool b3TestAabbAgainstAabb2(const b3Vector3& aabbMin1, const b3Vector3& aabbMax1,
+ const b3Vector3& aabbMin2, const b3Vector3& aabbMax2)
{
bool overlap = true;
overlap = (aabbMin1.getX() > aabbMax2.getX() || aabbMax1.getX() < aabbMin2.getX()) ? false : overlap;
@@ -56,52 +51,49 @@ B3_FORCE_INLINE bool b3TestAabbAgainstAabb2(const b3Vector3 &aabbMin1, const b3V
}
/// conservative test for overlap between triangle and aabb
-B3_FORCE_INLINE bool b3TestTriangleAgainstAabb2(const b3Vector3 *vertices,
- const b3Vector3 &aabbMin, const b3Vector3 &aabbMax)
+B3_FORCE_INLINE bool b3TestTriangleAgainstAabb2(const b3Vector3* vertices,
+ const b3Vector3& aabbMin, const b3Vector3& aabbMax)
{
- const b3Vector3 &p1 = vertices[0];
- const b3Vector3 &p2 = vertices[1];
- const b3Vector3 &p3 = vertices[2];
+ const b3Vector3& p1 = vertices[0];
+ const b3Vector3& p2 = vertices[1];
+ const b3Vector3& p3 = vertices[2];
if (b3Min(b3Min(p1[0], p2[0]), p3[0]) > aabbMax[0]) return false;
if (b3Max(b3Max(p1[0], p2[0]), p3[0]) < aabbMin[0]) return false;
if (b3Min(b3Min(p1[2], p2[2]), p3[2]) > aabbMax[2]) return false;
if (b3Max(b3Max(p1[2], p2[2]), p3[2]) < aabbMin[2]) return false;
-
+
if (b3Min(b3Min(p1[1], p2[1]), p3[1]) > aabbMax[1]) return false;
if (b3Max(b3Max(p1[1], p2[1]), p3[1]) < aabbMin[1]) return false;
return true;
}
-
-B3_FORCE_INLINE int b3Outcode(const b3Vector3& p,const b3Vector3& halfExtent)
+B3_FORCE_INLINE int b3Outcode(const b3Vector3& p, const b3Vector3& halfExtent)
{
- return (p.getX() < -halfExtent.getX() ? 0x01 : 0x0) |
- (p.getX() > halfExtent.getX() ? 0x08 : 0x0) |
- (p.getY() < -halfExtent.getY() ? 0x02 : 0x0) |
- (p.getY() > halfExtent.getY() ? 0x10 : 0x0) |
- (p.getZ() < -halfExtent.getZ() ? 0x4 : 0x0) |
- (p.getZ() > halfExtent.getZ() ? 0x20 : 0x0);
+ return (p.getX() < -halfExtent.getX() ? 0x01 : 0x0) |
+ (p.getX() > halfExtent.getX() ? 0x08 : 0x0) |
+ (p.getY() < -halfExtent.getY() ? 0x02 : 0x0) |
+ (p.getY() > halfExtent.getY() ? 0x10 : 0x0) |
+ (p.getZ() < -halfExtent.getZ() ? 0x4 : 0x0) |
+ (p.getZ() > halfExtent.getZ() ? 0x20 : 0x0);
}
-
-
B3_FORCE_INLINE bool b3RayAabb2(const b3Vector3& rayFrom,
- const b3Vector3& rayInvDirection,
- const unsigned int raySign[3],
- const b3Vector3 bounds[2],
- b3Scalar& tmin,
- b3Scalar lambda_min,
- b3Scalar lambda_max)
+ const b3Vector3& rayInvDirection,
+ const unsigned int raySign[3],
+ const b3Vector3 bounds[2],
+ b3Scalar& tmin,
+ b3Scalar lambda_min,
+ b3Scalar lambda_max)
{
b3Scalar tmax, tymin, tymax, tzmin, tzmax;
tmin = (bounds[raySign[0]].getX() - rayFrom.getX()) * rayInvDirection.getX();
- tmax = (bounds[1-raySign[0]].getX() - rayFrom.getX()) * rayInvDirection.getX();
+ tmax = (bounds[1 - raySign[0]].getX() - rayFrom.getX()) * rayInvDirection.getX();
tymin = (bounds[raySign[1]].getY() - rayFrom.getY()) * rayInvDirection.getY();
- tymax = (bounds[1-raySign[1]].getY() - rayFrom.getY()) * rayInvDirection.getY();
+ tymax = (bounds[1 - raySign[1]].getY() - rayFrom.getY()) * rayInvDirection.getY();
- if ( (tmin > tymax) || (tymin > tmax) )
+ if ((tmin > tymax) || (tymin > tmax))
return false;
if (tymin > tmin)
@@ -111,59 +103,59 @@ B3_FORCE_INLINE bool b3RayAabb2(const b3Vector3& rayFrom,
tmax = tymax;
tzmin = (bounds[raySign[2]].getZ() - rayFrom.getZ()) * rayInvDirection.getZ();
- tzmax = (bounds[1-raySign[2]].getZ() - rayFrom.getZ()) * rayInvDirection.getZ();
+ tzmax = (bounds[1 - raySign[2]].getZ() - rayFrom.getZ()) * rayInvDirection.getZ();
- if ( (tmin > tzmax) || (tzmin > tmax) )
+ if ((tmin > tzmax) || (tzmin > tmax))
return false;
if (tzmin > tmin)
tmin = tzmin;
if (tzmax < tmax)
tmax = tzmax;
- return ( (tmin < lambda_max) && (tmax > lambda_min) );
+ return ((tmin < lambda_max) && (tmax > lambda_min));
}
-B3_FORCE_INLINE bool b3RayAabb(const b3Vector3& rayFrom,
- const b3Vector3& rayTo,
- const b3Vector3& aabbMin,
- const b3Vector3& aabbMax,
- b3Scalar& param, b3Vector3& normal)
+B3_FORCE_INLINE bool b3RayAabb(const b3Vector3& rayFrom,
+ const b3Vector3& rayTo,
+ const b3Vector3& aabbMin,
+ const b3Vector3& aabbMax,
+ b3Scalar& param, b3Vector3& normal)
{
- b3Vector3 aabbHalfExtent = (aabbMax-aabbMin)* b3Scalar(0.5);
- b3Vector3 aabbCenter = (aabbMax+aabbMin)* b3Scalar(0.5);
- b3Vector3 source = rayFrom - aabbCenter;
- b3Vector3 target = rayTo - aabbCenter;
- int sourceOutcode = b3Outcode(source,aabbHalfExtent);
- int targetOutcode = b3Outcode(target,aabbHalfExtent);
+ b3Vector3 aabbHalfExtent = (aabbMax - aabbMin) * b3Scalar(0.5);
+ b3Vector3 aabbCenter = (aabbMax + aabbMin) * b3Scalar(0.5);
+ b3Vector3 source = rayFrom - aabbCenter;
+ b3Vector3 target = rayTo - aabbCenter;
+ int sourceOutcode = b3Outcode(source, aabbHalfExtent);
+ int targetOutcode = b3Outcode(target, aabbHalfExtent);
if ((sourceOutcode & targetOutcode) == 0x0)
{
b3Scalar lambda_enter = b3Scalar(0.0);
- b3Scalar lambda_exit = param;
+ b3Scalar lambda_exit = param;
b3Vector3 r = target - source;
int i;
- b3Scalar normSign = 1;
- b3Vector3 hitNormal = b3MakeVector3(0,0,0);
- int bit=1;
+ b3Scalar normSign = 1;
+ b3Vector3 hitNormal = b3MakeVector3(0, 0, 0);
+ int bit = 1;
- for (int j=0;j<2;j++)
+ for (int j = 0; j < 2; j++)
{
for (i = 0; i != 3; ++i)
{
if (sourceOutcode & bit)
{
- b3Scalar lambda = (-source[i] - aabbHalfExtent[i]*normSign) / r[i];
+ b3Scalar lambda = (-source[i] - aabbHalfExtent[i] * normSign) / r[i];
if (lambda_enter <= lambda)
{
lambda_enter = lambda;
- hitNormal.setValue(0,0,0);
+ hitNormal.setValue(0, 0, 0);
hitNormal[i] = normSign;
}
}
- else if (targetOutcode & bit)
+ else if (targetOutcode & bit)
{
- b3Scalar lambda = (-source[i] - aabbHalfExtent[i]*normSign) / r[i];
+ b3Scalar lambda = (-source[i] - aabbHalfExtent[i] * normSign) / r[i];
b3SetMin(lambda_exit, lambda);
}
- bit<<=1;
+ bit <<= 1;
}
normSign = b3Scalar(-1.);
}
@@ -177,56 +169,49 @@ B3_FORCE_INLINE bool b3RayAabb(const b3Vector3& rayFrom,
return false;
}
-
-
-B3_FORCE_INLINE void b3TransformAabb(const b3Vector3& halfExtents, b3Scalar margin,const b3Transform& t,b3Vector3& aabbMinOut,b3Vector3& aabbMaxOut)
+B3_FORCE_INLINE void b3TransformAabb(const b3Vector3& halfExtents, b3Scalar margin, const b3Transform& t, b3Vector3& aabbMinOut, b3Vector3& aabbMaxOut)
{
- b3Vector3 halfExtentsWithMargin = halfExtents+b3MakeVector3(margin,margin,margin);
- b3Matrix3x3 abs_b = t.getBasis().absolute();
+ b3Vector3 halfExtentsWithMargin = halfExtents + b3MakeVector3(margin, margin, margin);
+ b3Matrix3x3 abs_b = t.getBasis().absolute();
b3Vector3 center = t.getOrigin();
- b3Vector3 extent = halfExtentsWithMargin.dot3( abs_b[0], abs_b[1], abs_b[2] );
+ b3Vector3 extent = halfExtentsWithMargin.dot3(abs_b[0], abs_b[1], abs_b[2]);
aabbMinOut = center - extent;
aabbMaxOut = center + extent;
}
-
-B3_FORCE_INLINE void b3TransformAabb(const b3Vector3& localAabbMin,const b3Vector3& localAabbMax, b3Scalar margin,const b3Transform& trans,b3Vector3& aabbMinOut,b3Vector3& aabbMaxOut)
+B3_FORCE_INLINE void b3TransformAabb(const b3Vector3& localAabbMin, const b3Vector3& localAabbMax, b3Scalar margin, const b3Transform& trans, b3Vector3& aabbMinOut, b3Vector3& aabbMaxOut)
{
- //b3Assert(localAabbMin.getX() <= localAabbMax.getX());
- //b3Assert(localAabbMin.getY() <= localAabbMax.getY());
- //b3Assert(localAabbMin.getZ() <= localAabbMax.getZ());
- b3Vector3 localHalfExtents = b3Scalar(0.5)*(localAabbMax-localAabbMin);
- localHalfExtents+=b3MakeVector3(margin,margin,margin);
-
- b3Vector3 localCenter = b3Scalar(0.5)*(localAabbMax+localAabbMin);
- b3Matrix3x3 abs_b = trans.getBasis().absolute();
- b3Vector3 center = trans(localCenter);
- b3Vector3 extent = localHalfExtents.dot3( abs_b[0], abs_b[1], abs_b[2] );
- aabbMinOut = center-extent;
- aabbMaxOut = center+extent;
+ //b3Assert(localAabbMin.getX() <= localAabbMax.getX());
+ //b3Assert(localAabbMin.getY() <= localAabbMax.getY());
+ //b3Assert(localAabbMin.getZ() <= localAabbMax.getZ());
+ b3Vector3 localHalfExtents = b3Scalar(0.5) * (localAabbMax - localAabbMin);
+ localHalfExtents += b3MakeVector3(margin, margin, margin);
+
+ b3Vector3 localCenter = b3Scalar(0.5) * (localAabbMax + localAabbMin);
+ b3Matrix3x3 abs_b = trans.getBasis().absolute();
+ b3Vector3 center = trans(localCenter);
+ b3Vector3 extent = localHalfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
+ aabbMinOut = center - extent;
+ aabbMaxOut = center + extent;
}
#define B3_USE_BANCHLESS 1
#ifdef B3_USE_BANCHLESS
- //This block replaces the block below and uses no branches, and replaces the 8 bit return with a 32 bit return for improved performance (~3x on XBox 360)
- B3_FORCE_INLINE unsigned b3TestQuantizedAabbAgainstQuantizedAabb(const unsigned short int* aabbMin1,const unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2)
- {
- return static_cast<unsigned int>(b3Select((unsigned)((aabbMin1[0] <= aabbMax2[0]) & (aabbMax1[0] >= aabbMin2[0])
- & (aabbMin1[2] <= aabbMax2[2]) & (aabbMax1[2] >= aabbMin2[2])
- & (aabbMin1[1] <= aabbMax2[1]) & (aabbMax1[1] >= aabbMin2[1])),
- 1, 0));
- }
+//This block replaces the block below and uses no branches, and replaces the 8 bit return with a 32 bit return for improved performance (~3x on XBox 360)
+B3_FORCE_INLINE unsigned b3TestQuantizedAabbAgainstQuantizedAabb(const unsigned short int* aabbMin1, const unsigned short int* aabbMax1, const unsigned short int* aabbMin2, const unsigned short int* aabbMax2)
+{
+ return static_cast<unsigned int>(b3Select((unsigned)((aabbMin1[0] <= aabbMax2[0]) & (aabbMax1[0] >= aabbMin2[0]) & (aabbMin1[2] <= aabbMax2[2]) & (aabbMax1[2] >= aabbMin2[2]) & (aabbMin1[1] <= aabbMax2[1]) & (aabbMax1[1] >= aabbMin2[1])),
+ 1, 0));
+}
#else
- B3_FORCE_INLINE bool b3TestQuantizedAabbAgainstQuantizedAabb(const unsigned short int* aabbMin1,const unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2)
- {
- bool overlap = true;
- overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? false : overlap;
- overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? false : overlap;
- overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? false : overlap;
- return overlap;
- }
-#endif //B3_USE_BANCHLESS
-
-#endif //B3_AABB_UTIL2
-
+B3_FORCE_INLINE bool b3TestQuantizedAabbAgainstQuantizedAabb(const unsigned short int* aabbMin1, const unsigned short int* aabbMax1, const unsigned short int* aabbMin2, const unsigned short int* aabbMax2)
+{
+ bool overlap = true;
+ overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? false : overlap;
+ overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? false : overlap;
+ overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? false : overlap;
+ return overlap;
+}
+#endif //B3_USE_BANCHLESS
+#endif //B3_AABB_UTIL2
diff --git a/thirdparty/bullet/Bullet3Geometry/b3ConvexHullComputer.cpp b/thirdparty/bullet/Bullet3Geometry/b3ConvexHullComputer.cpp
index 18835c38d5..b37652456e 100644
--- a/thirdparty/bullet/Bullet3Geometry/b3ConvexHullComputer.cpp
+++ b/thirdparty/bullet/Bullet3Geometry/b3ConvexHullComputer.cpp
@@ -20,850 +20,851 @@ subject to the following restrictions:
#include "Bullet3Common/b3Vector3.h"
#ifdef __GNUC__
- #include <stdint.h>
- typedef int32_t btInt32_t;
- typedef int64_t btInt64_t;
- typedef uint32_t btUint32_t;
- typedef uint64_t btUint64_t;
+#include <stdint.h>
+typedef int32_t btInt32_t;
+typedef int64_t btInt64_t;
+typedef uint32_t btUint32_t;
+typedef uint64_t btUint64_t;
#elif defined(_MSC_VER)
- typedef __int32 btInt32_t;
- typedef __int64 btInt64_t;
- typedef unsigned __int32 btUint32_t;
- typedef unsigned __int64 btUint64_t;
+typedef __int32 btInt32_t;
+typedef __int64 btInt64_t;
+typedef unsigned __int32 btUint32_t;
+typedef unsigned __int64 btUint64_t;
#else
- typedef int btInt32_t;
- typedef long long int btInt64_t;
- typedef unsigned int btUint32_t;
- typedef unsigned long long int btUint64_t;
+typedef int btInt32_t;
+typedef long long int btInt64_t;
+typedef unsigned int btUint32_t;
+typedef unsigned long long int btUint64_t;
#endif
-
//The definition of USE_X86_64_ASM is moved into the build system. You can enable it manually by commenting out the following lines
//#if (defined(__GNUC__) && defined(__x86_64__) && !defined(__ICL)) // || (defined(__ICL) && defined(_M_X64)) bug in Intel compiler, disable inline assembly
// #define USE_X86_64_ASM
//#endif
-
//#define DEBUG_CONVEX_HULL
//#define SHOW_ITERATIONS
#if defined(DEBUG_CONVEX_HULL) || defined(SHOW_ITERATIONS)
- #include <stdio.h>
+#include <stdio.h>
#endif
// Convex hull implementation based on Preparata and Hong
// Ole Kniemeyer, MAXON Computer GmbH
class b3ConvexHullInternal
{
+public:
+ class Point64
+ {
public:
-
- class Point64
- {
- public:
- btInt64_t x;
- btInt64_t y;
- btInt64_t z;
-
- Point64(btInt64_t x, btInt64_t y, btInt64_t z): x(x), y(y), z(z)
- {
- }
+ btInt64_t x;
+ btInt64_t y;
+ btInt64_t z;
- bool isZero()
- {
- return (x == 0) && (y == 0) && (z == 0);
- }
+ Point64(btInt64_t x, btInt64_t y, btInt64_t z) : x(x), y(y), z(z)
+ {
+ }
- btInt64_t dot(const Point64& b) const
- {
- return x * b.x + y * b.y + z * b.z;
- }
- };
-
- class Point32
- {
- public:
- btInt32_t x;
- btInt32_t y;
- btInt32_t z;
- int index;
-
- Point32()
- {
- }
-
- Point32(btInt32_t x, btInt32_t y, btInt32_t z): x(x), y(y), z(z), index(-1)
- {
- }
-
- bool operator==(const Point32& b) const
- {
- return (x == b.x) && (y == b.y) && (z == b.z);
- }
+ bool isZero()
+ {
+ return (x == 0) && (y == 0) && (z == 0);
+ }
- bool operator!=(const Point32& b) const
- {
- return (x != b.x) || (y != b.y) || (z != b.z);
- }
+ btInt64_t dot(const Point64& b) const
+ {
+ return x * b.x + y * b.y + z * b.z;
+ }
+ };
- bool isZero()
- {
- return (x == 0) && (y == 0) && (z == 0);
- }
+ class Point32
+ {
+ public:
+ btInt32_t x;
+ btInt32_t y;
+ btInt32_t z;
+ int index;
- Point64 cross(const Point32& b) const
- {
- return Point64(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x);
- }
+ Point32()
+ {
+ }
- Point64 cross(const Point64& b) const
- {
- return Point64(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x);
- }
+ Point32(btInt32_t x, btInt32_t y, btInt32_t z) : x(x), y(y), z(z), index(-1)
+ {
+ }
- btInt64_t dot(const Point32& b) const
- {
- return x * b.x + y * b.y + z * b.z;
- }
+ bool operator==(const Point32& b) const
+ {
+ return (x == b.x) && (y == b.y) && (z == b.z);
+ }
- btInt64_t dot(const Point64& b) const
- {
- return x * b.x + y * b.y + z * b.z;
- }
+ bool operator!=(const Point32& b) const
+ {
+ return (x != b.x) || (y != b.y) || (z != b.z);
+ }
- Point32 operator+(const Point32& b) const
- {
- return Point32(x + b.x, y + b.y, z + b.z);
- }
+ bool isZero()
+ {
+ return (x == 0) && (y == 0) && (z == 0);
+ }
- Point32 operator-(const Point32& b) const
- {
- return Point32(x - b.x, y - b.y, z - b.z);
- }
- };
+ Point64 cross(const Point32& b) const
+ {
+ return Point64(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x);
+ }
- class Int128
+ Point64 cross(const Point64& b) const
{
- public:
- btUint64_t low;
- btUint64_t high;
+ return Point64(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x);
+ }
- Int128()
- {
- }
+ btInt64_t dot(const Point32& b) const
+ {
+ return x * b.x + y * b.y + z * b.z;
+ }
- Int128(btUint64_t low, btUint64_t high): low(low), high(high)
- {
- }
+ btInt64_t dot(const Point64& b) const
+ {
+ return x * b.x + y * b.y + z * b.z;
+ }
- Int128(btUint64_t low): low(low), high(0)
- {
- }
+ Point32 operator+(const Point32& b) const
+ {
+ return Point32(x + b.x, y + b.y, z + b.z);
+ }
- Int128(btInt64_t value): low(value), high((value >= 0) ? 0 : (btUint64_t) -1LL)
- {
- }
+ Point32 operator-(const Point32& b) const
+ {
+ return Point32(x - b.x, y - b.y, z - b.z);
+ }
+ };
- static Int128 mul(btInt64_t a, btInt64_t b);
+ class Int128
+ {
+ public:
+ btUint64_t low;
+ btUint64_t high;
- static Int128 mul(btUint64_t a, btUint64_t b);
+ Int128()
+ {
+ }
- Int128 operator-() const
- {
- return Int128((btUint64_t) -(btInt64_t)low, ~high + (low == 0));
- }
+ Int128(btUint64_t low, btUint64_t high) : low(low), high(high)
+ {
+ }
- Int128 operator+(const Int128& b) const
- {
+ Int128(btUint64_t low) : low(low), high(0)
+ {
+ }
+
+ Int128(btInt64_t value) : low(value), high((value >= 0) ? 0 : (btUint64_t)-1LL)
+ {
+ }
+
+ static Int128 mul(btInt64_t a, btInt64_t b);
+
+ static Int128 mul(btUint64_t a, btUint64_t b);
+
+ Int128 operator-() const
+ {
+ return Int128((btUint64_t) - (btInt64_t)low, ~high + (low == 0));
+ }
+
+ Int128 operator+(const Int128& b) const
+ {
#ifdef USE_X86_64_ASM
- Int128 result;
- __asm__ ("addq %[bl], %[rl]\n\t"
- "adcq %[bh], %[rh]\n\t"
- : [rl] "=r" (result.low), [rh] "=r" (result.high)
- : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
- : "cc" );
- return result;
+ Int128 result;
+ __asm__(
+ "addq %[bl], %[rl]\n\t"
+ "adcq %[bh], %[rh]\n\t"
+ : [rl] "=r"(result.low), [rh] "=r"(result.high)
+ : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
+ : "cc");
+ return result;
#else
- btUint64_t lo = low + b.low;
- return Int128(lo, high + b.high + (lo < low));
+ btUint64_t lo = low + b.low;
+ return Int128(lo, high + b.high + (lo < low));
#endif
- }
+ }
- Int128 operator-(const Int128& b) const
- {
+ Int128 operator-(const Int128& b) const
+ {
#ifdef USE_X86_64_ASM
- Int128 result;
- __asm__ ("subq %[bl], %[rl]\n\t"
- "sbbq %[bh], %[rh]\n\t"
- : [rl] "=r" (result.low), [rh] "=r" (result.high)
- : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
- : "cc" );
- return result;
+ Int128 result;
+ __asm__(
+ "subq %[bl], %[rl]\n\t"
+ "sbbq %[bh], %[rh]\n\t"
+ : [rl] "=r"(result.low), [rh] "=r"(result.high)
+ : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
+ : "cc");
+ return result;
#else
- return *this + -b;
+ return *this + -b;
#endif
- }
+ }
- Int128& operator+=(const Int128& b)
- {
+ Int128& operator+=(const Int128& b)
+ {
#ifdef USE_X86_64_ASM
- __asm__ ("addq %[bl], %[rl]\n\t"
- "adcq %[bh], %[rh]\n\t"
- : [rl] "=r" (low), [rh] "=r" (high)
- : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
- : "cc" );
+ __asm__(
+ "addq %[bl], %[rl]\n\t"
+ "adcq %[bh], %[rh]\n\t"
+ : [rl] "=r"(low), [rh] "=r"(high)
+ : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
+ : "cc");
#else
- btUint64_t lo = low + b.low;
- if (lo < low)
- {
- ++high;
- }
- low = lo;
- high += b.high;
+ btUint64_t lo = low + b.low;
+ if (lo < low)
+ {
+ ++high;
+ }
+ low = lo;
+ high += b.high;
#endif
- return *this;
- }
+ return *this;
+ }
- Int128& operator++()
- {
- if (++low == 0)
- {
- ++high;
- }
- return *this;
- }
+ Int128& operator++()
+ {
+ if (++low == 0)
+ {
+ ++high;
+ }
+ return *this;
+ }
- Int128 operator*(btInt64_t b) const;
+ Int128 operator*(btInt64_t b) const;
- b3Scalar toScalar() const
- {
- return ((btInt64_t) high >= 0) ? b3Scalar(high) * (b3Scalar(0x100000000LL) * b3Scalar(0x100000000LL)) + b3Scalar(low)
- : -(-*this).toScalar();
- }
+ b3Scalar toScalar() const
+ {
+ return ((btInt64_t)high >= 0) ? b3Scalar(high) * (b3Scalar(0x100000000LL) * b3Scalar(0x100000000LL)) + b3Scalar(low)
+ : -(-*this).toScalar();
+ }
- int getSign() const
- {
- return ((btInt64_t) high < 0) ? -1 : (high || low) ? 1 : 0;
- }
+ int getSign() const
+ {
+ return ((btInt64_t)high < 0) ? -1 : (high || low) ? 1 : 0;
+ }
- bool operator<(const Int128& b) const
- {
- return (high < b.high) || ((high == b.high) && (low < b.low));
- }
+ bool operator<(const Int128& b) const
+ {
+ return (high < b.high) || ((high == b.high) && (low < b.low));
+ }
- int ucmp(const Int128&b) const
- {
- if (high < b.high)
- {
- return -1;
- }
- if (high > b.high)
- {
- return 1;
- }
- if (low < b.low)
- {
- return -1;
- }
- if (low > b.low)
- {
- return 1;
- }
- return 0;
- }
- };
+ int ucmp(const Int128& b) const
+ {
+ if (high < b.high)
+ {
+ return -1;
+ }
+ if (high > b.high)
+ {
+ return 1;
+ }
+ if (low < b.low)
+ {
+ return -1;
+ }
+ if (low > b.low)
+ {
+ return 1;
+ }
+ return 0;
+ }
+ };
+ class Rational64
+ {
+ private:
+ btUint64_t m_numerator;
+ btUint64_t m_denominator;
+ int sign;
- class Rational64
+ public:
+ Rational64(btInt64_t numerator, btInt64_t denominator)
{
- private:
- btUint64_t m_numerator;
- btUint64_t m_denominator;
- int sign;
-
- public:
- Rational64(btInt64_t numerator, btInt64_t denominator)
- {
- if (numerator > 0)
- {
- sign = 1;
- m_numerator = (btUint64_t) numerator;
- }
- else if (numerator < 0)
- {
- sign = -1;
- m_numerator = (btUint64_t) -numerator;
- }
- else
- {
- sign = 0;
- m_numerator = 0;
- }
- if (denominator > 0)
- {
- m_denominator = (btUint64_t) denominator;
- }
- else if (denominator < 0)
- {
- sign = -sign;
- m_denominator = (btUint64_t) -denominator;
- }
- else
- {
- m_denominator = 0;
- }
- }
-
- bool isNegativeInfinity() const
- {
- return (sign < 0) && (m_denominator == 0);
- }
-
- bool isNaN() const
- {
- return (sign == 0) && (m_denominator == 0);
- }
-
- int compare(const Rational64& b) const;
-
- b3Scalar toScalar() const
- {
- return sign * ((m_denominator == 0) ? B3_INFINITY : (b3Scalar) m_numerator / m_denominator);
- }
- };
-
+ if (numerator > 0)
+ {
+ sign = 1;
+ m_numerator = (btUint64_t)numerator;
+ }
+ else if (numerator < 0)
+ {
+ sign = -1;
+ m_numerator = (btUint64_t)-numerator;
+ }
+ else
+ {
+ sign = 0;
+ m_numerator = 0;
+ }
+ if (denominator > 0)
+ {
+ m_denominator = (btUint64_t)denominator;
+ }
+ else if (denominator < 0)
+ {
+ sign = -sign;
+ m_denominator = (btUint64_t)-denominator;
+ }
+ else
+ {
+ m_denominator = 0;
+ }
+ }
- class Rational128
+ bool isNegativeInfinity() const
{
- private:
- Int128 numerator;
- Int128 denominator;
- int sign;
- bool isInt64;
+ return (sign < 0) && (m_denominator == 0);
+ }
- public:
- Rational128(btInt64_t value)
- {
- if (value > 0)
- {
- sign = 1;
- this->numerator = value;
- }
- else if (value < 0)
- {
- sign = -1;
- this->numerator = -value;
- }
- else
- {
- sign = 0;
- this->numerator = (btUint64_t) 0;
- }
- this->denominator = (btUint64_t) 1;
- isInt64 = true;
- }
+ bool isNaN() const
+ {
+ return (sign == 0) && (m_denominator == 0);
+ }
- Rational128(const Int128& numerator, const Int128& denominator)
- {
- sign = numerator.getSign();
- if (sign >= 0)
- {
- this->numerator = numerator;
- }
- else
- {
- this->numerator = -numerator;
- }
- int dsign = denominator.getSign();
- if (dsign >= 0)
- {
- this->denominator = denominator;
- }
- else
- {
- sign = -sign;
- this->denominator = -denominator;
- }
- isInt64 = false;
- }
+ int compare(const Rational64& b) const;
- int compare(const Rational128& b) const;
+ b3Scalar toScalar() const
+ {
+ return sign * ((m_denominator == 0) ? B3_INFINITY : (b3Scalar)m_numerator / m_denominator);
+ }
+ };
- int compare(btInt64_t b) const;
+ class Rational128
+ {
+ private:
+ Int128 numerator;
+ Int128 denominator;
+ int sign;
+ bool isInt64;
- b3Scalar toScalar() const
- {
- return sign * ((denominator.getSign() == 0) ? B3_INFINITY : numerator.toScalar() / denominator.toScalar());
- }
- };
+ public:
+ Rational128(btInt64_t value)
+ {
+ if (value > 0)
+ {
+ sign = 1;
+ this->numerator = value;
+ }
+ else if (value < 0)
+ {
+ sign = -1;
+ this->numerator = -value;
+ }
+ else
+ {
+ sign = 0;
+ this->numerator = (btUint64_t)0;
+ }
+ this->denominator = (btUint64_t)1;
+ isInt64 = true;
+ }
- class PointR128
+ Rational128(const Int128& numerator, const Int128& denominator)
{
- public:
- Int128 x;
- Int128 y;
- Int128 z;
- Int128 denominator;
+ sign = numerator.getSign();
+ if (sign >= 0)
+ {
+ this->numerator = numerator;
+ }
+ else
+ {
+ this->numerator = -numerator;
+ }
+ int dsign = denominator.getSign();
+ if (dsign >= 0)
+ {
+ this->denominator = denominator;
+ }
+ else
+ {
+ sign = -sign;
+ this->denominator = -denominator;
+ }
+ isInt64 = false;
+ }
- PointR128()
- {
- }
+ int compare(const Rational128& b) const;
- PointR128(Int128 x, Int128 y, Int128 z, Int128 denominator): x(x), y(y), z(z), denominator(denominator)
- {
- }
+ int compare(btInt64_t b) const;
- b3Scalar xvalue() const
- {
- return x.toScalar() / denominator.toScalar();
- }
+ b3Scalar toScalar() const
+ {
+ return sign * ((denominator.getSign() == 0) ? B3_INFINITY : numerator.toScalar() / denominator.toScalar());
+ }
+ };
- b3Scalar yvalue() const
- {
- return y.toScalar() / denominator.toScalar();
- }
+ class PointR128
+ {
+ public:
+ Int128 x;
+ Int128 y;
+ Int128 z;
+ Int128 denominator;
- b3Scalar zvalue() const
- {
- return z.toScalar() / denominator.toScalar();
- }
- };
+ PointR128()
+ {
+ }
+ PointR128(Int128 x, Int128 y, Int128 z, Int128 denominator) : x(x), y(y), z(z), denominator(denominator)
+ {
+ }
- class Edge;
- class Face;
+ b3Scalar xvalue() const
+ {
+ return x.toScalar() / denominator.toScalar();
+ }
- class Vertex
+ b3Scalar yvalue() const
{
- public:
- Vertex* next;
- Vertex* prev;
- Edge* edges;
- Face* firstNearbyFace;
- Face* lastNearbyFace;
- PointR128 point128;
- Point32 point;
- int copy;
-
- Vertex(): next(NULL), prev(NULL), edges(NULL), firstNearbyFace(NULL), lastNearbyFace(NULL), copy(-1)
- {
- }
+ return y.toScalar() / denominator.toScalar();
+ }
-#ifdef DEBUG_CONVEX_HULL
- void print()
- {
- b3Printf("V%d (%d, %d, %d)", point.index, point.x, point.y, point.z);
- }
+ b3Scalar zvalue() const
+ {
+ return z.toScalar() / denominator.toScalar();
+ }
+ };
- void printGraph();
-#endif
+ class Edge;
+ class Face;
- Point32 operator-(const Vertex& b) const
- {
- return point - b.point;
- }
+ class Vertex
+ {
+ public:
+ Vertex* next;
+ Vertex* prev;
+ Edge* edges;
+ Face* firstNearbyFace;
+ Face* lastNearbyFace;
+ PointR128 point128;
+ Point32 point;
+ int copy;
- Rational128 dot(const Point64& b) const
- {
- return (point.index >= 0) ? Rational128(point.dot(b))
- : Rational128(point128.x * b.x + point128.y * b.y + point128.z * b.z, point128.denominator);
- }
+ Vertex() : next(NULL), prev(NULL), edges(NULL), firstNearbyFace(NULL), lastNearbyFace(NULL), copy(-1)
+ {
+ }
- b3Scalar xvalue() const
- {
- return (point.index >= 0) ? b3Scalar(point.x) : point128.xvalue();
- }
+#ifdef DEBUG_CONVEX_HULL
+ void print()
+ {
+ b3Printf("V%d (%d, %d, %d)", point.index, point.x, point.y, point.z);
+ }
- b3Scalar yvalue() const
- {
- return (point.index >= 0) ? b3Scalar(point.y) : point128.yvalue();
- }
+ void printGraph();
+#endif
- b3Scalar zvalue() const
- {
- return (point.index >= 0) ? b3Scalar(point.z) : point128.zvalue();
- }
+ Point32 operator-(const Vertex& b) const
+ {
+ return point - b.point;
+ }
- void receiveNearbyFaces(Vertex* src)
- {
- if (lastNearbyFace)
- {
- lastNearbyFace->nextWithSameNearbyVertex = src->firstNearbyFace;
- }
- else
- {
- firstNearbyFace = src->firstNearbyFace;
- }
- if (src->lastNearbyFace)
- {
- lastNearbyFace = src->lastNearbyFace;
- }
- for (Face* f = src->firstNearbyFace; f; f = f->nextWithSameNearbyVertex)
- {
- b3Assert(f->nearbyVertex == src);
- f->nearbyVertex = this;
- }
- src->firstNearbyFace = NULL;
- src->lastNearbyFace = NULL;
- }
- };
+ Rational128 dot(const Point64& b) const
+ {
+ return (point.index >= 0) ? Rational128(point.dot(b))
+ : Rational128(point128.x * b.x + point128.y * b.y + point128.z * b.z, point128.denominator);
+ }
+ b3Scalar xvalue() const
+ {
+ return (point.index >= 0) ? b3Scalar(point.x) : point128.xvalue();
+ }
- class Edge
+ b3Scalar yvalue() const
{
- public:
- Edge* next;
- Edge* prev;
- Edge* reverse;
- Vertex* target;
- Face* face;
- int copy;
+ return (point.index >= 0) ? b3Scalar(point.y) : point128.yvalue();
+ }
- ~Edge()
- {
- next = NULL;
- prev = NULL;
- reverse = NULL;
- target = NULL;
- face = NULL;
- }
+ b3Scalar zvalue() const
+ {
+ return (point.index >= 0) ? b3Scalar(point.z) : point128.zvalue();
+ }
- void link(Edge* n)
- {
- b3Assert(reverse->target == n->reverse->target);
- next = n;
- n->prev = this;
- }
+ void receiveNearbyFaces(Vertex* src)
+ {
+ if (lastNearbyFace)
+ {
+ lastNearbyFace->nextWithSameNearbyVertex = src->firstNearbyFace;
+ }
+ else
+ {
+ firstNearbyFace = src->firstNearbyFace;
+ }
+ if (src->lastNearbyFace)
+ {
+ lastNearbyFace = src->lastNearbyFace;
+ }
+ for (Face* f = src->firstNearbyFace; f; f = f->nextWithSameNearbyVertex)
+ {
+ b3Assert(f->nearbyVertex == src);
+ f->nearbyVertex = this;
+ }
+ src->firstNearbyFace = NULL;
+ src->lastNearbyFace = NULL;
+ }
+ };
-#ifdef DEBUG_CONVEX_HULL
- void print()
- {
- b3Printf("E%p : %d -> %d, n=%p p=%p (0 %d\t%d\t%d) -> (%d %d %d)", this, reverse->target->point.index, target->point.index, next, prev,
- reverse->target->point.x, reverse->target->point.y, reverse->target->point.z, target->point.x, target->point.y, target->point.z);
- }
-#endif
- };
+ class Edge
+ {
+ public:
+ Edge* next;
+ Edge* prev;
+ Edge* reverse;
+ Vertex* target;
+ Face* face;
+ int copy;
+
+ ~Edge()
+ {
+ next = NULL;
+ prev = NULL;
+ reverse = NULL;
+ target = NULL;
+ face = NULL;
+ }
- class Face
+ void link(Edge* n)
{
- public:
- Face* next;
- Vertex* nearbyVertex;
- Face* nextWithSameNearbyVertex;
- Point32 origin;
- Point32 dir0;
- Point32 dir1;
+ b3Assert(reverse->target == n->reverse->target);
+ next = n;
+ n->prev = this;
+ }
- Face(): next(NULL), nearbyVertex(NULL), nextWithSameNearbyVertex(NULL)
- {
- }
+#ifdef DEBUG_CONVEX_HULL
+ void print()
+ {
+ b3Printf("E%p : %d -> %d, n=%p p=%p (0 %d\t%d\t%d) -> (%d %d %d)", this, reverse->target->point.index, target->point.index, next, prev,
+ reverse->target->point.x, reverse->target->point.y, reverse->target->point.z, target->point.x, target->point.y, target->point.z);
+ }
+#endif
+ };
- void init(Vertex* a, Vertex* b, Vertex* c)
- {
- nearbyVertex = a;
- origin = a->point;
- dir0 = *b - *a;
- dir1 = *c - *a;
- if (a->lastNearbyFace)
- {
- a->lastNearbyFace->nextWithSameNearbyVertex = this;
- }
- else
- {
- a->firstNearbyFace = this;
- }
- a->lastNearbyFace = this;
- }
+ class Face
+ {
+ public:
+ Face* next;
+ Vertex* nearbyVertex;
+ Face* nextWithSameNearbyVertex;
+ Point32 origin;
+ Point32 dir0;
+ Point32 dir1;
- Point64 getNormal()
- {
- return dir0.cross(dir1);
- }
- };
+ Face() : next(NULL), nearbyVertex(NULL), nextWithSameNearbyVertex(NULL)
+ {
+ }
- template<typename UWord, typename UHWord> class DMul
+ void init(Vertex* a, Vertex* b, Vertex* c)
{
- private:
- static btUint32_t high(btUint64_t value)
- {
- return (btUint32_t) (value >> 32);
- }
-
- static btUint32_t low(btUint64_t value)
- {
- return (btUint32_t) value;
- }
-
- static btUint64_t mul(btUint32_t a, btUint32_t b)
- {
- return (btUint64_t) a * (btUint64_t) b;
- }
-
- static void shlHalf(btUint64_t& value)
- {
- value <<= 32;
- }
-
- static btUint64_t high(Int128 value)
- {
- return value.high;
- }
-
- static btUint64_t low(Int128 value)
- {
- return value.low;
- }
-
- static Int128 mul(btUint64_t a, btUint64_t b)
- {
- return Int128::mul(a, b);
- }
-
- static void shlHalf(Int128& value)
- {
- value.high = value.low;
- value.low = 0;
- }
-
- public:
-
- static void mul(UWord a, UWord b, UWord& resLow, UWord& resHigh)
- {
- UWord p00 = mul(low(a), low(b));
- UWord p01 = mul(low(a), high(b));
- UWord p10 = mul(high(a), low(b));
- UWord p11 = mul(high(a), high(b));
- UWord p0110 = UWord(low(p01)) + UWord(low(p10));
- p11 += high(p01);
- p11 += high(p10);
- p11 += high(p0110);
- shlHalf(p0110);
- p00 += p0110;
- if (p00 < p0110)
- {
- ++p11;
- }
- resLow = p00;
- resHigh = p11;
- }
- };
-
- private:
+ nearbyVertex = a;
+ origin = a->point;
+ dir0 = *b - *a;
+ dir1 = *c - *a;
+ if (a->lastNearbyFace)
+ {
+ a->lastNearbyFace->nextWithSameNearbyVertex = this;
+ }
+ else
+ {
+ a->firstNearbyFace = this;
+ }
+ a->lastNearbyFace = this;
+ }
- class IntermediateHull
+ Point64 getNormal()
{
- public:
- Vertex* minXy;
- Vertex* maxXy;
- Vertex* minYx;
- Vertex* maxYx;
-
- IntermediateHull(): minXy(NULL), maxXy(NULL), minYx(NULL), maxYx(NULL)
- {
- }
-
- void print();
- };
-
- enum Orientation {NONE, CLOCKWISE, COUNTER_CLOCKWISE};
+ return dir0.cross(dir1);
+ }
+ };
- template <typename T> class PoolArray
+ template <typename UWord, typename UHWord>
+ class DMul
+ {
+ private:
+ static btUint32_t high(btUint64_t value)
{
- private:
- T* array;
- int size;
+ return (btUint32_t)(value >> 32);
+ }
- public:
- PoolArray<T>* next;
+ static btUint32_t low(btUint64_t value)
+ {
+ return (btUint32_t)value;
+ }
- PoolArray(int size): size(size), next(NULL)
- {
- array = (T*) b3AlignedAlloc(sizeof(T) * size, 16);
- }
+ static btUint64_t mul(btUint32_t a, btUint32_t b)
+ {
+ return (btUint64_t)a * (btUint64_t)b;
+ }
- ~PoolArray()
- {
- b3AlignedFree(array);
- }
+ static void shlHalf(btUint64_t& value)
+ {
+ value <<= 32;
+ }
- T* init()
- {
- T* o = array;
- for (int i = 0; i < size; i++, o++)
- {
- o->next = (i+1 < size) ? o + 1 : NULL;
- }
- return array;
- }
- };
+ static btUint64_t high(Int128 value)
+ {
+ return value.high;
+ }
- template <typename T> class Pool
+ static btUint64_t low(Int128 value)
{
- private:
- PoolArray<T>* arrays;
- PoolArray<T>* nextArray;
- T* freeObjects;
- int arraySize;
+ return value.low;
+ }
- public:
- Pool(): arrays(NULL), nextArray(NULL), freeObjects(NULL), arraySize(256)
- {
- }
+ static Int128 mul(btUint64_t a, btUint64_t b)
+ {
+ return Int128::mul(a, b);
+ }
- ~Pool()
- {
- while (arrays)
- {
- PoolArray<T>* p = arrays;
- arrays = p->next;
- p->~PoolArray<T>();
- b3AlignedFree(p);
- }
- }
+ static void shlHalf(Int128& value)
+ {
+ value.high = value.low;
+ value.low = 0;
+ }
- void reset()
- {
- nextArray = arrays;
- freeObjects = NULL;
- }
+ public:
+ static void mul(UWord a, UWord b, UWord& resLow, UWord& resHigh)
+ {
+ UWord p00 = mul(low(a), low(b));
+ UWord p01 = mul(low(a), high(b));
+ UWord p10 = mul(high(a), low(b));
+ UWord p11 = mul(high(a), high(b));
+ UWord p0110 = UWord(low(p01)) + UWord(low(p10));
+ p11 += high(p01);
+ p11 += high(p10);
+ p11 += high(p0110);
+ shlHalf(p0110);
+ p00 += p0110;
+ if (p00 < p0110)
+ {
+ ++p11;
+ }
+ resLow = p00;
+ resHigh = p11;
+ }
+ };
- void setArraySize(int arraySize)
- {
- this->arraySize = arraySize;
- }
+private:
+ class IntermediateHull
+ {
+ public:
+ Vertex* minXy;
+ Vertex* maxXy;
+ Vertex* minYx;
+ Vertex* maxYx;
- T* newObject()
- {
- T* o = freeObjects;
- if (!o)
- {
- PoolArray<T>* p = nextArray;
- if (p)
- {
- nextArray = p->next;
- }
- else
- {
- p = new(b3AlignedAlloc(sizeof(PoolArray<T>), 16)) PoolArray<T>(arraySize);
- p->next = arrays;
- arrays = p;
- }
- o = p->init();
- }
- freeObjects = o->next;
- return new(o) T();
- };
+ IntermediateHull() : minXy(NULL), maxXy(NULL), minYx(NULL), maxYx(NULL)
+ {
+ }
- void freeObject(T* object)
- {
- object->~T();
- object->next = freeObjects;
- freeObjects = object;
- }
- };
+ void print();
+ };
- b3Vector3 scaling;
- b3Vector3 center;
- Pool<Vertex> vertexPool;
- Pool<Edge> edgePool;
- Pool<Face> facePool;
- b3AlignedObjectArray<Vertex*> originalVertices;
- int mergeStamp;
- int minAxis;
- int medAxis;
- int maxAxis;
- int usedEdgePairs;
- int maxUsedEdgePairs;
+ enum Orientation
+ {
+ NONE,
+ CLOCKWISE,
+ COUNTER_CLOCKWISE
+ };
- static Orientation getOrientation(const Edge* prev, const Edge* next, const Point32& s, const Point32& t);
- Edge* findMaxAngle(bool ccw, const Vertex* start, const Point32& s, const Point64& rxs, const Point64& sxrxs, Rational64& minCot);
- void findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge*& e0, Edge*& e1, Vertex* stop0, Vertex* stop1);
+ template <typename T>
+ class PoolArray
+ {
+ private:
+ T* array;
+ int size;
- Edge* newEdgePair(Vertex* from, Vertex* to);
+ public:
+ PoolArray<T>* next;
- void removeEdgePair(Edge* edge)
+ PoolArray(int size) : size(size), next(NULL)
{
- Edge* n = edge->next;
- Edge* r = edge->reverse;
+ array = (T*)b3AlignedAlloc(sizeof(T) * size, 16);
+ }
- b3Assert(edge->target && r->target);
+ ~PoolArray()
+ {
+ b3AlignedFree(array);
+ }
- if (n != edge)
- {
- n->prev = edge->prev;
- edge->prev->next = n;
- r->target->edges = n;
- }
- else
+ T* init()
+ {
+ T* o = array;
+ for (int i = 0; i < size; i++, o++)
{
- r->target->edges = NULL;
+ o->next = (i + 1 < size) ? o + 1 : NULL;
}
-
- n = r->next;
-
- if (n != r)
+ return array;
+ }
+ };
+
+ template <typename T>
+ class Pool
+ {
+ private:
+ PoolArray<T>* arrays;
+ PoolArray<T>* nextArray;
+ T* freeObjects;
+ int arraySize;
+
+ public:
+ Pool() : arrays(NULL), nextArray(NULL), freeObjects(NULL), arraySize(256)
+ {
+ }
+
+ ~Pool()
+ {
+ while (arrays)
{
- n->prev = r->prev;
- r->prev->next = n;
- edge->target->edges = n;
+ PoolArray<T>* p = arrays;
+ arrays = p->next;
+ p->~PoolArray<T>();
+ b3AlignedFree(p);
}
- else
+ }
+
+ void reset()
+ {
+ nextArray = arrays;
+ freeObjects = NULL;
+ }
+
+ void setArraySize(int arraySize)
+ {
+ this->arraySize = arraySize;
+ }
+
+ T* newObject()
+ {
+ T* o = freeObjects;
+ if (!o)
{
- edge->target->edges = NULL;
+ PoolArray<T>* p = nextArray;
+ if (p)
+ {
+ nextArray = p->next;
+ }
+ else
+ {
+ p = new (b3AlignedAlloc(sizeof(PoolArray<T>), 16)) PoolArray<T>(arraySize);
+ p->next = arrays;
+ arrays = p;
+ }
+ o = p->init();
}
+ freeObjects = o->next;
+ return new (o) T();
+ };
- edgePool.freeObject(edge);
- edgePool.freeObject(r);
- usedEdgePairs--;
+ void freeObject(T* object)
+ {
+ object->~T();
+ object->next = freeObjects;
+ freeObjects = object;
}
-
- void computeInternal(int start, int end, IntermediateHull& result);
-
- bool mergeProjection(IntermediateHull& h0, IntermediateHull& h1, Vertex*& c0, Vertex*& c1);
-
- void merge(IntermediateHull& h0, IntermediateHull& h1);
+ };
- b3Vector3 toBtVector(const Point32& v);
+ b3Vector3 scaling;
+ b3Vector3 center;
+ Pool<Vertex> vertexPool;
+ Pool<Edge> edgePool;
+ Pool<Face> facePool;
+ b3AlignedObjectArray<Vertex*> originalVertices;
+ int mergeStamp;
+ int minAxis;
+ int medAxis;
+ int maxAxis;
+ int usedEdgePairs;
+ int maxUsedEdgePairs;
- b3Vector3 getBtNormal(Face* face);
+ static Orientation getOrientation(const Edge* prev, const Edge* next, const Point32& s, const Point32& t);
+ Edge* findMaxAngle(bool ccw, const Vertex* start, const Point32& s, const Point64& rxs, const Point64& sxrxs, Rational64& minCot);
+ void findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge*& e0, Edge*& e1, Vertex* stop0, Vertex* stop1);
- bool shiftFace(Face* face, b3Scalar amount, b3AlignedObjectArray<Vertex*> stack);
+ Edge* newEdgePair(Vertex* from, Vertex* to);
- public:
- Vertex* vertexList;
+ void removeEdgePair(Edge* edge)
+ {
+ Edge* n = edge->next;
+ Edge* r = edge->reverse;
- void compute(const void* coords, bool doubleCoords, int stride, int count);
+ b3Assert(edge->target && r->target);
- b3Vector3 getCoordinates(const Vertex* v);
+ if (n != edge)
+ {
+ n->prev = edge->prev;
+ edge->prev->next = n;
+ r->target->edges = n;
+ }
+ else
+ {
+ r->target->edges = NULL;
+ }
- b3Scalar shrink(b3Scalar amount, b3Scalar clampAmount);
-};
+ n = r->next;
+
+ if (n != r)
+ {
+ n->prev = r->prev;
+ r->prev->next = n;
+ edge->target->edges = n;
+ }
+ else
+ {
+ edge->target->edges = NULL;
+ }
+
+ edgePool.freeObject(edge);
+ edgePool.freeObject(r);
+ usedEdgePairs--;
+ }
+
+ void computeInternal(int start, int end, IntermediateHull& result);
+
+ bool mergeProjection(IntermediateHull& h0, IntermediateHull& h1, Vertex*& c0, Vertex*& c1);
+
+ void merge(IntermediateHull& h0, IntermediateHull& h1);
+ b3Vector3 toBtVector(const Point32& v);
+
+ b3Vector3 getBtNormal(Face* face);
+
+ bool shiftFace(Face* face, b3Scalar amount, b3AlignedObjectArray<Vertex*> stack);
+
+public:
+ Vertex* vertexList;
+
+ void compute(const void* coords, bool doubleCoords, int stride, int count);
+
+ b3Vector3 getCoordinates(const Vertex* v);
+
+ b3Scalar shrink(b3Scalar amount, b3Scalar clampAmount);
+};
b3ConvexHullInternal::Int128 b3ConvexHullInternal::Int128::operator*(btInt64_t b) const
{
- bool negative = (btInt64_t) high < 0;
+ bool negative = (btInt64_t)high < 0;
Int128 a = negative ? -*this : *this;
if (b < 0)
{
negative = !negative;
b = -b;
}
- Int128 result = mul(a.low, (btUint64_t) b);
- result.high += a.high * (btUint64_t) b;
+ Int128 result = mul(a.low, (btUint64_t)b);
+ result.high += a.high * (btUint64_t)b;
return negative ? -result : result;
}
b3ConvexHullInternal::Int128 b3ConvexHullInternal::Int128::mul(btInt64_t a, btInt64_t b)
{
Int128 result;
-
+
#ifdef USE_X86_64_ASM
- __asm__ ("imulq %[b]"
- : "=a" (result.low), "=d" (result.high)
- : "0"(a), [b] "r"(b)
- : "cc" );
+ __asm__("imulq %[b]"
+ : "=a"(result.low), "=d"(result.high)
+ : "0"(a), [b] "r"(b)
+ : "cc");
return result;
-
+
#else
bool negative = a < 0;
if (negative)
@@ -875,7 +876,7 @@ b3ConvexHullInternal::Int128 b3ConvexHullInternal::Int128::mul(btInt64_t a, btIn
negative = !negative;
b = -b;
}
- DMul<btUint64_t, btUint32_t>::mul((btUint64_t) a, (btUint64_t) b, result.low, result.high);
+ DMul<btUint64_t, btUint32_t>::mul((btUint64_t)a, (btUint64_t)b, result.low, result.high);
return negative ? -result : result;
#endif
}
@@ -885,10 +886,10 @@ b3ConvexHullInternal::Int128 b3ConvexHullInternal::Int128::mul(btUint64_t a, btU
Int128 result;
#ifdef USE_X86_64_ASM
- __asm__ ("mulq %[b]"
- : "=a" (result.low), "=d" (result.high)
- : "0"(a), [b] "r"(b)
- : "cc" );
+ __asm__("mulq %[b]"
+ : "=a"(result.low), "=d"(result.high)
+ : "0"(a), [b] "r"(b)
+ : "cc");
#else
DMul<btUint64_t, btUint32_t>::mul(a, b, result.low, result.high);
@@ -915,24 +916,25 @@ int b3ConvexHullInternal::Rational64::compare(const Rational64& b) const
int result;
btInt64_t tmp;
btInt64_t dummy;
- __asm__ ("mulq %[bn]\n\t"
- "movq %%rax, %[tmp]\n\t"
- "movq %%rdx, %%rbx\n\t"
- "movq %[tn], %%rax\n\t"
- "mulq %[bd]\n\t"
- "subq %[tmp], %%rax\n\t"
- "sbbq %%rbx, %%rdx\n\t" // rdx:rax contains 128-bit-difference "numerator*b.denominator - b.numerator*denominator"
- "setnsb %%bh\n\t" // bh=1 if difference is non-negative, bh=0 otherwise
- "orq %%rdx, %%rax\n\t"
- "setnzb %%bl\n\t" // bl=1 if difference if non-zero, bl=0 if it is zero
- "decb %%bh\n\t" // now bx=0x0000 if difference is zero, 0xff01 if it is negative, 0x0001 if it is positive (i.e., same sign as difference)
- "shll $16, %%ebx\n\t" // ebx has same sign as difference
- : "=&b"(result), [tmp] "=&r"(tmp), "=a"(dummy)
- : "a"(denominator), [bn] "g"(b.numerator), [tn] "g"(numerator), [bd] "g"(b.denominator)
- : "%rdx", "cc" );
- return result ? result ^ sign // if sign is +1, only bit 0 of result is inverted, which does not change the sign of result (and cannot result in zero)
- // if sign is -1, all bits of result are inverted, which changes the sign of result (and again cannot result in zero)
- : 0;
+ __asm__(
+ "mulq %[bn]\n\t"
+ "movq %%rax, %[tmp]\n\t"
+ "movq %%rdx, %%rbx\n\t"
+ "movq %[tn], %%rax\n\t"
+ "mulq %[bd]\n\t"
+ "subq %[tmp], %%rax\n\t"
+ "sbbq %%rbx, %%rdx\n\t" // rdx:rax contains 128-bit-difference "numerator*b.denominator - b.numerator*denominator"
+ "setnsb %%bh\n\t" // bh=1 if difference is non-negative, bh=0 otherwise
+ "orq %%rdx, %%rax\n\t"
+ "setnzb %%bl\n\t" // bl=1 if difference if non-zero, bl=0 if it is zero
+ "decb %%bh\n\t" // now bx=0x0000 if difference is zero, 0xff01 if it is negative, 0x0001 if it is positive (i.e., same sign as difference)
+ "shll $16, %%ebx\n\t" // ebx has same sign as difference
+ : "=&b"(result), [tmp] "=&r"(tmp), "=a"(dummy)
+ : "a"(denominator), [bn] "g"(b.numerator), [tn] "g"(numerator), [bd] "g"(b.denominator)
+ : "%rdx", "cc");
+ return result ? result ^ sign // if sign is +1, only bit 0 of result is inverted, which does not change the sign of result (and cannot result in zero)
+ // if sign is -1, all bits of result are inverted, which changes the sign of result (and again cannot result in zero)
+ : 0;
#else
@@ -953,7 +955,7 @@ int b3ConvexHullInternal::Rational128::compare(const Rational128& b) const
}
if (isInt64)
{
- return -b.compare(sign * (btInt64_t) numerator.low);
+ return -b.compare(sign * (btInt64_t)numerator.low);
}
Int128 nbdLow, nbdHigh, dbnLow, dbnHigh;
@@ -972,7 +974,7 @@ int b3ConvexHullInternal::Rational128::compare(btInt64_t b) const
{
if (isInt64)
{
- btInt64_t a = sign * (btInt64_t) numerator.low;
+ btInt64_t a = sign * (btInt64_t)numerator.low;
return (a > b) ? 1 : (a < b) ? -1 : 0;
}
if (b > 0)
@@ -998,7 +1000,6 @@ int b3ConvexHullInternal::Rational128::compare(btInt64_t b) const
return numerator.ucmp(denominator * b) * sign;
}
-
b3ConvexHullInternal::Edge* b3ConvexHullInternal::newEdgePair(Vertex* from, Vertex* to)
{
b3Assert(from && to);
@@ -1066,7 +1067,7 @@ bool b3ConvexHullInternal::mergeProjection(IntermediateHull& h0, IntermediateHul
}
}
}
-
+
v0 = h0.maxXy;
v1 = h1.maxXy;
Vertex* v00 = NULL;
@@ -1074,7 +1075,7 @@ bool b3ConvexHullInternal::mergeProjection(IntermediateHull& h0, IntermediateHul
btInt32_t sign = 1;
for (int side = 0; side <= 1; side++)
- {
+ {
btInt32_t dx = (v1->point.x - v0->point.x) * sign;
if (dx > 0)
{
@@ -1117,7 +1118,7 @@ bool b3ConvexHullInternal::mergeProjection(IntermediateHull& h0, IntermediateHul
while (true)
{
btInt32_t dy = v1->point.y - v0->point.y;
-
+
Vertex* w1 = side ? v1->prev : v1->next;
if (w1 != v1)
{
@@ -1130,7 +1131,7 @@ bool b3ConvexHullInternal::mergeProjection(IntermediateHull& h0, IntermediateHul
continue;
}
}
-
+
Vertex* w0 = side ? v0->prev : v0->next;
if (w0 != v0)
{
@@ -1144,7 +1145,7 @@ bool b3ConvexHullInternal::mergeProjection(IntermediateHull& h0, IntermediateHul
continue;
}
}
-
+
break;
}
}
@@ -1170,7 +1171,7 @@ bool b3ConvexHullInternal::mergeProjection(IntermediateHull& h0, IntermediateHul
}
v1 = w1;
}
-
+
if (side == 0)
{
v00 = v0;
@@ -1196,7 +1197,7 @@ bool b3ConvexHullInternal::mergeProjection(IntermediateHull& h0, IntermediateHul
{
h0.maxXy = h1.maxXy;
}
-
+
h0.maxYx = h1.maxYx;
c0 = v00;
@@ -1300,7 +1301,7 @@ void b3ConvexHullInternal::computeInternal(int start, int end, IntermediateHull&
}
int split0 = start + n / 2;
- Point32 p = originalVertices[split0-1]->point;
+ Point32 p = originalVertices[split0 - 1]->point;
int split1 = split0;
while ((split1 < end) && (originalVertices[split1]->point == p))
{
@@ -1325,7 +1326,7 @@ void b3ConvexHullInternal::computeInternal(int start, int end, IntermediateHull&
void b3ConvexHullInternal::IntermediateHull::print()
{
b3Printf(" Hull\n");
- for (Vertex* v = minXy; v; )
+ for (Vertex* v = minXy; v;)
{
b3Printf(" ");
v->print();
@@ -1353,7 +1354,7 @@ void b3ConvexHullInternal::IntermediateHull::print()
}
}
if (minXy)
- {
+ {
minXy->copy = (minXy->copy == -1) ? -2 : -1;
minXy->printGraph();
}
@@ -1429,7 +1430,7 @@ b3ConvexHullInternal::Edge* b3ConvexHullInternal::findMaxAngle(bool ccw, const V
Point32 t = *e->target - *start;
Rational64 cot(t.dot(sxrxs), t.dot(rxs));
#ifdef DEBUG_CONVEX_HULL
- b3Printf(" Angle is %f (%d) for ", (float) b3Atan(cot.toScalar()), (int) cot.isNaN());
+ b3Printf(" Angle is %f (%d) for ", (float)b3Atan(cot.toScalar()), (int)cot.isNaN());
e->print();
#endif
if (cot.isNaN())
@@ -1476,7 +1477,7 @@ void b3ConvexHullInternal::findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge
b3Assert(!start1 || (start1->target->point.dot(normal) == dist));
Point64 perp = s.cross(normal);
b3Assert(!perp.isZero());
-
+
#ifdef DEBUG_CONVEX_HULL
b3Printf(" Advancing %d %d (%p %p, %d %d)\n", c0->point.index, c1->point.index, start0, start1, start0 ? start0->target->point.index : -1, start1 ? start1->target->point.index : -1);
#endif
@@ -1506,7 +1507,7 @@ void b3ConvexHullInternal::findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge
et0 = e->target->point;
}
}
-
+
btInt64_t maxDot1 = et1.dot(perp);
if (e1)
{
@@ -1543,7 +1544,7 @@ void b3ConvexHullInternal::findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge
while (true)
{
btInt64_t dy = (et1 - et0).dot(s);
-
+
if (e0 && (e0->target != stop0))
{
Edge* f0 = e0->next->reverse;
@@ -1560,7 +1561,7 @@ void b3ConvexHullInternal::findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge
}
}
}
-
+
if (e1 && (e1->target != stop1))
{
Edge* f1 = e1->reverse->next;
@@ -1595,7 +1596,7 @@ void b3ConvexHullInternal::findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge
while (true)
{
btInt64_t dy = (et1 - et0).dot(s);
-
+
if (e1 && (e1->target != stop1))
{
Edge* f1 = e1->prev->reverse;
@@ -1612,7 +1613,7 @@ void b3ConvexHullInternal::findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge
}
}
}
-
+
if (e0 && (e0->target != stop0))
{
Edge* f0 = e0->reverse->prev;
@@ -1647,7 +1648,6 @@ void b3ConvexHullInternal::findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge
#endif
}
-
void b3ConvexHullInternal::merge(IntermediateHull& h0, IntermediateHull& h1)
{
if (!h1.maxXy)
@@ -1659,7 +1659,7 @@ void b3ConvexHullInternal::merge(IntermediateHull& h0, IntermediateHull& h1)
h0 = h1;
return;
}
-
+
mergeStamp--;
Vertex* c0 = NULL;
@@ -1699,7 +1699,7 @@ void b3ConvexHullInternal::merge(IntermediateHull& h0, IntermediateHull& h1)
e = e->next;
} while (e != c0->edges);
}
-
+
e = c1->edges;
Edge* start1 = NULL;
if (e)
@@ -1751,7 +1751,7 @@ void b3ConvexHullInternal::merge(IntermediateHull& h0, IntermediateHull& h1)
Point32 r = prevPoint - c0->point;
Point64 rxs = r.cross(s);
Point64 sxrxs = s.cross(rxs);
-
+
#ifdef DEBUG_CONVEX_HULL
b3Printf("\n Checking %d %d\n", c0->point.index, c1->point.index);
#endif
@@ -1802,7 +1802,7 @@ void b3ConvexHullInternal::merge(IntermediateHull& h0, IntermediateHull& h1)
e->prev = pendingTail1;
pendingTail1 = e;
}
-
+
Edge* e0 = min0;
Edge* e1 = min1;
@@ -1819,7 +1819,7 @@ void b3ConvexHullInternal::merge(IntermediateHull& h0, IntermediateHull& h1)
{
if (toPrev1)
{
- for (Edge* e = toPrev1->next, *n = NULL; e != min1; e = n)
+ for (Edge *e = toPrev1->next, *n = NULL; e != min1; e = n)
{
n = e->next;
removeEdgePair(e);
@@ -1855,7 +1855,7 @@ void b3ConvexHullInternal::merge(IntermediateHull& h0, IntermediateHull& h1)
{
if (toPrev0)
{
- for (Edge* e = toPrev0->prev, *n = NULL; e != min0; e = n)
+ for (Edge *e = toPrev0->prev, *n = NULL; e != min0; e = n)
{
n = e->prev;
removeEdgePair(e);
@@ -1897,7 +1897,7 @@ void b3ConvexHullInternal::merge(IntermediateHull& h0, IntermediateHull& h1)
}
else
{
- for (Edge* e = toPrev0->prev, *n = NULL; e != firstNew0; e = n)
+ for (Edge *e = toPrev0->prev, *n = NULL; e != firstNew0; e = n)
{
n = e->prev;
removeEdgePair(e);
@@ -1916,7 +1916,7 @@ void b3ConvexHullInternal::merge(IntermediateHull& h0, IntermediateHull& h1)
}
else
{
- for (Edge* e = toPrev1->next, *n = NULL; e != firstNew1; e = n)
+ for (Edge *e = toPrev1->next, *n = NULL; e != firstNew1; e = n)
{
n = e->next;
removeEdgePair(e);
@@ -1927,7 +1927,7 @@ void b3ConvexHullInternal::merge(IntermediateHull& h0, IntermediateHull& h1)
pendingTail1->link(firstNew1);
}
}
-
+
return;
}
@@ -1935,7 +1935,6 @@ void b3ConvexHullInternal::merge(IntermediateHull& h0, IntermediateHull& h1)
}
}
-
static bool b3PointCmp(const b3ConvexHullInternal::Point32& p, const b3ConvexHullInternal::Point32& q)
{
return (p.y < q.y) || ((p.y == q.y) && ((p.x < q.x) || ((p.x == q.x) && (p.z < q.z))));
@@ -1943,14 +1942,14 @@ static bool b3PointCmp(const b3ConvexHullInternal::Point32& p, const b3ConvexHul
void b3ConvexHullInternal::compute(const void* coords, bool doubleCoords, int stride, int count)
{
- b3Vector3 min = b3MakeVector3(b3Scalar(1e30), b3Scalar(1e30), b3Scalar(1e30)), max = b3MakeVector3(b3Scalar(-1e30), b3Scalar(-1e30), b3Scalar(-1e30));
- const char* ptr = (const char*) coords;
+ b3Vector3 min = b3MakeVector3(b3Scalar(1e30), b3Scalar(1e30), b3Scalar(1e30)), max = b3MakeVector3(b3Scalar(-1e30), b3Scalar(-1e30), b3Scalar(-1e30));
+ const char* ptr = (const char*)coords;
if (doubleCoords)
{
for (int i = 0; i < count; i++)
{
- const double* v = (const double*) ptr;
- b3Vector3 p = b3MakeVector3((b3Scalar) v[0], (b3Scalar) v[1], (b3Scalar) v[2]);
+ const double* v = (const double*)ptr;
+ b3Vector3 p = b3MakeVector3((b3Scalar)v[0], (b3Scalar)v[1], (b3Scalar)v[2]);
ptr += stride;
min.setMin(p);
max.setMax(p);
@@ -1960,7 +1959,7 @@ void b3ConvexHullInternal::compute(const void* coords, bool doubleCoords, int st
{
for (int i = 0; i < count; i++)
{
- const float* v = (const float*) ptr;
+ const float* v = (const float*)ptr;
b3Vector3 p = b3MakeVector3(v[0], v[1], v[2]);
ptr += stride;
min.setMin(p);
@@ -2001,18 +2000,18 @@ void b3ConvexHullInternal::compute(const void* coords, bool doubleCoords, int st
b3AlignedObjectArray<Point32> points;
points.resize(count);
- ptr = (const char*) coords;
+ ptr = (const char*)coords;
if (doubleCoords)
{
for (int i = 0; i < count; i++)
{
- const double* v = (const double*) ptr;
- b3Vector3 p = b3MakeVector3((b3Scalar) v[0], (b3Scalar) v[1], (b3Scalar) v[2]);
+ const double* v = (const double*)ptr;
+ b3Vector3 p = b3MakeVector3((b3Scalar)v[0], (b3Scalar)v[1], (b3Scalar)v[2]);
ptr += stride;
p = (p - center) * s;
- points[i].x = (btInt32_t) p[medAxis];
- points[i].y = (btInt32_t) p[maxAxis];
- points[i].z = (btInt32_t) p[minAxis];
+ points[i].x = (btInt32_t)p[medAxis];
+ points[i].y = (btInt32_t)p[maxAxis];
+ points[i].z = (btInt32_t)p[minAxis];
points[i].index = i;
}
}
@@ -2020,13 +2019,13 @@ void b3ConvexHullInternal::compute(const void* coords, bool doubleCoords, int st
{
for (int i = 0; i < count; i++)
{
- const float* v = (const float*) ptr;
+ const float* v = (const float*)ptr;
b3Vector3 p = b3MakeVector3(v[0], v[1], v[2]);
ptr += stride;
p = (p - center) * s;
- points[i].x = (btInt32_t) p[medAxis];
- points[i].y = (btInt32_t) p[maxAxis];
- points[i].z = (btInt32_t) p[minAxis];
+ points[i].x = (btInt32_t)p[medAxis];
+ points[i].y = (btInt32_t)p[maxAxis];
+ points[i].z = (btInt32_t)p[minAxis];
points[i].index = i;
}
}
@@ -2180,7 +2179,7 @@ b3Scalar b3ConvexHullInternal::shrink(b3Scalar amount, b3Scalar clampAmount)
minDist = dist;
}
}
-
+
if (minDist <= 0)
{
return 0;
@@ -2221,7 +2220,7 @@ bool b3ConvexHullInternal::shiftFace(Face* face, b3Scalar amount, b3AlignedObjec
{
origShift[2] /= scaling[2];
}
- Point32 shift((btInt32_t) origShift[medAxis], (btInt32_t) origShift[maxAxis], (btInt32_t) origShift[minAxis]);
+ Point32 shift((btInt32_t)origShift[medAxis], (btInt32_t)origShift[maxAxis], (btInt32_t)origShift[minAxis]);
if (shift.isZero())
{
return true;
@@ -2229,7 +2228,7 @@ bool b3ConvexHullInternal::shiftFace(Face* face, b3Scalar amount, b3AlignedObjec
Point64 normal = face->getNormal();
#ifdef DEBUG_CONVEX_HULL
b3Printf("\nShrinking face (%d %d %d) (%d %d %d) (%d %d %d) by (%d %d %d)\n",
- face->origin.x, face->origin.y, face->origin.z, face->dir0.x, face->dir0.y, face->dir0.z, face->dir1.x, face->dir1.y, face->dir1.z, shift.x, shift.y, shift.z);
+ face->origin.x, face->origin.y, face->origin.z, face->dir0.x, face->dir0.y, face->dir0.z, face->dir1.x, face->dir1.y, face->dir1.z, shift.x, shift.y, shift.z);
#endif
btInt64_t origDot = face->origin.dot(normal);
Point32 shiftedOrigin = face->origin + shift;
@@ -2266,7 +2265,7 @@ bool b3ConvexHullInternal::shiftFace(Face* face, b3Scalar amount, b3AlignedObjec
#ifdef DEBUG_CONVEX_HULL
b3Printf("Moving downwards, edge is ");
e->print();
- b3Printf(", dot is %f (%f %lld)\n", (float) dot.toScalar(), (float) optDot.toScalar(), shiftedDot);
+ b3Printf(", dot is %f (%f %lld)\n", (float)dot.toScalar(), (float)optDot.toScalar(), shiftedDot);
#endif
if (dot.compare(optDot) < 0)
{
@@ -2302,7 +2301,7 @@ bool b3ConvexHullInternal::shiftFace(Face* face, b3Scalar amount, b3AlignedObjec
#ifdef DEBUG_CONVEX_HULL
b3Printf("Moving upwards, edge is ");
e->print();
- b3Printf(", dot is %f (%f %lld)\n", (float) dot.toScalar(), (float) optDot.toScalar(), shiftedDot);
+ b3Printf(", dot is %f (%f %lld)\n", (float)dot.toScalar(), (float)optDot.toScalar(), shiftedDot);
#endif
if (dot.compare(optDot) > 0)
{
@@ -2318,7 +2317,7 @@ bool b3ConvexHullInternal::shiftFace(Face* face, b3Scalar amount, b3AlignedObjec
}
e = e->prev;
} while (e != startEdge);
-
+
if (!intersection)
{
return true;
@@ -2355,7 +2354,7 @@ bool b3ConvexHullInternal::shiftFace(Face* face, b3Scalar amount, b3AlignedObjec
b3Printf("Needed %d iterations to check for complete containment\n", n);
#endif
}
-
+
Edge* firstIntersection = NULL;
Edge* faceEdge = NULL;
Edge* firstFaceEdge = NULL;
@@ -2464,7 +2463,7 @@ bool b3ConvexHullInternal::shiftFace(Face* face, b3Scalar amount, b3AlignedObjec
#ifdef DEBUG_CONVEX_HULL
b3Printf("1: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z);
#endif
-
+
Point64 n0 = intersection->face->getNormal();
Point64 n1 = intersection->reverse->face->getNormal();
btInt64_t m00 = face->dir0.dot(n0);
@@ -2478,16 +2477,13 @@ bool b3ConvexHullInternal::shiftFace(Face* face, b3Scalar amount, b3AlignedObjec
Vertex* v = vertexPool.newObject();
v->point.index = -1;
v->copy = -1;
- v->point128 = PointR128(Int128::mul(face->dir0.x * r0, m11) - Int128::mul(face->dir0.x * r1, m01)
- + Int128::mul(face->dir1.x * r1, m00) - Int128::mul(face->dir1.x * r0, m10) + det * shiftedOrigin.x,
- Int128::mul(face->dir0.y * r0, m11) - Int128::mul(face->dir0.y * r1, m01)
- + Int128::mul(face->dir1.y * r1, m00) - Int128::mul(face->dir1.y * r0, m10) + det * shiftedOrigin.y,
- Int128::mul(face->dir0.z * r0, m11) - Int128::mul(face->dir0.z * r1, m01)
- + Int128::mul(face->dir1.z * r1, m00) - Int128::mul(face->dir1.z * r0, m10) + det * shiftedOrigin.z,
- det);
- v->point.x = (btInt32_t) v->point128.xvalue();
- v->point.y = (btInt32_t) v->point128.yvalue();
- v->point.z = (btInt32_t) v->point128.zvalue();
+ v->point128 = PointR128(Int128::mul(face->dir0.x * r0, m11) - Int128::mul(face->dir0.x * r1, m01) + Int128::mul(face->dir1.x * r1, m00) - Int128::mul(face->dir1.x * r0, m10) + det * shiftedOrigin.x,
+ Int128::mul(face->dir0.y * r0, m11) - Int128::mul(face->dir0.y * r1, m01) + Int128::mul(face->dir1.y * r1, m00) - Int128::mul(face->dir1.y * r0, m10) + det * shiftedOrigin.y,
+ Int128::mul(face->dir0.z * r0, m11) - Int128::mul(face->dir0.z * r1, m01) + Int128::mul(face->dir1.z * r1, m00) - Int128::mul(face->dir1.z * r0, m10) + det * shiftedOrigin.z,
+ det);
+ v->point.x = (btInt32_t)v->point128.xvalue();
+ v->point.y = (btInt32_t)v->point128.yvalue();
+ v->point.z = (btInt32_t)v->point128.zvalue();
intersection->target = v;
v->edges = e;
@@ -2626,7 +2622,6 @@ bool b3ConvexHullInternal::shiftFace(Face* face, b3Scalar amount, b3AlignedObjec
return true;
}
-
static int getVertexCopy(b3ConvexHullInternal::Vertex* vertex, b3AlignedObjectArray<b3ConvexHullInternal::Vertex*>& vertices)
{
int index = vertex->copy;
@@ -2748,8 +2743,3 @@ b3Scalar b3ConvexHullComputer::compute(const void* coords, bool doubleCoords, in
return shift;
}
-
-
-
-
-
diff --git a/thirdparty/bullet/Bullet3Geometry/b3ConvexHullComputer.h b/thirdparty/bullet/Bullet3Geometry/b3ConvexHullComputer.h
index 6dcc931a78..8852c5a524 100644
--- a/thirdparty/bullet/Bullet3Geometry/b3ConvexHullComputer.h
+++ b/thirdparty/bullet/Bullet3Geometry/b3ConvexHullComputer.h
@@ -23,58 +23,56 @@ subject to the following restrictions:
/// Ole Kniemeyer, MAXON Computer GmbH
class b3ConvexHullComputer
{
+private:
+ b3Scalar compute(const void* coords, bool doubleCoords, int stride, int count, b3Scalar shrink, b3Scalar shrinkClamp);
+
+public:
+ class Edge
+ {
private:
- b3Scalar compute(const void* coords, bool doubleCoords, int stride, int count, b3Scalar shrink, b3Scalar shrinkClamp);
+ int next;
+ int reverse;
+ int targetVertex;
- public:
+ friend class b3ConvexHullComputer;
- class Edge
+ public:
+ int getSourceVertex() const
{
- private:
- int next;
- int reverse;
- int targetVertex;
-
- friend class b3ConvexHullComputer;
-
- public:
- int getSourceVertex() const
- {
- return (this + reverse)->targetVertex;
- }
-
- int getTargetVertex() const
- {
- return targetVertex;
- }
+ return (this + reverse)->targetVertex;
+ }
- const Edge* getNextEdgeOfVertex() const // clockwise list of all edges of a vertex
- {
- return this + next;
- }
+ int getTargetVertex() const
+ {
+ return targetVertex;
+ }
- const Edge* getNextEdgeOfFace() const // counter-clockwise list of all edges of a face
- {
- return (this + reverse)->getNextEdgeOfVertex();
- }
+ const Edge* getNextEdgeOfVertex() const // clockwise list of all edges of a vertex
+ {
+ return this + next;
+ }
- const Edge* getReverseEdge() const
- {
- return this + reverse;
- }
- };
+ const Edge* getNextEdgeOfFace() const // counter-clockwise list of all edges of a face
+ {
+ return (this + reverse)->getNextEdgeOfVertex();
+ }
+ const Edge* getReverseEdge() const
+ {
+ return this + reverse;
+ }
+ };
- // Vertices of the output hull
- b3AlignedObjectArray<b3Vector3> vertices;
+ // Vertices of the output hull
+ b3AlignedObjectArray<b3Vector3> vertices;
- // Edges of the output hull
- b3AlignedObjectArray<Edge> edges;
+ // Edges of the output hull
+ b3AlignedObjectArray<Edge> edges;
- // Faces of the convex hull. Each entry is an index into the "edges" array pointing to an edge of the face. Faces are planar n-gons
- b3AlignedObjectArray<int> faces;
+ // Faces of the convex hull. Each entry is an index into the "edges" array pointing to an edge of the face. Faces are planar n-gons
+ b3AlignedObjectArray<int> faces;
- /*
+ /*
Compute convex hull of "count" vertices stored in "coords". "stride" is the difference in bytes
between the addresses of consecutive vertices. If "shrink" is positive, the convex hull is shrunken
by that amount (each face is moved by "shrink" length units towards the center along its normal).
@@ -86,18 +84,16 @@ class b3ConvexHullComputer
The output convex hull can be found in the member variables "vertices", "edges", "faces".
*/
- b3Scalar compute(const float* coords, int stride, int count, b3Scalar shrink, b3Scalar shrinkClamp)
- {
- return compute(coords, false, stride, count, shrink, shrinkClamp);
- }
-
- // same as above, but double precision
- b3Scalar compute(const double* coords, int stride, int count, b3Scalar shrink, b3Scalar shrinkClamp)
- {
- return compute(coords, true, stride, count, shrink, shrinkClamp);
- }
+ b3Scalar compute(const float* coords, int stride, int count, b3Scalar shrink, b3Scalar shrinkClamp)
+ {
+ return compute(coords, false, stride, count, shrink, shrinkClamp);
+ }
+
+ // same as above, but double precision
+ b3Scalar compute(const double* coords, int stride, int count, b3Scalar shrink, b3Scalar shrinkClamp)
+ {
+ return compute(coords, true, stride, count, shrink, shrinkClamp);
+ }
};
-
-#endif //B3_CONVEX_HULL_COMPUTER_H
-
+#endif //B3_CONVEX_HULL_COMPUTER_H
diff --git a/thirdparty/bullet/Bullet3Geometry/b3GeometryUtil.cpp b/thirdparty/bullet/Bullet3Geometry/b3GeometryUtil.cpp
index dd80fed6bd..c4041003ca 100644
--- a/thirdparty/bullet/Bullet3Geometry/b3GeometryUtil.cpp
+++ b/thirdparty/bullet/Bullet3Geometry/b3GeometryUtil.cpp
@@ -12,49 +12,43 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
-
#include "b3GeometryUtil.h"
-
/*
Make sure this dummy function never changes so that it
can be used by probes that are checking whether the
library is actually installed.
*/
extern "C"
-{
- void b3BulletMathProbe ();
+{
+ void b3BulletMathProbe();
- void b3BulletMathProbe () {}
+ void b3BulletMathProbe() {}
}
-
-bool b3GeometryUtil::isPointInsidePlanes(const b3AlignedObjectArray<b3Vector3>& planeEquations, const b3Vector3& point, b3Scalar margin)
+bool b3GeometryUtil::isPointInsidePlanes(const b3AlignedObjectArray<b3Vector3>& planeEquations, const b3Vector3& point, b3Scalar margin)
{
int numbrushes = planeEquations.size();
- for (int i=0;i<numbrushes;i++)
+ for (int i = 0; i < numbrushes; i++)
{
const b3Vector3& N1 = planeEquations[i];
- b3Scalar dist = b3Scalar(N1.dot(point))+b3Scalar(N1[3])-margin;
- if (dist>b3Scalar(0.))
+ b3Scalar dist = b3Scalar(N1.dot(point)) + b3Scalar(N1[3]) - margin;
+ if (dist > b3Scalar(0.))
{
return false;
}
}
return true;
-
}
-
-bool b3GeometryUtil::areVerticesBehindPlane(const b3Vector3& planeNormal, const b3AlignedObjectArray<b3Vector3>& vertices, b3Scalar margin)
+bool b3GeometryUtil::areVerticesBehindPlane(const b3Vector3& planeNormal, const b3AlignedObjectArray<b3Vector3>& vertices, b3Scalar margin)
{
int numvertices = vertices.size();
- for (int i=0;i<numvertices;i++)
+ for (int i = 0; i < numvertices; i++)
{
const b3Vector3& N1 = vertices[i];
- b3Scalar dist = b3Scalar(planeNormal.dot(N1))+b3Scalar(planeNormal[3])-margin;
- if (dist>b3Scalar(0.))
+ b3Scalar dist = b3Scalar(planeNormal.dot(N1)) + b3Scalar(planeNormal[3]) - margin;
+ if (dist > b3Scalar(0.))
{
return false;
}
@@ -62,102 +56,98 @@ bool b3GeometryUtil::areVerticesBehindPlane(const b3Vector3& planeNormal, const
return true;
}
-bool notExist(const b3Vector3& planeEquation,const b3AlignedObjectArray<b3Vector3>& planeEquations);
+bool notExist(const b3Vector3& planeEquation, const b3AlignedObjectArray<b3Vector3>& planeEquations);
-bool notExist(const b3Vector3& planeEquation,const b3AlignedObjectArray<b3Vector3>& planeEquations)
+bool notExist(const b3Vector3& planeEquation, const b3AlignedObjectArray<b3Vector3>& planeEquations)
{
int numbrushes = planeEquations.size();
- for (int i=0;i<numbrushes;i++)
+ for (int i = 0; i < numbrushes; i++)
{
const b3Vector3& N1 = planeEquations[i];
if (planeEquation.dot(N1) > b3Scalar(0.999))
{
return false;
- }
+ }
}
return true;
}
-void b3GeometryUtil::getPlaneEquationsFromVertices(b3AlignedObjectArray<b3Vector3>& vertices, b3AlignedObjectArray<b3Vector3>& planeEquationsOut )
+void b3GeometryUtil::getPlaneEquationsFromVertices(b3AlignedObjectArray<b3Vector3>& vertices, b3AlignedObjectArray<b3Vector3>& planeEquationsOut)
{
- const int numvertices = vertices.size();
+ const int numvertices = vertices.size();
// brute force:
- for (int i=0;i<numvertices;i++)
+ for (int i = 0; i < numvertices; i++)
{
const b3Vector3& N1 = vertices[i];
-
- for (int j=i+1;j<numvertices;j++)
+ for (int j = i + 1; j < numvertices; j++)
{
const b3Vector3& N2 = vertices[j];
-
- for (int k=j+1;k<numvertices;k++)
- {
+ for (int k = j + 1; k < numvertices; k++)
+ {
const b3Vector3& N3 = vertices[k];
- b3Vector3 planeEquation,edge0,edge1;
- edge0 = N2-N1;
- edge1 = N3-N1;
+ b3Vector3 planeEquation, edge0, edge1;
+ edge0 = N2 - N1;
+ edge1 = N3 - N1;
b3Scalar normalSign = b3Scalar(1.);
- for (int ww=0;ww<2;ww++)
+ for (int ww = 0; ww < 2; ww++)
{
planeEquation = normalSign * edge0.cross(edge1);
if (planeEquation.length2() > b3Scalar(0.0001))
{
planeEquation.normalize();
- if (notExist(planeEquation,planeEquationsOut))
+ if (notExist(planeEquation, planeEquationsOut))
{
planeEquation[3] = -planeEquation.dot(N1);
-
- //check if inside, and replace supportingVertexOut if needed
- if (areVerticesBehindPlane(planeEquation,vertices,b3Scalar(0.01)))
- {
- planeEquationsOut.push_back(planeEquation);
- }
+
+ //check if inside, and replace supportingVertexOut if needed
+ if (areVerticesBehindPlane(planeEquation, vertices, b3Scalar(0.01)))
+ {
+ planeEquationsOut.push_back(planeEquation);
+ }
}
}
normalSign = b3Scalar(-1.);
}
-
}
}
}
-
}
-void b3GeometryUtil::getVerticesFromPlaneEquations(const b3AlignedObjectArray<b3Vector3>& planeEquations , b3AlignedObjectArray<b3Vector3>& verticesOut )
+void b3GeometryUtil::getVerticesFromPlaneEquations(const b3AlignedObjectArray<b3Vector3>& planeEquations, b3AlignedObjectArray<b3Vector3>& verticesOut)
{
const int numbrushes = planeEquations.size();
// brute force:
- for (int i=0;i<numbrushes;i++)
+ for (int i = 0; i < numbrushes; i++)
{
const b3Vector3& N1 = planeEquations[i];
-
- for (int j=i+1;j<numbrushes;j++)
+ for (int j = i + 1; j < numbrushes; j++)
{
const b3Vector3& N2 = planeEquations[j];
-
- for (int k=j+1;k<numbrushes;k++)
- {
+ for (int k = j + 1; k < numbrushes; k++)
+ {
const b3Vector3& N3 = planeEquations[k];
- b3Vector3 n2n3; n2n3 = N2.cross(N3);
- b3Vector3 n3n1; n3n1 = N3.cross(N1);
- b3Vector3 n1n2; n1n2 = N1.cross(N2);
-
- if ( ( n2n3.length2() > b3Scalar(0.0001) ) &&
- ( n3n1.length2() > b3Scalar(0.0001) ) &&
- ( n1n2.length2() > b3Scalar(0.0001) ) )
+ b3Vector3 n2n3;
+ n2n3 = N2.cross(N3);
+ b3Vector3 n3n1;
+ n3n1 = N3.cross(N1);
+ b3Vector3 n1n2;
+ n1n2 = N1.cross(N2);
+
+ if ((n2n3.length2() > b3Scalar(0.0001)) &&
+ (n3n1.length2() > b3Scalar(0.0001)) &&
+ (n1n2.length2() > b3Scalar(0.0001)))
{
//point P out of 3 plane equations:
- // d1 ( N2 * N3 ) + d2 ( N3 * N1 ) + d3 ( N1 * N2 )
- //P = -------------------------------------------------------------------------
- // N1 . ( N2 * N3 )
-
+ // d1 ( N2 * N3 ) + d2 ( N3 * N1 ) + d3 ( N1 * N2 )
+ //P = -------------------------------------------------------------------------
+ // N1 . ( N2 * N3 )
b3Scalar quotient = (N1.dot(n2n3));
if (b3Fabs(quotient) > b3Scalar(0.000001))
@@ -172,7 +162,7 @@ void b3GeometryUtil::getVerticesFromPlaneEquations(const b3AlignedObjectArray<b3
potentialVertex *= quotient;
//check if inside, and replace supportingVertexOut if needed
- if (isPointInsidePlanes(planeEquations,potentialVertex,b3Scalar(0.01)))
+ if (isPointInsidePlanes(planeEquations, potentialVertex, b3Scalar(0.01)))
{
verticesOut.push_back(potentialVertex);
}
@@ -182,4 +172,3 @@ void b3GeometryUtil::getVerticesFromPlaneEquations(const b3AlignedObjectArray<b3
}
}
}
-
diff --git a/thirdparty/bullet/Bullet3Geometry/b3GeometryUtil.h b/thirdparty/bullet/Bullet3Geometry/b3GeometryUtil.h
index 8b5fd7ad62..967c8d67e9 100644
--- a/thirdparty/bullet/Bullet3Geometry/b3GeometryUtil.h
+++ b/thirdparty/bullet/Bullet3Geometry/b3GeometryUtil.h
@@ -12,7 +12,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#ifndef B3_GEOMETRY_UTIL_H
#define B3_GEOMETRY_UTIL_H
@@ -22,21 +21,16 @@ subject to the following restrictions:
///The b3GeometryUtil helper class provides a few methods to convert between plane equations and vertices.
class b3GeometryUtil
{
- public:
-
-
- static void getPlaneEquationsFromVertices(b3AlignedObjectArray<b3Vector3>& vertices, b3AlignedObjectArray<b3Vector3>& planeEquationsOut );
-
- static void getVerticesFromPlaneEquations(const b3AlignedObjectArray<b3Vector3>& planeEquations , b3AlignedObjectArray<b3Vector3>& verticesOut );
-
- static bool isInside(const b3AlignedObjectArray<b3Vector3>& vertices, const b3Vector3& planeNormal, b3Scalar margin);
-
- static bool isPointInsidePlanes(const b3AlignedObjectArray<b3Vector3>& planeEquations, const b3Vector3& point, b3Scalar margin);
+public:
+ static void getPlaneEquationsFromVertices(b3AlignedObjectArray<b3Vector3>& vertices, b3AlignedObjectArray<b3Vector3>& planeEquationsOut);
- static bool areVerticesBehindPlane(const b3Vector3& planeNormal, const b3AlignedObjectArray<b3Vector3>& vertices, b3Scalar margin);
+ static void getVerticesFromPlaneEquations(const b3AlignedObjectArray<b3Vector3>& planeEquations, b3AlignedObjectArray<b3Vector3>& verticesOut);
-};
+ static bool isInside(const b3AlignedObjectArray<b3Vector3>& vertices, const b3Vector3& planeNormal, b3Scalar margin);
+ static bool isPointInsidePlanes(const b3AlignedObjectArray<b3Vector3>& planeEquations, const b3Vector3& point, b3Scalar margin);
-#endif //B3_GEOMETRY_UTIL_H
+ static bool areVerticesBehindPlane(const b3Vector3& planeNormal, const b3AlignedObjectArray<b3Vector3>& vertices, b3Scalar margin);
+};
+#endif //B3_GEOMETRY_UTIL_H
diff --git a/thirdparty/bullet/Bullet3Geometry/b3GrahamScan2dConvexHull.h b/thirdparty/bullet/Bullet3Geometry/b3GrahamScan2dConvexHull.h
index 1b933c5264..8881c9a638 100644
--- a/thirdparty/bullet/Bullet3Geometry/b3GrahamScan2dConvexHull.h
+++ b/thirdparty/bullet/Bullet3Geometry/b3GrahamScan2dConvexHull.h
@@ -13,41 +13,40 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#ifndef B3_GRAHAM_SCAN_2D_CONVEX_HULL_H
#define B3_GRAHAM_SCAN_2D_CONVEX_HULL_H
-
#include "Bullet3Common/b3Vector3.h"
#include "Bullet3Common/b3AlignedObjectArray.h"
struct b3GrahamVector3 : public b3Vector3
{
b3GrahamVector3(const b3Vector3& org, int orgIndex)
- :b3Vector3(org),
- m_orgIndex(orgIndex)
+ : b3Vector3(org),
+ m_orgIndex(orgIndex)
{
}
- b3Scalar m_angle;
+ b3Scalar m_angle;
int m_orgIndex;
};
-
-struct b3AngleCompareFunc {
+struct b3AngleCompareFunc
+{
b3Vector3 m_anchor;
b3AngleCompareFunc(const b3Vector3& anchor)
- : m_anchor(anchor)
+ : m_anchor(anchor)
{
}
- bool operator()(const b3GrahamVector3& a, const b3GrahamVector3& b) const {
+ bool operator()(const b3GrahamVector3& a, const b3GrahamVector3& b) const
+ {
if (a.m_angle != b.m_angle)
return a.m_angle < b.m_angle;
else
{
- b3Scalar al = (a-m_anchor).length2();
- b3Scalar bl = (b-m_anchor).length2();
+ b3Scalar al = (a - m_anchor).length2();
+ b3Scalar bl = (b - m_anchor).length2();
if (al != bl)
- return al < bl;
+ return al < bl;
else
{
return a.m_orgIndex < b.m_orgIndex;
@@ -58,60 +57,60 @@ struct b3AngleCompareFunc {
inline void b3GrahamScanConvexHull2D(b3AlignedObjectArray<b3GrahamVector3>& originalPoints, b3AlignedObjectArray<b3GrahamVector3>& hull, const b3Vector3& normalAxis)
{
- b3Vector3 axis0,axis1;
- b3PlaneSpace1(normalAxis,axis0,axis1);
-
+ b3Vector3 axis0, axis1;
+ b3PlaneSpace1(normalAxis, axis0, axis1);
- if (originalPoints.size()<=1)
+ if (originalPoints.size() <= 1)
{
- for (int i=0;i<originalPoints.size();i++)
+ for (int i = 0; i < originalPoints.size(); i++)
hull.push_back(originalPoints[0]);
return;
}
//step1 : find anchor point with smallest projection on axis0 and move it to first location
- for (int i=0;i<originalPoints.size();i++)
+ for (int i = 0; i < originalPoints.size(); i++)
{
-// const b3Vector3& left = originalPoints[i];
-// const b3Vector3& right = originalPoints[0];
+ // const b3Vector3& left = originalPoints[i];
+ // const b3Vector3& right = originalPoints[0];
b3Scalar projL = originalPoints[i].dot(axis0);
b3Scalar projR = originalPoints[0].dot(axis0);
if (projL < projR)
{
- originalPoints.swap(0,i);
+ originalPoints.swap(0, i);
}
}
//also precompute angles
originalPoints[0].m_angle = -1e30f;
- for (int i=1;i<originalPoints.size();i++)
+ for (int i = 1; i < originalPoints.size(); i++)
{
b3Vector3 xvec = axis0;
- b3Vector3 ar = originalPoints[i]-originalPoints[0];
+ b3Vector3 ar = originalPoints[i] - originalPoints[0];
originalPoints[i].m_angle = b3Cross(xvec, ar).dot(normalAxis) / ar.length();
}
//step 2: sort all points, based on 'angle' with this anchor
b3AngleCompareFunc comp(originalPoints[0]);
- originalPoints.quickSortInternal(comp,1,originalPoints.size()-1);
+ originalPoints.quickSortInternal(comp, 1, originalPoints.size() - 1);
int i;
- for (i = 0; i<2; i++)
+ for (i = 0; i < 2; i++)
hull.push_back(originalPoints[i]);
//step 3: keep all 'convex' points and discard concave points (using back tracking)
- for (; i != originalPoints.size(); i++)
+ for (; i != originalPoints.size(); i++)
{
bool isConvex = false;
- while (!isConvex&& hull.size()>1) {
- b3Vector3& a = hull[hull.size()-2];
- b3Vector3& b = hull[hull.size()-1];
- isConvex = b3Cross(a-b,a-originalPoints[i]).dot(normalAxis)> 0;
+ while (!isConvex && hull.size() > 1)
+ {
+ b3Vector3& a = hull[hull.size() - 2];
+ b3Vector3& b = hull[hull.size() - 1];
+ isConvex = b3Cross(a - b, a - originalPoints[i]).dot(normalAxis) > 0;
if (!isConvex)
hull.pop_back();
- else
+ else
hull.push_back(originalPoints[i]);
}
}
}
-#endif //B3_GRAHAM_SCAN_2D_CONVEX_HULL_H
+#endif //B3_GRAHAM_SCAN_2D_CONVEX_HULL_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuBroadphaseInterface.h b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuBroadphaseInterface.h
index 0ed8aa8232..b296992525 100644
--- a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuBroadphaseInterface.h
+++ b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuBroadphaseInterface.h
@@ -12,33 +12,31 @@
class b3GpuBroadphaseInterface
{
public:
-
- typedef class b3GpuBroadphaseInterface* (CreateFunc)(cl_context ctx,cl_device_id device, cl_command_queue q);
+ typedef class b3GpuBroadphaseInterface*(CreateFunc)(cl_context ctx, cl_device_id device, cl_command_queue q);
virtual ~b3GpuBroadphaseInterface()
{
}
- virtual void createProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr , int collisionFilterGroup, int collisionFilterMask)=0;
- virtual void createLargeProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr , int collisionFilterGroup, int collisionFilterMask)=0;
+ virtual void createProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask) = 0;
+ virtual void createLargeProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask) = 0;
- virtual void calculateOverlappingPairs(int maxPairs)=0;
- virtual void calculateOverlappingPairsHost(int maxPairs)=0;
+ virtual void calculateOverlappingPairs(int maxPairs) = 0;
+ virtual void calculateOverlappingPairsHost(int maxPairs) = 0;
//call writeAabbsToGpu after done making all changes (createProxy etc)
- virtual void writeAabbsToGpu()=0;
+ virtual void writeAabbsToGpu() = 0;
+
+ virtual cl_mem getAabbBufferWS() = 0;
+ virtual int getNumOverlap() = 0;
+ virtual cl_mem getOverlappingPairBuffer() = 0;
- virtual cl_mem getAabbBufferWS()=0;
- virtual int getNumOverlap()=0;
- virtual cl_mem getOverlappingPairBuffer()=0;
+ virtual b3OpenCLArray<b3SapAabb>& getAllAabbsGPU() = 0;
+ virtual b3AlignedObjectArray<b3SapAabb>& getAllAabbsCPU() = 0;
- virtual b3OpenCLArray<b3SapAabb>& getAllAabbsGPU()=0;
- virtual b3AlignedObjectArray<b3SapAabb>& getAllAabbsCPU()=0;
-
virtual b3OpenCLArray<b3Int4>& getOverlappingPairsGPU() = 0;
virtual b3OpenCLArray<int>& getSmallAabbIndicesGPU() = 0;
virtual b3OpenCLArray<int>& getLargeAabbIndicesGPU() = 0;
-
};
-#endif //B3_GPU_BROADPHASE_INTERFACE_H
+#endif //B3_GPU_BROADPHASE_INTERFACE_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuGridBroadphase.cpp b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuGridBroadphase.cpp
index 74d0c8056c..e714fadac3 100644
--- a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuGridBroadphase.cpp
+++ b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuGridBroadphase.cpp
@@ -5,12 +5,9 @@
#include "kernels/sapKernels.h"
//#include "kernels/gridBroadphase.cl"
-
#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
#include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
-
-
#define B3_BROADPHASE_SAP_PATH "src/Bullet3OpenCL/BroadphaseCollision/kernels/sap.cl"
#define B3_GRID_BROADPHASE_PATH "src/Bullet3OpenCL/BroadphaseCollision/kernels/gridBroadphase.cl"
@@ -21,31 +18,25 @@ cl_kernel kFindOverlappingPairs;
cl_kernel m_copyAabbsKernel;
cl_kernel m_sap2Kernel;
-
-
-
-
//int maxPairsPerBody = 64;
-int maxBodiesPerCell = 256;//??
+int maxBodiesPerCell = 256; //??
-b3GpuGridBroadphase::b3GpuGridBroadphase(cl_context ctx,cl_device_id device, cl_command_queue q )
-:m_context(ctx),
-m_device(device),
-m_queue(q),
-m_allAabbsGPU1(ctx,q),
-m_smallAabbsMappingGPU(ctx,q),
-m_largeAabbsMappingGPU(ctx,q),
-m_gpuPairs(ctx,q),
+b3GpuGridBroadphase::b3GpuGridBroadphase(cl_context ctx, cl_device_id device, cl_command_queue q)
+ : m_context(ctx),
+ m_device(device),
+ m_queue(q),
+ m_allAabbsGPU1(ctx, q),
+ m_smallAabbsMappingGPU(ctx, q),
+ m_largeAabbsMappingGPU(ctx, q),
+ m_gpuPairs(ctx, q),
-m_hashGpu(ctx,q),
+ m_hashGpu(ctx, q),
-m_cellStartGpu(ctx,q),
-m_paramsGPU(ctx,q)
+ m_cellStartGpu(ctx, q),
+ m_paramsGPU(ctx, q)
{
-
-
- b3Vector3 gridSize = b3MakeVector3(3,3,3);
- b3Vector3 invGridSize = b3MakeVector3(1.f/gridSize[0],1.f/gridSize[1],1.f/gridSize[2]);
+ b3Vector3 gridSize = b3MakeVector3(3, 3, 3);
+ b3Vector3 invGridSize = b3MakeVector3(1.f / gridSize[0], 1.f / gridSize[1], 1.f / gridSize[2]);
m_paramsCPU.m_gridSize[0] = 128;
m_paramsCPU.m_gridSize[1] = 128;
@@ -58,92 +49,79 @@ m_paramsGPU(ctx,q)
m_paramsCPU.m_invCellSize[3] = 0.f;
m_paramsGPU.push_back(m_paramsCPU);
- cl_int errNum=0;
+ cl_int errNum = 0;
{
const char* sapSrc = sapCL;
- cl_program sapProg = b3OpenCLUtils::compileCLProgramFromString(m_context,m_device,sapSrc,&errNum,"",B3_BROADPHASE_SAP_PATH);
- b3Assert(errNum==CL_SUCCESS);
- m_copyAabbsKernel= b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,sapSrc, "copyAabbsKernel",&errNum,sapProg );
- m_sap2Kernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,sapSrc, "computePairsKernelTwoArrays",&errNum,sapProg );
- b3Assert(errNum==CL_SUCCESS);
+ cl_program sapProg = b3OpenCLUtils::compileCLProgramFromString(m_context, m_device, sapSrc, &errNum, "", B3_BROADPHASE_SAP_PATH);
+ b3Assert(errNum == CL_SUCCESS);
+ m_copyAabbsKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, sapSrc, "copyAabbsKernel", &errNum, sapProg);
+ m_sap2Kernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, sapSrc, "computePairsKernelTwoArrays", &errNum, sapProg);
+ b3Assert(errNum == CL_SUCCESS);
}
{
-
- cl_program gridProg = b3OpenCLUtils::compileCLProgramFromString(m_context,m_device,gridBroadphaseCL,&errNum,"",B3_GRID_BROADPHASE_PATH);
- b3Assert(errNum==CL_SUCCESS);
-
- kCalcHashAABB = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,gridBroadphaseCL, "kCalcHashAABB",&errNum,gridProg);
- b3Assert(errNum==CL_SUCCESS);
-
- kClearCellStart = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,gridBroadphaseCL, "kClearCellStart",&errNum,gridProg);
- b3Assert(errNum==CL_SUCCESS);
-
- kFindCellStart = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,gridBroadphaseCL, "kFindCellStart",&errNum,gridProg);
- b3Assert(errNum==CL_SUCCESS);
-
-
- kFindOverlappingPairs = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,gridBroadphaseCL, "kFindOverlappingPairs",&errNum,gridProg);
- b3Assert(errNum==CL_SUCCESS);
-
-
-
-
- }
+ cl_program gridProg = b3OpenCLUtils::compileCLProgramFromString(m_context, m_device, gridBroadphaseCL, &errNum, "", B3_GRID_BROADPHASE_PATH);
+ b3Assert(errNum == CL_SUCCESS);
- m_sorter = new b3RadixSort32CL(m_context,m_device,m_queue);
+ kCalcHashAABB = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, gridBroadphaseCL, "kCalcHashAABB", &errNum, gridProg);
+ b3Assert(errNum == CL_SUCCESS);
+ kClearCellStart = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, gridBroadphaseCL, "kClearCellStart", &errNum, gridProg);
+ b3Assert(errNum == CL_SUCCESS);
+
+ kFindCellStart = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, gridBroadphaseCL, "kFindCellStart", &errNum, gridProg);
+ b3Assert(errNum == CL_SUCCESS);
+
+ kFindOverlappingPairs = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, gridBroadphaseCL, "kFindOverlappingPairs", &errNum, gridProg);
+ b3Assert(errNum == CL_SUCCESS);
+ }
+
+ m_sorter = new b3RadixSort32CL(m_context, m_device, m_queue);
}
b3GpuGridBroadphase::~b3GpuGridBroadphase()
{
- clReleaseKernel( kCalcHashAABB);
- clReleaseKernel( kClearCellStart);
- clReleaseKernel( kFindCellStart);
- clReleaseKernel( kFindOverlappingPairs);
- clReleaseKernel( m_sap2Kernel);
- clReleaseKernel( m_copyAabbsKernel);
-
-
-
+ clReleaseKernel(kCalcHashAABB);
+ clReleaseKernel(kClearCellStart);
+ clReleaseKernel(kFindCellStart);
+ clReleaseKernel(kFindOverlappingPairs);
+ clReleaseKernel(m_sap2Kernel);
+ clReleaseKernel(m_copyAabbsKernel);
+
delete m_sorter;
}
-
-
-void b3GpuGridBroadphase::createProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr , int collisionFilterGroup, int collisionFilterMask)
+void b3GpuGridBroadphase::createProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask)
{
b3SapAabb aabb;
aabb.m_minVec = aabbMin;
aabb.m_maxVec = aabbMax;
aabb.m_minIndices[3] = userPtr;
- aabb.m_signedMaxIndices[3] = m_allAabbsCPU1.size();//NOT userPtr;
+ aabb.m_signedMaxIndices[3] = m_allAabbsCPU1.size(); //NOT userPtr;
m_smallAabbsMappingCPU.push_back(m_allAabbsCPU1.size());
m_allAabbsCPU1.push_back(aabb);
-
}
-void b3GpuGridBroadphase::createLargeProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr , int collisionFilterGroup, int collisionFilterMask)
+void b3GpuGridBroadphase::createLargeProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask)
{
b3SapAabb aabb;
aabb.m_minVec = aabbMin;
aabb.m_maxVec = aabbMax;
aabb.m_minIndices[3] = userPtr;
- aabb.m_signedMaxIndices[3] = m_allAabbsCPU1.size();//NOT userPtr;
+ aabb.m_signedMaxIndices[3] = m_allAabbsCPU1.size(); //NOT userPtr;
m_largeAabbsMappingCPU.push_back(m_allAabbsCPU1.size());
m_allAabbsCPU1.push_back(aabb);
}
-void b3GpuGridBroadphase::calculateOverlappingPairs(int maxPairs)
+void b3GpuGridBroadphase::calculateOverlappingPairs(int maxPairs)
{
B3_PROFILE("b3GpuGridBroadphase::calculateOverlappingPairs");
-
if (0)
{
calculateOverlappingPairsHost(maxPairs);
- /*
+ /*
b3AlignedObjectArray<b3Int4> cpuPairs;
m_gpuPairs.copyToHost(cpuPairs);
printf("host m_gpuPairs.size()=%d\n",m_gpuPairs.size());
@@ -154,57 +132,50 @@ void b3GpuGridBroadphase::calculateOverlappingPairs(int maxPairs)
*/
return;
}
-
-
-
-
int numSmallAabbs = m_smallAabbsMappingGPU.size();
- b3OpenCLArray<int> pairCount(m_context,m_queue);
+ b3OpenCLArray<int> pairCount(m_context, m_queue);
pairCount.push_back(0);
- m_gpuPairs.resize(maxPairs);//numSmallAabbs*maxPairsPerBody);
+ m_gpuPairs.resize(maxPairs); //numSmallAabbs*maxPairsPerBody);
{
int numLargeAabbs = m_largeAabbsMappingGPU.size();
if (numLargeAabbs && numSmallAabbs)
{
B3_PROFILE("sap2Kernel");
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL( m_allAabbsGPU1.getBufferCL() ),
- b3BufferInfoCL( m_largeAabbsMappingGPU.getBufferCL() ),
- b3BufferInfoCL( m_smallAabbsMappingGPU.getBufferCL() ),
- b3BufferInfoCL( m_gpuPairs.getBufferCL() ),
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL(m_allAabbsGPU1.getBufferCL()),
+ b3BufferInfoCL(m_largeAabbsMappingGPU.getBufferCL()),
+ b3BufferInfoCL(m_smallAabbsMappingGPU.getBufferCL()),
+ b3BufferInfoCL(m_gpuPairs.getBufferCL()),
b3BufferInfoCL(pairCount.getBufferCL())};
- b3LauncherCL launcher(m_queue, m_sap2Kernel,"m_sap2Kernel");
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst( numLargeAabbs );
- launcher.setConst( numSmallAabbs);
- launcher.setConst( 0 );//axis is not used
- launcher.setConst( maxPairs );
- //@todo: use actual maximum work item sizes of the device instead of hardcoded values
- launcher.launch2D( numLargeAabbs, numSmallAabbs,4,64);
-
+ b3LauncherCL launcher(m_queue, m_sap2Kernel, "m_sap2Kernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setConst(numLargeAabbs);
+ launcher.setConst(numSmallAabbs);
+ launcher.setConst(0); //axis is not used
+ launcher.setConst(maxPairs);
+ //@todo: use actual maximum work item sizes of the device instead of hardcoded values
+ launcher.launch2D(numLargeAabbs, numSmallAabbs, 4, 64);
+
int numPairs = pairCount.at(0);
-
- if (numPairs >maxPairs)
+
+ if (numPairs > maxPairs)
{
b3Error("Error running out of pairs: numPairs = %d, maxPairs = %d.\n", numPairs, maxPairs);
- numPairs =maxPairs;
+ numPairs = maxPairs;
}
}
}
-
-
-
if (numSmallAabbs)
{
B3_PROFILE("gridKernel");
m_hashGpu.resize(numSmallAabbs);
{
B3_PROFILE("kCalcHashAABB");
- b3LauncherCL launch(m_queue,kCalcHashAABB,"kCalcHashAABB");
+ b3LauncherCL launch(m_queue, kCalcHashAABB, "kCalcHashAABB");
launch.setConst(numSmallAabbs);
launch.setBuffer(m_allAabbsGPU1.getBufferCL());
launch.setBuffer(m_smallAabbsMappingGPU.getBufferCL());
@@ -214,117 +185,104 @@ void b3GpuGridBroadphase::calculateOverlappingPairs(int maxPairs)
}
m_sorter->execute(m_hashGpu);
-
- int numCells = this->m_paramsCPU.m_gridSize[0]*this->m_paramsCPU.m_gridSize[1]*this->m_paramsCPU.m_gridSize[2];
+
+ int numCells = this->m_paramsCPU.m_gridSize[0] * this->m_paramsCPU.m_gridSize[1] * this->m_paramsCPU.m_gridSize[2];
m_cellStartGpu.resize(numCells);
//b3AlignedObjectArray<int > cellStartCpu;
-
-
+
{
B3_PROFILE("kClearCellStart");
- b3LauncherCL launch(m_queue,kClearCellStart,"kClearCellStart");
+ b3LauncherCL launch(m_queue, kClearCellStart, "kClearCellStart");
launch.setConst(numCells);
launch.setBuffer(m_cellStartGpu.getBufferCL());
launch.launch1D(numCells);
//m_cellStartGpu.copyToHost(cellStartCpu);
//printf("??\n");
-
}
-
{
B3_PROFILE("kFindCellStart");
- b3LauncherCL launch(m_queue,kFindCellStart,"kFindCellStart");
+ b3LauncherCL launch(m_queue, kFindCellStart, "kFindCellStart");
launch.setConst(numSmallAabbs);
launch.setBuffer(m_hashGpu.getBufferCL());
launch.setBuffer(m_cellStartGpu.getBufferCL());
launch.launch1D(numSmallAabbs);
//m_cellStartGpu.copyToHost(cellStartCpu);
//printf("??\n");
-
}
-
+
{
B3_PROFILE("kFindOverlappingPairs");
-
-
- b3LauncherCL launch(m_queue,kFindOverlappingPairs,"kFindOverlappingPairs");
+
+ b3LauncherCL launch(m_queue, kFindOverlappingPairs, "kFindOverlappingPairs");
launch.setConst(numSmallAabbs);
launch.setBuffer(m_allAabbsGPU1.getBufferCL());
launch.setBuffer(m_smallAabbsMappingGPU.getBufferCL());
launch.setBuffer(m_hashGpu.getBufferCL());
launch.setBuffer(m_cellStartGpu.getBufferCL());
-
+
launch.setBuffer(m_paramsGPU.getBufferCL());
//launch.setBuffer(0);
launch.setBuffer(pairCount.getBufferCL());
launch.setBuffer(m_gpuPairs.getBufferCL());
-
+
launch.setConst(maxPairs);
launch.launch1D(numSmallAabbs);
-
int numPairs = pairCount.at(0);
- if (numPairs >maxPairs)
+ if (numPairs > maxPairs)
{
b3Error("Error running out of pairs: numPairs = %d, maxPairs = %d.\n", numPairs, maxPairs);
- numPairs =maxPairs;
+ numPairs = maxPairs;
}
-
+
m_gpuPairs.resize(numPairs);
-
+
if (0)
{
b3AlignedObjectArray<b3Int4> pairsCpu;
m_gpuPairs.copyToHost(pairsCpu);
int sz = m_gpuPairs.size();
- printf("m_gpuPairs.size()=%d\n",sz);
- for (int i=0;i<m_gpuPairs.size();i++)
+ printf("m_gpuPairs.size()=%d\n", sz);
+ for (int i = 0; i < m_gpuPairs.size(); i++)
{
- printf("pair %d = %d,%d\n",i,pairsCpu[i].x,pairsCpu[i].y);
+ printf("pair %d = %d,%d\n", i, pairsCpu[i].x, pairsCpu[i].y);
}
printf("?!?\n");
}
-
}
-
-
}
-
-
-
-
//calculateOverlappingPairsHost(maxPairs);
}
-void b3GpuGridBroadphase::calculateOverlappingPairsHost(int maxPairs)
+void b3GpuGridBroadphase::calculateOverlappingPairsHost(int maxPairs)
{
-
m_hostPairs.resize(0);
m_allAabbsGPU1.copyToHost(m_allAabbsCPU1);
- for (int i=0;i<m_allAabbsCPU1.size();i++)
+ for (int i = 0; i < m_allAabbsCPU1.size(); i++)
{
- for (int j=i+1;j<m_allAabbsCPU1.size();j++)
+ for (int j = i + 1; j < m_allAabbsCPU1.size(); j++)
{
if (b3TestAabbAgainstAabb2(m_allAabbsCPU1[i].m_minVec, m_allAabbsCPU1[i].m_maxVec,
- m_allAabbsCPU1[j].m_minVec,m_allAabbsCPU1[j].m_maxVec))
+ m_allAabbsCPU1[j].m_minVec, m_allAabbsCPU1[j].m_maxVec))
{
b3Int4 pair;
int a = m_allAabbsCPU1[j].m_minIndices[3];
int b = m_allAabbsCPU1[i].m_minIndices[3];
- if (a<=b)
+ if (a <= b)
{
- pair.x = a;
- pair.y = b;//store the original index in the unsorted aabb array
- } else
+ pair.x = a;
+ pair.y = b; //store the original index in the unsorted aabb array
+ }
+ else
{
pair.x = b;
- pair.y = a;//store the original index in the unsorted aabb array
+ pair.y = a; //store the original index in the unsorted aabb array
}
-
- if (m_hostPairs.size()<maxPairs)
+
+ if (m_hostPairs.size() < maxPairs)
{
m_hostPairs.push_back(pair);
}
@@ -332,40 +290,36 @@ void b3GpuGridBroadphase::calculateOverlappingPairsHost(int maxPairs)
}
}
-
m_gpuPairs.copyFromHost(m_hostPairs);
-
-
}
- //call writeAabbsToGpu after done making all changes (createProxy etc)
+//call writeAabbsToGpu after done making all changes (createProxy etc)
void b3GpuGridBroadphase::writeAabbsToGpu()
{
m_allAabbsGPU1.copyFromHost(m_allAabbsCPU1);
m_smallAabbsMappingGPU.copyFromHost(m_smallAabbsMappingCPU);
m_largeAabbsMappingGPU.copyFromHost(m_largeAabbsMappingCPU);
-
}
-cl_mem b3GpuGridBroadphase::getAabbBufferWS()
+cl_mem b3GpuGridBroadphase::getAabbBufferWS()
{
return this->m_allAabbsGPU1.getBufferCL();
}
-int b3GpuGridBroadphase::getNumOverlap()
+int b3GpuGridBroadphase::getNumOverlap()
{
return m_gpuPairs.size();
}
-cl_mem b3GpuGridBroadphase::getOverlappingPairBuffer()
+cl_mem b3GpuGridBroadphase::getOverlappingPairBuffer()
{
return m_gpuPairs.getBufferCL();
}
-b3OpenCLArray<b3SapAabb>& b3GpuGridBroadphase::getAllAabbsGPU()
+b3OpenCLArray<b3SapAabb>& b3GpuGridBroadphase::getAllAabbsGPU()
{
return m_allAabbsGPU1;
}
-b3AlignedObjectArray<b3SapAabb>& b3GpuGridBroadphase::getAllAabbsCPU()
+b3AlignedObjectArray<b3SapAabb>& b3GpuGridBroadphase::getAllAabbsCPU()
{
return m_allAabbsCPU1;
}
@@ -382,4 +336,3 @@ b3OpenCLArray<int>& b3GpuGridBroadphase::getLargeAabbIndicesGPU()
{
return m_largeAabbsMappingGPU;
}
-
diff --git a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuGridBroadphase.h b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuGridBroadphase.h
index ec18c9f716..b76cb43b68 100644
--- a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuGridBroadphase.h
+++ b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuGridBroadphase.h
@@ -6,83 +6,75 @@
struct b3ParamsGridBroadphaseCL
{
-
float m_invCellSize[4];
- int m_gridSize[4];
+ int m_gridSize[4];
- int getMaxBodiesPerCell() const
+ int getMaxBodiesPerCell() const
{
return m_gridSize[3];
}
- void setMaxBodiesPerCell(int maxOverlap)
+ void setMaxBodiesPerCell(int maxOverlap)
{
m_gridSize[3] = maxOverlap;
}
};
-
class b3GpuGridBroadphase : public b3GpuBroadphaseInterface
{
protected:
- cl_context m_context;
- cl_device_id m_device;
- cl_command_queue m_queue;
+ cl_context m_context;
+ cl_device_id m_device;
+ cl_command_queue m_queue;
- b3OpenCLArray<b3SapAabb> m_allAabbsGPU1;
- b3AlignedObjectArray<b3SapAabb> m_allAabbsCPU1;
+ b3OpenCLArray<b3SapAabb> m_allAabbsGPU1;
+ b3AlignedObjectArray<b3SapAabb> m_allAabbsCPU1;
- b3OpenCLArray<int> m_smallAabbsMappingGPU;
+ b3OpenCLArray<int> m_smallAabbsMappingGPU;
b3AlignedObjectArray<int> m_smallAabbsMappingCPU;
- b3OpenCLArray<int> m_largeAabbsMappingGPU;
+ b3OpenCLArray<int> m_largeAabbsMappingGPU;
b3AlignedObjectArray<int> m_largeAabbsMappingCPU;
b3AlignedObjectArray<b3Int4> m_hostPairs;
- b3OpenCLArray<b3Int4> m_gpuPairs;
+ b3OpenCLArray<b3Int4> m_gpuPairs;
- b3OpenCLArray<b3SortData> m_hashGpu;
- b3OpenCLArray<int> m_cellStartGpu;
-
+ b3OpenCLArray<b3SortData> m_hashGpu;
+ b3OpenCLArray<int> m_cellStartGpu;
- b3ParamsGridBroadphaseCL m_paramsCPU;
- b3OpenCLArray<b3ParamsGridBroadphaseCL> m_paramsGPU;
+ b3ParamsGridBroadphaseCL m_paramsCPU;
+ b3OpenCLArray<b3ParamsGridBroadphaseCL> m_paramsGPU;
- class b3RadixSort32CL* m_sorter;
+ class b3RadixSort32CL* m_sorter;
public:
-
- b3GpuGridBroadphase(cl_context ctx,cl_device_id device, cl_command_queue q );
+ b3GpuGridBroadphase(cl_context ctx, cl_device_id device, cl_command_queue q);
virtual ~b3GpuGridBroadphase();
- static b3GpuBroadphaseInterface* CreateFunc(cl_context ctx,cl_device_id device, cl_command_queue q)
+ static b3GpuBroadphaseInterface* CreateFunc(cl_context ctx, cl_device_id device, cl_command_queue q)
{
- return new b3GpuGridBroadphase(ctx,device,q);
+ return new b3GpuGridBroadphase(ctx, device, q);
}
-
-
+ virtual void createProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask);
+ virtual void createLargeProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask);
- virtual void createProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr , int collisionFilterGroup, int collisionFilterMask);
- virtual void createLargeProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr , int collisionFilterGroup, int collisionFilterMask);
-
- virtual void calculateOverlappingPairs(int maxPairs);
- virtual void calculateOverlappingPairsHost(int maxPairs);
+ virtual void calculateOverlappingPairs(int maxPairs);
+ virtual void calculateOverlappingPairsHost(int maxPairs);
//call writeAabbsToGpu after done making all changes (createProxy etc)
virtual void writeAabbsToGpu();
- virtual cl_mem getAabbBufferWS();
- virtual int getNumOverlap();
- virtual cl_mem getOverlappingPairBuffer();
+ virtual cl_mem getAabbBufferWS();
+ virtual int getNumOverlap();
+ virtual cl_mem getOverlappingPairBuffer();
+
+ virtual b3OpenCLArray<b3SapAabb>& getAllAabbsGPU();
+ virtual b3AlignedObjectArray<b3SapAabb>& getAllAabbsCPU();
- virtual b3OpenCLArray<b3SapAabb>& getAllAabbsGPU();
- virtual b3AlignedObjectArray<b3SapAabb>& getAllAabbsCPU();
-
virtual b3OpenCLArray<b3Int4>& getOverlappingPairsGPU();
virtual b3OpenCLArray<int>& getSmallAabbIndicesGPU();
virtual b3OpenCLArray<int>& getLargeAabbIndicesGPU();
-
};
-#endif //B3_GPU_GRID_BROADPHASE_H \ No newline at end of file
+#endif //B3_GPU_GRID_BROADPHASE_H \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.cpp b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.cpp
index 641df9eb12..0721928684 100644
--- a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.cpp
+++ b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.cpp
@@ -16,177 +16,174 @@ subject to the following restrictions:
#include "b3GpuParallelLinearBvh.h"
-b3GpuParallelLinearBvh::b3GpuParallelLinearBvh(cl_context context, cl_device_id device, cl_command_queue queue) :
- m_queue(queue),
- m_radixSorter(context, device, queue),
-
- m_rootNodeIndex(context, queue),
- m_maxDistanceFromRoot(context, queue),
- m_temp(context, queue),
-
- m_internalNodeAabbs(context, queue),
- m_internalNodeLeafIndexRanges(context, queue),
- m_internalNodeChildNodes(context, queue),
- m_internalNodeParentNodes(context, queue),
-
- m_commonPrefixes(context, queue),
- m_commonPrefixLengths(context, queue),
- m_distanceFromRoot(context, queue),
-
- m_leafNodeParentNodes(context, queue),
- m_mortonCodesAndAabbIndicies(context, queue),
- m_mergedAabb(context, queue),
- m_leafNodeAabbs(context, queue),
-
- m_largeAabbs(context, queue)
+b3GpuParallelLinearBvh::b3GpuParallelLinearBvh(cl_context context, cl_device_id device, cl_command_queue queue) : m_queue(queue),
+ m_radixSorter(context, device, queue),
+
+ m_rootNodeIndex(context, queue),
+ m_maxDistanceFromRoot(context, queue),
+ m_temp(context, queue),
+
+ m_internalNodeAabbs(context, queue),
+ m_internalNodeLeafIndexRanges(context, queue),
+ m_internalNodeChildNodes(context, queue),
+ m_internalNodeParentNodes(context, queue),
+
+ m_commonPrefixes(context, queue),
+ m_commonPrefixLengths(context, queue),
+ m_distanceFromRoot(context, queue),
+
+ m_leafNodeParentNodes(context, queue),
+ m_mortonCodesAndAabbIndicies(context, queue),
+ m_mergedAabb(context, queue),
+ m_leafNodeAabbs(context, queue),
+
+ m_largeAabbs(context, queue)
{
m_rootNodeIndex.resize(1);
m_maxDistanceFromRoot.resize(1);
m_temp.resize(1);
-
+
//
const char CL_PROGRAM_PATH[] = "src/Bullet3OpenCL/BroadphaseCollision/kernels/parallelLinearBvh.cl";
-
- const char* kernelSource = parallelLinearBvhCL; //parallelLinearBvhCL.h
+
+ const char* kernelSource = parallelLinearBvhCL; //parallelLinearBvhCL.h
cl_int error;
char* additionalMacros = 0;
m_parallelLinearBvhProgram = b3OpenCLUtils::compileCLProgramFromString(context, device, kernelSource, &error, additionalMacros, CL_PROGRAM_PATH);
b3Assert(m_parallelLinearBvhProgram);
-
- m_separateAabbsKernel = b3OpenCLUtils::compileCLKernelFromString( context, device, kernelSource, "separateAabbs", &error, m_parallelLinearBvhProgram, additionalMacros );
+
+ m_separateAabbsKernel = b3OpenCLUtils::compileCLKernelFromString(context, device, kernelSource, "separateAabbs", &error, m_parallelLinearBvhProgram, additionalMacros);
b3Assert(m_separateAabbsKernel);
- m_findAllNodesMergedAabbKernel = b3OpenCLUtils::compileCLKernelFromString( context, device, kernelSource, "findAllNodesMergedAabb", &error, m_parallelLinearBvhProgram, additionalMacros );
+ m_findAllNodesMergedAabbKernel = b3OpenCLUtils::compileCLKernelFromString(context, device, kernelSource, "findAllNodesMergedAabb", &error, m_parallelLinearBvhProgram, additionalMacros);
b3Assert(m_findAllNodesMergedAabbKernel);
- m_assignMortonCodesAndAabbIndiciesKernel = b3OpenCLUtils::compileCLKernelFromString( context, device, kernelSource, "assignMortonCodesAndAabbIndicies", &error, m_parallelLinearBvhProgram, additionalMacros );
+ m_assignMortonCodesAndAabbIndiciesKernel = b3OpenCLUtils::compileCLKernelFromString(context, device, kernelSource, "assignMortonCodesAndAabbIndicies", &error, m_parallelLinearBvhProgram, additionalMacros);
b3Assert(m_assignMortonCodesAndAabbIndiciesKernel);
-
- m_computeAdjacentPairCommonPrefixKernel = b3OpenCLUtils::compileCLKernelFromString( context, device, kernelSource, "computeAdjacentPairCommonPrefix", &error, m_parallelLinearBvhProgram, additionalMacros );
+
+ m_computeAdjacentPairCommonPrefixKernel = b3OpenCLUtils::compileCLKernelFromString(context, device, kernelSource, "computeAdjacentPairCommonPrefix", &error, m_parallelLinearBvhProgram, additionalMacros);
b3Assert(m_computeAdjacentPairCommonPrefixKernel);
- m_buildBinaryRadixTreeLeafNodesKernel = b3OpenCLUtils::compileCLKernelFromString( context, device, kernelSource, "buildBinaryRadixTreeLeafNodes", &error, m_parallelLinearBvhProgram, additionalMacros );
+ m_buildBinaryRadixTreeLeafNodesKernel = b3OpenCLUtils::compileCLKernelFromString(context, device, kernelSource, "buildBinaryRadixTreeLeafNodes", &error, m_parallelLinearBvhProgram, additionalMacros);
b3Assert(m_buildBinaryRadixTreeLeafNodesKernel);
- m_buildBinaryRadixTreeInternalNodesKernel = b3OpenCLUtils::compileCLKernelFromString( context, device, kernelSource, "buildBinaryRadixTreeInternalNodes", &error, m_parallelLinearBvhProgram, additionalMacros );
+ m_buildBinaryRadixTreeInternalNodesKernel = b3OpenCLUtils::compileCLKernelFromString(context, device, kernelSource, "buildBinaryRadixTreeInternalNodes", &error, m_parallelLinearBvhProgram, additionalMacros);
b3Assert(m_buildBinaryRadixTreeInternalNodesKernel);
- m_findDistanceFromRootKernel = b3OpenCLUtils::compileCLKernelFromString( context, device, kernelSource, "findDistanceFromRoot", &error, m_parallelLinearBvhProgram, additionalMacros );
+ m_findDistanceFromRootKernel = b3OpenCLUtils::compileCLKernelFromString(context, device, kernelSource, "findDistanceFromRoot", &error, m_parallelLinearBvhProgram, additionalMacros);
b3Assert(m_findDistanceFromRootKernel);
- m_buildBinaryRadixTreeAabbsRecursiveKernel = b3OpenCLUtils::compileCLKernelFromString( context, device, kernelSource, "buildBinaryRadixTreeAabbsRecursive", &error, m_parallelLinearBvhProgram, additionalMacros );
+ m_buildBinaryRadixTreeAabbsRecursiveKernel = b3OpenCLUtils::compileCLKernelFromString(context, device, kernelSource, "buildBinaryRadixTreeAabbsRecursive", &error, m_parallelLinearBvhProgram, additionalMacros);
b3Assert(m_buildBinaryRadixTreeAabbsRecursiveKernel);
-
- m_findLeafIndexRangesKernel = b3OpenCLUtils::compileCLKernelFromString( context, device, kernelSource, "findLeafIndexRanges", &error, m_parallelLinearBvhProgram, additionalMacros );
+
+ m_findLeafIndexRangesKernel = b3OpenCLUtils::compileCLKernelFromString(context, device, kernelSource, "findLeafIndexRanges", &error, m_parallelLinearBvhProgram, additionalMacros);
b3Assert(m_findLeafIndexRangesKernel);
-
- m_plbvhCalculateOverlappingPairsKernel = b3OpenCLUtils::compileCLKernelFromString( context, device, kernelSource, "plbvhCalculateOverlappingPairs", &error, m_parallelLinearBvhProgram, additionalMacros );
+
+ m_plbvhCalculateOverlappingPairsKernel = b3OpenCLUtils::compileCLKernelFromString(context, device, kernelSource, "plbvhCalculateOverlappingPairs", &error, m_parallelLinearBvhProgram, additionalMacros);
b3Assert(m_plbvhCalculateOverlappingPairsKernel);
- m_plbvhRayTraverseKernel = b3OpenCLUtils::compileCLKernelFromString( context, device, kernelSource, "plbvhRayTraverse", &error, m_parallelLinearBvhProgram, additionalMacros );
+ m_plbvhRayTraverseKernel = b3OpenCLUtils::compileCLKernelFromString(context, device, kernelSource, "plbvhRayTraverse", &error, m_parallelLinearBvhProgram, additionalMacros);
b3Assert(m_plbvhRayTraverseKernel);
- m_plbvhLargeAabbAabbTestKernel = b3OpenCLUtils::compileCLKernelFromString( context, device, kernelSource, "plbvhLargeAabbAabbTest", &error, m_parallelLinearBvhProgram, additionalMacros );
+ m_plbvhLargeAabbAabbTestKernel = b3OpenCLUtils::compileCLKernelFromString(context, device, kernelSource, "plbvhLargeAabbAabbTest", &error, m_parallelLinearBvhProgram, additionalMacros);
b3Assert(m_plbvhLargeAabbAabbTestKernel);
- m_plbvhLargeAabbRayTestKernel = b3OpenCLUtils::compileCLKernelFromString( context, device, kernelSource, "plbvhLargeAabbRayTest", &error, m_parallelLinearBvhProgram, additionalMacros );
+ m_plbvhLargeAabbRayTestKernel = b3OpenCLUtils::compileCLKernelFromString(context, device, kernelSource, "plbvhLargeAabbRayTest", &error, m_parallelLinearBvhProgram, additionalMacros);
b3Assert(m_plbvhLargeAabbRayTestKernel);
}
-b3GpuParallelLinearBvh::~b3GpuParallelLinearBvh()
+b3GpuParallelLinearBvh::~b3GpuParallelLinearBvh()
{
clReleaseKernel(m_separateAabbsKernel);
clReleaseKernel(m_findAllNodesMergedAabbKernel);
clReleaseKernel(m_assignMortonCodesAndAabbIndiciesKernel);
-
+
clReleaseKernel(m_computeAdjacentPairCommonPrefixKernel);
clReleaseKernel(m_buildBinaryRadixTreeLeafNodesKernel);
clReleaseKernel(m_buildBinaryRadixTreeInternalNodesKernel);
clReleaseKernel(m_findDistanceFromRootKernel);
clReleaseKernel(m_buildBinaryRadixTreeAabbsRecursiveKernel);
-
+
clReleaseKernel(m_findLeafIndexRangesKernel);
-
+
clReleaseKernel(m_plbvhCalculateOverlappingPairsKernel);
clReleaseKernel(m_plbvhRayTraverseKernel);
clReleaseKernel(m_plbvhLargeAabbAabbTestKernel);
clReleaseKernel(m_plbvhLargeAabbRayTestKernel);
-
+
clReleaseProgram(m_parallelLinearBvhProgram);
}
-void b3GpuParallelLinearBvh::build(const b3OpenCLArray<b3SapAabb>& worldSpaceAabbs, const b3OpenCLArray<int>& smallAabbIndices,
- const b3OpenCLArray<int>& largeAabbIndices)
+void b3GpuParallelLinearBvh::build(const b3OpenCLArray<b3SapAabb>& worldSpaceAabbs, const b3OpenCLArray<int>& smallAabbIndices,
+ const b3OpenCLArray<int>& largeAabbIndices)
{
B3_PROFILE("b3ParallelLinearBvh::build()");
-
+
int numLargeAabbs = largeAabbIndices.size();
int numSmallAabbs = smallAabbIndices.size();
-
- //Since all AABBs(both large and small) are input as a contiguous array,
+
+ //Since all AABBs(both large and small) are input as a contiguous array,
//with 2 additional arrays used to indicate the indices of large and small AABBs,
//it is necessary to separate the AABBs so that the large AABBs will not degrade the quality of the BVH.
{
B3_PROFILE("Separate large and small AABBs");
-
+
m_largeAabbs.resize(numLargeAabbs);
m_leafNodeAabbs.resize(numSmallAabbs);
-
+
//Write large AABBs into m_largeAabbs
{
- b3BufferInfoCL bufferInfo[] =
- {
- b3BufferInfoCL( worldSpaceAabbs.getBufferCL() ),
- b3BufferInfoCL( largeAabbIndices.getBufferCL() ),
-
- b3BufferInfoCL( m_largeAabbs.getBufferCL() )
- };
-
+ b3BufferInfoCL bufferInfo[] =
+ {
+ b3BufferInfoCL(worldSpaceAabbs.getBufferCL()),
+ b3BufferInfoCL(largeAabbIndices.getBufferCL()),
+
+ b3BufferInfoCL(m_largeAabbs.getBufferCL())};
+
b3LauncherCL launcher(m_queue, m_separateAabbsKernel, "m_separateAabbsKernel");
- launcher.setBuffers( bufferInfo, sizeof(bufferInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
launcher.setConst(numLargeAabbs);
-
+
launcher.launch1D(numLargeAabbs);
}
-
+
//Write small AABBs into m_leafNodeAabbs
{
- b3BufferInfoCL bufferInfo[] =
- {
- b3BufferInfoCL( worldSpaceAabbs.getBufferCL() ),
- b3BufferInfoCL( smallAabbIndices.getBufferCL() ),
-
- b3BufferInfoCL( m_leafNodeAabbs.getBufferCL() )
- };
-
+ b3BufferInfoCL bufferInfo[] =
+ {
+ b3BufferInfoCL(worldSpaceAabbs.getBufferCL()),
+ b3BufferInfoCL(smallAabbIndices.getBufferCL()),
+
+ b3BufferInfoCL(m_leafNodeAabbs.getBufferCL())};
+
b3LauncherCL launcher(m_queue, m_separateAabbsKernel, "m_separateAabbsKernel");
- launcher.setBuffers( bufferInfo, sizeof(bufferInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
launcher.setConst(numSmallAabbs);
-
+
launcher.launch1D(numSmallAabbs);
}
-
+
clFinish(m_queue);
}
-
+
//
- int numLeaves = numSmallAabbs; //Number of leaves in the BVH == Number of rigid bodies with small AABBs
+ int numLeaves = numSmallAabbs; //Number of leaves in the BVH == Number of rigid bodies with small AABBs
int numInternalNodes = numLeaves - 1;
-
- if(numLeaves < 2)
+
+ if (numLeaves < 2)
{
//Number of leaf nodes is checked in calculateOverlappingPairs() and testRaysAgainstBvhAabbs(),
//so it does not matter if numLeaves == 0 and rootNodeIndex == -1
int rootNodeIndex = numLeaves - 1;
m_rootNodeIndex.copyFromHostPointer(&rootNodeIndex, 1);
-
+
//Since the AABBs need to be rearranged(sorted) for the BVH construction algorithm,
//m_mortonCodesAndAabbIndicies.m_value is used to map a sorted AABB index to the unsorted AABB index
//instead of directly moving the AABBs. It needs to be set for the ray cast traversal kernel to work.
//( m_mortonCodesAndAabbIndicies[].m_value == unsorted index == index of m_leafNodeAabbs )
- if(numLeaves == 1)
+ if (numLeaves == 1)
{
b3SortData leaf;
- leaf.m_value = 0; //1 leaf so index is always 0; leaf.m_key does not need to be set
-
+ leaf.m_value = 0; //1 leaf so index is always 0; leaf.m_key does not need to be set
+
m_mortonCodesAndAabbIndicies.resize(1);
m_mortonCodesAndAabbIndicies.copyFromHostPointer(&leaf, 1);
}
-
+
return;
}
-
+
//
{
m_internalNodeAabbs.resize(numInternalNodes);
@@ -197,37 +194,37 @@ void b3GpuParallelLinearBvh::build(const b3OpenCLArray<b3SapAabb>& worldSpaceAab
m_commonPrefixes.resize(numInternalNodes);
m_commonPrefixLengths.resize(numInternalNodes);
m_distanceFromRoot.resize(numInternalNodes);
-
+
m_leafNodeParentNodes.resize(numLeaves);
m_mortonCodesAndAabbIndicies.resize(numLeaves);
m_mergedAabb.resize(numLeaves);
}
-
- //Find the merged AABB of all small AABBs; this is used to define the size of
+
+ //Find the merged AABB of all small AABBs; this is used to define the size of
//each cell in the virtual grid for the next kernel(2^10 cells in each dimension).
{
B3_PROFILE("Find AABB of merged nodes");
-
- m_mergedAabb.copyFromOpenCLArray(m_leafNodeAabbs); //Need to make a copy since the kernel modifies the array
-
- for(int numAabbsNeedingMerge = numLeaves; numAabbsNeedingMerge >= 2;
- numAabbsNeedingMerge = numAabbsNeedingMerge / 2 + numAabbsNeedingMerge % 2)
+
+ m_mergedAabb.copyFromOpenCLArray(m_leafNodeAabbs); //Need to make a copy since the kernel modifies the array
+
+ for (int numAabbsNeedingMerge = numLeaves; numAabbsNeedingMerge >= 2;
+ numAabbsNeedingMerge = numAabbsNeedingMerge / 2 + numAabbsNeedingMerge % 2)
{
- b3BufferInfoCL bufferInfo[] =
- {
- b3BufferInfoCL( m_mergedAabb.getBufferCL() ) //Resulting AABB is stored in m_mergedAabb[0]
- };
-
+ b3BufferInfoCL bufferInfo[] =
+ {
+ b3BufferInfoCL(m_mergedAabb.getBufferCL()) //Resulting AABB is stored in m_mergedAabb[0]
+ };
+
b3LauncherCL launcher(m_queue, m_findAllNodesMergedAabbKernel, "m_findAllNodesMergedAabbKernel");
- launcher.setBuffers( bufferInfo, sizeof(bufferInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
launcher.setConst(numAabbsNeedingMerge);
-
+
launcher.launch1D(numAabbsNeedingMerge);
}
-
+
clFinish(m_queue);
}
-
+
//Insert the center of the AABBs into a virtual grid,
//then convert the discrete grid coordinates into a morton code
//For each element in m_mortonCodesAndAabbIndicies, set
@@ -235,34 +232,32 @@ void b3GpuParallelLinearBvh::build(const b3OpenCLArray<b3SapAabb>& worldSpaceAab
// m_value == small AABB index
{
B3_PROFILE("Assign morton codes");
-
- b3BufferInfoCL bufferInfo[] =
- {
- b3BufferInfoCL( m_leafNodeAabbs.getBufferCL() ),
- b3BufferInfoCL( m_mergedAabb.getBufferCL() ),
- b3BufferInfoCL( m_mortonCodesAndAabbIndicies.getBufferCL() )
- };
-
+
+ b3BufferInfoCL bufferInfo[] =
+ {
+ b3BufferInfoCL(m_leafNodeAabbs.getBufferCL()),
+ b3BufferInfoCL(m_mergedAabb.getBufferCL()),
+ b3BufferInfoCL(m_mortonCodesAndAabbIndicies.getBufferCL())};
+
b3LauncherCL launcher(m_queue, m_assignMortonCodesAndAabbIndiciesKernel, "m_assignMortonCodesAndAabbIndiciesKernel");
- launcher.setBuffers( bufferInfo, sizeof(bufferInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
launcher.setConst(numLeaves);
-
+
launcher.launch1D(numLeaves);
clFinish(m_queue);
}
-
+
//
{
B3_PROFILE("Sort leaves by morton codes");
-
+
m_radixSorter.execute(m_mortonCodesAndAabbIndicies);
clFinish(m_queue);
}
-
+
//
constructBinaryRadixTree();
-
-
+
//Since it is a sorted binary radix tree, each internal node contains a contiguous subset of leaf node indices.
//The root node contains leaf node indices in the range [0, numLeafNodes - 1].
//The child nodes of each node split their parent's index range into 2 contiguous halves.
@@ -273,17 +268,16 @@ void b3GpuParallelLinearBvh::build(const b3OpenCLArray<b3SapAabb>& worldSpaceAab
//This property can be used for optimizing calculateOverlappingPairs(), to avoid testing each AABB pair twice
{
B3_PROFILE("m_findLeafIndexRangesKernel");
-
- b3BufferInfoCL bufferInfo[] =
- {
- b3BufferInfoCL( m_internalNodeChildNodes.getBufferCL() ),
- b3BufferInfoCL( m_internalNodeLeafIndexRanges.getBufferCL() )
- };
-
+
+ b3BufferInfoCL bufferInfo[] =
+ {
+ b3BufferInfoCL(m_internalNodeChildNodes.getBufferCL()),
+ b3BufferInfoCL(m_internalNodeLeafIndexRanges.getBufferCL())};
+
b3LauncherCL launcher(m_queue, m_findLeafIndexRangesKernel, "m_findLeafIndexRangesKernel");
- launcher.setBuffers( bufferInfo, sizeof(bufferInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
launcher.setConst(numInternalNodes);
-
+
launcher.launch1D(numInternalNodes);
clFinish(m_queue);
}
@@ -293,285 +287,271 @@ void b3GpuParallelLinearBvh::calculateOverlappingPairs(b3OpenCLArray<b3Int4>& ou
{
int maxPairs = out_overlappingPairs.size();
b3OpenCLArray<int>& numPairsGpu = m_temp;
-
+
int reset = 0;
numPairsGpu.copyFromHostPointer(&reset, 1);
-
+
//
- if( m_leafNodeAabbs.size() > 1 )
+ if (m_leafNodeAabbs.size() > 1)
{
B3_PROFILE("PLBVH small-small AABB test");
-
+
int numQueryAabbs = m_leafNodeAabbs.size();
-
- b3BufferInfoCL bufferInfo[] =
- {
- b3BufferInfoCL( m_leafNodeAabbs.getBufferCL() ),
-
- b3BufferInfoCL( m_rootNodeIndex.getBufferCL() ),
- b3BufferInfoCL( m_internalNodeChildNodes.getBufferCL() ),
- b3BufferInfoCL( m_internalNodeAabbs.getBufferCL() ),
- b3BufferInfoCL( m_internalNodeLeafIndexRanges.getBufferCL() ),
- b3BufferInfoCL( m_mortonCodesAndAabbIndicies.getBufferCL() ),
-
- b3BufferInfoCL( numPairsGpu.getBufferCL() ),
- b3BufferInfoCL( out_overlappingPairs.getBufferCL() )
- };
-
+
+ b3BufferInfoCL bufferInfo[] =
+ {
+ b3BufferInfoCL(m_leafNodeAabbs.getBufferCL()),
+
+ b3BufferInfoCL(m_rootNodeIndex.getBufferCL()),
+ b3BufferInfoCL(m_internalNodeChildNodes.getBufferCL()),
+ b3BufferInfoCL(m_internalNodeAabbs.getBufferCL()),
+ b3BufferInfoCL(m_internalNodeLeafIndexRanges.getBufferCL()),
+ b3BufferInfoCL(m_mortonCodesAndAabbIndicies.getBufferCL()),
+
+ b3BufferInfoCL(numPairsGpu.getBufferCL()),
+ b3BufferInfoCL(out_overlappingPairs.getBufferCL())};
+
b3LauncherCL launcher(m_queue, m_plbvhCalculateOverlappingPairsKernel, "m_plbvhCalculateOverlappingPairsKernel");
- launcher.setBuffers( bufferInfo, sizeof(bufferInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
launcher.setConst(maxPairs);
launcher.setConst(numQueryAabbs);
-
+
launcher.launch1D(numQueryAabbs);
clFinish(m_queue);
}
-
+
int numLargeAabbRigids = m_largeAabbs.size();
- if( numLargeAabbRigids > 0 && m_leafNodeAabbs.size() > 0 )
+ if (numLargeAabbRigids > 0 && m_leafNodeAabbs.size() > 0)
{
B3_PROFILE("PLBVH large-small AABB test");
-
+
int numQueryAabbs = m_leafNodeAabbs.size();
-
- b3BufferInfoCL bufferInfo[] =
- {
- b3BufferInfoCL( m_leafNodeAabbs.getBufferCL() ),
- b3BufferInfoCL( m_largeAabbs.getBufferCL() ),
-
- b3BufferInfoCL( numPairsGpu.getBufferCL() ),
- b3BufferInfoCL( out_overlappingPairs.getBufferCL() )
- };
-
+
+ b3BufferInfoCL bufferInfo[] =
+ {
+ b3BufferInfoCL(m_leafNodeAabbs.getBufferCL()),
+ b3BufferInfoCL(m_largeAabbs.getBufferCL()),
+
+ b3BufferInfoCL(numPairsGpu.getBufferCL()),
+ b3BufferInfoCL(out_overlappingPairs.getBufferCL())};
+
b3LauncherCL launcher(m_queue, m_plbvhLargeAabbAabbTestKernel, "m_plbvhLargeAabbAabbTestKernel");
- launcher.setBuffers( bufferInfo, sizeof(bufferInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
launcher.setConst(maxPairs);
launcher.setConst(numLargeAabbRigids);
launcher.setConst(numQueryAabbs);
-
+
launcher.launch1D(numQueryAabbs);
clFinish(m_queue);
}
-
-
+
//
int numPairs = -1;
numPairsGpu.copyToHostPointer(&numPairs, 1);
- if(numPairs > maxPairs)
+ if (numPairs > maxPairs)
{
b3Error("Error running out of pairs: numPairs = %d, maxPairs = %d.\n", numPairs, maxPairs);
numPairs = maxPairs;
numPairsGpu.copyFromHostPointer(&maxPairs, 1);
}
-
+
out_overlappingPairs.resize(numPairs);
}
-
-void b3GpuParallelLinearBvh::testRaysAgainstBvhAabbs(const b3OpenCLArray<b3RayInfo>& rays,
- b3OpenCLArray<int>& out_numRayRigidPairs, b3OpenCLArray<b3Int2>& out_rayRigidPairs)
+void b3GpuParallelLinearBvh::testRaysAgainstBvhAabbs(const b3OpenCLArray<b3RayInfo>& rays,
+ b3OpenCLArray<int>& out_numRayRigidPairs, b3OpenCLArray<b3Int2>& out_rayRigidPairs)
{
B3_PROFILE("PLBVH testRaysAgainstBvhAabbs()");
-
+
int numRays = rays.size();
int maxRayRigidPairs = out_rayRigidPairs.size();
-
+
int reset = 0;
out_numRayRigidPairs.copyFromHostPointer(&reset, 1);
-
+
//
- if( m_leafNodeAabbs.size() > 0 )
+ if (m_leafNodeAabbs.size() > 0)
{
B3_PROFILE("PLBVH ray test small AABB");
-
- b3BufferInfoCL bufferInfo[] =
- {
- b3BufferInfoCL( m_leafNodeAabbs.getBufferCL() ),
-
- b3BufferInfoCL( m_rootNodeIndex.getBufferCL() ),
- b3BufferInfoCL( m_internalNodeChildNodes.getBufferCL() ),
- b3BufferInfoCL( m_internalNodeAabbs.getBufferCL() ),
- b3BufferInfoCL( m_internalNodeLeafIndexRanges.getBufferCL() ),
- b3BufferInfoCL( m_mortonCodesAndAabbIndicies.getBufferCL() ),
-
- b3BufferInfoCL( rays.getBufferCL() ),
-
- b3BufferInfoCL( out_numRayRigidPairs.getBufferCL() ),
- b3BufferInfoCL( out_rayRigidPairs.getBufferCL() )
- };
-
+
+ b3BufferInfoCL bufferInfo[] =
+ {
+ b3BufferInfoCL(m_leafNodeAabbs.getBufferCL()),
+
+ b3BufferInfoCL(m_rootNodeIndex.getBufferCL()),
+ b3BufferInfoCL(m_internalNodeChildNodes.getBufferCL()),
+ b3BufferInfoCL(m_internalNodeAabbs.getBufferCL()),
+ b3BufferInfoCL(m_internalNodeLeafIndexRanges.getBufferCL()),
+ b3BufferInfoCL(m_mortonCodesAndAabbIndicies.getBufferCL()),
+
+ b3BufferInfoCL(rays.getBufferCL()),
+
+ b3BufferInfoCL(out_numRayRigidPairs.getBufferCL()),
+ b3BufferInfoCL(out_rayRigidPairs.getBufferCL())};
+
b3LauncherCL launcher(m_queue, m_plbvhRayTraverseKernel, "m_plbvhRayTraverseKernel");
- launcher.setBuffers( bufferInfo, sizeof(bufferInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
launcher.setConst(maxRayRigidPairs);
launcher.setConst(numRays);
-
+
launcher.launch1D(numRays);
clFinish(m_queue);
}
-
+
int numLargeAabbRigids = m_largeAabbs.size();
- if(numLargeAabbRigids > 0)
+ if (numLargeAabbRigids > 0)
{
B3_PROFILE("PLBVH ray test large AABB");
-
- b3BufferInfoCL bufferInfo[] =
- {
- b3BufferInfoCL( m_largeAabbs.getBufferCL() ),
- b3BufferInfoCL( rays.getBufferCL() ),
-
- b3BufferInfoCL( out_numRayRigidPairs.getBufferCL() ),
- b3BufferInfoCL( out_rayRigidPairs.getBufferCL() )
- };
-
+
+ b3BufferInfoCL bufferInfo[] =
+ {
+ b3BufferInfoCL(m_largeAabbs.getBufferCL()),
+ b3BufferInfoCL(rays.getBufferCL()),
+
+ b3BufferInfoCL(out_numRayRigidPairs.getBufferCL()),
+ b3BufferInfoCL(out_rayRigidPairs.getBufferCL())};
+
b3LauncherCL launcher(m_queue, m_plbvhLargeAabbRayTestKernel, "m_plbvhLargeAabbRayTestKernel");
- launcher.setBuffers( bufferInfo, sizeof(bufferInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
launcher.setConst(numLargeAabbRigids);
launcher.setConst(maxRayRigidPairs);
launcher.setConst(numRays);
-
+
launcher.launch1D(numRays);
clFinish(m_queue);
}
-
+
//
int numRayRigidPairs = -1;
out_numRayRigidPairs.copyToHostPointer(&numRayRigidPairs, 1);
-
- if(numRayRigidPairs > maxRayRigidPairs)
+
+ if (numRayRigidPairs > maxRayRigidPairs)
b3Error("Error running out of rayRigid pairs: numRayRigidPairs = %d, maxRayRigidPairs = %d.\n", numRayRigidPairs, maxRayRigidPairs);
-
}
void b3GpuParallelLinearBvh::constructBinaryRadixTree()
{
B3_PROFILE("b3GpuParallelLinearBvh::constructBinaryRadixTree()");
-
+
int numLeaves = m_leafNodeAabbs.size();
int numInternalNodes = numLeaves - 1;
-
+
//Each internal node is placed in between 2 leaf nodes.
//By using this arrangement and computing the common prefix between
//these 2 adjacent leaf nodes, it is possible to quickly construct a binary radix tree.
{
B3_PROFILE("m_computeAdjacentPairCommonPrefixKernel");
-
- b3BufferInfoCL bufferInfo[] =
- {
- b3BufferInfoCL( m_mortonCodesAndAabbIndicies.getBufferCL() ),
- b3BufferInfoCL( m_commonPrefixes.getBufferCL() ),
- b3BufferInfoCL( m_commonPrefixLengths.getBufferCL() )
- };
-
+
+ b3BufferInfoCL bufferInfo[] =
+ {
+ b3BufferInfoCL(m_mortonCodesAndAabbIndicies.getBufferCL()),
+ b3BufferInfoCL(m_commonPrefixes.getBufferCL()),
+ b3BufferInfoCL(m_commonPrefixLengths.getBufferCL())};
+
b3LauncherCL launcher(m_queue, m_computeAdjacentPairCommonPrefixKernel, "m_computeAdjacentPairCommonPrefixKernel");
- launcher.setBuffers( bufferInfo, sizeof(bufferInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
launcher.setConst(numInternalNodes);
-
+
launcher.launch1D(numInternalNodes);
clFinish(m_queue);
}
-
- //For each leaf node, select its parent node by
+
+ //For each leaf node, select its parent node by
//comparing the 2 nearest internal nodes and assign child node indices
{
B3_PROFILE("m_buildBinaryRadixTreeLeafNodesKernel");
-
- b3BufferInfoCL bufferInfo[] =
- {
- b3BufferInfoCL( m_commonPrefixLengths.getBufferCL() ),
- b3BufferInfoCL( m_leafNodeParentNodes.getBufferCL() ),
- b3BufferInfoCL( m_internalNodeChildNodes.getBufferCL() )
- };
-
+
+ b3BufferInfoCL bufferInfo[] =
+ {
+ b3BufferInfoCL(m_commonPrefixLengths.getBufferCL()),
+ b3BufferInfoCL(m_leafNodeParentNodes.getBufferCL()),
+ b3BufferInfoCL(m_internalNodeChildNodes.getBufferCL())};
+
b3LauncherCL launcher(m_queue, m_buildBinaryRadixTreeLeafNodesKernel, "m_buildBinaryRadixTreeLeafNodesKernel");
- launcher.setBuffers( bufferInfo, sizeof(bufferInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
launcher.setConst(numLeaves);
-
+
launcher.launch1D(numLeaves);
clFinish(m_queue);
}
-
+
//For each internal node, perform 2 binary searches among the other internal nodes
//to its left and right to find its potential parent nodes and assign child node indices
{
B3_PROFILE("m_buildBinaryRadixTreeInternalNodesKernel");
-
- b3BufferInfoCL bufferInfo[] =
- {
- b3BufferInfoCL( m_commonPrefixes.getBufferCL() ),
- b3BufferInfoCL( m_commonPrefixLengths.getBufferCL() ),
- b3BufferInfoCL( m_internalNodeChildNodes.getBufferCL() ),
- b3BufferInfoCL( m_internalNodeParentNodes.getBufferCL() ),
- b3BufferInfoCL( m_rootNodeIndex.getBufferCL() )
- };
-
+
+ b3BufferInfoCL bufferInfo[] =
+ {
+ b3BufferInfoCL(m_commonPrefixes.getBufferCL()),
+ b3BufferInfoCL(m_commonPrefixLengths.getBufferCL()),
+ b3BufferInfoCL(m_internalNodeChildNodes.getBufferCL()),
+ b3BufferInfoCL(m_internalNodeParentNodes.getBufferCL()),
+ b3BufferInfoCL(m_rootNodeIndex.getBufferCL())};
+
b3LauncherCL launcher(m_queue, m_buildBinaryRadixTreeInternalNodesKernel, "m_buildBinaryRadixTreeInternalNodesKernel");
- launcher.setBuffers( bufferInfo, sizeof(bufferInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
launcher.setConst(numInternalNodes);
-
+
launcher.launch1D(numInternalNodes);
clFinish(m_queue);
}
-
+
//Find the number of nodes seperating each internal node and the root node
//so that the AABBs can be set using the next kernel.
//Also determine the maximum number of nodes separating an internal node and the root node.
{
B3_PROFILE("m_findDistanceFromRootKernel");
-
- b3BufferInfoCL bufferInfo[] =
- {
- b3BufferInfoCL( m_rootNodeIndex.getBufferCL() ),
- b3BufferInfoCL( m_internalNodeParentNodes.getBufferCL() ),
- b3BufferInfoCL( m_maxDistanceFromRoot.getBufferCL() ),
- b3BufferInfoCL( m_distanceFromRoot.getBufferCL() )
- };
-
+
+ b3BufferInfoCL bufferInfo[] =
+ {
+ b3BufferInfoCL(m_rootNodeIndex.getBufferCL()),
+ b3BufferInfoCL(m_internalNodeParentNodes.getBufferCL()),
+ b3BufferInfoCL(m_maxDistanceFromRoot.getBufferCL()),
+ b3BufferInfoCL(m_distanceFromRoot.getBufferCL())};
+
b3LauncherCL launcher(m_queue, m_findDistanceFromRootKernel, "m_findDistanceFromRootKernel");
- launcher.setBuffers( bufferInfo, sizeof(bufferInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
launcher.setConst(numInternalNodes);
-
+
launcher.launch1D(numInternalNodes);
clFinish(m_queue);
}
-
+
//Starting from the internal nodes nearest to the leaf nodes, recursively move up
//the tree towards the root to set the AABBs of each internal node; each internal node
//checks its children and merges their AABBs
{
B3_PROFILE("m_buildBinaryRadixTreeAabbsRecursiveKernel");
-
+
int maxDistanceFromRoot = -1;
{
B3_PROFILE("copy maxDistanceFromRoot to CPU");
m_maxDistanceFromRoot.copyToHostPointer(&maxDistanceFromRoot, 1);
clFinish(m_queue);
}
-
- for(int distanceFromRoot = maxDistanceFromRoot; distanceFromRoot >= 0; --distanceFromRoot)
+
+ for (int distanceFromRoot = maxDistanceFromRoot; distanceFromRoot >= 0; --distanceFromRoot)
{
- b3BufferInfoCL bufferInfo[] =
- {
- b3BufferInfoCL( m_distanceFromRoot.getBufferCL() ),
- b3BufferInfoCL( m_mortonCodesAndAabbIndicies.getBufferCL() ),
- b3BufferInfoCL( m_internalNodeChildNodes.getBufferCL() ),
- b3BufferInfoCL( m_leafNodeAabbs.getBufferCL() ),
- b3BufferInfoCL( m_internalNodeAabbs.getBufferCL() )
- };
-
+ b3BufferInfoCL bufferInfo[] =
+ {
+ b3BufferInfoCL(m_distanceFromRoot.getBufferCL()),
+ b3BufferInfoCL(m_mortonCodesAndAabbIndicies.getBufferCL()),
+ b3BufferInfoCL(m_internalNodeChildNodes.getBufferCL()),
+ b3BufferInfoCL(m_leafNodeAabbs.getBufferCL()),
+ b3BufferInfoCL(m_internalNodeAabbs.getBufferCL())};
+
b3LauncherCL launcher(m_queue, m_buildBinaryRadixTreeAabbsRecursiveKernel, "m_buildBinaryRadixTreeAabbsRecursiveKernel");
- launcher.setBuffers( bufferInfo, sizeof(bufferInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
launcher.setConst(maxDistanceFromRoot);
launcher.setConst(distanceFromRoot);
launcher.setConst(numInternalNodes);
-
+
//It may seem inefficent to launch a thread for each internal node when a
//much smaller number of nodes is actually processed, but this is actually
- //faster than determining the exact nodes that are ready to merge their child AABBs.
+ //faster than determining the exact nodes that are ready to merge their child AABBs.
launcher.launch1D(numInternalNodes);
}
-
+
clFinish(m_queue);
}
}
-
- \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.h b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.h
index effe617b7b..b390775129 100644
--- a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.h
+++ b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.h
@@ -37,10 +37,10 @@ subject to the following restrictions:
///"Maximizing Parallelism in the Construction of BVHs, Octrees, and k-d trees" [Karras 2012] \n
///@par
///The basic algorithm for building the BVH as presented in [Lauterbach et al. 2009] consists of 4 stages:
-/// - [fully parallel] Assign morton codes for each AABB using its center (after quantizing the AABB centers into a virtual grid)
+/// - [fully parallel] Assign morton codes for each AABB using its center (after quantizing the AABB centers into a virtual grid)
/// - [fully parallel] Sort morton codes
-/// - [somewhat parallel] Build binary radix tree (assign parent/child pointers for internal nodes of the BVH)
-/// - [somewhat parallel] Set internal node AABBs
+/// - [somewhat parallel] Build binary radix tree (assign parent/child pointers for internal nodes of the BVH)
+/// - [somewhat parallel] Set internal node AABBs
///@par
///[Karras 2012] improves on the algorithm by introducing fully parallel methods for the last 2 stages.
///The BVH implementation here shares many concepts with [Karras 2012], but a different method is used for constructing the tree.
@@ -49,75 +49,75 @@ subject to the following restrictions:
class b3GpuParallelLinearBvh
{
cl_command_queue m_queue;
-
+
cl_program m_parallelLinearBvhProgram;
-
+
cl_kernel m_separateAabbsKernel;
cl_kernel m_findAllNodesMergedAabbKernel;
cl_kernel m_assignMortonCodesAndAabbIndiciesKernel;
-
+
//Binary radix tree construction kernels
cl_kernel m_computeAdjacentPairCommonPrefixKernel;
cl_kernel m_buildBinaryRadixTreeLeafNodesKernel;
cl_kernel m_buildBinaryRadixTreeInternalNodesKernel;
cl_kernel m_findDistanceFromRootKernel;
cl_kernel m_buildBinaryRadixTreeAabbsRecursiveKernel;
-
+
cl_kernel m_findLeafIndexRangesKernel;
-
+
//Traversal kernels
cl_kernel m_plbvhCalculateOverlappingPairsKernel;
cl_kernel m_plbvhRayTraverseKernel;
cl_kernel m_plbvhLargeAabbAabbTestKernel;
cl_kernel m_plbvhLargeAabbRayTestKernel;
-
+
b3RadixSort32CL m_radixSorter;
-
+
//1 element
- b3OpenCLArray<int> m_rootNodeIndex; //Most significant bit(0x80000000) is set to indicate internal node
- b3OpenCLArray<int> m_maxDistanceFromRoot; //Max number of internal nodes between an internal node and the root node
- b3OpenCLArray<int> m_temp; //Used to hold the number of pairs in calculateOverlappingPairs()
-
+ b3OpenCLArray<int> m_rootNodeIndex; //Most significant bit(0x80000000) is set to indicate internal node
+ b3OpenCLArray<int> m_maxDistanceFromRoot; //Max number of internal nodes between an internal node and the root node
+ b3OpenCLArray<int> m_temp; //Used to hold the number of pairs in calculateOverlappingPairs()
+
//1 element per internal node (number_of_internal_nodes == number_of_leaves - 1)
b3OpenCLArray<b3SapAabb> m_internalNodeAabbs;
- b3OpenCLArray<b3Int2> m_internalNodeLeafIndexRanges; //x == min leaf index, y == max leaf index
- b3OpenCLArray<b3Int2> m_internalNodeChildNodes; //x == left child, y == right child; msb(0x80000000) is set to indicate internal node
- b3OpenCLArray<int> m_internalNodeParentNodes; //For parent node index, msb(0x80000000) is not set since it is always internal
-
+ b3OpenCLArray<b3Int2> m_internalNodeLeafIndexRanges; //x == min leaf index, y == max leaf index
+ b3OpenCLArray<b3Int2> m_internalNodeChildNodes; //x == left child, y == right child; msb(0x80000000) is set to indicate internal node
+ b3OpenCLArray<int> m_internalNodeParentNodes; //For parent node index, msb(0x80000000) is not set since it is always internal
+
//1 element per internal node; for binary radix tree construction
b3OpenCLArray<b3Int64> m_commonPrefixes;
b3OpenCLArray<int> m_commonPrefixLengths;
- b3OpenCLArray<int> m_distanceFromRoot; //Number of internal nodes between this node and the root
-
+ b3OpenCLArray<int> m_distanceFromRoot; //Number of internal nodes between this node and the root
+
//1 element per leaf node (leaf nodes only include small AABBs)
- b3OpenCLArray<int> m_leafNodeParentNodes; //For parent node index, msb(0x80000000) is not set since it is always internal
- b3OpenCLArray<b3SortData> m_mortonCodesAndAabbIndicies; //m_key == morton code, m_value == aabb index in m_leafNodeAabbs
- b3OpenCLArray<b3SapAabb> m_mergedAabb; //m_mergedAabb[0] contains the merged AABB of all leaf nodes
- b3OpenCLArray<b3SapAabb> m_leafNodeAabbs; //Contains only small AABBs
-
+ b3OpenCLArray<int> m_leafNodeParentNodes; //For parent node index, msb(0x80000000) is not set since it is always internal
+ b3OpenCLArray<b3SortData> m_mortonCodesAndAabbIndicies; //m_key == morton code, m_value == aabb index in m_leafNodeAabbs
+ b3OpenCLArray<b3SapAabb> m_mergedAabb; //m_mergedAabb[0] contains the merged AABB of all leaf nodes
+ b3OpenCLArray<b3SapAabb> m_leafNodeAabbs; //Contains only small AABBs
+
//1 element per large AABB, which is not stored in the BVH
b3OpenCLArray<b3SapAabb> m_largeAabbs;
-
+
public:
b3GpuParallelLinearBvh(cl_context context, cl_device_id device, cl_command_queue queue);
virtual ~b3GpuParallelLinearBvh();
-
+
///Must be called before any other function
- void build(const b3OpenCLArray<b3SapAabb>& worldSpaceAabbs, const b3OpenCLArray<int>& smallAabbIndices,
- const b3OpenCLArray<int>& largeAabbIndices);
-
+ void build(const b3OpenCLArray<b3SapAabb>& worldSpaceAabbs, const b3OpenCLArray<int>& smallAabbIndices,
+ const b3OpenCLArray<int>& largeAabbIndices);
+
///calculateOverlappingPairs() uses the worldSpaceAabbs parameter of b3GpuParallelLinearBvh::build() as the query AABBs.
///@param out_overlappingPairs The size() of this array is used to determine the max number of pairs.
///If the number of overlapping pairs is < out_overlappingPairs.size(), out_overlappingPairs is resized.
void calculateOverlappingPairs(b3OpenCLArray<b3Int4>& out_overlappingPairs);
-
+
///@param out_numRigidRayPairs Array of length 1; contains the number of detected ray-rigid AABB intersections;
///this value may be greater than out_rayRigidPairs.size() if out_rayRigidPairs is not large enough.
///@param out_rayRigidPairs Contains an array of rays intersecting rigid AABBs; x == ray index, y == rigid body index.
///If the size of this array is insufficient to hold all ray-rigid AABB intersections, additional intersections are discarded.
- void testRaysAgainstBvhAabbs(const b3OpenCLArray<b3RayInfo>& rays,
- b3OpenCLArray<int>& out_numRayRigidPairs, b3OpenCLArray<b3Int2>& out_rayRigidPairs);
-
+ void testRaysAgainstBvhAabbs(const b3OpenCLArray<b3RayInfo>& rays,
+ b3OpenCLArray<int>& out_numRayRigidPairs, b3OpenCLArray<b3Int2>& out_rayRigidPairs);
+
private:
void constructBinaryRadixTree();
};
diff --git a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvhBroadphase.cpp b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvhBroadphase.cpp
index d2618024ac..62ea7a32df 100644
--- a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvhBroadphase.cpp
+++ b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvhBroadphase.cpp
@@ -13,45 +13,44 @@ subject to the following restrictions:
#include "b3GpuParallelLinearBvhBroadphase.h"
-b3GpuParallelLinearBvhBroadphase::b3GpuParallelLinearBvhBroadphase(cl_context context, cl_device_id device, cl_command_queue queue) :
- m_plbvh(context, device, queue),
-
- m_overlappingPairsGpu(context, queue),
-
- m_aabbsGpu(context, queue),
- m_smallAabbsMappingGpu(context, queue),
- m_largeAabbsMappingGpu(context, queue)
+b3GpuParallelLinearBvhBroadphase::b3GpuParallelLinearBvhBroadphase(cl_context context, cl_device_id device, cl_command_queue queue) : m_plbvh(context, device, queue),
+
+ m_overlappingPairsGpu(context, queue),
+
+ m_aabbsGpu(context, queue),
+ m_smallAabbsMappingGpu(context, queue),
+ m_largeAabbsMappingGpu(context, queue)
{
}
-void b3GpuParallelLinearBvhBroadphase::createProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask)
+void b3GpuParallelLinearBvhBroadphase::createProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask)
{
int newAabbIndex = m_aabbsCpu.size();
b3SapAabb aabb;
aabb.m_minVec = aabbMin;
aabb.m_maxVec = aabbMax;
-
+
aabb.m_minIndices[3] = userPtr;
aabb.m_signedMaxIndices[3] = newAabbIndex;
-
+
m_smallAabbsMappingCpu.push_back(newAabbIndex);
-
+
m_aabbsCpu.push_back(aabb);
}
-void b3GpuParallelLinearBvhBroadphase::createLargeProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask)
+void b3GpuParallelLinearBvhBroadphase::createLargeProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask)
{
int newAabbIndex = m_aabbsCpu.size();
b3SapAabb aabb;
aabb.m_minVec = aabbMin;
aabb.m_maxVec = aabbMax;
-
+
aabb.m_minIndices[3] = userPtr;
aabb.m_signedMaxIndices[3] = newAabbIndex;
-
+
m_largeAabbsMappingCpu.push_back(newAabbIndex);
-
+
m_aabbsCpu.push_back(aabb);
}
@@ -59,22 +58,19 @@ void b3GpuParallelLinearBvhBroadphase::calculateOverlappingPairs(int maxPairs)
{
//Reconstruct BVH
m_plbvh.build(m_aabbsGpu, m_smallAabbsMappingGpu, m_largeAabbsMappingGpu);
-
+
//
m_overlappingPairsGpu.resize(maxPairs);
m_plbvh.calculateOverlappingPairs(m_overlappingPairsGpu);
}
void b3GpuParallelLinearBvhBroadphase::calculateOverlappingPairsHost(int maxPairs)
{
- b3Assert(0); //CPU version not implemented
+ b3Assert(0); //CPU version not implemented
}
-void b3GpuParallelLinearBvhBroadphase::writeAabbsToGpu()
-{
- m_aabbsGpu.copyFromHost(m_aabbsCpu);
+void b3GpuParallelLinearBvhBroadphase::writeAabbsToGpu()
+{
+ m_aabbsGpu.copyFromHost(m_aabbsCpu);
m_smallAabbsMappingGpu.copyFromHost(m_smallAabbsMappingCpu);
m_largeAabbsMappingGpu.copyFromHost(m_largeAabbsMappingCpu);
}
-
-
-
diff --git a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvhBroadphase.h b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvhBroadphase.h
index e518500637..dda0eea7be 100644
--- a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvhBroadphase.h
+++ b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvhBroadphase.h
@@ -21,42 +21,42 @@ subject to the following restrictions:
class b3GpuParallelLinearBvhBroadphase : public b3GpuBroadphaseInterface
{
b3GpuParallelLinearBvh m_plbvh;
-
+
b3OpenCLArray<b3Int4> m_overlappingPairsGpu;
-
+
b3OpenCLArray<b3SapAabb> m_aabbsGpu;
b3OpenCLArray<int> m_smallAabbsMappingGpu;
b3OpenCLArray<int> m_largeAabbsMappingGpu;
-
+
b3AlignedObjectArray<b3SapAabb> m_aabbsCpu;
b3AlignedObjectArray<int> m_smallAabbsMappingCpu;
b3AlignedObjectArray<int> m_largeAabbsMappingCpu;
-
+
public:
b3GpuParallelLinearBvhBroadphase(cl_context context, cl_device_id device, cl_command_queue queue);
virtual ~b3GpuParallelLinearBvhBroadphase() {}
- virtual void createProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask);
- virtual void createLargeProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask);
-
+ virtual void createProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask);
+ virtual void createLargeProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask);
+
virtual void calculateOverlappingPairs(int maxPairs);
virtual void calculateOverlappingPairsHost(int maxPairs);
//call writeAabbsToGpu after done making all changes (createProxy etc)
virtual void writeAabbsToGpu();
-
- virtual int getNumOverlap() { return m_overlappingPairsGpu.size(); }
+
+ virtual int getNumOverlap() { return m_overlappingPairsGpu.size(); }
virtual cl_mem getOverlappingPairBuffer() { return m_overlappingPairsGpu.getBufferCL(); }
virtual cl_mem getAabbBufferWS() { return m_aabbsGpu.getBufferCL(); }
virtual b3OpenCLArray<b3SapAabb>& getAllAabbsGPU() { return m_aabbsGpu; }
-
+
virtual b3OpenCLArray<b3Int4>& getOverlappingPairsGPU() { return m_overlappingPairsGpu; }
virtual b3OpenCLArray<int>& getSmallAabbIndicesGPU() { return m_smallAabbsMappingGpu; }
virtual b3OpenCLArray<int>& getLargeAabbIndicesGPU() { return m_largeAabbsMappingGpu; }
-
+
virtual b3AlignedObjectArray<b3SapAabb>& getAllAabbsCPU() { return m_aabbsCpu; }
-
+
static b3GpuBroadphaseInterface* CreateFunc(cl_context context, cl_device_id device, cl_command_queue queue)
{
return new b3GpuParallelLinearBvhBroadphase(context, device, queue);
diff --git a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuSapBroadphase.cpp b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuSapBroadphase.cpp
index c45fbbdcaa..4126d03ed0 100644
--- a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuSapBroadphase.cpp
+++ b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuSapBroadphase.cpp
@@ -6,7 +6,6 @@ bool searchIncremental3dSapOnGpu = true;
#include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
#include "Bullet3OpenCL/ParallelPrimitives/b3PrefixScanFloat4CL.h"
-
#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
#include "kernels/sapKernels.h"
@@ -56,110 +55,105 @@ bool searchIncremental3dSapOnGpu = true;
class b3PrefixScanFloat4CL* m_prefixScanFloat4;
*/
-b3GpuSapBroadphase::b3GpuSapBroadphase(cl_context ctx,cl_device_id device, cl_command_queue q , b3GpuSapKernelType kernelType)
-:m_context(ctx),
-m_device(device),
-m_queue(q),
-
-m_objectMinMaxIndexGPUaxis0(ctx,q),
-m_objectMinMaxIndexGPUaxis1(ctx,q),
-m_objectMinMaxIndexGPUaxis2(ctx,q),
-m_objectMinMaxIndexGPUaxis0prev(ctx,q),
-m_objectMinMaxIndexGPUaxis1prev(ctx,q),
-m_objectMinMaxIndexGPUaxis2prev(ctx,q),
-m_sortedAxisGPU0(ctx,q),
-m_sortedAxisGPU1(ctx,q),
-m_sortedAxisGPU2(ctx,q),
-m_sortedAxisGPU0prev(ctx,q),
-m_sortedAxisGPU1prev(ctx,q),
-m_sortedAxisGPU2prev(ctx,q),
-m_addedHostPairsGPU(ctx,q),
-m_removedHostPairsGPU(ctx,q),
-m_addedCountGPU(ctx,q),
-m_removedCountGPU(ctx,q),
-m_currentBuffer(-1),
-m_pairCount(ctx,q),
-m_allAabbsGPU(ctx,q),
-m_sum(ctx,q),
-m_sum2(ctx,q),
-m_dst(ctx,q),
-m_smallAabbsMappingGPU(ctx,q),
-m_largeAabbsMappingGPU(ctx,q),
-m_overlappingPairs(ctx,q),
-m_gpuSmallSortData(ctx,q),
-m_gpuSmallSortedAabbs(ctx,q)
+b3GpuSapBroadphase::b3GpuSapBroadphase(cl_context ctx, cl_device_id device, cl_command_queue q, b3GpuSapKernelType kernelType)
+ : m_context(ctx),
+ m_device(device),
+ m_queue(q),
+
+ m_objectMinMaxIndexGPUaxis0(ctx, q),
+ m_objectMinMaxIndexGPUaxis1(ctx, q),
+ m_objectMinMaxIndexGPUaxis2(ctx, q),
+ m_objectMinMaxIndexGPUaxis0prev(ctx, q),
+ m_objectMinMaxIndexGPUaxis1prev(ctx, q),
+ m_objectMinMaxIndexGPUaxis2prev(ctx, q),
+ m_sortedAxisGPU0(ctx, q),
+ m_sortedAxisGPU1(ctx, q),
+ m_sortedAxisGPU2(ctx, q),
+ m_sortedAxisGPU0prev(ctx, q),
+ m_sortedAxisGPU1prev(ctx, q),
+ m_sortedAxisGPU2prev(ctx, q),
+ m_addedHostPairsGPU(ctx, q),
+ m_removedHostPairsGPU(ctx, q),
+ m_addedCountGPU(ctx, q),
+ m_removedCountGPU(ctx, q),
+ m_currentBuffer(-1),
+ m_pairCount(ctx, q),
+ m_allAabbsGPU(ctx, q),
+ m_sum(ctx, q),
+ m_sum2(ctx, q),
+ m_dst(ctx, q),
+ m_smallAabbsMappingGPU(ctx, q),
+ m_largeAabbsMappingGPU(ctx, q),
+ m_overlappingPairs(ctx, q),
+ m_gpuSmallSortData(ctx, q),
+ m_gpuSmallSortedAabbs(ctx, q)
{
const char* sapSrc = sapCL;
-
-
- cl_int errNum=0;
+
+ cl_int errNum = 0;
b3Assert(m_context);
b3Assert(m_device);
- cl_program sapProg = b3OpenCLUtils::compileCLProgramFromString(m_context,m_device,sapSrc,&errNum,"",B3_BROADPHASE_SAP_PATH);
- b3Assert(errNum==CL_SUCCESS);
-
+ cl_program sapProg = b3OpenCLUtils::compileCLProgramFromString(m_context, m_device, sapSrc, &errNum, "", B3_BROADPHASE_SAP_PATH);
+ b3Assert(errNum == CL_SUCCESS);
- b3Assert(errNum==CL_SUCCESS);
+ b3Assert(errNum == CL_SUCCESS);
#ifndef __APPLE__
- m_prefixScanFloat4 = new b3PrefixScanFloat4CL(m_context,m_device,m_queue);
+ m_prefixScanFloat4 = new b3PrefixScanFloat4CL(m_context, m_device, m_queue);
#else
m_prefixScanFloat4 = 0;
#endif
m_sapKernel = 0;
-
+
switch (kernelType)
{
case B3_GPU_SAP_KERNEL_BRUTE_FORCE_CPU:
{
- m_sapKernel=0;
+ m_sapKernel = 0;
break;
}
- case B3_GPU_SAP_KERNEL_BRUTE_FORCE_GPU:
+ case B3_GPU_SAP_KERNEL_BRUTE_FORCE_GPU:
{
- m_sapKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,sapSrc, "computePairsKernelBruteForce",&errNum,sapProg );
+ m_sapKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, sapSrc, "computePairsKernelBruteForce", &errNum, sapProg);
break;
}
case B3_GPU_SAP_KERNEL_ORIGINAL:
{
- m_sapKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,sapSrc, "computePairsKernelOriginal",&errNum,sapProg );
+ m_sapKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, sapSrc, "computePairsKernelOriginal", &errNum, sapProg);
break;
}
case B3_GPU_SAP_KERNEL_BARRIER:
{
- m_sapKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,sapSrc, "computePairsKernelBarrier",&errNum,sapProg );
+ m_sapKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, sapSrc, "computePairsKernelBarrier", &errNum, sapProg);
break;
}
case B3_GPU_SAP_KERNEL_LOCAL_SHARED_MEMORY:
{
- m_sapKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,sapSrc, "computePairsKernelLocalSharedMemory",&errNum,sapProg );
+ m_sapKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, sapSrc, "computePairsKernelLocalSharedMemory", &errNum, sapProg);
break;
}
default:
{
- m_sapKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,sapSrc, "computePairsKernelLocalSharedMemory",&errNum,sapProg );
+ m_sapKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, sapSrc, "computePairsKernelLocalSharedMemory", &errNum, sapProg);
b3Error("Unknown 3D GPU SAP provided, fallback to computePairsKernelLocalSharedMemory");
}
};
-
-
-
- m_sap2Kernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,sapSrc, "computePairsKernelTwoArrays",&errNum,sapProg );
- b3Assert(errNum==CL_SUCCESS);
- m_prepareSumVarianceKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,sapSrc, "prepareSumVarianceKernel",&errNum,sapProg );
- b3Assert(errNum==CL_SUCCESS);
+ m_sap2Kernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, sapSrc, "computePairsKernelTwoArrays", &errNum, sapProg);
+ b3Assert(errNum == CL_SUCCESS);
-
- m_flipFloatKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,sapSrc, "flipFloatKernel",&errNum,sapProg );
+ m_prepareSumVarianceKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, sapSrc, "prepareSumVarianceKernel", &errNum, sapProg);
+ b3Assert(errNum == CL_SUCCESS);
- m_copyAabbsKernel= b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,sapSrc, "copyAabbsKernel",&errNum,sapProg );
+ m_flipFloatKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, sapSrc, "flipFloatKernel", &errNum, sapProg);
- m_scatterKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,sapSrc, "scatterKernel",&errNum,sapProg );
+ m_copyAabbsKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, sapSrc, "copyAabbsKernel", &errNum, sapProg);
- m_sorter = new b3RadixSort32CL(m_context,m_device,m_queue);
+ m_scatterKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, sapSrc, "scatterKernel", &errNum, sapProg);
+
+ m_sorter = new b3RadixSort32CL(m_context, m_device, m_queue);
}
b3GpuSapBroadphase::~b3GpuSapBroadphase()
@@ -173,13 +167,11 @@ b3GpuSapBroadphase::~b3GpuSapBroadphase()
clReleaseKernel(m_sapKernel);
clReleaseKernel(m_sap2Kernel);
clReleaseKernel(m_prepareSumVarianceKernel);
-
-
}
/// conservative test for overlap between two aabbs
-static bool TestAabbAgainstAabb2(const b3Vector3 &aabbMin1, const b3Vector3 &aabbMax1,
- const b3Vector3 &aabbMin2, const b3Vector3 &aabbMax2)
+static bool TestAabbAgainstAabb2(const b3Vector3& aabbMin1, const b3Vector3& aabbMax1,
+ const b3Vector3& aabbMin2, const b3Vector3& aabbMax2)
{
bool overlap = true;
overlap = (aabbMin1.getX() > aabbMax2.getX() || aabbMax1.getX() < aabbMin2.getX()) ? false : overlap;
@@ -188,8 +180,6 @@ static bool TestAabbAgainstAabb2(const b3Vector3 &aabbMin1, const b3Vector3 &aab
return overlap;
}
-
-
//http://stereopsis.com/radix.html
static unsigned int FloatFlip(float fl)
{
@@ -198,79 +188,77 @@ static unsigned int FloatFlip(float fl)
return f ^ mask;
};
-void b3GpuSapBroadphase::init3dSap()
+void b3GpuSapBroadphase::init3dSap()
{
- if (m_currentBuffer<0)
+ if (m_currentBuffer < 0)
{
m_allAabbsGPU.copyToHost(m_allAabbsCPU);
m_currentBuffer = 0;
- for (int axis=0;axis<3;axis++)
+ for (int axis = 0; axis < 3; axis++)
{
- for (int buf=0;buf<2;buf++)
+ for (int buf = 0; buf < 2; buf++)
{
int totalNumAabbs = m_allAabbsCPU.size();
- int numEndPoints = 2*totalNumAabbs;
+ int numEndPoints = 2 * totalNumAabbs;
m_sortedAxisCPU[axis][buf].resize(numEndPoints);
- if (buf==m_currentBuffer)
+ if (buf == m_currentBuffer)
{
- for (int i=0;i<totalNumAabbs;i++)
+ for (int i = 0; i < totalNumAabbs; i++)
{
- m_sortedAxisCPU[axis][buf][i*2].m_key = FloatFlip(m_allAabbsCPU[i].m_min[axis])-1;
- m_sortedAxisCPU[axis][buf][i*2].m_value = i*2;
- m_sortedAxisCPU[axis][buf][i*2+1].m_key = FloatFlip(m_allAabbsCPU[i].m_max[axis])+1;
- m_sortedAxisCPU[axis][buf][i*2+1].m_value = i*2+1;
+ m_sortedAxisCPU[axis][buf][i * 2].m_key = FloatFlip(m_allAabbsCPU[i].m_min[axis]) - 1;
+ m_sortedAxisCPU[axis][buf][i * 2].m_value = i * 2;
+ m_sortedAxisCPU[axis][buf][i * 2 + 1].m_key = FloatFlip(m_allAabbsCPU[i].m_max[axis]) + 1;
+ m_sortedAxisCPU[axis][buf][i * 2 + 1].m_value = i * 2 + 1;
}
}
}
}
- for (int axis=0;axis<3;axis++)
+ for (int axis = 0; axis < 3; axis++)
{
m_sorter->executeHost(m_sortedAxisCPU[axis][m_currentBuffer]);
}
- for (int axis=0;axis<3;axis++)
+ for (int axis = 0; axis < 3; axis++)
{
//int totalNumAabbs = m_allAabbsCPU.size();
int numEndPoints = m_sortedAxisCPU[axis][m_currentBuffer].size();
m_objectMinMaxIndexCPU[axis][m_currentBuffer].resize(numEndPoints);
- for (int i=0;i<numEndPoints;i++)
+ for (int i = 0; i < numEndPoints; i++)
{
int destIndex = m_sortedAxisCPU[axis][m_currentBuffer][i].m_value;
- int newDest = destIndex/2;
- if (destIndex&1)
+ int newDest = destIndex / 2;
+ if (destIndex & 1)
{
- m_objectMinMaxIndexCPU[axis][m_currentBuffer][newDest].y=i;
- } else
+ m_objectMinMaxIndexCPU[axis][m_currentBuffer][newDest].y = i;
+ }
+ else
{
- m_objectMinMaxIndexCPU[axis][m_currentBuffer][newDest].x=i;
+ m_objectMinMaxIndexCPU[axis][m_currentBuffer][newDest].x = i;
}
}
}
-
}
}
-
static bool b3PairCmp(const b3Int4& p, const b3Int4& q)
{
- return ((p.x<q.x) || ((p.x==q.x) && (p.y<q.y)));
+ return ((p.x < q.x) || ((p.x == q.x) && (p.y < q.y)));
}
-
-static bool operator==(const b3Int4& a,const b3Int4& b)
+static bool operator==(const b3Int4& a, const b3Int4& b)
{
return a.x == b.x && a.y == b.y;
};
-static bool operator<(const b3Int4& a,const b3Int4& b)
+static bool operator<(const b3Int4& a, const b3Int4& b)
{
return a.x < b.x || (a.x == b.x && a.y < b.y);
};
-static bool operator>(const b3Int4& a,const b3Int4& b)
+static bool operator>(const b3Int4& a, const b3Int4& b)
{
return a.x > b.x || (a.x == b.x && a.y > b.y);
};
@@ -278,31 +266,29 @@ static bool operator>(const b3Int4& a,const b3Int4& b)
b3AlignedObjectArray<b3Int4> addedHostPairs;
b3AlignedObjectArray<b3Int4> removedHostPairs;
-b3AlignedObjectArray<b3SapAabb> preAabbs;
+b3AlignedObjectArray<b3SapAabb> preAabbs;
-void b3GpuSapBroadphase::calculateOverlappingPairsHostIncremental3Sap()
+void b3GpuSapBroadphase::calculateOverlappingPairsHostIncremental3Sap()
{
//static int framepje = 0;
//printf("framepje=%d\n",framepje++);
-
B3_PROFILE("calculateOverlappingPairsHostIncremental3Sap");
addedHostPairs.resize(0);
removedHostPairs.resize(0);
- b3Assert(m_currentBuffer>=0);
-
+ b3Assert(m_currentBuffer >= 0);
+
{
preAabbs.resize(m_allAabbsCPU.size());
- for (int i=0;i<preAabbs.size();i++)
+ for (int i = 0; i < preAabbs.size(); i++)
{
- preAabbs[i]=m_allAabbsCPU[i];
+ preAabbs[i] = m_allAabbsCPU[i];
}
}
-
- if (m_currentBuffer<0)
+ if (m_currentBuffer < 0)
return;
{
B3_PROFILE("m_allAabbsGPU.copyToHost");
@@ -316,100 +302,87 @@ void b3GpuSapBroadphase::calculateOverlappingPairsHostIncremental3Sap()
}
if (0)
{
- {
- printf("ab[40].min=%f,%f,%f,ab[40].max=%f,%f,%f\n",
- m_allAabbsCPU[40].m_min[0], m_allAabbsCPU[40].m_min[1],m_allAabbsCPU[40].m_min[2],
- m_allAabbsCPU[40].m_max[0], m_allAabbsCPU[40].m_max[1],m_allAabbsCPU[40].m_max[2]);
- }
-
- {
- printf("ab[53].min=%f,%f,%f,ab[53].max=%f,%f,%f\n",
- m_allAabbsCPU[53].m_min[0], m_allAabbsCPU[53].m_min[1],m_allAabbsCPU[53].m_min[2],
- m_allAabbsCPU[53].m_max[0], m_allAabbsCPU[53].m_max[1],m_allAabbsCPU[53].m_max[2]);
- }
-
-
- {
- b3Int4 newPair;
- newPair.x = 40;
- newPair.y = 53;
- int index = allPairs.findBinarySearch(newPair);
- printf("hasPair(40,53)=%d out of %d\n",index, allPairs.size());
-
{
- int overlap = TestAabbAgainstAabb2((const b3Vector3&)m_allAabbsCPU[40].m_min, (const b3Vector3&)m_allAabbsCPU[40].m_max,(const b3Vector3&)m_allAabbsCPU[53].m_min,(const b3Vector3&)m_allAabbsCPU[53].m_max);
- printf("overlap=%d\n",overlap);
+ printf("ab[40].min=%f,%f,%f,ab[40].max=%f,%f,%f\n",
+ m_allAabbsCPU[40].m_min[0], m_allAabbsCPU[40].m_min[1], m_allAabbsCPU[40].m_min[2],
+ m_allAabbsCPU[40].m_max[0], m_allAabbsCPU[40].m_max[1], m_allAabbsCPU[40].m_max[2]);
}
- if (preAabbs.size())
- {
- int prevOverlap = TestAabbAgainstAabb2((const b3Vector3&)preAabbs[40].m_min, (const b3Vector3&)preAabbs[40].m_max,(const b3Vector3&)preAabbs[53].m_min,(const b3Vector3&)preAabbs[53].m_max);
- printf("prevoverlap=%d\n",prevOverlap);
- } else
{
- printf("unknown prevoverlap\n");
+ printf("ab[53].min=%f,%f,%f,ab[53].max=%f,%f,%f\n",
+ m_allAabbsCPU[53].m_min[0], m_allAabbsCPU[53].m_min[1], m_allAabbsCPU[53].m_min[2],
+ m_allAabbsCPU[53].m_max[0], m_allAabbsCPU[53].m_max[1], m_allAabbsCPU[53].m_max[2]);
}
- }
- }
+ {
+ b3Int4 newPair;
+ newPair.x = 40;
+ newPair.y = 53;
+ int index = allPairs.findBinarySearch(newPair);
+ printf("hasPair(40,53)=%d out of %d\n", index, allPairs.size());
+ {
+ int overlap = TestAabbAgainstAabb2((const b3Vector3&)m_allAabbsCPU[40].m_min, (const b3Vector3&)m_allAabbsCPU[40].m_max, (const b3Vector3&)m_allAabbsCPU[53].m_min, (const b3Vector3&)m_allAabbsCPU[53].m_max);
+ printf("overlap=%d\n", overlap);
+ }
+
+ if (preAabbs.size())
+ {
+ int prevOverlap = TestAabbAgainstAabb2((const b3Vector3&)preAabbs[40].m_min, (const b3Vector3&)preAabbs[40].m_max, (const b3Vector3&)preAabbs[53].m_min, (const b3Vector3&)preAabbs[53].m_max);
+ printf("prevoverlap=%d\n", prevOverlap);
+ }
+ else
+ {
+ printf("unknown prevoverlap\n");
+ }
+ }
+ }
if (0)
{
- for (int i=0;i<m_allAabbsCPU.size();i++)
+ for (int i = 0; i < m_allAabbsCPU.size(); i++)
{
//printf("aabb[%d] min=%f,%f,%f max=%f,%f,%f\n",i,m_allAabbsCPU[i].m_min[0],m_allAabbsCPU[i].m_min[1],m_allAabbsCPU[i].m_min[2], m_allAabbsCPU[i].m_max[0],m_allAabbsCPU[i].m_max[1],m_allAabbsCPU[i].m_max[2]);
-
-
}
- for (int axis=0;axis<3;axis++)
+ for (int axis = 0; axis < 3; axis++)
{
- for (int buf=0;buf<2;buf++)
+ for (int buf = 0; buf < 2; buf++)
{
- b3Assert(m_sortedAxisCPU[axis][buf].size() == m_allAabbsCPU.size()*2);
+ b3Assert(m_sortedAxisCPU[axis][buf].size() == m_allAabbsCPU.size() * 2);
}
}
}
-
-
- m_currentBuffer = 1-m_currentBuffer;
-
-
+ m_currentBuffer = 1 - m_currentBuffer;
int totalNumAabbs = m_allAabbsCPU.size();
{
B3_PROFILE("assign m_sortedAxisCPU(FloatFlip)");
- for (int i=0;i<totalNumAabbs;i++)
+ for (int i = 0; i < totalNumAabbs; i++)
{
-
-
unsigned int keyMin[3];
unsigned int keyMax[3];
- for (int axis=0;axis<3;axis++)
+ for (int axis = 0; axis < 3; axis++)
{
- float vmin=m_allAabbsCPU[i].m_min[axis];
+ float vmin = m_allAabbsCPU[i].m_min[axis];
float vmax = m_allAabbsCPU[i].m_max[axis];
keyMin[axis] = FloatFlip(vmin);
keyMax[axis] = FloatFlip(vmax);
-
- m_sortedAxisCPU[axis][m_currentBuffer][i*2].m_key = keyMin[axis]-1;
- m_sortedAxisCPU[axis][m_currentBuffer][i*2].m_value = i*2;
- m_sortedAxisCPU[axis][m_currentBuffer][i*2+1].m_key = keyMax[axis]+1;
- m_sortedAxisCPU[axis][m_currentBuffer][i*2+1].m_value = i*2+1;
+
+ m_sortedAxisCPU[axis][m_currentBuffer][i * 2].m_key = keyMin[axis] - 1;
+ m_sortedAxisCPU[axis][m_currentBuffer][i * 2].m_value = i * 2;
+ m_sortedAxisCPU[axis][m_currentBuffer][i * 2 + 1].m_key = keyMax[axis] + 1;
+ m_sortedAxisCPU[axis][m_currentBuffer][i * 2 + 1].m_value = i * 2 + 1;
}
//printf("aabb[%d] min=%u,%u,%u max %u,%u,%u\n", i,keyMin[0],keyMin[1],keyMin[2],keyMax[0],keyMax[1],keyMax[2]);
-
}
}
-
-
{
B3_PROFILE("sort m_sortedAxisCPU");
- for (int axis=0;axis<3;axis++)
+ for (int axis = 0; axis < 3; axis++)
m_sorter->executeHost(m_sortedAxisCPU[axis][m_currentBuffer]);
}
@@ -432,21 +405,22 @@ void b3GpuSapBroadphase::calculateOverlappingPairsHostIncremental3Sap()
{
B3_PROFILE("assign m_objectMinMaxIndexCPU");
- for (int axis=0;axis<3;axis++)
+ for (int axis = 0; axis < 3; axis++)
{
int totalNumAabbs = m_allAabbsCPU.size();
int numEndPoints = m_sortedAxisCPU[axis][m_currentBuffer].size();
m_objectMinMaxIndexCPU[axis][m_currentBuffer].resize(totalNumAabbs);
- for (int i=0;i<numEndPoints;i++)
+ for (int i = 0; i < numEndPoints; i++)
{
int destIndex = m_sortedAxisCPU[axis][m_currentBuffer][i].m_value;
- int newDest = destIndex/2;
- if (destIndex&1)
+ int newDest = destIndex / 2;
+ if (destIndex & 1)
{
- m_objectMinMaxIndexCPU[axis][m_currentBuffer][newDest].y=i;
- } else
+ m_objectMinMaxIndexCPU[axis][m_currentBuffer][newDest].y = i;
+ }
+ else
{
- m_objectMinMaxIndexCPU[axis][m_currentBuffer][newDest].x=i;
+ m_objectMinMaxIndexCPU[axis][m_currentBuffer][newDest].x = i;
}
}
}
@@ -485,12 +459,11 @@ void b3GpuSapBroadphase::calculateOverlappingPairsHostIncremental3Sap()
}
#endif
-
int a = m_objectMinMaxIndexCPU[0][m_currentBuffer].size();
int b = m_objectMinMaxIndexCPU[1][m_currentBuffer].size();
int c = m_objectMinMaxIndexCPU[2][m_currentBuffer].size();
- b3Assert(a==b);
- b3Assert(b==c);
+ b3Assert(a == b);
+ b3Assert(b == c);
/*
if (searchIncremental3dSapOnGpu)
{
@@ -574,175 +547,170 @@ void b3GpuSapBroadphase::calculateOverlappingPairsHostIncremental3Sap()
int numObjects = m_objectMinMaxIndexCPU[0][m_currentBuffer].size();
B3_PROFILE("actual search");
- for (int i=0;i<numObjects;i++)
+ for (int i = 0; i < numObjects; i++)
{
//int numObjects = m_objectMinMaxIndexCPU[axis][m_currentBuffer].size();
//int checkObjects[]={40,53};
//int numCheckObjects = sizeof(checkObjects)/sizeof(int);
-
+
//for (int a=0;a<numCheckObjects ;a++)
-
- for (int axis=0;axis<3;axis++)
+
+ for (int axis = 0; axis < 3; axis++)
{
//int i = checkObjects[a];
unsigned int curMinIndex = m_objectMinMaxIndexCPU[axis][m_currentBuffer][i].x;
unsigned int curMaxIndex = m_objectMinMaxIndexCPU[axis][m_currentBuffer][i].y;
- unsigned int prevMinIndex = m_objectMinMaxIndexCPU[axis][1-m_currentBuffer][i].x;
+ unsigned int prevMinIndex = m_objectMinMaxIndexCPU[axis][1 - m_currentBuffer][i].x;
int dmin = curMinIndex - prevMinIndex;
-
- unsigned int prevMaxIndex = m_objectMinMaxIndexCPU[axis][1-m_currentBuffer][i].y;
-
+ unsigned int prevMaxIndex = m_objectMinMaxIndexCPU[axis][1 - m_currentBuffer][i].y;
int dmax = curMaxIndex - prevMaxIndex;
- if (dmin!=0)
+ if (dmin != 0)
{
//printf("for object %d, dmin=%d\n",i,dmin);
}
- if (dmax!=0)
+ if (dmax != 0)
{
//printf("for object %d, dmax=%d\n",i,dmax);
}
- for (int otherbuffer = 0;otherbuffer<2;otherbuffer++)
+ for (int otherbuffer = 0; otherbuffer < 2; otherbuffer++)
{
- if (dmin!=0)
+ if (dmin != 0)
{
- int stepMin = dmin<0 ? -1 : 1;
- for (int j=prevMinIndex;j!=curMinIndex;j+=stepMin)
+ int stepMin = dmin < 0 ? -1 : 1;
+ for (int j = prevMinIndex; j != curMinIndex; j += stepMin)
{
int otherIndex2 = m_sortedAxisCPU[axis][otherbuffer][j].y;
- int otherIndex = otherIndex2/2;
- if (otherIndex!=i)
+ int otherIndex = otherIndex2 / 2;
+ if (otherIndex != i)
{
- bool otherIsMax = ((otherIndex2&1)!=0);
+ bool otherIsMax = ((otherIndex2 & 1) != 0);
if (otherIsMax)
{
//bool overlap = TestAabbAgainstAabb2((const b3Vector3&)m_allAabbsCPU[i].m_min, (const b3Vector3&)m_allAabbsCPU[i].m_max,(const b3Vector3&)m_allAabbsCPU[otherIndex].m_min,(const b3Vector3&)m_allAabbsCPU[otherIndex].m_max);
//bool prevOverlap = TestAabbAgainstAabb2((const b3Vector3&)preAabbs[i].m_min, (const b3Vector3&)preAabbs[i].m_max,(const b3Vector3&)preAabbs[otherIndex].m_min,(const b3Vector3&)preAabbs[otherIndex].m_max);
-
+
bool overlap = true;
- for (int ax=0;ax<3;ax++)
+ for (int ax = 0; ax < 3; ax++)
{
if ((m_objectMinMaxIndexCPU[ax][m_currentBuffer][i].x > m_objectMinMaxIndexCPU[ax][m_currentBuffer][otherIndex].y) ||
(m_objectMinMaxIndexCPU[ax][m_currentBuffer][i].y < m_objectMinMaxIndexCPU[ax][m_currentBuffer][otherIndex].x))
- overlap=false;
+ overlap = false;
}
- // b3Assert(overlap2==overlap);
+ // b3Assert(overlap2==overlap);
bool prevOverlap = true;
- for (int ax=0;ax<3;ax++)
+ for (int ax = 0; ax < 3; ax++)
{
- if ((m_objectMinMaxIndexCPU[ax][1-m_currentBuffer][i].x > m_objectMinMaxIndexCPU[ax][1-m_currentBuffer][otherIndex].y) ||
- (m_objectMinMaxIndexCPU[ax][1-m_currentBuffer][i].y < m_objectMinMaxIndexCPU[ax][1-m_currentBuffer][otherIndex].x))
- prevOverlap=false;
+ if ((m_objectMinMaxIndexCPU[ax][1 - m_currentBuffer][i].x > m_objectMinMaxIndexCPU[ax][1 - m_currentBuffer][otherIndex].y) ||
+ (m_objectMinMaxIndexCPU[ax][1 - m_currentBuffer][i].y < m_objectMinMaxIndexCPU[ax][1 - m_currentBuffer][otherIndex].x))
+ prevOverlap = false;
}
-
//b3Assert(overlap==overlap2);
-
-
- if (dmin<0)
+ if (dmin < 0)
{
if (overlap && !prevOverlap)
{
//add a pair
b3Int4 newPair;
- if (i<=otherIndex)
+ if (i <= otherIndex)
{
newPair.x = i;
newPair.y = otherIndex;
- } else
+ }
+ else
{
newPair.x = otherIndex;
newPair.y = i;
}
addedHostPairs.push_back(newPair);
}
- }
+ }
else
{
if (!overlap && prevOverlap)
{
-
//remove a pair
b3Int4 removedPair;
- if (i<=otherIndex)
+ if (i <= otherIndex)
{
removedPair.x = i;
removedPair.y = otherIndex;
- } else
+ }
+ else
{
removedPair.x = otherIndex;
removedPair.y = i;
}
removedHostPairs.push_back(removedPair);
}
- }//otherisMax
- }//if (dmin<0)
- }//if (otherIndex!=i)
- }//for (int j=
+ } //otherisMax
+ } //if (dmin<0)
+ } //if (otherIndex!=i)
+ } //for (int j=
}
-
- if (dmax!=0)
+
+ if (dmax != 0)
{
- int stepMax = dmax<0 ? -1 : 1;
- for (int j=prevMaxIndex;j!=curMaxIndex;j+=stepMax)
+ int stepMax = dmax < 0 ? -1 : 1;
+ for (int j = prevMaxIndex; j != curMaxIndex; j += stepMax)
{
int otherIndex2 = m_sortedAxisCPU[axis][otherbuffer][j].y;
- int otherIndex = otherIndex2/2;
- if (otherIndex!=i)
+ int otherIndex = otherIndex2 / 2;
+ if (otherIndex != i)
{
//bool otherIsMin = ((otherIndex2&1)==0);
//if (otherIsMin)
{
//bool overlap = TestAabbAgainstAabb2((const b3Vector3&)m_allAabbsCPU[i].m_min, (const b3Vector3&)m_allAabbsCPU[i].m_max,(const b3Vector3&)m_allAabbsCPU[otherIndex].m_min,(const b3Vector3&)m_allAabbsCPU[otherIndex].m_max);
//bool prevOverlap = TestAabbAgainstAabb2((const b3Vector3&)preAabbs[i].m_min, (const b3Vector3&)preAabbs[i].m_max,(const b3Vector3&)preAabbs[otherIndex].m_min,(const b3Vector3&)preAabbs[otherIndex].m_max);
-
+
bool overlap = true;
- for (int ax=0;ax<3;ax++)
+ for (int ax = 0; ax < 3; ax++)
{
if ((m_objectMinMaxIndexCPU[ax][m_currentBuffer][i].x > m_objectMinMaxIndexCPU[ax][m_currentBuffer][otherIndex].y) ||
(m_objectMinMaxIndexCPU[ax][m_currentBuffer][i].y < m_objectMinMaxIndexCPU[ax][m_currentBuffer][otherIndex].x))
- overlap=false;
+ overlap = false;
}
//b3Assert(overlap2==overlap);
bool prevOverlap = true;
- for (int ax=0;ax<3;ax++)
+ for (int ax = 0; ax < 3; ax++)
{
- if ((m_objectMinMaxIndexCPU[ax][1-m_currentBuffer][i].x > m_objectMinMaxIndexCPU[ax][1-m_currentBuffer][otherIndex].y) ||
- (m_objectMinMaxIndexCPU[ax][1-m_currentBuffer][i].y < m_objectMinMaxIndexCPU[ax][1-m_currentBuffer][otherIndex].x))
- prevOverlap=false;
+ if ((m_objectMinMaxIndexCPU[ax][1 - m_currentBuffer][i].x > m_objectMinMaxIndexCPU[ax][1 - m_currentBuffer][otherIndex].y) ||
+ (m_objectMinMaxIndexCPU[ax][1 - m_currentBuffer][i].y < m_objectMinMaxIndexCPU[ax][1 - m_currentBuffer][otherIndex].x))
+ prevOverlap = false;
}
-
- if (dmax>0)
+ if (dmax > 0)
{
if (overlap && !prevOverlap)
{
//add a pair
b3Int4 newPair;
- if (i<=otherIndex)
+ if (i <= otherIndex)
{
newPair.x = i;
newPair.y = otherIndex;
- } else
+ }
+ else
{
newPair.x = otherIndex;
newPair.y = i;
}
addedHostPairs.push_back(newPair);
-
}
- }
+ }
else
{
if (!overlap && prevOverlap)
@@ -750,33 +718,31 @@ void b3GpuSapBroadphase::calculateOverlappingPairsHostIncremental3Sap()
//if (otherIndex2&1==0) -> min?
//remove a pair
b3Int4 removedPair;
- if (i<=otherIndex)
+ if (i <= otherIndex)
{
removedPair.x = i;
removedPair.y = otherIndex;
- } else
+ }
+ else
{
removedPair.x = otherIndex;
removedPair.y = i;
}
removedHostPairs.push_back(removedPair);
-
}
}
-
- }//if (dmin<0)
- }//if (otherIndex!=i)
- }//for (int j=
+
+ } //if (dmin<0)
+ } //if (otherIndex!=i)
+ } //for (int j=
}
- }//for (int otherbuffer
- }//for (int axis=0;
- }//for (int i=0;i<numObjects
+ } //for (int otherbuffer
+ } //for (int axis=0;
+ } //for (int i=0;i<numObjects
}
//remove duplicates and add/remove then to existing m_overlappingPairs
-
-
-
+
{
{
B3_PROFILE("sort allPairs");
@@ -795,31 +761,28 @@ void b3GpuSapBroadphase::calculateOverlappingPairsHostIncremental3Sap()
b3Int4 prevPair;
prevPair.x = -1;
prevPair.y = -1;
-
+
int uniqueRemovedPairs = 0;
b3AlignedObjectArray<int> removedPositions;
{
B3_PROFILE("actual removing");
- for (int i=0;i<removedHostPairs.size();i++)
+ for (int i = 0; i < removedHostPairs.size(); i++)
{
b3Int4 removedPair = removedHostPairs[i];
if ((removedPair.x != prevPair.x) || (removedPair.y != prevPair.y))
{
+ int index1 = allPairs.findBinarySearch(removedPair);
- int index1 = allPairs.findBinarySearch(removedPair);
+ //#ifdef _DEBUG
- //#ifdef _DEBUG
-
-
-
int index2 = allPairs.findLinearSearch(removedPair);
- b3Assert(index1==index2);
-
+ b3Assert(index1 == index2);
+
//b3Assert(index1!=allPairs.size());
- if (index1<allPairs.size())
- //#endif//_DEBUG
+ if (index1 < allPairs.size())
+ //#endif//_DEBUG
{
uniqueRemovedPairs++;
removedPositions.push_back(index1);
@@ -833,13 +796,13 @@ void b3GpuSapBroadphase::calculateOverlappingPairsHostIncremental3Sap()
if (uniqueRemovedPairs)
{
- for (int i=0;i<removedPositions.size();i++)
+ for (int i = 0; i < removedPositions.size(); i++)
{
- allPairs[removedPositions[i]].x = INT_MAX ;
- allPairs[removedPositions[i]].y = INT_MAX ;
+ allPairs[removedPositions[i]].x = INT_MAX;
+ allPairs[removedPositions[i]].y = INT_MAX;
}
allPairs.quickSort(b3PairCmp);
- allPairs.resize(allPairs.size()-uniqueRemovedPairs);
+ allPairs.resize(allPairs.size() - uniqueRemovedPairs);
}
}
//if (uniqueRemovedPairs)
@@ -848,33 +811,31 @@ void b3GpuSapBroadphase::calculateOverlappingPairsHostIncremental3Sap()
prevPair.x = -1;
prevPair.y = -1;
-
- int uniqueAddedPairs=0;
+
+ int uniqueAddedPairs = 0;
b3AlignedObjectArray<b3Int4> actualAddedPairs;
{
B3_PROFILE("actual adding");
- for (int i=0;i<addedHostPairs.size();i++)
+ for (int i = 0; i < addedHostPairs.size(); i++)
{
b3Int4 newPair = addedHostPairs[i];
if ((newPair.x != prevPair.x) || (newPair.y != prevPair.y))
{
-//#ifdef _DEBUG
+ //#ifdef _DEBUG
int index1 = allPairs.findBinarySearch(newPair);
-
-
+
int index2 = allPairs.findLinearSearch(newPair);
- b3Assert(index1==index2);
-
+ b3Assert(index1 == index2);
- b3Assert(index1==allPairs.size());
- if (index1!=allPairs.size())
+ b3Assert(index1 == allPairs.size());
+ if (index1 != allPairs.size())
{
printf("??\n");
}
- if (index1==allPairs.size())
-//#endif //_DEBUG
+ if (index1 == allPairs.size())
+ //#endif //_DEBUG
{
uniqueAddedPairs++;
actualAddedPairs.push_back(newPair);
@@ -882,94 +843,83 @@ void b3GpuSapBroadphase::calculateOverlappingPairsHostIncremental3Sap()
}
prevPair = newPair;
}
- for (int i=0;i<actualAddedPairs.size();i++)
+ for (int i = 0; i < actualAddedPairs.size(); i++)
{
//printf("framepje (%d), new pair(%d):%d,%d\n",framepje,i,actualAddedPairs[i].x,actualAddedPairs[i].y);
allPairs.push_back(actualAddedPairs[i]);
}
}
-
+
//if (uniqueAddedPairs)
// printf("uniqueAddedPairs=%d\n", uniqueAddedPairs);
-
{
B3_PROFILE("m_overlappingPairs.copyFromHost");
m_overlappingPairs.copyFromHost(allPairs);
}
-
-
}
-
-
-
-void b3GpuSapBroadphase::calculateOverlappingPairsHost(int maxPairs)
+void b3GpuSapBroadphase::calculateOverlappingPairsHost(int maxPairs)
{
//test
-// if (m_currentBuffer>=0)
+ // if (m_currentBuffer>=0)
// return calculateOverlappingPairsHostIncremental3Sap();
b3Assert(m_allAabbsCPU.size() == m_allAabbsGPU.size());
m_allAabbsGPU.copyToHost(m_allAabbsCPU);
-
-
- int axis=0;
+ int axis = 0;
{
B3_PROFILE("CPU compute best variance axis");
- b3Vector3 s=b3MakeVector3(0,0,0),s2=b3MakeVector3(0,0,0);
+ b3Vector3 s = b3MakeVector3(0, 0, 0), s2 = b3MakeVector3(0, 0, 0);
int numRigidBodies = m_smallAabbsMappingCPU.size();
- for(int i=0;i<numRigidBodies;i++)
+ for (int i = 0; i < numRigidBodies; i++)
{
b3SapAabb aabb = this->m_allAabbsCPU[m_smallAabbsMappingCPU[i]];
- b3Vector3 maxAabb=b3MakeVector3(aabb.m_max[0],aabb.m_max[1],aabb.m_max[2]);
- b3Vector3 minAabb=b3MakeVector3(aabb.m_min[0],aabb.m_min[1],aabb.m_min[2]);
- b3Vector3 centerAabb=(maxAabb+minAabb)*0.5f;
-
+ b3Vector3 maxAabb = b3MakeVector3(aabb.m_max[0], aabb.m_max[1], aabb.m_max[2]);
+ b3Vector3 minAabb = b3MakeVector3(aabb.m_min[0], aabb.m_min[1], aabb.m_min[2]);
+ b3Vector3 centerAabb = (maxAabb + minAabb) * 0.5f;
+
s += centerAabb;
- s2 += centerAabb*centerAabb;
+ s2 += centerAabb * centerAabb;
}
- b3Vector3 v = s2 - (s*s) / (float)numRigidBodies;
-
- if(v[1] > v[0])
+ b3Vector3 v = s2 - (s * s) / (float)numRigidBodies;
+
+ if (v[1] > v[0])
axis = 1;
- if(v[2] > v[axis])
+ if (v[2] > v[axis])
axis = 2;
}
-
-
-
b3AlignedObjectArray<b3Int4> hostPairs;
{
int numSmallAabbs = m_smallAabbsMappingCPU.size();
- for (int i=0;i<numSmallAabbs;i++)
+ for (int i = 0; i < numSmallAabbs; i++)
{
b3SapAabb smallAabbi = m_allAabbsCPU[m_smallAabbsMappingCPU[i]];
//float reference = smallAabbi.m_max[axis];
- for (int j=i+1;j<numSmallAabbs;j++)
+ for (int j = i + 1; j < numSmallAabbs; j++)
{
-
b3SapAabb smallAabbj = m_allAabbsCPU[m_smallAabbsMappingCPU[j]];
if (TestAabbAgainstAabb2((b3Vector3&)smallAabbi.m_min, (b3Vector3&)smallAabbi.m_max,
- (b3Vector3&)smallAabbj.m_min,(b3Vector3&)smallAabbj.m_max))
+ (b3Vector3&)smallAabbj.m_min, (b3Vector3&)smallAabbj.m_max))
{
b3Int4 pair;
int a = smallAabbi.m_minIndices[3];
int b = smallAabbj.m_minIndices[3];
- if (a<=b)
+ if (a <= b)
{
- pair.x = a;//store the original index in the unsorted aabb array
+ pair.x = a; //store the original index in the unsorted aabb array
pair.y = b;
- } else
+ }
+ else
{
- pair.x = b;//store the original index in the unsorted aabb array
+ pair.x = b; //store the original index in the unsorted aabb array
pair.y = a;
}
hostPairs.push_back(pair);
@@ -978,35 +928,35 @@ void b3GpuSapBroadphase::calculateOverlappingPairsHost(int maxPairs)
}
}
-
{
int numSmallAabbs = m_smallAabbsMappingCPU.size();
- for (int i=0;i<numSmallAabbs;i++)
+ for (int i = 0; i < numSmallAabbs; i++)
{
b3SapAabb smallAabbi = m_allAabbsCPU[m_smallAabbsMappingCPU[i]];
//float reference = smallAabbi.m_max[axis];
int numLargeAabbs = m_largeAabbsMappingCPU.size();
- for (int j=0;j<numLargeAabbs;j++)
+ for (int j = 0; j < numLargeAabbs; j++)
{
b3SapAabb largeAabbj = m_allAabbsCPU[m_largeAabbsMappingCPU[j]];
if (TestAabbAgainstAabb2((b3Vector3&)smallAabbi.m_min, (b3Vector3&)smallAabbi.m_max,
- (b3Vector3&)largeAabbj.m_min,(b3Vector3&)largeAabbj.m_max))
+ (b3Vector3&)largeAabbj.m_min, (b3Vector3&)largeAabbj.m_max))
{
b3Int4 pair;
int a = largeAabbj.m_minIndices[3];
int b = smallAabbi.m_minIndices[3];
- if (a<=b)
+ if (a <= b)
{
- pair.x = a;
- pair.y = b;//store the original index in the unsorted aabb array
- } else
+ pair.x = a;
+ pair.y = b; //store the original index in the unsorted aabb array
+ }
+ else
{
pair.x = b;
- pair.y = a;//store the original index in the unsorted aabb array
+ pair.y = a; //store the original index in the unsorted aabb array
}
-
+
hostPairs.push_back(pair);
}
}
@@ -1021,21 +971,20 @@ void b3GpuSapBroadphase::calculateOverlappingPairsHost(int maxPairs)
if (hostPairs.size())
{
m_overlappingPairs.copyFromHost(hostPairs);
- } else
+ }
+ else
{
m_overlappingPairs.resize(0);
}
//init3dSap();
-
}
-void b3GpuSapBroadphase::reset()
+void b3GpuSapBroadphase::reset()
{
m_allAabbsGPU.resize(0);
m_allAabbsCPU.resize(0);
-
m_smallAabbsMappingGPU.resize(0);
m_smallAabbsMappingCPU.resize(0);
@@ -1043,13 +992,11 @@ void b3GpuSapBroadphase::reset()
m_largeAabbsMappingGPU.resize(0);
m_largeAabbsMappingCPU.resize(0);
-
}
-
-void b3GpuSapBroadphase::calculateOverlappingPairs(int maxPairs)
+void b3GpuSapBroadphase::calculateOverlappingPairs(int maxPairs)
{
- if (m_sapKernel==0)
+ if (m_sapKernel == 0)
{
calculateOverlappingPairsHost(maxPairs);
return;
@@ -1065,68 +1012,62 @@ void b3GpuSapBroadphase::calculateOverlappingPairs(int maxPairs)
int axis = 0;
{
+ //bool syncOnHost = false;
- //bool syncOnHost = false;
-
- int numSmallAabbs = m_smallAabbsMappingCPU.size();
- if (m_prefixScanFloat4 && numSmallAabbs)
- {
- B3_PROFILE("GPU compute best variance axis");
-
- if (m_dst.size()!=(numSmallAabbs+1))
+ int numSmallAabbs = m_smallAabbsMappingCPU.size();
+ if (m_prefixScanFloat4 && numSmallAabbs)
{
- m_dst.resize(numSmallAabbs+128);
- m_sum.resize(numSmallAabbs+128);
- m_sum2.resize(numSmallAabbs+128);
- m_sum.at(numSmallAabbs)=b3MakeVector3(0,0,0); //slow?
- m_sum2.at(numSmallAabbs)=b3MakeVector3(0,0,0); //slow?
- }
+ B3_PROFILE("GPU compute best variance axis");
- b3LauncherCL launcher(m_queue, m_prepareSumVarianceKernel ,"m_prepareSumVarianceKernel");
- launcher.setBuffer(m_allAabbsGPU.getBufferCL());
-
- launcher.setBuffer(m_smallAabbsMappingGPU.getBufferCL());
- launcher.setBuffer(m_sum.getBufferCL());
- launcher.setBuffer(m_sum2.getBufferCL());
- launcher.setConst( numSmallAabbs );
- int num = numSmallAabbs;
- launcher.launch1D( num);
-
+ if (m_dst.size() != (numSmallAabbs + 1))
+ {
+ m_dst.resize(numSmallAabbs + 128);
+ m_sum.resize(numSmallAabbs + 128);
+ m_sum2.resize(numSmallAabbs + 128);
+ m_sum.at(numSmallAabbs) = b3MakeVector3(0, 0, 0); //slow?
+ m_sum2.at(numSmallAabbs) = b3MakeVector3(0, 0, 0); //slow?
+ }
- b3Vector3 s;
- b3Vector3 s2;
- m_prefixScanFloat4->execute(m_sum,m_dst,numSmallAabbs+1,&s);
- m_prefixScanFloat4->execute(m_sum2,m_dst,numSmallAabbs+1,&s2);
+ b3LauncherCL launcher(m_queue, m_prepareSumVarianceKernel, "m_prepareSumVarianceKernel");
+ launcher.setBuffer(m_allAabbsGPU.getBufferCL());
- b3Vector3 v = s2 - (s*s) / (float)numSmallAabbs;
-
- if(v[1] > v[0])
- axis = 1;
- if(v[2] > v[axis])
- axis = 2;
- }
+ launcher.setBuffer(m_smallAabbsMappingGPU.getBufferCL());
+ launcher.setBuffer(m_sum.getBufferCL());
+ launcher.setBuffer(m_sum2.getBufferCL());
+ launcher.setConst(numSmallAabbs);
+ int num = numSmallAabbs;
+ launcher.launch1D(num);
+ b3Vector3 s;
+ b3Vector3 s2;
+ m_prefixScanFloat4->execute(m_sum, m_dst, numSmallAabbs + 1, &s);
+ m_prefixScanFloat4->execute(m_sum2, m_dst, numSmallAabbs + 1, &s2);
+
+ b3Vector3 v = s2 - (s * s) / (float)numSmallAabbs;
+
+ if (v[1] > v[0])
+ axis = 1;
+ if (v[2] > v[axis])
+ axis = 2;
+ }
-
m_gpuSmallSortData.resize(numSmallAabbs);
-
#if 1
if (m_smallAabbsMappingGPU.size())
{
-
B3_PROFILE("flipFloatKernel");
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL( m_allAabbsGPU.getBufferCL(), true ),
- b3BufferInfoCL( m_smallAabbsMappingGPU.getBufferCL(), true),
- b3BufferInfoCL( m_gpuSmallSortData.getBufferCL())};
- b3LauncherCL launcher(m_queue, m_flipFloatKernel ,"m_flipFloatKernel");
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst( numSmallAabbs );
- launcher.setConst( axis );
-
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL(m_allAabbsGPU.getBufferCL(), true),
+ b3BufferInfoCL(m_smallAabbsMappingGPU.getBufferCL(), true),
+ b3BufferInfoCL(m_gpuSmallSortData.getBufferCL())};
+ b3LauncherCL launcher(m_queue, m_flipFloatKernel, "m_flipFloatKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setConst(numSmallAabbs);
+ launcher.setConst(axis);
+
int num = numSmallAabbs;
- launcher.launch1D( num);
+ launcher.launch1D(num);
clFinish(m_queue);
}
@@ -1141,69 +1082,66 @@ void b3GpuSapBroadphase::calculateOverlappingPairs(int maxPairs)
if (numSmallAabbs)
{
B3_PROFILE("scatterKernel");
-
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL( m_allAabbsGPU.getBufferCL(), true ),
- b3BufferInfoCL( m_smallAabbsMappingGPU.getBufferCL(), true),
- b3BufferInfoCL( m_gpuSmallSortData.getBufferCL(),true),
+
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL(m_allAabbsGPU.getBufferCL(), true),
+ b3BufferInfoCL(m_smallAabbsMappingGPU.getBufferCL(), true),
+ b3BufferInfoCL(m_gpuSmallSortData.getBufferCL(), true),
b3BufferInfoCL(m_gpuSmallSortedAabbs.getBufferCL())};
- b3LauncherCL launcher(m_queue, m_scatterKernel ,"m_scatterKernel ");
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst( numSmallAabbs);
+ b3LauncherCL launcher(m_queue, m_scatterKernel, "m_scatterKernel ");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setConst(numSmallAabbs);
int num = numSmallAabbs;
- launcher.launch1D( num);
+ launcher.launch1D(num);
clFinish(m_queue);
-
}
-
- m_overlappingPairs.resize(maxPairs);
+ m_overlappingPairs.resize(maxPairs);
- m_pairCount.resize(0);
- m_pairCount.push_back(0);
- int numPairs=0;
+ m_pairCount.resize(0);
+ m_pairCount.push_back(0);
+ int numPairs = 0;
+ {
+ int numLargeAabbs = m_largeAabbsMappingGPU.size();
+ if (numLargeAabbs && numSmallAabbs)
{
- int numLargeAabbs = m_largeAabbsMappingGPU.size();
- if (numLargeAabbs && numSmallAabbs)
+ //@todo
+ B3_PROFILE("sap2Kernel");
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL(m_allAabbsGPU.getBufferCL()),
+ b3BufferInfoCL(m_largeAabbsMappingGPU.getBufferCL()),
+ b3BufferInfoCL(m_smallAabbsMappingGPU.getBufferCL()),
+ b3BufferInfoCL(m_overlappingPairs.getBufferCL()),
+ b3BufferInfoCL(m_pairCount.getBufferCL())};
+ b3LauncherCL launcher(m_queue, m_sap2Kernel, "m_sap2Kernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setConst(numLargeAabbs);
+ launcher.setConst(numSmallAabbs);
+ launcher.setConst(axis);
+ launcher.setConst(maxPairs);
+ //@todo: use actual maximum work item sizes of the device instead of hardcoded values
+ launcher.launch2D(numLargeAabbs, numSmallAabbs, 4, 64);
+
+ numPairs = m_pairCount.at(0);
+ if (numPairs > maxPairs)
{
- //@todo
- B3_PROFILE("sap2Kernel");
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL( m_allAabbsGPU.getBufferCL() ),
- b3BufferInfoCL( m_largeAabbsMappingGPU.getBufferCL() ),
- b3BufferInfoCL( m_smallAabbsMappingGPU.getBufferCL() ),
- b3BufferInfoCL( m_overlappingPairs.getBufferCL() ),
- b3BufferInfoCL(m_pairCount.getBufferCL())};
- b3LauncherCL launcher(m_queue, m_sap2Kernel,"m_sap2Kernel");
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst( numLargeAabbs );
- launcher.setConst( numSmallAabbs);
- launcher.setConst( axis );
- launcher.setConst( maxPairs );
-//@todo: use actual maximum work item sizes of the device instead of hardcoded values
- launcher.launch2D( numLargeAabbs, numSmallAabbs,4,64);
-
- numPairs = m_pairCount.at(0);
- if (numPairs >maxPairs)
- {
- b3Error("Error running out of pairs: numPairs = %d, maxPairs = %d.\n", numPairs, maxPairs);
- numPairs =maxPairs;
- }
+ b3Error("Error running out of pairs: numPairs = %d, maxPairs = %d.\n", numPairs, maxPairs);
+ numPairs = maxPairs;
}
}
- if (m_gpuSmallSortedAabbs.size())
- {
- B3_PROFILE("sapKernel");
- b3BufferInfoCL bInfo[] = { b3BufferInfoCL( m_gpuSmallSortedAabbs.getBufferCL() ), b3BufferInfoCL( m_overlappingPairs.getBufferCL() ), b3BufferInfoCL(m_pairCount.getBufferCL())};
- b3LauncherCL launcher(m_queue, m_sapKernel,"m_sapKernel");
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst( numSmallAabbs );
- launcher.setConst( axis );
- launcher.setConst( maxPairs );
-
-
- int num = numSmallAabbs;
+ }
+ if (m_gpuSmallSortedAabbs.size())
+ {
+ B3_PROFILE("sapKernel");
+ b3BufferInfoCL bInfo[] = {b3BufferInfoCL(m_gpuSmallSortedAabbs.getBufferCL()), b3BufferInfoCL(m_overlappingPairs.getBufferCL()), b3BufferInfoCL(m_pairCount.getBufferCL())};
+ b3LauncherCL launcher(m_queue, m_sapKernel, "m_sapKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setConst(numSmallAabbs);
+ launcher.setConst(axis);
+ launcher.setConst(maxPairs);
+
+ int num = numSmallAabbs;
#if 0
int buffSize = launcher.getSerializationBufferSize();
unsigned char* buf = new unsigned char[buffSize+sizeof(int)];
@@ -1225,73 +1163,71 @@ void b3GpuSapBroadphase::calculateOverlappingPairs(int maxPairs)
FILE* f = fopen("m_sapKernelArgs.bin","wb");
fwrite(buf,buffSize+sizeof(int),1,f);
fclose(f);
-#endif//
+#endif //
- launcher.launch1D( num);
- clFinish(m_queue);
-
- numPairs = m_pairCount.at(0);
- if (numPairs>maxPairs)
- {
- b3Error("Error running out of pairs: numPairs = %d, maxPairs = %d.\n", numPairs, maxPairs);
- numPairs = maxPairs;
- m_pairCount.resize(0);
- m_pairCount.push_back(maxPairs);
- }
+ launcher.launch1D(num);
+ clFinish(m_queue);
+
+ numPairs = m_pairCount.at(0);
+ if (numPairs > maxPairs)
+ {
+ b3Error("Error running out of pairs: numPairs = %d, maxPairs = %d.\n", numPairs, maxPairs);
+ numPairs = maxPairs;
+ m_pairCount.resize(0);
+ m_pairCount.push_back(maxPairs);
}
-
+ }
+
#else
- int numPairs = 0;
-
-
- b3LauncherCL launcher(m_queue, m_sapKernel);
-
- const char* fileName = "m_sapKernelArgs.bin";
- FILE* f = fopen(fileName,"rb");
- if (f)
- {
- int sizeInBytes=0;
- if (fseek(f, 0, SEEK_END) || (sizeInBytes = ftell(f)) == EOF || fseek(f, 0, SEEK_SET))
- {
- printf("error, cannot get file size\n");
- exit(0);
- }
-
- unsigned char* buf = (unsigned char*) malloc(sizeInBytes);
- fread(buf,sizeInBytes,1,f);
- int serializedBytes = launcher.deserializeArgs(buf, sizeInBytes,m_context);
- int num = *(int*)&buf[serializedBytes];
- launcher.launch1D( num);
-
- b3OpenCLArray<int> pairCount(m_context, m_queue);
- int numElements = launcher.m_arrays[2]->size()/sizeof(int);
- pairCount.setFromOpenCLBuffer(launcher.m_arrays[2]->getBufferCL(),numElements);
- numPairs = pairCount.at(0);
- //printf("overlapping pairs = %d\n",numPairs);
- b3AlignedObjectArray<b3Int4> hostOoverlappingPairs;
- b3OpenCLArray<b3Int4> tmpGpuPairs(m_context,m_queue);
- tmpGpuPairs.setFromOpenCLBuffer(launcher.m_arrays[1]->getBufferCL(),numPairs );
-
- tmpGpuPairs.copyToHost(hostOoverlappingPairs);
- m_overlappingPairs.copyFromHost(hostOoverlappingPairs);
- //printf("hello %d\n", m_overlappingPairs.size());
- free(buf);
- fclose(f);
-
- } else {
- printf("error: cannot find file %s\n",fileName);
- }
-
- clFinish(m_queue);
-
-
+ int numPairs = 0;
+
+ b3LauncherCL launcher(m_queue, m_sapKernel);
+
+ const char* fileName = "m_sapKernelArgs.bin";
+ FILE* f = fopen(fileName, "rb");
+ if (f)
+ {
+ int sizeInBytes = 0;
+ if (fseek(f, 0, SEEK_END) || (sizeInBytes = ftell(f)) == EOF || fseek(f, 0, SEEK_SET))
+ {
+ printf("error, cannot get file size\n");
+ exit(0);
+ }
+
+ unsigned char* buf = (unsigned char*)malloc(sizeInBytes);
+ fread(buf, sizeInBytes, 1, f);
+ int serializedBytes = launcher.deserializeArgs(buf, sizeInBytes, m_context);
+ int num = *(int*)&buf[serializedBytes];
+ launcher.launch1D(num);
+
+ b3OpenCLArray<int> pairCount(m_context, m_queue);
+ int numElements = launcher.m_arrays[2]->size() / sizeof(int);
+ pairCount.setFromOpenCLBuffer(launcher.m_arrays[2]->getBufferCL(), numElements);
+ numPairs = pairCount.at(0);
+ //printf("overlapping pairs = %d\n",numPairs);
+ b3AlignedObjectArray<b3Int4> hostOoverlappingPairs;
+ b3OpenCLArray<b3Int4> tmpGpuPairs(m_context, m_queue);
+ tmpGpuPairs.setFromOpenCLBuffer(launcher.m_arrays[1]->getBufferCL(), numPairs);
+
+ tmpGpuPairs.copyToHost(hostOoverlappingPairs);
+ m_overlappingPairs.copyFromHost(hostOoverlappingPairs);
+ //printf("hello %d\n", m_overlappingPairs.size());
+ free(buf);
+ fclose(f);
+ }
+ else
+ {
+ printf("error: cannot find file %s\n", fileName);
+ }
+
+ clFinish(m_queue);
+
#endif
-
- m_overlappingPairs.resize(numPairs);
-
- }//B3_PROFILE("GPU_RADIX SORT");
- //init3dSap();
+ m_overlappingPairs.resize(numPairs);
+
+ } //B3_PROFILE("GPU_RADIX SORT");
+ //init3dSap();
}
void b3GpuSapBroadphase::writeAabbsToGpu()
@@ -1299,17 +1235,14 @@ void b3GpuSapBroadphase::writeAabbsToGpu()
m_smallAabbsMappingGPU.copyFromHost(m_smallAabbsMappingCPU);
m_largeAabbsMappingGPU.copyFromHost(m_largeAabbsMappingCPU);
- m_allAabbsGPU.copyFromHost(m_allAabbsCPU);//might not be necessary, the 'setupGpuAabbsFull' already takes care of this
-
-
-
+ m_allAabbsGPU.copyFromHost(m_allAabbsCPU); //might not be necessary, the 'setupGpuAabbsFull' already takes care of this
}
-void b3GpuSapBroadphase::createLargeProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr , int collisionFilterGroup, int collisionFilterMask)
+void b3GpuSapBroadphase::createLargeProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask)
{
int index = userPtr;
b3SapAabb aabb;
- for (int i=0;i<4;i++)
+ for (int i = 0; i < 4; i++)
{
aabb.m_min[i] = aabbMin[i];
aabb.m_max[i] = aabbMax[i];
@@ -1317,15 +1250,15 @@ void b3GpuSapBroadphase::createLargeProxy(const b3Vector3& aabbMin, const b3Vec
aabb.m_minIndices[3] = index;
aabb.m_signedMaxIndices[3] = m_allAabbsCPU.size();
m_largeAabbsMappingCPU.push_back(m_allAabbsCPU.size());
-
+
m_allAabbsCPU.push_back(aabb);
}
-void b3GpuSapBroadphase::createProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr , int collisionFilterGroup, int collisionFilterMask)
+void b3GpuSapBroadphase::createProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask)
{
int index = userPtr;
b3SapAabb aabb;
- for (int i=0;i<4;i++)
+ for (int i = 0; i < 4; i++)
{
aabb.m_min[i] = aabbMin[i];
aabb.m_max[i] = aabbMax[i];
@@ -1334,20 +1267,19 @@ void b3GpuSapBroadphase::createProxy(const b3Vector3& aabbMin, const b3Vector3&
aabb.m_signedMaxIndices[3] = m_allAabbsCPU.size();
m_smallAabbsMappingCPU.push_back(m_allAabbsCPU.size());
-
m_allAabbsCPU.push_back(aabb);
}
-cl_mem b3GpuSapBroadphase::getAabbBufferWS()
+cl_mem b3GpuSapBroadphase::getAabbBufferWS()
{
return m_allAabbsGPU.getBufferCL();
}
-int b3GpuSapBroadphase::getNumOverlap()
+int b3GpuSapBroadphase::getNumOverlap()
{
return m_overlappingPairs.size();
}
-cl_mem b3GpuSapBroadphase::getOverlappingPairBuffer()
+cl_mem b3GpuSapBroadphase::getOverlappingPairBuffer()
{
return m_overlappingPairs.getBufferCL();
}
diff --git a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuSapBroadphase.h b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuSapBroadphase.h
index 8d36ac78f2..d17590b14a 100644
--- a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuSapBroadphase.h
+++ b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuSapBroadphase.h
@@ -2,7 +2,7 @@
#define B3_GPU_SAP_BROADPHASE_H
#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
-#include "Bullet3OpenCL/ParallelPrimitives/b3FillCL.h" //b3Int2
+#include "Bullet3OpenCL/ParallelPrimitives/b3FillCL.h" //b3Int2
class b3Vector3;
#include "Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h"
@@ -11,141 +11,133 @@ class b3Vector3;
#include "b3GpuBroadphaseInterface.h"
-
class b3GpuSapBroadphase : public b3GpuBroadphaseInterface
{
-
- cl_context m_context;
- cl_device_id m_device;
- cl_command_queue m_queue;
- cl_kernel m_flipFloatKernel;
- cl_kernel m_scatterKernel ;
- cl_kernel m_copyAabbsKernel;
- cl_kernel m_sapKernel;
- cl_kernel m_sap2Kernel;
- cl_kernel m_prepareSumVarianceKernel;
-
+ cl_context m_context;
+ cl_device_id m_device;
+ cl_command_queue m_queue;
+ cl_kernel m_flipFloatKernel;
+ cl_kernel m_scatterKernel;
+ cl_kernel m_copyAabbsKernel;
+ cl_kernel m_sapKernel;
+ cl_kernel m_sap2Kernel;
+ cl_kernel m_prepareSumVarianceKernel;
class b3RadixSort32CL* m_sorter;
///test for 3d SAP
- b3AlignedObjectArray<b3SortData> m_sortedAxisCPU[3][2];
- b3AlignedObjectArray<b3UnsignedInt2> m_objectMinMaxIndexCPU[3][2];
- b3OpenCLArray<b3UnsignedInt2> m_objectMinMaxIndexGPUaxis0;
- b3OpenCLArray<b3UnsignedInt2> m_objectMinMaxIndexGPUaxis1;
- b3OpenCLArray<b3UnsignedInt2> m_objectMinMaxIndexGPUaxis2;
- b3OpenCLArray<b3UnsignedInt2> m_objectMinMaxIndexGPUaxis0prev;
- b3OpenCLArray<b3UnsignedInt2> m_objectMinMaxIndexGPUaxis1prev;
- b3OpenCLArray<b3UnsignedInt2> m_objectMinMaxIndexGPUaxis2prev;
-
- b3OpenCLArray<b3SortData> m_sortedAxisGPU0;
- b3OpenCLArray<b3SortData> m_sortedAxisGPU1;
- b3OpenCLArray<b3SortData> m_sortedAxisGPU2;
- b3OpenCLArray<b3SortData> m_sortedAxisGPU0prev;
- b3OpenCLArray<b3SortData> m_sortedAxisGPU1prev;
- b3OpenCLArray<b3SortData> m_sortedAxisGPU2prev;
-
-
- b3OpenCLArray<b3Int4> m_addedHostPairsGPU;
- b3OpenCLArray<b3Int4> m_removedHostPairsGPU;
- b3OpenCLArray<int> m_addedCountGPU;
- b3OpenCLArray<int> m_removedCountGPU;
-
- int m_currentBuffer;
+ b3AlignedObjectArray<b3SortData> m_sortedAxisCPU[3][2];
+ b3AlignedObjectArray<b3UnsignedInt2> m_objectMinMaxIndexCPU[3][2];
+ b3OpenCLArray<b3UnsignedInt2> m_objectMinMaxIndexGPUaxis0;
+ b3OpenCLArray<b3UnsignedInt2> m_objectMinMaxIndexGPUaxis1;
+ b3OpenCLArray<b3UnsignedInt2> m_objectMinMaxIndexGPUaxis2;
+ b3OpenCLArray<b3UnsignedInt2> m_objectMinMaxIndexGPUaxis0prev;
+ b3OpenCLArray<b3UnsignedInt2> m_objectMinMaxIndexGPUaxis1prev;
+ b3OpenCLArray<b3UnsignedInt2> m_objectMinMaxIndexGPUaxis2prev;
+
+ b3OpenCLArray<b3SortData> m_sortedAxisGPU0;
+ b3OpenCLArray<b3SortData> m_sortedAxisGPU1;
+ b3OpenCLArray<b3SortData> m_sortedAxisGPU2;
+ b3OpenCLArray<b3SortData> m_sortedAxisGPU0prev;
+ b3OpenCLArray<b3SortData> m_sortedAxisGPU1prev;
+ b3OpenCLArray<b3SortData> m_sortedAxisGPU2prev;
+
+ b3OpenCLArray<b3Int4> m_addedHostPairsGPU;
+ b3OpenCLArray<b3Int4> m_removedHostPairsGPU;
+ b3OpenCLArray<int> m_addedCountGPU;
+ b3OpenCLArray<int> m_removedCountGPU;
+
+ int m_currentBuffer;
public:
-
b3OpenCLArray<int> m_pairCount;
+ b3OpenCLArray<b3SapAabb> m_allAabbsGPU;
+ b3AlignedObjectArray<b3SapAabb> m_allAabbsCPU;
- b3OpenCLArray<b3SapAabb> m_allAabbsGPU;
- b3AlignedObjectArray<b3SapAabb> m_allAabbsCPU;
-
- virtual b3OpenCLArray<b3SapAabb>& getAllAabbsGPU()
+ virtual b3OpenCLArray<b3SapAabb>& getAllAabbsGPU()
{
return m_allAabbsGPU;
}
- virtual b3AlignedObjectArray<b3SapAabb>& getAllAabbsCPU()
+ virtual b3AlignedObjectArray<b3SapAabb>& getAllAabbsCPU()
{
return m_allAabbsCPU;
}
- b3OpenCLArray<b3Vector3> m_sum;
- b3OpenCLArray<b3Vector3> m_sum2;
- b3OpenCLArray<b3Vector3> m_dst;
+ b3OpenCLArray<b3Vector3> m_sum;
+ b3OpenCLArray<b3Vector3> m_sum2;
+ b3OpenCLArray<b3Vector3> m_dst;
- b3OpenCLArray<int> m_smallAabbsMappingGPU;
+ b3OpenCLArray<int> m_smallAabbsMappingGPU;
b3AlignedObjectArray<int> m_smallAabbsMappingCPU;
- b3OpenCLArray<int> m_largeAabbsMappingGPU;
+ b3OpenCLArray<int> m_largeAabbsMappingGPU;
b3AlignedObjectArray<int> m_largeAabbsMappingCPU;
-
- b3OpenCLArray<b3Int4> m_overlappingPairs;
+ b3OpenCLArray<b3Int4> m_overlappingPairs;
//temporary gpu work memory
- b3OpenCLArray<b3SortData> m_gpuSmallSortData;
- b3OpenCLArray<b3SapAabb> m_gpuSmallSortedAabbs;
+ b3OpenCLArray<b3SortData> m_gpuSmallSortData;
+ b3OpenCLArray<b3SapAabb> m_gpuSmallSortedAabbs;
- class b3PrefixScanFloat4CL* m_prefixScanFloat4;
+ class b3PrefixScanFloat4CL* m_prefixScanFloat4;
enum b3GpuSapKernelType
{
- B3_GPU_SAP_KERNEL_BRUTE_FORCE_CPU=1,
+ B3_GPU_SAP_KERNEL_BRUTE_FORCE_CPU = 1,
B3_GPU_SAP_KERNEL_BRUTE_FORCE_GPU,
B3_GPU_SAP_KERNEL_ORIGINAL,
B3_GPU_SAP_KERNEL_BARRIER,
B3_GPU_SAP_KERNEL_LOCAL_SHARED_MEMORY
};
- b3GpuSapBroadphase(cl_context ctx,cl_device_id device, cl_command_queue q , b3GpuSapKernelType kernelType=B3_GPU_SAP_KERNEL_LOCAL_SHARED_MEMORY);
+ b3GpuSapBroadphase(cl_context ctx, cl_device_id device, cl_command_queue q, b3GpuSapKernelType kernelType = B3_GPU_SAP_KERNEL_LOCAL_SHARED_MEMORY);
virtual ~b3GpuSapBroadphase();
-
- static b3GpuBroadphaseInterface* CreateFuncBruteForceCpu(cl_context ctx,cl_device_id device, cl_command_queue q)
+
+ static b3GpuBroadphaseInterface* CreateFuncBruteForceCpu(cl_context ctx, cl_device_id device, cl_command_queue q)
{
- return new b3GpuSapBroadphase(ctx,device,q,B3_GPU_SAP_KERNEL_BRUTE_FORCE_CPU);
+ return new b3GpuSapBroadphase(ctx, device, q, B3_GPU_SAP_KERNEL_BRUTE_FORCE_CPU);
}
- static b3GpuBroadphaseInterface* CreateFuncBruteForceGpu(cl_context ctx,cl_device_id device, cl_command_queue q)
+ static b3GpuBroadphaseInterface* CreateFuncBruteForceGpu(cl_context ctx, cl_device_id device, cl_command_queue q)
{
- return new b3GpuSapBroadphase(ctx,device,q,B3_GPU_SAP_KERNEL_BRUTE_FORCE_GPU);
+ return new b3GpuSapBroadphase(ctx, device, q, B3_GPU_SAP_KERNEL_BRUTE_FORCE_GPU);
}
- static b3GpuBroadphaseInterface* CreateFuncOriginal(cl_context ctx,cl_device_id device, cl_command_queue q)
+ static b3GpuBroadphaseInterface* CreateFuncOriginal(cl_context ctx, cl_device_id device, cl_command_queue q)
{
- return new b3GpuSapBroadphase(ctx,device,q,B3_GPU_SAP_KERNEL_ORIGINAL);
+ return new b3GpuSapBroadphase(ctx, device, q, B3_GPU_SAP_KERNEL_ORIGINAL);
}
- static b3GpuBroadphaseInterface* CreateFuncBarrier(cl_context ctx,cl_device_id device, cl_command_queue q)
+ static b3GpuBroadphaseInterface* CreateFuncBarrier(cl_context ctx, cl_device_id device, cl_command_queue q)
{
- return new b3GpuSapBroadphase(ctx,device,q,B3_GPU_SAP_KERNEL_BARRIER);
+ return new b3GpuSapBroadphase(ctx, device, q, B3_GPU_SAP_KERNEL_BARRIER);
}
- static b3GpuBroadphaseInterface* CreateFuncLocalMemory(cl_context ctx,cl_device_id device, cl_command_queue q)
+ static b3GpuBroadphaseInterface* CreateFuncLocalMemory(cl_context ctx, cl_device_id device, cl_command_queue q)
{
- return new b3GpuSapBroadphase(ctx,device,q,B3_GPU_SAP_KERNEL_LOCAL_SHARED_MEMORY);
+ return new b3GpuSapBroadphase(ctx, device, q, B3_GPU_SAP_KERNEL_LOCAL_SHARED_MEMORY);
}
-
- virtual void calculateOverlappingPairs(int maxPairs);
- virtual void calculateOverlappingPairsHost(int maxPairs);
-
- void reset();
+ virtual void calculateOverlappingPairs(int maxPairs);
+ virtual void calculateOverlappingPairsHost(int maxPairs);
+
+ void reset();
void init3dSap();
virtual void calculateOverlappingPairsHostIncremental3Sap();
- virtual void createProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr , int collisionFilterGroup, int collisionFilterMask);
- virtual void createLargeProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr , int collisionFilterGroup, int collisionFilterMask);
+ virtual void createProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask);
+ virtual void createLargeProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask);
//call writeAabbsToGpu after done making all changes (createProxy etc)
virtual void writeAabbsToGpu();
- virtual cl_mem getAabbBufferWS();
- virtual int getNumOverlap();
- virtual cl_mem getOverlappingPairBuffer();
-
+ virtual cl_mem getAabbBufferWS();
+ virtual int getNumOverlap();
+ virtual cl_mem getOverlappingPairBuffer();
+
virtual b3OpenCLArray<b3Int4>& getOverlappingPairsGPU();
virtual b3OpenCLArray<int>& getSmallAabbIndicesGPU();
virtual b3OpenCLArray<int>& getLargeAabbIndicesGPU();
};
-#endif //B3_GPU_SAP_BROADPHASE_H \ No newline at end of file
+#endif //B3_GPU_SAP_BROADPHASE_H \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3SapAabb.h b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3SapAabb.h
index ea6550fede..60570f2605 100644
--- a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3SapAabb.h
+++ b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3SapAabb.h
@@ -5,10 +5,9 @@
#include "Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h"
///just make sure that the b3Aabb is 16-byte aligned
-B3_ATTRIBUTE_ALIGNED16(struct) b3SapAabb : public b3Aabb
-{
+B3_ATTRIBUTE_ALIGNED16(struct)
+b3SapAabb : public b3Aabb{
-};
+ };
-
-#endif //B3_SAP_AABB_H
+#endif //B3_SAP_AABB_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/kernels/gridBroadphaseKernels.h b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/kernels/gridBroadphaseKernels.h
index dad42477c3..0185417786 100644
--- a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/kernels/gridBroadphaseKernels.h
+++ b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/kernels/gridBroadphaseKernels.h
@@ -1,199 +1,198 @@
//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* gridBroadphaseCL= \
-"int getPosHash(int4 gridPos, __global float4* pParams)\n"
-"{\n"
-" int4 gridDim = *((__global int4*)(pParams + 1));\n"
-" gridPos.x &= gridDim.x - 1;\n"
-" gridPos.y &= gridDim.y - 1;\n"
-" gridPos.z &= gridDim.z - 1;\n"
-" int hash = gridPos.z * gridDim.y * gridDim.x + gridPos.y * gridDim.x + gridPos.x;\n"
-" return hash;\n"
-"} \n"
-"int4 getGridPos(float4 worldPos, __global float4* pParams)\n"
-"{\n"
-" int4 gridPos;\n"
-" int4 gridDim = *((__global int4*)(pParams + 1));\n"
-" gridPos.x = (int)floor(worldPos.x * pParams[0].x) & (gridDim.x - 1);\n"
-" gridPos.y = (int)floor(worldPos.y * pParams[0].y) & (gridDim.y - 1);\n"
-" gridPos.z = (int)floor(worldPos.z * pParams[0].z) & (gridDim.z - 1);\n"
-" return gridPos;\n"
-"}\n"
-"// calculate grid hash value for each body using its AABB\n"
-"__kernel void kCalcHashAABB(int numObjects, __global float4* allpAABB, __global const int* smallAabbMapping, __global int2* pHash, __global float4* pParams )\n"
-"{\n"
-" int index = get_global_id(0);\n"
-" if(index >= numObjects)\n"
-" {\n"
-" return;\n"
-" }\n"
-" float4 bbMin = allpAABB[smallAabbMapping[index]*2];\n"
-" float4 bbMax = allpAABB[smallAabbMapping[index]*2 + 1];\n"
-" float4 pos;\n"
-" pos.x = (bbMin.x + bbMax.x) * 0.5f;\n"
-" pos.y = (bbMin.y + bbMax.y) * 0.5f;\n"
-" pos.z = (bbMin.z + bbMax.z) * 0.5f;\n"
-" pos.w = 0.f;\n"
-" // get address in grid\n"
-" int4 gridPos = getGridPos(pos, pParams);\n"
-" int gridHash = getPosHash(gridPos, pParams);\n"
-" // store grid hash and body index\n"
-" int2 hashVal;\n"
-" hashVal.x = gridHash;\n"
-" hashVal.y = index;\n"
-" pHash[index] = hashVal;\n"
-"}\n"
-"__kernel void kClearCellStart( int numCells, \n"
-" __global int* pCellStart )\n"
-"{\n"
-" int index = get_global_id(0);\n"
-" if(index >= numCells)\n"
-" {\n"
-" return;\n"
-" }\n"
-" pCellStart[index] = -1;\n"
-"}\n"
-"__kernel void kFindCellStart(int numObjects, __global int2* pHash, __global int* cellStart )\n"
-"{\n"
-" __local int sharedHash[513];\n"
-" int index = get_global_id(0);\n"
-" int2 sortedData;\n"
-" if(index < numObjects)\n"
-" {\n"
-" sortedData = pHash[index];\n"
-" // Load hash data into shared memory so that we can look \n"
-" // at neighboring body's hash value without loading\n"
-" // two hash values per thread\n"
-" sharedHash[get_local_id(0) + 1] = sortedData.x;\n"
-" if((index > 0) && (get_local_id(0) == 0))\n"
-" {\n"
-" // first thread in block must load neighbor body hash\n"
-" sharedHash[0] = pHash[index-1].x;\n"
-" }\n"
-" }\n"
-" barrier(CLK_LOCAL_MEM_FENCE);\n"
-" if(index < numObjects)\n"
-" {\n"
-" if((index == 0) || (sortedData.x != sharedHash[get_local_id(0)]))\n"
-" {\n"
-" cellStart[sortedData.x] = index;\n"
-" }\n"
-" }\n"
-"}\n"
-"int testAABBOverlap(float4 min0, float4 max0, float4 min1, float4 max1)\n"
-"{\n"
-" return (min0.x <= max1.x)&& (min1.x <= max0.x) && \n"
-" (min0.y <= max1.y)&& (min1.y <= max0.y) && \n"
-" (min0.z <= max1.z)&& (min1.z <= max0.z); \n"
-"}\n"
-"//search for AABB 'index' against other AABBs' in this cell\n"
-"void findPairsInCell( int numObjects,\n"
-" int4 gridPos,\n"
-" int index,\n"
-" __global int2* pHash,\n"
-" __global int* pCellStart,\n"
-" __global float4* allpAABB, \n"
-" __global const int* smallAabbMapping,\n"
-" __global float4* pParams,\n"
-" volatile __global int* pairCount,\n"
-" __global int4* pPairBuff2,\n"
-" int maxPairs\n"
-" )\n"
-"{\n"
-" int4 pGridDim = *((__global int4*)(pParams + 1));\n"
-" int maxBodiesPerCell = pGridDim.w;\n"
-" int gridHash = getPosHash(gridPos, pParams);\n"
-" // get start of bucket for this cell\n"
-" int bucketStart = pCellStart[gridHash];\n"
-" if (bucketStart == -1)\n"
-" {\n"
-" return; // cell empty\n"
-" }\n"
-" // iterate over bodies in this cell\n"
-" int2 sortedData = pHash[index];\n"
-" int unsorted_indx = sortedData.y;\n"
-" float4 min0 = allpAABB[smallAabbMapping[unsorted_indx]*2 + 0]; \n"
-" float4 max0 = allpAABB[smallAabbMapping[unsorted_indx]*2 + 1];\n"
-" int handleIndex = as_int(min0.w);\n"
-" \n"
-" int bucketEnd = bucketStart + maxBodiesPerCell;\n"
-" bucketEnd = (bucketEnd > numObjects) ? numObjects : bucketEnd;\n"
-" for(int index2 = bucketStart; index2 < bucketEnd; index2++) \n"
-" {\n"
-" int2 cellData = pHash[index2];\n"
-" if (cellData.x != gridHash)\n"
-" {\n"
-" break; // no longer in same bucket\n"
-" }\n"
-" int unsorted_indx2 = cellData.y;\n"
-" //if (unsorted_indx2 < unsorted_indx) // check not colliding with self\n"
-" if (unsorted_indx2 != unsorted_indx) // check not colliding with self\n"
-" { \n"
-" float4 min1 = allpAABB[smallAabbMapping[unsorted_indx2]*2 + 0];\n"
-" float4 max1 = allpAABB[smallAabbMapping[unsorted_indx2]*2 + 1];\n"
-" if(testAABBOverlap(min0, max0, min1, max1))\n"
-" {\n"
-" if (pairCount)\n"
-" {\n"
-" int handleIndex2 = as_int(min1.w);\n"
-" if (handleIndex<handleIndex2)\n"
-" {\n"
-" int curPair = atomic_add(pairCount,1);\n"
-" if (curPair<maxPairs)\n"
-" {\n"
-" int4 newpair;\n"
-" newpair.x = handleIndex;\n"
-" newpair.y = handleIndex2;\n"
-" newpair.z = -1;\n"
-" newpair.w = -1;\n"
-" pPairBuff2[curPair] = newpair;\n"
-" }\n"
-" }\n"
-" \n"
-" }\n"
-" }\n"
-" }\n"
-" }\n"
-"}\n"
-"__kernel void kFindOverlappingPairs( int numObjects,\n"
-" __global float4* allpAABB, \n"
-" __global const int* smallAabbMapping,\n"
-" __global int2* pHash, \n"
-" __global int* pCellStart, \n"
-" __global float4* pParams ,\n"
-" volatile __global int* pairCount,\n"
-" __global int4* pPairBuff2,\n"
-" int maxPairs\n"
-" )\n"
-"{\n"
-" int index = get_global_id(0);\n"
-" if(index >= numObjects)\n"
-" {\n"
-" return;\n"
-" }\n"
-" int2 sortedData = pHash[index];\n"
-" int unsorted_indx = sortedData.y;\n"
-" float4 bbMin = allpAABB[smallAabbMapping[unsorted_indx]*2 + 0];\n"
-" float4 bbMax = allpAABB[smallAabbMapping[unsorted_indx]*2 + 1];\n"
-" float4 pos;\n"
-" pos.x = (bbMin.x + bbMax.x) * 0.5f;\n"
-" pos.y = (bbMin.y + bbMax.y) * 0.5f;\n"
-" pos.z = (bbMin.z + bbMax.z) * 0.5f;\n"
-" // get address in grid\n"
-" int4 gridPosA = getGridPos(pos, pParams);\n"
-" int4 gridPosB; \n"
-" // examine only neighbouring cells\n"
-" for(int z=-1; z<=1; z++) \n"
-" {\n"
-" gridPosB.z = gridPosA.z + z;\n"
-" for(int y=-1; y<=1; y++) \n"
-" {\n"
-" gridPosB.y = gridPosA.y + y;\n"
-" for(int x=-1; x<=1; x++) \n"
-" {\n"
-" gridPosB.x = gridPosA.x + x;\n"
-" findPairsInCell(numObjects, gridPosB, index, pHash, pCellStart, allpAABB,smallAabbMapping, pParams, pairCount,pPairBuff2, maxPairs);\n"
-" }\n"
-" }\n"
-" }\n"
-"}\n"
-;
+static const char* gridBroadphaseCL =
+ "int getPosHash(int4 gridPos, __global float4* pParams)\n"
+ "{\n"
+ " int4 gridDim = *((__global int4*)(pParams + 1));\n"
+ " gridPos.x &= gridDim.x - 1;\n"
+ " gridPos.y &= gridDim.y - 1;\n"
+ " gridPos.z &= gridDim.z - 1;\n"
+ " int hash = gridPos.z * gridDim.y * gridDim.x + gridPos.y * gridDim.x + gridPos.x;\n"
+ " return hash;\n"
+ "} \n"
+ "int4 getGridPos(float4 worldPos, __global float4* pParams)\n"
+ "{\n"
+ " int4 gridPos;\n"
+ " int4 gridDim = *((__global int4*)(pParams + 1));\n"
+ " gridPos.x = (int)floor(worldPos.x * pParams[0].x) & (gridDim.x - 1);\n"
+ " gridPos.y = (int)floor(worldPos.y * pParams[0].y) & (gridDim.y - 1);\n"
+ " gridPos.z = (int)floor(worldPos.z * pParams[0].z) & (gridDim.z - 1);\n"
+ " return gridPos;\n"
+ "}\n"
+ "// calculate grid hash value for each body using its AABB\n"
+ "__kernel void kCalcHashAABB(int numObjects, __global float4* allpAABB, __global const int* smallAabbMapping, __global int2* pHash, __global float4* pParams )\n"
+ "{\n"
+ " int index = get_global_id(0);\n"
+ " if(index >= numObjects)\n"
+ " {\n"
+ " return;\n"
+ " }\n"
+ " float4 bbMin = allpAABB[smallAabbMapping[index]*2];\n"
+ " float4 bbMax = allpAABB[smallAabbMapping[index]*2 + 1];\n"
+ " float4 pos;\n"
+ " pos.x = (bbMin.x + bbMax.x) * 0.5f;\n"
+ " pos.y = (bbMin.y + bbMax.y) * 0.5f;\n"
+ " pos.z = (bbMin.z + bbMax.z) * 0.5f;\n"
+ " pos.w = 0.f;\n"
+ " // get address in grid\n"
+ " int4 gridPos = getGridPos(pos, pParams);\n"
+ " int gridHash = getPosHash(gridPos, pParams);\n"
+ " // store grid hash and body index\n"
+ " int2 hashVal;\n"
+ " hashVal.x = gridHash;\n"
+ " hashVal.y = index;\n"
+ " pHash[index] = hashVal;\n"
+ "}\n"
+ "__kernel void kClearCellStart( int numCells, \n"
+ " __global int* pCellStart )\n"
+ "{\n"
+ " int index = get_global_id(0);\n"
+ " if(index >= numCells)\n"
+ " {\n"
+ " return;\n"
+ " }\n"
+ " pCellStart[index] = -1;\n"
+ "}\n"
+ "__kernel void kFindCellStart(int numObjects, __global int2* pHash, __global int* cellStart )\n"
+ "{\n"
+ " __local int sharedHash[513];\n"
+ " int index = get_global_id(0);\n"
+ " int2 sortedData;\n"
+ " if(index < numObjects)\n"
+ " {\n"
+ " sortedData = pHash[index];\n"
+ " // Load hash data into shared memory so that we can look \n"
+ " // at neighboring body's hash value without loading\n"
+ " // two hash values per thread\n"
+ " sharedHash[get_local_id(0) + 1] = sortedData.x;\n"
+ " if((index > 0) && (get_local_id(0) == 0))\n"
+ " {\n"
+ " // first thread in block must load neighbor body hash\n"
+ " sharedHash[0] = pHash[index-1].x;\n"
+ " }\n"
+ " }\n"
+ " barrier(CLK_LOCAL_MEM_FENCE);\n"
+ " if(index < numObjects)\n"
+ " {\n"
+ " if((index == 0) || (sortedData.x != sharedHash[get_local_id(0)]))\n"
+ " {\n"
+ " cellStart[sortedData.x] = index;\n"
+ " }\n"
+ " }\n"
+ "}\n"
+ "int testAABBOverlap(float4 min0, float4 max0, float4 min1, float4 max1)\n"
+ "{\n"
+ " return (min0.x <= max1.x)&& (min1.x <= max0.x) && \n"
+ " (min0.y <= max1.y)&& (min1.y <= max0.y) && \n"
+ " (min0.z <= max1.z)&& (min1.z <= max0.z); \n"
+ "}\n"
+ "//search for AABB 'index' against other AABBs' in this cell\n"
+ "void findPairsInCell( int numObjects,\n"
+ " int4 gridPos,\n"
+ " int index,\n"
+ " __global int2* pHash,\n"
+ " __global int* pCellStart,\n"
+ " __global float4* allpAABB, \n"
+ " __global const int* smallAabbMapping,\n"
+ " __global float4* pParams,\n"
+ " volatile __global int* pairCount,\n"
+ " __global int4* pPairBuff2,\n"
+ " int maxPairs\n"
+ " )\n"
+ "{\n"
+ " int4 pGridDim = *((__global int4*)(pParams + 1));\n"
+ " int maxBodiesPerCell = pGridDim.w;\n"
+ " int gridHash = getPosHash(gridPos, pParams);\n"
+ " // get start of bucket for this cell\n"
+ " int bucketStart = pCellStart[gridHash];\n"
+ " if (bucketStart == -1)\n"
+ " {\n"
+ " return; // cell empty\n"
+ " }\n"
+ " // iterate over bodies in this cell\n"
+ " int2 sortedData = pHash[index];\n"
+ " int unsorted_indx = sortedData.y;\n"
+ " float4 min0 = allpAABB[smallAabbMapping[unsorted_indx]*2 + 0]; \n"
+ " float4 max0 = allpAABB[smallAabbMapping[unsorted_indx]*2 + 1];\n"
+ " int handleIndex = as_int(min0.w);\n"
+ " \n"
+ " int bucketEnd = bucketStart + maxBodiesPerCell;\n"
+ " bucketEnd = (bucketEnd > numObjects) ? numObjects : bucketEnd;\n"
+ " for(int index2 = bucketStart; index2 < bucketEnd; index2++) \n"
+ " {\n"
+ " int2 cellData = pHash[index2];\n"
+ " if (cellData.x != gridHash)\n"
+ " {\n"
+ " break; // no longer in same bucket\n"
+ " }\n"
+ " int unsorted_indx2 = cellData.y;\n"
+ " //if (unsorted_indx2 < unsorted_indx) // check not colliding with self\n"
+ " if (unsorted_indx2 != unsorted_indx) // check not colliding with self\n"
+ " { \n"
+ " float4 min1 = allpAABB[smallAabbMapping[unsorted_indx2]*2 + 0];\n"
+ " float4 max1 = allpAABB[smallAabbMapping[unsorted_indx2]*2 + 1];\n"
+ " if(testAABBOverlap(min0, max0, min1, max1))\n"
+ " {\n"
+ " if (pairCount)\n"
+ " {\n"
+ " int handleIndex2 = as_int(min1.w);\n"
+ " if (handleIndex<handleIndex2)\n"
+ " {\n"
+ " int curPair = atomic_add(pairCount,1);\n"
+ " if (curPair<maxPairs)\n"
+ " {\n"
+ " int4 newpair;\n"
+ " newpair.x = handleIndex;\n"
+ " newpair.y = handleIndex2;\n"
+ " newpair.z = -1;\n"
+ " newpair.w = -1;\n"
+ " pPairBuff2[curPair] = newpair;\n"
+ " }\n"
+ " }\n"
+ " \n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ "}\n"
+ "__kernel void kFindOverlappingPairs( int numObjects,\n"
+ " __global float4* allpAABB, \n"
+ " __global const int* smallAabbMapping,\n"
+ " __global int2* pHash, \n"
+ " __global int* pCellStart, \n"
+ " __global float4* pParams ,\n"
+ " volatile __global int* pairCount,\n"
+ " __global int4* pPairBuff2,\n"
+ " int maxPairs\n"
+ " )\n"
+ "{\n"
+ " int index = get_global_id(0);\n"
+ " if(index >= numObjects)\n"
+ " {\n"
+ " return;\n"
+ " }\n"
+ " int2 sortedData = pHash[index];\n"
+ " int unsorted_indx = sortedData.y;\n"
+ " float4 bbMin = allpAABB[smallAabbMapping[unsorted_indx]*2 + 0];\n"
+ " float4 bbMax = allpAABB[smallAabbMapping[unsorted_indx]*2 + 1];\n"
+ " float4 pos;\n"
+ " pos.x = (bbMin.x + bbMax.x) * 0.5f;\n"
+ " pos.y = (bbMin.y + bbMax.y) * 0.5f;\n"
+ " pos.z = (bbMin.z + bbMax.z) * 0.5f;\n"
+ " // get address in grid\n"
+ " int4 gridPosA = getGridPos(pos, pParams);\n"
+ " int4 gridPosB; \n"
+ " // examine only neighbouring cells\n"
+ " for(int z=-1; z<=1; z++) \n"
+ " {\n"
+ " gridPosB.z = gridPosA.z + z;\n"
+ " for(int y=-1; y<=1; y++) \n"
+ " {\n"
+ " gridPosB.y = gridPosA.y + y;\n"
+ " for(int x=-1; x<=1; x++) \n"
+ " {\n"
+ " gridPosB.x = gridPosA.x + x;\n"
+ " findPairsInCell(numObjects, gridPosB, index, pHash, pCellStart, allpAABB,smallAabbMapping, pParams, pairCount,pPairBuff2, maxPairs);\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/kernels/parallelLinearBvhKernels.h b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/kernels/parallelLinearBvhKernels.h
index 5eb8f45b16..c02877dde9 100644
--- a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/kernels/parallelLinearBvhKernels.h
+++ b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/kernels/parallelLinearBvhKernels.h
@@ -1,729 +1,728 @@
//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* parallelLinearBvhCL= \
-"/*\n"
-"This software is provided 'as-is', without any express or implied warranty.\n"
-"In no event will the authors be held liable for any damages arising from the use of this software.\n"
-"Permission is granted to anyone to use this software for any purpose,\n"
-"including commercial applications, and to alter it and redistribute it freely,\n"
-"subject to the following restrictions:\n"
-"1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
-"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
-"3. This notice may not be removed or altered from any source distribution.\n"
-"*/\n"
-"//Initial Author Jackson Lee, 2014\n"
-"typedef float b3Scalar;\n"
-"typedef float4 b3Vector3;\n"
-"#define b3Max max\n"
-"#define b3Min min\n"
-"#define b3Sqrt sqrt\n"
-"typedef struct\n"
-"{\n"
-" unsigned int m_key;\n"
-" unsigned int m_value;\n"
-"} SortDataCL;\n"
-"typedef struct \n"
-"{\n"
-" union\n"
-" {\n"
-" float4 m_min;\n"
-" float m_minElems[4];\n"
-" int m_minIndices[4];\n"
-" };\n"
-" union\n"
-" {\n"
-" float4 m_max;\n"
-" float m_maxElems[4];\n"
-" int m_maxIndices[4];\n"
-" };\n"
-"} b3AabbCL;\n"
-"unsigned int interleaveBits(unsigned int x)\n"
-"{\n"
-" //........ ........ ......12 3456789A //x\n"
-" //....1..2 ..3..4.. 5..6..7. .8..9..A //x after interleaving bits\n"
-" \n"
-" //......12 3456789A ......12 3456789A //x ^ (x << 16)\n"
-" //11111111 ........ ........ 11111111 //0x FF 00 00 FF\n"
-" //......12 ........ ........ 3456789A //x = (x ^ (x << 16)) & 0xFF0000FF;\n"
-" \n"
-" //......12 ........ 3456789A 3456789A //x ^ (x << 8)\n"
-" //......11 ........ 1111.... ....1111 //0x 03 00 F0 0F\n"
-" //......12 ........ 3456.... ....789A //x = (x ^ (x << 8)) & 0x0300F00F;\n"
-" \n"
-" //..12..12 ....3456 3456.... 789A789A //x ^ (x << 4)\n"
-" //......11 ....11.. ..11.... 11....11 //0x 03 0C 30 C3\n"
-" //......12 ....34.. ..56.... 78....9A //x = (x ^ (x << 4)) & 0x030C30C3;\n"
-" \n"
-" //....1212 ..3434.. 5656..78 78..9A9A //x ^ (x << 2)\n"
-" //....1..1 ..1..1.. 1..1..1. .1..1..1 //0x 09 24 92 49\n"
-" //....1..2 ..3..4.. 5..6..7. .8..9..A //x = (x ^ (x << 2)) & 0x09249249;\n"
-" \n"
-" //........ ........ ......11 11111111 //0x000003FF\n"
-" x &= 0x000003FF; //Clear all bits above bit 10\n"
-" \n"
-" x = (x ^ (x << 16)) & 0xFF0000FF;\n"
-" x = (x ^ (x << 8)) & 0x0300F00F;\n"
-" x = (x ^ (x << 4)) & 0x030C30C3;\n"
-" x = (x ^ (x << 2)) & 0x09249249;\n"
-" \n"
-" return x;\n"
-"}\n"
-"unsigned int getMortonCode(unsigned int x, unsigned int y, unsigned int z)\n"
-"{\n"
-" return interleaveBits(x) << 0 | interleaveBits(y) << 1 | interleaveBits(z) << 2;\n"
-"}\n"
-"__kernel void separateAabbs(__global b3AabbCL* unseparatedAabbs, __global int* aabbIndices, __global b3AabbCL* out_aabbs, int numAabbsToSeparate)\n"
-"{\n"
-" int separatedAabbIndex = get_global_id(0);\n"
-" if(separatedAabbIndex >= numAabbsToSeparate) return;\n"
-" int unseparatedAabbIndex = aabbIndices[separatedAabbIndex];\n"
-" out_aabbs[separatedAabbIndex] = unseparatedAabbs[unseparatedAabbIndex];\n"
-"}\n"
-"//Should replace with an optimized parallel reduction\n"
-"__kernel void findAllNodesMergedAabb(__global b3AabbCL* out_mergedAabb, int numAabbsNeedingMerge)\n"
-"{\n"
-" //Each time this kernel is added to the command queue, \n"
-" //the number of AABBs needing to be merged is halved\n"
-" //\n"
-" //Example with 159 AABBs:\n"
-" // numRemainingAabbs == 159 / 2 + 159 % 2 == 80\n"
-" // numMergedAabbs == 159 - 80 == 79\n"
-" //So, indices [0, 78] are merged with [0 + 80, 78 + 80]\n"
-" \n"
-" int numRemainingAabbs = numAabbsNeedingMerge / 2 + numAabbsNeedingMerge % 2;\n"
-" int numMergedAabbs = numAabbsNeedingMerge - numRemainingAabbs;\n"
-" \n"
-" int aabbIndex = get_global_id(0);\n"
-" if(aabbIndex >= numMergedAabbs) return;\n"
-" \n"
-" int otherAabbIndex = aabbIndex + numRemainingAabbs;\n"
-" \n"
-" b3AabbCL aabb = out_mergedAabb[aabbIndex];\n"
-" b3AabbCL otherAabb = out_mergedAabb[otherAabbIndex];\n"
-" \n"
-" b3AabbCL mergedAabb;\n"
-" mergedAabb.m_min = b3Min(aabb.m_min, otherAabb.m_min);\n"
-" mergedAabb.m_max = b3Max(aabb.m_max, otherAabb.m_max);\n"
-" out_mergedAabb[aabbIndex] = mergedAabb;\n"
-"}\n"
-"__kernel void assignMortonCodesAndAabbIndicies(__global b3AabbCL* worldSpaceAabbs, __global b3AabbCL* mergedAabbOfAllNodes, \n"
-" __global SortDataCL* out_mortonCodesAndAabbIndices, int numAabbs)\n"
-"{\n"
-" int leafNodeIndex = get_global_id(0); //Leaf node index == AABB index\n"
-" if(leafNodeIndex >= numAabbs) return;\n"
-" \n"
-" b3AabbCL mergedAabb = mergedAabbOfAllNodes[0];\n"
-" b3Vector3 gridCenter = (mergedAabb.m_min + mergedAabb.m_max) * 0.5f;\n"
-" b3Vector3 gridCellSize = (mergedAabb.m_max - mergedAabb.m_min) / (float)1024;\n"
-" \n"
-" b3AabbCL aabb = worldSpaceAabbs[leafNodeIndex];\n"
-" b3Vector3 aabbCenter = (aabb.m_min + aabb.m_max) * 0.5f;\n"
-" b3Vector3 aabbCenterRelativeToGrid = aabbCenter - gridCenter;\n"
-" \n"
-" //Quantize into integer coordinates\n"
-" //floor() is needed to prevent the center cell, at (0,0,0) from being twice the size\n"
-" b3Vector3 gridPosition = aabbCenterRelativeToGrid / gridCellSize;\n"
-" \n"
-" int4 discretePosition;\n"
-" discretePosition.x = (int)( (gridPosition.x >= 0.0f) ? gridPosition.x : floor(gridPosition.x) );\n"
-" discretePosition.y = (int)( (gridPosition.y >= 0.0f) ? gridPosition.y : floor(gridPosition.y) );\n"
-" discretePosition.z = (int)( (gridPosition.z >= 0.0f) ? gridPosition.z : floor(gridPosition.z) );\n"
-" \n"
-" //Clamp coordinates into [-512, 511], then convert range from [-512, 511] to [0, 1023]\n"
-" discretePosition = b3Max( -512, b3Min(discretePosition, 511) );\n"
-" discretePosition += 512;\n"
-" \n"
-" //Interleave bits(assign a morton code, also known as a z-curve)\n"
-" unsigned int mortonCode = getMortonCode(discretePosition.x, discretePosition.y, discretePosition.z);\n"
-" \n"
-" //\n"
-" SortDataCL mortonCodeIndexPair;\n"
-" mortonCodeIndexPair.m_key = mortonCode;\n"
-" mortonCodeIndexPair.m_value = leafNodeIndex;\n"
-" \n"
-" out_mortonCodesAndAabbIndices[leafNodeIndex] = mortonCodeIndexPair;\n"
-"}\n"
-"#define B3_PLVBH_TRAVERSE_MAX_STACK_SIZE 128\n"
-"//The most significant bit(0x80000000) of a int32 is used to distinguish between leaf and internal nodes.\n"
-"//If it is set, then the index is for an internal node; otherwise, it is a leaf node. \n"
-"//In both cases, the bit should be cleared to access the actual node index.\n"
-"int isLeafNode(int index) { return (index >> 31 == 0); }\n"
-"int getIndexWithInternalNodeMarkerRemoved(int index) { return index & (~0x80000000); }\n"
-"int getIndexWithInternalNodeMarkerSet(int isLeaf, int index) { return (isLeaf) ? index : (index | 0x80000000); }\n"
-"//From sap.cl\n"
-"#define NEW_PAIR_MARKER -1\n"
-"bool TestAabbAgainstAabb2(const b3AabbCL* aabb1, const b3AabbCL* aabb2)\n"
-"{\n"
-" bool overlap = true;\n"
-" overlap = (aabb1->m_min.x > aabb2->m_max.x || aabb1->m_max.x < aabb2->m_min.x) ? false : overlap;\n"
-" overlap = (aabb1->m_min.z > aabb2->m_max.z || aabb1->m_max.z < aabb2->m_min.z) ? false : overlap;\n"
-" overlap = (aabb1->m_min.y > aabb2->m_max.y || aabb1->m_max.y < aabb2->m_min.y) ? false : overlap;\n"
-" return overlap;\n"
-"}\n"
-"//From sap.cl\n"
-"__kernel void plbvhCalculateOverlappingPairs(__global b3AabbCL* rigidAabbs, \n"
-" __global int* rootNodeIndex, \n"
-" __global int2* internalNodeChildIndices, \n"
-" __global b3AabbCL* internalNodeAabbs,\n"
-" __global int2* internalNodeLeafIndexRanges,\n"
-" \n"
-" __global SortDataCL* mortonCodesAndAabbIndices,\n"
-" __global int* out_numPairs, __global int4* out_overlappingPairs, \n"
-" int maxPairs, int numQueryAabbs)\n"
-"{\n"
-" //Using get_group_id()/get_local_id() is Faster than get_global_id(0) since\n"
-" //mortonCodesAndAabbIndices[] contains rigid body indices sorted along the z-curve (more spatially coherent)\n"
-" int queryBvhNodeIndex = get_group_id(0) * get_local_size(0) + get_local_id(0);\n"
-" if(queryBvhNodeIndex >= numQueryAabbs) return;\n"
-" \n"
-" int queryRigidIndex = mortonCodesAndAabbIndices[queryBvhNodeIndex].m_value;\n"
-" b3AabbCL queryAabb = rigidAabbs[queryRigidIndex];\n"
-" \n"
-" int stack[B3_PLVBH_TRAVERSE_MAX_STACK_SIZE];\n"
-" \n"
-" int stackSize = 1;\n"
-" stack[0] = *rootNodeIndex;\n"
-" \n"
-" while(stackSize)\n"
-" {\n"
-" int internalOrLeafNodeIndex = stack[ stackSize - 1 ];\n"
-" --stackSize;\n"
-" \n"
-" int isLeaf = isLeafNode(internalOrLeafNodeIndex); //Internal node if false\n"
-" int bvhNodeIndex = getIndexWithInternalNodeMarkerRemoved(internalOrLeafNodeIndex);\n"
-" \n"
-" //Optimization - if the BVH is structured as a binary radix tree, then\n"
-" //each internal node corresponds to a contiguous range of leaf nodes(internalNodeLeafIndexRanges[]).\n"
-" //This can be used to avoid testing each AABB-AABB pair twice, including preventing each node from colliding with itself.\n"
-" {\n"
-" int highestLeafIndex = (isLeaf) ? bvhNodeIndex : internalNodeLeafIndexRanges[bvhNodeIndex].y;\n"
-" if(highestLeafIndex <= queryBvhNodeIndex) continue;\n"
-" }\n"
-" \n"
-" //bvhRigidIndex is not used if internal node\n"
-" int bvhRigidIndex = (isLeaf) ? mortonCodesAndAabbIndices[bvhNodeIndex].m_value : -1;\n"
-" \n"
-" b3AabbCL bvhNodeAabb = (isLeaf) ? rigidAabbs[bvhRigidIndex] : internalNodeAabbs[bvhNodeIndex];\n"
-" if( TestAabbAgainstAabb2(&queryAabb, &bvhNodeAabb) )\n"
-" {\n"
-" if(isLeaf)\n"
-" {\n"
-" int4 pair;\n"
-" pair.x = rigidAabbs[queryRigidIndex].m_minIndices[3];\n"
-" pair.y = rigidAabbs[bvhRigidIndex].m_minIndices[3];\n"
-" pair.z = NEW_PAIR_MARKER;\n"
-" pair.w = NEW_PAIR_MARKER;\n"
-" \n"
-" int pairIndex = atomic_inc(out_numPairs);\n"
-" if(pairIndex < maxPairs) out_overlappingPairs[pairIndex] = pair;\n"
-" }\n"
-" \n"
-" if(!isLeaf) //Internal node\n"
-" {\n"
-" if(stackSize + 2 > B3_PLVBH_TRAVERSE_MAX_STACK_SIZE)\n"
-" {\n"
-" //Error\n"
-" }\n"
-" else\n"
-" {\n"
-" stack[ stackSize++ ] = internalNodeChildIndices[bvhNodeIndex].x;\n"
-" stack[ stackSize++ ] = internalNodeChildIndices[bvhNodeIndex].y;\n"
-" }\n"
-" }\n"
-" }\n"
-" \n"
-" }\n"
-"}\n"
-"//From rayCastKernels.cl\n"
-"typedef struct\n"
-"{\n"
-" float4 m_from;\n"
-" float4 m_to;\n"
-"} b3RayInfo;\n"
-"//From rayCastKernels.cl\n"
-"b3Vector3 b3Vector3_normalize(b3Vector3 v)\n"
-"{\n"
-" b3Vector3 normal = (b3Vector3){v.x, v.y, v.z, 0.f};\n"
-" return normalize(normal); //OpenCL normalize == vector4 normalize\n"
-"}\n"
-"b3Scalar b3Vector3_length2(b3Vector3 v) { return v.x*v.x + v.y*v.y + v.z*v.z; }\n"
-"b3Scalar b3Vector3_dot(b3Vector3 a, b3Vector3 b) { return a.x*b.x + a.y*b.y + a.z*b.z; }\n"
-"int rayIntersectsAabb(b3Vector3 rayOrigin, b3Scalar rayLength, b3Vector3 rayNormalizedDirection, b3AabbCL aabb)\n"
-"{\n"
-" //AABB is considered as 3 pairs of 2 planes( {x_min, x_max}, {y_min, y_max}, {z_min, z_max} ).\n"
-" //t_min is the point of intersection with the closer plane, t_max is the point of intersection with the farther plane.\n"
-" //\n"
-" //if (rayNormalizedDirection.x < 0.0f), then max.x will be the near plane \n"
-" //and min.x will be the far plane; otherwise, it is reversed.\n"
-" //\n"
-" //In order for there to be a collision, the t_min and t_max of each pair must overlap.\n"
-" //This can be tested for by selecting the highest t_min and lowest t_max and comparing them.\n"
-" \n"
-" int4 isNegative = isless( rayNormalizedDirection, ((b3Vector3){0.0f, 0.0f, 0.0f, 0.0f}) ); //isless(x,y) returns (x < y)\n"
-" \n"
-" //When using vector types, the select() function checks the most signficant bit, \n"
-" //but isless() sets the least significant bit.\n"
-" isNegative <<= 31;\n"
-" //select(b, a, condition) == condition ? a : b\n"
-" //When using select() with vector types, (condition[i]) is true if its most significant bit is 1\n"
-" b3Vector3 t_min = ( select(aabb.m_min, aabb.m_max, isNegative) - rayOrigin ) / rayNormalizedDirection;\n"
-" b3Vector3 t_max = ( select(aabb.m_max, aabb.m_min, isNegative) - rayOrigin ) / rayNormalizedDirection;\n"
-" \n"
-" b3Scalar t_min_final = 0.0f;\n"
-" b3Scalar t_max_final = rayLength;\n"
-" \n"
-" //Must use fmin()/fmax(); if one of the parameters is NaN, then the parameter that is not NaN is returned. \n"
-" //Behavior of min()/max() with NaNs is undefined. (See OpenCL Specification 1.2 [6.12.2] and [6.12.4])\n"
-" //Since the innermost fmin()/fmax() is always not NaN, this should never return NaN.\n"
-" t_min_final = fmax( t_min.z, fmax(t_min.y, fmax(t_min.x, t_min_final)) );\n"
-" t_max_final = fmin( t_max.z, fmin(t_max.y, fmin(t_max.x, t_max_final)) );\n"
-" \n"
-" return (t_min_final <= t_max_final);\n"
-"}\n"
-"__kernel void plbvhRayTraverse(__global b3AabbCL* rigidAabbs,\n"
-" __global int* rootNodeIndex, \n"
-" __global int2* internalNodeChildIndices, \n"
-" __global b3AabbCL* internalNodeAabbs,\n"
-" __global int2* internalNodeLeafIndexRanges,\n"
-" __global SortDataCL* mortonCodesAndAabbIndices,\n"
-" \n"
-" __global b3RayInfo* rays,\n"
-" \n"
-" __global int* out_numRayRigidPairs, \n"
-" __global int2* out_rayRigidPairs,\n"
-" int maxRayRigidPairs, int numRays)\n"
-"{\n"
-" int rayIndex = get_global_id(0);\n"
-" if(rayIndex >= numRays) return;\n"
-" \n"
-" //\n"
-" b3Vector3 rayFrom = rays[rayIndex].m_from;\n"
-" b3Vector3 rayTo = rays[rayIndex].m_to;\n"
-" b3Vector3 rayNormalizedDirection = b3Vector3_normalize(rayTo - rayFrom);\n"
-" b3Scalar rayLength = b3Sqrt( b3Vector3_length2(rayTo - rayFrom) );\n"
-" \n"
-" //\n"
-" int stack[B3_PLVBH_TRAVERSE_MAX_STACK_SIZE];\n"
-" \n"
-" int stackSize = 1;\n"
-" stack[0] = *rootNodeIndex;\n"
-" \n"
-" while(stackSize)\n"
-" {\n"
-" int internalOrLeafNodeIndex = stack[ stackSize - 1 ];\n"
-" --stackSize;\n"
-" \n"
-" int isLeaf = isLeafNode(internalOrLeafNodeIndex); //Internal node if false\n"
-" int bvhNodeIndex = getIndexWithInternalNodeMarkerRemoved(internalOrLeafNodeIndex);\n"
-" \n"
-" //bvhRigidIndex is not used if internal node\n"
-" int bvhRigidIndex = (isLeaf) ? mortonCodesAndAabbIndices[bvhNodeIndex].m_value : -1;\n"
-" \n"
-" b3AabbCL bvhNodeAabb = (isLeaf) ? rigidAabbs[bvhRigidIndex] : internalNodeAabbs[bvhNodeIndex];\n"
-" if( rayIntersectsAabb(rayFrom, rayLength, rayNormalizedDirection, bvhNodeAabb) )\n"
-" {\n"
-" if(isLeaf)\n"
-" {\n"
-" int2 rayRigidPair;\n"
-" rayRigidPair.x = rayIndex;\n"
-" rayRigidPair.y = rigidAabbs[bvhRigidIndex].m_minIndices[3];\n"
-" \n"
-" int pairIndex = atomic_inc(out_numRayRigidPairs);\n"
-" if(pairIndex < maxRayRigidPairs) out_rayRigidPairs[pairIndex] = rayRigidPair;\n"
-" }\n"
-" \n"
-" if(!isLeaf) //Internal node\n"
-" {\n"
-" if(stackSize + 2 > B3_PLVBH_TRAVERSE_MAX_STACK_SIZE)\n"
-" {\n"
-" //Error\n"
-" }\n"
-" else\n"
-" {\n"
-" stack[ stackSize++ ] = internalNodeChildIndices[bvhNodeIndex].x;\n"
-" stack[ stackSize++ ] = internalNodeChildIndices[bvhNodeIndex].y;\n"
-" }\n"
-" }\n"
-" }\n"
-" }\n"
-"}\n"
-"__kernel void plbvhLargeAabbAabbTest(__global b3AabbCL* smallAabbs, __global b3AabbCL* largeAabbs, \n"
-" __global int* out_numPairs, __global int4* out_overlappingPairs, \n"
-" int maxPairs, int numLargeAabbRigids, int numSmallAabbRigids)\n"
-"{\n"
-" int smallAabbIndex = get_global_id(0);\n"
-" if(smallAabbIndex >= numSmallAabbRigids) return;\n"
-" \n"
-" b3AabbCL smallAabb = smallAabbs[smallAabbIndex];\n"
-" for(int i = 0; i < numLargeAabbRigids; ++i)\n"
-" {\n"
-" b3AabbCL largeAabb = largeAabbs[i];\n"
-" if( TestAabbAgainstAabb2(&smallAabb, &largeAabb) )\n"
-" {\n"
-" int4 pair;\n"
-" pair.x = largeAabb.m_minIndices[3];\n"
-" pair.y = smallAabb.m_minIndices[3];\n"
-" pair.z = NEW_PAIR_MARKER;\n"
-" pair.w = NEW_PAIR_MARKER;\n"
-" \n"
-" int pairIndex = atomic_inc(out_numPairs);\n"
-" if(pairIndex < maxPairs) out_overlappingPairs[pairIndex] = pair;\n"
-" }\n"
-" }\n"
-"}\n"
-"__kernel void plbvhLargeAabbRayTest(__global b3AabbCL* largeRigidAabbs, __global b3RayInfo* rays,\n"
-" __global int* out_numRayRigidPairs, __global int2* out_rayRigidPairs,\n"
-" int numLargeAabbRigids, int maxRayRigidPairs, int numRays)\n"
-"{\n"
-" int rayIndex = get_global_id(0);\n"
-" if(rayIndex >= numRays) return;\n"
-" \n"
-" b3Vector3 rayFrom = rays[rayIndex].m_from;\n"
-" b3Vector3 rayTo = rays[rayIndex].m_to;\n"
-" b3Vector3 rayNormalizedDirection = b3Vector3_normalize(rayTo - rayFrom);\n"
-" b3Scalar rayLength = b3Sqrt( b3Vector3_length2(rayTo - rayFrom) );\n"
-" \n"
-" for(int i = 0; i < numLargeAabbRigids; ++i)\n"
-" {\n"
-" b3AabbCL rigidAabb = largeRigidAabbs[i];\n"
-" if( rayIntersectsAabb(rayFrom, rayLength, rayNormalizedDirection, rigidAabb) )\n"
-" {\n"
-" int2 rayRigidPair;\n"
-" rayRigidPair.x = rayIndex;\n"
-" rayRigidPair.y = rigidAabb.m_minIndices[3];\n"
-" \n"
-" int pairIndex = atomic_inc(out_numRayRigidPairs);\n"
-" if(pairIndex < maxRayRigidPairs) out_rayRigidPairs[pairIndex] = rayRigidPair;\n"
-" }\n"
-" }\n"
-"}\n"
-"//Set so that it is always greater than the actual common prefixes, and never selected as a parent node.\n"
-"//If there are no duplicates, then the highest common prefix is 32 or 64, depending on the number of bits used for the z-curve.\n"
-"//Duplicate common prefixes increase the highest common prefix at most by the number of bits used to index the leaf node.\n"
-"//Since 32 bit ints are used to index leaf nodes, the max prefix is 64(32 + 32 bit z-curve) or 96(32 + 64 bit z-curve).\n"
-"#define B3_PLBVH_INVALID_COMMON_PREFIX 128\n"
-"#define B3_PLBVH_ROOT_NODE_MARKER -1\n"
-"#define b3Int64 long\n"
-"int computeCommonPrefixLength(b3Int64 i, b3Int64 j) { return (int)clz(i ^ j); }\n"
-"b3Int64 computeCommonPrefix(b3Int64 i, b3Int64 j) \n"
-"{\n"
-" //This function only needs to return (i & j) in order for the algorithm to work,\n"
-" //but it may help with debugging to mask out the lower bits.\n"
-" b3Int64 commonPrefixLength = (b3Int64)computeCommonPrefixLength(i, j);\n"
-" b3Int64 sharedBits = i & j;\n"
-" b3Int64 bitmask = ((b3Int64)(~0)) << (64 - commonPrefixLength); //Set all bits after the common prefix to 0\n"
-" \n"
-" return sharedBits & bitmask;\n"
-"}\n"
-"//Same as computeCommonPrefixLength(), but allows for prefixes with different lengths\n"
-"int getSharedPrefixLength(b3Int64 prefixA, int prefixLengthA, b3Int64 prefixB, int prefixLengthB)\n"
-"{\n"
-" return b3Min( computeCommonPrefixLength(prefixA, prefixB), b3Min(prefixLengthA, prefixLengthB) );\n"
-"}\n"
-"__kernel void computeAdjacentPairCommonPrefix(__global SortDataCL* mortonCodesAndAabbIndices,\n"
-" __global b3Int64* out_commonPrefixes,\n"
-" __global int* out_commonPrefixLengths,\n"
-" int numInternalNodes)\n"
-"{\n"
-" int internalNodeIndex = get_global_id(0);\n"
-" if (internalNodeIndex >= numInternalNodes) return;\n"
-" \n"
-" //Here, (internalNodeIndex + 1) is never out of bounds since it is a leaf node index,\n"
-" //and the number of internal nodes is always numLeafNodes - 1\n"
-" int leftLeafIndex = internalNodeIndex;\n"
-" int rightLeafIndex = internalNodeIndex + 1;\n"
-" \n"
-" int leftLeafMortonCode = mortonCodesAndAabbIndices[leftLeafIndex].m_key;\n"
-" int rightLeafMortonCode = mortonCodesAndAabbIndices[rightLeafIndex].m_key;\n"
-" \n"
-" //Binary radix tree construction algorithm does not work if there are duplicate morton codes.\n"
-" //Append the index of each leaf node to each morton code so that there are no duplicates.\n"
-" //The algorithm also requires that the morton codes are sorted in ascending order; this requirement\n"
-" //is also satisfied with this method, as (leftLeafIndex < rightLeafIndex) is always true.\n"
-" //\n"
-" //upsample(a, b) == ( ((b3Int64)a) << 32) | b\n"
-" b3Int64 nonduplicateLeftMortonCode = upsample(leftLeafMortonCode, leftLeafIndex);\n"
-" b3Int64 nonduplicateRightMortonCode = upsample(rightLeafMortonCode, rightLeafIndex);\n"
-" \n"
-" out_commonPrefixes[internalNodeIndex] = computeCommonPrefix(nonduplicateLeftMortonCode, nonduplicateRightMortonCode);\n"
-" out_commonPrefixLengths[internalNodeIndex] = computeCommonPrefixLength(nonduplicateLeftMortonCode, nonduplicateRightMortonCode);\n"
-"}\n"
-"__kernel void buildBinaryRadixTreeLeafNodes(__global int* commonPrefixLengths, __global int* out_leafNodeParentNodes,\n"
-" __global int2* out_childNodes, int numLeafNodes)\n"
-"{\n"
-" int leafNodeIndex = get_global_id(0);\n"
-" if (leafNodeIndex >= numLeafNodes) return;\n"
-" \n"
-" int numInternalNodes = numLeafNodes - 1;\n"
-" \n"
-" int leftSplitIndex = leafNodeIndex - 1;\n"
-" int rightSplitIndex = leafNodeIndex;\n"
-" \n"
-" int leftCommonPrefix = (leftSplitIndex >= 0) ? commonPrefixLengths[leftSplitIndex] : B3_PLBVH_INVALID_COMMON_PREFIX;\n"
-" int rightCommonPrefix = (rightSplitIndex < numInternalNodes) ? commonPrefixLengths[rightSplitIndex] : B3_PLBVH_INVALID_COMMON_PREFIX;\n"
-" \n"
-" //Parent node is the highest adjacent common prefix that is lower than the node's common prefix\n"
-" //Leaf nodes are considered as having the highest common prefix\n"
-" int isLeftHigherCommonPrefix = (leftCommonPrefix > rightCommonPrefix);\n"
-" \n"
-" //Handle cases for the edge nodes; the first and last node\n"
-" //For leaf nodes, leftCommonPrefix and rightCommonPrefix should never both be B3_PLBVH_INVALID_COMMON_PREFIX\n"
-" if(leftCommonPrefix == B3_PLBVH_INVALID_COMMON_PREFIX) isLeftHigherCommonPrefix = false;\n"
-" if(rightCommonPrefix == B3_PLBVH_INVALID_COMMON_PREFIX) isLeftHigherCommonPrefix = true;\n"
-" \n"
-" int parentNodeIndex = (isLeftHigherCommonPrefix) ? leftSplitIndex : rightSplitIndex;\n"
-" out_leafNodeParentNodes[leafNodeIndex] = parentNodeIndex;\n"
-" \n"
-" int isRightChild = (isLeftHigherCommonPrefix); //If the left node is the parent, then this node is its right child and vice versa\n"
-" \n"
-" //out_childNodesAsInt[0] == int2.x == left child\n"
-" //out_childNodesAsInt[1] == int2.y == right child\n"
-" int isLeaf = 1;\n"
-" __global int* out_childNodesAsInt = (__global int*)(&out_childNodes[parentNodeIndex]);\n"
-" out_childNodesAsInt[isRightChild] = getIndexWithInternalNodeMarkerSet(isLeaf, leafNodeIndex);\n"
-"}\n"
-"__kernel void buildBinaryRadixTreeInternalNodes(__global b3Int64* commonPrefixes, __global int* commonPrefixLengths,\n"
-" __global int2* out_childNodes,\n"
-" __global int* out_internalNodeParentNodes, __global int* out_rootNodeIndex,\n"
-" int numInternalNodes)\n"
-"{\n"
-" int internalNodeIndex = get_group_id(0) * get_local_size(0) + get_local_id(0);\n"
-" if(internalNodeIndex >= numInternalNodes) return;\n"
-" \n"
-" b3Int64 nodePrefix = commonPrefixes[internalNodeIndex];\n"
-" int nodePrefixLength = commonPrefixLengths[internalNodeIndex];\n"
-" \n"
-"//#define USE_LINEAR_SEARCH\n"
-"#ifdef USE_LINEAR_SEARCH\n"
-" int leftIndex = -1;\n"
-" int rightIndex = -1;\n"
-" \n"
-" //Find nearest element to left with a lower common prefix\n"
-" for(int i = internalNodeIndex - 1; i >= 0; --i)\n"
-" {\n"
-" int nodeLeftSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, commonPrefixes[i], commonPrefixLengths[i]);\n"
-" if(nodeLeftSharedPrefixLength < nodePrefixLength)\n"
-" {\n"
-" leftIndex = i;\n"
-" break;\n"
-" }\n"
-" }\n"
-" \n"
-" //Find nearest element to right with a lower common prefix\n"
-" for(int i = internalNodeIndex + 1; i < numInternalNodes; ++i)\n"
-" {\n"
-" int nodeRightSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, commonPrefixes[i], commonPrefixLengths[i]);\n"
-" if(nodeRightSharedPrefixLength < nodePrefixLength)\n"
-" {\n"
-" rightIndex = i;\n"
-" break;\n"
-" }\n"
-" }\n"
-" \n"
-"#else //Use binary search\n"
-" //Find nearest element to left with a lower common prefix\n"
-" int leftIndex = -1;\n"
-" {\n"
-" int lower = 0;\n"
-" int upper = internalNodeIndex - 1;\n"
-" \n"
-" while(lower <= upper)\n"
-" {\n"
-" int mid = (lower + upper) / 2;\n"
-" b3Int64 midPrefix = commonPrefixes[mid];\n"
-" int midPrefixLength = commonPrefixLengths[mid];\n"
-" \n"
-" int nodeMidSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, midPrefix, midPrefixLength);\n"
-" if(nodeMidSharedPrefixLength < nodePrefixLength) \n"
-" {\n"
-" int right = mid + 1;\n"
-" if(right < internalNodeIndex)\n"
-" {\n"
-" b3Int64 rightPrefix = commonPrefixes[right];\n"
-" int rightPrefixLength = commonPrefixLengths[right];\n"
-" \n"
-" int nodeRightSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, rightPrefix, rightPrefixLength);\n"
-" if(nodeRightSharedPrefixLength < nodePrefixLength) \n"
-" {\n"
-" lower = right;\n"
-" leftIndex = right;\n"
-" }\n"
-" else \n"
-" {\n"
-" leftIndex = mid;\n"
-" break;\n"
-" }\n"
-" }\n"
-" else \n"
-" {\n"
-" leftIndex = mid;\n"
-" break;\n"
-" }\n"
-" }\n"
-" else upper = mid - 1;\n"
-" }\n"
-" }\n"
-" \n"
-" //Find nearest element to right with a lower common prefix\n"
-" int rightIndex = -1;\n"
-" {\n"
-" int lower = internalNodeIndex + 1;\n"
-" int upper = numInternalNodes - 1;\n"
-" \n"
-" while(lower <= upper)\n"
-" {\n"
-" int mid = (lower + upper) / 2;\n"
-" b3Int64 midPrefix = commonPrefixes[mid];\n"
-" int midPrefixLength = commonPrefixLengths[mid];\n"
-" \n"
-" int nodeMidSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, midPrefix, midPrefixLength);\n"
-" if(nodeMidSharedPrefixLength < nodePrefixLength) \n"
-" {\n"
-" int left = mid - 1;\n"
-" if(left > internalNodeIndex)\n"
-" {\n"
-" b3Int64 leftPrefix = commonPrefixes[left];\n"
-" int leftPrefixLength = commonPrefixLengths[left];\n"
-" \n"
-" int nodeLeftSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, leftPrefix, leftPrefixLength);\n"
-" if(nodeLeftSharedPrefixLength < nodePrefixLength) \n"
-" {\n"
-" upper = left;\n"
-" rightIndex = left;\n"
-" }\n"
-" else \n"
-" {\n"
-" rightIndex = mid;\n"
-" break;\n"
-" }\n"
-" }\n"
-" else \n"
-" {\n"
-" rightIndex = mid;\n"
-" break;\n"
-" }\n"
-" }\n"
-" else lower = mid + 1;\n"
-" }\n"
-" }\n"
-"#endif\n"
-" \n"
-" //Select parent\n"
-" {\n"
-" int leftPrefixLength = (leftIndex != -1) ? commonPrefixLengths[leftIndex] : B3_PLBVH_INVALID_COMMON_PREFIX;\n"
-" int rightPrefixLength = (rightIndex != -1) ? commonPrefixLengths[rightIndex] : B3_PLBVH_INVALID_COMMON_PREFIX;\n"
-" \n"
-" int isLeftHigherPrefixLength = (leftPrefixLength > rightPrefixLength);\n"
-" \n"
-" if(leftPrefixLength == B3_PLBVH_INVALID_COMMON_PREFIX) isLeftHigherPrefixLength = false;\n"
-" else if(rightPrefixLength == B3_PLBVH_INVALID_COMMON_PREFIX) isLeftHigherPrefixLength = true;\n"
-" \n"
-" int parentNodeIndex = (isLeftHigherPrefixLength) ? leftIndex : rightIndex;\n"
-" \n"
-" int isRootNode = (leftIndex == -1 && rightIndex == -1);\n"
-" out_internalNodeParentNodes[internalNodeIndex] = (!isRootNode) ? parentNodeIndex : B3_PLBVH_ROOT_NODE_MARKER;\n"
-" \n"
-" int isLeaf = 0;\n"
-" if(!isRootNode)\n"
-" {\n"
-" int isRightChild = (isLeftHigherPrefixLength); //If the left node is the parent, then this node is its right child and vice versa\n"
-" \n"
-" //out_childNodesAsInt[0] == int2.x == left child\n"
-" //out_childNodesAsInt[1] == int2.y == right child\n"
-" __global int* out_childNodesAsInt = (__global int*)(&out_childNodes[parentNodeIndex]);\n"
-" out_childNodesAsInt[isRightChild] = getIndexWithInternalNodeMarkerSet(isLeaf, internalNodeIndex);\n"
-" }\n"
-" else *out_rootNodeIndex = getIndexWithInternalNodeMarkerSet(isLeaf, internalNodeIndex);\n"
-" }\n"
-"}\n"
-"__kernel void findDistanceFromRoot(__global int* rootNodeIndex, __global int* internalNodeParentNodes,\n"
-" __global int* out_maxDistanceFromRoot, __global int* out_distanceFromRoot, int numInternalNodes)\n"
-"{\n"
-" if( get_global_id(0) == 0 ) atomic_xchg(out_maxDistanceFromRoot, 0);\n"
-" int internalNodeIndex = get_global_id(0);\n"
-" if(internalNodeIndex >= numInternalNodes) return;\n"
-" \n"
-" //\n"
-" int distanceFromRoot = 0;\n"
-" {\n"
-" int parentIndex = internalNodeParentNodes[internalNodeIndex];\n"
-" while(parentIndex != B3_PLBVH_ROOT_NODE_MARKER)\n"
-" {\n"
-" parentIndex = internalNodeParentNodes[parentIndex];\n"
-" ++distanceFromRoot;\n"
-" }\n"
-" }\n"
-" out_distanceFromRoot[internalNodeIndex] = distanceFromRoot;\n"
-" \n"
-" //\n"
-" __local int localMaxDistanceFromRoot;\n"
-" if( get_local_id(0) == 0 ) localMaxDistanceFromRoot = 0;\n"
-" barrier(CLK_LOCAL_MEM_FENCE);\n"
-" \n"
-" atomic_max(&localMaxDistanceFromRoot, distanceFromRoot);\n"
-" barrier(CLK_LOCAL_MEM_FENCE);\n"
-" \n"
-" if( get_local_id(0) == 0 ) atomic_max(out_maxDistanceFromRoot, localMaxDistanceFromRoot);\n"
-"}\n"
-"__kernel void buildBinaryRadixTreeAabbsRecursive(__global int* distanceFromRoot, __global SortDataCL* mortonCodesAndAabbIndices,\n"
-" __global int2* childNodes,\n"
-" __global b3AabbCL* leafNodeAabbs, __global b3AabbCL* internalNodeAabbs,\n"
-" int maxDistanceFromRoot, int processedDistance, int numInternalNodes)\n"
-"{\n"
-" int internalNodeIndex = get_global_id(0);\n"
-" if(internalNodeIndex >= numInternalNodes) return;\n"
-" \n"
-" int distance = distanceFromRoot[internalNodeIndex];\n"
-" \n"
-" if(distance == processedDistance)\n"
-" {\n"
-" int leftChildIndex = childNodes[internalNodeIndex].x;\n"
-" int rightChildIndex = childNodes[internalNodeIndex].y;\n"
-" \n"
-" int isLeftChildLeaf = isLeafNode(leftChildIndex);\n"
-" int isRightChildLeaf = isLeafNode(rightChildIndex);\n"
-" \n"
-" leftChildIndex = getIndexWithInternalNodeMarkerRemoved(leftChildIndex);\n"
-" rightChildIndex = getIndexWithInternalNodeMarkerRemoved(rightChildIndex);\n"
-" \n"
-" //leftRigidIndex/rightRigidIndex is not used if internal node\n"
-" int leftRigidIndex = (isLeftChildLeaf) ? mortonCodesAndAabbIndices[leftChildIndex].m_value : -1;\n"
-" int rightRigidIndex = (isRightChildLeaf) ? mortonCodesAndAabbIndices[rightChildIndex].m_value : -1;\n"
-" \n"
-" b3AabbCL leftChildAabb = (isLeftChildLeaf) ? leafNodeAabbs[leftRigidIndex] : internalNodeAabbs[leftChildIndex];\n"
-" b3AabbCL rightChildAabb = (isRightChildLeaf) ? leafNodeAabbs[rightRigidIndex] : internalNodeAabbs[rightChildIndex];\n"
-" \n"
-" b3AabbCL mergedAabb;\n"
-" mergedAabb.m_min = b3Min(leftChildAabb.m_min, rightChildAabb.m_min);\n"
-" mergedAabb.m_max = b3Max(leftChildAabb.m_max, rightChildAabb.m_max);\n"
-" internalNodeAabbs[internalNodeIndex] = mergedAabb;\n"
-" }\n"
-"}\n"
-"__kernel void findLeafIndexRanges(__global int2* internalNodeChildNodes, __global int2* out_leafIndexRanges, int numInternalNodes)\n"
-"{\n"
-" int internalNodeIndex = get_global_id(0);\n"
-" if(internalNodeIndex >= numInternalNodes) return;\n"
-" \n"
-" int numLeafNodes = numInternalNodes + 1;\n"
-" \n"
-" int2 childNodes = internalNodeChildNodes[internalNodeIndex];\n"
-" \n"
-" int2 leafIndexRange; //x == min leaf index, y == max leaf index\n"
-" \n"
-" //Find lowest leaf index covered by this internal node\n"
-" {\n"
-" int lowestIndex = childNodes.x; //childNodes.x == Left child\n"
-" while( !isLeafNode(lowestIndex) ) lowestIndex = internalNodeChildNodes[ getIndexWithInternalNodeMarkerRemoved(lowestIndex) ].x;\n"
-" leafIndexRange.x = lowestIndex;\n"
-" }\n"
-" \n"
-" //Find highest leaf index covered by this internal node\n"
-" {\n"
-" int highestIndex = childNodes.y; //childNodes.y == Right child\n"
-" while( !isLeafNode(highestIndex) ) highestIndex = internalNodeChildNodes[ getIndexWithInternalNodeMarkerRemoved(highestIndex) ].y;\n"
-" leafIndexRange.y = highestIndex;\n"
-" }\n"
-" \n"
-" //\n"
-" out_leafIndexRanges[internalNodeIndex] = leafIndexRange;\n"
-"}\n"
-;
+static const char* parallelLinearBvhCL =
+ "/*\n"
+ "This software is provided 'as-is', without any express or implied warranty.\n"
+ "In no event will the authors be held liable for any damages arising from the use of this software.\n"
+ "Permission is granted to anyone to use this software for any purpose,\n"
+ "including commercial applications, and to alter it and redistribute it freely,\n"
+ "subject to the following restrictions:\n"
+ "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
+ "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+ "3. This notice may not be removed or altered from any source distribution.\n"
+ "*/\n"
+ "//Initial Author Jackson Lee, 2014\n"
+ "typedef float b3Scalar;\n"
+ "typedef float4 b3Vector3;\n"
+ "#define b3Max max\n"
+ "#define b3Min min\n"
+ "#define b3Sqrt sqrt\n"
+ "typedef struct\n"
+ "{\n"
+ " unsigned int m_key;\n"
+ " unsigned int m_value;\n"
+ "} SortDataCL;\n"
+ "typedef struct \n"
+ "{\n"
+ " union\n"
+ " {\n"
+ " float4 m_min;\n"
+ " float m_minElems[4];\n"
+ " int m_minIndices[4];\n"
+ " };\n"
+ " union\n"
+ " {\n"
+ " float4 m_max;\n"
+ " float m_maxElems[4];\n"
+ " int m_maxIndices[4];\n"
+ " };\n"
+ "} b3AabbCL;\n"
+ "unsigned int interleaveBits(unsigned int x)\n"
+ "{\n"
+ " //........ ........ ......12 3456789A //x\n"
+ " //....1..2 ..3..4.. 5..6..7. .8..9..A //x after interleaving bits\n"
+ " \n"
+ " //......12 3456789A ......12 3456789A //x ^ (x << 16)\n"
+ " //11111111 ........ ........ 11111111 //0x FF 00 00 FF\n"
+ " //......12 ........ ........ 3456789A //x = (x ^ (x << 16)) & 0xFF0000FF;\n"
+ " \n"
+ " //......12 ........ 3456789A 3456789A //x ^ (x << 8)\n"
+ " //......11 ........ 1111.... ....1111 //0x 03 00 F0 0F\n"
+ " //......12 ........ 3456.... ....789A //x = (x ^ (x << 8)) & 0x0300F00F;\n"
+ " \n"
+ " //..12..12 ....3456 3456.... 789A789A //x ^ (x << 4)\n"
+ " //......11 ....11.. ..11.... 11....11 //0x 03 0C 30 C3\n"
+ " //......12 ....34.. ..56.... 78....9A //x = (x ^ (x << 4)) & 0x030C30C3;\n"
+ " \n"
+ " //....1212 ..3434.. 5656..78 78..9A9A //x ^ (x << 2)\n"
+ " //....1..1 ..1..1.. 1..1..1. .1..1..1 //0x 09 24 92 49\n"
+ " //....1..2 ..3..4.. 5..6..7. .8..9..A //x = (x ^ (x << 2)) & 0x09249249;\n"
+ " \n"
+ " //........ ........ ......11 11111111 //0x000003FF\n"
+ " x &= 0x000003FF; //Clear all bits above bit 10\n"
+ " \n"
+ " x = (x ^ (x << 16)) & 0xFF0000FF;\n"
+ " x = (x ^ (x << 8)) & 0x0300F00F;\n"
+ " x = (x ^ (x << 4)) & 0x030C30C3;\n"
+ " x = (x ^ (x << 2)) & 0x09249249;\n"
+ " \n"
+ " return x;\n"
+ "}\n"
+ "unsigned int getMortonCode(unsigned int x, unsigned int y, unsigned int z)\n"
+ "{\n"
+ " return interleaveBits(x) << 0 | interleaveBits(y) << 1 | interleaveBits(z) << 2;\n"
+ "}\n"
+ "__kernel void separateAabbs(__global b3AabbCL* unseparatedAabbs, __global int* aabbIndices, __global b3AabbCL* out_aabbs, int numAabbsToSeparate)\n"
+ "{\n"
+ " int separatedAabbIndex = get_global_id(0);\n"
+ " if(separatedAabbIndex >= numAabbsToSeparate) return;\n"
+ " int unseparatedAabbIndex = aabbIndices[separatedAabbIndex];\n"
+ " out_aabbs[separatedAabbIndex] = unseparatedAabbs[unseparatedAabbIndex];\n"
+ "}\n"
+ "//Should replace with an optimized parallel reduction\n"
+ "__kernel void findAllNodesMergedAabb(__global b3AabbCL* out_mergedAabb, int numAabbsNeedingMerge)\n"
+ "{\n"
+ " //Each time this kernel is added to the command queue, \n"
+ " //the number of AABBs needing to be merged is halved\n"
+ " //\n"
+ " //Example with 159 AABBs:\n"
+ " // numRemainingAabbs == 159 / 2 + 159 % 2 == 80\n"
+ " // numMergedAabbs == 159 - 80 == 79\n"
+ " //So, indices [0, 78] are merged with [0 + 80, 78 + 80]\n"
+ " \n"
+ " int numRemainingAabbs = numAabbsNeedingMerge / 2 + numAabbsNeedingMerge % 2;\n"
+ " int numMergedAabbs = numAabbsNeedingMerge - numRemainingAabbs;\n"
+ " \n"
+ " int aabbIndex = get_global_id(0);\n"
+ " if(aabbIndex >= numMergedAabbs) return;\n"
+ " \n"
+ " int otherAabbIndex = aabbIndex + numRemainingAabbs;\n"
+ " \n"
+ " b3AabbCL aabb = out_mergedAabb[aabbIndex];\n"
+ " b3AabbCL otherAabb = out_mergedAabb[otherAabbIndex];\n"
+ " \n"
+ " b3AabbCL mergedAabb;\n"
+ " mergedAabb.m_min = b3Min(aabb.m_min, otherAabb.m_min);\n"
+ " mergedAabb.m_max = b3Max(aabb.m_max, otherAabb.m_max);\n"
+ " out_mergedAabb[aabbIndex] = mergedAabb;\n"
+ "}\n"
+ "__kernel void assignMortonCodesAndAabbIndicies(__global b3AabbCL* worldSpaceAabbs, __global b3AabbCL* mergedAabbOfAllNodes, \n"
+ " __global SortDataCL* out_mortonCodesAndAabbIndices, int numAabbs)\n"
+ "{\n"
+ " int leafNodeIndex = get_global_id(0); //Leaf node index == AABB index\n"
+ " if(leafNodeIndex >= numAabbs) return;\n"
+ " \n"
+ " b3AabbCL mergedAabb = mergedAabbOfAllNodes[0];\n"
+ " b3Vector3 gridCenter = (mergedAabb.m_min + mergedAabb.m_max) * 0.5f;\n"
+ " b3Vector3 gridCellSize = (mergedAabb.m_max - mergedAabb.m_min) / (float)1024;\n"
+ " \n"
+ " b3AabbCL aabb = worldSpaceAabbs[leafNodeIndex];\n"
+ " b3Vector3 aabbCenter = (aabb.m_min + aabb.m_max) * 0.5f;\n"
+ " b3Vector3 aabbCenterRelativeToGrid = aabbCenter - gridCenter;\n"
+ " \n"
+ " //Quantize into integer coordinates\n"
+ " //floor() is needed to prevent the center cell, at (0,0,0) from being twice the size\n"
+ " b3Vector3 gridPosition = aabbCenterRelativeToGrid / gridCellSize;\n"
+ " \n"
+ " int4 discretePosition;\n"
+ " discretePosition.x = (int)( (gridPosition.x >= 0.0f) ? gridPosition.x : floor(gridPosition.x) );\n"
+ " discretePosition.y = (int)( (gridPosition.y >= 0.0f) ? gridPosition.y : floor(gridPosition.y) );\n"
+ " discretePosition.z = (int)( (gridPosition.z >= 0.0f) ? gridPosition.z : floor(gridPosition.z) );\n"
+ " \n"
+ " //Clamp coordinates into [-512, 511], then convert range from [-512, 511] to [0, 1023]\n"
+ " discretePosition = b3Max( -512, b3Min(discretePosition, 511) );\n"
+ " discretePosition += 512;\n"
+ " \n"
+ " //Interleave bits(assign a morton code, also known as a z-curve)\n"
+ " unsigned int mortonCode = getMortonCode(discretePosition.x, discretePosition.y, discretePosition.z);\n"
+ " \n"
+ " //\n"
+ " SortDataCL mortonCodeIndexPair;\n"
+ " mortonCodeIndexPair.m_key = mortonCode;\n"
+ " mortonCodeIndexPair.m_value = leafNodeIndex;\n"
+ " \n"
+ " out_mortonCodesAndAabbIndices[leafNodeIndex] = mortonCodeIndexPair;\n"
+ "}\n"
+ "#define B3_PLVBH_TRAVERSE_MAX_STACK_SIZE 128\n"
+ "//The most significant bit(0x80000000) of a int32 is used to distinguish between leaf and internal nodes.\n"
+ "//If it is set, then the index is for an internal node; otherwise, it is a leaf node. \n"
+ "//In both cases, the bit should be cleared to access the actual node index.\n"
+ "int isLeafNode(int index) { return (index >> 31 == 0); }\n"
+ "int getIndexWithInternalNodeMarkerRemoved(int index) { return index & (~0x80000000); }\n"
+ "int getIndexWithInternalNodeMarkerSet(int isLeaf, int index) { return (isLeaf) ? index : (index | 0x80000000); }\n"
+ "//From sap.cl\n"
+ "#define NEW_PAIR_MARKER -1\n"
+ "bool TestAabbAgainstAabb2(const b3AabbCL* aabb1, const b3AabbCL* aabb2)\n"
+ "{\n"
+ " bool overlap = true;\n"
+ " overlap = (aabb1->m_min.x > aabb2->m_max.x || aabb1->m_max.x < aabb2->m_min.x) ? false : overlap;\n"
+ " overlap = (aabb1->m_min.z > aabb2->m_max.z || aabb1->m_max.z < aabb2->m_min.z) ? false : overlap;\n"
+ " overlap = (aabb1->m_min.y > aabb2->m_max.y || aabb1->m_max.y < aabb2->m_min.y) ? false : overlap;\n"
+ " return overlap;\n"
+ "}\n"
+ "//From sap.cl\n"
+ "__kernel void plbvhCalculateOverlappingPairs(__global b3AabbCL* rigidAabbs, \n"
+ " __global int* rootNodeIndex, \n"
+ " __global int2* internalNodeChildIndices, \n"
+ " __global b3AabbCL* internalNodeAabbs,\n"
+ " __global int2* internalNodeLeafIndexRanges,\n"
+ " \n"
+ " __global SortDataCL* mortonCodesAndAabbIndices,\n"
+ " __global int* out_numPairs, __global int4* out_overlappingPairs, \n"
+ " int maxPairs, int numQueryAabbs)\n"
+ "{\n"
+ " //Using get_group_id()/get_local_id() is Faster than get_global_id(0) since\n"
+ " //mortonCodesAndAabbIndices[] contains rigid body indices sorted along the z-curve (more spatially coherent)\n"
+ " int queryBvhNodeIndex = get_group_id(0) * get_local_size(0) + get_local_id(0);\n"
+ " if(queryBvhNodeIndex >= numQueryAabbs) return;\n"
+ " \n"
+ " int queryRigidIndex = mortonCodesAndAabbIndices[queryBvhNodeIndex].m_value;\n"
+ " b3AabbCL queryAabb = rigidAabbs[queryRigidIndex];\n"
+ " \n"
+ " int stack[B3_PLVBH_TRAVERSE_MAX_STACK_SIZE];\n"
+ " \n"
+ " int stackSize = 1;\n"
+ " stack[0] = *rootNodeIndex;\n"
+ " \n"
+ " while(stackSize)\n"
+ " {\n"
+ " int internalOrLeafNodeIndex = stack[ stackSize - 1 ];\n"
+ " --stackSize;\n"
+ " \n"
+ " int isLeaf = isLeafNode(internalOrLeafNodeIndex); //Internal node if false\n"
+ " int bvhNodeIndex = getIndexWithInternalNodeMarkerRemoved(internalOrLeafNodeIndex);\n"
+ " \n"
+ " //Optimization - if the BVH is structured as a binary radix tree, then\n"
+ " //each internal node corresponds to a contiguous range of leaf nodes(internalNodeLeafIndexRanges[]).\n"
+ " //This can be used to avoid testing each AABB-AABB pair twice, including preventing each node from colliding with itself.\n"
+ " {\n"
+ " int highestLeafIndex = (isLeaf) ? bvhNodeIndex : internalNodeLeafIndexRanges[bvhNodeIndex].y;\n"
+ " if(highestLeafIndex <= queryBvhNodeIndex) continue;\n"
+ " }\n"
+ " \n"
+ " //bvhRigidIndex is not used if internal node\n"
+ " int bvhRigidIndex = (isLeaf) ? mortonCodesAndAabbIndices[bvhNodeIndex].m_value : -1;\n"
+ " \n"
+ " b3AabbCL bvhNodeAabb = (isLeaf) ? rigidAabbs[bvhRigidIndex] : internalNodeAabbs[bvhNodeIndex];\n"
+ " if( TestAabbAgainstAabb2(&queryAabb, &bvhNodeAabb) )\n"
+ " {\n"
+ " if(isLeaf)\n"
+ " {\n"
+ " int4 pair;\n"
+ " pair.x = rigidAabbs[queryRigidIndex].m_minIndices[3];\n"
+ " pair.y = rigidAabbs[bvhRigidIndex].m_minIndices[3];\n"
+ " pair.z = NEW_PAIR_MARKER;\n"
+ " pair.w = NEW_PAIR_MARKER;\n"
+ " \n"
+ " int pairIndex = atomic_inc(out_numPairs);\n"
+ " if(pairIndex < maxPairs) out_overlappingPairs[pairIndex] = pair;\n"
+ " }\n"
+ " \n"
+ " if(!isLeaf) //Internal node\n"
+ " {\n"
+ " if(stackSize + 2 > B3_PLVBH_TRAVERSE_MAX_STACK_SIZE)\n"
+ " {\n"
+ " //Error\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " stack[ stackSize++ ] = internalNodeChildIndices[bvhNodeIndex].x;\n"
+ " stack[ stackSize++ ] = internalNodeChildIndices[bvhNodeIndex].y;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " \n"
+ " }\n"
+ "}\n"
+ "//From rayCastKernels.cl\n"
+ "typedef struct\n"
+ "{\n"
+ " float4 m_from;\n"
+ " float4 m_to;\n"
+ "} b3RayInfo;\n"
+ "//From rayCastKernels.cl\n"
+ "b3Vector3 b3Vector3_normalize(b3Vector3 v)\n"
+ "{\n"
+ " b3Vector3 normal = (b3Vector3){v.x, v.y, v.z, 0.f};\n"
+ " return normalize(normal); //OpenCL normalize == vector4 normalize\n"
+ "}\n"
+ "b3Scalar b3Vector3_length2(b3Vector3 v) { return v.x*v.x + v.y*v.y + v.z*v.z; }\n"
+ "b3Scalar b3Vector3_dot(b3Vector3 a, b3Vector3 b) { return a.x*b.x + a.y*b.y + a.z*b.z; }\n"
+ "int rayIntersectsAabb(b3Vector3 rayOrigin, b3Scalar rayLength, b3Vector3 rayNormalizedDirection, b3AabbCL aabb)\n"
+ "{\n"
+ " //AABB is considered as 3 pairs of 2 planes( {x_min, x_max}, {y_min, y_max}, {z_min, z_max} ).\n"
+ " //t_min is the point of intersection with the closer plane, t_max is the point of intersection with the farther plane.\n"
+ " //\n"
+ " //if (rayNormalizedDirection.x < 0.0f), then max.x will be the near plane \n"
+ " //and min.x will be the far plane; otherwise, it is reversed.\n"
+ " //\n"
+ " //In order for there to be a collision, the t_min and t_max of each pair must overlap.\n"
+ " //This can be tested for by selecting the highest t_min and lowest t_max and comparing them.\n"
+ " \n"
+ " int4 isNegative = isless( rayNormalizedDirection, ((b3Vector3){0.0f, 0.0f, 0.0f, 0.0f}) ); //isless(x,y) returns (x < y)\n"
+ " \n"
+ " //When using vector types, the select() function checks the most signficant bit, \n"
+ " //but isless() sets the least significant bit.\n"
+ " isNegative <<= 31;\n"
+ " //select(b, a, condition) == condition ? a : b\n"
+ " //When using select() with vector types, (condition[i]) is true if its most significant bit is 1\n"
+ " b3Vector3 t_min = ( select(aabb.m_min, aabb.m_max, isNegative) - rayOrigin ) / rayNormalizedDirection;\n"
+ " b3Vector3 t_max = ( select(aabb.m_max, aabb.m_min, isNegative) - rayOrigin ) / rayNormalizedDirection;\n"
+ " \n"
+ " b3Scalar t_min_final = 0.0f;\n"
+ " b3Scalar t_max_final = rayLength;\n"
+ " \n"
+ " //Must use fmin()/fmax(); if one of the parameters is NaN, then the parameter that is not NaN is returned. \n"
+ " //Behavior of min()/max() with NaNs is undefined. (See OpenCL Specification 1.2 [6.12.2] and [6.12.4])\n"
+ " //Since the innermost fmin()/fmax() is always not NaN, this should never return NaN.\n"
+ " t_min_final = fmax( t_min.z, fmax(t_min.y, fmax(t_min.x, t_min_final)) );\n"
+ " t_max_final = fmin( t_max.z, fmin(t_max.y, fmin(t_max.x, t_max_final)) );\n"
+ " \n"
+ " return (t_min_final <= t_max_final);\n"
+ "}\n"
+ "__kernel void plbvhRayTraverse(__global b3AabbCL* rigidAabbs,\n"
+ " __global int* rootNodeIndex, \n"
+ " __global int2* internalNodeChildIndices, \n"
+ " __global b3AabbCL* internalNodeAabbs,\n"
+ " __global int2* internalNodeLeafIndexRanges,\n"
+ " __global SortDataCL* mortonCodesAndAabbIndices,\n"
+ " \n"
+ " __global b3RayInfo* rays,\n"
+ " \n"
+ " __global int* out_numRayRigidPairs, \n"
+ " __global int2* out_rayRigidPairs,\n"
+ " int maxRayRigidPairs, int numRays)\n"
+ "{\n"
+ " int rayIndex = get_global_id(0);\n"
+ " if(rayIndex >= numRays) return;\n"
+ " \n"
+ " //\n"
+ " b3Vector3 rayFrom = rays[rayIndex].m_from;\n"
+ " b3Vector3 rayTo = rays[rayIndex].m_to;\n"
+ " b3Vector3 rayNormalizedDirection = b3Vector3_normalize(rayTo - rayFrom);\n"
+ " b3Scalar rayLength = b3Sqrt( b3Vector3_length2(rayTo - rayFrom) );\n"
+ " \n"
+ " //\n"
+ " int stack[B3_PLVBH_TRAVERSE_MAX_STACK_SIZE];\n"
+ " \n"
+ " int stackSize = 1;\n"
+ " stack[0] = *rootNodeIndex;\n"
+ " \n"
+ " while(stackSize)\n"
+ " {\n"
+ " int internalOrLeafNodeIndex = stack[ stackSize - 1 ];\n"
+ " --stackSize;\n"
+ " \n"
+ " int isLeaf = isLeafNode(internalOrLeafNodeIndex); //Internal node if false\n"
+ " int bvhNodeIndex = getIndexWithInternalNodeMarkerRemoved(internalOrLeafNodeIndex);\n"
+ " \n"
+ " //bvhRigidIndex is not used if internal node\n"
+ " int bvhRigidIndex = (isLeaf) ? mortonCodesAndAabbIndices[bvhNodeIndex].m_value : -1;\n"
+ " \n"
+ " b3AabbCL bvhNodeAabb = (isLeaf) ? rigidAabbs[bvhRigidIndex] : internalNodeAabbs[bvhNodeIndex];\n"
+ " if( rayIntersectsAabb(rayFrom, rayLength, rayNormalizedDirection, bvhNodeAabb) )\n"
+ " {\n"
+ " if(isLeaf)\n"
+ " {\n"
+ " int2 rayRigidPair;\n"
+ " rayRigidPair.x = rayIndex;\n"
+ " rayRigidPair.y = rigidAabbs[bvhRigidIndex].m_minIndices[3];\n"
+ " \n"
+ " int pairIndex = atomic_inc(out_numRayRigidPairs);\n"
+ " if(pairIndex < maxRayRigidPairs) out_rayRigidPairs[pairIndex] = rayRigidPair;\n"
+ " }\n"
+ " \n"
+ " if(!isLeaf) //Internal node\n"
+ " {\n"
+ " if(stackSize + 2 > B3_PLVBH_TRAVERSE_MAX_STACK_SIZE)\n"
+ " {\n"
+ " //Error\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " stack[ stackSize++ ] = internalNodeChildIndices[bvhNodeIndex].x;\n"
+ " stack[ stackSize++ ] = internalNodeChildIndices[bvhNodeIndex].y;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ "}\n"
+ "__kernel void plbvhLargeAabbAabbTest(__global b3AabbCL* smallAabbs, __global b3AabbCL* largeAabbs, \n"
+ " __global int* out_numPairs, __global int4* out_overlappingPairs, \n"
+ " int maxPairs, int numLargeAabbRigids, int numSmallAabbRigids)\n"
+ "{\n"
+ " int smallAabbIndex = get_global_id(0);\n"
+ " if(smallAabbIndex >= numSmallAabbRigids) return;\n"
+ " \n"
+ " b3AabbCL smallAabb = smallAabbs[smallAabbIndex];\n"
+ " for(int i = 0; i < numLargeAabbRigids; ++i)\n"
+ " {\n"
+ " b3AabbCL largeAabb = largeAabbs[i];\n"
+ " if( TestAabbAgainstAabb2(&smallAabb, &largeAabb) )\n"
+ " {\n"
+ " int4 pair;\n"
+ " pair.x = largeAabb.m_minIndices[3];\n"
+ " pair.y = smallAabb.m_minIndices[3];\n"
+ " pair.z = NEW_PAIR_MARKER;\n"
+ " pair.w = NEW_PAIR_MARKER;\n"
+ " \n"
+ " int pairIndex = atomic_inc(out_numPairs);\n"
+ " if(pairIndex < maxPairs) out_overlappingPairs[pairIndex] = pair;\n"
+ " }\n"
+ " }\n"
+ "}\n"
+ "__kernel void plbvhLargeAabbRayTest(__global b3AabbCL* largeRigidAabbs, __global b3RayInfo* rays,\n"
+ " __global int* out_numRayRigidPairs, __global int2* out_rayRigidPairs,\n"
+ " int numLargeAabbRigids, int maxRayRigidPairs, int numRays)\n"
+ "{\n"
+ " int rayIndex = get_global_id(0);\n"
+ " if(rayIndex >= numRays) return;\n"
+ " \n"
+ " b3Vector3 rayFrom = rays[rayIndex].m_from;\n"
+ " b3Vector3 rayTo = rays[rayIndex].m_to;\n"
+ " b3Vector3 rayNormalizedDirection = b3Vector3_normalize(rayTo - rayFrom);\n"
+ " b3Scalar rayLength = b3Sqrt( b3Vector3_length2(rayTo - rayFrom) );\n"
+ " \n"
+ " for(int i = 0; i < numLargeAabbRigids; ++i)\n"
+ " {\n"
+ " b3AabbCL rigidAabb = largeRigidAabbs[i];\n"
+ " if( rayIntersectsAabb(rayFrom, rayLength, rayNormalizedDirection, rigidAabb) )\n"
+ " {\n"
+ " int2 rayRigidPair;\n"
+ " rayRigidPair.x = rayIndex;\n"
+ " rayRigidPair.y = rigidAabb.m_minIndices[3];\n"
+ " \n"
+ " int pairIndex = atomic_inc(out_numRayRigidPairs);\n"
+ " if(pairIndex < maxRayRigidPairs) out_rayRigidPairs[pairIndex] = rayRigidPair;\n"
+ " }\n"
+ " }\n"
+ "}\n"
+ "//Set so that it is always greater than the actual common prefixes, and never selected as a parent node.\n"
+ "//If there are no duplicates, then the highest common prefix is 32 or 64, depending on the number of bits used for the z-curve.\n"
+ "//Duplicate common prefixes increase the highest common prefix at most by the number of bits used to index the leaf node.\n"
+ "//Since 32 bit ints are used to index leaf nodes, the max prefix is 64(32 + 32 bit z-curve) or 96(32 + 64 bit z-curve).\n"
+ "#define B3_PLBVH_INVALID_COMMON_PREFIX 128\n"
+ "#define B3_PLBVH_ROOT_NODE_MARKER -1\n"
+ "#define b3Int64 long\n"
+ "int computeCommonPrefixLength(b3Int64 i, b3Int64 j) { return (int)clz(i ^ j); }\n"
+ "b3Int64 computeCommonPrefix(b3Int64 i, b3Int64 j) \n"
+ "{\n"
+ " //This function only needs to return (i & j) in order for the algorithm to work,\n"
+ " //but it may help with debugging to mask out the lower bits.\n"
+ " b3Int64 commonPrefixLength = (b3Int64)computeCommonPrefixLength(i, j);\n"
+ " b3Int64 sharedBits = i & j;\n"
+ " b3Int64 bitmask = ((b3Int64)(~0)) << (64 - commonPrefixLength); //Set all bits after the common prefix to 0\n"
+ " \n"
+ " return sharedBits & bitmask;\n"
+ "}\n"
+ "//Same as computeCommonPrefixLength(), but allows for prefixes with different lengths\n"
+ "int getSharedPrefixLength(b3Int64 prefixA, int prefixLengthA, b3Int64 prefixB, int prefixLengthB)\n"
+ "{\n"
+ " return b3Min( computeCommonPrefixLength(prefixA, prefixB), b3Min(prefixLengthA, prefixLengthB) );\n"
+ "}\n"
+ "__kernel void computeAdjacentPairCommonPrefix(__global SortDataCL* mortonCodesAndAabbIndices,\n"
+ " __global b3Int64* out_commonPrefixes,\n"
+ " __global int* out_commonPrefixLengths,\n"
+ " int numInternalNodes)\n"
+ "{\n"
+ " int internalNodeIndex = get_global_id(0);\n"
+ " if (internalNodeIndex >= numInternalNodes) return;\n"
+ " \n"
+ " //Here, (internalNodeIndex + 1) is never out of bounds since it is a leaf node index,\n"
+ " //and the number of internal nodes is always numLeafNodes - 1\n"
+ " int leftLeafIndex = internalNodeIndex;\n"
+ " int rightLeafIndex = internalNodeIndex + 1;\n"
+ " \n"
+ " int leftLeafMortonCode = mortonCodesAndAabbIndices[leftLeafIndex].m_key;\n"
+ " int rightLeafMortonCode = mortonCodesAndAabbIndices[rightLeafIndex].m_key;\n"
+ " \n"
+ " //Binary radix tree construction algorithm does not work if there are duplicate morton codes.\n"
+ " //Append the index of each leaf node to each morton code so that there are no duplicates.\n"
+ " //The algorithm also requires that the morton codes are sorted in ascending order; this requirement\n"
+ " //is also satisfied with this method, as (leftLeafIndex < rightLeafIndex) is always true.\n"
+ " //\n"
+ " //upsample(a, b) == ( ((b3Int64)a) << 32) | b\n"
+ " b3Int64 nonduplicateLeftMortonCode = upsample(leftLeafMortonCode, leftLeafIndex);\n"
+ " b3Int64 nonduplicateRightMortonCode = upsample(rightLeafMortonCode, rightLeafIndex);\n"
+ " \n"
+ " out_commonPrefixes[internalNodeIndex] = computeCommonPrefix(nonduplicateLeftMortonCode, nonduplicateRightMortonCode);\n"
+ " out_commonPrefixLengths[internalNodeIndex] = computeCommonPrefixLength(nonduplicateLeftMortonCode, nonduplicateRightMortonCode);\n"
+ "}\n"
+ "__kernel void buildBinaryRadixTreeLeafNodes(__global int* commonPrefixLengths, __global int* out_leafNodeParentNodes,\n"
+ " __global int2* out_childNodes, int numLeafNodes)\n"
+ "{\n"
+ " int leafNodeIndex = get_global_id(0);\n"
+ " if (leafNodeIndex >= numLeafNodes) return;\n"
+ " \n"
+ " int numInternalNodes = numLeafNodes - 1;\n"
+ " \n"
+ " int leftSplitIndex = leafNodeIndex - 1;\n"
+ " int rightSplitIndex = leafNodeIndex;\n"
+ " \n"
+ " int leftCommonPrefix = (leftSplitIndex >= 0) ? commonPrefixLengths[leftSplitIndex] : B3_PLBVH_INVALID_COMMON_PREFIX;\n"
+ " int rightCommonPrefix = (rightSplitIndex < numInternalNodes) ? commonPrefixLengths[rightSplitIndex] : B3_PLBVH_INVALID_COMMON_PREFIX;\n"
+ " \n"
+ " //Parent node is the highest adjacent common prefix that is lower than the node's common prefix\n"
+ " //Leaf nodes are considered as having the highest common prefix\n"
+ " int isLeftHigherCommonPrefix = (leftCommonPrefix > rightCommonPrefix);\n"
+ " \n"
+ " //Handle cases for the edge nodes; the first and last node\n"
+ " //For leaf nodes, leftCommonPrefix and rightCommonPrefix should never both be B3_PLBVH_INVALID_COMMON_PREFIX\n"
+ " if(leftCommonPrefix == B3_PLBVH_INVALID_COMMON_PREFIX) isLeftHigherCommonPrefix = false;\n"
+ " if(rightCommonPrefix == B3_PLBVH_INVALID_COMMON_PREFIX) isLeftHigherCommonPrefix = true;\n"
+ " \n"
+ " int parentNodeIndex = (isLeftHigherCommonPrefix) ? leftSplitIndex : rightSplitIndex;\n"
+ " out_leafNodeParentNodes[leafNodeIndex] = parentNodeIndex;\n"
+ " \n"
+ " int isRightChild = (isLeftHigherCommonPrefix); //If the left node is the parent, then this node is its right child and vice versa\n"
+ " \n"
+ " //out_childNodesAsInt[0] == int2.x == left child\n"
+ " //out_childNodesAsInt[1] == int2.y == right child\n"
+ " int isLeaf = 1;\n"
+ " __global int* out_childNodesAsInt = (__global int*)(&out_childNodes[parentNodeIndex]);\n"
+ " out_childNodesAsInt[isRightChild] = getIndexWithInternalNodeMarkerSet(isLeaf, leafNodeIndex);\n"
+ "}\n"
+ "__kernel void buildBinaryRadixTreeInternalNodes(__global b3Int64* commonPrefixes, __global int* commonPrefixLengths,\n"
+ " __global int2* out_childNodes,\n"
+ " __global int* out_internalNodeParentNodes, __global int* out_rootNodeIndex,\n"
+ " int numInternalNodes)\n"
+ "{\n"
+ " int internalNodeIndex = get_group_id(0) * get_local_size(0) + get_local_id(0);\n"
+ " if(internalNodeIndex >= numInternalNodes) return;\n"
+ " \n"
+ " b3Int64 nodePrefix = commonPrefixes[internalNodeIndex];\n"
+ " int nodePrefixLength = commonPrefixLengths[internalNodeIndex];\n"
+ " \n"
+ "//#define USE_LINEAR_SEARCH\n"
+ "#ifdef USE_LINEAR_SEARCH\n"
+ " int leftIndex = -1;\n"
+ " int rightIndex = -1;\n"
+ " \n"
+ " //Find nearest element to left with a lower common prefix\n"
+ " for(int i = internalNodeIndex - 1; i >= 0; --i)\n"
+ " {\n"
+ " int nodeLeftSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, commonPrefixes[i], commonPrefixLengths[i]);\n"
+ " if(nodeLeftSharedPrefixLength < nodePrefixLength)\n"
+ " {\n"
+ " leftIndex = i;\n"
+ " break;\n"
+ " }\n"
+ " }\n"
+ " \n"
+ " //Find nearest element to right with a lower common prefix\n"
+ " for(int i = internalNodeIndex + 1; i < numInternalNodes; ++i)\n"
+ " {\n"
+ " int nodeRightSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, commonPrefixes[i], commonPrefixLengths[i]);\n"
+ " if(nodeRightSharedPrefixLength < nodePrefixLength)\n"
+ " {\n"
+ " rightIndex = i;\n"
+ " break;\n"
+ " }\n"
+ " }\n"
+ " \n"
+ "#else //Use binary search\n"
+ " //Find nearest element to left with a lower common prefix\n"
+ " int leftIndex = -1;\n"
+ " {\n"
+ " int lower = 0;\n"
+ " int upper = internalNodeIndex - 1;\n"
+ " \n"
+ " while(lower <= upper)\n"
+ " {\n"
+ " int mid = (lower + upper) / 2;\n"
+ " b3Int64 midPrefix = commonPrefixes[mid];\n"
+ " int midPrefixLength = commonPrefixLengths[mid];\n"
+ " \n"
+ " int nodeMidSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, midPrefix, midPrefixLength);\n"
+ " if(nodeMidSharedPrefixLength < nodePrefixLength) \n"
+ " {\n"
+ " int right = mid + 1;\n"
+ " if(right < internalNodeIndex)\n"
+ " {\n"
+ " b3Int64 rightPrefix = commonPrefixes[right];\n"
+ " int rightPrefixLength = commonPrefixLengths[right];\n"
+ " \n"
+ " int nodeRightSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, rightPrefix, rightPrefixLength);\n"
+ " if(nodeRightSharedPrefixLength < nodePrefixLength) \n"
+ " {\n"
+ " lower = right;\n"
+ " leftIndex = right;\n"
+ " }\n"
+ " else \n"
+ " {\n"
+ " leftIndex = mid;\n"
+ " break;\n"
+ " }\n"
+ " }\n"
+ " else \n"
+ " {\n"
+ " leftIndex = mid;\n"
+ " break;\n"
+ " }\n"
+ " }\n"
+ " else upper = mid - 1;\n"
+ " }\n"
+ " }\n"
+ " \n"
+ " //Find nearest element to right with a lower common prefix\n"
+ " int rightIndex = -1;\n"
+ " {\n"
+ " int lower = internalNodeIndex + 1;\n"
+ " int upper = numInternalNodes - 1;\n"
+ " \n"
+ " while(lower <= upper)\n"
+ " {\n"
+ " int mid = (lower + upper) / 2;\n"
+ " b3Int64 midPrefix = commonPrefixes[mid];\n"
+ " int midPrefixLength = commonPrefixLengths[mid];\n"
+ " \n"
+ " int nodeMidSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, midPrefix, midPrefixLength);\n"
+ " if(nodeMidSharedPrefixLength < nodePrefixLength) \n"
+ " {\n"
+ " int left = mid - 1;\n"
+ " if(left > internalNodeIndex)\n"
+ " {\n"
+ " b3Int64 leftPrefix = commonPrefixes[left];\n"
+ " int leftPrefixLength = commonPrefixLengths[left];\n"
+ " \n"
+ " int nodeLeftSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, leftPrefix, leftPrefixLength);\n"
+ " if(nodeLeftSharedPrefixLength < nodePrefixLength) \n"
+ " {\n"
+ " upper = left;\n"
+ " rightIndex = left;\n"
+ " }\n"
+ " else \n"
+ " {\n"
+ " rightIndex = mid;\n"
+ " break;\n"
+ " }\n"
+ " }\n"
+ " else \n"
+ " {\n"
+ " rightIndex = mid;\n"
+ " break;\n"
+ " }\n"
+ " }\n"
+ " else lower = mid + 1;\n"
+ " }\n"
+ " }\n"
+ "#endif\n"
+ " \n"
+ " //Select parent\n"
+ " {\n"
+ " int leftPrefixLength = (leftIndex != -1) ? commonPrefixLengths[leftIndex] : B3_PLBVH_INVALID_COMMON_PREFIX;\n"
+ " int rightPrefixLength = (rightIndex != -1) ? commonPrefixLengths[rightIndex] : B3_PLBVH_INVALID_COMMON_PREFIX;\n"
+ " \n"
+ " int isLeftHigherPrefixLength = (leftPrefixLength > rightPrefixLength);\n"
+ " \n"
+ " if(leftPrefixLength == B3_PLBVH_INVALID_COMMON_PREFIX) isLeftHigherPrefixLength = false;\n"
+ " else if(rightPrefixLength == B3_PLBVH_INVALID_COMMON_PREFIX) isLeftHigherPrefixLength = true;\n"
+ " \n"
+ " int parentNodeIndex = (isLeftHigherPrefixLength) ? leftIndex : rightIndex;\n"
+ " \n"
+ " int isRootNode = (leftIndex == -1 && rightIndex == -1);\n"
+ " out_internalNodeParentNodes[internalNodeIndex] = (!isRootNode) ? parentNodeIndex : B3_PLBVH_ROOT_NODE_MARKER;\n"
+ " \n"
+ " int isLeaf = 0;\n"
+ " if(!isRootNode)\n"
+ " {\n"
+ " int isRightChild = (isLeftHigherPrefixLength); //If the left node is the parent, then this node is its right child and vice versa\n"
+ " \n"
+ " //out_childNodesAsInt[0] == int2.x == left child\n"
+ " //out_childNodesAsInt[1] == int2.y == right child\n"
+ " __global int* out_childNodesAsInt = (__global int*)(&out_childNodes[parentNodeIndex]);\n"
+ " out_childNodesAsInt[isRightChild] = getIndexWithInternalNodeMarkerSet(isLeaf, internalNodeIndex);\n"
+ " }\n"
+ " else *out_rootNodeIndex = getIndexWithInternalNodeMarkerSet(isLeaf, internalNodeIndex);\n"
+ " }\n"
+ "}\n"
+ "__kernel void findDistanceFromRoot(__global int* rootNodeIndex, __global int* internalNodeParentNodes,\n"
+ " __global int* out_maxDistanceFromRoot, __global int* out_distanceFromRoot, int numInternalNodes)\n"
+ "{\n"
+ " if( get_global_id(0) == 0 ) atomic_xchg(out_maxDistanceFromRoot, 0);\n"
+ " int internalNodeIndex = get_global_id(0);\n"
+ " if(internalNodeIndex >= numInternalNodes) return;\n"
+ " \n"
+ " //\n"
+ " int distanceFromRoot = 0;\n"
+ " {\n"
+ " int parentIndex = internalNodeParentNodes[internalNodeIndex];\n"
+ " while(parentIndex != B3_PLBVH_ROOT_NODE_MARKER)\n"
+ " {\n"
+ " parentIndex = internalNodeParentNodes[parentIndex];\n"
+ " ++distanceFromRoot;\n"
+ " }\n"
+ " }\n"
+ " out_distanceFromRoot[internalNodeIndex] = distanceFromRoot;\n"
+ " \n"
+ " //\n"
+ " __local int localMaxDistanceFromRoot;\n"
+ " if( get_local_id(0) == 0 ) localMaxDistanceFromRoot = 0;\n"
+ " barrier(CLK_LOCAL_MEM_FENCE);\n"
+ " \n"
+ " atomic_max(&localMaxDistanceFromRoot, distanceFromRoot);\n"
+ " barrier(CLK_LOCAL_MEM_FENCE);\n"
+ " \n"
+ " if( get_local_id(0) == 0 ) atomic_max(out_maxDistanceFromRoot, localMaxDistanceFromRoot);\n"
+ "}\n"
+ "__kernel void buildBinaryRadixTreeAabbsRecursive(__global int* distanceFromRoot, __global SortDataCL* mortonCodesAndAabbIndices,\n"
+ " __global int2* childNodes,\n"
+ " __global b3AabbCL* leafNodeAabbs, __global b3AabbCL* internalNodeAabbs,\n"
+ " int maxDistanceFromRoot, int processedDistance, int numInternalNodes)\n"
+ "{\n"
+ " int internalNodeIndex = get_global_id(0);\n"
+ " if(internalNodeIndex >= numInternalNodes) return;\n"
+ " \n"
+ " int distance = distanceFromRoot[internalNodeIndex];\n"
+ " \n"
+ " if(distance == processedDistance)\n"
+ " {\n"
+ " int leftChildIndex = childNodes[internalNodeIndex].x;\n"
+ " int rightChildIndex = childNodes[internalNodeIndex].y;\n"
+ " \n"
+ " int isLeftChildLeaf = isLeafNode(leftChildIndex);\n"
+ " int isRightChildLeaf = isLeafNode(rightChildIndex);\n"
+ " \n"
+ " leftChildIndex = getIndexWithInternalNodeMarkerRemoved(leftChildIndex);\n"
+ " rightChildIndex = getIndexWithInternalNodeMarkerRemoved(rightChildIndex);\n"
+ " \n"
+ " //leftRigidIndex/rightRigidIndex is not used if internal node\n"
+ " int leftRigidIndex = (isLeftChildLeaf) ? mortonCodesAndAabbIndices[leftChildIndex].m_value : -1;\n"
+ " int rightRigidIndex = (isRightChildLeaf) ? mortonCodesAndAabbIndices[rightChildIndex].m_value : -1;\n"
+ " \n"
+ " b3AabbCL leftChildAabb = (isLeftChildLeaf) ? leafNodeAabbs[leftRigidIndex] : internalNodeAabbs[leftChildIndex];\n"
+ " b3AabbCL rightChildAabb = (isRightChildLeaf) ? leafNodeAabbs[rightRigidIndex] : internalNodeAabbs[rightChildIndex];\n"
+ " \n"
+ " b3AabbCL mergedAabb;\n"
+ " mergedAabb.m_min = b3Min(leftChildAabb.m_min, rightChildAabb.m_min);\n"
+ " mergedAabb.m_max = b3Max(leftChildAabb.m_max, rightChildAabb.m_max);\n"
+ " internalNodeAabbs[internalNodeIndex] = mergedAabb;\n"
+ " }\n"
+ "}\n"
+ "__kernel void findLeafIndexRanges(__global int2* internalNodeChildNodes, __global int2* out_leafIndexRanges, int numInternalNodes)\n"
+ "{\n"
+ " int internalNodeIndex = get_global_id(0);\n"
+ " if(internalNodeIndex >= numInternalNodes) return;\n"
+ " \n"
+ " int numLeafNodes = numInternalNodes + 1;\n"
+ " \n"
+ " int2 childNodes = internalNodeChildNodes[internalNodeIndex];\n"
+ " \n"
+ " int2 leafIndexRange; //x == min leaf index, y == max leaf index\n"
+ " \n"
+ " //Find lowest leaf index covered by this internal node\n"
+ " {\n"
+ " int lowestIndex = childNodes.x; //childNodes.x == Left child\n"
+ " while( !isLeafNode(lowestIndex) ) lowestIndex = internalNodeChildNodes[ getIndexWithInternalNodeMarkerRemoved(lowestIndex) ].x;\n"
+ " leafIndexRange.x = lowestIndex;\n"
+ " }\n"
+ " \n"
+ " //Find highest leaf index covered by this internal node\n"
+ " {\n"
+ " int highestIndex = childNodes.y; //childNodes.y == Right child\n"
+ " while( !isLeafNode(highestIndex) ) highestIndex = internalNodeChildNodes[ getIndexWithInternalNodeMarkerRemoved(highestIndex) ].y;\n"
+ " leafIndexRange.y = highestIndex;\n"
+ " }\n"
+ " \n"
+ " //\n"
+ " out_leafIndexRanges[internalNodeIndex] = leafIndexRange;\n"
+ "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/kernels/sapKernels.h b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/kernels/sapKernels.h
index 04d40fcf26..d6999b94cb 100644
--- a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/kernels/sapKernels.h
+++ b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/kernels/sapKernels.h
@@ -1,342 +1,341 @@
//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* sapCL= \
-"/*\n"
-"Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
-"This software is provided 'as-is', without any express or implied warranty.\n"
-"In no event will the authors be held liable for any damages arising from the use of this software.\n"
-"Permission is granted to anyone to use this software for any purpose, \n"
-"including commercial applications, and to alter it and redistribute it freely, \n"
-"subject to the following restrictions:\n"
-"1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
-"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
-"3. This notice may not be removed or altered from any source distribution.\n"
-"*/\n"
-"//Originally written by Erwin Coumans\n"
-"#define NEW_PAIR_MARKER -1\n"
-"typedef struct \n"
-"{\n"
-" union\n"
-" {\n"
-" float4 m_min;\n"
-" float m_minElems[4];\n"
-" int m_minIndices[4];\n"
-" };\n"
-" union\n"
-" {\n"
-" float4 m_max;\n"
-" float m_maxElems[4];\n"
-" int m_maxIndices[4];\n"
-" };\n"
-"} btAabbCL;\n"
-"/// conservative test for overlap between two aabbs\n"
-"bool TestAabbAgainstAabb2(const btAabbCL* aabb1, __local const btAabbCL* aabb2);\n"
-"bool TestAabbAgainstAabb2(const btAabbCL* aabb1, __local const btAabbCL* aabb2)\n"
-"{\n"
-" bool overlap = true;\n"
-" overlap = (aabb1->m_min.x > aabb2->m_max.x || aabb1->m_max.x < aabb2->m_min.x) ? false : overlap;\n"
-" overlap = (aabb1->m_min.z > aabb2->m_max.z || aabb1->m_max.z < aabb2->m_min.z) ? false : overlap;\n"
-" overlap = (aabb1->m_min.y > aabb2->m_max.y || aabb1->m_max.y < aabb2->m_min.y) ? false : overlap;\n"
-" return overlap;\n"
-"}\n"
-"bool TestAabbAgainstAabb2GlobalGlobal(__global const btAabbCL* aabb1, __global const btAabbCL* aabb2);\n"
-"bool TestAabbAgainstAabb2GlobalGlobal(__global const btAabbCL* aabb1, __global const btAabbCL* aabb2)\n"
-"{\n"
-" bool overlap = true;\n"
-" overlap = (aabb1->m_min.x > aabb2->m_max.x || aabb1->m_max.x < aabb2->m_min.x) ? false : overlap;\n"
-" overlap = (aabb1->m_min.z > aabb2->m_max.z || aabb1->m_max.z < aabb2->m_min.z) ? false : overlap;\n"
-" overlap = (aabb1->m_min.y > aabb2->m_max.y || aabb1->m_max.y < aabb2->m_min.y) ? false : overlap;\n"
-" return overlap;\n"
-"}\n"
-"bool TestAabbAgainstAabb2Global(const btAabbCL* aabb1, __global const btAabbCL* aabb2);\n"
-"bool TestAabbAgainstAabb2Global(const btAabbCL* aabb1, __global const btAabbCL* aabb2)\n"
-"{\n"
-" bool overlap = true;\n"
-" overlap = (aabb1->m_min.x > aabb2->m_max.x || aabb1->m_max.x < aabb2->m_min.x) ? false : overlap;\n"
-" overlap = (aabb1->m_min.z > aabb2->m_max.z || aabb1->m_max.z < aabb2->m_min.z) ? false : overlap;\n"
-" overlap = (aabb1->m_min.y > aabb2->m_max.y || aabb1->m_max.y < aabb2->m_min.y) ? false : overlap;\n"
-" return overlap;\n"
-"}\n"
-"__kernel void computePairsKernelTwoArrays( __global const btAabbCL* unsortedAabbs, __global const int* unsortedAabbMapping, __global const int* unsortedAabbMapping2, volatile __global int4* pairsOut,volatile __global int* pairCount, int numUnsortedAabbs, int numUnSortedAabbs2, int axis, int maxPairs)\n"
-"{\n"
-" int i = get_global_id(0);\n"
-" if (i>=numUnsortedAabbs)\n"
-" return;\n"
-" int j = get_global_id(1);\n"
-" if (j>=numUnSortedAabbs2)\n"
-" return;\n"
-" __global const btAabbCL* unsortedAabbPtr = &unsortedAabbs[unsortedAabbMapping[i]];\n"
-" __global const btAabbCL* unsortedAabbPtr2 = &unsortedAabbs[unsortedAabbMapping2[j]];\n"
-" if (TestAabbAgainstAabb2GlobalGlobal(unsortedAabbPtr,unsortedAabbPtr2))\n"
-" {\n"
-" int4 myPair;\n"
-" \n"
-" int xIndex = unsortedAabbPtr[0].m_minIndices[3];\n"
-" int yIndex = unsortedAabbPtr2[0].m_minIndices[3];\n"
-" if (xIndex>yIndex)\n"
-" {\n"
-" int tmp = xIndex;\n"
-" xIndex=yIndex;\n"
-" yIndex=tmp;\n"
-" }\n"
-" \n"
-" myPair.x = xIndex;\n"
-" myPair.y = yIndex;\n"
-" myPair.z = NEW_PAIR_MARKER;\n"
-" myPair.w = NEW_PAIR_MARKER;\n"
-" int curPair = atomic_inc (pairCount);\n"
-" if (curPair<maxPairs)\n"
-" {\n"
-" pairsOut[curPair] = myPair; //flush to main memory\n"
-" }\n"
-" }\n"
-"}\n"
-"__kernel void computePairsKernelBruteForce( __global const btAabbCL* aabbs, volatile __global int4* pairsOut,volatile __global int* pairCount, int numObjects, int axis, int maxPairs)\n"
-"{\n"
-" int i = get_global_id(0);\n"
-" if (i>=numObjects)\n"
-" return;\n"
-" for (int j=i+1;j<numObjects;j++)\n"
-" {\n"
-" if (TestAabbAgainstAabb2GlobalGlobal(&aabbs[i],&aabbs[j]))\n"
-" {\n"
-" int4 myPair;\n"
-" myPair.x = aabbs[i].m_minIndices[3];\n"
-" myPair.y = aabbs[j].m_minIndices[3];\n"
-" myPair.z = NEW_PAIR_MARKER;\n"
-" myPair.w = NEW_PAIR_MARKER;\n"
-" int curPair = atomic_inc (pairCount);\n"
-" if (curPair<maxPairs)\n"
-" {\n"
-" pairsOut[curPair] = myPair; //flush to main memory\n"
-" }\n"
-" }\n"
-" }\n"
-"}\n"
-"__kernel void computePairsKernelOriginal( __global const btAabbCL* aabbs, volatile __global int4* pairsOut,volatile __global int* pairCount, int numObjects, int axis, int maxPairs)\n"
-"{\n"
-" int i = get_global_id(0);\n"
-" if (i>=numObjects)\n"
-" return;\n"
-" for (int j=i+1;j<numObjects;j++)\n"
-" {\n"
-" if(aabbs[i].m_maxElems[axis] < (aabbs[j].m_minElems[axis])) \n"
-" {\n"
-" break;\n"
-" }\n"
-" if (TestAabbAgainstAabb2GlobalGlobal(&aabbs[i],&aabbs[j]))\n"
-" {\n"
-" int4 myPair;\n"
-" myPair.x = aabbs[i].m_minIndices[3];\n"
-" myPair.y = aabbs[j].m_minIndices[3];\n"
-" myPair.z = NEW_PAIR_MARKER;\n"
-" myPair.w = NEW_PAIR_MARKER;\n"
-" int curPair = atomic_inc (pairCount);\n"
-" if (curPair<maxPairs)\n"
-" {\n"
-" pairsOut[curPair] = myPair; //flush to main memory\n"
-" }\n"
-" }\n"
-" }\n"
-"}\n"
-"__kernel void computePairsKernelBarrier( __global const btAabbCL* aabbs, volatile __global int4* pairsOut,volatile __global int* pairCount, int numObjects, int axis, int maxPairs)\n"
-"{\n"
-" int i = get_global_id(0);\n"
-" int localId = get_local_id(0);\n"
-" __local int numActiveWgItems[1];\n"
-" __local int breakRequest[1];\n"
-" if (localId==0)\n"
-" {\n"
-" numActiveWgItems[0] = 0;\n"
-" breakRequest[0] = 0;\n"
-" }\n"
-" barrier(CLK_LOCAL_MEM_FENCE);\n"
-" atomic_inc(numActiveWgItems);\n"
-" barrier(CLK_LOCAL_MEM_FENCE);\n"
-" int localBreak = 0;\n"
-" int j=i+1;\n"
-" do\n"
-" {\n"
-" barrier(CLK_LOCAL_MEM_FENCE);\n"
-" \n"
-" if (j<numObjects)\n"
-" {\n"
-" if(aabbs[i].m_maxElems[axis] < (aabbs[j].m_minElems[axis])) \n"
-" {\n"
-" if (!localBreak)\n"
-" {\n"
-" atomic_inc(breakRequest);\n"
-" localBreak = 1;\n"
-" }\n"
-" }\n"
-" }\n"
-" \n"
-" barrier(CLK_LOCAL_MEM_FENCE);\n"
-" \n"
-" if (j>=numObjects && !localBreak)\n"
-" {\n"
-" atomic_inc(breakRequest);\n"
-" localBreak = 1;\n"
-" }\n"
-" barrier(CLK_LOCAL_MEM_FENCE);\n"
-" \n"
-" if (!localBreak)\n"
-" {\n"
-" if (TestAabbAgainstAabb2GlobalGlobal(&aabbs[i],&aabbs[j]))\n"
-" {\n"
-" int4 myPair;\n"
-" myPair.x = aabbs[i].m_minIndices[3];\n"
-" myPair.y = aabbs[j].m_minIndices[3];\n"
-" myPair.z = NEW_PAIR_MARKER;\n"
-" myPair.w = NEW_PAIR_MARKER;\n"
-" int curPair = atomic_inc (pairCount);\n"
-" if (curPair<maxPairs)\n"
-" {\n"
-" pairsOut[curPair] = myPair; //flush to main memory\n"
-" }\n"
-" }\n"
-" }\n"
-" j++;\n"
-" } while (breakRequest[0]<numActiveWgItems[0]);\n"
-"}\n"
-"__kernel void computePairsKernelLocalSharedMemory( __global const btAabbCL* aabbs, volatile __global int4* pairsOut,volatile __global int* pairCount, int numObjects, int axis, int maxPairs)\n"
-"{\n"
-" int i = get_global_id(0);\n"
-" int localId = get_local_id(0);\n"
-" __local int numActiveWgItems[1];\n"
-" __local int breakRequest[1];\n"
-" __local btAabbCL localAabbs[128];// = aabbs[i];\n"
-" \n"
-" btAabbCL myAabb;\n"
-" \n"
-" myAabb = (i<numObjects)? aabbs[i]:aabbs[0];\n"
-" float testValue = myAabb.m_maxElems[axis];\n"
-" \n"
-" if (localId==0)\n"
-" {\n"
-" numActiveWgItems[0] = 0;\n"
-" breakRequest[0] = 0;\n"
-" }\n"
-" int localCount=0;\n"
-" int block=0;\n"
-" localAabbs[localId] = (i+block)<numObjects? aabbs[i+block] : aabbs[0];\n"
-" localAabbs[localId+64] = (i+block+64)<numObjects? aabbs[i+block+64]: aabbs[0];\n"
-" \n"
-" barrier(CLK_LOCAL_MEM_FENCE);\n"
-" atomic_inc(numActiveWgItems);\n"
-" barrier(CLK_LOCAL_MEM_FENCE);\n"
-" int localBreak = 0;\n"
-" \n"
-" int j=i+1;\n"
-" do\n"
-" {\n"
-" barrier(CLK_LOCAL_MEM_FENCE);\n"
-" \n"
-" if (j<numObjects)\n"
-" {\n"
-" if(testValue < (localAabbs[localCount+localId+1].m_minElems[axis])) \n"
-" {\n"
-" if (!localBreak)\n"
-" {\n"
-" atomic_inc(breakRequest);\n"
-" localBreak = 1;\n"
-" }\n"
-" }\n"
-" }\n"
-" \n"
-" barrier(CLK_LOCAL_MEM_FENCE);\n"
-" \n"
-" if (j>=numObjects && !localBreak)\n"
-" {\n"
-" atomic_inc(breakRequest);\n"
-" localBreak = 1;\n"
-" }\n"
-" barrier(CLK_LOCAL_MEM_FENCE);\n"
-" \n"
-" if (!localBreak)\n"
-" {\n"
-" if (TestAabbAgainstAabb2(&myAabb,&localAabbs[localCount+localId+1]))\n"
-" {\n"
-" int4 myPair;\n"
-" myPair.x = myAabb.m_minIndices[3];\n"
-" myPair.y = localAabbs[localCount+localId+1].m_minIndices[3];\n"
-" myPair.z = NEW_PAIR_MARKER;\n"
-" myPair.w = NEW_PAIR_MARKER;\n"
-" int curPair = atomic_inc (pairCount);\n"
-" if (curPair<maxPairs)\n"
-" {\n"
-" pairsOut[curPair] = myPair; //flush to main memory\n"
-" }\n"
-" }\n"
-" }\n"
-" \n"
-" barrier(CLK_LOCAL_MEM_FENCE);\n"
-" localCount++;\n"
-" if (localCount==64)\n"
-" {\n"
-" localCount = 0;\n"
-" block+=64; \n"
-" localAabbs[localId] = ((i+block)<numObjects) ? aabbs[i+block] : aabbs[0];\n"
-" localAabbs[localId+64] = ((i+64+block)<numObjects) ? aabbs[i+block+64] : aabbs[0];\n"
-" }\n"
-" j++;\n"
-" \n"
-" } while (breakRequest[0]<numActiveWgItems[0]);\n"
-" \n"
-"}\n"
-"//http://stereopsis.com/radix.html\n"
-"unsigned int FloatFlip(float fl);\n"
-"unsigned int FloatFlip(float fl)\n"
-"{\n"
-" unsigned int f = *(unsigned int*)&fl;\n"
-" unsigned int mask = -(int)(f >> 31) | 0x80000000;\n"
-" return f ^ mask;\n"
-"}\n"
-"float IFloatFlip(unsigned int f);\n"
-"float IFloatFlip(unsigned int f)\n"
-"{\n"
-" unsigned int mask = ((f >> 31) - 1) | 0x80000000;\n"
-" unsigned int fl = f ^ mask;\n"
-" return *(float*)&fl;\n"
-"}\n"
-"__kernel void copyAabbsKernel( __global const btAabbCL* allAabbs, __global btAabbCL* destAabbs, int numObjects)\n"
-"{\n"
-" int i = get_global_id(0);\n"
-" if (i>=numObjects)\n"
-" return;\n"
-" int src = destAabbs[i].m_maxIndices[3];\n"
-" destAabbs[i] = allAabbs[src];\n"
-" destAabbs[i].m_maxIndices[3] = src;\n"
-"}\n"
-"__kernel void flipFloatKernel( __global const btAabbCL* allAabbs, __global const int* smallAabbMapping, __global int2* sortData, int numObjects, int axis)\n"
-"{\n"
-" int i = get_global_id(0);\n"
-" if (i>=numObjects)\n"
-" return;\n"
-" \n"
-" \n"
-" sortData[i].x = FloatFlip(allAabbs[smallAabbMapping[i]].m_minElems[axis]);\n"
-" sortData[i].y = i;\n"
-" \n"
-"}\n"
-"__kernel void scatterKernel( __global const btAabbCL* allAabbs, __global const int* smallAabbMapping, volatile __global const int2* sortData, __global btAabbCL* sortedAabbs, int numObjects)\n"
-"{\n"
-" int i = get_global_id(0);\n"
-" if (i>=numObjects)\n"
-" return;\n"
-" \n"
-" sortedAabbs[i] = allAabbs[smallAabbMapping[sortData[i].y]];\n"
-"}\n"
-"__kernel void prepareSumVarianceKernel( __global const btAabbCL* allAabbs, __global const int* smallAabbMapping, __global float4* sum, __global float4* sum2,int numAabbs)\n"
-"{\n"
-" int i = get_global_id(0);\n"
-" if (i>=numAabbs)\n"
-" return;\n"
-" \n"
-" btAabbCL smallAabb = allAabbs[smallAabbMapping[i]];\n"
-" \n"
-" float4 s;\n"
-" s = (smallAabb.m_max+smallAabb.m_min)*0.5f;\n"
-" sum[i]=s;\n"
-" sum2[i]=s*s; \n"
-"}\n"
-;
+static const char* sapCL =
+ "/*\n"
+ "Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
+ "This software is provided 'as-is', without any express or implied warranty.\n"
+ "In no event will the authors be held liable for any damages arising from the use of this software.\n"
+ "Permission is granted to anyone to use this software for any purpose, \n"
+ "including commercial applications, and to alter it and redistribute it freely, \n"
+ "subject to the following restrictions:\n"
+ "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
+ "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+ "3. This notice may not be removed or altered from any source distribution.\n"
+ "*/\n"
+ "//Originally written by Erwin Coumans\n"
+ "#define NEW_PAIR_MARKER -1\n"
+ "typedef struct \n"
+ "{\n"
+ " union\n"
+ " {\n"
+ " float4 m_min;\n"
+ " float m_minElems[4];\n"
+ " int m_minIndices[4];\n"
+ " };\n"
+ " union\n"
+ " {\n"
+ " float4 m_max;\n"
+ " float m_maxElems[4];\n"
+ " int m_maxIndices[4];\n"
+ " };\n"
+ "} btAabbCL;\n"
+ "/// conservative test for overlap between two aabbs\n"
+ "bool TestAabbAgainstAabb2(const btAabbCL* aabb1, __local const btAabbCL* aabb2);\n"
+ "bool TestAabbAgainstAabb2(const btAabbCL* aabb1, __local const btAabbCL* aabb2)\n"
+ "{\n"
+ " bool overlap = true;\n"
+ " overlap = (aabb1->m_min.x > aabb2->m_max.x || aabb1->m_max.x < aabb2->m_min.x) ? false : overlap;\n"
+ " overlap = (aabb1->m_min.z > aabb2->m_max.z || aabb1->m_max.z < aabb2->m_min.z) ? false : overlap;\n"
+ " overlap = (aabb1->m_min.y > aabb2->m_max.y || aabb1->m_max.y < aabb2->m_min.y) ? false : overlap;\n"
+ " return overlap;\n"
+ "}\n"
+ "bool TestAabbAgainstAabb2GlobalGlobal(__global const btAabbCL* aabb1, __global const btAabbCL* aabb2);\n"
+ "bool TestAabbAgainstAabb2GlobalGlobal(__global const btAabbCL* aabb1, __global const btAabbCL* aabb2)\n"
+ "{\n"
+ " bool overlap = true;\n"
+ " overlap = (aabb1->m_min.x > aabb2->m_max.x || aabb1->m_max.x < aabb2->m_min.x) ? false : overlap;\n"
+ " overlap = (aabb1->m_min.z > aabb2->m_max.z || aabb1->m_max.z < aabb2->m_min.z) ? false : overlap;\n"
+ " overlap = (aabb1->m_min.y > aabb2->m_max.y || aabb1->m_max.y < aabb2->m_min.y) ? false : overlap;\n"
+ " return overlap;\n"
+ "}\n"
+ "bool TestAabbAgainstAabb2Global(const btAabbCL* aabb1, __global const btAabbCL* aabb2);\n"
+ "bool TestAabbAgainstAabb2Global(const btAabbCL* aabb1, __global const btAabbCL* aabb2)\n"
+ "{\n"
+ " bool overlap = true;\n"
+ " overlap = (aabb1->m_min.x > aabb2->m_max.x || aabb1->m_max.x < aabb2->m_min.x) ? false : overlap;\n"
+ " overlap = (aabb1->m_min.z > aabb2->m_max.z || aabb1->m_max.z < aabb2->m_min.z) ? false : overlap;\n"
+ " overlap = (aabb1->m_min.y > aabb2->m_max.y || aabb1->m_max.y < aabb2->m_min.y) ? false : overlap;\n"
+ " return overlap;\n"
+ "}\n"
+ "__kernel void computePairsKernelTwoArrays( __global const btAabbCL* unsortedAabbs, __global const int* unsortedAabbMapping, __global const int* unsortedAabbMapping2, volatile __global int4* pairsOut,volatile __global int* pairCount, int numUnsortedAabbs, int numUnSortedAabbs2, int axis, int maxPairs)\n"
+ "{\n"
+ " int i = get_global_id(0);\n"
+ " if (i>=numUnsortedAabbs)\n"
+ " return;\n"
+ " int j = get_global_id(1);\n"
+ " if (j>=numUnSortedAabbs2)\n"
+ " return;\n"
+ " __global const btAabbCL* unsortedAabbPtr = &unsortedAabbs[unsortedAabbMapping[i]];\n"
+ " __global const btAabbCL* unsortedAabbPtr2 = &unsortedAabbs[unsortedAabbMapping2[j]];\n"
+ " if (TestAabbAgainstAabb2GlobalGlobal(unsortedAabbPtr,unsortedAabbPtr2))\n"
+ " {\n"
+ " int4 myPair;\n"
+ " \n"
+ " int xIndex = unsortedAabbPtr[0].m_minIndices[3];\n"
+ " int yIndex = unsortedAabbPtr2[0].m_minIndices[3];\n"
+ " if (xIndex>yIndex)\n"
+ " {\n"
+ " int tmp = xIndex;\n"
+ " xIndex=yIndex;\n"
+ " yIndex=tmp;\n"
+ " }\n"
+ " \n"
+ " myPair.x = xIndex;\n"
+ " myPair.y = yIndex;\n"
+ " myPair.z = NEW_PAIR_MARKER;\n"
+ " myPair.w = NEW_PAIR_MARKER;\n"
+ " int curPair = atomic_inc (pairCount);\n"
+ " if (curPair<maxPairs)\n"
+ " {\n"
+ " pairsOut[curPair] = myPair; //flush to main memory\n"
+ " }\n"
+ " }\n"
+ "}\n"
+ "__kernel void computePairsKernelBruteForce( __global const btAabbCL* aabbs, volatile __global int4* pairsOut,volatile __global int* pairCount, int numObjects, int axis, int maxPairs)\n"
+ "{\n"
+ " int i = get_global_id(0);\n"
+ " if (i>=numObjects)\n"
+ " return;\n"
+ " for (int j=i+1;j<numObjects;j++)\n"
+ " {\n"
+ " if (TestAabbAgainstAabb2GlobalGlobal(&aabbs[i],&aabbs[j]))\n"
+ " {\n"
+ " int4 myPair;\n"
+ " myPair.x = aabbs[i].m_minIndices[3];\n"
+ " myPair.y = aabbs[j].m_minIndices[3];\n"
+ " myPair.z = NEW_PAIR_MARKER;\n"
+ " myPair.w = NEW_PAIR_MARKER;\n"
+ " int curPair = atomic_inc (pairCount);\n"
+ " if (curPair<maxPairs)\n"
+ " {\n"
+ " pairsOut[curPair] = myPair; //flush to main memory\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ "}\n"
+ "__kernel void computePairsKernelOriginal( __global const btAabbCL* aabbs, volatile __global int4* pairsOut,volatile __global int* pairCount, int numObjects, int axis, int maxPairs)\n"
+ "{\n"
+ " int i = get_global_id(0);\n"
+ " if (i>=numObjects)\n"
+ " return;\n"
+ " for (int j=i+1;j<numObjects;j++)\n"
+ " {\n"
+ " if(aabbs[i].m_maxElems[axis] < (aabbs[j].m_minElems[axis])) \n"
+ " {\n"
+ " break;\n"
+ " }\n"
+ " if (TestAabbAgainstAabb2GlobalGlobal(&aabbs[i],&aabbs[j]))\n"
+ " {\n"
+ " int4 myPair;\n"
+ " myPair.x = aabbs[i].m_minIndices[3];\n"
+ " myPair.y = aabbs[j].m_minIndices[3];\n"
+ " myPair.z = NEW_PAIR_MARKER;\n"
+ " myPair.w = NEW_PAIR_MARKER;\n"
+ " int curPair = atomic_inc (pairCount);\n"
+ " if (curPair<maxPairs)\n"
+ " {\n"
+ " pairsOut[curPair] = myPair; //flush to main memory\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ "}\n"
+ "__kernel void computePairsKernelBarrier( __global const btAabbCL* aabbs, volatile __global int4* pairsOut,volatile __global int* pairCount, int numObjects, int axis, int maxPairs)\n"
+ "{\n"
+ " int i = get_global_id(0);\n"
+ " int localId = get_local_id(0);\n"
+ " __local int numActiveWgItems[1];\n"
+ " __local int breakRequest[1];\n"
+ " if (localId==0)\n"
+ " {\n"
+ " numActiveWgItems[0] = 0;\n"
+ " breakRequest[0] = 0;\n"
+ " }\n"
+ " barrier(CLK_LOCAL_MEM_FENCE);\n"
+ " atomic_inc(numActiveWgItems);\n"
+ " barrier(CLK_LOCAL_MEM_FENCE);\n"
+ " int localBreak = 0;\n"
+ " int j=i+1;\n"
+ " do\n"
+ " {\n"
+ " barrier(CLK_LOCAL_MEM_FENCE);\n"
+ " \n"
+ " if (j<numObjects)\n"
+ " {\n"
+ " if(aabbs[i].m_maxElems[axis] < (aabbs[j].m_minElems[axis])) \n"
+ " {\n"
+ " if (!localBreak)\n"
+ " {\n"
+ " atomic_inc(breakRequest);\n"
+ " localBreak = 1;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " \n"
+ " barrier(CLK_LOCAL_MEM_FENCE);\n"
+ " \n"
+ " if (j>=numObjects && !localBreak)\n"
+ " {\n"
+ " atomic_inc(breakRequest);\n"
+ " localBreak = 1;\n"
+ " }\n"
+ " barrier(CLK_LOCAL_MEM_FENCE);\n"
+ " \n"
+ " if (!localBreak)\n"
+ " {\n"
+ " if (TestAabbAgainstAabb2GlobalGlobal(&aabbs[i],&aabbs[j]))\n"
+ " {\n"
+ " int4 myPair;\n"
+ " myPair.x = aabbs[i].m_minIndices[3];\n"
+ " myPair.y = aabbs[j].m_minIndices[3];\n"
+ " myPair.z = NEW_PAIR_MARKER;\n"
+ " myPair.w = NEW_PAIR_MARKER;\n"
+ " int curPair = atomic_inc (pairCount);\n"
+ " if (curPair<maxPairs)\n"
+ " {\n"
+ " pairsOut[curPair] = myPair; //flush to main memory\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " j++;\n"
+ " } while (breakRequest[0]<numActiveWgItems[0]);\n"
+ "}\n"
+ "__kernel void computePairsKernelLocalSharedMemory( __global const btAabbCL* aabbs, volatile __global int4* pairsOut,volatile __global int* pairCount, int numObjects, int axis, int maxPairs)\n"
+ "{\n"
+ " int i = get_global_id(0);\n"
+ " int localId = get_local_id(0);\n"
+ " __local int numActiveWgItems[1];\n"
+ " __local int breakRequest[1];\n"
+ " __local btAabbCL localAabbs[128];// = aabbs[i];\n"
+ " \n"
+ " btAabbCL myAabb;\n"
+ " \n"
+ " myAabb = (i<numObjects)? aabbs[i]:aabbs[0];\n"
+ " float testValue = myAabb.m_maxElems[axis];\n"
+ " \n"
+ " if (localId==0)\n"
+ " {\n"
+ " numActiveWgItems[0] = 0;\n"
+ " breakRequest[0] = 0;\n"
+ " }\n"
+ " int localCount=0;\n"
+ " int block=0;\n"
+ " localAabbs[localId] = (i+block)<numObjects? aabbs[i+block] : aabbs[0];\n"
+ " localAabbs[localId+64] = (i+block+64)<numObjects? aabbs[i+block+64]: aabbs[0];\n"
+ " \n"
+ " barrier(CLK_LOCAL_MEM_FENCE);\n"
+ " atomic_inc(numActiveWgItems);\n"
+ " barrier(CLK_LOCAL_MEM_FENCE);\n"
+ " int localBreak = 0;\n"
+ " \n"
+ " int j=i+1;\n"
+ " do\n"
+ " {\n"
+ " barrier(CLK_LOCAL_MEM_FENCE);\n"
+ " \n"
+ " if (j<numObjects)\n"
+ " {\n"
+ " if(testValue < (localAabbs[localCount+localId+1].m_minElems[axis])) \n"
+ " {\n"
+ " if (!localBreak)\n"
+ " {\n"
+ " atomic_inc(breakRequest);\n"
+ " localBreak = 1;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " \n"
+ " barrier(CLK_LOCAL_MEM_FENCE);\n"
+ " \n"
+ " if (j>=numObjects && !localBreak)\n"
+ " {\n"
+ " atomic_inc(breakRequest);\n"
+ " localBreak = 1;\n"
+ " }\n"
+ " barrier(CLK_LOCAL_MEM_FENCE);\n"
+ " \n"
+ " if (!localBreak)\n"
+ " {\n"
+ " if (TestAabbAgainstAabb2(&myAabb,&localAabbs[localCount+localId+1]))\n"
+ " {\n"
+ " int4 myPair;\n"
+ " myPair.x = myAabb.m_minIndices[3];\n"
+ " myPair.y = localAabbs[localCount+localId+1].m_minIndices[3];\n"
+ " myPair.z = NEW_PAIR_MARKER;\n"
+ " myPair.w = NEW_PAIR_MARKER;\n"
+ " int curPair = atomic_inc (pairCount);\n"
+ " if (curPair<maxPairs)\n"
+ " {\n"
+ " pairsOut[curPair] = myPair; //flush to main memory\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " \n"
+ " barrier(CLK_LOCAL_MEM_FENCE);\n"
+ " localCount++;\n"
+ " if (localCount==64)\n"
+ " {\n"
+ " localCount = 0;\n"
+ " block+=64; \n"
+ " localAabbs[localId] = ((i+block)<numObjects) ? aabbs[i+block] : aabbs[0];\n"
+ " localAabbs[localId+64] = ((i+64+block)<numObjects) ? aabbs[i+block+64] : aabbs[0];\n"
+ " }\n"
+ " j++;\n"
+ " \n"
+ " } while (breakRequest[0]<numActiveWgItems[0]);\n"
+ " \n"
+ "}\n"
+ "//http://stereopsis.com/radix.html\n"
+ "unsigned int FloatFlip(float fl);\n"
+ "unsigned int FloatFlip(float fl)\n"
+ "{\n"
+ " unsigned int f = *(unsigned int*)&fl;\n"
+ " unsigned int mask = -(int)(f >> 31) | 0x80000000;\n"
+ " return f ^ mask;\n"
+ "}\n"
+ "float IFloatFlip(unsigned int f);\n"
+ "float IFloatFlip(unsigned int f)\n"
+ "{\n"
+ " unsigned int mask = ((f >> 31) - 1) | 0x80000000;\n"
+ " unsigned int fl = f ^ mask;\n"
+ " return *(float*)&fl;\n"
+ "}\n"
+ "__kernel void copyAabbsKernel( __global const btAabbCL* allAabbs, __global btAabbCL* destAabbs, int numObjects)\n"
+ "{\n"
+ " int i = get_global_id(0);\n"
+ " if (i>=numObjects)\n"
+ " return;\n"
+ " int src = destAabbs[i].m_maxIndices[3];\n"
+ " destAabbs[i] = allAabbs[src];\n"
+ " destAabbs[i].m_maxIndices[3] = src;\n"
+ "}\n"
+ "__kernel void flipFloatKernel( __global const btAabbCL* allAabbs, __global const int* smallAabbMapping, __global int2* sortData, int numObjects, int axis)\n"
+ "{\n"
+ " int i = get_global_id(0);\n"
+ " if (i>=numObjects)\n"
+ " return;\n"
+ " \n"
+ " \n"
+ " sortData[i].x = FloatFlip(allAabbs[smallAabbMapping[i]].m_minElems[axis]);\n"
+ " sortData[i].y = i;\n"
+ " \n"
+ "}\n"
+ "__kernel void scatterKernel( __global const btAabbCL* allAabbs, __global const int* smallAabbMapping, volatile __global const int2* sortData, __global btAabbCL* sortedAabbs, int numObjects)\n"
+ "{\n"
+ " int i = get_global_id(0);\n"
+ " if (i>=numObjects)\n"
+ " return;\n"
+ " \n"
+ " sortedAabbs[i] = allAabbs[smallAabbMapping[sortData[i].y]];\n"
+ "}\n"
+ "__kernel void prepareSumVarianceKernel( __global const btAabbCL* allAabbs, __global const int* smallAabbMapping, __global float4* sum, __global float4* sum2,int numAabbs)\n"
+ "{\n"
+ " int i = get_global_id(0);\n"
+ " if (i>=numAabbs)\n"
+ " return;\n"
+ " \n"
+ " btAabbCL smallAabb = allAabbs[smallAabbMapping[i]];\n"
+ " \n"
+ " float4 s;\n"
+ " s = (smallAabb.m_max+smallAabb.m_min)*0.5f;\n"
+ " sum[i]=s;\n"
+ " sum2[i]=s*s; \n"
+ "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/Initialize/b3OpenCLInclude.h b/thirdparty/bullet/Bullet3OpenCL/Initialize/b3OpenCLInclude.h
index e79182d7cb..6146538263 100644
--- a/thirdparty/bullet/Bullet3OpenCL/Initialize/b3OpenCLInclude.h
+++ b/thirdparty/bullet/Bullet3OpenCL/Initialize/b3OpenCLInclude.h
@@ -17,7 +17,7 @@ subject to the following restrictions:
#define B3_OPENCL_INCLUDE_H
#ifdef B3_USE_CLEW
- #include "clew/clew.h"
+#include "clew/clew.h"
#else
#ifdef __APPLE__
@@ -25,7 +25,7 @@ subject to the following restrictions:
#include <MiniCL/cl.h>
#else
#include <OpenCL/cl.h>
-#include <OpenCL/cl_ext.h> //clLogMessagesToStderrAPPLE
+#include <OpenCL/cl_ext.h> //clLogMessagesToStderrAPPLE
#endif
#else
#ifdef USE_MINICL
@@ -34,15 +34,18 @@ subject to the following restrictions:
#include <CL/cl.h>
#ifdef _WIN32
#include "CL/cl_gl.h"
-#endif //_WIN32
+#endif //_WIN32
#endif
-#endif //__APPLE__
-#endif //B3_USE_CLEW
+#endif //__APPLE__
+#endif //B3_USE_CLEW
#include <assert.h>
#include <stdio.h>
-#define oclCHECKERROR(a, b) if((a)!=(b)) { printf("OCL Error : %d\n", (a)); assert((a) == (b)); }
-
-
-#endif //B3_OPENCL_INCLUDE_H
-
+#define oclCHECKERROR(a, b) \
+ if ((a) != (b)) \
+ { \
+ printf("OCL Error : %d\n", (a)); \
+ assert((a) == (b)); \
+ }
+
+#endif //B3_OPENCL_INCLUDE_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/Initialize/b3OpenCLUtils.cpp b/thirdparty/bullet/Bullet3OpenCL/Initialize/b3OpenCLUtils.cpp
index 896191c89c..fe54ea5ec9 100644
--- a/thirdparty/bullet/Bullet3OpenCL/Initialize/b3OpenCLUtils.cpp
+++ b/thirdparty/bullet/Bullet3OpenCL/Initialize/b3OpenCLUtils.cpp
@@ -16,7 +16,6 @@ subject to the following restrictions:
//Original author: Roman Ponomarev
//Mostly Reimplemented by Erwin Coumans
-
bool gDebugForceLoadingFromSource = false;
bool gDebugSkipLoadingBinary = false;
@@ -25,7 +24,7 @@ bool gDebugSkipLoadingBinary = false;
#include <string.h>
#ifdef _WIN32
-#pragma warning (disable:4996)
+#pragma warning(disable : 4996)
#endif
#include "b3OpenCLUtils.h"
//#include "b3OpenCLInclude.h"
@@ -33,7 +32,7 @@ bool gDebugSkipLoadingBinary = false;
#include <stdio.h>
#include <stdlib.h>
-#define B3_MAX_CL_DEVICES 16 //who needs 16 devices?
+#define B3_MAX_CL_DEVICES 16 //who needs 16 devices?
#ifdef _WIN32
#include <windows.h>
@@ -46,53 +45,49 @@ bool gDebugSkipLoadingBinary = false;
#endif
-static const char* sCachedBinaryPath="cache";
-
+static const char* sCachedBinaryPath = "cache";
//Set the preferred platform vendor using the OpenCL SDK
static const char* spPlatformVendor =
#if defined(CL_PLATFORM_MINI_CL)
-"MiniCL, SCEA";
+ "MiniCL, SCEA";
#elif defined(CL_PLATFORM_AMD)
-"Advanced Micro Devices, Inc.";
+ "Advanced Micro Devices, Inc.";
#elif defined(CL_PLATFORM_NVIDIA)
-"NVIDIA Corporation";
+ "NVIDIA Corporation";
#elif defined(CL_PLATFORM_INTEL)
-"Intel(R) Corporation";
+ "Intel(R) Corporation";
#elif defined(B3_USE_CLEW)
-"clew (OpenCL Extension Wrangler library)";
+ "clew (OpenCL Extension Wrangler library)";
#else
-"Unknown Vendor";
+ "Unknown Vendor";
#endif
#ifndef CL_PLATFORM_MINI_CL
#ifdef _WIN32
#ifndef B3_USE_CLEW
#include "CL/cl_gl.h"
-#endif //B3_USE_CLEW
-#endif //_WIN32
+#endif //B3_USE_CLEW
+#endif //_WIN32
#endif
-
-void MyFatalBreakAPPLE( const char * errstr ,
- const void * private_info ,
- size_t cb ,
- void * user_data )
+void MyFatalBreakAPPLE(const char* errstr,
+ const void* private_info,
+ size_t cb,
+ void* user_data)
{
-
-
- const char* patloc = strstr(errstr, "Warning");
- //find out if it is a warning or error, exit if error
+ const char* patloc = strstr(errstr, "Warning");
+ //find out if it is a warning or error, exit if error
- if (patloc)
- {
+ if (patloc)
+ {
b3Warning("Warning: %s\n", errstr);
- } else
- {
+ }
+ else
+ {
b3Error("Error: %s\n", errstr);
- b3Assert(0);
- }
-
+ b3Assert(0);
+ }
}
#ifdef B3_USE_CLEW
@@ -102,30 +97,31 @@ int b3OpenCLUtils_clewInit()
int result = -1;
#ifdef _WIN32
- const char* cl = "OpenCL.dll";
+ const char* cl = "OpenCL.dll";
#elif defined __APPLE__
- const char* cl = "/System/Library/Frameworks/OpenCL.framework/Versions/Current/OpenCL";
-#else//presumable Linux?
- //linux (tested on Ubuntu 12.10 with Catalyst 13.4 beta drivers, not that there is no symbolic link from libOpenCL.so
- const char* cl = "libOpenCL.so.1";
- result = clewInit(cl);
- if (result != CLEW_SUCCESS)
- {
- cl = "libOpenCL.so";
- } else
- {
- clewExit();
- }
+ const char* cl = "/System/Library/Frameworks/OpenCL.framework/Versions/Current/OpenCL";
+#else //presumable Linux? \
+ //linux (tested on Ubuntu 12.10 with Catalyst 13.4 beta drivers, not that there is no symbolic link from libOpenCL.so
+ const char* cl = "libOpenCL.so.1";
+ result = clewInit(cl);
+ if (result != CLEW_SUCCESS)
+ {
+ cl = "libOpenCL.so";
+ }
+ else
+ {
+ clewExit();
+ }
#endif
- result = clewInit(cl);
- if (result!=CLEW_SUCCESS)
- {
- b3Error("clewInit failed with error code %d\n",result);
- }
- else
- {
- b3Printf("clewInit succesfull using %s\n",cl);
- }
+ result = clewInit(cl);
+ if (result != CLEW_SUCCESS)
+ {
+ b3Error("clewInit failed with error code %d\n", result);
+ }
+ else
+ {
+ b3Printf("clewInit succesfull using %s\n", cl);
+ }
return result;
}
#endif
@@ -136,19 +132,18 @@ int b3OpenCLUtils_getNumPlatforms(cl_int* pErrNum)
b3OpenCLUtils_clewInit();
#endif
- cl_platform_id pPlatforms[10] = { 0 };
+ cl_platform_id pPlatforms[10] = {0};
- cl_uint numPlatforms = 0;
- cl_int ciErrNum = clGetPlatformIDs(10, pPlatforms, &numPlatforms);
+ cl_uint numPlatforms = 0;
+ cl_int ciErrNum = clGetPlatformIDs(10, pPlatforms, &numPlatforms);
//cl_int ciErrNum = clGetPlatformIDs(0, NULL, &numPlatforms);
- if(ciErrNum != CL_SUCCESS)
+ if (ciErrNum != CL_SUCCESS)
{
- if(pErrNum != NULL)
+ if (pErrNum != NULL)
*pErrNum = ciErrNum;
}
return numPlatforms;
-
}
const char* b3OpenCLUtils_getSdkVendorName()
@@ -164,28 +159,28 @@ void b3OpenCLUtils_setCachePath(const char* path)
cl_platform_id b3OpenCLUtils_getPlatform(int platformIndex0, cl_int* pErrNum)
{
#ifdef B3_USE_CLEW
- b3OpenCLUtils_clewInit();
+ b3OpenCLUtils_clewInit();
#endif
cl_platform_id platform = 0;
- unsigned int platformIndex = (unsigned int )platformIndex0;
+ unsigned int platformIndex = (unsigned int)platformIndex0;
cl_uint numPlatforms;
cl_int ciErrNum = clGetPlatformIDs(0, NULL, &numPlatforms);
- if (platformIndex<numPlatforms)
+ if (platformIndex < numPlatforms)
{
- cl_platform_id* platforms = (cl_platform_id*) malloc (sizeof(cl_platform_id)*numPlatforms);
+ cl_platform_id* platforms = (cl_platform_id*)malloc(sizeof(cl_platform_id) * numPlatforms);
ciErrNum = clGetPlatformIDs(numPlatforms, platforms, NULL);
- if(ciErrNum != CL_SUCCESS)
+ if (ciErrNum != CL_SUCCESS)
{
- if(pErrNum != NULL)
+ if (pErrNum != NULL)
*pErrNum = ciErrNum;
return platform;
}
platform = platforms[platformIndex];
- free (platforms);
+ free(platforms);
}
return platform;
@@ -195,30 +190,28 @@ void b3OpenCLUtils::getPlatformInfo(cl_platform_id platform, b3OpenCLPlatformInf
{
b3Assert(platform);
cl_int ciErrNum;
- ciErrNum = clGetPlatformInfo( platform,CL_PLATFORM_VENDOR,B3_MAX_STRING_LENGTH,platformInfo->m_platformVendor,NULL);
- oclCHECKERROR(ciErrNum,CL_SUCCESS);
- ciErrNum = clGetPlatformInfo( platform,CL_PLATFORM_NAME,B3_MAX_STRING_LENGTH,platformInfo->m_platformName,NULL);
- oclCHECKERROR(ciErrNum,CL_SUCCESS);
- ciErrNum = clGetPlatformInfo( platform,CL_PLATFORM_VERSION,B3_MAX_STRING_LENGTH,platformInfo->m_platformVersion,NULL);
- oclCHECKERROR(ciErrNum,CL_SUCCESS);
+ ciErrNum = clGetPlatformInfo(platform, CL_PLATFORM_VENDOR, B3_MAX_STRING_LENGTH, platformInfo->m_platformVendor, NULL);
+ oclCHECKERROR(ciErrNum, CL_SUCCESS);
+ ciErrNum = clGetPlatformInfo(platform, CL_PLATFORM_NAME, B3_MAX_STRING_LENGTH, platformInfo->m_platformName, NULL);
+ oclCHECKERROR(ciErrNum, CL_SUCCESS);
+ ciErrNum = clGetPlatformInfo(platform, CL_PLATFORM_VERSION, B3_MAX_STRING_LENGTH, platformInfo->m_platformVersion, NULL);
+ oclCHECKERROR(ciErrNum, CL_SUCCESS);
}
-void b3OpenCLUtils_printPlatformInfo( cl_platform_id platform)
+void b3OpenCLUtils_printPlatformInfo(cl_platform_id platform)
{
b3OpenCLPlatformInfo platformInfo;
- b3OpenCLUtils::getPlatformInfo (platform, &platformInfo);
+ b3OpenCLUtils::getPlatformInfo(platform, &platformInfo);
b3Printf("Platform info:\n");
- b3Printf(" CL_PLATFORM_VENDOR: \t\t\t%s\n",platformInfo.m_platformVendor);
- b3Printf(" CL_PLATFORM_NAME: \t\t\t%s\n",platformInfo.m_platformName);
- b3Printf(" CL_PLATFORM_VERSION: \t\t\t%s\n",platformInfo.m_platformVersion);
+ b3Printf(" CL_PLATFORM_VENDOR: \t\t\t%s\n", platformInfo.m_platformVendor);
+ b3Printf(" CL_PLATFORM_NAME: \t\t\t%s\n", platformInfo.m_platformName);
+ b3Printf(" CL_PLATFORM_VERSION: \t\t\t%s\n", platformInfo.m_platformVersion);
}
-
-
cl_context b3OpenCLUtils_createContextFromPlatform(cl_platform_id platform, cl_device_type deviceType, cl_int* pErrNum, void* pGLContext, void* pGLDC, int preferredDeviceIndex, int preferredPlatformIndex)
{
cl_context retContext = 0;
- cl_int ciErrNum=0;
+ cl_int ciErrNum = 0;
cl_uint num_entries;
cl_device_id devices[B3_MAX_CL_DEVICES];
cl_uint num_devices;
@@ -228,7 +221,7 @@ cl_context b3OpenCLUtils_createContextFromPlatform(cl_platform_id platform, cl_d
* If we could find our platform, use it. Otherwise pass a NULL and get whatever the
* implementation thinks we should be using.
*/
- cl_context_properties cps[7] = {0,0,0,0,0,0,0};
+ cl_context_properties cps[7] = {0, 0, 0, 0, 0, 0, 0};
cps[0] = CL_CONTEXT_PLATFORM;
cps[1] = (cl_context_properties)platform;
#ifdef _WIN32
@@ -240,25 +233,24 @@ cl_context b3OpenCLUtils_createContextFromPlatform(cl_platform_id platform, cl_d
cps[4] = CL_WGL_HDC_KHR;
cps[5] = (cl_context_properties)pGLDC;
}
-#endif //B3_USE_CLEW
-#endif //_WIN32
+#endif //B3_USE_CLEW
+#endif //_WIN32
num_entries = B3_MAX_CL_DEVICES;
-
- num_devices=-1;
+ num_devices = -1;
ciErrNum = clGetDeviceIDs(
platform,
deviceType,
- num_entries,
- devices,
- &num_devices);
-
- if (ciErrNum<0)
- {
- b3Printf("clGetDeviceIDs returned %d\n",ciErrNum);
- return 0;
- }
+ num_entries,
+ devices,
+ &num_devices);
+
+ if (ciErrNum < 0)
+ {
+ b3Printf("clGetDeviceIDs returned %d\n", ciErrNum);
+ return 0;
+ }
cprops = (NULL == platform) ? NULL : cps;
if (!num_devices)
@@ -268,32 +260,33 @@ cl_context b3OpenCLUtils_createContextFromPlatform(cl_platform_id platform, cl_d
{
//search for the GPU that relates to the OpenCL context
unsigned int i;
- for (i=0;i<num_devices;i++)
+ for (i = 0; i < num_devices; i++)
{
- retContext = clCreateContext(cprops,1,&devices[i],NULL,NULL,&ciErrNum);
- if (ciErrNum==CL_SUCCESS)
+ retContext = clCreateContext(cprops, 1, &devices[i], NULL, NULL, &ciErrNum);
+ if (ciErrNum == CL_SUCCESS)
break;
}
}
else
{
- if (preferredDeviceIndex>=0 && (unsigned int)preferredDeviceIndex<num_devices)
+ if (preferredDeviceIndex >= 0 && (unsigned int)preferredDeviceIndex < num_devices)
{
//create a context of the preferred device index
- retContext = clCreateContext(cprops,1,&devices[preferredDeviceIndex],NULL,NULL,&ciErrNum);
- } else
+ retContext = clCreateContext(cprops, 1, &devices[preferredDeviceIndex], NULL, NULL, &ciErrNum);
+ }
+ else
{
//create a context of all devices
-#if defined (__APPLE__)
- retContext = clCreateContext(cprops,num_devices,devices,MyFatalBreakAPPLE,NULL,&ciErrNum);
+#if defined(__APPLE__)
+ retContext = clCreateContext(cprops, num_devices, devices, MyFatalBreakAPPLE, NULL, &ciErrNum);
#else
- b3Printf("numDevices=%d\n",num_devices);
+ b3Printf("numDevices=%d\n", num_devices);
- retContext = clCreateContext(cprops,num_devices,devices,NULL,NULL,&ciErrNum);
+ retContext = clCreateContext(cprops, num_devices, devices, NULL, NULL, &ciErrNum);
#endif
}
}
- if(pErrNum != NULL)
+ if (pErrNum != NULL)
{
*pErrNum = ciErrNum;
};
@@ -301,60 +294,58 @@ cl_context b3OpenCLUtils_createContextFromPlatform(cl_platform_id platform, cl_d
return retContext;
}
-cl_context b3OpenCLUtils_createContextFromType(cl_device_type deviceType, cl_int* pErrNum, void* pGLContext, void* pGLDC , int preferredDeviceIndex, int preferredPlatformIndex, cl_platform_id* retPlatformId)
+cl_context b3OpenCLUtils_createContextFromType(cl_device_type deviceType, cl_int* pErrNum, void* pGLContext, void* pGLDC, int preferredDeviceIndex, int preferredPlatformIndex, cl_platform_id* retPlatformId)
{
#ifdef B3_USE_CLEW
- b3OpenCLUtils_clewInit();
+ b3OpenCLUtils_clewInit();
#endif
-
cl_uint numPlatforms;
cl_context retContext = 0;
unsigned int i;
cl_int ciErrNum = clGetPlatformIDs(0, NULL, &numPlatforms);
- if(ciErrNum != CL_SUCCESS)
+ if (ciErrNum != CL_SUCCESS)
{
- if(pErrNum != NULL) *pErrNum = ciErrNum;
+ if (pErrNum != NULL) *pErrNum = ciErrNum;
return NULL;
}
- if(numPlatforms > 0)
+ if (numPlatforms > 0)
{
- cl_platform_id* platforms = (cl_platform_id*) malloc (sizeof(cl_platform_id)*numPlatforms);
+ cl_platform_id* platforms = (cl_platform_id*)malloc(sizeof(cl_platform_id) * numPlatforms);
ciErrNum = clGetPlatformIDs(numPlatforms, platforms, NULL);
- if(ciErrNum != CL_SUCCESS)
+ if (ciErrNum != CL_SUCCESS)
{
- if(pErrNum != NULL)
+ if (pErrNum != NULL)
*pErrNum = ciErrNum;
free(platforms);
return NULL;
}
-
-
- for ( i = 0; i < numPlatforms; ++i)
+ for (i = 0; i < numPlatforms; ++i)
{
char pbuf[128];
- ciErrNum = clGetPlatformInfo( platforms[i],
- CL_PLATFORM_VENDOR,
- sizeof(pbuf),
- pbuf,
- NULL);
- if(ciErrNum != CL_SUCCESS)
+ ciErrNum = clGetPlatformInfo(platforms[i],
+ CL_PLATFORM_VENDOR,
+ sizeof(pbuf),
+ pbuf,
+ NULL);
+ if (ciErrNum != CL_SUCCESS)
{
- if(pErrNum != NULL) *pErrNum = ciErrNum;
+ if (pErrNum != NULL) *pErrNum = ciErrNum;
return NULL;
}
- if (preferredPlatformIndex>=0 && i==preferredPlatformIndex)
+ if (preferredPlatformIndex >= 0 && i == preferredPlatformIndex)
{
cl_platform_id tmpPlatform = platforms[0];
platforms[0] = platforms[i];
platforms[i] = tmpPlatform;
break;
- } else
+ }
+ else
{
- if(!strcmp(pbuf, spPlatformVendor))
+ if (!strcmp(pbuf, spPlatformVendor))
{
cl_platform_id tmpPlatform = platforms[0];
platforms[0] = platforms[i];
@@ -368,11 +359,11 @@ cl_context b3OpenCLUtils_createContextFromType(cl_device_type deviceType, cl_int
cl_platform_id platform = platforms[i];
assert(platform);
- retContext = b3OpenCLUtils_createContextFromPlatform(platform,deviceType,pErrNum,pGLContext,pGLDC,preferredDeviceIndex,preferredPlatformIndex);
+ retContext = b3OpenCLUtils_createContextFromPlatform(platform, deviceType, pErrNum, pGLContext, pGLDC, preferredDeviceIndex, preferredPlatformIndex);
if (retContext)
{
-// printf("OpenCL platform details:\n");
+ // printf("OpenCL platform details:\n");
b3OpenCLPlatformInfo platformInfo;
b3OpenCLUtils::getPlatformInfo(platform, &platformInfo);
@@ -384,12 +375,11 @@ cl_context b3OpenCLUtils_createContextFromType(cl_device_type deviceType, cl_int
}
}
- free (platforms);
+ free(platforms);
}
return retContext;
}
-
//////////////////////////////////////////////////////////////////////////////
//! Gets the id of the nth device from the context
//!
@@ -403,16 +393,17 @@ cl_device_id b3OpenCLUtils_getDevice(cl_context cxMainContext, int deviceIndex)
size_t szParmDataBytes;
cl_device_id* cdDevices;
- cl_device_id device ;
+ cl_device_id device;
// get the list of devices associated with context
clGetContextInfo(cxMainContext, CL_CONTEXT_DEVICES, 0, NULL, &szParmDataBytes);
- if( szParmDataBytes / sizeof(cl_device_id) < (unsigned int)deviceIndex ) {
+ if (szParmDataBytes / sizeof(cl_device_id) < (unsigned int)deviceIndex)
+ {
return (cl_device_id)-1;
}
- cdDevices = (cl_device_id*) malloc(szParmDataBytes);
+ cdDevices = (cl_device_id*)malloc(szParmDataBytes);
clGetContextInfo(cxMainContext, CL_CONTEXT_DEVICES, szParmDataBytes, cdDevices, NULL);
@@ -427,12 +418,10 @@ int b3OpenCLUtils_getNumDevices(cl_context cxMainContext)
size_t szParamDataBytes;
int device_count;
clGetContextInfo(cxMainContext, CL_CONTEXT_DEVICES, 0, NULL, &szParamDataBytes);
- device_count = (int) szParamDataBytes/ sizeof(cl_device_id);
+ device_count = (int)szParamDataBytes / sizeof(cl_device_id);
return device_count;
}
-
-
void b3OpenCLUtils::getDeviceInfo(cl_device_id device, b3OpenCLDeviceInfo* info)
{
// CL_DEVICE_NAME
@@ -514,23 +503,22 @@ void b3OpenCLUtils::getDeviceInfo(cl_device_id device, b3OpenCLDeviceInfo* info)
clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE, sizeof(cl_uint), &info->m_vecWidthDouble, NULL);
}
-
void b3OpenCLUtils_printDeviceInfo(cl_device_id device)
{
b3OpenCLDeviceInfo info;
- b3OpenCLUtils::getDeviceInfo(device,&info);
+ b3OpenCLUtils::getDeviceInfo(device, &info);
b3Printf("Device Info:\n");
b3Printf(" CL_DEVICE_NAME: \t\t\t%s\n", info.m_deviceName);
b3Printf(" CL_DEVICE_VENDOR: \t\t\t%s\n", info.m_deviceVendor);
b3Printf(" CL_DRIVER_VERSION: \t\t\t%s\n", info.m_driverVersion);
- if( info.m_deviceType & CL_DEVICE_TYPE_CPU )
+ if (info.m_deviceType & CL_DEVICE_TYPE_CPU)
b3Printf(" CL_DEVICE_TYPE:\t\t\t%s\n", "CL_DEVICE_TYPE_CPU");
- if( info.m_deviceType & CL_DEVICE_TYPE_GPU )
+ if (info.m_deviceType & CL_DEVICE_TYPE_GPU)
b3Printf(" CL_DEVICE_TYPE:\t\t\t%s\n", "CL_DEVICE_TYPE_GPU");
- if( info.m_deviceType & CL_DEVICE_TYPE_ACCELERATOR )
+ if (info.m_deviceType & CL_DEVICE_TYPE_ACCELERATOR)
b3Printf(" CL_DEVICE_TYPE:\t\t\t%s\n", "CL_DEVICE_TYPE_ACCELERATOR");
- if( info.m_deviceType & CL_DEVICE_TYPE_DEFAULT )
+ if (info.m_deviceType & CL_DEVICE_TYPE_DEFAULT)
b3Printf(" CL_DEVICE_TYPE:\t\t\t%s\n", "CL_DEVICE_TYPE_DEFAULT");
b3Printf(" CL_DEVICE_MAX_COMPUTE_UNITS:\t\t%u\n", info.m_computeUnits);
@@ -539,15 +527,15 @@ void b3OpenCLUtils_printDeviceInfo(cl_device_id device)
b3Printf(" CL_DEVICE_MAX_WORK_GROUP_SIZE:\t%u\n", info.m_workgroupSize);
b3Printf(" CL_DEVICE_MAX_CLOCK_FREQUENCY:\t%u MHz\n", info.m_clockFrequency);
b3Printf(" CL_DEVICE_ADDRESS_BITS:\t\t%u\n", info.m_addressBits);
- b3Printf(" CL_DEVICE_MAX_MEM_ALLOC_SIZE:\t\t%u MByte\n", (unsigned int)(info.m_maxMemAllocSize/ (1024 * 1024)));
- b3Printf(" CL_DEVICE_GLOBAL_MEM_SIZE:\t\t%u MByte\n", (unsigned int)(info.m_globalMemSize/ (1024 * 1024)));
- b3Printf(" CL_DEVICE_ERROR_CORRECTION_SUPPORT:\t%s\n", info.m_errorCorrectionSupport== CL_TRUE ? "yes" : "no");
+ b3Printf(" CL_DEVICE_MAX_MEM_ALLOC_SIZE:\t\t%u MByte\n", (unsigned int)(info.m_maxMemAllocSize / (1024 * 1024)));
+ b3Printf(" CL_DEVICE_GLOBAL_MEM_SIZE:\t\t%u MByte\n", (unsigned int)(info.m_globalMemSize / (1024 * 1024)));
+ b3Printf(" CL_DEVICE_ERROR_CORRECTION_SUPPORT:\t%s\n", info.m_errorCorrectionSupport == CL_TRUE ? "yes" : "no");
b3Printf(" CL_DEVICE_LOCAL_MEM_TYPE:\t\t%s\n", info.m_localMemType == 1 ? "local" : "global");
b3Printf(" CL_DEVICE_LOCAL_MEM_SIZE:\t\t%u KByte\n", (unsigned int)(info.m_localMemSize / 1024));
b3Printf(" CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE:\t%u KByte\n", (unsigned int)(info.m_constantBufferSize / 1024));
- if( info.m_queueProperties & CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE )
+ if (info.m_queueProperties & CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE)
b3Printf(" CL_DEVICE_QUEUE_PROPERTIES:\t\t%s\n", "CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE");
- if( info.m_queueProperties & CL_QUEUE_PROFILING_ENABLE )
+ if (info.m_queueProperties & CL_QUEUE_PROFILING_ENABLE)
b3Printf(" CL_DEVICE_QUEUE_PROPERTIES:\t\t%s\n", "CL_QUEUE_PROFILING_ENABLE");
b3Printf(" CL_DEVICE_IMAGE_SUPPORT:\t\t%u\n", info.m_imageSupport);
@@ -562,7 +550,7 @@ void b3OpenCLUtils_printDeviceInfo(cl_device_id device)
b3Printf("\t\t\t\t\t3D_MAX_DEPTH\t %u\n", info.m_image3dMaxDepth);
if (*info.m_deviceExtensions != 0)
{
- b3Printf("\n CL_DEVICE_EXTENSIONS:%s\n",info.m_deviceExtensions);
+ b3Printf("\n CL_DEVICE_EXTENSIONS:%s\n", info.m_deviceExtensions);
}
else
{
@@ -570,36 +558,33 @@ void b3OpenCLUtils_printDeviceInfo(cl_device_id device)
}
b3Printf(" CL_DEVICE_PREFERRED_VECTOR_WIDTH_<t>\t");
b3Printf("CHAR %u, SHORT %u, INT %u,LONG %u, FLOAT %u, DOUBLE %u\n\n\n",
- info.m_vecWidthChar, info.m_vecWidthShort, info.m_vecWidthInt, info.m_vecWidthLong,info.m_vecWidthFloat, info.m_vecWidthDouble);
-
-
+ info.m_vecWidthChar, info.m_vecWidthShort, info.m_vecWidthInt, info.m_vecWidthLong, info.m_vecWidthFloat, info.m_vecWidthDouble);
}
-
static const char* strip2(const char* name, const char* pattern)
{
- size_t const patlen = strlen(pattern);
- size_t patcnt = 0;
- const char * oriptr;
- const char * patloc;
- // find how many times the pattern occurs in the original string
- for (oriptr = name; (patloc = strstr(oriptr, pattern)); oriptr = patloc + patlen)
- {
+ size_t const patlen = strlen(pattern);
+ size_t patcnt = 0;
+ const char* oriptr;
+ const char* patloc;
+ // find how many times the pattern occurs in the original string
+ for (oriptr = name; (patloc = strstr(oriptr, pattern)); oriptr = patloc + patlen)
+ {
patcnt++;
- }
- return oriptr;
+ }
+ return oriptr;
}
-cl_program b3OpenCLUtils_compileCLProgramFromString(cl_context clContext, cl_device_id device, const char* kernelSourceOrg, cl_int* pErrNum, const char* additionalMacrosArg , const char* clFileNameForCaching, bool disableBinaryCaching)
+cl_program b3OpenCLUtils_compileCLProgramFromString(cl_context clContext, cl_device_id device, const char* kernelSourceOrg, cl_int* pErrNum, const char* additionalMacrosArg, const char* clFileNameForCaching, bool disableBinaryCaching)
{
- const char* additionalMacros = additionalMacrosArg?additionalMacrosArg:"";
+ const char* additionalMacros = additionalMacrosArg ? additionalMacrosArg : "";
if (disableBinaryCaching)
{
//kernelSourceOrg = 0;
}
- cl_program m_cpProgram=0;
+ cl_program m_cpProgram = 0;
cl_int status;
char binaryFileName[B3_MAX_STRING_LENGTH];
@@ -609,67 +594,64 @@ cl_program b3OpenCLUtils_compileCLProgramFromString(cl_context clContext, cl_dev
const char* strippedName;
int fileUpToDate = 0;
#ifdef _WIN32
- int binaryFileValid=0;
-#endif
+ int binaryFileValid = 0;
+#endif
if (!disableBinaryCaching && clFileNameForCaching)
{
clGetDeviceInfo(device, CL_DEVICE_NAME, 256, &deviceName, NULL);
clGetDeviceInfo(device, CL_DRIVER_VERSION, 256, &driverVersion, NULL);
-
- strippedName = strip2(clFileNameForCaching,"\\");
- strippedName = strip2(strippedName,"/");
-
+
+ strippedName = strip2(clFileNameForCaching, "\\");
+ strippedName = strip2(strippedName, "/");
+
#ifdef _MSC_VER
- sprintf_s(binaryFileName,B3_MAX_STRING_LENGTH,"%s/%s.%s.%s.bin",sCachedBinaryPath,strippedName, deviceName,driverVersion );
+ sprintf_s(binaryFileName, B3_MAX_STRING_LENGTH, "%s/%s.%s.%s.bin", sCachedBinaryPath, strippedName, deviceName, driverVersion);
#else
- sprintf(binaryFileName,"%s/%s.%s.%s.bin",sCachedBinaryPath,strippedName, deviceName,driverVersion );
+ sprintf(binaryFileName, "%s/%s.%s.%s.bin", sCachedBinaryPath, strippedName, deviceName, driverVersion);
#endif
}
- if (clFileNameForCaching && !(disableBinaryCaching || gDebugSkipLoadingBinary||gDebugForceLoadingFromSource) )
+ if (clFileNameForCaching && !(disableBinaryCaching || gDebugSkipLoadingBinary || gDebugForceLoadingFromSource))
{
-
#ifdef _WIN32
- char* bla=0;
-
-
+ char* bla = 0;
//printf("searching for %s\n", binaryFileName);
-
FILETIME modtimeBinary;
- CreateDirectoryA(sCachedBinaryPath,0);
+ CreateDirectoryA(sCachedBinaryPath, 0);
{
-
- HANDLE binaryFileHandle = CreateFileA(binaryFileName,GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
- if (binaryFileHandle ==INVALID_HANDLE_VALUE)
+ HANDLE binaryFileHandle = CreateFileA(binaryFileName, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+ if (binaryFileHandle == INVALID_HANDLE_VALUE)
{
DWORD errorCode;
errorCode = GetLastError();
switch (errorCode)
{
- case ERROR_FILE_NOT_FOUND:
+ case ERROR_FILE_NOT_FOUND:
{
b3Warning("\nCached file not found %s\n", binaryFileName);
break;
}
- case ERROR_PATH_NOT_FOUND:
+ case ERROR_PATH_NOT_FOUND:
{
b3Warning("\nCached file path not found %s\n", binaryFileName);
break;
}
- default:
+ default:
{
b3Warning("\nFailed reading cached file with errorCode = %d\n", errorCode);
}
}
- } else
+ }
+ else
{
- if (GetFileTime(binaryFileHandle, NULL, NULL, &modtimeBinary)==0)
+ if (GetFileTime(binaryFileHandle, NULL, NULL, &modtimeBinary) == 0)
{
DWORD errorCode;
errorCode = GetLastError();
b3Warning("\nGetFileTime errorCode = %d\n", errorCode);
- } else
+ }
+ else
{
binaryFileValid = 1;
}
@@ -678,37 +660,35 @@ cl_program b3OpenCLUtils_compileCLProgramFromString(cl_context clContext, cl_dev
if (binaryFileValid)
{
- HANDLE srcFileHandle = CreateFileA(clFileNameForCaching,GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
+ HANDLE srcFileHandle = CreateFileA(clFileNameForCaching, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
- if (srcFileHandle==INVALID_HANDLE_VALUE)
+ if (srcFileHandle == INVALID_HANDLE_VALUE)
{
- const char* prefix[]={"./","../","../../","../../../","../../../../"};
- for (int i=0;(srcFileHandle==INVALID_HANDLE_VALUE) && i<5;i++)
+ const char* prefix[] = {"./", "../", "../../", "../../../", "../../../../"};
+ for (int i = 0; (srcFileHandle == INVALID_HANDLE_VALUE) && i < 5; i++)
{
char relativeFileName[1024];
- sprintf(relativeFileName,"%s%s",prefix[i],clFileNameForCaching);
- srcFileHandle = CreateFileA(relativeFileName,GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
+ sprintf(relativeFileName, "%s%s", prefix[i], clFileNameForCaching);
+ srcFileHandle = CreateFileA(relativeFileName, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
}
-
}
-
- if (srcFileHandle!=INVALID_HANDLE_VALUE)
+ if (srcFileHandle != INVALID_HANDLE_VALUE)
{
FILETIME modtimeSrc;
- if (GetFileTime(srcFileHandle, NULL, NULL, &modtimeSrc)==0)
+ if (GetFileTime(srcFileHandle, NULL, NULL, &modtimeSrc) == 0)
{
DWORD errorCode;
errorCode = GetLastError();
b3Warning("\nGetFileTime errorCode = %d\n", errorCode);
}
- if ( ( modtimeSrc.dwHighDateTime < modtimeBinary.dwHighDateTime)
- ||(( modtimeSrc.dwHighDateTime == modtimeBinary.dwHighDateTime)&&(modtimeSrc.dwLowDateTime <= modtimeBinary.dwLowDateTime)))
+ if ((modtimeSrc.dwHighDateTime < modtimeBinary.dwHighDateTime) || ((modtimeSrc.dwHighDateTime == modtimeBinary.dwHighDateTime) && (modtimeSrc.dwLowDateTime <= modtimeBinary.dwLowDateTime)))
{
- fileUpToDate=1;
- } else
+ fileUpToDate = 1;
+ }
+ else
{
- b3Warning("\nCached binary file out-of-date (%s)\n",binaryFileName);
+ b3Warning("\nCached binary file out-of-date (%s)\n", binaryFileName);
}
CloseHandle(srcFileHandle);
}
@@ -719,25 +699,25 @@ cl_program b3OpenCLUtils_compileCLProgramFromString(cl_context clContext, cl_dev
errorCode = GetLastError();
switch (errorCode)
{
- case ERROR_FILE_NOT_FOUND:
+ case ERROR_FILE_NOT_FOUND:
{
b3Warning("\nSrc file not found %s\n", clFileNameForCaching);
break;
}
- case ERROR_PATH_NOT_FOUND:
+ case ERROR_PATH_NOT_FOUND:
{
b3Warning("\nSrc path not found %s\n", clFileNameForCaching);
break;
}
- default:
+ default:
{
b3Warning("\nnSrc file reading errorCode = %d\n", errorCode);
}
}
//we should make sure the src file exists so we can verify the timestamp with binary
-// assert(0);
- b3Warning("Warning: cannot find OpenCL kernel %s to verify timestamp of binary cached kernel %s\n",clFileNameForCaching, binaryFileName);
+ // assert(0);
+ b3Warning("Warning: cannot find OpenCL kernel %s to verify timestamp of binary cached kernel %s\n", clFileNameForCaching, binaryFileName);
fileUpToDate = true;
#else
//if we cannot find the source, assume it is OK in release builds
@@ -745,126 +725,109 @@ cl_program b3OpenCLUtils_compileCLProgramFromString(cl_context clContext, cl_dev
#endif
}
}
-
-
}
-
-
#else
- fileUpToDate = true;
- if (mkdir(sCachedBinaryPath,0777) == -1)
- {
- }
- else
- {
- b3Printf("Succesfully created cache directory: %s\n", sCachedBinaryPath);
- }
-#endif //_WIN32
+ fileUpToDate = true;
+ if (mkdir(sCachedBinaryPath, 0777) == -1)
+ {
+ }
+ else
+ {
+ b3Printf("Succesfully created cache directory: %s\n", sCachedBinaryPath);
+ }
+#endif //_WIN32
}
-
-
- if( fileUpToDate)
+
+ if (fileUpToDate)
{
#ifdef _MSC_VER
FILE* file;
- if (fopen_s(&file,binaryFileName, "rb")!=0)
- file=0;
+ if (fopen_s(&file, binaryFileName, "rb") != 0)
+ file = 0;
#else
FILE* file = fopen(binaryFileName, "rb");
#endif
-
+
if (file)
{
- size_t binarySize=0;
- char* binary =0;
-
- fseek( file, 0L, SEEK_END );
- binarySize = ftell( file );
- rewind( file );
- binary = (char*)malloc(sizeof(char)*binarySize);
+ size_t binarySize = 0;
+ char* binary = 0;
+
+ fseek(file, 0L, SEEK_END);
+ binarySize = ftell(file);
+ rewind(file);
+ binary = (char*)malloc(sizeof(char) * binarySize);
int bytesRead;
- bytesRead = fread( binary, sizeof(char), binarySize, file );
- fclose( file );
-
- m_cpProgram = clCreateProgramWithBinary( clContext, 1,&device, &binarySize, (const unsigned char**)&binary, 0, &status );
- b3Assert( status == CL_SUCCESS );
- status = clBuildProgram( m_cpProgram, 1, &device, additionalMacros, 0, 0 );
- b3Assert( status == CL_SUCCESS );
-
- if( status != CL_SUCCESS )
+ bytesRead = fread(binary, sizeof(char), binarySize, file);
+ fclose(file);
+
+ m_cpProgram = clCreateProgramWithBinary(clContext, 1, &device, &binarySize, (const unsigned char**)&binary, 0, &status);
+ b3Assert(status == CL_SUCCESS);
+ status = clBuildProgram(m_cpProgram, 1, &device, additionalMacros, 0, 0);
+ b3Assert(status == CL_SUCCESS);
+
+ if (status != CL_SUCCESS)
{
- char *build_log;
+ char* build_log;
size_t ret_val_size;
clGetProgramBuildInfo(m_cpProgram, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &ret_val_size);
- build_log = (char*)malloc(sizeof(char)*(ret_val_size+1));
+ build_log = (char*)malloc(sizeof(char) * (ret_val_size + 1));
clGetProgramBuildInfo(m_cpProgram, device, CL_PROGRAM_BUILD_LOG, ret_val_size, build_log, NULL);
build_log[ret_val_size] = '\0';
b3Error("%s\n", build_log);
- free (build_log);
+ free(build_log);
b3Assert(0);
m_cpProgram = 0;
- b3Warning("clBuildProgram reported failure on cached binary: %s\n",binaryFileName);
-
- } else
+ b3Warning("clBuildProgram reported failure on cached binary: %s\n", binaryFileName);
+ }
+ else
{
- b3Printf("clBuildProgram successfully compiled cached binary: %s\n",binaryFileName);
+ b3Printf("clBuildProgram successfully compiled cached binary: %s\n", binaryFileName);
}
- free (binary);
-
- } else
+ free(binary);
+ }
+ else
{
- b3Warning("Cannot open cached binary: %s\n",binaryFileName);
+ b3Warning("Cannot open cached binary: %s\n", binaryFileName);
}
}
-
-
-
-
-
-
-
-
-
+
if (!m_cpProgram)
{
-
cl_int localErrNum;
char* compileFlags;
int flagsize;
-
-
const char* kernelSource = kernelSourceOrg;
if (!kernelSourceOrg || gDebugForceLoadingFromSource)
{
if (clFileNameForCaching)
{
-
FILE* file = fopen(clFileNameForCaching, "rb");
//in many cases the relative path is a few levels up the directory hierarchy, so try it
if (!file)
{
- const char* prefix[]={"../","../../","../../../","../../../../"};
- for (int i=0;!file && i<3;i++)
+ const char* prefix[] = {"../", "../../", "../../../", "../../../../"};
+ for (int i = 0; !file && i < 3; i++)
{
char relativeFileName[1024];
- sprintf(relativeFileName,"%s%s",prefix[i],clFileNameForCaching);
+ sprintf(relativeFileName, "%s%s", prefix[i], clFileNameForCaching);
file = fopen(relativeFileName, "rb");
}
}
if (file)
{
- char* kernelSrc=0;
- fseek( file, 0L, SEEK_END );
- int kernelSize = ftell( file );
- rewind( file );
- kernelSrc = (char*)malloc(kernelSize+1);
+ char* kernelSrc = 0;
+ fseek(file, 0L, SEEK_END);
+ int kernelSize = ftell(file);
+ rewind(file);
+ kernelSrc = (char*)malloc(kernelSize + 1);
int readBytes;
- readBytes = fread((void*)kernelSrc,1,kernelSize, file);
+ readBytes = fread((void*)kernelSrc, 1, kernelSize, file);
kernelSrc[kernelSize] = 0;
fclose(file);
kernelSource = kernelSrc;
@@ -873,15 +836,14 @@ cl_program b3OpenCLUtils_compileCLProgramFromString(cl_context clContext, cl_dev
}
size_t program_length = kernelSource ? strlen(kernelSource) : 0;
-#ifdef MAC //or __APPLE__?
+#ifdef MAC //or __APPLE__?
char* flags = "-cl-mad-enable -DMAC ";
#else
const char* flags = "";
#endif
-
m_cpProgram = clCreateProgramWithSource(clContext, 1, (const char**)&kernelSource, &program_length, &localErrNum);
- if (localErrNum!= CL_SUCCESS)
+ if (localErrNum != CL_SUCCESS)
{
if (pErrNum)
*pErrNum = localErrNum;
@@ -890,108 +852,100 @@ cl_program b3OpenCLUtils_compileCLProgramFromString(cl_context clContext, cl_dev
// Build the program with 'mad' Optimization option
-
-
- flagsize = sizeof(char)*(strlen(additionalMacros) + strlen(flags) + 5);
- compileFlags = (char*) malloc(flagsize);
+ flagsize = sizeof(char) * (strlen(additionalMacros) + strlen(flags) + 5);
+ compileFlags = (char*)malloc(flagsize);
#ifdef _MSC_VER
- sprintf_s(compileFlags,flagsize, "%s %s", flags, additionalMacros);
+ sprintf_s(compileFlags, flagsize, "%s %s", flags, additionalMacros);
#else
sprintf(compileFlags, "%s %s", flags, additionalMacros);
#endif
localErrNum = clBuildProgram(m_cpProgram, 1, &device, compileFlags, NULL, NULL);
- if (localErrNum!= CL_SUCCESS)
+ if (localErrNum != CL_SUCCESS)
{
- char *build_log;
+ char* build_log;
size_t ret_val_size;
clGetProgramBuildInfo(m_cpProgram, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &ret_val_size);
- build_log = (char*) malloc(sizeof(char)*(ret_val_size+1));
+ build_log = (char*)malloc(sizeof(char) * (ret_val_size + 1));
clGetProgramBuildInfo(m_cpProgram, device, CL_PROGRAM_BUILD_LOG, ret_val_size, build_log, NULL);
// to be carefully, terminate with \0
// there's no information in the reference whether the string is 0 terminated or not
build_log[ret_val_size] = '\0';
-
b3Error("Error in clBuildProgram, Line %u in file %s, Log: \n%s\n !!!\n\n", __LINE__, __FILE__, build_log);
- free (build_log);
+ free(build_log);
if (pErrNum)
*pErrNum = localErrNum;
return 0;
}
-
- if( !disableBinaryCaching && clFileNameForCaching )
- { // write to binary
+ if (!disableBinaryCaching && clFileNameForCaching)
+ { // write to binary
cl_uint numAssociatedDevices;
- status = clGetProgramInfo( m_cpProgram, CL_PROGRAM_NUM_DEVICES, sizeof(cl_uint), &numAssociatedDevices, 0 );
- b3Assert( status == CL_SUCCESS );
- if (numAssociatedDevices==1)
+ status = clGetProgramInfo(m_cpProgram, CL_PROGRAM_NUM_DEVICES, sizeof(cl_uint), &numAssociatedDevices, 0);
+ b3Assert(status == CL_SUCCESS);
+ if (numAssociatedDevices == 1)
{
-
size_t binarySize;
- char* binary ;
+ char* binary;
- status = clGetProgramInfo( m_cpProgram, CL_PROGRAM_BINARY_SIZES, sizeof(size_t), &binarySize, 0 );
- b3Assert( status == CL_SUCCESS );
+ status = clGetProgramInfo(m_cpProgram, CL_PROGRAM_BINARY_SIZES, sizeof(size_t), &binarySize, 0);
+ b3Assert(status == CL_SUCCESS);
- binary = (char*)malloc(sizeof(char)*binarySize);
+ binary = (char*)malloc(sizeof(char) * binarySize);
- status = clGetProgramInfo( m_cpProgram, CL_PROGRAM_BINARIES, sizeof(char*), &binary, 0 );
- b3Assert( status == CL_SUCCESS );
+ status = clGetProgramInfo(m_cpProgram, CL_PROGRAM_BINARIES, sizeof(char*), &binary, 0);
+ b3Assert(status == CL_SUCCESS);
{
- FILE* file=0;
+ FILE* file = 0;
#ifdef _MSC_VER
- if (fopen_s(&file,binaryFileName, "wb")!=0)
- file=0;
+ if (fopen_s(&file, binaryFileName, "wb") != 0)
+ file = 0;
#else
file = fopen(binaryFileName, "wb");
#endif
if (file)
{
- fwrite( binary, sizeof(char), binarySize, file );
- fclose( file );
- } else
+ fwrite(binary, sizeof(char), binarySize, file);
+ fclose(file);
+ }
+ else
{
b3Warning("cannot write file %s\n", binaryFileName);
}
}
- free (binary);
+ free(binary);
}
}
free(compileFlags);
-
}
return m_cpProgram;
}
-
-cl_kernel b3OpenCLUtils_compileCLKernelFromString(cl_context clContext, cl_device_id device, const char* kernelSource, const char* kernelName, cl_int* pErrNum, cl_program prog, const char* additionalMacros )
+cl_kernel b3OpenCLUtils_compileCLKernelFromString(cl_context clContext, cl_device_id device, const char* kernelSource, const char* kernelName, cl_int* pErrNum, cl_program prog, const char* additionalMacros)
{
-
cl_kernel kernel;
cl_int localErrNum;
cl_program m_cpProgram = prog;
- b3Printf("compiling kernel %s ",kernelName);
+ b3Printf("compiling kernel %s ", kernelName);
if (!m_cpProgram)
{
- m_cpProgram = b3OpenCLUtils_compileCLProgramFromString(clContext,device,kernelSource,pErrNum, additionalMacros,0, false);
+ m_cpProgram = b3OpenCLUtils_compileCLProgramFromString(clContext, device, kernelSource, pErrNum, additionalMacros, 0, false);
}
-
// Create the kernel
kernel = clCreateKernel(m_cpProgram, kernelName, &localErrNum);
if (localErrNum != CL_SUCCESS)
{
b3Error("Error in clCreateKernel, Line %u in file %s, cannot find kernel function %s !!!\n\n", __LINE__, __FILE__, kernelName);
- assert(0);
+ assert(0);
if (pErrNum)
*pErrNum = localErrNum;
return 0;
@@ -1003,9 +957,7 @@ cl_kernel b3OpenCLUtils_compileCLKernelFromString(cl_context clContext, cl_devic
}
b3Printf("ready. \n");
-
if (pErrNum)
- *pErrNum = CL_SUCCESS;
+ *pErrNum = CL_SUCCESS;
return kernel;
-
}
diff --git a/thirdparty/bullet/Bullet3OpenCL/Initialize/b3OpenCLUtils.h b/thirdparty/bullet/Bullet3OpenCL/Initialize/b3OpenCLUtils.h
index db6466e76b..6c82eed2a6 100644
--- a/thirdparty/bullet/Bullet3OpenCL/Initialize/b3OpenCLUtils.h
+++ b/thirdparty/bullet/Bullet3OpenCL/Initialize/b3OpenCLUtils.h
@@ -22,42 +22,41 @@ subject to the following restrictions:
#include "b3OpenCLInclude.h"
#ifdef __cplusplus
-extern "C" {
+extern "C"
+{
#endif
+ ///C API for OpenCL utilities: convenience functions, see below for C++ API
-///C API for OpenCL utilities: convenience functions, see below for C++ API
+ /// CL Context optionally takes a GL context. This is a generic type because we don't really want this code
+ /// to have to understand GL types. It is a HGLRC in _WIN32 or a GLXContext otherwise.
+ cl_context b3OpenCLUtils_createContextFromType(cl_device_type deviceType, cl_int* pErrNum, void* pGLCtx, void* pGLDC, int preferredDeviceIndex, int preferredPlatformIndex, cl_platform_id* platformId);
-/// CL Context optionally takes a GL context. This is a generic type because we don't really want this code
-/// to have to understand GL types. It is a HGLRC in _WIN32 or a GLXContext otherwise.
-cl_context b3OpenCLUtils_createContextFromType(cl_device_type deviceType, cl_int* pErrNum, void* pGLCtx , void* pGLDC , int preferredDeviceIndex , int preferredPlatformIndex, cl_platform_id* platformId);
-
-int b3OpenCLUtils_getNumDevices(cl_context cxMainContext);
+ int b3OpenCLUtils_getNumDevices(cl_context cxMainContext);
-cl_device_id b3OpenCLUtils_getDevice(cl_context cxMainContext, int nr);
+ cl_device_id b3OpenCLUtils_getDevice(cl_context cxMainContext, int nr);
-void b3OpenCLUtils_printDeviceInfo(cl_device_id device);
+ void b3OpenCLUtils_printDeviceInfo(cl_device_id device);
-cl_kernel b3OpenCLUtils_compileCLKernelFromString( cl_context clContext,cl_device_id device, const char* kernelSource, const char* kernelName, cl_int* pErrNum, cl_program prog,const char* additionalMacros);
+ cl_kernel b3OpenCLUtils_compileCLKernelFromString(cl_context clContext, cl_device_id device, const char* kernelSource, const char* kernelName, cl_int* pErrNum, cl_program prog, const char* additionalMacros);
-//optional
-cl_program b3OpenCLUtils_compileCLProgramFromString( cl_context clContext,cl_device_id device, const char* kernelSource, cl_int* pErrNum,const char* additionalMacros , const char* srcFileNameForCaching, bool disableBinaryCaching);
+ //optional
+ cl_program b3OpenCLUtils_compileCLProgramFromString(cl_context clContext, cl_device_id device, const char* kernelSource, cl_int* pErrNum, const char* additionalMacros, const char* srcFileNameForCaching, bool disableBinaryCaching);
-//the following optional APIs provide access using specific platform information
-int b3OpenCLUtils_getNumPlatforms(cl_int* pErrNum);
+ //the following optional APIs provide access using specific platform information
+ int b3OpenCLUtils_getNumPlatforms(cl_int* pErrNum);
+
+ ///get the nr'th platform, where nr is in the range [0..getNumPlatforms)
+ cl_platform_id b3OpenCLUtils_getPlatform(int nr, cl_int* pErrNum);
-///get the nr'th platform, where nr is in the range [0..getNumPlatforms)
-cl_platform_id b3OpenCLUtils_getPlatform(int nr, cl_int* pErrNum);
+ void b3OpenCLUtils_printPlatformInfo(cl_platform_id platform);
+ const char* b3OpenCLUtils_getSdkVendorName();
-void b3OpenCLUtils_printPlatformInfo(cl_platform_id platform);
+ ///set the path (directory/folder) where the compiled OpenCL kernel are stored
+ void b3OpenCLUtils_setCachePath(const char* path);
-const char* b3OpenCLUtils_getSdkVendorName();
-
-///set the path (directory/folder) where the compiled OpenCL kernel are stored
-void b3OpenCLUtils_setCachePath(const char* path);
-
-cl_context b3OpenCLUtils_createContextFromPlatform(cl_platform_id platform, cl_device_type deviceType, cl_int* pErrNum, void* pGLCtx , void* pGLDC ,int preferredDeviceIndex , int preferredPlatformIndex);
+ cl_context b3OpenCLUtils_createContextFromPlatform(cl_platform_id platform, cl_device_type deviceType, cl_int* pErrNum, void* pGLCtx, void* pGLDC, int preferredDeviceIndex, int preferredPlatformIndex);
#ifdef __cplusplus
}
@@ -71,37 +70,35 @@ typedef struct
char m_driverVersion[B3_MAX_STRING_LENGTH];
char m_deviceExtensions[B3_MAX_STRING_LENGTH];
- cl_device_type m_deviceType;
- cl_uint m_computeUnits;
- size_t m_workitemDims;
- size_t m_workItemSize[3];
- size_t m_image2dMaxWidth;
- size_t m_image2dMaxHeight;
- size_t m_image3dMaxWidth;
- size_t m_image3dMaxHeight;
- size_t m_image3dMaxDepth;
- size_t m_workgroupSize;
- cl_uint m_clockFrequency;
- cl_ulong m_constantBufferSize;
- cl_ulong m_localMemSize;
- cl_ulong m_globalMemSize;
- cl_bool m_errorCorrectionSupport;
+ cl_device_type m_deviceType;
+ cl_uint m_computeUnits;
+ size_t m_workitemDims;
+ size_t m_workItemSize[3];
+ size_t m_image2dMaxWidth;
+ size_t m_image2dMaxHeight;
+ size_t m_image3dMaxWidth;
+ size_t m_image3dMaxHeight;
+ size_t m_image3dMaxDepth;
+ size_t m_workgroupSize;
+ cl_uint m_clockFrequency;
+ cl_ulong m_constantBufferSize;
+ cl_ulong m_localMemSize;
+ cl_ulong m_globalMemSize;
+ cl_bool m_errorCorrectionSupport;
cl_device_local_mem_type m_localMemType;
- cl_uint m_maxReadImageArgs;
- cl_uint m_maxWriteImageArgs;
+ cl_uint m_maxReadImageArgs;
+ cl_uint m_maxWriteImageArgs;
-
-
- cl_uint m_addressBits;
- cl_ulong m_maxMemAllocSize;
+ cl_uint m_addressBits;
+ cl_ulong m_maxMemAllocSize;
cl_command_queue_properties m_queueProperties;
- cl_bool m_imageSupport;
- cl_uint m_vecWidthChar;
- cl_uint m_vecWidthShort;
- cl_uint m_vecWidthInt;
- cl_uint m_vecWidthLong;
- cl_uint m_vecWidthFloat;
- cl_uint m_vecWidthDouble;
+ cl_bool m_imageSupport;
+ cl_uint m_vecWidthChar;
+ cl_uint m_vecWidthShort;
+ cl_uint m_vecWidthInt;
+ cl_uint m_vecWidthLong;
+ cl_uint m_vecWidthFloat;
+ cl_uint m_vecWidthDouble;
} b3OpenCLDeviceInfo;
@@ -110,33 +107,32 @@ struct b3OpenCLPlatformInfo
char m_platformVendor[B3_MAX_STRING_LENGTH];
char m_platformName[B3_MAX_STRING_LENGTH];
char m_platformVersion[B3_MAX_STRING_LENGTH];
-
+
b3OpenCLPlatformInfo()
{
- m_platformVendor[0]=0;
- m_platformName[0]=0;
- m_platformVersion[0]=0;
+ m_platformVendor[0] = 0;
+ m_platformName[0] = 0;
+ m_platformVersion[0] = 0;
}
};
-
///C++ API for OpenCL utilities: convenience functions
struct b3OpenCLUtils
{
/// CL Context optionally takes a GL context. This is a generic type because we don't really want this code
/// to have to understand GL types. It is a HGLRC in _WIN32 or a GLXContext otherwise.
- static inline cl_context createContextFromType(cl_device_type deviceType, cl_int* pErrNum, void* pGLCtx = 0, void* pGLDC = 0, int preferredDeviceIndex = -1, int preferredPlatformIndex= - 1, cl_platform_id* platformId=0)
+ static inline cl_context createContextFromType(cl_device_type deviceType, cl_int* pErrNum, void* pGLCtx = 0, void* pGLDC = 0, int preferredDeviceIndex = -1, int preferredPlatformIndex = -1, cl_platform_id* platformId = 0)
{
- return b3OpenCLUtils_createContextFromType(deviceType, pErrNum, pGLCtx , pGLDC , preferredDeviceIndex, preferredPlatformIndex, platformId);
+ return b3OpenCLUtils_createContextFromType(deviceType, pErrNum, pGLCtx, pGLDC, preferredDeviceIndex, preferredPlatformIndex, platformId);
}
-
+
static inline int getNumDevices(cl_context cxMainContext)
{
return b3OpenCLUtils_getNumDevices(cxMainContext);
}
static inline cl_device_id getDevice(cl_context cxMainContext, int nr)
{
- return b3OpenCLUtils_getDevice(cxMainContext,nr);
+ return b3OpenCLUtils_getDevice(cxMainContext, nr);
}
static void getDeviceInfo(cl_device_id device, b3OpenCLDeviceInfo* info);
@@ -146,28 +142,28 @@ struct b3OpenCLUtils
b3OpenCLUtils_printDeviceInfo(device);
}
- static inline cl_kernel compileCLKernelFromString( cl_context clContext,cl_device_id device, const char* kernelSource, const char* kernelName, cl_int* pErrNum=0, cl_program prog=0,const char* additionalMacros = "" )
+ static inline cl_kernel compileCLKernelFromString(cl_context clContext, cl_device_id device, const char* kernelSource, const char* kernelName, cl_int* pErrNum = 0, cl_program prog = 0, const char* additionalMacros = "")
{
- return b3OpenCLUtils_compileCLKernelFromString(clContext,device, kernelSource, kernelName, pErrNum, prog,additionalMacros);
+ return b3OpenCLUtils_compileCLKernelFromString(clContext, device, kernelSource, kernelName, pErrNum, prog, additionalMacros);
}
//optional
- static inline cl_program compileCLProgramFromString( cl_context clContext,cl_device_id device, const char* kernelSource, cl_int* pErrNum=0,const char* additionalMacros = "" , const char* srcFileNameForCaching=0, bool disableBinaryCaching=false)
+ static inline cl_program compileCLProgramFromString(cl_context clContext, cl_device_id device, const char* kernelSource, cl_int* pErrNum = 0, const char* additionalMacros = "", const char* srcFileNameForCaching = 0, bool disableBinaryCaching = false)
{
- return b3OpenCLUtils_compileCLProgramFromString(clContext,device, kernelSource, pErrNum,additionalMacros, srcFileNameForCaching, disableBinaryCaching);
+ return b3OpenCLUtils_compileCLProgramFromString(clContext, device, kernelSource, pErrNum, additionalMacros, srcFileNameForCaching, disableBinaryCaching);
}
//the following optional APIs provide access using specific platform information
- static inline int getNumPlatforms(cl_int* pErrNum=0)
+ static inline int getNumPlatforms(cl_int* pErrNum = 0)
{
return b3OpenCLUtils_getNumPlatforms(pErrNum);
}
///get the nr'th platform, where nr is in the range [0..getNumPlatforms)
- static inline cl_platform_id getPlatform(int nr, cl_int* pErrNum=0)
+ static inline cl_platform_id getPlatform(int nr, cl_int* pErrNum = 0)
{
- return b3OpenCLUtils_getPlatform(nr,pErrNum);
+ return b3OpenCLUtils_getPlatform(nr, pErrNum);
}
-
+
static void getPlatformInfo(cl_platform_id platform, b3OpenCLPlatformInfo* platformInfo);
static inline void printPlatformInfo(cl_platform_id platform)
@@ -179,9 +175,9 @@ struct b3OpenCLUtils
{
return b3OpenCLUtils_getSdkVendorName();
}
- static inline cl_context createContextFromPlatform(cl_platform_id platform, cl_device_type deviceType, cl_int* pErrNum, void* pGLCtx = 0, void* pGLDC = 0,int preferredDeviceIndex = -1, int preferredPlatformIndex= -1)
+ static inline cl_context createContextFromPlatform(cl_platform_id platform, cl_device_type deviceType, cl_int* pErrNum, void* pGLCtx = 0, void* pGLDC = 0, int preferredDeviceIndex = -1, int preferredPlatformIndex = -1)
{
- return b3OpenCLUtils_createContextFromPlatform(platform, deviceType, pErrNum, pGLCtx,pGLDC,preferredDeviceIndex, preferredPlatformIndex);
+ return b3OpenCLUtils_createContextFromPlatform(platform, deviceType, pErrNum, pGLCtx, pGLDC, preferredDeviceIndex, preferredPlatformIndex);
}
static void setCachePath(const char* path)
{
@@ -189,6 +185,6 @@ struct b3OpenCLUtils
}
};
-#endif //__cplusplus
+#endif //__cplusplus
-#endif // B3_OPENCL_UTILS_H
+#endif // B3_OPENCL_UTILS_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3BvhInfo.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3BvhInfo.h
index 872f039506..27835bb747 100644
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3BvhInfo.h
+++ b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3BvhInfo.h
@@ -5,14 +5,13 @@
struct b3BvhInfo
{
- b3Vector3 m_aabbMin;
- b3Vector3 m_aabbMax;
- b3Vector3 m_quantization;
- int m_numNodes;
- int m_numSubTrees;
- int m_nodeOffset;
- int m_subTreeOffset;
-
+ b3Vector3 m_aabbMin;
+ b3Vector3 m_aabbMax;
+ b3Vector3 m_quantization;
+ int m_numNodes;
+ int m_numSubTrees;
+ int m_nodeOffset;
+ int m_subTreeOffset;
};
-#endif //B3_BVH_INFO_H \ No newline at end of file
+#endif //B3_BVH_INFO_H \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ContactCache.cpp b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ContactCache.cpp
index cb30ee939b..4db717f8c3 100644
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ContactCache.cpp
+++ b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ContactCache.cpp
@@ -15,7 +15,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#include "b3ContactCache.h"
#include "Bullet3Common/b3Transform.h"
@@ -69,7 +68,7 @@ int b3ContactCache::sortCachedPoints(const b3Vector3& pt)
maxPenetration = m_pointCache[i].getDistance();
}
}
-#endif //KEEP_DEEPEST_POINT
+#endif //KEEP_DEEPEST_POINT
b3Scalar res0(b3Scalar(0.)),res1(b3Scalar(0.)),res2(b3Scalar(0.)),res3(b3Scalar(0.));
@@ -251,8 +250,4 @@ void b3ContactCache::refreshContactPoints(const b3Transform& trA,const b3Transfo
}
-
-
-
-
#endif
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ContactCache.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ContactCache.h
index d6c9b0a07e..a15fd0b2a9 100644
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ContactCache.h
+++ b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ContactCache.h
@@ -17,17 +17,13 @@ subject to the following restrictions:
#ifndef B3_CONTACT_CACHE_H
#define B3_CONTACT_CACHE_H
-
#include "Bullet3Common/b3Vector3.h"
#include "Bullet3Common/b3Transform.h"
#include "Bullet3Common/b3AlignedAllocator.h"
-
///maximum contact breaking and merging threshold
extern b3Scalar gContactBreakingThreshold;
-
-
#define MANIFOLD_CACHE_SIZE 4
///b3ContactCache is a contact point cache, it stays persistent as long as objects are overlapping in the broadphase.
@@ -37,24 +33,16 @@ extern b3Scalar gContactBreakingThreshold;
///reduces the cache to 4 points, when more then 4 points are added, using following rules:
///the contact point with deepest penetration is always kept, and it tries to maximuze the area covered by the points
///note that some pairs of objects might have more then one contact manifold.
-B3_ATTRIBUTE_ALIGNED16( class) b3ContactCache
+B3_ATTRIBUTE_ALIGNED16(class)
+b3ContactCache
{
-
-
-
-
/// sort cached points so most isolated points come first
- int sortCachedPoints(const b3Vector3& pt);
-
-
+ int sortCachedPoints(const b3Vector3& pt);
public:
-
B3_DECLARE_ALIGNED_ALLOCATOR();
-
-
- int addManifoldPoint( const b3Vector3& newPoint);
+ int addManifoldPoint(const b3Vector3& newPoint);
/*void replaceContactPoint(const b3Vector3& newPoint,int insertIndex)
{
@@ -63,18 +51,12 @@ public:
}
*/
-
-
static bool validContactDistance(const b3Vector3& pt);
-
- /// calculated new worldspace coordinates and depth, and reject points that exceed the collision margin
- static void refreshContactPoints( const b3Transform& trA,const b3Transform& trB, struct b3Contact4Data& newContactCache);
- static void removeContactPoint(struct b3Contact4Data& newContactCache,int i);
-
+ /// calculated new worldspace coordinates and depth, and reject points that exceed the collision margin
+ static void refreshContactPoints(const b3Transform& trA, const b3Transform& trB, struct b3Contact4Data& newContactCache);
+ static void removeContactPoint(struct b3Contact4Data & newContactCache, int i);
};
-
-
-#endif //B3_CONTACT_CACHE_H
+#endif //B3_CONTACT_CACHE_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ConvexHullContact.cpp b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ConvexHullContact.cpp
index fb435aa7fd..54a104c5c8 100644
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ConvexHullContact.cpp
+++ b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ConvexHullContact.cpp
@@ -16,19 +16,18 @@ subject to the following restrictions:
bool findSeparatingAxisOnGpu = true;
bool splitSearchSepAxisConcave = false;
bool splitSearchSepAxisConvex = true;
-bool useMprGpu = true;//use mpr for edge-edge (+contact point) or sat. Needs testing on main OpenCL platforms, before enabling...
+bool useMprGpu = true; //use mpr for edge-edge (+contact point) or sat. Needs testing on main OpenCL platforms, before enabling...
bool bvhTraversalKernelGPU = true;
bool findConcaveSeparatingAxisKernelGPU = true;
-bool clipConcaveFacesAndFindContactsCPU = false;//false;//true;
-bool clipConvexFacesAndFindContactsCPU = false;//false;//true;
-bool reduceConcaveContactsOnGPU = true;//false;
-bool reduceConvexContactsOnGPU = true;//false;
+bool clipConcaveFacesAndFindContactsCPU = false; //false;//true;
+bool clipConvexFacesAndFindContactsCPU = false; //false;//true;
+bool reduceConcaveContactsOnGPU = true; //false;
+bool reduceConvexContactsOnGPU = true; //false;
bool findConvexClippingFacesGPU = true;
-bool useGjk = false;///option for CPU/host testing, when findSeparatingAxisOnGpu = false
-bool useGjkContacts = false;//////option for CPU/host testing when findSeparatingAxisOnGpu = false
+bool useGjk = false; ///option for CPU/host testing, when findSeparatingAxisOnGpu = false
+bool useGjkContacts = false; //////option for CPU/host testing when findSeparatingAxisOnGpu = false
-
-static int myframecount=0;///for testing
+static int myframecount = 0; ///for testing
///This file was written by Erwin Coumans
///Separating axis rest based on work from Pierre Terdiman, see
@@ -42,10 +41,10 @@ static int myframecount=0;///for testing
//#define PERSISTENT_CONTACTS_HOST
#endif
-int b3g_actualSATPairTests=0;
+int b3g_actualSATPairTests = 0;
#include "b3ConvexHullContact.h"
-#include <string.h>//memcpy
+#include <string.h> //memcpy
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3MprPenetration.h"
@@ -54,8 +53,7 @@ int b3g_actualSATPairTests=0;
typedef b3AlignedObjectArray<b3Vector3> b3VertexArray;
-
-#include <float.h> //for FLT_MAX
+#include <float.h> //for FLT_MAX
#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
#include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
//#include "AdlQuaternion.h"
@@ -69,7 +67,6 @@ typedef b3AlignedObjectArray<b3Vector3> b3VertexArray;
#include "kernels/bvhTraversal.h"
#include "kernels/primitiveContacts.h"
-
#include "Bullet3Geometry/b3AabbUtil.h"
#define BT_NARROWPHASE_SAT_PATH "src/Bullet3OpenCL/NarrowphaseCollision/kernels/sat.cl"
@@ -77,12 +74,10 @@ typedef b3AlignedObjectArray<b3Vector3> b3VertexArray;
#define BT_NARROWPHASE_MPR_PATH "src/Bullet3OpenCL/NarrowphaseCollision/kernels/mpr.cl"
-
#define BT_NARROWPHASE_CLIPHULL_PATH "src/Bullet3OpenCL/NarrowphaseCollision/kernels/satClipHullContacts.cl"
#define BT_NARROWPHASE_BVH_TRAVERSAL_PATH "src/Bullet3OpenCL/NarrowphaseCollision/kernels/bvhTraversal.cl"
#define BT_NARROWPHASE_PRIMITIVE_CONTACT_PATH "src/Bullet3OpenCL/NarrowphaseCollision/kernels/primitiveContacts.cl"
-
#ifndef __global
#define __global
#endif
@@ -91,204 +86,184 @@ typedef b3AlignedObjectArray<b3Vector3> b3VertexArray;
#define __kernel
#endif
-
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3BvhTraversal.h"
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3FindConcaveSatAxis.h"
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ClipFaces.h"
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3NewContactReduction.h"
-
-
#define dot3F4 b3Dot
-GpuSatCollision::GpuSatCollision(cl_context ctx,cl_device_id device, cl_command_queue q )
-:m_context(ctx),
-m_device(device),
-m_queue(q),
+GpuSatCollision::GpuSatCollision(cl_context ctx, cl_device_id device, cl_command_queue q)
+ : m_context(ctx),
+ m_device(device),
+ m_queue(q),
-m_findSeparatingAxisKernel(0),
-m_findSeparatingAxisVertexFaceKernel(0),
-m_findSeparatingAxisEdgeEdgeKernel(0),
-m_unitSphereDirections(m_context,m_queue),
+ m_findSeparatingAxisKernel(0),
+ m_findSeparatingAxisVertexFaceKernel(0),
+ m_findSeparatingAxisEdgeEdgeKernel(0),
+ m_unitSphereDirections(m_context, m_queue),
-m_totalContactsOut(m_context, m_queue),
-m_sepNormals(m_context, m_queue),
-m_dmins(m_context,m_queue),
+ m_totalContactsOut(m_context, m_queue),
+ m_sepNormals(m_context, m_queue),
+ m_dmins(m_context, m_queue),
-m_hasSeparatingNormals(m_context, m_queue),
-m_concaveSepNormals(m_context, m_queue),
-m_concaveHasSeparatingNormals(m_context,m_queue),
-m_numConcavePairsOut(m_context, m_queue),
+ m_hasSeparatingNormals(m_context, m_queue),
+ m_concaveSepNormals(m_context, m_queue),
+ m_concaveHasSeparatingNormals(m_context, m_queue),
+ m_numConcavePairsOut(m_context, m_queue),
+ m_gpuCompoundPairs(m_context, m_queue),
-m_gpuCompoundPairs(m_context, m_queue),
+ m_gpuCompoundSepNormals(m_context, m_queue),
+ m_gpuHasCompoundSepNormals(m_context, m_queue),
-
-m_gpuCompoundSepNormals(m_context, m_queue),
-m_gpuHasCompoundSepNormals(m_context, m_queue),
-
-m_numCompoundPairsOut(m_context, m_queue)
+ m_numCompoundPairsOut(m_context, m_queue)
{
m_totalContactsOut.push_back(0);
-
- cl_int errNum=0;
+
+ cl_int errNum = 0;
if (1)
{
const char* mprSrc = mprKernelsCL;
-
+
const char* srcConcave = satConcaveKernelsCL;
- char flags[1024]={0};
-//#ifdef CL_PLATFORM_INTEL
-// sprintf(flags,"-g -s \"%s\"","C:/develop/bullet3_experiments2/opencl/gpu_narrowphase/kernels/sat.cl");
-//#endif
- m_mprPenetrationKernel = 0;
+ char flags[1024] = {0};
+ //#ifdef CL_PLATFORM_INTEL
+ // sprintf(flags,"-g -s \"%s\"","C:/develop/bullet3_experiments2/opencl/gpu_narrowphase/kernels/sat.cl");
+ //#endif
+ m_mprPenetrationKernel = 0;
m_findSeparatingAxisUnitSphereKernel = 0;
if (useMprGpu)
{
- cl_program mprProg = b3OpenCLUtils::compileCLProgramFromString(m_context,m_device,mprSrc,&errNum,flags,BT_NARROWPHASE_MPR_PATH);
- b3Assert(errNum==CL_SUCCESS);
-
- m_mprPenetrationKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,mprSrc, "mprPenetrationKernel",&errNum,mprProg );
+ cl_program mprProg = b3OpenCLUtils::compileCLProgramFromString(m_context, m_device, mprSrc, &errNum, flags, BT_NARROWPHASE_MPR_PATH);
+ b3Assert(errNum == CL_SUCCESS);
+
+ m_mprPenetrationKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, mprSrc, "mprPenetrationKernel", &errNum, mprProg);
b3Assert(m_mprPenetrationKernel);
- b3Assert(errNum==CL_SUCCESS);
+ b3Assert(errNum == CL_SUCCESS);
- m_findSeparatingAxisUnitSphereKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,mprSrc, "findSeparatingAxisUnitSphereKernel",&errNum,mprProg );
+ m_findSeparatingAxisUnitSphereKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, mprSrc, "findSeparatingAxisUnitSphereKernel", &errNum, mprProg);
b3Assert(m_findSeparatingAxisUnitSphereKernel);
- b3Assert(errNum==CL_SUCCESS);
+ b3Assert(errNum == CL_SUCCESS);
-
- int numDirections = sizeof(unitSphere162)/sizeof(b3Vector3);
+ int numDirections = sizeof(unitSphere162) / sizeof(b3Vector3);
m_unitSphereDirections.resize(numDirections);
- m_unitSphereDirections.copyFromHostPointer(unitSphere162,numDirections,0,true);
-
-
+ m_unitSphereDirections.copyFromHostPointer(unitSphere162, numDirections, 0, true);
}
+ cl_program satProg = b3OpenCLUtils::compileCLProgramFromString(m_context, m_device, satKernelsCL, &errNum, flags, BT_NARROWPHASE_SAT_PATH);
+ b3Assert(errNum == CL_SUCCESS);
- cl_program satProg = b3OpenCLUtils::compileCLProgramFromString(m_context,m_device,satKernelsCL,&errNum,flags,BT_NARROWPHASE_SAT_PATH);
- b3Assert(errNum==CL_SUCCESS);
-
- cl_program satConcaveProg = b3OpenCLUtils::compileCLProgramFromString(m_context,m_device,srcConcave,&errNum,flags,BT_NARROWPHASE_SAT_CONCAVE_PATH);
- b3Assert(errNum==CL_SUCCESS);
+ cl_program satConcaveProg = b3OpenCLUtils::compileCLProgramFromString(m_context, m_device, srcConcave, &errNum, flags, BT_NARROWPHASE_SAT_CONCAVE_PATH);
+ b3Assert(errNum == CL_SUCCESS);
- m_findSeparatingAxisKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,satKernelsCL, "findSeparatingAxisKernel",&errNum,satProg );
+ m_findSeparatingAxisKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, satKernelsCL, "findSeparatingAxisKernel", &errNum, satProg);
b3Assert(m_findSeparatingAxisKernel);
- b3Assert(errNum==CL_SUCCESS);
+ b3Assert(errNum == CL_SUCCESS);
-
- m_findSeparatingAxisVertexFaceKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,satKernelsCL, "findSeparatingAxisVertexFaceKernel",&errNum,satProg );
+ m_findSeparatingAxisVertexFaceKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, satKernelsCL, "findSeparatingAxisVertexFaceKernel", &errNum, satProg);
b3Assert(m_findSeparatingAxisVertexFaceKernel);
- m_findSeparatingAxisEdgeEdgeKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,satKernelsCL, "findSeparatingAxisEdgeEdgeKernel",&errNum,satProg );
+ m_findSeparatingAxisEdgeEdgeKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, satKernelsCL, "findSeparatingAxisEdgeEdgeKernel", &errNum, satProg);
b3Assert(m_findSeparatingAxisVertexFaceKernel);
-
- m_findConcaveSeparatingAxisKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,satKernelsCL, "findConcaveSeparatingAxisKernel",&errNum,satProg );
+ m_findConcaveSeparatingAxisKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, satKernelsCL, "findConcaveSeparatingAxisKernel", &errNum, satProg);
b3Assert(m_findConcaveSeparatingAxisKernel);
- b3Assert(errNum==CL_SUCCESS);
-
- m_findConcaveSeparatingAxisVertexFaceKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,srcConcave, "findConcaveSeparatingAxisVertexFaceKernel",&errNum,satConcaveProg );
+ b3Assert(errNum == CL_SUCCESS);
+
+ m_findConcaveSeparatingAxisVertexFaceKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, srcConcave, "findConcaveSeparatingAxisVertexFaceKernel", &errNum, satConcaveProg);
b3Assert(m_findConcaveSeparatingAxisVertexFaceKernel);
- b3Assert(errNum==CL_SUCCESS);
-
- m_findConcaveSeparatingAxisEdgeEdgeKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,srcConcave, "findConcaveSeparatingAxisEdgeEdgeKernel",&errNum,satConcaveProg );
+ b3Assert(errNum == CL_SUCCESS);
+
+ m_findConcaveSeparatingAxisEdgeEdgeKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, srcConcave, "findConcaveSeparatingAxisEdgeEdgeKernel", &errNum, satConcaveProg);
b3Assert(m_findConcaveSeparatingAxisEdgeEdgeKernel);
- b3Assert(errNum==CL_SUCCESS);
-
-
-
-
- m_findCompoundPairsKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,satKernelsCL, "findCompoundPairsKernel",&errNum,satProg );
+ b3Assert(errNum == CL_SUCCESS);
+
+ m_findCompoundPairsKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, satKernelsCL, "findCompoundPairsKernel", &errNum, satProg);
b3Assert(m_findCompoundPairsKernel);
- b3Assert(errNum==CL_SUCCESS);
- m_processCompoundPairsKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,satKernelsCL, "processCompoundPairsKernel",&errNum,satProg );
+ b3Assert(errNum == CL_SUCCESS);
+ m_processCompoundPairsKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, satKernelsCL, "processCompoundPairsKernel", &errNum, satProg);
b3Assert(m_processCompoundPairsKernel);
- b3Assert(errNum==CL_SUCCESS);
+ b3Assert(errNum == CL_SUCCESS);
}
if (1)
{
const char* srcClip = satClipKernelsCL;
- char flags[1024]={0};
-//#ifdef CL_PLATFORM_INTEL
-// sprintf(flags,"-g -s \"%s\"","C:/develop/bullet3_experiments2/opencl/gpu_narrowphase/kernels/satClipHullContacts.cl");
-//#endif
+ char flags[1024] = {0};
+ //#ifdef CL_PLATFORM_INTEL
+ // sprintf(flags,"-g -s \"%s\"","C:/develop/bullet3_experiments2/opencl/gpu_narrowphase/kernels/satClipHullContacts.cl");
+ //#endif
- cl_program satClipContactsProg = b3OpenCLUtils::compileCLProgramFromString(m_context,m_device,srcClip,&errNum,flags,BT_NARROWPHASE_CLIPHULL_PATH);
- b3Assert(errNum==CL_SUCCESS);
+ cl_program satClipContactsProg = b3OpenCLUtils::compileCLProgramFromString(m_context, m_device, srcClip, &errNum, flags, BT_NARROWPHASE_CLIPHULL_PATH);
+ b3Assert(errNum == CL_SUCCESS);
- m_clipHullHullKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,srcClip, "clipHullHullKernel",&errNum,satClipContactsProg);
- b3Assert(errNum==CL_SUCCESS);
+ m_clipHullHullKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, srcClip, "clipHullHullKernel", &errNum, satClipContactsProg);
+ b3Assert(errNum == CL_SUCCESS);
- m_clipCompoundsHullHullKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,srcClip, "clipCompoundsHullHullKernel",&errNum,satClipContactsProg);
- b3Assert(errNum==CL_SUCCESS);
-
+ m_clipCompoundsHullHullKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, srcClip, "clipCompoundsHullHullKernel", &errNum, satClipContactsProg);
+ b3Assert(errNum == CL_SUCCESS);
- m_findClippingFacesKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,srcClip, "findClippingFacesKernel",&errNum,satClipContactsProg);
- b3Assert(errNum==CL_SUCCESS);
+ m_findClippingFacesKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, srcClip, "findClippingFacesKernel", &errNum, satClipContactsProg);
+ b3Assert(errNum == CL_SUCCESS);
- m_clipFacesAndFindContacts = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,srcClip, "clipFacesAndFindContactsKernel",&errNum,satClipContactsProg);
- b3Assert(errNum==CL_SUCCESS);
+ m_clipFacesAndFindContacts = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, srcClip, "clipFacesAndFindContactsKernel", &errNum, satClipContactsProg);
+ b3Assert(errNum == CL_SUCCESS);
- m_clipHullHullConcaveConvexKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,srcClip, "clipHullHullConcaveConvexKernel",&errNum,satClipContactsProg);
- b3Assert(errNum==CL_SUCCESS);
+ m_clipHullHullConcaveConvexKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, srcClip, "clipHullHullConcaveConvexKernel", &errNum, satClipContactsProg);
+ b3Assert(errNum == CL_SUCCESS);
-// m_extractManifoldAndAddContactKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,srcClip, "extractManifoldAndAddContactKernel",&errNum,satClipContactsProg);
- // b3Assert(errNum==CL_SUCCESS);
+ // m_extractManifoldAndAddContactKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,srcClip, "extractManifoldAndAddContactKernel",&errNum,satClipContactsProg);
+ // b3Assert(errNum==CL_SUCCESS);
- m_newContactReductionKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,srcClip,
- "newContactReductionKernel",&errNum,satClipContactsProg);
- b3Assert(errNum==CL_SUCCESS);
+ m_newContactReductionKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, srcClip,
+ "newContactReductionKernel", &errNum, satClipContactsProg);
+ b3Assert(errNum == CL_SUCCESS);
}
- else
+ else
{
- m_clipHullHullKernel=0;
+ m_clipHullHullKernel = 0;
m_clipCompoundsHullHullKernel = 0;
- m_findClippingFacesKernel = 0;
- m_newContactReductionKernel=0;
- m_clipFacesAndFindContacts = 0;
+ m_findClippingFacesKernel = 0;
+ m_newContactReductionKernel = 0;
+ m_clipFacesAndFindContacts = 0;
m_clipHullHullConcaveConvexKernel = 0;
-// m_extractManifoldAndAddContactKernel = 0;
+ // m_extractManifoldAndAddContactKernel = 0;
}
- if (1)
+ if (1)
{
const char* srcBvh = bvhTraversalKernelCL;
- cl_program bvhTraversalProg = b3OpenCLUtils::compileCLProgramFromString(m_context,m_device,srcBvh,&errNum,"",BT_NARROWPHASE_BVH_TRAVERSAL_PATH);
- b3Assert(errNum==CL_SUCCESS);
-
- m_bvhTraversalKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,srcBvh, "bvhTraversalKernel",&errNum,bvhTraversalProg,"");
- b3Assert(errNum==CL_SUCCESS);
+ cl_program bvhTraversalProg = b3OpenCLUtils::compileCLProgramFromString(m_context, m_device, srcBvh, &errNum, "", BT_NARROWPHASE_BVH_TRAVERSAL_PATH);
+ b3Assert(errNum == CL_SUCCESS);
+ m_bvhTraversalKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, srcBvh, "bvhTraversalKernel", &errNum, bvhTraversalProg, "");
+ b3Assert(errNum == CL_SUCCESS);
}
-
- {
- const char* primitiveContactsSrc = primitiveContactsKernelsCL;
- cl_program primitiveContactsProg = b3OpenCLUtils::compileCLProgramFromString(m_context,m_device,primitiveContactsSrc,&errNum,"",BT_NARROWPHASE_PRIMITIVE_CONTACT_PATH);
- b3Assert(errNum==CL_SUCCESS);
- m_primitiveContactsKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,primitiveContactsSrc, "primitiveContactsKernel",&errNum,primitiveContactsProg,"");
- b3Assert(errNum==CL_SUCCESS);
+ {
+ const char* primitiveContactsSrc = primitiveContactsKernelsCL;
+ cl_program primitiveContactsProg = b3OpenCLUtils::compileCLProgramFromString(m_context, m_device, primitiveContactsSrc, &errNum, "", BT_NARROWPHASE_PRIMITIVE_CONTACT_PATH);
+ b3Assert(errNum == CL_SUCCESS);
+
+ m_primitiveContactsKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, primitiveContactsSrc, "primitiveContactsKernel", &errNum, primitiveContactsProg, "");
+ b3Assert(errNum == CL_SUCCESS);
- m_findConcaveSphereContactsKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,primitiveContactsSrc, "findConcaveSphereContactsKernel",&errNum,primitiveContactsProg );
- b3Assert(errNum==CL_SUCCESS);
+ m_findConcaveSphereContactsKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, primitiveContactsSrc, "findConcaveSphereContactsKernel", &errNum, primitiveContactsProg);
+ b3Assert(errNum == CL_SUCCESS);
b3Assert(m_findConcaveSphereContactsKernel);
- m_processCompoundPairsPrimitivesKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,primitiveContactsSrc, "processCompoundPairsPrimitivesKernel",&errNum,primitiveContactsProg,"");
- b3Assert(errNum==CL_SUCCESS);
+ m_processCompoundPairsPrimitivesKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, primitiveContactsSrc, "processCompoundPairsPrimitivesKernel", &errNum, primitiveContactsProg, "");
+ b3Assert(errNum == CL_SUCCESS);
b3Assert(m_processCompoundPairsPrimitivesKernel);
-
- }
-
-
+ }
}
GpuSatCollision::~GpuSatCollision()
{
-
if (m_findSeparatingAxisVertexFaceKernel)
clReleaseKernel(m_findSeparatingAxisVertexFaceKernel);
@@ -301,17 +276,15 @@ GpuSatCollision::~GpuSatCollision()
if (m_mprPenetrationKernel)
clReleaseKernel(m_mprPenetrationKernel);
-
if (m_findSeparatingAxisKernel)
clReleaseKernel(m_findSeparatingAxisKernel);
- if (m_findConcaveSeparatingAxisVertexFaceKernel)
- clReleaseKernel(m_findConcaveSeparatingAxisVertexFaceKernel);
+ if (m_findConcaveSeparatingAxisVertexFaceKernel)
+ clReleaseKernel(m_findConcaveSeparatingAxisVertexFaceKernel);
+
+ if (m_findConcaveSeparatingAxisEdgeEdgeKernel)
+ clReleaseKernel(m_findConcaveSeparatingAxisEdgeEdgeKernel);
-
- if (m_findConcaveSeparatingAxisEdgeEdgeKernel)
- clReleaseKernel(m_findConcaveSeparatingAxisEdgeEdgeKernel);
-
if (m_findConcaveSeparatingAxisKernel)
clReleaseKernel(m_findConcaveSeparatingAxisKernel);
@@ -320,17 +293,17 @@ GpuSatCollision::~GpuSatCollision()
if (m_processCompoundPairsKernel)
clReleaseKernel(m_processCompoundPairsKernel);
-
- if (m_findClippingFacesKernel)
- clReleaseKernel(m_findClippingFacesKernel);
-
- if (m_clipFacesAndFindContacts)
- clReleaseKernel(m_clipFacesAndFindContacts);
- if (m_newContactReductionKernel)
- clReleaseKernel(m_newContactReductionKernel);
+
+ if (m_findClippingFacesKernel)
+ clReleaseKernel(m_findClippingFacesKernel);
+
+ if (m_clipFacesAndFindContacts)
+ clReleaseKernel(m_clipFacesAndFindContacts);
+ if (m_newContactReductionKernel)
+ clReleaseKernel(m_newContactReductionKernel);
if (m_primitiveContactsKernel)
clReleaseKernel(m_primitiveContactsKernel);
-
+
if (m_findConcaveSphereContactsKernel)
clReleaseKernel(m_findConcaveSphereContactsKernel);
@@ -344,12 +317,11 @@ GpuSatCollision::~GpuSatCollision()
if (m_clipHullHullConcaveConvexKernel)
clReleaseKernel(m_clipHullHullConcaveConvexKernel);
-// if (m_extractManifoldAndAddContactKernel)
+ // if (m_extractManifoldAndAddContactKernel)
// clReleaseKernel(m_extractManifoldAndAddContactKernel);
if (m_bvhTraversalKernel)
clReleaseKernel(m_bvhTraversalKernel);
-
}
struct MyTriangleCallback : public b3NodeOverlapCallback
@@ -359,14 +331,13 @@ struct MyTriangleCallback : public b3NodeOverlapCallback
virtual void processNode(int subPart, int triangleIndex)
{
- printf("bodyIndexA %d, bodyIndexB %d\n",m_bodyIndexA,m_bodyIndexB);
+ printf("bodyIndexA %d, bodyIndexB %d\n", m_bodyIndexA, m_bodyIndexB);
printf("triangleIndex %d\n", triangleIndex);
}
};
-
#define float4 b3Vector3
-#define make_float4(x,y,z,w) b3MakeVector3(x,y,z,w)
+#define make_float4(x, y, z, w) b3MakeVector3(x, y, z, w)
float signedDistanceFromPointToPlane(const float4& point, const float4& planeEqn, float4* closestPointOnFace)
{
@@ -377,9 +348,7 @@ float signedDistanceFromPointToPlane(const float4& point, const float4& planeEqn
return dist;
}
-
-
-#define cross3(a,b) (a.cross(b))
+#define cross3(a, b) (a.cross(b))
b3Vector3 transform(const b3Vector3* v, const b3Vector3* pos, const b3Quaternion* orn)
{
b3Transform tr;
@@ -390,184 +359,170 @@ b3Vector3 transform(const b3Vector3* v, const b3Vector3* pos, const b3Quaternion
return res;
}
-
-inline bool IsPointInPolygon(const float4& p,
- const b3GpuFace* face,
+inline bool IsPointInPolygon(const float4& p,
+ const b3GpuFace* face,
const float4* baseVertex,
- const int* convexIndices,
- float4* out)
+ const int* convexIndices,
+ float4* out)
{
- float4 a;
- float4 b;
- float4 ab;
- float4 ap;
- float4 v;
+ float4 a;
+ float4 b;
+ float4 ab;
+ float4 ap;
+ float4 v;
- float4 plane = b3MakeVector3(face->m_plane.x,face->m_plane.y,face->m_plane.z,0.f);
-
- if (face->m_numIndices<2)
+ float4 plane = b3MakeVector3(face->m_plane.x, face->m_plane.y, face->m_plane.z, 0.f);
+
+ if (face->m_numIndices < 2)
return false;
-
- float4 v0 = baseVertex[convexIndices[face->m_indexOffset + face->m_numIndices-1]];
+ float4 v0 = baseVertex[convexIndices[face->m_indexOffset + face->m_numIndices - 1]];
b = v0;
- for(unsigned i=0; i != face->m_numIndices; ++i)
- {
+ for (unsigned i = 0; i != face->m_numIndices; ++i)
+ {
a = b;
float4 vi = baseVertex[convexIndices[face->m_indexOffset + i]];
b = vi;
- ab = b-a;
- ap = p-a;
- v = cross3(ab,plane);
-
- if (b3Dot(ap, v) > 0.f)
- {
- float ab_m2 = b3Dot(ab, ab);
- float rt = ab_m2 != 0.f ? b3Dot(ab, ap) / ab_m2 : 0.f;
- if (rt <= 0.f)
- {
- *out = a;
- }
- else if (rt >= 1.f)
- {
- *out = b;
- }
- else
- {
- float s = 1.f - rt;
+ ab = b - a;
+ ap = p - a;
+ v = cross3(ab, plane);
+
+ if (b3Dot(ap, v) > 0.f)
+ {
+ float ab_m2 = b3Dot(ab, ab);
+ float rt = ab_m2 != 0.f ? b3Dot(ab, ap) / ab_m2 : 0.f;
+ if (rt <= 0.f)
+ {
+ *out = a;
+ }
+ else if (rt >= 1.f)
+ {
+ *out = b;
+ }
+ else
+ {
+ float s = 1.f - rt;
out[0].x = s * a.x + rt * b.x;
out[0].y = s * a.y + rt * b.y;
out[0].z = s * a.z + rt * b.z;
- }
- return false;
- }
- }
- return true;
+ }
+ return false;
+ }
+ }
+ return true;
}
#define normalize3(a) (a.normalize())
-
-int extractManifoldSequentialGlobal( const float4* p, int nPoints, const float4& nearNormal, b3Int4* contactIdx)
+int extractManifoldSequentialGlobal(const float4* p, int nPoints, const float4& nearNormal, b3Int4* contactIdx)
{
- if( nPoints == 0 )
- return 0;
-
- if (nPoints <=4)
- return nPoints;
-
-
- if (nPoints >64)
- nPoints = 64;
-
- float4 center = b3MakeVector3(0,0,0,0);
+ if (nPoints == 0)
+ return 0;
+
+ if (nPoints <= 4)
+ return nPoints;
+
+ if (nPoints > 64)
+ nPoints = 64;
+
+ float4 center = b3MakeVector3(0, 0, 0, 0);
{
-
- for (int i=0;i<nPoints;i++)
+ for (int i = 0; i < nPoints; i++)
center += p[i];
center /= (float)nPoints;
}
-
-
-
+
// sample 4 directions
-
- float4 aVector = p[0] - center;
- float4 u = cross3( nearNormal, aVector );
- float4 v = cross3( nearNormal, u );
- u = normalize3( u );
- v = normalize3( v );
-
-
- //keep point with deepest penetration
- float minW= FLT_MAX;
-
- int minIndex=-1;
-
- float4 maxDots;
- maxDots.x = FLT_MIN;
- maxDots.y = FLT_MIN;
- maxDots.z = FLT_MIN;
- maxDots.w = FLT_MIN;
-
- // idx, distance
- for(int ie = 0; ie<nPoints; ie++ )
- {
- if (p[ie].w<minW)
- {
- minW = p[ie].w;
- minIndex=ie;
- }
- float f;
- float4 r = p[ie]-center;
- f = dot3F4( u, r );
- if (f<maxDots.x)
- {
- maxDots.x = f;
- contactIdx[0].x = ie;
- }
-
- f = dot3F4( -u, r );
- if (f<maxDots.y)
- {
- maxDots.y = f;
- contactIdx[0].y = ie;
- }
-
-
- f = dot3F4( v, r );
- if (f<maxDots.z)
- {
- maxDots.z = f;
- contactIdx[0].z = ie;
- }
-
- f = dot3F4( -v, r );
- if (f<maxDots.w)
- {
- maxDots.w = f;
- contactIdx[0].w = ie;
- }
-
- }
-
- if (contactIdx[0].x != minIndex && contactIdx[0].y != minIndex && contactIdx[0].z != minIndex && contactIdx[0].w != minIndex)
- {
- //replace the first contact with minimum (todo: replace contact with least penetration)
- contactIdx[0].x = minIndex;
- }
-
- return 4;
-
-}
+ float4 aVector = p[0] - center;
+ float4 u = cross3(nearNormal, aVector);
+ float4 v = cross3(nearNormal, u);
+ u = normalize3(u);
+ v = normalize3(v);
+ //keep point with deepest penetration
+ float minW = FLT_MAX;
-#define MAX_VERTS 1024
+ int minIndex = -1;
+
+ float4 maxDots;
+ maxDots.x = FLT_MIN;
+ maxDots.y = FLT_MIN;
+ maxDots.z = FLT_MIN;
+ maxDots.w = FLT_MIN;
+
+ // idx, distance
+ for (int ie = 0; ie < nPoints; ie++)
+ {
+ if (p[ie].w < minW)
+ {
+ minW = p[ie].w;
+ minIndex = ie;
+ }
+ float f;
+ float4 r = p[ie] - center;
+ f = dot3F4(u, r);
+ if (f < maxDots.x)
+ {
+ maxDots.x = f;
+ contactIdx[0].x = ie;
+ }
+
+ f = dot3F4(-u, r);
+ if (f < maxDots.y)
+ {
+ maxDots.y = f;
+ contactIdx[0].y = ie;
+ }
+
+ f = dot3F4(v, r);
+ if (f < maxDots.z)
+ {
+ maxDots.z = f;
+ contactIdx[0].z = ie;
+ }
+
+ f = dot3F4(-v, r);
+ if (f < maxDots.w)
+ {
+ maxDots.w = f;
+ contactIdx[0].w = ie;
+ }
+ }
+
+ if (contactIdx[0].x != minIndex && contactIdx[0].y != minIndex && contactIdx[0].z != minIndex && contactIdx[0].w != minIndex)
+ {
+ //replace the first contact with minimum (todo: replace contact with least penetration)
+ contactIdx[0].x = minIndex;
+ }
+
+ return 4;
+}
+#define MAX_VERTS 1024
-inline void project(const b3ConvexPolyhedronData& hull, const float4& pos, const b3Quaternion& orn, const float4& dir, const b3AlignedObjectArray<b3Vector3>& vertices, b3Scalar& min, b3Scalar& max)
+inline void project(const b3ConvexPolyhedronData& hull, const float4& pos, const b3Quaternion& orn, const float4& dir, const b3AlignedObjectArray<b3Vector3>& vertices, b3Scalar& min, b3Scalar& max)
{
min = FLT_MAX;
max = -FLT_MAX;
int numVerts = hull.m_numVertices;
- const float4 localDir = b3QuatRotate(orn.inverse(),dir);
+ const float4 localDir = b3QuatRotate(orn.inverse(), dir);
- b3Scalar offset = dot3F4(pos,dir);
+ b3Scalar offset = dot3F4(pos, dir);
- for(int i=0;i<numVerts;i++)
+ for (int i = 0; i < numVerts; i++)
{
//b3Vector3 pt = trans * vertices[m_vertexOffset+i];
//b3Scalar dp = pt.dot(dir);
//b3Vector3 vertex = vertices[hull.m_vertexOffset+i];
- b3Scalar dp = dot3F4((float4&)vertices[hull.m_vertexOffset+i],localDir);
+ b3Scalar dp = dot3F4((float4&)vertices[hull.m_vertexOffset + i], localDir);
//b3Assert(dp==dpL);
- if(dp < min) min = dp;
- if(dp > max) max = dp;
+ if (dp < min) min = dp;
+ if (dp > max) max = dp;
}
- if(min>max)
+ if (min > max)
{
b3Scalar tmp = min;
min = max;
@@ -577,50 +532,48 @@ inline void project(const b3ConvexPolyhedronData& hull, const float4& pos, cons
max += offset;
}
-
-static bool TestSepAxis(const b3ConvexPolyhedronData& hullA, const b3ConvexPolyhedronData& hullB,
- const float4& posA,const b3Quaternion& ornA,
- const float4& posB,const b3Quaternion& ornB,
- const float4& sep_axis, const b3AlignedObjectArray<b3Vector3>& verticesA,const b3AlignedObjectArray<b3Vector3>& verticesB,b3Scalar& depth)
+static bool TestSepAxis(const b3ConvexPolyhedronData& hullA, const b3ConvexPolyhedronData& hullB,
+ const float4& posA, const b3Quaternion& ornA,
+ const float4& posB, const b3Quaternion& ornB,
+ const float4& sep_axis, const b3AlignedObjectArray<b3Vector3>& verticesA, const b3AlignedObjectArray<b3Vector3>& verticesB, b3Scalar& depth)
{
- b3Scalar Min0,Max0;
- b3Scalar Min1,Max1;
- project(hullA,posA,ornA,sep_axis,verticesA, Min0, Max0);
- project(hullB,posB,ornB, sep_axis,verticesB, Min1, Max1);
+ b3Scalar Min0, Max0;
+ b3Scalar Min1, Max1;
+ project(hullA, posA, ornA, sep_axis, verticesA, Min0, Max0);
+ project(hullB, posB, ornB, sep_axis, verticesB, Min1, Max1);
- if(Max0<Min1 || Max1<Min0)
+ if (Max0 < Min1 || Max1 < Min0)
return false;
b3Scalar d0 = Max0 - Min1;
- assert(d0>=0.0f);
+ assert(d0 >= 0.0f);
b3Scalar d1 = Max1 - Min0;
- assert(d1>=0.0f);
- depth = d0<d1 ? d0:d1;
+ assert(d1 >= 0.0f);
+ depth = d0 < d1 ? d0 : d1;
return true;
}
inline bool IsAlmostZero(const b3Vector3& v)
{
- if(fabsf(v.x)>1e-6 || fabsf(v.y)>1e-6 || fabsf(v.z)>1e-6) return false;
+ if (fabsf(v.x) > 1e-6 || fabsf(v.y) > 1e-6 || fabsf(v.z) > 1e-6) return false;
return true;
}
-
-static bool findSeparatingAxis( const b3ConvexPolyhedronData& hullA, const b3ConvexPolyhedronData& hullB,
- const float4& posA1,
- const b3Quaternion& ornA,
- const float4& posB1,
- const b3Quaternion& ornB,
- const b3AlignedObjectArray<b3Vector3>& verticesA,
- const b3AlignedObjectArray<b3Vector3>& uniqueEdgesA,
- const b3AlignedObjectArray<b3GpuFace>& facesA,
- const b3AlignedObjectArray<int>& indicesA,
- const b3AlignedObjectArray<b3Vector3>& verticesB,
- const b3AlignedObjectArray<b3Vector3>& uniqueEdgesB,
- const b3AlignedObjectArray<b3GpuFace>& facesB,
- const b3AlignedObjectArray<int>& indicesB,
-
- b3Vector3& sep)
+static bool findSeparatingAxis(const b3ConvexPolyhedronData& hullA, const b3ConvexPolyhedronData& hullB,
+ const float4& posA1,
+ const b3Quaternion& ornA,
+ const float4& posB1,
+ const b3Quaternion& ornB,
+ const b3AlignedObjectArray<b3Vector3>& verticesA,
+ const b3AlignedObjectArray<b3Vector3>& uniqueEdgesA,
+ const b3AlignedObjectArray<b3GpuFace>& facesA,
+ const b3AlignedObjectArray<int>& indicesA,
+ const b3AlignedObjectArray<b3Vector3>& verticesB,
+ const b3AlignedObjectArray<b3Vector3>& uniqueEdgesB,
+ const b3AlignedObjectArray<b3GpuFace>& facesB,
+ const b3AlignedObjectArray<int>& indicesB,
+
+ b3Vector3& sep)
{
B3_PROFILE("findSeparatingAxis");
@@ -629,41 +582,40 @@ static bool findSeparatingAxis( const b3ConvexPolyhedronData& hullA, const b3Con
posA.w = 0.f;
float4 posB = posB1;
posB.w = 0.f;
-//#ifdef TEST_INTERNAL_OBJECTS
+ //#ifdef TEST_INTERNAL_OBJECTS
float4 c0local = (float4&)hullA.m_localCenter;
float4 c0 = transform(&c0local, &posA, &ornA);
float4 c1local = (float4&)hullB.m_localCenter;
- float4 c1 = transform(&c1local,&posB,&ornB);
+ float4 c1 = transform(&c1local, &posB, &ornB);
const float4 deltaC2 = c0 - c1;
-//#endif
+ //#endif
b3Scalar dmin = FLT_MAX;
- int curPlaneTests=0;
+ int curPlaneTests = 0;
int numFacesA = hullA.m_numFaces;
// Test normals from hullA
- for(int i=0;i<numFacesA;i++)
+ for (int i = 0; i < numFacesA; i++)
{
- const float4& normal = (float4&)facesA[hullA.m_faceOffset+i].m_plane;
- float4 faceANormalWS = b3QuatRotate(ornA,normal);
+ const float4& normal = (float4&)facesA[hullA.m_faceOffset + i].m_plane;
+ float4 faceANormalWS = b3QuatRotate(ornA, normal);
- if (dot3F4(deltaC2,faceANormalWS)<0)
- faceANormalWS*=-1.f;
+ if (dot3F4(deltaC2, faceANormalWS) < 0)
+ faceANormalWS *= -1.f;
curPlaneTests++;
#ifdef TEST_INTERNAL_OBJECTS
gExpectedNbTests++;
- if(gUseInternalObject && !TestInternalObjects(transA,transB, DeltaC2, faceANormalWS, hullA, hullB, dmin))
+ if (gUseInternalObject && !TestInternalObjects(transA, transB, DeltaC2, faceANormalWS, hullA, hullB, dmin))
continue;
gActualNbTests++;
#endif
-
b3Scalar d;
- if(!TestSepAxis( hullA, hullB, posA,ornA,posB,ornB,faceANormalWS, verticesA, verticesB,d))
+ if (!TestSepAxis(hullA, hullB, posA, ornA, posB, ornB, faceANormalWS, verticesA, verticesB, d))
return false;
- if(d<dmin)
+ if (d < dmin)
{
dmin = d;
sep = (b3Vector3&)faceANormalWS;
@@ -672,28 +624,28 @@ static bool findSeparatingAxis( const b3ConvexPolyhedronData& hullA, const b3Con
int numFacesB = hullB.m_numFaces;
// Test normals from hullB
- for(int i=0;i<numFacesB;i++)
+ for (int i = 0; i < numFacesB; i++)
{
- float4 normal = (float4&)facesB[hullB.m_faceOffset+i].m_plane;
+ float4 normal = (float4&)facesB[hullB.m_faceOffset + i].m_plane;
float4 WorldNormal = b3QuatRotate(ornB, normal);
- if (dot3F4(deltaC2,WorldNormal)<0)
+ if (dot3F4(deltaC2, WorldNormal) < 0)
{
- WorldNormal*=-1.f;
+ WorldNormal *= -1.f;
}
curPlaneTests++;
#ifdef TEST_INTERNAL_OBJECTS
gExpectedNbTests++;
- if(gUseInternalObject && !TestInternalObjects(transA,transB,DeltaC2, WorldNormal, hullA, hullB, dmin))
+ if (gUseInternalObject && !TestInternalObjects(transA, transB, DeltaC2, WorldNormal, hullA, hullB, dmin))
continue;
gActualNbTests++;
#endif
b3Scalar d;
- if(!TestSepAxis(hullA, hullB,posA,ornA,posB,ornB,WorldNormal,verticesA,verticesB,d))
+ if (!TestSepAxis(hullA, hullB, posA, ornA, posB, ornB, WorldNormal, verticesA, verticesB, d))
return false;
- if(d<dmin)
+ if (d < dmin)
{
dmin = d;
sep = (b3Vector3&)WorldNormal;
@@ -702,70 +654,65 @@ static bool findSeparatingAxis( const b3ConvexPolyhedronData& hullA, const b3Con
int curEdgeEdge = 0;
// Test edges
- for(int e0=0;e0<hullA.m_numUniqueEdges;e0++)
+ for (int e0 = 0; e0 < hullA.m_numUniqueEdges; e0++)
{
- const float4& edge0 = (float4&) uniqueEdgesA[hullA.m_uniqueEdgesOffset+e0];
- float4 edge0World = b3QuatRotate(ornA,(float4&)edge0);
+ const float4& edge0 = (float4&)uniqueEdgesA[hullA.m_uniqueEdgesOffset + e0];
+ float4 edge0World = b3QuatRotate(ornA, (float4&)edge0);
- for(int e1=0;e1<hullB.m_numUniqueEdges;e1++)
+ for (int e1 = 0; e1 < hullB.m_numUniqueEdges; e1++)
{
- const b3Vector3 edge1 = uniqueEdgesB[hullB.m_uniqueEdgesOffset+e1];
- float4 edge1World = b3QuatRotate(ornB,(float4&)edge1);
-
+ const b3Vector3 edge1 = uniqueEdgesB[hullB.m_uniqueEdgesOffset + e1];
+ float4 edge1World = b3QuatRotate(ornB, (float4&)edge1);
- float4 crossje = cross3(edge0World,edge1World);
+ float4 crossje = cross3(edge0World, edge1World);
curEdgeEdge++;
- if(!IsAlmostZero((b3Vector3&)crossje))
+ if (!IsAlmostZero((b3Vector3&)crossje))
{
crossje = normalize3(crossje);
- if (dot3F4(deltaC2,crossje)<0)
- crossje*=-1.f;
-
+ if (dot3F4(deltaC2, crossje) < 0)
+ crossje *= -1.f;
#ifdef TEST_INTERNAL_OBJECTS
gExpectedNbTests++;
- if(gUseInternalObject && !TestInternalObjects(transA,transB,DeltaC2, Cross, hullA, hullB, dmin))
+ if (gUseInternalObject && !TestInternalObjects(transA, transB, DeltaC2, Cross, hullA, hullB, dmin))
continue;
gActualNbTests++;
#endif
b3Scalar dist;
- if(!TestSepAxis( hullA, hullB, posA,ornA,posB,ornB,crossje, verticesA,verticesB,dist))
+ if (!TestSepAxis(hullA, hullB, posA, ornA, posB, ornB, crossje, verticesA, verticesB, dist))
return false;
- if(dist<dmin)
+ if (dist < dmin)
{
dmin = dist;
sep = (b3Vector3&)crossje;
}
}
}
-
}
-
- if((dot3F4(-deltaC2,(float4&)sep))>0.0f)
+ if ((dot3F4(-deltaC2, (float4&)sep)) > 0.0f)
sep = -sep;
return true;
}
-
-bool findSeparatingAxisEdgeEdge( __global const b3ConvexPolyhedronData* hullA, __global const b3ConvexPolyhedronData* hullB,
- const b3Float4& posA1,
- const b3Quat& ornA,
- const b3Float4& posB1,
- const b3Quat& ornB,
- const b3Float4& DeltaC2,
- __global const b3AlignedObjectArray<float4>& vertices,
- __global const b3AlignedObjectArray<float4>& uniqueEdges,
- __global const b3AlignedObjectArray<b3GpuFace>& faces,
- __global const b3AlignedObjectArray<int>& indices,
- float4* sep,
- float* dmin)
+bool findSeparatingAxisEdgeEdge(__global const b3ConvexPolyhedronData* hullA, __global const b3ConvexPolyhedronData* hullB,
+ const b3Float4& posA1,
+ const b3Quat& ornA,
+ const b3Float4& posB1,
+ const b3Quat& ornB,
+ const b3Float4& DeltaC2,
+ __global const b3AlignedObjectArray<float4>& vertices,
+ __global const b3AlignedObjectArray<float4>& uniqueEdges,
+ __global const b3AlignedObjectArray<b3GpuFace>& faces,
+ __global const b3AlignedObjectArray<int>& indices,
+ float4* sep,
+ float* dmin)
{
-// int i = get_global_id(0);
+ // int i = get_global_id(0);
float4 posA = posA1;
posA.w = 0.f;
@@ -776,97 +723,89 @@ bool findSeparatingAxisEdgeEdge( __global const b3ConvexPolyhedronData* hullA, _
int curEdgeEdge = 0;
// Test edges
- for(int e0=0;e0<hullA->m_numUniqueEdges;e0++)
+ for (int e0 = 0; e0 < hullA->m_numUniqueEdges; e0++)
{
- const float4 edge0 = uniqueEdges[hullA->m_uniqueEdgesOffset+e0];
- float4 edge0World = b3QuatRotate(ornA,edge0);
+ const float4 edge0 = uniqueEdges[hullA->m_uniqueEdgesOffset + e0];
+ float4 edge0World = b3QuatRotate(ornA, edge0);
- for(int e1=0;e1<hullB->m_numUniqueEdges;e1++)
+ for (int e1 = 0; e1 < hullB->m_numUniqueEdges; e1++)
{
- const float4 edge1 = uniqueEdges[hullB->m_uniqueEdgesOffset+e1];
- float4 edge1World = b3QuatRotate(ornB,edge1);
+ const float4 edge1 = uniqueEdges[hullB->m_uniqueEdgesOffset + e1];
+ float4 edge1World = b3QuatRotate(ornB, edge1);
-
- float4 crossje = cross3(edge0World,edge1World);
+ float4 crossje = cross3(edge0World, edge1World);
curEdgeEdge++;
- if(!IsAlmostZero(crossje))
+ if (!IsAlmostZero(crossje))
{
crossje = normalize3(crossje);
- if (dot3F4(DeltaC2,crossje)<0)
- crossje*=-1.f;
-
+ if (dot3F4(DeltaC2, crossje) < 0)
+ crossje *= -1.f;
+
float dist;
bool result = true;
{
- float Min0,Max0;
- float Min1,Max1;
- project(*hullA,posA,ornA,crossje,vertices, Min0, Max0);
- project(*hullB,posB,ornB,crossje,vertices, Min1, Max1);
-
- if(Max0<Min1 || Max1<Min0)
+ float Min0, Max0;
+ float Min1, Max1;
+ project(*hullA, posA, ornA, crossje, vertices, Min0, Max0);
+ project(*hullB, posB, ornB, crossje, vertices, Min1, Max1);
+
+ if (Max0 < Min1 || Max1 < Min0)
result = false;
-
+
float d0 = Max0 - Min1;
float d1 = Max1 - Min0;
- dist = d0<d1 ? d0:d1;
+ dist = d0 < d1 ? d0 : d1;
result = true;
-
}
-
- if(dist<*dmin)
+ if (dist < *dmin)
{
*dmin = dist;
*sep = crossje;
}
}
}
-
}
-
- if((dot3F4(-DeltaC2,*sep))>0.0f)
+ if ((dot3F4(-DeltaC2, *sep)) > 0.0f)
{
*sep = -(*sep);
}
return true;
}
-
-__inline float4 lerp3(const float4& a,const float4& b, float t)
+__inline float4 lerp3(const float4& a, const float4& b, float t)
{
- return b3MakeVector3( a.x + (b.x - a.x) * t,
- a.y + (b.y - a.y) * t,
- a.z + (b.z - a.z) * t,
- 0.f);
+ return b3MakeVector3(a.x + (b.x - a.x) * t,
+ a.y + (b.y - a.y) * t,
+ a.z + (b.z - a.z) * t,
+ 0.f);
}
-
// Clips a face to the back of a plane, return the number of vertices out, stored in ppVtxOut
-int clipFace(const float4* pVtxIn, int numVertsIn, float4& planeNormalWS,float planeEqWS, float4* ppVtxOut)
+int clipFace(const float4* pVtxIn, int numVertsIn, float4& planeNormalWS, float planeEqWS, float4* ppVtxOut)
{
-
int ve;
float ds, de;
int numVertsOut = 0;
if (numVertsIn < 2)
return 0;
- float4 firstVertex=pVtxIn[numVertsIn-1];
+ float4 firstVertex = pVtxIn[numVertsIn - 1];
float4 endVertex = pVtxIn[0];
-
- ds = dot3F4(planeNormalWS,firstVertex)+planeEqWS;
+
+ ds = dot3F4(planeNormalWS, firstVertex) + planeEqWS;
for (ve = 0; ve < numVertsIn; ve++)
{
- endVertex=pVtxIn[ve];
+ endVertex = pVtxIn[ve];
- de = dot3F4(planeNormalWS,endVertex)+planeEqWS;
+ de = dot3F4(planeNormalWS, endVertex) + planeEqWS;
- if (ds<0)
+ if (ds < 0)
{
- if (de<0)
+ if (de < 0)
{
// Start < 0, end < 0, so output endVertex
ppVtxOut[numVertsOut++] = endVertex;
@@ -874,15 +813,15 @@ int clipFace(const float4* pVtxIn, int numVertsIn, float4& planeNormalWS,float p
else
{
// Start < 0, end >= 0, so output intersection
- ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );
+ ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex, (ds * 1.f / (ds - de)));
}
}
else
{
- if (de<0)
+ if (de < 0)
{
// Start >= 0, end < 0 so output intersection and end
- ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );
+ ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex, (ds * 1.f / (ds - de)));
ppVtxOut[numVertsOut++] = endVertex;
}
}
@@ -892,36 +831,35 @@ int clipFace(const float4* pVtxIn, int numVertsIn, float4& planeNormalWS,float p
return numVertsOut;
}
-
-int clipFaceAgainstHull(const float4& separatingNormal, const b3ConvexPolyhedronData* hullA,
- const float4& posA, const b3Quaternion& ornA, float4* worldVertsB1, int numWorldVertsB1,
- float4* worldVertsB2, int capacityWorldVertsB2,
- const float minDist, float maxDist,
- const b3AlignedObjectArray<float4>& verticesA, const b3AlignedObjectArray<b3GpuFace>& facesA, const b3AlignedObjectArray<int>& indicesA,
- //const float4* verticesB, const b3GpuFace* facesB, const int* indicesB,
- float4* contactsOut,
- int contactCapacity)
+int clipFaceAgainstHull(const float4& separatingNormal, const b3ConvexPolyhedronData* hullA,
+ const float4& posA, const b3Quaternion& ornA, float4* worldVertsB1, int numWorldVertsB1,
+ float4* worldVertsB2, int capacityWorldVertsB2,
+ const float minDist, float maxDist,
+ const b3AlignedObjectArray<float4>& verticesA, const b3AlignedObjectArray<b3GpuFace>& facesA, const b3AlignedObjectArray<int>& indicesA,
+ //const float4* verticesB, const b3GpuFace* facesB, const int* indicesB,
+ float4* contactsOut,
+ int contactCapacity)
{
int numContactsOut = 0;
float4* pVtxIn = worldVertsB1;
float4* pVtxOut = worldVertsB2;
-
+
int numVertsIn = numWorldVertsB1;
int numVertsOut = 0;
- int closestFaceA=-1;
+ int closestFaceA = -1;
{
float dmin = FLT_MAX;
- for(int face=0;face<hullA->m_numFaces;face++)
+ for (int face = 0; face < hullA->m_numFaces; face++)
{
const float4 Normal = b3MakeVector3(
- facesA[hullA->m_faceOffset+face].m_plane.x,
- facesA[hullA->m_faceOffset+face].m_plane.y,
- facesA[hullA->m_faceOffset+face].m_plane.z,0.f);
- const float4 faceANormalWS = b3QuatRotate(ornA,Normal);
-
- float d = dot3F4(faceANormalWS,separatingNormal);
+ facesA[hullA->m_faceOffset + face].m_plane.x,
+ facesA[hullA->m_faceOffset + face].m_plane.y,
+ facesA[hullA->m_faceOffset + face].m_plane.z, 0.f);
+ const float4 faceANormalWS = b3QuatRotate(ornA, Normal);
+
+ float d = dot3F4(faceANormalWS, separatingNormal);
if (d < dmin)
{
dmin = d;
@@ -929,33 +867,33 @@ int clipFaceAgainstHull(const float4& separatingNormal, const b3ConvexPolyhedron
}
}
}
- if (closestFaceA<0)
+ if (closestFaceA < 0)
return numContactsOut;
- b3GpuFace polyA = facesA[hullA->m_faceOffset+closestFaceA];
+ b3GpuFace polyA = facesA[hullA->m_faceOffset + closestFaceA];
// clip polygon to back of planes of all faces of hull A that are adjacent to witness face
-// int numContacts = numWorldVertsB1;
+ // int numContacts = numWorldVertsB1;
int numVerticesA = polyA.m_numIndices;
- for(int e0=0;e0<numVerticesA;e0++)
+ for (int e0 = 0; e0 < numVerticesA; e0++)
{
- const float4 a = verticesA[hullA->m_vertexOffset+indicesA[polyA.m_indexOffset+e0]];
- const float4 b = verticesA[hullA->m_vertexOffset+indicesA[polyA.m_indexOffset+((e0+1)%numVerticesA)]];
+ const float4 a = verticesA[hullA->m_vertexOffset + indicesA[polyA.m_indexOffset + e0]];
+ const float4 b = verticesA[hullA->m_vertexOffset + indicesA[polyA.m_indexOffset + ((e0 + 1) % numVerticesA)]];
const float4 edge0 = a - b;
- const float4 WorldEdge0 = b3QuatRotate(ornA,edge0);
- float4 planeNormalA = make_float4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);
- float4 worldPlaneAnormal1 = b3QuatRotate(ornA,planeNormalA);
+ const float4 WorldEdge0 = b3QuatRotate(ornA, edge0);
+ float4 planeNormalA = make_float4(polyA.m_plane.x, polyA.m_plane.y, polyA.m_plane.z, 0.f);
+ float4 worldPlaneAnormal1 = b3QuatRotate(ornA, planeNormalA);
+
+ float4 planeNormalWS1 = -cross3(WorldEdge0, worldPlaneAnormal1);
+ float4 worldA1 = transform(&a, &posA, &ornA);
+ float planeEqWS1 = -dot3F4(worldA1, planeNormalWS1);
- float4 planeNormalWS1 = -cross3(WorldEdge0,worldPlaneAnormal1);
- float4 worldA1 = transform(&a,&posA,&ornA);
- float planeEqWS1 = -dot3F4(worldA1,planeNormalWS1);
-
float4 planeNormalWS = planeNormalWS1;
- float planeEqWS=planeEqWS1;
-
+ float planeEqWS = planeEqWS1;
+
//clip face
//clipFace(*pVtxIn, *pVtxOut,planeNormalWS,planeEqWS);
- numVertsOut = clipFace(pVtxIn, numVertsIn, planeNormalWS,planeEqWS, pVtxOut);
+ numVertsOut = clipFace(pVtxIn, numVertsIn, planeNormalWS, planeEqWS, pVtxOut);
//btSwap(pVtxIn,pVtxOut);
float4* tmp = pVtxOut;
@@ -965,32 +903,32 @@ int clipFaceAgainstHull(const float4& separatingNormal, const b3ConvexPolyhedron
numVertsOut = 0;
}
-
// only keep points that are behind the witness face
{
- float4 localPlaneNormal = make_float4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);
+ float4 localPlaneNormal = make_float4(polyA.m_plane.x, polyA.m_plane.y, polyA.m_plane.z, 0.f);
float localPlaneEq = polyA.m_plane.w;
- float4 planeNormalWS = b3QuatRotate(ornA,localPlaneNormal);
- float planeEqWS=localPlaneEq-dot3F4(planeNormalWS,posA);
- for (int i=0;i<numVertsIn;i++)
+ float4 planeNormalWS = b3QuatRotate(ornA, localPlaneNormal);
+ float planeEqWS = localPlaneEq - dot3F4(planeNormalWS, posA);
+ for (int i = 0; i < numVertsIn; i++)
{
- float depth = dot3F4(planeNormalWS,pVtxIn[i])+planeEqWS;
- if (depth <=minDist)
+ float depth = dot3F4(planeNormalWS, pVtxIn[i]) + planeEqWS;
+ if (depth <= minDist)
{
depth = minDist;
}
- if (numContactsOut<contactCapacity)
+ if (numContactsOut < contactCapacity)
{
- if (depth <=maxDist)
+ if (depth <= maxDist)
{
float4 pointInWorld = pVtxIn[i];
//resultOut.addContactPoint(separatingNormal,point,depth);
- contactsOut[numContactsOut++] = b3MakeVector3(pointInWorld.x,pointInWorld.y,pointInWorld.z,depth);
+ contactsOut[numContactsOut++] = b3MakeVector3(pointInWorld.x, pointInWorld.y, pointInWorld.z, depth);
//printf("depth=%f\n",depth);
}
- } else
+ }
+ else
{
- b3Error("exceeding contact capacity (%d,%df)\n", numContactsOut,contactCapacity);
+ b3Error("exceeding contact capacity (%d,%df)\n", numContactsOut, contactCapacity);
}
}
}
@@ -998,62 +936,60 @@ int clipFaceAgainstHull(const float4& separatingNormal, const b3ConvexPolyhedron
return numContactsOut;
}
+static int clipHullAgainstHull(const float4& separatingNormal,
+ const b3ConvexPolyhedronData& hullA, const b3ConvexPolyhedronData& hullB,
+ const float4& posA, const b3Quaternion& ornA, const float4& posB, const b3Quaternion& ornB,
+ float4* worldVertsB1, float4* worldVertsB2, int capacityWorldVerts,
+ const float minDist, float maxDist,
+ const b3AlignedObjectArray<float4>& verticesA, const b3AlignedObjectArray<b3GpuFace>& facesA, const b3AlignedObjectArray<int>& indicesA,
+ const b3AlignedObjectArray<float4>& verticesB, const b3AlignedObjectArray<b3GpuFace>& facesB, const b3AlignedObjectArray<int>& indicesB,
-
-static int clipHullAgainstHull(const float4& separatingNormal,
- const b3ConvexPolyhedronData& hullA, const b3ConvexPolyhedronData& hullB,
- const float4& posA, const b3Quaternion& ornA,const float4& posB, const b3Quaternion& ornB,
- float4* worldVertsB1, float4* worldVertsB2, int capacityWorldVerts,
- const float minDist, float maxDist,
- const b3AlignedObjectArray<float4>& verticesA, const b3AlignedObjectArray<b3GpuFace>& facesA, const b3AlignedObjectArray<int>& indicesA,
- const b3AlignedObjectArray<float4>& verticesB, const b3AlignedObjectArray<b3GpuFace>& facesB, const b3AlignedObjectArray<int>& indicesB,
-
- float4* contactsOut,
- int contactCapacity)
+ float4* contactsOut,
+ int contactCapacity)
{
int numContactsOut = 0;
- int numWorldVertsB1= 0;
-
+ int numWorldVertsB1 = 0;
+
B3_PROFILE("clipHullAgainstHull");
-// float curMaxDist=maxDist;
- int closestFaceB=-1;
+ // float curMaxDist=maxDist;
+ int closestFaceB = -1;
float dmax = -FLT_MAX;
{
//B3_PROFILE("closestFaceB");
- if (hullB.m_numFaces!=1)
+ if (hullB.m_numFaces != 1)
{
//printf("wtf\n");
}
static bool once = true;
//printf("separatingNormal=%f,%f,%f\n",separatingNormal.x,separatingNormal.y,separatingNormal.z);
-
- for(int face=0;face<hullB.m_numFaces;face++)
+
+ for (int face = 0; face < hullB.m_numFaces; face++)
{
#ifdef BT_DEBUG_SAT_FACE
if (once)
- printf("face %d\n",face);
- const b3GpuFace* faceB = &facesB[hullB.m_faceOffset+face];
+ printf("face %d\n", face);
+ const b3GpuFace* faceB = &facesB[hullB.m_faceOffset + face];
if (once)
{
- for (int i=0;i<faceB->m_numIndices;i++)
+ for (int i = 0; i < faceB->m_numIndices; i++)
{
- float4 vert = verticesB[hullB.m_vertexOffset+indicesB[faceB->m_indexOffset+i]];
- printf("vert[%d] = %f,%f,%f\n",i,vert.x,vert.y,vert.z);
+ float4 vert = verticesB[hullB.m_vertexOffset + indicesB[faceB->m_indexOffset + i]];
+ printf("vert[%d] = %f,%f,%f\n", i, vert.x, vert.y, vert.z);
}
}
-#endif //BT_DEBUG_SAT_FACE
- //if (facesB[hullB.m_faceOffset+face].m_numIndices>2)
+#endif //BT_DEBUG_SAT_FACE \
+ //if (facesB[hullB.m_faceOffset+face].m_numIndices>2)
{
- const float4 Normal = b3MakeVector3(facesB[hullB.m_faceOffset+face].m_plane.x,
- facesB[hullB.m_faceOffset+face].m_plane.y, facesB[hullB.m_faceOffset+face].m_plane.z,0.f);
+ const float4 Normal = b3MakeVector3(facesB[hullB.m_faceOffset + face].m_plane.x,
+ facesB[hullB.m_faceOffset + face].m_plane.y, facesB[hullB.m_faceOffset + face].m_plane.z, 0.f);
const float4 WorldNormal = b3QuatRotate(ornB, Normal);
#ifdef BT_DEBUG_SAT_FACE
if (once)
- printf("faceNormal = %f,%f,%f\n",Normal.x,Normal.y,Normal.z);
+ printf("faceNormal = %f,%f,%f\n", Normal.x, Normal.y, Normal.z);
#endif
- float d = dot3F4(WorldNormal,separatingNormal);
+ float d = dot3F4(WorldNormal, separatingNormal);
if (d > dmax)
{
dmax = d;
@@ -1064,184 +1000,176 @@ static int clipHullAgainstHull(const float4& separatingNormal,
once = false;
}
-
- b3Assert(closestFaceB>=0);
+ b3Assert(closestFaceB >= 0);
{
//B3_PROFILE("worldVertsB1");
- const b3GpuFace& polyB = facesB[hullB.m_faceOffset+closestFaceB];
+ const b3GpuFace& polyB = facesB[hullB.m_faceOffset + closestFaceB];
const int numVertices = polyB.m_numIndices;
- for(int e0=0;e0<numVertices;e0++)
+ for (int e0 = 0; e0 < numVertices; e0++)
{
- const float4& b = verticesB[hullB.m_vertexOffset+indicesB[polyB.m_indexOffset+e0]];
- worldVertsB1[numWorldVertsB1++] = transform(&b,&posB,&ornB);
+ const float4& b = verticesB[hullB.m_vertexOffset + indicesB[polyB.m_indexOffset + e0]];
+ worldVertsB1[numWorldVertsB1++] = transform(&b, &posB, &ornB);
}
}
- if (closestFaceB>=0)
+ if (closestFaceB >= 0)
{
//B3_PROFILE("clipFaceAgainstHull");
- numContactsOut = clipFaceAgainstHull((float4&)separatingNormal, &hullA,
- posA,ornA,
- worldVertsB1,numWorldVertsB1,worldVertsB2,capacityWorldVerts, minDist, maxDist,
- verticesA, facesA, indicesA,
- contactsOut,contactCapacity);
+ numContactsOut = clipFaceAgainstHull((float4&)separatingNormal, &hullA,
+ posA, ornA,
+ worldVertsB1, numWorldVertsB1, worldVertsB2, capacityWorldVerts, minDist, maxDist,
+ verticesA, facesA, indicesA,
+ contactsOut, contactCapacity);
}
return numContactsOut;
}
+#define PARALLEL_SUM(v, n) \
+ for (int j = 1; j < n; j++) v[0] += v[j];
+#define PARALLEL_DO(execution, n) \
+ for (int ie = 0; ie < n; ie++) \
+ { \
+ execution; \
+ }
+#define REDUCE_MAX(v, n) \
+ { \
+ int i = 0; \
+ for (int offset = 0; offset < n; offset++) v[i] = (v[i].y > v[i + offset].y) ? v[i] : v[i + offset]; \
+ }
+#define REDUCE_MIN(v, n) \
+ { \
+ int i = 0; \
+ for (int offset = 0; offset < n; offset++) v[i] = (v[i].y < v[i + offset].y) ? v[i] : v[i + offset]; \
+ }
+int extractManifold(const float4* p, int nPoints, const float4& nearNormal, b3Int4* contactIdx)
+{
+ if (nPoints == 0)
+ return 0;
+ if (nPoints <= 4)
+ return nPoints;
+ if (nPoints > 64)
+ nPoints = 64;
-
-#define PARALLEL_SUM(v, n) for(int j=1; j<n; j++) v[0] += v[j];
-#define PARALLEL_DO(execution, n) for(int ie=0; ie<n; ie++){execution;}
-#define REDUCE_MAX(v, n) {int i=0;\
-for(int offset=0; offset<n; offset++) v[i] = (v[i].y > v[i+offset].y)? v[i]: v[i+offset]; }
-#define REDUCE_MIN(v, n) {int i=0;\
-for(int offset=0; offset<n; offset++) v[i] = (v[i].y < v[i+offset].y)? v[i]: v[i+offset]; }
-
-int extractManifold(const float4* p, int nPoints, const float4& nearNormal, b3Int4* contactIdx)
-{
- if( nPoints == 0 )
- return 0;
-
- if (nPoints <=4)
- return nPoints;
-
-
- if (nPoints >64)
- nPoints = 64;
-
- float4 center = make_float4(0,0,0,0);
+ float4 center = make_float4(0, 0, 0, 0);
{
-
- for (int i=0;i<nPoints;i++)
+ for (int i = 0; i < nPoints; i++)
center += p[i];
center /= (float)nPoints;
}
-
-
-
+
// sample 4 directions
-
- float4 aVector = p[0] - center;
- float4 u = cross3( nearNormal, aVector );
- float4 v = cross3( nearNormal, u );
- u = normalize3( u );
- v = normalize3( v );
-
-
- //keep point with deepest penetration
- float minW= FLT_MAX;
-
- int minIndex=-1;
-
- float4 maxDots;
- maxDots.x = FLT_MIN;
- maxDots.y = FLT_MIN;
- maxDots.z = FLT_MIN;
- maxDots.w = FLT_MIN;
-
- // idx, distance
- for(int ie = 0; ie<nPoints; ie++ )
- {
- if (p[ie].w<minW)
- {
- minW = p[ie].w;
- minIndex=ie;
- }
- float f;
- float4 r = p[ie]-center;
- f = dot3F4( u, r );
- if (f<maxDots.x)
- {
- maxDots.x = f;
- contactIdx[0].x = ie;
- }
-
- f = dot3F4( -u, r );
- if (f<maxDots.y)
- {
- maxDots.y = f;
- contactIdx[0].y = ie;
- }
-
-
- f = dot3F4( v, r );
- if (f<maxDots.z)
- {
- maxDots.z = f;
- contactIdx[0].z = ie;
- }
-
- f = dot3F4( -v, r );
- if (f<maxDots.w)
- {
- maxDots.w = f;
- contactIdx[0].w = ie;
- }
-
- }
-
- if (contactIdx[0].x != minIndex && contactIdx[0].y != minIndex && contactIdx[0].z != minIndex && contactIdx[0].w != minIndex)
- {
- //replace the first contact with minimum (todo: replace contact with least penetration)
- contactIdx[0].x = minIndex;
- }
-
- return 4;
-
-}
+ float4 aVector = p[0] - center;
+ float4 u = cross3(nearNormal, aVector);
+ float4 v = cross3(nearNormal, u);
+ u = normalize3(u);
+ v = normalize3(v);
+
+ //keep point with deepest penetration
+ float minW = FLT_MAX;
+ int minIndex = -1;
+ float4 maxDots;
+ maxDots.x = FLT_MIN;
+ maxDots.y = FLT_MIN;
+ maxDots.z = FLT_MIN;
+ maxDots.w = FLT_MIN;
+
+ // idx, distance
+ for (int ie = 0; ie < nPoints; ie++)
+ {
+ if (p[ie].w < minW)
+ {
+ minW = p[ie].w;
+ minIndex = ie;
+ }
+ float f;
+ float4 r = p[ie] - center;
+ f = dot3F4(u, r);
+ if (f < maxDots.x)
+ {
+ maxDots.x = f;
+ contactIdx[0].x = ie;
+ }
+
+ f = dot3F4(-u, r);
+ if (f < maxDots.y)
+ {
+ maxDots.y = f;
+ contactIdx[0].y = ie;
+ }
+
+ f = dot3F4(v, r);
+ if (f < maxDots.z)
+ {
+ maxDots.z = f;
+ contactIdx[0].z = ie;
+ }
+
+ f = dot3F4(-v, r);
+ if (f < maxDots.w)
+ {
+ maxDots.w = f;
+ contactIdx[0].w = ie;
+ }
+ }
+
+ if (contactIdx[0].x != minIndex && contactIdx[0].y != minIndex && contactIdx[0].z != minIndex && contactIdx[0].w != minIndex)
+ {
+ //replace the first contact with minimum (todo: replace contact with least penetration)
+ contactIdx[0].x = minIndex;
+ }
+
+ return 4;
+}
int clipHullHullSingle(
- int bodyIndexA, int bodyIndexB,
- const float4& posA,
- const b3Quaternion& ornA,
- const float4& posB,
- const b3Quaternion& ornB,
+ int bodyIndexA, int bodyIndexB,
+ const float4& posA,
+ const b3Quaternion& ornA,
+ const float4& posB,
+ const b3Quaternion& ornB,
- int collidableIndexA, int collidableIndexB,
+ int collidableIndexA, int collidableIndexB,
- const b3AlignedObjectArray<b3RigidBodyData>* bodyBuf,
- b3AlignedObjectArray<b3Contact4>* globalContactOut,
- int& nContacts,
-
- const b3AlignedObjectArray<b3ConvexPolyhedronData>& hostConvexDataA,
- const b3AlignedObjectArray<b3ConvexPolyhedronData>& hostConvexDataB,
-
- const b3AlignedObjectArray<b3Vector3>& verticesA,
- const b3AlignedObjectArray<b3Vector3>& uniqueEdgesA,
- const b3AlignedObjectArray<b3GpuFace>& facesA,
- const b3AlignedObjectArray<int>& indicesA,
-
- const b3AlignedObjectArray<b3Vector3>& verticesB,
- const b3AlignedObjectArray<b3Vector3>& uniqueEdgesB,
- const b3AlignedObjectArray<b3GpuFace>& facesB,
- const b3AlignedObjectArray<int>& indicesB,
-
- const b3AlignedObjectArray<b3Collidable>& hostCollidablesA,
- const b3AlignedObjectArray<b3Collidable>& hostCollidablesB,
- const b3Vector3& sepNormalWorldSpace,
- int maxContactCapacity )
+ const b3AlignedObjectArray<b3RigidBodyData>* bodyBuf,
+ b3AlignedObjectArray<b3Contact4>* globalContactOut,
+ int& nContacts,
+
+ const b3AlignedObjectArray<b3ConvexPolyhedronData>& hostConvexDataA,
+ const b3AlignedObjectArray<b3ConvexPolyhedronData>& hostConvexDataB,
+
+ const b3AlignedObjectArray<b3Vector3>& verticesA,
+ const b3AlignedObjectArray<b3Vector3>& uniqueEdgesA,
+ const b3AlignedObjectArray<b3GpuFace>& facesA,
+ const b3AlignedObjectArray<int>& indicesA,
+
+ const b3AlignedObjectArray<b3Vector3>& verticesB,
+ const b3AlignedObjectArray<b3Vector3>& uniqueEdgesB,
+ const b3AlignedObjectArray<b3GpuFace>& facesB,
+ const b3AlignedObjectArray<int>& indicesB,
+
+ const b3AlignedObjectArray<b3Collidable>& hostCollidablesA,
+ const b3AlignedObjectArray<b3Collidable>& hostCollidablesB,
+ const b3Vector3& sepNormalWorldSpace,
+ int maxContactCapacity)
{
int contactIndex = -1;
b3ConvexPolyhedronData hullA, hullB;
-
- b3Collidable colA = hostCollidablesA[collidableIndexA];
- hullA = hostConvexDataA[colA.m_shapeIndex];
- //printf("numvertsA = %d\n",hullA.m_numVertices);
-
-
- b3Collidable colB = hostCollidablesB[collidableIndexB];
- hullB = hostConvexDataB[colB.m_shapeIndex];
- //printf("numvertsB = %d\n",hullB.m_numVertices);
-
-
+
+ b3Collidable colA = hostCollidablesA[collidableIndexA];
+ hullA = hostConvexDataA[colA.m_shapeIndex];
+ //printf("numvertsA = %d\n",hullA.m_numVertices);
+
+ b3Collidable colB = hostCollidablesB[collidableIndexB];
+ hullB = hostConvexDataB[colB.m_shapeIndex];
+ //printf("numvertsB = %d\n",hullB.m_numVertices);
+
float4 contactsOut[MAX_VERTS];
int localContactCapacity = MAX_VERTS;
@@ -1249,133 +1177,125 @@ int clipHullHullSingle(
b3Assert(_finite(bodyBuf->at(bodyIndexA).m_pos.x));
b3Assert(_finite(bodyBuf->at(bodyIndexB).m_pos.x));
#endif
-
-
+
{
-
float4 worldVertsB1[MAX_VERTS];
float4 worldVertsB2[MAX_VERTS];
int capacityWorldVerts = MAX_VERTS;
- float4 hostNormal = make_float4(sepNormalWorldSpace.x,sepNormalWorldSpace.y,sepNormalWorldSpace.z,0.f);
+ float4 hostNormal = make_float4(sepNormalWorldSpace.x, sepNormalWorldSpace.y, sepNormalWorldSpace.z, 0.f);
int shapeA = hostCollidablesA[collidableIndexA].m_shapeIndex;
int shapeB = hostCollidablesB[collidableIndexB].m_shapeIndex;
b3Scalar minDist = -1;
b3Scalar maxDist = 0.;
-
-
- b3Transform trA,trB;
+ b3Transform trA, trB;
{
- //B3_PROFILE("transform computation");
- //trA.setIdentity();
- trA.setOrigin(b3MakeVector3(posA.x,posA.y,posA.z));
- trA.setRotation(b3Quaternion(ornA.x,ornA.y,ornA.z,ornA.w));
-
- //trB.setIdentity();
- trB.setOrigin(b3MakeVector3(posB.x,posB.y,posB.z));
- trB.setRotation(b3Quaternion(ornB.x,ornB.y,ornB.z,ornB.w));
+ //B3_PROFILE("transform computation");
+ //trA.setIdentity();
+ trA.setOrigin(b3MakeVector3(posA.x, posA.y, posA.z));
+ trA.setRotation(b3Quaternion(ornA.x, ornA.y, ornA.z, ornA.w));
+
+ //trB.setIdentity();
+ trB.setOrigin(b3MakeVector3(posB.x, posB.y, posB.z));
+ trB.setRotation(b3Quaternion(ornB.x, ornB.y, ornB.z, ornB.w));
}
b3Quaternion trAorn = trA.getRotation();
- b3Quaternion trBorn = trB.getRotation();
-
- int numContactsOut = clipHullAgainstHull(hostNormal,
- hostConvexDataA.at(shapeA),
- hostConvexDataB.at(shapeB),
- (float4&)trA.getOrigin(), (b3Quaternion&)trAorn,
- (float4&)trB.getOrigin(), (b3Quaternion&)trBorn,
- worldVertsB1,worldVertsB2,capacityWorldVerts,
- minDist, maxDist,
- verticesA, facesA,indicesA,
- verticesB, facesB,indicesB,
-
- contactsOut,localContactCapacity);
-
- if (numContactsOut>0)
+ b3Quaternion trBorn = trB.getRotation();
+
+ int numContactsOut = clipHullAgainstHull(hostNormal,
+ hostConvexDataA.at(shapeA),
+ hostConvexDataB.at(shapeB),
+ (float4&)trA.getOrigin(), (b3Quaternion&)trAorn,
+ (float4&)trB.getOrigin(), (b3Quaternion&)trBorn,
+ worldVertsB1, worldVertsB2, capacityWorldVerts,
+ minDist, maxDist,
+ verticesA, facesA, indicesA,
+ verticesB, facesB, indicesB,
+
+ contactsOut, localContactCapacity);
+
+ if (numContactsOut > 0)
{
B3_PROFILE("overlap");
float4 normalOnSurfaceB = (float4&)hostNormal;
-
+
b3Int4 contactIdx;
contactIdx.x = 0;
contactIdx.y = 1;
contactIdx.z = 2;
contactIdx.w = 3;
-
+
int numPoints = 0;
-
+
{
- // B3_PROFILE("extractManifold");
- numPoints = extractManifold(contactsOut, numContactsOut, normalOnSurfaceB, &contactIdx);
+ // B3_PROFILE("extractManifold");
+ numPoints = extractManifold(contactsOut, numContactsOut, normalOnSurfaceB, &contactIdx);
}
-
+
b3Assert(numPoints);
-
- if (nContacts<maxContactCapacity)
+
+ if (nContacts < maxContactCapacity)
{
contactIndex = nContacts;
globalContactOut->expand();
b3Contact4& contact = globalContactOut->at(nContacts);
- contact.m_batchIdx = 0;//i;
- contact.m_bodyAPtrAndSignBit = (bodyBuf->at(bodyIndexA).m_invMass==0)? -bodyIndexA:bodyIndexA;
- contact.m_bodyBPtrAndSignBit = (bodyBuf->at(bodyIndexB).m_invMass==0)? -bodyIndexB:bodyIndexB;
+ contact.m_batchIdx = 0; //i;
+ contact.m_bodyAPtrAndSignBit = (bodyBuf->at(bodyIndexA).m_invMass == 0) ? -bodyIndexA : bodyIndexA;
+ contact.m_bodyBPtrAndSignBit = (bodyBuf->at(bodyIndexB).m_invMass == 0) ? -bodyIndexB : bodyIndexB;
contact.m_frictionCoeffCmp = 45874;
contact.m_restituitionCoeffCmp = 0;
-
- // float distance = 0.f;
- for (int p=0;p<numPoints;p++)
+
+ // float distance = 0.f;
+ for (int p = 0; p < numPoints; p++)
{
- contact.m_worldPosB[p] = contactsOut[contactIdx.s[p]];//check if it is actually on B
- contact.m_worldNormalOnB = normalOnSurfaceB;
+ contact.m_worldPosB[p] = contactsOut[contactIdx.s[p]]; //check if it is actually on B
+ contact.m_worldNormalOnB = normalOnSurfaceB;
}
//printf("bodyIndexA %d,bodyIndexB %d,normal=%f,%f,%f numPoints %d\n",bodyIndexA,bodyIndexB,normalOnSurfaceB.x,normalOnSurfaceB.y,normalOnSurfaceB.z,numPoints);
contact.m_worldNormalOnB.w = (b3Scalar)numPoints;
nContacts++;
- } else
+ }
+ else
{
- b3Error("Error: exceeding contact capacity (%d/%d)\n", nContacts,maxContactCapacity);
+ b3Error("Error: exceeding contact capacity (%d/%d)\n", nContacts, maxContactCapacity);
}
}
}
return contactIndex;
}
-
-
-
-
void computeContactPlaneConvex(int pairIndex,
- int bodyIndexA, int bodyIndexB,
- int collidableIndexA, int collidableIndexB,
- const b3RigidBodyData* rigidBodies,
- const b3Collidable* collidables,
- const b3ConvexPolyhedronData* convexShapes,
- const b3Vector3* convexVertices,
- const int* convexIndices,
- const b3GpuFace* faces,
- b3Contact4* globalContactsOut,
- int& nGlobalContactsOut,
- int maxContactCapacity)
+ int bodyIndexA, int bodyIndexB,
+ int collidableIndexA, int collidableIndexB,
+ const b3RigidBodyData* rigidBodies,
+ const b3Collidable* collidables,
+ const b3ConvexPolyhedronData* convexShapes,
+ const b3Vector3* convexVertices,
+ const int* convexIndices,
+ const b3GpuFace* faces,
+ b3Contact4* globalContactsOut,
+ int& nGlobalContactsOut,
+ int maxContactCapacity)
{
-
- int shapeIndex = collidables[collidableIndexB].m_shapeIndex;
+ int shapeIndex = collidables[collidableIndexB].m_shapeIndex;
const b3ConvexPolyhedronData* hullB = &convexShapes[shapeIndex];
-
+
b3Vector3 posB = rigidBodies[bodyIndexB].m_pos;
b3Quaternion ornB = rigidBodies[bodyIndexB].m_quat;
b3Vector3 posA = rigidBodies[bodyIndexA].m_pos;
b3Quaternion ornA = rigidBodies[bodyIndexA].m_quat;
-// int numContactsOut = 0;
-// int numWorldVertsB1= 0;
+ // int numContactsOut = 0;
+ // int numWorldVertsB1= 0;
b3Vector3 planeEq = faces[collidables[collidableIndexA].m_shapeIndex].m_plane;
- b3Vector3 planeNormal=b3MakeVector3(planeEq.x,planeEq.y,planeEq.z);
- b3Vector3 planeNormalWorld = b3QuatRotate(ornA,planeNormal);
+ b3Vector3 planeNormal = b3MakeVector3(planeEq.x, planeEq.y, planeEq.z);
+ b3Vector3 planeNormalWorld = b3QuatRotate(ornA, planeNormal);
float planeConstant = planeEq.w;
b3Transform convexWorldTransform;
convexWorldTransform.setIdentity();
@@ -1387,13 +1307,13 @@ void computeContactPlaneConvex(int pairIndex,
planeTransform.setRotation(ornA);
b3Transform planeInConvex;
- planeInConvex= convexWorldTransform.inverse() * planeTransform;
+ planeInConvex = convexWorldTransform.inverse() * planeTransform;
b3Transform convexInPlane;
convexInPlane = planeTransform.inverse() * convexWorldTransform;
-
- b3Vector3 planeNormalInConvex = planeInConvex.getBasis()*-planeNormal;
+
+ b3Vector3 planeNormalInConvex = planeInConvex.getBasis() * -planeNormal;
float maxDot = -1e30;
- int hitVertex=-1;
+ int hitVertex = -1;
b3Vector3 hitVtx;
#define MAX_PLANE_CONVEX_POINTS 64
@@ -1406,54 +1326,52 @@ void computeContactPlaneConvex(int pairIndex,
contactIdx.s[1] = 1;
contactIdx.s[2] = 2;
contactIdx.s[3] = 3;
-
- for (int i=0;i<hullB->m_numVertices;i++)
+
+ for (int i = 0; i < hullB->m_numVertices; i++)
{
- b3Vector3 vtx = convexVertices[hullB->m_vertexOffset+i];
+ b3Vector3 vtx = convexVertices[hullB->m_vertexOffset + i];
float curDot = vtx.dot(planeNormalInConvex);
-
- if (curDot>maxDot)
+ if (curDot > maxDot)
{
- hitVertex=i;
- maxDot=curDot;
+ hitVertex = i;
+ maxDot = curDot;
hitVtx = vtx;
//make sure the deepest points is always included
- if (numPoints==MAX_PLANE_CONVEX_POINTS)
+ if (numPoints == MAX_PLANE_CONVEX_POINTS)
numPoints--;
}
- if (numPoints<MAX_PLANE_CONVEX_POINTS)
+ if (numPoints < MAX_PLANE_CONVEX_POINTS)
{
- b3Vector3 vtxWorld = convexWorldTransform*vtx;
- b3Vector3 vtxInPlane = planeTransform.inverse()*vtxWorld;
- float dist = planeNormal.dot(vtxInPlane)-planeConstant;
- if (dist<0.f)
+ b3Vector3 vtxWorld = convexWorldTransform * vtx;
+ b3Vector3 vtxInPlane = planeTransform.inverse() * vtxWorld;
+ float dist = planeNormal.dot(vtxInPlane) - planeConstant;
+ if (dist < 0.f)
{
vtxWorld.w = dist;
contactPoints[numPoints] = vtxWorld;
numPoints++;
}
}
-
}
- int numReducedPoints = 0;
+ int numReducedPoints = 0;
numReducedPoints = numPoints;
-
- if (numPoints>4)
+
+ if (numPoints > 4)
{
- numReducedPoints = extractManifoldSequentialGlobal( contactPoints, numPoints, planeNormalInConvex, &contactIdx);
+ numReducedPoints = extractManifoldSequentialGlobal(contactPoints, numPoints, planeNormalInConvex, &contactIdx);
}
int dstIdx;
-// dstIdx = nGlobalContactsOut++;//AppendInc( nGlobalContactsOut, dstIdx );
-
- if (numReducedPoints>0)
+ // dstIdx = nGlobalContactsOut++;//AppendInc( nGlobalContactsOut, dstIdx );
+
+ if (numReducedPoints > 0)
{
if (nGlobalContactsOut < maxContactCapacity)
{
- dstIdx=nGlobalContactsOut;
+ dstIdx = nGlobalContactsOut;
nGlobalContactsOut++;
b3Contact4* c = &globalContactsOut[dstIdx];
@@ -1462,38 +1380,33 @@ void computeContactPlaneConvex(int pairIndex,
c->setRestituitionCoeff(0.f);
c->m_batchIdx = pairIndex;
- c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;
- c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;
- for (int i=0;i<numReducedPoints;i++)
+ c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass == 0 ? -bodyIndexA : bodyIndexA;
+ c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass == 0 ? -bodyIndexB : bodyIndexB;
+ for (int i = 0; i < numReducedPoints; i++)
{
b3Vector3 pOnB1 = contactPoints[contactIdx.s[i]];
c->m_worldPosB[i] = pOnB1;
}
c->m_worldNormalOnB.w = (b3Scalar)numReducedPoints;
- }//if (dstIdx < numPairs)
- }
-
-
+ } //if (dstIdx < numPairs)
+ }
-// printf("computeContactPlaneConvex\n");
+ // printf("computeContactPlaneConvex\n");
}
-
-
-B3_FORCE_INLINE b3Vector3 MyUnQuantize(const unsigned short* vecIn, const b3Vector3& quantization, const b3Vector3& bvhAabbMin)
- {
- b3Vector3 vecOut;
- vecOut.setValue(
- (b3Scalar)(vecIn[0]) / (quantization.x),
- (b3Scalar)(vecIn[1]) / (quantization.y),
- (b3Scalar)(vecIn[2]) / (quantization.z));
- vecOut += bvhAabbMin;
- return vecOut;
- }
+B3_FORCE_INLINE b3Vector3 MyUnQuantize(const unsigned short* vecIn, const b3Vector3& quantization, const b3Vector3& bvhAabbMin)
+{
+ b3Vector3 vecOut;
+ vecOut.setValue(
+ (b3Scalar)(vecIn[0]) / (quantization.x),
+ (b3Scalar)(vecIn[1]) / (quantization.y),
+ (b3Scalar)(vecIn[2]) / (quantization.z));
+ vecOut += bvhAabbMin;
+ return vecOut;
+}
void traverseTreeTree()
{
-
}
#include "Bullet3Common/shared/b3Mat3x3.h"
@@ -1503,44 +1416,40 @@ int maxNumAabbChecks = 0;
int maxDepth = 0;
// work-in-progress
-__kernel void findCompoundPairsKernel(
+__kernel void findCompoundPairsKernel(
int pairIndex,
int bodyIndexA,
int bodyIndexB,
int collidableIndexA,
int collidableIndexB,
- __global const b3RigidBodyData* rigidBodies,
+ __global const b3RigidBodyData* rigidBodies,
__global const b3Collidable* collidables,
- __global const b3ConvexPolyhedronData* convexShapes,
+ __global const b3ConvexPolyhedronData* convexShapes,
__global const b3AlignedObjectArray<b3Float4>& vertices,
__global const b3AlignedObjectArray<b3Aabb>& aabbsWorldSpace,
__global const b3AlignedObjectArray<b3Aabb>& aabbsLocalSpace,
__global const b3GpuChildShape* gpuChildShapes,
__global b3Int4* gpuCompoundPairsOut,
- __global int* numCompoundPairsOut,
+ __global int* numCompoundPairsOut,
int maxNumCompoundPairsCapacity,
- b3AlignedObjectArray<b3QuantizedBvhNode>& treeNodesCPU,
- b3AlignedObjectArray<b3BvhSubtreeInfo>& subTreesCPU,
- b3AlignedObjectArray<b3BvhInfo>& bvhInfoCPU
- )
+ b3AlignedObjectArray<b3QuantizedBvhNode>& treeNodesCPU,
+ b3AlignedObjectArray<b3BvhSubtreeInfo>& subTreesCPU,
+ b3AlignedObjectArray<b3BvhInfo>& bvhInfoCPU)
{
- numAabbChecks=0;
- maxNumAabbChecks=0;
-// int i = pairIndex;
+ numAabbChecks = 0;
+ maxNumAabbChecks = 0;
+ // int i = pairIndex;
{
-
-
int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
-
//once the broadphase avoids static-static pairs, we can remove this test
- if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))
+ if ((rigidBodies[bodyIndexA].m_invMass == 0) && (rigidBodies[bodyIndexB].m_invMass == 0))
{
return;
}
- if ((collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS) &&(collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))
+ if ((collidables[collidableIndexA].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS) && (collidables[collidableIndexB].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS))
{
int bvhA = collidables[collidableIndexA].m_compoundBvhIndex;
int bvhB = collidables[collidableIndexB].m_compoundBvhIndex;
@@ -1548,9 +1457,8 @@ __kernel void findCompoundPairsKernel(
int subTreesOffsetA = bvhInfoCPU[bvhA].m_subTreeOffset;
int subTreesOffsetB = bvhInfoCPU[bvhB].m_subTreeOffset;
-
int numSubTreesB = bvhInfoCPU[bvhB].m_numSubTrees;
-
+
float4 posA = rigidBodies[bodyIndexA].m_pos;
b3Quat ornA = rigidBodies[bodyIndexA].m_quat;
@@ -1567,41 +1475,37 @@ __kernel void findCompoundPairsKernel(
transB.setOrigin(posB);
transB.setRotation(ornB);
-
-
- for (int p=0;p<numSubTreesA;p++)
+ for (int p = 0; p < numSubTreesA; p++)
{
- b3BvhSubtreeInfo subtreeA = subTreesCPU[subTreesOffsetA+p];
+ b3BvhSubtreeInfo subtreeA = subTreesCPU[subTreesOffsetA + p];
//bvhInfoCPU[bvhA].m_quantization
- b3Vector3 treeAminLocal = MyUnQuantize(subtreeA.m_quantizedAabbMin,bvhInfoCPU[bvhA].m_quantization,bvhInfoCPU[bvhA].m_aabbMin);
- b3Vector3 treeAmaxLocal = MyUnQuantize(subtreeA.m_quantizedAabbMax,bvhInfoCPU[bvhA].m_quantization,bvhInfoCPU[bvhA].m_aabbMin);
+ b3Vector3 treeAminLocal = MyUnQuantize(subtreeA.m_quantizedAabbMin, bvhInfoCPU[bvhA].m_quantization, bvhInfoCPU[bvhA].m_aabbMin);
+ b3Vector3 treeAmaxLocal = MyUnQuantize(subtreeA.m_quantizedAabbMax, bvhInfoCPU[bvhA].m_quantization, bvhInfoCPU[bvhA].m_aabbMin);
- b3Vector3 aabbAMinOut,aabbAMaxOut;
- float margin=0.f;
- b3TransformAabb2(treeAminLocal,treeAmaxLocal, margin,transA.getOrigin(),transA.getRotation(),&aabbAMinOut,&aabbAMaxOut);
+ b3Vector3 aabbAMinOut, aabbAMaxOut;
+ float margin = 0.f;
+ b3TransformAabb2(treeAminLocal, treeAmaxLocal, margin, transA.getOrigin(), transA.getRotation(), &aabbAMinOut, &aabbAMaxOut);
- for (int q=0;q<numSubTreesB;q++)
+ for (int q = 0; q < numSubTreesB; q++)
{
- b3BvhSubtreeInfo subtreeB = subTreesCPU[subTreesOffsetB+q];
+ b3BvhSubtreeInfo subtreeB = subTreesCPU[subTreesOffsetB + q];
- b3Vector3 treeBminLocal = MyUnQuantize(subtreeB.m_quantizedAabbMin,bvhInfoCPU[bvhB].m_quantization,bvhInfoCPU[bvhB].m_aabbMin);
- b3Vector3 treeBmaxLocal = MyUnQuantize(subtreeB.m_quantizedAabbMax,bvhInfoCPU[bvhB].m_quantization,bvhInfoCPU[bvhB].m_aabbMin);
+ b3Vector3 treeBminLocal = MyUnQuantize(subtreeB.m_quantizedAabbMin, bvhInfoCPU[bvhB].m_quantization, bvhInfoCPU[bvhB].m_aabbMin);
+ b3Vector3 treeBmaxLocal = MyUnQuantize(subtreeB.m_quantizedAabbMax, bvhInfoCPU[bvhB].m_quantization, bvhInfoCPU[bvhB].m_aabbMin);
- b3Vector3 aabbBMinOut,aabbBMaxOut;
- float margin=0.f;
- b3TransformAabb2(treeBminLocal,treeBmaxLocal, margin,transB.getOrigin(),transB.getRotation(),&aabbBMinOut,&aabbBMaxOut);
+ b3Vector3 aabbBMinOut, aabbBMaxOut;
+ float margin = 0.f;
+ b3TransformAabb2(treeBminLocal, treeBmaxLocal, margin, transB.getOrigin(), transB.getRotation(), &aabbBMinOut, &aabbBMaxOut);
-
- numAabbChecks=0;
- bool aabbOverlap = b3TestAabbAgainstAabb(aabbAMinOut,aabbAMaxOut,aabbBMinOut,aabbBMaxOut);
+ numAabbChecks = 0;
+ bool aabbOverlap = b3TestAabbAgainstAabb(aabbAMinOut, aabbAMaxOut, aabbBMinOut, aabbBMaxOut);
if (aabbOverlap)
{
-
- int startNodeIndexA = subtreeA.m_rootNodeIndex+bvhInfoCPU[bvhA].m_nodeOffset;
- // int endNodeIndexA = startNodeIndexA+subtreeA.m_subtreeSize;
+ int startNodeIndexA = subtreeA.m_rootNodeIndex + bvhInfoCPU[bvhA].m_nodeOffset;
+ // int endNodeIndexA = startNodeIndexA+subtreeA.m_subtreeSize;
- int startNodeIndexB = subtreeB.m_rootNodeIndex+bvhInfoCPU[bvhB].m_nodeOffset;
- // int endNodeIndexB = startNodeIndexB+subtreeB.m_subtreeSize;
+ int startNodeIndexB = subtreeB.m_rootNodeIndex + bvhInfoCPU[bvhB].m_nodeOffset;
+ // int endNodeIndexB = startNodeIndexB+subtreeB.m_subtreeSize;
b3AlignedObjectArray<b3Int2> nodeStack;
b3Int2 node0;
@@ -1610,33 +1514,33 @@ __kernel void findCompoundPairsKernel(
int maxStackDepth = 1024;
nodeStack.resize(maxStackDepth);
- int depth=0;
- nodeStack[depth++]=node0;
+ int depth = 0;
+ nodeStack[depth++] = node0;
do
{
if (depth > maxDepth)
{
- maxDepth=depth;
- printf("maxDepth=%d\n",maxDepth);
+ maxDepth = depth;
+ printf("maxDepth=%d\n", maxDepth);
}
b3Int2 node = nodeStack[--depth];
-
- b3Vector3 aMinLocal = MyUnQuantize(treeNodesCPU[node.x].m_quantizedAabbMin,bvhInfoCPU[bvhA].m_quantization,bvhInfoCPU[bvhA].m_aabbMin);
- b3Vector3 aMaxLocal = MyUnQuantize(treeNodesCPU[node.x].m_quantizedAabbMax,bvhInfoCPU[bvhA].m_quantization,bvhInfoCPU[bvhA].m_aabbMin);
- b3Vector3 bMinLocal = MyUnQuantize(treeNodesCPU[node.y].m_quantizedAabbMin,bvhInfoCPU[bvhB].m_quantization,bvhInfoCPU[bvhB].m_aabbMin);
- b3Vector3 bMaxLocal = MyUnQuantize(treeNodesCPU[node.y].m_quantizedAabbMax,bvhInfoCPU[bvhB].m_quantization,bvhInfoCPU[bvhB].m_aabbMin);
+ b3Vector3 aMinLocal = MyUnQuantize(treeNodesCPU[node.x].m_quantizedAabbMin, bvhInfoCPU[bvhA].m_quantization, bvhInfoCPU[bvhA].m_aabbMin);
+ b3Vector3 aMaxLocal = MyUnQuantize(treeNodesCPU[node.x].m_quantizedAabbMax, bvhInfoCPU[bvhA].m_quantization, bvhInfoCPU[bvhA].m_aabbMin);
- float margin=0.f;
- b3Vector3 aabbAMinOut,aabbAMaxOut;
- b3TransformAabb2(aMinLocal,aMaxLocal, margin,transA.getOrigin(),transA.getRotation(),&aabbAMinOut,&aabbAMaxOut);
+ b3Vector3 bMinLocal = MyUnQuantize(treeNodesCPU[node.y].m_quantizedAabbMin, bvhInfoCPU[bvhB].m_quantization, bvhInfoCPU[bvhB].m_aabbMin);
+ b3Vector3 bMaxLocal = MyUnQuantize(treeNodesCPU[node.y].m_quantizedAabbMax, bvhInfoCPU[bvhB].m_quantization, bvhInfoCPU[bvhB].m_aabbMin);
- b3Vector3 aabbBMinOut,aabbBMaxOut;
- b3TransformAabb2(bMinLocal,bMaxLocal, margin,transB.getOrigin(),transB.getRotation(),&aabbBMinOut,&aabbBMaxOut);
+ float margin = 0.f;
+ b3Vector3 aabbAMinOut, aabbAMaxOut;
+ b3TransformAabb2(aMinLocal, aMaxLocal, margin, transA.getOrigin(), transA.getRotation(), &aabbAMinOut, &aabbAMaxOut);
+
+ b3Vector3 aabbBMinOut, aabbBMaxOut;
+ b3TransformAabb2(bMinLocal, bMaxLocal, margin, transB.getOrigin(), transB.getRotation(), &aabbBMinOut, &aabbBMaxOut);
numAabbChecks++;
- bool nodeOverlap = b3TestAabbAgainstAabb(aabbAMinOut,aabbAMaxOut,aabbBMinOut,aabbBMaxOut);
+ bool nodeOverlap = b3TestAabbAgainstAabb(aabbAMinOut, aabbAMaxOut, aabbBMinOut, aabbBMaxOut);
if (nodeOverlap)
{
bool isLeafA = treeNodesCPU[node.x].isLeafNode();
@@ -1645,23 +1549,23 @@ __kernel void findCompoundPairsKernel(
bool isInternalB = !isLeafB;
//fail, even though it might hit two leaf nodes
- if (depth+4>maxStackDepth && !(isLeafA && isLeafB))
+ if (depth + 4 > maxStackDepth && !(isLeafA && isLeafB))
{
b3Error("Error: traversal exceeded maxStackDepth\n");
continue;
}
- if(isInternalA)
+ if (isInternalA)
{
- int nodeAleftChild = node.x+1;
- bool isNodeALeftChildLeaf = treeNodesCPU[node.x+1].isLeafNode();
- int nodeArightChild = isNodeALeftChildLeaf? node.x+2 : node.x+1 + treeNodesCPU[node.x+1].getEscapeIndex();
+ int nodeAleftChild = node.x + 1;
+ bool isNodeALeftChildLeaf = treeNodesCPU[node.x + 1].isLeafNode();
+ int nodeArightChild = isNodeALeftChildLeaf ? node.x + 2 : node.x + 1 + treeNodesCPU[node.x + 1].getEscapeIndex();
- if(isInternalB)
- {
- int nodeBleftChild = node.y+1;
- bool isNodeBLeftChildLeaf = treeNodesCPU[node.y+1].isLeafNode();
- int nodeBrightChild = isNodeBLeftChildLeaf? node.y+2 : node.y+1 + treeNodesCPU[node.y+1].getEscapeIndex();
+ if (isInternalB)
+ {
+ int nodeBleftChild = node.y + 1;
+ bool isNodeBLeftChildLeaf = treeNodesCPU[node.y + 1].isLeafNode();
+ int nodeBrightChild = isNodeBLeftChildLeaf ? node.y + 2 : node.y + 1 + treeNodesCPU[node.y + 1].getEscapeIndex();
nodeStack[depth++] = b3MakeInt2(nodeAleftChild, nodeBleftChild);
nodeStack[depth++] = b3MakeInt2(nodeArightChild, nodeBleftChild);
@@ -1670,90 +1574,83 @@ __kernel void findCompoundPairsKernel(
}
else
{
- nodeStack[depth++] = b3MakeInt2(nodeAleftChild,node.y);
- nodeStack[depth++] = b3MakeInt2(nodeArightChild,node.y);
+ nodeStack[depth++] = b3MakeInt2(nodeAleftChild, node.y);
+ nodeStack[depth++] = b3MakeInt2(nodeArightChild, node.y);
}
}
else
{
- if(isInternalB)
+ if (isInternalB)
{
- int nodeBleftChild = node.y+1;
- bool isNodeBLeftChildLeaf = treeNodesCPU[node.y+1].isLeafNode();
- int nodeBrightChild = isNodeBLeftChildLeaf? node.y+2 : node.y+1 + treeNodesCPU[node.y+1].getEscapeIndex();
- nodeStack[depth++] = b3MakeInt2(node.x,nodeBleftChild);
- nodeStack[depth++] = b3MakeInt2(node.x,nodeBrightChild);
+ int nodeBleftChild = node.y + 1;
+ bool isNodeBLeftChildLeaf = treeNodesCPU[node.y + 1].isLeafNode();
+ int nodeBrightChild = isNodeBLeftChildLeaf ? node.y + 2 : node.y + 1 + treeNodesCPU[node.y + 1].getEscapeIndex();
+ nodeStack[depth++] = b3MakeInt2(node.x, nodeBleftChild);
+ nodeStack[depth++] = b3MakeInt2(node.x, nodeBrightChild);
}
else
{
int compoundPairIdx = b3AtomicInc(numCompoundPairsOut);
- if (compoundPairIdx<maxNumCompoundPairsCapacity)
+ if (compoundPairIdx < maxNumCompoundPairsCapacity)
{
int childShapeIndexA = treeNodesCPU[node.x].getTriangleIndex();
int childShapeIndexB = treeNodesCPU[node.y].getTriangleIndex();
- gpuCompoundPairsOut[compoundPairIdx] = b3MakeInt4(bodyIndexA,bodyIndexB,childShapeIndexA,childShapeIndexB);
+ gpuCompoundPairsOut[compoundPairIdx] = b3MakeInt4(bodyIndexA, bodyIndexB, childShapeIndexA, childShapeIndexB);
}
}
}
}
} while (depth);
- maxNumAabbChecks = b3Max(numAabbChecks,maxNumAabbChecks);
+ maxNumAabbChecks = b3Max(numAabbChecks, maxNumAabbChecks);
}
}
}
-
+
return;
}
- if ((collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS) ||(collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))
+ if ((collidables[collidableIndexA].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS) || (collidables[collidableIndexB].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS))
{
-
- if (collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+ if (collidables[collidableIndexA].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS)
{
-
int numChildrenA = collidables[collidableIndexA].m_numChildShapes;
- for (int c=0;c<numChildrenA;c++)
+ for (int c = 0; c < numChildrenA; c++)
{
- int childShapeIndexA = collidables[collidableIndexA].m_shapeIndex+c;
+ int childShapeIndexA = collidables[collidableIndexA].m_shapeIndex + c;
int childColIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;
float4 posA = rigidBodies[bodyIndexA].m_pos;
b3Quat ornA = rigidBodies[bodyIndexA].m_quat;
float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;
b3Quat childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;
- float4 newPosA = b3QuatRotate(ornA,childPosA)+posA;
- b3Quat newOrnA = b3QuatMul(ornA,childOrnA);
-
+ float4 newPosA = b3QuatRotate(ornA, childPosA) + posA;
+ b3Quat newOrnA = b3QuatMul(ornA, childOrnA);
-
b3Aabb aabbA = aabbsLocalSpace[childColIndexA];
-
b3Transform transA;
transA.setIdentity();
transA.setOrigin(newPosA);
transA.setRotation(newOrnA);
- b3Scalar margin=0.0f;
+ b3Scalar margin = 0.0f;
- b3Vector3 aabbAMinOut,aabbAMaxOut;
+ b3Vector3 aabbAMinOut, aabbAMaxOut;
- b3TransformAabb2((const b3Float4&)aabbA.m_min,(const b3Float4&)aabbA.m_max, margin,transA.getOrigin(),transA.getRotation(),&aabbAMinOut,&aabbAMaxOut);
+ b3TransformAabb2((const b3Float4&)aabbA.m_min, (const b3Float4&)aabbA.m_max, margin, transA.getOrigin(), transA.getRotation(), &aabbAMinOut, &aabbAMaxOut);
- if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+ if (collidables[collidableIndexB].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS)
{
int numChildrenB = collidables[collidableIndexB].m_numChildShapes;
- for (int b=0;b<numChildrenB;b++)
+ for (int b = 0; b < numChildrenB; b++)
{
- int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex+b;
+ int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex + b;
int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
b3Quat ornB = rigidBodies[bodyIndexB].m_quat;
float4 posB = rigidBodies[bodyIndexB].m_pos;
float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
b3Quat childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
- float4 newPosB = transform(&childPosB,&posB,&ornB);
- b3Quat newOrnB = b3QuatMul(ornB,childOrnB);
-
-
+ float4 newPosB = transform(&childPosB, &posB, &ornB);
+ b3Quat newOrnB = b3QuatMul(ornB, childOrnB);
b3Aabb aabbB = aabbsLocalSpace[childColIndexB];
@@ -1762,11 +1659,11 @@ __kernel void findCompoundPairsKernel(
transB.setOrigin(newPosB);
transB.setRotation(newOrnB);
- b3Vector3 aabbBMinOut,aabbBMaxOut;
- b3TransformAabb2((const b3Float4&)aabbB.m_min,(const b3Float4&)aabbB.m_max, margin,transB.getOrigin(),transB.getRotation(),&aabbBMinOut,&aabbBMaxOut);
+ b3Vector3 aabbBMinOut, aabbBMaxOut;
+ b3TransformAabb2((const b3Float4&)aabbB.m_min, (const b3Float4&)aabbB.m_max, margin, transB.getOrigin(), transB.getRotation(), &aabbBMinOut, &aabbBMaxOut);
numAabbChecks++;
- bool aabbOverlap = b3TestAabbAgainstAabb(aabbAMinOut,aabbAMaxOut,aabbBMinOut,aabbBMaxOut);
+ bool aabbOverlap = b3TestAabbAgainstAabb(aabbAMinOut, aabbAMaxOut, aabbBMinOut, aabbBMaxOut);
if (aabbOverlap)
{
/*
@@ -1784,22 +1681,22 @@ __kernel void findCompoundPairsKernel(
float4 c1 = transform(&c1local,&posB,&ornB);
const float4 DeltaC2 = c0 - c1;
*/
- {//
+ { //
int compoundPairIdx = b3AtomicInc(numCompoundPairsOut);
- if (compoundPairIdx<maxNumCompoundPairsCapacity)
+ if (compoundPairIdx < maxNumCompoundPairsCapacity)
{
- gpuCompoundPairsOut[compoundPairIdx] = b3MakeInt4(bodyIndexA,bodyIndexB,childShapeIndexA,childShapeIndexB);
+ gpuCompoundPairsOut[compoundPairIdx] = b3MakeInt4(bodyIndexA, bodyIndexB, childShapeIndexA, childShapeIndexB);
}
- }//
- }//fi(1)
- } //for (int b=0
- }//if (collidables[collidableIndexB].
- else//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+ } //
+ } //fi(1)
+ } //for (int b=0
+ } //if (collidables[collidableIndexB].
+ else //if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
{
if (1)
{
- // int numFacesA = convexShapes[shapeIndexA].m_numFaces;
- // float dmin = FLT_MAX;
+ // int numFacesA = convexShapes[shapeIndexA].m_numFaces;
+ // float dmin = FLT_MAX;
float4 posA = newPosA;
posA.w = 0.f;
float4 posB = rigidBodies[bodyIndexB].m_pos;
@@ -1811,45 +1708,43 @@ __kernel void findCompoundPairsKernel(
float4 c1local = convexShapes[shapeIndexB].m_localCenter;
b3Quat ornB = rigidBodies[bodyIndexB].m_quat;
float4 c1;
- c1 = transform(&c1local,&posB,&ornB);
- // const float4 DeltaC2 = c0 - c1;
+ c1 = transform(&c1local, &posB, &ornB);
+ // const float4 DeltaC2 = c0 - c1;
{
int compoundPairIdx = b3AtomicInc(numCompoundPairsOut);
- if (compoundPairIdx<maxNumCompoundPairsCapacity)
+ if (compoundPairIdx < maxNumCompoundPairsCapacity)
{
- gpuCompoundPairsOut[compoundPairIdx] = b3MakeInt4(bodyIndexA,bodyIndexB,childShapeIndexA,-1);
- }//if (compoundPairIdx<maxNumCompoundPairsCapacity)
- }//
- }//fi (1)
- }//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
- }//for (int b=0;b<numChildrenB;b++)
+ gpuCompoundPairsOut[compoundPairIdx] = b3MakeInt4(bodyIndexA, bodyIndexB, childShapeIndexA, -1);
+ } //if (compoundPairIdx<maxNumCompoundPairsCapacity)
+ } //
+ } //fi (1)
+ } //if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+ } //for (int b=0;b<numChildrenB;b++)
return;
- }//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
- if ((collidables[collidableIndexA].m_shapeType!=SHAPE_CONCAVE_TRIMESH)
- && (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))
+ } //if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+ if ((collidables[collidableIndexA].m_shapeType != SHAPE_CONCAVE_TRIMESH) && (collidables[collidableIndexB].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS))
{
int numChildrenB = collidables[collidableIndexB].m_numChildShapes;
- for (int b=0;b<numChildrenB;b++)
+ for (int b = 0; b < numChildrenB; b++)
{
- int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex+b;
+ int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex + b;
int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
b3Quat ornB = rigidBodies[bodyIndexB].m_quat;
float4 posB = rigidBodies[bodyIndexB].m_pos;
float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
b3Quat childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
- float4 newPosB = b3QuatRotate(ornB,childPosB)+posB;
- b3Quat newOrnB = b3QuatMul(ornB,childOrnB);
+ float4 newPosB = b3QuatRotate(ornB, childPosB) + posB;
+ b3Quat newOrnB = b3QuatMul(ornB, childOrnB);
int shapeIndexB = collidables[childColIndexB].m_shapeIndex;
-
//////////////////////////////////////
if (1)
{
- // int numFacesA = convexShapes[shapeIndexA].m_numFaces;
- // float dmin = FLT_MAX;
+ // int numFacesA = convexShapes[shapeIndexA].m_numFaces;
+ // float dmin = FLT_MAX;
float4 posA = rigidBodies[bodyIndexA].m_pos;
posA.w = 0.f;
float4 posB = newPosB;
@@ -1859,99 +1754,96 @@ __kernel void findCompoundPairsKernel(
float4 c0;
c0 = transform(&c0local, &posA, &ornA);
float4 c1local = convexShapes[shapeIndexB].m_localCenter;
- b3Quat ornB =newOrnB;
+ b3Quat ornB = newOrnB;
float4 c1;
- c1 = transform(&c1local,&posB,&ornB);
- // const float4 DeltaC2 = c0 - c1;
- {//
+ c1 = transform(&c1local, &posB, &ornB);
+ // const float4 DeltaC2 = c0 - c1;
+ { //
int compoundPairIdx = b3AtomicInc(numCompoundPairsOut);
- if (compoundPairIdx<maxNumCompoundPairsCapacity)
+ if (compoundPairIdx < maxNumCompoundPairsCapacity)
{
- gpuCompoundPairsOut[compoundPairIdx] = b3MakeInt4(bodyIndexA,bodyIndexB,-1,childShapeIndexB);
- }//fi (compoundPairIdx<maxNumCompoundPairsCapacity)
- }//
- }//fi (1)
- }//for (int b=0;b<numChildrenB;b++)
+ gpuCompoundPairsOut[compoundPairIdx] = b3MakeInt4(bodyIndexA, bodyIndexB, -1, childShapeIndexB);
+ } //fi (compoundPairIdx<maxNumCompoundPairsCapacity)
+ } //
+ } //fi (1)
+ } //for (int b=0;b<numChildrenB;b++)
return;
- }//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+ } //if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
return;
- }//fi ((collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS) ||(collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))
- }//i<numPairs
+ } //fi ((collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS) ||(collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))
+ } //i<numPairs
}
-
-
-__kernel void processCompoundPairsKernel( __global const b3Int4* gpuCompoundPairs,
- __global const b3RigidBodyData* rigidBodies,
- __global const b3Collidable* collidables,
- __global const b3ConvexPolyhedronData* convexShapes,
- __global const b3AlignedObjectArray<b3Float4>& vertices,
- __global const b3AlignedObjectArray<b3Float4>& uniqueEdges,
- __global const b3AlignedObjectArray<b3GpuFace>& faces,
- __global const b3AlignedObjectArray<int>& indices,
- __global b3Aabb* aabbs,
- __global const b3GpuChildShape* gpuChildShapes,
- __global b3AlignedObjectArray<b3Float4>& gpuCompoundSepNormalsOut,
- __global b3AlignedObjectArray<int>& gpuHasCompoundSepNormalsOut,
- int numCompoundPairs,
- int i
- )
+__kernel void processCompoundPairsKernel(__global const b3Int4* gpuCompoundPairs,
+ __global const b3RigidBodyData* rigidBodies,
+ __global const b3Collidable* collidables,
+ __global const b3ConvexPolyhedronData* convexShapes,
+ __global const b3AlignedObjectArray<b3Float4>& vertices,
+ __global const b3AlignedObjectArray<b3Float4>& uniqueEdges,
+ __global const b3AlignedObjectArray<b3GpuFace>& faces,
+ __global const b3AlignedObjectArray<int>& indices,
+ __global b3Aabb* aabbs,
+ __global const b3GpuChildShape* gpuChildShapes,
+ __global b3AlignedObjectArray<b3Float4>& gpuCompoundSepNormalsOut,
+ __global b3AlignedObjectArray<int>& gpuHasCompoundSepNormalsOut,
+ int numCompoundPairs,
+ int i)
{
-
-// int i = get_global_id(0);
- if (i<numCompoundPairs)
+ // int i = get_global_id(0);
+ if (i < numCompoundPairs)
{
int bodyIndexA = gpuCompoundPairs[i].x;
int bodyIndexB = gpuCompoundPairs[i].y;
int childShapeIndexA = gpuCompoundPairs[i].z;
int childShapeIndexB = gpuCompoundPairs[i].w;
-
+
int collidableIndexA = -1;
int collidableIndexB = -1;
-
+
b3Quat ornA = rigidBodies[bodyIndexA].m_quat;
float4 posA = rigidBodies[bodyIndexA].m_pos;
-
+
b3Quat ornB = rigidBodies[bodyIndexB].m_quat;
float4 posB = rigidBodies[bodyIndexB].m_pos;
-
+
if (childShapeIndexA >= 0)
{
collidableIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;
float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;
- b3Quat childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;
- float4 newPosA = b3QuatRotate(ornA,childPosA)+posA;
- b3Quat newOrnA = b3QuatMul(ornA,childOrnA);
+ b3Quat childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;
+ float4 newPosA = b3QuatRotate(ornA, childPosA) + posA;
+ b3Quat newOrnA = b3QuatMul(ornA, childOrnA);
posA = newPosA;
ornA = newOrnA;
- } else
+ }
+ else
{
collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
}
-
- if (childShapeIndexB>=0)
+
+ if (childShapeIndexB >= 0)
{
collidableIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
b3Quat childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
- float4 newPosB = b3QuatRotate(ornB,childPosB)+posB;
- b3Quat newOrnB = b3QuatMul(ornB,childOrnB);
+ float4 newPosB = b3QuatRotate(ornB, childPosB) + posB;
+ b3Quat newOrnB = b3QuatMul(ornB, childOrnB);
posB = newPosB;
ornB = newOrnB;
- } else
+ }
+ else
{
- collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+ collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
}
-
+
gpuHasCompoundSepNormalsOut[i] = 0;
-
+
int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
-
+
int shapeTypeA = collidables[collidableIndexA].m_shapeType;
int shapeTypeB = collidables[collidableIndexB].m_shapeType;
-
if ((shapeTypeA != SHAPE_CONVEX_HULL) || (shapeTypeB != SHAPE_CONVEX_HULL))
{
@@ -1959,145 +1851,142 @@ __kernel void processCompoundPairsKernel( __global const b3Int4* gpuCompoundPa
}
int hasSeparatingAxis = 5;
-
- // int numFacesA = convexShapes[shapeIndexA].m_numFaces;
+
+ // int numFacesA = convexShapes[shapeIndexA].m_numFaces;
float dmin = FLT_MAX;
posA.w = 0.f;
posB.w = 0.f;
float4 c0local = convexShapes[shapeIndexA].m_localCenter;
float4 c0 = transform(&c0local, &posA, &ornA);
float4 c1local = convexShapes[shapeIndexB].m_localCenter;
- float4 c1 = transform(&c1local,&posB,&ornB);
+ float4 c1 = transform(&c1local, &posB, &ornB);
const float4 DeltaC2 = c0 - c1;
- float4 sepNormal = make_float4(1,0,0,0);
-// bool sepA = findSeparatingAxis( convexShapes[shapeIndexA], convexShapes[shapeIndexB],posA,ornA,posB,ornB,DeltaC2,vertices,uniqueEdges,faces,indices,&sepNormal,&dmin);
- bool sepA = findSeparatingAxis( convexShapes[shapeIndexA], convexShapes[shapeIndexB],posA,ornA,posB,ornB,vertices,uniqueEdges,faces,indices,vertices,uniqueEdges,faces,indices,sepNormal);//,&dmin);
-
+ float4 sepNormal = make_float4(1, 0, 0, 0);
+ // bool sepA = findSeparatingAxis( convexShapes[shapeIndexA], convexShapes[shapeIndexB],posA,ornA,posB,ornB,DeltaC2,vertices,uniqueEdges,faces,indices,&sepNormal,&dmin);
+ bool sepA = findSeparatingAxis(convexShapes[shapeIndexA], convexShapes[shapeIndexB], posA, ornA, posB, ornB, vertices, uniqueEdges, faces, indices, vertices, uniqueEdges, faces, indices, sepNormal); //,&dmin);
+
hasSeparatingAxis = 4;
if (!sepA)
{
hasSeparatingAxis = 0;
- } else
+ }
+ else
{
- bool sepB = findSeparatingAxis( convexShapes[shapeIndexB],convexShapes[shapeIndexA],posB,ornB,posA,ornA,vertices,uniqueEdges,faces,indices,vertices,uniqueEdges,faces,indices,sepNormal);//,&dmin);
+ bool sepB = findSeparatingAxis(convexShapes[shapeIndexB], convexShapes[shapeIndexA], posB, ornB, posA, ornA, vertices, uniqueEdges, faces, indices, vertices, uniqueEdges, faces, indices, sepNormal); //,&dmin);
if (!sepB)
{
hasSeparatingAxis = 0;
- } else//(!sepB)
+ }
+ else //(!sepB)
{
- bool sepEE = findSeparatingAxisEdgeEdge( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,posB,ornB,DeltaC2,vertices,uniqueEdges,faces,indices,&sepNormal,&dmin);
+ bool sepEE = findSeparatingAxisEdgeEdge(&convexShapes[shapeIndexA], &convexShapes[shapeIndexB], posA, ornA, posB, ornB, DeltaC2, vertices, uniqueEdges, faces, indices, &sepNormal, &dmin);
if (sepEE)
{
- gpuCompoundSepNormalsOut[i] = sepNormal;//fastNormalize4(sepNormal);
- gpuHasCompoundSepNormalsOut[i] = 1;
- }//sepEE
- }//(!sepB)
- }//(!sepA)
-
-
+ gpuCompoundSepNormalsOut[i] = sepNormal; //fastNormalize4(sepNormal);
+ gpuHasCompoundSepNormalsOut[i] = 1;
+ } //sepEE
+ } //(!sepB)
+ } //(!sepA)
}
-
}
-
-__kernel void clipCompoundsHullHullKernel( __global const b3Int4* gpuCompoundPairs,
- __global const b3RigidBodyData* rigidBodies,
- __global const b3Collidable* collidables,
- __global const b3ConvexPolyhedronData* convexShapes,
- __global const b3AlignedObjectArray<b3Float4>& vertices,
- __global const b3AlignedObjectArray<b3Float4>& uniqueEdges,
- __global const b3AlignedObjectArray<b3GpuFace>& faces,
- __global const b3AlignedObjectArray<int>& indices,
- __global const b3GpuChildShape* gpuChildShapes,
- __global const b3AlignedObjectArray<b3Float4>& gpuCompoundSepNormalsOut,
- __global const b3AlignedObjectArray<int>& gpuHasCompoundSepNormalsOut,
- __global struct b3Contact4Data* globalContactsOut,
- int* nGlobalContactsOut,
- int numCompoundPairs, int maxContactCapacity, int i)
+__kernel void clipCompoundsHullHullKernel(__global const b3Int4* gpuCompoundPairs,
+ __global const b3RigidBodyData* rigidBodies,
+ __global const b3Collidable* collidables,
+ __global const b3ConvexPolyhedronData* convexShapes,
+ __global const b3AlignedObjectArray<b3Float4>& vertices,
+ __global const b3AlignedObjectArray<b3Float4>& uniqueEdges,
+ __global const b3AlignedObjectArray<b3GpuFace>& faces,
+ __global const b3AlignedObjectArray<int>& indices,
+ __global const b3GpuChildShape* gpuChildShapes,
+ __global const b3AlignedObjectArray<b3Float4>& gpuCompoundSepNormalsOut,
+ __global const b3AlignedObjectArray<int>& gpuHasCompoundSepNormalsOut,
+ __global struct b3Contact4Data* globalContactsOut,
+ int* nGlobalContactsOut,
+ int numCompoundPairs, int maxContactCapacity, int i)
{
-
-// int i = get_global_id(0);
+ // int i = get_global_id(0);
int pairIndex = i;
-
+
float4 worldVertsB1[64];
float4 worldVertsB2[64];
- int capacityWorldVerts = 64;
+ int capacityWorldVerts = 64;
float4 localContactsOut[64];
- int localContactCapacity=64;
-
+ int localContactCapacity = 64;
+
float minDist = -1e30f;
float maxDist = 0.0f;
- if (i<numCompoundPairs)
+ if (i < numCompoundPairs)
{
-
if (gpuHasCompoundSepNormalsOut[i])
{
-
int bodyIndexA = gpuCompoundPairs[i].x;
int bodyIndexB = gpuCompoundPairs[i].y;
-
+
int childShapeIndexA = gpuCompoundPairs[i].z;
int childShapeIndexB = gpuCompoundPairs[i].w;
-
+
int collidableIndexA = -1;
int collidableIndexB = -1;
-
+
b3Quat ornA = rigidBodies[bodyIndexA].m_quat;
float4 posA = rigidBodies[bodyIndexA].m_pos;
-
+
b3Quat ornB = rigidBodies[bodyIndexB].m_quat;
float4 posB = rigidBodies[bodyIndexB].m_pos;
-
+
if (childShapeIndexA >= 0)
{
collidableIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;
float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;
b3Quat childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;
- float4 newPosA = b3QuatRotate(ornA,childPosA)+posA;
- b3Quat newOrnA = b3QuatMul(ornA,childOrnA);
+ float4 newPosA = b3QuatRotate(ornA, childPosA) + posA;
+ b3Quat newOrnA = b3QuatMul(ornA, childOrnA);
posA = newPosA;
ornA = newOrnA;
- } else
+ }
+ else
{
collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
}
-
- if (childShapeIndexB>=0)
+
+ if (childShapeIndexB >= 0)
{
collidableIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
- b3Quat childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
- float4 newPosB = b3QuatRotate(ornB,childPosB)+posB;
- b3Quat newOrnB = b3QuatMul(ornB,childOrnB);
+ b3Quat childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
+ float4 newPosB = b3QuatRotate(ornB, childPosB) + posB;
+ b3Quat newOrnB = b3QuatMul(ornB, childOrnB);
posB = newPosB;
ornB = newOrnB;
- } else
+ }
+ else
{
- collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+ collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
}
-
+
int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
-
+
int numLocalContactsOut = clipHullAgainstHull(gpuCompoundSepNormalsOut[i],
- convexShapes[shapeIndexA], convexShapes[shapeIndexB],
- posA,ornA,
- posB,ornB,
- worldVertsB1,worldVertsB2,capacityWorldVerts,
- minDist, maxDist,
- vertices,faces,indices,
- vertices,faces,indices,
- localContactsOut,localContactCapacity);
-
- if (numLocalContactsOut>0)
- {
+ convexShapes[shapeIndexA], convexShapes[shapeIndexB],
+ posA, ornA,
+ posB, ornB,
+ worldVertsB1, worldVertsB2, capacityWorldVerts,
+ minDist, maxDist,
+ vertices, faces, indices,
+ vertices, faces, indices,
+ localContactsOut, localContactCapacity);
+
+ if (numLocalContactsOut > 0)
+ {
float4 normal = -gpuCompoundSepNormalsOut[i];
int nPoints = numLocalContactsOut;
float4* pointsIn = localContactsOut;
- b3Int4 contactIdx;// = {-1,-1,-1,-1};
+ b3Int4 contactIdx; // = {-1,-1,-1,-1};
contactIdx.s[0] = 0;
contactIdx.s[1] = 1;
@@ -2105,111 +1994,106 @@ __kernel void clipCompoundsHullHullKernel( __global const b3Int4* gpuCompoundP
contactIdx.s[3] = 3;
int nReducedContacts = extractManifoldSequentialGlobal(pointsIn, nPoints, normal, &contactIdx);
-
+
int dstIdx;
- dstIdx = b3AtomicInc( nGlobalContactsOut);
- if ((dstIdx+nReducedContacts) < maxContactCapacity)
+ dstIdx = b3AtomicInc(nGlobalContactsOut);
+ if ((dstIdx + nReducedContacts) < maxContactCapacity)
{
- __global struct b3Contact4Data* c = globalContactsOut+ dstIdx;
+ __global struct b3Contact4Data* c = globalContactsOut + dstIdx;
c->m_worldNormalOnB = -normal;
- c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
+ c->m_restituitionCoeffCmp = (0.f * 0xffff);
+ c->m_frictionCoeffCmp = (0.7f * 0xffff);
c->m_batchIdx = pairIndex;
int bodyA = gpuCompoundPairs[pairIndex].x;
int bodyB = gpuCompoundPairs[pairIndex].y;
- c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;
- c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;
+ c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass == 0 ? -bodyA : bodyA;
+ c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass == 0 ? -bodyB : bodyB;
c->m_childIndexA = childShapeIndexA;
c->m_childIndexB = childShapeIndexB;
- for (int i=0;i<nReducedContacts;i++)
+ for (int i = 0; i < nReducedContacts; i++)
{
c->m_worldPosB[i] = pointsIn[contactIdx.s[i]];
}
- b3Contact4Data_setNumPoints(c,nReducedContacts);
+ b3Contact4Data_setNumPoints(c, nReducedContacts);
}
-
- }// if (numContactsOut>0)
- }// if (gpuHasCompoundSepNormalsOut[i])
- }// if (i<numCompoundPairs)
+ } // if (numContactsOut>0)
+ } // if (gpuHasCompoundSepNormalsOut[i])
+ } // if (i<numCompoundPairs)
}
-
void computeContactCompoundCompound(int pairIndex,
- int bodyIndexA, int bodyIndexB,
- int collidableIndexA, int collidableIndexB,
- const b3RigidBodyData* rigidBodies,
- const b3Collidable* collidables,
- const b3ConvexPolyhedronData* convexShapes,
- const b3GpuChildShape* cpuChildShapes,
- const b3AlignedObjectArray<b3Aabb>& hostAabbsWorldSpace,
- const b3AlignedObjectArray<b3Aabb>& hostAabbsLocalSpace,
-
- const b3AlignedObjectArray<b3Vector3>& convexVertices,
- const b3AlignedObjectArray<b3Vector3>& hostUniqueEdges,
- const b3AlignedObjectArray<int>& convexIndices,
- const b3AlignedObjectArray<b3GpuFace>& faces,
-
- b3Contact4* globalContactsOut,
- int& nGlobalContactsOut,
- int maxContactCapacity,
- b3AlignedObjectArray<b3QuantizedBvhNode>& treeNodesCPU,
- b3AlignedObjectArray<b3BvhSubtreeInfo>& subTreesCPU,
- b3AlignedObjectArray<b3BvhInfo>& bvhInfoCPU
- )
+ int bodyIndexA, int bodyIndexB,
+ int collidableIndexA, int collidableIndexB,
+ const b3RigidBodyData* rigidBodies,
+ const b3Collidable* collidables,
+ const b3ConvexPolyhedronData* convexShapes,
+ const b3GpuChildShape* cpuChildShapes,
+ const b3AlignedObjectArray<b3Aabb>& hostAabbsWorldSpace,
+ const b3AlignedObjectArray<b3Aabb>& hostAabbsLocalSpace,
+
+ const b3AlignedObjectArray<b3Vector3>& convexVertices,
+ const b3AlignedObjectArray<b3Vector3>& hostUniqueEdges,
+ const b3AlignedObjectArray<int>& convexIndices,
+ const b3AlignedObjectArray<b3GpuFace>& faces,
+
+ b3Contact4* globalContactsOut,
+ int& nGlobalContactsOut,
+ int maxContactCapacity,
+ b3AlignedObjectArray<b3QuantizedBvhNode>& treeNodesCPU,
+ b3AlignedObjectArray<b3BvhSubtreeInfo>& subTreesCPU,
+ b3AlignedObjectArray<b3BvhInfo>& bvhInfoCPU)
{
-
int shapeTypeB = collidables[collidableIndexB].m_shapeType;
b3Assert(shapeTypeB == SHAPE_COMPOUND_OF_CONVEX_HULLS);
b3AlignedObjectArray<b3Int4> cpuCompoundPairsOut;
- int numCompoundPairsOut=0;
- int maxNumCompoundPairsCapacity = 8192;//1024;
+ int numCompoundPairsOut = 0;
+ int maxNumCompoundPairsCapacity = 8192; //1024;
cpuCompoundPairsOut.resize(maxNumCompoundPairsCapacity);
// work-in-progress
- findCompoundPairsKernel(
- pairIndex,
- bodyIndexA,bodyIndexB,
- collidableIndexA,collidableIndexB,
- rigidBodies,
- collidables,
- convexShapes,
- convexVertices,
- hostAabbsWorldSpace,
- hostAabbsLocalSpace,
- cpuChildShapes,
- &cpuCompoundPairsOut[0],
- &numCompoundPairsOut,
- maxNumCompoundPairsCapacity ,
- treeNodesCPU,
- subTreesCPU,
- bvhInfoCPU
- );
-
- printf("maxNumAabbChecks=%d\n",maxNumAabbChecks);
- if (numCompoundPairsOut>maxNumCompoundPairsCapacity)
+ findCompoundPairsKernel(
+ pairIndex,
+ bodyIndexA, bodyIndexB,
+ collidableIndexA, collidableIndexB,
+ rigidBodies,
+ collidables,
+ convexShapes,
+ convexVertices,
+ hostAabbsWorldSpace,
+ hostAabbsLocalSpace,
+ cpuChildShapes,
+ &cpuCompoundPairsOut[0],
+ &numCompoundPairsOut,
+ maxNumCompoundPairsCapacity,
+ treeNodesCPU,
+ subTreesCPU,
+ bvhInfoCPU);
+
+ printf("maxNumAabbChecks=%d\n", maxNumAabbChecks);
+ if (numCompoundPairsOut > maxNumCompoundPairsCapacity)
{
- b3Error("numCompoundPairsOut exceeded maxNumCompoundPairsCapacity (%d)\n",maxNumCompoundPairsCapacity);
- numCompoundPairsOut=maxNumCompoundPairsCapacity;
+ b3Error("numCompoundPairsOut exceeded maxNumCompoundPairsCapacity (%d)\n", maxNumCompoundPairsCapacity);
+ numCompoundPairsOut = maxNumCompoundPairsCapacity;
}
b3AlignedObjectArray<b3Float4> cpuCompoundSepNormalsOut;
b3AlignedObjectArray<int> cpuHasCompoundSepNormalsOut;
cpuCompoundSepNormalsOut.resize(numCompoundPairsOut);
cpuHasCompoundSepNormalsOut.resize(numCompoundPairsOut);
- for (int i=0;i<numCompoundPairsOut;i++)
+ for (int i = 0; i < numCompoundPairsOut; i++)
{
-
- processCompoundPairsKernel(&cpuCompoundPairsOut[0],rigidBodies,collidables,convexShapes,convexVertices,hostUniqueEdges,faces,convexIndices,0,cpuChildShapes,
- cpuCompoundSepNormalsOut,cpuHasCompoundSepNormalsOut,numCompoundPairsOut,i);
+ processCompoundPairsKernel(&cpuCompoundPairsOut[0], rigidBodies, collidables, convexShapes, convexVertices, hostUniqueEdges, faces, convexIndices, 0, cpuChildShapes,
+ cpuCompoundSepNormalsOut, cpuHasCompoundSepNormalsOut, numCompoundPairsOut, i);
}
- for (int i=0;i<numCompoundPairsOut;i++)
+ for (int i = 0; i < numCompoundPairsOut; i++)
{
- clipCompoundsHullHullKernel(&cpuCompoundPairsOut[0],rigidBodies,collidables,convexShapes,convexVertices,hostUniqueEdges,faces,convexIndices,cpuChildShapes,
- cpuCompoundSepNormalsOut,cpuHasCompoundSepNormalsOut,globalContactsOut,&nGlobalContactsOut,numCompoundPairsOut,maxContactCapacity,i);
+ clipCompoundsHullHullKernel(&cpuCompoundPairsOut[0], rigidBodies, collidables, convexShapes, convexVertices, hostUniqueEdges, faces, convexIndices, cpuChildShapes,
+ cpuCompoundSepNormalsOut, cpuHasCompoundSepNormalsOut, globalContactsOut, &nGlobalContactsOut, numCompoundPairsOut, maxContactCapacity, i);
}
- /*
+ /*
int childColIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;
float4 posA = rigidBodies[bodyIndexA].m_pos;
@@ -2235,7 +2119,6 @@ void computeContactCompoundCompound(int pairIndex,
);
*/
-
/*
if (foundSepAxis)
{
@@ -2271,8 +2154,8 @@ void computeContactCompoundCompound(int pairIndex,
}
*/
-// return contactIndex;
-
+ // return contactIndex;
+
/*
int numChildrenB = collidables[collidableIndexB].m_numChildShapes;
@@ -2294,56 +2177,52 @@ void computeContactCompoundCompound(int pairIndex,
}
*/
-
}
void computeContactPlaneCompound(int pairIndex,
- int bodyIndexA, int bodyIndexB,
- int collidableIndexA, int collidableIndexB,
- const b3RigidBodyData* rigidBodies,
- const b3Collidable* collidables,
- const b3ConvexPolyhedronData* convexShapes,
- const b3GpuChildShape* cpuChildShapes,
- const b3Vector3* convexVertices,
- const int* convexIndices,
- const b3GpuFace* faces,
-
- b3Contact4* globalContactsOut,
- int& nGlobalContactsOut,
- int maxContactCapacity)
+ int bodyIndexA, int bodyIndexB,
+ int collidableIndexA, int collidableIndexB,
+ const b3RigidBodyData* rigidBodies,
+ const b3Collidable* collidables,
+ const b3ConvexPolyhedronData* convexShapes,
+ const b3GpuChildShape* cpuChildShapes,
+ const b3Vector3* convexVertices,
+ const int* convexIndices,
+ const b3GpuFace* faces,
+
+ b3Contact4* globalContactsOut,
+ int& nGlobalContactsOut,
+ int maxContactCapacity)
{
-
int shapeTypeB = collidables[collidableIndexB].m_shapeType;
b3Assert(shapeTypeB == SHAPE_COMPOUND_OF_CONVEX_HULLS);
-
int numChildrenB = collidables[collidableIndexB].m_numChildShapes;
- for (int c=0;c<numChildrenB;c++)
+ for (int c = 0; c < numChildrenB; c++)
{
- int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex+c;
+ int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex + c;
int childColIndexB = cpuChildShapes[childShapeIndexB].m_shapeIndex;
float4 rootPosB = rigidBodies[bodyIndexB].m_pos;
b3Quaternion rootOrnB = rigidBodies[bodyIndexB].m_quat;
b3Vector3 childPosB = cpuChildShapes[childShapeIndexB].m_childPosition;
b3Quaternion childOrnB = cpuChildShapes[childShapeIndexB].m_childOrientation;
- float4 posB = b3QuatRotate(rootOrnB,childPosB)+rootPosB;
- b3Quaternion ornB = rootOrnB*childOrnB;//b3QuatMul(ornB,childOrnB);
+ float4 posB = b3QuatRotate(rootOrnB, childPosB) + rootPosB;
+ b3Quaternion ornB = rootOrnB * childOrnB; //b3QuatMul(ornB,childOrnB);
int shapeIndexB = collidables[childColIndexB].m_shapeIndex;
const b3ConvexPolyhedronData* hullB = &convexShapes[shapeIndexB];
-
-
+
b3Vector3 posA = rigidBodies[bodyIndexA].m_pos;
b3Quaternion ornA = rigidBodies[bodyIndexA].m_quat;
- // int numContactsOut = 0;
- // int numWorldVertsB1= 0;
+ // int numContactsOut = 0;
+ // int numWorldVertsB1= 0;
b3Vector3 planeEq = faces[collidables[collidableIndexA].m_shapeIndex].m_plane;
- b3Vector3 planeNormal=b3MakeVector3(planeEq.x,planeEq.y,planeEq.z);
- b3Vector3 planeNormalWorld = b3QuatRotate(ornA,planeNormal);
+ b3Vector3 planeNormal = b3MakeVector3(planeEq.x, planeEq.y, planeEq.z);
+ b3Vector3 planeNormalWorld = b3QuatRotate(ornA, planeNormal);
float planeConstant = planeEq.w;
b3Transform convexWorldTransform;
convexWorldTransform.setIdentity();
@@ -2355,16 +2234,16 @@ void computeContactPlaneCompound(int pairIndex,
planeTransform.setRotation(ornA);
b3Transform planeInConvex;
- planeInConvex= convexWorldTransform.inverse() * planeTransform;
+ planeInConvex = convexWorldTransform.inverse() * planeTransform;
b3Transform convexInPlane;
convexInPlane = planeTransform.inverse() * convexWorldTransform;
-
- b3Vector3 planeNormalInConvex = planeInConvex.getBasis()*-planeNormal;
+
+ b3Vector3 planeNormalInConvex = planeInConvex.getBasis() * -planeNormal;
float maxDot = -1e30;
- int hitVertex=-1;
+ int hitVertex = -1;
b3Vector3 hitVtx;
- #define MAX_PLANE_CONVEX_POINTS 64
+#define MAX_PLANE_CONVEX_POINTS 64
b3Vector3 contactPoints[MAX_PLANE_CONVEX_POINTS];
int numPoints = 0;
@@ -2374,54 +2253,52 @@ void computeContactPlaneCompound(int pairIndex,
contactIdx.s[1] = 1;
contactIdx.s[2] = 2;
contactIdx.s[3] = 3;
-
- for (int i=0;i<hullB->m_numVertices;i++)
+
+ for (int i = 0; i < hullB->m_numVertices; i++)
{
- b3Vector3 vtx = convexVertices[hullB->m_vertexOffset+i];
+ b3Vector3 vtx = convexVertices[hullB->m_vertexOffset + i];
float curDot = vtx.dot(planeNormalInConvex);
-
- if (curDot>maxDot)
+ if (curDot > maxDot)
{
- hitVertex=i;
- maxDot=curDot;
+ hitVertex = i;
+ maxDot = curDot;
hitVtx = vtx;
//make sure the deepest points is always included
- if (numPoints==MAX_PLANE_CONVEX_POINTS)
+ if (numPoints == MAX_PLANE_CONVEX_POINTS)
numPoints--;
}
- if (numPoints<MAX_PLANE_CONVEX_POINTS)
+ if (numPoints < MAX_PLANE_CONVEX_POINTS)
{
- b3Vector3 vtxWorld = convexWorldTransform*vtx;
- b3Vector3 vtxInPlane = planeTransform.inverse()*vtxWorld;
- float dist = planeNormal.dot(vtxInPlane)-planeConstant;
- if (dist<0.f)
+ b3Vector3 vtxWorld = convexWorldTransform * vtx;
+ b3Vector3 vtxInPlane = planeTransform.inverse() * vtxWorld;
+ float dist = planeNormal.dot(vtxInPlane) - planeConstant;
+ if (dist < 0.f)
{
vtxWorld.w = dist;
contactPoints[numPoints] = vtxWorld;
numPoints++;
}
}
-
}
- int numReducedPoints = 0;
+ int numReducedPoints = 0;
numReducedPoints = numPoints;
-
- if (numPoints>4)
+
+ if (numPoints > 4)
{
- numReducedPoints = extractManifoldSequentialGlobal( contactPoints, numPoints, planeNormalInConvex, &contactIdx);
+ numReducedPoints = extractManifoldSequentialGlobal(contactPoints, numPoints, planeNormalInConvex, &contactIdx);
}
int dstIdx;
- // dstIdx = nGlobalContactsOut++;//AppendInc( nGlobalContactsOut, dstIdx );
-
- if (numReducedPoints>0)
+ // dstIdx = nGlobalContactsOut++;//AppendInc( nGlobalContactsOut, dstIdx );
+
+ if (numReducedPoints > 0)
{
if (nGlobalContactsOut < maxContactCapacity)
{
- dstIdx=nGlobalContactsOut;
+ dstIdx = nGlobalContactsOut;
nGlobalContactsOut++;
b3Contact4* c = &globalContactsOut[dstIdx];
@@ -2430,48 +2307,37 @@ void computeContactPlaneCompound(int pairIndex,
c->setRestituitionCoeff(0.f);
c->m_batchIdx = pairIndex;
- c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;
- c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;
- for (int i=0;i<numReducedPoints;i++)
+ c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass == 0 ? -bodyIndexA : bodyIndexA;
+ c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass == 0 ? -bodyIndexB : bodyIndexB;
+ for (int i = 0; i < numReducedPoints; i++)
{
b3Vector3 pOnB1 = contactPoints[contactIdx.s[i]];
c->m_worldPosB[i] = pOnB1;
}
c->m_worldNormalOnB.w = (b3Scalar)numReducedPoints;
- }//if (dstIdx < numPairs)
- }
-
+ } //if (dstIdx < numPairs)
+ }
}
-
-
}
-
-
-
-
-void computeContactSphereConvex(int pairIndex,
- int bodyIndexA, int bodyIndexB,
- int collidableIndexA, int collidableIndexB,
- const b3RigidBodyData* rigidBodies,
- const b3Collidable* collidables,
- const b3ConvexPolyhedronData* convexShapes,
- const b3Vector3* convexVertices,
- const int* convexIndices,
- const b3GpuFace* faces,
- b3Contact4* globalContactsOut,
- int& nGlobalContactsOut,
- int maxContactCapacity)
+void computeContactSphereConvex(int pairIndex,
+ int bodyIndexA, int bodyIndexB,
+ int collidableIndexA, int collidableIndexB,
+ const b3RigidBodyData* rigidBodies,
+ const b3Collidable* collidables,
+ const b3ConvexPolyhedronData* convexShapes,
+ const b3Vector3* convexVertices,
+ const int* convexIndices,
+ const b3GpuFace* faces,
+ b3Contact4* globalContactsOut,
+ int& nGlobalContactsOut,
+ int maxContactCapacity)
{
-
float radius = collidables[collidableIndexA].m_radius;
float4 spherePos1 = rigidBodies[bodyIndexA].m_pos;
b3Quaternion sphereOrn = rigidBodies[bodyIndexA].m_quat;
-
-
float4 pos = rigidBodies[bodyIndexB].m_pos;
-
b3Quaternion quat = rigidBodies[bodyIndexB].m_quat;
@@ -2487,64 +2353,65 @@ void computeContactSphereConvex(int pairIndex,
int shapeIndex = collidables[collidableIndex].m_shapeIndex;
int numFaces = convexShapes[shapeIndex].m_numFaces;
float4 closestPnt = b3MakeVector3(0, 0, 0, 0);
-// float4 hitNormalWorld = b3MakeVector3(0, 0, 0, 0);
- float minDist = -1000000.f; // TODO: What is the largest/smallest float?
+ // float4 hitNormalWorld = b3MakeVector3(0, 0, 0, 0);
+ float minDist = -1000000.f; // TODO: What is the largest/smallest float?
bool bCollide = true;
int region = -1;
float4 localHitNormal;
- for ( int f = 0; f < numFaces; f++ )
+ for (int f = 0; f < numFaces; f++)
{
- b3GpuFace face = faces[convexShapes[shapeIndex].m_faceOffset+f];
+ b3GpuFace face = faces[convexShapes[shapeIndex].m_faceOffset + f];
float4 planeEqn;
- float4 localPlaneNormal = b3MakeVector3(face.m_plane.x,face.m_plane.y,face.m_plane.z,0.f);
- float4 n1 = localPlaneNormal;//quatRotate(quat,localPlaneNormal);
+ float4 localPlaneNormal = b3MakeVector3(face.m_plane.x, face.m_plane.y, face.m_plane.z, 0.f);
+ float4 n1 = localPlaneNormal; //quatRotate(quat,localPlaneNormal);
planeEqn = n1;
planeEqn[3] = face.m_plane.w;
float4 pntReturn;
float dist = signedDistanceFromPointToPlane(spherePos, planeEqn, &pntReturn);
- if ( dist > radius)
+ if (dist > radius)
{
bCollide = false;
break;
}
- if ( dist > 0 )
+ if (dist > 0)
{
//might hit an edge or vertex
b3Vector3 out;
bool isInPoly = IsPointInPolygon(spherePos,
- &face,
- &convexVertices[convexShapes[shapeIndex].m_vertexOffset],
- convexIndices,
- &out);
+ &face,
+ &convexVertices[convexShapes[shapeIndex].m_vertexOffset],
+ convexIndices,
+ &out);
if (isInPoly)
{
- if (dist>minDist)
+ if (dist > minDist)
{
minDist = dist;
closestPnt = pntReturn;
localHitNormal = planeEqn;
- region=1;
+ region = 1;
}
- } else
+ }
+ else
{
- b3Vector3 tmp = spherePos-out;
+ b3Vector3 tmp = spherePos - out;
b3Scalar l2 = tmp.length2();
- if (l2<radius*radius)
+ if (l2 < radius * radius)
{
- dist = b3Sqrt(l2);
- if (dist>minDist)
+ dist = b3Sqrt(l2);
+ if (dist > minDist)
{
minDist = dist;
closestPnt = out;
- localHitNormal = tmp/dist;
- region=2;
+ localHitNormal = tmp / dist;
+ region = 2;
}
-
- } else
+ }
+ else
{
bCollide = false;
break;
@@ -2553,12 +2420,12 @@ void computeContactSphereConvex(int pairIndex,
}
else
{
- if ( dist > minDist )
+ if (dist > minDist)
{
minDist = dist;
closestPnt = pntReturn;
localHitNormal = planeEqn;
- region=3;
+ region = 3;
}
}
}
@@ -2567,128 +2434,113 @@ void computeContactSphereConvex(int pairIndex,
if (bCollide && minDist > -10000)
{
-
- float4 normalOnSurfaceB1 = tr.getBasis()*localHitNormal;//-hitNormalWorld;
+ float4 normalOnSurfaceB1 = tr.getBasis() * localHitNormal; //-hitNormalWorld;
float4 pOnB1 = tr(closestPnt);
//printf("dist ,%f,",minDist);
- float actualDepth = minDist-radius;
- if (actualDepth<0)
+ float actualDepth = minDist - radius;
+ if (actualDepth < 0)
{
- //printf("actualDepth = ,%f,", actualDepth);
- //printf("normalOnSurfaceB1 = ,%f,%f,%f,", normalOnSurfaceB1.x,normalOnSurfaceB1.y,normalOnSurfaceB1.z);
- //printf("region=,%d,\n", region);
- pOnB1[3] = actualDepth;
+ //printf("actualDepth = ,%f,", actualDepth);
+ //printf("normalOnSurfaceB1 = ,%f,%f,%f,", normalOnSurfaceB1.x,normalOnSurfaceB1.y,normalOnSurfaceB1.z);
+ //printf("region=,%d,\n", region);
+ pOnB1[3] = actualDepth;
- int dstIdx;
-// dstIdx = nGlobalContactsOut++;//AppendInc( nGlobalContactsOut, dstIdx );
-
- if (nGlobalContactsOut < maxContactCapacity)
- {
- dstIdx=nGlobalContactsOut;
- nGlobalContactsOut++;
+ int dstIdx;
+ // dstIdx = nGlobalContactsOut++;//AppendInc( nGlobalContactsOut, dstIdx );
- b3Contact4* c = &globalContactsOut[dstIdx];
- c->m_worldNormalOnB = normalOnSurfaceB1;
- c->setFrictionCoeff(0.7);
- c->setRestituitionCoeff(0.f);
+ if (nGlobalContactsOut < maxContactCapacity)
+ {
+ dstIdx = nGlobalContactsOut;
+ nGlobalContactsOut++;
- c->m_batchIdx = pairIndex;
- c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;
- c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;
- c->m_worldPosB[0] = pOnB1;
- int numPoints = 1;
- c->m_worldNormalOnB.w = (b3Scalar)numPoints;
- }//if (dstIdx < numPairs)
+ b3Contact4* c = &globalContactsOut[dstIdx];
+ c->m_worldNormalOnB = normalOnSurfaceB1;
+ c->setFrictionCoeff(0.7);
+ c->setRestituitionCoeff(0.f);
+
+ c->m_batchIdx = pairIndex;
+ c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass == 0 ? -bodyIndexA : bodyIndexA;
+ c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass == 0 ? -bodyIndexB : bodyIndexB;
+ c->m_worldPosB[0] = pOnB1;
+ int numPoints = 1;
+ c->m_worldNormalOnB.w = (b3Scalar)numPoints;
+ } //if (dstIdx < numPairs)
}
- }//if (hasCollision)
-
+ } //if (hasCollision)
}
-
-
-
int computeContactConvexConvex2(
- int pairIndex,
- int bodyIndexA, int bodyIndexB,
- int collidableIndexA, int collidableIndexB,
- const b3AlignedObjectArray<b3RigidBodyData>& rigidBodies,
- const b3AlignedObjectArray<b3Collidable>& collidables,
- const b3AlignedObjectArray<b3ConvexPolyhedronData>& convexShapes,
- const b3AlignedObjectArray<b3Vector3>& convexVertices,
- const b3AlignedObjectArray<b3Vector3>& uniqueEdges,
- const b3AlignedObjectArray<int>& convexIndices,
- const b3AlignedObjectArray<b3GpuFace>& faces,
- b3AlignedObjectArray<b3Contact4>& globalContactsOut,
- int& nGlobalContactsOut,
- int maxContactCapacity,
- const b3AlignedObjectArray<b3Contact4>& oldContacts
- )
+ int pairIndex,
+ int bodyIndexA, int bodyIndexB,
+ int collidableIndexA, int collidableIndexB,
+ const b3AlignedObjectArray<b3RigidBodyData>& rigidBodies,
+ const b3AlignedObjectArray<b3Collidable>& collidables,
+ const b3AlignedObjectArray<b3ConvexPolyhedronData>& convexShapes,
+ const b3AlignedObjectArray<b3Vector3>& convexVertices,
+ const b3AlignedObjectArray<b3Vector3>& uniqueEdges,
+ const b3AlignedObjectArray<int>& convexIndices,
+ const b3AlignedObjectArray<b3GpuFace>& faces,
+ b3AlignedObjectArray<b3Contact4>& globalContactsOut,
+ int& nGlobalContactsOut,
+ int maxContactCapacity,
+ const b3AlignedObjectArray<b3Contact4>& oldContacts)
{
int contactIndex = -1;
b3Vector3 posA = rigidBodies[bodyIndexA].m_pos;
b3Quaternion ornA = rigidBodies[bodyIndexA].m_quat;
b3Vector3 posB = rigidBodies[bodyIndexB].m_pos;
b3Quaternion ornB = rigidBodies[bodyIndexB].m_quat;
-
b3ConvexPolyhedronData hullA, hullB;
-
+
b3Vector3 sepNormalWorldSpace;
-
+ b3Collidable colA = collidables[collidableIndexA];
+ hullA = convexShapes[colA.m_shapeIndex];
+ //printf("numvertsA = %d\n",hullA.m_numVertices);
- b3Collidable colA = collidables[collidableIndexA];
- hullA = convexShapes[colA.m_shapeIndex];
- //printf("numvertsA = %d\n",hullA.m_numVertices);
-
-
- b3Collidable colB = collidables[collidableIndexB];
- hullB = convexShapes[colB.m_shapeIndex];
- //printf("numvertsB = %d\n",hullB.m_numVertices);
+ b3Collidable colB = collidables[collidableIndexB];
+ hullB = convexShapes[colB.m_shapeIndex];
+ //printf("numvertsB = %d\n",hullB.m_numVertices);
-// int contactCapacity = MAX_VERTS;
+ // int contactCapacity = MAX_VERTS;
//int numContactsOut=0;
-
#ifdef _WIN32
b3Assert(_finite(rigidBodies[bodyIndexA].m_pos.x));
b3Assert(_finite(rigidBodies[bodyIndexB].m_pos.x));
#endif
-
- bool foundSepAxis = findSeparatingAxis(hullA,hullB,
- posA,
- ornA,
- posB,
- ornB,
- convexVertices,uniqueEdges,faces,convexIndices,
- convexVertices,uniqueEdges,faces,convexIndices,
-
- sepNormalWorldSpace
- );
+ bool foundSepAxis = findSeparatingAxis(hullA, hullB,
+ posA,
+ ornA,
+ posB,
+ ornB,
+
+ convexVertices, uniqueEdges, faces, convexIndices,
+ convexVertices, uniqueEdges, faces, convexIndices,
+
+ sepNormalWorldSpace);
-
if (foundSepAxis)
{
-
-
contactIndex = clipHullHullSingle(
bodyIndexA, bodyIndexB,
- posA,ornA,
- posB,ornB,
+ posA, ornA,
+ posB, ornB,
collidableIndexA, collidableIndexB,
- &rigidBodies,
+ &rigidBodies,
&globalContactsOut,
nGlobalContactsOut,
-
+
convexShapes,
convexShapes,
-
- convexVertices,
- uniqueEdges,
+
+ convexVertices,
+ uniqueEdges,
faces,
convexIndices,
-
+
convexVertices,
uniqueEdges,
faces,
@@ -2698,50 +2550,42 @@ int computeContactConvexConvex2(
collidables,
sepNormalWorldSpace,
maxContactCapacity);
-
}
return contactIndex;
}
-
-
-
-
-
-
-void GpuSatCollision::computeConvexConvexContactsGPUSAT( b3OpenCLArray<b3Int4>* pairs, int nPairs,
- const b3OpenCLArray<b3RigidBodyData>* bodyBuf,
- b3OpenCLArray<b3Contact4>* contactOut, int& nContacts,
- const b3OpenCLArray<b3Contact4>* oldContacts,
- int maxContactCapacity,
- int compoundPairCapacity,
- const b3OpenCLArray<b3ConvexPolyhedronData>& convexData,
- const b3OpenCLArray<b3Vector3>& gpuVertices,
- const b3OpenCLArray<b3Vector3>& gpuUniqueEdges,
- const b3OpenCLArray<b3GpuFace>& gpuFaces,
- const b3OpenCLArray<int>& gpuIndices,
- const b3OpenCLArray<b3Collidable>& gpuCollidables,
- const b3OpenCLArray<b3GpuChildShape>& gpuChildShapes,
-
- const b3OpenCLArray<b3Aabb>& clAabbsWorldSpace,
- const b3OpenCLArray<b3Aabb>& clAabbsLocalSpace,
-
- b3OpenCLArray<b3Vector3>& worldVertsB1GPU,
- b3OpenCLArray<b3Int4>& clippingFacesOutGPU,
- b3OpenCLArray<b3Vector3>& worldNormalsAGPU,
- b3OpenCLArray<b3Vector3>& worldVertsA1GPU,
- b3OpenCLArray<b3Vector3>& worldVertsB2GPU,
- b3AlignedObjectArray<class b3OptimizedBvh*>& bvhDataUnused,
- b3OpenCLArray<b3QuantizedBvhNode>* treeNodesGPU,
- b3OpenCLArray<b3BvhSubtreeInfo>* subTreesGPU,
- b3OpenCLArray<b3BvhInfo>* bvhInfo,
-
- int numObjects,
- int maxTriConvexPairCapacity,
- b3OpenCLArray<b3Int4>& triangleConvexPairsOut,
- int& numTriConvexPairsOut
- )
+void GpuSatCollision::computeConvexConvexContactsGPUSAT(b3OpenCLArray<b3Int4>* pairs, int nPairs,
+ const b3OpenCLArray<b3RigidBodyData>* bodyBuf,
+ b3OpenCLArray<b3Contact4>* contactOut, int& nContacts,
+ const b3OpenCLArray<b3Contact4>* oldContacts,
+ int maxContactCapacity,
+ int compoundPairCapacity,
+ const b3OpenCLArray<b3ConvexPolyhedronData>& convexData,
+ const b3OpenCLArray<b3Vector3>& gpuVertices,
+ const b3OpenCLArray<b3Vector3>& gpuUniqueEdges,
+ const b3OpenCLArray<b3GpuFace>& gpuFaces,
+ const b3OpenCLArray<int>& gpuIndices,
+ const b3OpenCLArray<b3Collidable>& gpuCollidables,
+ const b3OpenCLArray<b3GpuChildShape>& gpuChildShapes,
+
+ const b3OpenCLArray<b3Aabb>& clAabbsWorldSpace,
+ const b3OpenCLArray<b3Aabb>& clAabbsLocalSpace,
+
+ b3OpenCLArray<b3Vector3>& worldVertsB1GPU,
+ b3OpenCLArray<b3Int4>& clippingFacesOutGPU,
+ b3OpenCLArray<b3Vector3>& worldNormalsAGPU,
+ b3OpenCLArray<b3Vector3>& worldVertsA1GPU,
+ b3OpenCLArray<b3Vector3>& worldVertsB2GPU,
+ b3AlignedObjectArray<class b3OptimizedBvh*>& bvhDataUnused,
+ b3OpenCLArray<b3QuantizedBvhNode>* treeNodesGPU,
+ b3OpenCLArray<b3BvhSubtreeInfo>* subTreesGPU,
+ b3OpenCLArray<b3BvhInfo>* bvhInfo,
+
+ int numObjects,
+ int maxTriConvexPairCapacity,
+ b3OpenCLArray<b3Int4>& triangleConvexPairsOut,
+ int& numTriConvexPairsOut)
{
myframecount++;
@@ -2750,14 +2594,13 @@ void GpuSatCollision::computeConvexConvexContactsGPUSAT( b3OpenCLArray<b3Int4>*
#ifdef CHECK_ON_HOST
-
- b3AlignedObjectArray<b3QuantizedBvhNode> treeNodesCPU;
+ b3AlignedObjectArray<b3QuantizedBvhNode> treeNodesCPU;
treeNodesGPU->copyToHost(treeNodesCPU);
- b3AlignedObjectArray<b3BvhSubtreeInfo> subTreesCPU;
+ b3AlignedObjectArray<b3BvhSubtreeInfo> subTreesCPU;
subTreesGPU->copyToHost(subTreesCPU);
- b3AlignedObjectArray<b3BvhInfo> bvhInfoCPU;
+ b3AlignedObjectArray<b3BvhInfo> bvhInfoCPU;
bvhInfo->copyToHost(bvhInfoCPU);
b3AlignedObjectArray<b3Aabb> hostAabbsWorldSpace;
@@ -2772,8 +2615,6 @@ void GpuSatCollision::computeConvexConvexContactsGPUSAT( b3OpenCLArray<b3Int4>*
b3AlignedObjectArray<b3RigidBodyData> hostBodyBuf;
bodyBuf->copyToHost(hostBodyBuf);
-
-
b3AlignedObjectArray<b3ConvexPolyhedronData> hostConvexData;
convexData.copyToHost(hostConvexData);
@@ -2788,10 +2629,9 @@ void GpuSatCollision::computeConvexConvexContactsGPUSAT( b3OpenCLArray<b3Int4>*
gpuIndices.copyToHost(hostIndices);
b3AlignedObjectArray<b3Collidable> hostCollidables;
gpuCollidables.copyToHost(hostCollidables);
-
+
b3AlignedObjectArray<b3GpuChildShape> cpuChildShapes;
gpuChildShapes.copyToHost(cpuChildShapes);
-
b3AlignedObjectArray<b3Int4> hostTriangleConvexPairs;
@@ -2802,16 +2642,15 @@ void GpuSatCollision::computeConvexConvexContactsGPUSAT( b3OpenCLArray<b3Int4>*
}
b3AlignedObjectArray<b3Contact4> oldHostContacts;
-
+
if (oldContacts->size())
{
oldContacts->copyToHost(oldHostContacts);
}
-
hostContacts.resize(maxContactCapacity);
- for (int i=0;i<nPairs;i++)
+ for (int i = 0; i < nPairs; i++)
{
int bodyIndexA = hostPairs[i].x;
int bodyIndexB = hostPairs[i].y;
@@ -2821,84 +2660,73 @@ void GpuSatCollision::computeConvexConvexContactsGPUSAT( b3OpenCLArray<b3Int4>*
if (hostCollidables[collidableIndexA].m_shapeType == SHAPE_SPHERE &&
hostCollidables[collidableIndexB].m_shapeType == SHAPE_CONVEX_HULL)
{
- computeContactSphereConvex(i,bodyIndexA,bodyIndexB,collidableIndexA,collidableIndexB,&hostBodyBuf[0],
- &hostCollidables[0],&hostConvexData[0],&hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
+ computeContactSphereConvex(i, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB, &hostBodyBuf[0],
+ &hostCollidables[0], &hostConvexData[0], &hostVertices[0], &hostIndices[0], &hostFaces[0], &hostContacts[0], nContacts, maxContactCapacity);
}
if (hostCollidables[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&
hostCollidables[collidableIndexB].m_shapeType == SHAPE_SPHERE)
{
- computeContactSphereConvex(i,bodyIndexB,bodyIndexA,collidableIndexB,collidableIndexA,&hostBodyBuf[0],
- &hostCollidables[0],&hostConvexData[0],&hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
+ computeContactSphereConvex(i, bodyIndexB, bodyIndexA, collidableIndexB, collidableIndexA, &hostBodyBuf[0],
+ &hostCollidables[0], &hostConvexData[0], &hostVertices[0], &hostIndices[0], &hostFaces[0], &hostContacts[0], nContacts, maxContactCapacity);
//printf("convex-sphere\n");
-
}
if (hostCollidables[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&
hostCollidables[collidableIndexB].m_shapeType == SHAPE_PLANE)
{
- computeContactPlaneConvex(i,bodyIndexB,bodyIndexA,collidableIndexB,collidableIndexA,&hostBodyBuf[0],
- &hostCollidables[0],&hostConvexData[0],&hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
-// printf("convex-plane\n");
-
+ computeContactPlaneConvex(i, bodyIndexB, bodyIndexA, collidableIndexB, collidableIndexA, &hostBodyBuf[0],
+ &hostCollidables[0], &hostConvexData[0], &hostVertices[0], &hostIndices[0], &hostFaces[0], &hostContacts[0], nContacts, maxContactCapacity);
+ // printf("convex-plane\n");
}
if (hostCollidables[collidableIndexA].m_shapeType == SHAPE_PLANE &&
hostCollidables[collidableIndexB].m_shapeType == SHAPE_CONVEX_HULL)
{
- computeContactPlaneConvex(i,bodyIndexA,bodyIndexB,collidableIndexA,collidableIndexB,&hostBodyBuf[0],
- &hostCollidables[0],&hostConvexData[0],&hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
-// printf("plane-convex\n");
-
+ computeContactPlaneConvex(i, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB, &hostBodyBuf[0],
+ &hostCollidables[0], &hostConvexData[0], &hostVertices[0], &hostIndices[0], &hostFaces[0], &hostContacts[0], nContacts, maxContactCapacity);
+ // printf("plane-convex\n");
}
- if (hostCollidables[collidableIndexA].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS &&
+ if (hostCollidables[collidableIndexA].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS &&
hostCollidables[collidableIndexB].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS)
{
- computeContactCompoundCompound(i,bodyIndexB,bodyIndexA,collidableIndexB,collidableIndexA,&hostBodyBuf[0],
- &hostCollidables[0],&hostConvexData[0],&cpuChildShapes[0], hostAabbsWorldSpace,hostAabbsLocalSpace,hostVertices,hostUniqueEdges,hostIndices,hostFaces,&hostContacts[0],
- nContacts,maxContactCapacity,treeNodesCPU,subTreesCPU,bvhInfoCPU);
-// printf("convex-plane\n");
-
+ computeContactCompoundCompound(i, bodyIndexB, bodyIndexA, collidableIndexB, collidableIndexA, &hostBodyBuf[0],
+ &hostCollidables[0], &hostConvexData[0], &cpuChildShapes[0], hostAabbsWorldSpace, hostAabbsLocalSpace, hostVertices, hostUniqueEdges, hostIndices, hostFaces, &hostContacts[0],
+ nContacts, maxContactCapacity, treeNodesCPU, subTreesCPU, bvhInfoCPU);
+ // printf("convex-plane\n");
}
-
- if (hostCollidables[collidableIndexA].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS &&
+ if (hostCollidables[collidableIndexA].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS &&
hostCollidables[collidableIndexB].m_shapeType == SHAPE_PLANE)
{
- computeContactPlaneCompound(i,bodyIndexB,bodyIndexA,collidableIndexB,collidableIndexA,&hostBodyBuf[0],
- &hostCollidables[0],&hostConvexData[0],&cpuChildShapes[0], &hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
-// printf("convex-plane\n");
-
+ computeContactPlaneCompound(i, bodyIndexB, bodyIndexA, collidableIndexB, collidableIndexA, &hostBodyBuf[0],
+ &hostCollidables[0], &hostConvexData[0], &cpuChildShapes[0], &hostVertices[0], &hostIndices[0], &hostFaces[0], &hostContacts[0], nContacts, maxContactCapacity);
+ // printf("convex-plane\n");
}
if (hostCollidables[collidableIndexA].m_shapeType == SHAPE_PLANE &&
hostCollidables[collidableIndexB].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS)
{
- computeContactPlaneCompound(i,bodyIndexA,bodyIndexB,collidableIndexA,collidableIndexB,&hostBodyBuf[0],
- &hostCollidables[0],&hostConvexData[0],&cpuChildShapes[0],&hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
-// printf("plane-convex\n");
-
+ computeContactPlaneCompound(i, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB, &hostBodyBuf[0],
+ &hostCollidables[0], &hostConvexData[0], &cpuChildShapes[0], &hostVertices[0], &hostIndices[0], &hostFaces[0], &hostContacts[0], nContacts, maxContactCapacity);
+ // printf("plane-convex\n");
}
if (hostCollidables[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&
hostCollidables[collidableIndexB].m_shapeType == SHAPE_CONVEX_HULL)
{
//printf("hostPairs[i].z=%d\n",hostPairs[i].z);
- int contactIndex = computeContactConvexConvex2( i,bodyIndexA,bodyIndexB,collidableIndexA,collidableIndexB,hostBodyBuf, hostCollidables,hostConvexData,hostVertices,hostUniqueEdges,hostIndices,hostFaces,hostContacts,nContacts,maxContactCapacity,oldHostContacts);
+ int contactIndex = computeContactConvexConvex2(i, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB, hostBodyBuf, hostCollidables, hostConvexData, hostVertices, hostUniqueEdges, hostIndices, hostFaces, hostContacts, nContacts, maxContactCapacity, oldHostContacts);
//int contactIndex = computeContactConvexConvex(hostPairs,i,bodyIndexA,bodyIndexB,collidableIndexA,collidableIndexB,hostBodyBuf,hostCollidables,hostConvexData,hostVertices,hostUniqueEdges,hostIndices,hostFaces,hostContacts,nContacts,maxContactCapacity,oldHostContacts);
-
- if (contactIndex>=0)
+ if (contactIndex >= 0)
{
-// printf("convex convex contactIndex = %d\n",contactIndex);
+ // printf("convex convex contactIndex = %d\n",contactIndex);
hostPairs[i].z = contactIndex;
}
-// printf("plane-convex\n");
-
+ // printf("plane-convex\n");
}
-
-
}
if (hostPairs.size())
@@ -2908,81 +2736,76 @@ void GpuSatCollision::computeConvexConvexContactsGPUSAT( b3OpenCLArray<b3Int4>*
hostContacts.resize(nContacts);
if (nContacts)
- {
-
- contactOut->copyFromHost(hostContacts);
- } else
+ {
+ contactOut->copyFromHost(hostContacts);
+ }
+ else
{
contactOut->resize(0);
- }
+ }
- m_totalContactsOut.copyFromHostPointer(&nContacts,1,0,true);
- //printf("(HOST) nContacts = %d\n",nContacts);
+ m_totalContactsOut.copyFromHostPointer(&nContacts, 1, 0, true);
+ //printf("(HOST) nContacts = %d\n",nContacts);
#else
{
if (nPairs)
{
- m_totalContactsOut.copyFromHostPointer(&nContacts,1,0,true);
+ m_totalContactsOut.copyFromHostPointer(&nContacts, 1, 0, true);
B3_PROFILE("primitiveContactsKernel");
b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL( pairs->getBufferCL(), true ),
- b3BufferInfoCL( bodyBuf->getBufferCL(),true),
- b3BufferInfoCL( gpuCollidables.getBufferCL(),true),
- b3BufferInfoCL( convexData.getBufferCL(),true),
- b3BufferInfoCL( gpuVertices.getBufferCL(),true),
- b3BufferInfoCL( gpuUniqueEdges.getBufferCL(),true),
- b3BufferInfoCL( gpuFaces.getBufferCL(),true),
- b3BufferInfoCL( gpuIndices.getBufferCL(),true),
- b3BufferInfoCL( contactOut->getBufferCL()),
- b3BufferInfoCL( m_totalContactsOut.getBufferCL())
- };
-
- b3LauncherCL launcher(m_queue, m_primitiveContactsKernel,"m_primitiveContactsKernel");
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst( nPairs );
+ b3BufferInfoCL(pairs->getBufferCL(), true),
+ b3BufferInfoCL(bodyBuf->getBufferCL(), true),
+ b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
+ b3BufferInfoCL(convexData.getBufferCL(), true),
+ b3BufferInfoCL(gpuVertices.getBufferCL(), true),
+ b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
+ b3BufferInfoCL(gpuFaces.getBufferCL(), true),
+ b3BufferInfoCL(gpuIndices.getBufferCL(), true),
+ b3BufferInfoCL(contactOut->getBufferCL()),
+ b3BufferInfoCL(m_totalContactsOut.getBufferCL())};
+
+ b3LauncherCL launcher(m_queue, m_primitiveContactsKernel, "m_primitiveContactsKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setConst(nPairs);
launcher.setConst(maxContactCapacity);
int num = nPairs;
- launcher.launch1D( num);
+ launcher.launch1D(num);
clFinish(m_queue);
-
+
nContacts = m_totalContactsOut.at(0);
contactOut->resize(nContacts);
}
}
-
-#endif//CHECK_ON_HOST
-
+#endif //CHECK_ON_HOST
+
B3_PROFILE("computeConvexConvexContactsGPUSAT");
- // printf("nContacts = %d\n",nContacts);
-
-
+ // printf("nContacts = %d\n",nContacts);
+
m_sepNormals.resize(nPairs);
m_hasSeparatingNormals.resize(nPairs);
-
- int concaveCapacity=maxTriConvexPairCapacity;
+
+ int concaveCapacity = maxTriConvexPairCapacity;
m_concaveSepNormals.resize(concaveCapacity);
m_concaveHasSeparatingNormals.resize(concaveCapacity);
m_numConcavePairsOut.resize(0);
m_numConcavePairsOut.push_back(0);
-
m_gpuCompoundPairs.resize(compoundPairCapacity);
m_gpuCompoundSepNormals.resize(compoundPairCapacity);
-
-
+
m_gpuHasCompoundSepNormals.resize(compoundPairCapacity);
-
+
m_numCompoundPairsOut.resize(0);
m_numCompoundPairsOut.push_back(0);
int numCompoundPairs = 0;
- int numConcavePairs =0;
+ int numConcavePairs = 0;
{
clFinish(m_queue);
@@ -2991,33 +2814,30 @@ void GpuSatCollision::computeConvexConvexContactsGPUSAT( b3OpenCLArray<b3Int4>*
m_dmins.resize(nPairs);
if (splitSearchSepAxisConvex)
{
-
-
if (useMprGpu)
{
nContacts = m_totalContactsOut.at(0);
{
B3_PROFILE("mprPenetrationKernel");
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL( pairs->getBufferCL(), true ),
- b3BufferInfoCL( bodyBuf->getBufferCL(),true),
- b3BufferInfoCL( gpuCollidables.getBufferCL(),true),
- b3BufferInfoCL( convexData.getBufferCL(),true),
- b3BufferInfoCL( gpuVertices.getBufferCL(),true),
- b3BufferInfoCL( m_sepNormals.getBufferCL()),
- b3BufferInfoCL( m_hasSeparatingNormals.getBufferCL()),
- b3BufferInfoCL( contactOut->getBufferCL()),
- b3BufferInfoCL( m_totalContactsOut.getBufferCL())
- };
-
- b3LauncherCL launcher(m_queue, m_mprPenetrationKernel,"mprPenetrationKernel");
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL(pairs->getBufferCL(), true),
+ b3BufferInfoCL(bodyBuf->getBufferCL(), true),
+ b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
+ b3BufferInfoCL(convexData.getBufferCL(), true),
+ b3BufferInfoCL(gpuVertices.getBufferCL(), true),
+ b3BufferInfoCL(m_sepNormals.getBufferCL()),
+ b3BufferInfoCL(m_hasSeparatingNormals.getBufferCL()),
+ b3BufferInfoCL(contactOut->getBufferCL()),
+ b3BufferInfoCL(m_totalContactsOut.getBufferCL())};
+
+ b3LauncherCL launcher(m_queue, m_mprPenetrationKernel, "mprPenetrationKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
launcher.setConst(maxContactCapacity);
- launcher.setConst( nPairs );
+ launcher.setConst(nPairs);
int num = nPairs;
- launcher.launch1D( num);
+ launcher.launch1D(num);
clFinish(m_queue);
/*
b3AlignedObjectArray<int>hostHasSepAxis;
@@ -3027,173 +2847,160 @@ void GpuSatCollision::computeConvexConvexContactsGPUSAT( b3OpenCLArray<b3Int4>*
*/
nContacts = m_totalContactsOut.at(0);
contactOut->resize(nContacts);
- // printf("nContacts (after mprPenetrationKernel) = %d\n",nContacts);
- if (nContacts>maxContactCapacity)
+ // printf("nContacts (after mprPenetrationKernel) = %d\n",nContacts);
+ if (nContacts > maxContactCapacity)
{
-
b3Error("Error: contacts exceeds capacity (%d/%d)\n", nContacts, maxContactCapacity);
nContacts = maxContactCapacity;
}
-
}
}
-
+
if (1)
{
-
if (1)
{
- {
- B3_PROFILE("findSeparatingAxisVertexFaceKernel");
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL( pairs->getBufferCL(), true ),
- b3BufferInfoCL( bodyBuf->getBufferCL(),true),
- b3BufferInfoCL( gpuCollidables.getBufferCL(),true),
- b3BufferInfoCL( convexData.getBufferCL(),true),
- b3BufferInfoCL( gpuVertices.getBufferCL(),true),
- b3BufferInfoCL( gpuUniqueEdges.getBufferCL(),true),
- b3BufferInfoCL( gpuFaces.getBufferCL(),true),
- b3BufferInfoCL( gpuIndices.getBufferCL(),true),
- b3BufferInfoCL( clAabbsWorldSpace.getBufferCL(),true),
- b3BufferInfoCL( m_sepNormals.getBufferCL()),
- b3BufferInfoCL( m_hasSeparatingNormals.getBufferCL()),
- b3BufferInfoCL( m_dmins.getBufferCL())
- };
-
- b3LauncherCL launcher(m_queue, m_findSeparatingAxisVertexFaceKernel,"findSeparatingAxisVertexFaceKernel");
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst( nPairs );
+ {
+ B3_PROFILE("findSeparatingAxisVertexFaceKernel");
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL(pairs->getBufferCL(), true),
+ b3BufferInfoCL(bodyBuf->getBufferCL(), true),
+ b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
+ b3BufferInfoCL(convexData.getBufferCL(), true),
+ b3BufferInfoCL(gpuVertices.getBufferCL(), true),
+ b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
+ b3BufferInfoCL(gpuFaces.getBufferCL(), true),
+ b3BufferInfoCL(gpuIndices.getBufferCL(), true),
+ b3BufferInfoCL(clAabbsWorldSpace.getBufferCL(), true),
+ b3BufferInfoCL(m_sepNormals.getBufferCL()),
+ b3BufferInfoCL(m_hasSeparatingNormals.getBufferCL()),
+ b3BufferInfoCL(m_dmins.getBufferCL())};
+
+ b3LauncherCL launcher(m_queue, m_findSeparatingAxisVertexFaceKernel, "findSeparatingAxisVertexFaceKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setConst(nPairs);
- int num = nPairs;
- launcher.launch1D( num);
- clFinish(m_queue);
- }
+ int num = nPairs;
+ launcher.launch1D(num);
+ clFinish(m_queue);
+ }
+ int numDirections = sizeof(unitSphere162) / sizeof(b3Vector3);
- int numDirections = sizeof(unitSphere162)/sizeof(b3Vector3);
-
- {
- B3_PROFILE("findSeparatingAxisEdgeEdgeKernel");
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL( pairs->getBufferCL(), true ),
- b3BufferInfoCL( bodyBuf->getBufferCL(),true),
- b3BufferInfoCL( gpuCollidables.getBufferCL(),true),
- b3BufferInfoCL( convexData.getBufferCL(),true),
- b3BufferInfoCL( gpuVertices.getBufferCL(),true),
- b3BufferInfoCL( gpuUniqueEdges.getBufferCL(),true),
- b3BufferInfoCL( gpuFaces.getBufferCL(),true),
- b3BufferInfoCL( gpuIndices.getBufferCL(),true),
- b3BufferInfoCL( clAabbsWorldSpace.getBufferCL(),true),
- b3BufferInfoCL( m_sepNormals.getBufferCL()),
- b3BufferInfoCL( m_hasSeparatingNormals.getBufferCL()),
- b3BufferInfoCL( m_dmins.getBufferCL()),
- b3BufferInfoCL( m_unitSphereDirections.getBufferCL(),true)
-
- };
-
- b3LauncherCL launcher(m_queue, m_findSeparatingAxisEdgeEdgeKernel,"findSeparatingAxisEdgeEdgeKernel");
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst( numDirections);
- launcher.setConst( nPairs );
- int num = nPairs;
- launcher.launch1D( num);
- clFinish(m_queue);
+ {
+ B3_PROFILE("findSeparatingAxisEdgeEdgeKernel");
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL(pairs->getBufferCL(), true),
+ b3BufferInfoCL(bodyBuf->getBufferCL(), true),
+ b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
+ b3BufferInfoCL(convexData.getBufferCL(), true),
+ b3BufferInfoCL(gpuVertices.getBufferCL(), true),
+ b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
+ b3BufferInfoCL(gpuFaces.getBufferCL(), true),
+ b3BufferInfoCL(gpuIndices.getBufferCL(), true),
+ b3BufferInfoCL(clAabbsWorldSpace.getBufferCL(), true),
+ b3BufferInfoCL(m_sepNormals.getBufferCL()),
+ b3BufferInfoCL(m_hasSeparatingNormals.getBufferCL()),
+ b3BufferInfoCL(m_dmins.getBufferCL()),
+ b3BufferInfoCL(m_unitSphereDirections.getBufferCL(), true)
- }
+ };
+
+ b3LauncherCL launcher(m_queue, m_findSeparatingAxisEdgeEdgeKernel, "findSeparatingAxisEdgeEdgeKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setConst(numDirections);
+ launcher.setConst(nPairs);
+ int num = nPairs;
+ launcher.launch1D(num);
+ clFinish(m_queue);
+ }
}
if (useMprGpu)
{
B3_PROFILE("findSeparatingAxisUnitSphereKernel");
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL( pairs->getBufferCL(), true ),
- b3BufferInfoCL( bodyBuf->getBufferCL(),true),
- b3BufferInfoCL( gpuCollidables.getBufferCL(),true),
- b3BufferInfoCL( convexData.getBufferCL(),true),
- b3BufferInfoCL( gpuVertices.getBufferCL(),true),
- b3BufferInfoCL( m_unitSphereDirections.getBufferCL(),true),
- b3BufferInfoCL( m_sepNormals.getBufferCL()),
- b3BufferInfoCL( m_hasSeparatingNormals.getBufferCL()),
- b3BufferInfoCL( m_dmins.getBufferCL())
- };
-
- b3LauncherCL launcher(m_queue, m_findSeparatingAxisUnitSphereKernel,"findSeparatingAxisUnitSphereKernel");
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- int numDirections = sizeof(unitSphere162)/sizeof(b3Vector3);
- launcher.setConst( numDirections);
-
- launcher.setConst( nPairs );
-
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL(pairs->getBufferCL(), true),
+ b3BufferInfoCL(bodyBuf->getBufferCL(), true),
+ b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
+ b3BufferInfoCL(convexData.getBufferCL(), true),
+ b3BufferInfoCL(gpuVertices.getBufferCL(), true),
+ b3BufferInfoCL(m_unitSphereDirections.getBufferCL(), true),
+ b3BufferInfoCL(m_sepNormals.getBufferCL()),
+ b3BufferInfoCL(m_hasSeparatingNormals.getBufferCL()),
+ b3BufferInfoCL(m_dmins.getBufferCL())};
+
+ b3LauncherCL launcher(m_queue, m_findSeparatingAxisUnitSphereKernel, "findSeparatingAxisUnitSphereKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ int numDirections = sizeof(unitSphere162) / sizeof(b3Vector3);
+ launcher.setConst(numDirections);
+
+ launcher.setConst(nPairs);
+
int num = nPairs;
- launcher.launch1D( num);
+ launcher.launch1D(num);
clFinish(m_queue);
}
+ }
}
-
-
- } else
+ else
{
B3_PROFILE("findSeparatingAxisKernel");
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL( pairs->getBufferCL(), true ),
- b3BufferInfoCL( bodyBuf->getBufferCL(),true),
- b3BufferInfoCL( gpuCollidables.getBufferCL(),true),
- b3BufferInfoCL( convexData.getBufferCL(),true),
- b3BufferInfoCL( gpuVertices.getBufferCL(),true),
- b3BufferInfoCL( gpuUniqueEdges.getBufferCL(),true),
- b3BufferInfoCL( gpuFaces.getBufferCL(),true),
- b3BufferInfoCL( gpuIndices.getBufferCL(),true),
- b3BufferInfoCL( clAabbsWorldSpace.getBufferCL(),true),
- b3BufferInfoCL( m_sepNormals.getBufferCL()),
- b3BufferInfoCL( m_hasSeparatingNormals.getBufferCL())
- };
-
- b3LauncherCL launcher(m_queue, m_findSeparatingAxisKernel,"m_findSeparatingAxisKernel");
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst( nPairs );
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL(pairs->getBufferCL(), true),
+ b3BufferInfoCL(bodyBuf->getBufferCL(), true),
+ b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
+ b3BufferInfoCL(convexData.getBufferCL(), true),
+ b3BufferInfoCL(gpuVertices.getBufferCL(), true),
+ b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
+ b3BufferInfoCL(gpuFaces.getBufferCL(), true),
+ b3BufferInfoCL(gpuIndices.getBufferCL(), true),
+ b3BufferInfoCL(clAabbsWorldSpace.getBufferCL(), true),
+ b3BufferInfoCL(m_sepNormals.getBufferCL()),
+ b3BufferInfoCL(m_hasSeparatingNormals.getBufferCL())};
+
+ b3LauncherCL launcher(m_queue, m_findSeparatingAxisKernel, "m_findSeparatingAxisKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setConst(nPairs);
int num = nPairs;
- launcher.launch1D( num);
+ launcher.launch1D(num);
clFinish(m_queue);
}
-
-
}
- else
- {
-
+ else
+ {
B3_PROFILE("findSeparatingAxisKernel CPU");
-
-
- b3AlignedObjectArray<b3Int4> hostPairs;
- pairs->copyToHost(hostPairs);
- b3AlignedObjectArray<b3RigidBodyData> hostBodyBuf;
- bodyBuf->copyToHost(hostBodyBuf);
-
- b3AlignedObjectArray<b3Collidable> hostCollidables;
- gpuCollidables.copyToHost(hostCollidables);
-
- b3AlignedObjectArray<b3GpuChildShape> cpuChildShapes;
- gpuChildShapes.copyToHost(cpuChildShapes);
-
- b3AlignedObjectArray<b3ConvexPolyhedronData> hostConvexShapeData;
- convexData.copyToHost(hostConvexShapeData);
-
- b3AlignedObjectArray<b3Vector3> hostVertices;
- gpuVertices.copyToHost(hostVertices);
-
- b3AlignedObjectArray<int> hostHasSepAxis;
- hostHasSepAxis.resize(nPairs);
- b3AlignedObjectArray<b3Vector3> hostSepAxis;
- hostSepAxis.resize(nPairs);
-
- b3AlignedObjectArray<b3Vector3> hostUniqueEdges;
- gpuUniqueEdges.copyToHost(hostUniqueEdges);
- b3AlignedObjectArray<b3GpuFace> hostFaces;
- gpuFaces.copyToHost(hostFaces);
-
- b3AlignedObjectArray<int> hostIndices;
- gpuIndices.copyToHost(hostIndices);
-
+
+ b3AlignedObjectArray<b3Int4> hostPairs;
+ pairs->copyToHost(hostPairs);
+ b3AlignedObjectArray<b3RigidBodyData> hostBodyBuf;
+ bodyBuf->copyToHost(hostBodyBuf);
+
+ b3AlignedObjectArray<b3Collidable> hostCollidables;
+ gpuCollidables.copyToHost(hostCollidables);
+
+ b3AlignedObjectArray<b3GpuChildShape> cpuChildShapes;
+ gpuChildShapes.copyToHost(cpuChildShapes);
+
+ b3AlignedObjectArray<b3ConvexPolyhedronData> hostConvexShapeData;
+ convexData.copyToHost(hostConvexShapeData);
+
+ b3AlignedObjectArray<b3Vector3> hostVertices;
+ gpuVertices.copyToHost(hostVertices);
+
+ b3AlignedObjectArray<int> hostHasSepAxis;
+ hostHasSepAxis.resize(nPairs);
+ b3AlignedObjectArray<b3Vector3> hostSepAxis;
+ hostSepAxis.resize(nPairs);
+
+ b3AlignedObjectArray<b3Vector3> hostUniqueEdges;
+ gpuUniqueEdges.copyToHost(hostUniqueEdges);
+ b3AlignedObjectArray<b3GpuFace> hostFaces;
+ gpuFaces.copyToHost(hostFaces);
+
+ b3AlignedObjectArray<int> hostIndices;
+ gpuIndices.copyToHost(hostIndices);
+
b3AlignedObjectArray<b3Contact4> hostContacts;
if (nContacts)
{
@@ -3201,61 +3008,56 @@ void GpuSatCollision::computeConvexConvexContactsGPUSAT( b3OpenCLArray<b3Int4>*
}
hostContacts.resize(maxContactCapacity);
int nGlobalContactsOut = nContacts;
-
-
- for (int i=0;i<nPairs;i++)
- {
-
- int bodyIndexA = hostPairs[i].x;
- int bodyIndexB = hostPairs[i].y;
- int collidableIndexA = hostBodyBuf[bodyIndexA].m_collidableIdx;
- int collidableIndexB = hostBodyBuf[bodyIndexB].m_collidableIdx;
-
- int shapeIndexA = hostCollidables[collidableIndexA].m_shapeIndex;
- int shapeIndexB = hostCollidables[collidableIndexB].m_shapeIndex;
-
- hostHasSepAxis[i] = 0;
-
- //once the broadphase avoids static-static pairs, we can remove this test
- if ((hostBodyBuf[bodyIndexA].m_invMass==0) &&(hostBodyBuf[bodyIndexB].m_invMass==0))
- {
- continue;
- }
-
-
- if ((hostCollidables[collidableIndexA].m_shapeType!=SHAPE_CONVEX_HULL) ||(hostCollidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL))
- {
- continue;
- }
-
- float dmin = FLT_MAX;
-
- b3ConvexPolyhedronData* convexShapeA = &hostConvexShapeData[shapeIndexA];
- b3ConvexPolyhedronData* convexShapeB = &hostConvexShapeData[shapeIndexB];
- b3Vector3 posA = hostBodyBuf[bodyIndexA].m_pos;
- b3Vector3 posB = hostBodyBuf[bodyIndexB].m_pos;
- b3Quaternion ornA =hostBodyBuf[bodyIndexA].m_quat;
- b3Quaternion ornB =hostBodyBuf[bodyIndexB].m_quat;
-
-
- if (useGjk)
+
+ for (int i = 0; i < nPairs; i++)
+ {
+ int bodyIndexA = hostPairs[i].x;
+ int bodyIndexB = hostPairs[i].y;
+ int collidableIndexA = hostBodyBuf[bodyIndexA].m_collidableIdx;
+ int collidableIndexB = hostBodyBuf[bodyIndexB].m_collidableIdx;
+
+ int shapeIndexA = hostCollidables[collidableIndexA].m_shapeIndex;
+ int shapeIndexB = hostCollidables[collidableIndexB].m_shapeIndex;
+
+ hostHasSepAxis[i] = 0;
+
+ //once the broadphase avoids static-static pairs, we can remove this test
+ if ((hostBodyBuf[bodyIndexA].m_invMass == 0) && (hostBodyBuf[bodyIndexB].m_invMass == 0))
{
+ continue;
+ }
+ if ((hostCollidables[collidableIndexA].m_shapeType != SHAPE_CONVEX_HULL) || (hostCollidables[collidableIndexB].m_shapeType != SHAPE_CONVEX_HULL))
+ {
+ continue;
+ }
+
+ float dmin = FLT_MAX;
+
+ b3ConvexPolyhedronData* convexShapeA = &hostConvexShapeData[shapeIndexA];
+ b3ConvexPolyhedronData* convexShapeB = &hostConvexShapeData[shapeIndexB];
+ b3Vector3 posA = hostBodyBuf[bodyIndexA].m_pos;
+ b3Vector3 posB = hostBodyBuf[bodyIndexB].m_pos;
+ b3Quaternion ornA = hostBodyBuf[bodyIndexA].m_quat;
+ b3Quaternion ornB = hostBodyBuf[bodyIndexB].m_quat;
+
+ if (useGjk)
+ {
//first approximate the separating axis, to 'fail-proof' GJK+EPA or MPR
{
b3Vector3 c0local = hostConvexShapeData[shapeIndexA].m_localCenter;
b3Vector3 c0 = b3TransformPoint(c0local, posA, ornA);
b3Vector3 c1local = hostConvexShapeData[shapeIndexB].m_localCenter;
- b3Vector3 c1 = b3TransformPoint(c1local,posB,ornB);
+ b3Vector3 c1 = b3TransformPoint(c1local, posB, ornB);
b3Vector3 DeltaC2 = c0 - c1;
-
+
b3Vector3 sepAxis;
-
+
bool hasSepAxisA = b3FindSeparatingAxis(convexShapeA, convexShapeB, posA, ornA, posB, ornB, DeltaC2,
- &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
- &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
- &sepAxis, &dmin);
-
+ &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
+ &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
+ &sepAxis, &dmin);
+
if (hasSepAxisA)
{
bool hasSepAxisB = b3FindSeparatingAxis(convexShapeB, convexShapeA, posB, ornB, posA, ornA, DeltaC2,
@@ -3264,11 +3066,11 @@ void GpuSatCollision::computeConvexConvexContactsGPUSAT( b3OpenCLArray<b3Int4>*
&sepAxis, &dmin);
if (hasSepAxisB)
{
- bool hasEdgeEdge =b3FindSeparatingAxisEdgeEdge(convexShapeA, convexShapeB, posA, ornA, posB, ornB, DeltaC2,
- &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
- &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
- &sepAxis, &dmin,false);
-
+ bool hasEdgeEdge = b3FindSeparatingAxisEdgeEdge(convexShapeA, convexShapeB, posA, ornA, posB, ornB, DeltaC2,
+ &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
+ &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
+ &sepAxis, &dmin, false);
+
if (hasEdgeEdge)
{
hostHasSepAxis[i] = 1;
@@ -3282,163 +3084,150 @@ void GpuSatCollision::computeConvexConvexContactsGPUSAT( b3OpenCLArray<b3Int4>*
if (hostHasSepAxis[i])
{
int pairIndex = i;
-
+
bool useMpr = true;
if (useMpr)
{
- int res=0;
+ int res = 0;
float depth = 0.f;
- b3Vector3 sepAxis2 = b3MakeVector3(1,0,0);
- b3Vector3 resultPointOnBWorld = b3MakeVector3(0,0,0);
+ b3Vector3 sepAxis2 = b3MakeVector3(1, 0, 0);
+ b3Vector3 resultPointOnBWorld = b3MakeVector3(0, 0, 0);
- float depthOut;
- b3Vector3 dirOut;
- b3Vector3 posOut;
-
+ float depthOut;
+ b3Vector3 dirOut;
+ b3Vector3 posOut;
- //res = b3MprPenetration(bodyIndexA,bodyIndexB,hostBodyBuf,hostConvexShapeData,hostCollidables,hostVertices,&mprConfig,&depthOut,&dirOut,&posOut);
- res = b3MprPenetration(pairIndex,bodyIndexA,bodyIndexB,&hostBodyBuf[0],&hostConvexShapeData[0],&hostCollidables[0],&hostVertices[0],&hostSepAxis[0],&hostHasSepAxis[0],&depthOut,&dirOut,&posOut);
- depth = depthOut;
- sepAxis2 = b3MakeVector3(-dirOut.x,-dirOut.y,-dirOut.z);
- resultPointOnBWorld = posOut;
- //hostHasSepAxis[i] = 0;
+ //res = b3MprPenetration(bodyIndexA,bodyIndexB,hostBodyBuf,hostConvexShapeData,hostCollidables,hostVertices,&mprConfig,&depthOut,&dirOut,&posOut);
+ res = b3MprPenetration(pairIndex, bodyIndexA, bodyIndexB, &hostBodyBuf[0], &hostConvexShapeData[0], &hostCollidables[0], &hostVertices[0], &hostSepAxis[0], &hostHasSepAxis[0], &depthOut, &dirOut, &posOut);
+ depth = depthOut;
+ sepAxis2 = b3MakeVector3(-dirOut.x, -dirOut.y, -dirOut.z);
+ resultPointOnBWorld = posOut;
+ //hostHasSepAxis[i] = 0;
+ if (res == 0)
+ {
+ //add point?
+ //printf("depth = %f\n",depth);
+ //printf("normal = %f,%f,%f\n",dir.v[0],dir.v[1],dir.v[2]);
+ //qprintf("pos = %f,%f,%f\n",pos.v[0],pos.v[1],pos.v[2]);
- if (res==0)
- {
- //add point?
- //printf("depth = %f\n",depth);
- //printf("normal = %f,%f,%f\n",dir.v[0],dir.v[1],dir.v[2]);
- //qprintf("pos = %f,%f,%f\n",pos.v[0],pos.v[1],pos.v[2]);
-
-
-
- float dist=0.f;
+ float dist = 0.f;
- const b3ConvexPolyhedronData& hullA = hostConvexShapeData[hostCollidables[hostBodyBuf[bodyIndexA].m_collidableIdx].m_shapeIndex];
- const b3ConvexPolyhedronData& hullB = hostConvexShapeData[hostCollidables[hostBodyBuf[bodyIndexB].m_collidableIdx].m_shapeIndex];
+ const b3ConvexPolyhedronData& hullA = hostConvexShapeData[hostCollidables[hostBodyBuf[bodyIndexA].m_collidableIdx].m_shapeIndex];
+ const b3ConvexPolyhedronData& hullB = hostConvexShapeData[hostCollidables[hostBodyBuf[bodyIndexB].m_collidableIdx].m_shapeIndex];
- if(b3TestSepAxis( &hullA, &hullB, posA,ornA,posB,ornB,&sepAxis2, &hostVertices[0], &hostVertices[0],&dist))
- {
- if (depth > dist)
+ if (b3TestSepAxis(&hullA, &hullB, posA, ornA, posB, ornB, &sepAxis2, &hostVertices[0], &hostVertices[0], &dist))
{
- float diff = depth - dist;
-
- static float maxdiff = 0.f;
- if (maxdiff < diff)
+ if (depth > dist)
{
- maxdiff = diff;
- printf("maxdiff = %20.10f\n",maxdiff);
+ float diff = depth - dist;
+
+ static float maxdiff = 0.f;
+ if (maxdiff < diff)
+ {
+ maxdiff = diff;
+ printf("maxdiff = %20.10f\n", maxdiff);
+ }
}
}
- }
- if (depth > dmin)
- {
- b3Vector3 oldAxis = hostSepAxis[i];
- depth = dmin;
- sepAxis2 = oldAxis;
- }
-
-
+ if (depth > dmin)
+ {
+ b3Vector3 oldAxis = hostSepAxis[i];
+ depth = dmin;
+ sepAxis2 = oldAxis;
+ }
- if(b3TestSepAxis( &hullA, &hullB, posA,ornA,posB,ornB,&sepAxis2, &hostVertices[0], &hostVertices[0],&dist))
- {
- if (depth > dist)
+ if (b3TestSepAxis(&hullA, &hullB, posA, ornA, posB, ornB, &sepAxis2, &hostVertices[0], &hostVertices[0], &dist))
{
- float diff = depth - dist;
- //printf("?diff = %f\n",diff );
- static float maxdiff = 0.f;
- if (maxdiff < diff)
+ if (depth > dist)
+ {
+ float diff = depth - dist;
+ //printf("?diff = %f\n",diff );
+ static float maxdiff = 0.f;
+ if (maxdiff < diff)
+ {
+ maxdiff = diff;
+ printf("maxdiff = %20.10f\n", maxdiff);
+ }
+ }
+ //this is used for SAT
+ //hostHasSepAxis[i] = 1;
+ //hostSepAxis[i] = sepAxis2;
+
+ //add contact point
+
+ //int contactIndex = nGlobalContactsOut;
+ b3Contact4& newContact = hostContacts.at(nGlobalContactsOut);
+ nGlobalContactsOut++;
+ newContact.m_batchIdx = 0; //i;
+ newContact.m_bodyAPtrAndSignBit = (hostBodyBuf.at(bodyIndexA).m_invMass == 0) ? -bodyIndexA : bodyIndexA;
+ newContact.m_bodyBPtrAndSignBit = (hostBodyBuf.at(bodyIndexB).m_invMass == 0) ? -bodyIndexB : bodyIndexB;
+
+ newContact.m_frictionCoeffCmp = 45874;
+ newContact.m_restituitionCoeffCmp = 0;
+
+ static float maxDepth = 0.f;
+
+ if (depth > maxDepth)
{
- maxdiff = diff;
- printf("maxdiff = %20.10f\n",maxdiff);
+ maxDepth = depth;
+ printf("MPR maxdepth = %f\n", maxDepth);
}
+
+ resultPointOnBWorld.w = -depth;
+ newContact.m_worldPosB[0] = resultPointOnBWorld;
+ //b3Vector3 resultPointOnAWorld = resultPointOnBWorld+depth*sepAxis2;
+ newContact.m_worldNormalOnB = sepAxis2;
+ newContact.m_worldNormalOnB.w = (b3Scalar)1;
}
- //this is used for SAT
- //hostHasSepAxis[i] = 1;
- //hostSepAxis[i] = sepAxis2;
-
- //add contact point
-
- //int contactIndex = nGlobalContactsOut;
- b3Contact4& newContact = hostContacts.at(nGlobalContactsOut);
- nGlobalContactsOut++;
- newContact.m_batchIdx = 0;//i;
- newContact.m_bodyAPtrAndSignBit = (hostBodyBuf.at(bodyIndexA).m_invMass==0)? -bodyIndexA:bodyIndexA;
- newContact.m_bodyBPtrAndSignBit = (hostBodyBuf.at(bodyIndexB).m_invMass==0)? -bodyIndexB:bodyIndexB;
-
- newContact.m_frictionCoeffCmp = 45874;
- newContact.m_restituitionCoeffCmp = 0;
-
-
- static float maxDepth = 0.f;
-
- if (depth > maxDepth)
+ else
{
- maxDepth = depth;
- printf("MPR maxdepth = %f\n",maxDepth );
-
+ printf("rejected\n");
}
-
-
- resultPointOnBWorld.w = -depth;
- newContact.m_worldPosB[0] = resultPointOnBWorld;
- //b3Vector3 resultPointOnAWorld = resultPointOnBWorld+depth*sepAxis2;
- newContact.m_worldNormalOnB = sepAxis2;
- newContact.m_worldNormalOnB.w = (b3Scalar)1;
- } else
- {
- printf("rejected\n");
}
-
-
}
- } else
+ else
{
-
-
-
- //int contactIndex = computeContactConvexConvex2( i,bodyIndexA,bodyIndexB,collidableIndexA,collidableIndexB,hostBodyBuf, hostCollidables,hostConvexData,hostVertices,hostUniqueEdges,hostIndices,hostFaces,hostContacts,nContacts,maxContactCapacity,oldHostContacts);
- b3AlignedObjectArray<b3Contact4> oldHostContacts;
+ //int contactIndex = computeContactConvexConvex2( i,bodyIndexA,bodyIndexB,collidableIndexA,collidableIndexB,hostBodyBuf, hostCollidables,hostConvexData,hostVertices,hostUniqueEdges,hostIndices,hostFaces,hostContacts,nContacts,maxContactCapacity,oldHostContacts);
+ b3AlignedObjectArray<b3Contact4> oldHostContacts;
int result;
- result = computeContactConvexConvex2( //hostPairs,
- pairIndex,
- bodyIndexA, bodyIndexB,
- collidableIndexA, collidableIndexB,
- hostBodyBuf,
- hostCollidables,
- hostConvexShapeData,
- hostVertices,
- hostUniqueEdges,
- hostIndices,
- hostFaces,
- hostContacts,
- nGlobalContactsOut,
- maxContactCapacity,
- oldHostContacts
- //hostHasSepAxis,
- //hostSepAxis
-
- );
- }//mpr
- }//hostHasSepAxis[i] = 1;
-
- } else
+ result = computeContactConvexConvex2( //hostPairs,
+ pairIndex,
+ bodyIndexA, bodyIndexB,
+ collidableIndexA, collidableIndexB,
+ hostBodyBuf,
+ hostCollidables,
+ hostConvexShapeData,
+ hostVertices,
+ hostUniqueEdges,
+ hostIndices,
+ hostFaces,
+ hostContacts,
+ nGlobalContactsOut,
+ maxContactCapacity,
+ oldHostContacts
+ //hostHasSepAxis,
+ //hostSepAxis
+
+ );
+ } //mpr
+ } //hostHasSepAxis[i] = 1;
+ }
+ else
{
-
b3Vector3 c0local = hostConvexShapeData[shapeIndexA].m_localCenter;
b3Vector3 c0 = b3TransformPoint(c0local, posA, ornA);
b3Vector3 c1local = hostConvexShapeData[shapeIndexB].m_localCenter;
- b3Vector3 c1 = b3TransformPoint(c1local,posB,ornB);
+ b3Vector3 c1 = b3TransformPoint(c1local, posB, ornB);
b3Vector3 DeltaC2 = c0 - c1;
-
+
b3Vector3 sepAxis;
-
+
bool hasSepAxisA = b3FindSeparatingAxis(convexShapeA, convexShapeB, posA, ornA, posB, ornB, DeltaC2,
- &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
- &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
- &sepAxis, &dmin);
-
+ &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
+ &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
+ &sepAxis, &dmin);
+
if (hasSepAxisA)
{
bool hasSepAxisB = b3FindSeparatingAxis(convexShapeB, convexShapeA, posB, ornB, posA, ornA, DeltaC2,
@@ -3447,11 +3236,11 @@ void GpuSatCollision::computeConvexConvexContactsGPUSAT( b3OpenCLArray<b3Int4>*
&sepAxis, &dmin);
if (hasSepAxisB)
{
- bool hasEdgeEdge =b3FindSeparatingAxisEdgeEdge(convexShapeA, convexShapeB, posA, ornA, posB, ornB, DeltaC2,
- &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
- &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
- &sepAxis, &dmin,true);
-
+ bool hasEdgeEdge = b3FindSeparatingAxisEdgeEdge(convexShapeA, convexShapeB, posA, ornA, posB, ornB, DeltaC2,
+ &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
+ &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
+ &sepAxis, &dmin, true);
+
if (hasEdgeEdge)
{
hostHasSepAxis[i] = 1;
@@ -3460,21 +3249,21 @@ void GpuSatCollision::computeConvexConvexContactsGPUSAT( b3OpenCLArray<b3Int4>*
}
}
}
- }
-
- if (useGjkContacts)//nGlobalContactsOut>0)
+ }
+
+ if (useGjkContacts) //nGlobalContactsOut>0)
{
//printf("nGlobalContactsOut=%d\n",nGlobalContactsOut);
nContacts = nGlobalContactsOut;
contactOut->copyFromHost(hostContacts);
-
- m_totalContactsOut.copyFromHostPointer(&nContacts,1,0,true);
+
+ m_totalContactsOut.copyFromHostPointer(&nContacts, 1, 0, true);
}
-
- m_hasSeparatingNormals.copyFromHost(hostHasSepAxis);
- m_sepNormals.copyFromHost(hostSepAxis);
-
- /*
+
+ m_hasSeparatingNormals.copyFromHost(hostHasSepAxis);
+ m_sepNormals.copyFromHost(hostSepAxis);
+
+ /*
//double-check results from GPU (comment-out the 'else' so both paths are executed
b3AlignedObjectArray<int> checkHasSepAxis;
m_hasSeparatingNormals.copyToHost(checkHasSepAxis);
@@ -3491,352 +3280,314 @@ void GpuSatCollision::computeConvexConvexContactsGPUSAT( b3OpenCLArray<b3Int4>*
//m_hasSeparatingNormals.copyFromHost(hostHasSepAxis);
// m_sepNormals.copyFromHost(hostSepAxis);
*/
- }
-
-
- numCompoundPairs = m_numCompoundPairsOut.at(0);
- bool useGpuFindCompoundPairs=true;
- if (useGpuFindCompoundPairs)
- {
- B3_PROFILE("findCompoundPairsKernel");
- b3BufferInfoCL bInfo[] =
- {
- b3BufferInfoCL( pairs->getBufferCL(), true ),
- b3BufferInfoCL( bodyBuf->getBufferCL(),true),
- b3BufferInfoCL( gpuCollidables.getBufferCL(),true),
- b3BufferInfoCL( convexData.getBufferCL(),true),
- b3BufferInfoCL( gpuVertices.getBufferCL(),true),
- b3BufferInfoCL( gpuUniqueEdges.getBufferCL(),true),
- b3BufferInfoCL( gpuFaces.getBufferCL(),true),
- b3BufferInfoCL( gpuIndices.getBufferCL(),true),
- b3BufferInfoCL( clAabbsLocalSpace.getBufferCL(),true),
- b3BufferInfoCL( gpuChildShapes.getBufferCL(),true),
- b3BufferInfoCL( m_gpuCompoundPairs.getBufferCL()),
- b3BufferInfoCL( m_numCompoundPairsOut.getBufferCL()),
- b3BufferInfoCL(subTreesGPU->getBufferCL()),
- b3BufferInfoCL(treeNodesGPU->getBufferCL()),
- b3BufferInfoCL(bvhInfo->getBufferCL())
- };
-
- b3LauncherCL launcher(m_queue, m_findCompoundPairsKernel,"m_findCompoundPairsKernel");
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst( nPairs );
- launcher.setConst( compoundPairCapacity);
-
- int num = nPairs;
- launcher.launch1D( num);
- clFinish(m_queue);
-
- numCompoundPairs = m_numCompoundPairsOut.at(0);
- //printf("numCompoundPairs =%d\n",numCompoundPairs );
- if (numCompoundPairs)
- {
- //printf("numCompoundPairs=%d\n",numCompoundPairs);
- }
-
-
- } else
- {
-
-
- b3AlignedObjectArray<b3QuantizedBvhNode> treeNodesCPU;
- treeNodesGPU->copyToHost(treeNodesCPU);
-
- b3AlignedObjectArray<b3BvhSubtreeInfo> subTreesCPU;
- subTreesGPU->copyToHost(subTreesCPU);
+ }
- b3AlignedObjectArray<b3BvhInfo> bvhInfoCPU;
- bvhInfo->copyToHost(bvhInfoCPU);
+ numCompoundPairs = m_numCompoundPairsOut.at(0);
+ bool useGpuFindCompoundPairs = true;
+ if (useGpuFindCompoundPairs)
+ {
+ B3_PROFILE("findCompoundPairsKernel");
+ b3BufferInfoCL bInfo[] =
+ {
+ b3BufferInfoCL(pairs->getBufferCL(), true),
+ b3BufferInfoCL(bodyBuf->getBufferCL(), true),
+ b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
+ b3BufferInfoCL(convexData.getBufferCL(), true),
+ b3BufferInfoCL(gpuVertices.getBufferCL(), true),
+ b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
+ b3BufferInfoCL(gpuFaces.getBufferCL(), true),
+ b3BufferInfoCL(gpuIndices.getBufferCL(), true),
+ b3BufferInfoCL(clAabbsLocalSpace.getBufferCL(), true),
+ b3BufferInfoCL(gpuChildShapes.getBufferCL(), true),
+ b3BufferInfoCL(m_gpuCompoundPairs.getBufferCL()),
+ b3BufferInfoCL(m_numCompoundPairsOut.getBufferCL()),
+ b3BufferInfoCL(subTreesGPU->getBufferCL()),
+ b3BufferInfoCL(treeNodesGPU->getBufferCL()),
+ b3BufferInfoCL(bvhInfo->getBufferCL())};
+
+ b3LauncherCL launcher(m_queue, m_findCompoundPairsKernel, "m_findCompoundPairsKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setConst(nPairs);
+ launcher.setConst(compoundPairCapacity);
- b3AlignedObjectArray<b3Aabb> hostAabbsWorldSpace;
- clAabbsWorldSpace.copyToHost(hostAabbsWorldSpace);
+ int num = nPairs;
+ launcher.launch1D(num);
+ clFinish(m_queue);
- b3AlignedObjectArray<b3Aabb> hostAabbsLocalSpace;
- clAabbsLocalSpace.copyToHost(hostAabbsLocalSpace);
+ numCompoundPairs = m_numCompoundPairsOut.at(0);
+ //printf("numCompoundPairs =%d\n",numCompoundPairs );
+ if (numCompoundPairs)
+ {
+ //printf("numCompoundPairs=%d\n",numCompoundPairs);
+ }
+ }
+ else
+ {
+ b3AlignedObjectArray<b3QuantizedBvhNode> treeNodesCPU;
+ treeNodesGPU->copyToHost(treeNodesCPU);
- b3AlignedObjectArray<b3Int4> hostPairs;
- pairs->copyToHost(hostPairs);
+ b3AlignedObjectArray<b3BvhSubtreeInfo> subTreesCPU;
+ subTreesGPU->copyToHost(subTreesCPU);
- b3AlignedObjectArray<b3RigidBodyData> hostBodyBuf;
- bodyBuf->copyToHost(hostBodyBuf);
+ b3AlignedObjectArray<b3BvhInfo> bvhInfoCPU;
+ bvhInfo->copyToHost(bvhInfoCPU);
+ b3AlignedObjectArray<b3Aabb> hostAabbsWorldSpace;
+ clAabbsWorldSpace.copyToHost(hostAabbsWorldSpace);
- b3AlignedObjectArray<b3Int4> cpuCompoundPairsOut;
- cpuCompoundPairsOut.resize(compoundPairCapacity);
+ b3AlignedObjectArray<b3Aabb> hostAabbsLocalSpace;
+ clAabbsLocalSpace.copyToHost(hostAabbsLocalSpace);
- b3AlignedObjectArray<b3Collidable> hostCollidables;
- gpuCollidables.copyToHost(hostCollidables);
+ b3AlignedObjectArray<b3Int4> hostPairs;
+ pairs->copyToHost(hostPairs);
- b3AlignedObjectArray<b3GpuChildShape> cpuChildShapes;
- gpuChildShapes.copyToHost(cpuChildShapes);
+ b3AlignedObjectArray<b3RigidBodyData> hostBodyBuf;
+ bodyBuf->copyToHost(hostBodyBuf);
- b3AlignedObjectArray<b3ConvexPolyhedronData> hostConvexData;
- convexData.copyToHost(hostConvexData);
+ b3AlignedObjectArray<b3Int4> cpuCompoundPairsOut;
+ cpuCompoundPairsOut.resize(compoundPairCapacity);
- b3AlignedObjectArray<b3Vector3> hostVertices;
- gpuVertices.copyToHost(hostVertices);
+ b3AlignedObjectArray<b3Collidable> hostCollidables;
+ gpuCollidables.copyToHost(hostCollidables);
+ b3AlignedObjectArray<b3GpuChildShape> cpuChildShapes;
+ gpuChildShapes.copyToHost(cpuChildShapes);
+ b3AlignedObjectArray<b3ConvexPolyhedronData> hostConvexData;
+ convexData.copyToHost(hostConvexData);
+ b3AlignedObjectArray<b3Vector3> hostVertices;
+ gpuVertices.copyToHost(hostVertices);
- for (int pairIndex=0;pairIndex<nPairs;pairIndex++)
- {
- int bodyIndexA = hostPairs[pairIndex].x;
- int bodyIndexB = hostPairs[pairIndex].y;
- int collidableIndexA = hostBodyBuf[bodyIndexA].m_collidableIdx;
- int collidableIndexB = hostBodyBuf[bodyIndexB].m_collidableIdx;
+ for (int pairIndex = 0; pairIndex < nPairs; pairIndex++)
+ {
+ int bodyIndexA = hostPairs[pairIndex].x;
+ int bodyIndexB = hostPairs[pairIndex].y;
+ int collidableIndexA = hostBodyBuf[bodyIndexA].m_collidableIdx;
+ int collidableIndexB = hostBodyBuf[bodyIndexB].m_collidableIdx;
if (cpuChildShapes.size())
{
- findCompoundPairsKernel(
- pairIndex,
- bodyIndexA,
- bodyIndexB,
- collidableIndexA,
- collidableIndexB,
- &hostBodyBuf[0],
- &hostCollidables[0],
- &hostConvexData[0],
- hostVertices,
- hostAabbsWorldSpace,
- hostAabbsLocalSpace,
- &cpuChildShapes[0],
- &cpuCompoundPairsOut[0],
- &numCompoundPairs,
- compoundPairCapacity,
- treeNodesCPU,
- subTreesCPU,
- bvhInfoCPU
- );
+ findCompoundPairsKernel(
+ pairIndex,
+ bodyIndexA,
+ bodyIndexB,
+ collidableIndexA,
+ collidableIndexB,
+ &hostBodyBuf[0],
+ &hostCollidables[0],
+ &hostConvexData[0],
+ hostVertices,
+ hostAabbsWorldSpace,
+ hostAabbsLocalSpace,
+ &cpuChildShapes[0],
+ &cpuCompoundPairsOut[0],
+ &numCompoundPairs,
+ compoundPairCapacity,
+ treeNodesCPU,
+ subTreesCPU,
+ bvhInfoCPU);
}
- }
-
+ }
- m_numCompoundPairsOut.copyFromHostPointer(&numCompoundPairs,1,0,true);
+ m_numCompoundPairsOut.copyFromHostPointer(&numCompoundPairs, 1, 0, true);
if (numCompoundPairs)
{
b3CompoundOverlappingPair* ptr = (b3CompoundOverlappingPair*)&cpuCompoundPairsOut[0];
- m_gpuCompoundPairs.copyFromHostPointer(ptr,numCompoundPairs,0,true);
+ m_gpuCompoundPairs.copyFromHostPointer(ptr, numCompoundPairs, 0, true);
}
//cpuCompoundPairsOut
-
- }
+ }
if (numCompoundPairs)
{
- printf("numCompoundPairs=%d\n",numCompoundPairs);
+ printf("numCompoundPairs=%d\n", numCompoundPairs);
}
- if (numCompoundPairs > compoundPairCapacity)
- {
- b3Error("Exceeded compound pair capacity (%d/%d)\n", numCompoundPairs, compoundPairCapacity);
- numCompoundPairs = compoundPairCapacity;
- }
-
-
-
- m_gpuCompoundPairs.resize(numCompoundPairs);
- m_gpuHasCompoundSepNormals.resize(numCompoundPairs);
- m_gpuCompoundSepNormals.resize(numCompoundPairs);
-
-
- if (numCompoundPairs)
- {
- B3_PROFILE("processCompoundPairsPrimitivesKernel");
- b3BufferInfoCL bInfo[] =
- {
- b3BufferInfoCL( m_gpuCompoundPairs.getBufferCL(), true ),
- b3BufferInfoCL( bodyBuf->getBufferCL(),true),
- b3BufferInfoCL( gpuCollidables.getBufferCL(),true),
- b3BufferInfoCL( convexData.getBufferCL(),true),
- b3BufferInfoCL( gpuVertices.getBufferCL(),true),
- b3BufferInfoCL( gpuUniqueEdges.getBufferCL(),true),
- b3BufferInfoCL( gpuFaces.getBufferCL(),true),
- b3BufferInfoCL( gpuIndices.getBufferCL(),true),
- b3BufferInfoCL( clAabbsWorldSpace.getBufferCL(),true),
- b3BufferInfoCL( gpuChildShapes.getBufferCL(),true),
- b3BufferInfoCL( contactOut->getBufferCL()),
- b3BufferInfoCL( m_totalContactsOut.getBufferCL())
- };
-
- b3LauncherCL launcher(m_queue, m_processCompoundPairsPrimitivesKernel,"m_processCompoundPairsPrimitivesKernel");
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst( numCompoundPairs );
- launcher.setConst(maxContactCapacity);
-
- int num = numCompoundPairs;
- launcher.launch1D( num);
- clFinish(m_queue);
- nContacts = m_totalContactsOut.at(0);
- //printf("nContacts (after processCompoundPairsPrimitivesKernel) = %d\n",nContacts);
- if (nContacts>maxContactCapacity)
- {
-
- b3Error("Error: contacts exceeds capacity (%d/%d)\n", nContacts, maxContactCapacity);
- nContacts = maxContactCapacity;
- }
- }
-
-
- if (numCompoundPairs)
- {
- B3_PROFILE("processCompoundPairsKernel");
- b3BufferInfoCL bInfo[] =
- {
- b3BufferInfoCL( m_gpuCompoundPairs.getBufferCL(), true ),
- b3BufferInfoCL( bodyBuf->getBufferCL(),true),
- b3BufferInfoCL( gpuCollidables.getBufferCL(),true),
- b3BufferInfoCL( convexData.getBufferCL(),true),
- b3BufferInfoCL( gpuVertices.getBufferCL(),true),
- b3BufferInfoCL( gpuUniqueEdges.getBufferCL(),true),
- b3BufferInfoCL( gpuFaces.getBufferCL(),true),
- b3BufferInfoCL( gpuIndices.getBufferCL(),true),
- b3BufferInfoCL( clAabbsWorldSpace.getBufferCL(),true),
- b3BufferInfoCL( gpuChildShapes.getBufferCL(),true),
- b3BufferInfoCL( m_gpuCompoundSepNormals.getBufferCL()),
- b3BufferInfoCL( m_gpuHasCompoundSepNormals.getBufferCL())
- };
-
- b3LauncherCL launcher(m_queue, m_processCompoundPairsKernel,"m_processCompoundPairsKernel");
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst( numCompoundPairs );
-
- int num = numCompoundPairs;
- launcher.launch1D( num);
- clFinish(m_queue);
-
- }
-
-
- //printf("numConcave = %d\n",numConcave);
-
-
-
-// printf("hostNormals.size()=%d\n",hostNormals.size());
+ if (numCompoundPairs > compoundPairCapacity)
+ {
+ b3Error("Exceeded compound pair capacity (%d/%d)\n", numCompoundPairs, compoundPairCapacity);
+ numCompoundPairs = compoundPairCapacity;
+ }
+
+ m_gpuCompoundPairs.resize(numCompoundPairs);
+ m_gpuHasCompoundSepNormals.resize(numCompoundPairs);
+ m_gpuCompoundSepNormals.resize(numCompoundPairs);
+
+ if (numCompoundPairs)
+ {
+ B3_PROFILE("processCompoundPairsPrimitivesKernel");
+ b3BufferInfoCL bInfo[] =
+ {
+ b3BufferInfoCL(m_gpuCompoundPairs.getBufferCL(), true),
+ b3BufferInfoCL(bodyBuf->getBufferCL(), true),
+ b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
+ b3BufferInfoCL(convexData.getBufferCL(), true),
+ b3BufferInfoCL(gpuVertices.getBufferCL(), true),
+ b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
+ b3BufferInfoCL(gpuFaces.getBufferCL(), true),
+ b3BufferInfoCL(gpuIndices.getBufferCL(), true),
+ b3BufferInfoCL(clAabbsWorldSpace.getBufferCL(), true),
+ b3BufferInfoCL(gpuChildShapes.getBufferCL(), true),
+ b3BufferInfoCL(contactOut->getBufferCL()),
+ b3BufferInfoCL(m_totalContactsOut.getBufferCL())};
+
+ b3LauncherCL launcher(m_queue, m_processCompoundPairsPrimitivesKernel, "m_processCompoundPairsPrimitivesKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setConst(numCompoundPairs);
+ launcher.setConst(maxContactCapacity);
+
+ int num = numCompoundPairs;
+ launcher.launch1D(num);
+ clFinish(m_queue);
+ nContacts = m_totalContactsOut.at(0);
+ //printf("nContacts (after processCompoundPairsPrimitivesKernel) = %d\n",nContacts);
+ if (nContacts > maxContactCapacity)
+ {
+ b3Error("Error: contacts exceeds capacity (%d/%d)\n", nContacts, maxContactCapacity);
+ nContacts = maxContactCapacity;
+ }
+ }
+
+ if (numCompoundPairs)
+ {
+ B3_PROFILE("processCompoundPairsKernel");
+ b3BufferInfoCL bInfo[] =
+ {
+ b3BufferInfoCL(m_gpuCompoundPairs.getBufferCL(), true),
+ b3BufferInfoCL(bodyBuf->getBufferCL(), true),
+ b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
+ b3BufferInfoCL(convexData.getBufferCL(), true),
+ b3BufferInfoCL(gpuVertices.getBufferCL(), true),
+ b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
+ b3BufferInfoCL(gpuFaces.getBufferCL(), true),
+ b3BufferInfoCL(gpuIndices.getBufferCL(), true),
+ b3BufferInfoCL(clAabbsWorldSpace.getBufferCL(), true),
+ b3BufferInfoCL(gpuChildShapes.getBufferCL(), true),
+ b3BufferInfoCL(m_gpuCompoundSepNormals.getBufferCL()),
+ b3BufferInfoCL(m_gpuHasCompoundSepNormals.getBufferCL())};
+
+ b3LauncherCL launcher(m_queue, m_processCompoundPairsKernel, "m_processCompoundPairsKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setConst(numCompoundPairs);
+
+ int num = numCompoundPairs;
+ launcher.launch1D(num);
+ clFinish(m_queue);
+ }
+
+ //printf("numConcave = %d\n",numConcave);
+
+ // printf("hostNormals.size()=%d\n",hostNormals.size());
//int numPairs = pairCount.at(0);
-
-
-
}
int vertexFaceCapacity = 64;
-
-
{
//now perform the tree query on GPU
-
-
-
-
+
if (treeNodesGPU->size() && treeNodesGPU->size())
{
if (bvhTraversalKernelGPU)
{
-
B3_PROFILE("m_bvhTraversalKernel");
-
-
+
numConcavePairs = m_numConcavePairsOut.at(0);
-
- b3LauncherCL launcher(m_queue, m_bvhTraversalKernel,"m_bvhTraversalKernel");
- launcher.setBuffer( pairs->getBufferCL());
- launcher.setBuffer( bodyBuf->getBufferCL());
- launcher.setBuffer( gpuCollidables.getBufferCL());
- launcher.setBuffer( clAabbsWorldSpace.getBufferCL());
- launcher.setBuffer( triangleConvexPairsOut.getBufferCL());
- launcher.setBuffer( m_numConcavePairsOut.getBufferCL());
- launcher.setBuffer( subTreesGPU->getBufferCL());
- launcher.setBuffer( treeNodesGPU->getBufferCL());
- launcher.setBuffer( bvhInfo->getBufferCL());
-
- launcher.setConst( nPairs );
- launcher.setConst( maxTriConvexPairCapacity);
+
+ b3LauncherCL launcher(m_queue, m_bvhTraversalKernel, "m_bvhTraversalKernel");
+ launcher.setBuffer(pairs->getBufferCL());
+ launcher.setBuffer(bodyBuf->getBufferCL());
+ launcher.setBuffer(gpuCollidables.getBufferCL());
+ launcher.setBuffer(clAabbsWorldSpace.getBufferCL());
+ launcher.setBuffer(triangleConvexPairsOut.getBufferCL());
+ launcher.setBuffer(m_numConcavePairsOut.getBufferCL());
+ launcher.setBuffer(subTreesGPU->getBufferCL());
+ launcher.setBuffer(treeNodesGPU->getBufferCL());
+ launcher.setBuffer(bvhInfo->getBufferCL());
+
+ launcher.setConst(nPairs);
+ launcher.setConst(maxTriConvexPairCapacity);
int num = nPairs;
- launcher.launch1D( num);
+ launcher.launch1D(num);
clFinish(m_queue);
numConcavePairs = m_numConcavePairsOut.at(0);
- } else
+ }
+ else
{
- b3AlignedObjectArray<b3Int4> hostPairs;
- pairs->copyToHost(hostPairs);
- b3AlignedObjectArray<b3RigidBodyData> hostBodyBuf;
- bodyBuf->copyToHost(hostBodyBuf);
- b3AlignedObjectArray<b3Collidable> hostCollidables;
- gpuCollidables.copyToHost(hostCollidables);
- b3AlignedObjectArray<b3Aabb> hostAabbsWorldSpace;
- clAabbsWorldSpace.copyToHost(hostAabbsWorldSpace);
+ b3AlignedObjectArray<b3Int4> hostPairs;
+ pairs->copyToHost(hostPairs);
+ b3AlignedObjectArray<b3RigidBodyData> hostBodyBuf;
+ bodyBuf->copyToHost(hostBodyBuf);
+ b3AlignedObjectArray<b3Collidable> hostCollidables;
+ gpuCollidables.copyToHost(hostCollidables);
+ b3AlignedObjectArray<b3Aabb> hostAabbsWorldSpace;
+ clAabbsWorldSpace.copyToHost(hostAabbsWorldSpace);
- //int maxTriConvexPairCapacity,
- b3AlignedObjectArray<b3Int4> triangleConvexPairsOutHost;
- triangleConvexPairsOutHost.resize(maxTriConvexPairCapacity);
+ //int maxTriConvexPairCapacity,
+ b3AlignedObjectArray<b3Int4> triangleConvexPairsOutHost;
+ triangleConvexPairsOutHost.resize(maxTriConvexPairCapacity);
- //int numTriConvexPairsOutHost=0;
- numConcavePairs = 0;
- //m_numConcavePairsOut
+ //int numTriConvexPairsOutHost=0;
+ numConcavePairs = 0;
+ //m_numConcavePairsOut
- b3AlignedObjectArray<b3QuantizedBvhNode> treeNodesCPU;
- treeNodesGPU->copyToHost(treeNodesCPU);
- b3AlignedObjectArray<b3BvhSubtreeInfo> subTreesCPU;
- subTreesGPU->copyToHost(subTreesCPU);
- b3AlignedObjectArray<b3BvhInfo> bvhInfoCPU;
- bvhInfo->copyToHost(bvhInfoCPU);
- //compute it...
+ b3AlignedObjectArray<b3QuantizedBvhNode> treeNodesCPU;
+ treeNodesGPU->copyToHost(treeNodesCPU);
+ b3AlignedObjectArray<b3BvhSubtreeInfo> subTreesCPU;
+ subTreesGPU->copyToHost(subTreesCPU);
+ b3AlignedObjectArray<b3BvhInfo> bvhInfoCPU;
+ bvhInfo->copyToHost(bvhInfoCPU);
+ //compute it...
- volatile int hostNumConcavePairsOut=0;
+ volatile int hostNumConcavePairsOut = 0;
- //
- for (int i=0;i<nPairs;i++)
- {
- b3BvhTraversal( &hostPairs.at(0),
- &hostBodyBuf.at(0),
- &hostCollidables.at(0),
- &hostAabbsWorldSpace.at(0),
- &triangleConvexPairsOutHost.at(0),
- &hostNumConcavePairsOut,
- &subTreesCPU.at(0),
- &treeNodesCPU.at(0),
- &bvhInfoCPU.at(0),
- nPairs,
- maxTriConvexPairCapacity,
- i);
- }
- numConcavePairs = hostNumConcavePairsOut;
+ //
+ for (int i = 0; i < nPairs; i++)
+ {
+ b3BvhTraversal(&hostPairs.at(0),
+ &hostBodyBuf.at(0),
+ &hostCollidables.at(0),
+ &hostAabbsWorldSpace.at(0),
+ &triangleConvexPairsOutHost.at(0),
+ &hostNumConcavePairsOut,
+ &subTreesCPU.at(0),
+ &treeNodesCPU.at(0),
+ &bvhInfoCPU.at(0),
+ nPairs,
+ maxTriConvexPairCapacity,
+ i);
+ }
+ numConcavePairs = hostNumConcavePairsOut;
- if (hostNumConcavePairsOut)
- {
- triangleConvexPairsOutHost.resize(hostNumConcavePairsOut);
- triangleConvexPairsOut.copyFromHost(triangleConvexPairsOutHost);
- }
- //
+ if (hostNumConcavePairsOut)
+ {
+ triangleConvexPairsOutHost.resize(hostNumConcavePairsOut);
+ triangleConvexPairsOut.copyFromHost(triangleConvexPairsOutHost);
+ }
+ //
- m_numConcavePairsOut.resize(0);
- m_numConcavePairsOut.push_back(numConcavePairs);
+ m_numConcavePairsOut.resize(0);
+ m_numConcavePairsOut.push_back(numConcavePairs);
}
- //printf("numConcavePairs=%d (max = %d\n",numConcavePairs,maxTriConvexPairCapacity);
-
+ //printf("numConcavePairs=%d (max = %d\n",numConcavePairs,maxTriConvexPairCapacity);
+
if (numConcavePairs > maxTriConvexPairCapacity)
{
static int exceeded_maxTriConvexPairCapacity_count = 0;
b3Error("Exceeded the maxTriConvexPairCapacity (found %d but max is %d, it happened %d times)\n",
- numConcavePairs,maxTriConvexPairCapacity,exceeded_maxTriConvexPairCapacity_count++);
+ numConcavePairs, maxTriConvexPairCapacity, exceeded_maxTriConvexPairCapacity_count++);
numConcavePairs = maxTriConvexPairCapacity;
}
triangleConvexPairsOut.resize(numConcavePairs);
-
+
if (numConcavePairs)
{
-
-
-
-
clippingFacesOutGPU.resize(numConcavePairs);
worldNormalsAGPU.resize(numConcavePairs);
- worldVertsA1GPU.resize(vertexFaceCapacity*(numConcavePairs));
- worldVertsB1GPU.resize(vertexFaceCapacity*(numConcavePairs));
-
+ worldVertsA1GPU.resize(vertexFaceCapacity * (numConcavePairs));
+ worldVertsB1GPU.resize(vertexFaceCapacity * (numConcavePairs));
if (findConcaveSeparatingAxisKernelGPU)
{
-
/*
m_concaveHasSeparatingNormals.copyFromHost(concaveHasSeparatingNormalsCPU);
clippingFacesOutGPU.copyFromHost(clippingFacesOutCPU);
@@ -3846,236 +3597,213 @@ void GpuSatCollision::computeConvexConvexContactsGPUSAT( b3OpenCLArray<b3Int4>*
*/
//now perform a SAT test for each triangle-convex element (stored in triangleConvexPairsOut)
- if (splitSearchSepAxisConcave)
- {
- //printf("numConcavePairs = %d\n",numConcavePairs);
- m_dmins.resize(numConcavePairs);
- {
- B3_PROFILE("findConcaveSeparatingAxisVertexFaceKernel");
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL( triangleConvexPairsOut.getBufferCL() ),
- b3BufferInfoCL( bodyBuf->getBufferCL(),true),
- b3BufferInfoCL( gpuCollidables.getBufferCL(),true),
- b3BufferInfoCL( convexData.getBufferCL(),true),
- b3BufferInfoCL( gpuVertices.getBufferCL(),true),
- b3BufferInfoCL( gpuUniqueEdges.getBufferCL(),true),
- b3BufferInfoCL( gpuFaces.getBufferCL(),true),
- b3BufferInfoCL( gpuIndices.getBufferCL(),true),
- b3BufferInfoCL( gpuChildShapes.getBufferCL(),true),
- b3BufferInfoCL( clAabbsWorldSpace.getBufferCL(),true),
- b3BufferInfoCL( m_concaveSepNormals.getBufferCL()),
- b3BufferInfoCL( m_concaveHasSeparatingNormals.getBufferCL()),
- b3BufferInfoCL( clippingFacesOutGPU.getBufferCL()),
- b3BufferInfoCL( worldVertsA1GPU.getBufferCL()),
- b3BufferInfoCL(worldNormalsAGPU.getBufferCL()),
- b3BufferInfoCL(worldVertsB1GPU.getBufferCL()),
- b3BufferInfoCL(m_dmins.getBufferCL())
- };
-
- b3LauncherCL launcher(m_queue, m_findConcaveSeparatingAxisVertexFaceKernel,"m_findConcaveSeparatingAxisVertexFaceKernel");
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst(vertexFaceCapacity);
- launcher.setConst( numConcavePairs );
-
- int num = numConcavePairs;
- launcher.launch1D( num);
- clFinish(m_queue);
-
-
- }
-// numConcavePairs = 0;
- if (1)
- {
- B3_PROFILE("findConcaveSeparatingAxisEdgeEdgeKernel");
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL( triangleConvexPairsOut.getBufferCL() ),
- b3BufferInfoCL( bodyBuf->getBufferCL(),true),
- b3BufferInfoCL( gpuCollidables.getBufferCL(),true),
- b3BufferInfoCL( convexData.getBufferCL(),true),
- b3BufferInfoCL( gpuVertices.getBufferCL(),true),
- b3BufferInfoCL( gpuUniqueEdges.getBufferCL(),true),
- b3BufferInfoCL( gpuFaces.getBufferCL(),true),
- b3BufferInfoCL( gpuIndices.getBufferCL(),true),
- b3BufferInfoCL( gpuChildShapes.getBufferCL(),true),
- b3BufferInfoCL( clAabbsWorldSpace.getBufferCL(),true),
- b3BufferInfoCL( m_concaveSepNormals.getBufferCL()),
- b3BufferInfoCL( m_concaveHasSeparatingNormals.getBufferCL()),
- b3BufferInfoCL( clippingFacesOutGPU.getBufferCL()),
- b3BufferInfoCL( worldVertsA1GPU.getBufferCL()),
- b3BufferInfoCL(worldNormalsAGPU.getBufferCL()),
- b3BufferInfoCL(worldVertsB1GPU.getBufferCL()),
- b3BufferInfoCL(m_dmins.getBufferCL())
- };
-
- b3LauncherCL launcher(m_queue, m_findConcaveSeparatingAxisEdgeEdgeKernel,"m_findConcaveSeparatingAxisEdgeEdgeKernel");
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst(vertexFaceCapacity);
- launcher.setConst( numConcavePairs );
-
- int num = numConcavePairs;
- launcher.launch1D( num);
- clFinish(m_queue);
- }
-
-
- // numConcavePairs = 0;
-
-
-
-
-
-
- } else
- {
- B3_PROFILE("findConcaveSeparatingAxisKernel");
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL( triangleConvexPairsOut.getBufferCL() ),
- b3BufferInfoCL( bodyBuf->getBufferCL(),true),
- b3BufferInfoCL( gpuCollidables.getBufferCL(),true),
- b3BufferInfoCL( convexData.getBufferCL(),true),
- b3BufferInfoCL( gpuVertices.getBufferCL(),true),
- b3BufferInfoCL( gpuUniqueEdges.getBufferCL(),true),
- b3BufferInfoCL( gpuFaces.getBufferCL(),true),
- b3BufferInfoCL( gpuIndices.getBufferCL(),true),
- b3BufferInfoCL( gpuChildShapes.getBufferCL(),true),
- b3BufferInfoCL( clAabbsWorldSpace.getBufferCL(),true),
- b3BufferInfoCL( m_concaveSepNormals.getBufferCL()),
- b3BufferInfoCL( m_concaveHasSeparatingNormals.getBufferCL()),
- b3BufferInfoCL( clippingFacesOutGPU.getBufferCL()),
- b3BufferInfoCL( worldVertsA1GPU.getBufferCL()),
- b3BufferInfoCL(worldNormalsAGPU.getBufferCL()),
- b3BufferInfoCL(worldVertsB1GPU.getBufferCL())
- };
-
- b3LauncherCL launcher(m_queue, m_findConcaveSeparatingAxisKernel,"m_findConcaveSeparatingAxisKernel");
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst(vertexFaceCapacity);
- launcher.setConst( numConcavePairs );
-
- int num = numConcavePairs;
- launcher.launch1D( num);
- clFinish(m_queue);
- }
-
-
- } else
- {
-
- b3AlignedObjectArray<b3Int4> clippingFacesOutCPU;
- b3AlignedObjectArray<b3Vector3> worldVertsA1CPU;
- b3AlignedObjectArray<b3Vector3> worldNormalsACPU;
- b3AlignedObjectArray<b3Vector3> worldVertsB1CPU;
- b3AlignedObjectArray<int>concaveHasSeparatingNormalsCPU;
+ if (splitSearchSepAxisConcave)
+ {
+ //printf("numConcavePairs = %d\n",numConcavePairs);
+ m_dmins.resize(numConcavePairs);
+ {
+ B3_PROFILE("findConcaveSeparatingAxisVertexFaceKernel");
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL(triangleConvexPairsOut.getBufferCL()),
+ b3BufferInfoCL(bodyBuf->getBufferCL(), true),
+ b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
+ b3BufferInfoCL(convexData.getBufferCL(), true),
+ b3BufferInfoCL(gpuVertices.getBufferCL(), true),
+ b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
+ b3BufferInfoCL(gpuFaces.getBufferCL(), true),
+ b3BufferInfoCL(gpuIndices.getBufferCL(), true),
+ b3BufferInfoCL(gpuChildShapes.getBufferCL(), true),
+ b3BufferInfoCL(clAabbsWorldSpace.getBufferCL(), true),
+ b3BufferInfoCL(m_concaveSepNormals.getBufferCL()),
+ b3BufferInfoCL(m_concaveHasSeparatingNormals.getBufferCL()),
+ b3BufferInfoCL(clippingFacesOutGPU.getBufferCL()),
+ b3BufferInfoCL(worldVertsA1GPU.getBufferCL()),
+ b3BufferInfoCL(worldNormalsAGPU.getBufferCL()),
+ b3BufferInfoCL(worldVertsB1GPU.getBufferCL()),
+ b3BufferInfoCL(m_dmins.getBufferCL())};
+
+ b3LauncherCL launcher(m_queue, m_findConcaveSeparatingAxisVertexFaceKernel, "m_findConcaveSeparatingAxisVertexFaceKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setConst(vertexFaceCapacity);
+ launcher.setConst(numConcavePairs);
- b3AlignedObjectArray<b3Int4> triangleConvexPairsOutHost;
- triangleConvexPairsOut.copyToHost(triangleConvexPairsOutHost);
- //triangleConvexPairsOutHost.resize(maxTriConvexPairCapacity);
- b3AlignedObjectArray<b3RigidBodyData> hostBodyBuf;
- bodyBuf->copyToHost(hostBodyBuf);
- b3AlignedObjectArray<b3Collidable> hostCollidables;
- gpuCollidables.copyToHost(hostCollidables);
- b3AlignedObjectArray<b3Aabb> hostAabbsWorldSpace;
- clAabbsWorldSpace.copyToHost(hostAabbsWorldSpace);
+ int num = numConcavePairs;
+ launcher.launch1D(num);
+ clFinish(m_queue);
+ }
+ // numConcavePairs = 0;
+ if (1)
+ {
+ B3_PROFILE("findConcaveSeparatingAxisEdgeEdgeKernel");
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL(triangleConvexPairsOut.getBufferCL()),
+ b3BufferInfoCL(bodyBuf->getBufferCL(), true),
+ b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
+ b3BufferInfoCL(convexData.getBufferCL(), true),
+ b3BufferInfoCL(gpuVertices.getBufferCL(), true),
+ b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
+ b3BufferInfoCL(gpuFaces.getBufferCL(), true),
+ b3BufferInfoCL(gpuIndices.getBufferCL(), true),
+ b3BufferInfoCL(gpuChildShapes.getBufferCL(), true),
+ b3BufferInfoCL(clAabbsWorldSpace.getBufferCL(), true),
+ b3BufferInfoCL(m_concaveSepNormals.getBufferCL()),
+ b3BufferInfoCL(m_concaveHasSeparatingNormals.getBufferCL()),
+ b3BufferInfoCL(clippingFacesOutGPU.getBufferCL()),
+ b3BufferInfoCL(worldVertsA1GPU.getBufferCL()),
+ b3BufferInfoCL(worldNormalsAGPU.getBufferCL()),
+ b3BufferInfoCL(worldVertsB1GPU.getBufferCL()),
+ b3BufferInfoCL(m_dmins.getBufferCL())};
+
+ b3LauncherCL launcher(m_queue, m_findConcaveSeparatingAxisEdgeEdgeKernel, "m_findConcaveSeparatingAxisEdgeEdgeKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setConst(vertexFaceCapacity);
+ launcher.setConst(numConcavePairs);
- b3AlignedObjectArray<b3ConvexPolyhedronData> hostConvexData;
- convexData.copyToHost(hostConvexData);
+ int num = numConcavePairs;
+ launcher.launch1D(num);
+ clFinish(m_queue);
+ }
- b3AlignedObjectArray<b3Vector3> hostVertices;
- gpuVertices.copyToHost(hostVertices);
+ // numConcavePairs = 0;
+ }
+ else
+ {
+ B3_PROFILE("findConcaveSeparatingAxisKernel");
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL(triangleConvexPairsOut.getBufferCL()),
+ b3BufferInfoCL(bodyBuf->getBufferCL(), true),
+ b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
+ b3BufferInfoCL(convexData.getBufferCL(), true),
+ b3BufferInfoCL(gpuVertices.getBufferCL(), true),
+ b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
+ b3BufferInfoCL(gpuFaces.getBufferCL(), true),
+ b3BufferInfoCL(gpuIndices.getBufferCL(), true),
+ b3BufferInfoCL(gpuChildShapes.getBufferCL(), true),
+ b3BufferInfoCL(clAabbsWorldSpace.getBufferCL(), true),
+ b3BufferInfoCL(m_concaveSepNormals.getBufferCL()),
+ b3BufferInfoCL(m_concaveHasSeparatingNormals.getBufferCL()),
+ b3BufferInfoCL(clippingFacesOutGPU.getBufferCL()),
+ b3BufferInfoCL(worldVertsA1GPU.getBufferCL()),
+ b3BufferInfoCL(worldNormalsAGPU.getBufferCL()),
+ b3BufferInfoCL(worldVertsB1GPU.getBufferCL())};
+
+ b3LauncherCL launcher(m_queue, m_findConcaveSeparatingAxisKernel, "m_findConcaveSeparatingAxisKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setConst(vertexFaceCapacity);
+ launcher.setConst(numConcavePairs);
- b3AlignedObjectArray<b3Vector3> hostUniqueEdges;
- gpuUniqueEdges.copyToHost(hostUniqueEdges);
- b3AlignedObjectArray<b3GpuFace> hostFaces;
- gpuFaces.copyToHost(hostFaces);
- b3AlignedObjectArray<int> hostIndices;
- gpuIndices.copyToHost(hostIndices);
- b3AlignedObjectArray<b3GpuChildShape> cpuChildShapes;
- gpuChildShapes.copyToHost(cpuChildShapes);
+ int num = numConcavePairs;
+ launcher.launch1D(num);
+ clFinish(m_queue);
+ }
+ }
+ else
+ {
+ b3AlignedObjectArray<b3Int4> clippingFacesOutCPU;
+ b3AlignedObjectArray<b3Vector3> worldVertsA1CPU;
+ b3AlignedObjectArray<b3Vector3> worldNormalsACPU;
+ b3AlignedObjectArray<b3Vector3> worldVertsB1CPU;
+ b3AlignedObjectArray<int> concaveHasSeparatingNormalsCPU;
+ b3AlignedObjectArray<b3Int4> triangleConvexPairsOutHost;
+ triangleConvexPairsOut.copyToHost(triangleConvexPairsOutHost);
+ //triangleConvexPairsOutHost.resize(maxTriConvexPairCapacity);
+ b3AlignedObjectArray<b3RigidBodyData> hostBodyBuf;
+ bodyBuf->copyToHost(hostBodyBuf);
+ b3AlignedObjectArray<b3Collidable> hostCollidables;
+ gpuCollidables.copyToHost(hostCollidables);
+ b3AlignedObjectArray<b3Aabb> hostAabbsWorldSpace;
+ clAabbsWorldSpace.copyToHost(hostAabbsWorldSpace);
-
- b3AlignedObjectArray<b3Vector3> concaveSepNormalsHost;
- m_concaveSepNormals.copyToHost(concaveSepNormalsHost);
- concaveHasSeparatingNormalsCPU.resize(concaveSepNormalsHost.size());
+ b3AlignedObjectArray<b3ConvexPolyhedronData> hostConvexData;
+ convexData.copyToHost(hostConvexData);
- b3GpuChildShape* childShapePointerCPU = 0;
- if (cpuChildShapes.size())
- childShapePointerCPU = &cpuChildShapes.at(0);
+ b3AlignedObjectArray<b3Vector3> hostVertices;
+ gpuVertices.copyToHost(hostVertices);
- clippingFacesOutCPU.resize(clippingFacesOutGPU.size());
- worldVertsA1CPU.resize(worldVertsA1GPU.size());
- worldNormalsACPU.resize(worldNormalsAGPU.size());
- worldVertsB1CPU.resize(worldVertsB1GPU.size());
+ b3AlignedObjectArray<b3Vector3> hostUniqueEdges;
+ gpuUniqueEdges.copyToHost(hostUniqueEdges);
+ b3AlignedObjectArray<b3GpuFace> hostFaces;
+ gpuFaces.copyToHost(hostFaces);
+ b3AlignedObjectArray<int> hostIndices;
+ gpuIndices.copyToHost(hostIndices);
+ b3AlignedObjectArray<b3GpuChildShape> cpuChildShapes;
+ gpuChildShapes.copyToHost(cpuChildShapes);
- for (int i=0;i<numConcavePairs;i++)
- {
- b3FindConcaveSeparatingAxisKernel(&triangleConvexPairsOutHost.at(0),
- &hostBodyBuf.at(0),
- &hostCollidables.at(0),
- &hostConvexData.at(0), &hostVertices.at(0),&hostUniqueEdges.at(0),
- &hostFaces.at(0),&hostIndices.at(0),childShapePointerCPU,
- &hostAabbsWorldSpace.at(0),
- &concaveSepNormalsHost.at(0),
- &clippingFacesOutCPU.at(0),
- &worldVertsA1CPU.at(0),
- &worldNormalsACPU.at(0),
- &worldVertsB1CPU.at(0),
- &concaveHasSeparatingNormalsCPU.at(0),
- vertexFaceCapacity,
- numConcavePairs,i);
- };
+ b3AlignedObjectArray<b3Vector3> concaveSepNormalsHost;
+ m_concaveSepNormals.copyToHost(concaveSepNormalsHost);
+ concaveHasSeparatingNormalsCPU.resize(concaveSepNormalsHost.size());
- m_concaveSepNormals.copyFromHost(concaveSepNormalsHost);
- m_concaveHasSeparatingNormals.copyFromHost(concaveHasSeparatingNormalsCPU);
- clippingFacesOutGPU.copyFromHost(clippingFacesOutCPU);
- worldVertsA1GPU.copyFromHost(worldVertsA1CPU);
- worldNormalsAGPU.copyFromHost(worldNormalsACPU);
- worldVertsB1GPU.copyFromHost(worldVertsB1CPU);
+ b3GpuChildShape* childShapePointerCPU = 0;
+ if (cpuChildShapes.size())
+ childShapePointerCPU = &cpuChildShapes.at(0);
+ clippingFacesOutCPU.resize(clippingFacesOutGPU.size());
+ worldVertsA1CPU.resize(worldVertsA1GPU.size());
+ worldNormalsACPU.resize(worldNormalsAGPU.size());
+ worldVertsB1CPU.resize(worldVertsB1GPU.size());
+ for (int i = 0; i < numConcavePairs; i++)
+ {
+ b3FindConcaveSeparatingAxisKernel(&triangleConvexPairsOutHost.at(0),
+ &hostBodyBuf.at(0),
+ &hostCollidables.at(0),
+ &hostConvexData.at(0), &hostVertices.at(0), &hostUniqueEdges.at(0),
+ &hostFaces.at(0), &hostIndices.at(0), childShapePointerCPU,
+ &hostAabbsWorldSpace.at(0),
+ &concaveSepNormalsHost.at(0),
+ &clippingFacesOutCPU.at(0),
+ &worldVertsA1CPU.at(0),
+ &worldNormalsACPU.at(0),
+ &worldVertsB1CPU.at(0),
+ &concaveHasSeparatingNormalsCPU.at(0),
+ vertexFaceCapacity,
+ numConcavePairs, i);
+ };
+ m_concaveSepNormals.copyFromHost(concaveSepNormalsHost);
+ m_concaveHasSeparatingNormals.copyFromHost(concaveHasSeparatingNormalsCPU);
+ clippingFacesOutGPU.copyFromHost(clippingFacesOutCPU);
+ worldVertsA1GPU.copyFromHost(worldVertsA1CPU);
+ worldNormalsAGPU.copyFromHost(worldNormalsACPU);
+ worldVertsB1GPU.copyFromHost(worldVertsB1CPU);
}
-// b3AlignedObjectArray<b3Vector3> cpuCompoundSepNormals;
-// m_concaveSepNormals.copyToHost(cpuCompoundSepNormals);
-// b3AlignedObjectArray<b3Int4> cpuConcavePairs;
-// triangleConvexPairsOut.copyToHost(cpuConcavePairs);
-
-
+ // b3AlignedObjectArray<b3Vector3> cpuCompoundSepNormals;
+ // m_concaveSepNormals.copyToHost(cpuCompoundSepNormals);
+ // b3AlignedObjectArray<b3Int4> cpuConcavePairs;
+ // triangleConvexPairsOut.copyToHost(cpuConcavePairs);
}
}
-
-
}
if (numConcavePairs)
{
- if (numConcavePairs)
+ if (numConcavePairs)
{
B3_PROFILE("findConcaveSphereContactsKernel");
- nContacts = m_totalContactsOut.at(0);
-// printf("nContacts1 = %d\n",nContacts);
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL( triangleConvexPairsOut.getBufferCL() ),
- b3BufferInfoCL( bodyBuf->getBufferCL(),true),
- b3BufferInfoCL( gpuCollidables.getBufferCL(),true),
- b3BufferInfoCL( convexData.getBufferCL(),true),
- b3BufferInfoCL( gpuVertices.getBufferCL(),true),
- b3BufferInfoCL( gpuUniqueEdges.getBufferCL(),true),
- b3BufferInfoCL( gpuFaces.getBufferCL(),true),
- b3BufferInfoCL( gpuIndices.getBufferCL(),true),
- b3BufferInfoCL( clAabbsWorldSpace.getBufferCL(),true),
- b3BufferInfoCL( contactOut->getBufferCL()),
- b3BufferInfoCL( m_totalContactsOut.getBufferCL())
- };
-
- b3LauncherCL launcher(m_queue, m_findConcaveSphereContactsKernel,"m_findConcaveSphereContactsKernel");
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
-
- launcher.setConst( numConcavePairs );
+ nContacts = m_totalContactsOut.at(0);
+ // printf("nContacts1 = %d\n",nContacts);
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL(triangleConvexPairsOut.getBufferCL()),
+ b3BufferInfoCL(bodyBuf->getBufferCL(), true),
+ b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
+ b3BufferInfoCL(convexData.getBufferCL(), true),
+ b3BufferInfoCL(gpuVertices.getBufferCL(), true),
+ b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
+ b3BufferInfoCL(gpuFaces.getBufferCL(), true),
+ b3BufferInfoCL(gpuIndices.getBufferCL(), true),
+ b3BufferInfoCL(clAabbsWorldSpace.getBufferCL(), true),
+ b3BufferInfoCL(contactOut->getBufferCL()),
+ b3BufferInfoCL(m_totalContactsOut.getBufferCL())};
+
+ b3LauncherCL launcher(m_queue, m_findConcaveSphereContactsKernel, "m_findConcaveSphereContactsKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+
+ launcher.setConst(numConcavePairs);
launcher.setConst(maxContactCapacity);
int num = numConcavePairs;
- launcher.launch1D( num);
+ launcher.launch1D(num);
clFinish(m_queue);
nContacts = m_totalContactsOut.at(0);
//printf("nContacts (after findConcaveSphereContactsKernel) = %d\n",nContacts);
@@ -4088,11 +3816,8 @@ void GpuSatCollision::computeConvexConvexContactsGPUSAT( b3OpenCLArray<b3Int4>*
nContacts = maxContactCapacity;
}
}
-
}
-
-
#ifdef __APPLE__
bool contactClippingOnGpu = true;
#else
@@ -4101,9 +3826,8 @@ void GpuSatCollision::computeConvexConvexContactsGPUSAT( b3OpenCLArray<b3Int4>*
if (contactClippingOnGpu)
{
- m_totalContactsOut.copyFromHostPointer(&nContacts,1,0,true);
-// printf("nContacts3 = %d\n",nContacts);
-
+ m_totalContactsOut.copyFromHostPointer(&nContacts, 1, 0, true);
+ // printf("nContacts3 = %d\n",nContacts);
//B3_PROFILE("clipHullHullKernel");
@@ -4122,15 +3846,12 @@ void GpuSatCollision::computeConvexConvexContactsGPUSAT( b3OpenCLArray<b3Int4>*
if (breakupConcaveConvexKernel)
{
-
- worldVertsB2GPU.resize(vertexFaceCapacity*numConcavePairs);
-
+ worldVertsB2GPU.resize(vertexFaceCapacity * numConcavePairs);
//clipFacesAndFindContacts
if (clipConcaveFacesAndFindContactsCPU)
{
-
b3AlignedObjectArray<b3Int4> clippingFacesOutCPU;
b3AlignedObjectArray<b3Vector3> worldVertsA1CPU;
b3AlignedObjectArray<b3Vector3> worldNormalsACPU;
@@ -4141,120 +3862,108 @@ void GpuSatCollision::computeConvexConvexContactsGPUSAT( b3OpenCLArray<b3Int4>*
worldNormalsAGPU.copyToHost(worldNormalsACPU);
worldVertsB1GPU.copyToHost(worldVertsB1CPU);
-
-
- b3AlignedObjectArray<int>concaveHasSeparatingNormalsCPU;
+ b3AlignedObjectArray<int> concaveHasSeparatingNormalsCPU;
m_concaveHasSeparatingNormals.copyToHost(concaveHasSeparatingNormalsCPU);
b3AlignedObjectArray<b3Vector3> concaveSepNormalsHost;
m_concaveSepNormals.copyToHost(concaveSepNormalsHost);
- b3AlignedObjectArray<b3Vector3> worldVertsB2CPU;
+ b3AlignedObjectArray<b3Vector3> worldVertsB2CPU;
worldVertsB2CPU.resize(worldVertsB2GPU.size());
-
- for (int i=0;i<numConcavePairs;i++)
+ for (int i = 0; i < numConcavePairs; i++)
{
-
- clipFacesAndFindContactsKernel( &concaveSepNormalsHost.at(0),
- &concaveHasSeparatingNormalsCPU.at(0),
- &clippingFacesOutCPU.at(0),
- &worldVertsA1CPU.at(0),
- &worldNormalsACPU.at(0),
- &worldVertsB1CPU.at(0),
- &worldVertsB2CPU.at(0),
- vertexFaceCapacity,
- i);
+ clipFacesAndFindContactsKernel(&concaveSepNormalsHost.at(0),
+ &concaveHasSeparatingNormalsCPU.at(0),
+ &clippingFacesOutCPU.at(0),
+ &worldVertsA1CPU.at(0),
+ &worldNormalsACPU.at(0),
+ &worldVertsB1CPU.at(0),
+ &worldVertsB2CPU.at(0),
+ vertexFaceCapacity,
+ i);
}
clippingFacesOutGPU.copyFromHost(clippingFacesOutCPU);
worldVertsB2GPU.copyFromHost(worldVertsB2CPU);
-
-
- } else
+ }
+ else
{
-
if (1)
{
-
-
-
B3_PROFILE("clipFacesAndFindContacts");
//nContacts = m_totalContactsOut.at(0);
//int h = m_hasSeparatingNormals.at(0);
//int4 p = clippingFacesOutGPU.at(0);
b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL( m_concaveSepNormals.getBufferCL()),
- b3BufferInfoCL( m_concaveHasSeparatingNormals.getBufferCL()),
- b3BufferInfoCL( clippingFacesOutGPU.getBufferCL()),
- b3BufferInfoCL( worldVertsA1GPU.getBufferCL()),
- b3BufferInfoCL( worldNormalsAGPU.getBufferCL()),
- b3BufferInfoCL( worldVertsB1GPU.getBufferCL()),
- b3BufferInfoCL( worldVertsB2GPU.getBufferCL())
- };
- b3LauncherCL launcher(m_queue, m_clipFacesAndFindContacts,"m_clipFacesAndFindContacts");
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ b3BufferInfoCL(m_concaveSepNormals.getBufferCL()),
+ b3BufferInfoCL(m_concaveHasSeparatingNormals.getBufferCL()),
+ b3BufferInfoCL(clippingFacesOutGPU.getBufferCL()),
+ b3BufferInfoCL(worldVertsA1GPU.getBufferCL()),
+ b3BufferInfoCL(worldNormalsAGPU.getBufferCL()),
+ b3BufferInfoCL(worldVertsB1GPU.getBufferCL()),
+ b3BufferInfoCL(worldVertsB2GPU.getBufferCL())};
+ b3LauncherCL launcher(m_queue, m_clipFacesAndFindContacts, "m_clipFacesAndFindContacts");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
launcher.setConst(vertexFaceCapacity);
- launcher.setConst( numConcavePairs );
+ launcher.setConst(numConcavePairs);
int debugMode = 0;
- launcher.setConst( debugMode);
+ launcher.setConst(debugMode);
int num = numConcavePairs;
- launcher.launch1D( num);
+ launcher.launch1D(num);
clFinish(m_queue);
//int bla = m_totalContactsOut.at(0);
}
}
//contactReduction
{
- int newContactCapacity=nContacts+numConcavePairs;
+ int newContactCapacity = nContacts + numConcavePairs;
contactOut->reserve(newContactCapacity);
if (reduceConcaveContactsOnGPU)
{
-// printf("newReservation = %d\n",newReservation);
+ // printf("newReservation = %d\n",newReservation);
{
B3_PROFILE("newContactReductionKernel");
b3BufferInfoCL bInfo[] =
- {
- b3BufferInfoCL( triangleConvexPairsOut.getBufferCL(), true ),
- b3BufferInfoCL( bodyBuf->getBufferCL(),true),
- b3BufferInfoCL( m_concaveSepNormals.getBufferCL()),
- b3BufferInfoCL( m_concaveHasSeparatingNormals.getBufferCL()),
- b3BufferInfoCL( contactOut->getBufferCL()),
- b3BufferInfoCL( clippingFacesOutGPU.getBufferCL()),
- b3BufferInfoCL( worldVertsB2GPU.getBufferCL()),
- b3BufferInfoCL( m_totalContactsOut.getBufferCL())
- };
-
- b3LauncherCL launcher(m_queue, m_newContactReductionKernel,"m_newContactReductionKernel");
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ {
+ b3BufferInfoCL(triangleConvexPairsOut.getBufferCL(), true),
+ b3BufferInfoCL(bodyBuf->getBufferCL(), true),
+ b3BufferInfoCL(m_concaveSepNormals.getBufferCL()),
+ b3BufferInfoCL(m_concaveHasSeparatingNormals.getBufferCL()),
+ b3BufferInfoCL(contactOut->getBufferCL()),
+ b3BufferInfoCL(clippingFacesOutGPU.getBufferCL()),
+ b3BufferInfoCL(worldVertsB2GPU.getBufferCL()),
+ b3BufferInfoCL(m_totalContactsOut.getBufferCL())};
+
+ b3LauncherCL launcher(m_queue, m_newContactReductionKernel, "m_newContactReductionKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
launcher.setConst(vertexFaceCapacity);
launcher.setConst(newContactCapacity);
- launcher.setConst( numConcavePairs );
+ launcher.setConst(numConcavePairs);
int num = numConcavePairs;
- launcher.launch1D( num);
+ launcher.launch1D(num);
}
nContacts = m_totalContactsOut.at(0);
contactOut->resize(nContacts);
//printf("contactOut4 (after newContactReductionKernel) = %d\n",nContacts);
- }else
+ }
+ else
{
-
volatile int nGlobalContactsOut = nContacts;
b3AlignedObjectArray<b3Int4> triangleConvexPairsOutHost;
triangleConvexPairsOut.copyToHost(triangleConvexPairsOutHost);
b3AlignedObjectArray<b3RigidBodyData> hostBodyBuf;
bodyBuf->copyToHost(hostBodyBuf);
- b3AlignedObjectArray<int>concaveHasSeparatingNormalsCPU;
+ b3AlignedObjectArray<int> concaveHasSeparatingNormalsCPU;
m_concaveHasSeparatingNormals.copyToHost(concaveHasSeparatingNormalsCPU);
b3AlignedObjectArray<b3Vector3> concaveSepNormalsHost;
m_concaveSepNormals.copyToHost(concaveSepNormalsHost);
-
b3AlignedObjectArray<b3Contact4> hostContacts;
if (nContacts)
{
@@ -4268,67 +3977,59 @@ void GpuSatCollision::computeConvexConvexContactsGPUSAT( b3OpenCLArray<b3Int4>*
clippingFacesOutGPU.copyToHost(clippingFacesOutCPU);
worldVertsB2GPU.copyToHost(worldVertsB2CPU);
-
-
- for (int i=0;i<numConcavePairs;i++)
+ for (int i = 0; i < numConcavePairs; i++)
{
- b3NewContactReductionKernel( &triangleConvexPairsOutHost.at(0),
- &hostBodyBuf.at(0),
- &concaveSepNormalsHost.at(0),
- &concaveHasSeparatingNormalsCPU.at(0),
- &hostContacts.at(0),
- &clippingFacesOutCPU.at(0),
- &worldVertsB2CPU.at(0),
- &nGlobalContactsOut,
- vertexFaceCapacity,
- newContactCapacity,
- numConcavePairs,
- i
- );
-
+ b3NewContactReductionKernel(&triangleConvexPairsOutHost.at(0),
+ &hostBodyBuf.at(0),
+ &concaveSepNormalsHost.at(0),
+ &concaveHasSeparatingNormalsCPU.at(0),
+ &hostContacts.at(0),
+ &clippingFacesOutCPU.at(0),
+ &worldVertsB2CPU.at(0),
+ &nGlobalContactsOut,
+ vertexFaceCapacity,
+ newContactCapacity,
+ numConcavePairs,
+ i);
}
-
nContacts = nGlobalContactsOut;
- m_totalContactsOut.copyFromHostPointer(&nContacts,1,0,true);
-// nContacts = m_totalContactsOut.at(0);
+ m_totalContactsOut.copyFromHostPointer(&nContacts, 1, 0, true);
+ // nContacts = m_totalContactsOut.at(0);
//contactOut->resize(nContacts);
hostContacts.resize(nContacts);
//printf("contactOut4 (after newContactReductionKernel) = %d\n",nContacts);
contactOut->copyFromHost(hostContacts);
}
-
}
//re-use?
-
-
- } else
+ }
+ else
{
B3_PROFILE("clipHullHullConcaveConvexKernel");
nContacts = m_totalContactsOut.at(0);
int newContactCapacity = contactOut->capacity();
//printf("contactOut5 = %d\n",nContacts);
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL( triangleConvexPairsOut.getBufferCL(), true ),
- b3BufferInfoCL( bodyBuf->getBufferCL(),true),
- b3BufferInfoCL( gpuCollidables.getBufferCL(),true),
- b3BufferInfoCL( convexData.getBufferCL(),true),
- b3BufferInfoCL( gpuVertices.getBufferCL(),true),
- b3BufferInfoCL( gpuUniqueEdges.getBufferCL(),true),
- b3BufferInfoCL( gpuFaces.getBufferCL(),true),
- b3BufferInfoCL( gpuIndices.getBufferCL(),true),
- b3BufferInfoCL( gpuChildShapes.getBufferCL(),true),
- b3BufferInfoCL( m_concaveSepNormals.getBufferCL()),
- b3BufferInfoCL( contactOut->getBufferCL()),
- b3BufferInfoCL( m_totalContactsOut.getBufferCL())
- };
- b3LauncherCL launcher(m_queue, m_clipHullHullConcaveConvexKernel,"m_clipHullHullConcaveConvexKernel");
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL(triangleConvexPairsOut.getBufferCL(), true),
+ b3BufferInfoCL(bodyBuf->getBufferCL(), true),
+ b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
+ b3BufferInfoCL(convexData.getBufferCL(), true),
+ b3BufferInfoCL(gpuVertices.getBufferCL(), true),
+ b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
+ b3BufferInfoCL(gpuFaces.getBufferCL(), true),
+ b3BufferInfoCL(gpuIndices.getBufferCL(), true),
+ b3BufferInfoCL(gpuChildShapes.getBufferCL(), true),
+ b3BufferInfoCL(m_concaveSepNormals.getBufferCL()),
+ b3BufferInfoCL(contactOut->getBufferCL()),
+ b3BufferInfoCL(m_totalContactsOut.getBufferCL())};
+ b3LauncherCL launcher(m_queue, m_clipHullHullConcaveConvexKernel, "m_clipHullHullConcaveConvexKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
launcher.setConst(newContactCapacity);
- launcher.setConst( numConcavePairs );
+ launcher.setConst(numConcavePairs);
int num = numConcavePairs;
- launcher.launch1D( num);
+ launcher.launch1D(num);
clFinish(m_queue);
nContacts = m_totalContactsOut.at(0);
contactOut->resize(nContacts);
@@ -4337,12 +4038,10 @@ void GpuSatCollision::computeConvexConvexContactsGPUSAT( b3OpenCLArray<b3Int4>*
contactOut->copyToHost(cpuContacts);
}
// printf("nContacts after = %d\n", nContacts);
- }//numConcavePairs
-
-
+ } //numConcavePairs
//convex-convex contact clipping
-
+
bool breakupKernel = false;
#ifdef __APPLE__
@@ -4350,166 +4049,149 @@ void GpuSatCollision::computeConvexConvexContactsGPUSAT( b3OpenCLArray<b3Int4>*
#endif
#ifdef CHECK_ON_HOST
- bool computeConvexConvex = false;
+ bool computeConvexConvex = false;
#else
- bool computeConvexConvex = true;
-#endif//CHECK_ON_HOST
+ bool computeConvexConvex = true;
+#endif //CHECK_ON_HOST
if (computeConvexConvex)
{
B3_PROFILE("clipHullHullKernel");
- if (breakupKernel)
- {
-
-
-
-
- worldVertsB1GPU.resize(vertexFaceCapacity*nPairs);
- clippingFacesOutGPU.resize(nPairs);
- worldNormalsAGPU.resize(nPairs);
- worldVertsA1GPU.resize(vertexFaceCapacity*nPairs);
- worldVertsB2GPU.resize(vertexFaceCapacity*nPairs);
-
- if (findConvexClippingFacesGPU)
- {
- B3_PROFILE("findClippingFacesKernel");
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL( pairs->getBufferCL(), true ),
- b3BufferInfoCL( bodyBuf->getBufferCL(),true),
- b3BufferInfoCL( gpuCollidables.getBufferCL(),true),
- b3BufferInfoCL( convexData.getBufferCL(),true),
- b3BufferInfoCL( gpuVertices.getBufferCL(),true),
- b3BufferInfoCL( gpuUniqueEdges.getBufferCL(),true),
- b3BufferInfoCL( gpuFaces.getBufferCL(),true),
- b3BufferInfoCL( gpuIndices.getBufferCL(),true),
- b3BufferInfoCL( m_sepNormals.getBufferCL()),
- b3BufferInfoCL( m_hasSeparatingNormals.getBufferCL()),
- b3BufferInfoCL( clippingFacesOutGPU.getBufferCL()),
- b3BufferInfoCL( worldVertsA1GPU.getBufferCL()),
- b3BufferInfoCL( worldNormalsAGPU.getBufferCL()),
- b3BufferInfoCL( worldVertsB1GPU.getBufferCL())
- };
-
- b3LauncherCL launcher(m_queue, m_findClippingFacesKernel,"m_findClippingFacesKernel");
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst( vertexFaceCapacity);
- launcher.setConst( nPairs );
- int num = nPairs;
- launcher.launch1D( num);
- clFinish(m_queue);
-
- } else
+ if (breakupKernel)
{
-
- float minDist = -1e30f;
- float maxDist = 0.02f;
+ worldVertsB1GPU.resize(vertexFaceCapacity * nPairs);
+ clippingFacesOutGPU.resize(nPairs);
+ worldNormalsAGPU.resize(nPairs);
+ worldVertsA1GPU.resize(vertexFaceCapacity * nPairs);
+ worldVertsB2GPU.resize(vertexFaceCapacity * nPairs);
- b3AlignedObjectArray<b3ConvexPolyhedronData> hostConvexData;
- convexData.copyToHost(hostConvexData);
- b3AlignedObjectArray<b3Collidable> hostCollidables;
- gpuCollidables.copyToHost(hostCollidables);
+ if (findConvexClippingFacesGPU)
+ {
+ B3_PROFILE("findClippingFacesKernel");
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL(pairs->getBufferCL(), true),
+ b3BufferInfoCL(bodyBuf->getBufferCL(), true),
+ b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
+ b3BufferInfoCL(convexData.getBufferCL(), true),
+ b3BufferInfoCL(gpuVertices.getBufferCL(), true),
+ b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
+ b3BufferInfoCL(gpuFaces.getBufferCL(), true),
+ b3BufferInfoCL(gpuIndices.getBufferCL(), true),
+ b3BufferInfoCL(m_sepNormals.getBufferCL()),
+ b3BufferInfoCL(m_hasSeparatingNormals.getBufferCL()),
+ b3BufferInfoCL(clippingFacesOutGPU.getBufferCL()),
+ b3BufferInfoCL(worldVertsA1GPU.getBufferCL()),
+ b3BufferInfoCL(worldNormalsAGPU.getBufferCL()),
+ b3BufferInfoCL(worldVertsB1GPU.getBufferCL())};
+
+ b3LauncherCL launcher(m_queue, m_findClippingFacesKernel, "m_findClippingFacesKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setConst(vertexFaceCapacity);
+ launcher.setConst(nPairs);
+ int num = nPairs;
+ launcher.launch1D(num);
+ clFinish(m_queue);
+ }
+ else
+ {
+ float minDist = -1e30f;
+ float maxDist = 0.02f;
- b3AlignedObjectArray<int> hostHasSepNormals;
- m_hasSeparatingNormals.copyToHost(hostHasSepNormals);
- b3AlignedObjectArray<b3Vector3> cpuSepNormals;
- m_sepNormals.copyToHost(cpuSepNormals);
+ b3AlignedObjectArray<b3ConvexPolyhedronData> hostConvexData;
+ convexData.copyToHost(hostConvexData);
+ b3AlignedObjectArray<b3Collidable> hostCollidables;
+ gpuCollidables.copyToHost(hostCollidables);
- b3AlignedObjectArray<b3Int4> hostPairs;
- pairs->copyToHost(hostPairs);
- b3AlignedObjectArray<b3RigidBodyData> hostBodyBuf;
- bodyBuf->copyToHost(hostBodyBuf);
+ b3AlignedObjectArray<int> hostHasSepNormals;
+ m_hasSeparatingNormals.copyToHost(hostHasSepNormals);
+ b3AlignedObjectArray<b3Vector3> cpuSepNormals;
+ m_sepNormals.copyToHost(cpuSepNormals);
+ b3AlignedObjectArray<b3Int4> hostPairs;
+ pairs->copyToHost(hostPairs);
+ b3AlignedObjectArray<b3RigidBodyData> hostBodyBuf;
+ bodyBuf->copyToHost(hostBodyBuf);
- //worldVertsB1GPU.resize(vertexFaceCapacity*nPairs);
- b3AlignedObjectArray<b3Vector3> worldVertsB1CPU;
- worldVertsB1GPU.copyToHost(worldVertsB1CPU);
+ //worldVertsB1GPU.resize(vertexFaceCapacity*nPairs);
+ b3AlignedObjectArray<b3Vector3> worldVertsB1CPU;
+ worldVertsB1GPU.copyToHost(worldVertsB1CPU);
- b3AlignedObjectArray<b3Int4> clippingFacesOutCPU;
- clippingFacesOutGPU.copyToHost(clippingFacesOutCPU);
+ b3AlignedObjectArray<b3Int4> clippingFacesOutCPU;
+ clippingFacesOutGPU.copyToHost(clippingFacesOutCPU);
- b3AlignedObjectArray<b3Vector3> worldNormalsACPU;
- worldNormalsACPU.resize(nPairs);
+ b3AlignedObjectArray<b3Vector3> worldNormalsACPU;
+ worldNormalsACPU.resize(nPairs);
- b3AlignedObjectArray<b3Vector3> worldVertsA1CPU;
- worldVertsA1CPU.resize(worldVertsA1GPU.size());
-
-
- b3AlignedObjectArray<b3Vector3> hostVertices;
- gpuVertices.copyToHost(hostVertices);
- b3AlignedObjectArray<b3GpuFace> hostFaces;
- gpuFaces.copyToHost(hostFaces);
- b3AlignedObjectArray<int> hostIndices;
- gpuIndices.copyToHost(hostIndices);
-
-
- for (int i=0;i<nPairs;i++)
- {
+ b3AlignedObjectArray<b3Vector3> worldVertsA1CPU;
+ worldVertsA1CPU.resize(worldVertsA1GPU.size());
- int bodyIndexA = hostPairs[i].x;
- int bodyIndexB = hostPairs[i].y;
-
- int collidableIndexA = hostBodyBuf[bodyIndexA].m_collidableIdx;
- int collidableIndexB = hostBodyBuf[bodyIndexB].m_collidableIdx;
-
- int shapeIndexA = hostCollidables[collidableIndexA].m_shapeIndex;
- int shapeIndexB = hostCollidables[collidableIndexB].m_shapeIndex;
-
+ b3AlignedObjectArray<b3Vector3> hostVertices;
+ gpuVertices.copyToHost(hostVertices);
+ b3AlignedObjectArray<b3GpuFace> hostFaces;
+ gpuFaces.copyToHost(hostFaces);
+ b3AlignedObjectArray<int> hostIndices;
+ gpuIndices.copyToHost(hostIndices);
- if (hostHasSepNormals[i])
+ for (int i = 0; i < nPairs; i++)
{
- b3FindClippingFaces(cpuSepNormals[i],
- &hostConvexData[shapeIndexA],
- &hostConvexData[shapeIndexB],
- hostBodyBuf[bodyIndexA].m_pos,hostBodyBuf[bodyIndexA].m_quat,
- hostBodyBuf[bodyIndexB].m_pos,hostBodyBuf[bodyIndexB].m_quat,
- &worldVertsA1CPU.at(0),&worldNormalsACPU.at(0),
- &worldVertsB1CPU.at(0),
- vertexFaceCapacity,minDist,maxDist,
- &hostVertices.at(0),&hostFaces.at(0),
- &hostIndices.at(0),
- &hostVertices.at(0),&hostFaces.at(0),
- &hostIndices.at(0),&clippingFacesOutCPU.at(0),i);
- }
- }
-
- clippingFacesOutGPU.copyFromHost(clippingFacesOutCPU);
- worldVertsA1GPU.copyFromHost(worldVertsA1CPU);
- worldNormalsAGPU.copyFromHost(worldNormalsACPU);
- worldVertsB1GPU.copyFromHost(worldVertsB1CPU);
-
- }
+ int bodyIndexA = hostPairs[i].x;
+ int bodyIndexB = hostPairs[i].y;
+ int collidableIndexA = hostBodyBuf[bodyIndexA].m_collidableIdx;
+ int collidableIndexB = hostBodyBuf[bodyIndexB].m_collidableIdx;
+ int shapeIndexA = hostCollidables[collidableIndexA].m_shapeIndex;
+ int shapeIndexB = hostCollidables[collidableIndexB].m_shapeIndex;
+ if (hostHasSepNormals[i])
+ {
+ b3FindClippingFaces(cpuSepNormals[i],
+ &hostConvexData[shapeIndexA],
+ &hostConvexData[shapeIndexB],
+ hostBodyBuf[bodyIndexA].m_pos, hostBodyBuf[bodyIndexA].m_quat,
+ hostBodyBuf[bodyIndexB].m_pos, hostBodyBuf[bodyIndexB].m_quat,
+ &worldVertsA1CPU.at(0), &worldNormalsACPU.at(0),
+ &worldVertsB1CPU.at(0),
+ vertexFaceCapacity, minDist, maxDist,
+ &hostVertices.at(0), &hostFaces.at(0),
+ &hostIndices.at(0),
+ &hostVertices.at(0), &hostFaces.at(0),
+ &hostIndices.at(0), &clippingFacesOutCPU.at(0), i);
+ }
+ }
+ clippingFacesOutGPU.copyFromHost(clippingFacesOutCPU);
+ worldVertsA1GPU.copyFromHost(worldVertsA1CPU);
+ worldNormalsAGPU.copyFromHost(worldNormalsACPU);
+ worldVertsB1GPU.copyFromHost(worldVertsB1CPU);
+ }
- ///clip face B against face A, reduce contacts and append them to a global contact array
- if (1)
- {
- if (clipConvexFacesAndFindContactsCPU)
+ ///clip face B against face A, reduce contacts and append them to a global contact array
+ if (1)
{
+ if (clipConvexFacesAndFindContactsCPU)
+ {
+ //b3AlignedObjectArray<b3Int4> hostPairs;
+ //pairs->copyToHost(hostPairs);
- //b3AlignedObjectArray<b3Int4> hostPairs;
- //pairs->copyToHost(hostPairs);
+ b3AlignedObjectArray<b3Vector3> hostSepNormals;
+ m_sepNormals.copyToHost(hostSepNormals);
+ b3AlignedObjectArray<int> hostHasSepAxis;
+ m_hasSeparatingNormals.copyToHost(hostHasSepAxis);
- b3AlignedObjectArray<b3Vector3> hostSepNormals;
- m_sepNormals.copyToHost(hostSepNormals);
- b3AlignedObjectArray<int> hostHasSepAxis;
- m_hasSeparatingNormals.copyToHost(hostHasSepAxis);
+ b3AlignedObjectArray<b3Int4> hostClippingFaces;
+ clippingFacesOutGPU.copyToHost(hostClippingFaces);
+ b3AlignedObjectArray<b3Vector3> worldVertsB2CPU;
+ worldVertsB2CPU.resize(vertexFaceCapacity * nPairs);
- b3AlignedObjectArray<b3Int4> hostClippingFaces;
- clippingFacesOutGPU.copyToHost(hostClippingFaces);
- b3AlignedObjectArray<b3Vector3> worldVertsB2CPU;
- worldVertsB2CPU.resize(vertexFaceCapacity*nPairs);
-
- b3AlignedObjectArray<b3Vector3>worldVertsA1CPU;
- worldVertsA1GPU.copyToHost(worldVertsA1CPU);
- b3AlignedObjectArray<b3Vector3> worldNormalsACPU;
- worldNormalsAGPU.copyToHost(worldNormalsACPU);
+ b3AlignedObjectArray<b3Vector3> worldVertsA1CPU;
+ worldVertsA1GPU.copyToHost(worldVertsA1CPU);
+ b3AlignedObjectArray<b3Vector3> worldNormalsACPU;
+ worldNormalsAGPU.copyToHost(worldNormalsACPU);
- b3AlignedObjectArray<b3Vector3> worldVertsB1CPU;
- worldVertsB1GPU.copyToHost(worldVertsB1CPU);
+ b3AlignedObjectArray<b3Vector3> worldVertsB1CPU;
+ worldVertsB1GPU.copyToHost(worldVertsB1CPU);
- /*
+ /*
__global const b3Float4* separatingNormals,
__global const int* hasSeparatingAxis,
__global b3Int4* clippingFacesOut,
@@ -4520,214 +4202,207 @@ void GpuSatCollision::computeConvexConvexContactsGPUSAT( b3OpenCLArray<b3Int4>*
int vertexFaceCapacity,
int pairIndex
*/
- for (int i=0;i<nPairs;i++)
- {
- clipFacesAndFindContactsKernel(
- &hostSepNormals.at(0),
- &hostHasSepAxis.at(0),
- &hostClippingFaces.at(0),
- &worldVertsA1CPU.at(0),
- &worldNormalsACPU.at(0),
- &worldVertsB1CPU.at(0),
- &worldVertsB2CPU.at(0),
-
- vertexFaceCapacity,
- i);
- }
-
- clippingFacesOutGPU.copyFromHost(hostClippingFaces);
- worldVertsB2GPU.copyFromHost(worldVertsB2CPU);
+ for (int i = 0; i < nPairs; i++)
+ {
+ clipFacesAndFindContactsKernel(
+ &hostSepNormals.at(0),
+ &hostHasSepAxis.at(0),
+ &hostClippingFaces.at(0),
+ &worldVertsA1CPU.at(0),
+ &worldNormalsACPU.at(0),
+ &worldVertsB1CPU.at(0),
+ &worldVertsB2CPU.at(0),
- } else
- {
- B3_PROFILE("clipFacesAndFindContacts");
- //nContacts = m_totalContactsOut.at(0);
- //int h = m_hasSeparatingNormals.at(0);
- //int4 p = clippingFacesOutGPU.at(0);
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL( m_sepNormals.getBufferCL()),
- b3BufferInfoCL( m_hasSeparatingNormals.getBufferCL()),
- b3BufferInfoCL( clippingFacesOutGPU.getBufferCL()),
- b3BufferInfoCL( worldVertsA1GPU.getBufferCL()),
- b3BufferInfoCL( worldNormalsAGPU.getBufferCL()),
- b3BufferInfoCL( worldVertsB1GPU.getBufferCL()),
- b3BufferInfoCL( worldVertsB2GPU.getBufferCL())
- };
+ vertexFaceCapacity,
+ i);
+ }
- b3LauncherCL launcher(m_queue, m_clipFacesAndFindContacts,"m_clipFacesAndFindContacts");
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst(vertexFaceCapacity);
+ clippingFacesOutGPU.copyFromHost(hostClippingFaces);
+ worldVertsB2GPU.copyFromHost(worldVertsB2CPU);
+ }
+ else
+ {
+ B3_PROFILE("clipFacesAndFindContacts");
+ //nContacts = m_totalContactsOut.at(0);
+ //int h = m_hasSeparatingNormals.at(0);
+ //int4 p = clippingFacesOutGPU.at(0);
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL(m_sepNormals.getBufferCL()),
+ b3BufferInfoCL(m_hasSeparatingNormals.getBufferCL()),
+ b3BufferInfoCL(clippingFacesOutGPU.getBufferCL()),
+ b3BufferInfoCL(worldVertsA1GPU.getBufferCL()),
+ b3BufferInfoCL(worldNormalsAGPU.getBufferCL()),
+ b3BufferInfoCL(worldVertsB1GPU.getBufferCL()),
+ b3BufferInfoCL(worldVertsB2GPU.getBufferCL())};
+
+ b3LauncherCL launcher(m_queue, m_clipFacesAndFindContacts, "m_clipFacesAndFindContacts");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setConst(vertexFaceCapacity);
- launcher.setConst( nPairs );
- int debugMode = 0;
- launcher.setConst( debugMode);
- int num = nPairs;
- launcher.launch1D( num);
- clFinish(m_queue);
- }
+ launcher.setConst(nPairs);
+ int debugMode = 0;
+ launcher.setConst(debugMode);
+ int num = nPairs;
+ launcher.launch1D(num);
+ clFinish(m_queue);
+ }
- {
- nContacts = m_totalContactsOut.at(0);
- //printf("nContacts = %d\n",nContacts);
+ {
+ nContacts = m_totalContactsOut.at(0);
+ //printf("nContacts = %d\n",nContacts);
- int newContactCapacity = nContacts+nPairs;
- contactOut->reserve(newContactCapacity);
+ int newContactCapacity = nContacts + nPairs;
+ contactOut->reserve(newContactCapacity);
- if (reduceConvexContactsOnGPU)
- {
+ if (reduceConvexContactsOnGPU)
{
- B3_PROFILE("newContactReductionKernel");
- b3BufferInfoCL bInfo[] =
{
- b3BufferInfoCL( pairs->getBufferCL(), true ),
- b3BufferInfoCL( bodyBuf->getBufferCL(),true),
- b3BufferInfoCL( m_sepNormals.getBufferCL()),
- b3BufferInfoCL( m_hasSeparatingNormals.getBufferCL()),
- b3BufferInfoCL( contactOut->getBufferCL()),
- b3BufferInfoCL( clippingFacesOutGPU.getBufferCL()),
- b3BufferInfoCL( worldVertsB2GPU.getBufferCL()),
- b3BufferInfoCL( m_totalContactsOut.getBufferCL())
- };
-
- b3LauncherCL launcher(m_queue, m_newContactReductionKernel,"m_newContactReductionKernel");
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst(vertexFaceCapacity);
- launcher.setConst(newContactCapacity);
- launcher.setConst( nPairs );
- int num = nPairs;
-
- launcher.launch1D( num);
+ B3_PROFILE("newContactReductionKernel");
+ b3BufferInfoCL bInfo[] =
+ {
+ b3BufferInfoCL(pairs->getBufferCL(), true),
+ b3BufferInfoCL(bodyBuf->getBufferCL(), true),
+ b3BufferInfoCL(m_sepNormals.getBufferCL()),
+ b3BufferInfoCL(m_hasSeparatingNormals.getBufferCL()),
+ b3BufferInfoCL(contactOut->getBufferCL()),
+ b3BufferInfoCL(clippingFacesOutGPU.getBufferCL()),
+ b3BufferInfoCL(worldVertsB2GPU.getBufferCL()),
+ b3BufferInfoCL(m_totalContactsOut.getBufferCL())};
+
+ b3LauncherCL launcher(m_queue, m_newContactReductionKernel, "m_newContactReductionKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setConst(vertexFaceCapacity);
+ launcher.setConst(newContactCapacity);
+ launcher.setConst(nPairs);
+ int num = nPairs;
+
+ launcher.launch1D(num);
+ }
+ nContacts = m_totalContactsOut.at(0);
+ contactOut->resize(nContacts);
}
- nContacts = m_totalContactsOut.at(0);
- contactOut->resize(nContacts);
- } else
- {
-
- volatile int nGlobalContactsOut = nContacts;
- b3AlignedObjectArray<b3Int4> hostPairs;
- pairs->copyToHost(hostPairs);
- b3AlignedObjectArray<b3RigidBodyData> hostBodyBuf;
- bodyBuf->copyToHost(hostBodyBuf);
- b3AlignedObjectArray<b3Vector3> hostSepNormals;
- m_sepNormals.copyToHost(hostSepNormals);
- b3AlignedObjectArray<int> hostHasSepAxis;
- m_hasSeparatingNormals.copyToHost(hostHasSepAxis);
- b3AlignedObjectArray<b3Contact4> hostContactsOut;
- contactOut->copyToHost(hostContactsOut);
- hostContactsOut.resize(newContactCapacity);
-
- b3AlignedObjectArray<b3Int4> hostClippingFaces;
- clippingFacesOutGPU.copyToHost(hostClippingFaces);
- b3AlignedObjectArray<b3Vector3> worldVertsB2CPU;
- worldVertsB2GPU.copyToHost(worldVertsB2CPU);
-
- for (int i=0;i<nPairs;i++)
+ else
{
- b3NewContactReductionKernel(&hostPairs.at(0),
- &hostBodyBuf.at(0),
- &hostSepNormals.at(0),
- &hostHasSepAxis.at(0),
- &hostContactsOut.at(0),
- &hostClippingFaces.at(0),
- &worldVertsB2CPU.at(0),
- &nGlobalContactsOut,
- vertexFaceCapacity,
- newContactCapacity,
- nPairs,
- i);
+ volatile int nGlobalContactsOut = nContacts;
+ b3AlignedObjectArray<b3Int4> hostPairs;
+ pairs->copyToHost(hostPairs);
+ b3AlignedObjectArray<b3RigidBodyData> hostBodyBuf;
+ bodyBuf->copyToHost(hostBodyBuf);
+ b3AlignedObjectArray<b3Vector3> hostSepNormals;
+ m_sepNormals.copyToHost(hostSepNormals);
+ b3AlignedObjectArray<int> hostHasSepAxis;
+ m_hasSeparatingNormals.copyToHost(hostHasSepAxis);
+ b3AlignedObjectArray<b3Contact4> hostContactsOut;
+ contactOut->copyToHost(hostContactsOut);
+ hostContactsOut.resize(newContactCapacity);
+
+ b3AlignedObjectArray<b3Int4> hostClippingFaces;
+ clippingFacesOutGPU.copyToHost(hostClippingFaces);
+ b3AlignedObjectArray<b3Vector3> worldVertsB2CPU;
+ worldVertsB2GPU.copyToHost(worldVertsB2CPU);
+
+ for (int i = 0; i < nPairs; i++)
+ {
+ b3NewContactReductionKernel(&hostPairs.at(0),
+ &hostBodyBuf.at(0),
+ &hostSepNormals.at(0),
+ &hostHasSepAxis.at(0),
+ &hostContactsOut.at(0),
+ &hostClippingFaces.at(0),
+ &worldVertsB2CPU.at(0),
+ &nGlobalContactsOut,
+ vertexFaceCapacity,
+ newContactCapacity,
+ nPairs,
+ i);
+ }
+
+ nContacts = nGlobalContactsOut;
+ m_totalContactsOut.copyFromHostPointer(&nContacts, 1, 0, true);
+ hostContactsOut.resize(nContacts);
+ //printf("contactOut4 (after newContactReductionKernel) = %d\n",nContacts);
+ contactOut->copyFromHost(hostContactsOut);
}
+ // b3Contact4 pt = contactOut->at(0);
+ // printf("nContacts = %d\n",nContacts);
+ }
+ }
+ }
+ else //breakupKernel
+ {
+ if (nPairs)
+ {
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL(pairs->getBufferCL(), true),
+ b3BufferInfoCL(bodyBuf->getBufferCL(), true),
+ b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
+ b3BufferInfoCL(convexData.getBufferCL(), true),
+ b3BufferInfoCL(gpuVertices.getBufferCL(), true),
+ b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
+ b3BufferInfoCL(gpuFaces.getBufferCL(), true),
+ b3BufferInfoCL(gpuIndices.getBufferCL(), true),
+ b3BufferInfoCL(m_sepNormals.getBufferCL()),
+ b3BufferInfoCL(m_hasSeparatingNormals.getBufferCL()),
+ b3BufferInfoCL(contactOut->getBufferCL()),
+ b3BufferInfoCL(m_totalContactsOut.getBufferCL())};
+ b3LauncherCL launcher(m_queue, m_clipHullHullKernel, "m_clipHullHullKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setConst(nPairs);
+ launcher.setConst(maxContactCapacity);
- nContacts = nGlobalContactsOut;
- m_totalContactsOut.copyFromHostPointer(&nContacts,1,0,true);
- hostContactsOut.resize(nContacts);
- //printf("contactOut4 (after newContactReductionKernel) = %d\n",nContacts);
- contactOut->copyFromHost(hostContactsOut);
+ int num = nPairs;
+ launcher.launch1D(num);
+ clFinish(m_queue);
+
+ nContacts = m_totalContactsOut.at(0);
+ if (nContacts >= maxContactCapacity)
+ {
+ b3Error("Exceeded contact capacity (%d/%d)\n", nContacts, maxContactCapacity);
+ nContacts = maxContactCapacity;
}
- // b3Contact4 pt = contactOut->at(0);
- // printf("nContacts = %d\n",nContacts);
+ contactOut->resize(nContacts);
}
}
- }
- else//breakupKernel
- {
- if (nPairs)
+ int nCompoundsPairs = m_gpuCompoundPairs.size();
+
+ if (nCompoundsPairs)
{
b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL( pairs->getBufferCL(), true ),
- b3BufferInfoCL( bodyBuf->getBufferCL(),true),
- b3BufferInfoCL( gpuCollidables.getBufferCL(),true),
- b3BufferInfoCL( convexData.getBufferCL(),true),
- b3BufferInfoCL( gpuVertices.getBufferCL(),true),
- b3BufferInfoCL( gpuUniqueEdges.getBufferCL(),true),
- b3BufferInfoCL( gpuFaces.getBufferCL(),true),
- b3BufferInfoCL( gpuIndices.getBufferCL(),true),
- b3BufferInfoCL( m_sepNormals.getBufferCL()),
- b3BufferInfoCL( m_hasSeparatingNormals.getBufferCL()),
- b3BufferInfoCL( contactOut->getBufferCL()),
- b3BufferInfoCL( m_totalContactsOut.getBufferCL())
- };
- b3LauncherCL launcher(m_queue, m_clipHullHullKernel,"m_clipHullHullKernel");
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst( nPairs );
+ b3BufferInfoCL(m_gpuCompoundPairs.getBufferCL(), true),
+ b3BufferInfoCL(bodyBuf->getBufferCL(), true),
+ b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
+ b3BufferInfoCL(convexData.getBufferCL(), true),
+ b3BufferInfoCL(gpuVertices.getBufferCL(), true),
+ b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
+ b3BufferInfoCL(gpuFaces.getBufferCL(), true),
+ b3BufferInfoCL(gpuIndices.getBufferCL(), true),
+ b3BufferInfoCL(gpuChildShapes.getBufferCL(), true),
+ b3BufferInfoCL(m_gpuCompoundSepNormals.getBufferCL(), true),
+ b3BufferInfoCL(m_gpuHasCompoundSepNormals.getBufferCL(), true),
+ b3BufferInfoCL(contactOut->getBufferCL()),
+ b3BufferInfoCL(m_totalContactsOut.getBufferCL())};
+ b3LauncherCL launcher(m_queue, m_clipCompoundsHullHullKernel, "m_clipCompoundsHullHullKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setConst(nCompoundsPairs);
launcher.setConst(maxContactCapacity);
- int num = nPairs;
- launcher.launch1D( num);
+ int num = nCompoundsPairs;
+ launcher.launch1D(num);
clFinish(m_queue);
nContacts = m_totalContactsOut.at(0);
- if (nContacts >= maxContactCapacity)
+ if (nContacts > maxContactCapacity)
{
- b3Error("Exceeded contact capacity (%d/%d)\n",nContacts,maxContactCapacity);
+ b3Error("Error: contacts exceeds capacity (%d/%d)\n", nContacts, maxContactCapacity);
nContacts = maxContactCapacity;
}
contactOut->resize(nContacts);
- }
- }
-
-
- int nCompoundsPairs = m_gpuCompoundPairs.size();
-
- if (nCompoundsPairs)
- {
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL( m_gpuCompoundPairs.getBufferCL(), true ),
- b3BufferInfoCL( bodyBuf->getBufferCL(),true),
- b3BufferInfoCL( gpuCollidables.getBufferCL(),true),
- b3BufferInfoCL( convexData.getBufferCL(),true),
- b3BufferInfoCL( gpuVertices.getBufferCL(),true),
- b3BufferInfoCL( gpuUniqueEdges.getBufferCL(),true),
- b3BufferInfoCL( gpuFaces.getBufferCL(),true),
- b3BufferInfoCL( gpuIndices.getBufferCL(),true),
- b3BufferInfoCL( gpuChildShapes.getBufferCL(),true),
- b3BufferInfoCL( m_gpuCompoundSepNormals.getBufferCL(),true),
- b3BufferInfoCL( m_gpuHasCompoundSepNormals.getBufferCL(),true),
- b3BufferInfoCL( contactOut->getBufferCL()),
- b3BufferInfoCL( m_totalContactsOut.getBufferCL())
- };
- b3LauncherCL launcher(m_queue, m_clipCompoundsHullHullKernel,"m_clipCompoundsHullHullKernel");
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst( nCompoundsPairs );
- launcher.setConst(maxContactCapacity);
-
- int num = nCompoundsPairs;
- launcher.launch1D( num);
- clFinish(m_queue);
-
- nContacts = m_totalContactsOut.at(0);
- if (nContacts>maxContactCapacity)
- {
-
- b3Error("Error: contacts exceeds capacity (%d/%d)\n", nContacts, maxContactCapacity);
- nContacts = maxContactCapacity;
- }
- contactOut->resize(nContacts);
- }//if nCompoundsPairs
+ } //if nCompoundsPairs
}
- }//contactClippingOnGpu
+ } //contactClippingOnGpu
//printf("nContacts end = %d\n",nContacts);
-
+
//printf("frameCount = %d\n",frameCount++);
}
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ConvexHullContact.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ConvexHullContact.h
index e24c1579c6..53e8c4ed4d 100644
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ConvexHullContact.h
+++ b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ConvexHullContact.h
@@ -17,102 +17,90 @@
//#include "../../dynamics/basic_demo/Stubs/ChNarrowPhase.h"
-
-
-
struct GpuSatCollision
{
- cl_context m_context;
- cl_device_id m_device;
- cl_command_queue m_queue;
- cl_kernel m_findSeparatingAxisKernel;
- cl_kernel m_mprPenetrationKernel;
- cl_kernel m_findSeparatingAxisUnitSphereKernel;
-
+ cl_context m_context;
+ cl_device_id m_device;
+ cl_command_queue m_queue;
+ cl_kernel m_findSeparatingAxisKernel;
+ cl_kernel m_mprPenetrationKernel;
+ cl_kernel m_findSeparatingAxisUnitSphereKernel;
cl_kernel m_findSeparatingAxisVertexFaceKernel;
cl_kernel m_findSeparatingAxisEdgeEdgeKernel;
-
- cl_kernel m_findConcaveSeparatingAxisKernel;
- cl_kernel m_findConcaveSeparatingAxisVertexFaceKernel;
- cl_kernel m_findConcaveSeparatingAxisEdgeEdgeKernel;
-
-
-
-
- cl_kernel m_findCompoundPairsKernel;
- cl_kernel m_processCompoundPairsKernel;
-
- cl_kernel m_clipHullHullKernel;
- cl_kernel m_clipCompoundsHullHullKernel;
-
- cl_kernel m_clipFacesAndFindContacts;
- cl_kernel m_findClippingFacesKernel;
-
- cl_kernel m_clipHullHullConcaveConvexKernel;
-// cl_kernel m_extractManifoldAndAddContactKernel;
- cl_kernel m_newContactReductionKernel;
-
- cl_kernel m_bvhTraversalKernel;
- cl_kernel m_primitiveContactsKernel;
- cl_kernel m_findConcaveSphereContactsKernel;
-
- cl_kernel m_processCompoundPairsPrimitivesKernel;
-
+
+ cl_kernel m_findConcaveSeparatingAxisKernel;
+ cl_kernel m_findConcaveSeparatingAxisVertexFaceKernel;
+ cl_kernel m_findConcaveSeparatingAxisEdgeEdgeKernel;
+
+ cl_kernel m_findCompoundPairsKernel;
+ cl_kernel m_processCompoundPairsKernel;
+
+ cl_kernel m_clipHullHullKernel;
+ cl_kernel m_clipCompoundsHullHullKernel;
+
+ cl_kernel m_clipFacesAndFindContacts;
+ cl_kernel m_findClippingFacesKernel;
+
+ cl_kernel m_clipHullHullConcaveConvexKernel;
+ // cl_kernel m_extractManifoldAndAddContactKernel;
+ cl_kernel m_newContactReductionKernel;
+
+ cl_kernel m_bvhTraversalKernel;
+ cl_kernel m_primitiveContactsKernel;
+ cl_kernel m_findConcaveSphereContactsKernel;
+
+ cl_kernel m_processCompoundPairsPrimitivesKernel;
+
b3OpenCLArray<b3Vector3> m_unitSphereDirections;
- b3OpenCLArray<int> m_totalContactsOut;
+ b3OpenCLArray<int> m_totalContactsOut;
b3OpenCLArray<b3Vector3> m_sepNormals;
b3OpenCLArray<float> m_dmins;
- b3OpenCLArray<int> m_hasSeparatingNormals;
+ b3OpenCLArray<int> m_hasSeparatingNormals;
b3OpenCLArray<b3Vector3> m_concaveSepNormals;
- b3OpenCLArray<int> m_concaveHasSeparatingNormals;
- b3OpenCLArray<int> m_numConcavePairsOut;
+ b3OpenCLArray<int> m_concaveHasSeparatingNormals;
+ b3OpenCLArray<int> m_numConcavePairsOut;
b3OpenCLArray<b3CompoundOverlappingPair> m_gpuCompoundPairs;
b3OpenCLArray<b3Vector3> m_gpuCompoundSepNormals;
- b3OpenCLArray<int> m_gpuHasCompoundSepNormals;
- b3OpenCLArray<int> m_numCompoundPairsOut;
-
+ b3OpenCLArray<int> m_gpuHasCompoundSepNormals;
+ b3OpenCLArray<int> m_numCompoundPairsOut;
- GpuSatCollision(cl_context ctx,cl_device_id device, cl_command_queue q );
+ GpuSatCollision(cl_context ctx, cl_device_id device, cl_command_queue q);
virtual ~GpuSatCollision();
-
-
- void computeConvexConvexContactsGPUSAT( b3OpenCLArray<b3Int4>* pairs, int nPairs,
- const b3OpenCLArray<b3RigidBodyData>* bodyBuf,
- b3OpenCLArray<b3Contact4>* contactOut, int& nContacts,
- const b3OpenCLArray<b3Contact4>* oldContacts,
- int maxContactCapacity,
- int compoundPairCapacity,
- const b3OpenCLArray<b3ConvexPolyhedronData>& hostConvexData,
- const b3OpenCLArray<b3Vector3>& vertices,
- const b3OpenCLArray<b3Vector3>& uniqueEdges,
- const b3OpenCLArray<b3GpuFace>& faces,
- const b3OpenCLArray<int>& indices,
- const b3OpenCLArray<b3Collidable>& gpuCollidables,
- const b3OpenCLArray<b3GpuChildShape>& gpuChildShapes,
-
- const b3OpenCLArray<b3Aabb>& clAabbsWorldSpace,
- const b3OpenCLArray<b3Aabb>& clAabbsLocalSpace,
-
- b3OpenCLArray<b3Vector3>& worldVertsB1GPU,
- b3OpenCLArray<b3Int4>& clippingFacesOutGPU,
- b3OpenCLArray<b3Vector3>& worldNormalsAGPU,
- b3OpenCLArray<b3Vector3>& worldVertsA1GPU,
- b3OpenCLArray<b3Vector3>& worldVertsB2GPU,
- b3AlignedObjectArray<class b3OptimizedBvh*>& bvhData,
- b3OpenCLArray<b3QuantizedBvhNode>* treeNodesGPU,
- b3OpenCLArray<b3BvhSubtreeInfo>* subTreesGPU,
- b3OpenCLArray<b3BvhInfo>* bvhInfo,
- int numObjects,
- int maxTriConvexPairCapacity,
- b3OpenCLArray<b3Int4>& triangleConvexPairs,
- int& numTriConvexPairsOut
- );
-
+ void computeConvexConvexContactsGPUSAT(b3OpenCLArray<b3Int4>* pairs, int nPairs,
+ const b3OpenCLArray<b3RigidBodyData>* bodyBuf,
+ b3OpenCLArray<b3Contact4>* contactOut, int& nContacts,
+ const b3OpenCLArray<b3Contact4>* oldContacts,
+ int maxContactCapacity,
+ int compoundPairCapacity,
+ const b3OpenCLArray<b3ConvexPolyhedronData>& hostConvexData,
+ const b3OpenCLArray<b3Vector3>& vertices,
+ const b3OpenCLArray<b3Vector3>& uniqueEdges,
+ const b3OpenCLArray<b3GpuFace>& faces,
+ const b3OpenCLArray<int>& indices,
+ const b3OpenCLArray<b3Collidable>& gpuCollidables,
+ const b3OpenCLArray<b3GpuChildShape>& gpuChildShapes,
+
+ const b3OpenCLArray<b3Aabb>& clAabbsWorldSpace,
+ const b3OpenCLArray<b3Aabb>& clAabbsLocalSpace,
+
+ b3OpenCLArray<b3Vector3>& worldVertsB1GPU,
+ b3OpenCLArray<b3Int4>& clippingFacesOutGPU,
+ b3OpenCLArray<b3Vector3>& worldNormalsAGPU,
+ b3OpenCLArray<b3Vector3>& worldVertsA1GPU,
+ b3OpenCLArray<b3Vector3>& worldVertsB2GPU,
+ b3AlignedObjectArray<class b3OptimizedBvh*>& bvhData,
+ b3OpenCLArray<b3QuantizedBvhNode>* treeNodesGPU,
+ b3OpenCLArray<b3BvhSubtreeInfo>* subTreesGPU,
+ b3OpenCLArray<b3BvhInfo>* bvhInfo,
+ int numObjects,
+ int maxTriConvexPairCapacity,
+ b3OpenCLArray<b3Int4>& triangleConvexPairs,
+ int& numTriConvexPairsOut);
};
-#endif //_CONVEX_HULL_CONTACT_H
+#endif //_CONVEX_HULL_CONTACT_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ConvexPolyhedronCL.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ConvexPolyhedronCL.h
index 337100fb1a..c4cf700076 100644
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ConvexPolyhedronCL.h
+++ b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ConvexPolyhedronCL.h
@@ -4,6 +4,4 @@
#include "Bullet3Common/b3Transform.h"
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
-
-
-#endif //CONVEX_POLYHEDRON_CL
+#endif //CONVEX_POLYHEDRON_CL
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3GjkEpa.cpp b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3GjkEpa.cpp
index d636f983c6..974b246f03 100644
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3GjkEpa.cpp
+++ b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3GjkEpa.cpp
@@ -29,902 +29,951 @@ GJK-EPA collision solver by Nathanael Presson, 2008
namespace gjkepa2_impl2
{
+// Config
- // Config
+/* GJK */
+#define GJK_MAX_ITERATIONS 128
+#define GJK_ACCURACY ((b3Scalar)0.0001)
+#define GJK_MIN_DISTANCE ((b3Scalar)0.0001)
+#define GJK_DUPLICATED_EPS ((b3Scalar)0.0001)
+#define GJK_SIMPLEX2_EPS ((b3Scalar)0.0)
+#define GJK_SIMPLEX3_EPS ((b3Scalar)0.0)
+#define GJK_SIMPLEX4_EPS ((b3Scalar)0.0)
- /* GJK */
-#define GJK_MAX_ITERATIONS 128
-#define GJK_ACCURACY ((b3Scalar)0.0001)
-#define GJK_MIN_DISTANCE ((b3Scalar)0.0001)
-#define GJK_DUPLICATED_EPS ((b3Scalar)0.0001)
-#define GJK_SIMPLEX2_EPS ((b3Scalar)0.0)
-#define GJK_SIMPLEX3_EPS ((b3Scalar)0.0)
-#define GJK_SIMPLEX4_EPS ((b3Scalar)0.0)
+/* EPA */
+#define EPA_MAX_VERTICES 64
+#define EPA_MAX_FACES (EPA_MAX_VERTICES * 2)
+#define EPA_MAX_ITERATIONS 255
+#define EPA_ACCURACY ((b3Scalar)0.0001)
+#define EPA_FALLBACK (10 * EPA_ACCURACY)
+#define EPA_PLANE_EPS ((b3Scalar)0.00001)
+#define EPA_INSIDE_EPS ((b3Scalar)0.01)
- /* EPA */
-#define EPA_MAX_VERTICES 64
-#define EPA_MAX_FACES (EPA_MAX_VERTICES*2)
-#define EPA_MAX_ITERATIONS 255
-#define EPA_ACCURACY ((b3Scalar)0.0001)
-#define EPA_FALLBACK (10*EPA_ACCURACY)
-#define EPA_PLANE_EPS ((b3Scalar)0.00001)
-#define EPA_INSIDE_EPS ((b3Scalar)0.01)
+// Shorthands
+// MinkowskiDiff
+struct b3MinkowskiDiff
+{
+ const b3ConvexPolyhedronData* m_shapes[2];
- // Shorthands
-
-
- // MinkowskiDiff
- struct b3MinkowskiDiff
- {
-
-
- const b3ConvexPolyhedronData* m_shapes[2];
-
-
- b3Matrix3x3 m_toshape1;
- b3Transform m_toshape0;
+ b3Matrix3x3 m_toshape1;
+ b3Transform m_toshape0;
- bool m_enableMargin;
-
+ bool m_enableMargin;
- void EnableMargin(bool enable)
- {
- m_enableMargin = enable;
- }
- inline b3Vector3 Support0(const b3Vector3& d, const b3AlignedObjectArray<b3Vector3>& verticesA) const
+ void EnableMargin(bool enable)
+ {
+ m_enableMargin = enable;
+ }
+ inline b3Vector3 Support0(const b3Vector3& d, const b3AlignedObjectArray<b3Vector3>& verticesA) const
+ {
+ if (m_enableMargin)
{
- if (m_enableMargin)
- {
- return localGetSupportVertexWithMargin(d,m_shapes[0],verticesA,0.f);
- } else
- {
- return localGetSupportVertexWithoutMargin(d,m_shapes[0],verticesA);
- }
+ return localGetSupportVertexWithMargin(d, m_shapes[0], verticesA, 0.f);
}
- inline b3Vector3 Support1(const b3Vector3& d, const b3AlignedObjectArray<b3Vector3>& verticesB) const
+ else
{
- if (m_enableMargin)
- {
- return m_toshape0*(localGetSupportVertexWithMargin(m_toshape1*d,m_shapes[1],verticesB,0.f));
- } else
- {
- return m_toshape0*(localGetSupportVertexWithoutMargin(m_toshape1*d,m_shapes[1],verticesB));
- }
+ return localGetSupportVertexWithoutMargin(d, m_shapes[0], verticesA);
}
-
- inline b3Vector3 Support(const b3Vector3& d, const b3AlignedObjectArray<b3Vector3>& verticesA, const b3AlignedObjectArray<b3Vector3>& verticesB) const
+ }
+ inline b3Vector3 Support1(const b3Vector3& d, const b3AlignedObjectArray<b3Vector3>& verticesB) const
+ {
+ if (m_enableMargin)
{
- return(Support0(d,verticesA)-Support1(-d,verticesB));
+ return m_toshape0 * (localGetSupportVertexWithMargin(m_toshape1 * d, m_shapes[1], verticesB, 0.f));
}
- b3Vector3 Support(const b3Vector3& d,unsigned int index,const b3AlignedObjectArray<b3Vector3>& verticesA, const b3AlignedObjectArray<b3Vector3>& verticesB) const
+ else
{
- if(index)
- return(Support1(d,verticesA));
- else
- return(Support0(d,verticesB));
+ return m_toshape0 * (localGetSupportVertexWithoutMargin(m_toshape1 * d, m_shapes[1], verticesB));
}
- };
+ }
- typedef b3MinkowskiDiff tShape;
+ inline b3Vector3 Support(const b3Vector3& d, const b3AlignedObjectArray<b3Vector3>& verticesA, const b3AlignedObjectArray<b3Vector3>& verticesB) const
+ {
+ return (Support0(d, verticesA) - Support1(-d, verticesB));
+ }
+ b3Vector3 Support(const b3Vector3& d, unsigned int index, const b3AlignedObjectArray<b3Vector3>& verticesA, const b3AlignedObjectArray<b3Vector3>& verticesB) const
+ {
+ if (index)
+ return (Support1(d, verticesA));
+ else
+ return (Support0(d, verticesB));
+ }
+};
+typedef b3MinkowskiDiff tShape;
- // GJK
- struct b3GJK
+// GJK
+struct b3GJK
+{
+ /* Types */
+ struct sSV
{
- /* Types */
- struct sSV
- {
- b3Vector3 d,w;
- };
- struct sSimplex
+ b3Vector3 d, w;
+ };
+ struct sSimplex
+ {
+ sSV* c[4];
+ b3Scalar p[4];
+ unsigned int rank;
+ };
+ struct eStatus
+ {
+ enum _
{
- sSV* c[4];
- b3Scalar p[4];
- unsigned int rank;
- };
- struct eStatus { enum _ {
Valid,
Inside,
- Failed };};
- /* Fields */
- tShape m_shape;
- const b3AlignedObjectArray<b3Vector3>& m_verticesA;
- const b3AlignedObjectArray<b3Vector3>& m_verticesB;
- b3Vector3 m_ray;
- b3Scalar m_distance;
- sSimplex m_simplices[2];
- sSV m_store[4];
- sSV* m_free[4];
- unsigned int m_nfree;
- unsigned int m_current;
- sSimplex* m_simplex;
- eStatus::_ m_status;
- /* Methods */
- b3GJK(const b3AlignedObjectArray<b3Vector3>& verticesA,const b3AlignedObjectArray<b3Vector3>& verticesB)
- :m_verticesA(verticesA),m_verticesB(verticesB)
- {
- Initialize();
+ Failed
+ };
+ };
+ /* Fields */
+ tShape m_shape;
+ const b3AlignedObjectArray<b3Vector3>& m_verticesA;
+ const b3AlignedObjectArray<b3Vector3>& m_verticesB;
+ b3Vector3 m_ray;
+ b3Scalar m_distance;
+ sSimplex m_simplices[2];
+ sSV m_store[4];
+ sSV* m_free[4];
+ unsigned int m_nfree;
+ unsigned int m_current;
+ sSimplex* m_simplex;
+ eStatus::_ m_status;
+ /* Methods */
+ b3GJK(const b3AlignedObjectArray<b3Vector3>& verticesA, const b3AlignedObjectArray<b3Vector3>& verticesB)
+ : m_verticesA(verticesA), m_verticesB(verticesB)
+ {
+ Initialize();
+ }
+ void Initialize()
+ {
+ m_ray = b3MakeVector3(0, 0, 0);
+ m_nfree = 0;
+ m_status = eStatus::Failed;
+ m_current = 0;
+ m_distance = 0;
+ }
+ eStatus::_ Evaluate(const tShape& shapearg, const b3Vector3& guess)
+ {
+ unsigned int iterations = 0;
+ b3Scalar sqdist = 0;
+ b3Scalar alpha = 0;
+ b3Vector3 lastw[4];
+ unsigned int clastw = 0;
+ /* Initialize solver */
+ m_free[0] = &m_store[0];
+ m_free[1] = &m_store[1];
+ m_free[2] = &m_store[2];
+ m_free[3] = &m_store[3];
+ m_nfree = 4;
+ m_current = 0;
+ m_status = eStatus::Valid;
+ m_shape = shapearg;
+ m_distance = 0;
+ /* Initialize simplex */
+ m_simplices[0].rank = 0;
+ m_ray = guess;
+ const b3Scalar sqrl = m_ray.length2();
+ appendvertice(m_simplices[0], sqrl > 0 ? -m_ray : b3MakeVector3(1, 0, 0));
+ m_simplices[0].p[0] = 1;
+ m_ray = m_simplices[0].c[0]->w;
+ sqdist = sqrl;
+ lastw[0] =
+ lastw[1] =
+ lastw[2] =
+ lastw[3] = m_ray;
+ /* Loop */
+ do
+ {
+ const unsigned int next = 1 - m_current;
+ sSimplex& cs = m_simplices[m_current];
+ sSimplex& ns = m_simplices[next];
+ /* Check zero */
+ const b3Scalar rl = m_ray.length();
+ if (rl < GJK_MIN_DISTANCE)
+ { /* Touching or inside */
+ m_status = eStatus::Inside;
+ break;
}
- void Initialize()
+ /* Append new vertice in -'v' direction */
+ appendvertice(cs, -m_ray);
+ const b3Vector3& w = cs.c[cs.rank - 1]->w;
+ bool found = false;
+ for (unsigned int i = 0; i < 4; ++i)
{
- m_ray = b3MakeVector3(0,0,0);
- m_nfree = 0;
- m_status = eStatus::Failed;
- m_current = 0;
- m_distance = 0;
+ if ((w - lastw[i]).length2() < GJK_DUPLICATED_EPS)
+ {
+ found = true;
+ break;
+ }
+ }
+ if (found)
+ { /* Return old simplex */
+ removevertice(m_simplices[m_current]);
+ break;
}
- eStatus::_ Evaluate(const tShape& shapearg,const b3Vector3& guess)
+ else
+ { /* Update lastw */
+ lastw[clastw = (clastw + 1) & 3] = w;
+ }
+ /* Check for termination */
+ const b3Scalar omega = b3Dot(m_ray, w) / rl;
+ alpha = b3Max(omega, alpha);
+ if (((rl - alpha) - (GJK_ACCURACY * rl)) <= 0)
+ { /* Return old simplex */
+ removevertice(m_simplices[m_current]);
+ break;
+ }
+ /* Reduce simplex */
+ b3Scalar weights[4];
+ unsigned int mask = 0;
+ switch (cs.rank)
{
- unsigned int iterations=0;
- b3Scalar sqdist=0;
- b3Scalar alpha=0;
- b3Vector3 lastw[4];
- unsigned int clastw=0;
- /* Initialize solver */
- m_free[0] = &m_store[0];
- m_free[1] = &m_store[1];
- m_free[2] = &m_store[2];
- m_free[3] = &m_store[3];
- m_nfree = 4;
- m_current = 0;
- m_status = eStatus::Valid;
- m_shape = shapearg;
- m_distance = 0;
- /* Initialize simplex */
- m_simplices[0].rank = 0;
- m_ray = guess;
- const b3Scalar sqrl= m_ray.length2();
- appendvertice(m_simplices[0],sqrl>0?-m_ray:b3MakeVector3(1,0,0));
- m_simplices[0].p[0] = 1;
- m_ray = m_simplices[0].c[0]->w;
- sqdist = sqrl;
- lastw[0] =
- lastw[1] =
- lastw[2] =
- lastw[3] = m_ray;
- /* Loop */
- do {
- const unsigned int next=1-m_current;
- sSimplex& cs=m_simplices[m_current];
- sSimplex& ns=m_simplices[next];
- /* Check zero */
- const b3Scalar rl=m_ray.length();
- if(rl<GJK_MIN_DISTANCE)
- {/* Touching or inside */
- m_status=eStatus::Inside;
- break;
- }
- /* Append new vertice in -'v' direction */
- appendvertice(cs,-m_ray);
- const b3Vector3& w=cs.c[cs.rank-1]->w;
- bool found=false;
- for(unsigned int i=0;i<4;++i)
+ case 2:
+ sqdist = projectorigin(cs.c[0]->w,
+ cs.c[1]->w,
+ weights, mask);
+ break;
+ case 3:
+ sqdist = projectorigin(cs.c[0]->w,
+ cs.c[1]->w,
+ cs.c[2]->w,
+ weights, mask);
+ break;
+ case 4:
+ sqdist = projectorigin(cs.c[0]->w,
+ cs.c[1]->w,
+ cs.c[2]->w,
+ cs.c[3]->w,
+ weights, mask);
+ break;
+ }
+ if (sqdist >= 0)
+ { /* Valid */
+ ns.rank = 0;
+ m_ray = b3MakeVector3(0, 0, 0);
+ m_current = next;
+ for (unsigned int i = 0, ni = cs.rank; i < ni; ++i)
+ {
+ if (mask & (1 << i))
{
- if((w-lastw[i]).length2()<GJK_DUPLICATED_EPS)
- { found=true;break; }
- }
- if(found)
- {/* Return old simplex */
- removevertice(m_simplices[m_current]);
- break;
+ ns.c[ns.rank] = cs.c[i];
+ ns.p[ns.rank++] = weights[i];
+ m_ray += cs.c[i]->w * weights[i];
}
else
- {/* Update lastw */
- lastw[clastw=(clastw+1)&3]=w;
- }
- /* Check for termination */
- const b3Scalar omega=b3Dot(m_ray,w)/rl;
- alpha=b3Max(omega,alpha);
- if(((rl-alpha)-(GJK_ACCURACY*rl))<=0)
- {/* Return old simplex */
- removevertice(m_simplices[m_current]);
- break;
- }
- /* Reduce simplex */
- b3Scalar weights[4];
- unsigned int mask=0;
- switch(cs.rank)
{
- case 2: sqdist=projectorigin( cs.c[0]->w,
- cs.c[1]->w,
- weights,mask);break;
- case 3: sqdist=projectorigin( cs.c[0]->w,
- cs.c[1]->w,
- cs.c[2]->w,
- weights,mask);break;
- case 4: sqdist=projectorigin( cs.c[0]->w,
- cs.c[1]->w,
- cs.c[2]->w,
- cs.c[3]->w,
- weights,mask);break;
- }
- if(sqdist>=0)
- {/* Valid */
- ns.rank = 0;
- m_ray = b3MakeVector3(0,0,0);
- m_current = next;
- for(unsigned int i=0,ni=cs.rank;i<ni;++i)
- {
- if(mask&(1<<i))
- {
- ns.c[ns.rank] = cs.c[i];
- ns.p[ns.rank++] = weights[i];
- m_ray += cs.c[i]->w*weights[i];
- }
- else
- {
- m_free[m_nfree++] = cs.c[i];
- }
- }
- if(mask==15) m_status=eStatus::Inside;
+ m_free[m_nfree++] = cs.c[i];
}
- else
- {/* Return old simplex */
- removevertice(m_simplices[m_current]);
- break;
- }
- m_status=((++iterations)<GJK_MAX_ITERATIONS)?m_status:eStatus::Failed;
- } while(m_status==eStatus::Valid);
- m_simplex=&m_simplices[m_current];
- switch(m_status)
+ }
+ if (mask == 15) m_status = eStatus::Inside;
+ }
+ else
+ { /* Return old simplex */
+ removevertice(m_simplices[m_current]);
+ break;
+ }
+ m_status = ((++iterations) < GJK_MAX_ITERATIONS) ? m_status : eStatus::Failed;
+ } while (m_status == eStatus::Valid);
+ m_simplex = &m_simplices[m_current];
+ switch (m_status)
+ {
+ case eStatus::Valid:
+ m_distance = m_ray.length();
+ break;
+ case eStatus::Inside:
+ m_distance = 0;
+ break;
+ default:
+ {
+ }
+ }
+ return (m_status);
+ }
+ bool EncloseOrigin()
+ {
+ switch (m_simplex->rank)
+ {
+ case 1:
+ {
+ for (unsigned int i = 0; i < 3; ++i)
{
- case eStatus::Valid: m_distance=m_ray.length();break;
- case eStatus::Inside: m_distance=0;break;
- default:
- {
- }
- }
- return(m_status);
+ b3Vector3 axis = b3MakeVector3(0, 0, 0);
+ axis[i] = 1;
+ appendvertice(*m_simplex, axis);
+ if (EncloseOrigin()) return (true);
+ removevertice(*m_simplex);
+ appendvertice(*m_simplex, -axis);
+ if (EncloseOrigin()) return (true);
+ removevertice(*m_simplex);
+ }
}
- bool EncloseOrigin()
+ break;
+ case 2:
{
- switch(m_simplex->rank)
+ const b3Vector3 d = m_simplex->c[1]->w - m_simplex->c[0]->w;
+ for (unsigned int i = 0; i < 3; ++i)
{
- case 1:
+ b3Vector3 axis = b3MakeVector3(0, 0, 0);
+ axis[i] = 1;
+ const b3Vector3 p = b3Cross(d, axis);
+ if (p.length2() > 0)
{
- for(unsigned int i=0;i<3;++i)
- {
- b3Vector3 axis=b3MakeVector3(0,0,0);
- axis[i]=1;
- appendvertice(*m_simplex, axis);
- if(EncloseOrigin()) return(true);
- removevertice(*m_simplex);
- appendvertice(*m_simplex,-axis);
- if(EncloseOrigin()) return(true);
- removevertice(*m_simplex);
- }
+ appendvertice(*m_simplex, p);
+ if (EncloseOrigin()) return (true);
+ removevertice(*m_simplex);
+ appendvertice(*m_simplex, -p);
+ if (EncloseOrigin()) return (true);
+ removevertice(*m_simplex);
}
- break;
- case 2:
- {
- const b3Vector3 d=m_simplex->c[1]->w-m_simplex->c[0]->w;
- for(unsigned int i=0;i<3;++i)
- {
- b3Vector3 axis=b3MakeVector3(0,0,0);
- axis[i]=1;
- const b3Vector3 p=b3Cross(d,axis);
- if(p.length2()>0)
- {
- appendvertice(*m_simplex, p);
- if(EncloseOrigin()) return(true);
- removevertice(*m_simplex);
- appendvertice(*m_simplex,-p);
- if(EncloseOrigin()) return(true);
- removevertice(*m_simplex);
- }
- }
- }
- break;
- case 3:
- {
- const b3Vector3 n=b3Cross(m_simplex->c[1]->w-m_simplex->c[0]->w,
- m_simplex->c[2]->w-m_simplex->c[0]->w);
- if(n.length2()>0)
- {
- appendvertice(*m_simplex,n);
- if(EncloseOrigin()) return(true);
- removevertice(*m_simplex);
- appendvertice(*m_simplex,-n);
- if(EncloseOrigin()) return(true);
- removevertice(*m_simplex);
- }
- }
- break;
- case 4:
- {
- if(b3Fabs(det( m_simplex->c[0]->w-m_simplex->c[3]->w,
- m_simplex->c[1]->w-m_simplex->c[3]->w,
- m_simplex->c[2]->w-m_simplex->c[3]->w))>0)
- return(true);
- }
- break;
}
- return(false);
}
- /* Internals */
- void getsupport(const b3Vector3& d,sSV& sv) const
+ break;
+ case 3:
{
- sv.d = d/d.length();
- sv.w = m_shape.Support(sv.d,m_verticesA,m_verticesB);
+ const b3Vector3 n = b3Cross(m_simplex->c[1]->w - m_simplex->c[0]->w,
+ m_simplex->c[2]->w - m_simplex->c[0]->w);
+ if (n.length2() > 0)
+ {
+ appendvertice(*m_simplex, n);
+ if (EncloseOrigin()) return (true);
+ removevertice(*m_simplex);
+ appendvertice(*m_simplex, -n);
+ if (EncloseOrigin()) return (true);
+ removevertice(*m_simplex);
+ }
}
- void removevertice(sSimplex& simplex)
+ break;
+ case 4:
{
- m_free[m_nfree++]=simplex.c[--simplex.rank];
+ if (b3Fabs(det(m_simplex->c[0]->w - m_simplex->c[3]->w,
+ m_simplex->c[1]->w - m_simplex->c[3]->w,
+ m_simplex->c[2]->w - m_simplex->c[3]->w)) > 0)
+ return (true);
}
- void appendvertice(sSimplex& simplex,const b3Vector3& v)
+ break;
+ }
+ return (false);
+ }
+ /* Internals */
+ void getsupport(const b3Vector3& d, sSV& sv) const
+ {
+ sv.d = d / d.length();
+ sv.w = m_shape.Support(sv.d, m_verticesA, m_verticesB);
+ }
+ void removevertice(sSimplex& simplex)
+ {
+ m_free[m_nfree++] = simplex.c[--simplex.rank];
+ }
+ void appendvertice(sSimplex& simplex, const b3Vector3& v)
+ {
+ simplex.p[simplex.rank] = 0;
+ simplex.c[simplex.rank] = m_free[--m_nfree];
+ getsupport(v, *simplex.c[simplex.rank++]);
+ }
+ static b3Scalar det(const b3Vector3& a, const b3Vector3& b, const b3Vector3& c)
+ {
+ return (a.y * b.z * c.x + a.z * b.x * c.y -
+ a.x * b.z * c.y - a.y * b.x * c.z +
+ a.x * b.y * c.z - a.z * b.y * c.x);
+ }
+ static b3Scalar projectorigin(const b3Vector3& a,
+ const b3Vector3& b,
+ b3Scalar* w, unsigned int& m)
+ {
+ const b3Vector3 d = b - a;
+ const b3Scalar l = d.length2();
+ if (l > GJK_SIMPLEX2_EPS)
+ {
+ const b3Scalar t(l > 0 ? -b3Dot(a, d) / l : 0);
+ if (t >= 1)
{
- simplex.p[simplex.rank]=0;
- simplex.c[simplex.rank]=m_free[--m_nfree];
- getsupport(v,*simplex.c[simplex.rank++]);
+ w[0] = 0;
+ w[1] = 1;
+ m = 2;
+ return (b.length2());
}
- static b3Scalar det(const b3Vector3& a,const b3Vector3& b,const b3Vector3& c)
+ else if (t <= 0)
{
- return( a.y*b.z*c.x+a.z*b.x*c.y-
- a.x*b.z*c.y-a.y*b.x*c.z+
- a.x*b.y*c.z-a.z*b.y*c.x);
+ w[0] = 1;
+ w[1] = 0;
+ m = 1;
+ return (a.length2());
}
- static b3Scalar projectorigin( const b3Vector3& a,
- const b3Vector3& b,
- b3Scalar* w,unsigned int& m)
+ else
{
- const b3Vector3 d=b-a;
- const b3Scalar l=d.length2();
- if(l>GJK_SIMPLEX2_EPS)
- {
- const b3Scalar t(l>0?-b3Dot(a,d)/l:0);
- if(t>=1) { w[0]=0;w[1]=1;m=2;return(b.length2()); }
- else if(t<=0) { w[0]=1;w[1]=0;m=1;return(a.length2()); }
- else { w[0]=1-(w[1]=t);m=3;return((a+d*t).length2()); }
- }
- return(-1);
+ w[0] = 1 - (w[1] = t);
+ m = 3;
+ return ((a + d * t).length2());
}
- static b3Scalar projectorigin( const b3Vector3& a,
- const b3Vector3& b,
- const b3Vector3& c,
- b3Scalar* w,unsigned int& m)
+ }
+ return (-1);
+ }
+ static b3Scalar projectorigin(const b3Vector3& a,
+ const b3Vector3& b,
+ const b3Vector3& c,
+ b3Scalar* w, unsigned int& m)
+ {
+ static const unsigned int imd3[] = {1, 2, 0};
+ const b3Vector3* vt[] = {&a, &b, &c};
+ const b3Vector3 dl[] = {a - b, b - c, c - a};
+ const b3Vector3 n = b3Cross(dl[0], dl[1]);
+ const b3Scalar l = n.length2();
+ if (l > GJK_SIMPLEX3_EPS)
+ {
+ b3Scalar mindist = -1;
+ b3Scalar subw[2] = {0.f, 0.f};
+ unsigned int subm(0);
+ for (unsigned int i = 0; i < 3; ++i)
{
- static const unsigned int imd3[]={1,2,0};
- const b3Vector3* vt[]={&a,&b,&c};
- const b3Vector3 dl[]={a-b,b-c,c-a};
- const b3Vector3 n=b3Cross(dl[0],dl[1]);
- const b3Scalar l=n.length2();
- if(l>GJK_SIMPLEX3_EPS)
+ if (b3Dot(*vt[i], b3Cross(dl[i], n)) > 0)
{
- b3Scalar mindist=-1;
- b3Scalar subw[2]={0.f,0.f};
- unsigned int subm(0);
- for(unsigned int i=0;i<3;++i)
- {
- if(b3Dot(*vt[i],b3Cross(dl[i],n))>0)
- {
- const unsigned int j=imd3[i];
- const b3Scalar subd(projectorigin(*vt[i],*vt[j],subw,subm));
- if((mindist<0)||(subd<mindist))
- {
- mindist = subd;
- m = static_cast<unsigned int>(((subm&1)?1<<i:0)+((subm&2)?1<<j:0));
- w[i] = subw[0];
- w[j] = subw[1];
- w[imd3[j]] = 0;
- }
- }
- }
- if(mindist<0)
+ const unsigned int j = imd3[i];
+ const b3Scalar subd(projectorigin(*vt[i], *vt[j], subw, subm));
+ if ((mindist < 0) || (subd < mindist))
{
- const b3Scalar d=b3Dot(a,n);
- const b3Scalar s=b3Sqrt(l);
- const b3Vector3 p=n*(d/l);
- mindist = p.length2();
- m = 7;
- w[0] = (b3Cross(dl[1],b-p)).length()/s;
- w[1] = (b3Cross(dl[2],c-p)).length()/s;
- w[2] = 1-(w[0]+w[1]);
+ mindist = subd;
+ m = static_cast<unsigned int>(((subm & 1) ? 1 << i : 0) + ((subm & 2) ? 1 << j : 0));
+ w[i] = subw[0];
+ w[j] = subw[1];
+ w[imd3[j]] = 0;
}
- return(mindist);
}
- return(-1);
}
- static b3Scalar projectorigin( const b3Vector3& a,
- const b3Vector3& b,
- const b3Vector3& c,
- const b3Vector3& d,
- b3Scalar* w,unsigned int& m)
+ if (mindist < 0)
+ {
+ const b3Scalar d = b3Dot(a, n);
+ const b3Scalar s = b3Sqrt(l);
+ const b3Vector3 p = n * (d / l);
+ mindist = p.length2();
+ m = 7;
+ w[0] = (b3Cross(dl[1], b - p)).length() / s;
+ w[1] = (b3Cross(dl[2], c - p)).length() / s;
+ w[2] = 1 - (w[0] + w[1]);
+ }
+ return (mindist);
+ }
+ return (-1);
+ }
+ static b3Scalar projectorigin(const b3Vector3& a,
+ const b3Vector3& b,
+ const b3Vector3& c,
+ const b3Vector3& d,
+ b3Scalar* w, unsigned int& m)
+ {
+ static const unsigned int imd3[] = {1, 2, 0};
+ const b3Vector3* vt[] = {&a, &b, &c, &d};
+ const b3Vector3 dl[] = {a - d, b - d, c - d};
+ const b3Scalar vl = det(dl[0], dl[1], dl[2]);
+ const bool ng = (vl * b3Dot(a, b3Cross(b - c, a - b))) <= 0;
+ if (ng && (b3Fabs(vl) > GJK_SIMPLEX4_EPS))
+ {
+ b3Scalar mindist = -1;
+ b3Scalar subw[3] = {0.f, 0.f, 0.f};
+ unsigned int subm(0);
+ for (unsigned int i = 0; i < 3; ++i)
{
- static const unsigned int imd3[]={1,2,0};
- const b3Vector3* vt[]={&a,&b,&c,&d};
- const b3Vector3 dl[]={a-d,b-d,c-d};
- const b3Scalar vl=det(dl[0],dl[1],dl[2]);
- const bool ng=(vl*b3Dot(a,b3Cross(b-c,a-b)))<=0;
- if(ng&&(b3Fabs(vl)>GJK_SIMPLEX4_EPS))
+ const unsigned int j = imd3[i];
+ const b3Scalar s = vl * b3Dot(d, b3Cross(dl[i], dl[j]));
+ if (s > 0)
{
- b3Scalar mindist=-1;
- b3Scalar subw[3]={0.f,0.f,0.f};
- unsigned int subm(0);
- for(unsigned int i=0;i<3;++i)
+ const b3Scalar subd = projectorigin(*vt[i], *vt[j], d, subw, subm);
+ if ((mindist < 0) || (subd < mindist))
{
- const unsigned int j=imd3[i];
- const b3Scalar s=vl*b3Dot(d,b3Cross(dl[i],dl[j]));
- if(s>0)
- {
- const b3Scalar subd=projectorigin(*vt[i],*vt[j],d,subw,subm);
- if((mindist<0)||(subd<mindist))
- {
- mindist = subd;
- m = static_cast<unsigned int>((subm&1?1<<i:0)+
- (subm&2?1<<j:0)+
- (subm&4?8:0));
- w[i] = subw[0];
- w[j] = subw[1];
- w[imd3[j]] = 0;
- w[3] = subw[2];
- }
- }
+ mindist = subd;
+ m = static_cast<unsigned int>((subm & 1 ? 1 << i : 0) +
+ (subm & 2 ? 1 << j : 0) +
+ (subm & 4 ? 8 : 0));
+ w[i] = subw[0];
+ w[j] = subw[1];
+ w[imd3[j]] = 0;
+ w[3] = subw[2];
}
- if(mindist<0)
- {
- mindist = 0;
- m = 15;
- w[0] = det(c,b,d)/vl;
- w[1] = det(a,c,d)/vl;
- w[2] = det(b,a,d)/vl;
- w[3] = 1-(w[0]+w[1]+w[2]);
- }
- return(mindist);
}
- return(-1);
}
- };
+ if (mindist < 0)
+ {
+ mindist = 0;
+ m = 15;
+ w[0] = det(c, b, d) / vl;
+ w[1] = det(a, c, d) / vl;
+ w[2] = det(b, a, d) / vl;
+ w[3] = 1 - (w[0] + w[1] + w[2]);
+ }
+ return (mindist);
+ }
+ return (-1);
+ }
+};
- // EPA
- struct b3EPA
+// EPA
+struct b3EPA
+{
+ /* Types */
+ typedef b3GJK::sSV sSV;
+ struct sFace
{
- /* Types */
- typedef b3GJK::sSV sSV;
- struct sFace
- {
- b3Vector3 n;
- b3Scalar d;
- sSV* c[3];
- sFace* f[3];
- sFace* l[2];
- unsigned char e[3];
- unsigned char pass;
- };
- struct sList
- {
- sFace* root;
- unsigned int count;
- sList() : root(0),count(0) {}
- };
- struct sHorizon
+ b3Vector3 n;
+ b3Scalar d;
+ sSV* c[3];
+ sFace* f[3];
+ sFace* l[2];
+ unsigned char e[3];
+ unsigned char pass;
+ };
+ struct sList
+ {
+ sFace* root;
+ unsigned int count;
+ sList() : root(0), count(0) {}
+ };
+ struct sHorizon
+ {
+ sFace* cf;
+ sFace* ff;
+ unsigned int nf;
+ sHorizon() : cf(0), ff(0), nf(0) {}
+ };
+ struct eStatus
+ {
+ enum _
{
- sFace* cf;
- sFace* ff;
- unsigned int nf;
- sHorizon() : cf(0),ff(0),nf(0) {}
- };
- struct eStatus { enum _ {
Valid,
Touching,
Degenerated,
NonConvex,
- InvalidHull,
+ InvalidHull,
OutOfFaces,
OutOfVertices,
AccuraryReached,
FallBack,
- Failed };};
- /* Fields */
- eStatus::_ m_status;
- b3GJK::sSimplex m_result;
- b3Vector3 m_normal;
- b3Scalar m_depth;
- sSV m_sv_store[EPA_MAX_VERTICES];
- sFace m_fc_store[EPA_MAX_FACES];
- unsigned int m_nextsv;
- sList m_hull;
- sList m_stock;
- /* Methods */
- b3EPA()
- {
- Initialize();
- }
+ Failed
+ };
+ };
+ /* Fields */
+ eStatus::_ m_status;
+ b3GJK::sSimplex m_result;
+ b3Vector3 m_normal;
+ b3Scalar m_depth;
+ sSV m_sv_store[EPA_MAX_VERTICES];
+ sFace m_fc_store[EPA_MAX_FACES];
+ unsigned int m_nextsv;
+ sList m_hull;
+ sList m_stock;
+ /* Methods */
+ b3EPA()
+ {
+ Initialize();
+ }
+ static inline void bind(sFace* fa, unsigned int ea, sFace* fb, unsigned int eb)
+ {
+ fa->e[ea] = (unsigned char)eb;
+ fa->f[ea] = fb;
+ fb->e[eb] = (unsigned char)ea;
+ fb->f[eb] = fa;
+ }
+ static inline void append(sList& list, sFace* face)
+ {
+ face->l[0] = 0;
+ face->l[1] = list.root;
+ if (list.root) list.root->l[0] = face;
+ list.root = face;
+ ++list.count;
+ }
+ static inline void remove(sList& list, sFace* face)
+ {
+ if (face->l[1]) face->l[1]->l[0] = face->l[0];
+ if (face->l[0]) face->l[0]->l[1] = face->l[1];
+ if (face == list.root) list.root = face->l[1];
+ --list.count;
+ }
- static inline void bind(sFace* fa,unsigned int ea,sFace* fb,unsigned int eb)
- {
- fa->e[ea]=(unsigned char)eb;fa->f[ea]=fb;
- fb->e[eb]=(unsigned char)ea;fb->f[eb]=fa;
- }
- static inline void append(sList& list,sFace* face)
+ void Initialize()
+ {
+ m_status = eStatus::Failed;
+ m_normal = b3MakeVector3(0, 0, 0);
+ m_depth = 0;
+ m_nextsv = 0;
+ for (unsigned int i = 0; i < EPA_MAX_FACES; ++i)
+ {
+ append(m_stock, &m_fc_store[EPA_MAX_FACES - i - 1]);
+ }
+ }
+ eStatus::_ Evaluate(b3GJK& gjk, const b3Vector3& guess)
+ {
+ b3GJK::sSimplex& simplex = *gjk.m_simplex;
+ if ((simplex.rank > 1) && gjk.EncloseOrigin())
+ {
+ /* Clean up */
+ while (m_hull.root)
{
- face->l[0] = 0;
- face->l[1] = list.root;
- if(list.root) list.root->l[0]=face;
- list.root = face;
- ++list.count;
+ sFace* f = m_hull.root;
+ remove(m_hull, f);
+ append(m_stock, f);
}
- static inline void remove(sList& list,sFace* face)
+ m_status = eStatus::Valid;
+ m_nextsv = 0;
+ /* Orient simplex */
+ if (gjk.det(simplex.c[0]->w - simplex.c[3]->w,
+ simplex.c[1]->w - simplex.c[3]->w,
+ simplex.c[2]->w - simplex.c[3]->w) < 0)
{
- if(face->l[1]) face->l[1]->l[0]=face->l[0];
- if(face->l[0]) face->l[0]->l[1]=face->l[1];
- if(face==list.root) list.root=face->l[1];
- --list.count;
+ b3Swap(simplex.c[0], simplex.c[1]);
+ b3Swap(simplex.p[0], simplex.p[1]);
}
-
-
- void Initialize()
+ /* Build initial hull */
+ sFace* tetra[] = {newface(simplex.c[0], simplex.c[1], simplex.c[2], true),
+ newface(simplex.c[1], simplex.c[0], simplex.c[3], true),
+ newface(simplex.c[2], simplex.c[1], simplex.c[3], true),
+ newface(simplex.c[0], simplex.c[2], simplex.c[3], true)};
+ if (m_hull.count == 4)
{
- m_status = eStatus::Failed;
- m_normal = b3MakeVector3(0,0,0);
- m_depth = 0;
- m_nextsv = 0;
- for(unsigned int i=0;i<EPA_MAX_FACES;++i)
+ sFace* best = findbest();
+ sFace outer = *best;
+ unsigned int pass = 0;
+ unsigned int iterations = 0;
+ bind(tetra[0], 0, tetra[1], 0);
+ bind(tetra[0], 1, tetra[2], 0);
+ bind(tetra[0], 2, tetra[3], 0);
+ bind(tetra[1], 1, tetra[3], 2);
+ bind(tetra[1], 2, tetra[2], 1);
+ bind(tetra[2], 2, tetra[3], 1);
+ m_status = eStatus::Valid;
+ for (; iterations < EPA_MAX_ITERATIONS; ++iterations)
{
- append(m_stock,&m_fc_store[EPA_MAX_FACES-i-1]);
- }
- }
- eStatus::_ Evaluate(b3GJK& gjk,const b3Vector3& guess)
- {
- b3GJK::sSimplex& simplex=*gjk.m_simplex;
- if((simplex.rank>1)&&gjk.EncloseOrigin())
- {
-
- /* Clean up */
- while(m_hull.root)
+ if (m_nextsv < EPA_MAX_VERTICES)
{
- sFace* f = m_hull.root;
- remove(m_hull,f);
- append(m_stock,f);
- }
- m_status = eStatus::Valid;
- m_nextsv = 0;
- /* Orient simplex */
- if(gjk.det( simplex.c[0]->w-simplex.c[3]->w,
- simplex.c[1]->w-simplex.c[3]->w,
- simplex.c[2]->w-simplex.c[3]->w)<0)
- {
- b3Swap(simplex.c[0],simplex.c[1]);
- b3Swap(simplex.p[0],simplex.p[1]);
- }
- /* Build initial hull */
- sFace* tetra[]={newface(simplex.c[0],simplex.c[1],simplex.c[2],true),
- newface(simplex.c[1],simplex.c[0],simplex.c[3],true),
- newface(simplex.c[2],simplex.c[1],simplex.c[3],true),
- newface(simplex.c[0],simplex.c[2],simplex.c[3],true)};
- if(m_hull.count==4)
- {
- sFace* best=findbest();
- sFace outer=*best;
- unsigned int pass=0;
- unsigned int iterations=0;
- bind(tetra[0],0,tetra[1],0);
- bind(tetra[0],1,tetra[2],0);
- bind(tetra[0],2,tetra[3],0);
- bind(tetra[1],1,tetra[3],2);
- bind(tetra[1],2,tetra[2],1);
- bind(tetra[2],2,tetra[3],1);
- m_status=eStatus::Valid;
- for(;iterations<EPA_MAX_ITERATIONS;++iterations)
+ sHorizon horizon;
+ sSV* w = &m_sv_store[m_nextsv++];
+ bool valid = true;
+ best->pass = (unsigned char)(++pass);
+ gjk.getsupport(best->n, *w);
+ const b3Scalar wdist = b3Dot(best->n, w->w) - best->d;
+ if (wdist > EPA_ACCURACY)
{
- if(m_nextsv<EPA_MAX_VERTICES)
- {
- sHorizon horizon;
- sSV* w=&m_sv_store[m_nextsv++];
- bool valid=true;
- best->pass = (unsigned char)(++pass);
- gjk.getsupport(best->n,*w);
- const b3Scalar wdist=b3Dot(best->n,w->w)-best->d;
- if(wdist>EPA_ACCURACY)
- {
- for(unsigned int j=0;(j<3)&&valid;++j)
- {
- valid&=expand( pass,w,
- best->f[j],best->e[j],
- horizon);
- }
- if(valid&&(horizon.nf>=3))
- {
- bind(horizon.cf,1,horizon.ff,2);
- remove(m_hull,best);
- append(m_stock,best);
- best=findbest();
- outer=*best;
- } else {
- m_status=eStatus::Failed;
- //m_status=eStatus::InvalidHull;
- break; }
- } else { m_status=eStatus::AccuraryReached;break; }
- } else { m_status=eStatus::OutOfVertices;break; }
+ for (unsigned int j = 0; (j < 3) && valid; ++j)
+ {
+ valid &= expand(pass, w,
+ best->f[j], best->e[j],
+ horizon);
+ }
+ if (valid && (horizon.nf >= 3))
+ {
+ bind(horizon.cf, 1, horizon.ff, 2);
+ remove(m_hull, best);
+ append(m_stock, best);
+ best = findbest();
+ outer = *best;
+ }
+ else
+ {
+ m_status = eStatus::Failed;
+ //m_status=eStatus::InvalidHull;
+ break;
+ }
+ }
+ else
+ {
+ m_status = eStatus::AccuraryReached;
+ break;
}
- const b3Vector3 projection=outer.n*outer.d;
- m_normal = outer.n;
- m_depth = outer.d;
- m_result.rank = 3;
- m_result.c[0] = outer.c[0];
- m_result.c[1] = outer.c[1];
- m_result.c[2] = outer.c[2];
- m_result.p[0] = b3Cross( outer.c[1]->w-projection,
- outer.c[2]->w-projection).length();
- m_result.p[1] = b3Cross( outer.c[2]->w-projection,
- outer.c[0]->w-projection).length();
- m_result.p[2] = b3Cross( outer.c[0]->w-projection,
- outer.c[1]->w-projection).length();
- const b3Scalar sum=m_result.p[0]+m_result.p[1]+m_result.p[2];
- m_result.p[0] /= sum;
- m_result.p[1] /= sum;
- m_result.p[2] /= sum;
- return(m_status);
- }
- }
- /* Fallback */
- m_status = eStatus::FallBack;
- m_normal = -guess;
- const b3Scalar nl=m_normal.length();
- if(nl>0)
- m_normal = m_normal/nl;
- else
- m_normal = b3MakeVector3(1,0,0);
- m_depth = 0;
- m_result.rank=1;
- m_result.c[0]=simplex.c[0];
- m_result.p[0]=1;
- return(m_status);
- }
- bool getedgedist(sFace* face, sSV* a, sSV* b, b3Scalar& dist)
- {
- const b3Vector3 ba = b->w - a->w;
- const b3Vector3 n_ab = b3Cross(ba, face->n); // Outward facing edge normal direction, on triangle plane
- const b3Scalar a_dot_nab = b3Dot(a->w, n_ab); // Only care about the sign to determine inside/outside, so not normalization required
-
- if(a_dot_nab < 0)
- {
- // Outside of edge a->b
-
- const b3Scalar ba_l2 = ba.length2();
- const b3Scalar a_dot_ba = b3Dot(a->w, ba);
- const b3Scalar b_dot_ba = b3Dot(b->w, ba);
-
- if(a_dot_ba > 0)
- {
- // Pick distance vertex a
- dist = a->w.length();
- }
- else if(b_dot_ba < 0)
- {
- // Pick distance vertex b
- dist = b->w.length();
}
else
{
- // Pick distance to edge a->b
- const b3Scalar a_dot_b = b3Dot(a->w, b->w);
- dist = b3Sqrt(b3Max((a->w.length2() * b->w.length2() - a_dot_b * a_dot_b) / ba_l2, (b3Scalar)0));
+ m_status = eStatus::OutOfVertices;
+ break;
}
-
- return true;
}
+ const b3Vector3 projection = outer.n * outer.d;
+ m_normal = outer.n;
+ m_depth = outer.d;
+ m_result.rank = 3;
+ m_result.c[0] = outer.c[0];
+ m_result.c[1] = outer.c[1];
+ m_result.c[2] = outer.c[2];
+ m_result.p[0] = b3Cross(outer.c[1]->w - projection,
+ outer.c[2]->w - projection)
+ .length();
+ m_result.p[1] = b3Cross(outer.c[2]->w - projection,
+ outer.c[0]->w - projection)
+ .length();
+ m_result.p[2] = b3Cross(outer.c[0]->w - projection,
+ outer.c[1]->w - projection)
+ .length();
+ const b3Scalar sum = m_result.p[0] + m_result.p[1] + m_result.p[2];
+ m_result.p[0] /= sum;
+ m_result.p[1] /= sum;
+ m_result.p[2] /= sum;
+ return (m_status);
+ }
+ }
+ /* Fallback */
+ m_status = eStatus::FallBack;
+ m_normal = -guess;
+ const b3Scalar nl = m_normal.length();
+ if (nl > 0)
+ m_normal = m_normal / nl;
+ else
+ m_normal = b3MakeVector3(1, 0, 0);
+ m_depth = 0;
+ m_result.rank = 1;
+ m_result.c[0] = simplex.c[0];
+ m_result.p[0] = 1;
+ return (m_status);
+ }
+ bool getedgedist(sFace* face, sSV* a, sSV* b, b3Scalar& dist)
+ {
+ const b3Vector3 ba = b->w - a->w;
+ const b3Vector3 n_ab = b3Cross(ba, face->n); // Outward facing edge normal direction, on triangle plane
+ const b3Scalar a_dot_nab = b3Dot(a->w, n_ab); // Only care about the sign to determine inside/outside, so not normalization required
+
+ if (a_dot_nab < 0)
+ {
+ // Outside of edge a->b
+
+ const b3Scalar ba_l2 = ba.length2();
+ const b3Scalar a_dot_ba = b3Dot(a->w, ba);
+ const b3Scalar b_dot_ba = b3Dot(b->w, ba);
- return false;
+ if (a_dot_ba > 0)
+ {
+ // Pick distance vertex a
+ dist = a->w.length();
}
- sFace* newface(sSV* a,sSV* b,sSV* c,bool forced)
+ else if (b_dot_ba < 0)
{
- if(m_stock.root)
- {
- sFace* face=m_stock.root;
- remove(m_stock,face);
- append(m_hull,face);
- face->pass = 0;
- face->c[0] = a;
- face->c[1] = b;
- face->c[2] = c;
- face->n = b3Cross(b->w-a->w,c->w-a->w);
- const b3Scalar l=face->n.length();
- const bool v=l>EPA_ACCURACY;
-
- if(v)
- {
- if(!(getedgedist(face, a, b, face->d) ||
- getedgedist(face, b, c, face->d) ||
- getedgedist(face, c, a, face->d)))
- {
- // Origin projects to the interior of the triangle
- // Use distance to triangle plane
- face->d = b3Dot(a->w, face->n) / l;
- }
+ // Pick distance vertex b
+ dist = b->w.length();
+ }
+ else
+ {
+ // Pick distance to edge a->b
+ const b3Scalar a_dot_b = b3Dot(a->w, b->w);
+ dist = b3Sqrt(b3Max((a->w.length2() * b->w.length2() - a_dot_b * a_dot_b) / ba_l2, (b3Scalar)0));
+ }
- face->n /= l;
- if(forced || (face->d >= -EPA_PLANE_EPS))
- {
- return face;
- }
- else
- m_status=eStatus::NonConvex;
- }
- else
- m_status=eStatus::Degenerated;
+ return true;
+ }
- remove(m_hull, face);
- append(m_stock, face);
- return 0;
+ return false;
+ }
+ sFace* newface(sSV* a, sSV* b, sSV* c, bool forced)
+ {
+ if (m_stock.root)
+ {
+ sFace* face = m_stock.root;
+ remove(m_stock, face);
+ append(m_hull, face);
+ face->pass = 0;
+ face->c[0] = a;
+ face->c[1] = b;
+ face->c[2] = c;
+ face->n = b3Cross(b->w - a->w, c->w - a->w);
+ const b3Scalar l = face->n.length();
+ const bool v = l > EPA_ACCURACY;
+ if (v)
+ {
+ if (!(getedgedist(face, a, b, face->d) ||
+ getedgedist(face, b, c, face->d) ||
+ getedgedist(face, c, a, face->d)))
+ {
+ // Origin projects to the interior of the triangle
+ // Use distance to triangle plane
+ face->d = b3Dot(a->w, face->n) / l;
}
- m_status = m_stock.root ? eStatus::OutOfVertices : eStatus::OutOfFaces;
- return 0;
+
+ face->n /= l;
+ if (forced || (face->d >= -EPA_PLANE_EPS))
+ {
+ return face;
+ }
+ else
+ m_status = eStatus::NonConvex;
}
- sFace* findbest()
+ else
+ m_status = eStatus::Degenerated;
+
+ remove(m_hull, face);
+ append(m_stock, face);
+ return 0;
+ }
+ m_status = m_stock.root ? eStatus::OutOfVertices : eStatus::OutOfFaces;
+ return 0;
+ }
+ sFace* findbest()
+ {
+ sFace* minf = m_hull.root;
+ b3Scalar mind = minf->d * minf->d;
+ for (sFace* f = minf->l[1]; f; f = f->l[1])
+ {
+ const b3Scalar sqd = f->d * f->d;
+ if (sqd < mind)
{
- sFace* minf=m_hull.root;
- b3Scalar mind=minf->d*minf->d;
- for(sFace* f=minf->l[1];f;f=f->l[1])
+ minf = f;
+ mind = sqd;
+ }
+ }
+ return (minf);
+ }
+ bool expand(unsigned int pass, sSV* w, sFace* f, unsigned int e, sHorizon& horizon)
+ {
+ static const unsigned int i1m3[] = {1, 2, 0};
+ static const unsigned int i2m3[] = {2, 0, 1};
+ if (f->pass != pass)
+ {
+ const unsigned int e1 = i1m3[e];
+ if ((b3Dot(f->n, w->w) - f->d) < -EPA_PLANE_EPS)
+ {
+ sFace* nf = newface(f->c[e1], f->c[e], w, false);
+ if (nf)
{
- const b3Scalar sqd=f->d*f->d;
- if(sqd<mind)
- {
- minf=f;
- mind=sqd;
- }
+ bind(nf, 0, f, e);
+ if (horizon.cf)
+ bind(horizon.cf, 1, nf, 2);
+ else
+ horizon.ff = nf;
+ horizon.cf = nf;
+ ++horizon.nf;
+ return (true);
}
- return(minf);
}
- bool expand(unsigned int pass,sSV* w,sFace* f,unsigned int e,sHorizon& horizon)
+ else
{
- static const unsigned int i1m3[]={1,2,0};
- static const unsigned int i2m3[]={2,0,1};
- if(f->pass!=pass)
+ const unsigned int e2 = i2m3[e];
+ f->pass = (unsigned char)pass;
+ if (expand(pass, w, f->f[e1], f->e[e1], horizon) &&
+ expand(pass, w, f->f[e2], f->e[e2], horizon))
{
- const unsigned int e1=i1m3[e];
- if((b3Dot(f->n,w->w)-f->d)<-EPA_PLANE_EPS)
- {
- sFace* nf=newface(f->c[e1],f->c[e],w,false);
- if(nf)
- {
- bind(nf,0,f,e);
- if(horizon.cf) bind(horizon.cf,1,nf,2); else horizon.ff=nf;
- horizon.cf=nf;
- ++horizon.nf;
- return(true);
- }
- }
- else
- {
- const unsigned int e2=i2m3[e];
- f->pass = (unsigned char)pass;
- if( expand(pass,w,f->f[e1],f->e[e1],horizon)&&
- expand(pass,w,f->f[e2],f->e[e2],horizon))
- {
- remove(m_hull,f);
- append(m_stock,f);
- return(true);
- }
- }
+ remove(m_hull, f);
+ append(m_stock, f);
+ return (true);
}
- return(false);
}
-
- };
-
- //
- static void Initialize(const b3Transform& transA, const b3Transform& transB,
- const b3ConvexPolyhedronData* hullA, const b3ConvexPolyhedronData* hullB,
- const b3AlignedObjectArray<b3Vector3>& verticesA,
- const b3AlignedObjectArray<b3Vector3>& verticesB,
- b3GjkEpaSolver2::sResults& results,
- tShape& shape,
- bool withmargins)
- {
- /* Results */
- results.witnesses[0] =
- results.witnesses[1] = b3MakeVector3(0,0,0);
- results.status = b3GjkEpaSolver2::sResults::Separated;
- /* Shape */
- shape.m_shapes[0] = hullA;
- shape.m_shapes[1] = hullB;
- shape.m_toshape1 = transB.getBasis().transposeTimes(transA.getBasis());
- shape.m_toshape0 = transA.inverseTimes(transB);
- shape.EnableMargin(withmargins);
+ }
+ return (false);
}
+};
+//
+static void Initialize(const b3Transform& transA, const b3Transform& transB,
+ const b3ConvexPolyhedronData* hullA, const b3ConvexPolyhedronData* hullB,
+ const b3AlignedObjectArray<b3Vector3>& verticesA,
+ const b3AlignedObjectArray<b3Vector3>& verticesB,
+ b3GjkEpaSolver2::sResults& results,
+ tShape& shape,
+ bool withmargins)
+{
+ /* Results */
+ results.witnesses[0] =
+ results.witnesses[1] = b3MakeVector3(0, 0, 0);
+ results.status = b3GjkEpaSolver2::sResults::Separated;
+ /* Shape */
+ shape.m_shapes[0] = hullA;
+ shape.m_shapes[1] = hullB;
+ shape.m_toshape1 = transB.getBasis().transposeTimes(transA.getBasis());
+ shape.m_toshape0 = transA.inverseTimes(transB);
+ shape.EnableMargin(withmargins);
}
+} // namespace gjkepa2_impl2
+
//
// Api
//
-using namespace gjkepa2_impl2;
+using namespace gjkepa2_impl2;
//
-int b3GjkEpaSolver2::StackSizeRequirement()
+int b3GjkEpaSolver2::StackSizeRequirement()
{
- return(sizeof(b3GJK)+sizeof(b3EPA));
+ return (sizeof(b3GJK) + sizeof(b3EPA));
}
//
-bool b3GjkEpaSolver2::Distance( const b3Transform& transA, const b3Transform& transB,
- const b3ConvexPolyhedronData* hullA, const b3ConvexPolyhedronData* hullB,
- const b3AlignedObjectArray<b3Vector3>& verticesA,
- const b3AlignedObjectArray<b3Vector3>& verticesB,
- const b3Vector3& guess,
- sResults& results)
+bool b3GjkEpaSolver2::Distance(const b3Transform& transA, const b3Transform& transB,
+ const b3ConvexPolyhedronData* hullA, const b3ConvexPolyhedronData* hullB,
+ const b3AlignedObjectArray<b3Vector3>& verticesA,
+ const b3AlignedObjectArray<b3Vector3>& verticesB,
+ const b3Vector3& guess,
+ sResults& results)
{
- tShape shape;
- Initialize(transA,transB,hullA,hullB,verticesA,verticesB,results,shape,false);
- b3GJK gjk(verticesA,verticesB);
- b3GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,guess);
- if(gjk_status==b3GJK::eStatus::Valid)
+ tShape shape;
+ Initialize(transA, transB, hullA, hullB, verticesA, verticesB, results, shape, false);
+ b3GJK gjk(verticesA, verticesB);
+ b3GJK::eStatus::_ gjk_status = gjk.Evaluate(shape, guess);
+ if (gjk_status == b3GJK::eStatus::Valid)
{
- b3Vector3 w0=b3MakeVector3(0,0,0);
- b3Vector3 w1=b3MakeVector3(0,0,0);
- for(unsigned int i=0;i<gjk.m_simplex->rank;++i)
+ b3Vector3 w0 = b3MakeVector3(0, 0, 0);
+ b3Vector3 w1 = b3MakeVector3(0, 0, 0);
+ for (unsigned int i = 0; i < gjk.m_simplex->rank; ++i)
{
- const b3Scalar p=gjk.m_simplex->p[i];
- w0+=shape.Support( gjk.m_simplex->c[i]->d,0,verticesA,verticesB)*p;
- w1+=shape.Support(-gjk.m_simplex->c[i]->d,1,verticesA,verticesB)*p;
+ const b3Scalar p = gjk.m_simplex->p[i];
+ w0 += shape.Support(gjk.m_simplex->c[i]->d, 0, verticesA, verticesB) * p;
+ w1 += shape.Support(-gjk.m_simplex->c[i]->d, 1, verticesA, verticesB) * p;
}
- results.witnesses[0] = transA*w0;
- results.witnesses[1] = transA*w1;
- results.normal = w0-w1;
- results.distance = results.normal.length();
- results.normal /= results.distance>GJK_MIN_DISTANCE?results.distance:1;
- return(true);
+ results.witnesses[0] = transA * w0;
+ results.witnesses[1] = transA * w1;
+ results.normal = w0 - w1;
+ results.distance = results.normal.length();
+ results.normal /= results.distance > GJK_MIN_DISTANCE ? results.distance : 1;
+ return (true);
}
else
{
- results.status = gjk_status==b3GJK::eStatus::Inside?
- sResults::Penetrating :
- sResults::GJK_Failed ;
- return(false);
+ results.status = gjk_status == b3GJK::eStatus::Inside ? sResults::Penetrating : sResults::GJK_Failed;
+ return (false);
}
}
//
-bool b3GjkEpaSolver2::Penetration( const b3Transform& transA, const b3Transform& transB,
- const b3ConvexPolyhedronData* hullA, const b3ConvexPolyhedronData* hullB,
- const b3AlignedObjectArray<b3Vector3>& verticesA,
- const b3AlignedObjectArray<b3Vector3>& verticesB,
- const b3Vector3& guess,
- sResults& results,
- bool usemargins)
+bool b3GjkEpaSolver2::Penetration(const b3Transform& transA, const b3Transform& transB,
+ const b3ConvexPolyhedronData* hullA, const b3ConvexPolyhedronData* hullB,
+ const b3AlignedObjectArray<b3Vector3>& verticesA,
+ const b3AlignedObjectArray<b3Vector3>& verticesB,
+ const b3Vector3& guess,
+ sResults& results,
+ bool usemargins)
{
-
- tShape shape;
- Initialize(transA,transB,hullA,hullB,verticesA,verticesB,results,shape,usemargins);
- b3GJK gjk(verticesA,verticesB);
- b3GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,guess);
- switch(gjk_status)
+ tShape shape;
+ Initialize(transA, transB, hullA, hullB, verticesA, verticesB, results, shape, usemargins);
+ b3GJK gjk(verticesA, verticesB);
+ b3GJK::eStatus::_ gjk_status = gjk.Evaluate(shape, guess);
+ switch (gjk_status)
{
- case b3GJK::eStatus::Inside:
+ case b3GJK::eStatus::Inside:
{
- b3EPA epa;
- b3EPA::eStatus::_ epa_status=epa.Evaluate(gjk,-guess);
- if(epa_status!=b3EPA::eStatus::Failed)
+ b3EPA epa;
+ b3EPA::eStatus::_ epa_status = epa.Evaluate(gjk, -guess);
+ if (epa_status != b3EPA::eStatus::Failed)
{
- b3Vector3 w0=b3MakeVector3(0,0,0);
- for(unsigned int i=0;i<epa.m_result.rank;++i)
+ b3Vector3 w0 = b3MakeVector3(0, 0, 0);
+ for (unsigned int i = 0; i < epa.m_result.rank; ++i)
{
- w0+=shape.Support(epa.m_result.c[i]->d,0,verticesA,verticesB)*epa.m_result.p[i];
+ w0 += shape.Support(epa.m_result.c[i]->d, 0, verticesA, verticesB) * epa.m_result.p[i];
}
- results.status = sResults::Penetrating;
- results.witnesses[0] = transA*w0;
- results.witnesses[1] = transA*(w0-epa.m_normal*epa.m_depth);
- results.normal = -epa.m_normal;
- results.distance = -epa.m_depth;
- return(true);
- } else results.status=sResults::EPA_Failed;
+ results.status = sResults::Penetrating;
+ results.witnesses[0] = transA * w0;
+ results.witnesses[1] = transA * (w0 - epa.m_normal * epa.m_depth);
+ results.normal = -epa.m_normal;
+ results.distance = -epa.m_depth;
+ return (true);
+ }
+ else
+ results.status = sResults::EPA_Failed;
}
break;
- case b3GJK::eStatus::Failed:
- results.status=sResults::GJK_Failed;
- break;
+ case b3GJK::eStatus::Failed:
+ results.status = sResults::GJK_Failed;
+ break;
default:
- {
- }
+ {
+ }
}
- return(false);
+ return (false);
}
-
#if 0
//
b3Scalar b3GjkEpaSolver2::SignedDistance(const b3Vector3& position,
@@ -994,8 +1043,7 @@ bool b3GjkEpaSolver2::SignedDistance(const btConvexShape* shape0,
}
#endif
-
-/* Symbols cleanup */
+/* Symbols cleanup */
#undef GJK_MAX_ITERATIONS
#undef GJK_ACCURACY
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3GjkEpa.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3GjkEpa.h
index 976238a04c..7db32c6309 100644
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3GjkEpa.h
+++ b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3GjkEpa.h
@@ -29,40 +29,39 @@ GJK-EPA collision solver by Nathanael Presson, 2008
#include "Bullet3Common/b3Transform.h"
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
-
///btGjkEpaSolver contributed under zlib by Nathanael Presson
-struct b3GjkEpaSolver2
+struct b3GjkEpaSolver2
{
-struct sResults
+ struct sResults
{
- enum eStatus
+ enum eStatus
{
- Separated, /* Shapes doesnt penetrate */
- Penetrating, /* Shapes are penetrating */
- GJK_Failed, /* GJK phase fail, no big issue, shapes are probably just 'touching' */
- EPA_Failed /* EPA phase fail, bigger problem, need to save parameters, and debug */
- } status;
- b3Vector3 witnesses[2];
- b3Vector3 normal;
- b3Scalar distance;
+ Separated, /* Shapes doesnt penetrate */
+ Penetrating, /* Shapes are penetrating */
+ GJK_Failed, /* GJK phase fail, no big issue, shapes are probably just 'touching' */
+ EPA_Failed /* EPA phase fail, bigger problem, need to save parameters, and debug */
+ } status;
+ b3Vector3 witnesses[2];
+ b3Vector3 normal;
+ b3Scalar distance;
};
-static int StackSizeRequirement();
+ static int StackSizeRequirement();
-static bool Distance( const b3Transform& transA, const b3Transform& transB,
- const b3ConvexPolyhedronData* hullA, const b3ConvexPolyhedronData* hullB,
- const b3AlignedObjectArray<b3Vector3>& verticesA,
- const b3AlignedObjectArray<b3Vector3>& verticesB,
- const b3Vector3& guess,
- sResults& results);
+ static bool Distance(const b3Transform& transA, const b3Transform& transB,
+ const b3ConvexPolyhedronData* hullA, const b3ConvexPolyhedronData* hullB,
+ const b3AlignedObjectArray<b3Vector3>& verticesA,
+ const b3AlignedObjectArray<b3Vector3>& verticesB,
+ const b3Vector3& guess,
+ sResults& results);
-static bool Penetration( const b3Transform& transA, const b3Transform& transB,
- const b3ConvexPolyhedronData* hullA, const b3ConvexPolyhedronData* hullB,
+ static bool Penetration(const b3Transform& transA, const b3Transform& transB,
+ const b3ConvexPolyhedronData* hullA, const b3ConvexPolyhedronData* hullB,
const b3AlignedObjectArray<b3Vector3>& verticesA,
const b3AlignedObjectArray<b3Vector3>& verticesB,
const b3Vector3& guess,
sResults& results,
- bool usemargins=true);
+ bool usemargins = true);
#if 0
static b3Scalar SignedDistance( const b3Vector3& position,
b3Scalar margin,
@@ -74,9 +73,7 @@ static bool SignedDistance( const btConvexShape* shape0,const btTransform& wtrs
const btConvexShape* shape1,const btTransform& wtrs1,
const b3Vector3& guess,
sResults& results);
-#endif
-
+#endif
};
-#endif //B3_GJK_EPA2_H
-
+#endif //B3_GJK_EPA2_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3OptimizedBvh.cpp b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3OptimizedBvh.cpp
index e9e51d5a36..6f2c5251a0 100644
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3OptimizedBvh.cpp
+++ b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3OptimizedBvh.cpp
@@ -13,50 +13,45 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#include "b3OptimizedBvh.h"
#include "b3StridingMeshInterface.h"
#include "Bullet3Geometry/b3AabbUtil.h"
-
b3OptimizedBvh::b3OptimizedBvh()
-{
+{
}
b3OptimizedBvh::~b3OptimizedBvh()
{
}
-
void b3OptimizedBvh::build(b3StridingMeshInterface* triangles, bool useQuantizedAabbCompression, const b3Vector3& bvhAabbMin, const b3Vector3& bvhAabbMax)
{
m_useQuantization = useQuantizedAabbCompression;
-
// NodeArray triangleNodes;
- struct NodeTriangleCallback : public b3InternalTriangleIndexCallback
+ struct NodeTriangleCallback : public b3InternalTriangleIndexCallback
{
-
- NodeArray& m_triangleNodes;
+ NodeArray& m_triangleNodes;
NodeTriangleCallback& operator=(NodeTriangleCallback& other)
{
m_triangleNodes.copyFromArray(other.m_triangleNodes);
return *this;
}
-
- NodeTriangleCallback(NodeArray& triangleNodes)
- :m_triangleNodes(triangleNodes)
+
+ NodeTriangleCallback(NodeArray& triangleNodes)
+ : m_triangleNodes(triangleNodes)
{
}
- virtual void internalProcessTriangleIndex(b3Vector3* triangle,int partId,int triangleIndex)
+ virtual void internalProcessTriangleIndex(b3Vector3* triangle, int partId, int triangleIndex)
{
b3OptimizedBvhNode node;
- b3Vector3 aabbMin,aabbMax;
- aabbMin.setValue(b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT));
- aabbMax.setValue(b3Scalar(-B3_LARGE_FLOAT),b3Scalar(-B3_LARGE_FLOAT),b3Scalar(-B3_LARGE_FLOAT));
+ b3Vector3 aabbMin, aabbMax;
+ aabbMin.setValue(b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT));
+ aabbMax.setValue(b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT));
aabbMin.setMin(triangle[0]);
aabbMax.setMax(triangle[0]);
aabbMin.setMin(triangle[1]);
@@ -69,17 +64,17 @@ void b3OptimizedBvh::build(b3StridingMeshInterface* triangles, bool useQuantized
node.m_aabbMaxOrg = aabbMax;
node.m_escapeIndex = -1;
-
+
//for child nodes
node.m_subPart = partId;
node.m_triangleIndex = triangleIndex;
m_triangleNodes.push_back(node);
}
};
- struct QuantizedNodeTriangleCallback : public b3InternalTriangleIndexCallback
+ struct QuantizedNodeTriangleCallback : public b3InternalTriangleIndexCallback
{
- QuantizedNodeArray& m_triangleNodes;
- const b3QuantizedBvh* m_optimizedTree; // for quantization
+ QuantizedNodeArray& m_triangleNodes;
+ const b3QuantizedBvh* m_optimizedTree; // for quantization
QuantizedNodeTriangleCallback& operator=(QuantizedNodeTriangleCallback& other)
{
@@ -88,23 +83,23 @@ void b3OptimizedBvh::build(b3StridingMeshInterface* triangles, bool useQuantized
return *this;
}
- QuantizedNodeTriangleCallback(QuantizedNodeArray& triangleNodes,const b3QuantizedBvh* tree)
- :m_triangleNodes(triangleNodes),m_optimizedTree(tree)
+ QuantizedNodeTriangleCallback(QuantizedNodeArray& triangleNodes, const b3QuantizedBvh* tree)
+ : m_triangleNodes(triangleNodes), m_optimizedTree(tree)
{
}
- virtual void internalProcessTriangleIndex(b3Vector3* triangle,int partId,int triangleIndex)
+ virtual void internalProcessTriangleIndex(b3Vector3* triangle, int partId, int triangleIndex)
{
// The partId and triangle index must fit in the same (positive) integer
- b3Assert(partId < (1<<MAX_NUM_PARTS_IN_BITS));
- b3Assert(triangleIndex < (1<<(31-MAX_NUM_PARTS_IN_BITS)));
+ b3Assert(partId < (1 << MAX_NUM_PARTS_IN_BITS));
+ b3Assert(triangleIndex < (1 << (31 - MAX_NUM_PARTS_IN_BITS)));
//negative indices are reserved for escapeIndex
- b3Assert(triangleIndex>=0);
+ b3Assert(triangleIndex >= 0);
b3QuantizedBvhNode node;
- b3Vector3 aabbMin,aabbMax;
- aabbMin.setValue(b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT));
- aabbMax.setValue(b3Scalar(-B3_LARGE_FLOAT),b3Scalar(-B3_LARGE_FLOAT),b3Scalar(-B3_LARGE_FLOAT));
+ b3Vector3 aabbMin, aabbMax;
+ aabbMin.setValue(b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT));
+ aabbMax.setValue(b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT));
aabbMin.setMin(triangle[0]);
aabbMax.setMax(triangle[0]);
aabbMin.setMin(triangle[1]);
@@ -131,59 +126,52 @@ void b3OptimizedBvh::build(b3StridingMeshInterface* triangles, bool useQuantized
aabbMin.setZ(aabbMin.getZ() - MIN_AABB_HALF_DIMENSION);
}
- m_optimizedTree->quantize(&node.m_quantizedAabbMin[0],aabbMin,0);
- m_optimizedTree->quantize(&node.m_quantizedAabbMax[0],aabbMax,1);
+ m_optimizedTree->quantize(&node.m_quantizedAabbMin[0], aabbMin, 0);
+ m_optimizedTree->quantize(&node.m_quantizedAabbMax[0], aabbMax, 1);
- node.m_escapeIndexOrTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | triangleIndex;
+ node.m_escapeIndexOrTriangleIndex = (partId << (31 - MAX_NUM_PARTS_IN_BITS)) | triangleIndex;
m_triangleNodes.push_back(node);
}
};
-
-
int numLeafNodes = 0;
-
if (m_useQuantization)
{
-
//initialize quantization values
- setQuantizationValues(bvhAabbMin,bvhAabbMax);
+ setQuantizationValues(bvhAabbMin, bvhAabbMax);
- QuantizedNodeTriangleCallback callback(m_quantizedLeafNodes,this);
+ QuantizedNodeTriangleCallback callback(m_quantizedLeafNodes, this);
-
- triangles->InternalProcessAllTriangles(&callback,m_bvhAabbMin,m_bvhAabbMax);
+ triangles->InternalProcessAllTriangles(&callback, m_bvhAabbMin, m_bvhAabbMax);
//now we have an array of leafnodes in m_leafNodes
numLeafNodes = m_quantizedLeafNodes.size();
-
- m_quantizedContiguousNodes.resize(2*numLeafNodes);
-
-
- } else
+ m_quantizedContiguousNodes.resize(2 * numLeafNodes);
+ }
+ else
{
- NodeTriangleCallback callback(m_leafNodes);
+ NodeTriangleCallback callback(m_leafNodes);
- b3Vector3 aabbMin=b3MakeVector3(b3Scalar(-B3_LARGE_FLOAT),b3Scalar(-B3_LARGE_FLOAT),b3Scalar(-B3_LARGE_FLOAT));
- b3Vector3 aabbMax=b3MakeVector3(b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT));
+ b3Vector3 aabbMin = b3MakeVector3(b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT));
+ b3Vector3 aabbMax = b3MakeVector3(b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT));
- triangles->InternalProcessAllTriangles(&callback,aabbMin,aabbMax);
+ triangles->InternalProcessAllTriangles(&callback, aabbMin, aabbMax);
//now we have an array of leafnodes in m_leafNodes
numLeafNodes = m_leafNodes.size();
- m_contiguousNodes.resize(2*numLeafNodes);
+ m_contiguousNodes.resize(2 * numLeafNodes);
}
m_curNodeIndex = 0;
- buildTree(0,numLeafNodes);
+ buildTree(0, numLeafNodes);
///if the entire tree is small then subtree size, we need to create a header info for the tree
- if(m_useQuantization && !m_SubtreeHeaders.size())
+ if (m_useQuantization && !m_SubtreeHeaders.size())
{
b3BvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[0]);
@@ -199,37 +187,29 @@ void b3OptimizedBvh::build(b3StridingMeshInterface* triangles, bool useQuantized
m_leafNodes.clear();
}
-
-
-
-void b3OptimizedBvh::refit(b3StridingMeshInterface* meshInterface,const b3Vector3& aabbMin,const b3Vector3& aabbMax)
+void b3OptimizedBvh::refit(b3StridingMeshInterface* meshInterface, const b3Vector3& aabbMin, const b3Vector3& aabbMax)
{
if (m_useQuantization)
{
+ setQuantizationValues(aabbMin, aabbMax);
- setQuantizationValues(aabbMin,aabbMax);
-
- updateBvhNodes(meshInterface,0,m_curNodeIndex,0);
+ updateBvhNodes(meshInterface, 0, m_curNodeIndex, 0);
///now update all subtree headers
int i;
- for (i=0;i<m_SubtreeHeaders.size();i++)
+ for (i = 0; i < m_SubtreeHeaders.size(); i++)
{
b3BvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[subtree.m_rootNodeIndex]);
}
-
- } else
+ }
+ else
{
-
}
}
-
-
-
-void b3OptimizedBvh::refitPartial(b3StridingMeshInterface* meshInterface,const b3Vector3& aabbMin,const b3Vector3& aabbMax)
+void b3OptimizedBvh::refitPartial(b3StridingMeshInterface* meshInterface, const b3Vector3& aabbMin, const b3Vector3& aabbMax)
{
//incrementally initialize quantization values
b3Assert(m_useQuantization);
@@ -244,147 +224,135 @@ void b3OptimizedBvh::refitPartial(b3StridingMeshInterface* meshInterface,const b
///we should update all quantization values, using updateBvhNodes(meshInterface);
///but we only update chunks that overlap the given aabb
-
- unsigned short quantizedQueryAabbMin[3];
- unsigned short quantizedQueryAabbMax[3];
- quantize(&quantizedQueryAabbMin[0],aabbMin,0);
- quantize(&quantizedQueryAabbMax[0],aabbMax,1);
+ unsigned short quantizedQueryAabbMin[3];
+ unsigned short quantizedQueryAabbMax[3];
+
+ quantize(&quantizedQueryAabbMin[0], aabbMin, 0);
+ quantize(&quantizedQueryAabbMax[0], aabbMax, 1);
int i;
- for (i=0;i<this->m_SubtreeHeaders.size();i++)
+ for (i = 0; i < this->m_SubtreeHeaders.size(); i++)
{
b3BvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
//PCK: unsigned instead of bool
- unsigned overlap = b3TestQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax);
+ unsigned overlap = b3TestQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin, quantizedQueryAabbMax, subtree.m_quantizedAabbMin, subtree.m_quantizedAabbMax);
if (overlap != 0)
{
- updateBvhNodes(meshInterface,subtree.m_rootNodeIndex,subtree.m_rootNodeIndex+subtree.m_subtreeSize,i);
+ updateBvhNodes(meshInterface, subtree.m_rootNodeIndex, subtree.m_rootNodeIndex + subtree.m_subtreeSize, i);
subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[subtree.m_rootNodeIndex]);
}
}
-
}
-void b3OptimizedBvh::updateBvhNodes(b3StridingMeshInterface* meshInterface,int firstNode,int endNode,int index)
+void b3OptimizedBvh::updateBvhNodes(b3StridingMeshInterface* meshInterface, int firstNode, int endNode, int index)
{
(void)index;
b3Assert(m_useQuantization);
- int curNodeSubPart=-1;
+ int curNodeSubPart = -1;
//get access info to trianglemesh data
- const unsigned char *vertexbase = 0;
- int numverts = 0;
- PHY_ScalarType type = PHY_INTEGER;
- int stride = 0;
- const unsigned char *indexbase = 0;
- int indexstride = 0;
- int numfaces = 0;
- PHY_ScalarType indicestype = PHY_INTEGER;
-
- b3Vector3 triangleVerts[3];
- b3Vector3 aabbMin,aabbMax;
- const b3Vector3& meshScaling = meshInterface->getScaling();
-
- int i;
- for (i=endNode-1;i>=firstNode;i--)
+ const unsigned char* vertexbase = 0;
+ int numverts = 0;
+ PHY_ScalarType type = PHY_INTEGER;
+ int stride = 0;
+ const unsigned char* indexbase = 0;
+ int indexstride = 0;
+ int numfaces = 0;
+ PHY_ScalarType indicestype = PHY_INTEGER;
+
+ b3Vector3 triangleVerts[3];
+ b3Vector3 aabbMin, aabbMax;
+ const b3Vector3& meshScaling = meshInterface->getScaling();
+
+ int i;
+ for (i = endNode - 1; i >= firstNode; i--)
+ {
+ b3QuantizedBvhNode& curNode = m_quantizedContiguousNodes[i];
+ if (curNode.isLeafNode())
{
+ //recalc aabb from triangle data
+ int nodeSubPart = curNode.getPartId();
+ int nodeTriangleIndex = curNode.getTriangleIndex();
+ if (nodeSubPart != curNodeSubPart)
+ {
+ if (curNodeSubPart >= 0)
+ meshInterface->unLockReadOnlyVertexBase(curNodeSubPart);
+ meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase, numverts, type, stride, &indexbase, indexstride, numfaces, indicestype, nodeSubPart);
+ curNodeSubPart = nodeSubPart;
+ b3Assert(indicestype == PHY_INTEGER || indicestype == PHY_SHORT);
+ }
+ //triangles->getLockedReadOnlyVertexIndexBase(vertexBase,numVerts,
- b3QuantizedBvhNode& curNode = m_quantizedContiguousNodes[i];
- if (curNode.isLeafNode())
+ unsigned int* gfxbase = (unsigned int*)(indexbase + nodeTriangleIndex * indexstride);
+
+ for (int j = 2; j >= 0; j--)
{
- //recalc aabb from triangle data
- int nodeSubPart = curNode.getPartId();
- int nodeTriangleIndex = curNode.getTriangleIndex();
- if (nodeSubPart != curNodeSubPart)
+ int graphicsindex = indicestype == PHY_SHORT ? ((unsigned short*)gfxbase)[j] : gfxbase[j];
+ if (type == PHY_FLOAT)
{
- if (curNodeSubPart >= 0)
- meshInterface->unLockReadOnlyVertexBase(curNodeSubPart);
- meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase,numverts, type,stride,&indexbase,indexstride,numfaces,indicestype,nodeSubPart);
-
- curNodeSubPart = nodeSubPart;
- b3Assert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
+ float* graphicsbase = (float*)(vertexbase + graphicsindex * stride);
+ triangleVerts[j] = b3MakeVector3(
+ graphicsbase[0] * meshScaling.getX(),
+ graphicsbase[1] * meshScaling.getY(),
+ graphicsbase[2] * meshScaling.getZ());
}
- //triangles->getLockedReadOnlyVertexIndexBase(vertexBase,numVerts,
-
- unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
-
-
- for (int j=2;j>=0;j--)
+ else
{
-
- int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
- if (type == PHY_FLOAT)
- {
- float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
- triangleVerts[j] = b3MakeVector3(
- graphicsbase[0]*meshScaling.getX(),
- graphicsbase[1]*meshScaling.getY(),
- graphicsbase[2]*meshScaling.getZ());
- }
- else
- {
- double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
- triangleVerts[j] = b3MakeVector3( b3Scalar(graphicsbase[0]*meshScaling.getX()), b3Scalar(graphicsbase[1]*meshScaling.getY()), b3Scalar(graphicsbase[2]*meshScaling.getZ()));
- }
+ double* graphicsbase = (double*)(vertexbase + graphicsindex * stride);
+ triangleVerts[j] = b3MakeVector3(b3Scalar(graphicsbase[0] * meshScaling.getX()), b3Scalar(graphicsbase[1] * meshScaling.getY()), b3Scalar(graphicsbase[2] * meshScaling.getZ()));
}
+ }
+ aabbMin.setValue(b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT));
+ aabbMax.setValue(b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT));
+ aabbMin.setMin(triangleVerts[0]);
+ aabbMax.setMax(triangleVerts[0]);
+ aabbMin.setMin(triangleVerts[1]);
+ aabbMax.setMax(triangleVerts[1]);
+ aabbMin.setMin(triangleVerts[2]);
+ aabbMax.setMax(triangleVerts[2]);
+
+ quantize(&curNode.m_quantizedAabbMin[0], aabbMin, 0);
+ quantize(&curNode.m_quantizedAabbMax[0], aabbMax, 1);
+ }
+ else
+ {
+ //combine aabb from both children
-
- aabbMin.setValue(b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT));
- aabbMax.setValue(b3Scalar(-B3_LARGE_FLOAT),b3Scalar(-B3_LARGE_FLOAT),b3Scalar(-B3_LARGE_FLOAT));
- aabbMin.setMin(triangleVerts[0]);
- aabbMax.setMax(triangleVerts[0]);
- aabbMin.setMin(triangleVerts[1]);
- aabbMax.setMax(triangleVerts[1]);
- aabbMin.setMin(triangleVerts[2]);
- aabbMax.setMax(triangleVerts[2]);
-
- quantize(&curNode.m_quantizedAabbMin[0],aabbMin,0);
- quantize(&curNode.m_quantizedAabbMax[0],aabbMax,1);
-
- } else
- {
- //combine aabb from both children
+ b3QuantizedBvhNode* leftChildNode = &m_quantizedContiguousNodes[i + 1];
- b3QuantizedBvhNode* leftChildNode = &m_quantizedContiguousNodes[i+1];
-
- b3QuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? &m_quantizedContiguousNodes[i+2] :
- &m_quantizedContiguousNodes[i+1+leftChildNode->getEscapeIndex()];
-
+ b3QuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? &m_quantizedContiguousNodes[i + 2] : &m_quantizedContiguousNodes[i + 1 + leftChildNode->getEscapeIndex()];
+ {
+ for (int i = 0; i < 3; i++)
{
- for (int i=0;i<3;i++)
- {
- curNode.m_quantizedAabbMin[i] = leftChildNode->m_quantizedAabbMin[i];
- if (curNode.m_quantizedAabbMin[i]>rightChildNode->m_quantizedAabbMin[i])
- curNode.m_quantizedAabbMin[i]=rightChildNode->m_quantizedAabbMin[i];
-
- curNode.m_quantizedAabbMax[i] = leftChildNode->m_quantizedAabbMax[i];
- if (curNode.m_quantizedAabbMax[i] < rightChildNode->m_quantizedAabbMax[i])
- curNode.m_quantizedAabbMax[i] = rightChildNode->m_quantizedAabbMax[i];
- }
+ curNode.m_quantizedAabbMin[i] = leftChildNode->m_quantizedAabbMin[i];
+ if (curNode.m_quantizedAabbMin[i] > rightChildNode->m_quantizedAabbMin[i])
+ curNode.m_quantizedAabbMin[i] = rightChildNode->m_quantizedAabbMin[i];
+
+ curNode.m_quantizedAabbMax[i] = leftChildNode->m_quantizedAabbMax[i];
+ if (curNode.m_quantizedAabbMax[i] < rightChildNode->m_quantizedAabbMax[i])
+ curNode.m_quantizedAabbMax[i] = rightChildNode->m_quantizedAabbMax[i];
}
}
-
}
+ }
- if (curNodeSubPart >= 0)
- meshInterface->unLockReadOnlyVertexBase(curNodeSubPart);
-
-
+ if (curNodeSubPart >= 0)
+ meshInterface->unLockReadOnlyVertexBase(curNodeSubPart);
}
///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
-b3OptimizedBvh* b3OptimizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian)
+b3OptimizedBvh* b3OptimizedBvh::deSerializeInPlace(void* i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian)
{
- b3QuantizedBvh* bvh = b3QuantizedBvh::deSerializeInPlace(i_alignedDataBuffer,i_dataBufferSize,i_swapEndian);
-
+ b3QuantizedBvh* bvh = b3QuantizedBvh::deSerializeInPlace(i_alignedDataBuffer, i_dataBufferSize, i_swapEndian);
+
//we don't add additional data so just do a static upcast
return static_cast<b3OptimizedBvh*>(bvh);
}
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3OptimizedBvh.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3OptimizedBvh.h
index 0272ef83bf..1286552939 100644
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3OptimizedBvh.h
+++ b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3OptimizedBvh.h
@@ -22,44 +22,35 @@ subject to the following restrictions:
class b3StridingMeshInterface;
-
///The b3OptimizedBvh extends the b3QuantizedBvh to create AABB tree for triangle meshes, through the b3StridingMeshInterface.
-B3_ATTRIBUTE_ALIGNED16(class) b3OptimizedBvh : public b3QuantizedBvh
+B3_ATTRIBUTE_ALIGNED16(class)
+b3OptimizedBvh : public b3QuantizedBvh
{
-
public:
B3_DECLARE_ALIGNED_ALLOCATOR();
protected:
-
public:
-
b3OptimizedBvh();
virtual ~b3OptimizedBvh();
- void build(b3StridingMeshInterface* triangles,bool useQuantizedAabbCompression, const b3Vector3& bvhAabbMin, const b3Vector3& bvhAabbMax);
+ void build(b3StridingMeshInterface * triangles, bool useQuantizedAabbCompression, const b3Vector3& bvhAabbMin, const b3Vector3& bvhAabbMax);
- void refit(b3StridingMeshInterface* triangles,const b3Vector3& aabbMin,const b3Vector3& aabbMax);
+ void refit(b3StridingMeshInterface * triangles, const b3Vector3& aabbMin, const b3Vector3& aabbMax);
- void refitPartial(b3StridingMeshInterface* triangles,const b3Vector3& aabbMin, const b3Vector3& aabbMax);
+ void refitPartial(b3StridingMeshInterface * triangles, const b3Vector3& aabbMin, const b3Vector3& aabbMax);
- void updateBvhNodes(b3StridingMeshInterface* meshInterface,int firstNode,int endNode,int index);
+ void updateBvhNodes(b3StridingMeshInterface * meshInterface, int firstNode, int endNode, int index);
/// Data buffer MUST be 16 byte aligned
- virtual bool serializeInPlace(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const
+ virtual bool serializeInPlace(void* o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const
{
- return b3QuantizedBvh::serialize(o_alignedDataBuffer,i_dataBufferSize,i_swapEndian);
-
+ return b3QuantizedBvh::serialize(o_alignedDataBuffer, i_dataBufferSize, i_swapEndian);
}
///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
- static b3OptimizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
-
-
+ static b3OptimizedBvh* deSerializeInPlace(void* i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
};
-
-#endif //B3_OPTIMIZED_BVH_H
-
-
+#endif //B3_OPTIMIZED_BVH_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3QuantizedBvh.cpp b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3QuantizedBvh.cpp
index 52027e1118..9a448495f3 100644
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3QuantizedBvh.cpp
+++ b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3QuantizedBvh.cpp
@@ -17,46 +17,40 @@ subject to the following restrictions:
#include "Bullet3Geometry/b3AabbUtil.h"
-
#define RAYAABB2
-b3QuantizedBvh::b3QuantizedBvh() :
- m_bulletVersion(B3_BULLET_VERSION),
- m_useQuantization(false),
- m_traversalMode(TRAVERSAL_STACKLESS_CACHE_FRIENDLY)
- //m_traversalMode(TRAVERSAL_STACKLESS)
- //m_traversalMode(TRAVERSAL_RECURSIVE)
- ,m_subtreeHeaderCount(0) //PCK: add this line
+b3QuantizedBvh::b3QuantizedBvh() : m_bulletVersion(B3_BULLET_VERSION),
+ m_useQuantization(false),
+ m_traversalMode(TRAVERSAL_STACKLESS_CACHE_FRIENDLY)
+ //m_traversalMode(TRAVERSAL_STACKLESS)
+ //m_traversalMode(TRAVERSAL_RECURSIVE)
+ ,
+ m_subtreeHeaderCount(0) //PCK: add this line
{
- m_bvhAabbMin.setValue(-B3_INFINITY,-B3_INFINITY,-B3_INFINITY);
- m_bvhAabbMax.setValue(B3_INFINITY,B3_INFINITY,B3_INFINITY);
+ m_bvhAabbMin.setValue(-B3_INFINITY, -B3_INFINITY, -B3_INFINITY);
+ m_bvhAabbMax.setValue(B3_INFINITY, B3_INFINITY, B3_INFINITY);
}
-
-
-
-
void b3QuantizedBvh::buildInternal()
{
///assumes that caller filled in the m_quantizedLeafNodes
m_useQuantization = true;
int numLeafNodes = 0;
-
+
if (m_useQuantization)
{
//now we have an array of leafnodes in m_leafNodes
numLeafNodes = m_quantizedLeafNodes.size();
- m_quantizedContiguousNodes.resize(2*numLeafNodes);
-
+ m_quantizedContiguousNodes.resize(2 * numLeafNodes);
}
m_curNodeIndex = 0;
- buildTree(0,numLeafNodes);
+ buildTree(0, numLeafNodes);
///if the entire tree is small then subtree size, we need to create a header info for the tree
- if(m_useQuantization && !m_SubtreeHeaders.size())
+ if (m_useQuantization && !m_SubtreeHeaders.size())
{
b3BvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[0]);
@@ -72,35 +66,27 @@ void b3QuantizedBvh::buildInternal()
m_leafNodes.clear();
}
-
-
///just for debugging, to visualize the individual patches/subtrees
#ifdef DEBUG_PATCH_COLORS
-b3Vector3 color[4]=
-{
- b3Vector3(1,0,0),
- b3Vector3(0,1,0),
- b3Vector3(0,0,1),
- b3Vector3(0,1,1)
-};
-#endif //DEBUG_PATCH_COLORS
-
-
+b3Vector3 color[4] =
+ {
+ b3Vector3(1, 0, 0),
+ b3Vector3(0, 1, 0),
+ b3Vector3(0, 0, 1),
+ b3Vector3(0, 1, 1)};
+#endif //DEBUG_PATCH_COLORS
-void b3QuantizedBvh::setQuantizationValues(const b3Vector3& bvhAabbMin,const b3Vector3& bvhAabbMax,b3Scalar quantizationMargin)
+void b3QuantizedBvh::setQuantizationValues(const b3Vector3& bvhAabbMin, const b3Vector3& bvhAabbMax, b3Scalar quantizationMargin)
{
//enlarge the AABB to avoid division by zero when initializing the quantization values
- b3Vector3 clampValue =b3MakeVector3(quantizationMargin,quantizationMargin,quantizationMargin);
+ b3Vector3 clampValue = b3MakeVector3(quantizationMargin, quantizationMargin, quantizationMargin);
m_bvhAabbMin = bvhAabbMin - clampValue;
m_bvhAabbMax = bvhAabbMax + clampValue;
b3Vector3 aabbSize = m_bvhAabbMax - m_bvhAabbMin;
- m_bvhQuantization = b3MakeVector3(b3Scalar(65533.0),b3Scalar(65533.0),b3Scalar(65533.0)) / aabbSize;
+ m_bvhQuantization = b3MakeVector3(b3Scalar(65533.0), b3Scalar(65533.0), b3Scalar(65533.0)) / aabbSize;
m_useQuantization = true;
}
-
-
-
b3QuantizedBvh::~b3QuantizedBvh()
{
}
@@ -108,104 +94,100 @@ b3QuantizedBvh::~b3QuantizedBvh()
#ifdef DEBUG_TREE_BUILDING
int gStackDepth = 0;
int gMaxStackDepth = 0;
-#endif //DEBUG_TREE_BUILDING
+#endif //DEBUG_TREE_BUILDING
-void b3QuantizedBvh::buildTree (int startIndex,int endIndex)
+void b3QuantizedBvh::buildTree(int startIndex, int endIndex)
{
#ifdef DEBUG_TREE_BUILDING
gStackDepth++;
if (gStackDepth > gMaxStackDepth)
gMaxStackDepth = gStackDepth;
-#endif //DEBUG_TREE_BUILDING
-
+#endif //DEBUG_TREE_BUILDING
int splitAxis, splitIndex, i;
- int numIndices =endIndex-startIndex;
+ int numIndices = endIndex - startIndex;
int curIndex = m_curNodeIndex;
- b3Assert(numIndices>0);
+ b3Assert(numIndices > 0);
- if (numIndices==1)
+ if (numIndices == 1)
{
#ifdef DEBUG_TREE_BUILDING
gStackDepth--;
-#endif //DEBUG_TREE_BUILDING
-
- assignInternalNodeFromLeafNode(m_curNodeIndex,startIndex);
+#endif //DEBUG_TREE_BUILDING
+
+ assignInternalNodeFromLeafNode(m_curNodeIndex, startIndex);
m_curNodeIndex++;
- return;
+ return;
}
//calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'.
-
- splitAxis = calcSplittingAxis(startIndex,endIndex);
- splitIndex = sortAndCalcSplittingIndex(startIndex,endIndex,splitAxis);
+ splitAxis = calcSplittingAxis(startIndex, endIndex);
+
+ splitIndex = sortAndCalcSplittingIndex(startIndex, endIndex, splitAxis);
int internalNodeIndex = m_curNodeIndex;
-
+
//set the min aabb to 'inf' or a max value, and set the max aabb to a -inf/minimum value.
//the aabb will be expanded during buildTree/mergeInternalNodeAabb with actual node values
- setInternalNodeAabbMin(m_curNodeIndex,m_bvhAabbMax);//can't use b3Vector3(B3_INFINITY,B3_INFINITY,B3_INFINITY)) because of quantization
- setInternalNodeAabbMax(m_curNodeIndex,m_bvhAabbMin);//can't use b3Vector3(-B3_INFINITY,-B3_INFINITY,-B3_INFINITY)) because of quantization
-
-
- for (i=startIndex;i<endIndex;i++)
+ setInternalNodeAabbMin(m_curNodeIndex, m_bvhAabbMax); //can't use b3Vector3(B3_INFINITY,B3_INFINITY,B3_INFINITY)) because of quantization
+ setInternalNodeAabbMax(m_curNodeIndex, m_bvhAabbMin); //can't use b3Vector3(-B3_INFINITY,-B3_INFINITY,-B3_INFINITY)) because of quantization
+
+ for (i = startIndex; i < endIndex; i++)
{
- mergeInternalNodeAabb(m_curNodeIndex,getAabbMin(i),getAabbMax(i));
+ mergeInternalNodeAabb(m_curNodeIndex, getAabbMin(i), getAabbMax(i));
}
m_curNodeIndex++;
-
//internalNode->m_escapeIndex;
-
+
int leftChildNodexIndex = m_curNodeIndex;
//build left child tree
- buildTree(startIndex,splitIndex);
+ buildTree(startIndex, splitIndex);
int rightChildNodexIndex = m_curNodeIndex;
//build right child tree
- buildTree(splitIndex,endIndex);
+ buildTree(splitIndex, endIndex);
#ifdef DEBUG_TREE_BUILDING
gStackDepth--;
-#endif //DEBUG_TREE_BUILDING
+#endif //DEBUG_TREE_BUILDING
int escapeIndex = m_curNodeIndex - curIndex;
if (m_useQuantization)
{
//escapeIndex is the number of nodes of this subtree
- const int sizeQuantizedNode =sizeof(b3QuantizedBvhNode);
+ const int sizeQuantizedNode = sizeof(b3QuantizedBvhNode);
const int treeSizeInBytes = escapeIndex * sizeQuantizedNode;
if (treeSizeInBytes > MAX_SUBTREE_SIZE_IN_BYTES)
{
- updateSubtreeHeaders(leftChildNodexIndex,rightChildNodexIndex);
+ updateSubtreeHeaders(leftChildNodexIndex, rightChildNodexIndex);
}
- } else
+ }
+ else
{
-
}
- setInternalNodeEscapeIndex(internalNodeIndex,escapeIndex);
-
+ setInternalNodeEscapeIndex(internalNodeIndex, escapeIndex);
}
-void b3QuantizedBvh::updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex)
+void b3QuantizedBvh::updateSubtreeHeaders(int leftChildNodexIndex, int rightChildNodexIndex)
{
b3Assert(m_useQuantization);
b3QuantizedBvhNode& leftChildNode = m_quantizedContiguousNodes[leftChildNodexIndex];
int leftSubTreeSize = leftChildNode.isLeafNode() ? 1 : leftChildNode.getEscapeIndex();
- int leftSubTreeSizeInBytes = leftSubTreeSize * static_cast<int>(sizeof(b3QuantizedBvhNode));
-
+ int leftSubTreeSizeInBytes = leftSubTreeSize * static_cast<int>(sizeof(b3QuantizedBvhNode));
+
b3QuantizedBvhNode& rightChildNode = m_quantizedContiguousNodes[rightChildNodexIndex];
int rightSubTreeSize = rightChildNode.isLeafNode() ? 1 : rightChildNode.getEscapeIndex();
- int rightSubTreeSizeInBytes = rightSubTreeSize * static_cast<int>(sizeof(b3QuantizedBvhNode));
+ int rightSubTreeSizeInBytes = rightSubTreeSize * static_cast<int>(sizeof(b3QuantizedBvhNode));
- if(leftSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES)
+ if (leftSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES)
{
b3BvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
subtree.setAabbFromQuantizeNode(leftChildNode);
@@ -213,7 +195,7 @@ void b3QuantizedBvh::updateSubtreeHeaders(int leftChildNodexIndex,int rightChild
subtree.m_subtreeSize = leftSubTreeSize;
}
- if(rightSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES)
+ if (rightSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES)
{
b3BvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
subtree.setAabbFromQuantizeNode(rightChildNode);
@@ -225,32 +207,31 @@ void b3QuantizedBvh::updateSubtreeHeaders(int leftChildNodexIndex,int rightChild
m_subtreeHeaderCount = m_SubtreeHeaders.size();
}
-
-int b3QuantizedBvh::sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis)
+int b3QuantizedBvh::sortAndCalcSplittingIndex(int startIndex, int endIndex, int splitAxis)
{
int i;
- int splitIndex =startIndex;
+ int splitIndex = startIndex;
int numIndices = endIndex - startIndex;
b3Scalar splitValue;
- b3Vector3 means=b3MakeVector3(b3Scalar(0.),b3Scalar(0.),b3Scalar(0.));
- for (i=startIndex;i<endIndex;i++)
+ b3Vector3 means = b3MakeVector3(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.));
+ for (i = startIndex; i < endIndex; i++)
{
- b3Vector3 center = b3Scalar(0.5)*(getAabbMax(i)+getAabbMin(i));
- means+=center;
+ b3Vector3 center = b3Scalar(0.5) * (getAabbMax(i) + getAabbMin(i));
+ means += center;
}
- means *= (b3Scalar(1.)/(b3Scalar)numIndices);
-
+ means *= (b3Scalar(1.) / (b3Scalar)numIndices);
+
splitValue = means[splitAxis];
-
+
//sort leafNodes so all values larger then splitValue comes first, and smaller values start from 'splitIndex'.
- for (i=startIndex;i<endIndex;i++)
+ for (i = startIndex; i < endIndex; i++)
{
- b3Vector3 center = b3Scalar(0.5)*(getAabbMax(i)+getAabbMin(i));
+ b3Vector3 center = b3Scalar(0.5) * (getAabbMax(i) + getAabbMin(i));
if (center[splitAxis] > splitValue)
{
//swap
- swapLeafNodes(i,splitIndex);
+ swapLeafNodes(i, splitIndex);
splitIndex++;
}
}
@@ -260,56 +241,53 @@ int b3QuantizedBvh::sortAndCalcSplittingIndex(int startIndex,int endIndex,int sp
//unbalanced1 is unsafe: it can cause stack overflows
//bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1)));
- //unbalanced2 should work too: always use center (perfect balanced trees)
+ //unbalanced2 should work too: always use center (perfect balanced trees)
//bool unbalanced2 = true;
//this should be safe too:
- int rangeBalancedIndices = numIndices/3;
- bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices)));
-
+ int rangeBalancedIndices = numIndices / 3;
+ bool unbalanced = ((splitIndex <= (startIndex + rangeBalancedIndices)) || (splitIndex >= (endIndex - 1 - rangeBalancedIndices)));
+
if (unbalanced)
{
- splitIndex = startIndex+ (numIndices>>1);
+ splitIndex = startIndex + (numIndices >> 1);
}
- bool unbal = (splitIndex==startIndex) || (splitIndex == (endIndex));
+ bool unbal = (splitIndex == startIndex) || (splitIndex == (endIndex));
(void)unbal;
b3Assert(!unbal);
return splitIndex;
}
-
-int b3QuantizedBvh::calcSplittingAxis(int startIndex,int endIndex)
+int b3QuantizedBvh::calcSplittingAxis(int startIndex, int endIndex)
{
int i;
- b3Vector3 means=b3MakeVector3(b3Scalar(0.),b3Scalar(0.),b3Scalar(0.));
- b3Vector3 variance=b3MakeVector3(b3Scalar(0.),b3Scalar(0.),b3Scalar(0.));
- int numIndices = endIndex-startIndex;
+ b3Vector3 means = b3MakeVector3(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.));
+ b3Vector3 variance = b3MakeVector3(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.));
+ int numIndices = endIndex - startIndex;
- for (i=startIndex;i<endIndex;i++)
+ for (i = startIndex; i < endIndex; i++)
{
- b3Vector3 center = b3Scalar(0.5)*(getAabbMax(i)+getAabbMin(i));
- means+=center;
+ b3Vector3 center = b3Scalar(0.5) * (getAabbMax(i) + getAabbMin(i));
+ means += center;
}
- means *= (b3Scalar(1.)/(b3Scalar)numIndices);
-
- for (i=startIndex;i<endIndex;i++)
+ means *= (b3Scalar(1.) / (b3Scalar)numIndices);
+
+ for (i = startIndex; i < endIndex; i++)
{
- b3Vector3 center = b3Scalar(0.5)*(getAabbMax(i)+getAabbMin(i));
- b3Vector3 diff2 = center-means;
+ b3Vector3 center = b3Scalar(0.5) * (getAabbMax(i) + getAabbMin(i));
+ b3Vector3 diff2 = center - means;
diff2 = diff2 * diff2;
variance += diff2;
}
- variance *= (b3Scalar(1.)/ ((b3Scalar)numIndices-1) );
-
+ variance *= (b3Scalar(1.) / ((b3Scalar)numIndices - 1));
+
return variance.maxAxis();
}
-
-
-void b3QuantizedBvh::reportAabbOverlappingNodex(b3NodeOverlapCallback* nodeCallback,const b3Vector3& aabbMin,const b3Vector3& aabbMax) const
+void b3QuantizedBvh::reportAabbOverlappingNodex(b3NodeOverlapCallback* nodeCallback, const b3Vector3& aabbMin, const b3Vector3& aabbMax) const
{
//either choose recursive traversal (walkTree) or stackless (walkStacklessTree)
@@ -318,38 +296,37 @@ void b3QuantizedBvh::reportAabbOverlappingNodex(b3NodeOverlapCallback* nodeCallb
///quantize query AABB
unsigned short int quantizedQueryAabbMin[3];
unsigned short int quantizedQueryAabbMax[3];
- quantizeWithClamp(quantizedQueryAabbMin,aabbMin,0);
- quantizeWithClamp(quantizedQueryAabbMax,aabbMax,1);
+ quantizeWithClamp(quantizedQueryAabbMin, aabbMin, 0);
+ quantizeWithClamp(quantizedQueryAabbMax, aabbMax, 1);
switch (m_traversalMode)
{
- case TRAVERSAL_STACKLESS:
- walkStacklessQuantizedTree(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax,0,m_curNodeIndex);
- break;
- case TRAVERSAL_STACKLESS_CACHE_FRIENDLY:
- walkStacklessQuantizedTreeCacheFriendly(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
- break;
- case TRAVERSAL_RECURSIVE:
+ case TRAVERSAL_STACKLESS:
+ walkStacklessQuantizedTree(nodeCallback, quantizedQueryAabbMin, quantizedQueryAabbMax, 0, m_curNodeIndex);
+ break;
+ case TRAVERSAL_STACKLESS_CACHE_FRIENDLY:
+ walkStacklessQuantizedTreeCacheFriendly(nodeCallback, quantizedQueryAabbMin, quantizedQueryAabbMax);
+ break;
+ case TRAVERSAL_RECURSIVE:
{
const b3QuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[0];
- walkRecursiveQuantizedTreeAgainstQueryAabb(rootNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
+ walkRecursiveQuantizedTreeAgainstQueryAabb(rootNode, nodeCallback, quantizedQueryAabbMin, quantizedQueryAabbMax);
}
break;
- default:
- //unsupported
- b3Assert(0);
+ default:
+ //unsupported
+ b3Assert(0);
}
- } else
+ }
+ else
{
- walkStacklessTree(nodeCallback,aabbMin,aabbMax);
+ walkStacklessTree(nodeCallback, aabbMin, aabbMax);
}
}
-
static int b3s_maxIterations = 0;
-
-void b3QuantizedBvh::walkStacklessTree(b3NodeOverlapCallback* nodeCallback,const b3Vector3& aabbMin,const b3Vector3& aabbMax) const
+void b3QuantizedBvh::walkStacklessTree(b3NodeOverlapCallback* nodeCallback, const b3Vector3& aabbMin, const b3Vector3& aabbMax) const
{
b3Assert(!m_useQuantization);
@@ -363,24 +340,25 @@ void b3QuantizedBvh::walkStacklessTree(b3NodeOverlapCallback* nodeCallback,const
while (curIndex < m_curNodeIndex)
{
//catch bugs in tree data
- b3Assert (walkIterations < m_curNodeIndex);
+ b3Assert(walkIterations < m_curNodeIndex);
walkIterations++;
- aabbOverlap = b3TestAabbAgainstAabb2(aabbMin,aabbMax,rootNode->m_aabbMinOrg,rootNode->m_aabbMaxOrg);
+ aabbOverlap = b3TestAabbAgainstAabb2(aabbMin, aabbMax, rootNode->m_aabbMinOrg, rootNode->m_aabbMaxOrg);
isLeafNode = rootNode->m_escapeIndex == -1;
-
+
//PCK: unsigned instead of bool
if (isLeafNode && (aabbOverlap != 0))
{
- nodeCallback->processNode(rootNode->m_subPart,rootNode->m_triangleIndex);
- }
-
+ nodeCallback->processNode(rootNode->m_subPart, rootNode->m_triangleIndex);
+ }
+
//PCK: unsigned instead of bool
if ((aabbOverlap != 0) || isLeafNode)
{
rootNode++;
curIndex++;
- } else
+ }
+ else
{
escapeIndex = rootNode->m_escapeIndex;
rootNode += escapeIndex;
@@ -389,7 +367,6 @@ void b3QuantizedBvh::walkStacklessTree(b3NodeOverlapCallback* nodeCallback,const
}
if (b3s_maxIterations < walkIterations)
b3s_maxIterations = walkIterations;
-
}
/*
@@ -413,39 +390,38 @@ void b3QuantizedBvh::walkTree(b3OptimizedBvhNode* rootNode,b3NodeOverlapCallback
}
*/
-void b3QuantizedBvh::walkRecursiveQuantizedTreeAgainstQueryAabb(const b3QuantizedBvhNode* currentNode,b3NodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const
+void b3QuantizedBvh::walkRecursiveQuantizedTreeAgainstQueryAabb(const b3QuantizedBvhNode* currentNode, b3NodeOverlapCallback* nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax) const
{
b3Assert(m_useQuantization);
-
+
bool isLeafNode;
//PCK: unsigned instead of bool
unsigned aabbOverlap;
//PCK: unsigned instead of bool
- aabbOverlap = b3TestQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,currentNode->m_quantizedAabbMin,currentNode->m_quantizedAabbMax);
+ aabbOverlap = b3TestQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin, quantizedQueryAabbMax, currentNode->m_quantizedAabbMin, currentNode->m_quantizedAabbMax);
isLeafNode = currentNode->isLeafNode();
-
+
//PCK: unsigned instead of bool
if (aabbOverlap != 0)
{
if (isLeafNode)
{
- nodeCallback->processNode(currentNode->getPartId(),currentNode->getTriangleIndex());
- } else
+ nodeCallback->processNode(currentNode->getPartId(), currentNode->getTriangleIndex());
+ }
+ else
{
//process left and right children
- const b3QuantizedBvhNode* leftChildNode = currentNode+1;
- walkRecursiveQuantizedTreeAgainstQueryAabb(leftChildNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
+ const b3QuantizedBvhNode* leftChildNode = currentNode + 1;
+ walkRecursiveQuantizedTreeAgainstQueryAabb(leftChildNode, nodeCallback, quantizedQueryAabbMin, quantizedQueryAabbMax);
- const b3QuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? leftChildNode+1:leftChildNode+leftChildNode->getEscapeIndex();
- walkRecursiveQuantizedTreeAgainstQueryAabb(rightChildNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
+ const b3QuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? leftChildNode + 1 : leftChildNode + leftChildNode->getEscapeIndex();
+ walkRecursiveQuantizedTreeAgainstQueryAabb(rightChildNode, nodeCallback, quantizedQueryAabbMin, quantizedQueryAabbMax);
}
- }
+ }
}
-
-
-void b3QuantizedBvh::walkStacklessTreeAgainstRay(b3NodeOverlapCallback* nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget, const b3Vector3& aabbMin, const b3Vector3& aabbMax, int startNodeIndex,int endNodeIndex) const
+void b3QuantizedBvh::walkStacklessTreeAgainstRay(b3NodeOverlapCallback* nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget, const b3Vector3& aabbMin, const b3Vector3& aabbMax, int startNodeIndex, int endNodeIndex) const
{
b3Assert(!m_useQuantization);
@@ -454,11 +430,11 @@ void b3QuantizedBvh::walkStacklessTreeAgainstRay(b3NodeOverlapCallback* nodeCall
int walkIterations = 0;
bool isLeafNode;
//PCK: unsigned instead of bool
- unsigned aabbOverlap=0;
- unsigned rayBoxOverlap=0;
+ unsigned aabbOverlap = 0;
+ unsigned rayBoxOverlap = 0;
b3Scalar lambda_max = 1.0;
-
- /* Quick pruning by quantized box */
+
+ /* Quick pruning by quantized box */
b3Vector3 rayAabbMin = raySource;
b3Vector3 rayAabbMax = raySource;
rayAabbMin.setMin(rayTarget);
@@ -469,15 +445,15 @@ void b3QuantizedBvh::walkStacklessTreeAgainstRay(b3NodeOverlapCallback* nodeCall
rayAabbMax += aabbMax;
#ifdef RAYAABB2
- b3Vector3 rayDir = (rayTarget-raySource);
- rayDir.normalize ();
- lambda_max = rayDir.dot(rayTarget-raySource);
+ b3Vector3 rayDir = (rayTarget - raySource);
+ rayDir.normalize();
+ lambda_max = rayDir.dot(rayTarget - raySource);
///what about division by zero? --> just set rayDirection[i] to 1.0
b3Vector3 rayDirectionInverse;
rayDirectionInverse[0] = rayDir[0] == b3Scalar(0.0) ? b3Scalar(B3_LARGE_FLOAT) : b3Scalar(1.0) / rayDir[0];
rayDirectionInverse[1] = rayDir[1] == b3Scalar(0.0) ? b3Scalar(B3_LARGE_FLOAT) : b3Scalar(1.0) / rayDir[1];
rayDirectionInverse[2] = rayDir[2] == b3Scalar(0.0) ? b3Scalar(B3_LARGE_FLOAT) : b3Scalar(1.0) / rayDir[2];
- unsigned int sign[3] = { rayDirectionInverse[0] < 0.0, rayDirectionInverse[1] < 0.0, rayDirectionInverse[2] < 0.0};
+ unsigned int sign[3] = {rayDirectionInverse[0] < 0.0, rayDirectionInverse[1] < 0.0, rayDirectionInverse[2] < 0.0};
#endif
b3Vector3 bounds[2];
@@ -486,7 +462,7 @@ void b3QuantizedBvh::walkStacklessTreeAgainstRay(b3NodeOverlapCallback* nodeCall
{
b3Scalar param = 1.0;
//catch bugs in tree data
- b3Assert (walkIterations < m_curNodeIndex);
+ b3Assert(walkIterations < m_curNodeIndex);
walkIterations++;
@@ -496,34 +472,35 @@ void b3QuantizedBvh::walkStacklessTreeAgainstRay(b3NodeOverlapCallback* nodeCall
bounds[0] -= aabbMax;
bounds[1] -= aabbMin;
- aabbOverlap = b3TestAabbAgainstAabb2(rayAabbMin,rayAabbMax,rootNode->m_aabbMinOrg,rootNode->m_aabbMaxOrg);
+ aabbOverlap = b3TestAabbAgainstAabb2(rayAabbMin, rayAabbMax, rootNode->m_aabbMinOrg, rootNode->m_aabbMaxOrg);
//perhaps profile if it is worth doing the aabbOverlap test first
#ifdef RAYAABB2
- ///careful with this check: need to check division by zero (above) and fix the unQuantize method
- ///thanks Joerg/hiker for the reproduction case!
- ///http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1858
- rayBoxOverlap = aabbOverlap ? b3RayAabb2 (raySource, rayDirectionInverse, sign, bounds, param, 0.0f, lambda_max) : false;
+ ///careful with this check: need to check division by zero (above) and fix the unQuantize method
+ ///thanks Joerg/hiker for the reproduction case!
+ ///http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1858
+ rayBoxOverlap = aabbOverlap ? b3RayAabb2(raySource, rayDirectionInverse, sign, bounds, param, 0.0f, lambda_max) : false;
#else
b3Vector3 normal;
- rayBoxOverlap = b3RayAabb(raySource, rayTarget,bounds[0],bounds[1],param, normal);
+ rayBoxOverlap = b3RayAabb(raySource, rayTarget, bounds[0], bounds[1], param, normal);
#endif
isLeafNode = rootNode->m_escapeIndex == -1;
-
+
//PCK: unsigned instead of bool
if (isLeafNode && (rayBoxOverlap != 0))
{
- nodeCallback->processNode(rootNode->m_subPart,rootNode->m_triangleIndex);
- }
-
+ nodeCallback->processNode(rootNode->m_subPart, rootNode->m_triangleIndex);
+ }
+
//PCK: unsigned instead of bool
if ((rayBoxOverlap != 0) || isLeafNode)
{
rootNode++;
curIndex++;
- } else
+ }
+ else
{
escapeIndex = rootNode->m_escapeIndex;
rootNode += escapeIndex;
@@ -532,15 +509,12 @@ void b3QuantizedBvh::walkStacklessTreeAgainstRay(b3NodeOverlapCallback* nodeCall
}
if (b3s_maxIterations < walkIterations)
b3s_maxIterations = walkIterations;
-
}
-
-
-void b3QuantizedBvh::walkStacklessQuantizedTreeAgainstRay(b3NodeOverlapCallback* nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget, const b3Vector3& aabbMin, const b3Vector3& aabbMax, int startNodeIndex,int endNodeIndex) const
+void b3QuantizedBvh::walkStacklessQuantizedTreeAgainstRay(b3NodeOverlapCallback* nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget, const b3Vector3& aabbMin, const b3Vector3& aabbMax, int startNodeIndex, int endNodeIndex) const
{
b3Assert(m_useQuantization);
-
+
int curIndex = startNodeIndex;
int walkIterations = 0;
int subTreeSize = endNodeIndex - startNodeIndex;
@@ -548,7 +522,7 @@ void b3QuantizedBvh::walkStacklessQuantizedTreeAgainstRay(b3NodeOverlapCallback*
const b3QuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex];
int escapeIndex;
-
+
bool isLeafNode;
//PCK: unsigned instead of bool
unsigned boxBoxOverlap = 0;
@@ -557,14 +531,14 @@ void b3QuantizedBvh::walkStacklessQuantizedTreeAgainstRay(b3NodeOverlapCallback*
b3Scalar lambda_max = 1.0;
#ifdef RAYAABB2
- b3Vector3 rayDirection = (rayTarget-raySource);
- rayDirection.normalize ();
- lambda_max = rayDirection.dot(rayTarget-raySource);
+ b3Vector3 rayDirection = (rayTarget - raySource);
+ rayDirection.normalize();
+ lambda_max = rayDirection.dot(rayTarget - raySource);
///what about division by zero? --> just set rayDirection[i] to 1.0
rayDirection[0] = rayDirection[0] == b3Scalar(0.0) ? b3Scalar(B3_LARGE_FLOAT) : b3Scalar(1.0) / rayDirection[0];
rayDirection[1] = rayDirection[1] == b3Scalar(0.0) ? b3Scalar(B3_LARGE_FLOAT) : b3Scalar(1.0) / rayDirection[1];
rayDirection[2] = rayDirection[2] == b3Scalar(0.0) ? b3Scalar(B3_LARGE_FLOAT) : b3Scalar(1.0) / rayDirection[2];
- unsigned int sign[3] = { rayDirection[0] < 0.0, rayDirection[1] < 0.0, rayDirection[2] < 0.0};
+ unsigned int sign[3] = {rayDirection[0] < 0.0, rayDirection[1] < 0.0, rayDirection[2] < 0.0};
#endif
/* Quick pruning by quantized box */
@@ -579,37 +553,36 @@ void b3QuantizedBvh::walkStacklessQuantizedTreeAgainstRay(b3NodeOverlapCallback*
unsigned short int quantizedQueryAabbMin[3];
unsigned short int quantizedQueryAabbMax[3];
- quantizeWithClamp(quantizedQueryAabbMin,rayAabbMin,0);
- quantizeWithClamp(quantizedQueryAabbMax,rayAabbMax,1);
+ quantizeWithClamp(quantizedQueryAabbMin, rayAabbMin, 0);
+ quantizeWithClamp(quantizedQueryAabbMax, rayAabbMax, 1);
while (curIndex < endNodeIndex)
{
-
//#define VISUALLY_ANALYZE_BVH 1
#ifdef VISUALLY_ANALYZE_BVH
//some code snippet to debugDraw aabb, to visually analyze bvh structure
static int drawPatch = 0;
//need some global access to a debugDrawer
extern b3IDebugDraw* debugDrawerPtr;
- if (curIndex==drawPatch)
+ if (curIndex == drawPatch)
{
- b3Vector3 aabbMin,aabbMax;
+ b3Vector3 aabbMin, aabbMax;
aabbMin = unQuantize(rootNode->m_quantizedAabbMin);
aabbMax = unQuantize(rootNode->m_quantizedAabbMax);
- b3Vector3 color(1,0,0);
- debugDrawerPtr->drawAabb(aabbMin,aabbMax,color);
+ b3Vector3 color(1, 0, 0);
+ debugDrawerPtr->drawAabb(aabbMin, aabbMax, color);
}
-#endif//VISUALLY_ANALYZE_BVH
+#endif //VISUALLY_ANALYZE_BVH
//catch bugs in tree data
- b3Assert (walkIterations < subTreeSize);
+ b3Assert(walkIterations < subTreeSize);
walkIterations++;
//PCK: unsigned instead of bool
// only interested if this is closer than any previous hit
b3Scalar param = 1.0;
rayBoxOverlap = 0;
- boxBoxOverlap = b3TestQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax);
+ boxBoxOverlap = b3TestQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin, quantizedQueryAabbMax, rootNode->m_quantizedAabbMin, rootNode->m_quantizedAabbMax);
isLeafNode = rootNode->isLeafNode();
if (boxBoxOverlap)
{
@@ -634,24 +607,25 @@ void b3QuantizedBvh::walkStacklessQuantizedTreeAgainstRay(b3NodeOverlapCallback*
///http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1858
//B3_PROFILE("b3RayAabb2");
- rayBoxOverlap = b3RayAabb2 (raySource, rayDirection, sign, bounds, param, 0.0f, lambda_max);
-
+ rayBoxOverlap = b3RayAabb2(raySource, rayDirection, sign, bounds, param, 0.0f, lambda_max);
+
#else
- rayBoxOverlap = true;//b3RayAabb(raySource, rayTarget, bounds[0], bounds[1], param, normal);
+ rayBoxOverlap = true; //b3RayAabb(raySource, rayTarget, bounds[0], bounds[1], param, normal);
#endif
}
-
+
if (isLeafNode && rayBoxOverlap)
{
- nodeCallback->processNode(rootNode->getPartId(),rootNode->getTriangleIndex());
+ nodeCallback->processNode(rootNode->getPartId(), rootNode->getTriangleIndex());
}
-
+
//PCK: unsigned instead of bool
if ((rayBoxOverlap != 0) || isLeafNode)
{
rootNode++;
curIndex++;
- } else
+ }
+ else
{
escapeIndex = rootNode->getEscapeIndex();
rootNode += escapeIndex;
@@ -660,13 +634,12 @@ void b3QuantizedBvh::walkStacklessQuantizedTreeAgainstRay(b3NodeOverlapCallback*
}
if (b3s_maxIterations < walkIterations)
b3s_maxIterations = walkIterations;
-
}
-void b3QuantizedBvh::walkStacklessQuantizedTree(b3NodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const
+void b3QuantizedBvh::walkStacklessQuantizedTree(b3NodeOverlapCallback* nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax, int startNodeIndex, int endNodeIndex) const
{
b3Assert(m_useQuantization);
-
+
int curIndex = startNodeIndex;
int walkIterations = 0;
int subTreeSize = endNodeIndex - startNodeIndex;
@@ -674,49 +647,49 @@ void b3QuantizedBvh::walkStacklessQuantizedTree(b3NodeOverlapCallback* nodeCallb
const b3QuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex];
int escapeIndex;
-
+
bool isLeafNode;
//PCK: unsigned instead of bool
unsigned aabbOverlap;
while (curIndex < endNodeIndex)
{
-
//#define VISUALLY_ANALYZE_BVH 1
#ifdef VISUALLY_ANALYZE_BVH
//some code snippet to debugDraw aabb, to visually analyze bvh structure
static int drawPatch = 0;
//need some global access to a debugDrawer
extern b3IDebugDraw* debugDrawerPtr;
- if (curIndex==drawPatch)
+ if (curIndex == drawPatch)
{
- b3Vector3 aabbMin,aabbMax;
+ b3Vector3 aabbMin, aabbMax;
aabbMin = unQuantize(rootNode->m_quantizedAabbMin);
aabbMax = unQuantize(rootNode->m_quantizedAabbMax);
- b3Vector3 color(1,0,0);
- debugDrawerPtr->drawAabb(aabbMin,aabbMax,color);
+ b3Vector3 color(1, 0, 0);
+ debugDrawerPtr->drawAabb(aabbMin, aabbMax, color);
}
-#endif//VISUALLY_ANALYZE_BVH
+#endif //VISUALLY_ANALYZE_BVH
//catch bugs in tree data
- b3Assert (walkIterations < subTreeSize);
+ b3Assert(walkIterations < subTreeSize);
walkIterations++;
//PCK: unsigned instead of bool
- aabbOverlap = b3TestQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax);
+ aabbOverlap = b3TestQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin, quantizedQueryAabbMax, rootNode->m_quantizedAabbMin, rootNode->m_quantizedAabbMax);
isLeafNode = rootNode->isLeafNode();
-
+
if (isLeafNode && aabbOverlap)
{
- nodeCallback->processNode(rootNode->getPartId(),rootNode->getTriangleIndex());
- }
-
+ nodeCallback->processNode(rootNode->getPartId(), rootNode->getTriangleIndex());
+ }
+
//PCK: unsigned instead of bool
if ((aabbOverlap != 0) || isLeafNode)
{
rootNode++;
curIndex++;
- } else
+ }
+ else
{
escapeIndex = rootNode->getEscapeIndex();
rootNode += escapeIndex;
@@ -725,40 +698,36 @@ void b3QuantizedBvh::walkStacklessQuantizedTree(b3NodeOverlapCallback* nodeCallb
}
if (b3s_maxIterations < walkIterations)
b3s_maxIterations = walkIterations;
-
}
//This traversal can be called from Playstation 3 SPU
-void b3QuantizedBvh::walkStacklessQuantizedTreeCacheFriendly(b3NodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const
+void b3QuantizedBvh::walkStacklessQuantizedTreeCacheFriendly(b3NodeOverlapCallback* nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax) const
{
b3Assert(m_useQuantization);
int i;
-
- for (i=0;i<this->m_SubtreeHeaders.size();i++)
+ for (i = 0; i < this->m_SubtreeHeaders.size(); i++)
{
const b3BvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
//PCK: unsigned instead of bool
- unsigned overlap = b3TestQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax);
+ unsigned overlap = b3TestQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin, quantizedQueryAabbMax, subtree.m_quantizedAabbMin, subtree.m_quantizedAabbMax);
if (overlap != 0)
{
- walkStacklessQuantizedTree(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax,
- subtree.m_rootNodeIndex,
- subtree.m_rootNodeIndex+subtree.m_subtreeSize);
+ walkStacklessQuantizedTree(nodeCallback, quantizedQueryAabbMin, quantizedQueryAabbMax,
+ subtree.m_rootNodeIndex,
+ subtree.m_rootNodeIndex + subtree.m_subtreeSize);
}
}
}
-
-void b3QuantizedBvh::reportRayOverlappingNodex (b3NodeOverlapCallback* nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget) const
+void b3QuantizedBvh::reportRayOverlappingNodex(b3NodeOverlapCallback* nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget) const
{
- reportBoxCastOverlappingNodex(nodeCallback,raySource,rayTarget,b3MakeVector3(0,0,0),b3MakeVector3(0,0,0));
+ reportBoxCastOverlappingNodex(nodeCallback, raySource, rayTarget, b3MakeVector3(0, 0, 0), b3MakeVector3(0, 0, 0));
}
-
-void b3QuantizedBvh::reportBoxCastOverlappingNodex(b3NodeOverlapCallback* nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget, const b3Vector3& aabbMin,const b3Vector3& aabbMax) const
+void b3QuantizedBvh::reportBoxCastOverlappingNodex(b3NodeOverlapCallback* nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget, const b3Vector3& aabbMin, const b3Vector3& aabbMax) const
{
//always use stackless
@@ -782,31 +751,31 @@ void b3QuantizedBvh::reportBoxCastOverlappingNodex(b3NodeOverlapCallback* nodeCa
reportAabbOverlappingNodex(nodeCallback,qaabbMin,qaabbMax);
}
*/
-
}
-
-void b3QuantizedBvh::swapLeafNodes(int i,int splitIndex)
+void b3QuantizedBvh::swapLeafNodes(int i, int splitIndex)
{
if (m_useQuantization)
{
- b3QuantizedBvhNode tmp = m_quantizedLeafNodes[i];
- m_quantizedLeafNodes[i] = m_quantizedLeafNodes[splitIndex];
- m_quantizedLeafNodes[splitIndex] = tmp;
- } else
+ b3QuantizedBvhNode tmp = m_quantizedLeafNodes[i];
+ m_quantizedLeafNodes[i] = m_quantizedLeafNodes[splitIndex];
+ m_quantizedLeafNodes[splitIndex] = tmp;
+ }
+ else
{
- b3OptimizedBvhNode tmp = m_leafNodes[i];
- m_leafNodes[i] = m_leafNodes[splitIndex];
- m_leafNodes[splitIndex] = tmp;
+ b3OptimizedBvhNode tmp = m_leafNodes[i];
+ m_leafNodes[i] = m_leafNodes[splitIndex];
+ m_leafNodes[splitIndex] = tmp;
}
}
-void b3QuantizedBvh::assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex)
+void b3QuantizedBvh::assignInternalNodeFromLeafNode(int internalNode, int leafNodeIndex)
{
if (m_useQuantization)
{
m_quantizedContiguousNodes[internalNode] = m_quantizedLeafNodes[leafNodeIndex];
- } else
+ }
+ else
{
m_contiguousNodes[internalNode] = m_leafNodes[leafNodeIndex];
}
@@ -823,11 +792,10 @@ static const unsigned BVH_ALIGNMENT_MASK = BVH_ALIGNMENT-1;
static const unsigned BVH_ALIGNMENT_BLOCKS = 2;
#endif
-
unsigned int b3QuantizedBvh::getAlignmentSerializationPadding()
{
// I changed this to 0 since the extra padding is not needed or used.
- return 0;//BVH_ALIGNMENT_BLOCKS * BVH_ALIGNMENT;
+ return 0; //BVH_ALIGNMENT_BLOCKS * BVH_ALIGNMENT;
}
unsigned b3QuantizedBvh::calculateSerializeBufferSize() const
@@ -841,12 +809,12 @@ unsigned b3QuantizedBvh::calculateSerializeBufferSize() const
return baseSize + m_curNodeIndex * sizeof(b3OptimizedBvhNode);
}
-bool b3QuantizedBvh::serialize(void *o_alignedDataBuffer, unsigned /*i_dataBufferSize */, bool i_swapEndian) const
+bool b3QuantizedBvh::serialize(void* o_alignedDataBuffer, unsigned /*i_dataBufferSize */, bool i_swapEndian) const
{
b3Assert(m_subtreeHeaderCount == m_SubtreeHeaders.size());
m_subtreeHeaderCount = m_SubtreeHeaders.size();
-/* if (i_dataBufferSize < calculateSerializeBufferSize() || o_alignedDataBuffer == NULL || (((unsigned)o_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0))
+ /* if (i_dataBufferSize < calculateSerializeBufferSize() || o_alignedDataBuffer == NULL || (((unsigned)o_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0))
{
///check alignedment for buffer?
b3Assert(0);
@@ -854,7 +822,7 @@ bool b3QuantizedBvh::serialize(void *o_alignedDataBuffer, unsigned /*i_dataBuffe
}
*/
- b3QuantizedBvh *targetBvh = (b3QuantizedBvh *)o_alignedDataBuffer;
+ b3QuantizedBvh* targetBvh = (b3QuantizedBvh*)o_alignedDataBuffer;
// construct the class so the virtual function table, etc will be set up
// Also, m_leafNodes and m_quantizedLeafNodes will be initialized to default values by the constructor
@@ -864,10 +832,9 @@ bool b3QuantizedBvh::serialize(void *o_alignedDataBuffer, unsigned /*i_dataBuffe
{
targetBvh->m_curNodeIndex = static_cast<int>(b3SwapEndian(m_curNodeIndex));
-
- b3SwapVector3Endian(m_bvhAabbMin,targetBvh->m_bvhAabbMin);
- b3SwapVector3Endian(m_bvhAabbMax,targetBvh->m_bvhAabbMax);
- b3SwapVector3Endian(m_bvhQuantization,targetBvh->m_bvhQuantization);
+ b3SwapVector3Endian(m_bvhAabbMin, targetBvh->m_bvhAabbMin);
+ b3SwapVector3Endian(m_bvhAabbMax, targetBvh->m_bvhAabbMax);
+ b3SwapVector3Endian(m_bvhQuantization, targetBvh->m_bvhQuantization);
targetBvh->m_traversalMode = (b3TraversalMode)b3SwapEndian(m_traversalMode);
targetBvh->m_subtreeHeaderCount = static_cast<int>(b3SwapEndian(m_subtreeHeaderCount));
@@ -884,12 +851,12 @@ bool b3QuantizedBvh::serialize(void *o_alignedDataBuffer, unsigned /*i_dataBuffe
targetBvh->m_useQuantization = m_useQuantization;
- unsigned char *nodeData = (unsigned char *)targetBvh;
+ unsigned char* nodeData = (unsigned char*)targetBvh;
nodeData += sizeof(b3QuantizedBvh);
-
- unsigned sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
+
+ unsigned sizeToAdd = 0; //(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
nodeData += sizeToAdd;
-
+
int nodeCount = m_curNodeIndex;
if (m_useQuantization)
@@ -915,7 +882,6 @@ bool b3QuantizedBvh::serialize(void *o_alignedDataBuffer, unsigned /*i_dataBuffe
{
for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
{
-
targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0];
targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1];
targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2];
@@ -925,8 +891,6 @@ bool b3QuantizedBvh::serialize(void *o_alignedDataBuffer, unsigned /*i_dataBuffe
targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2];
targetBvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex;
-
-
}
}
nodeData += sizeof(b3QuantizedBvhNode) * nodeCount;
@@ -972,7 +936,7 @@ bool b3QuantizedBvh::serialize(void *o_alignedDataBuffer, unsigned /*i_dataBuffe
targetBvh->m_contiguousNodes.initializeFromBuffer(NULL, 0, 0);
}
- sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
+ sizeToAdd = 0; //(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
nodeData += sizeToAdd;
// Now serialize the subtree headers
@@ -1027,14 +991,13 @@ bool b3QuantizedBvh::serialize(void *o_alignedDataBuffer, unsigned /*i_dataBuffe
return true;
}
-b3QuantizedBvh *b3QuantizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian)
+b3QuantizedBvh* b3QuantizedBvh::deSerializeInPlace(void* i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian)
{
-
- if (i_alignedDataBuffer == NULL)// || (((unsigned)i_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0))
+ if (i_alignedDataBuffer == NULL) // || (((unsigned)i_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0))
{
return NULL;
}
- b3QuantizedBvh *bvh = (b3QuantizedBvh *)i_alignedDataBuffer;
+ b3QuantizedBvh* bvh = (b3QuantizedBvh*)i_alignedDataBuffer;
if (i_swapEndian)
{
@@ -1056,12 +1019,12 @@ b3QuantizedBvh *b3QuantizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, un
return NULL;
}
- unsigned char *nodeData = (unsigned char *)bvh;
+ unsigned char* nodeData = (unsigned char*)bvh;
nodeData += sizeof(b3QuantizedBvh);
-
- unsigned sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
+
+ unsigned sizeToAdd = 0; //(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
nodeData += sizeToAdd;
-
+
int nodeCount = bvh->m_curNodeIndex;
// Must call placement new to fill in virtual function table, etc, but we don't want to overwrite most data, so call a special version of the constructor
@@ -1099,7 +1062,7 @@ b3QuantizedBvh *b3QuantizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, un
{
b3UnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg);
b3UnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg);
-
+
bvh->m_contiguousNodes[nodeIndex].m_escapeIndex = static_cast<int>(b3SwapEndian(bvh->m_contiguousNodes[nodeIndex].m_escapeIndex));
bvh->m_contiguousNodes[nodeIndex].m_subPart = static_cast<int>(b3SwapEndian(bvh->m_contiguousNodes[nodeIndex].m_subPart));
bvh->m_contiguousNodes[nodeIndex].m_triangleIndex = static_cast<int>(b3SwapEndian(bvh->m_contiguousNodes[nodeIndex].m_triangleIndex));
@@ -1108,7 +1071,7 @@ b3QuantizedBvh *b3QuantizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, un
nodeData += sizeof(b3OptimizedBvhNode) * nodeCount;
}
- sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
+ sizeToAdd = 0; //(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
nodeData += sizeToAdd;
// Now serialize the subtree headers
@@ -1134,13 +1097,11 @@ b3QuantizedBvh *b3QuantizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, un
}
// Constructor that prevents b3Vector3's default constructor from being called
-b3QuantizedBvh::b3QuantizedBvh(b3QuantizedBvh &self, bool /* ownsMemory */) :
-m_bvhAabbMin(self.m_bvhAabbMin),
-m_bvhAabbMax(self.m_bvhAabbMax),
-m_bvhQuantization(self.m_bvhQuantization),
-m_bulletVersion(B3_BULLET_VERSION)
+b3QuantizedBvh::b3QuantizedBvh(b3QuantizedBvh& self, bool /* ownsMemory */) : m_bvhAabbMin(self.m_bvhAabbMin),
+ m_bvhAabbMax(self.m_bvhAabbMax),
+ m_bvhQuantization(self.m_bvhQuantization),
+ m_bulletVersion(B3_BULLET_VERSION)
{
-
}
void b3QuantizedBvh::deSerializeFloat(struct b3QuantizedBvhFloatData& quantizedBvhFloatData)
@@ -1150,8 +1111,8 @@ void b3QuantizedBvh::deSerializeFloat(struct b3QuantizedBvhFloatData& quantizedB
m_bvhQuantization.deSerializeFloat(quantizedBvhFloatData.m_bvhQuantization);
m_curNodeIndex = quantizedBvhFloatData.m_curNodeIndex;
- m_useQuantization = quantizedBvhFloatData.m_useQuantization!=0;
-
+ m_useQuantization = quantizedBvhFloatData.m_useQuantization != 0;
+
{
int numElem = quantizedBvhFloatData.m_numContiguousLeafNodes;
m_contiguousNodes.resize(numElem);
@@ -1160,7 +1121,7 @@ void b3QuantizedBvh::deSerializeFloat(struct b3QuantizedBvhFloatData& quantizedB
{
b3OptimizedBvhNodeFloatData* memPtr = quantizedBvhFloatData.m_contiguousNodesPtr;
- for (int i=0;i<numElem;i++,memPtr++)
+ for (int i = 0; i < numElem; i++, memPtr++)
{
m_contiguousNodes[i].m_aabbMaxOrg.deSerializeFloat(memPtr->m_aabbMaxOrg);
m_contiguousNodes[i].m_aabbMinOrg.deSerializeFloat(memPtr->m_aabbMinOrg);
@@ -1174,11 +1135,11 @@ void b3QuantizedBvh::deSerializeFloat(struct b3QuantizedBvhFloatData& quantizedB
{
int numElem = quantizedBvhFloatData.m_numQuantizedContiguousNodes;
m_quantizedContiguousNodes.resize(numElem);
-
+
if (numElem)
{
b3QuantizedBvhNodeData* memPtr = quantizedBvhFloatData.m_quantizedContiguousNodesPtr;
- for (int i=0;i<numElem;i++,memPtr++)
+ for (int i = 0; i < numElem; i++, memPtr++)
{
m_quantizedContiguousNodes[i].m_escapeIndexOrTriangleIndex = memPtr->m_escapeIndexOrTriangleIndex;
m_quantizedContiguousNodes[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0];
@@ -1192,16 +1153,16 @@ void b3QuantizedBvh::deSerializeFloat(struct b3QuantizedBvhFloatData& quantizedB
}
m_traversalMode = b3TraversalMode(quantizedBvhFloatData.m_traversalMode);
-
+
{
int numElem = quantizedBvhFloatData.m_numSubtreeHeaders;
m_SubtreeHeaders.resize(numElem);
if (numElem)
{
b3BvhSubtreeInfoData* memPtr = quantizedBvhFloatData.m_subTreeInfoPtr;
- for (int i=0;i<numElem;i++,memPtr++)
+ for (int i = 0; i < numElem; i++, memPtr++)
{
- m_SubtreeHeaders[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0] ;
+ m_SubtreeHeaders[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0];
m_SubtreeHeaders[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
m_SubtreeHeaders[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
m_SubtreeHeaders[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
@@ -1221,8 +1182,8 @@ void b3QuantizedBvh::deSerializeDouble(struct b3QuantizedBvhDoubleData& quantize
m_bvhQuantization.deSerializeDouble(quantizedBvhDoubleData.m_bvhQuantization);
m_curNodeIndex = quantizedBvhDoubleData.m_curNodeIndex;
- m_useQuantization = quantizedBvhDoubleData.m_useQuantization!=0;
-
+ m_useQuantization = quantizedBvhDoubleData.m_useQuantization != 0;
+
{
int numElem = quantizedBvhDoubleData.m_numContiguousLeafNodes;
m_contiguousNodes.resize(numElem);
@@ -1231,7 +1192,7 @@ void b3QuantizedBvh::deSerializeDouble(struct b3QuantizedBvhDoubleData& quantize
{
b3OptimizedBvhNodeDoubleData* memPtr = quantizedBvhDoubleData.m_contiguousNodesPtr;
- for (int i=0;i<numElem;i++,memPtr++)
+ for (int i = 0; i < numElem; i++, memPtr++)
{
m_contiguousNodes[i].m_aabbMaxOrg.deSerializeDouble(memPtr->m_aabbMaxOrg);
m_contiguousNodes[i].m_aabbMinOrg.deSerializeDouble(memPtr->m_aabbMinOrg);
@@ -1245,11 +1206,11 @@ void b3QuantizedBvh::deSerializeDouble(struct b3QuantizedBvhDoubleData& quantize
{
int numElem = quantizedBvhDoubleData.m_numQuantizedContiguousNodes;
m_quantizedContiguousNodes.resize(numElem);
-
+
if (numElem)
{
b3QuantizedBvhNodeData* memPtr = quantizedBvhDoubleData.m_quantizedContiguousNodesPtr;
- for (int i=0;i<numElem;i++,memPtr++)
+ for (int i = 0; i < numElem; i++, memPtr++)
{
m_quantizedContiguousNodes[i].m_escapeIndexOrTriangleIndex = memPtr->m_escapeIndexOrTriangleIndex;
m_quantizedContiguousNodes[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0];
@@ -1263,16 +1224,16 @@ void b3QuantizedBvh::deSerializeDouble(struct b3QuantizedBvhDoubleData& quantize
}
m_traversalMode = b3TraversalMode(quantizedBvhDoubleData.m_traversalMode);
-
+
{
int numElem = quantizedBvhDoubleData.m_numSubtreeHeaders;
m_SubtreeHeaders.resize(numElem);
if (numElem)
{
b3BvhSubtreeInfoData* memPtr = quantizedBvhDoubleData.m_subTreeInfoPtr;
- for (int i=0;i<numElem;i++,memPtr++)
+ for (int i = 0; i < numElem; i++, memPtr++)
{
- m_SubtreeHeaders[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0] ;
+ m_SubtreeHeaders[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0];
m_SubtreeHeaders[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
m_SubtreeHeaders[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
m_SubtreeHeaders[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
@@ -1283,19 +1244,11 @@ void b3QuantizedBvh::deSerializeDouble(struct b3QuantizedBvhDoubleData& quantize
}
}
}
-
}
-
-
///fills the dataBuffer and returns the struct name (and 0 on failure)
-const char* b3QuantizedBvh::serialize(void* dataBuffer, b3Serializer* serializer) const
+const char* b3QuantizedBvh::serialize(void* dataBuffer, b3Serializer* serializer) const
{
b3Assert(0);
return 0;
}
-
-
-
-
-
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3QuantizedBvh.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3QuantizedBvh.h
index 63c523c758..48b41abcad 100644
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3QuantizedBvh.h
+++ b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3QuantizedBvh.h
@@ -22,11 +22,11 @@ class b3Serializer;
#ifdef DEBUG_CHECK_DEQUANTIZATION
#ifdef __SPU__
#define printf spu_printf
-#endif //__SPU__
+#endif //__SPU__
#include <stdio.h>
#include <stdlib.h>
-#endif //DEBUG_CHECK_DEQUANTIZATION
+#endif //DEBUG_CHECK_DEQUANTIZATION
#include "Bullet3Common/b3Vector3.h"
#include "Bullet3Common/b3AlignedAllocator.h"
@@ -44,13 +44,10 @@ class b3Serializer;
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3QuantizedBvhNodeData.h"
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3BvhSubtreeInfoData.h"
-
-
//http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vclrf__m128.asp
-
//Note: currently we have 16 bytes per quantized node
-#define MAX_SUBTREE_SIZE_IN_BYTES 2048
+#define MAX_SUBTREE_SIZE_IN_BYTES 2048
// 10 gives the potential for 1024 parts, with at most 2^21 (2097152) (minus one
// actually) triangles each (since the sign bit is reserved
@@ -58,7 +55,8 @@ class b3Serializer;
///b3QuantizedBvhNode is a compressed aabb node, 16 bytes.
///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).
-B3_ATTRIBUTE_ALIGNED16 (struct) b3QuantizedBvhNode : public b3QuantizedBvhNodeData
+B3_ATTRIBUTE_ALIGNED16(struct)
+b3QuantizedBvhNode : public b3QuantizedBvhNodeData
{
B3_DECLARE_ALIGNED_ALLOCATOR();
@@ -72,48 +70,48 @@ B3_ATTRIBUTE_ALIGNED16 (struct) b3QuantizedBvhNode : public b3QuantizedBvhNodeDa
b3Assert(!isLeafNode());
return -m_escapeIndexOrTriangleIndex;
}
- int getTriangleIndex() const
+ int getTriangleIndex() const
{
b3Assert(isLeafNode());
- unsigned int x=0;
- unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);
+ unsigned int x = 0;
+ unsigned int y = (~(x & 0)) << (31 - MAX_NUM_PARTS_IN_BITS);
// Get only the lower bits where the triangle index is stored
- return (m_escapeIndexOrTriangleIndex&~(y));
+ return (m_escapeIndexOrTriangleIndex & ~(y));
}
- int getPartId() const
+ int getPartId() const
{
b3Assert(isLeafNode());
// Get only the highest bits where the part index is stored
- return (m_escapeIndexOrTriangleIndex>>(31-MAX_NUM_PARTS_IN_BITS));
+ return (m_escapeIndexOrTriangleIndex >> (31 - MAX_NUM_PARTS_IN_BITS));
}
-}
-;
+};
/// b3OptimizedBvhNode contains both internal and leaf node information.
/// Total node size is 44 bytes / node. You can use the compressed version of 16 bytes.
-B3_ATTRIBUTE_ALIGNED16 (struct) b3OptimizedBvhNode
+B3_ATTRIBUTE_ALIGNED16(struct)
+b3OptimizedBvhNode
{
B3_DECLARE_ALIGNED_ALLOCATOR();
//32 bytes
- b3Vector3 m_aabbMinOrg;
- b3Vector3 m_aabbMaxOrg;
+ b3Vector3 m_aabbMinOrg;
+ b3Vector3 m_aabbMaxOrg;
//4
- int m_escapeIndex;
+ int m_escapeIndex;
//8
//for child nodes
- int m_subPart;
- int m_triangleIndex;
+ int m_subPart;
+ int m_triangleIndex;
-//pad the size to 64 bytes
- char m_padding[20];
+ //pad the size to 64 bytes
+ char m_padding[20];
};
-
///b3BvhSubtreeInfo provides info to gather a subtree of limited size
-B3_ATTRIBUTE_ALIGNED16(class) b3BvhSubtreeInfo : public b3BvhSubtreeInfoData
+B3_ATTRIBUTE_ALIGNED16(class)
+b3BvhSubtreeInfo : public b3BvhSubtreeInfoData
{
public:
B3_DECLARE_ALIGNED_ALLOCATOR();
@@ -123,8 +121,7 @@ public:
//memset(&m_padding[0], 0, sizeof(m_padding));
}
-
- void setAabbFromQuantizeNode(const b3QuantizedBvhNode& quantizedNode)
+ void setAabbFromQuantizeNode(const b3QuantizedBvhNode& quantizedNode)
{
m_quantizedAabbMin[0] = quantizedNode.m_quantizedAabbMin[0];
m_quantizedAabbMin[1] = quantizedNode.m_quantizedAabbMin[1];
@@ -133,14 +130,12 @@ public:
m_quantizedAabbMax[1] = quantizedNode.m_quantizedAabbMax[1];
m_quantizedAabbMax[2] = quantizedNode.m_quantizedAabbMax[2];
}
-}
-;
-
+};
class b3NodeOverlapCallback
{
public:
- virtual ~b3NodeOverlapCallback() {};
+ virtual ~b3NodeOverlapCallback(){};
virtual void processNode(int subPart, int triangleIndex) = 0;
};
@@ -148,18 +143,16 @@ public:
#include "Bullet3Common/b3AlignedAllocator.h"
#include "Bullet3Common/b3AlignedObjectArray.h"
-
-
///for code readability:
-typedef b3AlignedObjectArray<b3OptimizedBvhNode> NodeArray;
-typedef b3AlignedObjectArray<b3QuantizedBvhNode> QuantizedNodeArray;
-typedef b3AlignedObjectArray<b3BvhSubtreeInfo> BvhSubtreeInfoArray;
-
+typedef b3AlignedObjectArray<b3OptimizedBvhNode> NodeArray;
+typedef b3AlignedObjectArray<b3QuantizedBvhNode> QuantizedNodeArray;
+typedef b3AlignedObjectArray<b3BvhSubtreeInfo> BvhSubtreeInfoArray;
///The b3QuantizedBvh class stores an AABB tree that can be quickly traversed on CPU and Cell SPU.
///It is used by the b3BvhTriangleMeshShape as midphase
///It is recommended to use quantization for better performance and lower memory requirements.
-B3_ATTRIBUTE_ALIGNED16(class) b3QuantizedBvh
+B3_ATTRIBUTE_ALIGNED16(class)
+b3QuantizedBvh
{
public:
enum b3TraversalMode
@@ -169,56 +162,48 @@ public:
TRAVERSAL_RECURSIVE
};
-
-
-
- b3Vector3 m_bvhAabbMin;
- b3Vector3 m_bvhAabbMax;
- b3Vector3 m_bvhQuantization;
+ b3Vector3 m_bvhAabbMin;
+ b3Vector3 m_bvhAabbMax;
+ b3Vector3 m_bvhQuantization;
protected:
- int m_bulletVersion; //for serialization versioning. It could also be used to detect endianess.
+ int m_bulletVersion; //for serialization versioning. It could also be used to detect endianess.
- int m_curNodeIndex;
+ int m_curNodeIndex;
//quantization data
- bool m_useQuantization;
+ bool m_useQuantization;
+ NodeArray m_leafNodes;
+ NodeArray m_contiguousNodes;
+ QuantizedNodeArray m_quantizedLeafNodes;
+ QuantizedNodeArray m_quantizedContiguousNodes;
-
- NodeArray m_leafNodes;
- NodeArray m_contiguousNodes;
- QuantizedNodeArray m_quantizedLeafNodes;
- QuantizedNodeArray m_quantizedContiguousNodes;
-
- b3TraversalMode m_traversalMode;
- BvhSubtreeInfoArray m_SubtreeHeaders;
+ b3TraversalMode m_traversalMode;
+ BvhSubtreeInfoArray m_SubtreeHeaders;
//This is only used for serialization so we don't have to add serialization directly to b3AlignedObjectArray
mutable int m_subtreeHeaderCount;
-
-
-
-
///two versions, one for quantized and normal nodes. This allows code-reuse while maintaining readability (no template/macro!)
///this might be refactored into a virtual, it is usually not calculated at run-time
- void setInternalNodeAabbMin(int nodeIndex, const b3Vector3& aabbMin)
+ void setInternalNodeAabbMin(int nodeIndex, const b3Vector3& aabbMin)
{
if (m_useQuantization)
{
- quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] ,aabbMin,0);
- } else
+ quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0], aabbMin, 0);
+ }
+ else
{
m_contiguousNodes[nodeIndex].m_aabbMinOrg = aabbMin;
-
}
}
- void setInternalNodeAabbMax(int nodeIndex,const b3Vector3& aabbMax)
+ void setInternalNodeAabbMax(int nodeIndex, const b3Vector3& aabbMax)
{
if (m_useQuantization)
{
- quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0],aabbMax,1);
- } else
+ quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0], aabbMax, 1);
+ }
+ else
{
m_contiguousNodes[nodeIndex].m_aabbMaxOrg = aabbMax;
}
@@ -232,115 +217,102 @@ protected:
}
//non-quantized
return m_leafNodes[nodeIndex].m_aabbMinOrg;
-
}
b3Vector3 getAabbMax(int nodeIndex) const
{
if (m_useQuantization)
{
return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMax[0]);
- }
+ }
//non-quantized
return m_leafNodes[nodeIndex].m_aabbMaxOrg;
-
}
-
- void setInternalNodeEscapeIndex(int nodeIndex, int escapeIndex)
+ void setInternalNodeEscapeIndex(int nodeIndex, int escapeIndex)
{
if (m_useQuantization)
{
m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = -escapeIndex;
- }
+ }
else
{
m_contiguousNodes[nodeIndex].m_escapeIndex = escapeIndex;
}
-
}
- void mergeInternalNodeAabb(int nodeIndex,const b3Vector3& newAabbMin,const b3Vector3& newAabbMax)
+ void mergeInternalNodeAabb(int nodeIndex, const b3Vector3& newAabbMin, const b3Vector3& newAabbMax)
{
if (m_useQuantization)
{
unsigned short int quantizedAabbMin[3];
unsigned short int quantizedAabbMax[3];
- quantize(quantizedAabbMin,newAabbMin,0);
- quantize(quantizedAabbMax,newAabbMax,1);
- for (int i=0;i<3;i++)
+ quantize(quantizedAabbMin, newAabbMin, 0);
+ quantize(quantizedAabbMax, newAabbMax, 1);
+ for (int i = 0; i < 3; i++)
{
if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] > quantizedAabbMin[i])
m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] = quantizedAabbMin[i];
if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] < quantizedAabbMax[i])
m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] = quantizedAabbMax[i];
-
}
- } else
+ }
+ else
{
//non-quantized
m_contiguousNodes[nodeIndex].m_aabbMinOrg.setMin(newAabbMin);
- m_contiguousNodes[nodeIndex].m_aabbMaxOrg.setMax(newAabbMax);
+ m_contiguousNodes[nodeIndex].m_aabbMaxOrg.setMax(newAabbMax);
}
}
- void swapLeafNodes(int firstIndex,int secondIndex);
+ void swapLeafNodes(int firstIndex, int secondIndex);
- void assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex);
+ void assignInternalNodeFromLeafNode(int internalNode, int leafNodeIndex);
protected:
+ void buildTree(int startIndex, int endIndex);
-
-
- void buildTree (int startIndex,int endIndex);
+ int calcSplittingAxis(int startIndex, int endIndex);
- int calcSplittingAxis(int startIndex,int endIndex);
+ int sortAndCalcSplittingIndex(int startIndex, int endIndex, int splitAxis);
- int sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis);
-
- void walkStacklessTree(b3NodeOverlapCallback* nodeCallback,const b3Vector3& aabbMin,const b3Vector3& aabbMax) const;
+ void walkStacklessTree(b3NodeOverlapCallback * nodeCallback, const b3Vector3& aabbMin, const b3Vector3& aabbMax) const;
- void walkStacklessQuantizedTreeAgainstRay(b3NodeOverlapCallback* nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget, const b3Vector3& aabbMin, const b3Vector3& aabbMax, int startNodeIndex,int endNodeIndex) const;
- void walkStacklessQuantizedTree(b3NodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const;
- void walkStacklessTreeAgainstRay(b3NodeOverlapCallback* nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget, const b3Vector3& aabbMin, const b3Vector3& aabbMax, int startNodeIndex,int endNodeIndex) const;
+ void walkStacklessQuantizedTreeAgainstRay(b3NodeOverlapCallback * nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget, const b3Vector3& aabbMin, const b3Vector3& aabbMax, int startNodeIndex, int endNodeIndex) const;
+ void walkStacklessQuantizedTree(b3NodeOverlapCallback * nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax, int startNodeIndex, int endNodeIndex) const;
+ void walkStacklessTreeAgainstRay(b3NodeOverlapCallback * nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget, const b3Vector3& aabbMin, const b3Vector3& aabbMax, int startNodeIndex, int endNodeIndex) const;
///tree traversal designed for small-memory processors like PS3 SPU
- void walkStacklessQuantizedTreeCacheFriendly(b3NodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const;
+ void walkStacklessQuantizedTreeCacheFriendly(b3NodeOverlapCallback * nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax) const;
///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal
- void walkRecursiveQuantizedTreeAgainstQueryAabb(const b3QuantizedBvhNode* currentNode,b3NodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const;
+ void walkRecursiveQuantizedTreeAgainstQueryAabb(const b3QuantizedBvhNode* currentNode, b3NodeOverlapCallback* nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax) const;
///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal
- void walkRecursiveQuantizedTreeAgainstQuantizedTree(const b3QuantizedBvhNode* treeNodeA,const b3QuantizedBvhNode* treeNodeB,b3NodeOverlapCallback* nodeCallback) const;
-
-
-
+ void walkRecursiveQuantizedTreeAgainstQuantizedTree(const b3QuantizedBvhNode* treeNodeA, const b3QuantizedBvhNode* treeNodeB, b3NodeOverlapCallback* nodeCallback) const;
- void updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex);
+ void updateSubtreeHeaders(int leftChildNodexIndex, int rightChildNodexIndex);
public:
-
B3_DECLARE_ALIGNED_ALLOCATOR();
b3QuantizedBvh();
virtual ~b3QuantizedBvh();
-
///***************************************** expert/internal use only *************************
- void setQuantizationValues(const b3Vector3& bvhAabbMin,const b3Vector3& bvhAabbMax,b3Scalar quantizationMargin=b3Scalar(1.0));
- QuantizedNodeArray& getLeafNodeArray() { return m_quantizedLeafNodes; }
+ void setQuantizationValues(const b3Vector3& bvhAabbMin, const b3Vector3& bvhAabbMax, b3Scalar quantizationMargin = b3Scalar(1.0));
+ QuantizedNodeArray& getLeafNodeArray() { return m_quantizedLeafNodes; }
///buildInternal is expert use only: assumes that setQuantizationValues and LeafNodeArray are initialized
- void buildInternal();
+ void buildInternal();
///***************************************** expert/internal use only *************************
- void reportAabbOverlappingNodex(b3NodeOverlapCallback* nodeCallback,const b3Vector3& aabbMin,const b3Vector3& aabbMax) const;
- void reportRayOverlappingNodex (b3NodeOverlapCallback* nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget) const;
- void reportBoxCastOverlappingNodex(b3NodeOverlapCallback* nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget, const b3Vector3& aabbMin,const b3Vector3& aabbMax) const;
+ void reportAabbOverlappingNodex(b3NodeOverlapCallback * nodeCallback, const b3Vector3& aabbMin, const b3Vector3& aabbMax) const;
+ void reportRayOverlappingNodex(b3NodeOverlapCallback * nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget) const;
+ void reportBoxCastOverlappingNodex(b3NodeOverlapCallback * nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget, const b3Vector3& aabbMin, const b3Vector3& aabbMax) const;
- B3_FORCE_INLINE void quantize(unsigned short* out, const b3Vector3& point,int isMax) const
+ B3_FORCE_INLINE void quantize(unsigned short* out, const b3Vector3& point, int isMax) const
{
-
b3Assert(m_useQuantization);
b3Assert(point.getX() <= m_bvhAabbMax.getX());
@@ -357,122 +329,114 @@ public:
///@todo: double-check this
if (isMax)
{
- out[0] = (unsigned short) (((unsigned short)(v.getX()+b3Scalar(1.)) | 1));
- out[1] = (unsigned short) (((unsigned short)(v.getY()+b3Scalar(1.)) | 1));
- out[2] = (unsigned short) (((unsigned short)(v.getZ()+b3Scalar(1.)) | 1));
- } else
+ out[0] = (unsigned short)(((unsigned short)(v.getX() + b3Scalar(1.)) | 1));
+ out[1] = (unsigned short)(((unsigned short)(v.getY() + b3Scalar(1.)) | 1));
+ out[2] = (unsigned short)(((unsigned short)(v.getZ() + b3Scalar(1.)) | 1));
+ }
+ else
{
- out[0] = (unsigned short) (((unsigned short)(v.getX()) & 0xfffe));
- out[1] = (unsigned short) (((unsigned short)(v.getY()) & 0xfffe));
- out[2] = (unsigned short) (((unsigned short)(v.getZ()) & 0xfffe));
+ out[0] = (unsigned short)(((unsigned short)(v.getX()) & 0xfffe));
+ out[1] = (unsigned short)(((unsigned short)(v.getY()) & 0xfffe));
+ out[2] = (unsigned short)(((unsigned short)(v.getZ()) & 0xfffe));
}
-
#ifdef DEBUG_CHECK_DEQUANTIZATION
b3Vector3 newPoint = unQuantize(out);
if (isMax)
{
if (newPoint.getX() < point.getX())
{
- printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX());
+ printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n", newPoint.getX() - point.getX(), newPoint.getX(), point.getX());
}
if (newPoint.getY() < point.getY())
{
- printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY());
+ printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n", newPoint.getY() - point.getY(), newPoint.getY(), point.getY());
}
if (newPoint.getZ() < point.getZ())
{
-
- printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ());
+ printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n", newPoint.getZ() - point.getZ(), newPoint.getZ(), point.getZ());
}
- } else
+ }
+ else
{
if (newPoint.getX() > point.getX())
{
- printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX());
+ printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n", newPoint.getX() - point.getX(), newPoint.getX(), point.getX());
}
if (newPoint.getY() > point.getY())
{
- printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY());
+ printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n", newPoint.getY() - point.getY(), newPoint.getY(), point.getY());
}
if (newPoint.getZ() > point.getZ())
{
- printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ());
+ printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n", newPoint.getZ() - point.getZ(), newPoint.getZ(), point.getZ());
}
}
-#endif //DEBUG_CHECK_DEQUANTIZATION
-
+#endif //DEBUG_CHECK_DEQUANTIZATION
}
-
- B3_FORCE_INLINE void quantizeWithClamp(unsigned short* out, const b3Vector3& point2,int isMax) const
+ B3_FORCE_INLINE void quantizeWithClamp(unsigned short* out, const b3Vector3& point2, int isMax) const
{
-
b3Assert(m_useQuantization);
b3Vector3 clampedPoint(point2);
clampedPoint.setMax(m_bvhAabbMin);
clampedPoint.setMin(m_bvhAabbMax);
- quantize(out,clampedPoint,isMax);
-
+ quantize(out, clampedPoint, isMax);
}
-
- B3_FORCE_INLINE b3Vector3 unQuantize(const unsigned short* vecIn) const
+
+ B3_FORCE_INLINE b3Vector3 unQuantize(const unsigned short* vecIn) const
{
- b3Vector3 vecOut;
- vecOut.setValue(
+ b3Vector3 vecOut;
+ vecOut.setValue(
(b3Scalar)(vecIn[0]) / (m_bvhQuantization.getX()),
(b3Scalar)(vecIn[1]) / (m_bvhQuantization.getY()),
(b3Scalar)(vecIn[2]) / (m_bvhQuantization.getZ()));
- vecOut += m_bvhAabbMin;
- return vecOut;
+ vecOut += m_bvhAabbMin;
+ return vecOut;
}
///setTraversalMode let's you choose between stackless, recursive or stackless cache friendly tree traversal. Note this is only implemented for quantized trees.
- void setTraversalMode(b3TraversalMode traversalMode)
+ void setTraversalMode(b3TraversalMode traversalMode)
{
m_traversalMode = traversalMode;
}
-
- B3_FORCE_INLINE QuantizedNodeArray& getQuantizedNodeArray()
- {
- return m_quantizedContiguousNodes;
+ B3_FORCE_INLINE QuantizedNodeArray& getQuantizedNodeArray()
+ {
+ return m_quantizedContiguousNodes;
}
-
- B3_FORCE_INLINE BvhSubtreeInfoArray& getSubtreeInfoArray()
+ B3_FORCE_INLINE BvhSubtreeInfoArray& getSubtreeInfoArray()
{
return m_SubtreeHeaders;
}
-////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////
/////Calculate space needed to store BVH for serialization
unsigned calculateSerializeBufferSize() const;
/// Data buffer MUST be 16 byte aligned
- virtual bool serialize(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const;
+ virtual bool serialize(void* o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const;
///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
- static b3QuantizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
+ static b3QuantizedBvh* deSerializeInPlace(void* i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
static unsigned int getAlignmentSerializationPadding();
-//////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////
-
- virtual int calculateSerializeBufferSizeNew() const;
+ virtual int calculateSerializeBufferSizeNew() const;
///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, b3Serializer* serializer) const;
+ virtual const char* serialize(void* dataBuffer, b3Serializer* serializer) const;
- virtual void deSerializeFloat(struct b3QuantizedBvhFloatData& quantizedBvhFloatData);
+ virtual void deSerializeFloat(struct b3QuantizedBvhFloatData & quantizedBvhFloatData);
- virtual void deSerializeDouble(struct b3QuantizedBvhDoubleData& quantizedBvhDoubleData);
+ virtual void deSerializeDouble(struct b3QuantizedBvhDoubleData & quantizedBvhDoubleData);
-
-////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////
B3_FORCE_INLINE bool isQuantized()
{
@@ -483,74 +447,65 @@ private:
// Special "copy" constructor that allows for in-place deserialization
// Prevents b3Vector3's default constructor from being called, but doesn't inialize much else
// ownsMemory should most likely be false if deserializing, and if you are not, don't call this (it also changes the function signature, which we need)
- b3QuantizedBvh(b3QuantizedBvh &other, bool ownsMemory);
-
-}
-;
-
+ b3QuantizedBvh(b3QuantizedBvh & other, bool ownsMemory);
+};
struct b3OptimizedBvhNodeFloatData
{
- b3Vector3FloatData m_aabbMinOrg;
- b3Vector3FloatData m_aabbMaxOrg;
- int m_escapeIndex;
- int m_subPart;
- int m_triangleIndex;
+ b3Vector3FloatData m_aabbMinOrg;
+ b3Vector3FloatData m_aabbMaxOrg;
+ int m_escapeIndex;
+ int m_subPart;
+ int m_triangleIndex;
char m_pad[4];
};
struct b3OptimizedBvhNodeDoubleData
{
- b3Vector3DoubleData m_aabbMinOrg;
- b3Vector3DoubleData m_aabbMaxOrg;
- int m_escapeIndex;
- int m_subPart;
- int m_triangleIndex;
- char m_pad[4];
+ b3Vector3DoubleData m_aabbMinOrg;
+ b3Vector3DoubleData m_aabbMaxOrg;
+ int m_escapeIndex;
+ int m_subPart;
+ int m_triangleIndex;
+ char m_pad[4];
};
-
-
-struct b3QuantizedBvhFloatData
+struct b3QuantizedBvhFloatData
{
- b3Vector3FloatData m_bvhAabbMin;
- b3Vector3FloatData m_bvhAabbMax;
- b3Vector3FloatData m_bvhQuantization;
- int m_curNodeIndex;
- int m_useQuantization;
- int m_numContiguousLeafNodes;
- int m_numQuantizedContiguousNodes;
- b3OptimizedBvhNodeFloatData *m_contiguousNodesPtr;
- b3QuantizedBvhNodeData *m_quantizedContiguousNodesPtr;
- b3BvhSubtreeInfoData *m_subTreeInfoPtr;
- int m_traversalMode;
- int m_numSubtreeHeaders;
-
+ b3Vector3FloatData m_bvhAabbMin;
+ b3Vector3FloatData m_bvhAabbMax;
+ b3Vector3FloatData m_bvhQuantization;
+ int m_curNodeIndex;
+ int m_useQuantization;
+ int m_numContiguousLeafNodes;
+ int m_numQuantizedContiguousNodes;
+ b3OptimizedBvhNodeFloatData* m_contiguousNodesPtr;
+ b3QuantizedBvhNodeData* m_quantizedContiguousNodesPtr;
+ b3BvhSubtreeInfoData* m_subTreeInfoPtr;
+ int m_traversalMode;
+ int m_numSubtreeHeaders;
};
-struct b3QuantizedBvhDoubleData
+struct b3QuantizedBvhDoubleData
{
- b3Vector3DoubleData m_bvhAabbMin;
- b3Vector3DoubleData m_bvhAabbMax;
- b3Vector3DoubleData m_bvhQuantization;
- int m_curNodeIndex;
- int m_useQuantization;
- int m_numContiguousLeafNodes;
- int m_numQuantizedContiguousNodes;
- b3OptimizedBvhNodeDoubleData *m_contiguousNodesPtr;
- b3QuantizedBvhNodeData *m_quantizedContiguousNodesPtr;
-
- int m_traversalMode;
- int m_numSubtreeHeaders;
- b3BvhSubtreeInfoData *m_subTreeInfoPtr;
+ b3Vector3DoubleData m_bvhAabbMin;
+ b3Vector3DoubleData m_bvhAabbMax;
+ b3Vector3DoubleData m_bvhQuantization;
+ int m_curNodeIndex;
+ int m_useQuantization;
+ int m_numContiguousLeafNodes;
+ int m_numQuantizedContiguousNodes;
+ b3OptimizedBvhNodeDoubleData* m_contiguousNodesPtr;
+ b3QuantizedBvhNodeData* m_quantizedContiguousNodesPtr;
+
+ int m_traversalMode;
+ int m_numSubtreeHeaders;
+ b3BvhSubtreeInfoData* m_subTreeInfoPtr;
};
-
-B3_FORCE_INLINE int b3QuantizedBvh::calculateSerializeBufferSizeNew() const
+B3_FORCE_INLINE int b3QuantizedBvh::calculateSerializeBufferSizeNew() const
{
return sizeof(b3QuantizedBvhData);
}
-
-
-#endif //B3_QUANTIZED_BVH_H
+#endif //B3_QUANTIZED_BVH_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.cpp b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.cpp
index 4d97f7f62b..6b0c941f23 100644
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.cpp
+++ b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.cpp
@@ -15,35 +15,32 @@ subject to the following restrictions:
#include "b3StridingMeshInterface.h"
-
b3StridingMeshInterface::~b3StridingMeshInterface()
{
-
}
-
-void b3StridingMeshInterface::InternalProcessAllTriangles(b3InternalTriangleIndexCallback* callback,const b3Vector3& aabbMin,const b3Vector3& aabbMax) const
+void b3StridingMeshInterface::InternalProcessAllTriangles(b3InternalTriangleIndexCallback* callback, const b3Vector3& aabbMin, const b3Vector3& aabbMax) const
{
(void)aabbMin;
(void)aabbMax;
int numtotalphysicsverts = 0;
- int part,graphicssubparts = getNumSubParts();
- const unsigned char * vertexbase;
- const unsigned char * indexbase;
+ int part, graphicssubparts = getNumSubParts();
+ const unsigned char* vertexbase;
+ const unsigned char* indexbase;
int indexstride;
PHY_ScalarType type;
PHY_ScalarType gfxindextype;
- int stride,numverts,numtriangles;
+ int stride, numverts, numtriangles;
int gfxindex;
b3Vector3 triangle[3];
b3Vector3 meshScaling = getScaling();
///if the number of parts is big, the performance might drop due to the innerloop switch on indextype
- for (part=0;part<graphicssubparts ;part++)
+ for (part = 0; part < graphicssubparts; part++)
{
- getLockedReadOnlyVertexIndexBase(&vertexbase,numverts,type,stride,&indexbase,indexstride,numtriangles,gfxindextype,part);
- numtotalphysicsverts+=numtriangles*3; //upper bound
+ getLockedReadOnlyVertexIndexBase(&vertexbase, numverts, type, stride, &indexbase, indexstride, numtriangles, gfxindextype, part);
+ numtotalphysicsverts += numtriangles * 3; //upper bound
///unlike that developers want to pass in double-precision meshes in single-precision Bullet build
///so disable this feature by default
@@ -51,143 +48,141 @@ void b3StridingMeshInterface::InternalProcessAllTriangles(b3InternalTriangleInde
switch (type)
{
- case PHY_FLOAT:
- {
-
- float* graphicsbase;
-
- switch (gfxindextype)
- {
- case PHY_INTEGER:
- {
- for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
- {
- unsigned int* tri_indices= (unsigned int*)(indexbase+gfxindex*indexstride);
- graphicsbase = (float*)(vertexbase+tri_indices[0]*stride);
- triangle[0].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
- graphicsbase = (float*)(vertexbase+tri_indices[1]*stride);
- triangle[1].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(), graphicsbase[2]*meshScaling.getZ());
- graphicsbase = (float*)(vertexbase+tri_indices[2]*stride);
- triangle[2].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(), graphicsbase[2]*meshScaling.getZ());
- callback->internalProcessTriangleIndex(triangle,part,gfxindex);
- }
- break;
- }
- case PHY_SHORT:
- {
- for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
- {
- unsigned short int* tri_indices= (unsigned short int*)(indexbase+gfxindex*indexstride);
- graphicsbase = (float*)(vertexbase+tri_indices[0]*stride);
- triangle[0].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
- graphicsbase = (float*)(vertexbase+tri_indices[1]*stride);
- triangle[1].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(), graphicsbase[2]*meshScaling.getZ());
- graphicsbase = (float*)(vertexbase+tri_indices[2]*stride);
- triangle[2].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(), graphicsbase[2]*meshScaling.getZ());
- callback->internalProcessTriangleIndex(triangle,part,gfxindex);
- }
- break;
- }
- case PHY_UCHAR:
- {
- for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
- {
- unsigned char* tri_indices= (unsigned char*)(indexbase+gfxindex*indexstride);
- graphicsbase = (float*)(vertexbase+tri_indices[0]*stride);
- triangle[0].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
- graphicsbase = (float*)(vertexbase+tri_indices[1]*stride);
- triangle[1].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(), graphicsbase[2]*meshScaling.getZ());
- graphicsbase = (float*)(vertexbase+tri_indices[2]*stride);
- triangle[2].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(), graphicsbase[2]*meshScaling.getZ());
- callback->internalProcessTriangleIndex(triangle,part,gfxindex);
- }
- break;
- }
- default:
- b3Assert((gfxindextype == PHY_INTEGER) || (gfxindextype == PHY_SHORT));
- }
- break;
- }
-
- case PHY_DOUBLE:
+ case PHY_FLOAT:
+ {
+ float* graphicsbase;
+
+ switch (gfxindextype)
+ {
+ case PHY_INTEGER:
+ {
+ for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
+ {
+ unsigned int* tri_indices = (unsigned int*)(indexbase + gfxindex * indexstride);
+ graphicsbase = (float*)(vertexbase + tri_indices[0] * stride);
+ triangle[0].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
+ graphicsbase = (float*)(vertexbase + tri_indices[1] * stride);
+ triangle[1].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
+ graphicsbase = (float*)(vertexbase + tri_indices[2] * stride);
+ triangle[2].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
+ callback->internalProcessTriangleIndex(triangle, part, gfxindex);
+ }
+ break;
+ }
+ case PHY_SHORT:
+ {
+ for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
+ {
+ unsigned short int* tri_indices = (unsigned short int*)(indexbase + gfxindex * indexstride);
+ graphicsbase = (float*)(vertexbase + tri_indices[0] * stride);
+ triangle[0].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
+ graphicsbase = (float*)(vertexbase + tri_indices[1] * stride);
+ triangle[1].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
+ graphicsbase = (float*)(vertexbase + tri_indices[2] * stride);
+ triangle[2].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
+ callback->internalProcessTriangleIndex(triangle, part, gfxindex);
+ }
+ break;
+ }
+ case PHY_UCHAR:
+ {
+ for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
+ {
+ unsigned char* tri_indices = (unsigned char*)(indexbase + gfxindex * indexstride);
+ graphicsbase = (float*)(vertexbase + tri_indices[0] * stride);
+ triangle[0].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
+ graphicsbase = (float*)(vertexbase + tri_indices[1] * stride);
+ triangle[1].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
+ graphicsbase = (float*)(vertexbase + tri_indices[2] * stride);
+ triangle[2].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
+ callback->internalProcessTriangleIndex(triangle, part, gfxindex);
+ }
+ break;
+ }
+ default:
+ b3Assert((gfxindextype == PHY_INTEGER) || (gfxindextype == PHY_SHORT));
+ }
+ break;
+ }
+
+ case PHY_DOUBLE:
{
double* graphicsbase;
switch (gfxindextype)
{
- case PHY_INTEGER:
+ case PHY_INTEGER:
{
- for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
+ for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
{
- unsigned int* tri_indices= (unsigned int*)(indexbase+gfxindex*indexstride);
- graphicsbase = (double*)(vertexbase+tri_indices[0]*stride);
- triangle[0].setValue((b3Scalar)graphicsbase[0]*meshScaling.getX(),(b3Scalar)graphicsbase[1]*meshScaling.getY(),(b3Scalar)graphicsbase[2]*meshScaling.getZ());
- graphicsbase = (double*)(vertexbase+tri_indices[1]*stride);
- triangle[1].setValue((b3Scalar)graphicsbase[0]*meshScaling.getX(),(b3Scalar)graphicsbase[1]*meshScaling.getY(), (b3Scalar)graphicsbase[2]*meshScaling.getZ());
- graphicsbase = (double*)(vertexbase+tri_indices[2]*stride);
- triangle[2].setValue((b3Scalar)graphicsbase[0]*meshScaling.getX(),(b3Scalar)graphicsbase[1]*meshScaling.getY(), (b3Scalar)graphicsbase[2]*meshScaling.getZ());
- callback->internalProcessTriangleIndex(triangle,part,gfxindex);
+ unsigned int* tri_indices = (unsigned int*)(indexbase + gfxindex * indexstride);
+ graphicsbase = (double*)(vertexbase + tri_indices[0] * stride);
+ triangle[0].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
+ graphicsbase = (double*)(vertexbase + tri_indices[1] * stride);
+ triangle[1].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
+ graphicsbase = (double*)(vertexbase + tri_indices[2] * stride);
+ triangle[2].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
+ callback->internalProcessTriangleIndex(triangle, part, gfxindex);
}
break;
}
- case PHY_SHORT:
+ case PHY_SHORT:
{
- for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
+ for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
{
- unsigned short int* tri_indices= (unsigned short int*)(indexbase+gfxindex*indexstride);
- graphicsbase = (double*)(vertexbase+tri_indices[0]*stride);
- triangle[0].setValue((b3Scalar)graphicsbase[0]*meshScaling.getX(),(b3Scalar)graphicsbase[1]*meshScaling.getY(),(b3Scalar)graphicsbase[2]*meshScaling.getZ());
- graphicsbase = (double*)(vertexbase+tri_indices[1]*stride);
- triangle[1].setValue((b3Scalar)graphicsbase[0]*meshScaling.getX(),(b3Scalar)graphicsbase[1]*meshScaling.getY(), (b3Scalar)graphicsbase[2]*meshScaling.getZ());
- graphicsbase = (double*)(vertexbase+tri_indices[2]*stride);
- triangle[2].setValue((b3Scalar)graphicsbase[0]*meshScaling.getX(),(b3Scalar)graphicsbase[1]*meshScaling.getY(), (b3Scalar)graphicsbase[2]*meshScaling.getZ());
- callback->internalProcessTriangleIndex(triangle,part,gfxindex);
+ unsigned short int* tri_indices = (unsigned short int*)(indexbase + gfxindex * indexstride);
+ graphicsbase = (double*)(vertexbase + tri_indices[0] * stride);
+ triangle[0].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
+ graphicsbase = (double*)(vertexbase + tri_indices[1] * stride);
+ triangle[1].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
+ graphicsbase = (double*)(vertexbase + tri_indices[2] * stride);
+ triangle[2].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
+ callback->internalProcessTriangleIndex(triangle, part, gfxindex);
}
break;
}
- case PHY_UCHAR:
+ case PHY_UCHAR:
{
- for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
+ for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
{
- unsigned char* tri_indices= (unsigned char*)(indexbase+gfxindex*indexstride);
- graphicsbase = (double*)(vertexbase+tri_indices[0]*stride);
- triangle[0].setValue((b3Scalar)graphicsbase[0]*meshScaling.getX(),(b3Scalar)graphicsbase[1]*meshScaling.getY(),(b3Scalar)graphicsbase[2]*meshScaling.getZ());
- graphicsbase = (double*)(vertexbase+tri_indices[1]*stride);
- triangle[1].setValue((b3Scalar)graphicsbase[0]*meshScaling.getX(),(b3Scalar)graphicsbase[1]*meshScaling.getY(), (b3Scalar)graphicsbase[2]*meshScaling.getZ());
- graphicsbase = (double*)(vertexbase+tri_indices[2]*stride);
- triangle[2].setValue((b3Scalar)graphicsbase[0]*meshScaling.getX(),(b3Scalar)graphicsbase[1]*meshScaling.getY(), (b3Scalar)graphicsbase[2]*meshScaling.getZ());
- callback->internalProcessTriangleIndex(triangle,part,gfxindex);
+ unsigned char* tri_indices = (unsigned char*)(indexbase + gfxindex * indexstride);
+ graphicsbase = (double*)(vertexbase + tri_indices[0] * stride);
+ triangle[0].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
+ graphicsbase = (double*)(vertexbase + tri_indices[1] * stride);
+ triangle[1].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
+ graphicsbase = (double*)(vertexbase + tri_indices[2] * stride);
+ triangle[2].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
+ callback->internalProcessTriangleIndex(triangle, part, gfxindex);
}
break;
}
- default:
- b3Assert((gfxindextype == PHY_INTEGER) || (gfxindextype == PHY_SHORT));
+ default:
+ b3Assert((gfxindextype == PHY_INTEGER) || (gfxindextype == PHY_SHORT));
}
break;
}
- default:
- b3Assert((type == PHY_FLOAT) || (type == PHY_DOUBLE));
+ default:
+ b3Assert((type == PHY_FLOAT) || (type == PHY_DOUBLE));
}
unLockReadOnlyVertexBase(part);
}
}
-void b3StridingMeshInterface::calculateAabbBruteForce(b3Vector3& aabbMin,b3Vector3& aabbMax)
+void b3StridingMeshInterface::calculateAabbBruteForce(b3Vector3& aabbMin, b3Vector3& aabbMax)
{
-
- struct AabbCalculationCallback : public b3InternalTriangleIndexCallback
+ struct AabbCalculationCallback : public b3InternalTriangleIndexCallback
{
- b3Vector3 m_aabbMin;
- b3Vector3 m_aabbMax;
+ b3Vector3 m_aabbMin;
+ b3Vector3 m_aabbMax;
AabbCalculationCallback()
{
- m_aabbMin.setValue(b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT));
- m_aabbMax.setValue(b3Scalar(-B3_LARGE_FLOAT),b3Scalar(-B3_LARGE_FLOAT),b3Scalar(-B3_LARGE_FLOAT));
+ m_aabbMin.setValue(b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT));
+ m_aabbMax.setValue(b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT));
}
- virtual void internalProcessTriangleIndex(b3Vector3* triangle,int partId,int triangleIndex)
+ virtual void internalProcessTriangleIndex(b3Vector3* triangle, int partId, int triangleIndex)
{
(void)partId;
(void)triangleIndex;
@@ -202,13 +197,11 @@ void b3StridingMeshInterface::calculateAabbBruteForce(b3Vector3& aabbMin,b3Vecto
};
//first calculate the total aabb for all triangles
- AabbCalculationCallback aabbCallback;
- aabbMin.setValue(b3Scalar(-B3_LARGE_FLOAT),b3Scalar(-B3_LARGE_FLOAT),b3Scalar(-B3_LARGE_FLOAT));
- aabbMax.setValue(b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT));
- InternalProcessAllTriangles(&aabbCallback,aabbMin,aabbMax);
+ AabbCalculationCallback aabbCallback;
+ aabbMin.setValue(b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT));
+ aabbMax.setValue(b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT));
+ InternalProcessAllTriangles(&aabbCallback, aabbMin, aabbMax);
aabbMin = aabbCallback.m_aabbMin;
aabbMax = aabbCallback.m_aabbMax;
}
-
-
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.h
index 9513f68f77..087b30f3e6 100644
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.h
+++ b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.h
@@ -20,148 +20,139 @@ subject to the following restrictions:
#include "b3TriangleCallback.h"
//#include "b3ConcaveShape.h"
-
-enum PHY_ScalarType {
- PHY_FLOAT, PHY_DOUBLE, PHY_INTEGER, PHY_SHORT,
- PHY_FIXEDPOINT88, PHY_UCHAR
+enum PHY_ScalarType
+{
+ PHY_FLOAT,
+ PHY_DOUBLE,
+ PHY_INTEGER,
+ PHY_SHORT,
+ PHY_FIXEDPOINT88,
+ PHY_UCHAR
};
-
/// The b3StridingMeshInterface is the interface class for high performance generic access to triangle meshes, used in combination with b3BvhTriangleMeshShape and some other collision shapes.
/// Using index striding of 3*sizeof(integer) it can use triangle arrays, using index striding of 1*sizeof(integer) it can handle triangle strips.
/// It allows for sharing graphics and collision meshes. Also it provides locking/unlocking of graphics meshes that are in gpu memory.
-B3_ATTRIBUTE_ALIGNED16(class ) b3StridingMeshInterface
+B3_ATTRIBUTE_ALIGNED16(class)
+b3StridingMeshInterface
{
- protected:
-
- b3Vector3 m_scaling;
-
- public:
- B3_DECLARE_ALIGNED_ALLOCATOR();
-
- b3StridingMeshInterface() :m_scaling(b3MakeVector3(b3Scalar(1.),b3Scalar(1.),b3Scalar(1.)))
- {
-
- }
-
- virtual ~b3StridingMeshInterface();
-
-
-
- virtual void InternalProcessAllTriangles(b3InternalTriangleIndexCallback* callback,const b3Vector3& aabbMin,const b3Vector3& aabbMax) const;
-
- ///brute force method to calculate aabb
- void calculateAabbBruteForce(b3Vector3& aabbMin,b3Vector3& aabbMax);
-
- /// get read and write access to a subpart of a triangle mesh
- /// this subpart has a continuous array of vertices and indices
- /// in this way the mesh can be handled as chunks of memory with striding
- /// very similar to OpenGL vertexarray support
- /// make a call to unLockVertexBase when the read and write access is finished
- virtual void getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0)=0;
-
- virtual void getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0) const=0;
-
- /// unLockVertexBase finishes the access to a subpart of the triangle mesh
- /// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished
- virtual void unLockVertexBase(int subpart)=0;
-
- virtual void unLockReadOnlyVertexBase(int subpart) const=0;
-
-
- /// getNumSubParts returns the number of seperate subparts
- /// each subpart has a continuous array of vertices and indices
- virtual int getNumSubParts() const=0;
-
- virtual void preallocateVertices(int numverts)=0;
- virtual void preallocateIndices(int numindices)=0;
-
- virtual bool hasPremadeAabb() const { return false; }
- virtual void setPremadeAabb(const b3Vector3& aabbMin, const b3Vector3& aabbMax ) const
- {
- (void) aabbMin;
- (void) aabbMax;
- }
- virtual void getPremadeAabb(b3Vector3* aabbMin, b3Vector3* aabbMax ) const
- {
- (void) aabbMin;
- (void) aabbMax;
- }
-
- const b3Vector3& getScaling() const {
- return m_scaling;
- }
- void setScaling(const b3Vector3& scaling)
- {
- m_scaling = scaling;
- }
-
- virtual int calculateSerializeBufferSize() const;
-
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
- //virtual const char* serialize(void* dataBuffer, b3Serializer* serializer) const;
-
-
+protected:
+ b3Vector3 m_scaling;
+
+public:
+ B3_DECLARE_ALIGNED_ALLOCATOR();
+
+ b3StridingMeshInterface() : m_scaling(b3MakeVector3(b3Scalar(1.), b3Scalar(1.), b3Scalar(1.)))
+ {
+ }
+
+ virtual ~b3StridingMeshInterface();
+
+ virtual void InternalProcessAllTriangles(b3InternalTriangleIndexCallback * callback, const b3Vector3& aabbMin, const b3Vector3& aabbMax) const;
+
+ ///brute force method to calculate aabb
+ void calculateAabbBruteForce(b3Vector3 & aabbMin, b3Vector3 & aabbMax);
+
+ /// get read and write access to a subpart of a triangle mesh
+ /// this subpart has a continuous array of vertices and indices
+ /// in this way the mesh can be handled as chunks of memory with striding
+ /// very similar to OpenGL vertexarray support
+ /// make a call to unLockVertexBase when the read and write access is finished
+ virtual void getLockedVertexIndexBase(unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& stride, unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart = 0) = 0;
+
+ virtual void getLockedReadOnlyVertexIndexBase(const unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& stride, const unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart = 0) const = 0;
+
+ /// unLockVertexBase finishes the access to a subpart of the triangle mesh
+ /// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished
+ virtual void unLockVertexBase(int subpart) = 0;
+
+ virtual void unLockReadOnlyVertexBase(int subpart) const = 0;
+
+ /// getNumSubParts returns the number of seperate subparts
+ /// each subpart has a continuous array of vertices and indices
+ virtual int getNumSubParts() const = 0;
+
+ virtual void preallocateVertices(int numverts) = 0;
+ virtual void preallocateIndices(int numindices) = 0;
+
+ virtual bool hasPremadeAabb() const { return false; }
+ virtual void setPremadeAabb(const b3Vector3& aabbMin, const b3Vector3& aabbMax) const
+ {
+ (void)aabbMin;
+ (void)aabbMax;
+ }
+ virtual void getPremadeAabb(b3Vector3 * aabbMin, b3Vector3 * aabbMax) const
+ {
+ (void)aabbMin;
+ (void)aabbMax;
+ }
+
+ const b3Vector3& getScaling() const
+ {
+ return m_scaling;
+ }
+ void setScaling(const b3Vector3& scaling)
+ {
+ m_scaling = scaling;
+ }
+
+ virtual int calculateSerializeBufferSize() const;
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+ //virtual const char* serialize(void* dataBuffer, b3Serializer* serializer) const;
};
-struct b3IntIndexData
+struct b3IntIndexData
{
- int m_value;
+ int m_value;
};
-struct b3ShortIntIndexData
+struct b3ShortIntIndexData
{
short m_value;
char m_pad[2];
};
-struct b3ShortIntIndexTripletData
+struct b3ShortIntIndexTripletData
{
- short m_values[3];
- char m_pad[2];
+ short m_values[3];
+ char m_pad[2];
};
-struct b3CharIndexTripletData
+struct b3CharIndexTripletData
{
unsigned char m_values[3];
- char m_pad;
+ char m_pad;
};
-
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct b3MeshPartData
+struct b3MeshPartData
{
- b3Vector3FloatData *m_vertices3f;
- b3Vector3DoubleData *m_vertices3d;
+ b3Vector3FloatData* m_vertices3f;
+ b3Vector3DoubleData* m_vertices3d;
- b3IntIndexData *m_indices32;
- b3ShortIntIndexTripletData *m_3indices16;
- b3CharIndexTripletData *m_3indices8;
+ b3IntIndexData* m_indices32;
+ b3ShortIntIndexTripletData* m_3indices16;
+ b3CharIndexTripletData* m_3indices8;
- b3ShortIntIndexData *m_indices16;//backwards compatibility
+ b3ShortIntIndexData* m_indices16; //backwards compatibility
- int m_numTriangles;//length of m_indices = m_numTriangles
- int m_numVertices;
+ int m_numTriangles; //length of m_indices = m_numTriangles
+ int m_numVertices;
};
-
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct b3StridingMeshInterfaceData
+struct b3StridingMeshInterfaceData
{
- b3MeshPartData *m_meshPartsPtr;
- b3Vector3FloatData m_scaling;
- int m_numMeshParts;
+ b3MeshPartData* m_meshPartsPtr;
+ b3Vector3FloatData m_scaling;
+ int m_numMeshParts;
char m_padding[4];
};
-
-
-
-B3_FORCE_INLINE int b3StridingMeshInterface::calculateSerializeBufferSize() const
+B3_FORCE_INLINE int b3StridingMeshInterface::calculateSerializeBufferSize() const
{
return sizeof(b3StridingMeshInterfaceData);
}
-
-
-#endif //B3_STRIDING_MESHINTERFACE_H
+#endif //B3_STRIDING_MESHINTERFACE_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3SupportMappings.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3SupportMappings.h
index d073ee57c3..9ca1e22949 100644
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3SupportMappings.h
+++ b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3SupportMappings.h
@@ -6,33 +6,29 @@
#include "Bullet3Common/b3AlignedObjectArray.h"
#include "b3VectorFloat4.h"
-
struct b3GjkPairDetector;
-
-
-inline b3Vector3 localGetSupportVertexWithMargin(const float4& supportVec,const struct b3ConvexPolyhedronData* hull,
- const b3AlignedObjectArray<b3Vector3>& verticesA, b3Scalar margin)
+inline b3Vector3 localGetSupportVertexWithMargin(const float4& supportVec, const struct b3ConvexPolyhedronData* hull,
+ const b3AlignedObjectArray<b3Vector3>& verticesA, b3Scalar margin)
{
- b3Vector3 supVec = b3MakeVector3(b3Scalar(0.),b3Scalar(0.),b3Scalar(0.));
+ b3Vector3 supVec = b3MakeVector3(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.));
b3Scalar maxDot = b3Scalar(-B3_LARGE_FLOAT);
- // Here we take advantage of dot(a, b*c) = dot(a*b, c). Note: This is true mathematically, but not numerically.
- if( 0 < hull->m_numVertices )
- {
- const b3Vector3 scaled = supportVec;
- int index = (int) scaled.maxDot( &verticesA[hull->m_vertexOffset], hull->m_numVertices, maxDot);
- return verticesA[hull->m_vertexOffset+index];
- }
-
- return supVec;
+ // Here we take advantage of dot(a, b*c) = dot(a*b, c). Note: This is true mathematically, but not numerically.
+ if (0 < hull->m_numVertices)
+ {
+ const b3Vector3 scaled = supportVec;
+ int index = (int)scaled.maxDot(&verticesA[hull->m_vertexOffset], hull->m_numVertices, maxDot);
+ return verticesA[hull->m_vertexOffset + index];
+ }
+ return supVec;
}
-inline b3Vector3 localGetSupportVertexWithoutMargin(const float4& supportVec,const struct b3ConvexPolyhedronData* hull,
- const b3AlignedObjectArray<b3Vector3>& verticesA)
+inline b3Vector3 localGetSupportVertexWithoutMargin(const float4& supportVec, const struct b3ConvexPolyhedronData* hull,
+ const b3AlignedObjectArray<b3Vector3>& verticesA)
{
- return localGetSupportVertexWithMargin(supportVec,hull,verticesA,0.f);
+ return localGetSupportVertexWithMargin(supportVec, hull, verticesA, 0.f);
}
-#endif //B3_SUPPORT_MAPPINGS_H
+#endif //B3_SUPPORT_MAPPINGS_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleCallback.cpp b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleCallback.cpp
index 9066451884..3908c6de89 100644
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleCallback.cpp
+++ b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleCallback.cpp
@@ -17,12 +17,8 @@ subject to the following restrictions:
b3TriangleCallback::~b3TriangleCallback()
{
-
}
-
b3InternalTriangleIndexCallback::~b3InternalTriangleIndexCallback()
{
-
}
-
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleCallback.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleCallback.h
index 3059fa4f21..a0fd3e7ac7 100644
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleCallback.h
+++ b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleCallback.h
@@ -18,13 +18,11 @@ subject to the following restrictions:
#include "Bullet3Common/b3Vector3.h"
-
///The b3TriangleCallback provides a callback for each overlapping triangle when calling processAllTriangles.
///This callback is called by processAllTriangles for all b3ConcaveShape derived class, such as b3BvhTriangleMeshShape, b3StaticPlaneShape and b3HeightfieldTerrainShape.
class b3TriangleCallback
{
public:
-
virtual ~b3TriangleCallback();
virtual void processTriangle(b3Vector3* triangle, int partId, int triangleIndex) = 0;
};
@@ -32,11 +30,8 @@ public:
class b3InternalTriangleIndexCallback
{
public:
-
virtual ~b3InternalTriangleIndexCallback();
- virtual void internalProcessTriangleIndex(b3Vector3* triangle,int partId,int triangleIndex) = 0;
+ virtual void internalProcessTriangleIndex(b3Vector3* triangle, int partId, int triangleIndex) = 0;
};
-
-
-#endif //B3_TRIANGLE_CALLBACK_H
+#endif //B3_TRIANGLE_CALLBACK_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.cpp b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.cpp
index a0f59babbe..73faadbdd0 100644
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.cpp
+++ b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.cpp
@@ -15,81 +15,76 @@ subject to the following restrictions:
#include "b3TriangleIndexVertexArray.h"
-b3TriangleIndexVertexArray::b3TriangleIndexVertexArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,int numVertices,b3Scalar* vertexBase,int vertexStride)
-: m_hasAabb(0)
+b3TriangleIndexVertexArray::b3TriangleIndexVertexArray(int numTriangles, int* triangleIndexBase, int triangleIndexStride, int numVertices, b3Scalar* vertexBase, int vertexStride)
+ : m_hasAabb(0)
{
b3IndexedMesh mesh;
mesh.m_numTriangles = numTriangles;
- mesh.m_triangleIndexBase = (const unsigned char *)triangleIndexBase;
+ mesh.m_triangleIndexBase = (const unsigned char*)triangleIndexBase;
mesh.m_triangleIndexStride = triangleIndexStride;
mesh.m_numVertices = numVertices;
- mesh.m_vertexBase = (const unsigned char *)vertexBase;
+ mesh.m_vertexBase = (const unsigned char*)vertexBase;
mesh.m_vertexStride = vertexStride;
addIndexedMesh(mesh);
-
}
b3TriangleIndexVertexArray::~b3TriangleIndexVertexArray()
{
-
}
-void b3TriangleIndexVertexArray::getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart)
+void b3TriangleIndexVertexArray::getLockedVertexIndexBase(unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& vertexStride, unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart)
{
- b3Assert(subpart< getNumSubParts() );
+ b3Assert(subpart < getNumSubParts());
b3IndexedMesh& mesh = m_indexedMeshes[subpart];
numverts = mesh.m_numVertices;
- (*vertexbase) = (unsigned char *) mesh.m_vertexBase;
+ (*vertexbase) = (unsigned char*)mesh.m_vertexBase;
- type = mesh.m_vertexType;
+ type = mesh.m_vertexType;
vertexStride = mesh.m_vertexStride;
numfaces = mesh.m_numTriangles;
- (*indexbase) = (unsigned char *)mesh.m_triangleIndexBase;
+ (*indexbase) = (unsigned char*)mesh.m_triangleIndexBase;
indexstride = mesh.m_triangleIndexStride;
indicestype = mesh.m_indexType;
}
-void b3TriangleIndexVertexArray::getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart) const
+void b3TriangleIndexVertexArray::getLockedReadOnlyVertexIndexBase(const unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& vertexStride, const unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart) const
{
const b3IndexedMesh& mesh = m_indexedMeshes[subpart];
numverts = mesh.m_numVertices;
- (*vertexbase) = (const unsigned char *)mesh.m_vertexBase;
+ (*vertexbase) = (const unsigned char*)mesh.m_vertexBase;
+
+ type = mesh.m_vertexType;
- type = mesh.m_vertexType;
-
vertexStride = mesh.m_vertexStride;
numfaces = mesh.m_numTriangles;
- (*indexbase) = (const unsigned char *)mesh.m_triangleIndexBase;
+ (*indexbase) = (const unsigned char*)mesh.m_triangleIndexBase;
indexstride = mesh.m_triangleIndexStride;
indicestype = mesh.m_indexType;
}
-bool b3TriangleIndexVertexArray::hasPremadeAabb() const
+bool b3TriangleIndexVertexArray::hasPremadeAabb() const
{
return (m_hasAabb == 1);
}
-
-void b3TriangleIndexVertexArray::setPremadeAabb(const b3Vector3& aabbMin, const b3Vector3& aabbMax ) const
+void b3TriangleIndexVertexArray::setPremadeAabb(const b3Vector3& aabbMin, const b3Vector3& aabbMax) const
{
m_aabbMin = aabbMin;
m_aabbMax = aabbMax;
- m_hasAabb = 1; // this is intentionally an int see notes in header
+ m_hasAabb = 1; // this is intentionally an int see notes in header
}
-void b3TriangleIndexVertexArray::getPremadeAabb(b3Vector3* aabbMin, b3Vector3* aabbMax ) const
+void b3TriangleIndexVertexArray::getPremadeAabb(b3Vector3* aabbMin, b3Vector3* aabbMax) const
{
*aabbMin = m_aabbMin;
*aabbMax = m_aabbMax;
}
-
-
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.h
index d26b2893bc..b6ceb8df10 100644
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.h
+++ b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.h
@@ -20,62 +20,59 @@ subject to the following restrictions:
#include "Bullet3Common/b3AlignedObjectArray.h"
#include "Bullet3Common/b3Scalar.h"
-
///The b3IndexedMesh indexes a single vertex and index array. Multiple b3IndexedMesh objects can be passed into a b3TriangleIndexVertexArray using addIndexedMesh.
///Instead of the number of indices, we pass the number of triangles.
-B3_ATTRIBUTE_ALIGNED16( struct) b3IndexedMesh
+B3_ATTRIBUTE_ALIGNED16(struct)
+b3IndexedMesh
{
B3_DECLARE_ALIGNED_ALLOCATOR();
- int m_numTriangles;
- const unsigned char * m_triangleIndexBase;
- // Size in byte of the indices for one triangle (3*sizeof(index_type) if the indices are tightly packed)
- int m_triangleIndexStride;
- int m_numVertices;
- const unsigned char * m_vertexBase;
- // Size of a vertex, in bytes
- int m_vertexStride;
-
- // The index type is set when adding an indexed mesh to the
- // b3TriangleIndexVertexArray, do not set it manually
- PHY_ScalarType m_indexType;
-
- // The vertex type has a default type similar to Bullet's precision mode (float or double)
- // but can be set manually if you for example run Bullet with double precision but have
- // mesh data in single precision..
- PHY_ScalarType m_vertexType;
-
-
- b3IndexedMesh()
- :m_indexType(PHY_INTEGER),
+ int m_numTriangles;
+ const unsigned char* m_triangleIndexBase;
+ // Size in byte of the indices for one triangle (3*sizeof(index_type) if the indices are tightly packed)
+ int m_triangleIndexStride;
+ int m_numVertices;
+ const unsigned char* m_vertexBase;
+ // Size of a vertex, in bytes
+ int m_vertexStride;
+
+ // The index type is set when adding an indexed mesh to the
+ // b3TriangleIndexVertexArray, do not set it manually
+ PHY_ScalarType m_indexType;
+
+ // The vertex type has a default type similar to Bullet's precision mode (float or double)
+ // but can be set manually if you for example run Bullet with double precision but have
+ // mesh data in single precision..
+ PHY_ScalarType m_vertexType;
+
+ b3IndexedMesh()
+ : m_indexType(PHY_INTEGER),
#ifdef B3_USE_DOUBLE_PRECISION
- m_vertexType(PHY_DOUBLE)
-#else // B3_USE_DOUBLE_PRECISION
- m_vertexType(PHY_FLOAT)
-#endif // B3_USE_DOUBLE_PRECISION
- {
- }
-}
-;
-
+ m_vertexType(PHY_DOUBLE)
+#else // B3_USE_DOUBLE_PRECISION
+ m_vertexType(PHY_FLOAT)
+#endif // B3_USE_DOUBLE_PRECISION
+ {
+ }
+};
-typedef b3AlignedObjectArray<b3IndexedMesh> IndexedMeshArray;
+typedef b3AlignedObjectArray<b3IndexedMesh> IndexedMeshArray;
///The b3TriangleIndexVertexArray allows to access multiple triangle meshes, by indexing into existing triangle/index arrays.
///Additional meshes can be added using addIndexedMesh
///No duplcate is made of the vertex/index data, it only indexes into external vertex/index arrays.
///So keep those arrays around during the lifetime of this b3TriangleIndexVertexArray.
-B3_ATTRIBUTE_ALIGNED16( class) b3TriangleIndexVertexArray : public b3StridingMeshInterface
+B3_ATTRIBUTE_ALIGNED16(class)
+b3TriangleIndexVertexArray : public b3StridingMeshInterface
{
protected:
- IndexedMeshArray m_indexedMeshes;
+ IndexedMeshArray m_indexedMeshes;
int m_pad[2];
- mutable int m_hasAabb; // using int instead of bool to maintain alignment
+ mutable int m_hasAabb; // using int instead of bool to maintain alignment
mutable b3Vector3 m_aabbMin;
mutable b3Vector3 m_aabbMax;
public:
-
B3_DECLARE_ALIGNED_ALLOCATOR();
b3TriangleIndexVertexArray() : m_hasAabb(0)
@@ -85,49 +82,47 @@ public:
virtual ~b3TriangleIndexVertexArray();
//just to be backwards compatible
- b3TriangleIndexVertexArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,int numVertices,b3Scalar* vertexBase,int vertexStride);
-
- void addIndexedMesh(const b3IndexedMesh& mesh, PHY_ScalarType indexType = PHY_INTEGER)
+ b3TriangleIndexVertexArray(int numTriangles, int* triangleIndexBase, int triangleIndexStride, int numVertices, b3Scalar* vertexBase, int vertexStride);
+
+ void addIndexedMesh(const b3IndexedMesh& mesh, PHY_ScalarType indexType = PHY_INTEGER)
{
m_indexedMeshes.push_back(mesh);
- m_indexedMeshes[m_indexedMeshes.size()-1].m_indexType = indexType;
+ m_indexedMeshes[m_indexedMeshes.size() - 1].m_indexType = indexType;
}
-
-
- virtual void getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0);
- virtual void getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0) const;
+ virtual void getLockedVertexIndexBase(unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& vertexStride, unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart = 0);
+
+ virtual void getLockedReadOnlyVertexIndexBase(const unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& vertexStride, const unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart = 0) const;
/// unLockVertexBase finishes the access to a subpart of the triangle mesh
/// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished
- virtual void unLockVertexBase(int subpart) {(void)subpart;}
+ virtual void unLockVertexBase(int subpart) { (void)subpart; }
- virtual void unLockReadOnlyVertexBase(int subpart) const {(void)subpart;}
+ virtual void unLockReadOnlyVertexBase(int subpart) const { (void)subpart; }
/// getNumSubParts returns the number of seperate subparts
/// each subpart has a continuous array of vertices and indices
- virtual int getNumSubParts() const {
+ virtual int getNumSubParts() const
+ {
return (int)m_indexedMeshes.size();
}
- IndexedMeshArray& getIndexedMeshArray()
+ IndexedMeshArray& getIndexedMeshArray()
{
return m_indexedMeshes;
}
- const IndexedMeshArray& getIndexedMeshArray() const
+ const IndexedMeshArray& getIndexedMeshArray() const
{
return m_indexedMeshes;
}
- virtual void preallocateVertices(int numverts){(void) numverts;}
- virtual void preallocateIndices(int numindices){(void) numindices;}
-
- virtual bool hasPremadeAabb() const;
- virtual void setPremadeAabb(const b3Vector3& aabbMin, const b3Vector3& aabbMax ) const;
- virtual void getPremadeAabb(b3Vector3* aabbMin, b3Vector3* aabbMax ) const;
+ virtual void preallocateVertices(int numverts) { (void)numverts; }
+ virtual void preallocateIndices(int numindices) { (void)numindices; }
-}
-;
+ virtual bool hasPremadeAabb() const;
+ virtual void setPremadeAabb(const b3Vector3& aabbMin, const b3Vector3& aabbMax) const;
+ virtual void getPremadeAabb(b3Vector3 * aabbMin, b3Vector3 * aabbMax) const;
+};
-#endif //B3_TRIANGLE_INDEX_VERTEX_ARRAY_H
+#endif //B3_TRIANGLE_INDEX_VERTEX_ARRAY_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3VectorFloat4.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3VectorFloat4.h
index f6f65f7719..5cc4b5a626 100644
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3VectorFloat4.h
+++ b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3VectorFloat4.h
@@ -7,5 +7,4 @@
#define float4 b3Vector3
//#define make_float4(x,y,z,w) b3Vector4(x,y,z,w)
-
-#endif //B3_VECTOR_FLOAT4_H
+#endif //B3_VECTOR_FLOAT4_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.cpp b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.cpp
index cf3d5ef49d..dae61d4581 100644
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.cpp
+++ b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.cpp
@@ -23,26 +23,24 @@ subject to the following restrictions:
*/
-
#include "b3VoronoiSimplexSolver.h"
-#define VERTA 0
-#define VERTB 1
-#define VERTC 2
-#define VERTD 3
+#define VERTA 0
+#define VERTB 1
+#define VERTC 2
+#define VERTD 3
#define B3_CATCH_DEGENERATE_TETRAHEDRON 1
-void b3VoronoiSimplexSolver::removeVertex(int index)
+void b3VoronoiSimplexSolver::removeVertex(int index)
{
-
- b3Assert(m_numVertices>0);
+ b3Assert(m_numVertices > 0);
m_numVertices--;
m_simplexVectorW[index] = m_simplexVectorW[m_numVertices];
m_simplexPointsP[index] = m_simplexPointsP[m_numVertices];
m_simplexPointsQ[index] = m_simplexPointsQ[m_numVertices];
}
-void b3VoronoiSimplexSolver::reduceVertices (const b3UsageBitfield& usedVerts)
+void b3VoronoiSimplexSolver::reduceVertices(const b3UsageBitfield& usedVerts)
{
if ((numVertices() >= 4) && (!usedVerts.usedVertexD))
removeVertex(3);
@@ -52,29 +50,22 @@ void b3VoronoiSimplexSolver::reduceVertices (const b3UsageBitfield& usedVerts)
if ((numVertices() >= 2) && (!usedVerts.usedVertexB))
removeVertex(1);
-
+
if ((numVertices() >= 1) && (!usedVerts.usedVertexA))
removeVertex(0);
-
}
-
-
-
-
//clear the simplex, remove all the vertices
void b3VoronoiSimplexSolver::reset()
{
m_cachedValidClosest = false;
m_numVertices = 0;
m_needsUpdate = true;
- m_lastW = b3MakeVector3(b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT));
+ m_lastW = b3MakeVector3(b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT));
m_cachedBC.reset();
}
-
-
- //add a vertex
+//add a vertex
void b3VoronoiSimplexSolver::addVertex(const b3Vector3& w, const b3Vector3& p, const b3Vector3& q)
{
m_lastW = w;
@@ -87,9 +78,8 @@ void b3VoronoiSimplexSolver::addVertex(const b3Vector3& w, const b3Vector3& p, c
m_numVertices++;
}
-bool b3VoronoiSimplexSolver::updateClosestVectorAndPoints()
+bool b3VoronoiSimplexSolver::updateClosestVectorAndPoints()
{
-
if (m_needsUpdate)
{
m_cachedBC.reset();
@@ -98,127 +88,131 @@ bool b3VoronoiSimplexSolver::updateClosestVectorAndPoints()
switch (numVertices())
{
- case 0:
+ case 0:
m_cachedValidClosest = false;
break;
- case 1:
+ case 1:
{
m_cachedP1 = m_simplexPointsP[0];
m_cachedP2 = m_simplexPointsQ[0];
- m_cachedV = m_cachedP1-m_cachedP2; //== m_simplexVectorW[0]
+ m_cachedV = m_cachedP1 - m_cachedP2; //== m_simplexVectorW[0]
m_cachedBC.reset();
- m_cachedBC.setBarycentricCoordinates(b3Scalar(1.),b3Scalar(0.),b3Scalar(0.),b3Scalar(0.));
+ m_cachedBC.setBarycentricCoordinates(b3Scalar(1.), b3Scalar(0.), b3Scalar(0.), b3Scalar(0.));
m_cachedValidClosest = m_cachedBC.isValid();
break;
};
- case 2:
+ case 2:
{
- //closest point origin from line segment
- const b3Vector3& from = m_simplexVectorW[0];
- const b3Vector3& to = m_simplexVectorW[1];
- b3Vector3 nearest;
-
- b3Vector3 p =b3MakeVector3(b3Scalar(0.),b3Scalar(0.),b3Scalar(0.));
- b3Vector3 diff = p - from;
- b3Vector3 v = to - from;
- b3Scalar t = v.dot(diff);
-
- if (t > 0) {
- b3Scalar dotVV = v.dot(v);
- if (t < dotVV) {
- t /= dotVV;
- diff -= t*v;
- m_cachedBC.m_usedVertices.usedVertexA = true;
- m_cachedBC.m_usedVertices.usedVertexB = true;
- } else {
- t = 1;
- diff -= v;
- //reduce to 1 point
- m_cachedBC.m_usedVertices.usedVertexB = true;
- }
- } else
+ //closest point origin from line segment
+ const b3Vector3& from = m_simplexVectorW[0];
+ const b3Vector3& to = m_simplexVectorW[1];
+ b3Vector3 nearest;
+
+ b3Vector3 p = b3MakeVector3(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.));
+ b3Vector3 diff = p - from;
+ b3Vector3 v = to - from;
+ b3Scalar t = v.dot(diff);
+
+ if (t > 0)
+ {
+ b3Scalar dotVV = v.dot(v);
+ if (t < dotVV)
{
- t = 0;
- //reduce to 1 point
+ t /= dotVV;
+ diff -= t * v;
m_cachedBC.m_usedVertices.usedVertexA = true;
+ m_cachedBC.m_usedVertices.usedVertexB = true;
+ }
+ else
+ {
+ t = 1;
+ diff -= v;
+ //reduce to 1 point
+ m_cachedBC.m_usedVertices.usedVertexB = true;
}
- m_cachedBC.setBarycentricCoordinates(1-t,t);
- nearest = from + t*v;
+ }
+ else
+ {
+ t = 0;
+ //reduce to 1 point
+ m_cachedBC.m_usedVertices.usedVertexA = true;
+ }
+ m_cachedBC.setBarycentricCoordinates(1 - t, t);
+ nearest = from + t * v;
- m_cachedP1 = m_simplexPointsP[0] + t * (m_simplexPointsP[1] - m_simplexPointsP[0]);
- m_cachedP2 = m_simplexPointsQ[0] + t * (m_simplexPointsQ[1] - m_simplexPointsQ[0]);
- m_cachedV = m_cachedP1 - m_cachedP2;
-
- reduceVertices(m_cachedBC.m_usedVertices);
+ m_cachedP1 = m_simplexPointsP[0] + t * (m_simplexPointsP[1] - m_simplexPointsP[0]);
+ m_cachedP2 = m_simplexPointsQ[0] + t * (m_simplexPointsQ[1] - m_simplexPointsQ[0]);
+ m_cachedV = m_cachedP1 - m_cachedP2;
- m_cachedValidClosest = m_cachedBC.isValid();
- break;
+ reduceVertices(m_cachedBC.m_usedVertices);
+
+ m_cachedValidClosest = m_cachedBC.isValid();
+ break;
}
- case 3:
- {
- //closest point origin from triangle
- b3Vector3 p =b3MakeVector3(b3Scalar(0.),b3Scalar(0.),b3Scalar(0.));
+ case 3:
+ {
+ //closest point origin from triangle
+ b3Vector3 p = b3MakeVector3(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.));
- const b3Vector3& a = m_simplexVectorW[0];
- const b3Vector3& b = m_simplexVectorW[1];
- const b3Vector3& c = m_simplexVectorW[2];
+ const b3Vector3& a = m_simplexVectorW[0];
+ const b3Vector3& b = m_simplexVectorW[1];
+ const b3Vector3& c = m_simplexVectorW[2];
- closestPtPointTriangle(p,a,b,c,m_cachedBC);
- m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] +
- m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] +
- m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2];
+ closestPtPointTriangle(p, a, b, c, m_cachedBC);
+ m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] +
+ m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] +
+ m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2];
- m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] +
- m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] +
- m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2];
+ m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] +
+ m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] +
+ m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2];
- m_cachedV = m_cachedP1-m_cachedP2;
+ m_cachedV = m_cachedP1 - m_cachedP2;
- reduceVertices (m_cachedBC.m_usedVertices);
- m_cachedValidClosest = m_cachedBC.isValid();
+ reduceVertices(m_cachedBC.m_usedVertices);
+ m_cachedValidClosest = m_cachedBC.isValid();
- break;
+ break;
}
- case 4:
+ case 4:
{
+ b3Vector3 p = b3MakeVector3(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.));
-
- b3Vector3 p =b3MakeVector3(b3Scalar(0.),b3Scalar(0.),b3Scalar(0.));
-
const b3Vector3& a = m_simplexVectorW[0];
const b3Vector3& b = m_simplexVectorW[1];
const b3Vector3& c = m_simplexVectorW[2];
const b3Vector3& d = m_simplexVectorW[3];
- bool hasSeperation = closestPtPointTetrahedron(p,a,b,c,d,m_cachedBC);
+ bool hasSeperation = closestPtPointTetrahedron(p, a, b, c, d, m_cachedBC);
if (hasSeperation)
{
-
m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] +
- m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] +
- m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2] +
- m_simplexPointsP[3] * m_cachedBC.m_barycentricCoords[3];
+ m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] +
+ m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2] +
+ m_simplexPointsP[3] * m_cachedBC.m_barycentricCoords[3];
m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] +
- m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] +
- m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2] +
- m_simplexPointsQ[3] * m_cachedBC.m_barycentricCoords[3];
+ m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] +
+ m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2] +
+ m_simplexPointsQ[3] * m_cachedBC.m_barycentricCoords[3];
- m_cachedV = m_cachedP1-m_cachedP2;
- reduceVertices (m_cachedBC.m_usedVertices);
- } else
+ m_cachedV = m_cachedP1 - m_cachedP2;
+ reduceVertices(m_cachedBC.m_usedVertices);
+ }
+ else
{
-// printf("sub distance got penetration\n");
+ // printf("sub distance got penetration\n");
if (m_cachedBC.m_degenerate)
{
m_cachedValidClosest = false;
- } else
+ }
+ else
{
m_cachedValidClosest = true;
//degenerate case == false, penetration = true + zero
- m_cachedV.setValue(b3Scalar(0.),b3Scalar(0.),b3Scalar(0.));
+ m_cachedV.setValue(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.));
}
break;
}
@@ -228,7 +222,7 @@ bool b3VoronoiSimplexSolver::updateClosestVectorAndPoints()
//closest point origin from tetrahedron
break;
}
- default:
+ default:
{
m_cachedValidClosest = false;
}
@@ -236,7 +230,6 @@ bool b3VoronoiSimplexSolver::updateClosestVectorAndPoints()
}
return m_cachedValidClosest;
-
}
//return/calculate the closest vertex
@@ -247,13 +240,11 @@ bool b3VoronoiSimplexSolver::closest(b3Vector3& v)
return succes;
}
-
-
b3Scalar b3VoronoiSimplexSolver::maxVertex()
{
int i, numverts = numVertices();
b3Scalar maxV = b3Scalar(0.);
- for (i=0;i<numverts;i++)
+ for (i = 0; i < numverts; i++)
{
b3Scalar curLen2 = m_simplexVectorW[i].length2();
if (maxV < curLen2)
@@ -262,13 +253,11 @@ b3Scalar b3VoronoiSimplexSolver::maxVertex()
return maxV;
}
-
-
- //return the current simplex
-int b3VoronoiSimplexSolver::getSimplex(b3Vector3 *pBuf, b3Vector3 *qBuf, b3Vector3 *yBuf) const
+//return the current simplex
+int b3VoronoiSimplexSolver::getSimplex(b3Vector3* pBuf, b3Vector3* qBuf, b3Vector3* yBuf) const
{
int i;
- for (i=0;i<numVertices();i++)
+ for (i = 0; i < numVertices(); i++)
{
yBuf[i] = m_simplexVectorW[i];
pBuf[i] = m_simplexPointsP[i];
@@ -277,20 +266,17 @@ int b3VoronoiSimplexSolver::getSimplex(b3Vector3 *pBuf, b3Vector3 *qBuf, b3Vecto
return numVertices();
}
-
-
-
bool b3VoronoiSimplexSolver::inSimplex(const b3Vector3& w)
{
bool found = false;
int i, numverts = numVertices();
//b3Scalar maxV = b3Scalar(0.);
-
+
//w is in the current (reduced) simplex
- for (i=0;i<numverts;i++)
+ for (i = 0; i < numverts; i++)
{
#ifdef BT_USE_EQUAL_VERTEX_THRESHOLD
- if ( m_simplexVectorW[i].distance2(w) <= m_equalVertexThreshold)
+ if (m_simplexVectorW[i].distance2(w) <= m_equalVertexThreshold)
#else
if (m_simplexVectorW[i] == w)
#endif
@@ -300,199 +286,190 @@ bool b3VoronoiSimplexSolver::inSimplex(const b3Vector3& w)
//check in case lastW is already removed
if (w == m_lastW)
return true;
-
+
return found;
}
-void b3VoronoiSimplexSolver::backup_closest(b3Vector3& v)
+void b3VoronoiSimplexSolver::backup_closest(b3Vector3& v)
{
v = m_cachedV;
}
-
-bool b3VoronoiSimplexSolver::emptySimplex() const
+bool b3VoronoiSimplexSolver::emptySimplex() const
{
return (numVertices() == 0);
-
}
-void b3VoronoiSimplexSolver::compute_points(b3Vector3& p1, b3Vector3& p2)
+void b3VoronoiSimplexSolver::compute_points(b3Vector3& p1, b3Vector3& p2)
{
updateClosestVectorAndPoints();
p1 = m_cachedP1;
p2 = m_cachedP2;
-
}
-
-
-
-bool b3VoronoiSimplexSolver::closestPtPointTriangle(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c,b3SubSimplexClosestResult& result)
+bool b3VoronoiSimplexSolver::closestPtPointTriangle(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c, b3SubSimplexClosestResult& result)
{
result.m_usedVertices.reset();
- // Check if P in vertex region outside A
- b3Vector3 ab = b - a;
- b3Vector3 ac = c - a;
- b3Vector3 ap = p - a;
- b3Scalar d1 = ab.dot(ap);
- b3Scalar d2 = ac.dot(ap);
- if (d1 <= b3Scalar(0.0) && d2 <= b3Scalar(0.0))
+ // Check if P in vertex region outside A
+ b3Vector3 ab = b - a;
+ b3Vector3 ac = c - a;
+ b3Vector3 ap = p - a;
+ b3Scalar d1 = ab.dot(ap);
+ b3Scalar d2 = ac.dot(ap);
+ if (d1 <= b3Scalar(0.0) && d2 <= b3Scalar(0.0))
{
result.m_closestPointOnSimplex = a;
result.m_usedVertices.usedVertexA = true;
- result.setBarycentricCoordinates(1,0,0);
- return true;// a; // barycentric coordinates (1,0,0)
+ result.setBarycentricCoordinates(1, 0, 0);
+ return true; // a; // barycentric coordinates (1,0,0)
}
- // Check if P in vertex region outside B
- b3Vector3 bp = p - b;
- b3Scalar d3 = ab.dot(bp);
- b3Scalar d4 = ac.dot(bp);
- if (d3 >= b3Scalar(0.0) && d4 <= d3)
+ // Check if P in vertex region outside B
+ b3Vector3 bp = p - b;
+ b3Scalar d3 = ab.dot(bp);
+ b3Scalar d4 = ac.dot(bp);
+ if (d3 >= b3Scalar(0.0) && d4 <= d3)
{
result.m_closestPointOnSimplex = b;
result.m_usedVertices.usedVertexB = true;
- result.setBarycentricCoordinates(0,1,0);
+ result.setBarycentricCoordinates(0, 1, 0);
- return true; // b; // barycentric coordinates (0,1,0)
+ return true; // b; // barycentric coordinates (0,1,0)
}
- // Check if P in edge region of AB, if so return projection of P onto AB
- b3Scalar vc = d1*d4 - d3*d2;
- if (vc <= b3Scalar(0.0) && d1 >= b3Scalar(0.0) && d3 <= b3Scalar(0.0)) {
- b3Scalar v = d1 / (d1 - d3);
+ // Check if P in edge region of AB, if so return projection of P onto AB
+ b3Scalar vc = d1 * d4 - d3 * d2;
+ if (vc <= b3Scalar(0.0) && d1 >= b3Scalar(0.0) && d3 <= b3Scalar(0.0))
+ {
+ b3Scalar v = d1 / (d1 - d3);
result.m_closestPointOnSimplex = a + v * ab;
result.m_usedVertices.usedVertexA = true;
result.m_usedVertices.usedVertexB = true;
- result.setBarycentricCoordinates(1-v,v,0);
+ result.setBarycentricCoordinates(1 - v, v, 0);
return true;
- //return a + v * ab; // barycentric coordinates (1-v,v,0)
- }
-
- // Check if P in vertex region outside C
- b3Vector3 cp = p - c;
- b3Scalar d5 = ab.dot(cp);
- b3Scalar d6 = ac.dot(cp);
- if (d6 >= b3Scalar(0.0) && d5 <= d6)
+ //return a + v * ab; // barycentric coordinates (1-v,v,0)
+ }
+
+ // Check if P in vertex region outside C
+ b3Vector3 cp = p - c;
+ b3Scalar d5 = ab.dot(cp);
+ b3Scalar d6 = ac.dot(cp);
+ if (d6 >= b3Scalar(0.0) && d5 <= d6)
{
result.m_closestPointOnSimplex = c;
result.m_usedVertices.usedVertexC = true;
- result.setBarycentricCoordinates(0,0,1);
- return true;//c; // barycentric coordinates (0,0,1)
+ result.setBarycentricCoordinates(0, 0, 1);
+ return true; //c; // barycentric coordinates (0,0,1)
}
- // Check if P in edge region of AC, if so return projection of P onto AC
- b3Scalar vb = d5*d2 - d1*d6;
- if (vb <= b3Scalar(0.0) && d2 >= b3Scalar(0.0) && d6 <= b3Scalar(0.0)) {
- b3Scalar w = d2 / (d2 - d6);
+ // Check if P in edge region of AC, if so return projection of P onto AC
+ b3Scalar vb = d5 * d2 - d1 * d6;
+ if (vb <= b3Scalar(0.0) && d2 >= b3Scalar(0.0) && d6 <= b3Scalar(0.0))
+ {
+ b3Scalar w = d2 / (d2 - d6);
result.m_closestPointOnSimplex = a + w * ac;
result.m_usedVertices.usedVertexA = true;
result.m_usedVertices.usedVertexC = true;
- result.setBarycentricCoordinates(1-w,0,w);
+ result.setBarycentricCoordinates(1 - w, 0, w);
return true;
- //return a + w * ac; // barycentric coordinates (1-w,0,w)
- }
+ //return a + w * ac; // barycentric coordinates (1-w,0,w)
+ }
+
+ // Check if P in edge region of BC, if so return projection of P onto BC
+ b3Scalar va = d3 * d6 - d5 * d4;
+ if (va <= b3Scalar(0.0) && (d4 - d3) >= b3Scalar(0.0) && (d5 - d6) >= b3Scalar(0.0))
+ {
+ b3Scalar w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
- // Check if P in edge region of BC, if so return projection of P onto BC
- b3Scalar va = d3*d6 - d5*d4;
- if (va <= b3Scalar(0.0) && (d4 - d3) >= b3Scalar(0.0) && (d5 - d6) >= b3Scalar(0.0)) {
- b3Scalar w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
-
result.m_closestPointOnSimplex = b + w * (c - b);
result.m_usedVertices.usedVertexB = true;
result.m_usedVertices.usedVertexC = true;
- result.setBarycentricCoordinates(0,1-w,w);
- return true;
- // return b + w * (c - b); // barycentric coordinates (0,1-w,w)
- }
-
- // P inside face region. Compute Q through its barycentric coordinates (u,v,w)
- b3Scalar denom = b3Scalar(1.0) / (va + vb + vc);
- b3Scalar v = vb * denom;
- b3Scalar w = vc * denom;
-
+ result.setBarycentricCoordinates(0, 1 - w, w);
+ return true;
+ // return b + w * (c - b); // barycentric coordinates (0,1-w,w)
+ }
+
+ // P inside face region. Compute Q through its barycentric coordinates (u,v,w)
+ b3Scalar denom = b3Scalar(1.0) / (va + vb + vc);
+ b3Scalar v = vb * denom;
+ b3Scalar w = vc * denom;
+
result.m_closestPointOnSimplex = a + ab * v + ac * w;
result.m_usedVertices.usedVertexA = true;
result.m_usedVertices.usedVertexB = true;
result.m_usedVertices.usedVertexC = true;
- result.setBarycentricCoordinates(1-v-w,v,w);
-
- return true;
-// return a + ab * v + ac * w; // = u*a + v*b + w*c, u = va * denom = b3Scalar(1.0) - v - w
+ result.setBarycentricCoordinates(1 - v - w, v, w);
+ return true;
+ // return a + ab * v + ac * w; // = u*a + v*b + w*c, u = va * denom = b3Scalar(1.0) - v - w
}
-
-
-
-
/// Test if point p and d lie on opposite sides of plane through abc
int b3VoronoiSimplexSolver::pointOutsideOfPlane(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c, const b3Vector3& d)
{
- b3Vector3 normal = (b-a).cross(c-a);
+ b3Vector3 normal = (b - a).cross(c - a);
- b3Scalar signp = (p - a).dot(normal); // [AP AB AC]
- b3Scalar signd = (d - a).dot( normal); // [AD AB AC]
+ b3Scalar signp = (p - a).dot(normal); // [AP AB AC]
+ b3Scalar signd = (d - a).dot(normal); // [AD AB AC]
#ifdef B3_CATCH_DEGENERATE_TETRAHEDRON
#ifdef BT_USE_DOUBLE_PRECISION
-if (signd * signd < (b3Scalar(1e-8) * b3Scalar(1e-8)))
+ if (signd * signd < (b3Scalar(1e-8) * b3Scalar(1e-8)))
{
return -1;
}
#else
if (signd * signd < (b3Scalar(1e-4) * b3Scalar(1e-4)))
{
-// printf("affine dependent/degenerate\n");//
+ // printf("affine dependent/degenerate\n");//
return -1;
}
#endif
#endif
// Points on opposite sides if expression signs are opposite
- return signp * signd < b3Scalar(0.);
+ return signp * signd < b3Scalar(0.);
}
-
-bool b3VoronoiSimplexSolver::closestPtPointTetrahedron(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c, const b3Vector3& d, b3SubSimplexClosestResult& finalResult)
+bool b3VoronoiSimplexSolver::closestPtPointTetrahedron(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c, const b3Vector3& d, b3SubSimplexClosestResult& finalResult)
{
b3SubSimplexClosestResult tempResult;
- // Start out assuming point inside all halfspaces, so closest to itself
+ // Start out assuming point inside all halfspaces, so closest to itself
finalResult.m_closestPointOnSimplex = p;
finalResult.m_usedVertices.reset();
- finalResult.m_usedVertices.usedVertexA = true;
+ finalResult.m_usedVertices.usedVertexA = true;
finalResult.m_usedVertices.usedVertexB = true;
finalResult.m_usedVertices.usedVertexC = true;
finalResult.m_usedVertices.usedVertexD = true;
- int pointOutsideABC = pointOutsideOfPlane(p, a, b, c, d);
+ int pointOutsideABC = pointOutsideOfPlane(p, a, b, c, d);
int pointOutsideACD = pointOutsideOfPlane(p, a, c, d, b);
- int pointOutsideADB = pointOutsideOfPlane(p, a, d, b, c);
- int pointOutsideBDC = pointOutsideOfPlane(p, b, d, c, a);
-
- if (pointOutsideABC < 0 || pointOutsideACD < 0 || pointOutsideADB < 0 || pointOutsideBDC < 0)
- {
- finalResult.m_degenerate = true;
- return false;
- }
+ int pointOutsideADB = pointOutsideOfPlane(p, a, d, b, c);
+ int pointOutsideBDC = pointOutsideOfPlane(p, b, d, c, a);
- if (!pointOutsideABC && !pointOutsideACD && !pointOutsideADB && !pointOutsideBDC)
- {
- return false;
- }
+ if (pointOutsideABC < 0 || pointOutsideACD < 0 || pointOutsideADB < 0 || pointOutsideBDC < 0)
+ {
+ finalResult.m_degenerate = true;
+ return false;
+ }
+ if (!pointOutsideABC && !pointOutsideACD && !pointOutsideADB && !pointOutsideBDC)
+ {
+ return false;
+ }
- b3Scalar bestSqDist = FLT_MAX;
- // If point outside face abc then compute closest point on abc
- if (pointOutsideABC)
+ b3Scalar bestSqDist = FLT_MAX;
+ // If point outside face abc then compute closest point on abc
+ if (pointOutsideABC)
{
- closestPtPointTriangle(p, a, b, c,tempResult);
+ closestPtPointTriangle(p, a, b, c, tempResult);
b3Vector3 q = tempResult.m_closestPointOnSimplex;
-
- b3Scalar sqDist = (q - p).dot( q - p);
- // Update best closest point if (squared) distance is less than current best
- if (sqDist < bestSqDist) {
+
+ b3Scalar sqDist = (q - p).dot(q - p);
+ // Update best closest point if (squared) distance is less than current best
+ if (sqDist < bestSqDist)
+ {
bestSqDist = sqDist;
finalResult.m_closestPointOnSimplex = q;
//convert result bitmask!
@@ -501,25 +478,22 @@ bool b3VoronoiSimplexSolver::closestPtPointTetrahedron(const b3Vector3& p, const
finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexB;
finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexC;
finalResult.setBarycentricCoordinates(
- tempResult.m_barycentricCoords[VERTA],
- tempResult.m_barycentricCoords[VERTB],
- tempResult.m_barycentricCoords[VERTC],
- 0
- );
-
+ tempResult.m_barycentricCoords[VERTA],
+ tempResult.m_barycentricCoords[VERTB],
+ tempResult.m_barycentricCoords[VERTC],
+ 0);
}
- }
-
+ }
// Repeat test for face acd
- if (pointOutsideACD)
+ if (pointOutsideACD)
{
- closestPtPointTriangle(p, a, c, d,tempResult);
+ closestPtPointTriangle(p, a, c, d, tempResult);
b3Vector3 q = tempResult.m_closestPointOnSimplex;
//convert result bitmask!
- b3Scalar sqDist = (q - p).dot( q - p);
- if (sqDist < bestSqDist)
+ b3Scalar sqDist = (q - p).dot(q - p);
+ if (sqDist < bestSqDist)
{
bestSqDist = sqDist;
finalResult.m_closestPointOnSimplex = q;
@@ -529,52 +503,46 @@ bool b3VoronoiSimplexSolver::closestPtPointTetrahedron(const b3Vector3& p, const
finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexB;
finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexC;
finalResult.setBarycentricCoordinates(
- tempResult.m_barycentricCoords[VERTA],
- 0,
- tempResult.m_barycentricCoords[VERTB],
- tempResult.m_barycentricCoords[VERTC]
- );
-
+ tempResult.m_barycentricCoords[VERTA],
+ 0,
+ tempResult.m_barycentricCoords[VERTB],
+ tempResult.m_barycentricCoords[VERTC]);
}
- }
- // Repeat test for face adb
+ }
+ // Repeat test for face adb
-
if (pointOutsideADB)
{
- closestPtPointTriangle(p, a, d, b,tempResult);
+ closestPtPointTriangle(p, a, d, b, tempResult);
b3Vector3 q = tempResult.m_closestPointOnSimplex;
//convert result bitmask!
- b3Scalar sqDist = (q - p).dot( q - p);
- if (sqDist < bestSqDist)
+ b3Scalar sqDist = (q - p).dot(q - p);
+ if (sqDist < bestSqDist)
{
bestSqDist = sqDist;
finalResult.m_closestPointOnSimplex = q;
finalResult.m_usedVertices.reset();
finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA;
finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexC;
-
+
finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexB;
finalResult.setBarycentricCoordinates(
- tempResult.m_barycentricCoords[VERTA],
- tempResult.m_barycentricCoords[VERTC],
- 0,
- tempResult.m_barycentricCoords[VERTB]
- );
-
+ tempResult.m_barycentricCoords[VERTA],
+ tempResult.m_barycentricCoords[VERTC],
+ 0,
+ tempResult.m_barycentricCoords[VERTB]);
}
- }
- // Repeat test for face bdc
-
+ }
+ // Repeat test for face bdc
if (pointOutsideBDC)
{
- closestPtPointTriangle(p, b, d, c,tempResult);
+ closestPtPointTriangle(p, b, d, c, tempResult);
b3Vector3 q = tempResult.m_closestPointOnSimplex;
//convert result bitmask!
- b3Scalar sqDist = (q - p).dot( q - p);
- if (sqDist < bestSqDist)
+ b3Scalar sqDist = (q - p).dot(q - p);
+ if (sqDist < bestSqDist)
{
bestSqDist = sqDist;
finalResult.m_closestPointOnSimplex = q;
@@ -585,25 +553,22 @@ bool b3VoronoiSimplexSolver::closestPtPointTetrahedron(const b3Vector3& p, const
finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexB;
finalResult.setBarycentricCoordinates(
- 0,
- tempResult.m_barycentricCoords[VERTA],
- tempResult.m_barycentricCoords[VERTC],
- tempResult.m_barycentricCoords[VERTB]
- );
-
+ 0,
+ tempResult.m_barycentricCoords[VERTA],
+ tempResult.m_barycentricCoords[VERTC],
+ tempResult.m_barycentricCoords[VERTB]);
}
- }
+ }
//help! we ended up full !
-
+
if (finalResult.m_usedVertices.usedVertexA &&
finalResult.m_usedVertices.usedVertexB &&
finalResult.m_usedVertices.usedVertexC &&
- finalResult.m_usedVertices.usedVertexD)
+ finalResult.m_usedVertices.usedVertexD)
{
return true;
}
- return true;
+ return true;
}
-
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.h
index a6e27667d8..b40b169978 100644
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.h
+++ b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.h
@@ -13,22 +13,19 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
-
#ifndef B3_VORONOI_SIMPLEX_SOLVER_H
#define B3_VORONOI_SIMPLEX_SOLVER_H
#include "Bullet3Common/b3Vector3.h"
-
#define VORONOI_SIMPLEX_MAX_VERTS 5
///disable next define, or use defaultCollisionConfiguration->getSimplexSolver()->setEqualVertexThreshold(0.f) to disable/configure
//#define BT_USE_EQUAL_VERTEX_THRESHOLD
#define VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD 0.0001f
-
-struct b3UsageBitfield{
+struct b3UsageBitfield
+{
b3UsageBitfield()
{
reset();
@@ -41,137 +38,127 @@ struct b3UsageBitfield{
usedVertexC = false;
usedVertexD = false;
}
- unsigned short usedVertexA : 1;
- unsigned short usedVertexB : 1;
- unsigned short usedVertexC : 1;
- unsigned short usedVertexD : 1;
- unsigned short unused1 : 1;
- unsigned short unused2 : 1;
- unsigned short unused3 : 1;
- unsigned short unused4 : 1;
+ unsigned short usedVertexA : 1;
+ unsigned short usedVertexB : 1;
+ unsigned short usedVertexC : 1;
+ unsigned short usedVertexD : 1;
+ unsigned short unused1 : 1;
+ unsigned short unused2 : 1;
+ unsigned short unused3 : 1;
+ unsigned short unused4 : 1;
};
-
-struct b3SubSimplexClosestResult
+struct b3SubSimplexClosestResult
{
- b3Vector3 m_closestPointOnSimplex;
+ b3Vector3 m_closestPointOnSimplex;
//MASK for m_usedVertices
- //stores the simplex vertex-usage, using the MASK,
+ //stores the simplex vertex-usage, using the MASK,
// if m_usedVertices & MASK then the related vertex is used
- b3UsageBitfield m_usedVertices;
- b3Scalar m_barycentricCoords[4];
+ b3UsageBitfield m_usedVertices;
+ b3Scalar m_barycentricCoords[4];
bool m_degenerate;
- void reset()
+ void reset()
{
m_degenerate = false;
setBarycentricCoordinates();
m_usedVertices.reset();
}
- bool isValid()
+ bool isValid()
{
bool valid = (m_barycentricCoords[0] >= b3Scalar(0.)) &&
- (m_barycentricCoords[1] >= b3Scalar(0.)) &&
- (m_barycentricCoords[2] >= b3Scalar(0.)) &&
- (m_barycentricCoords[3] >= b3Scalar(0.));
-
+ (m_barycentricCoords[1] >= b3Scalar(0.)) &&
+ (m_barycentricCoords[2] >= b3Scalar(0.)) &&
+ (m_barycentricCoords[3] >= b3Scalar(0.));
return valid;
}
- void setBarycentricCoordinates(b3Scalar a=b3Scalar(0.),b3Scalar b=b3Scalar(0.),b3Scalar c=b3Scalar(0.),b3Scalar d=b3Scalar(0.))
+ void setBarycentricCoordinates(b3Scalar a = b3Scalar(0.), b3Scalar b = b3Scalar(0.), b3Scalar c = b3Scalar(0.), b3Scalar d = b3Scalar(0.))
{
m_barycentricCoords[0] = a;
m_barycentricCoords[1] = b;
m_barycentricCoords[2] = c;
m_barycentricCoords[3] = d;
}
-
};
/// b3VoronoiSimplexSolver is an implementation of the closest point distance algorithm from a 1-4 points simplex to the origin.
/// Can be used with GJK, as an alternative to Johnson distance algorithm.
-B3_ATTRIBUTE_ALIGNED16(class) b3VoronoiSimplexSolver
+B3_ATTRIBUTE_ALIGNED16(class)
+b3VoronoiSimplexSolver
{
public:
-
B3_DECLARE_ALIGNED_ALLOCATOR();
- int m_numVertices;
-
- b3Vector3 m_simplexVectorW[VORONOI_SIMPLEX_MAX_VERTS];
- b3Vector3 m_simplexPointsP[VORONOI_SIMPLEX_MAX_VERTS];
- b3Vector3 m_simplexPointsQ[VORONOI_SIMPLEX_MAX_VERTS];
+ int m_numVertices;
-
+ b3Vector3 m_simplexVectorW[VORONOI_SIMPLEX_MAX_VERTS];
+ b3Vector3 m_simplexPointsP[VORONOI_SIMPLEX_MAX_VERTS];
+ b3Vector3 m_simplexPointsQ[VORONOI_SIMPLEX_MAX_VERTS];
- b3Vector3 m_cachedP1;
- b3Vector3 m_cachedP2;
- b3Vector3 m_cachedV;
- b3Vector3 m_lastW;
-
- b3Scalar m_equalVertexThreshold;
- bool m_cachedValidClosest;
+ b3Vector3 m_cachedP1;
+ b3Vector3 m_cachedP2;
+ b3Vector3 m_cachedV;
+ b3Vector3 m_lastW;
+ b3Scalar m_equalVertexThreshold;
+ bool m_cachedValidClosest;
b3SubSimplexClosestResult m_cachedBC;
- bool m_needsUpdate;
-
- void removeVertex(int index);
- void reduceVertices (const b3UsageBitfield& usedVerts);
- bool updateClosestVectorAndPoints();
+ bool m_needsUpdate;
- bool closestPtPointTetrahedron(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c, const b3Vector3& d, b3SubSimplexClosestResult& finalResult);
- int pointOutsideOfPlane(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c, const b3Vector3& d);
- bool closestPtPointTriangle(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c,b3SubSimplexClosestResult& result);
+ void removeVertex(int index);
+ void reduceVertices(const b3UsageBitfield& usedVerts);
+ bool updateClosestVectorAndPoints();
-public:
+ bool closestPtPointTetrahedron(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c, const b3Vector3& d, b3SubSimplexClosestResult& finalResult);
+ int pointOutsideOfPlane(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c, const b3Vector3& d);
+ bool closestPtPointTriangle(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c, b3SubSimplexClosestResult& result);
+public:
b3VoronoiSimplexSolver()
- : m_equalVertexThreshold(VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD)
+ : m_equalVertexThreshold(VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD)
{
}
- void reset();
-
- void addVertex(const b3Vector3& w, const b3Vector3& p, const b3Vector3& q);
+ void reset();
- void setEqualVertexThreshold(b3Scalar threshold)
- {
- m_equalVertexThreshold = threshold;
- }
+ void addVertex(const b3Vector3& w, const b3Vector3& p, const b3Vector3& q);
- b3Scalar getEqualVertexThreshold() const
- {
- return m_equalVertexThreshold;
- }
+ void setEqualVertexThreshold(b3Scalar threshold)
+ {
+ m_equalVertexThreshold = threshold;
+ }
- bool closest(b3Vector3& v);
+ b3Scalar getEqualVertexThreshold() const
+ {
+ return m_equalVertexThreshold;
+ }
- b3Scalar maxVertex();
+ bool closest(b3Vector3 & v);
- bool fullSimplex() const
- {
- return (m_numVertices == 4);
- }
+ b3Scalar maxVertex();
- int getSimplex(b3Vector3 *pBuf, b3Vector3 *qBuf, b3Vector3 *yBuf) const;
+ bool fullSimplex() const
+ {
+ return (m_numVertices == 4);
+ }
- bool inSimplex(const b3Vector3& w);
-
- void backup_closest(b3Vector3& v) ;
+ int getSimplex(b3Vector3 * pBuf, b3Vector3 * qBuf, b3Vector3 * yBuf) const;
- bool emptySimplex() const ;
+ bool inSimplex(const b3Vector3& w);
- void compute_points(b3Vector3& p1, b3Vector3& p2) ;
+ void backup_closest(b3Vector3 & v);
- int numVertices() const
- {
- return m_numVertices;
- }
+ bool emptySimplex() const;
+ void compute_points(b3Vector3 & p1, b3Vector3 & p2);
+ int numVertices() const
+ {
+ return m_numVertices;
+ }
};
-#endif //B3_VORONOI_SIMPLEX_SOLVER_H
-
+#endif //B3_VORONOI_SIMPLEX_SOLVER_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/bvhTraversal.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/bvhTraversal.h
index 4b3b49eae8..f1df8a6970 100644
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/bvhTraversal.h
+++ b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/bvhTraversal.h
@@ -1,258 +1,257 @@
//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* bvhTraversalKernelCL= \
-"//keep this enum in sync with the CPU version (in btCollidable.h)\n"
-"//written by Erwin Coumans\n"
-"#define SHAPE_CONVEX_HULL 3\n"
-"#define SHAPE_CONCAVE_TRIMESH 5\n"
-"#define TRIANGLE_NUM_CONVEX_FACES 5\n"
-"#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6\n"
-"#define SHAPE_SPHERE 7\n"
-"typedef unsigned int u32;\n"
-"#define MAX_NUM_PARTS_IN_BITS 10\n"
-"///btQuantizedBvhNode is a compressed aabb node, 16 bytes.\n"
-"///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).\n"
-"typedef struct\n"
-"{\n"
-" //12 bytes\n"
-" unsigned short int m_quantizedAabbMin[3];\n"
-" unsigned short int m_quantizedAabbMax[3];\n"
-" //4 bytes\n"
-" int m_escapeIndexOrTriangleIndex;\n"
-"} btQuantizedBvhNode;\n"
-"typedef struct\n"
-"{\n"
-" float4 m_aabbMin;\n"
-" float4 m_aabbMax;\n"
-" float4 m_quantization;\n"
-" int m_numNodes;\n"
-" int m_numSubTrees;\n"
-" int m_nodeOffset;\n"
-" int m_subTreeOffset;\n"
-"} b3BvhInfo;\n"
-"int getTriangleIndex(const btQuantizedBvhNode* rootNode)\n"
-"{\n"
-" unsigned int x=0;\n"
-" unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);\n"
-" // Get only the lower bits where the triangle index is stored\n"
-" return (rootNode->m_escapeIndexOrTriangleIndex&~(y));\n"
-"}\n"
-"int isLeaf(const btQuantizedBvhNode* rootNode)\n"
-"{\n"
-" //skipindex is negative (internal node), triangleindex >=0 (leafnode)\n"
-" return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;\n"
-"}\n"
-" \n"
-"int getEscapeIndex(const btQuantizedBvhNode* rootNode)\n"
-"{\n"
-" return -rootNode->m_escapeIndexOrTriangleIndex;\n"
-"}\n"
-"typedef struct\n"
-"{\n"
-" //12 bytes\n"
-" unsigned short int m_quantizedAabbMin[3];\n"
-" unsigned short int m_quantizedAabbMax[3];\n"
-" //4 bytes, points to the root of the subtree\n"
-" int m_rootNodeIndex;\n"
-" //4 bytes\n"
-" int m_subtreeSize;\n"
-" int m_padding[3];\n"
-"} btBvhSubtreeInfo;\n"
-"///keep this in sync with btCollidable.h\n"
-"typedef struct\n"
-"{\n"
-" int m_numChildShapes;\n"
-" int blaat2;\n"
-" int m_shapeType;\n"
-" int m_shapeIndex;\n"
-" \n"
-"} btCollidableGpu;\n"
-"typedef struct\n"
-"{\n"
-" float4 m_childPosition;\n"
-" float4 m_childOrientation;\n"
-" int m_shapeIndex;\n"
-" int m_unused0;\n"
-" int m_unused1;\n"
-" int m_unused2;\n"
-"} btGpuChildShape;\n"
-"typedef struct\n"
-"{\n"
-" float4 m_pos;\n"
-" float4 m_quat;\n"
-" float4 m_linVel;\n"
-" float4 m_angVel;\n"
-" u32 m_collidableIdx;\n"
-" float m_invMass;\n"
-" float m_restituitionCoeff;\n"
-" float m_frictionCoeff;\n"
-"} BodyData;\n"
-"typedef struct \n"
-"{\n"
-" union\n"
-" {\n"
-" float4 m_min;\n"
-" float m_minElems[4];\n"
-" int m_minIndices[4];\n"
-" };\n"
-" union\n"
-" {\n"
-" float4 m_max;\n"
-" float m_maxElems[4];\n"
-" int m_maxIndices[4];\n"
-" };\n"
-"} btAabbCL;\n"
-"int testQuantizedAabbAgainstQuantizedAabb(\n"
-" const unsigned short int* aabbMin1,\n"
-" const unsigned short int* aabbMax1,\n"
-" const unsigned short int* aabbMin2,\n"
-" const unsigned short int* aabbMax2)\n"
-"{\n"
-" //int overlap = 1;\n"
-" if (aabbMin1[0] > aabbMax2[0])\n"
-" return 0;\n"
-" if (aabbMax1[0] < aabbMin2[0])\n"
-" return 0;\n"
-" if (aabbMin1[1] > aabbMax2[1])\n"
-" return 0;\n"
-" if (aabbMax1[1] < aabbMin2[1])\n"
-" return 0;\n"
-" if (aabbMin1[2] > aabbMax2[2])\n"
-" return 0;\n"
-" if (aabbMax1[2] < aabbMin2[2])\n"
-" return 0;\n"
-" return 1;\n"
-" //overlap = ((aabbMin1[0] > aabbMax2[0]) || (aabbMax1[0] < aabbMin2[0])) ? 0 : overlap;\n"
-" //overlap = ((aabbMin1[2] > aabbMax2[2]) || (aabbMax1[2] < aabbMin2[2])) ? 0 : overlap;\n"
-" //overlap = ((aabbMin1[1] > aabbMax2[1]) || (aabbMax1[1] < aabbMin2[1])) ? 0 : overlap;\n"
-" //return overlap;\n"
-"}\n"
-"void quantizeWithClamp(unsigned short* out, float4 point2,int isMax, float4 bvhAabbMin, float4 bvhAabbMax, float4 bvhQuantization)\n"
-"{\n"
-" float4 clampedPoint = max(point2,bvhAabbMin);\n"
-" clampedPoint = min (clampedPoint, bvhAabbMax);\n"
-" float4 v = (clampedPoint - bvhAabbMin) * bvhQuantization;\n"
-" if (isMax)\n"
-" {\n"
-" out[0] = (unsigned short) (((unsigned short)(v.x+1.f) | 1));\n"
-" out[1] = (unsigned short) (((unsigned short)(v.y+1.f) | 1));\n"
-" out[2] = (unsigned short) (((unsigned short)(v.z+1.f) | 1));\n"
-" } else\n"
-" {\n"
-" out[0] = (unsigned short) (((unsigned short)(v.x) & 0xfffe));\n"
-" out[1] = (unsigned short) (((unsigned short)(v.y) & 0xfffe));\n"
-" out[2] = (unsigned short) (((unsigned short)(v.z) & 0xfffe));\n"
-" }\n"
-"}\n"
-"// work-in-progress\n"
-"__kernel void bvhTraversalKernel( __global const int4* pairs, \n"
-" __global const BodyData* rigidBodies, \n"
-" __global const btCollidableGpu* collidables,\n"
-" __global btAabbCL* aabbs,\n"
-" __global int4* concavePairsOut,\n"
-" __global volatile int* numConcavePairsOut,\n"
-" __global const btBvhSubtreeInfo* subtreeHeadersRoot,\n"
-" __global const btQuantizedBvhNode* quantizedNodesRoot,\n"
-" __global const b3BvhInfo* bvhInfos,\n"
-" int numPairs,\n"
-" int maxNumConcavePairsCapacity)\n"
-"{\n"
-" int id = get_global_id(0);\n"
-" if (id>=numPairs)\n"
-" return;\n"
-" \n"
-" int bodyIndexA = pairs[id].x;\n"
-" int bodyIndexB = pairs[id].y;\n"
-" int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
-" int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
-" \n"
-" //once the broadphase avoids static-static pairs, we can remove this test\n"
-" if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))\n"
-" {\n"
-" return;\n"
-" }\n"
-" \n"
-" if (collidables[collidableIndexA].m_shapeType!=SHAPE_CONCAVE_TRIMESH)\n"
-" return;\n"
-" int shapeTypeB = collidables[collidableIndexB].m_shapeType;\n"
-" \n"
-" if (shapeTypeB!=SHAPE_CONVEX_HULL &&\n"
-" shapeTypeB!=SHAPE_SPHERE &&\n"
-" shapeTypeB!=SHAPE_COMPOUND_OF_CONVEX_HULLS\n"
-" )\n"
-" return;\n"
-" b3BvhInfo bvhInfo = bvhInfos[collidables[collidableIndexA].m_numChildShapes];\n"
-" float4 bvhAabbMin = bvhInfo.m_aabbMin;\n"
-" float4 bvhAabbMax = bvhInfo.m_aabbMax;\n"
-" float4 bvhQuantization = bvhInfo.m_quantization;\n"
-" int numSubtreeHeaders = bvhInfo.m_numSubTrees;\n"
-" __global const btBvhSubtreeInfo* subtreeHeaders = &subtreeHeadersRoot[bvhInfo.m_subTreeOffset];\n"
-" __global const btQuantizedBvhNode* quantizedNodes = &quantizedNodesRoot[bvhInfo.m_nodeOffset];\n"
-" \n"
-" unsigned short int quantizedQueryAabbMin[3];\n"
-" unsigned short int quantizedQueryAabbMax[3];\n"
-" quantizeWithClamp(quantizedQueryAabbMin,aabbs[bodyIndexB].m_min,false,bvhAabbMin, bvhAabbMax,bvhQuantization);\n"
-" quantizeWithClamp(quantizedQueryAabbMax,aabbs[bodyIndexB].m_max,true ,bvhAabbMin, bvhAabbMax,bvhQuantization);\n"
-" \n"
-" for (int i=0;i<numSubtreeHeaders;i++)\n"
-" {\n"
-" btBvhSubtreeInfo subtree = subtreeHeaders[i];\n"
-" \n"
-" int overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax);\n"
-" if (overlap != 0)\n"
-" {\n"
-" int startNodeIndex = subtree.m_rootNodeIndex;\n"
-" int endNodeIndex = subtree.m_rootNodeIndex+subtree.m_subtreeSize;\n"
-" int curIndex = startNodeIndex;\n"
-" int escapeIndex;\n"
-" int isLeafNode;\n"
-" int aabbOverlap;\n"
-" while (curIndex < endNodeIndex)\n"
-" {\n"
-" btQuantizedBvhNode rootNode = quantizedNodes[curIndex];\n"
-" aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode.m_quantizedAabbMin,rootNode.m_quantizedAabbMax);\n"
-" isLeafNode = isLeaf(&rootNode);\n"
-" if (aabbOverlap)\n"
-" {\n"
-" if (isLeafNode)\n"
-" {\n"
-" int triangleIndex = getTriangleIndex(&rootNode);\n"
-" if (shapeTypeB==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
-" {\n"
-" int numChildrenB = collidables[collidableIndexB].m_numChildShapes;\n"
-" int pairIdx = atomic_add(numConcavePairsOut,numChildrenB);\n"
-" for (int b=0;b<numChildrenB;b++)\n"
-" {\n"
-" if ((pairIdx+b)<maxNumConcavePairsCapacity)\n"
-" {\n"
-" int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex+b;\n"
-" int4 newPair = (int4)(bodyIndexA,bodyIndexB,triangleIndex,childShapeIndexB);\n"
-" concavePairsOut[pairIdx+b] = newPair;\n"
-" }\n"
-" }\n"
-" } else\n"
-" {\n"
-" int pairIdx = atomic_inc(numConcavePairsOut);\n"
-" if (pairIdx<maxNumConcavePairsCapacity)\n"
-" {\n"
-" int4 newPair = (int4)(bodyIndexA,bodyIndexB,triangleIndex,0);\n"
-" concavePairsOut[pairIdx] = newPair;\n"
-" }\n"
-" }\n"
-" } \n"
-" curIndex++;\n"
-" } else\n"
-" {\n"
-" if (isLeafNode)\n"
-" {\n"
-" curIndex++;\n"
-" } else\n"
-" {\n"
-" escapeIndex = getEscapeIndex(&rootNode);\n"
-" curIndex += escapeIndex;\n"
-" }\n"
-" }\n"
-" }\n"
-" }\n"
-" }\n"
-"}\n"
-;
+static const char* bvhTraversalKernelCL =
+ "//keep this enum in sync with the CPU version (in btCollidable.h)\n"
+ "//written by Erwin Coumans\n"
+ "#define SHAPE_CONVEX_HULL 3\n"
+ "#define SHAPE_CONCAVE_TRIMESH 5\n"
+ "#define TRIANGLE_NUM_CONVEX_FACES 5\n"
+ "#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6\n"
+ "#define SHAPE_SPHERE 7\n"
+ "typedef unsigned int u32;\n"
+ "#define MAX_NUM_PARTS_IN_BITS 10\n"
+ "///btQuantizedBvhNode is a compressed aabb node, 16 bytes.\n"
+ "///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).\n"
+ "typedef struct\n"
+ "{\n"
+ " //12 bytes\n"
+ " unsigned short int m_quantizedAabbMin[3];\n"
+ " unsigned short int m_quantizedAabbMax[3];\n"
+ " //4 bytes\n"
+ " int m_escapeIndexOrTriangleIndex;\n"
+ "} btQuantizedBvhNode;\n"
+ "typedef struct\n"
+ "{\n"
+ " float4 m_aabbMin;\n"
+ " float4 m_aabbMax;\n"
+ " float4 m_quantization;\n"
+ " int m_numNodes;\n"
+ " int m_numSubTrees;\n"
+ " int m_nodeOffset;\n"
+ " int m_subTreeOffset;\n"
+ "} b3BvhInfo;\n"
+ "int getTriangleIndex(const btQuantizedBvhNode* rootNode)\n"
+ "{\n"
+ " unsigned int x=0;\n"
+ " unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);\n"
+ " // Get only the lower bits where the triangle index is stored\n"
+ " return (rootNode->m_escapeIndexOrTriangleIndex&~(y));\n"
+ "}\n"
+ "int isLeaf(const btQuantizedBvhNode* rootNode)\n"
+ "{\n"
+ " //skipindex is negative (internal node), triangleindex >=0 (leafnode)\n"
+ " return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;\n"
+ "}\n"
+ " \n"
+ "int getEscapeIndex(const btQuantizedBvhNode* rootNode)\n"
+ "{\n"
+ " return -rootNode->m_escapeIndexOrTriangleIndex;\n"
+ "}\n"
+ "typedef struct\n"
+ "{\n"
+ " //12 bytes\n"
+ " unsigned short int m_quantizedAabbMin[3];\n"
+ " unsigned short int m_quantizedAabbMax[3];\n"
+ " //4 bytes, points to the root of the subtree\n"
+ " int m_rootNodeIndex;\n"
+ " //4 bytes\n"
+ " int m_subtreeSize;\n"
+ " int m_padding[3];\n"
+ "} btBvhSubtreeInfo;\n"
+ "///keep this in sync with btCollidable.h\n"
+ "typedef struct\n"
+ "{\n"
+ " int m_numChildShapes;\n"
+ " int blaat2;\n"
+ " int m_shapeType;\n"
+ " int m_shapeIndex;\n"
+ " \n"
+ "} btCollidableGpu;\n"
+ "typedef struct\n"
+ "{\n"
+ " float4 m_childPosition;\n"
+ " float4 m_childOrientation;\n"
+ " int m_shapeIndex;\n"
+ " int m_unused0;\n"
+ " int m_unused1;\n"
+ " int m_unused2;\n"
+ "} btGpuChildShape;\n"
+ "typedef struct\n"
+ "{\n"
+ " float4 m_pos;\n"
+ " float4 m_quat;\n"
+ " float4 m_linVel;\n"
+ " float4 m_angVel;\n"
+ " u32 m_collidableIdx;\n"
+ " float m_invMass;\n"
+ " float m_restituitionCoeff;\n"
+ " float m_frictionCoeff;\n"
+ "} BodyData;\n"
+ "typedef struct \n"
+ "{\n"
+ " union\n"
+ " {\n"
+ " float4 m_min;\n"
+ " float m_minElems[4];\n"
+ " int m_minIndices[4];\n"
+ " };\n"
+ " union\n"
+ " {\n"
+ " float4 m_max;\n"
+ " float m_maxElems[4];\n"
+ " int m_maxIndices[4];\n"
+ " };\n"
+ "} btAabbCL;\n"
+ "int testQuantizedAabbAgainstQuantizedAabb(\n"
+ " const unsigned short int* aabbMin1,\n"
+ " const unsigned short int* aabbMax1,\n"
+ " const unsigned short int* aabbMin2,\n"
+ " const unsigned short int* aabbMax2)\n"
+ "{\n"
+ " //int overlap = 1;\n"
+ " if (aabbMin1[0] > aabbMax2[0])\n"
+ " return 0;\n"
+ " if (aabbMax1[0] < aabbMin2[0])\n"
+ " return 0;\n"
+ " if (aabbMin1[1] > aabbMax2[1])\n"
+ " return 0;\n"
+ " if (aabbMax1[1] < aabbMin2[1])\n"
+ " return 0;\n"
+ " if (aabbMin1[2] > aabbMax2[2])\n"
+ " return 0;\n"
+ " if (aabbMax1[2] < aabbMin2[2])\n"
+ " return 0;\n"
+ " return 1;\n"
+ " //overlap = ((aabbMin1[0] > aabbMax2[0]) || (aabbMax1[0] < aabbMin2[0])) ? 0 : overlap;\n"
+ " //overlap = ((aabbMin1[2] > aabbMax2[2]) || (aabbMax1[2] < aabbMin2[2])) ? 0 : overlap;\n"
+ " //overlap = ((aabbMin1[1] > aabbMax2[1]) || (aabbMax1[1] < aabbMin2[1])) ? 0 : overlap;\n"
+ " //return overlap;\n"
+ "}\n"
+ "void quantizeWithClamp(unsigned short* out, float4 point2,int isMax, float4 bvhAabbMin, float4 bvhAabbMax, float4 bvhQuantization)\n"
+ "{\n"
+ " float4 clampedPoint = max(point2,bvhAabbMin);\n"
+ " clampedPoint = min (clampedPoint, bvhAabbMax);\n"
+ " float4 v = (clampedPoint - bvhAabbMin) * bvhQuantization;\n"
+ " if (isMax)\n"
+ " {\n"
+ " out[0] = (unsigned short) (((unsigned short)(v.x+1.f) | 1));\n"
+ " out[1] = (unsigned short) (((unsigned short)(v.y+1.f) | 1));\n"
+ " out[2] = (unsigned short) (((unsigned short)(v.z+1.f) | 1));\n"
+ " } else\n"
+ " {\n"
+ " out[0] = (unsigned short) (((unsigned short)(v.x) & 0xfffe));\n"
+ " out[1] = (unsigned short) (((unsigned short)(v.y) & 0xfffe));\n"
+ " out[2] = (unsigned short) (((unsigned short)(v.z) & 0xfffe));\n"
+ " }\n"
+ "}\n"
+ "// work-in-progress\n"
+ "__kernel void bvhTraversalKernel( __global const int4* pairs, \n"
+ " __global const BodyData* rigidBodies, \n"
+ " __global const btCollidableGpu* collidables,\n"
+ " __global btAabbCL* aabbs,\n"
+ " __global int4* concavePairsOut,\n"
+ " __global volatile int* numConcavePairsOut,\n"
+ " __global const btBvhSubtreeInfo* subtreeHeadersRoot,\n"
+ " __global const btQuantizedBvhNode* quantizedNodesRoot,\n"
+ " __global const b3BvhInfo* bvhInfos,\n"
+ " int numPairs,\n"
+ " int maxNumConcavePairsCapacity)\n"
+ "{\n"
+ " int id = get_global_id(0);\n"
+ " if (id>=numPairs)\n"
+ " return;\n"
+ " \n"
+ " int bodyIndexA = pairs[id].x;\n"
+ " int bodyIndexB = pairs[id].y;\n"
+ " int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+ " int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+ " \n"
+ " //once the broadphase avoids static-static pairs, we can remove this test\n"
+ " if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))\n"
+ " {\n"
+ " return;\n"
+ " }\n"
+ " \n"
+ " if (collidables[collidableIndexA].m_shapeType!=SHAPE_CONCAVE_TRIMESH)\n"
+ " return;\n"
+ " int shapeTypeB = collidables[collidableIndexB].m_shapeType;\n"
+ " \n"
+ " if (shapeTypeB!=SHAPE_CONVEX_HULL &&\n"
+ " shapeTypeB!=SHAPE_SPHERE &&\n"
+ " shapeTypeB!=SHAPE_COMPOUND_OF_CONVEX_HULLS\n"
+ " )\n"
+ " return;\n"
+ " b3BvhInfo bvhInfo = bvhInfos[collidables[collidableIndexA].m_numChildShapes];\n"
+ " float4 bvhAabbMin = bvhInfo.m_aabbMin;\n"
+ " float4 bvhAabbMax = bvhInfo.m_aabbMax;\n"
+ " float4 bvhQuantization = bvhInfo.m_quantization;\n"
+ " int numSubtreeHeaders = bvhInfo.m_numSubTrees;\n"
+ " __global const btBvhSubtreeInfo* subtreeHeaders = &subtreeHeadersRoot[bvhInfo.m_subTreeOffset];\n"
+ " __global const btQuantizedBvhNode* quantizedNodes = &quantizedNodesRoot[bvhInfo.m_nodeOffset];\n"
+ " \n"
+ " unsigned short int quantizedQueryAabbMin[3];\n"
+ " unsigned short int quantizedQueryAabbMax[3];\n"
+ " quantizeWithClamp(quantizedQueryAabbMin,aabbs[bodyIndexB].m_min,false,bvhAabbMin, bvhAabbMax,bvhQuantization);\n"
+ " quantizeWithClamp(quantizedQueryAabbMax,aabbs[bodyIndexB].m_max,true ,bvhAabbMin, bvhAabbMax,bvhQuantization);\n"
+ " \n"
+ " for (int i=0;i<numSubtreeHeaders;i++)\n"
+ " {\n"
+ " btBvhSubtreeInfo subtree = subtreeHeaders[i];\n"
+ " \n"
+ " int overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax);\n"
+ " if (overlap != 0)\n"
+ " {\n"
+ " int startNodeIndex = subtree.m_rootNodeIndex;\n"
+ " int endNodeIndex = subtree.m_rootNodeIndex+subtree.m_subtreeSize;\n"
+ " int curIndex = startNodeIndex;\n"
+ " int escapeIndex;\n"
+ " int isLeafNode;\n"
+ " int aabbOverlap;\n"
+ " while (curIndex < endNodeIndex)\n"
+ " {\n"
+ " btQuantizedBvhNode rootNode = quantizedNodes[curIndex];\n"
+ " aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode.m_quantizedAabbMin,rootNode.m_quantizedAabbMax);\n"
+ " isLeafNode = isLeaf(&rootNode);\n"
+ " if (aabbOverlap)\n"
+ " {\n"
+ " if (isLeafNode)\n"
+ " {\n"
+ " int triangleIndex = getTriangleIndex(&rootNode);\n"
+ " if (shapeTypeB==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
+ " {\n"
+ " int numChildrenB = collidables[collidableIndexB].m_numChildShapes;\n"
+ " int pairIdx = atomic_add(numConcavePairsOut,numChildrenB);\n"
+ " for (int b=0;b<numChildrenB;b++)\n"
+ " {\n"
+ " if ((pairIdx+b)<maxNumConcavePairsCapacity)\n"
+ " {\n"
+ " int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex+b;\n"
+ " int4 newPair = (int4)(bodyIndexA,bodyIndexB,triangleIndex,childShapeIndexB);\n"
+ " concavePairsOut[pairIdx+b] = newPair;\n"
+ " }\n"
+ " }\n"
+ " } else\n"
+ " {\n"
+ " int pairIdx = atomic_inc(numConcavePairsOut);\n"
+ " if (pairIdx<maxNumConcavePairsCapacity)\n"
+ " {\n"
+ " int4 newPair = (int4)(bodyIndexA,bodyIndexB,triangleIndex,0);\n"
+ " concavePairsOut[pairIdx] = newPair;\n"
+ " }\n"
+ " }\n"
+ " } \n"
+ " curIndex++;\n"
+ " } else\n"
+ " {\n"
+ " if (isLeafNode)\n"
+ " {\n"
+ " curIndex++;\n"
+ " } else\n"
+ " {\n"
+ " escapeIndex = getEscapeIndex(&rootNode);\n"
+ " curIndex += escapeIndex;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/mprKernels.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/mprKernels.h
index 7ed4b382c3..74959a931c 100644
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/mprKernels.h
+++ b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/mprKernels.h
@@ -1,1446 +1,1445 @@
//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* mprKernelsCL= \
-"/***\n"
-" * ---------------------------------\n"
-" * Copyright (c)2012 Daniel Fiser <danfis@danfis.cz>\n"
-" *\n"
-" * This file was ported from mpr.c file, part of libccd.\n"
-" * The Minkoski Portal Refinement implementation was ported \n"
-" * to OpenCL by Erwin Coumans for the Bullet 3 Physics library.\n"
-" * at http://github.com/erwincoumans/bullet3\n"
-" *\n"
-" * Distributed under the OSI-approved BSD License (the \"License\");\n"
-" * see <http://www.opensource.org/licenses/bsd-license.php>.\n"
-" * This software is distributed WITHOUT ANY WARRANTY; without even the\n"
-" * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
-" * See the License for more information.\n"
-" */\n"
-"#ifndef B3_MPR_PENETRATION_H\n"
-"#define B3_MPR_PENETRATION_H\n"
-"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
-"#define B3_PLATFORM_DEFINITIONS_H\n"
-"struct MyTest\n"
-"{\n"
-" int bla;\n"
-"};\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
-"#define B3_LARGE_FLOAT 1e18f\n"
-"#define B3_INFINITY 1e18f\n"
-"#define b3Assert(a)\n"
-"#define b3ConstArray(a) __global const a*\n"
-"#define b3AtomicInc atomic_inc\n"
-"#define b3AtomicAdd atomic_add\n"
-"#define b3Fabs fabs\n"
-"#define b3Sqrt native_sqrt\n"
-"#define b3Sin native_sin\n"
-"#define b3Cos native_cos\n"
-"#define B3_STATIC\n"
-"#endif\n"
-"#endif\n"
-"#ifndef B3_FLOAT4_H\n"
-"#define B3_FLOAT4_H\n"
-"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#endif\n"
-"#endif\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-" typedef float4 b3Float4;\n"
-" #define b3Float4ConstArg const b3Float4\n"
-" #define b3MakeFloat4 (float4)\n"
-" float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
-" {\n"
-" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
-" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
-" return dot(a1, b1);\n"
-" }\n"
-" b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
-" {\n"
-" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
-" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
-" return cross(a1, b1);\n"
-" }\n"
-" #define b3MinFloat4 min\n"
-" #define b3MaxFloat4 max\n"
-" #define b3Normalized(a) normalize(a)\n"
-"#endif \n"
-" \n"
-"inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
-"{\n"
-" if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
-" return false;\n"
-" return true;\n"
-"}\n"
-"inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
-"{\n"
-" float maxDot = -B3_INFINITY;\n"
-" int i = 0;\n"
-" int ptIndex = -1;\n"
-" for( i = 0; i < vecLen; i++ )\n"
-" {\n"
-" float dot = b3Dot3F4(vecArray[i],vec);\n"
-" \n"
-" if( dot > maxDot )\n"
-" {\n"
-" maxDot = dot;\n"
-" ptIndex = i;\n"
-" }\n"
-" }\n"
-" b3Assert(ptIndex>=0);\n"
-" if (ptIndex<0)\n"
-" {\n"
-" ptIndex = 0;\n"
-" }\n"
-" *dotOut = maxDot;\n"
-" return ptIndex;\n"
-"}\n"
-"#endif //B3_FLOAT4_H\n"
-"#ifndef B3_RIGIDBODY_DATA_H\n"
-"#define B3_RIGIDBODY_DATA_H\n"
-"#ifndef B3_FLOAT4_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#endif \n"
-"#endif //B3_FLOAT4_H\n"
-"#ifndef B3_QUAT_H\n"
-"#define B3_QUAT_H\n"
-"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#endif\n"
-"#endif\n"
-"#ifndef B3_FLOAT4_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#endif \n"
-"#endif //B3_FLOAT4_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-" typedef float4 b3Quat;\n"
-" #define b3QuatConstArg const b3Quat\n"
-" \n"
-" \n"
-"inline float4 b3FastNormalize4(float4 v)\n"
-"{\n"
-" v = (float4)(v.xyz,0.f);\n"
-" return fast_normalize(v);\n"
-"}\n"
-" \n"
-"inline b3Quat b3QuatMul(b3Quat a, b3Quat b);\n"
-"inline b3Quat b3QuatNormalized(b3QuatConstArg in);\n"
-"inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec);\n"
-"inline b3Quat b3QuatInvert(b3QuatConstArg q);\n"
-"inline b3Quat b3QuatInverse(b3QuatConstArg q);\n"
-"inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b)\n"
-"{\n"
-" b3Quat ans;\n"
-" ans = b3Cross3( a, b );\n"
-" ans += a.w*b+b.w*a;\n"
-"// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
-" ans.w = a.w*b.w - b3Dot3F4(a, b);\n"
-" return ans;\n"
-"}\n"
-"inline b3Quat b3QuatNormalized(b3QuatConstArg in)\n"
-"{\n"
-" b3Quat q;\n"
-" q=in;\n"
-" //return b3FastNormalize4(in);\n"
-" float len = native_sqrt(dot(q, q));\n"
-" if(len > 0.f)\n"
-" {\n"
-" q *= 1.f / len;\n"
-" }\n"
-" else\n"
-" {\n"
-" q.x = q.y = q.z = 0.f;\n"
-" q.w = 1.f;\n"
-" }\n"
-" return q;\n"
-"}\n"
-"inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
-"{\n"
-" b3Quat qInv = b3QuatInvert( q );\n"
-" float4 vcpy = vec;\n"
-" vcpy.w = 0.f;\n"
-" float4 out = b3QuatMul(b3QuatMul(q,vcpy),qInv);\n"
-" return out;\n"
-"}\n"
-"inline b3Quat b3QuatInverse(b3QuatConstArg q)\n"
-"{\n"
-" return (b3Quat)(-q.xyz, q.w);\n"
-"}\n"
-"inline b3Quat b3QuatInvert(b3QuatConstArg q)\n"
-"{\n"
-" return (b3Quat)(-q.xyz, q.w);\n"
-"}\n"
-"inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
-"{\n"
-" return b3QuatRotate( b3QuatInvert( q ), vec );\n"
-"}\n"
-"inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation)\n"
-"{\n"
-" return b3QuatRotate( orientation, point ) + (translation);\n"
-"}\n"
-" \n"
-"#endif \n"
-"#endif //B3_QUAT_H\n"
-"#ifndef B3_MAT3x3_H\n"
-"#define B3_MAT3x3_H\n"
-"#ifndef B3_QUAT_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#endif \n"
-"#endif //B3_QUAT_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"typedef struct\n"
-"{\n"
-" b3Float4 m_row[3];\n"
-"}b3Mat3x3;\n"
-"#define b3Mat3x3ConstArg const b3Mat3x3\n"
-"#define b3GetRow(m,row) (m.m_row[row])\n"
-"inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat)\n"
-"{\n"
-" b3Float4 quat2 = (b3Float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);\n"
-" b3Mat3x3 out;\n"
-" out.m_row[0].x=1-2*quat2.y-2*quat2.z;\n"
-" out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;\n"
-" out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;\n"
-" out.m_row[0].w = 0.f;\n"
-" out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;\n"
-" out.m_row[1].y=1-2*quat2.x-2*quat2.z;\n"
-" out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;\n"
-" out.m_row[1].w = 0.f;\n"
-" out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;\n"
-" out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;\n"
-" out.m_row[2].z=1-2*quat2.x-2*quat2.y;\n"
-" out.m_row[2].w = 0.f;\n"
-" return out;\n"
-"}\n"
-"inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn)\n"
-"{\n"
-" b3Mat3x3 out;\n"
-" out.m_row[0] = fabs(matIn.m_row[0]);\n"
-" out.m_row[1] = fabs(matIn.m_row[1]);\n"
-" out.m_row[2] = fabs(matIn.m_row[2]);\n"
-" return out;\n"
-"}\n"
-"__inline\n"
-"b3Mat3x3 mtZero();\n"
-"__inline\n"
-"b3Mat3x3 mtIdentity();\n"
-"__inline\n"
-"b3Mat3x3 mtTranspose(b3Mat3x3 m);\n"
-"__inline\n"
-"b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);\n"
-"__inline\n"
-"b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);\n"
-"__inline\n"
-"b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);\n"
-"__inline\n"
-"b3Mat3x3 mtZero()\n"
-"{\n"
-" b3Mat3x3 m;\n"
-" m.m_row[0] = (b3Float4)(0.f);\n"
-" m.m_row[1] = (b3Float4)(0.f);\n"
-" m.m_row[2] = (b3Float4)(0.f);\n"
-" return m;\n"
-"}\n"
-"__inline\n"
-"b3Mat3x3 mtIdentity()\n"
-"{\n"
-" b3Mat3x3 m;\n"
-" m.m_row[0] = (b3Float4)(1,0,0,0);\n"
-" m.m_row[1] = (b3Float4)(0,1,0,0);\n"
-" m.m_row[2] = (b3Float4)(0,0,1,0);\n"
-" return m;\n"
-"}\n"
-"__inline\n"
-"b3Mat3x3 mtTranspose(b3Mat3x3 m)\n"
-"{\n"
-" b3Mat3x3 out;\n"
-" out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
-" out.m_row[1] = (b3Float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
-" out.m_row[2] = (b3Float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
-" return out;\n"
-"}\n"
-"__inline\n"
-"b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)\n"
-"{\n"
-" b3Mat3x3 transB;\n"
-" transB = mtTranspose( b );\n"
-" b3Mat3x3 ans;\n"
-" // why this doesn't run when 0ing in the for{}\n"
-" a.m_row[0].w = 0.f;\n"
-" a.m_row[1].w = 0.f;\n"
-" a.m_row[2].w = 0.f;\n"
-" for(int i=0; i<3; i++)\n"
-" {\n"
-"// a.m_row[i].w = 0.f;\n"
-" ans.m_row[i].x = b3Dot3F4(a.m_row[i],transB.m_row[0]);\n"
-" ans.m_row[i].y = b3Dot3F4(a.m_row[i],transB.m_row[1]);\n"
-" ans.m_row[i].z = b3Dot3F4(a.m_row[i],transB.m_row[2]);\n"
-" ans.m_row[i].w = 0.f;\n"
-" }\n"
-" return ans;\n"
-"}\n"
-"__inline\n"
-"b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)\n"
-"{\n"
-" b3Float4 ans;\n"
-" ans.x = b3Dot3F4( a.m_row[0], b );\n"
-" ans.y = b3Dot3F4( a.m_row[1], b );\n"
-" ans.z = b3Dot3F4( a.m_row[2], b );\n"
-" ans.w = 0.f;\n"
-" return ans;\n"
-"}\n"
-"__inline\n"
-"b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)\n"
-"{\n"
-" b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
-" b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
-" b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
-" b3Float4 ans;\n"
-" ans.x = b3Dot3F4( a, colx );\n"
-" ans.y = b3Dot3F4( a, coly );\n"
-" ans.z = b3Dot3F4( a, colz );\n"
-" return ans;\n"
-"}\n"
-"#endif\n"
-"#endif //B3_MAT3x3_H\n"
-"typedef struct b3RigidBodyData b3RigidBodyData_t;\n"
-"struct b3RigidBodyData\n"
-"{\n"
-" b3Float4 m_pos;\n"
-" b3Quat m_quat;\n"
-" b3Float4 m_linVel;\n"
-" b3Float4 m_angVel;\n"
-" int m_collidableIdx;\n"
-" float m_invMass;\n"
-" float m_restituitionCoeff;\n"
-" float m_frictionCoeff;\n"
-"};\n"
-"typedef struct b3InertiaData b3InertiaData_t;\n"
-"struct b3InertiaData\n"
-"{\n"
-" b3Mat3x3 m_invInertiaWorld;\n"
-" b3Mat3x3 m_initInvInertia;\n"
-"};\n"
-"#endif //B3_RIGIDBODY_DATA_H\n"
-" \n"
-"#ifndef B3_CONVEX_POLYHEDRON_DATA_H\n"
-"#define B3_CONVEX_POLYHEDRON_DATA_H\n"
-"#ifndef B3_FLOAT4_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#endif \n"
-"#endif //B3_FLOAT4_H\n"
-"#ifndef B3_QUAT_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#endif \n"
-"#endif //B3_QUAT_H\n"
-"typedef struct b3GpuFace b3GpuFace_t;\n"
-"struct b3GpuFace\n"
-"{\n"
-" b3Float4 m_plane;\n"
-" int m_indexOffset;\n"
-" int m_numIndices;\n"
-" int m_unusedPadding1;\n"
-" int m_unusedPadding2;\n"
-"};\n"
-"typedef struct b3ConvexPolyhedronData b3ConvexPolyhedronData_t;\n"
-"struct b3ConvexPolyhedronData\n"
-"{\n"
-" b3Float4 m_localCenter;\n"
-" b3Float4 m_extents;\n"
-" b3Float4 mC;\n"
-" b3Float4 mE;\n"
-" float m_radius;\n"
-" int m_faceOffset;\n"
-" int m_numFaces;\n"
-" int m_numVertices;\n"
-" int m_vertexOffset;\n"
-" int m_uniqueEdgesOffset;\n"
-" int m_numUniqueEdges;\n"
-" int m_unused;\n"
-"};\n"
-"#endif //B3_CONVEX_POLYHEDRON_DATA_H\n"
-"#ifndef B3_COLLIDABLE_H\n"
-"#define B3_COLLIDABLE_H\n"
-"#ifndef B3_FLOAT4_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#endif \n"
-"#endif //B3_FLOAT4_H\n"
-"#ifndef B3_QUAT_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#endif \n"
-"#endif //B3_QUAT_H\n"
-"enum b3ShapeTypes\n"
-"{\n"
-" SHAPE_HEIGHT_FIELD=1,\n"
-" SHAPE_CONVEX_HULL=3,\n"
-" SHAPE_PLANE=4,\n"
-" SHAPE_CONCAVE_TRIMESH=5,\n"
-" SHAPE_COMPOUND_OF_CONVEX_HULLS=6,\n"
-" SHAPE_SPHERE=7,\n"
-" MAX_NUM_SHAPE_TYPES,\n"
-"};\n"
-"typedef struct b3Collidable b3Collidable_t;\n"
-"struct b3Collidable\n"
-"{\n"
-" union {\n"
-" int m_numChildShapes;\n"
-" int m_bvhIndex;\n"
-" };\n"
-" union\n"
-" {\n"
-" float m_radius;\n"
-" int m_compoundBvhIndex;\n"
-" };\n"
-" int m_shapeType;\n"
-" int m_shapeIndex;\n"
-"};\n"
-"typedef struct b3GpuChildShape b3GpuChildShape_t;\n"
-"struct b3GpuChildShape\n"
-"{\n"
-" b3Float4 m_childPosition;\n"
-" b3Quat m_childOrientation;\n"
-" int m_shapeIndex;\n"
-" int m_unused0;\n"
-" int m_unused1;\n"
-" int m_unused2;\n"
-"};\n"
-"struct b3CompoundOverlappingPair\n"
-"{\n"
-" int m_bodyIndexA;\n"
-" int m_bodyIndexB;\n"
-"// int m_pairType;\n"
-" int m_childShapeIndexA;\n"
-" int m_childShapeIndexB;\n"
-"};\n"
-"#endif //B3_COLLIDABLE_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#define B3_MPR_SQRT sqrt\n"
-"#endif\n"
-"#define B3_MPR_FMIN(x, y) ((x) < (y) ? (x) : (y))\n"
-"#define B3_MPR_FABS fabs\n"
-"#define B3_MPR_TOLERANCE 1E-6f\n"
-"#define B3_MPR_MAX_ITERATIONS 1000\n"
-"struct _b3MprSupport_t \n"
-"{\n"
-" b3Float4 v; //!< Support point in minkowski sum\n"
-" b3Float4 v1; //!< Support point in obj1\n"
-" b3Float4 v2; //!< Support point in obj2\n"
-"};\n"
-"typedef struct _b3MprSupport_t b3MprSupport_t;\n"
-"struct _b3MprSimplex_t \n"
-"{\n"
-" b3MprSupport_t ps[4];\n"
-" int last; //!< index of last added point\n"
-"};\n"
-"typedef struct _b3MprSimplex_t b3MprSimplex_t;\n"
-"inline b3MprSupport_t* b3MprSimplexPointW(b3MprSimplex_t *s, int idx)\n"
-"{\n"
-" return &s->ps[idx];\n"
-"}\n"
-"inline void b3MprSimplexSetSize(b3MprSimplex_t *s, int size)\n"
-"{\n"
-" s->last = size - 1;\n"
-"}\n"
-"inline int b3MprSimplexSize(const b3MprSimplex_t *s)\n"
-"{\n"
-" return s->last + 1;\n"
-"}\n"
-"inline const b3MprSupport_t* b3MprSimplexPoint(const b3MprSimplex_t* s, int idx)\n"
-"{\n"
-" // here is no check on boundaries\n"
-" return &s->ps[idx];\n"
-"}\n"
-"inline void b3MprSupportCopy(b3MprSupport_t *d, const b3MprSupport_t *s)\n"
-"{\n"
-" *d = *s;\n"
-"}\n"
-"inline void b3MprSimplexSet(b3MprSimplex_t *s, size_t pos, const b3MprSupport_t *a)\n"
-"{\n"
-" b3MprSupportCopy(s->ps + pos, a);\n"
-"}\n"
-"inline void b3MprSimplexSwap(b3MprSimplex_t *s, size_t pos1, size_t pos2)\n"
-"{\n"
-" b3MprSupport_t supp;\n"
-" b3MprSupportCopy(&supp, &s->ps[pos1]);\n"
-" b3MprSupportCopy(&s->ps[pos1], &s->ps[pos2]);\n"
-" b3MprSupportCopy(&s->ps[pos2], &supp);\n"
-"}\n"
-"inline int b3MprIsZero(float val)\n"
-"{\n"
-" return B3_MPR_FABS(val) < FLT_EPSILON;\n"
-"}\n"
-"inline int b3MprEq(float _a, float _b)\n"
-"{\n"
-" float ab;\n"
-" float a, b;\n"
-" ab = B3_MPR_FABS(_a - _b);\n"
-" if (B3_MPR_FABS(ab) < FLT_EPSILON)\n"
-" return 1;\n"
-" a = B3_MPR_FABS(_a);\n"
-" b = B3_MPR_FABS(_b);\n"
-" if (b > a){\n"
-" return ab < FLT_EPSILON * b;\n"
-" }else{\n"
-" return ab < FLT_EPSILON * a;\n"
-" }\n"
-"}\n"
-"inline int b3MprVec3Eq(const b3Float4* a, const b3Float4 *b)\n"
-"{\n"
-" return b3MprEq((*a).x, (*b).x)\n"
-" && b3MprEq((*a).y, (*b).y)\n"
-" && b3MprEq((*a).z, (*b).z);\n"
-"}\n"
-"inline b3Float4 b3LocalGetSupportVertex(b3Float4ConstArg supportVec,__global const b3ConvexPolyhedronData_t* hull, b3ConstArray(b3Float4) verticesA)\n"
-"{\n"
-" b3Float4 supVec = b3MakeFloat4(0,0,0,0);\n"
-" float maxDot = -B3_LARGE_FLOAT;\n"
-" if( 0 < hull->m_numVertices )\n"
-" {\n"
-" const b3Float4 scaled = supportVec;\n"
-" int index = b3MaxDot(scaled, &verticesA[hull->m_vertexOffset], hull->m_numVertices, &maxDot);\n"
-" return verticesA[hull->m_vertexOffset+index];\n"
-" }\n"
-" return supVec;\n"
-"}\n"
-"B3_STATIC void b3MprConvexSupport(int pairIndex,int bodyIndex, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf, \n"
-" b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData, \n"
-" b3ConstArray(b3Collidable_t) cpuCollidables,\n"
-" b3ConstArray(b3Float4) cpuVertices,\n"
-" __global b3Float4* sepAxis,\n"
-" const b3Float4* _dir, b3Float4* outp, int logme)\n"
-"{\n"
-" //dir is in worldspace, move to local space\n"
-" \n"
-" b3Float4 pos = cpuBodyBuf[bodyIndex].m_pos;\n"
-" b3Quat orn = cpuBodyBuf[bodyIndex].m_quat;\n"
-" \n"
-" b3Float4 dir = b3MakeFloat4((*_dir).x,(*_dir).y,(*_dir).z,0.f);\n"
-" \n"
-" const b3Float4 localDir = b3QuatRotate(b3QuatInverse(orn),dir);\n"
-" \n"
-" //find local support vertex\n"
-" int colIndex = cpuBodyBuf[bodyIndex].m_collidableIdx;\n"
-" \n"
-" b3Assert(cpuCollidables[colIndex].m_shapeType==SHAPE_CONVEX_HULL);\n"
-" __global const b3ConvexPolyhedronData_t* hull = &cpuConvexData[cpuCollidables[colIndex].m_shapeIndex];\n"
-" \n"
-" b3Float4 pInA;\n"
-" if (logme)\n"
-" {\n"
-" b3Float4 supVec = b3MakeFloat4(0,0,0,0);\n"
-" float maxDot = -B3_LARGE_FLOAT;\n"
-" if( 0 < hull->m_numVertices )\n"
-" {\n"
-" const b3Float4 scaled = localDir;\n"
-" int index = b3MaxDot(scaled, &cpuVertices[hull->m_vertexOffset], hull->m_numVertices, &maxDot);\n"
-" pInA = cpuVertices[hull->m_vertexOffset+index];\n"
-" \n"
-" }\n"
-" } else\n"
-" {\n"
-" pInA = b3LocalGetSupportVertex(localDir,hull,cpuVertices);\n"
-" }\n"
-" //move vertex to world space\n"
-" *outp = b3TransformPoint(pInA,pos,orn);\n"
-" \n"
-"}\n"
-"inline void b3MprSupport(int pairIndex,int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf, \n"
-" b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData, \n"
-" b3ConstArray(b3Collidable_t) cpuCollidables,\n"
-" b3ConstArray(b3Float4) cpuVertices,\n"
-" __global b3Float4* sepAxis,\n"
-" const b3Float4* _dir, b3MprSupport_t *supp)\n"
-"{\n"
-" b3Float4 dir;\n"
-" dir = *_dir;\n"
-" b3MprConvexSupport(pairIndex,bodyIndexA,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices,sepAxis,&dir, &supp->v1,0);\n"
-" dir = *_dir*-1.f;\n"
-" b3MprConvexSupport(pairIndex,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices,sepAxis,&dir, &supp->v2,0);\n"
-" supp->v = supp->v1 - supp->v2;\n"
-"}\n"
-"inline void b3FindOrigin(int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf, b3MprSupport_t *center)\n"
-"{\n"
-" center->v1 = cpuBodyBuf[bodyIndexA].m_pos;\n"
-" center->v2 = cpuBodyBuf[bodyIndexB].m_pos;\n"
-" center->v = center->v1 - center->v2;\n"
-"}\n"
-"inline void b3MprVec3Set(b3Float4 *v, float x, float y, float z)\n"
-"{\n"
-" (*v).x = x;\n"
-" (*v).y = y;\n"
-" (*v).z = z;\n"
-" (*v).w = 0.f;\n"
-"}\n"
-"inline void b3MprVec3Add(b3Float4 *v, const b3Float4 *w)\n"
-"{\n"
-" (*v).x += (*w).x;\n"
-" (*v).y += (*w).y;\n"
-" (*v).z += (*w).z;\n"
-"}\n"
-"inline void b3MprVec3Copy(b3Float4 *v, const b3Float4 *w)\n"
-"{\n"
-" *v = *w;\n"
-"}\n"
-"inline void b3MprVec3Scale(b3Float4 *d, float k)\n"
-"{\n"
-" *d *= k;\n"
-"}\n"
-"inline float b3MprVec3Dot(const b3Float4 *a, const b3Float4 *b)\n"
-"{\n"
-" float dot;\n"
-" dot = b3Dot3F4(*a,*b);\n"
-" return dot;\n"
-"}\n"
-"inline float b3MprVec3Len2(const b3Float4 *v)\n"
-"{\n"
-" return b3MprVec3Dot(v, v);\n"
-"}\n"
-"inline void b3MprVec3Normalize(b3Float4 *d)\n"
-"{\n"
-" float k = 1.f / B3_MPR_SQRT(b3MprVec3Len2(d));\n"
-" b3MprVec3Scale(d, k);\n"
-"}\n"
-"inline void b3MprVec3Cross(b3Float4 *d, const b3Float4 *a, const b3Float4 *b)\n"
-"{\n"
-" *d = b3Cross3(*a,*b);\n"
-" \n"
-"}\n"
-"inline void b3MprVec3Sub2(b3Float4 *d, const b3Float4 *v, const b3Float4 *w)\n"
-"{\n"
-" *d = *v - *w;\n"
-"}\n"
-"inline void b3PortalDir(const b3MprSimplex_t *portal, b3Float4 *dir)\n"
-"{\n"
-" b3Float4 v2v1, v3v1;\n"
-" b3MprVec3Sub2(&v2v1, &b3MprSimplexPoint(portal, 2)->v,\n"
-" &b3MprSimplexPoint(portal, 1)->v);\n"
-" b3MprVec3Sub2(&v3v1, &b3MprSimplexPoint(portal, 3)->v,\n"
-" &b3MprSimplexPoint(portal, 1)->v);\n"
-" b3MprVec3Cross(dir, &v2v1, &v3v1);\n"
-" b3MprVec3Normalize(dir);\n"
-"}\n"
-"inline int portalEncapsulesOrigin(const b3MprSimplex_t *portal,\n"
-" const b3Float4 *dir)\n"
-"{\n"
-" float dot;\n"
-" dot = b3MprVec3Dot(dir, &b3MprSimplexPoint(portal, 1)->v);\n"
-" return b3MprIsZero(dot) || dot > 0.f;\n"
-"}\n"
-"inline int portalReachTolerance(const b3MprSimplex_t *portal,\n"
-" const b3MprSupport_t *v4,\n"
-" const b3Float4 *dir)\n"
-"{\n"
-" float dv1, dv2, dv3, dv4;\n"
-" float dot1, dot2, dot3;\n"
-" // find the smallest dot product of dir and {v1-v4, v2-v4, v3-v4}\n"
-" dv1 = b3MprVec3Dot(&b3MprSimplexPoint(portal, 1)->v, dir);\n"
-" dv2 = b3MprVec3Dot(&b3MprSimplexPoint(portal, 2)->v, dir);\n"
-" dv3 = b3MprVec3Dot(&b3MprSimplexPoint(portal, 3)->v, dir);\n"
-" dv4 = b3MprVec3Dot(&v4->v, dir);\n"
-" dot1 = dv4 - dv1;\n"
-" dot2 = dv4 - dv2;\n"
-" dot3 = dv4 - dv3;\n"
-" dot1 = B3_MPR_FMIN(dot1, dot2);\n"
-" dot1 = B3_MPR_FMIN(dot1, dot3);\n"
-" return b3MprEq(dot1, B3_MPR_TOLERANCE) || dot1 < B3_MPR_TOLERANCE;\n"
-"}\n"
-"inline int portalCanEncapsuleOrigin(const b3MprSimplex_t *portal, \n"
-" const b3MprSupport_t *v4,\n"
-" const b3Float4 *dir)\n"
-"{\n"
-" float dot;\n"
-" dot = b3MprVec3Dot(&v4->v, dir);\n"
-" return b3MprIsZero(dot) || dot > 0.f;\n"
-"}\n"
-"inline void b3ExpandPortal(b3MprSimplex_t *portal,\n"
-" const b3MprSupport_t *v4)\n"
-"{\n"
-" float dot;\n"
-" b3Float4 v4v0;\n"
-" b3MprVec3Cross(&v4v0, &v4->v, &b3MprSimplexPoint(portal, 0)->v);\n"
-" dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 1)->v, &v4v0);\n"
-" if (dot > 0.f){\n"
-" dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 2)->v, &v4v0);\n"
-" if (dot > 0.f){\n"
-" b3MprSimplexSet(portal, 1, v4);\n"
-" }else{\n"
-" b3MprSimplexSet(portal, 3, v4);\n"
-" }\n"
-" }else{\n"
-" dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 3)->v, &v4v0);\n"
-" if (dot > 0.f){\n"
-" b3MprSimplexSet(portal, 2, v4);\n"
-" }else{\n"
-" b3MprSimplexSet(portal, 1, v4);\n"
-" }\n"
-" }\n"
-"}\n"
-"B3_STATIC int b3DiscoverPortal(int pairIndex, int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf, \n"
-" b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData, \n"
-" b3ConstArray(b3Collidable_t) cpuCollidables,\n"
-" b3ConstArray(b3Float4) cpuVertices,\n"
-" __global b3Float4* sepAxis,\n"
-" __global int* hasSepAxis,\n"
-" b3MprSimplex_t *portal)\n"
-"{\n"
-" b3Float4 dir, va, vb;\n"
-" float dot;\n"
-" int cont;\n"
-" \n"
-" \n"
-" // vertex 0 is center of portal\n"
-" b3FindOrigin(bodyIndexA,bodyIndexB,cpuBodyBuf, b3MprSimplexPointW(portal, 0));\n"
-" // vertex 0 is center of portal\n"
-" b3MprSimplexSetSize(portal, 1);\n"
-" \n"
-" b3Float4 zero = b3MakeFloat4(0,0,0,0);\n"
-" b3Float4* b3mpr_vec3_origin = &zero;\n"
-" if (b3MprVec3Eq(&b3MprSimplexPoint(portal, 0)->v, b3mpr_vec3_origin)){\n"
-" // Portal's center lies on origin (0,0,0) => we know that objects\n"
-" // intersect but we would need to know penetration info.\n"
-" // So move center little bit...\n"
-" b3MprVec3Set(&va, FLT_EPSILON * 10.f, 0.f, 0.f);\n"
-" b3MprVec3Add(&b3MprSimplexPointW(portal, 0)->v, &va);\n"
-" }\n"
-" // vertex 1 = support in direction of origin\n"
-" b3MprVec3Copy(&dir, &b3MprSimplexPoint(portal, 0)->v);\n"
-" b3MprVec3Scale(&dir, -1.f);\n"
-" b3MprVec3Normalize(&dir);\n"
-" b3MprSupport(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&dir, b3MprSimplexPointW(portal, 1));\n"
-" b3MprSimplexSetSize(portal, 2);\n"
-" // test if origin isn't outside of v1\n"
-" dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 1)->v, &dir);\n"
-" \n"
-" if (b3MprIsZero(dot) || dot < 0.f)\n"
-" return -1;\n"
-" // vertex 2\n"
-" b3MprVec3Cross(&dir, &b3MprSimplexPoint(portal, 0)->v,\n"
-" &b3MprSimplexPoint(portal, 1)->v);\n"
-" if (b3MprIsZero(b3MprVec3Len2(&dir))){\n"
-" if (b3MprVec3Eq(&b3MprSimplexPoint(portal, 1)->v, b3mpr_vec3_origin)){\n"
-" // origin lies on v1\n"
-" return 1;\n"
-" }else{\n"
-" // origin lies on v0-v1 segment\n"
-" return 2;\n"
-" }\n"
-" }\n"
-" b3MprVec3Normalize(&dir);\n"
-" b3MprSupport(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&dir, b3MprSimplexPointW(portal, 2));\n"
-" \n"
-" dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 2)->v, &dir);\n"
-" if (b3MprIsZero(dot) || dot < 0.f)\n"
-" return -1;\n"
-" b3MprSimplexSetSize(portal, 3);\n"
-" // vertex 3 direction\n"
-" b3MprVec3Sub2(&va, &b3MprSimplexPoint(portal, 1)->v,\n"
-" &b3MprSimplexPoint(portal, 0)->v);\n"
-" b3MprVec3Sub2(&vb, &b3MprSimplexPoint(portal, 2)->v,\n"
-" &b3MprSimplexPoint(portal, 0)->v);\n"
-" b3MprVec3Cross(&dir, &va, &vb);\n"
-" b3MprVec3Normalize(&dir);\n"
-" // it is better to form portal faces to be oriented \"outside\" origin\n"
-" dot = b3MprVec3Dot(&dir, &b3MprSimplexPoint(portal, 0)->v);\n"
-" if (dot > 0.f){\n"
-" b3MprSimplexSwap(portal, 1, 2);\n"
-" b3MprVec3Scale(&dir, -1.f);\n"
-" }\n"
-" while (b3MprSimplexSize(portal) < 4){\n"
-" b3MprSupport(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&dir, b3MprSimplexPointW(portal, 3));\n"
-" \n"
-" dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 3)->v, &dir);\n"
-" if (b3MprIsZero(dot) || dot < 0.f)\n"
-" return -1;\n"
-" cont = 0;\n"
-" // test if origin is outside (v1, v0, v3) - set v2 as v3 and\n"
-" // continue\n"
-" b3MprVec3Cross(&va, &b3MprSimplexPoint(portal, 1)->v,\n"
-" &b3MprSimplexPoint(portal, 3)->v);\n"
-" dot = b3MprVec3Dot(&va, &b3MprSimplexPoint(portal, 0)->v);\n"
-" if (dot < 0.f && !b3MprIsZero(dot)){\n"
-" b3MprSimplexSet(portal, 2, b3MprSimplexPoint(portal, 3));\n"
-" cont = 1;\n"
-" }\n"
-" if (!cont){\n"
-" // test if origin is outside (v3, v0, v2) - set v1 as v3 and\n"
-" // continue\n"
-" b3MprVec3Cross(&va, &b3MprSimplexPoint(portal, 3)->v,\n"
-" &b3MprSimplexPoint(portal, 2)->v);\n"
-" dot = b3MprVec3Dot(&va, &b3MprSimplexPoint(portal, 0)->v);\n"
-" if (dot < 0.f && !b3MprIsZero(dot)){\n"
-" b3MprSimplexSet(portal, 1, b3MprSimplexPoint(portal, 3));\n"
-" cont = 1;\n"
-" }\n"
-" }\n"
-" if (cont){\n"
-" b3MprVec3Sub2(&va, &b3MprSimplexPoint(portal, 1)->v,\n"
-" &b3MprSimplexPoint(portal, 0)->v);\n"
-" b3MprVec3Sub2(&vb, &b3MprSimplexPoint(portal, 2)->v,\n"
-" &b3MprSimplexPoint(portal, 0)->v);\n"
-" b3MprVec3Cross(&dir, &va, &vb);\n"
-" b3MprVec3Normalize(&dir);\n"
-" }else{\n"
-" b3MprSimplexSetSize(portal, 4);\n"
-" }\n"
-" }\n"
-" return 0;\n"
-"}\n"
-"B3_STATIC int b3RefinePortal(int pairIndex,int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf, \n"
-" b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData, \n"
-" b3ConstArray(b3Collidable_t) cpuCollidables,\n"
-" b3ConstArray(b3Float4) cpuVertices,\n"
-" __global b3Float4* sepAxis,\n"
-" b3MprSimplex_t *portal)\n"
-"{\n"
-" b3Float4 dir;\n"
-" b3MprSupport_t v4;\n"
-" for (int i=0;i<B3_MPR_MAX_ITERATIONS;i++)\n"
-" //while (1)\n"
-" {\n"
-" // compute direction outside the portal (from v0 throught v1,v2,v3\n"
-" // face)\n"
-" b3PortalDir(portal, &dir);\n"
-" // test if origin is inside the portal\n"
-" if (portalEncapsulesOrigin(portal, &dir))\n"
-" return 0;\n"
-" // get next support point\n"
-" \n"
-" b3MprSupport(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&dir, &v4);\n"
-" // test if v4 can expand portal to contain origin and if portal\n"
-" // expanding doesn't reach given tolerance\n"
-" if (!portalCanEncapsuleOrigin(portal, &v4, &dir)\n"
-" || portalReachTolerance(portal, &v4, &dir))\n"
-" {\n"
-" return -1;\n"
-" }\n"
-" // v1-v2-v3 triangle must be rearranged to face outside Minkowski\n"
-" // difference (direction from v0).\n"
-" b3ExpandPortal(portal, &v4);\n"
-" }\n"
-" return -1;\n"
-"}\n"
-"B3_STATIC void b3FindPos(const b3MprSimplex_t *portal, b3Float4 *pos)\n"
-"{\n"
-" b3Float4 zero = b3MakeFloat4(0,0,0,0);\n"
-" b3Float4* b3mpr_vec3_origin = &zero;\n"
-" b3Float4 dir;\n"
-" size_t i;\n"
-" float b[4], sum, inv;\n"
-" b3Float4 vec, p1, p2;\n"
-" b3PortalDir(portal, &dir);\n"
-" // use barycentric coordinates of tetrahedron to find origin\n"
-" b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 1)->v,\n"
-" &b3MprSimplexPoint(portal, 2)->v);\n"
-" b[0] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 3)->v);\n"
-" b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 3)->v,\n"
-" &b3MprSimplexPoint(portal, 2)->v);\n"
-" b[1] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 0)->v);\n"
-" b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 0)->v,\n"
-" &b3MprSimplexPoint(portal, 1)->v);\n"
-" b[2] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 3)->v);\n"
-" b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 2)->v,\n"
-" &b3MprSimplexPoint(portal, 1)->v);\n"
-" b[3] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 0)->v);\n"
-" sum = b[0] + b[1] + b[2] + b[3];\n"
-" if (b3MprIsZero(sum) || sum < 0.f){\n"
-" b[0] = 0.f;\n"
-" b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 2)->v,\n"
-" &b3MprSimplexPoint(portal, 3)->v);\n"
-" b[1] = b3MprVec3Dot(&vec, &dir);\n"
-" b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 3)->v,\n"
-" &b3MprSimplexPoint(portal, 1)->v);\n"
-" b[2] = b3MprVec3Dot(&vec, &dir);\n"
-" b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 1)->v,\n"
-" &b3MprSimplexPoint(portal, 2)->v);\n"
-" b[3] = b3MprVec3Dot(&vec, &dir);\n"
-" sum = b[1] + b[2] + b[3];\n"
-" }\n"
-" inv = 1.f / sum;\n"
-" b3MprVec3Copy(&p1, b3mpr_vec3_origin);\n"
-" b3MprVec3Copy(&p2, b3mpr_vec3_origin);\n"
-" for (i = 0; i < 4; i++){\n"
-" b3MprVec3Copy(&vec, &b3MprSimplexPoint(portal, i)->v1);\n"
-" b3MprVec3Scale(&vec, b[i]);\n"
-" b3MprVec3Add(&p1, &vec);\n"
-" b3MprVec3Copy(&vec, &b3MprSimplexPoint(portal, i)->v2);\n"
-" b3MprVec3Scale(&vec, b[i]);\n"
-" b3MprVec3Add(&p2, &vec);\n"
-" }\n"
-" b3MprVec3Scale(&p1, inv);\n"
-" b3MprVec3Scale(&p2, inv);\n"
-" b3MprVec3Copy(pos, &p1);\n"
-" b3MprVec3Add(pos, &p2);\n"
-" b3MprVec3Scale(pos, 0.5);\n"
-"}\n"
-"inline float b3MprVec3Dist2(const b3Float4 *a, const b3Float4 *b)\n"
-"{\n"
-" b3Float4 ab;\n"
-" b3MprVec3Sub2(&ab, a, b);\n"
-" return b3MprVec3Len2(&ab);\n"
-"}\n"
-"inline float _b3MprVec3PointSegmentDist2(const b3Float4 *P,\n"
-" const b3Float4 *x0,\n"
-" const b3Float4 *b,\n"
-" b3Float4 *witness)\n"
-"{\n"
-" // The computation comes from solving equation of segment:\n"
-" // S(t) = x0 + t.d\n"
-" // where - x0 is initial point of segment\n"
-" // - d is direction of segment from x0 (|d| > 0)\n"
-" // - t belongs to <0, 1> interval\n"
-" // \n"
-" // Than, distance from a segment to some point P can be expressed:\n"
-" // D(t) = |x0 + t.d - P|^2\n"
-" // which is distance from any point on segment. Minimization\n"
-" // of this function brings distance from P to segment.\n"
-" // Minimization of D(t) leads to simple quadratic equation that's\n"
-" // solving is straightforward.\n"
-" //\n"
-" // Bonus of this method is witness point for free.\n"
-" float dist, t;\n"
-" b3Float4 d, a;\n"
-" // direction of segment\n"
-" b3MprVec3Sub2(&d, b, x0);\n"
-" // precompute vector from P to x0\n"
-" b3MprVec3Sub2(&a, x0, P);\n"
-" t = -1.f * b3MprVec3Dot(&a, &d);\n"
-" t /= b3MprVec3Len2(&d);\n"
-" if (t < 0.f || b3MprIsZero(t)){\n"
-" dist = b3MprVec3Dist2(x0, P);\n"
-" if (witness)\n"
-" b3MprVec3Copy(witness, x0);\n"
-" }else if (t > 1.f || b3MprEq(t, 1.f)){\n"
-" dist = b3MprVec3Dist2(b, P);\n"
-" if (witness)\n"
-" b3MprVec3Copy(witness, b);\n"
-" }else{\n"
-" if (witness){\n"
-" b3MprVec3Copy(witness, &d);\n"
-" b3MprVec3Scale(witness, t);\n"
-" b3MprVec3Add(witness, x0);\n"
-" dist = b3MprVec3Dist2(witness, P);\n"
-" }else{\n"
-" // recycling variables\n"
-" b3MprVec3Scale(&d, t);\n"
-" b3MprVec3Add(&d, &a);\n"
-" dist = b3MprVec3Len2(&d);\n"
-" }\n"
-" }\n"
-" return dist;\n"
-"}\n"
-"inline float b3MprVec3PointTriDist2(const b3Float4 *P,\n"
-" const b3Float4 *x0, const b3Float4 *B,\n"
-" const b3Float4 *C,\n"
-" b3Float4 *witness)\n"
-"{\n"
-" // Computation comes from analytic expression for triangle (x0, B, C)\n"
-" // T(s, t) = x0 + s.d1 + t.d2, where d1 = B - x0 and d2 = C - x0 and\n"
-" // Then equation for distance is:\n"
-" // D(s, t) = | T(s, t) - P |^2\n"
-" // This leads to minimization of quadratic function of two variables.\n"
-" // The solution from is taken only if s is between 0 and 1, t is\n"
-" // between 0 and 1 and t + s < 1, otherwise distance from segment is\n"
-" // computed.\n"
-" b3Float4 d1, d2, a;\n"
-" float u, v, w, p, q, r;\n"
-" float s, t, dist, dist2;\n"
-" b3Float4 witness2;\n"
-" b3MprVec3Sub2(&d1, B, x0);\n"
-" b3MprVec3Sub2(&d2, C, x0);\n"
-" b3MprVec3Sub2(&a, x0, P);\n"
-" u = b3MprVec3Dot(&a, &a);\n"
-" v = b3MprVec3Dot(&d1, &d1);\n"
-" w = b3MprVec3Dot(&d2, &d2);\n"
-" p = b3MprVec3Dot(&a, &d1);\n"
-" q = b3MprVec3Dot(&a, &d2);\n"
-" r = b3MprVec3Dot(&d1, &d2);\n"
-" s = (q * r - w * p) / (w * v - r * r);\n"
-" t = (-s * r - q) / w;\n"
-" if ((b3MprIsZero(s) || s > 0.f)\n"
-" && (b3MprEq(s, 1.f) || s < 1.f)\n"
-" && (b3MprIsZero(t) || t > 0.f)\n"
-" && (b3MprEq(t, 1.f) || t < 1.f)\n"
-" && (b3MprEq(t + s, 1.f) || t + s < 1.f)){\n"
-" if (witness){\n"
-" b3MprVec3Scale(&d1, s);\n"
-" b3MprVec3Scale(&d2, t);\n"
-" b3MprVec3Copy(witness, x0);\n"
-" b3MprVec3Add(witness, &d1);\n"
-" b3MprVec3Add(witness, &d2);\n"
-" dist = b3MprVec3Dist2(witness, P);\n"
-" }else{\n"
-" dist = s * s * v;\n"
-" dist += t * t * w;\n"
-" dist += 2.f * s * t * r;\n"
-" dist += 2.f * s * p;\n"
-" dist += 2.f * t * q;\n"
-" dist += u;\n"
-" }\n"
-" }else{\n"
-" dist = _b3MprVec3PointSegmentDist2(P, x0, B, witness);\n"
-" dist2 = _b3MprVec3PointSegmentDist2(P, x0, C, &witness2);\n"
-" if (dist2 < dist){\n"
-" dist = dist2;\n"
-" if (witness)\n"
-" b3MprVec3Copy(witness, &witness2);\n"
-" }\n"
-" dist2 = _b3MprVec3PointSegmentDist2(P, B, C, &witness2);\n"
-" if (dist2 < dist){\n"
-" dist = dist2;\n"
-" if (witness)\n"
-" b3MprVec3Copy(witness, &witness2);\n"
-" }\n"
-" }\n"
-" return dist;\n"
-"}\n"
-"B3_STATIC void b3FindPenetr(int pairIndex,int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf, \n"
-" b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData, \n"
-" b3ConstArray(b3Collidable_t) cpuCollidables,\n"
-" b3ConstArray(b3Float4) cpuVertices,\n"
-" __global b3Float4* sepAxis,\n"
-" b3MprSimplex_t *portal,\n"
-" float *depth, b3Float4 *pdir, b3Float4 *pos)\n"
-"{\n"
-" b3Float4 dir;\n"
-" b3MprSupport_t v4;\n"
-" unsigned long iterations;\n"
-" b3Float4 zero = b3MakeFloat4(0,0,0,0);\n"
-" b3Float4* b3mpr_vec3_origin = &zero;\n"
-" iterations = 1UL;\n"
-" for (int i=0;i<B3_MPR_MAX_ITERATIONS;i++)\n"
-" //while (1)\n"
-" {\n"
-" // compute portal direction and obtain next support point\n"
-" b3PortalDir(portal, &dir);\n"
-" \n"
-" b3MprSupport(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&dir, &v4);\n"
-" // reached tolerance -> find penetration info\n"
-" if (portalReachTolerance(portal, &v4, &dir)\n"
-" || iterations ==B3_MPR_MAX_ITERATIONS)\n"
-" {\n"
-" *depth = b3MprVec3PointTriDist2(b3mpr_vec3_origin,&b3MprSimplexPoint(portal, 1)->v,&b3MprSimplexPoint(portal, 2)->v,&b3MprSimplexPoint(portal, 3)->v,pdir);\n"
-" *depth = B3_MPR_SQRT(*depth);\n"
-" \n"
-" if (b3MprIsZero((*pdir).x) && b3MprIsZero((*pdir).y) && b3MprIsZero((*pdir).z))\n"
-" {\n"
-" \n"
-" *pdir = dir;\n"
-" } \n"
-" b3MprVec3Normalize(pdir);\n"
-" \n"
-" // barycentric coordinates:\n"
-" b3FindPos(portal, pos);\n"
-" return;\n"
-" }\n"
-" b3ExpandPortal(portal, &v4);\n"
-" iterations++;\n"
-" }\n"
-"}\n"
-"B3_STATIC void b3FindPenetrTouch(b3MprSimplex_t *portal,float *depth, b3Float4 *dir, b3Float4 *pos)\n"
-"{\n"
-" // Touching contact on portal's v1 - so depth is zero and direction\n"
-" // is unimportant and pos can be guessed\n"
-" *depth = 0.f;\n"
-" b3Float4 zero = b3MakeFloat4(0,0,0,0);\n"
-" b3Float4* b3mpr_vec3_origin = &zero;\n"
-" b3MprVec3Copy(dir, b3mpr_vec3_origin);\n"
-" b3MprVec3Copy(pos, &b3MprSimplexPoint(portal, 1)->v1);\n"
-" b3MprVec3Add(pos, &b3MprSimplexPoint(portal, 1)->v2);\n"
-" b3MprVec3Scale(pos, 0.5);\n"
-"}\n"
-"B3_STATIC void b3FindPenetrSegment(b3MprSimplex_t *portal,\n"
-" float *depth, b3Float4 *dir, b3Float4 *pos)\n"
-"{\n"
-" \n"
-" // Origin lies on v0-v1 segment.\n"
-" // Depth is distance to v1, direction also and position must be\n"
-" // computed\n"
-" b3MprVec3Copy(pos, &b3MprSimplexPoint(portal, 1)->v1);\n"
-" b3MprVec3Add(pos, &b3MprSimplexPoint(portal, 1)->v2);\n"
-" b3MprVec3Scale(pos, 0.5f);\n"
-" \n"
-" b3MprVec3Copy(dir, &b3MprSimplexPoint(portal, 1)->v);\n"
-" *depth = B3_MPR_SQRT(b3MprVec3Len2(dir));\n"
-" b3MprVec3Normalize(dir);\n"
-"}\n"
-"inline int b3MprPenetration(int pairIndex, int bodyIndexA, int bodyIndexB,\n"
-" b3ConstArray(b3RigidBodyData_t) cpuBodyBuf,\n"
-" b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData, \n"
-" b3ConstArray(b3Collidable_t) cpuCollidables,\n"
-" b3ConstArray(b3Float4) cpuVertices,\n"
-" __global b3Float4* sepAxis,\n"
-" __global int* hasSepAxis,\n"
-" float *depthOut, b3Float4* dirOut, b3Float4* posOut)\n"
-"{\n"
-" \n"
-" b3MprSimplex_t portal;\n"
-" \n"
-"// if (!hasSepAxis[pairIndex])\n"
-" // return -1;\n"
-" \n"
-" hasSepAxis[pairIndex] = 0;\n"
-" int res;\n"
-" // Phase 1: Portal discovery\n"
-" res = b3DiscoverPortal(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices,sepAxis,hasSepAxis, &portal);\n"
-" \n"
-" \n"
-" //sepAxis[pairIndex] = *pdir;//or -dir?\n"
-" switch (res)\n"
-" {\n"
-" case 0:\n"
-" {\n"
-" // Phase 2: Portal refinement\n"
-" \n"
-" res = b3RefinePortal(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&portal);\n"
-" if (res < 0)\n"
-" return -1;\n"
-" // Phase 3. Penetration info\n"
-" b3FindPenetr(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&portal, depthOut, dirOut, posOut);\n"
-" hasSepAxis[pairIndex] = 1;\n"
-" sepAxis[pairIndex] = -*dirOut;\n"
-" break;\n"
-" }\n"
-" case 1:\n"
-" {\n"
-" // Touching contact on portal's v1.\n"
-" b3FindPenetrTouch(&portal, depthOut, dirOut, posOut);\n"
-" break;\n"
-" }\n"
-" case 2:\n"
-" {\n"
-" \n"
-" b3FindPenetrSegment( &portal, depthOut, dirOut, posOut);\n"
-" break;\n"
-" }\n"
-" default:\n"
-" {\n"
-" hasSepAxis[pairIndex]=0;\n"
-" //if (res < 0)\n"
-" //{\n"
-" // Origin isn't inside portal - no collision.\n"
-" return -1;\n"
-" //}\n"
-" }\n"
-" };\n"
-" \n"
-" return 0;\n"
-"};\n"
-"#endif //B3_MPR_PENETRATION_H\n"
-"#ifndef B3_CONTACT4DATA_H\n"
-"#define B3_CONTACT4DATA_H\n"
-"#ifndef B3_FLOAT4_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#endif \n"
-"#endif //B3_FLOAT4_H\n"
-"typedef struct b3Contact4Data b3Contact4Data_t;\n"
-"struct b3Contact4Data\n"
-"{\n"
-" b3Float4 m_worldPosB[4];\n"
-"// b3Float4 m_localPosA[4];\n"
-"// b3Float4 m_localPosB[4];\n"
-" b3Float4 m_worldNormalOnB; // w: m_nPoints\n"
-" unsigned short m_restituitionCoeffCmp;\n"
-" unsigned short m_frictionCoeffCmp;\n"
-" int m_batchIdx;\n"
-" int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
-" int m_bodyBPtrAndSignBit;\n"
-" int m_childIndexA;\n"
-" int m_childIndexB;\n"
-" int m_unused1;\n"
-" int m_unused2;\n"
-"};\n"
-"inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
-"{\n"
-" return (int)contact->m_worldNormalOnB.w;\n"
-"};\n"
-"inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
-"{\n"
-" contact->m_worldNormalOnB.w = (float)numPoints;\n"
-"};\n"
-"#endif //B3_CONTACT4DATA_H\n"
-"#define AppendInc(x, out) out = atomic_inc(x)\n"
-"#define GET_NPOINTS(x) (x).m_worldNormalOnB.w\n"
-"#ifdef cl_ext_atomic_counters_32\n"
-" #pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
-"#else\n"
-" #define counter32_t volatile __global int*\n"
-"#endif\n"
-"__kernel void mprPenetrationKernel( __global int4* pairs,\n"
-" __global const b3RigidBodyData_t* rigidBodies, \n"
-" __global const b3Collidable_t* collidables,\n"
-" __global const b3ConvexPolyhedronData_t* convexShapes, \n"
-" __global const float4* vertices,\n"
-" __global float4* separatingNormals,\n"
-" __global int* hasSeparatingAxis,\n"
-" __global struct b3Contact4Data* restrict globalContactsOut,\n"
-" counter32_t nGlobalContactsOut,\n"
-" int contactCapacity,\n"
-" int numPairs)\n"
-"{\n"
-" int i = get_global_id(0);\n"
-" int pairIndex = i;\n"
-" if (i<numPairs)\n"
-" {\n"
-" int bodyIndexA = pairs[i].x;\n"
-" int bodyIndexB = pairs[i].y;\n"
-" int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
-" int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
-" \n"
-" int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
-" int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
-" \n"
-" \n"
-" //once the broadphase avoids static-static pairs, we can remove this test\n"
-" if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))\n"
-" {\n"
-" return;\n"
-" }\n"
-" \n"
-" if ((collidables[collidableIndexA].m_shapeType!=SHAPE_CONVEX_HULL) ||(collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL))\n"
-" {\n"
-" return;\n"
-" }\n"
-" float depthOut;\n"
-" b3Float4 dirOut;\n"
-" b3Float4 posOut;\n"
-" int res = b3MprPenetration(pairIndex, bodyIndexA, bodyIndexB,rigidBodies,convexShapes,collidables,vertices,separatingNormals,hasSeparatingAxis,&depthOut, &dirOut, &posOut);\n"
-" \n"
-" \n"
-" \n"
-" \n"
-" if (res==0)\n"
-" {\n"
-" //add a contact\n"
-" int dstIdx;\n"
-" AppendInc( nGlobalContactsOut, dstIdx );\n"
-" if (dstIdx<contactCapacity)\n"
-" {\n"
-" pairs[pairIndex].z = dstIdx;\n"
-" __global struct b3Contact4Data* c = globalContactsOut + dstIdx;\n"
-" c->m_worldNormalOnB = -dirOut;//normal;\n"
-" c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
-" c->m_batchIdx = pairIndex;\n"
-" int bodyA = pairs[pairIndex].x;\n"
-" int bodyB = pairs[pairIndex].y;\n"
-" c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0 ? -bodyA:bodyA;\n"
-" c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0 ? -bodyB:bodyB;\n"
-" c->m_childIndexA = -1;\n"
-" c->m_childIndexB = -1;\n"
-" //for (int i=0;i<nContacts;i++)\n"
-" posOut.w = -depthOut;\n"
-" c->m_worldPosB[0] = posOut;//localPoints[contactIdx[i]];\n"
-" GET_NPOINTS(*c) = 1;//nContacts;\n"
-" }\n"
-" }\n"
-" }\n"
-"}\n"
-"typedef float4 Quaternion;\n"
-"#define make_float4 (float4)\n"
-"__inline\n"
-"float dot3F4(float4 a, float4 b)\n"
-"{\n"
-" float4 a1 = make_float4(a.xyz,0.f);\n"
-" float4 b1 = make_float4(b.xyz,0.f);\n"
-" return dot(a1, b1);\n"
-"}\n"
-"__inline\n"
-"float4 cross3(float4 a, float4 b)\n"
-"{\n"
-" return cross(a,b);\n"
-"}\n"
-"__inline\n"
-"Quaternion qtMul(Quaternion a, Quaternion b)\n"
-"{\n"
-" Quaternion ans;\n"
-" ans = cross3( a, b );\n"
-" ans += a.w*b+b.w*a;\n"
-"// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
-" ans.w = a.w*b.w - dot3F4(a, b);\n"
-" return ans;\n"
-"}\n"
-"__inline\n"
-"Quaternion qtInvert(Quaternion q)\n"
-"{\n"
-" return (Quaternion)(-q.xyz, q.w);\n"
-"}\n"
-"__inline\n"
-"float4 qtRotate(Quaternion q, float4 vec)\n"
-"{\n"
-" Quaternion qInv = qtInvert( q );\n"
-" float4 vcpy = vec;\n"
-" vcpy.w = 0.f;\n"
-" float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
-" return out;\n"
-"}\n"
-"__inline\n"
-"float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)\n"
-"{\n"
-" return qtRotate( *orientation, *p ) + (*translation);\n"
-"}\n"
-"__inline\n"
-"float4 qtInvRotate(const Quaternion q, float4 vec)\n"
-"{\n"
-" return qtRotate( qtInvert( q ), vec );\n"
-"}\n"
-"inline void project(__global const b3ConvexPolyhedronData_t* hull, const float4 pos, const float4 orn, \n"
-"const float4* dir, __global const float4* vertices, float* min, float* max)\n"
-"{\n"
-" min[0] = FLT_MAX;\n"
-" max[0] = -FLT_MAX;\n"
-" int numVerts = hull->m_numVertices;\n"
-" const float4 localDir = qtInvRotate(orn,*dir);\n"
-" float offset = dot(pos,*dir);\n"
-" for(int i=0;i<numVerts;i++)\n"
-" {\n"
-" float dp = dot(vertices[hull->m_vertexOffset+i],localDir);\n"
-" if(dp < min[0]) \n"
-" min[0] = dp;\n"
-" if(dp > max[0]) \n"
-" max[0] = dp;\n"
-" }\n"
-" if(min[0]>max[0])\n"
-" {\n"
-" float tmp = min[0];\n"
-" min[0] = max[0];\n"
-" max[0] = tmp;\n"
-" }\n"
-" min[0] += offset;\n"
-" max[0] += offset;\n"
-"}\n"
-"bool findSeparatingAxisUnitSphere( __global const b3ConvexPolyhedronData_t* hullA, __global const b3ConvexPolyhedronData_t* hullB, \n"
-" const float4 posA1,\n"
-" const float4 ornA,\n"
-" const float4 posB1,\n"
-" const float4 ornB,\n"
-" const float4 DeltaC2,\n"
-" __global const float4* vertices,\n"
-" __global const float4* unitSphereDirections,\n"
-" int numUnitSphereDirections,\n"
-" float4* sep,\n"
-" float* dmin)\n"
-"{\n"
-" \n"
-" float4 posA = posA1;\n"
-" posA.w = 0.f;\n"
-" float4 posB = posB1;\n"
-" posB.w = 0.f;\n"
-" int curPlaneTests=0;\n"
-" int curEdgeEdge = 0;\n"
-" // Test unit sphere directions\n"
-" for (int i=0;i<numUnitSphereDirections;i++)\n"
-" {\n"
-" float4 crossje;\n"
-" crossje = unitSphereDirections[i]; \n"
-" if (dot3F4(DeltaC2,crossje)>0)\n"
-" crossje *= -1.f;\n"
-" {\n"
-" float dist;\n"
-" bool result = true;\n"
-" float Min0,Max0;\n"
-" float Min1,Max1;\n"
-" project(hullA,posA,ornA,&crossje,vertices, &Min0, &Max0);\n"
-" project(hullB,posB,ornB,&crossje,vertices, &Min1, &Max1);\n"
-" \n"
-" if(Max0<Min1 || Max1<Min0)\n"
-" return false;\n"
-" \n"
-" float d0 = Max0 - Min1;\n"
-" float d1 = Max1 - Min0;\n"
-" dist = d0<d1 ? d0:d1;\n"
-" result = true;\n"
-" \n"
-" if(dist<*dmin)\n"
-" {\n"
-" *dmin = dist;\n"
-" *sep = crossje;\n"
-" }\n"
-" }\n"
-" }\n"
-" \n"
-" if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
-" {\n"
-" *sep = -(*sep);\n"
-" }\n"
-" return true;\n"
-"}\n"
-"__kernel void findSeparatingAxisUnitSphereKernel( __global const int4* pairs, \n"
-" __global const b3RigidBodyData_t* rigidBodies, \n"
-" __global const b3Collidable_t* collidables,\n"
-" __global const b3ConvexPolyhedronData_t* convexShapes, \n"
-" __global const float4* vertices,\n"
-" __global const float4* unitSphereDirections,\n"
-" __global float4* separatingNormals,\n"
-" __global int* hasSeparatingAxis,\n"
-" __global float* dmins,\n"
-" int numUnitSphereDirections,\n"
-" int numPairs\n"
-" )\n"
-"{\n"
-" int i = get_global_id(0);\n"
-" \n"
-" if (i<numPairs)\n"
-" {\n"
-" if (hasSeparatingAxis[i])\n"
-" {\n"
-" \n"
-" int bodyIndexA = pairs[i].x;\n"
-" int bodyIndexB = pairs[i].y;\n"
-" \n"
-" int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
-" int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
-" \n"
-" int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
-" int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
-" \n"
-" \n"
-" int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
-" \n"
-" float dmin = dmins[i];\n"
-" \n"
-" float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
-" posA.w = 0.f;\n"
-" float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
-" posB.w = 0.f;\n"
-" float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
-" float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
-" float4 c0 = transform(&c0local, &posA, &ornA);\n"
-" float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
-" float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
-" float4 c1 = transform(&c1local,&posB,&ornB);\n"
-" const float4 DeltaC2 = c0 - c1;\n"
-" float4 sepNormal = separatingNormals[i];\n"
-" \n"
-" int numEdgeEdgeDirections = convexShapes[shapeIndexA].m_numUniqueEdges*convexShapes[shapeIndexB].m_numUniqueEdges;\n"
-" if (numEdgeEdgeDirections>numUnitSphereDirections)\n"
-" {\n"
-" bool sepEE = findSeparatingAxisUnitSphere( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,\n"
-" posB,ornB,\n"
-" DeltaC2,\n"
-" vertices,unitSphereDirections,numUnitSphereDirections,&sepNormal,&dmin);\n"
-" if (!sepEE)\n"
-" {\n"
-" hasSeparatingAxis[i] = 0;\n"
-" } else\n"
-" {\n"
-" hasSeparatingAxis[i] = 1;\n"
-" separatingNormals[i] = sepNormal;\n"
-" }\n"
-" }\n"
-" } //if (hasSeparatingAxis[i])\n"
-" }//(i<numPairs)\n"
-"}\n"
-;
+static const char* mprKernelsCL =
+ "/***\n"
+ " * ---------------------------------\n"
+ " * Copyright (c)2012 Daniel Fiser <danfis@danfis.cz>\n"
+ " *\n"
+ " * This file was ported from mpr.c file, part of libccd.\n"
+ " * The Minkoski Portal Refinement implementation was ported \n"
+ " * to OpenCL by Erwin Coumans for the Bullet 3 Physics library.\n"
+ " * at http://github.com/erwincoumans/bullet3\n"
+ " *\n"
+ " * Distributed under the OSI-approved BSD License (the \"License\");\n"
+ " * see <http://www.opensource.org/licenses/bsd-license.php>.\n"
+ " * This software is distributed WITHOUT ANY WARRANTY; without even the\n"
+ " * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
+ " * See the License for more information.\n"
+ " */\n"
+ "#ifndef B3_MPR_PENETRATION_H\n"
+ "#define B3_MPR_PENETRATION_H\n"
+ "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+ "#define B3_PLATFORM_DEFINITIONS_H\n"
+ "struct MyTest\n"
+ "{\n"
+ " int bla;\n"
+ "};\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
+ "#define B3_LARGE_FLOAT 1e18f\n"
+ "#define B3_INFINITY 1e18f\n"
+ "#define b3Assert(a)\n"
+ "#define b3ConstArray(a) __global const a*\n"
+ "#define b3AtomicInc atomic_inc\n"
+ "#define b3AtomicAdd atomic_add\n"
+ "#define b3Fabs fabs\n"
+ "#define b3Sqrt native_sqrt\n"
+ "#define b3Sin native_sin\n"
+ "#define b3Cos native_cos\n"
+ "#define B3_STATIC\n"
+ "#endif\n"
+ "#endif\n"
+ "#ifndef B3_FLOAT4_H\n"
+ "#define B3_FLOAT4_H\n"
+ "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#endif\n"
+ "#endif\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ " typedef float4 b3Float4;\n"
+ " #define b3Float4ConstArg const b3Float4\n"
+ " #define b3MakeFloat4 (float4)\n"
+ " float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+ " {\n"
+ " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+ " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+ " return dot(a1, b1);\n"
+ " }\n"
+ " b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+ " {\n"
+ " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+ " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+ " return cross(a1, b1);\n"
+ " }\n"
+ " #define b3MinFloat4 min\n"
+ " #define b3MaxFloat4 max\n"
+ " #define b3Normalized(a) normalize(a)\n"
+ "#endif \n"
+ " \n"
+ "inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
+ "{\n"
+ " if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
+ " return false;\n"
+ " return true;\n"
+ "}\n"
+ "inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
+ "{\n"
+ " float maxDot = -B3_INFINITY;\n"
+ " int i = 0;\n"
+ " int ptIndex = -1;\n"
+ " for( i = 0; i < vecLen; i++ )\n"
+ " {\n"
+ " float dot = b3Dot3F4(vecArray[i],vec);\n"
+ " \n"
+ " if( dot > maxDot )\n"
+ " {\n"
+ " maxDot = dot;\n"
+ " ptIndex = i;\n"
+ " }\n"
+ " }\n"
+ " b3Assert(ptIndex>=0);\n"
+ " if (ptIndex<0)\n"
+ " {\n"
+ " ptIndex = 0;\n"
+ " }\n"
+ " *dotOut = maxDot;\n"
+ " return ptIndex;\n"
+ "}\n"
+ "#endif //B3_FLOAT4_H\n"
+ "#ifndef B3_RIGIDBODY_DATA_H\n"
+ "#define B3_RIGIDBODY_DATA_H\n"
+ "#ifndef B3_FLOAT4_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#endif \n"
+ "#endif //B3_FLOAT4_H\n"
+ "#ifndef B3_QUAT_H\n"
+ "#define B3_QUAT_H\n"
+ "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#endif\n"
+ "#endif\n"
+ "#ifndef B3_FLOAT4_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#endif \n"
+ "#endif //B3_FLOAT4_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ " typedef float4 b3Quat;\n"
+ " #define b3QuatConstArg const b3Quat\n"
+ " \n"
+ " \n"
+ "inline float4 b3FastNormalize4(float4 v)\n"
+ "{\n"
+ " v = (float4)(v.xyz,0.f);\n"
+ " return fast_normalize(v);\n"
+ "}\n"
+ " \n"
+ "inline b3Quat b3QuatMul(b3Quat a, b3Quat b);\n"
+ "inline b3Quat b3QuatNormalized(b3QuatConstArg in);\n"
+ "inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec);\n"
+ "inline b3Quat b3QuatInvert(b3QuatConstArg q);\n"
+ "inline b3Quat b3QuatInverse(b3QuatConstArg q);\n"
+ "inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b)\n"
+ "{\n"
+ " b3Quat ans;\n"
+ " ans = b3Cross3( a, b );\n"
+ " ans += a.w*b+b.w*a;\n"
+ "// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+ " ans.w = a.w*b.w - b3Dot3F4(a, b);\n"
+ " return ans;\n"
+ "}\n"
+ "inline b3Quat b3QuatNormalized(b3QuatConstArg in)\n"
+ "{\n"
+ " b3Quat q;\n"
+ " q=in;\n"
+ " //return b3FastNormalize4(in);\n"
+ " float len = native_sqrt(dot(q, q));\n"
+ " if(len > 0.f)\n"
+ " {\n"
+ " q *= 1.f / len;\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " q.x = q.y = q.z = 0.f;\n"
+ " q.w = 1.f;\n"
+ " }\n"
+ " return q;\n"
+ "}\n"
+ "inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+ "{\n"
+ " b3Quat qInv = b3QuatInvert( q );\n"
+ " float4 vcpy = vec;\n"
+ " vcpy.w = 0.f;\n"
+ " float4 out = b3QuatMul(b3QuatMul(q,vcpy),qInv);\n"
+ " return out;\n"
+ "}\n"
+ "inline b3Quat b3QuatInverse(b3QuatConstArg q)\n"
+ "{\n"
+ " return (b3Quat)(-q.xyz, q.w);\n"
+ "}\n"
+ "inline b3Quat b3QuatInvert(b3QuatConstArg q)\n"
+ "{\n"
+ " return (b3Quat)(-q.xyz, q.w);\n"
+ "}\n"
+ "inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+ "{\n"
+ " return b3QuatRotate( b3QuatInvert( q ), vec );\n"
+ "}\n"
+ "inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation)\n"
+ "{\n"
+ " return b3QuatRotate( orientation, point ) + (translation);\n"
+ "}\n"
+ " \n"
+ "#endif \n"
+ "#endif //B3_QUAT_H\n"
+ "#ifndef B3_MAT3x3_H\n"
+ "#define B3_MAT3x3_H\n"
+ "#ifndef B3_QUAT_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#endif \n"
+ "#endif //B3_QUAT_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "typedef struct\n"
+ "{\n"
+ " b3Float4 m_row[3];\n"
+ "}b3Mat3x3;\n"
+ "#define b3Mat3x3ConstArg const b3Mat3x3\n"
+ "#define b3GetRow(m,row) (m.m_row[row])\n"
+ "inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat)\n"
+ "{\n"
+ " b3Float4 quat2 = (b3Float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);\n"
+ " b3Mat3x3 out;\n"
+ " out.m_row[0].x=1-2*quat2.y-2*quat2.z;\n"
+ " out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;\n"
+ " out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;\n"
+ " out.m_row[0].w = 0.f;\n"
+ " out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;\n"
+ " out.m_row[1].y=1-2*quat2.x-2*quat2.z;\n"
+ " out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;\n"
+ " out.m_row[1].w = 0.f;\n"
+ " out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;\n"
+ " out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;\n"
+ " out.m_row[2].z=1-2*quat2.x-2*quat2.y;\n"
+ " out.m_row[2].w = 0.f;\n"
+ " return out;\n"
+ "}\n"
+ "inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn)\n"
+ "{\n"
+ " b3Mat3x3 out;\n"
+ " out.m_row[0] = fabs(matIn.m_row[0]);\n"
+ " out.m_row[1] = fabs(matIn.m_row[1]);\n"
+ " out.m_row[2] = fabs(matIn.m_row[2]);\n"
+ " return out;\n"
+ "}\n"
+ "__inline\n"
+ "b3Mat3x3 mtZero();\n"
+ "__inline\n"
+ "b3Mat3x3 mtIdentity();\n"
+ "__inline\n"
+ "b3Mat3x3 mtTranspose(b3Mat3x3 m);\n"
+ "__inline\n"
+ "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);\n"
+ "__inline\n"
+ "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);\n"
+ "__inline\n"
+ "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);\n"
+ "__inline\n"
+ "b3Mat3x3 mtZero()\n"
+ "{\n"
+ " b3Mat3x3 m;\n"
+ " m.m_row[0] = (b3Float4)(0.f);\n"
+ " m.m_row[1] = (b3Float4)(0.f);\n"
+ " m.m_row[2] = (b3Float4)(0.f);\n"
+ " return m;\n"
+ "}\n"
+ "__inline\n"
+ "b3Mat3x3 mtIdentity()\n"
+ "{\n"
+ " b3Mat3x3 m;\n"
+ " m.m_row[0] = (b3Float4)(1,0,0,0);\n"
+ " m.m_row[1] = (b3Float4)(0,1,0,0);\n"
+ " m.m_row[2] = (b3Float4)(0,0,1,0);\n"
+ " return m;\n"
+ "}\n"
+ "__inline\n"
+ "b3Mat3x3 mtTranspose(b3Mat3x3 m)\n"
+ "{\n"
+ " b3Mat3x3 out;\n"
+ " out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
+ " out.m_row[1] = (b3Float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
+ " out.m_row[2] = (b3Float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
+ " return out;\n"
+ "}\n"
+ "__inline\n"
+ "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)\n"
+ "{\n"
+ " b3Mat3x3 transB;\n"
+ " transB = mtTranspose( b );\n"
+ " b3Mat3x3 ans;\n"
+ " // why this doesn't run when 0ing in the for{}\n"
+ " a.m_row[0].w = 0.f;\n"
+ " a.m_row[1].w = 0.f;\n"
+ " a.m_row[2].w = 0.f;\n"
+ " for(int i=0; i<3; i++)\n"
+ " {\n"
+ "// a.m_row[i].w = 0.f;\n"
+ " ans.m_row[i].x = b3Dot3F4(a.m_row[i],transB.m_row[0]);\n"
+ " ans.m_row[i].y = b3Dot3F4(a.m_row[i],transB.m_row[1]);\n"
+ " ans.m_row[i].z = b3Dot3F4(a.m_row[i],transB.m_row[2]);\n"
+ " ans.m_row[i].w = 0.f;\n"
+ " }\n"
+ " return ans;\n"
+ "}\n"
+ "__inline\n"
+ "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)\n"
+ "{\n"
+ " b3Float4 ans;\n"
+ " ans.x = b3Dot3F4( a.m_row[0], b );\n"
+ " ans.y = b3Dot3F4( a.m_row[1], b );\n"
+ " ans.z = b3Dot3F4( a.m_row[2], b );\n"
+ " ans.w = 0.f;\n"
+ " return ans;\n"
+ "}\n"
+ "__inline\n"
+ "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)\n"
+ "{\n"
+ " b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
+ " b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
+ " b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
+ " b3Float4 ans;\n"
+ " ans.x = b3Dot3F4( a, colx );\n"
+ " ans.y = b3Dot3F4( a, coly );\n"
+ " ans.z = b3Dot3F4( a, colz );\n"
+ " return ans;\n"
+ "}\n"
+ "#endif\n"
+ "#endif //B3_MAT3x3_H\n"
+ "typedef struct b3RigidBodyData b3RigidBodyData_t;\n"
+ "struct b3RigidBodyData\n"
+ "{\n"
+ " b3Float4 m_pos;\n"
+ " b3Quat m_quat;\n"
+ " b3Float4 m_linVel;\n"
+ " b3Float4 m_angVel;\n"
+ " int m_collidableIdx;\n"
+ " float m_invMass;\n"
+ " float m_restituitionCoeff;\n"
+ " float m_frictionCoeff;\n"
+ "};\n"
+ "typedef struct b3InertiaData b3InertiaData_t;\n"
+ "struct b3InertiaData\n"
+ "{\n"
+ " b3Mat3x3 m_invInertiaWorld;\n"
+ " b3Mat3x3 m_initInvInertia;\n"
+ "};\n"
+ "#endif //B3_RIGIDBODY_DATA_H\n"
+ " \n"
+ "#ifndef B3_CONVEX_POLYHEDRON_DATA_H\n"
+ "#define B3_CONVEX_POLYHEDRON_DATA_H\n"
+ "#ifndef B3_FLOAT4_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#endif \n"
+ "#endif //B3_FLOAT4_H\n"
+ "#ifndef B3_QUAT_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#endif \n"
+ "#endif //B3_QUAT_H\n"
+ "typedef struct b3GpuFace b3GpuFace_t;\n"
+ "struct b3GpuFace\n"
+ "{\n"
+ " b3Float4 m_plane;\n"
+ " int m_indexOffset;\n"
+ " int m_numIndices;\n"
+ " int m_unusedPadding1;\n"
+ " int m_unusedPadding2;\n"
+ "};\n"
+ "typedef struct b3ConvexPolyhedronData b3ConvexPolyhedronData_t;\n"
+ "struct b3ConvexPolyhedronData\n"
+ "{\n"
+ " b3Float4 m_localCenter;\n"
+ " b3Float4 m_extents;\n"
+ " b3Float4 mC;\n"
+ " b3Float4 mE;\n"
+ " float m_radius;\n"
+ " int m_faceOffset;\n"
+ " int m_numFaces;\n"
+ " int m_numVertices;\n"
+ " int m_vertexOffset;\n"
+ " int m_uniqueEdgesOffset;\n"
+ " int m_numUniqueEdges;\n"
+ " int m_unused;\n"
+ "};\n"
+ "#endif //B3_CONVEX_POLYHEDRON_DATA_H\n"
+ "#ifndef B3_COLLIDABLE_H\n"
+ "#define B3_COLLIDABLE_H\n"
+ "#ifndef B3_FLOAT4_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#endif \n"
+ "#endif //B3_FLOAT4_H\n"
+ "#ifndef B3_QUAT_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#endif \n"
+ "#endif //B3_QUAT_H\n"
+ "enum b3ShapeTypes\n"
+ "{\n"
+ " SHAPE_HEIGHT_FIELD=1,\n"
+ " SHAPE_CONVEX_HULL=3,\n"
+ " SHAPE_PLANE=4,\n"
+ " SHAPE_CONCAVE_TRIMESH=5,\n"
+ " SHAPE_COMPOUND_OF_CONVEX_HULLS=6,\n"
+ " SHAPE_SPHERE=7,\n"
+ " MAX_NUM_SHAPE_TYPES,\n"
+ "};\n"
+ "typedef struct b3Collidable b3Collidable_t;\n"
+ "struct b3Collidable\n"
+ "{\n"
+ " union {\n"
+ " int m_numChildShapes;\n"
+ " int m_bvhIndex;\n"
+ " };\n"
+ " union\n"
+ " {\n"
+ " float m_radius;\n"
+ " int m_compoundBvhIndex;\n"
+ " };\n"
+ " int m_shapeType;\n"
+ " int m_shapeIndex;\n"
+ "};\n"
+ "typedef struct b3GpuChildShape b3GpuChildShape_t;\n"
+ "struct b3GpuChildShape\n"
+ "{\n"
+ " b3Float4 m_childPosition;\n"
+ " b3Quat m_childOrientation;\n"
+ " int m_shapeIndex;\n"
+ " int m_unused0;\n"
+ " int m_unused1;\n"
+ " int m_unused2;\n"
+ "};\n"
+ "struct b3CompoundOverlappingPair\n"
+ "{\n"
+ " int m_bodyIndexA;\n"
+ " int m_bodyIndexB;\n"
+ "// int m_pairType;\n"
+ " int m_childShapeIndexA;\n"
+ " int m_childShapeIndexB;\n"
+ "};\n"
+ "#endif //B3_COLLIDABLE_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#define B3_MPR_SQRT sqrt\n"
+ "#endif\n"
+ "#define B3_MPR_FMIN(x, y) ((x) < (y) ? (x) : (y))\n"
+ "#define B3_MPR_FABS fabs\n"
+ "#define B3_MPR_TOLERANCE 1E-6f\n"
+ "#define B3_MPR_MAX_ITERATIONS 1000\n"
+ "struct _b3MprSupport_t \n"
+ "{\n"
+ " b3Float4 v; //!< Support point in minkowski sum\n"
+ " b3Float4 v1; //!< Support point in obj1\n"
+ " b3Float4 v2; //!< Support point in obj2\n"
+ "};\n"
+ "typedef struct _b3MprSupport_t b3MprSupport_t;\n"
+ "struct _b3MprSimplex_t \n"
+ "{\n"
+ " b3MprSupport_t ps[4];\n"
+ " int last; //!< index of last added point\n"
+ "};\n"
+ "typedef struct _b3MprSimplex_t b3MprSimplex_t;\n"
+ "inline b3MprSupport_t* b3MprSimplexPointW(b3MprSimplex_t *s, int idx)\n"
+ "{\n"
+ " return &s->ps[idx];\n"
+ "}\n"
+ "inline void b3MprSimplexSetSize(b3MprSimplex_t *s, int size)\n"
+ "{\n"
+ " s->last = size - 1;\n"
+ "}\n"
+ "inline int b3MprSimplexSize(const b3MprSimplex_t *s)\n"
+ "{\n"
+ " return s->last + 1;\n"
+ "}\n"
+ "inline const b3MprSupport_t* b3MprSimplexPoint(const b3MprSimplex_t* s, int idx)\n"
+ "{\n"
+ " // here is no check on boundaries\n"
+ " return &s->ps[idx];\n"
+ "}\n"
+ "inline void b3MprSupportCopy(b3MprSupport_t *d, const b3MprSupport_t *s)\n"
+ "{\n"
+ " *d = *s;\n"
+ "}\n"
+ "inline void b3MprSimplexSet(b3MprSimplex_t *s, size_t pos, const b3MprSupport_t *a)\n"
+ "{\n"
+ " b3MprSupportCopy(s->ps + pos, a);\n"
+ "}\n"
+ "inline void b3MprSimplexSwap(b3MprSimplex_t *s, size_t pos1, size_t pos2)\n"
+ "{\n"
+ " b3MprSupport_t supp;\n"
+ " b3MprSupportCopy(&supp, &s->ps[pos1]);\n"
+ " b3MprSupportCopy(&s->ps[pos1], &s->ps[pos2]);\n"
+ " b3MprSupportCopy(&s->ps[pos2], &supp);\n"
+ "}\n"
+ "inline int b3MprIsZero(float val)\n"
+ "{\n"
+ " return B3_MPR_FABS(val) < FLT_EPSILON;\n"
+ "}\n"
+ "inline int b3MprEq(float _a, float _b)\n"
+ "{\n"
+ " float ab;\n"
+ " float a, b;\n"
+ " ab = B3_MPR_FABS(_a - _b);\n"
+ " if (B3_MPR_FABS(ab) < FLT_EPSILON)\n"
+ " return 1;\n"
+ " a = B3_MPR_FABS(_a);\n"
+ " b = B3_MPR_FABS(_b);\n"
+ " if (b > a){\n"
+ " return ab < FLT_EPSILON * b;\n"
+ " }else{\n"
+ " return ab < FLT_EPSILON * a;\n"
+ " }\n"
+ "}\n"
+ "inline int b3MprVec3Eq(const b3Float4* a, const b3Float4 *b)\n"
+ "{\n"
+ " return b3MprEq((*a).x, (*b).x)\n"
+ " && b3MprEq((*a).y, (*b).y)\n"
+ " && b3MprEq((*a).z, (*b).z);\n"
+ "}\n"
+ "inline b3Float4 b3LocalGetSupportVertex(b3Float4ConstArg supportVec,__global const b3ConvexPolyhedronData_t* hull, b3ConstArray(b3Float4) verticesA)\n"
+ "{\n"
+ " b3Float4 supVec = b3MakeFloat4(0,0,0,0);\n"
+ " float maxDot = -B3_LARGE_FLOAT;\n"
+ " if( 0 < hull->m_numVertices )\n"
+ " {\n"
+ " const b3Float4 scaled = supportVec;\n"
+ " int index = b3MaxDot(scaled, &verticesA[hull->m_vertexOffset], hull->m_numVertices, &maxDot);\n"
+ " return verticesA[hull->m_vertexOffset+index];\n"
+ " }\n"
+ " return supVec;\n"
+ "}\n"
+ "B3_STATIC void b3MprConvexSupport(int pairIndex,int bodyIndex, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf, \n"
+ " b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData, \n"
+ " b3ConstArray(b3Collidable_t) cpuCollidables,\n"
+ " b3ConstArray(b3Float4) cpuVertices,\n"
+ " __global b3Float4* sepAxis,\n"
+ " const b3Float4* _dir, b3Float4* outp, int logme)\n"
+ "{\n"
+ " //dir is in worldspace, move to local space\n"
+ " \n"
+ " b3Float4 pos = cpuBodyBuf[bodyIndex].m_pos;\n"
+ " b3Quat orn = cpuBodyBuf[bodyIndex].m_quat;\n"
+ " \n"
+ " b3Float4 dir = b3MakeFloat4((*_dir).x,(*_dir).y,(*_dir).z,0.f);\n"
+ " \n"
+ " const b3Float4 localDir = b3QuatRotate(b3QuatInverse(orn),dir);\n"
+ " \n"
+ " //find local support vertex\n"
+ " int colIndex = cpuBodyBuf[bodyIndex].m_collidableIdx;\n"
+ " \n"
+ " b3Assert(cpuCollidables[colIndex].m_shapeType==SHAPE_CONVEX_HULL);\n"
+ " __global const b3ConvexPolyhedronData_t* hull = &cpuConvexData[cpuCollidables[colIndex].m_shapeIndex];\n"
+ " \n"
+ " b3Float4 pInA;\n"
+ " if (logme)\n"
+ " {\n"
+ " b3Float4 supVec = b3MakeFloat4(0,0,0,0);\n"
+ " float maxDot = -B3_LARGE_FLOAT;\n"
+ " if( 0 < hull->m_numVertices )\n"
+ " {\n"
+ " const b3Float4 scaled = localDir;\n"
+ " int index = b3MaxDot(scaled, &cpuVertices[hull->m_vertexOffset], hull->m_numVertices, &maxDot);\n"
+ " pInA = cpuVertices[hull->m_vertexOffset+index];\n"
+ " \n"
+ " }\n"
+ " } else\n"
+ " {\n"
+ " pInA = b3LocalGetSupportVertex(localDir,hull,cpuVertices);\n"
+ " }\n"
+ " //move vertex to world space\n"
+ " *outp = b3TransformPoint(pInA,pos,orn);\n"
+ " \n"
+ "}\n"
+ "inline void b3MprSupport(int pairIndex,int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf, \n"
+ " b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData, \n"
+ " b3ConstArray(b3Collidable_t) cpuCollidables,\n"
+ " b3ConstArray(b3Float4) cpuVertices,\n"
+ " __global b3Float4* sepAxis,\n"
+ " const b3Float4* _dir, b3MprSupport_t *supp)\n"
+ "{\n"
+ " b3Float4 dir;\n"
+ " dir = *_dir;\n"
+ " b3MprConvexSupport(pairIndex,bodyIndexA,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices,sepAxis,&dir, &supp->v1,0);\n"
+ " dir = *_dir*-1.f;\n"
+ " b3MprConvexSupport(pairIndex,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices,sepAxis,&dir, &supp->v2,0);\n"
+ " supp->v = supp->v1 - supp->v2;\n"
+ "}\n"
+ "inline void b3FindOrigin(int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf, b3MprSupport_t *center)\n"
+ "{\n"
+ " center->v1 = cpuBodyBuf[bodyIndexA].m_pos;\n"
+ " center->v2 = cpuBodyBuf[bodyIndexB].m_pos;\n"
+ " center->v = center->v1 - center->v2;\n"
+ "}\n"
+ "inline void b3MprVec3Set(b3Float4 *v, float x, float y, float z)\n"
+ "{\n"
+ " (*v).x = x;\n"
+ " (*v).y = y;\n"
+ " (*v).z = z;\n"
+ " (*v).w = 0.f;\n"
+ "}\n"
+ "inline void b3MprVec3Add(b3Float4 *v, const b3Float4 *w)\n"
+ "{\n"
+ " (*v).x += (*w).x;\n"
+ " (*v).y += (*w).y;\n"
+ " (*v).z += (*w).z;\n"
+ "}\n"
+ "inline void b3MprVec3Copy(b3Float4 *v, const b3Float4 *w)\n"
+ "{\n"
+ " *v = *w;\n"
+ "}\n"
+ "inline void b3MprVec3Scale(b3Float4 *d, float k)\n"
+ "{\n"
+ " *d *= k;\n"
+ "}\n"
+ "inline float b3MprVec3Dot(const b3Float4 *a, const b3Float4 *b)\n"
+ "{\n"
+ " float dot;\n"
+ " dot = b3Dot3F4(*a,*b);\n"
+ " return dot;\n"
+ "}\n"
+ "inline float b3MprVec3Len2(const b3Float4 *v)\n"
+ "{\n"
+ " return b3MprVec3Dot(v, v);\n"
+ "}\n"
+ "inline void b3MprVec3Normalize(b3Float4 *d)\n"
+ "{\n"
+ " float k = 1.f / B3_MPR_SQRT(b3MprVec3Len2(d));\n"
+ " b3MprVec3Scale(d, k);\n"
+ "}\n"
+ "inline void b3MprVec3Cross(b3Float4 *d, const b3Float4 *a, const b3Float4 *b)\n"
+ "{\n"
+ " *d = b3Cross3(*a,*b);\n"
+ " \n"
+ "}\n"
+ "inline void b3MprVec3Sub2(b3Float4 *d, const b3Float4 *v, const b3Float4 *w)\n"
+ "{\n"
+ " *d = *v - *w;\n"
+ "}\n"
+ "inline void b3PortalDir(const b3MprSimplex_t *portal, b3Float4 *dir)\n"
+ "{\n"
+ " b3Float4 v2v1, v3v1;\n"
+ " b3MprVec3Sub2(&v2v1, &b3MprSimplexPoint(portal, 2)->v,\n"
+ " &b3MprSimplexPoint(portal, 1)->v);\n"
+ " b3MprVec3Sub2(&v3v1, &b3MprSimplexPoint(portal, 3)->v,\n"
+ " &b3MprSimplexPoint(portal, 1)->v);\n"
+ " b3MprVec3Cross(dir, &v2v1, &v3v1);\n"
+ " b3MprVec3Normalize(dir);\n"
+ "}\n"
+ "inline int portalEncapsulesOrigin(const b3MprSimplex_t *portal,\n"
+ " const b3Float4 *dir)\n"
+ "{\n"
+ " float dot;\n"
+ " dot = b3MprVec3Dot(dir, &b3MprSimplexPoint(portal, 1)->v);\n"
+ " return b3MprIsZero(dot) || dot > 0.f;\n"
+ "}\n"
+ "inline int portalReachTolerance(const b3MprSimplex_t *portal,\n"
+ " const b3MprSupport_t *v4,\n"
+ " const b3Float4 *dir)\n"
+ "{\n"
+ " float dv1, dv2, dv3, dv4;\n"
+ " float dot1, dot2, dot3;\n"
+ " // find the smallest dot product of dir and {v1-v4, v2-v4, v3-v4}\n"
+ " dv1 = b3MprVec3Dot(&b3MprSimplexPoint(portal, 1)->v, dir);\n"
+ " dv2 = b3MprVec3Dot(&b3MprSimplexPoint(portal, 2)->v, dir);\n"
+ " dv3 = b3MprVec3Dot(&b3MprSimplexPoint(portal, 3)->v, dir);\n"
+ " dv4 = b3MprVec3Dot(&v4->v, dir);\n"
+ " dot1 = dv4 - dv1;\n"
+ " dot2 = dv4 - dv2;\n"
+ " dot3 = dv4 - dv3;\n"
+ " dot1 = B3_MPR_FMIN(dot1, dot2);\n"
+ " dot1 = B3_MPR_FMIN(dot1, dot3);\n"
+ " return b3MprEq(dot1, B3_MPR_TOLERANCE) || dot1 < B3_MPR_TOLERANCE;\n"
+ "}\n"
+ "inline int portalCanEncapsuleOrigin(const b3MprSimplex_t *portal, \n"
+ " const b3MprSupport_t *v4,\n"
+ " const b3Float4 *dir)\n"
+ "{\n"
+ " float dot;\n"
+ " dot = b3MprVec3Dot(&v4->v, dir);\n"
+ " return b3MprIsZero(dot) || dot > 0.f;\n"
+ "}\n"
+ "inline void b3ExpandPortal(b3MprSimplex_t *portal,\n"
+ " const b3MprSupport_t *v4)\n"
+ "{\n"
+ " float dot;\n"
+ " b3Float4 v4v0;\n"
+ " b3MprVec3Cross(&v4v0, &v4->v, &b3MprSimplexPoint(portal, 0)->v);\n"
+ " dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 1)->v, &v4v0);\n"
+ " if (dot > 0.f){\n"
+ " dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 2)->v, &v4v0);\n"
+ " if (dot > 0.f){\n"
+ " b3MprSimplexSet(portal, 1, v4);\n"
+ " }else{\n"
+ " b3MprSimplexSet(portal, 3, v4);\n"
+ " }\n"
+ " }else{\n"
+ " dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 3)->v, &v4v0);\n"
+ " if (dot > 0.f){\n"
+ " b3MprSimplexSet(portal, 2, v4);\n"
+ " }else{\n"
+ " b3MprSimplexSet(portal, 1, v4);\n"
+ " }\n"
+ " }\n"
+ "}\n"
+ "B3_STATIC int b3DiscoverPortal(int pairIndex, int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf, \n"
+ " b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData, \n"
+ " b3ConstArray(b3Collidable_t) cpuCollidables,\n"
+ " b3ConstArray(b3Float4) cpuVertices,\n"
+ " __global b3Float4* sepAxis,\n"
+ " __global int* hasSepAxis,\n"
+ " b3MprSimplex_t *portal)\n"
+ "{\n"
+ " b3Float4 dir, va, vb;\n"
+ " float dot;\n"
+ " int cont;\n"
+ " \n"
+ " \n"
+ " // vertex 0 is center of portal\n"
+ " b3FindOrigin(bodyIndexA,bodyIndexB,cpuBodyBuf, b3MprSimplexPointW(portal, 0));\n"
+ " // vertex 0 is center of portal\n"
+ " b3MprSimplexSetSize(portal, 1);\n"
+ " \n"
+ " b3Float4 zero = b3MakeFloat4(0,0,0,0);\n"
+ " b3Float4* b3mpr_vec3_origin = &zero;\n"
+ " if (b3MprVec3Eq(&b3MprSimplexPoint(portal, 0)->v, b3mpr_vec3_origin)){\n"
+ " // Portal's center lies on origin (0,0,0) => we know that objects\n"
+ " // intersect but we would need to know penetration info.\n"
+ " // So move center little bit...\n"
+ " b3MprVec3Set(&va, FLT_EPSILON * 10.f, 0.f, 0.f);\n"
+ " b3MprVec3Add(&b3MprSimplexPointW(portal, 0)->v, &va);\n"
+ " }\n"
+ " // vertex 1 = support in direction of origin\n"
+ " b3MprVec3Copy(&dir, &b3MprSimplexPoint(portal, 0)->v);\n"
+ " b3MprVec3Scale(&dir, -1.f);\n"
+ " b3MprVec3Normalize(&dir);\n"
+ " b3MprSupport(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&dir, b3MprSimplexPointW(portal, 1));\n"
+ " b3MprSimplexSetSize(portal, 2);\n"
+ " // test if origin isn't outside of v1\n"
+ " dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 1)->v, &dir);\n"
+ " \n"
+ " if (b3MprIsZero(dot) || dot < 0.f)\n"
+ " return -1;\n"
+ " // vertex 2\n"
+ " b3MprVec3Cross(&dir, &b3MprSimplexPoint(portal, 0)->v,\n"
+ " &b3MprSimplexPoint(portal, 1)->v);\n"
+ " if (b3MprIsZero(b3MprVec3Len2(&dir))){\n"
+ " if (b3MprVec3Eq(&b3MprSimplexPoint(portal, 1)->v, b3mpr_vec3_origin)){\n"
+ " // origin lies on v1\n"
+ " return 1;\n"
+ " }else{\n"
+ " // origin lies on v0-v1 segment\n"
+ " return 2;\n"
+ " }\n"
+ " }\n"
+ " b3MprVec3Normalize(&dir);\n"
+ " b3MprSupport(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&dir, b3MprSimplexPointW(portal, 2));\n"
+ " \n"
+ " dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 2)->v, &dir);\n"
+ " if (b3MprIsZero(dot) || dot < 0.f)\n"
+ " return -1;\n"
+ " b3MprSimplexSetSize(portal, 3);\n"
+ " // vertex 3 direction\n"
+ " b3MprVec3Sub2(&va, &b3MprSimplexPoint(portal, 1)->v,\n"
+ " &b3MprSimplexPoint(portal, 0)->v);\n"
+ " b3MprVec3Sub2(&vb, &b3MprSimplexPoint(portal, 2)->v,\n"
+ " &b3MprSimplexPoint(portal, 0)->v);\n"
+ " b3MprVec3Cross(&dir, &va, &vb);\n"
+ " b3MprVec3Normalize(&dir);\n"
+ " // it is better to form portal faces to be oriented \"outside\" origin\n"
+ " dot = b3MprVec3Dot(&dir, &b3MprSimplexPoint(portal, 0)->v);\n"
+ " if (dot > 0.f){\n"
+ " b3MprSimplexSwap(portal, 1, 2);\n"
+ " b3MprVec3Scale(&dir, -1.f);\n"
+ " }\n"
+ " while (b3MprSimplexSize(portal) < 4){\n"
+ " b3MprSupport(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&dir, b3MprSimplexPointW(portal, 3));\n"
+ " \n"
+ " dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 3)->v, &dir);\n"
+ " if (b3MprIsZero(dot) || dot < 0.f)\n"
+ " return -1;\n"
+ " cont = 0;\n"
+ " // test if origin is outside (v1, v0, v3) - set v2 as v3 and\n"
+ " // continue\n"
+ " b3MprVec3Cross(&va, &b3MprSimplexPoint(portal, 1)->v,\n"
+ " &b3MprSimplexPoint(portal, 3)->v);\n"
+ " dot = b3MprVec3Dot(&va, &b3MprSimplexPoint(portal, 0)->v);\n"
+ " if (dot < 0.f && !b3MprIsZero(dot)){\n"
+ " b3MprSimplexSet(portal, 2, b3MprSimplexPoint(portal, 3));\n"
+ " cont = 1;\n"
+ " }\n"
+ " if (!cont){\n"
+ " // test if origin is outside (v3, v0, v2) - set v1 as v3 and\n"
+ " // continue\n"
+ " b3MprVec3Cross(&va, &b3MprSimplexPoint(portal, 3)->v,\n"
+ " &b3MprSimplexPoint(portal, 2)->v);\n"
+ " dot = b3MprVec3Dot(&va, &b3MprSimplexPoint(portal, 0)->v);\n"
+ " if (dot < 0.f && !b3MprIsZero(dot)){\n"
+ " b3MprSimplexSet(portal, 1, b3MprSimplexPoint(portal, 3));\n"
+ " cont = 1;\n"
+ " }\n"
+ " }\n"
+ " if (cont){\n"
+ " b3MprVec3Sub2(&va, &b3MprSimplexPoint(portal, 1)->v,\n"
+ " &b3MprSimplexPoint(portal, 0)->v);\n"
+ " b3MprVec3Sub2(&vb, &b3MprSimplexPoint(portal, 2)->v,\n"
+ " &b3MprSimplexPoint(portal, 0)->v);\n"
+ " b3MprVec3Cross(&dir, &va, &vb);\n"
+ " b3MprVec3Normalize(&dir);\n"
+ " }else{\n"
+ " b3MprSimplexSetSize(portal, 4);\n"
+ " }\n"
+ " }\n"
+ " return 0;\n"
+ "}\n"
+ "B3_STATIC int b3RefinePortal(int pairIndex,int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf, \n"
+ " b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData, \n"
+ " b3ConstArray(b3Collidable_t) cpuCollidables,\n"
+ " b3ConstArray(b3Float4) cpuVertices,\n"
+ " __global b3Float4* sepAxis,\n"
+ " b3MprSimplex_t *portal)\n"
+ "{\n"
+ " b3Float4 dir;\n"
+ " b3MprSupport_t v4;\n"
+ " for (int i=0;i<B3_MPR_MAX_ITERATIONS;i++)\n"
+ " //while (1)\n"
+ " {\n"
+ " // compute direction outside the portal (from v0 throught v1,v2,v3\n"
+ " // face)\n"
+ " b3PortalDir(portal, &dir);\n"
+ " // test if origin is inside the portal\n"
+ " if (portalEncapsulesOrigin(portal, &dir))\n"
+ " return 0;\n"
+ " // get next support point\n"
+ " \n"
+ " b3MprSupport(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&dir, &v4);\n"
+ " // test if v4 can expand portal to contain origin and if portal\n"
+ " // expanding doesn't reach given tolerance\n"
+ " if (!portalCanEncapsuleOrigin(portal, &v4, &dir)\n"
+ " || portalReachTolerance(portal, &v4, &dir))\n"
+ " {\n"
+ " return -1;\n"
+ " }\n"
+ " // v1-v2-v3 triangle must be rearranged to face outside Minkowski\n"
+ " // difference (direction from v0).\n"
+ " b3ExpandPortal(portal, &v4);\n"
+ " }\n"
+ " return -1;\n"
+ "}\n"
+ "B3_STATIC void b3FindPos(const b3MprSimplex_t *portal, b3Float4 *pos)\n"
+ "{\n"
+ " b3Float4 zero = b3MakeFloat4(0,0,0,0);\n"
+ " b3Float4* b3mpr_vec3_origin = &zero;\n"
+ " b3Float4 dir;\n"
+ " size_t i;\n"
+ " float b[4], sum, inv;\n"
+ " b3Float4 vec, p1, p2;\n"
+ " b3PortalDir(portal, &dir);\n"
+ " // use barycentric coordinates of tetrahedron to find origin\n"
+ " b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 1)->v,\n"
+ " &b3MprSimplexPoint(portal, 2)->v);\n"
+ " b[0] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 3)->v);\n"
+ " b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 3)->v,\n"
+ " &b3MprSimplexPoint(portal, 2)->v);\n"
+ " b[1] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 0)->v);\n"
+ " b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 0)->v,\n"
+ " &b3MprSimplexPoint(portal, 1)->v);\n"
+ " b[2] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 3)->v);\n"
+ " b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 2)->v,\n"
+ " &b3MprSimplexPoint(portal, 1)->v);\n"
+ " b[3] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 0)->v);\n"
+ " sum = b[0] + b[1] + b[2] + b[3];\n"
+ " if (b3MprIsZero(sum) || sum < 0.f){\n"
+ " b[0] = 0.f;\n"
+ " b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 2)->v,\n"
+ " &b3MprSimplexPoint(portal, 3)->v);\n"
+ " b[1] = b3MprVec3Dot(&vec, &dir);\n"
+ " b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 3)->v,\n"
+ " &b3MprSimplexPoint(portal, 1)->v);\n"
+ " b[2] = b3MprVec3Dot(&vec, &dir);\n"
+ " b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 1)->v,\n"
+ " &b3MprSimplexPoint(portal, 2)->v);\n"
+ " b[3] = b3MprVec3Dot(&vec, &dir);\n"
+ " sum = b[1] + b[2] + b[3];\n"
+ " }\n"
+ " inv = 1.f / sum;\n"
+ " b3MprVec3Copy(&p1, b3mpr_vec3_origin);\n"
+ " b3MprVec3Copy(&p2, b3mpr_vec3_origin);\n"
+ " for (i = 0; i < 4; i++){\n"
+ " b3MprVec3Copy(&vec, &b3MprSimplexPoint(portal, i)->v1);\n"
+ " b3MprVec3Scale(&vec, b[i]);\n"
+ " b3MprVec3Add(&p1, &vec);\n"
+ " b3MprVec3Copy(&vec, &b3MprSimplexPoint(portal, i)->v2);\n"
+ " b3MprVec3Scale(&vec, b[i]);\n"
+ " b3MprVec3Add(&p2, &vec);\n"
+ " }\n"
+ " b3MprVec3Scale(&p1, inv);\n"
+ " b3MprVec3Scale(&p2, inv);\n"
+ " b3MprVec3Copy(pos, &p1);\n"
+ " b3MprVec3Add(pos, &p2);\n"
+ " b3MprVec3Scale(pos, 0.5);\n"
+ "}\n"
+ "inline float b3MprVec3Dist2(const b3Float4 *a, const b3Float4 *b)\n"
+ "{\n"
+ " b3Float4 ab;\n"
+ " b3MprVec3Sub2(&ab, a, b);\n"
+ " return b3MprVec3Len2(&ab);\n"
+ "}\n"
+ "inline float _b3MprVec3PointSegmentDist2(const b3Float4 *P,\n"
+ " const b3Float4 *x0,\n"
+ " const b3Float4 *b,\n"
+ " b3Float4 *witness)\n"
+ "{\n"
+ " // The computation comes from solving equation of segment:\n"
+ " // S(t) = x0 + t.d\n"
+ " // where - x0 is initial point of segment\n"
+ " // - d is direction of segment from x0 (|d| > 0)\n"
+ " // - t belongs to <0, 1> interval\n"
+ " // \n"
+ " // Than, distance from a segment to some point P can be expressed:\n"
+ " // D(t) = |x0 + t.d - P|^2\n"
+ " // which is distance from any point on segment. Minimization\n"
+ " // of this function brings distance from P to segment.\n"
+ " // Minimization of D(t) leads to simple quadratic equation that's\n"
+ " // solving is straightforward.\n"
+ " //\n"
+ " // Bonus of this method is witness point for free.\n"
+ " float dist, t;\n"
+ " b3Float4 d, a;\n"
+ " // direction of segment\n"
+ " b3MprVec3Sub2(&d, b, x0);\n"
+ " // precompute vector from P to x0\n"
+ " b3MprVec3Sub2(&a, x0, P);\n"
+ " t = -1.f * b3MprVec3Dot(&a, &d);\n"
+ " t /= b3MprVec3Len2(&d);\n"
+ " if (t < 0.f || b3MprIsZero(t)){\n"
+ " dist = b3MprVec3Dist2(x0, P);\n"
+ " if (witness)\n"
+ " b3MprVec3Copy(witness, x0);\n"
+ " }else if (t > 1.f || b3MprEq(t, 1.f)){\n"
+ " dist = b3MprVec3Dist2(b, P);\n"
+ " if (witness)\n"
+ " b3MprVec3Copy(witness, b);\n"
+ " }else{\n"
+ " if (witness){\n"
+ " b3MprVec3Copy(witness, &d);\n"
+ " b3MprVec3Scale(witness, t);\n"
+ " b3MprVec3Add(witness, x0);\n"
+ " dist = b3MprVec3Dist2(witness, P);\n"
+ " }else{\n"
+ " // recycling variables\n"
+ " b3MprVec3Scale(&d, t);\n"
+ " b3MprVec3Add(&d, &a);\n"
+ " dist = b3MprVec3Len2(&d);\n"
+ " }\n"
+ " }\n"
+ " return dist;\n"
+ "}\n"
+ "inline float b3MprVec3PointTriDist2(const b3Float4 *P,\n"
+ " const b3Float4 *x0, const b3Float4 *B,\n"
+ " const b3Float4 *C,\n"
+ " b3Float4 *witness)\n"
+ "{\n"
+ " // Computation comes from analytic expression for triangle (x0, B, C)\n"
+ " // T(s, t) = x0 + s.d1 + t.d2, where d1 = B - x0 and d2 = C - x0 and\n"
+ " // Then equation for distance is:\n"
+ " // D(s, t) = | T(s, t) - P |^2\n"
+ " // This leads to minimization of quadratic function of two variables.\n"
+ " // The solution from is taken only if s is between 0 and 1, t is\n"
+ " // between 0 and 1 and t + s < 1, otherwise distance from segment is\n"
+ " // computed.\n"
+ " b3Float4 d1, d2, a;\n"
+ " float u, v, w, p, q, r;\n"
+ " float s, t, dist, dist2;\n"
+ " b3Float4 witness2;\n"
+ " b3MprVec3Sub2(&d1, B, x0);\n"
+ " b3MprVec3Sub2(&d2, C, x0);\n"
+ " b3MprVec3Sub2(&a, x0, P);\n"
+ " u = b3MprVec3Dot(&a, &a);\n"
+ " v = b3MprVec3Dot(&d1, &d1);\n"
+ " w = b3MprVec3Dot(&d2, &d2);\n"
+ " p = b3MprVec3Dot(&a, &d1);\n"
+ " q = b3MprVec3Dot(&a, &d2);\n"
+ " r = b3MprVec3Dot(&d1, &d2);\n"
+ " s = (q * r - w * p) / (w * v - r * r);\n"
+ " t = (-s * r - q) / w;\n"
+ " if ((b3MprIsZero(s) || s > 0.f)\n"
+ " && (b3MprEq(s, 1.f) || s < 1.f)\n"
+ " && (b3MprIsZero(t) || t > 0.f)\n"
+ " && (b3MprEq(t, 1.f) || t < 1.f)\n"
+ " && (b3MprEq(t + s, 1.f) || t + s < 1.f)){\n"
+ " if (witness){\n"
+ " b3MprVec3Scale(&d1, s);\n"
+ " b3MprVec3Scale(&d2, t);\n"
+ " b3MprVec3Copy(witness, x0);\n"
+ " b3MprVec3Add(witness, &d1);\n"
+ " b3MprVec3Add(witness, &d2);\n"
+ " dist = b3MprVec3Dist2(witness, P);\n"
+ " }else{\n"
+ " dist = s * s * v;\n"
+ " dist += t * t * w;\n"
+ " dist += 2.f * s * t * r;\n"
+ " dist += 2.f * s * p;\n"
+ " dist += 2.f * t * q;\n"
+ " dist += u;\n"
+ " }\n"
+ " }else{\n"
+ " dist = _b3MprVec3PointSegmentDist2(P, x0, B, witness);\n"
+ " dist2 = _b3MprVec3PointSegmentDist2(P, x0, C, &witness2);\n"
+ " if (dist2 < dist){\n"
+ " dist = dist2;\n"
+ " if (witness)\n"
+ " b3MprVec3Copy(witness, &witness2);\n"
+ " }\n"
+ " dist2 = _b3MprVec3PointSegmentDist2(P, B, C, &witness2);\n"
+ " if (dist2 < dist){\n"
+ " dist = dist2;\n"
+ " if (witness)\n"
+ " b3MprVec3Copy(witness, &witness2);\n"
+ " }\n"
+ " }\n"
+ " return dist;\n"
+ "}\n"
+ "B3_STATIC void b3FindPenetr(int pairIndex,int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf, \n"
+ " b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData, \n"
+ " b3ConstArray(b3Collidable_t) cpuCollidables,\n"
+ " b3ConstArray(b3Float4) cpuVertices,\n"
+ " __global b3Float4* sepAxis,\n"
+ " b3MprSimplex_t *portal,\n"
+ " float *depth, b3Float4 *pdir, b3Float4 *pos)\n"
+ "{\n"
+ " b3Float4 dir;\n"
+ " b3MprSupport_t v4;\n"
+ " unsigned long iterations;\n"
+ " b3Float4 zero = b3MakeFloat4(0,0,0,0);\n"
+ " b3Float4* b3mpr_vec3_origin = &zero;\n"
+ " iterations = 1UL;\n"
+ " for (int i=0;i<B3_MPR_MAX_ITERATIONS;i++)\n"
+ " //while (1)\n"
+ " {\n"
+ " // compute portal direction and obtain next support point\n"
+ " b3PortalDir(portal, &dir);\n"
+ " \n"
+ " b3MprSupport(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&dir, &v4);\n"
+ " // reached tolerance -> find penetration info\n"
+ " if (portalReachTolerance(portal, &v4, &dir)\n"
+ " || iterations ==B3_MPR_MAX_ITERATIONS)\n"
+ " {\n"
+ " *depth = b3MprVec3PointTriDist2(b3mpr_vec3_origin,&b3MprSimplexPoint(portal, 1)->v,&b3MprSimplexPoint(portal, 2)->v,&b3MprSimplexPoint(portal, 3)->v,pdir);\n"
+ " *depth = B3_MPR_SQRT(*depth);\n"
+ " \n"
+ " if (b3MprIsZero((*pdir).x) && b3MprIsZero((*pdir).y) && b3MprIsZero((*pdir).z))\n"
+ " {\n"
+ " \n"
+ " *pdir = dir;\n"
+ " } \n"
+ " b3MprVec3Normalize(pdir);\n"
+ " \n"
+ " // barycentric coordinates:\n"
+ " b3FindPos(portal, pos);\n"
+ " return;\n"
+ " }\n"
+ " b3ExpandPortal(portal, &v4);\n"
+ " iterations++;\n"
+ " }\n"
+ "}\n"
+ "B3_STATIC void b3FindPenetrTouch(b3MprSimplex_t *portal,float *depth, b3Float4 *dir, b3Float4 *pos)\n"
+ "{\n"
+ " // Touching contact on portal's v1 - so depth is zero and direction\n"
+ " // is unimportant and pos can be guessed\n"
+ " *depth = 0.f;\n"
+ " b3Float4 zero = b3MakeFloat4(0,0,0,0);\n"
+ " b3Float4* b3mpr_vec3_origin = &zero;\n"
+ " b3MprVec3Copy(dir, b3mpr_vec3_origin);\n"
+ " b3MprVec3Copy(pos, &b3MprSimplexPoint(portal, 1)->v1);\n"
+ " b3MprVec3Add(pos, &b3MprSimplexPoint(portal, 1)->v2);\n"
+ " b3MprVec3Scale(pos, 0.5);\n"
+ "}\n"
+ "B3_STATIC void b3FindPenetrSegment(b3MprSimplex_t *portal,\n"
+ " float *depth, b3Float4 *dir, b3Float4 *pos)\n"
+ "{\n"
+ " \n"
+ " // Origin lies on v0-v1 segment.\n"
+ " // Depth is distance to v1, direction also and position must be\n"
+ " // computed\n"
+ " b3MprVec3Copy(pos, &b3MprSimplexPoint(portal, 1)->v1);\n"
+ " b3MprVec3Add(pos, &b3MprSimplexPoint(portal, 1)->v2);\n"
+ " b3MprVec3Scale(pos, 0.5f);\n"
+ " \n"
+ " b3MprVec3Copy(dir, &b3MprSimplexPoint(portal, 1)->v);\n"
+ " *depth = B3_MPR_SQRT(b3MprVec3Len2(dir));\n"
+ " b3MprVec3Normalize(dir);\n"
+ "}\n"
+ "inline int b3MprPenetration(int pairIndex, int bodyIndexA, int bodyIndexB,\n"
+ " b3ConstArray(b3RigidBodyData_t) cpuBodyBuf,\n"
+ " b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData, \n"
+ " b3ConstArray(b3Collidable_t) cpuCollidables,\n"
+ " b3ConstArray(b3Float4) cpuVertices,\n"
+ " __global b3Float4* sepAxis,\n"
+ " __global int* hasSepAxis,\n"
+ " float *depthOut, b3Float4* dirOut, b3Float4* posOut)\n"
+ "{\n"
+ " \n"
+ " b3MprSimplex_t portal;\n"
+ " \n"
+ "// if (!hasSepAxis[pairIndex])\n"
+ " // return -1;\n"
+ " \n"
+ " hasSepAxis[pairIndex] = 0;\n"
+ " int res;\n"
+ " // Phase 1: Portal discovery\n"
+ " res = b3DiscoverPortal(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices,sepAxis,hasSepAxis, &portal);\n"
+ " \n"
+ " \n"
+ " //sepAxis[pairIndex] = *pdir;//or -dir?\n"
+ " switch (res)\n"
+ " {\n"
+ " case 0:\n"
+ " {\n"
+ " // Phase 2: Portal refinement\n"
+ " \n"
+ " res = b3RefinePortal(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&portal);\n"
+ " if (res < 0)\n"
+ " return -1;\n"
+ " // Phase 3. Penetration info\n"
+ " b3FindPenetr(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&portal, depthOut, dirOut, posOut);\n"
+ " hasSepAxis[pairIndex] = 1;\n"
+ " sepAxis[pairIndex] = -*dirOut;\n"
+ " break;\n"
+ " }\n"
+ " case 1:\n"
+ " {\n"
+ " // Touching contact on portal's v1.\n"
+ " b3FindPenetrTouch(&portal, depthOut, dirOut, posOut);\n"
+ " break;\n"
+ " }\n"
+ " case 2:\n"
+ " {\n"
+ " \n"
+ " b3FindPenetrSegment( &portal, depthOut, dirOut, posOut);\n"
+ " break;\n"
+ " }\n"
+ " default:\n"
+ " {\n"
+ " hasSepAxis[pairIndex]=0;\n"
+ " //if (res < 0)\n"
+ " //{\n"
+ " // Origin isn't inside portal - no collision.\n"
+ " return -1;\n"
+ " //}\n"
+ " }\n"
+ " };\n"
+ " \n"
+ " return 0;\n"
+ "};\n"
+ "#endif //B3_MPR_PENETRATION_H\n"
+ "#ifndef B3_CONTACT4DATA_H\n"
+ "#define B3_CONTACT4DATA_H\n"
+ "#ifndef B3_FLOAT4_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#endif \n"
+ "#endif //B3_FLOAT4_H\n"
+ "typedef struct b3Contact4Data b3Contact4Data_t;\n"
+ "struct b3Contact4Data\n"
+ "{\n"
+ " b3Float4 m_worldPosB[4];\n"
+ "// b3Float4 m_localPosA[4];\n"
+ "// b3Float4 m_localPosB[4];\n"
+ " b3Float4 m_worldNormalOnB; // w: m_nPoints\n"
+ " unsigned short m_restituitionCoeffCmp;\n"
+ " unsigned short m_frictionCoeffCmp;\n"
+ " int m_batchIdx;\n"
+ " int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
+ " int m_bodyBPtrAndSignBit;\n"
+ " int m_childIndexA;\n"
+ " int m_childIndexB;\n"
+ " int m_unused1;\n"
+ " int m_unused2;\n"
+ "};\n"
+ "inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
+ "{\n"
+ " return (int)contact->m_worldNormalOnB.w;\n"
+ "};\n"
+ "inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
+ "{\n"
+ " contact->m_worldNormalOnB.w = (float)numPoints;\n"
+ "};\n"
+ "#endif //B3_CONTACT4DATA_H\n"
+ "#define AppendInc(x, out) out = atomic_inc(x)\n"
+ "#define GET_NPOINTS(x) (x).m_worldNormalOnB.w\n"
+ "#ifdef cl_ext_atomic_counters_32\n"
+ " #pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
+ "#else\n"
+ " #define counter32_t volatile __global int*\n"
+ "#endif\n"
+ "__kernel void mprPenetrationKernel( __global int4* pairs,\n"
+ " __global const b3RigidBodyData_t* rigidBodies, \n"
+ " __global const b3Collidable_t* collidables,\n"
+ " __global const b3ConvexPolyhedronData_t* convexShapes, \n"
+ " __global const float4* vertices,\n"
+ " __global float4* separatingNormals,\n"
+ " __global int* hasSeparatingAxis,\n"
+ " __global struct b3Contact4Data* restrict globalContactsOut,\n"
+ " counter32_t nGlobalContactsOut,\n"
+ " int contactCapacity,\n"
+ " int numPairs)\n"
+ "{\n"
+ " int i = get_global_id(0);\n"
+ " int pairIndex = i;\n"
+ " if (i<numPairs)\n"
+ " {\n"
+ " int bodyIndexA = pairs[i].x;\n"
+ " int bodyIndexB = pairs[i].y;\n"
+ " int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+ " int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+ " \n"
+ " int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+ " int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+ " \n"
+ " \n"
+ " //once the broadphase avoids static-static pairs, we can remove this test\n"
+ " if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))\n"
+ " {\n"
+ " return;\n"
+ " }\n"
+ " \n"
+ " if ((collidables[collidableIndexA].m_shapeType!=SHAPE_CONVEX_HULL) ||(collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL))\n"
+ " {\n"
+ " return;\n"
+ " }\n"
+ " float depthOut;\n"
+ " b3Float4 dirOut;\n"
+ " b3Float4 posOut;\n"
+ " int res = b3MprPenetration(pairIndex, bodyIndexA, bodyIndexB,rigidBodies,convexShapes,collidables,vertices,separatingNormals,hasSeparatingAxis,&depthOut, &dirOut, &posOut);\n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " if (res==0)\n"
+ " {\n"
+ " //add a contact\n"
+ " int dstIdx;\n"
+ " AppendInc( nGlobalContactsOut, dstIdx );\n"
+ " if (dstIdx<contactCapacity)\n"
+ " {\n"
+ " pairs[pairIndex].z = dstIdx;\n"
+ " __global struct b3Contact4Data* c = globalContactsOut + dstIdx;\n"
+ " c->m_worldNormalOnB = -dirOut;//normal;\n"
+ " c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
+ " c->m_batchIdx = pairIndex;\n"
+ " int bodyA = pairs[pairIndex].x;\n"
+ " int bodyB = pairs[pairIndex].y;\n"
+ " c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0 ? -bodyA:bodyA;\n"
+ " c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0 ? -bodyB:bodyB;\n"
+ " c->m_childIndexA = -1;\n"
+ " c->m_childIndexB = -1;\n"
+ " //for (int i=0;i<nContacts;i++)\n"
+ " posOut.w = -depthOut;\n"
+ " c->m_worldPosB[0] = posOut;//localPoints[contactIdx[i]];\n"
+ " GET_NPOINTS(*c) = 1;//nContacts;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ "}\n"
+ "typedef float4 Quaternion;\n"
+ "#define make_float4 (float4)\n"
+ "__inline\n"
+ "float dot3F4(float4 a, float4 b)\n"
+ "{\n"
+ " float4 a1 = make_float4(a.xyz,0.f);\n"
+ " float4 b1 = make_float4(b.xyz,0.f);\n"
+ " return dot(a1, b1);\n"
+ "}\n"
+ "__inline\n"
+ "float4 cross3(float4 a, float4 b)\n"
+ "{\n"
+ " return cross(a,b);\n"
+ "}\n"
+ "__inline\n"
+ "Quaternion qtMul(Quaternion a, Quaternion b)\n"
+ "{\n"
+ " Quaternion ans;\n"
+ " ans = cross3( a, b );\n"
+ " ans += a.w*b+b.w*a;\n"
+ "// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+ " ans.w = a.w*b.w - dot3F4(a, b);\n"
+ " return ans;\n"
+ "}\n"
+ "__inline\n"
+ "Quaternion qtInvert(Quaternion q)\n"
+ "{\n"
+ " return (Quaternion)(-q.xyz, q.w);\n"
+ "}\n"
+ "__inline\n"
+ "float4 qtRotate(Quaternion q, float4 vec)\n"
+ "{\n"
+ " Quaternion qInv = qtInvert( q );\n"
+ " float4 vcpy = vec;\n"
+ " vcpy.w = 0.f;\n"
+ " float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
+ " return out;\n"
+ "}\n"
+ "__inline\n"
+ "float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)\n"
+ "{\n"
+ " return qtRotate( *orientation, *p ) + (*translation);\n"
+ "}\n"
+ "__inline\n"
+ "float4 qtInvRotate(const Quaternion q, float4 vec)\n"
+ "{\n"
+ " return qtRotate( qtInvert( q ), vec );\n"
+ "}\n"
+ "inline void project(__global const b3ConvexPolyhedronData_t* hull, const float4 pos, const float4 orn, \n"
+ "const float4* dir, __global const float4* vertices, float* min, float* max)\n"
+ "{\n"
+ " min[0] = FLT_MAX;\n"
+ " max[0] = -FLT_MAX;\n"
+ " int numVerts = hull->m_numVertices;\n"
+ " const float4 localDir = qtInvRotate(orn,*dir);\n"
+ " float offset = dot(pos,*dir);\n"
+ " for(int i=0;i<numVerts;i++)\n"
+ " {\n"
+ " float dp = dot(vertices[hull->m_vertexOffset+i],localDir);\n"
+ " if(dp < min[0]) \n"
+ " min[0] = dp;\n"
+ " if(dp > max[0]) \n"
+ " max[0] = dp;\n"
+ " }\n"
+ " if(min[0]>max[0])\n"
+ " {\n"
+ " float tmp = min[0];\n"
+ " min[0] = max[0];\n"
+ " max[0] = tmp;\n"
+ " }\n"
+ " min[0] += offset;\n"
+ " max[0] += offset;\n"
+ "}\n"
+ "bool findSeparatingAxisUnitSphere( __global const b3ConvexPolyhedronData_t* hullA, __global const b3ConvexPolyhedronData_t* hullB, \n"
+ " const float4 posA1,\n"
+ " const float4 ornA,\n"
+ " const float4 posB1,\n"
+ " const float4 ornB,\n"
+ " const float4 DeltaC2,\n"
+ " __global const float4* vertices,\n"
+ " __global const float4* unitSphereDirections,\n"
+ " int numUnitSphereDirections,\n"
+ " float4* sep,\n"
+ " float* dmin)\n"
+ "{\n"
+ " \n"
+ " float4 posA = posA1;\n"
+ " posA.w = 0.f;\n"
+ " float4 posB = posB1;\n"
+ " posB.w = 0.f;\n"
+ " int curPlaneTests=0;\n"
+ " int curEdgeEdge = 0;\n"
+ " // Test unit sphere directions\n"
+ " for (int i=0;i<numUnitSphereDirections;i++)\n"
+ " {\n"
+ " float4 crossje;\n"
+ " crossje = unitSphereDirections[i]; \n"
+ " if (dot3F4(DeltaC2,crossje)>0)\n"
+ " crossje *= -1.f;\n"
+ " {\n"
+ " float dist;\n"
+ " bool result = true;\n"
+ " float Min0,Max0;\n"
+ " float Min1,Max1;\n"
+ " project(hullA,posA,ornA,&crossje,vertices, &Min0, &Max0);\n"
+ " project(hullB,posB,ornB,&crossje,vertices, &Min1, &Max1);\n"
+ " \n"
+ " if(Max0<Min1 || Max1<Min0)\n"
+ " return false;\n"
+ " \n"
+ " float d0 = Max0 - Min1;\n"
+ " float d1 = Max1 - Min0;\n"
+ " dist = d0<d1 ? d0:d1;\n"
+ " result = true;\n"
+ " \n"
+ " if(dist<*dmin)\n"
+ " {\n"
+ " *dmin = dist;\n"
+ " *sep = crossje;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " \n"
+ " if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
+ " {\n"
+ " *sep = -(*sep);\n"
+ " }\n"
+ " return true;\n"
+ "}\n"
+ "__kernel void findSeparatingAxisUnitSphereKernel( __global const int4* pairs, \n"
+ " __global const b3RigidBodyData_t* rigidBodies, \n"
+ " __global const b3Collidable_t* collidables,\n"
+ " __global const b3ConvexPolyhedronData_t* convexShapes, \n"
+ " __global const float4* vertices,\n"
+ " __global const float4* unitSphereDirections,\n"
+ " __global float4* separatingNormals,\n"
+ " __global int* hasSeparatingAxis,\n"
+ " __global float* dmins,\n"
+ " int numUnitSphereDirections,\n"
+ " int numPairs\n"
+ " )\n"
+ "{\n"
+ " int i = get_global_id(0);\n"
+ " \n"
+ " if (i<numPairs)\n"
+ " {\n"
+ " if (hasSeparatingAxis[i])\n"
+ " {\n"
+ " \n"
+ " int bodyIndexA = pairs[i].x;\n"
+ " int bodyIndexB = pairs[i].y;\n"
+ " \n"
+ " int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+ " int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+ " \n"
+ " int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+ " int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+ " \n"
+ " \n"
+ " int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
+ " \n"
+ " float dmin = dmins[i];\n"
+ " \n"
+ " float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+ " posA.w = 0.f;\n"
+ " float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+ " posB.w = 0.f;\n"
+ " float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
+ " float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
+ " float4 c0 = transform(&c0local, &posA, &ornA);\n"
+ " float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
+ " float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
+ " float4 c1 = transform(&c1local,&posB,&ornB);\n"
+ " const float4 DeltaC2 = c0 - c1;\n"
+ " float4 sepNormal = separatingNormals[i];\n"
+ " \n"
+ " int numEdgeEdgeDirections = convexShapes[shapeIndexA].m_numUniqueEdges*convexShapes[shapeIndexB].m_numUniqueEdges;\n"
+ " if (numEdgeEdgeDirections>numUnitSphereDirections)\n"
+ " {\n"
+ " bool sepEE = findSeparatingAxisUnitSphere( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,\n"
+ " posB,ornB,\n"
+ " DeltaC2,\n"
+ " vertices,unitSphereDirections,numUnitSphereDirections,&sepNormal,&dmin);\n"
+ " if (!sepEE)\n"
+ " {\n"
+ " hasSeparatingAxis[i] = 0;\n"
+ " } else\n"
+ " {\n"
+ " hasSeparatingAxis[i] = 1;\n"
+ " separatingNormals[i] = sepNormal;\n"
+ " }\n"
+ " }\n"
+ " } //if (hasSeparatingAxis[i])\n"
+ " }//(i<numPairs)\n"
+ "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/primitiveContacts.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/primitiveContacts.h
index b0103fe674..b2e0a2dd47 100644
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/primitiveContacts.h
+++ b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/primitiveContacts.h
@@ -1,1289 +1,1288 @@
//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* primitiveContactsKernelsCL= \
-"#ifndef B3_CONTACT4DATA_H\n"
-"#define B3_CONTACT4DATA_H\n"
-"#ifndef B3_FLOAT4_H\n"
-"#define B3_FLOAT4_H\n"
-"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
-"#define B3_PLATFORM_DEFINITIONS_H\n"
-"struct MyTest\n"
-"{\n"
-" int bla;\n"
-"};\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
-"#define B3_LARGE_FLOAT 1e18f\n"
-"#define B3_INFINITY 1e18f\n"
-"#define b3Assert(a)\n"
-"#define b3ConstArray(a) __global const a*\n"
-"#define b3AtomicInc atomic_inc\n"
-"#define b3AtomicAdd atomic_add\n"
-"#define b3Fabs fabs\n"
-"#define b3Sqrt native_sqrt\n"
-"#define b3Sin native_sin\n"
-"#define b3Cos native_cos\n"
-"#define B3_STATIC\n"
-"#endif\n"
-"#endif\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-" typedef float4 b3Float4;\n"
-" #define b3Float4ConstArg const b3Float4\n"
-" #define b3MakeFloat4 (float4)\n"
-" float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
-" {\n"
-" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
-" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
-" return dot(a1, b1);\n"
-" }\n"
-" b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
-" {\n"
-" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
-" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
-" return cross(a1, b1);\n"
-" }\n"
-" #define b3MinFloat4 min\n"
-" #define b3MaxFloat4 max\n"
-" #define b3Normalized(a) normalize(a)\n"
-"#endif \n"
-" \n"
-"inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
-"{\n"
-" if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
-" return false;\n"
-" return true;\n"
-"}\n"
-"inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
-"{\n"
-" float maxDot = -B3_INFINITY;\n"
-" int i = 0;\n"
-" int ptIndex = -1;\n"
-" for( i = 0; i < vecLen; i++ )\n"
-" {\n"
-" float dot = b3Dot3F4(vecArray[i],vec);\n"
-" \n"
-" if( dot > maxDot )\n"
-" {\n"
-" maxDot = dot;\n"
-" ptIndex = i;\n"
-" }\n"
-" }\n"
-" b3Assert(ptIndex>=0);\n"
-" if (ptIndex<0)\n"
-" {\n"
-" ptIndex = 0;\n"
-" }\n"
-" *dotOut = maxDot;\n"
-" return ptIndex;\n"
-"}\n"
-"#endif //B3_FLOAT4_H\n"
-"typedef struct b3Contact4Data b3Contact4Data_t;\n"
-"struct b3Contact4Data\n"
-"{\n"
-" b3Float4 m_worldPosB[4];\n"
-"// b3Float4 m_localPosA[4];\n"
-"// b3Float4 m_localPosB[4];\n"
-" b3Float4 m_worldNormalOnB; // w: m_nPoints\n"
-" unsigned short m_restituitionCoeffCmp;\n"
-" unsigned short m_frictionCoeffCmp;\n"
-" int m_batchIdx;\n"
-" int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
-" int m_bodyBPtrAndSignBit;\n"
-" int m_childIndexA;\n"
-" int m_childIndexB;\n"
-" int m_unused1;\n"
-" int m_unused2;\n"
-"};\n"
-"inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
-"{\n"
-" return (int)contact->m_worldNormalOnB.w;\n"
-"};\n"
-"inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
-"{\n"
-" contact->m_worldNormalOnB.w = (float)numPoints;\n"
-"};\n"
-"#endif //B3_CONTACT4DATA_H\n"
-"#define SHAPE_CONVEX_HULL 3\n"
-"#define SHAPE_PLANE 4\n"
-"#define SHAPE_CONCAVE_TRIMESH 5\n"
-"#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6\n"
-"#define SHAPE_SPHERE 7\n"
-"#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
-"#ifdef cl_ext_atomic_counters_32\n"
-"#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
-"#else\n"
-"#define counter32_t volatile __global int*\n"
-"#endif\n"
-"#define GET_GROUP_IDX get_group_id(0)\n"
-"#define GET_LOCAL_IDX get_local_id(0)\n"
-"#define GET_GLOBAL_IDX get_global_id(0)\n"
-"#define GET_GROUP_SIZE get_local_size(0)\n"
-"#define GET_NUM_GROUPS get_num_groups(0)\n"
-"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
-"#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
-"#define AtomInc(x) atom_inc(&(x))\n"
-"#define AtomInc1(x, out) out = atom_inc(&(x))\n"
-"#define AppendInc(x, out) out = atomic_inc(x)\n"
-"#define AtomAdd(x, value) atom_add(&(x), value)\n"
-"#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
-"#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
-"#define max2 max\n"
-"#define min2 min\n"
-"typedef unsigned int u32;\n"
-"typedef struct \n"
-"{\n"
-" union\n"
-" {\n"
-" float4 m_min;\n"
-" float m_minElems[4];\n"
-" int m_minIndices[4];\n"
-" };\n"
-" union\n"
-" {\n"
-" float4 m_max;\n"
-" float m_maxElems[4];\n"
-" int m_maxIndices[4];\n"
-" };\n"
-"} btAabbCL;\n"
-"///keep this in sync with btCollidable.h\n"
-"typedef struct\n"
-"{\n"
-" int m_numChildShapes;\n"
-" float m_radius;\n"
-" int m_shapeType;\n"
-" int m_shapeIndex;\n"
-" \n"
-"} btCollidableGpu;\n"
-"typedef struct\n"
-"{\n"
-" float4 m_childPosition;\n"
-" float4 m_childOrientation;\n"
-" int m_shapeIndex;\n"
-" int m_unused0;\n"
-" int m_unused1;\n"
-" int m_unused2;\n"
-"} btGpuChildShape;\n"
-"#define GET_NPOINTS(x) (x).m_worldNormalOnB.w\n"
-"typedef struct\n"
-"{\n"
-" float4 m_pos;\n"
-" float4 m_quat;\n"
-" float4 m_linVel;\n"
-" float4 m_angVel;\n"
-" u32 m_collidableIdx; \n"
-" float m_invMass;\n"
-" float m_restituitionCoeff;\n"
-" float m_frictionCoeff;\n"
-"} BodyData;\n"
-"typedef struct \n"
-"{\n"
-" float4 m_localCenter;\n"
-" float4 m_extents;\n"
-" float4 mC;\n"
-" float4 mE;\n"
-" \n"
-" float m_radius;\n"
-" int m_faceOffset;\n"
-" int m_numFaces;\n"
-" int m_numVertices;\n"
-" \n"
-" int m_vertexOffset;\n"
-" int m_uniqueEdgesOffset;\n"
-" int m_numUniqueEdges;\n"
-" int m_unused;\n"
-"} ConvexPolyhedronCL;\n"
-"typedef struct\n"
-"{\n"
-" float4 m_plane;\n"
-" int m_indexOffset;\n"
-" int m_numIndices;\n"
-"} btGpuFace;\n"
-"#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
-"#define make_float4 (float4)\n"
-"#define make_float2 (float2)\n"
-"#define make_uint4 (uint4)\n"
-"#define make_int4 (int4)\n"
-"#define make_uint2 (uint2)\n"
-"#define make_int2 (int2)\n"
-"__inline\n"
-"float fastDiv(float numerator, float denominator)\n"
-"{\n"
-" return native_divide(numerator, denominator); \n"
-"// return numerator/denominator; \n"
-"}\n"
-"__inline\n"
-"float4 fastDiv4(float4 numerator, float4 denominator)\n"
-"{\n"
-" return native_divide(numerator, denominator); \n"
-"}\n"
-"__inline\n"
-"float4 cross3(float4 a, float4 b)\n"
-"{\n"
-" return cross(a,b);\n"
-"}\n"
-"//#define dot3F4 dot\n"
-"__inline\n"
-"float dot3F4(float4 a, float4 b)\n"
-"{\n"
-" float4 a1 = make_float4(a.xyz,0.f);\n"
-" float4 b1 = make_float4(b.xyz,0.f);\n"
-" return dot(a1, b1);\n"
-"}\n"
-"__inline\n"
-"float4 fastNormalize4(float4 v)\n"
-"{\n"
-" return fast_normalize(v);\n"
-"}\n"
-"///////////////////////////////////////\n"
-"// Quaternion\n"
-"///////////////////////////////////////\n"
-"typedef float4 Quaternion;\n"
-"__inline\n"
-"Quaternion qtMul(Quaternion a, Quaternion b);\n"
-"__inline\n"
-"Quaternion qtNormalize(Quaternion in);\n"
-"__inline\n"
-"float4 qtRotate(Quaternion q, float4 vec);\n"
-"__inline\n"
-"Quaternion qtInvert(Quaternion q);\n"
-"__inline\n"
-"Quaternion qtMul(Quaternion a, Quaternion b)\n"
-"{\n"
-" Quaternion ans;\n"
-" ans = cross3( a, b );\n"
-" ans += a.w*b+b.w*a;\n"
-"// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
-" ans.w = a.w*b.w - dot3F4(a, b);\n"
-" return ans;\n"
-"}\n"
-"__inline\n"
-"Quaternion qtNormalize(Quaternion in)\n"
-"{\n"
-" return fastNormalize4(in);\n"
-"// in /= length( in );\n"
-"// return in;\n"
-"}\n"
-"__inline\n"
-"float4 qtRotate(Quaternion q, float4 vec)\n"
-"{\n"
-" Quaternion qInv = qtInvert( q );\n"
-" float4 vcpy = vec;\n"
-" vcpy.w = 0.f;\n"
-" float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
-" return out;\n"
-"}\n"
-"__inline\n"
-"Quaternion qtInvert(Quaternion q)\n"
-"{\n"
-" return (Quaternion)(-q.xyz, q.w);\n"
-"}\n"
-"__inline\n"
-"float4 qtInvRotate(const Quaternion q, float4 vec)\n"
-"{\n"
-" return qtRotate( qtInvert( q ), vec );\n"
-"}\n"
-"__inline\n"
-"float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)\n"
-"{\n"
-" return qtRotate( *orientation, *p ) + (*translation);\n"
-"}\n"
-"void trInverse(float4 translationIn, Quaternion orientationIn,\n"
-" float4* translationOut, Quaternion* orientationOut)\n"
-"{\n"
-" *orientationOut = qtInvert(orientationIn);\n"
-" *translationOut = qtRotate(*orientationOut, -translationIn);\n"
-"}\n"
-"void trMul(float4 translationA, Quaternion orientationA,\n"
-" float4 translationB, Quaternion orientationB,\n"
-" float4* translationOut, Quaternion* orientationOut)\n"
-"{\n"
-" *orientationOut = qtMul(orientationA,orientationB);\n"
-" *translationOut = transform(&translationB,&translationA,&orientationA);\n"
-"}\n"
-"__inline\n"
-"float4 normalize3(const float4 a)\n"
-"{\n"
-" float4 n = make_float4(a.x, a.y, a.z, 0.f);\n"
-" return fastNormalize4( n );\n"
-"}\n"
-"__inline float4 lerp3(const float4 a,const float4 b, float t)\n"
-"{\n"
-" return make_float4( a.x + (b.x - a.x) * t,\n"
-" a.y + (b.y - a.y) * t,\n"
-" a.z + (b.z - a.z) * t,\n"
-" 0.f);\n"
-"}\n"
-"float signedDistanceFromPointToPlane(float4 point, float4 planeEqn, float4* closestPointOnFace)\n"
-"{\n"
-" float4 n = (float4)(planeEqn.x, planeEqn.y, planeEqn.z, 0);\n"
-" float dist = dot3F4(n, point) + planeEqn.w;\n"
-" *closestPointOnFace = point - dist * n;\n"
-" return dist;\n"
-"}\n"
-"inline bool IsPointInPolygon(float4 p, \n"
-" const btGpuFace* face,\n"
-" __global const float4* baseVertex,\n"
-" __global const int* convexIndices,\n"
-" float4* out)\n"
-"{\n"
-" float4 a;\n"
-" float4 b;\n"
-" float4 ab;\n"
-" float4 ap;\n"
-" float4 v;\n"
-" float4 plane = make_float4(face->m_plane.x,face->m_plane.y,face->m_plane.z,0.f);\n"
-" \n"
-" if (face->m_numIndices<2)\n"
-" return false;\n"
-" \n"
-" float4 v0 = baseVertex[convexIndices[face->m_indexOffset + face->m_numIndices-1]];\n"
-" \n"
-" b = v0;\n"
-" for(unsigned i=0; i != face->m_numIndices; ++i)\n"
-" {\n"
-" a = b;\n"
-" float4 vi = baseVertex[convexIndices[face->m_indexOffset + i]];\n"
-" b = vi;\n"
-" ab = b-a;\n"
-" ap = p-a;\n"
-" v = cross3(ab,plane);\n"
-" if (dot(ap, v) > 0.f)\n"
-" {\n"
-" float ab_m2 = dot(ab, ab);\n"
-" float rt = ab_m2 != 0.f ? dot(ab, ap) / ab_m2 : 0.f;\n"
-" if (rt <= 0.f)\n"
-" {\n"
-" *out = a;\n"
-" }\n"
-" else if (rt >= 1.f) \n"
-" {\n"
-" *out = b;\n"
-" }\n"
-" else\n"
-" {\n"
-" float s = 1.f - rt;\n"
-" out[0].x = s * a.x + rt * b.x;\n"
-" out[0].y = s * a.y + rt * b.y;\n"
-" out[0].z = s * a.z + rt * b.z;\n"
-" }\n"
-" return false;\n"
-" }\n"
-" }\n"
-" return true;\n"
-"}\n"
-"void computeContactSphereConvex(int pairIndex,\n"
-" int bodyIndexA, int bodyIndexB, \n"
-" int collidableIndexA, int collidableIndexB, \n"
-" __global const BodyData* rigidBodies, \n"
-" __global const btCollidableGpu* collidables,\n"
-" __global const ConvexPolyhedronCL* convexShapes,\n"
-" __global const float4* convexVertices,\n"
-" __global const int* convexIndices,\n"
-" __global const btGpuFace* faces,\n"
-" __global struct b3Contact4Data* restrict globalContactsOut,\n"
-" counter32_t nGlobalContactsOut,\n"
-" int maxContactCapacity,\n"
-" float4 spherePos2,\n"
-" float radius,\n"
-" float4 pos,\n"
-" float4 quat\n"
-" )\n"
-"{\n"
-" float4 invPos;\n"
-" float4 invOrn;\n"
-" trInverse(pos,quat, &invPos,&invOrn);\n"
-" float4 spherePos = transform(&spherePos2,&invPos,&invOrn);\n"
-" int shapeIndex = collidables[collidableIndexB].m_shapeIndex;\n"
-" int numFaces = convexShapes[shapeIndex].m_numFaces;\n"
-" float4 closestPnt = (float4)(0, 0, 0, 0);\n"
-" float4 hitNormalWorld = (float4)(0, 0, 0, 0);\n"
-" float minDist = -1000000.f;\n"
-" bool bCollide = true;\n"
-" for ( int f = 0; f < numFaces; f++ )\n"
-" {\n"
-" btGpuFace face = faces[convexShapes[shapeIndex].m_faceOffset+f];\n"
-" // set up a plane equation \n"
-" float4 planeEqn;\n"
-" float4 n1 = face.m_plane;\n"
-" n1.w = 0.f;\n"
-" planeEqn = n1;\n"
-" planeEqn.w = face.m_plane.w;\n"
-" \n"
-" \n"
-" // compute a signed distance from the vertex in cloth to the face of rigidbody.\n"
-" float4 pntReturn;\n"
-" float dist = signedDistanceFromPointToPlane(spherePos, planeEqn, &pntReturn);\n"
-" // If the distance is positive, the plane is a separating plane. \n"
-" if ( dist > radius )\n"
-" {\n"
-" bCollide = false;\n"
-" break;\n"
-" }\n"
-" if (dist>0)\n"
-" {\n"
-" //might hit an edge or vertex\n"
-" float4 out;\n"
-" float4 zeroPos = make_float4(0,0,0,0);\n"
-" bool isInPoly = IsPointInPolygon(spherePos,\n"
-" &face,\n"
-" &convexVertices[convexShapes[shapeIndex].m_vertexOffset],\n"
-" convexIndices,\n"
-" &out);\n"
-" if (isInPoly)\n"
-" {\n"
-" if (dist>minDist)\n"
-" {\n"
-" minDist = dist;\n"
-" closestPnt = pntReturn;\n"
-" hitNormalWorld = planeEqn;\n"
-" \n"
-" }\n"
-" } else\n"
-" {\n"
-" float4 tmp = spherePos-out;\n"
-" float l2 = dot(tmp,tmp);\n"
-" if (l2<radius*radius)\n"
-" {\n"
-" dist = sqrt(l2);\n"
-" if (dist>minDist)\n"
-" {\n"
-" minDist = dist;\n"
-" closestPnt = out;\n"
-" hitNormalWorld = tmp/dist;\n"
-" \n"
-" }\n"
-" \n"
-" } else\n"
-" {\n"
-" bCollide = false;\n"
-" break;\n"
-" }\n"
-" }\n"
-" } else\n"
-" {\n"
-" if ( dist > minDist )\n"
-" {\n"
-" minDist = dist;\n"
-" closestPnt = pntReturn;\n"
-" hitNormalWorld.xyz = planeEqn.xyz;\n"
-" }\n"
-" }\n"
-" \n"
-" }\n"
-" \n"
-" if (bCollide && minDist > -10000)\n"
-" {\n"
-" float4 normalOnSurfaceB1 = qtRotate(quat,-hitNormalWorld);\n"
-" float4 pOnB1 = transform(&closestPnt,&pos,&quat);\n"
-" \n"
-" float actualDepth = minDist-radius;\n"
-" if (actualDepth<=0.f)\n"
-" {\n"
-" \n"
-" pOnB1.w = actualDepth;\n"
-" int dstIdx;\n"
-" AppendInc( nGlobalContactsOut, dstIdx );\n"
-" \n"
-" \n"
-" if (1)//dstIdx < maxContactCapacity)\n"
-" {\n"
-" __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];\n"
-" c->m_worldNormalOnB = -normalOnSurfaceB1;\n"
-" c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
-" c->m_batchIdx = pairIndex;\n"
-" c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;\n"
-" c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;\n"
-" c->m_worldPosB[0] = pOnB1;\n"
-" c->m_childIndexA = -1;\n"
-" c->m_childIndexB = -1;\n"
-" GET_NPOINTS(*c) = 1;\n"
-" } \n"
-" }\n"
-" }//if (hasCollision)\n"
-"}\n"
-" \n"
-"int extractManifoldSequential(const float4* p, int nPoints, float4 nearNormal, int4* contactIdx)\n"
-"{\n"
-" if( nPoints == 0 )\n"
-" return 0;\n"
-" \n"
-" if (nPoints <=4)\n"
-" return nPoints;\n"
-" \n"
-" \n"
-" if (nPoints >64)\n"
-" nPoints = 64;\n"
-" \n"
-" float4 center = make_float4(0.f);\n"
-" {\n"
-" \n"
-" for (int i=0;i<nPoints;i++)\n"
-" center += p[i];\n"
-" center /= (float)nPoints;\n"
-" }\n"
-" \n"
-" \n"
-" \n"
-" // sample 4 directions\n"
-" \n"
-" float4 aVector = p[0] - center;\n"
-" float4 u = cross3( nearNormal, aVector );\n"
-" float4 v = cross3( nearNormal, u );\n"
-" u = normalize3( u );\n"
-" v = normalize3( v );\n"
-" \n"
-" \n"
-" //keep point with deepest penetration\n"
-" float minW= FLT_MAX;\n"
-" \n"
-" int minIndex=-1;\n"
-" \n"
-" float4 maxDots;\n"
-" maxDots.x = FLT_MIN;\n"
-" maxDots.y = FLT_MIN;\n"
-" maxDots.z = FLT_MIN;\n"
-" maxDots.w = FLT_MIN;\n"
-" \n"
-" // idx, distance\n"
-" for(int ie = 0; ie<nPoints; ie++ )\n"
-" {\n"
-" if (p[ie].w<minW)\n"
-" {\n"
-" minW = p[ie].w;\n"
-" minIndex=ie;\n"
-" }\n"
-" float f;\n"
-" float4 r = p[ie]-center;\n"
-" f = dot3F4( u, r );\n"
-" if (f<maxDots.x)\n"
-" {\n"
-" maxDots.x = f;\n"
-" contactIdx[0].x = ie;\n"
-" }\n"
-" \n"
-" f = dot3F4( -u, r );\n"
-" if (f<maxDots.y)\n"
-" {\n"
-" maxDots.y = f;\n"
-" contactIdx[0].y = ie;\n"
-" }\n"
-" \n"
-" \n"
-" f = dot3F4( v, r );\n"
-" if (f<maxDots.z)\n"
-" {\n"
-" maxDots.z = f;\n"
-" contactIdx[0].z = ie;\n"
-" }\n"
-" \n"
-" f = dot3F4( -v, r );\n"
-" if (f<maxDots.w)\n"
-" {\n"
-" maxDots.w = f;\n"
-" contactIdx[0].w = ie;\n"
-" }\n"
-" \n"
-" }\n"
-" \n"
-" if (contactIdx[0].x != minIndex && contactIdx[0].y != minIndex && contactIdx[0].z != minIndex && contactIdx[0].w != minIndex)\n"
-" {\n"
-" //replace the first contact with minimum (todo: replace contact with least penetration)\n"
-" contactIdx[0].x = minIndex;\n"
-" }\n"
-" \n"
-" return 4;\n"
-" \n"
-"}\n"
-"#define MAX_PLANE_CONVEX_POINTS 64\n"
-"int computeContactPlaneConvex(int pairIndex,\n"
-" int bodyIndexA, int bodyIndexB, \n"
-" int collidableIndexA, int collidableIndexB, \n"
-" __global const BodyData* rigidBodies, \n"
-" __global const btCollidableGpu*collidables,\n"
-" __global const ConvexPolyhedronCL* convexShapes,\n"
-" __global const float4* convexVertices,\n"
-" __global const int* convexIndices,\n"
-" __global const btGpuFace* faces,\n"
-" __global struct b3Contact4Data* restrict globalContactsOut,\n"
-" counter32_t nGlobalContactsOut,\n"
-" int maxContactCapacity,\n"
-" float4 posB,\n"
-" Quaternion ornB\n"
-" )\n"
-"{\n"
-" int resultIndex=-1;\n"
-" int shapeIndex = collidables[collidableIndexB].m_shapeIndex;\n"
-" __global const ConvexPolyhedronCL* hullB = &convexShapes[shapeIndex];\n"
-" \n"
-" float4 posA;\n"
-" posA = rigidBodies[bodyIndexA].m_pos;\n"
-" Quaternion ornA;\n"
-" ornA = rigidBodies[bodyIndexA].m_quat;\n"
-" int numContactsOut = 0;\n"
-" int numWorldVertsB1= 0;\n"
-" float4 planeEq;\n"
-" planeEq = faces[collidables[collidableIndexA].m_shapeIndex].m_plane;\n"
-" float4 planeNormal = make_float4(planeEq.x,planeEq.y,planeEq.z,0.f);\n"
-" float4 planeNormalWorld;\n"
-" planeNormalWorld = qtRotate(ornA,planeNormal);\n"
-" float planeConstant = planeEq.w;\n"
-" \n"
-" float4 invPosA;Quaternion invOrnA;\n"
-" float4 convexInPlaneTransPos1; Quaternion convexInPlaneTransOrn1;\n"
-" {\n"
-" \n"
-" trInverse(posA,ornA,&invPosA,&invOrnA);\n"
-" trMul(invPosA,invOrnA,posB,ornB,&convexInPlaneTransPos1,&convexInPlaneTransOrn1);\n"
-" }\n"
-" float4 invPosB;Quaternion invOrnB;\n"
-" float4 planeInConvexPos1; Quaternion planeInConvexOrn1;\n"
-" {\n"
-" \n"
-" trInverse(posB,ornB,&invPosB,&invOrnB);\n"
-" trMul(invPosB,invOrnB,posA,ornA,&planeInConvexPos1,&planeInConvexOrn1); \n"
-" }\n"
-" \n"
-" float4 planeNormalInConvex = qtRotate(planeInConvexOrn1,-planeNormal);\n"
-" float maxDot = -1e30;\n"
-" int hitVertex=-1;\n"
-" float4 hitVtx;\n"
-" float4 contactPoints[MAX_PLANE_CONVEX_POINTS];\n"
-" int numPoints = 0;\n"
-" int4 contactIdx;\n"
-" contactIdx=make_int4(0,1,2,3);\n"
-" \n"
-" \n"
-" for (int i=0;i<hullB->m_numVertices;i++)\n"
-" {\n"
-" float4 vtx = convexVertices[hullB->m_vertexOffset+i];\n"
-" float curDot = dot(vtx,planeNormalInConvex);\n"
-" if (curDot>maxDot)\n"
-" {\n"
-" hitVertex=i;\n"
-" maxDot=curDot;\n"
-" hitVtx = vtx;\n"
-" //make sure the deepest points is always included\n"
-" if (numPoints==MAX_PLANE_CONVEX_POINTS)\n"
-" numPoints--;\n"
-" }\n"
-" if (numPoints<MAX_PLANE_CONVEX_POINTS)\n"
-" {\n"
-" float4 vtxWorld = transform(&vtx, &posB, &ornB);\n"
-" float4 vtxInPlane = transform(&vtxWorld, &invPosA, &invOrnA);//oplaneTransform.inverse()*vtxWorld;\n"
-" float dist = dot(planeNormal,vtxInPlane)-planeConstant;\n"
-" if (dist<0.f)\n"
-" {\n"
-" vtxWorld.w = dist;\n"
-" contactPoints[numPoints] = vtxWorld;\n"
-" numPoints++;\n"
-" }\n"
-" }\n"
-" }\n"
-" int numReducedPoints = numPoints;\n"
-" if (numPoints>4)\n"
-" {\n"
-" numReducedPoints = extractManifoldSequential( contactPoints, numPoints, planeNormalInConvex, &contactIdx);\n"
-" }\n"
-" if (numReducedPoints>0)\n"
-" {\n"
-" int dstIdx;\n"
-" AppendInc( nGlobalContactsOut, dstIdx );\n"
-" if (dstIdx < maxContactCapacity)\n"
-" {\n"
-" resultIndex = dstIdx;\n"
-" __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];\n"
-" c->m_worldNormalOnB = -planeNormalWorld;\n"
-" //c->setFrictionCoeff(0.7);\n"
-" //c->setRestituitionCoeff(0.f);\n"
-" c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
-" c->m_batchIdx = pairIndex;\n"
-" c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;\n"
-" c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;\n"
-" c->m_childIndexA = -1;\n"
-" c->m_childIndexB = -1;\n"
-" switch (numReducedPoints)\n"
-" {\n"
-" case 4:\n"
-" c->m_worldPosB[3] = contactPoints[contactIdx.w];\n"
-" case 3:\n"
-" c->m_worldPosB[2] = contactPoints[contactIdx.z];\n"
-" case 2:\n"
-" c->m_worldPosB[1] = contactPoints[contactIdx.y];\n"
-" case 1:\n"
-" c->m_worldPosB[0] = contactPoints[contactIdx.x];\n"
-" default:\n"
-" {\n"
-" }\n"
-" };\n"
-" \n"
-" GET_NPOINTS(*c) = numReducedPoints;\n"
-" }//if (dstIdx < numPairs)\n"
-" } \n"
-" return resultIndex;\n"
-"}\n"
-"void computeContactPlaneSphere(int pairIndex,\n"
-" int bodyIndexA, int bodyIndexB, \n"
-" int collidableIndexA, int collidableIndexB, \n"
-" __global const BodyData* rigidBodies, \n"
-" __global const btCollidableGpu* collidables,\n"
-" __global const btGpuFace* faces,\n"
-" __global struct b3Contact4Data* restrict globalContactsOut,\n"
-" counter32_t nGlobalContactsOut,\n"
-" int maxContactCapacity)\n"
-"{\n"
-" float4 planeEq = faces[collidables[collidableIndexA].m_shapeIndex].m_plane;\n"
-" float radius = collidables[collidableIndexB].m_radius;\n"
-" float4 posA1 = rigidBodies[bodyIndexA].m_pos;\n"
-" float4 ornA1 = rigidBodies[bodyIndexA].m_quat;\n"
-" float4 posB1 = rigidBodies[bodyIndexB].m_pos;\n"
-" float4 ornB1 = rigidBodies[bodyIndexB].m_quat;\n"
-" \n"
-" bool hasCollision = false;\n"
-" float4 planeNormal1 = make_float4(planeEq.x,planeEq.y,planeEq.z,0.f);\n"
-" float planeConstant = planeEq.w;\n"
-" float4 convexInPlaneTransPos1; Quaternion convexInPlaneTransOrn1;\n"
-" {\n"
-" float4 invPosA;Quaternion invOrnA;\n"
-" trInverse(posA1,ornA1,&invPosA,&invOrnA);\n"
-" trMul(invPosA,invOrnA,posB1,ornB1,&convexInPlaneTransPos1,&convexInPlaneTransOrn1);\n"
-" }\n"
-" float4 planeInConvexPos1; Quaternion planeInConvexOrn1;\n"
-" {\n"
-" float4 invPosB;Quaternion invOrnB;\n"
-" trInverse(posB1,ornB1,&invPosB,&invOrnB);\n"
-" trMul(invPosB,invOrnB,posA1,ornA1,&planeInConvexPos1,&planeInConvexOrn1); \n"
-" }\n"
-" float4 vtx1 = qtRotate(planeInConvexOrn1,-planeNormal1)*radius;\n"
-" float4 vtxInPlane1 = transform(&vtx1,&convexInPlaneTransPos1,&convexInPlaneTransOrn1);\n"
-" float distance = dot3F4(planeNormal1,vtxInPlane1) - planeConstant;\n"
-" hasCollision = distance < 0.f;//m_manifoldPtr->getContactBreakingThreshold();\n"
-" if (hasCollision)\n"
-" {\n"
-" float4 vtxInPlaneProjected1 = vtxInPlane1 - distance*planeNormal1;\n"
-" float4 vtxInPlaneWorld1 = transform(&vtxInPlaneProjected1,&posA1,&ornA1);\n"
-" float4 normalOnSurfaceB1 = qtRotate(ornA1,planeNormal1);\n"
-" float4 pOnB1 = vtxInPlaneWorld1+normalOnSurfaceB1*distance;\n"
-" pOnB1.w = distance;\n"
-" int dstIdx;\n"
-" AppendInc( nGlobalContactsOut, dstIdx );\n"
-" \n"
-" if (dstIdx < maxContactCapacity)\n"
-" {\n"
-" __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];\n"
-" c->m_worldNormalOnB = -normalOnSurfaceB1;\n"
-" c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
-" c->m_batchIdx = pairIndex;\n"
-" c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;\n"
-" c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;\n"
-" c->m_worldPosB[0] = pOnB1;\n"
-" c->m_childIndexA = -1;\n"
-" c->m_childIndexB = -1;\n"
-" GET_NPOINTS(*c) = 1;\n"
-" }//if (dstIdx < numPairs)\n"
-" }//if (hasCollision)\n"
-"}\n"
-"__kernel void primitiveContactsKernel( __global int4* pairs, \n"
-" __global const BodyData* rigidBodies, \n"
-" __global const btCollidableGpu* collidables,\n"
-" __global const ConvexPolyhedronCL* convexShapes, \n"
-" __global const float4* vertices,\n"
-" __global const float4* uniqueEdges,\n"
-" __global const btGpuFace* faces,\n"
-" __global const int* indices,\n"
-" __global struct b3Contact4Data* restrict globalContactsOut,\n"
-" counter32_t nGlobalContactsOut,\n"
-" int numPairs, int maxContactCapacity)\n"
-"{\n"
-" int i = get_global_id(0);\n"
-" int pairIndex = i;\n"
-" \n"
-" float4 worldVertsB1[64];\n"
-" float4 worldVertsB2[64];\n"
-" int capacityWorldVerts = 64; \n"
-" float4 localContactsOut[64];\n"
-" int localContactCapacity=64;\n"
-" \n"
-" float minDist = -1e30f;\n"
-" float maxDist = 0.02f;\n"
-" if (i<numPairs)\n"
-" {\n"
-" int bodyIndexA = pairs[i].x;\n"
-" int bodyIndexB = pairs[i].y;\n"
-" \n"
-" int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
-" int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
-" \n"
-" if (collidables[collidableIndexA].m_shapeType == SHAPE_PLANE &&\n"
-" collidables[collidableIndexB].m_shapeType == SHAPE_CONVEX_HULL)\n"
-" {\n"
-" float4 posB;\n"
-" posB = rigidBodies[bodyIndexB].m_pos;\n"
-" Quaternion ornB;\n"
-" ornB = rigidBodies[bodyIndexB].m_quat;\n"
-" int contactIndex = computeContactPlaneConvex(pairIndex, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB, \n"
-" rigidBodies,collidables,convexShapes,vertices,indices,\n"
-" faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity, posB,ornB);\n"
-" if (contactIndex>=0)\n"
-" pairs[pairIndex].z = contactIndex;\n"
-" return;\n"
-" }\n"
-" if (collidables[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&\n"
-" collidables[collidableIndexB].m_shapeType == SHAPE_PLANE)\n"
-" {\n"
-" float4 posA;\n"
-" posA = rigidBodies[bodyIndexA].m_pos;\n"
-" Quaternion ornA;\n"
-" ornA = rigidBodies[bodyIndexA].m_quat;\n"
-" int contactIndex = computeContactPlaneConvex( pairIndex, bodyIndexB,bodyIndexA, collidableIndexB,collidableIndexA, \n"
-" rigidBodies,collidables,convexShapes,vertices,indices,\n"
-" faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,posA,ornA);\n"
-" if (contactIndex>=0)\n"
-" pairs[pairIndex].z = contactIndex;\n"
-" return;\n"
-" }\n"
-" if (collidables[collidableIndexA].m_shapeType == SHAPE_PLANE &&\n"
-" collidables[collidableIndexB].m_shapeType == SHAPE_SPHERE)\n"
-" {\n"
-" computeContactPlaneSphere(pairIndex, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB, \n"
-" rigidBodies,collidables,faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity);\n"
-" return;\n"
-" }\n"
-" if (collidables[collidableIndexA].m_shapeType == SHAPE_SPHERE &&\n"
-" collidables[collidableIndexB].m_shapeType == SHAPE_PLANE)\n"
-" {\n"
-" computeContactPlaneSphere( pairIndex, bodyIndexB,bodyIndexA, collidableIndexB,collidableIndexA, \n"
-" rigidBodies,collidables,\n"
-" faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity);\n"
-" return;\n"
-" }\n"
-" \n"
-" \n"
-" if (collidables[collidableIndexA].m_shapeType == SHAPE_SPHERE &&\n"
-" collidables[collidableIndexB].m_shapeType == SHAPE_CONVEX_HULL)\n"
-" {\n"
-" \n"
-" float4 spherePos = rigidBodies[bodyIndexA].m_pos;\n"
-" float sphereRadius = collidables[collidableIndexA].m_radius;\n"
-" float4 convexPos = rigidBodies[bodyIndexB].m_pos;\n"
-" float4 convexOrn = rigidBodies[bodyIndexB].m_quat;\n"
-" computeContactSphereConvex(pairIndex, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB, \n"
-" rigidBodies,collidables,convexShapes,vertices,indices,faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,\n"
-" spherePos,sphereRadius,convexPos,convexOrn);\n"
-" return;\n"
-" }\n"
-" if (collidables[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&\n"
-" collidables[collidableIndexB].m_shapeType == SHAPE_SPHERE)\n"
-" {\n"
-" \n"
-" float4 spherePos = rigidBodies[bodyIndexB].m_pos;\n"
-" float sphereRadius = collidables[collidableIndexB].m_radius;\n"
-" float4 convexPos = rigidBodies[bodyIndexA].m_pos;\n"
-" float4 convexOrn = rigidBodies[bodyIndexA].m_quat;\n"
-" computeContactSphereConvex(pairIndex, bodyIndexB, bodyIndexA, collidableIndexB, collidableIndexA, \n"
-" rigidBodies,collidables,convexShapes,vertices,indices,faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,\n"
-" spherePos,sphereRadius,convexPos,convexOrn);\n"
-" return;\n"
-" }\n"
-" \n"
-" \n"
-" \n"
-" \n"
-" \n"
-" \n"
-" if (collidables[collidableIndexA].m_shapeType == SHAPE_SPHERE &&\n"
-" collidables[collidableIndexB].m_shapeType == SHAPE_SPHERE)\n"
-" {\n"
-" //sphere-sphere\n"
-" float radiusA = collidables[collidableIndexA].m_radius;\n"
-" float radiusB = collidables[collidableIndexB].m_radius;\n"
-" float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
-" float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
-" float4 diff = posA-posB;\n"
-" float len = length(diff);\n"
-" \n"
-" ///iff distance positive, don't generate a new contact\n"
-" if ( len <= (radiusA+radiusB))\n"
-" {\n"
-" ///distance (negative means penetration)\n"
-" float dist = len - (radiusA+radiusB);\n"
-" float4 normalOnSurfaceB = make_float4(1.f,0.f,0.f,0.f);\n"
-" if (len > 0.00001)\n"
-" {\n"
-" normalOnSurfaceB = diff / len;\n"
-" }\n"
-" float4 contactPosB = posB + normalOnSurfaceB*radiusB;\n"
-" contactPosB.w = dist;\n"
-" \n"
-" int dstIdx;\n"
-" AppendInc( nGlobalContactsOut, dstIdx );\n"
-" \n"
-" if (dstIdx < maxContactCapacity)\n"
-" {\n"
-" __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];\n"
-" c->m_worldNormalOnB = normalOnSurfaceB;\n"
-" c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
-" c->m_batchIdx = pairIndex;\n"
-" int bodyA = pairs[pairIndex].x;\n"
-" int bodyB = pairs[pairIndex].y;\n"
-" c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;\n"
-" c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;\n"
-" c->m_worldPosB[0] = contactPosB;\n"
-" c->m_childIndexA = -1;\n"
-" c->m_childIndexB = -1;\n"
-" GET_NPOINTS(*c) = 1;\n"
-" }//if (dstIdx < numPairs)\n"
-" }//if ( len <= (radiusA+radiusB))\n"
-" return;\n"
-" }//SHAPE_SPHERE SHAPE_SPHERE\n"
-" }// if (i<numPairs)\n"
-"}\n"
-"// work-in-progress\n"
-"__kernel void processCompoundPairsPrimitivesKernel( __global const int4* gpuCompoundPairs,\n"
-" __global const BodyData* rigidBodies, \n"
-" __global const btCollidableGpu* collidables,\n"
-" __global const ConvexPolyhedronCL* convexShapes, \n"
-" __global const float4* vertices,\n"
-" __global const float4* uniqueEdges,\n"
-" __global const btGpuFace* faces,\n"
-" __global const int* indices,\n"
-" __global btAabbCL* aabbs,\n"
-" __global const btGpuChildShape* gpuChildShapes,\n"
-" __global struct b3Contact4Data* restrict globalContactsOut,\n"
-" counter32_t nGlobalContactsOut,\n"
-" int numCompoundPairs, int maxContactCapacity\n"
-" )\n"
-"{\n"
-" int i = get_global_id(0);\n"
-" if (i<numCompoundPairs)\n"
-" {\n"
-" int bodyIndexA = gpuCompoundPairs[i].x;\n"
-" int bodyIndexB = gpuCompoundPairs[i].y;\n"
-" int childShapeIndexA = gpuCompoundPairs[i].z;\n"
-" int childShapeIndexB = gpuCompoundPairs[i].w;\n"
-" \n"
-" int collidableIndexA = -1;\n"
-" int collidableIndexB = -1;\n"
-" \n"
-" float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
-" float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
-" \n"
-" float4 ornB = rigidBodies[bodyIndexB].m_quat;\n"
-" float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
-" \n"
-" if (childShapeIndexA >= 0)\n"
-" {\n"
-" collidableIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;\n"
-" float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;\n"
-" float4 childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;\n"
-" float4 newPosA = qtRotate(ornA,childPosA)+posA;\n"
-" float4 newOrnA = qtMul(ornA,childOrnA);\n"
-" posA = newPosA;\n"
-" ornA = newOrnA;\n"
-" } else\n"
-" {\n"
-" collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
-" }\n"
-" \n"
-" if (childShapeIndexB>=0)\n"
-" {\n"
-" collidableIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
-" float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
-" float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
-" float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
-" float4 newOrnB = qtMul(ornB,childOrnB);\n"
-" posB = newPosB;\n"
-" ornB = newOrnB;\n"
-" } else\n"
-" {\n"
-" collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx; \n"
-" }\n"
-" \n"
-" int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
-" int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
-" \n"
-" int shapeTypeA = collidables[collidableIndexA].m_shapeType;\n"
-" int shapeTypeB = collidables[collidableIndexB].m_shapeType;\n"
-" int pairIndex = i;\n"
-" if ((shapeTypeA == SHAPE_PLANE) && (shapeTypeB==SHAPE_CONVEX_HULL))\n"
-" {\n"
-" computeContactPlaneConvex( pairIndex, bodyIndexA,bodyIndexB, collidableIndexA,collidableIndexB, \n"
-" rigidBodies,collidables,convexShapes,vertices,indices,\n"
-" faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,posB,ornB);\n"
-" return;\n"
-" }\n"
-" if ((shapeTypeA == SHAPE_CONVEX_HULL) && (shapeTypeB==SHAPE_PLANE))\n"
-" {\n"
-" computeContactPlaneConvex( pairIndex, bodyIndexB,bodyIndexA, collidableIndexB,collidableIndexA, \n"
-" rigidBodies,collidables,convexShapes,vertices,indices,\n"
-" faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,posA,ornA);\n"
-" return;\n"
-" }\n"
-" if ((shapeTypeA == SHAPE_CONVEX_HULL) && (shapeTypeB == SHAPE_SPHERE))\n"
-" {\n"
-" float4 spherePos = rigidBodies[bodyIndexB].m_pos;\n"
-" float sphereRadius = collidables[collidableIndexB].m_radius;\n"
-" float4 convexPos = posA;\n"
-" float4 convexOrn = ornA;\n"
-" \n"
-" computeContactSphereConvex(pairIndex, bodyIndexB, bodyIndexA , collidableIndexB,collidableIndexA, \n"
-" rigidBodies,collidables,convexShapes,vertices,indices,faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,\n"
-" spherePos,sphereRadius,convexPos,convexOrn);\n"
-" \n"
-" return;\n"
-" }\n"
-" if ((shapeTypeA == SHAPE_SPHERE) && (shapeTypeB == SHAPE_CONVEX_HULL))\n"
-" {\n"
-" float4 spherePos = rigidBodies[bodyIndexA].m_pos;\n"
-" float sphereRadius = collidables[collidableIndexA].m_radius;\n"
-" float4 convexPos = posB;\n"
-" float4 convexOrn = ornB;\n"
-" \n"
-" computeContactSphereConvex(pairIndex, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB, \n"
-" rigidBodies,collidables,convexShapes,vertices,indices,faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,\n"
-" spherePos,sphereRadius,convexPos,convexOrn);\n"
-" \n"
-" return;\n"
-" }\n"
-" }// if (i<numCompoundPairs)\n"
-"}\n"
-"bool pointInTriangle(const float4* vertices, const float4* normal, float4 *p )\n"
-"{\n"
-" const float4* p1 = &vertices[0];\n"
-" const float4* p2 = &vertices[1];\n"
-" const float4* p3 = &vertices[2];\n"
-" float4 edge1; edge1 = (*p2 - *p1);\n"
-" float4 edge2; edge2 = ( *p3 - *p2 );\n"
-" float4 edge3; edge3 = ( *p1 - *p3 );\n"
-" \n"
-" float4 p1_to_p; p1_to_p = ( *p - *p1 );\n"
-" float4 p2_to_p; p2_to_p = ( *p - *p2 );\n"
-" float4 p3_to_p; p3_to_p = ( *p - *p3 );\n"
-" float4 edge1_normal; edge1_normal = ( cross(edge1,*normal));\n"
-" float4 edge2_normal; edge2_normal = ( cross(edge2,*normal));\n"
-" float4 edge3_normal; edge3_normal = ( cross(edge3,*normal));\n"
-" \n"
-" \n"
-" float r1, r2, r3;\n"
-" r1 = dot(edge1_normal,p1_to_p );\n"
-" r2 = dot(edge2_normal,p2_to_p );\n"
-" r3 = dot(edge3_normal,p3_to_p );\n"
-" \n"
-" if ( r1 > 0 && r2 > 0 && r3 > 0 )\n"
-" return true;\n"
-" if ( r1 <= 0 && r2 <= 0 && r3 <= 0 ) \n"
-" return true;\n"
-" return false;\n"
-"}\n"
-"float segmentSqrDistance(float4 from, float4 to,float4 p, float4* nearest) \n"
-"{\n"
-" float4 diff = p - from;\n"
-" float4 v = to - from;\n"
-" float t = dot(v,diff);\n"
-" \n"
-" if (t > 0) \n"
-" {\n"
-" float dotVV = dot(v,v);\n"
-" if (t < dotVV) \n"
-" {\n"
-" t /= dotVV;\n"
-" diff -= t*v;\n"
-" } else \n"
-" {\n"
-" t = 1;\n"
-" diff -= v;\n"
-" }\n"
-" } else\n"
-" {\n"
-" t = 0;\n"
-" }\n"
-" *nearest = from + t*v;\n"
-" return dot(diff,diff); \n"
-"}\n"
-"void computeContactSphereTriangle(int pairIndex,\n"
-" int bodyIndexA, int bodyIndexB,\n"
-" int collidableIndexA, int collidableIndexB, \n"
-" __global const BodyData* rigidBodies, \n"
-" __global const btCollidableGpu* collidables,\n"
-" const float4* triangleVertices,\n"
-" __global struct b3Contact4Data* restrict globalContactsOut,\n"
-" counter32_t nGlobalContactsOut,\n"
-" int maxContactCapacity,\n"
-" float4 spherePos2,\n"
-" float radius,\n"
-" float4 pos,\n"
-" float4 quat,\n"
-" int faceIndex\n"
-" )\n"
-"{\n"
-" float4 invPos;\n"
-" float4 invOrn;\n"
-" trInverse(pos,quat, &invPos,&invOrn);\n"
-" float4 spherePos = transform(&spherePos2,&invPos,&invOrn);\n"
-" int numFaces = 3;\n"
-" float4 closestPnt = (float4)(0, 0, 0, 0);\n"
-" float4 hitNormalWorld = (float4)(0, 0, 0, 0);\n"
-" float minDist = -1000000.f;\n"
-" bool bCollide = false;\n"
-" \n"
-" //////////////////////////////////////\n"
-" float4 sphereCenter;\n"
-" sphereCenter = spherePos;\n"
-" const float4* vertices = triangleVertices;\n"
-" float contactBreakingThreshold = 0.f;//todo?\n"
-" float radiusWithThreshold = radius + contactBreakingThreshold;\n"
-" float4 edge10;\n"
-" edge10 = vertices[1]-vertices[0];\n"
-" edge10.w = 0.f;//is this needed?\n"
-" float4 edge20;\n"
-" edge20 = vertices[2]-vertices[0];\n"
-" edge20.w = 0.f;//is this needed?\n"
-" float4 normal = cross3(edge10,edge20);\n"
-" normal = normalize(normal);\n"
-" float4 p1ToCenter;\n"
-" p1ToCenter = sphereCenter - vertices[0];\n"
-" \n"
-" float distanceFromPlane = dot(p1ToCenter,normal);\n"
-" if (distanceFromPlane < 0.f)\n"
-" {\n"
-" //triangle facing the other way\n"
-" distanceFromPlane *= -1.f;\n"
-" normal *= -1.f;\n"
-" }\n"
-" hitNormalWorld = normal;\n"
-" bool isInsideContactPlane = distanceFromPlane < radiusWithThreshold;\n"
-" \n"
-" // Check for contact / intersection\n"
-" bool hasContact = false;\n"
-" float4 contactPoint;\n"
-" if (isInsideContactPlane) \n"
-" {\n"
-" \n"
-" if (pointInTriangle(vertices,&normal, &sphereCenter)) \n"
-" {\n"
-" // Inside the contact wedge - touches a point on the shell plane\n"
-" hasContact = true;\n"
-" contactPoint = sphereCenter - normal*distanceFromPlane;\n"
-" \n"
-" } else {\n"
-" // Could be inside one of the contact capsules\n"
-" float contactCapsuleRadiusSqr = radiusWithThreshold*radiusWithThreshold;\n"
-" float4 nearestOnEdge;\n"
-" int numEdges = 3;\n"
-" for (int i = 0; i < numEdges; i++) \n"
-" {\n"
-" float4 pa =vertices[i];\n"
-" float4 pb = vertices[(i+1)%3];\n"
-" float distanceSqr = segmentSqrDistance(pa,pb,sphereCenter, &nearestOnEdge);\n"
-" if (distanceSqr < contactCapsuleRadiusSqr) \n"
-" {\n"
-" // Yep, we're inside a capsule\n"
-" hasContact = true;\n"
-" contactPoint = nearestOnEdge;\n"
-" \n"
-" }\n"
-" \n"
-" }\n"
-" }\n"
-" }\n"
-" if (hasContact) \n"
-" {\n"
-" closestPnt = contactPoint;\n"
-" float4 contactToCenter = sphereCenter - contactPoint;\n"
-" minDist = length(contactToCenter);\n"
-" if (minDist>FLT_EPSILON)\n"
-" {\n"
-" hitNormalWorld = normalize(contactToCenter);//*(1./minDist);\n"
-" bCollide = true;\n"
-" }\n"
-" \n"
-" }\n"
-" /////////////////////////////////////\n"
-" if (bCollide && minDist > -10000)\n"
-" {\n"
-" \n"
-" float4 normalOnSurfaceB1 = qtRotate(quat,-hitNormalWorld);\n"
-" float4 pOnB1 = transform(&closestPnt,&pos,&quat);\n"
-" float actualDepth = minDist-radius;\n"
-" \n"
-" if (actualDepth<=0.f)\n"
-" {\n"
-" pOnB1.w = actualDepth;\n"
-" int dstIdx;\n"
-" \n"
-" float lenSqr = dot3F4(normalOnSurfaceB1,normalOnSurfaceB1);\n"
-" if (lenSqr>FLT_EPSILON)\n"
-" {\n"
-" AppendInc( nGlobalContactsOut, dstIdx );\n"
-" \n"
-" if (dstIdx < maxContactCapacity)\n"
-" {\n"
-" __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];\n"
-" c->m_worldNormalOnB = -normalOnSurfaceB1;\n"
-" c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
-" c->m_batchIdx = pairIndex;\n"
-" c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;\n"
-" c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;\n"
-" c->m_worldPosB[0] = pOnB1;\n"
-" c->m_childIndexA = -1;\n"
-" c->m_childIndexB = faceIndex;\n"
-" GET_NPOINTS(*c) = 1;\n"
-" } \n"
-" }\n"
-" }\n"
-" }//if (hasCollision)\n"
-"}\n"
-"// work-in-progress\n"
-"__kernel void findConcaveSphereContactsKernel( __global int4* concavePairs,\n"
-" __global const BodyData* rigidBodies,\n"
-" __global const btCollidableGpu* collidables,\n"
-" __global const ConvexPolyhedronCL* convexShapes, \n"
-" __global const float4* vertices,\n"
-" __global const float4* uniqueEdges,\n"
-" __global const btGpuFace* faces,\n"
-" __global const int* indices,\n"
-" __global btAabbCL* aabbs,\n"
-" __global struct b3Contact4Data* restrict globalContactsOut,\n"
-" counter32_t nGlobalContactsOut,\n"
-" int numConcavePairs, int maxContactCapacity\n"
-" )\n"
-"{\n"
-" int i = get_global_id(0);\n"
-" if (i>=numConcavePairs)\n"
-" return;\n"
-" int pairIdx = i;\n"
-" int bodyIndexA = concavePairs[i].x;\n"
-" int bodyIndexB = concavePairs[i].y;\n"
-" int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
-" int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
-" int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
-" int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
-" if (collidables[collidableIndexB].m_shapeType==SHAPE_SPHERE)\n"
-" {\n"
-" int f = concavePairs[i].z;\n"
-" btGpuFace face = faces[convexShapes[shapeIndexA].m_faceOffset+f];\n"
-" \n"
-" float4 verticesA[3];\n"
-" for (int i=0;i<3;i++)\n"
-" {\n"
-" int index = indices[face.m_indexOffset+i];\n"
-" float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];\n"
-" verticesA[i] = vert;\n"
-" }\n"
-" float4 spherePos = rigidBodies[bodyIndexB].m_pos;\n"
-" float sphereRadius = collidables[collidableIndexB].m_radius;\n"
-" float4 convexPos = rigidBodies[bodyIndexA].m_pos;\n"
-" float4 convexOrn = rigidBodies[bodyIndexA].m_quat;\n"
-" computeContactSphereTriangle(i, bodyIndexB, bodyIndexA, collidableIndexB, collidableIndexA, \n"
-" rigidBodies,collidables,\n"
-" verticesA,\n"
-" globalContactsOut, nGlobalContactsOut,maxContactCapacity,\n"
-" spherePos,sphereRadius,convexPos,convexOrn, f);\n"
-" return;\n"
-" }\n"
-"}\n"
-;
+static const char* primitiveContactsKernelsCL =
+ "#ifndef B3_CONTACT4DATA_H\n"
+ "#define B3_CONTACT4DATA_H\n"
+ "#ifndef B3_FLOAT4_H\n"
+ "#define B3_FLOAT4_H\n"
+ "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+ "#define B3_PLATFORM_DEFINITIONS_H\n"
+ "struct MyTest\n"
+ "{\n"
+ " int bla;\n"
+ "};\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
+ "#define B3_LARGE_FLOAT 1e18f\n"
+ "#define B3_INFINITY 1e18f\n"
+ "#define b3Assert(a)\n"
+ "#define b3ConstArray(a) __global const a*\n"
+ "#define b3AtomicInc atomic_inc\n"
+ "#define b3AtomicAdd atomic_add\n"
+ "#define b3Fabs fabs\n"
+ "#define b3Sqrt native_sqrt\n"
+ "#define b3Sin native_sin\n"
+ "#define b3Cos native_cos\n"
+ "#define B3_STATIC\n"
+ "#endif\n"
+ "#endif\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ " typedef float4 b3Float4;\n"
+ " #define b3Float4ConstArg const b3Float4\n"
+ " #define b3MakeFloat4 (float4)\n"
+ " float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+ " {\n"
+ " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+ " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+ " return dot(a1, b1);\n"
+ " }\n"
+ " b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+ " {\n"
+ " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+ " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+ " return cross(a1, b1);\n"
+ " }\n"
+ " #define b3MinFloat4 min\n"
+ " #define b3MaxFloat4 max\n"
+ " #define b3Normalized(a) normalize(a)\n"
+ "#endif \n"
+ " \n"
+ "inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
+ "{\n"
+ " if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
+ " return false;\n"
+ " return true;\n"
+ "}\n"
+ "inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
+ "{\n"
+ " float maxDot = -B3_INFINITY;\n"
+ " int i = 0;\n"
+ " int ptIndex = -1;\n"
+ " for( i = 0; i < vecLen; i++ )\n"
+ " {\n"
+ " float dot = b3Dot3F4(vecArray[i],vec);\n"
+ " \n"
+ " if( dot > maxDot )\n"
+ " {\n"
+ " maxDot = dot;\n"
+ " ptIndex = i;\n"
+ " }\n"
+ " }\n"
+ " b3Assert(ptIndex>=0);\n"
+ " if (ptIndex<0)\n"
+ " {\n"
+ " ptIndex = 0;\n"
+ " }\n"
+ " *dotOut = maxDot;\n"
+ " return ptIndex;\n"
+ "}\n"
+ "#endif //B3_FLOAT4_H\n"
+ "typedef struct b3Contact4Data b3Contact4Data_t;\n"
+ "struct b3Contact4Data\n"
+ "{\n"
+ " b3Float4 m_worldPosB[4];\n"
+ "// b3Float4 m_localPosA[4];\n"
+ "// b3Float4 m_localPosB[4];\n"
+ " b3Float4 m_worldNormalOnB; // w: m_nPoints\n"
+ " unsigned short m_restituitionCoeffCmp;\n"
+ " unsigned short m_frictionCoeffCmp;\n"
+ " int m_batchIdx;\n"
+ " int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
+ " int m_bodyBPtrAndSignBit;\n"
+ " int m_childIndexA;\n"
+ " int m_childIndexB;\n"
+ " int m_unused1;\n"
+ " int m_unused2;\n"
+ "};\n"
+ "inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
+ "{\n"
+ " return (int)contact->m_worldNormalOnB.w;\n"
+ "};\n"
+ "inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
+ "{\n"
+ " contact->m_worldNormalOnB.w = (float)numPoints;\n"
+ "};\n"
+ "#endif //B3_CONTACT4DATA_H\n"
+ "#define SHAPE_CONVEX_HULL 3\n"
+ "#define SHAPE_PLANE 4\n"
+ "#define SHAPE_CONCAVE_TRIMESH 5\n"
+ "#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6\n"
+ "#define SHAPE_SPHERE 7\n"
+ "#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
+ "#ifdef cl_ext_atomic_counters_32\n"
+ "#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
+ "#else\n"
+ "#define counter32_t volatile __global int*\n"
+ "#endif\n"
+ "#define GET_GROUP_IDX get_group_id(0)\n"
+ "#define GET_LOCAL_IDX get_local_id(0)\n"
+ "#define GET_GLOBAL_IDX get_global_id(0)\n"
+ "#define GET_GROUP_SIZE get_local_size(0)\n"
+ "#define GET_NUM_GROUPS get_num_groups(0)\n"
+ "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+ "#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
+ "#define AtomInc(x) atom_inc(&(x))\n"
+ "#define AtomInc1(x, out) out = atom_inc(&(x))\n"
+ "#define AppendInc(x, out) out = atomic_inc(x)\n"
+ "#define AtomAdd(x, value) atom_add(&(x), value)\n"
+ "#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
+ "#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
+ "#define max2 max\n"
+ "#define min2 min\n"
+ "typedef unsigned int u32;\n"
+ "typedef struct \n"
+ "{\n"
+ " union\n"
+ " {\n"
+ " float4 m_min;\n"
+ " float m_minElems[4];\n"
+ " int m_minIndices[4];\n"
+ " };\n"
+ " union\n"
+ " {\n"
+ " float4 m_max;\n"
+ " float m_maxElems[4];\n"
+ " int m_maxIndices[4];\n"
+ " };\n"
+ "} btAabbCL;\n"
+ "///keep this in sync with btCollidable.h\n"
+ "typedef struct\n"
+ "{\n"
+ " int m_numChildShapes;\n"
+ " float m_radius;\n"
+ " int m_shapeType;\n"
+ " int m_shapeIndex;\n"
+ " \n"
+ "} btCollidableGpu;\n"
+ "typedef struct\n"
+ "{\n"
+ " float4 m_childPosition;\n"
+ " float4 m_childOrientation;\n"
+ " int m_shapeIndex;\n"
+ " int m_unused0;\n"
+ " int m_unused1;\n"
+ " int m_unused2;\n"
+ "} btGpuChildShape;\n"
+ "#define GET_NPOINTS(x) (x).m_worldNormalOnB.w\n"
+ "typedef struct\n"
+ "{\n"
+ " float4 m_pos;\n"
+ " float4 m_quat;\n"
+ " float4 m_linVel;\n"
+ " float4 m_angVel;\n"
+ " u32 m_collidableIdx; \n"
+ " float m_invMass;\n"
+ " float m_restituitionCoeff;\n"
+ " float m_frictionCoeff;\n"
+ "} BodyData;\n"
+ "typedef struct \n"
+ "{\n"
+ " float4 m_localCenter;\n"
+ " float4 m_extents;\n"
+ " float4 mC;\n"
+ " float4 mE;\n"
+ " \n"
+ " float m_radius;\n"
+ " int m_faceOffset;\n"
+ " int m_numFaces;\n"
+ " int m_numVertices;\n"
+ " \n"
+ " int m_vertexOffset;\n"
+ " int m_uniqueEdgesOffset;\n"
+ " int m_numUniqueEdges;\n"
+ " int m_unused;\n"
+ "} ConvexPolyhedronCL;\n"
+ "typedef struct\n"
+ "{\n"
+ " float4 m_plane;\n"
+ " int m_indexOffset;\n"
+ " int m_numIndices;\n"
+ "} btGpuFace;\n"
+ "#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
+ "#define make_float4 (float4)\n"
+ "#define make_float2 (float2)\n"
+ "#define make_uint4 (uint4)\n"
+ "#define make_int4 (int4)\n"
+ "#define make_uint2 (uint2)\n"
+ "#define make_int2 (int2)\n"
+ "__inline\n"
+ "float fastDiv(float numerator, float denominator)\n"
+ "{\n"
+ " return native_divide(numerator, denominator); \n"
+ "// return numerator/denominator; \n"
+ "}\n"
+ "__inline\n"
+ "float4 fastDiv4(float4 numerator, float4 denominator)\n"
+ "{\n"
+ " return native_divide(numerator, denominator); \n"
+ "}\n"
+ "__inline\n"
+ "float4 cross3(float4 a, float4 b)\n"
+ "{\n"
+ " return cross(a,b);\n"
+ "}\n"
+ "//#define dot3F4 dot\n"
+ "__inline\n"
+ "float dot3F4(float4 a, float4 b)\n"
+ "{\n"
+ " float4 a1 = make_float4(a.xyz,0.f);\n"
+ " float4 b1 = make_float4(b.xyz,0.f);\n"
+ " return dot(a1, b1);\n"
+ "}\n"
+ "__inline\n"
+ "float4 fastNormalize4(float4 v)\n"
+ "{\n"
+ " return fast_normalize(v);\n"
+ "}\n"
+ "///////////////////////////////////////\n"
+ "// Quaternion\n"
+ "///////////////////////////////////////\n"
+ "typedef float4 Quaternion;\n"
+ "__inline\n"
+ "Quaternion qtMul(Quaternion a, Quaternion b);\n"
+ "__inline\n"
+ "Quaternion qtNormalize(Quaternion in);\n"
+ "__inline\n"
+ "float4 qtRotate(Quaternion q, float4 vec);\n"
+ "__inline\n"
+ "Quaternion qtInvert(Quaternion q);\n"
+ "__inline\n"
+ "Quaternion qtMul(Quaternion a, Quaternion b)\n"
+ "{\n"
+ " Quaternion ans;\n"
+ " ans = cross3( a, b );\n"
+ " ans += a.w*b+b.w*a;\n"
+ "// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+ " ans.w = a.w*b.w - dot3F4(a, b);\n"
+ " return ans;\n"
+ "}\n"
+ "__inline\n"
+ "Quaternion qtNormalize(Quaternion in)\n"
+ "{\n"
+ " return fastNormalize4(in);\n"
+ "// in /= length( in );\n"
+ "// return in;\n"
+ "}\n"
+ "__inline\n"
+ "float4 qtRotate(Quaternion q, float4 vec)\n"
+ "{\n"
+ " Quaternion qInv = qtInvert( q );\n"
+ " float4 vcpy = vec;\n"
+ " vcpy.w = 0.f;\n"
+ " float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
+ " return out;\n"
+ "}\n"
+ "__inline\n"
+ "Quaternion qtInvert(Quaternion q)\n"
+ "{\n"
+ " return (Quaternion)(-q.xyz, q.w);\n"
+ "}\n"
+ "__inline\n"
+ "float4 qtInvRotate(const Quaternion q, float4 vec)\n"
+ "{\n"
+ " return qtRotate( qtInvert( q ), vec );\n"
+ "}\n"
+ "__inline\n"
+ "float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)\n"
+ "{\n"
+ " return qtRotate( *orientation, *p ) + (*translation);\n"
+ "}\n"
+ "void trInverse(float4 translationIn, Quaternion orientationIn,\n"
+ " float4* translationOut, Quaternion* orientationOut)\n"
+ "{\n"
+ " *orientationOut = qtInvert(orientationIn);\n"
+ " *translationOut = qtRotate(*orientationOut, -translationIn);\n"
+ "}\n"
+ "void trMul(float4 translationA, Quaternion orientationA,\n"
+ " float4 translationB, Quaternion orientationB,\n"
+ " float4* translationOut, Quaternion* orientationOut)\n"
+ "{\n"
+ " *orientationOut = qtMul(orientationA,orientationB);\n"
+ " *translationOut = transform(&translationB,&translationA,&orientationA);\n"
+ "}\n"
+ "__inline\n"
+ "float4 normalize3(const float4 a)\n"
+ "{\n"
+ " float4 n = make_float4(a.x, a.y, a.z, 0.f);\n"
+ " return fastNormalize4( n );\n"
+ "}\n"
+ "__inline float4 lerp3(const float4 a,const float4 b, float t)\n"
+ "{\n"
+ " return make_float4( a.x + (b.x - a.x) * t,\n"
+ " a.y + (b.y - a.y) * t,\n"
+ " a.z + (b.z - a.z) * t,\n"
+ " 0.f);\n"
+ "}\n"
+ "float signedDistanceFromPointToPlane(float4 point, float4 planeEqn, float4* closestPointOnFace)\n"
+ "{\n"
+ " float4 n = (float4)(planeEqn.x, planeEqn.y, planeEqn.z, 0);\n"
+ " float dist = dot3F4(n, point) + planeEqn.w;\n"
+ " *closestPointOnFace = point - dist * n;\n"
+ " return dist;\n"
+ "}\n"
+ "inline bool IsPointInPolygon(float4 p, \n"
+ " const btGpuFace* face,\n"
+ " __global const float4* baseVertex,\n"
+ " __global const int* convexIndices,\n"
+ " float4* out)\n"
+ "{\n"
+ " float4 a;\n"
+ " float4 b;\n"
+ " float4 ab;\n"
+ " float4 ap;\n"
+ " float4 v;\n"
+ " float4 plane = make_float4(face->m_plane.x,face->m_plane.y,face->m_plane.z,0.f);\n"
+ " \n"
+ " if (face->m_numIndices<2)\n"
+ " return false;\n"
+ " \n"
+ " float4 v0 = baseVertex[convexIndices[face->m_indexOffset + face->m_numIndices-1]];\n"
+ " \n"
+ " b = v0;\n"
+ " for(unsigned i=0; i != face->m_numIndices; ++i)\n"
+ " {\n"
+ " a = b;\n"
+ " float4 vi = baseVertex[convexIndices[face->m_indexOffset + i]];\n"
+ " b = vi;\n"
+ " ab = b-a;\n"
+ " ap = p-a;\n"
+ " v = cross3(ab,plane);\n"
+ " if (dot(ap, v) > 0.f)\n"
+ " {\n"
+ " float ab_m2 = dot(ab, ab);\n"
+ " float rt = ab_m2 != 0.f ? dot(ab, ap) / ab_m2 : 0.f;\n"
+ " if (rt <= 0.f)\n"
+ " {\n"
+ " *out = a;\n"
+ " }\n"
+ " else if (rt >= 1.f) \n"
+ " {\n"
+ " *out = b;\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " float s = 1.f - rt;\n"
+ " out[0].x = s * a.x + rt * b.x;\n"
+ " out[0].y = s * a.y + rt * b.y;\n"
+ " out[0].z = s * a.z + rt * b.z;\n"
+ " }\n"
+ " return false;\n"
+ " }\n"
+ " }\n"
+ " return true;\n"
+ "}\n"
+ "void computeContactSphereConvex(int pairIndex,\n"
+ " int bodyIndexA, int bodyIndexB, \n"
+ " int collidableIndexA, int collidableIndexB, \n"
+ " __global const BodyData* rigidBodies, \n"
+ " __global const btCollidableGpu* collidables,\n"
+ " __global const ConvexPolyhedronCL* convexShapes,\n"
+ " __global const float4* convexVertices,\n"
+ " __global const int* convexIndices,\n"
+ " __global const btGpuFace* faces,\n"
+ " __global struct b3Contact4Data* restrict globalContactsOut,\n"
+ " counter32_t nGlobalContactsOut,\n"
+ " int maxContactCapacity,\n"
+ " float4 spherePos2,\n"
+ " float radius,\n"
+ " float4 pos,\n"
+ " float4 quat\n"
+ " )\n"
+ "{\n"
+ " float4 invPos;\n"
+ " float4 invOrn;\n"
+ " trInverse(pos,quat, &invPos,&invOrn);\n"
+ " float4 spherePos = transform(&spherePos2,&invPos,&invOrn);\n"
+ " int shapeIndex = collidables[collidableIndexB].m_shapeIndex;\n"
+ " int numFaces = convexShapes[shapeIndex].m_numFaces;\n"
+ " float4 closestPnt = (float4)(0, 0, 0, 0);\n"
+ " float4 hitNormalWorld = (float4)(0, 0, 0, 0);\n"
+ " float minDist = -1000000.f;\n"
+ " bool bCollide = true;\n"
+ " for ( int f = 0; f < numFaces; f++ )\n"
+ " {\n"
+ " btGpuFace face = faces[convexShapes[shapeIndex].m_faceOffset+f];\n"
+ " // set up a plane equation \n"
+ " float4 planeEqn;\n"
+ " float4 n1 = face.m_plane;\n"
+ " n1.w = 0.f;\n"
+ " planeEqn = n1;\n"
+ " planeEqn.w = face.m_plane.w;\n"
+ " \n"
+ " \n"
+ " // compute a signed distance from the vertex in cloth to the face of rigidbody.\n"
+ " float4 pntReturn;\n"
+ " float dist = signedDistanceFromPointToPlane(spherePos, planeEqn, &pntReturn);\n"
+ " // If the distance is positive, the plane is a separating plane. \n"
+ " if ( dist > radius )\n"
+ " {\n"
+ " bCollide = false;\n"
+ " break;\n"
+ " }\n"
+ " if (dist>0)\n"
+ " {\n"
+ " //might hit an edge or vertex\n"
+ " float4 out;\n"
+ " float4 zeroPos = make_float4(0,0,0,0);\n"
+ " bool isInPoly = IsPointInPolygon(spherePos,\n"
+ " &face,\n"
+ " &convexVertices[convexShapes[shapeIndex].m_vertexOffset],\n"
+ " convexIndices,\n"
+ " &out);\n"
+ " if (isInPoly)\n"
+ " {\n"
+ " if (dist>minDist)\n"
+ " {\n"
+ " minDist = dist;\n"
+ " closestPnt = pntReturn;\n"
+ " hitNormalWorld = planeEqn;\n"
+ " \n"
+ " }\n"
+ " } else\n"
+ " {\n"
+ " float4 tmp = spherePos-out;\n"
+ " float l2 = dot(tmp,tmp);\n"
+ " if (l2<radius*radius)\n"
+ " {\n"
+ " dist = sqrt(l2);\n"
+ " if (dist>minDist)\n"
+ " {\n"
+ " minDist = dist;\n"
+ " closestPnt = out;\n"
+ " hitNormalWorld = tmp/dist;\n"
+ " \n"
+ " }\n"
+ " \n"
+ " } else\n"
+ " {\n"
+ " bCollide = false;\n"
+ " break;\n"
+ " }\n"
+ " }\n"
+ " } else\n"
+ " {\n"
+ " if ( dist > minDist )\n"
+ " {\n"
+ " minDist = dist;\n"
+ " closestPnt = pntReturn;\n"
+ " hitNormalWorld.xyz = planeEqn.xyz;\n"
+ " }\n"
+ " }\n"
+ " \n"
+ " }\n"
+ " \n"
+ " if (bCollide && minDist > -10000)\n"
+ " {\n"
+ " float4 normalOnSurfaceB1 = qtRotate(quat,-hitNormalWorld);\n"
+ " float4 pOnB1 = transform(&closestPnt,&pos,&quat);\n"
+ " \n"
+ " float actualDepth = minDist-radius;\n"
+ " if (actualDepth<=0.f)\n"
+ " {\n"
+ " \n"
+ " pOnB1.w = actualDepth;\n"
+ " int dstIdx;\n"
+ " AppendInc( nGlobalContactsOut, dstIdx );\n"
+ " \n"
+ " \n"
+ " if (1)//dstIdx < maxContactCapacity)\n"
+ " {\n"
+ " __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];\n"
+ " c->m_worldNormalOnB = -normalOnSurfaceB1;\n"
+ " c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
+ " c->m_batchIdx = pairIndex;\n"
+ " c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;\n"
+ " c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;\n"
+ " c->m_worldPosB[0] = pOnB1;\n"
+ " c->m_childIndexA = -1;\n"
+ " c->m_childIndexB = -1;\n"
+ " GET_NPOINTS(*c) = 1;\n"
+ " } \n"
+ " }\n"
+ " }//if (hasCollision)\n"
+ "}\n"
+ " \n"
+ "int extractManifoldSequential(const float4* p, int nPoints, float4 nearNormal, int4* contactIdx)\n"
+ "{\n"
+ " if( nPoints == 0 )\n"
+ " return 0;\n"
+ " \n"
+ " if (nPoints <=4)\n"
+ " return nPoints;\n"
+ " \n"
+ " \n"
+ " if (nPoints >64)\n"
+ " nPoints = 64;\n"
+ " \n"
+ " float4 center = make_float4(0.f);\n"
+ " {\n"
+ " \n"
+ " for (int i=0;i<nPoints;i++)\n"
+ " center += p[i];\n"
+ " center /= (float)nPoints;\n"
+ " }\n"
+ " \n"
+ " \n"
+ " \n"
+ " // sample 4 directions\n"
+ " \n"
+ " float4 aVector = p[0] - center;\n"
+ " float4 u = cross3( nearNormal, aVector );\n"
+ " float4 v = cross3( nearNormal, u );\n"
+ " u = normalize3( u );\n"
+ " v = normalize3( v );\n"
+ " \n"
+ " \n"
+ " //keep point with deepest penetration\n"
+ " float minW= FLT_MAX;\n"
+ " \n"
+ " int minIndex=-1;\n"
+ " \n"
+ " float4 maxDots;\n"
+ " maxDots.x = FLT_MIN;\n"
+ " maxDots.y = FLT_MIN;\n"
+ " maxDots.z = FLT_MIN;\n"
+ " maxDots.w = FLT_MIN;\n"
+ " \n"
+ " // idx, distance\n"
+ " for(int ie = 0; ie<nPoints; ie++ )\n"
+ " {\n"
+ " if (p[ie].w<minW)\n"
+ " {\n"
+ " minW = p[ie].w;\n"
+ " minIndex=ie;\n"
+ " }\n"
+ " float f;\n"
+ " float4 r = p[ie]-center;\n"
+ " f = dot3F4( u, r );\n"
+ " if (f<maxDots.x)\n"
+ " {\n"
+ " maxDots.x = f;\n"
+ " contactIdx[0].x = ie;\n"
+ " }\n"
+ " \n"
+ " f = dot3F4( -u, r );\n"
+ " if (f<maxDots.y)\n"
+ " {\n"
+ " maxDots.y = f;\n"
+ " contactIdx[0].y = ie;\n"
+ " }\n"
+ " \n"
+ " \n"
+ " f = dot3F4( v, r );\n"
+ " if (f<maxDots.z)\n"
+ " {\n"
+ " maxDots.z = f;\n"
+ " contactIdx[0].z = ie;\n"
+ " }\n"
+ " \n"
+ " f = dot3F4( -v, r );\n"
+ " if (f<maxDots.w)\n"
+ " {\n"
+ " maxDots.w = f;\n"
+ " contactIdx[0].w = ie;\n"
+ " }\n"
+ " \n"
+ " }\n"
+ " \n"
+ " if (contactIdx[0].x != minIndex && contactIdx[0].y != minIndex && contactIdx[0].z != minIndex && contactIdx[0].w != minIndex)\n"
+ " {\n"
+ " //replace the first contact with minimum (todo: replace contact with least penetration)\n"
+ " contactIdx[0].x = minIndex;\n"
+ " }\n"
+ " \n"
+ " return 4;\n"
+ " \n"
+ "}\n"
+ "#define MAX_PLANE_CONVEX_POINTS 64\n"
+ "int computeContactPlaneConvex(int pairIndex,\n"
+ " int bodyIndexA, int bodyIndexB, \n"
+ " int collidableIndexA, int collidableIndexB, \n"
+ " __global const BodyData* rigidBodies, \n"
+ " __global const btCollidableGpu*collidables,\n"
+ " __global const ConvexPolyhedronCL* convexShapes,\n"
+ " __global const float4* convexVertices,\n"
+ " __global const int* convexIndices,\n"
+ " __global const btGpuFace* faces,\n"
+ " __global struct b3Contact4Data* restrict globalContactsOut,\n"
+ " counter32_t nGlobalContactsOut,\n"
+ " int maxContactCapacity,\n"
+ " float4 posB,\n"
+ " Quaternion ornB\n"
+ " )\n"
+ "{\n"
+ " int resultIndex=-1;\n"
+ " int shapeIndex = collidables[collidableIndexB].m_shapeIndex;\n"
+ " __global const ConvexPolyhedronCL* hullB = &convexShapes[shapeIndex];\n"
+ " \n"
+ " float4 posA;\n"
+ " posA = rigidBodies[bodyIndexA].m_pos;\n"
+ " Quaternion ornA;\n"
+ " ornA = rigidBodies[bodyIndexA].m_quat;\n"
+ " int numContactsOut = 0;\n"
+ " int numWorldVertsB1= 0;\n"
+ " float4 planeEq;\n"
+ " planeEq = faces[collidables[collidableIndexA].m_shapeIndex].m_plane;\n"
+ " float4 planeNormal = make_float4(planeEq.x,planeEq.y,planeEq.z,0.f);\n"
+ " float4 planeNormalWorld;\n"
+ " planeNormalWorld = qtRotate(ornA,planeNormal);\n"
+ " float planeConstant = planeEq.w;\n"
+ " \n"
+ " float4 invPosA;Quaternion invOrnA;\n"
+ " float4 convexInPlaneTransPos1; Quaternion convexInPlaneTransOrn1;\n"
+ " {\n"
+ " \n"
+ " trInverse(posA,ornA,&invPosA,&invOrnA);\n"
+ " trMul(invPosA,invOrnA,posB,ornB,&convexInPlaneTransPos1,&convexInPlaneTransOrn1);\n"
+ " }\n"
+ " float4 invPosB;Quaternion invOrnB;\n"
+ " float4 planeInConvexPos1; Quaternion planeInConvexOrn1;\n"
+ " {\n"
+ " \n"
+ " trInverse(posB,ornB,&invPosB,&invOrnB);\n"
+ " trMul(invPosB,invOrnB,posA,ornA,&planeInConvexPos1,&planeInConvexOrn1); \n"
+ " }\n"
+ " \n"
+ " float4 planeNormalInConvex = qtRotate(planeInConvexOrn1,-planeNormal);\n"
+ " float maxDot = -1e30;\n"
+ " int hitVertex=-1;\n"
+ " float4 hitVtx;\n"
+ " float4 contactPoints[MAX_PLANE_CONVEX_POINTS];\n"
+ " int numPoints = 0;\n"
+ " int4 contactIdx;\n"
+ " contactIdx=make_int4(0,1,2,3);\n"
+ " \n"
+ " \n"
+ " for (int i=0;i<hullB->m_numVertices;i++)\n"
+ " {\n"
+ " float4 vtx = convexVertices[hullB->m_vertexOffset+i];\n"
+ " float curDot = dot(vtx,planeNormalInConvex);\n"
+ " if (curDot>maxDot)\n"
+ " {\n"
+ " hitVertex=i;\n"
+ " maxDot=curDot;\n"
+ " hitVtx = vtx;\n"
+ " //make sure the deepest points is always included\n"
+ " if (numPoints==MAX_PLANE_CONVEX_POINTS)\n"
+ " numPoints--;\n"
+ " }\n"
+ " if (numPoints<MAX_PLANE_CONVEX_POINTS)\n"
+ " {\n"
+ " float4 vtxWorld = transform(&vtx, &posB, &ornB);\n"
+ " float4 vtxInPlane = transform(&vtxWorld, &invPosA, &invOrnA);//oplaneTransform.inverse()*vtxWorld;\n"
+ " float dist = dot(planeNormal,vtxInPlane)-planeConstant;\n"
+ " if (dist<0.f)\n"
+ " {\n"
+ " vtxWorld.w = dist;\n"
+ " contactPoints[numPoints] = vtxWorld;\n"
+ " numPoints++;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " int numReducedPoints = numPoints;\n"
+ " if (numPoints>4)\n"
+ " {\n"
+ " numReducedPoints = extractManifoldSequential( contactPoints, numPoints, planeNormalInConvex, &contactIdx);\n"
+ " }\n"
+ " if (numReducedPoints>0)\n"
+ " {\n"
+ " int dstIdx;\n"
+ " AppendInc( nGlobalContactsOut, dstIdx );\n"
+ " if (dstIdx < maxContactCapacity)\n"
+ " {\n"
+ " resultIndex = dstIdx;\n"
+ " __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];\n"
+ " c->m_worldNormalOnB = -planeNormalWorld;\n"
+ " //c->setFrictionCoeff(0.7);\n"
+ " //c->setRestituitionCoeff(0.f);\n"
+ " c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
+ " c->m_batchIdx = pairIndex;\n"
+ " c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;\n"
+ " c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;\n"
+ " c->m_childIndexA = -1;\n"
+ " c->m_childIndexB = -1;\n"
+ " switch (numReducedPoints)\n"
+ " {\n"
+ " case 4:\n"
+ " c->m_worldPosB[3] = contactPoints[contactIdx.w];\n"
+ " case 3:\n"
+ " c->m_worldPosB[2] = contactPoints[contactIdx.z];\n"
+ " case 2:\n"
+ " c->m_worldPosB[1] = contactPoints[contactIdx.y];\n"
+ " case 1:\n"
+ " c->m_worldPosB[0] = contactPoints[contactIdx.x];\n"
+ " default:\n"
+ " {\n"
+ " }\n"
+ " };\n"
+ " \n"
+ " GET_NPOINTS(*c) = numReducedPoints;\n"
+ " }//if (dstIdx < numPairs)\n"
+ " } \n"
+ " return resultIndex;\n"
+ "}\n"
+ "void computeContactPlaneSphere(int pairIndex,\n"
+ " int bodyIndexA, int bodyIndexB, \n"
+ " int collidableIndexA, int collidableIndexB, \n"
+ " __global const BodyData* rigidBodies, \n"
+ " __global const btCollidableGpu* collidables,\n"
+ " __global const btGpuFace* faces,\n"
+ " __global struct b3Contact4Data* restrict globalContactsOut,\n"
+ " counter32_t nGlobalContactsOut,\n"
+ " int maxContactCapacity)\n"
+ "{\n"
+ " float4 planeEq = faces[collidables[collidableIndexA].m_shapeIndex].m_plane;\n"
+ " float radius = collidables[collidableIndexB].m_radius;\n"
+ " float4 posA1 = rigidBodies[bodyIndexA].m_pos;\n"
+ " float4 ornA1 = rigidBodies[bodyIndexA].m_quat;\n"
+ " float4 posB1 = rigidBodies[bodyIndexB].m_pos;\n"
+ " float4 ornB1 = rigidBodies[bodyIndexB].m_quat;\n"
+ " \n"
+ " bool hasCollision = false;\n"
+ " float4 planeNormal1 = make_float4(planeEq.x,planeEq.y,planeEq.z,0.f);\n"
+ " float planeConstant = planeEq.w;\n"
+ " float4 convexInPlaneTransPos1; Quaternion convexInPlaneTransOrn1;\n"
+ " {\n"
+ " float4 invPosA;Quaternion invOrnA;\n"
+ " trInverse(posA1,ornA1,&invPosA,&invOrnA);\n"
+ " trMul(invPosA,invOrnA,posB1,ornB1,&convexInPlaneTransPos1,&convexInPlaneTransOrn1);\n"
+ " }\n"
+ " float4 planeInConvexPos1; Quaternion planeInConvexOrn1;\n"
+ " {\n"
+ " float4 invPosB;Quaternion invOrnB;\n"
+ " trInverse(posB1,ornB1,&invPosB,&invOrnB);\n"
+ " trMul(invPosB,invOrnB,posA1,ornA1,&planeInConvexPos1,&planeInConvexOrn1); \n"
+ " }\n"
+ " float4 vtx1 = qtRotate(planeInConvexOrn1,-planeNormal1)*radius;\n"
+ " float4 vtxInPlane1 = transform(&vtx1,&convexInPlaneTransPos1,&convexInPlaneTransOrn1);\n"
+ " float distance = dot3F4(planeNormal1,vtxInPlane1) - planeConstant;\n"
+ " hasCollision = distance < 0.f;//m_manifoldPtr->getContactBreakingThreshold();\n"
+ " if (hasCollision)\n"
+ " {\n"
+ " float4 vtxInPlaneProjected1 = vtxInPlane1 - distance*planeNormal1;\n"
+ " float4 vtxInPlaneWorld1 = transform(&vtxInPlaneProjected1,&posA1,&ornA1);\n"
+ " float4 normalOnSurfaceB1 = qtRotate(ornA1,planeNormal1);\n"
+ " float4 pOnB1 = vtxInPlaneWorld1+normalOnSurfaceB1*distance;\n"
+ " pOnB1.w = distance;\n"
+ " int dstIdx;\n"
+ " AppendInc( nGlobalContactsOut, dstIdx );\n"
+ " \n"
+ " if (dstIdx < maxContactCapacity)\n"
+ " {\n"
+ " __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];\n"
+ " c->m_worldNormalOnB = -normalOnSurfaceB1;\n"
+ " c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
+ " c->m_batchIdx = pairIndex;\n"
+ " c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;\n"
+ " c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;\n"
+ " c->m_worldPosB[0] = pOnB1;\n"
+ " c->m_childIndexA = -1;\n"
+ " c->m_childIndexB = -1;\n"
+ " GET_NPOINTS(*c) = 1;\n"
+ " }//if (dstIdx < numPairs)\n"
+ " }//if (hasCollision)\n"
+ "}\n"
+ "__kernel void primitiveContactsKernel( __global int4* pairs, \n"
+ " __global const BodyData* rigidBodies, \n"
+ " __global const btCollidableGpu* collidables,\n"
+ " __global const ConvexPolyhedronCL* convexShapes, \n"
+ " __global const float4* vertices,\n"
+ " __global const float4* uniqueEdges,\n"
+ " __global const btGpuFace* faces,\n"
+ " __global const int* indices,\n"
+ " __global struct b3Contact4Data* restrict globalContactsOut,\n"
+ " counter32_t nGlobalContactsOut,\n"
+ " int numPairs, int maxContactCapacity)\n"
+ "{\n"
+ " int i = get_global_id(0);\n"
+ " int pairIndex = i;\n"
+ " \n"
+ " float4 worldVertsB1[64];\n"
+ " float4 worldVertsB2[64];\n"
+ " int capacityWorldVerts = 64; \n"
+ " float4 localContactsOut[64];\n"
+ " int localContactCapacity=64;\n"
+ " \n"
+ " float minDist = -1e30f;\n"
+ " float maxDist = 0.02f;\n"
+ " if (i<numPairs)\n"
+ " {\n"
+ " int bodyIndexA = pairs[i].x;\n"
+ " int bodyIndexB = pairs[i].y;\n"
+ " \n"
+ " int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+ " int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+ " \n"
+ " if (collidables[collidableIndexA].m_shapeType == SHAPE_PLANE &&\n"
+ " collidables[collidableIndexB].m_shapeType == SHAPE_CONVEX_HULL)\n"
+ " {\n"
+ " float4 posB;\n"
+ " posB = rigidBodies[bodyIndexB].m_pos;\n"
+ " Quaternion ornB;\n"
+ " ornB = rigidBodies[bodyIndexB].m_quat;\n"
+ " int contactIndex = computeContactPlaneConvex(pairIndex, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB, \n"
+ " rigidBodies,collidables,convexShapes,vertices,indices,\n"
+ " faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity, posB,ornB);\n"
+ " if (contactIndex>=0)\n"
+ " pairs[pairIndex].z = contactIndex;\n"
+ " return;\n"
+ " }\n"
+ " if (collidables[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&\n"
+ " collidables[collidableIndexB].m_shapeType == SHAPE_PLANE)\n"
+ " {\n"
+ " float4 posA;\n"
+ " posA = rigidBodies[bodyIndexA].m_pos;\n"
+ " Quaternion ornA;\n"
+ " ornA = rigidBodies[bodyIndexA].m_quat;\n"
+ " int contactIndex = computeContactPlaneConvex( pairIndex, bodyIndexB,bodyIndexA, collidableIndexB,collidableIndexA, \n"
+ " rigidBodies,collidables,convexShapes,vertices,indices,\n"
+ " faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,posA,ornA);\n"
+ " if (contactIndex>=0)\n"
+ " pairs[pairIndex].z = contactIndex;\n"
+ " return;\n"
+ " }\n"
+ " if (collidables[collidableIndexA].m_shapeType == SHAPE_PLANE &&\n"
+ " collidables[collidableIndexB].m_shapeType == SHAPE_SPHERE)\n"
+ " {\n"
+ " computeContactPlaneSphere(pairIndex, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB, \n"
+ " rigidBodies,collidables,faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity);\n"
+ " return;\n"
+ " }\n"
+ " if (collidables[collidableIndexA].m_shapeType == SHAPE_SPHERE &&\n"
+ " collidables[collidableIndexB].m_shapeType == SHAPE_PLANE)\n"
+ " {\n"
+ " computeContactPlaneSphere( pairIndex, bodyIndexB,bodyIndexA, collidableIndexB,collidableIndexA, \n"
+ " rigidBodies,collidables,\n"
+ " faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity);\n"
+ " return;\n"
+ " }\n"
+ " \n"
+ " \n"
+ " if (collidables[collidableIndexA].m_shapeType == SHAPE_SPHERE &&\n"
+ " collidables[collidableIndexB].m_shapeType == SHAPE_CONVEX_HULL)\n"
+ " {\n"
+ " \n"
+ " float4 spherePos = rigidBodies[bodyIndexA].m_pos;\n"
+ " float sphereRadius = collidables[collidableIndexA].m_radius;\n"
+ " float4 convexPos = rigidBodies[bodyIndexB].m_pos;\n"
+ " float4 convexOrn = rigidBodies[bodyIndexB].m_quat;\n"
+ " computeContactSphereConvex(pairIndex, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB, \n"
+ " rigidBodies,collidables,convexShapes,vertices,indices,faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,\n"
+ " spherePos,sphereRadius,convexPos,convexOrn);\n"
+ " return;\n"
+ " }\n"
+ " if (collidables[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&\n"
+ " collidables[collidableIndexB].m_shapeType == SHAPE_SPHERE)\n"
+ " {\n"
+ " \n"
+ " float4 spherePos = rigidBodies[bodyIndexB].m_pos;\n"
+ " float sphereRadius = collidables[collidableIndexB].m_radius;\n"
+ " float4 convexPos = rigidBodies[bodyIndexA].m_pos;\n"
+ " float4 convexOrn = rigidBodies[bodyIndexA].m_quat;\n"
+ " computeContactSphereConvex(pairIndex, bodyIndexB, bodyIndexA, collidableIndexB, collidableIndexA, \n"
+ " rigidBodies,collidables,convexShapes,vertices,indices,faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,\n"
+ " spherePos,sphereRadius,convexPos,convexOrn);\n"
+ " return;\n"
+ " }\n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " if (collidables[collidableIndexA].m_shapeType == SHAPE_SPHERE &&\n"
+ " collidables[collidableIndexB].m_shapeType == SHAPE_SPHERE)\n"
+ " {\n"
+ " //sphere-sphere\n"
+ " float radiusA = collidables[collidableIndexA].m_radius;\n"
+ " float radiusB = collidables[collidableIndexB].m_radius;\n"
+ " float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+ " float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+ " float4 diff = posA-posB;\n"
+ " float len = length(diff);\n"
+ " \n"
+ " ///iff distance positive, don't generate a new contact\n"
+ " if ( len <= (radiusA+radiusB))\n"
+ " {\n"
+ " ///distance (negative means penetration)\n"
+ " float dist = len - (radiusA+radiusB);\n"
+ " float4 normalOnSurfaceB = make_float4(1.f,0.f,0.f,0.f);\n"
+ " if (len > 0.00001)\n"
+ " {\n"
+ " normalOnSurfaceB = diff / len;\n"
+ " }\n"
+ " float4 contactPosB = posB + normalOnSurfaceB*radiusB;\n"
+ " contactPosB.w = dist;\n"
+ " \n"
+ " int dstIdx;\n"
+ " AppendInc( nGlobalContactsOut, dstIdx );\n"
+ " \n"
+ " if (dstIdx < maxContactCapacity)\n"
+ " {\n"
+ " __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];\n"
+ " c->m_worldNormalOnB = normalOnSurfaceB;\n"
+ " c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
+ " c->m_batchIdx = pairIndex;\n"
+ " int bodyA = pairs[pairIndex].x;\n"
+ " int bodyB = pairs[pairIndex].y;\n"
+ " c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;\n"
+ " c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;\n"
+ " c->m_worldPosB[0] = contactPosB;\n"
+ " c->m_childIndexA = -1;\n"
+ " c->m_childIndexB = -1;\n"
+ " GET_NPOINTS(*c) = 1;\n"
+ " }//if (dstIdx < numPairs)\n"
+ " }//if ( len <= (radiusA+radiusB))\n"
+ " return;\n"
+ " }//SHAPE_SPHERE SHAPE_SPHERE\n"
+ " }// if (i<numPairs)\n"
+ "}\n"
+ "// work-in-progress\n"
+ "__kernel void processCompoundPairsPrimitivesKernel( __global const int4* gpuCompoundPairs,\n"
+ " __global const BodyData* rigidBodies, \n"
+ " __global const btCollidableGpu* collidables,\n"
+ " __global const ConvexPolyhedronCL* convexShapes, \n"
+ " __global const float4* vertices,\n"
+ " __global const float4* uniqueEdges,\n"
+ " __global const btGpuFace* faces,\n"
+ " __global const int* indices,\n"
+ " __global btAabbCL* aabbs,\n"
+ " __global const btGpuChildShape* gpuChildShapes,\n"
+ " __global struct b3Contact4Data* restrict globalContactsOut,\n"
+ " counter32_t nGlobalContactsOut,\n"
+ " int numCompoundPairs, int maxContactCapacity\n"
+ " )\n"
+ "{\n"
+ " int i = get_global_id(0);\n"
+ " if (i<numCompoundPairs)\n"
+ " {\n"
+ " int bodyIndexA = gpuCompoundPairs[i].x;\n"
+ " int bodyIndexB = gpuCompoundPairs[i].y;\n"
+ " int childShapeIndexA = gpuCompoundPairs[i].z;\n"
+ " int childShapeIndexB = gpuCompoundPairs[i].w;\n"
+ " \n"
+ " int collidableIndexA = -1;\n"
+ " int collidableIndexB = -1;\n"
+ " \n"
+ " float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
+ " float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+ " \n"
+ " float4 ornB = rigidBodies[bodyIndexB].m_quat;\n"
+ " float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+ " \n"
+ " if (childShapeIndexA >= 0)\n"
+ " {\n"
+ " collidableIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;\n"
+ " float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;\n"
+ " float4 childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;\n"
+ " float4 newPosA = qtRotate(ornA,childPosA)+posA;\n"
+ " float4 newOrnA = qtMul(ornA,childOrnA);\n"
+ " posA = newPosA;\n"
+ " ornA = newOrnA;\n"
+ " } else\n"
+ " {\n"
+ " collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+ " }\n"
+ " \n"
+ " if (childShapeIndexB>=0)\n"
+ " {\n"
+ " collidableIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
+ " float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
+ " float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
+ " float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
+ " float4 newOrnB = qtMul(ornB,childOrnB);\n"
+ " posB = newPosB;\n"
+ " ornB = newOrnB;\n"
+ " } else\n"
+ " {\n"
+ " collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx; \n"
+ " }\n"
+ " \n"
+ " int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+ " int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+ " \n"
+ " int shapeTypeA = collidables[collidableIndexA].m_shapeType;\n"
+ " int shapeTypeB = collidables[collidableIndexB].m_shapeType;\n"
+ " int pairIndex = i;\n"
+ " if ((shapeTypeA == SHAPE_PLANE) && (shapeTypeB==SHAPE_CONVEX_HULL))\n"
+ " {\n"
+ " computeContactPlaneConvex( pairIndex, bodyIndexA,bodyIndexB, collidableIndexA,collidableIndexB, \n"
+ " rigidBodies,collidables,convexShapes,vertices,indices,\n"
+ " faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,posB,ornB);\n"
+ " return;\n"
+ " }\n"
+ " if ((shapeTypeA == SHAPE_CONVEX_HULL) && (shapeTypeB==SHAPE_PLANE))\n"
+ " {\n"
+ " computeContactPlaneConvex( pairIndex, bodyIndexB,bodyIndexA, collidableIndexB,collidableIndexA, \n"
+ " rigidBodies,collidables,convexShapes,vertices,indices,\n"
+ " faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,posA,ornA);\n"
+ " return;\n"
+ " }\n"
+ " if ((shapeTypeA == SHAPE_CONVEX_HULL) && (shapeTypeB == SHAPE_SPHERE))\n"
+ " {\n"
+ " float4 spherePos = rigidBodies[bodyIndexB].m_pos;\n"
+ " float sphereRadius = collidables[collidableIndexB].m_radius;\n"
+ " float4 convexPos = posA;\n"
+ " float4 convexOrn = ornA;\n"
+ " \n"
+ " computeContactSphereConvex(pairIndex, bodyIndexB, bodyIndexA , collidableIndexB,collidableIndexA, \n"
+ " rigidBodies,collidables,convexShapes,vertices,indices,faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,\n"
+ " spherePos,sphereRadius,convexPos,convexOrn);\n"
+ " \n"
+ " return;\n"
+ " }\n"
+ " if ((shapeTypeA == SHAPE_SPHERE) && (shapeTypeB == SHAPE_CONVEX_HULL))\n"
+ " {\n"
+ " float4 spherePos = rigidBodies[bodyIndexA].m_pos;\n"
+ " float sphereRadius = collidables[collidableIndexA].m_radius;\n"
+ " float4 convexPos = posB;\n"
+ " float4 convexOrn = ornB;\n"
+ " \n"
+ " computeContactSphereConvex(pairIndex, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB, \n"
+ " rigidBodies,collidables,convexShapes,vertices,indices,faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,\n"
+ " spherePos,sphereRadius,convexPos,convexOrn);\n"
+ " \n"
+ " return;\n"
+ " }\n"
+ " }// if (i<numCompoundPairs)\n"
+ "}\n"
+ "bool pointInTriangle(const float4* vertices, const float4* normal, float4 *p )\n"
+ "{\n"
+ " const float4* p1 = &vertices[0];\n"
+ " const float4* p2 = &vertices[1];\n"
+ " const float4* p3 = &vertices[2];\n"
+ " float4 edge1; edge1 = (*p2 - *p1);\n"
+ " float4 edge2; edge2 = ( *p3 - *p2 );\n"
+ " float4 edge3; edge3 = ( *p1 - *p3 );\n"
+ " \n"
+ " float4 p1_to_p; p1_to_p = ( *p - *p1 );\n"
+ " float4 p2_to_p; p2_to_p = ( *p - *p2 );\n"
+ " float4 p3_to_p; p3_to_p = ( *p - *p3 );\n"
+ " float4 edge1_normal; edge1_normal = ( cross(edge1,*normal));\n"
+ " float4 edge2_normal; edge2_normal = ( cross(edge2,*normal));\n"
+ " float4 edge3_normal; edge3_normal = ( cross(edge3,*normal));\n"
+ " \n"
+ " \n"
+ " float r1, r2, r3;\n"
+ " r1 = dot(edge1_normal,p1_to_p );\n"
+ " r2 = dot(edge2_normal,p2_to_p );\n"
+ " r3 = dot(edge3_normal,p3_to_p );\n"
+ " \n"
+ " if ( r1 > 0 && r2 > 0 && r3 > 0 )\n"
+ " return true;\n"
+ " if ( r1 <= 0 && r2 <= 0 && r3 <= 0 ) \n"
+ " return true;\n"
+ " return false;\n"
+ "}\n"
+ "float segmentSqrDistance(float4 from, float4 to,float4 p, float4* nearest) \n"
+ "{\n"
+ " float4 diff = p - from;\n"
+ " float4 v = to - from;\n"
+ " float t = dot(v,diff);\n"
+ " \n"
+ " if (t > 0) \n"
+ " {\n"
+ " float dotVV = dot(v,v);\n"
+ " if (t < dotVV) \n"
+ " {\n"
+ " t /= dotVV;\n"
+ " diff -= t*v;\n"
+ " } else \n"
+ " {\n"
+ " t = 1;\n"
+ " diff -= v;\n"
+ " }\n"
+ " } else\n"
+ " {\n"
+ " t = 0;\n"
+ " }\n"
+ " *nearest = from + t*v;\n"
+ " return dot(diff,diff); \n"
+ "}\n"
+ "void computeContactSphereTriangle(int pairIndex,\n"
+ " int bodyIndexA, int bodyIndexB,\n"
+ " int collidableIndexA, int collidableIndexB, \n"
+ " __global const BodyData* rigidBodies, \n"
+ " __global const btCollidableGpu* collidables,\n"
+ " const float4* triangleVertices,\n"
+ " __global struct b3Contact4Data* restrict globalContactsOut,\n"
+ " counter32_t nGlobalContactsOut,\n"
+ " int maxContactCapacity,\n"
+ " float4 spherePos2,\n"
+ " float radius,\n"
+ " float4 pos,\n"
+ " float4 quat,\n"
+ " int faceIndex\n"
+ " )\n"
+ "{\n"
+ " float4 invPos;\n"
+ " float4 invOrn;\n"
+ " trInverse(pos,quat, &invPos,&invOrn);\n"
+ " float4 spherePos = transform(&spherePos2,&invPos,&invOrn);\n"
+ " int numFaces = 3;\n"
+ " float4 closestPnt = (float4)(0, 0, 0, 0);\n"
+ " float4 hitNormalWorld = (float4)(0, 0, 0, 0);\n"
+ " float minDist = -1000000.f;\n"
+ " bool bCollide = false;\n"
+ " \n"
+ " //////////////////////////////////////\n"
+ " float4 sphereCenter;\n"
+ " sphereCenter = spherePos;\n"
+ " const float4* vertices = triangleVertices;\n"
+ " float contactBreakingThreshold = 0.f;//todo?\n"
+ " float radiusWithThreshold = radius + contactBreakingThreshold;\n"
+ " float4 edge10;\n"
+ " edge10 = vertices[1]-vertices[0];\n"
+ " edge10.w = 0.f;//is this needed?\n"
+ " float4 edge20;\n"
+ " edge20 = vertices[2]-vertices[0];\n"
+ " edge20.w = 0.f;//is this needed?\n"
+ " float4 normal = cross3(edge10,edge20);\n"
+ " normal = normalize(normal);\n"
+ " float4 p1ToCenter;\n"
+ " p1ToCenter = sphereCenter - vertices[0];\n"
+ " \n"
+ " float distanceFromPlane = dot(p1ToCenter,normal);\n"
+ " if (distanceFromPlane < 0.f)\n"
+ " {\n"
+ " //triangle facing the other way\n"
+ " distanceFromPlane *= -1.f;\n"
+ " normal *= -1.f;\n"
+ " }\n"
+ " hitNormalWorld = normal;\n"
+ " bool isInsideContactPlane = distanceFromPlane < radiusWithThreshold;\n"
+ " \n"
+ " // Check for contact / intersection\n"
+ " bool hasContact = false;\n"
+ " float4 contactPoint;\n"
+ " if (isInsideContactPlane) \n"
+ " {\n"
+ " \n"
+ " if (pointInTriangle(vertices,&normal, &sphereCenter)) \n"
+ " {\n"
+ " // Inside the contact wedge - touches a point on the shell plane\n"
+ " hasContact = true;\n"
+ " contactPoint = sphereCenter - normal*distanceFromPlane;\n"
+ " \n"
+ " } else {\n"
+ " // Could be inside one of the contact capsules\n"
+ " float contactCapsuleRadiusSqr = radiusWithThreshold*radiusWithThreshold;\n"
+ " float4 nearestOnEdge;\n"
+ " int numEdges = 3;\n"
+ " for (int i = 0; i < numEdges; i++) \n"
+ " {\n"
+ " float4 pa =vertices[i];\n"
+ " float4 pb = vertices[(i+1)%3];\n"
+ " float distanceSqr = segmentSqrDistance(pa,pb,sphereCenter, &nearestOnEdge);\n"
+ " if (distanceSqr < contactCapsuleRadiusSqr) \n"
+ " {\n"
+ " // Yep, we're inside a capsule\n"
+ " hasContact = true;\n"
+ " contactPoint = nearestOnEdge;\n"
+ " \n"
+ " }\n"
+ " \n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " if (hasContact) \n"
+ " {\n"
+ " closestPnt = contactPoint;\n"
+ " float4 contactToCenter = sphereCenter - contactPoint;\n"
+ " minDist = length(contactToCenter);\n"
+ " if (minDist>FLT_EPSILON)\n"
+ " {\n"
+ " hitNormalWorld = normalize(contactToCenter);//*(1./minDist);\n"
+ " bCollide = true;\n"
+ " }\n"
+ " \n"
+ " }\n"
+ " /////////////////////////////////////\n"
+ " if (bCollide && minDist > -10000)\n"
+ " {\n"
+ " \n"
+ " float4 normalOnSurfaceB1 = qtRotate(quat,-hitNormalWorld);\n"
+ " float4 pOnB1 = transform(&closestPnt,&pos,&quat);\n"
+ " float actualDepth = minDist-radius;\n"
+ " \n"
+ " if (actualDepth<=0.f)\n"
+ " {\n"
+ " pOnB1.w = actualDepth;\n"
+ " int dstIdx;\n"
+ " \n"
+ " float lenSqr = dot3F4(normalOnSurfaceB1,normalOnSurfaceB1);\n"
+ " if (lenSqr>FLT_EPSILON)\n"
+ " {\n"
+ " AppendInc( nGlobalContactsOut, dstIdx );\n"
+ " \n"
+ " if (dstIdx < maxContactCapacity)\n"
+ " {\n"
+ " __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];\n"
+ " c->m_worldNormalOnB = -normalOnSurfaceB1;\n"
+ " c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
+ " c->m_batchIdx = pairIndex;\n"
+ " c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;\n"
+ " c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;\n"
+ " c->m_worldPosB[0] = pOnB1;\n"
+ " c->m_childIndexA = -1;\n"
+ " c->m_childIndexB = faceIndex;\n"
+ " GET_NPOINTS(*c) = 1;\n"
+ " } \n"
+ " }\n"
+ " }\n"
+ " }//if (hasCollision)\n"
+ "}\n"
+ "// work-in-progress\n"
+ "__kernel void findConcaveSphereContactsKernel( __global int4* concavePairs,\n"
+ " __global const BodyData* rigidBodies,\n"
+ " __global const btCollidableGpu* collidables,\n"
+ " __global const ConvexPolyhedronCL* convexShapes, \n"
+ " __global const float4* vertices,\n"
+ " __global const float4* uniqueEdges,\n"
+ " __global const btGpuFace* faces,\n"
+ " __global const int* indices,\n"
+ " __global btAabbCL* aabbs,\n"
+ " __global struct b3Contact4Data* restrict globalContactsOut,\n"
+ " counter32_t nGlobalContactsOut,\n"
+ " int numConcavePairs, int maxContactCapacity\n"
+ " )\n"
+ "{\n"
+ " int i = get_global_id(0);\n"
+ " if (i>=numConcavePairs)\n"
+ " return;\n"
+ " int pairIdx = i;\n"
+ " int bodyIndexA = concavePairs[i].x;\n"
+ " int bodyIndexB = concavePairs[i].y;\n"
+ " int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+ " int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+ " int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+ " int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+ " if (collidables[collidableIndexB].m_shapeType==SHAPE_SPHERE)\n"
+ " {\n"
+ " int f = concavePairs[i].z;\n"
+ " btGpuFace face = faces[convexShapes[shapeIndexA].m_faceOffset+f];\n"
+ " \n"
+ " float4 verticesA[3];\n"
+ " for (int i=0;i<3;i++)\n"
+ " {\n"
+ " int index = indices[face.m_indexOffset+i];\n"
+ " float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];\n"
+ " verticesA[i] = vert;\n"
+ " }\n"
+ " float4 spherePos = rigidBodies[bodyIndexB].m_pos;\n"
+ " float sphereRadius = collidables[collidableIndexB].m_radius;\n"
+ " float4 convexPos = rigidBodies[bodyIndexA].m_pos;\n"
+ " float4 convexOrn = rigidBodies[bodyIndexA].m_quat;\n"
+ " computeContactSphereTriangle(i, bodyIndexB, bodyIndexA, collidableIndexB, collidableIndexA, \n"
+ " rigidBodies,collidables,\n"
+ " verticesA,\n"
+ " globalContactsOut, nGlobalContactsOut,maxContactCapacity,\n"
+ " spherePos,sphereRadius,convexPos,convexOrn, f);\n"
+ " return;\n"
+ " }\n"
+ "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/satClipHullContacts.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/satClipHullContacts.h
index f0ecfc7851..907809d8bd 100644
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/satClipHullContacts.h
+++ b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/satClipHullContacts.h
@@ -1,2099 +1,2098 @@
//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* satClipKernelsCL= \
-"#define TRIANGLE_NUM_CONVEX_FACES 5\n"
-"#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
-"#ifdef cl_ext_atomic_counters_32\n"
-"#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
-"#else\n"
-"#define counter32_t volatile __global int*\n"
-"#endif\n"
-"#define GET_GROUP_IDX get_group_id(0)\n"
-"#define GET_LOCAL_IDX get_local_id(0)\n"
-"#define GET_GLOBAL_IDX get_global_id(0)\n"
-"#define GET_GROUP_SIZE get_local_size(0)\n"
-"#define GET_NUM_GROUPS get_num_groups(0)\n"
-"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
-"#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
-"#define AtomInc(x) atom_inc(&(x))\n"
-"#define AtomInc1(x, out) out = atom_inc(&(x))\n"
-"#define AppendInc(x, out) out = atomic_inc(x)\n"
-"#define AtomAdd(x, value) atom_add(&(x), value)\n"
-"#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
-"#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
-"#define max2 max\n"
-"#define min2 min\n"
-"typedef unsigned int u32;\n"
-"#ifndef B3_CONTACT4DATA_H\n"
-"#define B3_CONTACT4DATA_H\n"
-"#ifndef B3_FLOAT4_H\n"
-"#define B3_FLOAT4_H\n"
-"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
-"#define B3_PLATFORM_DEFINITIONS_H\n"
-"struct MyTest\n"
-"{\n"
-" int bla;\n"
-"};\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
-"#define B3_LARGE_FLOAT 1e18f\n"
-"#define B3_INFINITY 1e18f\n"
-"#define b3Assert(a)\n"
-"#define b3ConstArray(a) __global const a*\n"
-"#define b3AtomicInc atomic_inc\n"
-"#define b3AtomicAdd atomic_add\n"
-"#define b3Fabs fabs\n"
-"#define b3Sqrt native_sqrt\n"
-"#define b3Sin native_sin\n"
-"#define b3Cos native_cos\n"
-"#define B3_STATIC\n"
-"#endif\n"
-"#endif\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-" typedef float4 b3Float4;\n"
-" #define b3Float4ConstArg const b3Float4\n"
-" #define b3MakeFloat4 (float4)\n"
-" float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
-" {\n"
-" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
-" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
-" return dot(a1, b1);\n"
-" }\n"
-" b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
-" {\n"
-" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
-" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
-" return cross(a1, b1);\n"
-" }\n"
-" #define b3MinFloat4 min\n"
-" #define b3MaxFloat4 max\n"
-" #define b3Normalized(a) normalize(a)\n"
-"#endif \n"
-" \n"
-"inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
-"{\n"
-" if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
-" return false;\n"
-" return true;\n"
-"}\n"
-"inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
-"{\n"
-" float maxDot = -B3_INFINITY;\n"
-" int i = 0;\n"
-" int ptIndex = -1;\n"
-" for( i = 0; i < vecLen; i++ )\n"
-" {\n"
-" float dot = b3Dot3F4(vecArray[i],vec);\n"
-" \n"
-" if( dot > maxDot )\n"
-" {\n"
-" maxDot = dot;\n"
-" ptIndex = i;\n"
-" }\n"
-" }\n"
-" b3Assert(ptIndex>=0);\n"
-" if (ptIndex<0)\n"
-" {\n"
-" ptIndex = 0;\n"
-" }\n"
-" *dotOut = maxDot;\n"
-" return ptIndex;\n"
-"}\n"
-"#endif //B3_FLOAT4_H\n"
-"typedef struct b3Contact4Data b3Contact4Data_t;\n"
-"struct b3Contact4Data\n"
-"{\n"
-" b3Float4 m_worldPosB[4];\n"
-"// b3Float4 m_localPosA[4];\n"
-"// b3Float4 m_localPosB[4];\n"
-" b3Float4 m_worldNormalOnB; // w: m_nPoints\n"
-" unsigned short m_restituitionCoeffCmp;\n"
-" unsigned short m_frictionCoeffCmp;\n"
-" int m_batchIdx;\n"
-" int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
-" int m_bodyBPtrAndSignBit;\n"
-" int m_childIndexA;\n"
-" int m_childIndexB;\n"
-" int m_unused1;\n"
-" int m_unused2;\n"
-"};\n"
-"inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
-"{\n"
-" return (int)contact->m_worldNormalOnB.w;\n"
-"};\n"
-"inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
-"{\n"
-" contact->m_worldNormalOnB.w = (float)numPoints;\n"
-"};\n"
-"#endif //B3_CONTACT4DATA_H\n"
-"#ifndef B3_CONVEX_POLYHEDRON_DATA_H\n"
-"#define B3_CONVEX_POLYHEDRON_DATA_H\n"
-"#ifndef B3_FLOAT4_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#endif \n"
-"#endif //B3_FLOAT4_H\n"
-"#ifndef B3_QUAT_H\n"
-"#define B3_QUAT_H\n"
-"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#endif\n"
-"#endif\n"
-"#ifndef B3_FLOAT4_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#endif \n"
-"#endif //B3_FLOAT4_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-" typedef float4 b3Quat;\n"
-" #define b3QuatConstArg const b3Quat\n"
-" \n"
-" \n"
-"inline float4 b3FastNormalize4(float4 v)\n"
-"{\n"
-" v = (float4)(v.xyz,0.f);\n"
-" return fast_normalize(v);\n"
-"}\n"
-" \n"
-"inline b3Quat b3QuatMul(b3Quat a, b3Quat b);\n"
-"inline b3Quat b3QuatNormalized(b3QuatConstArg in);\n"
-"inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec);\n"
-"inline b3Quat b3QuatInvert(b3QuatConstArg q);\n"
-"inline b3Quat b3QuatInverse(b3QuatConstArg q);\n"
-"inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b)\n"
-"{\n"
-" b3Quat ans;\n"
-" ans = b3Cross3( a, b );\n"
-" ans += a.w*b+b.w*a;\n"
-"// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
-" ans.w = a.w*b.w - b3Dot3F4(a, b);\n"
-" return ans;\n"
-"}\n"
-"inline b3Quat b3QuatNormalized(b3QuatConstArg in)\n"
-"{\n"
-" b3Quat q;\n"
-" q=in;\n"
-" //return b3FastNormalize4(in);\n"
-" float len = native_sqrt(dot(q, q));\n"
-" if(len > 0.f)\n"
-" {\n"
-" q *= 1.f / len;\n"
-" }\n"
-" else\n"
-" {\n"
-" q.x = q.y = q.z = 0.f;\n"
-" q.w = 1.f;\n"
-" }\n"
-" return q;\n"
-"}\n"
-"inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
-"{\n"
-" b3Quat qInv = b3QuatInvert( q );\n"
-" float4 vcpy = vec;\n"
-" vcpy.w = 0.f;\n"
-" float4 out = b3QuatMul(b3QuatMul(q,vcpy),qInv);\n"
-" return out;\n"
-"}\n"
-"inline b3Quat b3QuatInverse(b3QuatConstArg q)\n"
-"{\n"
-" return (b3Quat)(-q.xyz, q.w);\n"
-"}\n"
-"inline b3Quat b3QuatInvert(b3QuatConstArg q)\n"
-"{\n"
-" return (b3Quat)(-q.xyz, q.w);\n"
-"}\n"
-"inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
-"{\n"
-" return b3QuatRotate( b3QuatInvert( q ), vec );\n"
-"}\n"
-"inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation)\n"
-"{\n"
-" return b3QuatRotate( orientation, point ) + (translation);\n"
-"}\n"
-" \n"
-"#endif \n"
-"#endif //B3_QUAT_H\n"
-"typedef struct b3GpuFace b3GpuFace_t;\n"
-"struct b3GpuFace\n"
-"{\n"
-" b3Float4 m_plane;\n"
-" int m_indexOffset;\n"
-" int m_numIndices;\n"
-" int m_unusedPadding1;\n"
-" int m_unusedPadding2;\n"
-"};\n"
-"typedef struct b3ConvexPolyhedronData b3ConvexPolyhedronData_t;\n"
-"struct b3ConvexPolyhedronData\n"
-"{\n"
-" b3Float4 m_localCenter;\n"
-" b3Float4 m_extents;\n"
-" b3Float4 mC;\n"
-" b3Float4 mE;\n"
-" float m_radius;\n"
-" int m_faceOffset;\n"
-" int m_numFaces;\n"
-" int m_numVertices;\n"
-" int m_vertexOffset;\n"
-" int m_uniqueEdgesOffset;\n"
-" int m_numUniqueEdges;\n"
-" int m_unused;\n"
-"};\n"
-"#endif //B3_CONVEX_POLYHEDRON_DATA_H\n"
-"#ifndef B3_COLLIDABLE_H\n"
-"#define B3_COLLIDABLE_H\n"
-"#ifndef B3_FLOAT4_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#endif \n"
-"#endif //B3_FLOAT4_H\n"
-"#ifndef B3_QUAT_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#endif \n"
-"#endif //B3_QUAT_H\n"
-"enum b3ShapeTypes\n"
-"{\n"
-" SHAPE_HEIGHT_FIELD=1,\n"
-" SHAPE_CONVEX_HULL=3,\n"
-" SHAPE_PLANE=4,\n"
-" SHAPE_CONCAVE_TRIMESH=5,\n"
-" SHAPE_COMPOUND_OF_CONVEX_HULLS=6,\n"
-" SHAPE_SPHERE=7,\n"
-" MAX_NUM_SHAPE_TYPES,\n"
-"};\n"
-"typedef struct b3Collidable b3Collidable_t;\n"
-"struct b3Collidable\n"
-"{\n"
-" union {\n"
-" int m_numChildShapes;\n"
-" int m_bvhIndex;\n"
-" };\n"
-" union\n"
-" {\n"
-" float m_radius;\n"
-" int m_compoundBvhIndex;\n"
-" };\n"
-" int m_shapeType;\n"
-" int m_shapeIndex;\n"
-"};\n"
-"typedef struct b3GpuChildShape b3GpuChildShape_t;\n"
-"struct b3GpuChildShape\n"
-"{\n"
-" b3Float4 m_childPosition;\n"
-" b3Quat m_childOrientation;\n"
-" int m_shapeIndex;\n"
-" int m_unused0;\n"
-" int m_unused1;\n"
-" int m_unused2;\n"
-"};\n"
-"struct b3CompoundOverlappingPair\n"
-"{\n"
-" int m_bodyIndexA;\n"
-" int m_bodyIndexB;\n"
-"// int m_pairType;\n"
-" int m_childShapeIndexA;\n"
-" int m_childShapeIndexB;\n"
-"};\n"
-"#endif //B3_COLLIDABLE_H\n"
-"#ifndef B3_RIGIDBODY_DATA_H\n"
-"#define B3_RIGIDBODY_DATA_H\n"
-"#ifndef B3_FLOAT4_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#endif \n"
-"#endif //B3_FLOAT4_H\n"
-"#ifndef B3_QUAT_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#endif \n"
-"#endif //B3_QUAT_H\n"
-"#ifndef B3_MAT3x3_H\n"
-"#define B3_MAT3x3_H\n"
-"#ifndef B3_QUAT_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#endif \n"
-"#endif //B3_QUAT_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"typedef struct\n"
-"{\n"
-" b3Float4 m_row[3];\n"
-"}b3Mat3x3;\n"
-"#define b3Mat3x3ConstArg const b3Mat3x3\n"
-"#define b3GetRow(m,row) (m.m_row[row])\n"
-"inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat)\n"
-"{\n"
-" b3Float4 quat2 = (b3Float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);\n"
-" b3Mat3x3 out;\n"
-" out.m_row[0].x=1-2*quat2.y-2*quat2.z;\n"
-" out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;\n"
-" out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;\n"
-" out.m_row[0].w = 0.f;\n"
-" out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;\n"
-" out.m_row[1].y=1-2*quat2.x-2*quat2.z;\n"
-" out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;\n"
-" out.m_row[1].w = 0.f;\n"
-" out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;\n"
-" out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;\n"
-" out.m_row[2].z=1-2*quat2.x-2*quat2.y;\n"
-" out.m_row[2].w = 0.f;\n"
-" return out;\n"
-"}\n"
-"inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn)\n"
-"{\n"
-" b3Mat3x3 out;\n"
-" out.m_row[0] = fabs(matIn.m_row[0]);\n"
-" out.m_row[1] = fabs(matIn.m_row[1]);\n"
-" out.m_row[2] = fabs(matIn.m_row[2]);\n"
-" return out;\n"
-"}\n"
-"__inline\n"
-"b3Mat3x3 mtZero();\n"
-"__inline\n"
-"b3Mat3x3 mtIdentity();\n"
-"__inline\n"
-"b3Mat3x3 mtTranspose(b3Mat3x3 m);\n"
-"__inline\n"
-"b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);\n"
-"__inline\n"
-"b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);\n"
-"__inline\n"
-"b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);\n"
-"__inline\n"
-"b3Mat3x3 mtZero()\n"
-"{\n"
-" b3Mat3x3 m;\n"
-" m.m_row[0] = (b3Float4)(0.f);\n"
-" m.m_row[1] = (b3Float4)(0.f);\n"
-" m.m_row[2] = (b3Float4)(0.f);\n"
-" return m;\n"
-"}\n"
-"__inline\n"
-"b3Mat3x3 mtIdentity()\n"
-"{\n"
-" b3Mat3x3 m;\n"
-" m.m_row[0] = (b3Float4)(1,0,0,0);\n"
-" m.m_row[1] = (b3Float4)(0,1,0,0);\n"
-" m.m_row[2] = (b3Float4)(0,0,1,0);\n"
-" return m;\n"
-"}\n"
-"__inline\n"
-"b3Mat3x3 mtTranspose(b3Mat3x3 m)\n"
-"{\n"
-" b3Mat3x3 out;\n"
-" out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
-" out.m_row[1] = (b3Float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
-" out.m_row[2] = (b3Float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
-" return out;\n"
-"}\n"
-"__inline\n"
-"b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)\n"
-"{\n"
-" b3Mat3x3 transB;\n"
-" transB = mtTranspose( b );\n"
-" b3Mat3x3 ans;\n"
-" // why this doesn't run when 0ing in the for{}\n"
-" a.m_row[0].w = 0.f;\n"
-" a.m_row[1].w = 0.f;\n"
-" a.m_row[2].w = 0.f;\n"
-" for(int i=0; i<3; i++)\n"
-" {\n"
-"// a.m_row[i].w = 0.f;\n"
-" ans.m_row[i].x = b3Dot3F4(a.m_row[i],transB.m_row[0]);\n"
-" ans.m_row[i].y = b3Dot3F4(a.m_row[i],transB.m_row[1]);\n"
-" ans.m_row[i].z = b3Dot3F4(a.m_row[i],transB.m_row[2]);\n"
-" ans.m_row[i].w = 0.f;\n"
-" }\n"
-" return ans;\n"
-"}\n"
-"__inline\n"
-"b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)\n"
-"{\n"
-" b3Float4 ans;\n"
-" ans.x = b3Dot3F4( a.m_row[0], b );\n"
-" ans.y = b3Dot3F4( a.m_row[1], b );\n"
-" ans.z = b3Dot3F4( a.m_row[2], b );\n"
-" ans.w = 0.f;\n"
-" return ans;\n"
-"}\n"
-"__inline\n"
-"b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)\n"
-"{\n"
-" b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
-" b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
-" b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
-" b3Float4 ans;\n"
-" ans.x = b3Dot3F4( a, colx );\n"
-" ans.y = b3Dot3F4( a, coly );\n"
-" ans.z = b3Dot3F4( a, colz );\n"
-" return ans;\n"
-"}\n"
-"#endif\n"
-"#endif //B3_MAT3x3_H\n"
-"typedef struct b3RigidBodyData b3RigidBodyData_t;\n"
-"struct b3RigidBodyData\n"
-"{\n"
-" b3Float4 m_pos;\n"
-" b3Quat m_quat;\n"
-" b3Float4 m_linVel;\n"
-" b3Float4 m_angVel;\n"
-" int m_collidableIdx;\n"
-" float m_invMass;\n"
-" float m_restituitionCoeff;\n"
-" float m_frictionCoeff;\n"
-"};\n"
-"typedef struct b3InertiaData b3InertiaData_t;\n"
-"struct b3InertiaData\n"
-"{\n"
-" b3Mat3x3 m_invInertiaWorld;\n"
-" b3Mat3x3 m_initInvInertia;\n"
-"};\n"
-"#endif //B3_RIGIDBODY_DATA_H\n"
-" \n"
-"#define GET_NPOINTS(x) (x).m_worldNormalOnB.w\n"
-"#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
-"#define make_float4 (float4)\n"
-"#define make_float2 (float2)\n"
-"#define make_uint4 (uint4)\n"
-"#define make_int4 (int4)\n"
-"#define make_uint2 (uint2)\n"
-"#define make_int2 (int2)\n"
-"__inline\n"
-"float fastDiv(float numerator, float denominator)\n"
-"{\n"
-" return native_divide(numerator, denominator); \n"
-"// return numerator/denominator; \n"
-"}\n"
-"__inline\n"
-"float4 fastDiv4(float4 numerator, float4 denominator)\n"
-"{\n"
-" return native_divide(numerator, denominator); \n"
-"}\n"
-"__inline\n"
-"float4 cross3(float4 a, float4 b)\n"
-"{\n"
-" return cross(a,b);\n"
-"}\n"
-"//#define dot3F4 dot\n"
-"__inline\n"
-"float dot3F4(float4 a, float4 b)\n"
-"{\n"
-" float4 a1 = make_float4(a.xyz,0.f);\n"
-" float4 b1 = make_float4(b.xyz,0.f);\n"
-" return dot(a1, b1);\n"
-"}\n"
-"__inline\n"
-"float4 fastNormalize4(float4 v)\n"
-"{\n"
-" return fast_normalize(v);\n"
-"}\n"
-"///////////////////////////////////////\n"
-"// Quaternion\n"
-"///////////////////////////////////////\n"
-"typedef float4 Quaternion;\n"
-"__inline\n"
-"Quaternion qtMul(Quaternion a, Quaternion b);\n"
-"__inline\n"
-"Quaternion qtNormalize(Quaternion in);\n"
-"__inline\n"
-"float4 qtRotate(Quaternion q, float4 vec);\n"
-"__inline\n"
-"Quaternion qtInvert(Quaternion q);\n"
-"__inline\n"
-"Quaternion qtMul(Quaternion a, Quaternion b)\n"
-"{\n"
-" Quaternion ans;\n"
-" ans = cross3( a, b );\n"
-" ans += a.w*b+b.w*a;\n"
-"// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
-" ans.w = a.w*b.w - dot3F4(a, b);\n"
-" return ans;\n"
-"}\n"
-"__inline\n"
-"Quaternion qtNormalize(Quaternion in)\n"
-"{\n"
-" return fastNormalize4(in);\n"
-"// in /= length( in );\n"
-"// return in;\n"
-"}\n"
-"__inline\n"
-"float4 qtRotate(Quaternion q, float4 vec)\n"
-"{\n"
-" Quaternion qInv = qtInvert( q );\n"
-" float4 vcpy = vec;\n"
-" vcpy.w = 0.f;\n"
-" float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
-" return out;\n"
-"}\n"
-"__inline\n"
-"Quaternion qtInvert(Quaternion q)\n"
-"{\n"
-" return (Quaternion)(-q.xyz, q.w);\n"
-"}\n"
-"__inline\n"
-"float4 qtInvRotate(const Quaternion q, float4 vec)\n"
-"{\n"
-" return qtRotate( qtInvert( q ), vec );\n"
-"}\n"
-"__inline\n"
-"float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)\n"
-"{\n"
-" return qtRotate( *orientation, *p ) + (*translation);\n"
-"}\n"
-"__inline\n"
-"float4 normalize3(const float4 a)\n"
-"{\n"
-" float4 n = make_float4(a.x, a.y, a.z, 0.f);\n"
-" return fastNormalize4( n );\n"
-"}\n"
-"__inline float4 lerp3(const float4 a,const float4 b, float t)\n"
-"{\n"
-" return make_float4( a.x + (b.x - a.x) * t,\n"
-" a.y + (b.y - a.y) * t,\n"
-" a.z + (b.z - a.z) * t,\n"
-" 0.f);\n"
-"}\n"
-"// Clips a face to the back of a plane, return the number of vertices out, stored in ppVtxOut\n"
-"int clipFaceGlobal(__global const float4* pVtxIn, int numVertsIn, float4 planeNormalWS,float planeEqWS, __global float4* ppVtxOut)\n"
-"{\n"
-" \n"
-" int ve;\n"
-" float ds, de;\n"
-" int numVertsOut = 0;\n"
-" //double-check next test\n"
-" if (numVertsIn < 2)\n"
-" return 0;\n"
-" \n"
-" float4 firstVertex=pVtxIn[numVertsIn-1];\n"
-" float4 endVertex = pVtxIn[0];\n"
-" \n"
-" ds = dot3F4(planeNormalWS,firstVertex)+planeEqWS;\n"
-" \n"
-" for (ve = 0; ve < numVertsIn; ve++)\n"
-" {\n"
-" endVertex=pVtxIn[ve];\n"
-" de = dot3F4(planeNormalWS,endVertex)+planeEqWS;\n"
-" if (ds<0)\n"
-" {\n"
-" if (de<0)\n"
-" {\n"
-" // Start < 0, end < 0, so output endVertex\n"
-" ppVtxOut[numVertsOut++] = endVertex;\n"
-" }\n"
-" else\n"
-" {\n"
-" // Start < 0, end >= 0, so output intersection\n"
-" ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );\n"
-" }\n"
-" }\n"
-" else\n"
-" {\n"
-" if (de<0)\n"
-" {\n"
-" // Start >= 0, end < 0 so output intersection and end\n"
-" ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );\n"
-" ppVtxOut[numVertsOut++] = endVertex;\n"
-" }\n"
-" }\n"
-" firstVertex = endVertex;\n"
-" ds = de;\n"
-" }\n"
-" return numVertsOut;\n"
-"}\n"
-"// Clips a face to the back of a plane, return the number of vertices out, stored in ppVtxOut\n"
-"int clipFace(const float4* pVtxIn, int numVertsIn, float4 planeNormalWS,float planeEqWS, float4* ppVtxOut)\n"
-"{\n"
-" \n"
-" int ve;\n"
-" float ds, de;\n"
-" int numVertsOut = 0;\n"
-"//double-check next test\n"
-" if (numVertsIn < 2)\n"
-" return 0;\n"
-" float4 firstVertex=pVtxIn[numVertsIn-1];\n"
-" float4 endVertex = pVtxIn[0];\n"
-" \n"
-" ds = dot3F4(planeNormalWS,firstVertex)+planeEqWS;\n"
-" for (ve = 0; ve < numVertsIn; ve++)\n"
-" {\n"
-" endVertex=pVtxIn[ve];\n"
-" de = dot3F4(planeNormalWS,endVertex)+planeEqWS;\n"
-" if (ds<0)\n"
-" {\n"
-" if (de<0)\n"
-" {\n"
-" // Start < 0, end < 0, so output endVertex\n"
-" ppVtxOut[numVertsOut++] = endVertex;\n"
-" }\n"
-" else\n"
-" {\n"
-" // Start < 0, end >= 0, so output intersection\n"
-" ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );\n"
-" }\n"
-" }\n"
-" else\n"
-" {\n"
-" if (de<0)\n"
-" {\n"
-" // Start >= 0, end < 0 so output intersection and end\n"
-" ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );\n"
-" ppVtxOut[numVertsOut++] = endVertex;\n"
-" }\n"
-" }\n"
-" firstVertex = endVertex;\n"
-" ds = de;\n"
-" }\n"
-" return numVertsOut;\n"
-"}\n"
-"int clipFaceAgainstHull(const float4 separatingNormal, __global const b3ConvexPolyhedronData_t* hullA, \n"
-" const float4 posA, const Quaternion ornA, float4* worldVertsB1, int numWorldVertsB1,\n"
-" float4* worldVertsB2, int capacityWorldVertsB2,\n"
-" const float minDist, float maxDist,\n"
-" __global const float4* vertices,\n"
-" __global const b3GpuFace_t* faces,\n"
-" __global const int* indices,\n"
-" float4* contactsOut,\n"
-" int contactCapacity)\n"
-"{\n"
-" int numContactsOut = 0;\n"
-" float4* pVtxIn = worldVertsB1;\n"
-" float4* pVtxOut = worldVertsB2;\n"
-" \n"
-" int numVertsIn = numWorldVertsB1;\n"
-" int numVertsOut = 0;\n"
-" int closestFaceA=-1;\n"
-" {\n"
-" float dmin = FLT_MAX;\n"
-" for(int face=0;face<hullA->m_numFaces;face++)\n"
-" {\n"
-" const float4 Normal = make_float4(\n"
-" faces[hullA->m_faceOffset+face].m_plane.x, \n"
-" faces[hullA->m_faceOffset+face].m_plane.y, \n"
-" faces[hullA->m_faceOffset+face].m_plane.z,0.f);\n"
-" const float4 faceANormalWS = qtRotate(ornA,Normal);\n"
-" \n"
-" float d = dot3F4(faceANormalWS,separatingNormal);\n"
-" if (d < dmin)\n"
-" {\n"
-" dmin = d;\n"
-" closestFaceA = face;\n"
-" }\n"
-" }\n"
-" }\n"
-" if (closestFaceA<0)\n"
-" return numContactsOut;\n"
-" b3GpuFace_t polyA = faces[hullA->m_faceOffset+closestFaceA];\n"
-" // clip polygon to back of planes of all faces of hull A that are adjacent to witness face\n"
-" int numVerticesA = polyA.m_numIndices;\n"
-" for(int e0=0;e0<numVerticesA;e0++)\n"
-" {\n"
-" const float4 a = vertices[hullA->m_vertexOffset+indices[polyA.m_indexOffset+e0]];\n"
-" const float4 b = vertices[hullA->m_vertexOffset+indices[polyA.m_indexOffset+((e0+1)%numVerticesA)]];\n"
-" const float4 edge0 = a - b;\n"
-" const float4 WorldEdge0 = qtRotate(ornA,edge0);\n"
-" float4 planeNormalA = make_float4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);\n"
-" float4 worldPlaneAnormal1 = qtRotate(ornA,planeNormalA);\n"
-" float4 planeNormalWS1 = -cross3(WorldEdge0,worldPlaneAnormal1);\n"
-" float4 worldA1 = transform(&a,&posA,&ornA);\n"
-" float planeEqWS1 = -dot3F4(worldA1,planeNormalWS1);\n"
-" \n"
-" float4 planeNormalWS = planeNormalWS1;\n"
-" float planeEqWS=planeEqWS1;\n"
-" \n"
-" //clip face\n"
-" //clipFace(*pVtxIn, *pVtxOut,planeNormalWS,planeEqWS);\n"
-" numVertsOut = clipFace(pVtxIn, numVertsIn, planeNormalWS,planeEqWS, pVtxOut);\n"
-" //btSwap(pVtxIn,pVtxOut);\n"
-" float4* tmp = pVtxOut;\n"
-" pVtxOut = pVtxIn;\n"
-" pVtxIn = tmp;\n"
-" numVertsIn = numVertsOut;\n"
-" numVertsOut = 0;\n"
-" }\n"
-" \n"
-" // only keep points that are behind the witness face\n"
-" {\n"
-" float4 localPlaneNormal = make_float4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);\n"
-" float localPlaneEq = polyA.m_plane.w;\n"
-" float4 planeNormalWS = qtRotate(ornA,localPlaneNormal);\n"
-" float planeEqWS=localPlaneEq-dot3F4(planeNormalWS,posA);\n"
-" for (int i=0;i<numVertsIn;i++)\n"
-" {\n"
-" float depth = dot3F4(planeNormalWS,pVtxIn[i])+planeEqWS;\n"
-" if (depth <=minDist)\n"
-" {\n"
-" depth = minDist;\n"
-" }\n"
-" if (depth <=maxDist)\n"
-" {\n"
-" float4 pointInWorld = pVtxIn[i];\n"
-" //resultOut.addContactPoint(separatingNormal,point,depth);\n"
-" contactsOut[numContactsOut++] = make_float4(pointInWorld.x,pointInWorld.y,pointInWorld.z,depth);\n"
-" }\n"
-" }\n"
-" }\n"
-" return numContactsOut;\n"
-"}\n"
-"int clipFaceAgainstHullLocalA(const float4 separatingNormal, const b3ConvexPolyhedronData_t* hullA, \n"
-" const float4 posA, const Quaternion ornA, float4* worldVertsB1, int numWorldVertsB1,\n"
-" float4* worldVertsB2, int capacityWorldVertsB2,\n"
-" const float minDist, float maxDist,\n"
-" const float4* verticesA,\n"
-" const b3GpuFace_t* facesA,\n"
-" const int* indicesA,\n"
-" __global const float4* verticesB,\n"
-" __global const b3GpuFace_t* facesB,\n"
-" __global const int* indicesB,\n"
-" float4* contactsOut,\n"
-" int contactCapacity)\n"
-"{\n"
-" int numContactsOut = 0;\n"
-" float4* pVtxIn = worldVertsB1;\n"
-" float4* pVtxOut = worldVertsB2;\n"
-" \n"
-" int numVertsIn = numWorldVertsB1;\n"
-" int numVertsOut = 0;\n"
-" int closestFaceA=-1;\n"
-" {\n"
-" float dmin = FLT_MAX;\n"
-" for(int face=0;face<hullA->m_numFaces;face++)\n"
-" {\n"
-" const float4 Normal = make_float4(\n"
-" facesA[hullA->m_faceOffset+face].m_plane.x, \n"
-" facesA[hullA->m_faceOffset+face].m_plane.y, \n"
-" facesA[hullA->m_faceOffset+face].m_plane.z,0.f);\n"
-" const float4 faceANormalWS = qtRotate(ornA,Normal);\n"
-" \n"
-" float d = dot3F4(faceANormalWS,separatingNormal);\n"
-" if (d < dmin)\n"
-" {\n"
-" dmin = d;\n"
-" closestFaceA = face;\n"
-" }\n"
-" }\n"
-" }\n"
-" if (closestFaceA<0)\n"
-" return numContactsOut;\n"
-" b3GpuFace_t polyA = facesA[hullA->m_faceOffset+closestFaceA];\n"
-" // clip polygon to back of planes of all faces of hull A that are adjacent to witness face\n"
-" int numVerticesA = polyA.m_numIndices;\n"
-" for(int e0=0;e0<numVerticesA;e0++)\n"
-" {\n"
-" const float4 a = verticesA[hullA->m_vertexOffset+indicesA[polyA.m_indexOffset+e0]];\n"
-" const float4 b = verticesA[hullA->m_vertexOffset+indicesA[polyA.m_indexOffset+((e0+1)%numVerticesA)]];\n"
-" const float4 edge0 = a - b;\n"
-" const float4 WorldEdge0 = qtRotate(ornA,edge0);\n"
-" float4 planeNormalA = make_float4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);\n"
-" float4 worldPlaneAnormal1 = qtRotate(ornA,planeNormalA);\n"
-" float4 planeNormalWS1 = -cross3(WorldEdge0,worldPlaneAnormal1);\n"
-" float4 worldA1 = transform(&a,&posA,&ornA);\n"
-" float planeEqWS1 = -dot3F4(worldA1,planeNormalWS1);\n"
-" \n"
-" float4 planeNormalWS = planeNormalWS1;\n"
-" float planeEqWS=planeEqWS1;\n"
-" \n"
-" //clip face\n"
-" //clipFace(*pVtxIn, *pVtxOut,planeNormalWS,planeEqWS);\n"
-" numVertsOut = clipFace(pVtxIn, numVertsIn, planeNormalWS,planeEqWS, pVtxOut);\n"
-" //btSwap(pVtxIn,pVtxOut);\n"
-" float4* tmp = pVtxOut;\n"
-" pVtxOut = pVtxIn;\n"
-" pVtxIn = tmp;\n"
-" numVertsIn = numVertsOut;\n"
-" numVertsOut = 0;\n"
-" }\n"
-" \n"
-" // only keep points that are behind the witness face\n"
-" {\n"
-" float4 localPlaneNormal = make_float4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);\n"
-" float localPlaneEq = polyA.m_plane.w;\n"
-" float4 planeNormalWS = qtRotate(ornA,localPlaneNormal);\n"
-" float planeEqWS=localPlaneEq-dot3F4(planeNormalWS,posA);\n"
-" for (int i=0;i<numVertsIn;i++)\n"
-" {\n"
-" float depth = dot3F4(planeNormalWS,pVtxIn[i])+planeEqWS;\n"
-" if (depth <=minDist)\n"
-" {\n"
-" depth = minDist;\n"
-" }\n"
-" if (depth <=maxDist)\n"
-" {\n"
-" float4 pointInWorld = pVtxIn[i];\n"
-" //resultOut.addContactPoint(separatingNormal,point,depth);\n"
-" contactsOut[numContactsOut++] = make_float4(pointInWorld.x,pointInWorld.y,pointInWorld.z,depth);\n"
-" }\n"
-" }\n"
-" }\n"
-" return numContactsOut;\n"
-"}\n"
-"int clipHullAgainstHull(const float4 separatingNormal,\n"
-" __global const b3ConvexPolyhedronData_t* hullA, __global const b3ConvexPolyhedronData_t* hullB, \n"
-" const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB, \n"
-" float4* worldVertsB1, float4* worldVertsB2, int capacityWorldVerts,\n"
-" const float minDist, float maxDist,\n"
-" __global const float4* vertices,\n"
-" __global const b3GpuFace_t* faces,\n"
-" __global const int* indices,\n"
-" float4* localContactsOut,\n"
-" int localContactCapacity)\n"
-"{\n"
-" int numContactsOut = 0;\n"
-" int numWorldVertsB1= 0;\n"
-" int closestFaceB=-1;\n"
-" float dmax = -FLT_MAX;\n"
-" {\n"
-" for(int face=0;face<hullB->m_numFaces;face++)\n"
-" {\n"
-" const float4 Normal = make_float4(faces[hullB->m_faceOffset+face].m_plane.x, \n"
-" faces[hullB->m_faceOffset+face].m_plane.y, faces[hullB->m_faceOffset+face].m_plane.z,0.f);\n"
-" const float4 WorldNormal = qtRotate(ornB, Normal);\n"
-" float d = dot3F4(WorldNormal,separatingNormal);\n"
-" if (d > dmax)\n"
-" {\n"
-" dmax = d;\n"
-" closestFaceB = face;\n"
-" }\n"
-" }\n"
-" }\n"
-" {\n"
-" const b3GpuFace_t polyB = faces[hullB->m_faceOffset+closestFaceB];\n"
-" const int numVertices = polyB.m_numIndices;\n"
-" for(int e0=0;e0<numVertices;e0++)\n"
-" {\n"
-" const float4 b = vertices[hullB->m_vertexOffset+indices[polyB.m_indexOffset+e0]];\n"
-" worldVertsB1[numWorldVertsB1++] = transform(&b,&posB,&ornB);\n"
-" }\n"
-" }\n"
-" if (closestFaceB>=0)\n"
-" {\n"
-" numContactsOut = clipFaceAgainstHull(separatingNormal, hullA, \n"
-" posA,ornA,\n"
-" worldVertsB1,numWorldVertsB1,worldVertsB2,capacityWorldVerts, minDist, maxDist,vertices,\n"
-" faces,\n"
-" indices,localContactsOut,localContactCapacity);\n"
-" }\n"
-" return numContactsOut;\n"
-"}\n"
-"int clipHullAgainstHullLocalA(const float4 separatingNormal,\n"
-" const b3ConvexPolyhedronData_t* hullA, __global const b3ConvexPolyhedronData_t* hullB, \n"
-" const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB, \n"
-" float4* worldVertsB1, float4* worldVertsB2, int capacityWorldVerts,\n"
-" const float minDist, float maxDist,\n"
-" const float4* verticesA,\n"
-" const b3GpuFace_t* facesA,\n"
-" const int* indicesA,\n"
-" __global const float4* verticesB,\n"
-" __global const b3GpuFace_t* facesB,\n"
-" __global const int* indicesB,\n"
-" float4* localContactsOut,\n"
-" int localContactCapacity)\n"
-"{\n"
-" int numContactsOut = 0;\n"
-" int numWorldVertsB1= 0;\n"
-" int closestFaceB=-1;\n"
-" float dmax = -FLT_MAX;\n"
-" {\n"
-" for(int face=0;face<hullB->m_numFaces;face++)\n"
-" {\n"
-" const float4 Normal = make_float4(facesB[hullB->m_faceOffset+face].m_plane.x, \n"
-" facesB[hullB->m_faceOffset+face].m_plane.y, facesB[hullB->m_faceOffset+face].m_plane.z,0.f);\n"
-" const float4 WorldNormal = qtRotate(ornB, Normal);\n"
-" float d = dot3F4(WorldNormal,separatingNormal);\n"
-" if (d > dmax)\n"
-" {\n"
-" dmax = d;\n"
-" closestFaceB = face;\n"
-" }\n"
-" }\n"
-" }\n"
-" {\n"
-" const b3GpuFace_t polyB = facesB[hullB->m_faceOffset+closestFaceB];\n"
-" const int numVertices = polyB.m_numIndices;\n"
-" for(int e0=0;e0<numVertices;e0++)\n"
-" {\n"
-" const float4 b = verticesB[hullB->m_vertexOffset+indicesB[polyB.m_indexOffset+e0]];\n"
-" worldVertsB1[numWorldVertsB1++] = transform(&b,&posB,&ornB);\n"
-" }\n"
-" }\n"
-" if (closestFaceB>=0)\n"
-" {\n"
-" numContactsOut = clipFaceAgainstHullLocalA(separatingNormal, hullA, \n"
-" posA,ornA,\n"
-" worldVertsB1,numWorldVertsB1,worldVertsB2,capacityWorldVerts, minDist, maxDist,\n"
-" verticesA,facesA,indicesA,\n"
-" verticesB,facesB,indicesB,\n"
-" localContactsOut,localContactCapacity);\n"
-" }\n"
-" return numContactsOut;\n"
-"}\n"
-"#define PARALLEL_SUM(v, n) for(int j=1; j<n; j++) v[0] += v[j];\n"
-"#define PARALLEL_DO(execution, n) for(int ie=0; ie<n; ie++){execution;}\n"
-"#define REDUCE_MAX(v, n) {int i=0; for(int offset=0; offset<n; offset++) v[i] = (v[i].y > v[i+offset].y)? v[i]: v[i+offset]; }\n"
-"#define REDUCE_MIN(v, n) {int i=0; for(int offset=0; offset<n; offset++) v[i] = (v[i].y < v[i+offset].y)? v[i]: v[i+offset]; }\n"
-"int extractManifoldSequentialGlobal(__global const float4* p, int nPoints, float4 nearNormal, int4* contactIdx)\n"
-"{\n"
-" if( nPoints == 0 )\n"
-" return 0;\n"
-" \n"
-" if (nPoints <=4)\n"
-" return nPoints;\n"
-" \n"
-" \n"
-" if (nPoints >64)\n"
-" nPoints = 64;\n"
-" \n"
-" float4 center = make_float4(0.f);\n"
-" {\n"
-" \n"
-" for (int i=0;i<nPoints;i++)\n"
-" center += p[i];\n"
-" center /= (float)nPoints;\n"
-" }\n"
-" \n"
-" \n"
-" \n"
-" // sample 4 directions\n"
-" \n"
-" float4 aVector = p[0] - center;\n"
-" float4 u = cross3( nearNormal, aVector );\n"
-" float4 v = cross3( nearNormal, u );\n"
-" u = normalize3( u );\n"
-" v = normalize3( v );\n"
-" \n"
-" \n"
-" //keep point with deepest penetration\n"
-" float minW= FLT_MAX;\n"
-" \n"
-" int minIndex=-1;\n"
-" \n"
-" float4 maxDots;\n"
-" maxDots.x = FLT_MIN;\n"
-" maxDots.y = FLT_MIN;\n"
-" maxDots.z = FLT_MIN;\n"
-" maxDots.w = FLT_MIN;\n"
-" \n"
-" // idx, distance\n"
-" for(int ie = 0; ie<nPoints; ie++ )\n"
-" {\n"
-" if (p[ie].w<minW)\n"
-" {\n"
-" minW = p[ie].w;\n"
-" minIndex=ie;\n"
-" }\n"
-" float f;\n"
-" float4 r = p[ie]-center;\n"
-" f = dot3F4( u, r );\n"
-" if (f<maxDots.x)\n"
-" {\n"
-" maxDots.x = f;\n"
-" contactIdx[0].x = ie;\n"
-" }\n"
-" \n"
-" f = dot3F4( -u, r );\n"
-" if (f<maxDots.y)\n"
-" {\n"
-" maxDots.y = f;\n"
-" contactIdx[0].y = ie;\n"
-" }\n"
-" \n"
-" \n"
-" f = dot3F4( v, r );\n"
-" if (f<maxDots.z)\n"
-" {\n"
-" maxDots.z = f;\n"
-" contactIdx[0].z = ie;\n"
-" }\n"
-" \n"
-" f = dot3F4( -v, r );\n"
-" if (f<maxDots.w)\n"
-" {\n"
-" maxDots.w = f;\n"
-" contactIdx[0].w = ie;\n"
-" }\n"
-" \n"
-" }\n"
-" \n"
-" if (contactIdx[0].x != minIndex && contactIdx[0].y != minIndex && contactIdx[0].z != minIndex && contactIdx[0].w != minIndex)\n"
-" {\n"
-" //replace the first contact with minimum (todo: replace contact with least penetration)\n"
-" contactIdx[0].x = minIndex;\n"
-" }\n"
-" \n"
-" return 4;\n"
-" \n"
-"}\n"
-"int extractManifoldSequentialGlobalFake(__global const float4* p, int nPoints, float4 nearNormal, int* contactIdx)\n"
-"{\n"
-" contactIdx[0] = 0;\n"
-" contactIdx[1] = 1;\n"
-" contactIdx[2] = 2;\n"
-" contactIdx[3] = 3;\n"
-" \n"
-" if( nPoints == 0 ) return 0;\n"
-" \n"
-" nPoints = min2( nPoints, 4 );\n"
-" return nPoints;\n"
-" \n"
-"}\n"
-"int extractManifoldSequential(const float4* p, int nPoints, float4 nearNormal, int* contactIdx)\n"
-"{\n"
-" if( nPoints == 0 ) return 0;\n"
-" nPoints = min2( nPoints, 64 );\n"
-" float4 center = make_float4(0.f);\n"
-" {\n"
-" float4 v[64];\n"
-" for (int i=0;i<nPoints;i++)\n"
-" v[i] = p[i];\n"
-" //memcpy( v, p, nPoints*sizeof(float4) );\n"
-" PARALLEL_SUM( v, nPoints );\n"
-" center = v[0]/(float)nPoints;\n"
-" }\n"
-" \n"
-" { // sample 4 directions\n"
-" if( nPoints < 4 )\n"
-" {\n"
-" for(int i=0; i<nPoints; i++) \n"
-" contactIdx[i] = i;\n"
-" return nPoints;\n"
-" }\n"
-" float4 aVector = p[0] - center;\n"
-" float4 u = cross3( nearNormal, aVector );\n"
-" float4 v = cross3( nearNormal, u );\n"
-" u = normalize3( u );\n"
-" v = normalize3( v );\n"
-" int idx[4];\n"
-" float2 max00 = make_float2(0,FLT_MAX);\n"
-" {\n"
-" // idx, distance\n"
-" {\n"
-" {\n"
-" int4 a[64];\n"
-" for(int ie = 0; ie<nPoints; ie++ )\n"
-" {\n"
-" \n"
-" \n"
-" float f;\n"
-" float4 r = p[ie]-center;\n"
-" f = dot3F4( u, r );\n"
-" a[ie].x = ((*(u32*)&f) & 0xffffff00) | (0xff & ie);\n"
-" f = dot3F4( -u, r );\n"
-" a[ie].y = ((*(u32*)&f) & 0xffffff00) | (0xff & ie);\n"
-" f = dot3F4( v, r );\n"
-" a[ie].z = ((*(u32*)&f) & 0xffffff00) | (0xff & ie);\n"
-" f = dot3F4( -v, r );\n"
-" a[ie].w = ((*(u32*)&f) & 0xffffff00) | (0xff & ie);\n"
-" }\n"
-" for(int ie=0; ie<nPoints; ie++)\n"
-" {\n"
-" a[0].x = (a[0].x > a[ie].x )? a[0].x: a[ie].x;\n"
-" a[0].y = (a[0].y > a[ie].y )? a[0].y: a[ie].y;\n"
-" a[0].z = (a[0].z > a[ie].z )? a[0].z: a[ie].z;\n"
-" a[0].w = (a[0].w > a[ie].w )? a[0].w: a[ie].w;\n"
-" }\n"
-" idx[0] = (int)a[0].x & 0xff;\n"
-" idx[1] = (int)a[0].y & 0xff;\n"
-" idx[2] = (int)a[0].z & 0xff;\n"
-" idx[3] = (int)a[0].w & 0xff;\n"
-" }\n"
-" }\n"
-" {\n"
-" float2 h[64];\n"
-" PARALLEL_DO( h[ie] = make_float2((float)ie, p[ie].w), nPoints );\n"
-" REDUCE_MIN( h, nPoints );\n"
-" max00 = h[0];\n"
-" }\n"
-" }\n"
-" contactIdx[0] = idx[0];\n"
-" contactIdx[1] = idx[1];\n"
-" contactIdx[2] = idx[2];\n"
-" contactIdx[3] = idx[3];\n"
-" return 4;\n"
-" }\n"
-"}\n"
-"__kernel void extractManifoldAndAddContactKernel(__global const int4* pairs, \n"
-" __global const b3RigidBodyData_t* rigidBodies, \n"
-" __global const float4* closestPointsWorld,\n"
-" __global const float4* separatingNormalsWorld,\n"
-" __global const int* contactCounts,\n"
-" __global const int* contactOffsets,\n"
-" __global struct b3Contact4Data* restrict contactsOut,\n"
-" counter32_t nContactsOut,\n"
-" int contactCapacity,\n"
-" int numPairs,\n"
-" int pairIndex\n"
-" )\n"
-"{\n"
-" int idx = get_global_id(0);\n"
-" \n"
-" if (idx<numPairs)\n"
-" {\n"
-" float4 normal = separatingNormalsWorld[idx];\n"
-" int nPoints = contactCounts[idx];\n"
-" __global const float4* pointsIn = &closestPointsWorld[contactOffsets[idx]];\n"
-" float4 localPoints[64];\n"
-" for (int i=0;i<nPoints;i++)\n"
-" {\n"
-" localPoints[i] = pointsIn[i];\n"
-" }\n"
-" int contactIdx[4];// = {-1,-1,-1,-1};\n"
-" contactIdx[0] = -1;\n"
-" contactIdx[1] = -1;\n"
-" contactIdx[2] = -1;\n"
-" contactIdx[3] = -1;\n"
-" int nContacts = extractManifoldSequential(localPoints, nPoints, normal, contactIdx);\n"
-" int dstIdx;\n"
-" AppendInc( nContactsOut, dstIdx );\n"
-" if (dstIdx<contactCapacity)\n"
-" {\n"
-" __global struct b3Contact4Data* c = contactsOut + dstIdx;\n"
-" c->m_worldNormalOnB = -normal;\n"
-" c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
-" c->m_batchIdx = idx;\n"
-" int bodyA = pairs[pairIndex].x;\n"
-" int bodyB = pairs[pairIndex].y;\n"
-" c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0 ? -bodyA:bodyA;\n"
-" c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0 ? -bodyB:bodyB;\n"
-" c->m_childIndexA = -1;\n"
-" c->m_childIndexB = -1;\n"
-" for (int i=0;i<nContacts;i++)\n"
-" {\n"
-" c->m_worldPosB[i] = localPoints[contactIdx[i]];\n"
-" }\n"
-" GET_NPOINTS(*c) = nContacts;\n"
-" }\n"
-" }\n"
-"}\n"
-"void trInverse(float4 translationIn, Quaternion orientationIn,\n"
-" float4* translationOut, Quaternion* orientationOut)\n"
-"{\n"
-" *orientationOut = qtInvert(orientationIn);\n"
-" *translationOut = qtRotate(*orientationOut, -translationIn);\n"
-"}\n"
-"void trMul(float4 translationA, Quaternion orientationA,\n"
-" float4 translationB, Quaternion orientationB,\n"
-" float4* translationOut, Quaternion* orientationOut)\n"
-"{\n"
-" *orientationOut = qtMul(orientationA,orientationB);\n"
-" *translationOut = transform(&translationB,&translationA,&orientationA);\n"
-"}\n"
-"__kernel void clipHullHullKernel( __global int4* pairs, \n"
-" __global const b3RigidBodyData_t* rigidBodies, \n"
-" __global const b3Collidable_t* collidables,\n"
-" __global const b3ConvexPolyhedronData_t* convexShapes, \n"
-" __global const float4* vertices,\n"
-" __global const float4* uniqueEdges,\n"
-" __global const b3GpuFace_t* faces,\n"
-" __global const int* indices,\n"
-" __global const float4* separatingNormals,\n"
-" __global const int* hasSeparatingAxis,\n"
-" __global struct b3Contact4Data* restrict globalContactsOut,\n"
-" counter32_t nGlobalContactsOut,\n"
-" int numPairs,\n"
-" int contactCapacity)\n"
-"{\n"
-" int i = get_global_id(0);\n"
-" int pairIndex = i;\n"
-" \n"
-" float4 worldVertsB1[64];\n"
-" float4 worldVertsB2[64];\n"
-" int capacityWorldVerts = 64; \n"
-" float4 localContactsOut[64];\n"
-" int localContactCapacity=64;\n"
-" \n"
-" float minDist = -1e30f;\n"
-" float maxDist = 0.02f;\n"
-" if (i<numPairs)\n"
-" {\n"
-" int bodyIndexA = pairs[i].x;\n"
-" int bodyIndexB = pairs[i].y;\n"
-" \n"
-" int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
-" int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
-" if (hasSeparatingAxis[i])\n"
-" {\n"
-" \n"
-" int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
-" int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
-" \n"
-" \n"
-" int numLocalContactsOut = clipHullAgainstHull(separatingNormals[i],\n"
-" &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],\n"
-" rigidBodies[bodyIndexA].m_pos,rigidBodies[bodyIndexA].m_quat,\n"
-" rigidBodies[bodyIndexB].m_pos,rigidBodies[bodyIndexB].m_quat,\n"
-" worldVertsB1,worldVertsB2,capacityWorldVerts,\n"
-" minDist, maxDist,\n"
-" vertices,faces,indices,\n"
-" localContactsOut,localContactCapacity);\n"
-" \n"
-" if (numLocalContactsOut>0)\n"
-" {\n"
-" float4 normal = -separatingNormals[i];\n"
-" int nPoints = numLocalContactsOut;\n"
-" float4* pointsIn = localContactsOut;\n"
-" int contactIdx[4];// = {-1,-1,-1,-1};\n"
-" contactIdx[0] = -1;\n"
-" contactIdx[1] = -1;\n"
-" contactIdx[2] = -1;\n"
-" contactIdx[3] = -1;\n"
-" \n"
-" int nReducedContacts = extractManifoldSequential(pointsIn, nPoints, normal, contactIdx);\n"
-" \n"
-" \n"
-" int mprContactIndex = pairs[pairIndex].z;\n"
-" int dstIdx = mprContactIndex;\n"
-" if (dstIdx<0)\n"
-" {\n"
-" AppendInc( nGlobalContactsOut, dstIdx );\n"
-" }\n"
-" if (dstIdx<contactCapacity)\n"
-" {\n"
-" pairs[pairIndex].z = dstIdx;\n"
-" __global struct b3Contact4Data* c = globalContactsOut+ dstIdx;\n"
-" c->m_worldNormalOnB = -normal;\n"
-" c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
-" c->m_batchIdx = pairIndex;\n"
-" int bodyA = pairs[pairIndex].x;\n"
-" int bodyB = pairs[pairIndex].y;\n"
-" c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;\n"
-" c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;\n"
-" c->m_childIndexA = -1;\n"
-" c->m_childIndexB = -1;\n"
-" for (int i=0;i<nReducedContacts;i++)\n"
-" {\n"
-" //this condition means: overwrite contact point, unless at index i==0 we have a valid 'mpr' contact\n"
-" if (i>0||(mprContactIndex<0))\n"
-" {\n"
-" c->m_worldPosB[i] = pointsIn[contactIdx[i]];\n"
-" }\n"
-" }\n"
-" GET_NPOINTS(*c) = nReducedContacts;\n"
-" }\n"
-" \n"
-" }// if (numContactsOut>0)\n"
-" }// if (hasSeparatingAxis[i])\n"
-" }// if (i<numPairs)\n"
-"}\n"
-"__kernel void clipCompoundsHullHullKernel( __global const int4* gpuCompoundPairs, \n"
-" __global const b3RigidBodyData_t* rigidBodies, \n"
-" __global const b3Collidable_t* collidables,\n"
-" __global const b3ConvexPolyhedronData_t* convexShapes, \n"
-" __global const float4* vertices,\n"
-" __global const float4* uniqueEdges,\n"
-" __global const b3GpuFace_t* faces,\n"
-" __global const int* indices,\n"
-" __global const b3GpuChildShape_t* gpuChildShapes,\n"
-" __global const float4* gpuCompoundSepNormalsOut,\n"
-" __global const int* gpuHasCompoundSepNormalsOut,\n"
-" __global struct b3Contact4Data* restrict globalContactsOut,\n"
-" counter32_t nGlobalContactsOut,\n"
-" int numCompoundPairs, int maxContactCapacity)\n"
-"{\n"
-" int i = get_global_id(0);\n"
-" int pairIndex = i;\n"
-" \n"
-" float4 worldVertsB1[64];\n"
-" float4 worldVertsB2[64];\n"
-" int capacityWorldVerts = 64; \n"
-" float4 localContactsOut[64];\n"
-" int localContactCapacity=64;\n"
-" \n"
-" float minDist = -1e30f;\n"
-" float maxDist = 0.02f;\n"
-" if (i<numCompoundPairs)\n"
-" {\n"
-" if (gpuHasCompoundSepNormalsOut[i])\n"
-" {\n"
-" int bodyIndexA = gpuCompoundPairs[i].x;\n"
-" int bodyIndexB = gpuCompoundPairs[i].y;\n"
-" \n"
-" int childShapeIndexA = gpuCompoundPairs[i].z;\n"
-" int childShapeIndexB = gpuCompoundPairs[i].w;\n"
-" \n"
-" int collidableIndexA = -1;\n"
-" int collidableIndexB = -1;\n"
-" \n"
-" float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
-" float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
-" \n"
-" float4 ornB = rigidBodies[bodyIndexB].m_quat;\n"
-" float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
-" \n"
-" if (childShapeIndexA >= 0)\n"
-" {\n"
-" collidableIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;\n"
-" float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;\n"
-" float4 childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;\n"
-" float4 newPosA = qtRotate(ornA,childPosA)+posA;\n"
-" float4 newOrnA = qtMul(ornA,childOrnA);\n"
-" posA = newPosA;\n"
-" ornA = newOrnA;\n"
-" } else\n"
-" {\n"
-" collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
-" }\n"
-" \n"
-" if (childShapeIndexB>=0)\n"
-" {\n"
-" collidableIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
-" float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
-" float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
-" float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
-" float4 newOrnB = qtMul(ornB,childOrnB);\n"
-" posB = newPosB;\n"
-" ornB = newOrnB;\n"
-" } else\n"
-" {\n"
-" collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx; \n"
-" }\n"
-" \n"
-" int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
-" int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
-" \n"
-" int numLocalContactsOut = clipHullAgainstHull(gpuCompoundSepNormalsOut[i],\n"
-" &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],\n"
-" posA,ornA,\n"
-" posB,ornB,\n"
-" worldVertsB1,worldVertsB2,capacityWorldVerts,\n"
-" minDist, maxDist,\n"
-" vertices,faces,indices,\n"
-" localContactsOut,localContactCapacity);\n"
-" \n"
-" if (numLocalContactsOut>0)\n"
-" {\n"
-" float4 normal = -gpuCompoundSepNormalsOut[i];\n"
-" int nPoints = numLocalContactsOut;\n"
-" float4* pointsIn = localContactsOut;\n"
-" int contactIdx[4];// = {-1,-1,-1,-1};\n"
-" contactIdx[0] = -1;\n"
-" contactIdx[1] = -1;\n"
-" contactIdx[2] = -1;\n"
-" contactIdx[3] = -1;\n"
-" \n"
-" int nReducedContacts = extractManifoldSequential(pointsIn, nPoints, normal, contactIdx);\n"
-" \n"
-" int dstIdx;\n"
-" AppendInc( nGlobalContactsOut, dstIdx );\n"
-" if ((dstIdx+nReducedContacts) < maxContactCapacity)\n"
-" {\n"
-" __global struct b3Contact4Data* c = globalContactsOut+ dstIdx;\n"
-" c->m_worldNormalOnB = -normal;\n"
-" c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
-" c->m_batchIdx = pairIndex;\n"
-" int bodyA = gpuCompoundPairs[pairIndex].x;\n"
-" int bodyB = gpuCompoundPairs[pairIndex].y;\n"
-" c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;\n"
-" c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;\n"
-" c->m_childIndexA = childShapeIndexA;\n"
-" c->m_childIndexB = childShapeIndexB;\n"
-" for (int i=0;i<nReducedContacts;i++)\n"
-" {\n"
-" c->m_worldPosB[i] = pointsIn[contactIdx[i]];\n"
-" }\n"
-" GET_NPOINTS(*c) = nReducedContacts;\n"
-" }\n"
-" \n"
-" }// if (numContactsOut>0)\n"
-" }// if (gpuHasCompoundSepNormalsOut[i])\n"
-" }// if (i<numCompoundPairs)\n"
-"}\n"
-"__kernel void sphereSphereCollisionKernel( __global const int4* pairs, \n"
-" __global const b3RigidBodyData_t* rigidBodies, \n"
-" __global const b3Collidable_t* collidables,\n"
-" __global const float4* separatingNormals,\n"
-" __global const int* hasSeparatingAxis,\n"
-" __global struct b3Contact4Data* restrict globalContactsOut,\n"
-" counter32_t nGlobalContactsOut,\n"
-" int contactCapacity,\n"
-" int numPairs)\n"
-"{\n"
-" int i = get_global_id(0);\n"
-" int pairIndex = i;\n"
-" \n"
-" if (i<numPairs)\n"
-" {\n"
-" int bodyIndexA = pairs[i].x;\n"
-" int bodyIndexB = pairs[i].y;\n"
-" \n"
-" int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
-" int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
-" if (collidables[collidableIndexA].m_shapeType == SHAPE_SPHERE &&\n"
-" collidables[collidableIndexB].m_shapeType == SHAPE_SPHERE)\n"
-" {\n"
-" //sphere-sphere\n"
-" float radiusA = collidables[collidableIndexA].m_radius;\n"
-" float radiusB = collidables[collidableIndexB].m_radius;\n"
-" float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
-" float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
-" float4 diff = posA-posB;\n"
-" float len = length(diff);\n"
-" \n"
-" ///iff distance positive, don't generate a new contact\n"
-" if ( len <= (radiusA+radiusB))\n"
-" {\n"
-" ///distance (negative means penetration)\n"
-" float dist = len - (radiusA+radiusB);\n"
-" float4 normalOnSurfaceB = make_float4(1.f,0.f,0.f,0.f);\n"
-" if (len > 0.00001)\n"
-" {\n"
-" normalOnSurfaceB = diff / len;\n"
-" }\n"
-" float4 contactPosB = posB + normalOnSurfaceB*radiusB;\n"
-" contactPosB.w = dist;\n"
-" \n"
-" int dstIdx;\n"
-" AppendInc( nGlobalContactsOut, dstIdx );\n"
-" if (dstIdx < contactCapacity)\n"
-" {\n"
-" __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];\n"
-" c->m_worldNormalOnB = -normalOnSurfaceB;\n"
-" c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
-" c->m_batchIdx = pairIndex;\n"
-" int bodyA = pairs[pairIndex].x;\n"
-" int bodyB = pairs[pairIndex].y;\n"
-" c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;\n"
-" c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;\n"
-" c->m_worldPosB[0] = contactPosB;\n"
-" c->m_childIndexA = -1;\n"
-" c->m_childIndexB = -1;\n"
-" GET_NPOINTS(*c) = 1;\n"
-" }//if (dstIdx < numPairs)\n"
-" }//if ( len <= (radiusA+radiusB))\n"
-" }//SHAPE_SPHERE SHAPE_SPHERE\n"
-" }//if (i<numPairs)\n"
-"} \n"
-"__kernel void clipHullHullConcaveConvexKernel( __global int4* concavePairsIn,\n"
-" __global const b3RigidBodyData_t* rigidBodies, \n"
-" __global const b3Collidable_t* collidables,\n"
-" __global const b3ConvexPolyhedronData_t* convexShapes, \n"
-" __global const float4* vertices,\n"
-" __global const float4* uniqueEdges,\n"
-" __global const b3GpuFace_t* faces,\n"
-" __global const int* indices,\n"
-" __global const b3GpuChildShape_t* gpuChildShapes,\n"
-" __global const float4* separatingNormals,\n"
-" __global struct b3Contact4Data* restrict globalContactsOut,\n"
-" counter32_t nGlobalContactsOut,\n"
-" int contactCapacity,\n"
-" int numConcavePairs)\n"
-"{\n"
-" int i = get_global_id(0);\n"
-" int pairIndex = i;\n"
-" \n"
-" float4 worldVertsB1[64];\n"
-" float4 worldVertsB2[64];\n"
-" int capacityWorldVerts = 64; \n"
-" float4 localContactsOut[64];\n"
-" int localContactCapacity=64;\n"
-" \n"
-" float minDist = -1e30f;\n"
-" float maxDist = 0.02f;\n"
-" if (i<numConcavePairs)\n"
-" {\n"
-" //negative value means that the pair is invalid\n"
-" if (concavePairsIn[i].w<0)\n"
-" return;\n"
-" int bodyIndexA = concavePairsIn[i].x;\n"
-" int bodyIndexB = concavePairsIn[i].y;\n"
-" int f = concavePairsIn[i].z;\n"
-" int childShapeIndexA = f;\n"
-" \n"
-" int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
-" int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
-" \n"
-" int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
-" int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
-" \n"
-" ///////////////////////////////////////////////////////////////\n"
-" \n"
-" \n"
-" bool overlap = false;\n"
-" \n"
-" b3ConvexPolyhedronData_t convexPolyhedronA;\n"
-" //add 3 vertices of the triangle\n"
-" convexPolyhedronA.m_numVertices = 3;\n"
-" convexPolyhedronA.m_vertexOffset = 0;\n"
-" float4 localCenter = make_float4(0.f,0.f,0.f,0.f);\n"
-" b3GpuFace_t face = faces[convexShapes[shapeIndexA].m_faceOffset+f];\n"
-" \n"
-" float4 verticesA[3];\n"
-" for (int i=0;i<3;i++)\n"
-" {\n"
-" int index = indices[face.m_indexOffset+i];\n"
-" float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];\n"
-" verticesA[i] = vert;\n"
-" localCenter += vert;\n"
-" }\n"
-" float dmin = FLT_MAX;\n"
-" int localCC=0;\n"
-" //a triangle has 3 unique edges\n"
-" convexPolyhedronA.m_numUniqueEdges = 3;\n"
-" convexPolyhedronA.m_uniqueEdgesOffset = 0;\n"
-" float4 uniqueEdgesA[3];\n"
-" \n"
-" uniqueEdgesA[0] = (verticesA[1]-verticesA[0]);\n"
-" uniqueEdgesA[1] = (verticesA[2]-verticesA[1]);\n"
-" uniqueEdgesA[2] = (verticesA[0]-verticesA[2]);\n"
-" convexPolyhedronA.m_faceOffset = 0;\n"
-" \n"
-" float4 normal = make_float4(face.m_plane.x,face.m_plane.y,face.m_plane.z,0.f);\n"
-" \n"
-" b3GpuFace_t facesA[TRIANGLE_NUM_CONVEX_FACES];\n"
-" int indicesA[3+3+2+2+2];\n"
-" int curUsedIndices=0;\n"
-" int fidx=0;\n"
-" //front size of triangle\n"
-" {\n"
-" facesA[fidx].m_indexOffset=curUsedIndices;\n"
-" indicesA[0] = 0;\n"
-" indicesA[1] = 1;\n"
-" indicesA[2] = 2;\n"
-" curUsedIndices+=3;\n"
-" float c = face.m_plane.w;\n"
-" facesA[fidx].m_plane.x = normal.x;\n"
-" facesA[fidx].m_plane.y = normal.y;\n"
-" facesA[fidx].m_plane.z = normal.z;\n"
-" facesA[fidx].m_plane.w = c;\n"
-" facesA[fidx].m_numIndices=3;\n"
-" }\n"
-" fidx++;\n"
-" //back size of triangle\n"
-" {\n"
-" facesA[fidx].m_indexOffset=curUsedIndices;\n"
-" indicesA[3]=2;\n"
-" indicesA[4]=1;\n"
-" indicesA[5]=0;\n"
-" curUsedIndices+=3;\n"
-" float c = dot3F4(normal,verticesA[0]);\n"
-" float c1 = -face.m_plane.w;\n"
-" facesA[fidx].m_plane.x = -normal.x;\n"
-" facesA[fidx].m_plane.y = -normal.y;\n"
-" facesA[fidx].m_plane.z = -normal.z;\n"
-" facesA[fidx].m_plane.w = c;\n"
-" facesA[fidx].m_numIndices=3;\n"
-" }\n"
-" fidx++;\n"
-" bool addEdgePlanes = true;\n"
-" if (addEdgePlanes)\n"
-" {\n"
-" int numVertices=3;\n"
-" int prevVertex = numVertices-1;\n"
-" for (int i=0;i<numVertices;i++)\n"
-" {\n"
-" float4 v0 = verticesA[i];\n"
-" float4 v1 = verticesA[prevVertex];\n"
-" \n"
-" float4 edgeNormal = normalize(cross(normal,v1-v0));\n"
-" float c = -dot3F4(edgeNormal,v0);\n"
-" facesA[fidx].m_numIndices = 2;\n"
-" facesA[fidx].m_indexOffset=curUsedIndices;\n"
-" indicesA[curUsedIndices++]=i;\n"
-" indicesA[curUsedIndices++]=prevVertex;\n"
-" \n"
-" facesA[fidx].m_plane.x = edgeNormal.x;\n"
-" facesA[fidx].m_plane.y = edgeNormal.y;\n"
-" facesA[fidx].m_plane.z = edgeNormal.z;\n"
-" facesA[fidx].m_plane.w = c;\n"
-" fidx++;\n"
-" prevVertex = i;\n"
-" }\n"
-" }\n"
-" convexPolyhedronA.m_numFaces = TRIANGLE_NUM_CONVEX_FACES;\n"
-" convexPolyhedronA.m_localCenter = localCenter*(1.f/3.f);\n"
-" float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
-" posA.w = 0.f;\n"
-" float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
-" posB.w = 0.f;\n"
-" float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
-" float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
-" float4 sepAxis = separatingNormals[i];\n"
-" \n"
-" int shapeTypeB = collidables[collidableIndexB].m_shapeType;\n"
-" int childShapeIndexB =-1;\n"
-" if (shapeTypeB==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
-" {\n"
-" ///////////////////\n"
-" ///compound shape support\n"
-" \n"
-" childShapeIndexB = concavePairsIn[pairIndex].w;\n"
-" int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
-" shapeIndexB = collidables[childColIndexB].m_shapeIndex;\n"
-" float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
-" float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
-" float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
-" float4 newOrnB = qtMul(ornB,childOrnB);\n"
-" posB = newPosB;\n"
-" ornB = newOrnB;\n"
-" \n"
-" }\n"
-" \n"
-" ////////////////////////////////////////\n"
-" \n"
-" \n"
-" \n"
-" int numLocalContactsOut = clipHullAgainstHullLocalA(sepAxis,\n"
-" &convexPolyhedronA, &convexShapes[shapeIndexB],\n"
-" posA,ornA,\n"
-" posB,ornB,\n"
-" worldVertsB1,worldVertsB2,capacityWorldVerts,\n"
-" minDist, maxDist,\n"
-" &verticesA,&facesA,&indicesA,\n"
-" vertices,faces,indices,\n"
-" localContactsOut,localContactCapacity);\n"
-" \n"
-" if (numLocalContactsOut>0)\n"
-" {\n"
-" float4 normal = -separatingNormals[i];\n"
-" int nPoints = numLocalContactsOut;\n"
-" float4* pointsIn = localContactsOut;\n"
-" int contactIdx[4];// = {-1,-1,-1,-1};\n"
-" contactIdx[0] = -1;\n"
-" contactIdx[1] = -1;\n"
-" contactIdx[2] = -1;\n"
-" contactIdx[3] = -1;\n"
-" \n"
-" int nReducedContacts = extractManifoldSequential(pointsIn, nPoints, normal, contactIdx);\n"
-" \n"
-" int dstIdx;\n"
-" AppendInc( nGlobalContactsOut, dstIdx );\n"
-" if (dstIdx<contactCapacity)\n"
-" {\n"
-" __global struct b3Contact4Data* c = globalContactsOut+ dstIdx;\n"
-" c->m_worldNormalOnB = -normal;\n"
-" c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
-" c->m_batchIdx = pairIndex;\n"
-" int bodyA = concavePairsIn[pairIndex].x;\n"
-" int bodyB = concavePairsIn[pairIndex].y;\n"
-" c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;\n"
-" c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;\n"
-" c->m_childIndexA = childShapeIndexA;\n"
-" c->m_childIndexB = childShapeIndexB;\n"
-" for (int i=0;i<nReducedContacts;i++)\n"
-" {\n"
-" c->m_worldPosB[i] = pointsIn[contactIdx[i]];\n"
-" }\n"
-" GET_NPOINTS(*c) = nReducedContacts;\n"
-" }\n"
-" \n"
-" }// if (numContactsOut>0)\n"
-" }// if (i<numPairs)\n"
-"}\n"
-"int findClippingFaces(const float4 separatingNormal,\n"
-" __global const b3ConvexPolyhedronData_t* hullA, __global const b3ConvexPolyhedronData_t* hullB,\n"
-" const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB,\n"
-" __global float4* worldVertsA1,\n"
-" __global float4* worldNormalsA1,\n"
-" __global float4* worldVertsB1,\n"
-" int capacityWorldVerts,\n"
-" const float minDist, float maxDist,\n"
-" __global const float4* vertices,\n"
-" __global const b3GpuFace_t* faces,\n"
-" __global const int* indices,\n"
-" __global int4* clippingFaces, int pairIndex)\n"
-"{\n"
-" int numContactsOut = 0;\n"
-" int numWorldVertsB1= 0;\n"
-" \n"
-" \n"
-" int closestFaceB=-1;\n"
-" float dmax = -FLT_MAX;\n"
-" \n"
-" {\n"
-" for(int face=0;face<hullB->m_numFaces;face++)\n"
-" {\n"
-" const float4 Normal = make_float4(faces[hullB->m_faceOffset+face].m_plane.x,\n"
-" faces[hullB->m_faceOffset+face].m_plane.y, faces[hullB->m_faceOffset+face].m_plane.z,0.f);\n"
-" const float4 WorldNormal = qtRotate(ornB, Normal);\n"
-" float d = dot3F4(WorldNormal,separatingNormal);\n"
-" if (d > dmax)\n"
-" {\n"
-" dmax = d;\n"
-" closestFaceB = face;\n"
-" }\n"
-" }\n"
-" }\n"
-" \n"
-" {\n"
-" const b3GpuFace_t polyB = faces[hullB->m_faceOffset+closestFaceB];\n"
-" const int numVertices = polyB.m_numIndices;\n"
-" for(int e0=0;e0<numVertices;e0++)\n"
-" {\n"
-" const float4 b = vertices[hullB->m_vertexOffset+indices[polyB.m_indexOffset+e0]];\n"
-" worldVertsB1[pairIndex*capacityWorldVerts+numWorldVertsB1++] = transform(&b,&posB,&ornB);\n"
-" }\n"
-" }\n"
-" \n"
-" int closestFaceA=-1;\n"
-" {\n"
-" float dmin = FLT_MAX;\n"
-" for(int face=0;face<hullA->m_numFaces;face++)\n"
-" {\n"
-" const float4 Normal = make_float4(\n"
-" faces[hullA->m_faceOffset+face].m_plane.x,\n"
-" faces[hullA->m_faceOffset+face].m_plane.y,\n"
-" faces[hullA->m_faceOffset+face].m_plane.z,\n"
-" 0.f);\n"
-" const float4 faceANormalWS = qtRotate(ornA,Normal);\n"
-" \n"
-" float d = dot3F4(faceANormalWS,separatingNormal);\n"
-" if (d < dmin)\n"
-" {\n"
-" dmin = d;\n"
-" closestFaceA = face;\n"
-" worldNormalsA1[pairIndex] = faceANormalWS;\n"
-" }\n"
-" }\n"
-" }\n"
-" \n"
-" int numVerticesA = faces[hullA->m_faceOffset+closestFaceA].m_numIndices;\n"
-" for(int e0=0;e0<numVerticesA;e0++)\n"
-" {\n"
-" const float4 a = vertices[hullA->m_vertexOffset+indices[faces[hullA->m_faceOffset+closestFaceA].m_indexOffset+e0]];\n"
-" worldVertsA1[pairIndex*capacityWorldVerts+e0] = transform(&a, &posA,&ornA);\n"
-" }\n"
-" \n"
-" clippingFaces[pairIndex].x = closestFaceA;\n"
-" clippingFaces[pairIndex].y = closestFaceB;\n"
-" clippingFaces[pairIndex].z = numVerticesA;\n"
-" clippingFaces[pairIndex].w = numWorldVertsB1;\n"
-" \n"
-" \n"
-" return numContactsOut;\n"
-"}\n"
-"int clipFaces(__global float4* worldVertsA1,\n"
-" __global float4* worldNormalsA1,\n"
-" __global float4* worldVertsB1,\n"
-" __global float4* worldVertsB2, \n"
-" int capacityWorldVertsB2,\n"
-" const float minDist, float maxDist,\n"
-" __global int4* clippingFaces,\n"
-" int pairIndex)\n"
-"{\n"
-" int numContactsOut = 0;\n"
-" \n"
-" int closestFaceA = clippingFaces[pairIndex].x;\n"
-" int closestFaceB = clippingFaces[pairIndex].y;\n"
-" int numVertsInA = clippingFaces[pairIndex].z;\n"
-" int numVertsInB = clippingFaces[pairIndex].w;\n"
-" \n"
-" int numVertsOut = 0;\n"
-" \n"
-" if (closestFaceA<0)\n"
-" return numContactsOut;\n"
-" \n"
-" __global float4* pVtxIn = &worldVertsB1[pairIndex*capacityWorldVertsB2];\n"
-" __global float4* pVtxOut = &worldVertsB2[pairIndex*capacityWorldVertsB2];\n"
-" \n"
-" \n"
-" \n"
-" // clip polygon to back of planes of all faces of hull A that are adjacent to witness face\n"
-" \n"
-" for(int e0=0;e0<numVertsInA;e0++)\n"
-" {\n"
-" const float4 aw = worldVertsA1[pairIndex*capacityWorldVertsB2+e0];\n"
-" const float4 bw = worldVertsA1[pairIndex*capacityWorldVertsB2+((e0+1)%numVertsInA)];\n"
-" const float4 WorldEdge0 = aw - bw;\n"
-" float4 worldPlaneAnormal1 = worldNormalsA1[pairIndex];\n"
-" float4 planeNormalWS1 = -cross3(WorldEdge0,worldPlaneAnormal1);\n"
-" float4 worldA1 = aw;\n"
-" float planeEqWS1 = -dot3F4(worldA1,planeNormalWS1);\n"
-" float4 planeNormalWS = planeNormalWS1;\n"
-" float planeEqWS=planeEqWS1;\n"
-" numVertsOut = clipFaceGlobal(pVtxIn, numVertsInB, planeNormalWS,planeEqWS, pVtxOut);\n"
-" __global float4* tmp = pVtxOut;\n"
-" pVtxOut = pVtxIn;\n"
-" pVtxIn = tmp;\n"
-" numVertsInB = numVertsOut;\n"
-" numVertsOut = 0;\n"
-" }\n"
-" \n"
-" //float4 planeNormalWS = worldNormalsA1[pairIndex];\n"
-" //float planeEqWS=-dot3F4(planeNormalWS,worldVertsA1[pairIndex*capacityWorldVertsB2]);\n"
-" \n"
-" /*for (int i=0;i<numVertsInB;i++)\n"
-" {\n"
-" pVtxOut[i] = pVtxIn[i];\n"
-" }*/\n"
-" \n"
-" \n"
-" \n"
-" \n"
-" //numVertsInB=0;\n"
-" \n"
-" float4 planeNormalWS = worldNormalsA1[pairIndex];\n"
-" float planeEqWS=-dot3F4(planeNormalWS,worldVertsA1[pairIndex*capacityWorldVertsB2]);\n"
-" for (int i=0;i<numVertsInB;i++)\n"
-" {\n"
-" float depth = dot3F4(planeNormalWS,pVtxIn[i])+planeEqWS;\n"
-" if (depth <=minDist)\n"
-" {\n"
-" depth = minDist;\n"
-" }\n"
-" \n"
-" if (depth <=maxDist)\n"
-" {\n"
-" float4 pointInWorld = pVtxIn[i];\n"
-" pVtxOut[numContactsOut++] = make_float4(pointInWorld.x,pointInWorld.y,pointInWorld.z,depth);\n"
-" }\n"
-" }\n"
-" \n"
-" clippingFaces[pairIndex].w =numContactsOut;\n"
-" \n"
-" \n"
-" return numContactsOut;\n"
-"}\n"
-"__kernel void findClippingFacesKernel( __global const int4* pairs,\n"
-" __global const b3RigidBodyData_t* rigidBodies,\n"
-" __global const b3Collidable_t* collidables,\n"
-" __global const b3ConvexPolyhedronData_t* convexShapes,\n"
-" __global const float4* vertices,\n"
-" __global const float4* uniqueEdges,\n"
-" __global const b3GpuFace_t* faces,\n"
-" __global const int* indices,\n"
-" __global const float4* separatingNormals,\n"
-" __global const int* hasSeparatingAxis,\n"
-" __global int4* clippingFacesOut,\n"
-" __global float4* worldVertsA1,\n"
-" __global float4* worldNormalsA1,\n"
-" __global float4* worldVertsB1,\n"
-" int capacityWorldVerts,\n"
-" int numPairs\n"
-" )\n"
-"{\n"
-" \n"
-" int i = get_global_id(0);\n"
-" int pairIndex = i;\n"
-" \n"
-" \n"
-" float minDist = -1e30f;\n"
-" float maxDist = 0.02f;\n"
-" \n"
-" if (i<numPairs)\n"
-" {\n"
-" \n"
-" if (hasSeparatingAxis[i])\n"
-" {\n"
-" \n"
-" int bodyIndexA = pairs[i].x;\n"
-" int bodyIndexB = pairs[i].y;\n"
-" \n"
-" int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
-" int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
-" \n"
-" int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
-" int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
-" \n"
-" \n"
-" \n"
-" int numLocalContactsOut = findClippingFaces(separatingNormals[i],\n"
-" &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],\n"
-" rigidBodies[bodyIndexA].m_pos,rigidBodies[bodyIndexA].m_quat,\n"
-" rigidBodies[bodyIndexB].m_pos,rigidBodies[bodyIndexB].m_quat,\n"
-" worldVertsA1,\n"
-" worldNormalsA1,\n"
-" worldVertsB1,capacityWorldVerts,\n"
-" minDist, maxDist,\n"
-" vertices,faces,indices,\n"
-" clippingFacesOut,i);\n"
-" \n"
-" \n"
-" }// if (hasSeparatingAxis[i])\n"
-" }// if (i<numPairs)\n"
-" \n"
-"}\n"
-"__kernel void clipFacesAndFindContactsKernel( __global const float4* separatingNormals,\n"
-" __global const int* hasSeparatingAxis,\n"
-" __global int4* clippingFacesOut,\n"
-" __global float4* worldVertsA1,\n"
-" __global float4* worldNormalsA1,\n"
-" __global float4* worldVertsB1,\n"
-" __global float4* worldVertsB2,\n"
-" int vertexFaceCapacity,\n"
-" int numPairs,\n"
-" int debugMode\n"
-" )\n"
-"{\n"
-" int i = get_global_id(0);\n"
-" int pairIndex = i;\n"
-" \n"
-" \n"
-" float minDist = -1e30f;\n"
-" float maxDist = 0.02f;\n"
-" \n"
-" if (i<numPairs)\n"
-" {\n"
-" \n"
-" if (hasSeparatingAxis[i])\n"
-" {\n"
-" \n"
-"// int bodyIndexA = pairs[i].x;\n"
-" // int bodyIndexB = pairs[i].y;\n"
-" \n"
-" int numLocalContactsOut = 0;\n"
-" int capacityWorldVertsB2 = vertexFaceCapacity;\n"
-" \n"
-" __global float4* pVtxIn = &worldVertsB1[pairIndex*capacityWorldVertsB2];\n"
-" __global float4* pVtxOut = &worldVertsB2[pairIndex*capacityWorldVertsB2];\n"
-" \n"
-" {\n"
-" __global int4* clippingFaces = clippingFacesOut;\n"
-" \n"
-" \n"
-" int closestFaceA = clippingFaces[pairIndex].x;\n"
-" int closestFaceB = clippingFaces[pairIndex].y;\n"
-" int numVertsInA = clippingFaces[pairIndex].z;\n"
-" int numVertsInB = clippingFaces[pairIndex].w;\n"
-" \n"
-" int numVertsOut = 0;\n"
-" \n"
-" if (closestFaceA>=0)\n"
-" {\n"
-" \n"
-" \n"
-" \n"
-" // clip polygon to back of planes of all faces of hull A that are adjacent to witness face\n"
-" \n"
-" for(int e0=0;e0<numVertsInA;e0++)\n"
-" {\n"
-" const float4 aw = worldVertsA1[pairIndex*capacityWorldVertsB2+e0];\n"
-" const float4 bw = worldVertsA1[pairIndex*capacityWorldVertsB2+((e0+1)%numVertsInA)];\n"
-" const float4 WorldEdge0 = aw - bw;\n"
-" float4 worldPlaneAnormal1 = worldNormalsA1[pairIndex];\n"
-" float4 planeNormalWS1 = -cross3(WorldEdge0,worldPlaneAnormal1);\n"
-" float4 worldA1 = aw;\n"
-" float planeEqWS1 = -dot3F4(worldA1,planeNormalWS1);\n"
-" float4 planeNormalWS = planeNormalWS1;\n"
-" float planeEqWS=planeEqWS1;\n"
-" numVertsOut = clipFaceGlobal(pVtxIn, numVertsInB, planeNormalWS,planeEqWS, pVtxOut);\n"
-" __global float4* tmp = pVtxOut;\n"
-" pVtxOut = pVtxIn;\n"
-" pVtxIn = tmp;\n"
-" numVertsInB = numVertsOut;\n"
-" numVertsOut = 0;\n"
-" }\n"
-" \n"
-" float4 planeNormalWS = worldNormalsA1[pairIndex];\n"
-" float planeEqWS=-dot3F4(planeNormalWS,worldVertsA1[pairIndex*capacityWorldVertsB2]);\n"
-" \n"
-" for (int i=0;i<numVertsInB;i++)\n"
-" {\n"
-" float depth = dot3F4(planeNormalWS,pVtxIn[i])+planeEqWS;\n"
-" if (depth <=minDist)\n"
-" {\n"
-" depth = minDist;\n"
-" }\n"
-" \n"
-" if (depth <=maxDist)\n"
-" {\n"
-" float4 pointInWorld = pVtxIn[i];\n"
-" pVtxOut[numLocalContactsOut++] = make_float4(pointInWorld.x,pointInWorld.y,pointInWorld.z,depth);\n"
-" }\n"
-" }\n"
-" \n"
-" }\n"
-" clippingFaces[pairIndex].w =numLocalContactsOut;\n"
-" \n"
-" }\n"
-" \n"
-" for (int i=0;i<numLocalContactsOut;i++)\n"
-" pVtxIn[i] = pVtxOut[i];\n"
-" \n"
-" }// if (hasSeparatingAxis[i])\n"
-" }// if (i<numPairs)\n"
-" \n"
-"}\n"
-"__kernel void newContactReductionKernel( __global int4* pairs,\n"
-" __global const b3RigidBodyData_t* rigidBodies,\n"
-" __global const float4* separatingNormals,\n"
-" __global const int* hasSeparatingAxis,\n"
-" __global struct b3Contact4Data* globalContactsOut,\n"
-" __global int4* clippingFaces,\n"
-" __global float4* worldVertsB2,\n"
-" volatile __global int* nGlobalContactsOut,\n"
-" int vertexFaceCapacity,\n"
-" int contactCapacity,\n"
-" int numPairs\n"
-" )\n"
-"{\n"
-" int i = get_global_id(0);\n"
-" int pairIndex = i;\n"
-" \n"
-" int4 contactIdx;\n"
-" contactIdx=make_int4(0,1,2,3);\n"
-" \n"
-" if (i<numPairs)\n"
-" {\n"
-" \n"
-" if (hasSeparatingAxis[i])\n"
-" {\n"
-" \n"
-" \n"
-" \n"
-" \n"
-" int nPoints = clippingFaces[pairIndex].w;\n"
-" \n"
-" if (nPoints>0)\n"
-" {\n"
-" __global float4* pointsIn = &worldVertsB2[pairIndex*vertexFaceCapacity];\n"
-" float4 normal = -separatingNormals[i];\n"
-" \n"
-" int nReducedContacts = extractManifoldSequentialGlobal(pointsIn, nPoints, normal, &contactIdx);\n"
-" \n"
-" int mprContactIndex = pairs[pairIndex].z;\n"
-" int dstIdx = mprContactIndex;\n"
-" if (dstIdx<0)\n"
-" {\n"
-" AppendInc( nGlobalContactsOut, dstIdx );\n"
-" }\n"
-"//#if 0\n"
-" \n"
-" if (dstIdx < contactCapacity)\n"
-" {\n"
-" __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];\n"
-" c->m_worldNormalOnB = -normal;\n"
-" c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
-" c->m_batchIdx = pairIndex;\n"
-" int bodyA = pairs[pairIndex].x;\n"
-" int bodyB = pairs[pairIndex].y;\n"
-" pairs[pairIndex].w = dstIdx;\n"
-" c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;\n"
-" c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;\n"
-" c->m_childIndexA =-1;\n"
-" c->m_childIndexB =-1;\n"
-" switch (nReducedContacts)\n"
-" {\n"
-" case 4:\n"
-" c->m_worldPosB[3] = pointsIn[contactIdx.w];\n"
-" case 3:\n"
-" c->m_worldPosB[2] = pointsIn[contactIdx.z];\n"
-" case 2:\n"
-" c->m_worldPosB[1] = pointsIn[contactIdx.y];\n"
-" case 1:\n"
-" if (mprContactIndex<0)//test\n"
-" c->m_worldPosB[0] = pointsIn[contactIdx.x];\n"
-" default:\n"
-" {\n"
-" }\n"
-" };\n"
-" \n"
-" GET_NPOINTS(*c) = nReducedContacts;\n"
-" \n"
-" }\n"
-" \n"
-" \n"
-"//#endif\n"
-" \n"
-" }// if (numContactsOut>0)\n"
-" }// if (hasSeparatingAxis[i])\n"
-" }// if (i<numPairs)\n"
-" \n"
-" \n"
-"}\n"
-;
+static const char* satClipKernelsCL =
+ "#define TRIANGLE_NUM_CONVEX_FACES 5\n"
+ "#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
+ "#ifdef cl_ext_atomic_counters_32\n"
+ "#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
+ "#else\n"
+ "#define counter32_t volatile __global int*\n"
+ "#endif\n"
+ "#define GET_GROUP_IDX get_group_id(0)\n"
+ "#define GET_LOCAL_IDX get_local_id(0)\n"
+ "#define GET_GLOBAL_IDX get_global_id(0)\n"
+ "#define GET_GROUP_SIZE get_local_size(0)\n"
+ "#define GET_NUM_GROUPS get_num_groups(0)\n"
+ "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+ "#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
+ "#define AtomInc(x) atom_inc(&(x))\n"
+ "#define AtomInc1(x, out) out = atom_inc(&(x))\n"
+ "#define AppendInc(x, out) out = atomic_inc(x)\n"
+ "#define AtomAdd(x, value) atom_add(&(x), value)\n"
+ "#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
+ "#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
+ "#define max2 max\n"
+ "#define min2 min\n"
+ "typedef unsigned int u32;\n"
+ "#ifndef B3_CONTACT4DATA_H\n"
+ "#define B3_CONTACT4DATA_H\n"
+ "#ifndef B3_FLOAT4_H\n"
+ "#define B3_FLOAT4_H\n"
+ "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+ "#define B3_PLATFORM_DEFINITIONS_H\n"
+ "struct MyTest\n"
+ "{\n"
+ " int bla;\n"
+ "};\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
+ "#define B3_LARGE_FLOAT 1e18f\n"
+ "#define B3_INFINITY 1e18f\n"
+ "#define b3Assert(a)\n"
+ "#define b3ConstArray(a) __global const a*\n"
+ "#define b3AtomicInc atomic_inc\n"
+ "#define b3AtomicAdd atomic_add\n"
+ "#define b3Fabs fabs\n"
+ "#define b3Sqrt native_sqrt\n"
+ "#define b3Sin native_sin\n"
+ "#define b3Cos native_cos\n"
+ "#define B3_STATIC\n"
+ "#endif\n"
+ "#endif\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ " typedef float4 b3Float4;\n"
+ " #define b3Float4ConstArg const b3Float4\n"
+ " #define b3MakeFloat4 (float4)\n"
+ " float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+ " {\n"
+ " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+ " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+ " return dot(a1, b1);\n"
+ " }\n"
+ " b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+ " {\n"
+ " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+ " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+ " return cross(a1, b1);\n"
+ " }\n"
+ " #define b3MinFloat4 min\n"
+ " #define b3MaxFloat4 max\n"
+ " #define b3Normalized(a) normalize(a)\n"
+ "#endif \n"
+ " \n"
+ "inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
+ "{\n"
+ " if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
+ " return false;\n"
+ " return true;\n"
+ "}\n"
+ "inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
+ "{\n"
+ " float maxDot = -B3_INFINITY;\n"
+ " int i = 0;\n"
+ " int ptIndex = -1;\n"
+ " for( i = 0; i < vecLen; i++ )\n"
+ " {\n"
+ " float dot = b3Dot3F4(vecArray[i],vec);\n"
+ " \n"
+ " if( dot > maxDot )\n"
+ " {\n"
+ " maxDot = dot;\n"
+ " ptIndex = i;\n"
+ " }\n"
+ " }\n"
+ " b3Assert(ptIndex>=0);\n"
+ " if (ptIndex<0)\n"
+ " {\n"
+ " ptIndex = 0;\n"
+ " }\n"
+ " *dotOut = maxDot;\n"
+ " return ptIndex;\n"
+ "}\n"
+ "#endif //B3_FLOAT4_H\n"
+ "typedef struct b3Contact4Data b3Contact4Data_t;\n"
+ "struct b3Contact4Data\n"
+ "{\n"
+ " b3Float4 m_worldPosB[4];\n"
+ "// b3Float4 m_localPosA[4];\n"
+ "// b3Float4 m_localPosB[4];\n"
+ " b3Float4 m_worldNormalOnB; // w: m_nPoints\n"
+ " unsigned short m_restituitionCoeffCmp;\n"
+ " unsigned short m_frictionCoeffCmp;\n"
+ " int m_batchIdx;\n"
+ " int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
+ " int m_bodyBPtrAndSignBit;\n"
+ " int m_childIndexA;\n"
+ " int m_childIndexB;\n"
+ " int m_unused1;\n"
+ " int m_unused2;\n"
+ "};\n"
+ "inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
+ "{\n"
+ " return (int)contact->m_worldNormalOnB.w;\n"
+ "};\n"
+ "inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
+ "{\n"
+ " contact->m_worldNormalOnB.w = (float)numPoints;\n"
+ "};\n"
+ "#endif //B3_CONTACT4DATA_H\n"
+ "#ifndef B3_CONVEX_POLYHEDRON_DATA_H\n"
+ "#define B3_CONVEX_POLYHEDRON_DATA_H\n"
+ "#ifndef B3_FLOAT4_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#endif \n"
+ "#endif //B3_FLOAT4_H\n"
+ "#ifndef B3_QUAT_H\n"
+ "#define B3_QUAT_H\n"
+ "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#endif\n"
+ "#endif\n"
+ "#ifndef B3_FLOAT4_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#endif \n"
+ "#endif //B3_FLOAT4_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ " typedef float4 b3Quat;\n"
+ " #define b3QuatConstArg const b3Quat\n"
+ " \n"
+ " \n"
+ "inline float4 b3FastNormalize4(float4 v)\n"
+ "{\n"
+ " v = (float4)(v.xyz,0.f);\n"
+ " return fast_normalize(v);\n"
+ "}\n"
+ " \n"
+ "inline b3Quat b3QuatMul(b3Quat a, b3Quat b);\n"
+ "inline b3Quat b3QuatNormalized(b3QuatConstArg in);\n"
+ "inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec);\n"
+ "inline b3Quat b3QuatInvert(b3QuatConstArg q);\n"
+ "inline b3Quat b3QuatInverse(b3QuatConstArg q);\n"
+ "inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b)\n"
+ "{\n"
+ " b3Quat ans;\n"
+ " ans = b3Cross3( a, b );\n"
+ " ans += a.w*b+b.w*a;\n"
+ "// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+ " ans.w = a.w*b.w - b3Dot3F4(a, b);\n"
+ " return ans;\n"
+ "}\n"
+ "inline b3Quat b3QuatNormalized(b3QuatConstArg in)\n"
+ "{\n"
+ " b3Quat q;\n"
+ " q=in;\n"
+ " //return b3FastNormalize4(in);\n"
+ " float len = native_sqrt(dot(q, q));\n"
+ " if(len > 0.f)\n"
+ " {\n"
+ " q *= 1.f / len;\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " q.x = q.y = q.z = 0.f;\n"
+ " q.w = 1.f;\n"
+ " }\n"
+ " return q;\n"
+ "}\n"
+ "inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+ "{\n"
+ " b3Quat qInv = b3QuatInvert( q );\n"
+ " float4 vcpy = vec;\n"
+ " vcpy.w = 0.f;\n"
+ " float4 out = b3QuatMul(b3QuatMul(q,vcpy),qInv);\n"
+ " return out;\n"
+ "}\n"
+ "inline b3Quat b3QuatInverse(b3QuatConstArg q)\n"
+ "{\n"
+ " return (b3Quat)(-q.xyz, q.w);\n"
+ "}\n"
+ "inline b3Quat b3QuatInvert(b3QuatConstArg q)\n"
+ "{\n"
+ " return (b3Quat)(-q.xyz, q.w);\n"
+ "}\n"
+ "inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+ "{\n"
+ " return b3QuatRotate( b3QuatInvert( q ), vec );\n"
+ "}\n"
+ "inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation)\n"
+ "{\n"
+ " return b3QuatRotate( orientation, point ) + (translation);\n"
+ "}\n"
+ " \n"
+ "#endif \n"
+ "#endif //B3_QUAT_H\n"
+ "typedef struct b3GpuFace b3GpuFace_t;\n"
+ "struct b3GpuFace\n"
+ "{\n"
+ " b3Float4 m_plane;\n"
+ " int m_indexOffset;\n"
+ " int m_numIndices;\n"
+ " int m_unusedPadding1;\n"
+ " int m_unusedPadding2;\n"
+ "};\n"
+ "typedef struct b3ConvexPolyhedronData b3ConvexPolyhedronData_t;\n"
+ "struct b3ConvexPolyhedronData\n"
+ "{\n"
+ " b3Float4 m_localCenter;\n"
+ " b3Float4 m_extents;\n"
+ " b3Float4 mC;\n"
+ " b3Float4 mE;\n"
+ " float m_radius;\n"
+ " int m_faceOffset;\n"
+ " int m_numFaces;\n"
+ " int m_numVertices;\n"
+ " int m_vertexOffset;\n"
+ " int m_uniqueEdgesOffset;\n"
+ " int m_numUniqueEdges;\n"
+ " int m_unused;\n"
+ "};\n"
+ "#endif //B3_CONVEX_POLYHEDRON_DATA_H\n"
+ "#ifndef B3_COLLIDABLE_H\n"
+ "#define B3_COLLIDABLE_H\n"
+ "#ifndef B3_FLOAT4_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#endif \n"
+ "#endif //B3_FLOAT4_H\n"
+ "#ifndef B3_QUAT_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#endif \n"
+ "#endif //B3_QUAT_H\n"
+ "enum b3ShapeTypes\n"
+ "{\n"
+ " SHAPE_HEIGHT_FIELD=1,\n"
+ " SHAPE_CONVEX_HULL=3,\n"
+ " SHAPE_PLANE=4,\n"
+ " SHAPE_CONCAVE_TRIMESH=5,\n"
+ " SHAPE_COMPOUND_OF_CONVEX_HULLS=6,\n"
+ " SHAPE_SPHERE=7,\n"
+ " MAX_NUM_SHAPE_TYPES,\n"
+ "};\n"
+ "typedef struct b3Collidable b3Collidable_t;\n"
+ "struct b3Collidable\n"
+ "{\n"
+ " union {\n"
+ " int m_numChildShapes;\n"
+ " int m_bvhIndex;\n"
+ " };\n"
+ " union\n"
+ " {\n"
+ " float m_radius;\n"
+ " int m_compoundBvhIndex;\n"
+ " };\n"
+ " int m_shapeType;\n"
+ " int m_shapeIndex;\n"
+ "};\n"
+ "typedef struct b3GpuChildShape b3GpuChildShape_t;\n"
+ "struct b3GpuChildShape\n"
+ "{\n"
+ " b3Float4 m_childPosition;\n"
+ " b3Quat m_childOrientation;\n"
+ " int m_shapeIndex;\n"
+ " int m_unused0;\n"
+ " int m_unused1;\n"
+ " int m_unused2;\n"
+ "};\n"
+ "struct b3CompoundOverlappingPair\n"
+ "{\n"
+ " int m_bodyIndexA;\n"
+ " int m_bodyIndexB;\n"
+ "// int m_pairType;\n"
+ " int m_childShapeIndexA;\n"
+ " int m_childShapeIndexB;\n"
+ "};\n"
+ "#endif //B3_COLLIDABLE_H\n"
+ "#ifndef B3_RIGIDBODY_DATA_H\n"
+ "#define B3_RIGIDBODY_DATA_H\n"
+ "#ifndef B3_FLOAT4_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#endif \n"
+ "#endif //B3_FLOAT4_H\n"
+ "#ifndef B3_QUAT_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#endif \n"
+ "#endif //B3_QUAT_H\n"
+ "#ifndef B3_MAT3x3_H\n"
+ "#define B3_MAT3x3_H\n"
+ "#ifndef B3_QUAT_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#endif \n"
+ "#endif //B3_QUAT_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "typedef struct\n"
+ "{\n"
+ " b3Float4 m_row[3];\n"
+ "}b3Mat3x3;\n"
+ "#define b3Mat3x3ConstArg const b3Mat3x3\n"
+ "#define b3GetRow(m,row) (m.m_row[row])\n"
+ "inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat)\n"
+ "{\n"
+ " b3Float4 quat2 = (b3Float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);\n"
+ " b3Mat3x3 out;\n"
+ " out.m_row[0].x=1-2*quat2.y-2*quat2.z;\n"
+ " out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;\n"
+ " out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;\n"
+ " out.m_row[0].w = 0.f;\n"
+ " out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;\n"
+ " out.m_row[1].y=1-2*quat2.x-2*quat2.z;\n"
+ " out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;\n"
+ " out.m_row[1].w = 0.f;\n"
+ " out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;\n"
+ " out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;\n"
+ " out.m_row[2].z=1-2*quat2.x-2*quat2.y;\n"
+ " out.m_row[2].w = 0.f;\n"
+ " return out;\n"
+ "}\n"
+ "inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn)\n"
+ "{\n"
+ " b3Mat3x3 out;\n"
+ " out.m_row[0] = fabs(matIn.m_row[0]);\n"
+ " out.m_row[1] = fabs(matIn.m_row[1]);\n"
+ " out.m_row[2] = fabs(matIn.m_row[2]);\n"
+ " return out;\n"
+ "}\n"
+ "__inline\n"
+ "b3Mat3x3 mtZero();\n"
+ "__inline\n"
+ "b3Mat3x3 mtIdentity();\n"
+ "__inline\n"
+ "b3Mat3x3 mtTranspose(b3Mat3x3 m);\n"
+ "__inline\n"
+ "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);\n"
+ "__inline\n"
+ "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);\n"
+ "__inline\n"
+ "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);\n"
+ "__inline\n"
+ "b3Mat3x3 mtZero()\n"
+ "{\n"
+ " b3Mat3x3 m;\n"
+ " m.m_row[0] = (b3Float4)(0.f);\n"
+ " m.m_row[1] = (b3Float4)(0.f);\n"
+ " m.m_row[2] = (b3Float4)(0.f);\n"
+ " return m;\n"
+ "}\n"
+ "__inline\n"
+ "b3Mat3x3 mtIdentity()\n"
+ "{\n"
+ " b3Mat3x3 m;\n"
+ " m.m_row[0] = (b3Float4)(1,0,0,0);\n"
+ " m.m_row[1] = (b3Float4)(0,1,0,0);\n"
+ " m.m_row[2] = (b3Float4)(0,0,1,0);\n"
+ " return m;\n"
+ "}\n"
+ "__inline\n"
+ "b3Mat3x3 mtTranspose(b3Mat3x3 m)\n"
+ "{\n"
+ " b3Mat3x3 out;\n"
+ " out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
+ " out.m_row[1] = (b3Float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
+ " out.m_row[2] = (b3Float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
+ " return out;\n"
+ "}\n"
+ "__inline\n"
+ "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)\n"
+ "{\n"
+ " b3Mat3x3 transB;\n"
+ " transB = mtTranspose( b );\n"
+ " b3Mat3x3 ans;\n"
+ " // why this doesn't run when 0ing in the for{}\n"
+ " a.m_row[0].w = 0.f;\n"
+ " a.m_row[1].w = 0.f;\n"
+ " a.m_row[2].w = 0.f;\n"
+ " for(int i=0; i<3; i++)\n"
+ " {\n"
+ "// a.m_row[i].w = 0.f;\n"
+ " ans.m_row[i].x = b3Dot3F4(a.m_row[i],transB.m_row[0]);\n"
+ " ans.m_row[i].y = b3Dot3F4(a.m_row[i],transB.m_row[1]);\n"
+ " ans.m_row[i].z = b3Dot3F4(a.m_row[i],transB.m_row[2]);\n"
+ " ans.m_row[i].w = 0.f;\n"
+ " }\n"
+ " return ans;\n"
+ "}\n"
+ "__inline\n"
+ "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)\n"
+ "{\n"
+ " b3Float4 ans;\n"
+ " ans.x = b3Dot3F4( a.m_row[0], b );\n"
+ " ans.y = b3Dot3F4( a.m_row[1], b );\n"
+ " ans.z = b3Dot3F4( a.m_row[2], b );\n"
+ " ans.w = 0.f;\n"
+ " return ans;\n"
+ "}\n"
+ "__inline\n"
+ "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)\n"
+ "{\n"
+ " b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
+ " b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
+ " b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
+ " b3Float4 ans;\n"
+ " ans.x = b3Dot3F4( a, colx );\n"
+ " ans.y = b3Dot3F4( a, coly );\n"
+ " ans.z = b3Dot3F4( a, colz );\n"
+ " return ans;\n"
+ "}\n"
+ "#endif\n"
+ "#endif //B3_MAT3x3_H\n"
+ "typedef struct b3RigidBodyData b3RigidBodyData_t;\n"
+ "struct b3RigidBodyData\n"
+ "{\n"
+ " b3Float4 m_pos;\n"
+ " b3Quat m_quat;\n"
+ " b3Float4 m_linVel;\n"
+ " b3Float4 m_angVel;\n"
+ " int m_collidableIdx;\n"
+ " float m_invMass;\n"
+ " float m_restituitionCoeff;\n"
+ " float m_frictionCoeff;\n"
+ "};\n"
+ "typedef struct b3InertiaData b3InertiaData_t;\n"
+ "struct b3InertiaData\n"
+ "{\n"
+ " b3Mat3x3 m_invInertiaWorld;\n"
+ " b3Mat3x3 m_initInvInertia;\n"
+ "};\n"
+ "#endif //B3_RIGIDBODY_DATA_H\n"
+ " \n"
+ "#define GET_NPOINTS(x) (x).m_worldNormalOnB.w\n"
+ "#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
+ "#define make_float4 (float4)\n"
+ "#define make_float2 (float2)\n"
+ "#define make_uint4 (uint4)\n"
+ "#define make_int4 (int4)\n"
+ "#define make_uint2 (uint2)\n"
+ "#define make_int2 (int2)\n"
+ "__inline\n"
+ "float fastDiv(float numerator, float denominator)\n"
+ "{\n"
+ " return native_divide(numerator, denominator); \n"
+ "// return numerator/denominator; \n"
+ "}\n"
+ "__inline\n"
+ "float4 fastDiv4(float4 numerator, float4 denominator)\n"
+ "{\n"
+ " return native_divide(numerator, denominator); \n"
+ "}\n"
+ "__inline\n"
+ "float4 cross3(float4 a, float4 b)\n"
+ "{\n"
+ " return cross(a,b);\n"
+ "}\n"
+ "//#define dot3F4 dot\n"
+ "__inline\n"
+ "float dot3F4(float4 a, float4 b)\n"
+ "{\n"
+ " float4 a1 = make_float4(a.xyz,0.f);\n"
+ " float4 b1 = make_float4(b.xyz,0.f);\n"
+ " return dot(a1, b1);\n"
+ "}\n"
+ "__inline\n"
+ "float4 fastNormalize4(float4 v)\n"
+ "{\n"
+ " return fast_normalize(v);\n"
+ "}\n"
+ "///////////////////////////////////////\n"
+ "// Quaternion\n"
+ "///////////////////////////////////////\n"
+ "typedef float4 Quaternion;\n"
+ "__inline\n"
+ "Quaternion qtMul(Quaternion a, Quaternion b);\n"
+ "__inline\n"
+ "Quaternion qtNormalize(Quaternion in);\n"
+ "__inline\n"
+ "float4 qtRotate(Quaternion q, float4 vec);\n"
+ "__inline\n"
+ "Quaternion qtInvert(Quaternion q);\n"
+ "__inline\n"
+ "Quaternion qtMul(Quaternion a, Quaternion b)\n"
+ "{\n"
+ " Quaternion ans;\n"
+ " ans = cross3( a, b );\n"
+ " ans += a.w*b+b.w*a;\n"
+ "// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+ " ans.w = a.w*b.w - dot3F4(a, b);\n"
+ " return ans;\n"
+ "}\n"
+ "__inline\n"
+ "Quaternion qtNormalize(Quaternion in)\n"
+ "{\n"
+ " return fastNormalize4(in);\n"
+ "// in /= length( in );\n"
+ "// return in;\n"
+ "}\n"
+ "__inline\n"
+ "float4 qtRotate(Quaternion q, float4 vec)\n"
+ "{\n"
+ " Quaternion qInv = qtInvert( q );\n"
+ " float4 vcpy = vec;\n"
+ " vcpy.w = 0.f;\n"
+ " float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
+ " return out;\n"
+ "}\n"
+ "__inline\n"
+ "Quaternion qtInvert(Quaternion q)\n"
+ "{\n"
+ " return (Quaternion)(-q.xyz, q.w);\n"
+ "}\n"
+ "__inline\n"
+ "float4 qtInvRotate(const Quaternion q, float4 vec)\n"
+ "{\n"
+ " return qtRotate( qtInvert( q ), vec );\n"
+ "}\n"
+ "__inline\n"
+ "float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)\n"
+ "{\n"
+ " return qtRotate( *orientation, *p ) + (*translation);\n"
+ "}\n"
+ "__inline\n"
+ "float4 normalize3(const float4 a)\n"
+ "{\n"
+ " float4 n = make_float4(a.x, a.y, a.z, 0.f);\n"
+ " return fastNormalize4( n );\n"
+ "}\n"
+ "__inline float4 lerp3(const float4 a,const float4 b, float t)\n"
+ "{\n"
+ " return make_float4( a.x + (b.x - a.x) * t,\n"
+ " a.y + (b.y - a.y) * t,\n"
+ " a.z + (b.z - a.z) * t,\n"
+ " 0.f);\n"
+ "}\n"
+ "// Clips a face to the back of a plane, return the number of vertices out, stored in ppVtxOut\n"
+ "int clipFaceGlobal(__global const float4* pVtxIn, int numVertsIn, float4 planeNormalWS,float planeEqWS, __global float4* ppVtxOut)\n"
+ "{\n"
+ " \n"
+ " int ve;\n"
+ " float ds, de;\n"
+ " int numVertsOut = 0;\n"
+ " //double-check next test\n"
+ " if (numVertsIn < 2)\n"
+ " return 0;\n"
+ " \n"
+ " float4 firstVertex=pVtxIn[numVertsIn-1];\n"
+ " float4 endVertex = pVtxIn[0];\n"
+ " \n"
+ " ds = dot3F4(planeNormalWS,firstVertex)+planeEqWS;\n"
+ " \n"
+ " for (ve = 0; ve < numVertsIn; ve++)\n"
+ " {\n"
+ " endVertex=pVtxIn[ve];\n"
+ " de = dot3F4(planeNormalWS,endVertex)+planeEqWS;\n"
+ " if (ds<0)\n"
+ " {\n"
+ " if (de<0)\n"
+ " {\n"
+ " // Start < 0, end < 0, so output endVertex\n"
+ " ppVtxOut[numVertsOut++] = endVertex;\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " // Start < 0, end >= 0, so output intersection\n"
+ " ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );\n"
+ " }\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " if (de<0)\n"
+ " {\n"
+ " // Start >= 0, end < 0 so output intersection and end\n"
+ " ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );\n"
+ " ppVtxOut[numVertsOut++] = endVertex;\n"
+ " }\n"
+ " }\n"
+ " firstVertex = endVertex;\n"
+ " ds = de;\n"
+ " }\n"
+ " return numVertsOut;\n"
+ "}\n"
+ "// Clips a face to the back of a plane, return the number of vertices out, stored in ppVtxOut\n"
+ "int clipFace(const float4* pVtxIn, int numVertsIn, float4 planeNormalWS,float planeEqWS, float4* ppVtxOut)\n"
+ "{\n"
+ " \n"
+ " int ve;\n"
+ " float ds, de;\n"
+ " int numVertsOut = 0;\n"
+ "//double-check next test\n"
+ " if (numVertsIn < 2)\n"
+ " return 0;\n"
+ " float4 firstVertex=pVtxIn[numVertsIn-1];\n"
+ " float4 endVertex = pVtxIn[0];\n"
+ " \n"
+ " ds = dot3F4(planeNormalWS,firstVertex)+planeEqWS;\n"
+ " for (ve = 0; ve < numVertsIn; ve++)\n"
+ " {\n"
+ " endVertex=pVtxIn[ve];\n"
+ " de = dot3F4(planeNormalWS,endVertex)+planeEqWS;\n"
+ " if (ds<0)\n"
+ " {\n"
+ " if (de<0)\n"
+ " {\n"
+ " // Start < 0, end < 0, so output endVertex\n"
+ " ppVtxOut[numVertsOut++] = endVertex;\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " // Start < 0, end >= 0, so output intersection\n"
+ " ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );\n"
+ " }\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " if (de<0)\n"
+ " {\n"
+ " // Start >= 0, end < 0 so output intersection and end\n"
+ " ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );\n"
+ " ppVtxOut[numVertsOut++] = endVertex;\n"
+ " }\n"
+ " }\n"
+ " firstVertex = endVertex;\n"
+ " ds = de;\n"
+ " }\n"
+ " return numVertsOut;\n"
+ "}\n"
+ "int clipFaceAgainstHull(const float4 separatingNormal, __global const b3ConvexPolyhedronData_t* hullA, \n"
+ " const float4 posA, const Quaternion ornA, float4* worldVertsB1, int numWorldVertsB1,\n"
+ " float4* worldVertsB2, int capacityWorldVertsB2,\n"
+ " const float minDist, float maxDist,\n"
+ " __global const float4* vertices,\n"
+ " __global const b3GpuFace_t* faces,\n"
+ " __global const int* indices,\n"
+ " float4* contactsOut,\n"
+ " int contactCapacity)\n"
+ "{\n"
+ " int numContactsOut = 0;\n"
+ " float4* pVtxIn = worldVertsB1;\n"
+ " float4* pVtxOut = worldVertsB2;\n"
+ " \n"
+ " int numVertsIn = numWorldVertsB1;\n"
+ " int numVertsOut = 0;\n"
+ " int closestFaceA=-1;\n"
+ " {\n"
+ " float dmin = FLT_MAX;\n"
+ " for(int face=0;face<hullA->m_numFaces;face++)\n"
+ " {\n"
+ " const float4 Normal = make_float4(\n"
+ " faces[hullA->m_faceOffset+face].m_plane.x, \n"
+ " faces[hullA->m_faceOffset+face].m_plane.y, \n"
+ " faces[hullA->m_faceOffset+face].m_plane.z,0.f);\n"
+ " const float4 faceANormalWS = qtRotate(ornA,Normal);\n"
+ " \n"
+ " float d = dot3F4(faceANormalWS,separatingNormal);\n"
+ " if (d < dmin)\n"
+ " {\n"
+ " dmin = d;\n"
+ " closestFaceA = face;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " if (closestFaceA<0)\n"
+ " return numContactsOut;\n"
+ " b3GpuFace_t polyA = faces[hullA->m_faceOffset+closestFaceA];\n"
+ " // clip polygon to back of planes of all faces of hull A that are adjacent to witness face\n"
+ " int numVerticesA = polyA.m_numIndices;\n"
+ " for(int e0=0;e0<numVerticesA;e0++)\n"
+ " {\n"
+ " const float4 a = vertices[hullA->m_vertexOffset+indices[polyA.m_indexOffset+e0]];\n"
+ " const float4 b = vertices[hullA->m_vertexOffset+indices[polyA.m_indexOffset+((e0+1)%numVerticesA)]];\n"
+ " const float4 edge0 = a - b;\n"
+ " const float4 WorldEdge0 = qtRotate(ornA,edge0);\n"
+ " float4 planeNormalA = make_float4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);\n"
+ " float4 worldPlaneAnormal1 = qtRotate(ornA,planeNormalA);\n"
+ " float4 planeNormalWS1 = -cross3(WorldEdge0,worldPlaneAnormal1);\n"
+ " float4 worldA1 = transform(&a,&posA,&ornA);\n"
+ " float planeEqWS1 = -dot3F4(worldA1,planeNormalWS1);\n"
+ " \n"
+ " float4 planeNormalWS = planeNormalWS1;\n"
+ " float planeEqWS=planeEqWS1;\n"
+ " \n"
+ " //clip face\n"
+ " //clipFace(*pVtxIn, *pVtxOut,planeNormalWS,planeEqWS);\n"
+ " numVertsOut = clipFace(pVtxIn, numVertsIn, planeNormalWS,planeEqWS, pVtxOut);\n"
+ " //btSwap(pVtxIn,pVtxOut);\n"
+ " float4* tmp = pVtxOut;\n"
+ " pVtxOut = pVtxIn;\n"
+ " pVtxIn = tmp;\n"
+ " numVertsIn = numVertsOut;\n"
+ " numVertsOut = 0;\n"
+ " }\n"
+ " \n"
+ " // only keep points that are behind the witness face\n"
+ " {\n"
+ " float4 localPlaneNormal = make_float4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);\n"
+ " float localPlaneEq = polyA.m_plane.w;\n"
+ " float4 planeNormalWS = qtRotate(ornA,localPlaneNormal);\n"
+ " float planeEqWS=localPlaneEq-dot3F4(planeNormalWS,posA);\n"
+ " for (int i=0;i<numVertsIn;i++)\n"
+ " {\n"
+ " float depth = dot3F4(planeNormalWS,pVtxIn[i])+planeEqWS;\n"
+ " if (depth <=minDist)\n"
+ " {\n"
+ " depth = minDist;\n"
+ " }\n"
+ " if (depth <=maxDist)\n"
+ " {\n"
+ " float4 pointInWorld = pVtxIn[i];\n"
+ " //resultOut.addContactPoint(separatingNormal,point,depth);\n"
+ " contactsOut[numContactsOut++] = make_float4(pointInWorld.x,pointInWorld.y,pointInWorld.z,depth);\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " return numContactsOut;\n"
+ "}\n"
+ "int clipFaceAgainstHullLocalA(const float4 separatingNormal, const b3ConvexPolyhedronData_t* hullA, \n"
+ " const float4 posA, const Quaternion ornA, float4* worldVertsB1, int numWorldVertsB1,\n"
+ " float4* worldVertsB2, int capacityWorldVertsB2,\n"
+ " const float minDist, float maxDist,\n"
+ " const float4* verticesA,\n"
+ " const b3GpuFace_t* facesA,\n"
+ " const int* indicesA,\n"
+ " __global const float4* verticesB,\n"
+ " __global const b3GpuFace_t* facesB,\n"
+ " __global const int* indicesB,\n"
+ " float4* contactsOut,\n"
+ " int contactCapacity)\n"
+ "{\n"
+ " int numContactsOut = 0;\n"
+ " float4* pVtxIn = worldVertsB1;\n"
+ " float4* pVtxOut = worldVertsB2;\n"
+ " \n"
+ " int numVertsIn = numWorldVertsB1;\n"
+ " int numVertsOut = 0;\n"
+ " int closestFaceA=-1;\n"
+ " {\n"
+ " float dmin = FLT_MAX;\n"
+ " for(int face=0;face<hullA->m_numFaces;face++)\n"
+ " {\n"
+ " const float4 Normal = make_float4(\n"
+ " facesA[hullA->m_faceOffset+face].m_plane.x, \n"
+ " facesA[hullA->m_faceOffset+face].m_plane.y, \n"
+ " facesA[hullA->m_faceOffset+face].m_plane.z,0.f);\n"
+ " const float4 faceANormalWS = qtRotate(ornA,Normal);\n"
+ " \n"
+ " float d = dot3F4(faceANormalWS,separatingNormal);\n"
+ " if (d < dmin)\n"
+ " {\n"
+ " dmin = d;\n"
+ " closestFaceA = face;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " if (closestFaceA<0)\n"
+ " return numContactsOut;\n"
+ " b3GpuFace_t polyA = facesA[hullA->m_faceOffset+closestFaceA];\n"
+ " // clip polygon to back of planes of all faces of hull A that are adjacent to witness face\n"
+ " int numVerticesA = polyA.m_numIndices;\n"
+ " for(int e0=0;e0<numVerticesA;e0++)\n"
+ " {\n"
+ " const float4 a = verticesA[hullA->m_vertexOffset+indicesA[polyA.m_indexOffset+e0]];\n"
+ " const float4 b = verticesA[hullA->m_vertexOffset+indicesA[polyA.m_indexOffset+((e0+1)%numVerticesA)]];\n"
+ " const float4 edge0 = a - b;\n"
+ " const float4 WorldEdge0 = qtRotate(ornA,edge0);\n"
+ " float4 planeNormalA = make_float4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);\n"
+ " float4 worldPlaneAnormal1 = qtRotate(ornA,planeNormalA);\n"
+ " float4 planeNormalWS1 = -cross3(WorldEdge0,worldPlaneAnormal1);\n"
+ " float4 worldA1 = transform(&a,&posA,&ornA);\n"
+ " float planeEqWS1 = -dot3F4(worldA1,planeNormalWS1);\n"
+ " \n"
+ " float4 planeNormalWS = planeNormalWS1;\n"
+ " float planeEqWS=planeEqWS1;\n"
+ " \n"
+ " //clip face\n"
+ " //clipFace(*pVtxIn, *pVtxOut,planeNormalWS,planeEqWS);\n"
+ " numVertsOut = clipFace(pVtxIn, numVertsIn, planeNormalWS,planeEqWS, pVtxOut);\n"
+ " //btSwap(pVtxIn,pVtxOut);\n"
+ " float4* tmp = pVtxOut;\n"
+ " pVtxOut = pVtxIn;\n"
+ " pVtxIn = tmp;\n"
+ " numVertsIn = numVertsOut;\n"
+ " numVertsOut = 0;\n"
+ " }\n"
+ " \n"
+ " // only keep points that are behind the witness face\n"
+ " {\n"
+ " float4 localPlaneNormal = make_float4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);\n"
+ " float localPlaneEq = polyA.m_plane.w;\n"
+ " float4 planeNormalWS = qtRotate(ornA,localPlaneNormal);\n"
+ " float planeEqWS=localPlaneEq-dot3F4(planeNormalWS,posA);\n"
+ " for (int i=0;i<numVertsIn;i++)\n"
+ " {\n"
+ " float depth = dot3F4(planeNormalWS,pVtxIn[i])+planeEqWS;\n"
+ " if (depth <=minDist)\n"
+ " {\n"
+ " depth = minDist;\n"
+ " }\n"
+ " if (depth <=maxDist)\n"
+ " {\n"
+ " float4 pointInWorld = pVtxIn[i];\n"
+ " //resultOut.addContactPoint(separatingNormal,point,depth);\n"
+ " contactsOut[numContactsOut++] = make_float4(pointInWorld.x,pointInWorld.y,pointInWorld.z,depth);\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " return numContactsOut;\n"
+ "}\n"
+ "int clipHullAgainstHull(const float4 separatingNormal,\n"
+ " __global const b3ConvexPolyhedronData_t* hullA, __global const b3ConvexPolyhedronData_t* hullB, \n"
+ " const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB, \n"
+ " float4* worldVertsB1, float4* worldVertsB2, int capacityWorldVerts,\n"
+ " const float minDist, float maxDist,\n"
+ " __global const float4* vertices,\n"
+ " __global const b3GpuFace_t* faces,\n"
+ " __global const int* indices,\n"
+ " float4* localContactsOut,\n"
+ " int localContactCapacity)\n"
+ "{\n"
+ " int numContactsOut = 0;\n"
+ " int numWorldVertsB1= 0;\n"
+ " int closestFaceB=-1;\n"
+ " float dmax = -FLT_MAX;\n"
+ " {\n"
+ " for(int face=0;face<hullB->m_numFaces;face++)\n"
+ " {\n"
+ " const float4 Normal = make_float4(faces[hullB->m_faceOffset+face].m_plane.x, \n"
+ " faces[hullB->m_faceOffset+face].m_plane.y, faces[hullB->m_faceOffset+face].m_plane.z,0.f);\n"
+ " const float4 WorldNormal = qtRotate(ornB, Normal);\n"
+ " float d = dot3F4(WorldNormal,separatingNormal);\n"
+ " if (d > dmax)\n"
+ " {\n"
+ " dmax = d;\n"
+ " closestFaceB = face;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " {\n"
+ " const b3GpuFace_t polyB = faces[hullB->m_faceOffset+closestFaceB];\n"
+ " const int numVertices = polyB.m_numIndices;\n"
+ " for(int e0=0;e0<numVertices;e0++)\n"
+ " {\n"
+ " const float4 b = vertices[hullB->m_vertexOffset+indices[polyB.m_indexOffset+e0]];\n"
+ " worldVertsB1[numWorldVertsB1++] = transform(&b,&posB,&ornB);\n"
+ " }\n"
+ " }\n"
+ " if (closestFaceB>=0)\n"
+ " {\n"
+ " numContactsOut = clipFaceAgainstHull(separatingNormal, hullA, \n"
+ " posA,ornA,\n"
+ " worldVertsB1,numWorldVertsB1,worldVertsB2,capacityWorldVerts, minDist, maxDist,vertices,\n"
+ " faces,\n"
+ " indices,localContactsOut,localContactCapacity);\n"
+ " }\n"
+ " return numContactsOut;\n"
+ "}\n"
+ "int clipHullAgainstHullLocalA(const float4 separatingNormal,\n"
+ " const b3ConvexPolyhedronData_t* hullA, __global const b3ConvexPolyhedronData_t* hullB, \n"
+ " const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB, \n"
+ " float4* worldVertsB1, float4* worldVertsB2, int capacityWorldVerts,\n"
+ " const float minDist, float maxDist,\n"
+ " const float4* verticesA,\n"
+ " const b3GpuFace_t* facesA,\n"
+ " const int* indicesA,\n"
+ " __global const float4* verticesB,\n"
+ " __global const b3GpuFace_t* facesB,\n"
+ " __global const int* indicesB,\n"
+ " float4* localContactsOut,\n"
+ " int localContactCapacity)\n"
+ "{\n"
+ " int numContactsOut = 0;\n"
+ " int numWorldVertsB1= 0;\n"
+ " int closestFaceB=-1;\n"
+ " float dmax = -FLT_MAX;\n"
+ " {\n"
+ " for(int face=0;face<hullB->m_numFaces;face++)\n"
+ " {\n"
+ " const float4 Normal = make_float4(facesB[hullB->m_faceOffset+face].m_plane.x, \n"
+ " facesB[hullB->m_faceOffset+face].m_plane.y, facesB[hullB->m_faceOffset+face].m_plane.z,0.f);\n"
+ " const float4 WorldNormal = qtRotate(ornB, Normal);\n"
+ " float d = dot3F4(WorldNormal,separatingNormal);\n"
+ " if (d > dmax)\n"
+ " {\n"
+ " dmax = d;\n"
+ " closestFaceB = face;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " {\n"
+ " const b3GpuFace_t polyB = facesB[hullB->m_faceOffset+closestFaceB];\n"
+ " const int numVertices = polyB.m_numIndices;\n"
+ " for(int e0=0;e0<numVertices;e0++)\n"
+ " {\n"
+ " const float4 b = verticesB[hullB->m_vertexOffset+indicesB[polyB.m_indexOffset+e0]];\n"
+ " worldVertsB1[numWorldVertsB1++] = transform(&b,&posB,&ornB);\n"
+ " }\n"
+ " }\n"
+ " if (closestFaceB>=0)\n"
+ " {\n"
+ " numContactsOut = clipFaceAgainstHullLocalA(separatingNormal, hullA, \n"
+ " posA,ornA,\n"
+ " worldVertsB1,numWorldVertsB1,worldVertsB2,capacityWorldVerts, minDist, maxDist,\n"
+ " verticesA,facesA,indicesA,\n"
+ " verticesB,facesB,indicesB,\n"
+ " localContactsOut,localContactCapacity);\n"
+ " }\n"
+ " return numContactsOut;\n"
+ "}\n"
+ "#define PARALLEL_SUM(v, n) for(int j=1; j<n; j++) v[0] += v[j];\n"
+ "#define PARALLEL_DO(execution, n) for(int ie=0; ie<n; ie++){execution;}\n"
+ "#define REDUCE_MAX(v, n) {int i=0; for(int offset=0; offset<n; offset++) v[i] = (v[i].y > v[i+offset].y)? v[i]: v[i+offset]; }\n"
+ "#define REDUCE_MIN(v, n) {int i=0; for(int offset=0; offset<n; offset++) v[i] = (v[i].y < v[i+offset].y)? v[i]: v[i+offset]; }\n"
+ "int extractManifoldSequentialGlobal(__global const float4* p, int nPoints, float4 nearNormal, int4* contactIdx)\n"
+ "{\n"
+ " if( nPoints == 0 )\n"
+ " return 0;\n"
+ " \n"
+ " if (nPoints <=4)\n"
+ " return nPoints;\n"
+ " \n"
+ " \n"
+ " if (nPoints >64)\n"
+ " nPoints = 64;\n"
+ " \n"
+ " float4 center = make_float4(0.f);\n"
+ " {\n"
+ " \n"
+ " for (int i=0;i<nPoints;i++)\n"
+ " center += p[i];\n"
+ " center /= (float)nPoints;\n"
+ " }\n"
+ " \n"
+ " \n"
+ " \n"
+ " // sample 4 directions\n"
+ " \n"
+ " float4 aVector = p[0] - center;\n"
+ " float4 u = cross3( nearNormal, aVector );\n"
+ " float4 v = cross3( nearNormal, u );\n"
+ " u = normalize3( u );\n"
+ " v = normalize3( v );\n"
+ " \n"
+ " \n"
+ " //keep point with deepest penetration\n"
+ " float minW= FLT_MAX;\n"
+ " \n"
+ " int minIndex=-1;\n"
+ " \n"
+ " float4 maxDots;\n"
+ " maxDots.x = FLT_MIN;\n"
+ " maxDots.y = FLT_MIN;\n"
+ " maxDots.z = FLT_MIN;\n"
+ " maxDots.w = FLT_MIN;\n"
+ " \n"
+ " // idx, distance\n"
+ " for(int ie = 0; ie<nPoints; ie++ )\n"
+ " {\n"
+ " if (p[ie].w<minW)\n"
+ " {\n"
+ " minW = p[ie].w;\n"
+ " minIndex=ie;\n"
+ " }\n"
+ " float f;\n"
+ " float4 r = p[ie]-center;\n"
+ " f = dot3F4( u, r );\n"
+ " if (f<maxDots.x)\n"
+ " {\n"
+ " maxDots.x = f;\n"
+ " contactIdx[0].x = ie;\n"
+ " }\n"
+ " \n"
+ " f = dot3F4( -u, r );\n"
+ " if (f<maxDots.y)\n"
+ " {\n"
+ " maxDots.y = f;\n"
+ " contactIdx[0].y = ie;\n"
+ " }\n"
+ " \n"
+ " \n"
+ " f = dot3F4( v, r );\n"
+ " if (f<maxDots.z)\n"
+ " {\n"
+ " maxDots.z = f;\n"
+ " contactIdx[0].z = ie;\n"
+ " }\n"
+ " \n"
+ " f = dot3F4( -v, r );\n"
+ " if (f<maxDots.w)\n"
+ " {\n"
+ " maxDots.w = f;\n"
+ " contactIdx[0].w = ie;\n"
+ " }\n"
+ " \n"
+ " }\n"
+ " \n"
+ " if (contactIdx[0].x != minIndex && contactIdx[0].y != minIndex && contactIdx[0].z != minIndex && contactIdx[0].w != minIndex)\n"
+ " {\n"
+ " //replace the first contact with minimum (todo: replace contact with least penetration)\n"
+ " contactIdx[0].x = minIndex;\n"
+ " }\n"
+ " \n"
+ " return 4;\n"
+ " \n"
+ "}\n"
+ "int extractManifoldSequentialGlobalFake(__global const float4* p, int nPoints, float4 nearNormal, int* contactIdx)\n"
+ "{\n"
+ " contactIdx[0] = 0;\n"
+ " contactIdx[1] = 1;\n"
+ " contactIdx[2] = 2;\n"
+ " contactIdx[3] = 3;\n"
+ " \n"
+ " if( nPoints == 0 ) return 0;\n"
+ " \n"
+ " nPoints = min2( nPoints, 4 );\n"
+ " return nPoints;\n"
+ " \n"
+ "}\n"
+ "int extractManifoldSequential(const float4* p, int nPoints, float4 nearNormal, int* contactIdx)\n"
+ "{\n"
+ " if( nPoints == 0 ) return 0;\n"
+ " nPoints = min2( nPoints, 64 );\n"
+ " float4 center = make_float4(0.f);\n"
+ " {\n"
+ " float4 v[64];\n"
+ " for (int i=0;i<nPoints;i++)\n"
+ " v[i] = p[i];\n"
+ " //memcpy( v, p, nPoints*sizeof(float4) );\n"
+ " PARALLEL_SUM( v, nPoints );\n"
+ " center = v[0]/(float)nPoints;\n"
+ " }\n"
+ " \n"
+ " { // sample 4 directions\n"
+ " if( nPoints < 4 )\n"
+ " {\n"
+ " for(int i=0; i<nPoints; i++) \n"
+ " contactIdx[i] = i;\n"
+ " return nPoints;\n"
+ " }\n"
+ " float4 aVector = p[0] - center;\n"
+ " float4 u = cross3( nearNormal, aVector );\n"
+ " float4 v = cross3( nearNormal, u );\n"
+ " u = normalize3( u );\n"
+ " v = normalize3( v );\n"
+ " int idx[4];\n"
+ " float2 max00 = make_float2(0,FLT_MAX);\n"
+ " {\n"
+ " // idx, distance\n"
+ " {\n"
+ " {\n"
+ " int4 a[64];\n"
+ " for(int ie = 0; ie<nPoints; ie++ )\n"
+ " {\n"
+ " \n"
+ " \n"
+ " float f;\n"
+ " float4 r = p[ie]-center;\n"
+ " f = dot3F4( u, r );\n"
+ " a[ie].x = ((*(u32*)&f) & 0xffffff00) | (0xff & ie);\n"
+ " f = dot3F4( -u, r );\n"
+ " a[ie].y = ((*(u32*)&f) & 0xffffff00) | (0xff & ie);\n"
+ " f = dot3F4( v, r );\n"
+ " a[ie].z = ((*(u32*)&f) & 0xffffff00) | (0xff & ie);\n"
+ " f = dot3F4( -v, r );\n"
+ " a[ie].w = ((*(u32*)&f) & 0xffffff00) | (0xff & ie);\n"
+ " }\n"
+ " for(int ie=0; ie<nPoints; ie++)\n"
+ " {\n"
+ " a[0].x = (a[0].x > a[ie].x )? a[0].x: a[ie].x;\n"
+ " a[0].y = (a[0].y > a[ie].y )? a[0].y: a[ie].y;\n"
+ " a[0].z = (a[0].z > a[ie].z )? a[0].z: a[ie].z;\n"
+ " a[0].w = (a[0].w > a[ie].w )? a[0].w: a[ie].w;\n"
+ " }\n"
+ " idx[0] = (int)a[0].x & 0xff;\n"
+ " idx[1] = (int)a[0].y & 0xff;\n"
+ " idx[2] = (int)a[0].z & 0xff;\n"
+ " idx[3] = (int)a[0].w & 0xff;\n"
+ " }\n"
+ " }\n"
+ " {\n"
+ " float2 h[64];\n"
+ " PARALLEL_DO( h[ie] = make_float2((float)ie, p[ie].w), nPoints );\n"
+ " REDUCE_MIN( h, nPoints );\n"
+ " max00 = h[0];\n"
+ " }\n"
+ " }\n"
+ " contactIdx[0] = idx[0];\n"
+ " contactIdx[1] = idx[1];\n"
+ " contactIdx[2] = idx[2];\n"
+ " contactIdx[3] = idx[3];\n"
+ " return 4;\n"
+ " }\n"
+ "}\n"
+ "__kernel void extractManifoldAndAddContactKernel(__global const int4* pairs, \n"
+ " __global const b3RigidBodyData_t* rigidBodies, \n"
+ " __global const float4* closestPointsWorld,\n"
+ " __global const float4* separatingNormalsWorld,\n"
+ " __global const int* contactCounts,\n"
+ " __global const int* contactOffsets,\n"
+ " __global struct b3Contact4Data* restrict contactsOut,\n"
+ " counter32_t nContactsOut,\n"
+ " int contactCapacity,\n"
+ " int numPairs,\n"
+ " int pairIndex\n"
+ " )\n"
+ "{\n"
+ " int idx = get_global_id(0);\n"
+ " \n"
+ " if (idx<numPairs)\n"
+ " {\n"
+ " float4 normal = separatingNormalsWorld[idx];\n"
+ " int nPoints = contactCounts[idx];\n"
+ " __global const float4* pointsIn = &closestPointsWorld[contactOffsets[idx]];\n"
+ " float4 localPoints[64];\n"
+ " for (int i=0;i<nPoints;i++)\n"
+ " {\n"
+ " localPoints[i] = pointsIn[i];\n"
+ " }\n"
+ " int contactIdx[4];// = {-1,-1,-1,-1};\n"
+ " contactIdx[0] = -1;\n"
+ " contactIdx[1] = -1;\n"
+ " contactIdx[2] = -1;\n"
+ " contactIdx[3] = -1;\n"
+ " int nContacts = extractManifoldSequential(localPoints, nPoints, normal, contactIdx);\n"
+ " int dstIdx;\n"
+ " AppendInc( nContactsOut, dstIdx );\n"
+ " if (dstIdx<contactCapacity)\n"
+ " {\n"
+ " __global struct b3Contact4Data* c = contactsOut + dstIdx;\n"
+ " c->m_worldNormalOnB = -normal;\n"
+ " c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
+ " c->m_batchIdx = idx;\n"
+ " int bodyA = pairs[pairIndex].x;\n"
+ " int bodyB = pairs[pairIndex].y;\n"
+ " c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0 ? -bodyA:bodyA;\n"
+ " c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0 ? -bodyB:bodyB;\n"
+ " c->m_childIndexA = -1;\n"
+ " c->m_childIndexB = -1;\n"
+ " for (int i=0;i<nContacts;i++)\n"
+ " {\n"
+ " c->m_worldPosB[i] = localPoints[contactIdx[i]];\n"
+ " }\n"
+ " GET_NPOINTS(*c) = nContacts;\n"
+ " }\n"
+ " }\n"
+ "}\n"
+ "void trInverse(float4 translationIn, Quaternion orientationIn,\n"
+ " float4* translationOut, Quaternion* orientationOut)\n"
+ "{\n"
+ " *orientationOut = qtInvert(orientationIn);\n"
+ " *translationOut = qtRotate(*orientationOut, -translationIn);\n"
+ "}\n"
+ "void trMul(float4 translationA, Quaternion orientationA,\n"
+ " float4 translationB, Quaternion orientationB,\n"
+ " float4* translationOut, Quaternion* orientationOut)\n"
+ "{\n"
+ " *orientationOut = qtMul(orientationA,orientationB);\n"
+ " *translationOut = transform(&translationB,&translationA,&orientationA);\n"
+ "}\n"
+ "__kernel void clipHullHullKernel( __global int4* pairs, \n"
+ " __global const b3RigidBodyData_t* rigidBodies, \n"
+ " __global const b3Collidable_t* collidables,\n"
+ " __global const b3ConvexPolyhedronData_t* convexShapes, \n"
+ " __global const float4* vertices,\n"
+ " __global const float4* uniqueEdges,\n"
+ " __global const b3GpuFace_t* faces,\n"
+ " __global const int* indices,\n"
+ " __global const float4* separatingNormals,\n"
+ " __global const int* hasSeparatingAxis,\n"
+ " __global struct b3Contact4Data* restrict globalContactsOut,\n"
+ " counter32_t nGlobalContactsOut,\n"
+ " int numPairs,\n"
+ " int contactCapacity)\n"
+ "{\n"
+ " int i = get_global_id(0);\n"
+ " int pairIndex = i;\n"
+ " \n"
+ " float4 worldVertsB1[64];\n"
+ " float4 worldVertsB2[64];\n"
+ " int capacityWorldVerts = 64; \n"
+ " float4 localContactsOut[64];\n"
+ " int localContactCapacity=64;\n"
+ " \n"
+ " float minDist = -1e30f;\n"
+ " float maxDist = 0.02f;\n"
+ " if (i<numPairs)\n"
+ " {\n"
+ " int bodyIndexA = pairs[i].x;\n"
+ " int bodyIndexB = pairs[i].y;\n"
+ " \n"
+ " int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+ " int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+ " if (hasSeparatingAxis[i])\n"
+ " {\n"
+ " \n"
+ " int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+ " int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+ " \n"
+ " \n"
+ " int numLocalContactsOut = clipHullAgainstHull(separatingNormals[i],\n"
+ " &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],\n"
+ " rigidBodies[bodyIndexA].m_pos,rigidBodies[bodyIndexA].m_quat,\n"
+ " rigidBodies[bodyIndexB].m_pos,rigidBodies[bodyIndexB].m_quat,\n"
+ " worldVertsB1,worldVertsB2,capacityWorldVerts,\n"
+ " minDist, maxDist,\n"
+ " vertices,faces,indices,\n"
+ " localContactsOut,localContactCapacity);\n"
+ " \n"
+ " if (numLocalContactsOut>0)\n"
+ " {\n"
+ " float4 normal = -separatingNormals[i];\n"
+ " int nPoints = numLocalContactsOut;\n"
+ " float4* pointsIn = localContactsOut;\n"
+ " int contactIdx[4];// = {-1,-1,-1,-1};\n"
+ " contactIdx[0] = -1;\n"
+ " contactIdx[1] = -1;\n"
+ " contactIdx[2] = -1;\n"
+ " contactIdx[3] = -1;\n"
+ " \n"
+ " int nReducedContacts = extractManifoldSequential(pointsIn, nPoints, normal, contactIdx);\n"
+ " \n"
+ " \n"
+ " int mprContactIndex = pairs[pairIndex].z;\n"
+ " int dstIdx = mprContactIndex;\n"
+ " if (dstIdx<0)\n"
+ " {\n"
+ " AppendInc( nGlobalContactsOut, dstIdx );\n"
+ " }\n"
+ " if (dstIdx<contactCapacity)\n"
+ " {\n"
+ " pairs[pairIndex].z = dstIdx;\n"
+ " __global struct b3Contact4Data* c = globalContactsOut+ dstIdx;\n"
+ " c->m_worldNormalOnB = -normal;\n"
+ " c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
+ " c->m_batchIdx = pairIndex;\n"
+ " int bodyA = pairs[pairIndex].x;\n"
+ " int bodyB = pairs[pairIndex].y;\n"
+ " c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;\n"
+ " c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;\n"
+ " c->m_childIndexA = -1;\n"
+ " c->m_childIndexB = -1;\n"
+ " for (int i=0;i<nReducedContacts;i++)\n"
+ " {\n"
+ " //this condition means: overwrite contact point, unless at index i==0 we have a valid 'mpr' contact\n"
+ " if (i>0||(mprContactIndex<0))\n"
+ " {\n"
+ " c->m_worldPosB[i] = pointsIn[contactIdx[i]];\n"
+ " }\n"
+ " }\n"
+ " GET_NPOINTS(*c) = nReducedContacts;\n"
+ " }\n"
+ " \n"
+ " }// if (numContactsOut>0)\n"
+ " }// if (hasSeparatingAxis[i])\n"
+ " }// if (i<numPairs)\n"
+ "}\n"
+ "__kernel void clipCompoundsHullHullKernel( __global const int4* gpuCompoundPairs, \n"
+ " __global const b3RigidBodyData_t* rigidBodies, \n"
+ " __global const b3Collidable_t* collidables,\n"
+ " __global const b3ConvexPolyhedronData_t* convexShapes, \n"
+ " __global const float4* vertices,\n"
+ " __global const float4* uniqueEdges,\n"
+ " __global const b3GpuFace_t* faces,\n"
+ " __global const int* indices,\n"
+ " __global const b3GpuChildShape_t* gpuChildShapes,\n"
+ " __global const float4* gpuCompoundSepNormalsOut,\n"
+ " __global const int* gpuHasCompoundSepNormalsOut,\n"
+ " __global struct b3Contact4Data* restrict globalContactsOut,\n"
+ " counter32_t nGlobalContactsOut,\n"
+ " int numCompoundPairs, int maxContactCapacity)\n"
+ "{\n"
+ " int i = get_global_id(0);\n"
+ " int pairIndex = i;\n"
+ " \n"
+ " float4 worldVertsB1[64];\n"
+ " float4 worldVertsB2[64];\n"
+ " int capacityWorldVerts = 64; \n"
+ " float4 localContactsOut[64];\n"
+ " int localContactCapacity=64;\n"
+ " \n"
+ " float minDist = -1e30f;\n"
+ " float maxDist = 0.02f;\n"
+ " if (i<numCompoundPairs)\n"
+ " {\n"
+ " if (gpuHasCompoundSepNormalsOut[i])\n"
+ " {\n"
+ " int bodyIndexA = gpuCompoundPairs[i].x;\n"
+ " int bodyIndexB = gpuCompoundPairs[i].y;\n"
+ " \n"
+ " int childShapeIndexA = gpuCompoundPairs[i].z;\n"
+ " int childShapeIndexB = gpuCompoundPairs[i].w;\n"
+ " \n"
+ " int collidableIndexA = -1;\n"
+ " int collidableIndexB = -1;\n"
+ " \n"
+ " float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
+ " float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+ " \n"
+ " float4 ornB = rigidBodies[bodyIndexB].m_quat;\n"
+ " float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+ " \n"
+ " if (childShapeIndexA >= 0)\n"
+ " {\n"
+ " collidableIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;\n"
+ " float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;\n"
+ " float4 childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;\n"
+ " float4 newPosA = qtRotate(ornA,childPosA)+posA;\n"
+ " float4 newOrnA = qtMul(ornA,childOrnA);\n"
+ " posA = newPosA;\n"
+ " ornA = newOrnA;\n"
+ " } else\n"
+ " {\n"
+ " collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+ " }\n"
+ " \n"
+ " if (childShapeIndexB>=0)\n"
+ " {\n"
+ " collidableIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
+ " float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
+ " float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
+ " float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
+ " float4 newOrnB = qtMul(ornB,childOrnB);\n"
+ " posB = newPosB;\n"
+ " ornB = newOrnB;\n"
+ " } else\n"
+ " {\n"
+ " collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx; \n"
+ " }\n"
+ " \n"
+ " int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+ " int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+ " \n"
+ " int numLocalContactsOut = clipHullAgainstHull(gpuCompoundSepNormalsOut[i],\n"
+ " &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],\n"
+ " posA,ornA,\n"
+ " posB,ornB,\n"
+ " worldVertsB1,worldVertsB2,capacityWorldVerts,\n"
+ " minDist, maxDist,\n"
+ " vertices,faces,indices,\n"
+ " localContactsOut,localContactCapacity);\n"
+ " \n"
+ " if (numLocalContactsOut>0)\n"
+ " {\n"
+ " float4 normal = -gpuCompoundSepNormalsOut[i];\n"
+ " int nPoints = numLocalContactsOut;\n"
+ " float4* pointsIn = localContactsOut;\n"
+ " int contactIdx[4];// = {-1,-1,-1,-1};\n"
+ " contactIdx[0] = -1;\n"
+ " contactIdx[1] = -1;\n"
+ " contactIdx[2] = -1;\n"
+ " contactIdx[3] = -1;\n"
+ " \n"
+ " int nReducedContacts = extractManifoldSequential(pointsIn, nPoints, normal, contactIdx);\n"
+ " \n"
+ " int dstIdx;\n"
+ " AppendInc( nGlobalContactsOut, dstIdx );\n"
+ " if ((dstIdx+nReducedContacts) < maxContactCapacity)\n"
+ " {\n"
+ " __global struct b3Contact4Data* c = globalContactsOut+ dstIdx;\n"
+ " c->m_worldNormalOnB = -normal;\n"
+ " c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
+ " c->m_batchIdx = pairIndex;\n"
+ " int bodyA = gpuCompoundPairs[pairIndex].x;\n"
+ " int bodyB = gpuCompoundPairs[pairIndex].y;\n"
+ " c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;\n"
+ " c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;\n"
+ " c->m_childIndexA = childShapeIndexA;\n"
+ " c->m_childIndexB = childShapeIndexB;\n"
+ " for (int i=0;i<nReducedContacts;i++)\n"
+ " {\n"
+ " c->m_worldPosB[i] = pointsIn[contactIdx[i]];\n"
+ " }\n"
+ " GET_NPOINTS(*c) = nReducedContacts;\n"
+ " }\n"
+ " \n"
+ " }// if (numContactsOut>0)\n"
+ " }// if (gpuHasCompoundSepNormalsOut[i])\n"
+ " }// if (i<numCompoundPairs)\n"
+ "}\n"
+ "__kernel void sphereSphereCollisionKernel( __global const int4* pairs, \n"
+ " __global const b3RigidBodyData_t* rigidBodies, \n"
+ " __global const b3Collidable_t* collidables,\n"
+ " __global const float4* separatingNormals,\n"
+ " __global const int* hasSeparatingAxis,\n"
+ " __global struct b3Contact4Data* restrict globalContactsOut,\n"
+ " counter32_t nGlobalContactsOut,\n"
+ " int contactCapacity,\n"
+ " int numPairs)\n"
+ "{\n"
+ " int i = get_global_id(0);\n"
+ " int pairIndex = i;\n"
+ " \n"
+ " if (i<numPairs)\n"
+ " {\n"
+ " int bodyIndexA = pairs[i].x;\n"
+ " int bodyIndexB = pairs[i].y;\n"
+ " \n"
+ " int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+ " int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+ " if (collidables[collidableIndexA].m_shapeType == SHAPE_SPHERE &&\n"
+ " collidables[collidableIndexB].m_shapeType == SHAPE_SPHERE)\n"
+ " {\n"
+ " //sphere-sphere\n"
+ " float radiusA = collidables[collidableIndexA].m_radius;\n"
+ " float radiusB = collidables[collidableIndexB].m_radius;\n"
+ " float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+ " float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+ " float4 diff = posA-posB;\n"
+ " float len = length(diff);\n"
+ " \n"
+ " ///iff distance positive, don't generate a new contact\n"
+ " if ( len <= (radiusA+radiusB))\n"
+ " {\n"
+ " ///distance (negative means penetration)\n"
+ " float dist = len - (radiusA+radiusB);\n"
+ " float4 normalOnSurfaceB = make_float4(1.f,0.f,0.f,0.f);\n"
+ " if (len > 0.00001)\n"
+ " {\n"
+ " normalOnSurfaceB = diff / len;\n"
+ " }\n"
+ " float4 contactPosB = posB + normalOnSurfaceB*radiusB;\n"
+ " contactPosB.w = dist;\n"
+ " \n"
+ " int dstIdx;\n"
+ " AppendInc( nGlobalContactsOut, dstIdx );\n"
+ " if (dstIdx < contactCapacity)\n"
+ " {\n"
+ " __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];\n"
+ " c->m_worldNormalOnB = -normalOnSurfaceB;\n"
+ " c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
+ " c->m_batchIdx = pairIndex;\n"
+ " int bodyA = pairs[pairIndex].x;\n"
+ " int bodyB = pairs[pairIndex].y;\n"
+ " c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;\n"
+ " c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;\n"
+ " c->m_worldPosB[0] = contactPosB;\n"
+ " c->m_childIndexA = -1;\n"
+ " c->m_childIndexB = -1;\n"
+ " GET_NPOINTS(*c) = 1;\n"
+ " }//if (dstIdx < numPairs)\n"
+ " }//if ( len <= (radiusA+radiusB))\n"
+ " }//SHAPE_SPHERE SHAPE_SPHERE\n"
+ " }//if (i<numPairs)\n"
+ "} \n"
+ "__kernel void clipHullHullConcaveConvexKernel( __global int4* concavePairsIn,\n"
+ " __global const b3RigidBodyData_t* rigidBodies, \n"
+ " __global const b3Collidable_t* collidables,\n"
+ " __global const b3ConvexPolyhedronData_t* convexShapes, \n"
+ " __global const float4* vertices,\n"
+ " __global const float4* uniqueEdges,\n"
+ " __global const b3GpuFace_t* faces,\n"
+ " __global const int* indices,\n"
+ " __global const b3GpuChildShape_t* gpuChildShapes,\n"
+ " __global const float4* separatingNormals,\n"
+ " __global struct b3Contact4Data* restrict globalContactsOut,\n"
+ " counter32_t nGlobalContactsOut,\n"
+ " int contactCapacity,\n"
+ " int numConcavePairs)\n"
+ "{\n"
+ " int i = get_global_id(0);\n"
+ " int pairIndex = i;\n"
+ " \n"
+ " float4 worldVertsB1[64];\n"
+ " float4 worldVertsB2[64];\n"
+ " int capacityWorldVerts = 64; \n"
+ " float4 localContactsOut[64];\n"
+ " int localContactCapacity=64;\n"
+ " \n"
+ " float minDist = -1e30f;\n"
+ " float maxDist = 0.02f;\n"
+ " if (i<numConcavePairs)\n"
+ " {\n"
+ " //negative value means that the pair is invalid\n"
+ " if (concavePairsIn[i].w<0)\n"
+ " return;\n"
+ " int bodyIndexA = concavePairsIn[i].x;\n"
+ " int bodyIndexB = concavePairsIn[i].y;\n"
+ " int f = concavePairsIn[i].z;\n"
+ " int childShapeIndexA = f;\n"
+ " \n"
+ " int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+ " int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+ " \n"
+ " int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+ " int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+ " \n"
+ " ///////////////////////////////////////////////////////////////\n"
+ " \n"
+ " \n"
+ " bool overlap = false;\n"
+ " \n"
+ " b3ConvexPolyhedronData_t convexPolyhedronA;\n"
+ " //add 3 vertices of the triangle\n"
+ " convexPolyhedronA.m_numVertices = 3;\n"
+ " convexPolyhedronA.m_vertexOffset = 0;\n"
+ " float4 localCenter = make_float4(0.f,0.f,0.f,0.f);\n"
+ " b3GpuFace_t face = faces[convexShapes[shapeIndexA].m_faceOffset+f];\n"
+ " \n"
+ " float4 verticesA[3];\n"
+ " for (int i=0;i<3;i++)\n"
+ " {\n"
+ " int index = indices[face.m_indexOffset+i];\n"
+ " float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];\n"
+ " verticesA[i] = vert;\n"
+ " localCenter += vert;\n"
+ " }\n"
+ " float dmin = FLT_MAX;\n"
+ " int localCC=0;\n"
+ " //a triangle has 3 unique edges\n"
+ " convexPolyhedronA.m_numUniqueEdges = 3;\n"
+ " convexPolyhedronA.m_uniqueEdgesOffset = 0;\n"
+ " float4 uniqueEdgesA[3];\n"
+ " \n"
+ " uniqueEdgesA[0] = (verticesA[1]-verticesA[0]);\n"
+ " uniqueEdgesA[1] = (verticesA[2]-verticesA[1]);\n"
+ " uniqueEdgesA[2] = (verticesA[0]-verticesA[2]);\n"
+ " convexPolyhedronA.m_faceOffset = 0;\n"
+ " \n"
+ " float4 normal = make_float4(face.m_plane.x,face.m_plane.y,face.m_plane.z,0.f);\n"
+ " \n"
+ " b3GpuFace_t facesA[TRIANGLE_NUM_CONVEX_FACES];\n"
+ " int indicesA[3+3+2+2+2];\n"
+ " int curUsedIndices=0;\n"
+ " int fidx=0;\n"
+ " //front size of triangle\n"
+ " {\n"
+ " facesA[fidx].m_indexOffset=curUsedIndices;\n"
+ " indicesA[0] = 0;\n"
+ " indicesA[1] = 1;\n"
+ " indicesA[2] = 2;\n"
+ " curUsedIndices+=3;\n"
+ " float c = face.m_plane.w;\n"
+ " facesA[fidx].m_plane.x = normal.x;\n"
+ " facesA[fidx].m_plane.y = normal.y;\n"
+ " facesA[fidx].m_plane.z = normal.z;\n"
+ " facesA[fidx].m_plane.w = c;\n"
+ " facesA[fidx].m_numIndices=3;\n"
+ " }\n"
+ " fidx++;\n"
+ " //back size of triangle\n"
+ " {\n"
+ " facesA[fidx].m_indexOffset=curUsedIndices;\n"
+ " indicesA[3]=2;\n"
+ " indicesA[4]=1;\n"
+ " indicesA[5]=0;\n"
+ " curUsedIndices+=3;\n"
+ " float c = dot3F4(normal,verticesA[0]);\n"
+ " float c1 = -face.m_plane.w;\n"
+ " facesA[fidx].m_plane.x = -normal.x;\n"
+ " facesA[fidx].m_plane.y = -normal.y;\n"
+ " facesA[fidx].m_plane.z = -normal.z;\n"
+ " facesA[fidx].m_plane.w = c;\n"
+ " facesA[fidx].m_numIndices=3;\n"
+ " }\n"
+ " fidx++;\n"
+ " bool addEdgePlanes = true;\n"
+ " if (addEdgePlanes)\n"
+ " {\n"
+ " int numVertices=3;\n"
+ " int prevVertex = numVertices-1;\n"
+ " for (int i=0;i<numVertices;i++)\n"
+ " {\n"
+ " float4 v0 = verticesA[i];\n"
+ " float4 v1 = verticesA[prevVertex];\n"
+ " \n"
+ " float4 edgeNormal = normalize(cross(normal,v1-v0));\n"
+ " float c = -dot3F4(edgeNormal,v0);\n"
+ " facesA[fidx].m_numIndices = 2;\n"
+ " facesA[fidx].m_indexOffset=curUsedIndices;\n"
+ " indicesA[curUsedIndices++]=i;\n"
+ " indicesA[curUsedIndices++]=prevVertex;\n"
+ " \n"
+ " facesA[fidx].m_plane.x = edgeNormal.x;\n"
+ " facesA[fidx].m_plane.y = edgeNormal.y;\n"
+ " facesA[fidx].m_plane.z = edgeNormal.z;\n"
+ " facesA[fidx].m_plane.w = c;\n"
+ " fidx++;\n"
+ " prevVertex = i;\n"
+ " }\n"
+ " }\n"
+ " convexPolyhedronA.m_numFaces = TRIANGLE_NUM_CONVEX_FACES;\n"
+ " convexPolyhedronA.m_localCenter = localCenter*(1.f/3.f);\n"
+ " float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+ " posA.w = 0.f;\n"
+ " float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+ " posB.w = 0.f;\n"
+ " float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
+ " float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
+ " float4 sepAxis = separatingNormals[i];\n"
+ " \n"
+ " int shapeTypeB = collidables[collidableIndexB].m_shapeType;\n"
+ " int childShapeIndexB =-1;\n"
+ " if (shapeTypeB==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
+ " {\n"
+ " ///////////////////\n"
+ " ///compound shape support\n"
+ " \n"
+ " childShapeIndexB = concavePairsIn[pairIndex].w;\n"
+ " int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
+ " shapeIndexB = collidables[childColIndexB].m_shapeIndex;\n"
+ " float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
+ " float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
+ " float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
+ " float4 newOrnB = qtMul(ornB,childOrnB);\n"
+ " posB = newPosB;\n"
+ " ornB = newOrnB;\n"
+ " \n"
+ " }\n"
+ " \n"
+ " ////////////////////////////////////////\n"
+ " \n"
+ " \n"
+ " \n"
+ " int numLocalContactsOut = clipHullAgainstHullLocalA(sepAxis,\n"
+ " &convexPolyhedronA, &convexShapes[shapeIndexB],\n"
+ " posA,ornA,\n"
+ " posB,ornB,\n"
+ " worldVertsB1,worldVertsB2,capacityWorldVerts,\n"
+ " minDist, maxDist,\n"
+ " &verticesA,&facesA,&indicesA,\n"
+ " vertices,faces,indices,\n"
+ " localContactsOut,localContactCapacity);\n"
+ " \n"
+ " if (numLocalContactsOut>0)\n"
+ " {\n"
+ " float4 normal = -separatingNormals[i];\n"
+ " int nPoints = numLocalContactsOut;\n"
+ " float4* pointsIn = localContactsOut;\n"
+ " int contactIdx[4];// = {-1,-1,-1,-1};\n"
+ " contactIdx[0] = -1;\n"
+ " contactIdx[1] = -1;\n"
+ " contactIdx[2] = -1;\n"
+ " contactIdx[3] = -1;\n"
+ " \n"
+ " int nReducedContacts = extractManifoldSequential(pointsIn, nPoints, normal, contactIdx);\n"
+ " \n"
+ " int dstIdx;\n"
+ " AppendInc( nGlobalContactsOut, dstIdx );\n"
+ " if (dstIdx<contactCapacity)\n"
+ " {\n"
+ " __global struct b3Contact4Data* c = globalContactsOut+ dstIdx;\n"
+ " c->m_worldNormalOnB = -normal;\n"
+ " c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
+ " c->m_batchIdx = pairIndex;\n"
+ " int bodyA = concavePairsIn[pairIndex].x;\n"
+ " int bodyB = concavePairsIn[pairIndex].y;\n"
+ " c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;\n"
+ " c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;\n"
+ " c->m_childIndexA = childShapeIndexA;\n"
+ " c->m_childIndexB = childShapeIndexB;\n"
+ " for (int i=0;i<nReducedContacts;i++)\n"
+ " {\n"
+ " c->m_worldPosB[i] = pointsIn[contactIdx[i]];\n"
+ " }\n"
+ " GET_NPOINTS(*c) = nReducedContacts;\n"
+ " }\n"
+ " \n"
+ " }// if (numContactsOut>0)\n"
+ " }// if (i<numPairs)\n"
+ "}\n"
+ "int findClippingFaces(const float4 separatingNormal,\n"
+ " __global const b3ConvexPolyhedronData_t* hullA, __global const b3ConvexPolyhedronData_t* hullB,\n"
+ " const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB,\n"
+ " __global float4* worldVertsA1,\n"
+ " __global float4* worldNormalsA1,\n"
+ " __global float4* worldVertsB1,\n"
+ " int capacityWorldVerts,\n"
+ " const float minDist, float maxDist,\n"
+ " __global const float4* vertices,\n"
+ " __global const b3GpuFace_t* faces,\n"
+ " __global const int* indices,\n"
+ " __global int4* clippingFaces, int pairIndex)\n"
+ "{\n"
+ " int numContactsOut = 0;\n"
+ " int numWorldVertsB1= 0;\n"
+ " \n"
+ " \n"
+ " int closestFaceB=-1;\n"
+ " float dmax = -FLT_MAX;\n"
+ " \n"
+ " {\n"
+ " for(int face=0;face<hullB->m_numFaces;face++)\n"
+ " {\n"
+ " const float4 Normal = make_float4(faces[hullB->m_faceOffset+face].m_plane.x,\n"
+ " faces[hullB->m_faceOffset+face].m_plane.y, faces[hullB->m_faceOffset+face].m_plane.z,0.f);\n"
+ " const float4 WorldNormal = qtRotate(ornB, Normal);\n"
+ " float d = dot3F4(WorldNormal,separatingNormal);\n"
+ " if (d > dmax)\n"
+ " {\n"
+ " dmax = d;\n"
+ " closestFaceB = face;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " \n"
+ " {\n"
+ " const b3GpuFace_t polyB = faces[hullB->m_faceOffset+closestFaceB];\n"
+ " const int numVertices = polyB.m_numIndices;\n"
+ " for(int e0=0;e0<numVertices;e0++)\n"
+ " {\n"
+ " const float4 b = vertices[hullB->m_vertexOffset+indices[polyB.m_indexOffset+e0]];\n"
+ " worldVertsB1[pairIndex*capacityWorldVerts+numWorldVertsB1++] = transform(&b,&posB,&ornB);\n"
+ " }\n"
+ " }\n"
+ " \n"
+ " int closestFaceA=-1;\n"
+ " {\n"
+ " float dmin = FLT_MAX;\n"
+ " for(int face=0;face<hullA->m_numFaces;face++)\n"
+ " {\n"
+ " const float4 Normal = make_float4(\n"
+ " faces[hullA->m_faceOffset+face].m_plane.x,\n"
+ " faces[hullA->m_faceOffset+face].m_plane.y,\n"
+ " faces[hullA->m_faceOffset+face].m_plane.z,\n"
+ " 0.f);\n"
+ " const float4 faceANormalWS = qtRotate(ornA,Normal);\n"
+ " \n"
+ " float d = dot3F4(faceANormalWS,separatingNormal);\n"
+ " if (d < dmin)\n"
+ " {\n"
+ " dmin = d;\n"
+ " closestFaceA = face;\n"
+ " worldNormalsA1[pairIndex] = faceANormalWS;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " \n"
+ " int numVerticesA = faces[hullA->m_faceOffset+closestFaceA].m_numIndices;\n"
+ " for(int e0=0;e0<numVerticesA;e0++)\n"
+ " {\n"
+ " const float4 a = vertices[hullA->m_vertexOffset+indices[faces[hullA->m_faceOffset+closestFaceA].m_indexOffset+e0]];\n"
+ " worldVertsA1[pairIndex*capacityWorldVerts+e0] = transform(&a, &posA,&ornA);\n"
+ " }\n"
+ " \n"
+ " clippingFaces[pairIndex].x = closestFaceA;\n"
+ " clippingFaces[pairIndex].y = closestFaceB;\n"
+ " clippingFaces[pairIndex].z = numVerticesA;\n"
+ " clippingFaces[pairIndex].w = numWorldVertsB1;\n"
+ " \n"
+ " \n"
+ " return numContactsOut;\n"
+ "}\n"
+ "int clipFaces(__global float4* worldVertsA1,\n"
+ " __global float4* worldNormalsA1,\n"
+ " __global float4* worldVertsB1,\n"
+ " __global float4* worldVertsB2, \n"
+ " int capacityWorldVertsB2,\n"
+ " const float minDist, float maxDist,\n"
+ " __global int4* clippingFaces,\n"
+ " int pairIndex)\n"
+ "{\n"
+ " int numContactsOut = 0;\n"
+ " \n"
+ " int closestFaceA = clippingFaces[pairIndex].x;\n"
+ " int closestFaceB = clippingFaces[pairIndex].y;\n"
+ " int numVertsInA = clippingFaces[pairIndex].z;\n"
+ " int numVertsInB = clippingFaces[pairIndex].w;\n"
+ " \n"
+ " int numVertsOut = 0;\n"
+ " \n"
+ " if (closestFaceA<0)\n"
+ " return numContactsOut;\n"
+ " \n"
+ " __global float4* pVtxIn = &worldVertsB1[pairIndex*capacityWorldVertsB2];\n"
+ " __global float4* pVtxOut = &worldVertsB2[pairIndex*capacityWorldVertsB2];\n"
+ " \n"
+ " \n"
+ " \n"
+ " // clip polygon to back of planes of all faces of hull A that are adjacent to witness face\n"
+ " \n"
+ " for(int e0=0;e0<numVertsInA;e0++)\n"
+ " {\n"
+ " const float4 aw = worldVertsA1[pairIndex*capacityWorldVertsB2+e0];\n"
+ " const float4 bw = worldVertsA1[pairIndex*capacityWorldVertsB2+((e0+1)%numVertsInA)];\n"
+ " const float4 WorldEdge0 = aw - bw;\n"
+ " float4 worldPlaneAnormal1 = worldNormalsA1[pairIndex];\n"
+ " float4 planeNormalWS1 = -cross3(WorldEdge0,worldPlaneAnormal1);\n"
+ " float4 worldA1 = aw;\n"
+ " float planeEqWS1 = -dot3F4(worldA1,planeNormalWS1);\n"
+ " float4 planeNormalWS = planeNormalWS1;\n"
+ " float planeEqWS=planeEqWS1;\n"
+ " numVertsOut = clipFaceGlobal(pVtxIn, numVertsInB, planeNormalWS,planeEqWS, pVtxOut);\n"
+ " __global float4* tmp = pVtxOut;\n"
+ " pVtxOut = pVtxIn;\n"
+ " pVtxIn = tmp;\n"
+ " numVertsInB = numVertsOut;\n"
+ " numVertsOut = 0;\n"
+ " }\n"
+ " \n"
+ " //float4 planeNormalWS = worldNormalsA1[pairIndex];\n"
+ " //float planeEqWS=-dot3F4(planeNormalWS,worldVertsA1[pairIndex*capacityWorldVertsB2]);\n"
+ " \n"
+ " /*for (int i=0;i<numVertsInB;i++)\n"
+ " {\n"
+ " pVtxOut[i] = pVtxIn[i];\n"
+ " }*/\n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " //numVertsInB=0;\n"
+ " \n"
+ " float4 planeNormalWS = worldNormalsA1[pairIndex];\n"
+ " float planeEqWS=-dot3F4(planeNormalWS,worldVertsA1[pairIndex*capacityWorldVertsB2]);\n"
+ " for (int i=0;i<numVertsInB;i++)\n"
+ " {\n"
+ " float depth = dot3F4(planeNormalWS,pVtxIn[i])+planeEqWS;\n"
+ " if (depth <=minDist)\n"
+ " {\n"
+ " depth = minDist;\n"
+ " }\n"
+ " \n"
+ " if (depth <=maxDist)\n"
+ " {\n"
+ " float4 pointInWorld = pVtxIn[i];\n"
+ " pVtxOut[numContactsOut++] = make_float4(pointInWorld.x,pointInWorld.y,pointInWorld.z,depth);\n"
+ " }\n"
+ " }\n"
+ " \n"
+ " clippingFaces[pairIndex].w =numContactsOut;\n"
+ " \n"
+ " \n"
+ " return numContactsOut;\n"
+ "}\n"
+ "__kernel void findClippingFacesKernel( __global const int4* pairs,\n"
+ " __global const b3RigidBodyData_t* rigidBodies,\n"
+ " __global const b3Collidable_t* collidables,\n"
+ " __global const b3ConvexPolyhedronData_t* convexShapes,\n"
+ " __global const float4* vertices,\n"
+ " __global const float4* uniqueEdges,\n"
+ " __global const b3GpuFace_t* faces,\n"
+ " __global const int* indices,\n"
+ " __global const float4* separatingNormals,\n"
+ " __global const int* hasSeparatingAxis,\n"
+ " __global int4* clippingFacesOut,\n"
+ " __global float4* worldVertsA1,\n"
+ " __global float4* worldNormalsA1,\n"
+ " __global float4* worldVertsB1,\n"
+ " int capacityWorldVerts,\n"
+ " int numPairs\n"
+ " )\n"
+ "{\n"
+ " \n"
+ " int i = get_global_id(0);\n"
+ " int pairIndex = i;\n"
+ " \n"
+ " \n"
+ " float minDist = -1e30f;\n"
+ " float maxDist = 0.02f;\n"
+ " \n"
+ " if (i<numPairs)\n"
+ " {\n"
+ " \n"
+ " if (hasSeparatingAxis[i])\n"
+ " {\n"
+ " \n"
+ " int bodyIndexA = pairs[i].x;\n"
+ " int bodyIndexB = pairs[i].y;\n"
+ " \n"
+ " int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+ " int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+ " \n"
+ " int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+ " int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+ " \n"
+ " \n"
+ " \n"
+ " int numLocalContactsOut = findClippingFaces(separatingNormals[i],\n"
+ " &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],\n"
+ " rigidBodies[bodyIndexA].m_pos,rigidBodies[bodyIndexA].m_quat,\n"
+ " rigidBodies[bodyIndexB].m_pos,rigidBodies[bodyIndexB].m_quat,\n"
+ " worldVertsA1,\n"
+ " worldNormalsA1,\n"
+ " worldVertsB1,capacityWorldVerts,\n"
+ " minDist, maxDist,\n"
+ " vertices,faces,indices,\n"
+ " clippingFacesOut,i);\n"
+ " \n"
+ " \n"
+ " }// if (hasSeparatingAxis[i])\n"
+ " }// if (i<numPairs)\n"
+ " \n"
+ "}\n"
+ "__kernel void clipFacesAndFindContactsKernel( __global const float4* separatingNormals,\n"
+ " __global const int* hasSeparatingAxis,\n"
+ " __global int4* clippingFacesOut,\n"
+ " __global float4* worldVertsA1,\n"
+ " __global float4* worldNormalsA1,\n"
+ " __global float4* worldVertsB1,\n"
+ " __global float4* worldVertsB2,\n"
+ " int vertexFaceCapacity,\n"
+ " int numPairs,\n"
+ " int debugMode\n"
+ " )\n"
+ "{\n"
+ " int i = get_global_id(0);\n"
+ " int pairIndex = i;\n"
+ " \n"
+ " \n"
+ " float minDist = -1e30f;\n"
+ " float maxDist = 0.02f;\n"
+ " \n"
+ " if (i<numPairs)\n"
+ " {\n"
+ " \n"
+ " if (hasSeparatingAxis[i])\n"
+ " {\n"
+ " \n"
+ "// int bodyIndexA = pairs[i].x;\n"
+ " // int bodyIndexB = pairs[i].y;\n"
+ " \n"
+ " int numLocalContactsOut = 0;\n"
+ " int capacityWorldVertsB2 = vertexFaceCapacity;\n"
+ " \n"
+ " __global float4* pVtxIn = &worldVertsB1[pairIndex*capacityWorldVertsB2];\n"
+ " __global float4* pVtxOut = &worldVertsB2[pairIndex*capacityWorldVertsB2];\n"
+ " \n"
+ " {\n"
+ " __global int4* clippingFaces = clippingFacesOut;\n"
+ " \n"
+ " \n"
+ " int closestFaceA = clippingFaces[pairIndex].x;\n"
+ " int closestFaceB = clippingFaces[pairIndex].y;\n"
+ " int numVertsInA = clippingFaces[pairIndex].z;\n"
+ " int numVertsInB = clippingFaces[pairIndex].w;\n"
+ " \n"
+ " int numVertsOut = 0;\n"
+ " \n"
+ " if (closestFaceA>=0)\n"
+ " {\n"
+ " \n"
+ " \n"
+ " \n"
+ " // clip polygon to back of planes of all faces of hull A that are adjacent to witness face\n"
+ " \n"
+ " for(int e0=0;e0<numVertsInA;e0++)\n"
+ " {\n"
+ " const float4 aw = worldVertsA1[pairIndex*capacityWorldVertsB2+e0];\n"
+ " const float4 bw = worldVertsA1[pairIndex*capacityWorldVertsB2+((e0+1)%numVertsInA)];\n"
+ " const float4 WorldEdge0 = aw - bw;\n"
+ " float4 worldPlaneAnormal1 = worldNormalsA1[pairIndex];\n"
+ " float4 planeNormalWS1 = -cross3(WorldEdge0,worldPlaneAnormal1);\n"
+ " float4 worldA1 = aw;\n"
+ " float planeEqWS1 = -dot3F4(worldA1,planeNormalWS1);\n"
+ " float4 planeNormalWS = planeNormalWS1;\n"
+ " float planeEqWS=planeEqWS1;\n"
+ " numVertsOut = clipFaceGlobal(pVtxIn, numVertsInB, planeNormalWS,planeEqWS, pVtxOut);\n"
+ " __global float4* tmp = pVtxOut;\n"
+ " pVtxOut = pVtxIn;\n"
+ " pVtxIn = tmp;\n"
+ " numVertsInB = numVertsOut;\n"
+ " numVertsOut = 0;\n"
+ " }\n"
+ " \n"
+ " float4 planeNormalWS = worldNormalsA1[pairIndex];\n"
+ " float planeEqWS=-dot3F4(planeNormalWS,worldVertsA1[pairIndex*capacityWorldVertsB2]);\n"
+ " \n"
+ " for (int i=0;i<numVertsInB;i++)\n"
+ " {\n"
+ " float depth = dot3F4(planeNormalWS,pVtxIn[i])+planeEqWS;\n"
+ " if (depth <=minDist)\n"
+ " {\n"
+ " depth = minDist;\n"
+ " }\n"
+ " \n"
+ " if (depth <=maxDist)\n"
+ " {\n"
+ " float4 pointInWorld = pVtxIn[i];\n"
+ " pVtxOut[numLocalContactsOut++] = make_float4(pointInWorld.x,pointInWorld.y,pointInWorld.z,depth);\n"
+ " }\n"
+ " }\n"
+ " \n"
+ " }\n"
+ " clippingFaces[pairIndex].w =numLocalContactsOut;\n"
+ " \n"
+ " }\n"
+ " \n"
+ " for (int i=0;i<numLocalContactsOut;i++)\n"
+ " pVtxIn[i] = pVtxOut[i];\n"
+ " \n"
+ " }// if (hasSeparatingAxis[i])\n"
+ " }// if (i<numPairs)\n"
+ " \n"
+ "}\n"
+ "__kernel void newContactReductionKernel( __global int4* pairs,\n"
+ " __global const b3RigidBodyData_t* rigidBodies,\n"
+ " __global const float4* separatingNormals,\n"
+ " __global const int* hasSeparatingAxis,\n"
+ " __global struct b3Contact4Data* globalContactsOut,\n"
+ " __global int4* clippingFaces,\n"
+ " __global float4* worldVertsB2,\n"
+ " volatile __global int* nGlobalContactsOut,\n"
+ " int vertexFaceCapacity,\n"
+ " int contactCapacity,\n"
+ " int numPairs\n"
+ " )\n"
+ "{\n"
+ " int i = get_global_id(0);\n"
+ " int pairIndex = i;\n"
+ " \n"
+ " int4 contactIdx;\n"
+ " contactIdx=make_int4(0,1,2,3);\n"
+ " \n"
+ " if (i<numPairs)\n"
+ " {\n"
+ " \n"
+ " if (hasSeparatingAxis[i])\n"
+ " {\n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " int nPoints = clippingFaces[pairIndex].w;\n"
+ " \n"
+ " if (nPoints>0)\n"
+ " {\n"
+ " __global float4* pointsIn = &worldVertsB2[pairIndex*vertexFaceCapacity];\n"
+ " float4 normal = -separatingNormals[i];\n"
+ " \n"
+ " int nReducedContacts = extractManifoldSequentialGlobal(pointsIn, nPoints, normal, &contactIdx);\n"
+ " \n"
+ " int mprContactIndex = pairs[pairIndex].z;\n"
+ " int dstIdx = mprContactIndex;\n"
+ " if (dstIdx<0)\n"
+ " {\n"
+ " AppendInc( nGlobalContactsOut, dstIdx );\n"
+ " }\n"
+ "//#if 0\n"
+ " \n"
+ " if (dstIdx < contactCapacity)\n"
+ " {\n"
+ " __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];\n"
+ " c->m_worldNormalOnB = -normal;\n"
+ " c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
+ " c->m_batchIdx = pairIndex;\n"
+ " int bodyA = pairs[pairIndex].x;\n"
+ " int bodyB = pairs[pairIndex].y;\n"
+ " pairs[pairIndex].w = dstIdx;\n"
+ " c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;\n"
+ " c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;\n"
+ " c->m_childIndexA =-1;\n"
+ " c->m_childIndexB =-1;\n"
+ " switch (nReducedContacts)\n"
+ " {\n"
+ " case 4:\n"
+ " c->m_worldPosB[3] = pointsIn[contactIdx.w];\n"
+ " case 3:\n"
+ " c->m_worldPosB[2] = pointsIn[contactIdx.z];\n"
+ " case 2:\n"
+ " c->m_worldPosB[1] = pointsIn[contactIdx.y];\n"
+ " case 1:\n"
+ " if (mprContactIndex<0)//test\n"
+ " c->m_worldPosB[0] = pointsIn[contactIdx.x];\n"
+ " default:\n"
+ " {\n"
+ " }\n"
+ " };\n"
+ " \n"
+ " GET_NPOINTS(*c) = nReducedContacts;\n"
+ " \n"
+ " }\n"
+ " \n"
+ " \n"
+ "//#endif\n"
+ " \n"
+ " }// if (numContactsOut>0)\n"
+ " }// if (hasSeparatingAxis[i])\n"
+ " }// if (i<numPairs)\n"
+ " \n"
+ " \n"
+ "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/satConcaveKernels.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/satConcaveKernels.h
index 611569cacf..a60702ca62 100644
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/satConcaveKernels.h
+++ b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/satConcaveKernels.h
@@ -1,1457 +1,1456 @@
//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* satConcaveKernelsCL= \
-"//keep this enum in sync with the CPU version (in btCollidable.h)\n"
-"//written by Erwin Coumans\n"
-"#define SHAPE_CONVEX_HULL 3\n"
-"#define SHAPE_CONCAVE_TRIMESH 5\n"
-"#define TRIANGLE_NUM_CONVEX_FACES 5\n"
-"#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6\n"
-"#define B3_MAX_STACK_DEPTH 256\n"
-"typedef unsigned int u32;\n"
-"///keep this in sync with btCollidable.h\n"
-"typedef struct\n"
-"{\n"
-" union {\n"
-" int m_numChildShapes;\n"
-" int m_bvhIndex;\n"
-" };\n"
-" union\n"
-" {\n"
-" float m_radius;\n"
-" int m_compoundBvhIndex;\n"
-" };\n"
-" \n"
-" int m_shapeType;\n"
-" int m_shapeIndex;\n"
-" \n"
-"} btCollidableGpu;\n"
-"#define MAX_NUM_PARTS_IN_BITS 10\n"
-"///b3QuantizedBvhNode is a compressed aabb node, 16 bytes.\n"
-"///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).\n"
-"typedef struct\n"
-"{\n"
-" //12 bytes\n"
-" unsigned short int m_quantizedAabbMin[3];\n"
-" unsigned short int m_quantizedAabbMax[3];\n"
-" //4 bytes\n"
-" int m_escapeIndexOrTriangleIndex;\n"
-"} b3QuantizedBvhNode;\n"
-"typedef struct\n"
-"{\n"
-" float4 m_aabbMin;\n"
-" float4 m_aabbMax;\n"
-" float4 m_quantization;\n"
-" int m_numNodes;\n"
-" int m_numSubTrees;\n"
-" int m_nodeOffset;\n"
-" int m_subTreeOffset;\n"
-"} b3BvhInfo;\n"
-"int getTriangleIndex(const b3QuantizedBvhNode* rootNode)\n"
-"{\n"
-" unsigned int x=0;\n"
-" unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);\n"
-" // Get only the lower bits where the triangle index is stored\n"
-" return (rootNode->m_escapeIndexOrTriangleIndex&~(y));\n"
-"}\n"
-"int getTriangleIndexGlobal(__global const b3QuantizedBvhNode* rootNode)\n"
-"{\n"
-" unsigned int x=0;\n"
-" unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);\n"
-" // Get only the lower bits where the triangle index is stored\n"
-" return (rootNode->m_escapeIndexOrTriangleIndex&~(y));\n"
-"}\n"
-"int isLeafNode(const b3QuantizedBvhNode* rootNode)\n"
-"{\n"
-" //skipindex is negative (internal node), triangleindex >=0 (leafnode)\n"
-" return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;\n"
-"}\n"
-"int isLeafNodeGlobal(__global const b3QuantizedBvhNode* rootNode)\n"
-"{\n"
-" //skipindex is negative (internal node), triangleindex >=0 (leafnode)\n"
-" return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;\n"
-"}\n"
-" \n"
-"int getEscapeIndex(const b3QuantizedBvhNode* rootNode)\n"
-"{\n"
-" return -rootNode->m_escapeIndexOrTriangleIndex;\n"
-"}\n"
-"int getEscapeIndexGlobal(__global const b3QuantizedBvhNode* rootNode)\n"
-"{\n"
-" return -rootNode->m_escapeIndexOrTriangleIndex;\n"
-"}\n"
-"typedef struct\n"
-"{\n"
-" //12 bytes\n"
-" unsigned short int m_quantizedAabbMin[3];\n"
-" unsigned short int m_quantizedAabbMax[3];\n"
-" //4 bytes, points to the root of the subtree\n"
-" int m_rootNodeIndex;\n"
-" //4 bytes\n"
-" int m_subtreeSize;\n"
-" int m_padding[3];\n"
-"} b3BvhSubtreeInfo;\n"
-"typedef struct\n"
-"{\n"
-" float4 m_childPosition;\n"
-" float4 m_childOrientation;\n"
-" int m_shapeIndex;\n"
-" int m_unused0;\n"
-" int m_unused1;\n"
-" int m_unused2;\n"
-"} btGpuChildShape;\n"
-"typedef struct\n"
-"{\n"
-" float4 m_pos;\n"
-" float4 m_quat;\n"
-" float4 m_linVel;\n"
-" float4 m_angVel;\n"
-" u32 m_collidableIdx;\n"
-" float m_invMass;\n"
-" float m_restituitionCoeff;\n"
-" float m_frictionCoeff;\n"
-"} BodyData;\n"
-"typedef struct \n"
-"{\n"
-" float4 m_localCenter;\n"
-" float4 m_extents;\n"
-" float4 mC;\n"
-" float4 mE;\n"
-" \n"
-" float m_radius;\n"
-" int m_faceOffset;\n"
-" int m_numFaces;\n"
-" int m_numVertices;\n"
-" int m_vertexOffset;\n"
-" int m_uniqueEdgesOffset;\n"
-" int m_numUniqueEdges;\n"
-" int m_unused;\n"
-"} ConvexPolyhedronCL;\n"
-"typedef struct \n"
-"{\n"
-" union\n"
-" {\n"
-" float4 m_min;\n"
-" float m_minElems[4];\n"
-" int m_minIndices[4];\n"
-" };\n"
-" union\n"
-" {\n"
-" float4 m_max;\n"
-" float m_maxElems[4];\n"
-" int m_maxIndices[4];\n"
-" };\n"
-"} btAabbCL;\n"
-"#ifndef B3_AABB_H\n"
-"#define B3_AABB_H\n"
-"#ifndef B3_FLOAT4_H\n"
-"#define B3_FLOAT4_H\n"
-"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
-"#define B3_PLATFORM_DEFINITIONS_H\n"
-"struct MyTest\n"
-"{\n"
-" int bla;\n"
-"};\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
-"#define B3_LARGE_FLOAT 1e18f\n"
-"#define B3_INFINITY 1e18f\n"
-"#define b3Assert(a)\n"
-"#define b3ConstArray(a) __global const a*\n"
-"#define b3AtomicInc atomic_inc\n"
-"#define b3AtomicAdd atomic_add\n"
-"#define b3Fabs fabs\n"
-"#define b3Sqrt native_sqrt\n"
-"#define b3Sin native_sin\n"
-"#define b3Cos native_cos\n"
-"#define B3_STATIC\n"
-"#endif\n"
-"#endif\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-" typedef float4 b3Float4;\n"
-" #define b3Float4ConstArg const b3Float4\n"
-" #define b3MakeFloat4 (float4)\n"
-" float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
-" {\n"
-" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
-" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
-" return dot(a1, b1);\n"
-" }\n"
-" b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
-" {\n"
-" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
-" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
-" return cross(a1, b1);\n"
-" }\n"
-" #define b3MinFloat4 min\n"
-" #define b3MaxFloat4 max\n"
-" #define b3Normalized(a) normalize(a)\n"
-"#endif \n"
-" \n"
-"inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
-"{\n"
-" if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
-" return false;\n"
-" return true;\n"
-"}\n"
-"inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
-"{\n"
-" float maxDot = -B3_INFINITY;\n"
-" int i = 0;\n"
-" int ptIndex = -1;\n"
-" for( i = 0; i < vecLen; i++ )\n"
-" {\n"
-" float dot = b3Dot3F4(vecArray[i],vec);\n"
-" \n"
-" if( dot > maxDot )\n"
-" {\n"
-" maxDot = dot;\n"
-" ptIndex = i;\n"
-" }\n"
-" }\n"
-" b3Assert(ptIndex>=0);\n"
-" if (ptIndex<0)\n"
-" {\n"
-" ptIndex = 0;\n"
-" }\n"
-" *dotOut = maxDot;\n"
-" return ptIndex;\n"
-"}\n"
-"#endif //B3_FLOAT4_H\n"
-"#ifndef B3_MAT3x3_H\n"
-"#define B3_MAT3x3_H\n"
-"#ifndef B3_QUAT_H\n"
-"#define B3_QUAT_H\n"
-"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#endif\n"
-"#endif\n"
-"#ifndef B3_FLOAT4_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#endif \n"
-"#endif //B3_FLOAT4_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-" typedef float4 b3Quat;\n"
-" #define b3QuatConstArg const b3Quat\n"
-" \n"
-" \n"
-"inline float4 b3FastNormalize4(float4 v)\n"
-"{\n"
-" v = (float4)(v.xyz,0.f);\n"
-" return fast_normalize(v);\n"
-"}\n"
-" \n"
-"inline b3Quat b3QuatMul(b3Quat a, b3Quat b);\n"
-"inline b3Quat b3QuatNormalized(b3QuatConstArg in);\n"
-"inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec);\n"
-"inline b3Quat b3QuatInvert(b3QuatConstArg q);\n"
-"inline b3Quat b3QuatInverse(b3QuatConstArg q);\n"
-"inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b)\n"
-"{\n"
-" b3Quat ans;\n"
-" ans = b3Cross3( a, b );\n"
-" ans += a.w*b+b.w*a;\n"
-"// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
-" ans.w = a.w*b.w - b3Dot3F4(a, b);\n"
-" return ans;\n"
-"}\n"
-"inline b3Quat b3QuatNormalized(b3QuatConstArg in)\n"
-"{\n"
-" b3Quat q;\n"
-" q=in;\n"
-" //return b3FastNormalize4(in);\n"
-" float len = native_sqrt(dot(q, q));\n"
-" if(len > 0.f)\n"
-" {\n"
-" q *= 1.f / len;\n"
-" }\n"
-" else\n"
-" {\n"
-" q.x = q.y = q.z = 0.f;\n"
-" q.w = 1.f;\n"
-" }\n"
-" return q;\n"
-"}\n"
-"inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
-"{\n"
-" b3Quat qInv = b3QuatInvert( q );\n"
-" float4 vcpy = vec;\n"
-" vcpy.w = 0.f;\n"
-" float4 out = b3QuatMul(b3QuatMul(q,vcpy),qInv);\n"
-" return out;\n"
-"}\n"
-"inline b3Quat b3QuatInverse(b3QuatConstArg q)\n"
-"{\n"
-" return (b3Quat)(-q.xyz, q.w);\n"
-"}\n"
-"inline b3Quat b3QuatInvert(b3QuatConstArg q)\n"
-"{\n"
-" return (b3Quat)(-q.xyz, q.w);\n"
-"}\n"
-"inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
-"{\n"
-" return b3QuatRotate( b3QuatInvert( q ), vec );\n"
-"}\n"
-"inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation)\n"
-"{\n"
-" return b3QuatRotate( orientation, point ) + (translation);\n"
-"}\n"
-" \n"
-"#endif \n"
-"#endif //B3_QUAT_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"typedef struct\n"
-"{\n"
-" b3Float4 m_row[3];\n"
-"}b3Mat3x3;\n"
-"#define b3Mat3x3ConstArg const b3Mat3x3\n"
-"#define b3GetRow(m,row) (m.m_row[row])\n"
-"inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat)\n"
-"{\n"
-" b3Float4 quat2 = (b3Float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);\n"
-" b3Mat3x3 out;\n"
-" out.m_row[0].x=1-2*quat2.y-2*quat2.z;\n"
-" out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;\n"
-" out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;\n"
-" out.m_row[0].w = 0.f;\n"
-" out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;\n"
-" out.m_row[1].y=1-2*quat2.x-2*quat2.z;\n"
-" out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;\n"
-" out.m_row[1].w = 0.f;\n"
-" out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;\n"
-" out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;\n"
-" out.m_row[2].z=1-2*quat2.x-2*quat2.y;\n"
-" out.m_row[2].w = 0.f;\n"
-" return out;\n"
-"}\n"
-"inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn)\n"
-"{\n"
-" b3Mat3x3 out;\n"
-" out.m_row[0] = fabs(matIn.m_row[0]);\n"
-" out.m_row[1] = fabs(matIn.m_row[1]);\n"
-" out.m_row[2] = fabs(matIn.m_row[2]);\n"
-" return out;\n"
-"}\n"
-"__inline\n"
-"b3Mat3x3 mtZero();\n"
-"__inline\n"
-"b3Mat3x3 mtIdentity();\n"
-"__inline\n"
-"b3Mat3x3 mtTranspose(b3Mat3x3 m);\n"
-"__inline\n"
-"b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);\n"
-"__inline\n"
-"b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);\n"
-"__inline\n"
-"b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);\n"
-"__inline\n"
-"b3Mat3x3 mtZero()\n"
-"{\n"
-" b3Mat3x3 m;\n"
-" m.m_row[0] = (b3Float4)(0.f);\n"
-" m.m_row[1] = (b3Float4)(0.f);\n"
-" m.m_row[2] = (b3Float4)(0.f);\n"
-" return m;\n"
-"}\n"
-"__inline\n"
-"b3Mat3x3 mtIdentity()\n"
-"{\n"
-" b3Mat3x3 m;\n"
-" m.m_row[0] = (b3Float4)(1,0,0,0);\n"
-" m.m_row[1] = (b3Float4)(0,1,0,0);\n"
-" m.m_row[2] = (b3Float4)(0,0,1,0);\n"
-" return m;\n"
-"}\n"
-"__inline\n"
-"b3Mat3x3 mtTranspose(b3Mat3x3 m)\n"
-"{\n"
-" b3Mat3x3 out;\n"
-" out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
-" out.m_row[1] = (b3Float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
-" out.m_row[2] = (b3Float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
-" return out;\n"
-"}\n"
-"__inline\n"
-"b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)\n"
-"{\n"
-" b3Mat3x3 transB;\n"
-" transB = mtTranspose( b );\n"
-" b3Mat3x3 ans;\n"
-" // why this doesn't run when 0ing in the for{}\n"
-" a.m_row[0].w = 0.f;\n"
-" a.m_row[1].w = 0.f;\n"
-" a.m_row[2].w = 0.f;\n"
-" for(int i=0; i<3; i++)\n"
-" {\n"
-"// a.m_row[i].w = 0.f;\n"
-" ans.m_row[i].x = b3Dot3F4(a.m_row[i],transB.m_row[0]);\n"
-" ans.m_row[i].y = b3Dot3F4(a.m_row[i],transB.m_row[1]);\n"
-" ans.m_row[i].z = b3Dot3F4(a.m_row[i],transB.m_row[2]);\n"
-" ans.m_row[i].w = 0.f;\n"
-" }\n"
-" return ans;\n"
-"}\n"
-"__inline\n"
-"b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)\n"
-"{\n"
-" b3Float4 ans;\n"
-" ans.x = b3Dot3F4( a.m_row[0], b );\n"
-" ans.y = b3Dot3F4( a.m_row[1], b );\n"
-" ans.z = b3Dot3F4( a.m_row[2], b );\n"
-" ans.w = 0.f;\n"
-" return ans;\n"
-"}\n"
-"__inline\n"
-"b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)\n"
-"{\n"
-" b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
-" b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
-" b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
-" b3Float4 ans;\n"
-" ans.x = b3Dot3F4( a, colx );\n"
-" ans.y = b3Dot3F4( a, coly );\n"
-" ans.z = b3Dot3F4( a, colz );\n"
-" return ans;\n"
-"}\n"
-"#endif\n"
-"#endif //B3_MAT3x3_H\n"
-"typedef struct b3Aabb b3Aabb_t;\n"
-"struct b3Aabb\n"
-"{\n"
-" union\n"
-" {\n"
-" float m_min[4];\n"
-" b3Float4 m_minVec;\n"
-" int m_minIndices[4];\n"
-" };\n"
-" union\n"
-" {\n"
-" float m_max[4];\n"
-" b3Float4 m_maxVec;\n"
-" int m_signedMaxIndices[4];\n"
-" };\n"
-"};\n"
-"inline void b3TransformAabb2(b3Float4ConstArg localAabbMin,b3Float4ConstArg localAabbMax, float margin,\n"
-" b3Float4ConstArg pos,\n"
-" b3QuatConstArg orn,\n"
-" b3Float4* aabbMinOut,b3Float4* aabbMaxOut)\n"
-"{\n"
-" b3Float4 localHalfExtents = 0.5f*(localAabbMax-localAabbMin);\n"
-" localHalfExtents+=b3MakeFloat4(margin,margin,margin,0.f);\n"
-" b3Float4 localCenter = 0.5f*(localAabbMax+localAabbMin);\n"
-" b3Mat3x3 m;\n"
-" m = b3QuatGetRotationMatrix(orn);\n"
-" b3Mat3x3 abs_b = b3AbsoluteMat3x3(m);\n"
-" b3Float4 center = b3TransformPoint(localCenter,pos,orn);\n"
-" \n"
-" b3Float4 extent = b3MakeFloat4(b3Dot3F4(localHalfExtents,b3GetRow(abs_b,0)),\n"
-" b3Dot3F4(localHalfExtents,b3GetRow(abs_b,1)),\n"
-" b3Dot3F4(localHalfExtents,b3GetRow(abs_b,2)),\n"
-" 0.f);\n"
-" *aabbMinOut = center-extent;\n"
-" *aabbMaxOut = center+extent;\n"
-"}\n"
-"/// conservative test for overlap between two aabbs\n"
-"inline bool b3TestAabbAgainstAabb(b3Float4ConstArg aabbMin1,b3Float4ConstArg aabbMax1,\n"
-" b3Float4ConstArg aabbMin2, b3Float4ConstArg aabbMax2)\n"
-"{\n"
-" bool overlap = true;\n"
-" overlap = (aabbMin1.x > aabbMax2.x || aabbMax1.x < aabbMin2.x) ? false : overlap;\n"
-" overlap = (aabbMin1.z > aabbMax2.z || aabbMax1.z < aabbMin2.z) ? false : overlap;\n"
-" overlap = (aabbMin1.y > aabbMax2.y || aabbMax1.y < aabbMin2.y) ? false : overlap;\n"
-" return overlap;\n"
-"}\n"
-"#endif //B3_AABB_H\n"
-"/*\n"
-"Bullet Continuous Collision Detection and Physics Library\n"
-"Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org\n"
-"This software is provided 'as-is', without any express or implied warranty.\n"
-"In no event will the authors be held liable for any damages arising from the use of this software.\n"
-"Permission is granted to anyone to use this software for any purpose,\n"
-"including commercial applications, and to alter it and redistribute it freely,\n"
-"subject to the following restrictions:\n"
-"1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
-"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
-"3. This notice may not be removed or altered from any source distribution.\n"
-"*/\n"
-"#ifndef B3_INT2_H\n"
-"#define B3_INT2_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#define b3UnsignedInt2 uint2\n"
-"#define b3Int2 int2\n"
-"#define b3MakeInt2 (int2)\n"
-"#endif //__cplusplus\n"
-"#endif\n"
-"typedef struct\n"
-"{\n"
-" float4 m_plane;\n"
-" int m_indexOffset;\n"
-" int m_numIndices;\n"
-"} btGpuFace;\n"
-"#define make_float4 (float4)\n"
-"__inline\n"
-"float4 cross3(float4 a, float4 b)\n"
-"{\n"
-" return cross(a,b);\n"
-" \n"
-"// float4 a1 = make_float4(a.xyz,0.f);\n"
-"// float4 b1 = make_float4(b.xyz,0.f);\n"
-"// return cross(a1,b1);\n"
-"//float4 c = make_float4(a.y*b.z - a.z*b.y,a.z*b.x - a.x*b.z,a.x*b.y - a.y*b.x,0.f);\n"
-" \n"
-" // float4 c = make_float4(a.y*b.z - a.z*b.y,1.f,a.x*b.y - a.y*b.x,0.f);\n"
-" \n"
-" //return c;\n"
-"}\n"
-"__inline\n"
-"float dot3F4(float4 a, float4 b)\n"
-"{\n"
-" float4 a1 = make_float4(a.xyz,0.f);\n"
-" float4 b1 = make_float4(b.xyz,0.f);\n"
-" return dot(a1, b1);\n"
-"}\n"
-"__inline\n"
-"float4 fastNormalize4(float4 v)\n"
-"{\n"
-" v = make_float4(v.xyz,0.f);\n"
-" return fast_normalize(v);\n"
-"}\n"
-"///////////////////////////////////////\n"
-"// Quaternion\n"
-"///////////////////////////////////////\n"
-"typedef float4 Quaternion;\n"
-"__inline\n"
-"Quaternion qtMul(Quaternion a, Quaternion b);\n"
-"__inline\n"
-"Quaternion qtNormalize(Quaternion in);\n"
-"__inline\n"
-"float4 qtRotate(Quaternion q, float4 vec);\n"
-"__inline\n"
-"Quaternion qtInvert(Quaternion q);\n"
-"__inline\n"
-"Quaternion qtMul(Quaternion a, Quaternion b)\n"
-"{\n"
-" Quaternion ans;\n"
-" ans = cross3( a, b );\n"
-" ans += a.w*b+b.w*a;\n"
-"// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
-" ans.w = a.w*b.w - dot3F4(a, b);\n"
-" return ans;\n"
-"}\n"
-"__inline\n"
-"Quaternion qtNormalize(Quaternion in)\n"
-"{\n"
-" return fastNormalize4(in);\n"
-"// in /= length( in );\n"
-"// return in;\n"
-"}\n"
-"__inline\n"
-"float4 qtRotate(Quaternion q, float4 vec)\n"
-"{\n"
-" Quaternion qInv = qtInvert( q );\n"
-" float4 vcpy = vec;\n"
-" vcpy.w = 0.f;\n"
-" float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
-" return out;\n"
-"}\n"
-"__inline\n"
-"Quaternion qtInvert(Quaternion q)\n"
-"{\n"
-" return (Quaternion)(-q.xyz, q.w);\n"
-"}\n"
-"__inline\n"
-"float4 qtInvRotate(const Quaternion q, float4 vec)\n"
-"{\n"
-" return qtRotate( qtInvert( q ), vec );\n"
-"}\n"
-"__inline\n"
-"float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)\n"
-"{\n"
-" return qtRotate( *orientation, *p ) + (*translation);\n"
-"}\n"
-"__inline\n"
-"float4 normalize3(const float4 a)\n"
-"{\n"
-" float4 n = make_float4(a.x, a.y, a.z, 0.f);\n"
-" return fastNormalize4( n );\n"
-"}\n"
-"inline void projectLocal(const ConvexPolyhedronCL* hull, const float4 pos, const float4 orn, \n"
-"const float4* dir, const float4* vertices, float* min, float* max)\n"
-"{\n"
-" min[0] = FLT_MAX;\n"
-" max[0] = -FLT_MAX;\n"
-" int numVerts = hull->m_numVertices;\n"
-" const float4 localDir = qtInvRotate(orn,*dir);\n"
-" float offset = dot(pos,*dir);\n"
-" for(int i=0;i<numVerts;i++)\n"
-" {\n"
-" float dp = dot(vertices[hull->m_vertexOffset+i],localDir);\n"
-" if(dp < min[0]) \n"
-" min[0] = dp;\n"
-" if(dp > max[0]) \n"
-" max[0] = dp;\n"
-" }\n"
-" if(min[0]>max[0])\n"
-" {\n"
-" float tmp = min[0];\n"
-" min[0] = max[0];\n"
-" max[0] = tmp;\n"
-" }\n"
-" min[0] += offset;\n"
-" max[0] += offset;\n"
-"}\n"
-"inline void project(__global const ConvexPolyhedronCL* hull, const float4 pos, const float4 orn, \n"
-"const float4* dir, __global const float4* vertices, float* min, float* max)\n"
-"{\n"
-" min[0] = FLT_MAX;\n"
-" max[0] = -FLT_MAX;\n"
-" int numVerts = hull->m_numVertices;\n"
-" const float4 localDir = qtInvRotate(orn,*dir);\n"
-" float offset = dot(pos,*dir);\n"
-" for(int i=0;i<numVerts;i++)\n"
-" {\n"
-" float dp = dot(vertices[hull->m_vertexOffset+i],localDir);\n"
-" if(dp < min[0]) \n"
-" min[0] = dp;\n"
-" if(dp > max[0]) \n"
-" max[0] = dp;\n"
-" }\n"
-" if(min[0]>max[0])\n"
-" {\n"
-" float tmp = min[0];\n"
-" min[0] = max[0];\n"
-" max[0] = tmp;\n"
-" }\n"
-" min[0] += offset;\n"
-" max[0] += offset;\n"
-"}\n"
-"inline bool TestSepAxisLocalA(const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
-" const float4 posA,const float4 ornA,\n"
-" const float4 posB,const float4 ornB,\n"
-" float4* sep_axis, const float4* verticesA, __global const float4* verticesB,float* depth)\n"
-"{\n"
-" float Min0,Max0;\n"
-" float Min1,Max1;\n"
-" projectLocal(hullA,posA,ornA,sep_axis,verticesA, &Min0, &Max0);\n"
-" project(hullB,posB,ornB, sep_axis,verticesB, &Min1, &Max1);\n"
-" if(Max0<Min1 || Max1<Min0)\n"
-" return false;\n"
-" float d0 = Max0 - Min1;\n"
-" float d1 = Max1 - Min0;\n"
-" *depth = d0<d1 ? d0:d1;\n"
-" return true;\n"
-"}\n"
-"inline bool IsAlmostZero(const float4 v)\n"
-"{\n"
-" if(fabs(v.x)>1e-6f || fabs(v.y)>1e-6f || fabs(v.z)>1e-6f)\n"
-" return false;\n"
-" return true;\n"
-"}\n"
-"bool findSeparatingAxisLocalA( const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
-" const float4 posA1,\n"
-" const float4 ornA,\n"
-" const float4 posB1,\n"
-" const float4 ornB,\n"
-" const float4 DeltaC2,\n"
-" \n"
-" const float4* verticesA, \n"
-" const float4* uniqueEdgesA, \n"
-" const btGpuFace* facesA,\n"
-" const int* indicesA,\n"
-" __global const float4* verticesB, \n"
-" __global const float4* uniqueEdgesB, \n"
-" __global const btGpuFace* facesB,\n"
-" __global const int* indicesB,\n"
-" float4* sep,\n"
-" float* dmin)\n"
-"{\n"
-" \n"
-" float4 posA = posA1;\n"
-" posA.w = 0.f;\n"
-" float4 posB = posB1;\n"
-" posB.w = 0.f;\n"
-" int curPlaneTests=0;\n"
-" {\n"
-" int numFacesA = hullA->m_numFaces;\n"
-" // Test normals from hullA\n"
-" for(int i=0;i<numFacesA;i++)\n"
-" {\n"
-" const float4 normal = facesA[hullA->m_faceOffset+i].m_plane;\n"
-" float4 faceANormalWS = qtRotate(ornA,normal);\n"
-" if (dot3F4(DeltaC2,faceANormalWS)<0)\n"
-" faceANormalWS*=-1.f;\n"
-" curPlaneTests++;\n"
-" float d;\n"
-" if(!TestSepAxisLocalA( hullA, hullB, posA,ornA,posB,ornB,&faceANormalWS, verticesA, verticesB,&d))\n"
-" return false;\n"
-" if(d<*dmin)\n"
-" {\n"
-" *dmin = d;\n"
-" *sep = faceANormalWS;\n"
-" }\n"
-" }\n"
-" }\n"
-" if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
-" {\n"
-" *sep = -(*sep);\n"
-" }\n"
-" return true;\n"
-"}\n"
-"bool findSeparatingAxisLocalB( __global const ConvexPolyhedronCL* hullA, const ConvexPolyhedronCL* hullB, \n"
-" const float4 posA1,\n"
-" const float4 ornA,\n"
-" const float4 posB1,\n"
-" const float4 ornB,\n"
-" const float4 DeltaC2,\n"
-" __global const float4* verticesA, \n"
-" __global const float4* uniqueEdgesA, \n"
-" __global const btGpuFace* facesA,\n"
-" __global const int* indicesA,\n"
-" const float4* verticesB,\n"
-" const float4* uniqueEdgesB, \n"
-" const btGpuFace* facesB,\n"
-" const int* indicesB,\n"
-" float4* sep,\n"
-" float* dmin)\n"
-"{\n"
-" float4 posA = posA1;\n"
-" posA.w = 0.f;\n"
-" float4 posB = posB1;\n"
-" posB.w = 0.f;\n"
-" int curPlaneTests=0;\n"
-" {\n"
-" int numFacesA = hullA->m_numFaces;\n"
-" // Test normals from hullA\n"
-" for(int i=0;i<numFacesA;i++)\n"
-" {\n"
-" const float4 normal = facesA[hullA->m_faceOffset+i].m_plane;\n"
-" float4 faceANormalWS = qtRotate(ornA,normal);\n"
-" if (dot3F4(DeltaC2,faceANormalWS)<0)\n"
-" faceANormalWS *= -1.f;\n"
-" curPlaneTests++;\n"
-" float d;\n"
-" if(!TestSepAxisLocalA( hullB, hullA, posB,ornB,posA,ornA, &faceANormalWS, verticesB,verticesA, &d))\n"
-" return false;\n"
-" if(d<*dmin)\n"
-" {\n"
-" *dmin = d;\n"
-" *sep = faceANormalWS;\n"
-" }\n"
-" }\n"
-" }\n"
-" if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
-" {\n"
-" *sep = -(*sep);\n"
-" }\n"
-" return true;\n"
-"}\n"
-"bool findSeparatingAxisEdgeEdgeLocalA( const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
-" const float4 posA1,\n"
-" const float4 ornA,\n"
-" const float4 posB1,\n"
-" const float4 ornB,\n"
-" const float4 DeltaC2,\n"
-" const float4* verticesA, \n"
-" const float4* uniqueEdgesA, \n"
-" const btGpuFace* facesA,\n"
-" const int* indicesA,\n"
-" __global const float4* verticesB, \n"
-" __global const float4* uniqueEdgesB, \n"
-" __global const btGpuFace* facesB,\n"
-" __global const int* indicesB,\n"
-" float4* sep,\n"
-" float* dmin)\n"
-"{\n"
-" float4 posA = posA1;\n"
-" posA.w = 0.f;\n"
-" float4 posB = posB1;\n"
-" posB.w = 0.f;\n"
-" int curPlaneTests=0;\n"
-" int curEdgeEdge = 0;\n"
-" // Test edges\n"
-" for(int e0=0;e0<hullA->m_numUniqueEdges;e0++)\n"
-" {\n"
-" const float4 edge0 = uniqueEdgesA[hullA->m_uniqueEdgesOffset+e0];\n"
-" float4 edge0World = qtRotate(ornA,edge0);\n"
-" for(int e1=0;e1<hullB->m_numUniqueEdges;e1++)\n"
-" {\n"
-" const float4 edge1 = uniqueEdgesB[hullB->m_uniqueEdgesOffset+e1];\n"
-" float4 edge1World = qtRotate(ornB,edge1);\n"
-" float4 crossje = cross3(edge0World,edge1World);\n"
-" curEdgeEdge++;\n"
-" if(!IsAlmostZero(crossje))\n"
-" {\n"
-" crossje = normalize3(crossje);\n"
-" if (dot3F4(DeltaC2,crossje)<0)\n"
-" crossje *= -1.f;\n"
-" float dist;\n"
-" bool result = true;\n"
-" {\n"
-" float Min0,Max0;\n"
-" float Min1,Max1;\n"
-" projectLocal(hullA,posA,ornA,&crossje,verticesA, &Min0, &Max0);\n"
-" project(hullB,posB,ornB,&crossje,verticesB, &Min1, &Max1);\n"
-" \n"
-" if(Max0<Min1 || Max1<Min0)\n"
-" result = false;\n"
-" \n"
-" float d0 = Max0 - Min1;\n"
-" float d1 = Max1 - Min0;\n"
-" dist = d0<d1 ? d0:d1;\n"
-" result = true;\n"
-" }\n"
-" \n"
-" if(dist<*dmin)\n"
-" {\n"
-" *dmin = dist;\n"
-" *sep = crossje;\n"
-" }\n"
-" }\n"
-" }\n"
-" }\n"
-" \n"
-" if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
-" {\n"
-" *sep = -(*sep);\n"
-" }\n"
-" return true;\n"
-"}\n"
-"inline int findClippingFaces(const float4 separatingNormal,\n"
-" const ConvexPolyhedronCL* hullA, \n"
-" __global const ConvexPolyhedronCL* hullB,\n"
-" const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB,\n"
-" __global float4* worldVertsA1,\n"
-" __global float4* worldNormalsA1,\n"
-" __global float4* worldVertsB1,\n"
-" int capacityWorldVerts,\n"
-" const float minDist, float maxDist,\n"
-" const float4* verticesA,\n"
-" const btGpuFace* facesA,\n"
-" const int* indicesA,\n"
-" __global const float4* verticesB,\n"
-" __global const btGpuFace* facesB,\n"
-" __global const int* indicesB,\n"
-" __global int4* clippingFaces, int pairIndex)\n"
-"{\n"
-" int numContactsOut = 0;\n"
-" int numWorldVertsB1= 0;\n"
-" \n"
-" \n"
-" int closestFaceB=0;\n"
-" float dmax = -FLT_MAX;\n"
-" \n"
-" {\n"
-" for(int face=0;face<hullB->m_numFaces;face++)\n"
-" {\n"
-" const float4 Normal = make_float4(facesB[hullB->m_faceOffset+face].m_plane.x,\n"
-" facesB[hullB->m_faceOffset+face].m_plane.y, facesB[hullB->m_faceOffset+face].m_plane.z,0.f);\n"
-" const float4 WorldNormal = qtRotate(ornB, Normal);\n"
-" float d = dot3F4(WorldNormal,separatingNormal);\n"
-" if (d > dmax)\n"
-" {\n"
-" dmax = d;\n"
-" closestFaceB = face;\n"
-" }\n"
-" }\n"
-" }\n"
-" \n"
-" {\n"
-" const btGpuFace polyB = facesB[hullB->m_faceOffset+closestFaceB];\n"
-" int numVertices = polyB.m_numIndices;\n"
-" if (numVertices>capacityWorldVerts)\n"
-" numVertices = capacityWorldVerts;\n"
-" if (numVertices<0)\n"
-" numVertices = 0;\n"
-" \n"
-" for(int e0=0;e0<numVertices;e0++)\n"
-" {\n"
-" if (e0<capacityWorldVerts)\n"
-" {\n"
-" const float4 b = verticesB[hullB->m_vertexOffset+indicesB[polyB.m_indexOffset+e0]];\n"
-" worldVertsB1[pairIndex*capacityWorldVerts+numWorldVertsB1++] = transform(&b,&posB,&ornB);\n"
-" }\n"
-" }\n"
-" }\n"
-" \n"
-" int closestFaceA=0;\n"
-" {\n"
-" float dmin = FLT_MAX;\n"
-" for(int face=0;face<hullA->m_numFaces;face++)\n"
-" {\n"
-" const float4 Normal = make_float4(\n"
-" facesA[hullA->m_faceOffset+face].m_plane.x,\n"
-" facesA[hullA->m_faceOffset+face].m_plane.y,\n"
-" facesA[hullA->m_faceOffset+face].m_plane.z,\n"
-" 0.f);\n"
-" const float4 faceANormalWS = qtRotate(ornA,Normal);\n"
-" \n"
-" float d = dot3F4(faceANormalWS,separatingNormal);\n"
-" if (d < dmin)\n"
-" {\n"
-" dmin = d;\n"
-" closestFaceA = face;\n"
-" worldNormalsA1[pairIndex] = faceANormalWS;\n"
-" }\n"
-" }\n"
-" }\n"
-" \n"
-" int numVerticesA = facesA[hullA->m_faceOffset+closestFaceA].m_numIndices;\n"
-" if (numVerticesA>capacityWorldVerts)\n"
-" numVerticesA = capacityWorldVerts;\n"
-" if (numVerticesA<0)\n"
-" numVerticesA=0;\n"
-" \n"
-" for(int e0=0;e0<numVerticesA;e0++)\n"
-" {\n"
-" if (e0<capacityWorldVerts)\n"
-" {\n"
-" const float4 a = verticesA[hullA->m_vertexOffset+indicesA[facesA[hullA->m_faceOffset+closestFaceA].m_indexOffset+e0]];\n"
-" worldVertsA1[pairIndex*capacityWorldVerts+e0] = transform(&a, &posA,&ornA);\n"
-" }\n"
-" }\n"
-" \n"
-" clippingFaces[pairIndex].x = closestFaceA;\n"
-" clippingFaces[pairIndex].y = closestFaceB;\n"
-" clippingFaces[pairIndex].z = numVerticesA;\n"
-" clippingFaces[pairIndex].w = numWorldVertsB1;\n"
-" \n"
-" \n"
-" return numContactsOut;\n"
-"}\n"
-"// work-in-progress\n"
-"__kernel void findConcaveSeparatingAxisVertexFaceKernel( __global int4* concavePairs,\n"
-" __global const BodyData* rigidBodies,\n"
-" __global const btCollidableGpu* collidables,\n"
-" __global const ConvexPolyhedronCL* convexShapes,\n"
-" __global const float4* vertices,\n"
-" __global const float4* uniqueEdges,\n"
-" __global const btGpuFace* faces,\n"
-" __global const int* indices,\n"
-" __global const btGpuChildShape* gpuChildShapes,\n"
-" __global btAabbCL* aabbs,\n"
-" __global float4* concaveSeparatingNormalsOut,\n"
-" __global int* concaveHasSeparatingNormals,\n"
-" __global int4* clippingFacesOut,\n"
-" __global float4* worldVertsA1GPU,\n"
-" __global float4* worldNormalsAGPU,\n"
-" __global float4* worldVertsB1GPU,\n"
-" __global float* dmins,\n"
-" int vertexFaceCapacity,\n"
-" int numConcavePairs\n"
-" )\n"
-"{\n"
-" \n"
-" int i = get_global_id(0);\n"
-" if (i>=numConcavePairs)\n"
-" return;\n"
-" \n"
-" concaveHasSeparatingNormals[i] = 0;\n"
-" \n"
-" int pairIdx = i;\n"
-" \n"
-" int bodyIndexA = concavePairs[i].x;\n"
-" int bodyIndexB = concavePairs[i].y;\n"
-" \n"
-" int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
-" int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
-" \n"
-" int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
-" int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
-" \n"
-" if (collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL&&\n"
-" collidables[collidableIndexB].m_shapeType!=SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
-" {\n"
-" concavePairs[pairIdx].w = -1;\n"
-" return;\n"
-" }\n"
-" \n"
-" \n"
-" \n"
-" int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
-" int numActualConcaveConvexTests = 0;\n"
-" \n"
-" int f = concavePairs[i].z;\n"
-" \n"
-" bool overlap = false;\n"
-" \n"
-" ConvexPolyhedronCL convexPolyhedronA;\n"
-" \n"
-" //add 3 vertices of the triangle\n"
-" convexPolyhedronA.m_numVertices = 3;\n"
-" convexPolyhedronA.m_vertexOffset = 0;\n"
-" float4 localCenter = make_float4(0.f,0.f,0.f,0.f);\n"
-" \n"
-" btGpuFace face = faces[convexShapes[shapeIndexA].m_faceOffset+f];\n"
-" float4 triMinAabb, triMaxAabb;\n"
-" btAabbCL triAabb;\n"
-" triAabb.m_min = make_float4(1e30f,1e30f,1e30f,0.f);\n"
-" triAabb.m_max = make_float4(-1e30f,-1e30f,-1e30f,0.f);\n"
-" \n"
-" float4 verticesA[3];\n"
-" for (int i=0;i<3;i++)\n"
-" {\n"
-" int index = indices[face.m_indexOffset+i];\n"
-" float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];\n"
-" verticesA[i] = vert;\n"
-" localCenter += vert;\n"
-" \n"
-" triAabb.m_min = min(triAabb.m_min,vert);\n"
-" triAabb.m_max = max(triAabb.m_max,vert);\n"
-" \n"
-" }\n"
-" \n"
-" overlap = true;\n"
-" overlap = (triAabb.m_min.x > aabbs[bodyIndexB].m_max.x || triAabb.m_max.x < aabbs[bodyIndexB].m_min.x) ? false : overlap;\n"
-" overlap = (triAabb.m_min.z > aabbs[bodyIndexB].m_max.z || triAabb.m_max.z < aabbs[bodyIndexB].m_min.z) ? false : overlap;\n"
-" overlap = (triAabb.m_min.y > aabbs[bodyIndexB].m_max.y || triAabb.m_max.y < aabbs[bodyIndexB].m_min.y) ? false : overlap;\n"
-" \n"
-" if (overlap)\n"
-" {\n"
-" float dmin = FLT_MAX;\n"
-" int hasSeparatingAxis=5;\n"
-" float4 sepAxis=make_float4(1,2,3,4);\n"
-" \n"
-" int localCC=0;\n"
-" numActualConcaveConvexTests++;\n"
-" \n"
-" //a triangle has 3 unique edges\n"
-" convexPolyhedronA.m_numUniqueEdges = 3;\n"
-" convexPolyhedronA.m_uniqueEdgesOffset = 0;\n"
-" float4 uniqueEdgesA[3];\n"
-" \n"
-" uniqueEdgesA[0] = (verticesA[1]-verticesA[0]);\n"
-" uniqueEdgesA[1] = (verticesA[2]-verticesA[1]);\n"
-" uniqueEdgesA[2] = (verticesA[0]-verticesA[2]);\n"
-" \n"
-" \n"
-" convexPolyhedronA.m_faceOffset = 0;\n"
-" \n"
-" float4 normal = make_float4(face.m_plane.x,face.m_plane.y,face.m_plane.z,0.f);\n"
-" \n"
-" btGpuFace facesA[TRIANGLE_NUM_CONVEX_FACES];\n"
-" int indicesA[3+3+2+2+2];\n"
-" int curUsedIndices=0;\n"
-" int fidx=0;\n"
-" \n"
-" //front size of triangle\n"
-" {\n"
-" facesA[fidx].m_indexOffset=curUsedIndices;\n"
-" indicesA[0] = 0;\n"
-" indicesA[1] = 1;\n"
-" indicesA[2] = 2;\n"
-" curUsedIndices+=3;\n"
-" float c = face.m_plane.w;\n"
-" facesA[fidx].m_plane.x = normal.x;\n"
-" facesA[fidx].m_plane.y = normal.y;\n"
-" facesA[fidx].m_plane.z = normal.z;\n"
-" facesA[fidx].m_plane.w = c;\n"
-" facesA[fidx].m_numIndices=3;\n"
-" }\n"
-" fidx++;\n"
-" //back size of triangle\n"
-" {\n"
-" facesA[fidx].m_indexOffset=curUsedIndices;\n"
-" indicesA[3]=2;\n"
-" indicesA[4]=1;\n"
-" indicesA[5]=0;\n"
-" curUsedIndices+=3;\n"
-" float c = dot(normal,verticesA[0]);\n"
-" float c1 = -face.m_plane.w;\n"
-" facesA[fidx].m_plane.x = -normal.x;\n"
-" facesA[fidx].m_plane.y = -normal.y;\n"
-" facesA[fidx].m_plane.z = -normal.z;\n"
-" facesA[fidx].m_plane.w = c;\n"
-" facesA[fidx].m_numIndices=3;\n"
-" }\n"
-" fidx++;\n"
-" \n"
-" bool addEdgePlanes = true;\n"
-" if (addEdgePlanes)\n"
-" {\n"
-" int numVertices=3;\n"
-" int prevVertex = numVertices-1;\n"
-" for (int i=0;i<numVertices;i++)\n"
-" {\n"
-" float4 v0 = verticesA[i];\n"
-" float4 v1 = verticesA[prevVertex];\n"
-" \n"
-" float4 edgeNormal = normalize(cross(normal,v1-v0));\n"
-" float c = -dot(edgeNormal,v0);\n"
-" \n"
-" facesA[fidx].m_numIndices = 2;\n"
-" facesA[fidx].m_indexOffset=curUsedIndices;\n"
-" indicesA[curUsedIndices++]=i;\n"
-" indicesA[curUsedIndices++]=prevVertex;\n"
-" \n"
-" facesA[fidx].m_plane.x = edgeNormal.x;\n"
-" facesA[fidx].m_plane.y = edgeNormal.y;\n"
-" facesA[fidx].m_plane.z = edgeNormal.z;\n"
-" facesA[fidx].m_plane.w = c;\n"
-" fidx++;\n"
-" prevVertex = i;\n"
-" }\n"
-" }\n"
-" convexPolyhedronA.m_numFaces = TRIANGLE_NUM_CONVEX_FACES;\n"
-" convexPolyhedronA.m_localCenter = localCenter*(1.f/3.f);\n"
-" \n"
-" \n"
-" float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
-" posA.w = 0.f;\n"
-" float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
-" posB.w = 0.f;\n"
-" \n"
-" float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
-" float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
-" \n"
-" \n"
-" \n"
-" \n"
-" ///////////////////\n"
-" ///compound shape support\n"
-" \n"
-" if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
-" {\n"
-" int compoundChild = concavePairs[pairIdx].w;\n"
-" int childShapeIndexB = compoundChild;//collidables[collidableIndexB].m_shapeIndex+compoundChild;\n"
-" int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
-" float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
-" float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
-" float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
-" float4 newOrnB = qtMul(ornB,childOrnB);\n"
-" posB = newPosB;\n"
-" ornB = newOrnB;\n"
-" shapeIndexB = collidables[childColIndexB].m_shapeIndex;\n"
-" }\n"
-" //////////////////\n"
-" \n"
-" float4 c0local = convexPolyhedronA.m_localCenter;\n"
-" float4 c0 = transform(&c0local, &posA, &ornA);\n"
-" float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
-" float4 c1 = transform(&c1local,&posB,&ornB);\n"
-" const float4 DeltaC2 = c0 - c1;\n"
-" \n"
-" \n"
-" bool sepA = findSeparatingAxisLocalA( &convexPolyhedronA, &convexShapes[shapeIndexB],\n"
-" posA,ornA,\n"
-" posB,ornB,\n"
-" DeltaC2,\n"
-" verticesA,uniqueEdgesA,facesA,indicesA,\n"
-" vertices,uniqueEdges,faces,indices,\n"
-" &sepAxis,&dmin);\n"
-" hasSeparatingAxis = 4;\n"
-" if (!sepA)\n"
-" {\n"
-" hasSeparatingAxis = 0;\n"
-" } else\n"
-" {\n"
-" bool sepB = findSeparatingAxisLocalB( &convexShapes[shapeIndexB],&convexPolyhedronA,\n"
-" posB,ornB,\n"
-" posA,ornA,\n"
-" DeltaC2,\n"
-" vertices,uniqueEdges,faces,indices,\n"
-" verticesA,uniqueEdgesA,facesA,indicesA,\n"
-" &sepAxis,&dmin);\n"
-" \n"
-" if (!sepB)\n"
-" {\n"
-" hasSeparatingAxis = 0;\n"
-" } else\n"
-" {\n"
-" hasSeparatingAxis = 1;\n"
-" }\n"
-" } \n"
-" \n"
-" if (hasSeparatingAxis)\n"
-" {\n"
-" dmins[i] = dmin;\n"
-" concaveSeparatingNormalsOut[pairIdx]=sepAxis;\n"
-" concaveHasSeparatingNormals[i]=1;\n"
-" \n"
-" } else\n"
-" { \n"
-" //mark this pair as in-active\n"
-" concavePairs[pairIdx].w = -1;\n"
-" }\n"
-" }\n"
-" else\n"
-" { \n"
-" //mark this pair as in-active\n"
-" concavePairs[pairIdx].w = -1;\n"
-" }\n"
-"}\n"
-"// work-in-progress\n"
-"__kernel void findConcaveSeparatingAxisEdgeEdgeKernel( __global int4* concavePairs,\n"
-" __global const BodyData* rigidBodies,\n"
-" __global const btCollidableGpu* collidables,\n"
-" __global const ConvexPolyhedronCL* convexShapes,\n"
-" __global const float4* vertices,\n"
-" __global const float4* uniqueEdges,\n"
-" __global const btGpuFace* faces,\n"
-" __global const int* indices,\n"
-" __global const btGpuChildShape* gpuChildShapes,\n"
-" __global btAabbCL* aabbs,\n"
-" __global float4* concaveSeparatingNormalsOut,\n"
-" __global int* concaveHasSeparatingNormals,\n"
-" __global int4* clippingFacesOut,\n"
-" __global float4* worldVertsA1GPU,\n"
-" __global float4* worldNormalsAGPU,\n"
-" __global float4* worldVertsB1GPU,\n"
-" __global float* dmins,\n"
-" int vertexFaceCapacity,\n"
-" int numConcavePairs\n"
-" )\n"
-"{\n"
-" \n"
-" int i = get_global_id(0);\n"
-" if (i>=numConcavePairs)\n"
-" return;\n"
-" \n"
-" if (!concaveHasSeparatingNormals[i])\n"
-" return;\n"
-" \n"
-" int pairIdx = i;\n"
-" \n"
-" int bodyIndexA = concavePairs[i].x;\n"
-" int bodyIndexB = concavePairs[i].y;\n"
-" \n"
-" int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
-" int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
-" \n"
-" int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
-" int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
-" \n"
-" \n"
-" int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
-" int numActualConcaveConvexTests = 0;\n"
-" \n"
-" int f = concavePairs[i].z;\n"
-" \n"
-" bool overlap = false;\n"
-" \n"
-" ConvexPolyhedronCL convexPolyhedronA;\n"
-" \n"
-" //add 3 vertices of the triangle\n"
-" convexPolyhedronA.m_numVertices = 3;\n"
-" convexPolyhedronA.m_vertexOffset = 0;\n"
-" float4 localCenter = make_float4(0.f,0.f,0.f,0.f);\n"
-" \n"
-" btGpuFace face = faces[convexShapes[shapeIndexA].m_faceOffset+f];\n"
-" float4 triMinAabb, triMaxAabb;\n"
-" btAabbCL triAabb;\n"
-" triAabb.m_min = make_float4(1e30f,1e30f,1e30f,0.f);\n"
-" triAabb.m_max = make_float4(-1e30f,-1e30f,-1e30f,0.f);\n"
-" \n"
-" float4 verticesA[3];\n"
-" for (int i=0;i<3;i++)\n"
-" {\n"
-" int index = indices[face.m_indexOffset+i];\n"
-" float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];\n"
-" verticesA[i] = vert;\n"
-" localCenter += vert;\n"
-" \n"
-" triAabb.m_min = min(triAabb.m_min,vert);\n"
-" triAabb.m_max = max(triAabb.m_max,vert);\n"
-" \n"
-" }\n"
-" \n"
-" overlap = true;\n"
-" overlap = (triAabb.m_min.x > aabbs[bodyIndexB].m_max.x || triAabb.m_max.x < aabbs[bodyIndexB].m_min.x) ? false : overlap;\n"
-" overlap = (triAabb.m_min.z > aabbs[bodyIndexB].m_max.z || triAabb.m_max.z < aabbs[bodyIndexB].m_min.z) ? false : overlap;\n"
-" overlap = (triAabb.m_min.y > aabbs[bodyIndexB].m_max.y || triAabb.m_max.y < aabbs[bodyIndexB].m_min.y) ? false : overlap;\n"
-" \n"
-" if (overlap)\n"
-" {\n"
-" float dmin = dmins[i];\n"
-" int hasSeparatingAxis=5;\n"
-" float4 sepAxis=make_float4(1,2,3,4);\n"
-" sepAxis = concaveSeparatingNormalsOut[pairIdx];\n"
-" \n"
-" int localCC=0;\n"
-" numActualConcaveConvexTests++;\n"
-" \n"
-" //a triangle has 3 unique edges\n"
-" convexPolyhedronA.m_numUniqueEdges = 3;\n"
-" convexPolyhedronA.m_uniqueEdgesOffset = 0;\n"
-" float4 uniqueEdgesA[3];\n"
-" \n"
-" uniqueEdgesA[0] = (verticesA[1]-verticesA[0]);\n"
-" uniqueEdgesA[1] = (verticesA[2]-verticesA[1]);\n"
-" uniqueEdgesA[2] = (verticesA[0]-verticesA[2]);\n"
-" \n"
-" \n"
-" convexPolyhedronA.m_faceOffset = 0;\n"
-" \n"
-" float4 normal = make_float4(face.m_plane.x,face.m_plane.y,face.m_plane.z,0.f);\n"
-" \n"
-" btGpuFace facesA[TRIANGLE_NUM_CONVEX_FACES];\n"
-" int indicesA[3+3+2+2+2];\n"
-" int curUsedIndices=0;\n"
-" int fidx=0;\n"
-" \n"
-" //front size of triangle\n"
-" {\n"
-" facesA[fidx].m_indexOffset=curUsedIndices;\n"
-" indicesA[0] = 0;\n"
-" indicesA[1] = 1;\n"
-" indicesA[2] = 2;\n"
-" curUsedIndices+=3;\n"
-" float c = face.m_plane.w;\n"
-" facesA[fidx].m_plane.x = normal.x;\n"
-" facesA[fidx].m_plane.y = normal.y;\n"
-" facesA[fidx].m_plane.z = normal.z;\n"
-" facesA[fidx].m_plane.w = c;\n"
-" facesA[fidx].m_numIndices=3;\n"
-" }\n"
-" fidx++;\n"
-" //back size of triangle\n"
-" {\n"
-" facesA[fidx].m_indexOffset=curUsedIndices;\n"
-" indicesA[3]=2;\n"
-" indicesA[4]=1;\n"
-" indicesA[5]=0;\n"
-" curUsedIndices+=3;\n"
-" float c = dot(normal,verticesA[0]);\n"
-" float c1 = -face.m_plane.w;\n"
-" facesA[fidx].m_plane.x = -normal.x;\n"
-" facesA[fidx].m_plane.y = -normal.y;\n"
-" facesA[fidx].m_plane.z = -normal.z;\n"
-" facesA[fidx].m_plane.w = c;\n"
-" facesA[fidx].m_numIndices=3;\n"
-" }\n"
-" fidx++;\n"
-" \n"
-" bool addEdgePlanes = true;\n"
-" if (addEdgePlanes)\n"
-" {\n"
-" int numVertices=3;\n"
-" int prevVertex = numVertices-1;\n"
-" for (int i=0;i<numVertices;i++)\n"
-" {\n"
-" float4 v0 = verticesA[i];\n"
-" float4 v1 = verticesA[prevVertex];\n"
-" \n"
-" float4 edgeNormal = normalize(cross(normal,v1-v0));\n"
-" float c = -dot(edgeNormal,v0);\n"
-" \n"
-" facesA[fidx].m_numIndices = 2;\n"
-" facesA[fidx].m_indexOffset=curUsedIndices;\n"
-" indicesA[curUsedIndices++]=i;\n"
-" indicesA[curUsedIndices++]=prevVertex;\n"
-" \n"
-" facesA[fidx].m_plane.x = edgeNormal.x;\n"
-" facesA[fidx].m_plane.y = edgeNormal.y;\n"
-" facesA[fidx].m_plane.z = edgeNormal.z;\n"
-" facesA[fidx].m_plane.w = c;\n"
-" fidx++;\n"
-" prevVertex = i;\n"
-" }\n"
-" }\n"
-" convexPolyhedronA.m_numFaces = TRIANGLE_NUM_CONVEX_FACES;\n"
-" convexPolyhedronA.m_localCenter = localCenter*(1.f/3.f);\n"
-" \n"
-" \n"
-" float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
-" posA.w = 0.f;\n"
-" float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
-" posB.w = 0.f;\n"
-" \n"
-" float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
-" float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
-" \n"
-" \n"
-" \n"
-" \n"
-" ///////////////////\n"
-" ///compound shape support\n"
-" \n"
-" if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
-" {\n"
-" int compoundChild = concavePairs[pairIdx].w;\n"
-" int childShapeIndexB = compoundChild;//collidables[collidableIndexB].m_shapeIndex+compoundChild;\n"
-" int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
-" float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
-" float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
-" float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
-" float4 newOrnB = qtMul(ornB,childOrnB);\n"
-" posB = newPosB;\n"
-" ornB = newOrnB;\n"
-" shapeIndexB = collidables[childColIndexB].m_shapeIndex;\n"
-" }\n"
-" //////////////////\n"
-" \n"
-" float4 c0local = convexPolyhedronA.m_localCenter;\n"
-" float4 c0 = transform(&c0local, &posA, &ornA);\n"
-" float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
-" float4 c1 = transform(&c1local,&posB,&ornB);\n"
-" const float4 DeltaC2 = c0 - c1;\n"
-" \n"
-" \n"
-" {\n"
-" bool sepEE = findSeparatingAxisEdgeEdgeLocalA( &convexPolyhedronA, &convexShapes[shapeIndexB],\n"
-" posA,ornA,\n"
-" posB,ornB,\n"
-" DeltaC2,\n"
-" verticesA,uniqueEdgesA,facesA,indicesA,\n"
-" vertices,uniqueEdges,faces,indices,\n"
-" &sepAxis,&dmin);\n"
-" \n"
-" if (!sepEE)\n"
-" {\n"
-" hasSeparatingAxis = 0;\n"
-" } else\n"
-" {\n"
-" hasSeparatingAxis = 1;\n"
-" }\n"
-" }\n"
-" \n"
-" \n"
-" if (hasSeparatingAxis)\n"
-" {\n"
-" sepAxis.w = dmin;\n"
-" dmins[i] = dmin;\n"
-" concaveSeparatingNormalsOut[pairIdx]=sepAxis;\n"
-" concaveHasSeparatingNormals[i]=1;\n"
-" \n"
-" float minDist = -1e30f;\n"
-" float maxDist = 0.02f;\n"
-" \n"
-" findClippingFaces(sepAxis,\n"
-" &convexPolyhedronA,\n"
-" &convexShapes[shapeIndexB],\n"
-" posA,ornA,\n"
-" posB,ornB,\n"
-" worldVertsA1GPU,\n"
-" worldNormalsAGPU,\n"
-" worldVertsB1GPU,\n"
-" vertexFaceCapacity,\n"
-" minDist, maxDist,\n"
-" verticesA,\n"
-" facesA,\n"
-" indicesA,\n"
-" vertices,\n"
-" faces,\n"
-" indices,\n"
-" clippingFacesOut, pairIdx);\n"
-" \n"
-" \n"
-" } else\n"
-" { \n"
-" //mark this pair as in-active\n"
-" concavePairs[pairIdx].w = -1;\n"
-" }\n"
-" }\n"
-" else\n"
-" { \n"
-" //mark this pair as in-active\n"
-" concavePairs[pairIdx].w = -1;\n"
-" }\n"
-" \n"
-" concavePairs[i].z = -1;//for the next stage, z is used to determine existing contact points\n"
-"}\n"
-;
+static const char* satConcaveKernelsCL =
+ "//keep this enum in sync with the CPU version (in btCollidable.h)\n"
+ "//written by Erwin Coumans\n"
+ "#define SHAPE_CONVEX_HULL 3\n"
+ "#define SHAPE_CONCAVE_TRIMESH 5\n"
+ "#define TRIANGLE_NUM_CONVEX_FACES 5\n"
+ "#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6\n"
+ "#define B3_MAX_STACK_DEPTH 256\n"
+ "typedef unsigned int u32;\n"
+ "///keep this in sync with btCollidable.h\n"
+ "typedef struct\n"
+ "{\n"
+ " union {\n"
+ " int m_numChildShapes;\n"
+ " int m_bvhIndex;\n"
+ " };\n"
+ " union\n"
+ " {\n"
+ " float m_radius;\n"
+ " int m_compoundBvhIndex;\n"
+ " };\n"
+ " \n"
+ " int m_shapeType;\n"
+ " int m_shapeIndex;\n"
+ " \n"
+ "} btCollidableGpu;\n"
+ "#define MAX_NUM_PARTS_IN_BITS 10\n"
+ "///b3QuantizedBvhNode is a compressed aabb node, 16 bytes.\n"
+ "///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).\n"
+ "typedef struct\n"
+ "{\n"
+ " //12 bytes\n"
+ " unsigned short int m_quantizedAabbMin[3];\n"
+ " unsigned short int m_quantizedAabbMax[3];\n"
+ " //4 bytes\n"
+ " int m_escapeIndexOrTriangleIndex;\n"
+ "} b3QuantizedBvhNode;\n"
+ "typedef struct\n"
+ "{\n"
+ " float4 m_aabbMin;\n"
+ " float4 m_aabbMax;\n"
+ " float4 m_quantization;\n"
+ " int m_numNodes;\n"
+ " int m_numSubTrees;\n"
+ " int m_nodeOffset;\n"
+ " int m_subTreeOffset;\n"
+ "} b3BvhInfo;\n"
+ "int getTriangleIndex(const b3QuantizedBvhNode* rootNode)\n"
+ "{\n"
+ " unsigned int x=0;\n"
+ " unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);\n"
+ " // Get only the lower bits where the triangle index is stored\n"
+ " return (rootNode->m_escapeIndexOrTriangleIndex&~(y));\n"
+ "}\n"
+ "int getTriangleIndexGlobal(__global const b3QuantizedBvhNode* rootNode)\n"
+ "{\n"
+ " unsigned int x=0;\n"
+ " unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);\n"
+ " // Get only the lower bits where the triangle index is stored\n"
+ " return (rootNode->m_escapeIndexOrTriangleIndex&~(y));\n"
+ "}\n"
+ "int isLeafNode(const b3QuantizedBvhNode* rootNode)\n"
+ "{\n"
+ " //skipindex is negative (internal node), triangleindex >=0 (leafnode)\n"
+ " return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;\n"
+ "}\n"
+ "int isLeafNodeGlobal(__global const b3QuantizedBvhNode* rootNode)\n"
+ "{\n"
+ " //skipindex is negative (internal node), triangleindex >=0 (leafnode)\n"
+ " return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;\n"
+ "}\n"
+ " \n"
+ "int getEscapeIndex(const b3QuantizedBvhNode* rootNode)\n"
+ "{\n"
+ " return -rootNode->m_escapeIndexOrTriangleIndex;\n"
+ "}\n"
+ "int getEscapeIndexGlobal(__global const b3QuantizedBvhNode* rootNode)\n"
+ "{\n"
+ " return -rootNode->m_escapeIndexOrTriangleIndex;\n"
+ "}\n"
+ "typedef struct\n"
+ "{\n"
+ " //12 bytes\n"
+ " unsigned short int m_quantizedAabbMin[3];\n"
+ " unsigned short int m_quantizedAabbMax[3];\n"
+ " //4 bytes, points to the root of the subtree\n"
+ " int m_rootNodeIndex;\n"
+ " //4 bytes\n"
+ " int m_subtreeSize;\n"
+ " int m_padding[3];\n"
+ "} b3BvhSubtreeInfo;\n"
+ "typedef struct\n"
+ "{\n"
+ " float4 m_childPosition;\n"
+ " float4 m_childOrientation;\n"
+ " int m_shapeIndex;\n"
+ " int m_unused0;\n"
+ " int m_unused1;\n"
+ " int m_unused2;\n"
+ "} btGpuChildShape;\n"
+ "typedef struct\n"
+ "{\n"
+ " float4 m_pos;\n"
+ " float4 m_quat;\n"
+ " float4 m_linVel;\n"
+ " float4 m_angVel;\n"
+ " u32 m_collidableIdx;\n"
+ " float m_invMass;\n"
+ " float m_restituitionCoeff;\n"
+ " float m_frictionCoeff;\n"
+ "} BodyData;\n"
+ "typedef struct \n"
+ "{\n"
+ " float4 m_localCenter;\n"
+ " float4 m_extents;\n"
+ " float4 mC;\n"
+ " float4 mE;\n"
+ " \n"
+ " float m_radius;\n"
+ " int m_faceOffset;\n"
+ " int m_numFaces;\n"
+ " int m_numVertices;\n"
+ " int m_vertexOffset;\n"
+ " int m_uniqueEdgesOffset;\n"
+ " int m_numUniqueEdges;\n"
+ " int m_unused;\n"
+ "} ConvexPolyhedronCL;\n"
+ "typedef struct \n"
+ "{\n"
+ " union\n"
+ " {\n"
+ " float4 m_min;\n"
+ " float m_minElems[4];\n"
+ " int m_minIndices[4];\n"
+ " };\n"
+ " union\n"
+ " {\n"
+ " float4 m_max;\n"
+ " float m_maxElems[4];\n"
+ " int m_maxIndices[4];\n"
+ " };\n"
+ "} btAabbCL;\n"
+ "#ifndef B3_AABB_H\n"
+ "#define B3_AABB_H\n"
+ "#ifndef B3_FLOAT4_H\n"
+ "#define B3_FLOAT4_H\n"
+ "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+ "#define B3_PLATFORM_DEFINITIONS_H\n"
+ "struct MyTest\n"
+ "{\n"
+ " int bla;\n"
+ "};\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
+ "#define B3_LARGE_FLOAT 1e18f\n"
+ "#define B3_INFINITY 1e18f\n"
+ "#define b3Assert(a)\n"
+ "#define b3ConstArray(a) __global const a*\n"
+ "#define b3AtomicInc atomic_inc\n"
+ "#define b3AtomicAdd atomic_add\n"
+ "#define b3Fabs fabs\n"
+ "#define b3Sqrt native_sqrt\n"
+ "#define b3Sin native_sin\n"
+ "#define b3Cos native_cos\n"
+ "#define B3_STATIC\n"
+ "#endif\n"
+ "#endif\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ " typedef float4 b3Float4;\n"
+ " #define b3Float4ConstArg const b3Float4\n"
+ " #define b3MakeFloat4 (float4)\n"
+ " float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+ " {\n"
+ " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+ " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+ " return dot(a1, b1);\n"
+ " }\n"
+ " b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+ " {\n"
+ " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+ " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+ " return cross(a1, b1);\n"
+ " }\n"
+ " #define b3MinFloat4 min\n"
+ " #define b3MaxFloat4 max\n"
+ " #define b3Normalized(a) normalize(a)\n"
+ "#endif \n"
+ " \n"
+ "inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
+ "{\n"
+ " if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
+ " return false;\n"
+ " return true;\n"
+ "}\n"
+ "inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
+ "{\n"
+ " float maxDot = -B3_INFINITY;\n"
+ " int i = 0;\n"
+ " int ptIndex = -1;\n"
+ " for( i = 0; i < vecLen; i++ )\n"
+ " {\n"
+ " float dot = b3Dot3F4(vecArray[i],vec);\n"
+ " \n"
+ " if( dot > maxDot )\n"
+ " {\n"
+ " maxDot = dot;\n"
+ " ptIndex = i;\n"
+ " }\n"
+ " }\n"
+ " b3Assert(ptIndex>=0);\n"
+ " if (ptIndex<0)\n"
+ " {\n"
+ " ptIndex = 0;\n"
+ " }\n"
+ " *dotOut = maxDot;\n"
+ " return ptIndex;\n"
+ "}\n"
+ "#endif //B3_FLOAT4_H\n"
+ "#ifndef B3_MAT3x3_H\n"
+ "#define B3_MAT3x3_H\n"
+ "#ifndef B3_QUAT_H\n"
+ "#define B3_QUAT_H\n"
+ "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#endif\n"
+ "#endif\n"
+ "#ifndef B3_FLOAT4_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#endif \n"
+ "#endif //B3_FLOAT4_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ " typedef float4 b3Quat;\n"
+ " #define b3QuatConstArg const b3Quat\n"
+ " \n"
+ " \n"
+ "inline float4 b3FastNormalize4(float4 v)\n"
+ "{\n"
+ " v = (float4)(v.xyz,0.f);\n"
+ " return fast_normalize(v);\n"
+ "}\n"
+ " \n"
+ "inline b3Quat b3QuatMul(b3Quat a, b3Quat b);\n"
+ "inline b3Quat b3QuatNormalized(b3QuatConstArg in);\n"
+ "inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec);\n"
+ "inline b3Quat b3QuatInvert(b3QuatConstArg q);\n"
+ "inline b3Quat b3QuatInverse(b3QuatConstArg q);\n"
+ "inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b)\n"
+ "{\n"
+ " b3Quat ans;\n"
+ " ans = b3Cross3( a, b );\n"
+ " ans += a.w*b+b.w*a;\n"
+ "// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+ " ans.w = a.w*b.w - b3Dot3F4(a, b);\n"
+ " return ans;\n"
+ "}\n"
+ "inline b3Quat b3QuatNormalized(b3QuatConstArg in)\n"
+ "{\n"
+ " b3Quat q;\n"
+ " q=in;\n"
+ " //return b3FastNormalize4(in);\n"
+ " float len = native_sqrt(dot(q, q));\n"
+ " if(len > 0.f)\n"
+ " {\n"
+ " q *= 1.f / len;\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " q.x = q.y = q.z = 0.f;\n"
+ " q.w = 1.f;\n"
+ " }\n"
+ " return q;\n"
+ "}\n"
+ "inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+ "{\n"
+ " b3Quat qInv = b3QuatInvert( q );\n"
+ " float4 vcpy = vec;\n"
+ " vcpy.w = 0.f;\n"
+ " float4 out = b3QuatMul(b3QuatMul(q,vcpy),qInv);\n"
+ " return out;\n"
+ "}\n"
+ "inline b3Quat b3QuatInverse(b3QuatConstArg q)\n"
+ "{\n"
+ " return (b3Quat)(-q.xyz, q.w);\n"
+ "}\n"
+ "inline b3Quat b3QuatInvert(b3QuatConstArg q)\n"
+ "{\n"
+ " return (b3Quat)(-q.xyz, q.w);\n"
+ "}\n"
+ "inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+ "{\n"
+ " return b3QuatRotate( b3QuatInvert( q ), vec );\n"
+ "}\n"
+ "inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation)\n"
+ "{\n"
+ " return b3QuatRotate( orientation, point ) + (translation);\n"
+ "}\n"
+ " \n"
+ "#endif \n"
+ "#endif //B3_QUAT_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "typedef struct\n"
+ "{\n"
+ " b3Float4 m_row[3];\n"
+ "}b3Mat3x3;\n"
+ "#define b3Mat3x3ConstArg const b3Mat3x3\n"
+ "#define b3GetRow(m,row) (m.m_row[row])\n"
+ "inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat)\n"
+ "{\n"
+ " b3Float4 quat2 = (b3Float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);\n"
+ " b3Mat3x3 out;\n"
+ " out.m_row[0].x=1-2*quat2.y-2*quat2.z;\n"
+ " out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;\n"
+ " out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;\n"
+ " out.m_row[0].w = 0.f;\n"
+ " out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;\n"
+ " out.m_row[1].y=1-2*quat2.x-2*quat2.z;\n"
+ " out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;\n"
+ " out.m_row[1].w = 0.f;\n"
+ " out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;\n"
+ " out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;\n"
+ " out.m_row[2].z=1-2*quat2.x-2*quat2.y;\n"
+ " out.m_row[2].w = 0.f;\n"
+ " return out;\n"
+ "}\n"
+ "inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn)\n"
+ "{\n"
+ " b3Mat3x3 out;\n"
+ " out.m_row[0] = fabs(matIn.m_row[0]);\n"
+ " out.m_row[1] = fabs(matIn.m_row[1]);\n"
+ " out.m_row[2] = fabs(matIn.m_row[2]);\n"
+ " return out;\n"
+ "}\n"
+ "__inline\n"
+ "b3Mat3x3 mtZero();\n"
+ "__inline\n"
+ "b3Mat3x3 mtIdentity();\n"
+ "__inline\n"
+ "b3Mat3x3 mtTranspose(b3Mat3x3 m);\n"
+ "__inline\n"
+ "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);\n"
+ "__inline\n"
+ "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);\n"
+ "__inline\n"
+ "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);\n"
+ "__inline\n"
+ "b3Mat3x3 mtZero()\n"
+ "{\n"
+ " b3Mat3x3 m;\n"
+ " m.m_row[0] = (b3Float4)(0.f);\n"
+ " m.m_row[1] = (b3Float4)(0.f);\n"
+ " m.m_row[2] = (b3Float4)(0.f);\n"
+ " return m;\n"
+ "}\n"
+ "__inline\n"
+ "b3Mat3x3 mtIdentity()\n"
+ "{\n"
+ " b3Mat3x3 m;\n"
+ " m.m_row[0] = (b3Float4)(1,0,0,0);\n"
+ " m.m_row[1] = (b3Float4)(0,1,0,0);\n"
+ " m.m_row[2] = (b3Float4)(0,0,1,0);\n"
+ " return m;\n"
+ "}\n"
+ "__inline\n"
+ "b3Mat3x3 mtTranspose(b3Mat3x3 m)\n"
+ "{\n"
+ " b3Mat3x3 out;\n"
+ " out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
+ " out.m_row[1] = (b3Float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
+ " out.m_row[2] = (b3Float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
+ " return out;\n"
+ "}\n"
+ "__inline\n"
+ "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)\n"
+ "{\n"
+ " b3Mat3x3 transB;\n"
+ " transB = mtTranspose( b );\n"
+ " b3Mat3x3 ans;\n"
+ " // why this doesn't run when 0ing in the for{}\n"
+ " a.m_row[0].w = 0.f;\n"
+ " a.m_row[1].w = 0.f;\n"
+ " a.m_row[2].w = 0.f;\n"
+ " for(int i=0; i<3; i++)\n"
+ " {\n"
+ "// a.m_row[i].w = 0.f;\n"
+ " ans.m_row[i].x = b3Dot3F4(a.m_row[i],transB.m_row[0]);\n"
+ " ans.m_row[i].y = b3Dot3F4(a.m_row[i],transB.m_row[1]);\n"
+ " ans.m_row[i].z = b3Dot3F4(a.m_row[i],transB.m_row[2]);\n"
+ " ans.m_row[i].w = 0.f;\n"
+ " }\n"
+ " return ans;\n"
+ "}\n"
+ "__inline\n"
+ "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)\n"
+ "{\n"
+ " b3Float4 ans;\n"
+ " ans.x = b3Dot3F4( a.m_row[0], b );\n"
+ " ans.y = b3Dot3F4( a.m_row[1], b );\n"
+ " ans.z = b3Dot3F4( a.m_row[2], b );\n"
+ " ans.w = 0.f;\n"
+ " return ans;\n"
+ "}\n"
+ "__inline\n"
+ "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)\n"
+ "{\n"
+ " b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
+ " b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
+ " b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
+ " b3Float4 ans;\n"
+ " ans.x = b3Dot3F4( a, colx );\n"
+ " ans.y = b3Dot3F4( a, coly );\n"
+ " ans.z = b3Dot3F4( a, colz );\n"
+ " return ans;\n"
+ "}\n"
+ "#endif\n"
+ "#endif //B3_MAT3x3_H\n"
+ "typedef struct b3Aabb b3Aabb_t;\n"
+ "struct b3Aabb\n"
+ "{\n"
+ " union\n"
+ " {\n"
+ " float m_min[4];\n"
+ " b3Float4 m_minVec;\n"
+ " int m_minIndices[4];\n"
+ " };\n"
+ " union\n"
+ " {\n"
+ " float m_max[4];\n"
+ " b3Float4 m_maxVec;\n"
+ " int m_signedMaxIndices[4];\n"
+ " };\n"
+ "};\n"
+ "inline void b3TransformAabb2(b3Float4ConstArg localAabbMin,b3Float4ConstArg localAabbMax, float margin,\n"
+ " b3Float4ConstArg pos,\n"
+ " b3QuatConstArg orn,\n"
+ " b3Float4* aabbMinOut,b3Float4* aabbMaxOut)\n"
+ "{\n"
+ " b3Float4 localHalfExtents = 0.5f*(localAabbMax-localAabbMin);\n"
+ " localHalfExtents+=b3MakeFloat4(margin,margin,margin,0.f);\n"
+ " b3Float4 localCenter = 0.5f*(localAabbMax+localAabbMin);\n"
+ " b3Mat3x3 m;\n"
+ " m = b3QuatGetRotationMatrix(orn);\n"
+ " b3Mat3x3 abs_b = b3AbsoluteMat3x3(m);\n"
+ " b3Float4 center = b3TransformPoint(localCenter,pos,orn);\n"
+ " \n"
+ " b3Float4 extent = b3MakeFloat4(b3Dot3F4(localHalfExtents,b3GetRow(abs_b,0)),\n"
+ " b3Dot3F4(localHalfExtents,b3GetRow(abs_b,1)),\n"
+ " b3Dot3F4(localHalfExtents,b3GetRow(abs_b,2)),\n"
+ " 0.f);\n"
+ " *aabbMinOut = center-extent;\n"
+ " *aabbMaxOut = center+extent;\n"
+ "}\n"
+ "/// conservative test for overlap between two aabbs\n"
+ "inline bool b3TestAabbAgainstAabb(b3Float4ConstArg aabbMin1,b3Float4ConstArg aabbMax1,\n"
+ " b3Float4ConstArg aabbMin2, b3Float4ConstArg aabbMax2)\n"
+ "{\n"
+ " bool overlap = true;\n"
+ " overlap = (aabbMin1.x > aabbMax2.x || aabbMax1.x < aabbMin2.x) ? false : overlap;\n"
+ " overlap = (aabbMin1.z > aabbMax2.z || aabbMax1.z < aabbMin2.z) ? false : overlap;\n"
+ " overlap = (aabbMin1.y > aabbMax2.y || aabbMax1.y < aabbMin2.y) ? false : overlap;\n"
+ " return overlap;\n"
+ "}\n"
+ "#endif //B3_AABB_H\n"
+ "/*\n"
+ "Bullet Continuous Collision Detection and Physics Library\n"
+ "Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org\n"
+ "This software is provided 'as-is', without any express or implied warranty.\n"
+ "In no event will the authors be held liable for any damages arising from the use of this software.\n"
+ "Permission is granted to anyone to use this software for any purpose,\n"
+ "including commercial applications, and to alter it and redistribute it freely,\n"
+ "subject to the following restrictions:\n"
+ "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
+ "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+ "3. This notice may not be removed or altered from any source distribution.\n"
+ "*/\n"
+ "#ifndef B3_INT2_H\n"
+ "#define B3_INT2_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#define b3UnsignedInt2 uint2\n"
+ "#define b3Int2 int2\n"
+ "#define b3MakeInt2 (int2)\n"
+ "#endif //__cplusplus\n"
+ "#endif\n"
+ "typedef struct\n"
+ "{\n"
+ " float4 m_plane;\n"
+ " int m_indexOffset;\n"
+ " int m_numIndices;\n"
+ "} btGpuFace;\n"
+ "#define make_float4 (float4)\n"
+ "__inline\n"
+ "float4 cross3(float4 a, float4 b)\n"
+ "{\n"
+ " return cross(a,b);\n"
+ " \n"
+ "// float4 a1 = make_float4(a.xyz,0.f);\n"
+ "// float4 b1 = make_float4(b.xyz,0.f);\n"
+ "// return cross(a1,b1);\n"
+ "//float4 c = make_float4(a.y*b.z - a.z*b.y,a.z*b.x - a.x*b.z,a.x*b.y - a.y*b.x,0.f);\n"
+ " \n"
+ " // float4 c = make_float4(a.y*b.z - a.z*b.y,1.f,a.x*b.y - a.y*b.x,0.f);\n"
+ " \n"
+ " //return c;\n"
+ "}\n"
+ "__inline\n"
+ "float dot3F4(float4 a, float4 b)\n"
+ "{\n"
+ " float4 a1 = make_float4(a.xyz,0.f);\n"
+ " float4 b1 = make_float4(b.xyz,0.f);\n"
+ " return dot(a1, b1);\n"
+ "}\n"
+ "__inline\n"
+ "float4 fastNormalize4(float4 v)\n"
+ "{\n"
+ " v = make_float4(v.xyz,0.f);\n"
+ " return fast_normalize(v);\n"
+ "}\n"
+ "///////////////////////////////////////\n"
+ "// Quaternion\n"
+ "///////////////////////////////////////\n"
+ "typedef float4 Quaternion;\n"
+ "__inline\n"
+ "Quaternion qtMul(Quaternion a, Quaternion b);\n"
+ "__inline\n"
+ "Quaternion qtNormalize(Quaternion in);\n"
+ "__inline\n"
+ "float4 qtRotate(Quaternion q, float4 vec);\n"
+ "__inline\n"
+ "Quaternion qtInvert(Quaternion q);\n"
+ "__inline\n"
+ "Quaternion qtMul(Quaternion a, Quaternion b)\n"
+ "{\n"
+ " Quaternion ans;\n"
+ " ans = cross3( a, b );\n"
+ " ans += a.w*b+b.w*a;\n"
+ "// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+ " ans.w = a.w*b.w - dot3F4(a, b);\n"
+ " return ans;\n"
+ "}\n"
+ "__inline\n"
+ "Quaternion qtNormalize(Quaternion in)\n"
+ "{\n"
+ " return fastNormalize4(in);\n"
+ "// in /= length( in );\n"
+ "// return in;\n"
+ "}\n"
+ "__inline\n"
+ "float4 qtRotate(Quaternion q, float4 vec)\n"
+ "{\n"
+ " Quaternion qInv = qtInvert( q );\n"
+ " float4 vcpy = vec;\n"
+ " vcpy.w = 0.f;\n"
+ " float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
+ " return out;\n"
+ "}\n"
+ "__inline\n"
+ "Quaternion qtInvert(Quaternion q)\n"
+ "{\n"
+ " return (Quaternion)(-q.xyz, q.w);\n"
+ "}\n"
+ "__inline\n"
+ "float4 qtInvRotate(const Quaternion q, float4 vec)\n"
+ "{\n"
+ " return qtRotate( qtInvert( q ), vec );\n"
+ "}\n"
+ "__inline\n"
+ "float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)\n"
+ "{\n"
+ " return qtRotate( *orientation, *p ) + (*translation);\n"
+ "}\n"
+ "__inline\n"
+ "float4 normalize3(const float4 a)\n"
+ "{\n"
+ " float4 n = make_float4(a.x, a.y, a.z, 0.f);\n"
+ " return fastNormalize4( n );\n"
+ "}\n"
+ "inline void projectLocal(const ConvexPolyhedronCL* hull, const float4 pos, const float4 orn, \n"
+ "const float4* dir, const float4* vertices, float* min, float* max)\n"
+ "{\n"
+ " min[0] = FLT_MAX;\n"
+ " max[0] = -FLT_MAX;\n"
+ " int numVerts = hull->m_numVertices;\n"
+ " const float4 localDir = qtInvRotate(orn,*dir);\n"
+ " float offset = dot(pos,*dir);\n"
+ " for(int i=0;i<numVerts;i++)\n"
+ " {\n"
+ " float dp = dot(vertices[hull->m_vertexOffset+i],localDir);\n"
+ " if(dp < min[0]) \n"
+ " min[0] = dp;\n"
+ " if(dp > max[0]) \n"
+ " max[0] = dp;\n"
+ " }\n"
+ " if(min[0]>max[0])\n"
+ " {\n"
+ " float tmp = min[0];\n"
+ " min[0] = max[0];\n"
+ " max[0] = tmp;\n"
+ " }\n"
+ " min[0] += offset;\n"
+ " max[0] += offset;\n"
+ "}\n"
+ "inline void project(__global const ConvexPolyhedronCL* hull, const float4 pos, const float4 orn, \n"
+ "const float4* dir, __global const float4* vertices, float* min, float* max)\n"
+ "{\n"
+ " min[0] = FLT_MAX;\n"
+ " max[0] = -FLT_MAX;\n"
+ " int numVerts = hull->m_numVertices;\n"
+ " const float4 localDir = qtInvRotate(orn,*dir);\n"
+ " float offset = dot(pos,*dir);\n"
+ " for(int i=0;i<numVerts;i++)\n"
+ " {\n"
+ " float dp = dot(vertices[hull->m_vertexOffset+i],localDir);\n"
+ " if(dp < min[0]) \n"
+ " min[0] = dp;\n"
+ " if(dp > max[0]) \n"
+ " max[0] = dp;\n"
+ " }\n"
+ " if(min[0]>max[0])\n"
+ " {\n"
+ " float tmp = min[0];\n"
+ " min[0] = max[0];\n"
+ " max[0] = tmp;\n"
+ " }\n"
+ " min[0] += offset;\n"
+ " max[0] += offset;\n"
+ "}\n"
+ "inline bool TestSepAxisLocalA(const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
+ " const float4 posA,const float4 ornA,\n"
+ " const float4 posB,const float4 ornB,\n"
+ " float4* sep_axis, const float4* verticesA, __global const float4* verticesB,float* depth)\n"
+ "{\n"
+ " float Min0,Max0;\n"
+ " float Min1,Max1;\n"
+ " projectLocal(hullA,posA,ornA,sep_axis,verticesA, &Min0, &Max0);\n"
+ " project(hullB,posB,ornB, sep_axis,verticesB, &Min1, &Max1);\n"
+ " if(Max0<Min1 || Max1<Min0)\n"
+ " return false;\n"
+ " float d0 = Max0 - Min1;\n"
+ " float d1 = Max1 - Min0;\n"
+ " *depth = d0<d1 ? d0:d1;\n"
+ " return true;\n"
+ "}\n"
+ "inline bool IsAlmostZero(const float4 v)\n"
+ "{\n"
+ " if(fabs(v.x)>1e-6f || fabs(v.y)>1e-6f || fabs(v.z)>1e-6f)\n"
+ " return false;\n"
+ " return true;\n"
+ "}\n"
+ "bool findSeparatingAxisLocalA( const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
+ " const float4 posA1,\n"
+ " const float4 ornA,\n"
+ " const float4 posB1,\n"
+ " const float4 ornB,\n"
+ " const float4 DeltaC2,\n"
+ " \n"
+ " const float4* verticesA, \n"
+ " const float4* uniqueEdgesA, \n"
+ " const btGpuFace* facesA,\n"
+ " const int* indicesA,\n"
+ " __global const float4* verticesB, \n"
+ " __global const float4* uniqueEdgesB, \n"
+ " __global const btGpuFace* facesB,\n"
+ " __global const int* indicesB,\n"
+ " float4* sep,\n"
+ " float* dmin)\n"
+ "{\n"
+ " \n"
+ " float4 posA = posA1;\n"
+ " posA.w = 0.f;\n"
+ " float4 posB = posB1;\n"
+ " posB.w = 0.f;\n"
+ " int curPlaneTests=0;\n"
+ " {\n"
+ " int numFacesA = hullA->m_numFaces;\n"
+ " // Test normals from hullA\n"
+ " for(int i=0;i<numFacesA;i++)\n"
+ " {\n"
+ " const float4 normal = facesA[hullA->m_faceOffset+i].m_plane;\n"
+ " float4 faceANormalWS = qtRotate(ornA,normal);\n"
+ " if (dot3F4(DeltaC2,faceANormalWS)<0)\n"
+ " faceANormalWS*=-1.f;\n"
+ " curPlaneTests++;\n"
+ " float d;\n"
+ " if(!TestSepAxisLocalA( hullA, hullB, posA,ornA,posB,ornB,&faceANormalWS, verticesA, verticesB,&d))\n"
+ " return false;\n"
+ " if(d<*dmin)\n"
+ " {\n"
+ " *dmin = d;\n"
+ " *sep = faceANormalWS;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
+ " {\n"
+ " *sep = -(*sep);\n"
+ " }\n"
+ " return true;\n"
+ "}\n"
+ "bool findSeparatingAxisLocalB( __global const ConvexPolyhedronCL* hullA, const ConvexPolyhedronCL* hullB, \n"
+ " const float4 posA1,\n"
+ " const float4 ornA,\n"
+ " const float4 posB1,\n"
+ " const float4 ornB,\n"
+ " const float4 DeltaC2,\n"
+ " __global const float4* verticesA, \n"
+ " __global const float4* uniqueEdgesA, \n"
+ " __global const btGpuFace* facesA,\n"
+ " __global const int* indicesA,\n"
+ " const float4* verticesB,\n"
+ " const float4* uniqueEdgesB, \n"
+ " const btGpuFace* facesB,\n"
+ " const int* indicesB,\n"
+ " float4* sep,\n"
+ " float* dmin)\n"
+ "{\n"
+ " float4 posA = posA1;\n"
+ " posA.w = 0.f;\n"
+ " float4 posB = posB1;\n"
+ " posB.w = 0.f;\n"
+ " int curPlaneTests=0;\n"
+ " {\n"
+ " int numFacesA = hullA->m_numFaces;\n"
+ " // Test normals from hullA\n"
+ " for(int i=0;i<numFacesA;i++)\n"
+ " {\n"
+ " const float4 normal = facesA[hullA->m_faceOffset+i].m_plane;\n"
+ " float4 faceANormalWS = qtRotate(ornA,normal);\n"
+ " if (dot3F4(DeltaC2,faceANormalWS)<0)\n"
+ " faceANormalWS *= -1.f;\n"
+ " curPlaneTests++;\n"
+ " float d;\n"
+ " if(!TestSepAxisLocalA( hullB, hullA, posB,ornB,posA,ornA, &faceANormalWS, verticesB,verticesA, &d))\n"
+ " return false;\n"
+ " if(d<*dmin)\n"
+ " {\n"
+ " *dmin = d;\n"
+ " *sep = faceANormalWS;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
+ " {\n"
+ " *sep = -(*sep);\n"
+ " }\n"
+ " return true;\n"
+ "}\n"
+ "bool findSeparatingAxisEdgeEdgeLocalA( const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
+ " const float4 posA1,\n"
+ " const float4 ornA,\n"
+ " const float4 posB1,\n"
+ " const float4 ornB,\n"
+ " const float4 DeltaC2,\n"
+ " const float4* verticesA, \n"
+ " const float4* uniqueEdgesA, \n"
+ " const btGpuFace* facesA,\n"
+ " const int* indicesA,\n"
+ " __global const float4* verticesB, \n"
+ " __global const float4* uniqueEdgesB, \n"
+ " __global const btGpuFace* facesB,\n"
+ " __global const int* indicesB,\n"
+ " float4* sep,\n"
+ " float* dmin)\n"
+ "{\n"
+ " float4 posA = posA1;\n"
+ " posA.w = 0.f;\n"
+ " float4 posB = posB1;\n"
+ " posB.w = 0.f;\n"
+ " int curPlaneTests=0;\n"
+ " int curEdgeEdge = 0;\n"
+ " // Test edges\n"
+ " for(int e0=0;e0<hullA->m_numUniqueEdges;e0++)\n"
+ " {\n"
+ " const float4 edge0 = uniqueEdgesA[hullA->m_uniqueEdgesOffset+e0];\n"
+ " float4 edge0World = qtRotate(ornA,edge0);\n"
+ " for(int e1=0;e1<hullB->m_numUniqueEdges;e1++)\n"
+ " {\n"
+ " const float4 edge1 = uniqueEdgesB[hullB->m_uniqueEdgesOffset+e1];\n"
+ " float4 edge1World = qtRotate(ornB,edge1);\n"
+ " float4 crossje = cross3(edge0World,edge1World);\n"
+ " curEdgeEdge++;\n"
+ " if(!IsAlmostZero(crossje))\n"
+ " {\n"
+ " crossje = normalize3(crossje);\n"
+ " if (dot3F4(DeltaC2,crossje)<0)\n"
+ " crossje *= -1.f;\n"
+ " float dist;\n"
+ " bool result = true;\n"
+ " {\n"
+ " float Min0,Max0;\n"
+ " float Min1,Max1;\n"
+ " projectLocal(hullA,posA,ornA,&crossje,verticesA, &Min0, &Max0);\n"
+ " project(hullB,posB,ornB,&crossje,verticesB, &Min1, &Max1);\n"
+ " \n"
+ " if(Max0<Min1 || Max1<Min0)\n"
+ " result = false;\n"
+ " \n"
+ " float d0 = Max0 - Min1;\n"
+ " float d1 = Max1 - Min0;\n"
+ " dist = d0<d1 ? d0:d1;\n"
+ " result = true;\n"
+ " }\n"
+ " \n"
+ " if(dist<*dmin)\n"
+ " {\n"
+ " *dmin = dist;\n"
+ " *sep = crossje;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " \n"
+ " if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
+ " {\n"
+ " *sep = -(*sep);\n"
+ " }\n"
+ " return true;\n"
+ "}\n"
+ "inline int findClippingFaces(const float4 separatingNormal,\n"
+ " const ConvexPolyhedronCL* hullA, \n"
+ " __global const ConvexPolyhedronCL* hullB,\n"
+ " const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB,\n"
+ " __global float4* worldVertsA1,\n"
+ " __global float4* worldNormalsA1,\n"
+ " __global float4* worldVertsB1,\n"
+ " int capacityWorldVerts,\n"
+ " const float minDist, float maxDist,\n"
+ " const float4* verticesA,\n"
+ " const btGpuFace* facesA,\n"
+ " const int* indicesA,\n"
+ " __global const float4* verticesB,\n"
+ " __global const btGpuFace* facesB,\n"
+ " __global const int* indicesB,\n"
+ " __global int4* clippingFaces, int pairIndex)\n"
+ "{\n"
+ " int numContactsOut = 0;\n"
+ " int numWorldVertsB1= 0;\n"
+ " \n"
+ " \n"
+ " int closestFaceB=0;\n"
+ " float dmax = -FLT_MAX;\n"
+ " \n"
+ " {\n"
+ " for(int face=0;face<hullB->m_numFaces;face++)\n"
+ " {\n"
+ " const float4 Normal = make_float4(facesB[hullB->m_faceOffset+face].m_plane.x,\n"
+ " facesB[hullB->m_faceOffset+face].m_plane.y, facesB[hullB->m_faceOffset+face].m_plane.z,0.f);\n"
+ " const float4 WorldNormal = qtRotate(ornB, Normal);\n"
+ " float d = dot3F4(WorldNormal,separatingNormal);\n"
+ " if (d > dmax)\n"
+ " {\n"
+ " dmax = d;\n"
+ " closestFaceB = face;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " \n"
+ " {\n"
+ " const btGpuFace polyB = facesB[hullB->m_faceOffset+closestFaceB];\n"
+ " int numVertices = polyB.m_numIndices;\n"
+ " if (numVertices>capacityWorldVerts)\n"
+ " numVertices = capacityWorldVerts;\n"
+ " if (numVertices<0)\n"
+ " numVertices = 0;\n"
+ " \n"
+ " for(int e0=0;e0<numVertices;e0++)\n"
+ " {\n"
+ " if (e0<capacityWorldVerts)\n"
+ " {\n"
+ " const float4 b = verticesB[hullB->m_vertexOffset+indicesB[polyB.m_indexOffset+e0]];\n"
+ " worldVertsB1[pairIndex*capacityWorldVerts+numWorldVertsB1++] = transform(&b,&posB,&ornB);\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " \n"
+ " int closestFaceA=0;\n"
+ " {\n"
+ " float dmin = FLT_MAX;\n"
+ " for(int face=0;face<hullA->m_numFaces;face++)\n"
+ " {\n"
+ " const float4 Normal = make_float4(\n"
+ " facesA[hullA->m_faceOffset+face].m_plane.x,\n"
+ " facesA[hullA->m_faceOffset+face].m_plane.y,\n"
+ " facesA[hullA->m_faceOffset+face].m_plane.z,\n"
+ " 0.f);\n"
+ " const float4 faceANormalWS = qtRotate(ornA,Normal);\n"
+ " \n"
+ " float d = dot3F4(faceANormalWS,separatingNormal);\n"
+ " if (d < dmin)\n"
+ " {\n"
+ " dmin = d;\n"
+ " closestFaceA = face;\n"
+ " worldNormalsA1[pairIndex] = faceANormalWS;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " \n"
+ " int numVerticesA = facesA[hullA->m_faceOffset+closestFaceA].m_numIndices;\n"
+ " if (numVerticesA>capacityWorldVerts)\n"
+ " numVerticesA = capacityWorldVerts;\n"
+ " if (numVerticesA<0)\n"
+ " numVerticesA=0;\n"
+ " \n"
+ " for(int e0=0;e0<numVerticesA;e0++)\n"
+ " {\n"
+ " if (e0<capacityWorldVerts)\n"
+ " {\n"
+ " const float4 a = verticesA[hullA->m_vertexOffset+indicesA[facesA[hullA->m_faceOffset+closestFaceA].m_indexOffset+e0]];\n"
+ " worldVertsA1[pairIndex*capacityWorldVerts+e0] = transform(&a, &posA,&ornA);\n"
+ " }\n"
+ " }\n"
+ " \n"
+ " clippingFaces[pairIndex].x = closestFaceA;\n"
+ " clippingFaces[pairIndex].y = closestFaceB;\n"
+ " clippingFaces[pairIndex].z = numVerticesA;\n"
+ " clippingFaces[pairIndex].w = numWorldVertsB1;\n"
+ " \n"
+ " \n"
+ " return numContactsOut;\n"
+ "}\n"
+ "// work-in-progress\n"
+ "__kernel void findConcaveSeparatingAxisVertexFaceKernel( __global int4* concavePairs,\n"
+ " __global const BodyData* rigidBodies,\n"
+ " __global const btCollidableGpu* collidables,\n"
+ " __global const ConvexPolyhedronCL* convexShapes,\n"
+ " __global const float4* vertices,\n"
+ " __global const float4* uniqueEdges,\n"
+ " __global const btGpuFace* faces,\n"
+ " __global const int* indices,\n"
+ " __global const btGpuChildShape* gpuChildShapes,\n"
+ " __global btAabbCL* aabbs,\n"
+ " __global float4* concaveSeparatingNormalsOut,\n"
+ " __global int* concaveHasSeparatingNormals,\n"
+ " __global int4* clippingFacesOut,\n"
+ " __global float4* worldVertsA1GPU,\n"
+ " __global float4* worldNormalsAGPU,\n"
+ " __global float4* worldVertsB1GPU,\n"
+ " __global float* dmins,\n"
+ " int vertexFaceCapacity,\n"
+ " int numConcavePairs\n"
+ " )\n"
+ "{\n"
+ " \n"
+ " int i = get_global_id(0);\n"
+ " if (i>=numConcavePairs)\n"
+ " return;\n"
+ " \n"
+ " concaveHasSeparatingNormals[i] = 0;\n"
+ " \n"
+ " int pairIdx = i;\n"
+ " \n"
+ " int bodyIndexA = concavePairs[i].x;\n"
+ " int bodyIndexB = concavePairs[i].y;\n"
+ " \n"
+ " int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+ " int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+ " \n"
+ " int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+ " int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+ " \n"
+ " if (collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL&&\n"
+ " collidables[collidableIndexB].m_shapeType!=SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
+ " {\n"
+ " concavePairs[pairIdx].w = -1;\n"
+ " return;\n"
+ " }\n"
+ " \n"
+ " \n"
+ " \n"
+ " int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
+ " int numActualConcaveConvexTests = 0;\n"
+ " \n"
+ " int f = concavePairs[i].z;\n"
+ " \n"
+ " bool overlap = false;\n"
+ " \n"
+ " ConvexPolyhedronCL convexPolyhedronA;\n"
+ " \n"
+ " //add 3 vertices of the triangle\n"
+ " convexPolyhedronA.m_numVertices = 3;\n"
+ " convexPolyhedronA.m_vertexOffset = 0;\n"
+ " float4 localCenter = make_float4(0.f,0.f,0.f,0.f);\n"
+ " \n"
+ " btGpuFace face = faces[convexShapes[shapeIndexA].m_faceOffset+f];\n"
+ " float4 triMinAabb, triMaxAabb;\n"
+ " btAabbCL triAabb;\n"
+ " triAabb.m_min = make_float4(1e30f,1e30f,1e30f,0.f);\n"
+ " triAabb.m_max = make_float4(-1e30f,-1e30f,-1e30f,0.f);\n"
+ " \n"
+ " float4 verticesA[3];\n"
+ " for (int i=0;i<3;i++)\n"
+ " {\n"
+ " int index = indices[face.m_indexOffset+i];\n"
+ " float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];\n"
+ " verticesA[i] = vert;\n"
+ " localCenter += vert;\n"
+ " \n"
+ " triAabb.m_min = min(triAabb.m_min,vert);\n"
+ " triAabb.m_max = max(triAabb.m_max,vert);\n"
+ " \n"
+ " }\n"
+ " \n"
+ " overlap = true;\n"
+ " overlap = (triAabb.m_min.x > aabbs[bodyIndexB].m_max.x || triAabb.m_max.x < aabbs[bodyIndexB].m_min.x) ? false : overlap;\n"
+ " overlap = (triAabb.m_min.z > aabbs[bodyIndexB].m_max.z || triAabb.m_max.z < aabbs[bodyIndexB].m_min.z) ? false : overlap;\n"
+ " overlap = (triAabb.m_min.y > aabbs[bodyIndexB].m_max.y || triAabb.m_max.y < aabbs[bodyIndexB].m_min.y) ? false : overlap;\n"
+ " \n"
+ " if (overlap)\n"
+ " {\n"
+ " float dmin = FLT_MAX;\n"
+ " int hasSeparatingAxis=5;\n"
+ " float4 sepAxis=make_float4(1,2,3,4);\n"
+ " \n"
+ " int localCC=0;\n"
+ " numActualConcaveConvexTests++;\n"
+ " \n"
+ " //a triangle has 3 unique edges\n"
+ " convexPolyhedronA.m_numUniqueEdges = 3;\n"
+ " convexPolyhedronA.m_uniqueEdgesOffset = 0;\n"
+ " float4 uniqueEdgesA[3];\n"
+ " \n"
+ " uniqueEdgesA[0] = (verticesA[1]-verticesA[0]);\n"
+ " uniqueEdgesA[1] = (verticesA[2]-verticesA[1]);\n"
+ " uniqueEdgesA[2] = (verticesA[0]-verticesA[2]);\n"
+ " \n"
+ " \n"
+ " convexPolyhedronA.m_faceOffset = 0;\n"
+ " \n"
+ " float4 normal = make_float4(face.m_plane.x,face.m_plane.y,face.m_plane.z,0.f);\n"
+ " \n"
+ " btGpuFace facesA[TRIANGLE_NUM_CONVEX_FACES];\n"
+ " int indicesA[3+3+2+2+2];\n"
+ " int curUsedIndices=0;\n"
+ " int fidx=0;\n"
+ " \n"
+ " //front size of triangle\n"
+ " {\n"
+ " facesA[fidx].m_indexOffset=curUsedIndices;\n"
+ " indicesA[0] = 0;\n"
+ " indicesA[1] = 1;\n"
+ " indicesA[2] = 2;\n"
+ " curUsedIndices+=3;\n"
+ " float c = face.m_plane.w;\n"
+ " facesA[fidx].m_plane.x = normal.x;\n"
+ " facesA[fidx].m_plane.y = normal.y;\n"
+ " facesA[fidx].m_plane.z = normal.z;\n"
+ " facesA[fidx].m_plane.w = c;\n"
+ " facesA[fidx].m_numIndices=3;\n"
+ " }\n"
+ " fidx++;\n"
+ " //back size of triangle\n"
+ " {\n"
+ " facesA[fidx].m_indexOffset=curUsedIndices;\n"
+ " indicesA[3]=2;\n"
+ " indicesA[4]=1;\n"
+ " indicesA[5]=0;\n"
+ " curUsedIndices+=3;\n"
+ " float c = dot(normal,verticesA[0]);\n"
+ " float c1 = -face.m_plane.w;\n"
+ " facesA[fidx].m_plane.x = -normal.x;\n"
+ " facesA[fidx].m_plane.y = -normal.y;\n"
+ " facesA[fidx].m_plane.z = -normal.z;\n"
+ " facesA[fidx].m_plane.w = c;\n"
+ " facesA[fidx].m_numIndices=3;\n"
+ " }\n"
+ " fidx++;\n"
+ " \n"
+ " bool addEdgePlanes = true;\n"
+ " if (addEdgePlanes)\n"
+ " {\n"
+ " int numVertices=3;\n"
+ " int prevVertex = numVertices-1;\n"
+ " for (int i=0;i<numVertices;i++)\n"
+ " {\n"
+ " float4 v0 = verticesA[i];\n"
+ " float4 v1 = verticesA[prevVertex];\n"
+ " \n"
+ " float4 edgeNormal = normalize(cross(normal,v1-v0));\n"
+ " float c = -dot(edgeNormal,v0);\n"
+ " \n"
+ " facesA[fidx].m_numIndices = 2;\n"
+ " facesA[fidx].m_indexOffset=curUsedIndices;\n"
+ " indicesA[curUsedIndices++]=i;\n"
+ " indicesA[curUsedIndices++]=prevVertex;\n"
+ " \n"
+ " facesA[fidx].m_plane.x = edgeNormal.x;\n"
+ " facesA[fidx].m_plane.y = edgeNormal.y;\n"
+ " facesA[fidx].m_plane.z = edgeNormal.z;\n"
+ " facesA[fidx].m_plane.w = c;\n"
+ " fidx++;\n"
+ " prevVertex = i;\n"
+ " }\n"
+ " }\n"
+ " convexPolyhedronA.m_numFaces = TRIANGLE_NUM_CONVEX_FACES;\n"
+ " convexPolyhedronA.m_localCenter = localCenter*(1.f/3.f);\n"
+ " \n"
+ " \n"
+ " float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+ " posA.w = 0.f;\n"
+ " float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+ " posB.w = 0.f;\n"
+ " \n"
+ " float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
+ " float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " ///////////////////\n"
+ " ///compound shape support\n"
+ " \n"
+ " if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
+ " {\n"
+ " int compoundChild = concavePairs[pairIdx].w;\n"
+ " int childShapeIndexB = compoundChild;//collidables[collidableIndexB].m_shapeIndex+compoundChild;\n"
+ " int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
+ " float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
+ " float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
+ " float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
+ " float4 newOrnB = qtMul(ornB,childOrnB);\n"
+ " posB = newPosB;\n"
+ " ornB = newOrnB;\n"
+ " shapeIndexB = collidables[childColIndexB].m_shapeIndex;\n"
+ " }\n"
+ " //////////////////\n"
+ " \n"
+ " float4 c0local = convexPolyhedronA.m_localCenter;\n"
+ " float4 c0 = transform(&c0local, &posA, &ornA);\n"
+ " float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
+ " float4 c1 = transform(&c1local,&posB,&ornB);\n"
+ " const float4 DeltaC2 = c0 - c1;\n"
+ " \n"
+ " \n"
+ " bool sepA = findSeparatingAxisLocalA( &convexPolyhedronA, &convexShapes[shapeIndexB],\n"
+ " posA,ornA,\n"
+ " posB,ornB,\n"
+ " DeltaC2,\n"
+ " verticesA,uniqueEdgesA,facesA,indicesA,\n"
+ " vertices,uniqueEdges,faces,indices,\n"
+ " &sepAxis,&dmin);\n"
+ " hasSeparatingAxis = 4;\n"
+ " if (!sepA)\n"
+ " {\n"
+ " hasSeparatingAxis = 0;\n"
+ " } else\n"
+ " {\n"
+ " bool sepB = findSeparatingAxisLocalB( &convexShapes[shapeIndexB],&convexPolyhedronA,\n"
+ " posB,ornB,\n"
+ " posA,ornA,\n"
+ " DeltaC2,\n"
+ " vertices,uniqueEdges,faces,indices,\n"
+ " verticesA,uniqueEdgesA,facesA,indicesA,\n"
+ " &sepAxis,&dmin);\n"
+ " \n"
+ " if (!sepB)\n"
+ " {\n"
+ " hasSeparatingAxis = 0;\n"
+ " } else\n"
+ " {\n"
+ " hasSeparatingAxis = 1;\n"
+ " }\n"
+ " } \n"
+ " \n"
+ " if (hasSeparatingAxis)\n"
+ " {\n"
+ " dmins[i] = dmin;\n"
+ " concaveSeparatingNormalsOut[pairIdx]=sepAxis;\n"
+ " concaveHasSeparatingNormals[i]=1;\n"
+ " \n"
+ " } else\n"
+ " { \n"
+ " //mark this pair as in-active\n"
+ " concavePairs[pairIdx].w = -1;\n"
+ " }\n"
+ " }\n"
+ " else\n"
+ " { \n"
+ " //mark this pair as in-active\n"
+ " concavePairs[pairIdx].w = -1;\n"
+ " }\n"
+ "}\n"
+ "// work-in-progress\n"
+ "__kernel void findConcaveSeparatingAxisEdgeEdgeKernel( __global int4* concavePairs,\n"
+ " __global const BodyData* rigidBodies,\n"
+ " __global const btCollidableGpu* collidables,\n"
+ " __global const ConvexPolyhedronCL* convexShapes,\n"
+ " __global const float4* vertices,\n"
+ " __global const float4* uniqueEdges,\n"
+ " __global const btGpuFace* faces,\n"
+ " __global const int* indices,\n"
+ " __global const btGpuChildShape* gpuChildShapes,\n"
+ " __global btAabbCL* aabbs,\n"
+ " __global float4* concaveSeparatingNormalsOut,\n"
+ " __global int* concaveHasSeparatingNormals,\n"
+ " __global int4* clippingFacesOut,\n"
+ " __global float4* worldVertsA1GPU,\n"
+ " __global float4* worldNormalsAGPU,\n"
+ " __global float4* worldVertsB1GPU,\n"
+ " __global float* dmins,\n"
+ " int vertexFaceCapacity,\n"
+ " int numConcavePairs\n"
+ " )\n"
+ "{\n"
+ " \n"
+ " int i = get_global_id(0);\n"
+ " if (i>=numConcavePairs)\n"
+ " return;\n"
+ " \n"
+ " if (!concaveHasSeparatingNormals[i])\n"
+ " return;\n"
+ " \n"
+ " int pairIdx = i;\n"
+ " \n"
+ " int bodyIndexA = concavePairs[i].x;\n"
+ " int bodyIndexB = concavePairs[i].y;\n"
+ " \n"
+ " int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+ " int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+ " \n"
+ " int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+ " int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+ " \n"
+ " \n"
+ " int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
+ " int numActualConcaveConvexTests = 0;\n"
+ " \n"
+ " int f = concavePairs[i].z;\n"
+ " \n"
+ " bool overlap = false;\n"
+ " \n"
+ " ConvexPolyhedronCL convexPolyhedronA;\n"
+ " \n"
+ " //add 3 vertices of the triangle\n"
+ " convexPolyhedronA.m_numVertices = 3;\n"
+ " convexPolyhedronA.m_vertexOffset = 0;\n"
+ " float4 localCenter = make_float4(0.f,0.f,0.f,0.f);\n"
+ " \n"
+ " btGpuFace face = faces[convexShapes[shapeIndexA].m_faceOffset+f];\n"
+ " float4 triMinAabb, triMaxAabb;\n"
+ " btAabbCL triAabb;\n"
+ " triAabb.m_min = make_float4(1e30f,1e30f,1e30f,0.f);\n"
+ " triAabb.m_max = make_float4(-1e30f,-1e30f,-1e30f,0.f);\n"
+ " \n"
+ " float4 verticesA[3];\n"
+ " for (int i=0;i<3;i++)\n"
+ " {\n"
+ " int index = indices[face.m_indexOffset+i];\n"
+ " float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];\n"
+ " verticesA[i] = vert;\n"
+ " localCenter += vert;\n"
+ " \n"
+ " triAabb.m_min = min(triAabb.m_min,vert);\n"
+ " triAabb.m_max = max(triAabb.m_max,vert);\n"
+ " \n"
+ " }\n"
+ " \n"
+ " overlap = true;\n"
+ " overlap = (triAabb.m_min.x > aabbs[bodyIndexB].m_max.x || triAabb.m_max.x < aabbs[bodyIndexB].m_min.x) ? false : overlap;\n"
+ " overlap = (triAabb.m_min.z > aabbs[bodyIndexB].m_max.z || triAabb.m_max.z < aabbs[bodyIndexB].m_min.z) ? false : overlap;\n"
+ " overlap = (triAabb.m_min.y > aabbs[bodyIndexB].m_max.y || triAabb.m_max.y < aabbs[bodyIndexB].m_min.y) ? false : overlap;\n"
+ " \n"
+ " if (overlap)\n"
+ " {\n"
+ " float dmin = dmins[i];\n"
+ " int hasSeparatingAxis=5;\n"
+ " float4 sepAxis=make_float4(1,2,3,4);\n"
+ " sepAxis = concaveSeparatingNormalsOut[pairIdx];\n"
+ " \n"
+ " int localCC=0;\n"
+ " numActualConcaveConvexTests++;\n"
+ " \n"
+ " //a triangle has 3 unique edges\n"
+ " convexPolyhedronA.m_numUniqueEdges = 3;\n"
+ " convexPolyhedronA.m_uniqueEdgesOffset = 0;\n"
+ " float4 uniqueEdgesA[3];\n"
+ " \n"
+ " uniqueEdgesA[0] = (verticesA[1]-verticesA[0]);\n"
+ " uniqueEdgesA[1] = (verticesA[2]-verticesA[1]);\n"
+ " uniqueEdgesA[2] = (verticesA[0]-verticesA[2]);\n"
+ " \n"
+ " \n"
+ " convexPolyhedronA.m_faceOffset = 0;\n"
+ " \n"
+ " float4 normal = make_float4(face.m_plane.x,face.m_plane.y,face.m_plane.z,0.f);\n"
+ " \n"
+ " btGpuFace facesA[TRIANGLE_NUM_CONVEX_FACES];\n"
+ " int indicesA[3+3+2+2+2];\n"
+ " int curUsedIndices=0;\n"
+ " int fidx=0;\n"
+ " \n"
+ " //front size of triangle\n"
+ " {\n"
+ " facesA[fidx].m_indexOffset=curUsedIndices;\n"
+ " indicesA[0] = 0;\n"
+ " indicesA[1] = 1;\n"
+ " indicesA[2] = 2;\n"
+ " curUsedIndices+=3;\n"
+ " float c = face.m_plane.w;\n"
+ " facesA[fidx].m_plane.x = normal.x;\n"
+ " facesA[fidx].m_plane.y = normal.y;\n"
+ " facesA[fidx].m_plane.z = normal.z;\n"
+ " facesA[fidx].m_plane.w = c;\n"
+ " facesA[fidx].m_numIndices=3;\n"
+ " }\n"
+ " fidx++;\n"
+ " //back size of triangle\n"
+ " {\n"
+ " facesA[fidx].m_indexOffset=curUsedIndices;\n"
+ " indicesA[3]=2;\n"
+ " indicesA[4]=1;\n"
+ " indicesA[5]=0;\n"
+ " curUsedIndices+=3;\n"
+ " float c = dot(normal,verticesA[0]);\n"
+ " float c1 = -face.m_plane.w;\n"
+ " facesA[fidx].m_plane.x = -normal.x;\n"
+ " facesA[fidx].m_plane.y = -normal.y;\n"
+ " facesA[fidx].m_plane.z = -normal.z;\n"
+ " facesA[fidx].m_plane.w = c;\n"
+ " facesA[fidx].m_numIndices=3;\n"
+ " }\n"
+ " fidx++;\n"
+ " \n"
+ " bool addEdgePlanes = true;\n"
+ " if (addEdgePlanes)\n"
+ " {\n"
+ " int numVertices=3;\n"
+ " int prevVertex = numVertices-1;\n"
+ " for (int i=0;i<numVertices;i++)\n"
+ " {\n"
+ " float4 v0 = verticesA[i];\n"
+ " float4 v1 = verticesA[prevVertex];\n"
+ " \n"
+ " float4 edgeNormal = normalize(cross(normal,v1-v0));\n"
+ " float c = -dot(edgeNormal,v0);\n"
+ " \n"
+ " facesA[fidx].m_numIndices = 2;\n"
+ " facesA[fidx].m_indexOffset=curUsedIndices;\n"
+ " indicesA[curUsedIndices++]=i;\n"
+ " indicesA[curUsedIndices++]=prevVertex;\n"
+ " \n"
+ " facesA[fidx].m_plane.x = edgeNormal.x;\n"
+ " facesA[fidx].m_plane.y = edgeNormal.y;\n"
+ " facesA[fidx].m_plane.z = edgeNormal.z;\n"
+ " facesA[fidx].m_plane.w = c;\n"
+ " fidx++;\n"
+ " prevVertex = i;\n"
+ " }\n"
+ " }\n"
+ " convexPolyhedronA.m_numFaces = TRIANGLE_NUM_CONVEX_FACES;\n"
+ " convexPolyhedronA.m_localCenter = localCenter*(1.f/3.f);\n"
+ " \n"
+ " \n"
+ " float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+ " posA.w = 0.f;\n"
+ " float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+ " posB.w = 0.f;\n"
+ " \n"
+ " float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
+ " float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " ///////////////////\n"
+ " ///compound shape support\n"
+ " \n"
+ " if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
+ " {\n"
+ " int compoundChild = concavePairs[pairIdx].w;\n"
+ " int childShapeIndexB = compoundChild;//collidables[collidableIndexB].m_shapeIndex+compoundChild;\n"
+ " int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
+ " float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
+ " float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
+ " float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
+ " float4 newOrnB = qtMul(ornB,childOrnB);\n"
+ " posB = newPosB;\n"
+ " ornB = newOrnB;\n"
+ " shapeIndexB = collidables[childColIndexB].m_shapeIndex;\n"
+ " }\n"
+ " //////////////////\n"
+ " \n"
+ " float4 c0local = convexPolyhedronA.m_localCenter;\n"
+ " float4 c0 = transform(&c0local, &posA, &ornA);\n"
+ " float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
+ " float4 c1 = transform(&c1local,&posB,&ornB);\n"
+ " const float4 DeltaC2 = c0 - c1;\n"
+ " \n"
+ " \n"
+ " {\n"
+ " bool sepEE = findSeparatingAxisEdgeEdgeLocalA( &convexPolyhedronA, &convexShapes[shapeIndexB],\n"
+ " posA,ornA,\n"
+ " posB,ornB,\n"
+ " DeltaC2,\n"
+ " verticesA,uniqueEdgesA,facesA,indicesA,\n"
+ " vertices,uniqueEdges,faces,indices,\n"
+ " &sepAxis,&dmin);\n"
+ " \n"
+ " if (!sepEE)\n"
+ " {\n"
+ " hasSeparatingAxis = 0;\n"
+ " } else\n"
+ " {\n"
+ " hasSeparatingAxis = 1;\n"
+ " }\n"
+ " }\n"
+ " \n"
+ " \n"
+ " if (hasSeparatingAxis)\n"
+ " {\n"
+ " sepAxis.w = dmin;\n"
+ " dmins[i] = dmin;\n"
+ " concaveSeparatingNormalsOut[pairIdx]=sepAxis;\n"
+ " concaveHasSeparatingNormals[i]=1;\n"
+ " \n"
+ " float minDist = -1e30f;\n"
+ " float maxDist = 0.02f;\n"
+ " \n"
+ " findClippingFaces(sepAxis,\n"
+ " &convexPolyhedronA,\n"
+ " &convexShapes[shapeIndexB],\n"
+ " posA,ornA,\n"
+ " posB,ornB,\n"
+ " worldVertsA1GPU,\n"
+ " worldNormalsAGPU,\n"
+ " worldVertsB1GPU,\n"
+ " vertexFaceCapacity,\n"
+ " minDist, maxDist,\n"
+ " verticesA,\n"
+ " facesA,\n"
+ " indicesA,\n"
+ " vertices,\n"
+ " faces,\n"
+ " indices,\n"
+ " clippingFacesOut, pairIdx);\n"
+ " \n"
+ " \n"
+ " } else\n"
+ " { \n"
+ " //mark this pair as in-active\n"
+ " concavePairs[pairIdx].w = -1;\n"
+ " }\n"
+ " }\n"
+ " else\n"
+ " { \n"
+ " //mark this pair as in-active\n"
+ " concavePairs[pairIdx].w = -1;\n"
+ " }\n"
+ " \n"
+ " concavePairs[i].z = -1;//for the next stage, z is used to determine existing contact points\n"
+ "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/satKernels.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/satKernels.h
index 6f8b0a90db..e627af2799 100644
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/satKernels.h
+++ b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/satKernels.h
@@ -1,2104 +1,2103 @@
//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* satKernelsCL= \
-"//keep this enum in sync with the CPU version (in btCollidable.h)\n"
-"//written by Erwin Coumans\n"
-"#define SHAPE_CONVEX_HULL 3\n"
-"#define SHAPE_CONCAVE_TRIMESH 5\n"
-"#define TRIANGLE_NUM_CONVEX_FACES 5\n"
-"#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6\n"
-"#define B3_MAX_STACK_DEPTH 256\n"
-"typedef unsigned int u32;\n"
-"///keep this in sync with btCollidable.h\n"
-"typedef struct\n"
-"{\n"
-" union {\n"
-" int m_numChildShapes;\n"
-" int m_bvhIndex;\n"
-" };\n"
-" union\n"
-" {\n"
-" float m_radius;\n"
-" int m_compoundBvhIndex;\n"
-" };\n"
-" \n"
-" int m_shapeType;\n"
-" int m_shapeIndex;\n"
-" \n"
-"} btCollidableGpu;\n"
-"#define MAX_NUM_PARTS_IN_BITS 10\n"
-"///b3QuantizedBvhNode is a compressed aabb node, 16 bytes.\n"
-"///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).\n"
-"typedef struct\n"
-"{\n"
-" //12 bytes\n"
-" unsigned short int m_quantizedAabbMin[3];\n"
-" unsigned short int m_quantizedAabbMax[3];\n"
-" //4 bytes\n"
-" int m_escapeIndexOrTriangleIndex;\n"
-"} b3QuantizedBvhNode;\n"
-"typedef struct\n"
-"{\n"
-" float4 m_aabbMin;\n"
-" float4 m_aabbMax;\n"
-" float4 m_quantization;\n"
-" int m_numNodes;\n"
-" int m_numSubTrees;\n"
-" int m_nodeOffset;\n"
-" int m_subTreeOffset;\n"
-"} b3BvhInfo;\n"
-"int getTriangleIndex(const b3QuantizedBvhNode* rootNode)\n"
-"{\n"
-" unsigned int x=0;\n"
-" unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);\n"
-" // Get only the lower bits where the triangle index is stored\n"
-" return (rootNode->m_escapeIndexOrTriangleIndex&~(y));\n"
-"}\n"
-"int getTriangleIndexGlobal(__global const b3QuantizedBvhNode* rootNode)\n"
-"{\n"
-" unsigned int x=0;\n"
-" unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);\n"
-" // Get only the lower bits where the triangle index is stored\n"
-" return (rootNode->m_escapeIndexOrTriangleIndex&~(y));\n"
-"}\n"
-"int isLeafNode(const b3QuantizedBvhNode* rootNode)\n"
-"{\n"
-" //skipindex is negative (internal node), triangleindex >=0 (leafnode)\n"
-" return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;\n"
-"}\n"
-"int isLeafNodeGlobal(__global const b3QuantizedBvhNode* rootNode)\n"
-"{\n"
-" //skipindex is negative (internal node), triangleindex >=0 (leafnode)\n"
-" return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;\n"
-"}\n"
-" \n"
-"int getEscapeIndex(const b3QuantizedBvhNode* rootNode)\n"
-"{\n"
-" return -rootNode->m_escapeIndexOrTriangleIndex;\n"
-"}\n"
-"int getEscapeIndexGlobal(__global const b3QuantizedBvhNode* rootNode)\n"
-"{\n"
-" return -rootNode->m_escapeIndexOrTriangleIndex;\n"
-"}\n"
-"typedef struct\n"
-"{\n"
-" //12 bytes\n"
-" unsigned short int m_quantizedAabbMin[3];\n"
-" unsigned short int m_quantizedAabbMax[3];\n"
-" //4 bytes, points to the root of the subtree\n"
-" int m_rootNodeIndex;\n"
-" //4 bytes\n"
-" int m_subtreeSize;\n"
-" int m_padding[3];\n"
-"} b3BvhSubtreeInfo;\n"
-"typedef struct\n"
-"{\n"
-" float4 m_childPosition;\n"
-" float4 m_childOrientation;\n"
-" int m_shapeIndex;\n"
-" int m_unused0;\n"
-" int m_unused1;\n"
-" int m_unused2;\n"
-"} btGpuChildShape;\n"
-"typedef struct\n"
-"{\n"
-" float4 m_pos;\n"
-" float4 m_quat;\n"
-" float4 m_linVel;\n"
-" float4 m_angVel;\n"
-" u32 m_collidableIdx;\n"
-" float m_invMass;\n"
-" float m_restituitionCoeff;\n"
-" float m_frictionCoeff;\n"
-"} BodyData;\n"
-"typedef struct \n"
-"{\n"
-" float4 m_localCenter;\n"
-" float4 m_extents;\n"
-" float4 mC;\n"
-" float4 mE;\n"
-" \n"
-" float m_radius;\n"
-" int m_faceOffset;\n"
-" int m_numFaces;\n"
-" int m_numVertices;\n"
-" int m_vertexOffset;\n"
-" int m_uniqueEdgesOffset;\n"
-" int m_numUniqueEdges;\n"
-" int m_unused;\n"
-"} ConvexPolyhedronCL;\n"
-"typedef struct \n"
-"{\n"
-" union\n"
-" {\n"
-" float4 m_min;\n"
-" float m_minElems[4];\n"
-" int m_minIndices[4];\n"
-" };\n"
-" union\n"
-" {\n"
-" float4 m_max;\n"
-" float m_maxElems[4];\n"
-" int m_maxIndices[4];\n"
-" };\n"
-"} btAabbCL;\n"
-"#ifndef B3_AABB_H\n"
-"#define B3_AABB_H\n"
-"#ifndef B3_FLOAT4_H\n"
-"#define B3_FLOAT4_H\n"
-"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
-"#define B3_PLATFORM_DEFINITIONS_H\n"
-"struct MyTest\n"
-"{\n"
-" int bla;\n"
-"};\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
-"#define B3_LARGE_FLOAT 1e18f\n"
-"#define B3_INFINITY 1e18f\n"
-"#define b3Assert(a)\n"
-"#define b3ConstArray(a) __global const a*\n"
-"#define b3AtomicInc atomic_inc\n"
-"#define b3AtomicAdd atomic_add\n"
-"#define b3Fabs fabs\n"
-"#define b3Sqrt native_sqrt\n"
-"#define b3Sin native_sin\n"
-"#define b3Cos native_cos\n"
-"#define B3_STATIC\n"
-"#endif\n"
-"#endif\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-" typedef float4 b3Float4;\n"
-" #define b3Float4ConstArg const b3Float4\n"
-" #define b3MakeFloat4 (float4)\n"
-" float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
-" {\n"
-" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
-" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
-" return dot(a1, b1);\n"
-" }\n"
-" b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
-" {\n"
-" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
-" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
-" return cross(a1, b1);\n"
-" }\n"
-" #define b3MinFloat4 min\n"
-" #define b3MaxFloat4 max\n"
-" #define b3Normalized(a) normalize(a)\n"
-"#endif \n"
-" \n"
-"inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
-"{\n"
-" if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
-" return false;\n"
-" return true;\n"
-"}\n"
-"inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
-"{\n"
-" float maxDot = -B3_INFINITY;\n"
-" int i = 0;\n"
-" int ptIndex = -1;\n"
-" for( i = 0; i < vecLen; i++ )\n"
-" {\n"
-" float dot = b3Dot3F4(vecArray[i],vec);\n"
-" \n"
-" if( dot > maxDot )\n"
-" {\n"
-" maxDot = dot;\n"
-" ptIndex = i;\n"
-" }\n"
-" }\n"
-" b3Assert(ptIndex>=0);\n"
-" if (ptIndex<0)\n"
-" {\n"
-" ptIndex = 0;\n"
-" }\n"
-" *dotOut = maxDot;\n"
-" return ptIndex;\n"
-"}\n"
-"#endif //B3_FLOAT4_H\n"
-"#ifndef B3_MAT3x3_H\n"
-"#define B3_MAT3x3_H\n"
-"#ifndef B3_QUAT_H\n"
-"#define B3_QUAT_H\n"
-"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#endif\n"
-"#endif\n"
-"#ifndef B3_FLOAT4_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#endif \n"
-"#endif //B3_FLOAT4_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-" typedef float4 b3Quat;\n"
-" #define b3QuatConstArg const b3Quat\n"
-" \n"
-" \n"
-"inline float4 b3FastNormalize4(float4 v)\n"
-"{\n"
-" v = (float4)(v.xyz,0.f);\n"
-" return fast_normalize(v);\n"
-"}\n"
-" \n"
-"inline b3Quat b3QuatMul(b3Quat a, b3Quat b);\n"
-"inline b3Quat b3QuatNormalized(b3QuatConstArg in);\n"
-"inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec);\n"
-"inline b3Quat b3QuatInvert(b3QuatConstArg q);\n"
-"inline b3Quat b3QuatInverse(b3QuatConstArg q);\n"
-"inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b)\n"
-"{\n"
-" b3Quat ans;\n"
-" ans = b3Cross3( a, b );\n"
-" ans += a.w*b+b.w*a;\n"
-"// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
-" ans.w = a.w*b.w - b3Dot3F4(a, b);\n"
-" return ans;\n"
-"}\n"
-"inline b3Quat b3QuatNormalized(b3QuatConstArg in)\n"
-"{\n"
-" b3Quat q;\n"
-" q=in;\n"
-" //return b3FastNormalize4(in);\n"
-" float len = native_sqrt(dot(q, q));\n"
-" if(len > 0.f)\n"
-" {\n"
-" q *= 1.f / len;\n"
-" }\n"
-" else\n"
-" {\n"
-" q.x = q.y = q.z = 0.f;\n"
-" q.w = 1.f;\n"
-" }\n"
-" return q;\n"
-"}\n"
-"inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
-"{\n"
-" b3Quat qInv = b3QuatInvert( q );\n"
-" float4 vcpy = vec;\n"
-" vcpy.w = 0.f;\n"
-" float4 out = b3QuatMul(b3QuatMul(q,vcpy),qInv);\n"
-" return out;\n"
-"}\n"
-"inline b3Quat b3QuatInverse(b3QuatConstArg q)\n"
-"{\n"
-" return (b3Quat)(-q.xyz, q.w);\n"
-"}\n"
-"inline b3Quat b3QuatInvert(b3QuatConstArg q)\n"
-"{\n"
-" return (b3Quat)(-q.xyz, q.w);\n"
-"}\n"
-"inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
-"{\n"
-" return b3QuatRotate( b3QuatInvert( q ), vec );\n"
-"}\n"
-"inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation)\n"
-"{\n"
-" return b3QuatRotate( orientation, point ) + (translation);\n"
-"}\n"
-" \n"
-"#endif \n"
-"#endif //B3_QUAT_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"typedef struct\n"
-"{\n"
-" b3Float4 m_row[3];\n"
-"}b3Mat3x3;\n"
-"#define b3Mat3x3ConstArg const b3Mat3x3\n"
-"#define b3GetRow(m,row) (m.m_row[row])\n"
-"inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat)\n"
-"{\n"
-" b3Float4 quat2 = (b3Float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);\n"
-" b3Mat3x3 out;\n"
-" out.m_row[0].x=1-2*quat2.y-2*quat2.z;\n"
-" out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;\n"
-" out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;\n"
-" out.m_row[0].w = 0.f;\n"
-" out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;\n"
-" out.m_row[1].y=1-2*quat2.x-2*quat2.z;\n"
-" out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;\n"
-" out.m_row[1].w = 0.f;\n"
-" out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;\n"
-" out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;\n"
-" out.m_row[2].z=1-2*quat2.x-2*quat2.y;\n"
-" out.m_row[2].w = 0.f;\n"
-" return out;\n"
-"}\n"
-"inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn)\n"
-"{\n"
-" b3Mat3x3 out;\n"
-" out.m_row[0] = fabs(matIn.m_row[0]);\n"
-" out.m_row[1] = fabs(matIn.m_row[1]);\n"
-" out.m_row[2] = fabs(matIn.m_row[2]);\n"
-" return out;\n"
-"}\n"
-"__inline\n"
-"b3Mat3x3 mtZero();\n"
-"__inline\n"
-"b3Mat3x3 mtIdentity();\n"
-"__inline\n"
-"b3Mat3x3 mtTranspose(b3Mat3x3 m);\n"
-"__inline\n"
-"b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);\n"
-"__inline\n"
-"b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);\n"
-"__inline\n"
-"b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);\n"
-"__inline\n"
-"b3Mat3x3 mtZero()\n"
-"{\n"
-" b3Mat3x3 m;\n"
-" m.m_row[0] = (b3Float4)(0.f);\n"
-" m.m_row[1] = (b3Float4)(0.f);\n"
-" m.m_row[2] = (b3Float4)(0.f);\n"
-" return m;\n"
-"}\n"
-"__inline\n"
-"b3Mat3x3 mtIdentity()\n"
-"{\n"
-" b3Mat3x3 m;\n"
-" m.m_row[0] = (b3Float4)(1,0,0,0);\n"
-" m.m_row[1] = (b3Float4)(0,1,0,0);\n"
-" m.m_row[2] = (b3Float4)(0,0,1,0);\n"
-" return m;\n"
-"}\n"
-"__inline\n"
-"b3Mat3x3 mtTranspose(b3Mat3x3 m)\n"
-"{\n"
-" b3Mat3x3 out;\n"
-" out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
-" out.m_row[1] = (b3Float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
-" out.m_row[2] = (b3Float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
-" return out;\n"
-"}\n"
-"__inline\n"
-"b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)\n"
-"{\n"
-" b3Mat3x3 transB;\n"
-" transB = mtTranspose( b );\n"
-" b3Mat3x3 ans;\n"
-" // why this doesn't run when 0ing in the for{}\n"
-" a.m_row[0].w = 0.f;\n"
-" a.m_row[1].w = 0.f;\n"
-" a.m_row[2].w = 0.f;\n"
-" for(int i=0; i<3; i++)\n"
-" {\n"
-"// a.m_row[i].w = 0.f;\n"
-" ans.m_row[i].x = b3Dot3F4(a.m_row[i],transB.m_row[0]);\n"
-" ans.m_row[i].y = b3Dot3F4(a.m_row[i],transB.m_row[1]);\n"
-" ans.m_row[i].z = b3Dot3F4(a.m_row[i],transB.m_row[2]);\n"
-" ans.m_row[i].w = 0.f;\n"
-" }\n"
-" return ans;\n"
-"}\n"
-"__inline\n"
-"b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)\n"
-"{\n"
-" b3Float4 ans;\n"
-" ans.x = b3Dot3F4( a.m_row[0], b );\n"
-" ans.y = b3Dot3F4( a.m_row[1], b );\n"
-" ans.z = b3Dot3F4( a.m_row[2], b );\n"
-" ans.w = 0.f;\n"
-" return ans;\n"
-"}\n"
-"__inline\n"
-"b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)\n"
-"{\n"
-" b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
-" b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
-" b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
-" b3Float4 ans;\n"
-" ans.x = b3Dot3F4( a, colx );\n"
-" ans.y = b3Dot3F4( a, coly );\n"
-" ans.z = b3Dot3F4( a, colz );\n"
-" return ans;\n"
-"}\n"
-"#endif\n"
-"#endif //B3_MAT3x3_H\n"
-"typedef struct b3Aabb b3Aabb_t;\n"
-"struct b3Aabb\n"
-"{\n"
-" union\n"
-" {\n"
-" float m_min[4];\n"
-" b3Float4 m_minVec;\n"
-" int m_minIndices[4];\n"
-" };\n"
-" union\n"
-" {\n"
-" float m_max[4];\n"
-" b3Float4 m_maxVec;\n"
-" int m_signedMaxIndices[4];\n"
-" };\n"
-"};\n"
-"inline void b3TransformAabb2(b3Float4ConstArg localAabbMin,b3Float4ConstArg localAabbMax, float margin,\n"
-" b3Float4ConstArg pos,\n"
-" b3QuatConstArg orn,\n"
-" b3Float4* aabbMinOut,b3Float4* aabbMaxOut)\n"
-"{\n"
-" b3Float4 localHalfExtents = 0.5f*(localAabbMax-localAabbMin);\n"
-" localHalfExtents+=b3MakeFloat4(margin,margin,margin,0.f);\n"
-" b3Float4 localCenter = 0.5f*(localAabbMax+localAabbMin);\n"
-" b3Mat3x3 m;\n"
-" m = b3QuatGetRotationMatrix(orn);\n"
-" b3Mat3x3 abs_b = b3AbsoluteMat3x3(m);\n"
-" b3Float4 center = b3TransformPoint(localCenter,pos,orn);\n"
-" \n"
-" b3Float4 extent = b3MakeFloat4(b3Dot3F4(localHalfExtents,b3GetRow(abs_b,0)),\n"
-" b3Dot3F4(localHalfExtents,b3GetRow(abs_b,1)),\n"
-" b3Dot3F4(localHalfExtents,b3GetRow(abs_b,2)),\n"
-" 0.f);\n"
-" *aabbMinOut = center-extent;\n"
-" *aabbMaxOut = center+extent;\n"
-"}\n"
-"/// conservative test for overlap between two aabbs\n"
-"inline bool b3TestAabbAgainstAabb(b3Float4ConstArg aabbMin1,b3Float4ConstArg aabbMax1,\n"
-" b3Float4ConstArg aabbMin2, b3Float4ConstArg aabbMax2)\n"
-"{\n"
-" bool overlap = true;\n"
-" overlap = (aabbMin1.x > aabbMax2.x || aabbMax1.x < aabbMin2.x) ? false : overlap;\n"
-" overlap = (aabbMin1.z > aabbMax2.z || aabbMax1.z < aabbMin2.z) ? false : overlap;\n"
-" overlap = (aabbMin1.y > aabbMax2.y || aabbMax1.y < aabbMin2.y) ? false : overlap;\n"
-" return overlap;\n"
-"}\n"
-"#endif //B3_AABB_H\n"
-"/*\n"
-"Bullet Continuous Collision Detection and Physics Library\n"
-"Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org\n"
-"This software is provided 'as-is', without any express or implied warranty.\n"
-"In no event will the authors be held liable for any damages arising from the use of this software.\n"
-"Permission is granted to anyone to use this software for any purpose,\n"
-"including commercial applications, and to alter it and redistribute it freely,\n"
-"subject to the following restrictions:\n"
-"1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
-"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
-"3. This notice may not be removed or altered from any source distribution.\n"
-"*/\n"
-"#ifndef B3_INT2_H\n"
-"#define B3_INT2_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#define b3UnsignedInt2 uint2\n"
-"#define b3Int2 int2\n"
-"#define b3MakeInt2 (int2)\n"
-"#endif //__cplusplus\n"
-"#endif\n"
-"typedef struct\n"
-"{\n"
-" float4 m_plane;\n"
-" int m_indexOffset;\n"
-" int m_numIndices;\n"
-"} btGpuFace;\n"
-"#define make_float4 (float4)\n"
-"__inline\n"
-"float4 cross3(float4 a, float4 b)\n"
-"{\n"
-" return cross(a,b);\n"
-" \n"
-"// float4 a1 = make_float4(a.xyz,0.f);\n"
-"// float4 b1 = make_float4(b.xyz,0.f);\n"
-"// return cross(a1,b1);\n"
-"//float4 c = make_float4(a.y*b.z - a.z*b.y,a.z*b.x - a.x*b.z,a.x*b.y - a.y*b.x,0.f);\n"
-" \n"
-" // float4 c = make_float4(a.y*b.z - a.z*b.y,1.f,a.x*b.y - a.y*b.x,0.f);\n"
-" \n"
-" //return c;\n"
-"}\n"
-"__inline\n"
-"float dot3F4(float4 a, float4 b)\n"
-"{\n"
-" float4 a1 = make_float4(a.xyz,0.f);\n"
-" float4 b1 = make_float4(b.xyz,0.f);\n"
-" return dot(a1, b1);\n"
-"}\n"
-"__inline\n"
-"float4 fastNormalize4(float4 v)\n"
-"{\n"
-" v = make_float4(v.xyz,0.f);\n"
-" return fast_normalize(v);\n"
-"}\n"
-"///////////////////////////////////////\n"
-"// Quaternion\n"
-"///////////////////////////////////////\n"
-"typedef float4 Quaternion;\n"
-"__inline\n"
-"Quaternion qtMul(Quaternion a, Quaternion b);\n"
-"__inline\n"
-"Quaternion qtNormalize(Quaternion in);\n"
-"__inline\n"
-"float4 qtRotate(Quaternion q, float4 vec);\n"
-"__inline\n"
-"Quaternion qtInvert(Quaternion q);\n"
-"__inline\n"
-"Quaternion qtMul(Quaternion a, Quaternion b)\n"
-"{\n"
-" Quaternion ans;\n"
-" ans = cross3( a, b );\n"
-" ans += a.w*b+b.w*a;\n"
-"// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
-" ans.w = a.w*b.w - dot3F4(a, b);\n"
-" return ans;\n"
-"}\n"
-"__inline\n"
-"Quaternion qtNormalize(Quaternion in)\n"
-"{\n"
-" return fastNormalize4(in);\n"
-"// in /= length( in );\n"
-"// return in;\n"
-"}\n"
-"__inline\n"
-"float4 qtRotate(Quaternion q, float4 vec)\n"
-"{\n"
-" Quaternion qInv = qtInvert( q );\n"
-" float4 vcpy = vec;\n"
-" vcpy.w = 0.f;\n"
-" float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
-" return out;\n"
-"}\n"
-"__inline\n"
-"Quaternion qtInvert(Quaternion q)\n"
-"{\n"
-" return (Quaternion)(-q.xyz, q.w);\n"
-"}\n"
-"__inline\n"
-"float4 qtInvRotate(const Quaternion q, float4 vec)\n"
-"{\n"
-" return qtRotate( qtInvert( q ), vec );\n"
-"}\n"
-"__inline\n"
-"float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)\n"
-"{\n"
-" return qtRotate( *orientation, *p ) + (*translation);\n"
-"}\n"
-"__inline\n"
-"float4 normalize3(const float4 a)\n"
-"{\n"
-" float4 n = make_float4(a.x, a.y, a.z, 0.f);\n"
-" return fastNormalize4( n );\n"
-"}\n"
-"inline void projectLocal(const ConvexPolyhedronCL* hull, const float4 pos, const float4 orn, \n"
-"const float4* dir, const float4* vertices, float* min, float* max)\n"
-"{\n"
-" min[0] = FLT_MAX;\n"
-" max[0] = -FLT_MAX;\n"
-" int numVerts = hull->m_numVertices;\n"
-" const float4 localDir = qtInvRotate(orn,*dir);\n"
-" float offset = dot(pos,*dir);\n"
-" for(int i=0;i<numVerts;i++)\n"
-" {\n"
-" float dp = dot(vertices[hull->m_vertexOffset+i],localDir);\n"
-" if(dp < min[0]) \n"
-" min[0] = dp;\n"
-" if(dp > max[0]) \n"
-" max[0] = dp;\n"
-" }\n"
-" if(min[0]>max[0])\n"
-" {\n"
-" float tmp = min[0];\n"
-" min[0] = max[0];\n"
-" max[0] = tmp;\n"
-" }\n"
-" min[0] += offset;\n"
-" max[0] += offset;\n"
-"}\n"
-"inline void project(__global const ConvexPolyhedronCL* hull, const float4 pos, const float4 orn, \n"
-"const float4* dir, __global const float4* vertices, float* min, float* max)\n"
-"{\n"
-" min[0] = FLT_MAX;\n"
-" max[0] = -FLT_MAX;\n"
-" int numVerts = hull->m_numVertices;\n"
-" const float4 localDir = qtInvRotate(orn,*dir);\n"
-" float offset = dot(pos,*dir);\n"
-" for(int i=0;i<numVerts;i++)\n"
-" {\n"
-" float dp = dot(vertices[hull->m_vertexOffset+i],localDir);\n"
-" if(dp < min[0]) \n"
-" min[0] = dp;\n"
-" if(dp > max[0]) \n"
-" max[0] = dp;\n"
-" }\n"
-" if(min[0]>max[0])\n"
-" {\n"
-" float tmp = min[0];\n"
-" min[0] = max[0];\n"
-" max[0] = tmp;\n"
-" }\n"
-" min[0] += offset;\n"
-" max[0] += offset;\n"
-"}\n"
-"inline bool TestSepAxisLocalA(const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
-" const float4 posA,const float4 ornA,\n"
-" const float4 posB,const float4 ornB,\n"
-" float4* sep_axis, const float4* verticesA, __global const float4* verticesB,float* depth)\n"
-"{\n"
-" float Min0,Max0;\n"
-" float Min1,Max1;\n"
-" projectLocal(hullA,posA,ornA,sep_axis,verticesA, &Min0, &Max0);\n"
-" project(hullB,posB,ornB, sep_axis,verticesB, &Min1, &Max1);\n"
-" if(Max0<Min1 || Max1<Min0)\n"
-" return false;\n"
-" float d0 = Max0 - Min1;\n"
-" float d1 = Max1 - Min0;\n"
-" *depth = d0<d1 ? d0:d1;\n"
-" return true;\n"
-"}\n"
-"inline bool IsAlmostZero(const float4 v)\n"
-"{\n"
-" if(fabs(v.x)>1e-6f || fabs(v.y)>1e-6f || fabs(v.z)>1e-6f)\n"
-" return false;\n"
-" return true;\n"
-"}\n"
-"bool findSeparatingAxisLocalA( const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
-" const float4 posA1,\n"
-" const float4 ornA,\n"
-" const float4 posB1,\n"
-" const float4 ornB,\n"
-" const float4 DeltaC2,\n"
-" \n"
-" const float4* verticesA, \n"
-" const float4* uniqueEdgesA, \n"
-" const btGpuFace* facesA,\n"
-" const int* indicesA,\n"
-" __global const float4* verticesB, \n"
-" __global const float4* uniqueEdgesB, \n"
-" __global const btGpuFace* facesB,\n"
-" __global const int* indicesB,\n"
-" float4* sep,\n"
-" float* dmin)\n"
-"{\n"
-" \n"
-" float4 posA = posA1;\n"
-" posA.w = 0.f;\n"
-" float4 posB = posB1;\n"
-" posB.w = 0.f;\n"
-" int curPlaneTests=0;\n"
-" {\n"
-" int numFacesA = hullA->m_numFaces;\n"
-" // Test normals from hullA\n"
-" for(int i=0;i<numFacesA;i++)\n"
-" {\n"
-" const float4 normal = facesA[hullA->m_faceOffset+i].m_plane;\n"
-" float4 faceANormalWS = qtRotate(ornA,normal);\n"
-" if (dot3F4(DeltaC2,faceANormalWS)<0)\n"
-" faceANormalWS*=-1.f;\n"
-" curPlaneTests++;\n"
-" float d;\n"
-" if(!TestSepAxisLocalA( hullA, hullB, posA,ornA,posB,ornB,&faceANormalWS, verticesA, verticesB,&d))\n"
-" return false;\n"
-" if(d<*dmin)\n"
-" {\n"
-" *dmin = d;\n"
-" *sep = faceANormalWS;\n"
-" }\n"
-" }\n"
-" }\n"
-" if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
-" {\n"
-" *sep = -(*sep);\n"
-" }\n"
-" return true;\n"
-"}\n"
-"bool findSeparatingAxisLocalB( __global const ConvexPolyhedronCL* hullA, const ConvexPolyhedronCL* hullB, \n"
-" const float4 posA1,\n"
-" const float4 ornA,\n"
-" const float4 posB1,\n"
-" const float4 ornB,\n"
-" const float4 DeltaC2,\n"
-" __global const float4* verticesA, \n"
-" __global const float4* uniqueEdgesA, \n"
-" __global const btGpuFace* facesA,\n"
-" __global const int* indicesA,\n"
-" const float4* verticesB,\n"
-" const float4* uniqueEdgesB, \n"
-" const btGpuFace* facesB,\n"
-" const int* indicesB,\n"
-" float4* sep,\n"
-" float* dmin)\n"
-"{\n"
-" float4 posA = posA1;\n"
-" posA.w = 0.f;\n"
-" float4 posB = posB1;\n"
-" posB.w = 0.f;\n"
-" int curPlaneTests=0;\n"
-" {\n"
-" int numFacesA = hullA->m_numFaces;\n"
-" // Test normals from hullA\n"
-" for(int i=0;i<numFacesA;i++)\n"
-" {\n"
-" const float4 normal = facesA[hullA->m_faceOffset+i].m_plane;\n"
-" float4 faceANormalWS = qtRotate(ornA,normal);\n"
-" if (dot3F4(DeltaC2,faceANormalWS)<0)\n"
-" faceANormalWS *= -1.f;\n"
-" curPlaneTests++;\n"
-" float d;\n"
-" if(!TestSepAxisLocalA( hullB, hullA, posB,ornB,posA,ornA, &faceANormalWS, verticesB,verticesA, &d))\n"
-" return false;\n"
-" if(d<*dmin)\n"
-" {\n"
-" *dmin = d;\n"
-" *sep = faceANormalWS;\n"
-" }\n"
-" }\n"
-" }\n"
-" if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
-" {\n"
-" *sep = -(*sep);\n"
-" }\n"
-" return true;\n"
-"}\n"
-"bool findSeparatingAxisEdgeEdgeLocalA( const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
-" const float4 posA1,\n"
-" const float4 ornA,\n"
-" const float4 posB1,\n"
-" const float4 ornB,\n"
-" const float4 DeltaC2,\n"
-" const float4* verticesA, \n"
-" const float4* uniqueEdgesA, \n"
-" const btGpuFace* facesA,\n"
-" const int* indicesA,\n"
-" __global const float4* verticesB, \n"
-" __global const float4* uniqueEdgesB, \n"
-" __global const btGpuFace* facesB,\n"
-" __global const int* indicesB,\n"
-" float4* sep,\n"
-" float* dmin)\n"
-"{\n"
-" float4 posA = posA1;\n"
-" posA.w = 0.f;\n"
-" float4 posB = posB1;\n"
-" posB.w = 0.f;\n"
-" int curPlaneTests=0;\n"
-" int curEdgeEdge = 0;\n"
-" // Test edges\n"
-" for(int e0=0;e0<hullA->m_numUniqueEdges;e0++)\n"
-" {\n"
-" const float4 edge0 = uniqueEdgesA[hullA->m_uniqueEdgesOffset+e0];\n"
-" float4 edge0World = qtRotate(ornA,edge0);\n"
-" for(int e1=0;e1<hullB->m_numUniqueEdges;e1++)\n"
-" {\n"
-" const float4 edge1 = uniqueEdgesB[hullB->m_uniqueEdgesOffset+e1];\n"
-" float4 edge1World = qtRotate(ornB,edge1);\n"
-" float4 crossje = cross3(edge0World,edge1World);\n"
-" curEdgeEdge++;\n"
-" if(!IsAlmostZero(crossje))\n"
-" {\n"
-" crossje = normalize3(crossje);\n"
-" if (dot3F4(DeltaC2,crossje)<0)\n"
-" crossje *= -1.f;\n"
-" float dist;\n"
-" bool result = true;\n"
-" {\n"
-" float Min0,Max0;\n"
-" float Min1,Max1;\n"
-" projectLocal(hullA,posA,ornA,&crossje,verticesA, &Min0, &Max0);\n"
-" project(hullB,posB,ornB,&crossje,verticesB, &Min1, &Max1);\n"
-" \n"
-" if(Max0<Min1 || Max1<Min0)\n"
-" result = false;\n"
-" \n"
-" float d0 = Max0 - Min1;\n"
-" float d1 = Max1 - Min0;\n"
-" dist = d0<d1 ? d0:d1;\n"
-" result = true;\n"
-" }\n"
-" \n"
-" if(dist<*dmin)\n"
-" {\n"
-" *dmin = dist;\n"
-" *sep = crossje;\n"
-" }\n"
-" }\n"
-" }\n"
-" }\n"
-" \n"
-" if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
-" {\n"
-" *sep = -(*sep);\n"
-" }\n"
-" return true;\n"
-"}\n"
-"inline bool TestSepAxis(__global const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
-" const float4 posA,const float4 ornA,\n"
-" const float4 posB,const float4 ornB,\n"
-" float4* sep_axis, __global const float4* vertices,float* depth)\n"
-"{\n"
-" float Min0,Max0;\n"
-" float Min1,Max1;\n"
-" project(hullA,posA,ornA,sep_axis,vertices, &Min0, &Max0);\n"
-" project(hullB,posB,ornB, sep_axis,vertices, &Min1, &Max1);\n"
-" if(Max0<Min1 || Max1<Min0)\n"
-" return false;\n"
-" float d0 = Max0 - Min1;\n"
-" float d1 = Max1 - Min0;\n"
-" *depth = d0<d1 ? d0:d1;\n"
-" return true;\n"
-"}\n"
-"bool findSeparatingAxis( __global const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
-" const float4 posA1,\n"
-" const float4 ornA,\n"
-" const float4 posB1,\n"
-" const float4 ornB,\n"
-" const float4 DeltaC2,\n"
-" __global const float4* vertices, \n"
-" __global const float4* uniqueEdges, \n"
-" __global const btGpuFace* faces,\n"
-" __global const int* indices,\n"
-" float4* sep,\n"
-" float* dmin)\n"
-"{\n"
-" \n"
-" float4 posA = posA1;\n"
-" posA.w = 0.f;\n"
-" float4 posB = posB1;\n"
-" posB.w = 0.f;\n"
-" \n"
-" int curPlaneTests=0;\n"
-" {\n"
-" int numFacesA = hullA->m_numFaces;\n"
-" // Test normals from hullA\n"
-" for(int i=0;i<numFacesA;i++)\n"
-" {\n"
-" const float4 normal = faces[hullA->m_faceOffset+i].m_plane;\n"
-" float4 faceANormalWS = qtRotate(ornA,normal);\n"
-" \n"
-" if (dot3F4(DeltaC2,faceANormalWS)<0)\n"
-" faceANormalWS*=-1.f;\n"
-" \n"
-" curPlaneTests++;\n"
-" \n"
-" float d;\n"
-" if(!TestSepAxis( hullA, hullB, posA,ornA,posB,ornB,&faceANormalWS, vertices,&d))\n"
-" return false;\n"
-" \n"
-" if(d<*dmin)\n"
-" {\n"
-" *dmin = d;\n"
-" *sep = faceANormalWS;\n"
-" }\n"
-" }\n"
-" }\n"
-" if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
-" {\n"
-" *sep = -(*sep);\n"
-" }\n"
-" \n"
-" return true;\n"
-"}\n"
-"bool findSeparatingAxisUnitSphere( __global const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
-" const float4 posA1,\n"
-" const float4 ornA,\n"
-" const float4 posB1,\n"
-" const float4 ornB,\n"
-" const float4 DeltaC2,\n"
-" __global const float4* vertices,\n"
-" __global const float4* unitSphereDirections,\n"
-" int numUnitSphereDirections,\n"
-" float4* sep,\n"
-" float* dmin)\n"
-"{\n"
-" \n"
-" float4 posA = posA1;\n"
-" posA.w = 0.f;\n"
-" float4 posB = posB1;\n"
-" posB.w = 0.f;\n"
-" int curPlaneTests=0;\n"
-" int curEdgeEdge = 0;\n"
-" // Test unit sphere directions\n"
-" for (int i=0;i<numUnitSphereDirections;i++)\n"
-" {\n"
-" float4 crossje;\n"
-" crossje = unitSphereDirections[i]; \n"
-" if (dot3F4(DeltaC2,crossje)>0)\n"
-" crossje *= -1.f;\n"
-" {\n"
-" float dist;\n"
-" bool result = true;\n"
-" float Min0,Max0;\n"
-" float Min1,Max1;\n"
-" project(hullA,posA,ornA,&crossje,vertices, &Min0, &Max0);\n"
-" project(hullB,posB,ornB,&crossje,vertices, &Min1, &Max1);\n"
-" \n"
-" if(Max0<Min1 || Max1<Min0)\n"
-" return false;\n"
-" \n"
-" float d0 = Max0 - Min1;\n"
-" float d1 = Max1 - Min0;\n"
-" dist = d0<d1 ? d0:d1;\n"
-" result = true;\n"
-" \n"
-" if(dist<*dmin)\n"
-" {\n"
-" *dmin = dist;\n"
-" *sep = crossje;\n"
-" }\n"
-" }\n"
-" }\n"
-" \n"
-" if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
-" {\n"
-" *sep = -(*sep);\n"
-" }\n"
-" return true;\n"
-"}\n"
-"bool findSeparatingAxisEdgeEdge( __global const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
-" const float4 posA1,\n"
-" const float4 ornA,\n"
-" const float4 posB1,\n"
-" const float4 ornB,\n"
-" const float4 DeltaC2,\n"
-" __global const float4* vertices, \n"
-" __global const float4* uniqueEdges, \n"
-" __global const btGpuFace* faces,\n"
-" __global const int* indices,\n"
-" float4* sep,\n"
-" float* dmin)\n"
-"{\n"
-" \n"
-" float4 posA = posA1;\n"
-" posA.w = 0.f;\n"
-" float4 posB = posB1;\n"
-" posB.w = 0.f;\n"
-" int curPlaneTests=0;\n"
-" int curEdgeEdge = 0;\n"
-" // Test edges\n"
-" for(int e0=0;e0<hullA->m_numUniqueEdges;e0++)\n"
-" {\n"
-" const float4 edge0 = uniqueEdges[hullA->m_uniqueEdgesOffset+e0];\n"
-" float4 edge0World = qtRotate(ornA,edge0);\n"
-" for(int e1=0;e1<hullB->m_numUniqueEdges;e1++)\n"
-" {\n"
-" const float4 edge1 = uniqueEdges[hullB->m_uniqueEdgesOffset+e1];\n"
-" float4 edge1World = qtRotate(ornB,edge1);\n"
-" float4 crossje = cross3(edge0World,edge1World);\n"
-" curEdgeEdge++;\n"
-" if(!IsAlmostZero(crossje))\n"
-" {\n"
-" crossje = normalize3(crossje);\n"
-" if (dot3F4(DeltaC2,crossje)<0)\n"
-" crossje*=-1.f;\n"
-" \n"
-" float dist;\n"
-" bool result = true;\n"
-" {\n"
-" float Min0,Max0;\n"
-" float Min1,Max1;\n"
-" project(hullA,posA,ornA,&crossje,vertices, &Min0, &Max0);\n"
-" project(hullB,posB,ornB,&crossje,vertices, &Min1, &Max1);\n"
-" \n"
-" if(Max0<Min1 || Max1<Min0)\n"
-" return false;\n"
-" \n"
-" float d0 = Max0 - Min1;\n"
-" float d1 = Max1 - Min0;\n"
-" dist = d0<d1 ? d0:d1;\n"
-" result = true;\n"
-" }\n"
-" \n"
-" if(dist<*dmin)\n"
-" {\n"
-" *dmin = dist;\n"
-" *sep = crossje;\n"
-" }\n"
-" }\n"
-" }\n"
-" }\n"
-" \n"
-" if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
-" {\n"
-" *sep = -(*sep);\n"
-" }\n"
-" return true;\n"
-"}\n"
-"// work-in-progress\n"
-"__kernel void processCompoundPairsKernel( __global const int4* gpuCompoundPairs,\n"
-" __global const BodyData* rigidBodies, \n"
-" __global const btCollidableGpu* collidables,\n"
-" __global const ConvexPolyhedronCL* convexShapes, \n"
-" __global const float4* vertices,\n"
-" __global const float4* uniqueEdges,\n"
-" __global const btGpuFace* faces,\n"
-" __global const int* indices,\n"
-" __global btAabbCL* aabbs,\n"
-" __global const btGpuChildShape* gpuChildShapes,\n"
-" __global volatile float4* gpuCompoundSepNormalsOut,\n"
-" __global volatile int* gpuHasCompoundSepNormalsOut,\n"
-" int numCompoundPairs\n"
-" )\n"
-"{\n"
-" int i = get_global_id(0);\n"
-" if (i<numCompoundPairs)\n"
-" {\n"
-" int bodyIndexA = gpuCompoundPairs[i].x;\n"
-" int bodyIndexB = gpuCompoundPairs[i].y;\n"
-" int childShapeIndexA = gpuCompoundPairs[i].z;\n"
-" int childShapeIndexB = gpuCompoundPairs[i].w;\n"
-" \n"
-" int collidableIndexA = -1;\n"
-" int collidableIndexB = -1;\n"
-" \n"
-" float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
-" float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
-" \n"
-" float4 ornB = rigidBodies[bodyIndexB].m_quat;\n"
-" float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
-" \n"
-" if (childShapeIndexA >= 0)\n"
-" {\n"
-" collidableIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;\n"
-" float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;\n"
-" float4 childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;\n"
-" float4 newPosA = qtRotate(ornA,childPosA)+posA;\n"
-" float4 newOrnA = qtMul(ornA,childOrnA);\n"
-" posA = newPosA;\n"
-" ornA = newOrnA;\n"
-" } else\n"
-" {\n"
-" collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
-" }\n"
-" \n"
-" if (childShapeIndexB>=0)\n"
-" {\n"
-" collidableIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
-" float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
-" float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
-" float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
-" float4 newOrnB = qtMul(ornB,childOrnB);\n"
-" posB = newPosB;\n"
-" ornB = newOrnB;\n"
-" } else\n"
-" {\n"
-" collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx; \n"
-" }\n"
-" \n"
-" gpuHasCompoundSepNormalsOut[i] = 0;\n"
-" \n"
-" int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
-" int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
-" \n"
-" int shapeTypeA = collidables[collidableIndexA].m_shapeType;\n"
-" int shapeTypeB = collidables[collidableIndexB].m_shapeType;\n"
-" \n"
-" if ((shapeTypeA != SHAPE_CONVEX_HULL) || (shapeTypeB != SHAPE_CONVEX_HULL))\n"
-" {\n"
-" return;\n"
-" }\n"
-" int hasSeparatingAxis = 5;\n"
-" \n"
-" int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
-" float dmin = FLT_MAX;\n"
-" posA.w = 0.f;\n"
-" posB.w = 0.f;\n"
-" float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
-" float4 c0 = transform(&c0local, &posA, &ornA);\n"
-" float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
-" float4 c1 = transform(&c1local,&posB,&ornB);\n"
-" const float4 DeltaC2 = c0 - c1;\n"
-" float4 sepNormal = make_float4(1,0,0,0);\n"
-" bool sepA = findSeparatingAxis( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,posB,ornB,DeltaC2,vertices,uniqueEdges,faces,indices,&sepNormal,&dmin);\n"
-" hasSeparatingAxis = 4;\n"
-" if (!sepA)\n"
-" {\n"
-" hasSeparatingAxis = 0;\n"
-" } else\n"
-" {\n"
-" bool sepB = findSeparatingAxis( &convexShapes[shapeIndexB],&convexShapes[shapeIndexA],posB,ornB,posA,ornA,DeltaC2,vertices,uniqueEdges,faces,indices,&sepNormal,&dmin);\n"
-" if (!sepB)\n"
-" {\n"
-" hasSeparatingAxis = 0;\n"
-" } else//(!sepB)\n"
-" {\n"
-" bool sepEE = findSeparatingAxisEdgeEdge( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,posB,ornB,DeltaC2,vertices,uniqueEdges,faces,indices,&sepNormal,&dmin);\n"
-" if (sepEE)\n"
-" {\n"
-" gpuCompoundSepNormalsOut[i] = sepNormal;//fastNormalize4(sepNormal);\n"
-" gpuHasCompoundSepNormalsOut[i] = 1;\n"
-" }//sepEE\n"
-" }//(!sepB)\n"
-" }//(!sepA)\n"
-" \n"
-" \n"
-" }\n"
-" \n"
-"}\n"
-"inline b3Float4 MyUnQuantize(const unsigned short* vecIn, b3Float4 quantization, b3Float4 bvhAabbMin)\n"
-"{\n"
-" b3Float4 vecOut;\n"
-" vecOut = b3MakeFloat4(\n"
-" (float)(vecIn[0]) / (quantization.x),\n"
-" (float)(vecIn[1]) / (quantization.y),\n"
-" (float)(vecIn[2]) / (quantization.z),\n"
-" 0.f);\n"
-" vecOut += bvhAabbMin;\n"
-" return vecOut;\n"
-"}\n"
-"inline b3Float4 MyUnQuantizeGlobal(__global const unsigned short* vecIn, b3Float4 quantization, b3Float4 bvhAabbMin)\n"
-"{\n"
-" b3Float4 vecOut;\n"
-" vecOut = b3MakeFloat4(\n"
-" (float)(vecIn[0]) / (quantization.x),\n"
-" (float)(vecIn[1]) / (quantization.y),\n"
-" (float)(vecIn[2]) / (quantization.z),\n"
-" 0.f);\n"
-" vecOut += bvhAabbMin;\n"
-" return vecOut;\n"
-"}\n"
-"// work-in-progress\n"
-"__kernel void findCompoundPairsKernel( __global const int4* pairs, \n"
-" __global const BodyData* rigidBodies, \n"
-" __global const btCollidableGpu* collidables,\n"
-" __global const ConvexPolyhedronCL* convexShapes, \n"
-" __global const float4* vertices,\n"
-" __global const float4* uniqueEdges,\n"
-" __global const btGpuFace* faces,\n"
-" __global const int* indices,\n"
-" __global b3Aabb_t* aabbLocalSpace,\n"
-" __global const btGpuChildShape* gpuChildShapes,\n"
-" __global volatile int4* gpuCompoundPairsOut,\n"
-" __global volatile int* numCompoundPairsOut,\n"
-" __global const b3BvhSubtreeInfo* subtrees,\n"
-" __global const b3QuantizedBvhNode* quantizedNodes,\n"
-" __global const b3BvhInfo* bvhInfos,\n"
-" int numPairs,\n"
-" int maxNumCompoundPairsCapacity\n"
-" )\n"
-"{\n"
-" int i = get_global_id(0);\n"
-" if (i<numPairs)\n"
-" {\n"
-" int bodyIndexA = pairs[i].x;\n"
-" int bodyIndexB = pairs[i].y;\n"
-" int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
-" int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
-" int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
-" int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
-" //once the broadphase avoids static-static pairs, we can remove this test\n"
-" if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))\n"
-" {\n"
-" return;\n"
-" }\n"
-" if ((collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS) &&(collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))\n"
-" {\n"
-" int bvhA = collidables[collidableIndexA].m_compoundBvhIndex;\n"
-" int bvhB = collidables[collidableIndexB].m_compoundBvhIndex;\n"
-" int numSubTreesA = bvhInfos[bvhA].m_numSubTrees;\n"
-" int subTreesOffsetA = bvhInfos[bvhA].m_subTreeOffset;\n"
-" int subTreesOffsetB = bvhInfos[bvhB].m_subTreeOffset;\n"
-" int numSubTreesB = bvhInfos[bvhB].m_numSubTrees;\n"
-" \n"
-" float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
-" b3Quat ornA = rigidBodies[bodyIndexA].m_quat;\n"
-" b3Quat ornB = rigidBodies[bodyIndexB].m_quat;\n"
-" float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
-" \n"
-" for (int p=0;p<numSubTreesA;p++)\n"
-" {\n"
-" b3BvhSubtreeInfo subtreeA = subtrees[subTreesOffsetA+p];\n"
-" //bvhInfos[bvhA].m_quantization\n"
-" b3Float4 treeAminLocal = MyUnQuantize(subtreeA.m_quantizedAabbMin,bvhInfos[bvhA].m_quantization,bvhInfos[bvhA].m_aabbMin);\n"
-" b3Float4 treeAmaxLocal = MyUnQuantize(subtreeA.m_quantizedAabbMax,bvhInfos[bvhA].m_quantization,bvhInfos[bvhA].m_aabbMin);\n"
-" b3Float4 aabbAMinOut,aabbAMaxOut;\n"
-" float margin=0.f;\n"
-" b3TransformAabb2(treeAminLocal,treeAmaxLocal, margin,posA,ornA,&aabbAMinOut,&aabbAMaxOut);\n"
-" \n"
-" for (int q=0;q<numSubTreesB;q++)\n"
-" {\n"
-" b3BvhSubtreeInfo subtreeB = subtrees[subTreesOffsetB+q];\n"
-" b3Float4 treeBminLocal = MyUnQuantize(subtreeB.m_quantizedAabbMin,bvhInfos[bvhB].m_quantization,bvhInfos[bvhB].m_aabbMin);\n"
-" b3Float4 treeBmaxLocal = MyUnQuantize(subtreeB.m_quantizedAabbMax,bvhInfos[bvhB].m_quantization,bvhInfos[bvhB].m_aabbMin);\n"
-" b3Float4 aabbBMinOut,aabbBMaxOut;\n"
-" float margin=0.f;\n"
-" b3TransformAabb2(treeBminLocal,treeBmaxLocal, margin,posB,ornB,&aabbBMinOut,&aabbBMaxOut);\n"
-" \n"
-" \n"
-" bool aabbOverlap = b3TestAabbAgainstAabb(aabbAMinOut,aabbAMaxOut,aabbBMinOut,aabbBMaxOut);\n"
-" if (aabbOverlap)\n"
-" {\n"
-" \n"
-" int startNodeIndexA = subtreeA.m_rootNodeIndex+bvhInfos[bvhA].m_nodeOffset;\n"
-" int endNodeIndexA = startNodeIndexA+subtreeA.m_subtreeSize;\n"
-" int startNodeIndexB = subtreeB.m_rootNodeIndex+bvhInfos[bvhB].m_nodeOffset;\n"
-" int endNodeIndexB = startNodeIndexB+subtreeB.m_subtreeSize;\n"
-" b3Int2 nodeStack[B3_MAX_STACK_DEPTH];\n"
-" b3Int2 node0;\n"
-" node0.x = startNodeIndexA;\n"
-" node0.y = startNodeIndexB;\n"
-" int maxStackDepth = B3_MAX_STACK_DEPTH;\n"
-" int depth=0;\n"
-" nodeStack[depth++]=node0;\n"
-" do\n"
-" {\n"
-" b3Int2 node = nodeStack[--depth];\n"
-" b3Float4 aMinLocal = MyUnQuantizeGlobal(quantizedNodes[node.x].m_quantizedAabbMin,bvhInfos[bvhA].m_quantization,bvhInfos[bvhA].m_aabbMin);\n"
-" b3Float4 aMaxLocal = MyUnQuantizeGlobal(quantizedNodes[node.x].m_quantizedAabbMax,bvhInfos[bvhA].m_quantization,bvhInfos[bvhA].m_aabbMin);\n"
-" b3Float4 bMinLocal = MyUnQuantizeGlobal(quantizedNodes[node.y].m_quantizedAabbMin,bvhInfos[bvhB].m_quantization,bvhInfos[bvhB].m_aabbMin);\n"
-" b3Float4 bMaxLocal = MyUnQuantizeGlobal(quantizedNodes[node.y].m_quantizedAabbMax,bvhInfos[bvhB].m_quantization,bvhInfos[bvhB].m_aabbMin);\n"
-" float margin=0.f;\n"
-" b3Float4 aabbAMinOut,aabbAMaxOut;\n"
-" b3TransformAabb2(aMinLocal,aMaxLocal, margin,posA,ornA,&aabbAMinOut,&aabbAMaxOut);\n"
-" b3Float4 aabbBMinOut,aabbBMaxOut;\n"
-" b3TransformAabb2(bMinLocal,bMaxLocal, margin,posB,ornB,&aabbBMinOut,&aabbBMaxOut);\n"
-" \n"
-" bool nodeOverlap = b3TestAabbAgainstAabb(aabbAMinOut,aabbAMaxOut,aabbBMinOut,aabbBMaxOut);\n"
-" if (nodeOverlap)\n"
-" {\n"
-" bool isLeafA = isLeafNodeGlobal(&quantizedNodes[node.x]);\n"
-" bool isLeafB = isLeafNodeGlobal(&quantizedNodes[node.y]);\n"
-" bool isInternalA = !isLeafA;\n"
-" bool isInternalB = !isLeafB;\n"
-" //fail, even though it might hit two leaf nodes\n"
-" if (depth+4>maxStackDepth && !(isLeafA && isLeafB))\n"
-" {\n"
-" //printf(\"Error: traversal exceeded maxStackDepth\");\n"
-" continue;\n"
-" }\n"
-" if(isInternalA)\n"
-" {\n"
-" int nodeAleftChild = node.x+1;\n"
-" bool isNodeALeftChildLeaf = isLeafNodeGlobal(&quantizedNodes[node.x+1]);\n"
-" int nodeArightChild = isNodeALeftChildLeaf? node.x+2 : node.x+1 + getEscapeIndexGlobal(&quantizedNodes[node.x+1]);\n"
-" if(isInternalB)\n"
-" { \n"
-" int nodeBleftChild = node.y+1;\n"
-" bool isNodeBLeftChildLeaf = isLeafNodeGlobal(&quantizedNodes[node.y+1]);\n"
-" int nodeBrightChild = isNodeBLeftChildLeaf? node.y+2 : node.y+1 + getEscapeIndexGlobal(&quantizedNodes[node.y+1]);\n"
-" nodeStack[depth++] = b3MakeInt2(nodeAleftChild, nodeBleftChild);\n"
-" nodeStack[depth++] = b3MakeInt2(nodeArightChild, nodeBleftChild);\n"
-" nodeStack[depth++] = b3MakeInt2(nodeAleftChild, nodeBrightChild);\n"
-" nodeStack[depth++] = b3MakeInt2(nodeArightChild, nodeBrightChild);\n"
-" }\n"
-" else\n"
-" {\n"
-" nodeStack[depth++] = b3MakeInt2(nodeAleftChild,node.y);\n"
-" nodeStack[depth++] = b3MakeInt2(nodeArightChild,node.y);\n"
-" }\n"
-" }\n"
-" else\n"
-" {\n"
-" if(isInternalB)\n"
-" {\n"
-" int nodeBleftChild = node.y+1;\n"
-" bool isNodeBLeftChildLeaf = isLeafNodeGlobal(&quantizedNodes[node.y+1]);\n"
-" int nodeBrightChild = isNodeBLeftChildLeaf? node.y+2 : node.y+1 + getEscapeIndexGlobal(&quantizedNodes[node.y+1]);\n"
-" nodeStack[depth++] = b3MakeInt2(node.x,nodeBleftChild);\n"
-" nodeStack[depth++] = b3MakeInt2(node.x,nodeBrightChild);\n"
-" }\n"
-" else\n"
-" {\n"
-" int compoundPairIdx = atomic_inc(numCompoundPairsOut);\n"
-" if (compoundPairIdx<maxNumCompoundPairsCapacity)\n"
-" {\n"
-" int childShapeIndexA = getTriangleIndexGlobal(&quantizedNodes[node.x]);\n"
-" int childShapeIndexB = getTriangleIndexGlobal(&quantizedNodes[node.y]);\n"
-" gpuCompoundPairsOut[compoundPairIdx] = (int4)(bodyIndexA,bodyIndexB,childShapeIndexA,childShapeIndexB);\n"
-" }\n"
-" }\n"
-" }\n"
-" }\n"
-" } while (depth);\n"
-" }\n"
-" }\n"
-" }\n"
-" \n"
-" return;\n"
-" }\n"
-" if ((collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS) ||(collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))\n"
-" {\n"
-" if (collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS) \n"
-" {\n"
-" int numChildrenA = collidables[collidableIndexA].m_numChildShapes;\n"
-" for (int c=0;c<numChildrenA;c++)\n"
-" {\n"
-" int childShapeIndexA = collidables[collidableIndexA].m_shapeIndex+c;\n"
-" int childColIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;\n"
-" float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
-" float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
-" float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;\n"
-" float4 childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;\n"
-" float4 newPosA = qtRotate(ornA,childPosA)+posA;\n"
-" float4 newOrnA = qtMul(ornA,childOrnA);\n"
-" int shapeIndexA = collidables[childColIndexA].m_shapeIndex;\n"
-" b3Aabb_t aabbAlocal = aabbLocalSpace[shapeIndexA];\n"
-" float margin = 0.f;\n"
-" \n"
-" b3Float4 aabbAMinWS;\n"
-" b3Float4 aabbAMaxWS;\n"
-" \n"
-" b3TransformAabb2(aabbAlocal.m_minVec,aabbAlocal.m_maxVec,margin,\n"
-" newPosA,\n"
-" newOrnA,\n"
-" &aabbAMinWS,&aabbAMaxWS);\n"
-" \n"
-" \n"
-" if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
-" {\n"
-" int numChildrenB = collidables[collidableIndexB].m_numChildShapes;\n"
-" for (int b=0;b<numChildrenB;b++)\n"
-" {\n"
-" int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex+b;\n"
-" int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
-" float4 ornB = rigidBodies[bodyIndexB].m_quat;\n"
-" float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
-" float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
-" float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
-" float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
-" float4 newOrnB = qtMul(ornB,childOrnB);\n"
-" int shapeIndexB = collidables[childColIndexB].m_shapeIndex;\n"
-" b3Aabb_t aabbBlocal = aabbLocalSpace[shapeIndexB];\n"
-" \n"
-" b3Float4 aabbBMinWS;\n"
-" b3Float4 aabbBMaxWS;\n"
-" \n"
-" b3TransformAabb2(aabbBlocal.m_minVec,aabbBlocal.m_maxVec,margin,\n"
-" newPosB,\n"
-" newOrnB,\n"
-" &aabbBMinWS,&aabbBMaxWS);\n"
-" \n"
-" \n"
-" \n"
-" bool aabbOverlap = b3TestAabbAgainstAabb(aabbAMinWS,aabbAMaxWS,aabbBMinWS,aabbBMaxWS);\n"
-" if (aabbOverlap)\n"
-" {\n"
-" int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
-" float dmin = FLT_MAX;\n"
-" float4 posA = newPosA;\n"
-" posA.w = 0.f;\n"
-" float4 posB = newPosB;\n"
-" posB.w = 0.f;\n"
-" float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
-" float4 ornA = newOrnA;\n"
-" float4 c0 = transform(&c0local, &posA, &ornA);\n"
-" float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
-" float4 ornB =newOrnB;\n"
-" float4 c1 = transform(&c1local,&posB,&ornB);\n"
-" const float4 DeltaC2 = c0 - c1;\n"
-" {//\n"
-" int compoundPairIdx = atomic_inc(numCompoundPairsOut);\n"
-" if (compoundPairIdx<maxNumCompoundPairsCapacity)\n"
-" {\n"
-" gpuCompoundPairsOut[compoundPairIdx] = (int4)(bodyIndexA,bodyIndexB,childShapeIndexA,childShapeIndexB);\n"
-" }\n"
-" }//\n"
-" }//fi(1)\n"
-" } //for (int b=0\n"
-" }//if (collidables[collidableIndexB].\n"
-" else//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
-" {\n"
-" if (1)\n"
-" {\n"
-" int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
-" float dmin = FLT_MAX;\n"
-" float4 posA = newPosA;\n"
-" posA.w = 0.f;\n"
-" float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
-" posB.w = 0.f;\n"
-" float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
-" float4 ornA = newOrnA;\n"
-" float4 c0 = transform(&c0local, &posA, &ornA);\n"
-" float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
-" float4 ornB = rigidBodies[bodyIndexB].m_quat;\n"
-" float4 c1 = transform(&c1local,&posB,&ornB);\n"
-" const float4 DeltaC2 = c0 - c1;\n"
-" {\n"
-" int compoundPairIdx = atomic_inc(numCompoundPairsOut);\n"
-" if (compoundPairIdx<maxNumCompoundPairsCapacity)\n"
-" {\n"
-" gpuCompoundPairsOut[compoundPairIdx] = (int4)(bodyIndexA,bodyIndexB,childShapeIndexA,-1);\n"
-" }//if (compoundPairIdx<maxNumCompoundPairsCapacity)\n"
-" }//\n"
-" }//fi (1)\n"
-" }//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
-" }//for (int b=0;b<numChildrenB;b++) \n"
-" return;\n"
-" }//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
-" if ((collidables[collidableIndexA].m_shapeType!=SHAPE_CONCAVE_TRIMESH) \n"
-" && (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))\n"
-" {\n"
-" int numChildrenB = collidables[collidableIndexB].m_numChildShapes;\n"
-" for (int b=0;b<numChildrenB;b++)\n"
-" {\n"
-" int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex+b;\n"
-" int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
-" float4 ornB = rigidBodies[bodyIndexB].m_quat;\n"
-" float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
-" float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
-" float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
-" float4 newPosB = qtRotate(ornB,childPosB)+posB;\n"
-" float4 newOrnB = qtMul(ornB,childOrnB);\n"
-" int shapeIndexB = collidables[childColIndexB].m_shapeIndex;\n"
-" //////////////////////////////////////\n"
-" if (1)\n"
-" {\n"
-" int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
-" float dmin = FLT_MAX;\n"
-" float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
-" posA.w = 0.f;\n"
-" float4 posB = newPosB;\n"
-" posB.w = 0.f;\n"
-" float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
-" float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
-" float4 c0 = transform(&c0local, &posA, &ornA);\n"
-" float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
-" float4 ornB =newOrnB;\n"
-" float4 c1 = transform(&c1local,&posB,&ornB);\n"
-" const float4 DeltaC2 = c0 - c1;\n"
-" {//\n"
-" int compoundPairIdx = atomic_inc(numCompoundPairsOut);\n"
-" if (compoundPairIdx<maxNumCompoundPairsCapacity)\n"
-" {\n"
-" gpuCompoundPairsOut[compoundPairIdx] = (int4)(bodyIndexA,bodyIndexB,-1,childShapeIndexB);\n"
-" }//fi (compoundPairIdx<maxNumCompoundPairsCapacity)\n"
-" }//\n"
-" }//fi (1) \n"
-" }//for (int b=0;b<numChildrenB;b++)\n"
-" return;\n"
-" }//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
-" return;\n"
-" }//fi ((collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS) ||(collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))\n"
-" }//i<numPairs\n"
-"}\n"
-"// work-in-progress\n"
-"__kernel void findSeparatingAxisKernel( __global const int4* pairs, \n"
-" __global const BodyData* rigidBodies, \n"
-" __global const btCollidableGpu* collidables,\n"
-" __global const ConvexPolyhedronCL* convexShapes, \n"
-" __global const float4* vertices,\n"
-" __global const float4* uniqueEdges,\n"
-" __global const btGpuFace* faces,\n"
-" __global const int* indices,\n"
-" __global btAabbCL* aabbs,\n"
-" __global volatile float4* separatingNormals,\n"
-" __global volatile int* hasSeparatingAxis,\n"
-" int numPairs\n"
-" )\n"
-"{\n"
-" int i = get_global_id(0);\n"
-" \n"
-" if (i<numPairs)\n"
-" {\n"
-" \n"
-" int bodyIndexA = pairs[i].x;\n"
-" int bodyIndexB = pairs[i].y;\n"
-" int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
-" int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
-" \n"
-" int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
-" int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
-" \n"
-" \n"
-" //once the broadphase avoids static-static pairs, we can remove this test\n"
-" if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))\n"
-" {\n"
-" hasSeparatingAxis[i] = 0;\n"
-" return;\n"
-" }\n"
-" \n"
-" if ((collidables[collidableIndexA].m_shapeType!=SHAPE_CONVEX_HULL) ||(collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL))\n"
-" {\n"
-" hasSeparatingAxis[i] = 0;\n"
-" return;\n"
-" }\n"
-" \n"
-" if ((collidables[collidableIndexA].m_shapeType==SHAPE_CONCAVE_TRIMESH))\n"
-" {\n"
-" hasSeparatingAxis[i] = 0;\n"
-" return;\n"
-" }\n"
-" int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
-" float dmin = FLT_MAX;\n"
-" float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
-" posA.w = 0.f;\n"
-" float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
-" posB.w = 0.f;\n"
-" float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
-" float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
-" float4 c0 = transform(&c0local, &posA, &ornA);\n"
-" float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
-" float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
-" float4 c1 = transform(&c1local,&posB,&ornB);\n"
-" const float4 DeltaC2 = c0 - c1;\n"
-" float4 sepNormal;\n"
-" \n"
-" bool sepA = findSeparatingAxis( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,\n"
-" posB,ornB,\n"
-" DeltaC2,\n"
-" vertices,uniqueEdges,faces,\n"
-" indices,&sepNormal,&dmin);\n"
-" hasSeparatingAxis[i] = 4;\n"
-" if (!sepA)\n"
-" {\n"
-" hasSeparatingAxis[i] = 0;\n"
-" } else\n"
-" {\n"
-" bool sepB = findSeparatingAxis( &convexShapes[shapeIndexB],&convexShapes[shapeIndexA],posB,ornB,\n"
-" posA,ornA,\n"
-" DeltaC2,\n"
-" vertices,uniqueEdges,faces,\n"
-" indices,&sepNormal,&dmin);\n"
-" if (!sepB)\n"
-" {\n"
-" hasSeparatingAxis[i] = 0;\n"
-" } else\n"
-" {\n"
-" bool sepEE = findSeparatingAxisEdgeEdge( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,\n"
-" posB,ornB,\n"
-" DeltaC2,\n"
-" vertices,uniqueEdges,faces,\n"
-" indices,&sepNormal,&dmin);\n"
-" if (!sepEE)\n"
-" {\n"
-" hasSeparatingAxis[i] = 0;\n"
-" } else\n"
-" {\n"
-" hasSeparatingAxis[i] = 1;\n"
-" separatingNormals[i] = sepNormal;\n"
-" }\n"
-" }\n"
-" }\n"
-" \n"
-" }\n"
-"}\n"
-"__kernel void findSeparatingAxisVertexFaceKernel( __global const int4* pairs, \n"
-" __global const BodyData* rigidBodies, \n"
-" __global const btCollidableGpu* collidables,\n"
-" __global const ConvexPolyhedronCL* convexShapes, \n"
-" __global const float4* vertices,\n"
-" __global const float4* uniqueEdges,\n"
-" __global const btGpuFace* faces,\n"
-" __global const int* indices,\n"
-" __global btAabbCL* aabbs,\n"
-" __global volatile float4* separatingNormals,\n"
-" __global volatile int* hasSeparatingAxis,\n"
-" __global float* dmins,\n"
-" int numPairs\n"
-" )\n"
-"{\n"
-" int i = get_global_id(0);\n"
-" \n"
-" if (i<numPairs)\n"
-" {\n"
-" \n"
-" int bodyIndexA = pairs[i].x;\n"
-" int bodyIndexB = pairs[i].y;\n"
-" int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
-" int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
-" \n"
-" int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
-" int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
-" \n"
-" hasSeparatingAxis[i] = 0; \n"
-" \n"
-" //once the broadphase avoids static-static pairs, we can remove this test\n"
-" if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))\n"
-" {\n"
-" return;\n"
-" }\n"
-" \n"
-" if ((collidables[collidableIndexA].m_shapeType!=SHAPE_CONVEX_HULL) ||(collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL))\n"
-" {\n"
-" return;\n"
-" }\n"
-" \n"
-" int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
-" float dmin = FLT_MAX;\n"
-" dmins[i] = dmin;\n"
-" \n"
-" float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
-" posA.w = 0.f;\n"
-" float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
-" posB.w = 0.f;\n"
-" float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
-" float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
-" float4 c0 = transform(&c0local, &posA, &ornA);\n"
-" float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
-" float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
-" float4 c1 = transform(&c1local,&posB,&ornB);\n"
-" const float4 DeltaC2 = c0 - c1;\n"
-" float4 sepNormal;\n"
-" \n"
-" bool sepA = findSeparatingAxis( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,\n"
-" posB,ornB,\n"
-" DeltaC2,\n"
-" vertices,uniqueEdges,faces,\n"
-" indices,&sepNormal,&dmin);\n"
-" hasSeparatingAxis[i] = 4;\n"
-" if (!sepA)\n"
-" {\n"
-" hasSeparatingAxis[i] = 0;\n"
-" } else\n"
-" {\n"
-" bool sepB = findSeparatingAxis( &convexShapes[shapeIndexB],&convexShapes[shapeIndexA],posB,ornB,\n"
-" posA,ornA,\n"
-" DeltaC2,\n"
-" vertices,uniqueEdges,faces,\n"
-" indices,&sepNormal,&dmin);\n"
-" if (sepB)\n"
-" {\n"
-" dmins[i] = dmin;\n"
-" hasSeparatingAxis[i] = 1;\n"
-" separatingNormals[i] = sepNormal;\n"
-" }\n"
-" }\n"
-" \n"
-" }\n"
-"}\n"
-"__kernel void findSeparatingAxisEdgeEdgeKernel( __global const int4* pairs, \n"
-" __global const BodyData* rigidBodies, \n"
-" __global const btCollidableGpu* collidables,\n"
-" __global const ConvexPolyhedronCL* convexShapes, \n"
-" __global const float4* vertices,\n"
-" __global const float4* uniqueEdges,\n"
-" __global const btGpuFace* faces,\n"
-" __global const int* indices,\n"
-" __global btAabbCL* aabbs,\n"
-" __global float4* separatingNormals,\n"
-" __global int* hasSeparatingAxis,\n"
-" __global float* dmins,\n"
-" __global const float4* unitSphereDirections,\n"
-" int numUnitSphereDirections,\n"
-" int numPairs\n"
-" )\n"
-"{\n"
-" int i = get_global_id(0);\n"
-" \n"
-" if (i<numPairs)\n"
-" {\n"
-" if (hasSeparatingAxis[i])\n"
-" {\n"
-" \n"
-" int bodyIndexA = pairs[i].x;\n"
-" int bodyIndexB = pairs[i].y;\n"
-" \n"
-" int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
-" int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
-" \n"
-" int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
-" int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
-" \n"
-" \n"
-" int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
-" \n"
-" float dmin = dmins[i];\n"
-" \n"
-" float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
-" posA.w = 0.f;\n"
-" float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
-" posB.w = 0.f;\n"
-" float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
-" float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
-" float4 c0 = transform(&c0local, &posA, &ornA);\n"
-" float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
-" float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
-" float4 c1 = transform(&c1local,&posB,&ornB);\n"
-" const float4 DeltaC2 = c0 - c1;\n"
-" float4 sepNormal = separatingNormals[i];\n"
-" \n"
-" \n"
-" \n"
-" bool sepEE = false;\n"
-" int numEdgeEdgeDirections = convexShapes[shapeIndexA].m_numUniqueEdges*convexShapes[shapeIndexB].m_numUniqueEdges;\n"
-" if (numEdgeEdgeDirections<=numUnitSphereDirections)\n"
-" {\n"
-" sepEE = findSeparatingAxisEdgeEdge( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,\n"
-" posB,ornB,\n"
-" DeltaC2,\n"
-" vertices,uniqueEdges,faces,\n"
-" indices,&sepNormal,&dmin);\n"
-" \n"
-" if (!sepEE)\n"
-" {\n"
-" hasSeparatingAxis[i] = 0;\n"
-" } else\n"
-" {\n"
-" hasSeparatingAxis[i] = 1;\n"
-" separatingNormals[i] = sepNormal;\n"
-" }\n"
-" }\n"
-" /*\n"
-" ///else case is a separate kernel, to make Mac OSX OpenCL compiler happy\n"
-" else\n"
-" {\n"
-" sepEE = findSeparatingAxisUnitSphere(&convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,\n"
-" posB,ornB,\n"
-" DeltaC2,\n"
-" vertices,unitSphereDirections,numUnitSphereDirections,\n"
-" &sepNormal,&dmin);\n"
-" if (!sepEE)\n"
-" {\n"
-" hasSeparatingAxis[i] = 0;\n"
-" } else\n"
-" {\n"
-" hasSeparatingAxis[i] = 1;\n"
-" separatingNormals[i] = sepNormal;\n"
-" }\n"
-" }\n"
-" */\n"
-" } //if (hasSeparatingAxis[i])\n"
-" }//(i<numPairs)\n"
-"}\n"
-"inline int findClippingFaces(const float4 separatingNormal,\n"
-" const ConvexPolyhedronCL* hullA, \n"
-" __global const ConvexPolyhedronCL* hullB,\n"
-" const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB,\n"
-" __global float4* worldVertsA1,\n"
-" __global float4* worldNormalsA1,\n"
-" __global float4* worldVertsB1,\n"
-" int capacityWorldVerts,\n"
-" const float minDist, float maxDist,\n"
-" const float4* verticesA,\n"
-" const btGpuFace* facesA,\n"
-" const int* indicesA,\n"
-" __global const float4* verticesB,\n"
-" __global const btGpuFace* facesB,\n"
-" __global const int* indicesB,\n"
-" __global int4* clippingFaces, int pairIndex)\n"
-"{\n"
-" int numContactsOut = 0;\n"
-" int numWorldVertsB1= 0;\n"
-" \n"
-" \n"
-" int closestFaceB=0;\n"
-" float dmax = -FLT_MAX;\n"
-" \n"
-" {\n"
-" for(int face=0;face<hullB->m_numFaces;face++)\n"
-" {\n"
-" const float4 Normal = make_float4(facesB[hullB->m_faceOffset+face].m_plane.x,\n"
-" facesB[hullB->m_faceOffset+face].m_plane.y, facesB[hullB->m_faceOffset+face].m_plane.z,0.f);\n"
-" const float4 WorldNormal = qtRotate(ornB, Normal);\n"
-" float d = dot3F4(WorldNormal,separatingNormal);\n"
-" if (d > dmax)\n"
-" {\n"
-" dmax = d;\n"
-" closestFaceB = face;\n"
-" }\n"
-" }\n"
-" }\n"
-" \n"
-" {\n"
-" const btGpuFace polyB = facesB[hullB->m_faceOffset+closestFaceB];\n"
-" int numVertices = polyB.m_numIndices;\n"
-" if (numVertices>capacityWorldVerts)\n"
-" numVertices = capacityWorldVerts;\n"
-" \n"
-" for(int e0=0;e0<numVertices;e0++)\n"
-" {\n"
-" if (e0<capacityWorldVerts)\n"
-" {\n"
-" const float4 b = verticesB[hullB->m_vertexOffset+indicesB[polyB.m_indexOffset+e0]];\n"
-" worldVertsB1[pairIndex*capacityWorldVerts+numWorldVertsB1++] = transform(&b,&posB,&ornB);\n"
-" }\n"
-" }\n"
-" }\n"
-" \n"
-" int closestFaceA=0;\n"
-" {\n"
-" float dmin = FLT_MAX;\n"
-" for(int face=0;face<hullA->m_numFaces;face++)\n"
-" {\n"
-" const float4 Normal = make_float4(\n"
-" facesA[hullA->m_faceOffset+face].m_plane.x,\n"
-" facesA[hullA->m_faceOffset+face].m_plane.y,\n"
-" facesA[hullA->m_faceOffset+face].m_plane.z,\n"
-" 0.f);\n"
-" const float4 faceANormalWS = qtRotate(ornA,Normal);\n"
-" \n"
-" float d = dot3F4(faceANormalWS,separatingNormal);\n"
-" if (d < dmin)\n"
-" {\n"
-" dmin = d;\n"
-" closestFaceA = face;\n"
-" worldNormalsA1[pairIndex] = faceANormalWS;\n"
-" }\n"
-" }\n"
-" }\n"
-" \n"
-" int numVerticesA = facesA[hullA->m_faceOffset+closestFaceA].m_numIndices;\n"
-" if (numVerticesA>capacityWorldVerts)\n"
-" numVerticesA = capacityWorldVerts;\n"
-" \n"
-" for(int e0=0;e0<numVerticesA;e0++)\n"
-" {\n"
-" if (e0<capacityWorldVerts)\n"
-" {\n"
-" const float4 a = verticesA[hullA->m_vertexOffset+indicesA[facesA[hullA->m_faceOffset+closestFaceA].m_indexOffset+e0]];\n"
-" worldVertsA1[pairIndex*capacityWorldVerts+e0] = transform(&a, &posA,&ornA);\n"
-" }\n"
-" }\n"
-" \n"
-" clippingFaces[pairIndex].x = closestFaceA;\n"
-" clippingFaces[pairIndex].y = closestFaceB;\n"
-" clippingFaces[pairIndex].z = numVerticesA;\n"
-" clippingFaces[pairIndex].w = numWorldVertsB1;\n"
-" \n"
-" \n"
-" return numContactsOut;\n"
-"}\n"
-"// work-in-progress\n"
-"__kernel void findConcaveSeparatingAxisKernel( __global int4* concavePairs,\n"
-" __global const BodyData* rigidBodies,\n"
-" __global const btCollidableGpu* collidables,\n"
-" __global const ConvexPolyhedronCL* convexShapes, \n"
-" __global const float4* vertices,\n"
-" __global const float4* uniqueEdges,\n"
-" __global const btGpuFace* faces,\n"
-" __global const int* indices,\n"
-" __global const btGpuChildShape* gpuChildShapes,\n"
-" __global btAabbCL* aabbs,\n"
-" __global float4* concaveSeparatingNormalsOut,\n"
-" __global int* concaveHasSeparatingNormals,\n"
-" __global int4* clippingFacesOut,\n"
-" __global float4* worldVertsA1GPU,\n"
-" __global float4* worldNormalsAGPU,\n"
-" __global float4* worldVertsB1GPU,\n"
-" int vertexFaceCapacity,\n"
-" int numConcavePairs\n"
-" )\n"
-"{\n"
-" int i = get_global_id(0);\n"
-" if (i>=numConcavePairs)\n"
-" return;\n"
-" concaveHasSeparatingNormals[i] = 0;\n"
-" int pairIdx = i;\n"
-" int bodyIndexA = concavePairs[i].x;\n"
-" int bodyIndexB = concavePairs[i].y;\n"
-" int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
-" int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
-" int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
-" int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
-" if (collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL&&\n"
-" collidables[collidableIndexB].m_shapeType!=SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
-" {\n"
-" concavePairs[pairIdx].w = -1;\n"
-" return;\n"
-" }\n"
-" int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
-" int numActualConcaveConvexTests = 0;\n"
-" \n"
-" int f = concavePairs[i].z;\n"
-" \n"
-" bool overlap = false;\n"
-" \n"
-" ConvexPolyhedronCL convexPolyhedronA;\n"
-" //add 3 vertices of the triangle\n"
-" convexPolyhedronA.m_numVertices = 3;\n"
-" convexPolyhedronA.m_vertexOffset = 0;\n"
-" float4 localCenter = make_float4(0.f,0.f,0.f,0.f);\n"
-" btGpuFace face = faces[convexShapes[shapeIndexA].m_faceOffset+f];\n"
-" float4 triMinAabb, triMaxAabb;\n"
-" btAabbCL triAabb;\n"
-" triAabb.m_min = make_float4(1e30f,1e30f,1e30f,0.f);\n"
-" triAabb.m_max = make_float4(-1e30f,-1e30f,-1e30f,0.f);\n"
-" \n"
-" float4 verticesA[3];\n"
-" for (int i=0;i<3;i++)\n"
-" {\n"
-" int index = indices[face.m_indexOffset+i];\n"
-" float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];\n"
-" verticesA[i] = vert;\n"
-" localCenter += vert;\n"
-" \n"
-" triAabb.m_min = min(triAabb.m_min,vert); \n"
-" triAabb.m_max = max(triAabb.m_max,vert); \n"
-" }\n"
-" overlap = true;\n"
-" overlap = (triAabb.m_min.x > aabbs[bodyIndexB].m_max.x || triAabb.m_max.x < aabbs[bodyIndexB].m_min.x) ? false : overlap;\n"
-" overlap = (triAabb.m_min.z > aabbs[bodyIndexB].m_max.z || triAabb.m_max.z < aabbs[bodyIndexB].m_min.z) ? false : overlap;\n"
-" overlap = (triAabb.m_min.y > aabbs[bodyIndexB].m_max.y || triAabb.m_max.y < aabbs[bodyIndexB].m_min.y) ? false : overlap;\n"
-" \n"
-" if (overlap)\n"
-" {\n"
-" float dmin = FLT_MAX;\n"
-" int hasSeparatingAxis=5;\n"
-" float4 sepAxis=make_float4(1,2,3,4);\n"
-" int localCC=0;\n"
-" numActualConcaveConvexTests++;\n"
-" //a triangle has 3 unique edges\n"
-" convexPolyhedronA.m_numUniqueEdges = 3;\n"
-" convexPolyhedronA.m_uniqueEdgesOffset = 0;\n"
-" float4 uniqueEdgesA[3];\n"
-" \n"
-" uniqueEdgesA[0] = (verticesA[1]-verticesA[0]);\n"
-" uniqueEdgesA[1] = (verticesA[2]-verticesA[1]);\n"
-" uniqueEdgesA[2] = (verticesA[0]-verticesA[2]);\n"
-" convexPolyhedronA.m_faceOffset = 0;\n"
-" \n"
-" float4 normal = make_float4(face.m_plane.x,face.m_plane.y,face.m_plane.z,0.f);\n"
-" \n"
-" btGpuFace facesA[TRIANGLE_NUM_CONVEX_FACES];\n"
-" int indicesA[3+3+2+2+2];\n"
-" int curUsedIndices=0;\n"
-" int fidx=0;\n"
-" //front size of triangle\n"
-" {\n"
-" facesA[fidx].m_indexOffset=curUsedIndices;\n"
-" indicesA[0] = 0;\n"
-" indicesA[1] = 1;\n"
-" indicesA[2] = 2;\n"
-" curUsedIndices+=3;\n"
-" float c = face.m_plane.w;\n"
-" facesA[fidx].m_plane.x = normal.x;\n"
-" facesA[fidx].m_plane.y = normal.y;\n"
-" facesA[fidx].m_plane.z = normal.z;\n"
-" facesA[fidx].m_plane.w = c;\n"
-" facesA[fidx].m_numIndices=3;\n"
-" }\n"
-" fidx++;\n"
-" //back size of triangle\n"
-" {\n"
-" facesA[fidx].m_indexOffset=curUsedIndices;\n"
-" indicesA[3]=2;\n"
-" indicesA[4]=1;\n"
-" indicesA[5]=0;\n"
-" curUsedIndices+=3;\n"
-" float c = dot(normal,verticesA[0]);\n"
-" float c1 = -face.m_plane.w;\n"
-" facesA[fidx].m_plane.x = -normal.x;\n"
-" facesA[fidx].m_plane.y = -normal.y;\n"
-" facesA[fidx].m_plane.z = -normal.z;\n"
-" facesA[fidx].m_plane.w = c;\n"
-" facesA[fidx].m_numIndices=3;\n"
-" }\n"
-" fidx++;\n"
-" bool addEdgePlanes = true;\n"
-" if (addEdgePlanes)\n"
-" {\n"
-" int numVertices=3;\n"
-" int prevVertex = numVertices-1;\n"
-" for (int i=0;i<numVertices;i++)\n"
-" {\n"
-" float4 v0 = verticesA[i];\n"
-" float4 v1 = verticesA[prevVertex];\n"
-" \n"
-" float4 edgeNormal = normalize(cross(normal,v1-v0));\n"
-" float c = -dot(edgeNormal,v0);\n"
-" facesA[fidx].m_numIndices = 2;\n"
-" facesA[fidx].m_indexOffset=curUsedIndices;\n"
-" indicesA[curUsedIndices++]=i;\n"
-" indicesA[curUsedIndices++]=prevVertex;\n"
-" \n"
-" facesA[fidx].m_plane.x = edgeNormal.x;\n"
-" facesA[fidx].m_plane.y = edgeNormal.y;\n"
-" facesA[fidx].m_plane.z = edgeNormal.z;\n"
-" facesA[fidx].m_plane.w = c;\n"
-" fidx++;\n"
-" prevVertex = i;\n"
-" }\n"
-" }\n"
-" convexPolyhedronA.m_numFaces = TRIANGLE_NUM_CONVEX_FACES;\n"
-" convexPolyhedronA.m_localCenter = localCenter*(1.f/3.f);\n"
-" float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
-" posA.w = 0.f;\n"
-" float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
-" posB.w = 0.f;\n"
-" float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
-" float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
-" \n"
-" ///////////////////\n"
-" ///compound shape support\n"
-" if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
-" {\n"
-" int compoundChild = concavePairs[pairIdx].w;\n"
-" int childShapeIndexB = compoundChild;//collidables[collidableIndexB].m_shapeIndex+compoundChild;\n"
-" int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
-" float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
-" float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
-" float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
-" float4 newOrnB = qtMul(ornB,childOrnB);\n"
-" posB = newPosB;\n"
-" ornB = newOrnB;\n"
-" shapeIndexB = collidables[childColIndexB].m_shapeIndex;\n"
-" }\n"
-" //////////////////\n"
-" float4 c0local = convexPolyhedronA.m_localCenter;\n"
-" float4 c0 = transform(&c0local, &posA, &ornA);\n"
-" float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
-" float4 c1 = transform(&c1local,&posB,&ornB);\n"
-" const float4 DeltaC2 = c0 - c1;\n"
-" bool sepA = findSeparatingAxisLocalA( &convexPolyhedronA, &convexShapes[shapeIndexB],\n"
-" posA,ornA,\n"
-" posB,ornB,\n"
-" DeltaC2,\n"
-" verticesA,uniqueEdgesA,facesA,indicesA,\n"
-" vertices,uniqueEdges,faces,indices,\n"
-" &sepAxis,&dmin);\n"
-" hasSeparatingAxis = 4;\n"
-" if (!sepA)\n"
-" {\n"
-" hasSeparatingAxis = 0;\n"
-" } else\n"
-" {\n"
-" bool sepB = findSeparatingAxisLocalB( &convexShapes[shapeIndexB],&convexPolyhedronA,\n"
-" posB,ornB,\n"
-" posA,ornA,\n"
-" DeltaC2,\n"
-" vertices,uniqueEdges,faces,indices,\n"
-" verticesA,uniqueEdgesA,facesA,indicesA,\n"
-" &sepAxis,&dmin);\n"
-" if (!sepB)\n"
-" {\n"
-" hasSeparatingAxis = 0;\n"
-" } else\n"
-" {\n"
-" bool sepEE = findSeparatingAxisEdgeEdgeLocalA( &convexPolyhedronA, &convexShapes[shapeIndexB],\n"
-" posA,ornA,\n"
-" posB,ornB,\n"
-" DeltaC2,\n"
-" verticesA,uniqueEdgesA,facesA,indicesA,\n"
-" vertices,uniqueEdges,faces,indices,\n"
-" &sepAxis,&dmin);\n"
-" \n"
-" if (!sepEE)\n"
-" {\n"
-" hasSeparatingAxis = 0;\n"
-" } else\n"
-" {\n"
-" hasSeparatingAxis = 1;\n"
-" }\n"
-" }\n"
-" } \n"
-" \n"
-" if (hasSeparatingAxis)\n"
-" {\n"
-" sepAxis.w = dmin;\n"
-" concaveSeparatingNormalsOut[pairIdx]=sepAxis;\n"
-" concaveHasSeparatingNormals[i]=1;\n"
-" float minDist = -1e30f;\n"
-" float maxDist = 0.02f;\n"
-" \n"
-" findClippingFaces(sepAxis,\n"
-" &convexPolyhedronA,\n"
-" &convexShapes[shapeIndexB],\n"
-" posA,ornA,\n"
-" posB,ornB,\n"
-" worldVertsA1GPU,\n"
-" worldNormalsAGPU,\n"
-" worldVertsB1GPU,\n"
-" vertexFaceCapacity,\n"
-" minDist, maxDist,\n"
-" verticesA,\n"
-" facesA,\n"
-" indicesA,\n"
-" vertices,\n"
-" faces,\n"
-" indices,\n"
-" clippingFacesOut, pairIdx);\n"
-" } else\n"
-" { \n"
-" //mark this pair as in-active\n"
-" concavePairs[pairIdx].w = -1;\n"
-" }\n"
-" }\n"
-" else\n"
-" { \n"
-" //mark this pair as in-active\n"
-" concavePairs[pairIdx].w = -1;\n"
-" }\n"
-" \n"
-" concavePairs[pairIdx].z = -1;//now z is used for existing/persistent contacts\n"
-"}\n"
-;
+static const char* satKernelsCL =
+ "//keep this enum in sync with the CPU version (in btCollidable.h)\n"
+ "//written by Erwin Coumans\n"
+ "#define SHAPE_CONVEX_HULL 3\n"
+ "#define SHAPE_CONCAVE_TRIMESH 5\n"
+ "#define TRIANGLE_NUM_CONVEX_FACES 5\n"
+ "#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6\n"
+ "#define B3_MAX_STACK_DEPTH 256\n"
+ "typedef unsigned int u32;\n"
+ "///keep this in sync with btCollidable.h\n"
+ "typedef struct\n"
+ "{\n"
+ " union {\n"
+ " int m_numChildShapes;\n"
+ " int m_bvhIndex;\n"
+ " };\n"
+ " union\n"
+ " {\n"
+ " float m_radius;\n"
+ " int m_compoundBvhIndex;\n"
+ " };\n"
+ " \n"
+ " int m_shapeType;\n"
+ " int m_shapeIndex;\n"
+ " \n"
+ "} btCollidableGpu;\n"
+ "#define MAX_NUM_PARTS_IN_BITS 10\n"
+ "///b3QuantizedBvhNode is a compressed aabb node, 16 bytes.\n"
+ "///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).\n"
+ "typedef struct\n"
+ "{\n"
+ " //12 bytes\n"
+ " unsigned short int m_quantizedAabbMin[3];\n"
+ " unsigned short int m_quantizedAabbMax[3];\n"
+ " //4 bytes\n"
+ " int m_escapeIndexOrTriangleIndex;\n"
+ "} b3QuantizedBvhNode;\n"
+ "typedef struct\n"
+ "{\n"
+ " float4 m_aabbMin;\n"
+ " float4 m_aabbMax;\n"
+ " float4 m_quantization;\n"
+ " int m_numNodes;\n"
+ " int m_numSubTrees;\n"
+ " int m_nodeOffset;\n"
+ " int m_subTreeOffset;\n"
+ "} b3BvhInfo;\n"
+ "int getTriangleIndex(const b3QuantizedBvhNode* rootNode)\n"
+ "{\n"
+ " unsigned int x=0;\n"
+ " unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);\n"
+ " // Get only the lower bits where the triangle index is stored\n"
+ " return (rootNode->m_escapeIndexOrTriangleIndex&~(y));\n"
+ "}\n"
+ "int getTriangleIndexGlobal(__global const b3QuantizedBvhNode* rootNode)\n"
+ "{\n"
+ " unsigned int x=0;\n"
+ " unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);\n"
+ " // Get only the lower bits where the triangle index is stored\n"
+ " return (rootNode->m_escapeIndexOrTriangleIndex&~(y));\n"
+ "}\n"
+ "int isLeafNode(const b3QuantizedBvhNode* rootNode)\n"
+ "{\n"
+ " //skipindex is negative (internal node), triangleindex >=0 (leafnode)\n"
+ " return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;\n"
+ "}\n"
+ "int isLeafNodeGlobal(__global const b3QuantizedBvhNode* rootNode)\n"
+ "{\n"
+ " //skipindex is negative (internal node), triangleindex >=0 (leafnode)\n"
+ " return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;\n"
+ "}\n"
+ " \n"
+ "int getEscapeIndex(const b3QuantizedBvhNode* rootNode)\n"
+ "{\n"
+ " return -rootNode->m_escapeIndexOrTriangleIndex;\n"
+ "}\n"
+ "int getEscapeIndexGlobal(__global const b3QuantizedBvhNode* rootNode)\n"
+ "{\n"
+ " return -rootNode->m_escapeIndexOrTriangleIndex;\n"
+ "}\n"
+ "typedef struct\n"
+ "{\n"
+ " //12 bytes\n"
+ " unsigned short int m_quantizedAabbMin[3];\n"
+ " unsigned short int m_quantizedAabbMax[3];\n"
+ " //4 bytes, points to the root of the subtree\n"
+ " int m_rootNodeIndex;\n"
+ " //4 bytes\n"
+ " int m_subtreeSize;\n"
+ " int m_padding[3];\n"
+ "} b3BvhSubtreeInfo;\n"
+ "typedef struct\n"
+ "{\n"
+ " float4 m_childPosition;\n"
+ " float4 m_childOrientation;\n"
+ " int m_shapeIndex;\n"
+ " int m_unused0;\n"
+ " int m_unused1;\n"
+ " int m_unused2;\n"
+ "} btGpuChildShape;\n"
+ "typedef struct\n"
+ "{\n"
+ " float4 m_pos;\n"
+ " float4 m_quat;\n"
+ " float4 m_linVel;\n"
+ " float4 m_angVel;\n"
+ " u32 m_collidableIdx;\n"
+ " float m_invMass;\n"
+ " float m_restituitionCoeff;\n"
+ " float m_frictionCoeff;\n"
+ "} BodyData;\n"
+ "typedef struct \n"
+ "{\n"
+ " float4 m_localCenter;\n"
+ " float4 m_extents;\n"
+ " float4 mC;\n"
+ " float4 mE;\n"
+ " \n"
+ " float m_radius;\n"
+ " int m_faceOffset;\n"
+ " int m_numFaces;\n"
+ " int m_numVertices;\n"
+ " int m_vertexOffset;\n"
+ " int m_uniqueEdgesOffset;\n"
+ " int m_numUniqueEdges;\n"
+ " int m_unused;\n"
+ "} ConvexPolyhedronCL;\n"
+ "typedef struct \n"
+ "{\n"
+ " union\n"
+ " {\n"
+ " float4 m_min;\n"
+ " float m_minElems[4];\n"
+ " int m_minIndices[4];\n"
+ " };\n"
+ " union\n"
+ " {\n"
+ " float4 m_max;\n"
+ " float m_maxElems[4];\n"
+ " int m_maxIndices[4];\n"
+ " };\n"
+ "} btAabbCL;\n"
+ "#ifndef B3_AABB_H\n"
+ "#define B3_AABB_H\n"
+ "#ifndef B3_FLOAT4_H\n"
+ "#define B3_FLOAT4_H\n"
+ "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+ "#define B3_PLATFORM_DEFINITIONS_H\n"
+ "struct MyTest\n"
+ "{\n"
+ " int bla;\n"
+ "};\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
+ "#define B3_LARGE_FLOAT 1e18f\n"
+ "#define B3_INFINITY 1e18f\n"
+ "#define b3Assert(a)\n"
+ "#define b3ConstArray(a) __global const a*\n"
+ "#define b3AtomicInc atomic_inc\n"
+ "#define b3AtomicAdd atomic_add\n"
+ "#define b3Fabs fabs\n"
+ "#define b3Sqrt native_sqrt\n"
+ "#define b3Sin native_sin\n"
+ "#define b3Cos native_cos\n"
+ "#define B3_STATIC\n"
+ "#endif\n"
+ "#endif\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ " typedef float4 b3Float4;\n"
+ " #define b3Float4ConstArg const b3Float4\n"
+ " #define b3MakeFloat4 (float4)\n"
+ " float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+ " {\n"
+ " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+ " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+ " return dot(a1, b1);\n"
+ " }\n"
+ " b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+ " {\n"
+ " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+ " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+ " return cross(a1, b1);\n"
+ " }\n"
+ " #define b3MinFloat4 min\n"
+ " #define b3MaxFloat4 max\n"
+ " #define b3Normalized(a) normalize(a)\n"
+ "#endif \n"
+ " \n"
+ "inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
+ "{\n"
+ " if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
+ " return false;\n"
+ " return true;\n"
+ "}\n"
+ "inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
+ "{\n"
+ " float maxDot = -B3_INFINITY;\n"
+ " int i = 0;\n"
+ " int ptIndex = -1;\n"
+ " for( i = 0; i < vecLen; i++ )\n"
+ " {\n"
+ " float dot = b3Dot3F4(vecArray[i],vec);\n"
+ " \n"
+ " if( dot > maxDot )\n"
+ " {\n"
+ " maxDot = dot;\n"
+ " ptIndex = i;\n"
+ " }\n"
+ " }\n"
+ " b3Assert(ptIndex>=0);\n"
+ " if (ptIndex<0)\n"
+ " {\n"
+ " ptIndex = 0;\n"
+ " }\n"
+ " *dotOut = maxDot;\n"
+ " return ptIndex;\n"
+ "}\n"
+ "#endif //B3_FLOAT4_H\n"
+ "#ifndef B3_MAT3x3_H\n"
+ "#define B3_MAT3x3_H\n"
+ "#ifndef B3_QUAT_H\n"
+ "#define B3_QUAT_H\n"
+ "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#endif\n"
+ "#endif\n"
+ "#ifndef B3_FLOAT4_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#endif \n"
+ "#endif //B3_FLOAT4_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ " typedef float4 b3Quat;\n"
+ " #define b3QuatConstArg const b3Quat\n"
+ " \n"
+ " \n"
+ "inline float4 b3FastNormalize4(float4 v)\n"
+ "{\n"
+ " v = (float4)(v.xyz,0.f);\n"
+ " return fast_normalize(v);\n"
+ "}\n"
+ " \n"
+ "inline b3Quat b3QuatMul(b3Quat a, b3Quat b);\n"
+ "inline b3Quat b3QuatNormalized(b3QuatConstArg in);\n"
+ "inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec);\n"
+ "inline b3Quat b3QuatInvert(b3QuatConstArg q);\n"
+ "inline b3Quat b3QuatInverse(b3QuatConstArg q);\n"
+ "inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b)\n"
+ "{\n"
+ " b3Quat ans;\n"
+ " ans = b3Cross3( a, b );\n"
+ " ans += a.w*b+b.w*a;\n"
+ "// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+ " ans.w = a.w*b.w - b3Dot3F4(a, b);\n"
+ " return ans;\n"
+ "}\n"
+ "inline b3Quat b3QuatNormalized(b3QuatConstArg in)\n"
+ "{\n"
+ " b3Quat q;\n"
+ " q=in;\n"
+ " //return b3FastNormalize4(in);\n"
+ " float len = native_sqrt(dot(q, q));\n"
+ " if(len > 0.f)\n"
+ " {\n"
+ " q *= 1.f / len;\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " q.x = q.y = q.z = 0.f;\n"
+ " q.w = 1.f;\n"
+ " }\n"
+ " return q;\n"
+ "}\n"
+ "inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+ "{\n"
+ " b3Quat qInv = b3QuatInvert( q );\n"
+ " float4 vcpy = vec;\n"
+ " vcpy.w = 0.f;\n"
+ " float4 out = b3QuatMul(b3QuatMul(q,vcpy),qInv);\n"
+ " return out;\n"
+ "}\n"
+ "inline b3Quat b3QuatInverse(b3QuatConstArg q)\n"
+ "{\n"
+ " return (b3Quat)(-q.xyz, q.w);\n"
+ "}\n"
+ "inline b3Quat b3QuatInvert(b3QuatConstArg q)\n"
+ "{\n"
+ " return (b3Quat)(-q.xyz, q.w);\n"
+ "}\n"
+ "inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+ "{\n"
+ " return b3QuatRotate( b3QuatInvert( q ), vec );\n"
+ "}\n"
+ "inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation)\n"
+ "{\n"
+ " return b3QuatRotate( orientation, point ) + (translation);\n"
+ "}\n"
+ " \n"
+ "#endif \n"
+ "#endif //B3_QUAT_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "typedef struct\n"
+ "{\n"
+ " b3Float4 m_row[3];\n"
+ "}b3Mat3x3;\n"
+ "#define b3Mat3x3ConstArg const b3Mat3x3\n"
+ "#define b3GetRow(m,row) (m.m_row[row])\n"
+ "inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat)\n"
+ "{\n"
+ " b3Float4 quat2 = (b3Float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);\n"
+ " b3Mat3x3 out;\n"
+ " out.m_row[0].x=1-2*quat2.y-2*quat2.z;\n"
+ " out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;\n"
+ " out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;\n"
+ " out.m_row[0].w = 0.f;\n"
+ " out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;\n"
+ " out.m_row[1].y=1-2*quat2.x-2*quat2.z;\n"
+ " out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;\n"
+ " out.m_row[1].w = 0.f;\n"
+ " out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;\n"
+ " out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;\n"
+ " out.m_row[2].z=1-2*quat2.x-2*quat2.y;\n"
+ " out.m_row[2].w = 0.f;\n"
+ " return out;\n"
+ "}\n"
+ "inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn)\n"
+ "{\n"
+ " b3Mat3x3 out;\n"
+ " out.m_row[0] = fabs(matIn.m_row[0]);\n"
+ " out.m_row[1] = fabs(matIn.m_row[1]);\n"
+ " out.m_row[2] = fabs(matIn.m_row[2]);\n"
+ " return out;\n"
+ "}\n"
+ "__inline\n"
+ "b3Mat3x3 mtZero();\n"
+ "__inline\n"
+ "b3Mat3x3 mtIdentity();\n"
+ "__inline\n"
+ "b3Mat3x3 mtTranspose(b3Mat3x3 m);\n"
+ "__inline\n"
+ "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);\n"
+ "__inline\n"
+ "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);\n"
+ "__inline\n"
+ "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);\n"
+ "__inline\n"
+ "b3Mat3x3 mtZero()\n"
+ "{\n"
+ " b3Mat3x3 m;\n"
+ " m.m_row[0] = (b3Float4)(0.f);\n"
+ " m.m_row[1] = (b3Float4)(0.f);\n"
+ " m.m_row[2] = (b3Float4)(0.f);\n"
+ " return m;\n"
+ "}\n"
+ "__inline\n"
+ "b3Mat3x3 mtIdentity()\n"
+ "{\n"
+ " b3Mat3x3 m;\n"
+ " m.m_row[0] = (b3Float4)(1,0,0,0);\n"
+ " m.m_row[1] = (b3Float4)(0,1,0,0);\n"
+ " m.m_row[2] = (b3Float4)(0,0,1,0);\n"
+ " return m;\n"
+ "}\n"
+ "__inline\n"
+ "b3Mat3x3 mtTranspose(b3Mat3x3 m)\n"
+ "{\n"
+ " b3Mat3x3 out;\n"
+ " out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
+ " out.m_row[1] = (b3Float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
+ " out.m_row[2] = (b3Float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
+ " return out;\n"
+ "}\n"
+ "__inline\n"
+ "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)\n"
+ "{\n"
+ " b3Mat3x3 transB;\n"
+ " transB = mtTranspose( b );\n"
+ " b3Mat3x3 ans;\n"
+ " // why this doesn't run when 0ing in the for{}\n"
+ " a.m_row[0].w = 0.f;\n"
+ " a.m_row[1].w = 0.f;\n"
+ " a.m_row[2].w = 0.f;\n"
+ " for(int i=0; i<3; i++)\n"
+ " {\n"
+ "// a.m_row[i].w = 0.f;\n"
+ " ans.m_row[i].x = b3Dot3F4(a.m_row[i],transB.m_row[0]);\n"
+ " ans.m_row[i].y = b3Dot3F4(a.m_row[i],transB.m_row[1]);\n"
+ " ans.m_row[i].z = b3Dot3F4(a.m_row[i],transB.m_row[2]);\n"
+ " ans.m_row[i].w = 0.f;\n"
+ " }\n"
+ " return ans;\n"
+ "}\n"
+ "__inline\n"
+ "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)\n"
+ "{\n"
+ " b3Float4 ans;\n"
+ " ans.x = b3Dot3F4( a.m_row[0], b );\n"
+ " ans.y = b3Dot3F4( a.m_row[1], b );\n"
+ " ans.z = b3Dot3F4( a.m_row[2], b );\n"
+ " ans.w = 0.f;\n"
+ " return ans;\n"
+ "}\n"
+ "__inline\n"
+ "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)\n"
+ "{\n"
+ " b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
+ " b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
+ " b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
+ " b3Float4 ans;\n"
+ " ans.x = b3Dot3F4( a, colx );\n"
+ " ans.y = b3Dot3F4( a, coly );\n"
+ " ans.z = b3Dot3F4( a, colz );\n"
+ " return ans;\n"
+ "}\n"
+ "#endif\n"
+ "#endif //B3_MAT3x3_H\n"
+ "typedef struct b3Aabb b3Aabb_t;\n"
+ "struct b3Aabb\n"
+ "{\n"
+ " union\n"
+ " {\n"
+ " float m_min[4];\n"
+ " b3Float4 m_minVec;\n"
+ " int m_minIndices[4];\n"
+ " };\n"
+ " union\n"
+ " {\n"
+ " float m_max[4];\n"
+ " b3Float4 m_maxVec;\n"
+ " int m_signedMaxIndices[4];\n"
+ " };\n"
+ "};\n"
+ "inline void b3TransformAabb2(b3Float4ConstArg localAabbMin,b3Float4ConstArg localAabbMax, float margin,\n"
+ " b3Float4ConstArg pos,\n"
+ " b3QuatConstArg orn,\n"
+ " b3Float4* aabbMinOut,b3Float4* aabbMaxOut)\n"
+ "{\n"
+ " b3Float4 localHalfExtents = 0.5f*(localAabbMax-localAabbMin);\n"
+ " localHalfExtents+=b3MakeFloat4(margin,margin,margin,0.f);\n"
+ " b3Float4 localCenter = 0.5f*(localAabbMax+localAabbMin);\n"
+ " b3Mat3x3 m;\n"
+ " m = b3QuatGetRotationMatrix(orn);\n"
+ " b3Mat3x3 abs_b = b3AbsoluteMat3x3(m);\n"
+ " b3Float4 center = b3TransformPoint(localCenter,pos,orn);\n"
+ " \n"
+ " b3Float4 extent = b3MakeFloat4(b3Dot3F4(localHalfExtents,b3GetRow(abs_b,0)),\n"
+ " b3Dot3F4(localHalfExtents,b3GetRow(abs_b,1)),\n"
+ " b3Dot3F4(localHalfExtents,b3GetRow(abs_b,2)),\n"
+ " 0.f);\n"
+ " *aabbMinOut = center-extent;\n"
+ " *aabbMaxOut = center+extent;\n"
+ "}\n"
+ "/// conservative test for overlap between two aabbs\n"
+ "inline bool b3TestAabbAgainstAabb(b3Float4ConstArg aabbMin1,b3Float4ConstArg aabbMax1,\n"
+ " b3Float4ConstArg aabbMin2, b3Float4ConstArg aabbMax2)\n"
+ "{\n"
+ " bool overlap = true;\n"
+ " overlap = (aabbMin1.x > aabbMax2.x || aabbMax1.x < aabbMin2.x) ? false : overlap;\n"
+ " overlap = (aabbMin1.z > aabbMax2.z || aabbMax1.z < aabbMin2.z) ? false : overlap;\n"
+ " overlap = (aabbMin1.y > aabbMax2.y || aabbMax1.y < aabbMin2.y) ? false : overlap;\n"
+ " return overlap;\n"
+ "}\n"
+ "#endif //B3_AABB_H\n"
+ "/*\n"
+ "Bullet Continuous Collision Detection and Physics Library\n"
+ "Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org\n"
+ "This software is provided 'as-is', without any express or implied warranty.\n"
+ "In no event will the authors be held liable for any damages arising from the use of this software.\n"
+ "Permission is granted to anyone to use this software for any purpose,\n"
+ "including commercial applications, and to alter it and redistribute it freely,\n"
+ "subject to the following restrictions:\n"
+ "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
+ "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+ "3. This notice may not be removed or altered from any source distribution.\n"
+ "*/\n"
+ "#ifndef B3_INT2_H\n"
+ "#define B3_INT2_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#define b3UnsignedInt2 uint2\n"
+ "#define b3Int2 int2\n"
+ "#define b3MakeInt2 (int2)\n"
+ "#endif //__cplusplus\n"
+ "#endif\n"
+ "typedef struct\n"
+ "{\n"
+ " float4 m_plane;\n"
+ " int m_indexOffset;\n"
+ " int m_numIndices;\n"
+ "} btGpuFace;\n"
+ "#define make_float4 (float4)\n"
+ "__inline\n"
+ "float4 cross3(float4 a, float4 b)\n"
+ "{\n"
+ " return cross(a,b);\n"
+ " \n"
+ "// float4 a1 = make_float4(a.xyz,0.f);\n"
+ "// float4 b1 = make_float4(b.xyz,0.f);\n"
+ "// return cross(a1,b1);\n"
+ "//float4 c = make_float4(a.y*b.z - a.z*b.y,a.z*b.x - a.x*b.z,a.x*b.y - a.y*b.x,0.f);\n"
+ " \n"
+ " // float4 c = make_float4(a.y*b.z - a.z*b.y,1.f,a.x*b.y - a.y*b.x,0.f);\n"
+ " \n"
+ " //return c;\n"
+ "}\n"
+ "__inline\n"
+ "float dot3F4(float4 a, float4 b)\n"
+ "{\n"
+ " float4 a1 = make_float4(a.xyz,0.f);\n"
+ " float4 b1 = make_float4(b.xyz,0.f);\n"
+ " return dot(a1, b1);\n"
+ "}\n"
+ "__inline\n"
+ "float4 fastNormalize4(float4 v)\n"
+ "{\n"
+ " v = make_float4(v.xyz,0.f);\n"
+ " return fast_normalize(v);\n"
+ "}\n"
+ "///////////////////////////////////////\n"
+ "// Quaternion\n"
+ "///////////////////////////////////////\n"
+ "typedef float4 Quaternion;\n"
+ "__inline\n"
+ "Quaternion qtMul(Quaternion a, Quaternion b);\n"
+ "__inline\n"
+ "Quaternion qtNormalize(Quaternion in);\n"
+ "__inline\n"
+ "float4 qtRotate(Quaternion q, float4 vec);\n"
+ "__inline\n"
+ "Quaternion qtInvert(Quaternion q);\n"
+ "__inline\n"
+ "Quaternion qtMul(Quaternion a, Quaternion b)\n"
+ "{\n"
+ " Quaternion ans;\n"
+ " ans = cross3( a, b );\n"
+ " ans += a.w*b+b.w*a;\n"
+ "// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+ " ans.w = a.w*b.w - dot3F4(a, b);\n"
+ " return ans;\n"
+ "}\n"
+ "__inline\n"
+ "Quaternion qtNormalize(Quaternion in)\n"
+ "{\n"
+ " return fastNormalize4(in);\n"
+ "// in /= length( in );\n"
+ "// return in;\n"
+ "}\n"
+ "__inline\n"
+ "float4 qtRotate(Quaternion q, float4 vec)\n"
+ "{\n"
+ " Quaternion qInv = qtInvert( q );\n"
+ " float4 vcpy = vec;\n"
+ " vcpy.w = 0.f;\n"
+ " float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
+ " return out;\n"
+ "}\n"
+ "__inline\n"
+ "Quaternion qtInvert(Quaternion q)\n"
+ "{\n"
+ " return (Quaternion)(-q.xyz, q.w);\n"
+ "}\n"
+ "__inline\n"
+ "float4 qtInvRotate(const Quaternion q, float4 vec)\n"
+ "{\n"
+ " return qtRotate( qtInvert( q ), vec );\n"
+ "}\n"
+ "__inline\n"
+ "float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)\n"
+ "{\n"
+ " return qtRotate( *orientation, *p ) + (*translation);\n"
+ "}\n"
+ "__inline\n"
+ "float4 normalize3(const float4 a)\n"
+ "{\n"
+ " float4 n = make_float4(a.x, a.y, a.z, 0.f);\n"
+ " return fastNormalize4( n );\n"
+ "}\n"
+ "inline void projectLocal(const ConvexPolyhedronCL* hull, const float4 pos, const float4 orn, \n"
+ "const float4* dir, const float4* vertices, float* min, float* max)\n"
+ "{\n"
+ " min[0] = FLT_MAX;\n"
+ " max[0] = -FLT_MAX;\n"
+ " int numVerts = hull->m_numVertices;\n"
+ " const float4 localDir = qtInvRotate(orn,*dir);\n"
+ " float offset = dot(pos,*dir);\n"
+ " for(int i=0;i<numVerts;i++)\n"
+ " {\n"
+ " float dp = dot(vertices[hull->m_vertexOffset+i],localDir);\n"
+ " if(dp < min[0]) \n"
+ " min[0] = dp;\n"
+ " if(dp > max[0]) \n"
+ " max[0] = dp;\n"
+ " }\n"
+ " if(min[0]>max[0])\n"
+ " {\n"
+ " float tmp = min[0];\n"
+ " min[0] = max[0];\n"
+ " max[0] = tmp;\n"
+ " }\n"
+ " min[0] += offset;\n"
+ " max[0] += offset;\n"
+ "}\n"
+ "inline void project(__global const ConvexPolyhedronCL* hull, const float4 pos, const float4 orn, \n"
+ "const float4* dir, __global const float4* vertices, float* min, float* max)\n"
+ "{\n"
+ " min[0] = FLT_MAX;\n"
+ " max[0] = -FLT_MAX;\n"
+ " int numVerts = hull->m_numVertices;\n"
+ " const float4 localDir = qtInvRotate(orn,*dir);\n"
+ " float offset = dot(pos,*dir);\n"
+ " for(int i=0;i<numVerts;i++)\n"
+ " {\n"
+ " float dp = dot(vertices[hull->m_vertexOffset+i],localDir);\n"
+ " if(dp < min[0]) \n"
+ " min[0] = dp;\n"
+ " if(dp > max[0]) \n"
+ " max[0] = dp;\n"
+ " }\n"
+ " if(min[0]>max[0])\n"
+ " {\n"
+ " float tmp = min[0];\n"
+ " min[0] = max[0];\n"
+ " max[0] = tmp;\n"
+ " }\n"
+ " min[0] += offset;\n"
+ " max[0] += offset;\n"
+ "}\n"
+ "inline bool TestSepAxisLocalA(const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
+ " const float4 posA,const float4 ornA,\n"
+ " const float4 posB,const float4 ornB,\n"
+ " float4* sep_axis, const float4* verticesA, __global const float4* verticesB,float* depth)\n"
+ "{\n"
+ " float Min0,Max0;\n"
+ " float Min1,Max1;\n"
+ " projectLocal(hullA,posA,ornA,sep_axis,verticesA, &Min0, &Max0);\n"
+ " project(hullB,posB,ornB, sep_axis,verticesB, &Min1, &Max1);\n"
+ " if(Max0<Min1 || Max1<Min0)\n"
+ " return false;\n"
+ " float d0 = Max0 - Min1;\n"
+ " float d1 = Max1 - Min0;\n"
+ " *depth = d0<d1 ? d0:d1;\n"
+ " return true;\n"
+ "}\n"
+ "inline bool IsAlmostZero(const float4 v)\n"
+ "{\n"
+ " if(fabs(v.x)>1e-6f || fabs(v.y)>1e-6f || fabs(v.z)>1e-6f)\n"
+ " return false;\n"
+ " return true;\n"
+ "}\n"
+ "bool findSeparatingAxisLocalA( const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
+ " const float4 posA1,\n"
+ " const float4 ornA,\n"
+ " const float4 posB1,\n"
+ " const float4 ornB,\n"
+ " const float4 DeltaC2,\n"
+ " \n"
+ " const float4* verticesA, \n"
+ " const float4* uniqueEdgesA, \n"
+ " const btGpuFace* facesA,\n"
+ " const int* indicesA,\n"
+ " __global const float4* verticesB, \n"
+ " __global const float4* uniqueEdgesB, \n"
+ " __global const btGpuFace* facesB,\n"
+ " __global const int* indicesB,\n"
+ " float4* sep,\n"
+ " float* dmin)\n"
+ "{\n"
+ " \n"
+ " float4 posA = posA1;\n"
+ " posA.w = 0.f;\n"
+ " float4 posB = posB1;\n"
+ " posB.w = 0.f;\n"
+ " int curPlaneTests=0;\n"
+ " {\n"
+ " int numFacesA = hullA->m_numFaces;\n"
+ " // Test normals from hullA\n"
+ " for(int i=0;i<numFacesA;i++)\n"
+ " {\n"
+ " const float4 normal = facesA[hullA->m_faceOffset+i].m_plane;\n"
+ " float4 faceANormalWS = qtRotate(ornA,normal);\n"
+ " if (dot3F4(DeltaC2,faceANormalWS)<0)\n"
+ " faceANormalWS*=-1.f;\n"
+ " curPlaneTests++;\n"
+ " float d;\n"
+ " if(!TestSepAxisLocalA( hullA, hullB, posA,ornA,posB,ornB,&faceANormalWS, verticesA, verticesB,&d))\n"
+ " return false;\n"
+ " if(d<*dmin)\n"
+ " {\n"
+ " *dmin = d;\n"
+ " *sep = faceANormalWS;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
+ " {\n"
+ " *sep = -(*sep);\n"
+ " }\n"
+ " return true;\n"
+ "}\n"
+ "bool findSeparatingAxisLocalB( __global const ConvexPolyhedronCL* hullA, const ConvexPolyhedronCL* hullB, \n"
+ " const float4 posA1,\n"
+ " const float4 ornA,\n"
+ " const float4 posB1,\n"
+ " const float4 ornB,\n"
+ " const float4 DeltaC2,\n"
+ " __global const float4* verticesA, \n"
+ " __global const float4* uniqueEdgesA, \n"
+ " __global const btGpuFace* facesA,\n"
+ " __global const int* indicesA,\n"
+ " const float4* verticesB,\n"
+ " const float4* uniqueEdgesB, \n"
+ " const btGpuFace* facesB,\n"
+ " const int* indicesB,\n"
+ " float4* sep,\n"
+ " float* dmin)\n"
+ "{\n"
+ " float4 posA = posA1;\n"
+ " posA.w = 0.f;\n"
+ " float4 posB = posB1;\n"
+ " posB.w = 0.f;\n"
+ " int curPlaneTests=0;\n"
+ " {\n"
+ " int numFacesA = hullA->m_numFaces;\n"
+ " // Test normals from hullA\n"
+ " for(int i=0;i<numFacesA;i++)\n"
+ " {\n"
+ " const float4 normal = facesA[hullA->m_faceOffset+i].m_plane;\n"
+ " float4 faceANormalWS = qtRotate(ornA,normal);\n"
+ " if (dot3F4(DeltaC2,faceANormalWS)<0)\n"
+ " faceANormalWS *= -1.f;\n"
+ " curPlaneTests++;\n"
+ " float d;\n"
+ " if(!TestSepAxisLocalA( hullB, hullA, posB,ornB,posA,ornA, &faceANormalWS, verticesB,verticesA, &d))\n"
+ " return false;\n"
+ " if(d<*dmin)\n"
+ " {\n"
+ " *dmin = d;\n"
+ " *sep = faceANormalWS;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
+ " {\n"
+ " *sep = -(*sep);\n"
+ " }\n"
+ " return true;\n"
+ "}\n"
+ "bool findSeparatingAxisEdgeEdgeLocalA( const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
+ " const float4 posA1,\n"
+ " const float4 ornA,\n"
+ " const float4 posB1,\n"
+ " const float4 ornB,\n"
+ " const float4 DeltaC2,\n"
+ " const float4* verticesA, \n"
+ " const float4* uniqueEdgesA, \n"
+ " const btGpuFace* facesA,\n"
+ " const int* indicesA,\n"
+ " __global const float4* verticesB, \n"
+ " __global const float4* uniqueEdgesB, \n"
+ " __global const btGpuFace* facesB,\n"
+ " __global const int* indicesB,\n"
+ " float4* sep,\n"
+ " float* dmin)\n"
+ "{\n"
+ " float4 posA = posA1;\n"
+ " posA.w = 0.f;\n"
+ " float4 posB = posB1;\n"
+ " posB.w = 0.f;\n"
+ " int curPlaneTests=0;\n"
+ " int curEdgeEdge = 0;\n"
+ " // Test edges\n"
+ " for(int e0=0;e0<hullA->m_numUniqueEdges;e0++)\n"
+ " {\n"
+ " const float4 edge0 = uniqueEdgesA[hullA->m_uniqueEdgesOffset+e0];\n"
+ " float4 edge0World = qtRotate(ornA,edge0);\n"
+ " for(int e1=0;e1<hullB->m_numUniqueEdges;e1++)\n"
+ " {\n"
+ " const float4 edge1 = uniqueEdgesB[hullB->m_uniqueEdgesOffset+e1];\n"
+ " float4 edge1World = qtRotate(ornB,edge1);\n"
+ " float4 crossje = cross3(edge0World,edge1World);\n"
+ " curEdgeEdge++;\n"
+ " if(!IsAlmostZero(crossje))\n"
+ " {\n"
+ " crossje = normalize3(crossje);\n"
+ " if (dot3F4(DeltaC2,crossje)<0)\n"
+ " crossje *= -1.f;\n"
+ " float dist;\n"
+ " bool result = true;\n"
+ " {\n"
+ " float Min0,Max0;\n"
+ " float Min1,Max1;\n"
+ " projectLocal(hullA,posA,ornA,&crossje,verticesA, &Min0, &Max0);\n"
+ " project(hullB,posB,ornB,&crossje,verticesB, &Min1, &Max1);\n"
+ " \n"
+ " if(Max0<Min1 || Max1<Min0)\n"
+ " result = false;\n"
+ " \n"
+ " float d0 = Max0 - Min1;\n"
+ " float d1 = Max1 - Min0;\n"
+ " dist = d0<d1 ? d0:d1;\n"
+ " result = true;\n"
+ " }\n"
+ " \n"
+ " if(dist<*dmin)\n"
+ " {\n"
+ " *dmin = dist;\n"
+ " *sep = crossje;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " \n"
+ " if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
+ " {\n"
+ " *sep = -(*sep);\n"
+ " }\n"
+ " return true;\n"
+ "}\n"
+ "inline bool TestSepAxis(__global const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
+ " const float4 posA,const float4 ornA,\n"
+ " const float4 posB,const float4 ornB,\n"
+ " float4* sep_axis, __global const float4* vertices,float* depth)\n"
+ "{\n"
+ " float Min0,Max0;\n"
+ " float Min1,Max1;\n"
+ " project(hullA,posA,ornA,sep_axis,vertices, &Min0, &Max0);\n"
+ " project(hullB,posB,ornB, sep_axis,vertices, &Min1, &Max1);\n"
+ " if(Max0<Min1 || Max1<Min0)\n"
+ " return false;\n"
+ " float d0 = Max0 - Min1;\n"
+ " float d1 = Max1 - Min0;\n"
+ " *depth = d0<d1 ? d0:d1;\n"
+ " return true;\n"
+ "}\n"
+ "bool findSeparatingAxis( __global const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
+ " const float4 posA1,\n"
+ " const float4 ornA,\n"
+ " const float4 posB1,\n"
+ " const float4 ornB,\n"
+ " const float4 DeltaC2,\n"
+ " __global const float4* vertices, \n"
+ " __global const float4* uniqueEdges, \n"
+ " __global const btGpuFace* faces,\n"
+ " __global const int* indices,\n"
+ " float4* sep,\n"
+ " float* dmin)\n"
+ "{\n"
+ " \n"
+ " float4 posA = posA1;\n"
+ " posA.w = 0.f;\n"
+ " float4 posB = posB1;\n"
+ " posB.w = 0.f;\n"
+ " \n"
+ " int curPlaneTests=0;\n"
+ " {\n"
+ " int numFacesA = hullA->m_numFaces;\n"
+ " // Test normals from hullA\n"
+ " for(int i=0;i<numFacesA;i++)\n"
+ " {\n"
+ " const float4 normal = faces[hullA->m_faceOffset+i].m_plane;\n"
+ " float4 faceANormalWS = qtRotate(ornA,normal);\n"
+ " \n"
+ " if (dot3F4(DeltaC2,faceANormalWS)<0)\n"
+ " faceANormalWS*=-1.f;\n"
+ " \n"
+ " curPlaneTests++;\n"
+ " \n"
+ " float d;\n"
+ " if(!TestSepAxis( hullA, hullB, posA,ornA,posB,ornB,&faceANormalWS, vertices,&d))\n"
+ " return false;\n"
+ " \n"
+ " if(d<*dmin)\n"
+ " {\n"
+ " *dmin = d;\n"
+ " *sep = faceANormalWS;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
+ " {\n"
+ " *sep = -(*sep);\n"
+ " }\n"
+ " \n"
+ " return true;\n"
+ "}\n"
+ "bool findSeparatingAxisUnitSphere( __global const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
+ " const float4 posA1,\n"
+ " const float4 ornA,\n"
+ " const float4 posB1,\n"
+ " const float4 ornB,\n"
+ " const float4 DeltaC2,\n"
+ " __global const float4* vertices,\n"
+ " __global const float4* unitSphereDirections,\n"
+ " int numUnitSphereDirections,\n"
+ " float4* sep,\n"
+ " float* dmin)\n"
+ "{\n"
+ " \n"
+ " float4 posA = posA1;\n"
+ " posA.w = 0.f;\n"
+ " float4 posB = posB1;\n"
+ " posB.w = 0.f;\n"
+ " int curPlaneTests=0;\n"
+ " int curEdgeEdge = 0;\n"
+ " // Test unit sphere directions\n"
+ " for (int i=0;i<numUnitSphereDirections;i++)\n"
+ " {\n"
+ " float4 crossje;\n"
+ " crossje = unitSphereDirections[i]; \n"
+ " if (dot3F4(DeltaC2,crossje)>0)\n"
+ " crossje *= -1.f;\n"
+ " {\n"
+ " float dist;\n"
+ " bool result = true;\n"
+ " float Min0,Max0;\n"
+ " float Min1,Max1;\n"
+ " project(hullA,posA,ornA,&crossje,vertices, &Min0, &Max0);\n"
+ " project(hullB,posB,ornB,&crossje,vertices, &Min1, &Max1);\n"
+ " \n"
+ " if(Max0<Min1 || Max1<Min0)\n"
+ " return false;\n"
+ " \n"
+ " float d0 = Max0 - Min1;\n"
+ " float d1 = Max1 - Min0;\n"
+ " dist = d0<d1 ? d0:d1;\n"
+ " result = true;\n"
+ " \n"
+ " if(dist<*dmin)\n"
+ " {\n"
+ " *dmin = dist;\n"
+ " *sep = crossje;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " \n"
+ " if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
+ " {\n"
+ " *sep = -(*sep);\n"
+ " }\n"
+ " return true;\n"
+ "}\n"
+ "bool findSeparatingAxisEdgeEdge( __global const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
+ " const float4 posA1,\n"
+ " const float4 ornA,\n"
+ " const float4 posB1,\n"
+ " const float4 ornB,\n"
+ " const float4 DeltaC2,\n"
+ " __global const float4* vertices, \n"
+ " __global const float4* uniqueEdges, \n"
+ " __global const btGpuFace* faces,\n"
+ " __global const int* indices,\n"
+ " float4* sep,\n"
+ " float* dmin)\n"
+ "{\n"
+ " \n"
+ " float4 posA = posA1;\n"
+ " posA.w = 0.f;\n"
+ " float4 posB = posB1;\n"
+ " posB.w = 0.f;\n"
+ " int curPlaneTests=0;\n"
+ " int curEdgeEdge = 0;\n"
+ " // Test edges\n"
+ " for(int e0=0;e0<hullA->m_numUniqueEdges;e0++)\n"
+ " {\n"
+ " const float4 edge0 = uniqueEdges[hullA->m_uniqueEdgesOffset+e0];\n"
+ " float4 edge0World = qtRotate(ornA,edge0);\n"
+ " for(int e1=0;e1<hullB->m_numUniqueEdges;e1++)\n"
+ " {\n"
+ " const float4 edge1 = uniqueEdges[hullB->m_uniqueEdgesOffset+e1];\n"
+ " float4 edge1World = qtRotate(ornB,edge1);\n"
+ " float4 crossje = cross3(edge0World,edge1World);\n"
+ " curEdgeEdge++;\n"
+ " if(!IsAlmostZero(crossje))\n"
+ " {\n"
+ " crossje = normalize3(crossje);\n"
+ " if (dot3F4(DeltaC2,crossje)<0)\n"
+ " crossje*=-1.f;\n"
+ " \n"
+ " float dist;\n"
+ " bool result = true;\n"
+ " {\n"
+ " float Min0,Max0;\n"
+ " float Min1,Max1;\n"
+ " project(hullA,posA,ornA,&crossje,vertices, &Min0, &Max0);\n"
+ " project(hullB,posB,ornB,&crossje,vertices, &Min1, &Max1);\n"
+ " \n"
+ " if(Max0<Min1 || Max1<Min0)\n"
+ " return false;\n"
+ " \n"
+ " float d0 = Max0 - Min1;\n"
+ " float d1 = Max1 - Min0;\n"
+ " dist = d0<d1 ? d0:d1;\n"
+ " result = true;\n"
+ " }\n"
+ " \n"
+ " if(dist<*dmin)\n"
+ " {\n"
+ " *dmin = dist;\n"
+ " *sep = crossje;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " \n"
+ " if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
+ " {\n"
+ " *sep = -(*sep);\n"
+ " }\n"
+ " return true;\n"
+ "}\n"
+ "// work-in-progress\n"
+ "__kernel void processCompoundPairsKernel( __global const int4* gpuCompoundPairs,\n"
+ " __global const BodyData* rigidBodies, \n"
+ " __global const btCollidableGpu* collidables,\n"
+ " __global const ConvexPolyhedronCL* convexShapes, \n"
+ " __global const float4* vertices,\n"
+ " __global const float4* uniqueEdges,\n"
+ " __global const btGpuFace* faces,\n"
+ " __global const int* indices,\n"
+ " __global btAabbCL* aabbs,\n"
+ " __global const btGpuChildShape* gpuChildShapes,\n"
+ " __global volatile float4* gpuCompoundSepNormalsOut,\n"
+ " __global volatile int* gpuHasCompoundSepNormalsOut,\n"
+ " int numCompoundPairs\n"
+ " )\n"
+ "{\n"
+ " int i = get_global_id(0);\n"
+ " if (i<numCompoundPairs)\n"
+ " {\n"
+ " int bodyIndexA = gpuCompoundPairs[i].x;\n"
+ " int bodyIndexB = gpuCompoundPairs[i].y;\n"
+ " int childShapeIndexA = gpuCompoundPairs[i].z;\n"
+ " int childShapeIndexB = gpuCompoundPairs[i].w;\n"
+ " \n"
+ " int collidableIndexA = -1;\n"
+ " int collidableIndexB = -1;\n"
+ " \n"
+ " float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
+ " float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+ " \n"
+ " float4 ornB = rigidBodies[bodyIndexB].m_quat;\n"
+ " float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+ " \n"
+ " if (childShapeIndexA >= 0)\n"
+ " {\n"
+ " collidableIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;\n"
+ " float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;\n"
+ " float4 childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;\n"
+ " float4 newPosA = qtRotate(ornA,childPosA)+posA;\n"
+ " float4 newOrnA = qtMul(ornA,childOrnA);\n"
+ " posA = newPosA;\n"
+ " ornA = newOrnA;\n"
+ " } else\n"
+ " {\n"
+ " collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+ " }\n"
+ " \n"
+ " if (childShapeIndexB>=0)\n"
+ " {\n"
+ " collidableIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
+ " float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
+ " float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
+ " float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
+ " float4 newOrnB = qtMul(ornB,childOrnB);\n"
+ " posB = newPosB;\n"
+ " ornB = newOrnB;\n"
+ " } else\n"
+ " {\n"
+ " collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx; \n"
+ " }\n"
+ " \n"
+ " gpuHasCompoundSepNormalsOut[i] = 0;\n"
+ " \n"
+ " int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+ " int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+ " \n"
+ " int shapeTypeA = collidables[collidableIndexA].m_shapeType;\n"
+ " int shapeTypeB = collidables[collidableIndexB].m_shapeType;\n"
+ " \n"
+ " if ((shapeTypeA != SHAPE_CONVEX_HULL) || (shapeTypeB != SHAPE_CONVEX_HULL))\n"
+ " {\n"
+ " return;\n"
+ " }\n"
+ " int hasSeparatingAxis = 5;\n"
+ " \n"
+ " int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
+ " float dmin = FLT_MAX;\n"
+ " posA.w = 0.f;\n"
+ " posB.w = 0.f;\n"
+ " float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
+ " float4 c0 = transform(&c0local, &posA, &ornA);\n"
+ " float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
+ " float4 c1 = transform(&c1local,&posB,&ornB);\n"
+ " const float4 DeltaC2 = c0 - c1;\n"
+ " float4 sepNormal = make_float4(1,0,0,0);\n"
+ " bool sepA = findSeparatingAxis( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,posB,ornB,DeltaC2,vertices,uniqueEdges,faces,indices,&sepNormal,&dmin);\n"
+ " hasSeparatingAxis = 4;\n"
+ " if (!sepA)\n"
+ " {\n"
+ " hasSeparatingAxis = 0;\n"
+ " } else\n"
+ " {\n"
+ " bool sepB = findSeparatingAxis( &convexShapes[shapeIndexB],&convexShapes[shapeIndexA],posB,ornB,posA,ornA,DeltaC2,vertices,uniqueEdges,faces,indices,&sepNormal,&dmin);\n"
+ " if (!sepB)\n"
+ " {\n"
+ " hasSeparatingAxis = 0;\n"
+ " } else//(!sepB)\n"
+ " {\n"
+ " bool sepEE = findSeparatingAxisEdgeEdge( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,posB,ornB,DeltaC2,vertices,uniqueEdges,faces,indices,&sepNormal,&dmin);\n"
+ " if (sepEE)\n"
+ " {\n"
+ " gpuCompoundSepNormalsOut[i] = sepNormal;//fastNormalize4(sepNormal);\n"
+ " gpuHasCompoundSepNormalsOut[i] = 1;\n"
+ " }//sepEE\n"
+ " }//(!sepB)\n"
+ " }//(!sepA)\n"
+ " \n"
+ " \n"
+ " }\n"
+ " \n"
+ "}\n"
+ "inline b3Float4 MyUnQuantize(const unsigned short* vecIn, b3Float4 quantization, b3Float4 bvhAabbMin)\n"
+ "{\n"
+ " b3Float4 vecOut;\n"
+ " vecOut = b3MakeFloat4(\n"
+ " (float)(vecIn[0]) / (quantization.x),\n"
+ " (float)(vecIn[1]) / (quantization.y),\n"
+ " (float)(vecIn[2]) / (quantization.z),\n"
+ " 0.f);\n"
+ " vecOut += bvhAabbMin;\n"
+ " return vecOut;\n"
+ "}\n"
+ "inline b3Float4 MyUnQuantizeGlobal(__global const unsigned short* vecIn, b3Float4 quantization, b3Float4 bvhAabbMin)\n"
+ "{\n"
+ " b3Float4 vecOut;\n"
+ " vecOut = b3MakeFloat4(\n"
+ " (float)(vecIn[0]) / (quantization.x),\n"
+ " (float)(vecIn[1]) / (quantization.y),\n"
+ " (float)(vecIn[2]) / (quantization.z),\n"
+ " 0.f);\n"
+ " vecOut += bvhAabbMin;\n"
+ " return vecOut;\n"
+ "}\n"
+ "// work-in-progress\n"
+ "__kernel void findCompoundPairsKernel( __global const int4* pairs, \n"
+ " __global const BodyData* rigidBodies, \n"
+ " __global const btCollidableGpu* collidables,\n"
+ " __global const ConvexPolyhedronCL* convexShapes, \n"
+ " __global const float4* vertices,\n"
+ " __global const float4* uniqueEdges,\n"
+ " __global const btGpuFace* faces,\n"
+ " __global const int* indices,\n"
+ " __global b3Aabb_t* aabbLocalSpace,\n"
+ " __global const btGpuChildShape* gpuChildShapes,\n"
+ " __global volatile int4* gpuCompoundPairsOut,\n"
+ " __global volatile int* numCompoundPairsOut,\n"
+ " __global const b3BvhSubtreeInfo* subtrees,\n"
+ " __global const b3QuantizedBvhNode* quantizedNodes,\n"
+ " __global const b3BvhInfo* bvhInfos,\n"
+ " int numPairs,\n"
+ " int maxNumCompoundPairsCapacity\n"
+ " )\n"
+ "{\n"
+ " int i = get_global_id(0);\n"
+ " if (i<numPairs)\n"
+ " {\n"
+ " int bodyIndexA = pairs[i].x;\n"
+ " int bodyIndexB = pairs[i].y;\n"
+ " int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+ " int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+ " int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+ " int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+ " //once the broadphase avoids static-static pairs, we can remove this test\n"
+ " if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))\n"
+ " {\n"
+ " return;\n"
+ " }\n"
+ " if ((collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS) &&(collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))\n"
+ " {\n"
+ " int bvhA = collidables[collidableIndexA].m_compoundBvhIndex;\n"
+ " int bvhB = collidables[collidableIndexB].m_compoundBvhIndex;\n"
+ " int numSubTreesA = bvhInfos[bvhA].m_numSubTrees;\n"
+ " int subTreesOffsetA = bvhInfos[bvhA].m_subTreeOffset;\n"
+ " int subTreesOffsetB = bvhInfos[bvhB].m_subTreeOffset;\n"
+ " int numSubTreesB = bvhInfos[bvhB].m_numSubTrees;\n"
+ " \n"
+ " float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+ " b3Quat ornA = rigidBodies[bodyIndexA].m_quat;\n"
+ " b3Quat ornB = rigidBodies[bodyIndexB].m_quat;\n"
+ " float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+ " \n"
+ " for (int p=0;p<numSubTreesA;p++)\n"
+ " {\n"
+ " b3BvhSubtreeInfo subtreeA = subtrees[subTreesOffsetA+p];\n"
+ " //bvhInfos[bvhA].m_quantization\n"
+ " b3Float4 treeAminLocal = MyUnQuantize(subtreeA.m_quantizedAabbMin,bvhInfos[bvhA].m_quantization,bvhInfos[bvhA].m_aabbMin);\n"
+ " b3Float4 treeAmaxLocal = MyUnQuantize(subtreeA.m_quantizedAabbMax,bvhInfos[bvhA].m_quantization,bvhInfos[bvhA].m_aabbMin);\n"
+ " b3Float4 aabbAMinOut,aabbAMaxOut;\n"
+ " float margin=0.f;\n"
+ " b3TransformAabb2(treeAminLocal,treeAmaxLocal, margin,posA,ornA,&aabbAMinOut,&aabbAMaxOut);\n"
+ " \n"
+ " for (int q=0;q<numSubTreesB;q++)\n"
+ " {\n"
+ " b3BvhSubtreeInfo subtreeB = subtrees[subTreesOffsetB+q];\n"
+ " b3Float4 treeBminLocal = MyUnQuantize(subtreeB.m_quantizedAabbMin,bvhInfos[bvhB].m_quantization,bvhInfos[bvhB].m_aabbMin);\n"
+ " b3Float4 treeBmaxLocal = MyUnQuantize(subtreeB.m_quantizedAabbMax,bvhInfos[bvhB].m_quantization,bvhInfos[bvhB].m_aabbMin);\n"
+ " b3Float4 aabbBMinOut,aabbBMaxOut;\n"
+ " float margin=0.f;\n"
+ " b3TransformAabb2(treeBminLocal,treeBmaxLocal, margin,posB,ornB,&aabbBMinOut,&aabbBMaxOut);\n"
+ " \n"
+ " \n"
+ " bool aabbOverlap = b3TestAabbAgainstAabb(aabbAMinOut,aabbAMaxOut,aabbBMinOut,aabbBMaxOut);\n"
+ " if (aabbOverlap)\n"
+ " {\n"
+ " \n"
+ " int startNodeIndexA = subtreeA.m_rootNodeIndex+bvhInfos[bvhA].m_nodeOffset;\n"
+ " int endNodeIndexA = startNodeIndexA+subtreeA.m_subtreeSize;\n"
+ " int startNodeIndexB = subtreeB.m_rootNodeIndex+bvhInfos[bvhB].m_nodeOffset;\n"
+ " int endNodeIndexB = startNodeIndexB+subtreeB.m_subtreeSize;\n"
+ " b3Int2 nodeStack[B3_MAX_STACK_DEPTH];\n"
+ " b3Int2 node0;\n"
+ " node0.x = startNodeIndexA;\n"
+ " node0.y = startNodeIndexB;\n"
+ " int maxStackDepth = B3_MAX_STACK_DEPTH;\n"
+ " int depth=0;\n"
+ " nodeStack[depth++]=node0;\n"
+ " do\n"
+ " {\n"
+ " b3Int2 node = nodeStack[--depth];\n"
+ " b3Float4 aMinLocal = MyUnQuantizeGlobal(quantizedNodes[node.x].m_quantizedAabbMin,bvhInfos[bvhA].m_quantization,bvhInfos[bvhA].m_aabbMin);\n"
+ " b3Float4 aMaxLocal = MyUnQuantizeGlobal(quantizedNodes[node.x].m_quantizedAabbMax,bvhInfos[bvhA].m_quantization,bvhInfos[bvhA].m_aabbMin);\n"
+ " b3Float4 bMinLocal = MyUnQuantizeGlobal(quantizedNodes[node.y].m_quantizedAabbMin,bvhInfos[bvhB].m_quantization,bvhInfos[bvhB].m_aabbMin);\n"
+ " b3Float4 bMaxLocal = MyUnQuantizeGlobal(quantizedNodes[node.y].m_quantizedAabbMax,bvhInfos[bvhB].m_quantization,bvhInfos[bvhB].m_aabbMin);\n"
+ " float margin=0.f;\n"
+ " b3Float4 aabbAMinOut,aabbAMaxOut;\n"
+ " b3TransformAabb2(aMinLocal,aMaxLocal, margin,posA,ornA,&aabbAMinOut,&aabbAMaxOut);\n"
+ " b3Float4 aabbBMinOut,aabbBMaxOut;\n"
+ " b3TransformAabb2(bMinLocal,bMaxLocal, margin,posB,ornB,&aabbBMinOut,&aabbBMaxOut);\n"
+ " \n"
+ " bool nodeOverlap = b3TestAabbAgainstAabb(aabbAMinOut,aabbAMaxOut,aabbBMinOut,aabbBMaxOut);\n"
+ " if (nodeOverlap)\n"
+ " {\n"
+ " bool isLeafA = isLeafNodeGlobal(&quantizedNodes[node.x]);\n"
+ " bool isLeafB = isLeafNodeGlobal(&quantizedNodes[node.y]);\n"
+ " bool isInternalA = !isLeafA;\n"
+ " bool isInternalB = !isLeafB;\n"
+ " //fail, even though it might hit two leaf nodes\n"
+ " if (depth+4>maxStackDepth && !(isLeafA && isLeafB))\n"
+ " {\n"
+ " //printf(\"Error: traversal exceeded maxStackDepth\");\n"
+ " continue;\n"
+ " }\n"
+ " if(isInternalA)\n"
+ " {\n"
+ " int nodeAleftChild = node.x+1;\n"
+ " bool isNodeALeftChildLeaf = isLeafNodeGlobal(&quantizedNodes[node.x+1]);\n"
+ " int nodeArightChild = isNodeALeftChildLeaf? node.x+2 : node.x+1 + getEscapeIndexGlobal(&quantizedNodes[node.x+1]);\n"
+ " if(isInternalB)\n"
+ " { \n"
+ " int nodeBleftChild = node.y+1;\n"
+ " bool isNodeBLeftChildLeaf = isLeafNodeGlobal(&quantizedNodes[node.y+1]);\n"
+ " int nodeBrightChild = isNodeBLeftChildLeaf? node.y+2 : node.y+1 + getEscapeIndexGlobal(&quantizedNodes[node.y+1]);\n"
+ " nodeStack[depth++] = b3MakeInt2(nodeAleftChild, nodeBleftChild);\n"
+ " nodeStack[depth++] = b3MakeInt2(nodeArightChild, nodeBleftChild);\n"
+ " nodeStack[depth++] = b3MakeInt2(nodeAleftChild, nodeBrightChild);\n"
+ " nodeStack[depth++] = b3MakeInt2(nodeArightChild, nodeBrightChild);\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " nodeStack[depth++] = b3MakeInt2(nodeAleftChild,node.y);\n"
+ " nodeStack[depth++] = b3MakeInt2(nodeArightChild,node.y);\n"
+ " }\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " if(isInternalB)\n"
+ " {\n"
+ " int nodeBleftChild = node.y+1;\n"
+ " bool isNodeBLeftChildLeaf = isLeafNodeGlobal(&quantizedNodes[node.y+1]);\n"
+ " int nodeBrightChild = isNodeBLeftChildLeaf? node.y+2 : node.y+1 + getEscapeIndexGlobal(&quantizedNodes[node.y+1]);\n"
+ " nodeStack[depth++] = b3MakeInt2(node.x,nodeBleftChild);\n"
+ " nodeStack[depth++] = b3MakeInt2(node.x,nodeBrightChild);\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " int compoundPairIdx = atomic_inc(numCompoundPairsOut);\n"
+ " if (compoundPairIdx<maxNumCompoundPairsCapacity)\n"
+ " {\n"
+ " int childShapeIndexA = getTriangleIndexGlobal(&quantizedNodes[node.x]);\n"
+ " int childShapeIndexB = getTriangleIndexGlobal(&quantizedNodes[node.y]);\n"
+ " gpuCompoundPairsOut[compoundPairIdx] = (int4)(bodyIndexA,bodyIndexB,childShapeIndexA,childShapeIndexB);\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " } while (depth);\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " \n"
+ " return;\n"
+ " }\n"
+ " if ((collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS) ||(collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))\n"
+ " {\n"
+ " if (collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS) \n"
+ " {\n"
+ " int numChildrenA = collidables[collidableIndexA].m_numChildShapes;\n"
+ " for (int c=0;c<numChildrenA;c++)\n"
+ " {\n"
+ " int childShapeIndexA = collidables[collidableIndexA].m_shapeIndex+c;\n"
+ " int childColIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;\n"
+ " float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+ " float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
+ " float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;\n"
+ " float4 childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;\n"
+ " float4 newPosA = qtRotate(ornA,childPosA)+posA;\n"
+ " float4 newOrnA = qtMul(ornA,childOrnA);\n"
+ " int shapeIndexA = collidables[childColIndexA].m_shapeIndex;\n"
+ " b3Aabb_t aabbAlocal = aabbLocalSpace[shapeIndexA];\n"
+ " float margin = 0.f;\n"
+ " \n"
+ " b3Float4 aabbAMinWS;\n"
+ " b3Float4 aabbAMaxWS;\n"
+ " \n"
+ " b3TransformAabb2(aabbAlocal.m_minVec,aabbAlocal.m_maxVec,margin,\n"
+ " newPosA,\n"
+ " newOrnA,\n"
+ " &aabbAMinWS,&aabbAMaxWS);\n"
+ " \n"
+ " \n"
+ " if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
+ " {\n"
+ " int numChildrenB = collidables[collidableIndexB].m_numChildShapes;\n"
+ " for (int b=0;b<numChildrenB;b++)\n"
+ " {\n"
+ " int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex+b;\n"
+ " int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
+ " float4 ornB = rigidBodies[bodyIndexB].m_quat;\n"
+ " float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+ " float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
+ " float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
+ " float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
+ " float4 newOrnB = qtMul(ornB,childOrnB);\n"
+ " int shapeIndexB = collidables[childColIndexB].m_shapeIndex;\n"
+ " b3Aabb_t aabbBlocal = aabbLocalSpace[shapeIndexB];\n"
+ " \n"
+ " b3Float4 aabbBMinWS;\n"
+ " b3Float4 aabbBMaxWS;\n"
+ " \n"
+ " b3TransformAabb2(aabbBlocal.m_minVec,aabbBlocal.m_maxVec,margin,\n"
+ " newPosB,\n"
+ " newOrnB,\n"
+ " &aabbBMinWS,&aabbBMaxWS);\n"
+ " \n"
+ " \n"
+ " \n"
+ " bool aabbOverlap = b3TestAabbAgainstAabb(aabbAMinWS,aabbAMaxWS,aabbBMinWS,aabbBMaxWS);\n"
+ " if (aabbOverlap)\n"
+ " {\n"
+ " int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
+ " float dmin = FLT_MAX;\n"
+ " float4 posA = newPosA;\n"
+ " posA.w = 0.f;\n"
+ " float4 posB = newPosB;\n"
+ " posB.w = 0.f;\n"
+ " float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
+ " float4 ornA = newOrnA;\n"
+ " float4 c0 = transform(&c0local, &posA, &ornA);\n"
+ " float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
+ " float4 ornB =newOrnB;\n"
+ " float4 c1 = transform(&c1local,&posB,&ornB);\n"
+ " const float4 DeltaC2 = c0 - c1;\n"
+ " {//\n"
+ " int compoundPairIdx = atomic_inc(numCompoundPairsOut);\n"
+ " if (compoundPairIdx<maxNumCompoundPairsCapacity)\n"
+ " {\n"
+ " gpuCompoundPairsOut[compoundPairIdx] = (int4)(bodyIndexA,bodyIndexB,childShapeIndexA,childShapeIndexB);\n"
+ " }\n"
+ " }//\n"
+ " }//fi(1)\n"
+ " } //for (int b=0\n"
+ " }//if (collidables[collidableIndexB].\n"
+ " else//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
+ " {\n"
+ " if (1)\n"
+ " {\n"
+ " int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
+ " float dmin = FLT_MAX;\n"
+ " float4 posA = newPosA;\n"
+ " posA.w = 0.f;\n"
+ " float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+ " posB.w = 0.f;\n"
+ " float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
+ " float4 ornA = newOrnA;\n"
+ " float4 c0 = transform(&c0local, &posA, &ornA);\n"
+ " float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
+ " float4 ornB = rigidBodies[bodyIndexB].m_quat;\n"
+ " float4 c1 = transform(&c1local,&posB,&ornB);\n"
+ " const float4 DeltaC2 = c0 - c1;\n"
+ " {\n"
+ " int compoundPairIdx = atomic_inc(numCompoundPairsOut);\n"
+ " if (compoundPairIdx<maxNumCompoundPairsCapacity)\n"
+ " {\n"
+ " gpuCompoundPairsOut[compoundPairIdx] = (int4)(bodyIndexA,bodyIndexB,childShapeIndexA,-1);\n"
+ " }//if (compoundPairIdx<maxNumCompoundPairsCapacity)\n"
+ " }//\n"
+ " }//fi (1)\n"
+ " }//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
+ " }//for (int b=0;b<numChildrenB;b++) \n"
+ " return;\n"
+ " }//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
+ " if ((collidables[collidableIndexA].m_shapeType!=SHAPE_CONCAVE_TRIMESH) \n"
+ " && (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))\n"
+ " {\n"
+ " int numChildrenB = collidables[collidableIndexB].m_numChildShapes;\n"
+ " for (int b=0;b<numChildrenB;b++)\n"
+ " {\n"
+ " int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex+b;\n"
+ " int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
+ " float4 ornB = rigidBodies[bodyIndexB].m_quat;\n"
+ " float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+ " float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
+ " float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
+ " float4 newPosB = qtRotate(ornB,childPosB)+posB;\n"
+ " float4 newOrnB = qtMul(ornB,childOrnB);\n"
+ " int shapeIndexB = collidables[childColIndexB].m_shapeIndex;\n"
+ " //////////////////////////////////////\n"
+ " if (1)\n"
+ " {\n"
+ " int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
+ " float dmin = FLT_MAX;\n"
+ " float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+ " posA.w = 0.f;\n"
+ " float4 posB = newPosB;\n"
+ " posB.w = 0.f;\n"
+ " float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
+ " float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
+ " float4 c0 = transform(&c0local, &posA, &ornA);\n"
+ " float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
+ " float4 ornB =newOrnB;\n"
+ " float4 c1 = transform(&c1local,&posB,&ornB);\n"
+ " const float4 DeltaC2 = c0 - c1;\n"
+ " {//\n"
+ " int compoundPairIdx = atomic_inc(numCompoundPairsOut);\n"
+ " if (compoundPairIdx<maxNumCompoundPairsCapacity)\n"
+ " {\n"
+ " gpuCompoundPairsOut[compoundPairIdx] = (int4)(bodyIndexA,bodyIndexB,-1,childShapeIndexB);\n"
+ " }//fi (compoundPairIdx<maxNumCompoundPairsCapacity)\n"
+ " }//\n"
+ " }//fi (1) \n"
+ " }//for (int b=0;b<numChildrenB;b++)\n"
+ " return;\n"
+ " }//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
+ " return;\n"
+ " }//fi ((collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS) ||(collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))\n"
+ " }//i<numPairs\n"
+ "}\n"
+ "// work-in-progress\n"
+ "__kernel void findSeparatingAxisKernel( __global const int4* pairs, \n"
+ " __global const BodyData* rigidBodies, \n"
+ " __global const btCollidableGpu* collidables,\n"
+ " __global const ConvexPolyhedronCL* convexShapes, \n"
+ " __global const float4* vertices,\n"
+ " __global const float4* uniqueEdges,\n"
+ " __global const btGpuFace* faces,\n"
+ " __global const int* indices,\n"
+ " __global btAabbCL* aabbs,\n"
+ " __global volatile float4* separatingNormals,\n"
+ " __global volatile int* hasSeparatingAxis,\n"
+ " int numPairs\n"
+ " )\n"
+ "{\n"
+ " int i = get_global_id(0);\n"
+ " \n"
+ " if (i<numPairs)\n"
+ " {\n"
+ " \n"
+ " int bodyIndexA = pairs[i].x;\n"
+ " int bodyIndexB = pairs[i].y;\n"
+ " int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+ " int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+ " \n"
+ " int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+ " int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+ " \n"
+ " \n"
+ " //once the broadphase avoids static-static pairs, we can remove this test\n"
+ " if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))\n"
+ " {\n"
+ " hasSeparatingAxis[i] = 0;\n"
+ " return;\n"
+ " }\n"
+ " \n"
+ " if ((collidables[collidableIndexA].m_shapeType!=SHAPE_CONVEX_HULL) ||(collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL))\n"
+ " {\n"
+ " hasSeparatingAxis[i] = 0;\n"
+ " return;\n"
+ " }\n"
+ " \n"
+ " if ((collidables[collidableIndexA].m_shapeType==SHAPE_CONCAVE_TRIMESH))\n"
+ " {\n"
+ " hasSeparatingAxis[i] = 0;\n"
+ " return;\n"
+ " }\n"
+ " int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
+ " float dmin = FLT_MAX;\n"
+ " float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+ " posA.w = 0.f;\n"
+ " float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+ " posB.w = 0.f;\n"
+ " float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
+ " float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
+ " float4 c0 = transform(&c0local, &posA, &ornA);\n"
+ " float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
+ " float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
+ " float4 c1 = transform(&c1local,&posB,&ornB);\n"
+ " const float4 DeltaC2 = c0 - c1;\n"
+ " float4 sepNormal;\n"
+ " \n"
+ " bool sepA = findSeparatingAxis( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,\n"
+ " posB,ornB,\n"
+ " DeltaC2,\n"
+ " vertices,uniqueEdges,faces,\n"
+ " indices,&sepNormal,&dmin);\n"
+ " hasSeparatingAxis[i] = 4;\n"
+ " if (!sepA)\n"
+ " {\n"
+ " hasSeparatingAxis[i] = 0;\n"
+ " } else\n"
+ " {\n"
+ " bool sepB = findSeparatingAxis( &convexShapes[shapeIndexB],&convexShapes[shapeIndexA],posB,ornB,\n"
+ " posA,ornA,\n"
+ " DeltaC2,\n"
+ " vertices,uniqueEdges,faces,\n"
+ " indices,&sepNormal,&dmin);\n"
+ " if (!sepB)\n"
+ " {\n"
+ " hasSeparatingAxis[i] = 0;\n"
+ " } else\n"
+ " {\n"
+ " bool sepEE = findSeparatingAxisEdgeEdge( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,\n"
+ " posB,ornB,\n"
+ " DeltaC2,\n"
+ " vertices,uniqueEdges,faces,\n"
+ " indices,&sepNormal,&dmin);\n"
+ " if (!sepEE)\n"
+ " {\n"
+ " hasSeparatingAxis[i] = 0;\n"
+ " } else\n"
+ " {\n"
+ " hasSeparatingAxis[i] = 1;\n"
+ " separatingNormals[i] = sepNormal;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " \n"
+ " }\n"
+ "}\n"
+ "__kernel void findSeparatingAxisVertexFaceKernel( __global const int4* pairs, \n"
+ " __global const BodyData* rigidBodies, \n"
+ " __global const btCollidableGpu* collidables,\n"
+ " __global const ConvexPolyhedronCL* convexShapes, \n"
+ " __global const float4* vertices,\n"
+ " __global const float4* uniqueEdges,\n"
+ " __global const btGpuFace* faces,\n"
+ " __global const int* indices,\n"
+ " __global btAabbCL* aabbs,\n"
+ " __global volatile float4* separatingNormals,\n"
+ " __global volatile int* hasSeparatingAxis,\n"
+ " __global float* dmins,\n"
+ " int numPairs\n"
+ " )\n"
+ "{\n"
+ " int i = get_global_id(0);\n"
+ " \n"
+ " if (i<numPairs)\n"
+ " {\n"
+ " \n"
+ " int bodyIndexA = pairs[i].x;\n"
+ " int bodyIndexB = pairs[i].y;\n"
+ " int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+ " int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+ " \n"
+ " int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+ " int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+ " \n"
+ " hasSeparatingAxis[i] = 0; \n"
+ " \n"
+ " //once the broadphase avoids static-static pairs, we can remove this test\n"
+ " if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))\n"
+ " {\n"
+ " return;\n"
+ " }\n"
+ " \n"
+ " if ((collidables[collidableIndexA].m_shapeType!=SHAPE_CONVEX_HULL) ||(collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL))\n"
+ " {\n"
+ " return;\n"
+ " }\n"
+ " \n"
+ " int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
+ " float dmin = FLT_MAX;\n"
+ " dmins[i] = dmin;\n"
+ " \n"
+ " float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+ " posA.w = 0.f;\n"
+ " float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+ " posB.w = 0.f;\n"
+ " float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
+ " float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
+ " float4 c0 = transform(&c0local, &posA, &ornA);\n"
+ " float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
+ " float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
+ " float4 c1 = transform(&c1local,&posB,&ornB);\n"
+ " const float4 DeltaC2 = c0 - c1;\n"
+ " float4 sepNormal;\n"
+ " \n"
+ " bool sepA = findSeparatingAxis( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,\n"
+ " posB,ornB,\n"
+ " DeltaC2,\n"
+ " vertices,uniqueEdges,faces,\n"
+ " indices,&sepNormal,&dmin);\n"
+ " hasSeparatingAxis[i] = 4;\n"
+ " if (!sepA)\n"
+ " {\n"
+ " hasSeparatingAxis[i] = 0;\n"
+ " } else\n"
+ " {\n"
+ " bool sepB = findSeparatingAxis( &convexShapes[shapeIndexB],&convexShapes[shapeIndexA],posB,ornB,\n"
+ " posA,ornA,\n"
+ " DeltaC2,\n"
+ " vertices,uniqueEdges,faces,\n"
+ " indices,&sepNormal,&dmin);\n"
+ " if (sepB)\n"
+ " {\n"
+ " dmins[i] = dmin;\n"
+ " hasSeparatingAxis[i] = 1;\n"
+ " separatingNormals[i] = sepNormal;\n"
+ " }\n"
+ " }\n"
+ " \n"
+ " }\n"
+ "}\n"
+ "__kernel void findSeparatingAxisEdgeEdgeKernel( __global const int4* pairs, \n"
+ " __global const BodyData* rigidBodies, \n"
+ " __global const btCollidableGpu* collidables,\n"
+ " __global const ConvexPolyhedronCL* convexShapes, \n"
+ " __global const float4* vertices,\n"
+ " __global const float4* uniqueEdges,\n"
+ " __global const btGpuFace* faces,\n"
+ " __global const int* indices,\n"
+ " __global btAabbCL* aabbs,\n"
+ " __global float4* separatingNormals,\n"
+ " __global int* hasSeparatingAxis,\n"
+ " __global float* dmins,\n"
+ " __global const float4* unitSphereDirections,\n"
+ " int numUnitSphereDirections,\n"
+ " int numPairs\n"
+ " )\n"
+ "{\n"
+ " int i = get_global_id(0);\n"
+ " \n"
+ " if (i<numPairs)\n"
+ " {\n"
+ " if (hasSeparatingAxis[i])\n"
+ " {\n"
+ " \n"
+ " int bodyIndexA = pairs[i].x;\n"
+ " int bodyIndexB = pairs[i].y;\n"
+ " \n"
+ " int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+ " int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+ " \n"
+ " int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+ " int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+ " \n"
+ " \n"
+ " int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
+ " \n"
+ " float dmin = dmins[i];\n"
+ " \n"
+ " float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+ " posA.w = 0.f;\n"
+ " float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+ " posB.w = 0.f;\n"
+ " float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
+ " float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
+ " float4 c0 = transform(&c0local, &posA, &ornA);\n"
+ " float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
+ " float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
+ " float4 c1 = transform(&c1local,&posB,&ornB);\n"
+ " const float4 DeltaC2 = c0 - c1;\n"
+ " float4 sepNormal = separatingNormals[i];\n"
+ " \n"
+ " \n"
+ " \n"
+ " bool sepEE = false;\n"
+ " int numEdgeEdgeDirections = convexShapes[shapeIndexA].m_numUniqueEdges*convexShapes[shapeIndexB].m_numUniqueEdges;\n"
+ " if (numEdgeEdgeDirections<=numUnitSphereDirections)\n"
+ " {\n"
+ " sepEE = findSeparatingAxisEdgeEdge( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,\n"
+ " posB,ornB,\n"
+ " DeltaC2,\n"
+ " vertices,uniqueEdges,faces,\n"
+ " indices,&sepNormal,&dmin);\n"
+ " \n"
+ " if (!sepEE)\n"
+ " {\n"
+ " hasSeparatingAxis[i] = 0;\n"
+ " } else\n"
+ " {\n"
+ " hasSeparatingAxis[i] = 1;\n"
+ " separatingNormals[i] = sepNormal;\n"
+ " }\n"
+ " }\n"
+ " /*\n"
+ " ///else case is a separate kernel, to make Mac OSX OpenCL compiler happy\n"
+ " else\n"
+ " {\n"
+ " sepEE = findSeparatingAxisUnitSphere(&convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,\n"
+ " posB,ornB,\n"
+ " DeltaC2,\n"
+ " vertices,unitSphereDirections,numUnitSphereDirections,\n"
+ " &sepNormal,&dmin);\n"
+ " if (!sepEE)\n"
+ " {\n"
+ " hasSeparatingAxis[i] = 0;\n"
+ " } else\n"
+ " {\n"
+ " hasSeparatingAxis[i] = 1;\n"
+ " separatingNormals[i] = sepNormal;\n"
+ " }\n"
+ " }\n"
+ " */\n"
+ " } //if (hasSeparatingAxis[i])\n"
+ " }//(i<numPairs)\n"
+ "}\n"
+ "inline int findClippingFaces(const float4 separatingNormal,\n"
+ " const ConvexPolyhedronCL* hullA, \n"
+ " __global const ConvexPolyhedronCL* hullB,\n"
+ " const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB,\n"
+ " __global float4* worldVertsA1,\n"
+ " __global float4* worldNormalsA1,\n"
+ " __global float4* worldVertsB1,\n"
+ " int capacityWorldVerts,\n"
+ " const float minDist, float maxDist,\n"
+ " const float4* verticesA,\n"
+ " const btGpuFace* facesA,\n"
+ " const int* indicesA,\n"
+ " __global const float4* verticesB,\n"
+ " __global const btGpuFace* facesB,\n"
+ " __global const int* indicesB,\n"
+ " __global int4* clippingFaces, int pairIndex)\n"
+ "{\n"
+ " int numContactsOut = 0;\n"
+ " int numWorldVertsB1= 0;\n"
+ " \n"
+ " \n"
+ " int closestFaceB=0;\n"
+ " float dmax = -FLT_MAX;\n"
+ " \n"
+ " {\n"
+ " for(int face=0;face<hullB->m_numFaces;face++)\n"
+ " {\n"
+ " const float4 Normal = make_float4(facesB[hullB->m_faceOffset+face].m_plane.x,\n"
+ " facesB[hullB->m_faceOffset+face].m_plane.y, facesB[hullB->m_faceOffset+face].m_plane.z,0.f);\n"
+ " const float4 WorldNormal = qtRotate(ornB, Normal);\n"
+ " float d = dot3F4(WorldNormal,separatingNormal);\n"
+ " if (d > dmax)\n"
+ " {\n"
+ " dmax = d;\n"
+ " closestFaceB = face;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " \n"
+ " {\n"
+ " const btGpuFace polyB = facesB[hullB->m_faceOffset+closestFaceB];\n"
+ " int numVertices = polyB.m_numIndices;\n"
+ " if (numVertices>capacityWorldVerts)\n"
+ " numVertices = capacityWorldVerts;\n"
+ " \n"
+ " for(int e0=0;e0<numVertices;e0++)\n"
+ " {\n"
+ " if (e0<capacityWorldVerts)\n"
+ " {\n"
+ " const float4 b = verticesB[hullB->m_vertexOffset+indicesB[polyB.m_indexOffset+e0]];\n"
+ " worldVertsB1[pairIndex*capacityWorldVerts+numWorldVertsB1++] = transform(&b,&posB,&ornB);\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " \n"
+ " int closestFaceA=0;\n"
+ " {\n"
+ " float dmin = FLT_MAX;\n"
+ " for(int face=0;face<hullA->m_numFaces;face++)\n"
+ " {\n"
+ " const float4 Normal = make_float4(\n"
+ " facesA[hullA->m_faceOffset+face].m_plane.x,\n"
+ " facesA[hullA->m_faceOffset+face].m_plane.y,\n"
+ " facesA[hullA->m_faceOffset+face].m_plane.z,\n"
+ " 0.f);\n"
+ " const float4 faceANormalWS = qtRotate(ornA,Normal);\n"
+ " \n"
+ " float d = dot3F4(faceANormalWS,separatingNormal);\n"
+ " if (d < dmin)\n"
+ " {\n"
+ " dmin = d;\n"
+ " closestFaceA = face;\n"
+ " worldNormalsA1[pairIndex] = faceANormalWS;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " \n"
+ " int numVerticesA = facesA[hullA->m_faceOffset+closestFaceA].m_numIndices;\n"
+ " if (numVerticesA>capacityWorldVerts)\n"
+ " numVerticesA = capacityWorldVerts;\n"
+ " \n"
+ " for(int e0=0;e0<numVerticesA;e0++)\n"
+ " {\n"
+ " if (e0<capacityWorldVerts)\n"
+ " {\n"
+ " const float4 a = verticesA[hullA->m_vertexOffset+indicesA[facesA[hullA->m_faceOffset+closestFaceA].m_indexOffset+e0]];\n"
+ " worldVertsA1[pairIndex*capacityWorldVerts+e0] = transform(&a, &posA,&ornA);\n"
+ " }\n"
+ " }\n"
+ " \n"
+ " clippingFaces[pairIndex].x = closestFaceA;\n"
+ " clippingFaces[pairIndex].y = closestFaceB;\n"
+ " clippingFaces[pairIndex].z = numVerticesA;\n"
+ " clippingFaces[pairIndex].w = numWorldVertsB1;\n"
+ " \n"
+ " \n"
+ " return numContactsOut;\n"
+ "}\n"
+ "// work-in-progress\n"
+ "__kernel void findConcaveSeparatingAxisKernel( __global int4* concavePairs,\n"
+ " __global const BodyData* rigidBodies,\n"
+ " __global const btCollidableGpu* collidables,\n"
+ " __global const ConvexPolyhedronCL* convexShapes, \n"
+ " __global const float4* vertices,\n"
+ " __global const float4* uniqueEdges,\n"
+ " __global const btGpuFace* faces,\n"
+ " __global const int* indices,\n"
+ " __global const btGpuChildShape* gpuChildShapes,\n"
+ " __global btAabbCL* aabbs,\n"
+ " __global float4* concaveSeparatingNormalsOut,\n"
+ " __global int* concaveHasSeparatingNormals,\n"
+ " __global int4* clippingFacesOut,\n"
+ " __global float4* worldVertsA1GPU,\n"
+ " __global float4* worldNormalsAGPU,\n"
+ " __global float4* worldVertsB1GPU,\n"
+ " int vertexFaceCapacity,\n"
+ " int numConcavePairs\n"
+ " )\n"
+ "{\n"
+ " int i = get_global_id(0);\n"
+ " if (i>=numConcavePairs)\n"
+ " return;\n"
+ " concaveHasSeparatingNormals[i] = 0;\n"
+ " int pairIdx = i;\n"
+ " int bodyIndexA = concavePairs[i].x;\n"
+ " int bodyIndexB = concavePairs[i].y;\n"
+ " int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+ " int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+ " int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+ " int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+ " if (collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL&&\n"
+ " collidables[collidableIndexB].m_shapeType!=SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
+ " {\n"
+ " concavePairs[pairIdx].w = -1;\n"
+ " return;\n"
+ " }\n"
+ " int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
+ " int numActualConcaveConvexTests = 0;\n"
+ " \n"
+ " int f = concavePairs[i].z;\n"
+ " \n"
+ " bool overlap = false;\n"
+ " \n"
+ " ConvexPolyhedronCL convexPolyhedronA;\n"
+ " //add 3 vertices of the triangle\n"
+ " convexPolyhedronA.m_numVertices = 3;\n"
+ " convexPolyhedronA.m_vertexOffset = 0;\n"
+ " float4 localCenter = make_float4(0.f,0.f,0.f,0.f);\n"
+ " btGpuFace face = faces[convexShapes[shapeIndexA].m_faceOffset+f];\n"
+ " float4 triMinAabb, triMaxAabb;\n"
+ " btAabbCL triAabb;\n"
+ " triAabb.m_min = make_float4(1e30f,1e30f,1e30f,0.f);\n"
+ " triAabb.m_max = make_float4(-1e30f,-1e30f,-1e30f,0.f);\n"
+ " \n"
+ " float4 verticesA[3];\n"
+ " for (int i=0;i<3;i++)\n"
+ " {\n"
+ " int index = indices[face.m_indexOffset+i];\n"
+ " float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];\n"
+ " verticesA[i] = vert;\n"
+ " localCenter += vert;\n"
+ " \n"
+ " triAabb.m_min = min(triAabb.m_min,vert); \n"
+ " triAabb.m_max = max(triAabb.m_max,vert); \n"
+ " }\n"
+ " overlap = true;\n"
+ " overlap = (triAabb.m_min.x > aabbs[bodyIndexB].m_max.x || triAabb.m_max.x < aabbs[bodyIndexB].m_min.x) ? false : overlap;\n"
+ " overlap = (triAabb.m_min.z > aabbs[bodyIndexB].m_max.z || triAabb.m_max.z < aabbs[bodyIndexB].m_min.z) ? false : overlap;\n"
+ " overlap = (triAabb.m_min.y > aabbs[bodyIndexB].m_max.y || triAabb.m_max.y < aabbs[bodyIndexB].m_min.y) ? false : overlap;\n"
+ " \n"
+ " if (overlap)\n"
+ " {\n"
+ " float dmin = FLT_MAX;\n"
+ " int hasSeparatingAxis=5;\n"
+ " float4 sepAxis=make_float4(1,2,3,4);\n"
+ " int localCC=0;\n"
+ " numActualConcaveConvexTests++;\n"
+ " //a triangle has 3 unique edges\n"
+ " convexPolyhedronA.m_numUniqueEdges = 3;\n"
+ " convexPolyhedronA.m_uniqueEdgesOffset = 0;\n"
+ " float4 uniqueEdgesA[3];\n"
+ " \n"
+ " uniqueEdgesA[0] = (verticesA[1]-verticesA[0]);\n"
+ " uniqueEdgesA[1] = (verticesA[2]-verticesA[1]);\n"
+ " uniqueEdgesA[2] = (verticesA[0]-verticesA[2]);\n"
+ " convexPolyhedronA.m_faceOffset = 0;\n"
+ " \n"
+ " float4 normal = make_float4(face.m_plane.x,face.m_plane.y,face.m_plane.z,0.f);\n"
+ " \n"
+ " btGpuFace facesA[TRIANGLE_NUM_CONVEX_FACES];\n"
+ " int indicesA[3+3+2+2+2];\n"
+ " int curUsedIndices=0;\n"
+ " int fidx=0;\n"
+ " //front size of triangle\n"
+ " {\n"
+ " facesA[fidx].m_indexOffset=curUsedIndices;\n"
+ " indicesA[0] = 0;\n"
+ " indicesA[1] = 1;\n"
+ " indicesA[2] = 2;\n"
+ " curUsedIndices+=3;\n"
+ " float c = face.m_plane.w;\n"
+ " facesA[fidx].m_plane.x = normal.x;\n"
+ " facesA[fidx].m_plane.y = normal.y;\n"
+ " facesA[fidx].m_plane.z = normal.z;\n"
+ " facesA[fidx].m_plane.w = c;\n"
+ " facesA[fidx].m_numIndices=3;\n"
+ " }\n"
+ " fidx++;\n"
+ " //back size of triangle\n"
+ " {\n"
+ " facesA[fidx].m_indexOffset=curUsedIndices;\n"
+ " indicesA[3]=2;\n"
+ " indicesA[4]=1;\n"
+ " indicesA[5]=0;\n"
+ " curUsedIndices+=3;\n"
+ " float c = dot(normal,verticesA[0]);\n"
+ " float c1 = -face.m_plane.w;\n"
+ " facesA[fidx].m_plane.x = -normal.x;\n"
+ " facesA[fidx].m_plane.y = -normal.y;\n"
+ " facesA[fidx].m_plane.z = -normal.z;\n"
+ " facesA[fidx].m_plane.w = c;\n"
+ " facesA[fidx].m_numIndices=3;\n"
+ " }\n"
+ " fidx++;\n"
+ " bool addEdgePlanes = true;\n"
+ " if (addEdgePlanes)\n"
+ " {\n"
+ " int numVertices=3;\n"
+ " int prevVertex = numVertices-1;\n"
+ " for (int i=0;i<numVertices;i++)\n"
+ " {\n"
+ " float4 v0 = verticesA[i];\n"
+ " float4 v1 = verticesA[prevVertex];\n"
+ " \n"
+ " float4 edgeNormal = normalize(cross(normal,v1-v0));\n"
+ " float c = -dot(edgeNormal,v0);\n"
+ " facesA[fidx].m_numIndices = 2;\n"
+ " facesA[fidx].m_indexOffset=curUsedIndices;\n"
+ " indicesA[curUsedIndices++]=i;\n"
+ " indicesA[curUsedIndices++]=prevVertex;\n"
+ " \n"
+ " facesA[fidx].m_plane.x = edgeNormal.x;\n"
+ " facesA[fidx].m_plane.y = edgeNormal.y;\n"
+ " facesA[fidx].m_plane.z = edgeNormal.z;\n"
+ " facesA[fidx].m_plane.w = c;\n"
+ " fidx++;\n"
+ " prevVertex = i;\n"
+ " }\n"
+ " }\n"
+ " convexPolyhedronA.m_numFaces = TRIANGLE_NUM_CONVEX_FACES;\n"
+ " convexPolyhedronA.m_localCenter = localCenter*(1.f/3.f);\n"
+ " float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+ " posA.w = 0.f;\n"
+ " float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+ " posB.w = 0.f;\n"
+ " float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
+ " float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
+ " \n"
+ " ///////////////////\n"
+ " ///compound shape support\n"
+ " if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
+ " {\n"
+ " int compoundChild = concavePairs[pairIdx].w;\n"
+ " int childShapeIndexB = compoundChild;//collidables[collidableIndexB].m_shapeIndex+compoundChild;\n"
+ " int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
+ " float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
+ " float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
+ " float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
+ " float4 newOrnB = qtMul(ornB,childOrnB);\n"
+ " posB = newPosB;\n"
+ " ornB = newOrnB;\n"
+ " shapeIndexB = collidables[childColIndexB].m_shapeIndex;\n"
+ " }\n"
+ " //////////////////\n"
+ " float4 c0local = convexPolyhedronA.m_localCenter;\n"
+ " float4 c0 = transform(&c0local, &posA, &ornA);\n"
+ " float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
+ " float4 c1 = transform(&c1local,&posB,&ornB);\n"
+ " const float4 DeltaC2 = c0 - c1;\n"
+ " bool sepA = findSeparatingAxisLocalA( &convexPolyhedronA, &convexShapes[shapeIndexB],\n"
+ " posA,ornA,\n"
+ " posB,ornB,\n"
+ " DeltaC2,\n"
+ " verticesA,uniqueEdgesA,facesA,indicesA,\n"
+ " vertices,uniqueEdges,faces,indices,\n"
+ " &sepAxis,&dmin);\n"
+ " hasSeparatingAxis = 4;\n"
+ " if (!sepA)\n"
+ " {\n"
+ " hasSeparatingAxis = 0;\n"
+ " } else\n"
+ " {\n"
+ " bool sepB = findSeparatingAxisLocalB( &convexShapes[shapeIndexB],&convexPolyhedronA,\n"
+ " posB,ornB,\n"
+ " posA,ornA,\n"
+ " DeltaC2,\n"
+ " vertices,uniqueEdges,faces,indices,\n"
+ " verticesA,uniqueEdgesA,facesA,indicesA,\n"
+ " &sepAxis,&dmin);\n"
+ " if (!sepB)\n"
+ " {\n"
+ " hasSeparatingAxis = 0;\n"
+ " } else\n"
+ " {\n"
+ " bool sepEE = findSeparatingAxisEdgeEdgeLocalA( &convexPolyhedronA, &convexShapes[shapeIndexB],\n"
+ " posA,ornA,\n"
+ " posB,ornB,\n"
+ " DeltaC2,\n"
+ " verticesA,uniqueEdgesA,facesA,indicesA,\n"
+ " vertices,uniqueEdges,faces,indices,\n"
+ " &sepAxis,&dmin);\n"
+ " \n"
+ " if (!sepEE)\n"
+ " {\n"
+ " hasSeparatingAxis = 0;\n"
+ " } else\n"
+ " {\n"
+ " hasSeparatingAxis = 1;\n"
+ " }\n"
+ " }\n"
+ " } \n"
+ " \n"
+ " if (hasSeparatingAxis)\n"
+ " {\n"
+ " sepAxis.w = dmin;\n"
+ " concaveSeparatingNormalsOut[pairIdx]=sepAxis;\n"
+ " concaveHasSeparatingNormals[i]=1;\n"
+ " float minDist = -1e30f;\n"
+ " float maxDist = 0.02f;\n"
+ " \n"
+ " findClippingFaces(sepAxis,\n"
+ " &convexPolyhedronA,\n"
+ " &convexShapes[shapeIndexB],\n"
+ " posA,ornA,\n"
+ " posB,ornB,\n"
+ " worldVertsA1GPU,\n"
+ " worldNormalsAGPU,\n"
+ " worldVertsB1GPU,\n"
+ " vertexFaceCapacity,\n"
+ " minDist, maxDist,\n"
+ " verticesA,\n"
+ " facesA,\n"
+ " indicesA,\n"
+ " vertices,\n"
+ " faces,\n"
+ " indices,\n"
+ " clippingFacesOut, pairIdx);\n"
+ " } else\n"
+ " { \n"
+ " //mark this pair as in-active\n"
+ " concavePairs[pairIdx].w = -1;\n"
+ " }\n"
+ " }\n"
+ " else\n"
+ " { \n"
+ " //mark this pair as in-active\n"
+ " concavePairs[pairIdx].w = -1;\n"
+ " }\n"
+ " \n"
+ " concavePairs[pairIdx].z = -1;//now z is used for existing/persistent contacts\n"
+ "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.cpp b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.cpp
index a4980f71e1..c0e11bfb26 100644
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.cpp
+++ b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.cpp
@@ -19,149 +19,139 @@ subject to the following restrictions:
#define KERNEL1 "SearchSortDataUpperKernel"
#define KERNEL2 "SubtractKernel"
-
#include "b3BoundSearchCL.h"
#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
#include "b3LauncherCL.h"
#include "kernels/BoundSearchKernelsCL.h"
b3BoundSearchCL::b3BoundSearchCL(cl_context ctx, cl_device_id device, cl_command_queue queue, int maxSize)
- :m_context(ctx),
- m_device(device),
- m_queue(queue)
+ : m_context(ctx),
+ m_device(device),
+ m_queue(queue)
{
-
const char* additionalMacros = "";
//const char* srcFileNameForCaching="";
cl_int pErrNum;
const char* kernelSource = boundSearchKernelsCL;
- cl_program boundSearchProg = b3OpenCLUtils::compileCLProgramFromString( ctx, device, kernelSource, &pErrNum,additionalMacros, BOUNDSEARCH_PATH);
+ cl_program boundSearchProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, kernelSource, &pErrNum, additionalMacros, BOUNDSEARCH_PATH);
b3Assert(boundSearchProg);
- m_lowerSortDataKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, kernelSource, "SearchSortDataLowerKernel", &pErrNum, boundSearchProg,additionalMacros );
- b3Assert(m_lowerSortDataKernel );
+ m_lowerSortDataKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "SearchSortDataLowerKernel", &pErrNum, boundSearchProg, additionalMacros);
+ b3Assert(m_lowerSortDataKernel);
- m_upperSortDataKernel= b3OpenCLUtils::compileCLKernelFromString( ctx, device, kernelSource, "SearchSortDataUpperKernel", &pErrNum, boundSearchProg,additionalMacros );
+ m_upperSortDataKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "SearchSortDataUpperKernel", &pErrNum, boundSearchProg, additionalMacros);
b3Assert(m_upperSortDataKernel);
m_subtractKernel = 0;
- if( maxSize )
+ if (maxSize)
{
- m_subtractKernel= b3OpenCLUtils::compileCLKernelFromString( ctx, device, kernelSource, "SubtractKernel", &pErrNum, boundSearchProg,additionalMacros );
+ m_subtractKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "SubtractKernel", &pErrNum, boundSearchProg, additionalMacros);
b3Assert(m_subtractKernel);
}
//m_constBuffer = new b3OpenCLArray<b3Int4>( device, 1, BufferBase::BUFFER_CONST );
-
- m_lower = (maxSize == 0)? 0: new b3OpenCLArray<unsigned int>(ctx,queue,maxSize );
- m_upper = (maxSize == 0)? 0: new b3OpenCLArray<unsigned int>(ctx,queue, maxSize );
- m_filler = new b3FillCL(ctx,device,queue);
+ m_lower = (maxSize == 0) ? 0 : new b3OpenCLArray<unsigned int>(ctx, queue, maxSize);
+ m_upper = (maxSize == 0) ? 0 : new b3OpenCLArray<unsigned int>(ctx, queue, maxSize);
+
+ m_filler = new b3FillCL(ctx, device, queue);
}
b3BoundSearchCL::~b3BoundSearchCL()
{
-
delete m_lower;
delete m_upper;
delete m_filler;
-
+
clReleaseKernel(m_lowerSortDataKernel);
clReleaseKernel(m_upperSortDataKernel);
clReleaseKernel(m_subtractKernel);
-
-
}
-
-void b3BoundSearchCL::execute(b3OpenCLArray<b3SortData>& src, int nSrc, b3OpenCLArray<unsigned int>& dst, int nDst, Option option )
+void b3BoundSearchCL::execute(b3OpenCLArray<b3SortData>& src, int nSrc, b3OpenCLArray<unsigned int>& dst, int nDst, Option option)
{
b3Int4 constBuffer;
constBuffer.x = nSrc;
constBuffer.y = nDst;
- if( option == BOUND_LOWER )
+ if (option == BOUND_LOWER)
{
- b3BufferInfoCL bInfo[] = { b3BufferInfoCL( src.getBufferCL(), true ), b3BufferInfoCL( dst.getBufferCL()) };
-
- b3LauncherCL launcher( m_queue, m_lowerSortDataKernel,"m_lowerSortDataKernel" );
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst( nSrc );
- launcher.setConst( nDst );
-
- launcher.launch1D( nSrc, 64 );
+ b3BufferInfoCL bInfo[] = {b3BufferInfoCL(src.getBufferCL(), true), b3BufferInfoCL(dst.getBufferCL())};
+
+ b3LauncherCL launcher(m_queue, m_lowerSortDataKernel, "m_lowerSortDataKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setConst(nSrc);
+ launcher.setConst(nDst);
+
+ launcher.launch1D(nSrc, 64);
}
- else if( option == BOUND_UPPER )
+ else if (option == BOUND_UPPER)
{
- b3BufferInfoCL bInfo[] = { b3BufferInfoCL( src.getBufferCL(), true ), b3BufferInfoCL( dst.getBufferCL() ) };
+ b3BufferInfoCL bInfo[] = {b3BufferInfoCL(src.getBufferCL(), true), b3BufferInfoCL(dst.getBufferCL())};
- b3LauncherCL launcher(m_queue, m_upperSortDataKernel,"m_upperSortDataKernel" );
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst( nSrc );
- launcher.setConst( nDst );
+ b3LauncherCL launcher(m_queue, m_upperSortDataKernel, "m_upperSortDataKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setConst(nSrc);
+ launcher.setConst(nDst);
- launcher.launch1D( nSrc, 64 );
+ launcher.launch1D(nSrc, 64);
}
- else if( option == COUNT )
+ else if (option == COUNT)
{
- b3Assert( m_lower );
- b3Assert( m_upper );
- b3Assert( m_lower->capacity() <= (int)nDst );
- b3Assert( m_upper->capacity() <= (int)nDst );
+ b3Assert(m_lower);
+ b3Assert(m_upper);
+ b3Assert(m_lower->capacity() <= (int)nDst);
+ b3Assert(m_upper->capacity() <= (int)nDst);
int zero = 0;
- m_filler->execute( *m_lower, zero, nDst );
- m_filler->execute( *m_upper, zero, nDst );
+ m_filler->execute(*m_lower, zero, nDst);
+ m_filler->execute(*m_upper, zero, nDst);
- execute( src, nSrc, *m_lower, nDst, BOUND_LOWER );
- execute( src, nSrc, *m_upper, nDst, BOUND_UPPER );
+ execute(src, nSrc, *m_lower, nDst, BOUND_LOWER);
+ execute(src, nSrc, *m_upper, nDst, BOUND_UPPER);
{
- b3BufferInfoCL bInfo[] = { b3BufferInfoCL( m_upper->getBufferCL(), true ), b3BufferInfoCL( m_lower->getBufferCL(), true ), b3BufferInfoCL( dst.getBufferCL() ) };
+ b3BufferInfoCL bInfo[] = {b3BufferInfoCL(m_upper->getBufferCL(), true), b3BufferInfoCL(m_lower->getBufferCL(), true), b3BufferInfoCL(dst.getBufferCL())};
- b3LauncherCL launcher( m_queue, m_subtractKernel ,"m_subtractKernel");
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst( nSrc );
- launcher.setConst( nDst );
+ b3LauncherCL launcher(m_queue, m_subtractKernel, "m_subtractKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setConst(nSrc);
+ launcher.setConst(nDst);
- launcher.launch1D( nDst, 64 );
+ launcher.launch1D(nDst, 64);
}
}
else
{
- b3Assert( 0 );
+ b3Assert(0);
}
-
}
-
-void b3BoundSearchCL::executeHost( b3AlignedObjectArray<b3SortData>& src, int nSrc,
- b3AlignedObjectArray<unsigned int>& dst, int nDst, Option option )
+void b3BoundSearchCL::executeHost(b3AlignedObjectArray<b3SortData>& src, int nSrc,
+ b3AlignedObjectArray<unsigned int>& dst, int nDst, Option option)
{
+ for (int i = 0; i < nSrc - 1; i++)
+ b3Assert(src[i].m_key <= src[i + 1].m_key);
-
- for(int i=0; i<nSrc-1; i++)
- b3Assert( src[i].m_key <= src[i+1].m_key );
-
- b3SortData minData,zeroData,maxData;
+ b3SortData minData, zeroData, maxData;
minData.m_key = -1;
minData.m_value = -1;
- zeroData.m_key=0;
- zeroData.m_value=0;
+ zeroData.m_key = 0;
+ zeroData.m_value = 0;
maxData.m_key = nDst;
maxData.m_value = nDst;
- if( option == BOUND_LOWER )
+ if (option == BOUND_LOWER)
{
- for(int i=0; i<nSrc; i++)
+ for (int i = 0; i < nSrc; i++)
{
- b3SortData& iData = (i==0)? minData: src[i-1];
- b3SortData& jData = (i==nSrc)? maxData: src[i];
+ b3SortData& iData = (i == 0) ? minData : src[i - 1];
+ b3SortData& jData = (i == nSrc) ? maxData : src[i];
- if( iData.m_key != jData.m_key )
+ if (iData.m_key != jData.m_key)
{
int k = jData.m_key;
{
@@ -170,14 +160,14 @@ void b3BoundSearchCL::executeHost( b3AlignedObjectArray<b3SortData>& src, int nS
}
}
}
- else if( option == BOUND_UPPER )
+ else if (option == BOUND_UPPER)
{
- for(int i=1; i<nSrc+1; i++)
+ for (int i = 1; i < nSrc + 1; i++)
{
- b3SortData& iData = src[i-1];
- b3SortData& jData = (i==nSrc)? maxData: src[i];
+ b3SortData& iData = src[i - 1];
+ b3SortData& jData = (i == nSrc) ? maxData : src[i];
- if( iData.m_key != jData.m_key )
+ if (iData.m_key != jData.m_key)
{
int k = iData.m_key;
{
@@ -186,28 +176,28 @@ void b3BoundSearchCL::executeHost( b3AlignedObjectArray<b3SortData>& src, int nS
}
}
}
- else if( option == COUNT )
+ else if (option == COUNT)
{
b3AlignedObjectArray<unsigned int> lower;
- lower.resize(nDst );
+ lower.resize(nDst);
b3AlignedObjectArray<unsigned int> upper;
- upper.resize(nDst );
+ upper.resize(nDst);
- for(int i=0; i<nDst; i++)
- {
- lower[i] = upper[i] = 0;
+ for (int i = 0; i < nDst; i++)
+ {
+ lower[i] = upper[i] = 0;
}
- executeHost( src, nSrc, lower, nDst, BOUND_LOWER );
- executeHost( src, nSrc, upper, nDst, BOUND_UPPER );
+ executeHost(src, nSrc, lower, nDst, BOUND_LOWER);
+ executeHost(src, nSrc, upper, nDst, BOUND_UPPER);
- for( int i=0; i<nDst; i++)
- {
- dst[i] = upper[i] - lower[i];
+ for (int i = 0; i < nDst; i++)
+ {
+ dst[i] = upper[i] - lower[i];
}
}
else
{
- b3Assert( 0 );
+ b3Assert(0);
}
}
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.h b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.h
index 7e2940965c..0d633e3d23 100644
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.h
+++ b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.h
@@ -26,42 +26,39 @@ subject to the following restrictions:
#include "b3OpenCLArray.h"
#include "b3FillCL.h"
-#include "b3RadixSort32CL.h" //for b3SortData (perhaps move it?)
+#include "b3RadixSort32CL.h" //for b3SortData (perhaps move it?)
class b3BoundSearchCL
{
- public:
+public:
+ enum Option
+ {
+ BOUND_LOWER,
+ BOUND_UPPER,
+ COUNT,
+ };
- enum Option
- {
- BOUND_LOWER,
- BOUND_UPPER,
- COUNT,
- };
+ cl_context m_context;
+ cl_device_id m_device;
+ cl_command_queue m_queue;
- cl_context m_context;
- cl_device_id m_device;
- cl_command_queue m_queue;
+ cl_kernel m_lowerSortDataKernel;
+ cl_kernel m_upperSortDataKernel;
+ cl_kernel m_subtractKernel;
-
- cl_kernel m_lowerSortDataKernel;
- cl_kernel m_upperSortDataKernel;
- cl_kernel m_subtractKernel;
-
- b3OpenCLArray<b3Int4>* m_constbtOpenCLArray;
- b3OpenCLArray<unsigned int>* m_lower;
- b3OpenCLArray<unsigned int>* m_upper;
-
- b3FillCL* m_filler;
-
- b3BoundSearchCL(cl_context context, cl_device_id device, cl_command_queue queue, int size);
+ b3OpenCLArray<b3Int4>* m_constbtOpenCLArray;
+ b3OpenCLArray<unsigned int>* m_lower;
+ b3OpenCLArray<unsigned int>* m_upper;
- virtual ~b3BoundSearchCL();
+ b3FillCL* m_filler;
- // src has to be src[i].m_key <= src[i+1].m_key
- void execute( b3OpenCLArray<b3SortData>& src, int nSrc, b3OpenCLArray<unsigned int>& dst, int nDst, Option option = BOUND_LOWER );
+ b3BoundSearchCL(cl_context context, cl_device_id device, cl_command_queue queue, int size);
- void executeHost( b3AlignedObjectArray<b3SortData>& src, int nSrc, b3AlignedObjectArray<unsigned int>& dst, int nDst, Option option = BOUND_LOWER);
-};
+ virtual ~b3BoundSearchCL();
+
+ // src has to be src[i].m_key <= src[i+1].m_key
+ void execute(b3OpenCLArray<b3SortData>& src, int nSrc, b3OpenCLArray<unsigned int>& dst, int nDst, Option option = BOUND_LOWER);
+ void executeHost(b3AlignedObjectArray<b3SortData>& src, int nSrc, b3AlignedObjectArray<unsigned int>& dst, int nDst, Option option = BOUND_LOWER);
+};
-#endif //B3_BOUNDSEARCH_H
+#endif //B3_BOUNDSEARCH_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3BufferInfoCL.h b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3BufferInfoCL.h
index 52f219ae3f..35fc467b20 100644
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3BufferInfoCL.h
+++ b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3BufferInfoCL.h
@@ -4,16 +4,15 @@
#include "b3OpenCLArray.h"
-
struct b3BufferInfoCL
{
//b3BufferInfoCL(){}
-// template<typename T>
- b3BufferInfoCL(cl_mem buff, bool isReadOnly = false): m_clBuffer(buff), m_isReadOnly(isReadOnly){}
+ // template<typename T>
+ b3BufferInfoCL(cl_mem buff, bool isReadOnly = false) : m_clBuffer(buff), m_isReadOnly(isReadOnly) {}
cl_mem m_clBuffer;
bool m_isReadOnly;
};
-#endif //B3_BUFFER_INFO_CL_H
+#endif //B3_BUFFER_INFO_CL_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3FillCL.cpp b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3FillCL.cpp
index f05c2648f1..bd25bb2101 100644
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3FillCL.cpp
+++ b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3FillCL.cpp
@@ -8,29 +8,26 @@
#include "kernels/FillKernelsCL.h"
b3FillCL::b3FillCL(cl_context ctx, cl_device_id device, cl_command_queue queue)
-:m_commandQueue(queue)
+ : m_commandQueue(queue)
{
const char* kernelSource = fillKernelsCL;
cl_int pErrNum;
const char* additionalMacros = "";
- cl_program fillProg = b3OpenCLUtils::compileCLProgramFromString( ctx, device, kernelSource, &pErrNum,additionalMacros, FILL_CL_PROGRAM_PATH);
+ cl_program fillProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, kernelSource, &pErrNum, additionalMacros, FILL_CL_PROGRAM_PATH);
b3Assert(fillProg);
- m_fillIntKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, kernelSource, "FillIntKernel", &pErrNum, fillProg,additionalMacros );
+ m_fillIntKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "FillIntKernel", &pErrNum, fillProg, additionalMacros);
b3Assert(m_fillIntKernel);
- m_fillUnsignedIntKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, kernelSource, "FillUnsignedIntKernel", &pErrNum, fillProg,additionalMacros );
+ m_fillUnsignedIntKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "FillUnsignedIntKernel", &pErrNum, fillProg, additionalMacros);
b3Assert(m_fillIntKernel);
- m_fillFloatKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, kernelSource, "FillFloatKernel", &pErrNum, fillProg,additionalMacros );
+ m_fillFloatKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "FillFloatKernel", &pErrNum, fillProg, additionalMacros);
b3Assert(m_fillFloatKernel);
-
-
- m_fillKernelInt2 = b3OpenCLUtils::compileCLKernelFromString( ctx, device, kernelSource, "FillInt2Kernel", &pErrNum, fillProg,additionalMacros );
+ m_fillKernelInt2 = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "FillInt2Kernel", &pErrNum, fillProg, additionalMacros);
b3Assert(m_fillKernelInt2);
-
}
b3FillCL::~b3FillCL()
@@ -39,88 +36,84 @@ b3FillCL::~b3FillCL()
clReleaseKernel(m_fillIntKernel);
clReleaseKernel(m_fillUnsignedIntKernel);
clReleaseKernel(m_fillFloatKernel);
-
}
void b3FillCL::execute(b3OpenCLArray<float>& src, const float value, int n, int offset)
{
- b3Assert( n>0 );
+ b3Assert(n > 0);
{
- b3LauncherCL launcher( m_commandQueue, m_fillFloatKernel,"m_fillFloatKernel" );
- launcher.setBuffer( src.getBufferCL());
- launcher.setConst( n );
- launcher.setConst( value );
- launcher.setConst( offset);
+ b3LauncherCL launcher(m_commandQueue, m_fillFloatKernel, "m_fillFloatKernel");
+ launcher.setBuffer(src.getBufferCL());
+ launcher.setConst(n);
+ launcher.setConst(value);
+ launcher.setConst(offset);
- launcher.launch1D( n );
+ launcher.launch1D(n);
}
}
void b3FillCL::execute(b3OpenCLArray<int>& src, const int value, int n, int offset)
{
- b3Assert( n>0 );
-
+ b3Assert(n > 0);
{
- b3LauncherCL launcher( m_commandQueue, m_fillIntKernel ,"m_fillIntKernel");
+ b3LauncherCL launcher(m_commandQueue, m_fillIntKernel, "m_fillIntKernel");
launcher.setBuffer(src.getBufferCL());
- launcher.setConst( n);
- launcher.setConst( value);
- launcher.setConst( offset);
- launcher.launch1D( n );
+ launcher.setConst(n);
+ launcher.setConst(value);
+ launcher.setConst(offset);
+ launcher.launch1D(n);
}
}
-
void b3FillCL::execute(b3OpenCLArray<unsigned int>& src, const unsigned int value, int n, int offset)
{
- b3Assert( n>0 );
+ b3Assert(n > 0);
{
- b3BufferInfoCL bInfo[] = { b3BufferInfoCL( src.getBufferCL() ) };
+ b3BufferInfoCL bInfo[] = {b3BufferInfoCL(src.getBufferCL())};
- b3LauncherCL launcher( m_commandQueue, m_fillUnsignedIntKernel,"m_fillUnsignedIntKernel" );
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst( n );
- launcher.setConst(value);
+ b3LauncherCL launcher(m_commandQueue, m_fillUnsignedIntKernel, "m_fillUnsignedIntKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setConst(n);
+ launcher.setConst(value);
launcher.setConst(offset);
- launcher.launch1D( n );
+ launcher.launch1D(n);
}
}
-void b3FillCL::executeHost(b3AlignedObjectArray<b3Int2> &src, const b3Int2 &value, int n, int offset)
+void b3FillCL::executeHost(b3AlignedObjectArray<b3Int2>& src, const b3Int2& value, int n, int offset)
{
- for (int i=0;i<n;i++)
+ for (int i = 0; i < n; i++)
{
- src[i+offset]=value;
+ src[i + offset] = value;
}
}
-void b3FillCL::executeHost(b3AlignedObjectArray<int> &src, const int value, int n, int offset)
+void b3FillCL::executeHost(b3AlignedObjectArray<int>& src, const int value, int n, int offset)
{
- for (int i=0;i<n;i++)
+ for (int i = 0; i < n; i++)
{
- src[i+offset]=value;
+ src[i + offset] = value;
}
}
-void b3FillCL::execute(b3OpenCLArray<b3Int2> &src, const b3Int2 &value, int n, int offset)
+void b3FillCL::execute(b3OpenCLArray<b3Int2>& src, const b3Int2& value, int n, int offset)
{
- b3Assert( n>0 );
-
+ b3Assert(n > 0);
{
- b3BufferInfoCL bInfo[] = { b3BufferInfoCL( src.getBufferCL() ) };
+ b3BufferInfoCL bInfo[] = {b3BufferInfoCL(src.getBufferCL())};
- b3LauncherCL launcher(m_commandQueue, m_fillKernelInt2,"m_fillKernelInt2");
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ b3LauncherCL launcher(m_commandQueue, m_fillKernelInt2, "m_fillKernelInt2");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
launcher.setConst(n);
launcher.setConst(value);
launcher.setConst(offset);
//( constBuffer );
- launcher.launch1D( n );
+ launcher.launch1D(n);
}
}
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3FillCL.h b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3FillCL.h
index 1609676b9d..c92c3e5119 100644
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3FillCL.h
+++ b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3FillCL.h
@@ -7,57 +7,46 @@
#include "Bullet3Common/shared/b3Int2.h"
#include "Bullet3Common/shared/b3Int4.h"
-
class b3FillCL
{
-
- cl_command_queue m_commandQueue;
-
- cl_kernel m_fillKernelInt2;
- cl_kernel m_fillIntKernel;
- cl_kernel m_fillUnsignedIntKernel;
- cl_kernel m_fillFloatKernel;
-
- public:
-
- struct b3ConstData
- {
- union
- {
- b3Int4 m_data;
- b3UnsignedInt4 m_UnsignedData;
- };
- int m_offset;
- int m_n;
- int m_padding[2];
+ cl_command_queue m_commandQueue;
+
+ cl_kernel m_fillKernelInt2;
+ cl_kernel m_fillIntKernel;
+ cl_kernel m_fillUnsignedIntKernel;
+ cl_kernel m_fillFloatKernel;
+
+public:
+ struct b3ConstData
+ {
+ union {
+ b3Int4 m_data;
+ b3UnsignedInt4 m_UnsignedData;
};
+ int m_offset;
+ int m_n;
+ int m_padding[2];
+ };
protected:
-
public:
+ b3FillCL(cl_context ctx, cl_device_id device, cl_command_queue queue);
- b3FillCL(cl_context ctx, cl_device_id device, cl_command_queue queue);
+ virtual ~b3FillCL();
- virtual ~b3FillCL();
+ void execute(b3OpenCLArray<unsigned int>& src, const unsigned int value, int n, int offset = 0);
- void execute(b3OpenCLArray<unsigned int>& src, const unsigned int value, int n, int offset = 0);
-
- void execute(b3OpenCLArray<int>& src, const int value, int n, int offset = 0);
+ void execute(b3OpenCLArray<int>& src, const int value, int n, int offset = 0);
- void execute(b3OpenCLArray<float>& src, const float value, int n, int offset = 0);
+ void execute(b3OpenCLArray<float>& src, const float value, int n, int offset = 0);
- void execute(b3OpenCLArray<b3Int2>& src, const b3Int2& value, int n, int offset = 0);
+ void execute(b3OpenCLArray<b3Int2>& src, const b3Int2& value, int n, int offset = 0);
- void executeHost(b3AlignedObjectArray<b3Int2> &src, const b3Int2 &value, int n, int offset);
+ void executeHost(b3AlignedObjectArray<b3Int2>& src, const b3Int2& value, int n, int offset);
- void executeHost(b3AlignedObjectArray<int> &src, const int value, int n, int offset);
+ void executeHost(b3AlignedObjectArray<int>& src, const int value, int n, int offset);
// void execute(b3OpenCLArray<b3Int4>& src, const b3Int4& value, int n, int offset = 0);
-
};
-
-
-
-
-#endif //B3_FILL_CL_H
+#endif //B3_FILL_CL_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.cpp b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.cpp
index 94590d11ca..c97d02eb45 100644
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.cpp
+++ b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.cpp
@@ -1,13 +1,13 @@
#include "b3LauncherCL.h"
bool gDebugLauncherCL = false;
-
+
b3LauncherCL::b3LauncherCL(cl_command_queue queue, cl_kernel kernel, const char* name)
-:m_commandQueue(queue),
-m_kernel(kernel),
-m_idx(0),
-m_enableSerialization(false),
-m_name(name)
+ : m_commandQueue(queue),
+ m_kernel(kernel),
+ m_idx(0),
+ m_enableSerialization(false),
+ m_name(name)
{
if (gDebugLauncherCL)
{
@@ -15,59 +15,58 @@ m_name(name)
printf("[%d] Prepare to launch OpenCL kernel %s\n", counter++, name);
}
- m_serializationSizeInBytes = sizeof(int);
+ m_serializationSizeInBytes = sizeof(int);
}
-
+
b3LauncherCL::~b3LauncherCL()
- {
- for (int i=0;i<m_arrays.size();i++)
- {
- delete (m_arrays[i]);
- }
-
- m_arrays.clear();
- if (gDebugLauncherCL)
- {
+{
+ for (int i = 0; i < m_arrays.size(); i++)
+ {
+ delete (m_arrays[i]);
+ }
+
+ m_arrays.clear();
+ if (gDebugLauncherCL)
+ {
static int counter = 0;
- printf("[%d] Finished launching OpenCL kernel %s\n", counter++,m_name);
- }
- }
+ printf("[%d] Finished launching OpenCL kernel %s\n", counter++, m_name);
+ }
+}
-void b3LauncherCL::setBuffer( cl_mem clBuffer)
+void b3LauncherCL::setBuffer(cl_mem clBuffer)
{
- if (m_enableSerialization)
- {
- b3KernelArgData kernelArg;
- kernelArg.m_argIndex = m_idx;
- kernelArg.m_isBuffer = 1;
- kernelArg.m_clBuffer = clBuffer;
-
- cl_mem_info param_name = CL_MEM_SIZE;
- size_t param_value;
- size_t sizeInBytes = sizeof(size_t);
- size_t actualSizeInBytes;
- cl_int err;
- err = clGetMemObjectInfo ( kernelArg.m_clBuffer,
- param_name,
- sizeInBytes,
- &param_value,
- &actualSizeInBytes);
-
- b3Assert( err == CL_SUCCESS );
- kernelArg.m_argSizeInBytes = param_value;
-
- m_kernelArguments.push_back(kernelArg);
- m_serializationSizeInBytes+= sizeof(b3KernelArgData);
- m_serializationSizeInBytes+=param_value;
- }
- cl_int status = clSetKernelArg( m_kernel, m_idx++, sizeof(cl_mem), &clBuffer);
- b3Assert( status == CL_SUCCESS );
-}
+ if (m_enableSerialization)
+ {
+ b3KernelArgData kernelArg;
+ kernelArg.m_argIndex = m_idx;
+ kernelArg.m_isBuffer = 1;
+ kernelArg.m_clBuffer = clBuffer;
+ cl_mem_info param_name = CL_MEM_SIZE;
+ size_t param_value;
+ size_t sizeInBytes = sizeof(size_t);
+ size_t actualSizeInBytes;
+ cl_int err;
+ err = clGetMemObjectInfo(kernelArg.m_clBuffer,
+ param_name,
+ sizeInBytes,
+ &param_value,
+ &actualSizeInBytes);
+
+ b3Assert(err == CL_SUCCESS);
+ kernelArg.m_argSizeInBytes = param_value;
+
+ m_kernelArguments.push_back(kernelArg);
+ m_serializationSizeInBytes += sizeof(b3KernelArgData);
+ m_serializationSizeInBytes += param_value;
+ }
+ cl_int status = clSetKernelArg(m_kernel, m_idx++, sizeof(cl_mem), &clBuffer);
+ b3Assert(status == CL_SUCCESS);
+}
-void b3LauncherCL::setBuffers( b3BufferInfoCL* buffInfo, int n )
+void b3LauncherCL::setBuffers(b3BufferInfoCL* buffInfo, int n)
{
- for(int i=0; i<n; i++)
+ for (int i = 0; i < n; i++)
{
if (m_enableSerialization)
{
@@ -75,106 +74,103 @@ void b3LauncherCL::setBuffers( b3BufferInfoCL* buffInfo, int n )
kernelArg.m_argIndex = m_idx;
kernelArg.m_isBuffer = 1;
kernelArg.m_clBuffer = buffInfo[i].m_clBuffer;
-
+
cl_mem_info param_name = CL_MEM_SIZE;
size_t param_value;
size_t sizeInBytes = sizeof(size_t);
size_t actualSizeInBytes;
cl_int err;
- err = clGetMemObjectInfo ( kernelArg.m_clBuffer,
- param_name,
- sizeInBytes,
- &param_value,
- &actualSizeInBytes);
-
- b3Assert( err == CL_SUCCESS );
+ err = clGetMemObjectInfo(kernelArg.m_clBuffer,
+ param_name,
+ sizeInBytes,
+ &param_value,
+ &actualSizeInBytes);
+
+ b3Assert(err == CL_SUCCESS);
kernelArg.m_argSizeInBytes = param_value;
-
+
m_kernelArguments.push_back(kernelArg);
- m_serializationSizeInBytes+= sizeof(b3KernelArgData);
- m_serializationSizeInBytes+=param_value;
- }
- cl_int status = clSetKernelArg( m_kernel, m_idx++, sizeof(cl_mem), &buffInfo[i].m_clBuffer);
- b3Assert( status == CL_SUCCESS );
- }
+ m_serializationSizeInBytes += sizeof(b3KernelArgData);
+ m_serializationSizeInBytes += param_value;
+ }
+ cl_int status = clSetKernelArg(m_kernel, m_idx++, sizeof(cl_mem), &buffInfo[i].m_clBuffer);
+ b3Assert(status == CL_SUCCESS);
+ }
}
struct b3KernelArgDataUnaligned
{
- int m_isBuffer;
- int m_argIndex;
- int m_argSizeInBytes;
+ int m_isBuffer;
+ int m_argIndex;
+ int m_argSizeInBytes;
int m_unusedPadding;
- union
- {
- cl_mem m_clBuffer;
- unsigned char m_argData[B3_CL_MAX_ARG_SIZE];
- };
-
+ union {
+ cl_mem m_clBuffer;
+ unsigned char m_argData[B3_CL_MAX_ARG_SIZE];
+ };
};
#include <string.h>
-
-
int b3LauncherCL::deserializeArgs(unsigned char* buf, int bufSize, cl_context ctx)
{
- int index=0;
-
- int numArguments = *(int*) &buf[index];
- index+=sizeof(int);
-
- for (int i=0;i<numArguments;i++)
- {
- b3KernelArgDataUnaligned* arg = (b3KernelArgDataUnaligned*)&buf[index];
-
- index+=sizeof(b3KernelArgData);
- if (arg->m_isBuffer)
- {
- b3OpenCLArray<unsigned char>* clData = new b3OpenCLArray<unsigned char>(ctx,m_commandQueue, arg->m_argSizeInBytes);
- clData->resize(arg->m_argSizeInBytes);
-
- clData->copyFromHostPointer(&buf[index], arg->m_argSizeInBytes);
-
- arg->m_clBuffer = clData->getBufferCL();
-
- m_arrays.push_back(clData);
-
- cl_int status = clSetKernelArg( m_kernel, m_idx++, sizeof(cl_mem), &arg->m_clBuffer);
- b3Assert( status == CL_SUCCESS );
- index+=arg->m_argSizeInBytes;
- } else
- {
- cl_int status = clSetKernelArg( m_kernel, m_idx++, arg->m_argSizeInBytes, &arg->m_argData);
- b3Assert( status == CL_SUCCESS );
- }
+ int index = 0;
+
+ int numArguments = *(int*)&buf[index];
+ index += sizeof(int);
+
+ for (int i = 0; i < numArguments; i++)
+ {
+ b3KernelArgDataUnaligned* arg = (b3KernelArgDataUnaligned*)&buf[index];
+
+ index += sizeof(b3KernelArgData);
+ if (arg->m_isBuffer)
+ {
+ b3OpenCLArray<unsigned char>* clData = new b3OpenCLArray<unsigned char>(ctx, m_commandQueue, arg->m_argSizeInBytes);
+ clData->resize(arg->m_argSizeInBytes);
+
+ clData->copyFromHostPointer(&buf[index], arg->m_argSizeInBytes);
+
+ arg->m_clBuffer = clData->getBufferCL();
+
+ m_arrays.push_back(clData);
+
+ cl_int status = clSetKernelArg(m_kernel, m_idx++, sizeof(cl_mem), &arg->m_clBuffer);
+ b3Assert(status == CL_SUCCESS);
+ index += arg->m_argSizeInBytes;
+ }
+ else
+ {
+ cl_int status = clSetKernelArg(m_kernel, m_idx++, arg->m_argSizeInBytes, &arg->m_argData);
+ b3Assert(status == CL_SUCCESS);
+ }
b3KernelArgData b;
- memcpy(&b,arg,sizeof(b3KernelArgDataUnaligned));
- m_kernelArguments.push_back(b);
- }
-m_serializationSizeInBytes = index;
- return index;
+ memcpy(&b, arg, sizeof(b3KernelArgDataUnaligned));
+ m_kernelArguments.push_back(b);
+ }
+ m_serializationSizeInBytes = index;
+ return index;
}
int b3LauncherCL::validateResults(unsigned char* goldBuffer, int goldBufferCapacity, cl_context ctx)
- {
- int index=0;
-
- int numArguments = *(int*) &goldBuffer[index];
- index+=sizeof(int);
+{
+ int index = 0;
+
+ int numArguments = *(int*)&goldBuffer[index];
+ index += sizeof(int);
if (numArguments != m_kernelArguments.size())
{
- printf("failed validation: expected %d arguments, found %d\n",numArguments, m_kernelArguments.size());
+ printf("failed validation: expected %d arguments, found %d\n", numArguments, m_kernelArguments.size());
return -1;
}
-
- for (int ii=0;ii<numArguments;ii++)
- {
- b3KernelArgData* argGold = (b3KernelArgData*)&goldBuffer[index];
+
+ for (int ii = 0; ii < numArguments; ii++)
+ {
+ b3KernelArgData* argGold = (b3KernelArgData*)&goldBuffer[index];
if (m_kernelArguments[ii].m_argSizeInBytes != argGold->m_argSizeInBytes)
{
- printf("failed validation: argument %d sizeInBytes expected: %d, found %d\n",ii, argGold->m_argSizeInBytes, m_kernelArguments[ii].m_argSizeInBytes);
+ printf("failed validation: argument %d sizeInBytes expected: %d, found %d\n", ii, argGold->m_argSizeInBytes, m_kernelArguments[ii].m_argSizeInBytes);
return -2;
}
@@ -184,125 +180,117 @@ int b3LauncherCL::validateResults(unsigned char* goldBuffer, int goldBufferCapac
if (expected != found)
{
- printf("failed validation: argument %d isBuffer expected: %d, found %d\n",ii,expected, found);
+ printf("failed validation: argument %d isBuffer expected: %d, found %d\n", ii, expected, found);
return -3;
}
}
- index+=sizeof(b3KernelArgData);
+ index += sizeof(b3KernelArgData);
if (argGold->m_isBuffer)
- {
-
- unsigned char* memBuf= (unsigned char*) malloc(m_kernelArguments[ii].m_argSizeInBytes);
+ {
+ unsigned char* memBuf = (unsigned char*)malloc(m_kernelArguments[ii].m_argSizeInBytes);
unsigned char* goldBuf = &goldBuffer[index];
- for (int j=0;j<m_kernelArguments[j].m_argSizeInBytes;j++)
+ for (int j = 0; j < m_kernelArguments[j].m_argSizeInBytes; j++)
{
memBuf[j] = 0xaa;
}
cl_int status = 0;
- status = clEnqueueReadBuffer( m_commandQueue, m_kernelArguments[ii].m_clBuffer, CL_TRUE, 0, m_kernelArguments[ii].m_argSizeInBytes,
- memBuf, 0,0,0 );
- b3Assert( status==CL_SUCCESS );
- clFinish(m_commandQueue);
+ status = clEnqueueReadBuffer(m_commandQueue, m_kernelArguments[ii].m_clBuffer, CL_TRUE, 0, m_kernelArguments[ii].m_argSizeInBytes,
+ memBuf, 0, 0, 0);
+ b3Assert(status == CL_SUCCESS);
+ clFinish(m_commandQueue);
- for (int b=0;b<m_kernelArguments[ii].m_argSizeInBytes;b++)
+ for (int b = 0; b < m_kernelArguments[ii].m_argSizeInBytes; b++)
{
int expected = goldBuf[b];
int found = memBuf[b];
if (expected != found)
{
printf("failed validation: argument %d OpenCL data at byte position %d expected: %d, found %d\n",
- ii, b, expected, found);
+ ii, b, expected, found);
return -4;
}
}
-
- index+=argGold->m_argSizeInBytes;
- } else
- {
-
+ index += argGold->m_argSizeInBytes;
+ }
+ else
+ {
//compare content
- for (int b=0;b<m_kernelArguments[ii].m_argSizeInBytes;b++)
+ for (int b = 0; b < m_kernelArguments[ii].m_argSizeInBytes; b++)
{
int expected = argGold->m_argData[b];
- int found =m_kernelArguments[ii].m_argData[b];
+ int found = m_kernelArguments[ii].m_argData[b];
if (expected != found)
{
printf("failed validation: argument %d const data at byte position %d expected: %d, found %d\n",
- ii, b, expected, found);
+ ii, b, expected, found);
return -5;
}
}
-
- }
- }
- return index;
-
+ }
+ }
+ return index;
}
int b3LauncherCL::serializeArguments(unsigned char* destBuffer, int destBufferCapacity)
{
-//initialize to known values
-for (int i=0;i<destBufferCapacity;i++)
- destBuffer[i] = 0xec;
-
- assert(destBufferCapacity>=m_serializationSizeInBytes);
-
- //todo: use the b3Serializer for this to allow for 32/64bit, endianness etc
- int numArguments = m_kernelArguments.size();
- int curBufferSize = 0;
- int* dest = (int*)&destBuffer[curBufferSize];
- *dest = numArguments;
- curBufferSize += sizeof(int);
-
-
-
- for (int i=0;i<this->m_kernelArguments.size();i++)
- {
- b3KernelArgData* arg = (b3KernelArgData*) &destBuffer[curBufferSize];
- *arg = m_kernelArguments[i];
- curBufferSize+=sizeof(b3KernelArgData);
- if (arg->m_isBuffer==1)
- {
- //copy the OpenCL buffer content
- cl_int status = 0;
- status = clEnqueueReadBuffer( m_commandQueue, arg->m_clBuffer, 0, 0, arg->m_argSizeInBytes,
- &destBuffer[curBufferSize], 0,0,0 );
- b3Assert( status==CL_SUCCESS );
- clFinish(m_commandQueue);
- curBufferSize+=arg->m_argSizeInBytes;
- }
-
- }
- return curBufferSize;
+ //initialize to known values
+ for (int i = 0; i < destBufferCapacity; i++)
+ destBuffer[i] = 0xec;
+
+ assert(destBufferCapacity >= m_serializationSizeInBytes);
+
+ //todo: use the b3Serializer for this to allow for 32/64bit, endianness etc
+ int numArguments = m_kernelArguments.size();
+ int curBufferSize = 0;
+ int* dest = (int*)&destBuffer[curBufferSize];
+ *dest = numArguments;
+ curBufferSize += sizeof(int);
+
+ for (int i = 0; i < this->m_kernelArguments.size(); i++)
+ {
+ b3KernelArgData* arg = (b3KernelArgData*)&destBuffer[curBufferSize];
+ *arg = m_kernelArguments[i];
+ curBufferSize += sizeof(b3KernelArgData);
+ if (arg->m_isBuffer == 1)
+ {
+ //copy the OpenCL buffer content
+ cl_int status = 0;
+ status = clEnqueueReadBuffer(m_commandQueue, arg->m_clBuffer, 0, 0, arg->m_argSizeInBytes,
+ &destBuffer[curBufferSize], 0, 0, 0);
+ b3Assert(status == CL_SUCCESS);
+ clFinish(m_commandQueue);
+ curBufferSize += arg->m_argSizeInBytes;
+ }
+ }
+ return curBufferSize;
}
void b3LauncherCL::serializeToFile(const char* fileName, int numWorkItems)
{
int num = numWorkItems;
int buffSize = getSerializationBufferSize();
- unsigned char* buf = new unsigned char[buffSize+sizeof(int)];
- for (int i=0;i<buffSize+1;i++)
+ unsigned char* buf = new unsigned char[buffSize + sizeof(int)];
+ for (int i = 0; i < buffSize + 1; i++)
{
unsigned char* ptr = (unsigned char*)&buf[i];
*ptr = 0xff;
}
-// int actualWrite = serializeArguments(buf,buffSize);
-
-// unsigned char* cptr = (unsigned char*)&buf[buffSize];
-// printf("buf[buffSize] = %d\n",*cptr);
-
- assert(buf[buffSize]==0xff);//check for buffer overrun
+ // int actualWrite = serializeArguments(buf,buffSize);
+
+ // unsigned char* cptr = (unsigned char*)&buf[buffSize];
+ // printf("buf[buffSize] = %d\n",*cptr);
+
+ assert(buf[buffSize] == 0xff); //check for buffer overrun
int* ptr = (int*)&buf[buffSize];
-
+
*ptr = num;
-
- FILE* f = fopen(fileName,"wb");
- fwrite(buf,buffSize+sizeof(int),1,f);
+
+ FILE* f = fopen(fileName, "wb");
+ fwrite(buf, buffSize + sizeof(int), 1, f);
fclose(f);
delete[] buf;
-}
-
+}
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h
index 1b267b31ef..18e9c1db2b 100644
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h
+++ b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h
@@ -9,60 +9,57 @@
#define B3_DEBUG_SERIALIZE_CL
-
#ifdef _WIN32
-#pragma warning(disable :4996)
+#pragma warning(disable : 4996)
#endif
#define B3_CL_MAX_ARG_SIZE 16
-B3_ATTRIBUTE_ALIGNED16(struct) b3KernelArgData
+B3_ATTRIBUTE_ALIGNED16(struct)
+b3KernelArgData
{
- int m_isBuffer;
- int m_argIndex;
- int m_argSizeInBytes;
+ int m_isBuffer;
+ int m_argIndex;
+ int m_argSizeInBytes;
int m_unusedPadding;
- union
- {
- cl_mem m_clBuffer;
- unsigned char m_argData[B3_CL_MAX_ARG_SIZE];
- };
-
+ union {
+ cl_mem m_clBuffer;
+ unsigned char m_argData[B3_CL_MAX_ARG_SIZE];
+ };
};
class b3LauncherCL
{
-
cl_command_queue m_commandQueue;
cl_kernel m_kernel;
int m_idx;
-
- b3AlignedObjectArray<b3KernelArgData> m_kernelArguments;
- int m_serializationSizeInBytes;
- bool m_enableSerialization;
+
+ b3AlignedObjectArray<b3KernelArgData> m_kernelArguments;
+ int m_serializationSizeInBytes;
+ bool m_enableSerialization;
const char* m_name;
- public:
-
- b3AlignedObjectArray<b3OpenCLArray<unsigned char>* > m_arrays;
-
- b3LauncherCL(cl_command_queue queue, cl_kernel kernel, const char* name);
-
- virtual ~b3LauncherCL();
-
- void setBuffer( cl_mem clBuffer);
-
- void setBuffers( b3BufferInfoCL* buffInfo, int n );
-
- int getSerializationBufferSize() const
- {
- return m_serializationSizeInBytes;
- }
-
- int deserializeArgs(unsigned char* buf, int bufSize, cl_context ctx);
+
+public:
+ b3AlignedObjectArray<b3OpenCLArray<unsigned char>*> m_arrays;
+
+ b3LauncherCL(cl_command_queue queue, cl_kernel kernel, const char* name);
+
+ virtual ~b3LauncherCL();
+
+ void setBuffer(cl_mem clBuffer);
+
+ void setBuffers(b3BufferInfoCL* buffInfo, int n);
+
+ int getSerializationBufferSize() const
+ {
+ return m_serializationSizeInBytes;
+ }
+
+ int deserializeArgs(unsigned char* buf, int bufSize, cl_context ctx);
inline int validateResults(unsigned char* goldBuffer, int goldBufferCapacity, cl_context ctx);
- int serializeArguments(unsigned char* destBuffer, int destBufferCapacity);
-
+ int serializeArguments(unsigned char* destBuffer, int destBufferCapacity);
+
int getNumArguments() const
{
return m_kernelArguments.size();
@@ -75,61 +72,57 @@ class b3LauncherCL
void serializeToFile(const char* fileName, int numWorkItems);
- template<typename T>
- inline void setConst( const T& consts )
- {
- int sz=sizeof(T);
- b3Assert(sz<=B3_CL_MAX_ARG_SIZE);
-
- if (m_enableSerialization)
- {
- b3KernelArgData kernelArg;
- kernelArg.m_argIndex = m_idx;
- kernelArg.m_isBuffer = 0;
- T* destArg = (T*)kernelArg.m_argData;
- *destArg = consts;
- kernelArg.m_argSizeInBytes = sizeof(T);
- m_kernelArguments.push_back(kernelArg);
- m_serializationSizeInBytes+=sizeof(b3KernelArgData);
- }
-
- cl_int status = clSetKernelArg( m_kernel, m_idx++, sz, &consts );
- b3Assert( status == CL_SUCCESS );
- }
+ template <typename T>
+ inline void setConst(const T& consts)
+ {
+ int sz = sizeof(T);
+ b3Assert(sz <= B3_CL_MAX_ARG_SIZE);
- inline void launch1D( int numThreads, int localSize = 64)
+ if (m_enableSerialization)
{
- launch2D( numThreads, 1, localSize, 1 );
+ b3KernelArgData kernelArg;
+ kernelArg.m_argIndex = m_idx;
+ kernelArg.m_isBuffer = 0;
+ T* destArg = (T*)kernelArg.m_argData;
+ *destArg = consts;
+ kernelArg.m_argSizeInBytes = sizeof(T);
+ m_kernelArguments.push_back(kernelArg);
+ m_serializationSizeInBytes += sizeof(b3KernelArgData);
}
- inline void launch2D( int numThreadsX, int numThreadsY, int localSizeX, int localSizeY )
- {
- size_t gRange[3] = {1,1,1};
- size_t lRange[3] = {1,1,1};
- lRange[0] = localSizeX;
- lRange[1] = localSizeY;
- gRange[0] = b3Max((size_t)1, (numThreadsX/lRange[0])+(!(numThreadsX%lRange[0])?0:1));
- gRange[0] *= lRange[0];
- gRange[1] = b3Max((size_t)1, (numThreadsY/lRange[1])+(!(numThreadsY%lRange[1])?0:1));
- gRange[1] *= lRange[1];
-
- cl_int status = clEnqueueNDRangeKernel( m_commandQueue,
- m_kernel, 2, NULL, gRange, lRange, 0,0,0 );
- if (status != CL_SUCCESS)
- {
- printf("Error: OpenCL status = %d\n",status);
- }
- b3Assert( status == CL_SUCCESS );
+ cl_int status = clSetKernelArg(m_kernel, m_idx++, sz, &consts);
+ b3Assert(status == CL_SUCCESS);
+ }
- }
-
- void enableSerialization(bool serialize)
+ inline void launch1D(int numThreads, int localSize = 64)
+ {
+ launch2D(numThreads, 1, localSize, 1);
+ }
+
+ inline void launch2D(int numThreadsX, int numThreadsY, int localSizeX, int localSizeY)
+ {
+ size_t gRange[3] = {1, 1, 1};
+ size_t lRange[3] = {1, 1, 1};
+ lRange[0] = localSizeX;
+ lRange[1] = localSizeY;
+ gRange[0] = b3Max((size_t)1, (numThreadsX / lRange[0]) + (!(numThreadsX % lRange[0]) ? 0 : 1));
+ gRange[0] *= lRange[0];
+ gRange[1] = b3Max((size_t)1, (numThreadsY / lRange[1]) + (!(numThreadsY % lRange[1]) ? 0 : 1));
+ gRange[1] *= lRange[1];
+
+ cl_int status = clEnqueueNDRangeKernel(m_commandQueue,
+ m_kernel, 2, NULL, gRange, lRange, 0, 0, 0);
+ if (status != CL_SUCCESS)
{
- m_enableSerialization = serialize;
+ printf("Error: OpenCL status = %d\n", status);
}
-
-};
-
+ b3Assert(status == CL_SUCCESS);
+ }
+ void enableSerialization(bool serialize)
+ {
+ m_enableSerialization = serialize;
+ }
+};
-#endif //B3_LAUNCHER_CL_H
+#endif //B3_LAUNCHER_CL_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h
index d70c30f53f..e837cceb66 100644
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h
+++ b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h
@@ -7,16 +7,16 @@
template <typename T>
class b3OpenCLArray
{
- size_t m_size;
- size_t m_capacity;
- cl_mem m_clBuffer;
+ size_t m_size;
+ size_t m_capacity;
+ cl_mem m_clBuffer;
- cl_context m_clContext;
+ cl_context m_clContext;
cl_command_queue m_commandQueue;
- bool m_ownsMemory;
+ bool m_ownsMemory;
- bool m_allowGrowingCapacity;
+ bool m_allowGrowingCapacity;
void deallocate()
{
@@ -25,22 +25,19 @@ class b3OpenCLArray
clReleaseMemObject(m_clBuffer);
}
m_clBuffer = 0;
- m_capacity=0;
+ m_capacity = 0;
}
b3OpenCLArray<T>& operator=(const b3OpenCLArray<T>& src);
- B3_FORCE_INLINE size_t allocSize(size_t size)
- {
- return (size ? size*2 : 1);
- }
+ B3_FORCE_INLINE size_t allocSize(size_t size)
+ {
+ return (size ? size * 2 : 1);
+ }
public:
-
- b3OpenCLArray(cl_context ctx, cl_command_queue queue, size_t initialCapacity=0, bool allowGrowingCapacity=true)
- :m_size(0), m_capacity(0),m_clBuffer(0),
- m_clContext(ctx),m_commandQueue(queue),
- m_ownsMemory(true),m_allowGrowingCapacity(true)
+ b3OpenCLArray(cl_context ctx, cl_command_queue queue, size_t initialCapacity = 0, bool allowGrowingCapacity = true)
+ : m_size(0), m_capacity(0), m_clBuffer(0), m_clContext(ctx), m_commandQueue(queue), m_ownsMemory(true), m_allowGrowingCapacity(true)
{
if (initialCapacity)
{
@@ -60,34 +57,32 @@ public:
m_capacity = sizeInElements;
}
-// we could enable this assignment, but need to make sure to avoid accidental deep copies
-// b3OpenCLArray<T>& operator=(const b3AlignedObjectArray<T>& src)
-// {
-// copyFromArray(src);
-// return *this;
-// }
+ // we could enable this assignment, but need to make sure to avoid accidental deep copies
+ // b3OpenCLArray<T>& operator=(const b3AlignedObjectArray<T>& src)
+ // {
+ // copyFromArray(src);
+ // return *this;
+ // }
-
- cl_mem getBufferCL() const
+ cl_mem getBufferCL() const
{
return m_clBuffer;
}
-
virtual ~b3OpenCLArray()
{
deallocate();
- m_size=0;
- m_capacity=0;
+ m_size = 0;
+ m_capacity = 0;
}
- B3_FORCE_INLINE bool push_back(const T& _Val,bool waitForCompletion=true)
+ B3_FORCE_INLINE bool push_back(const T& _Val, bool waitForCompletion = true)
{
bool result = true;
size_t sz = size();
- if( sz == capacity() )
+ if (sz == capacity())
{
- result = reserve( allocSize(size()) );
+ result = reserve(allocSize(size()));
}
copyFromHostPointer(&_Val, 1, sz, waitForCompletion);
m_size++;
@@ -96,23 +91,23 @@ public:
B3_FORCE_INLINE T forcedAt(size_t n) const
{
- b3Assert(n>=0);
- b3Assert(n<capacity());
+ b3Assert(n >= 0);
+ b3Assert(n < capacity());
T elem;
- copyToHostPointer(&elem,1,n,true);
+ copyToHostPointer(&elem, 1, n, true);
return elem;
}
B3_FORCE_INLINE T at(size_t n) const
{
- b3Assert(n>=0);
- b3Assert(n<size());
+ b3Assert(n >= 0);
+ b3Assert(n < size());
T elem;
- copyToHostPointer(&elem,1,n,true);
+ copyToHostPointer(&elem, 1, n, true);
return elem;
}
- B3_FORCE_INLINE bool resize(size_t newsize, bool copyOldContents=true)
+ B3_FORCE_INLINE bool resize(size_t newsize, bool copyOldContents = true)
{
bool result = true;
size_t curSize = size();
@@ -120,11 +115,12 @@ public:
if (newsize < curSize)
{
//leave the OpenCL memory for now
- } else
+ }
+ else
{
if (newsize > size())
{
- result = reserve(newsize,copyOldContents);
+ result = reserve(newsize, copyOldContents);
}
//leave new data uninitialized (init in debug mode?)
@@ -134,7 +130,8 @@ public:
if (result)
{
m_size = newsize;
- } else
+ }
+ else
{
m_size = 0;
}
@@ -146,25 +143,25 @@ public:
return m_size;
}
- B3_FORCE_INLINE size_t capacity() const
+ B3_FORCE_INLINE size_t capacity() const
{
return m_capacity;
}
- B3_FORCE_INLINE bool reserve(size_t _Count, bool copyOldContents=true)
+ B3_FORCE_INLINE bool reserve(size_t _Count, bool copyOldContents = true)
{
- bool result=true;
+ bool result = true;
// determine new minimum length of allocated storage
if (capacity() < _Count)
- { // not enough room, reallocate
+ { // not enough room, reallocate
if (m_allowGrowingCapacity)
{
cl_int ciErrNum;
//create a new OpenCL buffer
- size_t memSizeInBytes = sizeof(T)*_Count;
+ size_t memSizeInBytes = sizeof(T) * _Count;
cl_mem buf = clCreateBuffer(m_clContext, CL_MEM_READ_WRITE, memSizeInBytes, NULL, &ciErrNum);
- if (ciErrNum!=CL_SUCCESS)
+ if (ciErrNum != CL_SUCCESS)
{
b3Error("OpenCL out-of-memory\n");
_Count = 0;
@@ -173,13 +170,13 @@ public:
//#define B3_ALWAYS_INITIALIZE_OPENCL_BUFFERS
#ifdef B3_ALWAYS_INITIALIZE_OPENCL_BUFFERS
unsigned char* src = (unsigned char*)malloc(memSizeInBytes);
- for (size_t i=0;i<memSizeInBytes;i++)
+ for (size_t i = 0; i < memSizeInBytes; i++)
src[i] = 0xbb;
- ciErrNum = clEnqueueWriteBuffer( m_commandQueue, buf, CL_TRUE, 0, memSizeInBytes, src, 0,0,0 );
- b3Assert(ciErrNum==CL_SUCCESS);
+ ciErrNum = clEnqueueWriteBuffer(m_commandQueue, buf, CL_TRUE, 0, memSizeInBytes, src, 0, 0, 0);
+ b3Assert(ciErrNum == CL_SUCCESS);
clFinish(m_commandQueue);
free(src);
-#endif //B3_ALWAYS_INITIALIZE_OPENCL_BUFFERS
+#endif //B3_ALWAYS_INITIALIZE_OPENCL_BUFFERS
if (result)
{
@@ -193,21 +190,21 @@ public:
m_clBuffer = buf;
m_capacity = _Count;
- } else
+ }
+ else
{
//fail: assert and
b3Assert(0);
deallocate();
- result=false;
+ result = false;
}
}
return result;
}
-
- void copyToCL(cl_mem destination, size_t numElements, size_t firstElem=0, size_t dstOffsetInElems=0) const
+ void copyToCL(cl_mem destination, size_t numElements, size_t firstElem = 0, size_t dstOffsetInElems = 0) const
{
- if (numElements<=0)
+ if (numElements <= 0)
return;
b3Assert(m_clBuffer);
@@ -216,75 +213,74 @@ public:
//likely some error, destination is same as source
b3Assert(m_clBuffer != destination);
- b3Assert((firstElem+numElements)<=m_size);
+ b3Assert((firstElem + numElements) <= m_size);
cl_int status = 0;
+ b3Assert(numElements > 0);
+ b3Assert(numElements <= m_size);
- b3Assert(numElements>0);
- b3Assert(numElements<=m_size);
-
- size_t srcOffsetBytes = sizeof(T)*firstElem;
- size_t dstOffsetInBytes = sizeof(T)*dstOffsetInElems;
+ size_t srcOffsetBytes = sizeof(T) * firstElem;
+ size_t dstOffsetInBytes = sizeof(T) * dstOffsetInElems;
- status = clEnqueueCopyBuffer( m_commandQueue, m_clBuffer, destination,
- srcOffsetBytes, dstOffsetInBytes, sizeof(T)*numElements, 0, 0, 0 );
+ status = clEnqueueCopyBuffer(m_commandQueue, m_clBuffer, destination,
+ srcOffsetBytes, dstOffsetInBytes, sizeof(T) * numElements, 0, 0, 0);
- b3Assert( status == CL_SUCCESS );
+ b3Assert(status == CL_SUCCESS);
}
- void copyFromHost(const b3AlignedObjectArray<T>& srcArray, bool waitForCompletion=true)
+ void copyFromHost(const b3AlignedObjectArray<T>& srcArray, bool waitForCompletion = true)
{
size_t newSize = srcArray.size();
bool copyOldContents = false;
- resize (newSize,copyOldContents);
+ resize(newSize, copyOldContents);
if (newSize)
- copyFromHostPointer(&srcArray[0],newSize,0,waitForCompletion);
-
+ copyFromHostPointer(&srcArray[0], newSize, 0, waitForCompletion);
}
- void copyFromHostPointer(const T* src, size_t numElems, size_t destFirstElem= 0, bool waitForCompletion=true)
+ void copyFromHostPointer(const T* src, size_t numElems, size_t destFirstElem = 0, bool waitForCompletion = true)
{
- b3Assert(numElems+destFirstElem <= capacity());
+ b3Assert(numElems + destFirstElem <= capacity());
- if (numElems+destFirstElem)
+ if (numElems + destFirstElem)
{
cl_int status = 0;
- size_t sizeInBytes=sizeof(T)*numElems;
- status = clEnqueueWriteBuffer( m_commandQueue, m_clBuffer, 0, sizeof(T)*destFirstElem, sizeInBytes,
- src, 0,0,0 );
- b3Assert(status == CL_SUCCESS );
+ size_t sizeInBytes = sizeof(T) * numElems;
+ status = clEnqueueWriteBuffer(m_commandQueue, m_clBuffer, 0, sizeof(T) * destFirstElem, sizeInBytes,
+ src, 0, 0, 0);
+ b3Assert(status == CL_SUCCESS);
if (waitForCompletion)
clFinish(m_commandQueue);
- } else
+ }
+ else
{
b3Error("copyFromHostPointer invalid range\n");
}
}
-
- void copyToHost(b3AlignedObjectArray<T>& destArray, bool waitForCompletion=true) const
+ void copyToHost(b3AlignedObjectArray<T>& destArray, bool waitForCompletion = true) const
{
destArray.resize(this->size());
if (size())
- copyToHostPointer(&destArray[0], size(),0,waitForCompletion);
+ copyToHostPointer(&destArray[0], size(), 0, waitForCompletion);
}
- void copyToHostPointer(T* destPtr, size_t numElem, size_t srcFirstElem=0, bool waitForCompletion=true) const
+ void copyToHostPointer(T* destPtr, size_t numElem, size_t srcFirstElem = 0, bool waitForCompletion = true) const
{
- b3Assert(numElem+srcFirstElem <= capacity());
+ b3Assert(numElem + srcFirstElem <= capacity());
- if(numElem+srcFirstElem <= capacity())
+ if (numElem + srcFirstElem <= capacity())
{
cl_int status = 0;
- status = clEnqueueReadBuffer( m_commandQueue, m_clBuffer, 0, sizeof(T)*srcFirstElem, sizeof(T)*numElem,
- destPtr, 0,0,0 );
- b3Assert( status==CL_SUCCESS );
+ status = clEnqueueReadBuffer(m_commandQueue, m_clBuffer, 0, sizeof(T) * srcFirstElem, sizeof(T) * numElem,
+ destPtr, 0, 0, 0);
+ b3Assert(status == CL_SUCCESS);
if (waitForCompletion)
clFinish(m_commandQueue);
- } else
+ }
+ else
{
b3Error("copyToHostPointer invalid range\n");
}
@@ -296,11 +292,9 @@ public:
resize(newSize);
if (size())
{
- src.copyToCL(m_clBuffer,size());
+ src.copyToCL(m_clBuffer, size());
}
}
-
};
-
-#endif //B3_OPENCL_ARRAY_H
+#endif //B3_OPENCL_ARRAY_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.cpp b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.cpp
index 42cd197740..822b511633 100644
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.cpp
+++ b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.cpp
@@ -7,25 +7,24 @@
#include "kernels/PrefixScanKernelsCL.h"
b3PrefixScanCL::b3PrefixScanCL(cl_context ctx, cl_device_id device, cl_command_queue queue, int size)
-:m_commandQueue(queue)
+ : m_commandQueue(queue)
{
const char* scanKernelSource = prefixScanKernelsCL;
cl_int pErrNum;
- char* additionalMacros=0;
+ char* additionalMacros = 0;
- m_workBuffer = new b3OpenCLArray<unsigned int>(ctx,queue,size);
- cl_program scanProg = b3OpenCLUtils::compileCLProgramFromString( ctx, device, scanKernelSource, &pErrNum,additionalMacros, B3_PREFIXSCAN_PROG_PATH);
+ m_workBuffer = new b3OpenCLArray<unsigned int>(ctx, queue, size);
+ cl_program scanProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, scanKernelSource, &pErrNum, additionalMacros, B3_PREFIXSCAN_PROG_PATH);
b3Assert(scanProg);
- m_localScanKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, scanKernelSource, "LocalScanKernel", &pErrNum, scanProg,additionalMacros );
- b3Assert(m_localScanKernel );
- m_blockSumKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, scanKernelSource, "TopLevelScanKernel", &pErrNum, scanProg,additionalMacros );
- b3Assert(m_blockSumKernel );
- m_propagationKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, scanKernelSource, "AddOffsetKernel", &pErrNum, scanProg,additionalMacros );
- b3Assert(m_propagationKernel );
+ m_localScanKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, scanKernelSource, "LocalScanKernel", &pErrNum, scanProg, additionalMacros);
+ b3Assert(m_localScanKernel);
+ m_blockSumKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, scanKernelSource, "TopLevelScanKernel", &pErrNum, scanProg, additionalMacros);
+ b3Assert(m_blockSumKernel);
+ m_propagationKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, scanKernelSource, "AddOffsetKernel", &pErrNum, scanProg, additionalMacros);
+ b3Assert(m_propagationKernel);
}
-
b3PrefixScanCL::~b3PrefixScanCL()
{
delete m_workBuffer;
@@ -34,20 +33,19 @@ b3PrefixScanCL::~b3PrefixScanCL()
clReleaseKernel(m_propagationKernel);
}
-template<class T>
+template <class T>
T b3NextPowerOf2(T n)
{
n -= 1;
- for(int i=0; i<sizeof(T)*8; i++)
- n = n | (n>>i);
- return n+1;
+ for (int i = 0; i < sizeof(T) * 8; i++)
+ n = n | (n >> i);
+ return n + 1;
}
void b3PrefixScanCL::execute(b3OpenCLArray<unsigned int>& src, b3OpenCLArray<unsigned int>& dst, int n, unsigned int* sum)
{
-
-// b3Assert( data->m_option == EXCLUSIVE );
- const unsigned int numBlocks = (const unsigned int)( (n+BLOCK_SIZE*2-1)/(BLOCK_SIZE*2) );
+ // b3Assert( data->m_option == EXCLUSIVE );
+ const unsigned int numBlocks = (const unsigned int)((n + BLOCK_SIZE * 2 - 1) / (BLOCK_SIZE * 2));
dst.resize(src.size());
m_workBuffer->resize(src.size());
@@ -55,55 +53,51 @@ void b3PrefixScanCL::execute(b3OpenCLArray<unsigned int>& src, b3OpenCLArray<uns
b3Int4 constBuffer;
constBuffer.x = n;
constBuffer.y = numBlocks;
- constBuffer.z = (int)b3NextPowerOf2( numBlocks );
+ constBuffer.z = (int)b3NextPowerOf2(numBlocks);
b3OpenCLArray<unsigned int>* srcNative = &src;
b3OpenCLArray<unsigned int>* dstNative = &dst;
-
+
{
- b3BufferInfoCL bInfo[] = { b3BufferInfoCL( dstNative->getBufferCL() ), b3BufferInfoCL( srcNative->getBufferCL() ), b3BufferInfoCL( m_workBuffer->getBufferCL() ) };
+ b3BufferInfoCL bInfo[] = {b3BufferInfoCL(dstNative->getBufferCL()), b3BufferInfoCL(srcNative->getBufferCL()), b3BufferInfoCL(m_workBuffer->getBufferCL())};
- b3LauncherCL launcher( m_commandQueue, m_localScanKernel,"m_localScanKernel" );
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst( constBuffer );
- launcher.launch1D( numBlocks*BLOCK_SIZE, BLOCK_SIZE );
+ b3LauncherCL launcher(m_commandQueue, m_localScanKernel, "m_localScanKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setConst(constBuffer);
+ launcher.launch1D(numBlocks * BLOCK_SIZE, BLOCK_SIZE);
}
{
- b3BufferInfoCL bInfo[] = { b3BufferInfoCL( m_workBuffer->getBufferCL() ) };
+ b3BufferInfoCL bInfo[] = {b3BufferInfoCL(m_workBuffer->getBufferCL())};
- b3LauncherCL launcher( m_commandQueue, m_blockSumKernel,"m_blockSumKernel" );
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst( constBuffer );
- launcher.launch1D( BLOCK_SIZE, BLOCK_SIZE );
+ b3LauncherCL launcher(m_commandQueue, m_blockSumKernel, "m_blockSumKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setConst(constBuffer);
+ launcher.launch1D(BLOCK_SIZE, BLOCK_SIZE);
}
-
- if( numBlocks > 1 )
+ if (numBlocks > 1)
{
- b3BufferInfoCL bInfo[] = { b3BufferInfoCL( dstNative->getBufferCL() ), b3BufferInfoCL( m_workBuffer->getBufferCL() ) };
- b3LauncherCL launcher( m_commandQueue, m_propagationKernel,"m_propagationKernel" );
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst( constBuffer );
- launcher.launch1D( (numBlocks-1)*BLOCK_SIZE, BLOCK_SIZE );
+ b3BufferInfoCL bInfo[] = {b3BufferInfoCL(dstNative->getBufferCL()), b3BufferInfoCL(m_workBuffer->getBufferCL())};
+ b3LauncherCL launcher(m_commandQueue, m_propagationKernel, "m_propagationKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setConst(constBuffer);
+ launcher.launch1D((numBlocks - 1) * BLOCK_SIZE, BLOCK_SIZE);
}
-
- if( sum )
+ if (sum)
{
clFinish(m_commandQueue);
- dstNative->copyToHostPointer(sum,1,n-1,true);
+ dstNative->copyToHostPointer(sum, 1, n - 1, true);
}
-
}
-
void b3PrefixScanCL::executeHost(b3AlignedObjectArray<unsigned int>& src, b3AlignedObjectArray<unsigned int>& dst, int n, unsigned int* sum)
{
unsigned int s = 0;
//if( data->m_option == EXCLUSIVE )
{
- for(int i=0; i<n; i++)
+ for (int i = 0; i < n; i++)
{
dst[i] = s;
s += src[i];
@@ -119,8 +113,8 @@ void b3PrefixScanCL::executeHost(b3AlignedObjectArray<unsigned int>& src, b3Alig
}
*/
- if( sum )
+ if (sum)
{
- *sum = dst[n-1];
+ *sum = dst[n - 1];
}
} \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.h b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.h
index a9a2e61b9e..346efa0c73 100644
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.h
+++ b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.h
@@ -13,9 +13,9 @@ class b3PrefixScanCL
BLOCK_SIZE = 128
};
-// Option m_option;
+ // Option m_option;
- cl_command_queue m_commandQueue;
+ cl_command_queue m_commandQueue;
cl_kernel m_localScanKernel;
cl_kernel m_blockSumKernel;
@@ -23,15 +23,13 @@ class b3PrefixScanCL
b3OpenCLArray<unsigned int>* m_workBuffer;
-
- public:
-
- b3PrefixScanCL(cl_context ctx, cl_device_id device, cl_command_queue queue,int size=0);
+public:
+ b3PrefixScanCL(cl_context ctx, cl_device_id device, cl_command_queue queue, int size = 0);
virtual ~b3PrefixScanCL();
void execute(b3OpenCLArray<unsigned int>& src, b3OpenCLArray<unsigned int>& dst, int n, unsigned int* sum = 0);
- void executeHost(b3AlignedObjectArray<unsigned int>& src, b3AlignedObjectArray<unsigned int>& dst, int n, unsigned int* sum=0);
+ void executeHost(b3AlignedObjectArray<unsigned int>& src, b3AlignedObjectArray<unsigned int>& dst, int n, unsigned int* sum = 0);
};
-#endif //B3_PREFIX_SCAN_CL_H
+#endif //B3_PREFIX_SCAN_CL_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanFloat4CL.cpp b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanFloat4CL.cpp
index 80560d793d..1cac97c988 100644
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanFloat4CL.cpp
+++ b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanFloat4CL.cpp
@@ -7,25 +7,24 @@
#include "kernels/PrefixScanKernelsFloat4CL.h"
b3PrefixScanFloat4CL::b3PrefixScanFloat4CL(cl_context ctx, cl_device_id device, cl_command_queue queue, int size)
-:m_commandQueue(queue)
+ : m_commandQueue(queue)
{
const char* scanKernelSource = prefixScanKernelsFloat4CL;
cl_int pErrNum;
- char* additionalMacros=0;
+ char* additionalMacros = 0;
- m_workBuffer = new b3OpenCLArray<b3Vector3>(ctx,queue,size);
- cl_program scanProg = b3OpenCLUtils::compileCLProgramFromString( ctx, device, scanKernelSource, &pErrNum,additionalMacros, B3_PREFIXSCAN_FLOAT4_PROG_PATH);
+ m_workBuffer = new b3OpenCLArray<b3Vector3>(ctx, queue, size);
+ cl_program scanProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, scanKernelSource, &pErrNum, additionalMacros, B3_PREFIXSCAN_FLOAT4_PROG_PATH);
b3Assert(scanProg);
- m_localScanKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, scanKernelSource, "LocalScanKernel", &pErrNum, scanProg,additionalMacros );
- b3Assert(m_localScanKernel );
- m_blockSumKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, scanKernelSource, "TopLevelScanKernel", &pErrNum, scanProg,additionalMacros );
- b3Assert(m_blockSumKernel );
- m_propagationKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, scanKernelSource, "AddOffsetKernel", &pErrNum, scanProg,additionalMacros );
- b3Assert(m_propagationKernel );
+ m_localScanKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, scanKernelSource, "LocalScanKernel", &pErrNum, scanProg, additionalMacros);
+ b3Assert(m_localScanKernel);
+ m_blockSumKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, scanKernelSource, "TopLevelScanKernel", &pErrNum, scanProg, additionalMacros);
+ b3Assert(m_blockSumKernel);
+ m_propagationKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, scanKernelSource, "AddOffsetKernel", &pErrNum, scanProg, additionalMacros);
+ b3Assert(m_propagationKernel);
}
-
b3PrefixScanFloat4CL::~b3PrefixScanFloat4CL()
{
delete m_workBuffer;
@@ -34,20 +33,19 @@ b3PrefixScanFloat4CL::~b3PrefixScanFloat4CL()
clReleaseKernel(m_propagationKernel);
}
-template<class T>
+template <class T>
T b3NextPowerOf2(T n)
{
n -= 1;
- for(int i=0; i<sizeof(T)*8; i++)
- n = n | (n>>i);
- return n+1;
+ for (int i = 0; i < sizeof(T) * 8; i++)
+ n = n | (n >> i);
+ return n + 1;
}
void b3PrefixScanFloat4CL::execute(b3OpenCLArray<b3Vector3>& src, b3OpenCLArray<b3Vector3>& dst, int n, b3Vector3* sum)
{
-
-// b3Assert( data->m_option == EXCLUSIVE );
- const unsigned int numBlocks = (const unsigned int)( (n+BLOCK_SIZE*2-1)/(BLOCK_SIZE*2) );
+ // b3Assert( data->m_option == EXCLUSIVE );
+ const unsigned int numBlocks = (const unsigned int)((n + BLOCK_SIZE * 2 - 1) / (BLOCK_SIZE * 2));
dst.resize(src.size());
m_workBuffer->resize(src.size());
@@ -55,55 +53,51 @@ void b3PrefixScanFloat4CL::execute(b3OpenCLArray<b3Vector3>& src, b3OpenCLArray<
b3Int4 constBuffer;
constBuffer.x = n;
constBuffer.y = numBlocks;
- constBuffer.z = (int)b3NextPowerOf2( numBlocks );
+ constBuffer.z = (int)b3NextPowerOf2(numBlocks);
b3OpenCLArray<b3Vector3>* srcNative = &src;
b3OpenCLArray<b3Vector3>* dstNative = &dst;
-
+
{
- b3BufferInfoCL bInfo[] = { b3BufferInfoCL( dstNative->getBufferCL() ), b3BufferInfoCL( srcNative->getBufferCL() ), b3BufferInfoCL( m_workBuffer->getBufferCL() ) };
+ b3BufferInfoCL bInfo[] = {b3BufferInfoCL(dstNative->getBufferCL()), b3BufferInfoCL(srcNative->getBufferCL()), b3BufferInfoCL(m_workBuffer->getBufferCL())};
- b3LauncherCL launcher( m_commandQueue, m_localScanKernel ,"m_localScanKernel");
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst( constBuffer );
- launcher.launch1D( numBlocks*BLOCK_SIZE, BLOCK_SIZE );
+ b3LauncherCL launcher(m_commandQueue, m_localScanKernel, "m_localScanKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setConst(constBuffer);
+ launcher.launch1D(numBlocks * BLOCK_SIZE, BLOCK_SIZE);
}
{
- b3BufferInfoCL bInfo[] = { b3BufferInfoCL( m_workBuffer->getBufferCL() ) };
+ b3BufferInfoCL bInfo[] = {b3BufferInfoCL(m_workBuffer->getBufferCL())};
- b3LauncherCL launcher( m_commandQueue, m_blockSumKernel ,"m_blockSumKernel");
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst( constBuffer );
- launcher.launch1D( BLOCK_SIZE, BLOCK_SIZE );
+ b3LauncherCL launcher(m_commandQueue, m_blockSumKernel, "m_blockSumKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setConst(constBuffer);
+ launcher.launch1D(BLOCK_SIZE, BLOCK_SIZE);
}
-
- if( numBlocks > 1 )
+ if (numBlocks > 1)
{
- b3BufferInfoCL bInfo[] = { b3BufferInfoCL( dstNative->getBufferCL() ), b3BufferInfoCL( m_workBuffer->getBufferCL() ) };
- b3LauncherCL launcher( m_commandQueue, m_propagationKernel ,"m_propagationKernel");
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst( constBuffer );
- launcher.launch1D( (numBlocks-1)*BLOCK_SIZE, BLOCK_SIZE );
+ b3BufferInfoCL bInfo[] = {b3BufferInfoCL(dstNative->getBufferCL()), b3BufferInfoCL(m_workBuffer->getBufferCL())};
+ b3LauncherCL launcher(m_commandQueue, m_propagationKernel, "m_propagationKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setConst(constBuffer);
+ launcher.launch1D((numBlocks - 1) * BLOCK_SIZE, BLOCK_SIZE);
}
-
- if( sum )
+ if (sum)
{
clFinish(m_commandQueue);
- dstNative->copyToHostPointer(sum,1,n-1,true);
+ dstNative->copyToHostPointer(sum, 1, n - 1, true);
}
-
}
-
void b3PrefixScanFloat4CL::executeHost(b3AlignedObjectArray<b3Vector3>& src, b3AlignedObjectArray<b3Vector3>& dst, int n, b3Vector3* sum)
{
- b3Vector3 s=b3MakeVector3(0,0,0);
+ b3Vector3 s = b3MakeVector3(0, 0, 0);
//if( data->m_option == EXCLUSIVE )
{
- for(int i=0; i<n; i++)
+ for (int i = 0; i < n; i++)
{
dst[i] = s;
s += src[i];
@@ -119,8 +113,8 @@ void b3PrefixScanFloat4CL::executeHost(b3AlignedObjectArray<b3Vector3>& src, b3A
}
*/
- if( sum )
+ if (sum)
{
- *sum = dst[n-1];
+ *sum = dst[n - 1];
}
} \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanFloat4CL.h b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanFloat4CL.h
index 2c8003c1bb..122b0bfd68 100644
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanFloat4CL.h
+++ b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanFloat4CL.h
@@ -14,9 +14,9 @@ class b3PrefixScanFloat4CL
BLOCK_SIZE = 128
};
-// Option m_option;
+ // Option m_option;
- cl_command_queue m_commandQueue;
+ cl_command_queue m_commandQueue;
cl_kernel m_localScanKernel;
cl_kernel m_blockSumKernel;
@@ -24,10 +24,8 @@ class b3PrefixScanFloat4CL
b3OpenCLArray<b3Vector3>* m_workBuffer;
-
- public:
-
- b3PrefixScanFloat4CL(cl_context ctx, cl_device_id device, cl_command_queue queue,int size=0);
+public:
+ b3PrefixScanFloat4CL(cl_context ctx, cl_device_id device, cl_command_queue queue, int size = 0);
virtual ~b3PrefixScanFloat4CL();
@@ -35,4 +33,4 @@ class b3PrefixScanFloat4CL
void executeHost(b3AlignedObjectArray<b3Vector3>& src, b3AlignedObjectArray<b3Vector3>& dst, int n, b3Vector3* sum);
};
-#endif //B3_PREFIX_SCAN_CL_H
+#endif //B3_PREFIX_SCAN_CL_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.cpp b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.cpp
index f11ae4bcdb..e86af6583f 100644
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.cpp
+++ b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.cpp
@@ -10,21 +10,20 @@
#include "kernels/RadixSort32KernelsCL.h"
b3RadixSort32CL::b3RadixSort32CL(cl_context ctx, cl_device_id device, cl_command_queue queue, int initialCapacity)
-:m_commandQueue(queue)
+ : m_commandQueue(queue)
{
b3OpenCLDeviceInfo info;
- b3OpenCLUtils::getDeviceInfo(device,&info);
- m_deviceCPU = (info.m_deviceType & CL_DEVICE_TYPE_CPU)!=0;
+ b3OpenCLUtils::getDeviceInfo(device, &info);
+ m_deviceCPU = (info.m_deviceType & CL_DEVICE_TYPE_CPU) != 0;
- m_workBuffer1 = new b3OpenCLArray<unsigned int>(ctx,queue);
- m_workBuffer2 = new b3OpenCLArray<unsigned int>(ctx,queue);
- m_workBuffer3 = new b3OpenCLArray<b3SortData>(ctx,queue);
- m_workBuffer3a = new b3OpenCLArray<unsigned int>(ctx,queue);
- m_workBuffer4 = new b3OpenCLArray<b3SortData>(ctx,queue);
- m_workBuffer4a = new b3OpenCLArray<unsigned int>(ctx,queue);
+ m_workBuffer1 = new b3OpenCLArray<unsigned int>(ctx, queue);
+ m_workBuffer2 = new b3OpenCLArray<unsigned int>(ctx, queue);
+ m_workBuffer3 = new b3OpenCLArray<b3SortData>(ctx, queue);
+ m_workBuffer3a = new b3OpenCLArray<unsigned int>(ctx, queue);
+ m_workBuffer4 = new b3OpenCLArray<b3SortData>(ctx, queue);
+ m_workBuffer4a = new b3OpenCLArray<unsigned int>(ctx, queue);
-
- if (initialCapacity>0)
+ if (initialCapacity > 0)
{
m_workBuffer1->resize(initialCapacity);
m_workBuffer3->resize(initialCapacity);
@@ -33,45 +32,40 @@ b3RadixSort32CL::b3RadixSort32CL(cl_context ctx, cl_device_id device, cl_command
m_workBuffer4a->resize(initialCapacity);
}
- m_scan = new b3PrefixScanCL(ctx,device,queue);
- m_fill = new b3FillCL(ctx,device,queue);
-
+ m_scan = new b3PrefixScanCL(ctx, device, queue);
+ m_fill = new b3FillCL(ctx, device, queue);
+
const char* additionalMacros = "";
cl_int pErrNum;
const char* kernelSource = radixSort32KernelsCL;
-
- cl_program sortProg = b3OpenCLUtils::compileCLProgramFromString( ctx, device, kernelSource, &pErrNum,additionalMacros, RADIXSORT32_PATH);
- b3Assert(sortProg);
- m_streamCountSortDataKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, kernelSource, "StreamCountSortDataKernel", &pErrNum, sortProg,additionalMacros );
- b3Assert(m_streamCountSortDataKernel );
+ cl_program sortProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, kernelSource, &pErrNum, additionalMacros, RADIXSORT32_PATH);
+ b3Assert(sortProg);
+ m_streamCountSortDataKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "StreamCountSortDataKernel", &pErrNum, sortProg, additionalMacros);
+ b3Assert(m_streamCountSortDataKernel);
-
- m_streamCountKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, kernelSource, "StreamCountKernel", &pErrNum, sortProg,additionalMacros );
+ m_streamCountKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "StreamCountKernel", &pErrNum, sortProg, additionalMacros);
b3Assert(m_streamCountKernel);
-
-
if (m_deviceCPU)
{
-
- m_sortAndScatterSortDataKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, kernelSource, "SortAndScatterSortDataKernelSerial", &pErrNum, sortProg,additionalMacros );
+ m_sortAndScatterSortDataKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "SortAndScatterSortDataKernelSerial", &pErrNum, sortProg, additionalMacros);
b3Assert(m_sortAndScatterSortDataKernel);
- m_sortAndScatterKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, kernelSource, "SortAndScatterKernelSerial", &pErrNum, sortProg,additionalMacros );
+ m_sortAndScatterKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "SortAndScatterKernelSerial", &pErrNum, sortProg, additionalMacros);
b3Assert(m_sortAndScatterKernel);
- } else
+ }
+ else
{
- m_sortAndScatterSortDataKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, kernelSource, "SortAndScatterSortDataKernel", &pErrNum, sortProg,additionalMacros );
+ m_sortAndScatterSortDataKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "SortAndScatterSortDataKernel", &pErrNum, sortProg, additionalMacros);
b3Assert(m_sortAndScatterSortDataKernel);
- m_sortAndScatterKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, kernelSource, "SortAndScatterKernel", &pErrNum, sortProg,additionalMacros );
+ m_sortAndScatterKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "SortAndScatterKernel", &pErrNum, sortProg, additionalMacros);
b3Assert(m_sortAndScatterKernel);
}
-
- m_prefixScanKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, kernelSource, "PrefixScanKernel", &pErrNum, sortProg,additionalMacros );
+
+ m_prefixScanKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "PrefixScanKernel", &pErrNum, sortProg, additionalMacros);
b3Assert(m_prefixScanKernel);
-
}
b3RadixSort32CL::~b3RadixSort32CL()
@@ -96,8 +90,7 @@ void b3RadixSort32CL::executeHost(b3AlignedObjectArray<b3SortData>& inout, int s
{
int n = inout.size();
const int BITS_PER_PASS = 8;
- const int NUM_TABLES = (1<<BITS_PER_PASS);
-
+ const int NUM_TABLES = (1 << BITS_PER_PASS);
int tables[NUM_TABLES];
int counter[NUM_TABLES];
@@ -107,34 +100,33 @@ void b3RadixSort32CL::executeHost(b3AlignedObjectArray<b3SortData>& inout, int s
workbuffer.resize(inout.size());
b3SortData* dst = &workbuffer[0];
- int count=0;
- for(int startBit=0; startBit<sortBits; startBit+=BITS_PER_PASS)
+ int count = 0;
+ for (int startBit = 0; startBit < sortBits; startBit += BITS_PER_PASS)
{
- for(int i=0; i<NUM_TABLES; i++)
+ for (int i = 0; i < NUM_TABLES; i++)
{
tables[i] = 0;
}
- for(int i=0; i<n; i++)
+ for (int i = 0; i < n; i++)
{
- int tableIdx = (src[i].m_key >> startBit) & (NUM_TABLES-1);
+ int tableIdx = (src[i].m_key >> startBit) & (NUM_TABLES - 1);
tables[tableIdx]++;
}
//#define TEST
#ifdef TEST
- printf("histogram size=%d\n",NUM_TABLES);
- for (int i=0;i<NUM_TABLES;i++)
+ printf("histogram size=%d\n", NUM_TABLES);
+ for (int i = 0; i < NUM_TABLES; i++)
{
- if (tables[i]!=0)
+ if (tables[i] != 0)
{
- printf("tables[%d]=%d]\n",i,tables[i]);
+ printf("tables[%d]=%d]\n", i, tables[i]);
}
-
}
-#endif //TEST
- // prefix scan
+#endif //TEST \
+ // prefix scan
int sum = 0;
- for(int i=0; i<NUM_TABLES; i++)
+ for (int i = 0; i < NUM_TABLES; i++)
{
int iData = tables[i];
tables[i] = sum;
@@ -143,71 +135,65 @@ void b3RadixSort32CL::executeHost(b3AlignedObjectArray<b3SortData>& inout, int s
}
// distribute
- for(int i=0; i<n; i++)
+ for (int i = 0; i < n; i++)
{
- int tableIdx = (src[i].m_key >> startBit) & (NUM_TABLES-1);
-
+ int tableIdx = (src[i].m_key >> startBit) & (NUM_TABLES - 1);
+
dst[tables[tableIdx] + counter[tableIdx]] = src[i];
- counter[tableIdx] ++;
+ counter[tableIdx]++;
}
- b3Swap( src, dst );
+ b3Swap(src, dst);
count++;
}
- if (count&1)
+ if (count & 1)
{
- b3Assert(0);//need to copy
-
+ b3Assert(0); //need to copy
}
}
void b3RadixSort32CL::executeHost(b3OpenCLArray<b3SortData>& keyValuesInOut, int sortBits /* = 32 */)
{
-
b3AlignedObjectArray<b3SortData> inout;
keyValuesInOut.copyToHost(inout);
- executeHost(inout,sortBits);
+ executeHost(inout, sortBits);
keyValuesInOut.copyFromHost(inout);
}
-void b3RadixSort32CL::execute(b3OpenCLArray<unsigned int>& keysIn, b3OpenCLArray<unsigned int>& keysOut, b3OpenCLArray<unsigned int>& valuesIn,
- b3OpenCLArray<unsigned int>& valuesOut, int n, int sortBits)
+void b3RadixSort32CL::execute(b3OpenCLArray<unsigned int>& keysIn, b3OpenCLArray<unsigned int>& keysOut, b3OpenCLArray<unsigned int>& valuesIn,
+ b3OpenCLArray<unsigned int>& valuesOut, int n, int sortBits)
{
-
}
//#define DEBUG_RADIXSORT
//#define DEBUG_RADIXSORT2
-
void b3RadixSort32CL::execute(b3OpenCLArray<b3SortData>& keyValuesInOut, int sortBits /* = 32 */)
{
-
int originalSize = keyValuesInOut.size();
int workingSize = originalSize;
-
-
+
int dataAlignment = DATA_ALIGNMENT;
#ifdef DEBUG_RADIXSORT2
- b3AlignedObjectArray<b3SortData> test2;
- keyValuesInOut.copyToHost(test2);
- printf("numElem = %d\n",test2.size());
- for (int i=0;i<test2.size();i++)
- {
- printf("test2[%d].m_key=%d\n",i,test2[i].m_key);
- printf("test2[%d].m_value=%d\n",i,test2[i].m_value);
- }
-#endif //DEBUG_RADIXSORT2
-
+ b3AlignedObjectArray<b3SortData> test2;
+ keyValuesInOut.copyToHost(test2);
+ printf("numElem = %d\n", test2.size());
+ for (int i = 0; i < test2.size(); i++)
+ {
+ printf("test2[%d].m_key=%d\n", i, test2[i].m_key);
+ printf("test2[%d].m_value=%d\n", i, test2[i].m_value);
+ }
+#endif //DEBUG_RADIXSORT2
+
b3OpenCLArray<b3SortData>* src = 0;
- if (workingSize%dataAlignment)
+ if (workingSize % dataAlignment)
{
- workingSize += dataAlignment-(workingSize%dataAlignment);
+ workingSize += dataAlignment - (workingSize % dataAlignment);
m_workBuffer4->copyFromOpenCLArray(keyValuesInOut);
m_workBuffer4->resize(workingSize);
b3SortData fillValue;
@@ -216,327 +202,301 @@ void b3RadixSort32CL::execute(b3OpenCLArray<b3SortData>& keyValuesInOut, int sor
#define USE_BTFILL
#ifdef USE_BTFILL
- m_fill->execute((b3OpenCLArray<b3Int2>&)*m_workBuffer4,(b3Int2&)fillValue,workingSize-originalSize,originalSize);
+ m_fill->execute((b3OpenCLArray<b3Int2>&)*m_workBuffer4, (b3Int2&)fillValue, workingSize - originalSize, originalSize);
#else
//fill the remaining bits (very slow way, todo: fill on GPU/OpenCL side)
-
- for (int i=originalSize; i<workingSize;i++)
+
+ for (int i = originalSize; i < workingSize; i++)
{
- m_workBuffer4->copyFromHostPointer(&fillValue,1,i);
+ m_workBuffer4->copyFromHostPointer(&fillValue, 1, i);
}
-#endif//USE_BTFILL
+#endif //USE_BTFILL
src = m_workBuffer4;
- } else
+ }
+ else
{
src = &keyValuesInOut;
m_workBuffer4->resize(0);
}
-
- b3Assert( workingSize%DATA_ALIGNMENT == 0 );
- int minCap = NUM_BUCKET*NUM_WGS;
+ b3Assert(workingSize % DATA_ALIGNMENT == 0);
+ int minCap = NUM_BUCKET * NUM_WGS;
int n = workingSize;
m_workBuffer1->resize(minCap);
m_workBuffer3->resize(workingSize);
-
-// ADLASSERT( ELEMENTS_PER_WORK_ITEM == 4 );
- b3Assert( BITS_PER_PASS == 4 );
- b3Assert( WG_SIZE == 64 );
- b3Assert( (sortBits&0x3) == 0 );
+ // ADLASSERT( ELEMENTS_PER_WORK_ITEM == 4 );
+ b3Assert(BITS_PER_PASS == 4);
+ b3Assert(WG_SIZE == 64);
+ b3Assert((sortBits & 0x3) == 0);
-
-
b3OpenCLArray<b3SortData>* dst = m_workBuffer3;
b3OpenCLArray<unsigned int>* srcHisto = m_workBuffer1;
b3OpenCLArray<unsigned int>* destHisto = m_workBuffer2;
-
int nWGs = NUM_WGS;
b3ConstData cdata;
{
- int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;//set at 256
- int nBlocks = (n+blockSize-1)/(blockSize);
+ int blockSize = ELEMENTS_PER_WORK_ITEM * WG_SIZE; //set at 256
+ int nBlocks = (n + blockSize - 1) / (blockSize);
cdata.m_n = n;
cdata.m_nWGs = NUM_WGS;
cdata.m_startBit = 0;
- cdata.m_nBlocksPerWG = (nBlocks + cdata.m_nWGs - 1)/cdata.m_nWGs;
- if( nBlocks < NUM_WGS )
+ cdata.m_nBlocksPerWG = (nBlocks + cdata.m_nWGs - 1) / cdata.m_nWGs;
+ if (nBlocks < NUM_WGS)
{
cdata.m_nBlocksPerWG = 1;
nWGs = nBlocks;
}
}
- int count=0;
- for(int ib=0; ib<sortBits; ib+=4)
+ int count = 0;
+ for (int ib = 0; ib < sortBits; ib += 4)
{
#ifdef DEBUG_RADIXSORT2
- keyValuesInOut.copyToHost(test2);
- printf("numElem = %d\n",test2.size());
- for (int i=0;i<test2.size();i++)
- {
- if (test2[i].m_key != test2[i].m_value)
- {
- printf("test2[%d].m_key=%d\n",i,test2[i].m_key);
- printf("test2[%d].m_value=%d\n",i,test2[i].m_value);
- }
- }
-#endif //DEBUG_RADIXSORT2
-
+ keyValuesInOut.copyToHost(test2);
+ printf("numElem = %d\n", test2.size());
+ for (int i = 0; i < test2.size(); i++)
+ {
+ if (test2[i].m_key != test2[i].m_value)
+ {
+ printf("test2[%d].m_key=%d\n", i, test2[i].m_key);
+ printf("test2[%d].m_value=%d\n", i, test2[i].m_value);
+ }
+ }
+#endif //DEBUG_RADIXSORT2
+
cdata.m_startBit = ib;
-
+
if (src->size())
{
- b3BufferInfoCL bInfo[] = { b3BufferInfoCL( src->getBufferCL(), true ), b3BufferInfoCL( srcHisto->getBufferCL() ) };
- b3LauncherCL launcher(m_commandQueue, m_streamCountSortDataKernel,"m_streamCountSortDataKernel");
-
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst( cdata );
-
- int num = NUM_WGS*WG_SIZE;
- launcher.launch1D( num, WG_SIZE );
+ b3BufferInfoCL bInfo[] = {b3BufferInfoCL(src->getBufferCL(), true), b3BufferInfoCL(srcHisto->getBufferCL())};
+ b3LauncherCL launcher(m_commandQueue, m_streamCountSortDataKernel, "m_streamCountSortDataKernel");
+
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setConst(cdata);
+
+ int num = NUM_WGS * WG_SIZE;
+ launcher.launch1D(num, WG_SIZE);
}
-
-
#ifdef DEBUG_RADIXSORT
b3AlignedObjectArray<unsigned int> testHist;
srcHisto->copyToHost(testHist);
- printf("ib = %d, testHist size = %d, non zero elements:\n",ib, testHist.size());
- for (int i=0;i<testHist.size();i++)
+ printf("ib = %d, testHist size = %d, non zero elements:\n", ib, testHist.size());
+ for (int i = 0; i < testHist.size(); i++)
{
- if (testHist[i]!=0)
- printf("testHist[%d]=%d\n",i,testHist[i]);
+ if (testHist[i] != 0)
+ printf("testHist[%d]=%d\n", i, testHist[i]);
}
-#endif //DEBUG_RADIXSORT
-
-
+#endif //DEBUG_RADIXSORT
//fast prefix scan is not working properly on Mac OSX yet
#ifdef __APPLE__
- bool fastScan=false;
+ bool fastScan = false;
#else
- bool fastScan=!m_deviceCPU;//only use fast scan on GPU
+ bool fastScan = !m_deviceCPU; //only use fast scan on GPU
#endif
if (fastScan)
- {// prefix scan group histogram
- b3BufferInfoCL bInfo[] = { b3BufferInfoCL( srcHisto->getBufferCL() ) };
- b3LauncherCL launcher( m_commandQueue, m_prefixScanKernel,"m_prefixScanKernel" );
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst( cdata );
- launcher.launch1D( 128, 128 );
+ { // prefix scan group histogram
+ b3BufferInfoCL bInfo[] = {b3BufferInfoCL(srcHisto->getBufferCL())};
+ b3LauncherCL launcher(m_commandQueue, m_prefixScanKernel, "m_prefixScanKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setConst(cdata);
+ launcher.launch1D(128, 128);
destHisto = srcHisto;
- }else
+ }
+ else
{
//unsigned int sum; //for debugging
- m_scan->execute(*srcHisto,*destHisto,1920,0);//,&sum);
+ m_scan->execute(*srcHisto, *destHisto, 1920, 0); //,&sum);
}
-
#ifdef DEBUG_RADIXSORT
destHisto->copyToHost(testHist);
- printf("ib = %d, testHist size = %d, non zero elements:\n",ib, testHist.size());
- for (int i=0;i<testHist.size();i++)
+ printf("ib = %d, testHist size = %d, non zero elements:\n", ib, testHist.size());
+ for (int i = 0; i < testHist.size(); i++)
{
- if (testHist[i]!=0)
- printf("testHist[%d]=%d\n",i,testHist[i]);
+ if (testHist[i] != 0)
+ printf("testHist[%d]=%d\n", i, testHist[i]);
}
-
- for (int i=0;i<testHist.size();i+=NUM_WGS)
+
+ for (int i = 0; i < testHist.size(); i += NUM_WGS)
{
- printf("testHist[%d]=%d\n",i/NUM_WGS,testHist[i]);
+ printf("testHist[%d]=%d\n", i / NUM_WGS, testHist[i]);
}
-#endif //DEBUG_RADIXSORT
+#endif //DEBUG_RADIXSORT
#define USE_GPU
#ifdef USE_GPU
-
+
if (src->size())
- {// local sort and distribute
- b3BufferInfoCL bInfo[] = { b3BufferInfoCL( src->getBufferCL(), true ), b3BufferInfoCL( destHisto->getBufferCL(), true ), b3BufferInfoCL( dst->getBufferCL() )};
- b3LauncherCL launcher( m_commandQueue, m_sortAndScatterSortDataKernel,"m_sortAndScatterSortDataKernel" );
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst( cdata );
- launcher.launch1D( nWGs*WG_SIZE, WG_SIZE );
-
+ { // local sort and distribute
+ b3BufferInfoCL bInfo[] = {b3BufferInfoCL(src->getBufferCL(), true), b3BufferInfoCL(destHisto->getBufferCL(), true), b3BufferInfoCL(dst->getBufferCL())};
+ b3LauncherCL launcher(m_commandQueue, m_sortAndScatterSortDataKernel, "m_sortAndScatterSortDataKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setConst(cdata);
+ launcher.launch1D(nWGs * WG_SIZE, WG_SIZE);
}
#else
- {
+ {
#define NUM_TABLES 16
//#define SEQUENTIAL
#ifdef SEQUENTIAL
- int counter2[NUM_TABLES]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
- int tables[NUM_TABLES];
- int startBit = ib;
-
- destHisto->copyToHost(testHist);
- b3AlignedObjectArray<b3SortData> srcHost;
- b3AlignedObjectArray<b3SortData> dstHost;
- dstHost.resize(src->size());
-
- src->copyToHost(srcHost);
-
- for (int i=0;i<NUM_TABLES;i++)
- {
- tables[i] = testHist[i*NUM_WGS];
- }
-
- // distribute
- for(int i=0; i<n; i++)
- {
- int tableIdx = (srcHost[i].m_key >> startBit) & (NUM_TABLES-1);
-
- dstHost[tables[tableIdx] + counter2[tableIdx]] = srcHost[i];
- counter2[tableIdx] ++;
- }
-
-
+ int counter2[NUM_TABLES] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ int tables[NUM_TABLES];
+ int startBit = ib;
+
+ destHisto->copyToHost(testHist);
+ b3AlignedObjectArray<b3SortData> srcHost;
+ b3AlignedObjectArray<b3SortData> dstHost;
+ dstHost.resize(src->size());
+
+ src->copyToHost(srcHost);
+
+ for (int i = 0; i < NUM_TABLES; i++)
+ {
+ tables[i] = testHist[i * NUM_WGS];
+ }
+
+ // distribute
+ for (int i = 0; i < n; i++)
+ {
+ int tableIdx = (srcHost[i].m_key >> startBit) & (NUM_TABLES - 1);
+
+ dstHost[tables[tableIdx] + counter2[tableIdx]] = srcHost[i];
+ counter2[tableIdx]++;
+ }
+
#else
-
- int counter2[NUM_TABLES]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-
- int tables[NUM_TABLES];
- b3AlignedObjectArray<b3SortData> dstHostOK;
- dstHostOK.resize(src->size());
-
- destHisto->copyToHost(testHist);
- b3AlignedObjectArray<b3SortData> srcHost;
- src->copyToHost(srcHost);
-
- int blockSize = 256;
- int nBlocksPerWG = cdata.m_nBlocksPerWG;
- int startBit = ib;
-
- {
- for (int i=0;i<NUM_TABLES;i++)
- {
- tables[i] = testHist[i*NUM_WGS];
- }
-
- // distribute
- for(int i=0; i<n; i++)
- {
- int tableIdx = (srcHost[i].m_key >> startBit) & (NUM_TABLES-1);
-
- dstHostOK[tables[tableIdx] + counter2[tableIdx]] = srcHost[i];
- counter2[tableIdx] ++;
- }
-
-
- }
-
-
- b3AlignedObjectArray<b3SortData> dstHost;
- dstHost.resize(src->size());
-
-
- int counter[NUM_TABLES]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-
-
-
- for (int wgIdx=0;wgIdx<NUM_WGS;wgIdx++)
- {
- int counter[NUM_TABLES]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-
- int nBlocks = (n)/blockSize - nBlocksPerWG*wgIdx;
-
- for(int iblock=0; iblock<b3Min(cdata.m_nBlocksPerWG, nBlocks); iblock++)
- {
- for (int lIdx = 0;lIdx < 64;lIdx++)
- {
- int addr = iblock*blockSize + blockSize*cdata.m_nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;
-
- // MY_HISTOGRAM( localKeys.x ) ++ is much expensive than atomic add as it requires read and write while atomics can just add on AMD
- // Using registers didn't perform well. It seems like use localKeys to address requires a lot of alu ops
- // AMD: AtomInc performs better while NV prefers ++
- for(int j=0; j<ELEMENTS_PER_WORK_ITEM; j++)
- {
- if( addr+j < n )
- {
- // printf ("addr+j=%d\n", addr+j);
-
- int i = addr+j;
-
- int tableIdx = (srcHost[i].m_key >> startBit) & (NUM_TABLES-1);
-
- int destIndex = testHist[tableIdx*NUM_WGS+wgIdx] + counter[tableIdx];
-
- b3SortData ok = dstHostOK[destIndex];
-
- if (ok.m_key != srcHost[i].m_key)
- {
- printf("ok.m_key = %d, srcHost[i].m_key = %d\n", ok.m_key,srcHost[i].m_key );
- printf("(ok.m_value = %d, srcHost[i].m_value = %d)\n", ok.m_value,srcHost[i].m_value );
- }
- if (ok.m_value != srcHost[i].m_value)
- {
-
- printf("ok.m_value = %d, srcHost[i].m_value = %d\n", ok.m_value,srcHost[i].m_value );
- printf("(ok.m_key = %d, srcHost[i].m_key = %d)\n", ok.m_key,srcHost[i].m_key );
-
- }
-
- dstHost[destIndex] = srcHost[i];
- counter[tableIdx] ++;
-
- }
- }
- }
- }
- }
-
-
-#endif //SEQUENTIAL
-
- dst->copyFromHost(dstHost);
- }
-#endif//USE_GPU
-
-
-
+
+ int counter2[NUM_TABLES] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+ int tables[NUM_TABLES];
+ b3AlignedObjectArray<b3SortData> dstHostOK;
+ dstHostOK.resize(src->size());
+
+ destHisto->copyToHost(testHist);
+ b3AlignedObjectArray<b3SortData> srcHost;
+ src->copyToHost(srcHost);
+
+ int blockSize = 256;
+ int nBlocksPerWG = cdata.m_nBlocksPerWG;
+ int startBit = ib;
+
+ {
+ for (int i = 0; i < NUM_TABLES; i++)
+ {
+ tables[i] = testHist[i * NUM_WGS];
+ }
+
+ // distribute
+ for (int i = 0; i < n; i++)
+ {
+ int tableIdx = (srcHost[i].m_key >> startBit) & (NUM_TABLES - 1);
+
+ dstHostOK[tables[tableIdx] + counter2[tableIdx]] = srcHost[i];
+ counter2[tableIdx]++;
+ }
+ }
+
+ b3AlignedObjectArray<b3SortData> dstHost;
+ dstHost.resize(src->size());
+
+ int counter[NUM_TABLES] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+ for (int wgIdx = 0; wgIdx < NUM_WGS; wgIdx++)
+ {
+ int counter[NUM_TABLES] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+ int nBlocks = (n) / blockSize - nBlocksPerWG * wgIdx;
+
+ for (int iblock = 0; iblock < b3Min(cdata.m_nBlocksPerWG, nBlocks); iblock++)
+ {
+ for (int lIdx = 0; lIdx < 64; lIdx++)
+ {
+ int addr = iblock * blockSize + blockSize * cdata.m_nBlocksPerWG * wgIdx + ELEMENTS_PER_WORK_ITEM * lIdx;
+
+ // MY_HISTOGRAM( localKeys.x ) ++ is much expensive than atomic add as it requires read and write while atomics can just add on AMD
+ // Using registers didn't perform well. It seems like use localKeys to address requires a lot of alu ops
+ // AMD: AtomInc performs better while NV prefers ++
+ for (int j = 0; j < ELEMENTS_PER_WORK_ITEM; j++)
+ {
+ if (addr + j < n)
+ {
+ // printf ("addr+j=%d\n", addr+j);
+
+ int i = addr + j;
+
+ int tableIdx = (srcHost[i].m_key >> startBit) & (NUM_TABLES - 1);
+
+ int destIndex = testHist[tableIdx * NUM_WGS + wgIdx] + counter[tableIdx];
+
+ b3SortData ok = dstHostOK[destIndex];
+
+ if (ok.m_key != srcHost[i].m_key)
+ {
+ printf("ok.m_key = %d, srcHost[i].m_key = %d\n", ok.m_key, srcHost[i].m_key);
+ printf("(ok.m_value = %d, srcHost[i].m_value = %d)\n", ok.m_value, srcHost[i].m_value);
+ }
+ if (ok.m_value != srcHost[i].m_value)
+ {
+ printf("ok.m_value = %d, srcHost[i].m_value = %d\n", ok.m_value, srcHost[i].m_value);
+ printf("(ok.m_key = %d, srcHost[i].m_key = %d)\n", ok.m_key, srcHost[i].m_key);
+ }
+
+ dstHost[destIndex] = srcHost[i];
+ counter[tableIdx]++;
+ }
+ }
+ }
+ }
+ }
+
+#endif //SEQUENTIAL
+
+ dst->copyFromHost(dstHost);
+ }
+#endif //USE_GPU
+
#ifdef DEBUG_RADIXSORT
destHisto->copyToHost(testHist);
- printf("ib = %d, testHist size = %d, non zero elements:\n",ib, testHist.size());
- for (int i=0;i<testHist.size();i++)
+ printf("ib = %d, testHist size = %d, non zero elements:\n", ib, testHist.size());
+ for (int i = 0; i < testHist.size(); i++)
{
- if (testHist[i]!=0)
- printf("testHist[%d]=%d\n",i,testHist[i]);
+ if (testHist[i] != 0)
+ printf("testHist[%d]=%d\n", i, testHist[i]);
}
-#endif //DEBUG_RADIXSORT
- b3Swap(src, dst );
- b3Swap(srcHisto,destHisto);
+#endif //DEBUG_RADIXSORT
+ b3Swap(src, dst);
+ b3Swap(srcHisto, destHisto);
#ifdef DEBUG_RADIXSORT2
- keyValuesInOut.copyToHost(test2);
- printf("numElem = %d\n",test2.size());
- for (int i=0;i<test2.size();i++)
- {
- if (test2[i].m_key != test2[i].m_value)
- {
- printf("test2[%d].m_key=%d\n",i,test2[i].m_key);
- printf("test2[%d].m_value=%d\n",i,test2[i].m_value);
- }
- }
-#endif //DEBUG_RADIXSORT2
-
- count++;
-
-
+ keyValuesInOut.copyToHost(test2);
+ printf("numElem = %d\n", test2.size());
+ for (int i = 0; i < test2.size(); i++)
+ {
+ if (test2[i].m_key != test2[i].m_value)
+ {
+ printf("test2[%d].m_key=%d\n", i, test2[i].m_key);
+ printf("test2[%d].m_value=%d\n", i, test2[i].m_value);
+ }
+ }
+#endif //DEBUG_RADIXSORT2
+
+ count++;
}
-
-
-
- if (count&1)
+
+ if (count & 1)
{
- b3Assert(0);//need to copy from workbuffer to keyValuesInOut
+ b3Assert(0); //need to copy from workbuffer to keyValuesInOut
}
if (m_workBuffer4->size())
@@ -545,153 +505,137 @@ void b3RadixSort32CL::execute(b3OpenCLArray<b3SortData>& keyValuesInOut, int sor
keyValuesInOut.copyFromOpenCLArray(*m_workBuffer4);
}
-
#ifdef DEBUG_RADIXSORT
- keyValuesInOut.copyToHost(test2);
-
- printf("numElem = %d\n",test2.size());
- for (int i=0;i<test2.size();i++)
- {
- printf("test2[%d].m_key=%d\n",i,test2[i].m_key);
- printf("test2[%d].m_value=%d\n",i,test2[i].m_value);
- }
-#endif
-
-}
-
-
-
-
+ keyValuesInOut.copyToHost(test2);
+ printf("numElem = %d\n", test2.size());
+ for (int i = 0; i < test2.size(); i++)
+ {
+ printf("test2[%d].m_key=%d\n", i, test2[i].m_key);
+ printf("test2[%d].m_value=%d\n", i, test2[i].m_value);
+ }
+#endif
+}
void b3RadixSort32CL::execute(b3OpenCLArray<unsigned int>& keysInOut, int sortBits /* = 32 */)
{
int originalSize = keysInOut.size();
int workingSize = originalSize;
-
-
+
int dataAlignment = DATA_ALIGNMENT;
b3OpenCLArray<unsigned int>* src = 0;
- if (workingSize%dataAlignment)
+ if (workingSize % dataAlignment)
{
- workingSize += dataAlignment-(workingSize%dataAlignment);
+ workingSize += dataAlignment - (workingSize % dataAlignment);
m_workBuffer4a->copyFromOpenCLArray(keysInOut);
m_workBuffer4a->resize(workingSize);
unsigned int fillValue = 0xffffffff;
-
- m_fill->execute(*m_workBuffer4a,fillValue,workingSize-originalSize,originalSize);
+
+ m_fill->execute(*m_workBuffer4a, fillValue, workingSize - originalSize, originalSize);
src = m_workBuffer4a;
- } else
+ }
+ else
{
src = &keysInOut;
m_workBuffer4a->resize(0);
}
-
-
-
- b3Assert( workingSize%DATA_ALIGNMENT == 0 );
- int minCap = NUM_BUCKET*NUM_WGS;
+ b3Assert(workingSize % DATA_ALIGNMENT == 0);
+ int minCap = NUM_BUCKET * NUM_WGS;
int n = workingSize;
-
m_workBuffer1->resize(minCap);
m_workBuffer3->resize(workingSize);
m_workBuffer3a->resize(workingSize);
-// ADLASSERT( ELEMENTS_PER_WORK_ITEM == 4 );
- b3Assert( BITS_PER_PASS == 4 );
- b3Assert( WG_SIZE == 64 );
- b3Assert( (sortBits&0x3) == 0 );
+ // ADLASSERT( ELEMENTS_PER_WORK_ITEM == 4 );
+ b3Assert(BITS_PER_PASS == 4);
+ b3Assert(WG_SIZE == 64);
+ b3Assert((sortBits & 0x3) == 0);
-
-
b3OpenCLArray<unsigned int>* dst = m_workBuffer3a;
b3OpenCLArray<unsigned int>* srcHisto = m_workBuffer1;
b3OpenCLArray<unsigned int>* destHisto = m_workBuffer2;
-
int nWGs = NUM_WGS;
b3ConstData cdata;
{
- int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;//set at 256
- int nBlocks = (n+blockSize-1)/(blockSize);
+ int blockSize = ELEMENTS_PER_WORK_ITEM * WG_SIZE; //set at 256
+ int nBlocks = (n + blockSize - 1) / (blockSize);
cdata.m_n = n;
cdata.m_nWGs = NUM_WGS;
cdata.m_startBit = 0;
- cdata.m_nBlocksPerWG = (nBlocks + cdata.m_nWGs - 1)/cdata.m_nWGs;
- if( nBlocks < NUM_WGS )
+ cdata.m_nBlocksPerWG = (nBlocks + cdata.m_nWGs - 1) / cdata.m_nWGs;
+ if (nBlocks < NUM_WGS)
{
cdata.m_nBlocksPerWG = 1;
nWGs = nBlocks;
}
}
- int count=0;
- for(int ib=0; ib<sortBits; ib+=4)
+ int count = 0;
+ for (int ib = 0; ib < sortBits; ib += 4)
{
cdata.m_startBit = ib;
-
+
if (src->size())
{
- b3BufferInfoCL bInfo[] = { b3BufferInfoCL( src->getBufferCL(), true ), b3BufferInfoCL( srcHisto->getBufferCL() ) };
- b3LauncherCL launcher(m_commandQueue, m_streamCountKernel,"m_streamCountKernel");
-
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst( cdata );
-
- int num = NUM_WGS*WG_SIZE;
- launcher.launch1D( num, WG_SIZE );
- }
+ b3BufferInfoCL bInfo[] = {b3BufferInfoCL(src->getBufferCL(), true), b3BufferInfoCL(srcHisto->getBufferCL())};
+ b3LauncherCL launcher(m_commandQueue, m_streamCountKernel, "m_streamCountKernel");
+
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setConst(cdata);
-
+ int num = NUM_WGS * WG_SIZE;
+ launcher.launch1D(num, WG_SIZE);
+ }
//fast prefix scan is not working properly on Mac OSX yet
#ifdef __APPLE__
- bool fastScan=false;
+ bool fastScan = false;
#else
- bool fastScan=!m_deviceCPU;
+ bool fastScan = !m_deviceCPU;
#endif
if (fastScan)
- {// prefix scan group histogram
- b3BufferInfoCL bInfo[] = { b3BufferInfoCL( srcHisto->getBufferCL() ) };
- b3LauncherCL launcher( m_commandQueue, m_prefixScanKernel,"m_prefixScanKernel" );
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst( cdata );
- launcher.launch1D( 128, 128 );
+ { // prefix scan group histogram
+ b3BufferInfoCL bInfo[] = {b3BufferInfoCL(srcHisto->getBufferCL())};
+ b3LauncherCL launcher(m_commandQueue, m_prefixScanKernel, "m_prefixScanKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setConst(cdata);
+ launcher.launch1D(128, 128);
destHisto = srcHisto;
- }else
+ }
+ else
{
//unsigned int sum; //for debugging
- m_scan->execute(*srcHisto,*destHisto,1920,0);//,&sum);
+ m_scan->execute(*srcHisto, *destHisto, 1920, 0); //,&sum);
}
if (src->size())
- {// local sort and distribute
- b3BufferInfoCL bInfo[] = { b3BufferInfoCL( src->getBufferCL(), true ), b3BufferInfoCL( destHisto->getBufferCL(), true ), b3BufferInfoCL( dst->getBufferCL() )};
- b3LauncherCL launcher( m_commandQueue, m_sortAndScatterKernel ,"m_sortAndScatterKernel");
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst( cdata );
- launcher.launch1D( nWGs*WG_SIZE, WG_SIZE );
-
+ { // local sort and distribute
+ b3BufferInfoCL bInfo[] = {b3BufferInfoCL(src->getBufferCL(), true), b3BufferInfoCL(destHisto->getBufferCL(), true), b3BufferInfoCL(dst->getBufferCL())};
+ b3LauncherCL launcher(m_commandQueue, m_sortAndScatterKernel, "m_sortAndScatterKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setConst(cdata);
+ launcher.launch1D(nWGs * WG_SIZE, WG_SIZE);
}
-
- b3Swap(src, dst );
- b3Swap(srcHisto,destHisto);
- count++;
+ b3Swap(src, dst);
+ b3Swap(srcHisto, destHisto);
+
+ count++;
}
-
- if (count&1)
+
+ if (count & 1)
{
- b3Assert(0);//need to copy from workbuffer to keyValuesInOut
+ b3Assert(0); //need to copy from workbuffer to keyValuesInOut
}
if (m_workBuffer4a->size())
@@ -699,12 +643,4 @@ void b3RadixSort32CL::execute(b3OpenCLArray<unsigned int>& keysInOut, int sortBi
m_workBuffer4a->resize(originalSize);
keysInOut.copyFromOpenCLArray(*m_workBuffer4a);
}
-
}
-
-
-
-
-
-
-
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h
index 975bd80e53..69caf182d7 100644
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h
+++ b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h
@@ -6,90 +6,79 @@
struct b3SortData
{
- union
- {
+ union {
unsigned int m_key;
unsigned int x;
};
- union
- {
+ union {
unsigned int m_value;
unsigned int y;
-
};
};
#include "b3BufferInfoCL.h"
-class b3RadixSort32CL
+class b3RadixSort32CL
{
+ b3OpenCLArray<unsigned int>* m_workBuffer1;
+ b3OpenCLArray<unsigned int>* m_workBuffer2;
- b3OpenCLArray<unsigned int>* m_workBuffer1;
- b3OpenCLArray<unsigned int>* m_workBuffer2;
-
- b3OpenCLArray<b3SortData>* m_workBuffer3;
- b3OpenCLArray<b3SortData>* m_workBuffer4;
-
- b3OpenCLArray<unsigned int>* m_workBuffer3a;
- b3OpenCLArray<unsigned int>* m_workBuffer4a;
+ b3OpenCLArray<b3SortData>* m_workBuffer3;
+ b3OpenCLArray<b3SortData>* m_workBuffer4;
- cl_command_queue m_commandQueue;
+ b3OpenCLArray<unsigned int>* m_workBuffer3a;
+ b3OpenCLArray<unsigned int>* m_workBuffer4a;
- cl_kernel m_streamCountSortDataKernel;
- cl_kernel m_streamCountKernel;
+ cl_command_queue m_commandQueue;
- cl_kernel m_prefixScanKernel;
- cl_kernel m_sortAndScatterSortDataKernel;
- cl_kernel m_sortAndScatterKernel;
+ cl_kernel m_streamCountSortDataKernel;
+ cl_kernel m_streamCountKernel;
+ cl_kernel m_prefixScanKernel;
+ cl_kernel m_sortAndScatterSortDataKernel;
+ cl_kernel m_sortAndScatterKernel;
- bool m_deviceCPU;
+ bool m_deviceCPU;
- class b3PrefixScanCL* m_scan;
- class b3FillCL* m_fill;
+ class b3PrefixScanCL* m_scan;
+ class b3FillCL* m_fill;
public:
struct b3ConstData
- {
- int m_n;
- int m_nWGs;
- int m_startBit;
- int m_nBlocksPerWG;
- };
+ {
+ int m_n;
+ int m_nWGs;
+ int m_startBit;
+ int m_nBlocksPerWG;
+ };
enum
- {
- DATA_ALIGNMENT = 256,
- WG_SIZE = 64,
- BLOCK_SIZE = 256,
- ELEMENTS_PER_WORK_ITEM = (BLOCK_SIZE/WG_SIZE),
- BITS_PER_PASS = 4,
- NUM_BUCKET=(1<<BITS_PER_PASS),
- // if you change this, change nPerWI in kernel as well
- NUM_WGS = 20*6, // cypress
-// NUM_WGS = 24*6, // cayman
-// NUM_WGS = 32*4, // nv
- };
-
+ {
+ DATA_ALIGNMENT = 256,
+ WG_SIZE = 64,
+ BLOCK_SIZE = 256,
+ ELEMENTS_PER_WORK_ITEM = (BLOCK_SIZE / WG_SIZE),
+ BITS_PER_PASS = 4,
+ NUM_BUCKET = (1 << BITS_PER_PASS),
+ // if you change this, change nPerWI in kernel as well
+ NUM_WGS = 20 * 6, // cypress
+ // NUM_WGS = 24*6, // cayman
+ // NUM_WGS = 32*4, // nv
+ };
private:
-
-
public:
+ b3RadixSort32CL(cl_context ctx, cl_device_id device, cl_command_queue queue, int initialCapacity = 0);
- b3RadixSort32CL(cl_context ctx, cl_device_id device, cl_command_queue queue, int initialCapacity =0);
+ virtual ~b3RadixSort32CL();
- virtual ~b3RadixSort32CL();
+ void execute(b3OpenCLArray<unsigned int>& keysIn, b3OpenCLArray<unsigned int>& keysOut, b3OpenCLArray<unsigned int>& valuesIn,
+ b3OpenCLArray<unsigned int>& valuesOut, int n, int sortBits = 32);
- void execute(b3OpenCLArray<unsigned int>& keysIn, b3OpenCLArray<unsigned int>& keysOut, b3OpenCLArray<unsigned int>& valuesIn,
- b3OpenCLArray<unsigned int>& valuesOut, int n, int sortBits = 32);
-
- ///keys only
- void execute(b3OpenCLArray<unsigned int>& keysInOut, int sortBits = 32 );
-
- void execute(b3OpenCLArray<b3SortData>& keyValuesInOut, int sortBits = 32 );
- void executeHost(b3OpenCLArray<b3SortData>& keyValuesInOut, int sortBits = 32);
- void executeHost(b3AlignedObjectArray<b3SortData>& keyValuesInOut, int sortBits = 32);
+ ///keys only
+ void execute(b3OpenCLArray<unsigned int>& keysInOut, int sortBits = 32);
+ void execute(b3OpenCLArray<b3SortData>& keyValuesInOut, int sortBits = 32);
+ void executeHost(b3OpenCLArray<b3SortData>& keyValuesInOut, int sortBits = 32);
+ void executeHost(b3AlignedObjectArray<b3SortData>& keyValuesInOut, int sortBits = 32);
};
-#endif //B3_RADIXSORT32_H
-
+#endif //B3_RADIXSORT32_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/BoundSearchKernelsCL.h b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/BoundSearchKernelsCL.h
index 9c9e847138..1758dd41e3 100644
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/BoundSearchKernelsCL.h
+++ b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/BoundSearchKernelsCL.h
@@ -1,87 +1,86 @@
//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* boundSearchKernelsCL= \
-"/*\n"
-"Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
-"This software is provided 'as-is', without any express or implied warranty.\n"
-"In no event will the authors be held liable for any damages arising from the use of this software.\n"
-"Permission is granted to anyone to use this software for any purpose, \n"
-"including commercial applications, and to alter it and redistribute it freely, \n"
-"subject to the following restrictions:\n"
-"1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
-"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
-"3. This notice may not be removed or altered from any source distribution.\n"
-"*/\n"
-"//Originally written by Takahiro Harada\n"
-"typedef unsigned int u32;\n"
-"#define GET_GROUP_IDX get_group_id(0)\n"
-"#define GET_LOCAL_IDX get_local_id(0)\n"
-"#define GET_GLOBAL_IDX get_global_id(0)\n"
-"#define GET_GROUP_SIZE get_local_size(0)\n"
-"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
-"typedef struct\n"
-"{\n"
-" u32 m_key; \n"
-" u32 m_value;\n"
-"}SortData;\n"
-"typedef struct\n"
-"{\n"
-" u32 m_nSrc;\n"
-" u32 m_nDst;\n"
-" u32 m_padding[2];\n"
-"} ConstBuffer;\n"
-"__attribute__((reqd_work_group_size(64,1,1)))\n"
-"__kernel\n"
-"void SearchSortDataLowerKernel(__global SortData* src, __global u32 *dst, \n"
-" unsigned int nSrc, unsigned int nDst)\n"
-"{\n"
-" int gIdx = GET_GLOBAL_IDX;\n"
-" if( gIdx < nSrc )\n"
-" {\n"
-" SortData first; first.m_key = (u32)(-1); first.m_value = (u32)(-1);\n"
-" SortData end; end.m_key = nDst; end.m_value = nDst;\n"
-" SortData iData = (gIdx==0)? first: src[gIdx-1];\n"
-" SortData jData = (gIdx==nSrc)? end: src[gIdx];\n"
-" if( iData.m_key != jData.m_key )\n"
-" {\n"
-"// for(u32 k=iData.m_key+1; k<=min(jData.m_key, nDst-1); k++)\n"
-" u32 k = jData.m_key;\n"
-" {\n"
-" dst[k] = gIdx;\n"
-" }\n"
-" }\n"
-" }\n"
-"}\n"
-"__attribute__((reqd_work_group_size(64,1,1)))\n"
-"__kernel\n"
-"void SearchSortDataUpperKernel(__global SortData* src, __global u32 *dst, \n"
-" unsigned int nSrc, unsigned int nDst)\n"
-"{\n"
-" int gIdx = GET_GLOBAL_IDX+1;\n"
-" if( gIdx < nSrc+1 )\n"
-" {\n"
-" SortData first; first.m_key = 0; first.m_value = 0;\n"
-" SortData end; end.m_key = nDst; end.m_value = nDst;\n"
-" SortData iData = src[gIdx-1];\n"
-" SortData jData = (gIdx==nSrc)? end: src[gIdx];\n"
-" if( iData.m_key != jData.m_key )\n"
-" {\n"
-" u32 k = iData.m_key;\n"
-" {\n"
-" dst[k] = gIdx;\n"
-" }\n"
-" }\n"
-" }\n"
-"}\n"
-"__attribute__((reqd_work_group_size(64,1,1)))\n"
-"__kernel\n"
-"void SubtractKernel(__global u32* A, __global u32 *B, __global u32 *C, \n"
-" unsigned int nSrc, unsigned int nDst)\n"
-"{\n"
-" int gIdx = GET_GLOBAL_IDX;\n"
-" \n"
-" if( gIdx < nDst )\n"
-" {\n"
-" C[gIdx] = A[gIdx] - B[gIdx];\n"
-" }\n"
-"}\n"
-;
+static const char* boundSearchKernelsCL =
+ "/*\n"
+ "Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
+ "This software is provided 'as-is', without any express or implied warranty.\n"
+ "In no event will the authors be held liable for any damages arising from the use of this software.\n"
+ "Permission is granted to anyone to use this software for any purpose, \n"
+ "including commercial applications, and to alter it and redistribute it freely, \n"
+ "subject to the following restrictions:\n"
+ "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
+ "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+ "3. This notice may not be removed or altered from any source distribution.\n"
+ "*/\n"
+ "//Originally written by Takahiro Harada\n"
+ "typedef unsigned int u32;\n"
+ "#define GET_GROUP_IDX get_group_id(0)\n"
+ "#define GET_LOCAL_IDX get_local_id(0)\n"
+ "#define GET_GLOBAL_IDX get_global_id(0)\n"
+ "#define GET_GROUP_SIZE get_local_size(0)\n"
+ "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+ "typedef struct\n"
+ "{\n"
+ " u32 m_key; \n"
+ " u32 m_value;\n"
+ "}SortData;\n"
+ "typedef struct\n"
+ "{\n"
+ " u32 m_nSrc;\n"
+ " u32 m_nDst;\n"
+ " u32 m_padding[2];\n"
+ "} ConstBuffer;\n"
+ "__attribute__((reqd_work_group_size(64,1,1)))\n"
+ "__kernel\n"
+ "void SearchSortDataLowerKernel(__global SortData* src, __global u32 *dst, \n"
+ " unsigned int nSrc, unsigned int nDst)\n"
+ "{\n"
+ " int gIdx = GET_GLOBAL_IDX;\n"
+ " if( gIdx < nSrc )\n"
+ " {\n"
+ " SortData first; first.m_key = (u32)(-1); first.m_value = (u32)(-1);\n"
+ " SortData end; end.m_key = nDst; end.m_value = nDst;\n"
+ " SortData iData = (gIdx==0)? first: src[gIdx-1];\n"
+ " SortData jData = (gIdx==nSrc)? end: src[gIdx];\n"
+ " if( iData.m_key != jData.m_key )\n"
+ " {\n"
+ "// for(u32 k=iData.m_key+1; k<=min(jData.m_key, nDst-1); k++)\n"
+ " u32 k = jData.m_key;\n"
+ " {\n"
+ " dst[k] = gIdx;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ "}\n"
+ "__attribute__((reqd_work_group_size(64,1,1)))\n"
+ "__kernel\n"
+ "void SearchSortDataUpperKernel(__global SortData* src, __global u32 *dst, \n"
+ " unsigned int nSrc, unsigned int nDst)\n"
+ "{\n"
+ " int gIdx = GET_GLOBAL_IDX+1;\n"
+ " if( gIdx < nSrc+1 )\n"
+ " {\n"
+ " SortData first; first.m_key = 0; first.m_value = 0;\n"
+ " SortData end; end.m_key = nDst; end.m_value = nDst;\n"
+ " SortData iData = src[gIdx-1];\n"
+ " SortData jData = (gIdx==nSrc)? end: src[gIdx];\n"
+ " if( iData.m_key != jData.m_key )\n"
+ " {\n"
+ " u32 k = iData.m_key;\n"
+ " {\n"
+ " dst[k] = gIdx;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ "}\n"
+ "__attribute__((reqd_work_group_size(64,1,1)))\n"
+ "__kernel\n"
+ "void SubtractKernel(__global u32* A, __global u32 *B, __global u32 *C, \n"
+ " unsigned int nSrc, unsigned int nDst)\n"
+ "{\n"
+ " int gIdx = GET_GLOBAL_IDX;\n"
+ " \n"
+ " if( gIdx < nDst )\n"
+ " {\n"
+ " C[gIdx] = A[gIdx] - B[gIdx];\n"
+ " }\n"
+ "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/CopyKernelsCL.h b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/CopyKernelsCL.h
index e5670e3cd3..33c9279462 100644
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/CopyKernelsCL.h
+++ b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/CopyKernelsCL.h
@@ -1,132 +1,131 @@
//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* copyKernelsCL= \
-"/*\n"
-"Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
-"\n"
-"This software is provided 'as-is', without any express or implied warranty.\n"
-"In no event will the authors be held liable for any damages arising from the use of this software.\n"
-"Permission is granted to anyone to use this software for any purpose, \n"
-"including commercial applications, and to alter it and redistribute it freely, \n"
-"subject to the following restrictions:\n"
-"\n"
-"1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
-"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
-"3. This notice may not be removed or altered from any source distribution.\n"
-"*/\n"
-"//Originally written by Takahiro Harada\n"
-"\n"
-"#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
-"\n"
-"typedef unsigned int u32;\n"
-"#define GET_GROUP_IDX get_group_id(0)\n"
-"#define GET_LOCAL_IDX get_local_id(0)\n"
-"#define GET_GLOBAL_IDX get_global_id(0)\n"
-"#define GET_GROUP_SIZE get_local_size(0)\n"
-"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
-"#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
-"#define AtomInc(x) atom_inc(&(x))\n"
-"#define AtomInc1(x, out) out = atom_inc(&(x))\n"
-"\n"
-"#define make_uint4 (uint4)\n"
-"#define make_uint2 (uint2)\n"
-"#define make_int2 (int2)\n"
-"\n"
-"typedef struct\n"
-"{\n"
-" int m_n;\n"
-" int m_padding[3];\n"
-"} ConstBuffer;\n"
-"\n"
-"\n"
-"\n"
-"__kernel\n"
-"__attribute__((reqd_work_group_size(64,1,1)))\n"
-"void Copy1F4Kernel(__global float4* dst, __global float4* src, \n"
-" ConstBuffer cb)\n"
-"{\n"
-" int gIdx = GET_GLOBAL_IDX;\n"
-"\n"
-" if( gIdx < cb.m_n )\n"
-" {\n"
-" float4 a0 = src[gIdx];\n"
-"\n"
-" dst[ gIdx ] = a0;\n"
-" }\n"
-"}\n"
-"\n"
-"__kernel\n"
-"__attribute__((reqd_work_group_size(64,1,1)))\n"
-"void Copy2F4Kernel(__global float4* dst, __global float4* src, \n"
-" ConstBuffer cb)\n"
-"{\n"
-" int gIdx = GET_GLOBAL_IDX;\n"
-"\n"
-" if( 2*gIdx <= cb.m_n )\n"
-" {\n"
-" float4 a0 = src[gIdx*2+0];\n"
-" float4 a1 = src[gIdx*2+1];\n"
-"\n"
-" dst[ gIdx*2+0 ] = a0;\n"
-" dst[ gIdx*2+1 ] = a1;\n"
-" }\n"
-"}\n"
-"\n"
-"__kernel\n"
-"__attribute__((reqd_work_group_size(64,1,1)))\n"
-"void Copy4F4Kernel(__global float4* dst, __global float4* src, \n"
-" ConstBuffer cb)\n"
-"{\n"
-" int gIdx = GET_GLOBAL_IDX;\n"
-"\n"
-" if( 4*gIdx <= cb.m_n )\n"
-" {\n"
-" int idx0 = gIdx*4+0;\n"
-" int idx1 = gIdx*4+1;\n"
-" int idx2 = gIdx*4+2;\n"
-" int idx3 = gIdx*4+3;\n"
-"\n"
-" float4 a0 = src[idx0];\n"
-" float4 a1 = src[idx1];\n"
-" float4 a2 = src[idx2];\n"
-" float4 a3 = src[idx3];\n"
-"\n"
-" dst[ idx0 ] = a0;\n"
-" dst[ idx1 ] = a1;\n"
-" dst[ idx2 ] = a2;\n"
-" dst[ idx3 ] = a3;\n"
-" }\n"
-"}\n"
-"\n"
-"__kernel\n"
-"__attribute__((reqd_work_group_size(64,1,1)))\n"
-"void CopyF1Kernel(__global float* dstF1, __global float* srcF1, \n"
-" ConstBuffer cb)\n"
-"{\n"
-" int gIdx = GET_GLOBAL_IDX;\n"
-"\n"
-" if( gIdx < cb.m_n )\n"
-" {\n"
-" float a0 = srcF1[gIdx];\n"
-"\n"
-" dstF1[ gIdx ] = a0;\n"
-" }\n"
-"}\n"
-"\n"
-"__kernel\n"
-"__attribute__((reqd_work_group_size(64,1,1)))\n"
-"void CopyF2Kernel(__global float2* dstF2, __global float2* srcF2, \n"
-" ConstBuffer cb)\n"
-"{\n"
-" int gIdx = GET_GLOBAL_IDX;\n"
-"\n"
-" if( gIdx < cb.m_n )\n"
-" {\n"
-" float2 a0 = srcF2[gIdx];\n"
-"\n"
-" dstF2[ gIdx ] = a0;\n"
-" }\n"
-"}\n"
-"\n"
-"\n"
-;
+static const char* copyKernelsCL =
+ "/*\n"
+ "Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
+ "\n"
+ "This software is provided 'as-is', without any express or implied warranty.\n"
+ "In no event will the authors be held liable for any damages arising from the use of this software.\n"
+ "Permission is granted to anyone to use this software for any purpose, \n"
+ "including commercial applications, and to alter it and redistribute it freely, \n"
+ "subject to the following restrictions:\n"
+ "\n"
+ "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
+ "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+ "3. This notice may not be removed or altered from any source distribution.\n"
+ "*/\n"
+ "//Originally written by Takahiro Harada\n"
+ "\n"
+ "#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
+ "\n"
+ "typedef unsigned int u32;\n"
+ "#define GET_GROUP_IDX get_group_id(0)\n"
+ "#define GET_LOCAL_IDX get_local_id(0)\n"
+ "#define GET_GLOBAL_IDX get_global_id(0)\n"
+ "#define GET_GROUP_SIZE get_local_size(0)\n"
+ "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+ "#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
+ "#define AtomInc(x) atom_inc(&(x))\n"
+ "#define AtomInc1(x, out) out = atom_inc(&(x))\n"
+ "\n"
+ "#define make_uint4 (uint4)\n"
+ "#define make_uint2 (uint2)\n"
+ "#define make_int2 (int2)\n"
+ "\n"
+ "typedef struct\n"
+ "{\n"
+ " int m_n;\n"
+ " int m_padding[3];\n"
+ "} ConstBuffer;\n"
+ "\n"
+ "\n"
+ "\n"
+ "__kernel\n"
+ "__attribute__((reqd_work_group_size(64,1,1)))\n"
+ "void Copy1F4Kernel(__global float4* dst, __global float4* src, \n"
+ " ConstBuffer cb)\n"
+ "{\n"
+ " int gIdx = GET_GLOBAL_IDX;\n"
+ "\n"
+ " if( gIdx < cb.m_n )\n"
+ " {\n"
+ " float4 a0 = src[gIdx];\n"
+ "\n"
+ " dst[ gIdx ] = a0;\n"
+ " }\n"
+ "}\n"
+ "\n"
+ "__kernel\n"
+ "__attribute__((reqd_work_group_size(64,1,1)))\n"
+ "void Copy2F4Kernel(__global float4* dst, __global float4* src, \n"
+ " ConstBuffer cb)\n"
+ "{\n"
+ " int gIdx = GET_GLOBAL_IDX;\n"
+ "\n"
+ " if( 2*gIdx <= cb.m_n )\n"
+ " {\n"
+ " float4 a0 = src[gIdx*2+0];\n"
+ " float4 a1 = src[gIdx*2+1];\n"
+ "\n"
+ " dst[ gIdx*2+0 ] = a0;\n"
+ " dst[ gIdx*2+1 ] = a1;\n"
+ " }\n"
+ "}\n"
+ "\n"
+ "__kernel\n"
+ "__attribute__((reqd_work_group_size(64,1,1)))\n"
+ "void Copy4F4Kernel(__global float4* dst, __global float4* src, \n"
+ " ConstBuffer cb)\n"
+ "{\n"
+ " int gIdx = GET_GLOBAL_IDX;\n"
+ "\n"
+ " if( 4*gIdx <= cb.m_n )\n"
+ " {\n"
+ " int idx0 = gIdx*4+0;\n"
+ " int idx1 = gIdx*4+1;\n"
+ " int idx2 = gIdx*4+2;\n"
+ " int idx3 = gIdx*4+3;\n"
+ "\n"
+ " float4 a0 = src[idx0];\n"
+ " float4 a1 = src[idx1];\n"
+ " float4 a2 = src[idx2];\n"
+ " float4 a3 = src[idx3];\n"
+ "\n"
+ " dst[ idx0 ] = a0;\n"
+ " dst[ idx1 ] = a1;\n"
+ " dst[ idx2 ] = a2;\n"
+ " dst[ idx3 ] = a3;\n"
+ " }\n"
+ "}\n"
+ "\n"
+ "__kernel\n"
+ "__attribute__((reqd_work_group_size(64,1,1)))\n"
+ "void CopyF1Kernel(__global float* dstF1, __global float* srcF1, \n"
+ " ConstBuffer cb)\n"
+ "{\n"
+ " int gIdx = GET_GLOBAL_IDX;\n"
+ "\n"
+ " if( gIdx < cb.m_n )\n"
+ " {\n"
+ " float a0 = srcF1[gIdx];\n"
+ "\n"
+ " dstF1[ gIdx ] = a0;\n"
+ " }\n"
+ "}\n"
+ "\n"
+ "__kernel\n"
+ "__attribute__((reqd_work_group_size(64,1,1)))\n"
+ "void CopyF2Kernel(__global float2* dstF2, __global float2* srcF2, \n"
+ " ConstBuffer cb)\n"
+ "{\n"
+ " int gIdx = GET_GLOBAL_IDX;\n"
+ "\n"
+ " if( gIdx < cb.m_n )\n"
+ " {\n"
+ " float2 a0 = srcF2[gIdx];\n"
+ "\n"
+ " dstF2[ gIdx ] = a0;\n"
+ " }\n"
+ "}\n"
+ "\n"
+ "\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/FillKernelsCL.h b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/FillKernelsCL.h
index 4f8b96e489..983e652270 100644
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/FillKernelsCL.h
+++ b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/FillKernelsCL.h
@@ -1,91 +1,90 @@
//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* fillKernelsCL= \
-"/*\n"
-"Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
-"This software is provided 'as-is', without any express or implied warranty.\n"
-"In no event will the authors be held liable for any damages arising from the use of this software.\n"
-"Permission is granted to anyone to use this software for any purpose, \n"
-"including commercial applications, and to alter it and redistribute it freely, \n"
-"subject to the following restrictions:\n"
-"1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
-"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
-"3. This notice may not be removed or altered from any source distribution.\n"
-"*/\n"
-"//Originally written by Takahiro Harada\n"
-"#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
-"typedef unsigned int u32;\n"
-"#define GET_GROUP_IDX get_group_id(0)\n"
-"#define GET_LOCAL_IDX get_local_id(0)\n"
-"#define GET_GLOBAL_IDX get_global_id(0)\n"
-"#define GET_GROUP_SIZE get_local_size(0)\n"
-"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
-"#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
-"#define AtomInc(x) atom_inc(&(x))\n"
-"#define AtomInc1(x, out) out = atom_inc(&(x))\n"
-"#define make_uint4 (uint4)\n"
-"#define make_uint2 (uint2)\n"
-"#define make_int2 (int2)\n"
-"typedef struct\n"
-"{\n"
-" union\n"
-" {\n"
-" int4 m_data;\n"
-" uint4 m_unsignedData;\n"
-" float m_floatData;\n"
-" };\n"
-" int m_offset;\n"
-" int m_n;\n"
-" int m_padding[2];\n"
-"} ConstBuffer;\n"
-"__kernel\n"
-"__attribute__((reqd_work_group_size(64,1,1)))\n"
-"void FillIntKernel(__global int* dstInt, int num_elements, int value, const int offset)\n"
-"{\n"
-" int gIdx = GET_GLOBAL_IDX;\n"
-" if( gIdx < num_elements )\n"
-" {\n"
-" dstInt[ offset+gIdx ] = value;\n"
-" }\n"
-"}\n"
-"__kernel\n"
-"__attribute__((reqd_work_group_size(64,1,1)))\n"
-"void FillFloatKernel(__global float* dstFloat, int num_elements, float value, const int offset)\n"
-"{\n"
-" int gIdx = GET_GLOBAL_IDX;\n"
-" if( gIdx < num_elements )\n"
-" {\n"
-" dstFloat[ offset+gIdx ] = value;\n"
-" }\n"
-"}\n"
-"__kernel\n"
-"__attribute__((reqd_work_group_size(64,1,1)))\n"
-"void FillUnsignedIntKernel(__global unsigned int* dstInt, const int num, const unsigned int value, const int offset)\n"
-"{\n"
-" int gIdx = GET_GLOBAL_IDX;\n"
-" if( gIdx < num )\n"
-" {\n"
-" dstInt[ offset+gIdx ] = value;\n"
-" }\n"
-"}\n"
-"__kernel\n"
-"__attribute__((reqd_work_group_size(64,1,1)))\n"
-"void FillInt2Kernel(__global int2* dstInt2, const int num, const int2 value, const int offset)\n"
-"{\n"
-" int gIdx = GET_GLOBAL_IDX;\n"
-" if( gIdx < num )\n"
-" {\n"
-" dstInt2[ gIdx + offset] = make_int2( value.x, value.y );\n"
-" }\n"
-"}\n"
-"__kernel\n"
-"__attribute__((reqd_work_group_size(64,1,1)))\n"
-"void FillInt4Kernel(__global int4* dstInt4, const int num, const int4 value, const int offset)\n"
-"{\n"
-" int gIdx = GET_GLOBAL_IDX;\n"
-" if( gIdx < num )\n"
-" {\n"
-" dstInt4[ offset+gIdx ] = value;\n"
-" }\n"
-"}\n"
-;
+static const char* fillKernelsCL =
+ "/*\n"
+ "Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
+ "This software is provided 'as-is', without any express or implied warranty.\n"
+ "In no event will the authors be held liable for any damages arising from the use of this software.\n"
+ "Permission is granted to anyone to use this software for any purpose, \n"
+ "including commercial applications, and to alter it and redistribute it freely, \n"
+ "subject to the following restrictions:\n"
+ "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
+ "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+ "3. This notice may not be removed or altered from any source distribution.\n"
+ "*/\n"
+ "//Originally written by Takahiro Harada\n"
+ "#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
+ "typedef unsigned int u32;\n"
+ "#define GET_GROUP_IDX get_group_id(0)\n"
+ "#define GET_LOCAL_IDX get_local_id(0)\n"
+ "#define GET_GLOBAL_IDX get_global_id(0)\n"
+ "#define GET_GROUP_SIZE get_local_size(0)\n"
+ "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+ "#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
+ "#define AtomInc(x) atom_inc(&(x))\n"
+ "#define AtomInc1(x, out) out = atom_inc(&(x))\n"
+ "#define make_uint4 (uint4)\n"
+ "#define make_uint2 (uint2)\n"
+ "#define make_int2 (int2)\n"
+ "typedef struct\n"
+ "{\n"
+ " union\n"
+ " {\n"
+ " int4 m_data;\n"
+ " uint4 m_unsignedData;\n"
+ " float m_floatData;\n"
+ " };\n"
+ " int m_offset;\n"
+ " int m_n;\n"
+ " int m_padding[2];\n"
+ "} ConstBuffer;\n"
+ "__kernel\n"
+ "__attribute__((reqd_work_group_size(64,1,1)))\n"
+ "void FillIntKernel(__global int* dstInt, int num_elements, int value, const int offset)\n"
+ "{\n"
+ " int gIdx = GET_GLOBAL_IDX;\n"
+ " if( gIdx < num_elements )\n"
+ " {\n"
+ " dstInt[ offset+gIdx ] = value;\n"
+ " }\n"
+ "}\n"
+ "__kernel\n"
+ "__attribute__((reqd_work_group_size(64,1,1)))\n"
+ "void FillFloatKernel(__global float* dstFloat, int num_elements, float value, const int offset)\n"
+ "{\n"
+ " int gIdx = GET_GLOBAL_IDX;\n"
+ " if( gIdx < num_elements )\n"
+ " {\n"
+ " dstFloat[ offset+gIdx ] = value;\n"
+ " }\n"
+ "}\n"
+ "__kernel\n"
+ "__attribute__((reqd_work_group_size(64,1,1)))\n"
+ "void FillUnsignedIntKernel(__global unsigned int* dstInt, const int num, const unsigned int value, const int offset)\n"
+ "{\n"
+ " int gIdx = GET_GLOBAL_IDX;\n"
+ " if( gIdx < num )\n"
+ " {\n"
+ " dstInt[ offset+gIdx ] = value;\n"
+ " }\n"
+ "}\n"
+ "__kernel\n"
+ "__attribute__((reqd_work_group_size(64,1,1)))\n"
+ "void FillInt2Kernel(__global int2* dstInt2, const int num, const int2 value, const int offset)\n"
+ "{\n"
+ " int gIdx = GET_GLOBAL_IDX;\n"
+ " if( gIdx < num )\n"
+ " {\n"
+ " dstInt2[ gIdx + offset] = make_int2( value.x, value.y );\n"
+ " }\n"
+ "}\n"
+ "__kernel\n"
+ "__attribute__((reqd_work_group_size(64,1,1)))\n"
+ "void FillInt4Kernel(__global int4* dstInt4, const int num, const int4 value, const int offset)\n"
+ "{\n"
+ " int gIdx = GET_GLOBAL_IDX;\n"
+ " if( gIdx < num )\n"
+ " {\n"
+ " dstInt4[ offset+gIdx ] = value;\n"
+ " }\n"
+ "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernelsCL.h b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernelsCL.h
index 27baab8331..fc5e7b865c 100644
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernelsCL.h
+++ b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernelsCL.h
@@ -1,129 +1,128 @@
//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* prefixScanKernelsCL= \
-"/*\n"
-"Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
-"This software is provided 'as-is', without any express or implied warranty.\n"
-"In no event will the authors be held liable for any damages arising from the use of this software.\n"
-"Permission is granted to anyone to use this software for any purpose, \n"
-"including commercial applications, and to alter it and redistribute it freely, \n"
-"subject to the following restrictions:\n"
-"1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
-"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
-"3. This notice may not be removed or altered from any source distribution.\n"
-"*/\n"
-"//Originally written by Takahiro Harada\n"
-"typedef unsigned int u32;\n"
-"#define GET_GROUP_IDX get_group_id(0)\n"
-"#define GET_LOCAL_IDX get_local_id(0)\n"
-"#define GET_GLOBAL_IDX get_global_id(0)\n"
-"#define GET_GROUP_SIZE get_local_size(0)\n"
-"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
-"// takahiro end\n"
-"#define WG_SIZE 128 \n"
-"#define m_numElems x\n"
-"#define m_numBlocks y\n"
-"#define m_numScanBlocks z\n"
-"/*typedef struct\n"
-"{\n"
-" uint m_numElems;\n"
-" uint m_numBlocks;\n"
-" uint m_numScanBlocks;\n"
-" uint m_padding[1];\n"
-"} ConstBuffer;\n"
-"*/\n"
-"u32 ScanExclusive(__local u32* data, u32 n, int lIdx, int lSize)\n"
-"{\n"
-" u32 blocksum;\n"
-" int offset = 1;\n"
-" for(int nActive=n>>1; nActive>0; nActive>>=1, offset<<=1)\n"
-" {\n"
-" GROUP_LDS_BARRIER;\n"
-" for(int iIdx=lIdx; iIdx<nActive; iIdx+=lSize)\n"
-" {\n"
-" int ai = offset*(2*iIdx+1)-1;\n"
-" int bi = offset*(2*iIdx+2)-1;\n"
-" data[bi] += data[ai];\n"
-" }\n"
-" }\n"
-" GROUP_LDS_BARRIER;\n"
-" if( lIdx == 0 )\n"
-" {\n"
-" blocksum = data[ n-1 ];\n"
-" data[ n-1 ] = 0;\n"
-" }\n"
-" GROUP_LDS_BARRIER;\n"
-" offset >>= 1;\n"
-" for(int nActive=1; nActive<n; nActive<<=1, offset>>=1 )\n"
-" {\n"
-" GROUP_LDS_BARRIER;\n"
-" for( int iIdx = lIdx; iIdx<nActive; iIdx += lSize )\n"
-" {\n"
-" int ai = offset*(2*iIdx+1)-1;\n"
-" int bi = offset*(2*iIdx+2)-1;\n"
-" u32 temp = data[ai];\n"
-" data[ai] = data[bi];\n"
-" data[bi] += temp;\n"
-" }\n"
-" }\n"
-" GROUP_LDS_BARRIER;\n"
-" return blocksum;\n"
-"}\n"
-"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
-"__kernel\n"
-"void LocalScanKernel(__global u32* dst, __global u32 *src, __global u32 *sumBuffer,\n"
-" uint4 cb)\n"
-"{\n"
-" __local u32 ldsData[WG_SIZE*2];\n"
-" int gIdx = GET_GLOBAL_IDX;\n"
-" int lIdx = GET_LOCAL_IDX;\n"
-" ldsData[2*lIdx] = ( 2*gIdx < cb.m_numElems )? src[2*gIdx]: 0;\n"
-" ldsData[2*lIdx + 1] = ( 2*gIdx+1 < cb.m_numElems )? src[2*gIdx + 1]: 0;\n"
-" u32 sum = ScanExclusive(ldsData, WG_SIZE*2, GET_LOCAL_IDX, GET_GROUP_SIZE);\n"
-" if( lIdx == 0 ) sumBuffer[GET_GROUP_IDX] = sum;\n"
-" if( (2*gIdx) < cb.m_numElems )\n"
-" {\n"
-" dst[2*gIdx] = ldsData[2*lIdx];\n"
-" }\n"
-" if( (2*gIdx + 1) < cb.m_numElems )\n"
-" {\n"
-" dst[2*gIdx + 1] = ldsData[2*lIdx + 1];\n"
-" }\n"
-"}\n"
-"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
-"__kernel\n"
-"void AddOffsetKernel(__global u32 *dst, __global u32 *blockSum, uint4 cb)\n"
-"{\n"
-" const u32 blockSize = WG_SIZE*2;\n"
-" int myIdx = GET_GROUP_IDX+1;\n"
-" int lIdx = GET_LOCAL_IDX;\n"
-" u32 iBlockSum = blockSum[myIdx];\n"
-" int endValue = min((myIdx+1)*(blockSize), cb.m_numElems);\n"
-" for(int i=myIdx*blockSize+lIdx; i<endValue; i+=GET_GROUP_SIZE)\n"
-" {\n"
-" dst[i] += iBlockSum;\n"
-" }\n"
-"}\n"
-"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
-"__kernel\n"
-"void TopLevelScanKernel(__global u32* dst, uint4 cb)\n"
-"{\n"
-" __local u32 ldsData[2048];\n"
-" int gIdx = GET_GLOBAL_IDX;\n"
-" int lIdx = GET_LOCAL_IDX;\n"
-" int lSize = GET_GROUP_SIZE;\n"
-" for(int i=lIdx; i<cb.m_numScanBlocks; i+=lSize )\n"
-" {\n"
-" ldsData[i] = (i<cb.m_numBlocks)? dst[i]:0;\n"
-" }\n"
-" GROUP_LDS_BARRIER;\n"
-" u32 sum = ScanExclusive(ldsData, cb.m_numScanBlocks, GET_LOCAL_IDX, GET_GROUP_SIZE);\n"
-" for(int i=lIdx; i<cb.m_numBlocks; i+=lSize )\n"
-" {\n"
-" dst[i] = ldsData[i];\n"
-" }\n"
-" if( gIdx == 0 )\n"
-" {\n"
-" dst[cb.m_numBlocks] = sum;\n"
-" }\n"
-"}\n"
-;
+static const char* prefixScanKernelsCL =
+ "/*\n"
+ "Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
+ "This software is provided 'as-is', without any express or implied warranty.\n"
+ "In no event will the authors be held liable for any damages arising from the use of this software.\n"
+ "Permission is granted to anyone to use this software for any purpose, \n"
+ "including commercial applications, and to alter it and redistribute it freely, \n"
+ "subject to the following restrictions:\n"
+ "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
+ "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+ "3. This notice may not be removed or altered from any source distribution.\n"
+ "*/\n"
+ "//Originally written by Takahiro Harada\n"
+ "typedef unsigned int u32;\n"
+ "#define GET_GROUP_IDX get_group_id(0)\n"
+ "#define GET_LOCAL_IDX get_local_id(0)\n"
+ "#define GET_GLOBAL_IDX get_global_id(0)\n"
+ "#define GET_GROUP_SIZE get_local_size(0)\n"
+ "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+ "// takahiro end\n"
+ "#define WG_SIZE 128 \n"
+ "#define m_numElems x\n"
+ "#define m_numBlocks y\n"
+ "#define m_numScanBlocks z\n"
+ "/*typedef struct\n"
+ "{\n"
+ " uint m_numElems;\n"
+ " uint m_numBlocks;\n"
+ " uint m_numScanBlocks;\n"
+ " uint m_padding[1];\n"
+ "} ConstBuffer;\n"
+ "*/\n"
+ "u32 ScanExclusive(__local u32* data, u32 n, int lIdx, int lSize)\n"
+ "{\n"
+ " u32 blocksum;\n"
+ " int offset = 1;\n"
+ " for(int nActive=n>>1; nActive>0; nActive>>=1, offset<<=1)\n"
+ " {\n"
+ " GROUP_LDS_BARRIER;\n"
+ " for(int iIdx=lIdx; iIdx<nActive; iIdx+=lSize)\n"
+ " {\n"
+ " int ai = offset*(2*iIdx+1)-1;\n"
+ " int bi = offset*(2*iIdx+2)-1;\n"
+ " data[bi] += data[ai];\n"
+ " }\n"
+ " }\n"
+ " GROUP_LDS_BARRIER;\n"
+ " if( lIdx == 0 )\n"
+ " {\n"
+ " blocksum = data[ n-1 ];\n"
+ " data[ n-1 ] = 0;\n"
+ " }\n"
+ " GROUP_LDS_BARRIER;\n"
+ " offset >>= 1;\n"
+ " for(int nActive=1; nActive<n; nActive<<=1, offset>>=1 )\n"
+ " {\n"
+ " GROUP_LDS_BARRIER;\n"
+ " for( int iIdx = lIdx; iIdx<nActive; iIdx += lSize )\n"
+ " {\n"
+ " int ai = offset*(2*iIdx+1)-1;\n"
+ " int bi = offset*(2*iIdx+2)-1;\n"
+ " u32 temp = data[ai];\n"
+ " data[ai] = data[bi];\n"
+ " data[bi] += temp;\n"
+ " }\n"
+ " }\n"
+ " GROUP_LDS_BARRIER;\n"
+ " return blocksum;\n"
+ "}\n"
+ "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+ "__kernel\n"
+ "void LocalScanKernel(__global u32* dst, __global u32 *src, __global u32 *sumBuffer,\n"
+ " uint4 cb)\n"
+ "{\n"
+ " __local u32 ldsData[WG_SIZE*2];\n"
+ " int gIdx = GET_GLOBAL_IDX;\n"
+ " int lIdx = GET_LOCAL_IDX;\n"
+ " ldsData[2*lIdx] = ( 2*gIdx < cb.m_numElems )? src[2*gIdx]: 0;\n"
+ " ldsData[2*lIdx + 1] = ( 2*gIdx+1 < cb.m_numElems )? src[2*gIdx + 1]: 0;\n"
+ " u32 sum = ScanExclusive(ldsData, WG_SIZE*2, GET_LOCAL_IDX, GET_GROUP_SIZE);\n"
+ " if( lIdx == 0 ) sumBuffer[GET_GROUP_IDX] = sum;\n"
+ " if( (2*gIdx) < cb.m_numElems )\n"
+ " {\n"
+ " dst[2*gIdx] = ldsData[2*lIdx];\n"
+ " }\n"
+ " if( (2*gIdx + 1) < cb.m_numElems )\n"
+ " {\n"
+ " dst[2*gIdx + 1] = ldsData[2*lIdx + 1];\n"
+ " }\n"
+ "}\n"
+ "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+ "__kernel\n"
+ "void AddOffsetKernel(__global u32 *dst, __global u32 *blockSum, uint4 cb)\n"
+ "{\n"
+ " const u32 blockSize = WG_SIZE*2;\n"
+ " int myIdx = GET_GROUP_IDX+1;\n"
+ " int lIdx = GET_LOCAL_IDX;\n"
+ " u32 iBlockSum = blockSum[myIdx];\n"
+ " int endValue = min((myIdx+1)*(blockSize), cb.m_numElems);\n"
+ " for(int i=myIdx*blockSize+lIdx; i<endValue; i+=GET_GROUP_SIZE)\n"
+ " {\n"
+ " dst[i] += iBlockSum;\n"
+ " }\n"
+ "}\n"
+ "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+ "__kernel\n"
+ "void TopLevelScanKernel(__global u32* dst, uint4 cb)\n"
+ "{\n"
+ " __local u32 ldsData[2048];\n"
+ " int gIdx = GET_GLOBAL_IDX;\n"
+ " int lIdx = GET_LOCAL_IDX;\n"
+ " int lSize = GET_GROUP_SIZE;\n"
+ " for(int i=lIdx; i<cb.m_numScanBlocks; i+=lSize )\n"
+ " {\n"
+ " ldsData[i] = (i<cb.m_numBlocks)? dst[i]:0;\n"
+ " }\n"
+ " GROUP_LDS_BARRIER;\n"
+ " u32 sum = ScanExclusive(ldsData, cb.m_numScanBlocks, GET_LOCAL_IDX, GET_GROUP_SIZE);\n"
+ " for(int i=lIdx; i<cb.m_numBlocks; i+=lSize )\n"
+ " {\n"
+ " dst[i] = ldsData[i];\n"
+ " }\n"
+ " if( gIdx == 0 )\n"
+ " {\n"
+ " dst[cb.m_numBlocks] = sum;\n"
+ " }\n"
+ "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernelsFloat4CL.h b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernelsFloat4CL.h
index 5b13254796..15d1bc5195 100644
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernelsFloat4CL.h
+++ b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernelsFloat4CL.h
@@ -1,129 +1,128 @@
//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* prefixScanKernelsFloat4CL= \
-"/*\n"
-"Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
-"This software is provided 'as-is', without any express or implied warranty.\n"
-"In no event will the authors be held liable for any damages arising from the use of this software.\n"
-"Permission is granted to anyone to use this software for any purpose, \n"
-"including commercial applications, and to alter it and redistribute it freely, \n"
-"subject to the following restrictions:\n"
-"1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
-"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
-"3. This notice may not be removed or altered from any source distribution.\n"
-"*/\n"
-"//Originally written by Takahiro Harada\n"
-"typedef unsigned int u32;\n"
-"#define GET_GROUP_IDX get_group_id(0)\n"
-"#define GET_LOCAL_IDX get_local_id(0)\n"
-"#define GET_GLOBAL_IDX get_global_id(0)\n"
-"#define GET_GROUP_SIZE get_local_size(0)\n"
-"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
-"// takahiro end\n"
-"#define WG_SIZE 128 \n"
-"#define m_numElems x\n"
-"#define m_numBlocks y\n"
-"#define m_numScanBlocks z\n"
-"/*typedef struct\n"
-"{\n"
-" uint m_numElems;\n"
-" uint m_numBlocks;\n"
-" uint m_numScanBlocks;\n"
-" uint m_padding[1];\n"
-"} ConstBuffer;\n"
-"*/\n"
-"float4 ScanExclusiveFloat4(__local float4* data, u32 n, int lIdx, int lSize)\n"
-"{\n"
-" float4 blocksum;\n"
-" int offset = 1;\n"
-" for(int nActive=n>>1; nActive>0; nActive>>=1, offset<<=1)\n"
-" {\n"
-" GROUP_LDS_BARRIER;\n"
-" for(int iIdx=lIdx; iIdx<nActive; iIdx+=lSize)\n"
-" {\n"
-" int ai = offset*(2*iIdx+1)-1;\n"
-" int bi = offset*(2*iIdx+2)-1;\n"
-" data[bi] += data[ai];\n"
-" }\n"
-" }\n"
-" GROUP_LDS_BARRIER;\n"
-" if( lIdx == 0 )\n"
-" {\n"
-" blocksum = data[ n-1 ];\n"
-" data[ n-1 ] = 0;\n"
-" }\n"
-" GROUP_LDS_BARRIER;\n"
-" offset >>= 1;\n"
-" for(int nActive=1; nActive<n; nActive<<=1, offset>>=1 )\n"
-" {\n"
-" GROUP_LDS_BARRIER;\n"
-" for( int iIdx = lIdx; iIdx<nActive; iIdx += lSize )\n"
-" {\n"
-" int ai = offset*(2*iIdx+1)-1;\n"
-" int bi = offset*(2*iIdx+2)-1;\n"
-" float4 temp = data[ai];\n"
-" data[ai] = data[bi];\n"
-" data[bi] += temp;\n"
-" }\n"
-" }\n"
-" GROUP_LDS_BARRIER;\n"
-" return blocksum;\n"
-"}\n"
-"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
-"__kernel\n"
-"void LocalScanKernel(__global float4* dst, __global float4* src, __global float4* sumBuffer, uint4 cb)\n"
-"{\n"
-" __local float4 ldsData[WG_SIZE*2];\n"
-" int gIdx = GET_GLOBAL_IDX;\n"
-" int lIdx = GET_LOCAL_IDX;\n"
-" ldsData[2*lIdx] = ( 2*gIdx < cb.m_numElems )? src[2*gIdx]: 0;\n"
-" ldsData[2*lIdx + 1] = ( 2*gIdx+1 < cb.m_numElems )? src[2*gIdx + 1]: 0;\n"
-" float4 sum = ScanExclusiveFloat4(ldsData, WG_SIZE*2, GET_LOCAL_IDX, GET_GROUP_SIZE);\n"
-" if( lIdx == 0 ) \n"
-" sumBuffer[GET_GROUP_IDX] = sum;\n"
-" if( (2*gIdx) < cb.m_numElems )\n"
-" {\n"
-" dst[2*gIdx] = ldsData[2*lIdx];\n"
-" }\n"
-" if( (2*gIdx + 1) < cb.m_numElems )\n"
-" {\n"
-" dst[2*gIdx + 1] = ldsData[2*lIdx + 1];\n"
-" }\n"
-"}\n"
-"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
-"__kernel\n"
-"void AddOffsetKernel(__global float4* dst, __global float4* blockSum, uint4 cb)\n"
-"{\n"
-" const u32 blockSize = WG_SIZE*2;\n"
-" int myIdx = GET_GROUP_IDX+1;\n"
-" int lIdx = GET_LOCAL_IDX;\n"
-" float4 iBlockSum = blockSum[myIdx];\n"
-" int endValue = min((myIdx+1)*(blockSize), cb.m_numElems);\n"
-" for(int i=myIdx*blockSize+lIdx; i<endValue; i+=GET_GROUP_SIZE)\n"
-" {\n"
-" dst[i] += iBlockSum;\n"
-" }\n"
-"}\n"
-"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
-"__kernel\n"
-"void TopLevelScanKernel(__global float4* dst, uint4 cb)\n"
-"{\n"
-" __local float4 ldsData[2048];\n"
-" int gIdx = GET_GLOBAL_IDX;\n"
-" int lIdx = GET_LOCAL_IDX;\n"
-" int lSize = GET_GROUP_SIZE;\n"
-" for(int i=lIdx; i<cb.m_numScanBlocks; i+=lSize )\n"
-" {\n"
-" ldsData[i] = (i<cb.m_numBlocks)? dst[i]:0;\n"
-" }\n"
-" GROUP_LDS_BARRIER;\n"
-" float4 sum = ScanExclusiveFloat4(ldsData, cb.m_numScanBlocks, GET_LOCAL_IDX, GET_GROUP_SIZE);\n"
-" for(int i=lIdx; i<cb.m_numBlocks; i+=lSize )\n"
-" {\n"
-" dst[i] = ldsData[i];\n"
-" }\n"
-" if( gIdx == 0 )\n"
-" {\n"
-" dst[cb.m_numBlocks] = sum;\n"
-" }\n"
-"}\n"
-;
+static const char* prefixScanKernelsFloat4CL =
+ "/*\n"
+ "Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
+ "This software is provided 'as-is', without any express or implied warranty.\n"
+ "In no event will the authors be held liable for any damages arising from the use of this software.\n"
+ "Permission is granted to anyone to use this software for any purpose, \n"
+ "including commercial applications, and to alter it and redistribute it freely, \n"
+ "subject to the following restrictions:\n"
+ "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
+ "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+ "3. This notice may not be removed or altered from any source distribution.\n"
+ "*/\n"
+ "//Originally written by Takahiro Harada\n"
+ "typedef unsigned int u32;\n"
+ "#define GET_GROUP_IDX get_group_id(0)\n"
+ "#define GET_LOCAL_IDX get_local_id(0)\n"
+ "#define GET_GLOBAL_IDX get_global_id(0)\n"
+ "#define GET_GROUP_SIZE get_local_size(0)\n"
+ "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+ "// takahiro end\n"
+ "#define WG_SIZE 128 \n"
+ "#define m_numElems x\n"
+ "#define m_numBlocks y\n"
+ "#define m_numScanBlocks z\n"
+ "/*typedef struct\n"
+ "{\n"
+ " uint m_numElems;\n"
+ " uint m_numBlocks;\n"
+ " uint m_numScanBlocks;\n"
+ " uint m_padding[1];\n"
+ "} ConstBuffer;\n"
+ "*/\n"
+ "float4 ScanExclusiveFloat4(__local float4* data, u32 n, int lIdx, int lSize)\n"
+ "{\n"
+ " float4 blocksum;\n"
+ " int offset = 1;\n"
+ " for(int nActive=n>>1; nActive>0; nActive>>=1, offset<<=1)\n"
+ " {\n"
+ " GROUP_LDS_BARRIER;\n"
+ " for(int iIdx=lIdx; iIdx<nActive; iIdx+=lSize)\n"
+ " {\n"
+ " int ai = offset*(2*iIdx+1)-1;\n"
+ " int bi = offset*(2*iIdx+2)-1;\n"
+ " data[bi] += data[ai];\n"
+ " }\n"
+ " }\n"
+ " GROUP_LDS_BARRIER;\n"
+ " if( lIdx == 0 )\n"
+ " {\n"
+ " blocksum = data[ n-1 ];\n"
+ " data[ n-1 ] = 0;\n"
+ " }\n"
+ " GROUP_LDS_BARRIER;\n"
+ " offset >>= 1;\n"
+ " for(int nActive=1; nActive<n; nActive<<=1, offset>>=1 )\n"
+ " {\n"
+ " GROUP_LDS_BARRIER;\n"
+ " for( int iIdx = lIdx; iIdx<nActive; iIdx += lSize )\n"
+ " {\n"
+ " int ai = offset*(2*iIdx+1)-1;\n"
+ " int bi = offset*(2*iIdx+2)-1;\n"
+ " float4 temp = data[ai];\n"
+ " data[ai] = data[bi];\n"
+ " data[bi] += temp;\n"
+ " }\n"
+ " }\n"
+ " GROUP_LDS_BARRIER;\n"
+ " return blocksum;\n"
+ "}\n"
+ "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+ "__kernel\n"
+ "void LocalScanKernel(__global float4* dst, __global float4* src, __global float4* sumBuffer, uint4 cb)\n"
+ "{\n"
+ " __local float4 ldsData[WG_SIZE*2];\n"
+ " int gIdx = GET_GLOBAL_IDX;\n"
+ " int lIdx = GET_LOCAL_IDX;\n"
+ " ldsData[2*lIdx] = ( 2*gIdx < cb.m_numElems )? src[2*gIdx]: 0;\n"
+ " ldsData[2*lIdx + 1] = ( 2*gIdx+1 < cb.m_numElems )? src[2*gIdx + 1]: 0;\n"
+ " float4 sum = ScanExclusiveFloat4(ldsData, WG_SIZE*2, GET_LOCAL_IDX, GET_GROUP_SIZE);\n"
+ " if( lIdx == 0 ) \n"
+ " sumBuffer[GET_GROUP_IDX] = sum;\n"
+ " if( (2*gIdx) < cb.m_numElems )\n"
+ " {\n"
+ " dst[2*gIdx] = ldsData[2*lIdx];\n"
+ " }\n"
+ " if( (2*gIdx + 1) < cb.m_numElems )\n"
+ " {\n"
+ " dst[2*gIdx + 1] = ldsData[2*lIdx + 1];\n"
+ " }\n"
+ "}\n"
+ "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+ "__kernel\n"
+ "void AddOffsetKernel(__global float4* dst, __global float4* blockSum, uint4 cb)\n"
+ "{\n"
+ " const u32 blockSize = WG_SIZE*2;\n"
+ " int myIdx = GET_GROUP_IDX+1;\n"
+ " int lIdx = GET_LOCAL_IDX;\n"
+ " float4 iBlockSum = blockSum[myIdx];\n"
+ " int endValue = min((myIdx+1)*(blockSize), cb.m_numElems);\n"
+ " for(int i=myIdx*blockSize+lIdx; i<endValue; i+=GET_GROUP_SIZE)\n"
+ " {\n"
+ " dst[i] += iBlockSum;\n"
+ " }\n"
+ "}\n"
+ "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+ "__kernel\n"
+ "void TopLevelScanKernel(__global float4* dst, uint4 cb)\n"
+ "{\n"
+ " __local float4 ldsData[2048];\n"
+ " int gIdx = GET_GLOBAL_IDX;\n"
+ " int lIdx = GET_LOCAL_IDX;\n"
+ " int lSize = GET_GROUP_SIZE;\n"
+ " for(int i=lIdx; i<cb.m_numScanBlocks; i+=lSize )\n"
+ " {\n"
+ " ldsData[i] = (i<cb.m_numBlocks)? dst[i]:0;\n"
+ " }\n"
+ " GROUP_LDS_BARRIER;\n"
+ " float4 sum = ScanExclusiveFloat4(ldsData, cb.m_numScanBlocks, GET_LOCAL_IDX, GET_GROUP_SIZE);\n"
+ " for(int i=lIdx; i<cb.m_numBlocks; i+=lSize )\n"
+ " {\n"
+ " dst[i] = ldsData[i];\n"
+ " }\n"
+ " if( gIdx == 0 )\n"
+ " {\n"
+ " dst[cb.m_numBlocks] = sum;\n"
+ " }\n"
+ "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/RadixSort32KernelsCL.h b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/RadixSort32KernelsCL.h
index 8876c16aa6..fb4bdda303 100644
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/RadixSort32KernelsCL.h
+++ b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/RadixSort32KernelsCL.h
@@ -1,910 +1,909 @@
//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* radixSort32KernelsCL= \
-"/*\n"
-"Bullet Continuous Collision Detection and Physics Library\n"
-"Copyright (c) 2011 Advanced Micro Devices, Inc. http://bulletphysics.org\n"
-"This software is provided 'as-is', without any express or implied warranty.\n"
-"In no event will the authors be held liable for any damages arising from the use of this software.\n"
-"Permission is granted to anyone to use this software for any purpose, \n"
-"including commercial applications, and to alter it and redistribute it freely, \n"
-"subject to the following restrictions:\n"
-"1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
-"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
-"3. This notice may not be removed or altered from any source distribution.\n"
-"*/\n"
-"//Author Takahiro Harada\n"
-"//#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
-"typedef unsigned int u32;\n"
-"#define GET_GROUP_IDX get_group_id(0)\n"
-"#define GET_LOCAL_IDX get_local_id(0)\n"
-"#define GET_GLOBAL_IDX get_global_id(0)\n"
-"#define GET_GROUP_SIZE get_local_size(0)\n"
-"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
-"#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
-"#define AtomInc(x) atom_inc(&(x))\n"
-"#define AtomInc1(x, out) out = atom_inc(&(x))\n"
-"#define AtomAdd(x, value) atom_add(&(x), value)\n"
-"#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
-"#define make_uint4 (uint4)\n"
-"#define make_uint2 (uint2)\n"
-"#define make_int2 (int2)\n"
-"#define WG_SIZE 64\n"
-"#define ELEMENTS_PER_WORK_ITEM (256/WG_SIZE)\n"
-"#define BITS_PER_PASS 4\n"
-"#define NUM_BUCKET (1<<BITS_PER_PASS)\n"
-"typedef uchar u8;\n"
-"// this isn't optimization for VLIW. But just reducing writes. \n"
-"#define USE_2LEVEL_REDUCE 1\n"
-"//#define CHECK_BOUNDARY 1\n"
-"//#define NV_GPU 1\n"
-"// Cypress\n"
-"#define nPerWI 16\n"
-"// Cayman\n"
-"//#define nPerWI 20\n"
-"#define m_n x\n"
-"#define m_nWGs y\n"
-"#define m_startBit z\n"
-"#define m_nBlocksPerWG w\n"
-"/*\n"
-"typedef struct\n"
-"{\n"
-" int m_n;\n"
-" int m_nWGs;\n"
-" int m_startBit;\n"
-" int m_nBlocksPerWG;\n"
-"} ConstBuffer;\n"
-"*/\n"
-"typedef struct\n"
-"{\n"
-" unsigned int m_key;\n"
-" unsigned int m_value;\n"
-"} SortDataCL;\n"
-"uint prefixScanVectorEx( uint4* data )\n"
-"{\n"
-" u32 sum = 0;\n"
-" u32 tmp = data[0].x;\n"
-" data[0].x = sum;\n"
-" sum += tmp;\n"
-" tmp = data[0].y;\n"
-" data[0].y = sum;\n"
-" sum += tmp;\n"
-" tmp = data[0].z;\n"
-" data[0].z = sum;\n"
-" sum += tmp;\n"
-" tmp = data[0].w;\n"
-" data[0].w = sum;\n"
-" sum += tmp;\n"
-" return sum;\n"
-"}\n"
-"u32 localPrefixSum( u32 pData, uint lIdx, uint* totalSum, __local u32* sorterSharedMemory, int wgSize /*64 or 128*/ )\n"
-"{\n"
-" { // Set data\n"
-" sorterSharedMemory[lIdx] = 0;\n"
-" sorterSharedMemory[lIdx+wgSize] = pData;\n"
-" }\n"
-" GROUP_LDS_BARRIER;\n"
-" { // Prefix sum\n"
-" int idx = 2*lIdx + (wgSize+1);\n"
-"#if defined(USE_2LEVEL_REDUCE)\n"
-" if( lIdx < 64 )\n"
-" {\n"
-" u32 u0, u1, u2;\n"
-" u0 = sorterSharedMemory[idx-3];\n"
-" u1 = sorterSharedMemory[idx-2];\n"
-" u2 = sorterSharedMemory[idx-1];\n"
-" AtomAdd( sorterSharedMemory[idx], u0+u1+u2 ); \n"
-" GROUP_MEM_FENCE;\n"
-" u0 = sorterSharedMemory[idx-12];\n"
-" u1 = sorterSharedMemory[idx-8];\n"
-" u2 = sorterSharedMemory[idx-4];\n"
-" AtomAdd( sorterSharedMemory[idx], u0+u1+u2 ); \n"
-" GROUP_MEM_FENCE;\n"
-" u0 = sorterSharedMemory[idx-48];\n"
-" u1 = sorterSharedMemory[idx-32];\n"
-" u2 = sorterSharedMemory[idx-16];\n"
-" AtomAdd( sorterSharedMemory[idx], u0+u1+u2 ); \n"
-" GROUP_MEM_FENCE;\n"
-" if( wgSize > 64 )\n"
-" {\n"
-" sorterSharedMemory[idx] += sorterSharedMemory[idx-64];\n"
-" GROUP_MEM_FENCE;\n"
-" }\n"
-" sorterSharedMemory[idx-1] += sorterSharedMemory[idx-2];\n"
-" GROUP_MEM_FENCE;\n"
-" }\n"
-"#else\n"
-" if( lIdx < 64 )\n"
-" {\n"
-" sorterSharedMemory[idx] += sorterSharedMemory[idx-1];\n"
-" GROUP_MEM_FENCE;\n"
-" sorterSharedMemory[idx] += sorterSharedMemory[idx-2]; \n"
-" GROUP_MEM_FENCE;\n"
-" sorterSharedMemory[idx] += sorterSharedMemory[idx-4];\n"
-" GROUP_MEM_FENCE;\n"
-" sorterSharedMemory[idx] += sorterSharedMemory[idx-8];\n"
-" GROUP_MEM_FENCE;\n"
-" sorterSharedMemory[idx] += sorterSharedMemory[idx-16];\n"
-" GROUP_MEM_FENCE;\n"
-" sorterSharedMemory[idx] += sorterSharedMemory[idx-32];\n"
-" GROUP_MEM_FENCE;\n"
-" if( wgSize > 64 )\n"
-" {\n"
-" sorterSharedMemory[idx] += sorterSharedMemory[idx-64];\n"
-" GROUP_MEM_FENCE;\n"
-" }\n"
-" sorterSharedMemory[idx-1] += sorterSharedMemory[idx-2];\n"
-" GROUP_MEM_FENCE;\n"
-" }\n"
-"#endif\n"
-" }\n"
-" GROUP_LDS_BARRIER;\n"
-" *totalSum = sorterSharedMemory[wgSize*2-1];\n"
-" u32 addValue = sorterSharedMemory[lIdx+wgSize-1];\n"
-" return addValue;\n"
-"}\n"
-"//__attribute__((reqd_work_group_size(128,1,1)))\n"
-"uint4 localPrefixSum128V( uint4 pData, uint lIdx, uint* totalSum, __local u32* sorterSharedMemory )\n"
-"{\n"
-" u32 s4 = prefixScanVectorEx( &pData );\n"
-" u32 rank = localPrefixSum( s4, lIdx, totalSum, sorterSharedMemory, 128 );\n"
-" return pData + make_uint4( rank, rank, rank, rank );\n"
-"}\n"
-"//__attribute__((reqd_work_group_size(64,1,1)))\n"
-"uint4 localPrefixSum64V( uint4 pData, uint lIdx, uint* totalSum, __local u32* sorterSharedMemory )\n"
-"{\n"
-" u32 s4 = prefixScanVectorEx( &pData );\n"
-" u32 rank = localPrefixSum( s4, lIdx, totalSum, sorterSharedMemory, 64 );\n"
-" return pData + make_uint4( rank, rank, rank, rank );\n"
-"}\n"
-"u32 unpack4Key( u32 key, int keyIdx ){ return (key>>(keyIdx*8)) & 0xff;}\n"
-"u32 bit8Scan(u32 v)\n"
-"{\n"
-" return (v<<8) + (v<<16) + (v<<24);\n"
-"}\n"
-"//===\n"
-"#define MY_HISTOGRAM(idx) localHistogramMat[(idx)*WG_SIZE+lIdx]\n"
-"__kernel\n"
-"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
-"void StreamCountKernel( __global u32* gSrc, __global u32* histogramOut, int4 cb )\n"
-"{\n"
-" __local u32 localHistogramMat[NUM_BUCKET*WG_SIZE];\n"
-" u32 gIdx = GET_GLOBAL_IDX;\n"
-" u32 lIdx = GET_LOCAL_IDX;\n"
-" u32 wgIdx = GET_GROUP_IDX;\n"
-" u32 wgSize = GET_GROUP_SIZE;\n"
-" const int startBit = cb.m_startBit;\n"
-" const int n = cb.m_n;\n"
-" const int nWGs = cb.m_nWGs;\n"
-" const int nBlocksPerWG = cb.m_nBlocksPerWG;\n"
-" for(int i=0; i<NUM_BUCKET; i++)\n"
-" {\n"
-" MY_HISTOGRAM(i) = 0;\n"
-" }\n"
-" GROUP_LDS_BARRIER;\n"
-" const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;\n"
-" u32 localKey;\n"
-" int nBlocks = (n)/blockSize - nBlocksPerWG*wgIdx;\n"
-" int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;\n"
-" for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++, addr+=blockSize)\n"
-" {\n"
-" // MY_HISTOGRAM( localKeys.x ) ++ is much expensive than atomic add as it requires read and write while atomics can just add on AMD\n"
-" // Using registers didn't perform well. It seems like use localKeys to address requires a lot of alu ops\n"
-" // AMD: AtomInc performs better while NV prefers ++\n"
-" for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
-" {\n"
-"#if defined(CHECK_BOUNDARY)\n"
-" if( addr+i < n )\n"
-"#endif\n"
-" {\n"
-" localKey = (gSrc[addr+i]>>startBit) & 0xf;\n"
-"#if defined(NV_GPU)\n"
-" MY_HISTOGRAM( localKey )++;\n"
-"#else\n"
-" AtomInc( MY_HISTOGRAM( localKey ) );\n"
-"#endif\n"
-" }\n"
-" }\n"
-" }\n"
-" GROUP_LDS_BARRIER;\n"
-" \n"
-" if( lIdx < NUM_BUCKET )\n"
-" {\n"
-" u32 sum = 0;\n"
-" for(int i=0; i<GET_GROUP_SIZE; i++)\n"
-" {\n"
-" sum += localHistogramMat[lIdx*WG_SIZE+(i+lIdx)%GET_GROUP_SIZE];\n"
-" }\n"
-" histogramOut[lIdx*nWGs+wgIdx] = sum;\n"
-" }\n"
-"}\n"
-"__kernel\n"
-"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
-"void StreamCountSortDataKernel( __global SortDataCL* gSrc, __global u32* histogramOut, int4 cb )\n"
-"{\n"
-" __local u32 localHistogramMat[NUM_BUCKET*WG_SIZE];\n"
-" u32 gIdx = GET_GLOBAL_IDX;\n"
-" u32 lIdx = GET_LOCAL_IDX;\n"
-" u32 wgIdx = GET_GROUP_IDX;\n"
-" u32 wgSize = GET_GROUP_SIZE;\n"
-" const int startBit = cb.m_startBit;\n"
-" const int n = cb.m_n;\n"
-" const int nWGs = cb.m_nWGs;\n"
-" const int nBlocksPerWG = cb.m_nBlocksPerWG;\n"
-" for(int i=0; i<NUM_BUCKET; i++)\n"
-" {\n"
-" MY_HISTOGRAM(i) = 0;\n"
-" }\n"
-" GROUP_LDS_BARRIER;\n"
-" const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;\n"
-" u32 localKey;\n"
-" int nBlocks = (n)/blockSize - nBlocksPerWG*wgIdx;\n"
-" int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;\n"
-" for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++, addr+=blockSize)\n"
-" {\n"
-" // MY_HISTOGRAM( localKeys.x ) ++ is much expensive than atomic add as it requires read and write while atomics can just add on AMD\n"
-" // Using registers didn't perform well. It seems like use localKeys to address requires a lot of alu ops\n"
-" // AMD: AtomInc performs better while NV prefers ++\n"
-" for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
-" {\n"
-"#if defined(CHECK_BOUNDARY)\n"
-" if( addr+i < n )\n"
-"#endif\n"
-" {\n"
-" localKey = (gSrc[addr+i].m_key>>startBit) & 0xf;\n"
-"#if defined(NV_GPU)\n"
-" MY_HISTOGRAM( localKey )++;\n"
-"#else\n"
-" AtomInc( MY_HISTOGRAM( localKey ) );\n"
-"#endif\n"
-" }\n"
-" }\n"
-" }\n"
-" GROUP_LDS_BARRIER;\n"
-" \n"
-" if( lIdx < NUM_BUCKET )\n"
-" {\n"
-" u32 sum = 0;\n"
-" for(int i=0; i<GET_GROUP_SIZE; i++)\n"
-" {\n"
-" sum += localHistogramMat[lIdx*WG_SIZE+(i+lIdx)%GET_GROUP_SIZE];\n"
-" }\n"
-" histogramOut[lIdx*nWGs+wgIdx] = sum;\n"
-" }\n"
-"}\n"
-"#define nPerLane (nPerWI/4)\n"
-"// NUM_BUCKET*nWGs < 128*nPerWI\n"
-"__kernel\n"
-"__attribute__((reqd_work_group_size(128,1,1)))\n"
-"void PrefixScanKernel( __global u32* wHistogram1, int4 cb )\n"
-"{\n"
-" __local u32 ldsTopScanData[128*2];\n"
-" u32 lIdx = GET_LOCAL_IDX;\n"
-" u32 wgIdx = GET_GROUP_IDX;\n"
-" const int nWGs = cb.m_nWGs;\n"
-" u32 data[nPerWI];\n"
-" for(int i=0; i<nPerWI; i++)\n"
-" {\n"
-" data[i] = 0;\n"
-" if( (nPerWI*lIdx+i) < NUM_BUCKET*nWGs )\n"
-" data[i] = wHistogram1[nPerWI*lIdx+i];\n"
-" }\n"
-" uint4 myData = make_uint4(0,0,0,0);\n"
-" for(int i=0; i<nPerLane; i++)\n"
-" {\n"
-" myData.x += data[nPerLane*0+i];\n"
-" myData.y += data[nPerLane*1+i];\n"
-" myData.z += data[nPerLane*2+i];\n"
-" myData.w += data[nPerLane*3+i];\n"
-" }\n"
-" uint totalSum;\n"
-" uint4 scanned = localPrefixSum128V( myData, lIdx, &totalSum, ldsTopScanData );\n"
-"// for(int j=0; j<4; j++) // somehow it introduces a lot of branches\n"
-" { int j = 0;\n"
-" u32 sum = 0;\n"
-" for(int i=0; i<nPerLane; i++)\n"
-" {\n"
-" u32 tmp = data[nPerLane*j+i];\n"
-" data[nPerLane*j+i] = sum;\n"
-" sum += tmp;\n"
-" }\n"
-" }\n"
-" { int j = 1;\n"
-" u32 sum = 0;\n"
-" for(int i=0; i<nPerLane; i++)\n"
-" {\n"
-" u32 tmp = data[nPerLane*j+i];\n"
-" data[nPerLane*j+i] = sum;\n"
-" sum += tmp;\n"
-" }\n"
-" }\n"
-" { int j = 2;\n"
-" u32 sum = 0;\n"
-" for(int i=0; i<nPerLane; i++)\n"
-" {\n"
-" u32 tmp = data[nPerLane*j+i];\n"
-" data[nPerLane*j+i] = sum;\n"
-" sum += tmp;\n"
-" }\n"
-" }\n"
-" { int j = 3;\n"
-" u32 sum = 0;\n"
-" for(int i=0; i<nPerLane; i++)\n"
-" {\n"
-" u32 tmp = data[nPerLane*j+i];\n"
-" data[nPerLane*j+i] = sum;\n"
-" sum += tmp;\n"
-" }\n"
-" }\n"
-" for(int i=0; i<nPerLane; i++)\n"
-" {\n"
-" data[nPerLane*0+i] += scanned.x;\n"
-" data[nPerLane*1+i] += scanned.y;\n"
-" data[nPerLane*2+i] += scanned.z;\n"
-" data[nPerLane*3+i] += scanned.w;\n"
-" }\n"
-" for(int i=0; i<nPerWI; i++)\n"
-" {\n"
-" int index = nPerWI*lIdx+i;\n"
-" if (index < NUM_BUCKET*nWGs)\n"
-" wHistogram1[nPerWI*lIdx+i] = data[i];\n"
-" }\n"
-"}\n"
-"// 4 scan, 4 exchange\n"
-"void sort4Bits(u32 sortData[4], int startBit, int lIdx, __local u32* ldsSortData)\n"
-"{\n"
-" for(int bitIdx=0; bitIdx<BITS_PER_PASS; bitIdx++)\n"
-" {\n"
-" u32 mask = (1<<bitIdx);\n"
-" uint4 cmpResult = make_uint4( (sortData[0]>>startBit) & mask, (sortData[1]>>startBit) & mask, (sortData[2]>>startBit) & mask, (sortData[3]>>startBit) & mask );\n"
-" uint4 prefixSum = SELECT_UINT4( make_uint4(1,1,1,1), make_uint4(0,0,0,0), cmpResult != make_uint4(0,0,0,0) );\n"
-" u32 total;\n"
-" prefixSum = localPrefixSum64V( prefixSum, lIdx, &total, ldsSortData );\n"
-" {\n"
-" uint4 localAddr = make_uint4(lIdx*4+0,lIdx*4+1,lIdx*4+2,lIdx*4+3);\n"
-" uint4 dstAddr = localAddr - prefixSum + make_uint4( total, total, total, total );\n"
-" dstAddr = SELECT_UINT4( prefixSum, dstAddr, cmpResult != make_uint4(0, 0, 0, 0) );\n"
-" GROUP_LDS_BARRIER;\n"
-" ldsSortData[dstAddr.x] = sortData[0];\n"
-" ldsSortData[dstAddr.y] = sortData[1];\n"
-" ldsSortData[dstAddr.z] = sortData[2];\n"
-" ldsSortData[dstAddr.w] = sortData[3];\n"
-" GROUP_LDS_BARRIER;\n"
-" sortData[0] = ldsSortData[localAddr.x];\n"
-" sortData[1] = ldsSortData[localAddr.y];\n"
-" sortData[2] = ldsSortData[localAddr.z];\n"
-" sortData[3] = ldsSortData[localAddr.w];\n"
-" GROUP_LDS_BARRIER;\n"
-" }\n"
-" }\n"
-"}\n"
-"// 2 scan, 2 exchange\n"
-"void sort4Bits1(u32 sortData[4], int startBit, int lIdx, __local u32* ldsSortData)\n"
-"{\n"
-" for(uint ibit=0; ibit<BITS_PER_PASS; ibit+=2)\n"
-" {\n"
-" uint4 b = make_uint4((sortData[0]>>(startBit+ibit)) & 0x3, \n"
-" (sortData[1]>>(startBit+ibit)) & 0x3, \n"
-" (sortData[2]>>(startBit+ibit)) & 0x3, \n"
-" (sortData[3]>>(startBit+ibit)) & 0x3);\n"
-" u32 key4;\n"
-" u32 sKeyPacked[4] = { 0, 0, 0, 0 };\n"
-" {\n"
-" sKeyPacked[0] |= 1<<(8*b.x);\n"
-" sKeyPacked[1] |= 1<<(8*b.y);\n"
-" sKeyPacked[2] |= 1<<(8*b.z);\n"
-" sKeyPacked[3] |= 1<<(8*b.w);\n"
-" key4 = sKeyPacked[0] + sKeyPacked[1] + sKeyPacked[2] + sKeyPacked[3];\n"
-" }\n"
-" u32 rankPacked;\n"
-" u32 sumPacked;\n"
-" {\n"
-" rankPacked = localPrefixSum( key4, lIdx, &sumPacked, ldsSortData, WG_SIZE );\n"
-" }\n"
-" GROUP_LDS_BARRIER;\n"
-" u32 newOffset[4] = { 0,0,0,0 };\n"
-" {\n"
-" u32 sumScanned = bit8Scan( sumPacked );\n"
-" u32 scannedKeys[4];\n"
-" scannedKeys[0] = 1<<(8*b.x);\n"
-" scannedKeys[1] = 1<<(8*b.y);\n"
-" scannedKeys[2] = 1<<(8*b.z);\n"
-" scannedKeys[3] = 1<<(8*b.w);\n"
-" { // 4 scans at once\n"
-" u32 sum4 = 0;\n"
-" for(int ie=0; ie<4; ie++)\n"
-" {\n"
-" u32 tmp = scannedKeys[ie];\n"
-" scannedKeys[ie] = sum4;\n"
-" sum4 += tmp;\n"
-" }\n"
-" }\n"
-" {\n"
-" u32 sumPlusRank = sumScanned + rankPacked;\n"
-" { u32 ie = b.x;\n"
-" scannedKeys[0] += sumPlusRank;\n"
-" newOffset[0] = unpack4Key( scannedKeys[0], ie );\n"
-" }\n"
-" { u32 ie = b.y;\n"
-" scannedKeys[1] += sumPlusRank;\n"
-" newOffset[1] = unpack4Key( scannedKeys[1], ie );\n"
-" }\n"
-" { u32 ie = b.z;\n"
-" scannedKeys[2] += sumPlusRank;\n"
-" newOffset[2] = unpack4Key( scannedKeys[2], ie );\n"
-" }\n"
-" { u32 ie = b.w;\n"
-" scannedKeys[3] += sumPlusRank;\n"
-" newOffset[3] = unpack4Key( scannedKeys[3], ie );\n"
-" }\n"
-" }\n"
-" }\n"
-" GROUP_LDS_BARRIER;\n"
-" {\n"
-" ldsSortData[newOffset[0]] = sortData[0];\n"
-" ldsSortData[newOffset[1]] = sortData[1];\n"
-" ldsSortData[newOffset[2]] = sortData[2];\n"
-" ldsSortData[newOffset[3]] = sortData[3];\n"
-" GROUP_LDS_BARRIER;\n"
-" u32 dstAddr = 4*lIdx;\n"
-" sortData[0] = ldsSortData[dstAddr+0];\n"
-" sortData[1] = ldsSortData[dstAddr+1];\n"
-" sortData[2] = ldsSortData[dstAddr+2];\n"
-" sortData[3] = ldsSortData[dstAddr+3];\n"
-" GROUP_LDS_BARRIER;\n"
-" }\n"
-" }\n"
-"}\n"
-"#define SET_HISTOGRAM(setIdx, key) ldsSortData[(setIdx)*NUM_BUCKET+key]\n"
-"__kernel\n"
-"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
-"void SortAndScatterKernel( __global const u32* restrict gSrc, __global const u32* rHistogram, __global u32* restrict gDst, int4 cb )\n"
-"{\n"
-" __local u32 ldsSortData[WG_SIZE*ELEMENTS_PER_WORK_ITEM+16];\n"
-" __local u32 localHistogramToCarry[NUM_BUCKET];\n"
-" __local u32 localHistogram[NUM_BUCKET*2];\n"
-" u32 gIdx = GET_GLOBAL_IDX;\n"
-" u32 lIdx = GET_LOCAL_IDX;\n"
-" u32 wgIdx = GET_GROUP_IDX;\n"
-" u32 wgSize = GET_GROUP_SIZE;\n"
-" const int n = cb.m_n;\n"
-" const int nWGs = cb.m_nWGs;\n"
-" const int startBit = cb.m_startBit;\n"
-" const int nBlocksPerWG = cb.m_nBlocksPerWG;\n"
-" if( lIdx < (NUM_BUCKET) )\n"
-" {\n"
-" localHistogramToCarry[lIdx] = rHistogram[lIdx*nWGs + wgIdx];\n"
-" }\n"
-" GROUP_LDS_BARRIER;\n"
-" const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;\n"
-" int nBlocks = n/blockSize - nBlocksPerWG*wgIdx;\n"
-" int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;\n"
-" for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++, addr+=blockSize)\n"
-" {\n"
-" u32 myHistogram = 0;\n"
-" u32 sortData[ELEMENTS_PER_WORK_ITEM];\n"
-" for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
-"#if defined(CHECK_BOUNDARY)\n"
-" sortData[i] = ( addr+i < n )? gSrc[ addr+i ] : 0xffffffff;\n"
-"#else\n"
-" sortData[i] = gSrc[ addr+i ];\n"
-"#endif\n"
-" sort4Bits(sortData, startBit, lIdx, ldsSortData);\n"
-" u32 keys[ELEMENTS_PER_WORK_ITEM];\n"
-" for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
-" keys[i] = (sortData[i]>>startBit) & 0xf;\n"
-" { // create histogram\n"
-" u32 setIdx = lIdx/16;\n"
-" if( lIdx < NUM_BUCKET )\n"
-" {\n"
-" localHistogram[lIdx] = 0;\n"
-" }\n"
-" ldsSortData[lIdx] = 0;\n"
-" GROUP_LDS_BARRIER;\n"
-" for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
-"#if defined(CHECK_BOUNDARY)\n"
-" if( addr+i < n )\n"
-"#endif\n"
-"#if defined(NV_GPU)\n"
-" SET_HISTOGRAM( setIdx, keys[i] )++;\n"
-"#else\n"
-" AtomInc( SET_HISTOGRAM( setIdx, keys[i] ) );\n"
-"#endif\n"
-" \n"
-" GROUP_LDS_BARRIER;\n"
-" \n"
-" uint hIdx = NUM_BUCKET+lIdx;\n"
-" if( lIdx < NUM_BUCKET )\n"
-" {\n"
-" u32 sum = 0;\n"
-" for(int i=0; i<WG_SIZE/16; i++)\n"
-" {\n"
-" sum += SET_HISTOGRAM( i, lIdx );\n"
-" }\n"
-" myHistogram = sum;\n"
-" localHistogram[hIdx] = sum;\n"
-" }\n"
-" GROUP_LDS_BARRIER;\n"
-"#if defined(USE_2LEVEL_REDUCE)\n"
-" if( lIdx < NUM_BUCKET )\n"
-" {\n"
-" localHistogram[hIdx] = localHistogram[hIdx-1];\n"
-" GROUP_MEM_FENCE;\n"
-" u32 u0, u1, u2;\n"
-" u0 = localHistogram[hIdx-3];\n"
-" u1 = localHistogram[hIdx-2];\n"
-" u2 = localHistogram[hIdx-1];\n"
-" AtomAdd( localHistogram[hIdx], u0 + u1 + u2 );\n"
-" GROUP_MEM_FENCE;\n"
-" u0 = localHistogram[hIdx-12];\n"
-" u1 = localHistogram[hIdx-8];\n"
-" u2 = localHistogram[hIdx-4];\n"
-" AtomAdd( localHistogram[hIdx], u0 + u1 + u2 );\n"
-" GROUP_MEM_FENCE;\n"
-" }\n"
-"#else\n"
-" if( lIdx < NUM_BUCKET )\n"
-" {\n"
-" localHistogram[hIdx] = localHistogram[hIdx-1];\n"
-" GROUP_MEM_FENCE;\n"
-" localHistogram[hIdx] += localHistogram[hIdx-1];\n"
-" GROUP_MEM_FENCE;\n"
-" localHistogram[hIdx] += localHistogram[hIdx-2];\n"
-" GROUP_MEM_FENCE;\n"
-" localHistogram[hIdx] += localHistogram[hIdx-4];\n"
-" GROUP_MEM_FENCE;\n"
-" localHistogram[hIdx] += localHistogram[hIdx-8];\n"
-" GROUP_MEM_FENCE;\n"
-" }\n"
-"#endif\n"
-" GROUP_LDS_BARRIER;\n"
-" }\n"
-" {\n"
-" for(int ie=0; ie<ELEMENTS_PER_WORK_ITEM; ie++)\n"
-" {\n"
-" int dataIdx = ELEMENTS_PER_WORK_ITEM*lIdx+ie;\n"
-" int binIdx = keys[ie];\n"
-" int groupOffset = localHistogramToCarry[binIdx];\n"
-" int myIdx = dataIdx - localHistogram[NUM_BUCKET+binIdx];\n"
-"#if defined(CHECK_BOUNDARY)\n"
-" if( addr+ie < n )\n"
-"#endif\n"
-" gDst[ groupOffset + myIdx ] = sortData[ie];\n"
-" }\n"
-" }\n"
-" GROUP_LDS_BARRIER;\n"
-" if( lIdx < NUM_BUCKET )\n"
-" {\n"
-" localHistogramToCarry[lIdx] += myHistogram;\n"
-" }\n"
-" GROUP_LDS_BARRIER;\n"
-" }\n"
-"}\n"
-"// 2 scan, 2 exchange\n"
-"void sort4Bits1KeyValue(u32 sortData[4], int sortVal[4], int startBit, int lIdx, __local u32* ldsSortData, __local int *ldsSortVal)\n"
-"{\n"
-" for(uint ibit=0; ibit<BITS_PER_PASS; ibit+=2)\n"
-" {\n"
-" uint4 b = make_uint4((sortData[0]>>(startBit+ibit)) & 0x3, \n"
-" (sortData[1]>>(startBit+ibit)) & 0x3, \n"
-" (sortData[2]>>(startBit+ibit)) & 0x3, \n"
-" (sortData[3]>>(startBit+ibit)) & 0x3);\n"
-" u32 key4;\n"
-" u32 sKeyPacked[4] = { 0, 0, 0, 0 };\n"
-" {\n"
-" sKeyPacked[0] |= 1<<(8*b.x);\n"
-" sKeyPacked[1] |= 1<<(8*b.y);\n"
-" sKeyPacked[2] |= 1<<(8*b.z);\n"
-" sKeyPacked[3] |= 1<<(8*b.w);\n"
-" key4 = sKeyPacked[0] + sKeyPacked[1] + sKeyPacked[2] + sKeyPacked[3];\n"
-" }\n"
-" u32 rankPacked;\n"
-" u32 sumPacked;\n"
-" {\n"
-" rankPacked = localPrefixSum( key4, lIdx, &sumPacked, ldsSortData, WG_SIZE );\n"
-" }\n"
-" GROUP_LDS_BARRIER;\n"
-" u32 newOffset[4] = { 0,0,0,0 };\n"
-" {\n"
-" u32 sumScanned = bit8Scan( sumPacked );\n"
-" u32 scannedKeys[4];\n"
-" scannedKeys[0] = 1<<(8*b.x);\n"
-" scannedKeys[1] = 1<<(8*b.y);\n"
-" scannedKeys[2] = 1<<(8*b.z);\n"
-" scannedKeys[3] = 1<<(8*b.w);\n"
-" { // 4 scans at once\n"
-" u32 sum4 = 0;\n"
-" for(int ie=0; ie<4; ie++)\n"
-" {\n"
-" u32 tmp = scannedKeys[ie];\n"
-" scannedKeys[ie] = sum4;\n"
-" sum4 += tmp;\n"
-" }\n"
-" }\n"
-" {\n"
-" u32 sumPlusRank = sumScanned + rankPacked;\n"
-" { u32 ie = b.x;\n"
-" scannedKeys[0] += sumPlusRank;\n"
-" newOffset[0] = unpack4Key( scannedKeys[0], ie );\n"
-" }\n"
-" { u32 ie = b.y;\n"
-" scannedKeys[1] += sumPlusRank;\n"
-" newOffset[1] = unpack4Key( scannedKeys[1], ie );\n"
-" }\n"
-" { u32 ie = b.z;\n"
-" scannedKeys[2] += sumPlusRank;\n"
-" newOffset[2] = unpack4Key( scannedKeys[2], ie );\n"
-" }\n"
-" { u32 ie = b.w;\n"
-" scannedKeys[3] += sumPlusRank;\n"
-" newOffset[3] = unpack4Key( scannedKeys[3], ie );\n"
-" }\n"
-" }\n"
-" }\n"
-" GROUP_LDS_BARRIER;\n"
-" {\n"
-" ldsSortData[newOffset[0]] = sortData[0];\n"
-" ldsSortData[newOffset[1]] = sortData[1];\n"
-" ldsSortData[newOffset[2]] = sortData[2];\n"
-" ldsSortData[newOffset[3]] = sortData[3];\n"
-" ldsSortVal[newOffset[0]] = sortVal[0];\n"
-" ldsSortVal[newOffset[1]] = sortVal[1];\n"
-" ldsSortVal[newOffset[2]] = sortVal[2];\n"
-" ldsSortVal[newOffset[3]] = sortVal[3];\n"
-" GROUP_LDS_BARRIER;\n"
-" u32 dstAddr = 4*lIdx;\n"
-" sortData[0] = ldsSortData[dstAddr+0];\n"
-" sortData[1] = ldsSortData[dstAddr+1];\n"
-" sortData[2] = ldsSortData[dstAddr+2];\n"
-" sortData[3] = ldsSortData[dstAddr+3];\n"
-" sortVal[0] = ldsSortVal[dstAddr+0];\n"
-" sortVal[1] = ldsSortVal[dstAddr+1];\n"
-" sortVal[2] = ldsSortVal[dstAddr+2];\n"
-" sortVal[3] = ldsSortVal[dstAddr+3];\n"
-" GROUP_LDS_BARRIER;\n"
-" }\n"
-" }\n"
-"}\n"
-"__kernel\n"
-"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
-"void SortAndScatterSortDataKernel( __global const SortDataCL* restrict gSrc, __global const u32* rHistogram, __global SortDataCL* restrict gDst, int4 cb)\n"
-"{\n"
-" __local int ldsSortData[WG_SIZE*ELEMENTS_PER_WORK_ITEM+16];\n"
-" __local int ldsSortVal[WG_SIZE*ELEMENTS_PER_WORK_ITEM+16];\n"
-" __local u32 localHistogramToCarry[NUM_BUCKET];\n"
-" __local u32 localHistogram[NUM_BUCKET*2];\n"
-" u32 gIdx = GET_GLOBAL_IDX;\n"
-" u32 lIdx = GET_LOCAL_IDX;\n"
-" u32 wgIdx = GET_GROUP_IDX;\n"
-" u32 wgSize = GET_GROUP_SIZE;\n"
-" const int n = cb.m_n;\n"
-" const int nWGs = cb.m_nWGs;\n"
-" const int startBit = cb.m_startBit;\n"
-" const int nBlocksPerWG = cb.m_nBlocksPerWG;\n"
-" if( lIdx < (NUM_BUCKET) )\n"
-" {\n"
-" localHistogramToCarry[lIdx] = rHistogram[lIdx*nWGs + wgIdx];\n"
-" }\n"
-" GROUP_LDS_BARRIER;\n"
-" \n"
-" const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;\n"
-" int nBlocks = n/blockSize - nBlocksPerWG*wgIdx;\n"
-" int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;\n"
-" for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++, addr+=blockSize)\n"
-" {\n"
-" u32 myHistogram = 0;\n"
-" int sortData[ELEMENTS_PER_WORK_ITEM];\n"
-" int sortVal[ELEMENTS_PER_WORK_ITEM];\n"
-" for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
-"#if defined(CHECK_BOUNDARY)\n"
-" {\n"
-" sortData[i] = ( addr+i < n )? gSrc[ addr+i ].m_key : 0xffffffff;\n"
-" sortVal[i] = ( addr+i < n )? gSrc[ addr+i ].m_value : 0xffffffff;\n"
-" }\n"
-"#else\n"
-" {\n"
-" sortData[i] = gSrc[ addr+i ].m_key;\n"
-" sortVal[i] = gSrc[ addr+i ].m_value;\n"
-" }\n"
-"#endif\n"
-" sort4Bits1KeyValue(sortData, sortVal, startBit, lIdx, ldsSortData, ldsSortVal);\n"
-" u32 keys[ELEMENTS_PER_WORK_ITEM];\n"
-" for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
-" keys[i] = (sortData[i]>>startBit) & 0xf;\n"
-" { // create histogram\n"
-" u32 setIdx = lIdx/16;\n"
-" if( lIdx < NUM_BUCKET )\n"
-" {\n"
-" localHistogram[lIdx] = 0;\n"
-" }\n"
-" ldsSortData[lIdx] = 0;\n"
-" GROUP_LDS_BARRIER;\n"
-" for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
-"#if defined(CHECK_BOUNDARY)\n"
-" if( addr+i < n )\n"
-"#endif\n"
-"#if defined(NV_GPU)\n"
-" SET_HISTOGRAM( setIdx, keys[i] )++;\n"
-"#else\n"
-" AtomInc( SET_HISTOGRAM( setIdx, keys[i] ) );\n"
-"#endif\n"
-" \n"
-" GROUP_LDS_BARRIER;\n"
-" \n"
-" uint hIdx = NUM_BUCKET+lIdx;\n"
-" if( lIdx < NUM_BUCKET )\n"
-" {\n"
-" u32 sum = 0;\n"
-" for(int i=0; i<WG_SIZE/16; i++)\n"
-" {\n"
-" sum += SET_HISTOGRAM( i, lIdx );\n"
-" }\n"
-" myHistogram = sum;\n"
-" localHistogram[hIdx] = sum;\n"
-" }\n"
-" GROUP_LDS_BARRIER;\n"
-"#if defined(USE_2LEVEL_REDUCE)\n"
-" if( lIdx < NUM_BUCKET )\n"
-" {\n"
-" localHistogram[hIdx] = localHistogram[hIdx-1];\n"
-" GROUP_MEM_FENCE;\n"
-" u32 u0, u1, u2;\n"
-" u0 = localHistogram[hIdx-3];\n"
-" u1 = localHistogram[hIdx-2];\n"
-" u2 = localHistogram[hIdx-1];\n"
-" AtomAdd( localHistogram[hIdx], u0 + u1 + u2 );\n"
-" GROUP_MEM_FENCE;\n"
-" u0 = localHistogram[hIdx-12];\n"
-" u1 = localHistogram[hIdx-8];\n"
-" u2 = localHistogram[hIdx-4];\n"
-" AtomAdd( localHistogram[hIdx], u0 + u1 + u2 );\n"
-" GROUP_MEM_FENCE;\n"
-" }\n"
-"#else\n"
-" if( lIdx < NUM_BUCKET )\n"
-" {\n"
-" localHistogram[hIdx] = localHistogram[hIdx-1];\n"
-" GROUP_MEM_FENCE;\n"
-" localHistogram[hIdx] += localHistogram[hIdx-1];\n"
-" GROUP_MEM_FENCE;\n"
-" localHistogram[hIdx] += localHistogram[hIdx-2];\n"
-" GROUP_MEM_FENCE;\n"
-" localHistogram[hIdx] += localHistogram[hIdx-4];\n"
-" GROUP_MEM_FENCE;\n"
-" localHistogram[hIdx] += localHistogram[hIdx-8];\n"
-" GROUP_MEM_FENCE;\n"
-" }\n"
-"#endif\n"
-" GROUP_LDS_BARRIER;\n"
-" }\n"
-" {\n"
-" for(int ie=0; ie<ELEMENTS_PER_WORK_ITEM; ie++)\n"
-" {\n"
-" int dataIdx = ELEMENTS_PER_WORK_ITEM*lIdx+ie;\n"
-" int binIdx = keys[ie];\n"
-" int groupOffset = localHistogramToCarry[binIdx];\n"
-" int myIdx = dataIdx - localHistogram[NUM_BUCKET+binIdx];\n"
-"#if defined(CHECK_BOUNDARY)\n"
-" if( addr+ie < n )\n"
-" {\n"
-" if ((groupOffset + myIdx)<n)\n"
-" {\n"
-" if (sortData[ie]==sortVal[ie])\n"
-" {\n"
-" \n"
-" SortDataCL tmp;\n"
-" tmp.m_key = sortData[ie];\n"
-" tmp.m_value = sortVal[ie];\n"
-" if (tmp.m_key == tmp.m_value)\n"
-" gDst[groupOffset + myIdx ] = tmp;\n"
-" }\n"
-" \n"
-" }\n"
-" }\n"
-"#else\n"
-" if ((groupOffset + myIdx)<n)\n"
-" {\n"
-" gDst[ groupOffset + myIdx ].m_key = sortData[ie];\n"
-" gDst[ groupOffset + myIdx ].m_value = sortVal[ie];\n"
-" }\n"
-"#endif\n"
-" }\n"
-" }\n"
-" GROUP_LDS_BARRIER;\n"
-" if( lIdx < NUM_BUCKET )\n"
-" {\n"
-" localHistogramToCarry[lIdx] += myHistogram;\n"
-" }\n"
-" GROUP_LDS_BARRIER;\n"
-" }\n"
-"}\n"
-"__kernel\n"
-"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
-"void SortAndScatterSortDataKernelSerial( __global const SortDataCL* restrict gSrc, __global const u32* rHistogram, __global SortDataCL* restrict gDst, int4 cb)\n"
-"{\n"
-" \n"
-" u32 gIdx = GET_GLOBAL_IDX;\n"
-" u32 realLocalIdx = GET_LOCAL_IDX;\n"
-" u32 wgIdx = GET_GROUP_IDX;\n"
-" u32 wgSize = GET_GROUP_SIZE;\n"
-" const int startBit = cb.m_startBit;\n"
-" const int n = cb.m_n;\n"
-" const int nWGs = cb.m_nWGs;\n"
-" const int nBlocksPerWG = cb.m_nBlocksPerWG;\n"
-" int counter[NUM_BUCKET];\n"
-" \n"
-" if (realLocalIdx>0)\n"
-" return;\n"
-" \n"
-" for (int c=0;c<NUM_BUCKET;c++)\n"
-" counter[c]=0;\n"
-" const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;\n"
-" \n"
-" int nBlocks = (n)/blockSize - nBlocksPerWG*wgIdx;\n"
-" for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++)\n"
-" {\n"
-" for (int lIdx=0;lIdx<WG_SIZE;lIdx++)\n"
-" {\n"
-" int addr2 = iblock*blockSize + blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;\n"
-" \n"
-" for(int j=0; j<ELEMENTS_PER_WORK_ITEM; j++)\n"
-" {\n"
-" int i = addr2+j;\n"
-" if( i < n )\n"
-" {\n"
-" int tableIdx;\n"
-" tableIdx = (gSrc[i].m_key>>startBit) & 0xf;//0xf = NUM_TABLES-1\n"
-" gDst[rHistogram[tableIdx*nWGs+wgIdx] + counter[tableIdx]] = gSrc[i];\n"
-" counter[tableIdx] ++;\n"
-" }\n"
-" }\n"
-" }\n"
-" }\n"
-" \n"
-"}\n"
-"__kernel\n"
-"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
-"void SortAndScatterKernelSerial( __global const u32* restrict gSrc, __global const u32* rHistogram, __global u32* restrict gDst, int4 cb )\n"
-"{\n"
-" \n"
-" u32 gIdx = GET_GLOBAL_IDX;\n"
-" u32 realLocalIdx = GET_LOCAL_IDX;\n"
-" u32 wgIdx = GET_GROUP_IDX;\n"
-" u32 wgSize = GET_GROUP_SIZE;\n"
-" const int startBit = cb.m_startBit;\n"
-" const int n = cb.m_n;\n"
-" const int nWGs = cb.m_nWGs;\n"
-" const int nBlocksPerWG = cb.m_nBlocksPerWG;\n"
-" int counter[NUM_BUCKET];\n"
-" \n"
-" if (realLocalIdx>0)\n"
-" return;\n"
-" \n"
-" for (int c=0;c<NUM_BUCKET;c++)\n"
-" counter[c]=0;\n"
-" const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;\n"
-" \n"
-" int nBlocks = (n)/blockSize - nBlocksPerWG*wgIdx;\n"
-" for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++)\n"
-" {\n"
-" for (int lIdx=0;lIdx<WG_SIZE;lIdx++)\n"
-" {\n"
-" int addr2 = iblock*blockSize + blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;\n"
-" \n"
-" for(int j=0; j<ELEMENTS_PER_WORK_ITEM; j++)\n"
-" {\n"
-" int i = addr2+j;\n"
-" if( i < n )\n"
-" {\n"
-" int tableIdx;\n"
-" tableIdx = (gSrc[i]>>startBit) & 0xf;//0xf = NUM_TABLES-1\n"
-" gDst[rHistogram[tableIdx*nWGs+wgIdx] + counter[tableIdx]] = gSrc[i];\n"
-" counter[tableIdx] ++;\n"
-" }\n"
-" }\n"
-" }\n"
-" }\n"
-" \n"
-"}\n"
-;
+static const char* radixSort32KernelsCL =
+ "/*\n"
+ "Bullet Continuous Collision Detection and Physics Library\n"
+ "Copyright (c) 2011 Advanced Micro Devices, Inc. http://bulletphysics.org\n"
+ "This software is provided 'as-is', without any express or implied warranty.\n"
+ "In no event will the authors be held liable for any damages arising from the use of this software.\n"
+ "Permission is granted to anyone to use this software for any purpose, \n"
+ "including commercial applications, and to alter it and redistribute it freely, \n"
+ "subject to the following restrictions:\n"
+ "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
+ "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+ "3. This notice may not be removed or altered from any source distribution.\n"
+ "*/\n"
+ "//Author Takahiro Harada\n"
+ "//#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
+ "typedef unsigned int u32;\n"
+ "#define GET_GROUP_IDX get_group_id(0)\n"
+ "#define GET_LOCAL_IDX get_local_id(0)\n"
+ "#define GET_GLOBAL_IDX get_global_id(0)\n"
+ "#define GET_GROUP_SIZE get_local_size(0)\n"
+ "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+ "#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
+ "#define AtomInc(x) atom_inc(&(x))\n"
+ "#define AtomInc1(x, out) out = atom_inc(&(x))\n"
+ "#define AtomAdd(x, value) atom_add(&(x), value)\n"
+ "#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
+ "#define make_uint4 (uint4)\n"
+ "#define make_uint2 (uint2)\n"
+ "#define make_int2 (int2)\n"
+ "#define WG_SIZE 64\n"
+ "#define ELEMENTS_PER_WORK_ITEM (256/WG_SIZE)\n"
+ "#define BITS_PER_PASS 4\n"
+ "#define NUM_BUCKET (1<<BITS_PER_PASS)\n"
+ "typedef uchar u8;\n"
+ "// this isn't optimization for VLIW. But just reducing writes. \n"
+ "#define USE_2LEVEL_REDUCE 1\n"
+ "//#define CHECK_BOUNDARY 1\n"
+ "//#define NV_GPU 1\n"
+ "// Cypress\n"
+ "#define nPerWI 16\n"
+ "// Cayman\n"
+ "//#define nPerWI 20\n"
+ "#define m_n x\n"
+ "#define m_nWGs y\n"
+ "#define m_startBit z\n"
+ "#define m_nBlocksPerWG w\n"
+ "/*\n"
+ "typedef struct\n"
+ "{\n"
+ " int m_n;\n"
+ " int m_nWGs;\n"
+ " int m_startBit;\n"
+ " int m_nBlocksPerWG;\n"
+ "} ConstBuffer;\n"
+ "*/\n"
+ "typedef struct\n"
+ "{\n"
+ " unsigned int m_key;\n"
+ " unsigned int m_value;\n"
+ "} SortDataCL;\n"
+ "uint prefixScanVectorEx( uint4* data )\n"
+ "{\n"
+ " u32 sum = 0;\n"
+ " u32 tmp = data[0].x;\n"
+ " data[0].x = sum;\n"
+ " sum += tmp;\n"
+ " tmp = data[0].y;\n"
+ " data[0].y = sum;\n"
+ " sum += tmp;\n"
+ " tmp = data[0].z;\n"
+ " data[0].z = sum;\n"
+ " sum += tmp;\n"
+ " tmp = data[0].w;\n"
+ " data[0].w = sum;\n"
+ " sum += tmp;\n"
+ " return sum;\n"
+ "}\n"
+ "u32 localPrefixSum( u32 pData, uint lIdx, uint* totalSum, __local u32* sorterSharedMemory, int wgSize /*64 or 128*/ )\n"
+ "{\n"
+ " { // Set data\n"
+ " sorterSharedMemory[lIdx] = 0;\n"
+ " sorterSharedMemory[lIdx+wgSize] = pData;\n"
+ " }\n"
+ " GROUP_LDS_BARRIER;\n"
+ " { // Prefix sum\n"
+ " int idx = 2*lIdx + (wgSize+1);\n"
+ "#if defined(USE_2LEVEL_REDUCE)\n"
+ " if( lIdx < 64 )\n"
+ " {\n"
+ " u32 u0, u1, u2;\n"
+ " u0 = sorterSharedMemory[idx-3];\n"
+ " u1 = sorterSharedMemory[idx-2];\n"
+ " u2 = sorterSharedMemory[idx-1];\n"
+ " AtomAdd( sorterSharedMemory[idx], u0+u1+u2 ); \n"
+ " GROUP_MEM_FENCE;\n"
+ " u0 = sorterSharedMemory[idx-12];\n"
+ " u1 = sorterSharedMemory[idx-8];\n"
+ " u2 = sorterSharedMemory[idx-4];\n"
+ " AtomAdd( sorterSharedMemory[idx], u0+u1+u2 ); \n"
+ " GROUP_MEM_FENCE;\n"
+ " u0 = sorterSharedMemory[idx-48];\n"
+ " u1 = sorterSharedMemory[idx-32];\n"
+ " u2 = sorterSharedMemory[idx-16];\n"
+ " AtomAdd( sorterSharedMemory[idx], u0+u1+u2 ); \n"
+ " GROUP_MEM_FENCE;\n"
+ " if( wgSize > 64 )\n"
+ " {\n"
+ " sorterSharedMemory[idx] += sorterSharedMemory[idx-64];\n"
+ " GROUP_MEM_FENCE;\n"
+ " }\n"
+ " sorterSharedMemory[idx-1] += sorterSharedMemory[idx-2];\n"
+ " GROUP_MEM_FENCE;\n"
+ " }\n"
+ "#else\n"
+ " if( lIdx < 64 )\n"
+ " {\n"
+ " sorterSharedMemory[idx] += sorterSharedMemory[idx-1];\n"
+ " GROUP_MEM_FENCE;\n"
+ " sorterSharedMemory[idx] += sorterSharedMemory[idx-2]; \n"
+ " GROUP_MEM_FENCE;\n"
+ " sorterSharedMemory[idx] += sorterSharedMemory[idx-4];\n"
+ " GROUP_MEM_FENCE;\n"
+ " sorterSharedMemory[idx] += sorterSharedMemory[idx-8];\n"
+ " GROUP_MEM_FENCE;\n"
+ " sorterSharedMemory[idx] += sorterSharedMemory[idx-16];\n"
+ " GROUP_MEM_FENCE;\n"
+ " sorterSharedMemory[idx] += sorterSharedMemory[idx-32];\n"
+ " GROUP_MEM_FENCE;\n"
+ " if( wgSize > 64 )\n"
+ " {\n"
+ " sorterSharedMemory[idx] += sorterSharedMemory[idx-64];\n"
+ " GROUP_MEM_FENCE;\n"
+ " }\n"
+ " sorterSharedMemory[idx-1] += sorterSharedMemory[idx-2];\n"
+ " GROUP_MEM_FENCE;\n"
+ " }\n"
+ "#endif\n"
+ " }\n"
+ " GROUP_LDS_BARRIER;\n"
+ " *totalSum = sorterSharedMemory[wgSize*2-1];\n"
+ " u32 addValue = sorterSharedMemory[lIdx+wgSize-1];\n"
+ " return addValue;\n"
+ "}\n"
+ "//__attribute__((reqd_work_group_size(128,1,1)))\n"
+ "uint4 localPrefixSum128V( uint4 pData, uint lIdx, uint* totalSum, __local u32* sorterSharedMemory )\n"
+ "{\n"
+ " u32 s4 = prefixScanVectorEx( &pData );\n"
+ " u32 rank = localPrefixSum( s4, lIdx, totalSum, sorterSharedMemory, 128 );\n"
+ " return pData + make_uint4( rank, rank, rank, rank );\n"
+ "}\n"
+ "//__attribute__((reqd_work_group_size(64,1,1)))\n"
+ "uint4 localPrefixSum64V( uint4 pData, uint lIdx, uint* totalSum, __local u32* sorterSharedMemory )\n"
+ "{\n"
+ " u32 s4 = prefixScanVectorEx( &pData );\n"
+ " u32 rank = localPrefixSum( s4, lIdx, totalSum, sorterSharedMemory, 64 );\n"
+ " return pData + make_uint4( rank, rank, rank, rank );\n"
+ "}\n"
+ "u32 unpack4Key( u32 key, int keyIdx ){ return (key>>(keyIdx*8)) & 0xff;}\n"
+ "u32 bit8Scan(u32 v)\n"
+ "{\n"
+ " return (v<<8) + (v<<16) + (v<<24);\n"
+ "}\n"
+ "//===\n"
+ "#define MY_HISTOGRAM(idx) localHistogramMat[(idx)*WG_SIZE+lIdx]\n"
+ "__kernel\n"
+ "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+ "void StreamCountKernel( __global u32* gSrc, __global u32* histogramOut, int4 cb )\n"
+ "{\n"
+ " __local u32 localHistogramMat[NUM_BUCKET*WG_SIZE];\n"
+ " u32 gIdx = GET_GLOBAL_IDX;\n"
+ " u32 lIdx = GET_LOCAL_IDX;\n"
+ " u32 wgIdx = GET_GROUP_IDX;\n"
+ " u32 wgSize = GET_GROUP_SIZE;\n"
+ " const int startBit = cb.m_startBit;\n"
+ " const int n = cb.m_n;\n"
+ " const int nWGs = cb.m_nWGs;\n"
+ " const int nBlocksPerWG = cb.m_nBlocksPerWG;\n"
+ " for(int i=0; i<NUM_BUCKET; i++)\n"
+ " {\n"
+ " MY_HISTOGRAM(i) = 0;\n"
+ " }\n"
+ " GROUP_LDS_BARRIER;\n"
+ " const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;\n"
+ " u32 localKey;\n"
+ " int nBlocks = (n)/blockSize - nBlocksPerWG*wgIdx;\n"
+ " int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;\n"
+ " for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++, addr+=blockSize)\n"
+ " {\n"
+ " // MY_HISTOGRAM( localKeys.x ) ++ is much expensive than atomic add as it requires read and write while atomics can just add on AMD\n"
+ " // Using registers didn't perform well. It seems like use localKeys to address requires a lot of alu ops\n"
+ " // AMD: AtomInc performs better while NV prefers ++\n"
+ " for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
+ " {\n"
+ "#if defined(CHECK_BOUNDARY)\n"
+ " if( addr+i < n )\n"
+ "#endif\n"
+ " {\n"
+ " localKey = (gSrc[addr+i]>>startBit) & 0xf;\n"
+ "#if defined(NV_GPU)\n"
+ " MY_HISTOGRAM( localKey )++;\n"
+ "#else\n"
+ " AtomInc( MY_HISTOGRAM( localKey ) );\n"
+ "#endif\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " GROUP_LDS_BARRIER;\n"
+ " \n"
+ " if( lIdx < NUM_BUCKET )\n"
+ " {\n"
+ " u32 sum = 0;\n"
+ " for(int i=0; i<GET_GROUP_SIZE; i++)\n"
+ " {\n"
+ " sum += localHistogramMat[lIdx*WG_SIZE+(i+lIdx)%GET_GROUP_SIZE];\n"
+ " }\n"
+ " histogramOut[lIdx*nWGs+wgIdx] = sum;\n"
+ " }\n"
+ "}\n"
+ "__kernel\n"
+ "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+ "void StreamCountSortDataKernel( __global SortDataCL* gSrc, __global u32* histogramOut, int4 cb )\n"
+ "{\n"
+ " __local u32 localHistogramMat[NUM_BUCKET*WG_SIZE];\n"
+ " u32 gIdx = GET_GLOBAL_IDX;\n"
+ " u32 lIdx = GET_LOCAL_IDX;\n"
+ " u32 wgIdx = GET_GROUP_IDX;\n"
+ " u32 wgSize = GET_GROUP_SIZE;\n"
+ " const int startBit = cb.m_startBit;\n"
+ " const int n = cb.m_n;\n"
+ " const int nWGs = cb.m_nWGs;\n"
+ " const int nBlocksPerWG = cb.m_nBlocksPerWG;\n"
+ " for(int i=0; i<NUM_BUCKET; i++)\n"
+ " {\n"
+ " MY_HISTOGRAM(i) = 0;\n"
+ " }\n"
+ " GROUP_LDS_BARRIER;\n"
+ " const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;\n"
+ " u32 localKey;\n"
+ " int nBlocks = (n)/blockSize - nBlocksPerWG*wgIdx;\n"
+ " int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;\n"
+ " for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++, addr+=blockSize)\n"
+ " {\n"
+ " // MY_HISTOGRAM( localKeys.x ) ++ is much expensive than atomic add as it requires read and write while atomics can just add on AMD\n"
+ " // Using registers didn't perform well. It seems like use localKeys to address requires a lot of alu ops\n"
+ " // AMD: AtomInc performs better while NV prefers ++\n"
+ " for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
+ " {\n"
+ "#if defined(CHECK_BOUNDARY)\n"
+ " if( addr+i < n )\n"
+ "#endif\n"
+ " {\n"
+ " localKey = (gSrc[addr+i].m_key>>startBit) & 0xf;\n"
+ "#if defined(NV_GPU)\n"
+ " MY_HISTOGRAM( localKey )++;\n"
+ "#else\n"
+ " AtomInc( MY_HISTOGRAM( localKey ) );\n"
+ "#endif\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " GROUP_LDS_BARRIER;\n"
+ " \n"
+ " if( lIdx < NUM_BUCKET )\n"
+ " {\n"
+ " u32 sum = 0;\n"
+ " for(int i=0; i<GET_GROUP_SIZE; i++)\n"
+ " {\n"
+ " sum += localHistogramMat[lIdx*WG_SIZE+(i+lIdx)%GET_GROUP_SIZE];\n"
+ " }\n"
+ " histogramOut[lIdx*nWGs+wgIdx] = sum;\n"
+ " }\n"
+ "}\n"
+ "#define nPerLane (nPerWI/4)\n"
+ "// NUM_BUCKET*nWGs < 128*nPerWI\n"
+ "__kernel\n"
+ "__attribute__((reqd_work_group_size(128,1,1)))\n"
+ "void PrefixScanKernel( __global u32* wHistogram1, int4 cb )\n"
+ "{\n"
+ " __local u32 ldsTopScanData[128*2];\n"
+ " u32 lIdx = GET_LOCAL_IDX;\n"
+ " u32 wgIdx = GET_GROUP_IDX;\n"
+ " const int nWGs = cb.m_nWGs;\n"
+ " u32 data[nPerWI];\n"
+ " for(int i=0; i<nPerWI; i++)\n"
+ " {\n"
+ " data[i] = 0;\n"
+ " if( (nPerWI*lIdx+i) < NUM_BUCKET*nWGs )\n"
+ " data[i] = wHistogram1[nPerWI*lIdx+i];\n"
+ " }\n"
+ " uint4 myData = make_uint4(0,0,0,0);\n"
+ " for(int i=0; i<nPerLane; i++)\n"
+ " {\n"
+ " myData.x += data[nPerLane*0+i];\n"
+ " myData.y += data[nPerLane*1+i];\n"
+ " myData.z += data[nPerLane*2+i];\n"
+ " myData.w += data[nPerLane*3+i];\n"
+ " }\n"
+ " uint totalSum;\n"
+ " uint4 scanned = localPrefixSum128V( myData, lIdx, &totalSum, ldsTopScanData );\n"
+ "// for(int j=0; j<4; j++) // somehow it introduces a lot of branches\n"
+ " { int j = 0;\n"
+ " u32 sum = 0;\n"
+ " for(int i=0; i<nPerLane; i++)\n"
+ " {\n"
+ " u32 tmp = data[nPerLane*j+i];\n"
+ " data[nPerLane*j+i] = sum;\n"
+ " sum += tmp;\n"
+ " }\n"
+ " }\n"
+ " { int j = 1;\n"
+ " u32 sum = 0;\n"
+ " for(int i=0; i<nPerLane; i++)\n"
+ " {\n"
+ " u32 tmp = data[nPerLane*j+i];\n"
+ " data[nPerLane*j+i] = sum;\n"
+ " sum += tmp;\n"
+ " }\n"
+ " }\n"
+ " { int j = 2;\n"
+ " u32 sum = 0;\n"
+ " for(int i=0; i<nPerLane; i++)\n"
+ " {\n"
+ " u32 tmp = data[nPerLane*j+i];\n"
+ " data[nPerLane*j+i] = sum;\n"
+ " sum += tmp;\n"
+ " }\n"
+ " }\n"
+ " { int j = 3;\n"
+ " u32 sum = 0;\n"
+ " for(int i=0; i<nPerLane; i++)\n"
+ " {\n"
+ " u32 tmp = data[nPerLane*j+i];\n"
+ " data[nPerLane*j+i] = sum;\n"
+ " sum += tmp;\n"
+ " }\n"
+ " }\n"
+ " for(int i=0; i<nPerLane; i++)\n"
+ " {\n"
+ " data[nPerLane*0+i] += scanned.x;\n"
+ " data[nPerLane*1+i] += scanned.y;\n"
+ " data[nPerLane*2+i] += scanned.z;\n"
+ " data[nPerLane*3+i] += scanned.w;\n"
+ " }\n"
+ " for(int i=0; i<nPerWI; i++)\n"
+ " {\n"
+ " int index = nPerWI*lIdx+i;\n"
+ " if (index < NUM_BUCKET*nWGs)\n"
+ " wHistogram1[nPerWI*lIdx+i] = data[i];\n"
+ " }\n"
+ "}\n"
+ "// 4 scan, 4 exchange\n"
+ "void sort4Bits(u32 sortData[4], int startBit, int lIdx, __local u32* ldsSortData)\n"
+ "{\n"
+ " for(int bitIdx=0; bitIdx<BITS_PER_PASS; bitIdx++)\n"
+ " {\n"
+ " u32 mask = (1<<bitIdx);\n"
+ " uint4 cmpResult = make_uint4( (sortData[0]>>startBit) & mask, (sortData[1]>>startBit) & mask, (sortData[2]>>startBit) & mask, (sortData[3]>>startBit) & mask );\n"
+ " uint4 prefixSum = SELECT_UINT4( make_uint4(1,1,1,1), make_uint4(0,0,0,0), cmpResult != make_uint4(0,0,0,0) );\n"
+ " u32 total;\n"
+ " prefixSum = localPrefixSum64V( prefixSum, lIdx, &total, ldsSortData );\n"
+ " {\n"
+ " uint4 localAddr = make_uint4(lIdx*4+0,lIdx*4+1,lIdx*4+2,lIdx*4+3);\n"
+ " uint4 dstAddr = localAddr - prefixSum + make_uint4( total, total, total, total );\n"
+ " dstAddr = SELECT_UINT4( prefixSum, dstAddr, cmpResult != make_uint4(0, 0, 0, 0) );\n"
+ " GROUP_LDS_BARRIER;\n"
+ " ldsSortData[dstAddr.x] = sortData[0];\n"
+ " ldsSortData[dstAddr.y] = sortData[1];\n"
+ " ldsSortData[dstAddr.z] = sortData[2];\n"
+ " ldsSortData[dstAddr.w] = sortData[3];\n"
+ " GROUP_LDS_BARRIER;\n"
+ " sortData[0] = ldsSortData[localAddr.x];\n"
+ " sortData[1] = ldsSortData[localAddr.y];\n"
+ " sortData[2] = ldsSortData[localAddr.z];\n"
+ " sortData[3] = ldsSortData[localAddr.w];\n"
+ " GROUP_LDS_BARRIER;\n"
+ " }\n"
+ " }\n"
+ "}\n"
+ "// 2 scan, 2 exchange\n"
+ "void sort4Bits1(u32 sortData[4], int startBit, int lIdx, __local u32* ldsSortData)\n"
+ "{\n"
+ " for(uint ibit=0; ibit<BITS_PER_PASS; ibit+=2)\n"
+ " {\n"
+ " uint4 b = make_uint4((sortData[0]>>(startBit+ibit)) & 0x3, \n"
+ " (sortData[1]>>(startBit+ibit)) & 0x3, \n"
+ " (sortData[2]>>(startBit+ibit)) & 0x3, \n"
+ " (sortData[3]>>(startBit+ibit)) & 0x3);\n"
+ " u32 key4;\n"
+ " u32 sKeyPacked[4] = { 0, 0, 0, 0 };\n"
+ " {\n"
+ " sKeyPacked[0] |= 1<<(8*b.x);\n"
+ " sKeyPacked[1] |= 1<<(8*b.y);\n"
+ " sKeyPacked[2] |= 1<<(8*b.z);\n"
+ " sKeyPacked[3] |= 1<<(8*b.w);\n"
+ " key4 = sKeyPacked[0] + sKeyPacked[1] + sKeyPacked[2] + sKeyPacked[3];\n"
+ " }\n"
+ " u32 rankPacked;\n"
+ " u32 sumPacked;\n"
+ " {\n"
+ " rankPacked = localPrefixSum( key4, lIdx, &sumPacked, ldsSortData, WG_SIZE );\n"
+ " }\n"
+ " GROUP_LDS_BARRIER;\n"
+ " u32 newOffset[4] = { 0,0,0,0 };\n"
+ " {\n"
+ " u32 sumScanned = bit8Scan( sumPacked );\n"
+ " u32 scannedKeys[4];\n"
+ " scannedKeys[0] = 1<<(8*b.x);\n"
+ " scannedKeys[1] = 1<<(8*b.y);\n"
+ " scannedKeys[2] = 1<<(8*b.z);\n"
+ " scannedKeys[3] = 1<<(8*b.w);\n"
+ " { // 4 scans at once\n"
+ " u32 sum4 = 0;\n"
+ " for(int ie=0; ie<4; ie++)\n"
+ " {\n"
+ " u32 tmp = scannedKeys[ie];\n"
+ " scannedKeys[ie] = sum4;\n"
+ " sum4 += tmp;\n"
+ " }\n"
+ " }\n"
+ " {\n"
+ " u32 sumPlusRank = sumScanned + rankPacked;\n"
+ " { u32 ie = b.x;\n"
+ " scannedKeys[0] += sumPlusRank;\n"
+ " newOffset[0] = unpack4Key( scannedKeys[0], ie );\n"
+ " }\n"
+ " { u32 ie = b.y;\n"
+ " scannedKeys[1] += sumPlusRank;\n"
+ " newOffset[1] = unpack4Key( scannedKeys[1], ie );\n"
+ " }\n"
+ " { u32 ie = b.z;\n"
+ " scannedKeys[2] += sumPlusRank;\n"
+ " newOffset[2] = unpack4Key( scannedKeys[2], ie );\n"
+ " }\n"
+ " { u32 ie = b.w;\n"
+ " scannedKeys[3] += sumPlusRank;\n"
+ " newOffset[3] = unpack4Key( scannedKeys[3], ie );\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " GROUP_LDS_BARRIER;\n"
+ " {\n"
+ " ldsSortData[newOffset[0]] = sortData[0];\n"
+ " ldsSortData[newOffset[1]] = sortData[1];\n"
+ " ldsSortData[newOffset[2]] = sortData[2];\n"
+ " ldsSortData[newOffset[3]] = sortData[3];\n"
+ " GROUP_LDS_BARRIER;\n"
+ " u32 dstAddr = 4*lIdx;\n"
+ " sortData[0] = ldsSortData[dstAddr+0];\n"
+ " sortData[1] = ldsSortData[dstAddr+1];\n"
+ " sortData[2] = ldsSortData[dstAddr+2];\n"
+ " sortData[3] = ldsSortData[dstAddr+3];\n"
+ " GROUP_LDS_BARRIER;\n"
+ " }\n"
+ " }\n"
+ "}\n"
+ "#define SET_HISTOGRAM(setIdx, key) ldsSortData[(setIdx)*NUM_BUCKET+key]\n"
+ "__kernel\n"
+ "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+ "void SortAndScatterKernel( __global const u32* restrict gSrc, __global const u32* rHistogram, __global u32* restrict gDst, int4 cb )\n"
+ "{\n"
+ " __local u32 ldsSortData[WG_SIZE*ELEMENTS_PER_WORK_ITEM+16];\n"
+ " __local u32 localHistogramToCarry[NUM_BUCKET];\n"
+ " __local u32 localHistogram[NUM_BUCKET*2];\n"
+ " u32 gIdx = GET_GLOBAL_IDX;\n"
+ " u32 lIdx = GET_LOCAL_IDX;\n"
+ " u32 wgIdx = GET_GROUP_IDX;\n"
+ " u32 wgSize = GET_GROUP_SIZE;\n"
+ " const int n = cb.m_n;\n"
+ " const int nWGs = cb.m_nWGs;\n"
+ " const int startBit = cb.m_startBit;\n"
+ " const int nBlocksPerWG = cb.m_nBlocksPerWG;\n"
+ " if( lIdx < (NUM_BUCKET) )\n"
+ " {\n"
+ " localHistogramToCarry[lIdx] = rHistogram[lIdx*nWGs + wgIdx];\n"
+ " }\n"
+ " GROUP_LDS_BARRIER;\n"
+ " const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;\n"
+ " int nBlocks = n/blockSize - nBlocksPerWG*wgIdx;\n"
+ " int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;\n"
+ " for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++, addr+=blockSize)\n"
+ " {\n"
+ " u32 myHistogram = 0;\n"
+ " u32 sortData[ELEMENTS_PER_WORK_ITEM];\n"
+ " for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
+ "#if defined(CHECK_BOUNDARY)\n"
+ " sortData[i] = ( addr+i < n )? gSrc[ addr+i ] : 0xffffffff;\n"
+ "#else\n"
+ " sortData[i] = gSrc[ addr+i ];\n"
+ "#endif\n"
+ " sort4Bits(sortData, startBit, lIdx, ldsSortData);\n"
+ " u32 keys[ELEMENTS_PER_WORK_ITEM];\n"
+ " for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
+ " keys[i] = (sortData[i]>>startBit) & 0xf;\n"
+ " { // create histogram\n"
+ " u32 setIdx = lIdx/16;\n"
+ " if( lIdx < NUM_BUCKET )\n"
+ " {\n"
+ " localHistogram[lIdx] = 0;\n"
+ " }\n"
+ " ldsSortData[lIdx] = 0;\n"
+ " GROUP_LDS_BARRIER;\n"
+ " for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
+ "#if defined(CHECK_BOUNDARY)\n"
+ " if( addr+i < n )\n"
+ "#endif\n"
+ "#if defined(NV_GPU)\n"
+ " SET_HISTOGRAM( setIdx, keys[i] )++;\n"
+ "#else\n"
+ " AtomInc( SET_HISTOGRAM( setIdx, keys[i] ) );\n"
+ "#endif\n"
+ " \n"
+ " GROUP_LDS_BARRIER;\n"
+ " \n"
+ " uint hIdx = NUM_BUCKET+lIdx;\n"
+ " if( lIdx < NUM_BUCKET )\n"
+ " {\n"
+ " u32 sum = 0;\n"
+ " for(int i=0; i<WG_SIZE/16; i++)\n"
+ " {\n"
+ " sum += SET_HISTOGRAM( i, lIdx );\n"
+ " }\n"
+ " myHistogram = sum;\n"
+ " localHistogram[hIdx] = sum;\n"
+ " }\n"
+ " GROUP_LDS_BARRIER;\n"
+ "#if defined(USE_2LEVEL_REDUCE)\n"
+ " if( lIdx < NUM_BUCKET )\n"
+ " {\n"
+ " localHistogram[hIdx] = localHistogram[hIdx-1];\n"
+ " GROUP_MEM_FENCE;\n"
+ " u32 u0, u1, u2;\n"
+ " u0 = localHistogram[hIdx-3];\n"
+ " u1 = localHistogram[hIdx-2];\n"
+ " u2 = localHistogram[hIdx-1];\n"
+ " AtomAdd( localHistogram[hIdx], u0 + u1 + u2 );\n"
+ " GROUP_MEM_FENCE;\n"
+ " u0 = localHistogram[hIdx-12];\n"
+ " u1 = localHistogram[hIdx-8];\n"
+ " u2 = localHistogram[hIdx-4];\n"
+ " AtomAdd( localHistogram[hIdx], u0 + u1 + u2 );\n"
+ " GROUP_MEM_FENCE;\n"
+ " }\n"
+ "#else\n"
+ " if( lIdx < NUM_BUCKET )\n"
+ " {\n"
+ " localHistogram[hIdx] = localHistogram[hIdx-1];\n"
+ " GROUP_MEM_FENCE;\n"
+ " localHistogram[hIdx] += localHistogram[hIdx-1];\n"
+ " GROUP_MEM_FENCE;\n"
+ " localHistogram[hIdx] += localHistogram[hIdx-2];\n"
+ " GROUP_MEM_FENCE;\n"
+ " localHistogram[hIdx] += localHistogram[hIdx-4];\n"
+ " GROUP_MEM_FENCE;\n"
+ " localHistogram[hIdx] += localHistogram[hIdx-8];\n"
+ " GROUP_MEM_FENCE;\n"
+ " }\n"
+ "#endif\n"
+ " GROUP_LDS_BARRIER;\n"
+ " }\n"
+ " {\n"
+ " for(int ie=0; ie<ELEMENTS_PER_WORK_ITEM; ie++)\n"
+ " {\n"
+ " int dataIdx = ELEMENTS_PER_WORK_ITEM*lIdx+ie;\n"
+ " int binIdx = keys[ie];\n"
+ " int groupOffset = localHistogramToCarry[binIdx];\n"
+ " int myIdx = dataIdx - localHistogram[NUM_BUCKET+binIdx];\n"
+ "#if defined(CHECK_BOUNDARY)\n"
+ " if( addr+ie < n )\n"
+ "#endif\n"
+ " gDst[ groupOffset + myIdx ] = sortData[ie];\n"
+ " }\n"
+ " }\n"
+ " GROUP_LDS_BARRIER;\n"
+ " if( lIdx < NUM_BUCKET )\n"
+ " {\n"
+ " localHistogramToCarry[lIdx] += myHistogram;\n"
+ " }\n"
+ " GROUP_LDS_BARRIER;\n"
+ " }\n"
+ "}\n"
+ "// 2 scan, 2 exchange\n"
+ "void sort4Bits1KeyValue(u32 sortData[4], int sortVal[4], int startBit, int lIdx, __local u32* ldsSortData, __local int *ldsSortVal)\n"
+ "{\n"
+ " for(uint ibit=0; ibit<BITS_PER_PASS; ibit+=2)\n"
+ " {\n"
+ " uint4 b = make_uint4((sortData[0]>>(startBit+ibit)) & 0x3, \n"
+ " (sortData[1]>>(startBit+ibit)) & 0x3, \n"
+ " (sortData[2]>>(startBit+ibit)) & 0x3, \n"
+ " (sortData[3]>>(startBit+ibit)) & 0x3);\n"
+ " u32 key4;\n"
+ " u32 sKeyPacked[4] = { 0, 0, 0, 0 };\n"
+ " {\n"
+ " sKeyPacked[0] |= 1<<(8*b.x);\n"
+ " sKeyPacked[1] |= 1<<(8*b.y);\n"
+ " sKeyPacked[2] |= 1<<(8*b.z);\n"
+ " sKeyPacked[3] |= 1<<(8*b.w);\n"
+ " key4 = sKeyPacked[0] + sKeyPacked[1] + sKeyPacked[2] + sKeyPacked[3];\n"
+ " }\n"
+ " u32 rankPacked;\n"
+ " u32 sumPacked;\n"
+ " {\n"
+ " rankPacked = localPrefixSum( key4, lIdx, &sumPacked, ldsSortData, WG_SIZE );\n"
+ " }\n"
+ " GROUP_LDS_BARRIER;\n"
+ " u32 newOffset[4] = { 0,0,0,0 };\n"
+ " {\n"
+ " u32 sumScanned = bit8Scan( sumPacked );\n"
+ " u32 scannedKeys[4];\n"
+ " scannedKeys[0] = 1<<(8*b.x);\n"
+ " scannedKeys[1] = 1<<(8*b.y);\n"
+ " scannedKeys[2] = 1<<(8*b.z);\n"
+ " scannedKeys[3] = 1<<(8*b.w);\n"
+ " { // 4 scans at once\n"
+ " u32 sum4 = 0;\n"
+ " for(int ie=0; ie<4; ie++)\n"
+ " {\n"
+ " u32 tmp = scannedKeys[ie];\n"
+ " scannedKeys[ie] = sum4;\n"
+ " sum4 += tmp;\n"
+ " }\n"
+ " }\n"
+ " {\n"
+ " u32 sumPlusRank = sumScanned + rankPacked;\n"
+ " { u32 ie = b.x;\n"
+ " scannedKeys[0] += sumPlusRank;\n"
+ " newOffset[0] = unpack4Key( scannedKeys[0], ie );\n"
+ " }\n"
+ " { u32 ie = b.y;\n"
+ " scannedKeys[1] += sumPlusRank;\n"
+ " newOffset[1] = unpack4Key( scannedKeys[1], ie );\n"
+ " }\n"
+ " { u32 ie = b.z;\n"
+ " scannedKeys[2] += sumPlusRank;\n"
+ " newOffset[2] = unpack4Key( scannedKeys[2], ie );\n"
+ " }\n"
+ " { u32 ie = b.w;\n"
+ " scannedKeys[3] += sumPlusRank;\n"
+ " newOffset[3] = unpack4Key( scannedKeys[3], ie );\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " GROUP_LDS_BARRIER;\n"
+ " {\n"
+ " ldsSortData[newOffset[0]] = sortData[0];\n"
+ " ldsSortData[newOffset[1]] = sortData[1];\n"
+ " ldsSortData[newOffset[2]] = sortData[2];\n"
+ " ldsSortData[newOffset[3]] = sortData[3];\n"
+ " ldsSortVal[newOffset[0]] = sortVal[0];\n"
+ " ldsSortVal[newOffset[1]] = sortVal[1];\n"
+ " ldsSortVal[newOffset[2]] = sortVal[2];\n"
+ " ldsSortVal[newOffset[3]] = sortVal[3];\n"
+ " GROUP_LDS_BARRIER;\n"
+ " u32 dstAddr = 4*lIdx;\n"
+ " sortData[0] = ldsSortData[dstAddr+0];\n"
+ " sortData[1] = ldsSortData[dstAddr+1];\n"
+ " sortData[2] = ldsSortData[dstAddr+2];\n"
+ " sortData[3] = ldsSortData[dstAddr+3];\n"
+ " sortVal[0] = ldsSortVal[dstAddr+0];\n"
+ " sortVal[1] = ldsSortVal[dstAddr+1];\n"
+ " sortVal[2] = ldsSortVal[dstAddr+2];\n"
+ " sortVal[3] = ldsSortVal[dstAddr+3];\n"
+ " GROUP_LDS_BARRIER;\n"
+ " }\n"
+ " }\n"
+ "}\n"
+ "__kernel\n"
+ "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+ "void SortAndScatterSortDataKernel( __global const SortDataCL* restrict gSrc, __global const u32* rHistogram, __global SortDataCL* restrict gDst, int4 cb)\n"
+ "{\n"
+ " __local int ldsSortData[WG_SIZE*ELEMENTS_PER_WORK_ITEM+16];\n"
+ " __local int ldsSortVal[WG_SIZE*ELEMENTS_PER_WORK_ITEM+16];\n"
+ " __local u32 localHistogramToCarry[NUM_BUCKET];\n"
+ " __local u32 localHistogram[NUM_BUCKET*2];\n"
+ " u32 gIdx = GET_GLOBAL_IDX;\n"
+ " u32 lIdx = GET_LOCAL_IDX;\n"
+ " u32 wgIdx = GET_GROUP_IDX;\n"
+ " u32 wgSize = GET_GROUP_SIZE;\n"
+ " const int n = cb.m_n;\n"
+ " const int nWGs = cb.m_nWGs;\n"
+ " const int startBit = cb.m_startBit;\n"
+ " const int nBlocksPerWG = cb.m_nBlocksPerWG;\n"
+ " if( lIdx < (NUM_BUCKET) )\n"
+ " {\n"
+ " localHistogramToCarry[lIdx] = rHistogram[lIdx*nWGs + wgIdx];\n"
+ " }\n"
+ " GROUP_LDS_BARRIER;\n"
+ " \n"
+ " const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;\n"
+ " int nBlocks = n/blockSize - nBlocksPerWG*wgIdx;\n"
+ " int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;\n"
+ " for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++, addr+=blockSize)\n"
+ " {\n"
+ " u32 myHistogram = 0;\n"
+ " int sortData[ELEMENTS_PER_WORK_ITEM];\n"
+ " int sortVal[ELEMENTS_PER_WORK_ITEM];\n"
+ " for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
+ "#if defined(CHECK_BOUNDARY)\n"
+ " {\n"
+ " sortData[i] = ( addr+i < n )? gSrc[ addr+i ].m_key : 0xffffffff;\n"
+ " sortVal[i] = ( addr+i < n )? gSrc[ addr+i ].m_value : 0xffffffff;\n"
+ " }\n"
+ "#else\n"
+ " {\n"
+ " sortData[i] = gSrc[ addr+i ].m_key;\n"
+ " sortVal[i] = gSrc[ addr+i ].m_value;\n"
+ " }\n"
+ "#endif\n"
+ " sort4Bits1KeyValue(sortData, sortVal, startBit, lIdx, ldsSortData, ldsSortVal);\n"
+ " u32 keys[ELEMENTS_PER_WORK_ITEM];\n"
+ " for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
+ " keys[i] = (sortData[i]>>startBit) & 0xf;\n"
+ " { // create histogram\n"
+ " u32 setIdx = lIdx/16;\n"
+ " if( lIdx < NUM_BUCKET )\n"
+ " {\n"
+ " localHistogram[lIdx] = 0;\n"
+ " }\n"
+ " ldsSortData[lIdx] = 0;\n"
+ " GROUP_LDS_BARRIER;\n"
+ " for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
+ "#if defined(CHECK_BOUNDARY)\n"
+ " if( addr+i < n )\n"
+ "#endif\n"
+ "#if defined(NV_GPU)\n"
+ " SET_HISTOGRAM( setIdx, keys[i] )++;\n"
+ "#else\n"
+ " AtomInc( SET_HISTOGRAM( setIdx, keys[i] ) );\n"
+ "#endif\n"
+ " \n"
+ " GROUP_LDS_BARRIER;\n"
+ " \n"
+ " uint hIdx = NUM_BUCKET+lIdx;\n"
+ " if( lIdx < NUM_BUCKET )\n"
+ " {\n"
+ " u32 sum = 0;\n"
+ " for(int i=0; i<WG_SIZE/16; i++)\n"
+ " {\n"
+ " sum += SET_HISTOGRAM( i, lIdx );\n"
+ " }\n"
+ " myHistogram = sum;\n"
+ " localHistogram[hIdx] = sum;\n"
+ " }\n"
+ " GROUP_LDS_BARRIER;\n"
+ "#if defined(USE_2LEVEL_REDUCE)\n"
+ " if( lIdx < NUM_BUCKET )\n"
+ " {\n"
+ " localHistogram[hIdx] = localHistogram[hIdx-1];\n"
+ " GROUP_MEM_FENCE;\n"
+ " u32 u0, u1, u2;\n"
+ " u0 = localHistogram[hIdx-3];\n"
+ " u1 = localHistogram[hIdx-2];\n"
+ " u2 = localHistogram[hIdx-1];\n"
+ " AtomAdd( localHistogram[hIdx], u0 + u1 + u2 );\n"
+ " GROUP_MEM_FENCE;\n"
+ " u0 = localHistogram[hIdx-12];\n"
+ " u1 = localHistogram[hIdx-8];\n"
+ " u2 = localHistogram[hIdx-4];\n"
+ " AtomAdd( localHistogram[hIdx], u0 + u1 + u2 );\n"
+ " GROUP_MEM_FENCE;\n"
+ " }\n"
+ "#else\n"
+ " if( lIdx < NUM_BUCKET )\n"
+ " {\n"
+ " localHistogram[hIdx] = localHistogram[hIdx-1];\n"
+ " GROUP_MEM_FENCE;\n"
+ " localHistogram[hIdx] += localHistogram[hIdx-1];\n"
+ " GROUP_MEM_FENCE;\n"
+ " localHistogram[hIdx] += localHistogram[hIdx-2];\n"
+ " GROUP_MEM_FENCE;\n"
+ " localHistogram[hIdx] += localHistogram[hIdx-4];\n"
+ " GROUP_MEM_FENCE;\n"
+ " localHistogram[hIdx] += localHistogram[hIdx-8];\n"
+ " GROUP_MEM_FENCE;\n"
+ " }\n"
+ "#endif\n"
+ " GROUP_LDS_BARRIER;\n"
+ " }\n"
+ " {\n"
+ " for(int ie=0; ie<ELEMENTS_PER_WORK_ITEM; ie++)\n"
+ " {\n"
+ " int dataIdx = ELEMENTS_PER_WORK_ITEM*lIdx+ie;\n"
+ " int binIdx = keys[ie];\n"
+ " int groupOffset = localHistogramToCarry[binIdx];\n"
+ " int myIdx = dataIdx - localHistogram[NUM_BUCKET+binIdx];\n"
+ "#if defined(CHECK_BOUNDARY)\n"
+ " if( addr+ie < n )\n"
+ " {\n"
+ " if ((groupOffset + myIdx)<n)\n"
+ " {\n"
+ " if (sortData[ie]==sortVal[ie])\n"
+ " {\n"
+ " \n"
+ " SortDataCL tmp;\n"
+ " tmp.m_key = sortData[ie];\n"
+ " tmp.m_value = sortVal[ie];\n"
+ " if (tmp.m_key == tmp.m_value)\n"
+ " gDst[groupOffset + myIdx ] = tmp;\n"
+ " }\n"
+ " \n"
+ " }\n"
+ " }\n"
+ "#else\n"
+ " if ((groupOffset + myIdx)<n)\n"
+ " {\n"
+ " gDst[ groupOffset + myIdx ].m_key = sortData[ie];\n"
+ " gDst[ groupOffset + myIdx ].m_value = sortVal[ie];\n"
+ " }\n"
+ "#endif\n"
+ " }\n"
+ " }\n"
+ " GROUP_LDS_BARRIER;\n"
+ " if( lIdx < NUM_BUCKET )\n"
+ " {\n"
+ " localHistogramToCarry[lIdx] += myHistogram;\n"
+ " }\n"
+ " GROUP_LDS_BARRIER;\n"
+ " }\n"
+ "}\n"
+ "__kernel\n"
+ "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+ "void SortAndScatterSortDataKernelSerial( __global const SortDataCL* restrict gSrc, __global const u32* rHistogram, __global SortDataCL* restrict gDst, int4 cb)\n"
+ "{\n"
+ " \n"
+ " u32 gIdx = GET_GLOBAL_IDX;\n"
+ " u32 realLocalIdx = GET_LOCAL_IDX;\n"
+ " u32 wgIdx = GET_GROUP_IDX;\n"
+ " u32 wgSize = GET_GROUP_SIZE;\n"
+ " const int startBit = cb.m_startBit;\n"
+ " const int n = cb.m_n;\n"
+ " const int nWGs = cb.m_nWGs;\n"
+ " const int nBlocksPerWG = cb.m_nBlocksPerWG;\n"
+ " int counter[NUM_BUCKET];\n"
+ " \n"
+ " if (realLocalIdx>0)\n"
+ " return;\n"
+ " \n"
+ " for (int c=0;c<NUM_BUCKET;c++)\n"
+ " counter[c]=0;\n"
+ " const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;\n"
+ " \n"
+ " int nBlocks = (n)/blockSize - nBlocksPerWG*wgIdx;\n"
+ " for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++)\n"
+ " {\n"
+ " for (int lIdx=0;lIdx<WG_SIZE;lIdx++)\n"
+ " {\n"
+ " int addr2 = iblock*blockSize + blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;\n"
+ " \n"
+ " for(int j=0; j<ELEMENTS_PER_WORK_ITEM; j++)\n"
+ " {\n"
+ " int i = addr2+j;\n"
+ " if( i < n )\n"
+ " {\n"
+ " int tableIdx;\n"
+ " tableIdx = (gSrc[i].m_key>>startBit) & 0xf;//0xf = NUM_TABLES-1\n"
+ " gDst[rHistogram[tableIdx*nWGs+wgIdx] + counter[tableIdx]] = gSrc[i];\n"
+ " counter[tableIdx] ++;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " \n"
+ "}\n"
+ "__kernel\n"
+ "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+ "void SortAndScatterKernelSerial( __global const u32* restrict gSrc, __global const u32* rHistogram, __global u32* restrict gDst, int4 cb )\n"
+ "{\n"
+ " \n"
+ " u32 gIdx = GET_GLOBAL_IDX;\n"
+ " u32 realLocalIdx = GET_LOCAL_IDX;\n"
+ " u32 wgIdx = GET_GROUP_IDX;\n"
+ " u32 wgSize = GET_GROUP_SIZE;\n"
+ " const int startBit = cb.m_startBit;\n"
+ " const int n = cb.m_n;\n"
+ " const int nWGs = cb.m_nWGs;\n"
+ " const int nBlocksPerWG = cb.m_nBlocksPerWG;\n"
+ " int counter[NUM_BUCKET];\n"
+ " \n"
+ " if (realLocalIdx>0)\n"
+ " return;\n"
+ " \n"
+ " for (int c=0;c<NUM_BUCKET;c++)\n"
+ " counter[c]=0;\n"
+ " const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;\n"
+ " \n"
+ " int nBlocks = (n)/blockSize - nBlocksPerWG*wgIdx;\n"
+ " for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++)\n"
+ " {\n"
+ " for (int lIdx=0;lIdx<WG_SIZE;lIdx++)\n"
+ " {\n"
+ " int addr2 = iblock*blockSize + blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;\n"
+ " \n"
+ " for(int j=0; j<ELEMENTS_PER_WORK_ITEM; j++)\n"
+ " {\n"
+ " int i = addr2+j;\n"
+ " if( i < n )\n"
+ " {\n"
+ " int tableIdx;\n"
+ " tableIdx = (gSrc[i]>>startBit) & 0xf;//0xf = NUM_TABLES-1\n"
+ " gDst[rHistogram[tableIdx*nWGs+wgIdx] + counter[tableIdx]] = gSrc[i];\n"
+ " counter[tableIdx] ++;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " \n"
+ "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/Raycast/b3GpuRaycast.cpp b/thirdparty/bullet/Bullet3OpenCL/Raycast/b3GpuRaycast.cpp
index 161e304f09..6571f30548 100644
--- a/thirdparty/bullet/Bullet3OpenCL/Raycast/b3GpuRaycast.cpp
+++ b/thirdparty/bullet/Bullet3OpenCL/Raycast/b3GpuRaycast.cpp
@@ -4,7 +4,6 @@
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
#include "Bullet3OpenCL/RigidBody/b3GpuNarrowPhaseInternalData.h"
-
#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
#include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
@@ -15,38 +14,35 @@
#include "Bullet3OpenCL/Raycast/kernels/rayCastKernels.h"
-
#define B3_RAYCAST_PATH "src/Bullet3OpenCL/Raycast/kernels/rayCastKernels.cl"
-
-
struct b3GpuRaycastInternalData
{
cl_context m_context;
cl_device_id m_device;
- cl_command_queue m_q;
+ cl_command_queue m_q;
cl_kernel m_raytraceKernel;
cl_kernel m_raytracePairsKernel;
cl_kernel m_findRayRigidPairIndexRanges;
-
+
b3GpuParallelLinearBvh* m_plbvh;
b3RadixSort32CL* m_radixSorter;
b3FillCL* m_fill;
-
+
//1 element per ray
b3OpenCLArray<b3RayInfo>* m_gpuRays;
b3OpenCLArray<b3RayHit>* m_gpuHitResults;
b3OpenCLArray<int>* m_firstRayRigidPairIndexPerRay;
b3OpenCLArray<int>* m_numRayRigidPairsPerRay;
-
+
//1 element per (ray index, rigid index) pair, where the ray intersects with the rigid's AABB
b3OpenCLArray<int>* m_gpuNumRayRigidPairs;
- b3OpenCLArray<b3Int2>* m_gpuRayRigidPairs; //x == ray index, y == rigid index
-
+ b3OpenCLArray<b3Int2>* m_gpuRayRigidPairs; //x == ray index, y == rigid index
+
int m_test;
};
-b3GpuRaycast::b3GpuRaycast(cl_context ctx,cl_device_id device, cl_command_queue q)
+b3GpuRaycast::b3GpuRaycast(cl_context ctx, cl_device_id device, cl_command_queue q)
{
m_data = new b3GpuRaycastInternalData;
m_data->m_context = ctx;
@@ -59,7 +55,7 @@ b3GpuRaycast::b3GpuRaycast(cl_context ctx,cl_device_id device, cl_command_queue
m_data->m_plbvh = new b3GpuParallelLinearBvh(ctx, device, q);
m_data->m_radixSorter = new b3RadixSort32CL(ctx, device, q);
m_data->m_fill = new b3FillCL(ctx, device, q);
-
+
m_data->m_gpuRays = new b3OpenCLArray<b3RayInfo>(ctx, q);
m_data->m_gpuHitResults = new b3OpenCLArray<b3RayHit>(ctx, q);
m_data->m_firstRayRigidPairIndexPerRay = new b3OpenCLArray<int>(ctx, q);
@@ -68,19 +64,17 @@ b3GpuRaycast::b3GpuRaycast(cl_context ctx,cl_device_id device, cl_command_queue
m_data->m_gpuRayRigidPairs = new b3OpenCLArray<b3Int2>(ctx, q);
{
- cl_int errNum=0;
- cl_program prog = b3OpenCLUtils::compileCLProgramFromString(m_data->m_context,m_data->m_device,rayCastKernelCL,&errNum,"",B3_RAYCAST_PATH);
- b3Assert(errNum==CL_SUCCESS);
- m_data->m_raytraceKernel = b3OpenCLUtils::compileCLKernelFromString(m_data->m_context, m_data->m_device,rayCastKernelCL, "rayCastKernel",&errNum,prog);
- b3Assert(errNum==CL_SUCCESS);
- m_data->m_raytracePairsKernel = b3OpenCLUtils::compileCLKernelFromString(m_data->m_context, m_data->m_device,rayCastKernelCL, "rayCastPairsKernel",&errNum,prog);
- b3Assert(errNum==CL_SUCCESS);
- m_data->m_findRayRigidPairIndexRanges = b3OpenCLUtils::compileCLKernelFromString(m_data->m_context, m_data->m_device,rayCastKernelCL, "findRayRigidPairIndexRanges",&errNum,prog);
- b3Assert(errNum==CL_SUCCESS);
+ cl_int errNum = 0;
+ cl_program prog = b3OpenCLUtils::compileCLProgramFromString(m_data->m_context, m_data->m_device, rayCastKernelCL, &errNum, "", B3_RAYCAST_PATH);
+ b3Assert(errNum == CL_SUCCESS);
+ m_data->m_raytraceKernel = b3OpenCLUtils::compileCLKernelFromString(m_data->m_context, m_data->m_device, rayCastKernelCL, "rayCastKernel", &errNum, prog);
+ b3Assert(errNum == CL_SUCCESS);
+ m_data->m_raytracePairsKernel = b3OpenCLUtils::compileCLKernelFromString(m_data->m_context, m_data->m_device, rayCastKernelCL, "rayCastPairsKernel", &errNum, prog);
+ b3Assert(errNum == CL_SUCCESS);
+ m_data->m_findRayRigidPairIndexRanges = b3OpenCLUtils::compileCLKernelFromString(m_data->m_context, m_data->m_device, rayCastKernelCL, "findRayRigidPairIndexRanges", &errNum, prog);
+ b3Assert(errNum == CL_SUCCESS);
clReleaseProgram(prog);
}
-
-
}
b3GpuRaycast::~b3GpuRaycast()
@@ -88,78 +82,80 @@ b3GpuRaycast::~b3GpuRaycast()
clReleaseKernel(m_data->m_raytraceKernel);
clReleaseKernel(m_data->m_raytracePairsKernel);
clReleaseKernel(m_data->m_findRayRigidPairIndexRanges);
-
+
delete m_data->m_plbvh;
delete m_data->m_radixSorter;
delete m_data->m_fill;
-
+
delete m_data->m_gpuRays;
delete m_data->m_gpuHitResults;
delete m_data->m_firstRayRigidPairIndexPerRay;
delete m_data->m_numRayRigidPairsPerRay;
delete m_data->m_gpuNumRayRigidPairs;
delete m_data->m_gpuRayRigidPairs;
-
+
delete m_data;
}
-bool sphere_intersect(const b3Vector3& spherePos, b3Scalar radius, const b3Vector3& rayFrom, const b3Vector3& rayTo, float& hitFraction)
+bool sphere_intersect(const b3Vector3& spherePos, b3Scalar radius, const b3Vector3& rayFrom, const b3Vector3& rayTo, float& hitFraction)
{
- b3Vector3 rs = rayFrom - spherePos;
- b3Vector3 rayDir = rayTo-rayFrom;
-
- float A = b3Dot(rayDir,rayDir);
- float B = b3Dot(rs, rayDir);
- float C = b3Dot(rs, rs) - (radius * radius);
-
- float D = B * B - A*C;
-
- if (D > 0.0)
- {
- float t = (-B - sqrt(D))/A;
-
- if ( (t >= 0.0f) && (t < hitFraction) )
- {
+ b3Vector3 rs = rayFrom - spherePos;
+ b3Vector3 rayDir = rayTo - rayFrom;
+
+ float A = b3Dot(rayDir, rayDir);
+ float B = b3Dot(rs, rayDir);
+ float C = b3Dot(rs, rs) - (radius * radius);
+
+ float D = B * B - A * C;
+
+ if (D > 0.0)
+ {
+ float t = (-B - sqrt(D)) / A;
+
+ if ((t >= 0.0f) && (t < hitFraction))
+ {
hitFraction = t;
- return true;
+ return true;
}
}
return false;
}
bool rayConvex(const b3Vector3& rayFromLocal, const b3Vector3& rayToLocal, const b3ConvexPolyhedronData& poly,
- const b3AlignedObjectArray<b3GpuFace>& faces, float& hitFraction, b3Vector3& hitNormal)
+ const b3AlignedObjectArray<b3GpuFace>& faces, float& hitFraction, b3Vector3& hitNormal)
{
float exitFraction = hitFraction;
float enterFraction = -0.1f;
- b3Vector3 curHitNormal=b3MakeVector3(0,0,0);
- for (int i=0;i<poly.m_numFaces;i++)
+ b3Vector3 curHitNormal = b3MakeVector3(0, 0, 0);
+ for (int i = 0; i < poly.m_numFaces; i++)
{
- const b3GpuFace& face = faces[poly.m_faceOffset+i];
- float fromPlaneDist = b3Dot(rayFromLocal,face.m_plane)+face.m_plane.w;
- float toPlaneDist = b3Dot(rayToLocal,face.m_plane)+face.m_plane.w;
- if (fromPlaneDist<0.f)
+ const b3GpuFace& face = faces[poly.m_faceOffset + i];
+ float fromPlaneDist = b3Dot(rayFromLocal, face.m_plane) + face.m_plane.w;
+ float toPlaneDist = b3Dot(rayToLocal, face.m_plane) + face.m_plane.w;
+ if (fromPlaneDist < 0.f)
{
if (toPlaneDist >= 0.f)
{
- float fraction = fromPlaneDist / (fromPlaneDist-toPlaneDist);
- if (exitFraction>fraction)
+ float fraction = fromPlaneDist / (fromPlaneDist - toPlaneDist);
+ if (exitFraction > fraction)
{
exitFraction = fraction;
}
- }
- } else
+ }
+ }
+ else
{
- if (toPlaneDist<0.f)
+ if (toPlaneDist < 0.f)
{
- float fraction = fromPlaneDist / (fromPlaneDist-toPlaneDist);
+ float fraction = fromPlaneDist / (fromPlaneDist - toPlaneDist);
if (enterFraction <= fraction)
{
enterFraction = fraction;
curHitNormal = face.m_plane;
curHitNormal.w = 0.f;
}
- } else
+ }
+ else
{
return false;
}
@@ -176,44 +172,41 @@ bool rayConvex(const b3Vector3& rayFromLocal, const b3Vector3& rayToLocal, const
return true;
}
-void b3GpuRaycast::castRaysHost(const b3AlignedObjectArray<b3RayInfo>& rays, b3AlignedObjectArray<b3RayHit>& hitResults,
- int numBodies,const struct b3RigidBodyData* bodies, int numCollidables,const struct b3Collidable* collidables, const struct b3GpuNarrowPhaseInternalData* narrowphaseData)
+void b3GpuRaycast::castRaysHost(const b3AlignedObjectArray<b3RayInfo>& rays, b3AlignedObjectArray<b3RayHit>& hitResults,
+ int numBodies, const struct b3RigidBodyData* bodies, int numCollidables, const struct b3Collidable* collidables, const struct b3GpuNarrowPhaseInternalData* narrowphaseData)
{
-
-// return castRays(rays,hitResults,numBodies,bodies,numCollidables,collidables);
+ // return castRays(rays,hitResults,numBodies,bodies,numCollidables,collidables);
B3_PROFILE("castRaysHost");
- for (int r=0;r<rays.size();r++)
+ for (int r = 0; r < rays.size(); r++)
{
b3Vector3 rayFrom = rays[r].m_from;
b3Vector3 rayTo = rays[r].m_to;
float hitFraction = hitResults[r].m_hitFraction;
- int hitBodyIndex= -1;
+ int hitBodyIndex = -1;
b3Vector3 hitNormal;
- for (int b=0;b<numBodies;b++)
+ for (int b = 0; b < numBodies; b++)
{
-
const b3Vector3& pos = bodies[b].m_pos;
//const b3Quaternion& orn = bodies[b].m_quat;
-
+
switch (collidables[bodies[b].m_collidableIdx].m_shapeType)
{
- case SHAPE_SPHERE:
+ case SHAPE_SPHERE:
{
b3Scalar radius = collidables[bodies[b].m_collidableIdx].m_radius;
- if (sphere_intersect(pos, radius, rayFrom, rayTo,hitFraction))
+ if (sphere_intersect(pos, radius, rayFrom, rayTo, hitFraction))
{
hitBodyIndex = b;
b3Vector3 hitPoint;
- hitPoint.setInterpolate3(rays[r].m_from, rays[r].m_to,hitFraction);
- hitNormal = (hitPoint-bodies[b].m_pos).normalize();
+ hitPoint.setInterpolate3(rays[r].m_from, rays[r].m_to, hitFraction);
+ hitNormal = (hitPoint - bodies[b].m_pos).normalize();
}
}
- case SHAPE_CONVEX_HULL:
+ case SHAPE_CONVEX_HULL:
{
-
b3Transform convexWorldTransform;
convexWorldTransform.setIdentity();
convexWorldTransform.setOrigin(bodies[b].m_pos);
@@ -222,72 +215,67 @@ void b3GpuRaycast::castRaysHost(const b3AlignedObjectArray<b3RayInfo>& rays, b3A
b3Vector3 rayFromLocal = convexWorld2Local(rayFrom);
b3Vector3 rayToLocal = convexWorld2Local(rayTo);
-
-
+
int shapeIndex = collidables[bodies[b].m_collidableIdx].m_shapeIndex;
const b3ConvexPolyhedronData& poly = narrowphaseData->m_convexPolyhedra[shapeIndex];
- if (rayConvex(rayFromLocal, rayToLocal,poly,narrowphaseData->m_convexFaces, hitFraction, hitNormal))
+ if (rayConvex(rayFromLocal, rayToLocal, poly, narrowphaseData->m_convexFaces, hitFraction, hitNormal))
{
hitBodyIndex = b;
}
-
break;
}
- default:
+ default:
{
- static bool once=true;
+ static bool once = true;
if (once)
{
- once=false;
+ once = false;
b3Warning("Raytest: unsupported shape type\n");
}
}
}
}
- if (hitBodyIndex>=0)
+ if (hitBodyIndex >= 0)
{
-
hitResults[r].m_hitFraction = hitFraction;
- hitResults[r].m_hitPoint.setInterpolate3(rays[r].m_from, rays[r].m_to,hitFraction);
+ hitResults[r].m_hitPoint.setInterpolate3(rays[r].m_from, rays[r].m_to, hitFraction);
hitResults[r].m_hitNormal = hitNormal;
hitResults[r].m_hitBody = hitBodyIndex;
}
-
}
}
///todo: add some acceleration structure (AABBs, tree etc)
-void b3GpuRaycast::castRays(const b3AlignedObjectArray<b3RayInfo>& rays, b3AlignedObjectArray<b3RayHit>& hitResults,
- int numBodies,const struct b3RigidBodyData* bodies, int numCollidables, const struct b3Collidable* collidables,
- const struct b3GpuNarrowPhaseInternalData* narrowphaseData, class b3GpuBroadphaseInterface* broadphase)
+void b3GpuRaycast::castRays(const b3AlignedObjectArray<b3RayInfo>& rays, b3AlignedObjectArray<b3RayHit>& hitResults,
+ int numBodies, const struct b3RigidBodyData* bodies, int numCollidables, const struct b3Collidable* collidables,
+ const struct b3GpuNarrowPhaseInternalData* narrowphaseData, class b3GpuBroadphaseInterface* broadphase)
{
//castRaysHost(rays,hitResults,numBodies,bodies,numCollidables,collidables,narrowphaseData);
B3_PROFILE("castRaysGPU");
-
+
{
B3_PROFILE("raycast copyFromHost");
m_data->m_gpuRays->copyFromHost(rays);
m_data->m_gpuHitResults->copyFromHost(hitResults);
-
}
-
+
int numRays = hitResults.size();
{
m_data->m_firstRayRigidPairIndexPerRay->resize(numRays);
m_data->m_numRayRigidPairsPerRay->resize(numRays);
-
+
m_data->m_gpuNumRayRigidPairs->resize(1);
m_data->m_gpuRayRigidPairs->resize(numRays * 16);
}
-
+
//run kernel
const bool USE_BRUTE_FORCE_RAYCAST = false;
- if(USE_BRUTE_FORCE_RAYCAST)
+ if (USE_BRUTE_FORCE_RAYCAST)
{
B3_PROFILE("raycast launch1D");
- b3LauncherCL launcher(m_data->m_q,m_data->m_raytraceKernel,"m_raytraceKernel");
+ b3LauncherCL launcher(m_data->m_q, m_data->m_raytraceKernel, "m_raytraceKernel");
int numRays = rays.size();
launcher.setConst(numRays);
@@ -299,93 +287,88 @@ void b3GpuRaycast::castRays(const b3AlignedObjectArray<b3RayInfo>& rays, b3Align
launcher.setBuffer(narrowphaseData->m_collidablesGPU->getBufferCL());
launcher.setBuffer(narrowphaseData->m_convexFacesGPU->getBufferCL());
launcher.setBuffer(narrowphaseData->m_convexPolyhedraGPU->getBufferCL());
-
+
launcher.launch1D(numRays);
clFinish(m_data->m_q);
}
else
{
- m_data->m_plbvh->build( broadphase->getAllAabbsGPU(), broadphase->getSmallAabbIndicesGPU(), broadphase->getLargeAabbIndicesGPU() );
+ m_data->m_plbvh->build(broadphase->getAllAabbsGPU(), broadphase->getSmallAabbIndicesGPU(), broadphase->getLargeAabbIndicesGPU());
m_data->m_plbvh->testRaysAgainstBvhAabbs(*m_data->m_gpuRays, *m_data->m_gpuNumRayRigidPairs, *m_data->m_gpuRayRigidPairs);
-
+
int numRayRigidPairs = -1;
m_data->m_gpuNumRayRigidPairs->copyToHostPointer(&numRayRigidPairs, 1);
- if( numRayRigidPairs > m_data->m_gpuRayRigidPairs->size() )
+ if (numRayRigidPairs > m_data->m_gpuRayRigidPairs->size())
{
numRayRigidPairs = m_data->m_gpuRayRigidPairs->size();
m_data->m_gpuNumRayRigidPairs->copyFromHostPointer(&numRayRigidPairs, 1);
}
-
- m_data->m_gpuRayRigidPairs->resize(numRayRigidPairs); //Radix sort needs b3OpenCLArray::size() to be correct
-
+
+ m_data->m_gpuRayRigidPairs->resize(numRayRigidPairs); //Radix sort needs b3OpenCLArray::size() to be correct
+
//Sort ray-rigid pairs by ray index
{
B3_PROFILE("sort ray-rigid pairs");
- m_data->m_radixSorter->execute( *reinterpret_cast< b3OpenCLArray<b3SortData>* >(m_data->m_gpuRayRigidPairs) );
+ m_data->m_radixSorter->execute(*reinterpret_cast<b3OpenCLArray<b3SortData>*>(m_data->m_gpuRayRigidPairs));
}
-
+
//detect start,count of each ray pair
{
B3_PROFILE("detect ray-rigid pair index ranges");
-
+
{
B3_PROFILE("reset ray-rigid pair index ranges");
-
- m_data->m_fill->execute(*m_data->m_firstRayRigidPairIndexPerRay, numRayRigidPairs, numRays); //atomic_min used to find first index
+
+ m_data->m_fill->execute(*m_data->m_firstRayRigidPairIndexPerRay, numRayRigidPairs, numRays); //atomic_min used to find first index
m_data->m_fill->execute(*m_data->m_numRayRigidPairsPerRay, 0, numRays);
clFinish(m_data->m_q);
}
-
- b3BufferInfoCL bufferInfo[] =
- {
- b3BufferInfoCL( m_data->m_gpuRayRigidPairs->getBufferCL() ),
-
- b3BufferInfoCL( m_data->m_firstRayRigidPairIndexPerRay->getBufferCL() ),
- b3BufferInfoCL( m_data->m_numRayRigidPairsPerRay->getBufferCL() )
- };
-
+
+ b3BufferInfoCL bufferInfo[] =
+ {
+ b3BufferInfoCL(m_data->m_gpuRayRigidPairs->getBufferCL()),
+
+ b3BufferInfoCL(m_data->m_firstRayRigidPairIndexPerRay->getBufferCL()),
+ b3BufferInfoCL(m_data->m_numRayRigidPairsPerRay->getBufferCL())};
+
b3LauncherCL launcher(m_data->m_q, m_data->m_findRayRigidPairIndexRanges, "m_findRayRigidPairIndexRanges");
- launcher.setBuffers( bufferInfo, sizeof(bufferInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
launcher.setConst(numRayRigidPairs);
-
+
launcher.launch1D(numRayRigidPairs);
clFinish(m_data->m_q);
}
-
+
{
B3_PROFILE("ray-rigid intersection");
-
- b3BufferInfoCL bufferInfo[] =
- {
- b3BufferInfoCL( m_data->m_gpuRays->getBufferCL() ),
- b3BufferInfoCL( m_data->m_gpuHitResults->getBufferCL() ),
- b3BufferInfoCL( m_data->m_firstRayRigidPairIndexPerRay->getBufferCL() ),
- b3BufferInfoCL( m_data->m_numRayRigidPairsPerRay->getBufferCL() ),
-
- b3BufferInfoCL( narrowphaseData->m_bodyBufferGPU->getBufferCL() ),
- b3BufferInfoCL( narrowphaseData->m_collidablesGPU->getBufferCL() ),
- b3BufferInfoCL( narrowphaseData->m_convexFacesGPU->getBufferCL() ),
- b3BufferInfoCL( narrowphaseData->m_convexPolyhedraGPU->getBufferCL() ),
-
- b3BufferInfoCL( m_data->m_gpuRayRigidPairs->getBufferCL() )
- };
-
+
+ b3BufferInfoCL bufferInfo[] =
+ {
+ b3BufferInfoCL(m_data->m_gpuRays->getBufferCL()),
+ b3BufferInfoCL(m_data->m_gpuHitResults->getBufferCL()),
+ b3BufferInfoCL(m_data->m_firstRayRigidPairIndexPerRay->getBufferCL()),
+ b3BufferInfoCL(m_data->m_numRayRigidPairsPerRay->getBufferCL()),
+
+ b3BufferInfoCL(narrowphaseData->m_bodyBufferGPU->getBufferCL()),
+ b3BufferInfoCL(narrowphaseData->m_collidablesGPU->getBufferCL()),
+ b3BufferInfoCL(narrowphaseData->m_convexFacesGPU->getBufferCL()),
+ b3BufferInfoCL(narrowphaseData->m_convexPolyhedraGPU->getBufferCL()),
+
+ b3BufferInfoCL(m_data->m_gpuRayRigidPairs->getBufferCL())};
+
b3LauncherCL launcher(m_data->m_q, m_data->m_raytracePairsKernel, "m_raytracePairsKernel");
- launcher.setBuffers( bufferInfo, sizeof(bufferInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
launcher.setConst(numRays);
-
+
launcher.launch1D(numRays);
clFinish(m_data->m_q);
}
}
-
-
//copy results
{
B3_PROFILE("raycast copyToHost");
m_data->m_gpuHitResults->copyToHost(hitResults);
}
-
} \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3OpenCL/Raycast/b3GpuRaycast.h b/thirdparty/bullet/Bullet3OpenCL/Raycast/b3GpuRaycast.h
index 3a5cf44b79..f1f6ffd402 100644
--- a/thirdparty/bullet/Bullet3OpenCL/Raycast/b3GpuRaycast.h
+++ b/thirdparty/bullet/Bullet3OpenCL/Raycast/b3GpuRaycast.h
@@ -7,26 +7,22 @@
#include "Bullet3Common/b3AlignedObjectArray.h"
#include "Bullet3Collision/NarrowPhaseCollision/b3RaycastInfo.h"
-
-
class b3GpuRaycast
{
protected:
struct b3GpuRaycastInternalData* m_data;
+
public:
- b3GpuRaycast(cl_context ctx,cl_device_id device, cl_command_queue q);
+ b3GpuRaycast(cl_context ctx, cl_device_id device, cl_command_queue q);
virtual ~b3GpuRaycast();
- void castRaysHost(const b3AlignedObjectArray<b3RayInfo>& raysIn, b3AlignedObjectArray<b3RayHit>& hitResults,
- int numBodies, const struct b3RigidBodyData* bodies, int numCollidables, const struct b3Collidable* collidables,
- const struct b3GpuNarrowPhaseInternalData* narrowphaseData);
-
- void castRays(const b3AlignedObjectArray<b3RayInfo>& rays, b3AlignedObjectArray<b3RayHit>& hitResults,
- int numBodies,const struct b3RigidBodyData* bodies, int numCollidables, const struct b3Collidable* collidables,
- const struct b3GpuNarrowPhaseInternalData* narrowphaseData, class b3GpuBroadphaseInterface* broadphase);
-
+ void castRaysHost(const b3AlignedObjectArray<b3RayInfo>& raysIn, b3AlignedObjectArray<b3RayHit>& hitResults,
+ int numBodies, const struct b3RigidBodyData* bodies, int numCollidables, const struct b3Collidable* collidables,
+ const struct b3GpuNarrowPhaseInternalData* narrowphaseData);
-
+ void castRays(const b3AlignedObjectArray<b3RayInfo>& rays, b3AlignedObjectArray<b3RayHit>& hitResults,
+ int numBodies, const struct b3RigidBodyData* bodies, int numCollidables, const struct b3Collidable* collidables,
+ const struct b3GpuNarrowPhaseInternalData* narrowphaseData, class b3GpuBroadphaseInterface* broadphase);
};
-#endif //B3_GPU_RAYCAST_H
+#endif //B3_GPU_RAYCAST_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/Raycast/kernels/rayCastKernels.h b/thirdparty/bullet/Bullet3OpenCL/Raycast/kernels/rayCastKernels.h
index 6257909a4d..94f6a8eb9f 100644
--- a/thirdparty/bullet/Bullet3OpenCL/Raycast/kernels/rayCastKernels.h
+++ b/thirdparty/bullet/Bullet3OpenCL/Raycast/kernels/rayCastKernels.h
@@ -1,381 +1,380 @@
//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* rayCastKernelCL= \
-"#define SHAPE_CONVEX_HULL 3\n"
-"#define SHAPE_PLANE 4\n"
-"#define SHAPE_CONCAVE_TRIMESH 5\n"
-"#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6\n"
-"#define SHAPE_SPHERE 7\n"
-"typedef struct\n"
-"{\n"
-" float4 m_from;\n"
-" float4 m_to;\n"
-"} b3RayInfo;\n"
-"typedef struct\n"
-"{\n"
-" float m_hitFraction;\n"
-" int m_hitResult0;\n"
-" int m_hitResult1;\n"
-" int m_hitResult2;\n"
-" float4 m_hitPoint;\n"
-" float4 m_hitNormal;\n"
-"} b3RayHit;\n"
-"typedef struct\n"
-"{\n"
-" float4 m_pos;\n"
-" float4 m_quat;\n"
-" float4 m_linVel;\n"
-" float4 m_angVel;\n"
-" unsigned int m_collidableIdx;\n"
-" float m_invMass;\n"
-" float m_restituitionCoeff;\n"
-" float m_frictionCoeff;\n"
-"} Body;\n"
-"typedef struct Collidable\n"
-"{\n"
-" union {\n"
-" int m_numChildShapes;\n"
-" int m_bvhIndex;\n"
-" };\n"
-" float m_radius;\n"
-" int m_shapeType;\n"
-" int m_shapeIndex;\n"
-"} Collidable;\n"
-"typedef struct \n"
-"{\n"
-" float4 m_localCenter;\n"
-" float4 m_extents;\n"
-" float4 mC;\n"
-" float4 mE;\n"
-" float m_radius;\n"
-" int m_faceOffset;\n"
-" int m_numFaces;\n"
-" int m_numVertices;\n"
-" int m_vertexOffset;\n"
-" int m_uniqueEdgesOffset;\n"
-" int m_numUniqueEdges;\n"
-" int m_unused;\n"
-"} ConvexPolyhedronCL;\n"
-"typedef struct\n"
-"{\n"
-" float4 m_plane;\n"
-" int m_indexOffset;\n"
-" int m_numIndices;\n"
-"} b3GpuFace;\n"
-"///////////////////////////////////////\n"
-"// Quaternion\n"
-"///////////////////////////////////////\n"
-"typedef float4 Quaternion;\n"
-"__inline\n"
-" Quaternion qtMul(Quaternion a, Quaternion b);\n"
-"__inline\n"
-" Quaternion qtNormalize(Quaternion in);\n"
-"__inline\n"
-" Quaternion qtInvert(Quaternion q);\n"
-"__inline\n"
-" float dot3F4(float4 a, float4 b)\n"
-"{\n"
-" float4 a1 = (float4)(a.xyz,0.f);\n"
-" float4 b1 = (float4)(b.xyz,0.f);\n"
-" return dot(a1, b1);\n"
-"}\n"
-"__inline\n"
-" Quaternion qtMul(Quaternion a, Quaternion b)\n"
-"{\n"
-" Quaternion ans;\n"
-" ans = cross( a, b );\n"
-" ans += a.w*b+b.w*a;\n"
-" // ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
-" ans.w = a.w*b.w - dot3F4(a, b);\n"
-" return ans;\n"
-"}\n"
-"__inline\n"
-" Quaternion qtNormalize(Quaternion in)\n"
-"{\n"
-" return fast_normalize(in);\n"
-" // in /= length( in );\n"
-" // return in;\n"
-"}\n"
-"__inline\n"
-" float4 qtRotate(Quaternion q, float4 vec)\n"
-"{\n"
-" Quaternion qInv = qtInvert( q );\n"
-" float4 vcpy = vec;\n"
-" vcpy.w = 0.f;\n"
-" float4 out = qtMul(q,vcpy);\n"
-" out = qtMul(out,qInv);\n"
-" return out;\n"
-"}\n"
-"__inline\n"
-" Quaternion qtInvert(Quaternion q)\n"
-"{\n"
-" return (Quaternion)(-q.xyz, q.w);\n"
-"}\n"
-"__inline\n"
-" float4 qtInvRotate(const Quaternion q, float4 vec)\n"
-"{\n"
-" return qtRotate( qtInvert( q ), vec );\n"
-"}\n"
-"void trInverse(float4 translationIn, Quaternion orientationIn,\n"
-" float4* translationOut, Quaternion* orientationOut)\n"
-"{\n"
-" *orientationOut = qtInvert(orientationIn);\n"
-" *translationOut = qtRotate(*orientationOut, -translationIn);\n"
-"}\n"
-"bool rayConvex(float4 rayFromLocal, float4 rayToLocal, int numFaces, int faceOffset,\n"
-" __global const b3GpuFace* faces, float* hitFraction, float4* hitNormal)\n"
-"{\n"
-" rayFromLocal.w = 0.f;\n"
-" rayToLocal.w = 0.f;\n"
-" bool result = true;\n"
-" float exitFraction = hitFraction[0];\n"
-" float enterFraction = -0.3f;\n"
-" float4 curHitNormal = (float4)(0,0,0,0);\n"
-" for (int i=0;i<numFaces && result;i++)\n"
-" {\n"
-" b3GpuFace face = faces[faceOffset+i];\n"
-" float fromPlaneDist = dot(rayFromLocal,face.m_plane)+face.m_plane.w;\n"
-" float toPlaneDist = dot(rayToLocal,face.m_plane)+face.m_plane.w;\n"
-" if (fromPlaneDist<0.f)\n"
-" {\n"
-" if (toPlaneDist >= 0.f)\n"
-" {\n"
-" float fraction = fromPlaneDist / (fromPlaneDist-toPlaneDist);\n"
-" if (exitFraction>fraction)\n"
-" {\n"
-" exitFraction = fraction;\n"
-" }\n"
-" } \n"
-" } else\n"
-" {\n"
-" if (toPlaneDist<0.f)\n"
-" {\n"
-" float fraction = fromPlaneDist / (fromPlaneDist-toPlaneDist);\n"
-" if (enterFraction <= fraction)\n"
-" {\n"
-" enterFraction = fraction;\n"
-" curHitNormal = face.m_plane;\n"
-" curHitNormal.w = 0.f;\n"
-" }\n"
-" } else\n"
-" {\n"
-" result = false;\n"
-" }\n"
-" }\n"
-" if (exitFraction <= enterFraction)\n"
-" result = false;\n"
-" }\n"
-" if (enterFraction < 0.f)\n"
-" {\n"
-" result = false;\n"
-" }\n"
-" if (result)\n"
-" { \n"
-" hitFraction[0] = enterFraction;\n"
-" hitNormal[0] = curHitNormal;\n"
-" }\n"
-" return result;\n"
-"}\n"
-"bool sphere_intersect(float4 spherePos, float radius, float4 rayFrom, float4 rayTo, float* hitFraction)\n"
-"{\n"
-" float4 rs = rayFrom - spherePos;\n"
-" rs.w = 0.f;\n"
-" float4 rayDir = rayTo-rayFrom;\n"
-" rayDir.w = 0.f;\n"
-" float A = dot(rayDir,rayDir);\n"
-" float B = dot(rs, rayDir);\n"
-" float C = dot(rs, rs) - (radius * radius);\n"
-" float D = B * B - A*C;\n"
-" if (D > 0.0f)\n"
-" {\n"
-" float t = (-B - sqrt(D))/A;\n"
-" if ( (t >= 0.0f) && (t < (*hitFraction)) )\n"
-" {\n"
-" *hitFraction = t;\n"
-" return true;\n"
-" }\n"
-" }\n"
-" return false;\n"
-"}\n"
-"float4 setInterpolate3(float4 from, float4 to, float t)\n"
-"{\n"
-" float s = 1.0f - t;\n"
-" float4 result;\n"
-" result = s * from + t * to;\n"
-" result.w = 0.f; \n"
-" return result; \n"
-"}\n"
-"__kernel void rayCastKernel( \n"
-" int numRays, \n"
-" const __global b3RayInfo* rays, \n"
-" __global b3RayHit* hitResults, \n"
-" const int numBodies, \n"
-" __global Body* bodies,\n"
-" __global Collidable* collidables,\n"
-" __global const b3GpuFace* faces,\n"
-" __global const ConvexPolyhedronCL* convexShapes )\n"
-"{\n"
-" int i = get_global_id(0);\n"
-" if (i>=numRays)\n"
-" return;\n"
-" hitResults[i].m_hitFraction = 1.f;\n"
-" float4 rayFrom = rays[i].m_from;\n"
-" float4 rayTo = rays[i].m_to;\n"
-" float hitFraction = 1.f;\n"
-" float4 hitPoint;\n"
-" float4 hitNormal;\n"
-" int hitBodyIndex= -1;\n"
-" int cachedCollidableIndex = -1;\n"
-" Collidable cachedCollidable;\n"
-" for (int b=0;b<numBodies;b++)\n"
-" {\n"
-" if (hitResults[i].m_hitResult2==b)\n"
-" continue;\n"
-" Body body = bodies[b];\n"
-" float4 pos = body.m_pos;\n"
-" float4 orn = body.m_quat;\n"
-" if (cachedCollidableIndex != body.m_collidableIdx)\n"
-" {\n"
-" cachedCollidableIndex = body.m_collidableIdx;\n"
-" cachedCollidable = collidables[cachedCollidableIndex];\n"
-" }\n"
-" if (cachedCollidable.m_shapeType == SHAPE_CONVEX_HULL)\n"
-" {\n"
-" float4 invPos = (float4)(0,0,0,0);\n"
-" float4 invOrn = (float4)(0,0,0,0);\n"
-" float4 rayFromLocal = (float4)(0,0,0,0);\n"
-" float4 rayToLocal = (float4)(0,0,0,0);\n"
-" invOrn = qtInvert(orn);\n"
-" invPos = qtRotate(invOrn, -pos);\n"
-" rayFromLocal = qtRotate( invOrn, rayFrom ) + invPos;\n"
-" rayToLocal = qtRotate( invOrn, rayTo) + invPos;\n"
-" rayFromLocal.w = 0.f;\n"
-" rayToLocal.w = 0.f;\n"
-" int numFaces = convexShapes[cachedCollidable.m_shapeIndex].m_numFaces;\n"
-" int faceOffset = convexShapes[cachedCollidable.m_shapeIndex].m_faceOffset;\n"
-" if (numFaces)\n"
-" {\n"
-" if (rayConvex(rayFromLocal, rayToLocal, numFaces, faceOffset,faces, &hitFraction, &hitNormal))\n"
-" {\n"
-" hitBodyIndex = b;\n"
-" \n"
-" }\n"
-" }\n"
-" }\n"
-" if (cachedCollidable.m_shapeType == SHAPE_SPHERE)\n"
-" {\n"
-" float radius = cachedCollidable.m_radius;\n"
-" \n"
-" if (sphere_intersect(pos, radius, rayFrom, rayTo, &hitFraction))\n"
-" {\n"
-" hitBodyIndex = b;\n"
-" hitNormal = (float4) (hitPoint-bodies[b].m_pos);\n"
-" }\n"
-" }\n"
-" }\n"
-" if (hitBodyIndex>=0)\n"
-" {\n"
-" hitPoint = setInterpolate3(rayFrom, rayTo,hitFraction);\n"
-" hitResults[i].m_hitFraction = hitFraction;\n"
-" hitResults[i].m_hitPoint = hitPoint;\n"
-" hitResults[i].m_hitNormal = normalize(hitNormal);\n"
-" hitResults[i].m_hitResult0 = hitBodyIndex;\n"
-" }\n"
-"}\n"
-"__kernel void findRayRigidPairIndexRanges(__global int2* rayRigidPairs, \n"
-" __global int* out_firstRayRigidPairIndexPerRay,\n"
-" __global int* out_numRayRigidPairsPerRay,\n"
-" int numRayRigidPairs)\n"
-"{\n"
-" int rayRigidPairIndex = get_global_id(0);\n"
-" if (rayRigidPairIndex >= numRayRigidPairs) return;\n"
-" \n"
-" int rayIndex = rayRigidPairs[rayRigidPairIndex].x;\n"
-" \n"
-" atomic_min(&out_firstRayRigidPairIndexPerRay[rayIndex], rayRigidPairIndex);\n"
-" atomic_inc(&out_numRayRigidPairsPerRay[rayIndex]);\n"
-"}\n"
-"__kernel void rayCastPairsKernel(const __global b3RayInfo* rays, \n"
-" __global b3RayHit* hitResults, \n"
-" __global int* firstRayRigidPairIndexPerRay,\n"
-" __global int* numRayRigidPairsPerRay,\n"
-" \n"
-" __global Body* bodies,\n"
-" __global Collidable* collidables,\n"
-" __global const b3GpuFace* faces,\n"
-" __global const ConvexPolyhedronCL* convexShapes,\n"
-" \n"
-" __global int2* rayRigidPairs,\n"
-" int numRays)\n"
-"{\n"
-" int i = get_global_id(0);\n"
-" if (i >= numRays) return;\n"
-" \n"
-" float4 rayFrom = rays[i].m_from;\n"
-" float4 rayTo = rays[i].m_to;\n"
-" \n"
-" hitResults[i].m_hitFraction = 1.f;\n"
-" \n"
-" float hitFraction = 1.f;\n"
-" float4 hitPoint;\n"
-" float4 hitNormal;\n"
-" int hitBodyIndex = -1;\n"
-" \n"
-" //\n"
-" for(int pair = 0; pair < numRayRigidPairsPerRay[i]; ++pair)\n"
-" {\n"
-" int rayRigidPairIndex = pair + firstRayRigidPairIndexPerRay[i];\n"
-" int b = rayRigidPairs[rayRigidPairIndex].y;\n"
-" \n"
-" if (hitResults[i].m_hitResult2 == b) continue;\n"
-" \n"
-" Body body = bodies[b];\n"
-" Collidable rigidCollidable = collidables[body.m_collidableIdx];\n"
-" \n"
-" float4 pos = body.m_pos;\n"
-" float4 orn = body.m_quat;\n"
-" \n"
-" if (rigidCollidable.m_shapeType == SHAPE_CONVEX_HULL)\n"
-" {\n"
-" float4 invPos = (float4)(0,0,0,0);\n"
-" float4 invOrn = (float4)(0,0,0,0);\n"
-" float4 rayFromLocal = (float4)(0,0,0,0);\n"
-" float4 rayToLocal = (float4)(0,0,0,0);\n"
-" invOrn = qtInvert(orn);\n"
-" invPos = qtRotate(invOrn, -pos);\n"
-" rayFromLocal = qtRotate( invOrn, rayFrom ) + invPos;\n"
-" rayToLocal = qtRotate( invOrn, rayTo) + invPos;\n"
-" rayFromLocal.w = 0.f;\n"
-" rayToLocal.w = 0.f;\n"
-" int numFaces = convexShapes[rigidCollidable.m_shapeIndex].m_numFaces;\n"
-" int faceOffset = convexShapes[rigidCollidable.m_shapeIndex].m_faceOffset;\n"
-" \n"
-" if (numFaces && rayConvex(rayFromLocal, rayToLocal, numFaces, faceOffset,faces, &hitFraction, &hitNormal))\n"
-" {\n"
-" hitBodyIndex = b;\n"
-" hitPoint = setInterpolate3(rayFrom, rayTo, hitFraction);\n"
-" }\n"
-" }\n"
-" \n"
-" if (rigidCollidable.m_shapeType == SHAPE_SPHERE)\n"
-" {\n"
-" float radius = rigidCollidable.m_radius;\n"
-" \n"
-" if (sphere_intersect(pos, radius, rayFrom, rayTo, &hitFraction))\n"
-" {\n"
-" hitBodyIndex = b;\n"
-" hitPoint = setInterpolate3(rayFrom, rayTo, hitFraction);\n"
-" hitNormal = (float4) (hitPoint - bodies[b].m_pos);\n"
-" }\n"
-" }\n"
-" }\n"
-" \n"
-" if (hitBodyIndex >= 0)\n"
-" {\n"
-" hitResults[i].m_hitFraction = hitFraction;\n"
-" hitResults[i].m_hitPoint = hitPoint;\n"
-" hitResults[i].m_hitNormal = normalize(hitNormal);\n"
-" hitResults[i].m_hitResult0 = hitBodyIndex;\n"
-" }\n"
-" \n"
-"}\n"
-;
+static const char* rayCastKernelCL =
+ "#define SHAPE_CONVEX_HULL 3\n"
+ "#define SHAPE_PLANE 4\n"
+ "#define SHAPE_CONCAVE_TRIMESH 5\n"
+ "#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6\n"
+ "#define SHAPE_SPHERE 7\n"
+ "typedef struct\n"
+ "{\n"
+ " float4 m_from;\n"
+ " float4 m_to;\n"
+ "} b3RayInfo;\n"
+ "typedef struct\n"
+ "{\n"
+ " float m_hitFraction;\n"
+ " int m_hitResult0;\n"
+ " int m_hitResult1;\n"
+ " int m_hitResult2;\n"
+ " float4 m_hitPoint;\n"
+ " float4 m_hitNormal;\n"
+ "} b3RayHit;\n"
+ "typedef struct\n"
+ "{\n"
+ " float4 m_pos;\n"
+ " float4 m_quat;\n"
+ " float4 m_linVel;\n"
+ " float4 m_angVel;\n"
+ " unsigned int m_collidableIdx;\n"
+ " float m_invMass;\n"
+ " float m_restituitionCoeff;\n"
+ " float m_frictionCoeff;\n"
+ "} Body;\n"
+ "typedef struct Collidable\n"
+ "{\n"
+ " union {\n"
+ " int m_numChildShapes;\n"
+ " int m_bvhIndex;\n"
+ " };\n"
+ " float m_radius;\n"
+ " int m_shapeType;\n"
+ " int m_shapeIndex;\n"
+ "} Collidable;\n"
+ "typedef struct \n"
+ "{\n"
+ " float4 m_localCenter;\n"
+ " float4 m_extents;\n"
+ " float4 mC;\n"
+ " float4 mE;\n"
+ " float m_radius;\n"
+ " int m_faceOffset;\n"
+ " int m_numFaces;\n"
+ " int m_numVertices;\n"
+ " int m_vertexOffset;\n"
+ " int m_uniqueEdgesOffset;\n"
+ " int m_numUniqueEdges;\n"
+ " int m_unused;\n"
+ "} ConvexPolyhedronCL;\n"
+ "typedef struct\n"
+ "{\n"
+ " float4 m_plane;\n"
+ " int m_indexOffset;\n"
+ " int m_numIndices;\n"
+ "} b3GpuFace;\n"
+ "///////////////////////////////////////\n"
+ "// Quaternion\n"
+ "///////////////////////////////////////\n"
+ "typedef float4 Quaternion;\n"
+ "__inline\n"
+ " Quaternion qtMul(Quaternion a, Quaternion b);\n"
+ "__inline\n"
+ " Quaternion qtNormalize(Quaternion in);\n"
+ "__inline\n"
+ " Quaternion qtInvert(Quaternion q);\n"
+ "__inline\n"
+ " float dot3F4(float4 a, float4 b)\n"
+ "{\n"
+ " float4 a1 = (float4)(a.xyz,0.f);\n"
+ " float4 b1 = (float4)(b.xyz,0.f);\n"
+ " return dot(a1, b1);\n"
+ "}\n"
+ "__inline\n"
+ " Quaternion qtMul(Quaternion a, Quaternion b)\n"
+ "{\n"
+ " Quaternion ans;\n"
+ " ans = cross( a, b );\n"
+ " ans += a.w*b+b.w*a;\n"
+ " // ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+ " ans.w = a.w*b.w - dot3F4(a, b);\n"
+ " return ans;\n"
+ "}\n"
+ "__inline\n"
+ " Quaternion qtNormalize(Quaternion in)\n"
+ "{\n"
+ " return fast_normalize(in);\n"
+ " // in /= length( in );\n"
+ " // return in;\n"
+ "}\n"
+ "__inline\n"
+ " float4 qtRotate(Quaternion q, float4 vec)\n"
+ "{\n"
+ " Quaternion qInv = qtInvert( q );\n"
+ " float4 vcpy = vec;\n"
+ " vcpy.w = 0.f;\n"
+ " float4 out = qtMul(q,vcpy);\n"
+ " out = qtMul(out,qInv);\n"
+ " return out;\n"
+ "}\n"
+ "__inline\n"
+ " Quaternion qtInvert(Quaternion q)\n"
+ "{\n"
+ " return (Quaternion)(-q.xyz, q.w);\n"
+ "}\n"
+ "__inline\n"
+ " float4 qtInvRotate(const Quaternion q, float4 vec)\n"
+ "{\n"
+ " return qtRotate( qtInvert( q ), vec );\n"
+ "}\n"
+ "void trInverse(float4 translationIn, Quaternion orientationIn,\n"
+ " float4* translationOut, Quaternion* orientationOut)\n"
+ "{\n"
+ " *orientationOut = qtInvert(orientationIn);\n"
+ " *translationOut = qtRotate(*orientationOut, -translationIn);\n"
+ "}\n"
+ "bool rayConvex(float4 rayFromLocal, float4 rayToLocal, int numFaces, int faceOffset,\n"
+ " __global const b3GpuFace* faces, float* hitFraction, float4* hitNormal)\n"
+ "{\n"
+ " rayFromLocal.w = 0.f;\n"
+ " rayToLocal.w = 0.f;\n"
+ " bool result = true;\n"
+ " float exitFraction = hitFraction[0];\n"
+ " float enterFraction = -0.3f;\n"
+ " float4 curHitNormal = (float4)(0,0,0,0);\n"
+ " for (int i=0;i<numFaces && result;i++)\n"
+ " {\n"
+ " b3GpuFace face = faces[faceOffset+i];\n"
+ " float fromPlaneDist = dot(rayFromLocal,face.m_plane)+face.m_plane.w;\n"
+ " float toPlaneDist = dot(rayToLocal,face.m_plane)+face.m_plane.w;\n"
+ " if (fromPlaneDist<0.f)\n"
+ " {\n"
+ " if (toPlaneDist >= 0.f)\n"
+ " {\n"
+ " float fraction = fromPlaneDist / (fromPlaneDist-toPlaneDist);\n"
+ " if (exitFraction>fraction)\n"
+ " {\n"
+ " exitFraction = fraction;\n"
+ " }\n"
+ " } \n"
+ " } else\n"
+ " {\n"
+ " if (toPlaneDist<0.f)\n"
+ " {\n"
+ " float fraction = fromPlaneDist / (fromPlaneDist-toPlaneDist);\n"
+ " if (enterFraction <= fraction)\n"
+ " {\n"
+ " enterFraction = fraction;\n"
+ " curHitNormal = face.m_plane;\n"
+ " curHitNormal.w = 0.f;\n"
+ " }\n"
+ " } else\n"
+ " {\n"
+ " result = false;\n"
+ " }\n"
+ " }\n"
+ " if (exitFraction <= enterFraction)\n"
+ " result = false;\n"
+ " }\n"
+ " if (enterFraction < 0.f)\n"
+ " {\n"
+ " result = false;\n"
+ " }\n"
+ " if (result)\n"
+ " { \n"
+ " hitFraction[0] = enterFraction;\n"
+ " hitNormal[0] = curHitNormal;\n"
+ " }\n"
+ " return result;\n"
+ "}\n"
+ "bool sphere_intersect(float4 spherePos, float radius, float4 rayFrom, float4 rayTo, float* hitFraction)\n"
+ "{\n"
+ " float4 rs = rayFrom - spherePos;\n"
+ " rs.w = 0.f;\n"
+ " float4 rayDir = rayTo-rayFrom;\n"
+ " rayDir.w = 0.f;\n"
+ " float A = dot(rayDir,rayDir);\n"
+ " float B = dot(rs, rayDir);\n"
+ " float C = dot(rs, rs) - (radius * radius);\n"
+ " float D = B * B - A*C;\n"
+ " if (D > 0.0f)\n"
+ " {\n"
+ " float t = (-B - sqrt(D))/A;\n"
+ " if ( (t >= 0.0f) && (t < (*hitFraction)) )\n"
+ " {\n"
+ " *hitFraction = t;\n"
+ " return true;\n"
+ " }\n"
+ " }\n"
+ " return false;\n"
+ "}\n"
+ "float4 setInterpolate3(float4 from, float4 to, float t)\n"
+ "{\n"
+ " float s = 1.0f - t;\n"
+ " float4 result;\n"
+ " result = s * from + t * to;\n"
+ " result.w = 0.f; \n"
+ " return result; \n"
+ "}\n"
+ "__kernel void rayCastKernel( \n"
+ " int numRays, \n"
+ " const __global b3RayInfo* rays, \n"
+ " __global b3RayHit* hitResults, \n"
+ " const int numBodies, \n"
+ " __global Body* bodies,\n"
+ " __global Collidable* collidables,\n"
+ " __global const b3GpuFace* faces,\n"
+ " __global const ConvexPolyhedronCL* convexShapes )\n"
+ "{\n"
+ " int i = get_global_id(0);\n"
+ " if (i>=numRays)\n"
+ " return;\n"
+ " hitResults[i].m_hitFraction = 1.f;\n"
+ " float4 rayFrom = rays[i].m_from;\n"
+ " float4 rayTo = rays[i].m_to;\n"
+ " float hitFraction = 1.f;\n"
+ " float4 hitPoint;\n"
+ " float4 hitNormal;\n"
+ " int hitBodyIndex= -1;\n"
+ " int cachedCollidableIndex = -1;\n"
+ " Collidable cachedCollidable;\n"
+ " for (int b=0;b<numBodies;b++)\n"
+ " {\n"
+ " if (hitResults[i].m_hitResult2==b)\n"
+ " continue;\n"
+ " Body body = bodies[b];\n"
+ " float4 pos = body.m_pos;\n"
+ " float4 orn = body.m_quat;\n"
+ " if (cachedCollidableIndex != body.m_collidableIdx)\n"
+ " {\n"
+ " cachedCollidableIndex = body.m_collidableIdx;\n"
+ " cachedCollidable = collidables[cachedCollidableIndex];\n"
+ " }\n"
+ " if (cachedCollidable.m_shapeType == SHAPE_CONVEX_HULL)\n"
+ " {\n"
+ " float4 invPos = (float4)(0,0,0,0);\n"
+ " float4 invOrn = (float4)(0,0,0,0);\n"
+ " float4 rayFromLocal = (float4)(0,0,0,0);\n"
+ " float4 rayToLocal = (float4)(0,0,0,0);\n"
+ " invOrn = qtInvert(orn);\n"
+ " invPos = qtRotate(invOrn, -pos);\n"
+ " rayFromLocal = qtRotate( invOrn, rayFrom ) + invPos;\n"
+ " rayToLocal = qtRotate( invOrn, rayTo) + invPos;\n"
+ " rayFromLocal.w = 0.f;\n"
+ " rayToLocal.w = 0.f;\n"
+ " int numFaces = convexShapes[cachedCollidable.m_shapeIndex].m_numFaces;\n"
+ " int faceOffset = convexShapes[cachedCollidable.m_shapeIndex].m_faceOffset;\n"
+ " if (numFaces)\n"
+ " {\n"
+ " if (rayConvex(rayFromLocal, rayToLocal, numFaces, faceOffset,faces, &hitFraction, &hitNormal))\n"
+ " {\n"
+ " hitBodyIndex = b;\n"
+ " \n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " if (cachedCollidable.m_shapeType == SHAPE_SPHERE)\n"
+ " {\n"
+ " float radius = cachedCollidable.m_radius;\n"
+ " \n"
+ " if (sphere_intersect(pos, radius, rayFrom, rayTo, &hitFraction))\n"
+ " {\n"
+ " hitBodyIndex = b;\n"
+ " hitNormal = (float4) (hitPoint-bodies[b].m_pos);\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " if (hitBodyIndex>=0)\n"
+ " {\n"
+ " hitPoint = setInterpolate3(rayFrom, rayTo,hitFraction);\n"
+ " hitResults[i].m_hitFraction = hitFraction;\n"
+ " hitResults[i].m_hitPoint = hitPoint;\n"
+ " hitResults[i].m_hitNormal = normalize(hitNormal);\n"
+ " hitResults[i].m_hitResult0 = hitBodyIndex;\n"
+ " }\n"
+ "}\n"
+ "__kernel void findRayRigidPairIndexRanges(__global int2* rayRigidPairs, \n"
+ " __global int* out_firstRayRigidPairIndexPerRay,\n"
+ " __global int* out_numRayRigidPairsPerRay,\n"
+ " int numRayRigidPairs)\n"
+ "{\n"
+ " int rayRigidPairIndex = get_global_id(0);\n"
+ " if (rayRigidPairIndex >= numRayRigidPairs) return;\n"
+ " \n"
+ " int rayIndex = rayRigidPairs[rayRigidPairIndex].x;\n"
+ " \n"
+ " atomic_min(&out_firstRayRigidPairIndexPerRay[rayIndex], rayRigidPairIndex);\n"
+ " atomic_inc(&out_numRayRigidPairsPerRay[rayIndex]);\n"
+ "}\n"
+ "__kernel void rayCastPairsKernel(const __global b3RayInfo* rays, \n"
+ " __global b3RayHit* hitResults, \n"
+ " __global int* firstRayRigidPairIndexPerRay,\n"
+ " __global int* numRayRigidPairsPerRay,\n"
+ " \n"
+ " __global Body* bodies,\n"
+ " __global Collidable* collidables,\n"
+ " __global const b3GpuFace* faces,\n"
+ " __global const ConvexPolyhedronCL* convexShapes,\n"
+ " \n"
+ " __global int2* rayRigidPairs,\n"
+ " int numRays)\n"
+ "{\n"
+ " int i = get_global_id(0);\n"
+ " if (i >= numRays) return;\n"
+ " \n"
+ " float4 rayFrom = rays[i].m_from;\n"
+ " float4 rayTo = rays[i].m_to;\n"
+ " \n"
+ " hitResults[i].m_hitFraction = 1.f;\n"
+ " \n"
+ " float hitFraction = 1.f;\n"
+ " float4 hitPoint;\n"
+ " float4 hitNormal;\n"
+ " int hitBodyIndex = -1;\n"
+ " \n"
+ " //\n"
+ " for(int pair = 0; pair < numRayRigidPairsPerRay[i]; ++pair)\n"
+ " {\n"
+ " int rayRigidPairIndex = pair + firstRayRigidPairIndexPerRay[i];\n"
+ " int b = rayRigidPairs[rayRigidPairIndex].y;\n"
+ " \n"
+ " if (hitResults[i].m_hitResult2 == b) continue;\n"
+ " \n"
+ " Body body = bodies[b];\n"
+ " Collidable rigidCollidable = collidables[body.m_collidableIdx];\n"
+ " \n"
+ " float4 pos = body.m_pos;\n"
+ " float4 orn = body.m_quat;\n"
+ " \n"
+ " if (rigidCollidable.m_shapeType == SHAPE_CONVEX_HULL)\n"
+ " {\n"
+ " float4 invPos = (float4)(0,0,0,0);\n"
+ " float4 invOrn = (float4)(0,0,0,0);\n"
+ " float4 rayFromLocal = (float4)(0,0,0,0);\n"
+ " float4 rayToLocal = (float4)(0,0,0,0);\n"
+ " invOrn = qtInvert(orn);\n"
+ " invPos = qtRotate(invOrn, -pos);\n"
+ " rayFromLocal = qtRotate( invOrn, rayFrom ) + invPos;\n"
+ " rayToLocal = qtRotate( invOrn, rayTo) + invPos;\n"
+ " rayFromLocal.w = 0.f;\n"
+ " rayToLocal.w = 0.f;\n"
+ " int numFaces = convexShapes[rigidCollidable.m_shapeIndex].m_numFaces;\n"
+ " int faceOffset = convexShapes[rigidCollidable.m_shapeIndex].m_faceOffset;\n"
+ " \n"
+ " if (numFaces && rayConvex(rayFromLocal, rayToLocal, numFaces, faceOffset,faces, &hitFraction, &hitNormal))\n"
+ " {\n"
+ " hitBodyIndex = b;\n"
+ " hitPoint = setInterpolate3(rayFrom, rayTo, hitFraction);\n"
+ " }\n"
+ " }\n"
+ " \n"
+ " if (rigidCollidable.m_shapeType == SHAPE_SPHERE)\n"
+ " {\n"
+ " float radius = rigidCollidable.m_radius;\n"
+ " \n"
+ " if (sphere_intersect(pos, radius, rayFrom, rayTo, &hitFraction))\n"
+ " {\n"
+ " hitBodyIndex = b;\n"
+ " hitPoint = setInterpolate3(rayFrom, rayTo, hitFraction);\n"
+ " hitNormal = (float4) (hitPoint - bodies[b].m_pos);\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " \n"
+ " if (hitBodyIndex >= 0)\n"
+ " {\n"
+ " hitResults[i].m_hitFraction = hitFraction;\n"
+ " hitResults[i].m_hitPoint = hitPoint;\n"
+ " hitResults[i].m_hitNormal = normalize(hitNormal);\n"
+ " hitResults[i].m_hitResult0 = hitBodyIndex;\n"
+ " }\n"
+ " \n"
+ "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuConstraint4.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuConstraint4.h
index c7478f54a1..89c0142ab3 100644
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuConstraint4.h
+++ b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuConstraint4.h
@@ -5,14 +5,13 @@
#include "Bullet3Dynamics/shared/b3ContactConstraint4.h"
-
-B3_ATTRIBUTE_ALIGNED16(struct) b3GpuConstraint4 : public b3ContactConstraint4
+B3_ATTRIBUTE_ALIGNED16(struct)
+b3GpuConstraint4 : public b3ContactConstraint4
{
B3_DECLARE_ALIGNED_ALLOCATOR();
- inline void setFrictionCoeff(float value) { m_linear[3] = value; }
- inline float getFrictionCoeff() const { return m_linear[3]; }
+ inline void setFrictionCoeff(float value) { m_linear[3] = value; }
+ inline float getFrictionCoeff() const { return m_linear[3]; }
};
-#endif //B3_CONSTRAINT4_h
-
+#endif //B3_CONSTRAINT4_h
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuGenericConstraint.cpp b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuGenericConstraint.cpp
index af687b54e9..a271090af4 100644
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuGenericConstraint.cpp
+++ b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuGenericConstraint.cpp
@@ -19,11 +19,11 @@ subject to the following restrictions:
#include <new>
#include "Bullet3Common/b3Transform.h"
-void b3GpuGenericConstraint::getInfo1 (unsigned int* info,const b3RigidBodyData* bodies)
+void b3GpuGenericConstraint::getInfo1(unsigned int* info, const b3RigidBodyData* bodies)
{
switch (m_constraintType)
{
- case B3_GPU_POINT2POINT_CONSTRAINT_TYPE:
+ case B3_GPU_POINT2POINT_CONSTRAINT_TYPE:
{
*info = 3;
break;
@@ -35,7 +35,7 @@ void b3GpuGenericConstraint::getInfo1 (unsigned int* info,const b3RigidBodyData*
};
}
-void getInfo2Point2Point(b3GpuGenericConstraint* constraint, b3GpuConstraintInfo2* info, const b3RigidBodyData* bodies)
+void getInfo2Point2Point(b3GpuGenericConstraint* constraint, b3GpuConstraintInfo2* info, const b3RigidBodyData* bodies)
{
b3Transform trA;
trA.setIdentity();
@@ -47,54 +47,52 @@ void getInfo2Point2Point(b3GpuGenericConstraint* constraint, b3GpuConstraintInfo
trB.setOrigin(bodies[constraint->m_rbB].m_pos);
trB.setRotation(bodies[constraint->m_rbB].m_quat);
- // anchor points in global coordinates with respect to body PORs.
-
- // set jacobian
- info->m_J1linearAxis[0] = 1;
- info->m_J1linearAxis[info->rowskip+1] = 1;
- info->m_J1linearAxis[2*info->rowskip+2] = 1;
+ // anchor points in global coordinates with respect to body PORs.
- b3Vector3 a1 = trA.getBasis()*constraint->getPivotInA();
+ // set jacobian
+ info->m_J1linearAxis[0] = 1;
+ info->m_J1linearAxis[info->rowskip + 1] = 1;
+ info->m_J1linearAxis[2 * info->rowskip + 2] = 1;
+
+ b3Vector3 a1 = trA.getBasis() * constraint->getPivotInA();
//b3Vector3 a1a = b3QuatRotate(trA.getRotation(),constraint->getPivotInA());
{
b3Vector3* angular0 = (b3Vector3*)(info->m_J1angularAxis);
- b3Vector3* angular1 = (b3Vector3*)(info->m_J1angularAxis+info->rowskip);
- b3Vector3* angular2 = (b3Vector3*)(info->m_J1angularAxis+2*info->rowskip);
+ b3Vector3* angular1 = (b3Vector3*)(info->m_J1angularAxis + info->rowskip);
+ b3Vector3* angular2 = (b3Vector3*)(info->m_J1angularAxis + 2 * info->rowskip);
b3Vector3 a1neg = -a1;
- a1neg.getSkewSymmetricMatrix(angular0,angular1,angular2);
+ a1neg.getSkewSymmetricMatrix(angular0, angular1, angular2);
}
-
+
if (info->m_J2linearAxis)
{
info->m_J2linearAxis[0] = -1;
- info->m_J2linearAxis[info->rowskip+1] = -1;
- info->m_J2linearAxis[2*info->rowskip+2] = -1;
+ info->m_J2linearAxis[info->rowskip + 1] = -1;
+ info->m_J2linearAxis[2 * info->rowskip + 2] = -1;
}
-
- b3Vector3 a2 = trB.getBasis()*constraint->getPivotInB();
-
+
+ b3Vector3 a2 = trB.getBasis() * constraint->getPivotInB();
+
{
- // b3Vector3 a2n = -a2;
+ // b3Vector3 a2n = -a2;
b3Vector3* angular0 = (b3Vector3*)(info->m_J2angularAxis);
- b3Vector3* angular1 = (b3Vector3*)(info->m_J2angularAxis+info->rowskip);
- b3Vector3* angular2 = (b3Vector3*)(info->m_J2angularAxis+2*info->rowskip);
- a2.getSkewSymmetricMatrix(angular0,angular1,angular2);
+ b3Vector3* angular1 = (b3Vector3*)(info->m_J2angularAxis + info->rowskip);
+ b3Vector3* angular2 = (b3Vector3*)(info->m_J2angularAxis + 2 * info->rowskip);
+ a2.getSkewSymmetricMatrix(angular0, angular1, angular2);
}
-
-
- // set right hand side
-// b3Scalar currERP = (m_flags & B3_P2P_FLAGS_ERP) ? m_erp : info->erp;
+ // set right hand side
+ // b3Scalar currERP = (m_flags & B3_P2P_FLAGS_ERP) ? m_erp : info->erp;
b3Scalar currERP = info->erp;
b3Scalar k = info->fps * currERP;
- int j;
- for (j=0; j<3; j++)
- {
- info->m_constraintError[j*info->rowskip] = k * (a2[j] + trB.getOrigin()[j] - a1[j] - trA.getOrigin()[j]);
+ int j;
+ for (j = 0; j < 3; j++)
+ {
+ info->m_constraintError[j * info->rowskip] = k * (a2[j] + trB.getOrigin()[j] - a1[j] - trA.getOrigin()[j]);
//printf("info->m_constraintError[%d]=%f\n",j,info->m_constraintError[j]);
- }
+ }
#if 0
if(m_flags & B3_P2P_FLAGS_CFM)
{
@@ -117,21 +115,20 @@ void getInfo2Point2Point(b3GpuGenericConstraint* constraint, b3GpuConstraintInfo
}
info->m_damping = m_setting.m_damping;
#endif
-
}
-void b3GpuGenericConstraint::getInfo2 (b3GpuConstraintInfo2* info, const b3RigidBodyData* bodies)
+void b3GpuGenericConstraint::getInfo2(b3GpuConstraintInfo2* info, const b3RigidBodyData* bodies)
{
switch (m_constraintType)
{
- case B3_GPU_POINT2POINT_CONSTRAINT_TYPE:
+ case B3_GPU_POINT2POINT_CONSTRAINT_TYPE:
{
- getInfo2Point2Point(this,info,bodies);
+ getInfo2Point2Point(this, info, bodies);
break;
};
default:
- {
- b3Assert(0);
- }
+ {
+ b3Assert(0);
+ }
};
}
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuGenericConstraint.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuGenericConstraint.h
index 14b3ba7fec..1f163ba7d5 100644
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuGenericConstraint.h
+++ b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuGenericConstraint.h
@@ -20,37 +20,35 @@ subject to the following restrictions:
struct b3RigidBodyData;
enum B3_CONSTRAINT_FLAGS
{
- B3_CONSTRAINT_FLAG_ENABLED=1,
+ B3_CONSTRAINT_FLAG_ENABLED = 1,
};
enum b3GpuGenericConstraintType
{
- B3_GPU_POINT2POINT_CONSTRAINT_TYPE=3,
- B3_GPU_FIXED_CONSTRAINT_TYPE=4,
-// B3_HINGE_CONSTRAINT_TYPE,
-// B3_CONETWIST_CONSTRAINT_TYPE,
-// B3_D6_CONSTRAINT_TYPE,
-// B3_SLIDER_CONSTRAINT_TYPE,
-// B3_CONTACT_CONSTRAINT_TYPE,
-// B3_D6_SPRING_CONSTRAINT_TYPE,
-// B3_GEAR_CONSTRAINT_TYPE,
-
+ B3_GPU_POINT2POINT_CONSTRAINT_TYPE = 3,
+ B3_GPU_FIXED_CONSTRAINT_TYPE = 4,
+ // B3_HINGE_CONSTRAINT_TYPE,
+ // B3_CONETWIST_CONSTRAINT_TYPE,
+ // B3_D6_CONSTRAINT_TYPE,
+ // B3_SLIDER_CONSTRAINT_TYPE,
+ // B3_CONTACT_CONSTRAINT_TYPE,
+ // B3_D6_SPRING_CONSTRAINT_TYPE,
+ // B3_GEAR_CONSTRAINT_TYPE,
+
B3_GPU_MAX_CONSTRAINT_TYPE
};
-
-
-struct b3GpuConstraintInfo2
+struct b3GpuConstraintInfo2
{
// integrator parameters: frames per second (1/stepsize), default error
// reduction parameter (0..1).
- b3Scalar fps,erp;
+ b3Scalar fps, erp;
// 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.
- b3Scalar *m_J1linearAxis,*m_J1angularAxis,*m_J2linearAxis,*m_J2angularAxis;
+ b3Scalar *m_J1linearAxis, *m_J1angularAxis, *m_J2linearAxis, *m_J2angularAxis;
// elements to jump from one row to the next in J's
int rowskip;
@@ -58,44 +56,44 @@ struct b3GpuConstraintInfo2
// 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.
- b3Scalar *m_constraintError,*cfm;
+ b3Scalar *m_constraintError, *cfm;
// lo and hi limits for variables (set to -/+ infinity on entry).
- b3Scalar *m_lowerLimit,*m_upperLimit;
+ b3Scalar *m_lowerLimit, *m_upperLimit;
// 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;
+ int* findex;
// number of solver iterations
int m_numIterations;
//damping of the velocity
- b3Scalar m_damping;
+ b3Scalar m_damping;
};
-
-B3_ATTRIBUTE_ALIGNED16(struct) b3GpuGenericConstraint
+B3_ATTRIBUTE_ALIGNED16(struct)
+b3GpuGenericConstraint
{
- int m_constraintType;
- int m_rbA;
- int m_rbB;
- float m_breakingImpulseThreshold;
+ int m_constraintType;
+ int m_rbA;
+ int m_rbB;
+ float m_breakingImpulseThreshold;
b3Vector3 m_pivotInA;
b3Vector3 m_pivotInB;
b3Quaternion m_relTargetAB;
- int m_flags;
+ int m_flags;
int m_uid;
int m_padding[2];
- int getRigidBodyA() const
+ int getRigidBodyA() const
{
return m_rbA;
}
- int getRigidBodyB() const
+ int getRigidBodyB() const
{
return m_rbB;
}
@@ -121,12 +119,10 @@ B3_ATTRIBUTE_ALIGNED16(struct) b3GpuGenericConstraint
}
///internal method used by the constraint solver, don't use them directly
- void getInfo1 (unsigned int* info,const b3RigidBodyData* bodies);
+ void getInfo1(unsigned int* info, const b3RigidBodyData* bodies);
///internal method used by the constraint solver, don't use them directly
- void getInfo2 (b3GpuConstraintInfo2* info, const b3RigidBodyData* bodies);
-
-
+ void getInfo2(b3GpuConstraintInfo2 * info, const b3RigidBodyData* bodies);
};
-#endif //B3_GPU_GENERIC_CONSTRAINT_H \ No newline at end of file
+#endif //B3_GPU_GENERIC_CONSTRAINT_H \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuJacobiContactSolver.cpp b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuJacobiContactSolver.cpp
index 179dfc4f26..089fb1f6a6 100644
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuJacobiContactSolver.cpp
+++ b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuJacobiContactSolver.cpp
@@ -2,7 +2,7 @@
#include "b3GpuJacobiContactSolver.h"
#include "Bullet3Collision/NarrowPhaseCollision/b3Contact4.h"
#include "Bullet3Common/b3AlignedObjectArray.h"
-#include "Bullet3OpenCL/ParallelPrimitives/b3FillCL.h" //b3Int2
+#include "Bullet3OpenCL/ParallelPrimitives/b3FillCL.h" //b3Int2
class b3Vector3;
#include "Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h"
#include "Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.h"
@@ -15,89 +15,78 @@ class b3Vector3;
#include "Bullet3Common/shared/b3Int4.h"
#define SOLVER_UTILS_KERNEL_PATH "src/Bullet3OpenCL/RigidBody/kernels/solverUtils.cl"
-
struct b3GpuJacobiSolverInternalData
{
- //btRadixSort32CL* m_sort32;
- //btBoundSearchCL* m_search;
- b3PrefixScanCL* m_scan;
-
- b3OpenCLArray<unsigned int>* m_bodyCount;
- b3OpenCLArray<b3Int2>* m_contactConstraintOffsets;
- b3OpenCLArray<unsigned int>* m_offsetSplitBodies;
-
- b3OpenCLArray<b3Vector3>* m_deltaLinearVelocities;
- b3OpenCLArray<b3Vector3>* m_deltaAngularVelocities;
-
- b3AlignedObjectArray<b3Vector3> m_deltaLinearVelocitiesCPU;
- b3AlignedObjectArray<b3Vector3> m_deltaAngularVelocitiesCPU;
+ //btRadixSort32CL* m_sort32;
+ //btBoundSearchCL* m_search;
+ b3PrefixScanCL* m_scan;
+ b3OpenCLArray<unsigned int>* m_bodyCount;
+ b3OpenCLArray<b3Int2>* m_contactConstraintOffsets;
+ b3OpenCLArray<unsigned int>* m_offsetSplitBodies;
+ b3OpenCLArray<b3Vector3>* m_deltaLinearVelocities;
+ b3OpenCLArray<b3Vector3>* m_deltaAngularVelocities;
- b3OpenCLArray<b3GpuConstraint4>* m_contactConstraints;
-
- b3FillCL* m_filler;
-
-
- cl_kernel m_countBodiesKernel;
- cl_kernel m_contactToConstraintSplitKernel;
- cl_kernel m_clearVelocitiesKernel;
- cl_kernel m_averageVelocitiesKernel;
- cl_kernel m_updateBodyVelocitiesKernel;
- cl_kernel m_solveContactKernel;
- cl_kernel m_solveFrictionKernel;
+ b3AlignedObjectArray<b3Vector3> m_deltaLinearVelocitiesCPU;
+ b3AlignedObjectArray<b3Vector3> m_deltaAngularVelocitiesCPU;
+ b3OpenCLArray<b3GpuConstraint4>* m_contactConstraints;
+ b3FillCL* m_filler;
+ cl_kernel m_countBodiesKernel;
+ cl_kernel m_contactToConstraintSplitKernel;
+ cl_kernel m_clearVelocitiesKernel;
+ cl_kernel m_averageVelocitiesKernel;
+ cl_kernel m_updateBodyVelocitiesKernel;
+ cl_kernel m_solveContactKernel;
+ cl_kernel m_solveFrictionKernel;
};
-
b3GpuJacobiContactSolver::b3GpuJacobiContactSolver(cl_context ctx, cl_device_id device, cl_command_queue queue, int pairCapacity)
- :m_context(ctx),
- m_device(device),
- m_queue(queue)
+ : m_context(ctx),
+ m_device(device),
+ m_queue(queue)
{
m_data = new b3GpuJacobiSolverInternalData;
- m_data->m_scan = new b3PrefixScanCL(m_context,m_device,m_queue);
- m_data->m_bodyCount = new b3OpenCLArray<unsigned int>(m_context,m_queue);
- m_data->m_filler = new b3FillCL(m_context,m_device,m_queue);
- m_data->m_contactConstraintOffsets = new b3OpenCLArray<b3Int2>(m_context,m_queue);
- m_data->m_offsetSplitBodies = new b3OpenCLArray<unsigned int>(m_context,m_queue);
- m_data->m_contactConstraints = new b3OpenCLArray<b3GpuConstraint4>(m_context,m_queue);
- m_data->m_deltaLinearVelocities = new b3OpenCLArray<b3Vector3>(m_context,m_queue);
- m_data->m_deltaAngularVelocities = new b3OpenCLArray<b3Vector3>(m_context,m_queue);
+ m_data->m_scan = new b3PrefixScanCL(m_context, m_device, m_queue);
+ m_data->m_bodyCount = new b3OpenCLArray<unsigned int>(m_context, m_queue);
+ m_data->m_filler = new b3FillCL(m_context, m_device, m_queue);
+ m_data->m_contactConstraintOffsets = new b3OpenCLArray<b3Int2>(m_context, m_queue);
+ m_data->m_offsetSplitBodies = new b3OpenCLArray<unsigned int>(m_context, m_queue);
+ m_data->m_contactConstraints = new b3OpenCLArray<b3GpuConstraint4>(m_context, m_queue);
+ m_data->m_deltaLinearVelocities = new b3OpenCLArray<b3Vector3>(m_context, m_queue);
+ m_data->m_deltaAngularVelocities = new b3OpenCLArray<b3Vector3>(m_context, m_queue);
cl_int pErrNum;
- const char* additionalMacros="";
+ const char* additionalMacros = "";
const char* solverUtilsSource = solverUtilsCL;
{
- cl_program solverUtilsProg= b3OpenCLUtils::compileCLProgramFromString( ctx, device, solverUtilsSource, &pErrNum,additionalMacros, SOLVER_UTILS_KERNEL_PATH);
+ cl_program solverUtilsProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, solverUtilsSource, &pErrNum, additionalMacros, SOLVER_UTILS_KERNEL_PATH);
b3Assert(solverUtilsProg);
- m_data->m_countBodiesKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solverUtilsSource, "CountBodiesKernel", &pErrNum, solverUtilsProg,additionalMacros );
+ m_data->m_countBodiesKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverUtilsSource, "CountBodiesKernel", &pErrNum, solverUtilsProg, additionalMacros);
b3Assert(m_data->m_countBodiesKernel);
- m_data->m_contactToConstraintSplitKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solverUtilsSource, "ContactToConstraintSplitKernel", &pErrNum, solverUtilsProg,additionalMacros );
+ m_data->m_contactToConstraintSplitKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverUtilsSource, "ContactToConstraintSplitKernel", &pErrNum, solverUtilsProg, additionalMacros);
b3Assert(m_data->m_contactToConstraintSplitKernel);
- m_data->m_clearVelocitiesKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solverUtilsSource, "ClearVelocitiesKernel", &pErrNum, solverUtilsProg,additionalMacros );
+ m_data->m_clearVelocitiesKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverUtilsSource, "ClearVelocitiesKernel", &pErrNum, solverUtilsProg, additionalMacros);
b3Assert(m_data->m_clearVelocitiesKernel);
- m_data->m_averageVelocitiesKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solverUtilsSource, "AverageVelocitiesKernel", &pErrNum, solverUtilsProg,additionalMacros );
+ m_data->m_averageVelocitiesKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverUtilsSource, "AverageVelocitiesKernel", &pErrNum, solverUtilsProg, additionalMacros);
b3Assert(m_data->m_averageVelocitiesKernel);
- m_data->m_updateBodyVelocitiesKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solverUtilsSource, "UpdateBodyVelocitiesKernel", &pErrNum, solverUtilsProg,additionalMacros );
+ m_data->m_updateBodyVelocitiesKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverUtilsSource, "UpdateBodyVelocitiesKernel", &pErrNum, solverUtilsProg, additionalMacros);
b3Assert(m_data->m_updateBodyVelocitiesKernel);
-
- m_data->m_solveContactKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solverUtilsSource, "SolveContactJacobiKernel", &pErrNum, solverUtilsProg,additionalMacros );
- b3Assert(m_data->m_solveContactKernel );
+ m_data->m_solveContactKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverUtilsSource, "SolveContactJacobiKernel", &pErrNum, solverUtilsProg, additionalMacros);
+ b3Assert(m_data->m_solveContactKernel);
- m_data->m_solveFrictionKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solverUtilsSource, "SolveFrictionJacobiKernel", &pErrNum, solverUtilsProg,additionalMacros );
+ m_data->m_solveFrictionKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverUtilsSource, "SolveFrictionJacobiKernel", &pErrNum, solverUtilsProg, additionalMacros);
b3Assert(m_data->m_solveFrictionKernel);
}
-
}
-
b3GpuJacobiContactSolver::~b3GpuJacobiContactSolver()
{
clReleaseKernel(m_data->m_solveContactKernel);
@@ -106,7 +95,7 @@ b3GpuJacobiContactSolver::~b3GpuJacobiContactSolver()
clReleaseKernel(m_data->m_contactToConstraintSplitKernel);
clReleaseKernel(m_data->m_averageVelocitiesKernel);
clReleaseKernel(m_data->m_updateBodyVelocitiesKernel);
- clReleaseKernel(m_data->m_clearVelocitiesKernel );
+ clReleaseKernel(m_data->m_clearVelocitiesKernel);
delete m_data->m_deltaLinearVelocities;
delete m_data->m_deltaAngularVelocities;
@@ -119,80 +108,70 @@ b3GpuJacobiContactSolver::~b3GpuJacobiContactSolver()
delete m_data;
}
-
-
b3Vector3 make_float4(float v)
{
- return b3MakeVector3 (v,v,v);
+ return b3MakeVector3(v, v, v);
}
-b3Vector4 make_float4(float x,float y, float z, float w)
+b3Vector4 make_float4(float x, float y, float z, float w)
{
- return b3MakeVector4 (x,y,z,w);
+ return b3MakeVector4(x, y, z, w);
}
-
- static
- inline
- float calcRelVel(const b3Vector3& l0, const b3Vector3& l1, const b3Vector3& a0, const b3Vector3& a1,
- const b3Vector3& linVel0, const b3Vector3& angVel0, const b3Vector3& linVel1, const b3Vector3& angVel1)
- {
- return b3Dot(l0, linVel0) + b3Dot(a0, angVel0) + b3Dot(l1, linVel1) + b3Dot(a1, angVel1);
- }
-
-
- static
- inline
- void setLinearAndAngular(const b3Vector3& n, const b3Vector3& r0, const b3Vector3& r1,
- b3Vector3& linear, b3Vector3& angular0, b3Vector3& angular1)
- {
- linear = n;
- angular0 = b3Cross(r0, n);
- angular1 = -b3Cross(r1, n);
- }
-
-
-static __inline void solveContact(b3GpuConstraint4& cs,
- const b3Vector3& posA, const b3Vector3& linVelARO, const b3Vector3& angVelARO, float invMassA, const b3Matrix3x3& invInertiaA,
- const b3Vector3& posB, const b3Vector3& linVelBRO, const b3Vector3& angVelBRO, float invMassB, const b3Matrix3x3& invInertiaB,
- float maxRambdaDt[4], float minRambdaDt[4], b3Vector3& dLinVelA, b3Vector3& dAngVelA, b3Vector3& dLinVelB, b3Vector3& dAngVelB)
+static inline float calcRelVel(const b3Vector3& l0, const b3Vector3& l1, const b3Vector3& a0, const b3Vector3& a1,
+ const b3Vector3& linVel0, const b3Vector3& angVel0, const b3Vector3& linVel1, const b3Vector3& angVel1)
{
+ return b3Dot(l0, linVel0) + b3Dot(a0, angVel0) + b3Dot(l1, linVel1) + b3Dot(a1, angVel1);
+}
+static inline void setLinearAndAngular(const b3Vector3& n, const b3Vector3& r0, const b3Vector3& r1,
+ b3Vector3& linear, b3Vector3& angular0, b3Vector3& angular1)
+{
+ linear = n;
+ angular0 = b3Cross(r0, n);
+ angular1 = -b3Cross(r1, n);
+}
- for(int ic=0; ic<4; ic++)
+static __inline void solveContact(b3GpuConstraint4& cs,
+ const b3Vector3& posA, const b3Vector3& linVelARO, const b3Vector3& angVelARO, float invMassA, const b3Matrix3x3& invInertiaA,
+ const b3Vector3& posB, const b3Vector3& linVelBRO, const b3Vector3& angVelBRO, float invMassB, const b3Matrix3x3& invInertiaB,
+ float maxRambdaDt[4], float minRambdaDt[4], b3Vector3& dLinVelA, b3Vector3& dAngVelA, b3Vector3& dLinVelB, b3Vector3& dAngVelB)
+{
+ for (int ic = 0; ic < 4; ic++)
{
// dont necessary because this makes change to 0
- if( cs.m_jacCoeffInv[ic] == 0.f ) continue;
+ if (cs.m_jacCoeffInv[ic] == 0.f) continue;
{
b3Vector3 angular0, angular1, linear;
b3Vector3 r0 = cs.m_worldPos[ic] - (b3Vector3&)posA;
b3Vector3 r1 = cs.m_worldPos[ic] - (b3Vector3&)posB;
- setLinearAndAngular( (const b3Vector3 &)cs.m_linear, (const b3Vector3 &)r0, (const b3Vector3 &)r1, linear, angular0, angular1 );
+ setLinearAndAngular((const b3Vector3&)cs.m_linear, (const b3Vector3&)r0, (const b3Vector3&)r1, linear, angular0, angular1);
- float rambdaDt = calcRelVel((const b3Vector3 &)cs.m_linear,(const b3Vector3 &) -cs.m_linear, angular0, angular1,
- linVelARO+dLinVelA, angVelARO+dAngVelA, linVelBRO+dLinVelB, angVelBRO+dAngVelB ) + cs.m_b[ic];
+ float rambdaDt = calcRelVel((const b3Vector3&)cs.m_linear, (const b3Vector3&)-cs.m_linear, angular0, angular1,
+ linVelARO + dLinVelA, angVelARO + dAngVelA, linVelBRO + dLinVelB, angVelBRO + dAngVelB) +
+ cs.m_b[ic];
rambdaDt *= cs.m_jacCoeffInv[ic];
{
float prevSum = cs.m_appliedRambdaDt[ic];
float updated = prevSum;
updated += rambdaDt;
- updated = b3Max( updated, minRambdaDt[ic] );
- updated = b3Min( updated, maxRambdaDt[ic] );
+ updated = b3Max(updated, minRambdaDt[ic]);
+ updated = b3Min(updated, maxRambdaDt[ic]);
rambdaDt = updated - prevSum;
cs.m_appliedRambdaDt[ic] = updated;
}
- b3Vector3 linImp0 = invMassA*linear*rambdaDt;
- b3Vector3 linImp1 = invMassB*(-linear)*rambdaDt;
- b3Vector3 angImp0 = (invInertiaA* angular0)*rambdaDt;
- b3Vector3 angImp1 = (invInertiaB* angular1)*rambdaDt;
+ b3Vector3 linImp0 = invMassA * linear * rambdaDt;
+ b3Vector3 linImp1 = invMassB * (-linear) * rambdaDt;
+ b3Vector3 angImp0 = (invInertiaA * angular0) * rambdaDt;
+ b3Vector3 angImp1 = (invInertiaB * angular1) * rambdaDt;
#ifdef _WIN32
- b3Assert(_finite(linImp0.getX()));
+ b3Assert(_finite(linImp0.getX()));
b3Assert(_finite(linImp1.getX()));
#endif
-
+
if (invMassA)
{
dLinVelA += linImp0;
@@ -207,43 +186,42 @@ static __inline void solveContact(b3GpuConstraint4& cs,
}
}
-
-
void solveContact3(b3GpuConstraint4* cs,
- b3Vector3* posAPtr, b3Vector3* linVelA, b3Vector3* angVelA, float invMassA, const b3Matrix3x3& invInertiaA,
- b3Vector3* posBPtr, b3Vector3* linVelB, b3Vector3* angVelB, float invMassB, const b3Matrix3x3& invInertiaB,
- b3Vector3* dLinVelA, b3Vector3* dAngVelA, b3Vector3* dLinVelB, b3Vector3* dAngVelB)
+ b3Vector3* posAPtr, b3Vector3* linVelA, b3Vector3* angVelA, float invMassA, const b3Matrix3x3& invInertiaA,
+ b3Vector3* posBPtr, b3Vector3* linVelB, b3Vector3* angVelB, float invMassB, const b3Matrix3x3& invInertiaB,
+ b3Vector3* dLinVelA, b3Vector3* dAngVelA, b3Vector3* dLinVelB, b3Vector3* dAngVelB)
{
float minRambdaDt = 0;
float maxRambdaDt = FLT_MAX;
- for(int ic=0; ic<4; ic++)
+ for (int ic = 0; ic < 4; ic++)
{
- if( cs->m_jacCoeffInv[ic] == 0.f ) continue;
+ if (cs->m_jacCoeffInv[ic] == 0.f) continue;
b3Vector3 angular0, angular1, linear;
b3Vector3 r0 = cs->m_worldPos[ic] - *posAPtr;
b3Vector3 r1 = cs->m_worldPos[ic] - *posBPtr;
- setLinearAndAngular( cs->m_linear, r0, r1, linear, angular0, angular1 );
+ setLinearAndAngular(cs->m_linear, r0, r1, linear, angular0, angular1);
- float rambdaDt = calcRelVel( cs->m_linear, -cs->m_linear, angular0, angular1,
- *linVelA+*dLinVelA, *angVelA+*dAngVelA, *linVelB+*dLinVelB, *angVelB+*dAngVelB ) + cs->m_b[ic];
+ float rambdaDt = calcRelVel(cs->m_linear, -cs->m_linear, angular0, angular1,
+ *linVelA + *dLinVelA, *angVelA + *dAngVelA, *linVelB + *dLinVelB, *angVelB + *dAngVelB) +
+ cs->m_b[ic];
rambdaDt *= cs->m_jacCoeffInv[ic];
{
float prevSum = cs->m_appliedRambdaDt[ic];
float updated = prevSum;
updated += rambdaDt;
- updated = b3Max( updated, minRambdaDt );
- updated = b3Min( updated, maxRambdaDt );
+ updated = b3Max(updated, minRambdaDt);
+ updated = b3Min(updated, maxRambdaDt);
rambdaDt = updated - prevSum;
cs->m_appliedRambdaDt[ic] = updated;
}
- b3Vector3 linImp0 = invMassA*linear*rambdaDt;
- b3Vector3 linImp1 = invMassB*(-linear)*rambdaDt;
- b3Vector3 angImp0 = (invInertiaA* angular0)*rambdaDt;
- b3Vector3 angImp1 = (invInertiaB* angular1)*rambdaDt;
+ b3Vector3 linImp0 = invMassA * linear * rambdaDt;
+ b3Vector3 linImp1 = invMassB * (-linear) * rambdaDt;
+ b3Vector3 angImp0 = (invInertiaA * angular0) * rambdaDt;
+ b3Vector3 angImp1 = (invInertiaB * angular1) * rambdaDt;
if (invMassA)
{
@@ -258,58 +236,56 @@ void solveContact3(b3GpuConstraint4* cs,
}
}
-
-static inline void solveFriction(b3GpuConstraint4& cs,
- const b3Vector3& posA, const b3Vector3& linVelARO, const b3Vector3& angVelARO, float invMassA, const b3Matrix3x3& invInertiaA,
- const b3Vector3& posB, const b3Vector3& linVelBRO, const b3Vector3& angVelBRO, float invMassB, const b3Matrix3x3& invInertiaB,
- float maxRambdaDt[4], float minRambdaDt[4], b3Vector3& dLinVelA, b3Vector3& dAngVelA, b3Vector3& dLinVelB, b3Vector3& dAngVelB)
+static inline void solveFriction(b3GpuConstraint4& cs,
+ const b3Vector3& posA, const b3Vector3& linVelARO, const b3Vector3& angVelARO, float invMassA, const b3Matrix3x3& invInertiaA,
+ const b3Vector3& posB, const b3Vector3& linVelBRO, const b3Vector3& angVelBRO, float invMassB, const b3Matrix3x3& invInertiaB,
+ float maxRambdaDt[4], float minRambdaDt[4], b3Vector3& dLinVelA, b3Vector3& dAngVelA, b3Vector3& dLinVelB, b3Vector3& dAngVelB)
{
+ b3Vector3 linVelA = linVelARO + dLinVelA;
+ b3Vector3 linVelB = linVelBRO + dLinVelB;
+ b3Vector3 angVelA = angVelARO + dAngVelA;
+ b3Vector3 angVelB = angVelBRO + dAngVelB;
- b3Vector3 linVelA = linVelARO+dLinVelA;
- b3Vector3 linVelB = linVelBRO+dLinVelB;
- b3Vector3 angVelA = angVelARO+dAngVelA;
- b3Vector3 angVelB = angVelBRO+dAngVelB;
-
- if( cs.m_fJacCoeffInv[0] == 0 && cs.m_fJacCoeffInv[0] == 0 ) return;
+ if (cs.m_fJacCoeffInv[0] == 0 && cs.m_fJacCoeffInv[0] == 0) return;
const b3Vector3& center = (const b3Vector3&)cs.m_center;
b3Vector3 n = -(const b3Vector3&)cs.m_linear;
b3Vector3 tangent[2];
-#if 1
- b3PlaneSpace1 (n, tangent[0],tangent[1]);
+#if 1
+ b3PlaneSpace1(n, tangent[0], tangent[1]);
#else
- b3Vector3 r = cs.m_worldPos[0]-center;
- tangent[0] = cross3( n, r );
- tangent[1] = cross3( tangent[0], n );
- tangent[0] = normalize3( tangent[0] );
- tangent[1] = normalize3( tangent[1] );
+ b3Vector3 r = cs.m_worldPos[0] - center;
+ tangent[0] = cross3(n, r);
+ tangent[1] = cross3(tangent[0], n);
+ tangent[0] = normalize3(tangent[0]);
+ tangent[1] = normalize3(tangent[1]);
#endif
b3Vector3 angular0, angular1, linear;
b3Vector3 r0 = center - posA;
b3Vector3 r1 = center - posB;
- for(int i=0; i<2; i++)
+ for (int i = 0; i < 2; i++)
{
- setLinearAndAngular( tangent[i], r0, r1, linear, angular0, angular1 );
+ setLinearAndAngular(tangent[i], r0, r1, linear, angular0, angular1);
float rambdaDt = calcRelVel(linear, -linear, angular0, angular1,
- linVelA, angVelA, linVelB, angVelB );
+ linVelA, angVelA, linVelB, angVelB);
rambdaDt *= cs.m_fJacCoeffInv[i];
- {
- float prevSum = cs.m_fAppliedRambdaDt[i];
- float updated = prevSum;
- updated += rambdaDt;
- updated = b3Max( updated, minRambdaDt[i] );
- updated = b3Min( updated, maxRambdaDt[i] );
- rambdaDt = updated - prevSum;
- cs.m_fAppliedRambdaDt[i] = updated;
- }
+ {
+ float prevSum = cs.m_fAppliedRambdaDt[i];
+ float updated = prevSum;
+ updated += rambdaDt;
+ updated = b3Max(updated, minRambdaDt[i]);
+ updated = b3Min(updated, maxRambdaDt[i]);
+ rambdaDt = updated - prevSum;
+ cs.m_fAppliedRambdaDt[i] = updated;
+ }
- b3Vector3 linImp0 = invMassA*linear*rambdaDt;
- b3Vector3 linImp1 = invMassB*(-linear)*rambdaDt;
- b3Vector3 angImp0 = (invInertiaA* angular0)*rambdaDt;
- b3Vector3 angImp1 = (invInertiaB* angular1)*rambdaDt;
+ b3Vector3 linImp0 = invMassA * linear * rambdaDt;
+ b3Vector3 linImp1 = invMassB * (-linear) * rambdaDt;
+ b3Vector3 angImp0 = (invInertiaA * angular0) * rambdaDt;
+ b3Vector3 angImp1 = (invInertiaB * angular1) * rambdaDt;
#ifdef _WIN32
b3Assert(_finite(linImp0.getX()));
b3Assert(_finite(linImp1.getX()));
@@ -326,65 +302,58 @@ static inline void solveFriction(b3GpuConstraint4& cs,
}
}
- { // angular damping for point constraint
- b3Vector3 ab = ( posB - posA ).normalized();
- b3Vector3 ac = ( center - posA ).normalized();
- if( b3Dot( ab, ac ) > 0.95f || (invMassA == 0.f || invMassB == 0.f))
+ { // angular damping for point constraint
+ b3Vector3 ab = (posB - posA).normalized();
+ b3Vector3 ac = (center - posA).normalized();
+ if (b3Dot(ab, ac) > 0.95f || (invMassA == 0.f || invMassB == 0.f))
{
- float angNA = b3Dot( n, angVelA );
- float angNB = b3Dot( n, angVelB );
+ float angNA = b3Dot(n, angVelA);
+ float angNB = b3Dot(n, angVelB);
if (invMassA)
- dAngVelA -= (angNA*0.1f)*n;
+ dAngVelA -= (angNA * 0.1f) * n;
if (invMassB)
- dAngVelB -= (angNB*0.1f)*n;
+ dAngVelB -= (angNB * 0.1f) * n;
}
}
-
}
-
-
-
float calcJacCoeff(const b3Vector3& linear0, const b3Vector3& linear1, const b3Vector3& angular0, const b3Vector3& angular1,
- float invMass0, const b3Matrix3x3* invInertia0, float invMass1, const b3Matrix3x3* invInertia1, float countA, float countB)
+ float invMass0, const b3Matrix3x3* invInertia0, float invMass1, const b3Matrix3x3* invInertia1, float countA, float countB)
{
// linear0,1 are normlized
- float jmj0 = invMass0;//dot3F4(linear0, linear0)*invMass0;
-
- float jmj1 = b3Dot(mtMul3(angular0,*invInertia0), angular0);
- float jmj2 = invMass1;//dot3F4(linear1, linear1)*invMass1;
- float jmj3 = b3Dot(mtMul3(angular1,*invInertia1), angular1);
- return -1.f/((jmj0+jmj1)*countA+(jmj2+jmj3)*countB);
-// return -1.f/((jmj0+jmj1)+(jmj2+jmj3));
+ float jmj0 = invMass0; //dot3F4(linear0, linear0)*invMass0;
+ float jmj1 = b3Dot(mtMul3(angular0, *invInertia0), angular0);
+ float jmj2 = invMass1; //dot3F4(linear1, linear1)*invMass1;
+ float jmj3 = b3Dot(mtMul3(angular1, *invInertia1), angular1);
+ return -1.f / ((jmj0 + jmj1) * countA + (jmj2 + jmj3) * countB);
+ // return -1.f/((jmj0+jmj1)+(jmj2+jmj3));
}
-
-void setConstraint4( const b3Vector3& posA, const b3Vector3& linVelA, const b3Vector3& angVelA, float invMassA, const b3Matrix3x3& invInertiaA,
- const b3Vector3& posB, const b3Vector3& linVelB, const b3Vector3& angVelB, float invMassB, const b3Matrix3x3& invInertiaB,
- b3Contact4* src, float dt, float positionDrift, float positionConstraintCoeff, float countA, float countB,
- b3GpuConstraint4* dstC )
+void setConstraint4(const b3Vector3& posA, const b3Vector3& linVelA, const b3Vector3& angVelA, float invMassA, const b3Matrix3x3& invInertiaA,
+ const b3Vector3& posB, const b3Vector3& linVelB, const b3Vector3& angVelB, float invMassB, const b3Matrix3x3& invInertiaB,
+ b3Contact4* src, float dt, float positionDrift, float positionConstraintCoeff, float countA, float countB,
+ b3GpuConstraint4* dstC)
{
dstC->m_bodyA = abs(src->m_bodyAPtrAndSignBit);
dstC->m_bodyB = abs(src->m_bodyBPtrAndSignBit);
- float dtInv = 1.f/dt;
- for(int ic=0; ic<4; ic++)
+ float dtInv = 1.f / dt;
+ for (int ic = 0; ic < 4; ic++)
{
dstC->m_appliedRambdaDt[ic] = 0.f;
}
dstC->m_fJacCoeffInv[0] = dstC->m_fJacCoeffInv[1] = 0.f;
-
dstC->m_linear = src->m_worldNormalOnB;
- dstC->m_linear[3] = 0.7f ;//src->getFrictionCoeff() );
- for(int ic=0; ic<4; ic++)
+ dstC->m_linear[3] = 0.7f; //src->getFrictionCoeff() );
+ for (int ic = 0; ic < 4; ic++)
{
b3Vector3 r0 = src->m_worldPosB[ic] - posA;
b3Vector3 r1 = src->m_worldPosB[ic] - posB;
- if( ic >= src->m_worldNormalOnB[3] )//npoints
+ if (ic >= src->m_worldNormalOnB[3]) //npoints
{
dstC->m_jacCoeffInv[ic] = 0.f;
continue;
@@ -396,53 +365,53 @@ void setConstraint4( const b3Vector3& posA, const b3Vector3& linVelA, const b3Ve
setLinearAndAngular(src->m_worldNormalOnB, r0, r1, linear, angular0, angular1);
dstC->m_jacCoeffInv[ic] = calcJacCoeff(linear, -linear, angular0, angular1,
- invMassA, &invInertiaA, invMassB, &invInertiaB ,countA,countB);
+ invMassA, &invInertiaA, invMassB, &invInertiaB, countA, countB);
relVelN = calcRelVel(linear, -linear, angular0, angular1,
- linVelA, angVelA, linVelB, angVelB);
+ linVelA, angVelA, linVelB, angVelB);
- float e = 0.f;//src->getRestituitionCoeff();
- if( relVelN*relVelN < 0.004f )
+ float e = 0.f; //src->getRestituitionCoeff();
+ if (relVelN * relVelN < 0.004f)
{
e = 0.f;
}
- dstC->m_b[ic] = e*relVelN;
+ dstC->m_b[ic] = e * relVelN;
//float penetration = src->m_worldPos[ic].w;
- dstC->m_b[ic] += (src->m_worldPosB[ic][3] + positionDrift)*positionConstraintCoeff*dtInv;
+ dstC->m_b[ic] += (src->m_worldPosB[ic][3] + positionDrift) * positionConstraintCoeff * dtInv;
dstC->m_appliedRambdaDt[ic] = 0.f;
}
}
- if( src->m_worldNormalOnB[3] > 0 )//npoints
- { // prepare friction
+ if (src->m_worldNormalOnB[3] > 0) //npoints
+ { // prepare friction
b3Vector3 center = make_float4(0.f);
- for(int i=0; i<src->m_worldNormalOnB[3]; i++)
+ for (int i = 0; i < src->m_worldNormalOnB[3]; i++)
center += src->m_worldPosB[i];
center /= (float)src->m_worldNormalOnB[3];
b3Vector3 tangent[2];
- b3PlaneSpace1(src->m_worldNormalOnB,tangent[0],tangent[1]);
-
+ b3PlaneSpace1(src->m_worldNormalOnB, tangent[0], tangent[1]);
+
b3Vector3 r[2];
r[0] = center - posA;
r[1] = center - posB;
- for(int i=0; i<2; i++)
+ for (int i = 0; i < 2; i++)
{
b3Vector3 linear, angular0, angular1;
setLinearAndAngular(tangent[i], r[0], r[1], linear, angular0, angular1);
dstC->m_fJacCoeffInv[i] = calcJacCoeff(linear, -linear, angular0, angular1,
- invMassA, &invInertiaA, invMassB, &invInertiaB ,countA,countB);
+ invMassA, &invInertiaA, invMassB, &invInertiaB, countA, countB);
dstC->m_fAppliedRambdaDt[i] = 0.f;
}
dstC->m_center = center;
}
- for(int i=0; i<4; i++)
+ for (int i = 0; i < 4; i++)
{
- if( i<src->m_worldNormalOnB[3] )
+ if (i < src->m_worldNormalOnB[3])
{
dstC->m_worldPos[i] = src->m_worldPosB[i];
}
@@ -453,17 +422,14 @@ void setConstraint4( const b3Vector3& posA, const b3Vector3& linVelA, const b3Ve
}
}
-
-
void ContactToConstraintKernel(b3Contact4* gContact, b3RigidBodyData* gBodies, b3InertiaData* gShapes, b3GpuConstraint4* gConstraintOut, int nContacts,
-float dt,
-float positionDrift,
-float positionConstraintCoeff, int gIdx, b3AlignedObjectArray<unsigned int>& bodyCount
-)
+ float dt,
+ float positionDrift,
+ float positionConstraintCoeff, int gIdx, b3AlignedObjectArray<unsigned int>& bodyCount)
{
//int gIdx = 0;//GET_GLOBAL_IDX;
-
- if( gIdx < nContacts )
+
+ if (gIdx < nContacts)
{
int aIdx = abs(gContact[gIdx].m_bodyAPtrAndSignBit);
int bIdx = abs(gContact[gIdx].m_bodyBPtrAndSignBit);
@@ -472,50 +438,46 @@ float positionConstraintCoeff, int gIdx, b3AlignedObjectArray<unsigned int>& bod
b3Vector3 linVelA = gBodies[aIdx].m_linVel;
b3Vector3 angVelA = gBodies[aIdx].m_angVel;
float invMassA = gBodies[aIdx].m_invMass;
- b3Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertiaWorld;//.m_invInertia;
+ b3Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertiaWorld; //.m_invInertia;
b3Vector3 posB = gBodies[bIdx].m_pos;
b3Vector3 linVelB = gBodies[bIdx].m_linVel;
b3Vector3 angVelB = gBodies[bIdx].m_angVel;
float invMassB = gBodies[bIdx].m_invMass;
- b3Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertiaWorld;//m_invInertia;
+ b3Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertiaWorld; //m_invInertia;
b3GpuConstraint4 cs;
float countA = invMassA ? (float)(bodyCount[aIdx]) : 1;
float countB = invMassB ? (float)(bodyCount[bIdx]) : 1;
- setConstraint4( posA, linVelA, angVelA, invMassA, invInertiaA, posB, linVelB, angVelB, invMassB, invInertiaB,
- &gContact[gIdx], dt, positionDrift, positionConstraintCoeff,countA,countB,
- &cs );
-
+ setConstraint4(posA, linVelA, angVelA, invMassA, invInertiaA, posB, linVelB, angVelB, invMassB, invInertiaB,
+ &gContact[gIdx], dt, positionDrift, positionConstraintCoeff, countA, countB,
+ &cs);
-
cs.m_batchIdx = gContact[gIdx].m_batchIdx;
gConstraintOut[gIdx] = cs;
}
}
-
-void b3GpuJacobiContactSolver::solveGroupHost(b3RigidBodyData* bodies,b3InertiaData* inertias,int numBodies,b3Contact4* manifoldPtr, int numManifolds,const b3JacobiSolverInfo& solverInfo)
+void b3GpuJacobiContactSolver::solveGroupHost(b3RigidBodyData* bodies, b3InertiaData* inertias, int numBodies, b3Contact4* manifoldPtr, int numManifolds, const b3JacobiSolverInfo& solverInfo)
{
B3_PROFILE("b3GpuJacobiContactSolver::solveGroup");
b3AlignedObjectArray<unsigned int> bodyCount;
bodyCount.resize(numBodies);
- for (int i=0;i<numBodies;i++)
+ for (int i = 0; i < numBodies; i++)
bodyCount[i] = 0;
b3AlignedObjectArray<b3Int2> contactConstraintOffsets;
contactConstraintOffsets.resize(numManifolds);
-
- for (int i=0;i<numManifolds;i++)
+ for (int i = 0; i < numManifolds; i++)
{
int pa = manifoldPtr[i].m_bodyAPtrAndSignBit;
int pb = manifoldPtr[i].m_bodyBPtrAndSignBit;
- bool isFixedA = (pa <0) || (pa == solverInfo.m_fixedBodyIndex);
- bool isFixedB = (pb <0) || (pb == solverInfo.m_fixedBodyIndex);
+ bool isFixedA = (pa < 0) || (pa == solverInfo.m_fixedBodyIndex);
+ bool isFixedB = (pb < 0) || (pb == solverInfo.m_fixedBodyIndex);
int bodyIndexA = manifoldPtr[i].getBodyA();
int bodyIndexB = manifoldPtr[i].getBodyB();
@@ -529,71 +491,63 @@ void b3GpuJacobiContactSolver::solveGroupHost(b3RigidBodyData* bodies,b3InertiaD
{
contactConstraintOffsets[i].y = bodyCount[bodyIndexB];
bodyCount[bodyIndexB]++;
- }
+ }
}
b3AlignedObjectArray<unsigned int> offsetSplitBodies;
offsetSplitBodies.resize(numBodies);
unsigned int totalNumSplitBodies;
- m_data->m_scan->executeHost(bodyCount,offsetSplitBodies,numBodies,&totalNumSplitBodies);
- int numlastBody = bodyCount[numBodies-1];
+ m_data->m_scan->executeHost(bodyCount, offsetSplitBodies, numBodies, &totalNumSplitBodies);
+ int numlastBody = bodyCount[numBodies - 1];
totalNumSplitBodies += numlastBody;
- printf("totalNumSplitBodies = %d\n",totalNumSplitBodies);
-
-
-
-
+ printf("totalNumSplitBodies = %d\n", totalNumSplitBodies);
b3AlignedObjectArray<b3GpuConstraint4> contactConstraints;
contactConstraints.resize(numManifolds);
- for (int i=0;i<numManifolds;i++)
+ for (int i = 0; i < numManifolds; i++)
{
- ContactToConstraintKernel(&manifoldPtr[0],bodies,inertias,&contactConstraints[0],numManifolds,
- solverInfo.m_deltaTime,
- solverInfo.m_positionDrift,
- solverInfo.m_positionConstraintCoeff,
- i, bodyCount);
+ ContactToConstraintKernel(&manifoldPtr[0], bodies, inertias, &contactConstraints[0], numManifolds,
+ solverInfo.m_deltaTime,
+ solverInfo.m_positionDrift,
+ solverInfo.m_positionConstraintCoeff,
+ i, bodyCount);
}
int maxIter = solverInfo.m_numIterations;
-
b3AlignedObjectArray<b3Vector3> deltaLinearVelocities;
b3AlignedObjectArray<b3Vector3> deltaAngularVelocities;
deltaLinearVelocities.resize(totalNumSplitBodies);
deltaAngularVelocities.resize(totalNumSplitBodies);
- for (unsigned int i=0;i<totalNumSplitBodies;i++)
+ for (unsigned int i = 0; i < totalNumSplitBodies; i++)
{
deltaLinearVelocities[i].setZero();
deltaAngularVelocities[i].setZero();
}
-
-
- for (int iter = 0;iter<maxIter;iter++)
+ for (int iter = 0; iter < maxIter; iter++)
{
- int i=0;
- for( i=0; i<numManifolds; i++)
+ int i = 0;
+ for (i = 0; i < numManifolds; i++)
{
-
//float frictionCoeff = contactConstraints[i].getFrictionCoeff();
int aIdx = (int)contactConstraints[i].m_bodyA;
int bIdx = (int)contactConstraints[i].m_bodyB;
b3RigidBodyData& bodyA = bodies[aIdx];
b3RigidBodyData& bodyB = bodies[bIdx];
- b3Vector3 zero = b3MakeVector3(0,0,0);
-
- b3Vector3* dlvAPtr=&zero;
- b3Vector3* davAPtr=&zero;
- b3Vector3* dlvBPtr=&zero;
- b3Vector3* davBPtr=&zero;
-
+ b3Vector3 zero = b3MakeVector3(0, 0, 0);
+
+ b3Vector3* dlvAPtr = &zero;
+ b3Vector3* davAPtr = &zero;
+ b3Vector3* dlvBPtr = &zero;
+ b3Vector3* davBPtr = &zero;
+
if (bodyA.m_invMass)
{
int bodyOffsetA = offsetSplitBodies[aIdx];
int constraintOffsetA = contactConstraintOffsets[i].x;
- int splitIndexA = bodyOffsetA+constraintOffsetA;
+ int splitIndexA = bodyOffsetA + constraintOffsetA;
dlvAPtr = &deltaLinearVelocities[splitIndexA];
davAPtr = &deltaAngularVelocities[splitIndexA];
}
@@ -602,67 +556,61 @@ void b3GpuJacobiContactSolver::solveGroupHost(b3RigidBodyData* bodies,b3InertiaD
{
int bodyOffsetB = offsetSplitBodies[bIdx];
int constraintOffsetB = contactConstraintOffsets[i].y;
- int splitIndexB= bodyOffsetB+constraintOffsetB;
- dlvBPtr =&deltaLinearVelocities[splitIndexB];
+ int splitIndexB = bodyOffsetB + constraintOffsetB;
+ dlvBPtr = &deltaLinearVelocities[splitIndexB];
davBPtr = &deltaAngularVelocities[splitIndexB];
}
-
-
{
- float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};
- float minRambdaDt[4] = {0.f,0.f,0.f,0.f};
-
- solveContact( contactConstraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass, inertias[aIdx].m_invInertiaWorld,
- (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass, inertias[bIdx].m_invInertiaWorld,
- maxRambdaDt, minRambdaDt , *dlvAPtr,*davAPtr,*dlvBPtr,*davBPtr );
-
+ float maxRambdaDt[4] = {FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX};
+ float minRambdaDt[4] = {0.f, 0.f, 0.f, 0.f};
+ solveContact(contactConstraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass, inertias[aIdx].m_invInertiaWorld,
+ (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass, inertias[bIdx].m_invInertiaWorld,
+ maxRambdaDt, minRambdaDt, *dlvAPtr, *davAPtr, *dlvBPtr, *davBPtr);
}
-
}
-
//easy
- for (int i=0;i<numBodies;i++)
+ for (int i = 0; i < numBodies; i++)
{
if (bodies[i].m_invMass)
{
int bodyOffset = offsetSplitBodies[i];
int count = bodyCount[i];
- float factor = 1.f/float(count);
+ float factor = 1.f / float(count);
b3Vector3 averageLinVel;
averageLinVel.setZero();
b3Vector3 averageAngVel;
averageAngVel.setZero();
- for (int j=0;j<count;j++)
+ for (int j = 0; j < count; j++)
{
- averageLinVel += deltaLinearVelocities[bodyOffset+j]*factor;
- averageAngVel += deltaAngularVelocities[bodyOffset+j]*factor;
+ averageLinVel += deltaLinearVelocities[bodyOffset + j] * factor;
+ averageAngVel += deltaAngularVelocities[bodyOffset + j] * factor;
}
- for (int j=0;j<count;j++)
+ for (int j = 0; j < count; j++)
{
- deltaLinearVelocities[bodyOffset+j] = averageLinVel;
- deltaAngularVelocities[bodyOffset+j] = averageAngVel;
+ deltaLinearVelocities[bodyOffset + j] = averageLinVel;
+ deltaAngularVelocities[bodyOffset + j] = averageAngVel;
}
}
}
}
- for (int iter = 0;iter<maxIter;iter++)
+ for (int iter = 0; iter < maxIter; iter++)
{
//int i=0;
-
+
//solve friction
- for(int i=0; i<numManifolds; i++)
+ for (int i = 0; i < numManifolds; i++)
{
- float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};
- float minRambdaDt[4] = {0.f,0.f,0.f,0.f};
+ float maxRambdaDt[4] = {FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX};
+ float minRambdaDt[4] = {0.f, 0.f, 0.f, 0.f};
float sum = 0;
- for(int j=0; j<4; j++)
+ for (int j = 0; j < 4; j++)
{
- sum +=contactConstraints[i].m_appliedRambdaDt[j];
+ sum += contactConstraints[i].m_appliedRambdaDt[j];
}
float frictionCoeff = contactConstraints[i].getFrictionCoeff();
int aIdx = (int)contactConstraints[i].m_bodyA;
@@ -670,18 +618,18 @@ void b3GpuJacobiContactSolver::solveGroupHost(b3RigidBodyData* bodies,b3InertiaD
b3RigidBodyData& bodyA = bodies[aIdx];
b3RigidBodyData& bodyB = bodies[bIdx];
- b3Vector3 zero = b3MakeVector3(0,0,0);
-
- b3Vector3* dlvAPtr=&zero;
- b3Vector3* davAPtr=&zero;
- b3Vector3* dlvBPtr=&zero;
- b3Vector3* davBPtr=&zero;
-
+ b3Vector3 zero = b3MakeVector3(0, 0, 0);
+
+ b3Vector3* dlvAPtr = &zero;
+ b3Vector3* davAPtr = &zero;
+ b3Vector3* dlvBPtr = &zero;
+ b3Vector3* davBPtr = &zero;
+
if (bodyA.m_invMass)
{
int bodyOffsetA = offsetSplitBodies[aIdx];
int constraintOffsetA = contactConstraintOffsets[i].x;
- int splitIndexA = bodyOffsetA+constraintOffsetA;
+ int splitIndexA = bodyOffsetA + constraintOffsetA;
dlvAPtr = &deltaLinearVelocities[splitIndexA];
davAPtr = &deltaAngularVelocities[splitIndexA];
}
@@ -690,55 +638,50 @@ void b3GpuJacobiContactSolver::solveGroupHost(b3RigidBodyData* bodies,b3InertiaD
{
int bodyOffsetB = offsetSplitBodies[bIdx];
int constraintOffsetB = contactConstraintOffsets[i].y;
- int splitIndexB= bodyOffsetB+constraintOffsetB;
- dlvBPtr =&deltaLinearVelocities[splitIndexB];
+ int splitIndexB = bodyOffsetB + constraintOffsetB;
+ dlvBPtr = &deltaLinearVelocities[splitIndexB];
davBPtr = &deltaAngularVelocities[splitIndexB];
}
- for(int j=0; j<4; j++)
+ for (int j = 0; j < 4; j++)
{
- maxRambdaDt[j] = frictionCoeff*sum;
+ maxRambdaDt[j] = frictionCoeff * sum;
minRambdaDt[j] = -maxRambdaDt[j];
}
- solveFriction( contactConstraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass,inertias[aIdx].m_invInertiaWorld,
- (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass, inertias[bIdx].m_invInertiaWorld,
- maxRambdaDt, minRambdaDt , *dlvAPtr,*davAPtr,*dlvBPtr,*davBPtr);
-
+ solveFriction(contactConstraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass, inertias[aIdx].m_invInertiaWorld,
+ (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass, inertias[bIdx].m_invInertiaWorld,
+ maxRambdaDt, minRambdaDt, *dlvAPtr, *davAPtr, *dlvBPtr, *davBPtr);
}
//easy
- for (int i=0;i<numBodies;i++)
+ for (int i = 0; i < numBodies; i++)
{
if (bodies[i].m_invMass)
{
int bodyOffset = offsetSplitBodies[i];
int count = bodyCount[i];
- float factor = 1.f/float(count);
+ float factor = 1.f / float(count);
b3Vector3 averageLinVel;
averageLinVel.setZero();
b3Vector3 averageAngVel;
averageAngVel.setZero();
- for (int j=0;j<count;j++)
+ for (int j = 0; j < count; j++)
{
- averageLinVel += deltaLinearVelocities[bodyOffset+j]*factor;
- averageAngVel += deltaAngularVelocities[bodyOffset+j]*factor;
+ averageLinVel += deltaLinearVelocities[bodyOffset + j] * factor;
+ averageAngVel += deltaAngularVelocities[bodyOffset + j] * factor;
}
- for (int j=0;j<count;j++)
+ for (int j = 0; j < count; j++)
{
- deltaLinearVelocities[bodyOffset+j] = averageLinVel;
- deltaAngularVelocities[bodyOffset+j] = averageAngVel;
+ deltaLinearVelocities[bodyOffset + j] = averageLinVel;
+ deltaAngularVelocities[bodyOffset + j] = averageAngVel;
}
}
}
-
-
-
}
-
//easy
- for (int i=0;i<numBodies;i++)
+ for (int i = 0; i < numBodies; i++)
{
if (bodies[i].m_invMass)
{
@@ -753,8 +696,6 @@ void b3GpuJacobiContactSolver::solveGroupHost(b3RigidBodyData* bodies,b3InertiaD
}
}
-
-
void b3GpuJacobiContactSolver::solveContacts(int numBodies, cl_mem bodyBuf, cl_mem inertiaBuf, int numContacts, cl_mem contactBuf, const struct b3Config& config, int static0Index)
//
//
@@ -762,49 +703,47 @@ void b3GpuJacobiContactSolver::solveContacts(int numBodies, cl_mem bodyBuf, cl_m
{
b3JacobiSolverInfo solverInfo;
solverInfo.m_fixedBodyIndex = static0Index;
-
B3_PROFILE("b3GpuJacobiContactSolver::solveGroup");
//int numBodies = bodies->size();
- int numManifolds = numContacts;//manifoldPtr->size();
+ int numManifolds = numContacts; //manifoldPtr->size();
{
B3_PROFILE("resize");
m_data->m_bodyCount->resize(numBodies);
}
-
- unsigned int val=0;
+
+ unsigned int val = 0;
b3Int2 val2;
- val2.x=0;
- val2.y=0;
+ val2.x = 0;
+ val2.y = 0;
- {
+ {
B3_PROFILE("m_filler");
m_data->m_contactConstraintOffsets->resize(numManifolds);
- m_data->m_filler->execute(*m_data->m_bodyCount,val,numBodies);
-
-
- m_data->m_filler->execute(*m_data->m_contactConstraintOffsets,val2,numManifolds);
+ m_data->m_filler->execute(*m_data->m_bodyCount, val, numBodies);
+
+ m_data->m_filler->execute(*m_data->m_contactConstraintOffsets, val2, numManifolds);
}
{
B3_PROFILE("m_countBodiesKernel");
- b3LauncherCL launcher(this->m_queue,m_data->m_countBodiesKernel,"m_countBodiesKernel");
- launcher.setBuffer(contactBuf);//manifoldPtr->getBufferCL());
+ b3LauncherCL launcher(this->m_queue, m_data->m_countBodiesKernel, "m_countBodiesKernel");
+ launcher.setBuffer(contactBuf); //manifoldPtr->getBufferCL());
launcher.setBuffer(m_data->m_bodyCount->getBufferCL());
launcher.setBuffer(m_data->m_contactConstraintOffsets->getBufferCL());
launcher.setConst(numManifolds);
launcher.setConst(solverInfo.m_fixedBodyIndex);
launcher.launch1D(numManifolds);
}
- unsigned int totalNumSplitBodies=0;
+ unsigned int totalNumSplitBodies = 0;
{
B3_PROFILE("m_scan->execute");
-
+
m_data->m_offsetSplitBodies->resize(numBodies);
- m_data->m_scan->execute(*m_data->m_bodyCount,*m_data->m_offsetSplitBodies,numBodies,&totalNumSplitBodies);
- totalNumSplitBodies+=m_data->m_bodyCount->at(numBodies-1);
+ m_data->m_scan->execute(*m_data->m_bodyCount, *m_data->m_offsetSplitBodies, numBodies, &totalNumSplitBodies);
+ totalNumSplitBodies += m_data->m_bodyCount->at(numBodies - 1);
}
{
@@ -812,50 +751,45 @@ void b3GpuJacobiContactSolver::solveContacts(int numBodies, cl_mem bodyBuf, cl_m
//int numContacts = manifoldPtr->size();
m_data->m_contactConstraints->resize(numContacts);
}
-
+
{
B3_PROFILE("contactToConstraintSplitKernel");
- b3LauncherCL launcher( m_queue, m_data->m_contactToConstraintSplitKernel,"m_contactToConstraintSplitKernel");
+ b3LauncherCL launcher(m_queue, m_data->m_contactToConstraintSplitKernel, "m_contactToConstraintSplitKernel");
launcher.setBuffer(contactBuf);
launcher.setBuffer(bodyBuf);
launcher.setBuffer(inertiaBuf);
launcher.setBuffer(m_data->m_contactConstraints->getBufferCL());
launcher.setBuffer(m_data->m_bodyCount->getBufferCL());
- launcher.setConst(numContacts);
+ launcher.setConst(numContacts);
launcher.setConst(solverInfo.m_deltaTime);
launcher.setConst(solverInfo.m_positionDrift);
launcher.setConst(solverInfo.m_positionConstraintCoeff);
- launcher.launch1D( numContacts, 64 );
-
+ launcher.launch1D(numContacts, 64);
}
-
{
B3_PROFILE("m_data->m_deltaLinearVelocities->resize");
m_data->m_deltaLinearVelocities->resize(totalNumSplitBodies);
m_data->m_deltaAngularVelocities->resize(totalNumSplitBodies);
}
-
-
{
B3_PROFILE("m_clearVelocitiesKernel");
- b3LauncherCL launch(m_queue,m_data->m_clearVelocitiesKernel,"m_clearVelocitiesKernel");
+ b3LauncherCL launch(m_queue, m_data->m_clearVelocitiesKernel, "m_clearVelocitiesKernel");
launch.setBuffer(m_data->m_deltaAngularVelocities->getBufferCL());
launch.setBuffer(m_data->m_deltaLinearVelocities->getBufferCL());
launch.setConst(totalNumSplitBodies);
launch.launch1D(totalNumSplitBodies);
clFinish(m_queue);
}
-
-
+
int maxIter = solverInfo.m_numIterations;
- for (int iter = 0;iter<maxIter;iter++)
+ for (int iter = 0; iter < maxIter; iter++)
{
{
B3_PROFILE("m_solveContactKernel");
- b3LauncherCL launcher( m_queue, m_data->m_solveContactKernel,"m_solveContactKernel" );
+ b3LauncherCL launcher(m_queue, m_data->m_solveContactKernel, "m_solveContactKernel");
launcher.setBuffer(m_data->m_contactConstraints->getBufferCL());
launcher.setBuffer(bodyBuf);
launcher.setBuffer(inertiaBuf);
@@ -873,11 +807,9 @@ void b3GpuJacobiContactSolver::solveContacts(int numBodies, cl_mem bodyBuf, cl_m
clFinish(m_queue);
}
-
-
{
B3_PROFILE("average velocities");
- b3LauncherCL launcher( m_queue, m_data->m_averageVelocitiesKernel,"m_averageVelocitiesKernel");
+ b3LauncherCL launcher(m_queue, m_data->m_averageVelocitiesKernel, "m_averageVelocitiesKernel");
launcher.setBuffer(bodyBuf);
launcher.setBuffer(m_data->m_offsetSplitBodies->getBufferCL());
launcher.setBuffer(m_data->m_bodyCount->getBufferCL());
@@ -888,10 +820,9 @@ void b3GpuJacobiContactSolver::solveContacts(int numBodies, cl_mem bodyBuf, cl_m
clFinish(m_queue);
}
-
{
B3_PROFILE("m_solveFrictionKernel");
- b3LauncherCL launcher( m_queue, m_data->m_solveFrictionKernel,"m_solveFrictionKernel");
+ b3LauncherCL launcher(m_queue, m_data->m_solveFrictionKernel, "m_solveFrictionKernel");
launcher.setBuffer(m_data->m_contactConstraints->getBufferCL());
launcher.setBuffer(bodyBuf);
launcher.setBuffer(inertiaBuf);
@@ -909,10 +840,9 @@ void b3GpuJacobiContactSolver::solveContacts(int numBodies, cl_mem bodyBuf, cl_m
clFinish(m_queue);
}
-
{
B3_PROFILE("average velocities");
- b3LauncherCL launcher( m_queue, m_data->m_averageVelocitiesKernel,"m_averageVelocitiesKernel");
+ b3LauncherCL launcher(m_queue, m_data->m_averageVelocitiesKernel, "m_averageVelocitiesKernel");
launcher.setBuffer(bodyBuf);
launcher.setBuffer(m_data->m_offsetSplitBodies->getBufferCL());
launcher.setBuffer(m_data->m_bodyCount->getBufferCL());
@@ -922,27 +852,20 @@ void b3GpuJacobiContactSolver::solveContacts(int numBodies, cl_mem bodyBuf, cl_m
launcher.launch1D(numBodies);
clFinish(m_queue);
}
-
-
-
}
-
{
- B3_PROFILE("update body velocities");
- b3LauncherCL launcher( m_queue, m_data->m_updateBodyVelocitiesKernel,"m_updateBodyVelocitiesKernel");
- launcher.setBuffer(bodyBuf);
- launcher.setBuffer(m_data->m_offsetSplitBodies->getBufferCL());
- launcher.setBuffer(m_data->m_bodyCount->getBufferCL());
- launcher.setBuffer(m_data->m_deltaLinearVelocities->getBufferCL());
- launcher.setBuffer(m_data->m_deltaAngularVelocities->getBufferCL());
- launcher.setConst(numBodies);
- launcher.launch1D(numBodies);
- clFinish(m_queue);
- }
-
-
-
+ B3_PROFILE("update body velocities");
+ b3LauncherCL launcher(m_queue, m_data->m_updateBodyVelocitiesKernel, "m_updateBodyVelocitiesKernel");
+ launcher.setBuffer(bodyBuf);
+ launcher.setBuffer(m_data->m_offsetSplitBodies->getBufferCL());
+ launcher.setBuffer(m_data->m_bodyCount->getBufferCL());
+ launcher.setBuffer(m_data->m_deltaLinearVelocities->getBufferCL());
+ launcher.setBuffer(m_data->m_deltaAngularVelocities->getBufferCL());
+ launcher.setConst(numBodies);
+ launcher.launch1D(numBodies);
+ clFinish(m_queue);
+ }
}
#if 0
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuJacobiContactSolver.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuJacobiContactSolver.h
index b418f29ec4..8281aee05d 100644
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuJacobiContactSolver.h
+++ b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuJacobiContactSolver.h
@@ -8,7 +8,6 @@
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
-
//struct b3InertiaData;
//b3InertiaData
@@ -21,21 +20,20 @@ struct b3JacobiSolverInfo
float m_deltaTime;
float m_positionDrift;
float m_positionConstraintCoeff;
- int m_numIterations;
+ int m_numIterations;
b3JacobiSolverInfo()
- :m_fixedBodyIndex(0),
- m_deltaTime(1./60.f),
- m_positionDrift( 0.005f ),
- m_positionConstraintCoeff( 0.99f ),
- m_numIterations(7)
+ : m_fixedBodyIndex(0),
+ m_deltaTime(1. / 60.f),
+ m_positionDrift(0.005f),
+ m_positionConstraintCoeff(0.99f),
+ m_numIterations(7)
{
}
};
class b3GpuJacobiContactSolver
{
protected:
-
struct b3GpuJacobiSolverInternalData* m_data;
cl_context m_context;
@@ -43,20 +41,16 @@ protected:
cl_command_queue m_queue;
public:
-
b3GpuJacobiContactSolver(cl_context ctx, cl_device_id device, cl_command_queue queue, int pairCapacity);
virtual ~b3GpuJacobiContactSolver();
-
void solveContacts(int numBodies, cl_mem bodyBuf, cl_mem inertiaBuf, int numContacts, cl_mem contactBuf, const struct b3Config& config, int static0Index);
- void solveGroupHost(b3RigidBodyData* bodies,b3InertiaData* inertias,int numBodies,struct b3Contact4* manifoldPtr, int numManifolds,const b3JacobiSolverInfo& solverInfo);
+ void solveGroupHost(b3RigidBodyData* bodies, b3InertiaData* inertias, int numBodies, struct b3Contact4* manifoldPtr, int numManifolds, const b3JacobiSolverInfo& solverInfo);
//void solveGroupHost(btRigidBodyCL* bodies,b3InertiaData* inertias,int numBodies,btContact4* manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btJacobiSolverInfo& solverInfo);
//b3Scalar solveGroup(b3OpenCLArray<b3RigidBodyData>* gpuBodies,b3OpenCLArray<b3InertiaData>* gpuInertias, int numBodies,b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints,int numConstraints,const b3ContactSolverInfo& infoGlobal);
//void solveGroup(btOpenCLArray<btRigidBodyCL>* bodies,btOpenCLArray<btInertiaCL>* inertias,btOpenCLArray<btContact4>* manifoldPtr,const btJacobiSolverInfo& solverInfo);
//void solveGroupMixed(btOpenCLArray<btRigidBodyCL>* bodies,btOpenCLArray<btInertiaCL>* inertias,btOpenCLArray<btContact4>* manifoldPtr,const btJacobiSolverInfo& solverInfo);
-
};
-#endif //B3_GPU_JACOBI_CONTACT_SOLVER_H
-
+#endif //B3_GPU_JACOBI_CONTACT_SOLVER_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuNarrowPhase.cpp b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuNarrowPhase.cpp
index 698fa15f96..2e4f6c1572 100644
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuNarrowPhase.cpp
+++ b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuNarrowPhase.cpp
@@ -1,6 +1,5 @@
#include "b3GpuNarrowPhase.h"
-
#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
#include "Bullet3OpenCL/NarrowphaseCollision/b3ConvexHullContact.h"
@@ -16,107 +15,87 @@
#include "Bullet3OpenCL/NarrowphaseCollision/b3QuantizedBvh.h"
#include "Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.h"
-
-
-
b3GpuNarrowPhase::b3GpuNarrowPhase(cl_context ctx, cl_device_id device, cl_command_queue queue, const b3Config& config)
-:m_data(0) ,m_planeBodyIndex(-1),m_static0Index(-1),
-m_context(ctx),
-m_device(device),
-m_queue(queue)
+ : m_data(0), m_planeBodyIndex(-1), m_static0Index(-1), m_context(ctx), m_device(device), m_queue(queue)
{
-
m_data = new b3GpuNarrowPhaseInternalData();
m_data->m_currentContactBuffer = 0;
- memset(m_data,0,sizeof(b3GpuNarrowPhaseInternalData));
-
+ memset(m_data, 0, sizeof(b3GpuNarrowPhaseInternalData));
m_data->m_config = config;
-
- m_data->m_gpuSatCollision = new GpuSatCollision(ctx,device,queue);
-
-
- m_data->m_triangleConvexPairs = new b3OpenCLArray<b3Int4>(m_context,m_queue, config.m_maxTriConvexPairCapacity);
+ m_data->m_gpuSatCollision = new GpuSatCollision(ctx, device, queue);
+
+ m_data->m_triangleConvexPairs = new b3OpenCLArray<b3Int4>(m_context, m_queue, config.m_maxTriConvexPairCapacity);
//m_data->m_convexPairsOutGPU = new b3OpenCLArray<b3Int2>(ctx,queue,config.m_maxBroadphasePairs,false);
//m_data->m_planePairs = new b3OpenCLArray<b3Int2>(ctx,queue,config.m_maxBroadphasePairs,false);
-
+
m_data->m_pBufContactOutCPU = new b3AlignedObjectArray<b3Contact4>();
m_data->m_pBufContactOutCPU->resize(config.m_maxBroadphasePairs);
m_data->m_bodyBufferCPU = new b3AlignedObjectArray<b3RigidBodyData>();
m_data->m_bodyBufferCPU->resize(config.m_maxConvexBodies);
-
+
m_data->m_inertiaBufferCPU = new b3AlignedObjectArray<b3InertiaData>();
m_data->m_inertiaBufferCPU->resize(config.m_maxConvexBodies);
-
- m_data->m_pBufContactBuffersGPU[0] = new b3OpenCLArray<b3Contact4>(ctx,queue, config.m_maxContactCapacity,true);
- m_data->m_pBufContactBuffersGPU[1] = new b3OpenCLArray<b3Contact4>(ctx,queue, config.m_maxContactCapacity,true);
-
- m_data->m_inertiaBufferGPU = new b3OpenCLArray<b3InertiaData>(ctx,queue,config.m_maxConvexBodies,false);
- m_data->m_collidablesGPU = new b3OpenCLArray<b3Collidable>(ctx,queue,config.m_maxConvexShapes);
+
+ m_data->m_pBufContactBuffersGPU[0] = new b3OpenCLArray<b3Contact4>(ctx, queue, config.m_maxContactCapacity, true);
+ m_data->m_pBufContactBuffersGPU[1] = new b3OpenCLArray<b3Contact4>(ctx, queue, config.m_maxContactCapacity, true);
+
+ m_data->m_inertiaBufferGPU = new b3OpenCLArray<b3InertiaData>(ctx, queue, config.m_maxConvexBodies, false);
+ m_data->m_collidablesGPU = new b3OpenCLArray<b3Collidable>(ctx, queue, config.m_maxConvexShapes);
m_data->m_collidablesCPU.reserve(config.m_maxConvexShapes);
m_data->m_localShapeAABBCPU = new b3AlignedObjectArray<b3SapAabb>;
- m_data->m_localShapeAABBGPU = new b3OpenCLArray<b3SapAabb>(ctx,queue,config.m_maxConvexShapes);
-
-
+ m_data->m_localShapeAABBGPU = new b3OpenCLArray<b3SapAabb>(ctx, queue, config.m_maxConvexShapes);
+
//m_data->m_solverDataGPU = adl::Solver<adl::TYPE_CL>::allocate(ctx,queue, config.m_maxBroadphasePairs,false);
- m_data->m_bodyBufferGPU = new b3OpenCLArray<b3RigidBodyData>(ctx,queue, config.m_maxConvexBodies,false);
+ m_data->m_bodyBufferGPU = new b3OpenCLArray<b3RigidBodyData>(ctx, queue, config.m_maxConvexBodies, false);
- m_data->m_convexFacesGPU = new b3OpenCLArray<b3GpuFace>(ctx,queue,config.m_maxConvexShapes*config.m_maxFacesPerShape,false);
- m_data->m_convexFaces.reserve(config.m_maxConvexShapes*config.m_maxFacesPerShape);
+ m_data->m_convexFacesGPU = new b3OpenCLArray<b3GpuFace>(ctx, queue, config.m_maxConvexShapes * config.m_maxFacesPerShape, false);
+ m_data->m_convexFaces.reserve(config.m_maxConvexShapes * config.m_maxFacesPerShape);
- m_data->m_gpuChildShapes = new b3OpenCLArray<b3GpuChildShape>(ctx,queue,config.m_maxCompoundChildShapes,false);
-
- m_data->m_convexPolyhedraGPU = new b3OpenCLArray<b3ConvexPolyhedronData>(ctx,queue,config.m_maxConvexShapes,false);
+ m_data->m_gpuChildShapes = new b3OpenCLArray<b3GpuChildShape>(ctx, queue, config.m_maxCompoundChildShapes, false);
+
+ m_data->m_convexPolyhedraGPU = new b3OpenCLArray<b3ConvexPolyhedronData>(ctx, queue, config.m_maxConvexShapes, false);
m_data->m_convexPolyhedra.reserve(config.m_maxConvexShapes);
- m_data->m_uniqueEdgesGPU = new b3OpenCLArray<b3Vector3>(ctx,queue,config.m_maxConvexUniqueEdges,true);
+ m_data->m_uniqueEdgesGPU = new b3OpenCLArray<b3Vector3>(ctx, queue, config.m_maxConvexUniqueEdges, true);
m_data->m_uniqueEdges.reserve(config.m_maxConvexUniqueEdges);
-
-
- m_data->m_convexVerticesGPU = new b3OpenCLArray<b3Vector3>(ctx,queue,config.m_maxConvexVertices,true);
+ m_data->m_convexVerticesGPU = new b3OpenCLArray<b3Vector3>(ctx, queue, config.m_maxConvexVertices, true);
m_data->m_convexVertices.reserve(config.m_maxConvexVertices);
- m_data->m_convexIndicesGPU = new b3OpenCLArray<int>(ctx,queue,config.m_maxConvexIndices,true);
- m_data->m_convexIndices.reserve(config.m_maxConvexIndices);
-
- m_data->m_worldVertsB1GPU = new b3OpenCLArray<b3Vector3>(ctx,queue,config.m_maxConvexBodies*config.m_maxVerticesPerFace);
- m_data->m_clippingFacesOutGPU = new b3OpenCLArray<b3Int4>(ctx,queue,config.m_maxConvexBodies);
- m_data->m_worldNormalsAGPU = new b3OpenCLArray<b3Vector3>(ctx,queue,config.m_maxConvexBodies);
- m_data->m_worldVertsA1GPU = new b3OpenCLArray<b3Vector3>(ctx,queue,config.m_maxConvexBodies*config.m_maxVerticesPerFace);
- m_data->m_worldVertsB2GPU = new b3OpenCLArray<b3Vector3>(ctx,queue,config.m_maxConvexBodies*config.m_maxVerticesPerFace);
-
-
+ m_data->m_convexIndicesGPU = new b3OpenCLArray<int>(ctx, queue, config.m_maxConvexIndices, true);
+ m_data->m_convexIndices.reserve(config.m_maxConvexIndices);
+
+ m_data->m_worldVertsB1GPU = new b3OpenCLArray<b3Vector3>(ctx, queue, config.m_maxConvexBodies * config.m_maxVerticesPerFace);
+ m_data->m_clippingFacesOutGPU = new b3OpenCLArray<b3Int4>(ctx, queue, config.m_maxConvexBodies);
+ m_data->m_worldNormalsAGPU = new b3OpenCLArray<b3Vector3>(ctx, queue, config.m_maxConvexBodies);
+ m_data->m_worldVertsA1GPU = new b3OpenCLArray<b3Vector3>(ctx, queue, config.m_maxConvexBodies * config.m_maxVerticesPerFace);
+ m_data->m_worldVertsB2GPU = new b3OpenCLArray<b3Vector3>(ctx, queue, config.m_maxConvexBodies * config.m_maxVerticesPerFace);
- m_data->m_convexData = new b3AlignedObjectArray<b3ConvexUtility* >();
+ m_data->m_convexData = new b3AlignedObjectArray<b3ConvexUtility*>();
m_data->m_convexData->resize(config.m_maxConvexShapes);
m_data->m_convexPolyhedra.resize(config.m_maxConvexShapes);
-
+
m_data->m_numAcceleratedShapes = 0;
m_data->m_numAcceleratedRigidBodies = 0;
-
-
- m_data->m_subTreesGPU = new b3OpenCLArray<b3BvhSubtreeInfo>(this->m_context,this->m_queue);
- m_data->m_treeNodesGPU = new b3OpenCLArray<b3QuantizedBvhNode>(this->m_context,this->m_queue);
- m_data->m_bvhInfoGPU = new b3OpenCLArray<b3BvhInfo>(this->m_context,this->m_queue);
+
+ m_data->m_subTreesGPU = new b3OpenCLArray<b3BvhSubtreeInfo>(this->m_context, this->m_queue);
+ m_data->m_treeNodesGPU = new b3OpenCLArray<b3QuantizedBvhNode>(this->m_context, this->m_queue);
+ m_data->m_bvhInfoGPU = new b3OpenCLArray<b3BvhInfo>(this->m_context, this->m_queue);
//m_data->m_contactCGPU = new b3OpenCLArray<Constraint4>(ctx,queue,config.m_maxBroadphasePairs,false);
//m_data->m_frictionCGPU = new b3OpenCLArray<adl::Solver<adl::TYPE_CL>::allocateFrictionConstraint( m_data->m_deviceCL, config.m_maxBroadphasePairs);
-
-
-
}
-
b3GpuNarrowPhase::~b3GpuNarrowPhase()
{
delete m_data->m_gpuSatCollision;
-
+
delete m_data->m_triangleConvexPairs;
//delete m_data->m_convexPairsOutGPU;
//delete m_data->m_planePairs;
@@ -126,7 +105,6 @@ b3GpuNarrowPhase::~b3GpuNarrowPhase()
delete m_data->m_pBufContactBuffersGPU[0];
delete m_data->m_pBufContactBuffersGPU[1];
-
delete m_data->m_inertiaBufferGPU;
delete m_data->m_collidablesGPU;
delete m_data->m_localShapeAABBCPU;
@@ -139,18 +117,18 @@ b3GpuNarrowPhase::~b3GpuNarrowPhase()
delete m_data->m_convexVerticesGPU;
delete m_data->m_convexIndicesGPU;
delete m_data->m_worldVertsB1GPU;
- delete m_data->m_clippingFacesOutGPU;
- delete m_data->m_worldNormalsAGPU;
+ delete m_data->m_clippingFacesOutGPU;
+ delete m_data->m_worldNormalsAGPU;
delete m_data->m_worldVertsA1GPU;
- delete m_data->m_worldVertsB2GPU;
-
+ delete m_data->m_worldVertsB2GPU;
+
delete m_data->m_bvhInfoGPU;
- for (int i=0;i<m_data->m_bvhData.size();i++)
+ for (int i = 0; i < m_data->m_bvhData.size(); i++)
{
delete m_data->m_bvhData[i];
}
- for (int i=0;i<m_data->m_meshInterfaces.size();i++)
+ for (int i = 0; i < m_data->m_meshInterfaces.size(); i++)
{
delete m_data->m_meshInterfaces[i];
}
@@ -159,198 +137,180 @@ b3GpuNarrowPhase::~b3GpuNarrowPhase()
delete m_data->m_treeNodesGPU;
delete m_data->m_subTreesGPU;
-
- delete m_data->m_convexData;
+ delete m_data->m_convexData;
delete m_data;
}
-
-int b3GpuNarrowPhase::allocateCollidable()
+int b3GpuNarrowPhase::allocateCollidable()
{
int curSize = m_data->m_collidablesCPU.size();
- if (curSize<m_data->m_config.m_maxConvexShapes)
+ if (curSize < m_data->m_config.m_maxConvexShapes)
{
m_data->m_collidablesCPU.expand();
return curSize;
}
else
{
- b3Error("allocateCollidable out-of-range %d\n",m_data->m_config.m_maxConvexShapes);
+ b3Error("allocateCollidable out-of-range %d\n", m_data->m_config.m_maxConvexShapes);
}
return -1;
-
}
-
-
-
-
-int b3GpuNarrowPhase::registerSphereShape(float radius)
+int b3GpuNarrowPhase::registerSphereShape(float radius)
{
int collidableIndex = allocateCollidable();
- if (collidableIndex<0)
+ if (collidableIndex < 0)
return collidableIndex;
-
b3Collidable& col = getCollidableCpu(collidableIndex);
col.m_shapeType = SHAPE_SPHERE;
col.m_shapeIndex = 0;
col.m_radius = radius;
-
- if (col.m_shapeIndex>=0)
+
+ if (col.m_shapeIndex >= 0)
{
b3SapAabb aabb;
- b3Vector3 myAabbMin=b3MakeVector3(-radius,-radius,-radius);
- b3Vector3 myAabbMax=b3MakeVector3(radius,radius,radius);
+ b3Vector3 myAabbMin = b3MakeVector3(-radius, -radius, -radius);
+ b3Vector3 myAabbMax = b3MakeVector3(radius, radius, radius);
- aabb.m_min[0] = myAabbMin[0];//s_convexHeightField->m_aabb.m_min.x;
- aabb.m_min[1] = myAabbMin[1];//s_convexHeightField->m_aabb.m_min.y;
- aabb.m_min[2] = myAabbMin[2];//s_convexHeightField->m_aabb.m_min.z;
+ aabb.m_min[0] = myAabbMin[0]; //s_convexHeightField->m_aabb.m_min.x;
+ aabb.m_min[1] = myAabbMin[1]; //s_convexHeightField->m_aabb.m_min.y;
+ aabb.m_min[2] = myAabbMin[2]; //s_convexHeightField->m_aabb.m_min.z;
aabb.m_minIndices[3] = 0;
- aabb.m_max[0] = myAabbMax[0];//s_convexHeightField->m_aabb.m_max.x;
- aabb.m_max[1] = myAabbMax[1];//s_convexHeightField->m_aabb.m_max.y;
- aabb.m_max[2] = myAabbMax[2];//s_convexHeightField->m_aabb.m_max.z;
+ aabb.m_max[0] = myAabbMax[0]; //s_convexHeightField->m_aabb.m_max.x;
+ aabb.m_max[1] = myAabbMax[1]; //s_convexHeightField->m_aabb.m_max.y;
+ aabb.m_max[2] = myAabbMax[2]; //s_convexHeightField->m_aabb.m_max.z;
aabb.m_signedMaxIndices[3] = 0;
m_data->m_localShapeAABBCPU->push_back(aabb);
-// m_data->m_localShapeAABBGPU->push_back(aabb);
+ // m_data->m_localShapeAABBGPU->push_back(aabb);
clFinish(m_queue);
}
-
+
return collidableIndex;
}
-
int b3GpuNarrowPhase::registerFace(const b3Vector3& faceNormal, float faceConstant)
{
int faceOffset = m_data->m_convexFaces.size();
b3GpuFace& face = m_data->m_convexFaces.expand();
- face.m_plane = b3MakeVector3(faceNormal.x,faceNormal.y,faceNormal.z,faceConstant);
+ face.m_plane = b3MakeVector3(faceNormal.x, faceNormal.y, faceNormal.z, faceConstant);
return faceOffset;
}
-int b3GpuNarrowPhase::registerPlaneShape(const b3Vector3& planeNormal, float planeConstant)
+int b3GpuNarrowPhase::registerPlaneShape(const b3Vector3& planeNormal, float planeConstant)
{
int collidableIndex = allocateCollidable();
- if (collidableIndex<0)
+ if (collidableIndex < 0)
return collidableIndex;
-
b3Collidable& col = getCollidableCpu(collidableIndex);
col.m_shapeType = SHAPE_PLANE;
- col.m_shapeIndex = registerFace(planeNormal,planeConstant);
+ col.m_shapeIndex = registerFace(planeNormal, planeConstant);
col.m_radius = planeConstant;
-
- if (col.m_shapeIndex>=0)
+
+ if (col.m_shapeIndex >= 0)
{
b3SapAabb aabb;
aabb.m_min[0] = -1e30f;
aabb.m_min[1] = -1e30f;
aabb.m_min[2] = -1e30f;
aabb.m_minIndices[3] = 0;
-
+
aabb.m_max[0] = 1e30f;
aabb.m_max[1] = 1e30f;
aabb.m_max[2] = 1e30f;
aabb.m_signedMaxIndices[3] = 0;
m_data->m_localShapeAABBCPU->push_back(aabb);
-// m_data->m_localShapeAABBGPU->push_back(aabb);
+ // m_data->m_localShapeAABBGPU->push_back(aabb);
clFinish(m_queue);
}
-
+
return collidableIndex;
}
-
-int b3GpuNarrowPhase::registerConvexHullShapeInternal(b3ConvexUtility* convexPtr,b3Collidable& col)
+int b3GpuNarrowPhase::registerConvexHullShapeInternal(b3ConvexUtility* convexPtr, b3Collidable& col)
{
+ m_data->m_convexData->resize(m_data->m_numAcceleratedShapes + 1);
+ m_data->m_convexPolyhedra.resize(m_data->m_numAcceleratedShapes + 1);
- m_data->m_convexData->resize(m_data->m_numAcceleratedShapes+1);
- m_data->m_convexPolyhedra.resize(m_data->m_numAcceleratedShapes+1);
-
-
- b3ConvexPolyhedronData& convex = m_data->m_convexPolyhedra.at(m_data->m_convexPolyhedra.size()-1);
+ b3ConvexPolyhedronData& convex = m_data->m_convexPolyhedra.at(m_data->m_convexPolyhedra.size() - 1);
convex.mC = convexPtr->mC;
convex.mE = convexPtr->mE;
- convex.m_extents= convexPtr->m_extents;
+ convex.m_extents = convexPtr->m_extents;
convex.m_localCenter = convexPtr->m_localCenter;
convex.m_radius = convexPtr->m_radius;
-
+
convex.m_numUniqueEdges = convexPtr->m_uniqueEdges.size();
int edgeOffset = m_data->m_uniqueEdges.size();
convex.m_uniqueEdgesOffset = edgeOffset;
-
- m_data->m_uniqueEdges.resize(edgeOffset+convex.m_numUniqueEdges);
-
+
+ m_data->m_uniqueEdges.resize(edgeOffset + convex.m_numUniqueEdges);
+
//convex data here
int i;
- for ( i=0;i<convexPtr->m_uniqueEdges.size();i++)
+ for (i = 0; i < convexPtr->m_uniqueEdges.size(); i++)
{
- m_data->m_uniqueEdges[edgeOffset+i] = convexPtr->m_uniqueEdges[i];
+ m_data->m_uniqueEdges[edgeOffset + i] = convexPtr->m_uniqueEdges[i];
}
-
+
int faceOffset = m_data->m_convexFaces.size();
convex.m_faceOffset = faceOffset;
convex.m_numFaces = convexPtr->m_faces.size();
- m_data->m_convexFaces.resize(faceOffset+convex.m_numFaces);
-
+ m_data->m_convexFaces.resize(faceOffset + convex.m_numFaces);
- for (i=0;i<convexPtr->m_faces.size();i++)
+ for (i = 0; i < convexPtr->m_faces.size(); i++)
{
- m_data->m_convexFaces[convex.m_faceOffset+i].m_plane = b3MakeVector3(convexPtr->m_faces[i].m_plane[0],
- convexPtr->m_faces[i].m_plane[1],
- convexPtr->m_faces[i].m_plane[2],
- convexPtr->m_faces[i].m_plane[3]);
+ m_data->m_convexFaces[convex.m_faceOffset + i].m_plane = b3MakeVector3(convexPtr->m_faces[i].m_plane[0],
+ convexPtr->m_faces[i].m_plane[1],
+ convexPtr->m_faces[i].m_plane[2],
+ convexPtr->m_faces[i].m_plane[3]);
-
int indexOffset = m_data->m_convexIndices.size();
int numIndices = convexPtr->m_faces[i].m_indices.size();
- m_data->m_convexFaces[convex.m_faceOffset+i].m_numIndices = numIndices;
- m_data->m_convexFaces[convex.m_faceOffset+i].m_indexOffset = indexOffset;
- m_data->m_convexIndices.resize(indexOffset+numIndices);
- for (int p=0;p<numIndices;p++)
+ m_data->m_convexFaces[convex.m_faceOffset + i].m_numIndices = numIndices;
+ m_data->m_convexFaces[convex.m_faceOffset + i].m_indexOffset = indexOffset;
+ m_data->m_convexIndices.resize(indexOffset + numIndices);
+ for (int p = 0; p < numIndices; p++)
{
- m_data->m_convexIndices[indexOffset+p] = convexPtr->m_faces[i].m_indices[p];
+ m_data->m_convexIndices[indexOffset + p] = convexPtr->m_faces[i].m_indices[p];
}
}
-
+
convex.m_numVertices = convexPtr->m_vertices.size();
int vertexOffset = m_data->m_convexVertices.size();
- convex.m_vertexOffset =vertexOffset;
-
- m_data->m_convexVertices.resize(vertexOffset+convex.m_numVertices);
- for (int i=0;i<convexPtr->m_vertices.size();i++)
+ convex.m_vertexOffset = vertexOffset;
+
+ m_data->m_convexVertices.resize(vertexOffset + convex.m_numVertices);
+ for (int i = 0; i < convexPtr->m_vertices.size(); i++)
{
- m_data->m_convexVertices[vertexOffset+i] = convexPtr->m_vertices[i];
+ m_data->m_convexVertices[vertexOffset + i] = convexPtr->m_vertices[i];
}
(*m_data->m_convexData)[m_data->m_numAcceleratedShapes] = convexPtr;
-
-
-
+
return m_data->m_numAcceleratedShapes++;
}
-
-int b3GpuNarrowPhase::registerConvexHullShape(const float* vertices, int strideInBytes, int numVertices, const float* scaling)
+int b3GpuNarrowPhase::registerConvexHullShape(const float* vertices, int strideInBytes, int numVertices, const float* scaling)
{
b3AlignedObjectArray<b3Vector3> verts;
- unsigned char* vts = (unsigned char*) vertices;
- for (int i=0;i<numVertices;i++)
+ unsigned char* vts = (unsigned char*)vertices;
+ for (int i = 0; i < numVertices; i++)
{
- float* vertex = (float*) &vts[i*strideInBytes];
- verts.push_back(b3MakeVector3(vertex[0]*scaling[0],vertex[1]*scaling[1],vertex[2]*scaling[2]));
+ float* vertex = (float*)&vts[i * strideInBytes];
+ verts.push_back(b3MakeVector3(vertex[0] * scaling[0], vertex[1] * scaling[1], vertex[2] * scaling[2]));
}
b3ConvexUtility* utilPtr = new b3ConvexUtility();
bool merge = true;
if (numVertices)
{
- utilPtr->initializePolyhedralFeatures(&verts[0],verts.size(),merge);
+ utilPtr->initializePolyhedralFeatures(&verts[0], verts.size(), merge);
}
int collidableIndex = registerConvexHullShape(utilPtr);
@@ -358,35 +318,34 @@ int b3GpuNarrowPhase::registerConvexHullShape(const float* vertices, int stride
return collidableIndex;
}
-int b3GpuNarrowPhase::registerConvexHullShape(b3ConvexUtility* utilPtr)
+int b3GpuNarrowPhase::registerConvexHullShape(b3ConvexUtility* utilPtr)
{
int collidableIndex = allocateCollidable();
- if (collidableIndex<0)
+ if (collidableIndex < 0)
return collidableIndex;
b3Collidable& col = getCollidableCpu(collidableIndex);
col.m_shapeType = SHAPE_CONVEX_HULL;
col.m_shapeIndex = -1;
-
-
+
{
- b3Vector3 localCenter=b3MakeVector3(0,0,0);
- for (int i=0;i<utilPtr->m_vertices.size();i++)
- localCenter+=utilPtr->m_vertices[i];
- localCenter*= (1.f/utilPtr->m_vertices.size());
+ b3Vector3 localCenter = b3MakeVector3(0, 0, 0);
+ for (int i = 0; i < utilPtr->m_vertices.size(); i++)
+ localCenter += utilPtr->m_vertices[i];
+ localCenter *= (1.f / utilPtr->m_vertices.size());
utilPtr->m_localCenter = localCenter;
- col.m_shapeIndex = registerConvexHullShapeInternal(utilPtr,col);
+ col.m_shapeIndex = registerConvexHullShapeInternal(utilPtr, col);
}
- if (col.m_shapeIndex>=0)
+ if (col.m_shapeIndex >= 0)
{
b3SapAabb aabb;
-
- b3Vector3 myAabbMin=b3MakeVector3(1e30f,1e30f,1e30f);
- b3Vector3 myAabbMax=b3MakeVector3(-1e30f,-1e30f,-1e30f);
- for (int i=0;i<utilPtr->m_vertices.size();i++)
+ b3Vector3 myAabbMin = b3MakeVector3(1e30f, 1e30f, 1e30f);
+ b3Vector3 myAabbMax = b3MakeVector3(-1e30f, -1e30f, -1e30f);
+
+ for (int i = 0; i < utilPtr->m_vertices.size(); i++)
{
myAabbMin.setMin(utilPtr->m_vertices[i]);
myAabbMax.setMax(utilPtr->m_vertices[i]);
@@ -402,18 +361,16 @@ int b3GpuNarrowPhase::registerConvexHullShape(b3ConvexUtility* utilPtr)
aabb.m_signedMaxIndices[3] = 0;
m_data->m_localShapeAABBCPU->push_back(aabb);
-// m_data->m_localShapeAABBGPU->push_back(aabb);
+ // m_data->m_localShapeAABBGPU->push_back(aabb);
}
-
- return collidableIndex;
+ return collidableIndex;
}
-int b3GpuNarrowPhase::registerCompoundShape(b3AlignedObjectArray<b3GpuChildShape>* childShapes)
+int b3GpuNarrowPhase::registerCompoundShape(b3AlignedObjectArray<b3GpuChildShape>* childShapes)
{
-
int collidableIndex = allocateCollidable();
- if (collidableIndex<0)
+ if (collidableIndex < 0)
return collidableIndex;
b3Collidable& col = getCollidableCpu(collidableIndex);
@@ -422,44 +379,41 @@ int b3GpuNarrowPhase::registerCompoundShape(b3AlignedObjectArray<b3GpuChildShap
col.m_compoundBvhIndex = m_data->m_bvhInfoCPU.size();
{
- b3Assert(col.m_shapeIndex+childShapes->size()<m_data->m_config.m_maxCompoundChildShapes);
- for (int i=0;i<childShapes->size();i++)
+ b3Assert(col.m_shapeIndex + childShapes->size() < m_data->m_config.m_maxCompoundChildShapes);
+ for (int i = 0; i < childShapes->size(); i++)
{
m_data->m_cpuChildShapes.push_back(childShapes->at(i));
}
}
-
-
col.m_numChildShapes = childShapes->size();
-
-
+
b3SapAabb aabbLocalSpace;
- b3Vector3 myAabbMin=b3MakeVector3(1e30f,1e30f,1e30f);
- b3Vector3 myAabbMax=b3MakeVector3(-1e30f,-1e30f,-1e30f);
-
+ b3Vector3 myAabbMin = b3MakeVector3(1e30f, 1e30f, 1e30f);
+ b3Vector3 myAabbMax = b3MakeVector3(-1e30f, -1e30f, -1e30f);
+
b3AlignedObjectArray<b3Aabb> childLocalAabbs;
childLocalAabbs.resize(childShapes->size());
//compute local AABB of the compound of all children
- for (int i=0;i<childShapes->size();i++)
+ for (int i = 0; i < childShapes->size(); i++)
{
int childColIndex = childShapes->at(i).m_shapeIndex;
//b3Collidable& childCol = getCollidableCpu(childColIndex);
- b3SapAabb aabbLoc =m_data->m_localShapeAABBCPU->at(childColIndex);
+ b3SapAabb aabbLoc = m_data->m_localShapeAABBCPU->at(childColIndex);
- b3Vector3 childLocalAabbMin=b3MakeVector3(aabbLoc.m_min[0],aabbLoc.m_min[1],aabbLoc.m_min[2]);
- b3Vector3 childLocalAabbMax=b3MakeVector3(aabbLoc.m_max[0],aabbLoc.m_max[1],aabbLoc.m_max[2]);
- b3Vector3 aMin,aMax;
+ b3Vector3 childLocalAabbMin = b3MakeVector3(aabbLoc.m_min[0], aabbLoc.m_min[1], aabbLoc.m_min[2]);
+ b3Vector3 childLocalAabbMax = b3MakeVector3(aabbLoc.m_max[0], aabbLoc.m_max[1], aabbLoc.m_max[2]);
+ b3Vector3 aMin, aMax;
b3Scalar margin(0.f);
b3Transform childTr;
childTr.setIdentity();
childTr.setOrigin(childShapes->at(i).m_childPosition);
childTr.setRotation(b3Quaternion(childShapes->at(i).m_childOrientation));
- b3TransformAabb(childLocalAabbMin,childLocalAabbMax,margin,childTr,aMin,aMax);
+ b3TransformAabb(childLocalAabbMin, childLocalAabbMax, margin, childTr, aMin, aMax);
myAabbMin.setMin(aMin);
- myAabbMax.setMax(aMax);
+ myAabbMax.setMax(aMax);
childLocalAabbs[i].m_min[0] = aMin[0];
childLocalAabbs[i].m_min[1] = aMin[1];
childLocalAabbs[i].m_min[2] = aMin[2];
@@ -469,36 +423,35 @@ int b3GpuNarrowPhase::registerCompoundShape(b3AlignedObjectArray<b3GpuChildShap
childLocalAabbs[i].m_max[2] = aMax[2];
childLocalAabbs[i].m_max[3] = 0;
}
-
- aabbLocalSpace.m_min[0] = myAabbMin[0];//s_convexHeightField->m_aabb.m_min.x;
- aabbLocalSpace.m_min[1]= myAabbMin[1];//s_convexHeightField->m_aabb.m_min.y;
- aabbLocalSpace.m_min[2]= myAabbMin[2];//s_convexHeightField->m_aabb.m_min.z;
+
+ aabbLocalSpace.m_min[0] = myAabbMin[0]; //s_convexHeightField->m_aabb.m_min.x;
+ aabbLocalSpace.m_min[1] = myAabbMin[1]; //s_convexHeightField->m_aabb.m_min.y;
+ aabbLocalSpace.m_min[2] = myAabbMin[2]; //s_convexHeightField->m_aabb.m_min.z;
aabbLocalSpace.m_minIndices[3] = 0;
-
- aabbLocalSpace.m_max[0] = myAabbMax[0];//s_convexHeightField->m_aabb.m_max.x;
- aabbLocalSpace.m_max[1]= myAabbMax[1];//s_convexHeightField->m_aabb.m_max.y;
- aabbLocalSpace.m_max[2]= myAabbMax[2];//s_convexHeightField->m_aabb.m_max.z;
+
+ aabbLocalSpace.m_max[0] = myAabbMax[0]; //s_convexHeightField->m_aabb.m_max.x;
+ aabbLocalSpace.m_max[1] = myAabbMax[1]; //s_convexHeightField->m_aabb.m_max.y;
+ aabbLocalSpace.m_max[2] = myAabbMax[2]; //s_convexHeightField->m_aabb.m_max.z;
aabbLocalSpace.m_signedMaxIndices[3] = 0;
-
- m_data->m_localShapeAABBCPU->push_back(aabbLocalSpace);
+ m_data->m_localShapeAABBCPU->push_back(aabbLocalSpace);
b3QuantizedBvh* bvh = new b3QuantizedBvh;
- bvh->setQuantizationValues(myAabbMin,myAabbMax);
- QuantizedNodeArray& nodes = bvh->getLeafNodeArray();
+ bvh->setQuantizationValues(myAabbMin, myAabbMax);
+ QuantizedNodeArray& nodes = bvh->getLeafNodeArray();
int numNodes = childShapes->size();
- for (int i=0;i<numNodes;i++)
+ for (int i = 0; i < numNodes; i++)
{
b3QuantizedBvhNode node;
- b3Vector3 aabbMin,aabbMax;
- aabbMin = (b3Vector3&) childLocalAabbs[i].m_min;
- aabbMax = (b3Vector3&) childLocalAabbs[i].m_max;
+ b3Vector3 aabbMin, aabbMax;
+ aabbMin = (b3Vector3&)childLocalAabbs[i].m_min;
+ aabbMax = (b3Vector3&)childLocalAabbs[i].m_max;
- bvh->quantize(&node.m_quantizedAabbMin[0],aabbMin,0);
- bvh->quantize(&node.m_quantizedAabbMax[0],aabbMax,1);
+ bvh->quantize(&node.m_quantizedAabbMin[0], aabbMin, 0);
+ bvh->quantize(&node.m_quantizedAabbMax[0], aabbMax, 1);
int partId = 0;
- node.m_escapeIndexOrTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | i;
+ node.m_escapeIndexOrTriangleIndex = (partId << (31 - MAX_NUM_PARTS_IN_BITS)) | i;
nodes.push_back(node);
}
bvh->buildInternal();
@@ -511,7 +464,7 @@ int b3GpuNarrowPhase::registerCompoundShape(b3AlignedObjectArray<b3GpuChildShap
//void buildInternal();
b3BvhInfo bvhInfo;
-
+
bvhInfo.m_aabbMin = bvh->m_bvhAabbMin;
bvhInfo.m_aabbMax = bvh->m_bvhAabbMax;
bvhInfo.m_quantization = bvh->m_bvhQuantization;
@@ -520,80 +473,72 @@ int b3GpuNarrowPhase::registerCompoundShape(b3AlignedObjectArray<b3GpuChildShap
bvhInfo.m_nodeOffset = m_data->m_treeNodesCPU.size();
bvhInfo.m_subTreeOffset = m_data->m_subTreesCPU.size();
- int numNewNodes = bvh->getQuantizedNodeArray().size();
+ int numNewNodes = bvh->getQuantizedNodeArray().size();
- for (int i=0;i<numNewNodes-1;i++)
+ for (int i = 0; i < numNewNodes - 1; i++)
{
-
if (bvh->getQuantizedNodeArray()[i].isLeafNode())
{
int orgIndex = bvh->getQuantizedNodeArray()[i].getTriangleIndex();
b3Vector3 nodeMinVec = bvh->unQuantize(bvh->getQuantizedNodeArray()[i].m_quantizedAabbMin);
b3Vector3 nodeMaxVec = bvh->unQuantize(bvh->getQuantizedNodeArray()[i].m_quantizedAabbMax);
-
- for (int c=0;c<3;c++)
+
+ for (int c = 0; c < 3; c++)
{
if (childLocalAabbs[orgIndex].m_min[c] < nodeMinVec[c])
{
- printf("min org (%f) and new (%f) ? at i:%d,c:%d\n",childLocalAabbs[i].m_min[c],nodeMinVec[c],i,c);
+ printf("min org (%f) and new (%f) ? at i:%d,c:%d\n", childLocalAabbs[i].m_min[c], nodeMinVec[c], i, c);
}
if (childLocalAabbs[orgIndex].m_max[c] > nodeMaxVec[c])
{
- printf("max org (%f) and new (%f) ? at i:%d,c:%d\n",childLocalAabbs[i].m_max[c],nodeMaxVec[c],i,c);
+ printf("max org (%f) and new (%f) ? at i:%d,c:%d\n", childLocalAabbs[i].m_max[c], nodeMaxVec[c], i, c);
}
-
}
}
-
}
m_data->m_bvhInfoCPU.push_back(bvhInfo);
int numNewSubtrees = bvh->getSubtreeInfoArray().size();
- m_data->m_subTreesCPU.reserve(m_data->m_subTreesCPU.size()+numNewSubtrees);
- for (int i=0;i<numNewSubtrees;i++)
+ m_data->m_subTreesCPU.reserve(m_data->m_subTreesCPU.size() + numNewSubtrees);
+ for (int i = 0; i < numNewSubtrees; i++)
{
m_data->m_subTreesCPU.push_back(bvh->getSubtreeInfoArray()[i]);
}
int numNewTreeNodes = bvh->getQuantizedNodeArray().size();
- for (int i=0;i<numNewTreeNodes;i++)
+ for (int i = 0; i < numNewTreeNodes; i++)
{
m_data->m_treeNodesCPU.push_back(bvh->getQuantizedNodeArray()[i]);
}
-// m_data->m_localShapeAABBGPU->push_back(aabbWS);
+ // m_data->m_localShapeAABBGPU->push_back(aabbWS);
clFinish(m_queue);
return collidableIndex;
-
}
-
-int b3GpuNarrowPhase::registerConcaveMesh(b3AlignedObjectArray<b3Vector3>* vertices, b3AlignedObjectArray<int>* indices,const float* scaling1)
+int b3GpuNarrowPhase::registerConcaveMesh(b3AlignedObjectArray<b3Vector3>* vertices, b3AlignedObjectArray<int>* indices, const float* scaling1)
{
-
-
- b3Vector3 scaling=b3MakeVector3(scaling1[0],scaling1[1],scaling1[2]);
+ b3Vector3 scaling = b3MakeVector3(scaling1[0], scaling1[1], scaling1[2]);
int collidableIndex = allocateCollidable();
- if (collidableIndex<0)
+ if (collidableIndex < 0)
return collidableIndex;
b3Collidable& col = getCollidableCpu(collidableIndex);
-
+
col.m_shapeType = SHAPE_CONCAVE_TRIMESH;
- col.m_shapeIndex = registerConcaveMeshShape(vertices,indices,col,scaling);
+ col.m_shapeIndex = registerConcaveMeshShape(vertices, indices, col, scaling);
col.m_bvhIndex = m_data->m_bvhInfoCPU.size();
-
b3SapAabb aabb;
- b3Vector3 myAabbMin=b3MakeVector3(1e30f,1e30f,1e30f);
- b3Vector3 myAabbMax=b3MakeVector3(-1e30f,-1e30f,-1e30f);
+ b3Vector3 myAabbMin = b3MakeVector3(1e30f, 1e30f, 1e30f);
+ b3Vector3 myAabbMax = b3MakeVector3(-1e30f, -1e30f, -1e30f);
- for (int i=0;i<vertices->size();i++)
+ for (int i = 0; i < vertices->size(); i++)
{
- b3Vector3 vtx(vertices->at(i)*scaling);
+ b3Vector3 vtx(vertices->at(i) * scaling);
myAabbMin.setMin(vtx);
myAabbMax.setMax(vtx);
}
@@ -603,27 +548,27 @@ int b3GpuNarrowPhase::registerConcaveMesh(b3AlignedObjectArray<b3Vector3>* vert
aabb.m_minIndices[3] = 0;
aabb.m_max[0] = myAabbMax[0];
- aabb.m_max[1]= myAabbMax[1];
- aabb.m_max[2]= myAabbMax[2];
- aabb.m_signedMaxIndices[3]= 0;
+ aabb.m_max[1] = myAabbMax[1];
+ aabb.m_max[2] = myAabbMax[2];
+ aabb.m_signedMaxIndices[3] = 0;
m_data->m_localShapeAABBCPU->push_back(aabb);
-// m_data->m_localShapeAABBGPU->push_back(aabb);
+ // m_data->m_localShapeAABBGPU->push_back(aabb);
b3OptimizedBvh* bvh = new b3OptimizedBvh();
//void b3OptimizedBvh::build(b3StridingMeshInterface* triangles, bool useQuantizedAabbCompression, const b3Vector3& bvhAabbMin, const b3Vector3& bvhAabbMax)
-
+
bool useQuantizedAabbCompression = true;
- b3TriangleIndexVertexArray* meshInterface=new b3TriangleIndexVertexArray();
+ b3TriangleIndexVertexArray* meshInterface = new b3TriangleIndexVertexArray();
m_data->m_meshInterfaces.push_back(meshInterface);
b3IndexedMesh mesh;
- mesh.m_numTriangles = indices->size()/3;
+ mesh.m_numTriangles = indices->size() / 3;
mesh.m_numVertices = vertices->size();
- mesh.m_vertexBase = (const unsigned char *)&vertices->at(0).x;
+ mesh.m_vertexBase = (const unsigned char*)&vertices->at(0).x;
mesh.m_vertexStride = sizeof(b3Vector3);
- mesh.m_triangleIndexStride = 3 * sizeof(int);// or sizeof(int)
- mesh.m_triangleIndexBase = (const unsigned char *)&indices->at(0);
-
+ mesh.m_triangleIndexStride = 3 * sizeof(int); // or sizeof(int)
+ mesh.m_triangleIndexBase = (const unsigned char*)&indices->at(0);
+
meshInterface->addIndexedMesh(mesh);
bvh->build(meshInterface, useQuantizedAabbCompression, (b3Vector3&)aabb.m_min, (b3Vector3&)aabb.m_max);
m_data->m_bvhData.push_back(bvh);
@@ -632,7 +577,7 @@ int b3GpuNarrowPhase::registerConcaveMesh(b3AlignedObjectArray<b3Vector3>* vert
int numSubTrees = bvh->getSubtreeInfoArray().size();
b3BvhInfo bvhInfo;
-
+
bvhInfo.m_aabbMin = bvh->m_bvhAabbMin;
bvhInfo.m_aabbMax = bvh->m_bvhAabbMax;
bvhInfo.m_quantization = bvh->m_bvhQuantization;
@@ -643,97 +588,87 @@ int b3GpuNarrowPhase::registerConcaveMesh(b3AlignedObjectArray<b3Vector3>* vert
m_data->m_bvhInfoCPU.push_back(bvhInfo);
-
int numNewSubtrees = bvh->getSubtreeInfoArray().size();
- m_data->m_subTreesCPU.reserve(m_data->m_subTreesCPU.size()+numNewSubtrees);
- for (int i=0;i<numNewSubtrees;i++)
+ m_data->m_subTreesCPU.reserve(m_data->m_subTreesCPU.size() + numNewSubtrees);
+ for (int i = 0; i < numNewSubtrees; i++)
{
m_data->m_subTreesCPU.push_back(bvh->getSubtreeInfoArray()[i]);
}
int numNewTreeNodes = bvh->getQuantizedNodeArray().size();
- for (int i=0;i<numNewTreeNodes;i++)
+ for (int i = 0; i < numNewTreeNodes; i++)
{
m_data->m_treeNodesCPU.push_back(bvh->getQuantizedNodeArray()[i]);
}
-
-
-
return collidableIndex;
}
-int b3GpuNarrowPhase::registerConcaveMeshShape(b3AlignedObjectArray<b3Vector3>* vertices, b3AlignedObjectArray<int>* indices,b3Collidable& col, const float* scaling1)
+int b3GpuNarrowPhase::registerConcaveMeshShape(b3AlignedObjectArray<b3Vector3>* vertices, b3AlignedObjectArray<int>* indices, b3Collidable& col, const float* scaling1)
{
+ b3Vector3 scaling = b3MakeVector3(scaling1[0], scaling1[1], scaling1[2]);
+ m_data->m_convexData->resize(m_data->m_numAcceleratedShapes + 1);
+ m_data->m_convexPolyhedra.resize(m_data->m_numAcceleratedShapes + 1);
- b3Vector3 scaling=b3MakeVector3(scaling1[0],scaling1[1],scaling1[2]);
-
- m_data->m_convexData->resize(m_data->m_numAcceleratedShapes+1);
- m_data->m_convexPolyhedra.resize(m_data->m_numAcceleratedShapes+1);
-
-
- b3ConvexPolyhedronData& convex = m_data->m_convexPolyhedra.at(m_data->m_convexPolyhedra.size()-1);
- convex.mC = b3MakeVector3(0,0,0);
- convex.mE = b3MakeVector3(0,0,0);
- convex.m_extents= b3MakeVector3(0,0,0);
- convex.m_localCenter = b3MakeVector3(0,0,0);
+ b3ConvexPolyhedronData& convex = m_data->m_convexPolyhedra.at(m_data->m_convexPolyhedra.size() - 1);
+ convex.mC = b3MakeVector3(0, 0, 0);
+ convex.mE = b3MakeVector3(0, 0, 0);
+ convex.m_extents = b3MakeVector3(0, 0, 0);
+ convex.m_localCenter = b3MakeVector3(0, 0, 0);
convex.m_radius = 0.f;
-
+
convex.m_numUniqueEdges = 0;
int edgeOffset = m_data->m_uniqueEdges.size();
convex.m_uniqueEdgesOffset = edgeOffset;
-
+
int faceOffset = m_data->m_convexFaces.size();
convex.m_faceOffset = faceOffset;
-
- convex.m_numFaces = indices->size()/3;
- m_data->m_convexFaces.resize(faceOffset+convex.m_numFaces);
- m_data->m_convexIndices.reserve(convex.m_numFaces*3);
- for (int i=0;i<convex.m_numFaces;i++)
+
+ convex.m_numFaces = indices->size() / 3;
+ m_data->m_convexFaces.resize(faceOffset + convex.m_numFaces);
+ m_data->m_convexIndices.reserve(convex.m_numFaces * 3);
+ for (int i = 0; i < convex.m_numFaces; i++)
{
- if (i%256==0)
+ if (i % 256 == 0)
{
//printf("i=%d out of %d", i,convex.m_numFaces);
}
- b3Vector3 vert0(vertices->at(indices->at(i*3))*scaling);
- b3Vector3 vert1(vertices->at(indices->at(i*3+1))*scaling);
- b3Vector3 vert2(vertices->at(indices->at(i*3+2))*scaling);
+ b3Vector3 vert0(vertices->at(indices->at(i * 3)) * scaling);
+ b3Vector3 vert1(vertices->at(indices->at(i * 3 + 1)) * scaling);
+ b3Vector3 vert2(vertices->at(indices->at(i * 3 + 2)) * scaling);
- b3Vector3 normal = ((vert1-vert0).cross(vert2-vert0)).normalize();
+ b3Vector3 normal = ((vert1 - vert0).cross(vert2 - vert0)).normalize();
b3Scalar c = -(normal.dot(vert0));
- m_data->m_convexFaces[convex.m_faceOffset+i].m_plane = b3MakeVector4(normal.x,normal.y,normal.z,c);
+ m_data->m_convexFaces[convex.m_faceOffset + i].m_plane = b3MakeVector4(normal.x, normal.y, normal.z, c);
int indexOffset = m_data->m_convexIndices.size();
int numIndices = 3;
- m_data->m_convexFaces[convex.m_faceOffset+i].m_numIndices = numIndices;
- m_data->m_convexFaces[convex.m_faceOffset+i].m_indexOffset = indexOffset;
- m_data->m_convexIndices.resize(indexOffset+numIndices);
- for (int p=0;p<numIndices;p++)
+ m_data->m_convexFaces[convex.m_faceOffset + i].m_numIndices = numIndices;
+ m_data->m_convexFaces[convex.m_faceOffset + i].m_indexOffset = indexOffset;
+ m_data->m_convexIndices.resize(indexOffset + numIndices);
+ for (int p = 0; p < numIndices; p++)
{
- int vi = indices->at(i*3+p);
- m_data->m_convexIndices[indexOffset+p] = vi;//convexPtr->m_faces[i].m_indices[p];
+ int vi = indices->at(i * 3 + p);
+ m_data->m_convexIndices[indexOffset + p] = vi; //convexPtr->m_faces[i].m_indices[p];
}
}
-
+
convex.m_numVertices = vertices->size();
int vertexOffset = m_data->m_convexVertices.size();
- convex.m_vertexOffset =vertexOffset;
- m_data->m_convexVertices.resize(vertexOffset+convex.m_numVertices);
- for (int i=0;i<vertices->size();i++)
+ convex.m_vertexOffset = vertexOffset;
+ m_data->m_convexVertices.resize(vertexOffset + convex.m_numVertices);
+ for (int i = 0; i < vertices->size(); i++)
{
- m_data->m_convexVertices[vertexOffset+i] = vertices->at(i)*scaling;
+ m_data->m_convexVertices[vertexOffset + i] = vertices->at(i) * scaling;
}
(*m_data->m_convexData)[m_data->m_numAcceleratedShapes] = 0;
-
-
+
return m_data->m_numAcceleratedShapes++;
}
-
-
-cl_mem b3GpuNarrowPhase::getBodiesGpu()
+cl_mem b3GpuNarrowPhase::getBodiesGpu()
{
return (cl_mem)m_data->m_bodyBufferGPU->getBufferCL();
}
@@ -743,25 +678,21 @@ const struct b3RigidBodyData* b3GpuNarrowPhase::getBodiesCpu() const
return &m_data->m_bodyBufferCPU->at(0);
};
-
-
-
-int b3GpuNarrowPhase::getNumBodiesGpu() const
+int b3GpuNarrowPhase::getNumBodiesGpu() const
{
return m_data->m_bodyBufferGPU->size();
}
-cl_mem b3GpuNarrowPhase::getBodyInertiasGpu()
+cl_mem b3GpuNarrowPhase::getBodyInertiasGpu()
{
return (cl_mem)m_data->m_inertiaBufferGPU->getBufferCL();
}
-int b3GpuNarrowPhase::getNumBodyInertiasGpu() const
+int b3GpuNarrowPhase::getNumBodyInertiasGpu() const
{
return m_data->m_inertiaBufferGPU->size();
}
-
b3Collidable& b3GpuNarrowPhase::getCollidableCpu(int collidableIndex)
{
return m_data->m_collidablesCPU[collidableIndex];
@@ -789,25 +720,20 @@ const struct b3SapAabb* b3GpuNarrowPhase::getLocalSpaceAabbsCpu() const
if (m_data->m_localShapeAABBCPU->size())
{
return &m_data->m_localShapeAABBCPU->at(0);
- }
+ }
return 0;
}
-
-cl_mem b3GpuNarrowPhase::getAabbLocalSpaceBufferGpu()
+cl_mem b3GpuNarrowPhase::getAabbLocalSpaceBufferGpu()
{
return m_data->m_localShapeAABBGPU->getBufferCL();
}
-int b3GpuNarrowPhase::getNumCollidablesGpu() const
+int b3GpuNarrowPhase::getNumCollidablesGpu() const
{
return m_data->m_collidablesGPU->size();
}
-
-
-
-
-int b3GpuNarrowPhase::getNumContactsGpu() const
+int b3GpuNarrowPhase::getNumContactsGpu() const
{
return m_data->m_pBufContactBuffersGPU[m_data->m_currentContactBuffer]->size();
}
@@ -824,37 +750,33 @@ const b3Contact4* b3GpuNarrowPhase::getContactsCPU() const
void b3GpuNarrowPhase::computeContacts(cl_mem broadphasePairs, int numBroadphasePairs, cl_mem aabbsWorldSpace, int numObjects)
{
-
cl_mem aabbsLocalSpace = m_data->m_localShapeAABBGPU->getBufferCL();
int nContactOut = 0;
//swap buffer
- m_data->m_currentContactBuffer=1-m_data->m_currentContactBuffer;
+ m_data->m_currentContactBuffer = 1 - m_data->m_currentContactBuffer;
//int curSize = m_data->m_pBufContactBuffersGPU[m_data->m_currentContactBuffer]->size();
int maxTriConvexPairCapacity = m_data->m_config.m_maxTriConvexPairCapacity;
- int numTriConvexPairsOut=0;
-
- b3OpenCLArray<b3Int4> broadphasePairsGPU(m_context,m_queue);
- broadphasePairsGPU.setFromOpenCLBuffer(broadphasePairs,numBroadphasePairs);
-
-
+ int numTriConvexPairsOut = 0;
+ b3OpenCLArray<b3Int4> broadphasePairsGPU(m_context, m_queue);
+ broadphasePairsGPU.setFromOpenCLBuffer(broadphasePairs, numBroadphasePairs);
- b3OpenCLArray<b3Aabb> clAabbArrayWorldSpace(this->m_context,this->m_queue);
- clAabbArrayWorldSpace.setFromOpenCLBuffer(aabbsWorldSpace,numObjects);
+ b3OpenCLArray<b3Aabb> clAabbArrayWorldSpace(this->m_context, this->m_queue);
+ clAabbArrayWorldSpace.setFromOpenCLBuffer(aabbsWorldSpace, numObjects);
- b3OpenCLArray<b3Aabb> clAabbArrayLocalSpace(this->m_context,this->m_queue);
- clAabbArrayLocalSpace.setFromOpenCLBuffer(aabbsLocalSpace,numObjects);
+ b3OpenCLArray<b3Aabb> clAabbArrayLocalSpace(this->m_context, this->m_queue);
+ clAabbArrayLocalSpace.setFromOpenCLBuffer(aabbsLocalSpace, numObjects);
m_data->m_gpuSatCollision->computeConvexConvexContactsGPUSAT(
&broadphasePairsGPU, numBroadphasePairs,
m_data->m_bodyBufferGPU,
m_data->m_pBufContactBuffersGPU[m_data->m_currentContactBuffer],
nContactOut,
- m_data->m_pBufContactBuffersGPU[1-m_data->m_currentContactBuffer],
+ m_data->m_pBufContactBuffersGPU[1 - m_data->m_currentContactBuffer],
m_data->m_config.m_maxContactCapacity,
m_data->m_config.m_compoundPairCapacity,
*m_data->m_convexPolyhedraGPU,
@@ -878,8 +800,7 @@ void b3GpuNarrowPhase::computeContacts(cl_mem broadphasePairs, int numBroadphase
numObjects,
maxTriConvexPairCapacity,
*m_data->m_triangleConvexPairs,
- numTriConvexPairsOut
- );
+ numTriConvexPairsOut);
/*b3AlignedObjectArray<b3Int4> broadphasePairsCPU;
broadphasePairsGPU.copyToHost(broadphasePairsCPU);
@@ -892,105 +813,97 @@ const b3SapAabb& b3GpuNarrowPhase::getLocalSpaceAabb(int collidableIndex) const
return m_data->m_localShapeAABBCPU->at(collidableIndex);
}
-
-
-
-
-int b3GpuNarrowPhase::registerRigidBody(int collidableIndex, float mass, const float* position, const float* orientation , const float* aabbMinPtr, const float* aabbMaxPtr,bool writeToGpu)
+int b3GpuNarrowPhase::registerRigidBody(int collidableIndex, float mass, const float* position, const float* orientation, const float* aabbMinPtr, const float* aabbMaxPtr, bool writeToGpu)
{
- b3Vector3 aabbMin=b3MakeVector3(aabbMinPtr[0],aabbMinPtr[1],aabbMinPtr[2]);
- b3Vector3 aabbMax=b3MakeVector3(aabbMaxPtr[0],aabbMaxPtr[1],aabbMaxPtr[2]);
-
+ b3Vector3 aabbMin = b3MakeVector3(aabbMinPtr[0], aabbMinPtr[1], aabbMinPtr[2]);
+ b3Vector3 aabbMax = b3MakeVector3(aabbMaxPtr[0], aabbMaxPtr[1], aabbMaxPtr[2]);
if (m_data->m_numAcceleratedRigidBodies >= (m_data->m_config.m_maxConvexBodies))
{
- b3Error("registerRigidBody: exceeding the number of rigid bodies, %d > %d \n",m_data->m_numAcceleratedRigidBodies,m_data->m_config.m_maxConvexBodies);
+ b3Error("registerRigidBody: exceeding the number of rigid bodies, %d > %d \n", m_data->m_numAcceleratedRigidBodies, m_data->m_config.m_maxConvexBodies);
return -1;
}
-
- m_data->m_bodyBufferCPU->resize(m_data->m_numAcceleratedRigidBodies+1);
-
+
+ m_data->m_bodyBufferCPU->resize(m_data->m_numAcceleratedRigidBodies + 1);
+
b3RigidBodyData& body = m_data->m_bodyBufferCPU->at(m_data->m_numAcceleratedRigidBodies);
-
+
float friction = 1.f;
float restitution = 0.f;
-
+
body.m_frictionCoeff = friction;
body.m_restituitionCoeff = restitution;
- body.m_angVel = b3MakeVector3(0,0,0);
- body.m_linVel=b3MakeVector3(0,0,0);//.setZero();
- body.m_pos =b3MakeVector3(position[0],position[1],position[2]);
- body.m_quat.setValue(orientation[0],orientation[1],orientation[2],orientation[3]);
+ body.m_angVel = b3MakeVector3(0, 0, 0);
+ body.m_linVel = b3MakeVector3(0, 0, 0); //.setZero();
+ body.m_pos = b3MakeVector3(position[0], position[1], position[2]);
+ body.m_quat.setValue(orientation[0], orientation[1], orientation[2], orientation[3]);
body.m_collidableIdx = collidableIndex;
- if (collidableIndex>=0)
+ if (collidableIndex >= 0)
{
-// body.m_shapeType = m_data->m_collidablesCPU.at(collidableIndex).m_shapeType;
- } else
+ // body.m_shapeType = m_data->m_collidablesCPU.at(collidableIndex).m_shapeType;
+ }
+ else
{
- // body.m_shapeType = CollisionShape::SHAPE_PLANE;
+ // body.m_shapeType = CollisionShape::SHAPE_PLANE;
m_planeBodyIndex = m_data->m_numAcceleratedRigidBodies;
}
//body.m_shapeType = shapeType;
-
-
- body.m_invMass = mass? 1.f/mass : 0.f;
-
+
+ body.m_invMass = mass ? 1.f / mass : 0.f;
+
if (writeToGpu)
{
- m_data->m_bodyBufferGPU->copyFromHostPointer(&body,1,m_data->m_numAcceleratedRigidBodies);
+ m_data->m_bodyBufferGPU->copyFromHostPointer(&body, 1, m_data->m_numAcceleratedRigidBodies);
}
-
+
b3InertiaData& shapeInfo = m_data->m_inertiaBufferCPU->at(m_data->m_numAcceleratedRigidBodies);
-
- if (mass==0.f)
+
+ if (mass == 0.f)
{
- if (m_data->m_numAcceleratedRigidBodies==0)
+ if (m_data->m_numAcceleratedRigidBodies == 0)
m_static0Index = 0;
-
- shapeInfo.m_initInvInertia.setValue(0,0,0,0,0,0,0,0,0);
- shapeInfo.m_invInertiaWorld.setValue(0,0,0,0,0,0,0,0,0);
- } else
+
+ shapeInfo.m_initInvInertia.setValue(0, 0, 0, 0, 0, 0, 0, 0, 0);
+ shapeInfo.m_invInertiaWorld.setValue(0, 0, 0, 0, 0, 0, 0, 0, 0);
+ }
+ else
{
-
- b3Assert(body.m_collidableIdx>=0);
-
+ b3Assert(body.m_collidableIdx >= 0);
+
//approximate using the aabb of the shape
-
+
//Aabb aabb = (*m_data->m_shapePointers)[shapeIndex]->m_aabb;
- b3Vector3 halfExtents = (aabbMax-aabbMin);//*0.5f;//fake larger inertia makes demos more stable ;-)
-
+ b3Vector3 halfExtents = (aabbMax - aabbMin); //*0.5f;//fake larger inertia makes demos more stable ;-)
+
b3Vector3 localInertia;
-
- float lx=2.f*halfExtents[0];
- float ly=2.f*halfExtents[1];
- float lz=2.f*halfExtents[2];
-
- localInertia.setValue( (mass/12.0f) * (ly*ly + lz*lz),
- (mass/12.0f) * (lx*lx + lz*lz),
- (mass/12.0f) * (lx*lx + ly*ly));
-
+
+ float lx = 2.f * halfExtents[0];
+ float ly = 2.f * halfExtents[1];
+ float lz = 2.f * halfExtents[2];
+
+ localInertia.setValue((mass / 12.0f) * (ly * ly + lz * lz),
+ (mass / 12.0f) * (lx * lx + lz * lz),
+ (mass / 12.0f) * (lx * lx + ly * ly));
+
b3Vector3 invLocalInertia;
- invLocalInertia[0] = 1.f/localInertia[0];
- invLocalInertia[1] = 1.f/localInertia[1];
- invLocalInertia[2] = 1.f/localInertia[2];
+ invLocalInertia[0] = 1.f / localInertia[0];
+ invLocalInertia[1] = 1.f / localInertia[1];
+ invLocalInertia[2] = 1.f / localInertia[2];
invLocalInertia[3] = 0.f;
-
+
shapeInfo.m_initInvInertia.setValue(
- invLocalInertia[0], 0, 0,
- 0, invLocalInertia[1], 0,
- 0, 0, invLocalInertia[2]);
+ invLocalInertia[0], 0, 0,
+ 0, invLocalInertia[1], 0,
+ 0, 0, invLocalInertia[2]);
- b3Matrix3x3 m (body.m_quat);
+ b3Matrix3x3 m(body.m_quat);
shapeInfo.m_invInertiaWorld = m.scaled(invLocalInertia) * m.transpose();
-
}
-
+
if (writeToGpu)
- m_data->m_inertiaBufferGPU->copyFromHostPointer(&shapeInfo,1,m_data->m_numAcceleratedRigidBodies);
-
-
-
+ m_data->m_inertiaBufferGPU->copyFromHostPointer(&shapeInfo, 1, m_data->m_numAcceleratedRigidBodies);
+
return m_data->m_numAcceleratedRigidBodies++;
}
@@ -999,15 +912,13 @@ int b3GpuNarrowPhase::getNumRigidBodies() const
return m_data->m_numAcceleratedRigidBodies;
}
-void b3GpuNarrowPhase::writeAllBodiesToGpu()
+void b3GpuNarrowPhase::writeAllBodiesToGpu()
{
-
if (m_data->m_localShapeAABBCPU->size())
{
m_data->m_localShapeAABBGPU->copyFromHost(*m_data->m_localShapeAABBCPU);
}
-
-
+
m_data->m_gpuChildShapes->copyFromHost(m_data->m_cpuChildShapes);
m_data->m_convexFacesGPU->copyFromHost(m_data->m_convexFaces);
m_data->m_convexPolyhedraGPU->copyFromHost(m_data->m_convexPolyhedra);
@@ -1018,25 +929,21 @@ void b3GpuNarrowPhase::writeAllBodiesToGpu()
m_data->m_treeNodesGPU->copyFromHost(m_data->m_treeNodesCPU);
m_data->m_subTreesGPU->copyFromHost(m_data->m_subTreesCPU);
-
m_data->m_bodyBufferGPU->resize(m_data->m_numAcceleratedRigidBodies);
m_data->m_inertiaBufferGPU->resize(m_data->m_numAcceleratedRigidBodies);
-
+
if (m_data->m_numAcceleratedRigidBodies)
{
- m_data->m_bodyBufferGPU->copyFromHostPointer(&m_data->m_bodyBufferCPU->at(0),m_data->m_numAcceleratedRigidBodies);
- m_data->m_inertiaBufferGPU->copyFromHostPointer(&m_data->m_inertiaBufferCPU->at(0),m_data->m_numAcceleratedRigidBodies);
+ m_data->m_bodyBufferGPU->copyFromHostPointer(&m_data->m_bodyBufferCPU->at(0), m_data->m_numAcceleratedRigidBodies);
+ m_data->m_inertiaBufferGPU->copyFromHostPointer(&m_data->m_inertiaBufferCPU->at(0), m_data->m_numAcceleratedRigidBodies);
}
- if (m_data->m_collidablesCPU.size())
+ if (m_data->m_collidablesCPU.size())
{
m_data->m_collidablesGPU->copyFromHost(m_data->m_collidablesCPU);
}
-
-
}
-
-void b3GpuNarrowPhase::reset()
+void b3GpuNarrowPhase::reset()
{
m_data->m_numAcceleratedShapes = 0;
m_data->m_numAcceleratedRigidBodies = 0;
@@ -1053,21 +960,19 @@ void b3GpuNarrowPhase::reset()
m_data->m_treeNodesCPU.resize(0);
m_data->m_subTreesCPU.resize(0);
m_data->m_bvhInfoCPU.resize(0);
-
}
-
-void b3GpuNarrowPhase::readbackAllBodiesToCpu()
+void b3GpuNarrowPhase::readbackAllBodiesToCpu()
{
- m_data->m_bodyBufferGPU->copyToHostPointer(&m_data->m_bodyBufferCPU->at(0),m_data->m_numAcceleratedRigidBodies);
+ m_data->m_bodyBufferGPU->copyToHostPointer(&m_data->m_bodyBufferCPU->at(0), m_data->m_numAcceleratedRigidBodies);
}
-void b3GpuNarrowPhase::setObjectTransformCpu(float* position, float* orientation , int bodyIndex)
+void b3GpuNarrowPhase::setObjectTransformCpu(float* position, float* orientation, int bodyIndex)
{
- if (bodyIndex>=0 && bodyIndex<m_data->m_bodyBufferCPU->size())
+ if (bodyIndex >= 0 && bodyIndex < m_data->m_bodyBufferCPU->size())
{
- m_data->m_bodyBufferCPU->at(bodyIndex).m_pos=b3MakeVector3(position[0],position[1],position[2]);
- m_data->m_bodyBufferCPU->at(bodyIndex).m_quat.setValue(orientation[0],orientation[1],orientation[2],orientation[3]);
+ m_data->m_bodyBufferCPU->at(bodyIndex).m_pos = b3MakeVector3(position[0], position[1], position[2]);
+ m_data->m_bodyBufferCPU->at(bodyIndex).m_quat.setValue(orientation[0], orientation[1], orientation[2], orientation[3]);
}
else
{
@@ -1076,24 +981,25 @@ void b3GpuNarrowPhase::setObjectTransformCpu(float* position, float* orientation
}
void b3GpuNarrowPhase::setObjectVelocityCpu(float* linVel, float* angVel, int bodyIndex)
{
- if (bodyIndex>=0 && bodyIndex<m_data->m_bodyBufferCPU->size())
+ if (bodyIndex >= 0 && bodyIndex < m_data->m_bodyBufferCPU->size())
{
- m_data->m_bodyBufferCPU->at(bodyIndex).m_linVel=b3MakeVector3(linVel[0],linVel[1],linVel[2]);
- m_data->m_bodyBufferCPU->at(bodyIndex).m_angVel=b3MakeVector3(angVel[0],angVel[1],angVel[2]);
- } else
+ m_data->m_bodyBufferCPU->at(bodyIndex).m_linVel = b3MakeVector3(linVel[0], linVel[1], linVel[2]);
+ m_data->m_bodyBufferCPU->at(bodyIndex).m_angVel = b3MakeVector3(angVel[0], angVel[1], angVel[2]);
+ }
+ else
{
b3Warning("setObjectVelocityCpu out of range.\n");
}
}
-bool b3GpuNarrowPhase::getObjectTransformFromCpu(float* position, float* orientation , int bodyIndex) const
+bool b3GpuNarrowPhase::getObjectTransformFromCpu(float* position, float* orientation, int bodyIndex) const
{
- if (bodyIndex>=0 && bodyIndex<m_data->m_bodyBufferCPU->size())
+ if (bodyIndex >= 0 && bodyIndex < m_data->m_bodyBufferCPU->size())
{
position[0] = m_data->m_bodyBufferCPU->at(bodyIndex).m_pos.x;
position[1] = m_data->m_bodyBufferCPU->at(bodyIndex).m_pos.y;
position[2] = m_data->m_bodyBufferCPU->at(bodyIndex).m_pos.z;
- position[3] = 1.f;//or 1
+ position[3] = 1.f; //or 1
orientation[0] = m_data->m_bodyBufferCPU->at(bodyIndex).m_quat.x;
orientation[1] = m_data->m_bodyBufferCPU->at(bodyIndex).m_quat.y;
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuNarrowPhase.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuNarrowPhase.h
index 05ff3fd09e..21a68de343 100644
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuNarrowPhase.h
+++ b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuNarrowPhase.h
@@ -9,11 +9,10 @@
class b3GpuNarrowPhase
{
protected:
-
- struct b3GpuNarrowPhaseInternalData* m_data;
+ struct b3GpuNarrowPhaseInternalData* m_data;
int m_acceleratedCompanionShapeIndex;
int m_planeBodyIndex;
- int m_static0Index;
+ int m_static0Index;
cl_context m_context;
cl_device_id m_device;
@@ -23,64 +22,58 @@ protected:
int registerConcaveMeshShape(b3AlignedObjectArray<b3Vector3>* vertices, b3AlignedObjectArray<int>* indices, b3Collidable& col, const float* scaling);
public:
-
-
-
-
b3GpuNarrowPhase(cl_context vtx, cl_device_id dev, cl_command_queue q, const struct b3Config& config);
virtual ~b3GpuNarrowPhase(void);
- int registerSphereShape(float radius);
- int registerPlaneShape(const b3Vector3& planeNormal, float planeConstant);
+ int registerSphereShape(float radius);
+ int registerPlaneShape(const b3Vector3& planeNormal, float planeConstant);
int registerCompoundShape(b3AlignedObjectArray<b3GpuChildShape>* childShapes);
int registerFace(const b3Vector3& faceNormal, float faceConstant);
-
- int registerConcaveMesh(b3AlignedObjectArray<b3Vector3>* vertices, b3AlignedObjectArray<int>* indices,const float* scaling);
-
+
+ int registerConcaveMesh(b3AlignedObjectArray<b3Vector3>* vertices, b3AlignedObjectArray<int>* indices, const float* scaling);
+
//do they need to be merged?
-
- int registerConvexHullShape(b3ConvexUtility* utilPtr);
- int registerConvexHullShape(const float* vertices, int strideInBytes, int numVertices, const float* scaling);
- int registerRigidBody(int collidableIndex, float mass, const float* position, const float* orientation, const float* aabbMin, const float* aabbMax,bool writeToGpu);
- void setObjectTransform(const float* position, const float* orientation , int bodyIndex);
+ int registerConvexHullShape(b3ConvexUtility* utilPtr);
+ int registerConvexHullShape(const float* vertices, int strideInBytes, int numVertices, const float* scaling);
+
+ int registerRigidBody(int collidableIndex, float mass, const float* position, const float* orientation, const float* aabbMin, const float* aabbMax, bool writeToGpu);
+ void setObjectTransform(const float* position, const float* orientation, int bodyIndex);
- void writeAllBodiesToGpu();
- void reset();
- void readbackAllBodiesToCpu();
- bool getObjectTransformFromCpu(float* position, float* orientation , int bodyIndex) const;
+ void writeAllBodiesToGpu();
+ void reset();
+ void readbackAllBodiesToCpu();
+ bool getObjectTransformFromCpu(float* position, float* orientation, int bodyIndex) const;
- void setObjectTransformCpu(float* position, float* orientation , int bodyIndex);
+ void setObjectTransformCpu(float* position, float* orientation, int bodyIndex);
void setObjectVelocityCpu(float* linVel, float* angVel, int bodyIndex);
-
virtual void computeContacts(cl_mem broadphasePairs, int numBroadphasePairs, cl_mem aabbsWorldSpace, int numObjects);
-
- cl_mem getBodiesGpu();
+ cl_mem getBodiesGpu();
const struct b3RigidBodyData* getBodiesCpu() const;
//struct b3RigidBodyData* getBodiesCpu();
- int getNumBodiesGpu() const;
+ int getNumBodiesGpu() const;
- cl_mem getBodyInertiasGpu();
- int getNumBodyInertiasGpu() const;
+ cl_mem getBodyInertiasGpu();
+ int getNumBodyInertiasGpu() const;
- cl_mem getCollidablesGpu();
+ cl_mem getCollidablesGpu();
const struct b3Collidable* getCollidablesCpu() const;
- int getNumCollidablesGpu() const;
+ int getNumCollidablesGpu() const;
const struct b3SapAabb* getLocalSpaceAabbsCpu() const;
const struct b3Contact4* getContactsCPU() const;
- cl_mem getContactsGpu();
- int getNumContactsGpu() const;
+ cl_mem getContactsGpu();
+ int getNumContactsGpu() const;
+
+ cl_mem getAabbLocalSpaceBufferGpu();
- cl_mem getAabbLocalSpaceBufferGpu();
-
int getNumRigidBodies() const;
int allocateCollidable();
@@ -92,18 +85,17 @@ public:
b3Collidable& getCollidableCpu(int collidableIndex);
const b3Collidable& getCollidableCpu(int collidableIndex) const;
- const b3GpuNarrowPhaseInternalData* getInternalData() const
+ const b3GpuNarrowPhaseInternalData* getInternalData() const
{
- return m_data;
+ return m_data;
}
- b3GpuNarrowPhaseInternalData* getInternalData()
+ b3GpuNarrowPhaseInternalData* getInternalData()
{
- return m_data;
+ return m_data;
}
const struct b3SapAabb& getLocalSpaceAabb(int collidableIndex) const;
};
-#endif //B3_GPU_NARROWPHASE_H
-
+#endif //B3_GPU_NARROWPHASE_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuNarrowPhaseInternalData.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuNarrowPhaseInternalData.h
index 8a7f1ea859..716a5ea0fc 100644
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuNarrowPhaseInternalData.h
+++ b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuNarrowPhaseInternalData.h
@@ -20,57 +20,53 @@
#include "Bullet3Common/shared/b3Int4.h"
#include "Bullet3Common/shared/b3Int2.h"
-
class b3ConvexUtility;
struct b3GpuNarrowPhaseInternalData
{
b3AlignedObjectArray<b3ConvexUtility*>* m_convexData;
-
+
b3AlignedObjectArray<b3ConvexPolyhedronData> m_convexPolyhedra;
b3AlignedObjectArray<b3Vector3> m_uniqueEdges;
b3AlignedObjectArray<b3Vector3> m_convexVertices;
b3AlignedObjectArray<int> m_convexIndices;
-
+
b3OpenCLArray<b3ConvexPolyhedronData>* m_convexPolyhedraGPU;
b3OpenCLArray<b3Vector3>* m_uniqueEdgesGPU;
b3OpenCLArray<b3Vector3>* m_convexVerticesGPU;
b3OpenCLArray<int>* m_convexIndicesGPU;
-
- b3OpenCLArray<b3Vector3>* m_worldVertsB1GPU;
- b3OpenCLArray<b3Int4>* m_clippingFacesOutGPU;
- b3OpenCLArray<b3Vector3>* m_worldNormalsAGPU;
- b3OpenCLArray<b3Vector3>* m_worldVertsA1GPU;
- b3OpenCLArray<b3Vector3>* m_worldVertsB2GPU;
-
+
+ b3OpenCLArray<b3Vector3>* m_worldVertsB1GPU;
+ b3OpenCLArray<b3Int4>* m_clippingFacesOutGPU;
+ b3OpenCLArray<b3Vector3>* m_worldNormalsAGPU;
+ b3OpenCLArray<b3Vector3>* m_worldVertsA1GPU;
+ b3OpenCLArray<b3Vector3>* m_worldVertsB2GPU;
+
b3AlignedObjectArray<b3GpuChildShape> m_cpuChildShapes;
- b3OpenCLArray<b3GpuChildShape>* m_gpuChildShapes;
-
+ b3OpenCLArray<b3GpuChildShape>* m_gpuChildShapes;
+
b3AlignedObjectArray<b3GpuFace> m_convexFaces;
b3OpenCLArray<b3GpuFace>* m_convexFacesGPU;
-
- struct GpuSatCollision* m_gpuSatCollision;
-
-
- b3OpenCLArray<b3Int4>* m_triangleConvexPairs;
-
-
+
+ struct GpuSatCollision* m_gpuSatCollision;
+
+ b3OpenCLArray<b3Int4>* m_triangleConvexPairs;
+
b3OpenCLArray<b3Contact4>* m_pBufContactBuffersGPU[2];
- int m_currentContactBuffer;
+ int m_currentContactBuffer;
b3AlignedObjectArray<b3Contact4>* m_pBufContactOutCPU;
-
-
+
b3AlignedObjectArray<b3RigidBodyData>* m_bodyBufferCPU;
b3OpenCLArray<b3RigidBodyData>* m_bodyBufferGPU;
-
- b3AlignedObjectArray<b3InertiaData>* m_inertiaBufferCPU;
- b3OpenCLArray<b3InertiaData>* m_inertiaBufferGPU;
-
+
+ b3AlignedObjectArray<b3InertiaData>* m_inertiaBufferCPU;
+ b3OpenCLArray<b3InertiaData>* m_inertiaBufferGPU;
+
int m_numAcceleratedShapes;
int m_numAcceleratedRigidBodies;
-
- b3AlignedObjectArray<b3Collidable> m_collidablesCPU;
- b3OpenCLArray<b3Collidable>* m_collidablesGPU;
+
+ b3AlignedObjectArray<b3Collidable> m_collidablesCPU;
+ b3OpenCLArray<b3Collidable>* m_collidablesGPU;
b3OpenCLArray<b3SapAabb>* m_localShapeAABBGPU;
b3AlignedObjectArray<b3SapAabb>* m_localShapeAABBCPU;
@@ -78,18 +74,16 @@ struct b3GpuNarrowPhaseInternalData
b3AlignedObjectArray<class b3OptimizedBvh*> m_bvhData;
b3AlignedObjectArray<class b3TriangleIndexVertexArray*> m_meshInterfaces;
- b3AlignedObjectArray<b3QuantizedBvhNode> m_treeNodesCPU;
- b3AlignedObjectArray<b3BvhSubtreeInfo> m_subTreesCPU;
+ b3AlignedObjectArray<b3QuantizedBvhNode> m_treeNodesCPU;
+ b3AlignedObjectArray<b3BvhSubtreeInfo> m_subTreesCPU;
+
+ b3AlignedObjectArray<b3BvhInfo> m_bvhInfoCPU;
+ b3OpenCLArray<b3BvhInfo>* m_bvhInfoGPU;
- b3AlignedObjectArray<b3BvhInfo> m_bvhInfoCPU;
- b3OpenCLArray<b3BvhInfo>* m_bvhInfoGPU;
-
- b3OpenCLArray<b3QuantizedBvhNode>* m_treeNodesGPU;
- b3OpenCLArray<b3BvhSubtreeInfo>* m_subTreesGPU;
-
+ b3OpenCLArray<b3QuantizedBvhNode>* m_treeNodesGPU;
+ b3OpenCLArray<b3BvhSubtreeInfo>* m_subTreesGPU;
- b3Config m_config;
-
+ b3Config m_config;
};
-#endif //B3_GPU_NARROWPHASE_INTERNAL_DATA_H
+#endif //B3_GPU_NARROWPHASE_INTERNAL_DATA_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuPgsConstraintSolver.cpp b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuPgsConstraintSolver.cpp
index 0d3d50c548..bd9d6bb04b 100644
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuPgsConstraintSolver.cpp
+++ b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuPgsConstraintSolver.cpp
@@ -14,11 +14,10 @@ subject to the following restrictions:
*/
//Originally written by Erwin Coumans
-
bool useGpuInitSolverBodies = true;
bool useGpuInfo1 = true;
-bool useGpuInfo2= true;
-bool useGpuSolveJointConstraintRows=true;
+bool useGpuInfo2 = true;
+bool useGpuSolveJointConstraintRows = true;
bool useGpuWriteBackVelocities = true;
bool gpuBreakConstraints = true;
@@ -29,27 +28,25 @@ bool gpuBreakConstraints = true;
#include "Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.h"
#include <new>
#include "Bullet3Common/b3AlignedObjectArray.h"
-#include <string.h> //for memset
+#include <string.h> //for memset
#include "Bullet3Collision/NarrowPhaseCollision/b3Contact4.h"
#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
#include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
#include "Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.h"
-#include "Bullet3OpenCL/RigidBody/kernels/jointSolver.h" //solveConstraintRowsCL
+#include "Bullet3OpenCL/RigidBody/kernels/jointSolver.h" //solveConstraintRowsCL
#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
#define B3_JOINT_SOLVER_PATH "src/Bullet3OpenCL/RigidBody/kernels/jointSolver.cl"
-
struct b3GpuPgsJacobiSolverInternalData
{
-
cl_context m_context;
cl_device_id m_device;
cl_command_queue m_queue;
- b3PrefixScanCL* m_prefixScan;
+ b3PrefixScanCL* m_prefixScan;
cl_kernel m_solveJointConstraintRowsKernels;
cl_kernel m_initSolverBodiesKernel;
@@ -59,31 +56,27 @@ struct b3GpuPgsJacobiSolverInternalData
cl_kernel m_writeBackVelocitiesKernel;
cl_kernel m_breakViolatedConstraintsKernel;
- b3OpenCLArray<unsigned int>* m_gpuConstraintRowOffsets;
+ b3OpenCLArray<unsigned int>* m_gpuConstraintRowOffsets;
- b3OpenCLArray<b3GpuSolverBody>* m_gpuSolverBodies;
- b3OpenCLArray<b3BatchConstraint>* m_gpuBatchConstraints;
- b3OpenCLArray<b3GpuSolverConstraint>* m_gpuConstraintRows;
- b3OpenCLArray<unsigned int>* m_gpuConstraintInfo1;
+ b3OpenCLArray<b3GpuSolverBody>* m_gpuSolverBodies;
+ b3OpenCLArray<b3BatchConstraint>* m_gpuBatchConstraints;
+ b3OpenCLArray<b3GpuSolverConstraint>* m_gpuConstraintRows;
+ b3OpenCLArray<unsigned int>* m_gpuConstraintInfo1;
-// b3AlignedObjectArray<b3GpuSolverBody> m_cpuSolverBodies;
- b3AlignedObjectArray<b3BatchConstraint> m_cpuBatchConstraints;
- b3AlignedObjectArray<b3GpuSolverConstraint> m_cpuConstraintRows;
- b3AlignedObjectArray<unsigned int> m_cpuConstraintInfo1;
- b3AlignedObjectArray<unsigned int> m_cpuConstraintRowOffsets;
+ // b3AlignedObjectArray<b3GpuSolverBody> m_cpuSolverBodies;
+ b3AlignedObjectArray<b3BatchConstraint> m_cpuBatchConstraints;
+ b3AlignedObjectArray<b3GpuSolverConstraint> m_cpuConstraintRows;
+ b3AlignedObjectArray<unsigned int> m_cpuConstraintInfo1;
+ b3AlignedObjectArray<unsigned int> m_cpuConstraintRowOffsets;
- b3AlignedObjectArray<b3RigidBodyData> m_cpuBodies;
- b3AlignedObjectArray<b3InertiaData> m_cpuInertias;
+ b3AlignedObjectArray<b3RigidBodyData> m_cpuBodies;
+ b3AlignedObjectArray<b3InertiaData> m_cpuInertias;
-
b3AlignedObjectArray<b3GpuGenericConstraint> m_cpuConstraints;
- b3AlignedObjectArray<int> m_batchSizes;
-
-
+ b3AlignedObjectArray<int> m_batchSizes;
};
-
/*
static b3Transform getWorldTransform(b3RigidBodyData* rb)
{
@@ -100,12 +93,12 @@ static const b3Matrix3x3& getInvInertiaTensorWorld(b3InertiaData* inertia)
*/
-static const b3Vector3& getLinearVelocity(b3RigidBodyData* rb)
+static const b3Vector3& getLinearVelocity(b3RigidBodyData* rb)
{
return rb->m_linVel;
}
-static const b3Vector3& getAngularVelocity(b3RigidBodyData* rb)
+static const b3Vector3& getAngularVelocity(b3RigidBodyData* rb)
{
return rb->m_angVel;
}
@@ -114,12 +107,9 @@ b3Vector3 getVelocityInLocalPoint(b3RigidBodyData* rb, const b3Vector3& rel_pos)
{
//we also calculate lin/ang velocity for kinematic objects
return getLinearVelocity(rb) + getAngularVelocity(rb).cross(rel_pos);
-
}
-
-
-b3GpuPgsConstraintSolver::b3GpuPgsConstraintSolver (cl_context ctx, cl_device_id device, cl_command_queue queue,bool usePgs)
+b3GpuPgsConstraintSolver::b3GpuPgsConstraintSolver(cl_context ctx, cl_device_id device, cl_command_queue queue, bool usePgs)
{
m_usePgs = usePgs;
m_gpuData = new b3GpuPgsJacobiSolverInternalData();
@@ -127,45 +117,40 @@ b3GpuPgsConstraintSolver::b3GpuPgsConstraintSolver (cl_context ctx, cl_device_id
m_gpuData->m_device = device;
m_gpuData->m_queue = queue;
- m_gpuData->m_prefixScan = new b3PrefixScanCL(ctx,device,queue);
+ m_gpuData->m_prefixScan = new b3PrefixScanCL(ctx, device, queue);
- m_gpuData->m_gpuConstraintRowOffsets = new b3OpenCLArray<unsigned int>(m_gpuData->m_context,m_gpuData->m_queue);
+ m_gpuData->m_gpuConstraintRowOffsets = new b3OpenCLArray<unsigned int>(m_gpuData->m_context, m_gpuData->m_queue);
- m_gpuData->m_gpuSolverBodies = new b3OpenCLArray<b3GpuSolverBody>(m_gpuData->m_context,m_gpuData->m_queue);
- m_gpuData->m_gpuBatchConstraints = new b3OpenCLArray<b3BatchConstraint>(m_gpuData->m_context,m_gpuData->m_queue);
- m_gpuData->m_gpuConstraintRows = new b3OpenCLArray<b3GpuSolverConstraint>(m_gpuData->m_context,m_gpuData->m_queue);
- m_gpuData->m_gpuConstraintInfo1 = new b3OpenCLArray<unsigned int>(m_gpuData->m_context,m_gpuData->m_queue);
- cl_int errNum=0;
+ m_gpuData->m_gpuSolverBodies = new b3OpenCLArray<b3GpuSolverBody>(m_gpuData->m_context, m_gpuData->m_queue);
+ m_gpuData->m_gpuBatchConstraints = new b3OpenCLArray<b3BatchConstraint>(m_gpuData->m_context, m_gpuData->m_queue);
+ m_gpuData->m_gpuConstraintRows = new b3OpenCLArray<b3GpuSolverConstraint>(m_gpuData->m_context, m_gpuData->m_queue);
+ m_gpuData->m_gpuConstraintInfo1 = new b3OpenCLArray<unsigned int>(m_gpuData->m_context, m_gpuData->m_queue);
+ cl_int errNum = 0;
{
- cl_program prog = b3OpenCLUtils::compileCLProgramFromString(m_gpuData->m_context,m_gpuData->m_device,solveConstraintRowsCL,&errNum,"",B3_JOINT_SOLVER_PATH);
+ cl_program prog = b3OpenCLUtils::compileCLProgramFromString(m_gpuData->m_context, m_gpuData->m_device, solveConstraintRowsCL, &errNum, "", B3_JOINT_SOLVER_PATH);
//cl_program prog = b3OpenCLUtils::compileCLProgramFromString(m_gpuData->m_context,m_gpuData->m_device,0,&errNum,"",B3_JOINT_SOLVER_PATH,true);
- b3Assert(errNum==CL_SUCCESS);
- m_gpuData->m_solveJointConstraintRowsKernels = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context, m_gpuData->m_device,solveConstraintRowsCL, "solveJointConstraintRows",&errNum,prog);
- b3Assert(errNum==CL_SUCCESS);
- m_gpuData->m_initSolverBodiesKernel = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context,m_gpuData->m_device,solveConstraintRowsCL,"initSolverBodies",&errNum,prog);
- b3Assert(errNum==CL_SUCCESS);
- m_gpuData->m_getInfo1Kernel = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context,m_gpuData->m_device,solveConstraintRowsCL,"getInfo1Kernel",&errNum,prog);
- b3Assert(errNum==CL_SUCCESS);
- m_gpuData->m_initBatchConstraintsKernel = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context,m_gpuData->m_device,solveConstraintRowsCL,"initBatchConstraintsKernel",&errNum,prog);
- b3Assert(errNum==CL_SUCCESS);
- m_gpuData->m_getInfo2Kernel= b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context,m_gpuData->m_device,solveConstraintRowsCL,"getInfo2Kernel",&errNum,prog);
- b3Assert(errNum==CL_SUCCESS);
- m_gpuData->m_writeBackVelocitiesKernel = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context,m_gpuData->m_device,solveConstraintRowsCL,"writeBackVelocitiesKernel",&errNum,prog);
- b3Assert(errNum==CL_SUCCESS);
- m_gpuData->m_breakViolatedConstraintsKernel = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context,m_gpuData->m_device,solveConstraintRowsCL,"breakViolatedConstraintsKernel",&errNum,prog);
- b3Assert(errNum==CL_SUCCESS);
-
-
-
+ b3Assert(errNum == CL_SUCCESS);
+ m_gpuData->m_solveJointConstraintRowsKernels = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context, m_gpuData->m_device, solveConstraintRowsCL, "solveJointConstraintRows", &errNum, prog);
+ b3Assert(errNum == CL_SUCCESS);
+ m_gpuData->m_initSolverBodiesKernel = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context, m_gpuData->m_device, solveConstraintRowsCL, "initSolverBodies", &errNum, prog);
+ b3Assert(errNum == CL_SUCCESS);
+ m_gpuData->m_getInfo1Kernel = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context, m_gpuData->m_device, solveConstraintRowsCL, "getInfo1Kernel", &errNum, prog);
+ b3Assert(errNum == CL_SUCCESS);
+ m_gpuData->m_initBatchConstraintsKernel = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context, m_gpuData->m_device, solveConstraintRowsCL, "initBatchConstraintsKernel", &errNum, prog);
+ b3Assert(errNum == CL_SUCCESS);
+ m_gpuData->m_getInfo2Kernel = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context, m_gpuData->m_device, solveConstraintRowsCL, "getInfo2Kernel", &errNum, prog);
+ b3Assert(errNum == CL_SUCCESS);
+ m_gpuData->m_writeBackVelocitiesKernel = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context, m_gpuData->m_device, solveConstraintRowsCL, "writeBackVelocitiesKernel", &errNum, prog);
+ b3Assert(errNum == CL_SUCCESS);
+ m_gpuData->m_breakViolatedConstraintsKernel = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context, m_gpuData->m_device, solveConstraintRowsCL, "breakViolatedConstraintsKernel", &errNum, prog);
+ b3Assert(errNum == CL_SUCCESS);
clReleaseProgram(prog);
}
-
-
}
-b3GpuPgsConstraintSolver::~b3GpuPgsConstraintSolver ()
+b3GpuPgsConstraintSolver::~b3GpuPgsConstraintSolver()
{
clReleaseKernel(m_gpuData->m_solveJointConstraintRowsKernels);
clReleaseKernel(m_gpuData->m_initSolverBodiesKernel);
@@ -195,16 +180,12 @@ struct b3BatchConstraint
static b3AlignedObjectArray<b3BatchConstraint> batchConstraints;
-
-void b3GpuPgsConstraintSolver::recomputeBatches()
+void b3GpuPgsConstraintSolver::recomputeBatches()
{
m_gpuData->m_batchSizes.clear();
}
-
-
-
-b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlySetup(b3OpenCLArray<b3RigidBodyData>* gpuBodies, b3OpenCLArray<b3InertiaData>* gpuInertias, int numBodies, b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints,int numConstraints,const b3ContactSolverInfo& infoGlobal)
+b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlySetup(b3OpenCLArray<b3RigidBodyData>* gpuBodies, b3OpenCLArray<b3InertiaData>* gpuInertias, int numBodies, b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints, int numConstraints, const b3ContactSolverInfo& infoGlobal)
{
B3_PROFILE("GPU solveGroupCacheFriendlySetup");
batchConstraints.resize(numConstraints);
@@ -212,7 +193,6 @@ b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlySetup(b3OpenCLArray<b3
m_staticIdx = -1;
m_maxOverrideNumSolverIterations = 0;
-
/* m_gpuData->m_gpuBodies->resize(numBodies);
m_gpuData->m_gpuBodies->copyFromHostPointer(bodies,numBodies);
@@ -223,15 +203,13 @@ b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlySetup(b3OpenCLArray<b3
m_gpuData->m_gpuSolverBodies->resize(numBodies);
-
m_tmpSolverBodyPool.resize(numBodies);
{
-
if (useGpuInitSolverBodies)
{
B3_PROFILE("m_initSolverBodiesKernel");
- b3LauncherCL launcher(m_gpuData->m_queue,m_gpuData->m_initSolverBodiesKernel,"m_initSolverBodiesKernel");
+ b3LauncherCL launcher(m_gpuData->m_queue, m_gpuData->m_initSolverBodiesKernel, "m_initSolverBodiesKernel");
launcher.setBuffer(m_gpuData->m_gpuSolverBodies->getBufferCL());
launcher.setBuffer(gpuBodies->getBufferCL());
launcher.setConst(numBodies);
@@ -239,48 +217,44 @@ b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlySetup(b3OpenCLArray<b3
clFinish(m_gpuData->m_queue);
// m_gpuData->m_gpuSolverBodies->copyToHost(m_tmpSolverBodyPool);
- } else
+ }
+ else
{
gpuBodies->copyToHost(m_gpuData->m_cpuBodies);
- for (int i=0;i<numBodies;i++)
+ for (int i = 0; i < numBodies; i++)
{
-
b3RigidBodyData& body = m_gpuData->m_cpuBodies[i];
b3GpuSolverBody& solverBody = m_tmpSolverBodyPool[i];
- initSolverBody(i,&solverBody,&body);
+ initSolverBody(i, &solverBody, &body);
solverBody.m_originalBodyIndex = i;
}
m_gpuData->m_gpuSolverBodies->copyFromHost(m_tmpSolverBodyPool);
}
}
-// int totalBodies = 0;
+ // int totalBodies = 0;
int totalNumRows = 0;
//b3RigidBody* rb0=0,*rb1=0;
//if (1)
{
{
-
-
// int i;
m_tmpConstraintSizesPool.resizeNoInitialize(numConstraints);
// b3OpenCLArray<b3GpuGenericConstraint> gpuConstraints(m_gpuData->m_context,m_gpuData->m_queue);
-
if (useGpuInfo1)
{
B3_PROFILE("info1 and init batchConstraint");
-
+
m_gpuData->m_gpuConstraintInfo1->resize(numConstraints);
-
if (1)
{
B3_PROFILE("getInfo1Kernel");
- b3LauncherCL launcher(m_gpuData->m_queue,m_gpuData->m_getInfo1Kernel,"m_getInfo1Kernel");
+ b3LauncherCL launcher(m_gpuData->m_queue, m_gpuData->m_getInfo1Kernel, "m_getInfo1Kernel");
launcher.setBuffer(m_gpuData->m_gpuConstraintInfo1->getBufferCL());
launcher.setBuffer(gpuConstraints->getBufferCL());
launcher.setConst(numConstraints);
@@ -288,19 +262,19 @@ b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlySetup(b3OpenCLArray<b3
clFinish(m_gpuData->m_queue);
}
- if (m_gpuData->m_batchSizes.size()==0)
+ if (m_gpuData->m_batchSizes.size() == 0)
{
B3_PROFILE("initBatchConstraintsKernel");
m_gpuData->m_gpuConstraintRowOffsets->resize(numConstraints);
- unsigned int total=0;
- m_gpuData->m_prefixScan->execute(*m_gpuData->m_gpuConstraintInfo1,*m_gpuData->m_gpuConstraintRowOffsets,numConstraints,&total);
- unsigned int lastElem = m_gpuData->m_gpuConstraintInfo1->at(numConstraints-1);
- totalNumRows = total+lastElem;
+ unsigned int total = 0;
+ m_gpuData->m_prefixScan->execute(*m_gpuData->m_gpuConstraintInfo1, *m_gpuData->m_gpuConstraintRowOffsets, numConstraints, &total);
+ unsigned int lastElem = m_gpuData->m_gpuConstraintInfo1->at(numConstraints - 1);
+ totalNumRows = total + lastElem;
{
B3_PROFILE("init batch constraints");
- b3LauncherCL launcher(m_gpuData->m_queue,m_gpuData->m_initBatchConstraintsKernel,"m_initBatchConstraintsKernel");
+ b3LauncherCL launcher(m_gpuData->m_queue, m_gpuData->m_initBatchConstraintsKernel, "m_initBatchConstraintsKernel");
launcher.setBuffer(m_gpuData->m_gpuConstraintInfo1->getBufferCL());
launcher.setBuffer(m_gpuData->m_gpuConstraintRowOffsets->getBufferCL());
launcher.setBuffer(m_gpuData->m_gpuBatchConstraints->getBufferCL());
@@ -313,79 +287,74 @@ b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlySetup(b3OpenCLArray<b3
//assume the batching happens on CPU, so copy the data
m_gpuData->m_gpuBatchConstraints->copyToHost(batchConstraints);
}
- }
+ }
else
{
- totalNumRows = 0;
+ totalNumRows = 0;
gpuConstraints->copyToHost(m_gpuData->m_cpuConstraints);
//calculate the total number of contraint rows
- for (int i=0;i<numConstraints;i++)
+ for (int i = 0; i < numConstraints; i++)
{
- unsigned int& info1= m_tmpConstraintSizesPool[i];
+ unsigned int& info1 = m_tmpConstraintSizesPool[i];
// unsigned int info1;
if (m_gpuData->m_cpuConstraints[i].isEnabled())
{
-
- m_gpuData->m_cpuConstraints[i].getInfo1(&info1,&m_gpuData->m_cpuBodies[0]);
- } else
+ m_gpuData->m_cpuConstraints[i].getInfo1(&info1, &m_gpuData->m_cpuBodies[0]);
+ }
+ else
{
info1 = 0;
}
-
+
totalNumRows += info1;
}
m_gpuData->m_gpuBatchConstraints->copyFromHost(batchConstraints);
m_gpuData->m_gpuConstraintInfo1->copyFromHost(m_tmpConstraintSizesPool);
-
}
m_tmpSolverNonContactConstraintPool.resizeNoInitialize(totalNumRows);
m_gpuData->m_gpuConstraintRows->resize(totalNumRows);
-
+
// b3GpuConstraintArray verify;
if (useGpuInfo2)
{
{
- B3_PROFILE("getInfo2Kernel");
- b3LauncherCL launcher(m_gpuData->m_queue,m_gpuData->m_getInfo2Kernel,"m_getInfo2Kernel");
- launcher.setBuffer(m_gpuData->m_gpuConstraintRows->getBufferCL());
- launcher.setBuffer(m_gpuData->m_gpuConstraintInfo1->getBufferCL());
- launcher.setBuffer(m_gpuData->m_gpuConstraintRowOffsets->getBufferCL());
- launcher.setBuffer(gpuConstraints->getBufferCL());
- launcher.setBuffer(m_gpuData->m_gpuBatchConstraints->getBufferCL());
- launcher.setBuffer(gpuBodies->getBufferCL());
- launcher.setBuffer(gpuInertias->getBufferCL());
- launcher.setBuffer(m_gpuData->m_gpuSolverBodies->getBufferCL());
- launcher.setConst(infoGlobal.m_timeStep);
- launcher.setConst(infoGlobal.m_erp);
- launcher.setConst(infoGlobal.m_globalCfm);
- launcher.setConst(infoGlobal.m_damping);
- launcher.setConst(infoGlobal.m_numIterations);
- launcher.setConst(numConstraints);
- launcher.launch1D(numConstraints);
- clFinish(m_gpuData->m_queue);
-
- if (m_gpuData->m_batchSizes.size()==0)
- m_gpuData->m_gpuBatchConstraints->copyToHost(batchConstraints);
- //m_gpuData->m_gpuConstraintRows->copyToHost(verify);
- //m_gpuData->m_gpuConstraintRows->copyToHost(m_tmpSolverNonContactConstraintPool);
-
-
+ B3_PROFILE("getInfo2Kernel");
+ b3LauncherCL launcher(m_gpuData->m_queue, m_gpuData->m_getInfo2Kernel, "m_getInfo2Kernel");
+ launcher.setBuffer(m_gpuData->m_gpuConstraintRows->getBufferCL());
+ launcher.setBuffer(m_gpuData->m_gpuConstraintInfo1->getBufferCL());
+ launcher.setBuffer(m_gpuData->m_gpuConstraintRowOffsets->getBufferCL());
+ launcher.setBuffer(gpuConstraints->getBufferCL());
+ launcher.setBuffer(m_gpuData->m_gpuBatchConstraints->getBufferCL());
+ launcher.setBuffer(gpuBodies->getBufferCL());
+ launcher.setBuffer(gpuInertias->getBufferCL());
+ launcher.setBuffer(m_gpuData->m_gpuSolverBodies->getBufferCL());
+ launcher.setConst(infoGlobal.m_timeStep);
+ launcher.setConst(infoGlobal.m_erp);
+ launcher.setConst(infoGlobal.m_globalCfm);
+ launcher.setConst(infoGlobal.m_damping);
+ launcher.setConst(infoGlobal.m_numIterations);
+ launcher.setConst(numConstraints);
+ launcher.launch1D(numConstraints);
+ clFinish(m_gpuData->m_queue);
- }
- }
+ if (m_gpuData->m_batchSizes.size() == 0)
+ m_gpuData->m_gpuBatchConstraints->copyToHost(batchConstraints);
+ //m_gpuData->m_gpuConstraintRows->copyToHost(verify);
+ //m_gpuData->m_gpuConstraintRows->copyToHost(m_tmpSolverNonContactConstraintPool);
+ }
+ }
else
{
-
gpuInertias->copyToHost(m_gpuData->m_cpuInertias);
- ///setup the b3SolverConstraints
-
- for (int i=0;i<numConstraints;i++)
+ ///setup the b3SolverConstraints
+
+ for (int i = 0; i < numConstraints; i++)
{
const int& info1 = m_tmpConstraintSizesPool[i];
-
+
if (info1)
{
int constraintIndex = batchConstraints[i].m_originalConstraintIndex;
@@ -394,15 +363,13 @@ b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlySetup(b3OpenCLArray<b3
b3GpuSolverConstraint* currentConstraintRow = &m_tmpSolverNonContactConstraintPool[constraintRowOffset];
b3GpuGenericConstraint& constraint = m_gpuData->m_cpuConstraints[i];
- b3RigidBodyData& rbA = m_gpuData->m_cpuBodies[ constraint.getRigidBodyA()];
+ b3RigidBodyData& rbA = m_gpuData->m_cpuBodies[constraint.getRigidBodyA()];
//b3RigidBody& rbA = constraint.getRigidBodyA();
- // b3RigidBody& rbB = constraint.getRigidBodyB();
- b3RigidBodyData& rbB = m_gpuData->m_cpuBodies[ constraint.getRigidBodyB()];
-
-
+ // b3RigidBody& rbB = constraint.getRigidBodyB();
+ b3RigidBodyData& rbB = m_gpuData->m_cpuBodies[constraint.getRigidBodyB()];
- int solverBodyIdA = constraint.getRigidBodyA();//getOrInitSolverBody(constraint.getRigidBodyA(),bodies,inertias);
- int solverBodyIdB = constraint.getRigidBodyB();//getOrInitSolverBody(constraint.getRigidBodyB(),bodies,inertias);
+ int solverBodyIdA = constraint.getRigidBodyA(); //getOrInitSolverBody(constraint.getRigidBodyA(),bodies,inertias);
+ int solverBodyIdB = constraint.getRigidBodyB(); //getOrInitSolverBody(constraint.getRigidBodyB(),bodies,inertias);
b3GpuSolverBody* bodyAPtr = &m_tmpSolverBodyPool[solverBodyIdA];
b3GpuSolverBody* bodyBPtr = &m_tmpSolverBodyPool[solverBodyIdB];
@@ -410,7 +377,8 @@ b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlySetup(b3OpenCLArray<b3
if (rbA.m_invMass)
{
batchConstraints[i].m_bodyAPtrAndSignBit = solverBodyIdA;
- } else
+ }
+ else
{
if (!solverBodyIdA)
m_staticIdx = 0;
@@ -420,29 +388,28 @@ b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlySetup(b3OpenCLArray<b3
if (rbB.m_invMass)
{
batchConstraints[i].m_bodyBPtrAndSignBit = solverBodyIdB;
- } else
+ }
+ else
{
if (!solverBodyIdB)
m_staticIdx = 0;
batchConstraints[i].m_bodyBPtrAndSignBit = -solverBodyIdB;
}
-
- int overrideNumSolverIterations = 0;//constraint->getOverrideNumSolverIterations() > 0 ? constraint->getOverrideNumSolverIterations() : infoGlobal.m_numIterations;
- if (overrideNumSolverIterations>m_maxOverrideNumSolverIterations)
+ int overrideNumSolverIterations = 0; //constraint->getOverrideNumSolverIterations() > 0 ? constraint->getOverrideNumSolverIterations() : infoGlobal.m_numIterations;
+ if (overrideNumSolverIterations > m_maxOverrideNumSolverIterations)
m_maxOverrideNumSolverIterations = overrideNumSolverIterations;
-
int j;
- for ( j=0;j<info1;j++)
+ for (j = 0; j < info1; j++)
{
- memset(&currentConstraintRow[j],0,sizeof(b3GpuSolverConstraint));
- currentConstraintRow[j].m_angularComponentA.setValue(0,0,0);
- currentConstraintRow[j].m_angularComponentB.setValue(0,0,0);
+ memset(&currentConstraintRow[j], 0, sizeof(b3GpuSolverConstraint));
+ currentConstraintRow[j].m_angularComponentA.setValue(0, 0, 0);
+ currentConstraintRow[j].m_angularComponentB.setValue(0, 0, 0);
currentConstraintRow[j].m_appliedImpulse = 0.f;
currentConstraintRow[j].m_appliedPushImpulse = 0.f;
currentConstraintRow[j].m_cfm = 0.f;
- currentConstraintRow[j].m_contactNormal.setValue(0,0,0);
+ currentConstraintRow[j].m_contactNormal.setValue(0, 0, 0);
currentConstraintRow[j].m_friction = 0.f;
currentConstraintRow[j].m_frictionIndex = 0;
currentConstraintRow[j].m_jacDiagABInv = 0.f;
@@ -451,13 +418,13 @@ b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlySetup(b3OpenCLArray<b3
currentConstraintRow[j].m_originalContactPoint = 0;
currentConstraintRow[j].m_overrideNumSolverIterations = 0;
- currentConstraintRow[j].m_relpos1CrossNormal.setValue(0,0,0);
- currentConstraintRow[j].m_relpos2CrossNormal.setValue(0,0,0);
+ currentConstraintRow[j].m_relpos1CrossNormal.setValue(0, 0, 0);
+ currentConstraintRow[j].m_relpos2CrossNormal.setValue(0, 0, 0);
currentConstraintRow[j].m_rhs = 0.f;
currentConstraintRow[j].m_rhsPenetration = 0.f;
currentConstraintRow[j].m_solverBodyIdA = 0;
currentConstraintRow[j].m_solverBodyIdB = 0;
-
+
currentConstraintRow[j].m_lowerLimit = -B3_INFINITY;
currentConstraintRow[j].m_upperLimit = B3_INFINITY;
currentConstraintRow[j].m_appliedImpulse = 0.f;
@@ -467,26 +434,25 @@ b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlySetup(b3OpenCLArray<b3
currentConstraintRow[j].m_overrideNumSolverIterations = overrideNumSolverIterations;
}
- bodyAPtr->internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
- bodyAPtr->internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f);
- bodyAPtr->internalGetPushVelocity().setValue(0.f,0.f,0.f);
- bodyAPtr->internalGetTurnVelocity().setValue(0.f,0.f,0.f);
- bodyBPtr->internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
- bodyBPtr->internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f);
- bodyBPtr->internalGetPushVelocity().setValue(0.f,0.f,0.f);
- bodyBPtr->internalGetTurnVelocity().setValue(0.f,0.f,0.f);
-
+ bodyAPtr->internalGetDeltaLinearVelocity().setValue(0.f, 0.f, 0.f);
+ bodyAPtr->internalGetDeltaAngularVelocity().setValue(0.f, 0.f, 0.f);
+ bodyAPtr->internalGetPushVelocity().setValue(0.f, 0.f, 0.f);
+ bodyAPtr->internalGetTurnVelocity().setValue(0.f, 0.f, 0.f);
+ bodyBPtr->internalGetDeltaLinearVelocity().setValue(0.f, 0.f, 0.f);
+ bodyBPtr->internalGetDeltaAngularVelocity().setValue(0.f, 0.f, 0.f);
+ bodyBPtr->internalGetPushVelocity().setValue(0.f, 0.f, 0.f);
+ bodyBPtr->internalGetTurnVelocity().setValue(0.f, 0.f, 0.f);
b3GpuConstraintInfo2 info2;
- info2.fps = 1.f/infoGlobal.m_timeStep;
+ info2.fps = 1.f / infoGlobal.m_timeStep;
info2.erp = infoGlobal.m_erp;
info2.m_J1linearAxis = currentConstraintRow->m_contactNormal;
info2.m_J1angularAxis = currentConstraintRow->m_relpos1CrossNormal;
info2.m_J2linearAxis = 0;
info2.m_J2angularAxis = currentConstraintRow->m_relpos2CrossNormal;
- info2.rowskip = sizeof(b3GpuSolverConstraint)/sizeof(b3Scalar);//check this
+ info2.rowskip = sizeof(b3GpuSolverConstraint) / sizeof(b3Scalar); //check this
///the size of b3GpuSolverConstraint needs be a multiple of b3Scalar
- b3Assert(info2.rowskip*sizeof(b3Scalar)== sizeof(b3GpuSolverConstraint));
+ b3Assert(info2.rowskip * sizeof(b3Scalar) == sizeof(b3GpuSolverConstraint));
info2.m_constraintError = &currentConstraintRow->m_rhs;
currentConstraintRow->m_cfm = infoGlobal.m_globalCfm;
info2.m_damping = infoGlobal.m_damping;
@@ -494,47 +460,45 @@ b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlySetup(b3OpenCLArray<b3
info2.m_lowerLimit = &currentConstraintRow->m_lowerLimit;
info2.m_upperLimit = &currentConstraintRow->m_upperLimit;
info2.m_numIterations = infoGlobal.m_numIterations;
- m_gpuData->m_cpuConstraints[i].getInfo2(&info2,&m_gpuData->m_cpuBodies[0]);
+ m_gpuData->m_cpuConstraints[i].getInfo2(&info2, &m_gpuData->m_cpuBodies[0]);
///finalize the constraint setup
- for ( j=0;j<info1;j++)
+ for (j = 0; j < info1; j++)
{
b3GpuSolverConstraint& solverConstraint = currentConstraintRow[j];
- if (solverConstraint.m_upperLimit>=m_gpuData->m_cpuConstraints[i].getBreakingImpulseThreshold())
+ if (solverConstraint.m_upperLimit >= m_gpuData->m_cpuConstraints[i].getBreakingImpulseThreshold())
{
solverConstraint.m_upperLimit = m_gpuData->m_cpuConstraints[i].getBreakingImpulseThreshold();
}
- if (solverConstraint.m_lowerLimit<=-m_gpuData->m_cpuConstraints[i].getBreakingImpulseThreshold())
+ if (solverConstraint.m_lowerLimit <= -m_gpuData->m_cpuConstraints[i].getBreakingImpulseThreshold())
{
solverConstraint.m_lowerLimit = -m_gpuData->m_cpuConstraints[i].getBreakingImpulseThreshold();
}
- // solverConstraint.m_originalContactPoint = constraint;
-
- b3Matrix3x3& invInertiaWorldA= m_gpuData->m_cpuInertias[constraint.getRigidBodyA()].m_invInertiaWorld;
- {
+ // solverConstraint.m_originalContactPoint = constraint;
+ b3Matrix3x3& invInertiaWorldA = m_gpuData->m_cpuInertias[constraint.getRigidBodyA()].m_invInertiaWorld;
+ {
//b3Vector3 angularFactorA(1,1,1);
const b3Vector3& ftorqueAxis1 = solverConstraint.m_relpos1CrossNormal;
- solverConstraint.m_angularComponentA = invInertiaWorldA*ftorqueAxis1;//*angularFactorA;
+ solverConstraint.m_angularComponentA = invInertiaWorldA * ftorqueAxis1; //*angularFactorA;
}
-
- b3Matrix3x3& invInertiaWorldB= m_gpuData->m_cpuInertias[constraint.getRigidBodyB()].m_invInertiaWorld;
- {
+ b3Matrix3x3& invInertiaWorldB = m_gpuData->m_cpuInertias[constraint.getRigidBodyB()].m_invInertiaWorld;
+ {
const b3Vector3& ftorqueAxis2 = solverConstraint.m_relpos2CrossNormal;
- solverConstraint.m_angularComponentB = invInertiaWorldB*ftorqueAxis2;//*constraint.getRigidBodyB().getAngularFactor();
+ solverConstraint.m_angularComponentB = invInertiaWorldB * ftorqueAxis2; //*constraint.getRigidBodyB().getAngularFactor();
}
{
//it is ok to use solverConstraint.m_contactNormal instead of -solverConstraint.m_contactNormal
//because it gets multiplied iMJlB
- b3Vector3 iMJlA = solverConstraint.m_contactNormal*rbA.m_invMass;
- b3Vector3 iMJaA = invInertiaWorldA*solverConstraint.m_relpos1CrossNormal;
- b3Vector3 iMJlB = solverConstraint.m_contactNormal*rbB.m_invMass;//sign of normal?
- b3Vector3 iMJaB = invInertiaWorldB*solverConstraint.m_relpos2CrossNormal;
+ b3Vector3 iMJlA = solverConstraint.m_contactNormal * rbA.m_invMass;
+ b3Vector3 iMJaA = invInertiaWorldA * solverConstraint.m_relpos1CrossNormal;
+ b3Vector3 iMJlB = solverConstraint.m_contactNormal * rbB.m_invMass; //sign of normal?
+ b3Vector3 iMJaB = invInertiaWorldB * solverConstraint.m_relpos2CrossNormal;
b3Scalar sum = iMJlA.dot(solverConstraint.m_contactNormal);
sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
@@ -542,10 +506,9 @@ b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlySetup(b3OpenCLArray<b3
sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
b3Scalar fsum = b3Fabs(sum);
b3Assert(fsum > B3_EPSILON);
- solverConstraint.m_jacDiagABInv = fsum>B3_EPSILON?b3Scalar(1.)/sum : 0.f;
+ solverConstraint.m_jacDiagABInv = fsum > B3_EPSILON ? b3Scalar(1.) / sum : 0.f;
}
-
///fix rhs
///todo: add force/torque accelerators
{
@@ -553,94 +516,80 @@ b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlySetup(b3OpenCLArray<b3
b3Scalar vel1Dotn = solverConstraint.m_contactNormal.dot(rbA.m_linVel) + solverConstraint.m_relpos1CrossNormal.dot(rbA.m_angVel);
b3Scalar vel2Dotn = -solverConstraint.m_contactNormal.dot(rbB.m_linVel) + solverConstraint.m_relpos2CrossNormal.dot(rbB.m_angVel);
- rel_vel = vel1Dotn+vel2Dotn;
+ rel_vel = vel1Dotn + vel2Dotn;
b3Scalar restitution = 0.f;
- b3Scalar positionalError = solverConstraint.m_rhs;//already filled in by getConstraintInfo2
- b3Scalar velocityError = restitution - rel_vel * info2.m_damping;
- b3Scalar penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv;
- b3Scalar velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv;
- solverConstraint.m_rhs = penetrationImpulse+velocityImpulse;
+ b3Scalar positionalError = solverConstraint.m_rhs; //already filled in by getConstraintInfo2
+ b3Scalar velocityError = restitution - rel_vel * info2.m_damping;
+ b3Scalar penetrationImpulse = positionalError * solverConstraint.m_jacDiagABInv;
+ b3Scalar velocityImpulse = velocityError * solverConstraint.m_jacDiagABInv;
+ solverConstraint.m_rhs = penetrationImpulse + velocityImpulse;
solverConstraint.m_appliedImpulse = 0.f;
-
}
}
-
}
}
-
-
m_gpuData->m_gpuConstraintRows->copyFromHost(m_tmpSolverNonContactConstraintPool);
m_gpuData->m_gpuConstraintInfo1->copyFromHost(m_tmpConstraintSizesPool);
- if (m_gpuData->m_batchSizes.size()==0)
+ if (m_gpuData->m_batchSizes.size() == 0)
m_gpuData->m_gpuBatchConstraints->copyFromHost(batchConstraints);
else
m_gpuData->m_gpuBatchConstraints->copyToHost(batchConstraints);
m_gpuData->m_gpuSolverBodies->copyFromHost(m_tmpSolverBodyPool);
-
-
- }//end useGpuInfo2
-
-
+ } //end useGpuInfo2
}
#ifdef B3_SUPPORT_CONTACT_CONSTRAINTS
{
int i;
- for (i=0;i<numManifolds;i++)
+ for (i = 0; i < numManifolds; i++)
{
b3Contact4& manifold = manifoldPtr[i];
- convertContact(bodies,inertias,&manifold,infoGlobal);
+ convertContact(bodies, inertias, &manifold, infoGlobal);
}
}
-#endif //B3_SUPPORT_CONTACT_CONSTRAINTS
+#endif //B3_SUPPORT_CONTACT_CONSTRAINTS
}
-// b3ContactSolverInfo info = infoGlobal;
-
-
-// int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
-// int numConstraintPool = m_tmpSolverContactConstraintPool.size();
-// int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size();
+ // b3ContactSolverInfo info = infoGlobal;
+ // int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
+ // int numConstraintPool = m_tmpSolverContactConstraintPool.size();
+ // int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size();
return 0.f;
-
}
-
-
///a straight copy from GPU/OpenCL kernel, for debugging
-__inline void internalApplyImpulse( b3GpuSolverBody* body, const b3Vector3& linearComponent, const b3Vector3& angularComponent,float impulseMagnitude)
+__inline void internalApplyImpulse(b3GpuSolverBody* body, const b3Vector3& linearComponent, const b3Vector3& angularComponent, float impulseMagnitude)
{
- body->m_deltaLinearVelocity += linearComponent*impulseMagnitude*body->m_linearFactor;
- body->m_deltaAngularVelocity += angularComponent*(impulseMagnitude*body->m_angularFactor);
+ body->m_deltaLinearVelocity += linearComponent * impulseMagnitude * body->m_linearFactor;
+ body->m_deltaAngularVelocity += angularComponent * (impulseMagnitude * body->m_angularFactor);
}
-
-void resolveSingleConstraintRowGeneric2( b3GpuSolverBody* body1, b3GpuSolverBody* body2, b3GpuSolverConstraint* c)
+void resolveSingleConstraintRowGeneric2(b3GpuSolverBody* body1, b3GpuSolverBody* body2, b3GpuSolverConstraint* c)
{
- float deltaImpulse = c->m_rhs-b3Scalar(c->m_appliedImpulse)*c->m_cfm;
- float deltaVel1Dotn = b3Dot(c->m_contactNormal,body1->m_deltaLinearVelocity) + b3Dot(c->m_relpos1CrossNormal,body1->m_deltaAngularVelocity);
- float deltaVel2Dotn = -b3Dot(c->m_contactNormal,body2->m_deltaLinearVelocity) + b3Dot(c->m_relpos2CrossNormal,body2->m_deltaAngularVelocity);
+ float deltaImpulse = c->m_rhs - b3Scalar(c->m_appliedImpulse) * c->m_cfm;
+ float deltaVel1Dotn = b3Dot(c->m_contactNormal, body1->m_deltaLinearVelocity) + b3Dot(c->m_relpos1CrossNormal, body1->m_deltaAngularVelocity);
+ float deltaVel2Dotn = -b3Dot(c->m_contactNormal, body2->m_deltaLinearVelocity) + b3Dot(c->m_relpos2CrossNormal, body2->m_deltaAngularVelocity);
- deltaImpulse -= deltaVel1Dotn*c->m_jacDiagABInv;
- deltaImpulse -= deltaVel2Dotn*c->m_jacDiagABInv;
+ deltaImpulse -= deltaVel1Dotn * c->m_jacDiagABInv;
+ deltaImpulse -= deltaVel2Dotn * c->m_jacDiagABInv;
float sum = b3Scalar(c->m_appliedImpulse) + deltaImpulse;
if (sum < c->m_lowerLimit)
{
- deltaImpulse = c->m_lowerLimit-b3Scalar(c->m_appliedImpulse);
+ deltaImpulse = c->m_lowerLimit - b3Scalar(c->m_appliedImpulse);
c->m_appliedImpulse = c->m_lowerLimit;
}
- else if (sum > c->m_upperLimit)
+ else if (sum > c->m_upperLimit)
{
- deltaImpulse = c->m_upperLimit-b3Scalar(c->m_appliedImpulse);
+ deltaImpulse = c->m_upperLimit - b3Scalar(c->m_appliedImpulse);
c->m_appliedImpulse = c->m_upperLimit;
}
else
@@ -648,64 +597,56 @@ void resolveSingleConstraintRowGeneric2( b3GpuSolverBody* body1, b3GpuSolverBod
c->m_appliedImpulse = sum;
}
- internalApplyImpulse(body1,c->m_contactNormal*body1->m_invMass,c->m_angularComponentA,deltaImpulse);
- internalApplyImpulse(body2,-c->m_contactNormal*body2->m_invMass,c->m_angularComponentB,deltaImpulse);
-
+ internalApplyImpulse(body1, c->m_contactNormal * body1->m_invMass, c->m_angularComponentA, deltaImpulse);
+ internalApplyImpulse(body2, -c->m_contactNormal * body2->m_invMass, c->m_angularComponentB, deltaImpulse);
}
-
-
-void b3GpuPgsConstraintSolver::initSolverBody(int bodyIndex, b3GpuSolverBody* solverBody, b3RigidBodyData* rb)
+void b3GpuPgsConstraintSolver::initSolverBody(int bodyIndex, b3GpuSolverBody* solverBody, b3RigidBodyData* rb)
{
-
- solverBody->m_deltaLinearVelocity.setValue(0.f,0.f,0.f);
- solverBody->m_deltaAngularVelocity.setValue(0.f,0.f,0.f);
- solverBody->internalGetPushVelocity().setValue(0.f,0.f,0.f);
- solverBody->internalGetTurnVelocity().setValue(0.f,0.f,0.f);
+ solverBody->m_deltaLinearVelocity.setValue(0.f, 0.f, 0.f);
+ solverBody->m_deltaAngularVelocity.setValue(0.f, 0.f, 0.f);
+ solverBody->internalGetPushVelocity().setValue(0.f, 0.f, 0.f);
+ solverBody->internalGetTurnVelocity().setValue(0.f, 0.f, 0.f);
b3Assert(rb);
-// solverBody->m_worldTransform = getWorldTransform(rb);
- solverBody->internalSetInvMass(b3MakeVector3(rb->m_invMass,rb->m_invMass,rb->m_invMass));
+ // solverBody->m_worldTransform = getWorldTransform(rb);
+ solverBody->internalSetInvMass(b3MakeVector3(rb->m_invMass, rb->m_invMass, rb->m_invMass));
solverBody->m_originalBodyIndex = bodyIndex;
- solverBody->m_angularFactor = b3MakeVector3(1,1,1);
- solverBody->m_linearFactor = b3MakeVector3(1,1,1);
+ solverBody->m_angularFactor = b3MakeVector3(1, 1, 1);
+ solverBody->m_linearFactor = b3MakeVector3(1, 1, 1);
solverBody->m_linearVelocity = getLinearVelocity(rb);
solverBody->m_angularVelocity = getAngularVelocity(rb);
}
-
-void b3GpuPgsConstraintSolver::averageVelocities()
+void b3GpuPgsConstraintSolver::averageVelocities()
{
}
-
-b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlyIterations(b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints1,int numConstraints,const b3ContactSolverInfo& infoGlobal)
+b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlyIterations(b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints1, int numConstraints, const b3ContactSolverInfo& infoGlobal)
{
//only create the batches once.
//@todo: incrementally update batches when constraints are added/activated and/or removed/deactivated
B3_PROFILE("GpuSolveGroupCacheFriendlyIterations");
- bool createBatches = m_gpuData->m_batchSizes.size()==0;
+ bool createBatches = m_gpuData->m_batchSizes.size() == 0;
{
-
if (createBatches)
{
-
m_gpuData->m_batchSizes.resize(0);
{
m_gpuData->m_gpuBatchConstraints->copyToHost(batchConstraints);
B3_PROFILE("batch joints");
- b3Assert(batchConstraints.size()==numConstraints);
- int simdWidth =numConstraints+1;
+ b3Assert(batchConstraints.size() == numConstraints);
+ int simdWidth = numConstraints + 1;
int numBodies = m_tmpSolverBodyPool.size();
- sortConstraintByBatch3( &batchConstraints[0], numConstraints, simdWidth , m_staticIdx, numBodies);
+ sortConstraintByBatch3(&batchConstraints[0], numConstraints, simdWidth, m_staticIdx, numBodies);
m_gpuData->m_gpuBatchConstraints->copyFromHost(batchConstraints);
-
}
- } else
+ }
+ else
{
/*b3AlignedObjectArray<b3BatchConstraint> cpuCheckBatches;
m_gpuData->m_gpuBatchConstraints->copyToHost(cpuCheckBatches);
@@ -715,12 +656,11 @@ b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlyIterations(b3OpenCLArr
//>copyFromHost(batchConstraints);
}
int maxIterations = infoGlobal.m_numIterations;
-
+
bool useBatching = true;
- if (useBatching )
+ if (useBatching)
{
-
if (!useGpuSolveJointConstraintRows)
{
B3_PROFILE("copy to host");
@@ -730,24 +670,21 @@ b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlyIterations(b3OpenCLArr
m_gpuData->m_gpuConstraintInfo1->copyToHost(m_gpuData->m_cpuConstraintInfo1);
m_gpuData->m_gpuConstraintRowOffsets->copyToHost(m_gpuData->m_cpuConstraintRowOffsets);
gpuConstraints1->copyToHost(m_gpuData->m_cpuConstraints);
-
}
- for ( int iteration = 0 ; iteration< maxIterations ; iteration++)
+ for (int iteration = 0; iteration < maxIterations; iteration++)
{
-
int batchOffset = 0;
- int constraintOffset=0;
+ int constraintOffset = 0;
int numBatches = m_gpuData->m_batchSizes.size();
- for (int bb=0;bb<numBatches;bb++)
+ for (int bb = 0; bb < numBatches; bb++)
{
int numConstraintsInBatch = m_gpuData->m_batchSizes[bb];
-
if (useGpuSolveJointConstraintRows)
{
B3_PROFILE("solveJointConstraintRowsKernels");
-
+
/*
__kernel void solveJointConstraintRows(__global b3GpuSolverBody* solverBodies,
__global b3BatchConstraint* batchConstraints,
@@ -758,53 +695,48 @@ b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlyIterations(b3OpenCLArr
int batchOffset,
int numConstraintsInBatch*/
-
- b3LauncherCL launcher(m_gpuData->m_queue,m_gpuData->m_solveJointConstraintRowsKernels,"m_solveJointConstraintRowsKernels");
+ b3LauncherCL launcher(m_gpuData->m_queue, m_gpuData->m_solveJointConstraintRowsKernels, "m_solveJointConstraintRowsKernels");
launcher.setBuffer(m_gpuData->m_gpuSolverBodies->getBufferCL());
launcher.setBuffer(m_gpuData->m_gpuBatchConstraints->getBufferCL());
launcher.setBuffer(m_gpuData->m_gpuConstraintRows->getBufferCL());
launcher.setBuffer(m_gpuData->m_gpuConstraintInfo1->getBufferCL());
launcher.setBuffer(m_gpuData->m_gpuConstraintRowOffsets->getBufferCL());
- launcher.setBuffer(gpuConstraints1->getBufferCL());//to detect disabled constraints
+ launcher.setBuffer(gpuConstraints1->getBufferCL()); //to detect disabled constraints
launcher.setConst(batchOffset);
launcher.setConst(numConstraintsInBatch);
launcher.launch1D(numConstraintsInBatch);
-
-
- } else//useGpu
+ }
+ else //useGpu
{
-
-
-
- for (int b=0;b<numConstraintsInBatch;b++)
+ for (int b = 0; b < numConstraintsInBatch; b++)
{
- const b3BatchConstraint& c = batchConstraints[batchOffset+b];
+ const b3BatchConstraint& c = batchConstraints[batchOffset + b];
/*printf("-----------\n");
printf("bb=%d\n",bb);
printf("c.batchId = %d\n", c.m_batchId);
*/
- b3Assert(c.m_batchId==bb);
+ b3Assert(c.m_batchId == bb);
b3GpuGenericConstraint* constraint = &m_gpuData->m_cpuConstraints[c.m_originalConstraintIndex];
- if (constraint->m_flags&B3_CONSTRAINT_FLAG_ENABLED)
+ if (constraint->m_flags & B3_CONSTRAINT_FLAG_ENABLED)
{
int numConstraintRows = m_gpuData->m_cpuConstraintInfo1[c.m_originalConstraintIndex];
int constraintOffset = m_gpuData->m_cpuConstraintRowOffsets[c.m_originalConstraintIndex];
-
- for (int jj=0;jj<numConstraintRows;jj++)
+
+ for (int jj = 0; jj < numConstraintRows; jj++)
{
- //
- b3GpuSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[constraintOffset+jj];
+ //
+ b3GpuSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[constraintOffset + jj];
//resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[constraint.m_solverBodyIdA],m_tmpSolverBodyPool[constraint.m_solverBodyIdB],constraint);
- resolveSingleConstraintRowGeneric2(&m_tmpSolverBodyPool[constraint.m_solverBodyIdA],&m_tmpSolverBodyPool[constraint.m_solverBodyIdB],&constraint);
+ resolveSingleConstraintRowGeneric2(&m_tmpSolverBodyPool[constraint.m_solverBodyIdA], &m_tmpSolverBodyPool[constraint.m_solverBodyIdB], &constraint);
}
}
}
- }//useGpu
- batchOffset+=numConstraintsInBatch;
- constraintOffset+=numConstraintsInBatch;
+ } //useGpu
+ batchOffset += numConstraintsInBatch;
+ constraintOffset += numConstraintsInBatch;
}
- }//for (int iteration...
+ } //for (int iteration...
if (!useGpuSolveJointConstraintRows)
{
@@ -820,20 +752,16 @@ b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlyIterations(b3OpenCLArr
}
//int sz = sizeof(b3GpuSolverBody);
//printf("cpu sizeof(b3GpuSolverBody)=%d\n",sz);
-
-
-
-
-
- } else
+ }
+ else
{
- for ( int iteration = 0 ; iteration< maxIterations ; iteration++)
- {
- int numJoints = m_tmpSolverNonContactConstraintPool.size();
- for (int j=0;j<numJoints;j++)
+ for (int iteration = 0; iteration < maxIterations; iteration++)
+ {
+ int numJoints = m_tmpSolverNonContactConstraintPool.size();
+ for (int j = 0; j < numJoints; j++)
{
b3GpuSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[j];
- resolveSingleConstraintRowGeneric2(&m_tmpSolverBodyPool[constraint.m_solverBodyIdA],&m_tmpSolverBodyPool[constraint.m_solverBodyIdB],&constraint);
+ resolveSingleConstraintRowGeneric2(&m_tmpSolverBodyPool[constraint.m_solverBodyIdA], &m_tmpSolverBodyPool[constraint.m_solverBodyIdB], &constraint);
}
if (!m_usePgs)
@@ -842,212 +770,198 @@ b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlyIterations(b3OpenCLArr
}
}
}
-
}
clFinish(m_gpuData->m_queue);
return 0.f;
}
-
-
-
static b3AlignedObjectArray<int> bodyUsed;
static b3AlignedObjectArray<int> curUsed;
-
-
-inline int b3GpuPgsConstraintSolver::sortConstraintByBatch3( b3BatchConstraint* cs, int numConstraints, int simdWidth , int staticIdx, int numBodies)
+inline int b3GpuPgsConstraintSolver::sortConstraintByBatch3(b3BatchConstraint* cs, int numConstraints, int simdWidth, int staticIdx, int numBodies)
{
//int sz = sizeof(b3BatchConstraint);
B3_PROFILE("sortConstraintByBatch3");
-
+
static int maxSwaps = 0;
int numSwaps = 0;
- curUsed.resize(2*simdWidth);
+ curUsed.resize(2 * simdWidth);
static int maxNumConstraints = 0;
- if (maxNumConstraints<numConstraints)
+ if (maxNumConstraints < numConstraints)
{
maxNumConstraints = numConstraints;
//printf("maxNumConstraints = %d\n",maxNumConstraints );
}
- int numUsedArray = numBodies/32+1;
+ int numUsedArray = numBodies / 32 + 1;
bodyUsed.resize(numUsedArray);
- for (int q=0;q<numUsedArray;q++)
- bodyUsed[q]=0;
+ for (int q = 0; q < numUsedArray; q++)
+ bodyUsed[q] = 0;
-
int curBodyUsed = 0;
int numIter = 0;
-
-
+
#if defined(_DEBUG)
- for(int i=0; i<numConstraints; i++)
+ for (int i = 0; i < numConstraints; i++)
cs[i].m_batchId = -1;
#endif
-
+
int numValidConstraints = 0;
-// int unprocessedConstraintIndex = 0;
+ // int unprocessedConstraintIndex = 0;
int batchIdx = 0;
-
{
B3_PROFILE("cpu batch innerloop");
-
- while( numValidConstraints < numConstraints)
+
+ while (numValidConstraints < numConstraints)
{
numIter++;
int nCurrentBatch = 0;
// clear flag
- for(int i=0; i<curBodyUsed; i++)
- bodyUsed[curUsed[i]/32] = 0;
+ for (int i = 0; i < curBodyUsed; i++)
+ bodyUsed[curUsed[i] / 32] = 0;
- curBodyUsed = 0;
+ curBodyUsed = 0;
- for(int i=numValidConstraints; i<numConstraints; i++)
+ for (int i = numValidConstraints; i < numConstraints; i++)
{
int idx = i;
- b3Assert( idx < numConstraints );
+ b3Assert(idx < numConstraints);
// check if it can go
int bodyAS = cs[idx].m_bodyAPtrAndSignBit;
int bodyBS = cs[idx].m_bodyBPtrAndSignBit;
int bodyA = abs(bodyAS);
int bodyB = abs(bodyBS);
- bool aIsStatic = (bodyAS<0) || bodyAS==staticIdx;
- bool bIsStatic = (bodyBS<0) || bodyBS==staticIdx;
+ bool aIsStatic = (bodyAS < 0) || bodyAS == staticIdx;
+ bool bIsStatic = (bodyBS < 0) || bodyBS == staticIdx;
int aUnavailable = 0;
int bUnavailable = 0;
if (!aIsStatic)
{
- aUnavailable = bodyUsed[ bodyA/32 ] & (1<<(bodyA&31));
+ aUnavailable = bodyUsed[bodyA / 32] & (1 << (bodyA & 31));
}
if (!aUnavailable)
- if (!bIsStatic)
- {
- bUnavailable = bodyUsed[ bodyB/32 ] & (1<<(bodyB&31));
- }
-
- if( aUnavailable==0 && bUnavailable==0 ) // ok
+ if (!bIsStatic)
+ {
+ bUnavailable = bodyUsed[bodyB / 32] & (1 << (bodyB & 31));
+ }
+
+ if (aUnavailable == 0 && bUnavailable == 0) // ok
{
if (!aIsStatic)
{
- bodyUsed[ bodyA/32 ] |= (1<<(bodyA&31));
- curUsed[curBodyUsed++]=bodyA;
+ bodyUsed[bodyA / 32] |= (1 << (bodyA & 31));
+ curUsed[curBodyUsed++] = bodyA;
}
if (!bIsStatic)
{
- bodyUsed[ bodyB/32 ] |= (1<<(bodyB&31));
- curUsed[curBodyUsed++]=bodyB;
+ bodyUsed[bodyB / 32] |= (1 << (bodyB & 31));
+ curUsed[curBodyUsed++] = bodyB;
}
cs[idx].m_batchId = batchIdx;
- if (i!=numValidConstraints)
+ if (i != numValidConstraints)
{
- b3Swap(cs[i],cs[numValidConstraints]);
+ b3Swap(cs[i], cs[numValidConstraints]);
numSwaps++;
}
numValidConstraints++;
{
nCurrentBatch++;
- if( nCurrentBatch == simdWidth )
+ if (nCurrentBatch == simdWidth)
{
nCurrentBatch = 0;
- for(int i=0; i<curBodyUsed; i++)
- bodyUsed[curUsed[i]/32] = 0;
+ for (int i = 0; i < curBodyUsed; i++)
+ bodyUsed[curUsed[i] / 32] = 0;
curBodyUsed = 0;
}
}
}
}
m_gpuData->m_batchSizes.push_back(nCurrentBatch);
- batchIdx ++;
+ batchIdx++;
}
}
-
+
#if defined(_DEBUG)
- // debugPrintf( "nBatches: %d\n", batchIdx );
- for(int i=0; i<numConstraints; i++)
- {
- b3Assert( cs[i].m_batchId != -1 );
- }
+ // debugPrintf( "nBatches: %d\n", batchIdx );
+ for (int i = 0; i < numConstraints; i++)
+ {
+ b3Assert(cs[i].m_batchId != -1);
+ }
#endif
- if (maxSwaps<numSwaps)
+ if (maxSwaps < numSwaps)
{
maxSwaps = numSwaps;
//printf("maxSwaps = %d\n", maxSwaps);
}
-
+
return batchIdx;
}
-
/// b3PgsJacobiSolver Sequentially applies impulses
-b3Scalar b3GpuPgsConstraintSolver::solveGroup(b3OpenCLArray<b3RigidBodyData>* gpuBodies, b3OpenCLArray<b3InertiaData>* gpuInertias,
- int numBodies, b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints,int numConstraints, const b3ContactSolverInfo& infoGlobal)
+b3Scalar b3GpuPgsConstraintSolver::solveGroup(b3OpenCLArray<b3RigidBodyData>* gpuBodies, b3OpenCLArray<b3InertiaData>* gpuInertias,
+ int numBodies, b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints, int numConstraints, const b3ContactSolverInfo& infoGlobal)
{
-
B3_PROFILE("solveJoints");
//you need to provide at least some bodies
-
- solveGroupCacheFriendlySetup( gpuBodies, gpuInertias,numBodies,gpuConstraints, numConstraints,infoGlobal);
- solveGroupCacheFriendlyIterations(gpuConstraints, numConstraints,infoGlobal);
+ solveGroupCacheFriendlySetup(gpuBodies, gpuInertias, numBodies, gpuConstraints, numConstraints, infoGlobal);
+
+ solveGroupCacheFriendlyIterations(gpuConstraints, numConstraints, infoGlobal);
+
+ solveGroupCacheFriendlyFinish(gpuBodies, gpuInertias, numBodies, gpuConstraints, numConstraints, infoGlobal);
- solveGroupCacheFriendlyFinish(gpuBodies, gpuInertias,numBodies, gpuConstraints, numConstraints, infoGlobal);
-
return 0.f;
}
-void b3GpuPgsConstraintSolver::solveJoints(int numBodies, b3OpenCLArray<b3RigidBodyData>* gpuBodies, b3OpenCLArray<b3InertiaData>* gpuInertias,
- int numConstraints, b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints)
+void b3GpuPgsConstraintSolver::solveJoints(int numBodies, b3OpenCLArray<b3RigidBodyData>* gpuBodies, b3OpenCLArray<b3InertiaData>* gpuInertias,
+ int numConstraints, b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints)
{
b3ContactSolverInfo infoGlobal;
infoGlobal.m_splitImpulse = false;
- infoGlobal.m_timeStep = 1.f/60.f;
- infoGlobal.m_numIterations = 4;//4;
-// infoGlobal.m_solverMode|=B3_SOLVER_USE_2_FRICTION_DIRECTIONS|B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS|B3_SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION;
+ infoGlobal.m_timeStep = 1.f / 60.f;
+ infoGlobal.m_numIterations = 4; //4;
+ // infoGlobal.m_solverMode|=B3_SOLVER_USE_2_FRICTION_DIRECTIONS|B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS|B3_SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION;
//infoGlobal.m_solverMode|=B3_SOLVER_USE_2_FRICTION_DIRECTIONS|B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS;
- infoGlobal.m_solverMode|=B3_SOLVER_USE_2_FRICTION_DIRECTIONS;
+ infoGlobal.m_solverMode |= B3_SOLVER_USE_2_FRICTION_DIRECTIONS;
//if (infoGlobal.m_solverMode & B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS)
//if ((infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & B3_SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION))
-
-
- solveGroup(gpuBodies,gpuInertias,numBodies,gpuConstraints,numConstraints,infoGlobal);
+ solveGroup(gpuBodies, gpuInertias, numBodies, gpuConstraints, numConstraints, infoGlobal);
}
//b3AlignedObjectArray<b3RigidBodyData> testBodies;
-
-b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlyFinish(b3OpenCLArray<b3RigidBodyData>* gpuBodies,b3OpenCLArray<b3InertiaData>* gpuInertias,int numBodies,b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints,int numConstraints,const b3ContactSolverInfo& infoGlobal)
+b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlyFinish(b3OpenCLArray<b3RigidBodyData>* gpuBodies, b3OpenCLArray<b3InertiaData>* gpuInertias, int numBodies, b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints, int numConstraints, const b3ContactSolverInfo& infoGlobal)
{
B3_PROFILE("solveGroupCacheFriendlyFinish");
-// int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
-// int i,j;
-
+ // int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+ // int i,j;
{
if (gpuBreakConstraints)
{
B3_PROFILE("breakViolatedConstraintsKernel");
- b3LauncherCL launcher(m_gpuData->m_queue,m_gpuData->m_breakViolatedConstraintsKernel,"m_breakViolatedConstraintsKernel");
+ b3LauncherCL launcher(m_gpuData->m_queue, m_gpuData->m_breakViolatedConstraintsKernel, "m_breakViolatedConstraintsKernel");
launcher.setBuffer(gpuConstraints->getBufferCL());
launcher.setBuffer(m_gpuData->m_gpuConstraintInfo1->getBufferCL());
launcher.setBuffer(m_gpuData->m_gpuConstraintRowOffsets->getBufferCL());
launcher.setBuffer(m_gpuData->m_gpuConstraintRows->getBufferCL());
launcher.setConst(numConstraints);
launcher.launch1D(numConstraints);
- } else
+ }
+ else
{
gpuConstraints->copyToHost(m_gpuData->m_cpuConstraints);
m_gpuData->m_gpuBatchConstraints->copyToHost(m_gpuData->m_cpuBatchConstraints);
@@ -1056,31 +970,28 @@ b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlyFinish(b3OpenCLArray<b
m_gpuData->m_gpuConstraintInfo1->copyToHost(m_gpuData->m_cpuConstraintInfo1);
m_gpuData->m_gpuConstraintRowOffsets->copyToHost(m_gpuData->m_cpuConstraintRowOffsets);
- for (int cid=0;cid<numConstraints;cid++)
+ for (int cid = 0; cid < numConstraints; cid++)
{
int originalConstraintIndex = batchConstraints[cid].m_originalConstraintIndex;
int constraintRowOffset = m_gpuData->m_cpuConstraintRowOffsets[originalConstraintIndex];
int numRows = m_gpuData->m_cpuConstraintInfo1[originalConstraintIndex];
if (numRows)
{
-
- // printf("cid=%d, breakingThreshold =%f\n",cid,breakingThreshold);
- for (int i=0;i<numRows;i++)
+ // printf("cid=%d, breakingThreshold =%f\n",cid,breakingThreshold);
+ for (int i = 0; i < numRows; i++)
{
- int rowIndex =constraintRowOffset+i;
+ int rowIndex = constraintRowOffset + i;
int orgConstraintIndex = m_gpuData->m_cpuConstraintRows[rowIndex].m_originalConstraintIndex;
float breakingThreshold = m_gpuData->m_cpuConstraints[orgConstraintIndex].m_breakingImpulseThreshold;
- // printf("rows[%d].m_appliedImpulse=%f\n",rowIndex,rows[rowIndex].m_appliedImpulse);
+ // printf("rows[%d].m_appliedImpulse=%f\n",rowIndex,rows[rowIndex].m_appliedImpulse);
if (b3Fabs(m_gpuData->m_cpuConstraintRows[rowIndex].m_appliedImpulse) >= breakingThreshold)
{
-
- m_gpuData->m_cpuConstraints[orgConstraintIndex].m_flags =0;//&= ~B3_CONSTRAINT_FLAG_ENABLED;
+ m_gpuData->m_cpuConstraints[orgConstraintIndex].m_flags = 0; //&= ~B3_CONSTRAINT_FLAG_ENABLED;
}
}
}
}
-
gpuConstraints->copyFromHost(m_gpuData->m_cpuConstraints);
}
}
@@ -1090,28 +1001,27 @@ b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlyFinish(b3OpenCLArray<b
{
B3_PROFILE("GPU write back velocities and transforms");
- b3LauncherCL launcher(m_gpuData->m_queue,m_gpuData->m_writeBackVelocitiesKernel,"m_writeBackVelocitiesKernel");
+ b3LauncherCL launcher(m_gpuData->m_queue, m_gpuData->m_writeBackVelocitiesKernel, "m_writeBackVelocitiesKernel");
launcher.setBuffer(gpuBodies->getBufferCL());
launcher.setBuffer(m_gpuData->m_gpuSolverBodies->getBufferCL());
launcher.setConst(numBodies);
launcher.launch1D(numBodies);
clFinish(m_gpuData->m_queue);
-// m_gpuData->m_gpuSolverBodies->copyToHost(m_tmpSolverBodyPool);
-// m_gpuData->m_gpuBodies->copyToHostPointer(bodies,numBodies);
+ // m_gpuData->m_gpuSolverBodies->copyToHost(m_tmpSolverBodyPool);
+ // m_gpuData->m_gpuBodies->copyToHostPointer(bodies,numBodies);
//m_gpuData->m_gpuBodies->copyToHost(testBodies);
-
- }
+ }
else
{
B3_PROFILE("CPU write back velocities and transforms");
m_gpuData->m_gpuSolverBodies->copyToHost(m_tmpSolverBodyPool);
gpuBodies->copyToHost(m_gpuData->m_cpuBodies);
- for ( int i=0;i<m_tmpSolverBodyPool.size();i++)
+ for (int i = 0; i < m_tmpSolverBodyPool.size(); i++)
{
int bodyIndex = m_tmpSolverBodyPool[i].m_originalBodyIndex;
//printf("bodyIndex=%d\n",bodyIndex);
- b3Assert(i==bodyIndex);
+ b3Assert(i == bodyIndex);
b3RigidBodyData* body = &m_gpuData->m_cpuBodies[bodyIndex];
if (body->m_invMass)
@@ -1125,11 +1035,12 @@ b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlyFinish(b3OpenCLArray<b
{
body->m_linVel = m_tmpSolverBodyPool[i].m_linearVelocity;
body->m_angVel = m_tmpSolverBodyPool[i].m_angularVelocity;
- } else
+ }
+ else
{
b3Assert(0);
}
- /*
+ /*
if (infoGlobal.m_splitImpulse)
{
body->m_pos = m_tmpSolverBodyPool[i].m_worldTransform.getOrigin();
@@ -1139,10 +1050,9 @@ b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlyFinish(b3OpenCLArray<b
}
*/
}
- }//for
+ } //for
gpuBodies->copyFromHost(m_gpuData->m_cpuBodies);
-
}
}
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuPgsConstraintSolver.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuPgsConstraintSolver.h
index ec0e3f73d6..00bc544f02 100644
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuPgsConstraintSolver.h
+++ b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuPgsConstraintSolver.h
@@ -19,7 +19,6 @@ subject to the following restrictions:
struct b3Contact4;
struct b3ContactPoint;
-
class b3Dispatcher;
#include "Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.h"
@@ -38,41 +37,40 @@ class b3GpuPgsConstraintSolver
protected:
int m_staticIdx;
struct b3GpuPgsJacobiSolverInternalData* m_gpuData;
- protected:
- b3AlignedObjectArray<b3GpuSolverBody> m_tmpSolverBodyPool;
- b3GpuConstraintArray m_tmpSolverContactConstraintPool;
- b3GpuConstraintArray m_tmpSolverNonContactConstraintPool;
- b3GpuConstraintArray m_tmpSolverContactFrictionConstraintPool;
- b3GpuConstraintArray m_tmpSolverContactRollingFrictionConstraintPool;
+
+protected:
+ b3AlignedObjectArray<b3GpuSolverBody> m_tmpSolverBodyPool;
+ b3GpuConstraintArray m_tmpSolverContactConstraintPool;
+ b3GpuConstraintArray m_tmpSolverNonContactConstraintPool;
+ b3GpuConstraintArray m_tmpSolverContactFrictionConstraintPool;
+ b3GpuConstraintArray m_tmpSolverContactRollingFrictionConstraintPool;
b3AlignedObjectArray<unsigned int> m_tmpConstraintSizesPool;
-
- bool m_usePgs;
- void averageVelocities();
+ bool m_usePgs;
+ void averageVelocities();
- int m_maxOverrideNumSolverIterations;
+ int m_maxOverrideNumSolverIterations;
- int m_numSplitImpulseRecoveries;
+ int m_numSplitImpulseRecoveries;
-// int getOrInitSolverBody(int bodyIndex, b3RigidBodyData* bodies,b3InertiaData* inertias);
- void initSolverBody(int bodyIndex, b3GpuSolverBody* solverBody, b3RigidBodyData* rb);
+ // int getOrInitSolverBody(int bodyIndex, b3RigidBodyData* bodies,b3InertiaData* inertias);
+ void initSolverBody(int bodyIndex, b3GpuSolverBody* solverBody, b3RigidBodyData* rb);
public:
- b3GpuPgsConstraintSolver (cl_context ctx, cl_device_id device, cl_command_queue queue,bool usePgs);
- virtual~b3GpuPgsConstraintSolver ();
-
- virtual b3Scalar solveGroupCacheFriendlyIterations(b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints1,int numConstraints,const b3ContactSolverInfo& infoGlobal);
- virtual b3Scalar solveGroupCacheFriendlySetup(b3OpenCLArray<b3RigidBodyData>* gpuBodies, b3OpenCLArray<b3InertiaData>* gpuInertias, int numBodies,b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints,int numConstraints,const b3ContactSolverInfo& infoGlobal);
- b3Scalar solveGroupCacheFriendlyFinish(b3OpenCLArray<b3RigidBodyData>* gpuBodies,b3OpenCLArray<b3InertiaData>* gpuInertias,int numBodies,b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints,int numConstraints,const b3ContactSolverInfo& infoGlobal);
+ b3GpuPgsConstraintSolver(cl_context ctx, cl_device_id device, cl_command_queue queue, bool usePgs);
+ virtual ~b3GpuPgsConstraintSolver();
+ virtual b3Scalar solveGroupCacheFriendlyIterations(b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints1, int numConstraints, const b3ContactSolverInfo& infoGlobal);
+ virtual b3Scalar solveGroupCacheFriendlySetup(b3OpenCLArray<b3RigidBodyData>* gpuBodies, b3OpenCLArray<b3InertiaData>* gpuInertias, int numBodies, b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints, int numConstraints, const b3ContactSolverInfo& infoGlobal);
+ b3Scalar solveGroupCacheFriendlyFinish(b3OpenCLArray<b3RigidBodyData>* gpuBodies, b3OpenCLArray<b3InertiaData>* gpuInertias, int numBodies, b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints, int numConstraints, const b3ContactSolverInfo& infoGlobal);
- b3Scalar solveGroup(b3OpenCLArray<b3RigidBodyData>* gpuBodies,b3OpenCLArray<b3InertiaData>* gpuInertias, int numBodies,b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints,int numConstraints,const b3ContactSolverInfo& infoGlobal);
- void solveJoints(int numBodies, b3OpenCLArray<b3RigidBodyData>* gpuBodies, b3OpenCLArray<b3InertiaData>* gpuInertias,
- int numConstraints, b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints);
+ b3Scalar solveGroup(b3OpenCLArray<b3RigidBodyData>* gpuBodies, b3OpenCLArray<b3InertiaData>* gpuInertias, int numBodies, b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints, int numConstraints, const b3ContactSolverInfo& infoGlobal);
+ void solveJoints(int numBodies, b3OpenCLArray<b3RigidBodyData>* gpuBodies, b3OpenCLArray<b3InertiaData>* gpuInertias,
+ int numConstraints, b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints);
- int sortConstraintByBatch3( struct b3BatchConstraint* cs, int numConstraints, int simdWidth , int staticIdx, int numBodies);
- void recomputeBatches();
+ int sortConstraintByBatch3(struct b3BatchConstraint* cs, int numConstraints, int simdWidth, int staticIdx, int numBodies);
+ void recomputeBatches();
};
-#endif //B3_GPU_PGS_CONSTRAINT_SOLVER_H
+#endif //B3_GPU_PGS_CONSTRAINT_SOLVER_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuPgsContactSolver.cpp b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuPgsContactSolver.cpp
index f0b0abd5e0..e3d235a4fd 100644
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuPgsContactSolver.cpp
+++ b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuPgsContactSolver.cpp
@@ -2,7 +2,7 @@
bool gUseLargeBatches = false;
bool gCpuBatchContacts = false;
bool gCpuSolveConstraint = false;
-bool gCpuRadixSort=false;
+bool gCpuRadixSort = false;
bool gCpuSetSortData = false;
bool gCpuSortContactsDeterminism = false;
bool gUseCpuCopyConstraints = false;
@@ -11,7 +11,6 @@ bool gReorderContactsOnCpu = false;
bool optionalSortContactsDeterminism = true;
-
#include "b3GpuPgsContactSolver.h"
#include "Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h"
@@ -23,7 +22,6 @@ bool optionalSortContactsDeterminism = true;
#include "Bullet3Collision/NarrowPhaseCollision/b3Config.h"
#include "b3Solver.h"
-
#define B3_SOLVER_SETUP_KERNEL_PATH "src/Bullet3OpenCL/RigidBody/kernels/solverSetup.cl"
#define B3_SOLVER_SETUP2_KERNEL_PATH "src/Bullet3OpenCL/RigidBody/kernels/solverSetup2.cl"
#define B3_SOLVER_CONTACT_KERNEL_PATH "src/Bullet3OpenCL/RigidBody/kernels/solveContact.cl"
@@ -38,11 +36,7 @@ bool optionalSortContactsDeterminism = true;
#include "kernels/batchingKernels.h"
#include "kernels/batchingKernelsNew.h"
-
-
-
-
-struct b3GpuBatchingPgsSolverInternalData
+struct b3GpuBatchingPgsSolverInternalData
{
cl_context m_context;
cl_device_id m_device;
@@ -53,9 +47,9 @@ struct b3GpuBatchingPgsSolverInternalData
b3OpenCLArray<b3GpuConstraint4>* m_contactCGPU;
b3OpenCLArray<unsigned int>* m_numConstraints;
b3OpenCLArray<unsigned int>* m_offsets;
-
- b3Solver* m_solverGPU;
-
+
+ b3Solver* m_solverGPU;
+
cl_kernel m_batchingKernel;
cl_kernel m_batchingKernelNew;
cl_kernel m_solveContactKernel;
@@ -67,17 +61,14 @@ struct b3GpuBatchingPgsSolverInternalData
cl_kernel m_reorderContactKernel;
cl_kernel m_copyConstraintKernel;
- cl_kernel m_setDeterminismSortDataBodyAKernel;
- cl_kernel m_setDeterminismSortDataBodyBKernel;
- cl_kernel m_setDeterminismSortDataChildShapeAKernel;
- cl_kernel m_setDeterminismSortDataChildShapeBKernel;
-
+ cl_kernel m_setDeterminismSortDataBodyAKernel;
+ cl_kernel m_setDeterminismSortDataBodyBKernel;
+ cl_kernel m_setDeterminismSortDataChildShapeAKernel;
+ cl_kernel m_setDeterminismSortDataChildShapeBKernel;
-
-
- class b3RadixSort32CL* m_sort32;
- class b3BoundSearchCL* m_search;
- class b3PrefixScanCL* m_scan;
+ class b3RadixSort32CL* m_sort32;
+ class b3BoundSearchCL* m_search;
+ class b3PrefixScanCL* m_scan;
b3OpenCLArray<b3SortData>* m_sortDataBuffer;
b3OpenCLArray<b3Contact4>* m_contactBuffer;
@@ -85,63 +76,56 @@ struct b3GpuBatchingPgsSolverInternalData
b3OpenCLArray<b3RigidBodyData>* m_bodyBufferGPU;
b3OpenCLArray<b3InertiaData>* m_inertiaBufferGPU;
b3OpenCLArray<b3Contact4>* m_pBufContactOutGPU;
-
- b3OpenCLArray<b3Contact4>* m_pBufContactOutGPUCopy;
- b3OpenCLArray<b3SortData>* m_contactKeyValues;
+ b3OpenCLArray<b3Contact4>* m_pBufContactOutGPUCopy;
+ b3OpenCLArray<b3SortData>* m_contactKeyValues;
b3AlignedObjectArray<unsigned int> m_idxBuffer;
b3AlignedObjectArray<b3SortData> m_sortData;
b3AlignedObjectArray<b3Contact4> m_old;
- b3AlignedObjectArray<int> m_batchSizes;
- b3OpenCLArray<int>* m_batchSizesGpu;
-
+ b3AlignedObjectArray<int> m_batchSizes;
+ b3OpenCLArray<int>* m_batchSizesGpu;
};
-
-
-b3GpuPgsContactSolver::b3GpuPgsContactSolver(cl_context ctx,cl_device_id device, cl_command_queue q,int pairCapacity)
+b3GpuPgsContactSolver::b3GpuPgsContactSolver(cl_context ctx, cl_device_id device, cl_command_queue q, int pairCapacity)
{
- m_debugOutput=0;
+ m_debugOutput = 0;
m_data = new b3GpuBatchingPgsSolverInternalData;
m_data->m_context = ctx;
m_data->m_device = device;
m_data->m_queue = q;
m_data->m_pairCapacity = pairCapacity;
m_data->m_nIterations = 4;
- m_data->m_batchSizesGpu = new b3OpenCLArray<int>(ctx,q);
- m_data->m_bodyBufferGPU = new b3OpenCLArray<b3RigidBodyData>(ctx,q);
- m_data->m_inertiaBufferGPU = new b3OpenCLArray<b3InertiaData>(ctx,q);
- m_data->m_pBufContactOutGPU = new b3OpenCLArray<b3Contact4>(ctx,q);
-
- m_data->m_pBufContactOutGPUCopy = new b3OpenCLArray<b3Contact4>(ctx,q);
- m_data->m_contactKeyValues = new b3OpenCLArray<b3SortData>(ctx,q);
+ m_data->m_batchSizesGpu = new b3OpenCLArray<int>(ctx, q);
+ m_data->m_bodyBufferGPU = new b3OpenCLArray<b3RigidBodyData>(ctx, q);
+ m_data->m_inertiaBufferGPU = new b3OpenCLArray<b3InertiaData>(ctx, q);
+ m_data->m_pBufContactOutGPU = new b3OpenCLArray<b3Contact4>(ctx, q);
+ m_data->m_pBufContactOutGPUCopy = new b3OpenCLArray<b3Contact4>(ctx, q);
+ m_data->m_contactKeyValues = new b3OpenCLArray<b3SortData>(ctx, q);
- m_data->m_solverGPU = new b3Solver(ctx,device,q,512*1024);
+ m_data->m_solverGPU = new b3Solver(ctx, device, q, 512 * 1024);
- m_data->m_sort32 = new b3RadixSort32CL(ctx,device,m_data->m_queue);
- m_data->m_scan = new b3PrefixScanCL(ctx,device,m_data->m_queue,B3_SOLVER_N_CELLS);
- m_data->m_search = new b3BoundSearchCL(ctx,device,m_data->m_queue,B3_SOLVER_N_CELLS);
+ m_data->m_sort32 = new b3RadixSort32CL(ctx, device, m_data->m_queue);
+ m_data->m_scan = new b3PrefixScanCL(ctx, device, m_data->m_queue, B3_SOLVER_N_CELLS);
+ m_data->m_search = new b3BoundSearchCL(ctx, device, m_data->m_queue, B3_SOLVER_N_CELLS);
- const int sortSize = B3NEXTMULTIPLEOF( pairCapacity, 512 );
+ const int sortSize = B3NEXTMULTIPLEOF(pairCapacity, 512);
- m_data->m_sortDataBuffer = new b3OpenCLArray<b3SortData>(ctx,m_data->m_queue,sortSize);
- m_data->m_contactBuffer = new b3OpenCLArray<b3Contact4>(ctx,m_data->m_queue);
+ m_data->m_sortDataBuffer = new b3OpenCLArray<b3SortData>(ctx, m_data->m_queue, sortSize);
+ m_data->m_contactBuffer = new b3OpenCLArray<b3Contact4>(ctx, m_data->m_queue);
- m_data->m_numConstraints = new b3OpenCLArray<unsigned int>(ctx,m_data->m_queue,B3_SOLVER_N_CELLS);
+ m_data->m_numConstraints = new b3OpenCLArray<unsigned int>(ctx, m_data->m_queue, B3_SOLVER_N_CELLS);
m_data->m_numConstraints->resize(B3_SOLVER_N_CELLS);
- m_data->m_contactCGPU = new b3OpenCLArray<b3GpuConstraint4>(ctx,q,pairCapacity);
+ m_data->m_contactCGPU = new b3OpenCLArray<b3GpuConstraint4>(ctx, q, pairCapacity);
- m_data->m_offsets = new b3OpenCLArray<unsigned int>( ctx,m_data->m_queue,B3_SOLVER_N_CELLS);
+ m_data->m_offsets = new b3OpenCLArray<unsigned int>(ctx, m_data->m_queue, B3_SOLVER_N_CELLS);
m_data->m_offsets->resize(B3_SOLVER_N_CELLS);
const char* additionalMacros = "";
//const char* srcFileNameForCaching="";
-
-
cl_int pErrNum;
const char* batchKernelSource = batchingKernelsCL;
const char* batchKernelNewSource = batchingKernelsNewCL;
@@ -149,88 +133,73 @@ b3GpuPgsContactSolver::b3GpuPgsContactSolver(cl_context ctx,cl_device_id device,
const char* solverSetup2Source = solverSetup2CL;
const char* solveContactSource = solveContactCL;
const char* solveFrictionSource = solveFrictionCL;
-
-
+
{
-
- cl_program solveContactProg= b3OpenCLUtils::compileCLProgramFromString( ctx, device, solveContactSource, &pErrNum,additionalMacros, B3_SOLVER_CONTACT_KERNEL_PATH);
+ cl_program solveContactProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, solveContactSource, &pErrNum, additionalMacros, B3_SOLVER_CONTACT_KERNEL_PATH);
b3Assert(solveContactProg);
-
- cl_program solveFrictionProg= b3OpenCLUtils::compileCLProgramFromString( ctx, device, solveFrictionSource, &pErrNum,additionalMacros, B3_SOLVER_FRICTION_KERNEL_PATH);
+
+ cl_program solveFrictionProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, solveFrictionSource, &pErrNum, additionalMacros, B3_SOLVER_FRICTION_KERNEL_PATH);
b3Assert(solveFrictionProg);
- cl_program solverSetup2Prog= b3OpenCLUtils::compileCLProgramFromString( ctx, device, solverSetup2Source, &pErrNum,additionalMacros, B3_SOLVER_SETUP2_KERNEL_PATH);
-
-
+ cl_program solverSetup2Prog = b3OpenCLUtils::compileCLProgramFromString(ctx, device, solverSetup2Source, &pErrNum, additionalMacros, B3_SOLVER_SETUP2_KERNEL_PATH);
+
b3Assert(solverSetup2Prog);
-
- cl_program solverSetupProg= b3OpenCLUtils::compileCLProgramFromString( ctx, device, solverSetupSource, &pErrNum,additionalMacros, B3_SOLVER_SETUP_KERNEL_PATH);
+ cl_program solverSetupProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, solverSetupSource, &pErrNum, additionalMacros, B3_SOLVER_SETUP_KERNEL_PATH);
b3Assert(solverSetupProg);
-
-
- m_data->m_solveFrictionKernel= b3OpenCLUtils::compileCLKernelFromString( ctx, device, solveFrictionSource, "BatchSolveKernelFriction", &pErrNum, solveFrictionProg,additionalMacros );
+
+ m_data->m_solveFrictionKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solveFrictionSource, "BatchSolveKernelFriction", &pErrNum, solveFrictionProg, additionalMacros);
b3Assert(m_data->m_solveFrictionKernel);
- m_data->m_solveContactKernel= b3OpenCLUtils::compileCLKernelFromString( ctx, device, solveContactSource, "BatchSolveKernelContact", &pErrNum, solveContactProg,additionalMacros );
+ m_data->m_solveContactKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solveContactSource, "BatchSolveKernelContact", &pErrNum, solveContactProg, additionalMacros);
b3Assert(m_data->m_solveContactKernel);
- m_data->m_solveSingleContactKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solveContactSource, "solveSingleContactKernel", &pErrNum, solveContactProg,additionalMacros );
+ m_data->m_solveSingleContactKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solveContactSource, "solveSingleContactKernel", &pErrNum, solveContactProg, additionalMacros);
b3Assert(m_data->m_solveSingleContactKernel);
- m_data->m_solveSingleFrictionKernel =b3OpenCLUtils::compileCLKernelFromString( ctx, device, solveFrictionSource, "solveSingleFrictionKernel", &pErrNum, solveFrictionProg,additionalMacros );
+ m_data->m_solveSingleFrictionKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solveFrictionSource, "solveSingleFrictionKernel", &pErrNum, solveFrictionProg, additionalMacros);
b3Assert(m_data->m_solveSingleFrictionKernel);
-
- m_data->m_contactToConstraintKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solverSetupSource, "ContactToConstraintKernel", &pErrNum, solverSetupProg,additionalMacros );
+
+ m_data->m_contactToConstraintKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverSetupSource, "ContactToConstraintKernel", &pErrNum, solverSetupProg, additionalMacros);
b3Assert(m_data->m_contactToConstraintKernel);
-
- m_data->m_setSortDataKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solverSetup2Source, "SetSortDataKernel", &pErrNum, solverSetup2Prog,additionalMacros );
+
+ m_data->m_setSortDataKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverSetup2Source, "SetSortDataKernel", &pErrNum, solverSetup2Prog, additionalMacros);
b3Assert(m_data->m_setSortDataKernel);
- m_data->m_setDeterminismSortDataBodyAKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solverSetup2Source, "SetDeterminismSortDataBodyA", &pErrNum, solverSetup2Prog,additionalMacros );
+ m_data->m_setDeterminismSortDataBodyAKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverSetup2Source, "SetDeterminismSortDataBodyA", &pErrNum, solverSetup2Prog, additionalMacros);
b3Assert(m_data->m_setDeterminismSortDataBodyAKernel);
- m_data->m_setDeterminismSortDataBodyBKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solverSetup2Source, "SetDeterminismSortDataBodyB", &pErrNum, solverSetup2Prog,additionalMacros );
+ m_data->m_setDeterminismSortDataBodyBKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverSetup2Source, "SetDeterminismSortDataBodyB", &pErrNum, solverSetup2Prog, additionalMacros);
b3Assert(m_data->m_setDeterminismSortDataBodyBKernel);
- m_data->m_setDeterminismSortDataChildShapeAKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solverSetup2Source, "SetDeterminismSortDataChildShapeA", &pErrNum, solverSetup2Prog,additionalMacros );
+ m_data->m_setDeterminismSortDataChildShapeAKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverSetup2Source, "SetDeterminismSortDataChildShapeA", &pErrNum, solverSetup2Prog, additionalMacros);
b3Assert(m_data->m_setDeterminismSortDataChildShapeAKernel);
- m_data->m_setDeterminismSortDataChildShapeBKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solverSetup2Source, "SetDeterminismSortDataChildShapeB", &pErrNum, solverSetup2Prog,additionalMacros );
+ m_data->m_setDeterminismSortDataChildShapeBKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverSetup2Source, "SetDeterminismSortDataChildShapeB", &pErrNum, solverSetup2Prog, additionalMacros);
b3Assert(m_data->m_setDeterminismSortDataChildShapeBKernel);
-
- m_data->m_reorderContactKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solverSetup2Source, "ReorderContactKernel", &pErrNum, solverSetup2Prog,additionalMacros );
+ m_data->m_reorderContactKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverSetup2Source, "ReorderContactKernel", &pErrNum, solverSetup2Prog, additionalMacros);
b3Assert(m_data->m_reorderContactKernel);
-
- m_data->m_copyConstraintKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solverSetup2Source, "CopyConstraintKernel", &pErrNum, solverSetup2Prog,additionalMacros );
+ m_data->m_copyConstraintKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverSetup2Source, "CopyConstraintKernel", &pErrNum, solverSetup2Prog, additionalMacros);
b3Assert(m_data->m_copyConstraintKernel);
-
}
{
- cl_program batchingProg = b3OpenCLUtils::compileCLProgramFromString( ctx, device, batchKernelSource, &pErrNum,additionalMacros, B3_BATCHING_PATH);
+ cl_program batchingProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, batchKernelSource, &pErrNum, additionalMacros, B3_BATCHING_PATH);
b3Assert(batchingProg);
-
- m_data->m_batchingKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, batchKernelSource, "CreateBatches", &pErrNum, batchingProg,additionalMacros );
+
+ m_data->m_batchingKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, batchKernelSource, "CreateBatches", &pErrNum, batchingProg, additionalMacros);
b3Assert(m_data->m_batchingKernel);
}
-
+
{
- cl_program batchingNewProg = b3OpenCLUtils::compileCLProgramFromString( ctx, device, batchKernelNewSource, &pErrNum,additionalMacros, B3_BATCHING_NEW_PATH);
+ cl_program batchingNewProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, batchKernelNewSource, &pErrNum, additionalMacros, B3_BATCHING_NEW_PATH);
b3Assert(batchingNewProg);
-
- m_data->m_batchingKernelNew = b3OpenCLUtils::compileCLKernelFromString( ctx, device, batchKernelNewSource, "CreateBatchesNew", &pErrNum, batchingNewProg,additionalMacros );
+
+ m_data->m_batchingKernelNew = b3OpenCLUtils::compileCLKernelFromString(ctx, device, batchKernelNewSource, "CreateBatchesNew", &pErrNum, batchingNewProg, additionalMacros);
b3Assert(m_data->m_batchingKernelNew);
}
-
-
-
-
-
-
-
}
b3GpuPgsContactSolver::~b3GpuPgsContactSolver()
@@ -242,8 +211,6 @@ b3GpuPgsContactSolver::~b3GpuPgsContactSolver()
delete m_data->m_pBufContactOutGPUCopy;
delete m_data->m_contactKeyValues;
-
-
delete m_data->m_contactCGPU;
delete m_data->m_numConstraints;
delete m_data->m_offsets;
@@ -259,29 +226,25 @@ b3GpuPgsContactSolver::~b3GpuPgsContactSolver()
clReleaseKernel(m_data->m_batchingKernelNew);
clReleaseKernel(m_data->m_solveSingleContactKernel);
clReleaseKernel(m_data->m_solveSingleFrictionKernel);
- clReleaseKernel( m_data->m_solveContactKernel);
- clReleaseKernel( m_data->m_solveFrictionKernel);
+ clReleaseKernel(m_data->m_solveContactKernel);
+ clReleaseKernel(m_data->m_solveFrictionKernel);
- clReleaseKernel( m_data->m_contactToConstraintKernel);
- clReleaseKernel( m_data->m_setSortDataKernel);
- clReleaseKernel( m_data->m_reorderContactKernel);
- clReleaseKernel( m_data->m_copyConstraintKernel);
+ clReleaseKernel(m_data->m_contactToConstraintKernel);
+ clReleaseKernel(m_data->m_setSortDataKernel);
+ clReleaseKernel(m_data->m_reorderContactKernel);
+ clReleaseKernel(m_data->m_copyConstraintKernel);
clReleaseKernel(m_data->m_setDeterminismSortDataBodyAKernel);
clReleaseKernel(m_data->m_setDeterminismSortDataBodyBKernel);
clReleaseKernel(m_data->m_setDeterminismSortDataChildShapeAKernel);
clReleaseKernel(m_data->m_setDeterminismSortDataChildShapeBKernel);
-
-
delete m_data;
}
-
-
struct b3ConstraintCfg
{
- b3ConstraintCfg( float dt = 0.f ): m_positionDrift( 0.005f ), m_positionConstraintCoeff( 0.2f ), m_dt(dt), m_staticIdx(0) {}
+ b3ConstraintCfg(float dt = 0.f) : m_positionDrift(0.005f), m_positionConstraintCoeff(0.2f), m_dt(dt), m_staticIdx(0) {}
float m_positionDrift;
float m_positionConstraintCoeff;
@@ -291,354 +254,306 @@ struct b3ConstraintCfg
int m_staticIdx;
};
-
-
-void b3GpuPgsContactSolver::solveContactConstraintBatchSizes( const b3OpenCLArray<b3RigidBodyData>* bodyBuf, const b3OpenCLArray<b3InertiaData>* shapeBuf,
- b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n ,int maxNumBatches,int numIterations, const b3AlignedObjectArray<int>* batchSizes)//const b3OpenCLArray<int>* gpuBatchSizes)
+void b3GpuPgsContactSolver::solveContactConstraintBatchSizes(const b3OpenCLArray<b3RigidBodyData>* bodyBuf, const b3OpenCLArray<b3InertiaData>* shapeBuf,
+ b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n, int maxNumBatches, int numIterations, const b3AlignedObjectArray<int>* batchSizes) //const b3OpenCLArray<int>* gpuBatchSizes)
{
B3_PROFILE("solveContactConstraintBatchSizes");
- int numBatches = batchSizes->size()/B3_MAX_NUM_BATCHES;
- for(int iter=0; iter<numIterations; iter++)
+ int numBatches = batchSizes->size() / B3_MAX_NUM_BATCHES;
+ for (int iter = 0; iter < numIterations; iter++)
{
-
- for (int cellId=0;cellId<numBatches;cellId++)
+ for (int cellId = 0; cellId < numBatches; cellId++)
{
int offset = 0;
- for (int ii=0;ii<B3_MAX_NUM_BATCHES;ii++)
+ for (int ii = 0; ii < B3_MAX_NUM_BATCHES; ii++)
{
- int numInBatch = batchSizes->at(cellId*B3_MAX_NUM_BATCHES+ii);
+ int numInBatch = batchSizes->at(cellId * B3_MAX_NUM_BATCHES + ii);
if (!numInBatch)
break;
{
- b3LauncherCL launcher( m_data->m_queue, m_data->m_solveSingleContactKernel,"m_solveSingleContactKernel" );
- launcher.setBuffer(bodyBuf->getBufferCL() );
- launcher.setBuffer(shapeBuf->getBufferCL() );
- launcher.setBuffer( constraint->getBufferCL() );
+ b3LauncherCL launcher(m_data->m_queue, m_data->m_solveSingleContactKernel, "m_solveSingleContactKernel");
+ launcher.setBuffer(bodyBuf->getBufferCL());
+ launcher.setBuffer(shapeBuf->getBufferCL());
+ launcher.setBuffer(constraint->getBufferCL());
launcher.setConst(cellId);
launcher.setConst(offset);
launcher.setConst(numInBatch);
launcher.launch1D(numInBatch);
- offset+=numInBatch;
+ offset += numInBatch;
}
}
}
}
-
- for(int iter=0; iter<numIterations; iter++)
+ for (int iter = 0; iter < numIterations; iter++)
{
- for (int cellId=0;cellId<numBatches;cellId++)
+ for (int cellId = 0; cellId < numBatches; cellId++)
{
int offset = 0;
- for (int ii=0;ii<B3_MAX_NUM_BATCHES;ii++)
+ for (int ii = 0; ii < B3_MAX_NUM_BATCHES; ii++)
{
- int numInBatch = batchSizes->at(cellId*B3_MAX_NUM_BATCHES+ii);
+ int numInBatch = batchSizes->at(cellId * B3_MAX_NUM_BATCHES + ii);
if (!numInBatch)
break;
{
- b3LauncherCL launcher( m_data->m_queue, m_data->m_solveSingleFrictionKernel,"m_solveSingleFrictionKernel" );
- launcher.setBuffer(bodyBuf->getBufferCL() );
- launcher.setBuffer(shapeBuf->getBufferCL() );
- launcher.setBuffer( constraint->getBufferCL() );
+ b3LauncherCL launcher(m_data->m_queue, m_data->m_solveSingleFrictionKernel, "m_solveSingleFrictionKernel");
+ launcher.setBuffer(bodyBuf->getBufferCL());
+ launcher.setBuffer(shapeBuf->getBufferCL());
+ launcher.setBuffer(constraint->getBufferCL());
launcher.setConst(cellId);
launcher.setConst(offset);
launcher.setConst(numInBatch);
launcher.launch1D(numInBatch);
- offset+=numInBatch;
+ offset += numInBatch;
}
}
}
}
}
-void b3GpuPgsContactSolver::solveContactConstraint( const b3OpenCLArray<b3RigidBodyData>* bodyBuf, const b3OpenCLArray<b3InertiaData>* shapeBuf,
- b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n ,int maxNumBatches,int numIterations, const b3AlignedObjectArray<int>* batchSizes)//,const b3OpenCLArray<int>* gpuBatchSizes)
+void b3GpuPgsContactSolver::solveContactConstraint(const b3OpenCLArray<b3RigidBodyData>* bodyBuf, const b3OpenCLArray<b3InertiaData>* shapeBuf,
+ b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n, int maxNumBatches, int numIterations, const b3AlignedObjectArray<int>* batchSizes) //,const b3OpenCLArray<int>* gpuBatchSizes)
{
-
//sort the contacts
-
- b3Int4 cdata = b3MakeInt4( n, 0, 0, 0 );
+ b3Int4 cdata = b3MakeInt4(n, 0, 0, 0);
{
-
const int nn = B3_SOLVER_N_CELLS;
cdata.x = 0;
- cdata.y = maxNumBatches;//250;
-
+ cdata.y = maxNumBatches; //250;
- int numWorkItems = 64*nn/B3_SOLVER_N_BATCHES;
+ int numWorkItems = 64 * nn / B3_SOLVER_N_BATCHES;
#ifdef DEBUG_ME
- SolverDebugInfo* debugInfo = new SolverDebugInfo[numWorkItems];
- adl::b3OpenCLArray<SolverDebugInfo> gpuDebugInfo(data->m_device,numWorkItems);
+ SolverDebugInfo* debugInfo = new SolverDebugInfo[numWorkItems];
+ adl::b3OpenCLArray<SolverDebugInfo> gpuDebugInfo(data->m_device, numWorkItems);
#endif
-
-
{
-
B3_PROFILE("m_batchSolveKernel iterations");
- for(int iter=0; iter<numIterations; iter++)
+ for (int iter = 0; iter < numIterations; iter++)
{
- for(int ib=0; ib<B3_SOLVER_N_BATCHES; ib++)
+ for (int ib = 0; ib < B3_SOLVER_N_BATCHES; ib++)
{
#ifdef DEBUG_ME
- memset(debugInfo,0,sizeof(SolverDebugInfo)*numWorkItems);
- gpuDebugInfo.write(debugInfo,numWorkItems);
+ memset(debugInfo, 0, sizeof(SolverDebugInfo) * numWorkItems);
+ gpuDebugInfo.write(debugInfo, numWorkItems);
#endif
-
cdata.z = ib;
-
- b3LauncherCL launcher( m_data->m_queue, m_data->m_solveContactKernel,"m_solveContactKernel" );
+ b3LauncherCL launcher(m_data->m_queue, m_data->m_solveContactKernel, "m_solveContactKernel");
#if 1
-
- b3BufferInfoCL bInfo[] = {
-
- b3BufferInfoCL( bodyBuf->getBufferCL() ),
- b3BufferInfoCL( shapeBuf->getBufferCL() ),
- b3BufferInfoCL( constraint->getBufferCL() ),
- b3BufferInfoCL( m_data->m_solverGPU->m_numConstraints->getBufferCL() ),
- b3BufferInfoCL( m_data->m_solverGPU->m_offsets->getBufferCL() )
+
+ b3BufferInfoCL bInfo[] = {
+
+ b3BufferInfoCL(bodyBuf->getBufferCL()),
+ b3BufferInfoCL(shapeBuf->getBufferCL()),
+ b3BufferInfoCL(constraint->getBufferCL()),
+ b3BufferInfoCL(m_data->m_solverGPU->m_numConstraints->getBufferCL()),
+ b3BufferInfoCL(m_data->m_solverGPU->m_offsets->getBufferCL())
#ifdef DEBUG_ME
- , b3BufferInfoCL(&gpuDebugInfo)
+ ,
+ b3BufferInfoCL(&gpuDebugInfo)
#endif
- };
-
-
+ };
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setBuffer( m_data->m_solverGPU->m_batchSizes.getBufferCL());
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setBuffer(m_data->m_solverGPU->m_batchSizes.getBufferCL());
//launcher.setConst( cdata.x );
- launcher.setConst( cdata.y );
- launcher.setConst( cdata.z );
+ launcher.setConst(cdata.y);
+ launcher.setConst(cdata.z);
b3Int4 nSplit;
nSplit.x = B3_SOLVER_N_SPLIT_X;
nSplit.y = B3_SOLVER_N_SPLIT_Y;
nSplit.z = B3_SOLVER_N_SPLIT_Z;
- launcher.setConst( nSplit );
- launcher.launch1D( numWorkItems, 64 );
+ launcher.setConst(nSplit);
+ launcher.launch1D(numWorkItems, 64);
-
#else
- const char* fileName = "m_batchSolveKernel.bin";
- FILE* f = fopen(fileName,"rb");
- if (f)
- {
- int sizeInBytes=0;
- if (fseek(f, 0, SEEK_END) || (sizeInBytes = ftell(f)) == EOF || fseek(f, 0, SEEK_SET))
- {
- printf("error, cannot get file size\n");
- exit(0);
- }
-
- unsigned char* buf = (unsigned char*) malloc(sizeInBytes);
- fread(buf,sizeInBytes,1,f);
- int serializedBytes = launcher.deserializeArgs(buf, sizeInBytes,m_context);
- int num = *(int*)&buf[serializedBytes];
-
- launcher.launch1D( num);
-
- //this clFinish is for testing on errors
- clFinish(m_queue);
- }
+ const char* fileName = "m_batchSolveKernel.bin";
+ FILE* f = fopen(fileName, "rb");
+ if (f)
+ {
+ int sizeInBytes = 0;
+ if (fseek(f, 0, SEEK_END) || (sizeInBytes = ftell(f)) == EOF || fseek(f, 0, SEEK_SET))
+ {
+ printf("error, cannot get file size\n");
+ exit(0);
+ }
+
+ unsigned char* buf = (unsigned char*)malloc(sizeInBytes);
+ fread(buf, sizeInBytes, 1, f);
+ int serializedBytes = launcher.deserializeArgs(buf, sizeInBytes, m_context);
+ int num = *(int*)&buf[serializedBytes];
+
+ launcher.launch1D(num);
+
+ //this clFinish is for testing on errors
+ clFinish(m_queue);
+ }
#endif
-
#ifdef DEBUG_ME
clFinish(m_queue);
- gpuDebugInfo.read(debugInfo,numWorkItems);
+ gpuDebugInfo.read(debugInfo, numWorkItems);
clFinish(m_queue);
- for (int i=0;i<numWorkItems;i++)
+ for (int i = 0; i < numWorkItems; i++)
{
- if (debugInfo[i].m_valInt2>0)
+ if (debugInfo[i].m_valInt2 > 0)
{
- printf("debugInfo[i].m_valInt2 = %d\n",i,debugInfo[i].m_valInt2);
+ printf("debugInfo[i].m_valInt2 = %d\n", i, debugInfo[i].m_valInt2);
}
- if (debugInfo[i].m_valInt3>0)
+ if (debugInfo[i].m_valInt3 > 0)
{
- printf("debugInfo[i].m_valInt3 = %d\n",i,debugInfo[i].m_valInt3);
+ printf("debugInfo[i].m_valInt3 = %d\n", i, debugInfo[i].m_valInt3);
}
}
-#endif //DEBUG_ME
-
-
+#endif //DEBUG_ME
}
}
-
- clFinish(m_data->m_queue);
-
+ clFinish(m_data->m_queue);
}
cdata.x = 1;
- bool applyFriction=true;
+ bool applyFriction = true;
if (applyFriction)
- {
+ {
B3_PROFILE("m_batchSolveKernel iterations2");
- for(int iter=0; iter<numIterations; iter++)
+ for (int iter = 0; iter < numIterations; iter++)
{
- for(int ib=0; ib<B3_SOLVER_N_BATCHES; ib++)
+ for (int ib = 0; ib < B3_SOLVER_N_BATCHES; ib++)
{
cdata.z = ib;
-
-
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL( bodyBuf->getBufferCL() ),
- b3BufferInfoCL( shapeBuf->getBufferCL() ),
- b3BufferInfoCL( constraint->getBufferCL() ),
- b3BufferInfoCL( m_data->m_solverGPU->m_numConstraints->getBufferCL() ),
- b3BufferInfoCL( m_data->m_solverGPU->m_offsets->getBufferCL() )
+
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL(bodyBuf->getBufferCL()),
+ b3BufferInfoCL(shapeBuf->getBufferCL()),
+ b3BufferInfoCL(constraint->getBufferCL()),
+ b3BufferInfoCL(m_data->m_solverGPU->m_numConstraints->getBufferCL()),
+ b3BufferInfoCL(m_data->m_solverGPU->m_offsets->getBufferCL())
#ifdef DEBUG_ME
- ,b3BufferInfoCL(&gpuDebugInfo)
-#endif //DEBUG_ME
+ ,
+ b3BufferInfoCL(&gpuDebugInfo)
+#endif //DEBUG_ME
};
- b3LauncherCL launcher( m_data->m_queue, m_data->m_solveFrictionKernel,"m_solveFrictionKernel" );
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setBuffer( m_data->m_solverGPU->m_batchSizes.getBufferCL());
+ b3LauncherCL launcher(m_data->m_queue, m_data->m_solveFrictionKernel, "m_solveFrictionKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setBuffer(m_data->m_solverGPU->m_batchSizes.getBufferCL());
//launcher.setConst( cdata.x );
- launcher.setConst( cdata.y );
- launcher.setConst( cdata.z );
+ launcher.setConst(cdata.y);
+ launcher.setConst(cdata.z);
- b3Int4 nSplit;
+ b3Int4 nSplit;
nSplit.x = B3_SOLVER_N_SPLIT_X;
nSplit.y = B3_SOLVER_N_SPLIT_Y;
nSplit.z = B3_SOLVER_N_SPLIT_Z;
- launcher.setConst( nSplit );
-
- launcher.launch1D( 64*nn/B3_SOLVER_N_BATCHES, 64 );
+ launcher.setConst(nSplit);
+
+ launcher.launch1D(64 * nn / B3_SOLVER_N_BATCHES, 64);
}
}
clFinish(m_data->m_queue);
-
}
#ifdef DEBUG_ME
delete[] debugInfo;
-#endif //DEBUG_ME
+#endif //DEBUG_ME
}
-
-
}
-
-
-
-
-
-
-
-
-
-
-static bool sortfnc(const b3SortData& a,const b3SortData& b)
+static bool sortfnc(const b3SortData& a, const b3SortData& b)
{
- return (a.m_key<b.m_key);
+ return (a.m_key < b.m_key);
}
static bool b3ContactCmp(const b3Contact4& p, const b3Contact4& q)
{
- return ((p.m_bodyAPtrAndSignBit<q.m_bodyAPtrAndSignBit) ||
- ((p.m_bodyAPtrAndSignBit==q.m_bodyAPtrAndSignBit) && (p.m_bodyBPtrAndSignBit<q.m_bodyBPtrAndSignBit)) ||
- ((p.m_bodyAPtrAndSignBit==q.m_bodyAPtrAndSignBit) && (p.m_bodyBPtrAndSignBit==q.m_bodyBPtrAndSignBit) && p.m_childIndexA<q.m_childIndexA ) ||
- ((p.m_bodyAPtrAndSignBit==q.m_bodyAPtrAndSignBit) && (p.m_bodyBPtrAndSignBit==q.m_bodyBPtrAndSignBit) && p.m_childIndexA<q.m_childIndexA ) ||
- ((p.m_bodyAPtrAndSignBit==q.m_bodyAPtrAndSignBit) && (p.m_bodyBPtrAndSignBit==q.m_bodyBPtrAndSignBit) && p.m_childIndexA==q.m_childIndexA && p.m_childIndexB<q.m_childIndexB)
- );
+ return ((p.m_bodyAPtrAndSignBit < q.m_bodyAPtrAndSignBit) ||
+ ((p.m_bodyAPtrAndSignBit == q.m_bodyAPtrAndSignBit) && (p.m_bodyBPtrAndSignBit < q.m_bodyBPtrAndSignBit)) ||
+ ((p.m_bodyAPtrAndSignBit == q.m_bodyAPtrAndSignBit) && (p.m_bodyBPtrAndSignBit == q.m_bodyBPtrAndSignBit) && p.m_childIndexA < q.m_childIndexA) ||
+ ((p.m_bodyAPtrAndSignBit == q.m_bodyAPtrAndSignBit) && (p.m_bodyBPtrAndSignBit == q.m_bodyBPtrAndSignBit) && p.m_childIndexA < q.m_childIndexA) ||
+ ((p.m_bodyAPtrAndSignBit == q.m_bodyAPtrAndSignBit) && (p.m_bodyBPtrAndSignBit == q.m_bodyBPtrAndSignBit) && p.m_childIndexA == q.m_childIndexA && p.m_childIndexB < q.m_childIndexB));
}
-
-
-
-
-
-
-
-
-
-
#define USE_SPATIAL_BATCHING 1
#define USE_4x4_GRID 1
#ifndef USE_SPATIAL_BATCHING
-static const int gridTable4x4[] =
-{
- 0,1,17,16,
- 1,2,18,19,
- 17,18,32,3,
- 16,19,3,34
-};
-static const int gridTable8x8[] =
-{
- 0, 2, 3, 16, 17, 18, 19, 1,
- 66, 64, 80, 67, 82, 81, 65, 83,
- 131,144,128,130,147,129,145,146,
- 208,195,194,192,193,211,210,209,
- 21, 22, 23, 5, 4, 6, 7, 20,
- 86, 85, 69, 87, 70, 68, 84, 71,
- 151,133,149,150,135,148,132,134,
- 197,27,214,213,212,199,198,196
-
-};
+static const int gridTable4x4[] =
+ {
+ 0, 1, 17, 16,
+ 1, 2, 18, 19,
+ 17, 18, 32, 3,
+ 16, 19, 3, 34};
+static const int gridTable8x8[] =
+ {
+ 0, 2, 3, 16, 17, 18, 19, 1,
+ 66, 64, 80, 67, 82, 81, 65, 83,
+ 131, 144, 128, 130, 147, 129, 145, 146,
+ 208, 195, 194, 192, 193, 211, 210, 209,
+ 21, 22, 23, 5, 4, 6, 7, 20,
+ 86, 85, 69, 87, 70, 68, 84, 71,
+ 151, 133, 149, 150, 135, 148, 132, 134,
+ 197, 27, 214, 213, 212, 199, 198, 196
+};
#endif
-
-void SetSortDataCPU(b3Contact4* gContact, b3RigidBodyData* gBodies, b3SortData* gSortDataOut, int nContacts,float scale,const b3Int4& nSplit,int staticIdx)
+void SetSortDataCPU(b3Contact4* gContact, b3RigidBodyData* gBodies, b3SortData* gSortDataOut, int nContacts, float scale, const b3Int4& nSplit, int staticIdx)
{
- for (int gIdx=0;gIdx<nContacts;gIdx++)
+ for (int gIdx = 0; gIdx < nContacts; gIdx++)
{
- if( gIdx < nContacts )
+ if (gIdx < nContacts)
{
- int aPtrAndSignBit = gContact[gIdx].m_bodyAPtrAndSignBit;
- int bPtrAndSignBit = gContact[gIdx].m_bodyBPtrAndSignBit;
+ int aPtrAndSignBit = gContact[gIdx].m_bodyAPtrAndSignBit;
+ int bPtrAndSignBit = gContact[gIdx].m_bodyBPtrAndSignBit;
- int aIdx = abs(aPtrAndSignBit );
+ int aIdx = abs(aPtrAndSignBit);
int bIdx = abs(bPtrAndSignBit);
- bool aStatic = (aPtrAndSignBit<0) ||(aPtrAndSignBit==staticIdx);
+ bool aStatic = (aPtrAndSignBit < 0) || (aPtrAndSignBit == staticIdx);
- #if USE_SPATIAL_BATCHING
- int idx = (aStatic)? bIdx: aIdx;
+#if USE_SPATIAL_BATCHING
+ int idx = (aStatic) ? bIdx : aIdx;
b3Vector3 p = gBodies[idx].m_pos;
- int xIdx = (int)((p.x-((p.x<0.f)?1.f:0.f))*scale) & (nSplit.x-1);
- int yIdx = (int)((p.y-((p.y<0.f)?1.f:0.f))*scale) & (nSplit.y-1);
- int zIdx = (int)((p.z-((p.z<0.f)?1.f:0.f))*scale) & (nSplit.z-1);
-
- int newIndex = (xIdx+yIdx*nSplit.x+zIdx*nSplit.x*nSplit.y);
-
- #else//USE_SPATIAL_BATCHING
- bool bStatic = (bPtrAndSignBit<0) ||(bPtrAndSignBit==staticIdx);
-
- #if USE_4x4_GRID
- int aa = aIdx&3;
- int bb = bIdx&3;
+ int xIdx = (int)((p.x - ((p.x < 0.f) ? 1.f : 0.f)) * scale) & (nSplit.x - 1);
+ int yIdx = (int)((p.y - ((p.y < 0.f) ? 1.f : 0.f)) * scale) & (nSplit.y - 1);
+ int zIdx = (int)((p.z - ((p.z < 0.f) ? 1.f : 0.f)) * scale) & (nSplit.z - 1);
+
+ int newIndex = (xIdx + yIdx * nSplit.x + zIdx * nSplit.x * nSplit.y);
+
+#else //USE_SPATIAL_BATCHING
+ bool bStatic = (bPtrAndSignBit < 0) || (bPtrAndSignBit == staticIdx);
+
+#if USE_4x4_GRID
+ int aa = aIdx & 3;
+ int bb = bIdx & 3;
if (aStatic)
aa = bb;
if (bStatic)
bb = aa;
- int gridIndex = aa + bb*4;
+ int gridIndex = aa + bb * 4;
int newIndex = gridTable4x4[gridIndex];
- #else//USE_4x4_GRID
- int aa = aIdx&7;
- int bb = bIdx&7;
+#else //USE_4x4_GRID
+ int aa = aIdx & 7;
+ int bb = bIdx & 7;
if (aStatic)
aa = bb;
if (bStatic)
bb = aa;
- int gridIndex = aa + bb*8;
+ int gridIndex = aa + bb * 8;
int newIndex = gridTable8x8[gridIndex];
- #endif//USE_4x4_GRID
- #endif//USE_SPATIAL_BATCHING
-
+#endif //USE_4x4_GRID
+#endif //USE_SPATIAL_BATCHING
gSortDataOut[gIdx].x = newIndex;
gSortDataOut[gIdx].y = gIdx;
@@ -650,17 +565,12 @@ void SetSortDataCPU(b3Contact4* gContact, b3RigidBodyData* gBodies, b3SortData*
}
}
-
-
-
-
-
void b3GpuPgsContactSolver::solveContacts(int numBodies, cl_mem bodyBuf, cl_mem inertiaBuf, int numContacts, cl_mem contactBuf, const b3Config& config, int static0Index)
{
B3_PROFILE("solveContacts");
- m_data->m_bodyBufferGPU->setFromOpenCLBuffer(bodyBuf,numBodies);
- m_data->m_inertiaBufferGPU->setFromOpenCLBuffer(inertiaBuf,numBodies);
- m_data->m_pBufContactOutGPU->setFromOpenCLBuffer(contactBuf,numContacts);
+ m_data->m_bodyBufferGPU->setFromOpenCLBuffer(bodyBuf, numBodies);
+ m_data->m_inertiaBufferGPU->setFromOpenCLBuffer(inertiaBuf, numBodies);
+ m_data->m_pBufContactOutGPU->setFromOpenCLBuffer(contactBuf, numContacts);
if (optionalSortContactsDeterminism)
{
@@ -671,61 +581,61 @@ void b3GpuPgsContactSolver::solveContacts(int numBodies, cl_mem bodyBuf, cl_mem
m_data->m_pBufContactOutGPUCopy->resize(numContacts);
m_data->m_contactKeyValues->resize(numContacts);
- m_data->m_pBufContactOutGPU->copyToCL(m_data->m_pBufContactOutGPUCopy->getBufferCL(),numContacts,0,0);
+ m_data->m_pBufContactOutGPU->copyToCL(m_data->m_pBufContactOutGPUCopy->getBufferCL(), numContacts, 0, 0);
{
- b3LauncherCL launcher(m_data->m_queue, m_data->m_setDeterminismSortDataChildShapeBKernel,"m_setDeterminismSortDataChildShapeBKernel");
+ b3LauncherCL launcher(m_data->m_queue, m_data->m_setDeterminismSortDataChildShapeBKernel, "m_setDeterminismSortDataChildShapeBKernel");
launcher.setBuffer(m_data->m_pBufContactOutGPUCopy->getBufferCL());
launcher.setBuffer(m_data->m_contactKeyValues->getBufferCL());
launcher.setConst(numContacts);
- launcher.launch1D( numContacts, 64 );
+ launcher.launch1D(numContacts, 64);
}
m_data->m_solverGPU->m_sort32->execute(*m_data->m_contactKeyValues);
{
- b3LauncherCL launcher(m_data->m_queue, m_data->m_setDeterminismSortDataChildShapeAKernel,"m_setDeterminismSortDataChildShapeAKernel");
+ b3LauncherCL launcher(m_data->m_queue, m_data->m_setDeterminismSortDataChildShapeAKernel, "m_setDeterminismSortDataChildShapeAKernel");
launcher.setBuffer(m_data->m_pBufContactOutGPUCopy->getBufferCL());
launcher.setBuffer(m_data->m_contactKeyValues->getBufferCL());
launcher.setConst(numContacts);
- launcher.launch1D( numContacts, 64 );
+ launcher.launch1D(numContacts, 64);
}
m_data->m_solverGPU->m_sort32->execute(*m_data->m_contactKeyValues);
{
- b3LauncherCL launcher(m_data->m_queue, m_data->m_setDeterminismSortDataBodyBKernel,"m_setDeterminismSortDataBodyBKernel");
+ b3LauncherCL launcher(m_data->m_queue, m_data->m_setDeterminismSortDataBodyBKernel, "m_setDeterminismSortDataBodyBKernel");
launcher.setBuffer(m_data->m_pBufContactOutGPUCopy->getBufferCL());
launcher.setBuffer(m_data->m_contactKeyValues->getBufferCL());
launcher.setConst(numContacts);
- launcher.launch1D( numContacts, 64 );
+ launcher.launch1D(numContacts, 64);
}
-
+
m_data->m_solverGPU->m_sort32->execute(*m_data->m_contactKeyValues);
-
+
{
- b3LauncherCL launcher(m_data->m_queue, m_data->m_setDeterminismSortDataBodyAKernel,"m_setDeterminismSortDataBodyAKernel");
+ b3LauncherCL launcher(m_data->m_queue, m_data->m_setDeterminismSortDataBodyAKernel, "m_setDeterminismSortDataBodyAKernel");
launcher.setBuffer(m_data->m_pBufContactOutGPUCopy->getBufferCL());
launcher.setBuffer(m_data->m_contactKeyValues->getBufferCL());
launcher.setConst(numContacts);
- launcher.launch1D( numContacts, 64 );
+ launcher.launch1D(numContacts, 64);
}
m_data->m_solverGPU->m_sort32->execute(*m_data->m_contactKeyValues);
{
B3_PROFILE("gpu reorderContactKernel (determinism)");
-
+
b3Int4 cdata;
cdata.x = numContacts;
-
+
//b3BufferInfoCL bInfo[] = { b3BufferInfoCL( m_data->m_pBufContactOutGPU->getBufferCL() ), b3BufferInfoCL( m_data->m_solverGPU->m_contactBuffer2->getBufferCL())
// , b3BufferInfoCL( m_data->m_solverGPU->m_sortDataBuffer->getBufferCL()) };
- b3LauncherCL launcher(m_data->m_queue,m_data->m_solverGPU->m_reorderContactKernel,"m_reorderContactKernel");
+ b3LauncherCL launcher(m_data->m_queue, m_data->m_solverGPU->m_reorderContactKernel, "m_reorderContactKernel");
launcher.setBuffer(m_data->m_pBufContactOutGPUCopy->getBufferCL());
launcher.setBuffer(m_data->m_pBufContactOutGPU->getBufferCL());
launcher.setBuffer(m_data->m_contactKeyValues->getBufferCL());
- launcher.setConst( cdata );
- launcher.launch1D( numContacts, 64 );
- }
-
- } else
+ launcher.setConst(cdata);
+ launcher.launch1D(numContacts, 64);
+ }
+ }
+ else
{
B3_PROFILE("CPU Sort contact constraints (determinism)");
b3AlignedObjectArray<b3Contact4> cpuConstraints;
@@ -735,96 +645,80 @@ void b3GpuPgsContactSolver::solveContacts(int numBodies, cl_mem bodyBuf, cl_mem
{
cpuConstraints.quickSort(b3ContactCmp);
- for (int i=0;i<cpuConstraints.size();i++)
+ for (int i = 0; i < cpuConstraints.size(); i++)
{
cpuConstraints[i].m_batchIdx = i;
}
}
m_data->m_pBufContactOutGPU->copyFromHost(cpuConstraints);
- if (m_debugOutput==100)
+ if (m_debugOutput == 100)
{
- for (int i=0;i<cpuConstraints.size();i++)
+ for (int i = 0; i < cpuConstraints.size(); i++)
{
- printf("c[%d].m_bodyA = %d, m_bodyB = %d, batchId = %d\n",i,cpuConstraints[i].m_bodyAPtrAndSignBit,cpuConstraints[i].m_bodyBPtrAndSignBit, cpuConstraints[i].m_batchIdx);
+ printf("c[%d].m_bodyA = %d, m_bodyB = %d, batchId = %d\n", i, cpuConstraints[i].m_bodyAPtrAndSignBit, cpuConstraints[i].m_bodyBPtrAndSignBit, cpuConstraints[i].m_batchIdx);
}
}
m_debugOutput++;
}
}
-
-
-
int nContactOut = m_data->m_pBufContactOutGPU->size();
bool useSolver = true;
-
-
- if (useSolver)
- {
- float dt=1./60.;
- b3ConstraintCfg csCfg( dt );
- csCfg.m_enableParallelSolve = true;
- csCfg.m_batchCellSize = 6;
- csCfg.m_staticIdx = static0Index;
-
-
- b3OpenCLArray<b3RigidBodyData>* bodyBuf = m_data->m_bodyBufferGPU;
-
- void* additionalData = 0;//m_data->m_frictionCGPU;
- const b3OpenCLArray<b3InertiaData>* shapeBuf = m_data->m_inertiaBufferGPU;
- b3OpenCLArray<b3GpuConstraint4>* contactConstraintOut = m_data->m_contactCGPU;
- int nContacts = nContactOut;
-
-
+
+ if (useSolver)
+ {
+ float dt = 1. / 60.;
+ b3ConstraintCfg csCfg(dt);
+ csCfg.m_enableParallelSolve = true;
+ csCfg.m_batchCellSize = 6;
+ csCfg.m_staticIdx = static0Index;
+
+ b3OpenCLArray<b3RigidBodyData>* bodyBuf = m_data->m_bodyBufferGPU;
+
+ void* additionalData = 0; //m_data->m_frictionCGPU;
+ const b3OpenCLArray<b3InertiaData>* shapeBuf = m_data->m_inertiaBufferGPU;
+ b3OpenCLArray<b3GpuConstraint4>* contactConstraintOut = m_data->m_contactCGPU;
+ int nContacts = nContactOut;
+
int maxNumBatches = 0;
-
+
if (!gUseLargeBatches)
- {
-
- if( m_data->m_solverGPU->m_contactBuffer2)
- {
- m_data->m_solverGPU->m_contactBuffer2->resize(nContacts);
- }
-
- if( m_data->m_solverGPU->m_contactBuffer2 == 0 )
- {
- m_data->m_solverGPU->m_contactBuffer2 = new b3OpenCLArray<b3Contact4>(m_data->m_context,m_data->m_queue, nContacts );
- m_data->m_solverGPU->m_contactBuffer2->resize(nContacts);
- }
-
- //clFinish(m_data->m_queue);
-
-
-
+ {
+ if (m_data->m_solverGPU->m_contactBuffer2)
{
- B3_PROFILE("batching");
- //@todo: just reserve it, without copy of original contact (unless we use warmstarting)
+ m_data->m_solverGPU->m_contactBuffer2->resize(nContacts);
+ }
+ if (m_data->m_solverGPU->m_contactBuffer2 == 0)
+ {
+ m_data->m_solverGPU->m_contactBuffer2 = new b3OpenCLArray<b3Contact4>(m_data->m_context, m_data->m_queue, nContacts);
+ m_data->m_solverGPU->m_contactBuffer2->resize(nContacts);
+ }
+ //clFinish(m_data->m_queue);
- //const b3OpenCLArray<b3RigidBodyData>* bodyNative = bodyBuf;
+ {
+ B3_PROFILE("batching");
+ //@todo: just reserve it, without copy of original contact (unless we use warmstarting)
+ //const b3OpenCLArray<b3RigidBodyData>* bodyNative = bodyBuf;
{
-
//b3OpenCLArray<b3RigidBodyData>* bodyNative = b3OpenCLArrayUtils::map<adl::TYPE_CL, true>( data->m_device, bodyBuf );
//b3OpenCLArray<b3Contact4>* contactNative = b3OpenCLArrayUtils::map<adl::TYPE_CL, true>( data->m_device, contactsIn );
- const int sortAlignment = 512; // todo. get this out of sort
- if( csCfg.m_enableParallelSolve )
+ const int sortAlignment = 512; // todo. get this out of sort
+ if (csCfg.m_enableParallelSolve)
{
-
-
- int sortSize = B3NEXTMULTIPLEOF( nContacts, sortAlignment );
+ int sortSize = B3NEXTMULTIPLEOF(nContacts, sortAlignment);
b3OpenCLArray<unsigned int>* countsNative = m_data->m_solverGPU->m_numConstraints;
b3OpenCLArray<unsigned int>* offsetsNative = m_data->m_solverGPU->m_offsets;
-
if (!gCpuSetSortData)
- { // 2. set cell idx
+ { // 2. set cell idx
B3_PROFILE("GPU set cell idx");
struct CB
{
@@ -834,29 +728,28 @@ void b3GpuPgsContactSolver::solveContacts(int numBodies, cl_mem bodyBuf, cl_mem
b3Int4 m_nSplit;
};
- b3Assert( sortSize%64 == 0 );
+ b3Assert(sortSize % 64 == 0);
CB cdata;
cdata.m_nContacts = nContacts;
cdata.m_staticIdx = csCfg.m_staticIdx;
- cdata.m_scale = 1.f/csCfg.m_batchCellSize;
+ cdata.m_scale = 1.f / csCfg.m_batchCellSize;
cdata.m_nSplit.x = B3_SOLVER_N_SPLIT_X;
cdata.m_nSplit.y = B3_SOLVER_N_SPLIT_Y;
cdata.m_nSplit.z = B3_SOLVER_N_SPLIT_Z;
m_data->m_solverGPU->m_sortDataBuffer->resize(nContacts);
-
- b3BufferInfoCL bInfo[] = { b3BufferInfoCL( m_data->m_pBufContactOutGPU->getBufferCL() ), b3BufferInfoCL( bodyBuf->getBufferCL()), b3BufferInfoCL( m_data->m_solverGPU->m_sortDataBuffer->getBufferCL()) };
- b3LauncherCL launcher(m_data->m_queue, m_data->m_solverGPU->m_setSortDataKernel,"m_setSortDataKernel" );
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst( cdata.m_nContacts );
- launcher.setConst( cdata.m_scale );
+ b3BufferInfoCL bInfo[] = {b3BufferInfoCL(m_data->m_pBufContactOutGPU->getBufferCL()), b3BufferInfoCL(bodyBuf->getBufferCL()), b3BufferInfoCL(m_data->m_solverGPU->m_sortDataBuffer->getBufferCL())};
+ b3LauncherCL launcher(m_data->m_queue, m_data->m_solverGPU->m_setSortDataKernel, "m_setSortDataKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setConst(cdata.m_nContacts);
+ launcher.setConst(cdata.m_scale);
launcher.setConst(cdata.m_nSplit);
launcher.setConst(cdata.m_staticIdx);
-
- launcher.launch1D( sortSize, 64 );
- } else
+ launcher.launch1D(sortSize, 64);
+ }
+ else
{
m_data->m_solverGPU->m_sortDataBuffer->resize(nContacts);
b3AlignedObjectArray<b3SortData> sortDataCPU;
@@ -866,22 +759,19 @@ void b3GpuPgsContactSolver::solveContacts(int numBodies, cl_mem bodyBuf, cl_mem
m_data->m_pBufContactOutGPU->copyToHost(contactCPU);
b3AlignedObjectArray<b3RigidBodyData> bodiesCPU;
bodyBuf->copyToHost(bodiesCPU);
- float scale = 1.f/csCfg.m_batchCellSize;
+ float scale = 1.f / csCfg.m_batchCellSize;
b3Int4 nSplit;
nSplit.x = B3_SOLVER_N_SPLIT_X;
nSplit.y = B3_SOLVER_N_SPLIT_Y;
nSplit.z = B3_SOLVER_N_SPLIT_Z;
- SetSortDataCPU(&contactCPU[0], &bodiesCPU[0], &sortDataCPU[0], nContacts,scale,nSplit,csCfg.m_staticIdx);
-
+ SetSortDataCPU(&contactCPU[0], &bodiesCPU[0], &sortDataCPU[0], nContacts, scale, nSplit, csCfg.m_staticIdx);
m_data->m_solverGPU->m_sortDataBuffer->copyFromHost(sortDataCPU);
}
-
-
if (!gCpuRadixSort)
- { // 3. sort by cell idx
+ { // 3. sort by cell idx
B3_PROFILE("gpuRadixSort");
//int n = B3_SOLVER_N_SPLIT*B3_SOLVER_N_SPLIT;
//int sortBit = 32;
@@ -891,10 +781,8 @@ void b3GpuPgsContactSolver::solveContacts(int numBodies, cl_mem bodyBuf, cl_mem
//adl::RadixSort32<adl::TYPE_CL>::execute( data->m_sort32, *data->m_sortDataBuffer, sortSize );
b3OpenCLArray<b3SortData>& keyValuesInOut = *(m_data->m_solverGPU->m_sortDataBuffer);
this->m_data->m_solverGPU->m_sort32->execute(keyValuesInOut);
-
-
-
- } else
+ }
+ else
{
b3OpenCLArray<b3SortData>& keyValuesInOut = *(m_data->m_solverGPU->m_sortDataBuffer);
b3AlignedObjectArray<b3SortData> hostValues;
@@ -903,7 +791,6 @@ void b3GpuPgsContactSolver::solveContacts(int numBodies, cl_mem bodyBuf, cl_mem
keyValuesInOut.copyFromHost(hostValues);
}
-
if (gUseScanHost)
{
// 4. find entries
@@ -914,13 +801,11 @@ void b3GpuPgsContactSolver::solveContacts(int numBodies, cl_mem bodyBuf, cl_mem
b3AlignedObjectArray<b3SortData> sortDataHost;
m_data->m_solverGPU->m_sortDataBuffer->copyToHost(sortDataHost);
-
//m_data->m_solverGPU->m_search->executeHost(*m_data->m_solverGPU->m_sortDataBuffer,nContacts,*countsNative,B3_SOLVER_N_CELLS,b3BoundSearchCL::COUNT);
- m_data->m_solverGPU->m_search->executeHost(sortDataHost,nContacts,countsHost,B3_SOLVER_N_CELLS,b3BoundSearchCL::COUNT);
+ m_data->m_solverGPU->m_search->executeHost(sortDataHost, nContacts, countsHost, B3_SOLVER_N_CELLS, b3BoundSearchCL::COUNT);
countsNative->copyFromHost(countsHost);
-
//adl::BoundSearch<adl::TYPE_CL>::execute( data->m_search, *data->m_sortDataBuffer, nContacts, *countsNative,
// B3_SOLVER_N_SPLIT*B3_SOLVER_N_SPLIT, adl::BoundSearchBase::COUNT );
@@ -929,24 +814,21 @@ void b3GpuPgsContactSolver::solveContacts(int numBodies, cl_mem bodyBuf, cl_mem
b3AlignedObjectArray<unsigned int> offsetsHost;
offsetsHost.resize(offsetsNative->size());
-
- m_data->m_solverGPU->m_scan->executeHost(countsHost,offsetsHost, B3_SOLVER_N_CELLS);//,&sum );
+ m_data->m_solverGPU->m_scan->executeHost(countsHost, offsetsHost, B3_SOLVER_N_CELLS); //,&sum );
offsetsNative->copyFromHost(offsetsHost);
//printf("sum = %d\n",sum);
- } else
+ }
+ else
{
// 4. find entries
B3_PROFILE("gpuBoundSearch");
- m_data->m_solverGPU->m_search->execute(*m_data->m_solverGPU->m_sortDataBuffer,nContacts,*countsNative,B3_SOLVER_N_CELLS,b3BoundSearchCL::COUNT);
- m_data->m_solverGPU->m_scan->execute(*countsNative,*offsetsNative, B3_SOLVER_N_CELLS);//,&sum );
- }
-
-
-
+ m_data->m_solverGPU->m_search->execute(*m_data->m_solverGPU->m_sortDataBuffer, nContacts, *countsNative, B3_SOLVER_N_CELLS, b3BoundSearchCL::COUNT);
+ m_data->m_solverGPU->m_scan->execute(*countsNative, *offsetsNative, B3_SOLVER_N_CELLS); //,&sum );
+ }
if (nContacts)
- { // 5. sort constraints by cellIdx
+ { // 5. sort constraints by cellIdx
if (gReorderContactsOnCpu)
{
B3_PROFILE("cpu m_reorderContactKernel");
@@ -956,7 +838,7 @@ void b3GpuPgsContactSolver::solveContacts(int numBodies, cl_mem bodyBuf, cl_mem
b3AlignedObjectArray<b3Contact4> outContacts;
m_data->m_pBufContactOutGPU->copyToHost(inContacts);
outContacts.resize(inContacts.size());
- for (int i=0;i<nContacts;i++)
+ for (int i = 0; i < nContacts; i++)
{
int srcIdx = sortDataHost[i].y;
outContacts[i] = inContacts[srcIdx];
@@ -974,30 +856,25 @@ void b3GpuPgsContactSolver::solveContacts(int numBodies, cl_mem bodyBuf, cl_mem
" }\n"
"}\n"
*/
- } else
+ }
+ else
{
B3_PROFILE("gpu m_reorderContactKernel");
b3Int4 cdata;
cdata.x = nContacts;
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL( m_data->m_pBufContactOutGPU->getBufferCL() ),
- b3BufferInfoCL( m_data->m_solverGPU->m_contactBuffer2->getBufferCL())
- , b3BufferInfoCL( m_data->m_solverGPU->m_sortDataBuffer->getBufferCL()) };
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL(m_data->m_pBufContactOutGPU->getBufferCL()),
+ b3BufferInfoCL(m_data->m_solverGPU->m_contactBuffer2->getBufferCL()), b3BufferInfoCL(m_data->m_solverGPU->m_sortDataBuffer->getBufferCL())};
- b3LauncherCL launcher(m_data->m_queue,m_data->m_solverGPU->m_reorderContactKernel,"m_reorderContactKernel");
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst( cdata );
- launcher.launch1D( nContacts, 64 );
+ b3LauncherCL launcher(m_data->m_queue, m_data->m_solverGPU->m_reorderContactKernel, "m_reorderContactKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setConst(cdata);
+ launcher.launch1D(nContacts, 64);
}
}
-
-
-
-
}
-
}
//clFinish(m_data->m_queue);
@@ -1008,48 +885,46 @@ void b3GpuPgsContactSolver::solveContacts(int numBodies, cl_mem bodyBuf, cl_mem
// printf(",,,\n");
// }
-
if (nContacts)
{
-
if (gUseCpuCopyConstraints)
{
- for (int i=0;i<nContacts;i++)
+ for (int i = 0; i < nContacts; i++)
{
m_data->m_pBufContactOutGPU->copyFromOpenCLArray(*m_data->m_solverGPU->m_contactBuffer2);
- // m_data->m_solverGPU->m_contactBuffer2->getBufferCL();
- // m_data->m_pBufContactOutGPU->getBufferCL()
+ // m_data->m_solverGPU->m_contactBuffer2->getBufferCL();
+ // m_data->m_pBufContactOutGPU->getBufferCL()
}
-
- } else
+ }
+ else
{
B3_PROFILE("gpu m_copyConstraintKernel");
- b3Int4 cdata; cdata.x = nContacts;
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL( m_data->m_solverGPU->m_contactBuffer2->getBufferCL() ),
- b3BufferInfoCL( m_data->m_pBufContactOutGPU->getBufferCL() )
- };
-
- b3LauncherCL launcher(m_data->m_queue, m_data->m_solverGPU->m_copyConstraintKernel,"m_copyConstraintKernel" );
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst( cdata );
- launcher.launch1D( nContacts, 64 );
+ b3Int4 cdata;
+ cdata.x = nContacts;
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL(m_data->m_solverGPU->m_contactBuffer2->getBufferCL()),
+ b3BufferInfoCL(m_data->m_pBufContactOutGPU->getBufferCL())};
+
+ b3LauncherCL launcher(m_data->m_queue, m_data->m_solverGPU->m_copyConstraintKernel, "m_copyConstraintKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+ launcher.setConst(cdata);
+ launcher.launch1D(nContacts, 64);
//we use the clFinish for proper benchmark/profile
clFinish(m_data->m_queue);
}
}
-
-// bool compareGPU = false;
+ // bool compareGPU = false;
if (nContacts)
{
if (!gCpuBatchContacts)
{
B3_PROFILE("gpu batchContacts");
- maxNumBatches = 250;//250;
- m_data->m_solverGPU->batchContacts( m_data->m_pBufContactOutGPU, nContacts, m_data->m_solverGPU->m_numConstraints, m_data->m_solverGPU->m_offsets, csCfg.m_staticIdx );
+ maxNumBatches = 250; //250;
+ m_data->m_solverGPU->batchContacts(m_data->m_pBufContactOutGPU, nContacts, m_data->m_solverGPU->m_numConstraints, m_data->m_solverGPU->m_offsets, csCfg.m_staticIdx);
clFinish(m_data->m_queue);
- } else
+ }
+ else
{
B3_PROFILE("cpu batchContacts");
static b3AlignedObjectArray<b3Contact4> cpuContacts;
@@ -1070,45 +945,43 @@ void b3GpuPgsContactSolver::solveContacts(int numBodies, cl_mem bodyBuf, cl_mem
offsetsNative->copyToHost(offsetsNativeHost);
}
-
- int numNonzeroGrid=0;
+ int numNonzeroGrid = 0;
if (gUseLargeBatches)
{
m_data->m_batchSizes.resize(B3_MAX_NUM_BATCHES);
int totalNumConstraints = cpuContacts.size();
//int simdWidth =numBodies+1;//-1;//64;//-1;//32;
- int numBatches = sortConstraintByBatch3( &cpuContacts[0], totalNumConstraints, totalNumConstraints+1,csCfg.m_staticIdx ,numBodies,&m_data->m_batchSizes[0]); // on GPU
- maxNumBatches = b3Max(numBatches,maxNumBatches);
+ int numBatches = sortConstraintByBatch3(&cpuContacts[0], totalNumConstraints, totalNumConstraints + 1, csCfg.m_staticIdx, numBodies, &m_data->m_batchSizes[0]); // on GPU
+ maxNumBatches = b3Max(numBatches, maxNumBatches);
static int globalMaxBatch = 0;
- if (maxNumBatches>globalMaxBatch )
+ if (maxNumBatches > globalMaxBatch)
{
- globalMaxBatch = maxNumBatches;
- b3Printf("maxNumBatches = %d\n",maxNumBatches);
+ globalMaxBatch = maxNumBatches;
+ b3Printf("maxNumBatches = %d\n", maxNumBatches);
}
-
- } else
+ }
+ else
{
- m_data->m_batchSizes.resize(B3_SOLVER_N_CELLS*B3_MAX_NUM_BATCHES);
+ m_data->m_batchSizes.resize(B3_SOLVER_N_CELLS * B3_MAX_NUM_BATCHES);
B3_PROFILE("cpu batch grid");
- for(int i=0; i<B3_SOLVER_N_CELLS; i++)
+ for (int i = 0; i < B3_SOLVER_N_CELLS; i++)
{
int n = (nNativeHost)[i];
int offset = (offsetsNativeHost)[i];
- if( n )
+ if (n)
{
numNonzeroGrid++;
- int simdWidth =numBodies+1;//-1;//64;//-1;//32;
- int numBatches = sortConstraintByBatch3( &cpuContacts[0]+offset, n, simdWidth,csCfg.m_staticIdx ,numBodies,&m_data->m_batchSizes[i*B3_MAX_NUM_BATCHES]); // on GPU
- maxNumBatches = b3Max(numBatches,maxNumBatches);
+ int simdWidth = numBodies + 1; //-1;//64;//-1;//32;
+ int numBatches = sortConstraintByBatch3(&cpuContacts[0] + offset, n, simdWidth, csCfg.m_staticIdx, numBodies, &m_data->m_batchSizes[i * B3_MAX_NUM_BATCHES]); // on GPU
+ maxNumBatches = b3Max(numBatches, maxNumBatches);
static int globalMaxBatch = 0;
- if (maxNumBatches>globalMaxBatch )
+ if (maxNumBatches > globalMaxBatch)
{
- globalMaxBatch = maxNumBatches;
- b3Printf("maxNumBatches = %d\n",maxNumBatches);
+ globalMaxBatch = maxNumBatches;
+ b3Printf("maxNumBatches = %d\n", maxNumBatches);
}
//we use the clFinish for proper benchmark/profile
-
}
}
//clFinish(m_data->m_queue);
@@ -1117,22 +990,12 @@ void b3GpuPgsContactSolver::solveContacts(int numBodies, cl_mem bodyBuf, cl_mem
B3_PROFILE("m_contactBuffer->copyFromHost");
m_data->m_solverGPU->m_contactBuffer2->copyFromHost((b3AlignedObjectArray<b3Contact4>&)cpuContacts);
}
-
- }
-
+ }
}
+ }
+ }
-
-
-
-
- }
-
-
- }
-
-
- //printf("maxNumBatches = %d\n", maxNumBatches);
+ //printf("maxNumBatches = %d\n", maxNumBatches);
if (gUseLargeBatches)
{
@@ -1140,58 +1003,52 @@ void b3GpuPgsContactSolver::solveContacts(int numBodies, cl_mem bodyBuf, cl_mem
{
B3_PROFILE("cpu batchContacts");
static b3AlignedObjectArray<b3Contact4> cpuContacts;
-// b3OpenCLArray<b3Contact4>* contactsIn = m_data->m_solverGPU->m_contactBuffer2;
+ // b3OpenCLArray<b3Contact4>* contactsIn = m_data->m_solverGPU->m_contactBuffer2;
{
B3_PROFILE("copyToHost");
m_data->m_pBufContactOutGPU->copyToHost(cpuContacts);
}
-// b3OpenCLArray<unsigned int>* countsNative = m_data->m_solverGPU->m_numConstraints;
-// b3OpenCLArray<unsigned int>* offsetsNative = m_data->m_solverGPU->m_offsets;
-
+ // b3OpenCLArray<unsigned int>* countsNative = m_data->m_solverGPU->m_numConstraints;
+ // b3OpenCLArray<unsigned int>* offsetsNative = m_data->m_solverGPU->m_offsets;
-
-// int numNonzeroGrid=0;
+ // int numNonzeroGrid=0;
{
m_data->m_batchSizes.resize(B3_MAX_NUM_BATCHES);
int totalNumConstraints = cpuContacts.size();
- // int simdWidth =numBodies+1;//-1;//64;//-1;//32;
- int numBatches = sortConstraintByBatch3( &cpuContacts[0], totalNumConstraints, totalNumConstraints+1,csCfg.m_staticIdx ,numBodies,&m_data->m_batchSizes[0]); // on GPU
- maxNumBatches = b3Max(numBatches,maxNumBatches);
+ // int simdWidth =numBodies+1;//-1;//64;//-1;//32;
+ int numBatches = sortConstraintByBatch3(&cpuContacts[0], totalNumConstraints, totalNumConstraints + 1, csCfg.m_staticIdx, numBodies, &m_data->m_batchSizes[0]); // on GPU
+ maxNumBatches = b3Max(numBatches, maxNumBatches);
static int globalMaxBatch = 0;
- if (maxNumBatches>globalMaxBatch )
+ if (maxNumBatches > globalMaxBatch)
{
- globalMaxBatch = maxNumBatches;
- b3Printf("maxNumBatches = %d\n",maxNumBatches);
+ globalMaxBatch = maxNumBatches;
+ b3Printf("maxNumBatches = %d\n", maxNumBatches);
}
-
}
{
B3_PROFILE("m_contactBuffer->copyFromHost");
m_data->m_solverGPU->m_contactBuffer2->copyFromHost((b3AlignedObjectArray<b3Contact4>&)cpuContacts);
}
-
- }
-
+ }
}
if (nContacts)
{
B3_PROFILE("gpu convertToConstraints");
- m_data->m_solverGPU->convertToConstraints( bodyBuf,
- shapeBuf, m_data->m_solverGPU->m_contactBuffer2,
- contactConstraintOut,
- additionalData, nContacts,
- (b3SolverBase::ConstraintCfg&) csCfg );
+ m_data->m_solverGPU->convertToConstraints(bodyBuf,
+ shapeBuf, m_data->m_solverGPU->m_contactBuffer2,
+ contactConstraintOut,
+ additionalData, nContacts,
+ (b3SolverBase::ConstraintCfg&)csCfg);
clFinish(m_data->m_queue);
}
-
if (1)
{
int numIter = 4;
- m_data->m_solverGPU->m_nIterations = numIter;//10
+ m_data->m_solverGPU->m_nIterations = numIter; //10
if (!gCpuSolveConstraint)
{
B3_PROFILE("GPU solveContactConstraint");
@@ -1208,32 +1065,30 @@ void b3GpuPgsContactSolver::solveContacts(int numBodies, cl_mem bodyBuf, cl_mem
if (gUseLargeBatches)
{
- solveContactConstraintBatchSizes(m_data->m_bodyBufferGPU,
- m_data->m_inertiaBufferGPU,
- m_data->m_contactCGPU,0,
- nContactOut ,
- maxNumBatches,numIter,&m_data->m_batchSizes);
- } else
+ solveContactConstraintBatchSizes(m_data->m_bodyBufferGPU,
+ m_data->m_inertiaBufferGPU,
+ m_data->m_contactCGPU, 0,
+ nContactOut,
+ maxNumBatches, numIter, &m_data->m_batchSizes);
+ }
+ else
{
solveContactConstraint(
- m_data->m_bodyBufferGPU,
+ m_data->m_bodyBufferGPU,
m_data->m_inertiaBufferGPU,
- m_data->m_contactCGPU,0,
- nContactOut ,
- maxNumBatches,numIter,&m_data->m_batchSizes);//m_data->m_batchSizesGpu);
+ m_data->m_contactCGPU, 0,
+ nContactOut,
+ maxNumBatches, numIter, &m_data->m_batchSizes); //m_data->m_batchSizesGpu);
}
}
else
{
B3_PROFILE("Host solveContactConstraint");
- m_data->m_solverGPU->solveContactConstraintHost(m_data->m_bodyBufferGPU, m_data->m_inertiaBufferGPU, m_data->m_contactCGPU,0, nContactOut ,maxNumBatches,&m_data->m_batchSizes);
+ m_data->m_solverGPU->solveContactConstraintHost(m_data->m_bodyBufferGPU, m_data->m_inertiaBufferGPU, m_data->m_contactCGPU, 0, nContactOut, maxNumBatches, &m_data->m_batchSizes);
}
-
-
- }
-
-
+ }
+
#if 0
if (0)
{
@@ -1244,114 +1099,96 @@ void b3GpuPgsContactSolver::solveContacts(int numBodies, cl_mem bodyBuf, cl_mem
adl::DeviceUtils::waitForCompletion( m_data->m_deviceCL );
}
#endif
-
- }
-
+ }
}
-
-void b3GpuPgsContactSolver::batchContacts( b3OpenCLArray<b3Contact4>* contacts, int nContacts, b3OpenCLArray<unsigned int>* n, b3OpenCLArray<unsigned int>* offsets, int staticIdx )
+void b3GpuPgsContactSolver::batchContacts(b3OpenCLArray<b3Contact4>* contacts, int nContacts, b3OpenCLArray<unsigned int>* n, b3OpenCLArray<unsigned int>* offsets, int staticIdx)
{
}
-
-
-
-
-
-
-
-
-
-
b3AlignedObjectArray<unsigned int> idxBuffer;
b3AlignedObjectArray<b3SortData> sortData;
b3AlignedObjectArray<b3Contact4> old;
-
-inline int b3GpuPgsContactSolver::sortConstraintByBatch( b3Contact4* cs, int n, int simdWidth , int staticIdx, int numBodies)
+inline int b3GpuPgsContactSolver::sortConstraintByBatch(b3Contact4* cs, int n, int simdWidth, int staticIdx, int numBodies)
{
-
B3_PROFILE("sortConstraintByBatch");
int numIter = 0;
-
+
sortData.resize(n);
idxBuffer.resize(n);
old.resize(n);
-
+
unsigned int* idxSrc = &idxBuffer[0];
unsigned int* idxDst = &idxBuffer[0];
int nIdxSrc, nIdxDst;
-
+
const int N_FLG = 256;
- const int FLG_MASK = N_FLG-1;
- unsigned int flg[N_FLG/32];
+ const int FLG_MASK = N_FLG - 1;
+ unsigned int flg[N_FLG / 32];
#if defined(_DEBUG)
- for(int i=0; i<n; i++)
+ for (int i = 0; i < n; i++)
cs[i].getBatchIdx() = -1;
#endif
- for(int i=0; i<n; i++)
+ for (int i = 0; i < n; i++)
idxSrc[i] = i;
nIdxSrc = n;
-
+
int batchIdx = 0;
-
+
{
B3_PROFILE("cpu batch innerloop");
- while( nIdxSrc )
+ while (nIdxSrc)
{
numIter++;
nIdxDst = 0;
int nCurrentBatch = 0;
-
+
// clear flag
- for(int i=0; i<N_FLG/32; i++) flg[i] = 0;
-
- for(int i=0; i<nIdxSrc; i++)
+ for (int i = 0; i < N_FLG / 32; i++) flg[i] = 0;
+
+ for (int i = 0; i < nIdxSrc; i++)
{
int idx = idxSrc[i];
-
- b3Assert( idx < n );
+ b3Assert(idx < n);
// check if it can go
int bodyAS = cs[idx].m_bodyAPtrAndSignBit;
int bodyBS = cs[idx].m_bodyBPtrAndSignBit;
-
-
-
+
int bodyA = abs(bodyAS);
int bodyB = abs(bodyBS);
-
+
int aIdx = bodyA & FLG_MASK;
int bIdx = bodyB & FLG_MASK;
-
- unsigned int aUnavailable = flg[ aIdx/32 ] & (1<<(aIdx&31));
- unsigned int bUnavailable = flg[ bIdx/32 ] & (1<<(bIdx&31));
-
- bool aIsStatic = (bodyAS<0) || bodyAS==staticIdx;
- bool bIsStatic = (bodyBS<0) || bodyBS==staticIdx;
-
- //use inv_mass!
- aUnavailable = !aIsStatic? aUnavailable:0;//
- bUnavailable = !bIsStatic? bUnavailable:0;
-
- if( aUnavailable==0 && bUnavailable==0 ) // ok
+
+ unsigned int aUnavailable = flg[aIdx / 32] & (1 << (aIdx & 31));
+ unsigned int bUnavailable = flg[bIdx / 32] & (1 << (bIdx & 31));
+
+ bool aIsStatic = (bodyAS < 0) || bodyAS == staticIdx;
+ bool bIsStatic = (bodyBS < 0) || bodyBS == staticIdx;
+
+ //use inv_mass!
+ aUnavailable = !aIsStatic ? aUnavailable : 0; //
+ bUnavailable = !bIsStatic ? bUnavailable : 0;
+
+ if (aUnavailable == 0 && bUnavailable == 0) // ok
{
if (!aIsStatic)
- flg[ aIdx/32 ] |= (1<<(aIdx&31));
+ flg[aIdx / 32] |= (1 << (aIdx & 31));
if (!bIsStatic)
- flg[ bIdx/32 ] |= (1<<(bIdx&31));
+ flg[bIdx / 32] |= (1 << (bIdx & 31));
cs[idx].getBatchIdx() = batchIdx;
sortData[idx].m_key = batchIdx;
sortData[idx].m_value = idx;
-
+
{
nCurrentBatch++;
- if( nCurrentBatch == simdWidth )
+ if (nCurrentBatch == simdWidth)
{
nCurrentBatch = 0;
- for(int i=0; i<N_FLG/32; i++) flg[i] = 0;
+ for (int i = 0; i < N_FLG / 32; i++) flg[i] = 0;
}
}
}
@@ -1360,128 +1197,121 @@ inline int b3GpuPgsContactSolver::sortConstraintByBatch( b3Contact4* cs, int n,
idxDst[nIdxDst++] = idx;
}
}
- b3Swap( idxSrc, idxDst );
- b3Swap( nIdxSrc, nIdxDst );
- batchIdx ++;
+ b3Swap(idxSrc, idxDst);
+ b3Swap(nIdxSrc, nIdxDst);
+ batchIdx++;
}
}
{
B3_PROFILE("quickSort");
sortData.quickSort(sortfnc);
}
-
-
+
{
- B3_PROFILE("reorder");
+ B3_PROFILE("reorder");
// reorder
-
- memcpy( &old[0], cs, sizeof(b3Contact4)*n);
- for(int i=0; i<n; i++)
+
+ memcpy(&old[0], cs, sizeof(b3Contact4) * n);
+ for (int i = 0; i < n; i++)
{
int idx = sortData[i].m_value;
cs[i] = old[idx];
}
}
-
-
+
#if defined(_DEBUG)
- // debugPrintf( "nBatches: %d\n", batchIdx );
- for(int i=0; i<n; i++)
- {
- b3Assert( cs[i].getBatchIdx() != -1 );
- }
+ // debugPrintf( "nBatches: %d\n", batchIdx );
+ for (int i = 0; i < n; i++)
+ {
+ b3Assert(cs[i].getBatchIdx() != -1);
+ }
#endif
return batchIdx;
}
-
b3AlignedObjectArray<int> bodyUsed2;
-inline int b3GpuPgsContactSolver::sortConstraintByBatch2( b3Contact4* cs, int numConstraints, int simdWidth , int staticIdx, int numBodies)
+inline int b3GpuPgsContactSolver::sortConstraintByBatch2(b3Contact4* cs, int numConstraints, int simdWidth, int staticIdx, int numBodies)
{
-
B3_PROFILE("sortConstraintByBatch2");
-
-
- bodyUsed2.resize(2*simdWidth);
+ bodyUsed2.resize(2 * simdWidth);
- for (int q=0;q<2*simdWidth;q++)
- bodyUsed2[q]=0;
+ for (int q = 0; q < 2 * simdWidth; q++)
+ bodyUsed2[q] = 0;
int curBodyUsed = 0;
int numIter = 0;
-
+
m_data->m_sortData.resize(numConstraints);
m_data->m_idxBuffer.resize(numConstraints);
m_data->m_old.resize(numConstraints);
-
+
unsigned int* idxSrc = &m_data->m_idxBuffer[0];
-
+
#if defined(_DEBUG)
- for(int i=0; i<numConstraints; i++)
+ for (int i = 0; i < numConstraints; i++)
cs[i].getBatchIdx() = -1;
#endif
- for(int i=0; i<numConstraints; i++)
+ for (int i = 0; i < numConstraints; i++)
idxSrc[i] = i;
-
+
int numValidConstraints = 0;
-// int unprocessedConstraintIndex = 0;
+ // int unprocessedConstraintIndex = 0;
int batchIdx = 0;
-
{
B3_PROFILE("cpu batch innerloop");
-
- while( numValidConstraints < numConstraints)
+
+ while (numValidConstraints < numConstraints)
{
numIter++;
int nCurrentBatch = 0;
// clear flag
- for(int i=0; i<curBodyUsed; i++)
+ for (int i = 0; i < curBodyUsed; i++)
bodyUsed2[i] = 0;
- curBodyUsed = 0;
+ curBodyUsed = 0;
- for(int i=numValidConstraints; i<numConstraints; i++)
+ for (int i = numValidConstraints; i < numConstraints; i++)
{
int idx = idxSrc[i];
- b3Assert( idx < numConstraints );
+ b3Assert(idx < numConstraints);
// check if it can go
int bodyAS = cs[idx].m_bodyAPtrAndSignBit;
int bodyBS = cs[idx].m_bodyBPtrAndSignBit;
int bodyA = abs(bodyAS);
int bodyB = abs(bodyBS);
- bool aIsStatic = (bodyAS<0) || bodyAS==staticIdx;
- bool bIsStatic = (bodyBS<0) || bodyBS==staticIdx;
+ bool aIsStatic = (bodyAS < 0) || bodyAS == staticIdx;
+ bool bIsStatic = (bodyBS < 0) || bodyBS == staticIdx;
int aUnavailable = 0;
int bUnavailable = 0;
if (!aIsStatic)
{
- for (int j=0;j<curBodyUsed;j++)
+ for (int j = 0; j < curBodyUsed; j++)
{
if (bodyA == bodyUsed2[j])
{
- aUnavailable=1;
+ aUnavailable = 1;
break;
}
}
}
if (!aUnavailable)
- if (!bIsStatic)
- {
- for (int j=0;j<curBodyUsed;j++)
+ if (!bIsStatic)
{
- if (bodyB == bodyUsed2[j])
+ for (int j = 0; j < curBodyUsed; j++)
{
- bUnavailable=1;
- break;
+ if (bodyB == bodyUsed2[j])
+ {
+ bUnavailable = 1;
+ break;
+ }
}
}
- }
-
- if( aUnavailable==0 && bUnavailable==0 ) // ok
+
+ if (aUnavailable == 0 && bUnavailable == 0) // ok
{
if (!aIsStatic)
{
@@ -1496,7 +1326,7 @@ inline int b3GpuPgsContactSolver::sortConstraintByBatch2( b3Contact4* cs, int nu
m_data->m_sortData[idx].m_key = batchIdx;
m_data->m_sortData[idx].m_value = idx;
- if (i!=numValidConstraints)
+ if (i != numValidConstraints)
{
b3Swap(idxSrc[i], idxSrc[numValidConstraints]);
}
@@ -1504,20 +1334,19 @@ inline int b3GpuPgsContactSolver::sortConstraintByBatch2( b3Contact4* cs, int nu
numValidConstraints++;
{
nCurrentBatch++;
- if( nCurrentBatch == simdWidth )
+ if (nCurrentBatch == simdWidth)
{
nCurrentBatch = 0;
- for(int i=0; i<curBodyUsed; i++)
+ for (int i = 0; i < curBodyUsed; i++)
bodyUsed2[i] = 0;
-
curBodyUsed = 0;
}
}
}
}
-
- batchIdx ++;
+
+ batchIdx++;
}
}
{
@@ -1526,155 +1355,148 @@ inline int b3GpuPgsContactSolver::sortConstraintByBatch2( b3Contact4* cs, int nu
}
{
- B3_PROFILE("reorder");
+ B3_PROFILE("reorder");
// reorder
-
- memcpy( &m_data->m_old[0], cs, sizeof(b3Contact4)*numConstraints);
- for(int i=0; i<numConstraints; i++)
+ memcpy(&m_data->m_old[0], cs, sizeof(b3Contact4) * numConstraints);
+
+ for (int i = 0; i < numConstraints; i++)
{
b3Assert(m_data->m_sortData[idxSrc[i]].m_value == idxSrc[i]);
int idx = m_data->m_sortData[idxSrc[i]].m_value;
cs[i] = m_data->m_old[idx];
}
}
-
+
#if defined(_DEBUG)
- // debugPrintf( "nBatches: %d\n", batchIdx );
- for(int i=0; i<numConstraints; i++)
- {
- b3Assert( cs[i].getBatchIdx() != -1 );
- }
+ // debugPrintf( "nBatches: %d\n", batchIdx );
+ for (int i = 0; i < numConstraints; i++)
+ {
+ b3Assert(cs[i].getBatchIdx() != -1);
+ }
#endif
-
return batchIdx;
}
-
b3AlignedObjectArray<int> bodyUsed;
b3AlignedObjectArray<int> curUsed;
-
-inline int b3GpuPgsContactSolver::sortConstraintByBatch3( b3Contact4* cs, int numConstraints, int simdWidth , int staticIdx, int numBodies, int* batchSizes)
+inline int b3GpuPgsContactSolver::sortConstraintByBatch3(b3Contact4* cs, int numConstraints, int simdWidth, int staticIdx, int numBodies, int* batchSizes)
{
-
B3_PROFILE("sortConstraintByBatch3");
-
+
static int maxSwaps = 0;
int numSwaps = 0;
- curUsed.resize(2*simdWidth);
+ curUsed.resize(2 * simdWidth);
static int maxNumConstraints = 0;
- if (maxNumConstraints<numConstraints)
+ if (maxNumConstraints < numConstraints)
{
maxNumConstraints = numConstraints;
//printf("maxNumConstraints = %d\n",maxNumConstraints );
}
- int numUsedArray = numBodies/32+1;
+ int numUsedArray = numBodies / 32 + 1;
bodyUsed.resize(numUsedArray);
- for (int q=0;q<numUsedArray;q++)
- bodyUsed[q]=0;
+ for (int q = 0; q < numUsedArray; q++)
+ bodyUsed[q] = 0;
-
int curBodyUsed = 0;
int numIter = 0;
-
+
m_data->m_sortData.resize(0);
m_data->m_idxBuffer.resize(0);
m_data->m_old.resize(0);
-
-
+
#if defined(_DEBUG)
- for(int i=0; i<numConstraints; i++)
+ for (int i = 0; i < numConstraints; i++)
cs[i].getBatchIdx() = -1;
#endif
-
+
int numValidConstraints = 0;
-// int unprocessedConstraintIndex = 0;
+ // int unprocessedConstraintIndex = 0;
int batchIdx = 0;
-
{
B3_PROFILE("cpu batch innerloop");
-
- while( numValidConstraints < numConstraints)
+
+ while (numValidConstraints < numConstraints)
{
numIter++;
int nCurrentBatch = 0;
batchSizes[batchIdx] = 0;
// clear flag
- for(int i=0; i<curBodyUsed; i++)
- bodyUsed[curUsed[i]/32] = 0;
+ for (int i = 0; i < curBodyUsed; i++)
+ bodyUsed[curUsed[i] / 32] = 0;
- curBodyUsed = 0;
+ curBodyUsed = 0;
- for(int i=numValidConstraints; i<numConstraints; i++)
+ for (int i = numValidConstraints; i < numConstraints; i++)
{
int idx = i;
- b3Assert( idx < numConstraints );
+ b3Assert(idx < numConstraints);
// check if it can go
int bodyAS = cs[idx].m_bodyAPtrAndSignBit;
int bodyBS = cs[idx].m_bodyBPtrAndSignBit;
int bodyA = abs(bodyAS);
int bodyB = abs(bodyBS);
- bool aIsStatic = (bodyAS<0) || bodyAS==staticIdx;
- bool bIsStatic = (bodyBS<0) || bodyBS==staticIdx;
+ bool aIsStatic = (bodyAS < 0) || bodyAS == staticIdx;
+ bool bIsStatic = (bodyBS < 0) || bodyBS == staticIdx;
int aUnavailable = 0;
int bUnavailable = 0;
if (!aIsStatic)
{
- aUnavailable = bodyUsed[ bodyA/32 ] & (1<<(bodyA&31));
+ aUnavailable = bodyUsed[bodyA / 32] & (1 << (bodyA & 31));
}
if (!aUnavailable)
- if (!bIsStatic)
- {
- bUnavailable = bodyUsed[ bodyB/32 ] & (1<<(bodyB&31));
- }
-
- if( aUnavailable==0 && bUnavailable==0 ) // ok
+ if (!bIsStatic)
+ {
+ bUnavailable = bodyUsed[bodyB / 32] & (1 << (bodyB & 31));
+ }
+
+ if (aUnavailable == 0 && bUnavailable == 0) // ok
{
if (!aIsStatic)
{
- bodyUsed[ bodyA/32 ] |= (1<<(bodyA&31));
- curUsed[curBodyUsed++]=bodyA;
+ bodyUsed[bodyA / 32] |= (1 << (bodyA & 31));
+ curUsed[curBodyUsed++] = bodyA;
}
if (!bIsStatic)
{
- bodyUsed[ bodyB/32 ] |= (1<<(bodyB&31));
- curUsed[curBodyUsed++]=bodyB;
+ bodyUsed[bodyB / 32] |= (1 << (bodyB & 31));
+ curUsed[curBodyUsed++] = bodyB;
}
cs[idx].getBatchIdx() = batchIdx;
- if (i!=numValidConstraints)
+ if (i != numValidConstraints)
{
- b3Swap(cs[i],cs[numValidConstraints]);
+ b3Swap(cs[i], cs[numValidConstraints]);
numSwaps++;
}
numValidConstraints++;
{
nCurrentBatch++;
- if( nCurrentBatch == simdWidth )
+ if (nCurrentBatch == simdWidth)
{
batchSizes[batchIdx] += simdWidth;
nCurrentBatch = 0;
- for(int i=0; i<curBodyUsed; i++)
- bodyUsed[curUsed[i]/32] = 0;
+ for (int i = 0; i < curBodyUsed; i++)
+ bodyUsed[curUsed[i] / 32] = 0;
curBodyUsed = 0;
}
}
}
}
- if (batchIdx>=B3_MAX_NUM_BATCHES)
+ if (batchIdx >= B3_MAX_NUM_BATCHES)
{
b3Error("batchIdx>=B3_MAX_NUM_BATCHES");
b3Assert(0);
@@ -1683,26 +1505,25 @@ inline int b3GpuPgsContactSolver::sortConstraintByBatch3( b3Contact4* cs, int nu
batchSizes[batchIdx] += nCurrentBatch;
- batchIdx ++;
-
+ batchIdx++;
}
}
-
+
#if defined(_DEBUG)
- // debugPrintf( "nBatches: %d\n", batchIdx );
- for(int i=0; i<numConstraints; i++)
- {
- b3Assert( cs[i].getBatchIdx() != -1 );
- }
+ // debugPrintf( "nBatches: %d\n", batchIdx );
+ for (int i = 0; i < numConstraints; i++)
+ {
+ b3Assert(cs[i].getBatchIdx() != -1);
+ }
#endif
- batchSizes[batchIdx] =0;
-
- if (maxSwaps<numSwaps)
+ batchSizes[batchIdx] = 0;
+
+ if (maxSwaps < numSwaps)
{
maxSwaps = numSwaps;
//printf("maxSwaps = %d\n", maxSwaps);
}
-
+
return batchIdx;
}
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuPgsContactSolver.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuPgsContactSolver.h
index 98e2a5b8c4..6ab7502af3 100644
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuPgsContactSolver.h
+++ b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuPgsContactSolver.h
@@ -11,33 +11,27 @@
class b3GpuPgsContactSolver
{
protected:
-
int m_debugOutput;
- struct b3GpuBatchingPgsSolverInternalData* m_data;
+ struct b3GpuBatchingPgsSolverInternalData* m_data;
+
+ void batchContacts(b3OpenCLArray<b3Contact4>* contacts, int nContacts, b3OpenCLArray<unsigned int>* n, b3OpenCLArray<unsigned int>* offsets, int staticIdx);
- void batchContacts( b3OpenCLArray<b3Contact4>* contacts, int nContacts, b3OpenCLArray<unsigned int>* n, b3OpenCLArray<unsigned int>* offsets, int staticIdx );
-
- inline int sortConstraintByBatch( b3Contact4* cs, int n, int simdWidth , int staticIdx, int numBodies);
- inline int sortConstraintByBatch2( b3Contact4* cs, int n, int simdWidth , int staticIdx, int numBodies);
- inline int sortConstraintByBatch3( b3Contact4* cs, int n, int simdWidth , int staticIdx, int numBodies, int* batchSizes);
-
+ inline int sortConstraintByBatch(b3Contact4* cs, int n, int simdWidth, int staticIdx, int numBodies);
+ inline int sortConstraintByBatch2(b3Contact4* cs, int n, int simdWidth, int staticIdx, int numBodies);
+ inline int sortConstraintByBatch3(b3Contact4* cs, int n, int simdWidth, int staticIdx, int numBodies, int* batchSizes);
-
- void solveContactConstraintBatchSizes( const b3OpenCLArray<b3RigidBodyData>* bodyBuf, const b3OpenCLArray<b3InertiaData>* shapeBuf,
- b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n ,int maxNumBatches, int numIterations, const b3AlignedObjectArray<int>* batchSizes);//const b3OpenCLArray<int>* gpuBatchSizes);
+ void solveContactConstraintBatchSizes(const b3OpenCLArray<b3RigidBodyData>* bodyBuf, const b3OpenCLArray<b3InertiaData>* shapeBuf,
+ b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n, int maxNumBatches, int numIterations, const b3AlignedObjectArray<int>* batchSizes); //const b3OpenCLArray<int>* gpuBatchSizes);
- void solveContactConstraint( const b3OpenCLArray<b3RigidBodyData>* bodyBuf, const b3OpenCLArray<b3InertiaData>* shapeBuf,
- b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n ,int maxNumBatches, int numIterations, const b3AlignedObjectArray<int>* batchSizes);//const b3OpenCLArray<int>* gpuBatchSizes);
+ void solveContactConstraint(const b3OpenCLArray<b3RigidBodyData>* bodyBuf, const b3OpenCLArray<b3InertiaData>* shapeBuf,
+ b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n, int maxNumBatches, int numIterations, const b3AlignedObjectArray<int>* batchSizes); //const b3OpenCLArray<int>* gpuBatchSizes);
public:
-
- b3GpuPgsContactSolver(cl_context ctx,cl_device_id device, cl_command_queue q,int pairCapacity);
+ b3GpuPgsContactSolver(cl_context ctx, cl_device_id device, cl_command_queue q, int pairCapacity);
virtual ~b3GpuPgsContactSolver();
void solveContacts(int numBodies, cl_mem bodyBuf, cl_mem inertiaBuf, int numContacts, cl_mem contactBuf, const struct b3Config& config, int static0Index);
-
};
-#endif //B3_GPU_BATCHING_PGS_SOLVER_H
-
+#endif //B3_GPU_BATCHING_PGS_SOLVER_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipeline.cpp b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipeline.cpp
index 783e443060..fef33ad1cd 100644
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipeline.cpp
+++ b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipeline.cpp
@@ -47,7 +47,7 @@ bool gClearPairsOnGpu = true;
#define TEST_OTHER_GPU_SOLVER 1
#ifdef TEST_OTHER_GPU_SOLVER
#include "b3GpuJacobiContactSolver.h"
-#endif //TEST_OTHER_GPU_SOLVER
+#endif //TEST_OTHER_GPU_SOLVER
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
#include "Bullet3Collision/NarrowPhaseCollision/b3Contact4.h"
@@ -59,73 +59,68 @@ bool gClearPairsOnGpu = true;
#include "Bullet3Collision/NarrowPhaseCollision/b3Config.h"
#include "Bullet3OpenCL/Raycast/b3GpuRaycast.h"
-
#include "Bullet3Dynamics/shared/b3IntegrateTransforms.h"
#include "Bullet3OpenCL/RigidBody/b3GpuNarrowPhaseInternalData.h"
-b3GpuRigidBodyPipeline::b3GpuRigidBodyPipeline(cl_context ctx,cl_device_id device, cl_command_queue q,class b3GpuNarrowPhase* narrowphase, class b3GpuBroadphaseInterface* broadphaseSap , struct b3DynamicBvhBroadphase* broadphaseDbvt, const b3Config& config)
+b3GpuRigidBodyPipeline::b3GpuRigidBodyPipeline(cl_context ctx, cl_device_id device, cl_command_queue q, class b3GpuNarrowPhase* narrowphase, class b3GpuBroadphaseInterface* broadphaseSap, struct b3DynamicBvhBroadphase* broadphaseDbvt, const b3Config& config)
{
m_data = new b3GpuRigidBodyPipelineInternalData;
- m_data->m_constraintUid=0;
+ m_data->m_constraintUid = 0;
m_data->m_config = config;
m_data->m_context = ctx;
m_data->m_device = device;
m_data->m_queue = q;
- m_data->m_solver = new b3PgsJacobiSolver(true);//new b3PgsJacobiSolver(true);
- m_data->m_gpuSolver = new b3GpuPgsConstraintSolver(ctx,device,q,true);//new b3PgsJacobiSolver(true);
-
- m_data->m_allAabbsGPU = new b3OpenCLArray<b3SapAabb>(ctx,q,config.m_maxConvexBodies);
- m_data->m_overlappingPairsGPU = new b3OpenCLArray<b3BroadphasePair>(ctx,q,config.m_maxBroadphasePairs);
+ m_data->m_solver = new b3PgsJacobiSolver(true); //new b3PgsJacobiSolver(true);
+ m_data->m_gpuSolver = new b3GpuPgsConstraintSolver(ctx, device, q, true); //new b3PgsJacobiSolver(true);
- m_data->m_gpuConstraints = new b3OpenCLArray<b3GpuGenericConstraint>(ctx,q);
+ m_data->m_allAabbsGPU = new b3OpenCLArray<b3SapAabb>(ctx, q, config.m_maxConvexBodies);
+ m_data->m_overlappingPairsGPU = new b3OpenCLArray<b3BroadphasePair>(ctx, q, config.m_maxBroadphasePairs);
+
+ m_data->m_gpuConstraints = new b3OpenCLArray<b3GpuGenericConstraint>(ctx, q);
#ifdef TEST_OTHER_GPU_SOLVER
- m_data->m_solver3 = new b3GpuJacobiContactSolver(ctx,device,q,config.m_maxBroadphasePairs);
-#endif // TEST_OTHER_GPU_SOLVER
-
- m_data->m_solver2 = new b3GpuPgsContactSolver(ctx,device,q,config.m_maxBroadphasePairs);
+ m_data->m_solver3 = new b3GpuJacobiContactSolver(ctx, device, q, config.m_maxBroadphasePairs);
+#endif // TEST_OTHER_GPU_SOLVER
+
+ m_data->m_solver2 = new b3GpuPgsContactSolver(ctx, device, q, config.m_maxBroadphasePairs);
- m_data->m_raycaster = new b3GpuRaycast(ctx,device,q);
+ m_data->m_raycaster = new b3GpuRaycast(ctx, device, q);
-
m_data->m_broadphaseDbvt = broadphaseDbvt;
m_data->m_broadphaseSap = broadphaseSap;
m_data->m_narrowphase = narrowphase;
- m_data->m_gravity.setValue(0.f,-9.8f,0.f);
+ m_data->m_gravity.setValue(0.f, -9.8f, 0.f);
- cl_int errNum=0;
+ cl_int errNum = 0;
{
- cl_program prog = b3OpenCLUtils::compileCLProgramFromString(m_data->m_context,m_data->m_device,integrateKernelCL,&errNum,"",B3_RIGIDBODY_INTEGRATE_PATH);
- b3Assert(errNum==CL_SUCCESS);
- m_data->m_integrateTransformsKernel = b3OpenCLUtils::compileCLKernelFromString(m_data->m_context, m_data->m_device,integrateKernelCL, "integrateTransformsKernel",&errNum,prog);
- b3Assert(errNum==CL_SUCCESS);
+ cl_program prog = b3OpenCLUtils::compileCLProgramFromString(m_data->m_context, m_data->m_device, integrateKernelCL, &errNum, "", B3_RIGIDBODY_INTEGRATE_PATH);
+ b3Assert(errNum == CL_SUCCESS);
+ m_data->m_integrateTransformsKernel = b3OpenCLUtils::compileCLKernelFromString(m_data->m_context, m_data->m_device, integrateKernelCL, "integrateTransformsKernel", &errNum, prog);
+ b3Assert(errNum == CL_SUCCESS);
clReleaseProgram(prog);
}
{
- cl_program prog = b3OpenCLUtils::compileCLProgramFromString(m_data->m_context,m_data->m_device,updateAabbsKernelCL,&errNum,"",B3_RIGIDBODY_UPDATEAABB_PATH);
- b3Assert(errNum==CL_SUCCESS);
- m_data->m_updateAabbsKernel = b3OpenCLUtils::compileCLKernelFromString(m_data->m_context, m_data->m_device,updateAabbsKernelCL, "initializeGpuAabbsFull",&errNum,prog);
- b3Assert(errNum==CL_SUCCESS);
+ cl_program prog = b3OpenCLUtils::compileCLProgramFromString(m_data->m_context, m_data->m_device, updateAabbsKernelCL, &errNum, "", B3_RIGIDBODY_UPDATEAABB_PATH);
+ b3Assert(errNum == CL_SUCCESS);
+ m_data->m_updateAabbsKernel = b3OpenCLUtils::compileCLKernelFromString(m_data->m_context, m_data->m_device, updateAabbsKernelCL, "initializeGpuAabbsFull", &errNum, prog);
+ b3Assert(errNum == CL_SUCCESS);
-
- m_data->m_clearOverlappingPairsKernel = b3OpenCLUtils::compileCLKernelFromString(m_data->m_context, m_data->m_device,updateAabbsKernelCL, "clearOverlappingPairsKernel",&errNum,prog);
- b3Assert(errNum==CL_SUCCESS);
+ m_data->m_clearOverlappingPairsKernel = b3OpenCLUtils::compileCLKernelFromString(m_data->m_context, m_data->m_device, updateAabbsKernelCL, "clearOverlappingPairsKernel", &errNum, prog);
+ b3Assert(errNum == CL_SUCCESS);
clReleaseProgram(prog);
}
-
-
}
b3GpuRigidBodyPipeline::~b3GpuRigidBodyPipeline()
{
if (m_data->m_integrateTransformsKernel)
clReleaseKernel(m_data->m_integrateTransformsKernel);
-
+
if (m_data->m_updateAabbsKernel)
clReleaseKernel(m_data->m_updateAabbsKernel);
-
+
if (m_data->m_clearOverlappingPairsKernel)
clReleaseKernel(m_data->m_clearOverlappingPairsKernel);
delete m_data->m_raycaster;
@@ -136,15 +131,14 @@ b3GpuRigidBodyPipeline::~b3GpuRigidBodyPipeline()
#ifdef TEST_OTHER_GPU_SOLVER
delete m_data->m_solver3;
-#endif //TEST_OTHER_GPU_SOLVER
-
+#endif //TEST_OTHER_GPU_SOLVER
+
delete m_data->m_solver2;
-
-
+
delete m_data;
}
-void b3GpuRigidBodyPipeline::reset()
+void b3GpuRigidBodyPipeline::reset()
{
m_data->m_gpuConstraints->resize(0);
m_data->m_cpuConstraints.resize(0);
@@ -152,30 +146,28 @@ void b3GpuRigidBodyPipeline::reset()
m_data->m_allAabbsCPU.resize(0);
}
-void b3GpuRigidBodyPipeline::addConstraint(b3TypedConstraint* constraint)
+void b3GpuRigidBodyPipeline::addConstraint(b3TypedConstraint* constraint)
{
m_data->m_joints.push_back(constraint);
}
-void b3GpuRigidBodyPipeline::removeConstraint(b3TypedConstraint* constraint)
+void b3GpuRigidBodyPipeline::removeConstraint(b3TypedConstraint* constraint)
{
m_data->m_joints.remove(constraint);
}
-
-
-void b3GpuRigidBodyPipeline::removeConstraintByUid(int uid)
+void b3GpuRigidBodyPipeline::removeConstraintByUid(int uid)
{
m_data->m_gpuSolver->recomputeBatches();
//slow linear search
m_data->m_gpuConstraints->copyToHost(m_data->m_cpuConstraints);
//remove
- for (int i=0;i<m_data->m_cpuConstraints.size();i++)
+ for (int i = 0; i < m_data->m_cpuConstraints.size(); i++)
{
if (m_data->m_cpuConstraints[i].m_uid == uid)
{
//m_data->m_cpuConstraints.remove(m_data->m_cpuConstraints[i]);
- m_data->m_cpuConstraints.swap(i,m_data->m_cpuConstraints.size()-1);
+ m_data->m_cpuConstraints.swap(i, m_data->m_cpuConstraints.size() - 1);
m_data->m_cpuConstraints.pop_back();
break;
@@ -185,13 +177,13 @@ void b3GpuRigidBodyPipeline::removeConstraintByUid(int uid)
if (m_data->m_cpuConstraints.size())
{
m_data->m_gpuConstraints->copyFromHost(m_data->m_cpuConstraints);
- } else
+ }
+ else
{
m_data->m_gpuConstraints->resize(0);
}
-
}
-int b3GpuRigidBodyPipeline::createPoint2PointConstraint(int bodyA, int bodyB, const float* pivotInA, const float* pivotInB,float breakingThreshold)
+int b3GpuRigidBodyPipeline::createPoint2PointConstraint(int bodyA, int bodyB, const float* pivotInA, const float* pivotInB, float breakingThreshold)
{
m_data->m_gpuSolver->recomputeBatches();
b3GpuGenericConstraint c;
@@ -200,14 +192,14 @@ int b3GpuRigidBodyPipeline::createPoint2PointConstraint(int bodyA, int bodyB, co
c.m_flags = B3_CONSTRAINT_FLAG_ENABLED;
c.m_rbA = bodyA;
c.m_rbB = bodyB;
- c.m_pivotInA.setValue(pivotInA[0],pivotInA[1],pivotInA[2]);
- c.m_pivotInB.setValue(pivotInB[0],pivotInB[1],pivotInB[2]);
+ c.m_pivotInA.setValue(pivotInA[0], pivotInA[1], pivotInA[2]);
+ c.m_pivotInB.setValue(pivotInB[0], pivotInB[1], pivotInB[2]);
c.m_breakingImpulseThreshold = breakingThreshold;
c.m_constraintType = B3_GPU_POINT2POINT_CONSTRAINT_TYPE;
m_data->m_cpuConstraints.push_back(c);
return c.m_uid;
}
-int b3GpuRigidBodyPipeline::createFixedConstraint(int bodyA, int bodyB, const float* pivotInA, const float* pivotInB, const float* relTargetAB,float breakingThreshold)
+int b3GpuRigidBodyPipeline::createFixedConstraint(int bodyA, int bodyB, const float* pivotInA, const float* pivotInB, const float* relTargetAB, float breakingThreshold)
{
m_data->m_gpuSolver->recomputeBatches();
b3GpuGenericConstraint c;
@@ -216,9 +208,9 @@ int b3GpuRigidBodyPipeline::createFixedConstraint(int bodyA, int bodyB, const fl
c.m_flags = B3_CONSTRAINT_FLAG_ENABLED;
c.m_rbA = bodyA;
c.m_rbB = bodyB;
- c.m_pivotInA.setValue(pivotInA[0],pivotInA[1],pivotInA[2]);
- c.m_pivotInB.setValue(pivotInB[0],pivotInB[1],pivotInB[2]);
- c.m_relTargetAB.setValue(relTargetAB[0],relTargetAB[1],relTargetAB[2],relTargetAB[3]);
+ c.m_pivotInA.setValue(pivotInA[0], pivotInA[1], pivotInA[2]);
+ c.m_pivotInB.setValue(pivotInB[0], pivotInB[1], pivotInB[2]);
+ c.m_relTargetAB.setValue(relTargetAB[0], relTargetAB[1], relTargetAB[2], relTargetAB[3]);
c.m_breakingImpulseThreshold = breakingThreshold;
c.m_constraintType = B3_GPU_FIXED_CONSTRAINT_TYPE;
@@ -226,31 +218,28 @@ int b3GpuRigidBodyPipeline::createFixedConstraint(int bodyA, int bodyB, const fl
return c.m_uid;
}
-
-void b3GpuRigidBodyPipeline::stepSimulation(float deltaTime)
+void b3GpuRigidBodyPipeline::stepSimulation(float deltaTime)
{
-
//update worldspace AABBs from local AABB/worldtransform
{
B3_PROFILE("setupGpuAabbs");
setupGpuAabbsFull();
}
- int numPairs =0;
+ int numPairs = 0;
//compute overlapping pairs
{
-
if (gUseDbvt)
{
{
B3_PROFILE("setAabb");
m_data->m_allAabbsGPU->copyToHost(m_data->m_allAabbsCPU);
- for (int i=0;i<m_data->m_allAabbsCPU.size();i++)
+ for (int i = 0; i < m_data->m_allAabbsCPU.size(); i++)
{
- b3Vector3 aabbMin=b3MakeVector3(m_data->m_allAabbsCPU[i].m_min[0],m_data->m_allAabbsCPU[i].m_min[1],m_data->m_allAabbsCPU[i].m_min[2]);
- b3Vector3 aabbMax=b3MakeVector3(m_data->m_allAabbsCPU[i].m_max[0],m_data->m_allAabbsCPU[i].m_max[1],m_data->m_allAabbsCPU[i].m_max[2]);
- m_data->m_broadphaseDbvt->setAabb(i,aabbMin,aabbMax,0);
+ b3Vector3 aabbMin = b3MakeVector3(m_data->m_allAabbsCPU[i].m_min[0], m_data->m_allAabbsCPU[i].m_min[1], m_data->m_allAabbsCPU[i].m_min[2]);
+ b3Vector3 aabbMax = b3MakeVector3(m_data->m_allAabbsCPU[i].m_max[0], m_data->m_allAabbsCPU[i].m_max[1], m_data->m_allAabbsCPU[i].m_max[2]);
+ m_data->m_broadphaseDbvt->setAabb(i, aabbMin, aabbMax, 0);
}
}
@@ -259,13 +248,14 @@ void b3GpuRigidBodyPipeline::stepSimulation(float deltaTime)
m_data->m_broadphaseDbvt->calculateOverlappingPairs();
}
numPairs = m_data->m_broadphaseDbvt->getOverlappingPairCache()->getNumOverlappingPairs();
-
- } else
+ }
+ else
{
if (gUseCalculateOverlappingPairsHost)
{
m_data->m_broadphaseSap->calculateOverlappingPairsHost(m_data->m_config.m_maxBroadphasePairs);
- } else
+ }
+ else
{
m_data->m_broadphaseSap->calculateOverlappingPairs(m_data->m_config.m_maxBroadphasePairs);
}
@@ -274,24 +264,24 @@ void b3GpuRigidBodyPipeline::stepSimulation(float deltaTime)
}
//compute contact points
-// printf("numPairs=%d\n",numPairs);
-
- int numContacts = 0;
+ // printf("numPairs=%d\n",numPairs);
+ int numContacts = 0;
int numBodies = m_data->m_narrowphase->getNumRigidBodies();
if (numPairs)
{
- cl_mem pairs =0;
- cl_mem aabbsWS =0;
+ cl_mem pairs = 0;
+ cl_mem aabbsWS = 0;
if (gUseDbvt)
{
B3_PROFILE("m_overlappingPairsGPU->copyFromHost");
m_data->m_overlappingPairsGPU->copyFromHost(m_data->m_broadphaseDbvt->getOverlappingPairCache()->getOverlappingPairArray());
pairs = m_data->m_overlappingPairsGPU->getBufferCL();
aabbsWS = m_data->m_allAabbsGPU->getBufferCL();
- } else
+ }
+ else
{
pairs = m_data->m_broadphaseSap->getOverlappingPairBuffer();
aabbsWS = m_data->m_broadphaseSap->getAabbBufferWS();
@@ -302,31 +292,27 @@ void b3GpuRigidBodyPipeline::stepSimulation(float deltaTime)
//mark the contacts for each pair as 'unused'
if (numPairs)
{
- b3OpenCLArray<b3BroadphasePair> gpuPairs(this->m_data->m_context,m_data->m_queue);
- gpuPairs.setFromOpenCLBuffer(pairs,numPairs);
+ b3OpenCLArray<b3BroadphasePair> gpuPairs(this->m_data->m_context, m_data->m_queue);
+ gpuPairs.setFromOpenCLBuffer(pairs, numPairs);
if (gClearPairsOnGpu)
{
-
-
//b3AlignedObjectArray<b3BroadphasePair> hostPairs;//just for debugging
//gpuPairs.copyToHost(hostPairs);
- b3LauncherCL launcher(m_data->m_queue,m_data->m_clearOverlappingPairsKernel,"clearOverlappingPairsKernel");
+ b3LauncherCL launcher(m_data->m_queue, m_data->m_clearOverlappingPairsKernel, "clearOverlappingPairsKernel");
launcher.setBuffer(pairs);
launcher.setConst(numPairs);
launcher.launch1D(numPairs);
-
//gpuPairs.copyToHost(hostPairs);
-
-
- } else
+ }
+ else
{
b3AlignedObjectArray<b3BroadphasePair> hostPairs;
gpuPairs.copyToHost(hostPairs);
- for (int i=0;i<hostPairs.size();i++)
+ for (int i = 0; i < hostPairs.size(); i++)
{
hostPairs[i].z = 0xffffffff;
}
@@ -335,7 +321,7 @@ void b3GpuRigidBodyPipeline::stepSimulation(float deltaTime)
}
}
- m_data->m_narrowphase->computeContacts(pairs,numPairs,aabbsWS,numBodies);
+ m_data->m_narrowphase->computeContacts(pairs, numPairs, aabbsWS, numBodies);
numContacts = m_data->m_narrowphase->getNumContactsGpu();
if (gUseDbvt)
@@ -347,56 +333,54 @@ void b3GpuRigidBodyPipeline::stepSimulation(float deltaTime)
if (gDumpContactStats && numContacts)
{
m_data->m_narrowphase->getContactsGpu();
-
+
printf("numContacts = %d\n", numContacts);
- int totalPoints = 0;
+ int totalPoints = 0;
const b3Contact4* contacts = m_data->m_narrowphase->getContactsCPU();
- for (int i=0;i<numContacts;i++)
+ for (int i = 0; i < numContacts; i++)
{
totalPoints += contacts->getNPoints();
}
- printf("totalPoints=%d\n",totalPoints);
-
+ printf("totalPoints=%d\n", totalPoints);
}
}
-
//convert contact points to contact constraints
-
+
//solve constraints
- b3OpenCLArray<b3RigidBodyData> gpuBodies(m_data->m_context,m_data->m_queue,0,true);
- gpuBodies.setFromOpenCLBuffer(m_data->m_narrowphase->getBodiesGpu(),m_data->m_narrowphase->getNumRigidBodies());
- b3OpenCLArray<b3InertiaData> gpuInertias(m_data->m_context,m_data->m_queue,0,true);
- gpuInertias.setFromOpenCLBuffer(m_data->m_narrowphase->getBodyInertiasGpu(),m_data->m_narrowphase->getNumRigidBodies());
- b3OpenCLArray<b3Contact4> gpuContacts(m_data->m_context,m_data->m_queue,0,true);
- gpuContacts.setFromOpenCLBuffer(m_data->m_narrowphase->getContactsGpu(),m_data->m_narrowphase->getNumContactsGpu());
+ b3OpenCLArray<b3RigidBodyData> gpuBodies(m_data->m_context, m_data->m_queue, 0, true);
+ gpuBodies.setFromOpenCLBuffer(m_data->m_narrowphase->getBodiesGpu(), m_data->m_narrowphase->getNumRigidBodies());
+ b3OpenCLArray<b3InertiaData> gpuInertias(m_data->m_context, m_data->m_queue, 0, true);
+ gpuInertias.setFromOpenCLBuffer(m_data->m_narrowphase->getBodyInertiasGpu(), m_data->m_narrowphase->getNumRigidBodies());
+ b3OpenCLArray<b3Contact4> gpuContacts(m_data->m_context, m_data->m_queue, 0, true);
+ gpuContacts.setFromOpenCLBuffer(m_data->m_narrowphase->getContactsGpu(), m_data->m_narrowphase->getNumContactsGpu());
- int numJoints = m_data->m_joints.size() ? m_data->m_joints.size() : m_data->m_cpuConstraints.size();
+ int numJoints = m_data->m_joints.size() ? m_data->m_joints.size() : m_data->m_cpuConstraints.size();
if (useBullet2CpuSolver && numJoints)
{
-
- // b3AlignedObjectArray<b3Contact4> hostContacts;
+ // b3AlignedObjectArray<b3Contact4> hostContacts;
//gpuContacts.copyToHost(hostContacts);
{
- bool useGpu = m_data->m_joints.size()==0;
+ bool useGpu = m_data->m_joints.size() == 0;
-// b3Contact4* contacts = numContacts? &hostContacts[0]: 0;
+ // b3Contact4* contacts = numContacts? &hostContacts[0]: 0;
//m_data->m_solver->solveContacts(m_data->m_narrowphase->getNumBodiesGpu(),&hostBodies[0],&hostInertias[0],numContacts,contacts,numJoints, joints);
if (useGpu)
{
- m_data->m_gpuSolver->solveJoints(m_data->m_narrowphase->getNumRigidBodies(),&gpuBodies,&gpuInertias,numJoints, m_data->m_gpuConstraints);
- } else
+ m_data->m_gpuSolver->solveJoints(m_data->m_narrowphase->getNumRigidBodies(), &gpuBodies, &gpuInertias, numJoints, m_data->m_gpuConstraints);
+ }
+ else
{
b3AlignedObjectArray<b3RigidBodyData> hostBodies;
gpuBodies.copyToHost(hostBodies);
b3AlignedObjectArray<b3InertiaData> hostInertias;
gpuInertias.copyToHost(hostInertias);
- b3TypedConstraint** joints = numJoints? &m_data->m_joints[0] : 0;
- m_data->m_solver->solveContacts(m_data->m_narrowphase->getNumRigidBodies(),&hostBodies[0],&hostInertias[0],0,0,numJoints, joints);
+ b3TypedConstraint** joints = numJoints ? &m_data->m_joints[0] : 0;
+ m_data->m_solver->solveContacts(m_data->m_narrowphase->getNumRigidBodies(), &hostBodies[0], &hostInertias[0], 0, 0, numJoints, joints);
gpuBodies.copyFromHost(hostBodies);
}
}
@@ -404,22 +388,20 @@ void b3GpuRigidBodyPipeline::stepSimulation(float deltaTime)
if (numContacts)
{
-
#ifdef TEST_OTHER_GPU_SOLVER
-
+
if (gUseJacobi)
{
bool useGpu = true;
if (useGpu)
{
-
bool forceHost = false;
if (forceHost)
{
b3AlignedObjectArray<b3RigidBodyData> hostBodies;
b3AlignedObjectArray<b3InertiaData> hostInertias;
b3AlignedObjectArray<b3Contact4> hostContacts;
-
+
{
B3_PROFILE("copyToHost");
gpuBodies.copyToHost(hostBodies);
@@ -429,25 +411,24 @@ void b3GpuRigidBodyPipeline::stepSimulation(float deltaTime)
{
b3JacobiSolverInfo solverInfo;
- m_data->m_solver3->solveGroupHost(&hostBodies[0], &hostInertias[0], hostBodies.size(),&hostContacts[0],hostContacts.size(),solverInfo);
-
-
+ m_data->m_solver3->solveGroupHost(&hostBodies[0], &hostInertias[0], hostBodies.size(), &hostContacts[0], hostContacts.size(), solverInfo);
}
{
B3_PROFILE("copyFromHost");
gpuBodies.copyFromHost(hostBodies);
}
- } else
-
+ }
+ else
{
int static0Index = m_data->m_narrowphase->getStatic0Index();
b3JacobiSolverInfo solverInfo;
//m_data->m_solver3->solveContacts( >solveGroup(&gpuBodies, &gpuInertias, &gpuContacts,solverInfo);
//m_data->m_solver3->solveContacts(m_data->m_narrowphase->getNumBodiesGpu(),&hostBodies[0],&hostInertias[0],numContacts,&hostContacts[0]);
- m_data->m_solver3->solveContacts(numBodies, gpuBodies.getBufferCL(),gpuInertias.getBufferCL(),numContacts, gpuContacts.getBufferCL(),m_data->m_config, static0Index);
+ m_data->m_solver3->solveContacts(numBodies, gpuBodies.getBufferCL(), gpuInertias.getBufferCL(), numContacts, gpuContacts.getBufferCL(), m_data->m_config, static0Index);
}
- } else
+ }
+ else
{
b3AlignedObjectArray<b3RigidBodyData> hostBodies;
gpuBodies.copyToHost(hostBodies);
@@ -460,17 +441,15 @@ void b3GpuRigidBodyPipeline::stepSimulation(float deltaTime)
}
gpuBodies.copyFromHost(hostBodies);
}
-
- } else
-#endif //TEST_OTHER_GPU_SOLVER
+ }
+ else
+#endif //TEST_OTHER_GPU_SOLVER
{
-
int static0Index = m_data->m_narrowphase->getStatic0Index();
- m_data->m_solver2->solveContacts(numBodies, gpuBodies.getBufferCL(),gpuInertias.getBufferCL(),numContacts, gpuContacts.getBufferCL(),m_data->m_config, static0Index);
-
+ m_data->m_solver2->solveContacts(numBodies, gpuBodies.getBufferCL(), gpuInertias.getBufferCL(), numContacts, gpuContacts.getBufferCL(), m_data->m_config, static0Index);
+
//m_data->m_solver4->solveContacts(m_data->m_narrowphase->getNumBodiesGpu(), gpuBodies.getBufferCL(), gpuInertias.getBufferCL(), numContacts, gpuContacts.getBufferCL());
-
-
+
/*m_data->m_solver3->solveContactConstraintHost(
(b3OpenCLArray<RigidBodyBase::Body>*)&gpuBodies,
(b3OpenCLArray<RigidBodyBase::Inertia>*)&gpuInertias,
@@ -481,11 +460,9 @@ void b3GpuRigidBodyPipeline::stepSimulation(float deltaTime)
}
integrate(deltaTime);
-
}
-
-void b3GpuRigidBodyPipeline::integrate(float timeStep)
+void b3GpuRigidBodyPipeline::integrate(float timeStep)
{
//integrate
int numBodies = m_data->m_narrowphase->getNumRigidBodies();
@@ -493,24 +470,25 @@ void b3GpuRigidBodyPipeline::integrate(float timeStep)
if (gIntegrateOnCpu)
{
- if(numBodies)
+ if (numBodies)
{
- b3GpuNarrowPhaseInternalData* npData = m_data->m_narrowphase->getInternalData();
+ b3GpuNarrowPhaseInternalData* npData = m_data->m_narrowphase->getInternalData();
npData->m_bodyBufferGPU->copyToHost(*npData->m_bodyBufferCPU);
b3RigidBodyData_t* bodies = &npData->m_bodyBufferCPU->at(0);
- for (int nodeID=0;nodeID<numBodies;nodeID++)
+ for (int nodeID = 0; nodeID < numBodies; nodeID++)
{
- integrateSingleTransform( bodies,nodeID, timeStep, angularDamp, m_data->m_gravity);
+ integrateSingleTransform(bodies, nodeID, timeStep, angularDamp, m_data->m_gravity);
}
npData->m_bodyBufferGPU->copyFromHost(*npData->m_bodyBufferCPU);
}
- } else
+ }
+ else
{
- b3LauncherCL launcher(m_data->m_queue,m_data->m_integrateTransformsKernel,"m_integrateTransformsKernel");
+ b3LauncherCL launcher(m_data->m_queue, m_data->m_integrateTransformsKernel, "m_integrateTransformsKernel");
launcher.setBuffer(m_data->m_narrowphase->getBodiesGpu());
-
+
launcher.setConst(numBodies);
launcher.setConst(timeStep);
launcher.setConst(angularDamp);
@@ -519,12 +497,9 @@ void b3GpuRigidBodyPipeline::integrate(float timeStep)
}
}
-
-
-
-void b3GpuRigidBodyPipeline::setupGpuAabbsFull()
+void b3GpuRigidBodyPipeline::setupGpuAabbsFull()
{
- cl_int ciErrNum=0;
+ cl_int ciErrNum = 0;
int numBodies = m_data->m_narrowphase->getNumRigidBodies();
if (!numBodies)
@@ -532,34 +507,35 @@ void b3GpuRigidBodyPipeline::setupGpuAabbsFull()
if (gCalcWorldSpaceAabbOnCpu)
{
-
if (numBodies)
{
if (gUseDbvt)
{
m_data->m_allAabbsCPU.resize(numBodies);
m_data->m_narrowphase->readbackAllBodiesToCpu();
- for (int i=0;i<numBodies;i++)
+ for (int i = 0; i < numBodies; i++)
{
- b3ComputeWorldAabb( i, m_data->m_narrowphase->getBodiesCpu(), m_data->m_narrowphase->getCollidablesCpu(), m_data->m_narrowphase->getLocalSpaceAabbsCpu(),&m_data->m_allAabbsCPU[0]);
+ b3ComputeWorldAabb(i, m_data->m_narrowphase->getBodiesCpu(), m_data->m_narrowphase->getCollidablesCpu(), m_data->m_narrowphase->getLocalSpaceAabbsCpu(), &m_data->m_allAabbsCPU[0]);
}
m_data->m_allAabbsGPU->copyFromHost(m_data->m_allAabbsCPU);
- } else
+ }
+ else
{
m_data->m_broadphaseSap->getAllAabbsCPU().resize(numBodies);
m_data->m_narrowphase->readbackAllBodiesToCpu();
- for (int i=0;i<numBodies;i++)
+ for (int i = 0; i < numBodies; i++)
{
- b3ComputeWorldAabb( i, m_data->m_narrowphase->getBodiesCpu(), m_data->m_narrowphase->getCollidablesCpu(), m_data->m_narrowphase->getLocalSpaceAabbsCpu(),&m_data->m_broadphaseSap->getAllAabbsCPU()[0]);
+ b3ComputeWorldAabb(i, m_data->m_narrowphase->getBodiesCpu(), m_data->m_narrowphase->getCollidablesCpu(), m_data->m_narrowphase->getLocalSpaceAabbsCpu(), &m_data->m_broadphaseSap->getAllAabbsCPU()[0]);
}
m_data->m_broadphaseSap->getAllAabbsGPU().copyFromHost(m_data->m_broadphaseSap->getAllAabbsCPU());
//m_data->m_broadphaseSap->writeAabbsToGpu();
}
}
- } else
+ }
+ else
{
//__kernel void initializeGpuAabbsFull( const int numNodes, __global Body* gBodies,__global Collidable* collidables, __global b3AABBCL* plocalShapeAABB, __global b3AABBCL* pAABB)
- b3LauncherCL launcher(m_data->m_queue,m_data->m_updateAabbsKernel,"m_updateAabbsKernel");
+ b3LauncherCL launcher(m_data->m_queue, m_data->m_updateAabbsKernel, "m_updateAabbsKernel");
launcher.setConst(numBodies);
cl_mem bodies = m_data->m_narrowphase->getBodiesGpu();
launcher.setBuffer(bodies);
@@ -568,17 +544,18 @@ void b3GpuRigidBodyPipeline::setupGpuAabbsFull()
cl_mem localAabbs = m_data->m_narrowphase->getAabbLocalSpaceBufferGpu();
launcher.setBuffer(localAabbs);
- cl_mem worldAabbs =0;
+ cl_mem worldAabbs = 0;
if (gUseDbvt)
{
worldAabbs = m_data->m_allAabbsGPU->getBufferCL();
- } else
+ }
+ else
{
worldAabbs = m_data->m_broadphaseSap->getAabbBufferWS();
}
launcher.setBuffer(worldAabbs);
launcher.launch1D(numBodies);
-
+
oclCHECKERROR(ciErrNum, CL_SUCCESS);
}
@@ -595,78 +572,68 @@ void b3GpuRigidBodyPipeline::setupGpuAabbsFull()
};
*/
-
-
-
-
-
}
-
-
-cl_mem b3GpuRigidBodyPipeline::getBodyBuffer()
+cl_mem b3GpuRigidBodyPipeline::getBodyBuffer()
{
return m_data->m_narrowphase->getBodiesGpu();
}
-int b3GpuRigidBodyPipeline::getNumBodies() const
+int b3GpuRigidBodyPipeline::getNumBodies() const
{
return m_data->m_narrowphase->getNumRigidBodies();
}
-void b3GpuRigidBodyPipeline::setGravity(const float* grav)
+void b3GpuRigidBodyPipeline::setGravity(const float* grav)
{
- m_data->m_gravity.setValue(grav[0],grav[1],grav[2]);
+ m_data->m_gravity.setValue(grav[0], grav[1], grav[2]);
}
-void b3GpuRigidBodyPipeline::copyConstraintsToHost()
+void b3GpuRigidBodyPipeline::copyConstraintsToHost()
{
m_data->m_gpuConstraints->copyToHost(m_data->m_cpuConstraints);
}
-void b3GpuRigidBodyPipeline::writeAllInstancesToGpu()
+void b3GpuRigidBodyPipeline::writeAllInstancesToGpu()
{
m_data->m_allAabbsGPU->copyFromHost(m_data->m_allAabbsCPU);
m_data->m_gpuConstraints->copyFromHost(m_data->m_cpuConstraints);
}
-
-int b3GpuRigidBodyPipeline::registerPhysicsInstance(float mass, const float* position, const float* orientation, int collidableIndex, int userIndex, bool writeInstanceToGpu)
+int b3GpuRigidBodyPipeline::registerPhysicsInstance(float mass, const float* position, const float* orientation, int collidableIndex, int userIndex, bool writeInstanceToGpu)
{
-
- b3Vector3 aabbMin=b3MakeVector3(0,0,0),aabbMax=b3MakeVector3(0,0,0);
+ b3Vector3 aabbMin = b3MakeVector3(0, 0, 0), aabbMax = b3MakeVector3(0, 0, 0);
-
- if (collidableIndex>=0)
+ if (collidableIndex >= 0)
{
b3SapAabb localAabb = m_data->m_narrowphase->getLocalSpaceAabb(collidableIndex);
- b3Vector3 localAabbMin=b3MakeVector3(localAabb.m_min[0],localAabb.m_min[1],localAabb.m_min[2]);
- b3Vector3 localAabbMax=b3MakeVector3(localAabb.m_max[0],localAabb.m_max[1],localAabb.m_max[2]);
-
+ b3Vector3 localAabbMin = b3MakeVector3(localAabb.m_min[0], localAabb.m_min[1], localAabb.m_min[2]);
+ b3Vector3 localAabbMax = b3MakeVector3(localAabb.m_max[0], localAabb.m_max[1], localAabb.m_max[2]);
+
b3Scalar margin = 0.01f;
b3Transform t;
t.setIdentity();
- t.setOrigin(b3MakeVector3(position[0],position[1],position[2]));
- t.setRotation(b3Quaternion(orientation[0],orientation[1],orientation[2],orientation[3]));
- b3TransformAabb(localAabbMin,localAabbMax, margin,t,aabbMin,aabbMax);
- } else
+ t.setOrigin(b3MakeVector3(position[0], position[1], position[2]));
+ t.setRotation(b3Quaternion(orientation[0], orientation[1], orientation[2], orientation[3]));
+ b3TransformAabb(localAabbMin, localAabbMax, margin, t, aabbMin, aabbMax);
+ }
+ else
{
b3Error("registerPhysicsInstance using invalid collidableIndex\n");
return -1;
}
-
-
+
bool writeToGpu = false;
int bodyIndex = m_data->m_narrowphase->getNumRigidBodies();
- bodyIndex = m_data->m_narrowphase->registerRigidBody(collidableIndex,mass,position,orientation,&aabbMin.getX(),&aabbMax.getX(),writeToGpu);
+ bodyIndex = m_data->m_narrowphase->registerRigidBody(collidableIndex, mass, position, orientation, &aabbMin.getX(), &aabbMax.getX(), writeToGpu);
- if (bodyIndex>=0)
+ if (bodyIndex >= 0)
{
if (gUseDbvt)
{
- m_data->m_broadphaseDbvt->createProxy(aabbMin,aabbMax,bodyIndex,0,1,1);
+ m_data->m_broadphaseDbvt->createProxy(aabbMin, aabbMax, bodyIndex, 0, 1, 1);
b3SapAabb aabb;
- for (int i=0;i<3;i++)
+ for (int i = 0; i < 3; i++)
{
aabb.m_min[i] = aabbMin[i];
aabb.m_max[i] = aabbMax[i];
@@ -677,14 +644,16 @@ int b3GpuRigidBodyPipeline::registerPhysicsInstance(float mass, const float* po
{
m_data->m_allAabbsGPU->copyFromHost(m_data->m_allAabbsCPU);
}
- } else
+ }
+ else
{
if (mass)
{
- m_data->m_broadphaseSap->createProxy(aabbMin,aabbMax,bodyIndex,1,1);//m_dispatcher);
- } else
+ m_data->m_broadphaseSap->createProxy(aabbMin, aabbMax, bodyIndex, 1, 1); //m_dispatcher);
+ }
+ else
{
- m_data->m_broadphaseSap->createLargeProxy(aabbMin,aabbMax,bodyIndex,1,1);//m_dispatcher);
+ m_data->m_broadphaseSap->createLargeProxy(aabbMin, aabbMax, bodyIndex, 1, 1); //m_dispatcher);
}
}
}
@@ -699,10 +668,10 @@ int b3GpuRigidBodyPipeline::registerPhysicsInstance(float mass, const float* po
return bodyIndex;
}
-void b3GpuRigidBodyPipeline::castRays(const b3AlignedObjectArray<b3RayInfo>& rays, b3AlignedObjectArray<b3RayHit>& hitResults)
+void b3GpuRigidBodyPipeline::castRays(const b3AlignedObjectArray<b3RayInfo>& rays, b3AlignedObjectArray<b3RayHit>& hitResults)
{
- this->m_data->m_raycaster->castRays(rays,hitResults,
- getNumBodies(),this->m_data->m_narrowphase->getBodiesCpu(),
- m_data->m_narrowphase->getNumCollidablesGpu(), m_data->m_narrowphase->getCollidablesCpu(),
- m_data->m_narrowphase->getInternalData(), m_data->m_broadphaseSap);
+ this->m_data->m_raycaster->castRays(rays, hitResults,
+ getNumBodies(), this->m_data->m_narrowphase->getBodiesCpu(),
+ m_data->m_narrowphase->getNumCollidablesGpu(), m_data->m_narrowphase->getCollidablesCpu(),
+ m_data->m_narrowphase->getInternalData(), m_data->m_broadphaseSap);
}
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipeline.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipeline.h
index b4eac6841a..0e5c6fec12 100644
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipeline.h
+++ b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipeline.h
@@ -25,50 +25,46 @@ subject to the following restrictions:
class b3GpuRigidBodyPipeline
{
protected:
- struct b3GpuRigidBodyPipelineInternalData* m_data;
+ struct b3GpuRigidBodyPipelineInternalData* m_data;
int allocateCollidable();
public:
-
-
- b3GpuRigidBodyPipeline(cl_context ctx,cl_device_id device, cl_command_queue q , class b3GpuNarrowPhase* narrowphase, class b3GpuBroadphaseInterface* broadphaseSap, struct b3DynamicBvhBroadphase* broadphaseDbvt, const b3Config& config);
+ b3GpuRigidBodyPipeline(cl_context ctx, cl_device_id device, cl_command_queue q, class b3GpuNarrowPhase* narrowphase, class b3GpuBroadphaseInterface* broadphaseSap, struct b3DynamicBvhBroadphase* broadphaseDbvt, const b3Config& config);
virtual ~b3GpuRigidBodyPipeline();
- void stepSimulation(float deltaTime);
- void integrate(float timeStep);
- void setupGpuAabbsFull();
+ void stepSimulation(float deltaTime);
+ void integrate(float timeStep);
+ void setupGpuAabbsFull();
- int registerConvexPolyhedron(class b3ConvexUtility* convex);
+ int registerConvexPolyhedron(class b3ConvexUtility* convex);
//int registerConvexPolyhedron(const float* vertices, int strideInBytes, int numVertices, const float* scaling);
//int registerSphereShape(float radius);
//int registerPlaneShape(const b3Vector3& planeNormal, float planeConstant);
-
+
//int registerConcaveMesh(b3AlignedObjectArray<b3Vector3>* vertices, b3AlignedObjectArray<int>* indices, const float* scaling);
//int registerCompoundShape(b3AlignedObjectArray<b3GpuChildShape>* childShapes);
-
- int registerPhysicsInstance(float mass, const float* position, const float* orientation, int collisionShapeIndex, int userData, bool writeInstanceToGpu);
+ int registerPhysicsInstance(float mass, const float* position, const float* orientation, int collisionShapeIndex, int userData, bool writeInstanceToGpu);
//if you passed "writeInstanceToGpu" false in the registerPhysicsInstance method (for performance) you need to call writeAllInstancesToGpu after all instances are registered
- void writeAllInstancesToGpu();
- void copyConstraintsToHost();
- void setGravity(const float* grav);
+ void writeAllInstancesToGpu();
+ void copyConstraintsToHost();
+ void setGravity(const float* grav);
void reset();
-
- int createPoint2PointConstraint(int bodyA, int bodyB, const float* pivotInA, const float* pivotInB,float breakingThreshold);
+
+ int createPoint2PointConstraint(int bodyA, int bodyB, const float* pivotInA, const float* pivotInB, float breakingThreshold);
int createFixedConstraint(int bodyA, int bodyB, const float* pivotInA, const float* pivotInB, const float* relTargetAB, float breakingThreshold);
void removeConstraintByUid(int uid);
- void addConstraint(class b3TypedConstraint* constraint);
- void removeConstraint(b3TypedConstraint* constraint);
-
- void castRays(const b3AlignedObjectArray<b3RayInfo>& rays, b3AlignedObjectArray<b3RayHit>& hitResults);
+ void addConstraint(class b3TypedConstraint* constraint);
+ void removeConstraint(b3TypedConstraint* constraint);
- cl_mem getBodyBuffer();
+ void castRays(const b3AlignedObjectArray<b3RayInfo>& rays, b3AlignedObjectArray<b3RayHit>& hitResults);
- int getNumBodies() const;
+ cl_mem getBodyBuffer();
+ int getNumBodies() const;
};
-#endif //B3_GPU_RIGIDBODY_PIPELINE_H \ No newline at end of file
+#endif //B3_GPU_RIGIDBODY_PIPELINE_H \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipelineInternalData.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipelineInternalData.h
index 5ac92f97d6..e0a26fda17 100644
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipelineInternalData.h
+++ b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipelineInternalData.h
@@ -22,52 +22,47 @@ subject to the following restrictions:
#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
-
#include "Bullet3OpenCL/BroadphaseCollision/b3SapAabb.h"
#include "Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.h"
#include "Bullet3Collision/NarrowPhaseCollision/b3Config.h"
-
-
#include "Bullet3Collision/BroadPhaseCollision/b3OverlappingPair.h"
#include "Bullet3OpenCL/RigidBody/b3GpuGenericConstraint.h"
struct b3GpuRigidBodyPipelineInternalData
{
+ cl_context m_context;
+ cl_device_id m_device;
+ cl_command_queue m_queue;
- cl_context m_context;
- cl_device_id m_device;
- cl_command_queue m_queue;
+ cl_kernel m_integrateTransformsKernel;
+ cl_kernel m_updateAabbsKernel;
+ cl_kernel m_clearOverlappingPairsKernel;
- cl_kernel m_integrateTransformsKernel;
- cl_kernel m_updateAabbsKernel;
- cl_kernel m_clearOverlappingPairsKernel;
-
class b3PgsJacobiSolver* m_solver;
-
+
class b3GpuPgsConstraintSolver* m_gpuSolver;
class b3GpuPgsContactSolver* m_solver2;
class b3GpuJacobiContactSolver* m_solver3;
class b3GpuRaycast* m_raycaster;
-
+
class b3GpuBroadphaseInterface* m_broadphaseSap;
-
+
struct b3DynamicBvhBroadphase* m_broadphaseDbvt;
- b3OpenCLArray<b3SapAabb>* m_allAabbsGPU;
- b3AlignedObjectArray<b3SapAabb> m_allAabbsCPU;
- b3OpenCLArray<b3BroadphasePair>* m_overlappingPairsGPU;
+ b3OpenCLArray<b3SapAabb>* m_allAabbsGPU;
+ b3AlignedObjectArray<b3SapAabb> m_allAabbsCPU;
+ b3OpenCLArray<b3BroadphasePair>* m_overlappingPairsGPU;
b3OpenCLArray<b3GpuGenericConstraint>* m_gpuConstraints;
b3AlignedObjectArray<b3GpuGenericConstraint> m_cpuConstraints;
b3AlignedObjectArray<b3TypedConstraint*> m_joints;
- int m_constraintUid;
- class b3GpuNarrowPhase* m_narrowphase;
- b3Vector3 m_gravity;
+ int m_constraintUid;
+ class b3GpuNarrowPhase* m_narrowphase;
+ b3Vector3 m_gravity;
- b3Config m_config;
+ b3Config m_config;
};
-#endif //B3_GPU_RIGIDBODY_PIPELINE_INTERNAL_DATA_H
-
+#endif //B3_GPU_RIGIDBODY_PIPELINE_INTERNAL_DATA_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuSolverBody.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuSolverBody.h
index f2a61801ac..db815d9b31 100644
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuSolverBody.h
+++ b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuSolverBody.h
@@ -13,11 +13,9 @@ subject to the following restrictions:
*/
//Originally written by Erwin Coumans
-
#ifndef B3_GPU_SOLVER_BODY_H
#define B3_GPU_SOLVER_BODY_H
-
#include "Bullet3Common/b3Vector3.h"
#include "Bullet3Common/b3Matrix3x3.h"
@@ -27,29 +25,27 @@ subject to the following restrictions:
///Until we get other contributions, only use SIMD on Windows, when using Visual Studio 2008 or later, and not double precision
#ifdef B3_USE_SSE
#define USE_SIMD 1
-#endif //
-
-
+#endif //
///The b3SolverBody is an internal datastructure for the constraint solver. Only necessary data is packed to increase cache coherence/performance.
-B3_ATTRIBUTE_ALIGNED16 (struct) b3GpuSolverBody
+B3_ATTRIBUTE_ALIGNED16(struct)
+b3GpuSolverBody
{
B3_DECLARE_ALIGNED_ALLOCATOR();
-// b3Transform m_worldTransformUnused;
- b3Vector3 m_deltaLinearVelocity;
- b3Vector3 m_deltaAngularVelocity;
- b3Vector3 m_angularFactor;
- b3Vector3 m_linearFactor;
- b3Vector3 m_invMass;
- b3Vector3 m_pushVelocity;
- b3Vector3 m_turnVelocity;
- b3Vector3 m_linearVelocity;
- b3Vector3 m_angularVelocity;
-
- union
- {
- void* m_originalBody;
- int m_originalBodyIndex;
+ // b3Transform m_worldTransformUnused;
+ b3Vector3 m_deltaLinearVelocity;
+ b3Vector3 m_deltaAngularVelocity;
+ b3Vector3 m_angularFactor;
+ b3Vector3 m_linearFactor;
+ b3Vector3 m_invMass;
+ b3Vector3 m_pushVelocity;
+ b3Vector3 m_turnVelocity;
+ b3Vector3 m_linearVelocity;
+ b3Vector3 m_angularVelocity;
+
+ union {
+ void* m_originalBody;
+ int m_originalBodyIndex;
};
int padding[3];
@@ -65,44 +61,41 @@ B3_ATTRIBUTE_ALIGNED16 (struct) b3GpuSolverBody
return m_worldTransform;
}
*/
- B3_FORCE_INLINE void getVelocityInLocalPointObsolete(const b3Vector3& rel_pos, b3Vector3& velocity ) const
+ B3_FORCE_INLINE void getVelocityInLocalPointObsolete(const b3Vector3& rel_pos, b3Vector3& velocity) const
{
if (m_originalBody)
- velocity = m_linearVelocity+m_deltaLinearVelocity + (m_angularVelocity+m_deltaAngularVelocity).cross(rel_pos);
+ velocity = m_linearVelocity + m_deltaLinearVelocity + (m_angularVelocity + m_deltaAngularVelocity).cross(rel_pos);
else
- velocity.setValue(0,0,0);
+ velocity.setValue(0, 0, 0);
}
- B3_FORCE_INLINE void getAngularVelocity(b3Vector3& angVel) const
+ B3_FORCE_INLINE void getAngularVelocity(b3Vector3 & angVel) const
{
if (m_originalBody)
- angVel =m_angularVelocity+m_deltaAngularVelocity;
+ angVel = m_angularVelocity + m_deltaAngularVelocity;
else
- angVel.setValue(0,0,0);
+ angVel.setValue(0, 0, 0);
}
-
//Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position
- B3_FORCE_INLINE void applyImpulse(const b3Vector3& linearComponent, const b3Vector3& angularComponent,const b3Scalar impulseMagnitude)
+ B3_FORCE_INLINE void applyImpulse(const b3Vector3& linearComponent, const b3Vector3& angularComponent, const b3Scalar impulseMagnitude)
{
if (m_originalBody)
{
- m_deltaLinearVelocity += linearComponent*impulseMagnitude*m_linearFactor;
- m_deltaAngularVelocity += angularComponent*(impulseMagnitude*m_angularFactor);
+ m_deltaLinearVelocity += linearComponent * impulseMagnitude * m_linearFactor;
+ m_deltaAngularVelocity += angularComponent * (impulseMagnitude * m_angularFactor);
}
}
- B3_FORCE_INLINE void internalApplyPushImpulse(const b3Vector3& linearComponent, const b3Vector3& angularComponent,b3Scalar impulseMagnitude)
+ B3_FORCE_INLINE void internalApplyPushImpulse(const b3Vector3& linearComponent, const b3Vector3& angularComponent, b3Scalar impulseMagnitude)
{
if (m_originalBody)
{
- m_pushVelocity += linearComponent*impulseMagnitude*m_linearFactor;
- m_turnVelocity += angularComponent*(impulseMagnitude*m_angularFactor);
+ m_pushVelocity += linearComponent * impulseMagnitude * m_linearFactor;
+ m_turnVelocity += angularComponent * (impulseMagnitude * m_angularFactor);
}
}
-
-
const b3Vector3& getDeltaLinearVelocity() const
{
return m_deltaLinearVelocity;
@@ -113,20 +106,19 @@ B3_ATTRIBUTE_ALIGNED16 (struct) b3GpuSolverBody
return m_deltaAngularVelocity;
}
- const b3Vector3& getPushVelocity() const
+ const b3Vector3& getPushVelocity() const
{
return m_pushVelocity;
}
- const b3Vector3& getTurnVelocity() const
+ const b3Vector3& getTurnVelocity() const
{
return m_turnVelocity;
}
-
////////////////////////////////////////////////
///some internal methods, don't use them
-
+
b3Vector3& internalGetDeltaLinearVelocity()
{
return m_deltaLinearVelocity;
@@ -151,7 +143,7 @@ B3_ATTRIBUTE_ALIGNED16 (struct) b3GpuSolverBody
{
m_invMass = invMass;
}
-
+
b3Vector3& internalGetPushVelocity()
{
return m_pushVelocity;
@@ -162,67 +154,57 @@ B3_ATTRIBUTE_ALIGNED16 (struct) b3GpuSolverBody
return m_turnVelocity;
}
- B3_FORCE_INLINE void internalGetVelocityInLocalPointObsolete(const b3Vector3& rel_pos, b3Vector3& velocity ) const
+ B3_FORCE_INLINE void internalGetVelocityInLocalPointObsolete(const b3Vector3& rel_pos, b3Vector3& velocity) const
{
- velocity = m_linearVelocity+m_deltaLinearVelocity + (m_angularVelocity+m_deltaAngularVelocity).cross(rel_pos);
+ velocity = m_linearVelocity + m_deltaLinearVelocity + (m_angularVelocity + m_deltaAngularVelocity).cross(rel_pos);
}
- B3_FORCE_INLINE void internalGetAngularVelocity(b3Vector3& angVel) const
+ B3_FORCE_INLINE void internalGetAngularVelocity(b3Vector3 & angVel) const
{
- angVel = m_angularVelocity+m_deltaAngularVelocity;
+ angVel = m_angularVelocity + m_deltaAngularVelocity;
}
-
//Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position
- B3_FORCE_INLINE void internalApplyImpulse(const b3Vector3& linearComponent, const b3Vector3& angularComponent,const b3Scalar impulseMagnitude)
+ B3_FORCE_INLINE void internalApplyImpulse(const b3Vector3& linearComponent, const b3Vector3& angularComponent, const b3Scalar impulseMagnitude)
{
//if (m_originalBody)
{
- m_deltaLinearVelocity += linearComponent*impulseMagnitude*m_linearFactor;
- m_deltaAngularVelocity += angularComponent*(impulseMagnitude*m_angularFactor);
+ m_deltaLinearVelocity += linearComponent * impulseMagnitude * m_linearFactor;
+ m_deltaAngularVelocity += angularComponent * (impulseMagnitude * m_angularFactor);
}
}
-
-
-
- void writebackVelocity()
+ void writebackVelocity()
{
//if (m_originalBody>=0)
{
- m_linearVelocity +=m_deltaLinearVelocity;
+ m_linearVelocity += m_deltaLinearVelocity;
m_angularVelocity += m_deltaAngularVelocity;
-
+
//m_originalBody->setCompanionId(-1);
}
}
-
- void writebackVelocityAndTransform(b3Scalar timeStep, b3Scalar splitImpulseTurnErp)
+ void writebackVelocityAndTransform(b3Scalar timeStep, b3Scalar splitImpulseTurnErp)
{
- (void) timeStep;
+ (void)timeStep;
if (m_originalBody)
{
m_linearVelocity += m_deltaLinearVelocity;
m_angularVelocity += m_deltaAngularVelocity;
-
+
//correct the position/orientation based on push/turn recovery
b3Transform newTransform;
- if (m_pushVelocity[0]!=0.f || m_pushVelocity[1]!=0 || m_pushVelocity[2]!=0 || m_turnVelocity[0]!=0.f || m_turnVelocity[1]!=0 || m_turnVelocity[2]!=0)
+ if (m_pushVelocity[0] != 0.f || m_pushVelocity[1] != 0 || m_pushVelocity[2] != 0 || m_turnVelocity[0] != 0.f || m_turnVelocity[1] != 0 || m_turnVelocity[2] != 0)
{
- // b3Quaternion orn = m_worldTransform.getRotation();
-// b3TransformUtil::integrateTransform(m_worldTransform,m_pushVelocity,m_turnVelocity*splitImpulseTurnErp,timeStep,newTransform);
-// m_worldTransform = newTransform;
+ // b3Quaternion orn = m_worldTransform.getRotation();
+ // b3TransformUtil::integrateTransform(m_worldTransform,m_pushVelocity,m_turnVelocity*splitImpulseTurnErp,timeStep,newTransform);
+ // m_worldTransform = newTransform;
}
//m_worldTransform.setRotation(orn);
//m_originalBody->setCompanionId(-1);
}
}
-
-
-
};
-#endif //B3_SOLVER_BODY_H
-
-
+#endif //B3_SOLVER_BODY_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuSolverConstraint.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuSolverConstraint.h
index 60d235baab..7d9eea243a 100644
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuSolverConstraint.h
+++ b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuSolverConstraint.h
@@ -13,11 +13,9 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#ifndef B3_GPU_SOLVER_CONSTRAINT_H
#define B3_GPU_SOLVER_CONSTRAINT_H
-
#include "Bullet3Common/b3Vector3.h"
#include "Bullet3Common/b3Matrix3x3.h"
//#include "b3JacobianEntry.h"
@@ -25,58 +23,51 @@ subject to the following restrictions:
//#define NO_FRICTION_TANGENTIALS 1
-
-
///1D constraint along a normal axis between bodyA and bodyB. It can be combined to solve contact and friction constraints.
-B3_ATTRIBUTE_ALIGNED16 (struct) b3GpuSolverConstraint
+B3_ATTRIBUTE_ALIGNED16(struct)
+b3GpuSolverConstraint
{
B3_DECLARE_ALIGNED_ALLOCATOR();
- b3Vector3 m_relpos1CrossNormal;
- b3Vector3 m_contactNormal;
+ b3Vector3 m_relpos1CrossNormal;
+ b3Vector3 m_contactNormal;
- b3Vector3 m_relpos2CrossNormal;
+ b3Vector3 m_relpos2CrossNormal;
//b3Vector3 m_contactNormal2;//usually m_contactNormal2 == -m_contactNormal
- b3Vector3 m_angularComponentA;
- b3Vector3 m_angularComponentB;
-
- mutable b3Scalar m_appliedPushImpulse;
- mutable b3Scalar m_appliedImpulse;
+ b3Vector3 m_angularComponentA;
+ b3Vector3 m_angularComponentB;
+
+ mutable b3Scalar m_appliedPushImpulse;
+ mutable b3Scalar m_appliedImpulse;
int m_padding1;
int m_padding2;
- b3Scalar m_friction;
- b3Scalar m_jacDiagABInv;
- b3Scalar m_rhs;
- b3Scalar m_cfm;
-
- b3Scalar m_lowerLimit;
- b3Scalar m_upperLimit;
- b3Scalar m_rhsPenetration;
- union
- {
- void* m_originalContactPoint;
- int m_originalConstraintIndex;
- b3Scalar m_unusedPadding4;
+ b3Scalar m_friction;
+ b3Scalar m_jacDiagABInv;
+ b3Scalar m_rhs;
+ b3Scalar m_cfm;
+
+ b3Scalar m_lowerLimit;
+ b3Scalar m_upperLimit;
+ b3Scalar m_rhsPenetration;
+ union {
+ void* m_originalContactPoint;
+ int m_originalConstraintIndex;
+ b3Scalar m_unusedPadding4;
};
- int m_overrideNumSolverIterations;
- int m_frictionIndex;
+ int m_overrideNumSolverIterations;
+ int m_frictionIndex;
int m_solverBodyIdA;
int m_solverBodyIdB;
-
- enum b3SolverConstraintType
+ enum b3SolverConstraintType
{
B3_SOLVER_CONTACT_1D = 0,
B3_SOLVER_FRICTION_1D
};
};
-typedef b3AlignedObjectArray<b3GpuSolverConstraint> b3GpuConstraintArray;
-
-
-#endif //B3_GPU_SOLVER_CONSTRAINT_H
-
-
+typedef b3AlignedObjectArray<b3GpuSolverConstraint> b3GpuConstraintArray;
+#endif //B3_GPU_SOLVER_CONSTRAINT_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3Solver.cpp b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3Solver.cpp
index 20bf6d47c5..ccf67da1a8 100644
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3Solver.cpp
+++ b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3Solver.cpp
@@ -13,7 +13,6 @@ subject to the following restrictions:
*/
//Originally written by Takahiro Harada
-
#include "b3Solver.h"
///useNewBatchingKernel is a rewritten kernel using just a single thread of the warp, for experiments
@@ -38,7 +37,6 @@ bool gConvertConstraintOnCpu = false;
#include "kernels/batchingKernels.h"
#include "kernels/batchingKernelsNew.h"
-
#include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
#include "Bullet3Common/b3Vector3.h"
@@ -48,7 +46,7 @@ struct SolverDebugInfo
int m_valInt1;
int m_valInt2;
int m_valInt3;
-
+
int m_valInt4;
int m_valInt5;
int m_valInt6;
@@ -59,11 +57,10 @@ struct SolverDebugInfo
int m_valInt10;
int m_valInt11;
- int m_valInt12;
- int m_valInt13;
- int m_valInt14;
- int m_valInt15;
-
+ int m_valInt12;
+ int m_valInt13;
+ int m_valInt14;
+ int m_valInt15;
float m_val0;
float m_val1;
@@ -71,9 +68,6 @@ struct SolverDebugInfo
float m_val3;
};
-
-
-
class SolverDeviceInl
{
public:
@@ -84,101 +78,89 @@ public:
};
};
-
-
b3Solver::b3Solver(cl_context ctx, cl_device_id device, cl_command_queue queue, int pairCapacity)
- :
- m_context(ctx),
- m_device(device),
- m_queue(queue),
- m_batchSizes(ctx,queue),
- m_nIterations(4)
+ : m_context(ctx),
+ m_device(device),
+ m_queue(queue),
+ m_batchSizes(ctx, queue),
+ m_nIterations(4)
{
- m_sort32 = new b3RadixSort32CL(ctx,device,queue);
- m_scan = new b3PrefixScanCL(ctx,device,queue,B3_SOLVER_N_CELLS);
- m_search = new b3BoundSearchCL(ctx,device,queue,B3_SOLVER_N_CELLS);
+ m_sort32 = new b3RadixSort32CL(ctx, device, queue);
+ m_scan = new b3PrefixScanCL(ctx, device, queue, B3_SOLVER_N_CELLS);
+ m_search = new b3BoundSearchCL(ctx, device, queue, B3_SOLVER_N_CELLS);
- const int sortSize = B3NEXTMULTIPLEOF( pairCapacity, 512 );
+ const int sortSize = B3NEXTMULTIPLEOF(pairCapacity, 512);
- m_sortDataBuffer = new b3OpenCLArray<b3SortData>(ctx,queue,sortSize);
- m_contactBuffer2 = new b3OpenCLArray<b3Contact4>(ctx,queue);
+ m_sortDataBuffer = new b3OpenCLArray<b3SortData>(ctx, queue, sortSize);
+ m_contactBuffer2 = new b3OpenCLArray<b3Contact4>(ctx, queue);
- m_numConstraints = new b3OpenCLArray<unsigned int>(ctx,queue,B3_SOLVER_N_CELLS );
+ m_numConstraints = new b3OpenCLArray<unsigned int>(ctx, queue, B3_SOLVER_N_CELLS);
m_numConstraints->resize(B3_SOLVER_N_CELLS);
- m_offsets = new b3OpenCLArray<unsigned int>( ctx,queue,B3_SOLVER_N_CELLS);
+ m_offsets = new b3OpenCLArray<unsigned int>(ctx, queue, B3_SOLVER_N_CELLS);
m_offsets->resize(B3_SOLVER_N_CELLS);
const char* additionalMacros = "";
-// const char* srcFileNameForCaching="";
-
-
+ // const char* srcFileNameForCaching="";
cl_int pErrNum;
const char* batchKernelSource = batchingKernelsCL;
const char* batchKernelNewSource = batchingKernelsNewCL;
-
+
const char* solverSetupSource = solverSetupCL;
const char* solverSetup2Source = solverSetup2CL;
const char* solveContactSource = solveContactCL;
const char* solveFrictionSource = solveFrictionCL;
-
-
-
+
{
-
- cl_program solveContactProg= b3OpenCLUtils::compileCLProgramFromString( ctx, device, solveContactSource, &pErrNum,additionalMacros, B3_SOLVER_CONTACT_KERNEL_PATH);
+ cl_program solveContactProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, solveContactSource, &pErrNum, additionalMacros, B3_SOLVER_CONTACT_KERNEL_PATH);
b3Assert(solveContactProg);
-
- cl_program solveFrictionProg= b3OpenCLUtils::compileCLProgramFromString( ctx, device, solveFrictionSource, &pErrNum,additionalMacros, B3_SOLVER_FRICTION_KERNEL_PATH);
+
+ cl_program solveFrictionProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, solveFrictionSource, &pErrNum, additionalMacros, B3_SOLVER_FRICTION_KERNEL_PATH);
b3Assert(solveFrictionProg);
- cl_program solverSetup2Prog= b3OpenCLUtils::compileCLProgramFromString( ctx, device, solverSetup2Source, &pErrNum,additionalMacros, B3_SOLVER_SETUP2_KERNEL_PATH);
+ cl_program solverSetup2Prog = b3OpenCLUtils::compileCLProgramFromString(ctx, device, solverSetup2Source, &pErrNum, additionalMacros, B3_SOLVER_SETUP2_KERNEL_PATH);
b3Assert(solverSetup2Prog);
-
- cl_program solverSetupProg= b3OpenCLUtils::compileCLProgramFromString( ctx, device, solverSetupSource, &pErrNum,additionalMacros, B3_SOLVER_SETUP_KERNEL_PATH);
+ cl_program solverSetupProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, solverSetupSource, &pErrNum, additionalMacros, B3_SOLVER_SETUP_KERNEL_PATH);
b3Assert(solverSetupProg);
-
-
- m_solveFrictionKernel= b3OpenCLUtils::compileCLKernelFromString( ctx, device, solveFrictionSource, "BatchSolveKernelFriction", &pErrNum, solveFrictionProg,additionalMacros );
+
+ m_solveFrictionKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solveFrictionSource, "BatchSolveKernelFriction", &pErrNum, solveFrictionProg, additionalMacros);
b3Assert(m_solveFrictionKernel);
- m_solveContactKernel= b3OpenCLUtils::compileCLKernelFromString( ctx, device, solveContactSource, "BatchSolveKernelContact", &pErrNum, solveContactProg,additionalMacros );
+ m_solveContactKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solveContactSource, "BatchSolveKernelContact", &pErrNum, solveContactProg, additionalMacros);
b3Assert(m_solveContactKernel);
-
- m_contactToConstraintKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solverSetupSource, "ContactToConstraintKernel", &pErrNum, solverSetupProg,additionalMacros );
+
+ m_contactToConstraintKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverSetupSource, "ContactToConstraintKernel", &pErrNum, solverSetupProg, additionalMacros);
b3Assert(m_contactToConstraintKernel);
-
- m_setSortDataKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solverSetup2Source, "SetSortDataKernel", &pErrNum, solverSetup2Prog,additionalMacros );
+
+ m_setSortDataKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverSetup2Source, "SetSortDataKernel", &pErrNum, solverSetup2Prog, additionalMacros);
b3Assert(m_setSortDataKernel);
-
- m_reorderContactKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solverSetup2Source, "ReorderContactKernel", &pErrNum, solverSetup2Prog,additionalMacros );
+
+ m_reorderContactKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverSetup2Source, "ReorderContactKernel", &pErrNum, solverSetup2Prog, additionalMacros);
b3Assert(m_reorderContactKernel);
-
- m_copyConstraintKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solverSetup2Source, "CopyConstraintKernel", &pErrNum, solverSetup2Prog,additionalMacros );
+ m_copyConstraintKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverSetup2Source, "CopyConstraintKernel", &pErrNum, solverSetup2Prog, additionalMacros);
b3Assert(m_copyConstraintKernel);
-
}
{
- cl_program batchingProg = b3OpenCLUtils::compileCLProgramFromString( ctx, device, batchKernelSource, &pErrNum,additionalMacros, B3_BATCHING_PATH);
+ cl_program batchingProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, batchKernelSource, &pErrNum, additionalMacros, B3_BATCHING_PATH);
//cl_program batchingProg = b3OpenCLUtils::compileCLProgramFromString( ctx, device, 0, &pErrNum,additionalMacros, B3_BATCHING_PATH,true);
b3Assert(batchingProg);
-
- m_batchingKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, batchKernelSource, "CreateBatches", &pErrNum, batchingProg,additionalMacros );
+
+ m_batchingKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, batchKernelSource, "CreateBatches", &pErrNum, batchingProg, additionalMacros);
b3Assert(m_batchingKernel);
}
{
- cl_program batchingNewProg = b3OpenCLUtils::compileCLProgramFromString( ctx, device, batchKernelNewSource, &pErrNum,additionalMacros, B3_BATCHING_NEW_PATH);
+ cl_program batchingNewProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, batchKernelNewSource, &pErrNum, additionalMacros, B3_BATCHING_NEW_PATH);
b3Assert(batchingNewProg);
- m_batchingKernelNew = b3OpenCLUtils::compileCLKernelFromString( ctx, device, batchKernelNewSource, "CreateBatchesNew", &pErrNum, batchingNewProg,additionalMacros );
+ m_batchingKernelNew = b3OpenCLUtils::compileCLKernelFromString(ctx, device, batchKernelNewSource, "CreateBatchesNew", &pErrNum, batchingNewProg, additionalMacros);
//m_batchingKernelNew = b3OpenCLUtils::compileCLKernelFromString( ctx, device, batchKernelNewSource, "CreateBatchesBruteForce", &pErrNum, batchingNewProg,additionalMacros );
b3Assert(m_batchingKernelNew);
}
}
-
+
b3Solver::~b3Solver()
{
delete m_offsets;
@@ -190,71 +172,68 @@ b3Solver::~b3Solver()
delete m_scan;
delete m_search;
-
clReleaseKernel(m_batchingKernel);
clReleaseKernel(m_batchingKernelNew);
-
- clReleaseKernel( m_solveContactKernel);
- clReleaseKernel( m_solveFrictionKernel);
-
- clReleaseKernel( m_contactToConstraintKernel);
- clReleaseKernel( m_setSortDataKernel);
- clReleaseKernel( m_reorderContactKernel);
- clReleaseKernel( m_copyConstraintKernel);
-
-}
+ clReleaseKernel(m_solveContactKernel);
+ clReleaseKernel(m_solveFrictionKernel);
-
+ clReleaseKernel(m_contactToConstraintKernel);
+ clReleaseKernel(m_setSortDataKernel);
+ clReleaseKernel(m_reorderContactKernel);
+ clReleaseKernel(m_copyConstraintKernel);
+}
-template<bool JACOBI>
-static
-__inline
-void solveContact(b3GpuConstraint4& cs,
- const b3Vector3& posA, b3Vector3& linVelA, b3Vector3& angVelA, float invMassA, const b3Matrix3x3& invInertiaA,
- const b3Vector3& posB, b3Vector3& linVelB, b3Vector3& angVelB, float invMassB, const b3Matrix3x3& invInertiaB,
- float maxRambdaDt[4], float minRambdaDt[4])
+template <bool JACOBI>
+static __inline void solveContact(b3GpuConstraint4& cs,
+ const b3Vector3& posA, b3Vector3& linVelA, b3Vector3& angVelA, float invMassA, const b3Matrix3x3& invInertiaA,
+ const b3Vector3& posB, b3Vector3& linVelB, b3Vector3& angVelB, float invMassB, const b3Matrix3x3& invInertiaB,
+ float maxRambdaDt[4], float minRambdaDt[4])
{
-
- b3Vector3 dLinVelA; dLinVelA.setZero();
- b3Vector3 dAngVelA; dAngVelA.setZero();
- b3Vector3 dLinVelB; dLinVelB.setZero();
- b3Vector3 dAngVelB; dAngVelB.setZero();
-
- for(int ic=0; ic<4; ic++)
+ b3Vector3 dLinVelA;
+ dLinVelA.setZero();
+ b3Vector3 dAngVelA;
+ dAngVelA.setZero();
+ b3Vector3 dLinVelB;
+ dLinVelB.setZero();
+ b3Vector3 dAngVelB;
+ dAngVelB.setZero();
+
+ for (int ic = 0; ic < 4; ic++)
{
// dont necessary because this makes change to 0
- if( cs.m_jacCoeffInv[ic] == 0.f ) continue;
+ if (cs.m_jacCoeffInv[ic] == 0.f) continue;
{
b3Vector3 angular0, angular1, linear;
b3Vector3 r0 = cs.m_worldPos[ic] - (b3Vector3&)posA;
b3Vector3 r1 = cs.m_worldPos[ic] - (b3Vector3&)posB;
- setLinearAndAngular( (const b3Vector3 &)cs.m_linear, (const b3Vector3 &)r0, (const b3Vector3 &)r1, &linear, &angular0, &angular1 );
+ setLinearAndAngular((const b3Vector3&)cs.m_linear, (const b3Vector3&)r0, (const b3Vector3&)r1, &linear, &angular0, &angular1);
- float rambdaDt = calcRelVel((const b3Vector3 &)cs.m_linear,(const b3Vector3 &) -cs.m_linear, angular0, angular1,
- linVelA, angVelA, linVelB, angVelB ) + cs.m_b[ic];
+ float rambdaDt = calcRelVel((const b3Vector3&)cs.m_linear, (const b3Vector3&)-cs.m_linear, angular0, angular1,
+ linVelA, angVelA, linVelB, angVelB) +
+ cs.m_b[ic];
rambdaDt *= cs.m_jacCoeffInv[ic];
{
float prevSum = cs.m_appliedRambdaDt[ic];
float updated = prevSum;
updated += rambdaDt;
- updated = b3Max( updated, minRambdaDt[ic] );
- updated = b3Min( updated, maxRambdaDt[ic] );
+ updated = b3Max(updated, minRambdaDt[ic]);
+ updated = b3Min(updated, maxRambdaDt[ic]);
rambdaDt = updated - prevSum;
cs.m_appliedRambdaDt[ic] = updated;
}
- b3Vector3 linImp0 = invMassA*linear*rambdaDt;
- b3Vector3 linImp1 = invMassB*(-linear)*rambdaDt;
- b3Vector3 angImp0 = (invInertiaA* angular0)*rambdaDt;
- b3Vector3 angImp1 = (invInertiaB* angular1)*rambdaDt;
+ b3Vector3 linImp0 = invMassA * linear * rambdaDt;
+ b3Vector3 linImp1 = invMassB * (-linear) * rambdaDt;
+ b3Vector3 angImp0 = (invInertiaA * angular0) * rambdaDt;
+ b3Vector3 angImp1 = (invInertiaB * angular1) * rambdaDt;
#ifdef _WIN32
- b3Assert(_finite(linImp0.getX()));
+ b3Assert(_finite(linImp0.getX()));
b3Assert(_finite(linImp1.getX()));
#endif
- if( JACOBI )
+ if (JACOBI)
{
dLinVelA += linImp0;
dAngVelA += angImp0;
@@ -271,92 +250,83 @@ void solveContact(b3GpuConstraint4& cs,
}
}
- if( JACOBI )
+ if (JACOBI)
{
linVelA += dLinVelA;
angVelA += dAngVelA;
linVelB += dLinVelB;
angVelB += dAngVelB;
}
-
}
+static __inline void solveFriction(b3GpuConstraint4& cs,
+ const b3Vector3& posA, b3Vector3& linVelA, b3Vector3& angVelA, float invMassA, const b3Matrix3x3& invInertiaA,
+ const b3Vector3& posB, b3Vector3& linVelB, b3Vector3& angVelB, float invMassB, const b3Matrix3x3& invInertiaB,
+ float maxRambdaDt[4], float minRambdaDt[4])
+{
+ if (cs.m_fJacCoeffInv[0] == 0 && cs.m_fJacCoeffInv[0] == 0) return;
+ const b3Vector3& center = (const b3Vector3&)cs.m_center;
+ b3Vector3 n = -(const b3Vector3&)cs.m_linear;
-
-
- static
- __inline
- void solveFriction(b3GpuConstraint4& cs,
- const b3Vector3& posA, b3Vector3& linVelA, b3Vector3& angVelA, float invMassA, const b3Matrix3x3& invInertiaA,
- const b3Vector3& posB, b3Vector3& linVelB, b3Vector3& angVelB, float invMassB, const b3Matrix3x3& invInertiaB,
- float maxRambdaDt[4], float minRambdaDt[4])
- {
-
- if( cs.m_fJacCoeffInv[0] == 0 && cs.m_fJacCoeffInv[0] == 0 ) return;
- const b3Vector3& center = (const b3Vector3&)cs.m_center;
-
- b3Vector3 n = -(const b3Vector3&)cs.m_linear;
-
- b3Vector3 tangent[2];
-#if 1
- b3PlaneSpace1 (n, tangent[0],tangent[1]);
+ b3Vector3 tangent[2];
+#if 1
+ b3PlaneSpace1(n, tangent[0], tangent[1]);
#else
- b3Vector3 r = cs.m_worldPos[0]-center;
- tangent[0] = cross3( n, r );
- tangent[1] = cross3( tangent[0], n );
- tangent[0] = normalize3( tangent[0] );
- tangent[1] = normalize3( tangent[1] );
+ b3Vector3 r = cs.m_worldPos[0] - center;
+ tangent[0] = cross3(n, r);
+ tangent[1] = cross3(tangent[0], n);
+ tangent[0] = normalize3(tangent[0]);
+ tangent[1] = normalize3(tangent[1]);
#endif
- b3Vector3 angular0, angular1, linear;
- b3Vector3 r0 = center - posA;
- b3Vector3 r1 = center - posB;
- for(int i=0; i<2; i++)
- {
- setLinearAndAngular( tangent[i], r0, r1, &linear, &angular0, &angular1 );
- float rambdaDt = calcRelVel(linear, -linear, angular0, angular1,
- linVelA, angVelA, linVelB, angVelB );
- rambdaDt *= cs.m_fJacCoeffInv[i];
+ b3Vector3 angular0, angular1, linear;
+ b3Vector3 r0 = center - posA;
+ b3Vector3 r1 = center - posB;
+ for (int i = 0; i < 2; i++)
+ {
+ setLinearAndAngular(tangent[i], r0, r1, &linear, &angular0, &angular1);
+ float rambdaDt = calcRelVel(linear, -linear, angular0, angular1,
+ linVelA, angVelA, linVelB, angVelB);
+ rambdaDt *= cs.m_fJacCoeffInv[i];
- {
- float prevSum = cs.m_fAppliedRambdaDt[i];
- float updated = prevSum;
- updated += rambdaDt;
- updated = b3Max( updated, minRambdaDt[i] );
- updated = b3Min( updated, maxRambdaDt[i] );
- rambdaDt = updated - prevSum;
- cs.m_fAppliedRambdaDt[i] = updated;
- }
+ {
+ float prevSum = cs.m_fAppliedRambdaDt[i];
+ float updated = prevSum;
+ updated += rambdaDt;
+ updated = b3Max(updated, minRambdaDt[i]);
+ updated = b3Min(updated, maxRambdaDt[i]);
+ rambdaDt = updated - prevSum;
+ cs.m_fAppliedRambdaDt[i] = updated;
+ }
- b3Vector3 linImp0 = invMassA*linear*rambdaDt;
- b3Vector3 linImp1 = invMassB*(-linear)*rambdaDt;
- b3Vector3 angImp0 = (invInertiaA* angular0)*rambdaDt;
- b3Vector3 angImp1 = (invInertiaB* angular1)*rambdaDt;
+ b3Vector3 linImp0 = invMassA * linear * rambdaDt;
+ b3Vector3 linImp1 = invMassB * (-linear) * rambdaDt;
+ b3Vector3 angImp0 = (invInertiaA * angular0) * rambdaDt;
+ b3Vector3 angImp1 = (invInertiaB * angular1) * rambdaDt;
#ifdef _WIN32
- b3Assert(_finite(linImp0.getX()));
- b3Assert(_finite(linImp1.getX()));
+ b3Assert(_finite(linImp0.getX()));
+ b3Assert(_finite(linImp1.getX()));
#endif
- linVelA += linImp0;
- angVelA += angImp0;
- linVelB += linImp1;
- angVelB += angImp1;
- }
+ linVelA += linImp0;
+ angVelA += angImp0;
+ linVelB += linImp1;
+ angVelB += angImp1;
+ }
- { // angular damping for point constraint
- b3Vector3 ab = ( posB - posA ).normalized();
- b3Vector3 ac = ( center - posA ).normalized();
- if( b3Dot( ab, ac ) > 0.95f || (invMassA == 0.f || invMassB == 0.f))
- {
- float angNA = b3Dot( n, angVelA );
- float angNB = b3Dot( n, angVelB );
+ { // angular damping for point constraint
+ b3Vector3 ab = (posB - posA).normalized();
+ b3Vector3 ac = (center - posA).normalized();
+ if (b3Dot(ab, ac) > 0.95f || (invMassA == 0.f || invMassB == 0.f))
+ {
+ float angNA = b3Dot(n, angVelA);
+ float angNB = b3Dot(n, angVelB);
- angVelA -= (angNA*0.1f)*n;
- angVelB -= (angNB*0.1f)*n;
- }
+ angVelA -= (angNA * 0.1f) * n;
+ angVelB -= (angNB * 0.1f) * n;
}
-
}
+}
/*
b3AlignedObjectArray<b3RigidBodyData>& m_bodies;
b3AlignedObjectArray<b3InertiaData>& m_shapes;
@@ -370,79 +340,69 @@ void solveContact(b3GpuConstraint4& cs,
int m_maxNumBatches;
*/
-struct SolveTask// : public ThreadPool::Task
+struct SolveTask // : public ThreadPool::Task
{
- SolveTask(b3AlignedObjectArray<b3RigidBodyData>& bodies, b3AlignedObjectArray<b3InertiaData>& shapes, b3AlignedObjectArray<b3GpuConstraint4>& constraints,
- int start, int nConstraints,int maxNumBatches,b3AlignedObjectArray<int>* wgUsedBodies, int curWgidx, b3AlignedObjectArray<int>* batchSizes, int cellIndex)
- : m_bodies( bodies ), m_shapes( shapes ),
- m_constraints( constraints ),
- m_batchSizes(batchSizes),
- m_cellIndex(cellIndex),
- m_curWgidx(curWgidx),
- m_start( start ),
- m_nConstraints( nConstraints ),
- m_solveFriction( true ),
- m_maxNumBatches(maxNumBatches)
- {}
-
- unsigned short int getType(){ return 0; }
+ SolveTask(b3AlignedObjectArray<b3RigidBodyData>& bodies, b3AlignedObjectArray<b3InertiaData>& shapes, b3AlignedObjectArray<b3GpuConstraint4>& constraints,
+ int start, int nConstraints, int maxNumBatches, b3AlignedObjectArray<int>* wgUsedBodies, int curWgidx, b3AlignedObjectArray<int>* batchSizes, int cellIndex)
+ : m_bodies(bodies), m_shapes(shapes), m_constraints(constraints), m_batchSizes(batchSizes), m_cellIndex(cellIndex), m_curWgidx(curWgidx), m_start(start), m_nConstraints(nConstraints), m_solveFriction(true), m_maxNumBatches(maxNumBatches)
+ {
+ }
+
+ unsigned short int getType() { return 0; }
void run(int tIdx)
{
int offset = 0;
- for (int ii=0;ii<B3_MAX_NUM_BATCHES;ii++)
+ for (int ii = 0; ii < B3_MAX_NUM_BATCHES; ii++)
{
- int numInBatch = m_batchSizes->at(m_cellIndex*B3_MAX_NUM_BATCHES+ii);
+ int numInBatch = m_batchSizes->at(m_cellIndex * B3_MAX_NUM_BATCHES + ii);
if (!numInBatch)
break;
- for (int jj=0;jj<numInBatch;jj++)
+ for (int jj = 0; jj < numInBatch; jj++)
{
- int i = m_start + offset+jj;
+ int i = m_start + offset + jj;
int batchId = m_constraints[i].m_batchIdx;
- b3Assert(batchId==ii);
+ b3Assert(batchId == ii);
float frictionCoeff = m_constraints[i].getFrictionCoeff();
int aIdx = (int)m_constraints[i].m_bodyA;
int bIdx = (int)m_constraints[i].m_bodyB;
-// int localBatch = m_constraints[i].m_batchIdx;
+ // int localBatch = m_constraints[i].m_batchIdx;
b3RigidBodyData& bodyA = m_bodies[aIdx];
b3RigidBodyData& bodyB = m_bodies[bIdx];
- if( !m_solveFriction )
+ if (!m_solveFriction)
{
- float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};
- float minRambdaDt[4] = {0.f,0.f,0.f,0.f};
+ float maxRambdaDt[4] = {FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX};
+ float minRambdaDt[4] = {0.f, 0.f, 0.f, 0.f};
- solveContact<false>( m_constraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass, (const b3Matrix3x3 &)m_shapes[aIdx].m_invInertiaWorld,
- (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass, (const b3Matrix3x3 &)m_shapes[bIdx].m_invInertiaWorld,
- maxRambdaDt, minRambdaDt );
+ solveContact<false>(m_constraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass, (const b3Matrix3x3&)m_shapes[aIdx].m_invInertiaWorld,
+ (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass, (const b3Matrix3x3&)m_shapes[bIdx].m_invInertiaWorld,
+ maxRambdaDt, minRambdaDt);
}
else
{
- float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};
- float minRambdaDt[4] = {0.f,0.f,0.f,0.f};
+ float maxRambdaDt[4] = {FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX};
+ float minRambdaDt[4] = {0.f, 0.f, 0.f, 0.f};
float sum = 0;
- for(int j=0; j<4; j++)
+ for (int j = 0; j < 4; j++)
{
- sum +=m_constraints[i].m_appliedRambdaDt[j];
+ sum += m_constraints[i].m_appliedRambdaDt[j];
}
frictionCoeff = 0.7f;
- for(int j=0; j<4; j++)
+ for (int j = 0; j < 4; j++)
{
- maxRambdaDt[j] = frictionCoeff*sum;
+ maxRambdaDt[j] = frictionCoeff * sum;
minRambdaDt[j] = -maxRambdaDt[j];
}
- solveFriction( m_constraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass,(const b3Matrix3x3 &) m_shapes[aIdx].m_invInertiaWorld,
- (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass,(const b3Matrix3x3 &) m_shapes[bIdx].m_invInertiaWorld,
- maxRambdaDt, minRambdaDt );
-
+ solveFriction(m_constraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass, (const b3Matrix3x3&)m_shapes[aIdx].m_invInertiaWorld,
+ (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass, (const b3Matrix3x3&)m_shapes[bIdx].m_invInertiaWorld,
+ maxRambdaDt, minRambdaDt);
}
}
- offset+=numInBatch;
-
-
+ offset += numInBatch;
}
-/* for (int bb=0;bb<m_maxNumBatches;bb++)
+ /* for (int bb=0;bb<m_maxNumBatches;bb++)
{
//for(int ic=m_nConstraints-1; ic>=0; ic--)
for(int ic=0; ic<m_nConstraints; ic++)
@@ -491,9 +451,6 @@ struct SolveTask// : public ThreadPool::Task
}
}
*/
-
-
-
}
b3AlignedObjectArray<b3RigidBodyData>& m_bodies;
@@ -508,11 +465,9 @@ struct SolveTask// : public ThreadPool::Task
int m_maxNumBatches;
};
-
-void b3Solver::solveContactConstraintHost( b3OpenCLArray<b3RigidBodyData>* bodyBuf, b3OpenCLArray<b3InertiaData>* shapeBuf,
- b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n ,int maxNumBatches,b3AlignedObjectArray<int>* batchSizes)
+void b3Solver::solveContactConstraintHost(b3OpenCLArray<b3RigidBodyData>* bodyBuf, b3OpenCLArray<b3InertiaData>* shapeBuf,
+ b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n, int maxNumBatches, b3AlignedObjectArray<int>* batchSizes)
{
-
#if 0
{
int nSplitX = B3_SOLVER_N_SPLIT_X;
@@ -571,114 +526,105 @@ void b3Solver::solveContactConstraintHost( b3OpenCLArray<b3RigidBodyData>* body
//printf("------------------------\n");
b3AlignedObjectArray<unsigned int> offsetsHost;
m_offsets->copyToHost(offsetsHost);
- static int frame=0;
- bool useBatches=true;
+ static int frame = 0;
+ bool useBatches = true;
if (useBatches)
{
- for(int iter=0; iter<m_nIterations; iter++)
+ for (int iter = 0; iter < m_nIterations; iter++)
{
- for (int cellBatch=0;cellBatch<B3_SOLVER_N_BATCHES;cellBatch++)
+ for (int cellBatch = 0; cellBatch < B3_SOLVER_N_BATCHES; cellBatch++)
{
-
int nSplitX = B3_SOLVER_N_SPLIT_X;
int nSplitY = B3_SOLVER_N_SPLIT_Y;
- int numWorkgroups = B3_SOLVER_N_CELLS/B3_SOLVER_N_BATCHES;
+ int numWorkgroups = B3_SOLVER_N_CELLS / B3_SOLVER_N_BATCHES;
//printf("cell Batch %d\n",cellBatch);
b3AlignedObjectArray<int> usedBodies[B3_SOLVER_N_CELLS];
- for (int i=0;i<B3_SOLVER_N_CELLS;i++)
+ for (int i = 0; i < B3_SOLVER_N_CELLS; i++)
{
usedBodies[i].resize(0);
}
-
-
-
//for (int wgIdx=numWorkgroups-1;wgIdx>=0;wgIdx--)
- for (int wgIdx=0;wgIdx<numWorkgroups;wgIdx++)
+ for (int wgIdx = 0; wgIdx < numWorkgroups; wgIdx++)
{
- int zIdx = (wgIdx/((nSplitX*nSplitY)/4))*2+((cellBatch&4)>>2);
- int remain= (wgIdx%((nSplitX*nSplitY)/4));
- int yIdx = (remain/(nSplitX/2))*2 + ((cellBatch&2)>>1);
- int xIdx = (remain%(nSplitX/2))*2 + (cellBatch&1);
- int cellIdx = xIdx+yIdx*nSplitX+zIdx*(nSplitX*nSplitY);
-
-
- if( numConstraintsHost[cellIdx] == 0 )
+ int zIdx = (wgIdx / ((nSplitX * nSplitY) / 4)) * 2 + ((cellBatch & 4) >> 2);
+ int remain = (wgIdx % ((nSplitX * nSplitY) / 4));
+ int yIdx = (remain / (nSplitX / 2)) * 2 + ((cellBatch & 2) >> 1);
+ int xIdx = (remain % (nSplitX / 2)) * 2 + (cellBatch & 1);
+ int cellIdx = xIdx + yIdx * nSplitX + zIdx * (nSplitX * nSplitY);
+
+ if (numConstraintsHost[cellIdx] == 0)
continue;
//printf("wgIdx %d: xIdx=%d, yIdx=%d, zIdx=%d, cellIdx=%d, cell Batch %d\n",wgIdx,xIdx,yIdx,zIdx,cellIdx,cellBatch);
//printf("cell %d has %d constraints\n", cellIdx,numConstraintsHost[cellIdx]);
if (zIdx)
{
- //printf("?\n");
+ //printf("?\n");
}
- if (iter==0)
+ if (iter == 0)
{
//printf("frame=%d, Cell xIdx=%x, yIdx=%d ",frame, xIdx,yIdx);
//printf("cellBatch=%d, wgIdx=%d, #constraints in cell=%d\n",cellBatch,wgIdx,numConstraintsHost[cellIdx]);
}
const int start = offsetsHost[cellIdx];
int numConstraintsInCell = numConstraintsHost[cellIdx];
- // const int end = start + numConstraintsInCell;
+ // const int end = start + numConstraintsInCell;
- SolveTask task( bodyNative, shapeNative, constraintNative, start, numConstraintsInCell ,maxNumBatches,usedBodies,wgIdx,batchSizes,cellIdx);
+ SolveTask task(bodyNative, shapeNative, constraintNative, start, numConstraintsInCell, maxNumBatches, usedBodies, wgIdx, batchSizes, cellIdx);
task.m_solveFriction = false;
task.run(0);
-
}
}
}
- for(int iter=0; iter<m_nIterations; iter++)
+ for (int iter = 0; iter < m_nIterations; iter++)
{
- for (int cellBatch=0;cellBatch<B3_SOLVER_N_BATCHES;cellBatch++)
+ for (int cellBatch = 0; cellBatch < B3_SOLVER_N_BATCHES; cellBatch++)
{
int nSplitX = B3_SOLVER_N_SPLIT_X;
int nSplitY = B3_SOLVER_N_SPLIT_Y;
-
- int numWorkgroups = B3_SOLVER_N_CELLS/B3_SOLVER_N_BATCHES;
+ int numWorkgroups = B3_SOLVER_N_CELLS / B3_SOLVER_N_BATCHES;
- for (int wgIdx=0;wgIdx<numWorkgroups;wgIdx++)
+ for (int wgIdx = 0; wgIdx < numWorkgroups; wgIdx++)
{
- int zIdx = (wgIdx/((nSplitX*nSplitY)/4))*2+((cellBatch&4)>>2);
- int remain= (wgIdx%((nSplitX*nSplitY)/4));
- int yIdx = (remain/(nSplitX/2))*2 + ((cellBatch&2)>>1);
- int xIdx = (remain%(nSplitX/2))*2 + (cellBatch&1);
-
- int cellIdx = xIdx+yIdx*nSplitX+zIdx*(nSplitX*nSplitY);
-
- if( numConstraintsHost[cellIdx] == 0 )
+ int zIdx = (wgIdx / ((nSplitX * nSplitY) / 4)) * 2 + ((cellBatch & 4) >> 2);
+ int remain = (wgIdx % ((nSplitX * nSplitY) / 4));
+ int yIdx = (remain / (nSplitX / 2)) * 2 + ((cellBatch & 2) >> 1);
+ int xIdx = (remain % (nSplitX / 2)) * 2 + (cellBatch & 1);
+
+ int cellIdx = xIdx + yIdx * nSplitX + zIdx * (nSplitX * nSplitY);
+
+ if (numConstraintsHost[cellIdx] == 0)
continue;
-
+
//printf("yIdx=%d\n",yIdx);
-
+
const int start = offsetsHost[cellIdx];
int numConstraintsInCell = numConstraintsHost[cellIdx];
- // const int end = start + numConstraintsInCell;
+ // const int end = start + numConstraintsInCell;
- SolveTask task( bodyNative, shapeNative, constraintNative, start, numConstraintsInCell,maxNumBatches, 0,0,batchSizes,cellIdx);
+ SolveTask task(bodyNative, shapeNative, constraintNative, start, numConstraintsInCell, maxNumBatches, 0, 0, batchSizes, cellIdx);
task.m_solveFriction = true;
task.run(0);
-
}
}
}
-
-
- } else
+ }
+ else
{
- for(int iter=0; iter<m_nIterations; iter++)
+ for (int iter = 0; iter < m_nIterations; iter++)
{
- SolveTask task( bodyNative, shapeNative, constraintNative, 0, n ,maxNumBatches,0,0,0,0);
+ SolveTask task(bodyNative, shapeNative, constraintNative, 0, n, maxNumBatches, 0, 0, 0, 0);
task.m_solveFriction = false;
task.run(0);
}
- for(int iter=0; iter<m_nIterations; iter++)
+ for (int iter = 0; iter < m_nIterations; iter++)
{
- SolveTask task( bodyNative, shapeNative, constraintNative, 0, n ,maxNumBatches,0,0,0,0);
+ SolveTask task(bodyNative, shapeNative, constraintNative, 0, n, maxNumBatches, 0, 0, 0, 0);
task.m_solveFriction = true;
task.run(0);
}
@@ -688,23 +634,21 @@ void b3Solver::solveContactConstraintHost( b3OpenCLArray<b3RigidBodyData>* body
shapeBuf->copyFromHost(shapeNative);
constraint->copyFromHost(constraintNative);
frame++;
-
}
void checkConstraintBatch(const b3OpenCLArray<b3RigidBodyData>* bodyBuf,
- const b3OpenCLArray<b3InertiaData>* shapeBuf,
- b3OpenCLArray<b3GpuConstraint4>* constraint,
- b3OpenCLArray<unsigned int>* m_numConstraints,
- b3OpenCLArray<unsigned int>* m_offsets,
- int batchId
- )
+ const b3OpenCLArray<b3InertiaData>* shapeBuf,
+ b3OpenCLArray<b3GpuConstraint4>* constraint,
+ b3OpenCLArray<unsigned int>* m_numConstraints,
+ b3OpenCLArray<unsigned int>* m_offsets,
+ int batchId)
{
-// b3BufferInfoCL( m_numConstraints->getBufferCL() ),
-// b3BufferInfoCL( m_offsets->getBufferCL() )
-
+ // b3BufferInfoCL( m_numConstraints->getBufferCL() ),
+ // b3BufferInfoCL( m_offsets->getBufferCL() )
+
int cellBatch = batchId;
const int nn = B3_SOLVER_N_CELLS;
-// int numWorkItems = 64*nn/B3_SOLVER_N_BATCHES;
+ // int numWorkItems = 64*nn/B3_SOLVER_N_BATCHES;
b3AlignedObjectArray<unsigned int> gN;
m_numConstraints->copyToHost(gN);
@@ -712,243 +656,220 @@ void checkConstraintBatch(const b3OpenCLArray<b3RigidBodyData>* bodyBuf,
m_offsets->copyToHost(gOffsets);
int nSplitX = B3_SOLVER_N_SPLIT_X;
int nSplitY = B3_SOLVER_N_SPLIT_Y;
-
-// int bIdx = batchId;
+
+ // int bIdx = batchId;
b3AlignedObjectArray<b3GpuConstraint4> cpuConstraints;
constraint->copyToHost(cpuConstraints);
printf("batch = %d\n", batchId);
- int numWorkgroups = nn/B3_SOLVER_N_BATCHES;
+ int numWorkgroups = nn / B3_SOLVER_N_BATCHES;
b3AlignedObjectArray<int> usedBodies;
-
- for (int wgIdx=0;wgIdx<numWorkgroups;wgIdx++)
+ for (int wgIdx = 0; wgIdx < numWorkgroups; wgIdx++)
{
printf("wgIdx = %d ", wgIdx);
- int zIdx = (wgIdx/((nSplitX*nSplitY))/2)*2+((cellBatch&4)>>2);
- int remain = wgIdx%((nSplitX*nSplitY));
- int yIdx = (remain%(nSplitX/2))*2 + ((cellBatch&2)>>1);
- int xIdx = (remain/(nSplitX/2))*2 + (cellBatch&1);
+ int zIdx = (wgIdx / ((nSplitX * nSplitY)) / 2) * 2 + ((cellBatch & 4) >> 2);
+ int remain = wgIdx % ((nSplitX * nSplitY));
+ int yIdx = (remain % (nSplitX / 2)) * 2 + ((cellBatch & 2) >> 1);
+ int xIdx = (remain / (nSplitX / 2)) * 2 + (cellBatch & 1);
-
- int cellIdx = xIdx+yIdx*nSplitX+zIdx*(nSplitX*nSplitY);
- printf("cellIdx=%d\n",cellIdx);
- if( gN[cellIdx] == 0 )
+ int cellIdx = xIdx + yIdx * nSplitX + zIdx * (nSplitX * nSplitY);
+ printf("cellIdx=%d\n", cellIdx);
+ if (gN[cellIdx] == 0)
continue;
const int start = gOffsets[cellIdx];
const int end = start + gN[cellIdx];
- for (int c=start;c<end;c++)
+ for (int c = start; c < end; c++)
{
b3GpuConstraint4& constraint = cpuConstraints[c];
//printf("constraint (%d,%d)\n", constraint.m_bodyA,constraint.m_bodyB);
- if (usedBodies.findLinearSearch(constraint.m_bodyA)< usedBodies.size())
+ if (usedBodies.findLinearSearch(constraint.m_bodyA) < usedBodies.size())
{
printf("error?\n");
}
- if (usedBodies.findLinearSearch(constraint.m_bodyB)< usedBodies.size())
+ if (usedBodies.findLinearSearch(constraint.m_bodyB) < usedBodies.size())
{
printf("error?\n");
}
}
- for (int c=start;c<end;c++)
+ for (int c = start; c < end; c++)
{
b3GpuConstraint4& constraint = cpuConstraints[c];
usedBodies.push_back(constraint.m_bodyA);
usedBodies.push_back(constraint.m_bodyB);
}
-
}
}
-static bool verify=false;
+static bool verify = false;
-void b3Solver::solveContactConstraint( const b3OpenCLArray<b3RigidBodyData>* bodyBuf, const b3OpenCLArray<b3InertiaData>* shapeBuf,
- b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n ,int maxNumBatches)
+void b3Solver::solveContactConstraint(const b3OpenCLArray<b3RigidBodyData>* bodyBuf, const b3OpenCLArray<b3InertiaData>* shapeBuf,
+ b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n, int maxNumBatches)
{
-
-
- b3Int4 cdata = b3MakeInt4( n, 0, 0, 0 );
+ b3Int4 cdata = b3MakeInt4(n, 0, 0, 0);
{
-
const int nn = B3_SOLVER_N_CELLS;
cdata.x = 0;
- cdata.y = maxNumBatches;//250;
-
+ cdata.y = maxNumBatches; //250;
- int numWorkItems = 64*nn/B3_SOLVER_N_BATCHES;
+ int numWorkItems = 64 * nn / B3_SOLVER_N_BATCHES;
#ifdef DEBUG_ME
- SolverDebugInfo* debugInfo = new SolverDebugInfo[numWorkItems];
- adl::b3OpenCLArray<SolverDebugInfo> gpuDebugInfo(data->m_device,numWorkItems);
+ SolverDebugInfo* debugInfo = new SolverDebugInfo[numWorkItems];
+ adl::b3OpenCLArray<SolverDebugInfo> gpuDebugInfo(data->m_device, numWorkItems);
#endif
-
-
{
-
B3_PROFILE("m_batchSolveKernel iterations");
- for(int iter=0; iter<m_nIterations; iter++)
+ for (int iter = 0; iter < m_nIterations; iter++)
{
- for(int ib=0; ib<B3_SOLVER_N_BATCHES; ib++)
+ for (int ib = 0; ib < B3_SOLVER_N_BATCHES; ib++)
{
-
if (verify)
{
- checkConstraintBatch(bodyBuf,shapeBuf,constraint,m_numConstraints,m_offsets,ib);
+ checkConstraintBatch(bodyBuf, shapeBuf, constraint, m_numConstraints, m_offsets, ib);
}
#ifdef DEBUG_ME
- memset(debugInfo,0,sizeof(SolverDebugInfo)*numWorkItems);
- gpuDebugInfo.write(debugInfo,numWorkItems);
+ memset(debugInfo, 0, sizeof(SolverDebugInfo) * numWorkItems);
+ gpuDebugInfo.write(debugInfo, numWorkItems);
#endif
-
cdata.z = ib;
-
- b3LauncherCL launcher( m_queue, m_solveContactKernel ,"m_solveContactKernel");
+ b3LauncherCL launcher(m_queue, m_solveContactKernel, "m_solveContactKernel");
#if 1
-
- b3BufferInfoCL bInfo[] = {
-
- b3BufferInfoCL( bodyBuf->getBufferCL() ),
- b3BufferInfoCL( shapeBuf->getBufferCL() ),
- b3BufferInfoCL( constraint->getBufferCL() ),
- b3BufferInfoCL( m_numConstraints->getBufferCL() ),
- b3BufferInfoCL( m_offsets->getBufferCL() )
+
+ b3BufferInfoCL bInfo[] = {
+
+ b3BufferInfoCL(bodyBuf->getBufferCL()),
+ b3BufferInfoCL(shapeBuf->getBufferCL()),
+ b3BufferInfoCL(constraint->getBufferCL()),
+ b3BufferInfoCL(m_numConstraints->getBufferCL()),
+ b3BufferInfoCL(m_offsets->getBufferCL())
#ifdef DEBUG_ME
- , b3BufferInfoCL(&gpuDebugInfo)
+ ,
+ b3BufferInfoCL(&gpuDebugInfo)
#endif
- };
-
-
+ };
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
//launcher.setConst( cdata.x );
- launcher.setConst( cdata.y );
- launcher.setConst( cdata.z );
- b3Int4 nSplit;
+ launcher.setConst(cdata.y);
+ launcher.setConst(cdata.z);
+ b3Int4 nSplit;
nSplit.x = B3_SOLVER_N_SPLIT_X;
nSplit.y = B3_SOLVER_N_SPLIT_Y;
nSplit.z = B3_SOLVER_N_SPLIT_Z;
- launcher.setConst( nSplit );
- launcher.launch1D( numWorkItems, 64 );
+ launcher.setConst(nSplit);
+ launcher.launch1D(numWorkItems, 64);
-
#else
- const char* fileName = "m_batchSolveKernel.bin";
- FILE* f = fopen(fileName,"rb");
- if (f)
- {
- int sizeInBytes=0;
- if (fseek(f, 0, SEEK_END) || (sizeInBytes = ftell(f)) == EOF || fseek(f, 0, SEEK_SET))
- {
- printf("error, cannot get file size\n");
- exit(0);
- }
-
- unsigned char* buf = (unsigned char*) malloc(sizeInBytes);
- fread(buf,sizeInBytes,1,f);
- int serializedBytes = launcher.deserializeArgs(buf, sizeInBytes,m_context);
- int num = *(int*)&buf[serializedBytes];
-
- launcher.launch1D( num);
-
- //this clFinish is for testing on errors
- clFinish(m_queue);
- }
+ const char* fileName = "m_batchSolveKernel.bin";
+ FILE* f = fopen(fileName, "rb");
+ if (f)
+ {
+ int sizeInBytes = 0;
+ if (fseek(f, 0, SEEK_END) || (sizeInBytes = ftell(f)) == EOF || fseek(f, 0, SEEK_SET))
+ {
+ printf("error, cannot get file size\n");
+ exit(0);
+ }
+
+ unsigned char* buf = (unsigned char*)malloc(sizeInBytes);
+ fread(buf, sizeInBytes, 1, f);
+ int serializedBytes = launcher.deserializeArgs(buf, sizeInBytes, m_context);
+ int num = *(int*)&buf[serializedBytes];
+
+ launcher.launch1D(num);
+
+ //this clFinish is for testing on errors
+ clFinish(m_queue);
+ }
#endif
-
#ifdef DEBUG_ME
clFinish(m_queue);
- gpuDebugInfo.read(debugInfo,numWorkItems);
+ gpuDebugInfo.read(debugInfo, numWorkItems);
clFinish(m_queue);
- for (int i=0;i<numWorkItems;i++)
+ for (int i = 0; i < numWorkItems; i++)
{
- if (debugInfo[i].m_valInt2>0)
+ if (debugInfo[i].m_valInt2 > 0)
{
- printf("debugInfo[i].m_valInt2 = %d\n",i,debugInfo[i].m_valInt2);
+ printf("debugInfo[i].m_valInt2 = %d\n", i, debugInfo[i].m_valInt2);
}
- if (debugInfo[i].m_valInt3>0)
+ if (debugInfo[i].m_valInt3 > 0)
{
- printf("debugInfo[i].m_valInt3 = %d\n",i,debugInfo[i].m_valInt3);
+ printf("debugInfo[i].m_valInt3 = %d\n", i, debugInfo[i].m_valInt3);
}
}
-#endif //DEBUG_ME
-
-
+#endif //DEBUG_ME
}
}
-
- clFinish(m_queue);
-
+ clFinish(m_queue);
}
cdata.x = 1;
- bool applyFriction=true;
+ bool applyFriction = true;
if (applyFriction)
- {
+ {
B3_PROFILE("m_batchSolveKernel iterations2");
- for(int iter=0; iter<m_nIterations; iter++)
+ for (int iter = 0; iter < m_nIterations; iter++)
{
- for(int ib=0; ib<B3_SOLVER_N_BATCHES; ib++)
+ for (int ib = 0; ib < B3_SOLVER_N_BATCHES; ib++)
{
cdata.z = ib;
-
-
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL( bodyBuf->getBufferCL() ),
- b3BufferInfoCL( shapeBuf->getBufferCL() ),
- b3BufferInfoCL( constraint->getBufferCL() ),
- b3BufferInfoCL( m_numConstraints->getBufferCL() ),
- b3BufferInfoCL( m_offsets->getBufferCL() )
+
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL(bodyBuf->getBufferCL()),
+ b3BufferInfoCL(shapeBuf->getBufferCL()),
+ b3BufferInfoCL(constraint->getBufferCL()),
+ b3BufferInfoCL(m_numConstraints->getBufferCL()),
+ b3BufferInfoCL(m_offsets->getBufferCL())
#ifdef DEBUG_ME
- ,b3BufferInfoCL(&gpuDebugInfo)
-#endif //DEBUG_ME
+ ,
+ b3BufferInfoCL(&gpuDebugInfo)
+#endif //DEBUG_ME
};
- b3LauncherCL launcher( m_queue, m_solveFrictionKernel,"m_solveFrictionKernel" );
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ b3LauncherCL launcher(m_queue, m_solveFrictionKernel, "m_solveFrictionKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
//launcher.setConst( cdata.x );
- launcher.setConst( cdata.y );
- launcher.setConst( cdata.z );
- b3Int4 nSplit;
+ launcher.setConst(cdata.y);
+ launcher.setConst(cdata.z);
+ b3Int4 nSplit;
nSplit.x = B3_SOLVER_N_SPLIT_X;
nSplit.y = B3_SOLVER_N_SPLIT_Y;
nSplit.z = B3_SOLVER_N_SPLIT_Z;
- launcher.setConst( nSplit );
-
- launcher.launch1D( 64*nn/B3_SOLVER_N_BATCHES, 64 );
+ launcher.setConst(nSplit);
+
+ launcher.launch1D(64 * nn / B3_SOLVER_N_BATCHES, 64);
}
}
clFinish(m_queue);
-
}
#ifdef DEBUG_ME
delete[] debugInfo;
-#endif //DEBUG_ME
+#endif //DEBUG_ME
}
-
-
}
-void b3Solver::convertToConstraints( const b3OpenCLArray<b3RigidBodyData>* bodyBuf,
- const b3OpenCLArray<b3InertiaData>* shapeBuf,
- b3OpenCLArray<b3Contact4>* contactsIn, b3OpenCLArray<b3GpuConstraint4>* contactCOut, void* additionalData,
- int nContacts, const ConstraintCfg& cfg )
+void b3Solver::convertToConstraints(const b3OpenCLArray<b3RigidBodyData>* bodyBuf,
+ const b3OpenCLArray<b3InertiaData>* shapeBuf,
+ b3OpenCLArray<b3Contact4>* contactsIn, b3OpenCLArray<b3GpuConstraint4>* contactCOut, void* additionalData,
+ int nContacts, const ConstraintCfg& cfg)
{
-// b3OpenCLArray<b3GpuConstraint4>* constraintNative =0;
+ // b3OpenCLArray<b3GpuConstraint4>* constraintNative =0;
contactCOut->resize(nContacts);
struct CB
{
@@ -959,30 +880,28 @@ void b3Solver::convertToConstraints( const b3OpenCLArray<b3RigidBodyData>* bodyB
};
{
-
CB cdata;
cdata.m_nContacts = nContacts;
cdata.m_dt = cfg.m_dt;
cdata.m_positionDrift = cfg.m_positionDrift;
cdata.m_positionConstraintCoeff = cfg.m_positionConstraintCoeff;
-
if (gConvertConstraintOnCpu)
{
b3AlignedObjectArray<b3RigidBodyData> gBodies;
- bodyBuf->copyToHost(gBodies);
+ bodyBuf->copyToHost(gBodies);
- b3AlignedObjectArray<b3Contact4> gContact;
- contactsIn->copyToHost(gContact);
+ b3AlignedObjectArray<b3Contact4> gContact;
+ contactsIn->copyToHost(gContact);
+
+ b3AlignedObjectArray<b3InertiaData> gShapes;
+ shapeBuf->copyToHost(gShapes);
+
+ b3AlignedObjectArray<b3GpuConstraint4> gConstraintOut;
+ gConstraintOut.resize(nContacts);
- b3AlignedObjectArray<b3InertiaData> gShapes;
- shapeBuf->copyToHost(gShapes);
-
- b3AlignedObjectArray<b3GpuConstraint4> gConstraintOut;
- gConstraintOut.resize(nContacts);
-
B3_PROFILE("cpu contactToConstraintKernel");
- for (int gIdx=0;gIdx<nContacts;gIdx++)
+ for (int gIdx = 0; gIdx < nContacts; gIdx++)
{
int aIdx = abs(gContact[gIdx].m_bodyAPtrAndSignBit);
int bIdx = abs(gContact[gIdx].m_bodyBPtrAndSignBit);
@@ -1001,40 +920,36 @@ void b3Solver::convertToConstraints( const b3OpenCLArray<b3RigidBodyData>* bodyB
b3ContactConstraint4_t cs;
- setConstraint4( posA, linVelA, angVelA, invMassA, invInertiaA, posB, linVelB, angVelB, invMassB, invInertiaB,
- &gContact[gIdx], cdata.m_dt, cdata.m_positionDrift, cdata.m_positionConstraintCoeff,
- &cs );
-
+ setConstraint4(posA, linVelA, angVelA, invMassA, invInertiaA, posB, linVelB, angVelB, invMassB, invInertiaB,
+ &gContact[gIdx], cdata.m_dt, cdata.m_positionDrift, cdata.m_positionConstraintCoeff,
+ &cs);
+
cs.m_batchIdx = gContact[gIdx].m_batchIdx;
gConstraintOut[gIdx] = (b3GpuConstraint4&)cs;
}
contactCOut->copyFromHost(gConstraintOut);
-
- } else
+ }
+ else
{
B3_PROFILE("gpu m_contactToConstraintKernel");
-
- b3BufferInfoCL bInfo[] = { b3BufferInfoCL( contactsIn->getBufferCL() ), b3BufferInfoCL( bodyBuf->getBufferCL() ), b3BufferInfoCL( shapeBuf->getBufferCL()),
- b3BufferInfoCL( contactCOut->getBufferCL() )};
- b3LauncherCL launcher( m_queue, m_contactToConstraintKernel,"m_contactToConstraintKernel" );
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ b3BufferInfoCL bInfo[] = {b3BufferInfoCL(contactsIn->getBufferCL()), b3BufferInfoCL(bodyBuf->getBufferCL()), b3BufferInfoCL(shapeBuf->getBufferCL()),
+ b3BufferInfoCL(contactCOut->getBufferCL())};
+ b3LauncherCL launcher(m_queue, m_contactToConstraintKernel, "m_contactToConstraintKernel");
+ launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
//launcher.setConst( cdata );
-
+
launcher.setConst(cdata.m_nContacts);
launcher.setConst(cdata.m_dt);
launcher.setConst(cdata.m_positionDrift);
launcher.setConst(cdata.m_positionConstraintCoeff);
-
- launcher.launch1D( nContacts, 64 );
- clFinish(m_queue);
+ launcher.launch1D(nContacts, 64);
+ clFinish(m_queue);
}
}
-
-
}
/*
@@ -1115,28 +1030,24 @@ void b3Solver::sortContacts( const b3OpenCLArray<b3RigidBodyData>* bodyBuf,
}
*/
-void b3Solver::batchContacts( b3OpenCLArray<b3Contact4>* contacts, int nContacts, b3OpenCLArray<unsigned int>* nNative, b3OpenCLArray<unsigned int>* offsetsNative, int staticIdx )
+void b3Solver::batchContacts(b3OpenCLArray<b3Contact4>* contacts, int nContacts, b3OpenCLArray<unsigned int>* nNative, b3OpenCLArray<unsigned int>* offsetsNative, int staticIdx)
{
-
- int numWorkItems = 64*B3_SOLVER_N_CELLS;
+ int numWorkItems = 64 * B3_SOLVER_N_CELLS;
{
B3_PROFILE("batch generation");
-
+
b3Int4 cdata;
cdata.x = nContacts;
cdata.y = 0;
cdata.z = staticIdx;
-
#ifdef BATCH_DEBUG
- SolverDebugInfo* debugInfo = new SolverDebugInfo[numWorkItems];
- adl::b3OpenCLArray<SolverDebugInfo> gpuDebugInfo(data->m_device,numWorkItems);
- memset(debugInfo,0,sizeof(SolverDebugInfo)*numWorkItems);
- gpuDebugInfo.write(debugInfo,numWorkItems);
+ SolverDebugInfo* debugInfo = new SolverDebugInfo[numWorkItems];
+ adl::b3OpenCLArray<SolverDebugInfo> gpuDebugInfo(data->m_device, numWorkItems);
+ memset(debugInfo, 0, sizeof(SolverDebugInfo) * numWorkItems);
+ gpuDebugInfo.write(debugInfo, numWorkItems);
#endif
-
-
#if 0
b3BufferInfoCL bInfo[] = {
b3BufferInfoCL( contacts->getBufferCL() ),
@@ -1148,8 +1059,6 @@ void b3Solver::batchContacts( b3OpenCLArray<b3Contact4>* contacts, int nContact
#endif
};
#endif
-
-
{
m_batchSizes.resize(nNative->size());
@@ -1157,22 +1066,21 @@ void b3Solver::batchContacts( b3OpenCLArray<b3Contact4>* contacts, int nContact
//b3LauncherCL launcher( m_queue, m_batchingKernel);
cl_kernel k = useNewBatchingKernel ? m_batchingKernelNew : m_batchingKernel;
- b3LauncherCL launcher( m_queue, k,"*batchingKernel");
- if (!useNewBatchingKernel )
+ b3LauncherCL launcher(m_queue, k, "*batchingKernel");
+ if (!useNewBatchingKernel)
{
- launcher.setBuffer( contacts->getBufferCL() );
+ launcher.setBuffer(contacts->getBufferCL());
}
- launcher.setBuffer( m_contactBuffer2->getBufferCL() );
- launcher.setBuffer( nNative->getBufferCL());
- launcher.setBuffer( offsetsNative->getBufferCL());
-
+ launcher.setBuffer(m_contactBuffer2->getBufferCL());
+ launcher.setBuffer(nNative->getBufferCL());
+ launcher.setBuffer(offsetsNative->getBufferCL());
+
launcher.setBuffer(m_batchSizes.getBufferCL());
-
//launcher.setConst( cdata );
- launcher.setConst(staticIdx);
-
- launcher.launch1D( numWorkItems, 64 );
+ launcher.setConst(staticIdx);
+
+ launcher.launch1D(numWorkItems, 64);
//clFinish(m_queue);
//b3AlignedObjectArray<int> batchSizesCPU;
//m_batchSizes.copyToHost(batchSizesCPU);
@@ -1180,46 +1088,41 @@ void b3Solver::batchContacts( b3OpenCLArray<b3Contact4>* contacts, int nContact
}
#ifdef BATCH_DEBUG
- aaaa
- b3Contact4* hostContacts = new b3Contact4[nContacts];
- m_contactBuffer->read(hostContacts,nContacts);
+ aaaa
+ b3Contact4* hostContacts = new b3Contact4[nContacts];
+ m_contactBuffer->read(hostContacts, nContacts);
clFinish(m_queue);
- gpuDebugInfo.read(debugInfo,numWorkItems);
+ gpuDebugInfo.read(debugInfo, numWorkItems);
clFinish(m_queue);
- for (int i=0;i<numWorkItems;i++)
+ for (int i = 0; i < numWorkItems; i++)
{
- if (debugInfo[i].m_valInt1>0)
+ if (debugInfo[i].m_valInt1 > 0)
{
printf("catch\n");
}
- if (debugInfo[i].m_valInt2>0)
+ if (debugInfo[i].m_valInt2 > 0)
{
printf("catch22\n");
}
- if (debugInfo[i].m_valInt3>0)
+ if (debugInfo[i].m_valInt3 > 0)
{
printf("catch666\n");
}
- if (debugInfo[i].m_valInt4>0)
+ if (debugInfo[i].m_valInt4 > 0)
{
printf("catch777\n");
}
}
delete[] debugInfo;
-#endif //BATCH_DEBUG
-
+#endif //BATCH_DEBUG
}
-// copy buffer to buffer
+ // copy buffer to buffer
//b3Assert(m_contactBuffer->size()==nContacts);
//contacts->copyFromOpenCLArray( *m_contactBuffer);
//clFinish(m_queue);//needed?
-
-
-
}
-
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3Solver.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3Solver.h
index b37f2f1bec..ee63531d78 100644
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3Solver.h
+++ b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3Solver.h
@@ -13,7 +13,6 @@ subject to the following restrictions:
*/
//Originally written by Takahiro Harada
-
#ifndef __ADL_SOLVER_H
#define __ADL_SOLVER_H
@@ -29,98 +28,83 @@ subject to the following restrictions:
#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
-
-#define B3NEXTMULTIPLEOF(num, alignment) (((num)/(alignment) + (((num)%(alignment)==0)?0:1))*(alignment))
+#define B3NEXTMULTIPLEOF(num, alignment) (((num) / (alignment) + (((num) % (alignment) == 0) ? 0 : 1)) * (alignment))
enum
{
- B3_SOLVER_N_SPLIT_X = 8,//16,//4,
- B3_SOLVER_N_SPLIT_Y = 4,//16,//4,
- B3_SOLVER_N_SPLIT_Z = 8,//,
- B3_SOLVER_N_CELLS = B3_SOLVER_N_SPLIT_X*B3_SOLVER_N_SPLIT_Y*B3_SOLVER_N_SPLIT_Z,
- B3_SOLVER_N_BATCHES = 8,//4,//8,//4,
+ B3_SOLVER_N_SPLIT_X = 8, //16,//4,
+ B3_SOLVER_N_SPLIT_Y = 4, //16,//4,
+ B3_SOLVER_N_SPLIT_Z = 8, //,
+ B3_SOLVER_N_CELLS = B3_SOLVER_N_SPLIT_X * B3_SOLVER_N_SPLIT_Y * B3_SOLVER_N_SPLIT_Z,
+ B3_SOLVER_N_BATCHES = 8, //4,//8,//4,
B3_MAX_NUM_BATCHES = 128,
};
class b3SolverBase
{
- public:
-
-
- struct ConstraintCfg
- {
- ConstraintCfg( float dt = 0.f ): m_positionDrift( 0.005f ), m_positionConstraintCoeff( 0.2f ), m_dt(dt), m_staticIdx(-1) {}
-
- float m_positionDrift;
- float m_positionConstraintCoeff;
- float m_dt;
- bool m_enableParallelSolve;
- float m_batchCellSize;
- int m_staticIdx;
- };
-
+public:
+ struct ConstraintCfg
+ {
+ ConstraintCfg(float dt = 0.f) : m_positionDrift(0.005f), m_positionConstraintCoeff(0.2f), m_dt(dt), m_staticIdx(-1) {}
+
+ float m_positionDrift;
+ float m_positionConstraintCoeff;
+ float m_dt;
+ bool m_enableParallelSolve;
+ float m_batchCellSize;
+ int m_staticIdx;
+ };
};
class b3Solver : public b3SolverBase
{
- public:
-
- cl_context m_context;
- cl_device_id m_device;
- cl_command_queue m_queue;
-
-
- b3OpenCLArray<unsigned int>* m_numConstraints;
- b3OpenCLArray<unsigned int>* m_offsets;
- b3OpenCLArray<int> m_batchSizes;
-
-
- int m_nIterations;
- cl_kernel m_batchingKernel;
- cl_kernel m_batchingKernelNew;
- cl_kernel m_solveContactKernel;
- cl_kernel m_solveFrictionKernel;
- cl_kernel m_contactToConstraintKernel;
- cl_kernel m_setSortDataKernel;
- cl_kernel m_reorderContactKernel;
- cl_kernel m_copyConstraintKernel;
+public:
+ cl_context m_context;
+ cl_device_id m_device;
+ cl_command_queue m_queue;
- class b3RadixSort32CL* m_sort32;
- class b3BoundSearchCL* m_search;
- class b3PrefixScanCL* m_scan;
+ b3OpenCLArray<unsigned int>* m_numConstraints;
+ b3OpenCLArray<unsigned int>* m_offsets;
+ b3OpenCLArray<int> m_batchSizes;
- b3OpenCLArray<b3SortData>* m_sortDataBuffer;
- b3OpenCLArray<b3Contact4>* m_contactBuffer2;
+ int m_nIterations;
+ cl_kernel m_batchingKernel;
+ cl_kernel m_batchingKernelNew;
+ cl_kernel m_solveContactKernel;
+ cl_kernel m_solveFrictionKernel;
+ cl_kernel m_contactToConstraintKernel;
+ cl_kernel m_setSortDataKernel;
+ cl_kernel m_reorderContactKernel;
+ cl_kernel m_copyConstraintKernel;
- enum
- {
- DYNAMIC_CONTACT_ALLOCATION_THRESHOLD = 2000000,
- };
+ class b3RadixSort32CL* m_sort32;
+ class b3BoundSearchCL* m_search;
+ class b3PrefixScanCL* m_scan;
-
+ b3OpenCLArray<b3SortData>* m_sortDataBuffer;
+ b3OpenCLArray<b3Contact4>* m_contactBuffer2;
-
- b3Solver(cl_context ctx, cl_device_id device, cl_command_queue queue, int pairCapacity);
+ enum
+ {
+ DYNAMIC_CONTACT_ALLOCATION_THRESHOLD = 2000000,
+ };
- virtual ~b3Solver();
-
- void solveContactConstraint( const b3OpenCLArray<b3RigidBodyData>* bodyBuf, const b3OpenCLArray<b3InertiaData>* inertiaBuf,
- b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n ,int maxNumBatches);
+ b3Solver(cl_context ctx, cl_device_id device, cl_command_queue queue, int pairCapacity);
- void solveContactConstraintHost( b3OpenCLArray<b3RigidBodyData>* bodyBuf, b3OpenCLArray<b3InertiaData>* shapeBuf,
- b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n ,int maxNumBatches, b3AlignedObjectArray<int>* batchSizes);
+ virtual ~b3Solver();
+ void solveContactConstraint(const b3OpenCLArray<b3RigidBodyData>* bodyBuf, const b3OpenCLArray<b3InertiaData>* inertiaBuf,
+ b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n, int maxNumBatches);
- void convertToConstraints( const b3OpenCLArray<b3RigidBodyData>* bodyBuf,
- const b3OpenCLArray<b3InertiaData>* shapeBuf,
- b3OpenCLArray<b3Contact4>* contactsIn, b3OpenCLArray<b3GpuConstraint4>* contactCOut, void* additionalData,
- int nContacts, const ConstraintCfg& cfg );
+ void solveContactConstraintHost(b3OpenCLArray<b3RigidBodyData>* bodyBuf, b3OpenCLArray<b3InertiaData>* shapeBuf,
+ b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n, int maxNumBatches, b3AlignedObjectArray<int>* batchSizes);
- void batchContacts( b3OpenCLArray<b3Contact4>* contacts, int nContacts, b3OpenCLArray<unsigned int>* n, b3OpenCLArray<unsigned int>* offsets, int staticIdx );
+ void convertToConstraints(const b3OpenCLArray<b3RigidBodyData>* bodyBuf,
+ const b3OpenCLArray<b3InertiaData>* shapeBuf,
+ b3OpenCLArray<b3Contact4>* contactsIn, b3OpenCLArray<b3GpuConstraint4>* contactCOut, void* additionalData,
+ int nContacts, const ConstraintCfg& cfg);
+ void batchContacts(b3OpenCLArray<b3Contact4>* contacts, int nContacts, b3OpenCLArray<unsigned int>* n, b3OpenCLArray<unsigned int>* offsets, int staticIdx);
};
-
-
-
-#endif //__ADL_SOLVER_H
+#endif //__ADL_SOLVER_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/batchingKernels.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/batchingKernels.h
index 150eedc94b..7c73c96baa 100644
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/batchingKernels.h
+++ b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/batchingKernels.h
@@ -1,388 +1,387 @@
//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* batchingKernelsCL= \
-"/*\n"
-"Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
-"This software is provided 'as-is', without any express or implied warranty.\n"
-"In no event will the authors be held liable for any damages arising from the use of this software.\n"
-"Permission is granted to anyone to use this software for any purpose, \n"
-"including commercial applications, and to alter it and redistribute it freely, \n"
-"subject to the following restrictions:\n"
-"1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
-"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
-"3. This notice may not be removed or altered from any source distribution.\n"
-"*/\n"
-"//Originally written by Takahiro Harada\n"
-"#ifndef B3_CONTACT4DATA_H\n"
-"#define B3_CONTACT4DATA_H\n"
-"#ifndef B3_FLOAT4_H\n"
-"#define B3_FLOAT4_H\n"
-"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
-"#define B3_PLATFORM_DEFINITIONS_H\n"
-"struct MyTest\n"
-"{\n"
-" int bla;\n"
-"};\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
-"#define B3_LARGE_FLOAT 1e18f\n"
-"#define B3_INFINITY 1e18f\n"
-"#define b3Assert(a)\n"
-"#define b3ConstArray(a) __global const a*\n"
-"#define b3AtomicInc atomic_inc\n"
-"#define b3AtomicAdd atomic_add\n"
-"#define b3Fabs fabs\n"
-"#define b3Sqrt native_sqrt\n"
-"#define b3Sin native_sin\n"
-"#define b3Cos native_cos\n"
-"#define B3_STATIC\n"
-"#endif\n"
-"#endif\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-" typedef float4 b3Float4;\n"
-" #define b3Float4ConstArg const b3Float4\n"
-" #define b3MakeFloat4 (float4)\n"
-" float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
-" {\n"
-" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
-" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
-" return dot(a1, b1);\n"
-" }\n"
-" b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
-" {\n"
-" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
-" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
-" return cross(a1, b1);\n"
-" }\n"
-" #define b3MinFloat4 min\n"
-" #define b3MaxFloat4 max\n"
-" #define b3Normalized(a) normalize(a)\n"
-"#endif \n"
-" \n"
-"inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
-"{\n"
-" if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
-" return false;\n"
-" return true;\n"
-"}\n"
-"inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
-"{\n"
-" float maxDot = -B3_INFINITY;\n"
-" int i = 0;\n"
-" int ptIndex = -1;\n"
-" for( i = 0; i < vecLen; i++ )\n"
-" {\n"
-" float dot = b3Dot3F4(vecArray[i],vec);\n"
-" \n"
-" if( dot > maxDot )\n"
-" {\n"
-" maxDot = dot;\n"
-" ptIndex = i;\n"
-" }\n"
-" }\n"
-" b3Assert(ptIndex>=0);\n"
-" if (ptIndex<0)\n"
-" {\n"
-" ptIndex = 0;\n"
-" }\n"
-" *dotOut = maxDot;\n"
-" return ptIndex;\n"
-"}\n"
-"#endif //B3_FLOAT4_H\n"
-"typedef struct b3Contact4Data b3Contact4Data_t;\n"
-"struct b3Contact4Data\n"
-"{\n"
-" b3Float4 m_worldPosB[4];\n"
-"// b3Float4 m_localPosA[4];\n"
-"// b3Float4 m_localPosB[4];\n"
-" b3Float4 m_worldNormalOnB; // w: m_nPoints\n"
-" unsigned short m_restituitionCoeffCmp;\n"
-" unsigned short m_frictionCoeffCmp;\n"
-" int m_batchIdx;\n"
-" int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
-" int m_bodyBPtrAndSignBit;\n"
-" int m_childIndexA;\n"
-" int m_childIndexB;\n"
-" int m_unused1;\n"
-" int m_unused2;\n"
-"};\n"
-"inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
-"{\n"
-" return (int)contact->m_worldNormalOnB.w;\n"
-"};\n"
-"inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
-"{\n"
-" contact->m_worldNormalOnB.w = (float)numPoints;\n"
-"};\n"
-"#endif //B3_CONTACT4DATA_H\n"
-"#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
-"#ifdef cl_ext_atomic_counters_32\n"
-"#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
-"#else\n"
-"#define counter32_t volatile __global int*\n"
-"#endif\n"
-"typedef unsigned int u32;\n"
-"typedef unsigned short u16;\n"
-"typedef unsigned char u8;\n"
-"#define GET_GROUP_IDX get_group_id(0)\n"
-"#define GET_LOCAL_IDX get_local_id(0)\n"
-"#define GET_GLOBAL_IDX get_global_id(0)\n"
-"#define GET_GROUP_SIZE get_local_size(0)\n"
-"#define GET_NUM_GROUPS get_num_groups(0)\n"
-"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
-"#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
-"#define AtomInc(x) atom_inc(&(x))\n"
-"#define AtomInc1(x, out) out = atom_inc(&(x))\n"
-"#define AppendInc(x, out) out = atomic_inc(x)\n"
-"#define AtomAdd(x, value) atom_add(&(x), value)\n"
-"#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
-"#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
-"#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
-"#define make_float4 (float4)\n"
-"#define make_float2 (float2)\n"
-"#define make_uint4 (uint4)\n"
-"#define make_int4 (int4)\n"
-"#define make_uint2 (uint2)\n"
-"#define make_int2 (int2)\n"
-"#define max2 max\n"
-"#define min2 min\n"
-"#define WG_SIZE 64\n"
-"typedef struct \n"
-"{\n"
-" int m_n;\n"
-" int m_start;\n"
-" int m_staticIdx;\n"
-" int m_paddings[1];\n"
-"} ConstBuffer;\n"
-"typedef struct \n"
-"{\n"
-" int m_a;\n"
-" int m_b;\n"
-" u32 m_idx;\n"
-"}Elem;\n"
-"#define STACK_SIZE (WG_SIZE*10)\n"
-"//#define STACK_SIZE (WG_SIZE)\n"
-"#define RING_SIZE 1024\n"
-"#define RING_SIZE_MASK (RING_SIZE-1)\n"
-"#define CHECK_SIZE (WG_SIZE)\n"
-"#define GET_RING_CAPACITY (RING_SIZE - ldsRingEnd)\n"
-"#define RING_END ldsTmp\n"
-"u32 readBuf(__local u32* buff, int idx)\n"
-"{\n"
-" idx = idx % (32*CHECK_SIZE);\n"
-" int bitIdx = idx%32;\n"
-" int bufIdx = idx/32;\n"
-" return buff[bufIdx] & (1<<bitIdx);\n"
-"}\n"
-"void writeBuf(__local u32* buff, int idx)\n"
-"{\n"
-" idx = idx % (32*CHECK_SIZE);\n"
-" int bitIdx = idx%32;\n"
-" int bufIdx = idx/32;\n"
-"// buff[bufIdx] |= (1<<bitIdx);\n"
-" atom_or( &buff[bufIdx], (1<<bitIdx) );\n"
-"}\n"
-"u32 tryWrite(__local u32* buff, int idx)\n"
-"{\n"
-" idx = idx % (32*CHECK_SIZE);\n"
-" int bitIdx = idx%32;\n"
-" int bufIdx = idx/32;\n"
-" u32 ans = (u32)atom_or( &buff[bufIdx], (1<<bitIdx) );\n"
-" return ((ans >> bitIdx)&1) == 0;\n"
-"}\n"
-"// batching on the GPU\n"
-"__kernel void CreateBatches( __global const struct b3Contact4Data* gConstraints, __global struct b3Contact4Data* gConstraintsOut,\n"
-" __global const u32* gN, __global const u32* gStart, __global int* batchSizes, \n"
-" int m_staticIdx )\n"
-"{\n"
-" __local u32 ldsStackIdx[STACK_SIZE];\n"
-" __local u32 ldsStackEnd;\n"
-" __local Elem ldsRingElem[RING_SIZE];\n"
-" __local u32 ldsRingEnd;\n"
-" __local u32 ldsTmp;\n"
-" __local u32 ldsCheckBuffer[CHECK_SIZE];\n"
-" __local u32 ldsFixedBuffer[CHECK_SIZE];\n"
-" __local u32 ldsGEnd;\n"
-" __local u32 ldsDstEnd;\n"
-" int wgIdx = GET_GROUP_IDX;\n"
-" int lIdx = GET_LOCAL_IDX;\n"
-" \n"
-" const int m_n = gN[wgIdx];\n"
-" const int m_start = gStart[wgIdx];\n"
-" \n"
-" if( lIdx == 0 )\n"
-" {\n"
-" ldsRingEnd = 0;\n"
-" ldsGEnd = 0;\n"
-" ldsStackEnd = 0;\n"
-" ldsDstEnd = m_start;\n"
-" }\n"
-" \n"
-" \n"
-" \n"
-"// while(1)\n"
-"//was 250\n"
-" int ie=0;\n"
-" int maxBatch = 0;\n"
-" for(ie=0; ie<50; ie++)\n"
-" {\n"
-" ldsFixedBuffer[lIdx] = 0;\n"
-" for(int giter=0; giter<4; giter++)\n"
-" {\n"
-" int ringCap = GET_RING_CAPACITY;\n"
-" \n"
-" // 1. fill ring\n"
-" if( ldsGEnd < m_n )\n"
-" {\n"
-" while( ringCap > WG_SIZE )\n"
-" {\n"
-" if( ldsGEnd >= m_n ) break;\n"
-" if( lIdx < ringCap - WG_SIZE )\n"
-" {\n"
-" int srcIdx;\n"
-" AtomInc1( ldsGEnd, srcIdx );\n"
-" if( srcIdx < m_n )\n"
-" {\n"
-" int dstIdx;\n"
-" AtomInc1( ldsRingEnd, dstIdx );\n"
-" \n"
-" int a = gConstraints[m_start+srcIdx].m_bodyAPtrAndSignBit;\n"
-" int b = gConstraints[m_start+srcIdx].m_bodyBPtrAndSignBit;\n"
-" ldsRingElem[dstIdx].m_a = (a>b)? b:a;\n"
-" ldsRingElem[dstIdx].m_b = (a>b)? a:b;\n"
-" ldsRingElem[dstIdx].m_idx = srcIdx;\n"
-" }\n"
-" }\n"
-" ringCap = GET_RING_CAPACITY;\n"
-" }\n"
-" }\n"
-" GROUP_LDS_BARRIER;\n"
-" \n"
-" // 2. fill stack\n"
-" __local Elem* dst = ldsRingElem;\n"
-" if( lIdx == 0 ) RING_END = 0;\n"
-" int srcIdx=lIdx;\n"
-" int end = ldsRingEnd;\n"
-" {\n"
-" for(int ii=0; ii<end; ii+=WG_SIZE, srcIdx+=WG_SIZE)\n"
-" {\n"
-" Elem e;\n"
-" if(srcIdx<end) e = ldsRingElem[srcIdx];\n"
-" bool done = (srcIdx<end)?false:true;\n"
-" for(int i=lIdx; i<CHECK_SIZE; i+=WG_SIZE) ldsCheckBuffer[lIdx] = 0;\n"
-" \n"
-" if( !done )\n"
-" {\n"
-" int aUsed = readBuf( ldsFixedBuffer, abs(e.m_a));\n"
-" int bUsed = readBuf( ldsFixedBuffer, abs(e.m_b));\n"
-" if( aUsed==0 && bUsed==0 )\n"
-" {\n"
-" int aAvailable=1;\n"
-" int bAvailable=1;\n"
-" int ea = abs(e.m_a);\n"
-" int eb = abs(e.m_b);\n"
-" bool aStatic = (e.m_a<0) ||(ea==m_staticIdx);\n"
-" bool bStatic = (e.m_b<0) ||(eb==m_staticIdx);\n"
-" \n"
-" if (!aStatic)\n"
-" aAvailable = tryWrite( ldsCheckBuffer, ea );\n"
-" if (!bStatic)\n"
-" bAvailable = tryWrite( ldsCheckBuffer, eb );\n"
-" \n"
-" //aAvailable = aStatic? 1: aAvailable;\n"
-" //bAvailable = bStatic? 1: bAvailable;\n"
-" bool success = (aAvailable && bAvailable);\n"
-" if(success)\n"
-" {\n"
-" \n"
-" if (!aStatic)\n"
-" writeBuf( ldsFixedBuffer, ea );\n"
-" if (!bStatic)\n"
-" writeBuf( ldsFixedBuffer, eb );\n"
-" }\n"
-" done = success;\n"
-" }\n"
-" }\n"
-" // put it aside\n"
-" if(srcIdx<end)\n"
-" {\n"
-" if( done )\n"
-" {\n"
-" int dstIdx; AtomInc1( ldsStackEnd, dstIdx );\n"
-" if( dstIdx < STACK_SIZE )\n"
-" ldsStackIdx[dstIdx] = e.m_idx;\n"
-" else{\n"
-" done = false;\n"
-" AtomAdd( ldsStackEnd, -1 );\n"
-" }\n"
-" }\n"
-" if( !done )\n"
-" {\n"
-" int dstIdx; AtomInc1( RING_END, dstIdx );\n"
-" dst[dstIdx] = e;\n"
-" }\n"
-" }\n"
-" // if filled, flush\n"
-" if( ldsStackEnd == STACK_SIZE )\n"
-" {\n"
-" for(int i=lIdx; i<STACK_SIZE; i+=WG_SIZE)\n"
-" {\n"
-" int idx = m_start + ldsStackIdx[i];\n"
-" int dstIdx; AtomInc1( ldsDstEnd, dstIdx );\n"
-" gConstraintsOut[ dstIdx ] = gConstraints[ idx ];\n"
-" gConstraintsOut[ dstIdx ].m_batchIdx = ie;\n"
-" }\n"
-" if( lIdx == 0 ) ldsStackEnd = 0;\n"
-" //for(int i=lIdx; i<CHECK_SIZE; i+=WG_SIZE) \n"
-" ldsFixedBuffer[lIdx] = 0;\n"
-" }\n"
-" }\n"
-" }\n"
-" if( lIdx == 0 ) ldsRingEnd = RING_END;\n"
-" }\n"
-" GROUP_LDS_BARRIER;\n"
-" for(int i=lIdx; i<ldsStackEnd; i+=WG_SIZE)\n"
-" {\n"
-" int idx = m_start + ldsStackIdx[i];\n"
-" int dstIdx; AtomInc1( ldsDstEnd, dstIdx );\n"
-" gConstraintsOut[ dstIdx ] = gConstraints[ idx ];\n"
-" gConstraintsOut[ dstIdx ].m_batchIdx = ie;\n"
-" }\n"
-" // in case it couldn't consume any pair. Flush them\n"
-" // todo. Serial batch worth while?\n"
-" if( ldsStackEnd == 0 )\n"
-" {\n"
-" for(int i=lIdx; i<ldsRingEnd; i+=WG_SIZE)\n"
-" {\n"
-" int idx = m_start + ldsRingElem[i].m_idx;\n"
-" int dstIdx; AtomInc1( ldsDstEnd, dstIdx );\n"
-" gConstraintsOut[ dstIdx ] = gConstraints[ idx ];\n"
-" int curBatch = 100+i;\n"
-" if (maxBatch < curBatch)\n"
-" maxBatch = curBatch;\n"
-" \n"
-" gConstraintsOut[ dstIdx ].m_batchIdx = curBatch;\n"
-" \n"
-" }\n"
-" GROUP_LDS_BARRIER;\n"
-" if( lIdx == 0 ) ldsRingEnd = 0;\n"
-" }\n"
-" if( lIdx == 0 ) ldsStackEnd = 0;\n"
-" GROUP_LDS_BARRIER;\n"
-" // termination\n"
-" if( ldsGEnd == m_n && ldsRingEnd == 0 )\n"
-" break;\n"
-" }\n"
-" if( lIdx == 0 )\n"
-" {\n"
-" if (maxBatch < ie)\n"
-" maxBatch=ie;\n"
-" batchSizes[wgIdx]=maxBatch;\n"
-" }\n"
-"}\n"
-;
+static const char* batchingKernelsCL =
+ "/*\n"
+ "Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
+ "This software is provided 'as-is', without any express or implied warranty.\n"
+ "In no event will the authors be held liable for any damages arising from the use of this software.\n"
+ "Permission is granted to anyone to use this software for any purpose, \n"
+ "including commercial applications, and to alter it and redistribute it freely, \n"
+ "subject to the following restrictions:\n"
+ "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
+ "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+ "3. This notice may not be removed or altered from any source distribution.\n"
+ "*/\n"
+ "//Originally written by Takahiro Harada\n"
+ "#ifndef B3_CONTACT4DATA_H\n"
+ "#define B3_CONTACT4DATA_H\n"
+ "#ifndef B3_FLOAT4_H\n"
+ "#define B3_FLOAT4_H\n"
+ "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+ "#define B3_PLATFORM_DEFINITIONS_H\n"
+ "struct MyTest\n"
+ "{\n"
+ " int bla;\n"
+ "};\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
+ "#define B3_LARGE_FLOAT 1e18f\n"
+ "#define B3_INFINITY 1e18f\n"
+ "#define b3Assert(a)\n"
+ "#define b3ConstArray(a) __global const a*\n"
+ "#define b3AtomicInc atomic_inc\n"
+ "#define b3AtomicAdd atomic_add\n"
+ "#define b3Fabs fabs\n"
+ "#define b3Sqrt native_sqrt\n"
+ "#define b3Sin native_sin\n"
+ "#define b3Cos native_cos\n"
+ "#define B3_STATIC\n"
+ "#endif\n"
+ "#endif\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ " typedef float4 b3Float4;\n"
+ " #define b3Float4ConstArg const b3Float4\n"
+ " #define b3MakeFloat4 (float4)\n"
+ " float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+ " {\n"
+ " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+ " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+ " return dot(a1, b1);\n"
+ " }\n"
+ " b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+ " {\n"
+ " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+ " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+ " return cross(a1, b1);\n"
+ " }\n"
+ " #define b3MinFloat4 min\n"
+ " #define b3MaxFloat4 max\n"
+ " #define b3Normalized(a) normalize(a)\n"
+ "#endif \n"
+ " \n"
+ "inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
+ "{\n"
+ " if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
+ " return false;\n"
+ " return true;\n"
+ "}\n"
+ "inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
+ "{\n"
+ " float maxDot = -B3_INFINITY;\n"
+ " int i = 0;\n"
+ " int ptIndex = -1;\n"
+ " for( i = 0; i < vecLen; i++ )\n"
+ " {\n"
+ " float dot = b3Dot3F4(vecArray[i],vec);\n"
+ " \n"
+ " if( dot > maxDot )\n"
+ " {\n"
+ " maxDot = dot;\n"
+ " ptIndex = i;\n"
+ " }\n"
+ " }\n"
+ " b3Assert(ptIndex>=0);\n"
+ " if (ptIndex<0)\n"
+ " {\n"
+ " ptIndex = 0;\n"
+ " }\n"
+ " *dotOut = maxDot;\n"
+ " return ptIndex;\n"
+ "}\n"
+ "#endif //B3_FLOAT4_H\n"
+ "typedef struct b3Contact4Data b3Contact4Data_t;\n"
+ "struct b3Contact4Data\n"
+ "{\n"
+ " b3Float4 m_worldPosB[4];\n"
+ "// b3Float4 m_localPosA[4];\n"
+ "// b3Float4 m_localPosB[4];\n"
+ " b3Float4 m_worldNormalOnB; // w: m_nPoints\n"
+ " unsigned short m_restituitionCoeffCmp;\n"
+ " unsigned short m_frictionCoeffCmp;\n"
+ " int m_batchIdx;\n"
+ " int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
+ " int m_bodyBPtrAndSignBit;\n"
+ " int m_childIndexA;\n"
+ " int m_childIndexB;\n"
+ " int m_unused1;\n"
+ " int m_unused2;\n"
+ "};\n"
+ "inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
+ "{\n"
+ " return (int)contact->m_worldNormalOnB.w;\n"
+ "};\n"
+ "inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
+ "{\n"
+ " contact->m_worldNormalOnB.w = (float)numPoints;\n"
+ "};\n"
+ "#endif //B3_CONTACT4DATA_H\n"
+ "#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
+ "#ifdef cl_ext_atomic_counters_32\n"
+ "#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
+ "#else\n"
+ "#define counter32_t volatile __global int*\n"
+ "#endif\n"
+ "typedef unsigned int u32;\n"
+ "typedef unsigned short u16;\n"
+ "typedef unsigned char u8;\n"
+ "#define GET_GROUP_IDX get_group_id(0)\n"
+ "#define GET_LOCAL_IDX get_local_id(0)\n"
+ "#define GET_GLOBAL_IDX get_global_id(0)\n"
+ "#define GET_GROUP_SIZE get_local_size(0)\n"
+ "#define GET_NUM_GROUPS get_num_groups(0)\n"
+ "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+ "#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
+ "#define AtomInc(x) atom_inc(&(x))\n"
+ "#define AtomInc1(x, out) out = atom_inc(&(x))\n"
+ "#define AppendInc(x, out) out = atomic_inc(x)\n"
+ "#define AtomAdd(x, value) atom_add(&(x), value)\n"
+ "#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
+ "#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
+ "#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
+ "#define make_float4 (float4)\n"
+ "#define make_float2 (float2)\n"
+ "#define make_uint4 (uint4)\n"
+ "#define make_int4 (int4)\n"
+ "#define make_uint2 (uint2)\n"
+ "#define make_int2 (int2)\n"
+ "#define max2 max\n"
+ "#define min2 min\n"
+ "#define WG_SIZE 64\n"
+ "typedef struct \n"
+ "{\n"
+ " int m_n;\n"
+ " int m_start;\n"
+ " int m_staticIdx;\n"
+ " int m_paddings[1];\n"
+ "} ConstBuffer;\n"
+ "typedef struct \n"
+ "{\n"
+ " int m_a;\n"
+ " int m_b;\n"
+ " u32 m_idx;\n"
+ "}Elem;\n"
+ "#define STACK_SIZE (WG_SIZE*10)\n"
+ "//#define STACK_SIZE (WG_SIZE)\n"
+ "#define RING_SIZE 1024\n"
+ "#define RING_SIZE_MASK (RING_SIZE-1)\n"
+ "#define CHECK_SIZE (WG_SIZE)\n"
+ "#define GET_RING_CAPACITY (RING_SIZE - ldsRingEnd)\n"
+ "#define RING_END ldsTmp\n"
+ "u32 readBuf(__local u32* buff, int idx)\n"
+ "{\n"
+ " idx = idx % (32*CHECK_SIZE);\n"
+ " int bitIdx = idx%32;\n"
+ " int bufIdx = idx/32;\n"
+ " return buff[bufIdx] & (1<<bitIdx);\n"
+ "}\n"
+ "void writeBuf(__local u32* buff, int idx)\n"
+ "{\n"
+ " idx = idx % (32*CHECK_SIZE);\n"
+ " int bitIdx = idx%32;\n"
+ " int bufIdx = idx/32;\n"
+ "// buff[bufIdx] |= (1<<bitIdx);\n"
+ " atom_or( &buff[bufIdx], (1<<bitIdx) );\n"
+ "}\n"
+ "u32 tryWrite(__local u32* buff, int idx)\n"
+ "{\n"
+ " idx = idx % (32*CHECK_SIZE);\n"
+ " int bitIdx = idx%32;\n"
+ " int bufIdx = idx/32;\n"
+ " u32 ans = (u32)atom_or( &buff[bufIdx], (1<<bitIdx) );\n"
+ " return ((ans >> bitIdx)&1) == 0;\n"
+ "}\n"
+ "// batching on the GPU\n"
+ "__kernel void CreateBatches( __global const struct b3Contact4Data* gConstraints, __global struct b3Contact4Data* gConstraintsOut,\n"
+ " __global const u32* gN, __global const u32* gStart, __global int* batchSizes, \n"
+ " int m_staticIdx )\n"
+ "{\n"
+ " __local u32 ldsStackIdx[STACK_SIZE];\n"
+ " __local u32 ldsStackEnd;\n"
+ " __local Elem ldsRingElem[RING_SIZE];\n"
+ " __local u32 ldsRingEnd;\n"
+ " __local u32 ldsTmp;\n"
+ " __local u32 ldsCheckBuffer[CHECK_SIZE];\n"
+ " __local u32 ldsFixedBuffer[CHECK_SIZE];\n"
+ " __local u32 ldsGEnd;\n"
+ " __local u32 ldsDstEnd;\n"
+ " int wgIdx = GET_GROUP_IDX;\n"
+ " int lIdx = GET_LOCAL_IDX;\n"
+ " \n"
+ " const int m_n = gN[wgIdx];\n"
+ " const int m_start = gStart[wgIdx];\n"
+ " \n"
+ " if( lIdx == 0 )\n"
+ " {\n"
+ " ldsRingEnd = 0;\n"
+ " ldsGEnd = 0;\n"
+ " ldsStackEnd = 0;\n"
+ " ldsDstEnd = m_start;\n"
+ " }\n"
+ " \n"
+ " \n"
+ " \n"
+ "// while(1)\n"
+ "//was 250\n"
+ " int ie=0;\n"
+ " int maxBatch = 0;\n"
+ " for(ie=0; ie<50; ie++)\n"
+ " {\n"
+ " ldsFixedBuffer[lIdx] = 0;\n"
+ " for(int giter=0; giter<4; giter++)\n"
+ " {\n"
+ " int ringCap = GET_RING_CAPACITY;\n"
+ " \n"
+ " // 1. fill ring\n"
+ " if( ldsGEnd < m_n )\n"
+ " {\n"
+ " while( ringCap > WG_SIZE )\n"
+ " {\n"
+ " if( ldsGEnd >= m_n ) break;\n"
+ " if( lIdx < ringCap - WG_SIZE )\n"
+ " {\n"
+ " int srcIdx;\n"
+ " AtomInc1( ldsGEnd, srcIdx );\n"
+ " if( srcIdx < m_n )\n"
+ " {\n"
+ " int dstIdx;\n"
+ " AtomInc1( ldsRingEnd, dstIdx );\n"
+ " \n"
+ " int a = gConstraints[m_start+srcIdx].m_bodyAPtrAndSignBit;\n"
+ " int b = gConstraints[m_start+srcIdx].m_bodyBPtrAndSignBit;\n"
+ " ldsRingElem[dstIdx].m_a = (a>b)? b:a;\n"
+ " ldsRingElem[dstIdx].m_b = (a>b)? a:b;\n"
+ " ldsRingElem[dstIdx].m_idx = srcIdx;\n"
+ " }\n"
+ " }\n"
+ " ringCap = GET_RING_CAPACITY;\n"
+ " }\n"
+ " }\n"
+ " GROUP_LDS_BARRIER;\n"
+ " \n"
+ " // 2. fill stack\n"
+ " __local Elem* dst = ldsRingElem;\n"
+ " if( lIdx == 0 ) RING_END = 0;\n"
+ " int srcIdx=lIdx;\n"
+ " int end = ldsRingEnd;\n"
+ " {\n"
+ " for(int ii=0; ii<end; ii+=WG_SIZE, srcIdx+=WG_SIZE)\n"
+ " {\n"
+ " Elem e;\n"
+ " if(srcIdx<end) e = ldsRingElem[srcIdx];\n"
+ " bool done = (srcIdx<end)?false:true;\n"
+ " for(int i=lIdx; i<CHECK_SIZE; i+=WG_SIZE) ldsCheckBuffer[lIdx] = 0;\n"
+ " \n"
+ " if( !done )\n"
+ " {\n"
+ " int aUsed = readBuf( ldsFixedBuffer, abs(e.m_a));\n"
+ " int bUsed = readBuf( ldsFixedBuffer, abs(e.m_b));\n"
+ " if( aUsed==0 && bUsed==0 )\n"
+ " {\n"
+ " int aAvailable=1;\n"
+ " int bAvailable=1;\n"
+ " int ea = abs(e.m_a);\n"
+ " int eb = abs(e.m_b);\n"
+ " bool aStatic = (e.m_a<0) ||(ea==m_staticIdx);\n"
+ " bool bStatic = (e.m_b<0) ||(eb==m_staticIdx);\n"
+ " \n"
+ " if (!aStatic)\n"
+ " aAvailable = tryWrite( ldsCheckBuffer, ea );\n"
+ " if (!bStatic)\n"
+ " bAvailable = tryWrite( ldsCheckBuffer, eb );\n"
+ " \n"
+ " //aAvailable = aStatic? 1: aAvailable;\n"
+ " //bAvailable = bStatic? 1: bAvailable;\n"
+ " bool success = (aAvailable && bAvailable);\n"
+ " if(success)\n"
+ " {\n"
+ " \n"
+ " if (!aStatic)\n"
+ " writeBuf( ldsFixedBuffer, ea );\n"
+ " if (!bStatic)\n"
+ " writeBuf( ldsFixedBuffer, eb );\n"
+ " }\n"
+ " done = success;\n"
+ " }\n"
+ " }\n"
+ " // put it aside\n"
+ " if(srcIdx<end)\n"
+ " {\n"
+ " if( done )\n"
+ " {\n"
+ " int dstIdx; AtomInc1( ldsStackEnd, dstIdx );\n"
+ " if( dstIdx < STACK_SIZE )\n"
+ " ldsStackIdx[dstIdx] = e.m_idx;\n"
+ " else{\n"
+ " done = false;\n"
+ " AtomAdd( ldsStackEnd, -1 );\n"
+ " }\n"
+ " }\n"
+ " if( !done )\n"
+ " {\n"
+ " int dstIdx; AtomInc1( RING_END, dstIdx );\n"
+ " dst[dstIdx] = e;\n"
+ " }\n"
+ " }\n"
+ " // if filled, flush\n"
+ " if( ldsStackEnd == STACK_SIZE )\n"
+ " {\n"
+ " for(int i=lIdx; i<STACK_SIZE; i+=WG_SIZE)\n"
+ " {\n"
+ " int idx = m_start + ldsStackIdx[i];\n"
+ " int dstIdx; AtomInc1( ldsDstEnd, dstIdx );\n"
+ " gConstraintsOut[ dstIdx ] = gConstraints[ idx ];\n"
+ " gConstraintsOut[ dstIdx ].m_batchIdx = ie;\n"
+ " }\n"
+ " if( lIdx == 0 ) ldsStackEnd = 0;\n"
+ " //for(int i=lIdx; i<CHECK_SIZE; i+=WG_SIZE) \n"
+ " ldsFixedBuffer[lIdx] = 0;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " if( lIdx == 0 ) ldsRingEnd = RING_END;\n"
+ " }\n"
+ " GROUP_LDS_BARRIER;\n"
+ " for(int i=lIdx; i<ldsStackEnd; i+=WG_SIZE)\n"
+ " {\n"
+ " int idx = m_start + ldsStackIdx[i];\n"
+ " int dstIdx; AtomInc1( ldsDstEnd, dstIdx );\n"
+ " gConstraintsOut[ dstIdx ] = gConstraints[ idx ];\n"
+ " gConstraintsOut[ dstIdx ].m_batchIdx = ie;\n"
+ " }\n"
+ " // in case it couldn't consume any pair. Flush them\n"
+ " // todo. Serial batch worth while?\n"
+ " if( ldsStackEnd == 0 )\n"
+ " {\n"
+ " for(int i=lIdx; i<ldsRingEnd; i+=WG_SIZE)\n"
+ " {\n"
+ " int idx = m_start + ldsRingElem[i].m_idx;\n"
+ " int dstIdx; AtomInc1( ldsDstEnd, dstIdx );\n"
+ " gConstraintsOut[ dstIdx ] = gConstraints[ idx ];\n"
+ " int curBatch = 100+i;\n"
+ " if (maxBatch < curBatch)\n"
+ " maxBatch = curBatch;\n"
+ " \n"
+ " gConstraintsOut[ dstIdx ].m_batchIdx = curBatch;\n"
+ " \n"
+ " }\n"
+ " GROUP_LDS_BARRIER;\n"
+ " if( lIdx == 0 ) ldsRingEnd = 0;\n"
+ " }\n"
+ " if( lIdx == 0 ) ldsStackEnd = 0;\n"
+ " GROUP_LDS_BARRIER;\n"
+ " // termination\n"
+ " if( ldsGEnd == m_n && ldsRingEnd == 0 )\n"
+ " break;\n"
+ " }\n"
+ " if( lIdx == 0 )\n"
+ " {\n"
+ " if (maxBatch < ie)\n"
+ " maxBatch=ie;\n"
+ " batchSizes[wgIdx]=maxBatch;\n"
+ " }\n"
+ "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/batchingKernelsNew.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/batchingKernelsNew.h
index 1e5957adae..05800656cb 100644
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/batchingKernelsNew.h
+++ b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/batchingKernelsNew.h
@@ -1,291 +1,290 @@
//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* batchingKernelsNewCL= \
-"/*\n"
-"Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
-"This software is provided 'as-is', without any express or implied warranty.\n"
-"In no event will the authors be held liable for any damages arising from the use of this software.\n"
-"Permission is granted to anyone to use this software for any purpose, \n"
-"including commercial applications, and to alter it and redistribute it freely, \n"
-"subject to the following restrictions:\n"
-"1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
-"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
-"3. This notice may not be removed or altered from any source distribution.\n"
-"*/\n"
-"//Originally written by Erwin Coumans\n"
-"#ifndef B3_CONTACT4DATA_H\n"
-"#define B3_CONTACT4DATA_H\n"
-"#ifndef B3_FLOAT4_H\n"
-"#define B3_FLOAT4_H\n"
-"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
-"#define B3_PLATFORM_DEFINITIONS_H\n"
-"struct MyTest\n"
-"{\n"
-" int bla;\n"
-"};\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
-"#define B3_LARGE_FLOAT 1e18f\n"
-"#define B3_INFINITY 1e18f\n"
-"#define b3Assert(a)\n"
-"#define b3ConstArray(a) __global const a*\n"
-"#define b3AtomicInc atomic_inc\n"
-"#define b3AtomicAdd atomic_add\n"
-"#define b3Fabs fabs\n"
-"#define b3Sqrt native_sqrt\n"
-"#define b3Sin native_sin\n"
-"#define b3Cos native_cos\n"
-"#define B3_STATIC\n"
-"#endif\n"
-"#endif\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-" typedef float4 b3Float4;\n"
-" #define b3Float4ConstArg const b3Float4\n"
-" #define b3MakeFloat4 (float4)\n"
-" float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
-" {\n"
-" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
-" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
-" return dot(a1, b1);\n"
-" }\n"
-" b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
-" {\n"
-" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
-" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
-" return cross(a1, b1);\n"
-" }\n"
-" #define b3MinFloat4 min\n"
-" #define b3MaxFloat4 max\n"
-" #define b3Normalized(a) normalize(a)\n"
-"#endif \n"
-" \n"
-"inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
-"{\n"
-" if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
-" return false;\n"
-" return true;\n"
-"}\n"
-"inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
-"{\n"
-" float maxDot = -B3_INFINITY;\n"
-" int i = 0;\n"
-" int ptIndex = -1;\n"
-" for( i = 0; i < vecLen; i++ )\n"
-" {\n"
-" float dot = b3Dot3F4(vecArray[i],vec);\n"
-" \n"
-" if( dot > maxDot )\n"
-" {\n"
-" maxDot = dot;\n"
-" ptIndex = i;\n"
-" }\n"
-" }\n"
-" b3Assert(ptIndex>=0);\n"
-" if (ptIndex<0)\n"
-" {\n"
-" ptIndex = 0;\n"
-" }\n"
-" *dotOut = maxDot;\n"
-" return ptIndex;\n"
-"}\n"
-"#endif //B3_FLOAT4_H\n"
-"typedef struct b3Contact4Data b3Contact4Data_t;\n"
-"struct b3Contact4Data\n"
-"{\n"
-" b3Float4 m_worldPosB[4];\n"
-"// b3Float4 m_localPosA[4];\n"
-"// b3Float4 m_localPosB[4];\n"
-" b3Float4 m_worldNormalOnB; // w: m_nPoints\n"
-" unsigned short m_restituitionCoeffCmp;\n"
-" unsigned short m_frictionCoeffCmp;\n"
-" int m_batchIdx;\n"
-" int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
-" int m_bodyBPtrAndSignBit;\n"
-" int m_childIndexA;\n"
-" int m_childIndexB;\n"
-" int m_unused1;\n"
-" int m_unused2;\n"
-"};\n"
-"inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
-"{\n"
-" return (int)contact->m_worldNormalOnB.w;\n"
-"};\n"
-"inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
-"{\n"
-" contact->m_worldNormalOnB.w = (float)numPoints;\n"
-"};\n"
-"#endif //B3_CONTACT4DATA_H\n"
-"#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
-"#ifdef cl_ext_atomic_counters_32\n"
-"#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
-"#else\n"
-"#define counter32_t volatile __global int*\n"
-"#endif\n"
-"#define SIMD_WIDTH 64\n"
-"typedef unsigned int u32;\n"
-"typedef unsigned short u16;\n"
-"typedef unsigned char u8;\n"
-"#define GET_GROUP_IDX get_group_id(0)\n"
-"#define GET_LOCAL_IDX get_local_id(0)\n"
-"#define GET_GLOBAL_IDX get_global_id(0)\n"
-"#define GET_GROUP_SIZE get_local_size(0)\n"
-"#define GET_NUM_GROUPS get_num_groups(0)\n"
-"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
-"#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
-"#define AtomInc(x) atom_inc(&(x))\n"
-"#define AtomInc1(x, out) out = atom_inc(&(x))\n"
-"#define AppendInc(x, out) out = atomic_inc(x)\n"
-"#define AtomAdd(x, value) atom_add(&(x), value)\n"
-"#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
-"#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
-"#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
-"#define make_float4 (float4)\n"
-"#define make_float2 (float2)\n"
-"#define make_uint4 (uint4)\n"
-"#define make_int4 (int4)\n"
-"#define make_uint2 (uint2)\n"
-"#define make_int2 (int2)\n"
-"#define max2 max\n"
-"#define min2 min\n"
-"#define WG_SIZE 64\n"
-"typedef struct \n"
-"{\n"
-" int m_n;\n"
-" int m_start;\n"
-" int m_staticIdx;\n"
-" int m_paddings[1];\n"
-"} ConstBuffer;\n"
-"typedef struct \n"
-"{\n"
-" int m_a;\n"
-" int m_b;\n"
-" u32 m_idx;\n"
-"}Elem;\n"
-"// batching on the GPU\n"
-"__kernel void CreateBatchesBruteForce( __global struct b3Contact4Data* gConstraints, __global const u32* gN, __global const u32* gStart, int m_staticIdx )\n"
-"{\n"
-" int wgIdx = GET_GROUP_IDX;\n"
-" int lIdx = GET_LOCAL_IDX;\n"
-" \n"
-" const int m_n = gN[wgIdx];\n"
-" const int m_start = gStart[wgIdx];\n"
-" \n"
-" if( lIdx == 0 )\n"
-" {\n"
-" for (int i=0;i<m_n;i++)\n"
-" {\n"
-" int srcIdx = i+m_start;\n"
-" int batchIndex = i;\n"
-" gConstraints[ srcIdx ].m_batchIdx = batchIndex; \n"
-" }\n"
-" }\n"
-"}\n"
-"#define CHECK_SIZE (WG_SIZE)\n"
-"u32 readBuf(__local u32* buff, int idx)\n"
-"{\n"
-" idx = idx % (32*CHECK_SIZE);\n"
-" int bitIdx = idx%32;\n"
-" int bufIdx = idx/32;\n"
-" return buff[bufIdx] & (1<<bitIdx);\n"
-"}\n"
-"void writeBuf(__local u32* buff, int idx)\n"
-"{\n"
-" idx = idx % (32*CHECK_SIZE);\n"
-" int bitIdx = idx%32;\n"
-" int bufIdx = idx/32;\n"
-" buff[bufIdx] |= (1<<bitIdx);\n"
-" //atom_or( &buff[bufIdx], (1<<bitIdx) );\n"
-"}\n"
-"u32 tryWrite(__local u32* buff, int idx)\n"
-"{\n"
-" idx = idx % (32*CHECK_SIZE);\n"
-" int bitIdx = idx%32;\n"
-" int bufIdx = idx/32;\n"
-" u32 ans = (u32)atom_or( &buff[bufIdx], (1<<bitIdx) );\n"
-" return ((ans >> bitIdx)&1) == 0;\n"
-"}\n"
-"// batching on the GPU\n"
-"__kernel void CreateBatchesNew( __global struct b3Contact4Data* gConstraints, __global const u32* gN, __global const u32* gStart, __global int* batchSizes, int staticIdx )\n"
-"{\n"
-" int wgIdx = GET_GROUP_IDX;\n"
-" int lIdx = GET_LOCAL_IDX;\n"
-" const int numConstraints = gN[wgIdx];\n"
-" const int m_start = gStart[wgIdx];\n"
-" b3Contact4Data_t tmp;\n"
-" \n"
-" __local u32 ldsFixedBuffer[CHECK_SIZE];\n"
-" \n"
-" \n"
-" \n"
-" \n"
-" \n"
-" if( lIdx == 0 )\n"
-" {\n"
-" \n"
-" \n"
-" __global struct b3Contact4Data* cs = &gConstraints[m_start]; \n"
-" \n"
-" \n"
-" int numValidConstraints = 0;\n"
-" int batchIdx = 0;\n"
-" while( numValidConstraints < numConstraints)\n"
-" {\n"
-" int nCurrentBatch = 0;\n"
-" // clear flag\n"
-" \n"
-" for(int i=0; i<CHECK_SIZE; i++) \n"
-" ldsFixedBuffer[i] = 0; \n"
-" for(int i=numValidConstraints; i<numConstraints; i++)\n"
-" {\n"
-" int bodyAS = cs[i].m_bodyAPtrAndSignBit;\n"
-" int bodyBS = cs[i].m_bodyBPtrAndSignBit;\n"
-" int bodyA = abs(bodyAS);\n"
-" int bodyB = abs(bodyBS);\n"
-" bool aIsStatic = (bodyAS<0) || bodyAS==staticIdx;\n"
-" bool bIsStatic = (bodyBS<0) || bodyBS==staticIdx;\n"
-" int aUnavailable = aIsStatic ? 0 : readBuf( ldsFixedBuffer, bodyA);\n"
-" int bUnavailable = bIsStatic ? 0 : readBuf( ldsFixedBuffer, bodyB);\n"
-" \n"
-" if( aUnavailable==0 && bUnavailable==0 ) // ok\n"
-" {\n"
-" if (!aIsStatic)\n"
-" {\n"
-" writeBuf( ldsFixedBuffer, bodyA );\n"
-" }\n"
-" if (!bIsStatic)\n"
-" {\n"
-" writeBuf( ldsFixedBuffer, bodyB );\n"
-" }\n"
-" cs[i].m_batchIdx = batchIdx;\n"
-" if (i!=numValidConstraints)\n"
-" {\n"
-" tmp = cs[i];\n"
-" cs[i] = cs[numValidConstraints];\n"
-" cs[numValidConstraints] = tmp;\n"
-" }\n"
-" numValidConstraints++;\n"
-" \n"
-" nCurrentBatch++;\n"
-" if( nCurrentBatch == SIMD_WIDTH)\n"
-" {\n"
-" nCurrentBatch = 0;\n"
-" for(int i=0; i<CHECK_SIZE; i++) \n"
-" ldsFixedBuffer[i] = 0;\n"
-" \n"
-" }\n"
-" }\n"
-" }//for\n"
-" batchIdx ++;\n"
-" }//while\n"
-" \n"
-" batchSizes[wgIdx] = batchIdx;\n"
-" }//if( lIdx == 0 )\n"
-" \n"
-" //return batchIdx;\n"
-"}\n"
-;
+static const char* batchingKernelsNewCL =
+ "/*\n"
+ "Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
+ "This software is provided 'as-is', without any express or implied warranty.\n"
+ "In no event will the authors be held liable for any damages arising from the use of this software.\n"
+ "Permission is granted to anyone to use this software for any purpose, \n"
+ "including commercial applications, and to alter it and redistribute it freely, \n"
+ "subject to the following restrictions:\n"
+ "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
+ "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+ "3. This notice may not be removed or altered from any source distribution.\n"
+ "*/\n"
+ "//Originally written by Erwin Coumans\n"
+ "#ifndef B3_CONTACT4DATA_H\n"
+ "#define B3_CONTACT4DATA_H\n"
+ "#ifndef B3_FLOAT4_H\n"
+ "#define B3_FLOAT4_H\n"
+ "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+ "#define B3_PLATFORM_DEFINITIONS_H\n"
+ "struct MyTest\n"
+ "{\n"
+ " int bla;\n"
+ "};\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
+ "#define B3_LARGE_FLOAT 1e18f\n"
+ "#define B3_INFINITY 1e18f\n"
+ "#define b3Assert(a)\n"
+ "#define b3ConstArray(a) __global const a*\n"
+ "#define b3AtomicInc atomic_inc\n"
+ "#define b3AtomicAdd atomic_add\n"
+ "#define b3Fabs fabs\n"
+ "#define b3Sqrt native_sqrt\n"
+ "#define b3Sin native_sin\n"
+ "#define b3Cos native_cos\n"
+ "#define B3_STATIC\n"
+ "#endif\n"
+ "#endif\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ " typedef float4 b3Float4;\n"
+ " #define b3Float4ConstArg const b3Float4\n"
+ " #define b3MakeFloat4 (float4)\n"
+ " float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+ " {\n"
+ " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+ " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+ " return dot(a1, b1);\n"
+ " }\n"
+ " b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+ " {\n"
+ " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+ " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+ " return cross(a1, b1);\n"
+ " }\n"
+ " #define b3MinFloat4 min\n"
+ " #define b3MaxFloat4 max\n"
+ " #define b3Normalized(a) normalize(a)\n"
+ "#endif \n"
+ " \n"
+ "inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
+ "{\n"
+ " if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
+ " return false;\n"
+ " return true;\n"
+ "}\n"
+ "inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
+ "{\n"
+ " float maxDot = -B3_INFINITY;\n"
+ " int i = 0;\n"
+ " int ptIndex = -1;\n"
+ " for( i = 0; i < vecLen; i++ )\n"
+ " {\n"
+ " float dot = b3Dot3F4(vecArray[i],vec);\n"
+ " \n"
+ " if( dot > maxDot )\n"
+ " {\n"
+ " maxDot = dot;\n"
+ " ptIndex = i;\n"
+ " }\n"
+ " }\n"
+ " b3Assert(ptIndex>=0);\n"
+ " if (ptIndex<0)\n"
+ " {\n"
+ " ptIndex = 0;\n"
+ " }\n"
+ " *dotOut = maxDot;\n"
+ " return ptIndex;\n"
+ "}\n"
+ "#endif //B3_FLOAT4_H\n"
+ "typedef struct b3Contact4Data b3Contact4Data_t;\n"
+ "struct b3Contact4Data\n"
+ "{\n"
+ " b3Float4 m_worldPosB[4];\n"
+ "// b3Float4 m_localPosA[4];\n"
+ "// b3Float4 m_localPosB[4];\n"
+ " b3Float4 m_worldNormalOnB; // w: m_nPoints\n"
+ " unsigned short m_restituitionCoeffCmp;\n"
+ " unsigned short m_frictionCoeffCmp;\n"
+ " int m_batchIdx;\n"
+ " int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
+ " int m_bodyBPtrAndSignBit;\n"
+ " int m_childIndexA;\n"
+ " int m_childIndexB;\n"
+ " int m_unused1;\n"
+ " int m_unused2;\n"
+ "};\n"
+ "inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
+ "{\n"
+ " return (int)contact->m_worldNormalOnB.w;\n"
+ "};\n"
+ "inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
+ "{\n"
+ " contact->m_worldNormalOnB.w = (float)numPoints;\n"
+ "};\n"
+ "#endif //B3_CONTACT4DATA_H\n"
+ "#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
+ "#ifdef cl_ext_atomic_counters_32\n"
+ "#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
+ "#else\n"
+ "#define counter32_t volatile __global int*\n"
+ "#endif\n"
+ "#define SIMD_WIDTH 64\n"
+ "typedef unsigned int u32;\n"
+ "typedef unsigned short u16;\n"
+ "typedef unsigned char u8;\n"
+ "#define GET_GROUP_IDX get_group_id(0)\n"
+ "#define GET_LOCAL_IDX get_local_id(0)\n"
+ "#define GET_GLOBAL_IDX get_global_id(0)\n"
+ "#define GET_GROUP_SIZE get_local_size(0)\n"
+ "#define GET_NUM_GROUPS get_num_groups(0)\n"
+ "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+ "#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
+ "#define AtomInc(x) atom_inc(&(x))\n"
+ "#define AtomInc1(x, out) out = atom_inc(&(x))\n"
+ "#define AppendInc(x, out) out = atomic_inc(x)\n"
+ "#define AtomAdd(x, value) atom_add(&(x), value)\n"
+ "#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
+ "#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
+ "#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
+ "#define make_float4 (float4)\n"
+ "#define make_float2 (float2)\n"
+ "#define make_uint4 (uint4)\n"
+ "#define make_int4 (int4)\n"
+ "#define make_uint2 (uint2)\n"
+ "#define make_int2 (int2)\n"
+ "#define max2 max\n"
+ "#define min2 min\n"
+ "#define WG_SIZE 64\n"
+ "typedef struct \n"
+ "{\n"
+ " int m_n;\n"
+ " int m_start;\n"
+ " int m_staticIdx;\n"
+ " int m_paddings[1];\n"
+ "} ConstBuffer;\n"
+ "typedef struct \n"
+ "{\n"
+ " int m_a;\n"
+ " int m_b;\n"
+ " u32 m_idx;\n"
+ "}Elem;\n"
+ "// batching on the GPU\n"
+ "__kernel void CreateBatchesBruteForce( __global struct b3Contact4Data* gConstraints, __global const u32* gN, __global const u32* gStart, int m_staticIdx )\n"
+ "{\n"
+ " int wgIdx = GET_GROUP_IDX;\n"
+ " int lIdx = GET_LOCAL_IDX;\n"
+ " \n"
+ " const int m_n = gN[wgIdx];\n"
+ " const int m_start = gStart[wgIdx];\n"
+ " \n"
+ " if( lIdx == 0 )\n"
+ " {\n"
+ " for (int i=0;i<m_n;i++)\n"
+ " {\n"
+ " int srcIdx = i+m_start;\n"
+ " int batchIndex = i;\n"
+ " gConstraints[ srcIdx ].m_batchIdx = batchIndex; \n"
+ " }\n"
+ " }\n"
+ "}\n"
+ "#define CHECK_SIZE (WG_SIZE)\n"
+ "u32 readBuf(__local u32* buff, int idx)\n"
+ "{\n"
+ " idx = idx % (32*CHECK_SIZE);\n"
+ " int bitIdx = idx%32;\n"
+ " int bufIdx = idx/32;\n"
+ " return buff[bufIdx] & (1<<bitIdx);\n"
+ "}\n"
+ "void writeBuf(__local u32* buff, int idx)\n"
+ "{\n"
+ " idx = idx % (32*CHECK_SIZE);\n"
+ " int bitIdx = idx%32;\n"
+ " int bufIdx = idx/32;\n"
+ " buff[bufIdx] |= (1<<bitIdx);\n"
+ " //atom_or( &buff[bufIdx], (1<<bitIdx) );\n"
+ "}\n"
+ "u32 tryWrite(__local u32* buff, int idx)\n"
+ "{\n"
+ " idx = idx % (32*CHECK_SIZE);\n"
+ " int bitIdx = idx%32;\n"
+ " int bufIdx = idx/32;\n"
+ " u32 ans = (u32)atom_or( &buff[bufIdx], (1<<bitIdx) );\n"
+ " return ((ans >> bitIdx)&1) == 0;\n"
+ "}\n"
+ "// batching on the GPU\n"
+ "__kernel void CreateBatchesNew( __global struct b3Contact4Data* gConstraints, __global const u32* gN, __global const u32* gStart, __global int* batchSizes, int staticIdx )\n"
+ "{\n"
+ " int wgIdx = GET_GROUP_IDX;\n"
+ " int lIdx = GET_LOCAL_IDX;\n"
+ " const int numConstraints = gN[wgIdx];\n"
+ " const int m_start = gStart[wgIdx];\n"
+ " b3Contact4Data_t tmp;\n"
+ " \n"
+ " __local u32 ldsFixedBuffer[CHECK_SIZE];\n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " if( lIdx == 0 )\n"
+ " {\n"
+ " \n"
+ " \n"
+ " __global struct b3Contact4Data* cs = &gConstraints[m_start]; \n"
+ " \n"
+ " \n"
+ " int numValidConstraints = 0;\n"
+ " int batchIdx = 0;\n"
+ " while( numValidConstraints < numConstraints)\n"
+ " {\n"
+ " int nCurrentBatch = 0;\n"
+ " // clear flag\n"
+ " \n"
+ " for(int i=0; i<CHECK_SIZE; i++) \n"
+ " ldsFixedBuffer[i] = 0; \n"
+ " for(int i=numValidConstraints; i<numConstraints; i++)\n"
+ " {\n"
+ " int bodyAS = cs[i].m_bodyAPtrAndSignBit;\n"
+ " int bodyBS = cs[i].m_bodyBPtrAndSignBit;\n"
+ " int bodyA = abs(bodyAS);\n"
+ " int bodyB = abs(bodyBS);\n"
+ " bool aIsStatic = (bodyAS<0) || bodyAS==staticIdx;\n"
+ " bool bIsStatic = (bodyBS<0) || bodyBS==staticIdx;\n"
+ " int aUnavailable = aIsStatic ? 0 : readBuf( ldsFixedBuffer, bodyA);\n"
+ " int bUnavailable = bIsStatic ? 0 : readBuf( ldsFixedBuffer, bodyB);\n"
+ " \n"
+ " if( aUnavailable==0 && bUnavailable==0 ) // ok\n"
+ " {\n"
+ " if (!aIsStatic)\n"
+ " {\n"
+ " writeBuf( ldsFixedBuffer, bodyA );\n"
+ " }\n"
+ " if (!bIsStatic)\n"
+ " {\n"
+ " writeBuf( ldsFixedBuffer, bodyB );\n"
+ " }\n"
+ " cs[i].m_batchIdx = batchIdx;\n"
+ " if (i!=numValidConstraints)\n"
+ " {\n"
+ " tmp = cs[i];\n"
+ " cs[i] = cs[numValidConstraints];\n"
+ " cs[numValidConstraints] = tmp;\n"
+ " }\n"
+ " numValidConstraints++;\n"
+ " \n"
+ " nCurrentBatch++;\n"
+ " if( nCurrentBatch == SIMD_WIDTH)\n"
+ " {\n"
+ " nCurrentBatch = 0;\n"
+ " for(int i=0; i<CHECK_SIZE; i++) \n"
+ " ldsFixedBuffer[i] = 0;\n"
+ " \n"
+ " }\n"
+ " }\n"
+ " }//for\n"
+ " batchIdx ++;\n"
+ " }//while\n"
+ " \n"
+ " batchSizes[wgIdx] = batchIdx;\n"
+ " }//if( lIdx == 0 )\n"
+ " \n"
+ " //return batchIdx;\n"
+ "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/integrateKernel.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/integrateKernel.h
index a5a432947c..6e9c53e161 100644
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/integrateKernel.h
+++ b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/integrateKernel.h
@@ -1,433 +1,432 @@
//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* integrateKernelCL= \
-"/*\n"
-"Copyright (c) 2013 Advanced Micro Devices, Inc. \n"
-"This software is provided 'as-is', without any express or implied warranty.\n"
-"In no event will the authors be held liable for any damages arising from the use of this software.\n"
-"Permission is granted to anyone to use this software for any purpose, \n"
-"including commercial applications, and to alter it and redistribute it freely, \n"
-"subject to the following restrictions:\n"
-"1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
-"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
-"3. This notice may not be removed or altered from any source distribution.\n"
-"*/\n"
-"//Originally written by Erwin Coumans\n"
-"#ifndef B3_RIGIDBODY_DATA_H\n"
-"#define B3_RIGIDBODY_DATA_H\n"
-"#ifndef B3_FLOAT4_H\n"
-"#define B3_FLOAT4_H\n"
-"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
-"#define B3_PLATFORM_DEFINITIONS_H\n"
-"struct MyTest\n"
-"{\n"
-" int bla;\n"
-"};\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
-"#define B3_LARGE_FLOAT 1e18f\n"
-"#define B3_INFINITY 1e18f\n"
-"#define b3Assert(a)\n"
-"#define b3ConstArray(a) __global const a*\n"
-"#define b3AtomicInc atomic_inc\n"
-"#define b3AtomicAdd atomic_add\n"
-"#define b3Fabs fabs\n"
-"#define b3Sqrt native_sqrt\n"
-"#define b3Sin native_sin\n"
-"#define b3Cos native_cos\n"
-"#define B3_STATIC\n"
-"#endif\n"
-"#endif\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-" typedef float4 b3Float4;\n"
-" #define b3Float4ConstArg const b3Float4\n"
-" #define b3MakeFloat4 (float4)\n"
-" float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
-" {\n"
-" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
-" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
-" return dot(a1, b1);\n"
-" }\n"
-" b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
-" {\n"
-" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
-" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
-" return cross(a1, b1);\n"
-" }\n"
-" #define b3MinFloat4 min\n"
-" #define b3MaxFloat4 max\n"
-" #define b3Normalized(a) normalize(a)\n"
-"#endif \n"
-" \n"
-"inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
-"{\n"
-" if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
-" return false;\n"
-" return true;\n"
-"}\n"
-"inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
-"{\n"
-" float maxDot = -B3_INFINITY;\n"
-" int i = 0;\n"
-" int ptIndex = -1;\n"
-" for( i = 0; i < vecLen; i++ )\n"
-" {\n"
-" float dot = b3Dot3F4(vecArray[i],vec);\n"
-" \n"
-" if( dot > maxDot )\n"
-" {\n"
-" maxDot = dot;\n"
-" ptIndex = i;\n"
-" }\n"
-" }\n"
-" b3Assert(ptIndex>=0);\n"
-" if (ptIndex<0)\n"
-" {\n"
-" ptIndex = 0;\n"
-" }\n"
-" *dotOut = maxDot;\n"
-" return ptIndex;\n"
-"}\n"
-"#endif //B3_FLOAT4_H\n"
-"#ifndef B3_QUAT_H\n"
-"#define B3_QUAT_H\n"
-"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#endif\n"
-"#endif\n"
-"#ifndef B3_FLOAT4_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#endif \n"
-"#endif //B3_FLOAT4_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-" typedef float4 b3Quat;\n"
-" #define b3QuatConstArg const b3Quat\n"
-" \n"
-" \n"
-"inline float4 b3FastNormalize4(float4 v)\n"
-"{\n"
-" v = (float4)(v.xyz,0.f);\n"
-" return fast_normalize(v);\n"
-"}\n"
-" \n"
-"inline b3Quat b3QuatMul(b3Quat a, b3Quat b);\n"
-"inline b3Quat b3QuatNormalized(b3QuatConstArg in);\n"
-"inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec);\n"
-"inline b3Quat b3QuatInvert(b3QuatConstArg q);\n"
-"inline b3Quat b3QuatInverse(b3QuatConstArg q);\n"
-"inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b)\n"
-"{\n"
-" b3Quat ans;\n"
-" ans = b3Cross3( a, b );\n"
-" ans += a.w*b+b.w*a;\n"
-"// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
-" ans.w = a.w*b.w - b3Dot3F4(a, b);\n"
-" return ans;\n"
-"}\n"
-"inline b3Quat b3QuatNormalized(b3QuatConstArg in)\n"
-"{\n"
-" b3Quat q;\n"
-" q=in;\n"
-" //return b3FastNormalize4(in);\n"
-" float len = native_sqrt(dot(q, q));\n"
-" if(len > 0.f)\n"
-" {\n"
-" q *= 1.f / len;\n"
-" }\n"
-" else\n"
-" {\n"
-" q.x = q.y = q.z = 0.f;\n"
-" q.w = 1.f;\n"
-" }\n"
-" return q;\n"
-"}\n"
-"inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
-"{\n"
-" b3Quat qInv = b3QuatInvert( q );\n"
-" float4 vcpy = vec;\n"
-" vcpy.w = 0.f;\n"
-" float4 out = b3QuatMul(b3QuatMul(q,vcpy),qInv);\n"
-" return out;\n"
-"}\n"
-"inline b3Quat b3QuatInverse(b3QuatConstArg q)\n"
-"{\n"
-" return (b3Quat)(-q.xyz, q.w);\n"
-"}\n"
-"inline b3Quat b3QuatInvert(b3QuatConstArg q)\n"
-"{\n"
-" return (b3Quat)(-q.xyz, q.w);\n"
-"}\n"
-"inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
-"{\n"
-" return b3QuatRotate( b3QuatInvert( q ), vec );\n"
-"}\n"
-"inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation)\n"
-"{\n"
-" return b3QuatRotate( orientation, point ) + (translation);\n"
-"}\n"
-" \n"
-"#endif \n"
-"#endif //B3_QUAT_H\n"
-"#ifndef B3_MAT3x3_H\n"
-"#define B3_MAT3x3_H\n"
-"#ifndef B3_QUAT_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#endif \n"
-"#endif //B3_QUAT_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"typedef struct\n"
-"{\n"
-" b3Float4 m_row[3];\n"
-"}b3Mat3x3;\n"
-"#define b3Mat3x3ConstArg const b3Mat3x3\n"
-"#define b3GetRow(m,row) (m.m_row[row])\n"
-"inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat)\n"
-"{\n"
-" b3Float4 quat2 = (b3Float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);\n"
-" b3Mat3x3 out;\n"
-" out.m_row[0].x=1-2*quat2.y-2*quat2.z;\n"
-" out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;\n"
-" out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;\n"
-" out.m_row[0].w = 0.f;\n"
-" out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;\n"
-" out.m_row[1].y=1-2*quat2.x-2*quat2.z;\n"
-" out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;\n"
-" out.m_row[1].w = 0.f;\n"
-" out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;\n"
-" out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;\n"
-" out.m_row[2].z=1-2*quat2.x-2*quat2.y;\n"
-" out.m_row[2].w = 0.f;\n"
-" return out;\n"
-"}\n"
-"inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn)\n"
-"{\n"
-" b3Mat3x3 out;\n"
-" out.m_row[0] = fabs(matIn.m_row[0]);\n"
-" out.m_row[1] = fabs(matIn.m_row[1]);\n"
-" out.m_row[2] = fabs(matIn.m_row[2]);\n"
-" return out;\n"
-"}\n"
-"__inline\n"
-"b3Mat3x3 mtZero();\n"
-"__inline\n"
-"b3Mat3x3 mtIdentity();\n"
-"__inline\n"
-"b3Mat3x3 mtTranspose(b3Mat3x3 m);\n"
-"__inline\n"
-"b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);\n"
-"__inline\n"
-"b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);\n"
-"__inline\n"
-"b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);\n"
-"__inline\n"
-"b3Mat3x3 mtZero()\n"
-"{\n"
-" b3Mat3x3 m;\n"
-" m.m_row[0] = (b3Float4)(0.f);\n"
-" m.m_row[1] = (b3Float4)(0.f);\n"
-" m.m_row[2] = (b3Float4)(0.f);\n"
-" return m;\n"
-"}\n"
-"__inline\n"
-"b3Mat3x3 mtIdentity()\n"
-"{\n"
-" b3Mat3x3 m;\n"
-" m.m_row[0] = (b3Float4)(1,0,0,0);\n"
-" m.m_row[1] = (b3Float4)(0,1,0,0);\n"
-" m.m_row[2] = (b3Float4)(0,0,1,0);\n"
-" return m;\n"
-"}\n"
-"__inline\n"
-"b3Mat3x3 mtTranspose(b3Mat3x3 m)\n"
-"{\n"
-" b3Mat3x3 out;\n"
-" out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
-" out.m_row[1] = (b3Float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
-" out.m_row[2] = (b3Float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
-" return out;\n"
-"}\n"
-"__inline\n"
-"b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)\n"
-"{\n"
-" b3Mat3x3 transB;\n"
-" transB = mtTranspose( b );\n"
-" b3Mat3x3 ans;\n"
-" // why this doesn't run when 0ing in the for{}\n"
-" a.m_row[0].w = 0.f;\n"
-" a.m_row[1].w = 0.f;\n"
-" a.m_row[2].w = 0.f;\n"
-" for(int i=0; i<3; i++)\n"
-" {\n"
-"// a.m_row[i].w = 0.f;\n"
-" ans.m_row[i].x = b3Dot3F4(a.m_row[i],transB.m_row[0]);\n"
-" ans.m_row[i].y = b3Dot3F4(a.m_row[i],transB.m_row[1]);\n"
-" ans.m_row[i].z = b3Dot3F4(a.m_row[i],transB.m_row[2]);\n"
-" ans.m_row[i].w = 0.f;\n"
-" }\n"
-" return ans;\n"
-"}\n"
-"__inline\n"
-"b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)\n"
-"{\n"
-" b3Float4 ans;\n"
-" ans.x = b3Dot3F4( a.m_row[0], b );\n"
-" ans.y = b3Dot3F4( a.m_row[1], b );\n"
-" ans.z = b3Dot3F4( a.m_row[2], b );\n"
-" ans.w = 0.f;\n"
-" return ans;\n"
-"}\n"
-"__inline\n"
-"b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)\n"
-"{\n"
-" b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
-" b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
-" b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
-" b3Float4 ans;\n"
-" ans.x = b3Dot3F4( a, colx );\n"
-" ans.y = b3Dot3F4( a, coly );\n"
-" ans.z = b3Dot3F4( a, colz );\n"
-" return ans;\n"
-"}\n"
-"#endif\n"
-"#endif //B3_MAT3x3_H\n"
-"typedef struct b3RigidBodyData b3RigidBodyData_t;\n"
-"struct b3RigidBodyData\n"
-"{\n"
-" b3Float4 m_pos;\n"
-" b3Quat m_quat;\n"
-" b3Float4 m_linVel;\n"
-" b3Float4 m_angVel;\n"
-" int m_collidableIdx;\n"
-" float m_invMass;\n"
-" float m_restituitionCoeff;\n"
-" float m_frictionCoeff;\n"
-"};\n"
-"typedef struct b3InertiaData b3InertiaData_t;\n"
-"struct b3InertiaData\n"
-"{\n"
-" b3Mat3x3 m_invInertiaWorld;\n"
-" b3Mat3x3 m_initInvInertia;\n"
-"};\n"
-"#endif //B3_RIGIDBODY_DATA_H\n"
-" \n"
-"#ifndef B3_RIGIDBODY_DATA_H\n"
-"#endif //B3_RIGIDBODY_DATA_H\n"
-" \n"
-"inline void integrateSingleTransform( __global b3RigidBodyData_t* bodies,int nodeID, float timeStep, float angularDamping, b3Float4ConstArg gravityAcceleration)\n"
-"{\n"
-" \n"
-" if (bodies[nodeID].m_invMass != 0.f)\n"
-" {\n"
-" float BT_GPU_ANGULAR_MOTION_THRESHOLD = (0.25f * 3.14159254f);\n"
-" //angular velocity\n"
-" {\n"
-" b3Float4 axis;\n"
-" //add some hardcoded angular damping\n"
-" bodies[nodeID].m_angVel.x *= angularDamping;\n"
-" bodies[nodeID].m_angVel.y *= angularDamping;\n"
-" bodies[nodeID].m_angVel.z *= angularDamping;\n"
-" \n"
-" b3Float4 angvel = bodies[nodeID].m_angVel;\n"
-" float fAngle = b3Sqrt(b3Dot3F4(angvel, angvel));\n"
-" \n"
-" //limit the angular motion\n"
-" if(fAngle*timeStep > BT_GPU_ANGULAR_MOTION_THRESHOLD)\n"
-" {\n"
-" fAngle = BT_GPU_ANGULAR_MOTION_THRESHOLD / timeStep;\n"
-" }\n"
-" if(fAngle < 0.001f)\n"
-" {\n"
-" // use Taylor's expansions of sync function\n"
-" axis = angvel * (0.5f*timeStep-(timeStep*timeStep*timeStep)*0.020833333333f * fAngle * fAngle);\n"
-" }\n"
-" else\n"
-" {\n"
-" // sync(fAngle) = sin(c*fAngle)/t\n"
-" axis = angvel * ( b3Sin(0.5f * fAngle * timeStep) / fAngle);\n"
-" }\n"
-" \n"
-" b3Quat dorn;\n"
-" dorn.x = axis.x;\n"
-" dorn.y = axis.y;\n"
-" dorn.z = axis.z;\n"
-" dorn.w = b3Cos(fAngle * timeStep * 0.5f);\n"
-" b3Quat orn0 = bodies[nodeID].m_quat;\n"
-" b3Quat predictedOrn = b3QuatMul(dorn, orn0);\n"
-" predictedOrn = b3QuatNormalized(predictedOrn);\n"
-" bodies[nodeID].m_quat=predictedOrn;\n"
-" }\n"
-" //linear velocity \n"
-" bodies[nodeID].m_pos += bodies[nodeID].m_linVel * timeStep;\n"
-" \n"
-" //apply gravity\n"
-" bodies[nodeID].m_linVel += gravityAcceleration * timeStep;\n"
-" \n"
-" }\n"
-" \n"
-"}\n"
-"inline void b3IntegrateTransform( __global b3RigidBodyData_t* body, float timeStep, float angularDamping, b3Float4ConstArg gravityAcceleration)\n"
-"{\n"
-" float BT_GPU_ANGULAR_MOTION_THRESHOLD = (0.25f * 3.14159254f);\n"
-" \n"
-" if( (body->m_invMass != 0.f))\n"
-" {\n"
-" //angular velocity\n"
-" {\n"
-" b3Float4 axis;\n"
-" //add some hardcoded angular damping\n"
-" body->m_angVel.x *= angularDamping;\n"
-" body->m_angVel.y *= angularDamping;\n"
-" body->m_angVel.z *= angularDamping;\n"
-" \n"
-" b3Float4 angvel = body->m_angVel;\n"
-" float fAngle = b3Sqrt(b3Dot3F4(angvel, angvel));\n"
-" //limit the angular motion\n"
-" if(fAngle*timeStep > BT_GPU_ANGULAR_MOTION_THRESHOLD)\n"
-" {\n"
-" fAngle = BT_GPU_ANGULAR_MOTION_THRESHOLD / timeStep;\n"
-" }\n"
-" if(fAngle < 0.001f)\n"
-" {\n"
-" // use Taylor's expansions of sync function\n"
-" axis = angvel * (0.5f*timeStep-(timeStep*timeStep*timeStep)*0.020833333333f * fAngle * fAngle);\n"
-" }\n"
-" else\n"
-" {\n"
-" // sync(fAngle) = sin(c*fAngle)/t\n"
-" axis = angvel * ( b3Sin(0.5f * fAngle * timeStep) / fAngle);\n"
-" }\n"
-" b3Quat dorn;\n"
-" dorn.x = axis.x;\n"
-" dorn.y = axis.y;\n"
-" dorn.z = axis.z;\n"
-" dorn.w = b3Cos(fAngle * timeStep * 0.5f);\n"
-" b3Quat orn0 = body->m_quat;\n"
-" b3Quat predictedOrn = b3QuatMul(dorn, orn0);\n"
-" predictedOrn = b3QuatNormalized(predictedOrn);\n"
-" body->m_quat=predictedOrn;\n"
-" }\n"
-" //apply gravity\n"
-" body->m_linVel += gravityAcceleration * timeStep;\n"
-" //linear velocity \n"
-" body->m_pos += body->m_linVel * timeStep;\n"
-" \n"
-" }\n"
-" \n"
-"}\n"
-"__kernel void \n"
-" integrateTransformsKernel( __global b3RigidBodyData_t* bodies,const int numNodes, float timeStep, float angularDamping, float4 gravityAcceleration)\n"
-"{\n"
-" int nodeID = get_global_id(0);\n"
-" \n"
-" if( nodeID < numNodes)\n"
-" {\n"
-" integrateSingleTransform(bodies,nodeID, timeStep, angularDamping,gravityAcceleration);\n"
-" }\n"
-"}\n"
-;
+static const char* integrateKernelCL =
+ "/*\n"
+ "Copyright (c) 2013 Advanced Micro Devices, Inc. \n"
+ "This software is provided 'as-is', without any express or implied warranty.\n"
+ "In no event will the authors be held liable for any damages arising from the use of this software.\n"
+ "Permission is granted to anyone to use this software for any purpose, \n"
+ "including commercial applications, and to alter it and redistribute it freely, \n"
+ "subject to the following restrictions:\n"
+ "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
+ "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+ "3. This notice may not be removed or altered from any source distribution.\n"
+ "*/\n"
+ "//Originally written by Erwin Coumans\n"
+ "#ifndef B3_RIGIDBODY_DATA_H\n"
+ "#define B3_RIGIDBODY_DATA_H\n"
+ "#ifndef B3_FLOAT4_H\n"
+ "#define B3_FLOAT4_H\n"
+ "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+ "#define B3_PLATFORM_DEFINITIONS_H\n"
+ "struct MyTest\n"
+ "{\n"
+ " int bla;\n"
+ "};\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
+ "#define B3_LARGE_FLOAT 1e18f\n"
+ "#define B3_INFINITY 1e18f\n"
+ "#define b3Assert(a)\n"
+ "#define b3ConstArray(a) __global const a*\n"
+ "#define b3AtomicInc atomic_inc\n"
+ "#define b3AtomicAdd atomic_add\n"
+ "#define b3Fabs fabs\n"
+ "#define b3Sqrt native_sqrt\n"
+ "#define b3Sin native_sin\n"
+ "#define b3Cos native_cos\n"
+ "#define B3_STATIC\n"
+ "#endif\n"
+ "#endif\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ " typedef float4 b3Float4;\n"
+ " #define b3Float4ConstArg const b3Float4\n"
+ " #define b3MakeFloat4 (float4)\n"
+ " float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+ " {\n"
+ " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+ " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+ " return dot(a1, b1);\n"
+ " }\n"
+ " b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+ " {\n"
+ " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+ " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+ " return cross(a1, b1);\n"
+ " }\n"
+ " #define b3MinFloat4 min\n"
+ " #define b3MaxFloat4 max\n"
+ " #define b3Normalized(a) normalize(a)\n"
+ "#endif \n"
+ " \n"
+ "inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
+ "{\n"
+ " if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
+ " return false;\n"
+ " return true;\n"
+ "}\n"
+ "inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
+ "{\n"
+ " float maxDot = -B3_INFINITY;\n"
+ " int i = 0;\n"
+ " int ptIndex = -1;\n"
+ " for( i = 0; i < vecLen; i++ )\n"
+ " {\n"
+ " float dot = b3Dot3F4(vecArray[i],vec);\n"
+ " \n"
+ " if( dot > maxDot )\n"
+ " {\n"
+ " maxDot = dot;\n"
+ " ptIndex = i;\n"
+ " }\n"
+ " }\n"
+ " b3Assert(ptIndex>=0);\n"
+ " if (ptIndex<0)\n"
+ " {\n"
+ " ptIndex = 0;\n"
+ " }\n"
+ " *dotOut = maxDot;\n"
+ " return ptIndex;\n"
+ "}\n"
+ "#endif //B3_FLOAT4_H\n"
+ "#ifndef B3_QUAT_H\n"
+ "#define B3_QUAT_H\n"
+ "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#endif\n"
+ "#endif\n"
+ "#ifndef B3_FLOAT4_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#endif \n"
+ "#endif //B3_FLOAT4_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ " typedef float4 b3Quat;\n"
+ " #define b3QuatConstArg const b3Quat\n"
+ " \n"
+ " \n"
+ "inline float4 b3FastNormalize4(float4 v)\n"
+ "{\n"
+ " v = (float4)(v.xyz,0.f);\n"
+ " return fast_normalize(v);\n"
+ "}\n"
+ " \n"
+ "inline b3Quat b3QuatMul(b3Quat a, b3Quat b);\n"
+ "inline b3Quat b3QuatNormalized(b3QuatConstArg in);\n"
+ "inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec);\n"
+ "inline b3Quat b3QuatInvert(b3QuatConstArg q);\n"
+ "inline b3Quat b3QuatInverse(b3QuatConstArg q);\n"
+ "inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b)\n"
+ "{\n"
+ " b3Quat ans;\n"
+ " ans = b3Cross3( a, b );\n"
+ " ans += a.w*b+b.w*a;\n"
+ "// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+ " ans.w = a.w*b.w - b3Dot3F4(a, b);\n"
+ " return ans;\n"
+ "}\n"
+ "inline b3Quat b3QuatNormalized(b3QuatConstArg in)\n"
+ "{\n"
+ " b3Quat q;\n"
+ " q=in;\n"
+ " //return b3FastNormalize4(in);\n"
+ " float len = native_sqrt(dot(q, q));\n"
+ " if(len > 0.f)\n"
+ " {\n"
+ " q *= 1.f / len;\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " q.x = q.y = q.z = 0.f;\n"
+ " q.w = 1.f;\n"
+ " }\n"
+ " return q;\n"
+ "}\n"
+ "inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+ "{\n"
+ " b3Quat qInv = b3QuatInvert( q );\n"
+ " float4 vcpy = vec;\n"
+ " vcpy.w = 0.f;\n"
+ " float4 out = b3QuatMul(b3QuatMul(q,vcpy),qInv);\n"
+ " return out;\n"
+ "}\n"
+ "inline b3Quat b3QuatInverse(b3QuatConstArg q)\n"
+ "{\n"
+ " return (b3Quat)(-q.xyz, q.w);\n"
+ "}\n"
+ "inline b3Quat b3QuatInvert(b3QuatConstArg q)\n"
+ "{\n"
+ " return (b3Quat)(-q.xyz, q.w);\n"
+ "}\n"
+ "inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+ "{\n"
+ " return b3QuatRotate( b3QuatInvert( q ), vec );\n"
+ "}\n"
+ "inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation)\n"
+ "{\n"
+ " return b3QuatRotate( orientation, point ) + (translation);\n"
+ "}\n"
+ " \n"
+ "#endif \n"
+ "#endif //B3_QUAT_H\n"
+ "#ifndef B3_MAT3x3_H\n"
+ "#define B3_MAT3x3_H\n"
+ "#ifndef B3_QUAT_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#endif \n"
+ "#endif //B3_QUAT_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "typedef struct\n"
+ "{\n"
+ " b3Float4 m_row[3];\n"
+ "}b3Mat3x3;\n"
+ "#define b3Mat3x3ConstArg const b3Mat3x3\n"
+ "#define b3GetRow(m,row) (m.m_row[row])\n"
+ "inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat)\n"
+ "{\n"
+ " b3Float4 quat2 = (b3Float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);\n"
+ " b3Mat3x3 out;\n"
+ " out.m_row[0].x=1-2*quat2.y-2*quat2.z;\n"
+ " out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;\n"
+ " out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;\n"
+ " out.m_row[0].w = 0.f;\n"
+ " out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;\n"
+ " out.m_row[1].y=1-2*quat2.x-2*quat2.z;\n"
+ " out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;\n"
+ " out.m_row[1].w = 0.f;\n"
+ " out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;\n"
+ " out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;\n"
+ " out.m_row[2].z=1-2*quat2.x-2*quat2.y;\n"
+ " out.m_row[2].w = 0.f;\n"
+ " return out;\n"
+ "}\n"
+ "inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn)\n"
+ "{\n"
+ " b3Mat3x3 out;\n"
+ " out.m_row[0] = fabs(matIn.m_row[0]);\n"
+ " out.m_row[1] = fabs(matIn.m_row[1]);\n"
+ " out.m_row[2] = fabs(matIn.m_row[2]);\n"
+ " return out;\n"
+ "}\n"
+ "__inline\n"
+ "b3Mat3x3 mtZero();\n"
+ "__inline\n"
+ "b3Mat3x3 mtIdentity();\n"
+ "__inline\n"
+ "b3Mat3x3 mtTranspose(b3Mat3x3 m);\n"
+ "__inline\n"
+ "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);\n"
+ "__inline\n"
+ "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);\n"
+ "__inline\n"
+ "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);\n"
+ "__inline\n"
+ "b3Mat3x3 mtZero()\n"
+ "{\n"
+ " b3Mat3x3 m;\n"
+ " m.m_row[0] = (b3Float4)(0.f);\n"
+ " m.m_row[1] = (b3Float4)(0.f);\n"
+ " m.m_row[2] = (b3Float4)(0.f);\n"
+ " return m;\n"
+ "}\n"
+ "__inline\n"
+ "b3Mat3x3 mtIdentity()\n"
+ "{\n"
+ " b3Mat3x3 m;\n"
+ " m.m_row[0] = (b3Float4)(1,0,0,0);\n"
+ " m.m_row[1] = (b3Float4)(0,1,0,0);\n"
+ " m.m_row[2] = (b3Float4)(0,0,1,0);\n"
+ " return m;\n"
+ "}\n"
+ "__inline\n"
+ "b3Mat3x3 mtTranspose(b3Mat3x3 m)\n"
+ "{\n"
+ " b3Mat3x3 out;\n"
+ " out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
+ " out.m_row[1] = (b3Float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
+ " out.m_row[2] = (b3Float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
+ " return out;\n"
+ "}\n"
+ "__inline\n"
+ "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)\n"
+ "{\n"
+ " b3Mat3x3 transB;\n"
+ " transB = mtTranspose( b );\n"
+ " b3Mat3x3 ans;\n"
+ " // why this doesn't run when 0ing in the for{}\n"
+ " a.m_row[0].w = 0.f;\n"
+ " a.m_row[1].w = 0.f;\n"
+ " a.m_row[2].w = 0.f;\n"
+ " for(int i=0; i<3; i++)\n"
+ " {\n"
+ "// a.m_row[i].w = 0.f;\n"
+ " ans.m_row[i].x = b3Dot3F4(a.m_row[i],transB.m_row[0]);\n"
+ " ans.m_row[i].y = b3Dot3F4(a.m_row[i],transB.m_row[1]);\n"
+ " ans.m_row[i].z = b3Dot3F4(a.m_row[i],transB.m_row[2]);\n"
+ " ans.m_row[i].w = 0.f;\n"
+ " }\n"
+ " return ans;\n"
+ "}\n"
+ "__inline\n"
+ "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)\n"
+ "{\n"
+ " b3Float4 ans;\n"
+ " ans.x = b3Dot3F4( a.m_row[0], b );\n"
+ " ans.y = b3Dot3F4( a.m_row[1], b );\n"
+ " ans.z = b3Dot3F4( a.m_row[2], b );\n"
+ " ans.w = 0.f;\n"
+ " return ans;\n"
+ "}\n"
+ "__inline\n"
+ "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)\n"
+ "{\n"
+ " b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
+ " b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
+ " b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
+ " b3Float4 ans;\n"
+ " ans.x = b3Dot3F4( a, colx );\n"
+ " ans.y = b3Dot3F4( a, coly );\n"
+ " ans.z = b3Dot3F4( a, colz );\n"
+ " return ans;\n"
+ "}\n"
+ "#endif\n"
+ "#endif //B3_MAT3x3_H\n"
+ "typedef struct b3RigidBodyData b3RigidBodyData_t;\n"
+ "struct b3RigidBodyData\n"
+ "{\n"
+ " b3Float4 m_pos;\n"
+ " b3Quat m_quat;\n"
+ " b3Float4 m_linVel;\n"
+ " b3Float4 m_angVel;\n"
+ " int m_collidableIdx;\n"
+ " float m_invMass;\n"
+ " float m_restituitionCoeff;\n"
+ " float m_frictionCoeff;\n"
+ "};\n"
+ "typedef struct b3InertiaData b3InertiaData_t;\n"
+ "struct b3InertiaData\n"
+ "{\n"
+ " b3Mat3x3 m_invInertiaWorld;\n"
+ " b3Mat3x3 m_initInvInertia;\n"
+ "};\n"
+ "#endif //B3_RIGIDBODY_DATA_H\n"
+ " \n"
+ "#ifndef B3_RIGIDBODY_DATA_H\n"
+ "#endif //B3_RIGIDBODY_DATA_H\n"
+ " \n"
+ "inline void integrateSingleTransform( __global b3RigidBodyData_t* bodies,int nodeID, float timeStep, float angularDamping, b3Float4ConstArg gravityAcceleration)\n"
+ "{\n"
+ " \n"
+ " if (bodies[nodeID].m_invMass != 0.f)\n"
+ " {\n"
+ " float BT_GPU_ANGULAR_MOTION_THRESHOLD = (0.25f * 3.14159254f);\n"
+ " //angular velocity\n"
+ " {\n"
+ " b3Float4 axis;\n"
+ " //add some hardcoded angular damping\n"
+ " bodies[nodeID].m_angVel.x *= angularDamping;\n"
+ " bodies[nodeID].m_angVel.y *= angularDamping;\n"
+ " bodies[nodeID].m_angVel.z *= angularDamping;\n"
+ " \n"
+ " b3Float4 angvel = bodies[nodeID].m_angVel;\n"
+ " float fAngle = b3Sqrt(b3Dot3F4(angvel, angvel));\n"
+ " \n"
+ " //limit the angular motion\n"
+ " if(fAngle*timeStep > BT_GPU_ANGULAR_MOTION_THRESHOLD)\n"
+ " {\n"
+ " fAngle = BT_GPU_ANGULAR_MOTION_THRESHOLD / timeStep;\n"
+ " }\n"
+ " if(fAngle < 0.001f)\n"
+ " {\n"
+ " // use Taylor's expansions of sync function\n"
+ " axis = angvel * (0.5f*timeStep-(timeStep*timeStep*timeStep)*0.020833333333f * fAngle * fAngle);\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " // sync(fAngle) = sin(c*fAngle)/t\n"
+ " axis = angvel * ( b3Sin(0.5f * fAngle * timeStep) / fAngle);\n"
+ " }\n"
+ " \n"
+ " b3Quat dorn;\n"
+ " dorn.x = axis.x;\n"
+ " dorn.y = axis.y;\n"
+ " dorn.z = axis.z;\n"
+ " dorn.w = b3Cos(fAngle * timeStep * 0.5f);\n"
+ " b3Quat orn0 = bodies[nodeID].m_quat;\n"
+ " b3Quat predictedOrn = b3QuatMul(dorn, orn0);\n"
+ " predictedOrn = b3QuatNormalized(predictedOrn);\n"
+ " bodies[nodeID].m_quat=predictedOrn;\n"
+ " }\n"
+ " //linear velocity \n"
+ " bodies[nodeID].m_pos += bodies[nodeID].m_linVel * timeStep;\n"
+ " \n"
+ " //apply gravity\n"
+ " bodies[nodeID].m_linVel += gravityAcceleration * timeStep;\n"
+ " \n"
+ " }\n"
+ " \n"
+ "}\n"
+ "inline void b3IntegrateTransform( __global b3RigidBodyData_t* body, float timeStep, float angularDamping, b3Float4ConstArg gravityAcceleration)\n"
+ "{\n"
+ " float BT_GPU_ANGULAR_MOTION_THRESHOLD = (0.25f * 3.14159254f);\n"
+ " \n"
+ " if( (body->m_invMass != 0.f))\n"
+ " {\n"
+ " //angular velocity\n"
+ " {\n"
+ " b3Float4 axis;\n"
+ " //add some hardcoded angular damping\n"
+ " body->m_angVel.x *= angularDamping;\n"
+ " body->m_angVel.y *= angularDamping;\n"
+ " body->m_angVel.z *= angularDamping;\n"
+ " \n"
+ " b3Float4 angvel = body->m_angVel;\n"
+ " float fAngle = b3Sqrt(b3Dot3F4(angvel, angvel));\n"
+ " //limit the angular motion\n"
+ " if(fAngle*timeStep > BT_GPU_ANGULAR_MOTION_THRESHOLD)\n"
+ " {\n"
+ " fAngle = BT_GPU_ANGULAR_MOTION_THRESHOLD / timeStep;\n"
+ " }\n"
+ " if(fAngle < 0.001f)\n"
+ " {\n"
+ " // use Taylor's expansions of sync function\n"
+ " axis = angvel * (0.5f*timeStep-(timeStep*timeStep*timeStep)*0.020833333333f * fAngle * fAngle);\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " // sync(fAngle) = sin(c*fAngle)/t\n"
+ " axis = angvel * ( b3Sin(0.5f * fAngle * timeStep) / fAngle);\n"
+ " }\n"
+ " b3Quat dorn;\n"
+ " dorn.x = axis.x;\n"
+ " dorn.y = axis.y;\n"
+ " dorn.z = axis.z;\n"
+ " dorn.w = b3Cos(fAngle * timeStep * 0.5f);\n"
+ " b3Quat orn0 = body->m_quat;\n"
+ " b3Quat predictedOrn = b3QuatMul(dorn, orn0);\n"
+ " predictedOrn = b3QuatNormalized(predictedOrn);\n"
+ " body->m_quat=predictedOrn;\n"
+ " }\n"
+ " //apply gravity\n"
+ " body->m_linVel += gravityAcceleration * timeStep;\n"
+ " //linear velocity \n"
+ " body->m_pos += body->m_linVel * timeStep;\n"
+ " \n"
+ " }\n"
+ " \n"
+ "}\n"
+ "__kernel void \n"
+ " integrateTransformsKernel( __global b3RigidBodyData_t* bodies,const int numNodes, float timeStep, float angularDamping, float4 gravityAcceleration)\n"
+ "{\n"
+ " int nodeID = get_global_id(0);\n"
+ " \n"
+ " if( nodeID < numNodes)\n"
+ " {\n"
+ " integrateSingleTransform(bodies,nodeID, timeStep, angularDamping,gravityAcceleration);\n"
+ " }\n"
+ "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/jointSolver.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/jointSolver.h
index d48ecf6ea6..c94b55851e 100644
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/jointSolver.h
+++ b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/jointSolver.h
@@ -1,721 +1,720 @@
//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* solveConstraintRowsCL= \
-"/*\n"
-"Copyright (c) 2013 Advanced Micro Devices, Inc. \n"
-"This software is provided 'as-is', without any express or implied warranty.\n"
-"In no event will the authors be held liable for any damages arising from the use of this software.\n"
-"Permission is granted to anyone to use this software for any purpose, \n"
-"including commercial applications, and to alter it and redistribute it freely, \n"
-"subject to the following restrictions:\n"
-"1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
-"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
-"3. This notice may not be removed or altered from any source distribution.\n"
-"*/\n"
-"//Originally written by Erwin Coumans\n"
-"#define B3_CONSTRAINT_FLAG_ENABLED 1\n"
-"#define B3_GPU_POINT2POINT_CONSTRAINT_TYPE 3\n"
-"#define B3_GPU_FIXED_CONSTRAINT_TYPE 4\n"
-"#define MOTIONCLAMP 100000 //unused, for debugging/safety in case constraint solver fails\n"
-"#define B3_INFINITY 1e30f\n"
-"#define mymake_float4 (float4)\n"
-"__inline float dot3F4(float4 a, float4 b)\n"
-"{\n"
-" float4 a1 = mymake_float4(a.xyz,0.f);\n"
-" float4 b1 = mymake_float4(b.xyz,0.f);\n"
-" return dot(a1, b1);\n"
-"}\n"
-"typedef float4 Quaternion;\n"
-"typedef struct\n"
-"{\n"
-" float4 m_row[3];\n"
-"}Matrix3x3;\n"
-"__inline\n"
-"float4 mtMul1(Matrix3x3 a, float4 b);\n"
-"__inline\n"
-"float4 mtMul3(float4 a, Matrix3x3 b);\n"
-"__inline\n"
-"float4 mtMul1(Matrix3x3 a, float4 b)\n"
-"{\n"
-" float4 ans;\n"
-" ans.x = dot3F4( a.m_row[0], b );\n"
-" ans.y = dot3F4( a.m_row[1], b );\n"
-" ans.z = dot3F4( a.m_row[2], b );\n"
-" ans.w = 0.f;\n"
-" return ans;\n"
-"}\n"
-"__inline\n"
-"float4 mtMul3(float4 a, Matrix3x3 b)\n"
-"{\n"
-" float4 colx = mymake_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
-" float4 coly = mymake_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
-" float4 colz = mymake_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
-" float4 ans;\n"
-" ans.x = dot3F4( a, colx );\n"
-" ans.y = dot3F4( a, coly );\n"
-" ans.z = dot3F4( a, colz );\n"
-" return ans;\n"
-"}\n"
-"typedef struct\n"
-"{\n"
-" Matrix3x3 m_invInertiaWorld;\n"
-" Matrix3x3 m_initInvInertia;\n"
-"} BodyInertia;\n"
-"typedef struct\n"
-"{\n"
-" Matrix3x3 m_basis;//orientation\n"
-" float4 m_origin;//transform\n"
-"}b3Transform;\n"
-"typedef struct\n"
-"{\n"
-"// b3Transform m_worldTransformUnused;\n"
-" float4 m_deltaLinearVelocity;\n"
-" float4 m_deltaAngularVelocity;\n"
-" float4 m_angularFactor;\n"
-" float4 m_linearFactor;\n"
-" float4 m_invMass;\n"
-" float4 m_pushVelocity;\n"
-" float4 m_turnVelocity;\n"
-" float4 m_linearVelocity;\n"
-" float4 m_angularVelocity;\n"
-" union \n"
-" {\n"
-" void* m_originalBody;\n"
-" int m_originalBodyIndex;\n"
-" };\n"
-" int padding[3];\n"
-"} b3GpuSolverBody;\n"
-"typedef struct\n"
-"{\n"
-" float4 m_pos;\n"
-" Quaternion m_quat;\n"
-" float4 m_linVel;\n"
-" float4 m_angVel;\n"
-" unsigned int m_shapeIdx;\n"
-" float m_invMass;\n"
-" float m_restituitionCoeff;\n"
-" float m_frictionCoeff;\n"
-"} b3RigidBodyCL;\n"
-"typedef struct\n"
-"{\n"
-" float4 m_relpos1CrossNormal;\n"
-" float4 m_contactNormal;\n"
-" float4 m_relpos2CrossNormal;\n"
-" //float4 m_contactNormal2;//usually m_contactNormal2 == -m_contactNormal\n"
-" float4 m_angularComponentA;\n"
-" float4 m_angularComponentB;\n"
-" \n"
-" float m_appliedPushImpulse;\n"
-" float m_appliedImpulse;\n"
-" int m_padding1;\n"
-" int m_padding2;\n"
-" float m_friction;\n"
-" float m_jacDiagABInv;\n"
-" float m_rhs;\n"
-" float m_cfm;\n"
-" \n"
-" float m_lowerLimit;\n"
-" float m_upperLimit;\n"
-" float m_rhsPenetration;\n"
-" int m_originalConstraint;\n"
-" int m_overrideNumSolverIterations;\n"
-" int m_frictionIndex;\n"
-" int m_solverBodyIdA;\n"
-" int m_solverBodyIdB;\n"
-"} b3SolverConstraint;\n"
-"typedef struct \n"
-"{\n"
-" int m_bodyAPtrAndSignBit;\n"
-" int m_bodyBPtrAndSignBit;\n"
-" int m_originalConstraintIndex;\n"
-" int m_batchId;\n"
-"} b3BatchConstraint;\n"
-"typedef struct \n"
-"{\n"
-" int m_constraintType;\n"
-" int m_rbA;\n"
-" int m_rbB;\n"
-" float m_breakingImpulseThreshold;\n"
-" float4 m_pivotInA;\n"
-" float4 m_pivotInB;\n"
-" Quaternion m_relTargetAB;\n"
-" int m_flags;\n"
-" int m_padding[3];\n"
-"} b3GpuGenericConstraint;\n"
-"/*b3Transform getWorldTransform(b3RigidBodyCL* rb)\n"
-"{\n"
-" b3Transform newTrans;\n"
-" newTrans.setOrigin(rb->m_pos);\n"
-" newTrans.setRotation(rb->m_quat);\n"
-" return newTrans;\n"
-"}*/\n"
-"__inline\n"
-"float4 cross3(float4 a, float4 b)\n"
-"{\n"
-" return cross(a,b);\n"
-"}\n"
-"__inline\n"
-"float4 fastNormalize4(float4 v)\n"
-"{\n"
-" v = mymake_float4(v.xyz,0.f);\n"
-" return fast_normalize(v);\n"
-"}\n"
-"__inline\n"
-"Quaternion qtMul(Quaternion a, Quaternion b);\n"
-"__inline\n"
-"Quaternion qtNormalize(Quaternion in);\n"
-"__inline\n"
-"float4 qtRotate(Quaternion q, float4 vec);\n"
-"__inline\n"
-"Quaternion qtInvert(Quaternion q);\n"
-"__inline\n"
-"Quaternion qtMul(Quaternion a, Quaternion b)\n"
-"{\n"
-" Quaternion ans;\n"
-" ans = cross3( a, b );\n"
-" ans += a.w*b+b.w*a;\n"
-"// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
-" ans.w = a.w*b.w - dot3F4(a, b);\n"
-" return ans;\n"
-"}\n"
-"__inline\n"
-"Quaternion qtNormalize(Quaternion in)\n"
-"{\n"
-" return fastNormalize4(in);\n"
-"// in /= length( in );\n"
-"// return in;\n"
-"}\n"
-"__inline\n"
-"float4 qtRotate(Quaternion q, float4 vec)\n"
-"{\n"
-" Quaternion qInv = qtInvert( q );\n"
-" float4 vcpy = vec;\n"
-" vcpy.w = 0.f;\n"
-" float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
-" return out;\n"
-"}\n"
-"__inline\n"
-"Quaternion qtInvert(Quaternion q)\n"
-"{\n"
-" return (Quaternion)(-q.xyz, q.w);\n"
-"}\n"
-"__inline void internalApplyImpulse(__global b3GpuSolverBody* body, float4 linearComponent, float4 angularComponent,float impulseMagnitude)\n"
-"{\n"
-" body->m_deltaLinearVelocity += linearComponent*impulseMagnitude*body->m_linearFactor;\n"
-" body->m_deltaAngularVelocity += angularComponent*(impulseMagnitude*body->m_angularFactor);\n"
-"}\n"
-"void resolveSingleConstraintRowGeneric(__global b3GpuSolverBody* body1, __global b3GpuSolverBody* body2, __global b3SolverConstraint* c)\n"
-"{\n"
-" float deltaImpulse = c->m_rhs-c->m_appliedImpulse*c->m_cfm;\n"
-" float deltaVel1Dotn = dot3F4(c->m_contactNormal,body1->m_deltaLinearVelocity) + dot3F4(c->m_relpos1CrossNormal,body1->m_deltaAngularVelocity);\n"
-" float deltaVel2Dotn = -dot3F4(c->m_contactNormal,body2->m_deltaLinearVelocity) + dot3F4(c->m_relpos2CrossNormal,body2->m_deltaAngularVelocity);\n"
-" deltaImpulse -= deltaVel1Dotn*c->m_jacDiagABInv;\n"
-" deltaImpulse -= deltaVel2Dotn*c->m_jacDiagABInv;\n"
-" float sum = c->m_appliedImpulse + deltaImpulse;\n"
-" if (sum < c->m_lowerLimit)\n"
-" {\n"
-" deltaImpulse = c->m_lowerLimit-c->m_appliedImpulse;\n"
-" c->m_appliedImpulse = c->m_lowerLimit;\n"
-" }\n"
-" else if (sum > c->m_upperLimit) \n"
-" {\n"
-" deltaImpulse = c->m_upperLimit-c->m_appliedImpulse;\n"
-" c->m_appliedImpulse = c->m_upperLimit;\n"
-" }\n"
-" else\n"
-" {\n"
-" c->m_appliedImpulse = sum;\n"
-" }\n"
-" internalApplyImpulse(body1,c->m_contactNormal*body1->m_invMass,c->m_angularComponentA,deltaImpulse);\n"
-" internalApplyImpulse(body2,-c->m_contactNormal*body2->m_invMass,c->m_angularComponentB,deltaImpulse);\n"
-"}\n"
-"__kernel void solveJointConstraintRows(__global b3GpuSolverBody* solverBodies,\n"
-" __global b3BatchConstraint* batchConstraints,\n"
-" __global b3SolverConstraint* rows,\n"
-" __global unsigned int* numConstraintRowsInfo1, \n"
-" __global unsigned int* rowOffsets,\n"
-" __global b3GpuGenericConstraint* constraints,\n"
-" int batchOffset,\n"
-" int numConstraintsInBatch\n"
-" )\n"
-"{\n"
-" int b = get_global_id(0);\n"
-" if (b>=numConstraintsInBatch)\n"
-" return;\n"
-" __global b3BatchConstraint* c = &batchConstraints[b+batchOffset];\n"
-" int originalConstraintIndex = c->m_originalConstraintIndex;\n"
-" if (constraints[originalConstraintIndex].m_flags&B3_CONSTRAINT_FLAG_ENABLED)\n"
-" {\n"
-" int numConstraintRows = numConstraintRowsInfo1[originalConstraintIndex];\n"
-" int rowOffset = rowOffsets[originalConstraintIndex];\n"
-" for (int jj=0;jj<numConstraintRows;jj++)\n"
-" {\n"
-" __global b3SolverConstraint* constraint = &rows[rowOffset+jj];\n"
-" resolveSingleConstraintRowGeneric(&solverBodies[constraint->m_solverBodyIdA],&solverBodies[constraint->m_solverBodyIdB],constraint);\n"
-" }\n"
-" }\n"
-"};\n"
-"__kernel void initSolverBodies(__global b3GpuSolverBody* solverBodies,__global b3RigidBodyCL* bodiesCL, int numBodies)\n"
-"{\n"
-" int i = get_global_id(0);\n"
-" if (i>=numBodies)\n"
-" return;\n"
-" __global b3GpuSolverBody* solverBody = &solverBodies[i];\n"
-" __global b3RigidBodyCL* bodyCL = &bodiesCL[i];\n"
-" solverBody->m_deltaLinearVelocity = (float4)(0.f,0.f,0.f,0.f);\n"
-" solverBody->m_deltaAngularVelocity = (float4)(0.f,0.f,0.f,0.f);\n"
-" solverBody->m_pushVelocity = (float4)(0.f,0.f,0.f,0.f);\n"
-" solverBody->m_pushVelocity = (float4)(0.f,0.f,0.f,0.f);\n"
-" solverBody->m_invMass = (float4)(bodyCL->m_invMass,bodyCL->m_invMass,bodyCL->m_invMass,0.f);\n"
-" solverBody->m_originalBodyIndex = i;\n"
-" solverBody->m_angularFactor = (float4)(1,1,1,0);\n"
-" solverBody->m_linearFactor = (float4) (1,1,1,0);\n"
-" solverBody->m_linearVelocity = bodyCL->m_linVel;\n"
-" solverBody->m_angularVelocity = bodyCL->m_angVel;\n"
-"}\n"
-"__kernel void breakViolatedConstraintsKernel(__global b3GpuGenericConstraint* constraints, __global unsigned int* numConstraintRows, __global unsigned int* rowOffsets, __global b3SolverConstraint* rows, int numConstraints)\n"
-"{\n"
-" int cid = get_global_id(0);\n"
-" if (cid>=numConstraints)\n"
-" return;\n"
-" int numRows = numConstraintRows[cid];\n"
-" if (numRows)\n"
-" {\n"
-" for (int i=0;i<numRows;i++)\n"
-" {\n"
-" int rowIndex = rowOffsets[cid]+i;\n"
-" float breakingThreshold = constraints[cid].m_breakingImpulseThreshold;\n"
-" if (fabs(rows[rowIndex].m_appliedImpulse) >= breakingThreshold)\n"
-" {\n"
-" constraints[cid].m_flags =0;//&= ~B3_CONSTRAINT_FLAG_ENABLED;\n"
-" }\n"
-" }\n"
-" }\n"
-"}\n"
-"__kernel void getInfo1Kernel(__global unsigned int* infos, __global b3GpuGenericConstraint* constraints, int numConstraints)\n"
-"{\n"
-" int i = get_global_id(0);\n"
-" if (i>=numConstraints)\n"
-" return;\n"
-" __global b3GpuGenericConstraint* constraint = &constraints[i];\n"
-" switch (constraint->m_constraintType)\n"
-" {\n"
-" case B3_GPU_POINT2POINT_CONSTRAINT_TYPE:\n"
-" {\n"
-" infos[i] = 3;\n"
-" break;\n"
-" }\n"
-" case B3_GPU_FIXED_CONSTRAINT_TYPE:\n"
-" {\n"
-" infos[i] = 6;\n"
-" break;\n"
-" }\n"
-" default:\n"
-" {\n"
-" }\n"
-" }\n"
-"}\n"
-"__kernel void initBatchConstraintsKernel(__global unsigned int* numConstraintRows, __global unsigned int* rowOffsets, \n"
-" __global b3BatchConstraint* batchConstraints, \n"
-" __global b3GpuGenericConstraint* constraints,\n"
-" __global b3RigidBodyCL* bodies,\n"
-" int numConstraints)\n"
-"{\n"
-" int i = get_global_id(0);\n"
-" if (i>=numConstraints)\n"
-" return;\n"
-" int rbA = constraints[i].m_rbA;\n"
-" int rbB = constraints[i].m_rbB;\n"
-" batchConstraints[i].m_bodyAPtrAndSignBit = bodies[rbA].m_invMass != 0.f ? rbA : -rbA;\n"
-" batchConstraints[i].m_bodyBPtrAndSignBit = bodies[rbB].m_invMass != 0.f ? rbB : -rbB;\n"
-" batchConstraints[i].m_batchId = -1;\n"
-" batchConstraints[i].m_originalConstraintIndex = i;\n"
-"}\n"
-"typedef struct\n"
-"{\n"
-" // integrator parameters: frames per second (1/stepsize), default error\n"
-" // reduction parameter (0..1).\n"
-" float fps,erp;\n"
-" // for the first and second body, pointers to two (linear and angular)\n"
-" // n*3 jacobian sub matrices, stored by rows. these matrices will have\n"
-" // been initialized to 0 on entry. if the second body is zero then the\n"
-" // J2xx pointers may be 0.\n"
-" union \n"
-" {\n"
-" __global float4* m_J1linearAxisFloat4;\n"
-" __global float* m_J1linearAxis;\n"
-" };\n"
-" union\n"
-" {\n"
-" __global float4* m_J1angularAxisFloat4;\n"
-" __global float* m_J1angularAxis;\n"
-" };\n"
-" union\n"
-" {\n"
-" __global float4* m_J2linearAxisFloat4;\n"
-" __global float* m_J2linearAxis;\n"
-" };\n"
-" union\n"
-" {\n"
-" __global float4* m_J2angularAxisFloat4;\n"
-" __global float* m_J2angularAxis;\n"
-" };\n"
-" // elements to jump from one row to the next in J's\n"
-" int rowskip;\n"
-" // right hand sides of the equation J*v = c + cfm * lambda. cfm is the\n"
-" // \"constraint force mixing\" vector. c is set to zero on entry, cfm is\n"
-" // set to a constant value (typically very small or zero) value on entry.\n"
-" __global float* m_constraintError;\n"
-" __global float* cfm;\n"
-" // lo and hi limits for variables (set to -/+ infinity on entry).\n"
-" __global float* m_lowerLimit;\n"
-" __global float* m_upperLimit;\n"
-" // findex vector for variables. see the LCP solver interface for a\n"
-" // description of what this does. this is set to -1 on entry.\n"
-" // note that the returned indexes are relative to the first index of\n"
-" // the constraint.\n"
-" __global int *findex;\n"
-" // number of solver iterations\n"
-" int m_numIterations;\n"
-" //damping of the velocity\n"
-" float m_damping;\n"
-"} b3GpuConstraintInfo2;\n"
-"void getSkewSymmetricMatrix(float4 vecIn, __global float4* v0,__global float4* v1,__global float4* v2)\n"
-"{\n"
-" *v0 = (float4)(0. ,-vecIn.z ,vecIn.y,0.f);\n"
-" *v1 = (float4)(vecIn.z ,0. ,-vecIn.x,0.f);\n"
-" *v2 = (float4)(-vecIn.y ,vecIn.x ,0.f,0.f);\n"
-"}\n"
-"void getInfo2Point2Point(__global b3GpuGenericConstraint* constraint,b3GpuConstraintInfo2* info,__global b3RigidBodyCL* bodies)\n"
-"{\n"
-" float4 posA = bodies[constraint->m_rbA].m_pos;\n"
-" Quaternion rotA = bodies[constraint->m_rbA].m_quat;\n"
-" float4 posB = bodies[constraint->m_rbB].m_pos;\n"
-" Quaternion rotB = bodies[constraint->m_rbB].m_quat;\n"
-" // anchor points in global coordinates with respect to body PORs.\n"
-" \n"
-" // set jacobian\n"
-" info->m_J1linearAxis[0] = 1;\n"
-" info->m_J1linearAxis[info->rowskip+1] = 1;\n"
-" info->m_J1linearAxis[2*info->rowskip+2] = 1;\n"
-" float4 a1 = qtRotate(rotA,constraint->m_pivotInA);\n"
-" {\n"
-" __global float4* angular0 = (__global float4*)(info->m_J1angularAxis);\n"
-" __global float4* angular1 = (__global float4*)(info->m_J1angularAxis+info->rowskip);\n"
-" __global float4* angular2 = (__global float4*)(info->m_J1angularAxis+2*info->rowskip);\n"
-" float4 a1neg = -a1;\n"
-" getSkewSymmetricMatrix(a1neg,angular0,angular1,angular2);\n"
-" }\n"
-" if (info->m_J2linearAxis)\n"
-" {\n"
-" info->m_J2linearAxis[0] = -1;\n"
-" info->m_J2linearAxis[info->rowskip+1] = -1;\n"
-" info->m_J2linearAxis[2*info->rowskip+2] = -1;\n"
-" }\n"
-" \n"
-" float4 a2 = qtRotate(rotB,constraint->m_pivotInB);\n"
-" \n"
-" {\n"
-" // float4 a2n = -a2;\n"
-" __global float4* angular0 = (__global float4*)(info->m_J2angularAxis);\n"
-" __global float4* angular1 = (__global float4*)(info->m_J2angularAxis+info->rowskip);\n"
-" __global float4* angular2 = (__global float4*)(info->m_J2angularAxis+2*info->rowskip);\n"
-" getSkewSymmetricMatrix(a2,angular0,angular1,angular2);\n"
-" }\n"
-" \n"
-" // set right hand side\n"
-"// float currERP = (m_flags & B3_P2P_FLAGS_ERP) ? m_erp : info->erp;\n"
-" float currERP = info->erp;\n"
-" float k = info->fps * currERP;\n"
-" int j;\n"
-" float4 result = a2 + posB - a1 - posA;\n"
-" float* resultPtr = &result;\n"
-" for (j=0; j<3; j++)\n"
-" {\n"
-" info->m_constraintError[j*info->rowskip] = k * (resultPtr[j]);\n"
-" }\n"
-"}\n"
-"Quaternion nearest( Quaternion first, Quaternion qd)\n"
-"{\n"
-" Quaternion diff,sum;\n"
-" diff = first- qd;\n"
-" sum = first + qd;\n"
-" \n"
-" if( dot(diff,diff) < dot(sum,sum) )\n"
-" return qd;\n"
-" return (-qd);\n"
-"}\n"
-"float b3Acos(float x) \n"
-"{ \n"
-" if (x<-1) \n"
-" x=-1; \n"
-" if (x>1) \n"
-" x=1;\n"
-" return acos(x); \n"
-"}\n"
-"float getAngle(Quaternion orn)\n"
-"{\n"
-" if (orn.w>=1.f)\n"
-" orn.w=1.f;\n"
-" float s = 2.f * b3Acos(orn.w);\n"
-" return s;\n"
-"}\n"
-"void calculateDiffAxisAngleQuaternion( Quaternion orn0,Quaternion orn1a,float4* axis,float* angle)\n"
-"{\n"
-" Quaternion orn1 = nearest(orn0,orn1a);\n"
-" \n"
-" Quaternion dorn = qtMul(orn1,qtInvert(orn0));\n"
-" *angle = getAngle(dorn);\n"
-" *axis = (float4)(dorn.x,dorn.y,dorn.z,0.f);\n"
-" \n"
-" //check for axis length\n"
-" float len = dot3F4(*axis,*axis);\n"
-" if (len < FLT_EPSILON*FLT_EPSILON)\n"
-" *axis = (float4)(1,0,0,0);\n"
-" else\n"
-" *axis /= sqrt(len);\n"
-"}\n"
-"void getInfo2FixedOrientation(__global b3GpuGenericConstraint* constraint,b3GpuConstraintInfo2* info,__global b3RigidBodyCL* bodies, int start_row)\n"
-"{\n"
-" Quaternion worldOrnA = bodies[constraint->m_rbA].m_quat;\n"
-" Quaternion worldOrnB = bodies[constraint->m_rbB].m_quat;\n"
-" int s = info->rowskip;\n"
-" int start_index = start_row * s;\n"
-" // 3 rows to make body rotations equal\n"
-" info->m_J1angularAxis[start_index] = 1;\n"
-" info->m_J1angularAxis[start_index + s + 1] = 1;\n"
-" info->m_J1angularAxis[start_index + s*2+2] = 1;\n"
-" if ( info->m_J2angularAxis)\n"
-" {\n"
-" info->m_J2angularAxis[start_index] = -1;\n"
-" info->m_J2angularAxis[start_index + s+1] = -1;\n"
-" info->m_J2angularAxis[start_index + s*2+2] = -1;\n"
-" }\n"
-" \n"
-" float currERP = info->erp;\n"
-" float k = info->fps * currERP;\n"
-" float4 diff;\n"
-" float angle;\n"
-" float4 qrelCur = qtMul(worldOrnA,qtInvert(worldOrnB));\n"
-" \n"
-" calculateDiffAxisAngleQuaternion(constraint->m_relTargetAB,qrelCur,&diff,&angle);\n"
-" diff*=-angle;\n"
-" \n"
-" float* resultPtr = &diff;\n"
-" \n"
-" for (int j=0; j<3; j++)\n"
-" {\n"
-" info->m_constraintError[(3+j)*info->rowskip] = k * resultPtr[j];\n"
-" }\n"
-" \n"
-"}\n"
-"__kernel void writeBackVelocitiesKernel(__global b3RigidBodyCL* bodies,__global b3GpuSolverBody* solverBodies,int numBodies)\n"
-"{\n"
-" int i = get_global_id(0);\n"
-" if (i>=numBodies)\n"
-" return;\n"
-" if (bodies[i].m_invMass)\n"
-" {\n"
-"// if (length(solverBodies[i].m_deltaLinearVelocity)<MOTIONCLAMP)\n"
-" {\n"
-" bodies[i].m_linVel += solverBodies[i].m_deltaLinearVelocity;\n"
-" }\n"
-"// if (length(solverBodies[i].m_deltaAngularVelocity)<MOTIONCLAMP)\n"
-" {\n"
-" bodies[i].m_angVel += solverBodies[i].m_deltaAngularVelocity;\n"
-" } \n"
-" }\n"
-"}\n"
-"__kernel void getInfo2Kernel(__global b3SolverConstraint* solverConstraintRows, \n"
-" __global unsigned int* infos, \n"
-" __global unsigned int* constraintRowOffsets, \n"
-" __global b3GpuGenericConstraint* constraints, \n"
-" __global b3BatchConstraint* batchConstraints, \n"
-" __global b3RigidBodyCL* bodies,\n"
-" __global BodyInertia* inertias,\n"
-" __global b3GpuSolverBody* solverBodies,\n"
-" float timeStep,\n"
-" float globalErp,\n"
-" float globalCfm,\n"
-" float globalDamping,\n"
-" int globalNumIterations,\n"
-" int numConstraints)\n"
-"{\n"
-" int i = get_global_id(0);\n"
-" if (i>=numConstraints)\n"
-" return;\n"
-" \n"
-" //for now, always initialize the batch info\n"
-" int info1 = infos[i];\n"
-" \n"
-" __global b3SolverConstraint* currentConstraintRow = &solverConstraintRows[constraintRowOffsets[i]];\n"
-" __global b3GpuGenericConstraint* constraint = &constraints[i];\n"
-" __global b3RigidBodyCL* rbA = &bodies[ constraint->m_rbA];\n"
-" __global b3RigidBodyCL* rbB = &bodies[ constraint->m_rbB];\n"
-" int solverBodyIdA = constraint->m_rbA;\n"
-" int solverBodyIdB = constraint->m_rbB;\n"
-" __global b3GpuSolverBody* bodyAPtr = &solverBodies[solverBodyIdA];\n"
-" __global b3GpuSolverBody* bodyBPtr = &solverBodies[solverBodyIdB];\n"
-" if (rbA->m_invMass)\n"
-" {\n"
-" batchConstraints[i].m_bodyAPtrAndSignBit = solverBodyIdA;\n"
-" } else\n"
-" {\n"
-"// if (!solverBodyIdA)\n"
-"// m_staticIdx = 0;\n"
-" batchConstraints[i].m_bodyAPtrAndSignBit = -solverBodyIdA;\n"
-" }\n"
-" if (rbB->m_invMass)\n"
-" {\n"
-" batchConstraints[i].m_bodyBPtrAndSignBit = solverBodyIdB;\n"
-" } else\n"
-" {\n"
-"// if (!solverBodyIdB)\n"
-"// m_staticIdx = 0;\n"
-" batchConstraints[i].m_bodyBPtrAndSignBit = -solverBodyIdB;\n"
-" }\n"
-" if (info1)\n"
-" {\n"
-" int overrideNumSolverIterations = 0;//constraint->getOverrideNumSolverIterations() > 0 ? constraint->getOverrideNumSolverIterations() : infoGlobal.m_numIterations;\n"
-"// if (overrideNumSolverIterations>m_maxOverrideNumSolverIterations)\n"
-" // m_maxOverrideNumSolverIterations = overrideNumSolverIterations;\n"
-" int j;\n"
-" for ( j=0;j<info1;j++)\n"
-" {\n"
-"// memset(&currentConstraintRow[j],0,sizeof(b3SolverConstraint));\n"
-" currentConstraintRow[j].m_angularComponentA = (float4)(0,0,0,0);\n"
-" currentConstraintRow[j].m_angularComponentB = (float4)(0,0,0,0);\n"
-" currentConstraintRow[j].m_appliedImpulse = 0.f;\n"
-" currentConstraintRow[j].m_appliedPushImpulse = 0.f;\n"
-" currentConstraintRow[j].m_cfm = 0.f;\n"
-" currentConstraintRow[j].m_contactNormal = (float4)(0,0,0,0);\n"
-" currentConstraintRow[j].m_friction = 0.f;\n"
-" currentConstraintRow[j].m_frictionIndex = 0;\n"
-" currentConstraintRow[j].m_jacDiagABInv = 0.f;\n"
-" currentConstraintRow[j].m_lowerLimit = 0.f;\n"
-" currentConstraintRow[j].m_upperLimit = 0.f;\n"
-" currentConstraintRow[j].m_originalConstraint = i;\n"
-" currentConstraintRow[j].m_overrideNumSolverIterations = 0;\n"
-" currentConstraintRow[j].m_relpos1CrossNormal = (float4)(0,0,0,0);\n"
-" currentConstraintRow[j].m_relpos2CrossNormal = (float4)(0,0,0,0);\n"
-" currentConstraintRow[j].m_rhs = 0.f;\n"
-" currentConstraintRow[j].m_rhsPenetration = 0.f;\n"
-" currentConstraintRow[j].m_solverBodyIdA = 0;\n"
-" currentConstraintRow[j].m_solverBodyIdB = 0;\n"
-" \n"
-" currentConstraintRow[j].m_lowerLimit = -B3_INFINITY;\n"
-" currentConstraintRow[j].m_upperLimit = B3_INFINITY;\n"
-" currentConstraintRow[j].m_appliedImpulse = 0.f;\n"
-" currentConstraintRow[j].m_appliedPushImpulse = 0.f;\n"
-" currentConstraintRow[j].m_solverBodyIdA = solverBodyIdA;\n"
-" currentConstraintRow[j].m_solverBodyIdB = solverBodyIdB;\n"
-" currentConstraintRow[j].m_overrideNumSolverIterations = overrideNumSolverIterations; \n"
-" }\n"
-" bodyAPtr->m_deltaLinearVelocity = (float4)(0,0,0,0);\n"
-" bodyAPtr->m_deltaAngularVelocity = (float4)(0,0,0,0);\n"
-" bodyAPtr->m_pushVelocity = (float4)(0,0,0,0);\n"
-" bodyAPtr->m_turnVelocity = (float4)(0,0,0,0);\n"
-" bodyBPtr->m_deltaLinearVelocity = (float4)(0,0,0,0);\n"
-" bodyBPtr->m_deltaAngularVelocity = (float4)(0,0,0,0);\n"
-" bodyBPtr->m_pushVelocity = (float4)(0,0,0,0);\n"
-" bodyBPtr->m_turnVelocity = (float4)(0,0,0,0);\n"
-" int rowskip = sizeof(b3SolverConstraint)/sizeof(float);//check this\n"
-" \n"
-" b3GpuConstraintInfo2 info2;\n"
-" info2.fps = 1.f/timeStep;\n"
-" info2.erp = globalErp;\n"
-" info2.m_J1linearAxisFloat4 = &currentConstraintRow->m_contactNormal;\n"
-" info2.m_J1angularAxisFloat4 = &currentConstraintRow->m_relpos1CrossNormal;\n"
-" info2.m_J2linearAxisFloat4 = 0;\n"
-" info2.m_J2angularAxisFloat4 = &currentConstraintRow->m_relpos2CrossNormal;\n"
-" info2.rowskip = sizeof(b3SolverConstraint)/sizeof(float);//check this\n"
-" ///the size of b3SolverConstraint needs be a multiple of float\n"
-"// b3Assert(info2.rowskip*sizeof(float)== sizeof(b3SolverConstraint));\n"
-" info2.m_constraintError = &currentConstraintRow->m_rhs;\n"
-" currentConstraintRow->m_cfm = globalCfm;\n"
-" info2.m_damping = globalDamping;\n"
-" info2.cfm = &currentConstraintRow->m_cfm;\n"
-" info2.m_lowerLimit = &currentConstraintRow->m_lowerLimit;\n"
-" info2.m_upperLimit = &currentConstraintRow->m_upperLimit;\n"
-" info2.m_numIterations = globalNumIterations;\n"
-" switch (constraint->m_constraintType)\n"
-" {\n"
-" case B3_GPU_POINT2POINT_CONSTRAINT_TYPE:\n"
-" {\n"
-" getInfo2Point2Point(constraint,&info2,bodies);\n"
-" break;\n"
-" }\n"
-" case B3_GPU_FIXED_CONSTRAINT_TYPE:\n"
-" {\n"
-" getInfo2Point2Point(constraint,&info2,bodies);\n"
-" getInfo2FixedOrientation(constraint,&info2,bodies,3);\n"
-" break;\n"
-" }\n"
-" default:\n"
-" {\n"
-" }\n"
-" }\n"
-" ///finalize the constraint setup\n"
-" for ( j=0;j<info1;j++)\n"
-" {\n"
-" __global b3SolverConstraint* solverConstraint = &currentConstraintRow[j];\n"
-" if (solverConstraint->m_upperLimit>=constraint->m_breakingImpulseThreshold)\n"
-" {\n"
-" solverConstraint->m_upperLimit = constraint->m_breakingImpulseThreshold;\n"
-" }\n"
-" if (solverConstraint->m_lowerLimit<=-constraint->m_breakingImpulseThreshold)\n"
-" {\n"
-" solverConstraint->m_lowerLimit = -constraint->m_breakingImpulseThreshold;\n"
-" }\n"
-"// solverConstraint->m_originalContactPoint = constraint;\n"
-" \n"
-" Matrix3x3 invInertiaWorldA= inertias[constraint->m_rbA].m_invInertiaWorld;\n"
-" {\n"
-" //float4 angularFactorA(1,1,1);\n"
-" float4 ftorqueAxis1 = solverConstraint->m_relpos1CrossNormal;\n"
-" solverConstraint->m_angularComponentA = mtMul1(invInertiaWorldA,ftorqueAxis1);//*angularFactorA;\n"
-" }\n"
-" \n"
-" Matrix3x3 invInertiaWorldB= inertias[constraint->m_rbB].m_invInertiaWorld;\n"
-" {\n"
-" float4 ftorqueAxis2 = solverConstraint->m_relpos2CrossNormal;\n"
-" solverConstraint->m_angularComponentB = mtMul1(invInertiaWorldB,ftorqueAxis2);//*constraint->m_rbB.getAngularFactor();\n"
-" }\n"
-" {\n"
-" //it is ok to use solverConstraint->m_contactNormal instead of -solverConstraint->m_contactNormal\n"
-" //because it gets multiplied iMJlB\n"
-" float4 iMJlA = solverConstraint->m_contactNormal*rbA->m_invMass;\n"
-" float4 iMJaA = mtMul3(solverConstraint->m_relpos1CrossNormal,invInertiaWorldA);\n"
-" float4 iMJlB = solverConstraint->m_contactNormal*rbB->m_invMass;//sign of normal?\n"
-" float4 iMJaB = mtMul3(solverConstraint->m_relpos2CrossNormal,invInertiaWorldB);\n"
-" float sum = dot3F4(iMJlA,solverConstraint->m_contactNormal);\n"
-" sum += dot3F4(iMJaA,solverConstraint->m_relpos1CrossNormal);\n"
-" sum += dot3F4(iMJlB,solverConstraint->m_contactNormal);\n"
-" sum += dot3F4(iMJaB,solverConstraint->m_relpos2CrossNormal);\n"
-" float fsum = fabs(sum);\n"
-" if (fsum>FLT_EPSILON)\n"
-" {\n"
-" solverConstraint->m_jacDiagABInv = 1.f/sum;\n"
-" } else\n"
-" {\n"
-" solverConstraint->m_jacDiagABInv = 0.f;\n"
-" }\n"
-" }\n"
-" ///fix rhs\n"
-" ///todo: add force/torque accelerators\n"
-" {\n"
-" float rel_vel;\n"
-" float vel1Dotn = dot3F4(solverConstraint->m_contactNormal,rbA->m_linVel) + dot3F4(solverConstraint->m_relpos1CrossNormal,rbA->m_angVel);\n"
-" float vel2Dotn = -dot3F4(solverConstraint->m_contactNormal,rbB->m_linVel) + dot3F4(solverConstraint->m_relpos2CrossNormal,rbB->m_angVel);\n"
-" rel_vel = vel1Dotn+vel2Dotn;\n"
-" float restitution = 0.f;\n"
-" float positionalError = solverConstraint->m_rhs;//already filled in by getConstraintInfo2\n"
-" float velocityError = restitution - rel_vel * info2.m_damping;\n"
-" float penetrationImpulse = positionalError*solverConstraint->m_jacDiagABInv;\n"
-" float velocityImpulse = velocityError *solverConstraint->m_jacDiagABInv;\n"
-" solverConstraint->m_rhs = penetrationImpulse+velocityImpulse;\n"
-" solverConstraint->m_appliedImpulse = 0.f;\n"
-" }\n"
-" }\n"
-" }\n"
-"}\n"
-;
+static const char* solveConstraintRowsCL =
+ "/*\n"
+ "Copyright (c) 2013 Advanced Micro Devices, Inc. \n"
+ "This software is provided 'as-is', without any express or implied warranty.\n"
+ "In no event will the authors be held liable for any damages arising from the use of this software.\n"
+ "Permission is granted to anyone to use this software for any purpose, \n"
+ "including commercial applications, and to alter it and redistribute it freely, \n"
+ "subject to the following restrictions:\n"
+ "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
+ "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+ "3. This notice may not be removed or altered from any source distribution.\n"
+ "*/\n"
+ "//Originally written by Erwin Coumans\n"
+ "#define B3_CONSTRAINT_FLAG_ENABLED 1\n"
+ "#define B3_GPU_POINT2POINT_CONSTRAINT_TYPE 3\n"
+ "#define B3_GPU_FIXED_CONSTRAINT_TYPE 4\n"
+ "#define MOTIONCLAMP 100000 //unused, for debugging/safety in case constraint solver fails\n"
+ "#define B3_INFINITY 1e30f\n"
+ "#define mymake_float4 (float4)\n"
+ "__inline float dot3F4(float4 a, float4 b)\n"
+ "{\n"
+ " float4 a1 = mymake_float4(a.xyz,0.f);\n"
+ " float4 b1 = mymake_float4(b.xyz,0.f);\n"
+ " return dot(a1, b1);\n"
+ "}\n"
+ "typedef float4 Quaternion;\n"
+ "typedef struct\n"
+ "{\n"
+ " float4 m_row[3];\n"
+ "}Matrix3x3;\n"
+ "__inline\n"
+ "float4 mtMul1(Matrix3x3 a, float4 b);\n"
+ "__inline\n"
+ "float4 mtMul3(float4 a, Matrix3x3 b);\n"
+ "__inline\n"
+ "float4 mtMul1(Matrix3x3 a, float4 b)\n"
+ "{\n"
+ " float4 ans;\n"
+ " ans.x = dot3F4( a.m_row[0], b );\n"
+ " ans.y = dot3F4( a.m_row[1], b );\n"
+ " ans.z = dot3F4( a.m_row[2], b );\n"
+ " ans.w = 0.f;\n"
+ " return ans;\n"
+ "}\n"
+ "__inline\n"
+ "float4 mtMul3(float4 a, Matrix3x3 b)\n"
+ "{\n"
+ " float4 colx = mymake_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
+ " float4 coly = mymake_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
+ " float4 colz = mymake_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
+ " float4 ans;\n"
+ " ans.x = dot3F4( a, colx );\n"
+ " ans.y = dot3F4( a, coly );\n"
+ " ans.z = dot3F4( a, colz );\n"
+ " return ans;\n"
+ "}\n"
+ "typedef struct\n"
+ "{\n"
+ " Matrix3x3 m_invInertiaWorld;\n"
+ " Matrix3x3 m_initInvInertia;\n"
+ "} BodyInertia;\n"
+ "typedef struct\n"
+ "{\n"
+ " Matrix3x3 m_basis;//orientation\n"
+ " float4 m_origin;//transform\n"
+ "}b3Transform;\n"
+ "typedef struct\n"
+ "{\n"
+ "// b3Transform m_worldTransformUnused;\n"
+ " float4 m_deltaLinearVelocity;\n"
+ " float4 m_deltaAngularVelocity;\n"
+ " float4 m_angularFactor;\n"
+ " float4 m_linearFactor;\n"
+ " float4 m_invMass;\n"
+ " float4 m_pushVelocity;\n"
+ " float4 m_turnVelocity;\n"
+ " float4 m_linearVelocity;\n"
+ " float4 m_angularVelocity;\n"
+ " union \n"
+ " {\n"
+ " void* m_originalBody;\n"
+ " int m_originalBodyIndex;\n"
+ " };\n"
+ " int padding[3];\n"
+ "} b3GpuSolverBody;\n"
+ "typedef struct\n"
+ "{\n"
+ " float4 m_pos;\n"
+ " Quaternion m_quat;\n"
+ " float4 m_linVel;\n"
+ " float4 m_angVel;\n"
+ " unsigned int m_shapeIdx;\n"
+ " float m_invMass;\n"
+ " float m_restituitionCoeff;\n"
+ " float m_frictionCoeff;\n"
+ "} b3RigidBodyCL;\n"
+ "typedef struct\n"
+ "{\n"
+ " float4 m_relpos1CrossNormal;\n"
+ " float4 m_contactNormal;\n"
+ " float4 m_relpos2CrossNormal;\n"
+ " //float4 m_contactNormal2;//usually m_contactNormal2 == -m_contactNormal\n"
+ " float4 m_angularComponentA;\n"
+ " float4 m_angularComponentB;\n"
+ " \n"
+ " float m_appliedPushImpulse;\n"
+ " float m_appliedImpulse;\n"
+ " int m_padding1;\n"
+ " int m_padding2;\n"
+ " float m_friction;\n"
+ " float m_jacDiagABInv;\n"
+ " float m_rhs;\n"
+ " float m_cfm;\n"
+ " \n"
+ " float m_lowerLimit;\n"
+ " float m_upperLimit;\n"
+ " float m_rhsPenetration;\n"
+ " int m_originalConstraint;\n"
+ " int m_overrideNumSolverIterations;\n"
+ " int m_frictionIndex;\n"
+ " int m_solverBodyIdA;\n"
+ " int m_solverBodyIdB;\n"
+ "} b3SolverConstraint;\n"
+ "typedef struct \n"
+ "{\n"
+ " int m_bodyAPtrAndSignBit;\n"
+ " int m_bodyBPtrAndSignBit;\n"
+ " int m_originalConstraintIndex;\n"
+ " int m_batchId;\n"
+ "} b3BatchConstraint;\n"
+ "typedef struct \n"
+ "{\n"
+ " int m_constraintType;\n"
+ " int m_rbA;\n"
+ " int m_rbB;\n"
+ " float m_breakingImpulseThreshold;\n"
+ " float4 m_pivotInA;\n"
+ " float4 m_pivotInB;\n"
+ " Quaternion m_relTargetAB;\n"
+ " int m_flags;\n"
+ " int m_padding[3];\n"
+ "} b3GpuGenericConstraint;\n"
+ "/*b3Transform getWorldTransform(b3RigidBodyCL* rb)\n"
+ "{\n"
+ " b3Transform newTrans;\n"
+ " newTrans.setOrigin(rb->m_pos);\n"
+ " newTrans.setRotation(rb->m_quat);\n"
+ " return newTrans;\n"
+ "}*/\n"
+ "__inline\n"
+ "float4 cross3(float4 a, float4 b)\n"
+ "{\n"
+ " return cross(a,b);\n"
+ "}\n"
+ "__inline\n"
+ "float4 fastNormalize4(float4 v)\n"
+ "{\n"
+ " v = mymake_float4(v.xyz,0.f);\n"
+ " return fast_normalize(v);\n"
+ "}\n"
+ "__inline\n"
+ "Quaternion qtMul(Quaternion a, Quaternion b);\n"
+ "__inline\n"
+ "Quaternion qtNormalize(Quaternion in);\n"
+ "__inline\n"
+ "float4 qtRotate(Quaternion q, float4 vec);\n"
+ "__inline\n"
+ "Quaternion qtInvert(Quaternion q);\n"
+ "__inline\n"
+ "Quaternion qtMul(Quaternion a, Quaternion b)\n"
+ "{\n"
+ " Quaternion ans;\n"
+ " ans = cross3( a, b );\n"
+ " ans += a.w*b+b.w*a;\n"
+ "// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+ " ans.w = a.w*b.w - dot3F4(a, b);\n"
+ " return ans;\n"
+ "}\n"
+ "__inline\n"
+ "Quaternion qtNormalize(Quaternion in)\n"
+ "{\n"
+ " return fastNormalize4(in);\n"
+ "// in /= length( in );\n"
+ "// return in;\n"
+ "}\n"
+ "__inline\n"
+ "float4 qtRotate(Quaternion q, float4 vec)\n"
+ "{\n"
+ " Quaternion qInv = qtInvert( q );\n"
+ " float4 vcpy = vec;\n"
+ " vcpy.w = 0.f;\n"
+ " float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
+ " return out;\n"
+ "}\n"
+ "__inline\n"
+ "Quaternion qtInvert(Quaternion q)\n"
+ "{\n"
+ " return (Quaternion)(-q.xyz, q.w);\n"
+ "}\n"
+ "__inline void internalApplyImpulse(__global b3GpuSolverBody* body, float4 linearComponent, float4 angularComponent,float impulseMagnitude)\n"
+ "{\n"
+ " body->m_deltaLinearVelocity += linearComponent*impulseMagnitude*body->m_linearFactor;\n"
+ " body->m_deltaAngularVelocity += angularComponent*(impulseMagnitude*body->m_angularFactor);\n"
+ "}\n"
+ "void resolveSingleConstraintRowGeneric(__global b3GpuSolverBody* body1, __global b3GpuSolverBody* body2, __global b3SolverConstraint* c)\n"
+ "{\n"
+ " float deltaImpulse = c->m_rhs-c->m_appliedImpulse*c->m_cfm;\n"
+ " float deltaVel1Dotn = dot3F4(c->m_contactNormal,body1->m_deltaLinearVelocity) + dot3F4(c->m_relpos1CrossNormal,body1->m_deltaAngularVelocity);\n"
+ " float deltaVel2Dotn = -dot3F4(c->m_contactNormal,body2->m_deltaLinearVelocity) + dot3F4(c->m_relpos2CrossNormal,body2->m_deltaAngularVelocity);\n"
+ " deltaImpulse -= deltaVel1Dotn*c->m_jacDiagABInv;\n"
+ " deltaImpulse -= deltaVel2Dotn*c->m_jacDiagABInv;\n"
+ " float sum = c->m_appliedImpulse + deltaImpulse;\n"
+ " if (sum < c->m_lowerLimit)\n"
+ " {\n"
+ " deltaImpulse = c->m_lowerLimit-c->m_appliedImpulse;\n"
+ " c->m_appliedImpulse = c->m_lowerLimit;\n"
+ " }\n"
+ " else if (sum > c->m_upperLimit) \n"
+ " {\n"
+ " deltaImpulse = c->m_upperLimit-c->m_appliedImpulse;\n"
+ " c->m_appliedImpulse = c->m_upperLimit;\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " c->m_appliedImpulse = sum;\n"
+ " }\n"
+ " internalApplyImpulse(body1,c->m_contactNormal*body1->m_invMass,c->m_angularComponentA,deltaImpulse);\n"
+ " internalApplyImpulse(body2,-c->m_contactNormal*body2->m_invMass,c->m_angularComponentB,deltaImpulse);\n"
+ "}\n"
+ "__kernel void solveJointConstraintRows(__global b3GpuSolverBody* solverBodies,\n"
+ " __global b3BatchConstraint* batchConstraints,\n"
+ " __global b3SolverConstraint* rows,\n"
+ " __global unsigned int* numConstraintRowsInfo1, \n"
+ " __global unsigned int* rowOffsets,\n"
+ " __global b3GpuGenericConstraint* constraints,\n"
+ " int batchOffset,\n"
+ " int numConstraintsInBatch\n"
+ " )\n"
+ "{\n"
+ " int b = get_global_id(0);\n"
+ " if (b>=numConstraintsInBatch)\n"
+ " return;\n"
+ " __global b3BatchConstraint* c = &batchConstraints[b+batchOffset];\n"
+ " int originalConstraintIndex = c->m_originalConstraintIndex;\n"
+ " if (constraints[originalConstraintIndex].m_flags&B3_CONSTRAINT_FLAG_ENABLED)\n"
+ " {\n"
+ " int numConstraintRows = numConstraintRowsInfo1[originalConstraintIndex];\n"
+ " int rowOffset = rowOffsets[originalConstraintIndex];\n"
+ " for (int jj=0;jj<numConstraintRows;jj++)\n"
+ " {\n"
+ " __global b3SolverConstraint* constraint = &rows[rowOffset+jj];\n"
+ " resolveSingleConstraintRowGeneric(&solverBodies[constraint->m_solverBodyIdA],&solverBodies[constraint->m_solverBodyIdB],constraint);\n"
+ " }\n"
+ " }\n"
+ "};\n"
+ "__kernel void initSolverBodies(__global b3GpuSolverBody* solverBodies,__global b3RigidBodyCL* bodiesCL, int numBodies)\n"
+ "{\n"
+ " int i = get_global_id(0);\n"
+ " if (i>=numBodies)\n"
+ " return;\n"
+ " __global b3GpuSolverBody* solverBody = &solverBodies[i];\n"
+ " __global b3RigidBodyCL* bodyCL = &bodiesCL[i];\n"
+ " solverBody->m_deltaLinearVelocity = (float4)(0.f,0.f,0.f,0.f);\n"
+ " solverBody->m_deltaAngularVelocity = (float4)(0.f,0.f,0.f,0.f);\n"
+ " solverBody->m_pushVelocity = (float4)(0.f,0.f,0.f,0.f);\n"
+ " solverBody->m_pushVelocity = (float4)(0.f,0.f,0.f,0.f);\n"
+ " solverBody->m_invMass = (float4)(bodyCL->m_invMass,bodyCL->m_invMass,bodyCL->m_invMass,0.f);\n"
+ " solverBody->m_originalBodyIndex = i;\n"
+ " solverBody->m_angularFactor = (float4)(1,1,1,0);\n"
+ " solverBody->m_linearFactor = (float4) (1,1,1,0);\n"
+ " solverBody->m_linearVelocity = bodyCL->m_linVel;\n"
+ " solverBody->m_angularVelocity = bodyCL->m_angVel;\n"
+ "}\n"
+ "__kernel void breakViolatedConstraintsKernel(__global b3GpuGenericConstraint* constraints, __global unsigned int* numConstraintRows, __global unsigned int* rowOffsets, __global b3SolverConstraint* rows, int numConstraints)\n"
+ "{\n"
+ " int cid = get_global_id(0);\n"
+ " if (cid>=numConstraints)\n"
+ " return;\n"
+ " int numRows = numConstraintRows[cid];\n"
+ " if (numRows)\n"
+ " {\n"
+ " for (int i=0;i<numRows;i++)\n"
+ " {\n"
+ " int rowIndex = rowOffsets[cid]+i;\n"
+ " float breakingThreshold = constraints[cid].m_breakingImpulseThreshold;\n"
+ " if (fabs(rows[rowIndex].m_appliedImpulse) >= breakingThreshold)\n"
+ " {\n"
+ " constraints[cid].m_flags =0;//&= ~B3_CONSTRAINT_FLAG_ENABLED;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ "}\n"
+ "__kernel void getInfo1Kernel(__global unsigned int* infos, __global b3GpuGenericConstraint* constraints, int numConstraints)\n"
+ "{\n"
+ " int i = get_global_id(0);\n"
+ " if (i>=numConstraints)\n"
+ " return;\n"
+ " __global b3GpuGenericConstraint* constraint = &constraints[i];\n"
+ " switch (constraint->m_constraintType)\n"
+ " {\n"
+ " case B3_GPU_POINT2POINT_CONSTRAINT_TYPE:\n"
+ " {\n"
+ " infos[i] = 3;\n"
+ " break;\n"
+ " }\n"
+ " case B3_GPU_FIXED_CONSTRAINT_TYPE:\n"
+ " {\n"
+ " infos[i] = 6;\n"
+ " break;\n"
+ " }\n"
+ " default:\n"
+ " {\n"
+ " }\n"
+ " }\n"
+ "}\n"
+ "__kernel void initBatchConstraintsKernel(__global unsigned int* numConstraintRows, __global unsigned int* rowOffsets, \n"
+ " __global b3BatchConstraint* batchConstraints, \n"
+ " __global b3GpuGenericConstraint* constraints,\n"
+ " __global b3RigidBodyCL* bodies,\n"
+ " int numConstraints)\n"
+ "{\n"
+ " int i = get_global_id(0);\n"
+ " if (i>=numConstraints)\n"
+ " return;\n"
+ " int rbA = constraints[i].m_rbA;\n"
+ " int rbB = constraints[i].m_rbB;\n"
+ " batchConstraints[i].m_bodyAPtrAndSignBit = bodies[rbA].m_invMass != 0.f ? rbA : -rbA;\n"
+ " batchConstraints[i].m_bodyBPtrAndSignBit = bodies[rbB].m_invMass != 0.f ? rbB : -rbB;\n"
+ " batchConstraints[i].m_batchId = -1;\n"
+ " batchConstraints[i].m_originalConstraintIndex = i;\n"
+ "}\n"
+ "typedef struct\n"
+ "{\n"
+ " // integrator parameters: frames per second (1/stepsize), default error\n"
+ " // reduction parameter (0..1).\n"
+ " float fps,erp;\n"
+ " // for the first and second body, pointers to two (linear and angular)\n"
+ " // n*3 jacobian sub matrices, stored by rows. these matrices will have\n"
+ " // been initialized to 0 on entry. if the second body is zero then the\n"
+ " // J2xx pointers may be 0.\n"
+ " union \n"
+ " {\n"
+ " __global float4* m_J1linearAxisFloat4;\n"
+ " __global float* m_J1linearAxis;\n"
+ " };\n"
+ " union\n"
+ " {\n"
+ " __global float4* m_J1angularAxisFloat4;\n"
+ " __global float* m_J1angularAxis;\n"
+ " };\n"
+ " union\n"
+ " {\n"
+ " __global float4* m_J2linearAxisFloat4;\n"
+ " __global float* m_J2linearAxis;\n"
+ " };\n"
+ " union\n"
+ " {\n"
+ " __global float4* m_J2angularAxisFloat4;\n"
+ " __global float* m_J2angularAxis;\n"
+ " };\n"
+ " // elements to jump from one row to the next in J's\n"
+ " int rowskip;\n"
+ " // right hand sides of the equation J*v = c + cfm * lambda. cfm is the\n"
+ " // \"constraint force mixing\" vector. c is set to zero on entry, cfm is\n"
+ " // set to a constant value (typically very small or zero) value on entry.\n"
+ " __global float* m_constraintError;\n"
+ " __global float* cfm;\n"
+ " // lo and hi limits for variables (set to -/+ infinity on entry).\n"
+ " __global float* m_lowerLimit;\n"
+ " __global float* m_upperLimit;\n"
+ " // findex vector for variables. see the LCP solver interface for a\n"
+ " // description of what this does. this is set to -1 on entry.\n"
+ " // note that the returned indexes are relative to the first index of\n"
+ " // the constraint.\n"
+ " __global int *findex;\n"
+ " // number of solver iterations\n"
+ " int m_numIterations;\n"
+ " //damping of the velocity\n"
+ " float m_damping;\n"
+ "} b3GpuConstraintInfo2;\n"
+ "void getSkewSymmetricMatrix(float4 vecIn, __global float4* v0,__global float4* v1,__global float4* v2)\n"
+ "{\n"
+ " *v0 = (float4)(0. ,-vecIn.z ,vecIn.y,0.f);\n"
+ " *v1 = (float4)(vecIn.z ,0. ,-vecIn.x,0.f);\n"
+ " *v2 = (float4)(-vecIn.y ,vecIn.x ,0.f,0.f);\n"
+ "}\n"
+ "void getInfo2Point2Point(__global b3GpuGenericConstraint* constraint,b3GpuConstraintInfo2* info,__global b3RigidBodyCL* bodies)\n"
+ "{\n"
+ " float4 posA = bodies[constraint->m_rbA].m_pos;\n"
+ " Quaternion rotA = bodies[constraint->m_rbA].m_quat;\n"
+ " float4 posB = bodies[constraint->m_rbB].m_pos;\n"
+ " Quaternion rotB = bodies[constraint->m_rbB].m_quat;\n"
+ " // anchor points in global coordinates with respect to body PORs.\n"
+ " \n"
+ " // set jacobian\n"
+ " info->m_J1linearAxis[0] = 1;\n"
+ " info->m_J1linearAxis[info->rowskip+1] = 1;\n"
+ " info->m_J1linearAxis[2*info->rowskip+2] = 1;\n"
+ " float4 a1 = qtRotate(rotA,constraint->m_pivotInA);\n"
+ " {\n"
+ " __global float4* angular0 = (__global float4*)(info->m_J1angularAxis);\n"
+ " __global float4* angular1 = (__global float4*)(info->m_J1angularAxis+info->rowskip);\n"
+ " __global float4* angular2 = (__global float4*)(info->m_J1angularAxis+2*info->rowskip);\n"
+ " float4 a1neg = -a1;\n"
+ " getSkewSymmetricMatrix(a1neg,angular0,angular1,angular2);\n"
+ " }\n"
+ " if (info->m_J2linearAxis)\n"
+ " {\n"
+ " info->m_J2linearAxis[0] = -1;\n"
+ " info->m_J2linearAxis[info->rowskip+1] = -1;\n"
+ " info->m_J2linearAxis[2*info->rowskip+2] = -1;\n"
+ " }\n"
+ " \n"
+ " float4 a2 = qtRotate(rotB,constraint->m_pivotInB);\n"
+ " \n"
+ " {\n"
+ " // float4 a2n = -a2;\n"
+ " __global float4* angular0 = (__global float4*)(info->m_J2angularAxis);\n"
+ " __global float4* angular1 = (__global float4*)(info->m_J2angularAxis+info->rowskip);\n"
+ " __global float4* angular2 = (__global float4*)(info->m_J2angularAxis+2*info->rowskip);\n"
+ " getSkewSymmetricMatrix(a2,angular0,angular1,angular2);\n"
+ " }\n"
+ " \n"
+ " // set right hand side\n"
+ "// float currERP = (m_flags & B3_P2P_FLAGS_ERP) ? m_erp : info->erp;\n"
+ " float currERP = info->erp;\n"
+ " float k = info->fps * currERP;\n"
+ " int j;\n"
+ " float4 result = a2 + posB - a1 - posA;\n"
+ " float* resultPtr = &result;\n"
+ " for (j=0; j<3; j++)\n"
+ " {\n"
+ " info->m_constraintError[j*info->rowskip] = k * (resultPtr[j]);\n"
+ " }\n"
+ "}\n"
+ "Quaternion nearest( Quaternion first, Quaternion qd)\n"
+ "{\n"
+ " Quaternion diff,sum;\n"
+ " diff = first- qd;\n"
+ " sum = first + qd;\n"
+ " \n"
+ " if( dot(diff,diff) < dot(sum,sum) )\n"
+ " return qd;\n"
+ " return (-qd);\n"
+ "}\n"
+ "float b3Acos(float x) \n"
+ "{ \n"
+ " if (x<-1) \n"
+ " x=-1; \n"
+ " if (x>1) \n"
+ " x=1;\n"
+ " return acos(x); \n"
+ "}\n"
+ "float getAngle(Quaternion orn)\n"
+ "{\n"
+ " if (orn.w>=1.f)\n"
+ " orn.w=1.f;\n"
+ " float s = 2.f * b3Acos(orn.w);\n"
+ " return s;\n"
+ "}\n"
+ "void calculateDiffAxisAngleQuaternion( Quaternion orn0,Quaternion orn1a,float4* axis,float* angle)\n"
+ "{\n"
+ " Quaternion orn1 = nearest(orn0,orn1a);\n"
+ " \n"
+ " Quaternion dorn = qtMul(orn1,qtInvert(orn0));\n"
+ " *angle = getAngle(dorn);\n"
+ " *axis = (float4)(dorn.x,dorn.y,dorn.z,0.f);\n"
+ " \n"
+ " //check for axis length\n"
+ " float len = dot3F4(*axis,*axis);\n"
+ " if (len < FLT_EPSILON*FLT_EPSILON)\n"
+ " *axis = (float4)(1,0,0,0);\n"
+ " else\n"
+ " *axis /= sqrt(len);\n"
+ "}\n"
+ "void getInfo2FixedOrientation(__global b3GpuGenericConstraint* constraint,b3GpuConstraintInfo2* info,__global b3RigidBodyCL* bodies, int start_row)\n"
+ "{\n"
+ " Quaternion worldOrnA = bodies[constraint->m_rbA].m_quat;\n"
+ " Quaternion worldOrnB = bodies[constraint->m_rbB].m_quat;\n"
+ " int s = info->rowskip;\n"
+ " int start_index = start_row * s;\n"
+ " // 3 rows to make body rotations equal\n"
+ " info->m_J1angularAxis[start_index] = 1;\n"
+ " info->m_J1angularAxis[start_index + s + 1] = 1;\n"
+ " info->m_J1angularAxis[start_index + s*2+2] = 1;\n"
+ " if ( info->m_J2angularAxis)\n"
+ " {\n"
+ " info->m_J2angularAxis[start_index] = -1;\n"
+ " info->m_J2angularAxis[start_index + s+1] = -1;\n"
+ " info->m_J2angularAxis[start_index + s*2+2] = -1;\n"
+ " }\n"
+ " \n"
+ " float currERP = info->erp;\n"
+ " float k = info->fps * currERP;\n"
+ " float4 diff;\n"
+ " float angle;\n"
+ " float4 qrelCur = qtMul(worldOrnA,qtInvert(worldOrnB));\n"
+ " \n"
+ " calculateDiffAxisAngleQuaternion(constraint->m_relTargetAB,qrelCur,&diff,&angle);\n"
+ " diff*=-angle;\n"
+ " \n"
+ " float* resultPtr = &diff;\n"
+ " \n"
+ " for (int j=0; j<3; j++)\n"
+ " {\n"
+ " info->m_constraintError[(3+j)*info->rowskip] = k * resultPtr[j];\n"
+ " }\n"
+ " \n"
+ "}\n"
+ "__kernel void writeBackVelocitiesKernel(__global b3RigidBodyCL* bodies,__global b3GpuSolverBody* solverBodies,int numBodies)\n"
+ "{\n"
+ " int i = get_global_id(0);\n"
+ " if (i>=numBodies)\n"
+ " return;\n"
+ " if (bodies[i].m_invMass)\n"
+ " {\n"
+ "// if (length(solverBodies[i].m_deltaLinearVelocity)<MOTIONCLAMP)\n"
+ " {\n"
+ " bodies[i].m_linVel += solverBodies[i].m_deltaLinearVelocity;\n"
+ " }\n"
+ "// if (length(solverBodies[i].m_deltaAngularVelocity)<MOTIONCLAMP)\n"
+ " {\n"
+ " bodies[i].m_angVel += solverBodies[i].m_deltaAngularVelocity;\n"
+ " } \n"
+ " }\n"
+ "}\n"
+ "__kernel void getInfo2Kernel(__global b3SolverConstraint* solverConstraintRows, \n"
+ " __global unsigned int* infos, \n"
+ " __global unsigned int* constraintRowOffsets, \n"
+ " __global b3GpuGenericConstraint* constraints, \n"
+ " __global b3BatchConstraint* batchConstraints, \n"
+ " __global b3RigidBodyCL* bodies,\n"
+ " __global BodyInertia* inertias,\n"
+ " __global b3GpuSolverBody* solverBodies,\n"
+ " float timeStep,\n"
+ " float globalErp,\n"
+ " float globalCfm,\n"
+ " float globalDamping,\n"
+ " int globalNumIterations,\n"
+ " int numConstraints)\n"
+ "{\n"
+ " int i = get_global_id(0);\n"
+ " if (i>=numConstraints)\n"
+ " return;\n"
+ " \n"
+ " //for now, always initialize the batch info\n"
+ " int info1 = infos[i];\n"
+ " \n"
+ " __global b3SolverConstraint* currentConstraintRow = &solverConstraintRows[constraintRowOffsets[i]];\n"
+ " __global b3GpuGenericConstraint* constraint = &constraints[i];\n"
+ " __global b3RigidBodyCL* rbA = &bodies[ constraint->m_rbA];\n"
+ " __global b3RigidBodyCL* rbB = &bodies[ constraint->m_rbB];\n"
+ " int solverBodyIdA = constraint->m_rbA;\n"
+ " int solverBodyIdB = constraint->m_rbB;\n"
+ " __global b3GpuSolverBody* bodyAPtr = &solverBodies[solverBodyIdA];\n"
+ " __global b3GpuSolverBody* bodyBPtr = &solverBodies[solverBodyIdB];\n"
+ " if (rbA->m_invMass)\n"
+ " {\n"
+ " batchConstraints[i].m_bodyAPtrAndSignBit = solverBodyIdA;\n"
+ " } else\n"
+ " {\n"
+ "// if (!solverBodyIdA)\n"
+ "// m_staticIdx = 0;\n"
+ " batchConstraints[i].m_bodyAPtrAndSignBit = -solverBodyIdA;\n"
+ " }\n"
+ " if (rbB->m_invMass)\n"
+ " {\n"
+ " batchConstraints[i].m_bodyBPtrAndSignBit = solverBodyIdB;\n"
+ " } else\n"
+ " {\n"
+ "// if (!solverBodyIdB)\n"
+ "// m_staticIdx = 0;\n"
+ " batchConstraints[i].m_bodyBPtrAndSignBit = -solverBodyIdB;\n"
+ " }\n"
+ " if (info1)\n"
+ " {\n"
+ " int overrideNumSolverIterations = 0;//constraint->getOverrideNumSolverIterations() > 0 ? constraint->getOverrideNumSolverIterations() : infoGlobal.m_numIterations;\n"
+ "// if (overrideNumSolverIterations>m_maxOverrideNumSolverIterations)\n"
+ " // m_maxOverrideNumSolverIterations = overrideNumSolverIterations;\n"
+ " int j;\n"
+ " for ( j=0;j<info1;j++)\n"
+ " {\n"
+ "// memset(&currentConstraintRow[j],0,sizeof(b3SolverConstraint));\n"
+ " currentConstraintRow[j].m_angularComponentA = (float4)(0,0,0,0);\n"
+ " currentConstraintRow[j].m_angularComponentB = (float4)(0,0,0,0);\n"
+ " currentConstraintRow[j].m_appliedImpulse = 0.f;\n"
+ " currentConstraintRow[j].m_appliedPushImpulse = 0.f;\n"
+ " currentConstraintRow[j].m_cfm = 0.f;\n"
+ " currentConstraintRow[j].m_contactNormal = (float4)(0,0,0,0);\n"
+ " currentConstraintRow[j].m_friction = 0.f;\n"
+ " currentConstraintRow[j].m_frictionIndex = 0;\n"
+ " currentConstraintRow[j].m_jacDiagABInv = 0.f;\n"
+ " currentConstraintRow[j].m_lowerLimit = 0.f;\n"
+ " currentConstraintRow[j].m_upperLimit = 0.f;\n"
+ " currentConstraintRow[j].m_originalConstraint = i;\n"
+ " currentConstraintRow[j].m_overrideNumSolverIterations = 0;\n"
+ " currentConstraintRow[j].m_relpos1CrossNormal = (float4)(0,0,0,0);\n"
+ " currentConstraintRow[j].m_relpos2CrossNormal = (float4)(0,0,0,0);\n"
+ " currentConstraintRow[j].m_rhs = 0.f;\n"
+ " currentConstraintRow[j].m_rhsPenetration = 0.f;\n"
+ " currentConstraintRow[j].m_solverBodyIdA = 0;\n"
+ " currentConstraintRow[j].m_solverBodyIdB = 0;\n"
+ " \n"
+ " currentConstraintRow[j].m_lowerLimit = -B3_INFINITY;\n"
+ " currentConstraintRow[j].m_upperLimit = B3_INFINITY;\n"
+ " currentConstraintRow[j].m_appliedImpulse = 0.f;\n"
+ " currentConstraintRow[j].m_appliedPushImpulse = 0.f;\n"
+ " currentConstraintRow[j].m_solverBodyIdA = solverBodyIdA;\n"
+ " currentConstraintRow[j].m_solverBodyIdB = solverBodyIdB;\n"
+ " currentConstraintRow[j].m_overrideNumSolverIterations = overrideNumSolverIterations; \n"
+ " }\n"
+ " bodyAPtr->m_deltaLinearVelocity = (float4)(0,0,0,0);\n"
+ " bodyAPtr->m_deltaAngularVelocity = (float4)(0,0,0,0);\n"
+ " bodyAPtr->m_pushVelocity = (float4)(0,0,0,0);\n"
+ " bodyAPtr->m_turnVelocity = (float4)(0,0,0,0);\n"
+ " bodyBPtr->m_deltaLinearVelocity = (float4)(0,0,0,0);\n"
+ " bodyBPtr->m_deltaAngularVelocity = (float4)(0,0,0,0);\n"
+ " bodyBPtr->m_pushVelocity = (float4)(0,0,0,0);\n"
+ " bodyBPtr->m_turnVelocity = (float4)(0,0,0,0);\n"
+ " int rowskip = sizeof(b3SolverConstraint)/sizeof(float);//check this\n"
+ " \n"
+ " b3GpuConstraintInfo2 info2;\n"
+ " info2.fps = 1.f/timeStep;\n"
+ " info2.erp = globalErp;\n"
+ " info2.m_J1linearAxisFloat4 = &currentConstraintRow->m_contactNormal;\n"
+ " info2.m_J1angularAxisFloat4 = &currentConstraintRow->m_relpos1CrossNormal;\n"
+ " info2.m_J2linearAxisFloat4 = 0;\n"
+ " info2.m_J2angularAxisFloat4 = &currentConstraintRow->m_relpos2CrossNormal;\n"
+ " info2.rowskip = sizeof(b3SolverConstraint)/sizeof(float);//check this\n"
+ " ///the size of b3SolverConstraint needs be a multiple of float\n"
+ "// b3Assert(info2.rowskip*sizeof(float)== sizeof(b3SolverConstraint));\n"
+ " info2.m_constraintError = &currentConstraintRow->m_rhs;\n"
+ " currentConstraintRow->m_cfm = globalCfm;\n"
+ " info2.m_damping = globalDamping;\n"
+ " info2.cfm = &currentConstraintRow->m_cfm;\n"
+ " info2.m_lowerLimit = &currentConstraintRow->m_lowerLimit;\n"
+ " info2.m_upperLimit = &currentConstraintRow->m_upperLimit;\n"
+ " info2.m_numIterations = globalNumIterations;\n"
+ " switch (constraint->m_constraintType)\n"
+ " {\n"
+ " case B3_GPU_POINT2POINT_CONSTRAINT_TYPE:\n"
+ " {\n"
+ " getInfo2Point2Point(constraint,&info2,bodies);\n"
+ " break;\n"
+ " }\n"
+ " case B3_GPU_FIXED_CONSTRAINT_TYPE:\n"
+ " {\n"
+ " getInfo2Point2Point(constraint,&info2,bodies);\n"
+ " getInfo2FixedOrientation(constraint,&info2,bodies,3);\n"
+ " break;\n"
+ " }\n"
+ " default:\n"
+ " {\n"
+ " }\n"
+ " }\n"
+ " ///finalize the constraint setup\n"
+ " for ( j=0;j<info1;j++)\n"
+ " {\n"
+ " __global b3SolverConstraint* solverConstraint = &currentConstraintRow[j];\n"
+ " if (solverConstraint->m_upperLimit>=constraint->m_breakingImpulseThreshold)\n"
+ " {\n"
+ " solverConstraint->m_upperLimit = constraint->m_breakingImpulseThreshold;\n"
+ " }\n"
+ " if (solverConstraint->m_lowerLimit<=-constraint->m_breakingImpulseThreshold)\n"
+ " {\n"
+ " solverConstraint->m_lowerLimit = -constraint->m_breakingImpulseThreshold;\n"
+ " }\n"
+ "// solverConstraint->m_originalContactPoint = constraint;\n"
+ " \n"
+ " Matrix3x3 invInertiaWorldA= inertias[constraint->m_rbA].m_invInertiaWorld;\n"
+ " {\n"
+ " //float4 angularFactorA(1,1,1);\n"
+ " float4 ftorqueAxis1 = solverConstraint->m_relpos1CrossNormal;\n"
+ " solverConstraint->m_angularComponentA = mtMul1(invInertiaWorldA,ftorqueAxis1);//*angularFactorA;\n"
+ " }\n"
+ " \n"
+ " Matrix3x3 invInertiaWorldB= inertias[constraint->m_rbB].m_invInertiaWorld;\n"
+ " {\n"
+ " float4 ftorqueAxis2 = solverConstraint->m_relpos2CrossNormal;\n"
+ " solverConstraint->m_angularComponentB = mtMul1(invInertiaWorldB,ftorqueAxis2);//*constraint->m_rbB.getAngularFactor();\n"
+ " }\n"
+ " {\n"
+ " //it is ok to use solverConstraint->m_contactNormal instead of -solverConstraint->m_contactNormal\n"
+ " //because it gets multiplied iMJlB\n"
+ " float4 iMJlA = solverConstraint->m_contactNormal*rbA->m_invMass;\n"
+ " float4 iMJaA = mtMul3(solverConstraint->m_relpos1CrossNormal,invInertiaWorldA);\n"
+ " float4 iMJlB = solverConstraint->m_contactNormal*rbB->m_invMass;//sign of normal?\n"
+ " float4 iMJaB = mtMul3(solverConstraint->m_relpos2CrossNormal,invInertiaWorldB);\n"
+ " float sum = dot3F4(iMJlA,solverConstraint->m_contactNormal);\n"
+ " sum += dot3F4(iMJaA,solverConstraint->m_relpos1CrossNormal);\n"
+ " sum += dot3F4(iMJlB,solverConstraint->m_contactNormal);\n"
+ " sum += dot3F4(iMJaB,solverConstraint->m_relpos2CrossNormal);\n"
+ " float fsum = fabs(sum);\n"
+ " if (fsum>FLT_EPSILON)\n"
+ " {\n"
+ " solverConstraint->m_jacDiagABInv = 1.f/sum;\n"
+ " } else\n"
+ " {\n"
+ " solverConstraint->m_jacDiagABInv = 0.f;\n"
+ " }\n"
+ " }\n"
+ " ///fix rhs\n"
+ " ///todo: add force/torque accelerators\n"
+ " {\n"
+ " float rel_vel;\n"
+ " float vel1Dotn = dot3F4(solverConstraint->m_contactNormal,rbA->m_linVel) + dot3F4(solverConstraint->m_relpos1CrossNormal,rbA->m_angVel);\n"
+ " float vel2Dotn = -dot3F4(solverConstraint->m_contactNormal,rbB->m_linVel) + dot3F4(solverConstraint->m_relpos2CrossNormal,rbB->m_angVel);\n"
+ " rel_vel = vel1Dotn+vel2Dotn;\n"
+ " float restitution = 0.f;\n"
+ " float positionalError = solverConstraint->m_rhs;//already filled in by getConstraintInfo2\n"
+ " float velocityError = restitution - rel_vel * info2.m_damping;\n"
+ " float penetrationImpulse = positionalError*solverConstraint->m_jacDiagABInv;\n"
+ " float velocityImpulse = velocityError *solverConstraint->m_jacDiagABInv;\n"
+ " solverConstraint->m_rhs = penetrationImpulse+velocityImpulse;\n"
+ " solverConstraint->m_appliedImpulse = 0.f;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solveContact.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solveContact.h
index 15a049992b..6e14ad51fc 100644
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solveContact.h
+++ b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solveContact.h
@@ -1,393 +1,392 @@
//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* solveContactCL= \
-"/*\n"
-"Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
-"This software is provided 'as-is', without any express or implied warranty.\n"
-"In no event will the authors be held liable for any damages arising from the use of this software.\n"
-"Permission is granted to anyone to use this software for any purpose, \n"
-"including commercial applications, and to alter it and redistribute it freely, \n"
-"subject to the following restrictions:\n"
-"1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
-"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
-"3. This notice may not be removed or altered from any source distribution.\n"
-"*/\n"
-"//Originally written by Takahiro Harada\n"
-"//#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
-"#ifdef cl_ext_atomic_counters_32\n"
-"#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
-"#else\n"
-"#define counter32_t volatile global int*\n"
-"#endif\n"
-"typedef unsigned int u32;\n"
-"typedef unsigned short u16;\n"
-"typedef unsigned char u8;\n"
-"#define GET_GROUP_IDX get_group_id(0)\n"
-"#define GET_LOCAL_IDX get_local_id(0)\n"
-"#define GET_GLOBAL_IDX get_global_id(0)\n"
-"#define GET_GROUP_SIZE get_local_size(0)\n"
-"#define GET_NUM_GROUPS get_num_groups(0)\n"
-"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
-"#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
-"#define AtomInc(x) atom_inc(&(x))\n"
-"#define AtomInc1(x, out) out = atom_inc(&(x))\n"
-"#define AppendInc(x, out) out = atomic_inc(x)\n"
-"#define AtomAdd(x, value) atom_add(&(x), value)\n"
-"#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
-"#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
-"#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
-"#define mymake_float4 (float4)\n"
-"//#define make_float2 (float2)\n"
-"//#define make_uint4 (uint4)\n"
-"//#define make_int4 (int4)\n"
-"//#define make_uint2 (uint2)\n"
-"//#define make_int2 (int2)\n"
-"#define max2 max\n"
-"#define min2 min\n"
-"///////////////////////////////////////\n"
-"// Vector\n"
-"///////////////////////////////////////\n"
-"__inline\n"
-"float4 fastNormalize4(float4 v)\n"
-"{\n"
-" return fast_normalize(v);\n"
-"}\n"
-"__inline\n"
-"float4 cross3(float4 a, float4 b)\n"
-"{\n"
-" return cross(a,b);\n"
-"}\n"
-"__inline\n"
-"float dot3F4(float4 a, float4 b)\n"
-"{\n"
-" float4 a1 = mymake_float4(a.xyz,0.f);\n"
-" float4 b1 = mymake_float4(b.xyz,0.f);\n"
-" return dot(a1, b1);\n"
-"}\n"
-"__inline\n"
-"float4 normalize3(const float4 a)\n"
-"{\n"
-" float4 n = mymake_float4(a.x, a.y, a.z, 0.f);\n"
-" return fastNormalize4( n );\n"
-"// float length = sqrtf(dot3F4(a, a));\n"
-"// return 1.f/length * a;\n"
-"}\n"
-"///////////////////////////////////////\n"
-"// Matrix3x3\n"
-"///////////////////////////////////////\n"
-"typedef struct\n"
-"{\n"
-" float4 m_row[3];\n"
-"}Matrix3x3;\n"
-"__inline\n"
-"float4 mtMul1(Matrix3x3 a, float4 b);\n"
-"__inline\n"
-"float4 mtMul3(float4 a, Matrix3x3 b);\n"
-"__inline\n"
-"float4 mtMul1(Matrix3x3 a, float4 b)\n"
-"{\n"
-" float4 ans;\n"
-" ans.x = dot3F4( a.m_row[0], b );\n"
-" ans.y = dot3F4( a.m_row[1], b );\n"
-" ans.z = dot3F4( a.m_row[2], b );\n"
-" ans.w = 0.f;\n"
-" return ans;\n"
-"}\n"
-"__inline\n"
-"float4 mtMul3(float4 a, Matrix3x3 b)\n"
-"{\n"
-" float4 colx = mymake_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
-" float4 coly = mymake_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
-" float4 colz = mymake_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
-" float4 ans;\n"
-" ans.x = dot3F4( a, colx );\n"
-" ans.y = dot3F4( a, coly );\n"
-" ans.z = dot3F4( a, colz );\n"
-" return ans;\n"
-"}\n"
-"///////////////////////////////////////\n"
-"// Quaternion\n"
-"///////////////////////////////////////\n"
-"typedef float4 Quaternion;\n"
-"#define WG_SIZE 64\n"
-"typedef struct\n"
-"{\n"
-" float4 m_pos;\n"
-" Quaternion m_quat;\n"
-" float4 m_linVel;\n"
-" float4 m_angVel;\n"
-" u32 m_shapeIdx;\n"
-" float m_invMass;\n"
-" float m_restituitionCoeff;\n"
-" float m_frictionCoeff;\n"
-"} Body;\n"
-"typedef struct\n"
-"{\n"
-" Matrix3x3 m_invInertia;\n"
-" Matrix3x3 m_initInvInertia;\n"
-"} Shape;\n"
-"typedef struct\n"
-"{\n"
-" float4 m_linear;\n"
-" float4 m_worldPos[4];\n"
-" float4 m_center; \n"
-" float m_jacCoeffInv[4];\n"
-" float m_b[4];\n"
-" float m_appliedRambdaDt[4];\n"
-" float m_fJacCoeffInv[2]; \n"
-" float m_fAppliedRambdaDt[2]; \n"
-" u32 m_bodyA;\n"
-" u32 m_bodyB;\n"
-" int m_batchIdx;\n"
-" u32 m_paddings[1];\n"
-"} Constraint4;\n"
-"typedef struct\n"
-"{\n"
-" int m_nConstraints;\n"
-" int m_start;\n"
-" int m_batchIdx;\n"
-" int m_nSplit;\n"
-"// int m_paddings[1];\n"
-"} ConstBuffer;\n"
-"typedef struct\n"
-"{\n"
-" int m_solveFriction;\n"
-" int m_maxBatch; // long batch really kills the performance\n"
-" int m_batchIdx;\n"
-" int m_nSplit;\n"
-"// int m_paddings[1];\n"
-"} ConstBufferBatchSolve;\n"
-"void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1);\n"
-"void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1)\n"
-"{\n"
-" *linear = mymake_float4(-n.xyz,0.f);\n"
-" *angular0 = -cross3(r0, n);\n"
-" *angular1 = cross3(r1, n);\n"
-"}\n"
-"float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 );\n"
-"float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 )\n"
-"{\n"
-" return dot3F4(l0, linVel0) + dot3F4(a0, angVel0) + dot3F4(l1, linVel1) + dot3F4(a1, angVel1);\n"
-"}\n"
-"float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,\n"
-" float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1);\n"
-"float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,\n"
-" float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1)\n"
-"{\n"
-" // linear0,1 are normlized\n"
-" float jmj0 = invMass0;//dot3F4(linear0, linear0)*invMass0;\n"
-" float jmj1 = dot3F4(mtMul3(angular0,*invInertia0), angular0);\n"
-" float jmj2 = invMass1;//dot3F4(linear1, linear1)*invMass1;\n"
-" float jmj3 = dot3F4(mtMul3(angular1,*invInertia1), angular1);\n"
-" return -1.f/(jmj0+jmj1+jmj2+jmj3);\n"
-"}\n"
-"void solveContact(__global Constraint4* cs,\n"
-" float4 posA, float4* linVelA, float4* angVelA, float invMassA, Matrix3x3 invInertiaA,\n"
-" float4 posB, float4* linVelB, float4* angVelB, float invMassB, Matrix3x3 invInertiaB);\n"
-"void solveContact(__global Constraint4* cs,\n"
-" float4 posA, float4* linVelA, float4* angVelA, float invMassA, Matrix3x3 invInertiaA,\n"
-" float4 posB, float4* linVelB, float4* angVelB, float invMassB, Matrix3x3 invInertiaB)\n"
-"{\n"
-" float minRambdaDt = 0;\n"
-" float maxRambdaDt = FLT_MAX;\n"
-" for(int ic=0; ic<4; ic++)\n"
-" {\n"
-" if( cs->m_jacCoeffInv[ic] == 0.f ) continue;\n"
-" float4 angular0, angular1, linear;\n"
-" float4 r0 = cs->m_worldPos[ic] - posA;\n"
-" float4 r1 = cs->m_worldPos[ic] - posB;\n"
-" setLinearAndAngular( -cs->m_linear, r0, r1, &linear, &angular0, &angular1 );\n"
-" float rambdaDt = calcRelVel( cs->m_linear, -cs->m_linear, angular0, angular1, \n"
-" *linVelA, *angVelA, *linVelB, *angVelB ) + cs->m_b[ic];\n"
-" rambdaDt *= cs->m_jacCoeffInv[ic];\n"
-" {\n"
-" float prevSum = cs->m_appliedRambdaDt[ic];\n"
-" float updated = prevSum;\n"
-" updated += rambdaDt;\n"
-" updated = max2( updated, minRambdaDt );\n"
-" updated = min2( updated, maxRambdaDt );\n"
-" rambdaDt = updated - prevSum;\n"
-" cs->m_appliedRambdaDt[ic] = updated;\n"
-" }\n"
-" float4 linImp0 = invMassA*linear*rambdaDt;\n"
-" float4 linImp1 = invMassB*(-linear)*rambdaDt;\n"
-" float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;\n"
-" float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;\n"
-" *linVelA += linImp0;\n"
-" *angVelA += angImp0;\n"
-" *linVelB += linImp1;\n"
-" *angVelB += angImp1;\n"
-" }\n"
-"}\n"
-"void btPlaneSpace1 (const float4* n, float4* p, float4* q);\n"
-" void btPlaneSpace1 (const float4* n, float4* p, float4* q)\n"
-"{\n"
-" if (fabs(n[0].z) > 0.70710678f) {\n"
-" // choose p in y-z plane\n"
-" float a = n[0].y*n[0].y + n[0].z*n[0].z;\n"
-" float k = 1.f/sqrt(a);\n"
-" p[0].x = 0;\n"
-" p[0].y = -n[0].z*k;\n"
-" p[0].z = n[0].y*k;\n"
-" // set q = n x p\n"
-" q[0].x = a*k;\n"
-" q[0].y = -n[0].x*p[0].z;\n"
-" q[0].z = n[0].x*p[0].y;\n"
-" }\n"
-" else {\n"
-" // choose p in x-y plane\n"
-" float a = n[0].x*n[0].x + n[0].y*n[0].y;\n"
-" float k = 1.f/sqrt(a);\n"
-" p[0].x = -n[0].y*k;\n"
-" p[0].y = n[0].x*k;\n"
-" p[0].z = 0;\n"
-" // set q = n x p\n"
-" q[0].x = -n[0].z*p[0].y;\n"
-" q[0].y = n[0].z*p[0].x;\n"
-" q[0].z = a*k;\n"
-" }\n"
-"}\n"
-"void solveContactConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs);\n"
-"void solveContactConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs)\n"
-"{\n"
-" //float frictionCoeff = ldsCs[0].m_linear.w;\n"
-" int aIdx = ldsCs[0].m_bodyA;\n"
-" int bIdx = ldsCs[0].m_bodyB;\n"
-" float4 posA = gBodies[aIdx].m_pos;\n"
-" float4 linVelA = gBodies[aIdx].m_linVel;\n"
-" float4 angVelA = gBodies[aIdx].m_angVel;\n"
-" float invMassA = gBodies[aIdx].m_invMass;\n"
-" Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;\n"
-" float4 posB = gBodies[bIdx].m_pos;\n"
-" float4 linVelB = gBodies[bIdx].m_linVel;\n"
-" float4 angVelB = gBodies[bIdx].m_angVel;\n"
-" float invMassB = gBodies[bIdx].m_invMass;\n"
-" Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;\n"
-" solveContact( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,\n"
-" posB, &linVelB, &angVelB, invMassB, invInertiaB );\n"
-" if (gBodies[aIdx].m_invMass)\n"
-" {\n"
-" gBodies[aIdx].m_linVel = linVelA;\n"
-" gBodies[aIdx].m_angVel = angVelA;\n"
-" } else\n"
-" {\n"
-" gBodies[aIdx].m_linVel = mymake_float4(0,0,0,0);\n"
-" gBodies[aIdx].m_angVel = mymake_float4(0,0,0,0);\n"
-" \n"
-" }\n"
-" if (gBodies[bIdx].m_invMass)\n"
-" {\n"
-" gBodies[bIdx].m_linVel = linVelB;\n"
-" gBodies[bIdx].m_angVel = angVelB;\n"
-" } else\n"
-" {\n"
-" gBodies[bIdx].m_linVel = mymake_float4(0,0,0,0);\n"
-" gBodies[bIdx].m_angVel = mymake_float4(0,0,0,0);\n"
-" \n"
-" }\n"
-"}\n"
-"typedef struct \n"
-"{\n"
-" int m_valInt0;\n"
-" int m_valInt1;\n"
-" int m_valInt2;\n"
-" int m_valInt3;\n"
-" float m_val0;\n"
-" float m_val1;\n"
-" float m_val2;\n"
-" float m_val3;\n"
-"} SolverDebugInfo;\n"
-"__kernel\n"
-"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
-"void BatchSolveKernelContact(__global Body* gBodies,\n"
-" __global Shape* gShapes,\n"
-" __global Constraint4* gConstraints,\n"
-" __global int* gN,\n"
-" __global int* gOffsets,\n"
-" __global int* batchSizes,\n"
-" int maxBatch1,\n"
-" int cellBatch,\n"
-" int4 nSplit\n"
-" )\n"
-"{\n"
-" //__local int ldsBatchIdx[WG_SIZE+1];\n"
-" __local int ldsCurBatch;\n"
-" __local int ldsNextBatch;\n"
-" __local int ldsStart;\n"
-" int lIdx = GET_LOCAL_IDX;\n"
-" int wgIdx = GET_GROUP_IDX;\n"
-"// int gIdx = GET_GLOBAL_IDX;\n"
-"// debugInfo[gIdx].m_valInt0 = gIdx;\n"
-" //debugInfo[gIdx].m_valInt1 = GET_GROUP_SIZE;\n"
-" \n"
-" \n"
-" int zIdx = (wgIdx/((nSplit.x*nSplit.y)/4))*2+((cellBatch&4)>>2);\n"
-" int remain= (wgIdx%((nSplit.x*nSplit.y)/4));\n"
-" int yIdx = (remain/(nSplit.x/2))*2 + ((cellBatch&2)>>1);\n"
-" int xIdx = (remain%(nSplit.x/2))*2 + (cellBatch&1);\n"
-" int cellIdx = xIdx+yIdx*nSplit.x+zIdx*(nSplit.x*nSplit.y);\n"
-" //int xIdx = (wgIdx/(nSplit/2))*2 + (bIdx&1);\n"
-" //int yIdx = (wgIdx%(nSplit/2))*2 + (bIdx>>1);\n"
-" //int cellIdx = xIdx+yIdx*nSplit;\n"
-" \n"
-" if( gN[cellIdx] == 0 ) \n"
-" return;\n"
-" int maxBatch = batchSizes[cellIdx];\n"
-" \n"
-" \n"
-" const int start = gOffsets[cellIdx];\n"
-" const int end = start + gN[cellIdx];\n"
-" \n"
-" \n"
-" \n"
-" if( lIdx == 0 )\n"
-" {\n"
-" ldsCurBatch = 0;\n"
-" ldsNextBatch = 0;\n"
-" ldsStart = start;\n"
-" }\n"
-" GROUP_LDS_BARRIER;\n"
-" int idx=ldsStart+lIdx;\n"
-" while (ldsCurBatch < maxBatch)\n"
-" {\n"
-" for(; idx<end; )\n"
-" {\n"
-" if (gConstraints[idx].m_batchIdx == ldsCurBatch)\n"
-" {\n"
-" solveContactConstraint( gBodies, gShapes, &gConstraints[idx] );\n"
-" idx+=64;\n"
-" } else\n"
-" {\n"
-" break;\n"
-" }\n"
-" }\n"
-" GROUP_LDS_BARRIER;\n"
-" \n"
-" if( lIdx == 0 )\n"
-" {\n"
-" ldsCurBatch++;\n"
-" }\n"
-" GROUP_LDS_BARRIER;\n"
-" }\n"
-" \n"
-" \n"
-"}\n"
-"__kernel void solveSingleContactKernel(__global Body* gBodies,\n"
-" __global Shape* gShapes,\n"
-" __global Constraint4* gConstraints,\n"
-" int cellIdx,\n"
-" int batchOffset,\n"
-" int numConstraintsInBatch\n"
-" )\n"
-"{\n"
-" int index = get_global_id(0);\n"
-" if (index < numConstraintsInBatch)\n"
-" {\n"
-" int idx=batchOffset+index;\n"
-" solveContactConstraint( gBodies, gShapes, &gConstraints[idx] );\n"
-" } \n"
-"}\n"
-;
+static const char* solveContactCL =
+ "/*\n"
+ "Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
+ "This software is provided 'as-is', without any express or implied warranty.\n"
+ "In no event will the authors be held liable for any damages arising from the use of this software.\n"
+ "Permission is granted to anyone to use this software for any purpose, \n"
+ "including commercial applications, and to alter it and redistribute it freely, \n"
+ "subject to the following restrictions:\n"
+ "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
+ "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+ "3. This notice may not be removed or altered from any source distribution.\n"
+ "*/\n"
+ "//Originally written by Takahiro Harada\n"
+ "//#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
+ "#ifdef cl_ext_atomic_counters_32\n"
+ "#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
+ "#else\n"
+ "#define counter32_t volatile global int*\n"
+ "#endif\n"
+ "typedef unsigned int u32;\n"
+ "typedef unsigned short u16;\n"
+ "typedef unsigned char u8;\n"
+ "#define GET_GROUP_IDX get_group_id(0)\n"
+ "#define GET_LOCAL_IDX get_local_id(0)\n"
+ "#define GET_GLOBAL_IDX get_global_id(0)\n"
+ "#define GET_GROUP_SIZE get_local_size(0)\n"
+ "#define GET_NUM_GROUPS get_num_groups(0)\n"
+ "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+ "#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
+ "#define AtomInc(x) atom_inc(&(x))\n"
+ "#define AtomInc1(x, out) out = atom_inc(&(x))\n"
+ "#define AppendInc(x, out) out = atomic_inc(x)\n"
+ "#define AtomAdd(x, value) atom_add(&(x), value)\n"
+ "#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
+ "#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
+ "#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
+ "#define mymake_float4 (float4)\n"
+ "//#define make_float2 (float2)\n"
+ "//#define make_uint4 (uint4)\n"
+ "//#define make_int4 (int4)\n"
+ "//#define make_uint2 (uint2)\n"
+ "//#define make_int2 (int2)\n"
+ "#define max2 max\n"
+ "#define min2 min\n"
+ "///////////////////////////////////////\n"
+ "// Vector\n"
+ "///////////////////////////////////////\n"
+ "__inline\n"
+ "float4 fastNormalize4(float4 v)\n"
+ "{\n"
+ " return fast_normalize(v);\n"
+ "}\n"
+ "__inline\n"
+ "float4 cross3(float4 a, float4 b)\n"
+ "{\n"
+ " return cross(a,b);\n"
+ "}\n"
+ "__inline\n"
+ "float dot3F4(float4 a, float4 b)\n"
+ "{\n"
+ " float4 a1 = mymake_float4(a.xyz,0.f);\n"
+ " float4 b1 = mymake_float4(b.xyz,0.f);\n"
+ " return dot(a1, b1);\n"
+ "}\n"
+ "__inline\n"
+ "float4 normalize3(const float4 a)\n"
+ "{\n"
+ " float4 n = mymake_float4(a.x, a.y, a.z, 0.f);\n"
+ " return fastNormalize4( n );\n"
+ "// float length = sqrtf(dot3F4(a, a));\n"
+ "// return 1.f/length * a;\n"
+ "}\n"
+ "///////////////////////////////////////\n"
+ "// Matrix3x3\n"
+ "///////////////////////////////////////\n"
+ "typedef struct\n"
+ "{\n"
+ " float4 m_row[3];\n"
+ "}Matrix3x3;\n"
+ "__inline\n"
+ "float4 mtMul1(Matrix3x3 a, float4 b);\n"
+ "__inline\n"
+ "float4 mtMul3(float4 a, Matrix3x3 b);\n"
+ "__inline\n"
+ "float4 mtMul1(Matrix3x3 a, float4 b)\n"
+ "{\n"
+ " float4 ans;\n"
+ " ans.x = dot3F4( a.m_row[0], b );\n"
+ " ans.y = dot3F4( a.m_row[1], b );\n"
+ " ans.z = dot3F4( a.m_row[2], b );\n"
+ " ans.w = 0.f;\n"
+ " return ans;\n"
+ "}\n"
+ "__inline\n"
+ "float4 mtMul3(float4 a, Matrix3x3 b)\n"
+ "{\n"
+ " float4 colx = mymake_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
+ " float4 coly = mymake_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
+ " float4 colz = mymake_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
+ " float4 ans;\n"
+ " ans.x = dot3F4( a, colx );\n"
+ " ans.y = dot3F4( a, coly );\n"
+ " ans.z = dot3F4( a, colz );\n"
+ " return ans;\n"
+ "}\n"
+ "///////////////////////////////////////\n"
+ "// Quaternion\n"
+ "///////////////////////////////////////\n"
+ "typedef float4 Quaternion;\n"
+ "#define WG_SIZE 64\n"
+ "typedef struct\n"
+ "{\n"
+ " float4 m_pos;\n"
+ " Quaternion m_quat;\n"
+ " float4 m_linVel;\n"
+ " float4 m_angVel;\n"
+ " u32 m_shapeIdx;\n"
+ " float m_invMass;\n"
+ " float m_restituitionCoeff;\n"
+ " float m_frictionCoeff;\n"
+ "} Body;\n"
+ "typedef struct\n"
+ "{\n"
+ " Matrix3x3 m_invInertia;\n"
+ " Matrix3x3 m_initInvInertia;\n"
+ "} Shape;\n"
+ "typedef struct\n"
+ "{\n"
+ " float4 m_linear;\n"
+ " float4 m_worldPos[4];\n"
+ " float4 m_center; \n"
+ " float m_jacCoeffInv[4];\n"
+ " float m_b[4];\n"
+ " float m_appliedRambdaDt[4];\n"
+ " float m_fJacCoeffInv[2]; \n"
+ " float m_fAppliedRambdaDt[2]; \n"
+ " u32 m_bodyA;\n"
+ " u32 m_bodyB;\n"
+ " int m_batchIdx;\n"
+ " u32 m_paddings[1];\n"
+ "} Constraint4;\n"
+ "typedef struct\n"
+ "{\n"
+ " int m_nConstraints;\n"
+ " int m_start;\n"
+ " int m_batchIdx;\n"
+ " int m_nSplit;\n"
+ "// int m_paddings[1];\n"
+ "} ConstBuffer;\n"
+ "typedef struct\n"
+ "{\n"
+ " int m_solveFriction;\n"
+ " int m_maxBatch; // long batch really kills the performance\n"
+ " int m_batchIdx;\n"
+ " int m_nSplit;\n"
+ "// int m_paddings[1];\n"
+ "} ConstBufferBatchSolve;\n"
+ "void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1);\n"
+ "void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1)\n"
+ "{\n"
+ " *linear = mymake_float4(-n.xyz,0.f);\n"
+ " *angular0 = -cross3(r0, n);\n"
+ " *angular1 = cross3(r1, n);\n"
+ "}\n"
+ "float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 );\n"
+ "float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 )\n"
+ "{\n"
+ " return dot3F4(l0, linVel0) + dot3F4(a0, angVel0) + dot3F4(l1, linVel1) + dot3F4(a1, angVel1);\n"
+ "}\n"
+ "float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,\n"
+ " float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1);\n"
+ "float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,\n"
+ " float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1)\n"
+ "{\n"
+ " // linear0,1 are normlized\n"
+ " float jmj0 = invMass0;//dot3F4(linear0, linear0)*invMass0;\n"
+ " float jmj1 = dot3F4(mtMul3(angular0,*invInertia0), angular0);\n"
+ " float jmj2 = invMass1;//dot3F4(linear1, linear1)*invMass1;\n"
+ " float jmj3 = dot3F4(mtMul3(angular1,*invInertia1), angular1);\n"
+ " return -1.f/(jmj0+jmj1+jmj2+jmj3);\n"
+ "}\n"
+ "void solveContact(__global Constraint4* cs,\n"
+ " float4 posA, float4* linVelA, float4* angVelA, float invMassA, Matrix3x3 invInertiaA,\n"
+ " float4 posB, float4* linVelB, float4* angVelB, float invMassB, Matrix3x3 invInertiaB);\n"
+ "void solveContact(__global Constraint4* cs,\n"
+ " float4 posA, float4* linVelA, float4* angVelA, float invMassA, Matrix3x3 invInertiaA,\n"
+ " float4 posB, float4* linVelB, float4* angVelB, float invMassB, Matrix3x3 invInertiaB)\n"
+ "{\n"
+ " float minRambdaDt = 0;\n"
+ " float maxRambdaDt = FLT_MAX;\n"
+ " for(int ic=0; ic<4; ic++)\n"
+ " {\n"
+ " if( cs->m_jacCoeffInv[ic] == 0.f ) continue;\n"
+ " float4 angular0, angular1, linear;\n"
+ " float4 r0 = cs->m_worldPos[ic] - posA;\n"
+ " float4 r1 = cs->m_worldPos[ic] - posB;\n"
+ " setLinearAndAngular( -cs->m_linear, r0, r1, &linear, &angular0, &angular1 );\n"
+ " float rambdaDt = calcRelVel( cs->m_linear, -cs->m_linear, angular0, angular1, \n"
+ " *linVelA, *angVelA, *linVelB, *angVelB ) + cs->m_b[ic];\n"
+ " rambdaDt *= cs->m_jacCoeffInv[ic];\n"
+ " {\n"
+ " float prevSum = cs->m_appliedRambdaDt[ic];\n"
+ " float updated = prevSum;\n"
+ " updated += rambdaDt;\n"
+ " updated = max2( updated, minRambdaDt );\n"
+ " updated = min2( updated, maxRambdaDt );\n"
+ " rambdaDt = updated - prevSum;\n"
+ " cs->m_appliedRambdaDt[ic] = updated;\n"
+ " }\n"
+ " float4 linImp0 = invMassA*linear*rambdaDt;\n"
+ " float4 linImp1 = invMassB*(-linear)*rambdaDt;\n"
+ " float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;\n"
+ " float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;\n"
+ " *linVelA += linImp0;\n"
+ " *angVelA += angImp0;\n"
+ " *linVelB += linImp1;\n"
+ " *angVelB += angImp1;\n"
+ " }\n"
+ "}\n"
+ "void btPlaneSpace1 (const float4* n, float4* p, float4* q);\n"
+ " void btPlaneSpace1 (const float4* n, float4* p, float4* q)\n"
+ "{\n"
+ " if (fabs(n[0].z) > 0.70710678f) {\n"
+ " // choose p in y-z plane\n"
+ " float a = n[0].y*n[0].y + n[0].z*n[0].z;\n"
+ " float k = 1.f/sqrt(a);\n"
+ " p[0].x = 0;\n"
+ " p[0].y = -n[0].z*k;\n"
+ " p[0].z = n[0].y*k;\n"
+ " // set q = n x p\n"
+ " q[0].x = a*k;\n"
+ " q[0].y = -n[0].x*p[0].z;\n"
+ " q[0].z = n[0].x*p[0].y;\n"
+ " }\n"
+ " else {\n"
+ " // choose p in x-y plane\n"
+ " float a = n[0].x*n[0].x + n[0].y*n[0].y;\n"
+ " float k = 1.f/sqrt(a);\n"
+ " p[0].x = -n[0].y*k;\n"
+ " p[0].y = n[0].x*k;\n"
+ " p[0].z = 0;\n"
+ " // set q = n x p\n"
+ " q[0].x = -n[0].z*p[0].y;\n"
+ " q[0].y = n[0].z*p[0].x;\n"
+ " q[0].z = a*k;\n"
+ " }\n"
+ "}\n"
+ "void solveContactConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs);\n"
+ "void solveContactConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs)\n"
+ "{\n"
+ " //float frictionCoeff = ldsCs[0].m_linear.w;\n"
+ " int aIdx = ldsCs[0].m_bodyA;\n"
+ " int bIdx = ldsCs[0].m_bodyB;\n"
+ " float4 posA = gBodies[aIdx].m_pos;\n"
+ " float4 linVelA = gBodies[aIdx].m_linVel;\n"
+ " float4 angVelA = gBodies[aIdx].m_angVel;\n"
+ " float invMassA = gBodies[aIdx].m_invMass;\n"
+ " Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;\n"
+ " float4 posB = gBodies[bIdx].m_pos;\n"
+ " float4 linVelB = gBodies[bIdx].m_linVel;\n"
+ " float4 angVelB = gBodies[bIdx].m_angVel;\n"
+ " float invMassB = gBodies[bIdx].m_invMass;\n"
+ " Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;\n"
+ " solveContact( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,\n"
+ " posB, &linVelB, &angVelB, invMassB, invInertiaB );\n"
+ " if (gBodies[aIdx].m_invMass)\n"
+ " {\n"
+ " gBodies[aIdx].m_linVel = linVelA;\n"
+ " gBodies[aIdx].m_angVel = angVelA;\n"
+ " } else\n"
+ " {\n"
+ " gBodies[aIdx].m_linVel = mymake_float4(0,0,0,0);\n"
+ " gBodies[aIdx].m_angVel = mymake_float4(0,0,0,0);\n"
+ " \n"
+ " }\n"
+ " if (gBodies[bIdx].m_invMass)\n"
+ " {\n"
+ " gBodies[bIdx].m_linVel = linVelB;\n"
+ " gBodies[bIdx].m_angVel = angVelB;\n"
+ " } else\n"
+ " {\n"
+ " gBodies[bIdx].m_linVel = mymake_float4(0,0,0,0);\n"
+ " gBodies[bIdx].m_angVel = mymake_float4(0,0,0,0);\n"
+ " \n"
+ " }\n"
+ "}\n"
+ "typedef struct \n"
+ "{\n"
+ " int m_valInt0;\n"
+ " int m_valInt1;\n"
+ " int m_valInt2;\n"
+ " int m_valInt3;\n"
+ " float m_val0;\n"
+ " float m_val1;\n"
+ " float m_val2;\n"
+ " float m_val3;\n"
+ "} SolverDebugInfo;\n"
+ "__kernel\n"
+ "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+ "void BatchSolveKernelContact(__global Body* gBodies,\n"
+ " __global Shape* gShapes,\n"
+ " __global Constraint4* gConstraints,\n"
+ " __global int* gN,\n"
+ " __global int* gOffsets,\n"
+ " __global int* batchSizes,\n"
+ " int maxBatch1,\n"
+ " int cellBatch,\n"
+ " int4 nSplit\n"
+ " )\n"
+ "{\n"
+ " //__local int ldsBatchIdx[WG_SIZE+1];\n"
+ " __local int ldsCurBatch;\n"
+ " __local int ldsNextBatch;\n"
+ " __local int ldsStart;\n"
+ " int lIdx = GET_LOCAL_IDX;\n"
+ " int wgIdx = GET_GROUP_IDX;\n"
+ "// int gIdx = GET_GLOBAL_IDX;\n"
+ "// debugInfo[gIdx].m_valInt0 = gIdx;\n"
+ " //debugInfo[gIdx].m_valInt1 = GET_GROUP_SIZE;\n"
+ " \n"
+ " \n"
+ " int zIdx = (wgIdx/((nSplit.x*nSplit.y)/4))*2+((cellBatch&4)>>2);\n"
+ " int remain= (wgIdx%((nSplit.x*nSplit.y)/4));\n"
+ " int yIdx = (remain/(nSplit.x/2))*2 + ((cellBatch&2)>>1);\n"
+ " int xIdx = (remain%(nSplit.x/2))*2 + (cellBatch&1);\n"
+ " int cellIdx = xIdx+yIdx*nSplit.x+zIdx*(nSplit.x*nSplit.y);\n"
+ " //int xIdx = (wgIdx/(nSplit/2))*2 + (bIdx&1);\n"
+ " //int yIdx = (wgIdx%(nSplit/2))*2 + (bIdx>>1);\n"
+ " //int cellIdx = xIdx+yIdx*nSplit;\n"
+ " \n"
+ " if( gN[cellIdx] == 0 ) \n"
+ " return;\n"
+ " int maxBatch = batchSizes[cellIdx];\n"
+ " \n"
+ " \n"
+ " const int start = gOffsets[cellIdx];\n"
+ " const int end = start + gN[cellIdx];\n"
+ " \n"
+ " \n"
+ " \n"
+ " if( lIdx == 0 )\n"
+ " {\n"
+ " ldsCurBatch = 0;\n"
+ " ldsNextBatch = 0;\n"
+ " ldsStart = start;\n"
+ " }\n"
+ " GROUP_LDS_BARRIER;\n"
+ " int idx=ldsStart+lIdx;\n"
+ " while (ldsCurBatch < maxBatch)\n"
+ " {\n"
+ " for(; idx<end; )\n"
+ " {\n"
+ " if (gConstraints[idx].m_batchIdx == ldsCurBatch)\n"
+ " {\n"
+ " solveContactConstraint( gBodies, gShapes, &gConstraints[idx] );\n"
+ " idx+=64;\n"
+ " } else\n"
+ " {\n"
+ " break;\n"
+ " }\n"
+ " }\n"
+ " GROUP_LDS_BARRIER;\n"
+ " \n"
+ " if( lIdx == 0 )\n"
+ " {\n"
+ " ldsCurBatch++;\n"
+ " }\n"
+ " GROUP_LDS_BARRIER;\n"
+ " }\n"
+ " \n"
+ " \n"
+ "}\n"
+ "__kernel void solveSingleContactKernel(__global Body* gBodies,\n"
+ " __global Shape* gShapes,\n"
+ " __global Constraint4* gConstraints,\n"
+ " int cellIdx,\n"
+ " int batchOffset,\n"
+ " int numConstraintsInBatch\n"
+ " )\n"
+ "{\n"
+ " int index = get_global_id(0);\n"
+ " if (index < numConstraintsInBatch)\n"
+ " {\n"
+ " int idx=batchOffset+index;\n"
+ " solveContactConstraint( gBodies, gShapes, &gConstraints[idx] );\n"
+ " } \n"
+ "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solveFriction.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solveFriction.h
index eb58674f22..9707cdb25d 100644
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solveFriction.h
+++ b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solveFriction.h
@@ -1,421 +1,420 @@
//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* solveFrictionCL= \
-"/*\n"
-"Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
-"This software is provided 'as-is', without any express or implied warranty.\n"
-"In no event will the authors be held liable for any damages arising from the use of this software.\n"
-"Permission is granted to anyone to use this software for any purpose, \n"
-"including commercial applications, and to alter it and redistribute it freely, \n"
-"subject to the following restrictions:\n"
-"1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
-"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
-"3. This notice may not be removed or altered from any source distribution.\n"
-"*/\n"
-"//Originally written by Takahiro Harada\n"
-"//#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
-"#ifdef cl_ext_atomic_counters_32\n"
-"#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
-"#else\n"
-"#define counter32_t volatile global int*\n"
-"#endif\n"
-"typedef unsigned int u32;\n"
-"typedef unsigned short u16;\n"
-"typedef unsigned char u8;\n"
-"#define GET_GROUP_IDX get_group_id(0)\n"
-"#define GET_LOCAL_IDX get_local_id(0)\n"
-"#define GET_GLOBAL_IDX get_global_id(0)\n"
-"#define GET_GROUP_SIZE get_local_size(0)\n"
-"#define GET_NUM_GROUPS get_num_groups(0)\n"
-"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
-"#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
-"#define AtomInc(x) atom_inc(&(x))\n"
-"#define AtomInc1(x, out) out = atom_inc(&(x))\n"
-"#define AppendInc(x, out) out = atomic_inc(x)\n"
-"#define AtomAdd(x, value) atom_add(&(x), value)\n"
-"#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
-"#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
-"#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
-"#define mymake_float4 (float4)\n"
-"//#define make_float2 (float2)\n"
-"//#define make_uint4 (uint4)\n"
-"//#define make_int4 (int4)\n"
-"//#define make_uint2 (uint2)\n"
-"//#define make_int2 (int2)\n"
-"#define max2 max\n"
-"#define min2 min\n"
-"///////////////////////////////////////\n"
-"// Vector\n"
-"///////////////////////////////////////\n"
-"__inline\n"
-"float4 fastNormalize4(float4 v)\n"
-"{\n"
-" return fast_normalize(v);\n"
-"}\n"
-"__inline\n"
-"float4 cross3(float4 a, float4 b)\n"
-"{\n"
-" return cross(a,b);\n"
-"}\n"
-"__inline\n"
-"float dot3F4(float4 a, float4 b)\n"
-"{\n"
-" float4 a1 = mymake_float4(a.xyz,0.f);\n"
-" float4 b1 = mymake_float4(b.xyz,0.f);\n"
-" return dot(a1, b1);\n"
-"}\n"
-"__inline\n"
-"float4 normalize3(const float4 a)\n"
-"{\n"
-" float4 n = mymake_float4(a.x, a.y, a.z, 0.f);\n"
-" return fastNormalize4( n );\n"
-"// float length = sqrtf(dot3F4(a, a));\n"
-"// return 1.f/length * a;\n"
-"}\n"
-"///////////////////////////////////////\n"
-"// Matrix3x3\n"
-"///////////////////////////////////////\n"
-"typedef struct\n"
-"{\n"
-" float4 m_row[3];\n"
-"}Matrix3x3;\n"
-"__inline\n"
-"float4 mtMul1(Matrix3x3 a, float4 b);\n"
-"__inline\n"
-"float4 mtMul3(float4 a, Matrix3x3 b);\n"
-"__inline\n"
-"float4 mtMul1(Matrix3x3 a, float4 b)\n"
-"{\n"
-" float4 ans;\n"
-" ans.x = dot3F4( a.m_row[0], b );\n"
-" ans.y = dot3F4( a.m_row[1], b );\n"
-" ans.z = dot3F4( a.m_row[2], b );\n"
-" ans.w = 0.f;\n"
-" return ans;\n"
-"}\n"
-"__inline\n"
-"float4 mtMul3(float4 a, Matrix3x3 b)\n"
-"{\n"
-" float4 colx = mymake_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
-" float4 coly = mymake_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
-" float4 colz = mymake_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
-" float4 ans;\n"
-" ans.x = dot3F4( a, colx );\n"
-" ans.y = dot3F4( a, coly );\n"
-" ans.z = dot3F4( a, colz );\n"
-" return ans;\n"
-"}\n"
-"///////////////////////////////////////\n"
-"// Quaternion\n"
-"///////////////////////////////////////\n"
-"typedef float4 Quaternion;\n"
-"#define WG_SIZE 64\n"
-"typedef struct\n"
-"{\n"
-" float4 m_pos;\n"
-" Quaternion m_quat;\n"
-" float4 m_linVel;\n"
-" float4 m_angVel;\n"
-" u32 m_shapeIdx;\n"
-" float m_invMass;\n"
-" float m_restituitionCoeff;\n"
-" float m_frictionCoeff;\n"
-"} Body;\n"
-"typedef struct\n"
-"{\n"
-" Matrix3x3 m_invInertia;\n"
-" Matrix3x3 m_initInvInertia;\n"
-"} Shape;\n"
-"typedef struct\n"
-"{\n"
-" float4 m_linear;\n"
-" float4 m_worldPos[4];\n"
-" float4 m_center; \n"
-" float m_jacCoeffInv[4];\n"
-" float m_b[4];\n"
-" float m_appliedRambdaDt[4];\n"
-" float m_fJacCoeffInv[2]; \n"
-" float m_fAppliedRambdaDt[2]; \n"
-" u32 m_bodyA;\n"
-" u32 m_bodyB;\n"
-" int m_batchIdx;\n"
-" u32 m_paddings[1];\n"
-"} Constraint4;\n"
-"typedef struct\n"
-"{\n"
-" int m_nConstraints;\n"
-" int m_start;\n"
-" int m_batchIdx;\n"
-" int m_nSplit;\n"
-"// int m_paddings[1];\n"
-"} ConstBuffer;\n"
-"typedef struct\n"
-"{\n"
-" int m_solveFriction;\n"
-" int m_maxBatch; // long batch really kills the performance\n"
-" int m_batchIdx;\n"
-" int m_nSplit;\n"
-"// int m_paddings[1];\n"
-"} ConstBufferBatchSolve;\n"
-"void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1);\n"
-"void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1)\n"
-"{\n"
-" *linear = mymake_float4(-n.xyz,0.f);\n"
-" *angular0 = -cross3(r0, n);\n"
-" *angular1 = cross3(r1, n);\n"
-"}\n"
-"float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 );\n"
-"float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 )\n"
-"{\n"
-" return dot3F4(l0, linVel0) + dot3F4(a0, angVel0) + dot3F4(l1, linVel1) + dot3F4(a1, angVel1);\n"
-"}\n"
-"float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,\n"
-" float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1);\n"
-"float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,\n"
-" float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1)\n"
-"{\n"
-" // linear0,1 are normlized\n"
-" float jmj0 = invMass0;//dot3F4(linear0, linear0)*invMass0;\n"
-" float jmj1 = dot3F4(mtMul3(angular0,*invInertia0), angular0);\n"
-" float jmj2 = invMass1;//dot3F4(linear1, linear1)*invMass1;\n"
-" float jmj3 = dot3F4(mtMul3(angular1,*invInertia1), angular1);\n"
-" return -1.f/(jmj0+jmj1+jmj2+jmj3);\n"
-"}\n"
-"void btPlaneSpace1 (const float4* n, float4* p, float4* q);\n"
-" void btPlaneSpace1 (const float4* n, float4* p, float4* q)\n"
-"{\n"
-" if (fabs(n[0].z) > 0.70710678f) {\n"
-" // choose p in y-z plane\n"
-" float a = n[0].y*n[0].y + n[0].z*n[0].z;\n"
-" float k = 1.f/sqrt(a);\n"
-" p[0].x = 0;\n"
-" p[0].y = -n[0].z*k;\n"
-" p[0].z = n[0].y*k;\n"
-" // set q = n x p\n"
-" q[0].x = a*k;\n"
-" q[0].y = -n[0].x*p[0].z;\n"
-" q[0].z = n[0].x*p[0].y;\n"
-" }\n"
-" else {\n"
-" // choose p in x-y plane\n"
-" float a = n[0].x*n[0].x + n[0].y*n[0].y;\n"
-" float k = 1.f/sqrt(a);\n"
-" p[0].x = -n[0].y*k;\n"
-" p[0].y = n[0].x*k;\n"
-" p[0].z = 0;\n"
-" // set q = n x p\n"
-" q[0].x = -n[0].z*p[0].y;\n"
-" q[0].y = n[0].z*p[0].x;\n"
-" q[0].z = a*k;\n"
-" }\n"
-"}\n"
-"void solveFrictionConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs);\n"
-"void solveFrictionConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs)\n"
-"{\n"
-" float frictionCoeff = ldsCs[0].m_linear.w;\n"
-" int aIdx = ldsCs[0].m_bodyA;\n"
-" int bIdx = ldsCs[0].m_bodyB;\n"
-" float4 posA = gBodies[aIdx].m_pos;\n"
-" float4 linVelA = gBodies[aIdx].m_linVel;\n"
-" float4 angVelA = gBodies[aIdx].m_angVel;\n"
-" float invMassA = gBodies[aIdx].m_invMass;\n"
-" Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;\n"
-" float4 posB = gBodies[bIdx].m_pos;\n"
-" float4 linVelB = gBodies[bIdx].m_linVel;\n"
-" float4 angVelB = gBodies[bIdx].m_angVel;\n"
-" float invMassB = gBodies[bIdx].m_invMass;\n"
-" Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;\n"
-" \n"
-" {\n"
-" float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};\n"
-" float minRambdaDt[4] = {0.f,0.f,0.f,0.f};\n"
-" float sum = 0;\n"
-" for(int j=0; j<4; j++)\n"
-" {\n"
-" sum +=ldsCs[0].m_appliedRambdaDt[j];\n"
-" }\n"
-" frictionCoeff = 0.7f;\n"
-" for(int j=0; j<4; j++)\n"
-" {\n"
-" maxRambdaDt[j] = frictionCoeff*sum;\n"
-" minRambdaDt[j] = -maxRambdaDt[j];\n"
-" }\n"
-" \n"
-"// solveFriction( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,\n"
-"// posB, &linVelB, &angVelB, invMassB, invInertiaB, maxRambdaDt, minRambdaDt );\n"
-" \n"
-" \n"
-" {\n"
-" \n"
-" __global Constraint4* cs = ldsCs;\n"
-" \n"
-" if( cs->m_fJacCoeffInv[0] == 0 && cs->m_fJacCoeffInv[0] == 0 ) return;\n"
-" const float4 center = cs->m_center;\n"
-" \n"
-" float4 n = -cs->m_linear;\n"
-" \n"
-" float4 tangent[2];\n"
-" btPlaneSpace1(&n,&tangent[0],&tangent[1]);\n"
-" float4 angular0, angular1, linear;\n"
-" float4 r0 = center - posA;\n"
-" float4 r1 = center - posB;\n"
-" for(int i=0; i<2; i++)\n"
-" {\n"
-" setLinearAndAngular( tangent[i], r0, r1, &linear, &angular0, &angular1 );\n"
-" float rambdaDt = calcRelVel(linear, -linear, angular0, angular1,\n"
-" linVelA, angVelA, linVelB, angVelB );\n"
-" rambdaDt *= cs->m_fJacCoeffInv[i];\n"
-" \n"
-" {\n"
-" float prevSum = cs->m_fAppliedRambdaDt[i];\n"
-" float updated = prevSum;\n"
-" updated += rambdaDt;\n"
-" updated = max2( updated, minRambdaDt[i] );\n"
-" updated = min2( updated, maxRambdaDt[i] );\n"
-" rambdaDt = updated - prevSum;\n"
-" cs->m_fAppliedRambdaDt[i] = updated;\n"
-" }\n"
-" \n"
-" float4 linImp0 = invMassA*linear*rambdaDt;\n"
-" float4 linImp1 = invMassB*(-linear)*rambdaDt;\n"
-" float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;\n"
-" float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;\n"
-" \n"
-" linVelA += linImp0;\n"
-" angVelA += angImp0;\n"
-" linVelB += linImp1;\n"
-" angVelB += angImp1;\n"
-" }\n"
-" { // angular damping for point constraint\n"
-" float4 ab = normalize3( posB - posA );\n"
-" float4 ac = normalize3( center - posA );\n"
-" if( dot3F4( ab, ac ) > 0.95f || (invMassA == 0.f || invMassB == 0.f))\n"
-" {\n"
-" float angNA = dot3F4( n, angVelA );\n"
-" float angNB = dot3F4( n, angVelB );\n"
-" \n"
-" angVelA -= (angNA*0.1f)*n;\n"
-" angVelB -= (angNB*0.1f)*n;\n"
-" }\n"
-" }\n"
-" }\n"
-" \n"
-" \n"
-" }\n"
-" if (gBodies[aIdx].m_invMass)\n"
-" {\n"
-" gBodies[aIdx].m_linVel = linVelA;\n"
-" gBodies[aIdx].m_angVel = angVelA;\n"
-" } else\n"
-" {\n"
-" gBodies[aIdx].m_linVel = mymake_float4(0,0,0,0);\n"
-" gBodies[aIdx].m_angVel = mymake_float4(0,0,0,0);\n"
-" }\n"
-" if (gBodies[bIdx].m_invMass)\n"
-" {\n"
-" gBodies[bIdx].m_linVel = linVelB;\n"
-" gBodies[bIdx].m_angVel = angVelB;\n"
-" } else\n"
-" {\n"
-" gBodies[bIdx].m_linVel = mymake_float4(0,0,0,0);\n"
-" gBodies[bIdx].m_angVel = mymake_float4(0,0,0,0);\n"
-" }\n"
-" \n"
-"}\n"
-"typedef struct \n"
-"{\n"
-" int m_valInt0;\n"
-" int m_valInt1;\n"
-" int m_valInt2;\n"
-" int m_valInt3;\n"
-" float m_val0;\n"
-" float m_val1;\n"
-" float m_val2;\n"
-" float m_val3;\n"
-"} SolverDebugInfo;\n"
-"__kernel\n"
-"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
-"void BatchSolveKernelFriction(__global Body* gBodies,\n"
-" __global Shape* gShapes,\n"
-" __global Constraint4* gConstraints,\n"
-" __global int* gN,\n"
-" __global int* gOffsets,\n"
-" __global int* batchSizes,\n"
-" int maxBatch1,\n"
-" int cellBatch,\n"
-" int4 nSplit\n"
-" )\n"
-"{\n"
-" //__local int ldsBatchIdx[WG_SIZE+1];\n"
-" __local int ldsCurBatch;\n"
-" __local int ldsNextBatch;\n"
-" __local int ldsStart;\n"
-" int lIdx = GET_LOCAL_IDX;\n"
-" int wgIdx = GET_GROUP_IDX;\n"
-"// int gIdx = GET_GLOBAL_IDX;\n"
-"// debugInfo[gIdx].m_valInt0 = gIdx;\n"
-" //debugInfo[gIdx].m_valInt1 = GET_GROUP_SIZE;\n"
-" int zIdx = (wgIdx/((nSplit.x*nSplit.y)/4))*2+((cellBatch&4)>>2);\n"
-" int remain= (wgIdx%((nSplit.x*nSplit.y)/4));\n"
-" int yIdx = (remain/(nSplit.x/2))*2 + ((cellBatch&2)>>1);\n"
-" int xIdx = (remain%(nSplit.x/2))*2 + (cellBatch&1);\n"
-" int cellIdx = xIdx+yIdx*nSplit.x+zIdx*(nSplit.x*nSplit.y);\n"
-" \n"
-" if( gN[cellIdx] == 0 ) \n"
-" return;\n"
-" int maxBatch = batchSizes[cellIdx];\n"
-" const int start = gOffsets[cellIdx];\n"
-" const int end = start + gN[cellIdx];\n"
-" \n"
-" if( lIdx == 0 )\n"
-" {\n"
-" ldsCurBatch = 0;\n"
-" ldsNextBatch = 0;\n"
-" ldsStart = start;\n"
-" }\n"
-" GROUP_LDS_BARRIER;\n"
-" int idx=ldsStart+lIdx;\n"
-" while (ldsCurBatch < maxBatch)\n"
-" {\n"
-" for(; idx<end; )\n"
-" {\n"
-" if (gConstraints[idx].m_batchIdx == ldsCurBatch)\n"
-" {\n"
-" solveFrictionConstraint( gBodies, gShapes, &gConstraints[idx] );\n"
-" idx+=64;\n"
-" } else\n"
-" {\n"
-" break;\n"
-" }\n"
-" }\n"
-" GROUP_LDS_BARRIER;\n"
-" if( lIdx == 0 )\n"
-" {\n"
-" ldsCurBatch++;\n"
-" }\n"
-" GROUP_LDS_BARRIER;\n"
-" }\n"
-" \n"
-" \n"
-"}\n"
-"__kernel void solveSingleFrictionKernel(__global Body* gBodies,\n"
-" __global Shape* gShapes,\n"
-" __global Constraint4* gConstraints,\n"
-" int cellIdx,\n"
-" int batchOffset,\n"
-" int numConstraintsInBatch\n"
-" )\n"
-"{\n"
-" int index = get_global_id(0);\n"
-" if (index < numConstraintsInBatch)\n"
-" {\n"
-" \n"
-" int idx=batchOffset+index;\n"
-" \n"
-" solveFrictionConstraint( gBodies, gShapes, &gConstraints[idx] );\n"
-" } \n"
-"}\n"
-;
+static const char* solveFrictionCL =
+ "/*\n"
+ "Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
+ "This software is provided 'as-is', without any express or implied warranty.\n"
+ "In no event will the authors be held liable for any damages arising from the use of this software.\n"
+ "Permission is granted to anyone to use this software for any purpose, \n"
+ "including commercial applications, and to alter it and redistribute it freely, \n"
+ "subject to the following restrictions:\n"
+ "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
+ "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+ "3. This notice may not be removed or altered from any source distribution.\n"
+ "*/\n"
+ "//Originally written by Takahiro Harada\n"
+ "//#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
+ "#ifdef cl_ext_atomic_counters_32\n"
+ "#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
+ "#else\n"
+ "#define counter32_t volatile global int*\n"
+ "#endif\n"
+ "typedef unsigned int u32;\n"
+ "typedef unsigned short u16;\n"
+ "typedef unsigned char u8;\n"
+ "#define GET_GROUP_IDX get_group_id(0)\n"
+ "#define GET_LOCAL_IDX get_local_id(0)\n"
+ "#define GET_GLOBAL_IDX get_global_id(0)\n"
+ "#define GET_GROUP_SIZE get_local_size(0)\n"
+ "#define GET_NUM_GROUPS get_num_groups(0)\n"
+ "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+ "#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
+ "#define AtomInc(x) atom_inc(&(x))\n"
+ "#define AtomInc1(x, out) out = atom_inc(&(x))\n"
+ "#define AppendInc(x, out) out = atomic_inc(x)\n"
+ "#define AtomAdd(x, value) atom_add(&(x), value)\n"
+ "#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
+ "#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
+ "#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
+ "#define mymake_float4 (float4)\n"
+ "//#define make_float2 (float2)\n"
+ "//#define make_uint4 (uint4)\n"
+ "//#define make_int4 (int4)\n"
+ "//#define make_uint2 (uint2)\n"
+ "//#define make_int2 (int2)\n"
+ "#define max2 max\n"
+ "#define min2 min\n"
+ "///////////////////////////////////////\n"
+ "// Vector\n"
+ "///////////////////////////////////////\n"
+ "__inline\n"
+ "float4 fastNormalize4(float4 v)\n"
+ "{\n"
+ " return fast_normalize(v);\n"
+ "}\n"
+ "__inline\n"
+ "float4 cross3(float4 a, float4 b)\n"
+ "{\n"
+ " return cross(a,b);\n"
+ "}\n"
+ "__inline\n"
+ "float dot3F4(float4 a, float4 b)\n"
+ "{\n"
+ " float4 a1 = mymake_float4(a.xyz,0.f);\n"
+ " float4 b1 = mymake_float4(b.xyz,0.f);\n"
+ " return dot(a1, b1);\n"
+ "}\n"
+ "__inline\n"
+ "float4 normalize3(const float4 a)\n"
+ "{\n"
+ " float4 n = mymake_float4(a.x, a.y, a.z, 0.f);\n"
+ " return fastNormalize4( n );\n"
+ "// float length = sqrtf(dot3F4(a, a));\n"
+ "// return 1.f/length * a;\n"
+ "}\n"
+ "///////////////////////////////////////\n"
+ "// Matrix3x3\n"
+ "///////////////////////////////////////\n"
+ "typedef struct\n"
+ "{\n"
+ " float4 m_row[3];\n"
+ "}Matrix3x3;\n"
+ "__inline\n"
+ "float4 mtMul1(Matrix3x3 a, float4 b);\n"
+ "__inline\n"
+ "float4 mtMul3(float4 a, Matrix3x3 b);\n"
+ "__inline\n"
+ "float4 mtMul1(Matrix3x3 a, float4 b)\n"
+ "{\n"
+ " float4 ans;\n"
+ " ans.x = dot3F4( a.m_row[0], b );\n"
+ " ans.y = dot3F4( a.m_row[1], b );\n"
+ " ans.z = dot3F4( a.m_row[2], b );\n"
+ " ans.w = 0.f;\n"
+ " return ans;\n"
+ "}\n"
+ "__inline\n"
+ "float4 mtMul3(float4 a, Matrix3x3 b)\n"
+ "{\n"
+ " float4 colx = mymake_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
+ " float4 coly = mymake_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
+ " float4 colz = mymake_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
+ " float4 ans;\n"
+ " ans.x = dot3F4( a, colx );\n"
+ " ans.y = dot3F4( a, coly );\n"
+ " ans.z = dot3F4( a, colz );\n"
+ " return ans;\n"
+ "}\n"
+ "///////////////////////////////////////\n"
+ "// Quaternion\n"
+ "///////////////////////////////////////\n"
+ "typedef float4 Quaternion;\n"
+ "#define WG_SIZE 64\n"
+ "typedef struct\n"
+ "{\n"
+ " float4 m_pos;\n"
+ " Quaternion m_quat;\n"
+ " float4 m_linVel;\n"
+ " float4 m_angVel;\n"
+ " u32 m_shapeIdx;\n"
+ " float m_invMass;\n"
+ " float m_restituitionCoeff;\n"
+ " float m_frictionCoeff;\n"
+ "} Body;\n"
+ "typedef struct\n"
+ "{\n"
+ " Matrix3x3 m_invInertia;\n"
+ " Matrix3x3 m_initInvInertia;\n"
+ "} Shape;\n"
+ "typedef struct\n"
+ "{\n"
+ " float4 m_linear;\n"
+ " float4 m_worldPos[4];\n"
+ " float4 m_center; \n"
+ " float m_jacCoeffInv[4];\n"
+ " float m_b[4];\n"
+ " float m_appliedRambdaDt[4];\n"
+ " float m_fJacCoeffInv[2]; \n"
+ " float m_fAppliedRambdaDt[2]; \n"
+ " u32 m_bodyA;\n"
+ " u32 m_bodyB;\n"
+ " int m_batchIdx;\n"
+ " u32 m_paddings[1];\n"
+ "} Constraint4;\n"
+ "typedef struct\n"
+ "{\n"
+ " int m_nConstraints;\n"
+ " int m_start;\n"
+ " int m_batchIdx;\n"
+ " int m_nSplit;\n"
+ "// int m_paddings[1];\n"
+ "} ConstBuffer;\n"
+ "typedef struct\n"
+ "{\n"
+ " int m_solveFriction;\n"
+ " int m_maxBatch; // long batch really kills the performance\n"
+ " int m_batchIdx;\n"
+ " int m_nSplit;\n"
+ "// int m_paddings[1];\n"
+ "} ConstBufferBatchSolve;\n"
+ "void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1);\n"
+ "void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1)\n"
+ "{\n"
+ " *linear = mymake_float4(-n.xyz,0.f);\n"
+ " *angular0 = -cross3(r0, n);\n"
+ " *angular1 = cross3(r1, n);\n"
+ "}\n"
+ "float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 );\n"
+ "float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 )\n"
+ "{\n"
+ " return dot3F4(l0, linVel0) + dot3F4(a0, angVel0) + dot3F4(l1, linVel1) + dot3F4(a1, angVel1);\n"
+ "}\n"
+ "float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,\n"
+ " float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1);\n"
+ "float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,\n"
+ " float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1)\n"
+ "{\n"
+ " // linear0,1 are normlized\n"
+ " float jmj0 = invMass0;//dot3F4(linear0, linear0)*invMass0;\n"
+ " float jmj1 = dot3F4(mtMul3(angular0,*invInertia0), angular0);\n"
+ " float jmj2 = invMass1;//dot3F4(linear1, linear1)*invMass1;\n"
+ " float jmj3 = dot3F4(mtMul3(angular1,*invInertia1), angular1);\n"
+ " return -1.f/(jmj0+jmj1+jmj2+jmj3);\n"
+ "}\n"
+ "void btPlaneSpace1 (const float4* n, float4* p, float4* q);\n"
+ " void btPlaneSpace1 (const float4* n, float4* p, float4* q)\n"
+ "{\n"
+ " if (fabs(n[0].z) > 0.70710678f) {\n"
+ " // choose p in y-z plane\n"
+ " float a = n[0].y*n[0].y + n[0].z*n[0].z;\n"
+ " float k = 1.f/sqrt(a);\n"
+ " p[0].x = 0;\n"
+ " p[0].y = -n[0].z*k;\n"
+ " p[0].z = n[0].y*k;\n"
+ " // set q = n x p\n"
+ " q[0].x = a*k;\n"
+ " q[0].y = -n[0].x*p[0].z;\n"
+ " q[0].z = n[0].x*p[0].y;\n"
+ " }\n"
+ " else {\n"
+ " // choose p in x-y plane\n"
+ " float a = n[0].x*n[0].x + n[0].y*n[0].y;\n"
+ " float k = 1.f/sqrt(a);\n"
+ " p[0].x = -n[0].y*k;\n"
+ " p[0].y = n[0].x*k;\n"
+ " p[0].z = 0;\n"
+ " // set q = n x p\n"
+ " q[0].x = -n[0].z*p[0].y;\n"
+ " q[0].y = n[0].z*p[0].x;\n"
+ " q[0].z = a*k;\n"
+ " }\n"
+ "}\n"
+ "void solveFrictionConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs);\n"
+ "void solveFrictionConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs)\n"
+ "{\n"
+ " float frictionCoeff = ldsCs[0].m_linear.w;\n"
+ " int aIdx = ldsCs[0].m_bodyA;\n"
+ " int bIdx = ldsCs[0].m_bodyB;\n"
+ " float4 posA = gBodies[aIdx].m_pos;\n"
+ " float4 linVelA = gBodies[aIdx].m_linVel;\n"
+ " float4 angVelA = gBodies[aIdx].m_angVel;\n"
+ " float invMassA = gBodies[aIdx].m_invMass;\n"
+ " Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;\n"
+ " float4 posB = gBodies[bIdx].m_pos;\n"
+ " float4 linVelB = gBodies[bIdx].m_linVel;\n"
+ " float4 angVelB = gBodies[bIdx].m_angVel;\n"
+ " float invMassB = gBodies[bIdx].m_invMass;\n"
+ " Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;\n"
+ " \n"
+ " {\n"
+ " float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};\n"
+ " float minRambdaDt[4] = {0.f,0.f,0.f,0.f};\n"
+ " float sum = 0;\n"
+ " for(int j=0; j<4; j++)\n"
+ " {\n"
+ " sum +=ldsCs[0].m_appliedRambdaDt[j];\n"
+ " }\n"
+ " frictionCoeff = 0.7f;\n"
+ " for(int j=0; j<4; j++)\n"
+ " {\n"
+ " maxRambdaDt[j] = frictionCoeff*sum;\n"
+ " minRambdaDt[j] = -maxRambdaDt[j];\n"
+ " }\n"
+ " \n"
+ "// solveFriction( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,\n"
+ "// posB, &linVelB, &angVelB, invMassB, invInertiaB, maxRambdaDt, minRambdaDt );\n"
+ " \n"
+ " \n"
+ " {\n"
+ " \n"
+ " __global Constraint4* cs = ldsCs;\n"
+ " \n"
+ " if( cs->m_fJacCoeffInv[0] == 0 && cs->m_fJacCoeffInv[0] == 0 ) return;\n"
+ " const float4 center = cs->m_center;\n"
+ " \n"
+ " float4 n = -cs->m_linear;\n"
+ " \n"
+ " float4 tangent[2];\n"
+ " btPlaneSpace1(&n,&tangent[0],&tangent[1]);\n"
+ " float4 angular0, angular1, linear;\n"
+ " float4 r0 = center - posA;\n"
+ " float4 r1 = center - posB;\n"
+ " for(int i=0; i<2; i++)\n"
+ " {\n"
+ " setLinearAndAngular( tangent[i], r0, r1, &linear, &angular0, &angular1 );\n"
+ " float rambdaDt = calcRelVel(linear, -linear, angular0, angular1,\n"
+ " linVelA, angVelA, linVelB, angVelB );\n"
+ " rambdaDt *= cs->m_fJacCoeffInv[i];\n"
+ " \n"
+ " {\n"
+ " float prevSum = cs->m_fAppliedRambdaDt[i];\n"
+ " float updated = prevSum;\n"
+ " updated += rambdaDt;\n"
+ " updated = max2( updated, minRambdaDt[i] );\n"
+ " updated = min2( updated, maxRambdaDt[i] );\n"
+ " rambdaDt = updated - prevSum;\n"
+ " cs->m_fAppliedRambdaDt[i] = updated;\n"
+ " }\n"
+ " \n"
+ " float4 linImp0 = invMassA*linear*rambdaDt;\n"
+ " float4 linImp1 = invMassB*(-linear)*rambdaDt;\n"
+ " float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;\n"
+ " float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;\n"
+ " \n"
+ " linVelA += linImp0;\n"
+ " angVelA += angImp0;\n"
+ " linVelB += linImp1;\n"
+ " angVelB += angImp1;\n"
+ " }\n"
+ " { // angular damping for point constraint\n"
+ " float4 ab = normalize3( posB - posA );\n"
+ " float4 ac = normalize3( center - posA );\n"
+ " if( dot3F4( ab, ac ) > 0.95f || (invMassA == 0.f || invMassB == 0.f))\n"
+ " {\n"
+ " float angNA = dot3F4( n, angVelA );\n"
+ " float angNB = dot3F4( n, angVelB );\n"
+ " \n"
+ " angVelA -= (angNA*0.1f)*n;\n"
+ " angVelB -= (angNB*0.1f)*n;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " \n"
+ " \n"
+ " }\n"
+ " if (gBodies[aIdx].m_invMass)\n"
+ " {\n"
+ " gBodies[aIdx].m_linVel = linVelA;\n"
+ " gBodies[aIdx].m_angVel = angVelA;\n"
+ " } else\n"
+ " {\n"
+ " gBodies[aIdx].m_linVel = mymake_float4(0,0,0,0);\n"
+ " gBodies[aIdx].m_angVel = mymake_float4(0,0,0,0);\n"
+ " }\n"
+ " if (gBodies[bIdx].m_invMass)\n"
+ " {\n"
+ " gBodies[bIdx].m_linVel = linVelB;\n"
+ " gBodies[bIdx].m_angVel = angVelB;\n"
+ " } else\n"
+ " {\n"
+ " gBodies[bIdx].m_linVel = mymake_float4(0,0,0,0);\n"
+ " gBodies[bIdx].m_angVel = mymake_float4(0,0,0,0);\n"
+ " }\n"
+ " \n"
+ "}\n"
+ "typedef struct \n"
+ "{\n"
+ " int m_valInt0;\n"
+ " int m_valInt1;\n"
+ " int m_valInt2;\n"
+ " int m_valInt3;\n"
+ " float m_val0;\n"
+ " float m_val1;\n"
+ " float m_val2;\n"
+ " float m_val3;\n"
+ "} SolverDebugInfo;\n"
+ "__kernel\n"
+ "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+ "void BatchSolveKernelFriction(__global Body* gBodies,\n"
+ " __global Shape* gShapes,\n"
+ " __global Constraint4* gConstraints,\n"
+ " __global int* gN,\n"
+ " __global int* gOffsets,\n"
+ " __global int* batchSizes,\n"
+ " int maxBatch1,\n"
+ " int cellBatch,\n"
+ " int4 nSplit\n"
+ " )\n"
+ "{\n"
+ " //__local int ldsBatchIdx[WG_SIZE+1];\n"
+ " __local int ldsCurBatch;\n"
+ " __local int ldsNextBatch;\n"
+ " __local int ldsStart;\n"
+ " int lIdx = GET_LOCAL_IDX;\n"
+ " int wgIdx = GET_GROUP_IDX;\n"
+ "// int gIdx = GET_GLOBAL_IDX;\n"
+ "// debugInfo[gIdx].m_valInt0 = gIdx;\n"
+ " //debugInfo[gIdx].m_valInt1 = GET_GROUP_SIZE;\n"
+ " int zIdx = (wgIdx/((nSplit.x*nSplit.y)/4))*2+((cellBatch&4)>>2);\n"
+ " int remain= (wgIdx%((nSplit.x*nSplit.y)/4));\n"
+ " int yIdx = (remain/(nSplit.x/2))*2 + ((cellBatch&2)>>1);\n"
+ " int xIdx = (remain%(nSplit.x/2))*2 + (cellBatch&1);\n"
+ " int cellIdx = xIdx+yIdx*nSplit.x+zIdx*(nSplit.x*nSplit.y);\n"
+ " \n"
+ " if( gN[cellIdx] == 0 ) \n"
+ " return;\n"
+ " int maxBatch = batchSizes[cellIdx];\n"
+ " const int start = gOffsets[cellIdx];\n"
+ " const int end = start + gN[cellIdx];\n"
+ " \n"
+ " if( lIdx == 0 )\n"
+ " {\n"
+ " ldsCurBatch = 0;\n"
+ " ldsNextBatch = 0;\n"
+ " ldsStart = start;\n"
+ " }\n"
+ " GROUP_LDS_BARRIER;\n"
+ " int idx=ldsStart+lIdx;\n"
+ " while (ldsCurBatch < maxBatch)\n"
+ " {\n"
+ " for(; idx<end; )\n"
+ " {\n"
+ " if (gConstraints[idx].m_batchIdx == ldsCurBatch)\n"
+ " {\n"
+ " solveFrictionConstraint( gBodies, gShapes, &gConstraints[idx] );\n"
+ " idx+=64;\n"
+ " } else\n"
+ " {\n"
+ " break;\n"
+ " }\n"
+ " }\n"
+ " GROUP_LDS_BARRIER;\n"
+ " if( lIdx == 0 )\n"
+ " {\n"
+ " ldsCurBatch++;\n"
+ " }\n"
+ " GROUP_LDS_BARRIER;\n"
+ " }\n"
+ " \n"
+ " \n"
+ "}\n"
+ "__kernel void solveSingleFrictionKernel(__global Body* gBodies,\n"
+ " __global Shape* gShapes,\n"
+ " __global Constraint4* gConstraints,\n"
+ " int cellIdx,\n"
+ " int batchOffset,\n"
+ " int numConstraintsInBatch\n"
+ " )\n"
+ "{\n"
+ " int index = get_global_id(0);\n"
+ " if (index < numConstraintsInBatch)\n"
+ " {\n"
+ " \n"
+ " int idx=batchOffset+index;\n"
+ " \n"
+ " solveFrictionConstraint( gBodies, gShapes, &gConstraints[idx] );\n"
+ " } \n"
+ "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solverSetup.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solverSetup.h
index eb1834ee00..d53db03181 100644
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solverSetup.h
+++ b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solverSetup.h
@@ -1,703 +1,702 @@
//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* solverSetupCL= \
-"/*\n"
-"Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
-"This software is provided 'as-is', without any express or implied warranty.\n"
-"In no event will the authors be held liable for any damages arising from the use of this software.\n"
-"Permission is granted to anyone to use this software for any purpose, \n"
-"including commercial applications, and to alter it and redistribute it freely, \n"
-"subject to the following restrictions:\n"
-"1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
-"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
-"3. This notice may not be removed or altered from any source distribution.\n"
-"*/\n"
-"//Originally written by Takahiro Harada\n"
-"#ifndef B3_CONTACT4DATA_H\n"
-"#define B3_CONTACT4DATA_H\n"
-"#ifndef B3_FLOAT4_H\n"
-"#define B3_FLOAT4_H\n"
-"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
-"#define B3_PLATFORM_DEFINITIONS_H\n"
-"struct MyTest\n"
-"{\n"
-" int bla;\n"
-"};\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
-"#define B3_LARGE_FLOAT 1e18f\n"
-"#define B3_INFINITY 1e18f\n"
-"#define b3Assert(a)\n"
-"#define b3ConstArray(a) __global const a*\n"
-"#define b3AtomicInc atomic_inc\n"
-"#define b3AtomicAdd atomic_add\n"
-"#define b3Fabs fabs\n"
-"#define b3Sqrt native_sqrt\n"
-"#define b3Sin native_sin\n"
-"#define b3Cos native_cos\n"
-"#define B3_STATIC\n"
-"#endif\n"
-"#endif\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-" typedef float4 b3Float4;\n"
-" #define b3Float4ConstArg const b3Float4\n"
-" #define b3MakeFloat4 (float4)\n"
-" float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
-" {\n"
-" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
-" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
-" return dot(a1, b1);\n"
-" }\n"
-" b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
-" {\n"
-" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
-" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
-" return cross(a1, b1);\n"
-" }\n"
-" #define b3MinFloat4 min\n"
-" #define b3MaxFloat4 max\n"
-" #define b3Normalized(a) normalize(a)\n"
-"#endif \n"
-" \n"
-"inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
-"{\n"
-" if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
-" return false;\n"
-" return true;\n"
-"}\n"
-"inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
-"{\n"
-" float maxDot = -B3_INFINITY;\n"
-" int i = 0;\n"
-" int ptIndex = -1;\n"
-" for( i = 0; i < vecLen; i++ )\n"
-" {\n"
-" float dot = b3Dot3F4(vecArray[i],vec);\n"
-" \n"
-" if( dot > maxDot )\n"
-" {\n"
-" maxDot = dot;\n"
-" ptIndex = i;\n"
-" }\n"
-" }\n"
-" b3Assert(ptIndex>=0);\n"
-" if (ptIndex<0)\n"
-" {\n"
-" ptIndex = 0;\n"
-" }\n"
-" *dotOut = maxDot;\n"
-" return ptIndex;\n"
-"}\n"
-"#endif //B3_FLOAT4_H\n"
-"typedef struct b3Contact4Data b3Contact4Data_t;\n"
-"struct b3Contact4Data\n"
-"{\n"
-" b3Float4 m_worldPosB[4];\n"
-"// b3Float4 m_localPosA[4];\n"
-"// b3Float4 m_localPosB[4];\n"
-" b3Float4 m_worldNormalOnB; // w: m_nPoints\n"
-" unsigned short m_restituitionCoeffCmp;\n"
-" unsigned short m_frictionCoeffCmp;\n"
-" int m_batchIdx;\n"
-" int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
-" int m_bodyBPtrAndSignBit;\n"
-" int m_childIndexA;\n"
-" int m_childIndexB;\n"
-" int m_unused1;\n"
-" int m_unused2;\n"
-"};\n"
-"inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
-"{\n"
-" return (int)contact->m_worldNormalOnB.w;\n"
-"};\n"
-"inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
-"{\n"
-" contact->m_worldNormalOnB.w = (float)numPoints;\n"
-"};\n"
-"#endif //B3_CONTACT4DATA_H\n"
-"#ifndef B3_CONTACT_CONSTRAINT5_H\n"
-"#define B3_CONTACT_CONSTRAINT5_H\n"
-"#ifndef B3_FLOAT4_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#endif \n"
-"#endif //B3_FLOAT4_H\n"
-"typedef struct b3ContactConstraint4 b3ContactConstraint4_t;\n"
-"struct b3ContactConstraint4\n"
-"{\n"
-" b3Float4 m_linear;//normal?\n"
-" b3Float4 m_worldPos[4];\n"
-" b3Float4 m_center; // friction\n"
-" float m_jacCoeffInv[4];\n"
-" float m_b[4];\n"
-" float m_appliedRambdaDt[4];\n"
-" float m_fJacCoeffInv[2]; // friction\n"
-" float m_fAppliedRambdaDt[2]; // friction\n"
-" unsigned int m_bodyA;\n"
-" unsigned int m_bodyB;\n"
-" int m_batchIdx;\n"
-" unsigned int m_paddings;\n"
-"};\n"
-"//inline void setFrictionCoeff(float value) { m_linear[3] = value; }\n"
-"inline float b3GetFrictionCoeff(b3ContactConstraint4_t* constraint) \n"
-"{\n"
-" return constraint->m_linear.w; \n"
-"}\n"
-"#endif //B3_CONTACT_CONSTRAINT5_H\n"
-"#ifndef B3_RIGIDBODY_DATA_H\n"
-"#define B3_RIGIDBODY_DATA_H\n"
-"#ifndef B3_FLOAT4_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#endif \n"
-"#endif //B3_FLOAT4_H\n"
-"#ifndef B3_QUAT_H\n"
-"#define B3_QUAT_H\n"
-"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#endif\n"
-"#endif\n"
-"#ifndef B3_FLOAT4_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#endif \n"
-"#endif //B3_FLOAT4_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-" typedef float4 b3Quat;\n"
-" #define b3QuatConstArg const b3Quat\n"
-" \n"
-" \n"
-"inline float4 b3FastNormalize4(float4 v)\n"
-"{\n"
-" v = (float4)(v.xyz,0.f);\n"
-" return fast_normalize(v);\n"
-"}\n"
-" \n"
-"inline b3Quat b3QuatMul(b3Quat a, b3Quat b);\n"
-"inline b3Quat b3QuatNormalized(b3QuatConstArg in);\n"
-"inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec);\n"
-"inline b3Quat b3QuatInvert(b3QuatConstArg q);\n"
-"inline b3Quat b3QuatInverse(b3QuatConstArg q);\n"
-"inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b)\n"
-"{\n"
-" b3Quat ans;\n"
-" ans = b3Cross3( a, b );\n"
-" ans += a.w*b+b.w*a;\n"
-"// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
-" ans.w = a.w*b.w - b3Dot3F4(a, b);\n"
-" return ans;\n"
-"}\n"
-"inline b3Quat b3QuatNormalized(b3QuatConstArg in)\n"
-"{\n"
-" b3Quat q;\n"
-" q=in;\n"
-" //return b3FastNormalize4(in);\n"
-" float len = native_sqrt(dot(q, q));\n"
-" if(len > 0.f)\n"
-" {\n"
-" q *= 1.f / len;\n"
-" }\n"
-" else\n"
-" {\n"
-" q.x = q.y = q.z = 0.f;\n"
-" q.w = 1.f;\n"
-" }\n"
-" return q;\n"
-"}\n"
-"inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
-"{\n"
-" b3Quat qInv = b3QuatInvert( q );\n"
-" float4 vcpy = vec;\n"
-" vcpy.w = 0.f;\n"
-" float4 out = b3QuatMul(b3QuatMul(q,vcpy),qInv);\n"
-" return out;\n"
-"}\n"
-"inline b3Quat b3QuatInverse(b3QuatConstArg q)\n"
-"{\n"
-" return (b3Quat)(-q.xyz, q.w);\n"
-"}\n"
-"inline b3Quat b3QuatInvert(b3QuatConstArg q)\n"
-"{\n"
-" return (b3Quat)(-q.xyz, q.w);\n"
-"}\n"
-"inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
-"{\n"
-" return b3QuatRotate( b3QuatInvert( q ), vec );\n"
-"}\n"
-"inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation)\n"
-"{\n"
-" return b3QuatRotate( orientation, point ) + (translation);\n"
-"}\n"
-" \n"
-"#endif \n"
-"#endif //B3_QUAT_H\n"
-"#ifndef B3_MAT3x3_H\n"
-"#define B3_MAT3x3_H\n"
-"#ifndef B3_QUAT_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#endif \n"
-"#endif //B3_QUAT_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"typedef struct\n"
-"{\n"
-" b3Float4 m_row[3];\n"
-"}b3Mat3x3;\n"
-"#define b3Mat3x3ConstArg const b3Mat3x3\n"
-"#define b3GetRow(m,row) (m.m_row[row])\n"
-"inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat)\n"
-"{\n"
-" b3Float4 quat2 = (b3Float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);\n"
-" b3Mat3x3 out;\n"
-" out.m_row[0].x=1-2*quat2.y-2*quat2.z;\n"
-" out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;\n"
-" out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;\n"
-" out.m_row[0].w = 0.f;\n"
-" out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;\n"
-" out.m_row[1].y=1-2*quat2.x-2*quat2.z;\n"
-" out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;\n"
-" out.m_row[1].w = 0.f;\n"
-" out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;\n"
-" out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;\n"
-" out.m_row[2].z=1-2*quat2.x-2*quat2.y;\n"
-" out.m_row[2].w = 0.f;\n"
-" return out;\n"
-"}\n"
-"inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn)\n"
-"{\n"
-" b3Mat3x3 out;\n"
-" out.m_row[0] = fabs(matIn.m_row[0]);\n"
-" out.m_row[1] = fabs(matIn.m_row[1]);\n"
-" out.m_row[2] = fabs(matIn.m_row[2]);\n"
-" return out;\n"
-"}\n"
-"__inline\n"
-"b3Mat3x3 mtZero();\n"
-"__inline\n"
-"b3Mat3x3 mtIdentity();\n"
-"__inline\n"
-"b3Mat3x3 mtTranspose(b3Mat3x3 m);\n"
-"__inline\n"
-"b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);\n"
-"__inline\n"
-"b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);\n"
-"__inline\n"
-"b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);\n"
-"__inline\n"
-"b3Mat3x3 mtZero()\n"
-"{\n"
-" b3Mat3x3 m;\n"
-" m.m_row[0] = (b3Float4)(0.f);\n"
-" m.m_row[1] = (b3Float4)(0.f);\n"
-" m.m_row[2] = (b3Float4)(0.f);\n"
-" return m;\n"
-"}\n"
-"__inline\n"
-"b3Mat3x3 mtIdentity()\n"
-"{\n"
-" b3Mat3x3 m;\n"
-" m.m_row[0] = (b3Float4)(1,0,0,0);\n"
-" m.m_row[1] = (b3Float4)(0,1,0,0);\n"
-" m.m_row[2] = (b3Float4)(0,0,1,0);\n"
-" return m;\n"
-"}\n"
-"__inline\n"
-"b3Mat3x3 mtTranspose(b3Mat3x3 m)\n"
-"{\n"
-" b3Mat3x3 out;\n"
-" out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
-" out.m_row[1] = (b3Float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
-" out.m_row[2] = (b3Float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
-" return out;\n"
-"}\n"
-"__inline\n"
-"b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)\n"
-"{\n"
-" b3Mat3x3 transB;\n"
-" transB = mtTranspose( b );\n"
-" b3Mat3x3 ans;\n"
-" // why this doesn't run when 0ing in the for{}\n"
-" a.m_row[0].w = 0.f;\n"
-" a.m_row[1].w = 0.f;\n"
-" a.m_row[2].w = 0.f;\n"
-" for(int i=0; i<3; i++)\n"
-" {\n"
-"// a.m_row[i].w = 0.f;\n"
-" ans.m_row[i].x = b3Dot3F4(a.m_row[i],transB.m_row[0]);\n"
-" ans.m_row[i].y = b3Dot3F4(a.m_row[i],transB.m_row[1]);\n"
-" ans.m_row[i].z = b3Dot3F4(a.m_row[i],transB.m_row[2]);\n"
-" ans.m_row[i].w = 0.f;\n"
-" }\n"
-" return ans;\n"
-"}\n"
-"__inline\n"
-"b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)\n"
-"{\n"
-" b3Float4 ans;\n"
-" ans.x = b3Dot3F4( a.m_row[0], b );\n"
-" ans.y = b3Dot3F4( a.m_row[1], b );\n"
-" ans.z = b3Dot3F4( a.m_row[2], b );\n"
-" ans.w = 0.f;\n"
-" return ans;\n"
-"}\n"
-"__inline\n"
-"b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)\n"
-"{\n"
-" b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
-" b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
-" b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
-" b3Float4 ans;\n"
-" ans.x = b3Dot3F4( a, colx );\n"
-" ans.y = b3Dot3F4( a, coly );\n"
-" ans.z = b3Dot3F4( a, colz );\n"
-" return ans;\n"
-"}\n"
-"#endif\n"
-"#endif //B3_MAT3x3_H\n"
-"typedef struct b3RigidBodyData b3RigidBodyData_t;\n"
-"struct b3RigidBodyData\n"
-"{\n"
-" b3Float4 m_pos;\n"
-" b3Quat m_quat;\n"
-" b3Float4 m_linVel;\n"
-" b3Float4 m_angVel;\n"
-" int m_collidableIdx;\n"
-" float m_invMass;\n"
-" float m_restituitionCoeff;\n"
-" float m_frictionCoeff;\n"
-"};\n"
-"typedef struct b3InertiaData b3InertiaData_t;\n"
-"struct b3InertiaData\n"
-"{\n"
-" b3Mat3x3 m_invInertiaWorld;\n"
-" b3Mat3x3 m_initInvInertia;\n"
-"};\n"
-"#endif //B3_RIGIDBODY_DATA_H\n"
-" \n"
-"void b3PlaneSpace1 (b3Float4ConstArg n, b3Float4* p, b3Float4* q);\n"
-" void b3PlaneSpace1 (b3Float4ConstArg n, b3Float4* p, b3Float4* q)\n"
-"{\n"
-" if (b3Fabs(n.z) > 0.70710678f) {\n"
-" // choose p in y-z plane\n"
-" float a = n.y*n.y + n.z*n.z;\n"
-" float k = 1.f/sqrt(a);\n"
-" p[0].x = 0;\n"
-" p[0].y = -n.z*k;\n"
-" p[0].z = n.y*k;\n"
-" // set q = n x p\n"
-" q[0].x = a*k;\n"
-" q[0].y = -n.x*p[0].z;\n"
-" q[0].z = n.x*p[0].y;\n"
-" }\n"
-" else {\n"
-" // choose p in x-y plane\n"
-" float a = n.x*n.x + n.y*n.y;\n"
-" float k = 1.f/sqrt(a);\n"
-" p[0].x = -n.y*k;\n"
-" p[0].y = n.x*k;\n"
-" p[0].z = 0;\n"
-" // set q = n x p\n"
-" q[0].x = -n.z*p[0].y;\n"
-" q[0].y = n.z*p[0].x;\n"
-" q[0].z = a*k;\n"
-" }\n"
-"}\n"
-" \n"
-"void setLinearAndAngular( b3Float4ConstArg n, b3Float4ConstArg r0, b3Float4ConstArg r1, b3Float4* linear, b3Float4* angular0, b3Float4* angular1)\n"
-"{\n"
-" *linear = b3MakeFloat4(n.x,n.y,n.z,0.f);\n"
-" *angular0 = b3Cross3(r0, n);\n"
-" *angular1 = -b3Cross3(r1, n);\n"
-"}\n"
-"float calcRelVel( b3Float4ConstArg l0, b3Float4ConstArg l1, b3Float4ConstArg a0, b3Float4ConstArg a1, b3Float4ConstArg linVel0,\n"
-" b3Float4ConstArg angVel0, b3Float4ConstArg linVel1, b3Float4ConstArg angVel1 )\n"
-"{\n"
-" return b3Dot3F4(l0, linVel0) + b3Dot3F4(a0, angVel0) + b3Dot3F4(l1, linVel1) + b3Dot3F4(a1, angVel1);\n"
-"}\n"
-"float calcJacCoeff(b3Float4ConstArg linear0, b3Float4ConstArg linear1, b3Float4ConstArg angular0, b3Float4ConstArg angular1,\n"
-" float invMass0, const b3Mat3x3* invInertia0, float invMass1, const b3Mat3x3* invInertia1)\n"
-"{\n"
-" // linear0,1 are normlized\n"
-" float jmj0 = invMass0;//b3Dot3F4(linear0, linear0)*invMass0;\n"
-" float jmj1 = b3Dot3F4(mtMul3(angular0,*invInertia0), angular0);\n"
-" float jmj2 = invMass1;//b3Dot3F4(linear1, linear1)*invMass1;\n"
-" float jmj3 = b3Dot3F4(mtMul3(angular1,*invInertia1), angular1);\n"
-" return -1.f/(jmj0+jmj1+jmj2+jmj3);\n"
-"}\n"
-"void setConstraint4( b3Float4ConstArg posA, b3Float4ConstArg linVelA, b3Float4ConstArg angVelA, float invMassA, b3Mat3x3ConstArg invInertiaA,\n"
-" b3Float4ConstArg posB, b3Float4ConstArg linVelB, b3Float4ConstArg angVelB, float invMassB, b3Mat3x3ConstArg invInertiaB, \n"
-" __global struct b3Contact4Data* src, float dt, float positionDrift, float positionConstraintCoeff,\n"
-" b3ContactConstraint4_t* dstC )\n"
-"{\n"
-" dstC->m_bodyA = abs(src->m_bodyAPtrAndSignBit);\n"
-" dstC->m_bodyB = abs(src->m_bodyBPtrAndSignBit);\n"
-" float dtInv = 1.f/dt;\n"
-" for(int ic=0; ic<4; ic++)\n"
-" {\n"
-" dstC->m_appliedRambdaDt[ic] = 0.f;\n"
-" }\n"
-" dstC->m_fJacCoeffInv[0] = dstC->m_fJacCoeffInv[1] = 0.f;\n"
-" dstC->m_linear = src->m_worldNormalOnB;\n"
-" dstC->m_linear.w = 0.7f ;//src->getFrictionCoeff() );\n"
-" for(int ic=0; ic<4; ic++)\n"
-" {\n"
-" b3Float4 r0 = src->m_worldPosB[ic] - posA;\n"
-" b3Float4 r1 = src->m_worldPosB[ic] - posB;\n"
-" if( ic >= src->m_worldNormalOnB.w )//npoints\n"
-" {\n"
-" dstC->m_jacCoeffInv[ic] = 0.f;\n"
-" continue;\n"
-" }\n"
-" float relVelN;\n"
-" {\n"
-" b3Float4 linear, angular0, angular1;\n"
-" setLinearAndAngular(src->m_worldNormalOnB, r0, r1, &linear, &angular0, &angular1);\n"
-" dstC->m_jacCoeffInv[ic] = calcJacCoeff(linear, -linear, angular0, angular1,\n"
-" invMassA, &invInertiaA, invMassB, &invInertiaB );\n"
-" relVelN = calcRelVel(linear, -linear, angular0, angular1,\n"
-" linVelA, angVelA, linVelB, angVelB);\n"
-" float e = 0.f;//src->getRestituitionCoeff();\n"
-" if( relVelN*relVelN < 0.004f ) e = 0.f;\n"
-" dstC->m_b[ic] = e*relVelN;\n"
-" //float penetration = src->m_worldPosB[ic].w;\n"
-" dstC->m_b[ic] += (src->m_worldPosB[ic].w + positionDrift)*positionConstraintCoeff*dtInv;\n"
-" dstC->m_appliedRambdaDt[ic] = 0.f;\n"
-" }\n"
-" }\n"
-" if( src->m_worldNormalOnB.w > 0 )//npoints\n"
-" { // prepare friction\n"
-" b3Float4 center = b3MakeFloat4(0.f,0.f,0.f,0.f);\n"
-" for(int i=0; i<src->m_worldNormalOnB.w; i++) \n"
-" center += src->m_worldPosB[i];\n"
-" center /= (float)src->m_worldNormalOnB.w;\n"
-" b3Float4 tangent[2];\n"
-" b3PlaneSpace1(src->m_worldNormalOnB,&tangent[0],&tangent[1]);\n"
-" \n"
-" b3Float4 r[2];\n"
-" r[0] = center - posA;\n"
-" r[1] = center - posB;\n"
-" for(int i=0; i<2; i++)\n"
-" {\n"
-" b3Float4 linear, angular0, angular1;\n"
-" setLinearAndAngular(tangent[i], r[0], r[1], &linear, &angular0, &angular1);\n"
-" dstC->m_fJacCoeffInv[i] = calcJacCoeff(linear, -linear, angular0, angular1,\n"
-" invMassA, &invInertiaA, invMassB, &invInertiaB );\n"
-" dstC->m_fAppliedRambdaDt[i] = 0.f;\n"
-" }\n"
-" dstC->m_center = center;\n"
-" }\n"
-" for(int i=0; i<4; i++)\n"
-" {\n"
-" if( i<src->m_worldNormalOnB.w )\n"
-" {\n"
-" dstC->m_worldPos[i] = src->m_worldPosB[i];\n"
-" }\n"
-" else\n"
-" {\n"
-" dstC->m_worldPos[i] = b3MakeFloat4(0.f,0.f,0.f,0.f);\n"
-" }\n"
-" }\n"
-"}\n"
-"#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
-"#ifdef cl_ext_atomic_counters_32\n"
-"#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
-"#else\n"
-"#define counter32_t volatile global int*\n"
-"#endif\n"
-"typedef unsigned int u32;\n"
-"typedef unsigned short u16;\n"
-"typedef unsigned char u8;\n"
-"#define GET_GROUP_IDX get_group_id(0)\n"
-"#define GET_LOCAL_IDX get_local_id(0)\n"
-"#define GET_GLOBAL_IDX get_global_id(0)\n"
-"#define GET_GROUP_SIZE get_local_size(0)\n"
-"#define GET_NUM_GROUPS get_num_groups(0)\n"
-"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
-"#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
-"#define AtomInc(x) atom_inc(&(x))\n"
-"#define AtomInc1(x, out) out = atom_inc(&(x))\n"
-"#define AppendInc(x, out) out = atomic_inc(x)\n"
-"#define AtomAdd(x, value) atom_add(&(x), value)\n"
-"#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
-"#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
-"#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
-"#define make_float4 (float4)\n"
-"#define make_float2 (float2)\n"
-"#define make_uint4 (uint4)\n"
-"#define make_int4 (int4)\n"
-"#define make_uint2 (uint2)\n"
-"#define make_int2 (int2)\n"
-"#define max2 max\n"
-"#define min2 min\n"
-"///////////////////////////////////////\n"
-"// Vector\n"
-"///////////////////////////////////////\n"
-"__inline\n"
-"float fastDiv(float numerator, float denominator)\n"
-"{\n"
-" return native_divide(numerator, denominator); \n"
-"// return numerator/denominator; \n"
-"}\n"
-"__inline\n"
-"float4 fastDiv4(float4 numerator, float4 denominator)\n"
-"{\n"
-" return native_divide(numerator, denominator); \n"
-"}\n"
-"__inline\n"
-"float fastSqrtf(float f2)\n"
-"{\n"
-" return native_sqrt(f2);\n"
-"// return sqrt(f2);\n"
-"}\n"
-"__inline\n"
-"float fastRSqrt(float f2)\n"
-"{\n"
-" return native_rsqrt(f2);\n"
-"}\n"
-"__inline\n"
-"float fastLength4(float4 v)\n"
-"{\n"
-" return fast_length(v);\n"
-"}\n"
-"__inline\n"
-"float4 fastNormalize4(float4 v)\n"
-"{\n"
-" return fast_normalize(v);\n"
-"}\n"
-"__inline\n"
-"float sqrtf(float a)\n"
-"{\n"
-"// return sqrt(a);\n"
-" return native_sqrt(a);\n"
-"}\n"
-"__inline\n"
-"float4 cross3(float4 a, float4 b)\n"
-"{\n"
-" return cross(a,b);\n"
-"}\n"
-"__inline\n"
-"float dot3F4(float4 a, float4 b)\n"
-"{\n"
-" float4 a1 = make_float4(a.xyz,0.f);\n"
-" float4 b1 = make_float4(b.xyz,0.f);\n"
-" return dot(a1, b1);\n"
-"}\n"
-"__inline\n"
-"float length3(const float4 a)\n"
-"{\n"
-" return sqrtf(dot3F4(a,a));\n"
-"}\n"
-"__inline\n"
-"float dot4(const float4 a, const float4 b)\n"
-"{\n"
-" return dot( a, b );\n"
-"}\n"
-"// for height\n"
-"__inline\n"
-"float dot3w1(const float4 point, const float4 eqn)\n"
-"{\n"
-" return dot3F4(point,eqn) + eqn.w;\n"
-"}\n"
-"__inline\n"
-"float4 normalize3(const float4 a)\n"
-"{\n"
-" float4 n = make_float4(a.x, a.y, a.z, 0.f);\n"
-" return fastNormalize4( n );\n"
-"// float length = sqrtf(dot3F4(a, a));\n"
-"// return 1.f/length * a;\n"
-"}\n"
-"__inline\n"
-"float4 normalize4(const float4 a)\n"
-"{\n"
-" float length = sqrtf(dot4(a, a));\n"
-" return 1.f/length * a;\n"
-"}\n"
-"__inline\n"
-"float4 createEquation(const float4 a, const float4 b, const float4 c)\n"
-"{\n"
-" float4 eqn;\n"
-" float4 ab = b-a;\n"
-" float4 ac = c-a;\n"
-" eqn = normalize3( cross3(ab, ac) );\n"
-" eqn.w = -dot3F4(eqn,a);\n"
-" return eqn;\n"
-"}\n"
-"#define WG_SIZE 64\n"
-"typedef struct\n"
-"{\n"
-" int m_nConstraints;\n"
-" int m_start;\n"
-" int m_batchIdx;\n"
-" int m_nSplit;\n"
-"// int m_paddings[1];\n"
-"} ConstBuffer;\n"
-"typedef struct\n"
-"{\n"
-" int m_solveFriction;\n"
-" int m_maxBatch; // long batch really kills the performance\n"
-" int m_batchIdx;\n"
-" int m_nSplit;\n"
-"// int m_paddings[1];\n"
-"} ConstBufferBatchSolve;\n"
-" \n"
-"typedef struct \n"
-"{\n"
-" int m_valInt0;\n"
-" int m_valInt1;\n"
-" int m_valInt2;\n"
-" int m_valInt3;\n"
-" float m_val0;\n"
-" float m_val1;\n"
-" float m_val2;\n"
-" float m_val3;\n"
-"} SolverDebugInfo;\n"
-"typedef struct\n"
-"{\n"
-" int m_nContacts;\n"
-" float m_dt;\n"
-" float m_positionDrift;\n"
-" float m_positionConstraintCoeff;\n"
-"} ConstBufferCTC;\n"
-"__kernel\n"
-"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
-"void ContactToConstraintKernel(__global struct b3Contact4Data* gContact, __global b3RigidBodyData_t* gBodies, __global b3InertiaData_t* gShapes, __global b3ContactConstraint4_t* gConstraintOut, \n"
-"int nContacts,\n"
-"float dt,\n"
-"float positionDrift,\n"
-"float positionConstraintCoeff\n"
-")\n"
-"{\n"
-" int gIdx = GET_GLOBAL_IDX;\n"
-" \n"
-" if( gIdx < nContacts )\n"
-" {\n"
-" int aIdx = abs(gContact[gIdx].m_bodyAPtrAndSignBit);\n"
-" int bIdx = abs(gContact[gIdx].m_bodyBPtrAndSignBit);\n"
-" float4 posA = gBodies[aIdx].m_pos;\n"
-" float4 linVelA = gBodies[aIdx].m_linVel;\n"
-" float4 angVelA = gBodies[aIdx].m_angVel;\n"
-" float invMassA = gBodies[aIdx].m_invMass;\n"
-" b3Mat3x3 invInertiaA = gShapes[aIdx].m_initInvInertia;\n"
-" float4 posB = gBodies[bIdx].m_pos;\n"
-" float4 linVelB = gBodies[bIdx].m_linVel;\n"
-" float4 angVelB = gBodies[bIdx].m_angVel;\n"
-" float invMassB = gBodies[bIdx].m_invMass;\n"
-" b3Mat3x3 invInertiaB = gShapes[bIdx].m_initInvInertia;\n"
-" b3ContactConstraint4_t cs;\n"
-" setConstraint4( posA, linVelA, angVelA, invMassA, invInertiaA, posB, linVelB, angVelB, invMassB, invInertiaB,\n"
-" &gContact[gIdx], dt, positionDrift, positionConstraintCoeff,\n"
-" &cs );\n"
-" \n"
-" cs.m_batchIdx = gContact[gIdx].m_batchIdx;\n"
-" gConstraintOut[gIdx] = cs;\n"
-" }\n"
-"}\n"
-;
+static const char* solverSetupCL =
+ "/*\n"
+ "Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
+ "This software is provided 'as-is', without any express or implied warranty.\n"
+ "In no event will the authors be held liable for any damages arising from the use of this software.\n"
+ "Permission is granted to anyone to use this software for any purpose, \n"
+ "including commercial applications, and to alter it and redistribute it freely, \n"
+ "subject to the following restrictions:\n"
+ "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
+ "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+ "3. This notice may not be removed or altered from any source distribution.\n"
+ "*/\n"
+ "//Originally written by Takahiro Harada\n"
+ "#ifndef B3_CONTACT4DATA_H\n"
+ "#define B3_CONTACT4DATA_H\n"
+ "#ifndef B3_FLOAT4_H\n"
+ "#define B3_FLOAT4_H\n"
+ "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+ "#define B3_PLATFORM_DEFINITIONS_H\n"
+ "struct MyTest\n"
+ "{\n"
+ " int bla;\n"
+ "};\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
+ "#define B3_LARGE_FLOAT 1e18f\n"
+ "#define B3_INFINITY 1e18f\n"
+ "#define b3Assert(a)\n"
+ "#define b3ConstArray(a) __global const a*\n"
+ "#define b3AtomicInc atomic_inc\n"
+ "#define b3AtomicAdd atomic_add\n"
+ "#define b3Fabs fabs\n"
+ "#define b3Sqrt native_sqrt\n"
+ "#define b3Sin native_sin\n"
+ "#define b3Cos native_cos\n"
+ "#define B3_STATIC\n"
+ "#endif\n"
+ "#endif\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ " typedef float4 b3Float4;\n"
+ " #define b3Float4ConstArg const b3Float4\n"
+ " #define b3MakeFloat4 (float4)\n"
+ " float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+ " {\n"
+ " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+ " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+ " return dot(a1, b1);\n"
+ " }\n"
+ " b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+ " {\n"
+ " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+ " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+ " return cross(a1, b1);\n"
+ " }\n"
+ " #define b3MinFloat4 min\n"
+ " #define b3MaxFloat4 max\n"
+ " #define b3Normalized(a) normalize(a)\n"
+ "#endif \n"
+ " \n"
+ "inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
+ "{\n"
+ " if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
+ " return false;\n"
+ " return true;\n"
+ "}\n"
+ "inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
+ "{\n"
+ " float maxDot = -B3_INFINITY;\n"
+ " int i = 0;\n"
+ " int ptIndex = -1;\n"
+ " for( i = 0; i < vecLen; i++ )\n"
+ " {\n"
+ " float dot = b3Dot3F4(vecArray[i],vec);\n"
+ " \n"
+ " if( dot > maxDot )\n"
+ " {\n"
+ " maxDot = dot;\n"
+ " ptIndex = i;\n"
+ " }\n"
+ " }\n"
+ " b3Assert(ptIndex>=0);\n"
+ " if (ptIndex<0)\n"
+ " {\n"
+ " ptIndex = 0;\n"
+ " }\n"
+ " *dotOut = maxDot;\n"
+ " return ptIndex;\n"
+ "}\n"
+ "#endif //B3_FLOAT4_H\n"
+ "typedef struct b3Contact4Data b3Contact4Data_t;\n"
+ "struct b3Contact4Data\n"
+ "{\n"
+ " b3Float4 m_worldPosB[4];\n"
+ "// b3Float4 m_localPosA[4];\n"
+ "// b3Float4 m_localPosB[4];\n"
+ " b3Float4 m_worldNormalOnB; // w: m_nPoints\n"
+ " unsigned short m_restituitionCoeffCmp;\n"
+ " unsigned short m_frictionCoeffCmp;\n"
+ " int m_batchIdx;\n"
+ " int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
+ " int m_bodyBPtrAndSignBit;\n"
+ " int m_childIndexA;\n"
+ " int m_childIndexB;\n"
+ " int m_unused1;\n"
+ " int m_unused2;\n"
+ "};\n"
+ "inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
+ "{\n"
+ " return (int)contact->m_worldNormalOnB.w;\n"
+ "};\n"
+ "inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
+ "{\n"
+ " contact->m_worldNormalOnB.w = (float)numPoints;\n"
+ "};\n"
+ "#endif //B3_CONTACT4DATA_H\n"
+ "#ifndef B3_CONTACT_CONSTRAINT5_H\n"
+ "#define B3_CONTACT_CONSTRAINT5_H\n"
+ "#ifndef B3_FLOAT4_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#endif \n"
+ "#endif //B3_FLOAT4_H\n"
+ "typedef struct b3ContactConstraint4 b3ContactConstraint4_t;\n"
+ "struct b3ContactConstraint4\n"
+ "{\n"
+ " b3Float4 m_linear;//normal?\n"
+ " b3Float4 m_worldPos[4];\n"
+ " b3Float4 m_center; // friction\n"
+ " float m_jacCoeffInv[4];\n"
+ " float m_b[4];\n"
+ " float m_appliedRambdaDt[4];\n"
+ " float m_fJacCoeffInv[2]; // friction\n"
+ " float m_fAppliedRambdaDt[2]; // friction\n"
+ " unsigned int m_bodyA;\n"
+ " unsigned int m_bodyB;\n"
+ " int m_batchIdx;\n"
+ " unsigned int m_paddings;\n"
+ "};\n"
+ "//inline void setFrictionCoeff(float value) { m_linear[3] = value; }\n"
+ "inline float b3GetFrictionCoeff(b3ContactConstraint4_t* constraint) \n"
+ "{\n"
+ " return constraint->m_linear.w; \n"
+ "}\n"
+ "#endif //B3_CONTACT_CONSTRAINT5_H\n"
+ "#ifndef B3_RIGIDBODY_DATA_H\n"
+ "#define B3_RIGIDBODY_DATA_H\n"
+ "#ifndef B3_FLOAT4_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#endif \n"
+ "#endif //B3_FLOAT4_H\n"
+ "#ifndef B3_QUAT_H\n"
+ "#define B3_QUAT_H\n"
+ "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#endif\n"
+ "#endif\n"
+ "#ifndef B3_FLOAT4_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#endif \n"
+ "#endif //B3_FLOAT4_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ " typedef float4 b3Quat;\n"
+ " #define b3QuatConstArg const b3Quat\n"
+ " \n"
+ " \n"
+ "inline float4 b3FastNormalize4(float4 v)\n"
+ "{\n"
+ " v = (float4)(v.xyz,0.f);\n"
+ " return fast_normalize(v);\n"
+ "}\n"
+ " \n"
+ "inline b3Quat b3QuatMul(b3Quat a, b3Quat b);\n"
+ "inline b3Quat b3QuatNormalized(b3QuatConstArg in);\n"
+ "inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec);\n"
+ "inline b3Quat b3QuatInvert(b3QuatConstArg q);\n"
+ "inline b3Quat b3QuatInverse(b3QuatConstArg q);\n"
+ "inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b)\n"
+ "{\n"
+ " b3Quat ans;\n"
+ " ans = b3Cross3( a, b );\n"
+ " ans += a.w*b+b.w*a;\n"
+ "// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+ " ans.w = a.w*b.w - b3Dot3F4(a, b);\n"
+ " return ans;\n"
+ "}\n"
+ "inline b3Quat b3QuatNormalized(b3QuatConstArg in)\n"
+ "{\n"
+ " b3Quat q;\n"
+ " q=in;\n"
+ " //return b3FastNormalize4(in);\n"
+ " float len = native_sqrt(dot(q, q));\n"
+ " if(len > 0.f)\n"
+ " {\n"
+ " q *= 1.f / len;\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " q.x = q.y = q.z = 0.f;\n"
+ " q.w = 1.f;\n"
+ " }\n"
+ " return q;\n"
+ "}\n"
+ "inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+ "{\n"
+ " b3Quat qInv = b3QuatInvert( q );\n"
+ " float4 vcpy = vec;\n"
+ " vcpy.w = 0.f;\n"
+ " float4 out = b3QuatMul(b3QuatMul(q,vcpy),qInv);\n"
+ " return out;\n"
+ "}\n"
+ "inline b3Quat b3QuatInverse(b3QuatConstArg q)\n"
+ "{\n"
+ " return (b3Quat)(-q.xyz, q.w);\n"
+ "}\n"
+ "inline b3Quat b3QuatInvert(b3QuatConstArg q)\n"
+ "{\n"
+ " return (b3Quat)(-q.xyz, q.w);\n"
+ "}\n"
+ "inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+ "{\n"
+ " return b3QuatRotate( b3QuatInvert( q ), vec );\n"
+ "}\n"
+ "inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation)\n"
+ "{\n"
+ " return b3QuatRotate( orientation, point ) + (translation);\n"
+ "}\n"
+ " \n"
+ "#endif \n"
+ "#endif //B3_QUAT_H\n"
+ "#ifndef B3_MAT3x3_H\n"
+ "#define B3_MAT3x3_H\n"
+ "#ifndef B3_QUAT_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#endif \n"
+ "#endif //B3_QUAT_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "typedef struct\n"
+ "{\n"
+ " b3Float4 m_row[3];\n"
+ "}b3Mat3x3;\n"
+ "#define b3Mat3x3ConstArg const b3Mat3x3\n"
+ "#define b3GetRow(m,row) (m.m_row[row])\n"
+ "inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat)\n"
+ "{\n"
+ " b3Float4 quat2 = (b3Float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);\n"
+ " b3Mat3x3 out;\n"
+ " out.m_row[0].x=1-2*quat2.y-2*quat2.z;\n"
+ " out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;\n"
+ " out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;\n"
+ " out.m_row[0].w = 0.f;\n"
+ " out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;\n"
+ " out.m_row[1].y=1-2*quat2.x-2*quat2.z;\n"
+ " out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;\n"
+ " out.m_row[1].w = 0.f;\n"
+ " out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;\n"
+ " out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;\n"
+ " out.m_row[2].z=1-2*quat2.x-2*quat2.y;\n"
+ " out.m_row[2].w = 0.f;\n"
+ " return out;\n"
+ "}\n"
+ "inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn)\n"
+ "{\n"
+ " b3Mat3x3 out;\n"
+ " out.m_row[0] = fabs(matIn.m_row[0]);\n"
+ " out.m_row[1] = fabs(matIn.m_row[1]);\n"
+ " out.m_row[2] = fabs(matIn.m_row[2]);\n"
+ " return out;\n"
+ "}\n"
+ "__inline\n"
+ "b3Mat3x3 mtZero();\n"
+ "__inline\n"
+ "b3Mat3x3 mtIdentity();\n"
+ "__inline\n"
+ "b3Mat3x3 mtTranspose(b3Mat3x3 m);\n"
+ "__inline\n"
+ "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);\n"
+ "__inline\n"
+ "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);\n"
+ "__inline\n"
+ "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);\n"
+ "__inline\n"
+ "b3Mat3x3 mtZero()\n"
+ "{\n"
+ " b3Mat3x3 m;\n"
+ " m.m_row[0] = (b3Float4)(0.f);\n"
+ " m.m_row[1] = (b3Float4)(0.f);\n"
+ " m.m_row[2] = (b3Float4)(0.f);\n"
+ " return m;\n"
+ "}\n"
+ "__inline\n"
+ "b3Mat3x3 mtIdentity()\n"
+ "{\n"
+ " b3Mat3x3 m;\n"
+ " m.m_row[0] = (b3Float4)(1,0,0,0);\n"
+ " m.m_row[1] = (b3Float4)(0,1,0,0);\n"
+ " m.m_row[2] = (b3Float4)(0,0,1,0);\n"
+ " return m;\n"
+ "}\n"
+ "__inline\n"
+ "b3Mat3x3 mtTranspose(b3Mat3x3 m)\n"
+ "{\n"
+ " b3Mat3x3 out;\n"
+ " out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
+ " out.m_row[1] = (b3Float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
+ " out.m_row[2] = (b3Float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
+ " return out;\n"
+ "}\n"
+ "__inline\n"
+ "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)\n"
+ "{\n"
+ " b3Mat3x3 transB;\n"
+ " transB = mtTranspose( b );\n"
+ " b3Mat3x3 ans;\n"
+ " // why this doesn't run when 0ing in the for{}\n"
+ " a.m_row[0].w = 0.f;\n"
+ " a.m_row[1].w = 0.f;\n"
+ " a.m_row[2].w = 0.f;\n"
+ " for(int i=0; i<3; i++)\n"
+ " {\n"
+ "// a.m_row[i].w = 0.f;\n"
+ " ans.m_row[i].x = b3Dot3F4(a.m_row[i],transB.m_row[0]);\n"
+ " ans.m_row[i].y = b3Dot3F4(a.m_row[i],transB.m_row[1]);\n"
+ " ans.m_row[i].z = b3Dot3F4(a.m_row[i],transB.m_row[2]);\n"
+ " ans.m_row[i].w = 0.f;\n"
+ " }\n"
+ " return ans;\n"
+ "}\n"
+ "__inline\n"
+ "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)\n"
+ "{\n"
+ " b3Float4 ans;\n"
+ " ans.x = b3Dot3F4( a.m_row[0], b );\n"
+ " ans.y = b3Dot3F4( a.m_row[1], b );\n"
+ " ans.z = b3Dot3F4( a.m_row[2], b );\n"
+ " ans.w = 0.f;\n"
+ " return ans;\n"
+ "}\n"
+ "__inline\n"
+ "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)\n"
+ "{\n"
+ " b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
+ " b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
+ " b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
+ " b3Float4 ans;\n"
+ " ans.x = b3Dot3F4( a, colx );\n"
+ " ans.y = b3Dot3F4( a, coly );\n"
+ " ans.z = b3Dot3F4( a, colz );\n"
+ " return ans;\n"
+ "}\n"
+ "#endif\n"
+ "#endif //B3_MAT3x3_H\n"
+ "typedef struct b3RigidBodyData b3RigidBodyData_t;\n"
+ "struct b3RigidBodyData\n"
+ "{\n"
+ " b3Float4 m_pos;\n"
+ " b3Quat m_quat;\n"
+ " b3Float4 m_linVel;\n"
+ " b3Float4 m_angVel;\n"
+ " int m_collidableIdx;\n"
+ " float m_invMass;\n"
+ " float m_restituitionCoeff;\n"
+ " float m_frictionCoeff;\n"
+ "};\n"
+ "typedef struct b3InertiaData b3InertiaData_t;\n"
+ "struct b3InertiaData\n"
+ "{\n"
+ " b3Mat3x3 m_invInertiaWorld;\n"
+ " b3Mat3x3 m_initInvInertia;\n"
+ "};\n"
+ "#endif //B3_RIGIDBODY_DATA_H\n"
+ " \n"
+ "void b3PlaneSpace1 (b3Float4ConstArg n, b3Float4* p, b3Float4* q);\n"
+ " void b3PlaneSpace1 (b3Float4ConstArg n, b3Float4* p, b3Float4* q)\n"
+ "{\n"
+ " if (b3Fabs(n.z) > 0.70710678f) {\n"
+ " // choose p in y-z plane\n"
+ " float a = n.y*n.y + n.z*n.z;\n"
+ " float k = 1.f/sqrt(a);\n"
+ " p[0].x = 0;\n"
+ " p[0].y = -n.z*k;\n"
+ " p[0].z = n.y*k;\n"
+ " // set q = n x p\n"
+ " q[0].x = a*k;\n"
+ " q[0].y = -n.x*p[0].z;\n"
+ " q[0].z = n.x*p[0].y;\n"
+ " }\n"
+ " else {\n"
+ " // choose p in x-y plane\n"
+ " float a = n.x*n.x + n.y*n.y;\n"
+ " float k = 1.f/sqrt(a);\n"
+ " p[0].x = -n.y*k;\n"
+ " p[0].y = n.x*k;\n"
+ " p[0].z = 0;\n"
+ " // set q = n x p\n"
+ " q[0].x = -n.z*p[0].y;\n"
+ " q[0].y = n.z*p[0].x;\n"
+ " q[0].z = a*k;\n"
+ " }\n"
+ "}\n"
+ " \n"
+ "void setLinearAndAngular( b3Float4ConstArg n, b3Float4ConstArg r0, b3Float4ConstArg r1, b3Float4* linear, b3Float4* angular0, b3Float4* angular1)\n"
+ "{\n"
+ " *linear = b3MakeFloat4(n.x,n.y,n.z,0.f);\n"
+ " *angular0 = b3Cross3(r0, n);\n"
+ " *angular1 = -b3Cross3(r1, n);\n"
+ "}\n"
+ "float calcRelVel( b3Float4ConstArg l0, b3Float4ConstArg l1, b3Float4ConstArg a0, b3Float4ConstArg a1, b3Float4ConstArg linVel0,\n"
+ " b3Float4ConstArg angVel0, b3Float4ConstArg linVel1, b3Float4ConstArg angVel1 )\n"
+ "{\n"
+ " return b3Dot3F4(l0, linVel0) + b3Dot3F4(a0, angVel0) + b3Dot3F4(l1, linVel1) + b3Dot3F4(a1, angVel1);\n"
+ "}\n"
+ "float calcJacCoeff(b3Float4ConstArg linear0, b3Float4ConstArg linear1, b3Float4ConstArg angular0, b3Float4ConstArg angular1,\n"
+ " float invMass0, const b3Mat3x3* invInertia0, float invMass1, const b3Mat3x3* invInertia1)\n"
+ "{\n"
+ " // linear0,1 are normlized\n"
+ " float jmj0 = invMass0;//b3Dot3F4(linear0, linear0)*invMass0;\n"
+ " float jmj1 = b3Dot3F4(mtMul3(angular0,*invInertia0), angular0);\n"
+ " float jmj2 = invMass1;//b3Dot3F4(linear1, linear1)*invMass1;\n"
+ " float jmj3 = b3Dot3F4(mtMul3(angular1,*invInertia1), angular1);\n"
+ " return -1.f/(jmj0+jmj1+jmj2+jmj3);\n"
+ "}\n"
+ "void setConstraint4( b3Float4ConstArg posA, b3Float4ConstArg linVelA, b3Float4ConstArg angVelA, float invMassA, b3Mat3x3ConstArg invInertiaA,\n"
+ " b3Float4ConstArg posB, b3Float4ConstArg linVelB, b3Float4ConstArg angVelB, float invMassB, b3Mat3x3ConstArg invInertiaB, \n"
+ " __global struct b3Contact4Data* src, float dt, float positionDrift, float positionConstraintCoeff,\n"
+ " b3ContactConstraint4_t* dstC )\n"
+ "{\n"
+ " dstC->m_bodyA = abs(src->m_bodyAPtrAndSignBit);\n"
+ " dstC->m_bodyB = abs(src->m_bodyBPtrAndSignBit);\n"
+ " float dtInv = 1.f/dt;\n"
+ " for(int ic=0; ic<4; ic++)\n"
+ " {\n"
+ " dstC->m_appliedRambdaDt[ic] = 0.f;\n"
+ " }\n"
+ " dstC->m_fJacCoeffInv[0] = dstC->m_fJacCoeffInv[1] = 0.f;\n"
+ " dstC->m_linear = src->m_worldNormalOnB;\n"
+ " dstC->m_linear.w = 0.7f ;//src->getFrictionCoeff() );\n"
+ " for(int ic=0; ic<4; ic++)\n"
+ " {\n"
+ " b3Float4 r0 = src->m_worldPosB[ic] - posA;\n"
+ " b3Float4 r1 = src->m_worldPosB[ic] - posB;\n"
+ " if( ic >= src->m_worldNormalOnB.w )//npoints\n"
+ " {\n"
+ " dstC->m_jacCoeffInv[ic] = 0.f;\n"
+ " continue;\n"
+ " }\n"
+ " float relVelN;\n"
+ " {\n"
+ " b3Float4 linear, angular0, angular1;\n"
+ " setLinearAndAngular(src->m_worldNormalOnB, r0, r1, &linear, &angular0, &angular1);\n"
+ " dstC->m_jacCoeffInv[ic] = calcJacCoeff(linear, -linear, angular0, angular1,\n"
+ " invMassA, &invInertiaA, invMassB, &invInertiaB );\n"
+ " relVelN = calcRelVel(linear, -linear, angular0, angular1,\n"
+ " linVelA, angVelA, linVelB, angVelB);\n"
+ " float e = 0.f;//src->getRestituitionCoeff();\n"
+ " if( relVelN*relVelN < 0.004f ) e = 0.f;\n"
+ " dstC->m_b[ic] = e*relVelN;\n"
+ " //float penetration = src->m_worldPosB[ic].w;\n"
+ " dstC->m_b[ic] += (src->m_worldPosB[ic].w + positionDrift)*positionConstraintCoeff*dtInv;\n"
+ " dstC->m_appliedRambdaDt[ic] = 0.f;\n"
+ " }\n"
+ " }\n"
+ " if( src->m_worldNormalOnB.w > 0 )//npoints\n"
+ " { // prepare friction\n"
+ " b3Float4 center = b3MakeFloat4(0.f,0.f,0.f,0.f);\n"
+ " for(int i=0; i<src->m_worldNormalOnB.w; i++) \n"
+ " center += src->m_worldPosB[i];\n"
+ " center /= (float)src->m_worldNormalOnB.w;\n"
+ " b3Float4 tangent[2];\n"
+ " b3PlaneSpace1(src->m_worldNormalOnB,&tangent[0],&tangent[1]);\n"
+ " \n"
+ " b3Float4 r[2];\n"
+ " r[0] = center - posA;\n"
+ " r[1] = center - posB;\n"
+ " for(int i=0; i<2; i++)\n"
+ " {\n"
+ " b3Float4 linear, angular0, angular1;\n"
+ " setLinearAndAngular(tangent[i], r[0], r[1], &linear, &angular0, &angular1);\n"
+ " dstC->m_fJacCoeffInv[i] = calcJacCoeff(linear, -linear, angular0, angular1,\n"
+ " invMassA, &invInertiaA, invMassB, &invInertiaB );\n"
+ " dstC->m_fAppliedRambdaDt[i] = 0.f;\n"
+ " }\n"
+ " dstC->m_center = center;\n"
+ " }\n"
+ " for(int i=0; i<4; i++)\n"
+ " {\n"
+ " if( i<src->m_worldNormalOnB.w )\n"
+ " {\n"
+ " dstC->m_worldPos[i] = src->m_worldPosB[i];\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " dstC->m_worldPos[i] = b3MakeFloat4(0.f,0.f,0.f,0.f);\n"
+ " }\n"
+ " }\n"
+ "}\n"
+ "#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
+ "#ifdef cl_ext_atomic_counters_32\n"
+ "#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
+ "#else\n"
+ "#define counter32_t volatile global int*\n"
+ "#endif\n"
+ "typedef unsigned int u32;\n"
+ "typedef unsigned short u16;\n"
+ "typedef unsigned char u8;\n"
+ "#define GET_GROUP_IDX get_group_id(0)\n"
+ "#define GET_LOCAL_IDX get_local_id(0)\n"
+ "#define GET_GLOBAL_IDX get_global_id(0)\n"
+ "#define GET_GROUP_SIZE get_local_size(0)\n"
+ "#define GET_NUM_GROUPS get_num_groups(0)\n"
+ "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+ "#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
+ "#define AtomInc(x) atom_inc(&(x))\n"
+ "#define AtomInc1(x, out) out = atom_inc(&(x))\n"
+ "#define AppendInc(x, out) out = atomic_inc(x)\n"
+ "#define AtomAdd(x, value) atom_add(&(x), value)\n"
+ "#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
+ "#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
+ "#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
+ "#define make_float4 (float4)\n"
+ "#define make_float2 (float2)\n"
+ "#define make_uint4 (uint4)\n"
+ "#define make_int4 (int4)\n"
+ "#define make_uint2 (uint2)\n"
+ "#define make_int2 (int2)\n"
+ "#define max2 max\n"
+ "#define min2 min\n"
+ "///////////////////////////////////////\n"
+ "// Vector\n"
+ "///////////////////////////////////////\n"
+ "__inline\n"
+ "float fastDiv(float numerator, float denominator)\n"
+ "{\n"
+ " return native_divide(numerator, denominator); \n"
+ "// return numerator/denominator; \n"
+ "}\n"
+ "__inline\n"
+ "float4 fastDiv4(float4 numerator, float4 denominator)\n"
+ "{\n"
+ " return native_divide(numerator, denominator); \n"
+ "}\n"
+ "__inline\n"
+ "float fastSqrtf(float f2)\n"
+ "{\n"
+ " return native_sqrt(f2);\n"
+ "// return sqrt(f2);\n"
+ "}\n"
+ "__inline\n"
+ "float fastRSqrt(float f2)\n"
+ "{\n"
+ " return native_rsqrt(f2);\n"
+ "}\n"
+ "__inline\n"
+ "float fastLength4(float4 v)\n"
+ "{\n"
+ " return fast_length(v);\n"
+ "}\n"
+ "__inline\n"
+ "float4 fastNormalize4(float4 v)\n"
+ "{\n"
+ " return fast_normalize(v);\n"
+ "}\n"
+ "__inline\n"
+ "float sqrtf(float a)\n"
+ "{\n"
+ "// return sqrt(a);\n"
+ " return native_sqrt(a);\n"
+ "}\n"
+ "__inline\n"
+ "float4 cross3(float4 a, float4 b)\n"
+ "{\n"
+ " return cross(a,b);\n"
+ "}\n"
+ "__inline\n"
+ "float dot3F4(float4 a, float4 b)\n"
+ "{\n"
+ " float4 a1 = make_float4(a.xyz,0.f);\n"
+ " float4 b1 = make_float4(b.xyz,0.f);\n"
+ " return dot(a1, b1);\n"
+ "}\n"
+ "__inline\n"
+ "float length3(const float4 a)\n"
+ "{\n"
+ " return sqrtf(dot3F4(a,a));\n"
+ "}\n"
+ "__inline\n"
+ "float dot4(const float4 a, const float4 b)\n"
+ "{\n"
+ " return dot( a, b );\n"
+ "}\n"
+ "// for height\n"
+ "__inline\n"
+ "float dot3w1(const float4 point, const float4 eqn)\n"
+ "{\n"
+ " return dot3F4(point,eqn) + eqn.w;\n"
+ "}\n"
+ "__inline\n"
+ "float4 normalize3(const float4 a)\n"
+ "{\n"
+ " float4 n = make_float4(a.x, a.y, a.z, 0.f);\n"
+ " return fastNormalize4( n );\n"
+ "// float length = sqrtf(dot3F4(a, a));\n"
+ "// return 1.f/length * a;\n"
+ "}\n"
+ "__inline\n"
+ "float4 normalize4(const float4 a)\n"
+ "{\n"
+ " float length = sqrtf(dot4(a, a));\n"
+ " return 1.f/length * a;\n"
+ "}\n"
+ "__inline\n"
+ "float4 createEquation(const float4 a, const float4 b, const float4 c)\n"
+ "{\n"
+ " float4 eqn;\n"
+ " float4 ab = b-a;\n"
+ " float4 ac = c-a;\n"
+ " eqn = normalize3( cross3(ab, ac) );\n"
+ " eqn.w = -dot3F4(eqn,a);\n"
+ " return eqn;\n"
+ "}\n"
+ "#define WG_SIZE 64\n"
+ "typedef struct\n"
+ "{\n"
+ " int m_nConstraints;\n"
+ " int m_start;\n"
+ " int m_batchIdx;\n"
+ " int m_nSplit;\n"
+ "// int m_paddings[1];\n"
+ "} ConstBuffer;\n"
+ "typedef struct\n"
+ "{\n"
+ " int m_solveFriction;\n"
+ " int m_maxBatch; // long batch really kills the performance\n"
+ " int m_batchIdx;\n"
+ " int m_nSplit;\n"
+ "// int m_paddings[1];\n"
+ "} ConstBufferBatchSolve;\n"
+ " \n"
+ "typedef struct \n"
+ "{\n"
+ " int m_valInt0;\n"
+ " int m_valInt1;\n"
+ " int m_valInt2;\n"
+ " int m_valInt3;\n"
+ " float m_val0;\n"
+ " float m_val1;\n"
+ " float m_val2;\n"
+ " float m_val3;\n"
+ "} SolverDebugInfo;\n"
+ "typedef struct\n"
+ "{\n"
+ " int m_nContacts;\n"
+ " float m_dt;\n"
+ " float m_positionDrift;\n"
+ " float m_positionConstraintCoeff;\n"
+ "} ConstBufferCTC;\n"
+ "__kernel\n"
+ "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+ "void ContactToConstraintKernel(__global struct b3Contact4Data* gContact, __global b3RigidBodyData_t* gBodies, __global b3InertiaData_t* gShapes, __global b3ContactConstraint4_t* gConstraintOut, \n"
+ "int nContacts,\n"
+ "float dt,\n"
+ "float positionDrift,\n"
+ "float positionConstraintCoeff\n"
+ ")\n"
+ "{\n"
+ " int gIdx = GET_GLOBAL_IDX;\n"
+ " \n"
+ " if( gIdx < nContacts )\n"
+ " {\n"
+ " int aIdx = abs(gContact[gIdx].m_bodyAPtrAndSignBit);\n"
+ " int bIdx = abs(gContact[gIdx].m_bodyBPtrAndSignBit);\n"
+ " float4 posA = gBodies[aIdx].m_pos;\n"
+ " float4 linVelA = gBodies[aIdx].m_linVel;\n"
+ " float4 angVelA = gBodies[aIdx].m_angVel;\n"
+ " float invMassA = gBodies[aIdx].m_invMass;\n"
+ " b3Mat3x3 invInertiaA = gShapes[aIdx].m_initInvInertia;\n"
+ " float4 posB = gBodies[bIdx].m_pos;\n"
+ " float4 linVelB = gBodies[bIdx].m_linVel;\n"
+ " float4 angVelB = gBodies[bIdx].m_angVel;\n"
+ " float invMassB = gBodies[bIdx].m_invMass;\n"
+ " b3Mat3x3 invInertiaB = gShapes[bIdx].m_initInvInertia;\n"
+ " b3ContactConstraint4_t cs;\n"
+ " setConstraint4( posA, linVelA, angVelA, invMassA, invInertiaA, posB, linVelB, angVelB, invMassB, invInertiaB,\n"
+ " &gContact[gIdx], dt, positionDrift, positionConstraintCoeff,\n"
+ " &cs );\n"
+ " \n"
+ " cs.m_batchIdx = gContact[gIdx].m_batchIdx;\n"
+ " gConstraintOut[gIdx] = cs;\n"
+ " }\n"
+ "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solverSetup2.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solverSetup2.h
index 1b5819f6cf..1e6e3579b6 100644
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solverSetup2.h
+++ b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solverSetup2.h
@@ -1,601 +1,600 @@
//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* solverSetup2CL= \
-"/*\n"
-"Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
-"This software is provided 'as-is', without any express or implied warranty.\n"
-"In no event will the authors be held liable for any damages arising from the use of this software.\n"
-"Permission is granted to anyone to use this software for any purpose, \n"
-"including commercial applications, and to alter it and redistribute it freely, \n"
-"subject to the following restrictions:\n"
-"1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
-"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
-"3. This notice may not be removed or altered from any source distribution.\n"
-"*/\n"
-"//Originally written by Takahiro Harada\n"
-"#ifndef B3_CONTACT4DATA_H\n"
-"#define B3_CONTACT4DATA_H\n"
-"#ifndef B3_FLOAT4_H\n"
-"#define B3_FLOAT4_H\n"
-"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
-"#define B3_PLATFORM_DEFINITIONS_H\n"
-"struct MyTest\n"
-"{\n"
-" int bla;\n"
-"};\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
-"#define B3_LARGE_FLOAT 1e18f\n"
-"#define B3_INFINITY 1e18f\n"
-"#define b3Assert(a)\n"
-"#define b3ConstArray(a) __global const a*\n"
-"#define b3AtomicInc atomic_inc\n"
-"#define b3AtomicAdd atomic_add\n"
-"#define b3Fabs fabs\n"
-"#define b3Sqrt native_sqrt\n"
-"#define b3Sin native_sin\n"
-"#define b3Cos native_cos\n"
-"#define B3_STATIC\n"
-"#endif\n"
-"#endif\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-" typedef float4 b3Float4;\n"
-" #define b3Float4ConstArg const b3Float4\n"
-" #define b3MakeFloat4 (float4)\n"
-" float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
-" {\n"
-" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
-" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
-" return dot(a1, b1);\n"
-" }\n"
-" b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
-" {\n"
-" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
-" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
-" return cross(a1, b1);\n"
-" }\n"
-" #define b3MinFloat4 min\n"
-" #define b3MaxFloat4 max\n"
-" #define b3Normalized(a) normalize(a)\n"
-"#endif \n"
-" \n"
-"inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
-"{\n"
-" if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
-" return false;\n"
-" return true;\n"
-"}\n"
-"inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
-"{\n"
-" float maxDot = -B3_INFINITY;\n"
-" int i = 0;\n"
-" int ptIndex = -1;\n"
-" for( i = 0; i < vecLen; i++ )\n"
-" {\n"
-" float dot = b3Dot3F4(vecArray[i],vec);\n"
-" \n"
-" if( dot > maxDot )\n"
-" {\n"
-" maxDot = dot;\n"
-" ptIndex = i;\n"
-" }\n"
-" }\n"
-" b3Assert(ptIndex>=0);\n"
-" if (ptIndex<0)\n"
-" {\n"
-" ptIndex = 0;\n"
-" }\n"
-" *dotOut = maxDot;\n"
-" return ptIndex;\n"
-"}\n"
-"#endif //B3_FLOAT4_H\n"
-"typedef struct b3Contact4Data b3Contact4Data_t;\n"
-"struct b3Contact4Data\n"
-"{\n"
-" b3Float4 m_worldPosB[4];\n"
-"// b3Float4 m_localPosA[4];\n"
-"// b3Float4 m_localPosB[4];\n"
-" b3Float4 m_worldNormalOnB; // w: m_nPoints\n"
-" unsigned short m_restituitionCoeffCmp;\n"
-" unsigned short m_frictionCoeffCmp;\n"
-" int m_batchIdx;\n"
-" int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
-" int m_bodyBPtrAndSignBit;\n"
-" int m_childIndexA;\n"
-" int m_childIndexB;\n"
-" int m_unused1;\n"
-" int m_unused2;\n"
-"};\n"
-"inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
-"{\n"
-" return (int)contact->m_worldNormalOnB.w;\n"
-"};\n"
-"inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
-"{\n"
-" contact->m_worldNormalOnB.w = (float)numPoints;\n"
-"};\n"
-"#endif //B3_CONTACT4DATA_H\n"
-"#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
-"#ifdef cl_ext_atomic_counters_32\n"
-"#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
-"#else\n"
-"#define counter32_t volatile global int*\n"
-"#endif\n"
-"typedef unsigned int u32;\n"
-"typedef unsigned short u16;\n"
-"typedef unsigned char u8;\n"
-"#define GET_GROUP_IDX get_group_id(0)\n"
-"#define GET_LOCAL_IDX get_local_id(0)\n"
-"#define GET_GLOBAL_IDX get_global_id(0)\n"
-"#define GET_GROUP_SIZE get_local_size(0)\n"
-"#define GET_NUM_GROUPS get_num_groups(0)\n"
-"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
-"#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
-"#define AtomInc(x) atom_inc(&(x))\n"
-"#define AtomInc1(x, out) out = atom_inc(&(x))\n"
-"#define AppendInc(x, out) out = atomic_inc(x)\n"
-"#define AtomAdd(x, value) atom_add(&(x), value)\n"
-"#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
-"#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
-"#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
-"#define make_float4 (float4)\n"
-"#define make_float2 (float2)\n"
-"#define make_uint4 (uint4)\n"
-"#define make_int4 (int4)\n"
-"#define make_uint2 (uint2)\n"
-"#define make_int2 (int2)\n"
-"#define max2 max\n"
-"#define min2 min\n"
-"///////////////////////////////////////\n"
-"// Vector\n"
-"///////////////////////////////////////\n"
-"__inline\n"
-"float fastDiv(float numerator, float denominator)\n"
-"{\n"
-" return native_divide(numerator, denominator); \n"
-"// return numerator/denominator; \n"
-"}\n"
-"__inline\n"
-"float4 fastDiv4(float4 numerator, float4 denominator)\n"
-"{\n"
-" return native_divide(numerator, denominator); \n"
-"}\n"
-"__inline\n"
-"float fastSqrtf(float f2)\n"
-"{\n"
-" return native_sqrt(f2);\n"
-"// return sqrt(f2);\n"
-"}\n"
-"__inline\n"
-"float fastRSqrt(float f2)\n"
-"{\n"
-" return native_rsqrt(f2);\n"
-"}\n"
-"__inline\n"
-"float fastLength4(float4 v)\n"
-"{\n"
-" return fast_length(v);\n"
-"}\n"
-"__inline\n"
-"float4 fastNormalize4(float4 v)\n"
-"{\n"
-" return fast_normalize(v);\n"
-"}\n"
-"__inline\n"
-"float sqrtf(float a)\n"
-"{\n"
-"// return sqrt(a);\n"
-" return native_sqrt(a);\n"
-"}\n"
-"__inline\n"
-"float4 cross3(float4 a, float4 b)\n"
-"{\n"
-" return cross(a,b);\n"
-"}\n"
-"__inline\n"
-"float dot3F4(float4 a, float4 b)\n"
-"{\n"
-" float4 a1 = make_float4(a.xyz,0.f);\n"
-" float4 b1 = make_float4(b.xyz,0.f);\n"
-" return dot(a1, b1);\n"
-"}\n"
-"__inline\n"
-"float length3(const float4 a)\n"
-"{\n"
-" return sqrtf(dot3F4(a,a));\n"
-"}\n"
-"__inline\n"
-"float dot4(const float4 a, const float4 b)\n"
-"{\n"
-" return dot( a, b );\n"
-"}\n"
-"// for height\n"
-"__inline\n"
-"float dot3w1(const float4 point, const float4 eqn)\n"
-"{\n"
-" return dot3F4(point,eqn) + eqn.w;\n"
-"}\n"
-"__inline\n"
-"float4 normalize3(const float4 a)\n"
-"{\n"
-" float4 n = make_float4(a.x, a.y, a.z, 0.f);\n"
-" return fastNormalize4( n );\n"
-"// float length = sqrtf(dot3F4(a, a));\n"
-"// return 1.f/length * a;\n"
-"}\n"
-"__inline\n"
-"float4 normalize4(const float4 a)\n"
-"{\n"
-" float length = sqrtf(dot4(a, a));\n"
-" return 1.f/length * a;\n"
-"}\n"
-"__inline\n"
-"float4 createEquation(const float4 a, const float4 b, const float4 c)\n"
-"{\n"
-" float4 eqn;\n"
-" float4 ab = b-a;\n"
-" float4 ac = c-a;\n"
-" eqn = normalize3( cross3(ab, ac) );\n"
-" eqn.w = -dot3F4(eqn,a);\n"
-" return eqn;\n"
-"}\n"
-"///////////////////////////////////////\n"
-"// Matrix3x3\n"
-"///////////////////////////////////////\n"
-"typedef struct\n"
-"{\n"
-" float4 m_row[3];\n"
-"}Matrix3x3;\n"
-"__inline\n"
-"Matrix3x3 mtZero();\n"
-"__inline\n"
-"Matrix3x3 mtIdentity();\n"
-"__inline\n"
-"Matrix3x3 mtTranspose(Matrix3x3 m);\n"
-"__inline\n"
-"Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b);\n"
-"__inline\n"
-"float4 mtMul1(Matrix3x3 a, float4 b);\n"
-"__inline\n"
-"float4 mtMul3(float4 a, Matrix3x3 b);\n"
-"__inline\n"
-"Matrix3x3 mtZero()\n"
-"{\n"
-" Matrix3x3 m;\n"
-" m.m_row[0] = (float4)(0.f);\n"
-" m.m_row[1] = (float4)(0.f);\n"
-" m.m_row[2] = (float4)(0.f);\n"
-" return m;\n"
-"}\n"
-"__inline\n"
-"Matrix3x3 mtIdentity()\n"
-"{\n"
-" Matrix3x3 m;\n"
-" m.m_row[0] = (float4)(1,0,0,0);\n"
-" m.m_row[1] = (float4)(0,1,0,0);\n"
-" m.m_row[2] = (float4)(0,0,1,0);\n"
-" return m;\n"
-"}\n"
-"__inline\n"
-"Matrix3x3 mtTranspose(Matrix3x3 m)\n"
-"{\n"
-" Matrix3x3 out;\n"
-" out.m_row[0] = (float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
-" out.m_row[1] = (float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
-" out.m_row[2] = (float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
-" return out;\n"
-"}\n"
-"__inline\n"
-"Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b)\n"
-"{\n"
-" Matrix3x3 transB;\n"
-" transB = mtTranspose( b );\n"
-" Matrix3x3 ans;\n"
-" // why this doesn't run when 0ing in the for{}\n"
-" a.m_row[0].w = 0.f;\n"
-" a.m_row[1].w = 0.f;\n"
-" a.m_row[2].w = 0.f;\n"
-" for(int i=0; i<3; i++)\n"
-" {\n"
-"// a.m_row[i].w = 0.f;\n"
-" ans.m_row[i].x = dot3F4(a.m_row[i],transB.m_row[0]);\n"
-" ans.m_row[i].y = dot3F4(a.m_row[i],transB.m_row[1]);\n"
-" ans.m_row[i].z = dot3F4(a.m_row[i],transB.m_row[2]);\n"
-" ans.m_row[i].w = 0.f;\n"
-" }\n"
-" return ans;\n"
-"}\n"
-"__inline\n"
-"float4 mtMul1(Matrix3x3 a, float4 b)\n"
-"{\n"
-" float4 ans;\n"
-" ans.x = dot3F4( a.m_row[0], b );\n"
-" ans.y = dot3F4( a.m_row[1], b );\n"
-" ans.z = dot3F4( a.m_row[2], b );\n"
-" ans.w = 0.f;\n"
-" return ans;\n"
-"}\n"
-"__inline\n"
-"float4 mtMul3(float4 a, Matrix3x3 b)\n"
-"{\n"
-" float4 colx = make_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
-" float4 coly = make_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
-" float4 colz = make_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
-" float4 ans;\n"
-" ans.x = dot3F4( a, colx );\n"
-" ans.y = dot3F4( a, coly );\n"
-" ans.z = dot3F4( a, colz );\n"
-" return ans;\n"
-"}\n"
-"///////////////////////////////////////\n"
-"// Quaternion\n"
-"///////////////////////////////////////\n"
-"typedef float4 Quaternion;\n"
-"__inline\n"
-"Quaternion qtMul(Quaternion a, Quaternion b);\n"
-"__inline\n"
-"Quaternion qtNormalize(Quaternion in);\n"
-"__inline\n"
-"float4 qtRotate(Quaternion q, float4 vec);\n"
-"__inline\n"
-"Quaternion qtInvert(Quaternion q);\n"
-"__inline\n"
-"Quaternion qtMul(Quaternion a, Quaternion b)\n"
-"{\n"
-" Quaternion ans;\n"
-" ans = cross3( a, b );\n"
-" ans += a.w*b+b.w*a;\n"
-"// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
-" ans.w = a.w*b.w - dot3F4(a, b);\n"
-" return ans;\n"
-"}\n"
-"__inline\n"
-"Quaternion qtNormalize(Quaternion in)\n"
-"{\n"
-" return fastNormalize4(in);\n"
-"// in /= length( in );\n"
-"// return in;\n"
-"}\n"
-"__inline\n"
-"float4 qtRotate(Quaternion q, float4 vec)\n"
-"{\n"
-" Quaternion qInv = qtInvert( q );\n"
-" float4 vcpy = vec;\n"
-" vcpy.w = 0.f;\n"
-" float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
-" return out;\n"
-"}\n"
-"__inline\n"
-"Quaternion qtInvert(Quaternion q)\n"
-"{\n"
-" return (Quaternion)(-q.xyz, q.w);\n"
-"}\n"
-"__inline\n"
-"float4 qtInvRotate(const Quaternion q, float4 vec)\n"
-"{\n"
-" return qtRotate( qtInvert( q ), vec );\n"
-"}\n"
-"#define WG_SIZE 64\n"
-"typedef struct\n"
-"{\n"
-" float4 m_pos;\n"
-" Quaternion m_quat;\n"
-" float4 m_linVel;\n"
-" float4 m_angVel;\n"
-" u32 m_shapeIdx;\n"
-" float m_invMass;\n"
-" float m_restituitionCoeff;\n"
-" float m_frictionCoeff;\n"
-"} Body;\n"
-"typedef struct\n"
-"{\n"
-" Matrix3x3 m_invInertia;\n"
-" Matrix3x3 m_initInvInertia;\n"
-"} Shape;\n"
-"typedef struct\n"
-"{\n"
-" float4 m_linear;\n"
-" float4 m_worldPos[4];\n"
-" float4 m_center; \n"
-" float m_jacCoeffInv[4];\n"
-" float m_b[4];\n"
-" float m_appliedRambdaDt[4];\n"
-" float m_fJacCoeffInv[2]; \n"
-" float m_fAppliedRambdaDt[2]; \n"
-" u32 m_bodyA;\n"
-" u32 m_bodyB;\n"
-" int m_batchIdx;\n"
-" u32 m_paddings[1];\n"
-"} Constraint4;\n"
-"typedef struct\n"
-"{\n"
-" int m_nConstraints;\n"
-" int m_start;\n"
-" int m_batchIdx;\n"
-" int m_nSplit;\n"
-"// int m_paddings[1];\n"
-"} ConstBuffer;\n"
-"typedef struct\n"
-"{\n"
-" int m_solveFriction;\n"
-" int m_maxBatch; // long batch really kills the performance\n"
-" int m_batchIdx;\n"
-" int m_nSplit;\n"
-"// int m_paddings[1];\n"
-"} ConstBufferBatchSolve;\n"
-" \n"
-"typedef struct \n"
-"{\n"
-" int m_valInt0;\n"
-" int m_valInt1;\n"
-" int m_valInt2;\n"
-" int m_valInt3;\n"
-" float m_val0;\n"
-" float m_val1;\n"
-" float m_val2;\n"
-" float m_val3;\n"
-"} SolverDebugInfo;\n"
-"// others\n"
-"__kernel\n"
-"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
-"void ReorderContactKernel(__global struct b3Contact4Data* in, __global struct b3Contact4Data* out, __global int2* sortData, int4 cb )\n"
-"{\n"
-" int nContacts = cb.x;\n"
-" int gIdx = GET_GLOBAL_IDX;\n"
-" if( gIdx < nContacts )\n"
-" {\n"
-" int srcIdx = sortData[gIdx].y;\n"
-" out[gIdx] = in[srcIdx];\n"
-" }\n"
-"}\n"
-"__kernel __attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
-"void SetDeterminismSortDataChildShapeB(__global struct b3Contact4Data* contactsIn, __global int2* sortDataOut, int nContacts)\n"
-"{\n"
-" int gIdx = GET_GLOBAL_IDX;\n"
-" if( gIdx < nContacts )\n"
-" {\n"
-" int2 sd;\n"
-" sd.x = contactsIn[gIdx].m_childIndexB;\n"
-" sd.y = gIdx;\n"
-" sortDataOut[gIdx] = sd;\n"
-" }\n"
-"}\n"
-"__kernel __attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
-"void SetDeterminismSortDataChildShapeA(__global struct b3Contact4Data* contactsIn, __global int2* sortDataInOut, int nContacts)\n"
-"{\n"
-" int gIdx = GET_GLOBAL_IDX;\n"
-" if( gIdx < nContacts )\n"
-" {\n"
-" int2 sdIn;\n"
-" sdIn = sortDataInOut[gIdx];\n"
-" int2 sdOut;\n"
-" sdOut.x = contactsIn[sdIn.y].m_childIndexA;\n"
-" sdOut.y = sdIn.y;\n"
-" sortDataInOut[gIdx] = sdOut;\n"
-" }\n"
-"}\n"
-"__kernel __attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
-"void SetDeterminismSortDataBodyA(__global struct b3Contact4Data* contactsIn, __global int2* sortDataInOut, int nContacts)\n"
-"{\n"
-" int gIdx = GET_GLOBAL_IDX;\n"
-" if( gIdx < nContacts )\n"
-" {\n"
-" int2 sdIn;\n"
-" sdIn = sortDataInOut[gIdx];\n"
-" int2 sdOut;\n"
-" sdOut.x = contactsIn[sdIn.y].m_bodyAPtrAndSignBit;\n"
-" sdOut.y = sdIn.y;\n"
-" sortDataInOut[gIdx] = sdOut;\n"
-" }\n"
-"}\n"
-"__kernel\n"
-"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
-"void SetDeterminismSortDataBodyB(__global struct b3Contact4Data* contactsIn, __global int2* sortDataInOut, int nContacts)\n"
-"{\n"
-" int gIdx = GET_GLOBAL_IDX;\n"
-" if( gIdx < nContacts )\n"
-" {\n"
-" int2 sdIn;\n"
-" sdIn = sortDataInOut[gIdx];\n"
-" int2 sdOut;\n"
-" sdOut.x = contactsIn[sdIn.y].m_bodyBPtrAndSignBit;\n"
-" sdOut.y = sdIn.y;\n"
-" sortDataInOut[gIdx] = sdOut;\n"
-" }\n"
-"}\n"
-"typedef struct\n"
-"{\n"
-" int m_nContacts;\n"
-" int m_staticIdx;\n"
-" float m_scale;\n"
-" int m_nSplit;\n"
-"} ConstBufferSSD;\n"
-"__constant const int gridTable4x4[] = \n"
-"{\n"
-" 0,1,17,16,\n"
-" 1,2,18,19,\n"
-" 17,18,32,3,\n"
-" 16,19,3,34\n"
-"};\n"
-"__constant const int gridTable8x8[] = \n"
-"{\n"
-" 0, 2, 3, 16, 17, 18, 19, 1,\n"
-" 66, 64, 80, 67, 82, 81, 65, 83,\n"
-" 131,144,128,130,147,129,145,146,\n"
-" 208,195,194,192,193,211,210,209,\n"
-" 21, 22, 23, 5, 4, 6, 7, 20,\n"
-" 86, 85, 69, 87, 70, 68, 84, 71,\n"
-" 151,133,149,150,135,148,132,134,\n"
-" 197,27,214,213,212,199,198,196\n"
-" \n"
-"};\n"
-"#define USE_SPATIAL_BATCHING 1\n"
-"#define USE_4x4_GRID 1\n"
-"__kernel\n"
-"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
-"void SetSortDataKernel(__global struct b3Contact4Data* gContact, __global Body* gBodies, __global int2* gSortDataOut, \n"
-"int nContacts,float scale,int4 nSplit,int staticIdx)\n"
-"{\n"
-" int gIdx = GET_GLOBAL_IDX;\n"
-" \n"
-" if( gIdx < nContacts )\n"
-" {\n"
-" int aPtrAndSignBit = gContact[gIdx].m_bodyAPtrAndSignBit;\n"
-" int bPtrAndSignBit = gContact[gIdx].m_bodyBPtrAndSignBit;\n"
-" int aIdx = abs(aPtrAndSignBit );\n"
-" int bIdx = abs(bPtrAndSignBit);\n"
-" bool aStatic = (aPtrAndSignBit<0) ||(aPtrAndSignBit==staticIdx);\n"
-" bool bStatic = (bPtrAndSignBit<0) ||(bPtrAndSignBit==staticIdx);\n"
-"#if USE_SPATIAL_BATCHING \n"
-" int idx = (aStatic)? bIdx: aIdx;\n"
-" float4 p = gBodies[idx].m_pos;\n"
-" int xIdx = (int)((p.x-((p.x<0.f)?1.f:0.f))*scale) & (nSplit.x-1);\n"
-" int yIdx = (int)((p.y-((p.y<0.f)?1.f:0.f))*scale) & (nSplit.y-1);\n"
-" int zIdx = (int)((p.z-((p.z<0.f)?1.f:0.f))*scale) & (nSplit.z-1);\n"
-" int newIndex = (xIdx+yIdx*nSplit.x+zIdx*nSplit.x*nSplit.y);\n"
-" \n"
-"#else//USE_SPATIAL_BATCHING\n"
-" #if USE_4x4_GRID\n"
-" int aa = aIdx&3;\n"
-" int bb = bIdx&3;\n"
-" if (aStatic)\n"
-" aa = bb;\n"
-" if (bStatic)\n"
-" bb = aa;\n"
-" int gridIndex = aa + bb*4;\n"
-" int newIndex = gridTable4x4[gridIndex];\n"
-" #else//USE_4x4_GRID\n"
-" int aa = aIdx&7;\n"
-" int bb = bIdx&7;\n"
-" if (aStatic)\n"
-" aa = bb;\n"
-" if (bStatic)\n"
-" bb = aa;\n"
-" int gridIndex = aa + bb*8;\n"
-" int newIndex = gridTable8x8[gridIndex];\n"
-" #endif//USE_4x4_GRID\n"
-"#endif//USE_SPATIAL_BATCHING\n"
-" gSortDataOut[gIdx].x = newIndex;\n"
-" gSortDataOut[gIdx].y = gIdx;\n"
-" }\n"
-" else\n"
-" {\n"
-" gSortDataOut[gIdx].x = 0xffffffff;\n"
-" }\n"
-"}\n"
-"__kernel\n"
-"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
-"void CopyConstraintKernel(__global struct b3Contact4Data* gIn, __global struct b3Contact4Data* gOut, int4 cb )\n"
-"{\n"
-" int gIdx = GET_GLOBAL_IDX;\n"
-" if( gIdx < cb.x )\n"
-" {\n"
-" gOut[gIdx] = gIn[gIdx];\n"
-" }\n"
-"}\n"
-;
+static const char* solverSetup2CL =
+ "/*\n"
+ "Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
+ "This software is provided 'as-is', without any express or implied warranty.\n"
+ "In no event will the authors be held liable for any damages arising from the use of this software.\n"
+ "Permission is granted to anyone to use this software for any purpose, \n"
+ "including commercial applications, and to alter it and redistribute it freely, \n"
+ "subject to the following restrictions:\n"
+ "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
+ "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+ "3. This notice may not be removed or altered from any source distribution.\n"
+ "*/\n"
+ "//Originally written by Takahiro Harada\n"
+ "#ifndef B3_CONTACT4DATA_H\n"
+ "#define B3_CONTACT4DATA_H\n"
+ "#ifndef B3_FLOAT4_H\n"
+ "#define B3_FLOAT4_H\n"
+ "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+ "#define B3_PLATFORM_DEFINITIONS_H\n"
+ "struct MyTest\n"
+ "{\n"
+ " int bla;\n"
+ "};\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
+ "#define B3_LARGE_FLOAT 1e18f\n"
+ "#define B3_INFINITY 1e18f\n"
+ "#define b3Assert(a)\n"
+ "#define b3ConstArray(a) __global const a*\n"
+ "#define b3AtomicInc atomic_inc\n"
+ "#define b3AtomicAdd atomic_add\n"
+ "#define b3Fabs fabs\n"
+ "#define b3Sqrt native_sqrt\n"
+ "#define b3Sin native_sin\n"
+ "#define b3Cos native_cos\n"
+ "#define B3_STATIC\n"
+ "#endif\n"
+ "#endif\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ " typedef float4 b3Float4;\n"
+ " #define b3Float4ConstArg const b3Float4\n"
+ " #define b3MakeFloat4 (float4)\n"
+ " float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+ " {\n"
+ " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+ " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+ " return dot(a1, b1);\n"
+ " }\n"
+ " b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+ " {\n"
+ " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+ " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+ " return cross(a1, b1);\n"
+ " }\n"
+ " #define b3MinFloat4 min\n"
+ " #define b3MaxFloat4 max\n"
+ " #define b3Normalized(a) normalize(a)\n"
+ "#endif \n"
+ " \n"
+ "inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
+ "{\n"
+ " if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
+ " return false;\n"
+ " return true;\n"
+ "}\n"
+ "inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
+ "{\n"
+ " float maxDot = -B3_INFINITY;\n"
+ " int i = 0;\n"
+ " int ptIndex = -1;\n"
+ " for( i = 0; i < vecLen; i++ )\n"
+ " {\n"
+ " float dot = b3Dot3F4(vecArray[i],vec);\n"
+ " \n"
+ " if( dot > maxDot )\n"
+ " {\n"
+ " maxDot = dot;\n"
+ " ptIndex = i;\n"
+ " }\n"
+ " }\n"
+ " b3Assert(ptIndex>=0);\n"
+ " if (ptIndex<0)\n"
+ " {\n"
+ " ptIndex = 0;\n"
+ " }\n"
+ " *dotOut = maxDot;\n"
+ " return ptIndex;\n"
+ "}\n"
+ "#endif //B3_FLOAT4_H\n"
+ "typedef struct b3Contact4Data b3Contact4Data_t;\n"
+ "struct b3Contact4Data\n"
+ "{\n"
+ " b3Float4 m_worldPosB[4];\n"
+ "// b3Float4 m_localPosA[4];\n"
+ "// b3Float4 m_localPosB[4];\n"
+ " b3Float4 m_worldNormalOnB; // w: m_nPoints\n"
+ " unsigned short m_restituitionCoeffCmp;\n"
+ " unsigned short m_frictionCoeffCmp;\n"
+ " int m_batchIdx;\n"
+ " int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
+ " int m_bodyBPtrAndSignBit;\n"
+ " int m_childIndexA;\n"
+ " int m_childIndexB;\n"
+ " int m_unused1;\n"
+ " int m_unused2;\n"
+ "};\n"
+ "inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
+ "{\n"
+ " return (int)contact->m_worldNormalOnB.w;\n"
+ "};\n"
+ "inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
+ "{\n"
+ " contact->m_worldNormalOnB.w = (float)numPoints;\n"
+ "};\n"
+ "#endif //B3_CONTACT4DATA_H\n"
+ "#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
+ "#ifdef cl_ext_atomic_counters_32\n"
+ "#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
+ "#else\n"
+ "#define counter32_t volatile global int*\n"
+ "#endif\n"
+ "typedef unsigned int u32;\n"
+ "typedef unsigned short u16;\n"
+ "typedef unsigned char u8;\n"
+ "#define GET_GROUP_IDX get_group_id(0)\n"
+ "#define GET_LOCAL_IDX get_local_id(0)\n"
+ "#define GET_GLOBAL_IDX get_global_id(0)\n"
+ "#define GET_GROUP_SIZE get_local_size(0)\n"
+ "#define GET_NUM_GROUPS get_num_groups(0)\n"
+ "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+ "#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
+ "#define AtomInc(x) atom_inc(&(x))\n"
+ "#define AtomInc1(x, out) out = atom_inc(&(x))\n"
+ "#define AppendInc(x, out) out = atomic_inc(x)\n"
+ "#define AtomAdd(x, value) atom_add(&(x), value)\n"
+ "#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
+ "#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
+ "#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
+ "#define make_float4 (float4)\n"
+ "#define make_float2 (float2)\n"
+ "#define make_uint4 (uint4)\n"
+ "#define make_int4 (int4)\n"
+ "#define make_uint2 (uint2)\n"
+ "#define make_int2 (int2)\n"
+ "#define max2 max\n"
+ "#define min2 min\n"
+ "///////////////////////////////////////\n"
+ "// Vector\n"
+ "///////////////////////////////////////\n"
+ "__inline\n"
+ "float fastDiv(float numerator, float denominator)\n"
+ "{\n"
+ " return native_divide(numerator, denominator); \n"
+ "// return numerator/denominator; \n"
+ "}\n"
+ "__inline\n"
+ "float4 fastDiv4(float4 numerator, float4 denominator)\n"
+ "{\n"
+ " return native_divide(numerator, denominator); \n"
+ "}\n"
+ "__inline\n"
+ "float fastSqrtf(float f2)\n"
+ "{\n"
+ " return native_sqrt(f2);\n"
+ "// return sqrt(f2);\n"
+ "}\n"
+ "__inline\n"
+ "float fastRSqrt(float f2)\n"
+ "{\n"
+ " return native_rsqrt(f2);\n"
+ "}\n"
+ "__inline\n"
+ "float fastLength4(float4 v)\n"
+ "{\n"
+ " return fast_length(v);\n"
+ "}\n"
+ "__inline\n"
+ "float4 fastNormalize4(float4 v)\n"
+ "{\n"
+ " return fast_normalize(v);\n"
+ "}\n"
+ "__inline\n"
+ "float sqrtf(float a)\n"
+ "{\n"
+ "// return sqrt(a);\n"
+ " return native_sqrt(a);\n"
+ "}\n"
+ "__inline\n"
+ "float4 cross3(float4 a, float4 b)\n"
+ "{\n"
+ " return cross(a,b);\n"
+ "}\n"
+ "__inline\n"
+ "float dot3F4(float4 a, float4 b)\n"
+ "{\n"
+ " float4 a1 = make_float4(a.xyz,0.f);\n"
+ " float4 b1 = make_float4(b.xyz,0.f);\n"
+ " return dot(a1, b1);\n"
+ "}\n"
+ "__inline\n"
+ "float length3(const float4 a)\n"
+ "{\n"
+ " return sqrtf(dot3F4(a,a));\n"
+ "}\n"
+ "__inline\n"
+ "float dot4(const float4 a, const float4 b)\n"
+ "{\n"
+ " return dot( a, b );\n"
+ "}\n"
+ "// for height\n"
+ "__inline\n"
+ "float dot3w1(const float4 point, const float4 eqn)\n"
+ "{\n"
+ " return dot3F4(point,eqn) + eqn.w;\n"
+ "}\n"
+ "__inline\n"
+ "float4 normalize3(const float4 a)\n"
+ "{\n"
+ " float4 n = make_float4(a.x, a.y, a.z, 0.f);\n"
+ " return fastNormalize4( n );\n"
+ "// float length = sqrtf(dot3F4(a, a));\n"
+ "// return 1.f/length * a;\n"
+ "}\n"
+ "__inline\n"
+ "float4 normalize4(const float4 a)\n"
+ "{\n"
+ " float length = sqrtf(dot4(a, a));\n"
+ " return 1.f/length * a;\n"
+ "}\n"
+ "__inline\n"
+ "float4 createEquation(const float4 a, const float4 b, const float4 c)\n"
+ "{\n"
+ " float4 eqn;\n"
+ " float4 ab = b-a;\n"
+ " float4 ac = c-a;\n"
+ " eqn = normalize3( cross3(ab, ac) );\n"
+ " eqn.w = -dot3F4(eqn,a);\n"
+ " return eqn;\n"
+ "}\n"
+ "///////////////////////////////////////\n"
+ "// Matrix3x3\n"
+ "///////////////////////////////////////\n"
+ "typedef struct\n"
+ "{\n"
+ " float4 m_row[3];\n"
+ "}Matrix3x3;\n"
+ "__inline\n"
+ "Matrix3x3 mtZero();\n"
+ "__inline\n"
+ "Matrix3x3 mtIdentity();\n"
+ "__inline\n"
+ "Matrix3x3 mtTranspose(Matrix3x3 m);\n"
+ "__inline\n"
+ "Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b);\n"
+ "__inline\n"
+ "float4 mtMul1(Matrix3x3 a, float4 b);\n"
+ "__inline\n"
+ "float4 mtMul3(float4 a, Matrix3x3 b);\n"
+ "__inline\n"
+ "Matrix3x3 mtZero()\n"
+ "{\n"
+ " Matrix3x3 m;\n"
+ " m.m_row[0] = (float4)(0.f);\n"
+ " m.m_row[1] = (float4)(0.f);\n"
+ " m.m_row[2] = (float4)(0.f);\n"
+ " return m;\n"
+ "}\n"
+ "__inline\n"
+ "Matrix3x3 mtIdentity()\n"
+ "{\n"
+ " Matrix3x3 m;\n"
+ " m.m_row[0] = (float4)(1,0,0,0);\n"
+ " m.m_row[1] = (float4)(0,1,0,0);\n"
+ " m.m_row[2] = (float4)(0,0,1,0);\n"
+ " return m;\n"
+ "}\n"
+ "__inline\n"
+ "Matrix3x3 mtTranspose(Matrix3x3 m)\n"
+ "{\n"
+ " Matrix3x3 out;\n"
+ " out.m_row[0] = (float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
+ " out.m_row[1] = (float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
+ " out.m_row[2] = (float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
+ " return out;\n"
+ "}\n"
+ "__inline\n"
+ "Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b)\n"
+ "{\n"
+ " Matrix3x3 transB;\n"
+ " transB = mtTranspose( b );\n"
+ " Matrix3x3 ans;\n"
+ " // why this doesn't run when 0ing in the for{}\n"
+ " a.m_row[0].w = 0.f;\n"
+ " a.m_row[1].w = 0.f;\n"
+ " a.m_row[2].w = 0.f;\n"
+ " for(int i=0; i<3; i++)\n"
+ " {\n"
+ "// a.m_row[i].w = 0.f;\n"
+ " ans.m_row[i].x = dot3F4(a.m_row[i],transB.m_row[0]);\n"
+ " ans.m_row[i].y = dot3F4(a.m_row[i],transB.m_row[1]);\n"
+ " ans.m_row[i].z = dot3F4(a.m_row[i],transB.m_row[2]);\n"
+ " ans.m_row[i].w = 0.f;\n"
+ " }\n"
+ " return ans;\n"
+ "}\n"
+ "__inline\n"
+ "float4 mtMul1(Matrix3x3 a, float4 b)\n"
+ "{\n"
+ " float4 ans;\n"
+ " ans.x = dot3F4( a.m_row[0], b );\n"
+ " ans.y = dot3F4( a.m_row[1], b );\n"
+ " ans.z = dot3F4( a.m_row[2], b );\n"
+ " ans.w = 0.f;\n"
+ " return ans;\n"
+ "}\n"
+ "__inline\n"
+ "float4 mtMul3(float4 a, Matrix3x3 b)\n"
+ "{\n"
+ " float4 colx = make_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
+ " float4 coly = make_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
+ " float4 colz = make_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
+ " float4 ans;\n"
+ " ans.x = dot3F4( a, colx );\n"
+ " ans.y = dot3F4( a, coly );\n"
+ " ans.z = dot3F4( a, colz );\n"
+ " return ans;\n"
+ "}\n"
+ "///////////////////////////////////////\n"
+ "// Quaternion\n"
+ "///////////////////////////////////////\n"
+ "typedef float4 Quaternion;\n"
+ "__inline\n"
+ "Quaternion qtMul(Quaternion a, Quaternion b);\n"
+ "__inline\n"
+ "Quaternion qtNormalize(Quaternion in);\n"
+ "__inline\n"
+ "float4 qtRotate(Quaternion q, float4 vec);\n"
+ "__inline\n"
+ "Quaternion qtInvert(Quaternion q);\n"
+ "__inline\n"
+ "Quaternion qtMul(Quaternion a, Quaternion b)\n"
+ "{\n"
+ " Quaternion ans;\n"
+ " ans = cross3( a, b );\n"
+ " ans += a.w*b+b.w*a;\n"
+ "// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+ " ans.w = a.w*b.w - dot3F4(a, b);\n"
+ " return ans;\n"
+ "}\n"
+ "__inline\n"
+ "Quaternion qtNormalize(Quaternion in)\n"
+ "{\n"
+ " return fastNormalize4(in);\n"
+ "// in /= length( in );\n"
+ "// return in;\n"
+ "}\n"
+ "__inline\n"
+ "float4 qtRotate(Quaternion q, float4 vec)\n"
+ "{\n"
+ " Quaternion qInv = qtInvert( q );\n"
+ " float4 vcpy = vec;\n"
+ " vcpy.w = 0.f;\n"
+ " float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
+ " return out;\n"
+ "}\n"
+ "__inline\n"
+ "Quaternion qtInvert(Quaternion q)\n"
+ "{\n"
+ " return (Quaternion)(-q.xyz, q.w);\n"
+ "}\n"
+ "__inline\n"
+ "float4 qtInvRotate(const Quaternion q, float4 vec)\n"
+ "{\n"
+ " return qtRotate( qtInvert( q ), vec );\n"
+ "}\n"
+ "#define WG_SIZE 64\n"
+ "typedef struct\n"
+ "{\n"
+ " float4 m_pos;\n"
+ " Quaternion m_quat;\n"
+ " float4 m_linVel;\n"
+ " float4 m_angVel;\n"
+ " u32 m_shapeIdx;\n"
+ " float m_invMass;\n"
+ " float m_restituitionCoeff;\n"
+ " float m_frictionCoeff;\n"
+ "} Body;\n"
+ "typedef struct\n"
+ "{\n"
+ " Matrix3x3 m_invInertia;\n"
+ " Matrix3x3 m_initInvInertia;\n"
+ "} Shape;\n"
+ "typedef struct\n"
+ "{\n"
+ " float4 m_linear;\n"
+ " float4 m_worldPos[4];\n"
+ " float4 m_center; \n"
+ " float m_jacCoeffInv[4];\n"
+ " float m_b[4];\n"
+ " float m_appliedRambdaDt[4];\n"
+ " float m_fJacCoeffInv[2]; \n"
+ " float m_fAppliedRambdaDt[2]; \n"
+ " u32 m_bodyA;\n"
+ " u32 m_bodyB;\n"
+ " int m_batchIdx;\n"
+ " u32 m_paddings[1];\n"
+ "} Constraint4;\n"
+ "typedef struct\n"
+ "{\n"
+ " int m_nConstraints;\n"
+ " int m_start;\n"
+ " int m_batchIdx;\n"
+ " int m_nSplit;\n"
+ "// int m_paddings[1];\n"
+ "} ConstBuffer;\n"
+ "typedef struct\n"
+ "{\n"
+ " int m_solveFriction;\n"
+ " int m_maxBatch; // long batch really kills the performance\n"
+ " int m_batchIdx;\n"
+ " int m_nSplit;\n"
+ "// int m_paddings[1];\n"
+ "} ConstBufferBatchSolve;\n"
+ " \n"
+ "typedef struct \n"
+ "{\n"
+ " int m_valInt0;\n"
+ " int m_valInt1;\n"
+ " int m_valInt2;\n"
+ " int m_valInt3;\n"
+ " float m_val0;\n"
+ " float m_val1;\n"
+ " float m_val2;\n"
+ " float m_val3;\n"
+ "} SolverDebugInfo;\n"
+ "// others\n"
+ "__kernel\n"
+ "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+ "void ReorderContactKernel(__global struct b3Contact4Data* in, __global struct b3Contact4Data* out, __global int2* sortData, int4 cb )\n"
+ "{\n"
+ " int nContacts = cb.x;\n"
+ " int gIdx = GET_GLOBAL_IDX;\n"
+ " if( gIdx < nContacts )\n"
+ " {\n"
+ " int srcIdx = sortData[gIdx].y;\n"
+ " out[gIdx] = in[srcIdx];\n"
+ " }\n"
+ "}\n"
+ "__kernel __attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+ "void SetDeterminismSortDataChildShapeB(__global struct b3Contact4Data* contactsIn, __global int2* sortDataOut, int nContacts)\n"
+ "{\n"
+ " int gIdx = GET_GLOBAL_IDX;\n"
+ " if( gIdx < nContacts )\n"
+ " {\n"
+ " int2 sd;\n"
+ " sd.x = contactsIn[gIdx].m_childIndexB;\n"
+ " sd.y = gIdx;\n"
+ " sortDataOut[gIdx] = sd;\n"
+ " }\n"
+ "}\n"
+ "__kernel __attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+ "void SetDeterminismSortDataChildShapeA(__global struct b3Contact4Data* contactsIn, __global int2* sortDataInOut, int nContacts)\n"
+ "{\n"
+ " int gIdx = GET_GLOBAL_IDX;\n"
+ " if( gIdx < nContacts )\n"
+ " {\n"
+ " int2 sdIn;\n"
+ " sdIn = sortDataInOut[gIdx];\n"
+ " int2 sdOut;\n"
+ " sdOut.x = contactsIn[sdIn.y].m_childIndexA;\n"
+ " sdOut.y = sdIn.y;\n"
+ " sortDataInOut[gIdx] = sdOut;\n"
+ " }\n"
+ "}\n"
+ "__kernel __attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+ "void SetDeterminismSortDataBodyA(__global struct b3Contact4Data* contactsIn, __global int2* sortDataInOut, int nContacts)\n"
+ "{\n"
+ " int gIdx = GET_GLOBAL_IDX;\n"
+ " if( gIdx < nContacts )\n"
+ " {\n"
+ " int2 sdIn;\n"
+ " sdIn = sortDataInOut[gIdx];\n"
+ " int2 sdOut;\n"
+ " sdOut.x = contactsIn[sdIn.y].m_bodyAPtrAndSignBit;\n"
+ " sdOut.y = sdIn.y;\n"
+ " sortDataInOut[gIdx] = sdOut;\n"
+ " }\n"
+ "}\n"
+ "__kernel\n"
+ "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+ "void SetDeterminismSortDataBodyB(__global struct b3Contact4Data* contactsIn, __global int2* sortDataInOut, int nContacts)\n"
+ "{\n"
+ " int gIdx = GET_GLOBAL_IDX;\n"
+ " if( gIdx < nContacts )\n"
+ " {\n"
+ " int2 sdIn;\n"
+ " sdIn = sortDataInOut[gIdx];\n"
+ " int2 sdOut;\n"
+ " sdOut.x = contactsIn[sdIn.y].m_bodyBPtrAndSignBit;\n"
+ " sdOut.y = sdIn.y;\n"
+ " sortDataInOut[gIdx] = sdOut;\n"
+ " }\n"
+ "}\n"
+ "typedef struct\n"
+ "{\n"
+ " int m_nContacts;\n"
+ " int m_staticIdx;\n"
+ " float m_scale;\n"
+ " int m_nSplit;\n"
+ "} ConstBufferSSD;\n"
+ "__constant const int gridTable4x4[] = \n"
+ "{\n"
+ " 0,1,17,16,\n"
+ " 1,2,18,19,\n"
+ " 17,18,32,3,\n"
+ " 16,19,3,34\n"
+ "};\n"
+ "__constant const int gridTable8x8[] = \n"
+ "{\n"
+ " 0, 2, 3, 16, 17, 18, 19, 1,\n"
+ " 66, 64, 80, 67, 82, 81, 65, 83,\n"
+ " 131,144,128,130,147,129,145,146,\n"
+ " 208,195,194,192,193,211,210,209,\n"
+ " 21, 22, 23, 5, 4, 6, 7, 20,\n"
+ " 86, 85, 69, 87, 70, 68, 84, 71,\n"
+ " 151,133,149,150,135,148,132,134,\n"
+ " 197,27,214,213,212,199,198,196\n"
+ " \n"
+ "};\n"
+ "#define USE_SPATIAL_BATCHING 1\n"
+ "#define USE_4x4_GRID 1\n"
+ "__kernel\n"
+ "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+ "void SetSortDataKernel(__global struct b3Contact4Data* gContact, __global Body* gBodies, __global int2* gSortDataOut, \n"
+ "int nContacts,float scale,int4 nSplit,int staticIdx)\n"
+ "{\n"
+ " int gIdx = GET_GLOBAL_IDX;\n"
+ " \n"
+ " if( gIdx < nContacts )\n"
+ " {\n"
+ " int aPtrAndSignBit = gContact[gIdx].m_bodyAPtrAndSignBit;\n"
+ " int bPtrAndSignBit = gContact[gIdx].m_bodyBPtrAndSignBit;\n"
+ " int aIdx = abs(aPtrAndSignBit );\n"
+ " int bIdx = abs(bPtrAndSignBit);\n"
+ " bool aStatic = (aPtrAndSignBit<0) ||(aPtrAndSignBit==staticIdx);\n"
+ " bool bStatic = (bPtrAndSignBit<0) ||(bPtrAndSignBit==staticIdx);\n"
+ "#if USE_SPATIAL_BATCHING \n"
+ " int idx = (aStatic)? bIdx: aIdx;\n"
+ " float4 p = gBodies[idx].m_pos;\n"
+ " int xIdx = (int)((p.x-((p.x<0.f)?1.f:0.f))*scale) & (nSplit.x-1);\n"
+ " int yIdx = (int)((p.y-((p.y<0.f)?1.f:0.f))*scale) & (nSplit.y-1);\n"
+ " int zIdx = (int)((p.z-((p.z<0.f)?1.f:0.f))*scale) & (nSplit.z-1);\n"
+ " int newIndex = (xIdx+yIdx*nSplit.x+zIdx*nSplit.x*nSplit.y);\n"
+ " \n"
+ "#else//USE_SPATIAL_BATCHING\n"
+ " #if USE_4x4_GRID\n"
+ " int aa = aIdx&3;\n"
+ " int bb = bIdx&3;\n"
+ " if (aStatic)\n"
+ " aa = bb;\n"
+ " if (bStatic)\n"
+ " bb = aa;\n"
+ " int gridIndex = aa + bb*4;\n"
+ " int newIndex = gridTable4x4[gridIndex];\n"
+ " #else//USE_4x4_GRID\n"
+ " int aa = aIdx&7;\n"
+ " int bb = bIdx&7;\n"
+ " if (aStatic)\n"
+ " aa = bb;\n"
+ " if (bStatic)\n"
+ " bb = aa;\n"
+ " int gridIndex = aa + bb*8;\n"
+ " int newIndex = gridTable8x8[gridIndex];\n"
+ " #endif//USE_4x4_GRID\n"
+ "#endif//USE_SPATIAL_BATCHING\n"
+ " gSortDataOut[gIdx].x = newIndex;\n"
+ " gSortDataOut[gIdx].y = gIdx;\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " gSortDataOut[gIdx].x = 0xffffffff;\n"
+ " }\n"
+ "}\n"
+ "__kernel\n"
+ "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+ "void CopyConstraintKernel(__global struct b3Contact4Data* gIn, __global struct b3Contact4Data* gOut, int4 cb )\n"
+ "{\n"
+ " int gIdx = GET_GLOBAL_IDX;\n"
+ " if( gIdx < cb.x )\n"
+ " {\n"
+ " gOut[gIdx] = gIn[gIdx];\n"
+ " }\n"
+ "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solverUtils.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solverUtils.h
index c0173ad9f4..f4d98d9941 100644
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solverUtils.h
+++ b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solverUtils.h
@@ -1,909 +1,908 @@
//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* solverUtilsCL= \
-"/*\n"
-"Copyright (c) 2013 Advanced Micro Devices, Inc. \n"
-"This software is provided 'as-is', without any express or implied warranty.\n"
-"In no event will the authors be held liable for any damages arising from the use of this software.\n"
-"Permission is granted to anyone to use this software for any purpose, \n"
-"including commercial applications, and to alter it and redistribute it freely, \n"
-"subject to the following restrictions:\n"
-"1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
-"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
-"3. This notice may not be removed or altered from any source distribution.\n"
-"*/\n"
-"//Originally written by Erwin Coumans\n"
-"#ifndef B3_CONTACT4DATA_H\n"
-"#define B3_CONTACT4DATA_H\n"
-"#ifndef B3_FLOAT4_H\n"
-"#define B3_FLOAT4_H\n"
-"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
-"#define B3_PLATFORM_DEFINITIONS_H\n"
-"struct MyTest\n"
-"{\n"
-" int bla;\n"
-"};\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
-"#define B3_LARGE_FLOAT 1e18f\n"
-"#define B3_INFINITY 1e18f\n"
-"#define b3Assert(a)\n"
-"#define b3ConstArray(a) __global const a*\n"
-"#define b3AtomicInc atomic_inc\n"
-"#define b3AtomicAdd atomic_add\n"
-"#define b3Fabs fabs\n"
-"#define b3Sqrt native_sqrt\n"
-"#define b3Sin native_sin\n"
-"#define b3Cos native_cos\n"
-"#define B3_STATIC\n"
-"#endif\n"
-"#endif\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-" typedef float4 b3Float4;\n"
-" #define b3Float4ConstArg const b3Float4\n"
-" #define b3MakeFloat4 (float4)\n"
-" float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
-" {\n"
-" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
-" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
-" return dot(a1, b1);\n"
-" }\n"
-" b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
-" {\n"
-" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
-" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
-" return cross(a1, b1);\n"
-" }\n"
-" #define b3MinFloat4 min\n"
-" #define b3MaxFloat4 max\n"
-" #define b3Normalized(a) normalize(a)\n"
-"#endif \n"
-" \n"
-"inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
-"{\n"
-" if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
-" return false;\n"
-" return true;\n"
-"}\n"
-"inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
-"{\n"
-" float maxDot = -B3_INFINITY;\n"
-" int i = 0;\n"
-" int ptIndex = -1;\n"
-" for( i = 0; i < vecLen; i++ )\n"
-" {\n"
-" float dot = b3Dot3F4(vecArray[i],vec);\n"
-" \n"
-" if( dot > maxDot )\n"
-" {\n"
-" maxDot = dot;\n"
-" ptIndex = i;\n"
-" }\n"
-" }\n"
-" b3Assert(ptIndex>=0);\n"
-" if (ptIndex<0)\n"
-" {\n"
-" ptIndex = 0;\n"
-" }\n"
-" *dotOut = maxDot;\n"
-" return ptIndex;\n"
-"}\n"
-"#endif //B3_FLOAT4_H\n"
-"typedef struct b3Contact4Data b3Contact4Data_t;\n"
-"struct b3Contact4Data\n"
-"{\n"
-" b3Float4 m_worldPosB[4];\n"
-"// b3Float4 m_localPosA[4];\n"
-"// b3Float4 m_localPosB[4];\n"
-" b3Float4 m_worldNormalOnB; // w: m_nPoints\n"
-" unsigned short m_restituitionCoeffCmp;\n"
-" unsigned short m_frictionCoeffCmp;\n"
-" int m_batchIdx;\n"
-" int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
-" int m_bodyBPtrAndSignBit;\n"
-" int m_childIndexA;\n"
-" int m_childIndexB;\n"
-" int m_unused1;\n"
-" int m_unused2;\n"
-"};\n"
-"inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
-"{\n"
-" return (int)contact->m_worldNormalOnB.w;\n"
-"};\n"
-"inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
-"{\n"
-" contact->m_worldNormalOnB.w = (float)numPoints;\n"
-"};\n"
-"#endif //B3_CONTACT4DATA_H\n"
-"#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
-"#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
-"#ifdef cl_ext_atomic_counters_32\n"
-"#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
-"#else\n"
-"#define counter32_t volatile global int*\n"
-"#endif\n"
-"typedef unsigned int u32;\n"
-"typedef unsigned short u16;\n"
-"typedef unsigned char u8;\n"
-"#define GET_GROUP_IDX get_group_id(0)\n"
-"#define GET_LOCAL_IDX get_local_id(0)\n"
-"#define GET_GLOBAL_IDX get_global_id(0)\n"
-"#define GET_GROUP_SIZE get_local_size(0)\n"
-"#define GET_NUM_GROUPS get_num_groups(0)\n"
-"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
-"#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
-"#define AtomInc(x) atom_inc(&(x))\n"
-"#define AtomInc1(x, out) out = atom_inc(&(x))\n"
-"#define AppendInc(x, out) out = atomic_inc(x)\n"
-"#define AtomAdd(x, value) atom_add(&(x), value)\n"
-"#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
-"#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
-"#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
-"#define make_float4 (float4)\n"
-"#define make_float2 (float2)\n"
-"#define make_uint4 (uint4)\n"
-"#define make_int4 (int4)\n"
-"#define make_uint2 (uint2)\n"
-"#define make_int2 (int2)\n"
-"#define max2 max\n"
-"#define min2 min\n"
-"///////////////////////////////////////\n"
-"// Vector\n"
-"///////////////////////////////////////\n"
-"__inline\n"
-"float fastDiv(float numerator, float denominator)\n"
-"{\n"
-" return native_divide(numerator, denominator); \n"
-"// return numerator/denominator; \n"
-"}\n"
-"__inline\n"
-"float4 fastDiv4(float4 numerator, float4 denominator)\n"
-"{\n"
-" return native_divide(numerator, denominator); \n"
-"}\n"
-"__inline\n"
-"float fastSqrtf(float f2)\n"
-"{\n"
-" return native_sqrt(f2);\n"
-"// return sqrt(f2);\n"
-"}\n"
-"__inline\n"
-"float fastRSqrt(float f2)\n"
-"{\n"
-" return native_rsqrt(f2);\n"
-"}\n"
-"__inline\n"
-"float fastLength4(float4 v)\n"
-"{\n"
-" return fast_length(v);\n"
-"}\n"
-"__inline\n"
-"float4 fastNormalize4(float4 v)\n"
-"{\n"
-" return fast_normalize(v);\n"
-"}\n"
-"__inline\n"
-"float sqrtf(float a)\n"
-"{\n"
-"// return sqrt(a);\n"
-" return native_sqrt(a);\n"
-"}\n"
-"__inline\n"
-"float4 cross3(float4 a1, float4 b1)\n"
-"{\n"
-" float4 a=make_float4(a1.xyz,0.f);\n"
-" float4 b=make_float4(b1.xyz,0.f);\n"
-" //float4 a=a1;\n"
-" //float4 b=b1;\n"
-" return cross(a,b);\n"
-"}\n"
-"__inline\n"
-"float dot3F4(float4 a, float4 b)\n"
-"{\n"
-" float4 a1 = make_float4(a.xyz,0.f);\n"
-" float4 b1 = make_float4(b.xyz,0.f);\n"
-" return dot(a1, b1);\n"
-"}\n"
-"__inline\n"
-"float length3(const float4 a)\n"
-"{\n"
-" return sqrtf(dot3F4(a,a));\n"
-"}\n"
-"__inline\n"
-"float dot4(const float4 a, const float4 b)\n"
-"{\n"
-" return dot( a, b );\n"
-"}\n"
-"// for height\n"
-"__inline\n"
-"float dot3w1(const float4 point, const float4 eqn)\n"
-"{\n"
-" return dot3F4(point,eqn) + eqn.w;\n"
-"}\n"
-"__inline\n"
-"float4 normalize3(const float4 a)\n"
-"{\n"
-" float4 n = make_float4(a.x, a.y, a.z, 0.f);\n"
-" return fastNormalize4( n );\n"
-"// float length = sqrtf(dot3F4(a, a));\n"
-"// return 1.f/length * a;\n"
-"}\n"
-"__inline\n"
-"float4 normalize4(const float4 a)\n"
-"{\n"
-" float length = sqrtf(dot4(a, a));\n"
-" return 1.f/length * a;\n"
-"}\n"
-"__inline\n"
-"float4 createEquation(const float4 a, const float4 b, const float4 c)\n"
-"{\n"
-" float4 eqn;\n"
-" float4 ab = b-a;\n"
-" float4 ac = c-a;\n"
-" eqn = normalize3( cross3(ab, ac) );\n"
-" eqn.w = -dot3F4(eqn,a);\n"
-" return eqn;\n"
-"}\n"
-"///////////////////////////////////////\n"
-"// Matrix3x3\n"
-"///////////////////////////////////////\n"
-"typedef struct\n"
-"{\n"
-" float4 m_row[3];\n"
-"}Matrix3x3;\n"
-"__inline\n"
-"Matrix3x3 mtZero();\n"
-"__inline\n"
-"Matrix3x3 mtIdentity();\n"
-"__inline\n"
-"Matrix3x3 mtTranspose(Matrix3x3 m);\n"
-"__inline\n"
-"Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b);\n"
-"__inline\n"
-"float4 mtMul1(Matrix3x3 a, float4 b);\n"
-"__inline\n"
-"float4 mtMul3(float4 a, Matrix3x3 b);\n"
-"__inline\n"
-"Matrix3x3 mtZero()\n"
-"{\n"
-" Matrix3x3 m;\n"
-" m.m_row[0] = (float4)(0.f);\n"
-" m.m_row[1] = (float4)(0.f);\n"
-" m.m_row[2] = (float4)(0.f);\n"
-" return m;\n"
-"}\n"
-"__inline\n"
-"Matrix3x3 mtIdentity()\n"
-"{\n"
-" Matrix3x3 m;\n"
-" m.m_row[0] = (float4)(1,0,0,0);\n"
-" m.m_row[1] = (float4)(0,1,0,0);\n"
-" m.m_row[2] = (float4)(0,0,1,0);\n"
-" return m;\n"
-"}\n"
-"__inline\n"
-"Matrix3x3 mtTranspose(Matrix3x3 m)\n"
-"{\n"
-" Matrix3x3 out;\n"
-" out.m_row[0] = (float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
-" out.m_row[1] = (float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
-" out.m_row[2] = (float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
-" return out;\n"
-"}\n"
-"__inline\n"
-"Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b)\n"
-"{\n"
-" Matrix3x3 transB;\n"
-" transB = mtTranspose( b );\n"
-" Matrix3x3 ans;\n"
-" // why this doesn't run when 0ing in the for{}\n"
-" a.m_row[0].w = 0.f;\n"
-" a.m_row[1].w = 0.f;\n"
-" a.m_row[2].w = 0.f;\n"
-" for(int i=0; i<3; i++)\n"
-" {\n"
-"// a.m_row[i].w = 0.f;\n"
-" ans.m_row[i].x = dot3F4(a.m_row[i],transB.m_row[0]);\n"
-" ans.m_row[i].y = dot3F4(a.m_row[i],transB.m_row[1]);\n"
-" ans.m_row[i].z = dot3F4(a.m_row[i],transB.m_row[2]);\n"
-" ans.m_row[i].w = 0.f;\n"
-" }\n"
-" return ans;\n"
-"}\n"
-"__inline\n"
-"float4 mtMul1(Matrix3x3 a, float4 b)\n"
-"{\n"
-" float4 ans;\n"
-" ans.x = dot3F4( a.m_row[0], b );\n"
-" ans.y = dot3F4( a.m_row[1], b );\n"
-" ans.z = dot3F4( a.m_row[2], b );\n"
-" ans.w = 0.f;\n"
-" return ans;\n"
-"}\n"
-"__inline\n"
-"float4 mtMul3(float4 a, Matrix3x3 b)\n"
-"{\n"
-" float4 colx = make_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
-" float4 coly = make_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
-" float4 colz = make_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
-" float4 ans;\n"
-" ans.x = dot3F4( a, colx );\n"
-" ans.y = dot3F4( a, coly );\n"
-" ans.z = dot3F4( a, colz );\n"
-" return ans;\n"
-"}\n"
-"///////////////////////////////////////\n"
-"// Quaternion\n"
-"///////////////////////////////////////\n"
-"typedef float4 Quaternion;\n"
-"__inline\n"
-"Quaternion qtMul(Quaternion a, Quaternion b);\n"
-"__inline\n"
-"Quaternion qtNormalize(Quaternion in);\n"
-"__inline\n"
-"float4 qtRotate(Quaternion q, float4 vec);\n"
-"__inline\n"
-"Quaternion qtInvert(Quaternion q);\n"
-"__inline\n"
-"Quaternion qtMul(Quaternion a, Quaternion b)\n"
-"{\n"
-" Quaternion ans;\n"
-" ans = cross3( a, b );\n"
-" ans += a.w*b+b.w*a;\n"
-"// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
-" ans.w = a.w*b.w - dot3F4(a, b);\n"
-" return ans;\n"
-"}\n"
-"__inline\n"
-"Quaternion qtNormalize(Quaternion in)\n"
-"{\n"
-" return fastNormalize4(in);\n"
-"// in /= length( in );\n"
-"// return in;\n"
-"}\n"
-"__inline\n"
-"float4 qtRotate(Quaternion q, float4 vec)\n"
-"{\n"
-" Quaternion qInv = qtInvert( q );\n"
-" float4 vcpy = vec;\n"
-" vcpy.w = 0.f;\n"
-" float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
-" return out;\n"
-"}\n"
-"__inline\n"
-"Quaternion qtInvert(Quaternion q)\n"
-"{\n"
-" return (Quaternion)(-q.xyz, q.w);\n"
-"}\n"
-"__inline\n"
-"float4 qtInvRotate(const Quaternion q, float4 vec)\n"
-"{\n"
-" return qtRotate( qtInvert( q ), vec );\n"
-"}\n"
-"#define WG_SIZE 64\n"
-"typedef struct\n"
-"{\n"
-" float4 m_pos;\n"
-" Quaternion m_quat;\n"
-" float4 m_linVel;\n"
-" float4 m_angVel;\n"
-" u32 m_shapeIdx;\n"
-" float m_invMass;\n"
-" float m_restituitionCoeff;\n"
-" float m_frictionCoeff;\n"
-"} Body;\n"
-"typedef struct\n"
-"{\n"
-" Matrix3x3 m_invInertia;\n"
-" Matrix3x3 m_initInvInertia;\n"
-"} Shape;\n"
-"typedef struct\n"
-"{\n"
-" float4 m_linear;\n"
-" float4 m_worldPos[4];\n"
-" float4 m_center; \n"
-" float m_jacCoeffInv[4];\n"
-" float m_b[4];\n"
-" float m_appliedRambdaDt[4];\n"
-" float m_fJacCoeffInv[2]; \n"
-" float m_fAppliedRambdaDt[2]; \n"
-" u32 m_bodyA;\n"
-" u32 m_bodyB;\n"
-" int m_batchIdx;\n"
-" u32 m_paddings;\n"
-"} Constraint4;\n"
-"__kernel void CountBodiesKernel(__global struct b3Contact4Data* manifoldPtr, __global unsigned int* bodyCount, __global int2* contactConstraintOffsets, int numContactManifolds, int fixedBodyIndex)\n"
-"{\n"
-" int i = GET_GLOBAL_IDX;\n"
-" \n"
-" if( i < numContactManifolds)\n"
-" {\n"
-" int pa = manifoldPtr[i].m_bodyAPtrAndSignBit;\n"
-" bool isFixedA = (pa <0) || (pa == fixedBodyIndex);\n"
-" int bodyIndexA = abs(pa);\n"
-" if (!isFixedA)\n"
-" {\n"
-" AtomInc1(bodyCount[bodyIndexA],contactConstraintOffsets[i].x);\n"
-" }\n"
-" barrier(CLK_GLOBAL_MEM_FENCE);\n"
-" int pb = manifoldPtr[i].m_bodyBPtrAndSignBit;\n"
-" bool isFixedB = (pb <0) || (pb == fixedBodyIndex);\n"
-" int bodyIndexB = abs(pb);\n"
-" if (!isFixedB)\n"
-" {\n"
-" AtomInc1(bodyCount[bodyIndexB],contactConstraintOffsets[i].y);\n"
-" } \n"
-" }\n"
-"}\n"
-"__kernel void ClearVelocitiesKernel(__global float4* linearVelocities,__global float4* angularVelocities, int numSplitBodies)\n"
-"{\n"
-" int i = GET_GLOBAL_IDX;\n"
-" \n"
-" if( i < numSplitBodies)\n"
-" {\n"
-" linearVelocities[i] = make_float4(0);\n"
-" angularVelocities[i] = make_float4(0);\n"
-" }\n"
-"}\n"
-"__kernel void AverageVelocitiesKernel(__global Body* gBodies,__global int* offsetSplitBodies,__global const unsigned int* bodyCount,\n"
-"__global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities, int numBodies)\n"
-"{\n"
-" int i = GET_GLOBAL_IDX;\n"
-" if (i<numBodies)\n"
-" {\n"
-" if (gBodies[i].m_invMass)\n"
-" {\n"
-" int bodyOffset = offsetSplitBodies[i];\n"
-" int count = bodyCount[i];\n"
-" float factor = 1.f/((float)count);\n"
-" float4 averageLinVel = make_float4(0.f);\n"
-" float4 averageAngVel = make_float4(0.f);\n"
-" \n"
-" for (int j=0;j<count;j++)\n"
-" {\n"
-" averageLinVel += deltaLinearVelocities[bodyOffset+j]*factor;\n"
-" averageAngVel += deltaAngularVelocities[bodyOffset+j]*factor;\n"
-" }\n"
-" \n"
-" for (int j=0;j<count;j++)\n"
-" {\n"
-" deltaLinearVelocities[bodyOffset+j] = averageLinVel;\n"
-" deltaAngularVelocities[bodyOffset+j] = averageAngVel;\n"
-" }\n"
-" \n"
-" }//bodies[i].m_invMass\n"
-" }//i<numBodies\n"
-"}\n"
-"void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1)\n"
-"{\n"
-" *linear = make_float4(n.xyz,0.f);\n"
-" *angular0 = cross3(r0, n);\n"
-" *angular1 = -cross3(r1, n);\n"
-"}\n"
-"float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 )\n"
-"{\n"
-" return dot3F4(l0, linVel0) + dot3F4(a0, angVel0) + dot3F4(l1, linVel1) + dot3F4(a1, angVel1);\n"
-"}\n"
-"float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,\n"
-" float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1, float countA, float countB)\n"
-"{\n"
-" // linear0,1 are normlized\n"
-" float jmj0 = invMass0;//dot3F4(linear0, linear0)*invMass0;\n"
-" float jmj1 = dot3F4(mtMul3(angular0,*invInertia0), angular0);\n"
-" float jmj2 = invMass1;//dot3F4(linear1, linear1)*invMass1;\n"
-" float jmj3 = dot3F4(mtMul3(angular1,*invInertia1), angular1);\n"
-" return -1.f/((jmj0+jmj1)*countA+(jmj2+jmj3)*countB);\n"
-"}\n"
-"void btPlaneSpace1 (float4 n, float4* p, float4* q);\n"
-" void btPlaneSpace1 (float4 n, float4* p, float4* q)\n"
-"{\n"
-" if (fabs(n.z) > 0.70710678f) {\n"
-" // choose p in y-z plane\n"
-" float a = n.y*n.y + n.z*n.z;\n"
-" float k = 1.f/sqrt(a);\n"
-" p[0].x = 0;\n"
-" p[0].y = -n.z*k;\n"
-" p[0].z = n.y*k;\n"
-" // set q = n x p\n"
-" q[0].x = a*k;\n"
-" q[0].y = -n.x*p[0].z;\n"
-" q[0].z = n.x*p[0].y;\n"
-" }\n"
-" else {\n"
-" // choose p in x-y plane\n"
-" float a = n.x*n.x + n.y*n.y;\n"
-" float k = 1.f/sqrt(a);\n"
-" p[0].x = -n.y*k;\n"
-" p[0].y = n.x*k;\n"
-" p[0].z = 0;\n"
-" // set q = n x p\n"
-" q[0].x = -n.z*p[0].y;\n"
-" q[0].y = n.z*p[0].x;\n"
-" q[0].z = a*k;\n"
-" }\n"
-"}\n"
-"void solveContact(__global Constraint4* cs,\n"
-" float4 posA, float4* linVelA, float4* angVelA, float invMassA, Matrix3x3 invInertiaA,\n"
-" float4 posB, float4* linVelB, float4* angVelB, float invMassB, Matrix3x3 invInertiaB,\n"
-" float4* dLinVelA, float4* dAngVelA, float4* dLinVelB, float4* dAngVelB)\n"
-"{\n"
-" float minRambdaDt = 0;\n"
-" float maxRambdaDt = FLT_MAX;\n"
-" for(int ic=0; ic<4; ic++)\n"
-" {\n"
-" if( cs->m_jacCoeffInv[ic] == 0.f ) continue;\n"
-" float4 angular0, angular1, linear;\n"
-" float4 r0 = cs->m_worldPos[ic] - posA;\n"
-" float4 r1 = cs->m_worldPos[ic] - posB;\n"
-" setLinearAndAngular( cs->m_linear, r0, r1, &linear, &angular0, &angular1 );\n"
-" \n"
-" float rambdaDt = calcRelVel( cs->m_linear, -cs->m_linear, angular0, angular1, \n"
-" *linVelA+*dLinVelA, *angVelA+*dAngVelA, *linVelB+*dLinVelB, *angVelB+*dAngVelB ) + cs->m_b[ic];\n"
-" rambdaDt *= cs->m_jacCoeffInv[ic];\n"
-" \n"
-" {\n"
-" float prevSum = cs->m_appliedRambdaDt[ic];\n"
-" float updated = prevSum;\n"
-" updated += rambdaDt;\n"
-" updated = max2( updated, minRambdaDt );\n"
-" updated = min2( updated, maxRambdaDt );\n"
-" rambdaDt = updated - prevSum;\n"
-" cs->m_appliedRambdaDt[ic] = updated;\n"
-" }\n"
-" \n"
-" float4 linImp0 = invMassA*linear*rambdaDt;\n"
-" float4 linImp1 = invMassB*(-linear)*rambdaDt;\n"
-" float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;\n"
-" float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;\n"
-" \n"
-" if (invMassA)\n"
-" {\n"
-" *dLinVelA += linImp0;\n"
-" *dAngVelA += angImp0;\n"
-" }\n"
-" if (invMassB)\n"
-" {\n"
-" *dLinVelB += linImp1;\n"
-" *dAngVelB += angImp1;\n"
-" }\n"
-" }\n"
-"}\n"
-"// solveContactConstraint( gBodies, gShapes, &gConstraints[i] ,contactConstraintOffsets,offsetSplitBodies, deltaLinearVelocities, deltaAngularVelocities);\n"
-"void solveContactConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs, \n"
-"__global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,\n"
-"__global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities)\n"
-"{\n"
-" //float frictionCoeff = ldsCs[0].m_linear.w;\n"
-" int aIdx = ldsCs[0].m_bodyA;\n"
-" int bIdx = ldsCs[0].m_bodyB;\n"
-" float4 posA = gBodies[aIdx].m_pos;\n"
-" float4 linVelA = gBodies[aIdx].m_linVel;\n"
-" float4 angVelA = gBodies[aIdx].m_angVel;\n"
-" float invMassA = gBodies[aIdx].m_invMass;\n"
-" Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;\n"
-" float4 posB = gBodies[bIdx].m_pos;\n"
-" float4 linVelB = gBodies[bIdx].m_linVel;\n"
-" float4 angVelB = gBodies[bIdx].m_angVel;\n"
-" float invMassB = gBodies[bIdx].m_invMass;\n"
-" Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;\n"
-" \n"
-" float4 dLinVelA = make_float4(0,0,0,0);\n"
-" float4 dAngVelA = make_float4(0,0,0,0);\n"
-" float4 dLinVelB = make_float4(0,0,0,0);\n"
-" float4 dAngVelB = make_float4(0,0,0,0);\n"
-" \n"
-" int bodyOffsetA = offsetSplitBodies[aIdx];\n"
-" int constraintOffsetA = contactConstraintOffsets[0].x;\n"
-" int splitIndexA = bodyOffsetA+constraintOffsetA;\n"
-" \n"
-" if (invMassA)\n"
-" {\n"
-" dLinVelA = deltaLinearVelocities[splitIndexA];\n"
-" dAngVelA = deltaAngularVelocities[splitIndexA];\n"
-" }\n"
-" int bodyOffsetB = offsetSplitBodies[bIdx];\n"
-" int constraintOffsetB = contactConstraintOffsets[0].y;\n"
-" int splitIndexB= bodyOffsetB+constraintOffsetB;\n"
-" if (invMassB)\n"
-" {\n"
-" dLinVelB = deltaLinearVelocities[splitIndexB];\n"
-" dAngVelB = deltaAngularVelocities[splitIndexB];\n"
-" }\n"
-" solveContact( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,\n"
-" posB, &linVelB, &angVelB, invMassB, invInertiaB ,&dLinVelA, &dAngVelA, &dLinVelB, &dAngVelB);\n"
-" if (invMassA)\n"
-" {\n"
-" deltaLinearVelocities[splitIndexA] = dLinVelA;\n"
-" deltaAngularVelocities[splitIndexA] = dAngVelA;\n"
-" } \n"
-" if (invMassB)\n"
-" {\n"
-" deltaLinearVelocities[splitIndexB] = dLinVelB;\n"
-" deltaAngularVelocities[splitIndexB] = dAngVelB;\n"
-" }\n"
-"}\n"
-"__kernel void SolveContactJacobiKernel(__global Constraint4* gConstraints, __global Body* gBodies, __global Shape* gShapes ,\n"
-"__global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,__global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities,\n"
-"float deltaTime, float positionDrift, float positionConstraintCoeff, int fixedBodyIndex, int numManifolds\n"
-")\n"
-"{\n"
-" int i = GET_GLOBAL_IDX;\n"
-" if (i<numManifolds)\n"
-" {\n"
-" solveContactConstraint( gBodies, gShapes, &gConstraints[i] ,&contactConstraintOffsets[i],offsetSplitBodies, deltaLinearVelocities, deltaAngularVelocities);\n"
-" }\n"
-"}\n"
-"void solveFrictionConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs,\n"
-" __global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,\n"
-" __global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities)\n"
-"{\n"
-" float frictionCoeff = 0.7f;//ldsCs[0].m_linear.w;\n"
-" int aIdx = ldsCs[0].m_bodyA;\n"
-" int bIdx = ldsCs[0].m_bodyB;\n"
-" float4 posA = gBodies[aIdx].m_pos;\n"
-" float4 linVelA = gBodies[aIdx].m_linVel;\n"
-" float4 angVelA = gBodies[aIdx].m_angVel;\n"
-" float invMassA = gBodies[aIdx].m_invMass;\n"
-" Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;\n"
-" float4 posB = gBodies[bIdx].m_pos;\n"
-" float4 linVelB = gBodies[bIdx].m_linVel;\n"
-" float4 angVelB = gBodies[bIdx].m_angVel;\n"
-" float invMassB = gBodies[bIdx].m_invMass;\n"
-" Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;\n"
-" \n"
-" float4 dLinVelA = make_float4(0,0,0,0);\n"
-" float4 dAngVelA = make_float4(0,0,0,0);\n"
-" float4 dLinVelB = make_float4(0,0,0,0);\n"
-" float4 dAngVelB = make_float4(0,0,0,0);\n"
-" \n"
-" int bodyOffsetA = offsetSplitBodies[aIdx];\n"
-" int constraintOffsetA = contactConstraintOffsets[0].x;\n"
-" int splitIndexA = bodyOffsetA+constraintOffsetA;\n"
-" \n"
-" if (invMassA)\n"
-" {\n"
-" dLinVelA = deltaLinearVelocities[splitIndexA];\n"
-" dAngVelA = deltaAngularVelocities[splitIndexA];\n"
-" }\n"
-" int bodyOffsetB = offsetSplitBodies[bIdx];\n"
-" int constraintOffsetB = contactConstraintOffsets[0].y;\n"
-" int splitIndexB= bodyOffsetB+constraintOffsetB;\n"
-" if (invMassB)\n"
-" {\n"
-" dLinVelB = deltaLinearVelocities[splitIndexB];\n"
-" dAngVelB = deltaAngularVelocities[splitIndexB];\n"
-" }\n"
-" {\n"
-" float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};\n"
-" float minRambdaDt[4] = {0.f,0.f,0.f,0.f};\n"
-" float sum = 0;\n"
-" for(int j=0; j<4; j++)\n"
-" {\n"
-" sum +=ldsCs[0].m_appliedRambdaDt[j];\n"
-" }\n"
-" frictionCoeff = 0.7f;\n"
-" for(int j=0; j<4; j++)\n"
-" {\n"
-" maxRambdaDt[j] = frictionCoeff*sum;\n"
-" minRambdaDt[j] = -maxRambdaDt[j];\n"
-" }\n"
-" \n"
-"// solveFriction( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,\n"
-"// posB, &linVelB, &angVelB, invMassB, invInertiaB, maxRambdaDt, minRambdaDt );\n"
-" \n"
-" \n"
-" {\n"
-" \n"
-" __global Constraint4* cs = ldsCs;\n"
-" \n"
-" if( cs->m_fJacCoeffInv[0] == 0 && cs->m_fJacCoeffInv[0] == 0 ) return;\n"
-" const float4 center = cs->m_center;\n"
-" \n"
-" float4 n = -cs->m_linear;\n"
-" \n"
-" float4 tangent[2];\n"
-" btPlaneSpace1(n,&tangent[0],&tangent[1]);\n"
-" float4 angular0, angular1, linear;\n"
-" float4 r0 = center - posA;\n"
-" float4 r1 = center - posB;\n"
-" for(int i=0; i<2; i++)\n"
-" {\n"
-" setLinearAndAngular( tangent[i], r0, r1, &linear, &angular0, &angular1 );\n"
-" float rambdaDt = calcRelVel(linear, -linear, angular0, angular1,\n"
-" linVelA+dLinVelA, angVelA+dAngVelA, linVelB+dLinVelB, angVelB+dAngVelB );\n"
-" rambdaDt *= cs->m_fJacCoeffInv[i];\n"
-" \n"
-" {\n"
-" float prevSum = cs->m_fAppliedRambdaDt[i];\n"
-" float updated = prevSum;\n"
-" updated += rambdaDt;\n"
-" updated = max2( updated, minRambdaDt[i] );\n"
-" updated = min2( updated, maxRambdaDt[i] );\n"
-" rambdaDt = updated - prevSum;\n"
-" cs->m_fAppliedRambdaDt[i] = updated;\n"
-" }\n"
-" \n"
-" float4 linImp0 = invMassA*linear*rambdaDt;\n"
-" float4 linImp1 = invMassB*(-linear)*rambdaDt;\n"
-" float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;\n"
-" float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;\n"
-" \n"
-" dLinVelA += linImp0;\n"
-" dAngVelA += angImp0;\n"
-" dLinVelB += linImp1;\n"
-" dAngVelB += angImp1;\n"
-" }\n"
-" { // angular damping for point constraint\n"
-" float4 ab = normalize3( posB - posA );\n"
-" float4 ac = normalize3( center - posA );\n"
-" if( dot3F4( ab, ac ) > 0.95f || (invMassA == 0.f || invMassB == 0.f))\n"
-" {\n"
-" float angNA = dot3F4( n, angVelA );\n"
-" float angNB = dot3F4( n, angVelB );\n"
-" \n"
-" dAngVelA -= (angNA*0.1f)*n;\n"
-" dAngVelB -= (angNB*0.1f)*n;\n"
-" }\n"
-" }\n"
-" }\n"
-" \n"
-" \n"
-" }\n"
-" if (invMassA)\n"
-" {\n"
-" deltaLinearVelocities[splitIndexA] = dLinVelA;\n"
-" deltaAngularVelocities[splitIndexA] = dAngVelA;\n"
-" } \n"
-" if (invMassB)\n"
-" {\n"
-" deltaLinearVelocities[splitIndexB] = dLinVelB;\n"
-" deltaAngularVelocities[splitIndexB] = dAngVelB;\n"
-" }\n"
-" \n"
-"}\n"
-"__kernel void SolveFrictionJacobiKernel(__global Constraint4* gConstraints, __global Body* gBodies, __global Shape* gShapes ,\n"
-" __global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,\n"
-" __global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities,\n"
-" float deltaTime, float positionDrift, float positionConstraintCoeff, int fixedBodyIndex, int numManifolds\n"
-")\n"
-"{\n"
-" int i = GET_GLOBAL_IDX;\n"
-" if (i<numManifolds)\n"
-" {\n"
-" solveFrictionConstraint( gBodies, gShapes, &gConstraints[i] ,&contactConstraintOffsets[i],offsetSplitBodies, deltaLinearVelocities, deltaAngularVelocities);\n"
-" }\n"
-"}\n"
-"__kernel void UpdateBodyVelocitiesKernel(__global Body* gBodies,__global int* offsetSplitBodies,__global const unsigned int* bodyCount,\n"
-" __global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities, int numBodies)\n"
-"{\n"
-" int i = GET_GLOBAL_IDX;\n"
-" if (i<numBodies)\n"
-" {\n"
-" if (gBodies[i].m_invMass)\n"
-" {\n"
-" int bodyOffset = offsetSplitBodies[i];\n"
-" int count = bodyCount[i];\n"
-" if (count)\n"
-" {\n"
-" gBodies[i].m_linVel += deltaLinearVelocities[bodyOffset];\n"
-" gBodies[i].m_angVel += deltaAngularVelocities[bodyOffset];\n"
-" }\n"
-" }\n"
-" }\n"
-"}\n"
-"void setConstraint4( const float4 posA, const float4 linVelA, const float4 angVelA, float invMassA, const Matrix3x3 invInertiaA,\n"
-" const float4 posB, const float4 linVelB, const float4 angVelB, float invMassB, const Matrix3x3 invInertiaB, \n"
-" __global struct b3Contact4Data* src, float dt, float positionDrift, float positionConstraintCoeff,float countA, float countB,\n"
-" Constraint4* dstC )\n"
-"{\n"
-" dstC->m_bodyA = abs(src->m_bodyAPtrAndSignBit);\n"
-" dstC->m_bodyB = abs(src->m_bodyBPtrAndSignBit);\n"
-" float dtInv = 1.f/dt;\n"
-" for(int ic=0; ic<4; ic++)\n"
-" {\n"
-" dstC->m_appliedRambdaDt[ic] = 0.f;\n"
-" }\n"
-" dstC->m_fJacCoeffInv[0] = dstC->m_fJacCoeffInv[1] = 0.f;\n"
-" dstC->m_linear = src->m_worldNormalOnB;\n"
-" dstC->m_linear.w = 0.7f ;//src->getFrictionCoeff() );\n"
-" for(int ic=0; ic<4; ic++)\n"
-" {\n"
-" float4 r0 = src->m_worldPosB[ic] - posA;\n"
-" float4 r1 = src->m_worldPosB[ic] - posB;\n"
-" if( ic >= src->m_worldNormalOnB.w )//npoints\n"
-" {\n"
-" dstC->m_jacCoeffInv[ic] = 0.f;\n"
-" continue;\n"
-" }\n"
-" float relVelN;\n"
-" {\n"
-" float4 linear, angular0, angular1;\n"
-" setLinearAndAngular(src->m_worldNormalOnB, r0, r1, &linear, &angular0, &angular1);\n"
-" dstC->m_jacCoeffInv[ic] = calcJacCoeff(linear, -linear, angular0, angular1,\n"
-" invMassA, &invInertiaA, invMassB, &invInertiaB , countA, countB);\n"
-" relVelN = calcRelVel(linear, -linear, angular0, angular1,\n"
-" linVelA, angVelA, linVelB, angVelB);\n"
-" float e = 0.f;//src->getRestituitionCoeff();\n"
-" if( relVelN*relVelN < 0.004f ) e = 0.f;\n"
-" dstC->m_b[ic] = e*relVelN;\n"
-" //float penetration = src->m_worldPosB[ic].w;\n"
-" dstC->m_b[ic] += (src->m_worldPosB[ic].w + positionDrift)*positionConstraintCoeff*dtInv;\n"
-" dstC->m_appliedRambdaDt[ic] = 0.f;\n"
-" }\n"
-" }\n"
-" if( src->m_worldNormalOnB.w > 0 )//npoints\n"
-" { // prepare friction\n"
-" float4 center = make_float4(0.f);\n"
-" for(int i=0; i<src->m_worldNormalOnB.w; i++) \n"
-" center += src->m_worldPosB[i];\n"
-" center /= (float)src->m_worldNormalOnB.w;\n"
-" float4 tangent[2];\n"
-" btPlaneSpace1(-src->m_worldNormalOnB,&tangent[0],&tangent[1]);\n"
-" \n"
-" float4 r[2];\n"
-" r[0] = center - posA;\n"
-" r[1] = center - posB;\n"
-" for(int i=0; i<2; i++)\n"
-" {\n"
-" float4 linear, angular0, angular1;\n"
-" setLinearAndAngular(tangent[i], r[0], r[1], &linear, &angular0, &angular1);\n"
-" dstC->m_fJacCoeffInv[i] = calcJacCoeff(linear, -linear, angular0, angular1,\n"
-" invMassA, &invInertiaA, invMassB, &invInertiaB ,countA, countB);\n"
-" dstC->m_fAppliedRambdaDt[i] = 0.f;\n"
-" }\n"
-" dstC->m_center = center;\n"
-" }\n"
-" for(int i=0; i<4; i++)\n"
-" {\n"
-" if( i<src->m_worldNormalOnB.w )\n"
-" {\n"
-" dstC->m_worldPos[i] = src->m_worldPosB[i];\n"
-" }\n"
-" else\n"
-" {\n"
-" dstC->m_worldPos[i] = make_float4(0.f);\n"
-" }\n"
-" }\n"
-"}\n"
-"__kernel\n"
-"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
-"void ContactToConstraintSplitKernel(__global const struct b3Contact4Data* gContact, __global const Body* gBodies, __global const Shape* gShapes, __global Constraint4* gConstraintOut, \n"
-"__global const unsigned int* bodyCount,\n"
-"int nContacts,\n"
-"float dt,\n"
-"float positionDrift,\n"
-"float positionConstraintCoeff\n"
-")\n"
-"{\n"
-" int gIdx = GET_GLOBAL_IDX;\n"
-" \n"
-" if( gIdx < nContacts )\n"
-" {\n"
-" int aIdx = abs(gContact[gIdx].m_bodyAPtrAndSignBit);\n"
-" int bIdx = abs(gContact[gIdx].m_bodyBPtrAndSignBit);\n"
-" float4 posA = gBodies[aIdx].m_pos;\n"
-" float4 linVelA = gBodies[aIdx].m_linVel;\n"
-" float4 angVelA = gBodies[aIdx].m_angVel;\n"
-" float invMassA = gBodies[aIdx].m_invMass;\n"
-" Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;\n"
-" float4 posB = gBodies[bIdx].m_pos;\n"
-" float4 linVelB = gBodies[bIdx].m_linVel;\n"
-" float4 angVelB = gBodies[bIdx].m_angVel;\n"
-" float invMassB = gBodies[bIdx].m_invMass;\n"
-" Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;\n"
-" Constraint4 cs;\n"
-" float countA = invMassA != 0.f ? (float)bodyCount[aIdx] : 1;\n"
-" float countB = invMassB != 0.f ? (float)bodyCount[bIdx] : 1;\n"
-" setConstraint4( posA, linVelA, angVelA, invMassA, invInertiaA, posB, linVelB, angVelB, invMassB, invInertiaB,\n"
-" &gContact[gIdx], dt, positionDrift, positionConstraintCoeff,countA,countB,\n"
-" &cs );\n"
-" \n"
-" cs.m_batchIdx = gContact[gIdx].m_batchIdx;\n"
-" gConstraintOut[gIdx] = cs;\n"
-" }\n"
-"}\n"
-;
+static const char* solverUtilsCL =
+ "/*\n"
+ "Copyright (c) 2013 Advanced Micro Devices, Inc. \n"
+ "This software is provided 'as-is', without any express or implied warranty.\n"
+ "In no event will the authors be held liable for any damages arising from the use of this software.\n"
+ "Permission is granted to anyone to use this software for any purpose, \n"
+ "including commercial applications, and to alter it and redistribute it freely, \n"
+ "subject to the following restrictions:\n"
+ "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
+ "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+ "3. This notice may not be removed or altered from any source distribution.\n"
+ "*/\n"
+ "//Originally written by Erwin Coumans\n"
+ "#ifndef B3_CONTACT4DATA_H\n"
+ "#define B3_CONTACT4DATA_H\n"
+ "#ifndef B3_FLOAT4_H\n"
+ "#define B3_FLOAT4_H\n"
+ "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+ "#define B3_PLATFORM_DEFINITIONS_H\n"
+ "struct MyTest\n"
+ "{\n"
+ " int bla;\n"
+ "};\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
+ "#define B3_LARGE_FLOAT 1e18f\n"
+ "#define B3_INFINITY 1e18f\n"
+ "#define b3Assert(a)\n"
+ "#define b3ConstArray(a) __global const a*\n"
+ "#define b3AtomicInc atomic_inc\n"
+ "#define b3AtomicAdd atomic_add\n"
+ "#define b3Fabs fabs\n"
+ "#define b3Sqrt native_sqrt\n"
+ "#define b3Sin native_sin\n"
+ "#define b3Cos native_cos\n"
+ "#define B3_STATIC\n"
+ "#endif\n"
+ "#endif\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ " typedef float4 b3Float4;\n"
+ " #define b3Float4ConstArg const b3Float4\n"
+ " #define b3MakeFloat4 (float4)\n"
+ " float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+ " {\n"
+ " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+ " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+ " return dot(a1, b1);\n"
+ " }\n"
+ " b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+ " {\n"
+ " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+ " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+ " return cross(a1, b1);\n"
+ " }\n"
+ " #define b3MinFloat4 min\n"
+ " #define b3MaxFloat4 max\n"
+ " #define b3Normalized(a) normalize(a)\n"
+ "#endif \n"
+ " \n"
+ "inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
+ "{\n"
+ " if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
+ " return false;\n"
+ " return true;\n"
+ "}\n"
+ "inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
+ "{\n"
+ " float maxDot = -B3_INFINITY;\n"
+ " int i = 0;\n"
+ " int ptIndex = -1;\n"
+ " for( i = 0; i < vecLen; i++ )\n"
+ " {\n"
+ " float dot = b3Dot3F4(vecArray[i],vec);\n"
+ " \n"
+ " if( dot > maxDot )\n"
+ " {\n"
+ " maxDot = dot;\n"
+ " ptIndex = i;\n"
+ " }\n"
+ " }\n"
+ " b3Assert(ptIndex>=0);\n"
+ " if (ptIndex<0)\n"
+ " {\n"
+ " ptIndex = 0;\n"
+ " }\n"
+ " *dotOut = maxDot;\n"
+ " return ptIndex;\n"
+ "}\n"
+ "#endif //B3_FLOAT4_H\n"
+ "typedef struct b3Contact4Data b3Contact4Data_t;\n"
+ "struct b3Contact4Data\n"
+ "{\n"
+ " b3Float4 m_worldPosB[4];\n"
+ "// b3Float4 m_localPosA[4];\n"
+ "// b3Float4 m_localPosB[4];\n"
+ " b3Float4 m_worldNormalOnB; // w: m_nPoints\n"
+ " unsigned short m_restituitionCoeffCmp;\n"
+ " unsigned short m_frictionCoeffCmp;\n"
+ " int m_batchIdx;\n"
+ " int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
+ " int m_bodyBPtrAndSignBit;\n"
+ " int m_childIndexA;\n"
+ " int m_childIndexB;\n"
+ " int m_unused1;\n"
+ " int m_unused2;\n"
+ "};\n"
+ "inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
+ "{\n"
+ " return (int)contact->m_worldNormalOnB.w;\n"
+ "};\n"
+ "inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
+ "{\n"
+ " contact->m_worldNormalOnB.w = (float)numPoints;\n"
+ "};\n"
+ "#endif //B3_CONTACT4DATA_H\n"
+ "#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
+ "#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
+ "#ifdef cl_ext_atomic_counters_32\n"
+ "#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
+ "#else\n"
+ "#define counter32_t volatile global int*\n"
+ "#endif\n"
+ "typedef unsigned int u32;\n"
+ "typedef unsigned short u16;\n"
+ "typedef unsigned char u8;\n"
+ "#define GET_GROUP_IDX get_group_id(0)\n"
+ "#define GET_LOCAL_IDX get_local_id(0)\n"
+ "#define GET_GLOBAL_IDX get_global_id(0)\n"
+ "#define GET_GROUP_SIZE get_local_size(0)\n"
+ "#define GET_NUM_GROUPS get_num_groups(0)\n"
+ "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+ "#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
+ "#define AtomInc(x) atom_inc(&(x))\n"
+ "#define AtomInc1(x, out) out = atom_inc(&(x))\n"
+ "#define AppendInc(x, out) out = atomic_inc(x)\n"
+ "#define AtomAdd(x, value) atom_add(&(x), value)\n"
+ "#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
+ "#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
+ "#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
+ "#define make_float4 (float4)\n"
+ "#define make_float2 (float2)\n"
+ "#define make_uint4 (uint4)\n"
+ "#define make_int4 (int4)\n"
+ "#define make_uint2 (uint2)\n"
+ "#define make_int2 (int2)\n"
+ "#define max2 max\n"
+ "#define min2 min\n"
+ "///////////////////////////////////////\n"
+ "// Vector\n"
+ "///////////////////////////////////////\n"
+ "__inline\n"
+ "float fastDiv(float numerator, float denominator)\n"
+ "{\n"
+ " return native_divide(numerator, denominator); \n"
+ "// return numerator/denominator; \n"
+ "}\n"
+ "__inline\n"
+ "float4 fastDiv4(float4 numerator, float4 denominator)\n"
+ "{\n"
+ " return native_divide(numerator, denominator); \n"
+ "}\n"
+ "__inline\n"
+ "float fastSqrtf(float f2)\n"
+ "{\n"
+ " return native_sqrt(f2);\n"
+ "// return sqrt(f2);\n"
+ "}\n"
+ "__inline\n"
+ "float fastRSqrt(float f2)\n"
+ "{\n"
+ " return native_rsqrt(f2);\n"
+ "}\n"
+ "__inline\n"
+ "float fastLength4(float4 v)\n"
+ "{\n"
+ " return fast_length(v);\n"
+ "}\n"
+ "__inline\n"
+ "float4 fastNormalize4(float4 v)\n"
+ "{\n"
+ " return fast_normalize(v);\n"
+ "}\n"
+ "__inline\n"
+ "float sqrtf(float a)\n"
+ "{\n"
+ "// return sqrt(a);\n"
+ " return native_sqrt(a);\n"
+ "}\n"
+ "__inline\n"
+ "float4 cross3(float4 a1, float4 b1)\n"
+ "{\n"
+ " float4 a=make_float4(a1.xyz,0.f);\n"
+ " float4 b=make_float4(b1.xyz,0.f);\n"
+ " //float4 a=a1;\n"
+ " //float4 b=b1;\n"
+ " return cross(a,b);\n"
+ "}\n"
+ "__inline\n"
+ "float dot3F4(float4 a, float4 b)\n"
+ "{\n"
+ " float4 a1 = make_float4(a.xyz,0.f);\n"
+ " float4 b1 = make_float4(b.xyz,0.f);\n"
+ " return dot(a1, b1);\n"
+ "}\n"
+ "__inline\n"
+ "float length3(const float4 a)\n"
+ "{\n"
+ " return sqrtf(dot3F4(a,a));\n"
+ "}\n"
+ "__inline\n"
+ "float dot4(const float4 a, const float4 b)\n"
+ "{\n"
+ " return dot( a, b );\n"
+ "}\n"
+ "// for height\n"
+ "__inline\n"
+ "float dot3w1(const float4 point, const float4 eqn)\n"
+ "{\n"
+ " return dot3F4(point,eqn) + eqn.w;\n"
+ "}\n"
+ "__inline\n"
+ "float4 normalize3(const float4 a)\n"
+ "{\n"
+ " float4 n = make_float4(a.x, a.y, a.z, 0.f);\n"
+ " return fastNormalize4( n );\n"
+ "// float length = sqrtf(dot3F4(a, a));\n"
+ "// return 1.f/length * a;\n"
+ "}\n"
+ "__inline\n"
+ "float4 normalize4(const float4 a)\n"
+ "{\n"
+ " float length = sqrtf(dot4(a, a));\n"
+ " return 1.f/length * a;\n"
+ "}\n"
+ "__inline\n"
+ "float4 createEquation(const float4 a, const float4 b, const float4 c)\n"
+ "{\n"
+ " float4 eqn;\n"
+ " float4 ab = b-a;\n"
+ " float4 ac = c-a;\n"
+ " eqn = normalize3( cross3(ab, ac) );\n"
+ " eqn.w = -dot3F4(eqn,a);\n"
+ " return eqn;\n"
+ "}\n"
+ "///////////////////////////////////////\n"
+ "// Matrix3x3\n"
+ "///////////////////////////////////////\n"
+ "typedef struct\n"
+ "{\n"
+ " float4 m_row[3];\n"
+ "}Matrix3x3;\n"
+ "__inline\n"
+ "Matrix3x3 mtZero();\n"
+ "__inline\n"
+ "Matrix3x3 mtIdentity();\n"
+ "__inline\n"
+ "Matrix3x3 mtTranspose(Matrix3x3 m);\n"
+ "__inline\n"
+ "Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b);\n"
+ "__inline\n"
+ "float4 mtMul1(Matrix3x3 a, float4 b);\n"
+ "__inline\n"
+ "float4 mtMul3(float4 a, Matrix3x3 b);\n"
+ "__inline\n"
+ "Matrix3x3 mtZero()\n"
+ "{\n"
+ " Matrix3x3 m;\n"
+ " m.m_row[0] = (float4)(0.f);\n"
+ " m.m_row[1] = (float4)(0.f);\n"
+ " m.m_row[2] = (float4)(0.f);\n"
+ " return m;\n"
+ "}\n"
+ "__inline\n"
+ "Matrix3x3 mtIdentity()\n"
+ "{\n"
+ " Matrix3x3 m;\n"
+ " m.m_row[0] = (float4)(1,0,0,0);\n"
+ " m.m_row[1] = (float4)(0,1,0,0);\n"
+ " m.m_row[2] = (float4)(0,0,1,0);\n"
+ " return m;\n"
+ "}\n"
+ "__inline\n"
+ "Matrix3x3 mtTranspose(Matrix3x3 m)\n"
+ "{\n"
+ " Matrix3x3 out;\n"
+ " out.m_row[0] = (float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
+ " out.m_row[1] = (float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
+ " out.m_row[2] = (float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
+ " return out;\n"
+ "}\n"
+ "__inline\n"
+ "Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b)\n"
+ "{\n"
+ " Matrix3x3 transB;\n"
+ " transB = mtTranspose( b );\n"
+ " Matrix3x3 ans;\n"
+ " // why this doesn't run when 0ing in the for{}\n"
+ " a.m_row[0].w = 0.f;\n"
+ " a.m_row[1].w = 0.f;\n"
+ " a.m_row[2].w = 0.f;\n"
+ " for(int i=0; i<3; i++)\n"
+ " {\n"
+ "// a.m_row[i].w = 0.f;\n"
+ " ans.m_row[i].x = dot3F4(a.m_row[i],transB.m_row[0]);\n"
+ " ans.m_row[i].y = dot3F4(a.m_row[i],transB.m_row[1]);\n"
+ " ans.m_row[i].z = dot3F4(a.m_row[i],transB.m_row[2]);\n"
+ " ans.m_row[i].w = 0.f;\n"
+ " }\n"
+ " return ans;\n"
+ "}\n"
+ "__inline\n"
+ "float4 mtMul1(Matrix3x3 a, float4 b)\n"
+ "{\n"
+ " float4 ans;\n"
+ " ans.x = dot3F4( a.m_row[0], b );\n"
+ " ans.y = dot3F4( a.m_row[1], b );\n"
+ " ans.z = dot3F4( a.m_row[2], b );\n"
+ " ans.w = 0.f;\n"
+ " return ans;\n"
+ "}\n"
+ "__inline\n"
+ "float4 mtMul3(float4 a, Matrix3x3 b)\n"
+ "{\n"
+ " float4 colx = make_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
+ " float4 coly = make_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
+ " float4 colz = make_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
+ " float4 ans;\n"
+ " ans.x = dot3F4( a, colx );\n"
+ " ans.y = dot3F4( a, coly );\n"
+ " ans.z = dot3F4( a, colz );\n"
+ " return ans;\n"
+ "}\n"
+ "///////////////////////////////////////\n"
+ "// Quaternion\n"
+ "///////////////////////////////////////\n"
+ "typedef float4 Quaternion;\n"
+ "__inline\n"
+ "Quaternion qtMul(Quaternion a, Quaternion b);\n"
+ "__inline\n"
+ "Quaternion qtNormalize(Quaternion in);\n"
+ "__inline\n"
+ "float4 qtRotate(Quaternion q, float4 vec);\n"
+ "__inline\n"
+ "Quaternion qtInvert(Quaternion q);\n"
+ "__inline\n"
+ "Quaternion qtMul(Quaternion a, Quaternion b)\n"
+ "{\n"
+ " Quaternion ans;\n"
+ " ans = cross3( a, b );\n"
+ " ans += a.w*b+b.w*a;\n"
+ "// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+ " ans.w = a.w*b.w - dot3F4(a, b);\n"
+ " return ans;\n"
+ "}\n"
+ "__inline\n"
+ "Quaternion qtNormalize(Quaternion in)\n"
+ "{\n"
+ " return fastNormalize4(in);\n"
+ "// in /= length( in );\n"
+ "// return in;\n"
+ "}\n"
+ "__inline\n"
+ "float4 qtRotate(Quaternion q, float4 vec)\n"
+ "{\n"
+ " Quaternion qInv = qtInvert( q );\n"
+ " float4 vcpy = vec;\n"
+ " vcpy.w = 0.f;\n"
+ " float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
+ " return out;\n"
+ "}\n"
+ "__inline\n"
+ "Quaternion qtInvert(Quaternion q)\n"
+ "{\n"
+ " return (Quaternion)(-q.xyz, q.w);\n"
+ "}\n"
+ "__inline\n"
+ "float4 qtInvRotate(const Quaternion q, float4 vec)\n"
+ "{\n"
+ " return qtRotate( qtInvert( q ), vec );\n"
+ "}\n"
+ "#define WG_SIZE 64\n"
+ "typedef struct\n"
+ "{\n"
+ " float4 m_pos;\n"
+ " Quaternion m_quat;\n"
+ " float4 m_linVel;\n"
+ " float4 m_angVel;\n"
+ " u32 m_shapeIdx;\n"
+ " float m_invMass;\n"
+ " float m_restituitionCoeff;\n"
+ " float m_frictionCoeff;\n"
+ "} Body;\n"
+ "typedef struct\n"
+ "{\n"
+ " Matrix3x3 m_invInertia;\n"
+ " Matrix3x3 m_initInvInertia;\n"
+ "} Shape;\n"
+ "typedef struct\n"
+ "{\n"
+ " float4 m_linear;\n"
+ " float4 m_worldPos[4];\n"
+ " float4 m_center; \n"
+ " float m_jacCoeffInv[4];\n"
+ " float m_b[4];\n"
+ " float m_appliedRambdaDt[4];\n"
+ " float m_fJacCoeffInv[2]; \n"
+ " float m_fAppliedRambdaDt[2]; \n"
+ " u32 m_bodyA;\n"
+ " u32 m_bodyB;\n"
+ " int m_batchIdx;\n"
+ " u32 m_paddings;\n"
+ "} Constraint4;\n"
+ "__kernel void CountBodiesKernel(__global struct b3Contact4Data* manifoldPtr, __global unsigned int* bodyCount, __global int2* contactConstraintOffsets, int numContactManifolds, int fixedBodyIndex)\n"
+ "{\n"
+ " int i = GET_GLOBAL_IDX;\n"
+ " \n"
+ " if( i < numContactManifolds)\n"
+ " {\n"
+ " int pa = manifoldPtr[i].m_bodyAPtrAndSignBit;\n"
+ " bool isFixedA = (pa <0) || (pa == fixedBodyIndex);\n"
+ " int bodyIndexA = abs(pa);\n"
+ " if (!isFixedA)\n"
+ " {\n"
+ " AtomInc1(bodyCount[bodyIndexA],contactConstraintOffsets[i].x);\n"
+ " }\n"
+ " barrier(CLK_GLOBAL_MEM_FENCE);\n"
+ " int pb = manifoldPtr[i].m_bodyBPtrAndSignBit;\n"
+ " bool isFixedB = (pb <0) || (pb == fixedBodyIndex);\n"
+ " int bodyIndexB = abs(pb);\n"
+ " if (!isFixedB)\n"
+ " {\n"
+ " AtomInc1(bodyCount[bodyIndexB],contactConstraintOffsets[i].y);\n"
+ " } \n"
+ " }\n"
+ "}\n"
+ "__kernel void ClearVelocitiesKernel(__global float4* linearVelocities,__global float4* angularVelocities, int numSplitBodies)\n"
+ "{\n"
+ " int i = GET_GLOBAL_IDX;\n"
+ " \n"
+ " if( i < numSplitBodies)\n"
+ " {\n"
+ " linearVelocities[i] = make_float4(0);\n"
+ " angularVelocities[i] = make_float4(0);\n"
+ " }\n"
+ "}\n"
+ "__kernel void AverageVelocitiesKernel(__global Body* gBodies,__global int* offsetSplitBodies,__global const unsigned int* bodyCount,\n"
+ "__global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities, int numBodies)\n"
+ "{\n"
+ " int i = GET_GLOBAL_IDX;\n"
+ " if (i<numBodies)\n"
+ " {\n"
+ " if (gBodies[i].m_invMass)\n"
+ " {\n"
+ " int bodyOffset = offsetSplitBodies[i];\n"
+ " int count = bodyCount[i];\n"
+ " float factor = 1.f/((float)count);\n"
+ " float4 averageLinVel = make_float4(0.f);\n"
+ " float4 averageAngVel = make_float4(0.f);\n"
+ " \n"
+ " for (int j=0;j<count;j++)\n"
+ " {\n"
+ " averageLinVel += deltaLinearVelocities[bodyOffset+j]*factor;\n"
+ " averageAngVel += deltaAngularVelocities[bodyOffset+j]*factor;\n"
+ " }\n"
+ " \n"
+ " for (int j=0;j<count;j++)\n"
+ " {\n"
+ " deltaLinearVelocities[bodyOffset+j] = averageLinVel;\n"
+ " deltaAngularVelocities[bodyOffset+j] = averageAngVel;\n"
+ " }\n"
+ " \n"
+ " }//bodies[i].m_invMass\n"
+ " }//i<numBodies\n"
+ "}\n"
+ "void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1)\n"
+ "{\n"
+ " *linear = make_float4(n.xyz,0.f);\n"
+ " *angular0 = cross3(r0, n);\n"
+ " *angular1 = -cross3(r1, n);\n"
+ "}\n"
+ "float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 )\n"
+ "{\n"
+ " return dot3F4(l0, linVel0) + dot3F4(a0, angVel0) + dot3F4(l1, linVel1) + dot3F4(a1, angVel1);\n"
+ "}\n"
+ "float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,\n"
+ " float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1, float countA, float countB)\n"
+ "{\n"
+ " // linear0,1 are normlized\n"
+ " float jmj0 = invMass0;//dot3F4(linear0, linear0)*invMass0;\n"
+ " float jmj1 = dot3F4(mtMul3(angular0,*invInertia0), angular0);\n"
+ " float jmj2 = invMass1;//dot3F4(linear1, linear1)*invMass1;\n"
+ " float jmj3 = dot3F4(mtMul3(angular1,*invInertia1), angular1);\n"
+ " return -1.f/((jmj0+jmj1)*countA+(jmj2+jmj3)*countB);\n"
+ "}\n"
+ "void btPlaneSpace1 (float4 n, float4* p, float4* q);\n"
+ " void btPlaneSpace1 (float4 n, float4* p, float4* q)\n"
+ "{\n"
+ " if (fabs(n.z) > 0.70710678f) {\n"
+ " // choose p in y-z plane\n"
+ " float a = n.y*n.y + n.z*n.z;\n"
+ " float k = 1.f/sqrt(a);\n"
+ " p[0].x = 0;\n"
+ " p[0].y = -n.z*k;\n"
+ " p[0].z = n.y*k;\n"
+ " // set q = n x p\n"
+ " q[0].x = a*k;\n"
+ " q[0].y = -n.x*p[0].z;\n"
+ " q[0].z = n.x*p[0].y;\n"
+ " }\n"
+ " else {\n"
+ " // choose p in x-y plane\n"
+ " float a = n.x*n.x + n.y*n.y;\n"
+ " float k = 1.f/sqrt(a);\n"
+ " p[0].x = -n.y*k;\n"
+ " p[0].y = n.x*k;\n"
+ " p[0].z = 0;\n"
+ " // set q = n x p\n"
+ " q[0].x = -n.z*p[0].y;\n"
+ " q[0].y = n.z*p[0].x;\n"
+ " q[0].z = a*k;\n"
+ " }\n"
+ "}\n"
+ "void solveContact(__global Constraint4* cs,\n"
+ " float4 posA, float4* linVelA, float4* angVelA, float invMassA, Matrix3x3 invInertiaA,\n"
+ " float4 posB, float4* linVelB, float4* angVelB, float invMassB, Matrix3x3 invInertiaB,\n"
+ " float4* dLinVelA, float4* dAngVelA, float4* dLinVelB, float4* dAngVelB)\n"
+ "{\n"
+ " float minRambdaDt = 0;\n"
+ " float maxRambdaDt = FLT_MAX;\n"
+ " for(int ic=0; ic<4; ic++)\n"
+ " {\n"
+ " if( cs->m_jacCoeffInv[ic] == 0.f ) continue;\n"
+ " float4 angular0, angular1, linear;\n"
+ " float4 r0 = cs->m_worldPos[ic] - posA;\n"
+ " float4 r1 = cs->m_worldPos[ic] - posB;\n"
+ " setLinearAndAngular( cs->m_linear, r0, r1, &linear, &angular0, &angular1 );\n"
+ " \n"
+ " float rambdaDt = calcRelVel( cs->m_linear, -cs->m_linear, angular0, angular1, \n"
+ " *linVelA+*dLinVelA, *angVelA+*dAngVelA, *linVelB+*dLinVelB, *angVelB+*dAngVelB ) + cs->m_b[ic];\n"
+ " rambdaDt *= cs->m_jacCoeffInv[ic];\n"
+ " \n"
+ " {\n"
+ " float prevSum = cs->m_appliedRambdaDt[ic];\n"
+ " float updated = prevSum;\n"
+ " updated += rambdaDt;\n"
+ " updated = max2( updated, minRambdaDt );\n"
+ " updated = min2( updated, maxRambdaDt );\n"
+ " rambdaDt = updated - prevSum;\n"
+ " cs->m_appliedRambdaDt[ic] = updated;\n"
+ " }\n"
+ " \n"
+ " float4 linImp0 = invMassA*linear*rambdaDt;\n"
+ " float4 linImp1 = invMassB*(-linear)*rambdaDt;\n"
+ " float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;\n"
+ " float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;\n"
+ " \n"
+ " if (invMassA)\n"
+ " {\n"
+ " *dLinVelA += linImp0;\n"
+ " *dAngVelA += angImp0;\n"
+ " }\n"
+ " if (invMassB)\n"
+ " {\n"
+ " *dLinVelB += linImp1;\n"
+ " *dAngVelB += angImp1;\n"
+ " }\n"
+ " }\n"
+ "}\n"
+ "// solveContactConstraint( gBodies, gShapes, &gConstraints[i] ,contactConstraintOffsets,offsetSplitBodies, deltaLinearVelocities, deltaAngularVelocities);\n"
+ "void solveContactConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs, \n"
+ "__global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,\n"
+ "__global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities)\n"
+ "{\n"
+ " //float frictionCoeff = ldsCs[0].m_linear.w;\n"
+ " int aIdx = ldsCs[0].m_bodyA;\n"
+ " int bIdx = ldsCs[0].m_bodyB;\n"
+ " float4 posA = gBodies[aIdx].m_pos;\n"
+ " float4 linVelA = gBodies[aIdx].m_linVel;\n"
+ " float4 angVelA = gBodies[aIdx].m_angVel;\n"
+ " float invMassA = gBodies[aIdx].m_invMass;\n"
+ " Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;\n"
+ " float4 posB = gBodies[bIdx].m_pos;\n"
+ " float4 linVelB = gBodies[bIdx].m_linVel;\n"
+ " float4 angVelB = gBodies[bIdx].m_angVel;\n"
+ " float invMassB = gBodies[bIdx].m_invMass;\n"
+ " Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;\n"
+ " \n"
+ " float4 dLinVelA = make_float4(0,0,0,0);\n"
+ " float4 dAngVelA = make_float4(0,0,0,0);\n"
+ " float4 dLinVelB = make_float4(0,0,0,0);\n"
+ " float4 dAngVelB = make_float4(0,0,0,0);\n"
+ " \n"
+ " int bodyOffsetA = offsetSplitBodies[aIdx];\n"
+ " int constraintOffsetA = contactConstraintOffsets[0].x;\n"
+ " int splitIndexA = bodyOffsetA+constraintOffsetA;\n"
+ " \n"
+ " if (invMassA)\n"
+ " {\n"
+ " dLinVelA = deltaLinearVelocities[splitIndexA];\n"
+ " dAngVelA = deltaAngularVelocities[splitIndexA];\n"
+ " }\n"
+ " int bodyOffsetB = offsetSplitBodies[bIdx];\n"
+ " int constraintOffsetB = contactConstraintOffsets[0].y;\n"
+ " int splitIndexB= bodyOffsetB+constraintOffsetB;\n"
+ " if (invMassB)\n"
+ " {\n"
+ " dLinVelB = deltaLinearVelocities[splitIndexB];\n"
+ " dAngVelB = deltaAngularVelocities[splitIndexB];\n"
+ " }\n"
+ " solveContact( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,\n"
+ " posB, &linVelB, &angVelB, invMassB, invInertiaB ,&dLinVelA, &dAngVelA, &dLinVelB, &dAngVelB);\n"
+ " if (invMassA)\n"
+ " {\n"
+ " deltaLinearVelocities[splitIndexA] = dLinVelA;\n"
+ " deltaAngularVelocities[splitIndexA] = dAngVelA;\n"
+ " } \n"
+ " if (invMassB)\n"
+ " {\n"
+ " deltaLinearVelocities[splitIndexB] = dLinVelB;\n"
+ " deltaAngularVelocities[splitIndexB] = dAngVelB;\n"
+ " }\n"
+ "}\n"
+ "__kernel void SolveContactJacobiKernel(__global Constraint4* gConstraints, __global Body* gBodies, __global Shape* gShapes ,\n"
+ "__global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,__global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities,\n"
+ "float deltaTime, float positionDrift, float positionConstraintCoeff, int fixedBodyIndex, int numManifolds\n"
+ ")\n"
+ "{\n"
+ " int i = GET_GLOBAL_IDX;\n"
+ " if (i<numManifolds)\n"
+ " {\n"
+ " solveContactConstraint( gBodies, gShapes, &gConstraints[i] ,&contactConstraintOffsets[i],offsetSplitBodies, deltaLinearVelocities, deltaAngularVelocities);\n"
+ " }\n"
+ "}\n"
+ "void solveFrictionConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs,\n"
+ " __global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,\n"
+ " __global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities)\n"
+ "{\n"
+ " float frictionCoeff = 0.7f;//ldsCs[0].m_linear.w;\n"
+ " int aIdx = ldsCs[0].m_bodyA;\n"
+ " int bIdx = ldsCs[0].m_bodyB;\n"
+ " float4 posA = gBodies[aIdx].m_pos;\n"
+ " float4 linVelA = gBodies[aIdx].m_linVel;\n"
+ " float4 angVelA = gBodies[aIdx].m_angVel;\n"
+ " float invMassA = gBodies[aIdx].m_invMass;\n"
+ " Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;\n"
+ " float4 posB = gBodies[bIdx].m_pos;\n"
+ " float4 linVelB = gBodies[bIdx].m_linVel;\n"
+ " float4 angVelB = gBodies[bIdx].m_angVel;\n"
+ " float invMassB = gBodies[bIdx].m_invMass;\n"
+ " Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;\n"
+ " \n"
+ " float4 dLinVelA = make_float4(0,0,0,0);\n"
+ " float4 dAngVelA = make_float4(0,0,0,0);\n"
+ " float4 dLinVelB = make_float4(0,0,0,0);\n"
+ " float4 dAngVelB = make_float4(0,0,0,0);\n"
+ " \n"
+ " int bodyOffsetA = offsetSplitBodies[aIdx];\n"
+ " int constraintOffsetA = contactConstraintOffsets[0].x;\n"
+ " int splitIndexA = bodyOffsetA+constraintOffsetA;\n"
+ " \n"
+ " if (invMassA)\n"
+ " {\n"
+ " dLinVelA = deltaLinearVelocities[splitIndexA];\n"
+ " dAngVelA = deltaAngularVelocities[splitIndexA];\n"
+ " }\n"
+ " int bodyOffsetB = offsetSplitBodies[bIdx];\n"
+ " int constraintOffsetB = contactConstraintOffsets[0].y;\n"
+ " int splitIndexB= bodyOffsetB+constraintOffsetB;\n"
+ " if (invMassB)\n"
+ " {\n"
+ " dLinVelB = deltaLinearVelocities[splitIndexB];\n"
+ " dAngVelB = deltaAngularVelocities[splitIndexB];\n"
+ " }\n"
+ " {\n"
+ " float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};\n"
+ " float minRambdaDt[4] = {0.f,0.f,0.f,0.f};\n"
+ " float sum = 0;\n"
+ " for(int j=0; j<4; j++)\n"
+ " {\n"
+ " sum +=ldsCs[0].m_appliedRambdaDt[j];\n"
+ " }\n"
+ " frictionCoeff = 0.7f;\n"
+ " for(int j=0; j<4; j++)\n"
+ " {\n"
+ " maxRambdaDt[j] = frictionCoeff*sum;\n"
+ " minRambdaDt[j] = -maxRambdaDt[j];\n"
+ " }\n"
+ " \n"
+ "// solveFriction( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,\n"
+ "// posB, &linVelB, &angVelB, invMassB, invInertiaB, maxRambdaDt, minRambdaDt );\n"
+ " \n"
+ " \n"
+ " {\n"
+ " \n"
+ " __global Constraint4* cs = ldsCs;\n"
+ " \n"
+ " if( cs->m_fJacCoeffInv[0] == 0 && cs->m_fJacCoeffInv[0] == 0 ) return;\n"
+ " const float4 center = cs->m_center;\n"
+ " \n"
+ " float4 n = -cs->m_linear;\n"
+ " \n"
+ " float4 tangent[2];\n"
+ " btPlaneSpace1(n,&tangent[0],&tangent[1]);\n"
+ " float4 angular0, angular1, linear;\n"
+ " float4 r0 = center - posA;\n"
+ " float4 r1 = center - posB;\n"
+ " for(int i=0; i<2; i++)\n"
+ " {\n"
+ " setLinearAndAngular( tangent[i], r0, r1, &linear, &angular0, &angular1 );\n"
+ " float rambdaDt = calcRelVel(linear, -linear, angular0, angular1,\n"
+ " linVelA+dLinVelA, angVelA+dAngVelA, linVelB+dLinVelB, angVelB+dAngVelB );\n"
+ " rambdaDt *= cs->m_fJacCoeffInv[i];\n"
+ " \n"
+ " {\n"
+ " float prevSum = cs->m_fAppliedRambdaDt[i];\n"
+ " float updated = prevSum;\n"
+ " updated += rambdaDt;\n"
+ " updated = max2( updated, minRambdaDt[i] );\n"
+ " updated = min2( updated, maxRambdaDt[i] );\n"
+ " rambdaDt = updated - prevSum;\n"
+ " cs->m_fAppliedRambdaDt[i] = updated;\n"
+ " }\n"
+ " \n"
+ " float4 linImp0 = invMassA*linear*rambdaDt;\n"
+ " float4 linImp1 = invMassB*(-linear)*rambdaDt;\n"
+ " float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;\n"
+ " float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;\n"
+ " \n"
+ " dLinVelA += linImp0;\n"
+ " dAngVelA += angImp0;\n"
+ " dLinVelB += linImp1;\n"
+ " dAngVelB += angImp1;\n"
+ " }\n"
+ " { // angular damping for point constraint\n"
+ " float4 ab = normalize3( posB - posA );\n"
+ " float4 ac = normalize3( center - posA );\n"
+ " if( dot3F4( ab, ac ) > 0.95f || (invMassA == 0.f || invMassB == 0.f))\n"
+ " {\n"
+ " float angNA = dot3F4( n, angVelA );\n"
+ " float angNB = dot3F4( n, angVelB );\n"
+ " \n"
+ " dAngVelA -= (angNA*0.1f)*n;\n"
+ " dAngVelB -= (angNB*0.1f)*n;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " \n"
+ " \n"
+ " }\n"
+ " if (invMassA)\n"
+ " {\n"
+ " deltaLinearVelocities[splitIndexA] = dLinVelA;\n"
+ " deltaAngularVelocities[splitIndexA] = dAngVelA;\n"
+ " } \n"
+ " if (invMassB)\n"
+ " {\n"
+ " deltaLinearVelocities[splitIndexB] = dLinVelB;\n"
+ " deltaAngularVelocities[splitIndexB] = dAngVelB;\n"
+ " }\n"
+ " \n"
+ "}\n"
+ "__kernel void SolveFrictionJacobiKernel(__global Constraint4* gConstraints, __global Body* gBodies, __global Shape* gShapes ,\n"
+ " __global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,\n"
+ " __global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities,\n"
+ " float deltaTime, float positionDrift, float positionConstraintCoeff, int fixedBodyIndex, int numManifolds\n"
+ ")\n"
+ "{\n"
+ " int i = GET_GLOBAL_IDX;\n"
+ " if (i<numManifolds)\n"
+ " {\n"
+ " solveFrictionConstraint( gBodies, gShapes, &gConstraints[i] ,&contactConstraintOffsets[i],offsetSplitBodies, deltaLinearVelocities, deltaAngularVelocities);\n"
+ " }\n"
+ "}\n"
+ "__kernel void UpdateBodyVelocitiesKernel(__global Body* gBodies,__global int* offsetSplitBodies,__global const unsigned int* bodyCount,\n"
+ " __global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities, int numBodies)\n"
+ "{\n"
+ " int i = GET_GLOBAL_IDX;\n"
+ " if (i<numBodies)\n"
+ " {\n"
+ " if (gBodies[i].m_invMass)\n"
+ " {\n"
+ " int bodyOffset = offsetSplitBodies[i];\n"
+ " int count = bodyCount[i];\n"
+ " if (count)\n"
+ " {\n"
+ " gBodies[i].m_linVel += deltaLinearVelocities[bodyOffset];\n"
+ " gBodies[i].m_angVel += deltaAngularVelocities[bodyOffset];\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ "}\n"
+ "void setConstraint4( const float4 posA, const float4 linVelA, const float4 angVelA, float invMassA, const Matrix3x3 invInertiaA,\n"
+ " const float4 posB, const float4 linVelB, const float4 angVelB, float invMassB, const Matrix3x3 invInertiaB, \n"
+ " __global struct b3Contact4Data* src, float dt, float positionDrift, float positionConstraintCoeff,float countA, float countB,\n"
+ " Constraint4* dstC )\n"
+ "{\n"
+ " dstC->m_bodyA = abs(src->m_bodyAPtrAndSignBit);\n"
+ " dstC->m_bodyB = abs(src->m_bodyBPtrAndSignBit);\n"
+ " float dtInv = 1.f/dt;\n"
+ " for(int ic=0; ic<4; ic++)\n"
+ " {\n"
+ " dstC->m_appliedRambdaDt[ic] = 0.f;\n"
+ " }\n"
+ " dstC->m_fJacCoeffInv[0] = dstC->m_fJacCoeffInv[1] = 0.f;\n"
+ " dstC->m_linear = src->m_worldNormalOnB;\n"
+ " dstC->m_linear.w = 0.7f ;//src->getFrictionCoeff() );\n"
+ " for(int ic=0; ic<4; ic++)\n"
+ " {\n"
+ " float4 r0 = src->m_worldPosB[ic] - posA;\n"
+ " float4 r1 = src->m_worldPosB[ic] - posB;\n"
+ " if( ic >= src->m_worldNormalOnB.w )//npoints\n"
+ " {\n"
+ " dstC->m_jacCoeffInv[ic] = 0.f;\n"
+ " continue;\n"
+ " }\n"
+ " float relVelN;\n"
+ " {\n"
+ " float4 linear, angular0, angular1;\n"
+ " setLinearAndAngular(src->m_worldNormalOnB, r0, r1, &linear, &angular0, &angular1);\n"
+ " dstC->m_jacCoeffInv[ic] = calcJacCoeff(linear, -linear, angular0, angular1,\n"
+ " invMassA, &invInertiaA, invMassB, &invInertiaB , countA, countB);\n"
+ " relVelN = calcRelVel(linear, -linear, angular0, angular1,\n"
+ " linVelA, angVelA, linVelB, angVelB);\n"
+ " float e = 0.f;//src->getRestituitionCoeff();\n"
+ " if( relVelN*relVelN < 0.004f ) e = 0.f;\n"
+ " dstC->m_b[ic] = e*relVelN;\n"
+ " //float penetration = src->m_worldPosB[ic].w;\n"
+ " dstC->m_b[ic] += (src->m_worldPosB[ic].w + positionDrift)*positionConstraintCoeff*dtInv;\n"
+ " dstC->m_appliedRambdaDt[ic] = 0.f;\n"
+ " }\n"
+ " }\n"
+ " if( src->m_worldNormalOnB.w > 0 )//npoints\n"
+ " { // prepare friction\n"
+ " float4 center = make_float4(0.f);\n"
+ " for(int i=0; i<src->m_worldNormalOnB.w; i++) \n"
+ " center += src->m_worldPosB[i];\n"
+ " center /= (float)src->m_worldNormalOnB.w;\n"
+ " float4 tangent[2];\n"
+ " btPlaneSpace1(-src->m_worldNormalOnB,&tangent[0],&tangent[1]);\n"
+ " \n"
+ " float4 r[2];\n"
+ " r[0] = center - posA;\n"
+ " r[1] = center - posB;\n"
+ " for(int i=0; i<2; i++)\n"
+ " {\n"
+ " float4 linear, angular0, angular1;\n"
+ " setLinearAndAngular(tangent[i], r[0], r[1], &linear, &angular0, &angular1);\n"
+ " dstC->m_fJacCoeffInv[i] = calcJacCoeff(linear, -linear, angular0, angular1,\n"
+ " invMassA, &invInertiaA, invMassB, &invInertiaB ,countA, countB);\n"
+ " dstC->m_fAppliedRambdaDt[i] = 0.f;\n"
+ " }\n"
+ " dstC->m_center = center;\n"
+ " }\n"
+ " for(int i=0; i<4; i++)\n"
+ " {\n"
+ " if( i<src->m_worldNormalOnB.w )\n"
+ " {\n"
+ " dstC->m_worldPos[i] = src->m_worldPosB[i];\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " dstC->m_worldPos[i] = make_float4(0.f);\n"
+ " }\n"
+ " }\n"
+ "}\n"
+ "__kernel\n"
+ "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+ "void ContactToConstraintSplitKernel(__global const struct b3Contact4Data* gContact, __global const Body* gBodies, __global const Shape* gShapes, __global Constraint4* gConstraintOut, \n"
+ "__global const unsigned int* bodyCount,\n"
+ "int nContacts,\n"
+ "float dt,\n"
+ "float positionDrift,\n"
+ "float positionConstraintCoeff\n"
+ ")\n"
+ "{\n"
+ " int gIdx = GET_GLOBAL_IDX;\n"
+ " \n"
+ " if( gIdx < nContacts )\n"
+ " {\n"
+ " int aIdx = abs(gContact[gIdx].m_bodyAPtrAndSignBit);\n"
+ " int bIdx = abs(gContact[gIdx].m_bodyBPtrAndSignBit);\n"
+ " float4 posA = gBodies[aIdx].m_pos;\n"
+ " float4 linVelA = gBodies[aIdx].m_linVel;\n"
+ " float4 angVelA = gBodies[aIdx].m_angVel;\n"
+ " float invMassA = gBodies[aIdx].m_invMass;\n"
+ " Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;\n"
+ " float4 posB = gBodies[bIdx].m_pos;\n"
+ " float4 linVelB = gBodies[bIdx].m_linVel;\n"
+ " float4 angVelB = gBodies[bIdx].m_angVel;\n"
+ " float invMassB = gBodies[bIdx].m_invMass;\n"
+ " Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;\n"
+ " Constraint4 cs;\n"
+ " float countA = invMassA != 0.f ? (float)bodyCount[aIdx] : 1;\n"
+ " float countB = invMassB != 0.f ? (float)bodyCount[bIdx] : 1;\n"
+ " setConstraint4( posA, linVelA, angVelA, invMassA, invInertiaA, posB, linVelB, angVelB, invMassB, invInertiaB,\n"
+ " &gContact[gIdx], dt, positionDrift, positionConstraintCoeff,countA,countB,\n"
+ " &cs );\n"
+ " \n"
+ " cs.m_batchIdx = gContact[gIdx].m_batchIdx;\n"
+ " gConstraintOut[gIdx] = cs;\n"
+ " }\n"
+ "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/updateAabbsKernel.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/updateAabbsKernel.h
index d70e74017a..bb949b2027 100644
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/updateAabbsKernel.h
+++ b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/updateAabbsKernel.h
@@ -1,483 +1,482 @@
//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* updateAabbsKernelCL= \
-"#ifndef B3_UPDATE_AABBS_H\n"
-"#define B3_UPDATE_AABBS_H\n"
-"#ifndef B3_AABB_H\n"
-"#define B3_AABB_H\n"
-"#ifndef B3_FLOAT4_H\n"
-"#define B3_FLOAT4_H\n"
-"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
-"#define B3_PLATFORM_DEFINITIONS_H\n"
-"struct MyTest\n"
-"{\n"
-" int bla;\n"
-"};\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
-"#define B3_LARGE_FLOAT 1e18f\n"
-"#define B3_INFINITY 1e18f\n"
-"#define b3Assert(a)\n"
-"#define b3ConstArray(a) __global const a*\n"
-"#define b3AtomicInc atomic_inc\n"
-"#define b3AtomicAdd atomic_add\n"
-"#define b3Fabs fabs\n"
-"#define b3Sqrt native_sqrt\n"
-"#define b3Sin native_sin\n"
-"#define b3Cos native_cos\n"
-"#define B3_STATIC\n"
-"#endif\n"
-"#endif\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-" typedef float4 b3Float4;\n"
-" #define b3Float4ConstArg const b3Float4\n"
-" #define b3MakeFloat4 (float4)\n"
-" float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
-" {\n"
-" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
-" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
-" return dot(a1, b1);\n"
-" }\n"
-" b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
-" {\n"
-" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
-" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
-" return cross(a1, b1);\n"
-" }\n"
-" #define b3MinFloat4 min\n"
-" #define b3MaxFloat4 max\n"
-" #define b3Normalized(a) normalize(a)\n"
-"#endif \n"
-" \n"
-"inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
-"{\n"
-" if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
-" return false;\n"
-" return true;\n"
-"}\n"
-"inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
-"{\n"
-" float maxDot = -B3_INFINITY;\n"
-" int i = 0;\n"
-" int ptIndex = -1;\n"
-" for( i = 0; i < vecLen; i++ )\n"
-" {\n"
-" float dot = b3Dot3F4(vecArray[i],vec);\n"
-" \n"
-" if( dot > maxDot )\n"
-" {\n"
-" maxDot = dot;\n"
-" ptIndex = i;\n"
-" }\n"
-" }\n"
-" b3Assert(ptIndex>=0);\n"
-" if (ptIndex<0)\n"
-" {\n"
-" ptIndex = 0;\n"
-" }\n"
-" *dotOut = maxDot;\n"
-" return ptIndex;\n"
-"}\n"
-"#endif //B3_FLOAT4_H\n"
-"#ifndef B3_MAT3x3_H\n"
-"#define B3_MAT3x3_H\n"
-"#ifndef B3_QUAT_H\n"
-"#define B3_QUAT_H\n"
-"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#endif\n"
-"#endif\n"
-"#ifndef B3_FLOAT4_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#endif \n"
-"#endif //B3_FLOAT4_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-" typedef float4 b3Quat;\n"
-" #define b3QuatConstArg const b3Quat\n"
-" \n"
-" \n"
-"inline float4 b3FastNormalize4(float4 v)\n"
-"{\n"
-" v = (float4)(v.xyz,0.f);\n"
-" return fast_normalize(v);\n"
-"}\n"
-" \n"
-"inline b3Quat b3QuatMul(b3Quat a, b3Quat b);\n"
-"inline b3Quat b3QuatNormalized(b3QuatConstArg in);\n"
-"inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec);\n"
-"inline b3Quat b3QuatInvert(b3QuatConstArg q);\n"
-"inline b3Quat b3QuatInverse(b3QuatConstArg q);\n"
-"inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b)\n"
-"{\n"
-" b3Quat ans;\n"
-" ans = b3Cross3( a, b );\n"
-" ans += a.w*b+b.w*a;\n"
-"// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
-" ans.w = a.w*b.w - b3Dot3F4(a, b);\n"
-" return ans;\n"
-"}\n"
-"inline b3Quat b3QuatNormalized(b3QuatConstArg in)\n"
-"{\n"
-" b3Quat q;\n"
-" q=in;\n"
-" //return b3FastNormalize4(in);\n"
-" float len = native_sqrt(dot(q, q));\n"
-" if(len > 0.f)\n"
-" {\n"
-" q *= 1.f / len;\n"
-" }\n"
-" else\n"
-" {\n"
-" q.x = q.y = q.z = 0.f;\n"
-" q.w = 1.f;\n"
-" }\n"
-" return q;\n"
-"}\n"
-"inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
-"{\n"
-" b3Quat qInv = b3QuatInvert( q );\n"
-" float4 vcpy = vec;\n"
-" vcpy.w = 0.f;\n"
-" float4 out = b3QuatMul(b3QuatMul(q,vcpy),qInv);\n"
-" return out;\n"
-"}\n"
-"inline b3Quat b3QuatInverse(b3QuatConstArg q)\n"
-"{\n"
-" return (b3Quat)(-q.xyz, q.w);\n"
-"}\n"
-"inline b3Quat b3QuatInvert(b3QuatConstArg q)\n"
-"{\n"
-" return (b3Quat)(-q.xyz, q.w);\n"
-"}\n"
-"inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
-"{\n"
-" return b3QuatRotate( b3QuatInvert( q ), vec );\n"
-"}\n"
-"inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation)\n"
-"{\n"
-" return b3QuatRotate( orientation, point ) + (translation);\n"
-"}\n"
-" \n"
-"#endif \n"
-"#endif //B3_QUAT_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"typedef struct\n"
-"{\n"
-" b3Float4 m_row[3];\n"
-"}b3Mat3x3;\n"
-"#define b3Mat3x3ConstArg const b3Mat3x3\n"
-"#define b3GetRow(m,row) (m.m_row[row])\n"
-"inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat)\n"
-"{\n"
-" b3Float4 quat2 = (b3Float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);\n"
-" b3Mat3x3 out;\n"
-" out.m_row[0].x=1-2*quat2.y-2*quat2.z;\n"
-" out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;\n"
-" out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;\n"
-" out.m_row[0].w = 0.f;\n"
-" out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;\n"
-" out.m_row[1].y=1-2*quat2.x-2*quat2.z;\n"
-" out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;\n"
-" out.m_row[1].w = 0.f;\n"
-" out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;\n"
-" out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;\n"
-" out.m_row[2].z=1-2*quat2.x-2*quat2.y;\n"
-" out.m_row[2].w = 0.f;\n"
-" return out;\n"
-"}\n"
-"inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn)\n"
-"{\n"
-" b3Mat3x3 out;\n"
-" out.m_row[0] = fabs(matIn.m_row[0]);\n"
-" out.m_row[1] = fabs(matIn.m_row[1]);\n"
-" out.m_row[2] = fabs(matIn.m_row[2]);\n"
-" return out;\n"
-"}\n"
-"__inline\n"
-"b3Mat3x3 mtZero();\n"
-"__inline\n"
-"b3Mat3x3 mtIdentity();\n"
-"__inline\n"
-"b3Mat3x3 mtTranspose(b3Mat3x3 m);\n"
-"__inline\n"
-"b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);\n"
-"__inline\n"
-"b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);\n"
-"__inline\n"
-"b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);\n"
-"__inline\n"
-"b3Mat3x3 mtZero()\n"
-"{\n"
-" b3Mat3x3 m;\n"
-" m.m_row[0] = (b3Float4)(0.f);\n"
-" m.m_row[1] = (b3Float4)(0.f);\n"
-" m.m_row[2] = (b3Float4)(0.f);\n"
-" return m;\n"
-"}\n"
-"__inline\n"
-"b3Mat3x3 mtIdentity()\n"
-"{\n"
-" b3Mat3x3 m;\n"
-" m.m_row[0] = (b3Float4)(1,0,0,0);\n"
-" m.m_row[1] = (b3Float4)(0,1,0,0);\n"
-" m.m_row[2] = (b3Float4)(0,0,1,0);\n"
-" return m;\n"
-"}\n"
-"__inline\n"
-"b3Mat3x3 mtTranspose(b3Mat3x3 m)\n"
-"{\n"
-" b3Mat3x3 out;\n"
-" out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
-" out.m_row[1] = (b3Float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
-" out.m_row[2] = (b3Float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
-" return out;\n"
-"}\n"
-"__inline\n"
-"b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)\n"
-"{\n"
-" b3Mat3x3 transB;\n"
-" transB = mtTranspose( b );\n"
-" b3Mat3x3 ans;\n"
-" // why this doesn't run when 0ing in the for{}\n"
-" a.m_row[0].w = 0.f;\n"
-" a.m_row[1].w = 0.f;\n"
-" a.m_row[2].w = 0.f;\n"
-" for(int i=0; i<3; i++)\n"
-" {\n"
-"// a.m_row[i].w = 0.f;\n"
-" ans.m_row[i].x = b3Dot3F4(a.m_row[i],transB.m_row[0]);\n"
-" ans.m_row[i].y = b3Dot3F4(a.m_row[i],transB.m_row[1]);\n"
-" ans.m_row[i].z = b3Dot3F4(a.m_row[i],transB.m_row[2]);\n"
-" ans.m_row[i].w = 0.f;\n"
-" }\n"
-" return ans;\n"
-"}\n"
-"__inline\n"
-"b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)\n"
-"{\n"
-" b3Float4 ans;\n"
-" ans.x = b3Dot3F4( a.m_row[0], b );\n"
-" ans.y = b3Dot3F4( a.m_row[1], b );\n"
-" ans.z = b3Dot3F4( a.m_row[2], b );\n"
-" ans.w = 0.f;\n"
-" return ans;\n"
-"}\n"
-"__inline\n"
-"b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)\n"
-"{\n"
-" b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
-" b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
-" b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
-" b3Float4 ans;\n"
-" ans.x = b3Dot3F4( a, colx );\n"
-" ans.y = b3Dot3F4( a, coly );\n"
-" ans.z = b3Dot3F4( a, colz );\n"
-" return ans;\n"
-"}\n"
-"#endif\n"
-"#endif //B3_MAT3x3_H\n"
-"typedef struct b3Aabb b3Aabb_t;\n"
-"struct b3Aabb\n"
-"{\n"
-" union\n"
-" {\n"
-" float m_min[4];\n"
-" b3Float4 m_minVec;\n"
-" int m_minIndices[4];\n"
-" };\n"
-" union\n"
-" {\n"
-" float m_max[4];\n"
-" b3Float4 m_maxVec;\n"
-" int m_signedMaxIndices[4];\n"
-" };\n"
-"};\n"
-"inline void b3TransformAabb2(b3Float4ConstArg localAabbMin,b3Float4ConstArg localAabbMax, float margin,\n"
-" b3Float4ConstArg pos,\n"
-" b3QuatConstArg orn,\n"
-" b3Float4* aabbMinOut,b3Float4* aabbMaxOut)\n"
-"{\n"
-" b3Float4 localHalfExtents = 0.5f*(localAabbMax-localAabbMin);\n"
-" localHalfExtents+=b3MakeFloat4(margin,margin,margin,0.f);\n"
-" b3Float4 localCenter = 0.5f*(localAabbMax+localAabbMin);\n"
-" b3Mat3x3 m;\n"
-" m = b3QuatGetRotationMatrix(orn);\n"
-" b3Mat3x3 abs_b = b3AbsoluteMat3x3(m);\n"
-" b3Float4 center = b3TransformPoint(localCenter,pos,orn);\n"
-" \n"
-" b3Float4 extent = b3MakeFloat4(b3Dot3F4(localHalfExtents,b3GetRow(abs_b,0)),\n"
-" b3Dot3F4(localHalfExtents,b3GetRow(abs_b,1)),\n"
-" b3Dot3F4(localHalfExtents,b3GetRow(abs_b,2)),\n"
-" 0.f);\n"
-" *aabbMinOut = center-extent;\n"
-" *aabbMaxOut = center+extent;\n"
-"}\n"
-"/// conservative test for overlap between two aabbs\n"
-"inline bool b3TestAabbAgainstAabb(b3Float4ConstArg aabbMin1,b3Float4ConstArg aabbMax1,\n"
-" b3Float4ConstArg aabbMin2, b3Float4ConstArg aabbMax2)\n"
-"{\n"
-" bool overlap = true;\n"
-" overlap = (aabbMin1.x > aabbMax2.x || aabbMax1.x < aabbMin2.x) ? false : overlap;\n"
-" overlap = (aabbMin1.z > aabbMax2.z || aabbMax1.z < aabbMin2.z) ? false : overlap;\n"
-" overlap = (aabbMin1.y > aabbMax2.y || aabbMax1.y < aabbMin2.y) ? false : overlap;\n"
-" return overlap;\n"
-"}\n"
-"#endif //B3_AABB_H\n"
-"#ifndef B3_COLLIDABLE_H\n"
-"#define B3_COLLIDABLE_H\n"
-"#ifndef B3_FLOAT4_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#endif \n"
-"#endif //B3_FLOAT4_H\n"
-"#ifndef B3_QUAT_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#endif \n"
-"#endif //B3_QUAT_H\n"
-"enum b3ShapeTypes\n"
-"{\n"
-" SHAPE_HEIGHT_FIELD=1,\n"
-" SHAPE_CONVEX_HULL=3,\n"
-" SHAPE_PLANE=4,\n"
-" SHAPE_CONCAVE_TRIMESH=5,\n"
-" SHAPE_COMPOUND_OF_CONVEX_HULLS=6,\n"
-" SHAPE_SPHERE=7,\n"
-" MAX_NUM_SHAPE_TYPES,\n"
-"};\n"
-"typedef struct b3Collidable b3Collidable_t;\n"
-"struct b3Collidable\n"
-"{\n"
-" union {\n"
-" int m_numChildShapes;\n"
-" int m_bvhIndex;\n"
-" };\n"
-" union\n"
-" {\n"
-" float m_radius;\n"
-" int m_compoundBvhIndex;\n"
-" };\n"
-" int m_shapeType;\n"
-" union\n"
-" {\n"
-" int m_shapeIndex;\n"
-" float m_height;\n"
-" };\n"
-"};\n"
-"typedef struct b3GpuChildShape b3GpuChildShape_t;\n"
-"struct b3GpuChildShape\n"
-"{\n"
-" b3Float4 m_childPosition;\n"
-" b3Quat m_childOrientation;\n"
-" union\n"
-" {\n"
-" int m_shapeIndex;//used for SHAPE_COMPOUND_OF_CONVEX_HULLS\n"
-" int m_capsuleAxis;\n"
-" };\n"
-" union \n"
-" {\n"
-" float m_radius;//used for childshape of SHAPE_COMPOUND_OF_SPHERES or SHAPE_COMPOUND_OF_CAPSULES\n"
-" int m_numChildShapes;//used for compound shape\n"
-" };\n"
-" union \n"
-" {\n"
-" float m_height;//used for childshape of SHAPE_COMPOUND_OF_CAPSULES\n"
-" int m_collidableShapeIndex;\n"
-" };\n"
-" int m_shapeType;\n"
-"};\n"
-"struct b3CompoundOverlappingPair\n"
-"{\n"
-" int m_bodyIndexA;\n"
-" int m_bodyIndexB;\n"
-"// int m_pairType;\n"
-" int m_childShapeIndexA;\n"
-" int m_childShapeIndexB;\n"
-"};\n"
-"#endif //B3_COLLIDABLE_H\n"
-"#ifndef B3_RIGIDBODY_DATA_H\n"
-"#define B3_RIGIDBODY_DATA_H\n"
-"#ifndef B3_FLOAT4_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#endif \n"
-"#endif //B3_FLOAT4_H\n"
-"#ifndef B3_QUAT_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#endif \n"
-"#endif //B3_QUAT_H\n"
-"#ifndef B3_MAT3x3_H\n"
-"#ifdef __cplusplus\n"
-"#else\n"
-"#endif\n"
-"#endif //B3_MAT3x3_H\n"
-"typedef struct b3RigidBodyData b3RigidBodyData_t;\n"
-"struct b3RigidBodyData\n"
-"{\n"
-" b3Float4 m_pos;\n"
-" b3Quat m_quat;\n"
-" b3Float4 m_linVel;\n"
-" b3Float4 m_angVel;\n"
-" int m_collidableIdx;\n"
-" float m_invMass;\n"
-" float m_restituitionCoeff;\n"
-" float m_frictionCoeff;\n"
-"};\n"
-"typedef struct b3InertiaData b3InertiaData_t;\n"
-"struct b3InertiaData\n"
-"{\n"
-" b3Mat3x3 m_invInertiaWorld;\n"
-" b3Mat3x3 m_initInvInertia;\n"
-"};\n"
-"#endif //B3_RIGIDBODY_DATA_H\n"
-" \n"
-"void b3ComputeWorldAabb( int bodyId, __global const b3RigidBodyData_t* bodies, __global const b3Collidable_t* collidables, __global const b3Aabb_t* localShapeAABB, __global b3Aabb_t* worldAabbs)\n"
-"{\n"
-" __global const b3RigidBodyData_t* body = &bodies[bodyId];\n"
-" b3Float4 position = body->m_pos;\n"
-" b3Quat orientation = body->m_quat;\n"
-" \n"
-" int collidableIndex = body->m_collidableIdx;\n"
-" int shapeIndex = collidables[collidableIndex].m_shapeIndex;\n"
-" \n"
-" if (shapeIndex>=0)\n"
-" {\n"
-" \n"
-" b3Aabb_t localAabb = localShapeAABB[collidableIndex];\n"
-" b3Aabb_t worldAabb;\n"
-" \n"
-" b3Float4 aabbAMinOut,aabbAMaxOut; \n"
-" float margin = 0.f;\n"
-" b3TransformAabb2(localAabb.m_minVec,localAabb.m_maxVec,margin,position,orientation,&aabbAMinOut,&aabbAMaxOut);\n"
-" \n"
-" worldAabb.m_minVec =aabbAMinOut;\n"
-" worldAabb.m_minIndices[3] = bodyId;\n"
-" worldAabb.m_maxVec = aabbAMaxOut;\n"
-" worldAabb.m_signedMaxIndices[3] = body[bodyId].m_invMass==0.f? 0 : 1;\n"
-" worldAabbs[bodyId] = worldAabb;\n"
-" }\n"
-"}\n"
-"#endif //B3_UPDATE_AABBS_H\n"
-"__kernel void initializeGpuAabbsFull( const int numNodes, __global b3RigidBodyData_t* gBodies,__global b3Collidable_t* collidables, __global b3Aabb_t* plocalShapeAABB, __global b3Aabb_t* pAABB)\n"
-"{\n"
-" int nodeID = get_global_id(0);\n"
-" if( nodeID < numNodes )\n"
-" {\n"
-" b3ComputeWorldAabb(nodeID, gBodies, collidables, plocalShapeAABB,pAABB);\n"
-" }\n"
-"}\n"
-"__kernel void clearOverlappingPairsKernel( __global int4* pairs, int numPairs)\n"
-"{\n"
-" int pairId = get_global_id(0);\n"
-" if( pairId< numPairs )\n"
-" {\n"
-" pairs[pairId].z = 0xffffffff;\n"
-" }\n"
-"}\n"
-;
+static const char* updateAabbsKernelCL =
+ "#ifndef B3_UPDATE_AABBS_H\n"
+ "#define B3_UPDATE_AABBS_H\n"
+ "#ifndef B3_AABB_H\n"
+ "#define B3_AABB_H\n"
+ "#ifndef B3_FLOAT4_H\n"
+ "#define B3_FLOAT4_H\n"
+ "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+ "#define B3_PLATFORM_DEFINITIONS_H\n"
+ "struct MyTest\n"
+ "{\n"
+ " int bla;\n"
+ "};\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
+ "#define B3_LARGE_FLOAT 1e18f\n"
+ "#define B3_INFINITY 1e18f\n"
+ "#define b3Assert(a)\n"
+ "#define b3ConstArray(a) __global const a*\n"
+ "#define b3AtomicInc atomic_inc\n"
+ "#define b3AtomicAdd atomic_add\n"
+ "#define b3Fabs fabs\n"
+ "#define b3Sqrt native_sqrt\n"
+ "#define b3Sin native_sin\n"
+ "#define b3Cos native_cos\n"
+ "#define B3_STATIC\n"
+ "#endif\n"
+ "#endif\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ " typedef float4 b3Float4;\n"
+ " #define b3Float4ConstArg const b3Float4\n"
+ " #define b3MakeFloat4 (float4)\n"
+ " float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+ " {\n"
+ " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+ " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+ " return dot(a1, b1);\n"
+ " }\n"
+ " b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+ " {\n"
+ " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+ " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+ " return cross(a1, b1);\n"
+ " }\n"
+ " #define b3MinFloat4 min\n"
+ " #define b3MaxFloat4 max\n"
+ " #define b3Normalized(a) normalize(a)\n"
+ "#endif \n"
+ " \n"
+ "inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
+ "{\n"
+ " if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
+ " return false;\n"
+ " return true;\n"
+ "}\n"
+ "inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
+ "{\n"
+ " float maxDot = -B3_INFINITY;\n"
+ " int i = 0;\n"
+ " int ptIndex = -1;\n"
+ " for( i = 0; i < vecLen; i++ )\n"
+ " {\n"
+ " float dot = b3Dot3F4(vecArray[i],vec);\n"
+ " \n"
+ " if( dot > maxDot )\n"
+ " {\n"
+ " maxDot = dot;\n"
+ " ptIndex = i;\n"
+ " }\n"
+ " }\n"
+ " b3Assert(ptIndex>=0);\n"
+ " if (ptIndex<0)\n"
+ " {\n"
+ " ptIndex = 0;\n"
+ " }\n"
+ " *dotOut = maxDot;\n"
+ " return ptIndex;\n"
+ "}\n"
+ "#endif //B3_FLOAT4_H\n"
+ "#ifndef B3_MAT3x3_H\n"
+ "#define B3_MAT3x3_H\n"
+ "#ifndef B3_QUAT_H\n"
+ "#define B3_QUAT_H\n"
+ "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#endif\n"
+ "#endif\n"
+ "#ifndef B3_FLOAT4_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#endif \n"
+ "#endif //B3_FLOAT4_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ " typedef float4 b3Quat;\n"
+ " #define b3QuatConstArg const b3Quat\n"
+ " \n"
+ " \n"
+ "inline float4 b3FastNormalize4(float4 v)\n"
+ "{\n"
+ " v = (float4)(v.xyz,0.f);\n"
+ " return fast_normalize(v);\n"
+ "}\n"
+ " \n"
+ "inline b3Quat b3QuatMul(b3Quat a, b3Quat b);\n"
+ "inline b3Quat b3QuatNormalized(b3QuatConstArg in);\n"
+ "inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec);\n"
+ "inline b3Quat b3QuatInvert(b3QuatConstArg q);\n"
+ "inline b3Quat b3QuatInverse(b3QuatConstArg q);\n"
+ "inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b)\n"
+ "{\n"
+ " b3Quat ans;\n"
+ " ans = b3Cross3( a, b );\n"
+ " ans += a.w*b+b.w*a;\n"
+ "// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+ " ans.w = a.w*b.w - b3Dot3F4(a, b);\n"
+ " return ans;\n"
+ "}\n"
+ "inline b3Quat b3QuatNormalized(b3QuatConstArg in)\n"
+ "{\n"
+ " b3Quat q;\n"
+ " q=in;\n"
+ " //return b3FastNormalize4(in);\n"
+ " float len = native_sqrt(dot(q, q));\n"
+ " if(len > 0.f)\n"
+ " {\n"
+ " q *= 1.f / len;\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " q.x = q.y = q.z = 0.f;\n"
+ " q.w = 1.f;\n"
+ " }\n"
+ " return q;\n"
+ "}\n"
+ "inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+ "{\n"
+ " b3Quat qInv = b3QuatInvert( q );\n"
+ " float4 vcpy = vec;\n"
+ " vcpy.w = 0.f;\n"
+ " float4 out = b3QuatMul(b3QuatMul(q,vcpy),qInv);\n"
+ " return out;\n"
+ "}\n"
+ "inline b3Quat b3QuatInverse(b3QuatConstArg q)\n"
+ "{\n"
+ " return (b3Quat)(-q.xyz, q.w);\n"
+ "}\n"
+ "inline b3Quat b3QuatInvert(b3QuatConstArg q)\n"
+ "{\n"
+ " return (b3Quat)(-q.xyz, q.w);\n"
+ "}\n"
+ "inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+ "{\n"
+ " return b3QuatRotate( b3QuatInvert( q ), vec );\n"
+ "}\n"
+ "inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation)\n"
+ "{\n"
+ " return b3QuatRotate( orientation, point ) + (translation);\n"
+ "}\n"
+ " \n"
+ "#endif \n"
+ "#endif //B3_QUAT_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "typedef struct\n"
+ "{\n"
+ " b3Float4 m_row[3];\n"
+ "}b3Mat3x3;\n"
+ "#define b3Mat3x3ConstArg const b3Mat3x3\n"
+ "#define b3GetRow(m,row) (m.m_row[row])\n"
+ "inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat)\n"
+ "{\n"
+ " b3Float4 quat2 = (b3Float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);\n"
+ " b3Mat3x3 out;\n"
+ " out.m_row[0].x=1-2*quat2.y-2*quat2.z;\n"
+ " out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;\n"
+ " out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;\n"
+ " out.m_row[0].w = 0.f;\n"
+ " out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;\n"
+ " out.m_row[1].y=1-2*quat2.x-2*quat2.z;\n"
+ " out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;\n"
+ " out.m_row[1].w = 0.f;\n"
+ " out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;\n"
+ " out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;\n"
+ " out.m_row[2].z=1-2*quat2.x-2*quat2.y;\n"
+ " out.m_row[2].w = 0.f;\n"
+ " return out;\n"
+ "}\n"
+ "inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn)\n"
+ "{\n"
+ " b3Mat3x3 out;\n"
+ " out.m_row[0] = fabs(matIn.m_row[0]);\n"
+ " out.m_row[1] = fabs(matIn.m_row[1]);\n"
+ " out.m_row[2] = fabs(matIn.m_row[2]);\n"
+ " return out;\n"
+ "}\n"
+ "__inline\n"
+ "b3Mat3x3 mtZero();\n"
+ "__inline\n"
+ "b3Mat3x3 mtIdentity();\n"
+ "__inline\n"
+ "b3Mat3x3 mtTranspose(b3Mat3x3 m);\n"
+ "__inline\n"
+ "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);\n"
+ "__inline\n"
+ "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);\n"
+ "__inline\n"
+ "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);\n"
+ "__inline\n"
+ "b3Mat3x3 mtZero()\n"
+ "{\n"
+ " b3Mat3x3 m;\n"
+ " m.m_row[0] = (b3Float4)(0.f);\n"
+ " m.m_row[1] = (b3Float4)(0.f);\n"
+ " m.m_row[2] = (b3Float4)(0.f);\n"
+ " return m;\n"
+ "}\n"
+ "__inline\n"
+ "b3Mat3x3 mtIdentity()\n"
+ "{\n"
+ " b3Mat3x3 m;\n"
+ " m.m_row[0] = (b3Float4)(1,0,0,0);\n"
+ " m.m_row[1] = (b3Float4)(0,1,0,0);\n"
+ " m.m_row[2] = (b3Float4)(0,0,1,0);\n"
+ " return m;\n"
+ "}\n"
+ "__inline\n"
+ "b3Mat3x3 mtTranspose(b3Mat3x3 m)\n"
+ "{\n"
+ " b3Mat3x3 out;\n"
+ " out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
+ " out.m_row[1] = (b3Float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
+ " out.m_row[2] = (b3Float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
+ " return out;\n"
+ "}\n"
+ "__inline\n"
+ "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)\n"
+ "{\n"
+ " b3Mat3x3 transB;\n"
+ " transB = mtTranspose( b );\n"
+ " b3Mat3x3 ans;\n"
+ " // why this doesn't run when 0ing in the for{}\n"
+ " a.m_row[0].w = 0.f;\n"
+ " a.m_row[1].w = 0.f;\n"
+ " a.m_row[2].w = 0.f;\n"
+ " for(int i=0; i<3; i++)\n"
+ " {\n"
+ "// a.m_row[i].w = 0.f;\n"
+ " ans.m_row[i].x = b3Dot3F4(a.m_row[i],transB.m_row[0]);\n"
+ " ans.m_row[i].y = b3Dot3F4(a.m_row[i],transB.m_row[1]);\n"
+ " ans.m_row[i].z = b3Dot3F4(a.m_row[i],transB.m_row[2]);\n"
+ " ans.m_row[i].w = 0.f;\n"
+ " }\n"
+ " return ans;\n"
+ "}\n"
+ "__inline\n"
+ "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)\n"
+ "{\n"
+ " b3Float4 ans;\n"
+ " ans.x = b3Dot3F4( a.m_row[0], b );\n"
+ " ans.y = b3Dot3F4( a.m_row[1], b );\n"
+ " ans.z = b3Dot3F4( a.m_row[2], b );\n"
+ " ans.w = 0.f;\n"
+ " return ans;\n"
+ "}\n"
+ "__inline\n"
+ "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)\n"
+ "{\n"
+ " b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
+ " b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
+ " b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
+ " b3Float4 ans;\n"
+ " ans.x = b3Dot3F4( a, colx );\n"
+ " ans.y = b3Dot3F4( a, coly );\n"
+ " ans.z = b3Dot3F4( a, colz );\n"
+ " return ans;\n"
+ "}\n"
+ "#endif\n"
+ "#endif //B3_MAT3x3_H\n"
+ "typedef struct b3Aabb b3Aabb_t;\n"
+ "struct b3Aabb\n"
+ "{\n"
+ " union\n"
+ " {\n"
+ " float m_min[4];\n"
+ " b3Float4 m_minVec;\n"
+ " int m_minIndices[4];\n"
+ " };\n"
+ " union\n"
+ " {\n"
+ " float m_max[4];\n"
+ " b3Float4 m_maxVec;\n"
+ " int m_signedMaxIndices[4];\n"
+ " };\n"
+ "};\n"
+ "inline void b3TransformAabb2(b3Float4ConstArg localAabbMin,b3Float4ConstArg localAabbMax, float margin,\n"
+ " b3Float4ConstArg pos,\n"
+ " b3QuatConstArg orn,\n"
+ " b3Float4* aabbMinOut,b3Float4* aabbMaxOut)\n"
+ "{\n"
+ " b3Float4 localHalfExtents = 0.5f*(localAabbMax-localAabbMin);\n"
+ " localHalfExtents+=b3MakeFloat4(margin,margin,margin,0.f);\n"
+ " b3Float4 localCenter = 0.5f*(localAabbMax+localAabbMin);\n"
+ " b3Mat3x3 m;\n"
+ " m = b3QuatGetRotationMatrix(orn);\n"
+ " b3Mat3x3 abs_b = b3AbsoluteMat3x3(m);\n"
+ " b3Float4 center = b3TransformPoint(localCenter,pos,orn);\n"
+ " \n"
+ " b3Float4 extent = b3MakeFloat4(b3Dot3F4(localHalfExtents,b3GetRow(abs_b,0)),\n"
+ " b3Dot3F4(localHalfExtents,b3GetRow(abs_b,1)),\n"
+ " b3Dot3F4(localHalfExtents,b3GetRow(abs_b,2)),\n"
+ " 0.f);\n"
+ " *aabbMinOut = center-extent;\n"
+ " *aabbMaxOut = center+extent;\n"
+ "}\n"
+ "/// conservative test for overlap between two aabbs\n"
+ "inline bool b3TestAabbAgainstAabb(b3Float4ConstArg aabbMin1,b3Float4ConstArg aabbMax1,\n"
+ " b3Float4ConstArg aabbMin2, b3Float4ConstArg aabbMax2)\n"
+ "{\n"
+ " bool overlap = true;\n"
+ " overlap = (aabbMin1.x > aabbMax2.x || aabbMax1.x < aabbMin2.x) ? false : overlap;\n"
+ " overlap = (aabbMin1.z > aabbMax2.z || aabbMax1.z < aabbMin2.z) ? false : overlap;\n"
+ " overlap = (aabbMin1.y > aabbMax2.y || aabbMax1.y < aabbMin2.y) ? false : overlap;\n"
+ " return overlap;\n"
+ "}\n"
+ "#endif //B3_AABB_H\n"
+ "#ifndef B3_COLLIDABLE_H\n"
+ "#define B3_COLLIDABLE_H\n"
+ "#ifndef B3_FLOAT4_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#endif \n"
+ "#endif //B3_FLOAT4_H\n"
+ "#ifndef B3_QUAT_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#endif \n"
+ "#endif //B3_QUAT_H\n"
+ "enum b3ShapeTypes\n"
+ "{\n"
+ " SHAPE_HEIGHT_FIELD=1,\n"
+ " SHAPE_CONVEX_HULL=3,\n"
+ " SHAPE_PLANE=4,\n"
+ " SHAPE_CONCAVE_TRIMESH=5,\n"
+ " SHAPE_COMPOUND_OF_CONVEX_HULLS=6,\n"
+ " SHAPE_SPHERE=7,\n"
+ " MAX_NUM_SHAPE_TYPES,\n"
+ "};\n"
+ "typedef struct b3Collidable b3Collidable_t;\n"
+ "struct b3Collidable\n"
+ "{\n"
+ " union {\n"
+ " int m_numChildShapes;\n"
+ " int m_bvhIndex;\n"
+ " };\n"
+ " union\n"
+ " {\n"
+ " float m_radius;\n"
+ " int m_compoundBvhIndex;\n"
+ " };\n"
+ " int m_shapeType;\n"
+ " union\n"
+ " {\n"
+ " int m_shapeIndex;\n"
+ " float m_height;\n"
+ " };\n"
+ "};\n"
+ "typedef struct b3GpuChildShape b3GpuChildShape_t;\n"
+ "struct b3GpuChildShape\n"
+ "{\n"
+ " b3Float4 m_childPosition;\n"
+ " b3Quat m_childOrientation;\n"
+ " union\n"
+ " {\n"
+ " int m_shapeIndex;//used for SHAPE_COMPOUND_OF_CONVEX_HULLS\n"
+ " int m_capsuleAxis;\n"
+ " };\n"
+ " union \n"
+ " {\n"
+ " float m_radius;//used for childshape of SHAPE_COMPOUND_OF_SPHERES or SHAPE_COMPOUND_OF_CAPSULES\n"
+ " int m_numChildShapes;//used for compound shape\n"
+ " };\n"
+ " union \n"
+ " {\n"
+ " float m_height;//used for childshape of SHAPE_COMPOUND_OF_CAPSULES\n"
+ " int m_collidableShapeIndex;\n"
+ " };\n"
+ " int m_shapeType;\n"
+ "};\n"
+ "struct b3CompoundOverlappingPair\n"
+ "{\n"
+ " int m_bodyIndexA;\n"
+ " int m_bodyIndexB;\n"
+ "// int m_pairType;\n"
+ " int m_childShapeIndexA;\n"
+ " int m_childShapeIndexB;\n"
+ "};\n"
+ "#endif //B3_COLLIDABLE_H\n"
+ "#ifndef B3_RIGIDBODY_DATA_H\n"
+ "#define B3_RIGIDBODY_DATA_H\n"
+ "#ifndef B3_FLOAT4_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#endif \n"
+ "#endif //B3_FLOAT4_H\n"
+ "#ifndef B3_QUAT_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#endif \n"
+ "#endif //B3_QUAT_H\n"
+ "#ifndef B3_MAT3x3_H\n"
+ "#ifdef __cplusplus\n"
+ "#else\n"
+ "#endif\n"
+ "#endif //B3_MAT3x3_H\n"
+ "typedef struct b3RigidBodyData b3RigidBodyData_t;\n"
+ "struct b3RigidBodyData\n"
+ "{\n"
+ " b3Float4 m_pos;\n"
+ " b3Quat m_quat;\n"
+ " b3Float4 m_linVel;\n"
+ " b3Float4 m_angVel;\n"
+ " int m_collidableIdx;\n"
+ " float m_invMass;\n"
+ " float m_restituitionCoeff;\n"
+ " float m_frictionCoeff;\n"
+ "};\n"
+ "typedef struct b3InertiaData b3InertiaData_t;\n"
+ "struct b3InertiaData\n"
+ "{\n"
+ " b3Mat3x3 m_invInertiaWorld;\n"
+ " b3Mat3x3 m_initInvInertia;\n"
+ "};\n"
+ "#endif //B3_RIGIDBODY_DATA_H\n"
+ " \n"
+ "void b3ComputeWorldAabb( int bodyId, __global const b3RigidBodyData_t* bodies, __global const b3Collidable_t* collidables, __global const b3Aabb_t* localShapeAABB, __global b3Aabb_t* worldAabbs)\n"
+ "{\n"
+ " __global const b3RigidBodyData_t* body = &bodies[bodyId];\n"
+ " b3Float4 position = body->m_pos;\n"
+ " b3Quat orientation = body->m_quat;\n"
+ " \n"
+ " int collidableIndex = body->m_collidableIdx;\n"
+ " int shapeIndex = collidables[collidableIndex].m_shapeIndex;\n"
+ " \n"
+ " if (shapeIndex>=0)\n"
+ " {\n"
+ " \n"
+ " b3Aabb_t localAabb = localShapeAABB[collidableIndex];\n"
+ " b3Aabb_t worldAabb;\n"
+ " \n"
+ " b3Float4 aabbAMinOut,aabbAMaxOut; \n"
+ " float margin = 0.f;\n"
+ " b3TransformAabb2(localAabb.m_minVec,localAabb.m_maxVec,margin,position,orientation,&aabbAMinOut,&aabbAMaxOut);\n"
+ " \n"
+ " worldAabb.m_minVec =aabbAMinOut;\n"
+ " worldAabb.m_minIndices[3] = bodyId;\n"
+ " worldAabb.m_maxVec = aabbAMaxOut;\n"
+ " worldAabb.m_signedMaxIndices[3] = body[bodyId].m_invMass==0.f? 0 : 1;\n"
+ " worldAabbs[bodyId] = worldAabb;\n"
+ " }\n"
+ "}\n"
+ "#endif //B3_UPDATE_AABBS_H\n"
+ "__kernel void initializeGpuAabbsFull( const int numNodes, __global b3RigidBodyData_t* gBodies,__global b3Collidable_t* collidables, __global b3Aabb_t* plocalShapeAABB, __global b3Aabb_t* pAABB)\n"
+ "{\n"
+ " int nodeID = get_global_id(0);\n"
+ " if( nodeID < numNodes )\n"
+ " {\n"
+ " b3ComputeWorldAabb(nodeID, gBodies, collidables, plocalShapeAABB,pAABB);\n"
+ " }\n"
+ "}\n"
+ "__kernel void clearOverlappingPairsKernel( __global int4* pairs, int numPairs)\n"
+ "{\n"
+ " int pairId = get_global_id(0);\n"
+ " if( pairId< numPairs )\n"
+ " {\n"
+ " pairs[pairId].z = 0xffffffff;\n"
+ " }\n"
+ "}\n";
diff --git a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/autogenerated/bullet2.h b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/autogenerated/bullet2.h
index a6b57b1a12..eaa27dfe8f 100644
--- a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/autogenerated/bullet2.h
+++ b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/autogenerated/bullet2.h
@@ -19,1035 +19,969 @@
// Auto generated from Bullet/Extras/HeaderGenerator/bulletGenerate.py
#ifndef __BULLET2_H__
#define __BULLET2_H__
-namespace Bullet3SerializeBullet2 {
-
+namespace Bullet3SerializeBullet2
+{
// put an empty struct in the case
-typedef struct bInvalidHandle {
+typedef struct bInvalidHandle
+{
int unused;
-}bInvalidHandle;
-
- class PointerArray;
- class b3PhysicsSystem;
- class ListBase;
- class b3Vector3FloatData;
- class b3Vector3DoubleData;
- class b3Matrix3x3FloatData;
- class b3Matrix3x3DoubleData;
- class b3TransformFloatData;
- class b3TransformDoubleData;
- class b3BvhSubtreeInfoData;
- class b3OptimizedBvhNodeFloatData;
- class b3OptimizedBvhNodeDoubleData;
- class b3QuantizedBvhNodeData;
- class b3QuantizedBvhFloatData;
- class b3QuantizedBvhDoubleData;
- class b3CollisionShapeData;
- class b3StaticPlaneShapeData;
- class b3ConvexInternalShapeData;
- class b3PositionAndRadius;
- class b3MultiSphereShapeData;
- class b3IntIndexData;
- class b3ShortIntIndexData;
- class b3ShortIntIndexTripletData;
- class b3CharIndexTripletData;
- class b3MeshPartData;
- class b3StridingMeshInterfaceData;
- class b3TriangleMeshShapeData;
- class b3ScaledTriangleMeshShapeData;
- class b3CompoundShapeChildData;
- class b3CompoundShapeData;
- class b3CylinderShapeData;
- class b3CapsuleShapeData;
- class b3TriangleInfoData;
- class b3TriangleInfoMapData;
- class b3GImpactMeshShapeData;
- class b3ConvexHullShapeData;
- class b3CollisionObjectDoubleData;
- class b3CollisionObjectFloatData;
- class b3DynamicsWorldDoubleData;
- class b3DynamicsWorldFloatData;
- class b3RigidBodyFloatData;
- class b3RigidBodyDoubleData;
- class b3ConstraintInfo1;
- class b3TypedConstraintData;
- class b3Point2PointConstraintFloatData;
- class b3Point2PointConstraintDoubleData;
- class b3HingeConstraintDoubleData;
- class b3HingeConstraintFloatData;
- class b3ConeTwistConstraintData;
- class b3Generic6DofConstraintData;
- class b3Generic6DofSpringConstraintData;
- class b3SliderConstraintData;
- class b3ContactSolverInfoDoubleData;
- class b3ContactSolverInfoFloatData;
- class SoftBodyMaterialData;
- class SoftBodyNodeData;
- class SoftBodyLinkData;
- class SoftBodyFaceData;
- class SoftBodyTetraData;
- class SoftRigidAnchorData;
- class SoftBodyConfigData;
- class SoftBodyPoseData;
- class SoftBodyClusterData;
- class b3SoftBodyJointData;
- class b3SoftBodyFloatData;
-// -------------------------------------------------- //
- class PointerArray
- {
- public:
- int m_size;
- int m_capacity;
- void *m_data;
- };
-
-
-// -------------------------------------------------- //
- class b3PhysicsSystem
- {
- public:
- PointerArray m_collisionShapes;
- PointerArray m_collisionObjects;
- PointerArray m_constraints;
- };
-
-
-// -------------------------------------------------- //
- class ListBase
- {
- public:
- void *first;
- void *last;
- };
-
-
-// -------------------------------------------------- //
- class b3Vector3FloatData
- {
- public:
- float m_floats[4];
- };
-
-
-// -------------------------------------------------- //
- class b3Vector3DoubleData
- {
- public:
- double m_floats[4];
- };
-
-
-// -------------------------------------------------- //
- class b3Matrix3x3FloatData
- {
- public:
- b3Vector3FloatData m_el[3];
- };
-
-
-// -------------------------------------------------- //
- class b3Matrix3x3DoubleData
- {
- public:
- b3Vector3DoubleData m_el[3];
- };
-
-
-// -------------------------------------------------- //
- class b3TransformFloatData
- {
- public:
- b3Matrix3x3FloatData m_basis;
- b3Vector3FloatData m_origin;
- };
-
-
-// -------------------------------------------------- //
- class b3TransformDoubleData
- {
- public:
- b3Matrix3x3DoubleData m_basis;
- b3Vector3DoubleData m_origin;
- };
-
-
-// -------------------------------------------------- //
- class b3BvhSubtreeInfoData
- {
- public:
- int m_rootNodeIndex;
- int m_subtreeSize;
- short m_quantizedAabbMin[3];
- short m_quantizedAabbMax[3];
- };
-
-
-// -------------------------------------------------- //
- class b3OptimizedBvhNodeFloatData
- {
- public:
- b3Vector3FloatData m_aabbMinOrg;
- b3Vector3FloatData m_aabbMaxOrg;
- int m_escapeIndex;
- int m_subPart;
- int m_triangleIndex;
- char m_pad[4];
- };
-
-
-// -------------------------------------------------- //
- class b3OptimizedBvhNodeDoubleData
- {
- public:
- b3Vector3DoubleData m_aabbMinOrg;
- b3Vector3DoubleData m_aabbMaxOrg;
- int m_escapeIndex;
- int m_subPart;
- int m_triangleIndex;
- char m_pad[4];
- };
-
-
-// -------------------------------------------------- //
- class b3QuantizedBvhNodeData
- {
- public:
- short m_quantizedAabbMin[3];
- short m_quantizedAabbMax[3];
- int m_escapeIndexOrTriangleIndex;
- };
-
-
-// -------------------------------------------------- //
- class b3QuantizedBvhFloatData
- {
- public:
- b3Vector3FloatData m_bvhAabbMin;
- b3Vector3FloatData m_bvhAabbMax;
- b3Vector3FloatData m_bvhQuantization;
- int m_curNodeIndex;
- int m_useQuantization;
- int m_numContiguousLeafNodes;
- int m_numQuantizedContiguousNodes;
- b3OptimizedBvhNodeFloatData *m_contiguousNodesPtr;
- b3QuantizedBvhNodeData *m_quantizedContiguousNodesPtr;
- b3BvhSubtreeInfoData *m_subTreeInfoPtr;
- int m_traversalMode;
- int m_numSubtreeHeaders;
- };
-
-
-// -------------------------------------------------- //
- class b3QuantizedBvhDoubleData
- {
- public:
- b3Vector3DoubleData m_bvhAabbMin;
- b3Vector3DoubleData m_bvhAabbMax;
- b3Vector3DoubleData m_bvhQuantization;
- int m_curNodeIndex;
- int m_useQuantization;
- int m_numContiguousLeafNodes;
- int m_numQuantizedContiguousNodes;
- b3OptimizedBvhNodeDoubleData *m_contiguousNodesPtr;
- b3QuantizedBvhNodeData *m_quantizedContiguousNodesPtr;
- int m_traversalMode;
- int m_numSubtreeHeaders;
- b3BvhSubtreeInfoData *m_subTreeInfoPtr;
- };
-
-
-// -------------------------------------------------- //
- class b3CollisionShapeData
- {
- public:
- char *m_name;
- int m_shapeType;
- char m_padding[4];
- };
-
-
-// -------------------------------------------------- //
- class b3StaticPlaneShapeData
- {
- public:
- b3CollisionShapeData m_collisionShapeData;
- b3Vector3FloatData m_localScaling;
- b3Vector3FloatData m_planeNormal;
- float m_planeConstant;
- char m_pad[4];
- };
-
-
-// -------------------------------------------------- //
- class b3ConvexInternalShapeData
- {
- public:
- b3CollisionShapeData m_collisionShapeData;
- b3Vector3FloatData m_localScaling;
- b3Vector3FloatData m_implicitShapeDimensions;
- float m_collisionMargin;
- int m_padding;
- };
-
-
-// -------------------------------------------------- //
- class b3PositionAndRadius
- {
- public:
- b3Vector3FloatData m_pos;
- float m_radius;
- };
-
-
-// -------------------------------------------------- //
- class b3MultiSphereShapeData
- {
- public:
- b3ConvexInternalShapeData m_convexInternalShapeData;
- b3PositionAndRadius *m_localPositionArrayPtr;
- int m_localPositionArraySize;
- char m_padding[4];
- };
-
-
-// -------------------------------------------------- //
- class b3IntIndexData
- {
- public:
- int m_value;
- };
-
-
-// -------------------------------------------------- //
- class b3ShortIntIndexData
- {
- public:
- short m_value;
- char m_pad[2];
- };
-
-
-// -------------------------------------------------- //
- class b3ShortIntIndexTripletData
- {
- public:
- short m_values[3];
- char m_pad[2];
- };
-
-
-// -------------------------------------------------- //
- class b3CharIndexTripletData
- {
- public:
- char m_values[3];
- char m_pad;
- };
-
-
-// -------------------------------------------------- //
- class b3MeshPartData
- {
- public:
- b3Vector3FloatData *m_vertices3f;
- b3Vector3DoubleData *m_vertices3d;
- b3IntIndexData *m_indices32;
- b3ShortIntIndexTripletData *m_3indices16;
- b3CharIndexTripletData *m_3indices8;
- b3ShortIntIndexData *m_indices16;
- int m_numTriangles;
- int m_numVertices;
- };
-
-
-// -------------------------------------------------- //
- class b3StridingMeshInterfaceData
- {
- public:
- b3MeshPartData *m_meshPartsPtr;
- b3Vector3FloatData m_scaling;
- int m_numMeshParts;
- char m_padding[4];
- };
-
-
-// -------------------------------------------------- //
- class b3TriangleMeshShapeData
- {
- public:
- b3CollisionShapeData m_collisionShapeData;
- b3StridingMeshInterfaceData m_meshInterface;
- b3QuantizedBvhFloatData *m_quantizedFloatBvh;
- b3QuantizedBvhDoubleData *m_quantizedDoubleBvh;
- b3TriangleInfoMapData *m_triangleInfoMap;
- float m_collisionMargin;
- char m_pad3[4];
- };
-
-
-// -------------------------------------------------- //
- class b3ScaledTriangleMeshShapeData
- {
- public:
- b3TriangleMeshShapeData m_trimeshShapeData;
- b3Vector3FloatData m_localScaling;
- };
-
-
-// -------------------------------------------------- //
- class b3CompoundShapeChildData
- {
- public:
- b3TransformFloatData m_transform;
- b3CollisionShapeData *m_childShape;
- int m_childShapeType;
- float m_childMargin;
- };
-
-
-// -------------------------------------------------- //
- class b3CompoundShapeData
- {
- public:
- b3CollisionShapeData m_collisionShapeData;
- b3CompoundShapeChildData *m_childShapePtr;
- int m_numChildShapes;
- float m_collisionMargin;
- };
-
-
-// -------------------------------------------------- //
- class b3CylinderShapeData
- {
- public:
- b3ConvexInternalShapeData m_convexInternalShapeData;
- int m_upAxis;
- char m_padding[4];
- };
-
-
-// -------------------------------------------------- //
- class b3CapsuleShapeData
- {
- public:
- b3ConvexInternalShapeData m_convexInternalShapeData;
- int m_upAxis;
- char m_padding[4];
- };
-
-
-// -------------------------------------------------- //
- class b3TriangleInfoData
- {
- public:
- int m_flags;
- float m_edgeV0V1Angle;
- float m_edgeV1V2Angle;
- float m_edgeV2V0Angle;
- };
-
-
-// -------------------------------------------------- //
- class b3TriangleInfoMapData
- {
- public:
- int *m_hashTablePtr;
- int *m_nextPtr;
- b3TriangleInfoData *m_valueArrayPtr;
- int *m_keyArrayPtr;
- float m_convexEpsilon;
- float m_planarEpsilon;
- float m_equalVertexThreshold;
- float m_edgeDistanceThreshold;
- float m_zeroAreaThreshold;
- int m_nextSize;
- int m_hashTableSize;
- int m_numValues;
- int m_numKeys;
- char m_padding[4];
- };
-
-
-// -------------------------------------------------- //
- class b3GImpactMeshShapeData
- {
- public:
- b3CollisionShapeData m_collisionShapeData;
- b3StridingMeshInterfaceData m_meshInterface;
- b3Vector3FloatData m_localScaling;
- float m_collisionMargin;
- int m_gimpactSubType;
- };
-
-
-// -------------------------------------------------- //
- class b3ConvexHullShapeData
- {
- public:
- b3ConvexInternalShapeData m_convexInternalShapeData;
- b3Vector3FloatData *m_unscaledPointsFloatPtr;
- b3Vector3DoubleData *m_unscaledPointsDoublePtr;
- int m_numUnscaledPoints;
- char m_padding3[4];
- };
-
-
-// -------------------------------------------------- //
- class b3CollisionObjectDoubleData
- {
- public:
- void *m_broadphaseHandle;
- void *m_collisionShape;
- b3CollisionShapeData *m_rootCollisionShape;
- char *m_name;
- b3TransformDoubleData m_worldTransform;
- b3TransformDoubleData m_interpolationWorldTransform;
- b3Vector3DoubleData m_interpolationLinearVelocity;
- b3Vector3DoubleData m_interpolationAngularVelocity;
- b3Vector3DoubleData m_anisotropicFriction;
- double m_contactProcessingThreshold;
- double m_deactivationTime;
- double m_friction;
- double m_rollingFriction;
- double m_restitution;
- double m_hitFraction;
- double m_ccdSweptSphereRadius;
- double m_ccdMotionThreshold;
- int m_hasAnisotropicFriction;
- int m_collisionFlags;
- int m_islandTag1;
- int m_companionId;
- int m_activationState1;
- int m_internalType;
- int m_checkCollideWith;
- char m_padding[4];
- };
-
-
-// -------------------------------------------------- //
- class b3CollisionObjectFloatData
- {
- public:
- void *m_broadphaseHandle;
- void *m_collisionShape;
- b3CollisionShapeData *m_rootCollisionShape;
- char *m_name;
- b3TransformFloatData m_worldTransform;
- b3TransformFloatData m_interpolationWorldTransform;
- b3Vector3FloatData m_interpolationLinearVelocity;
- b3Vector3FloatData m_interpolationAngularVelocity;
- b3Vector3FloatData m_anisotropicFriction;
- float m_contactProcessingThreshold;
- float m_deactivationTime;
- float m_friction;
- float m_rollingFriction;
- float m_restitution;
- float m_hitFraction;
- float m_ccdSweptSphereRadius;
- float m_ccdMotionThreshold;
- int m_hasAnisotropicFriction;
- int m_collisionFlags;
- int m_islandTag1;
- int m_companionId;
- int m_activationState1;
- int m_internalType;
- int m_checkCollideWith;
- char m_padding[4];
- };
-
-
-
-// -------------------------------------------------- //
- class b3RigidBodyFloatData
- {
- public:
- b3CollisionObjectFloatData m_collisionObjectData;
- b3Matrix3x3FloatData m_invInertiaTensorWorld;
- b3Vector3FloatData m_linearVelocity;
- b3Vector3FloatData m_angularVelocity;
- b3Vector3FloatData m_angularFactor;
- b3Vector3FloatData m_linearFactor;
- b3Vector3FloatData m_gravity;
- b3Vector3FloatData m_gravity_acceleration;
- b3Vector3FloatData m_invInertiaLocal;
- b3Vector3FloatData m_totalForce;
- b3Vector3FloatData m_totalTorque;
- float m_inverseMass;
- float m_linearDamping;
- float m_angularDamping;
- float m_additionalDampingFactor;
- float m_additionalLinearDampingThresholdSqr;
- float m_additionalAngularDampingThresholdSqr;
- float m_additionalAngularDampingFactor;
- float m_linearSleepingThreshold;
- float m_angularSleepingThreshold;
- int m_additionalDamping;
- };
-
-
-// -------------------------------------------------- //
- class b3RigidBodyDoubleData
- {
- public:
- b3CollisionObjectDoubleData m_collisionObjectData;
- b3Matrix3x3DoubleData m_invInertiaTensorWorld;
- b3Vector3DoubleData m_linearVelocity;
- b3Vector3DoubleData m_angularVelocity;
- b3Vector3DoubleData m_angularFactor;
- b3Vector3DoubleData m_linearFactor;
- b3Vector3DoubleData m_gravity;
- b3Vector3DoubleData m_gravity_acceleration;
- b3Vector3DoubleData m_invInertiaLocal;
- b3Vector3DoubleData m_totalForce;
- b3Vector3DoubleData m_totalTorque;
- double m_inverseMass;
- double m_linearDamping;
- double m_angularDamping;
- double m_additionalDampingFactor;
- double m_additionalLinearDampingThresholdSqr;
- double m_additionalAngularDampingThresholdSqr;
- double m_additionalAngularDampingFactor;
- double m_linearSleepingThreshold;
- double m_angularSleepingThreshold;
- int m_additionalDamping;
- char m_padding[4];
- };
-
-
-// -------------------------------------------------- //
- class b3ConstraintInfo1
- {
- public:
- int m_numConstraintRows;
- int nub;
- };
-
-
-// -------------------------------------------------- //
- class b3TypedConstraintData
- {
- public:
- bInvalidHandle *m_rbA;
- bInvalidHandle *m_rbB;
- char *m_name;
- int m_objectType;
- int m_userConstraintType;
- int m_userConstraintId;
- int m_needsFeedback;
- float m_appliedImpulse;
- float m_dbgDrawSize;
- int m_disableCollisionsBetweenLinkedBodies;
- int m_overrideNumSolverIterations;
- float m_breakingImpulseThreshold;
- int m_isEnabled;
- };
-
-
-// -------------------------------------------------- //
- class b3Point2PointConstraintFloatData
- {
- public:
- b3TypedConstraintData m_typeConstraintData;
- b3Vector3FloatData m_pivotInA;
- b3Vector3FloatData m_pivotInB;
- };
-
-
-// -------------------------------------------------- //
- class b3Point2PointConstraintDoubleData
- {
- public:
- b3TypedConstraintData m_typeConstraintData;
- b3Vector3DoubleData m_pivotInA;
- b3Vector3DoubleData m_pivotInB;
- };
-
-
-// -------------------------------------------------- //
- class b3HingeConstraintDoubleData
- {
- public:
- b3TypedConstraintData m_typeConstraintData;
- b3TransformDoubleData m_rbAFrame;
- b3TransformDoubleData m_rbBFrame;
- int m_useReferenceFrameA;
- int m_angularOnly;
- int m_enableAngularMotor;
- float m_motorTargetVelocity;
- float m_maxMotorImpulse;
- float m_lowerLimit;
- float m_upperLimit;
- float m_limitSoftness;
- float m_biasFactor;
- float m_relaxationFactor;
- };
-
-
-// -------------------------------------------------- //
- class b3HingeConstraintFloatData
- {
- public:
- b3TypedConstraintData m_typeConstraintData;
- b3TransformFloatData m_rbAFrame;
- b3TransformFloatData m_rbBFrame;
- int m_useReferenceFrameA;
- int m_angularOnly;
- int m_enableAngularMotor;
- float m_motorTargetVelocity;
- float m_maxMotorImpulse;
- float m_lowerLimit;
- float m_upperLimit;
- float m_limitSoftness;
- float m_biasFactor;
- float m_relaxationFactor;
- };
-
-
-// -------------------------------------------------- //
- class b3ConeTwistConstraintData
- {
- public:
- b3TypedConstraintData m_typeConstraintData;
- b3TransformFloatData m_rbAFrame;
- b3TransformFloatData m_rbBFrame;
- float m_swingSpan1;
- float m_swingSpan2;
- float m_twistSpan;
- float m_limitSoftness;
- float m_biasFactor;
- float m_relaxationFactor;
- float m_damping;
- char m_pad[4];
- };
-
-
-// -------------------------------------------------- //
- class b3Generic6DofConstraintData
- {
- public:
- b3TypedConstraintData m_typeConstraintData;
- b3TransformFloatData m_rbAFrame;
- b3TransformFloatData m_rbBFrame;
- b3Vector3FloatData m_linearUpperLimit;
- b3Vector3FloatData m_linearLowerLimit;
- b3Vector3FloatData m_angularUpperLimit;
- b3Vector3FloatData m_angularLowerLimit;
- int m_useLinearReferenceFrameA;
- int m_useOffsetForConstraintFrame;
- };
-
-
-// -------------------------------------------------- //
- class b3Generic6DofSpringConstraintData
- {
- public:
- b3Generic6DofConstraintData m_6dofData;
- int m_springEnabled[6];
- float m_equilibriumPoint[6];
- float m_springStiffness[6];
- float m_springDamping[6];
- };
-
-
-// -------------------------------------------------- //
- class b3SliderConstraintData
- {
- public:
- b3TypedConstraintData m_typeConstraintData;
- b3TransformFloatData m_rbAFrame;
- b3TransformFloatData m_rbBFrame;
- float m_linearUpperLimit;
- float m_linearLowerLimit;
- float m_angularUpperLimit;
- float m_angularLowerLimit;
- int m_useLinearReferenceFrameA;
- int m_useOffsetForConstraintFrame;
- };
-
-
-// -------------------------------------------------- //
- class b3ContactSolverInfoDoubleData
- {
- public:
- double m_tau;
- double m_damping;
- double m_friction;
- double m_timeStep;
- double m_restitution;
- double m_maxErrorReduction;
- double m_sor;
- double m_erp;
- double m_erp2;
- double m_globalCfm;
- double m_splitImpulsePenetrationThreshold;
- double m_splitImpulseTurnErp;
- double m_linearSlop;
- double m_warmstartingFactor;
- double m_maxGyroscopicForce;
- double m_singleAxisRollingFrictionThreshold;
- int m_numIterations;
- int m_solverMode;
- int m_restingContactRestitutionThreshold;
- int m_minimumSolverBatchSize;
- int m_splitImpulse;
- char m_padding[4];
- };
-
-
-// -------------------------------------------------- //
- class b3ContactSolverInfoFloatData
- {
- public:
- float m_tau;
- float m_damping;
- float m_friction;
- float m_timeStep;
- float m_restitution;
- float m_maxErrorReduction;
- float m_sor;
- float m_erp;
- float m_erp2;
- float m_globalCfm;
- float m_splitImpulsePenetrationThreshold;
- float m_splitImpulseTurnErp;
- float m_linearSlop;
- float m_warmstartingFactor;
- float m_maxGyroscopicForce;
- float m_singleAxisRollingFrictionThreshold;
- int m_numIterations;
- int m_solverMode;
- int m_restingContactRestitutionThreshold;
- int m_minimumSolverBatchSize;
- int m_splitImpulse;
- char m_padding[4];
- };
-
-
- // -------------------------------------------------- //
- class b3DynamicsWorldDoubleData
- {
- public:
- b3ContactSolverInfoDoubleData m_solverInfo;
- b3Vector3DoubleData m_gravity;
- };
-
-
-// -------------------------------------------------- //
- class b3DynamicsWorldFloatData
- {
- public:
- b3ContactSolverInfoFloatData m_solverInfo;
- b3Vector3FloatData m_gravity;
- };
-
-
-
-// -------------------------------------------------- //
- class SoftBodyMaterialData
- {
- public:
- float m_linearStiffness;
- float m_angularStiffness;
- float m_volumeStiffness;
- int m_flags;
- };
-
-
-// -------------------------------------------------- //
- class SoftBodyNodeData
- {
- public:
- SoftBodyMaterialData *m_material;
- b3Vector3FloatData m_position;
- b3Vector3FloatData m_previousPosition;
- b3Vector3FloatData m_velocity;
- b3Vector3FloatData m_accumulatedForce;
- b3Vector3FloatData m_normal;
- float m_inverseMass;
- float m_area;
- int m_attach;
- int m_pad;
- };
-
-
-// -------------------------------------------------- //
- class SoftBodyLinkData
- {
- public:
- SoftBodyMaterialData *m_material;
- int m_nodeIndices[2];
- float m_restLength;
- int m_bbending;
- };
-
-
-// -------------------------------------------------- //
- class SoftBodyFaceData
- {
- public:
- b3Vector3FloatData m_normal;
- SoftBodyMaterialData *m_material;
- int m_nodeIndices[3];
- float m_restArea;
- };
-
-
-// -------------------------------------------------- //
- class SoftBodyTetraData
- {
- public:
- b3Vector3FloatData m_c0[4];
- SoftBodyMaterialData *m_material;
- int m_nodeIndices[4];
- float m_restVolume;
- float m_c1;
- float m_c2;
- int m_pad;
- };
-
-
-// -------------------------------------------------- //
- class SoftRigidAnchorData
- {
- public:
- b3Matrix3x3FloatData m_c0;
- b3Vector3FloatData m_c1;
- b3Vector3FloatData m_localFrame;
- bInvalidHandle *m_rigidBody;
- int m_nodeIndex;
- float m_c2;
- };
-
-
-// -------------------------------------------------- //
- class SoftBodyConfigData
- {
- public:
- int m_aeroModel;
- float m_baumgarte;
- float m_damping;
- float m_drag;
- float m_lift;
- float m_pressure;
- float m_volume;
- float m_dynamicFriction;
- float m_poseMatch;
- float m_rigidContactHardness;
- float m_kineticContactHardness;
- float m_softContactHardness;
- float m_anchorHardness;
- float m_softRigidClusterHardness;
- float m_softKineticClusterHardness;
- float m_softSoftClusterHardness;
- float m_softRigidClusterImpulseSplit;
- float m_softKineticClusterImpulseSplit;
- float m_softSoftClusterImpulseSplit;
- float m_maxVolume;
- float m_timeScale;
- int m_velocityIterations;
- int m_positionIterations;
- int m_driftIterations;
- int m_clusterIterations;
- int m_collisionFlags;
- };
-
-
-// -------------------------------------------------- //
- class SoftBodyPoseData
- {
- public:
- b3Matrix3x3FloatData m_rot;
- b3Matrix3x3FloatData m_scale;
- b3Matrix3x3FloatData m_aqq;
- b3Vector3FloatData m_com;
- b3Vector3FloatData *m_positions;
- float *m_weights;
- int m_numPositions;
- int m_numWeigts;
- int m_bvolume;
- int m_bframe;
- float m_restVolume;
- int m_pad;
- };
-
-
-// -------------------------------------------------- //
- class SoftBodyClusterData
- {
- public:
- b3TransformFloatData m_framexform;
- b3Matrix3x3FloatData m_locii;
- b3Matrix3x3FloatData m_invwi;
- b3Vector3FloatData m_com;
- b3Vector3FloatData m_vimpulses[2];
- b3Vector3FloatData m_dimpulses[2];
- b3Vector3FloatData m_lv;
- b3Vector3FloatData m_av;
- b3Vector3FloatData *m_framerefs;
- int *m_nodeIndices;
- float *m_masses;
- int m_numFrameRefs;
- int m_numNodes;
- int m_numMasses;
- float m_idmass;
- float m_imass;
- int m_nvimpulses;
- int m_ndimpulses;
- float m_ndamping;
- float m_ldamping;
- float m_adamping;
- float m_matching;
- float m_maxSelfCollisionImpulse;
- float m_selfCollisionImpulseFactor;
- int m_containsAnchor;
- int m_collide;
- int m_clusterIndex;
- };
-
-
-// -------------------------------------------------- //
- class b3SoftBodyJointData
- {
- public:
- void *m_bodyA;
- void *m_bodyB;
- b3Vector3FloatData m_refs[2];
- float m_cfm;
- float m_erp;
- float m_split;
- int m_delete;
- b3Vector3FloatData m_relPosition[2];
- int m_bodyAtype;
- int m_bodyBtype;
- int m_jointType;
- int m_pad;
- };
-
-
-// -------------------------------------------------- //
- class b3SoftBodyFloatData
- {
- public:
- b3CollisionObjectFloatData m_collisionObjectData;
- SoftBodyPoseData *m_pose;
- SoftBodyMaterialData **m_materials;
- SoftBodyNodeData *m_nodes;
- SoftBodyLinkData *m_links;
- SoftBodyFaceData *m_faces;
- SoftBodyTetraData *m_tetrahedra;
- SoftRigidAnchorData *m_anchors;
- SoftBodyClusterData *m_clusters;
- b3SoftBodyJointData *m_joints;
- int m_numMaterials;
- int m_numNodes;
- int m_numLinks;
- int m_numFaces;
- int m_numTetrahedra;
- int m_numAnchors;
- int m_numClusters;
- int m_numJoints;
- SoftBodyConfigData m_config;
- };
-
-
-}
-#endif//__BULLET2_H__ \ No newline at end of file
+} bInvalidHandle;
+
+class PointerArray;
+class b3PhysicsSystem;
+class ListBase;
+class b3Vector3FloatData;
+class b3Vector3DoubleData;
+class b3Matrix3x3FloatData;
+class b3Matrix3x3DoubleData;
+class b3TransformFloatData;
+class b3TransformDoubleData;
+class b3BvhSubtreeInfoData;
+class b3OptimizedBvhNodeFloatData;
+class b3OptimizedBvhNodeDoubleData;
+class b3QuantizedBvhNodeData;
+class b3QuantizedBvhFloatData;
+class b3QuantizedBvhDoubleData;
+class b3CollisionShapeData;
+class b3StaticPlaneShapeData;
+class b3ConvexInternalShapeData;
+class b3PositionAndRadius;
+class b3MultiSphereShapeData;
+class b3IntIndexData;
+class b3ShortIntIndexData;
+class b3ShortIntIndexTripletData;
+class b3CharIndexTripletData;
+class b3MeshPartData;
+class b3StridingMeshInterfaceData;
+class b3TriangleMeshShapeData;
+class b3ScaledTriangleMeshShapeData;
+class b3CompoundShapeChildData;
+class b3CompoundShapeData;
+class b3CylinderShapeData;
+class b3CapsuleShapeData;
+class b3TriangleInfoData;
+class b3TriangleInfoMapData;
+class b3GImpactMeshShapeData;
+class b3ConvexHullShapeData;
+class b3CollisionObjectDoubleData;
+class b3CollisionObjectFloatData;
+class b3DynamicsWorldDoubleData;
+class b3DynamicsWorldFloatData;
+class b3RigidBodyFloatData;
+class b3RigidBodyDoubleData;
+class b3ConstraintInfo1;
+class b3TypedConstraintData;
+class b3Point2PointConstraintFloatData;
+class b3Point2PointConstraintDoubleData;
+class b3HingeConstraintDoubleData;
+class b3HingeConstraintFloatData;
+class b3ConeTwistConstraintData;
+class b3Generic6DofConstraintData;
+class b3Generic6DofSpringConstraintData;
+class b3SliderConstraintData;
+class b3ContactSolverInfoDoubleData;
+class b3ContactSolverInfoFloatData;
+class SoftBodyMaterialData;
+class SoftBodyNodeData;
+class SoftBodyLinkData;
+class SoftBodyFaceData;
+class SoftBodyTetraData;
+class SoftRigidAnchorData;
+class SoftBodyConfigData;
+class SoftBodyPoseData;
+class SoftBodyClusterData;
+class b3SoftBodyJointData;
+class b3SoftBodyFloatData;
+// -------------------------------------------------- //
+class PointerArray
+{
+public:
+ int m_size;
+ int m_capacity;
+ void *m_data;
+};
+
+// -------------------------------------------------- //
+class b3PhysicsSystem
+{
+public:
+ PointerArray m_collisionShapes;
+ PointerArray m_collisionObjects;
+ PointerArray m_constraints;
+};
+
+// -------------------------------------------------- //
+class ListBase
+{
+public:
+ void *first;
+ void *last;
+};
+
+// -------------------------------------------------- //
+class b3Vector3FloatData
+{
+public:
+ float m_floats[4];
+};
+
+// -------------------------------------------------- //
+class b3Vector3DoubleData
+{
+public:
+ double m_floats[4];
+};
+
+// -------------------------------------------------- //
+class b3Matrix3x3FloatData
+{
+public:
+ b3Vector3FloatData m_el[3];
+};
+
+// -------------------------------------------------- //
+class b3Matrix3x3DoubleData
+{
+public:
+ b3Vector3DoubleData m_el[3];
+};
+
+// -------------------------------------------------- //
+class b3TransformFloatData
+{
+public:
+ b3Matrix3x3FloatData m_basis;
+ b3Vector3FloatData m_origin;
+};
+
+// -------------------------------------------------- //
+class b3TransformDoubleData
+{
+public:
+ b3Matrix3x3DoubleData m_basis;
+ b3Vector3DoubleData m_origin;
+};
+
+// -------------------------------------------------- //
+class b3BvhSubtreeInfoData
+{
+public:
+ int m_rootNodeIndex;
+ int m_subtreeSize;
+ short m_quantizedAabbMin[3];
+ short m_quantizedAabbMax[3];
+};
+
+// -------------------------------------------------- //
+class b3OptimizedBvhNodeFloatData
+{
+public:
+ b3Vector3FloatData m_aabbMinOrg;
+ b3Vector3FloatData m_aabbMaxOrg;
+ int m_escapeIndex;
+ int m_subPart;
+ int m_triangleIndex;
+ char m_pad[4];
+};
+
+// -------------------------------------------------- //
+class b3OptimizedBvhNodeDoubleData
+{
+public:
+ b3Vector3DoubleData m_aabbMinOrg;
+ b3Vector3DoubleData m_aabbMaxOrg;
+ int m_escapeIndex;
+ int m_subPart;
+ int m_triangleIndex;
+ char m_pad[4];
+};
+
+// -------------------------------------------------- //
+class b3QuantizedBvhNodeData
+{
+public:
+ short m_quantizedAabbMin[3];
+ short m_quantizedAabbMax[3];
+ int m_escapeIndexOrTriangleIndex;
+};
+
+// -------------------------------------------------- //
+class b3QuantizedBvhFloatData
+{
+public:
+ b3Vector3FloatData m_bvhAabbMin;
+ b3Vector3FloatData m_bvhAabbMax;
+ b3Vector3FloatData m_bvhQuantization;
+ int m_curNodeIndex;
+ int m_useQuantization;
+ int m_numContiguousLeafNodes;
+ int m_numQuantizedContiguousNodes;
+ b3OptimizedBvhNodeFloatData *m_contiguousNodesPtr;
+ b3QuantizedBvhNodeData *m_quantizedContiguousNodesPtr;
+ b3BvhSubtreeInfoData *m_subTreeInfoPtr;
+ int m_traversalMode;
+ int m_numSubtreeHeaders;
+};
+
+// -------------------------------------------------- //
+class b3QuantizedBvhDoubleData
+{
+public:
+ b3Vector3DoubleData m_bvhAabbMin;
+ b3Vector3DoubleData m_bvhAabbMax;
+ b3Vector3DoubleData m_bvhQuantization;
+ int m_curNodeIndex;
+ int m_useQuantization;
+ int m_numContiguousLeafNodes;
+ int m_numQuantizedContiguousNodes;
+ b3OptimizedBvhNodeDoubleData *m_contiguousNodesPtr;
+ b3QuantizedBvhNodeData *m_quantizedContiguousNodesPtr;
+ int m_traversalMode;
+ int m_numSubtreeHeaders;
+ b3BvhSubtreeInfoData *m_subTreeInfoPtr;
+};
+
+// -------------------------------------------------- //
+class b3CollisionShapeData
+{
+public:
+ char *m_name;
+ int m_shapeType;
+ char m_padding[4];
+};
+
+// -------------------------------------------------- //
+class b3StaticPlaneShapeData
+{
+public:
+ b3CollisionShapeData m_collisionShapeData;
+ b3Vector3FloatData m_localScaling;
+ b3Vector3FloatData m_planeNormal;
+ float m_planeConstant;
+ char m_pad[4];
+};
+
+// -------------------------------------------------- //
+class b3ConvexInternalShapeData
+{
+public:
+ b3CollisionShapeData m_collisionShapeData;
+ b3Vector3FloatData m_localScaling;
+ b3Vector3FloatData m_implicitShapeDimensions;
+ float m_collisionMargin;
+ int m_padding;
+};
+
+// -------------------------------------------------- //
+class b3PositionAndRadius
+{
+public:
+ b3Vector3FloatData m_pos;
+ float m_radius;
+};
+
+// -------------------------------------------------- //
+class b3MultiSphereShapeData
+{
+public:
+ b3ConvexInternalShapeData m_convexInternalShapeData;
+ b3PositionAndRadius *m_localPositionArrayPtr;
+ int m_localPositionArraySize;
+ char m_padding[4];
+};
+
+// -------------------------------------------------- //
+class b3IntIndexData
+{
+public:
+ int m_value;
+};
+
+// -------------------------------------------------- //
+class b3ShortIntIndexData
+{
+public:
+ short m_value;
+ char m_pad[2];
+};
+
+// -------------------------------------------------- //
+class b3ShortIntIndexTripletData
+{
+public:
+ short m_values[3];
+ char m_pad[2];
+};
+
+// -------------------------------------------------- //
+class b3CharIndexTripletData
+{
+public:
+ char m_values[3];
+ char m_pad;
+};
+
+// -------------------------------------------------- //
+class b3MeshPartData
+{
+public:
+ b3Vector3FloatData *m_vertices3f;
+ b3Vector3DoubleData *m_vertices3d;
+ b3IntIndexData *m_indices32;
+ b3ShortIntIndexTripletData *m_3indices16;
+ b3CharIndexTripletData *m_3indices8;
+ b3ShortIntIndexData *m_indices16;
+ int m_numTriangles;
+ int m_numVertices;
+};
+
+// -------------------------------------------------- //
+class b3StridingMeshInterfaceData
+{
+public:
+ b3MeshPartData *m_meshPartsPtr;
+ b3Vector3FloatData m_scaling;
+ int m_numMeshParts;
+ char m_padding[4];
+};
+
+// -------------------------------------------------- //
+class b3TriangleMeshShapeData
+{
+public:
+ b3CollisionShapeData m_collisionShapeData;
+ b3StridingMeshInterfaceData m_meshInterface;
+ b3QuantizedBvhFloatData *m_quantizedFloatBvh;
+ b3QuantizedBvhDoubleData *m_quantizedDoubleBvh;
+ b3TriangleInfoMapData *m_triangleInfoMap;
+ float m_collisionMargin;
+ char m_pad3[4];
+};
+
+// -------------------------------------------------- //
+class b3ScaledTriangleMeshShapeData
+{
+public:
+ b3TriangleMeshShapeData m_trimeshShapeData;
+ b3Vector3FloatData m_localScaling;
+};
+
+// -------------------------------------------------- //
+class b3CompoundShapeChildData
+{
+public:
+ b3TransformFloatData m_transform;
+ b3CollisionShapeData *m_childShape;
+ int m_childShapeType;
+ float m_childMargin;
+};
+
+// -------------------------------------------------- //
+class b3CompoundShapeData
+{
+public:
+ b3CollisionShapeData m_collisionShapeData;
+ b3CompoundShapeChildData *m_childShapePtr;
+ int m_numChildShapes;
+ float m_collisionMargin;
+};
+
+// -------------------------------------------------- //
+class b3CylinderShapeData
+{
+public:
+ b3ConvexInternalShapeData m_convexInternalShapeData;
+ int m_upAxis;
+ char m_padding[4];
+};
+
+// -------------------------------------------------- //
+class b3CapsuleShapeData
+{
+public:
+ b3ConvexInternalShapeData m_convexInternalShapeData;
+ int m_upAxis;
+ char m_padding[4];
+};
+
+// -------------------------------------------------- //
+class b3TriangleInfoData
+{
+public:
+ int m_flags;
+ float m_edgeV0V1Angle;
+ float m_edgeV1V2Angle;
+ float m_edgeV2V0Angle;
+};
+
+// -------------------------------------------------- //
+class b3TriangleInfoMapData
+{
+public:
+ int *m_hashTablePtr;
+ int *m_nextPtr;
+ b3TriangleInfoData *m_valueArrayPtr;
+ int *m_keyArrayPtr;
+ float m_convexEpsilon;
+ float m_planarEpsilon;
+ float m_equalVertexThreshold;
+ float m_edgeDistanceThreshold;
+ float m_zeroAreaThreshold;
+ int m_nextSize;
+ int m_hashTableSize;
+ int m_numValues;
+ int m_numKeys;
+ char m_padding[4];
+};
+
+// -------------------------------------------------- //
+class b3GImpactMeshShapeData
+{
+public:
+ b3CollisionShapeData m_collisionShapeData;
+ b3StridingMeshInterfaceData m_meshInterface;
+ b3Vector3FloatData m_localScaling;
+ float m_collisionMargin;
+ int m_gimpactSubType;
+};
+
+// -------------------------------------------------- //
+class b3ConvexHullShapeData
+{
+public:
+ b3ConvexInternalShapeData m_convexInternalShapeData;
+ b3Vector3FloatData *m_unscaledPointsFloatPtr;
+ b3Vector3DoubleData *m_unscaledPointsDoublePtr;
+ int m_numUnscaledPoints;
+ char m_padding3[4];
+};
+
+// -------------------------------------------------- //
+class b3CollisionObjectDoubleData
+{
+public:
+ void *m_broadphaseHandle;
+ void *m_collisionShape;
+ b3CollisionShapeData *m_rootCollisionShape;
+ char *m_name;
+ b3TransformDoubleData m_worldTransform;
+ b3TransformDoubleData m_interpolationWorldTransform;
+ b3Vector3DoubleData m_interpolationLinearVelocity;
+ b3Vector3DoubleData m_interpolationAngularVelocity;
+ b3Vector3DoubleData m_anisotropicFriction;
+ double m_contactProcessingThreshold;
+ double m_deactivationTime;
+ double m_friction;
+ double m_rollingFriction;
+ double m_restitution;
+ double m_hitFraction;
+ double m_ccdSweptSphereRadius;
+ double m_ccdMotionThreshold;
+ int m_hasAnisotropicFriction;
+ int m_collisionFlags;
+ int m_islandTag1;
+ int m_companionId;
+ int m_activationState1;
+ int m_internalType;
+ int m_checkCollideWith;
+ char m_padding[4];
+};
+
+// -------------------------------------------------- //
+class b3CollisionObjectFloatData
+{
+public:
+ void *m_broadphaseHandle;
+ void *m_collisionShape;
+ b3CollisionShapeData *m_rootCollisionShape;
+ char *m_name;
+ b3TransformFloatData m_worldTransform;
+ b3TransformFloatData m_interpolationWorldTransform;
+ b3Vector3FloatData m_interpolationLinearVelocity;
+ b3Vector3FloatData m_interpolationAngularVelocity;
+ b3Vector3FloatData m_anisotropicFriction;
+ float m_contactProcessingThreshold;
+ float m_deactivationTime;
+ float m_friction;
+ float m_rollingFriction;
+ float m_restitution;
+ float m_hitFraction;
+ float m_ccdSweptSphereRadius;
+ float m_ccdMotionThreshold;
+ int m_hasAnisotropicFriction;
+ int m_collisionFlags;
+ int m_islandTag1;
+ int m_companionId;
+ int m_activationState1;
+ int m_internalType;
+ int m_checkCollideWith;
+ char m_padding[4];
+};
+
+// -------------------------------------------------- //
+class b3RigidBodyFloatData
+{
+public:
+ b3CollisionObjectFloatData m_collisionObjectData;
+ b3Matrix3x3FloatData m_invInertiaTensorWorld;
+ b3Vector3FloatData m_linearVelocity;
+ b3Vector3FloatData m_angularVelocity;
+ b3Vector3FloatData m_angularFactor;
+ b3Vector3FloatData m_linearFactor;
+ b3Vector3FloatData m_gravity;
+ b3Vector3FloatData m_gravity_acceleration;
+ b3Vector3FloatData m_invInertiaLocal;
+ b3Vector3FloatData m_totalForce;
+ b3Vector3FloatData m_totalTorque;
+ float m_inverseMass;
+ float m_linearDamping;
+ float m_angularDamping;
+ float m_additionalDampingFactor;
+ float m_additionalLinearDampingThresholdSqr;
+ float m_additionalAngularDampingThresholdSqr;
+ float m_additionalAngularDampingFactor;
+ float m_linearSleepingThreshold;
+ float m_angularSleepingThreshold;
+ int m_additionalDamping;
+};
+
+// -------------------------------------------------- //
+class b3RigidBodyDoubleData
+{
+public:
+ b3CollisionObjectDoubleData m_collisionObjectData;
+ b3Matrix3x3DoubleData m_invInertiaTensorWorld;
+ b3Vector3DoubleData m_linearVelocity;
+ b3Vector3DoubleData m_angularVelocity;
+ b3Vector3DoubleData m_angularFactor;
+ b3Vector3DoubleData m_linearFactor;
+ b3Vector3DoubleData m_gravity;
+ b3Vector3DoubleData m_gravity_acceleration;
+ b3Vector3DoubleData m_invInertiaLocal;
+ b3Vector3DoubleData m_totalForce;
+ b3Vector3DoubleData m_totalTorque;
+ double m_inverseMass;
+ double m_linearDamping;
+ double m_angularDamping;
+ double m_additionalDampingFactor;
+ double m_additionalLinearDampingThresholdSqr;
+ double m_additionalAngularDampingThresholdSqr;
+ double m_additionalAngularDampingFactor;
+ double m_linearSleepingThreshold;
+ double m_angularSleepingThreshold;
+ int m_additionalDamping;
+ char m_padding[4];
+};
+
+// -------------------------------------------------- //
+class b3ConstraintInfo1
+{
+public:
+ int m_numConstraintRows;
+ int nub;
+};
+
+// -------------------------------------------------- //
+class b3TypedConstraintData
+{
+public:
+ bInvalidHandle *m_rbA;
+ bInvalidHandle *m_rbB;
+ char *m_name;
+ int m_objectType;
+ int m_userConstraintType;
+ int m_userConstraintId;
+ int m_needsFeedback;
+ float m_appliedImpulse;
+ float m_dbgDrawSize;
+ int m_disableCollisionsBetweenLinkedBodies;
+ int m_overrideNumSolverIterations;
+ float m_breakingImpulseThreshold;
+ int m_isEnabled;
+};
+
+// -------------------------------------------------- //
+class b3Point2PointConstraintFloatData
+{
+public:
+ b3TypedConstraintData m_typeConstraintData;
+ b3Vector3FloatData m_pivotInA;
+ b3Vector3FloatData m_pivotInB;
+};
+
+// -------------------------------------------------- //
+class b3Point2PointConstraintDoubleData
+{
+public:
+ b3TypedConstraintData m_typeConstraintData;
+ b3Vector3DoubleData m_pivotInA;
+ b3Vector3DoubleData m_pivotInB;
+};
+
+// -------------------------------------------------- //
+class b3HingeConstraintDoubleData
+{
+public:
+ b3TypedConstraintData m_typeConstraintData;
+ b3TransformDoubleData m_rbAFrame;
+ b3TransformDoubleData m_rbBFrame;
+ int m_useReferenceFrameA;
+ int m_angularOnly;
+ int m_enableAngularMotor;
+ float m_motorTargetVelocity;
+ float m_maxMotorImpulse;
+ float m_lowerLimit;
+ float m_upperLimit;
+ float m_limitSoftness;
+ float m_biasFactor;
+ float m_relaxationFactor;
+};
+
+// -------------------------------------------------- //
+class b3HingeConstraintFloatData
+{
+public:
+ b3TypedConstraintData m_typeConstraintData;
+ b3TransformFloatData m_rbAFrame;
+ b3TransformFloatData m_rbBFrame;
+ int m_useReferenceFrameA;
+ int m_angularOnly;
+ int m_enableAngularMotor;
+ float m_motorTargetVelocity;
+ float m_maxMotorImpulse;
+ float m_lowerLimit;
+ float m_upperLimit;
+ float m_limitSoftness;
+ float m_biasFactor;
+ float m_relaxationFactor;
+};
+
+// -------------------------------------------------- //
+class b3ConeTwistConstraintData
+{
+public:
+ b3TypedConstraintData m_typeConstraintData;
+ b3TransformFloatData m_rbAFrame;
+ b3TransformFloatData m_rbBFrame;
+ float m_swingSpan1;
+ float m_swingSpan2;
+ float m_twistSpan;
+ float m_limitSoftness;
+ float m_biasFactor;
+ float m_relaxationFactor;
+ float m_damping;
+ char m_pad[4];
+};
+
+// -------------------------------------------------- //
+class b3Generic6DofConstraintData
+{
+public:
+ b3TypedConstraintData m_typeConstraintData;
+ b3TransformFloatData m_rbAFrame;
+ b3TransformFloatData m_rbBFrame;
+ b3Vector3FloatData m_linearUpperLimit;
+ b3Vector3FloatData m_linearLowerLimit;
+ b3Vector3FloatData m_angularUpperLimit;
+ b3Vector3FloatData m_angularLowerLimit;
+ int m_useLinearReferenceFrameA;
+ int m_useOffsetForConstraintFrame;
+};
+
+// -------------------------------------------------- //
+class b3Generic6DofSpringConstraintData
+{
+public:
+ b3Generic6DofConstraintData m_6dofData;
+ int m_springEnabled[6];
+ float m_equilibriumPoint[6];
+ float m_springStiffness[6];
+ float m_springDamping[6];
+};
+
+// -------------------------------------------------- //
+class b3SliderConstraintData
+{
+public:
+ b3TypedConstraintData m_typeConstraintData;
+ b3TransformFloatData m_rbAFrame;
+ b3TransformFloatData m_rbBFrame;
+ float m_linearUpperLimit;
+ float m_linearLowerLimit;
+ float m_angularUpperLimit;
+ float m_angularLowerLimit;
+ int m_useLinearReferenceFrameA;
+ int m_useOffsetForConstraintFrame;
+};
+
+// -------------------------------------------------- //
+class b3ContactSolverInfoDoubleData
+{
+public:
+ double m_tau;
+ double m_damping;
+ double m_friction;
+ double m_timeStep;
+ double m_restitution;
+ double m_maxErrorReduction;
+ double m_sor;
+ double m_erp;
+ double m_erp2;
+ double m_globalCfm;
+ double m_splitImpulsePenetrationThreshold;
+ double m_splitImpulseTurnErp;
+ double m_linearSlop;
+ double m_warmstartingFactor;
+ double m_maxGyroscopicForce;
+ double m_singleAxisRollingFrictionThreshold;
+ int m_numIterations;
+ int m_solverMode;
+ int m_restingContactRestitutionThreshold;
+ int m_minimumSolverBatchSize;
+ int m_splitImpulse;
+ char m_padding[4];
+};
+
+// -------------------------------------------------- //
+class b3ContactSolverInfoFloatData
+{
+public:
+ float m_tau;
+ float m_damping;
+ float m_friction;
+ float m_timeStep;
+ float m_restitution;
+ float m_maxErrorReduction;
+ float m_sor;
+ float m_erp;
+ float m_erp2;
+ float m_globalCfm;
+ float m_splitImpulsePenetrationThreshold;
+ float m_splitImpulseTurnErp;
+ float m_linearSlop;
+ float m_warmstartingFactor;
+ float m_maxGyroscopicForce;
+ float m_singleAxisRollingFrictionThreshold;
+ int m_numIterations;
+ int m_solverMode;
+ int m_restingContactRestitutionThreshold;
+ int m_minimumSolverBatchSize;
+ int m_splitImpulse;
+ char m_padding[4];
+};
+
+// -------------------------------------------------- //
+class b3DynamicsWorldDoubleData
+{
+public:
+ b3ContactSolverInfoDoubleData m_solverInfo;
+ b3Vector3DoubleData m_gravity;
+};
+
+// -------------------------------------------------- //
+class b3DynamicsWorldFloatData
+{
+public:
+ b3ContactSolverInfoFloatData m_solverInfo;
+ b3Vector3FloatData m_gravity;
+};
+
+// -------------------------------------------------- //
+class SoftBodyMaterialData
+{
+public:
+ float m_linearStiffness;
+ float m_angularStiffness;
+ float m_volumeStiffness;
+ int m_flags;
+};
+
+// -------------------------------------------------- //
+class SoftBodyNodeData
+{
+public:
+ SoftBodyMaterialData *m_material;
+ b3Vector3FloatData m_position;
+ b3Vector3FloatData m_previousPosition;
+ b3Vector3FloatData m_velocity;
+ b3Vector3FloatData m_accumulatedForce;
+ b3Vector3FloatData m_normal;
+ float m_inverseMass;
+ float m_area;
+ int m_attach;
+ int m_pad;
+};
+
+// -------------------------------------------------- //
+class SoftBodyLinkData
+{
+public:
+ SoftBodyMaterialData *m_material;
+ int m_nodeIndices[2];
+ float m_restLength;
+ int m_bbending;
+};
+
+// -------------------------------------------------- //
+class SoftBodyFaceData
+{
+public:
+ b3Vector3FloatData m_normal;
+ SoftBodyMaterialData *m_material;
+ int m_nodeIndices[3];
+ float m_restArea;
+};
+
+// -------------------------------------------------- //
+class SoftBodyTetraData
+{
+public:
+ b3Vector3FloatData m_c0[4];
+ SoftBodyMaterialData *m_material;
+ int m_nodeIndices[4];
+ float m_restVolume;
+ float m_c1;
+ float m_c2;
+ int m_pad;
+};
+
+// -------------------------------------------------- //
+class SoftRigidAnchorData
+{
+public:
+ b3Matrix3x3FloatData m_c0;
+ b3Vector3FloatData m_c1;
+ b3Vector3FloatData m_localFrame;
+ bInvalidHandle *m_rigidBody;
+ int m_nodeIndex;
+ float m_c2;
+};
+
+// -------------------------------------------------- //
+class SoftBodyConfigData
+{
+public:
+ int m_aeroModel;
+ float m_baumgarte;
+ float m_damping;
+ float m_drag;
+ float m_lift;
+ float m_pressure;
+ float m_volume;
+ float m_dynamicFriction;
+ float m_poseMatch;
+ float m_rigidContactHardness;
+ float m_kineticContactHardness;
+ float m_softContactHardness;
+ float m_anchorHardness;
+ float m_softRigidClusterHardness;
+ float m_softKineticClusterHardness;
+ float m_softSoftClusterHardness;
+ float m_softRigidClusterImpulseSplit;
+ float m_softKineticClusterImpulseSplit;
+ float m_softSoftClusterImpulseSplit;
+ float m_maxVolume;
+ float m_timeScale;
+ int m_velocityIterations;
+ int m_positionIterations;
+ int m_driftIterations;
+ int m_clusterIterations;
+ int m_collisionFlags;
+};
+
+// -------------------------------------------------- //
+class SoftBodyPoseData
+{
+public:
+ b3Matrix3x3FloatData m_rot;
+ b3Matrix3x3FloatData m_scale;
+ b3Matrix3x3FloatData m_aqq;
+ b3Vector3FloatData m_com;
+ b3Vector3FloatData *m_positions;
+ float *m_weights;
+ int m_numPositions;
+ int m_numWeigts;
+ int m_bvolume;
+ int m_bframe;
+ float m_restVolume;
+ int m_pad;
+};
+
+// -------------------------------------------------- //
+class SoftBodyClusterData
+{
+public:
+ b3TransformFloatData m_framexform;
+ b3Matrix3x3FloatData m_locii;
+ b3Matrix3x3FloatData m_invwi;
+ b3Vector3FloatData m_com;
+ b3Vector3FloatData m_vimpulses[2];
+ b3Vector3FloatData m_dimpulses[2];
+ b3Vector3FloatData m_lv;
+ b3Vector3FloatData m_av;
+ b3Vector3FloatData *m_framerefs;
+ int *m_nodeIndices;
+ float *m_masses;
+ int m_numFrameRefs;
+ int m_numNodes;
+ int m_numMasses;
+ float m_idmass;
+ float m_imass;
+ int m_nvimpulses;
+ int m_ndimpulses;
+ float m_ndamping;
+ float m_ldamping;
+ float m_adamping;
+ float m_matching;
+ float m_maxSelfCollisionImpulse;
+ float m_selfCollisionImpulseFactor;
+ int m_containsAnchor;
+ int m_collide;
+ int m_clusterIndex;
+};
+
+// -------------------------------------------------- //
+class b3SoftBodyJointData
+{
+public:
+ void *m_bodyA;
+ void *m_bodyB;
+ b3Vector3FloatData m_refs[2];
+ float m_cfm;
+ float m_erp;
+ float m_split;
+ int m_delete;
+ b3Vector3FloatData m_relPosition[2];
+ int m_bodyAtype;
+ int m_bodyBtype;
+ int m_jointType;
+ int m_pad;
+};
+
+// -------------------------------------------------- //
+class b3SoftBodyFloatData
+{
+public:
+ b3CollisionObjectFloatData m_collisionObjectData;
+ SoftBodyPoseData *m_pose;
+ SoftBodyMaterialData **m_materials;
+ SoftBodyNodeData *m_nodes;
+ SoftBodyLinkData *m_links;
+ SoftBodyFaceData *m_faces;
+ SoftBodyTetraData *m_tetrahedra;
+ SoftRigidAnchorData *m_anchors;
+ SoftBodyClusterData *m_clusters;
+ b3SoftBodyJointData *m_joints;
+ int m_numMaterials;
+ int m_numNodes;
+ int m_numLinks;
+ int m_numFaces;
+ int m_numTetrahedra;
+ int m_numAnchors;
+ int m_numClusters;
+ int m_numJoints;
+ SoftBodyConfigData m_config;
+};
+
+} // namespace Bullet3SerializeBullet2
+#endif //__BULLET2_H__ \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3BulletFile.cpp b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3BulletFile.cpp
index c3ceb8388c..d2a7163670 100644
--- a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3BulletFile.cpp
+++ b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3BulletFile.cpp
@@ -17,12 +17,11 @@ subject to the following restrictions:
#include "b3Defines.h"
#include "b3DNA.h"
-#if !defined( __CELLOS_LV2__) && !defined(__MWERKS__)
+#if !defined(__CELLOS_LV2__) && !defined(__MWERKS__)
#include <memory.h>
#endif
#include <string.h>
-
// 32 && 64 bit versions
#ifdef B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
#ifdef _WIN64
@@ -31,130 +30,116 @@ extern int b3s_bulletDNAlen64;
#else
extern char b3s_bulletDNAstr[];
extern int b3s_bulletDNAlen;
-#endif //_WIN64
-#else//B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+#endif //_WIN64
+#else //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
extern char b3s_bulletDNAstr64[];
extern int b3s_bulletDNAlen64;
extern char b3s_bulletDNAstr[];
extern int b3s_bulletDNAlen;
-#endif //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+#endif //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
using namespace bParse;
b3BulletFile::b3BulletFile()
-:bFile("", "BULLET ")
+ : bFile("", "BULLET ")
{
- mMemoryDNA = new bDNA(); //this memory gets released in the bFile::~bFile destructor,@todo not consistent with the rule 'who allocates it, has to deallocate it"
+ mMemoryDNA = new bDNA(); //this memory gets released in the bFile::~bFile destructor,@todo not consistent with the rule 'who allocates it, has to deallocate it"
m_DnaCopy = 0;
-
#ifdef B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
#ifdef _WIN64
- m_DnaCopy = (char*)b3AlignedAlloc(b3s_bulletDNAlen64,16);
- memcpy(m_DnaCopy,b3s_bulletDNAstr64,b3s_bulletDNAlen64);
- mMemoryDNA->init(m_DnaCopy,b3s_bulletDNAlen64);
-#else//_WIN64
- m_DnaCopy = (char*)b3AlignedAlloc(b3s_bulletDNAlen,16);
- memcpy(m_DnaCopy,b3s_bulletDNAstr,b3s_bulletDNAlen);
- mMemoryDNA->init(m_DnaCopy,b3s_bulletDNAlen);
-#endif//_WIN64
-#else//B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+ m_DnaCopy = (char*)b3AlignedAlloc(b3s_bulletDNAlen64, 16);
+ memcpy(m_DnaCopy, b3s_bulletDNAstr64, b3s_bulletDNAlen64);
+ mMemoryDNA->init(m_DnaCopy, b3s_bulletDNAlen64);
+#else //_WIN64
+ m_DnaCopy = (char*)b3AlignedAlloc(b3s_bulletDNAlen, 16);
+ memcpy(m_DnaCopy, b3s_bulletDNAstr, b3s_bulletDNAlen);
+ mMemoryDNA->init(m_DnaCopy, b3s_bulletDNAlen);
+#endif //_WIN64
+#else //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
if (VOID_IS_8)
{
- m_DnaCopy = (char*) b3AlignedAlloc(b3s_bulletDNAlen64,16);
- memcpy(m_DnaCopy,b3s_bulletDNAstr64,b3s_bulletDNAlen64);
- mMemoryDNA->init(m_DnaCopy,b3s_bulletDNAlen64);
+ m_DnaCopy = (char*)b3AlignedAlloc(b3s_bulletDNAlen64, 16);
+ memcpy(m_DnaCopy, b3s_bulletDNAstr64, b3s_bulletDNAlen64);
+ mMemoryDNA->init(m_DnaCopy, b3s_bulletDNAlen64);
}
else
{
- m_DnaCopy =(char*) b3AlignedAlloc(b3s_bulletDNAlen,16);
- memcpy(m_DnaCopy,b3s_bulletDNAstr,b3s_bulletDNAlen);
- mMemoryDNA->init(m_DnaCopy,b3s_bulletDNAlen);
+ m_DnaCopy = (char*)b3AlignedAlloc(b3s_bulletDNAlen, 16);
+ memcpy(m_DnaCopy, b3s_bulletDNAstr, b3s_bulletDNAlen);
+ mMemoryDNA->init(m_DnaCopy, b3s_bulletDNAlen);
}
-#endif//B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+#endif //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
}
-
-
b3BulletFile::b3BulletFile(const char* fileName)
-:bFile(fileName, "BULLET ")
+ : bFile(fileName, "BULLET ")
{
m_DnaCopy = 0;
}
-
-
-b3BulletFile::b3BulletFile(char *memoryBuffer, int len)
-:bFile(memoryBuffer,len, "BULLET ")
+b3BulletFile::b3BulletFile(char* memoryBuffer, int len)
+ : bFile(memoryBuffer, len, "BULLET ")
{
m_DnaCopy = 0;
}
-
b3BulletFile::~b3BulletFile()
{
if (m_DnaCopy)
b3AlignedFree(m_DnaCopy);
-
while (m_dataBlocks.size())
{
- char* dataBlock = m_dataBlocks[m_dataBlocks.size()-1];
+ char* dataBlock = m_dataBlocks[m_dataBlocks.size() - 1];
delete[] dataBlock;
m_dataBlocks.pop_back();
}
-
}
-
-
// ----------------------------------------------------- //
void b3BulletFile::parseData()
{
-// printf ("Building datablocks");
-// printf ("Chunk size = %d",CHUNK_HEADER_LEN);
-// printf ("File chunk size = %d",ChunkUtils::getOffset(mFlags));
+ // printf ("Building datablocks");
+ // printf ("Chunk size = %d",CHUNK_HEADER_LEN);
+ // printf ("File chunk size = %d",ChunkUtils::getOffset(mFlags));
- const bool brokenDNA = (mFlags&FD_BROKEN_DNA)!=0;
+ const bool brokenDNA = (mFlags & FD_BROKEN_DNA) != 0;
//const bool swap = (mFlags&FD_ENDIAN_SWAP)!=0;
-
mDataStart = 12;
- char *dataPtr = mFileBuffer+mDataStart;
+ char* dataPtr = mFileBuffer + mDataStart;
bChunkInd dataChunk;
dataChunk.code = 0;
-
//dataPtr += ChunkUtils::getNextBlock(&dataChunk, dataPtr, mFlags);
int seek = getNextBlock(&dataChunk, dataPtr, mFlags);
-
-
- if (mFlags &FD_ENDIAN_SWAP)
+
+ if (mFlags & FD_ENDIAN_SWAP)
swapLen(dataPtr);
//dataPtr += ChunkUtils::getOffset(mFlags);
- char *dataPtrHead = 0;
+ char* dataPtrHead = 0;
while (dataChunk.code != B3_DNA1)
{
- if (!brokenDNA || (dataChunk.code != B3_QUANTIZED_BVH_CODE) )
+ if (!brokenDNA || (dataChunk.code != B3_QUANTIZED_BVH_CODE))
{
-
// one behind
if (dataChunk.code == B3_SDNA) break;
//if (dataChunk.code == DNA1) break;
// same as (BHEAD+DATA dependency)
- dataPtrHead = dataPtr+ChunkUtils::getOffset(mFlags);
- if (dataChunk.dna_nr>=0)
+ dataPtrHead = dataPtr + ChunkUtils::getOffset(mFlags);
+ if (dataChunk.dna_nr >= 0)
{
- char *id = readStruct(dataPtrHead, dataChunk);
+ char* id = readStruct(dataPtrHead, dataChunk);
// lookup maps
if (id)
@@ -171,96 +156,91 @@ void b3BulletFile::parseData()
if (dataChunk.code == B3_SOFTBODY_CODE)
{
- m_softBodies.push_back((bStructHandle*) id);
+ m_softBodies.push_back((bStructHandle*)id);
}
-
+
if (dataChunk.code == B3_RIGIDBODY_CODE)
{
- m_rigidBodies.push_back((bStructHandle*) id);
+ m_rigidBodies.push_back((bStructHandle*)id);
}
if (dataChunk.code == B3_DYNAMICSWORLD_CODE)
{
- m_dynamicsWorldInfo.push_back((bStructHandle*) id);
+ m_dynamicsWorldInfo.push_back((bStructHandle*)id);
}
if (dataChunk.code == B3_CONSTRAINT_CODE)
{
- m_constraints.push_back((bStructHandle*) id);
+ m_constraints.push_back((bStructHandle*)id);
}
if (dataChunk.code == B3_QUANTIZED_BVH_CODE)
{
- m_bvhs.push_back((bStructHandle*) id);
+ m_bvhs.push_back((bStructHandle*)id);
}
if (dataChunk.code == B3_TRIANLGE_INFO_MAP)
{
- m_triangleInfoMaps.push_back((bStructHandle*) id);
+ m_triangleInfoMaps.push_back((bStructHandle*)id);
}
if (dataChunk.code == B3_COLLISIONOBJECT_CODE)
{
- m_collisionObjects.push_back((bStructHandle*) id);
+ m_collisionObjects.push_back((bStructHandle*)id);
}
if (dataChunk.code == B3_SHAPE_CODE)
{
- m_collisionShapes.push_back((bStructHandle*) id);
+ m_collisionShapes.push_back((bStructHandle*)id);
}
- // if (dataChunk.code == GLOB)
- // {
- // m_glob = (bStructHandle*) id;
- // }
- } else
+ // if (dataChunk.code == GLOB)
+ // {
+ // m_glob = (bStructHandle*) id;
+ // }
+ }
+ else
{
//printf("unknown chunk\n");
mLibPointers.insert(dataChunk.oldPtr, (bStructHandle*)dataPtrHead);
}
- } else
+ }
+ else
{
printf("skipping B3_QUANTIZED_BVH_CODE due to broken DNA\n");
}
-
dataPtr += seek;
- seek = getNextBlock(&dataChunk, dataPtr, mFlags);
- if (mFlags &FD_ENDIAN_SWAP)
+ seek = getNextBlock(&dataChunk, dataPtr, mFlags);
+ if (mFlags & FD_ENDIAN_SWAP)
swapLen(dataPtr);
if (seek < 0)
break;
}
-
}
-void b3BulletFile::addDataBlock(char* dataBlock)
+void b3BulletFile::addDataBlock(char* dataBlock)
{
m_dataBlocks.push_back(dataBlock);
-
}
-
-
-
-void b3BulletFile::writeDNA(FILE* fp)
+void b3BulletFile::writeDNA(FILE* fp)
{
-
bChunkInd dataChunk;
dataChunk.code = B3_DNA1;
dataChunk.dna_nr = 0;
dataChunk.nr = 1;
-#ifdef B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+#ifdef B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
if (VOID_IS_8)
{
#ifdef _WIN64
dataChunk.len = b3s_bulletDNAlen64;
dataChunk.oldPtr = b3s_bulletDNAstr64;
- fwrite(&dataChunk,sizeof(bChunkInd),1,fp);
- fwrite(b3s_bulletDNAstr64, b3s_bulletDNAlen64,1,fp);
+ fwrite(&dataChunk, sizeof(bChunkInd), 1, fp);
+ fwrite(b3s_bulletDNAstr64, b3s_bulletDNAlen64, 1, fp);
#else
b3Assert(0);
#endif
@@ -270,43 +250,42 @@ void b3BulletFile::writeDNA(FILE* fp)
#ifndef _WIN64
dataChunk.len = b3s_bulletDNAlen;
dataChunk.oldPtr = b3s_bulletDNAstr;
- fwrite(&dataChunk,sizeof(bChunkInd),1,fp);
- fwrite(b3s_bulletDNAstr, b3s_bulletDNAlen,1,fp);
-#else//_WIN64
+ fwrite(&dataChunk, sizeof(bChunkInd), 1, fp);
+ fwrite(b3s_bulletDNAstr, b3s_bulletDNAlen, 1, fp);
+#else //_WIN64
b3Assert(0);
-#endif//_WIN64
+#endif //_WIN64
}
-#else//B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+#else //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
if (VOID_IS_8)
{
dataChunk.len = b3s_bulletDNAlen64;
dataChunk.oldPtr = b3s_bulletDNAstr64;
- fwrite(&dataChunk,sizeof(bChunkInd),1,fp);
- fwrite(b3s_bulletDNAstr64, b3s_bulletDNAlen64,1,fp);
+ fwrite(&dataChunk, sizeof(bChunkInd), 1, fp);
+ fwrite(b3s_bulletDNAstr64, b3s_bulletDNAlen64, 1, fp);
}
else
{
dataChunk.len = b3s_bulletDNAlen;
dataChunk.oldPtr = b3s_bulletDNAstr;
- fwrite(&dataChunk,sizeof(bChunkInd),1,fp);
- fwrite(b3s_bulletDNAstr, b3s_bulletDNAlen,1,fp);
+ fwrite(&dataChunk, sizeof(bChunkInd), 1, fp);
+ fwrite(b3s_bulletDNAstr, b3s_bulletDNAlen, 1, fp);
}
-#endif//B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+#endif //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
}
-
-void b3BulletFile::parse(int verboseMode)
+void b3BulletFile::parse(int verboseMode)
{
#ifdef B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
if (VOID_IS_8)
{
#ifdef _WIN64
-
+
if (m_DnaCopy)
delete m_DnaCopy;
- m_DnaCopy = (char*)b3AlignedAlloc(b3s_bulletDNAlen64,16);
- memcpy(m_DnaCopy,b3s_bulletDNAstr64,b3s_bulletDNAlen64);
- parseInternal(verboseMode,(char*)b3s_bulletDNAstr64,b3s_bulletDNAlen64);
+ m_DnaCopy = (char*)b3AlignedAlloc(b3s_bulletDNAlen64, 16);
+ memcpy(m_DnaCopy, b3s_bulletDNAstr64, b3s_bulletDNAlen64);
+ parseInternal(verboseMode, (char*)b3s_bulletDNAstr64, b3s_bulletDNAlen64);
#else
b3Assert(0);
#endif
@@ -317,93 +296,91 @@ void b3BulletFile::parse(int verboseMode)
if (m_DnaCopy)
delete m_DnaCopy;
- m_DnaCopy = (char*)b3AlignedAlloc(b3s_bulletDNAlen,16);
- memcpy(m_DnaCopy,b3s_bulletDNAstr,b3s_bulletDNAlen);
- parseInternal(verboseMode,m_DnaCopy,b3s_bulletDNAlen);
+ m_DnaCopy = (char*)b3AlignedAlloc(b3s_bulletDNAlen, 16);
+ memcpy(m_DnaCopy, b3s_bulletDNAstr, b3s_bulletDNAlen);
+ parseInternal(verboseMode, m_DnaCopy, b3s_bulletDNAlen);
#else
b3Assert(0);
#endif
}
-#else//B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+#else //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
if (VOID_IS_8)
{
if (m_DnaCopy)
delete m_DnaCopy;
- m_DnaCopy = (char*)b3AlignedAlloc(b3s_bulletDNAlen64,16);
- memcpy(m_DnaCopy,b3s_bulletDNAstr64,b3s_bulletDNAlen64);
- parseInternal(verboseMode,m_DnaCopy,b3s_bulletDNAlen64);
+ m_DnaCopy = (char*)b3AlignedAlloc(b3s_bulletDNAlen64, 16);
+ memcpy(m_DnaCopy, b3s_bulletDNAstr64, b3s_bulletDNAlen64);
+ parseInternal(verboseMode, m_DnaCopy, b3s_bulletDNAlen64);
}
else
{
if (m_DnaCopy)
delete m_DnaCopy;
- m_DnaCopy = (char*)b3AlignedAlloc(b3s_bulletDNAlen,16);
- memcpy(m_DnaCopy,b3s_bulletDNAstr,b3s_bulletDNAlen);
- parseInternal(verboseMode,m_DnaCopy,b3s_bulletDNAlen);
+ m_DnaCopy = (char*)b3AlignedAlloc(b3s_bulletDNAlen, 16);
+ memcpy(m_DnaCopy, b3s_bulletDNAstr, b3s_bulletDNAlen);
+ parseInternal(verboseMode, m_DnaCopy, b3s_bulletDNAlen);
}
-#endif//B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
-
+#endif //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+
//the parsing will convert to cpu endian
- mFlags &=~FD_ENDIAN_SWAP;
+ mFlags &= ~FD_ENDIAN_SWAP;
- int littleEndian= 1;
- littleEndian= ((char*)&littleEndian)[0];
-
- mFileBuffer[8] = littleEndian?'v':'V';
-
+ int littleEndian = 1;
+ littleEndian = ((char*)&littleEndian)[0];
+
+ mFileBuffer[8] = littleEndian ? 'v' : 'V';
}
// experimental
-int b3BulletFile::write(const char* fileName, bool fixupPointers)
+int b3BulletFile::write(const char* fileName, bool fixupPointers)
{
- FILE *fp = fopen(fileName, "wb");
+ FILE* fp = fopen(fileName, "wb");
if (fp)
{
- char header[B3_SIZEOFBLENDERHEADER] ;
+ char header[B3_SIZEOFBLENDERHEADER];
memcpy(header, m_headerString, 7);
- int endian= 1;
- endian= ((char*)&endian)[0];
+ int endian = 1;
+ endian = ((char*)&endian)[0];
if (endian)
{
header[7] = '_';
- } else
+ }
+ else
{
header[7] = '-';
}
if (VOID_IS_8)
{
- header[8]='V';
- } else
+ header[8] = 'V';
+ }
+ else
{
- header[8]='v';
+ header[8] = 'v';
}
header[9] = '2';
header[10] = '7';
header[11] = '5';
-
- fwrite(header,B3_SIZEOFBLENDERHEADER,1,fp);
+
+ fwrite(header, B3_SIZEOFBLENDERHEADER, 1, fp);
writeChunks(fp, fixupPointers);
writeDNA(fp);
fclose(fp);
-
- } else
+ }
+ else
{
- printf("Error: cannot open file %s for writing\n",fileName);
+ printf("Error: cannot open file %s for writing\n", fileName);
return 0;
}
return 1;
}
-
-
-void b3BulletFile::addStruct(const char* structType,void* data, int len, void* oldPtr, int code)
+void b3BulletFile::addStruct(const char* structType, void* data, int len, void* oldPtr, int code)
{
-
bParse::bChunkInd dataChunk;
dataChunk.code = code;
dataChunk.nr = 1;
@@ -412,11 +389,11 @@ void b3BulletFile::addStruct(const char* structType,void* data, int len, void* o
dataChunk.oldPtr = oldPtr;
///Perform structure size validation
- short* structInfo= mMemoryDNA->getStruct(dataChunk.dna_nr);
+ short* structInfo = mMemoryDNA->getStruct(dataChunk.dna_nr);
int elemBytes;
- elemBytes= mMemoryDNA->getLength(structInfo[0]);
-// int elemBytes = mMemoryDNA->getElementSize(structInfo[0],structInfo[1]);
- assert(len==elemBytes);
+ elemBytes = mMemoryDNA->getLength(structInfo[0]);
+ // int elemBytes = mMemoryDNA->getElementSize(structInfo[0],structInfo[1]);
+ assert(len == elemBytes);
mLibPointers.insert(dataChunk.oldPtr, (bStructHandle*)data);
m_chunks.push_back(dataChunk);
diff --git a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3BulletFile.h b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3BulletFile.h
index fb1b9b0dde..ede1d378ae 100644
--- a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3BulletFile.h
+++ b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3BulletFile.h
@@ -16,68 +16,59 @@ subject to the following restrictions:
#ifndef B3_BULLET_FILE_H
#define B3_BULLET_FILE_H
-
#include "b3File.h"
#include "Bullet3Common/b3AlignedObjectArray.h"
#include "b3Defines.h"
#include "Bullet3Serialize/Bullet2FileLoader/b3Serializer.h"
+namespace bParse
+{
+// ----------------------------------------------------- //
+class b3BulletFile : public bFile
+{
+protected:
+ char* m_DnaCopy;
+public:
+ b3AlignedObjectArray<bStructHandle*> m_softBodies;
-namespace bParse {
-
- // ----------------------------------------------------- //
- class b3BulletFile : public bFile
- {
-
-
- protected:
-
- char* m_DnaCopy;
-
- public:
-
- b3AlignedObjectArray<bStructHandle*> m_softBodies;
-
- b3AlignedObjectArray<bStructHandle*> m_rigidBodies;
-
- b3AlignedObjectArray<bStructHandle*> m_collisionObjects;
+ b3AlignedObjectArray<bStructHandle*> m_rigidBodies;
- b3AlignedObjectArray<bStructHandle*> m_collisionShapes;
+ b3AlignedObjectArray<bStructHandle*> m_collisionObjects;
- b3AlignedObjectArray<bStructHandle*> m_constraints;
+ b3AlignedObjectArray<bStructHandle*> m_collisionShapes;
- b3AlignedObjectArray<bStructHandle*> m_bvhs;
+ b3AlignedObjectArray<bStructHandle*> m_constraints;
- b3AlignedObjectArray<bStructHandle*> m_triangleInfoMaps;
+ b3AlignedObjectArray<bStructHandle*> m_bvhs;
- b3AlignedObjectArray<bStructHandle*> m_dynamicsWorldInfo;
+ b3AlignedObjectArray<bStructHandle*> m_triangleInfoMaps;
- b3AlignedObjectArray<char*> m_dataBlocks;
- b3BulletFile();
+ b3AlignedObjectArray<bStructHandle*> m_dynamicsWorldInfo;
- b3BulletFile(const char* fileName);
+ b3AlignedObjectArray<char*> m_dataBlocks;
+ b3BulletFile();
- b3BulletFile(char *memoryBuffer, int len);
+ b3BulletFile(const char* fileName);
- virtual ~b3BulletFile();
+ b3BulletFile(char* memoryBuffer, int len);
- virtual void addDataBlock(char* dataBlock);
-
+ virtual ~b3BulletFile();
- // experimental
- virtual int write(const char* fileName, bool fixupPointers=false);
+ virtual void addDataBlock(char* dataBlock);
- virtual void parse(int verboseMode);
+ // experimental
+ virtual int write(const char* fileName, bool fixupPointers = false);
- virtual void parseData();
+ virtual void parse(int verboseMode);
- virtual void writeDNA(FILE* fp);
+ virtual void parseData();
- void addStruct(const char* structType,void* data, int len, void* oldPtr, int code);
+ virtual void writeDNA(FILE* fp);
- };
+ void addStruct(const char* structType, void* data, int len, void* oldPtr, int code);
};
+}; // namespace bParse
-#endif //B3_BULLET_FILE_H
+#endif //B3_BULLET_FILE_H
diff --git a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Chunk.cpp b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Chunk.cpp
index c0e1bb708c..ff75ff8cc4 100644
--- a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Chunk.cpp
+++ b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Chunk.cpp
@@ -17,15 +17,13 @@ subject to the following restrictions:
#include "b3Defines.h"
#include "b3File.h"
-#if !defined( __CELLOS_LV2__) && !defined(__MWERKS__)
+#if !defined(__CELLOS_LV2__) && !defined(__MWERKS__)
#include <memory.h>
#endif
#include <string.h>
-
using namespace bParse;
-
// ----------------------------------------------------- //
short ChunkUtils::swapShort(short sht)
{
@@ -57,19 +55,15 @@ int ChunkUtils::getOffset(int flags)
if (VOID_IS_8)
{
- if (flags &FD_BITS_VARIES)
+ if (flags & FD_BITS_VARIES)
res = sizeof(bChunkPtr4);
}
else
{
- if (flags &FD_BITS_VARIES)
+ if (flags & FD_BITS_VARIES)
res = sizeof(bChunkPtr8);
}
return res;
}
-
-
-
-
//eof
diff --git a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Chunk.h b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Chunk.h
index 03ecb6b4fa..c9d0f37d9e 100644
--- a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Chunk.h
+++ b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Chunk.h
@@ -16,77 +16,69 @@ subject to the following restrictions:
#ifndef __BCHUNK_H__
#define __BCHUNK_H__
-#if defined (_WIN32) && ! defined (__MINGW32__)
- #define b3Long64 __int64
-#elif defined (__MINGW32__)
- #include <stdint.h>
- #define b3Long64 int64_t
+#if defined(_WIN32) && !defined(__MINGW32__)
+#define b3Long64 __int64
+#elif defined(__MINGW32__)
+#include <stdint.h>
+#define b3Long64 int64_t
#else
- #define b3Long64 long long
+#define b3Long64 long long
#endif
-
-namespace bParse {
-
-
- // ----------------------------------------------------- //
- class bChunkPtr4
- {
- public:
- bChunkPtr4(){}
- int code;
- int len;
- union
- {
- int m_uniqueInt;
- };
- int dna_nr;
- int nr;
- };
-
- // ----------------------------------------------------- //
- class bChunkPtr8
- {
- public:
- bChunkPtr8(){}
- int code, len;
- union
- {
- b3Long64 oldPrev;
- int m_uniqueInts[2];
- };
- int dna_nr, nr;
- };
-
- // ----------------------------------------------------- //
- class bChunkInd
- {
- public:
- bChunkInd(){}
- int code, len;
- void *oldPtr;
- int dna_nr, nr;
+namespace bParse
+{
+// ----------------------------------------------------- //
+class bChunkPtr4
+{
+public:
+ bChunkPtr4() {}
+ int code;
+ int len;
+ union {
+ int m_uniqueInt;
};
-
-
- // ----------------------------------------------------- //
- class ChunkUtils
- {
- public:
-
- // file chunk offset
- static int getOffset(int flags);
-
- // endian utils
- static short swapShort(short sht);
- static int swapInt(int inte);
- static b3Long64 swapLong64(b3Long64 lng);
-
+ int dna_nr;
+ int nr;
+};
+
+// ----------------------------------------------------- //
+class bChunkPtr8
+{
+public:
+ bChunkPtr8() {}
+ int code, len;
+ union {
+ b3Long64 oldPrev;
+ int m_uniqueInts[2];
};
-
-
- const int CHUNK_HEADER_LEN = ((sizeof(bChunkInd)));
- const bool VOID_IS_8 = ((sizeof(void*)==8));
-}
-
-#endif//__BCHUNK_H__
+ int dna_nr, nr;
+};
+
+// ----------------------------------------------------- //
+class bChunkInd
+{
+public:
+ bChunkInd() {}
+ int code, len;
+ void *oldPtr;
+ int dna_nr, nr;
+};
+
+// ----------------------------------------------------- //
+class ChunkUtils
+{
+public:
+ // file chunk offset
+ static int getOffset(int flags);
+
+ // endian utils
+ static short swapShort(short sht);
+ static int swapInt(int inte);
+ static b3Long64 swapLong64(b3Long64 lng);
+};
+
+const int CHUNK_HEADER_LEN = ((sizeof(bChunkInd)));
+const bool VOID_IS_8 = ((sizeof(void *) == 8));
+} // namespace bParse
+
+#endif //__BCHUNK_H__
diff --git a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Common.h b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Common.h
index 2792d84033..5884fad4d6 100644
--- a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Common.h
+++ b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Common.h
@@ -16,24 +16,25 @@ subject to the following restrictions:
#ifndef __BCOMMON_H__
#define __BCOMMON_H__
-
#include <assert.h>
//#include "bLog.h"
#include "Bullet3Common/b3AlignedObjectArray.h"
#include "Bullet3Common/b3HashMap.h"
-namespace bParse {
-
- class bMain;
- class bFileData;
- class bFile;
- class bDNA;
-
- // delete void* undefined
- typedef struct bStructHandle {int unused;}bStructHandle;
- typedef b3AlignedObjectArray<bStructHandle*> bListBasePtr;
- typedef b3HashMap<b3HashPtr, bStructHandle*> bPtrMap;
-}
-
-
-#endif//__BCOMMON_H__
+namespace bParse
+{
+class bMain;
+class bFileData;
+class bFile;
+class bDNA;
+
+// delete void* undefined
+typedef struct bStructHandle
+{
+ int unused;
+} bStructHandle;
+typedef b3AlignedObjectArray<bStructHandle*> bListBasePtr;
+typedef b3HashMap<b3HashPtr, bStructHandle*> bPtrMap;
+} // namespace bParse
+
+#endif //__BCOMMON_H__
diff --git a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3DNA.cpp b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3DNA.cpp
index 0fe5056922..09c8f23859 100644
--- a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3DNA.cpp
+++ b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3DNA.cpp
@@ -23,13 +23,11 @@ subject to the following restrictions:
//this define will force traversal of structures, to check backward (and forward) compatibility
//#define TEST_BACKWARD_FORWARD_COMPATIBILITY
-
using namespace bParse;
-
// ----------------------------------------------------- //
bDNA::bDNA()
- : mPtrLen(0)
+ : mPtrLen(0)
{
// --
}
@@ -43,7 +41,7 @@ bDNA::~bDNA()
// ----------------------------------------------------- //
bool bDNA::lessThan(bDNA *file)
{
- return ( m_Names.size() < file->m_Names.size());
+ return (m_Names.size() < file->m_Names.size());
}
// ----------------------------------------------------- //
@@ -53,36 +51,31 @@ char *bDNA::getName(int ind)
return m_Names[ind].m_name;
}
-
// ----------------------------------------------------- //
char *bDNA::getType(int ind)
{
- assert(ind<= (int)mTypes.size());
+ assert(ind <= (int)mTypes.size());
return mTypes[ind];
}
-
// ----------------------------------------------------- //
short *bDNA::getStruct(int ind)
{
- assert(ind <= (int)mStructs.size());
+ assert(ind <= (int)mStructs.size());
return mStructs[ind];
}
-
// ----------------------------------------------------- //
short bDNA::getLength(int ind)
{
- assert(ind <= (int)mTlens.size());
+ assert(ind <= (int)mTlens.size());
return mTlens[ind];
}
-
// ----------------------------------------------------- //
int bDNA::getReverseType(short type)
{
-
- int* intPtr = mStructReverse.find(type);
+ int *intPtr = mStructReverse.find(type);
if (intPtr)
return *intPtr;
@@ -92,12 +85,11 @@ int bDNA::getReverseType(short type)
// ----------------------------------------------------- //
int bDNA::getReverseType(const char *type)
{
-
b3HashString key(type);
- int* valuePtr = mTypeLookup.find(key);
+ int *valuePtr = mTypeLookup.find(key);
if (valuePtr)
return *valuePtr;
-
+
return -1;
}
@@ -110,22 +102,22 @@ int bDNA::getNumStructs()
// ----------------------------------------------------- //
bool bDNA::flagNotEqual(int dna_nr)
{
- assert(dna_nr <= (int)mCMPFlags.size());
+ assert(dna_nr <= (int)mCMPFlags.size());
return mCMPFlags[dna_nr] == FDF_STRUCT_NEQU;
}
// ----------------------------------------------------- //
bool bDNA::flagEqual(int dna_nr)
{
- assert(dna_nr <= (int)mCMPFlags.size());
+ assert(dna_nr <= (int)mCMPFlags.size());
int flag = mCMPFlags[dna_nr];
- return flag == FDF_STRUCT_EQU;
+ return flag == FDF_STRUCT_EQU;
}
// ----------------------------------------------------- //
bool bDNA::flagNone(int dna_nr)
{
- assert(dna_nr <= (int)mCMPFlags.size());
+ assert(dna_nr <= (int)mCMPFlags.size());
return mCMPFlags[dna_nr] == FDF_NONE;
}
@@ -143,15 +135,15 @@ void bDNA::initRecurseCmpFlags(int iter)
short *oldStrc = mStructs[iter];
short type = oldStrc[0];
- for (int i=0; i<(int)mStructs.size(); i++)
+ for (int i = 0; i < (int)mStructs.size(); i++)
{
- if (i != iter && mCMPFlags[i] == FDF_STRUCT_EQU )
+ if (i != iter && mCMPFlags[i] == FDF_STRUCT_EQU)
{
short *curStruct = mStructs[i];
int eleLen = curStruct[1];
- curStruct+=2;
+ curStruct += 2;
- for (int j=0; j<eleLen; j++, curStruct+=2)
+ for (int j = 0; j < eleLen; j++, curStruct += 2)
{
if (curStruct[0] == type)
{
@@ -171,18 +163,14 @@ void bDNA::initRecurseCmpFlags(int iter)
// ----------------------------------------------------- //
void bDNA::initCmpFlags(bDNA *memDNA)
{
-
- // compare the file to memory
+ // compare the file to memory
// this ptr should be the file data
-
- assert(!(m_Names.size() == 0));// && "SDNA empty!");
+ assert(!(m_Names.size() == 0)); // && "SDNA empty!");
mCMPFlags.resize(mStructs.size(), FDF_NONE);
-
-
int i;
- for ( i=0; i<(int)mStructs.size(); i++)
+ for (i = 0; i < (int)mStructs.size(); i++)
{
short *oldStruct = mStructs[i];
@@ -196,7 +184,7 @@ void bDNA::initCmpFlags(bDNA *memDNA)
//#define SLOW_FORWARD_COMPATIBLE 1
#ifdef SLOW_FORWARD_COMPATIBLE
- char* typeName = mTypes[oldLookup];
+ char *typeName = mTypes[oldLookup];
int newLookup = memDNA->getReverseType(typeName);
if (newLookup == -1)
{
@@ -210,71 +198,61 @@ void bDNA::initCmpFlags(bDNA *memDNA)
if (oldLookup < memDNA->mStructs.size())
{
short *curStruct = memDNA->mStructs[oldLookup];
-#endif
-
-
+#endif
- // rebuild...
- mCMPFlags[i] = FDF_STRUCT_NEQU;
+ // rebuild...
+ mCMPFlags[i] = FDF_STRUCT_NEQU;
#ifndef TEST_BACKWARD_FORWARD_COMPATIBILITY
- if (curStruct[1] == oldStruct[1])
+ if (curStruct[1] == oldStruct[1])
+ {
+ // type len same ...
+ if (mTlens[oldStruct[0]] == memDNA->mTlens[curStruct[0]])
{
- // type len same ...
- if (mTlens[oldStruct[0]] == memDNA->mTlens[curStruct[0]])
- {
- bool isSame = true;
- int elementLength = oldStruct[1];
-
+ bool isSame = true;
+ int elementLength = oldStruct[1];
- curStruct+=2;
- oldStruct+=2;
+ curStruct += 2;
+ oldStruct += 2;
+ for (int j = 0; j < elementLength; j++, curStruct += 2, oldStruct += 2)
+ {
+ // type the same
+ //const char* typeFileDNA = mTypes[oldStruct[0]];
+ //const char* typeMemDNA = mTypes[curStruct[0]];
+ if (strcmp(mTypes[oldStruct[0]], memDNA->mTypes[curStruct[0]]) != 0)
+ {
+ isSame = false;
+ break;
+ }
- for (int j=0; j<elementLength; j++, curStruct+=2, oldStruct+=2)
+ // name the same
+ if (strcmp(m_Names[oldStruct[1]].m_name, memDNA->m_Names[curStruct[1]].m_name) != 0)
{
- // type the same
- //const char* typeFileDNA = mTypes[oldStruct[0]];
- //const char* typeMemDNA = mTypes[curStruct[0]];
- if (strcmp(mTypes[oldStruct[0]], memDNA->mTypes[curStruct[0]])!=0)
- {
- isSame=false;
- break;
- }
-
- // name the same
- if (strcmp(m_Names[oldStruct[1]].m_name, memDNA->m_Names[curStruct[1]].m_name)!=0)
- {
- isSame=false;
- break;
- }
+ isSame = false;
+ break;
}
- // flag valid ==
- if (isSame)
- mCMPFlags[i] = FDF_STRUCT_EQU;
}
+ // flag valid ==
+ if (isSame)
+ mCMPFlags[i] = FDF_STRUCT_EQU;
}
-#endif
}
- }
-
-
-
-
-
- // recurse in
- for ( i=0; i<(int)mStructs.size(); i++)
- {
- if (mCMPFlags[i] == FDF_STRUCT_NEQU)
- initRecurseCmpFlags(i);
+#endif
}
}
+// recurse in
+for (i = 0; i < (int)mStructs.size(); i++)
+{
+ if (mCMPFlags[i] == FDF_STRUCT_NEQU)
+ initRecurseCmpFlags(i);
+}
+}
-
-
-static int name_is_array(char* name, int* dim1, int* dim2) {
+static int name_is_array(char *name, int *dim1, int *dim2)
+{
int len = strlen(name);
/*fprintf(stderr,"[%s]",name);*/
/*if (len >= 1) {
@@ -284,58 +262,77 @@ static int name_is_array(char* name, int* dim1, int* dim2) {
return 0;*/
char *bp;
int num;
- if (dim1) {
+ if (dim1)
+ {
*dim1 = 1;
}
- if (dim2) {
+ if (dim2)
+ {
*dim2 = 1;
}
bp = strchr(name, '[');
- if (!bp) {
+ if (!bp)
+ {
return 0;
}
num = 0;
- while (++bp < name+len-1) {
+ while (++bp < name + len - 1)
+ {
const char c = *bp;
- if (c == ']') {
+ if (c == ']')
+ {
break;
}
- if (c <= '9' && c >= '0') {
+ if (c <= '9' && c >= '0')
+ {
num *= 10;
num += (c - '0');
- } else {
+ }
+ else
+ {
printf("array parse error.\n");
return 0;
}
}
- if (dim2) {
+ if (dim2)
+ {
*dim2 = num;
}
/* find second dim, if any. */
bp = strchr(bp, '[');
- if (!bp) {
+ if (!bp)
+ {
return 1; /* at least we got the first dim. */
}
num = 0;
- while (++bp < name+len-1) {
+ while (++bp < name + len - 1)
+ {
const char c = *bp;
- if (c == ']') {
+ if (c == ']')
+ {
break;
}
- if (c <= '9' && c >= '0') {
+ if (c <= '9' && c >= '0')
+ {
num *= 10;
num += (c - '0');
- } else {
+ }
+ else
+ {
printf("array2 parse error.\n");
return 1;
}
}
- if (dim1) {
- if (dim2) {
+ if (dim1)
+ {
+ if (dim2)
+ {
*dim1 = *dim2;
*dim2 = num;
- } else {
+ }
+ else
+ {
*dim1 = num;
}
}
@@ -343,14 +340,15 @@ static int name_is_array(char* name, int* dim1, int* dim2) {
return 1;
}
-
// ----------------------------------------------------- //
void bDNA::init(char *data, int len, bool swap)
{
- int *intPtr=0;short *shtPtr=0;
- char *cp = 0;int dataLen =0;
+ int *intPtr = 0;
+ short *shtPtr = 0;
+ char *cp = 0;
+ int dataLen = 0;
//long nr=0;
- intPtr = (int*)data;
+ intPtr = (int *)data;
/*
SDNA (4 bytes) (magic number)
@@ -360,38 +358,35 @@ void bDNA::init(char *data, int len, bool swap)
<string>
*/
- if (strncmp(data, "SDNA", 4)==0)
+ if (strncmp(data, "SDNA", 4) == 0)
{
// skip ++ NAME
- intPtr++; intPtr++;
+ intPtr++;
+ intPtr++;
}
-
-
// Parse names
- if (swap)
+ if (swap)
{
*intPtr = ChunkUtils::swapInt(*intPtr);
}
dataLen = *intPtr;
intPtr++;
- cp = (char*)intPtr;
+ cp = (char *)intPtr;
int i;
- for ( i=0; i<dataLen; i++)
+ for (i = 0; i < dataLen; i++)
{
bNameInfo info;
info.m_name = cp;
info.m_isPointer = (info.m_name[0] == '*') || (info.m_name[1] == '*');
- name_is_array(info.m_name,&info.m_dim0,&info.m_dim1);
+ name_is_array(info.m_name, &info.m_dim0, &info.m_dim1);
m_Names.push_back(info);
- while (*cp)cp++;
+ while (*cp) cp++;
cp++;
}
-
- cp = b3AlignPointer(cp,4);
-
+ cp = b3AlignPointer(cp, 4);
/*
TYPE (4 bytes)
@@ -400,26 +395,26 @@ void bDNA::init(char *data, int len, bool swap)
<string>
*/
- intPtr = (int*)cp;
- assert(strncmp(cp, "TYPE", 4)==0); intPtr++;
+ intPtr = (int *)cp;
+ assert(strncmp(cp, "TYPE", 4) == 0);
+ intPtr++;
- if (swap)
+ if (swap)
{
*intPtr = ChunkUtils::swapInt(*intPtr);
}
dataLen = *intPtr;
intPtr++;
- cp = (char*)intPtr;
- for ( i=0; i<dataLen; i++)
+ cp = (char *)intPtr;
+ for (i = 0; i < dataLen; i++)
{
mTypes.push_back(cp);
- while (*cp)cp++;
+ while (*cp) cp++;
cp++;
}
-
- cp = b3AlignPointer(cp,4);
+ cp = b3AlignPointer(cp, 4);
/*
TLEN (4 bytes)
@@ -428,13 +423,14 @@ void bDNA::init(char *data, int len, bool swap)
*/
// Parse type lens
- intPtr = (int*)cp;
- assert(strncmp(cp, "TLEN", 4)==0); intPtr++;
+ intPtr = (int *)cp;
+ assert(strncmp(cp, "TLEN", 4) == 0);
+ intPtr++;
dataLen = (int)mTypes.size();
- shtPtr = (short*)intPtr;
- for ( i=0; i<dataLen; i++, shtPtr++)
+ shtPtr = (short *)intPtr;
+ for (i = 0; i < dataLen; i++, shtPtr++)
{
if (swap)
shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
@@ -454,94 +450,89 @@ void bDNA::init(char *data, int len, bool swap)
<namenr>
*/
- intPtr = (int*)shtPtr;
- cp = (char*)intPtr;
- assert(strncmp(cp, "STRC", 4)==0); intPtr++;
+ intPtr = (int *)shtPtr;
+ cp = (char *)intPtr;
+ assert(strncmp(cp, "STRC", 4) == 0);
+ intPtr++;
- if (swap)
+ if (swap)
{
*intPtr = ChunkUtils::swapInt(*intPtr);
}
dataLen = *intPtr;
intPtr++;
-
- shtPtr = (short*)intPtr;
- for ( i=0; i<dataLen; i++)
+ shtPtr = (short *)intPtr;
+ for (i = 0; i < dataLen; i++)
{
- mStructs.push_back (shtPtr);
+ mStructs.push_back(shtPtr);
if (swap)
{
- shtPtr[0]= ChunkUtils::swapShort(shtPtr[0]);
- shtPtr[1]= ChunkUtils::swapShort(shtPtr[1]);
+ shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
+ shtPtr[1] = ChunkUtils::swapShort(shtPtr[1]);
int len = shtPtr[1];
- shtPtr+= 2;
+ shtPtr += 2;
- for (int a=0; a<len; a++, shtPtr+=2)
+ for (int a = 0; a < len; a++, shtPtr += 2)
{
- shtPtr[0]= ChunkUtils::swapShort(shtPtr[0]);
- shtPtr[1]= ChunkUtils::swapShort(shtPtr[1]);
+ shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
+ shtPtr[1] = ChunkUtils::swapShort(shtPtr[1]);
}
}
else
- shtPtr+= (2*shtPtr[1])+2;
+ shtPtr += (2 * shtPtr[1]) + 2;
}
-
// build reverse lookups
- for ( i=0; i<(int)mStructs.size(); i++)
+ for (i = 0; i < (int)mStructs.size(); i++)
{
short *strc = mStructs.at(i);
- if (!mPtrLen && strcmp(mTypes[strc[0]],"ListBase")==0)
+ if (!mPtrLen && strcmp(mTypes[strc[0]], "ListBase") == 0)
{
- mPtrLen = mTlens[strc[0]]/2;
+ mPtrLen = mTlens[strc[0]] / 2;
}
mStructReverse.insert(strc[0], i);
- mTypeLookup.insert(b3HashString(mTypes[strc[0]]),i);
+ mTypeLookup.insert(b3HashString(mTypes[strc[0]]), i);
}
}
-
// ----------------------------------------------------- //
-int bDNA::getArraySize(char* string)
+int bDNA::getArraySize(char *string)
{
int ret = 1;
int len = strlen(string);
-
- char* next = 0;
- for (int i=0; i<len; i++)
+ char *next = 0;
+ for (int i = 0; i < len; i++)
{
char c = string[i];
if (c == '[')
- next = &string[i+1];
- else if (c==']')
+ next = &string[i + 1];
+ else if (c == ']')
if (next)
ret *= atoi(next);
}
-// print (string << ' ' << ret);
+ // print (string << ' ' << ret);
return ret;
}
-
void bDNA::dumpTypeDefinitions()
{
int i;
int numTypes = mTypes.size();
-
- for (i=0;i<numTypes;i++)
- {
+ for (i = 0; i < numTypes; i++)
+ {
}
- for ( i=0; i<(int)mStructs.size(); i++)
+ for (i = 0; i < (int)mStructs.size(); i++)
{
- int totalBytes=0;
+ int totalBytes = 0;
short *oldStruct = mStructs[i];
int oldLookup = getReverseType(oldStruct[0]);
@@ -551,44 +542,46 @@ void bDNA::dumpTypeDefinitions()
continue;
}
- short* newStruct = mStructs[oldLookup];
- char* typeName = mTypes[newStruct[0]];
- printf("%3d: %s ",i,typeName);
-
+ short *newStruct = mStructs[oldLookup];
+ char *typeName = mTypes[newStruct[0]];
+ printf("%3d: %s ", i, typeName);
+
//char *name = mNames[oldStruct[1]];
int len = oldStruct[1];
- printf(" (%d fields) ",len);
- oldStruct+=2;
+ printf(" (%d fields) ", len);
+ oldStruct += 2;
printf("{");
int j;
- for (j=0; j<len; ++j,oldStruct+=2) {
- const char* name = m_Names[oldStruct[1]].m_name;
- printf("%s %s", mTypes[oldStruct[0]],name);
- int elemNumBytes= 0;
+ for (j = 0; j < len; ++j, oldStruct += 2)
+ {
+ const char *name = m_Names[oldStruct[1]].m_name;
+ printf("%s %s", mTypes[oldStruct[0]], name);
+ int elemNumBytes = 0;
int arrayDimensions = getArraySizeNew(oldStruct[1]);
if (m_Names[oldStruct[1]].m_isPointer)
{
elemNumBytes = VOID_IS_8 ? 8 : 4;
- } else
+ }
+ else
{
elemNumBytes = getLength(oldStruct[0]);
}
- printf(" /* %d bytes */",elemNumBytes*arrayDimensions);
-
- if (j == len-1) {
+ printf(" /* %d bytes */", elemNumBytes * arrayDimensions);
+
+ if (j == len - 1)
+ {
printf(";}");
- } else {
+ }
+ else
+ {
printf("; ");
}
- totalBytes+=elemNumBytes*arrayDimensions;
+ totalBytes += elemNumBytes * arrayDimensions;
}
- printf("\ntotalBytes=%d\n\n",totalBytes);
-
+ printf("\ntotalBytes=%d\n\n", totalBytes);
}
-
-
#if 0
/* dump out display of types and their sizes */
@@ -618,12 +611,6 @@ void bDNA::dumpTypeDefinitions()
}
}
#endif
-
}
-
-
-
//eof
-
-
diff --git a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3DNA.h b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3DNA.h
index 6e60087cce..ca6004d960 100644
--- a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3DNA.h
+++ b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3DNA.h
@@ -16,95 +16,86 @@ subject to the following restrictions:
#ifndef __BDNA_H__
#define __BDNA_H__
-
#include "b3Common.h"
-namespace bParse {
-
- struct bNameInfo
+namespace bParse
+{
+struct bNameInfo
+{
+ char *m_name;
+ bool m_isPointer;
+ int m_dim0;
+ int m_dim1;
+};
+
+class bDNA
+{
+public:
+ bDNA();
+ ~bDNA();
+
+ void init(char *data, int len, bool swap = false);
+
+ int getArraySize(char *str);
+ int getArraySizeNew(short name)
{
- char* m_name;
- bool m_isPointer;
- int m_dim0;
- int m_dim1;
- };
-
- class bDNA
+ const bNameInfo &nameInfo = m_Names[name];
+ return nameInfo.m_dim0 * nameInfo.m_dim1;
+ }
+ int getElementSize(short type, short name)
{
- public:
- bDNA();
- ~bDNA();
-
- void init(char *data, int len, bool swap=false);
-
- int getArraySize(char* str);
- int getArraySizeNew(short name)
- {
- const bNameInfo& nameInfo = m_Names[name];
- return nameInfo.m_dim0*nameInfo.m_dim1;
- }
- int getElementSize(short type, short name)
- {
- const bNameInfo& nameInfo = m_Names[name];
- int size = nameInfo.m_isPointer ? mPtrLen*nameInfo.m_dim0*nameInfo.m_dim1 : mTlens[type]*nameInfo.m_dim0*nameInfo.m_dim1;
- return size;
- }
-
- int getNumNames() const
- {
- return m_Names.size();
- }
-
- char *getName(int ind);
- char *getType(int ind);
- short *getStruct(int ind);
- short getLength(int ind);
- int getReverseType(short type);
- int getReverseType(const char *type);
-
-
- int getNumStructs();
-
- //
- bool lessThan(bDNA* other);
-
- void initCmpFlags(bDNA *memDNA);
- bool flagNotEqual(int dna_nr);
- bool flagEqual(int dna_nr);
- bool flagNone(int dna_nr);
+ const bNameInfo &nameInfo = m_Names[name];
+ int size = nameInfo.m_isPointer ? mPtrLen * nameInfo.m_dim0 * nameInfo.m_dim1 : mTlens[type] * nameInfo.m_dim0 * nameInfo.m_dim1;
+ return size;
+ }
+ int getNumNames() const
+ {
+ return m_Names.size();
+ }
- int getPointerSize();
+ char *getName(int ind);
+ char *getType(int ind);
+ short *getStruct(int ind);
+ short getLength(int ind);
+ int getReverseType(short type);
+ int getReverseType(const char *type);
- void dumpTypeDefinitions();
+ int getNumStructs();
-
- private:
- enum FileDNAFlags
- {
- FDF_NONE=0,
- FDF_STRUCT_NEQU,
- FDF_STRUCT_EQU
- };
+ //
+ bool lessThan(bDNA *other);
- void initRecurseCmpFlags(int i);
+ void initCmpFlags(bDNA *memDNA);
+ bool flagNotEqual(int dna_nr);
+ bool flagEqual(int dna_nr);
+ bool flagNone(int dna_nr);
- b3AlignedObjectArray<int> mCMPFlags;
+ int getPointerSize();
- b3AlignedObjectArray<bNameInfo> m_Names;
- b3AlignedObjectArray<char*> mTypes;
- b3AlignedObjectArray<short*> mStructs;
- b3AlignedObjectArray<short> mTlens;
- b3HashMap<b3HashInt, int> mStructReverse;
- b3HashMap<b3HashString,int> mTypeLookup;
+ void dumpTypeDefinitions();
- int mPtrLen;
-
+private:
+ enum FileDNAFlags
+ {
+ FDF_NONE = 0,
+ FDF_STRUCT_NEQU,
+ FDF_STRUCT_EQU
+ };
+ void initRecurseCmpFlags(int i);
+ b3AlignedObjectArray<int> mCMPFlags;
- };
-}
+ b3AlignedObjectArray<bNameInfo> m_Names;
+ b3AlignedObjectArray<char *> mTypes;
+ b3AlignedObjectArray<short *> mStructs;
+ b3AlignedObjectArray<short> mTlens;
+ b3HashMap<b3HashInt, int> mStructReverse;
+ b3HashMap<b3HashString, int> mTypeLookup;
+ int mPtrLen;
+};
+} // namespace bParse
-#endif//__BDNA_H__
+#endif //__BDNA_H__
diff --git a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Defines.h b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Defines.h
index 8f28d3c441..0524c94db1 100644
--- a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Defines.h
+++ b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Defines.h
@@ -19,118 +19,131 @@
#ifndef __B_DEFINES_H__
#define __B_DEFINES_H__
-
// MISC defines, see BKE_global.h, BKE_utildefines.h
#define B3_SIZEOFBLENDERHEADER 12
-
// ------------------------------------------------------------
-#if defined(__sgi) || defined (__sparc) || defined (__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__)
-# define B3_MAKE_ID(a,b,c,d) ( (int)(a)<<24 | (int)(b)<<16 | (c)<<8 | (d) )
+#if defined(__sgi) || defined(__sparc) || defined(__sparc__) || defined(__PPC__) || defined(__ppc__) || defined(__BIG_ENDIAN__)
+#define B3_MAKE_ID(a, b, c, d) ((int)(a) << 24 | (int)(b) << 16 | (c) << 8 | (d))
#else
-# define B3_MAKE_ID(a,b,c,d) ( (int)(d)<<24 | (int)(c)<<16 | (b)<<8 | (a) )
+#define B3_MAKE_ID(a, b, c, d) ((int)(d) << 24 | (int)(c) << 16 | (b) << 8 | (a))
#endif
-
// ------------------------------------------------------------
-#if defined(__sgi) || defined(__sparc) || defined(__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__)
-# define B3_MAKE_ID2(c, d) ( (c)<<8 | (d) )
+#if defined(__sgi) || defined(__sparc) || defined(__sparc__) || defined(__PPC__) || defined(__ppc__) || defined(__BIG_ENDIAN__)
+#define B3_MAKE_ID2(c, d) ((c) << 8 | (d))
#else
-# define B3_MAKE_ID2(c, d) ( (d)<<8 | (c) )
+#define B3_MAKE_ID2(c, d) ((d) << 8 | (c))
#endif
// ------------------------------------------------------------
-#define B3_ID_SCE B3_MAKE_ID2('S', 'C')
-#define B3_ID_LI B3_MAKE_ID2('L', 'I')
-#define B3_ID_OB B3_MAKE_ID2('O', 'B')
-#define B3_ID_ME B3_MAKE_ID2('M', 'E')
-#define B3_ID_CU B3_MAKE_ID2('C', 'U')
-#define B3_ID_MB B3_MAKE_ID2('M', 'B')
-#define B3_ID_MA B3_MAKE_ID2('M', 'A')
-#define B3_ID_TE B3_MAKE_ID2('T', 'E')
-#define B3_ID_IM B3_MAKE_ID2('I', 'M')
-#define B3_ID_IK B3_MAKE_ID2('I', 'K')
-#define B3_ID_WV B3_MAKE_ID2('W', 'V')
-#define B3_ID_LT B3_MAKE_ID2('L', 'T')
-#define B3_ID_SE B3_MAKE_ID2('S', 'E')
-#define B3_ID_LF B3_MAKE_ID2('L', 'F')
-#define B3_ID_LA B3_MAKE_ID2('L', 'A')
-#define B3_ID_CA B3_MAKE_ID2('C', 'A')
-#define B3_ID_IP B3_MAKE_ID2('I', 'P')
-#define B3_ID_KE B3_MAKE_ID2('K', 'E')
-#define B3_ID_WO B3_MAKE_ID2('W', 'O')
-#define B3_ID_SCR B3_MAKE_ID2('S', 'R')
-#define B3_ID_VF B3_MAKE_ID2('V', 'F')
-#define B3_ID_TXT B3_MAKE_ID2('T', 'X')
-#define B3_ID_SO B3_MAKE_ID2('S', 'O')
-#define B3_ID_SAMPLE B3_MAKE_ID2('S', 'A')
-#define B3_ID_GR B3_MAKE_ID2('G', 'R')
-#define B3_ID_ID B3_MAKE_ID2('I', 'D')
-#define B3_ID_AR B3_MAKE_ID2('A', 'R')
-#define B3_ID_AC B3_MAKE_ID2('A', 'C')
-#define B3_ID_SCRIPT B3_MAKE_ID2('P', 'Y')
-#define B3_ID_FLUIDSIM B3_MAKE_ID2('F', 'S')
-#define B3_ID_NT B3_MAKE_ID2('N', 'T')
-#define B3_ID_BR B3_MAKE_ID2('B', 'R')
-
-
-#define B3_ID_SEQ B3_MAKE_ID2('S', 'Q')
-#define B3_ID_CO B3_MAKE_ID2('C', 'O')
-#define B3_ID_PO B3_MAKE_ID2('A', 'C')
-#define B3_ID_NLA B3_MAKE_ID2('N', 'L')
-
-#define B3_ID_VS B3_MAKE_ID2('V', 'S')
-#define B3_ID_VN B3_MAKE_ID2('V', 'N')
-
+#define B3_ID_SCE B3_MAKE_ID2('S', 'C')
+#define B3_ID_LI B3_MAKE_ID2('L', 'I')
+#define B3_ID_OB B3_MAKE_ID2('O', 'B')
+#define B3_ID_ME B3_MAKE_ID2('M', 'E')
+#define B3_ID_CU B3_MAKE_ID2('C', 'U')
+#define B3_ID_MB B3_MAKE_ID2('M', 'B')
+#define B3_ID_MA B3_MAKE_ID2('M', 'A')
+#define B3_ID_TE B3_MAKE_ID2('T', 'E')
+#define B3_ID_IM B3_MAKE_ID2('I', 'M')
+#define B3_ID_IK B3_MAKE_ID2('I', 'K')
+#define B3_ID_WV B3_MAKE_ID2('W', 'V')
+#define B3_ID_LT B3_MAKE_ID2('L', 'T')
+#define B3_ID_SE B3_MAKE_ID2('S', 'E')
+#define B3_ID_LF B3_MAKE_ID2('L', 'F')
+#define B3_ID_LA B3_MAKE_ID2('L', 'A')
+#define B3_ID_CA B3_MAKE_ID2('C', 'A')
+#define B3_ID_IP B3_MAKE_ID2('I', 'P')
+#define B3_ID_KE B3_MAKE_ID2('K', 'E')
+#define B3_ID_WO B3_MAKE_ID2('W', 'O')
+#define B3_ID_SCR B3_MAKE_ID2('S', 'R')
+#define B3_ID_VF B3_MAKE_ID2('V', 'F')
+#define B3_ID_TXT B3_MAKE_ID2('T', 'X')
+#define B3_ID_SO B3_MAKE_ID2('S', 'O')
+#define B3_ID_SAMPLE B3_MAKE_ID2('S', 'A')
+#define B3_ID_GR B3_MAKE_ID2('G', 'R')
+#define B3_ID_ID B3_MAKE_ID2('I', 'D')
+#define B3_ID_AR B3_MAKE_ID2('A', 'R')
+#define B3_ID_AC B3_MAKE_ID2('A', 'C')
+#define B3_ID_SCRIPT B3_MAKE_ID2('P', 'Y')
+#define B3_ID_FLUIDSIM B3_MAKE_ID2('F', 'S')
+#define B3_ID_NT B3_MAKE_ID2('N', 'T')
+#define B3_ID_BR B3_MAKE_ID2('B', 'R')
+
+#define B3_ID_SEQ B3_MAKE_ID2('S', 'Q')
+#define B3_ID_CO B3_MAKE_ID2('C', 'O')
+#define B3_ID_PO B3_MAKE_ID2('A', 'C')
+#define B3_ID_NLA B3_MAKE_ID2('N', 'L')
+
+#define B3_ID_VS B3_MAKE_ID2('V', 'S')
+#define B3_ID_VN B3_MAKE_ID2('V', 'N')
// ------------------------------------------------------------
-#define B3_FORM B3_MAKE_ID('F','O','R','M')
-#define B3_DDG1 B3_MAKE_ID('3','D','G','1')
-#define B3_DDG2 B3_MAKE_ID('3','D','G','2')
-#define B3_DDG3 B3_MAKE_ID('3','D','G','3')
-#define B3_DDG4 B3_MAKE_ID('3','D','G','4')
-#define B3_GOUR B3_MAKE_ID('G','O','U','R')
-#define B3_BLEN B3_MAKE_ID('B','L','E','N')
-#define B3_DER_ B3_MAKE_ID('D','E','R','_')
-#define B3_V100 B3_MAKE_ID('V','1','0','0')
-#define B3_DATA B3_MAKE_ID('D','A','T','A')
-#define B3_GLOB B3_MAKE_ID('G','L','O','B')
-#define B3_IMAG B3_MAKE_ID('I','M','A','G')
-#define B3_TEST B3_MAKE_ID('T','E','S','T')
-#define B3_USER B3_MAKE_ID('U','S','E','R')
-
+#define B3_FORM B3_MAKE_ID('F', 'O', 'R', 'M')
+#define B3_DDG1 B3_MAKE_ID('3', 'D', 'G', '1')
+#define B3_DDG2 B3_MAKE_ID('3', 'D', 'G', '2')
+#define B3_DDG3 B3_MAKE_ID('3', 'D', 'G', '3')
+#define B3_DDG4 B3_MAKE_ID('3', 'D', 'G', '4')
+#define B3_GOUR B3_MAKE_ID('G', 'O', 'U', 'R')
+#define B3_BLEN B3_MAKE_ID('B', 'L', 'E', 'N')
+#define B3_DER_ B3_MAKE_ID('D', 'E', 'R', '_')
+#define B3_V100 B3_MAKE_ID('V', '1', '0', '0')
+#define B3_DATA B3_MAKE_ID('D', 'A', 'T', 'A')
+#define B3_GLOB B3_MAKE_ID('G', 'L', 'O', 'B')
+#define B3_IMAG B3_MAKE_ID('I', 'M', 'A', 'G')
+#define B3_TEST B3_MAKE_ID('T', 'E', 'S', 'T')
+#define B3_USER B3_MAKE_ID('U', 'S', 'E', 'R')
// ------------------------------------------------------------
-#define B3_DNA1 B3_MAKE_ID('D','N','A','1')
-#define B3_REND B3_MAKE_ID('R','E','N','D')
-#define B3_ENDB B3_MAKE_ID('E','N','D','B')
-#define B3_NAME B3_MAKE_ID('N','A','M','E')
-#define B3_SDNA B3_MAKE_ID('S','D','N','A')
-#define B3_TYPE B3_MAKE_ID('T','Y','P','E')
-#define B3_TLEN B3_MAKE_ID('T','L','E','N')
-#define B3_STRC B3_MAKE_ID('S','T','R','C')
-
+#define B3_DNA1 B3_MAKE_ID('D', 'N', 'A', '1')
+#define B3_REND B3_MAKE_ID('R', 'E', 'N', 'D')
+#define B3_ENDB B3_MAKE_ID('E', 'N', 'D', 'B')
+#define B3_NAME B3_MAKE_ID('N', 'A', 'M', 'E')
+#define B3_SDNA B3_MAKE_ID('S', 'D', 'N', 'A')
+#define B3_TYPE B3_MAKE_ID('T', 'Y', 'P', 'E')
+#define B3_TLEN B3_MAKE_ID('T', 'L', 'E', 'N')
+#define B3_STRC B3_MAKE_ID('S', 'T', 'R', 'C')
// ------------------------------------------------------------
-#define B3_SWITCH_INT(a) { \
- char s_i, *p_i; \
- p_i= (char *)&(a); \
- s_i=p_i[0]; p_i[0]=p_i[3]; p_i[3]=s_i; \
- s_i=p_i[1]; p_i[1]=p_i[2]; p_i[2]=s_i; }
+#define B3_SWITCH_INT(a) \
+ { \
+ char s_i, *p_i; \
+ p_i = (char *)&(a); \
+ s_i = p_i[0]; \
+ p_i[0] = p_i[3]; \
+ p_i[3] = s_i; \
+ s_i = p_i[1]; \
+ p_i[1] = p_i[2]; \
+ p_i[2] = s_i; \
+ }
// ------------------------------------------------------------
-#define B3_SWITCH_SHORT(a) { \
- char s_i, *p_i; \
- p_i= (char *)&(a); \
- s_i=p_i[0]; p_i[0]=p_i[1]; p_i[1]=s_i; }
+#define B3_SWITCH_SHORT(a) \
+ { \
+ char s_i, *p_i; \
+ p_i = (char *)&(a); \
+ s_i = p_i[0]; \
+ p_i[0] = p_i[1]; \
+ p_i[1] = s_i; \
+ }
// ------------------------------------------------------------
-#define B3_SWITCH_LONGINT(a) { \
- char s_i, *p_i; \
- p_i= (char *)&(a); \
- s_i=p_i[0]; p_i[0]=p_i[7]; p_i[7]=s_i; \
- s_i=p_i[1]; p_i[1]=p_i[6]; p_i[6]=s_i; \
- s_i=p_i[2]; p_i[2]=p_i[5]; p_i[5]=s_i; \
- s_i=p_i[3]; p_i[3]=p_i[4]; p_i[4]=s_i; }
-
-#endif//__B_DEFINES_H__
+#define B3_SWITCH_LONGINT(a) \
+ { \
+ char s_i, *p_i; \
+ p_i = (char *)&(a); \
+ s_i = p_i[0]; \
+ p_i[0] = p_i[7]; \
+ p_i[7] = s_i; \
+ s_i = p_i[1]; \
+ p_i[1] = p_i[6]; \
+ p_i[6] = s_i; \
+ s_i = p_i[2]; \
+ p_i[2] = p_i[5]; \
+ p_i[5] = s_i; \
+ s_i = p_i[3]; \
+ p_i[3] = p_i[4]; \
+ p_i[4] = s_i; \
+ }
+
+#endif //__B_DEFINES_H__
diff --git a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3File.cpp b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3File.cpp
index 432f7fc2b4..145de62db3 100644
--- a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3File.cpp
+++ b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3File.cpp
@@ -29,39 +29,38 @@ subject to the following restrictions:
using namespace bParse;
#define MAX_STRLEN 1024
-const char* getCleanName(const char* memName, char* buffer)
+const char *getCleanName(const char *memName, char *buffer)
{
int slen = strlen(memName);
- assert(slen<MAX_STRLEN);
- slen=b3Min(slen,MAX_STRLEN);
- for (int i=0;i<slen;i++)
+ assert(slen < MAX_STRLEN);
+ slen = b3Min(slen, MAX_STRLEN);
+ for (int i = 0; i < slen; i++)
{
- if (memName[i]==']'||memName[i]=='[')
+ if (memName[i] == ']' || memName[i] == '[')
{
- buffer[i] = 0;//'_';
- } else
+ buffer[i] = 0; //'_';
+ }
+ else
{
buffer[i] = memName[i];
}
}
- buffer[slen]=0;
+ buffer[slen] = 0;
return buffer;
}
-
-
// ----------------------------------------------------- //
bFile::bFile(const char *filename, const char headerString[7])
- : mOwnsBuffer(true),
- mFileBuffer(0),
- mFileLen(0),
- mVersion(0),
- mDataStart(0),
- mFileDNA(0),
- mMemoryDNA(0),
- mFlags(FD_INVALID)
+ : mOwnsBuffer(true),
+ mFileBuffer(0),
+ mFileLen(0),
+ mVersion(0),
+ mDataStart(0),
+ mFileDNA(0),
+ mMemoryDNA(0),
+ mFlags(FD_INVALID)
{
- for (int i=0;i<7;i++)
+ for (int i = 0; i < 7; i++)
{
m_headerString[i] = headerString[i];
}
@@ -73,7 +72,7 @@ bFile::bFile(const char *filename, const char headerString[7])
mFileLen = ftell(fp);
fseek(fp, 0L, SEEK_SET);
- mFileBuffer = (char*)malloc(mFileLen+1);
+ mFileBuffer = (char *)malloc(mFileLen + 1);
int bytesRead;
bytesRead = fread(mFileBuffer, mFileLen, 1, fp);
@@ -81,22 +80,21 @@ bFile::bFile(const char *filename, const char headerString[7])
//
parseHeader();
-
}
}
// ----------------------------------------------------- //
-bFile::bFile( char *memoryBuffer, int len, const char headerString[7])
-: mOwnsBuffer(false),
- mFileBuffer(0),
- mFileLen(0),
- mVersion(0),
- mDataStart(0),
- mFileDNA(0),
- mMemoryDNA(0),
- mFlags(FD_INVALID)
+bFile::bFile(char *memoryBuffer, int len, const char headerString[7])
+ : mOwnsBuffer(false),
+ mFileBuffer(0),
+ mFileLen(0),
+ mVersion(0),
+ mDataStart(0),
+ mFileDNA(0),
+ mMemoryDNA(0),
+ mFlags(FD_INVALID)
{
- for (int i=0;i<7;i++)
+ for (int i = 0; i < 7; i++)
{
m_headerString[i] = headerString[i];
}
@@ -104,10 +102,8 @@ bFile::bFile( char *memoryBuffer, int len, const char headerString[7])
mFileLen = len;
parseHeader();
-
}
-
// ----------------------------------------------------- //
bFile::~bFile()
{
@@ -117,15 +113,10 @@ bFile::~bFile()
mFileBuffer = 0;
}
-
delete mMemoryDNA;
delete mFileDNA;
}
-
-
-
-
// ----------------------------------------------------- //
void bFile::parseHeader()
{
@@ -133,11 +124,11 @@ void bFile::parseHeader()
return;
char *blenderBuf = mFileBuffer;
- char header[B3_SIZEOFBLENDERHEADER+1] ;
+ char header[B3_SIZEOFBLENDERHEADER + 1];
memcpy(header, blenderBuf, B3_SIZEOFBLENDERHEADER);
- header[B3_SIZEOFBLENDERHEADER]='\0';
+ header[B3_SIZEOFBLENDERHEADER] = '\0';
- if (strncmp(header, m_headerString, 6)!=0)
+ if (strncmp(header, m_headerString, 6) != 0)
{
memcpy(header, m_headerString, B3_SIZEOFBLENDERHEADER);
return;
@@ -148,35 +139,34 @@ void bFile::parseHeader()
mFlags |= FD_DOUBLE_PRECISION;
}
- char *ver = header+9;
+ char *ver = header + 9;
mVersion = atoi(ver);
if (mVersion <= 241)
{
//printf("Warning, %d not fully tested : <= 242\n", mVersion);
}
- int littleEndian= 1;
- littleEndian= ((char*)&littleEndian)[0];
+ int littleEndian = 1;
+ littleEndian = ((char *)&littleEndian)[0];
// swap ptr sizes...
- if (header[7]=='-')
+ if (header[7] == '-')
{
mFlags |= FD_FILE_64;
if (!VOID_IS_8)
mFlags |= FD_BITS_VARIES;
}
- else if (VOID_IS_8) mFlags |= FD_BITS_VARIES;
+ else if (VOID_IS_8)
+ mFlags |= FD_BITS_VARIES;
// swap endian...
- if (header[8]=='V')
+ if (header[8] == 'V')
{
- if (littleEndian ==1)
+ if (littleEndian == 1)
mFlags |= FD_ENDIAN_SWAP;
}
- else
- if (littleEndian==0)
- mFlags |= FD_ENDIAN_SWAP;
-
+ else if (littleEndian == 0)
+ mFlags |= FD_ENDIAN_SWAP;
mFlags |= FD_OK;
}
@@ -184,13 +174,13 @@ void bFile::parseHeader()
// ----------------------------------------------------- //
bool bFile::ok()
{
- return (mFlags &FD_OK)!=0;
+ return (mFlags & FD_OK) != 0;
}
// ----------------------------------------------------- //
-void bFile::parseInternal(int verboseMode, char* memDna,int memDnaLength)
+void bFile::parseInternal(int verboseMode, char *memDna, int memDnaLength)
{
- if ( (mFlags &FD_OK) ==0)
+ if ((mFlags & FD_OK) == 0)
return;
char *blenderData = mFileBuffer;
@@ -198,38 +188,40 @@ void bFile::parseInternal(int verboseMode, char* memDna,int memDnaLength)
dna.oldPtr = 0;
char *tempBuffer = blenderData;
- for (int i=0; i<mFileLen; i++)
+ for (int i = 0; i < mFileLen; i++)
{
// looking for the data's starting position
// and the start of SDNA decls
- if (!mDataStart && strncmp(tempBuffer, "REND", 4)==0)
+ if (!mDataStart && strncmp(tempBuffer, "REND", 4) == 0)
mDataStart = i;
- if (strncmp(tempBuffer, "DNA1", 4)==0)
+ if (strncmp(tempBuffer, "DNA1", 4) == 0)
{
// read the DNA1 block and extract SDNA
if (getNextBlock(&dna, tempBuffer, mFlags) > 0)
{
- if (strncmp((tempBuffer + ChunkUtils::getOffset(mFlags)), "SDNANAME", 8) ==0)
+ if (strncmp((tempBuffer + ChunkUtils::getOffset(mFlags)), "SDNANAME", 8) == 0)
dna.oldPtr = (tempBuffer + ChunkUtils::getOffset(mFlags));
- else dna.oldPtr = 0;
+ else
+ dna.oldPtr = 0;
}
- else dna.oldPtr = 0;
+ else
+ dna.oldPtr = 0;
}
// Some Bullet files are missing the DNA1 block
// In Blender it's DNA1 + ChunkUtils::getOffset() + SDNA + NAME
// In Bullet tests its SDNA + NAME
- else if (strncmp(tempBuffer, "SDNANAME", 8) ==0)
+ else if (strncmp(tempBuffer, "SDNANAME", 8) == 0)
{
dna.oldPtr = blenderData + i;
- dna.len = mFileLen-i;
+ dna.len = mFileLen - i;
// Also no REND block, so exit now.
- if (mVersion==276) break;
+ if (mVersion == 276) break;
}
- if (mDataStart && dna.oldPtr) break;
+ if (mDataStart && dna.oldPtr) break;
tempBuffer++;
}
if (!dna.oldPtr || !dna.len)
@@ -239,43 +231,35 @@ void bFile::parseInternal(int verboseMode, char* memDna,int memDnaLength)
return;
}
-
mFileDNA = new bDNA();
-
///mFileDNA->init will convert part of DNA file endianness to current CPU endianness if necessary
- mFileDNA->init((char*)dna.oldPtr, dna.len, (mFlags & FD_ENDIAN_SWAP)!=0);
-
+ mFileDNA->init((char *)dna.oldPtr, dna.len, (mFlags & FD_ENDIAN_SWAP) != 0);
- if (mVersion==276)
+ if (mVersion == 276)
{
int i;
- for (i=0;i<mFileDNA->getNumNames();i++)
+ for (i = 0; i < mFileDNA->getNumNames(); i++)
{
- if (strcmp(mFileDNA->getName(i),"int")==0)
+ if (strcmp(mFileDNA->getName(i), "int") == 0)
{
mFlags |= FD_BROKEN_DNA;
}
}
- if ((mFlags&FD_BROKEN_DNA)!=0)
+ if ((mFlags & FD_BROKEN_DNA) != 0)
{
//printf("warning: fixing some broken DNA version\n");
}
}
-
-
if (verboseMode & FD_VERBOSE_DUMP_DNA_TYPE_DEFINITIONS)
mFileDNA->dumpTypeDefinitions();
mMemoryDNA = new bDNA();
- int littleEndian= 1;
- littleEndian= ((char*)&littleEndian)[0];
-
- mMemoryDNA->init(memDna,memDnaLength,littleEndian==0);
-
-
+ int littleEndian = 1;
+ littleEndian = ((char *)&littleEndian)[0];
+ mMemoryDNA->init(memDna, memDnaLength, littleEndian == 0);
///@todo we need a better version check, add version/sub version info from FileGlobal into memory DNA/header files
if (mMemoryDNA->getNumNames() != mFileDNA->getNumNames())
@@ -290,7 +274,6 @@ void bFile::parseInternal(int verboseMode, char* memDna,int memDnaLength)
//printf ("Warning, file DNA is newer than built in.");
}
-
mFileDNA->initCmpFlags(mMemoryDNA);
parseData();
@@ -298,102 +281,95 @@ void bFile::parseInternal(int verboseMode, char* memDna,int memDnaLength)
resolvePointers(verboseMode);
updateOldPointers();
-
-
}
-
-
// ----------------------------------------------------- //
-void bFile::swap(char *head, bChunkInd& dataChunk, bool ignoreEndianFlag)
+void bFile::swap(char *head, bChunkInd &dataChunk, bool ignoreEndianFlag)
{
char *data = head;
short *strc = mFileDNA->getStruct(dataChunk.dna_nr);
-
-
const char s[] = "SoftBodyMaterialData";
int szs = sizeof(s);
- if (strncmp((char*)&dataChunk.code,"ARAY",4)==0)
+ if (strncmp((char *)&dataChunk.code, "ARAY", 4) == 0)
{
short *oldStruct = mFileDNA->getStruct(dataChunk.dna_nr);
char *oldType = mFileDNA->getType(oldStruct[0]);
- if (strncmp(oldType,s,szs)==0)
+ if (strncmp(oldType, s, szs) == 0)
{
return;
}
}
-
int len = mFileDNA->getLength(strc[0]);
- for (int i=0; i<dataChunk.nr; i++)
+ for (int i = 0; i < dataChunk.nr; i++)
{
- swapStruct(dataChunk.dna_nr, data,ignoreEndianFlag);
- data+=len;
+ swapStruct(dataChunk.dna_nr, data, ignoreEndianFlag);
+ data += len;
}
}
void bFile::swapLen(char *dataPtr)
{
- const bool VOID_IS_8 = ((sizeof(void*)==8));
+ const bool VOID_IS_8 = ((sizeof(void *) == 8));
if (VOID_IS_8)
{
- if (mFlags &FD_BITS_VARIES)
+ if (mFlags & FD_BITS_VARIES)
{
- bChunkPtr4*c = (bChunkPtr4*) dataPtr;
- if ((c->code & 0xFFFF)==0)
- c->code >>=16;
+ bChunkPtr4 *c = (bChunkPtr4 *)dataPtr;
+ if ((c->code & 0xFFFF) == 0)
+ c->code >>= 16;
B3_SWITCH_INT(c->len);
B3_SWITCH_INT(c->dna_nr);
B3_SWITCH_INT(c->nr);
- } else
+ }
+ else
{
- bChunkPtr8* c = (bChunkPtr8*) dataPtr;
- if ((c->code & 0xFFFF)==0)
- c->code >>=16;
+ bChunkPtr8 *c = (bChunkPtr8 *)dataPtr;
+ if ((c->code & 0xFFFF) == 0)
+ c->code >>= 16;
B3_SWITCH_INT(c->len);
B3_SWITCH_INT(c->dna_nr);
B3_SWITCH_INT(c->nr);
-
}
- } else
+ }
+ else
{
- if (mFlags &FD_BITS_VARIES)
+ if (mFlags & FD_BITS_VARIES)
{
- bChunkPtr8*c = (bChunkPtr8*) dataPtr;
- if ((c->code & 0xFFFF)==0)
- c->code >>=16;
+ bChunkPtr8 *c = (bChunkPtr8 *)dataPtr;
+ if ((c->code & 0xFFFF) == 0)
+ c->code >>= 16;
B3_SWITCH_INT(c->len);
B3_SWITCH_INT(c->dna_nr);
B3_SWITCH_INT(c->nr);
-
- } else
+ }
+ else
{
- bChunkPtr4* c = (bChunkPtr4*) dataPtr;
- if ((c->code & 0xFFFF)==0)
- c->code >>=16;
+ bChunkPtr4 *c = (bChunkPtr4 *)dataPtr;
+ if ((c->code & 0xFFFF) == 0)
+ c->code >>= 16;
B3_SWITCH_INT(c->len);
B3_SWITCH_INT(c->dna_nr);
B3_SWITCH_INT(c->nr);
-
}
}
-
}
-
-void bFile::swapDNA(char* ptr)
+void bFile::swapDNA(char *ptr)
{
- bool swap = ((mFlags & FD_ENDIAN_SWAP)!=0);
-
- char* data = &ptr[20];
-// void bDNA::init(char *data, int len, bool swap)
- int *intPtr=0;short *shtPtr=0;
- char *cp = 0;int dataLen =0;
+ bool swap = ((mFlags & FD_ENDIAN_SWAP) != 0);
+
+ char *data = &ptr[20];
+ // void bDNA::init(char *data, int len, bool swap)
+ int *intPtr = 0;
+ short *shtPtr = 0;
+ char *cp = 0;
+ int dataLen = 0;
//long nr=0;
- intPtr = (int*)data;
+ intPtr = (int *)data;
/*
SDNA (4 bytes) (magic number)
@@ -403,14 +379,13 @@ void bFile::swapDNA(char* ptr)
<string>
*/
- if (strncmp(data, "SDNA", 4)==0)
+ if (strncmp(data, "SDNA", 4) == 0)
{
// skip ++ NAME
- intPtr++; intPtr++;
+ intPtr++;
+ intPtr++;
}
-
-
// Parse names
if (swap)
dataLen = ChunkUtils::swapInt(*intPtr);
@@ -420,16 +395,15 @@ void bFile::swapDNA(char* ptr)
*intPtr = ChunkUtils::swapInt(*intPtr);
intPtr++;
- cp = (char*)intPtr;
+ cp = (char *)intPtr;
int i;
- for ( i=0; i<dataLen; i++)
+ for (i = 0; i < dataLen; i++)
{
- while (*cp)cp++;
+ while (*cp) cp++;
cp++;
}
-
- cp = b3AlignPointer(cp,4);
+ cp = b3AlignPointer(cp, 4);
/*
TYPE (4 bytes)
@@ -438,8 +412,9 @@ void bFile::swapDNA(char* ptr)
<string>
*/
- intPtr = (int*)cp;
- assert(strncmp(cp, "TYPE", 4)==0); intPtr++;
+ intPtr = (int *)cp;
+ assert(strncmp(cp, "TYPE", 4) == 0);
+ intPtr++;
if (swap)
dataLen = ChunkUtils::swapInt(*intPtr);
@@ -450,14 +425,14 @@ void bFile::swapDNA(char* ptr)
intPtr++;
- cp = (char*)intPtr;
- for ( i=0; i<dataLen; i++)
+ cp = (char *)intPtr;
+ for (i = 0; i < dataLen; i++)
{
- while (*cp)cp++;
+ while (*cp) cp++;
cp++;
}
- cp = b3AlignPointer(cp,4);
+ cp = b3AlignPointer(cp, 4);
/*
TLEN (4 bytes)
@@ -466,15 +441,15 @@ void bFile::swapDNA(char* ptr)
*/
// Parse type lens
- intPtr = (int*)cp;
- assert(strncmp(cp, "TLEN", 4)==0); intPtr++;
-
+ intPtr = (int *)cp;
+ assert(strncmp(cp, "TLEN", 4) == 0);
+ intPtr++;
- shtPtr = (short*)intPtr;
- for ( i=0; i<dataLen; i++, shtPtr++)
+ shtPtr = (short *)intPtr;
+ for (i = 0; i < dataLen; i++, shtPtr++)
{
//??????if (swap)
- shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
+ shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
}
if (dataLen & 1)
@@ -491,9 +466,9 @@ void bFile::swapDNA(char* ptr)
<namenr>
*/
- intPtr = (int*)shtPtr;
- cp = (char*)intPtr;
- assert(strncmp(cp, "STRC", 4)==0);
+ intPtr = (int *)shtPtr;
+ cp = (char *)intPtr;
+ assert(strncmp(cp, "STRC", 4) == 0);
intPtr++;
if (swap)
@@ -505,66 +480,56 @@ void bFile::swapDNA(char* ptr)
intPtr++;
-
- shtPtr = (short*)intPtr;
- for ( i=0; i<dataLen; i++)
+ shtPtr = (short *)intPtr;
+ for (i = 0; i < dataLen; i++)
{
-
//if (swap)
{
int len = shtPtr[1];
- shtPtr[0]= ChunkUtils::swapShort(shtPtr[0]);
- shtPtr[1]= ChunkUtils::swapShort(shtPtr[1]);
+ shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
+ shtPtr[1] = ChunkUtils::swapShort(shtPtr[1]);
- shtPtr+= 2;
+ shtPtr += 2;
- for (int a=0; a<len; a++, shtPtr+=2)
+ for (int a = 0; a < len; a++, shtPtr += 2)
{
- shtPtr[0]= ChunkUtils::swapShort(shtPtr[0]);
- shtPtr[1]= ChunkUtils::swapShort(shtPtr[1]);
+ shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
+ shtPtr[1] = ChunkUtils::swapShort(shtPtr[1]);
}
}
-// else
-// shtPtr+= (2*shtPtr[1])+2;
+ // else
+ // shtPtr+= (2*shtPtr[1])+2;
}
-
}
-void bFile::writeFile(const char* fileName)
+void bFile::writeFile(const char *fileName)
{
- FILE* f = fopen(fileName,"wb");
- fwrite(mFileBuffer,1,mFileLen,f);
+ FILE *f = fopen(fileName, "wb");
+ fwrite(mFileBuffer, 1, mFileLen, f);
fclose(f);
}
void bFile::preSwap()
{
-
//const bool brokenDNA = (mFlags&FD_BROKEN_DNA)!=0;
//FD_ENDIAN_SWAP
//byte 8 determines the endianness of the file, little (v) versus big (V)
- int littleEndian= 1;
- littleEndian= ((char*)&littleEndian)[0];
-
+ int littleEndian = 1;
+ littleEndian = ((char *)&littleEndian)[0];
- if (mFileBuffer[8]=='V')
+ if (mFileBuffer[8] == 'V')
{
- mFileBuffer[8]='v';
+ mFileBuffer[8] = 'v';
}
else
{
- mFileBuffer[8]='V';
+ mFileBuffer[8] = 'V';
}
-
-
-
-
-
mDataStart = 12;
- char *dataPtr = mFileBuffer+mDataStart;
+ char *dataPtr = mFileBuffer + mDataStart;
bChunkInd dataChunk;
dataChunk.code = 0;
@@ -579,21 +544,22 @@ void bFile::preSwap()
while (1)
{
// one behind
- if (dataChunk.code == B3_SDNA || dataChunk.code==B3_DNA1 || dataChunk.code == B3_TYPE || dataChunk.code == B3_TLEN || dataChunk.code==B3_STRC)
+ if (dataChunk.code == B3_SDNA || dataChunk.code == B3_DNA1 || dataChunk.code == B3_TYPE || dataChunk.code == B3_TLEN || dataChunk.code == B3_STRC)
{
-
swapDNA(dataPtr);
break;
- } else
+ }
+ else
{
//if (dataChunk.code == DNA1) break;
- dataPtrHead = dataPtr+ChunkUtils::getOffset(mFlags);
+ dataPtrHead = dataPtr + ChunkUtils::getOffset(mFlags);
swapLen(dataPtr);
- if (dataChunk.dna_nr>=0)
+ if (dataChunk.dna_nr >= 0)
{
- swap(dataPtrHead, dataChunk,ignoreEndianFlag);
- } else
+ swap(dataPtrHead, dataChunk, ignoreEndianFlag);
+ }
+ else
{
//printf("unknown chunk\n");
}
@@ -602,7 +568,7 @@ void bFile::preSwap()
// next please!
dataPtr += seek;
- seek = getNextBlock(&dataChunk, dataPtr, mFlags);
+ seek = getNextBlock(&dataChunk, dataPtr, mFlags);
if (seek < 0)
break;
}
@@ -610,56 +576,50 @@ void bFile::preSwap()
if (mFlags & FD_ENDIAN_SWAP)
{
mFlags &= ~FD_ENDIAN_SWAP;
- } else
+ }
+ else
{
mFlags |= FD_ENDIAN_SWAP;
}
-
-
-
}
-
// ----------------------------------------------------- //
-char* bFile::readStruct(char *head, bChunkInd& dataChunk)
+char *bFile::readStruct(char *head, bChunkInd &dataChunk)
{
bool ignoreEndianFlag = false;
if (mFlags & FD_ENDIAN_SWAP)
swap(head, dataChunk, ignoreEndianFlag);
-
-
if (!mFileDNA->flagEqual(dataChunk.dna_nr))
{
// Ouch! need to rebuild the struct
- short *oldStruct,*curStruct;
+ short *oldStruct, *curStruct;
char *oldType, *newType;
int oldLen, curLen, reverseOld;
-
oldStruct = mFileDNA->getStruct(dataChunk.dna_nr);
oldType = mFileDNA->getType(oldStruct[0]);
oldLen = mFileDNA->getLength(oldStruct[0]);
- if ((mFlags&FD_BROKEN_DNA)!=0)
+ if ((mFlags & FD_BROKEN_DNA) != 0)
{
- if ((strcmp(oldType,"b3QuantizedBvhNodeData")==0)&&oldLen==20)
+ if ((strcmp(oldType, "b3QuantizedBvhNodeData") == 0) && oldLen == 20)
{
return 0;
}
- if ((strcmp(oldType,"b3ShortIntIndexData")==0))
+ if ((strcmp(oldType, "b3ShortIntIndexData") == 0))
{
int allocLen = 2;
- char *dataAlloc = new char[(dataChunk.nr*allocLen)+1];
- memset(dataAlloc, 0, (dataChunk.nr*allocLen)+1);
- short* dest = (short*) dataAlloc;
- const short* src = (short*) head;
- for (int i=0;i<dataChunk.nr;i++)
+ char *dataAlloc = new char[(dataChunk.nr * allocLen) + 1];
+ memset(dataAlloc, 0, (dataChunk.nr * allocLen) + 1);
+ short *dest = (short *)dataAlloc;
+ const short *src = (short *)head;
+ for (int i = 0; i < dataChunk.nr; i++)
{
dest[i] = src[i];
- if (mFlags &FD_ENDIAN_SWAP)
+ if (mFlags & FD_ENDIAN_SWAP)
{
B3_SWITCH_SHORT(dest[i]);
}
@@ -669,14 +629,12 @@ char* bFile::readStruct(char *head, bChunkInd& dataChunk)
}
}
-
-
///don't try to convert Link block data, just memcpy it. Other data can be converted.
- if (strcmp("Link",oldType)!=0)
+ if (strcmp("Link", oldType) != 0)
{
reverseOld = mMemoryDNA->getReverseType(oldType);
- if ((reverseOld!=-1))
+ if ((reverseOld != -1))
{
// make sure it's here
//assert(reverseOld!= -1 && "getReverseType() returned -1, struct required!");
@@ -686,39 +644,38 @@ char* bFile::readStruct(char *head, bChunkInd& dataChunk)
newType = mMemoryDNA->getType(curStruct[0]);
curLen = mMemoryDNA->getLength(curStruct[0]);
-
-
// make sure it's the same
- assert((strcmp(oldType, newType)==0) && "internal error, struct mismatch!");
-
+ assert((strcmp(oldType, newType) == 0) && "internal error, struct mismatch!");
// numBlocks * length
- int allocLen = (curLen);
- char *dataAlloc = new char[(dataChunk.nr*allocLen)+1];
- memset(dataAlloc, 0, (dataChunk.nr*allocLen));
+ int allocLen = (curLen);
+ char *dataAlloc = new char[(dataChunk.nr * allocLen) + 1];
+ memset(dataAlloc, 0, (dataChunk.nr * allocLen));
// track allocated
addDataBlock(dataAlloc);
char *cur = dataAlloc;
char *old = head;
- for (int block=0; block<dataChunk.nr; block++)
+ for (int block = 0; block < dataChunk.nr; block++)
{
bool fixupPointers = true;
parseStruct(cur, old, dataChunk.dna_nr, reverseOld, fixupPointers);
- mLibPointers.insert(old,(bStructHandle*)cur);
+ mLibPointers.insert(old, (bStructHandle *)cur);
cur += curLen;
old += oldLen;
}
return dataAlloc;
}
- } else
+ }
+ else
{
//printf("Link found\n");
}
- } else
+ }
+ else
{
//#define DEBUG_EQUAL_STRUCTS
#ifdef DEBUG_EQUAL_STRUCTS
@@ -726,24 +683,20 @@ char* bFile::readStruct(char *head, bChunkInd& dataChunk)
char *oldType;
oldStruct = mFileDNA->getStruct(dataChunk.dna_nr);
oldType = mFileDNA->getType(oldStruct[0]);
- printf("%s equal structure, just memcpy\n",oldType);
-#endif //
+ printf("%s equal structure, just memcpy\n", oldType);
+#endif //
}
-
- char *dataAlloc = new char[(dataChunk.len)+1];
- memset(dataAlloc, 0, dataChunk.len+1);
-
+ char *dataAlloc = new char[(dataChunk.len) + 1];
+ memset(dataAlloc, 0, dataChunk.len + 1);
// track allocated
addDataBlock(dataAlloc);
memcpy(dataAlloc, head, dataChunk.len);
return dataAlloc;
-
}
-
// ----------------------------------------------------- //
void bFile::parseStruct(char *strcPtr, char *dtPtr, int old_dna, int new_dna, bool fixupPointers)
{
@@ -751,7 +704,7 @@ void bFile::parseStruct(char *strcPtr, char *dtPtr, int old_dna, int new_dna, bo
if (new_dna == -1) return;
//disable this, because we need to fixup pointers/ListBase
- if (0)//mFileDNA->flagEqual(old_dna))
+ if (0) //mFileDNA->flagEqual(old_dna))
{
short *strc = mFileDNA->getStruct(old_dna);
int len = mFileDNA->getLength(strc[0]);
@@ -766,31 +719,29 @@ void bFile::parseStruct(char *strcPtr, char *dtPtr, int old_dna, int new_dna, bo
int elementLength, size, revType, old_nr, new_nr, fpLen;
short firstStructType;
-
// File to memory lookup
memoryStruct = mMemoryDNA->getStruct(new_dna);
fileStruct = mFileDNA->getStruct(old_dna);
firstStruct = fileStruct;
-
filePtrOld = fileStruct;
firstStructType = mMemoryDNA->getStruct(0)[0];
// Get number of elements
elementLength = memoryStruct[1];
- memoryStruct+=2;
+ memoryStruct += 2;
- cpc = strcPtr; cpo = 0;
- for (int ele=0; ele<elementLength; ele++, memoryStruct+=2)
+ cpc = strcPtr;
+ cpo = 0;
+ for (int ele = 0; ele < elementLength; ele++, memoryStruct += 2)
{
memType = mMemoryDNA->getType(memoryStruct[0]);
memName = mMemoryDNA->getName(memoryStruct[1]);
-
size = mMemoryDNA->getElementSize(memoryStruct[0], memoryStruct[1]);
revType = mMemoryDNA->getReverseType(memoryStruct[0]);
- if (revType != -1 && memoryStruct[0]>=firstStructType && memName[0] != '*')
+ if (revType != -1 && memoryStruct[0] >= firstStructType && memName[0] != '*')
{
cpo = getFileElement(firstStruct, memName, memType, dtPtr, &filePtrOld);
if (cpo)
@@ -799,94 +750,92 @@ void bFile::parseStruct(char *strcPtr, char *dtPtr, int old_dna, int new_dna, bo
old_nr = mFileDNA->getReverseType(memType);
new_nr = revType;
fpLen = mFileDNA->getElementSize(filePtrOld[0], filePtrOld[1]);
- if (arrayLen==1)
+ if (arrayLen == 1)
{
- parseStruct(cpc, cpo, old_nr, new_nr,fixupPointers);
- } else
+ parseStruct(cpc, cpo, old_nr, new_nr, fixupPointers);
+ }
+ else
{
- char* tmpCpc = cpc;
- char* tmpCpo = cpo;
+ char *tmpCpc = cpc;
+ char *tmpCpo = cpo;
- for (int i=0;i<arrayLen;i++)
+ for (int i = 0; i < arrayLen; i++)
{
- parseStruct(tmpCpc, tmpCpo, old_nr, new_nr,fixupPointers);
- tmpCpc += size/arrayLen;
- tmpCpo += fpLen/arrayLen;
+ parseStruct(tmpCpc, tmpCpo, old_nr, new_nr, fixupPointers);
+ tmpCpc += size / arrayLen;
+ tmpCpo += fpLen / arrayLen;
}
}
- cpc+=size;
- cpo+=fpLen;
+ cpc += size;
+ cpo += fpLen;
}
else
- cpc+=size;
+ cpc += size;
}
else
{
- getMatchingFileDNA(fileStruct, memName, memType, cpc, dtPtr,fixupPointers);
- cpc+=size;
+ getMatchingFileDNA(fileStruct, memName, memType, cpc, dtPtr, fixupPointers);
+ cpc += size;
}
-
}
}
-
// ----------------------------------------------------- //
static void getElement(int arrayLen, const char *cur, const char *old, char *oldPtr, char *curData)
{
-#define b3GetEle(value, current, type, cast, size, ptr)\
- if (strcmp(current, type)==0)\
- {\
- value = (*(cast*)ptr);\
- ptr += size;\
+#define b3GetEle(value, current, type, cast, size, ptr) \
+ if (strcmp(current, type) == 0) \
+ { \
+ value = (*(cast *)ptr); \
+ ptr += size; \
}
-#define b3SetEle(value, current, type, cast, size, ptr)\
- if (strcmp(current, type)==0)\
- {\
- (*(cast*)ptr) = (cast)value;\
- ptr += size;\
+#define b3SetEle(value, current, type, cast, size, ptr) \
+ if (strcmp(current, type) == 0) \
+ { \
+ (*(cast *)ptr) = (cast)value; \
+ ptr += size; \
}
double value = 0.0;
- for (int i=0; i<arrayLen; i++)
+ for (int i = 0; i < arrayLen; i++)
{
- b3GetEle(value, old, "char", char, sizeof(char), oldPtr);
- b3SetEle(value, cur, "char", char, sizeof(char), curData);
- b3GetEle(value, old, "short", short, sizeof(short), oldPtr);
- b3SetEle(value, cur, "short", short, sizeof(short), curData);
- b3GetEle(value, old, "ushort", unsigned short, sizeof(unsigned short), oldPtr);
- b3SetEle(value, cur, "ushort", unsigned short, sizeof(unsigned short), curData);
- b3GetEle(value, old, "int", int, sizeof(int), oldPtr);
- b3SetEle(value, cur, "int", int, sizeof(int), curData);
- b3GetEle(value, old, "long", int, sizeof(int), oldPtr);
- b3SetEle(value, cur, "long", int, sizeof(int), curData);
- b3GetEle(value, old, "float", float, sizeof(float), oldPtr);
- b3SetEle(value, cur, "float", float, sizeof(float), curData);
+ b3GetEle(value, old, "char", char, sizeof(char), oldPtr);
+ b3SetEle(value, cur, "char", char, sizeof(char), curData);
+ b3GetEle(value, old, "short", short, sizeof(short), oldPtr);
+ b3SetEle(value, cur, "short", short, sizeof(short), curData);
+ b3GetEle(value, old, "ushort", unsigned short, sizeof(unsigned short), oldPtr);
+ b3SetEle(value, cur, "ushort", unsigned short, sizeof(unsigned short), curData);
+ b3GetEle(value, old, "int", int, sizeof(int), oldPtr);
+ b3SetEle(value, cur, "int", int, sizeof(int), curData);
+ b3GetEle(value, old, "long", int, sizeof(int), oldPtr);
+ b3SetEle(value, cur, "long", int, sizeof(int), curData);
+ b3GetEle(value, old, "float", float, sizeof(float), oldPtr);
+ b3SetEle(value, cur, "float", float, sizeof(float), curData);
b3GetEle(value, old, "double", double, sizeof(double), oldPtr);
b3SetEle(value, cur, "double", double, sizeof(double), curData);
}
}
-
// ----------------------------------------------------- //
-void bFile::swapData(char *data, short type, int arraySize,bool ignoreEndianFlag)
+void bFile::swapData(char *data, short type, int arraySize, bool ignoreEndianFlag)
{
- if (ignoreEndianFlag || (mFlags &FD_ENDIAN_SWAP))
+ if (ignoreEndianFlag || (mFlags & FD_ENDIAN_SWAP))
{
if (type == 2 || type == 3)
{
- short *sp = (short*)data;
- for (int i=0; i<arraySize; i++)
+ short *sp = (short *)data;
+ for (int i = 0; i < arraySize; i++)
{
sp[0] = ChunkUtils::swapShort(sp[0]);
sp++;
}
}
- if (type>3 && type <8)
+ if (type > 3 && type < 8)
{
char c;
char *cp = data;
- for (int i=0; i<arraySize; i++)
+ for (int i = 0; i < arraySize; i++)
{
c = cp[0];
cp[0] = cp[3];
@@ -894,14 +843,12 @@ void bFile::swapData(char *data, short type, int arraySize,bool ignoreEndianFlag
c = cp[1];
cp[1] = cp[2];
cp[2] = c;
- cp+=4;
+ cp += 4;
}
}
}
}
-
-
void bFile::safeSwapPtr(char *dst, const char *src)
{
int ptrFile = mFileDNA->getPointerSize();
@@ -910,84 +857,79 @@ void bFile::safeSwapPtr(char *dst, const char *src)
if (!src && !dst)
return;
-
if (ptrFile == ptrMem)
{
memcpy(dst, src, ptrMem);
}
- else if (ptrMem==4 && ptrFile==8)
+ else if (ptrMem == 4 && ptrFile == 8)
{
- b3PointerUid* oldPtr = (b3PointerUid*)src;
- b3PointerUid* newPtr = (b3PointerUid*)dst;
+ b3PointerUid *oldPtr = (b3PointerUid *)src;
+ b3PointerUid *newPtr = (b3PointerUid *)dst;
if (oldPtr->m_uniqueIds[0] == oldPtr->m_uniqueIds[1])
{
//Bullet stores the 32bit unique ID in both upper and lower part of 64bit pointers
//so it can be used to distinguish between .blend and .bullet
newPtr->m_uniqueIds[0] = oldPtr->m_uniqueIds[0];
- } else
+ }
+ else
{
//deal with pointers the Blender .blend style way, see
//readfile.c in the Blender source tree
- b3Long64 longValue = *((b3Long64*)src);
+ b3Long64 longValue = *((b3Long64 *)src);
//endian swap for 64bit pointer otherwise truncation will fail due to trailing zeros
if (mFlags & FD_ENDIAN_SWAP)
B3_SWITCH_LONGINT(longValue);
- *((int*)dst) = (int)(longValue>>3);
+ *((int *)dst) = (int)(longValue >> 3);
}
-
}
- else if (ptrMem==8 && ptrFile==4)
+ else if (ptrMem == 8 && ptrFile == 4)
{
- b3PointerUid* oldPtr = (b3PointerUid*)src;
- b3PointerUid* newPtr = (b3PointerUid*)dst;
+ b3PointerUid *oldPtr = (b3PointerUid *)src;
+ b3PointerUid *newPtr = (b3PointerUid *)dst;
if (oldPtr->m_uniqueIds[0] == oldPtr->m_uniqueIds[1])
{
newPtr->m_uniqueIds[0] = oldPtr->m_uniqueIds[0];
newPtr->m_uniqueIds[1] = 0;
- } else
+ }
+ else
{
- *((b3Long64*)dst)= *((int*)src);
+ *((b3Long64 *)dst) = *((int *)src);
}
}
else
{
- printf ("%d %d\n", ptrFile,ptrMem);
+ printf("%d %d\n", ptrFile, ptrMem);
assert(0 && "Invalid pointer len");
}
-
-
}
-
// ----------------------------------------------------- //
-void bFile::getMatchingFileDNA(short* dna_addr, const char* lookupName, const char* lookupType, char *strcData, char *data, bool fixupPointers)
+void bFile::getMatchingFileDNA(short *dna_addr, const char *lookupName, const char *lookupType, char *strcData, char *data, bool fixupPointers)
{
// find the matching memory dna data
// to the file being loaded. Fill the
// memory with the file data...
int len = dna_addr[1];
- dna_addr+=2;
+ dna_addr += 2;
- for (int i=0; i<len; i++, dna_addr+=2)
+ for (int i = 0; i < len; i++, dna_addr += 2)
{
- const char* type = mFileDNA->getType(dna_addr[0]);
- const char* name = mFileDNA->getName(dna_addr[1]);
-
-
+ const char *type = mFileDNA->getType(dna_addr[0]);
+ const char *name = mFileDNA->getName(dna_addr[1]);
int eleLen = mFileDNA->getElementSize(dna_addr[0], dna_addr[1]);
- if ((mFlags&FD_BROKEN_DNA)!=0)
+ if ((mFlags & FD_BROKEN_DNA) != 0)
{
- if ((strcmp(type,"short")==0)&&(strcmp(name,"int")==0))
+ if ((strcmp(type, "short") == 0) && (strcmp(name, "int") == 0))
{
eleLen = 0;
}
}
- if (strcmp(lookupName, name)==0)
+ if (strcmp(lookupName, name) == 0)
{
//int arrayLenold = mFileDNA->getArraySize((char*)name.c_str());
int arrayLen = mFileDNA->getArraySizeNew(dna_addr[1]);
@@ -998,7 +940,7 @@ void bFile::getMatchingFileDNA(short* dna_addr, const char* lookupName, const c
// cast pointers
int ptrFile = mFileDNA->getPointerSize();
int ptrMem = mMemoryDNA->getPointerSize();
- safeSwapPtr(strcData,data);
+ safeSwapPtr(strcData, data);
if (fixupPointers)
{
@@ -1007,11 +949,11 @@ void bFile::getMatchingFileDNA(short* dna_addr, const char* lookupName, const c
//void **sarray = (void**)strcData;
//void **darray = (void**)data;
- char *cpc, *cpo;
- cpc = (char*)strcData;
- cpo = (char*)data;
+ char *cpc, *cpo;
+ cpc = (char *)strcData;
+ cpo = (char *)data;
- for (int a=0; a<arrayLen; a++)
+ for (int a = 0; a < arrayLen; a++)
{
safeSwapPtr(cpc, cpo);
m_pointerFixupArray.push_back(cpc);
@@ -1029,12 +971,11 @@ void bFile::getMatchingFileDNA(short* dna_addr, const char* lookupName, const c
}
else
{
-// printf("skipped %s %s : %x\n",type.c_str(),name.c_str(),strcData);
+ // printf("skipped %s %s : %x\n",type.c_str(),name.c_str(),strcData);
}
-
}
- else if (strcmp(type, lookupType)==0)
+ else if (strcmp(type, lookupType) == 0)
memcpy(strcData, data, eleLen);
else
getElement(arrayLen, lookupType, type, data, strcData);
@@ -1042,27 +983,26 @@ void bFile::getMatchingFileDNA(short* dna_addr, const char* lookupName, const c
// --
return;
}
- data+=eleLen;
+ data += eleLen;
}
}
-
// ----------------------------------------------------- //
-char* bFile::getFileElement(short *firstStruct, char *lookupName, char *lookupType, char *data, short **foundPos)
+char *bFile::getFileElement(short *firstStruct, char *lookupName, char *lookupType, char *data, short **foundPos)
{
- short *old = firstStruct;//mFileDNA->getStruct(old_nr);
+ short *old = firstStruct; //mFileDNA->getStruct(old_nr);
int elementLength = old[1];
- old+=2;
+ old += 2;
- for (int i=0; i<elementLength; i++, old+=2)
+ for (int i = 0; i < elementLength; i++, old += 2)
{
- char* type = mFileDNA->getType(old[0]);
- char* name = mFileDNA->getName(old[1]);
+ char *type = mFileDNA->getType(old[0]);
+ char *name = mFileDNA->getName(old[1]);
int len = mFileDNA->getElementSize(old[0], old[1]);
- if (strcmp(lookupName, name)==0)
+ if (strcmp(lookupName, name) == 0)
{
- if (strcmp(type, lookupType)==0)
+ if (strcmp(type, lookupType) == 0)
{
if (foundPos)
*foundPos = old;
@@ -1070,46 +1010,46 @@ char* bFile::getFileElement(short *firstStruct, char *lookupName, char *lookupTy
}
return 0;
}
- data+=len;
+ data += len;
}
return 0;
}
-
// ----------------------------------------------------- //
-void bFile::swapStruct(int dna_nr, char *data,bool ignoreEndianFlag)
+void bFile::swapStruct(int dna_nr, char *data, bool ignoreEndianFlag)
{
if (dna_nr == -1) return;
short *strc = mFileDNA->getStruct(dna_nr);
//short *firstStrc = strc;
- int elementLen= strc[1];
- strc+=2;
+ int elementLen = strc[1];
+ strc += 2;
short first = mFileDNA->getStruct(0)[0];
char *buf = data;
- for (int i=0; i<elementLen; i++, strc+=2)
+ for (int i = 0; i < elementLen; i++, strc += 2)
{
char *type = mFileDNA->getType(strc[0]);
char *name = mFileDNA->getName(strc[1]);
int size = mFileDNA->getElementSize(strc[0], strc[1]);
- if (strc[0] >= first && name[0]!='*')
+ if (strc[0] >= first && name[0] != '*')
{
int old_nr = mFileDNA->getReverseType(type);
int arrayLen = mFileDNA->getArraySizeNew(strc[1]);
- if (arrayLen==1)
+ if (arrayLen == 1)
{
- swapStruct(old_nr,buf,ignoreEndianFlag);
- } else
+ swapStruct(old_nr, buf, ignoreEndianFlag);
+ }
+ else
{
- char* tmpBuf = buf;
- for (int i=0;i<arrayLen;i++)
+ char *tmpBuf = buf;
+ for (int i = 0; i < arrayLen; i++)
{
- swapStruct(old_nr,tmpBuf,ignoreEndianFlag);
- tmpBuf+=size/arrayLen;
+ swapStruct(old_nr, tmpBuf, ignoreEndianFlag);
+ tmpBuf += size / arrayLen;
}
}
}
@@ -1118,39 +1058,39 @@ void bFile::swapStruct(int dna_nr, char *data,bool ignoreEndianFlag)
//int arrayLenOld = mFileDNA->getArraySize(name);
int arrayLen = mFileDNA->getArraySizeNew(strc[1]);
//assert(arrayLenOld == arrayLen);
- swapData(buf, strc[0], arrayLen,ignoreEndianFlag);
+ swapData(buf, strc[0], arrayLen, ignoreEndianFlag);
}
- buf+=size;
+ buf += size;
}
}
void bFile::resolvePointersMismatch()
{
-// printf("resolvePointersStructMismatch\n");
+ // printf("resolvePointersStructMismatch\n");
int i;
- for (i=0;i< m_pointerFixupArray.size();i++)
+ for (i = 0; i < m_pointerFixupArray.size(); i++)
{
- char* cur = m_pointerFixupArray.at(i);
- void** ptrptr = (void**) cur;
- void* ptr = *ptrptr;
+ char *cur = m_pointerFixupArray.at(i);
+ void **ptrptr = (void **)cur;
+ void *ptr = *ptrptr;
ptr = findLibPointer(ptr);
if (ptr)
{
//printf("Fixup pointer!\n");
*(ptrptr) = ptr;
- } else
+ }
+ else
{
-// printf("pointer not found: %x\n",cur);
+ // printf("pointer not found: %x\n",cur);
}
}
-
- for (i=0; i<m_pointerPtrFixupArray.size(); i++)
+ for (i = 0; i < m_pointerPtrFixupArray.size(); i++)
{
- char* cur= m_pointerPtrFixupArray.at(i);
- void** ptrptr = (void**)cur;
+ char *cur = m_pointerPtrFixupArray.at(i);
+ void **ptrptr = (void **)cur;
bChunkInd *block = m_chunkPtrPtrMap.find(*ptrptr);
if (block)
@@ -1158,7 +1098,6 @@ void bFile::resolvePointersMismatch()
int ptrMem = mMemoryDNA->getPointerSize();
int ptrFile = mFileDNA->getPointerSize();
-
int blockLen = block->len / ptrFile;
void *onptr = findLibPointer(*ptrptr);
@@ -1168,16 +1107,16 @@ void bFile::resolvePointersMismatch()
addDataBlock(newPtr);
memset(newPtr, 0, blockLen * ptrMem);
- void **onarray = (void**)onptr;
- char *oldPtr = (char*)onarray;
+ void **onarray = (void **)onptr;
+ char *oldPtr = (char *)onarray;
int p = 0;
while (blockLen-- > 0)
{
b3PointerUid dp = {{0}};
- safeSwapPtr((char*)dp.m_uniqueIds, oldPtr);
+ safeSwapPtr((char *)dp.m_uniqueIds, oldPtr);
- void **tptr = (void**)(newPtr + p * ptrMem);
+ void **tptr = (void **)(newPtr + p * ptrMem);
*tptr = findLibPointer(dp.m_ptr);
oldPtr += ptrFile;
@@ -1190,70 +1129,63 @@ void bFile::resolvePointersMismatch()
}
}
-
///this loop only works fine if the Blender DNA structure of the file matches the headerfiles
-void bFile::resolvePointersChunk(const bChunkInd& dataChunk, int verboseMode)
+void bFile::resolvePointersChunk(const bChunkInd &dataChunk, int verboseMode)
{
- bParse::bDNA* fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
+ bParse::bDNA *fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
- short int* oldStruct = fileDna->getStruct(dataChunk.dna_nr);
+ short int *oldStruct = fileDna->getStruct(dataChunk.dna_nr);
short oldLen = fileDna->getLength(oldStruct[0]);
//char* structType = fileDna->getType(oldStruct[0]);
- char* cur = (char*)findLibPointer(dataChunk.oldPtr);
- for (int block=0; block<dataChunk.nr; block++)
+ char *cur = (char *)findLibPointer(dataChunk.oldPtr);
+ for (int block = 0; block < dataChunk.nr; block++)
{
- resolvePointersStructRecursive(cur,dataChunk.dna_nr, verboseMode,1);
+ resolvePointersStructRecursive(cur, dataChunk.dna_nr, verboseMode, 1);
cur += oldLen;
}
}
-
-int bFile::resolvePointersStructRecursive(char *strcPtr, int dna_nr, int verboseMode,int recursion)
+int bFile::resolvePointersStructRecursive(char *strcPtr, int dna_nr, int verboseMode, int recursion)
{
+ bParse::bDNA *fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
- bParse::bDNA* fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
+ char *memType;
+ char *memName;
+ short firstStructType = fileDna->getStruct(0)[0];
- char* memType;
- char* memName;
- short firstStructType = fileDna->getStruct(0)[0];
+ char *elemPtr = strcPtr;
-
- char* elemPtr= strcPtr;
-
- short int* oldStruct = fileDna->getStruct(dna_nr);
+ short int *oldStruct = fileDna->getStruct(dna_nr);
int elementLength = oldStruct[1];
- oldStruct+=2;
+ oldStruct += 2;
int totalSize = 0;
- for (int ele=0; ele<elementLength; ele++, oldStruct+=2)
+ for (int ele = 0; ele < elementLength; ele++, oldStruct += 2)
{
-
memType = fileDna->getType(oldStruct[0]);
memName = fileDna->getName(oldStruct[1]);
-
-
int arrayLen = fileDna->getArraySizeNew(oldStruct[1]);
if (memName[0] == '*')
{
if (arrayLen > 1)
{
- void **array= (void**)elemPtr;
- for (int a=0; a<arrayLen; a++)
+ void **array = (void **)elemPtr;
+ for (int a = 0; a < arrayLen; a++)
{
if (verboseMode & FD_VERBOSE_EXPORT_XML)
{
- for (int i=0;i<recursion;i++)
+ for (int i = 0; i < recursion; i++)
{
printf(" ");
}
//skip the *
- printf("<%s type=\"pointer\"> ",&memName[1]);
+ printf("<%s type=\"pointer\"> ", &memName[1]);
printf("%p ", array[a]);
- printf("</%s>\n",&memName[1]);
+ printf("</%s>\n", &memName[1]);
}
array[a] = findLibPointer(array[a]);
@@ -1261,266 +1193,259 @@ int bFile::resolvePointersStructRecursive(char *strcPtr, int dna_nr, int verbose
}
else
{
- void** ptrptr = (void**) elemPtr;
- void* ptr = *ptrptr;
+ void **ptrptr = (void **)elemPtr;
+ void *ptr = *ptrptr;
if (verboseMode & FD_VERBOSE_EXPORT_XML)
{
- for (int i=0;i<recursion;i++)
+ for (int i = 0; i < recursion; i++)
{
printf(" ");
}
- printf("<%s type=\"pointer\"> ",&memName[1]);
+ printf("<%s type=\"pointer\"> ", &memName[1]);
printf("%p ", ptr);
- printf("</%s>\n",&memName[1]);
+ printf("</%s>\n", &memName[1]);
}
ptr = findLibPointer(ptr);
if (ptr)
{
- // printf("Fixup pointer at 0x%x from 0x%x to 0x%x!\n",ptrptr,*ptrptr,ptr);
+ // printf("Fixup pointer at 0x%x from 0x%x to 0x%x!\n",ptrptr,*ptrptr,ptr);
*(ptrptr) = ptr;
if (memName[1] == '*' && ptrptr && *ptrptr)
{
// This will only work if the given **array is continuous
- void **array= (void**)*(ptrptr);
- void *np= array[0];
- int n=0;
+ void **array = (void **)*(ptrptr);
+ void *np = array[0];
+ int n = 0;
while (np)
{
- np= findLibPointer(array[n]);
- if (np) array[n]= np;
+ np = findLibPointer(array[n]);
+ if (np) array[n] = np;
n++;
}
}
- } else
+ }
+ else
{
- // printf("Cannot fixup pointer at 0x%x from 0x%x to 0x%x!\n",ptrptr,*ptrptr,ptr);
+ // printf("Cannot fixup pointer at 0x%x from 0x%x to 0x%x!\n",ptrptr,*ptrptr,ptr);
}
}
- } else
+ }
+ else
{
int revType = fileDna->getReverseType(oldStruct[0]);
- if (oldStruct[0]>=firstStructType) //revType != -1 &&
+ if (oldStruct[0] >= firstStructType) //revType != -1 &&
{
char cleanName[MAX_STRLEN];
- getCleanName(memName,cleanName);
+ getCleanName(memName, cleanName);
int arrayLen = fileDna->getArraySizeNew(oldStruct[1]);
int byteOffset = 0;
if (verboseMode & FD_VERBOSE_EXPORT_XML)
{
- for (int i=0;i<recursion;i++)
+ for (int i = 0; i < recursion; i++)
{
printf(" ");
}
- if (arrayLen>1)
+ if (arrayLen > 1)
{
- printf("<%s type=\"%s\" count=%d>\n",cleanName,memType, arrayLen);
- } else
+ printf("<%s type=\"%s\" count=%d>\n", cleanName, memType, arrayLen);
+ }
+ else
{
- printf("<%s type=\"%s\">\n",cleanName,memType);
+ printf("<%s type=\"%s\">\n", cleanName, memType);
}
}
- for (int i=0;i<arrayLen;i++)
+ for (int i = 0; i < arrayLen; i++)
{
- byteOffset += resolvePointersStructRecursive(elemPtr+byteOffset,revType, verboseMode,recursion+1);
+ byteOffset += resolvePointersStructRecursive(elemPtr + byteOffset, revType, verboseMode, recursion + 1);
}
if (verboseMode & FD_VERBOSE_EXPORT_XML)
{
- for (int i=0;i<recursion;i++)
+ for (int i = 0; i < recursion; i++)
{
printf(" ");
}
- printf("</%s>\n",cleanName);
+ printf("</%s>\n", cleanName);
}
- } else
+ }
+ else
{
//export a simple type
if (verboseMode & FD_VERBOSE_EXPORT_XML)
{
-
- if (arrayLen>MAX_ARRAY_LENGTH)
+ if (arrayLen > MAX_ARRAY_LENGTH)
{
printf("too long\n");
- } else
+ }
+ else
{
//printf("%s %s\n",memType,memName);
- bool isIntegerType = (strcmp(memType,"char")==0) || (strcmp(memType,"int")==0) || (strcmp(memType,"short")==0);
+ bool isIntegerType = (strcmp(memType, "char") == 0) || (strcmp(memType, "int") == 0) || (strcmp(memType, "short") == 0);
if (isIntegerType)
{
- const char* newtype="int";
+ const char *newtype = "int";
int dbarray[MAX_ARRAY_LENGTH];
- int* dbPtr = 0;
- char* tmp = elemPtr;
+ int *dbPtr = 0;
+ char *tmp = elemPtr;
dbPtr = &dbarray[0];
if (dbPtr)
{
char cleanName[MAX_STRLEN];
- getCleanName(memName,cleanName);
+ getCleanName(memName, cleanName);
int i;
- getElement(arrayLen, newtype,memType, tmp, (char*)dbPtr);
- for (i=0;i<recursion;i++)
+ getElement(arrayLen, newtype, memType, tmp, (char *)dbPtr);
+ for (i = 0; i < recursion; i++)
printf(" ");
- if (arrayLen==1)
- printf("<%s type=\"%s\">",cleanName,memType);
+ if (arrayLen == 1)
+ printf("<%s type=\"%s\">", cleanName, memType);
else
- printf("<%s type=\"%s\" count=%d>",cleanName,memType,arrayLen);
- for (i=0;i<arrayLen;i++)
- printf(" %d ",dbPtr[i]);
- printf("</%s>\n",cleanName);
+ printf("<%s type=\"%s\" count=%d>", cleanName, memType, arrayLen);
+ for (i = 0; i < arrayLen; i++)
+ printf(" %d ", dbPtr[i]);
+ printf("</%s>\n", cleanName);
}
- } else
+ }
+ else
{
- const char* newtype="double";
+ const char *newtype = "double";
double dbarray[MAX_ARRAY_LENGTH];
- double* dbPtr = 0;
- char* tmp = elemPtr;
+ double *dbPtr = 0;
+ char *tmp = elemPtr;
dbPtr = &dbarray[0];
if (dbPtr)
{
int i;
- getElement(arrayLen, newtype,memType, tmp, (char*)dbPtr);
- for (i=0;i<recursion;i++)
+ getElement(arrayLen, newtype, memType, tmp, (char *)dbPtr);
+ for (i = 0; i < recursion; i++)
printf(" ");
char cleanName[MAX_STRLEN];
- getCleanName(memName,cleanName);
+ getCleanName(memName, cleanName);
- if (arrayLen==1)
+ if (arrayLen == 1)
{
- printf("<%s type=\"%s\">",memName,memType);
+ printf("<%s type=\"%s\">", memName, memType);
}
else
{
- printf("<%s type=\"%s\" count=%d>",cleanName,memType,arrayLen);
+ printf("<%s type=\"%s\" count=%d>", cleanName, memType, arrayLen);
}
- for (i=0;i<arrayLen;i++)
- printf(" %f ",dbPtr[i]);
- printf("</%s>\n",cleanName);
+ for (i = 0; i < arrayLen; i++)
+ printf(" %f ", dbPtr[i]);
+ printf("</%s>\n", cleanName);
}
}
}
-
}
}
}
int size = fileDna->getElementSize(oldStruct[0], oldStruct[1]);
totalSize += size;
- elemPtr+=size;
-
+ elemPtr += size;
}
return totalSize;
}
-
///Resolve pointers replaces the original pointers in structures, and linked lists by the new in-memory structures
void bFile::resolvePointers(int verboseMode)
{
- bParse::bDNA* fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
+ bParse::bDNA *fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
//char *dataPtr = mFileBuffer+mDataStart;
- if (1) //mFlags & (FD_BITS_VARIES | FD_VERSION_VARIES))
+ if (1) //mFlags & (FD_BITS_VARIES | FD_VERSION_VARIES))
{
resolvePointersMismatch();
}
{
-
if (verboseMode & FD_VERBOSE_EXPORT_XML)
{
printf("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
int numitems = m_chunks.size();
printf("<bullet_physics version=%d itemcount = %d>\n", b3GetVersion(), numitems);
}
- for (int i=0;i<m_chunks.size();i++)
+ for (int i = 0; i < m_chunks.size(); i++)
{
- const bChunkInd& dataChunk = m_chunks.at(i);
+ const bChunkInd &dataChunk = m_chunks.at(i);
if (!mFileDNA || fileDna->flagEqual(dataChunk.dna_nr))
{
//dataChunk.len
- short int* oldStruct = fileDna->getStruct(dataChunk.dna_nr);
- char* oldType = fileDna->getType(oldStruct[0]);
+ short int *oldStruct = fileDna->getStruct(dataChunk.dna_nr);
+ char *oldType = fileDna->getType(oldStruct[0]);
if (verboseMode & FD_VERBOSE_EXPORT_XML)
- printf(" <%s pointer=%p>\n",oldType,dataChunk.oldPtr);
+ printf(" <%s pointer=%p>\n", oldType, dataChunk.oldPtr);
resolvePointersChunk(dataChunk, verboseMode);
if (verboseMode & FD_VERBOSE_EXPORT_XML)
- printf(" </%s>\n",oldType);
- } else
+ printf(" </%s>\n", oldType);
+ }
+ else
{
//printf("skipping mStruct\n");
}
}
- if (verboseMode & FD_VERBOSE_EXPORT_XML)
- {
- printf("</bullet_physics>\n");
- }
+ if (verboseMode & FD_VERBOSE_EXPORT_XML)
+ {
+ printf("</bullet_physics>\n");
+ }
}
-
-
}
-
// ----------------------------------------------------- //
-void* bFile::findLibPointer(void *ptr)
+void *bFile::findLibPointer(void *ptr)
{
-
- bStructHandle** ptrptr = getLibPointers().find(ptr);
+ bStructHandle **ptrptr = getLibPointers().find(ptr);
if (ptrptr)
return *ptrptr;
return 0;
}
-
-void bFile::updateOldPointers()
+void bFile::updateOldPointers()
{
int i;
- for (i=0;i<m_chunks.size();i++)
+ for (i = 0; i < m_chunks.size(); i++)
{
- bChunkInd& dataChunk = m_chunks[i];
+ bChunkInd &dataChunk = m_chunks[i];
dataChunk.oldPtr = findLibPointer(dataChunk.oldPtr);
}
}
-void bFile::dumpChunks(bParse::bDNA* dna)
+void bFile::dumpChunks(bParse::bDNA *dna)
{
int i;
- for (i=0;i<m_chunks.size();i++)
+ for (i = 0; i < m_chunks.size(); i++)
{
- bChunkInd& dataChunk = m_chunks[i];
- char* codeptr = (char*)&dataChunk.code;
- char codestr[5] = {codeptr[0],codeptr[1],codeptr[2],codeptr[3],0};
+ bChunkInd &dataChunk = m_chunks[i];
+ char *codeptr = (char *)&dataChunk.code;
+ char codestr[5] = {codeptr[0], codeptr[1], codeptr[2], codeptr[3], 0};
- short* newStruct = dna->getStruct(dataChunk.dna_nr);
- char* typeName = dna->getType(newStruct[0]);
- printf("%3d: %s ",i,typeName);
+ short *newStruct = dna->getStruct(dataChunk.dna_nr);
+ char *typeName = dna->getType(newStruct[0]);
+ printf("%3d: %s ", i, typeName);
- printf("code=%s ",codestr);
+ printf("code=%s ", codestr);
- printf("ptr=%p ",dataChunk.oldPtr);
- printf("len=%d ",dataChunk.len);
- printf("nr=%d ",dataChunk.nr);
- if (dataChunk.nr!=1)
+ printf("ptr=%p ", dataChunk.oldPtr);
+ printf("len=%d ", dataChunk.len);
+ printf("nr=%d ", dataChunk.nr);
+ if (dataChunk.nr != 1)
{
printf("not 1\n");
}
printf("\n");
-
-
-
-
}
#if 0
@@ -1536,20 +1461,18 @@ void bFile::dumpChunks(bParse::bDNA* dna)
printf("\n");
}
#endif
-
}
-
-void bFile::writeChunks(FILE* fp, bool fixupPointers)
+void bFile::writeChunks(FILE *fp, bool fixupPointers)
{
- bParse::bDNA* fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
+ bParse::bDNA *fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
- for (int i=0;i<m_chunks.size();i++)
+ for (int i = 0; i < m_chunks.size(); i++)
{
- bChunkInd& dataChunk = m_chunks.at(i);
+ bChunkInd &dataChunk = m_chunks.at(i);
// Ouch! need to rebuild the struct
- short *oldStruct,*curStruct;
+ short *oldStruct, *curStruct;
char *oldType, *newType;
int oldLen, curLen, reverseOld;
@@ -1559,8 +1482,7 @@ void bFile::writeChunks(FILE* fp, bool fixupPointers)
///don't try to convert Link block data, just memcpy it. Other data can be converted.
reverseOld = mMemoryDNA->getReverseType(oldType);
-
- if ((reverseOld!=-1))
+ if ((reverseOld != -1))
{
// make sure it's here
//assert(reverseOld!= -1 && "getReverseType() returned -1, struct required!");
@@ -1568,50 +1490,47 @@ void bFile::writeChunks(FILE* fp, bool fixupPointers)
curStruct = mMemoryDNA->getStruct(reverseOld);
newType = mMemoryDNA->getType(curStruct[0]);
// make sure it's the same
- assert((strcmp(oldType, newType)==0) && "internal error, struct mismatch!");
-
+ assert((strcmp(oldType, newType) == 0) && "internal error, struct mismatch!");
curLen = mMemoryDNA->getLength(curStruct[0]);
dataChunk.dna_nr = reverseOld;
- if (strcmp("Link",oldType)!=0)
+ if (strcmp("Link", oldType) != 0)
{
dataChunk.len = curLen * dataChunk.nr;
- } else
+ }
+ else
{
-// printf("keep length of link = %d\n",dataChunk.len);
+ // printf("keep length of link = %d\n",dataChunk.len);
}
//write the structure header
- fwrite(&dataChunk,sizeof(bChunkInd),1,fp);
-
+ fwrite(&dataChunk, sizeof(bChunkInd), 1, fp);
-
- short int* curStruct1;
+ short int *curStruct1;
curStruct1 = mMemoryDNA->getStruct(dataChunk.dna_nr);
assert(curStruct1 == curStruct);
- char* cur = fixupPointers ? (char*)findLibPointer(dataChunk.oldPtr) : (char*)dataChunk.oldPtr;
+ char *cur = fixupPointers ? (char *)findLibPointer(dataChunk.oldPtr) : (char *)dataChunk.oldPtr;
//write the actual contents of the structure(s)
- fwrite(cur,dataChunk.len,1,fp);
- } else
+ fwrite(cur, dataChunk.len, 1, fp);
+ }
+ else
{
printf("serious error, struct mismatch: don't write\n");
}
}
-
}
-
// ----------------------------------------------------- //
-int bFile::getNextBlock(bChunkInd *dataChunk, const char *dataPtr, const int flags)
+int bFile::getNextBlock(bChunkInd *dataChunk, const char *dataPtr, const int flags)
{
bool swap = false;
bool varies = false;
- if (flags &FD_ENDIAN_SWAP)
+ if (flags & FD_ENDIAN_SWAP)
swap = true;
- if (flags &FD_BITS_VARIES)
+ if (flags & FD_BITS_VARIES)
varies = true;
if (VOID_IS_8)
@@ -1621,27 +1540,25 @@ int bFile::getNextBlock(bChunkInd *dataChunk, const char *dataPtr, const int fl
bChunkPtr4 head;
memcpy(&head, dataPtr, sizeof(bChunkPtr4));
-
bChunkPtr8 chunk;
- chunk.code = head.code;
- chunk.len = head.len;
+ chunk.code = head.code;
+ chunk.len = head.len;
chunk.m_uniqueInts[0] = head.m_uniqueInt;
chunk.m_uniqueInts[1] = 0;
- chunk.dna_nr = head.dna_nr;
- chunk.nr = head.nr;
+ chunk.dna_nr = head.dna_nr;
+ chunk.nr = head.nr;
if (swap)
{
- if ((chunk.code & 0xFFFF)==0)
- chunk.code >>=16;
+ if ((chunk.code & 0xFFFF) == 0)
+ chunk.code >>= 16;
B3_SWITCH_INT(chunk.len);
B3_SWITCH_INT(chunk.dna_nr);
B3_SWITCH_INT(chunk.nr);
}
-
memcpy(dataChunk, &chunk, sizeof(bChunkInd));
}
else
@@ -1651,8 +1568,8 @@ int bFile::getNextBlock(bChunkInd *dataChunk, const char *dataPtr, const int fl
if (swap)
{
- if ((c.code & 0xFFFF)==0)
- c.code >>=16;
+ if ((c.code & 0xFFFF) == 0)
+ c.code >>= 16;
B3_SWITCH_INT(c.len);
B3_SWITCH_INT(c.dna_nr);
@@ -1669,31 +1586,30 @@ int bFile::getNextBlock(bChunkInd *dataChunk, const char *dataPtr, const int fl
bChunkPtr8 head;
memcpy(&head, dataPtr, sizeof(bChunkPtr8));
-
bChunkPtr4 chunk;
chunk.code = head.code;
chunk.len = head.len;
- if (head.m_uniqueInts[0]==head.m_uniqueInts[1])
+ if (head.m_uniqueInts[0] == head.m_uniqueInts[1])
{
chunk.m_uniqueInt = head.m_uniqueInts[0];
- } else
+ }
+ else
{
- b3Long64 oldPtr =0;
+ b3Long64 oldPtr = 0;
memcpy(&oldPtr, &head.m_uniqueInts[0], 8);
if (swap)
B3_SWITCH_LONGINT(oldPtr);
chunk.m_uniqueInt = (int)(oldPtr >> 3);
}
-
chunk.dna_nr = head.dna_nr;
chunk.nr = head.nr;
if (swap)
{
- if ((chunk.code & 0xFFFF)==0)
- chunk.code >>=16;
+ if ((chunk.code & 0xFFFF) == 0)
+ chunk.code >>= 16;
B3_SWITCH_INT(chunk.len);
B3_SWITCH_INT(chunk.dna_nr);
@@ -1709,8 +1625,8 @@ int bFile::getNextBlock(bChunkInd *dataChunk, const char *dataPtr, const int fl
if (swap)
{
- if ((c.code & 0xFFFF)==0)
- c.code >>=16;
+ if ((c.code & 0xFFFF) == 0)
+ c.code >>= 16;
B3_SWITCH_INT(c.len);
B3_SWITCH_INT(c.dna_nr);
@@ -1731,9 +1647,7 @@ int bFile::getNextBlock(bChunkInd *dataChunk, const char *dataPtr, const int fl
print (dataChunk->dna_nr);
print (dataChunk->nr);
#endif
- return (dataChunk->len+ChunkUtils::getOffset(flags));
+ return (dataChunk->len + ChunkUtils::getOffset(flags));
}
-
-
//eof
diff --git a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3File.h b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3File.h
index 861056806d..bda229cfbd 100644
--- a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3File.h
+++ b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3File.h
@@ -20,146 +20,139 @@ subject to the following restrictions:
#include "b3Chunk.h"
#include <stdio.h>
-namespace bParse {
-
- // ----------------------------------------------------- //
- enum bFileFlags
- {
- FD_INVALID =0,
- FD_OK =1,
- FD_VOID_IS_8 =2,
- FD_ENDIAN_SWAP =4,
- FD_FILE_64 =8,
- FD_BITS_VARIES =16,
- FD_VERSION_VARIES = 32,
- FD_DOUBLE_PRECISION =64,
- FD_BROKEN_DNA = 128
- };
-
- enum bFileVerboseMode
+namespace bParse
+{
+// ----------------------------------------------------- //
+enum bFileFlags
+{
+ FD_INVALID = 0,
+ FD_OK = 1,
+ FD_VOID_IS_8 = 2,
+ FD_ENDIAN_SWAP = 4,
+ FD_FILE_64 = 8,
+ FD_BITS_VARIES = 16,
+ FD_VERSION_VARIES = 32,
+ FD_DOUBLE_PRECISION = 64,
+ FD_BROKEN_DNA = 128
+};
+
+enum bFileVerboseMode
+{
+ FD_VERBOSE_EXPORT_XML = 1,
+ FD_VERBOSE_DUMP_DNA_TYPE_DEFINITIONS = 2,
+ FD_VERBOSE_DUMP_CHUNKS = 4,
+ FD_VERBOSE_DUMP_FILE_INFO = 8,
+};
+// ----------------------------------------------------- //
+class bFile
+{
+protected:
+ char m_headerString[7];
+
+ bool mOwnsBuffer;
+ char *mFileBuffer;
+ int mFileLen;
+ int mVersion;
+
+ bPtrMap mLibPointers;
+
+ int mDataStart;
+ bDNA *mFileDNA;
+ bDNA *mMemoryDNA;
+
+ b3AlignedObjectArray<char *> m_pointerFixupArray;
+ b3AlignedObjectArray<char *> m_pointerPtrFixupArray;
+
+ b3AlignedObjectArray<bChunkInd> m_chunks;
+ b3HashMap<b3HashPtr, bChunkInd> m_chunkPtrPtrMap;
+
+ //
+
+ bPtrMap mDataPointers;
+
+ int mFlags;
+
+ // ////////////////////////////////////////////////////////////////////////////
+
+ // buffer offset util
+ int getNextBlock(bChunkInd *dataChunk, const char *dataPtr, const int flags);
+ void safeSwapPtr(char *dst, const char *src);
+
+ virtual void parseHeader();
+
+ virtual void parseData() = 0;
+
+ void resolvePointersMismatch();
+ void resolvePointersChunk(const bChunkInd &dataChunk, int verboseMode);
+
+ int resolvePointersStructRecursive(char *strcPtr, int old_dna, int verboseMode, int recursion);
+ //void swapPtr(char *dst, char *src);
+
+ void parseStruct(char *strcPtr, char *dtPtr, int old_dna, int new_dna, bool fixupPointers);
+ void getMatchingFileDNA(short *old, const char *lookupName, const char *lookupType, char *strcData, char *data, bool fixupPointers);
+ char *getFileElement(short *firstStruct, char *lookupName, char *lookupType, char *data, short **foundPos);
+
+ void swap(char *head, class bChunkInd &ch, bool ignoreEndianFlag);
+ void swapData(char *data, short type, int arraySize, bool ignoreEndianFlag);
+ void swapStruct(int dna_nr, char *data, bool ignoreEndianFlag);
+ void swapLen(char *dataPtr);
+ void swapDNA(char *ptr);
+
+ char *readStruct(char *head, class bChunkInd &chunk);
+ char *getAsString(int code);
+
+ void parseInternal(int verboseMode, char *memDna, int memDnaLength);
+
+public:
+ bFile(const char *filename, const char headerString[7]);
+
+ //todo: make memoryBuffer const char
+ //bFile( const char *memoryBuffer, int len);
+ bFile(char *memoryBuffer, int len, const char headerString[7]);
+ virtual ~bFile();
+
+ bDNA *getFileDNA()
{
- FD_VERBOSE_EXPORT_XML = 1,
- FD_VERBOSE_DUMP_DNA_TYPE_DEFINITIONS = 2,
- FD_VERBOSE_DUMP_CHUNKS = 4,
- FD_VERBOSE_DUMP_FILE_INFO=8,
- };
- // ----------------------------------------------------- //
- class bFile
- {
- protected:
-
- char m_headerString[7];
-
- bool mOwnsBuffer;
- char* mFileBuffer;
- int mFileLen;
- int mVersion;
-
-
- bPtrMap mLibPointers;
-
- int mDataStart;
- bDNA* mFileDNA;
- bDNA* mMemoryDNA;
-
- b3AlignedObjectArray<char*> m_pointerFixupArray;
- b3AlignedObjectArray<char*> m_pointerPtrFixupArray;
-
- b3AlignedObjectArray<bChunkInd> m_chunks;
- b3HashMap<b3HashPtr, bChunkInd> m_chunkPtrPtrMap;
-
- //
-
- bPtrMap mDataPointers;
-
-
- int mFlags;
-
- // ////////////////////////////////////////////////////////////////////////////
-
- // buffer offset util
- int getNextBlock(bChunkInd *dataChunk, const char *dataPtr, const int flags);
- void safeSwapPtr(char *dst, const char *src);
-
- virtual void parseHeader();
-
- virtual void parseData() = 0;
-
- void resolvePointersMismatch();
- void resolvePointersChunk(const bChunkInd& dataChunk, int verboseMode);
+ return mFileDNA;
+ }
- int resolvePointersStructRecursive(char *strcPtr, int old_dna, int verboseMode, int recursion);
- //void swapPtr(char *dst, char *src);
+ virtual void addDataBlock(char *dataBlock) = 0;
- void parseStruct(char *strcPtr, char *dtPtr, int old_dna, int new_dna, bool fixupPointers);
- void getMatchingFileDNA(short* old, const char* lookupName, const char* lookupType, char *strcData, char *data, bool fixupPointers);
- char* getFileElement(short *firstStruct, char *lookupName, char *lookupType, char *data, short **foundPos);
-
-
- void swap(char *head, class bChunkInd& ch, bool ignoreEndianFlag);
- void swapData(char *data, short type, int arraySize, bool ignoreEndianFlag);
- void swapStruct(int dna_nr, char *data, bool ignoreEndianFlag);
- void swapLen(char *dataPtr);
- void swapDNA(char* ptr);
-
-
- char* readStruct(char *head, class bChunkInd& chunk);
- char *getAsString(int code);
-
- void parseInternal(int verboseMode, char* memDna,int memDnaLength);
-
- public:
- bFile(const char *filename, const char headerString[7]);
-
- //todo: make memoryBuffer const char
- //bFile( const char *memoryBuffer, int len);
- bFile( char *memoryBuffer, int len, const char headerString[7]);
- virtual ~bFile();
-
- bDNA* getFileDNA()
- {
- return mFileDNA;
- }
-
- virtual void addDataBlock(char* dataBlock) = 0;
-
- int getFlags() const
- {
- return mFlags;
- }
-
- bPtrMap& getLibPointers()
- {
- return mLibPointers;
- }
-
- void* findLibPointer(void *ptr);
+ int getFlags() const
+ {
+ return mFlags;
+ }
- bool ok();
+ bPtrMap &getLibPointers()
+ {
+ return mLibPointers;
+ }
- virtual void parse(int verboseMode) = 0;
+ void *findLibPointer(void *ptr);
- virtual int write(const char* fileName, bool fixupPointers=false) = 0;
+ bool ok();
- virtual void writeChunks(FILE* fp, bool fixupPointers );
+ virtual void parse(int verboseMode) = 0;
- virtual void writeDNA(FILE* fp) = 0;
+ virtual int write(const char *fileName, bool fixupPointers = false) = 0;
- void updateOldPointers();
- void resolvePointers(int verboseMode);
+ virtual void writeChunks(FILE *fp, bool fixupPointers);
- void dumpChunks(bDNA* dna);
-
- int getVersion() const
- {
- return mVersion;
- }
- //pre-swap the endianness, so that data loaded on a target with different endianness doesn't need to be swapped
- void preSwap();
- void writeFile(const char* fileName);
+ virtual void writeDNA(FILE *fp) = 0;
- };
-}
+ void updateOldPointers();
+ void resolvePointers(int verboseMode);
+ void dumpChunks(bDNA *dna);
-#endif//__BFILE_H__
+ int getVersion() const
+ {
+ return mVersion;
+ }
+ //pre-swap the endianness, so that data loaded on a target with different endianness doesn't need to be swapped
+ void preSwap();
+ void writeFile(const char *fileName);
+};
+} // namespace bParse
+
+#endif //__BFILE_H__
diff --git a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Serializer.cpp b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Serializer.cpp
index c6a2a832ad..ea4a8e2007 100644
--- a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Serializer.cpp
+++ b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Serializer.cpp
@@ -1,908 +1,18062 @@
-char b3s_bulletDNAstr[]= {
-char(83),char(68),char(78),char(65),char(78),char(65),char(77),char(69),char(63),char(1),char(0),char(0),char(109),char(95),char(115),char(105),char(122),char(101),char(0),char(109),
-char(95),char(99),char(97),char(112),char(97),char(99),char(105),char(116),char(121),char(0),char(42),char(109),char(95),char(100),char(97),char(116),char(97),char(0),char(109),char(95),
-char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(115),char(0),char(109),char(95),char(99),char(111),
-char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(110),
-char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(115),char(0),char(42),char(102),char(105),char(114),char(115),char(116),char(0),char(42),char(108),char(97),char(115),
-char(116),char(0),char(109),char(95),char(102),char(108),char(111),char(97),char(116),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(101),char(108),char(91),char(51),
-char(93),char(0),char(109),char(95),char(98),char(97),char(115),char(105),char(115),char(0),char(109),char(95),char(111),char(114),char(105),char(103),char(105),char(110),char(0),char(109),
-char(95),char(114),char(111),char(111),char(116),char(78),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(115),char(117),char(98),
-char(116),char(114),char(101),char(101),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),
-char(65),char(97),char(98),char(98),char(77),char(105),char(110),char(91),char(51),char(93),char(0),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),
-char(101),char(100),char(65),char(97),char(98),char(98),char(77),char(97),char(120),char(91),char(51),char(93),char(0),char(109),char(95),char(97),char(97),char(98),char(98),char(77),
-char(105),char(110),char(79),char(114),char(103),char(0),char(109),char(95),char(97),char(97),char(98),char(98),char(77),char(97),char(120),char(79),char(114),char(103),char(0),char(109),
-char(95),char(101),char(115),char(99),char(97),char(112),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(115),char(117),char(98),char(80),char(97),
-char(114),char(116),char(0),char(109),char(95),char(116),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),
-char(95),char(112),char(97),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(101),char(115),char(99),char(97),char(112),char(101),char(73),char(110),char(100),char(101),
-char(120),char(79),char(114),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(98),
-char(118),char(104),char(65),char(97),char(98),char(98),char(77),char(105),char(110),char(0),char(109),char(95),char(98),char(118),char(104),char(65),char(97),char(98),char(98),char(77),
-char(97),char(120),char(0),char(109),char(95),char(98),char(118),char(104),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(97),char(116),char(105),char(111),char(110),
-char(0),char(109),char(95),char(99),char(117),char(114),char(78),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(117),char(115),
-char(101),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(97),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(110),char(117),char(109),char(67),
-char(111),char(110),char(116),char(105),char(103),char(117),char(111),char(117),char(115),char(76),char(101),char(97),char(102),char(78),char(111),char(100),char(101),char(115),char(0),char(109),
-char(95),char(110),char(117),char(109),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(67),char(111),char(110),char(116),char(105),char(103),char(117),
-char(111),char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(0),char(42),char(109),char(95),char(99),char(111),char(110),char(116),char(105),char(103),char(117),char(111),
-char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),
-char(122),char(101),char(100),char(67),char(111),char(110),char(116),char(105),char(103),char(117),char(111),char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(80),char(116),
-char(114),char(0),char(42),char(109),char(95),char(115),char(117),char(98),char(84),char(114),char(101),char(101),char(73),char(110),char(102),char(111),char(80),char(116),char(114),char(0),
-char(109),char(95),char(116),char(114),char(97),char(118),char(101),char(114),char(115),char(97),char(108),char(77),char(111),char(100),char(101),char(0),char(109),char(95),char(110),char(117),
-char(109),char(83),char(117),char(98),char(116),char(114),char(101),char(101),char(72),char(101),char(97),char(100),char(101),char(114),char(115),char(0),char(42),char(109),char(95),char(110),
-char(97),char(109),char(101),char(0),char(109),char(95),char(115),char(104),char(97),char(112),char(101),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(112),char(97),
-char(100),char(100),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),
-char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(83),char(99),char(97),
-char(108),char(105),char(110),char(103),char(0),char(109),char(95),char(112),char(108),char(97),char(110),char(101),char(78),char(111),char(114),char(109),char(97),char(108),char(0),char(109),
-char(95),char(112),char(108),char(97),char(110),char(101),char(67),char(111),char(110),char(115),char(116),char(97),char(110),char(116),char(0),char(109),char(95),char(105),char(109),char(112),
-char(108),char(105),char(99),char(105),char(116),char(83),char(104),char(97),char(112),char(101),char(68),char(105),char(109),char(101),char(110),char(115),char(105),char(111),char(110),char(115),
-char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(77),char(97),char(114),char(103),char(105),char(110),char(0),char(109),
-char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(0),char(109),char(95),char(112),char(111),char(115),char(0),char(109),char(95),char(114),char(97),char(100),
-char(105),char(117),char(115),char(0),char(109),char(95),char(99),char(111),char(110),char(118),char(101),char(120),char(73),char(110),char(116),char(101),char(114),char(110),char(97),char(108),
-char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(42),char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(80),char(111),
-char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(114),char(114),char(97),char(121),char(80),char(116),char(114),char(0),char(109),char(95),char(108),char(111),char(99),
-char(97),char(108),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(114),char(114),char(97),char(121),char(83),char(105),char(122),char(101),char(0),
-char(109),char(95),char(118),char(97),char(108),char(117),char(101),char(0),char(109),char(95),char(112),char(97),char(100),char(91),char(50),char(93),char(0),char(109),char(95),char(118),
-char(97),char(108),char(117),char(101),char(115),char(91),char(51),char(93),char(0),char(109),char(95),char(112),char(97),char(100),char(0),char(42),char(109),char(95),char(118),char(101),
-char(114),char(116),char(105),char(99),char(101),char(115),char(51),char(102),char(0),char(42),char(109),char(95),char(118),char(101),char(114),char(116),char(105),char(99),char(101),char(115),
-char(51),char(100),char(0),char(42),char(109),char(95),char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(51),char(50),char(0),char(42),char(109),char(95),char(51),
-char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(49),char(54),char(0),char(42),char(109),char(95),char(51),char(105),char(110),char(100),char(105),char(99),char(101),
-char(115),char(56),char(0),char(42),char(109),char(95),char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(49),char(54),char(0),char(109),char(95),char(110),char(117),
-char(109),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(86),char(101),char(114),char(116),
-char(105),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(109),char(101),char(115),char(104),char(80),char(97),char(114),char(116),char(115),char(80),char(116),char(114),
-char(0),char(109),char(95),char(115),char(99),char(97),char(108),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(101),char(115),char(104),
-char(80),char(97),char(114),char(116),char(115),char(0),char(109),char(95),char(109),char(101),char(115),char(104),char(73),char(110),char(116),char(101),char(114),char(102),char(97),char(99),
-char(101),char(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(70),char(108),char(111),char(97),char(116),char(66),
-char(118),char(104),char(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(68),char(111),char(117),char(98),char(108),
-char(101),char(66),char(118),char(104),char(0),char(42),char(109),char(95),char(116),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(102),char(111),
-char(77),char(97),char(112),char(0),char(109),char(95),char(112),char(97),char(100),char(51),char(91),char(52),char(93),char(0),char(109),char(95),char(116),char(114),char(105),char(109),
-char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(116),char(114),char(97),char(110),char(115),
-char(102),char(111),char(114),char(109),char(0),char(42),char(109),char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),char(97),char(112),char(101),char(0),char(109),
-char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),char(97),char(112),char(101),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(99),char(104),
-char(105),char(108),char(100),char(77),char(97),char(114),char(103),char(105),char(110),char(0),char(42),char(109),char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),
-char(97),char(112),char(101),char(80),char(116),char(114),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(104),char(105),char(108),char(100),char(83),char(104),char(97),
-char(112),char(101),char(115),char(0),char(109),char(95),char(117),char(112),char(65),char(120),char(105),char(115),char(0),char(109),char(95),char(102),char(108),char(97),char(103),char(115),
-char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(86),char(48),char(86),char(49),char(65),char(110),char(103),char(108),char(101),char(0),char(109),char(95),char(101),
-char(100),char(103),char(101),char(86),char(49),char(86),char(50),char(65),char(110),char(103),char(108),char(101),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(86),
-char(50),char(86),char(48),char(65),char(110),char(103),char(108),char(101),char(0),char(42),char(109),char(95),char(104),char(97),char(115),char(104),char(84),char(97),char(98),char(108),
-char(101),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(110),char(101),char(120),char(116),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(118),
-char(97),char(108),char(117),char(101),char(65),char(114),char(114),char(97),char(121),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(107),char(101),char(121),char(65),
-char(114),char(114),char(97),char(121),char(80),char(116),char(114),char(0),char(109),char(95),char(99),char(111),char(110),char(118),char(101),char(120),char(69),char(112),char(115),char(105),
-char(108),char(111),char(110),char(0),char(109),char(95),char(112),char(108),char(97),char(110),char(97),char(114),char(69),char(112),char(115),char(105),char(108),char(111),char(110),char(0),
-char(109),char(95),char(101),char(113),char(117),char(97),char(108),char(86),char(101),char(114),char(116),char(101),char(120),char(84),char(104),char(114),char(101),char(115),char(104),char(111),
-char(108),char(100),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(68),char(105),char(115),char(116),char(97),char(110),char(99),char(101),char(84),char(104),char(114),
-char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(122),char(101),char(114),char(111),char(65),char(114),char(101),char(97),char(84),char(104),char(114),
-char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(110),char(101),char(120),char(116),char(83),char(105),char(122),char(101),char(0),char(109),char(95),
-char(104),char(97),char(115),char(104),char(84),char(97),char(98),char(108),char(101),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(110),char(117),char(109),char(86),
-char(97),char(108),char(117),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(75),char(101),char(121),char(115),char(0),char(109),char(95),char(103),char(105),
-char(109),char(112),char(97),char(99),char(116),char(83),char(117),char(98),char(84),char(121),char(112),char(101),char(0),char(42),char(109),char(95),char(117),char(110),char(115),char(99),
-char(97),char(108),char(101),char(100),char(80),char(111),char(105),char(110),char(116),char(115),char(70),char(108),char(111),char(97),char(116),char(80),char(116),char(114),char(0),char(42),
-char(109),char(95),char(117),char(110),char(115),char(99),char(97),char(108),char(101),char(100),char(80),char(111),char(105),char(110),char(116),char(115),char(68),char(111),char(117),char(98),
-char(108),char(101),char(80),char(116),char(114),char(0),char(109),char(95),char(110),char(117),char(109),char(85),char(110),char(115),char(99),char(97),char(108),char(101),char(100),char(80),
-char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(51),char(91),char(52),char(93),char(0),
-char(42),char(109),char(95),char(98),char(114),char(111),char(97),char(100),char(112),char(104),char(97),char(115),char(101),char(72),char(97),char(110),char(100),char(108),char(101),char(0),
-char(42),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(0),char(42),char(109),
-char(95),char(114),char(111),char(111),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(0),
-char(109),char(95),char(119),char(111),char(114),char(108),char(100),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(105),
-char(110),char(116),char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),char(111),char(110),char(87),char(111),char(114),char(108),char(100),char(84),char(114),char(97),
-char(110),char(115),char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),
-char(111),char(110),char(76),char(105),char(110),char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(105),
-char(110),char(116),char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),char(111),char(110),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(86),
-char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(105),char(115),char(111),char(116),char(114),char(111),char(112),char(105),
-char(99),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(99),char(116),char(80),
-char(114),char(111),char(99),char(101),char(115),char(115),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),
-char(95),char(100),char(101),char(97),char(99),char(116),char(105),char(118),char(97),char(116),char(105),char(111),char(110),char(84),char(105),char(109),char(101),char(0),char(109),char(95),
-char(102),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(114),char(111),char(108),char(108),char(105),char(110),char(103),char(70),char(114),
-char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(105),char(116),char(117),char(116),char(105),char(111),char(110),
-char(0),char(109),char(95),char(104),char(105),char(116),char(70),char(114),char(97),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(99),char(100),
-char(83),char(119),char(101),char(112),char(116),char(83),char(112),char(104),char(101),char(114),char(101),char(82),char(97),char(100),char(105),char(117),char(115),char(0),char(109),char(95),
-char(99),char(99),char(100),char(77),char(111),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),
-char(95),char(104),char(97),char(115),char(65),char(110),char(105),char(115),char(111),char(116),char(114),char(111),char(112),char(105),char(99),char(70),char(114),char(105),char(99),char(116),
-char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(70),char(108),char(97),char(103),char(115),
-char(0),char(109),char(95),char(105),char(115),char(108),char(97),char(110),char(100),char(84),char(97),char(103),char(49),char(0),char(109),char(95),char(99),char(111),char(109),char(112),
-char(97),char(110),char(105),char(111),char(110),char(73),char(100),char(0),char(109),char(95),char(97),char(99),char(116),char(105),char(118),char(97),char(116),char(105),char(111),char(110),
-char(83),char(116),char(97),char(116),char(101),char(49),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(110),char(97),char(108),char(84),char(121),char(112),
-char(101),char(0),char(109),char(95),char(99),char(104),char(101),char(99),char(107),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(87),char(105),char(116),char(104),
-char(0),char(109),char(95),char(115),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(0),char(109),char(95),char(103),char(114),char(97),char(118),
-char(105),char(116),char(121),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),
-char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(105),char(110),char(118),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(84),char(101),
-char(110),char(115),char(111),char(114),char(87),char(111),char(114),char(108),char(100),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(86),char(101),
-char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),char(111),
-char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(70),char(97),char(99),char(116),char(111),char(114),
-char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(103),char(114),
-char(97),char(118),char(105),char(116),char(121),char(95),char(97),char(99),char(99),char(101),char(108),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(0),char(109),
-char(95),char(105),char(110),char(118),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(76),char(111),char(99),char(97),char(108),char(0),char(109),char(95),char(116),
-char(111),char(116),char(97),char(108),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(116),char(111),char(116),char(97),char(108),char(84),char(111),char(114),
-char(113),char(117),char(101),char(0),char(109),char(95),char(105),char(110),char(118),char(101),char(114),char(115),char(101),char(77),char(97),char(115),char(115),char(0),char(109),char(95),
-char(108),char(105),char(110),char(101),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(97),char(110),char(103),char(117),
-char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),
-char(110),char(97),char(108),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(97),
-char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(76),char(105),char(110),char(101),char(97),char(114),char(68),char(97),char(109),char(112),char(105),
-char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(83),char(113),char(114),char(0),char(109),char(95),char(97),char(100),char(100),
-char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),
-char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(83),char(113),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105),
-char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),
-char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(108),char(101),char(101),char(112),
-char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),
-char(97),char(114),char(83),char(108),char(101),char(101),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),
-char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),
-char(109),char(95),char(110),char(117),char(109),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(82),char(111),char(119),char(115),char(0),
-char(110),char(117),char(98),char(0),char(42),char(109),char(95),char(114),char(98),char(65),char(0),char(42),char(109),char(95),char(114),char(98),char(66),char(0),char(109),char(95),
-char(111),char(98),char(106),char(101),char(99),char(116),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110),
-char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),
-char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(73),char(100),char(0),char(109),char(95),char(110),char(101),char(101),char(100),char(115),char(70),char(101),
-char(101),char(100),char(98),char(97),char(99),char(107),char(0),char(109),char(95),char(97),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),
-char(108),char(115),char(101),char(0),char(109),char(95),char(100),char(98),char(103),char(68),char(114),char(97),char(119),char(83),char(105),char(122),char(101),char(0),char(109),char(95),
-char(100),char(105),char(115),char(97),char(98),char(108),char(101),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(115),char(66),char(101),char(116),
-char(119),char(101),char(101),char(110),char(76),char(105),char(110),char(107),char(101),char(100),char(66),char(111),char(100),char(105),char(101),char(115),char(0),char(109),char(95),char(111),
-char(118),char(101),char(114),char(114),char(105),char(100),char(101),char(78),char(117),char(109),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(116),char(101),char(114),
-char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(98),char(114),char(101),char(97),char(107),char(105),char(110),char(103),char(73),char(109),char(112),
-char(117),char(108),char(115),char(101),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(105),char(115),char(69),char(110),
-char(97),char(98),char(108),char(101),char(100),char(0),char(109),char(95),char(116),char(121),char(112),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),
-char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(112),char(105),char(118),char(111),char(116),char(73),char(110),char(65),char(0),char(109),char(95),
-char(112),char(105),char(118),char(111),char(116),char(73),char(110),char(66),char(0),char(109),char(95),char(114),char(98),char(65),char(70),char(114),char(97),char(109),char(101),char(0),
-char(109),char(95),char(114),char(98),char(66),char(70),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(117),char(115),char(101),char(82),char(101),char(102),char(101),
-char(114),char(101),char(110),char(99),char(101),char(70),char(114),char(97),char(109),char(101),char(65),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),
-char(114),char(79),char(110),char(108),char(121),char(0),char(109),char(95),char(101),char(110),char(97),char(98),char(108),char(101),char(65),char(110),char(103),char(117),char(108),char(97),
-char(114),char(77),char(111),char(116),char(111),char(114),char(0),char(109),char(95),char(109),char(111),char(116),char(111),char(114),char(84),char(97),char(114),char(103),char(101),char(116),
-char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(109),char(97),char(120),char(77),char(111),char(116),char(111),char(114),char(73),
-char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(108),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),
-char(109),char(95),char(117),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(108),char(105),char(109),char(105),char(116),
-char(83),char(111),char(102),char(116),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(98),char(105),char(97),char(115),char(70),char(97),char(99),char(116),char(111),
-char(114),char(0),char(109),char(95),char(114),char(101),char(108),char(97),char(120),char(97),char(116),char(105),char(111),char(110),char(70),char(97),char(99),char(116),char(111),char(114),
-char(0),char(109),char(95),char(115),char(119),char(105),char(110),char(103),char(83),char(112),char(97),char(110),char(49),char(0),char(109),char(95),char(115),char(119),char(105),char(110),
-char(103),char(83),char(112),char(97),char(110),char(50),char(0),char(109),char(95),char(116),char(119),char(105),char(115),char(116),char(83),char(112),char(97),char(110),char(0),char(109),
-char(95),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(85),char(112),char(112),
-char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(76),char(111),char(119),char(101),
-char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(85),char(112),char(112),char(101),
-char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(76),char(111),char(119),char(101),
-char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(117),char(115),char(101),char(76),char(105),char(110),char(101),char(97),char(114),char(82),char(101),
-char(102),char(101),char(114),char(101),char(110),char(99),char(101),char(70),char(114),char(97),char(109),char(101),char(65),char(0),char(109),char(95),char(117),char(115),char(101),char(79),
-char(102),char(102),char(115),char(101),char(116),char(70),char(111),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(114),
-char(97),char(109),char(101),char(0),char(109),char(95),char(54),char(100),char(111),char(102),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(115),char(112),char(114),
-char(105),char(110),char(103),char(69),char(110),char(97),char(98),char(108),char(101),char(100),char(91),char(54),char(93),char(0),char(109),char(95),char(101),char(113),char(117),char(105),
-char(108),char(105),char(98),char(114),char(105),char(117),char(109),char(80),char(111),char(105),char(110),char(116),char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),
-char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(91),char(54),char(93),char(0),char(109),char(95),char(115),
-char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(91),char(54),char(93),char(0),char(109),char(95),char(116),char(97),
-char(117),char(0),char(109),char(95),char(116),char(105),char(109),char(101),char(83),char(116),char(101),char(112),char(0),char(109),char(95),char(109),char(97),char(120),char(69),char(114),
-char(114),char(111),char(114),char(82),char(101),char(100),char(117),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(115),char(111),char(114),char(0),char(109),
-char(95),char(101),char(114),char(112),char(0),char(109),char(95),char(101),char(114),char(112),char(50),char(0),char(109),char(95),char(103),char(108),char(111),char(98),char(97),char(108),
-char(67),char(102),char(109),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(80),char(101),
-char(110),char(101),char(116),char(114),char(97),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),
-char(95),char(115),char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(84),char(117),char(114),char(110),char(69),char(114),char(112),
-char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(108),char(111),char(112),char(0),char(109),char(95),char(119),char(97),char(114),char(109),
-char(115),char(116),char(97),char(114),char(116),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(109),char(97),char(120),
-char(71),char(121),char(114),char(111),char(115),char(99),char(111),char(112),char(105),char(99),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(115),char(105),
-char(110),char(103),char(108),char(101),char(65),char(120),char(105),char(115),char(82),char(111),char(108),char(108),char(105),char(110),char(103),char(70),char(114),char(105),char(99),char(116),
-char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(110),char(117),char(109),char(73),char(116),
-char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(115),char(111),char(108),char(118),char(101),char(114),char(77),char(111),char(100),
-char(101),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(105),char(110),char(103),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(82),char(101),
-char(115),char(116),char(105),char(116),char(117),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),
-char(95),char(109),char(105),char(110),char(105),char(109),char(117),char(109),char(83),char(111),char(108),char(118),char(101),char(114),char(66),char(97),char(116),char(99),char(104),char(83),
-char(105),char(122),char(101),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),
-char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(97),
-char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(118),char(111),
-char(108),char(117),char(109),char(101),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(42),char(109),char(95),char(109),char(97),char(116),
-char(101),char(114),char(105),char(97),char(108),char(0),char(109),char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(112),
-char(114),char(101),char(118),char(105),char(111),char(117),char(115),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(118),char(101),
-char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(99),char(99),char(117),char(109),char(117),char(108),char(97),char(116),char(101),char(100),
-char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(110),char(111),char(114),char(109),char(97),char(108),char(0),char(109),char(95),char(97),char(114),char(101),
-char(97),char(0),char(109),char(95),char(97),char(116),char(116),char(97),char(99),char(104),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),
-char(105),char(99),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(76),char(101),char(110),char(103),char(116),char(104),
-char(0),char(109),char(95),char(98),char(98),char(101),char(110),char(100),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),
-char(100),char(105),char(99),char(101),char(115),char(91),char(51),char(93),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(65),char(114),char(101),char(97),char(0),
-char(109),char(95),char(99),char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),
-char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(86),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),
-char(99),char(49),char(0),char(109),char(95),char(99),char(50),char(0),char(109),char(95),char(99),char(48),char(0),char(109),char(95),char(108),char(111),char(99),char(97),char(108),
-char(70),char(114),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(114),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(0),char(109),
-char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(97),char(101),char(114),char(111),char(77),char(111),char(100),
-char(101),char(108),char(0),char(109),char(95),char(98),char(97),char(117),char(109),char(103),char(97),char(114),char(116),char(101),char(0),char(109),char(95),char(100),char(114),char(97),
-char(103),char(0),char(109),char(95),char(108),char(105),char(102),char(116),char(0),char(109),char(95),char(112),char(114),char(101),char(115),char(115),char(117),char(114),char(101),char(0),
-char(109),char(95),char(118),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(100),char(121),char(110),char(97),char(109),char(105),char(99),char(70),char(114),
-char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(112),char(111),char(115),char(101),char(77),char(97),char(116),char(99),char(104),char(0),char(109),
-char(95),char(114),char(105),char(103),char(105),char(100),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),
-char(115),char(0),char(109),char(95),char(107),char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(72),char(97),
-char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),
-char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),char(99),char(104),char(111),char(114),char(72),char(97),char(114),
-char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(67),char(108),char(117),
-char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(75),
-char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),
-char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(83),char(111),char(102),char(116),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(72),
-char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(67),
-char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),
-char(95),char(115),char(111),char(102),char(116),char(75),char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),
-char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(83),char(111),
-char(102),char(116),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105),
-char(116),char(0),char(109),char(95),char(109),char(97),char(120),char(86),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(116),char(105),char(109),char(101),
-char(83),char(99),char(97),char(108),char(101),char(0),char(109),char(95),char(118),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(73),char(116),char(101),char(114),
-char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(73),char(116),char(101),
-char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(100),char(114),char(105),char(102),char(116),char(73),char(116),char(101),char(114),char(97),
-char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(116),char(101),char(114),char(97),
-char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(114),char(111),char(116),char(0),char(109),char(95),char(115),char(99),char(97),char(108),char(101),char(0),
-char(109),char(95),char(97),char(113),char(113),char(0),char(109),char(95),char(99),char(111),char(109),char(0),char(42),char(109),char(95),char(112),char(111),char(115),char(105),char(116),
-char(105),char(111),char(110),char(115),char(0),char(42),char(109),char(95),char(119),char(101),char(105),char(103),char(104),char(116),char(115),char(0),char(109),char(95),char(110),char(117),
-char(109),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(87),char(101),char(105),char(103),
-char(116),char(115),char(0),char(109),char(95),char(98),char(118),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(98),char(102),char(114),char(97),char(109),
-char(101),char(0),char(109),char(95),char(102),char(114),char(97),char(109),char(101),char(120),char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(108),char(111),char(99),
-char(105),char(105),char(0),char(109),char(95),char(105),char(110),char(118),char(119),char(105),char(0),char(109),char(95),char(118),char(105),char(109),char(112),char(117),char(108),char(115),
-char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(100),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(91),char(50),char(93),
-char(0),char(109),char(95),char(108),char(118),char(0),char(109),char(95),char(97),char(118),char(0),char(42),char(109),char(95),char(102),char(114),char(97),char(109),char(101),char(114),
-char(101),char(102),char(115),char(0),char(42),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(0),char(42),
-char(109),char(95),char(109),char(97),char(115),char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(70),char(114),char(97),char(109),char(101),char(82),
-char(101),char(102),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(78),char(111),char(100),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),
-char(77),char(97),char(115),char(115),char(101),char(115),char(0),char(109),char(95),char(105),char(100),char(109),char(97),char(115),char(115),char(0),char(109),char(95),char(105),char(109),
-char(97),char(115),char(115),char(0),char(109),char(95),char(110),char(118),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(0),char(109),char(95),char(110),
-char(100),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(100),char(97),char(109),char(112),char(105),char(110),char(103),
-char(0),char(109),char(95),char(108),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(97),char(100),char(97),char(109),char(112),char(105),
-char(110),char(103),char(0),char(109),char(95),char(109),char(97),char(116),char(99),char(104),char(105),char(110),char(103),char(0),char(109),char(95),char(109),char(97),char(120),char(83),
-char(101),char(108),char(102),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),
-char(109),char(95),char(115),char(101),char(108),char(102),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(73),char(109),char(112),char(117),char(108),
-char(115),char(101),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(105),char(110),char(115),char(65),
-char(110),char(99),char(104),char(111),char(114),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(100),char(101),char(0),char(109),char(95),char(99),char(108),
-char(117),char(115),char(116),char(101),char(114),char(73),char(110),char(100),char(101),char(120),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(65),char(0),
-char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(66),char(0),char(109),char(95),char(114),char(101),char(102),char(115),char(91),char(50),char(93),char(0),char(109),
-char(95),char(99),char(102),char(109),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(100),char(101),char(108),char(101),char(116),
-char(101),char(0),char(109),char(95),char(114),char(101),char(108),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(91),char(50),char(93),char(0),char(109),
-char(95),char(98),char(111),char(100),char(121),char(65),char(116),char(121),char(112),char(101),char(0),char(109),char(95),char(98),char(111),char(100),char(121),char(66),char(116),char(121),
-char(112),char(101),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(84),char(121),char(112),char(101),char(0),char(42),char(109),char(95),char(112),char(111),
-char(115),char(101),char(0),char(42),char(42),char(109),char(95),char(109),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(115),char(0),char(42),char(109),char(95),
-char(110),char(111),char(100),char(101),char(115),char(0),char(42),char(109),char(95),char(108),char(105),char(110),char(107),char(115),char(0),char(42),char(109),char(95),char(102),char(97),
-char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(116),char(101),char(116),char(114),char(97),char(104),char(101),char(100),char(114),char(97),char(0),char(42),char(109),
-char(95),char(97),char(110),char(99),char(104),char(111),char(114),char(115),char(0),char(42),char(109),char(95),char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(115),
-char(0),char(42),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(97),char(116),char(101),
-char(114),char(105),char(97),char(108),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(76),char(105),char(110),char(107),char(115),char(0),char(109),char(95),char(110),
-char(117),char(109),char(70),char(97),char(99),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(84),char(101),char(116),char(114),char(97),char(104),char(101),
-char(100),char(114),char(97),char(0),char(109),char(95),char(110),char(117),char(109),char(65),char(110),char(99),char(104),char(111),char(114),char(115),char(0),char(109),char(95),char(110),
-char(117),char(109),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(74),char(111),char(105),char(110),
-char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(110),char(102),char(105),char(103),char(0),char(84),char(89),char(80),char(69),char(76),char(0),char(0),char(0),
-char(99),char(104),char(97),char(114),char(0),char(117),char(99),char(104),char(97),char(114),char(0),char(115),char(104),char(111),char(114),char(116),char(0),char(117),char(115),char(104),
-char(111),char(114),char(116),char(0),char(105),char(110),char(116),char(0),char(108),char(111),char(110),char(103),char(0),char(117),char(108),char(111),char(110),char(103),char(0),char(102),
-char(108),char(111),char(97),char(116),char(0),char(100),char(111),char(117),char(98),char(108),char(101),char(0),char(118),char(111),char(105),char(100),char(0),char(80),char(111),char(105),
-char(110),char(116),char(101),char(114),char(65),char(114),char(114),char(97),char(121),char(0),char(98),char(116),char(80),char(104),char(121),char(115),char(105),char(99),char(115),char(83),
-char(121),char(115),char(116),char(101),char(109),char(0),char(76),char(105),char(115),char(116),char(66),char(97),char(115),char(101),char(0),char(98),char(116),char(86),char(101),char(99),
-char(116),char(111),char(114),char(51),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(86),char(101),char(99),char(116),
-char(111),char(114),char(51),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(97),char(116),char(114),
-char(105),char(120),char(51),char(120),char(51),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(97),char(116),
-char(114),char(105),char(120),char(51),char(120),char(51),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),
-char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),
-char(98),char(116),char(66),char(118),char(104),char(83),char(117),char(98),char(116),char(114),char(101),char(101),char(73),char(110),char(102),char(111),char(68),char(97),char(116),char(97),
-char(0),char(98),char(116),char(79),char(112),char(116),char(105),char(109),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(70),
-char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(79),char(112),char(116),char(105),char(109),char(105),char(122),char(101),char(100),
-char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(68),char(97),char(116),char(97),
-char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(70),char(108),char(111),char(97),char(116),
-char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(68),
-char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),
-char(110),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116),char(97),char(116),char(105),char(99),char(80),
-char(108),char(97),char(110),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(118),
-char(101),char(120),char(73),char(110),char(116),char(101),char(114),char(110),char(97),char(108),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),
-char(98),char(116),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(110),char(100),char(82),char(97),char(100),char(105),char(117),char(115),char(0),
-char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(83),char(112),char(104),char(101),char(114),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),
-char(116),char(97),char(0),char(98),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(83),char(104),char(111),char(114),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(83),char(104),char(111),char(114),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(84),char(114),char(105),char(112),char(108),char(101),char(116),
-char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(104),char(97),char(114),char(73),char(110),char(100),char(101),char(120),char(84),char(114),char(105),char(112),
-char(108),char(101),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(101),char(115),char(104),char(80),char(97),char(114),char(116),char(68),char(97),
-char(116),char(97),char(0),char(98),char(116),char(83),char(116),char(114),char(105),char(100),char(105),char(110),char(103),char(77),char(101),char(115),char(104),char(73),char(110),char(116),
-char(101),char(114),char(102),char(97),char(99),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108),
-char(101),char(77),char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),
-char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(102),char(111),char(77),char(97),char(112),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),
-char(99),char(97),char(108),char(101),char(100),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(77),char(101),char(115),char(104),char(83),char(104),char(97),
-char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(109),char(112),char(111),char(117),char(110),char(100),char(83),char(104),char(97),
-char(112),char(101),char(67),char(104),char(105),char(108),char(100),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(109),char(112),char(111),char(117),
-char(110),char(100),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(121),char(108),char(105),char(110),char(100),
-char(101),char(114),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(97),char(112),char(115),char(117),char(108),
-char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108),
-char(101),char(73),char(110),char(102),char(111),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(73),char(109),char(112),char(97),char(99),char(116),char(77),
-char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(118),char(101),
-char(120),char(72),char(117),char(108),char(108),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),
-char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),
-char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),
-char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(68),char(121),char(110),char(97),char(109),char(105),char(99),char(115),
-char(87),char(111),char(114),char(108),char(100),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),
-char(110),char(116),char(97),char(99),char(116),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(68),char(111),char(117),char(98),char(108),
-char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(68),char(121),char(110),char(97),char(109),char(105),char(99),char(115),char(87),char(111),char(114),char(108),
-char(100),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),
-char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),
-char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),
-char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),
-char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(73),char(110),char(102),char(111),char(49),
-char(0),char(98),char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),
-char(116),char(97),char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(68),char(97),char(116),char(97),char(0),char(98),
-char(116),char(80),char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),
-char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),
-char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),
-char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),
-char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),
-char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),
-char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(84),char(119),char(105),char(115),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),
-char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),
-char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),
-char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(67),char(111),char(110),char(115),char(116),char(114),
-char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(108),char(105),char(100),char(101),char(114),char(67),char(111),char(110),
-char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),
-char(77),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),
-char(121),char(78),char(111),char(100),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(76),char(105),
-char(110),char(107),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(70),char(97),char(99),char(101),char(68),
-char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(84),char(101),char(116),char(114),char(97),char(68),char(97),char(116),
-char(97),char(0),char(83),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(65),char(110),char(99),char(104),char(111),char(114),char(68),char(97),char(116),
-char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(67),char(111),char(110),char(102),char(105),char(103),char(68),char(97),char(116),char(97),
-char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(80),char(111),char(115),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),
-char(102),char(116),char(66),char(111),char(100),char(121),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(74),char(111),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(0),char(0),
-char(84),char(76),char(69),char(78),char(1),char(0),char(1),char(0),char(2),char(0),char(2),char(0),char(4),char(0),char(4),char(0),char(4),char(0),char(4),char(0),
-char(8),char(0),char(0),char(0),char(12),char(0),char(36),char(0),char(8),char(0),char(16),char(0),char(32),char(0),char(48),char(0),char(96),char(0),char(64),char(0),
-char(-128),char(0),char(20),char(0),char(48),char(0),char(80),char(0),char(16),char(0),char(84),char(0),char(-124),char(0),char(12),char(0),char(52),char(0),char(52),char(0),
-char(20),char(0),char(64),char(0),char(4),char(0),char(4),char(0),char(8),char(0),char(4),char(0),char(32),char(0),char(28),char(0),char(60),char(0),char(56),char(0),
-char(76),char(0),char(76),char(0),char(24),char(0),char(60),char(0),char(60),char(0),char(16),char(0),char(64),char(0),char(68),char(0),char(-48),char(1),char(0),char(1),
-char(-72),char(0),char(-104),char(0),char(104),char(0),char(88),char(0),char(-24),char(1),char(-96),char(3),char(8),char(0),char(52),char(0),char(0),char(0),char(84),char(0),
-char(116),char(0),char(92),char(1),char(-36),char(0),char(-44),char(0),char(-4),char(0),char(92),char(1),char(-52),char(0),char(16),char(0),char(100),char(0),char(20),char(0),
-char(36),char(0),char(100),char(0),char(92),char(0),char(104),char(0),char(-64),char(0),char(92),char(1),char(104),char(0),char(-84),char(1),char(83),char(84),char(82),char(67),
-char(65),char(0),char(0),char(0),char(10),char(0),char(3),char(0),char(4),char(0),char(0),char(0),char(4),char(0),char(1),char(0),char(9),char(0),char(2),char(0),
-char(11),char(0),char(3),char(0),char(10),char(0),char(3),char(0),char(10),char(0),char(4),char(0),char(10),char(0),char(5),char(0),char(12),char(0),char(2),char(0),
-char(9),char(0),char(6),char(0),char(9),char(0),char(7),char(0),char(13),char(0),char(1),char(0),char(7),char(0),char(8),char(0),char(14),char(0),char(1),char(0),
-char(8),char(0),char(8),char(0),char(15),char(0),char(1),char(0),char(13),char(0),char(9),char(0),char(16),char(0),char(1),char(0),char(14),char(0),char(9),char(0),
-char(17),char(0),char(2),char(0),char(15),char(0),char(10),char(0),char(13),char(0),char(11),char(0),char(18),char(0),char(2),char(0),char(16),char(0),char(10),char(0),
-char(14),char(0),char(11),char(0),char(19),char(0),char(4),char(0),char(4),char(0),char(12),char(0),char(4),char(0),char(13),char(0),char(2),char(0),char(14),char(0),
-char(2),char(0),char(15),char(0),char(20),char(0),char(6),char(0),char(13),char(0),char(16),char(0),char(13),char(0),char(17),char(0),char(4),char(0),char(18),char(0),
-char(4),char(0),char(19),char(0),char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),char(21),char(0),char(6),char(0),char(14),char(0),char(16),char(0),
-char(14),char(0),char(17),char(0),char(4),char(0),char(18),char(0),char(4),char(0),char(19),char(0),char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),
-char(22),char(0),char(3),char(0),char(2),char(0),char(14),char(0),char(2),char(0),char(15),char(0),char(4),char(0),char(22),char(0),char(23),char(0),char(12),char(0),
-char(13),char(0),char(23),char(0),char(13),char(0),char(24),char(0),char(13),char(0),char(25),char(0),char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),
-char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0),char(20),char(0),char(30),char(0),char(22),char(0),char(31),char(0),char(19),char(0),char(32),char(0),
-char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0),char(24),char(0),char(12),char(0),char(14),char(0),char(23),char(0),char(14),char(0),char(24),char(0),
-char(14),char(0),char(25),char(0),char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0),
-char(21),char(0),char(30),char(0),char(22),char(0),char(31),char(0),char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0),char(19),char(0),char(32),char(0),
-char(25),char(0),char(3),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(36),char(0),char(0),char(0),char(37),char(0),char(26),char(0),char(5),char(0),
-char(25),char(0),char(38),char(0),char(13),char(0),char(39),char(0),char(13),char(0),char(40),char(0),char(7),char(0),char(41),char(0),char(0),char(0),char(21),char(0),
-char(27),char(0),char(5),char(0),char(25),char(0),char(38),char(0),char(13),char(0),char(39),char(0),char(13),char(0),char(42),char(0),char(7),char(0),char(43),char(0),
-char(4),char(0),char(44),char(0),char(28),char(0),char(2),char(0),char(13),char(0),char(45),char(0),char(7),char(0),char(46),char(0),char(29),char(0),char(4),char(0),
-char(27),char(0),char(47),char(0),char(28),char(0),char(48),char(0),char(4),char(0),char(49),char(0),char(0),char(0),char(37),char(0),char(30),char(0),char(1),char(0),
-char(4),char(0),char(50),char(0),char(31),char(0),char(2),char(0),char(2),char(0),char(50),char(0),char(0),char(0),char(51),char(0),char(32),char(0),char(2),char(0),
-char(2),char(0),char(52),char(0),char(0),char(0),char(51),char(0),char(33),char(0),char(2),char(0),char(0),char(0),char(52),char(0),char(0),char(0),char(53),char(0),
-char(34),char(0),char(8),char(0),char(13),char(0),char(54),char(0),char(14),char(0),char(55),char(0),char(30),char(0),char(56),char(0),char(32),char(0),char(57),char(0),
-char(33),char(0),char(58),char(0),char(31),char(0),char(59),char(0),char(4),char(0),char(60),char(0),char(4),char(0),char(61),char(0),char(35),char(0),char(4),char(0),
-char(34),char(0),char(62),char(0),char(13),char(0),char(63),char(0),char(4),char(0),char(64),char(0),char(0),char(0),char(37),char(0),char(36),char(0),char(7),char(0),
-char(25),char(0),char(38),char(0),char(35),char(0),char(65),char(0),char(23),char(0),char(66),char(0),char(24),char(0),char(67),char(0),char(37),char(0),char(68),char(0),
-char(7),char(0),char(43),char(0),char(0),char(0),char(69),char(0),char(38),char(0),char(2),char(0),char(36),char(0),char(70),char(0),char(13),char(0),char(39),char(0),
-char(39),char(0),char(4),char(0),char(17),char(0),char(71),char(0),char(25),char(0),char(72),char(0),char(4),char(0),char(73),char(0),char(7),char(0),char(74),char(0),
-char(40),char(0),char(4),char(0),char(25),char(0),char(38),char(0),char(39),char(0),char(75),char(0),char(4),char(0),char(76),char(0),char(7),char(0),char(43),char(0),
-char(41),char(0),char(3),char(0),char(27),char(0),char(47),char(0),char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0),char(42),char(0),char(3),char(0),
-char(27),char(0),char(47),char(0),char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0),char(43),char(0),char(4),char(0),char(4),char(0),char(78),char(0),
-char(7),char(0),char(79),char(0),char(7),char(0),char(80),char(0),char(7),char(0),char(81),char(0),char(37),char(0),char(14),char(0),char(4),char(0),char(82),char(0),
-char(4),char(0),char(83),char(0),char(43),char(0),char(84),char(0),char(4),char(0),char(85),char(0),char(7),char(0),char(86),char(0),char(7),char(0),char(87),char(0),
-char(7),char(0),char(88),char(0),char(7),char(0),char(89),char(0),char(7),char(0),char(90),char(0),char(4),char(0),char(91),char(0),char(4),char(0),char(92),char(0),
-char(4),char(0),char(93),char(0),char(4),char(0),char(94),char(0),char(0),char(0),char(37),char(0),char(44),char(0),char(5),char(0),char(25),char(0),char(38),char(0),
-char(35),char(0),char(65),char(0),char(13),char(0),char(39),char(0),char(7),char(0),char(43),char(0),char(4),char(0),char(95),char(0),char(45),char(0),char(5),char(0),
-char(27),char(0),char(47),char(0),char(13),char(0),char(96),char(0),char(14),char(0),char(97),char(0),char(4),char(0),char(98),char(0),char(0),char(0),char(99),char(0),
-char(46),char(0),char(25),char(0),char(9),char(0),char(100),char(0),char(9),char(0),char(101),char(0),char(25),char(0),char(102),char(0),char(0),char(0),char(35),char(0),
-char(18),char(0),char(103),char(0),char(18),char(0),char(104),char(0),char(14),char(0),char(105),char(0),char(14),char(0),char(106),char(0),char(14),char(0),char(107),char(0),
-char(8),char(0),char(108),char(0),char(8),char(0),char(109),char(0),char(8),char(0),char(110),char(0),char(8),char(0),char(111),char(0),char(8),char(0),char(112),char(0),
-char(8),char(0),char(113),char(0),char(8),char(0),char(114),char(0),char(8),char(0),char(115),char(0),char(4),char(0),char(116),char(0),char(4),char(0),char(117),char(0),
-char(4),char(0),char(118),char(0),char(4),char(0),char(119),char(0),char(4),char(0),char(120),char(0),char(4),char(0),char(121),char(0),char(4),char(0),char(122),char(0),
-char(0),char(0),char(37),char(0),char(47),char(0),char(25),char(0),char(9),char(0),char(100),char(0),char(9),char(0),char(101),char(0),char(25),char(0),char(102),char(0),
-char(0),char(0),char(35),char(0),char(17),char(0),char(103),char(0),char(17),char(0),char(104),char(0),char(13),char(0),char(105),char(0),char(13),char(0),char(106),char(0),
-char(13),char(0),char(107),char(0),char(7),char(0),char(108),char(0),char(7),char(0),char(109),char(0),char(7),char(0),char(110),char(0),char(7),char(0),char(111),char(0),
-char(7),char(0),char(112),char(0),char(7),char(0),char(113),char(0),char(7),char(0),char(114),char(0),char(7),char(0),char(115),char(0),char(4),char(0),char(116),char(0),
-char(4),char(0),char(117),char(0),char(4),char(0),char(118),char(0),char(4),char(0),char(119),char(0),char(4),char(0),char(120),char(0),char(4),char(0),char(121),char(0),
-char(4),char(0),char(122),char(0),char(0),char(0),char(37),char(0),char(48),char(0),char(2),char(0),char(49),char(0),char(123),char(0),char(14),char(0),char(124),char(0),
-char(50),char(0),char(2),char(0),char(51),char(0),char(123),char(0),char(13),char(0),char(124),char(0),char(52),char(0),char(21),char(0),char(47),char(0),char(125),char(0),
-char(15),char(0),char(126),char(0),char(13),char(0),char(127),char(0),char(13),char(0),char(-128),char(0),char(13),char(0),char(-127),char(0),char(13),char(0),char(-126),char(0),
-char(13),char(0),char(124),char(0),char(13),char(0),char(-125),char(0),char(13),char(0),char(-124),char(0),char(13),char(0),char(-123),char(0),char(13),char(0),char(-122),char(0),
-char(7),char(0),char(-121),char(0),char(7),char(0),char(-120),char(0),char(7),char(0),char(-119),char(0),char(7),char(0),char(-118),char(0),char(7),char(0),char(-117),char(0),
-char(7),char(0),char(-116),char(0),char(7),char(0),char(-115),char(0),char(7),char(0),char(-114),char(0),char(7),char(0),char(-113),char(0),char(4),char(0),char(-112),char(0),
-char(53),char(0),char(22),char(0),char(46),char(0),char(125),char(0),char(16),char(0),char(126),char(0),char(14),char(0),char(127),char(0),char(14),char(0),char(-128),char(0),
-char(14),char(0),char(-127),char(0),char(14),char(0),char(-126),char(0),char(14),char(0),char(124),char(0),char(14),char(0),char(-125),char(0),char(14),char(0),char(-124),char(0),
-char(14),char(0),char(-123),char(0),char(14),char(0),char(-122),char(0),char(8),char(0),char(-121),char(0),char(8),char(0),char(-120),char(0),char(8),char(0),char(-119),char(0),
-char(8),char(0),char(-118),char(0),char(8),char(0),char(-117),char(0),char(8),char(0),char(-116),char(0),char(8),char(0),char(-115),char(0),char(8),char(0),char(-114),char(0),
-char(8),char(0),char(-113),char(0),char(4),char(0),char(-112),char(0),char(0),char(0),char(37),char(0),char(54),char(0),char(2),char(0),char(4),char(0),char(-111),char(0),
-char(4),char(0),char(-110),char(0),char(55),char(0),char(13),char(0),char(56),char(0),char(-109),char(0),char(56),char(0),char(-108),char(0),char(0),char(0),char(35),char(0),
-char(4),char(0),char(-107),char(0),char(4),char(0),char(-106),char(0),char(4),char(0),char(-105),char(0),char(4),char(0),char(-104),char(0),char(7),char(0),char(-103),char(0),
-char(7),char(0),char(-102),char(0),char(4),char(0),char(-101),char(0),char(4),char(0),char(-100),char(0),char(7),char(0),char(-99),char(0),char(4),char(0),char(-98),char(0),
-char(57),char(0),char(3),char(0),char(55),char(0),char(-97),char(0),char(13),char(0),char(-96),char(0),char(13),char(0),char(-95),char(0),char(58),char(0),char(3),char(0),
-char(55),char(0),char(-97),char(0),char(14),char(0),char(-96),char(0),char(14),char(0),char(-95),char(0),char(59),char(0),char(13),char(0),char(55),char(0),char(-97),char(0),
-char(18),char(0),char(-94),char(0),char(18),char(0),char(-93),char(0),char(4),char(0),char(-92),char(0),char(4),char(0),char(-91),char(0),char(4),char(0),char(-90),char(0),
-char(7),char(0),char(-89),char(0),char(7),char(0),char(-88),char(0),char(7),char(0),char(-87),char(0),char(7),char(0),char(-86),char(0),char(7),char(0),char(-85),char(0),
-char(7),char(0),char(-84),char(0),char(7),char(0),char(-83),char(0),char(60),char(0),char(13),char(0),char(55),char(0),char(-97),char(0),char(17),char(0),char(-94),char(0),
-char(17),char(0),char(-93),char(0),char(4),char(0),char(-92),char(0),char(4),char(0),char(-91),char(0),char(4),char(0),char(-90),char(0),char(7),char(0),char(-89),char(0),
-char(7),char(0),char(-88),char(0),char(7),char(0),char(-87),char(0),char(7),char(0),char(-86),char(0),char(7),char(0),char(-85),char(0),char(7),char(0),char(-84),char(0),
-char(7),char(0),char(-83),char(0),char(61),char(0),char(11),char(0),char(55),char(0),char(-97),char(0),char(17),char(0),char(-94),char(0),char(17),char(0),char(-93),char(0),
-char(7),char(0),char(-82),char(0),char(7),char(0),char(-81),char(0),char(7),char(0),char(-80),char(0),char(7),char(0),char(-85),char(0),char(7),char(0),char(-84),char(0),
-char(7),char(0),char(-83),char(0),char(7),char(0),char(-79),char(0),char(0),char(0),char(21),char(0),char(62),char(0),char(9),char(0),char(55),char(0),char(-97),char(0),
-char(17),char(0),char(-94),char(0),char(17),char(0),char(-93),char(0),char(13),char(0),char(-78),char(0),char(13),char(0),char(-77),char(0),char(13),char(0),char(-76),char(0),
-char(13),char(0),char(-75),char(0),char(4),char(0),char(-74),char(0),char(4),char(0),char(-73),char(0),char(63),char(0),char(5),char(0),char(62),char(0),char(-72),char(0),
-char(4),char(0),char(-71),char(0),char(7),char(0),char(-70),char(0),char(7),char(0),char(-69),char(0),char(7),char(0),char(-68),char(0),char(64),char(0),char(9),char(0),
-char(55),char(0),char(-97),char(0),char(17),char(0),char(-94),char(0),char(17),char(0),char(-93),char(0),char(7),char(0),char(-78),char(0),char(7),char(0),char(-77),char(0),
-char(7),char(0),char(-76),char(0),char(7),char(0),char(-75),char(0),char(4),char(0),char(-74),char(0),char(4),char(0),char(-73),char(0),char(49),char(0),char(22),char(0),
-char(8),char(0),char(-67),char(0),char(8),char(0),char(-79),char(0),char(8),char(0),char(110),char(0),char(8),char(0),char(-66),char(0),char(8),char(0),char(112),char(0),
-char(8),char(0),char(-65),char(0),char(8),char(0),char(-64),char(0),char(8),char(0),char(-63),char(0),char(8),char(0),char(-62),char(0),char(8),char(0),char(-61),char(0),
-char(8),char(0),char(-60),char(0),char(8),char(0),char(-59),char(0),char(8),char(0),char(-58),char(0),char(8),char(0),char(-57),char(0),char(8),char(0),char(-56),char(0),
-char(8),char(0),char(-55),char(0),char(4),char(0),char(-54),char(0),char(4),char(0),char(-53),char(0),char(4),char(0),char(-52),char(0),char(4),char(0),char(-51),char(0),
-char(4),char(0),char(-50),char(0),char(0),char(0),char(37),char(0),char(51),char(0),char(22),char(0),char(7),char(0),char(-67),char(0),char(7),char(0),char(-79),char(0),
-char(7),char(0),char(110),char(0),char(7),char(0),char(-66),char(0),char(7),char(0),char(112),char(0),char(7),char(0),char(-65),char(0),char(7),char(0),char(-64),char(0),
-char(7),char(0),char(-63),char(0),char(7),char(0),char(-62),char(0),char(7),char(0),char(-61),char(0),char(7),char(0),char(-60),char(0),char(7),char(0),char(-59),char(0),
-char(7),char(0),char(-58),char(0),char(7),char(0),char(-57),char(0),char(7),char(0),char(-56),char(0),char(7),char(0),char(-55),char(0),char(4),char(0),char(-54),char(0),
-char(4),char(0),char(-53),char(0),char(4),char(0),char(-52),char(0),char(4),char(0),char(-51),char(0),char(4),char(0),char(-50),char(0),char(0),char(0),char(37),char(0),
-char(65),char(0),char(4),char(0),char(7),char(0),char(-49),char(0),char(7),char(0),char(-48),char(0),char(7),char(0),char(-47),char(0),char(4),char(0),char(78),char(0),
-char(66),char(0),char(10),char(0),char(65),char(0),char(-46),char(0),char(13),char(0),char(-45),char(0),char(13),char(0),char(-44),char(0),char(13),char(0),char(-43),char(0),
-char(13),char(0),char(-42),char(0),char(13),char(0),char(-41),char(0),char(7),char(0),char(-121),char(0),char(7),char(0),char(-40),char(0),char(4),char(0),char(-39),char(0),
-char(4),char(0),char(53),char(0),char(67),char(0),char(4),char(0),char(65),char(0),char(-46),char(0),char(4),char(0),char(-38),char(0),char(7),char(0),char(-37),char(0),
-char(4),char(0),char(-36),char(0),char(68),char(0),char(4),char(0),char(13),char(0),char(-41),char(0),char(65),char(0),char(-46),char(0),char(4),char(0),char(-35),char(0),
-char(7),char(0),char(-34),char(0),char(69),char(0),char(7),char(0),char(13),char(0),char(-33),char(0),char(65),char(0),char(-46),char(0),char(4),char(0),char(-32),char(0),
-char(7),char(0),char(-31),char(0),char(7),char(0),char(-30),char(0),char(7),char(0),char(-29),char(0),char(4),char(0),char(53),char(0),char(70),char(0),char(6),char(0),
-char(15),char(0),char(-28),char(0),char(13),char(0),char(-30),char(0),char(13),char(0),char(-27),char(0),char(56),char(0),char(-26),char(0),char(4),char(0),char(-25),char(0),
-char(7),char(0),char(-29),char(0),char(71),char(0),char(26),char(0),char(4),char(0),char(-24),char(0),char(7),char(0),char(-23),char(0),char(7),char(0),char(-79),char(0),
-char(7),char(0),char(-22),char(0),char(7),char(0),char(-21),char(0),char(7),char(0),char(-20),char(0),char(7),char(0),char(-19),char(0),char(7),char(0),char(-18),char(0),
-char(7),char(0),char(-17),char(0),char(7),char(0),char(-16),char(0),char(7),char(0),char(-15),char(0),char(7),char(0),char(-14),char(0),char(7),char(0),char(-13),char(0),
-char(7),char(0),char(-12),char(0),char(7),char(0),char(-11),char(0),char(7),char(0),char(-10),char(0),char(7),char(0),char(-9),char(0),char(7),char(0),char(-8),char(0),
-char(7),char(0),char(-7),char(0),char(7),char(0),char(-6),char(0),char(7),char(0),char(-5),char(0),char(4),char(0),char(-4),char(0),char(4),char(0),char(-3),char(0),
-char(4),char(0),char(-2),char(0),char(4),char(0),char(-1),char(0),char(4),char(0),char(117),char(0),char(72),char(0),char(12),char(0),char(15),char(0),char(0),char(1),
-char(15),char(0),char(1),char(1),char(15),char(0),char(2),char(1),char(13),char(0),char(3),char(1),char(13),char(0),char(4),char(1),char(7),char(0),char(5),char(1),
-char(4),char(0),char(6),char(1),char(4),char(0),char(7),char(1),char(4),char(0),char(8),char(1),char(4),char(0),char(9),char(1),char(7),char(0),char(-31),char(0),
-char(4),char(0),char(53),char(0),char(73),char(0),char(27),char(0),char(17),char(0),char(10),char(1),char(15),char(0),char(11),char(1),char(15),char(0),char(12),char(1),
-char(13),char(0),char(3),char(1),char(13),char(0),char(13),char(1),char(13),char(0),char(14),char(1),char(13),char(0),char(15),char(1),char(13),char(0),char(16),char(1),
-char(13),char(0),char(17),char(1),char(4),char(0),char(18),char(1),char(7),char(0),char(19),char(1),char(4),char(0),char(20),char(1),char(4),char(0),char(21),char(1),
-char(4),char(0),char(22),char(1),char(7),char(0),char(23),char(1),char(7),char(0),char(24),char(1),char(4),char(0),char(25),char(1),char(4),char(0),char(26),char(1),
-char(7),char(0),char(27),char(1),char(7),char(0),char(28),char(1),char(7),char(0),char(29),char(1),char(7),char(0),char(30),char(1),char(7),char(0),char(31),char(1),
-char(7),char(0),char(32),char(1),char(4),char(0),char(33),char(1),char(4),char(0),char(34),char(1),char(4),char(0),char(35),char(1),char(74),char(0),char(12),char(0),
-char(9),char(0),char(36),char(1),char(9),char(0),char(37),char(1),char(13),char(0),char(38),char(1),char(7),char(0),char(39),char(1),char(7),char(0),char(-63),char(0),
-char(7),char(0),char(40),char(1),char(4),char(0),char(41),char(1),char(13),char(0),char(42),char(1),char(4),char(0),char(43),char(1),char(4),char(0),char(44),char(1),
-char(4),char(0),char(45),char(1),char(4),char(0),char(53),char(0),char(75),char(0),char(19),char(0),char(47),char(0),char(125),char(0),char(72),char(0),char(46),char(1),
-char(65),char(0),char(47),char(1),char(66),char(0),char(48),char(1),char(67),char(0),char(49),char(1),char(68),char(0),char(50),char(1),char(69),char(0),char(51),char(1),
-char(70),char(0),char(52),char(1),char(73),char(0),char(53),char(1),char(74),char(0),char(54),char(1),char(4),char(0),char(55),char(1),char(4),char(0),char(21),char(1),
-char(4),char(0),char(56),char(1),char(4),char(0),char(57),char(1),char(4),char(0),char(58),char(1),char(4),char(0),char(59),char(1),char(4),char(0),char(60),char(1),
-char(4),char(0),char(61),char(1),char(71),char(0),char(62),char(1),};
-int b3s_bulletDNAlen= sizeof(b3s_bulletDNAstr);
-char b3s_bulletDNAstr64[]= {
-char(83),char(68),char(78),char(65),char(78),char(65),char(77),char(69),char(63),char(1),char(0),char(0),char(109),char(95),char(115),char(105),char(122),char(101),char(0),char(109),
-char(95),char(99),char(97),char(112),char(97),char(99),char(105),char(116),char(121),char(0),char(42),char(109),char(95),char(100),char(97),char(116),char(97),char(0),char(109),char(95),
-char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(115),char(0),char(109),char(95),char(99),char(111),
-char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(110),
-char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(115),char(0),char(42),char(102),char(105),char(114),char(115),char(116),char(0),char(42),char(108),char(97),char(115),
-char(116),char(0),char(109),char(95),char(102),char(108),char(111),char(97),char(116),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(101),char(108),char(91),char(51),
-char(93),char(0),char(109),char(95),char(98),char(97),char(115),char(105),char(115),char(0),char(109),char(95),char(111),char(114),char(105),char(103),char(105),char(110),char(0),char(109),
-char(95),char(114),char(111),char(111),char(116),char(78),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(115),char(117),char(98),
-char(116),char(114),char(101),char(101),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),
-char(65),char(97),char(98),char(98),char(77),char(105),char(110),char(91),char(51),char(93),char(0),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),
-char(101),char(100),char(65),char(97),char(98),char(98),char(77),char(97),char(120),char(91),char(51),char(93),char(0),char(109),char(95),char(97),char(97),char(98),char(98),char(77),
-char(105),char(110),char(79),char(114),char(103),char(0),char(109),char(95),char(97),char(97),char(98),char(98),char(77),char(97),char(120),char(79),char(114),char(103),char(0),char(109),
-char(95),char(101),char(115),char(99),char(97),char(112),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(115),char(117),char(98),char(80),char(97),
-char(114),char(116),char(0),char(109),char(95),char(116),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),
-char(95),char(112),char(97),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(101),char(115),char(99),char(97),char(112),char(101),char(73),char(110),char(100),char(101),
-char(120),char(79),char(114),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(98),
-char(118),char(104),char(65),char(97),char(98),char(98),char(77),char(105),char(110),char(0),char(109),char(95),char(98),char(118),char(104),char(65),char(97),char(98),char(98),char(77),
-char(97),char(120),char(0),char(109),char(95),char(98),char(118),char(104),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(97),char(116),char(105),char(111),char(110),
-char(0),char(109),char(95),char(99),char(117),char(114),char(78),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(117),char(115),
-char(101),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(97),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(110),char(117),char(109),char(67),
-char(111),char(110),char(116),char(105),char(103),char(117),char(111),char(117),char(115),char(76),char(101),char(97),char(102),char(78),char(111),char(100),char(101),char(115),char(0),char(109),
-char(95),char(110),char(117),char(109),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(67),char(111),char(110),char(116),char(105),char(103),char(117),
-char(111),char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(0),char(42),char(109),char(95),char(99),char(111),char(110),char(116),char(105),char(103),char(117),char(111),
-char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),
-char(122),char(101),char(100),char(67),char(111),char(110),char(116),char(105),char(103),char(117),char(111),char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(80),char(116),
-char(114),char(0),char(42),char(109),char(95),char(115),char(117),char(98),char(84),char(114),char(101),char(101),char(73),char(110),char(102),char(111),char(80),char(116),char(114),char(0),
-char(109),char(95),char(116),char(114),char(97),char(118),char(101),char(114),char(115),char(97),char(108),char(77),char(111),char(100),char(101),char(0),char(109),char(95),char(110),char(117),
-char(109),char(83),char(117),char(98),char(116),char(114),char(101),char(101),char(72),char(101),char(97),char(100),char(101),char(114),char(115),char(0),char(42),char(109),char(95),char(110),
-char(97),char(109),char(101),char(0),char(109),char(95),char(115),char(104),char(97),char(112),char(101),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(112),char(97),
-char(100),char(100),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),
-char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(83),char(99),char(97),
-char(108),char(105),char(110),char(103),char(0),char(109),char(95),char(112),char(108),char(97),char(110),char(101),char(78),char(111),char(114),char(109),char(97),char(108),char(0),char(109),
-char(95),char(112),char(108),char(97),char(110),char(101),char(67),char(111),char(110),char(115),char(116),char(97),char(110),char(116),char(0),char(109),char(95),char(105),char(109),char(112),
-char(108),char(105),char(99),char(105),char(116),char(83),char(104),char(97),char(112),char(101),char(68),char(105),char(109),char(101),char(110),char(115),char(105),char(111),char(110),char(115),
-char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(77),char(97),char(114),char(103),char(105),char(110),char(0),char(109),
-char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(0),char(109),char(95),char(112),char(111),char(115),char(0),char(109),char(95),char(114),char(97),char(100),
-char(105),char(117),char(115),char(0),char(109),char(95),char(99),char(111),char(110),char(118),char(101),char(120),char(73),char(110),char(116),char(101),char(114),char(110),char(97),char(108),
-char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(42),char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(80),char(111),
-char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(114),char(114),char(97),char(121),char(80),char(116),char(114),char(0),char(109),char(95),char(108),char(111),char(99),
-char(97),char(108),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(114),char(114),char(97),char(121),char(83),char(105),char(122),char(101),char(0),
-char(109),char(95),char(118),char(97),char(108),char(117),char(101),char(0),char(109),char(95),char(112),char(97),char(100),char(91),char(50),char(93),char(0),char(109),char(95),char(118),
-char(97),char(108),char(117),char(101),char(115),char(91),char(51),char(93),char(0),char(109),char(95),char(112),char(97),char(100),char(0),char(42),char(109),char(95),char(118),char(101),
-char(114),char(116),char(105),char(99),char(101),char(115),char(51),char(102),char(0),char(42),char(109),char(95),char(118),char(101),char(114),char(116),char(105),char(99),char(101),char(115),
-char(51),char(100),char(0),char(42),char(109),char(95),char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(51),char(50),char(0),char(42),char(109),char(95),char(51),
-char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(49),char(54),char(0),char(42),char(109),char(95),char(51),char(105),char(110),char(100),char(105),char(99),char(101),
-char(115),char(56),char(0),char(42),char(109),char(95),char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(49),char(54),char(0),char(109),char(95),char(110),char(117),
-char(109),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(86),char(101),char(114),char(116),
-char(105),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(109),char(101),char(115),char(104),char(80),char(97),char(114),char(116),char(115),char(80),char(116),char(114),
-char(0),char(109),char(95),char(115),char(99),char(97),char(108),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(101),char(115),char(104),
-char(80),char(97),char(114),char(116),char(115),char(0),char(109),char(95),char(109),char(101),char(115),char(104),char(73),char(110),char(116),char(101),char(114),char(102),char(97),char(99),
-char(101),char(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(70),char(108),char(111),char(97),char(116),char(66),
-char(118),char(104),char(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(68),char(111),char(117),char(98),char(108),
-char(101),char(66),char(118),char(104),char(0),char(42),char(109),char(95),char(116),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(102),char(111),
-char(77),char(97),char(112),char(0),char(109),char(95),char(112),char(97),char(100),char(51),char(91),char(52),char(93),char(0),char(109),char(95),char(116),char(114),char(105),char(109),
-char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(116),char(114),char(97),char(110),char(115),
-char(102),char(111),char(114),char(109),char(0),char(42),char(109),char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),char(97),char(112),char(101),char(0),char(109),
-char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),char(97),char(112),char(101),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(99),char(104),
-char(105),char(108),char(100),char(77),char(97),char(114),char(103),char(105),char(110),char(0),char(42),char(109),char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),
-char(97),char(112),char(101),char(80),char(116),char(114),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(104),char(105),char(108),char(100),char(83),char(104),char(97),
-char(112),char(101),char(115),char(0),char(109),char(95),char(117),char(112),char(65),char(120),char(105),char(115),char(0),char(109),char(95),char(102),char(108),char(97),char(103),char(115),
-char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(86),char(48),char(86),char(49),char(65),char(110),char(103),char(108),char(101),char(0),char(109),char(95),char(101),
-char(100),char(103),char(101),char(86),char(49),char(86),char(50),char(65),char(110),char(103),char(108),char(101),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(86),
-char(50),char(86),char(48),char(65),char(110),char(103),char(108),char(101),char(0),char(42),char(109),char(95),char(104),char(97),char(115),char(104),char(84),char(97),char(98),char(108),
-char(101),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(110),char(101),char(120),char(116),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(118),
-char(97),char(108),char(117),char(101),char(65),char(114),char(114),char(97),char(121),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(107),char(101),char(121),char(65),
-char(114),char(114),char(97),char(121),char(80),char(116),char(114),char(0),char(109),char(95),char(99),char(111),char(110),char(118),char(101),char(120),char(69),char(112),char(115),char(105),
-char(108),char(111),char(110),char(0),char(109),char(95),char(112),char(108),char(97),char(110),char(97),char(114),char(69),char(112),char(115),char(105),char(108),char(111),char(110),char(0),
-char(109),char(95),char(101),char(113),char(117),char(97),char(108),char(86),char(101),char(114),char(116),char(101),char(120),char(84),char(104),char(114),char(101),char(115),char(104),char(111),
-char(108),char(100),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(68),char(105),char(115),char(116),char(97),char(110),char(99),char(101),char(84),char(104),char(114),
-char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(122),char(101),char(114),char(111),char(65),char(114),char(101),char(97),char(84),char(104),char(114),
-char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(110),char(101),char(120),char(116),char(83),char(105),char(122),char(101),char(0),char(109),char(95),
-char(104),char(97),char(115),char(104),char(84),char(97),char(98),char(108),char(101),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(110),char(117),char(109),char(86),
-char(97),char(108),char(117),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(75),char(101),char(121),char(115),char(0),char(109),char(95),char(103),char(105),
-char(109),char(112),char(97),char(99),char(116),char(83),char(117),char(98),char(84),char(121),char(112),char(101),char(0),char(42),char(109),char(95),char(117),char(110),char(115),char(99),
-char(97),char(108),char(101),char(100),char(80),char(111),char(105),char(110),char(116),char(115),char(70),char(108),char(111),char(97),char(116),char(80),char(116),char(114),char(0),char(42),
-char(109),char(95),char(117),char(110),char(115),char(99),char(97),char(108),char(101),char(100),char(80),char(111),char(105),char(110),char(116),char(115),char(68),char(111),char(117),char(98),
-char(108),char(101),char(80),char(116),char(114),char(0),char(109),char(95),char(110),char(117),char(109),char(85),char(110),char(115),char(99),char(97),char(108),char(101),char(100),char(80),
-char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(51),char(91),char(52),char(93),char(0),
-char(42),char(109),char(95),char(98),char(114),char(111),char(97),char(100),char(112),char(104),char(97),char(115),char(101),char(72),char(97),char(110),char(100),char(108),char(101),char(0),
-char(42),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(0),char(42),char(109),
-char(95),char(114),char(111),char(111),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(0),
-char(109),char(95),char(119),char(111),char(114),char(108),char(100),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(105),
-char(110),char(116),char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),char(111),char(110),char(87),char(111),char(114),char(108),char(100),char(84),char(114),char(97),
-char(110),char(115),char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),
-char(111),char(110),char(76),char(105),char(110),char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(105),
-char(110),char(116),char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),char(111),char(110),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(86),
-char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(105),char(115),char(111),char(116),char(114),char(111),char(112),char(105),
-char(99),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(99),char(116),char(80),
-char(114),char(111),char(99),char(101),char(115),char(115),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),
-char(95),char(100),char(101),char(97),char(99),char(116),char(105),char(118),char(97),char(116),char(105),char(111),char(110),char(84),char(105),char(109),char(101),char(0),char(109),char(95),
-char(102),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(114),char(111),char(108),char(108),char(105),char(110),char(103),char(70),char(114),
-char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(105),char(116),char(117),char(116),char(105),char(111),char(110),
-char(0),char(109),char(95),char(104),char(105),char(116),char(70),char(114),char(97),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(99),char(100),
-char(83),char(119),char(101),char(112),char(116),char(83),char(112),char(104),char(101),char(114),char(101),char(82),char(97),char(100),char(105),char(117),char(115),char(0),char(109),char(95),
-char(99),char(99),char(100),char(77),char(111),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),
-char(95),char(104),char(97),char(115),char(65),char(110),char(105),char(115),char(111),char(116),char(114),char(111),char(112),char(105),char(99),char(70),char(114),char(105),char(99),char(116),
-char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(70),char(108),char(97),char(103),char(115),
-char(0),char(109),char(95),char(105),char(115),char(108),char(97),char(110),char(100),char(84),char(97),char(103),char(49),char(0),char(109),char(95),char(99),char(111),char(109),char(112),
-char(97),char(110),char(105),char(111),char(110),char(73),char(100),char(0),char(109),char(95),char(97),char(99),char(116),char(105),char(118),char(97),char(116),char(105),char(111),char(110),
-char(83),char(116),char(97),char(116),char(101),char(49),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(110),char(97),char(108),char(84),char(121),char(112),
-char(101),char(0),char(109),char(95),char(99),char(104),char(101),char(99),char(107),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(87),char(105),char(116),char(104),
-char(0),char(109),char(95),char(115),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(0),char(109),char(95),char(103),char(114),char(97),char(118),
-char(105),char(116),char(121),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),
-char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(105),char(110),char(118),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(84),char(101),
-char(110),char(115),char(111),char(114),char(87),char(111),char(114),char(108),char(100),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(86),char(101),
-char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),char(111),
-char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(70),char(97),char(99),char(116),char(111),char(114),
-char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(103),char(114),
-char(97),char(118),char(105),char(116),char(121),char(95),char(97),char(99),char(99),char(101),char(108),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(0),char(109),
-char(95),char(105),char(110),char(118),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(76),char(111),char(99),char(97),char(108),char(0),char(109),char(95),char(116),
-char(111),char(116),char(97),char(108),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(116),char(111),char(116),char(97),char(108),char(84),char(111),char(114),
-char(113),char(117),char(101),char(0),char(109),char(95),char(105),char(110),char(118),char(101),char(114),char(115),char(101),char(77),char(97),char(115),char(115),char(0),char(109),char(95),
-char(108),char(105),char(110),char(101),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(97),char(110),char(103),char(117),
-char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),
-char(110),char(97),char(108),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(97),
-char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(76),char(105),char(110),char(101),char(97),char(114),char(68),char(97),char(109),char(112),char(105),
-char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(83),char(113),char(114),char(0),char(109),char(95),char(97),char(100),char(100),
-char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),
-char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(83),char(113),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105),
-char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),
-char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(108),char(101),char(101),char(112),
-char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),
-char(97),char(114),char(83),char(108),char(101),char(101),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),
-char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),
-char(109),char(95),char(110),char(117),char(109),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(82),char(111),char(119),char(115),char(0),
-char(110),char(117),char(98),char(0),char(42),char(109),char(95),char(114),char(98),char(65),char(0),char(42),char(109),char(95),char(114),char(98),char(66),char(0),char(109),char(95),
-char(111),char(98),char(106),char(101),char(99),char(116),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110),
-char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),
-char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(73),char(100),char(0),char(109),char(95),char(110),char(101),char(101),char(100),char(115),char(70),char(101),
-char(101),char(100),char(98),char(97),char(99),char(107),char(0),char(109),char(95),char(97),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),
-char(108),char(115),char(101),char(0),char(109),char(95),char(100),char(98),char(103),char(68),char(114),char(97),char(119),char(83),char(105),char(122),char(101),char(0),char(109),char(95),
-char(100),char(105),char(115),char(97),char(98),char(108),char(101),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(115),char(66),char(101),char(116),
-char(119),char(101),char(101),char(110),char(76),char(105),char(110),char(107),char(101),char(100),char(66),char(111),char(100),char(105),char(101),char(115),char(0),char(109),char(95),char(111),
-char(118),char(101),char(114),char(114),char(105),char(100),char(101),char(78),char(117),char(109),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(116),char(101),char(114),
-char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(98),char(114),char(101),char(97),char(107),char(105),char(110),char(103),char(73),char(109),char(112),
-char(117),char(108),char(115),char(101),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(105),char(115),char(69),char(110),
-char(97),char(98),char(108),char(101),char(100),char(0),char(109),char(95),char(116),char(121),char(112),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),
-char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(112),char(105),char(118),char(111),char(116),char(73),char(110),char(65),char(0),char(109),char(95),
-char(112),char(105),char(118),char(111),char(116),char(73),char(110),char(66),char(0),char(109),char(95),char(114),char(98),char(65),char(70),char(114),char(97),char(109),char(101),char(0),
-char(109),char(95),char(114),char(98),char(66),char(70),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(117),char(115),char(101),char(82),char(101),char(102),char(101),
-char(114),char(101),char(110),char(99),char(101),char(70),char(114),char(97),char(109),char(101),char(65),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),
-char(114),char(79),char(110),char(108),char(121),char(0),char(109),char(95),char(101),char(110),char(97),char(98),char(108),char(101),char(65),char(110),char(103),char(117),char(108),char(97),
-char(114),char(77),char(111),char(116),char(111),char(114),char(0),char(109),char(95),char(109),char(111),char(116),char(111),char(114),char(84),char(97),char(114),char(103),char(101),char(116),
-char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(109),char(97),char(120),char(77),char(111),char(116),char(111),char(114),char(73),
-char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(108),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),
-char(109),char(95),char(117),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(108),char(105),char(109),char(105),char(116),
-char(83),char(111),char(102),char(116),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(98),char(105),char(97),char(115),char(70),char(97),char(99),char(116),char(111),
-char(114),char(0),char(109),char(95),char(114),char(101),char(108),char(97),char(120),char(97),char(116),char(105),char(111),char(110),char(70),char(97),char(99),char(116),char(111),char(114),
-char(0),char(109),char(95),char(115),char(119),char(105),char(110),char(103),char(83),char(112),char(97),char(110),char(49),char(0),char(109),char(95),char(115),char(119),char(105),char(110),
-char(103),char(83),char(112),char(97),char(110),char(50),char(0),char(109),char(95),char(116),char(119),char(105),char(115),char(116),char(83),char(112),char(97),char(110),char(0),char(109),
-char(95),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(85),char(112),char(112),
-char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(76),char(111),char(119),char(101),
-char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(85),char(112),char(112),char(101),
-char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(76),char(111),char(119),char(101),
-char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(117),char(115),char(101),char(76),char(105),char(110),char(101),char(97),char(114),char(82),char(101),
-char(102),char(101),char(114),char(101),char(110),char(99),char(101),char(70),char(114),char(97),char(109),char(101),char(65),char(0),char(109),char(95),char(117),char(115),char(101),char(79),
-char(102),char(102),char(115),char(101),char(116),char(70),char(111),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(114),
-char(97),char(109),char(101),char(0),char(109),char(95),char(54),char(100),char(111),char(102),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(115),char(112),char(114),
-char(105),char(110),char(103),char(69),char(110),char(97),char(98),char(108),char(101),char(100),char(91),char(54),char(93),char(0),char(109),char(95),char(101),char(113),char(117),char(105),
-char(108),char(105),char(98),char(114),char(105),char(117),char(109),char(80),char(111),char(105),char(110),char(116),char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),
-char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(91),char(54),char(93),char(0),char(109),char(95),char(115),
-char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(91),char(54),char(93),char(0),char(109),char(95),char(116),char(97),
-char(117),char(0),char(109),char(95),char(116),char(105),char(109),char(101),char(83),char(116),char(101),char(112),char(0),char(109),char(95),char(109),char(97),char(120),char(69),char(114),
-char(114),char(111),char(114),char(82),char(101),char(100),char(117),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(115),char(111),char(114),char(0),char(109),
-char(95),char(101),char(114),char(112),char(0),char(109),char(95),char(101),char(114),char(112),char(50),char(0),char(109),char(95),char(103),char(108),char(111),char(98),char(97),char(108),
-char(67),char(102),char(109),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(80),char(101),
-char(110),char(101),char(116),char(114),char(97),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),
-char(95),char(115),char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(84),char(117),char(114),char(110),char(69),char(114),char(112),
-char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(108),char(111),char(112),char(0),char(109),char(95),char(119),char(97),char(114),char(109),
-char(115),char(116),char(97),char(114),char(116),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(109),char(97),char(120),
-char(71),char(121),char(114),char(111),char(115),char(99),char(111),char(112),char(105),char(99),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(115),char(105),
-char(110),char(103),char(108),char(101),char(65),char(120),char(105),char(115),char(82),char(111),char(108),char(108),char(105),char(110),char(103),char(70),char(114),char(105),char(99),char(116),
-char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(110),char(117),char(109),char(73),char(116),
-char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(115),char(111),char(108),char(118),char(101),char(114),char(77),char(111),char(100),
-char(101),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(105),char(110),char(103),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(82),char(101),
-char(115),char(116),char(105),char(116),char(117),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),
-char(95),char(109),char(105),char(110),char(105),char(109),char(117),char(109),char(83),char(111),char(108),char(118),char(101),char(114),char(66),char(97),char(116),char(99),char(104),char(83),
-char(105),char(122),char(101),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),
-char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(97),
-char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(118),char(111),
-char(108),char(117),char(109),char(101),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(42),char(109),char(95),char(109),char(97),char(116),
-char(101),char(114),char(105),char(97),char(108),char(0),char(109),char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(112),
-char(114),char(101),char(118),char(105),char(111),char(117),char(115),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(118),char(101),
-char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(99),char(99),char(117),char(109),char(117),char(108),char(97),char(116),char(101),char(100),
-char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(110),char(111),char(114),char(109),char(97),char(108),char(0),char(109),char(95),char(97),char(114),char(101),
-char(97),char(0),char(109),char(95),char(97),char(116),char(116),char(97),char(99),char(104),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),
-char(105),char(99),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(76),char(101),char(110),char(103),char(116),char(104),
-char(0),char(109),char(95),char(98),char(98),char(101),char(110),char(100),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),
-char(100),char(105),char(99),char(101),char(115),char(91),char(51),char(93),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(65),char(114),char(101),char(97),char(0),
-char(109),char(95),char(99),char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),
-char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(86),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),
-char(99),char(49),char(0),char(109),char(95),char(99),char(50),char(0),char(109),char(95),char(99),char(48),char(0),char(109),char(95),char(108),char(111),char(99),char(97),char(108),
-char(70),char(114),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(114),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(0),char(109),
-char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(97),char(101),char(114),char(111),char(77),char(111),char(100),
-char(101),char(108),char(0),char(109),char(95),char(98),char(97),char(117),char(109),char(103),char(97),char(114),char(116),char(101),char(0),char(109),char(95),char(100),char(114),char(97),
-char(103),char(0),char(109),char(95),char(108),char(105),char(102),char(116),char(0),char(109),char(95),char(112),char(114),char(101),char(115),char(115),char(117),char(114),char(101),char(0),
-char(109),char(95),char(118),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(100),char(121),char(110),char(97),char(109),char(105),char(99),char(70),char(114),
-char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(112),char(111),char(115),char(101),char(77),char(97),char(116),char(99),char(104),char(0),char(109),
-char(95),char(114),char(105),char(103),char(105),char(100),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),
-char(115),char(0),char(109),char(95),char(107),char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(72),char(97),
-char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),
-char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),char(99),char(104),char(111),char(114),char(72),char(97),char(114),
-char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(67),char(108),char(117),
-char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(75),
-char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),
-char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(83),char(111),char(102),char(116),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(72),
-char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(67),
-char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),
-char(95),char(115),char(111),char(102),char(116),char(75),char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),
-char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(83),char(111),
-char(102),char(116),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105),
-char(116),char(0),char(109),char(95),char(109),char(97),char(120),char(86),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(116),char(105),char(109),char(101),
-char(83),char(99),char(97),char(108),char(101),char(0),char(109),char(95),char(118),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(73),char(116),char(101),char(114),
-char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(73),char(116),char(101),
-char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(100),char(114),char(105),char(102),char(116),char(73),char(116),char(101),char(114),char(97),
-char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(116),char(101),char(114),char(97),
-char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(114),char(111),char(116),char(0),char(109),char(95),char(115),char(99),char(97),char(108),char(101),char(0),
-char(109),char(95),char(97),char(113),char(113),char(0),char(109),char(95),char(99),char(111),char(109),char(0),char(42),char(109),char(95),char(112),char(111),char(115),char(105),char(116),
-char(105),char(111),char(110),char(115),char(0),char(42),char(109),char(95),char(119),char(101),char(105),char(103),char(104),char(116),char(115),char(0),char(109),char(95),char(110),char(117),
-char(109),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(87),char(101),char(105),char(103),
-char(116),char(115),char(0),char(109),char(95),char(98),char(118),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(98),char(102),char(114),char(97),char(109),
-char(101),char(0),char(109),char(95),char(102),char(114),char(97),char(109),char(101),char(120),char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(108),char(111),char(99),
-char(105),char(105),char(0),char(109),char(95),char(105),char(110),char(118),char(119),char(105),char(0),char(109),char(95),char(118),char(105),char(109),char(112),char(117),char(108),char(115),
-char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(100),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(91),char(50),char(93),
-char(0),char(109),char(95),char(108),char(118),char(0),char(109),char(95),char(97),char(118),char(0),char(42),char(109),char(95),char(102),char(114),char(97),char(109),char(101),char(114),
-char(101),char(102),char(115),char(0),char(42),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(0),char(42),
-char(109),char(95),char(109),char(97),char(115),char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(70),char(114),char(97),char(109),char(101),char(82),
-char(101),char(102),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(78),char(111),char(100),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),
-char(77),char(97),char(115),char(115),char(101),char(115),char(0),char(109),char(95),char(105),char(100),char(109),char(97),char(115),char(115),char(0),char(109),char(95),char(105),char(109),
-char(97),char(115),char(115),char(0),char(109),char(95),char(110),char(118),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(0),char(109),char(95),char(110),
-char(100),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(100),char(97),char(109),char(112),char(105),char(110),char(103),
-char(0),char(109),char(95),char(108),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(97),char(100),char(97),char(109),char(112),char(105),
-char(110),char(103),char(0),char(109),char(95),char(109),char(97),char(116),char(99),char(104),char(105),char(110),char(103),char(0),char(109),char(95),char(109),char(97),char(120),char(83),
-char(101),char(108),char(102),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),
-char(109),char(95),char(115),char(101),char(108),char(102),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(73),char(109),char(112),char(117),char(108),
-char(115),char(101),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(105),char(110),char(115),char(65),
-char(110),char(99),char(104),char(111),char(114),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(100),char(101),char(0),char(109),char(95),char(99),char(108),
-char(117),char(115),char(116),char(101),char(114),char(73),char(110),char(100),char(101),char(120),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(65),char(0),
-char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(66),char(0),char(109),char(95),char(114),char(101),char(102),char(115),char(91),char(50),char(93),char(0),char(109),
-char(95),char(99),char(102),char(109),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(100),char(101),char(108),char(101),char(116),
-char(101),char(0),char(109),char(95),char(114),char(101),char(108),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(91),char(50),char(93),char(0),char(109),
-char(95),char(98),char(111),char(100),char(121),char(65),char(116),char(121),char(112),char(101),char(0),char(109),char(95),char(98),char(111),char(100),char(121),char(66),char(116),char(121),
-char(112),char(101),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(84),char(121),char(112),char(101),char(0),char(42),char(109),char(95),char(112),char(111),
-char(115),char(101),char(0),char(42),char(42),char(109),char(95),char(109),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(115),char(0),char(42),char(109),char(95),
-char(110),char(111),char(100),char(101),char(115),char(0),char(42),char(109),char(95),char(108),char(105),char(110),char(107),char(115),char(0),char(42),char(109),char(95),char(102),char(97),
-char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(116),char(101),char(116),char(114),char(97),char(104),char(101),char(100),char(114),char(97),char(0),char(42),char(109),
-char(95),char(97),char(110),char(99),char(104),char(111),char(114),char(115),char(0),char(42),char(109),char(95),char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(115),
-char(0),char(42),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(97),char(116),char(101),
-char(114),char(105),char(97),char(108),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(76),char(105),char(110),char(107),char(115),char(0),char(109),char(95),char(110),
-char(117),char(109),char(70),char(97),char(99),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(84),char(101),char(116),char(114),char(97),char(104),char(101),
-char(100),char(114),char(97),char(0),char(109),char(95),char(110),char(117),char(109),char(65),char(110),char(99),char(104),char(111),char(114),char(115),char(0),char(109),char(95),char(110),
-char(117),char(109),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(74),char(111),char(105),char(110),
-char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(110),char(102),char(105),char(103),char(0),char(84),char(89),char(80),char(69),char(76),char(0),char(0),char(0),
-char(99),char(104),char(97),char(114),char(0),char(117),char(99),char(104),char(97),char(114),char(0),char(115),char(104),char(111),char(114),char(116),char(0),char(117),char(115),char(104),
-char(111),char(114),char(116),char(0),char(105),char(110),char(116),char(0),char(108),char(111),char(110),char(103),char(0),char(117),char(108),char(111),char(110),char(103),char(0),char(102),
-char(108),char(111),char(97),char(116),char(0),char(100),char(111),char(117),char(98),char(108),char(101),char(0),char(118),char(111),char(105),char(100),char(0),char(80),char(111),char(105),
-char(110),char(116),char(101),char(114),char(65),char(114),char(114),char(97),char(121),char(0),char(98),char(116),char(80),char(104),char(121),char(115),char(105),char(99),char(115),char(83),
-char(121),char(115),char(116),char(101),char(109),char(0),char(76),char(105),char(115),char(116),char(66),char(97),char(115),char(101),char(0),char(98),char(116),char(86),char(101),char(99),
-char(116),char(111),char(114),char(51),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(86),char(101),char(99),char(116),
-char(111),char(114),char(51),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(97),char(116),char(114),
-char(105),char(120),char(51),char(120),char(51),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(97),char(116),
-char(114),char(105),char(120),char(51),char(120),char(51),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),
-char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),
-char(98),char(116),char(66),char(118),char(104),char(83),char(117),char(98),char(116),char(114),char(101),char(101),char(73),char(110),char(102),char(111),char(68),char(97),char(116),char(97),
-char(0),char(98),char(116),char(79),char(112),char(116),char(105),char(109),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(70),
-char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(79),char(112),char(116),char(105),char(109),char(105),char(122),char(101),char(100),
-char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(68),char(97),char(116),char(97),
-char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(70),char(108),char(111),char(97),char(116),
-char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(68),
-char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),
-char(110),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116),char(97),char(116),char(105),char(99),char(80),
-char(108),char(97),char(110),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(118),
-char(101),char(120),char(73),char(110),char(116),char(101),char(114),char(110),char(97),char(108),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),
-char(98),char(116),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(110),char(100),char(82),char(97),char(100),char(105),char(117),char(115),char(0),
-char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(83),char(112),char(104),char(101),char(114),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),
-char(116),char(97),char(0),char(98),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(83),char(104),char(111),char(114),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(83),char(104),char(111),char(114),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(84),char(114),char(105),char(112),char(108),char(101),char(116),
-char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(104),char(97),char(114),char(73),char(110),char(100),char(101),char(120),char(84),char(114),char(105),char(112),
-char(108),char(101),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(101),char(115),char(104),char(80),char(97),char(114),char(116),char(68),char(97),
-char(116),char(97),char(0),char(98),char(116),char(83),char(116),char(114),char(105),char(100),char(105),char(110),char(103),char(77),char(101),char(115),char(104),char(73),char(110),char(116),
-char(101),char(114),char(102),char(97),char(99),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108),
-char(101),char(77),char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),
-char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(102),char(111),char(77),char(97),char(112),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),
-char(99),char(97),char(108),char(101),char(100),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(77),char(101),char(115),char(104),char(83),char(104),char(97),
-char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(109),char(112),char(111),char(117),char(110),char(100),char(83),char(104),char(97),
-char(112),char(101),char(67),char(104),char(105),char(108),char(100),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(109),char(112),char(111),char(117),
-char(110),char(100),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(121),char(108),char(105),char(110),char(100),
-char(101),char(114),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(97),char(112),char(115),char(117),char(108),
-char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108),
-char(101),char(73),char(110),char(102),char(111),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(73),char(109),char(112),char(97),char(99),char(116),char(77),
-char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(118),char(101),
-char(120),char(72),char(117),char(108),char(108),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),
-char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),
-char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),
-char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(68),char(121),char(110),char(97),char(109),char(105),char(99),char(115),
-char(87),char(111),char(114),char(108),char(100),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),
-char(110),char(116),char(97),char(99),char(116),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(68),char(111),char(117),char(98),char(108),
-char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(68),char(121),char(110),char(97),char(109),char(105),char(99),char(115),char(87),char(111),char(114),char(108),
-char(100),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),
-char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),
-char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),
-char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),
-char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(73),char(110),char(102),char(111),char(49),
-char(0),char(98),char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),
-char(116),char(97),char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(68),char(97),char(116),char(97),char(0),char(98),
-char(116),char(80),char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),
-char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),
-char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),
-char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),
-char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),
-char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),
-char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(84),char(119),char(105),char(115),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),
-char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),
-char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),
-char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(67),char(111),char(110),char(115),char(116),char(114),
-char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(108),char(105),char(100),char(101),char(114),char(67),char(111),char(110),
-char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),
-char(77),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),
-char(121),char(78),char(111),char(100),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(76),char(105),
-char(110),char(107),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(70),char(97),char(99),char(101),char(68),
-char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(84),char(101),char(116),char(114),char(97),char(68),char(97),char(116),
-char(97),char(0),char(83),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(65),char(110),char(99),char(104),char(111),char(114),char(68),char(97),char(116),
-char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(67),char(111),char(110),char(102),char(105),char(103),char(68),char(97),char(116),char(97),
-char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(80),char(111),char(115),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),
-char(102),char(116),char(66),char(111),char(100),char(121),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(74),char(111),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(0),char(0),
-char(84),char(76),char(69),char(78),char(1),char(0),char(1),char(0),char(2),char(0),char(2),char(0),char(4),char(0),char(4),char(0),char(4),char(0),char(4),char(0),
-char(8),char(0),char(0),char(0),char(16),char(0),char(48),char(0),char(16),char(0),char(16),char(0),char(32),char(0),char(48),char(0),char(96),char(0),char(64),char(0),
-char(-128),char(0),char(20),char(0),char(48),char(0),char(80),char(0),char(16),char(0),char(96),char(0),char(-112),char(0),char(16),char(0),char(56),char(0),char(56),char(0),
-char(20),char(0),char(72),char(0),char(4),char(0),char(4),char(0),char(8),char(0),char(4),char(0),char(56),char(0),char(32),char(0),char(80),char(0),char(72),char(0),
-char(96),char(0),char(80),char(0),char(32),char(0),char(64),char(0),char(64),char(0),char(16),char(0),char(72),char(0),char(80),char(0),char(-32),char(1),char(16),char(1),
-char(-72),char(0),char(-104),char(0),char(104),char(0),char(88),char(0),char(-8),char(1),char(-80),char(3),char(8),char(0),char(64),char(0),char(0),char(0),char(96),char(0),
-char(-128),char(0),char(104),char(1),char(-24),char(0),char(-32),char(0),char(8),char(1),char(104),char(1),char(-40),char(0),char(16),char(0),char(104),char(0),char(24),char(0),
-char(40),char(0),char(104),char(0),char(96),char(0),char(104),char(0),char(-56),char(0),char(104),char(1),char(112),char(0),char(-32),char(1),char(83),char(84),char(82),char(67),
-char(65),char(0),char(0),char(0),char(10),char(0),char(3),char(0),char(4),char(0),char(0),char(0),char(4),char(0),char(1),char(0),char(9),char(0),char(2),char(0),
-char(11),char(0),char(3),char(0),char(10),char(0),char(3),char(0),char(10),char(0),char(4),char(0),char(10),char(0),char(5),char(0),char(12),char(0),char(2),char(0),
-char(9),char(0),char(6),char(0),char(9),char(0),char(7),char(0),char(13),char(0),char(1),char(0),char(7),char(0),char(8),char(0),char(14),char(0),char(1),char(0),
-char(8),char(0),char(8),char(0),char(15),char(0),char(1),char(0),char(13),char(0),char(9),char(0),char(16),char(0),char(1),char(0),char(14),char(0),char(9),char(0),
-char(17),char(0),char(2),char(0),char(15),char(0),char(10),char(0),char(13),char(0),char(11),char(0),char(18),char(0),char(2),char(0),char(16),char(0),char(10),char(0),
-char(14),char(0),char(11),char(0),char(19),char(0),char(4),char(0),char(4),char(0),char(12),char(0),char(4),char(0),char(13),char(0),char(2),char(0),char(14),char(0),
-char(2),char(0),char(15),char(0),char(20),char(0),char(6),char(0),char(13),char(0),char(16),char(0),char(13),char(0),char(17),char(0),char(4),char(0),char(18),char(0),
-char(4),char(0),char(19),char(0),char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),char(21),char(0),char(6),char(0),char(14),char(0),char(16),char(0),
-char(14),char(0),char(17),char(0),char(4),char(0),char(18),char(0),char(4),char(0),char(19),char(0),char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),
-char(22),char(0),char(3),char(0),char(2),char(0),char(14),char(0),char(2),char(0),char(15),char(0),char(4),char(0),char(22),char(0),char(23),char(0),char(12),char(0),
-char(13),char(0),char(23),char(0),char(13),char(0),char(24),char(0),char(13),char(0),char(25),char(0),char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),
-char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0),char(20),char(0),char(30),char(0),char(22),char(0),char(31),char(0),char(19),char(0),char(32),char(0),
-char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0),char(24),char(0),char(12),char(0),char(14),char(0),char(23),char(0),char(14),char(0),char(24),char(0),
-char(14),char(0),char(25),char(0),char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0),
-char(21),char(0),char(30),char(0),char(22),char(0),char(31),char(0),char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0),char(19),char(0),char(32),char(0),
-char(25),char(0),char(3),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(36),char(0),char(0),char(0),char(37),char(0),char(26),char(0),char(5),char(0),
-char(25),char(0),char(38),char(0),char(13),char(0),char(39),char(0),char(13),char(0),char(40),char(0),char(7),char(0),char(41),char(0),char(0),char(0),char(21),char(0),
-char(27),char(0),char(5),char(0),char(25),char(0),char(38),char(0),char(13),char(0),char(39),char(0),char(13),char(0),char(42),char(0),char(7),char(0),char(43),char(0),
-char(4),char(0),char(44),char(0),char(28),char(0),char(2),char(0),char(13),char(0),char(45),char(0),char(7),char(0),char(46),char(0),char(29),char(0),char(4),char(0),
-char(27),char(0),char(47),char(0),char(28),char(0),char(48),char(0),char(4),char(0),char(49),char(0),char(0),char(0),char(37),char(0),char(30),char(0),char(1),char(0),
-char(4),char(0),char(50),char(0),char(31),char(0),char(2),char(0),char(2),char(0),char(50),char(0),char(0),char(0),char(51),char(0),char(32),char(0),char(2),char(0),
-char(2),char(0),char(52),char(0),char(0),char(0),char(51),char(0),char(33),char(0),char(2),char(0),char(0),char(0),char(52),char(0),char(0),char(0),char(53),char(0),
-char(34),char(0),char(8),char(0),char(13),char(0),char(54),char(0),char(14),char(0),char(55),char(0),char(30),char(0),char(56),char(0),char(32),char(0),char(57),char(0),
-char(33),char(0),char(58),char(0),char(31),char(0),char(59),char(0),char(4),char(0),char(60),char(0),char(4),char(0),char(61),char(0),char(35),char(0),char(4),char(0),
-char(34),char(0),char(62),char(0),char(13),char(0),char(63),char(0),char(4),char(0),char(64),char(0),char(0),char(0),char(37),char(0),char(36),char(0),char(7),char(0),
-char(25),char(0),char(38),char(0),char(35),char(0),char(65),char(0),char(23),char(0),char(66),char(0),char(24),char(0),char(67),char(0),char(37),char(0),char(68),char(0),
-char(7),char(0),char(43),char(0),char(0),char(0),char(69),char(0),char(38),char(0),char(2),char(0),char(36),char(0),char(70),char(0),char(13),char(0),char(39),char(0),
-char(39),char(0),char(4),char(0),char(17),char(0),char(71),char(0),char(25),char(0),char(72),char(0),char(4),char(0),char(73),char(0),char(7),char(0),char(74),char(0),
-char(40),char(0),char(4),char(0),char(25),char(0),char(38),char(0),char(39),char(0),char(75),char(0),char(4),char(0),char(76),char(0),char(7),char(0),char(43),char(0),
-char(41),char(0),char(3),char(0),char(27),char(0),char(47),char(0),char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0),char(42),char(0),char(3),char(0),
-char(27),char(0),char(47),char(0),char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0),char(43),char(0),char(4),char(0),char(4),char(0),char(78),char(0),
-char(7),char(0),char(79),char(0),char(7),char(0),char(80),char(0),char(7),char(0),char(81),char(0),char(37),char(0),char(14),char(0),char(4),char(0),char(82),char(0),
-char(4),char(0),char(83),char(0),char(43),char(0),char(84),char(0),char(4),char(0),char(85),char(0),char(7),char(0),char(86),char(0),char(7),char(0),char(87),char(0),
-char(7),char(0),char(88),char(0),char(7),char(0),char(89),char(0),char(7),char(0),char(90),char(0),char(4),char(0),char(91),char(0),char(4),char(0),char(92),char(0),
-char(4),char(0),char(93),char(0),char(4),char(0),char(94),char(0),char(0),char(0),char(37),char(0),char(44),char(0),char(5),char(0),char(25),char(0),char(38),char(0),
-char(35),char(0),char(65),char(0),char(13),char(0),char(39),char(0),char(7),char(0),char(43),char(0),char(4),char(0),char(95),char(0),char(45),char(0),char(5),char(0),
-char(27),char(0),char(47),char(0),char(13),char(0),char(96),char(0),char(14),char(0),char(97),char(0),char(4),char(0),char(98),char(0),char(0),char(0),char(99),char(0),
-char(46),char(0),char(25),char(0),char(9),char(0),char(100),char(0),char(9),char(0),char(101),char(0),char(25),char(0),char(102),char(0),char(0),char(0),char(35),char(0),
-char(18),char(0),char(103),char(0),char(18),char(0),char(104),char(0),char(14),char(0),char(105),char(0),char(14),char(0),char(106),char(0),char(14),char(0),char(107),char(0),
-char(8),char(0),char(108),char(0),char(8),char(0),char(109),char(0),char(8),char(0),char(110),char(0),char(8),char(0),char(111),char(0),char(8),char(0),char(112),char(0),
-char(8),char(0),char(113),char(0),char(8),char(0),char(114),char(0),char(8),char(0),char(115),char(0),char(4),char(0),char(116),char(0),char(4),char(0),char(117),char(0),
-char(4),char(0),char(118),char(0),char(4),char(0),char(119),char(0),char(4),char(0),char(120),char(0),char(4),char(0),char(121),char(0),char(4),char(0),char(122),char(0),
-char(0),char(0),char(37),char(0),char(47),char(0),char(25),char(0),char(9),char(0),char(100),char(0),char(9),char(0),char(101),char(0),char(25),char(0),char(102),char(0),
-char(0),char(0),char(35),char(0),char(17),char(0),char(103),char(0),char(17),char(0),char(104),char(0),char(13),char(0),char(105),char(0),char(13),char(0),char(106),char(0),
-char(13),char(0),char(107),char(0),char(7),char(0),char(108),char(0),char(7),char(0),char(109),char(0),char(7),char(0),char(110),char(0),char(7),char(0),char(111),char(0),
-char(7),char(0),char(112),char(0),char(7),char(0),char(113),char(0),char(7),char(0),char(114),char(0),char(7),char(0),char(115),char(0),char(4),char(0),char(116),char(0),
-char(4),char(0),char(117),char(0),char(4),char(0),char(118),char(0),char(4),char(0),char(119),char(0),char(4),char(0),char(120),char(0),char(4),char(0),char(121),char(0),
-char(4),char(0),char(122),char(0),char(0),char(0),char(37),char(0),char(48),char(0),char(2),char(0),char(49),char(0),char(123),char(0),char(14),char(0),char(124),char(0),
-char(50),char(0),char(2),char(0),char(51),char(0),char(123),char(0),char(13),char(0),char(124),char(0),char(52),char(0),char(21),char(0),char(47),char(0),char(125),char(0),
-char(15),char(0),char(126),char(0),char(13),char(0),char(127),char(0),char(13),char(0),char(-128),char(0),char(13),char(0),char(-127),char(0),char(13),char(0),char(-126),char(0),
-char(13),char(0),char(124),char(0),char(13),char(0),char(-125),char(0),char(13),char(0),char(-124),char(0),char(13),char(0),char(-123),char(0),char(13),char(0),char(-122),char(0),
-char(7),char(0),char(-121),char(0),char(7),char(0),char(-120),char(0),char(7),char(0),char(-119),char(0),char(7),char(0),char(-118),char(0),char(7),char(0),char(-117),char(0),
-char(7),char(0),char(-116),char(0),char(7),char(0),char(-115),char(0),char(7),char(0),char(-114),char(0),char(7),char(0),char(-113),char(0),char(4),char(0),char(-112),char(0),
-char(53),char(0),char(22),char(0),char(46),char(0),char(125),char(0),char(16),char(0),char(126),char(0),char(14),char(0),char(127),char(0),char(14),char(0),char(-128),char(0),
-char(14),char(0),char(-127),char(0),char(14),char(0),char(-126),char(0),char(14),char(0),char(124),char(0),char(14),char(0),char(-125),char(0),char(14),char(0),char(-124),char(0),
-char(14),char(0),char(-123),char(0),char(14),char(0),char(-122),char(0),char(8),char(0),char(-121),char(0),char(8),char(0),char(-120),char(0),char(8),char(0),char(-119),char(0),
-char(8),char(0),char(-118),char(0),char(8),char(0),char(-117),char(0),char(8),char(0),char(-116),char(0),char(8),char(0),char(-115),char(0),char(8),char(0),char(-114),char(0),
-char(8),char(0),char(-113),char(0),char(4),char(0),char(-112),char(0),char(0),char(0),char(37),char(0),char(54),char(0),char(2),char(0),char(4),char(0),char(-111),char(0),
-char(4),char(0),char(-110),char(0),char(55),char(0),char(13),char(0),char(56),char(0),char(-109),char(0),char(56),char(0),char(-108),char(0),char(0),char(0),char(35),char(0),
-char(4),char(0),char(-107),char(0),char(4),char(0),char(-106),char(0),char(4),char(0),char(-105),char(0),char(4),char(0),char(-104),char(0),char(7),char(0),char(-103),char(0),
-char(7),char(0),char(-102),char(0),char(4),char(0),char(-101),char(0),char(4),char(0),char(-100),char(0),char(7),char(0),char(-99),char(0),char(4),char(0),char(-98),char(0),
-char(57),char(0),char(3),char(0),char(55),char(0),char(-97),char(0),char(13),char(0),char(-96),char(0),char(13),char(0),char(-95),char(0),char(58),char(0),char(3),char(0),
-char(55),char(0),char(-97),char(0),char(14),char(0),char(-96),char(0),char(14),char(0),char(-95),char(0),char(59),char(0),char(13),char(0),char(55),char(0),char(-97),char(0),
-char(18),char(0),char(-94),char(0),char(18),char(0),char(-93),char(0),char(4),char(0),char(-92),char(0),char(4),char(0),char(-91),char(0),char(4),char(0),char(-90),char(0),
-char(7),char(0),char(-89),char(0),char(7),char(0),char(-88),char(0),char(7),char(0),char(-87),char(0),char(7),char(0),char(-86),char(0),char(7),char(0),char(-85),char(0),
-char(7),char(0),char(-84),char(0),char(7),char(0),char(-83),char(0),char(60),char(0),char(13),char(0),char(55),char(0),char(-97),char(0),char(17),char(0),char(-94),char(0),
-char(17),char(0),char(-93),char(0),char(4),char(0),char(-92),char(0),char(4),char(0),char(-91),char(0),char(4),char(0),char(-90),char(0),char(7),char(0),char(-89),char(0),
-char(7),char(0),char(-88),char(0),char(7),char(0),char(-87),char(0),char(7),char(0),char(-86),char(0),char(7),char(0),char(-85),char(0),char(7),char(0),char(-84),char(0),
-char(7),char(0),char(-83),char(0),char(61),char(0),char(11),char(0),char(55),char(0),char(-97),char(0),char(17),char(0),char(-94),char(0),char(17),char(0),char(-93),char(0),
-char(7),char(0),char(-82),char(0),char(7),char(0),char(-81),char(0),char(7),char(0),char(-80),char(0),char(7),char(0),char(-85),char(0),char(7),char(0),char(-84),char(0),
-char(7),char(0),char(-83),char(0),char(7),char(0),char(-79),char(0),char(0),char(0),char(21),char(0),char(62),char(0),char(9),char(0),char(55),char(0),char(-97),char(0),
-char(17),char(0),char(-94),char(0),char(17),char(0),char(-93),char(0),char(13),char(0),char(-78),char(0),char(13),char(0),char(-77),char(0),char(13),char(0),char(-76),char(0),
-char(13),char(0),char(-75),char(0),char(4),char(0),char(-74),char(0),char(4),char(0),char(-73),char(0),char(63),char(0),char(5),char(0),char(62),char(0),char(-72),char(0),
-char(4),char(0),char(-71),char(0),char(7),char(0),char(-70),char(0),char(7),char(0),char(-69),char(0),char(7),char(0),char(-68),char(0),char(64),char(0),char(9),char(0),
-char(55),char(0),char(-97),char(0),char(17),char(0),char(-94),char(0),char(17),char(0),char(-93),char(0),char(7),char(0),char(-78),char(0),char(7),char(0),char(-77),char(0),
-char(7),char(0),char(-76),char(0),char(7),char(0),char(-75),char(0),char(4),char(0),char(-74),char(0),char(4),char(0),char(-73),char(0),char(49),char(0),char(22),char(0),
-char(8),char(0),char(-67),char(0),char(8),char(0),char(-79),char(0),char(8),char(0),char(110),char(0),char(8),char(0),char(-66),char(0),char(8),char(0),char(112),char(0),
-char(8),char(0),char(-65),char(0),char(8),char(0),char(-64),char(0),char(8),char(0),char(-63),char(0),char(8),char(0),char(-62),char(0),char(8),char(0),char(-61),char(0),
-char(8),char(0),char(-60),char(0),char(8),char(0),char(-59),char(0),char(8),char(0),char(-58),char(0),char(8),char(0),char(-57),char(0),char(8),char(0),char(-56),char(0),
-char(8),char(0),char(-55),char(0),char(4),char(0),char(-54),char(0),char(4),char(0),char(-53),char(0),char(4),char(0),char(-52),char(0),char(4),char(0),char(-51),char(0),
-char(4),char(0),char(-50),char(0),char(0),char(0),char(37),char(0),char(51),char(0),char(22),char(0),char(7),char(0),char(-67),char(0),char(7),char(0),char(-79),char(0),
-char(7),char(0),char(110),char(0),char(7),char(0),char(-66),char(0),char(7),char(0),char(112),char(0),char(7),char(0),char(-65),char(0),char(7),char(0),char(-64),char(0),
-char(7),char(0),char(-63),char(0),char(7),char(0),char(-62),char(0),char(7),char(0),char(-61),char(0),char(7),char(0),char(-60),char(0),char(7),char(0),char(-59),char(0),
-char(7),char(0),char(-58),char(0),char(7),char(0),char(-57),char(0),char(7),char(0),char(-56),char(0),char(7),char(0),char(-55),char(0),char(4),char(0),char(-54),char(0),
-char(4),char(0),char(-53),char(0),char(4),char(0),char(-52),char(0),char(4),char(0),char(-51),char(0),char(4),char(0),char(-50),char(0),char(0),char(0),char(37),char(0),
-char(65),char(0),char(4),char(0),char(7),char(0),char(-49),char(0),char(7),char(0),char(-48),char(0),char(7),char(0),char(-47),char(0),char(4),char(0),char(78),char(0),
-char(66),char(0),char(10),char(0),char(65),char(0),char(-46),char(0),char(13),char(0),char(-45),char(0),char(13),char(0),char(-44),char(0),char(13),char(0),char(-43),char(0),
-char(13),char(0),char(-42),char(0),char(13),char(0),char(-41),char(0),char(7),char(0),char(-121),char(0),char(7),char(0),char(-40),char(0),char(4),char(0),char(-39),char(0),
-char(4),char(0),char(53),char(0),char(67),char(0),char(4),char(0),char(65),char(0),char(-46),char(0),char(4),char(0),char(-38),char(0),char(7),char(0),char(-37),char(0),
-char(4),char(0),char(-36),char(0),char(68),char(0),char(4),char(0),char(13),char(0),char(-41),char(0),char(65),char(0),char(-46),char(0),char(4),char(0),char(-35),char(0),
-char(7),char(0),char(-34),char(0),char(69),char(0),char(7),char(0),char(13),char(0),char(-33),char(0),char(65),char(0),char(-46),char(0),char(4),char(0),char(-32),char(0),
-char(7),char(0),char(-31),char(0),char(7),char(0),char(-30),char(0),char(7),char(0),char(-29),char(0),char(4),char(0),char(53),char(0),char(70),char(0),char(6),char(0),
-char(15),char(0),char(-28),char(0),char(13),char(0),char(-30),char(0),char(13),char(0),char(-27),char(0),char(56),char(0),char(-26),char(0),char(4),char(0),char(-25),char(0),
-char(7),char(0),char(-29),char(0),char(71),char(0),char(26),char(0),char(4),char(0),char(-24),char(0),char(7),char(0),char(-23),char(0),char(7),char(0),char(-79),char(0),
-char(7),char(0),char(-22),char(0),char(7),char(0),char(-21),char(0),char(7),char(0),char(-20),char(0),char(7),char(0),char(-19),char(0),char(7),char(0),char(-18),char(0),
-char(7),char(0),char(-17),char(0),char(7),char(0),char(-16),char(0),char(7),char(0),char(-15),char(0),char(7),char(0),char(-14),char(0),char(7),char(0),char(-13),char(0),
-char(7),char(0),char(-12),char(0),char(7),char(0),char(-11),char(0),char(7),char(0),char(-10),char(0),char(7),char(0),char(-9),char(0),char(7),char(0),char(-8),char(0),
-char(7),char(0),char(-7),char(0),char(7),char(0),char(-6),char(0),char(7),char(0),char(-5),char(0),char(4),char(0),char(-4),char(0),char(4),char(0),char(-3),char(0),
-char(4),char(0),char(-2),char(0),char(4),char(0),char(-1),char(0),char(4),char(0),char(117),char(0),char(72),char(0),char(12),char(0),char(15),char(0),char(0),char(1),
-char(15),char(0),char(1),char(1),char(15),char(0),char(2),char(1),char(13),char(0),char(3),char(1),char(13),char(0),char(4),char(1),char(7),char(0),char(5),char(1),
-char(4),char(0),char(6),char(1),char(4),char(0),char(7),char(1),char(4),char(0),char(8),char(1),char(4),char(0),char(9),char(1),char(7),char(0),char(-31),char(0),
-char(4),char(0),char(53),char(0),char(73),char(0),char(27),char(0),char(17),char(0),char(10),char(1),char(15),char(0),char(11),char(1),char(15),char(0),char(12),char(1),
-char(13),char(0),char(3),char(1),char(13),char(0),char(13),char(1),char(13),char(0),char(14),char(1),char(13),char(0),char(15),char(1),char(13),char(0),char(16),char(1),
-char(13),char(0),char(17),char(1),char(4),char(0),char(18),char(1),char(7),char(0),char(19),char(1),char(4),char(0),char(20),char(1),char(4),char(0),char(21),char(1),
-char(4),char(0),char(22),char(1),char(7),char(0),char(23),char(1),char(7),char(0),char(24),char(1),char(4),char(0),char(25),char(1),char(4),char(0),char(26),char(1),
-char(7),char(0),char(27),char(1),char(7),char(0),char(28),char(1),char(7),char(0),char(29),char(1),char(7),char(0),char(30),char(1),char(7),char(0),char(31),char(1),
-char(7),char(0),char(32),char(1),char(4),char(0),char(33),char(1),char(4),char(0),char(34),char(1),char(4),char(0),char(35),char(1),char(74),char(0),char(12),char(0),
-char(9),char(0),char(36),char(1),char(9),char(0),char(37),char(1),char(13),char(0),char(38),char(1),char(7),char(0),char(39),char(1),char(7),char(0),char(-63),char(0),
-char(7),char(0),char(40),char(1),char(4),char(0),char(41),char(1),char(13),char(0),char(42),char(1),char(4),char(0),char(43),char(1),char(4),char(0),char(44),char(1),
-char(4),char(0),char(45),char(1),char(4),char(0),char(53),char(0),char(75),char(0),char(19),char(0),char(47),char(0),char(125),char(0),char(72),char(0),char(46),char(1),
-char(65),char(0),char(47),char(1),char(66),char(0),char(48),char(1),char(67),char(0),char(49),char(1),char(68),char(0),char(50),char(1),char(69),char(0),char(51),char(1),
-char(70),char(0),char(52),char(1),char(73),char(0),char(53),char(1),char(74),char(0),char(54),char(1),char(4),char(0),char(55),char(1),char(4),char(0),char(21),char(1),
-char(4),char(0),char(56),char(1),char(4),char(0),char(57),char(1),char(4),char(0),char(58),char(1),char(4),char(0),char(59),char(1),char(4),char(0),char(60),char(1),
-char(4),char(0),char(61),char(1),char(71),char(0),char(62),char(1),};
-int b3s_bulletDNAlen64= sizeof(b3s_bulletDNAstr64);
+char b3s_bulletDNAstr[] = {
+ char(83),
+ char(68),
+ char(78),
+ char(65),
+ char(78),
+ char(65),
+ char(77),
+ char(69),
+ char(63),
+ char(1),
+ char(0),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(105),
+ char(122),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(97),
+ char(112),
+ char(97),
+ char(99),
+ char(105),
+ char(116),
+ char(121),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(100),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(111),
+ char(108),
+ char(108),
+ char(105),
+ char(115),
+ char(105),
+ char(111),
+ char(110),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(111),
+ char(108),
+ char(108),
+ char(105),
+ char(115),
+ char(105),
+ char(111),
+ char(110),
+ char(79),
+ char(98),
+ char(106),
+ char(101),
+ char(99),
+ char(116),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(111),
+ char(110),
+ char(115),
+ char(116),
+ char(114),
+ char(97),
+ char(105),
+ char(110),
+ char(116),
+ char(115),
+ char(0),
+ char(42),
+ char(102),
+ char(105),
+ char(114),
+ char(115),
+ char(116),
+ char(0),
+ char(42),
+ char(108),
+ char(97),
+ char(115),
+ char(116),
+ char(0),
+ char(109),
+ char(95),
+ char(102),
+ char(108),
+ char(111),
+ char(97),
+ char(116),
+ char(115),
+ char(91),
+ char(52),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(101),
+ char(108),
+ char(91),
+ char(51),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(98),
+ char(97),
+ char(115),
+ char(105),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(111),
+ char(114),
+ char(105),
+ char(103),
+ char(105),
+ char(110),
+ char(0),
+ char(109),
+ char(95),
+ char(114),
+ char(111),
+ char(111),
+ char(116),
+ char(78),
+ char(111),
+ char(100),
+ char(101),
+ char(73),
+ char(110),
+ char(100),
+ char(101),
+ char(120),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(117),
+ char(98),
+ char(116),
+ char(114),
+ char(101),
+ char(101),
+ char(83),
+ char(105),
+ char(122),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(113),
+ char(117),
+ char(97),
+ char(110),
+ char(116),
+ char(105),
+ char(122),
+ char(101),
+ char(100),
+ char(65),
+ char(97),
+ char(98),
+ char(98),
+ char(77),
+ char(105),
+ char(110),
+ char(91),
+ char(51),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(113),
+ char(117),
+ char(97),
+ char(110),
+ char(116),
+ char(105),
+ char(122),
+ char(101),
+ char(100),
+ char(65),
+ char(97),
+ char(98),
+ char(98),
+ char(77),
+ char(97),
+ char(120),
+ char(91),
+ char(51),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(97),
+ char(98),
+ char(98),
+ char(77),
+ char(105),
+ char(110),
+ char(79),
+ char(114),
+ char(103),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(97),
+ char(98),
+ char(98),
+ char(77),
+ char(97),
+ char(120),
+ char(79),
+ char(114),
+ char(103),
+ char(0),
+ char(109),
+ char(95),
+ char(101),
+ char(115),
+ char(99),
+ char(97),
+ char(112),
+ char(101),
+ char(73),
+ char(110),
+ char(100),
+ char(101),
+ char(120),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(117),
+ char(98),
+ char(80),
+ char(97),
+ char(114),
+ char(116),
+ char(0),
+ char(109),
+ char(95),
+ char(116),
+ char(114),
+ char(105),
+ char(97),
+ char(110),
+ char(103),
+ char(108),
+ char(101),
+ char(73),
+ char(110),
+ char(100),
+ char(101),
+ char(120),
+ char(0),
+ char(109),
+ char(95),
+ char(112),
+ char(97),
+ char(100),
+ char(91),
+ char(52),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(101),
+ char(115),
+ char(99),
+ char(97),
+ char(112),
+ char(101),
+ char(73),
+ char(110),
+ char(100),
+ char(101),
+ char(120),
+ char(79),
+ char(114),
+ char(84),
+ char(114),
+ char(105),
+ char(97),
+ char(110),
+ char(103),
+ char(108),
+ char(101),
+ char(73),
+ char(110),
+ char(100),
+ char(101),
+ char(120),
+ char(0),
+ char(109),
+ char(95),
+ char(98),
+ char(118),
+ char(104),
+ char(65),
+ char(97),
+ char(98),
+ char(98),
+ char(77),
+ char(105),
+ char(110),
+ char(0),
+ char(109),
+ char(95),
+ char(98),
+ char(118),
+ char(104),
+ char(65),
+ char(97),
+ char(98),
+ char(98),
+ char(77),
+ char(97),
+ char(120),
+ char(0),
+ char(109),
+ char(95),
+ char(98),
+ char(118),
+ char(104),
+ char(81),
+ char(117),
+ char(97),
+ char(110),
+ char(116),
+ char(105),
+ char(122),
+ char(97),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(117),
+ char(114),
+ char(78),
+ char(111),
+ char(100),
+ char(101),
+ char(73),
+ char(110),
+ char(100),
+ char(101),
+ char(120),
+ char(0),
+ char(109),
+ char(95),
+ char(117),
+ char(115),
+ char(101),
+ char(81),
+ char(117),
+ char(97),
+ char(110),
+ char(116),
+ char(105),
+ char(122),
+ char(97),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(67),
+ char(111),
+ char(110),
+ char(116),
+ char(105),
+ char(103),
+ char(117),
+ char(111),
+ char(117),
+ char(115),
+ char(76),
+ char(101),
+ char(97),
+ char(102),
+ char(78),
+ char(111),
+ char(100),
+ char(101),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(81),
+ char(117),
+ char(97),
+ char(110),
+ char(116),
+ char(105),
+ char(122),
+ char(101),
+ char(100),
+ char(67),
+ char(111),
+ char(110),
+ char(116),
+ char(105),
+ char(103),
+ char(117),
+ char(111),
+ char(117),
+ char(115),
+ char(78),
+ char(111),
+ char(100),
+ char(101),
+ char(115),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(99),
+ char(111),
+ char(110),
+ char(116),
+ char(105),
+ char(103),
+ char(117),
+ char(111),
+ char(117),
+ char(115),
+ char(78),
+ char(111),
+ char(100),
+ char(101),
+ char(115),
+ char(80),
+ char(116),
+ char(114),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(113),
+ char(117),
+ char(97),
+ char(110),
+ char(116),
+ char(105),
+ char(122),
+ char(101),
+ char(100),
+ char(67),
+ char(111),
+ char(110),
+ char(116),
+ char(105),
+ char(103),
+ char(117),
+ char(111),
+ char(117),
+ char(115),
+ char(78),
+ char(111),
+ char(100),
+ char(101),
+ char(115),
+ char(80),
+ char(116),
+ char(114),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(115),
+ char(117),
+ char(98),
+ char(84),
+ char(114),
+ char(101),
+ char(101),
+ char(73),
+ char(110),
+ char(102),
+ char(111),
+ char(80),
+ char(116),
+ char(114),
+ char(0),
+ char(109),
+ char(95),
+ char(116),
+ char(114),
+ char(97),
+ char(118),
+ char(101),
+ char(114),
+ char(115),
+ char(97),
+ char(108),
+ char(77),
+ char(111),
+ char(100),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(83),
+ char(117),
+ char(98),
+ char(116),
+ char(114),
+ char(101),
+ char(101),
+ char(72),
+ char(101),
+ char(97),
+ char(100),
+ char(101),
+ char(114),
+ char(115),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(110),
+ char(97),
+ char(109),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(84),
+ char(121),
+ char(112),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(112),
+ char(97),
+ char(100),
+ char(100),
+ char(105),
+ char(110),
+ char(103),
+ char(91),
+ char(52),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(111),
+ char(108),
+ char(108),
+ char(105),
+ char(115),
+ char(105),
+ char(111),
+ char(110),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(109),
+ char(95),
+ char(108),
+ char(111),
+ char(99),
+ char(97),
+ char(108),
+ char(83),
+ char(99),
+ char(97),
+ char(108),
+ char(105),
+ char(110),
+ char(103),
+ char(0),
+ char(109),
+ char(95),
+ char(112),
+ char(108),
+ char(97),
+ char(110),
+ char(101),
+ char(78),
+ char(111),
+ char(114),
+ char(109),
+ char(97),
+ char(108),
+ char(0),
+ char(109),
+ char(95),
+ char(112),
+ char(108),
+ char(97),
+ char(110),
+ char(101),
+ char(67),
+ char(111),
+ char(110),
+ char(115),
+ char(116),
+ char(97),
+ char(110),
+ char(116),
+ char(0),
+ char(109),
+ char(95),
+ char(105),
+ char(109),
+ char(112),
+ char(108),
+ char(105),
+ char(99),
+ char(105),
+ char(116),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(68),
+ char(105),
+ char(109),
+ char(101),
+ char(110),
+ char(115),
+ char(105),
+ char(111),
+ char(110),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(111),
+ char(108),
+ char(108),
+ char(105),
+ char(115),
+ char(105),
+ char(111),
+ char(110),
+ char(77),
+ char(97),
+ char(114),
+ char(103),
+ char(105),
+ char(110),
+ char(0),
+ char(109),
+ char(95),
+ char(112),
+ char(97),
+ char(100),
+ char(100),
+ char(105),
+ char(110),
+ char(103),
+ char(0),
+ char(109),
+ char(95),
+ char(112),
+ char(111),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(114),
+ char(97),
+ char(100),
+ char(105),
+ char(117),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(111),
+ char(110),
+ char(118),
+ char(101),
+ char(120),
+ char(73),
+ char(110),
+ char(116),
+ char(101),
+ char(114),
+ char(110),
+ char(97),
+ char(108),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(108),
+ char(111),
+ char(99),
+ char(97),
+ char(108),
+ char(80),
+ char(111),
+ char(115),
+ char(105),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(65),
+ char(114),
+ char(114),
+ char(97),
+ char(121),
+ char(80),
+ char(116),
+ char(114),
+ char(0),
+ char(109),
+ char(95),
+ char(108),
+ char(111),
+ char(99),
+ char(97),
+ char(108),
+ char(80),
+ char(111),
+ char(115),
+ char(105),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(65),
+ char(114),
+ char(114),
+ char(97),
+ char(121),
+ char(83),
+ char(105),
+ char(122),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(118),
+ char(97),
+ char(108),
+ char(117),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(112),
+ char(97),
+ char(100),
+ char(91),
+ char(50),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(118),
+ char(97),
+ char(108),
+ char(117),
+ char(101),
+ char(115),
+ char(91),
+ char(51),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(112),
+ char(97),
+ char(100),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(118),
+ char(101),
+ char(114),
+ char(116),
+ char(105),
+ char(99),
+ char(101),
+ char(115),
+ char(51),
+ char(102),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(118),
+ char(101),
+ char(114),
+ char(116),
+ char(105),
+ char(99),
+ char(101),
+ char(115),
+ char(51),
+ char(100),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(105),
+ char(110),
+ char(100),
+ char(105),
+ char(99),
+ char(101),
+ char(115),
+ char(51),
+ char(50),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(51),
+ char(105),
+ char(110),
+ char(100),
+ char(105),
+ char(99),
+ char(101),
+ char(115),
+ char(49),
+ char(54),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(51),
+ char(105),
+ char(110),
+ char(100),
+ char(105),
+ char(99),
+ char(101),
+ char(115),
+ char(56),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(105),
+ char(110),
+ char(100),
+ char(105),
+ char(99),
+ char(101),
+ char(115),
+ char(49),
+ char(54),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(84),
+ char(114),
+ char(105),
+ char(97),
+ char(110),
+ char(103),
+ char(108),
+ char(101),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(86),
+ char(101),
+ char(114),
+ char(116),
+ char(105),
+ char(99),
+ char(101),
+ char(115),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(109),
+ char(101),
+ char(115),
+ char(104),
+ char(80),
+ char(97),
+ char(114),
+ char(116),
+ char(115),
+ char(80),
+ char(116),
+ char(114),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(99),
+ char(97),
+ char(108),
+ char(105),
+ char(110),
+ char(103),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(77),
+ char(101),
+ char(115),
+ char(104),
+ char(80),
+ char(97),
+ char(114),
+ char(116),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(109),
+ char(101),
+ char(115),
+ char(104),
+ char(73),
+ char(110),
+ char(116),
+ char(101),
+ char(114),
+ char(102),
+ char(97),
+ char(99),
+ char(101),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(113),
+ char(117),
+ char(97),
+ char(110),
+ char(116),
+ char(105),
+ char(122),
+ char(101),
+ char(100),
+ char(70),
+ char(108),
+ char(111),
+ char(97),
+ char(116),
+ char(66),
+ char(118),
+ char(104),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(113),
+ char(117),
+ char(97),
+ char(110),
+ char(116),
+ char(105),
+ char(122),
+ char(101),
+ char(100),
+ char(68),
+ char(111),
+ char(117),
+ char(98),
+ char(108),
+ char(101),
+ char(66),
+ char(118),
+ char(104),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(116),
+ char(114),
+ char(105),
+ char(97),
+ char(110),
+ char(103),
+ char(108),
+ char(101),
+ char(73),
+ char(110),
+ char(102),
+ char(111),
+ char(77),
+ char(97),
+ char(112),
+ char(0),
+ char(109),
+ char(95),
+ char(112),
+ char(97),
+ char(100),
+ char(51),
+ char(91),
+ char(52),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(116),
+ char(114),
+ char(105),
+ char(109),
+ char(101),
+ char(115),
+ char(104),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(109),
+ char(95),
+ char(116),
+ char(114),
+ char(97),
+ char(110),
+ char(115),
+ char(102),
+ char(111),
+ char(114),
+ char(109),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(99),
+ char(104),
+ char(105),
+ char(108),
+ char(100),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(104),
+ char(105),
+ char(108),
+ char(100),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(84),
+ char(121),
+ char(112),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(104),
+ char(105),
+ char(108),
+ char(100),
+ char(77),
+ char(97),
+ char(114),
+ char(103),
+ char(105),
+ char(110),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(99),
+ char(104),
+ char(105),
+ char(108),
+ char(100),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(80),
+ char(116),
+ char(114),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(67),
+ char(104),
+ char(105),
+ char(108),
+ char(100),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(117),
+ char(112),
+ char(65),
+ char(120),
+ char(105),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(102),
+ char(108),
+ char(97),
+ char(103),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(101),
+ char(100),
+ char(103),
+ char(101),
+ char(86),
+ char(48),
+ char(86),
+ char(49),
+ char(65),
+ char(110),
+ char(103),
+ char(108),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(101),
+ char(100),
+ char(103),
+ char(101),
+ char(86),
+ char(49),
+ char(86),
+ char(50),
+ char(65),
+ char(110),
+ char(103),
+ char(108),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(101),
+ char(100),
+ char(103),
+ char(101),
+ char(86),
+ char(50),
+ char(86),
+ char(48),
+ char(65),
+ char(110),
+ char(103),
+ char(108),
+ char(101),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(104),
+ char(97),
+ char(115),
+ char(104),
+ char(84),
+ char(97),
+ char(98),
+ char(108),
+ char(101),
+ char(80),
+ char(116),
+ char(114),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(110),
+ char(101),
+ char(120),
+ char(116),
+ char(80),
+ char(116),
+ char(114),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(118),
+ char(97),
+ char(108),
+ char(117),
+ char(101),
+ char(65),
+ char(114),
+ char(114),
+ char(97),
+ char(121),
+ char(80),
+ char(116),
+ char(114),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(107),
+ char(101),
+ char(121),
+ char(65),
+ char(114),
+ char(114),
+ char(97),
+ char(121),
+ char(80),
+ char(116),
+ char(114),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(111),
+ char(110),
+ char(118),
+ char(101),
+ char(120),
+ char(69),
+ char(112),
+ char(115),
+ char(105),
+ char(108),
+ char(111),
+ char(110),
+ char(0),
+ char(109),
+ char(95),
+ char(112),
+ char(108),
+ char(97),
+ char(110),
+ char(97),
+ char(114),
+ char(69),
+ char(112),
+ char(115),
+ char(105),
+ char(108),
+ char(111),
+ char(110),
+ char(0),
+ char(109),
+ char(95),
+ char(101),
+ char(113),
+ char(117),
+ char(97),
+ char(108),
+ char(86),
+ char(101),
+ char(114),
+ char(116),
+ char(101),
+ char(120),
+ char(84),
+ char(104),
+ char(114),
+ char(101),
+ char(115),
+ char(104),
+ char(111),
+ char(108),
+ char(100),
+ char(0),
+ char(109),
+ char(95),
+ char(101),
+ char(100),
+ char(103),
+ char(101),
+ char(68),
+ char(105),
+ char(115),
+ char(116),
+ char(97),
+ char(110),
+ char(99),
+ char(101),
+ char(84),
+ char(104),
+ char(114),
+ char(101),
+ char(115),
+ char(104),
+ char(111),
+ char(108),
+ char(100),
+ char(0),
+ char(109),
+ char(95),
+ char(122),
+ char(101),
+ char(114),
+ char(111),
+ char(65),
+ char(114),
+ char(101),
+ char(97),
+ char(84),
+ char(104),
+ char(114),
+ char(101),
+ char(115),
+ char(104),
+ char(111),
+ char(108),
+ char(100),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(101),
+ char(120),
+ char(116),
+ char(83),
+ char(105),
+ char(122),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(104),
+ char(97),
+ char(115),
+ char(104),
+ char(84),
+ char(97),
+ char(98),
+ char(108),
+ char(101),
+ char(83),
+ char(105),
+ char(122),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(86),
+ char(97),
+ char(108),
+ char(117),
+ char(101),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(75),
+ char(101),
+ char(121),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(103),
+ char(105),
+ char(109),
+ char(112),
+ char(97),
+ char(99),
+ char(116),
+ char(83),
+ char(117),
+ char(98),
+ char(84),
+ char(121),
+ char(112),
+ char(101),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(117),
+ char(110),
+ char(115),
+ char(99),
+ char(97),
+ char(108),
+ char(101),
+ char(100),
+ char(80),
+ char(111),
+ char(105),
+ char(110),
+ char(116),
+ char(115),
+ char(70),
+ char(108),
+ char(111),
+ char(97),
+ char(116),
+ char(80),
+ char(116),
+ char(114),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(117),
+ char(110),
+ char(115),
+ char(99),
+ char(97),
+ char(108),
+ char(101),
+ char(100),
+ char(80),
+ char(111),
+ char(105),
+ char(110),
+ char(116),
+ char(115),
+ char(68),
+ char(111),
+ char(117),
+ char(98),
+ char(108),
+ char(101),
+ char(80),
+ char(116),
+ char(114),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(85),
+ char(110),
+ char(115),
+ char(99),
+ char(97),
+ char(108),
+ char(101),
+ char(100),
+ char(80),
+ char(111),
+ char(105),
+ char(110),
+ char(116),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(112),
+ char(97),
+ char(100),
+ char(100),
+ char(105),
+ char(110),
+ char(103),
+ char(51),
+ char(91),
+ char(52),
+ char(93),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(98),
+ char(114),
+ char(111),
+ char(97),
+ char(100),
+ char(112),
+ char(104),
+ char(97),
+ char(115),
+ char(101),
+ char(72),
+ char(97),
+ char(110),
+ char(100),
+ char(108),
+ char(101),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(99),
+ char(111),
+ char(108),
+ char(108),
+ char(105),
+ char(115),
+ char(105),
+ char(111),
+ char(110),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(114),
+ char(111),
+ char(111),
+ char(116),
+ char(67),
+ char(111),
+ char(108),
+ char(108),
+ char(105),
+ char(115),
+ char(105),
+ char(111),
+ char(110),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(119),
+ char(111),
+ char(114),
+ char(108),
+ char(100),
+ char(84),
+ char(114),
+ char(97),
+ char(110),
+ char(115),
+ char(102),
+ char(111),
+ char(114),
+ char(109),
+ char(0),
+ char(109),
+ char(95),
+ char(105),
+ char(110),
+ char(116),
+ char(101),
+ char(114),
+ char(112),
+ char(111),
+ char(108),
+ char(97),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(87),
+ char(111),
+ char(114),
+ char(108),
+ char(100),
+ char(84),
+ char(114),
+ char(97),
+ char(110),
+ char(115),
+ char(102),
+ char(111),
+ char(114),
+ char(109),
+ char(0),
+ char(109),
+ char(95),
+ char(105),
+ char(110),
+ char(116),
+ char(101),
+ char(114),
+ char(112),
+ char(111),
+ char(108),
+ char(97),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(76),
+ char(105),
+ char(110),
+ char(101),
+ char(97),
+ char(114),
+ char(86),
+ char(101),
+ char(108),
+ char(111),
+ char(99),
+ char(105),
+ char(116),
+ char(121),
+ char(0),
+ char(109),
+ char(95),
+ char(105),
+ char(110),
+ char(116),
+ char(101),
+ char(114),
+ char(112),
+ char(111),
+ char(108),
+ char(97),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(65),
+ char(110),
+ char(103),
+ char(117),
+ char(108),
+ char(97),
+ char(114),
+ char(86),
+ char(101),
+ char(108),
+ char(111),
+ char(99),
+ char(105),
+ char(116),
+ char(121),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(110),
+ char(105),
+ char(115),
+ char(111),
+ char(116),
+ char(114),
+ char(111),
+ char(112),
+ char(105),
+ char(99),
+ char(70),
+ char(114),
+ char(105),
+ char(99),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(111),
+ char(110),
+ char(116),
+ char(97),
+ char(99),
+ char(116),
+ char(80),
+ char(114),
+ char(111),
+ char(99),
+ char(101),
+ char(115),
+ char(115),
+ char(105),
+ char(110),
+ char(103),
+ char(84),
+ char(104),
+ char(114),
+ char(101),
+ char(115),
+ char(104),
+ char(111),
+ char(108),
+ char(100),
+ char(0),
+ char(109),
+ char(95),
+ char(100),
+ char(101),
+ char(97),
+ char(99),
+ char(116),
+ char(105),
+ char(118),
+ char(97),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(84),
+ char(105),
+ char(109),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(102),
+ char(114),
+ char(105),
+ char(99),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(0),
+ char(109),
+ char(95),
+ char(114),
+ char(111),
+ char(108),
+ char(108),
+ char(105),
+ char(110),
+ char(103),
+ char(70),
+ char(114),
+ char(105),
+ char(99),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(0),
+ char(109),
+ char(95),
+ char(114),
+ char(101),
+ char(115),
+ char(116),
+ char(105),
+ char(116),
+ char(117),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(0),
+ char(109),
+ char(95),
+ char(104),
+ char(105),
+ char(116),
+ char(70),
+ char(114),
+ char(97),
+ char(99),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(99),
+ char(100),
+ char(83),
+ char(119),
+ char(101),
+ char(112),
+ char(116),
+ char(83),
+ char(112),
+ char(104),
+ char(101),
+ char(114),
+ char(101),
+ char(82),
+ char(97),
+ char(100),
+ char(105),
+ char(117),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(99),
+ char(100),
+ char(77),
+ char(111),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(84),
+ char(104),
+ char(114),
+ char(101),
+ char(115),
+ char(104),
+ char(111),
+ char(108),
+ char(100),
+ char(0),
+ char(109),
+ char(95),
+ char(104),
+ char(97),
+ char(115),
+ char(65),
+ char(110),
+ char(105),
+ char(115),
+ char(111),
+ char(116),
+ char(114),
+ char(111),
+ char(112),
+ char(105),
+ char(99),
+ char(70),
+ char(114),
+ char(105),
+ char(99),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(111),
+ char(108),
+ char(108),
+ char(105),
+ char(115),
+ char(105),
+ char(111),
+ char(110),
+ char(70),
+ char(108),
+ char(97),
+ char(103),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(105),
+ char(115),
+ char(108),
+ char(97),
+ char(110),
+ char(100),
+ char(84),
+ char(97),
+ char(103),
+ char(49),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(111),
+ char(109),
+ char(112),
+ char(97),
+ char(110),
+ char(105),
+ char(111),
+ char(110),
+ char(73),
+ char(100),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(99),
+ char(116),
+ char(105),
+ char(118),
+ char(97),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(83),
+ char(116),
+ char(97),
+ char(116),
+ char(101),
+ char(49),
+ char(0),
+ char(109),
+ char(95),
+ char(105),
+ char(110),
+ char(116),
+ char(101),
+ char(114),
+ char(110),
+ char(97),
+ char(108),
+ char(84),
+ char(121),
+ char(112),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(104),
+ char(101),
+ char(99),
+ char(107),
+ char(67),
+ char(111),
+ char(108),
+ char(108),
+ char(105),
+ char(100),
+ char(101),
+ char(87),
+ char(105),
+ char(116),
+ char(104),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(111),
+ char(108),
+ char(118),
+ char(101),
+ char(114),
+ char(73),
+ char(110),
+ char(102),
+ char(111),
+ char(0),
+ char(109),
+ char(95),
+ char(103),
+ char(114),
+ char(97),
+ char(118),
+ char(105),
+ char(116),
+ char(121),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(111),
+ char(108),
+ char(108),
+ char(105),
+ char(115),
+ char(105),
+ char(111),
+ char(110),
+ char(79),
+ char(98),
+ char(106),
+ char(101),
+ char(99),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(109),
+ char(95),
+ char(105),
+ char(110),
+ char(118),
+ char(73),
+ char(110),
+ char(101),
+ char(114),
+ char(116),
+ char(105),
+ char(97),
+ char(84),
+ char(101),
+ char(110),
+ char(115),
+ char(111),
+ char(114),
+ char(87),
+ char(111),
+ char(114),
+ char(108),
+ char(100),
+ char(0),
+ char(109),
+ char(95),
+ char(108),
+ char(105),
+ char(110),
+ char(101),
+ char(97),
+ char(114),
+ char(86),
+ char(101),
+ char(108),
+ char(111),
+ char(99),
+ char(105),
+ char(116),
+ char(121),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(110),
+ char(103),
+ char(117),
+ char(108),
+ char(97),
+ char(114),
+ char(86),
+ char(101),
+ char(108),
+ char(111),
+ char(99),
+ char(105),
+ char(116),
+ char(121),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(110),
+ char(103),
+ char(117),
+ char(108),
+ char(97),
+ char(114),
+ char(70),
+ char(97),
+ char(99),
+ char(116),
+ char(111),
+ char(114),
+ char(0),
+ char(109),
+ char(95),
+ char(108),
+ char(105),
+ char(110),
+ char(101),
+ char(97),
+ char(114),
+ char(70),
+ char(97),
+ char(99),
+ char(116),
+ char(111),
+ char(114),
+ char(0),
+ char(109),
+ char(95),
+ char(103),
+ char(114),
+ char(97),
+ char(118),
+ char(105),
+ char(116),
+ char(121),
+ char(95),
+ char(97),
+ char(99),
+ char(99),
+ char(101),
+ char(108),
+ char(101),
+ char(114),
+ char(97),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(0),
+ char(109),
+ char(95),
+ char(105),
+ char(110),
+ char(118),
+ char(73),
+ char(110),
+ char(101),
+ char(114),
+ char(116),
+ char(105),
+ char(97),
+ char(76),
+ char(111),
+ char(99),
+ char(97),
+ char(108),
+ char(0),
+ char(109),
+ char(95),
+ char(116),
+ char(111),
+ char(116),
+ char(97),
+ char(108),
+ char(70),
+ char(111),
+ char(114),
+ char(99),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(116),
+ char(111),
+ char(116),
+ char(97),
+ char(108),
+ char(84),
+ char(111),
+ char(114),
+ char(113),
+ char(117),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(105),
+ char(110),
+ char(118),
+ char(101),
+ char(114),
+ char(115),
+ char(101),
+ char(77),
+ char(97),
+ char(115),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(108),
+ char(105),
+ char(110),
+ char(101),
+ char(97),
+ char(114),
+ char(68),
+ char(97),
+ char(109),
+ char(112),
+ char(105),
+ char(110),
+ char(103),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(110),
+ char(103),
+ char(117),
+ char(108),
+ char(97),
+ char(114),
+ char(68),
+ char(97),
+ char(109),
+ char(112),
+ char(105),
+ char(110),
+ char(103),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(100),
+ char(100),
+ char(105),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(97),
+ char(108),
+ char(68),
+ char(97),
+ char(109),
+ char(112),
+ char(105),
+ char(110),
+ char(103),
+ char(70),
+ char(97),
+ char(99),
+ char(116),
+ char(111),
+ char(114),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(100),
+ char(100),
+ char(105),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(97),
+ char(108),
+ char(76),
+ char(105),
+ char(110),
+ char(101),
+ char(97),
+ char(114),
+ char(68),
+ char(97),
+ char(109),
+ char(112),
+ char(105),
+ char(110),
+ char(103),
+ char(84),
+ char(104),
+ char(114),
+ char(101),
+ char(115),
+ char(104),
+ char(111),
+ char(108),
+ char(100),
+ char(83),
+ char(113),
+ char(114),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(100),
+ char(100),
+ char(105),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(97),
+ char(108),
+ char(65),
+ char(110),
+ char(103),
+ char(117),
+ char(108),
+ char(97),
+ char(114),
+ char(68),
+ char(97),
+ char(109),
+ char(112),
+ char(105),
+ char(110),
+ char(103),
+ char(84),
+ char(104),
+ char(114),
+ char(101),
+ char(115),
+ char(104),
+ char(111),
+ char(108),
+ char(100),
+ char(83),
+ char(113),
+ char(114),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(100),
+ char(100),
+ char(105),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(97),
+ char(108),
+ char(65),
+ char(110),
+ char(103),
+ char(117),
+ char(108),
+ char(97),
+ char(114),
+ char(68),
+ char(97),
+ char(109),
+ char(112),
+ char(105),
+ char(110),
+ char(103),
+ char(70),
+ char(97),
+ char(99),
+ char(116),
+ char(111),
+ char(114),
+ char(0),
+ char(109),
+ char(95),
+ char(108),
+ char(105),
+ char(110),
+ char(101),
+ char(97),
+ char(114),
+ char(83),
+ char(108),
+ char(101),
+ char(101),
+ char(112),
+ char(105),
+ char(110),
+ char(103),
+ char(84),
+ char(104),
+ char(114),
+ char(101),
+ char(115),
+ char(104),
+ char(111),
+ char(108),
+ char(100),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(110),
+ char(103),
+ char(117),
+ char(108),
+ char(97),
+ char(114),
+ char(83),
+ char(108),
+ char(101),
+ char(101),
+ char(112),
+ char(105),
+ char(110),
+ char(103),
+ char(84),
+ char(104),
+ char(114),
+ char(101),
+ char(115),
+ char(104),
+ char(111),
+ char(108),
+ char(100),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(100),
+ char(100),
+ char(105),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(97),
+ char(108),
+ char(68),
+ char(97),
+ char(109),
+ char(112),
+ char(105),
+ char(110),
+ char(103),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(67),
+ char(111),
+ char(110),
+ char(115),
+ char(116),
+ char(114),
+ char(97),
+ char(105),
+ char(110),
+ char(116),
+ char(82),
+ char(111),
+ char(119),
+ char(115),
+ char(0),
+ char(110),
+ char(117),
+ char(98),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(114),
+ char(98),
+ char(65),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(114),
+ char(98),
+ char(66),
+ char(0),
+ char(109),
+ char(95),
+ char(111),
+ char(98),
+ char(106),
+ char(101),
+ char(99),
+ char(116),
+ char(84),
+ char(121),
+ char(112),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(117),
+ char(115),
+ char(101),
+ char(114),
+ char(67),
+ char(111),
+ char(110),
+ char(115),
+ char(116),
+ char(114),
+ char(97),
+ char(105),
+ char(110),
+ char(116),
+ char(84),
+ char(121),
+ char(112),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(117),
+ char(115),
+ char(101),
+ char(114),
+ char(67),
+ char(111),
+ char(110),
+ char(115),
+ char(116),
+ char(114),
+ char(97),
+ char(105),
+ char(110),
+ char(116),
+ char(73),
+ char(100),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(101),
+ char(101),
+ char(100),
+ char(115),
+ char(70),
+ char(101),
+ char(101),
+ char(100),
+ char(98),
+ char(97),
+ char(99),
+ char(107),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(112),
+ char(112),
+ char(108),
+ char(105),
+ char(101),
+ char(100),
+ char(73),
+ char(109),
+ char(112),
+ char(117),
+ char(108),
+ char(115),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(100),
+ char(98),
+ char(103),
+ char(68),
+ char(114),
+ char(97),
+ char(119),
+ char(83),
+ char(105),
+ char(122),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(100),
+ char(105),
+ char(115),
+ char(97),
+ char(98),
+ char(108),
+ char(101),
+ char(67),
+ char(111),
+ char(108),
+ char(108),
+ char(105),
+ char(115),
+ char(105),
+ char(111),
+ char(110),
+ char(115),
+ char(66),
+ char(101),
+ char(116),
+ char(119),
+ char(101),
+ char(101),
+ char(110),
+ char(76),
+ char(105),
+ char(110),
+ char(107),
+ char(101),
+ char(100),
+ char(66),
+ char(111),
+ char(100),
+ char(105),
+ char(101),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(111),
+ char(118),
+ char(101),
+ char(114),
+ char(114),
+ char(105),
+ char(100),
+ char(101),
+ char(78),
+ char(117),
+ char(109),
+ char(83),
+ char(111),
+ char(108),
+ char(118),
+ char(101),
+ char(114),
+ char(73),
+ char(116),
+ char(101),
+ char(114),
+ char(97),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(98),
+ char(114),
+ char(101),
+ char(97),
+ char(107),
+ char(105),
+ char(110),
+ char(103),
+ char(73),
+ char(109),
+ char(112),
+ char(117),
+ char(108),
+ char(115),
+ char(101),
+ char(84),
+ char(104),
+ char(114),
+ char(101),
+ char(115),
+ char(104),
+ char(111),
+ char(108),
+ char(100),
+ char(0),
+ char(109),
+ char(95),
+ char(105),
+ char(115),
+ char(69),
+ char(110),
+ char(97),
+ char(98),
+ char(108),
+ char(101),
+ char(100),
+ char(0),
+ char(109),
+ char(95),
+ char(116),
+ char(121),
+ char(112),
+ char(101),
+ char(67),
+ char(111),
+ char(110),
+ char(115),
+ char(116),
+ char(114),
+ char(97),
+ char(105),
+ char(110),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(109),
+ char(95),
+ char(112),
+ char(105),
+ char(118),
+ char(111),
+ char(116),
+ char(73),
+ char(110),
+ char(65),
+ char(0),
+ char(109),
+ char(95),
+ char(112),
+ char(105),
+ char(118),
+ char(111),
+ char(116),
+ char(73),
+ char(110),
+ char(66),
+ char(0),
+ char(109),
+ char(95),
+ char(114),
+ char(98),
+ char(65),
+ char(70),
+ char(114),
+ char(97),
+ char(109),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(114),
+ char(98),
+ char(66),
+ char(70),
+ char(114),
+ char(97),
+ char(109),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(117),
+ char(115),
+ char(101),
+ char(82),
+ char(101),
+ char(102),
+ char(101),
+ char(114),
+ char(101),
+ char(110),
+ char(99),
+ char(101),
+ char(70),
+ char(114),
+ char(97),
+ char(109),
+ char(101),
+ char(65),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(110),
+ char(103),
+ char(117),
+ char(108),
+ char(97),
+ char(114),
+ char(79),
+ char(110),
+ char(108),
+ char(121),
+ char(0),
+ char(109),
+ char(95),
+ char(101),
+ char(110),
+ char(97),
+ char(98),
+ char(108),
+ char(101),
+ char(65),
+ char(110),
+ char(103),
+ char(117),
+ char(108),
+ char(97),
+ char(114),
+ char(77),
+ char(111),
+ char(116),
+ char(111),
+ char(114),
+ char(0),
+ char(109),
+ char(95),
+ char(109),
+ char(111),
+ char(116),
+ char(111),
+ char(114),
+ char(84),
+ char(97),
+ char(114),
+ char(103),
+ char(101),
+ char(116),
+ char(86),
+ char(101),
+ char(108),
+ char(111),
+ char(99),
+ char(105),
+ char(116),
+ char(121),
+ char(0),
+ char(109),
+ char(95),
+ char(109),
+ char(97),
+ char(120),
+ char(77),
+ char(111),
+ char(116),
+ char(111),
+ char(114),
+ char(73),
+ char(109),
+ char(112),
+ char(117),
+ char(108),
+ char(115),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(108),
+ char(111),
+ char(119),
+ char(101),
+ char(114),
+ char(76),
+ char(105),
+ char(109),
+ char(105),
+ char(116),
+ char(0),
+ char(109),
+ char(95),
+ char(117),
+ char(112),
+ char(112),
+ char(101),
+ char(114),
+ char(76),
+ char(105),
+ char(109),
+ char(105),
+ char(116),
+ char(0),
+ char(109),
+ char(95),
+ char(108),
+ char(105),
+ char(109),
+ char(105),
+ char(116),
+ char(83),
+ char(111),
+ char(102),
+ char(116),
+ char(110),
+ char(101),
+ char(115),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(98),
+ char(105),
+ char(97),
+ char(115),
+ char(70),
+ char(97),
+ char(99),
+ char(116),
+ char(111),
+ char(114),
+ char(0),
+ char(109),
+ char(95),
+ char(114),
+ char(101),
+ char(108),
+ char(97),
+ char(120),
+ char(97),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(70),
+ char(97),
+ char(99),
+ char(116),
+ char(111),
+ char(114),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(119),
+ char(105),
+ char(110),
+ char(103),
+ char(83),
+ char(112),
+ char(97),
+ char(110),
+ char(49),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(119),
+ char(105),
+ char(110),
+ char(103),
+ char(83),
+ char(112),
+ char(97),
+ char(110),
+ char(50),
+ char(0),
+ char(109),
+ char(95),
+ char(116),
+ char(119),
+ char(105),
+ char(115),
+ char(116),
+ char(83),
+ char(112),
+ char(97),
+ char(110),
+ char(0),
+ char(109),
+ char(95),
+ char(100),
+ char(97),
+ char(109),
+ char(112),
+ char(105),
+ char(110),
+ char(103),
+ char(0),
+ char(109),
+ char(95),
+ char(108),
+ char(105),
+ char(110),
+ char(101),
+ char(97),
+ char(114),
+ char(85),
+ char(112),
+ char(112),
+ char(101),
+ char(114),
+ char(76),
+ char(105),
+ char(109),
+ char(105),
+ char(116),
+ char(0),
+ char(109),
+ char(95),
+ char(108),
+ char(105),
+ char(110),
+ char(101),
+ char(97),
+ char(114),
+ char(76),
+ char(111),
+ char(119),
+ char(101),
+ char(114),
+ char(76),
+ char(105),
+ char(109),
+ char(105),
+ char(116),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(110),
+ char(103),
+ char(117),
+ char(108),
+ char(97),
+ char(114),
+ char(85),
+ char(112),
+ char(112),
+ char(101),
+ char(114),
+ char(76),
+ char(105),
+ char(109),
+ char(105),
+ char(116),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(110),
+ char(103),
+ char(117),
+ char(108),
+ char(97),
+ char(114),
+ char(76),
+ char(111),
+ char(119),
+ char(101),
+ char(114),
+ char(76),
+ char(105),
+ char(109),
+ char(105),
+ char(116),
+ char(0),
+ char(109),
+ char(95),
+ char(117),
+ char(115),
+ char(101),
+ char(76),
+ char(105),
+ char(110),
+ char(101),
+ char(97),
+ char(114),
+ char(82),
+ char(101),
+ char(102),
+ char(101),
+ char(114),
+ char(101),
+ char(110),
+ char(99),
+ char(101),
+ char(70),
+ char(114),
+ char(97),
+ char(109),
+ char(101),
+ char(65),
+ char(0),
+ char(109),
+ char(95),
+ char(117),
+ char(115),
+ char(101),
+ char(79),
+ char(102),
+ char(102),
+ char(115),
+ char(101),
+ char(116),
+ char(70),
+ char(111),
+ char(114),
+ char(67),
+ char(111),
+ char(110),
+ char(115),
+ char(116),
+ char(114),
+ char(97),
+ char(105),
+ char(110),
+ char(116),
+ char(70),
+ char(114),
+ char(97),
+ char(109),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(54),
+ char(100),
+ char(111),
+ char(102),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(112),
+ char(114),
+ char(105),
+ char(110),
+ char(103),
+ char(69),
+ char(110),
+ char(97),
+ char(98),
+ char(108),
+ char(101),
+ char(100),
+ char(91),
+ char(54),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(101),
+ char(113),
+ char(117),
+ char(105),
+ char(108),
+ char(105),
+ char(98),
+ char(114),
+ char(105),
+ char(117),
+ char(109),
+ char(80),
+ char(111),
+ char(105),
+ char(110),
+ char(116),
+ char(91),
+ char(54),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(112),
+ char(114),
+ char(105),
+ char(110),
+ char(103),
+ char(83),
+ char(116),
+ char(105),
+ char(102),
+ char(102),
+ char(110),
+ char(101),
+ char(115),
+ char(115),
+ char(91),
+ char(54),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(112),
+ char(114),
+ char(105),
+ char(110),
+ char(103),
+ char(68),
+ char(97),
+ char(109),
+ char(112),
+ char(105),
+ char(110),
+ char(103),
+ char(91),
+ char(54),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(116),
+ char(97),
+ char(117),
+ char(0),
+ char(109),
+ char(95),
+ char(116),
+ char(105),
+ char(109),
+ char(101),
+ char(83),
+ char(116),
+ char(101),
+ char(112),
+ char(0),
+ char(109),
+ char(95),
+ char(109),
+ char(97),
+ char(120),
+ char(69),
+ char(114),
+ char(114),
+ char(111),
+ char(114),
+ char(82),
+ char(101),
+ char(100),
+ char(117),
+ char(99),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(111),
+ char(114),
+ char(0),
+ char(109),
+ char(95),
+ char(101),
+ char(114),
+ char(112),
+ char(0),
+ char(109),
+ char(95),
+ char(101),
+ char(114),
+ char(112),
+ char(50),
+ char(0),
+ char(109),
+ char(95),
+ char(103),
+ char(108),
+ char(111),
+ char(98),
+ char(97),
+ char(108),
+ char(67),
+ char(102),
+ char(109),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(112),
+ char(108),
+ char(105),
+ char(116),
+ char(73),
+ char(109),
+ char(112),
+ char(117),
+ char(108),
+ char(115),
+ char(101),
+ char(80),
+ char(101),
+ char(110),
+ char(101),
+ char(116),
+ char(114),
+ char(97),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(84),
+ char(104),
+ char(114),
+ char(101),
+ char(115),
+ char(104),
+ char(111),
+ char(108),
+ char(100),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(112),
+ char(108),
+ char(105),
+ char(116),
+ char(73),
+ char(109),
+ char(112),
+ char(117),
+ char(108),
+ char(115),
+ char(101),
+ char(84),
+ char(117),
+ char(114),
+ char(110),
+ char(69),
+ char(114),
+ char(112),
+ char(0),
+ char(109),
+ char(95),
+ char(108),
+ char(105),
+ char(110),
+ char(101),
+ char(97),
+ char(114),
+ char(83),
+ char(108),
+ char(111),
+ char(112),
+ char(0),
+ char(109),
+ char(95),
+ char(119),
+ char(97),
+ char(114),
+ char(109),
+ char(115),
+ char(116),
+ char(97),
+ char(114),
+ char(116),
+ char(105),
+ char(110),
+ char(103),
+ char(70),
+ char(97),
+ char(99),
+ char(116),
+ char(111),
+ char(114),
+ char(0),
+ char(109),
+ char(95),
+ char(109),
+ char(97),
+ char(120),
+ char(71),
+ char(121),
+ char(114),
+ char(111),
+ char(115),
+ char(99),
+ char(111),
+ char(112),
+ char(105),
+ char(99),
+ char(70),
+ char(111),
+ char(114),
+ char(99),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(105),
+ char(110),
+ char(103),
+ char(108),
+ char(101),
+ char(65),
+ char(120),
+ char(105),
+ char(115),
+ char(82),
+ char(111),
+ char(108),
+ char(108),
+ char(105),
+ char(110),
+ char(103),
+ char(70),
+ char(114),
+ char(105),
+ char(99),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(84),
+ char(104),
+ char(114),
+ char(101),
+ char(115),
+ char(104),
+ char(111),
+ char(108),
+ char(100),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(73),
+ char(116),
+ char(101),
+ char(114),
+ char(97),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(111),
+ char(108),
+ char(118),
+ char(101),
+ char(114),
+ char(77),
+ char(111),
+ char(100),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(114),
+ char(101),
+ char(115),
+ char(116),
+ char(105),
+ char(110),
+ char(103),
+ char(67),
+ char(111),
+ char(110),
+ char(116),
+ char(97),
+ char(99),
+ char(116),
+ char(82),
+ char(101),
+ char(115),
+ char(116),
+ char(105),
+ char(116),
+ char(117),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(84),
+ char(104),
+ char(114),
+ char(101),
+ char(115),
+ char(104),
+ char(111),
+ char(108),
+ char(100),
+ char(0),
+ char(109),
+ char(95),
+ char(109),
+ char(105),
+ char(110),
+ char(105),
+ char(109),
+ char(117),
+ char(109),
+ char(83),
+ char(111),
+ char(108),
+ char(118),
+ char(101),
+ char(114),
+ char(66),
+ char(97),
+ char(116),
+ char(99),
+ char(104),
+ char(83),
+ char(105),
+ char(122),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(112),
+ char(108),
+ char(105),
+ char(116),
+ char(73),
+ char(109),
+ char(112),
+ char(117),
+ char(108),
+ char(115),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(108),
+ char(105),
+ char(110),
+ char(101),
+ char(97),
+ char(114),
+ char(83),
+ char(116),
+ char(105),
+ char(102),
+ char(102),
+ char(110),
+ char(101),
+ char(115),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(110),
+ char(103),
+ char(117),
+ char(108),
+ char(97),
+ char(114),
+ char(83),
+ char(116),
+ char(105),
+ char(102),
+ char(102),
+ char(110),
+ char(101),
+ char(115),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(118),
+ char(111),
+ char(108),
+ char(117),
+ char(109),
+ char(101),
+ char(83),
+ char(116),
+ char(105),
+ char(102),
+ char(102),
+ char(110),
+ char(101),
+ char(115),
+ char(115),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(109),
+ char(97),
+ char(116),
+ char(101),
+ char(114),
+ char(105),
+ char(97),
+ char(108),
+ char(0),
+ char(109),
+ char(95),
+ char(112),
+ char(111),
+ char(115),
+ char(105),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(0),
+ char(109),
+ char(95),
+ char(112),
+ char(114),
+ char(101),
+ char(118),
+ char(105),
+ char(111),
+ char(117),
+ char(115),
+ char(80),
+ char(111),
+ char(115),
+ char(105),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(0),
+ char(109),
+ char(95),
+ char(118),
+ char(101),
+ char(108),
+ char(111),
+ char(99),
+ char(105),
+ char(116),
+ char(121),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(99),
+ char(99),
+ char(117),
+ char(109),
+ char(117),
+ char(108),
+ char(97),
+ char(116),
+ char(101),
+ char(100),
+ char(70),
+ char(111),
+ char(114),
+ char(99),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(111),
+ char(114),
+ char(109),
+ char(97),
+ char(108),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(114),
+ char(101),
+ char(97),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(116),
+ char(116),
+ char(97),
+ char(99),
+ char(104),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(111),
+ char(100),
+ char(101),
+ char(73),
+ char(110),
+ char(100),
+ char(105),
+ char(99),
+ char(101),
+ char(115),
+ char(91),
+ char(50),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(114),
+ char(101),
+ char(115),
+ char(116),
+ char(76),
+ char(101),
+ char(110),
+ char(103),
+ char(116),
+ char(104),
+ char(0),
+ char(109),
+ char(95),
+ char(98),
+ char(98),
+ char(101),
+ char(110),
+ char(100),
+ char(105),
+ char(110),
+ char(103),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(111),
+ char(100),
+ char(101),
+ char(73),
+ char(110),
+ char(100),
+ char(105),
+ char(99),
+ char(101),
+ char(115),
+ char(91),
+ char(51),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(114),
+ char(101),
+ char(115),
+ char(116),
+ char(65),
+ char(114),
+ char(101),
+ char(97),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(48),
+ char(91),
+ char(52),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(111),
+ char(100),
+ char(101),
+ char(73),
+ char(110),
+ char(100),
+ char(105),
+ char(99),
+ char(101),
+ char(115),
+ char(91),
+ char(52),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(114),
+ char(101),
+ char(115),
+ char(116),
+ char(86),
+ char(111),
+ char(108),
+ char(117),
+ char(109),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(49),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(50),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(48),
+ char(0),
+ char(109),
+ char(95),
+ char(108),
+ char(111),
+ char(99),
+ char(97),
+ char(108),
+ char(70),
+ char(114),
+ char(97),
+ char(109),
+ char(101),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(114),
+ char(105),
+ char(103),
+ char(105),
+ char(100),
+ char(66),
+ char(111),
+ char(100),
+ char(121),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(111),
+ char(100),
+ char(101),
+ char(73),
+ char(110),
+ char(100),
+ char(101),
+ char(120),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(101),
+ char(114),
+ char(111),
+ char(77),
+ char(111),
+ char(100),
+ char(101),
+ char(108),
+ char(0),
+ char(109),
+ char(95),
+ char(98),
+ char(97),
+ char(117),
+ char(109),
+ char(103),
+ char(97),
+ char(114),
+ char(116),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(100),
+ char(114),
+ char(97),
+ char(103),
+ char(0),
+ char(109),
+ char(95),
+ char(108),
+ char(105),
+ char(102),
+ char(116),
+ char(0),
+ char(109),
+ char(95),
+ char(112),
+ char(114),
+ char(101),
+ char(115),
+ char(115),
+ char(117),
+ char(114),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(118),
+ char(111),
+ char(108),
+ char(117),
+ char(109),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(100),
+ char(121),
+ char(110),
+ char(97),
+ char(109),
+ char(105),
+ char(99),
+ char(70),
+ char(114),
+ char(105),
+ char(99),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(0),
+ char(109),
+ char(95),
+ char(112),
+ char(111),
+ char(115),
+ char(101),
+ char(77),
+ char(97),
+ char(116),
+ char(99),
+ char(104),
+ char(0),
+ char(109),
+ char(95),
+ char(114),
+ char(105),
+ char(103),
+ char(105),
+ char(100),
+ char(67),
+ char(111),
+ char(110),
+ char(116),
+ char(97),
+ char(99),
+ char(116),
+ char(72),
+ char(97),
+ char(114),
+ char(100),
+ char(110),
+ char(101),
+ char(115),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(107),
+ char(105),
+ char(110),
+ char(101),
+ char(116),
+ char(105),
+ char(99),
+ char(67),
+ char(111),
+ char(110),
+ char(116),
+ char(97),
+ char(99),
+ char(116),
+ char(72),
+ char(97),
+ char(114),
+ char(100),
+ char(110),
+ char(101),
+ char(115),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(111),
+ char(102),
+ char(116),
+ char(67),
+ char(111),
+ char(110),
+ char(116),
+ char(97),
+ char(99),
+ char(116),
+ char(72),
+ char(97),
+ char(114),
+ char(100),
+ char(110),
+ char(101),
+ char(115),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(110),
+ char(99),
+ char(104),
+ char(111),
+ char(114),
+ char(72),
+ char(97),
+ char(114),
+ char(100),
+ char(110),
+ char(101),
+ char(115),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(111),
+ char(102),
+ char(116),
+ char(82),
+ char(105),
+ char(103),
+ char(105),
+ char(100),
+ char(67),
+ char(108),
+ char(117),
+ char(115),
+ char(116),
+ char(101),
+ char(114),
+ char(72),
+ char(97),
+ char(114),
+ char(100),
+ char(110),
+ char(101),
+ char(115),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(111),
+ char(102),
+ char(116),
+ char(75),
+ char(105),
+ char(110),
+ char(101),
+ char(116),
+ char(105),
+ char(99),
+ char(67),
+ char(108),
+ char(117),
+ char(115),
+ char(116),
+ char(101),
+ char(114),
+ char(72),
+ char(97),
+ char(114),
+ char(100),
+ char(110),
+ char(101),
+ char(115),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(111),
+ char(102),
+ char(116),
+ char(83),
+ char(111),
+ char(102),
+ char(116),
+ char(67),
+ char(108),
+ char(117),
+ char(115),
+ char(116),
+ char(101),
+ char(114),
+ char(72),
+ char(97),
+ char(114),
+ char(100),
+ char(110),
+ char(101),
+ char(115),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(111),
+ char(102),
+ char(116),
+ char(82),
+ char(105),
+ char(103),
+ char(105),
+ char(100),
+ char(67),
+ char(108),
+ char(117),
+ char(115),
+ char(116),
+ char(101),
+ char(114),
+ char(73),
+ char(109),
+ char(112),
+ char(117),
+ char(108),
+ char(115),
+ char(101),
+ char(83),
+ char(112),
+ char(108),
+ char(105),
+ char(116),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(111),
+ char(102),
+ char(116),
+ char(75),
+ char(105),
+ char(110),
+ char(101),
+ char(116),
+ char(105),
+ char(99),
+ char(67),
+ char(108),
+ char(117),
+ char(115),
+ char(116),
+ char(101),
+ char(114),
+ char(73),
+ char(109),
+ char(112),
+ char(117),
+ char(108),
+ char(115),
+ char(101),
+ char(83),
+ char(112),
+ char(108),
+ char(105),
+ char(116),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(111),
+ char(102),
+ char(116),
+ char(83),
+ char(111),
+ char(102),
+ char(116),
+ char(67),
+ char(108),
+ char(117),
+ char(115),
+ char(116),
+ char(101),
+ char(114),
+ char(73),
+ char(109),
+ char(112),
+ char(117),
+ char(108),
+ char(115),
+ char(101),
+ char(83),
+ char(112),
+ char(108),
+ char(105),
+ char(116),
+ char(0),
+ char(109),
+ char(95),
+ char(109),
+ char(97),
+ char(120),
+ char(86),
+ char(111),
+ char(108),
+ char(117),
+ char(109),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(116),
+ char(105),
+ char(109),
+ char(101),
+ char(83),
+ char(99),
+ char(97),
+ char(108),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(118),
+ char(101),
+ char(108),
+ char(111),
+ char(99),
+ char(105),
+ char(116),
+ char(121),
+ char(73),
+ char(116),
+ char(101),
+ char(114),
+ char(97),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(112),
+ char(111),
+ char(115),
+ char(105),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(73),
+ char(116),
+ char(101),
+ char(114),
+ char(97),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(100),
+ char(114),
+ char(105),
+ char(102),
+ char(116),
+ char(73),
+ char(116),
+ char(101),
+ char(114),
+ char(97),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(108),
+ char(117),
+ char(115),
+ char(116),
+ char(101),
+ char(114),
+ char(73),
+ char(116),
+ char(101),
+ char(114),
+ char(97),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(114),
+ char(111),
+ char(116),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(99),
+ char(97),
+ char(108),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(113),
+ char(113),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(111),
+ char(109),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(112),
+ char(111),
+ char(115),
+ char(105),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(115),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(119),
+ char(101),
+ char(105),
+ char(103),
+ char(104),
+ char(116),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(80),
+ char(111),
+ char(115),
+ char(105),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(87),
+ char(101),
+ char(105),
+ char(103),
+ char(116),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(98),
+ char(118),
+ char(111),
+ char(108),
+ char(117),
+ char(109),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(98),
+ char(102),
+ char(114),
+ char(97),
+ char(109),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(102),
+ char(114),
+ char(97),
+ char(109),
+ char(101),
+ char(120),
+ char(102),
+ char(111),
+ char(114),
+ char(109),
+ char(0),
+ char(109),
+ char(95),
+ char(108),
+ char(111),
+ char(99),
+ char(105),
+ char(105),
+ char(0),
+ char(109),
+ char(95),
+ char(105),
+ char(110),
+ char(118),
+ char(119),
+ char(105),
+ char(0),
+ char(109),
+ char(95),
+ char(118),
+ char(105),
+ char(109),
+ char(112),
+ char(117),
+ char(108),
+ char(115),
+ char(101),
+ char(115),
+ char(91),
+ char(50),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(100),
+ char(105),
+ char(109),
+ char(112),
+ char(117),
+ char(108),
+ char(115),
+ char(101),
+ char(115),
+ char(91),
+ char(50),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(108),
+ char(118),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(118),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(102),
+ char(114),
+ char(97),
+ char(109),
+ char(101),
+ char(114),
+ char(101),
+ char(102),
+ char(115),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(110),
+ char(111),
+ char(100),
+ char(101),
+ char(73),
+ char(110),
+ char(100),
+ char(105),
+ char(99),
+ char(101),
+ char(115),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(109),
+ char(97),
+ char(115),
+ char(115),
+ char(101),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(70),
+ char(114),
+ char(97),
+ char(109),
+ char(101),
+ char(82),
+ char(101),
+ char(102),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(78),
+ char(111),
+ char(100),
+ char(101),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(77),
+ char(97),
+ char(115),
+ char(115),
+ char(101),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(105),
+ char(100),
+ char(109),
+ char(97),
+ char(115),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(105),
+ char(109),
+ char(97),
+ char(115),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(118),
+ char(105),
+ char(109),
+ char(112),
+ char(117),
+ char(108),
+ char(115),
+ char(101),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(100),
+ char(105),
+ char(109),
+ char(112),
+ char(117),
+ char(108),
+ char(115),
+ char(101),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(100),
+ char(97),
+ char(109),
+ char(112),
+ char(105),
+ char(110),
+ char(103),
+ char(0),
+ char(109),
+ char(95),
+ char(108),
+ char(100),
+ char(97),
+ char(109),
+ char(112),
+ char(105),
+ char(110),
+ char(103),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(100),
+ char(97),
+ char(109),
+ char(112),
+ char(105),
+ char(110),
+ char(103),
+ char(0),
+ char(109),
+ char(95),
+ char(109),
+ char(97),
+ char(116),
+ char(99),
+ char(104),
+ char(105),
+ char(110),
+ char(103),
+ char(0),
+ char(109),
+ char(95),
+ char(109),
+ char(97),
+ char(120),
+ char(83),
+ char(101),
+ char(108),
+ char(102),
+ char(67),
+ char(111),
+ char(108),
+ char(108),
+ char(105),
+ char(115),
+ char(105),
+ char(111),
+ char(110),
+ char(73),
+ char(109),
+ char(112),
+ char(117),
+ char(108),
+ char(115),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(101),
+ char(108),
+ char(102),
+ char(67),
+ char(111),
+ char(108),
+ char(108),
+ char(105),
+ char(115),
+ char(105),
+ char(111),
+ char(110),
+ char(73),
+ char(109),
+ char(112),
+ char(117),
+ char(108),
+ char(115),
+ char(101),
+ char(70),
+ char(97),
+ char(99),
+ char(116),
+ char(111),
+ char(114),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(111),
+ char(110),
+ char(116),
+ char(97),
+ char(105),
+ char(110),
+ char(115),
+ char(65),
+ char(110),
+ char(99),
+ char(104),
+ char(111),
+ char(114),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(111),
+ char(108),
+ char(108),
+ char(105),
+ char(100),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(108),
+ char(117),
+ char(115),
+ char(116),
+ char(101),
+ char(114),
+ char(73),
+ char(110),
+ char(100),
+ char(101),
+ char(120),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(98),
+ char(111),
+ char(100),
+ char(121),
+ char(65),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(98),
+ char(111),
+ char(100),
+ char(121),
+ char(66),
+ char(0),
+ char(109),
+ char(95),
+ char(114),
+ char(101),
+ char(102),
+ char(115),
+ char(91),
+ char(50),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(102),
+ char(109),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(112),
+ char(108),
+ char(105),
+ char(116),
+ char(0),
+ char(109),
+ char(95),
+ char(100),
+ char(101),
+ char(108),
+ char(101),
+ char(116),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(114),
+ char(101),
+ char(108),
+ char(80),
+ char(111),
+ char(115),
+ char(105),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(91),
+ char(50),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(98),
+ char(111),
+ char(100),
+ char(121),
+ char(65),
+ char(116),
+ char(121),
+ char(112),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(98),
+ char(111),
+ char(100),
+ char(121),
+ char(66),
+ char(116),
+ char(121),
+ char(112),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(106),
+ char(111),
+ char(105),
+ char(110),
+ char(116),
+ char(84),
+ char(121),
+ char(112),
+ char(101),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(112),
+ char(111),
+ char(115),
+ char(101),
+ char(0),
+ char(42),
+ char(42),
+ char(109),
+ char(95),
+ char(109),
+ char(97),
+ char(116),
+ char(101),
+ char(114),
+ char(105),
+ char(97),
+ char(108),
+ char(115),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(110),
+ char(111),
+ char(100),
+ char(101),
+ char(115),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(108),
+ char(105),
+ char(110),
+ char(107),
+ char(115),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(102),
+ char(97),
+ char(99),
+ char(101),
+ char(115),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(116),
+ char(101),
+ char(116),
+ char(114),
+ char(97),
+ char(104),
+ char(101),
+ char(100),
+ char(114),
+ char(97),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(97),
+ char(110),
+ char(99),
+ char(104),
+ char(111),
+ char(114),
+ char(115),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(99),
+ char(108),
+ char(117),
+ char(115),
+ char(116),
+ char(101),
+ char(114),
+ char(115),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(106),
+ char(111),
+ char(105),
+ char(110),
+ char(116),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(77),
+ char(97),
+ char(116),
+ char(101),
+ char(114),
+ char(105),
+ char(97),
+ char(108),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(76),
+ char(105),
+ char(110),
+ char(107),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(70),
+ char(97),
+ char(99),
+ char(101),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(84),
+ char(101),
+ char(116),
+ char(114),
+ char(97),
+ char(104),
+ char(101),
+ char(100),
+ char(114),
+ char(97),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(65),
+ char(110),
+ char(99),
+ char(104),
+ char(111),
+ char(114),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(67),
+ char(108),
+ char(117),
+ char(115),
+ char(116),
+ char(101),
+ char(114),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(74),
+ char(111),
+ char(105),
+ char(110),
+ char(116),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(111),
+ char(110),
+ char(102),
+ char(105),
+ char(103),
+ char(0),
+ char(84),
+ char(89),
+ char(80),
+ char(69),
+ char(76),
+ char(0),
+ char(0),
+ char(0),
+ char(99),
+ char(104),
+ char(97),
+ char(114),
+ char(0),
+ char(117),
+ char(99),
+ char(104),
+ char(97),
+ char(114),
+ char(0),
+ char(115),
+ char(104),
+ char(111),
+ char(114),
+ char(116),
+ char(0),
+ char(117),
+ char(115),
+ char(104),
+ char(111),
+ char(114),
+ char(116),
+ char(0),
+ char(105),
+ char(110),
+ char(116),
+ char(0),
+ char(108),
+ char(111),
+ char(110),
+ char(103),
+ char(0),
+ char(117),
+ char(108),
+ char(111),
+ char(110),
+ char(103),
+ char(0),
+ char(102),
+ char(108),
+ char(111),
+ char(97),
+ char(116),
+ char(0),
+ char(100),
+ char(111),
+ char(117),
+ char(98),
+ char(108),
+ char(101),
+ char(0),
+ char(118),
+ char(111),
+ char(105),
+ char(100),
+ char(0),
+ char(80),
+ char(111),
+ char(105),
+ char(110),
+ char(116),
+ char(101),
+ char(114),
+ char(65),
+ char(114),
+ char(114),
+ char(97),
+ char(121),
+ char(0),
+ char(98),
+ char(116),
+ char(80),
+ char(104),
+ char(121),
+ char(115),
+ char(105),
+ char(99),
+ char(115),
+ char(83),
+ char(121),
+ char(115),
+ char(116),
+ char(101),
+ char(109),
+ char(0),
+ char(76),
+ char(105),
+ char(115),
+ char(116),
+ char(66),
+ char(97),
+ char(115),
+ char(101),
+ char(0),
+ char(98),
+ char(116),
+ char(86),
+ char(101),
+ char(99),
+ char(116),
+ char(111),
+ char(114),
+ char(51),
+ char(70),
+ char(108),
+ char(111),
+ char(97),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(86),
+ char(101),
+ char(99),
+ char(116),
+ char(111),
+ char(114),
+ char(51),
+ char(68),
+ char(111),
+ char(117),
+ char(98),
+ char(108),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(77),
+ char(97),
+ char(116),
+ char(114),
+ char(105),
+ char(120),
+ char(51),
+ char(120),
+ char(51),
+ char(70),
+ char(108),
+ char(111),
+ char(97),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(77),
+ char(97),
+ char(116),
+ char(114),
+ char(105),
+ char(120),
+ char(51),
+ char(120),
+ char(51),
+ char(68),
+ char(111),
+ char(117),
+ char(98),
+ char(108),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(84),
+ char(114),
+ char(97),
+ char(110),
+ char(115),
+ char(102),
+ char(111),
+ char(114),
+ char(109),
+ char(70),
+ char(108),
+ char(111),
+ char(97),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(84),
+ char(114),
+ char(97),
+ char(110),
+ char(115),
+ char(102),
+ char(111),
+ char(114),
+ char(109),
+ char(68),
+ char(111),
+ char(117),
+ char(98),
+ char(108),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(66),
+ char(118),
+ char(104),
+ char(83),
+ char(117),
+ char(98),
+ char(116),
+ char(114),
+ char(101),
+ char(101),
+ char(73),
+ char(110),
+ char(102),
+ char(111),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(79),
+ char(112),
+ char(116),
+ char(105),
+ char(109),
+ char(105),
+ char(122),
+ char(101),
+ char(100),
+ char(66),
+ char(118),
+ char(104),
+ char(78),
+ char(111),
+ char(100),
+ char(101),
+ char(70),
+ char(108),
+ char(111),
+ char(97),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(79),
+ char(112),
+ char(116),
+ char(105),
+ char(109),
+ char(105),
+ char(122),
+ char(101),
+ char(100),
+ char(66),
+ char(118),
+ char(104),
+ char(78),
+ char(111),
+ char(100),
+ char(101),
+ char(68),
+ char(111),
+ char(117),
+ char(98),
+ char(108),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(81),
+ char(117),
+ char(97),
+ char(110),
+ char(116),
+ char(105),
+ char(122),
+ char(101),
+ char(100),
+ char(66),
+ char(118),
+ char(104),
+ char(78),
+ char(111),
+ char(100),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(81),
+ char(117),
+ char(97),
+ char(110),
+ char(116),
+ char(105),
+ char(122),
+ char(101),
+ char(100),
+ char(66),
+ char(118),
+ char(104),
+ char(70),
+ char(108),
+ char(111),
+ char(97),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(81),
+ char(117),
+ char(97),
+ char(110),
+ char(116),
+ char(105),
+ char(122),
+ char(101),
+ char(100),
+ char(66),
+ char(118),
+ char(104),
+ char(68),
+ char(111),
+ char(117),
+ char(98),
+ char(108),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(67),
+ char(111),
+ char(108),
+ char(108),
+ char(105),
+ char(115),
+ char(105),
+ char(111),
+ char(110),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(83),
+ char(116),
+ char(97),
+ char(116),
+ char(105),
+ char(99),
+ char(80),
+ char(108),
+ char(97),
+ char(110),
+ char(101),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(67),
+ char(111),
+ char(110),
+ char(118),
+ char(101),
+ char(120),
+ char(73),
+ char(110),
+ char(116),
+ char(101),
+ char(114),
+ char(110),
+ char(97),
+ char(108),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(80),
+ char(111),
+ char(115),
+ char(105),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(65),
+ char(110),
+ char(100),
+ char(82),
+ char(97),
+ char(100),
+ char(105),
+ char(117),
+ char(115),
+ char(0),
+ char(98),
+ char(116),
+ char(77),
+ char(117),
+ char(108),
+ char(116),
+ char(105),
+ char(83),
+ char(112),
+ char(104),
+ char(101),
+ char(114),
+ char(101),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(73),
+ char(110),
+ char(116),
+ char(73),
+ char(110),
+ char(100),
+ char(101),
+ char(120),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(83),
+ char(104),
+ char(111),
+ char(114),
+ char(116),
+ char(73),
+ char(110),
+ char(116),
+ char(73),
+ char(110),
+ char(100),
+ char(101),
+ char(120),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(83),
+ char(104),
+ char(111),
+ char(114),
+ char(116),
+ char(73),
+ char(110),
+ char(116),
+ char(73),
+ char(110),
+ char(100),
+ char(101),
+ char(120),
+ char(84),
+ char(114),
+ char(105),
+ char(112),
+ char(108),
+ char(101),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(67),
+ char(104),
+ char(97),
+ char(114),
+ char(73),
+ char(110),
+ char(100),
+ char(101),
+ char(120),
+ char(84),
+ char(114),
+ char(105),
+ char(112),
+ char(108),
+ char(101),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(77),
+ char(101),
+ char(115),
+ char(104),
+ char(80),
+ char(97),
+ char(114),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(83),
+ char(116),
+ char(114),
+ char(105),
+ char(100),
+ char(105),
+ char(110),
+ char(103),
+ char(77),
+ char(101),
+ char(115),
+ char(104),
+ char(73),
+ char(110),
+ char(116),
+ char(101),
+ char(114),
+ char(102),
+ char(97),
+ char(99),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(84),
+ char(114),
+ char(105),
+ char(97),
+ char(110),
+ char(103),
+ char(108),
+ char(101),
+ char(77),
+ char(101),
+ char(115),
+ char(104),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(84),
+ char(114),
+ char(105),
+ char(97),
+ char(110),
+ char(103),
+ char(108),
+ char(101),
+ char(73),
+ char(110),
+ char(102),
+ char(111),
+ char(77),
+ char(97),
+ char(112),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(83),
+ char(99),
+ char(97),
+ char(108),
+ char(101),
+ char(100),
+ char(84),
+ char(114),
+ char(105),
+ char(97),
+ char(110),
+ char(103),
+ char(108),
+ char(101),
+ char(77),
+ char(101),
+ char(115),
+ char(104),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(67),
+ char(111),
+ char(109),
+ char(112),
+ char(111),
+ char(117),
+ char(110),
+ char(100),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(67),
+ char(104),
+ char(105),
+ char(108),
+ char(100),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(67),
+ char(111),
+ char(109),
+ char(112),
+ char(111),
+ char(117),
+ char(110),
+ char(100),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(67),
+ char(121),
+ char(108),
+ char(105),
+ char(110),
+ char(100),
+ char(101),
+ char(114),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(67),
+ char(97),
+ char(112),
+ char(115),
+ char(117),
+ char(108),
+ char(101),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(84),
+ char(114),
+ char(105),
+ char(97),
+ char(110),
+ char(103),
+ char(108),
+ char(101),
+ char(73),
+ char(110),
+ char(102),
+ char(111),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(71),
+ char(73),
+ char(109),
+ char(112),
+ char(97),
+ char(99),
+ char(116),
+ char(77),
+ char(101),
+ char(115),
+ char(104),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(67),
+ char(111),
+ char(110),
+ char(118),
+ char(101),
+ char(120),
+ char(72),
+ char(117),
+ char(108),
+ char(108),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(67),
+ char(111),
+ char(108),
+ char(108),
+ char(105),
+ char(115),
+ char(105),
+ char(111),
+ char(110),
+ char(79),
+ char(98),
+ char(106),
+ char(101),
+ char(99),
+ char(116),
+ char(68),
+ char(111),
+ char(117),
+ char(98),
+ char(108),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(67),
+ char(111),
+ char(108),
+ char(108),
+ char(105),
+ char(115),
+ char(105),
+ char(111),
+ char(110),
+ char(79),
+ char(98),
+ char(106),
+ char(101),
+ char(99),
+ char(116),
+ char(70),
+ char(108),
+ char(111),
+ char(97),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(68),
+ char(121),
+ char(110),
+ char(97),
+ char(109),
+ char(105),
+ char(99),
+ char(115),
+ char(87),
+ char(111),
+ char(114),
+ char(108),
+ char(100),
+ char(68),
+ char(111),
+ char(117),
+ char(98),
+ char(108),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(67),
+ char(111),
+ char(110),
+ char(116),
+ char(97),
+ char(99),
+ char(116),
+ char(83),
+ char(111),
+ char(108),
+ char(118),
+ char(101),
+ char(114),
+ char(73),
+ char(110),
+ char(102),
+ char(111),
+ char(68),
+ char(111),
+ char(117),
+ char(98),
+ char(108),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(68),
+ char(121),
+ char(110),
+ char(97),
+ char(109),
+ char(105),
+ char(99),
+ char(115),
+ char(87),
+ char(111),
+ char(114),
+ char(108),
+ char(100),
+ char(70),
+ char(108),
+ char(111),
+ char(97),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(67),
+ char(111),
+ char(110),
+ char(116),
+ char(97),
+ char(99),
+ char(116),
+ char(83),
+ char(111),
+ char(108),
+ char(118),
+ char(101),
+ char(114),
+ char(73),
+ char(110),
+ char(102),
+ char(111),
+ char(70),
+ char(108),
+ char(111),
+ char(97),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(82),
+ char(105),
+ char(103),
+ char(105),
+ char(100),
+ char(66),
+ char(111),
+ char(100),
+ char(121),
+ char(70),
+ char(108),
+ char(111),
+ char(97),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(82),
+ char(105),
+ char(103),
+ char(105),
+ char(100),
+ char(66),
+ char(111),
+ char(100),
+ char(121),
+ char(68),
+ char(111),
+ char(117),
+ char(98),
+ char(108),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(67),
+ char(111),
+ char(110),
+ char(115),
+ char(116),
+ char(114),
+ char(97),
+ char(105),
+ char(110),
+ char(116),
+ char(73),
+ char(110),
+ char(102),
+ char(111),
+ char(49),
+ char(0),
+ char(98),
+ char(116),
+ char(84),
+ char(121),
+ char(112),
+ char(101),
+ char(100),
+ char(67),
+ char(111),
+ char(110),
+ char(115),
+ char(116),
+ char(114),
+ char(97),
+ char(105),
+ char(110),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(82),
+ char(105),
+ char(103),
+ char(105),
+ char(100),
+ char(66),
+ char(111),
+ char(100),
+ char(121),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(80),
+ char(111),
+ char(105),
+ char(110),
+ char(116),
+ char(50),
+ char(80),
+ char(111),
+ char(105),
+ char(110),
+ char(116),
+ char(67),
+ char(111),
+ char(110),
+ char(115),
+ char(116),
+ char(114),
+ char(97),
+ char(105),
+ char(110),
+ char(116),
+ char(70),
+ char(108),
+ char(111),
+ char(97),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(80),
+ char(111),
+ char(105),
+ char(110),
+ char(116),
+ char(50),
+ char(80),
+ char(111),
+ char(105),
+ char(110),
+ char(116),
+ char(67),
+ char(111),
+ char(110),
+ char(115),
+ char(116),
+ char(114),
+ char(97),
+ char(105),
+ char(110),
+ char(116),
+ char(68),
+ char(111),
+ char(117),
+ char(98),
+ char(108),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(72),
+ char(105),
+ char(110),
+ char(103),
+ char(101),
+ char(67),
+ char(111),
+ char(110),
+ char(115),
+ char(116),
+ char(114),
+ char(97),
+ char(105),
+ char(110),
+ char(116),
+ char(68),
+ char(111),
+ char(117),
+ char(98),
+ char(108),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(72),
+ char(105),
+ char(110),
+ char(103),
+ char(101),
+ char(67),
+ char(111),
+ char(110),
+ char(115),
+ char(116),
+ char(114),
+ char(97),
+ char(105),
+ char(110),
+ char(116),
+ char(70),
+ char(108),
+ char(111),
+ char(97),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(67),
+ char(111),
+ char(110),
+ char(101),
+ char(84),
+ char(119),
+ char(105),
+ char(115),
+ char(116),
+ char(67),
+ char(111),
+ char(110),
+ char(115),
+ char(116),
+ char(114),
+ char(97),
+ char(105),
+ char(110),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(71),
+ char(101),
+ char(110),
+ char(101),
+ char(114),
+ char(105),
+ char(99),
+ char(54),
+ char(68),
+ char(111),
+ char(102),
+ char(67),
+ char(111),
+ char(110),
+ char(115),
+ char(116),
+ char(114),
+ char(97),
+ char(105),
+ char(110),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(71),
+ char(101),
+ char(110),
+ char(101),
+ char(114),
+ char(105),
+ char(99),
+ char(54),
+ char(68),
+ char(111),
+ char(102),
+ char(83),
+ char(112),
+ char(114),
+ char(105),
+ char(110),
+ char(103),
+ char(67),
+ char(111),
+ char(110),
+ char(115),
+ char(116),
+ char(114),
+ char(97),
+ char(105),
+ char(110),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(83),
+ char(108),
+ char(105),
+ char(100),
+ char(101),
+ char(114),
+ char(67),
+ char(111),
+ char(110),
+ char(115),
+ char(116),
+ char(114),
+ char(97),
+ char(105),
+ char(110),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(83),
+ char(111),
+ char(102),
+ char(116),
+ char(66),
+ char(111),
+ char(100),
+ char(121),
+ char(77),
+ char(97),
+ char(116),
+ char(101),
+ char(114),
+ char(105),
+ char(97),
+ char(108),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(83),
+ char(111),
+ char(102),
+ char(116),
+ char(66),
+ char(111),
+ char(100),
+ char(121),
+ char(78),
+ char(111),
+ char(100),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(83),
+ char(111),
+ char(102),
+ char(116),
+ char(66),
+ char(111),
+ char(100),
+ char(121),
+ char(76),
+ char(105),
+ char(110),
+ char(107),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(83),
+ char(111),
+ char(102),
+ char(116),
+ char(66),
+ char(111),
+ char(100),
+ char(121),
+ char(70),
+ char(97),
+ char(99),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(83),
+ char(111),
+ char(102),
+ char(116),
+ char(66),
+ char(111),
+ char(100),
+ char(121),
+ char(84),
+ char(101),
+ char(116),
+ char(114),
+ char(97),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(83),
+ char(111),
+ char(102),
+ char(116),
+ char(82),
+ char(105),
+ char(103),
+ char(105),
+ char(100),
+ char(65),
+ char(110),
+ char(99),
+ char(104),
+ char(111),
+ char(114),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(83),
+ char(111),
+ char(102),
+ char(116),
+ char(66),
+ char(111),
+ char(100),
+ char(121),
+ char(67),
+ char(111),
+ char(110),
+ char(102),
+ char(105),
+ char(103),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(83),
+ char(111),
+ char(102),
+ char(116),
+ char(66),
+ char(111),
+ char(100),
+ char(121),
+ char(80),
+ char(111),
+ char(115),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(83),
+ char(111),
+ char(102),
+ char(116),
+ char(66),
+ char(111),
+ char(100),
+ char(121),
+ char(67),
+ char(108),
+ char(117),
+ char(115),
+ char(116),
+ char(101),
+ char(114),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(83),
+ char(111),
+ char(102),
+ char(116),
+ char(66),
+ char(111),
+ char(100),
+ char(121),
+ char(74),
+ char(111),
+ char(105),
+ char(110),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(83),
+ char(111),
+ char(102),
+ char(116),
+ char(66),
+ char(111),
+ char(100),
+ char(121),
+ char(70),
+ char(108),
+ char(111),
+ char(97),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(0),
+ char(0),
+ char(84),
+ char(76),
+ char(69),
+ char(78),
+ char(1),
+ char(0),
+ char(1),
+ char(0),
+ char(2),
+ char(0),
+ char(2),
+ char(0),
+ char(4),
+ char(0),
+ char(4),
+ char(0),
+ char(4),
+ char(0),
+ char(4),
+ char(0),
+ char(8),
+ char(0),
+ char(0),
+ char(0),
+ char(12),
+ char(0),
+ char(36),
+ char(0),
+ char(8),
+ char(0),
+ char(16),
+ char(0),
+ char(32),
+ char(0),
+ char(48),
+ char(0),
+ char(96),
+ char(0),
+ char(64),
+ char(0),
+ char(-128),
+ char(0),
+ char(20),
+ char(0),
+ char(48),
+ char(0),
+ char(80),
+ char(0),
+ char(16),
+ char(0),
+ char(84),
+ char(0),
+ char(-124),
+ char(0),
+ char(12),
+ char(0),
+ char(52),
+ char(0),
+ char(52),
+ char(0),
+ char(20),
+ char(0),
+ char(64),
+ char(0),
+ char(4),
+ char(0),
+ char(4),
+ char(0),
+ char(8),
+ char(0),
+ char(4),
+ char(0),
+ char(32),
+ char(0),
+ char(28),
+ char(0),
+ char(60),
+ char(0),
+ char(56),
+ char(0),
+ char(76),
+ char(0),
+ char(76),
+ char(0),
+ char(24),
+ char(0),
+ char(60),
+ char(0),
+ char(60),
+ char(0),
+ char(16),
+ char(0),
+ char(64),
+ char(0),
+ char(68),
+ char(0),
+ char(-48),
+ char(1),
+ char(0),
+ char(1),
+ char(-72),
+ char(0),
+ char(-104),
+ char(0),
+ char(104),
+ char(0),
+ char(88),
+ char(0),
+ char(-24),
+ char(1),
+ char(-96),
+ char(3),
+ char(8),
+ char(0),
+ char(52),
+ char(0),
+ char(0),
+ char(0),
+ char(84),
+ char(0),
+ char(116),
+ char(0),
+ char(92),
+ char(1),
+ char(-36),
+ char(0),
+ char(-44),
+ char(0),
+ char(-4),
+ char(0),
+ char(92),
+ char(1),
+ char(-52),
+ char(0),
+ char(16),
+ char(0),
+ char(100),
+ char(0),
+ char(20),
+ char(0),
+ char(36),
+ char(0),
+ char(100),
+ char(0),
+ char(92),
+ char(0),
+ char(104),
+ char(0),
+ char(-64),
+ char(0),
+ char(92),
+ char(1),
+ char(104),
+ char(0),
+ char(-84),
+ char(1),
+ char(83),
+ char(84),
+ char(82),
+ char(67),
+ char(65),
+ char(0),
+ char(0),
+ char(0),
+ char(10),
+ char(0),
+ char(3),
+ char(0),
+ char(4),
+ char(0),
+ char(0),
+ char(0),
+ char(4),
+ char(0),
+ char(1),
+ char(0),
+ char(9),
+ char(0),
+ char(2),
+ char(0),
+ char(11),
+ char(0),
+ char(3),
+ char(0),
+ char(10),
+ char(0),
+ char(3),
+ char(0),
+ char(10),
+ char(0),
+ char(4),
+ char(0),
+ char(10),
+ char(0),
+ char(5),
+ char(0),
+ char(12),
+ char(0),
+ char(2),
+ char(0),
+ char(9),
+ char(0),
+ char(6),
+ char(0),
+ char(9),
+ char(0),
+ char(7),
+ char(0),
+ char(13),
+ char(0),
+ char(1),
+ char(0),
+ char(7),
+ char(0),
+ char(8),
+ char(0),
+ char(14),
+ char(0),
+ char(1),
+ char(0),
+ char(8),
+ char(0),
+ char(8),
+ char(0),
+ char(15),
+ char(0),
+ char(1),
+ char(0),
+ char(13),
+ char(0),
+ char(9),
+ char(0),
+ char(16),
+ char(0),
+ char(1),
+ char(0),
+ char(14),
+ char(0),
+ char(9),
+ char(0),
+ char(17),
+ char(0),
+ char(2),
+ char(0),
+ char(15),
+ char(0),
+ char(10),
+ char(0),
+ char(13),
+ char(0),
+ char(11),
+ char(0),
+ char(18),
+ char(0),
+ char(2),
+ char(0),
+ char(16),
+ char(0),
+ char(10),
+ char(0),
+ char(14),
+ char(0),
+ char(11),
+ char(0),
+ char(19),
+ char(0),
+ char(4),
+ char(0),
+ char(4),
+ char(0),
+ char(12),
+ char(0),
+ char(4),
+ char(0),
+ char(13),
+ char(0),
+ char(2),
+ char(0),
+ char(14),
+ char(0),
+ char(2),
+ char(0),
+ char(15),
+ char(0),
+ char(20),
+ char(0),
+ char(6),
+ char(0),
+ char(13),
+ char(0),
+ char(16),
+ char(0),
+ char(13),
+ char(0),
+ char(17),
+ char(0),
+ char(4),
+ char(0),
+ char(18),
+ char(0),
+ char(4),
+ char(0),
+ char(19),
+ char(0),
+ char(4),
+ char(0),
+ char(20),
+ char(0),
+ char(0),
+ char(0),
+ char(21),
+ char(0),
+ char(21),
+ char(0),
+ char(6),
+ char(0),
+ char(14),
+ char(0),
+ char(16),
+ char(0),
+ char(14),
+ char(0),
+ char(17),
+ char(0),
+ char(4),
+ char(0),
+ char(18),
+ char(0),
+ char(4),
+ char(0),
+ char(19),
+ char(0),
+ char(4),
+ char(0),
+ char(20),
+ char(0),
+ char(0),
+ char(0),
+ char(21),
+ char(0),
+ char(22),
+ char(0),
+ char(3),
+ char(0),
+ char(2),
+ char(0),
+ char(14),
+ char(0),
+ char(2),
+ char(0),
+ char(15),
+ char(0),
+ char(4),
+ char(0),
+ char(22),
+ char(0),
+ char(23),
+ char(0),
+ char(12),
+ char(0),
+ char(13),
+ char(0),
+ char(23),
+ char(0),
+ char(13),
+ char(0),
+ char(24),
+ char(0),
+ char(13),
+ char(0),
+ char(25),
+ char(0),
+ char(4),
+ char(0),
+ char(26),
+ char(0),
+ char(4),
+ char(0),
+ char(27),
+ char(0),
+ char(4),
+ char(0),
+ char(28),
+ char(0),
+ char(4),
+ char(0),
+ char(29),
+ char(0),
+ char(20),
+ char(0),
+ char(30),
+ char(0),
+ char(22),
+ char(0),
+ char(31),
+ char(0),
+ char(19),
+ char(0),
+ char(32),
+ char(0),
+ char(4),
+ char(0),
+ char(33),
+ char(0),
+ char(4),
+ char(0),
+ char(34),
+ char(0),
+ char(24),
+ char(0),
+ char(12),
+ char(0),
+ char(14),
+ char(0),
+ char(23),
+ char(0),
+ char(14),
+ char(0),
+ char(24),
+ char(0),
+ char(14),
+ char(0),
+ char(25),
+ char(0),
+ char(4),
+ char(0),
+ char(26),
+ char(0),
+ char(4),
+ char(0),
+ char(27),
+ char(0),
+ char(4),
+ char(0),
+ char(28),
+ char(0),
+ char(4),
+ char(0),
+ char(29),
+ char(0),
+ char(21),
+ char(0),
+ char(30),
+ char(0),
+ char(22),
+ char(0),
+ char(31),
+ char(0),
+ char(4),
+ char(0),
+ char(33),
+ char(0),
+ char(4),
+ char(0),
+ char(34),
+ char(0),
+ char(19),
+ char(0),
+ char(32),
+ char(0),
+ char(25),
+ char(0),
+ char(3),
+ char(0),
+ char(0),
+ char(0),
+ char(35),
+ char(0),
+ char(4),
+ char(0),
+ char(36),
+ char(0),
+ char(0),
+ char(0),
+ char(37),
+ char(0),
+ char(26),
+ char(0),
+ char(5),
+ char(0),
+ char(25),
+ char(0),
+ char(38),
+ char(0),
+ char(13),
+ char(0),
+ char(39),
+ char(0),
+ char(13),
+ char(0),
+ char(40),
+ char(0),
+ char(7),
+ char(0),
+ char(41),
+ char(0),
+ char(0),
+ char(0),
+ char(21),
+ char(0),
+ char(27),
+ char(0),
+ char(5),
+ char(0),
+ char(25),
+ char(0),
+ char(38),
+ char(0),
+ char(13),
+ char(0),
+ char(39),
+ char(0),
+ char(13),
+ char(0),
+ char(42),
+ char(0),
+ char(7),
+ char(0),
+ char(43),
+ char(0),
+ char(4),
+ char(0),
+ char(44),
+ char(0),
+ char(28),
+ char(0),
+ char(2),
+ char(0),
+ char(13),
+ char(0),
+ char(45),
+ char(0),
+ char(7),
+ char(0),
+ char(46),
+ char(0),
+ char(29),
+ char(0),
+ char(4),
+ char(0),
+ char(27),
+ char(0),
+ char(47),
+ char(0),
+ char(28),
+ char(0),
+ char(48),
+ char(0),
+ char(4),
+ char(0),
+ char(49),
+ char(0),
+ char(0),
+ char(0),
+ char(37),
+ char(0),
+ char(30),
+ char(0),
+ char(1),
+ char(0),
+ char(4),
+ char(0),
+ char(50),
+ char(0),
+ char(31),
+ char(0),
+ char(2),
+ char(0),
+ char(2),
+ char(0),
+ char(50),
+ char(0),
+ char(0),
+ char(0),
+ char(51),
+ char(0),
+ char(32),
+ char(0),
+ char(2),
+ char(0),
+ char(2),
+ char(0),
+ char(52),
+ char(0),
+ char(0),
+ char(0),
+ char(51),
+ char(0),
+ char(33),
+ char(0),
+ char(2),
+ char(0),
+ char(0),
+ char(0),
+ char(52),
+ char(0),
+ char(0),
+ char(0),
+ char(53),
+ char(0),
+ char(34),
+ char(0),
+ char(8),
+ char(0),
+ char(13),
+ char(0),
+ char(54),
+ char(0),
+ char(14),
+ char(0),
+ char(55),
+ char(0),
+ char(30),
+ char(0),
+ char(56),
+ char(0),
+ char(32),
+ char(0),
+ char(57),
+ char(0),
+ char(33),
+ char(0),
+ char(58),
+ char(0),
+ char(31),
+ char(0),
+ char(59),
+ char(0),
+ char(4),
+ char(0),
+ char(60),
+ char(0),
+ char(4),
+ char(0),
+ char(61),
+ char(0),
+ char(35),
+ char(0),
+ char(4),
+ char(0),
+ char(34),
+ char(0),
+ char(62),
+ char(0),
+ char(13),
+ char(0),
+ char(63),
+ char(0),
+ char(4),
+ char(0),
+ char(64),
+ char(0),
+ char(0),
+ char(0),
+ char(37),
+ char(0),
+ char(36),
+ char(0),
+ char(7),
+ char(0),
+ char(25),
+ char(0),
+ char(38),
+ char(0),
+ char(35),
+ char(0),
+ char(65),
+ char(0),
+ char(23),
+ char(0),
+ char(66),
+ char(0),
+ char(24),
+ char(0),
+ char(67),
+ char(0),
+ char(37),
+ char(0),
+ char(68),
+ char(0),
+ char(7),
+ char(0),
+ char(43),
+ char(0),
+ char(0),
+ char(0),
+ char(69),
+ char(0),
+ char(38),
+ char(0),
+ char(2),
+ char(0),
+ char(36),
+ char(0),
+ char(70),
+ char(0),
+ char(13),
+ char(0),
+ char(39),
+ char(0),
+ char(39),
+ char(0),
+ char(4),
+ char(0),
+ char(17),
+ char(0),
+ char(71),
+ char(0),
+ char(25),
+ char(0),
+ char(72),
+ char(0),
+ char(4),
+ char(0),
+ char(73),
+ char(0),
+ char(7),
+ char(0),
+ char(74),
+ char(0),
+ char(40),
+ char(0),
+ char(4),
+ char(0),
+ char(25),
+ char(0),
+ char(38),
+ char(0),
+ char(39),
+ char(0),
+ char(75),
+ char(0),
+ char(4),
+ char(0),
+ char(76),
+ char(0),
+ char(7),
+ char(0),
+ char(43),
+ char(0),
+ char(41),
+ char(0),
+ char(3),
+ char(0),
+ char(27),
+ char(0),
+ char(47),
+ char(0),
+ char(4),
+ char(0),
+ char(77),
+ char(0),
+ char(0),
+ char(0),
+ char(37),
+ char(0),
+ char(42),
+ char(0),
+ char(3),
+ char(0),
+ char(27),
+ char(0),
+ char(47),
+ char(0),
+ char(4),
+ char(0),
+ char(77),
+ char(0),
+ char(0),
+ char(0),
+ char(37),
+ char(0),
+ char(43),
+ char(0),
+ char(4),
+ char(0),
+ char(4),
+ char(0),
+ char(78),
+ char(0),
+ char(7),
+ char(0),
+ char(79),
+ char(0),
+ char(7),
+ char(0),
+ char(80),
+ char(0),
+ char(7),
+ char(0),
+ char(81),
+ char(0),
+ char(37),
+ char(0),
+ char(14),
+ char(0),
+ char(4),
+ char(0),
+ char(82),
+ char(0),
+ char(4),
+ char(0),
+ char(83),
+ char(0),
+ char(43),
+ char(0),
+ char(84),
+ char(0),
+ char(4),
+ char(0),
+ char(85),
+ char(0),
+ char(7),
+ char(0),
+ char(86),
+ char(0),
+ char(7),
+ char(0),
+ char(87),
+ char(0),
+ char(7),
+ char(0),
+ char(88),
+ char(0),
+ char(7),
+ char(0),
+ char(89),
+ char(0),
+ char(7),
+ char(0),
+ char(90),
+ char(0),
+ char(4),
+ char(0),
+ char(91),
+ char(0),
+ char(4),
+ char(0),
+ char(92),
+ char(0),
+ char(4),
+ char(0),
+ char(93),
+ char(0),
+ char(4),
+ char(0),
+ char(94),
+ char(0),
+ char(0),
+ char(0),
+ char(37),
+ char(0),
+ char(44),
+ char(0),
+ char(5),
+ char(0),
+ char(25),
+ char(0),
+ char(38),
+ char(0),
+ char(35),
+ char(0),
+ char(65),
+ char(0),
+ char(13),
+ char(0),
+ char(39),
+ char(0),
+ char(7),
+ char(0),
+ char(43),
+ char(0),
+ char(4),
+ char(0),
+ char(95),
+ char(0),
+ char(45),
+ char(0),
+ char(5),
+ char(0),
+ char(27),
+ char(0),
+ char(47),
+ char(0),
+ char(13),
+ char(0),
+ char(96),
+ char(0),
+ char(14),
+ char(0),
+ char(97),
+ char(0),
+ char(4),
+ char(0),
+ char(98),
+ char(0),
+ char(0),
+ char(0),
+ char(99),
+ char(0),
+ char(46),
+ char(0),
+ char(25),
+ char(0),
+ char(9),
+ char(0),
+ char(100),
+ char(0),
+ char(9),
+ char(0),
+ char(101),
+ char(0),
+ char(25),
+ char(0),
+ char(102),
+ char(0),
+ char(0),
+ char(0),
+ char(35),
+ char(0),
+ char(18),
+ char(0),
+ char(103),
+ char(0),
+ char(18),
+ char(0),
+ char(104),
+ char(0),
+ char(14),
+ char(0),
+ char(105),
+ char(0),
+ char(14),
+ char(0),
+ char(106),
+ char(0),
+ char(14),
+ char(0),
+ char(107),
+ char(0),
+ char(8),
+ char(0),
+ char(108),
+ char(0),
+ char(8),
+ char(0),
+ char(109),
+ char(0),
+ char(8),
+ char(0),
+ char(110),
+ char(0),
+ char(8),
+ char(0),
+ char(111),
+ char(0),
+ char(8),
+ char(0),
+ char(112),
+ char(0),
+ char(8),
+ char(0),
+ char(113),
+ char(0),
+ char(8),
+ char(0),
+ char(114),
+ char(0),
+ char(8),
+ char(0),
+ char(115),
+ char(0),
+ char(4),
+ char(0),
+ char(116),
+ char(0),
+ char(4),
+ char(0),
+ char(117),
+ char(0),
+ char(4),
+ char(0),
+ char(118),
+ char(0),
+ char(4),
+ char(0),
+ char(119),
+ char(0),
+ char(4),
+ char(0),
+ char(120),
+ char(0),
+ char(4),
+ char(0),
+ char(121),
+ char(0),
+ char(4),
+ char(0),
+ char(122),
+ char(0),
+ char(0),
+ char(0),
+ char(37),
+ char(0),
+ char(47),
+ char(0),
+ char(25),
+ char(0),
+ char(9),
+ char(0),
+ char(100),
+ char(0),
+ char(9),
+ char(0),
+ char(101),
+ char(0),
+ char(25),
+ char(0),
+ char(102),
+ char(0),
+ char(0),
+ char(0),
+ char(35),
+ char(0),
+ char(17),
+ char(0),
+ char(103),
+ char(0),
+ char(17),
+ char(0),
+ char(104),
+ char(0),
+ char(13),
+ char(0),
+ char(105),
+ char(0),
+ char(13),
+ char(0),
+ char(106),
+ char(0),
+ char(13),
+ char(0),
+ char(107),
+ char(0),
+ char(7),
+ char(0),
+ char(108),
+ char(0),
+ char(7),
+ char(0),
+ char(109),
+ char(0),
+ char(7),
+ char(0),
+ char(110),
+ char(0),
+ char(7),
+ char(0),
+ char(111),
+ char(0),
+ char(7),
+ char(0),
+ char(112),
+ char(0),
+ char(7),
+ char(0),
+ char(113),
+ char(0),
+ char(7),
+ char(0),
+ char(114),
+ char(0),
+ char(7),
+ char(0),
+ char(115),
+ char(0),
+ char(4),
+ char(0),
+ char(116),
+ char(0),
+ char(4),
+ char(0),
+ char(117),
+ char(0),
+ char(4),
+ char(0),
+ char(118),
+ char(0),
+ char(4),
+ char(0),
+ char(119),
+ char(0),
+ char(4),
+ char(0),
+ char(120),
+ char(0),
+ char(4),
+ char(0),
+ char(121),
+ char(0),
+ char(4),
+ char(0),
+ char(122),
+ char(0),
+ char(0),
+ char(0),
+ char(37),
+ char(0),
+ char(48),
+ char(0),
+ char(2),
+ char(0),
+ char(49),
+ char(0),
+ char(123),
+ char(0),
+ char(14),
+ char(0),
+ char(124),
+ char(0),
+ char(50),
+ char(0),
+ char(2),
+ char(0),
+ char(51),
+ char(0),
+ char(123),
+ char(0),
+ char(13),
+ char(0),
+ char(124),
+ char(0),
+ char(52),
+ char(0),
+ char(21),
+ char(0),
+ char(47),
+ char(0),
+ char(125),
+ char(0),
+ char(15),
+ char(0),
+ char(126),
+ char(0),
+ char(13),
+ char(0),
+ char(127),
+ char(0),
+ char(13),
+ char(0),
+ char(-128),
+ char(0),
+ char(13),
+ char(0),
+ char(-127),
+ char(0),
+ char(13),
+ char(0),
+ char(-126),
+ char(0),
+ char(13),
+ char(0),
+ char(124),
+ char(0),
+ char(13),
+ char(0),
+ char(-125),
+ char(0),
+ char(13),
+ char(0),
+ char(-124),
+ char(0),
+ char(13),
+ char(0),
+ char(-123),
+ char(0),
+ char(13),
+ char(0),
+ char(-122),
+ char(0),
+ char(7),
+ char(0),
+ char(-121),
+ char(0),
+ char(7),
+ char(0),
+ char(-120),
+ char(0),
+ char(7),
+ char(0),
+ char(-119),
+ char(0),
+ char(7),
+ char(0),
+ char(-118),
+ char(0),
+ char(7),
+ char(0),
+ char(-117),
+ char(0),
+ char(7),
+ char(0),
+ char(-116),
+ char(0),
+ char(7),
+ char(0),
+ char(-115),
+ char(0),
+ char(7),
+ char(0),
+ char(-114),
+ char(0),
+ char(7),
+ char(0),
+ char(-113),
+ char(0),
+ char(4),
+ char(0),
+ char(-112),
+ char(0),
+ char(53),
+ char(0),
+ char(22),
+ char(0),
+ char(46),
+ char(0),
+ char(125),
+ char(0),
+ char(16),
+ char(0),
+ char(126),
+ char(0),
+ char(14),
+ char(0),
+ char(127),
+ char(0),
+ char(14),
+ char(0),
+ char(-128),
+ char(0),
+ char(14),
+ char(0),
+ char(-127),
+ char(0),
+ char(14),
+ char(0),
+ char(-126),
+ char(0),
+ char(14),
+ char(0),
+ char(124),
+ char(0),
+ char(14),
+ char(0),
+ char(-125),
+ char(0),
+ char(14),
+ char(0),
+ char(-124),
+ char(0),
+ char(14),
+ char(0),
+ char(-123),
+ char(0),
+ char(14),
+ char(0),
+ char(-122),
+ char(0),
+ char(8),
+ char(0),
+ char(-121),
+ char(0),
+ char(8),
+ char(0),
+ char(-120),
+ char(0),
+ char(8),
+ char(0),
+ char(-119),
+ char(0),
+ char(8),
+ char(0),
+ char(-118),
+ char(0),
+ char(8),
+ char(0),
+ char(-117),
+ char(0),
+ char(8),
+ char(0),
+ char(-116),
+ char(0),
+ char(8),
+ char(0),
+ char(-115),
+ char(0),
+ char(8),
+ char(0),
+ char(-114),
+ char(0),
+ char(8),
+ char(0),
+ char(-113),
+ char(0),
+ char(4),
+ char(0),
+ char(-112),
+ char(0),
+ char(0),
+ char(0),
+ char(37),
+ char(0),
+ char(54),
+ char(0),
+ char(2),
+ char(0),
+ char(4),
+ char(0),
+ char(-111),
+ char(0),
+ char(4),
+ char(0),
+ char(-110),
+ char(0),
+ char(55),
+ char(0),
+ char(13),
+ char(0),
+ char(56),
+ char(0),
+ char(-109),
+ char(0),
+ char(56),
+ char(0),
+ char(-108),
+ char(0),
+ char(0),
+ char(0),
+ char(35),
+ char(0),
+ char(4),
+ char(0),
+ char(-107),
+ char(0),
+ char(4),
+ char(0),
+ char(-106),
+ char(0),
+ char(4),
+ char(0),
+ char(-105),
+ char(0),
+ char(4),
+ char(0),
+ char(-104),
+ char(0),
+ char(7),
+ char(0),
+ char(-103),
+ char(0),
+ char(7),
+ char(0),
+ char(-102),
+ char(0),
+ char(4),
+ char(0),
+ char(-101),
+ char(0),
+ char(4),
+ char(0),
+ char(-100),
+ char(0),
+ char(7),
+ char(0),
+ char(-99),
+ char(0),
+ char(4),
+ char(0),
+ char(-98),
+ char(0),
+ char(57),
+ char(0),
+ char(3),
+ char(0),
+ char(55),
+ char(0),
+ char(-97),
+ char(0),
+ char(13),
+ char(0),
+ char(-96),
+ char(0),
+ char(13),
+ char(0),
+ char(-95),
+ char(0),
+ char(58),
+ char(0),
+ char(3),
+ char(0),
+ char(55),
+ char(0),
+ char(-97),
+ char(0),
+ char(14),
+ char(0),
+ char(-96),
+ char(0),
+ char(14),
+ char(0),
+ char(-95),
+ char(0),
+ char(59),
+ char(0),
+ char(13),
+ char(0),
+ char(55),
+ char(0),
+ char(-97),
+ char(0),
+ char(18),
+ char(0),
+ char(-94),
+ char(0),
+ char(18),
+ char(0),
+ char(-93),
+ char(0),
+ char(4),
+ char(0),
+ char(-92),
+ char(0),
+ char(4),
+ char(0),
+ char(-91),
+ char(0),
+ char(4),
+ char(0),
+ char(-90),
+ char(0),
+ char(7),
+ char(0),
+ char(-89),
+ char(0),
+ char(7),
+ char(0),
+ char(-88),
+ char(0),
+ char(7),
+ char(0),
+ char(-87),
+ char(0),
+ char(7),
+ char(0),
+ char(-86),
+ char(0),
+ char(7),
+ char(0),
+ char(-85),
+ char(0),
+ char(7),
+ char(0),
+ char(-84),
+ char(0),
+ char(7),
+ char(0),
+ char(-83),
+ char(0),
+ char(60),
+ char(0),
+ char(13),
+ char(0),
+ char(55),
+ char(0),
+ char(-97),
+ char(0),
+ char(17),
+ char(0),
+ char(-94),
+ char(0),
+ char(17),
+ char(0),
+ char(-93),
+ char(0),
+ char(4),
+ char(0),
+ char(-92),
+ char(0),
+ char(4),
+ char(0),
+ char(-91),
+ char(0),
+ char(4),
+ char(0),
+ char(-90),
+ char(0),
+ char(7),
+ char(0),
+ char(-89),
+ char(0),
+ char(7),
+ char(0),
+ char(-88),
+ char(0),
+ char(7),
+ char(0),
+ char(-87),
+ char(0),
+ char(7),
+ char(0),
+ char(-86),
+ char(0),
+ char(7),
+ char(0),
+ char(-85),
+ char(0),
+ char(7),
+ char(0),
+ char(-84),
+ char(0),
+ char(7),
+ char(0),
+ char(-83),
+ char(0),
+ char(61),
+ char(0),
+ char(11),
+ char(0),
+ char(55),
+ char(0),
+ char(-97),
+ char(0),
+ char(17),
+ char(0),
+ char(-94),
+ char(0),
+ char(17),
+ char(0),
+ char(-93),
+ char(0),
+ char(7),
+ char(0),
+ char(-82),
+ char(0),
+ char(7),
+ char(0),
+ char(-81),
+ char(0),
+ char(7),
+ char(0),
+ char(-80),
+ char(0),
+ char(7),
+ char(0),
+ char(-85),
+ char(0),
+ char(7),
+ char(0),
+ char(-84),
+ char(0),
+ char(7),
+ char(0),
+ char(-83),
+ char(0),
+ char(7),
+ char(0),
+ char(-79),
+ char(0),
+ char(0),
+ char(0),
+ char(21),
+ char(0),
+ char(62),
+ char(0),
+ char(9),
+ char(0),
+ char(55),
+ char(0),
+ char(-97),
+ char(0),
+ char(17),
+ char(0),
+ char(-94),
+ char(0),
+ char(17),
+ char(0),
+ char(-93),
+ char(0),
+ char(13),
+ char(0),
+ char(-78),
+ char(0),
+ char(13),
+ char(0),
+ char(-77),
+ char(0),
+ char(13),
+ char(0),
+ char(-76),
+ char(0),
+ char(13),
+ char(0),
+ char(-75),
+ char(0),
+ char(4),
+ char(0),
+ char(-74),
+ char(0),
+ char(4),
+ char(0),
+ char(-73),
+ char(0),
+ char(63),
+ char(0),
+ char(5),
+ char(0),
+ char(62),
+ char(0),
+ char(-72),
+ char(0),
+ char(4),
+ char(0),
+ char(-71),
+ char(0),
+ char(7),
+ char(0),
+ char(-70),
+ char(0),
+ char(7),
+ char(0),
+ char(-69),
+ char(0),
+ char(7),
+ char(0),
+ char(-68),
+ char(0),
+ char(64),
+ char(0),
+ char(9),
+ char(0),
+ char(55),
+ char(0),
+ char(-97),
+ char(0),
+ char(17),
+ char(0),
+ char(-94),
+ char(0),
+ char(17),
+ char(0),
+ char(-93),
+ char(0),
+ char(7),
+ char(0),
+ char(-78),
+ char(0),
+ char(7),
+ char(0),
+ char(-77),
+ char(0),
+ char(7),
+ char(0),
+ char(-76),
+ char(0),
+ char(7),
+ char(0),
+ char(-75),
+ char(0),
+ char(4),
+ char(0),
+ char(-74),
+ char(0),
+ char(4),
+ char(0),
+ char(-73),
+ char(0),
+ char(49),
+ char(0),
+ char(22),
+ char(0),
+ char(8),
+ char(0),
+ char(-67),
+ char(0),
+ char(8),
+ char(0),
+ char(-79),
+ char(0),
+ char(8),
+ char(0),
+ char(110),
+ char(0),
+ char(8),
+ char(0),
+ char(-66),
+ char(0),
+ char(8),
+ char(0),
+ char(112),
+ char(0),
+ char(8),
+ char(0),
+ char(-65),
+ char(0),
+ char(8),
+ char(0),
+ char(-64),
+ char(0),
+ char(8),
+ char(0),
+ char(-63),
+ char(0),
+ char(8),
+ char(0),
+ char(-62),
+ char(0),
+ char(8),
+ char(0),
+ char(-61),
+ char(0),
+ char(8),
+ char(0),
+ char(-60),
+ char(0),
+ char(8),
+ char(0),
+ char(-59),
+ char(0),
+ char(8),
+ char(0),
+ char(-58),
+ char(0),
+ char(8),
+ char(0),
+ char(-57),
+ char(0),
+ char(8),
+ char(0),
+ char(-56),
+ char(0),
+ char(8),
+ char(0),
+ char(-55),
+ char(0),
+ char(4),
+ char(0),
+ char(-54),
+ char(0),
+ char(4),
+ char(0),
+ char(-53),
+ char(0),
+ char(4),
+ char(0),
+ char(-52),
+ char(0),
+ char(4),
+ char(0),
+ char(-51),
+ char(0),
+ char(4),
+ char(0),
+ char(-50),
+ char(0),
+ char(0),
+ char(0),
+ char(37),
+ char(0),
+ char(51),
+ char(0),
+ char(22),
+ char(0),
+ char(7),
+ char(0),
+ char(-67),
+ char(0),
+ char(7),
+ char(0),
+ char(-79),
+ char(0),
+ char(7),
+ char(0),
+ char(110),
+ char(0),
+ char(7),
+ char(0),
+ char(-66),
+ char(0),
+ char(7),
+ char(0),
+ char(112),
+ char(0),
+ char(7),
+ char(0),
+ char(-65),
+ char(0),
+ char(7),
+ char(0),
+ char(-64),
+ char(0),
+ char(7),
+ char(0),
+ char(-63),
+ char(0),
+ char(7),
+ char(0),
+ char(-62),
+ char(0),
+ char(7),
+ char(0),
+ char(-61),
+ char(0),
+ char(7),
+ char(0),
+ char(-60),
+ char(0),
+ char(7),
+ char(0),
+ char(-59),
+ char(0),
+ char(7),
+ char(0),
+ char(-58),
+ char(0),
+ char(7),
+ char(0),
+ char(-57),
+ char(0),
+ char(7),
+ char(0),
+ char(-56),
+ char(0),
+ char(7),
+ char(0),
+ char(-55),
+ char(0),
+ char(4),
+ char(0),
+ char(-54),
+ char(0),
+ char(4),
+ char(0),
+ char(-53),
+ char(0),
+ char(4),
+ char(0),
+ char(-52),
+ char(0),
+ char(4),
+ char(0),
+ char(-51),
+ char(0),
+ char(4),
+ char(0),
+ char(-50),
+ char(0),
+ char(0),
+ char(0),
+ char(37),
+ char(0),
+ char(65),
+ char(0),
+ char(4),
+ char(0),
+ char(7),
+ char(0),
+ char(-49),
+ char(0),
+ char(7),
+ char(0),
+ char(-48),
+ char(0),
+ char(7),
+ char(0),
+ char(-47),
+ char(0),
+ char(4),
+ char(0),
+ char(78),
+ char(0),
+ char(66),
+ char(0),
+ char(10),
+ char(0),
+ char(65),
+ char(0),
+ char(-46),
+ char(0),
+ char(13),
+ char(0),
+ char(-45),
+ char(0),
+ char(13),
+ char(0),
+ char(-44),
+ char(0),
+ char(13),
+ char(0),
+ char(-43),
+ char(0),
+ char(13),
+ char(0),
+ char(-42),
+ char(0),
+ char(13),
+ char(0),
+ char(-41),
+ char(0),
+ char(7),
+ char(0),
+ char(-121),
+ char(0),
+ char(7),
+ char(0),
+ char(-40),
+ char(0),
+ char(4),
+ char(0),
+ char(-39),
+ char(0),
+ char(4),
+ char(0),
+ char(53),
+ char(0),
+ char(67),
+ char(0),
+ char(4),
+ char(0),
+ char(65),
+ char(0),
+ char(-46),
+ char(0),
+ char(4),
+ char(0),
+ char(-38),
+ char(0),
+ char(7),
+ char(0),
+ char(-37),
+ char(0),
+ char(4),
+ char(0),
+ char(-36),
+ char(0),
+ char(68),
+ char(0),
+ char(4),
+ char(0),
+ char(13),
+ char(0),
+ char(-41),
+ char(0),
+ char(65),
+ char(0),
+ char(-46),
+ char(0),
+ char(4),
+ char(0),
+ char(-35),
+ char(0),
+ char(7),
+ char(0),
+ char(-34),
+ char(0),
+ char(69),
+ char(0),
+ char(7),
+ char(0),
+ char(13),
+ char(0),
+ char(-33),
+ char(0),
+ char(65),
+ char(0),
+ char(-46),
+ char(0),
+ char(4),
+ char(0),
+ char(-32),
+ char(0),
+ char(7),
+ char(0),
+ char(-31),
+ char(0),
+ char(7),
+ char(0),
+ char(-30),
+ char(0),
+ char(7),
+ char(0),
+ char(-29),
+ char(0),
+ char(4),
+ char(0),
+ char(53),
+ char(0),
+ char(70),
+ char(0),
+ char(6),
+ char(0),
+ char(15),
+ char(0),
+ char(-28),
+ char(0),
+ char(13),
+ char(0),
+ char(-30),
+ char(0),
+ char(13),
+ char(0),
+ char(-27),
+ char(0),
+ char(56),
+ char(0),
+ char(-26),
+ char(0),
+ char(4),
+ char(0),
+ char(-25),
+ char(0),
+ char(7),
+ char(0),
+ char(-29),
+ char(0),
+ char(71),
+ char(0),
+ char(26),
+ char(0),
+ char(4),
+ char(0),
+ char(-24),
+ char(0),
+ char(7),
+ char(0),
+ char(-23),
+ char(0),
+ char(7),
+ char(0),
+ char(-79),
+ char(0),
+ char(7),
+ char(0),
+ char(-22),
+ char(0),
+ char(7),
+ char(0),
+ char(-21),
+ char(0),
+ char(7),
+ char(0),
+ char(-20),
+ char(0),
+ char(7),
+ char(0),
+ char(-19),
+ char(0),
+ char(7),
+ char(0),
+ char(-18),
+ char(0),
+ char(7),
+ char(0),
+ char(-17),
+ char(0),
+ char(7),
+ char(0),
+ char(-16),
+ char(0),
+ char(7),
+ char(0),
+ char(-15),
+ char(0),
+ char(7),
+ char(0),
+ char(-14),
+ char(0),
+ char(7),
+ char(0),
+ char(-13),
+ char(0),
+ char(7),
+ char(0),
+ char(-12),
+ char(0),
+ char(7),
+ char(0),
+ char(-11),
+ char(0),
+ char(7),
+ char(0),
+ char(-10),
+ char(0),
+ char(7),
+ char(0),
+ char(-9),
+ char(0),
+ char(7),
+ char(0),
+ char(-8),
+ char(0),
+ char(7),
+ char(0),
+ char(-7),
+ char(0),
+ char(7),
+ char(0),
+ char(-6),
+ char(0),
+ char(7),
+ char(0),
+ char(-5),
+ char(0),
+ char(4),
+ char(0),
+ char(-4),
+ char(0),
+ char(4),
+ char(0),
+ char(-3),
+ char(0),
+ char(4),
+ char(0),
+ char(-2),
+ char(0),
+ char(4),
+ char(0),
+ char(-1),
+ char(0),
+ char(4),
+ char(0),
+ char(117),
+ char(0),
+ char(72),
+ char(0),
+ char(12),
+ char(0),
+ char(15),
+ char(0),
+ char(0),
+ char(1),
+ char(15),
+ char(0),
+ char(1),
+ char(1),
+ char(15),
+ char(0),
+ char(2),
+ char(1),
+ char(13),
+ char(0),
+ char(3),
+ char(1),
+ char(13),
+ char(0),
+ char(4),
+ char(1),
+ char(7),
+ char(0),
+ char(5),
+ char(1),
+ char(4),
+ char(0),
+ char(6),
+ char(1),
+ char(4),
+ char(0),
+ char(7),
+ char(1),
+ char(4),
+ char(0),
+ char(8),
+ char(1),
+ char(4),
+ char(0),
+ char(9),
+ char(1),
+ char(7),
+ char(0),
+ char(-31),
+ char(0),
+ char(4),
+ char(0),
+ char(53),
+ char(0),
+ char(73),
+ char(0),
+ char(27),
+ char(0),
+ char(17),
+ char(0),
+ char(10),
+ char(1),
+ char(15),
+ char(0),
+ char(11),
+ char(1),
+ char(15),
+ char(0),
+ char(12),
+ char(1),
+ char(13),
+ char(0),
+ char(3),
+ char(1),
+ char(13),
+ char(0),
+ char(13),
+ char(1),
+ char(13),
+ char(0),
+ char(14),
+ char(1),
+ char(13),
+ char(0),
+ char(15),
+ char(1),
+ char(13),
+ char(0),
+ char(16),
+ char(1),
+ char(13),
+ char(0),
+ char(17),
+ char(1),
+ char(4),
+ char(0),
+ char(18),
+ char(1),
+ char(7),
+ char(0),
+ char(19),
+ char(1),
+ char(4),
+ char(0),
+ char(20),
+ char(1),
+ char(4),
+ char(0),
+ char(21),
+ char(1),
+ char(4),
+ char(0),
+ char(22),
+ char(1),
+ char(7),
+ char(0),
+ char(23),
+ char(1),
+ char(7),
+ char(0),
+ char(24),
+ char(1),
+ char(4),
+ char(0),
+ char(25),
+ char(1),
+ char(4),
+ char(0),
+ char(26),
+ char(1),
+ char(7),
+ char(0),
+ char(27),
+ char(1),
+ char(7),
+ char(0),
+ char(28),
+ char(1),
+ char(7),
+ char(0),
+ char(29),
+ char(1),
+ char(7),
+ char(0),
+ char(30),
+ char(1),
+ char(7),
+ char(0),
+ char(31),
+ char(1),
+ char(7),
+ char(0),
+ char(32),
+ char(1),
+ char(4),
+ char(0),
+ char(33),
+ char(1),
+ char(4),
+ char(0),
+ char(34),
+ char(1),
+ char(4),
+ char(0),
+ char(35),
+ char(1),
+ char(74),
+ char(0),
+ char(12),
+ char(0),
+ char(9),
+ char(0),
+ char(36),
+ char(1),
+ char(9),
+ char(0),
+ char(37),
+ char(1),
+ char(13),
+ char(0),
+ char(38),
+ char(1),
+ char(7),
+ char(0),
+ char(39),
+ char(1),
+ char(7),
+ char(0),
+ char(-63),
+ char(0),
+ char(7),
+ char(0),
+ char(40),
+ char(1),
+ char(4),
+ char(0),
+ char(41),
+ char(1),
+ char(13),
+ char(0),
+ char(42),
+ char(1),
+ char(4),
+ char(0),
+ char(43),
+ char(1),
+ char(4),
+ char(0),
+ char(44),
+ char(1),
+ char(4),
+ char(0),
+ char(45),
+ char(1),
+ char(4),
+ char(0),
+ char(53),
+ char(0),
+ char(75),
+ char(0),
+ char(19),
+ char(0),
+ char(47),
+ char(0),
+ char(125),
+ char(0),
+ char(72),
+ char(0),
+ char(46),
+ char(1),
+ char(65),
+ char(0),
+ char(47),
+ char(1),
+ char(66),
+ char(0),
+ char(48),
+ char(1),
+ char(67),
+ char(0),
+ char(49),
+ char(1),
+ char(68),
+ char(0),
+ char(50),
+ char(1),
+ char(69),
+ char(0),
+ char(51),
+ char(1),
+ char(70),
+ char(0),
+ char(52),
+ char(1),
+ char(73),
+ char(0),
+ char(53),
+ char(1),
+ char(74),
+ char(0),
+ char(54),
+ char(1),
+ char(4),
+ char(0),
+ char(55),
+ char(1),
+ char(4),
+ char(0),
+ char(21),
+ char(1),
+ char(4),
+ char(0),
+ char(56),
+ char(1),
+ char(4),
+ char(0),
+ char(57),
+ char(1),
+ char(4),
+ char(0),
+ char(58),
+ char(1),
+ char(4),
+ char(0),
+ char(59),
+ char(1),
+ char(4),
+ char(0),
+ char(60),
+ char(1),
+ char(4),
+ char(0),
+ char(61),
+ char(1),
+ char(71),
+ char(0),
+ char(62),
+ char(1),
+};
+int b3s_bulletDNAlen = sizeof(b3s_bulletDNAstr);
+char b3s_bulletDNAstr64[] = {
+ char(83),
+ char(68),
+ char(78),
+ char(65),
+ char(78),
+ char(65),
+ char(77),
+ char(69),
+ char(63),
+ char(1),
+ char(0),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(105),
+ char(122),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(97),
+ char(112),
+ char(97),
+ char(99),
+ char(105),
+ char(116),
+ char(121),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(100),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(111),
+ char(108),
+ char(108),
+ char(105),
+ char(115),
+ char(105),
+ char(111),
+ char(110),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(111),
+ char(108),
+ char(108),
+ char(105),
+ char(115),
+ char(105),
+ char(111),
+ char(110),
+ char(79),
+ char(98),
+ char(106),
+ char(101),
+ char(99),
+ char(116),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(111),
+ char(110),
+ char(115),
+ char(116),
+ char(114),
+ char(97),
+ char(105),
+ char(110),
+ char(116),
+ char(115),
+ char(0),
+ char(42),
+ char(102),
+ char(105),
+ char(114),
+ char(115),
+ char(116),
+ char(0),
+ char(42),
+ char(108),
+ char(97),
+ char(115),
+ char(116),
+ char(0),
+ char(109),
+ char(95),
+ char(102),
+ char(108),
+ char(111),
+ char(97),
+ char(116),
+ char(115),
+ char(91),
+ char(52),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(101),
+ char(108),
+ char(91),
+ char(51),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(98),
+ char(97),
+ char(115),
+ char(105),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(111),
+ char(114),
+ char(105),
+ char(103),
+ char(105),
+ char(110),
+ char(0),
+ char(109),
+ char(95),
+ char(114),
+ char(111),
+ char(111),
+ char(116),
+ char(78),
+ char(111),
+ char(100),
+ char(101),
+ char(73),
+ char(110),
+ char(100),
+ char(101),
+ char(120),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(117),
+ char(98),
+ char(116),
+ char(114),
+ char(101),
+ char(101),
+ char(83),
+ char(105),
+ char(122),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(113),
+ char(117),
+ char(97),
+ char(110),
+ char(116),
+ char(105),
+ char(122),
+ char(101),
+ char(100),
+ char(65),
+ char(97),
+ char(98),
+ char(98),
+ char(77),
+ char(105),
+ char(110),
+ char(91),
+ char(51),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(113),
+ char(117),
+ char(97),
+ char(110),
+ char(116),
+ char(105),
+ char(122),
+ char(101),
+ char(100),
+ char(65),
+ char(97),
+ char(98),
+ char(98),
+ char(77),
+ char(97),
+ char(120),
+ char(91),
+ char(51),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(97),
+ char(98),
+ char(98),
+ char(77),
+ char(105),
+ char(110),
+ char(79),
+ char(114),
+ char(103),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(97),
+ char(98),
+ char(98),
+ char(77),
+ char(97),
+ char(120),
+ char(79),
+ char(114),
+ char(103),
+ char(0),
+ char(109),
+ char(95),
+ char(101),
+ char(115),
+ char(99),
+ char(97),
+ char(112),
+ char(101),
+ char(73),
+ char(110),
+ char(100),
+ char(101),
+ char(120),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(117),
+ char(98),
+ char(80),
+ char(97),
+ char(114),
+ char(116),
+ char(0),
+ char(109),
+ char(95),
+ char(116),
+ char(114),
+ char(105),
+ char(97),
+ char(110),
+ char(103),
+ char(108),
+ char(101),
+ char(73),
+ char(110),
+ char(100),
+ char(101),
+ char(120),
+ char(0),
+ char(109),
+ char(95),
+ char(112),
+ char(97),
+ char(100),
+ char(91),
+ char(52),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(101),
+ char(115),
+ char(99),
+ char(97),
+ char(112),
+ char(101),
+ char(73),
+ char(110),
+ char(100),
+ char(101),
+ char(120),
+ char(79),
+ char(114),
+ char(84),
+ char(114),
+ char(105),
+ char(97),
+ char(110),
+ char(103),
+ char(108),
+ char(101),
+ char(73),
+ char(110),
+ char(100),
+ char(101),
+ char(120),
+ char(0),
+ char(109),
+ char(95),
+ char(98),
+ char(118),
+ char(104),
+ char(65),
+ char(97),
+ char(98),
+ char(98),
+ char(77),
+ char(105),
+ char(110),
+ char(0),
+ char(109),
+ char(95),
+ char(98),
+ char(118),
+ char(104),
+ char(65),
+ char(97),
+ char(98),
+ char(98),
+ char(77),
+ char(97),
+ char(120),
+ char(0),
+ char(109),
+ char(95),
+ char(98),
+ char(118),
+ char(104),
+ char(81),
+ char(117),
+ char(97),
+ char(110),
+ char(116),
+ char(105),
+ char(122),
+ char(97),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(117),
+ char(114),
+ char(78),
+ char(111),
+ char(100),
+ char(101),
+ char(73),
+ char(110),
+ char(100),
+ char(101),
+ char(120),
+ char(0),
+ char(109),
+ char(95),
+ char(117),
+ char(115),
+ char(101),
+ char(81),
+ char(117),
+ char(97),
+ char(110),
+ char(116),
+ char(105),
+ char(122),
+ char(97),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(67),
+ char(111),
+ char(110),
+ char(116),
+ char(105),
+ char(103),
+ char(117),
+ char(111),
+ char(117),
+ char(115),
+ char(76),
+ char(101),
+ char(97),
+ char(102),
+ char(78),
+ char(111),
+ char(100),
+ char(101),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(81),
+ char(117),
+ char(97),
+ char(110),
+ char(116),
+ char(105),
+ char(122),
+ char(101),
+ char(100),
+ char(67),
+ char(111),
+ char(110),
+ char(116),
+ char(105),
+ char(103),
+ char(117),
+ char(111),
+ char(117),
+ char(115),
+ char(78),
+ char(111),
+ char(100),
+ char(101),
+ char(115),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(99),
+ char(111),
+ char(110),
+ char(116),
+ char(105),
+ char(103),
+ char(117),
+ char(111),
+ char(117),
+ char(115),
+ char(78),
+ char(111),
+ char(100),
+ char(101),
+ char(115),
+ char(80),
+ char(116),
+ char(114),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(113),
+ char(117),
+ char(97),
+ char(110),
+ char(116),
+ char(105),
+ char(122),
+ char(101),
+ char(100),
+ char(67),
+ char(111),
+ char(110),
+ char(116),
+ char(105),
+ char(103),
+ char(117),
+ char(111),
+ char(117),
+ char(115),
+ char(78),
+ char(111),
+ char(100),
+ char(101),
+ char(115),
+ char(80),
+ char(116),
+ char(114),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(115),
+ char(117),
+ char(98),
+ char(84),
+ char(114),
+ char(101),
+ char(101),
+ char(73),
+ char(110),
+ char(102),
+ char(111),
+ char(80),
+ char(116),
+ char(114),
+ char(0),
+ char(109),
+ char(95),
+ char(116),
+ char(114),
+ char(97),
+ char(118),
+ char(101),
+ char(114),
+ char(115),
+ char(97),
+ char(108),
+ char(77),
+ char(111),
+ char(100),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(83),
+ char(117),
+ char(98),
+ char(116),
+ char(114),
+ char(101),
+ char(101),
+ char(72),
+ char(101),
+ char(97),
+ char(100),
+ char(101),
+ char(114),
+ char(115),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(110),
+ char(97),
+ char(109),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(84),
+ char(121),
+ char(112),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(112),
+ char(97),
+ char(100),
+ char(100),
+ char(105),
+ char(110),
+ char(103),
+ char(91),
+ char(52),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(111),
+ char(108),
+ char(108),
+ char(105),
+ char(115),
+ char(105),
+ char(111),
+ char(110),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(109),
+ char(95),
+ char(108),
+ char(111),
+ char(99),
+ char(97),
+ char(108),
+ char(83),
+ char(99),
+ char(97),
+ char(108),
+ char(105),
+ char(110),
+ char(103),
+ char(0),
+ char(109),
+ char(95),
+ char(112),
+ char(108),
+ char(97),
+ char(110),
+ char(101),
+ char(78),
+ char(111),
+ char(114),
+ char(109),
+ char(97),
+ char(108),
+ char(0),
+ char(109),
+ char(95),
+ char(112),
+ char(108),
+ char(97),
+ char(110),
+ char(101),
+ char(67),
+ char(111),
+ char(110),
+ char(115),
+ char(116),
+ char(97),
+ char(110),
+ char(116),
+ char(0),
+ char(109),
+ char(95),
+ char(105),
+ char(109),
+ char(112),
+ char(108),
+ char(105),
+ char(99),
+ char(105),
+ char(116),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(68),
+ char(105),
+ char(109),
+ char(101),
+ char(110),
+ char(115),
+ char(105),
+ char(111),
+ char(110),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(111),
+ char(108),
+ char(108),
+ char(105),
+ char(115),
+ char(105),
+ char(111),
+ char(110),
+ char(77),
+ char(97),
+ char(114),
+ char(103),
+ char(105),
+ char(110),
+ char(0),
+ char(109),
+ char(95),
+ char(112),
+ char(97),
+ char(100),
+ char(100),
+ char(105),
+ char(110),
+ char(103),
+ char(0),
+ char(109),
+ char(95),
+ char(112),
+ char(111),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(114),
+ char(97),
+ char(100),
+ char(105),
+ char(117),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(111),
+ char(110),
+ char(118),
+ char(101),
+ char(120),
+ char(73),
+ char(110),
+ char(116),
+ char(101),
+ char(114),
+ char(110),
+ char(97),
+ char(108),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(108),
+ char(111),
+ char(99),
+ char(97),
+ char(108),
+ char(80),
+ char(111),
+ char(115),
+ char(105),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(65),
+ char(114),
+ char(114),
+ char(97),
+ char(121),
+ char(80),
+ char(116),
+ char(114),
+ char(0),
+ char(109),
+ char(95),
+ char(108),
+ char(111),
+ char(99),
+ char(97),
+ char(108),
+ char(80),
+ char(111),
+ char(115),
+ char(105),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(65),
+ char(114),
+ char(114),
+ char(97),
+ char(121),
+ char(83),
+ char(105),
+ char(122),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(118),
+ char(97),
+ char(108),
+ char(117),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(112),
+ char(97),
+ char(100),
+ char(91),
+ char(50),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(118),
+ char(97),
+ char(108),
+ char(117),
+ char(101),
+ char(115),
+ char(91),
+ char(51),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(112),
+ char(97),
+ char(100),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(118),
+ char(101),
+ char(114),
+ char(116),
+ char(105),
+ char(99),
+ char(101),
+ char(115),
+ char(51),
+ char(102),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(118),
+ char(101),
+ char(114),
+ char(116),
+ char(105),
+ char(99),
+ char(101),
+ char(115),
+ char(51),
+ char(100),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(105),
+ char(110),
+ char(100),
+ char(105),
+ char(99),
+ char(101),
+ char(115),
+ char(51),
+ char(50),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(51),
+ char(105),
+ char(110),
+ char(100),
+ char(105),
+ char(99),
+ char(101),
+ char(115),
+ char(49),
+ char(54),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(51),
+ char(105),
+ char(110),
+ char(100),
+ char(105),
+ char(99),
+ char(101),
+ char(115),
+ char(56),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(105),
+ char(110),
+ char(100),
+ char(105),
+ char(99),
+ char(101),
+ char(115),
+ char(49),
+ char(54),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(84),
+ char(114),
+ char(105),
+ char(97),
+ char(110),
+ char(103),
+ char(108),
+ char(101),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(86),
+ char(101),
+ char(114),
+ char(116),
+ char(105),
+ char(99),
+ char(101),
+ char(115),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(109),
+ char(101),
+ char(115),
+ char(104),
+ char(80),
+ char(97),
+ char(114),
+ char(116),
+ char(115),
+ char(80),
+ char(116),
+ char(114),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(99),
+ char(97),
+ char(108),
+ char(105),
+ char(110),
+ char(103),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(77),
+ char(101),
+ char(115),
+ char(104),
+ char(80),
+ char(97),
+ char(114),
+ char(116),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(109),
+ char(101),
+ char(115),
+ char(104),
+ char(73),
+ char(110),
+ char(116),
+ char(101),
+ char(114),
+ char(102),
+ char(97),
+ char(99),
+ char(101),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(113),
+ char(117),
+ char(97),
+ char(110),
+ char(116),
+ char(105),
+ char(122),
+ char(101),
+ char(100),
+ char(70),
+ char(108),
+ char(111),
+ char(97),
+ char(116),
+ char(66),
+ char(118),
+ char(104),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(113),
+ char(117),
+ char(97),
+ char(110),
+ char(116),
+ char(105),
+ char(122),
+ char(101),
+ char(100),
+ char(68),
+ char(111),
+ char(117),
+ char(98),
+ char(108),
+ char(101),
+ char(66),
+ char(118),
+ char(104),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(116),
+ char(114),
+ char(105),
+ char(97),
+ char(110),
+ char(103),
+ char(108),
+ char(101),
+ char(73),
+ char(110),
+ char(102),
+ char(111),
+ char(77),
+ char(97),
+ char(112),
+ char(0),
+ char(109),
+ char(95),
+ char(112),
+ char(97),
+ char(100),
+ char(51),
+ char(91),
+ char(52),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(116),
+ char(114),
+ char(105),
+ char(109),
+ char(101),
+ char(115),
+ char(104),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(109),
+ char(95),
+ char(116),
+ char(114),
+ char(97),
+ char(110),
+ char(115),
+ char(102),
+ char(111),
+ char(114),
+ char(109),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(99),
+ char(104),
+ char(105),
+ char(108),
+ char(100),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(104),
+ char(105),
+ char(108),
+ char(100),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(84),
+ char(121),
+ char(112),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(104),
+ char(105),
+ char(108),
+ char(100),
+ char(77),
+ char(97),
+ char(114),
+ char(103),
+ char(105),
+ char(110),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(99),
+ char(104),
+ char(105),
+ char(108),
+ char(100),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(80),
+ char(116),
+ char(114),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(67),
+ char(104),
+ char(105),
+ char(108),
+ char(100),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(117),
+ char(112),
+ char(65),
+ char(120),
+ char(105),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(102),
+ char(108),
+ char(97),
+ char(103),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(101),
+ char(100),
+ char(103),
+ char(101),
+ char(86),
+ char(48),
+ char(86),
+ char(49),
+ char(65),
+ char(110),
+ char(103),
+ char(108),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(101),
+ char(100),
+ char(103),
+ char(101),
+ char(86),
+ char(49),
+ char(86),
+ char(50),
+ char(65),
+ char(110),
+ char(103),
+ char(108),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(101),
+ char(100),
+ char(103),
+ char(101),
+ char(86),
+ char(50),
+ char(86),
+ char(48),
+ char(65),
+ char(110),
+ char(103),
+ char(108),
+ char(101),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(104),
+ char(97),
+ char(115),
+ char(104),
+ char(84),
+ char(97),
+ char(98),
+ char(108),
+ char(101),
+ char(80),
+ char(116),
+ char(114),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(110),
+ char(101),
+ char(120),
+ char(116),
+ char(80),
+ char(116),
+ char(114),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(118),
+ char(97),
+ char(108),
+ char(117),
+ char(101),
+ char(65),
+ char(114),
+ char(114),
+ char(97),
+ char(121),
+ char(80),
+ char(116),
+ char(114),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(107),
+ char(101),
+ char(121),
+ char(65),
+ char(114),
+ char(114),
+ char(97),
+ char(121),
+ char(80),
+ char(116),
+ char(114),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(111),
+ char(110),
+ char(118),
+ char(101),
+ char(120),
+ char(69),
+ char(112),
+ char(115),
+ char(105),
+ char(108),
+ char(111),
+ char(110),
+ char(0),
+ char(109),
+ char(95),
+ char(112),
+ char(108),
+ char(97),
+ char(110),
+ char(97),
+ char(114),
+ char(69),
+ char(112),
+ char(115),
+ char(105),
+ char(108),
+ char(111),
+ char(110),
+ char(0),
+ char(109),
+ char(95),
+ char(101),
+ char(113),
+ char(117),
+ char(97),
+ char(108),
+ char(86),
+ char(101),
+ char(114),
+ char(116),
+ char(101),
+ char(120),
+ char(84),
+ char(104),
+ char(114),
+ char(101),
+ char(115),
+ char(104),
+ char(111),
+ char(108),
+ char(100),
+ char(0),
+ char(109),
+ char(95),
+ char(101),
+ char(100),
+ char(103),
+ char(101),
+ char(68),
+ char(105),
+ char(115),
+ char(116),
+ char(97),
+ char(110),
+ char(99),
+ char(101),
+ char(84),
+ char(104),
+ char(114),
+ char(101),
+ char(115),
+ char(104),
+ char(111),
+ char(108),
+ char(100),
+ char(0),
+ char(109),
+ char(95),
+ char(122),
+ char(101),
+ char(114),
+ char(111),
+ char(65),
+ char(114),
+ char(101),
+ char(97),
+ char(84),
+ char(104),
+ char(114),
+ char(101),
+ char(115),
+ char(104),
+ char(111),
+ char(108),
+ char(100),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(101),
+ char(120),
+ char(116),
+ char(83),
+ char(105),
+ char(122),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(104),
+ char(97),
+ char(115),
+ char(104),
+ char(84),
+ char(97),
+ char(98),
+ char(108),
+ char(101),
+ char(83),
+ char(105),
+ char(122),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(86),
+ char(97),
+ char(108),
+ char(117),
+ char(101),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(75),
+ char(101),
+ char(121),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(103),
+ char(105),
+ char(109),
+ char(112),
+ char(97),
+ char(99),
+ char(116),
+ char(83),
+ char(117),
+ char(98),
+ char(84),
+ char(121),
+ char(112),
+ char(101),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(117),
+ char(110),
+ char(115),
+ char(99),
+ char(97),
+ char(108),
+ char(101),
+ char(100),
+ char(80),
+ char(111),
+ char(105),
+ char(110),
+ char(116),
+ char(115),
+ char(70),
+ char(108),
+ char(111),
+ char(97),
+ char(116),
+ char(80),
+ char(116),
+ char(114),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(117),
+ char(110),
+ char(115),
+ char(99),
+ char(97),
+ char(108),
+ char(101),
+ char(100),
+ char(80),
+ char(111),
+ char(105),
+ char(110),
+ char(116),
+ char(115),
+ char(68),
+ char(111),
+ char(117),
+ char(98),
+ char(108),
+ char(101),
+ char(80),
+ char(116),
+ char(114),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(85),
+ char(110),
+ char(115),
+ char(99),
+ char(97),
+ char(108),
+ char(101),
+ char(100),
+ char(80),
+ char(111),
+ char(105),
+ char(110),
+ char(116),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(112),
+ char(97),
+ char(100),
+ char(100),
+ char(105),
+ char(110),
+ char(103),
+ char(51),
+ char(91),
+ char(52),
+ char(93),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(98),
+ char(114),
+ char(111),
+ char(97),
+ char(100),
+ char(112),
+ char(104),
+ char(97),
+ char(115),
+ char(101),
+ char(72),
+ char(97),
+ char(110),
+ char(100),
+ char(108),
+ char(101),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(99),
+ char(111),
+ char(108),
+ char(108),
+ char(105),
+ char(115),
+ char(105),
+ char(111),
+ char(110),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(114),
+ char(111),
+ char(111),
+ char(116),
+ char(67),
+ char(111),
+ char(108),
+ char(108),
+ char(105),
+ char(115),
+ char(105),
+ char(111),
+ char(110),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(119),
+ char(111),
+ char(114),
+ char(108),
+ char(100),
+ char(84),
+ char(114),
+ char(97),
+ char(110),
+ char(115),
+ char(102),
+ char(111),
+ char(114),
+ char(109),
+ char(0),
+ char(109),
+ char(95),
+ char(105),
+ char(110),
+ char(116),
+ char(101),
+ char(114),
+ char(112),
+ char(111),
+ char(108),
+ char(97),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(87),
+ char(111),
+ char(114),
+ char(108),
+ char(100),
+ char(84),
+ char(114),
+ char(97),
+ char(110),
+ char(115),
+ char(102),
+ char(111),
+ char(114),
+ char(109),
+ char(0),
+ char(109),
+ char(95),
+ char(105),
+ char(110),
+ char(116),
+ char(101),
+ char(114),
+ char(112),
+ char(111),
+ char(108),
+ char(97),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(76),
+ char(105),
+ char(110),
+ char(101),
+ char(97),
+ char(114),
+ char(86),
+ char(101),
+ char(108),
+ char(111),
+ char(99),
+ char(105),
+ char(116),
+ char(121),
+ char(0),
+ char(109),
+ char(95),
+ char(105),
+ char(110),
+ char(116),
+ char(101),
+ char(114),
+ char(112),
+ char(111),
+ char(108),
+ char(97),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(65),
+ char(110),
+ char(103),
+ char(117),
+ char(108),
+ char(97),
+ char(114),
+ char(86),
+ char(101),
+ char(108),
+ char(111),
+ char(99),
+ char(105),
+ char(116),
+ char(121),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(110),
+ char(105),
+ char(115),
+ char(111),
+ char(116),
+ char(114),
+ char(111),
+ char(112),
+ char(105),
+ char(99),
+ char(70),
+ char(114),
+ char(105),
+ char(99),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(111),
+ char(110),
+ char(116),
+ char(97),
+ char(99),
+ char(116),
+ char(80),
+ char(114),
+ char(111),
+ char(99),
+ char(101),
+ char(115),
+ char(115),
+ char(105),
+ char(110),
+ char(103),
+ char(84),
+ char(104),
+ char(114),
+ char(101),
+ char(115),
+ char(104),
+ char(111),
+ char(108),
+ char(100),
+ char(0),
+ char(109),
+ char(95),
+ char(100),
+ char(101),
+ char(97),
+ char(99),
+ char(116),
+ char(105),
+ char(118),
+ char(97),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(84),
+ char(105),
+ char(109),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(102),
+ char(114),
+ char(105),
+ char(99),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(0),
+ char(109),
+ char(95),
+ char(114),
+ char(111),
+ char(108),
+ char(108),
+ char(105),
+ char(110),
+ char(103),
+ char(70),
+ char(114),
+ char(105),
+ char(99),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(0),
+ char(109),
+ char(95),
+ char(114),
+ char(101),
+ char(115),
+ char(116),
+ char(105),
+ char(116),
+ char(117),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(0),
+ char(109),
+ char(95),
+ char(104),
+ char(105),
+ char(116),
+ char(70),
+ char(114),
+ char(97),
+ char(99),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(99),
+ char(100),
+ char(83),
+ char(119),
+ char(101),
+ char(112),
+ char(116),
+ char(83),
+ char(112),
+ char(104),
+ char(101),
+ char(114),
+ char(101),
+ char(82),
+ char(97),
+ char(100),
+ char(105),
+ char(117),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(99),
+ char(100),
+ char(77),
+ char(111),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(84),
+ char(104),
+ char(114),
+ char(101),
+ char(115),
+ char(104),
+ char(111),
+ char(108),
+ char(100),
+ char(0),
+ char(109),
+ char(95),
+ char(104),
+ char(97),
+ char(115),
+ char(65),
+ char(110),
+ char(105),
+ char(115),
+ char(111),
+ char(116),
+ char(114),
+ char(111),
+ char(112),
+ char(105),
+ char(99),
+ char(70),
+ char(114),
+ char(105),
+ char(99),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(111),
+ char(108),
+ char(108),
+ char(105),
+ char(115),
+ char(105),
+ char(111),
+ char(110),
+ char(70),
+ char(108),
+ char(97),
+ char(103),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(105),
+ char(115),
+ char(108),
+ char(97),
+ char(110),
+ char(100),
+ char(84),
+ char(97),
+ char(103),
+ char(49),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(111),
+ char(109),
+ char(112),
+ char(97),
+ char(110),
+ char(105),
+ char(111),
+ char(110),
+ char(73),
+ char(100),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(99),
+ char(116),
+ char(105),
+ char(118),
+ char(97),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(83),
+ char(116),
+ char(97),
+ char(116),
+ char(101),
+ char(49),
+ char(0),
+ char(109),
+ char(95),
+ char(105),
+ char(110),
+ char(116),
+ char(101),
+ char(114),
+ char(110),
+ char(97),
+ char(108),
+ char(84),
+ char(121),
+ char(112),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(104),
+ char(101),
+ char(99),
+ char(107),
+ char(67),
+ char(111),
+ char(108),
+ char(108),
+ char(105),
+ char(100),
+ char(101),
+ char(87),
+ char(105),
+ char(116),
+ char(104),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(111),
+ char(108),
+ char(118),
+ char(101),
+ char(114),
+ char(73),
+ char(110),
+ char(102),
+ char(111),
+ char(0),
+ char(109),
+ char(95),
+ char(103),
+ char(114),
+ char(97),
+ char(118),
+ char(105),
+ char(116),
+ char(121),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(111),
+ char(108),
+ char(108),
+ char(105),
+ char(115),
+ char(105),
+ char(111),
+ char(110),
+ char(79),
+ char(98),
+ char(106),
+ char(101),
+ char(99),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(109),
+ char(95),
+ char(105),
+ char(110),
+ char(118),
+ char(73),
+ char(110),
+ char(101),
+ char(114),
+ char(116),
+ char(105),
+ char(97),
+ char(84),
+ char(101),
+ char(110),
+ char(115),
+ char(111),
+ char(114),
+ char(87),
+ char(111),
+ char(114),
+ char(108),
+ char(100),
+ char(0),
+ char(109),
+ char(95),
+ char(108),
+ char(105),
+ char(110),
+ char(101),
+ char(97),
+ char(114),
+ char(86),
+ char(101),
+ char(108),
+ char(111),
+ char(99),
+ char(105),
+ char(116),
+ char(121),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(110),
+ char(103),
+ char(117),
+ char(108),
+ char(97),
+ char(114),
+ char(86),
+ char(101),
+ char(108),
+ char(111),
+ char(99),
+ char(105),
+ char(116),
+ char(121),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(110),
+ char(103),
+ char(117),
+ char(108),
+ char(97),
+ char(114),
+ char(70),
+ char(97),
+ char(99),
+ char(116),
+ char(111),
+ char(114),
+ char(0),
+ char(109),
+ char(95),
+ char(108),
+ char(105),
+ char(110),
+ char(101),
+ char(97),
+ char(114),
+ char(70),
+ char(97),
+ char(99),
+ char(116),
+ char(111),
+ char(114),
+ char(0),
+ char(109),
+ char(95),
+ char(103),
+ char(114),
+ char(97),
+ char(118),
+ char(105),
+ char(116),
+ char(121),
+ char(95),
+ char(97),
+ char(99),
+ char(99),
+ char(101),
+ char(108),
+ char(101),
+ char(114),
+ char(97),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(0),
+ char(109),
+ char(95),
+ char(105),
+ char(110),
+ char(118),
+ char(73),
+ char(110),
+ char(101),
+ char(114),
+ char(116),
+ char(105),
+ char(97),
+ char(76),
+ char(111),
+ char(99),
+ char(97),
+ char(108),
+ char(0),
+ char(109),
+ char(95),
+ char(116),
+ char(111),
+ char(116),
+ char(97),
+ char(108),
+ char(70),
+ char(111),
+ char(114),
+ char(99),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(116),
+ char(111),
+ char(116),
+ char(97),
+ char(108),
+ char(84),
+ char(111),
+ char(114),
+ char(113),
+ char(117),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(105),
+ char(110),
+ char(118),
+ char(101),
+ char(114),
+ char(115),
+ char(101),
+ char(77),
+ char(97),
+ char(115),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(108),
+ char(105),
+ char(110),
+ char(101),
+ char(97),
+ char(114),
+ char(68),
+ char(97),
+ char(109),
+ char(112),
+ char(105),
+ char(110),
+ char(103),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(110),
+ char(103),
+ char(117),
+ char(108),
+ char(97),
+ char(114),
+ char(68),
+ char(97),
+ char(109),
+ char(112),
+ char(105),
+ char(110),
+ char(103),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(100),
+ char(100),
+ char(105),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(97),
+ char(108),
+ char(68),
+ char(97),
+ char(109),
+ char(112),
+ char(105),
+ char(110),
+ char(103),
+ char(70),
+ char(97),
+ char(99),
+ char(116),
+ char(111),
+ char(114),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(100),
+ char(100),
+ char(105),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(97),
+ char(108),
+ char(76),
+ char(105),
+ char(110),
+ char(101),
+ char(97),
+ char(114),
+ char(68),
+ char(97),
+ char(109),
+ char(112),
+ char(105),
+ char(110),
+ char(103),
+ char(84),
+ char(104),
+ char(114),
+ char(101),
+ char(115),
+ char(104),
+ char(111),
+ char(108),
+ char(100),
+ char(83),
+ char(113),
+ char(114),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(100),
+ char(100),
+ char(105),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(97),
+ char(108),
+ char(65),
+ char(110),
+ char(103),
+ char(117),
+ char(108),
+ char(97),
+ char(114),
+ char(68),
+ char(97),
+ char(109),
+ char(112),
+ char(105),
+ char(110),
+ char(103),
+ char(84),
+ char(104),
+ char(114),
+ char(101),
+ char(115),
+ char(104),
+ char(111),
+ char(108),
+ char(100),
+ char(83),
+ char(113),
+ char(114),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(100),
+ char(100),
+ char(105),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(97),
+ char(108),
+ char(65),
+ char(110),
+ char(103),
+ char(117),
+ char(108),
+ char(97),
+ char(114),
+ char(68),
+ char(97),
+ char(109),
+ char(112),
+ char(105),
+ char(110),
+ char(103),
+ char(70),
+ char(97),
+ char(99),
+ char(116),
+ char(111),
+ char(114),
+ char(0),
+ char(109),
+ char(95),
+ char(108),
+ char(105),
+ char(110),
+ char(101),
+ char(97),
+ char(114),
+ char(83),
+ char(108),
+ char(101),
+ char(101),
+ char(112),
+ char(105),
+ char(110),
+ char(103),
+ char(84),
+ char(104),
+ char(114),
+ char(101),
+ char(115),
+ char(104),
+ char(111),
+ char(108),
+ char(100),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(110),
+ char(103),
+ char(117),
+ char(108),
+ char(97),
+ char(114),
+ char(83),
+ char(108),
+ char(101),
+ char(101),
+ char(112),
+ char(105),
+ char(110),
+ char(103),
+ char(84),
+ char(104),
+ char(114),
+ char(101),
+ char(115),
+ char(104),
+ char(111),
+ char(108),
+ char(100),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(100),
+ char(100),
+ char(105),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(97),
+ char(108),
+ char(68),
+ char(97),
+ char(109),
+ char(112),
+ char(105),
+ char(110),
+ char(103),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(67),
+ char(111),
+ char(110),
+ char(115),
+ char(116),
+ char(114),
+ char(97),
+ char(105),
+ char(110),
+ char(116),
+ char(82),
+ char(111),
+ char(119),
+ char(115),
+ char(0),
+ char(110),
+ char(117),
+ char(98),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(114),
+ char(98),
+ char(65),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(114),
+ char(98),
+ char(66),
+ char(0),
+ char(109),
+ char(95),
+ char(111),
+ char(98),
+ char(106),
+ char(101),
+ char(99),
+ char(116),
+ char(84),
+ char(121),
+ char(112),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(117),
+ char(115),
+ char(101),
+ char(114),
+ char(67),
+ char(111),
+ char(110),
+ char(115),
+ char(116),
+ char(114),
+ char(97),
+ char(105),
+ char(110),
+ char(116),
+ char(84),
+ char(121),
+ char(112),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(117),
+ char(115),
+ char(101),
+ char(114),
+ char(67),
+ char(111),
+ char(110),
+ char(115),
+ char(116),
+ char(114),
+ char(97),
+ char(105),
+ char(110),
+ char(116),
+ char(73),
+ char(100),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(101),
+ char(101),
+ char(100),
+ char(115),
+ char(70),
+ char(101),
+ char(101),
+ char(100),
+ char(98),
+ char(97),
+ char(99),
+ char(107),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(112),
+ char(112),
+ char(108),
+ char(105),
+ char(101),
+ char(100),
+ char(73),
+ char(109),
+ char(112),
+ char(117),
+ char(108),
+ char(115),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(100),
+ char(98),
+ char(103),
+ char(68),
+ char(114),
+ char(97),
+ char(119),
+ char(83),
+ char(105),
+ char(122),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(100),
+ char(105),
+ char(115),
+ char(97),
+ char(98),
+ char(108),
+ char(101),
+ char(67),
+ char(111),
+ char(108),
+ char(108),
+ char(105),
+ char(115),
+ char(105),
+ char(111),
+ char(110),
+ char(115),
+ char(66),
+ char(101),
+ char(116),
+ char(119),
+ char(101),
+ char(101),
+ char(110),
+ char(76),
+ char(105),
+ char(110),
+ char(107),
+ char(101),
+ char(100),
+ char(66),
+ char(111),
+ char(100),
+ char(105),
+ char(101),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(111),
+ char(118),
+ char(101),
+ char(114),
+ char(114),
+ char(105),
+ char(100),
+ char(101),
+ char(78),
+ char(117),
+ char(109),
+ char(83),
+ char(111),
+ char(108),
+ char(118),
+ char(101),
+ char(114),
+ char(73),
+ char(116),
+ char(101),
+ char(114),
+ char(97),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(98),
+ char(114),
+ char(101),
+ char(97),
+ char(107),
+ char(105),
+ char(110),
+ char(103),
+ char(73),
+ char(109),
+ char(112),
+ char(117),
+ char(108),
+ char(115),
+ char(101),
+ char(84),
+ char(104),
+ char(114),
+ char(101),
+ char(115),
+ char(104),
+ char(111),
+ char(108),
+ char(100),
+ char(0),
+ char(109),
+ char(95),
+ char(105),
+ char(115),
+ char(69),
+ char(110),
+ char(97),
+ char(98),
+ char(108),
+ char(101),
+ char(100),
+ char(0),
+ char(109),
+ char(95),
+ char(116),
+ char(121),
+ char(112),
+ char(101),
+ char(67),
+ char(111),
+ char(110),
+ char(115),
+ char(116),
+ char(114),
+ char(97),
+ char(105),
+ char(110),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(109),
+ char(95),
+ char(112),
+ char(105),
+ char(118),
+ char(111),
+ char(116),
+ char(73),
+ char(110),
+ char(65),
+ char(0),
+ char(109),
+ char(95),
+ char(112),
+ char(105),
+ char(118),
+ char(111),
+ char(116),
+ char(73),
+ char(110),
+ char(66),
+ char(0),
+ char(109),
+ char(95),
+ char(114),
+ char(98),
+ char(65),
+ char(70),
+ char(114),
+ char(97),
+ char(109),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(114),
+ char(98),
+ char(66),
+ char(70),
+ char(114),
+ char(97),
+ char(109),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(117),
+ char(115),
+ char(101),
+ char(82),
+ char(101),
+ char(102),
+ char(101),
+ char(114),
+ char(101),
+ char(110),
+ char(99),
+ char(101),
+ char(70),
+ char(114),
+ char(97),
+ char(109),
+ char(101),
+ char(65),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(110),
+ char(103),
+ char(117),
+ char(108),
+ char(97),
+ char(114),
+ char(79),
+ char(110),
+ char(108),
+ char(121),
+ char(0),
+ char(109),
+ char(95),
+ char(101),
+ char(110),
+ char(97),
+ char(98),
+ char(108),
+ char(101),
+ char(65),
+ char(110),
+ char(103),
+ char(117),
+ char(108),
+ char(97),
+ char(114),
+ char(77),
+ char(111),
+ char(116),
+ char(111),
+ char(114),
+ char(0),
+ char(109),
+ char(95),
+ char(109),
+ char(111),
+ char(116),
+ char(111),
+ char(114),
+ char(84),
+ char(97),
+ char(114),
+ char(103),
+ char(101),
+ char(116),
+ char(86),
+ char(101),
+ char(108),
+ char(111),
+ char(99),
+ char(105),
+ char(116),
+ char(121),
+ char(0),
+ char(109),
+ char(95),
+ char(109),
+ char(97),
+ char(120),
+ char(77),
+ char(111),
+ char(116),
+ char(111),
+ char(114),
+ char(73),
+ char(109),
+ char(112),
+ char(117),
+ char(108),
+ char(115),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(108),
+ char(111),
+ char(119),
+ char(101),
+ char(114),
+ char(76),
+ char(105),
+ char(109),
+ char(105),
+ char(116),
+ char(0),
+ char(109),
+ char(95),
+ char(117),
+ char(112),
+ char(112),
+ char(101),
+ char(114),
+ char(76),
+ char(105),
+ char(109),
+ char(105),
+ char(116),
+ char(0),
+ char(109),
+ char(95),
+ char(108),
+ char(105),
+ char(109),
+ char(105),
+ char(116),
+ char(83),
+ char(111),
+ char(102),
+ char(116),
+ char(110),
+ char(101),
+ char(115),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(98),
+ char(105),
+ char(97),
+ char(115),
+ char(70),
+ char(97),
+ char(99),
+ char(116),
+ char(111),
+ char(114),
+ char(0),
+ char(109),
+ char(95),
+ char(114),
+ char(101),
+ char(108),
+ char(97),
+ char(120),
+ char(97),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(70),
+ char(97),
+ char(99),
+ char(116),
+ char(111),
+ char(114),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(119),
+ char(105),
+ char(110),
+ char(103),
+ char(83),
+ char(112),
+ char(97),
+ char(110),
+ char(49),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(119),
+ char(105),
+ char(110),
+ char(103),
+ char(83),
+ char(112),
+ char(97),
+ char(110),
+ char(50),
+ char(0),
+ char(109),
+ char(95),
+ char(116),
+ char(119),
+ char(105),
+ char(115),
+ char(116),
+ char(83),
+ char(112),
+ char(97),
+ char(110),
+ char(0),
+ char(109),
+ char(95),
+ char(100),
+ char(97),
+ char(109),
+ char(112),
+ char(105),
+ char(110),
+ char(103),
+ char(0),
+ char(109),
+ char(95),
+ char(108),
+ char(105),
+ char(110),
+ char(101),
+ char(97),
+ char(114),
+ char(85),
+ char(112),
+ char(112),
+ char(101),
+ char(114),
+ char(76),
+ char(105),
+ char(109),
+ char(105),
+ char(116),
+ char(0),
+ char(109),
+ char(95),
+ char(108),
+ char(105),
+ char(110),
+ char(101),
+ char(97),
+ char(114),
+ char(76),
+ char(111),
+ char(119),
+ char(101),
+ char(114),
+ char(76),
+ char(105),
+ char(109),
+ char(105),
+ char(116),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(110),
+ char(103),
+ char(117),
+ char(108),
+ char(97),
+ char(114),
+ char(85),
+ char(112),
+ char(112),
+ char(101),
+ char(114),
+ char(76),
+ char(105),
+ char(109),
+ char(105),
+ char(116),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(110),
+ char(103),
+ char(117),
+ char(108),
+ char(97),
+ char(114),
+ char(76),
+ char(111),
+ char(119),
+ char(101),
+ char(114),
+ char(76),
+ char(105),
+ char(109),
+ char(105),
+ char(116),
+ char(0),
+ char(109),
+ char(95),
+ char(117),
+ char(115),
+ char(101),
+ char(76),
+ char(105),
+ char(110),
+ char(101),
+ char(97),
+ char(114),
+ char(82),
+ char(101),
+ char(102),
+ char(101),
+ char(114),
+ char(101),
+ char(110),
+ char(99),
+ char(101),
+ char(70),
+ char(114),
+ char(97),
+ char(109),
+ char(101),
+ char(65),
+ char(0),
+ char(109),
+ char(95),
+ char(117),
+ char(115),
+ char(101),
+ char(79),
+ char(102),
+ char(102),
+ char(115),
+ char(101),
+ char(116),
+ char(70),
+ char(111),
+ char(114),
+ char(67),
+ char(111),
+ char(110),
+ char(115),
+ char(116),
+ char(114),
+ char(97),
+ char(105),
+ char(110),
+ char(116),
+ char(70),
+ char(114),
+ char(97),
+ char(109),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(54),
+ char(100),
+ char(111),
+ char(102),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(112),
+ char(114),
+ char(105),
+ char(110),
+ char(103),
+ char(69),
+ char(110),
+ char(97),
+ char(98),
+ char(108),
+ char(101),
+ char(100),
+ char(91),
+ char(54),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(101),
+ char(113),
+ char(117),
+ char(105),
+ char(108),
+ char(105),
+ char(98),
+ char(114),
+ char(105),
+ char(117),
+ char(109),
+ char(80),
+ char(111),
+ char(105),
+ char(110),
+ char(116),
+ char(91),
+ char(54),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(112),
+ char(114),
+ char(105),
+ char(110),
+ char(103),
+ char(83),
+ char(116),
+ char(105),
+ char(102),
+ char(102),
+ char(110),
+ char(101),
+ char(115),
+ char(115),
+ char(91),
+ char(54),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(112),
+ char(114),
+ char(105),
+ char(110),
+ char(103),
+ char(68),
+ char(97),
+ char(109),
+ char(112),
+ char(105),
+ char(110),
+ char(103),
+ char(91),
+ char(54),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(116),
+ char(97),
+ char(117),
+ char(0),
+ char(109),
+ char(95),
+ char(116),
+ char(105),
+ char(109),
+ char(101),
+ char(83),
+ char(116),
+ char(101),
+ char(112),
+ char(0),
+ char(109),
+ char(95),
+ char(109),
+ char(97),
+ char(120),
+ char(69),
+ char(114),
+ char(114),
+ char(111),
+ char(114),
+ char(82),
+ char(101),
+ char(100),
+ char(117),
+ char(99),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(111),
+ char(114),
+ char(0),
+ char(109),
+ char(95),
+ char(101),
+ char(114),
+ char(112),
+ char(0),
+ char(109),
+ char(95),
+ char(101),
+ char(114),
+ char(112),
+ char(50),
+ char(0),
+ char(109),
+ char(95),
+ char(103),
+ char(108),
+ char(111),
+ char(98),
+ char(97),
+ char(108),
+ char(67),
+ char(102),
+ char(109),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(112),
+ char(108),
+ char(105),
+ char(116),
+ char(73),
+ char(109),
+ char(112),
+ char(117),
+ char(108),
+ char(115),
+ char(101),
+ char(80),
+ char(101),
+ char(110),
+ char(101),
+ char(116),
+ char(114),
+ char(97),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(84),
+ char(104),
+ char(114),
+ char(101),
+ char(115),
+ char(104),
+ char(111),
+ char(108),
+ char(100),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(112),
+ char(108),
+ char(105),
+ char(116),
+ char(73),
+ char(109),
+ char(112),
+ char(117),
+ char(108),
+ char(115),
+ char(101),
+ char(84),
+ char(117),
+ char(114),
+ char(110),
+ char(69),
+ char(114),
+ char(112),
+ char(0),
+ char(109),
+ char(95),
+ char(108),
+ char(105),
+ char(110),
+ char(101),
+ char(97),
+ char(114),
+ char(83),
+ char(108),
+ char(111),
+ char(112),
+ char(0),
+ char(109),
+ char(95),
+ char(119),
+ char(97),
+ char(114),
+ char(109),
+ char(115),
+ char(116),
+ char(97),
+ char(114),
+ char(116),
+ char(105),
+ char(110),
+ char(103),
+ char(70),
+ char(97),
+ char(99),
+ char(116),
+ char(111),
+ char(114),
+ char(0),
+ char(109),
+ char(95),
+ char(109),
+ char(97),
+ char(120),
+ char(71),
+ char(121),
+ char(114),
+ char(111),
+ char(115),
+ char(99),
+ char(111),
+ char(112),
+ char(105),
+ char(99),
+ char(70),
+ char(111),
+ char(114),
+ char(99),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(105),
+ char(110),
+ char(103),
+ char(108),
+ char(101),
+ char(65),
+ char(120),
+ char(105),
+ char(115),
+ char(82),
+ char(111),
+ char(108),
+ char(108),
+ char(105),
+ char(110),
+ char(103),
+ char(70),
+ char(114),
+ char(105),
+ char(99),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(84),
+ char(104),
+ char(114),
+ char(101),
+ char(115),
+ char(104),
+ char(111),
+ char(108),
+ char(100),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(73),
+ char(116),
+ char(101),
+ char(114),
+ char(97),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(111),
+ char(108),
+ char(118),
+ char(101),
+ char(114),
+ char(77),
+ char(111),
+ char(100),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(114),
+ char(101),
+ char(115),
+ char(116),
+ char(105),
+ char(110),
+ char(103),
+ char(67),
+ char(111),
+ char(110),
+ char(116),
+ char(97),
+ char(99),
+ char(116),
+ char(82),
+ char(101),
+ char(115),
+ char(116),
+ char(105),
+ char(116),
+ char(117),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(84),
+ char(104),
+ char(114),
+ char(101),
+ char(115),
+ char(104),
+ char(111),
+ char(108),
+ char(100),
+ char(0),
+ char(109),
+ char(95),
+ char(109),
+ char(105),
+ char(110),
+ char(105),
+ char(109),
+ char(117),
+ char(109),
+ char(83),
+ char(111),
+ char(108),
+ char(118),
+ char(101),
+ char(114),
+ char(66),
+ char(97),
+ char(116),
+ char(99),
+ char(104),
+ char(83),
+ char(105),
+ char(122),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(112),
+ char(108),
+ char(105),
+ char(116),
+ char(73),
+ char(109),
+ char(112),
+ char(117),
+ char(108),
+ char(115),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(108),
+ char(105),
+ char(110),
+ char(101),
+ char(97),
+ char(114),
+ char(83),
+ char(116),
+ char(105),
+ char(102),
+ char(102),
+ char(110),
+ char(101),
+ char(115),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(110),
+ char(103),
+ char(117),
+ char(108),
+ char(97),
+ char(114),
+ char(83),
+ char(116),
+ char(105),
+ char(102),
+ char(102),
+ char(110),
+ char(101),
+ char(115),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(118),
+ char(111),
+ char(108),
+ char(117),
+ char(109),
+ char(101),
+ char(83),
+ char(116),
+ char(105),
+ char(102),
+ char(102),
+ char(110),
+ char(101),
+ char(115),
+ char(115),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(109),
+ char(97),
+ char(116),
+ char(101),
+ char(114),
+ char(105),
+ char(97),
+ char(108),
+ char(0),
+ char(109),
+ char(95),
+ char(112),
+ char(111),
+ char(115),
+ char(105),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(0),
+ char(109),
+ char(95),
+ char(112),
+ char(114),
+ char(101),
+ char(118),
+ char(105),
+ char(111),
+ char(117),
+ char(115),
+ char(80),
+ char(111),
+ char(115),
+ char(105),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(0),
+ char(109),
+ char(95),
+ char(118),
+ char(101),
+ char(108),
+ char(111),
+ char(99),
+ char(105),
+ char(116),
+ char(121),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(99),
+ char(99),
+ char(117),
+ char(109),
+ char(117),
+ char(108),
+ char(97),
+ char(116),
+ char(101),
+ char(100),
+ char(70),
+ char(111),
+ char(114),
+ char(99),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(111),
+ char(114),
+ char(109),
+ char(97),
+ char(108),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(114),
+ char(101),
+ char(97),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(116),
+ char(116),
+ char(97),
+ char(99),
+ char(104),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(111),
+ char(100),
+ char(101),
+ char(73),
+ char(110),
+ char(100),
+ char(105),
+ char(99),
+ char(101),
+ char(115),
+ char(91),
+ char(50),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(114),
+ char(101),
+ char(115),
+ char(116),
+ char(76),
+ char(101),
+ char(110),
+ char(103),
+ char(116),
+ char(104),
+ char(0),
+ char(109),
+ char(95),
+ char(98),
+ char(98),
+ char(101),
+ char(110),
+ char(100),
+ char(105),
+ char(110),
+ char(103),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(111),
+ char(100),
+ char(101),
+ char(73),
+ char(110),
+ char(100),
+ char(105),
+ char(99),
+ char(101),
+ char(115),
+ char(91),
+ char(51),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(114),
+ char(101),
+ char(115),
+ char(116),
+ char(65),
+ char(114),
+ char(101),
+ char(97),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(48),
+ char(91),
+ char(52),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(111),
+ char(100),
+ char(101),
+ char(73),
+ char(110),
+ char(100),
+ char(105),
+ char(99),
+ char(101),
+ char(115),
+ char(91),
+ char(52),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(114),
+ char(101),
+ char(115),
+ char(116),
+ char(86),
+ char(111),
+ char(108),
+ char(117),
+ char(109),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(49),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(50),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(48),
+ char(0),
+ char(109),
+ char(95),
+ char(108),
+ char(111),
+ char(99),
+ char(97),
+ char(108),
+ char(70),
+ char(114),
+ char(97),
+ char(109),
+ char(101),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(114),
+ char(105),
+ char(103),
+ char(105),
+ char(100),
+ char(66),
+ char(111),
+ char(100),
+ char(121),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(111),
+ char(100),
+ char(101),
+ char(73),
+ char(110),
+ char(100),
+ char(101),
+ char(120),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(101),
+ char(114),
+ char(111),
+ char(77),
+ char(111),
+ char(100),
+ char(101),
+ char(108),
+ char(0),
+ char(109),
+ char(95),
+ char(98),
+ char(97),
+ char(117),
+ char(109),
+ char(103),
+ char(97),
+ char(114),
+ char(116),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(100),
+ char(114),
+ char(97),
+ char(103),
+ char(0),
+ char(109),
+ char(95),
+ char(108),
+ char(105),
+ char(102),
+ char(116),
+ char(0),
+ char(109),
+ char(95),
+ char(112),
+ char(114),
+ char(101),
+ char(115),
+ char(115),
+ char(117),
+ char(114),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(118),
+ char(111),
+ char(108),
+ char(117),
+ char(109),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(100),
+ char(121),
+ char(110),
+ char(97),
+ char(109),
+ char(105),
+ char(99),
+ char(70),
+ char(114),
+ char(105),
+ char(99),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(0),
+ char(109),
+ char(95),
+ char(112),
+ char(111),
+ char(115),
+ char(101),
+ char(77),
+ char(97),
+ char(116),
+ char(99),
+ char(104),
+ char(0),
+ char(109),
+ char(95),
+ char(114),
+ char(105),
+ char(103),
+ char(105),
+ char(100),
+ char(67),
+ char(111),
+ char(110),
+ char(116),
+ char(97),
+ char(99),
+ char(116),
+ char(72),
+ char(97),
+ char(114),
+ char(100),
+ char(110),
+ char(101),
+ char(115),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(107),
+ char(105),
+ char(110),
+ char(101),
+ char(116),
+ char(105),
+ char(99),
+ char(67),
+ char(111),
+ char(110),
+ char(116),
+ char(97),
+ char(99),
+ char(116),
+ char(72),
+ char(97),
+ char(114),
+ char(100),
+ char(110),
+ char(101),
+ char(115),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(111),
+ char(102),
+ char(116),
+ char(67),
+ char(111),
+ char(110),
+ char(116),
+ char(97),
+ char(99),
+ char(116),
+ char(72),
+ char(97),
+ char(114),
+ char(100),
+ char(110),
+ char(101),
+ char(115),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(110),
+ char(99),
+ char(104),
+ char(111),
+ char(114),
+ char(72),
+ char(97),
+ char(114),
+ char(100),
+ char(110),
+ char(101),
+ char(115),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(111),
+ char(102),
+ char(116),
+ char(82),
+ char(105),
+ char(103),
+ char(105),
+ char(100),
+ char(67),
+ char(108),
+ char(117),
+ char(115),
+ char(116),
+ char(101),
+ char(114),
+ char(72),
+ char(97),
+ char(114),
+ char(100),
+ char(110),
+ char(101),
+ char(115),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(111),
+ char(102),
+ char(116),
+ char(75),
+ char(105),
+ char(110),
+ char(101),
+ char(116),
+ char(105),
+ char(99),
+ char(67),
+ char(108),
+ char(117),
+ char(115),
+ char(116),
+ char(101),
+ char(114),
+ char(72),
+ char(97),
+ char(114),
+ char(100),
+ char(110),
+ char(101),
+ char(115),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(111),
+ char(102),
+ char(116),
+ char(83),
+ char(111),
+ char(102),
+ char(116),
+ char(67),
+ char(108),
+ char(117),
+ char(115),
+ char(116),
+ char(101),
+ char(114),
+ char(72),
+ char(97),
+ char(114),
+ char(100),
+ char(110),
+ char(101),
+ char(115),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(111),
+ char(102),
+ char(116),
+ char(82),
+ char(105),
+ char(103),
+ char(105),
+ char(100),
+ char(67),
+ char(108),
+ char(117),
+ char(115),
+ char(116),
+ char(101),
+ char(114),
+ char(73),
+ char(109),
+ char(112),
+ char(117),
+ char(108),
+ char(115),
+ char(101),
+ char(83),
+ char(112),
+ char(108),
+ char(105),
+ char(116),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(111),
+ char(102),
+ char(116),
+ char(75),
+ char(105),
+ char(110),
+ char(101),
+ char(116),
+ char(105),
+ char(99),
+ char(67),
+ char(108),
+ char(117),
+ char(115),
+ char(116),
+ char(101),
+ char(114),
+ char(73),
+ char(109),
+ char(112),
+ char(117),
+ char(108),
+ char(115),
+ char(101),
+ char(83),
+ char(112),
+ char(108),
+ char(105),
+ char(116),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(111),
+ char(102),
+ char(116),
+ char(83),
+ char(111),
+ char(102),
+ char(116),
+ char(67),
+ char(108),
+ char(117),
+ char(115),
+ char(116),
+ char(101),
+ char(114),
+ char(73),
+ char(109),
+ char(112),
+ char(117),
+ char(108),
+ char(115),
+ char(101),
+ char(83),
+ char(112),
+ char(108),
+ char(105),
+ char(116),
+ char(0),
+ char(109),
+ char(95),
+ char(109),
+ char(97),
+ char(120),
+ char(86),
+ char(111),
+ char(108),
+ char(117),
+ char(109),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(116),
+ char(105),
+ char(109),
+ char(101),
+ char(83),
+ char(99),
+ char(97),
+ char(108),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(118),
+ char(101),
+ char(108),
+ char(111),
+ char(99),
+ char(105),
+ char(116),
+ char(121),
+ char(73),
+ char(116),
+ char(101),
+ char(114),
+ char(97),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(112),
+ char(111),
+ char(115),
+ char(105),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(73),
+ char(116),
+ char(101),
+ char(114),
+ char(97),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(100),
+ char(114),
+ char(105),
+ char(102),
+ char(116),
+ char(73),
+ char(116),
+ char(101),
+ char(114),
+ char(97),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(108),
+ char(117),
+ char(115),
+ char(116),
+ char(101),
+ char(114),
+ char(73),
+ char(116),
+ char(101),
+ char(114),
+ char(97),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(114),
+ char(111),
+ char(116),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(99),
+ char(97),
+ char(108),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(113),
+ char(113),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(111),
+ char(109),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(112),
+ char(111),
+ char(115),
+ char(105),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(115),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(119),
+ char(101),
+ char(105),
+ char(103),
+ char(104),
+ char(116),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(80),
+ char(111),
+ char(115),
+ char(105),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(87),
+ char(101),
+ char(105),
+ char(103),
+ char(116),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(98),
+ char(118),
+ char(111),
+ char(108),
+ char(117),
+ char(109),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(98),
+ char(102),
+ char(114),
+ char(97),
+ char(109),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(102),
+ char(114),
+ char(97),
+ char(109),
+ char(101),
+ char(120),
+ char(102),
+ char(111),
+ char(114),
+ char(109),
+ char(0),
+ char(109),
+ char(95),
+ char(108),
+ char(111),
+ char(99),
+ char(105),
+ char(105),
+ char(0),
+ char(109),
+ char(95),
+ char(105),
+ char(110),
+ char(118),
+ char(119),
+ char(105),
+ char(0),
+ char(109),
+ char(95),
+ char(118),
+ char(105),
+ char(109),
+ char(112),
+ char(117),
+ char(108),
+ char(115),
+ char(101),
+ char(115),
+ char(91),
+ char(50),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(100),
+ char(105),
+ char(109),
+ char(112),
+ char(117),
+ char(108),
+ char(115),
+ char(101),
+ char(115),
+ char(91),
+ char(50),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(108),
+ char(118),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(118),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(102),
+ char(114),
+ char(97),
+ char(109),
+ char(101),
+ char(114),
+ char(101),
+ char(102),
+ char(115),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(110),
+ char(111),
+ char(100),
+ char(101),
+ char(73),
+ char(110),
+ char(100),
+ char(105),
+ char(99),
+ char(101),
+ char(115),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(109),
+ char(97),
+ char(115),
+ char(115),
+ char(101),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(70),
+ char(114),
+ char(97),
+ char(109),
+ char(101),
+ char(82),
+ char(101),
+ char(102),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(78),
+ char(111),
+ char(100),
+ char(101),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(77),
+ char(97),
+ char(115),
+ char(115),
+ char(101),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(105),
+ char(100),
+ char(109),
+ char(97),
+ char(115),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(105),
+ char(109),
+ char(97),
+ char(115),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(118),
+ char(105),
+ char(109),
+ char(112),
+ char(117),
+ char(108),
+ char(115),
+ char(101),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(100),
+ char(105),
+ char(109),
+ char(112),
+ char(117),
+ char(108),
+ char(115),
+ char(101),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(100),
+ char(97),
+ char(109),
+ char(112),
+ char(105),
+ char(110),
+ char(103),
+ char(0),
+ char(109),
+ char(95),
+ char(108),
+ char(100),
+ char(97),
+ char(109),
+ char(112),
+ char(105),
+ char(110),
+ char(103),
+ char(0),
+ char(109),
+ char(95),
+ char(97),
+ char(100),
+ char(97),
+ char(109),
+ char(112),
+ char(105),
+ char(110),
+ char(103),
+ char(0),
+ char(109),
+ char(95),
+ char(109),
+ char(97),
+ char(116),
+ char(99),
+ char(104),
+ char(105),
+ char(110),
+ char(103),
+ char(0),
+ char(109),
+ char(95),
+ char(109),
+ char(97),
+ char(120),
+ char(83),
+ char(101),
+ char(108),
+ char(102),
+ char(67),
+ char(111),
+ char(108),
+ char(108),
+ char(105),
+ char(115),
+ char(105),
+ char(111),
+ char(110),
+ char(73),
+ char(109),
+ char(112),
+ char(117),
+ char(108),
+ char(115),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(101),
+ char(108),
+ char(102),
+ char(67),
+ char(111),
+ char(108),
+ char(108),
+ char(105),
+ char(115),
+ char(105),
+ char(111),
+ char(110),
+ char(73),
+ char(109),
+ char(112),
+ char(117),
+ char(108),
+ char(115),
+ char(101),
+ char(70),
+ char(97),
+ char(99),
+ char(116),
+ char(111),
+ char(114),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(111),
+ char(110),
+ char(116),
+ char(97),
+ char(105),
+ char(110),
+ char(115),
+ char(65),
+ char(110),
+ char(99),
+ char(104),
+ char(111),
+ char(114),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(111),
+ char(108),
+ char(108),
+ char(105),
+ char(100),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(108),
+ char(117),
+ char(115),
+ char(116),
+ char(101),
+ char(114),
+ char(73),
+ char(110),
+ char(100),
+ char(101),
+ char(120),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(98),
+ char(111),
+ char(100),
+ char(121),
+ char(65),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(98),
+ char(111),
+ char(100),
+ char(121),
+ char(66),
+ char(0),
+ char(109),
+ char(95),
+ char(114),
+ char(101),
+ char(102),
+ char(115),
+ char(91),
+ char(50),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(102),
+ char(109),
+ char(0),
+ char(109),
+ char(95),
+ char(115),
+ char(112),
+ char(108),
+ char(105),
+ char(116),
+ char(0),
+ char(109),
+ char(95),
+ char(100),
+ char(101),
+ char(108),
+ char(101),
+ char(116),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(114),
+ char(101),
+ char(108),
+ char(80),
+ char(111),
+ char(115),
+ char(105),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(91),
+ char(50),
+ char(93),
+ char(0),
+ char(109),
+ char(95),
+ char(98),
+ char(111),
+ char(100),
+ char(121),
+ char(65),
+ char(116),
+ char(121),
+ char(112),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(98),
+ char(111),
+ char(100),
+ char(121),
+ char(66),
+ char(116),
+ char(121),
+ char(112),
+ char(101),
+ char(0),
+ char(109),
+ char(95),
+ char(106),
+ char(111),
+ char(105),
+ char(110),
+ char(116),
+ char(84),
+ char(121),
+ char(112),
+ char(101),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(112),
+ char(111),
+ char(115),
+ char(101),
+ char(0),
+ char(42),
+ char(42),
+ char(109),
+ char(95),
+ char(109),
+ char(97),
+ char(116),
+ char(101),
+ char(114),
+ char(105),
+ char(97),
+ char(108),
+ char(115),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(110),
+ char(111),
+ char(100),
+ char(101),
+ char(115),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(108),
+ char(105),
+ char(110),
+ char(107),
+ char(115),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(102),
+ char(97),
+ char(99),
+ char(101),
+ char(115),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(116),
+ char(101),
+ char(116),
+ char(114),
+ char(97),
+ char(104),
+ char(101),
+ char(100),
+ char(114),
+ char(97),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(97),
+ char(110),
+ char(99),
+ char(104),
+ char(111),
+ char(114),
+ char(115),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(99),
+ char(108),
+ char(117),
+ char(115),
+ char(116),
+ char(101),
+ char(114),
+ char(115),
+ char(0),
+ char(42),
+ char(109),
+ char(95),
+ char(106),
+ char(111),
+ char(105),
+ char(110),
+ char(116),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(77),
+ char(97),
+ char(116),
+ char(101),
+ char(114),
+ char(105),
+ char(97),
+ char(108),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(76),
+ char(105),
+ char(110),
+ char(107),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(70),
+ char(97),
+ char(99),
+ char(101),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(84),
+ char(101),
+ char(116),
+ char(114),
+ char(97),
+ char(104),
+ char(101),
+ char(100),
+ char(114),
+ char(97),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(65),
+ char(110),
+ char(99),
+ char(104),
+ char(111),
+ char(114),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(67),
+ char(108),
+ char(117),
+ char(115),
+ char(116),
+ char(101),
+ char(114),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(110),
+ char(117),
+ char(109),
+ char(74),
+ char(111),
+ char(105),
+ char(110),
+ char(116),
+ char(115),
+ char(0),
+ char(109),
+ char(95),
+ char(99),
+ char(111),
+ char(110),
+ char(102),
+ char(105),
+ char(103),
+ char(0),
+ char(84),
+ char(89),
+ char(80),
+ char(69),
+ char(76),
+ char(0),
+ char(0),
+ char(0),
+ char(99),
+ char(104),
+ char(97),
+ char(114),
+ char(0),
+ char(117),
+ char(99),
+ char(104),
+ char(97),
+ char(114),
+ char(0),
+ char(115),
+ char(104),
+ char(111),
+ char(114),
+ char(116),
+ char(0),
+ char(117),
+ char(115),
+ char(104),
+ char(111),
+ char(114),
+ char(116),
+ char(0),
+ char(105),
+ char(110),
+ char(116),
+ char(0),
+ char(108),
+ char(111),
+ char(110),
+ char(103),
+ char(0),
+ char(117),
+ char(108),
+ char(111),
+ char(110),
+ char(103),
+ char(0),
+ char(102),
+ char(108),
+ char(111),
+ char(97),
+ char(116),
+ char(0),
+ char(100),
+ char(111),
+ char(117),
+ char(98),
+ char(108),
+ char(101),
+ char(0),
+ char(118),
+ char(111),
+ char(105),
+ char(100),
+ char(0),
+ char(80),
+ char(111),
+ char(105),
+ char(110),
+ char(116),
+ char(101),
+ char(114),
+ char(65),
+ char(114),
+ char(114),
+ char(97),
+ char(121),
+ char(0),
+ char(98),
+ char(116),
+ char(80),
+ char(104),
+ char(121),
+ char(115),
+ char(105),
+ char(99),
+ char(115),
+ char(83),
+ char(121),
+ char(115),
+ char(116),
+ char(101),
+ char(109),
+ char(0),
+ char(76),
+ char(105),
+ char(115),
+ char(116),
+ char(66),
+ char(97),
+ char(115),
+ char(101),
+ char(0),
+ char(98),
+ char(116),
+ char(86),
+ char(101),
+ char(99),
+ char(116),
+ char(111),
+ char(114),
+ char(51),
+ char(70),
+ char(108),
+ char(111),
+ char(97),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(86),
+ char(101),
+ char(99),
+ char(116),
+ char(111),
+ char(114),
+ char(51),
+ char(68),
+ char(111),
+ char(117),
+ char(98),
+ char(108),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(77),
+ char(97),
+ char(116),
+ char(114),
+ char(105),
+ char(120),
+ char(51),
+ char(120),
+ char(51),
+ char(70),
+ char(108),
+ char(111),
+ char(97),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(77),
+ char(97),
+ char(116),
+ char(114),
+ char(105),
+ char(120),
+ char(51),
+ char(120),
+ char(51),
+ char(68),
+ char(111),
+ char(117),
+ char(98),
+ char(108),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(84),
+ char(114),
+ char(97),
+ char(110),
+ char(115),
+ char(102),
+ char(111),
+ char(114),
+ char(109),
+ char(70),
+ char(108),
+ char(111),
+ char(97),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(84),
+ char(114),
+ char(97),
+ char(110),
+ char(115),
+ char(102),
+ char(111),
+ char(114),
+ char(109),
+ char(68),
+ char(111),
+ char(117),
+ char(98),
+ char(108),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(66),
+ char(118),
+ char(104),
+ char(83),
+ char(117),
+ char(98),
+ char(116),
+ char(114),
+ char(101),
+ char(101),
+ char(73),
+ char(110),
+ char(102),
+ char(111),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(79),
+ char(112),
+ char(116),
+ char(105),
+ char(109),
+ char(105),
+ char(122),
+ char(101),
+ char(100),
+ char(66),
+ char(118),
+ char(104),
+ char(78),
+ char(111),
+ char(100),
+ char(101),
+ char(70),
+ char(108),
+ char(111),
+ char(97),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(79),
+ char(112),
+ char(116),
+ char(105),
+ char(109),
+ char(105),
+ char(122),
+ char(101),
+ char(100),
+ char(66),
+ char(118),
+ char(104),
+ char(78),
+ char(111),
+ char(100),
+ char(101),
+ char(68),
+ char(111),
+ char(117),
+ char(98),
+ char(108),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(81),
+ char(117),
+ char(97),
+ char(110),
+ char(116),
+ char(105),
+ char(122),
+ char(101),
+ char(100),
+ char(66),
+ char(118),
+ char(104),
+ char(78),
+ char(111),
+ char(100),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(81),
+ char(117),
+ char(97),
+ char(110),
+ char(116),
+ char(105),
+ char(122),
+ char(101),
+ char(100),
+ char(66),
+ char(118),
+ char(104),
+ char(70),
+ char(108),
+ char(111),
+ char(97),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(81),
+ char(117),
+ char(97),
+ char(110),
+ char(116),
+ char(105),
+ char(122),
+ char(101),
+ char(100),
+ char(66),
+ char(118),
+ char(104),
+ char(68),
+ char(111),
+ char(117),
+ char(98),
+ char(108),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(67),
+ char(111),
+ char(108),
+ char(108),
+ char(105),
+ char(115),
+ char(105),
+ char(111),
+ char(110),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(83),
+ char(116),
+ char(97),
+ char(116),
+ char(105),
+ char(99),
+ char(80),
+ char(108),
+ char(97),
+ char(110),
+ char(101),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(67),
+ char(111),
+ char(110),
+ char(118),
+ char(101),
+ char(120),
+ char(73),
+ char(110),
+ char(116),
+ char(101),
+ char(114),
+ char(110),
+ char(97),
+ char(108),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(80),
+ char(111),
+ char(115),
+ char(105),
+ char(116),
+ char(105),
+ char(111),
+ char(110),
+ char(65),
+ char(110),
+ char(100),
+ char(82),
+ char(97),
+ char(100),
+ char(105),
+ char(117),
+ char(115),
+ char(0),
+ char(98),
+ char(116),
+ char(77),
+ char(117),
+ char(108),
+ char(116),
+ char(105),
+ char(83),
+ char(112),
+ char(104),
+ char(101),
+ char(114),
+ char(101),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(73),
+ char(110),
+ char(116),
+ char(73),
+ char(110),
+ char(100),
+ char(101),
+ char(120),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(83),
+ char(104),
+ char(111),
+ char(114),
+ char(116),
+ char(73),
+ char(110),
+ char(116),
+ char(73),
+ char(110),
+ char(100),
+ char(101),
+ char(120),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(83),
+ char(104),
+ char(111),
+ char(114),
+ char(116),
+ char(73),
+ char(110),
+ char(116),
+ char(73),
+ char(110),
+ char(100),
+ char(101),
+ char(120),
+ char(84),
+ char(114),
+ char(105),
+ char(112),
+ char(108),
+ char(101),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(67),
+ char(104),
+ char(97),
+ char(114),
+ char(73),
+ char(110),
+ char(100),
+ char(101),
+ char(120),
+ char(84),
+ char(114),
+ char(105),
+ char(112),
+ char(108),
+ char(101),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(77),
+ char(101),
+ char(115),
+ char(104),
+ char(80),
+ char(97),
+ char(114),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(83),
+ char(116),
+ char(114),
+ char(105),
+ char(100),
+ char(105),
+ char(110),
+ char(103),
+ char(77),
+ char(101),
+ char(115),
+ char(104),
+ char(73),
+ char(110),
+ char(116),
+ char(101),
+ char(114),
+ char(102),
+ char(97),
+ char(99),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(84),
+ char(114),
+ char(105),
+ char(97),
+ char(110),
+ char(103),
+ char(108),
+ char(101),
+ char(77),
+ char(101),
+ char(115),
+ char(104),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(84),
+ char(114),
+ char(105),
+ char(97),
+ char(110),
+ char(103),
+ char(108),
+ char(101),
+ char(73),
+ char(110),
+ char(102),
+ char(111),
+ char(77),
+ char(97),
+ char(112),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(83),
+ char(99),
+ char(97),
+ char(108),
+ char(101),
+ char(100),
+ char(84),
+ char(114),
+ char(105),
+ char(97),
+ char(110),
+ char(103),
+ char(108),
+ char(101),
+ char(77),
+ char(101),
+ char(115),
+ char(104),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(67),
+ char(111),
+ char(109),
+ char(112),
+ char(111),
+ char(117),
+ char(110),
+ char(100),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(67),
+ char(104),
+ char(105),
+ char(108),
+ char(100),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(67),
+ char(111),
+ char(109),
+ char(112),
+ char(111),
+ char(117),
+ char(110),
+ char(100),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(67),
+ char(121),
+ char(108),
+ char(105),
+ char(110),
+ char(100),
+ char(101),
+ char(114),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(67),
+ char(97),
+ char(112),
+ char(115),
+ char(117),
+ char(108),
+ char(101),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(84),
+ char(114),
+ char(105),
+ char(97),
+ char(110),
+ char(103),
+ char(108),
+ char(101),
+ char(73),
+ char(110),
+ char(102),
+ char(111),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(71),
+ char(73),
+ char(109),
+ char(112),
+ char(97),
+ char(99),
+ char(116),
+ char(77),
+ char(101),
+ char(115),
+ char(104),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(67),
+ char(111),
+ char(110),
+ char(118),
+ char(101),
+ char(120),
+ char(72),
+ char(117),
+ char(108),
+ char(108),
+ char(83),
+ char(104),
+ char(97),
+ char(112),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(67),
+ char(111),
+ char(108),
+ char(108),
+ char(105),
+ char(115),
+ char(105),
+ char(111),
+ char(110),
+ char(79),
+ char(98),
+ char(106),
+ char(101),
+ char(99),
+ char(116),
+ char(68),
+ char(111),
+ char(117),
+ char(98),
+ char(108),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(67),
+ char(111),
+ char(108),
+ char(108),
+ char(105),
+ char(115),
+ char(105),
+ char(111),
+ char(110),
+ char(79),
+ char(98),
+ char(106),
+ char(101),
+ char(99),
+ char(116),
+ char(70),
+ char(108),
+ char(111),
+ char(97),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(68),
+ char(121),
+ char(110),
+ char(97),
+ char(109),
+ char(105),
+ char(99),
+ char(115),
+ char(87),
+ char(111),
+ char(114),
+ char(108),
+ char(100),
+ char(68),
+ char(111),
+ char(117),
+ char(98),
+ char(108),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(67),
+ char(111),
+ char(110),
+ char(116),
+ char(97),
+ char(99),
+ char(116),
+ char(83),
+ char(111),
+ char(108),
+ char(118),
+ char(101),
+ char(114),
+ char(73),
+ char(110),
+ char(102),
+ char(111),
+ char(68),
+ char(111),
+ char(117),
+ char(98),
+ char(108),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(68),
+ char(121),
+ char(110),
+ char(97),
+ char(109),
+ char(105),
+ char(99),
+ char(115),
+ char(87),
+ char(111),
+ char(114),
+ char(108),
+ char(100),
+ char(70),
+ char(108),
+ char(111),
+ char(97),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(67),
+ char(111),
+ char(110),
+ char(116),
+ char(97),
+ char(99),
+ char(116),
+ char(83),
+ char(111),
+ char(108),
+ char(118),
+ char(101),
+ char(114),
+ char(73),
+ char(110),
+ char(102),
+ char(111),
+ char(70),
+ char(108),
+ char(111),
+ char(97),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(82),
+ char(105),
+ char(103),
+ char(105),
+ char(100),
+ char(66),
+ char(111),
+ char(100),
+ char(121),
+ char(70),
+ char(108),
+ char(111),
+ char(97),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(82),
+ char(105),
+ char(103),
+ char(105),
+ char(100),
+ char(66),
+ char(111),
+ char(100),
+ char(121),
+ char(68),
+ char(111),
+ char(117),
+ char(98),
+ char(108),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(67),
+ char(111),
+ char(110),
+ char(115),
+ char(116),
+ char(114),
+ char(97),
+ char(105),
+ char(110),
+ char(116),
+ char(73),
+ char(110),
+ char(102),
+ char(111),
+ char(49),
+ char(0),
+ char(98),
+ char(116),
+ char(84),
+ char(121),
+ char(112),
+ char(101),
+ char(100),
+ char(67),
+ char(111),
+ char(110),
+ char(115),
+ char(116),
+ char(114),
+ char(97),
+ char(105),
+ char(110),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(82),
+ char(105),
+ char(103),
+ char(105),
+ char(100),
+ char(66),
+ char(111),
+ char(100),
+ char(121),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(80),
+ char(111),
+ char(105),
+ char(110),
+ char(116),
+ char(50),
+ char(80),
+ char(111),
+ char(105),
+ char(110),
+ char(116),
+ char(67),
+ char(111),
+ char(110),
+ char(115),
+ char(116),
+ char(114),
+ char(97),
+ char(105),
+ char(110),
+ char(116),
+ char(70),
+ char(108),
+ char(111),
+ char(97),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(80),
+ char(111),
+ char(105),
+ char(110),
+ char(116),
+ char(50),
+ char(80),
+ char(111),
+ char(105),
+ char(110),
+ char(116),
+ char(67),
+ char(111),
+ char(110),
+ char(115),
+ char(116),
+ char(114),
+ char(97),
+ char(105),
+ char(110),
+ char(116),
+ char(68),
+ char(111),
+ char(117),
+ char(98),
+ char(108),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(72),
+ char(105),
+ char(110),
+ char(103),
+ char(101),
+ char(67),
+ char(111),
+ char(110),
+ char(115),
+ char(116),
+ char(114),
+ char(97),
+ char(105),
+ char(110),
+ char(116),
+ char(68),
+ char(111),
+ char(117),
+ char(98),
+ char(108),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(72),
+ char(105),
+ char(110),
+ char(103),
+ char(101),
+ char(67),
+ char(111),
+ char(110),
+ char(115),
+ char(116),
+ char(114),
+ char(97),
+ char(105),
+ char(110),
+ char(116),
+ char(70),
+ char(108),
+ char(111),
+ char(97),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(67),
+ char(111),
+ char(110),
+ char(101),
+ char(84),
+ char(119),
+ char(105),
+ char(115),
+ char(116),
+ char(67),
+ char(111),
+ char(110),
+ char(115),
+ char(116),
+ char(114),
+ char(97),
+ char(105),
+ char(110),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(71),
+ char(101),
+ char(110),
+ char(101),
+ char(114),
+ char(105),
+ char(99),
+ char(54),
+ char(68),
+ char(111),
+ char(102),
+ char(67),
+ char(111),
+ char(110),
+ char(115),
+ char(116),
+ char(114),
+ char(97),
+ char(105),
+ char(110),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(71),
+ char(101),
+ char(110),
+ char(101),
+ char(114),
+ char(105),
+ char(99),
+ char(54),
+ char(68),
+ char(111),
+ char(102),
+ char(83),
+ char(112),
+ char(114),
+ char(105),
+ char(110),
+ char(103),
+ char(67),
+ char(111),
+ char(110),
+ char(115),
+ char(116),
+ char(114),
+ char(97),
+ char(105),
+ char(110),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(83),
+ char(108),
+ char(105),
+ char(100),
+ char(101),
+ char(114),
+ char(67),
+ char(111),
+ char(110),
+ char(115),
+ char(116),
+ char(114),
+ char(97),
+ char(105),
+ char(110),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(83),
+ char(111),
+ char(102),
+ char(116),
+ char(66),
+ char(111),
+ char(100),
+ char(121),
+ char(77),
+ char(97),
+ char(116),
+ char(101),
+ char(114),
+ char(105),
+ char(97),
+ char(108),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(83),
+ char(111),
+ char(102),
+ char(116),
+ char(66),
+ char(111),
+ char(100),
+ char(121),
+ char(78),
+ char(111),
+ char(100),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(83),
+ char(111),
+ char(102),
+ char(116),
+ char(66),
+ char(111),
+ char(100),
+ char(121),
+ char(76),
+ char(105),
+ char(110),
+ char(107),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(83),
+ char(111),
+ char(102),
+ char(116),
+ char(66),
+ char(111),
+ char(100),
+ char(121),
+ char(70),
+ char(97),
+ char(99),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(83),
+ char(111),
+ char(102),
+ char(116),
+ char(66),
+ char(111),
+ char(100),
+ char(121),
+ char(84),
+ char(101),
+ char(116),
+ char(114),
+ char(97),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(83),
+ char(111),
+ char(102),
+ char(116),
+ char(82),
+ char(105),
+ char(103),
+ char(105),
+ char(100),
+ char(65),
+ char(110),
+ char(99),
+ char(104),
+ char(111),
+ char(114),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(83),
+ char(111),
+ char(102),
+ char(116),
+ char(66),
+ char(111),
+ char(100),
+ char(121),
+ char(67),
+ char(111),
+ char(110),
+ char(102),
+ char(105),
+ char(103),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(83),
+ char(111),
+ char(102),
+ char(116),
+ char(66),
+ char(111),
+ char(100),
+ char(121),
+ char(80),
+ char(111),
+ char(115),
+ char(101),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(83),
+ char(111),
+ char(102),
+ char(116),
+ char(66),
+ char(111),
+ char(100),
+ char(121),
+ char(67),
+ char(108),
+ char(117),
+ char(115),
+ char(116),
+ char(101),
+ char(114),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(83),
+ char(111),
+ char(102),
+ char(116),
+ char(66),
+ char(111),
+ char(100),
+ char(121),
+ char(74),
+ char(111),
+ char(105),
+ char(110),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(98),
+ char(116),
+ char(83),
+ char(111),
+ char(102),
+ char(116),
+ char(66),
+ char(111),
+ char(100),
+ char(121),
+ char(70),
+ char(108),
+ char(111),
+ char(97),
+ char(116),
+ char(68),
+ char(97),
+ char(116),
+ char(97),
+ char(0),
+ char(0),
+ char(0),
+ char(84),
+ char(76),
+ char(69),
+ char(78),
+ char(1),
+ char(0),
+ char(1),
+ char(0),
+ char(2),
+ char(0),
+ char(2),
+ char(0),
+ char(4),
+ char(0),
+ char(4),
+ char(0),
+ char(4),
+ char(0),
+ char(4),
+ char(0),
+ char(8),
+ char(0),
+ char(0),
+ char(0),
+ char(16),
+ char(0),
+ char(48),
+ char(0),
+ char(16),
+ char(0),
+ char(16),
+ char(0),
+ char(32),
+ char(0),
+ char(48),
+ char(0),
+ char(96),
+ char(0),
+ char(64),
+ char(0),
+ char(-128),
+ char(0),
+ char(20),
+ char(0),
+ char(48),
+ char(0),
+ char(80),
+ char(0),
+ char(16),
+ char(0),
+ char(96),
+ char(0),
+ char(-112),
+ char(0),
+ char(16),
+ char(0),
+ char(56),
+ char(0),
+ char(56),
+ char(0),
+ char(20),
+ char(0),
+ char(72),
+ char(0),
+ char(4),
+ char(0),
+ char(4),
+ char(0),
+ char(8),
+ char(0),
+ char(4),
+ char(0),
+ char(56),
+ char(0),
+ char(32),
+ char(0),
+ char(80),
+ char(0),
+ char(72),
+ char(0),
+ char(96),
+ char(0),
+ char(80),
+ char(0),
+ char(32),
+ char(0),
+ char(64),
+ char(0),
+ char(64),
+ char(0),
+ char(16),
+ char(0),
+ char(72),
+ char(0),
+ char(80),
+ char(0),
+ char(-32),
+ char(1),
+ char(16),
+ char(1),
+ char(-72),
+ char(0),
+ char(-104),
+ char(0),
+ char(104),
+ char(0),
+ char(88),
+ char(0),
+ char(-8),
+ char(1),
+ char(-80),
+ char(3),
+ char(8),
+ char(0),
+ char(64),
+ char(0),
+ char(0),
+ char(0),
+ char(96),
+ char(0),
+ char(-128),
+ char(0),
+ char(104),
+ char(1),
+ char(-24),
+ char(0),
+ char(-32),
+ char(0),
+ char(8),
+ char(1),
+ char(104),
+ char(1),
+ char(-40),
+ char(0),
+ char(16),
+ char(0),
+ char(104),
+ char(0),
+ char(24),
+ char(0),
+ char(40),
+ char(0),
+ char(104),
+ char(0),
+ char(96),
+ char(0),
+ char(104),
+ char(0),
+ char(-56),
+ char(0),
+ char(104),
+ char(1),
+ char(112),
+ char(0),
+ char(-32),
+ char(1),
+ char(83),
+ char(84),
+ char(82),
+ char(67),
+ char(65),
+ char(0),
+ char(0),
+ char(0),
+ char(10),
+ char(0),
+ char(3),
+ char(0),
+ char(4),
+ char(0),
+ char(0),
+ char(0),
+ char(4),
+ char(0),
+ char(1),
+ char(0),
+ char(9),
+ char(0),
+ char(2),
+ char(0),
+ char(11),
+ char(0),
+ char(3),
+ char(0),
+ char(10),
+ char(0),
+ char(3),
+ char(0),
+ char(10),
+ char(0),
+ char(4),
+ char(0),
+ char(10),
+ char(0),
+ char(5),
+ char(0),
+ char(12),
+ char(0),
+ char(2),
+ char(0),
+ char(9),
+ char(0),
+ char(6),
+ char(0),
+ char(9),
+ char(0),
+ char(7),
+ char(0),
+ char(13),
+ char(0),
+ char(1),
+ char(0),
+ char(7),
+ char(0),
+ char(8),
+ char(0),
+ char(14),
+ char(0),
+ char(1),
+ char(0),
+ char(8),
+ char(0),
+ char(8),
+ char(0),
+ char(15),
+ char(0),
+ char(1),
+ char(0),
+ char(13),
+ char(0),
+ char(9),
+ char(0),
+ char(16),
+ char(0),
+ char(1),
+ char(0),
+ char(14),
+ char(0),
+ char(9),
+ char(0),
+ char(17),
+ char(0),
+ char(2),
+ char(0),
+ char(15),
+ char(0),
+ char(10),
+ char(0),
+ char(13),
+ char(0),
+ char(11),
+ char(0),
+ char(18),
+ char(0),
+ char(2),
+ char(0),
+ char(16),
+ char(0),
+ char(10),
+ char(0),
+ char(14),
+ char(0),
+ char(11),
+ char(0),
+ char(19),
+ char(0),
+ char(4),
+ char(0),
+ char(4),
+ char(0),
+ char(12),
+ char(0),
+ char(4),
+ char(0),
+ char(13),
+ char(0),
+ char(2),
+ char(0),
+ char(14),
+ char(0),
+ char(2),
+ char(0),
+ char(15),
+ char(0),
+ char(20),
+ char(0),
+ char(6),
+ char(0),
+ char(13),
+ char(0),
+ char(16),
+ char(0),
+ char(13),
+ char(0),
+ char(17),
+ char(0),
+ char(4),
+ char(0),
+ char(18),
+ char(0),
+ char(4),
+ char(0),
+ char(19),
+ char(0),
+ char(4),
+ char(0),
+ char(20),
+ char(0),
+ char(0),
+ char(0),
+ char(21),
+ char(0),
+ char(21),
+ char(0),
+ char(6),
+ char(0),
+ char(14),
+ char(0),
+ char(16),
+ char(0),
+ char(14),
+ char(0),
+ char(17),
+ char(0),
+ char(4),
+ char(0),
+ char(18),
+ char(0),
+ char(4),
+ char(0),
+ char(19),
+ char(0),
+ char(4),
+ char(0),
+ char(20),
+ char(0),
+ char(0),
+ char(0),
+ char(21),
+ char(0),
+ char(22),
+ char(0),
+ char(3),
+ char(0),
+ char(2),
+ char(0),
+ char(14),
+ char(0),
+ char(2),
+ char(0),
+ char(15),
+ char(0),
+ char(4),
+ char(0),
+ char(22),
+ char(0),
+ char(23),
+ char(0),
+ char(12),
+ char(0),
+ char(13),
+ char(0),
+ char(23),
+ char(0),
+ char(13),
+ char(0),
+ char(24),
+ char(0),
+ char(13),
+ char(0),
+ char(25),
+ char(0),
+ char(4),
+ char(0),
+ char(26),
+ char(0),
+ char(4),
+ char(0),
+ char(27),
+ char(0),
+ char(4),
+ char(0),
+ char(28),
+ char(0),
+ char(4),
+ char(0),
+ char(29),
+ char(0),
+ char(20),
+ char(0),
+ char(30),
+ char(0),
+ char(22),
+ char(0),
+ char(31),
+ char(0),
+ char(19),
+ char(0),
+ char(32),
+ char(0),
+ char(4),
+ char(0),
+ char(33),
+ char(0),
+ char(4),
+ char(0),
+ char(34),
+ char(0),
+ char(24),
+ char(0),
+ char(12),
+ char(0),
+ char(14),
+ char(0),
+ char(23),
+ char(0),
+ char(14),
+ char(0),
+ char(24),
+ char(0),
+ char(14),
+ char(0),
+ char(25),
+ char(0),
+ char(4),
+ char(0),
+ char(26),
+ char(0),
+ char(4),
+ char(0),
+ char(27),
+ char(0),
+ char(4),
+ char(0),
+ char(28),
+ char(0),
+ char(4),
+ char(0),
+ char(29),
+ char(0),
+ char(21),
+ char(0),
+ char(30),
+ char(0),
+ char(22),
+ char(0),
+ char(31),
+ char(0),
+ char(4),
+ char(0),
+ char(33),
+ char(0),
+ char(4),
+ char(0),
+ char(34),
+ char(0),
+ char(19),
+ char(0),
+ char(32),
+ char(0),
+ char(25),
+ char(0),
+ char(3),
+ char(0),
+ char(0),
+ char(0),
+ char(35),
+ char(0),
+ char(4),
+ char(0),
+ char(36),
+ char(0),
+ char(0),
+ char(0),
+ char(37),
+ char(0),
+ char(26),
+ char(0),
+ char(5),
+ char(0),
+ char(25),
+ char(0),
+ char(38),
+ char(0),
+ char(13),
+ char(0),
+ char(39),
+ char(0),
+ char(13),
+ char(0),
+ char(40),
+ char(0),
+ char(7),
+ char(0),
+ char(41),
+ char(0),
+ char(0),
+ char(0),
+ char(21),
+ char(0),
+ char(27),
+ char(0),
+ char(5),
+ char(0),
+ char(25),
+ char(0),
+ char(38),
+ char(0),
+ char(13),
+ char(0),
+ char(39),
+ char(0),
+ char(13),
+ char(0),
+ char(42),
+ char(0),
+ char(7),
+ char(0),
+ char(43),
+ char(0),
+ char(4),
+ char(0),
+ char(44),
+ char(0),
+ char(28),
+ char(0),
+ char(2),
+ char(0),
+ char(13),
+ char(0),
+ char(45),
+ char(0),
+ char(7),
+ char(0),
+ char(46),
+ char(0),
+ char(29),
+ char(0),
+ char(4),
+ char(0),
+ char(27),
+ char(0),
+ char(47),
+ char(0),
+ char(28),
+ char(0),
+ char(48),
+ char(0),
+ char(4),
+ char(0),
+ char(49),
+ char(0),
+ char(0),
+ char(0),
+ char(37),
+ char(0),
+ char(30),
+ char(0),
+ char(1),
+ char(0),
+ char(4),
+ char(0),
+ char(50),
+ char(0),
+ char(31),
+ char(0),
+ char(2),
+ char(0),
+ char(2),
+ char(0),
+ char(50),
+ char(0),
+ char(0),
+ char(0),
+ char(51),
+ char(0),
+ char(32),
+ char(0),
+ char(2),
+ char(0),
+ char(2),
+ char(0),
+ char(52),
+ char(0),
+ char(0),
+ char(0),
+ char(51),
+ char(0),
+ char(33),
+ char(0),
+ char(2),
+ char(0),
+ char(0),
+ char(0),
+ char(52),
+ char(0),
+ char(0),
+ char(0),
+ char(53),
+ char(0),
+ char(34),
+ char(0),
+ char(8),
+ char(0),
+ char(13),
+ char(0),
+ char(54),
+ char(0),
+ char(14),
+ char(0),
+ char(55),
+ char(0),
+ char(30),
+ char(0),
+ char(56),
+ char(0),
+ char(32),
+ char(0),
+ char(57),
+ char(0),
+ char(33),
+ char(0),
+ char(58),
+ char(0),
+ char(31),
+ char(0),
+ char(59),
+ char(0),
+ char(4),
+ char(0),
+ char(60),
+ char(0),
+ char(4),
+ char(0),
+ char(61),
+ char(0),
+ char(35),
+ char(0),
+ char(4),
+ char(0),
+ char(34),
+ char(0),
+ char(62),
+ char(0),
+ char(13),
+ char(0),
+ char(63),
+ char(0),
+ char(4),
+ char(0),
+ char(64),
+ char(0),
+ char(0),
+ char(0),
+ char(37),
+ char(0),
+ char(36),
+ char(0),
+ char(7),
+ char(0),
+ char(25),
+ char(0),
+ char(38),
+ char(0),
+ char(35),
+ char(0),
+ char(65),
+ char(0),
+ char(23),
+ char(0),
+ char(66),
+ char(0),
+ char(24),
+ char(0),
+ char(67),
+ char(0),
+ char(37),
+ char(0),
+ char(68),
+ char(0),
+ char(7),
+ char(0),
+ char(43),
+ char(0),
+ char(0),
+ char(0),
+ char(69),
+ char(0),
+ char(38),
+ char(0),
+ char(2),
+ char(0),
+ char(36),
+ char(0),
+ char(70),
+ char(0),
+ char(13),
+ char(0),
+ char(39),
+ char(0),
+ char(39),
+ char(0),
+ char(4),
+ char(0),
+ char(17),
+ char(0),
+ char(71),
+ char(0),
+ char(25),
+ char(0),
+ char(72),
+ char(0),
+ char(4),
+ char(0),
+ char(73),
+ char(0),
+ char(7),
+ char(0),
+ char(74),
+ char(0),
+ char(40),
+ char(0),
+ char(4),
+ char(0),
+ char(25),
+ char(0),
+ char(38),
+ char(0),
+ char(39),
+ char(0),
+ char(75),
+ char(0),
+ char(4),
+ char(0),
+ char(76),
+ char(0),
+ char(7),
+ char(0),
+ char(43),
+ char(0),
+ char(41),
+ char(0),
+ char(3),
+ char(0),
+ char(27),
+ char(0),
+ char(47),
+ char(0),
+ char(4),
+ char(0),
+ char(77),
+ char(0),
+ char(0),
+ char(0),
+ char(37),
+ char(0),
+ char(42),
+ char(0),
+ char(3),
+ char(0),
+ char(27),
+ char(0),
+ char(47),
+ char(0),
+ char(4),
+ char(0),
+ char(77),
+ char(0),
+ char(0),
+ char(0),
+ char(37),
+ char(0),
+ char(43),
+ char(0),
+ char(4),
+ char(0),
+ char(4),
+ char(0),
+ char(78),
+ char(0),
+ char(7),
+ char(0),
+ char(79),
+ char(0),
+ char(7),
+ char(0),
+ char(80),
+ char(0),
+ char(7),
+ char(0),
+ char(81),
+ char(0),
+ char(37),
+ char(0),
+ char(14),
+ char(0),
+ char(4),
+ char(0),
+ char(82),
+ char(0),
+ char(4),
+ char(0),
+ char(83),
+ char(0),
+ char(43),
+ char(0),
+ char(84),
+ char(0),
+ char(4),
+ char(0),
+ char(85),
+ char(0),
+ char(7),
+ char(0),
+ char(86),
+ char(0),
+ char(7),
+ char(0),
+ char(87),
+ char(0),
+ char(7),
+ char(0),
+ char(88),
+ char(0),
+ char(7),
+ char(0),
+ char(89),
+ char(0),
+ char(7),
+ char(0),
+ char(90),
+ char(0),
+ char(4),
+ char(0),
+ char(91),
+ char(0),
+ char(4),
+ char(0),
+ char(92),
+ char(0),
+ char(4),
+ char(0),
+ char(93),
+ char(0),
+ char(4),
+ char(0),
+ char(94),
+ char(0),
+ char(0),
+ char(0),
+ char(37),
+ char(0),
+ char(44),
+ char(0),
+ char(5),
+ char(0),
+ char(25),
+ char(0),
+ char(38),
+ char(0),
+ char(35),
+ char(0),
+ char(65),
+ char(0),
+ char(13),
+ char(0),
+ char(39),
+ char(0),
+ char(7),
+ char(0),
+ char(43),
+ char(0),
+ char(4),
+ char(0),
+ char(95),
+ char(0),
+ char(45),
+ char(0),
+ char(5),
+ char(0),
+ char(27),
+ char(0),
+ char(47),
+ char(0),
+ char(13),
+ char(0),
+ char(96),
+ char(0),
+ char(14),
+ char(0),
+ char(97),
+ char(0),
+ char(4),
+ char(0),
+ char(98),
+ char(0),
+ char(0),
+ char(0),
+ char(99),
+ char(0),
+ char(46),
+ char(0),
+ char(25),
+ char(0),
+ char(9),
+ char(0),
+ char(100),
+ char(0),
+ char(9),
+ char(0),
+ char(101),
+ char(0),
+ char(25),
+ char(0),
+ char(102),
+ char(0),
+ char(0),
+ char(0),
+ char(35),
+ char(0),
+ char(18),
+ char(0),
+ char(103),
+ char(0),
+ char(18),
+ char(0),
+ char(104),
+ char(0),
+ char(14),
+ char(0),
+ char(105),
+ char(0),
+ char(14),
+ char(0),
+ char(106),
+ char(0),
+ char(14),
+ char(0),
+ char(107),
+ char(0),
+ char(8),
+ char(0),
+ char(108),
+ char(0),
+ char(8),
+ char(0),
+ char(109),
+ char(0),
+ char(8),
+ char(0),
+ char(110),
+ char(0),
+ char(8),
+ char(0),
+ char(111),
+ char(0),
+ char(8),
+ char(0),
+ char(112),
+ char(0),
+ char(8),
+ char(0),
+ char(113),
+ char(0),
+ char(8),
+ char(0),
+ char(114),
+ char(0),
+ char(8),
+ char(0),
+ char(115),
+ char(0),
+ char(4),
+ char(0),
+ char(116),
+ char(0),
+ char(4),
+ char(0),
+ char(117),
+ char(0),
+ char(4),
+ char(0),
+ char(118),
+ char(0),
+ char(4),
+ char(0),
+ char(119),
+ char(0),
+ char(4),
+ char(0),
+ char(120),
+ char(0),
+ char(4),
+ char(0),
+ char(121),
+ char(0),
+ char(4),
+ char(0),
+ char(122),
+ char(0),
+ char(0),
+ char(0),
+ char(37),
+ char(0),
+ char(47),
+ char(0),
+ char(25),
+ char(0),
+ char(9),
+ char(0),
+ char(100),
+ char(0),
+ char(9),
+ char(0),
+ char(101),
+ char(0),
+ char(25),
+ char(0),
+ char(102),
+ char(0),
+ char(0),
+ char(0),
+ char(35),
+ char(0),
+ char(17),
+ char(0),
+ char(103),
+ char(0),
+ char(17),
+ char(0),
+ char(104),
+ char(0),
+ char(13),
+ char(0),
+ char(105),
+ char(0),
+ char(13),
+ char(0),
+ char(106),
+ char(0),
+ char(13),
+ char(0),
+ char(107),
+ char(0),
+ char(7),
+ char(0),
+ char(108),
+ char(0),
+ char(7),
+ char(0),
+ char(109),
+ char(0),
+ char(7),
+ char(0),
+ char(110),
+ char(0),
+ char(7),
+ char(0),
+ char(111),
+ char(0),
+ char(7),
+ char(0),
+ char(112),
+ char(0),
+ char(7),
+ char(0),
+ char(113),
+ char(0),
+ char(7),
+ char(0),
+ char(114),
+ char(0),
+ char(7),
+ char(0),
+ char(115),
+ char(0),
+ char(4),
+ char(0),
+ char(116),
+ char(0),
+ char(4),
+ char(0),
+ char(117),
+ char(0),
+ char(4),
+ char(0),
+ char(118),
+ char(0),
+ char(4),
+ char(0),
+ char(119),
+ char(0),
+ char(4),
+ char(0),
+ char(120),
+ char(0),
+ char(4),
+ char(0),
+ char(121),
+ char(0),
+ char(4),
+ char(0),
+ char(122),
+ char(0),
+ char(0),
+ char(0),
+ char(37),
+ char(0),
+ char(48),
+ char(0),
+ char(2),
+ char(0),
+ char(49),
+ char(0),
+ char(123),
+ char(0),
+ char(14),
+ char(0),
+ char(124),
+ char(0),
+ char(50),
+ char(0),
+ char(2),
+ char(0),
+ char(51),
+ char(0),
+ char(123),
+ char(0),
+ char(13),
+ char(0),
+ char(124),
+ char(0),
+ char(52),
+ char(0),
+ char(21),
+ char(0),
+ char(47),
+ char(0),
+ char(125),
+ char(0),
+ char(15),
+ char(0),
+ char(126),
+ char(0),
+ char(13),
+ char(0),
+ char(127),
+ char(0),
+ char(13),
+ char(0),
+ char(-128),
+ char(0),
+ char(13),
+ char(0),
+ char(-127),
+ char(0),
+ char(13),
+ char(0),
+ char(-126),
+ char(0),
+ char(13),
+ char(0),
+ char(124),
+ char(0),
+ char(13),
+ char(0),
+ char(-125),
+ char(0),
+ char(13),
+ char(0),
+ char(-124),
+ char(0),
+ char(13),
+ char(0),
+ char(-123),
+ char(0),
+ char(13),
+ char(0),
+ char(-122),
+ char(0),
+ char(7),
+ char(0),
+ char(-121),
+ char(0),
+ char(7),
+ char(0),
+ char(-120),
+ char(0),
+ char(7),
+ char(0),
+ char(-119),
+ char(0),
+ char(7),
+ char(0),
+ char(-118),
+ char(0),
+ char(7),
+ char(0),
+ char(-117),
+ char(0),
+ char(7),
+ char(0),
+ char(-116),
+ char(0),
+ char(7),
+ char(0),
+ char(-115),
+ char(0),
+ char(7),
+ char(0),
+ char(-114),
+ char(0),
+ char(7),
+ char(0),
+ char(-113),
+ char(0),
+ char(4),
+ char(0),
+ char(-112),
+ char(0),
+ char(53),
+ char(0),
+ char(22),
+ char(0),
+ char(46),
+ char(0),
+ char(125),
+ char(0),
+ char(16),
+ char(0),
+ char(126),
+ char(0),
+ char(14),
+ char(0),
+ char(127),
+ char(0),
+ char(14),
+ char(0),
+ char(-128),
+ char(0),
+ char(14),
+ char(0),
+ char(-127),
+ char(0),
+ char(14),
+ char(0),
+ char(-126),
+ char(0),
+ char(14),
+ char(0),
+ char(124),
+ char(0),
+ char(14),
+ char(0),
+ char(-125),
+ char(0),
+ char(14),
+ char(0),
+ char(-124),
+ char(0),
+ char(14),
+ char(0),
+ char(-123),
+ char(0),
+ char(14),
+ char(0),
+ char(-122),
+ char(0),
+ char(8),
+ char(0),
+ char(-121),
+ char(0),
+ char(8),
+ char(0),
+ char(-120),
+ char(0),
+ char(8),
+ char(0),
+ char(-119),
+ char(0),
+ char(8),
+ char(0),
+ char(-118),
+ char(0),
+ char(8),
+ char(0),
+ char(-117),
+ char(0),
+ char(8),
+ char(0),
+ char(-116),
+ char(0),
+ char(8),
+ char(0),
+ char(-115),
+ char(0),
+ char(8),
+ char(0),
+ char(-114),
+ char(0),
+ char(8),
+ char(0),
+ char(-113),
+ char(0),
+ char(4),
+ char(0),
+ char(-112),
+ char(0),
+ char(0),
+ char(0),
+ char(37),
+ char(0),
+ char(54),
+ char(0),
+ char(2),
+ char(0),
+ char(4),
+ char(0),
+ char(-111),
+ char(0),
+ char(4),
+ char(0),
+ char(-110),
+ char(0),
+ char(55),
+ char(0),
+ char(13),
+ char(0),
+ char(56),
+ char(0),
+ char(-109),
+ char(0),
+ char(56),
+ char(0),
+ char(-108),
+ char(0),
+ char(0),
+ char(0),
+ char(35),
+ char(0),
+ char(4),
+ char(0),
+ char(-107),
+ char(0),
+ char(4),
+ char(0),
+ char(-106),
+ char(0),
+ char(4),
+ char(0),
+ char(-105),
+ char(0),
+ char(4),
+ char(0),
+ char(-104),
+ char(0),
+ char(7),
+ char(0),
+ char(-103),
+ char(0),
+ char(7),
+ char(0),
+ char(-102),
+ char(0),
+ char(4),
+ char(0),
+ char(-101),
+ char(0),
+ char(4),
+ char(0),
+ char(-100),
+ char(0),
+ char(7),
+ char(0),
+ char(-99),
+ char(0),
+ char(4),
+ char(0),
+ char(-98),
+ char(0),
+ char(57),
+ char(0),
+ char(3),
+ char(0),
+ char(55),
+ char(0),
+ char(-97),
+ char(0),
+ char(13),
+ char(0),
+ char(-96),
+ char(0),
+ char(13),
+ char(0),
+ char(-95),
+ char(0),
+ char(58),
+ char(0),
+ char(3),
+ char(0),
+ char(55),
+ char(0),
+ char(-97),
+ char(0),
+ char(14),
+ char(0),
+ char(-96),
+ char(0),
+ char(14),
+ char(0),
+ char(-95),
+ char(0),
+ char(59),
+ char(0),
+ char(13),
+ char(0),
+ char(55),
+ char(0),
+ char(-97),
+ char(0),
+ char(18),
+ char(0),
+ char(-94),
+ char(0),
+ char(18),
+ char(0),
+ char(-93),
+ char(0),
+ char(4),
+ char(0),
+ char(-92),
+ char(0),
+ char(4),
+ char(0),
+ char(-91),
+ char(0),
+ char(4),
+ char(0),
+ char(-90),
+ char(0),
+ char(7),
+ char(0),
+ char(-89),
+ char(0),
+ char(7),
+ char(0),
+ char(-88),
+ char(0),
+ char(7),
+ char(0),
+ char(-87),
+ char(0),
+ char(7),
+ char(0),
+ char(-86),
+ char(0),
+ char(7),
+ char(0),
+ char(-85),
+ char(0),
+ char(7),
+ char(0),
+ char(-84),
+ char(0),
+ char(7),
+ char(0),
+ char(-83),
+ char(0),
+ char(60),
+ char(0),
+ char(13),
+ char(0),
+ char(55),
+ char(0),
+ char(-97),
+ char(0),
+ char(17),
+ char(0),
+ char(-94),
+ char(0),
+ char(17),
+ char(0),
+ char(-93),
+ char(0),
+ char(4),
+ char(0),
+ char(-92),
+ char(0),
+ char(4),
+ char(0),
+ char(-91),
+ char(0),
+ char(4),
+ char(0),
+ char(-90),
+ char(0),
+ char(7),
+ char(0),
+ char(-89),
+ char(0),
+ char(7),
+ char(0),
+ char(-88),
+ char(0),
+ char(7),
+ char(0),
+ char(-87),
+ char(0),
+ char(7),
+ char(0),
+ char(-86),
+ char(0),
+ char(7),
+ char(0),
+ char(-85),
+ char(0),
+ char(7),
+ char(0),
+ char(-84),
+ char(0),
+ char(7),
+ char(0),
+ char(-83),
+ char(0),
+ char(61),
+ char(0),
+ char(11),
+ char(0),
+ char(55),
+ char(0),
+ char(-97),
+ char(0),
+ char(17),
+ char(0),
+ char(-94),
+ char(0),
+ char(17),
+ char(0),
+ char(-93),
+ char(0),
+ char(7),
+ char(0),
+ char(-82),
+ char(0),
+ char(7),
+ char(0),
+ char(-81),
+ char(0),
+ char(7),
+ char(0),
+ char(-80),
+ char(0),
+ char(7),
+ char(0),
+ char(-85),
+ char(0),
+ char(7),
+ char(0),
+ char(-84),
+ char(0),
+ char(7),
+ char(0),
+ char(-83),
+ char(0),
+ char(7),
+ char(0),
+ char(-79),
+ char(0),
+ char(0),
+ char(0),
+ char(21),
+ char(0),
+ char(62),
+ char(0),
+ char(9),
+ char(0),
+ char(55),
+ char(0),
+ char(-97),
+ char(0),
+ char(17),
+ char(0),
+ char(-94),
+ char(0),
+ char(17),
+ char(0),
+ char(-93),
+ char(0),
+ char(13),
+ char(0),
+ char(-78),
+ char(0),
+ char(13),
+ char(0),
+ char(-77),
+ char(0),
+ char(13),
+ char(0),
+ char(-76),
+ char(0),
+ char(13),
+ char(0),
+ char(-75),
+ char(0),
+ char(4),
+ char(0),
+ char(-74),
+ char(0),
+ char(4),
+ char(0),
+ char(-73),
+ char(0),
+ char(63),
+ char(0),
+ char(5),
+ char(0),
+ char(62),
+ char(0),
+ char(-72),
+ char(0),
+ char(4),
+ char(0),
+ char(-71),
+ char(0),
+ char(7),
+ char(0),
+ char(-70),
+ char(0),
+ char(7),
+ char(0),
+ char(-69),
+ char(0),
+ char(7),
+ char(0),
+ char(-68),
+ char(0),
+ char(64),
+ char(0),
+ char(9),
+ char(0),
+ char(55),
+ char(0),
+ char(-97),
+ char(0),
+ char(17),
+ char(0),
+ char(-94),
+ char(0),
+ char(17),
+ char(0),
+ char(-93),
+ char(0),
+ char(7),
+ char(0),
+ char(-78),
+ char(0),
+ char(7),
+ char(0),
+ char(-77),
+ char(0),
+ char(7),
+ char(0),
+ char(-76),
+ char(0),
+ char(7),
+ char(0),
+ char(-75),
+ char(0),
+ char(4),
+ char(0),
+ char(-74),
+ char(0),
+ char(4),
+ char(0),
+ char(-73),
+ char(0),
+ char(49),
+ char(0),
+ char(22),
+ char(0),
+ char(8),
+ char(0),
+ char(-67),
+ char(0),
+ char(8),
+ char(0),
+ char(-79),
+ char(0),
+ char(8),
+ char(0),
+ char(110),
+ char(0),
+ char(8),
+ char(0),
+ char(-66),
+ char(0),
+ char(8),
+ char(0),
+ char(112),
+ char(0),
+ char(8),
+ char(0),
+ char(-65),
+ char(0),
+ char(8),
+ char(0),
+ char(-64),
+ char(0),
+ char(8),
+ char(0),
+ char(-63),
+ char(0),
+ char(8),
+ char(0),
+ char(-62),
+ char(0),
+ char(8),
+ char(0),
+ char(-61),
+ char(0),
+ char(8),
+ char(0),
+ char(-60),
+ char(0),
+ char(8),
+ char(0),
+ char(-59),
+ char(0),
+ char(8),
+ char(0),
+ char(-58),
+ char(0),
+ char(8),
+ char(0),
+ char(-57),
+ char(0),
+ char(8),
+ char(0),
+ char(-56),
+ char(0),
+ char(8),
+ char(0),
+ char(-55),
+ char(0),
+ char(4),
+ char(0),
+ char(-54),
+ char(0),
+ char(4),
+ char(0),
+ char(-53),
+ char(0),
+ char(4),
+ char(0),
+ char(-52),
+ char(0),
+ char(4),
+ char(0),
+ char(-51),
+ char(0),
+ char(4),
+ char(0),
+ char(-50),
+ char(0),
+ char(0),
+ char(0),
+ char(37),
+ char(0),
+ char(51),
+ char(0),
+ char(22),
+ char(0),
+ char(7),
+ char(0),
+ char(-67),
+ char(0),
+ char(7),
+ char(0),
+ char(-79),
+ char(0),
+ char(7),
+ char(0),
+ char(110),
+ char(0),
+ char(7),
+ char(0),
+ char(-66),
+ char(0),
+ char(7),
+ char(0),
+ char(112),
+ char(0),
+ char(7),
+ char(0),
+ char(-65),
+ char(0),
+ char(7),
+ char(0),
+ char(-64),
+ char(0),
+ char(7),
+ char(0),
+ char(-63),
+ char(0),
+ char(7),
+ char(0),
+ char(-62),
+ char(0),
+ char(7),
+ char(0),
+ char(-61),
+ char(0),
+ char(7),
+ char(0),
+ char(-60),
+ char(0),
+ char(7),
+ char(0),
+ char(-59),
+ char(0),
+ char(7),
+ char(0),
+ char(-58),
+ char(0),
+ char(7),
+ char(0),
+ char(-57),
+ char(0),
+ char(7),
+ char(0),
+ char(-56),
+ char(0),
+ char(7),
+ char(0),
+ char(-55),
+ char(0),
+ char(4),
+ char(0),
+ char(-54),
+ char(0),
+ char(4),
+ char(0),
+ char(-53),
+ char(0),
+ char(4),
+ char(0),
+ char(-52),
+ char(0),
+ char(4),
+ char(0),
+ char(-51),
+ char(0),
+ char(4),
+ char(0),
+ char(-50),
+ char(0),
+ char(0),
+ char(0),
+ char(37),
+ char(0),
+ char(65),
+ char(0),
+ char(4),
+ char(0),
+ char(7),
+ char(0),
+ char(-49),
+ char(0),
+ char(7),
+ char(0),
+ char(-48),
+ char(0),
+ char(7),
+ char(0),
+ char(-47),
+ char(0),
+ char(4),
+ char(0),
+ char(78),
+ char(0),
+ char(66),
+ char(0),
+ char(10),
+ char(0),
+ char(65),
+ char(0),
+ char(-46),
+ char(0),
+ char(13),
+ char(0),
+ char(-45),
+ char(0),
+ char(13),
+ char(0),
+ char(-44),
+ char(0),
+ char(13),
+ char(0),
+ char(-43),
+ char(0),
+ char(13),
+ char(0),
+ char(-42),
+ char(0),
+ char(13),
+ char(0),
+ char(-41),
+ char(0),
+ char(7),
+ char(0),
+ char(-121),
+ char(0),
+ char(7),
+ char(0),
+ char(-40),
+ char(0),
+ char(4),
+ char(0),
+ char(-39),
+ char(0),
+ char(4),
+ char(0),
+ char(53),
+ char(0),
+ char(67),
+ char(0),
+ char(4),
+ char(0),
+ char(65),
+ char(0),
+ char(-46),
+ char(0),
+ char(4),
+ char(0),
+ char(-38),
+ char(0),
+ char(7),
+ char(0),
+ char(-37),
+ char(0),
+ char(4),
+ char(0),
+ char(-36),
+ char(0),
+ char(68),
+ char(0),
+ char(4),
+ char(0),
+ char(13),
+ char(0),
+ char(-41),
+ char(0),
+ char(65),
+ char(0),
+ char(-46),
+ char(0),
+ char(4),
+ char(0),
+ char(-35),
+ char(0),
+ char(7),
+ char(0),
+ char(-34),
+ char(0),
+ char(69),
+ char(0),
+ char(7),
+ char(0),
+ char(13),
+ char(0),
+ char(-33),
+ char(0),
+ char(65),
+ char(0),
+ char(-46),
+ char(0),
+ char(4),
+ char(0),
+ char(-32),
+ char(0),
+ char(7),
+ char(0),
+ char(-31),
+ char(0),
+ char(7),
+ char(0),
+ char(-30),
+ char(0),
+ char(7),
+ char(0),
+ char(-29),
+ char(0),
+ char(4),
+ char(0),
+ char(53),
+ char(0),
+ char(70),
+ char(0),
+ char(6),
+ char(0),
+ char(15),
+ char(0),
+ char(-28),
+ char(0),
+ char(13),
+ char(0),
+ char(-30),
+ char(0),
+ char(13),
+ char(0),
+ char(-27),
+ char(0),
+ char(56),
+ char(0),
+ char(-26),
+ char(0),
+ char(4),
+ char(0),
+ char(-25),
+ char(0),
+ char(7),
+ char(0),
+ char(-29),
+ char(0),
+ char(71),
+ char(0),
+ char(26),
+ char(0),
+ char(4),
+ char(0),
+ char(-24),
+ char(0),
+ char(7),
+ char(0),
+ char(-23),
+ char(0),
+ char(7),
+ char(0),
+ char(-79),
+ char(0),
+ char(7),
+ char(0),
+ char(-22),
+ char(0),
+ char(7),
+ char(0),
+ char(-21),
+ char(0),
+ char(7),
+ char(0),
+ char(-20),
+ char(0),
+ char(7),
+ char(0),
+ char(-19),
+ char(0),
+ char(7),
+ char(0),
+ char(-18),
+ char(0),
+ char(7),
+ char(0),
+ char(-17),
+ char(0),
+ char(7),
+ char(0),
+ char(-16),
+ char(0),
+ char(7),
+ char(0),
+ char(-15),
+ char(0),
+ char(7),
+ char(0),
+ char(-14),
+ char(0),
+ char(7),
+ char(0),
+ char(-13),
+ char(0),
+ char(7),
+ char(0),
+ char(-12),
+ char(0),
+ char(7),
+ char(0),
+ char(-11),
+ char(0),
+ char(7),
+ char(0),
+ char(-10),
+ char(0),
+ char(7),
+ char(0),
+ char(-9),
+ char(0),
+ char(7),
+ char(0),
+ char(-8),
+ char(0),
+ char(7),
+ char(0),
+ char(-7),
+ char(0),
+ char(7),
+ char(0),
+ char(-6),
+ char(0),
+ char(7),
+ char(0),
+ char(-5),
+ char(0),
+ char(4),
+ char(0),
+ char(-4),
+ char(0),
+ char(4),
+ char(0),
+ char(-3),
+ char(0),
+ char(4),
+ char(0),
+ char(-2),
+ char(0),
+ char(4),
+ char(0),
+ char(-1),
+ char(0),
+ char(4),
+ char(0),
+ char(117),
+ char(0),
+ char(72),
+ char(0),
+ char(12),
+ char(0),
+ char(15),
+ char(0),
+ char(0),
+ char(1),
+ char(15),
+ char(0),
+ char(1),
+ char(1),
+ char(15),
+ char(0),
+ char(2),
+ char(1),
+ char(13),
+ char(0),
+ char(3),
+ char(1),
+ char(13),
+ char(0),
+ char(4),
+ char(1),
+ char(7),
+ char(0),
+ char(5),
+ char(1),
+ char(4),
+ char(0),
+ char(6),
+ char(1),
+ char(4),
+ char(0),
+ char(7),
+ char(1),
+ char(4),
+ char(0),
+ char(8),
+ char(1),
+ char(4),
+ char(0),
+ char(9),
+ char(1),
+ char(7),
+ char(0),
+ char(-31),
+ char(0),
+ char(4),
+ char(0),
+ char(53),
+ char(0),
+ char(73),
+ char(0),
+ char(27),
+ char(0),
+ char(17),
+ char(0),
+ char(10),
+ char(1),
+ char(15),
+ char(0),
+ char(11),
+ char(1),
+ char(15),
+ char(0),
+ char(12),
+ char(1),
+ char(13),
+ char(0),
+ char(3),
+ char(1),
+ char(13),
+ char(0),
+ char(13),
+ char(1),
+ char(13),
+ char(0),
+ char(14),
+ char(1),
+ char(13),
+ char(0),
+ char(15),
+ char(1),
+ char(13),
+ char(0),
+ char(16),
+ char(1),
+ char(13),
+ char(0),
+ char(17),
+ char(1),
+ char(4),
+ char(0),
+ char(18),
+ char(1),
+ char(7),
+ char(0),
+ char(19),
+ char(1),
+ char(4),
+ char(0),
+ char(20),
+ char(1),
+ char(4),
+ char(0),
+ char(21),
+ char(1),
+ char(4),
+ char(0),
+ char(22),
+ char(1),
+ char(7),
+ char(0),
+ char(23),
+ char(1),
+ char(7),
+ char(0),
+ char(24),
+ char(1),
+ char(4),
+ char(0),
+ char(25),
+ char(1),
+ char(4),
+ char(0),
+ char(26),
+ char(1),
+ char(7),
+ char(0),
+ char(27),
+ char(1),
+ char(7),
+ char(0),
+ char(28),
+ char(1),
+ char(7),
+ char(0),
+ char(29),
+ char(1),
+ char(7),
+ char(0),
+ char(30),
+ char(1),
+ char(7),
+ char(0),
+ char(31),
+ char(1),
+ char(7),
+ char(0),
+ char(32),
+ char(1),
+ char(4),
+ char(0),
+ char(33),
+ char(1),
+ char(4),
+ char(0),
+ char(34),
+ char(1),
+ char(4),
+ char(0),
+ char(35),
+ char(1),
+ char(74),
+ char(0),
+ char(12),
+ char(0),
+ char(9),
+ char(0),
+ char(36),
+ char(1),
+ char(9),
+ char(0),
+ char(37),
+ char(1),
+ char(13),
+ char(0),
+ char(38),
+ char(1),
+ char(7),
+ char(0),
+ char(39),
+ char(1),
+ char(7),
+ char(0),
+ char(-63),
+ char(0),
+ char(7),
+ char(0),
+ char(40),
+ char(1),
+ char(4),
+ char(0),
+ char(41),
+ char(1),
+ char(13),
+ char(0),
+ char(42),
+ char(1),
+ char(4),
+ char(0),
+ char(43),
+ char(1),
+ char(4),
+ char(0),
+ char(44),
+ char(1),
+ char(4),
+ char(0),
+ char(45),
+ char(1),
+ char(4),
+ char(0),
+ char(53),
+ char(0),
+ char(75),
+ char(0),
+ char(19),
+ char(0),
+ char(47),
+ char(0),
+ char(125),
+ char(0),
+ char(72),
+ char(0),
+ char(46),
+ char(1),
+ char(65),
+ char(0),
+ char(47),
+ char(1),
+ char(66),
+ char(0),
+ char(48),
+ char(1),
+ char(67),
+ char(0),
+ char(49),
+ char(1),
+ char(68),
+ char(0),
+ char(50),
+ char(1),
+ char(69),
+ char(0),
+ char(51),
+ char(1),
+ char(70),
+ char(0),
+ char(52),
+ char(1),
+ char(73),
+ char(0),
+ char(53),
+ char(1),
+ char(74),
+ char(0),
+ char(54),
+ char(1),
+ char(4),
+ char(0),
+ char(55),
+ char(1),
+ char(4),
+ char(0),
+ char(21),
+ char(1),
+ char(4),
+ char(0),
+ char(56),
+ char(1),
+ char(4),
+ char(0),
+ char(57),
+ char(1),
+ char(4),
+ char(0),
+ char(58),
+ char(1),
+ char(4),
+ char(0),
+ char(59),
+ char(1),
+ char(4),
+ char(0),
+ char(60),
+ char(1),
+ char(4),
+ char(0),
+ char(61),
+ char(1),
+ char(71),
+ char(0),
+ char(62),
+ char(1),
+};
+int b3s_bulletDNAlen64 = sizeof(b3s_bulletDNAstr64);
diff --git a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Serializer.h b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Serializer.h
index 1c1ce43764..d9e153e238 100644
--- a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Serializer.h
+++ b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Serializer.h
@@ -16,158 +16,142 @@ subject to the following restrictions:
#ifndef B3_SERIALIZER_H
#define B3_SERIALIZER_H
-#include "Bullet3Common/b3Scalar.h" // has definitions like B3_FORCE_INLINE
+#include "Bullet3Common/b3Scalar.h" // has definitions like B3_FORCE_INLINE
#include "Bullet3Common/b3StackAlloc.h"
#include "Bullet3Common/b3HashMap.h"
-#if !defined( __CELLOS_LV2__) && !defined(__MWERKS__)
+#if !defined(__CELLOS_LV2__) && !defined(__MWERKS__)
#include <memory.h>
#endif
#include <string.h>
-
-
extern char b3s_bulletDNAstr[];
extern int b3s_bulletDNAlen;
extern char b3s_bulletDNAstr64[];
extern int b3s_bulletDNAlen64;
-B3_FORCE_INLINE int b3StrLen(const char* str)
+B3_FORCE_INLINE int b3StrLen(const char* str)
{
- if (!str)
- return(0);
+ if (!str)
+ return (0);
int len = 0;
-
+
while (*str != 0)
{
- str++;
- len++;
- }
+ str++;
+ len++;
+ }
- return len;
+ return len;
}
-
class b3Chunk
{
public:
- int m_chunkCode;
- int m_length;
- void *m_oldPtr;
- int m_dna_nr;
- int m_number;
+ int m_chunkCode;
+ int m_length;
+ void* m_oldPtr;
+ int m_dna_nr;
+ int m_number;
};
-enum b3SerializationFlags
+enum b3SerializationFlags
{
B3_SERIALIZE_NO_BVH = 1,
B3_SERIALIZE_NO_TRIANGLEINFOMAP = 2,
B3_SERIALIZE_NO_DUPLICATE_ASSERT = 4
};
-class b3Serializer
+class b3Serializer
{
-
public:
-
virtual ~b3Serializer() {}
- virtual const unsigned char* getBufferPointer() const = 0;
-
- virtual int getCurrentBufferSize() const = 0;
+ virtual const unsigned char* getBufferPointer() const = 0;
- virtual b3Chunk* allocate(size_t size, int numElements) = 0;
+ virtual int getCurrentBufferSize() const = 0;
- virtual void finalizeChunk(b3Chunk* chunk, const char* structType, int chunkCode,void* oldPtr)= 0;
+ virtual b3Chunk* allocate(size_t size, int numElements) = 0;
- virtual void* findPointer(void* oldPtr) = 0;
+ virtual void finalizeChunk(b3Chunk* chunk, const char* structType, int chunkCode, void* oldPtr) = 0;
- virtual void* getUniquePointer(void*oldPtr) = 0;
+ virtual void* findPointer(void* oldPtr) = 0;
- virtual void startSerialization() = 0;
-
- virtual void finishSerialization() = 0;
+ virtual void* getUniquePointer(void* oldPtr) = 0;
- virtual const char* findNameForPointer(const void* ptr) const = 0;
+ virtual void startSerialization() = 0;
- virtual void registerNameForPointer(const void* ptr, const char* name) = 0;
+ virtual void finishSerialization() = 0;
- virtual void serializeName(const char* ptr) = 0;
+ virtual const char* findNameForPointer(const void* ptr) const = 0;
- virtual int getSerializationFlags() const = 0;
+ virtual void registerNameForPointer(const void* ptr, const char* name) = 0;
- virtual void setSerializationFlags(int flags) = 0;
+ virtual void serializeName(const char* ptr) = 0;
+ virtual int getSerializationFlags() const = 0;
+ virtual void setSerializationFlags(int flags) = 0;
};
-
-
#define B3_HEADER_LENGTH 12
-#if defined(__sgi) || defined (__sparc) || defined (__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__)
-# define B3_MAKE_ID(a,b,c,d) ( (int)(a)<<24 | (int)(b)<<16 | (c)<<8 | (d) )
+#if defined(__sgi) || defined(__sparc) || defined(__sparc__) || defined(__PPC__) || defined(__ppc__) || defined(__BIG_ENDIAN__)
+#define B3_MAKE_ID(a, b, c, d) ((int)(a) << 24 | (int)(b) << 16 | (c) << 8 | (d))
#else
-# define B3_MAKE_ID(a,b,c,d) ( (int)(d)<<24 | (int)(c)<<16 | (b)<<8 | (a) )
+#define B3_MAKE_ID(a, b, c, d) ((int)(d) << 24 | (int)(c) << 16 | (b) << 8 | (a))
#endif
-#define B3_SOFTBODY_CODE B3_MAKE_ID('S','B','D','Y')
-#define B3_COLLISIONOBJECT_CODE B3_MAKE_ID('C','O','B','J')
-#define B3_RIGIDBODY_CODE B3_MAKE_ID('R','B','D','Y')
-#define B3_CONSTRAINT_CODE B3_MAKE_ID('C','O','N','S')
-#define B3_BOXSHAPE_CODE B3_MAKE_ID('B','O','X','S')
-#define B3_QUANTIZED_BVH_CODE B3_MAKE_ID('Q','B','V','H')
-#define B3_TRIANLGE_INFO_MAP B3_MAKE_ID('T','M','A','P')
-#define B3_SHAPE_CODE B3_MAKE_ID('S','H','A','P')
-#define B3_ARRAY_CODE B3_MAKE_ID('A','R','A','Y')
-#define B3_SBMATERIAL_CODE B3_MAKE_ID('S','B','M','T')
-#define B3_SBNODE_CODE B3_MAKE_ID('S','B','N','D')
-#define B3_DYNAMICSWORLD_CODE B3_MAKE_ID('D','W','L','D')
-#define B3_DNA_CODE B3_MAKE_ID('D','N','A','1')
-
-
-struct b3PointerUid
+#define B3_SOFTBODY_CODE B3_MAKE_ID('S', 'B', 'D', 'Y')
+#define B3_COLLISIONOBJECT_CODE B3_MAKE_ID('C', 'O', 'B', 'J')
+#define B3_RIGIDBODY_CODE B3_MAKE_ID('R', 'B', 'D', 'Y')
+#define B3_CONSTRAINT_CODE B3_MAKE_ID('C', 'O', 'N', 'S')
+#define B3_BOXSHAPE_CODE B3_MAKE_ID('B', 'O', 'X', 'S')
+#define B3_QUANTIZED_BVH_CODE B3_MAKE_ID('Q', 'B', 'V', 'H')
+#define B3_TRIANLGE_INFO_MAP B3_MAKE_ID('T', 'M', 'A', 'P')
+#define B3_SHAPE_CODE B3_MAKE_ID('S', 'H', 'A', 'P')
+#define B3_ARRAY_CODE B3_MAKE_ID('A', 'R', 'A', 'Y')
+#define B3_SBMATERIAL_CODE B3_MAKE_ID('S', 'B', 'M', 'T')
+#define B3_SBNODE_CODE B3_MAKE_ID('S', 'B', 'N', 'D')
+#define B3_DYNAMICSWORLD_CODE B3_MAKE_ID('D', 'W', 'L', 'D')
+#define B3_DNA_CODE B3_MAKE_ID('D', 'N', 'A', '1')
+
+struct b3PointerUid
{
- union
- {
- void* m_ptr;
- int m_uniqueIds[2];
+ union {
+ void* m_ptr;
+ int m_uniqueIds[2];
};
};
///The b3DefaultSerializer is the main Bullet serialization class.
///The constructor takes an optional argument for backwards compatibility, it is recommended to leave this empty/zero.
-class b3DefaultSerializer : public b3Serializer
+class b3DefaultSerializer : public b3Serializer
{
+ b3AlignedObjectArray<char*> mTypes;
+ b3AlignedObjectArray<short*> mStructs;
+ b3AlignedObjectArray<short> mTlens;
+ b3HashMap<b3HashInt, int> mStructReverse;
+ b3HashMap<b3HashString, int> mTypeLookup;
+ b3HashMap<b3HashPtr, void*> m_chunkP;
- b3AlignedObjectArray<char*> mTypes;
- b3AlignedObjectArray<short*> mStructs;
- b3AlignedObjectArray<short> mTlens;
- b3HashMap<b3HashInt, int> mStructReverse;
- b3HashMap<b3HashString,int> mTypeLookup;
+ b3HashMap<b3HashPtr, const char*> m_nameMap;
-
- b3HashMap<b3HashPtr,void*> m_chunkP;
-
- b3HashMap<b3HashPtr,const char*> m_nameMap;
+ b3HashMap<b3HashPtr, b3PointerUid> m_uniquePointers;
+ int m_uniqueIdGenerator;
- b3HashMap<b3HashPtr,b3PointerUid> m_uniquePointers;
- int m_uniqueIdGenerator;
+ int m_totalSize;
+ unsigned char* m_buffer;
+ int m_currentSize;
+ void* m_dna;
+ int m_dnaLength;
- int m_totalSize;
- unsigned char* m_buffer;
- int m_currentSize;
- void* m_dna;
- int m_dnaLength;
+ int m_serializationFlags;
- int m_serializationFlags;
+ b3AlignedObjectArray<b3Chunk*> m_chunkPtrs;
-
- b3AlignedObjectArray<b3Chunk*> m_chunkPtrs;
-
protected:
-
- virtual void* findPointer(void* oldPtr)
+ virtual void* findPointer(void* oldPtr)
{
void** ptr = m_chunkP.find(oldPtr);
if (ptr && *ptr)
@@ -175,48 +159,43 @@ protected:
return 0;
}
-
-
-
-
- void writeDNA()
- {
- b3Chunk* dnaChunk = allocate(m_dnaLength,1);
- memcpy(dnaChunk->m_oldPtr,m_dna,m_dnaLength);
- finalizeChunk(dnaChunk,"DNA1",B3_DNA_CODE, m_dna);
- }
+ void writeDNA()
+ {
+ b3Chunk* dnaChunk = allocate(m_dnaLength, 1);
+ memcpy(dnaChunk->m_oldPtr, m_dna, m_dnaLength);
+ finalizeChunk(dnaChunk, "DNA1", B3_DNA_CODE, m_dna);
+ }
- int getReverseType(const char *type) const
- {
+ int getReverseType(const char* type) const
+ {
+ b3HashString key(type);
+ const int* valuePtr = mTypeLookup.find(key);
+ if (valuePtr)
+ return *valuePtr;
- b3HashString key(type);
- const int* valuePtr = mTypeLookup.find(key);
- if (valuePtr)
- return *valuePtr;
-
- return -1;
- }
+ return -1;
+ }
- void initDNA(const char* bdnaOrg,int dnalen)
- {
- ///was already initialized
- if (m_dna)
- return;
+ void initDNA(const char* bdnaOrg, int dnalen)
+ {
+ ///was already initialized
+ if (m_dna)
+ return;
- int littleEndian= 1;
- littleEndian= ((char*)&littleEndian)[0];
-
+ int littleEndian = 1;
+ littleEndian = ((char*)&littleEndian)[0];
- m_dna = b3AlignedAlloc(dnalen,16);
- memcpy(m_dna,bdnaOrg,dnalen);
- m_dnaLength = dnalen;
+ m_dna = b3AlignedAlloc(dnalen, 16);
+ memcpy(m_dna, bdnaOrg, dnalen);
+ m_dnaLength = dnalen;
- int *intPtr=0;
- short *shtPtr=0;
- char *cp = 0;int dataLen =0;
- intPtr = (int*)m_dna;
+ int* intPtr = 0;
+ short* shtPtr = 0;
+ char* cp = 0;
+ int dataLen = 0;
+ intPtr = (int*)m_dna;
- /*
+ /*
SDNA (4 bytes) (magic number)
NAME (4 bytes)
<nr> (4 bytes) amount of names (int)
@@ -224,81 +203,81 @@ protected:
<string>
*/
- if (strncmp((const char*)m_dna, "SDNA", 4)==0)
- {
- // skip ++ NAME
- intPtr++; intPtr++;
- }
-
- // Parse names
- if (!littleEndian)
- *intPtr = b3SwapEndian(*intPtr);
-
- dataLen = *intPtr;
-
+ if (strncmp((const char*)m_dna, "SDNA", 4) == 0)
+ {
+ // skip ++ NAME
+ intPtr++;
intPtr++;
+ }
- cp = (char*)intPtr;
- int i;
- for ( i=0; i<dataLen; i++)
- {
-
- while (*cp)cp++;
- cp++;
- }
- cp = b3AlignPointer(cp,4);
+ // Parse names
+ if (!littleEndian)
+ *intPtr = b3SwapEndian(*intPtr);
- /*
+ dataLen = *intPtr;
+
+ intPtr++;
+
+ cp = (char*)intPtr;
+ int i;
+ for (i = 0; i < dataLen; i++)
+ {
+ while (*cp) cp++;
+ cp++;
+ }
+ cp = b3AlignPointer(cp, 4);
+
+ /*
TYPE (4 bytes)
<nr> amount of types (int)
<string>
<string>
*/
- intPtr = (int*)cp;
- b3Assert(strncmp(cp, "TYPE", 4)==0); intPtr++;
+ intPtr = (int*)cp;
+ b3Assert(strncmp(cp, "TYPE", 4) == 0);
+ intPtr++;
- if (!littleEndian)
- *intPtr = b3SwapEndian(*intPtr);
-
- dataLen = *intPtr;
- intPtr++;
+ if (!littleEndian)
+ *intPtr = b3SwapEndian(*intPtr);
-
- cp = (char*)intPtr;
- for (i=0; i<dataLen; i++)
- {
- mTypes.push_back(cp);
- while (*cp)cp++;
- cp++;
- }
+ dataLen = *intPtr;
+ intPtr++;
- cp = b3AlignPointer(cp,4);
+ cp = (char*)intPtr;
+ for (i = 0; i < dataLen; i++)
+ {
+ mTypes.push_back(cp);
+ while (*cp) cp++;
+ cp++;
+ }
+ cp = b3AlignPointer(cp, 4);
- /*
+ /*
TLEN (4 bytes)
<len> (short) the lengths of types
<len>
*/
- // Parse type lens
- intPtr = (int*)cp;
- b3Assert(strncmp(cp, "TLEN", 4)==0); intPtr++;
+ // Parse type lens
+ intPtr = (int*)cp;
+ b3Assert(strncmp(cp, "TLEN", 4) == 0);
+ intPtr++;
- dataLen = (int)mTypes.size();
+ dataLen = (int)mTypes.size();
- shtPtr = (short*)intPtr;
- for (i=0; i<dataLen; i++, shtPtr++)
- {
- if (!littleEndian)
- shtPtr[0] = b3SwapEndian(shtPtr[0]);
- mTlens.push_back(shtPtr[0]);
- }
+ shtPtr = (short*)intPtr;
+ for (i = 0; i < dataLen; i++, shtPtr++)
+ {
+ if (!littleEndian)
+ shtPtr[0] = b3SwapEndian(shtPtr[0]);
+ mTlens.push_back(shtPtr[0]);
+ }
- if (dataLen & 1) shtPtr++;
+ if (dataLen & 1) shtPtr++;
- /*
+ /*
STRC (4 bytes)
<nr> amount of structs (int)
<typenr>
@@ -309,331 +288,314 @@ protected:
<namenr>
*/
- intPtr = (int*)shtPtr;
- cp = (char*)intPtr;
- b3Assert(strncmp(cp, "STRC", 4)==0); intPtr++;
+ intPtr = (int*)shtPtr;
+ cp = (char*)intPtr;
+ b3Assert(strncmp(cp, "STRC", 4) == 0);
+ intPtr++;
- if (!littleEndian)
- *intPtr = b3SwapEndian(*intPtr);
- dataLen = *intPtr ;
- intPtr++;
+ if (!littleEndian)
+ *intPtr = b3SwapEndian(*intPtr);
+ dataLen = *intPtr;
+ intPtr++;
+ shtPtr = (short*)intPtr;
+ for (i = 0; i < dataLen; i++)
+ {
+ mStructs.push_back(shtPtr);
- shtPtr = (short*)intPtr;
- for (i=0; i<dataLen; i++)
+ if (!littleEndian)
{
- mStructs.push_back (shtPtr);
-
- if (!littleEndian)
- {
- shtPtr[0]= b3SwapEndian(shtPtr[0]);
- shtPtr[1]= b3SwapEndian(shtPtr[1]);
+ shtPtr[0] = b3SwapEndian(shtPtr[0]);
+ shtPtr[1] = b3SwapEndian(shtPtr[1]);
- int len = shtPtr[1];
- shtPtr+= 2;
+ int len = shtPtr[1];
+ shtPtr += 2;
- for (int a=0; a<len; a++, shtPtr+=2)
- {
- shtPtr[0]= b3SwapEndian(shtPtr[0]);
- shtPtr[1]= b3SwapEndian(shtPtr[1]);
- }
-
- } else
+ for (int a = 0; a < len; a++, shtPtr += 2)
{
- shtPtr+= (2*shtPtr[1])+2;
+ shtPtr[0] = b3SwapEndian(shtPtr[0]);
+ shtPtr[1] = b3SwapEndian(shtPtr[1]);
}
}
-
- // build reverse lookups
- for (i=0; i<(int)mStructs.size(); i++)
+ else
{
- short *strc = mStructs.at(i);
- mStructReverse.insert(strc[0], i);
- mTypeLookup.insert(b3HashString(mTypes[strc[0]]),i);
+ shtPtr += (2 * shtPtr[1]) + 2;
}
}
-public:
-
+ // build reverse lookups
+ for (i = 0; i < (int)mStructs.size(); i++)
+ {
+ short* strc = mStructs.at(i);
+ mStructReverse.insert(strc[0], i);
+ mTypeLookup.insert(b3HashString(mTypes[strc[0]]), i);
+ }
+ }
-
+public:
+ b3DefaultSerializer(int totalSize = 0)
+ : m_totalSize(totalSize),
+ m_currentSize(0),
+ m_dna(0),
+ m_dnaLength(0),
+ m_serializationFlags(0)
+ {
+ m_buffer = m_totalSize ? (unsigned char*)b3AlignedAlloc(totalSize, 16) : 0;
- b3DefaultSerializer(int totalSize=0)
- :m_totalSize(totalSize),
- m_currentSize(0),
- m_dna(0),
- m_dnaLength(0),
- m_serializationFlags(0)
- {
- m_buffer = m_totalSize?(unsigned char*)b3AlignedAlloc(totalSize,16):0;
-
- const bool VOID_IS_8 = ((sizeof(void*)==8));
+ const bool VOID_IS_8 = ((sizeof(void*) == 8));
#ifdef B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
- if (VOID_IS_8)
- {
+ if (VOID_IS_8)
+ {
#if _WIN64
- initDNA((const char*)b3s_bulletDNAstr64,b3s_bulletDNAlen64);
+ initDNA((const char*)b3s_bulletDNAstr64, b3s_bulletDNAlen64);
#else
- b3Assert(0);
+ b3Assert(0);
#endif
- } else
- {
+ }
+ else
+ {
#ifndef _WIN64
- initDNA((const char*)b3s_bulletDNAstr,b3s_bulletDNAlen);
+ initDNA((const char*)b3s_bulletDNAstr, b3s_bulletDNAlen);
#else
- b3Assert(0);
+ b3Assert(0);
#endif
- }
-
-#else //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
- if (VOID_IS_8)
- {
- initDNA((const char*)b3s_bulletDNAstr64,b3s_bulletDNAlen64);
- } else
- {
- initDNA((const char*)b3s_bulletDNAstr,b3s_bulletDNAlen);
- }
-#endif //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
-
}
- virtual ~b3DefaultSerializer()
+#else //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+ if (VOID_IS_8)
{
- if (m_buffer)
- b3AlignedFree(m_buffer);
- if (m_dna)
- b3AlignedFree(m_dna);
+ initDNA((const char*)b3s_bulletDNAstr64, b3s_bulletDNAlen64);
}
-
- void writeHeader(unsigned char* buffer) const
+ else
{
-
+ initDNA((const char*)b3s_bulletDNAstr, b3s_bulletDNAlen);
+ }
+#endif //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+ }
-#ifdef B3_USE_DOUBLE_PRECISION
- memcpy(buffer, "BULLETd", 7);
+ virtual ~b3DefaultSerializer()
+ {
+ if (m_buffer)
+ b3AlignedFree(m_buffer);
+ if (m_dna)
+ b3AlignedFree(m_dna);
+ }
+
+ void writeHeader(unsigned char* buffer) const
+ {
+#ifdef B3_USE_DOUBLE_PRECISION
+ memcpy(buffer, "BULLETd", 7);
#else
- memcpy(buffer, "BULLETf", 7);
-#endif //B3_USE_DOUBLE_PRECISION
-
- int littleEndian= 1;
- littleEndian= ((char*)&littleEndian)[0];
+ memcpy(buffer, "BULLETf", 7);
+#endif //B3_USE_DOUBLE_PRECISION
- if (sizeof(void*)==8)
- {
- buffer[7] = '-';
- } else
- {
- buffer[7] = '_';
- }
+ int littleEndian = 1;
+ littleEndian = ((char*)&littleEndian)[0];
- if (littleEndian)
- {
- buffer[8]='v';
- } else
- {
- buffer[8]='V';
- }
+ if (sizeof(void*) == 8)
+ {
+ buffer[7] = '-';
+ }
+ else
+ {
+ buffer[7] = '_';
+ }
+ if (littleEndian)
+ {
+ buffer[8] = 'v';
+ }
+ else
+ {
+ buffer[8] = 'V';
+ }
- buffer[9] = '2';
- buffer[10] = '8';
- buffer[11] = '1';
+ buffer[9] = '2';
+ buffer[10] = '8';
+ buffer[11] = '1';
+ }
+ virtual void startSerialization()
+ {
+ m_uniqueIdGenerator = 1;
+ if (m_totalSize)
+ {
+ unsigned char* buffer = internalAlloc(B3_HEADER_LENGTH);
+ writeHeader(buffer);
}
+ }
+
+ virtual void finishSerialization()
+ {
+ writeDNA();
- virtual void startSerialization()
+ //if we didn't pre-allocate a buffer, we need to create a contiguous buffer now
+ int mysize = 0;
+ if (!m_totalSize)
{
- m_uniqueIdGenerator= 1;
- if (m_totalSize)
+ if (m_buffer)
+ b3AlignedFree(m_buffer);
+
+ m_currentSize += B3_HEADER_LENGTH;
+ m_buffer = (unsigned char*)b3AlignedAlloc(m_currentSize, 16);
+
+ unsigned char* currentPtr = m_buffer;
+ writeHeader(m_buffer);
+ currentPtr += B3_HEADER_LENGTH;
+ mysize += B3_HEADER_LENGTH;
+ for (int i = 0; i < m_chunkPtrs.size(); i++)
{
- unsigned char* buffer = internalAlloc(B3_HEADER_LENGTH);
- writeHeader(buffer);
+ int curLength = sizeof(b3Chunk) + m_chunkPtrs[i]->m_length;
+ memcpy(currentPtr, m_chunkPtrs[i], curLength);
+ b3AlignedFree(m_chunkPtrs[i]);
+ currentPtr += curLength;
+ mysize += curLength;
}
-
}
- virtual void finishSerialization()
+ mTypes.clear();
+ mStructs.clear();
+ mTlens.clear();
+ mStructReverse.clear();
+ mTypeLookup.clear();
+ m_chunkP.clear();
+ m_nameMap.clear();
+ m_uniquePointers.clear();
+ m_chunkPtrs.clear();
+ }
+
+ virtual void* getUniquePointer(void* oldPtr)
+ {
+ if (!oldPtr)
+ return 0;
+
+ b3PointerUid* uptr = (b3PointerUid*)m_uniquePointers.find(oldPtr);
+ if (uptr)
{
- writeDNA();
+ return uptr->m_ptr;
+ }
+ m_uniqueIdGenerator++;
- //if we didn't pre-allocate a buffer, we need to create a contiguous buffer now
- int mysize = 0;
- if (!m_totalSize)
- {
- if (m_buffer)
- b3AlignedFree(m_buffer);
+ b3PointerUid uid;
+ uid.m_uniqueIds[0] = m_uniqueIdGenerator;
+ uid.m_uniqueIds[1] = m_uniqueIdGenerator;
+ m_uniquePointers.insert(oldPtr, uid);
+ return uid.m_ptr;
+ }
- m_currentSize += B3_HEADER_LENGTH;
- m_buffer = (unsigned char*)b3AlignedAlloc(m_currentSize,16);
+ virtual const unsigned char* getBufferPointer() const
+ {
+ return m_buffer;
+ }
- unsigned char* currentPtr = m_buffer;
- writeHeader(m_buffer);
- currentPtr += B3_HEADER_LENGTH;
- mysize+=B3_HEADER_LENGTH;
- for (int i=0;i< m_chunkPtrs.size();i++)
- {
- int curLength = sizeof(b3Chunk)+m_chunkPtrs[i]->m_length;
- memcpy(currentPtr,m_chunkPtrs[i], curLength);
- b3AlignedFree(m_chunkPtrs[i]);
- currentPtr+=curLength;
- mysize+=curLength;
- }
- }
+ virtual int getCurrentBufferSize() const
+ {
+ return m_currentSize;
+ }
- mTypes.clear();
- mStructs.clear();
- mTlens.clear();
- mStructReverse.clear();
- mTypeLookup.clear();
- m_chunkP.clear();
- m_nameMap.clear();
- m_uniquePointers.clear();
- m_chunkPtrs.clear();
+ virtual void finalizeChunk(b3Chunk* chunk, const char* structType, int chunkCode, void* oldPtr)
+ {
+ if (!(m_serializationFlags & B3_SERIALIZE_NO_DUPLICATE_ASSERT))
+ {
+ b3Assert(!findPointer(oldPtr));
}
- virtual void* getUniquePointer(void*oldPtr)
- {
- if (!oldPtr)
- return 0;
+ chunk->m_dna_nr = getReverseType(structType);
- b3PointerUid* uptr = (b3PointerUid*)m_uniquePointers.find(oldPtr);
- if (uptr)
- {
- return uptr->m_ptr;
- }
- m_uniqueIdGenerator++;
-
- b3PointerUid uid;
- uid.m_uniqueIds[0] = m_uniqueIdGenerator;
- uid.m_uniqueIds[1] = m_uniqueIdGenerator;
- m_uniquePointers.insert(oldPtr,uid);
- return uid.m_ptr;
+ chunk->m_chunkCode = chunkCode;
- }
+ void* uniquePtr = getUniquePointer(oldPtr);
- virtual const unsigned char* getBufferPointer() const
- {
- return m_buffer;
- }
+ m_chunkP.insert(oldPtr, uniquePtr); //chunk->m_oldPtr);
+ chunk->m_oldPtr = uniquePtr; //oldPtr;
+ }
- virtual int getCurrentBufferSize() const
- {
- return m_currentSize;
- }
+ virtual unsigned char* internalAlloc(size_t size)
+ {
+ unsigned char* ptr = 0;
- virtual void finalizeChunk(b3Chunk* chunk, const char* structType, int chunkCode,void* oldPtr)
+ if (m_totalSize)
{
- if (!(m_serializationFlags&B3_SERIALIZE_NO_DUPLICATE_ASSERT))
- {
- b3Assert(!findPointer(oldPtr));
- }
-
- chunk->m_dna_nr = getReverseType(structType);
-
- chunk->m_chunkCode = chunkCode;
-
- void* uniquePtr = getUniquePointer(oldPtr);
-
- m_chunkP.insert(oldPtr,uniquePtr);//chunk->m_oldPtr);
- chunk->m_oldPtr = uniquePtr;//oldPtr;
-
+ ptr = m_buffer + m_currentSize;
+ m_currentSize += int(size);
+ b3Assert(m_currentSize < m_totalSize);
}
-
-
- virtual unsigned char* internalAlloc(size_t size)
+ else
{
- unsigned char* ptr = 0;
-
- if (m_totalSize)
- {
- ptr = m_buffer+m_currentSize;
- m_currentSize += int(size);
- b3Assert(m_currentSize<m_totalSize);
- } else
- {
- ptr = (unsigned char*)b3AlignedAlloc(size,16);
- m_currentSize += int(size);
- }
- return ptr;
+ ptr = (unsigned char*)b3AlignedAlloc(size, 16);
+ m_currentSize += int(size);
}
+ return ptr;
+ }
-
+ virtual b3Chunk* allocate(size_t size, int numElements)
+ {
+ unsigned char* ptr = internalAlloc(int(size) * numElements + sizeof(b3Chunk));
- virtual b3Chunk* allocate(size_t size, int numElements)
- {
+ unsigned char* data = ptr + sizeof(b3Chunk);
- unsigned char* ptr = internalAlloc(int(size)*numElements+sizeof(b3Chunk));
+ b3Chunk* chunk = (b3Chunk*)ptr;
+ chunk->m_chunkCode = 0;
+ chunk->m_oldPtr = data;
+ chunk->m_length = int(size) * numElements;
+ chunk->m_number = numElements;
- unsigned char* data = ptr + sizeof(b3Chunk);
-
- b3Chunk* chunk = (b3Chunk*)ptr;
- chunk->m_chunkCode = 0;
- chunk->m_oldPtr = data;
- chunk->m_length = int(size)*numElements;
- chunk->m_number = numElements;
-
- m_chunkPtrs.push_back(chunk);
-
+ m_chunkPtrs.push_back(chunk);
- return chunk;
- }
+ return chunk;
+ }
- virtual const char* findNameForPointer(const void* ptr) const
- {
- const char*const * namePtr = m_nameMap.find(ptr);
- if (namePtr && *namePtr)
- return *namePtr;
- return 0;
+ virtual const char* findNameForPointer(const void* ptr) const
+ {
+ const char* const* namePtr = m_nameMap.find(ptr);
+ if (namePtr && *namePtr)
+ return *namePtr;
+ return 0;
+ }
- }
+ virtual void registerNameForPointer(const void* ptr, const char* name)
+ {
+ m_nameMap.insert(ptr, name);
+ }
- virtual void registerNameForPointer(const void* ptr, const char* name)
+ virtual void serializeName(const char* name)
+ {
+ if (name)
{
- m_nameMap.insert(ptr,name);
- }
+ //don't serialize name twice
+ if (findPointer((void*)name))
+ return;
- virtual void serializeName(const char* name)
- {
- if (name)
+ int len = b3StrLen(name);
+ if (len)
{
- //don't serialize name twice
- if (findPointer((void*)name))
- return;
-
- int len = b3StrLen(name);
- if (len)
+ int newLen = len + 1;
+ int padding = ((newLen + 3) & ~3) - newLen;
+ newLen += padding;
+
+ //serialize name string now
+ b3Chunk* chunk = allocate(sizeof(char), newLen);
+ char* destinationName = (char*)chunk->m_oldPtr;
+ for (int i = 0; i < len; i++)
{
-
- int newLen = len+1;
- int padding = ((newLen+3)&~3)-newLen;
- newLen += padding;
-
- //serialize name string now
- b3Chunk* chunk = allocate(sizeof(char),newLen);
- char* destinationName = (char*)chunk->m_oldPtr;
- for (int i=0;i<len;i++)
- {
- destinationName[i] = name[i];
- }
- destinationName[len] = 0;
- finalizeChunk(chunk,"char",B3_ARRAY_CODE,(void*)name);
+ destinationName[i] = name[i];
}
+ destinationName[len] = 0;
+ finalizeChunk(chunk, "char", B3_ARRAY_CODE, (void*)name);
}
}
+ }
- virtual int getSerializationFlags() const
- {
- return m_serializationFlags;
- }
-
- virtual void setSerializationFlags(int flags)
- {
- m_serializationFlags = flags;
- }
+ virtual int getSerializationFlags() const
+ {
+ return m_serializationFlags;
+ }
+ virtual void setSerializationFlags(int flags)
+ {
+ m_serializationFlags = flags;
+ }
};
-
-#endif //B3_SERIALIZER_H
-
+#endif //B3_SERIALIZER_H
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp
index 77763305b1..ec6fe9f4d8 100644
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp
+++ b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp
@@ -2,7 +2,6 @@
//Bullet Continuous Collision Detection and Physics Library
//Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
//
// btAxisSweep3
//
@@ -19,18 +18,15 @@
// 3. This notice may not be removed or altered from any source distribution.
#include "btAxisSweep3.h"
-
-btAxisSweep3::btAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned short int maxHandles, btOverlappingPairCache* pairCache, bool disableRaycastAccelerator)
-:btAxisSweep3Internal<unsigned short int>(worldAabbMin,worldAabbMax,0xfffe,0xffff,maxHandles,pairCache,disableRaycastAccelerator)
+btAxisSweep3::btAxisSweep3(const btVector3& worldAabbMin, const btVector3& worldAabbMax, unsigned short int maxHandles, btOverlappingPairCache* pairCache, bool disableRaycastAccelerator)
+ : btAxisSweep3Internal<unsigned short int>(worldAabbMin, worldAabbMax, 0xfffe, 0xffff, maxHandles, pairCache, disableRaycastAccelerator)
{
// 1 handle is reserved as sentinel
btAssert(maxHandles > 1 && maxHandles < 32767);
-
}
-
-bt32BitAxisSweep3::bt32BitAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned int maxHandles , btOverlappingPairCache* pairCache , bool disableRaycastAccelerator)
-:btAxisSweep3Internal<unsigned int>(worldAabbMin,worldAabbMax,0xfffffffe,0x7fffffff,maxHandles,pairCache,disableRaycastAccelerator)
+bt32BitAxisSweep3::bt32BitAxisSweep3(const btVector3& worldAabbMin, const btVector3& worldAabbMax, unsigned int maxHandles, btOverlappingPairCache* pairCache, bool disableRaycastAccelerator)
+ : btAxisSweep3Internal<unsigned int>(worldAabbMin, worldAabbMax, 0xfffffffe, 0x7fffffff, maxHandles, pairCache, disableRaycastAccelerator)
{
// 1 handle is reserved as sentinel
btAssert(maxHandles > 1 && maxHandles < 2147483647);
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3.h b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3.h
index a3648df1af..1e42f25f3b 100644
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3.h
+++ b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3.h
@@ -33,9 +33,7 @@
class btAxisSweep3 : public btAxisSweep3Internal<unsigned short int>
{
public:
-
- btAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned short int maxHandles = 16384, btOverlappingPairCache* pairCache = 0, bool disableRaycastAccelerator = false);
-
+ btAxisSweep3(const btVector3& worldAabbMin, const btVector3& worldAabbMax, unsigned short int maxHandles = 16384, btOverlappingPairCache* pairCache = 0, bool disableRaycastAccelerator = false);
};
/// The bt32BitAxisSweep3 allows higher precision quantization and more objects compared to the btAxisSweep3 sweep and prune.
@@ -44,9 +42,7 @@ public:
class bt32BitAxisSweep3 : public btAxisSweep3Internal<unsigned int>
{
public:
-
- bt32BitAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned int maxHandles = 1500000, btOverlappingPairCache* pairCache = 0, bool disableRaycastAccelerator = false);
-
+ bt32BitAxisSweep3(const btVector3& worldAabbMin, const btVector3& worldAabbMax, unsigned int maxHandles = 1500000, btOverlappingPairCache* pairCache = 0, bool disableRaycastAccelerator = false);
};
#endif
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3Internal.h b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3Internal.h
index 323aa96dca..2ee35528fd 100644
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3Internal.h
+++ b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3Internal.h
@@ -36,172 +36,158 @@ template <typename BP_FP_INT_TYPE>
class btAxisSweep3Internal : public btBroadphaseInterface
{
protected:
-
- BP_FP_INT_TYPE m_bpHandleMask;
- BP_FP_INT_TYPE m_handleSentinel;
+ BP_FP_INT_TYPE m_bpHandleMask;
+ BP_FP_INT_TYPE m_handleSentinel;
public:
-
- BT_DECLARE_ALIGNED_ALLOCATOR();
+ BT_DECLARE_ALIGNED_ALLOCATOR();
class Edge
{
public:
- BP_FP_INT_TYPE m_pos; // low bit is min/max
+ BP_FP_INT_TYPE m_pos; // low bit is min/max
BP_FP_INT_TYPE m_handle;
- BP_FP_INT_TYPE IsMax() const {return static_cast<BP_FP_INT_TYPE>(m_pos & 1);}
+ BP_FP_INT_TYPE IsMax() const { return static_cast<BP_FP_INT_TYPE>(m_pos & 1); }
};
public:
- class Handle : public btBroadphaseProxy
+ class Handle : public btBroadphaseProxy
{
public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
// indexes into the edge arrays
- BP_FP_INT_TYPE m_minEdges[3], m_maxEdges[3]; // 6 * 2 = 12
-// BP_FP_INT_TYPE m_uniqueId;
- btBroadphaseProxy* m_dbvtProxy;//for faster raycast
+ BP_FP_INT_TYPE m_minEdges[3], m_maxEdges[3]; // 6 * 2 = 12
+ // BP_FP_INT_TYPE m_uniqueId;
+ btBroadphaseProxy* m_dbvtProxy; //for faster raycast
//void* m_pOwner; this is now in btBroadphaseProxy.m_clientObject
-
- SIMD_FORCE_INLINE void SetNextFree(BP_FP_INT_TYPE next) {m_minEdges[0] = next;}
- SIMD_FORCE_INLINE BP_FP_INT_TYPE GetNextFree() const {return m_minEdges[0];}
- }; // 24 bytes + 24 for Edge structures = 44 bytes total per entry
-
+ SIMD_FORCE_INLINE void SetNextFree(BP_FP_INT_TYPE next) { m_minEdges[0] = next; }
+ SIMD_FORCE_INLINE BP_FP_INT_TYPE GetNextFree() const { return m_minEdges[0]; }
+ }; // 24 bytes + 24 for Edge structures = 44 bytes total per entry
+
protected:
- btVector3 m_worldAabbMin; // overall system bounds
- btVector3 m_worldAabbMax; // overall system bounds
+ btVector3 m_worldAabbMin; // overall system bounds
+ btVector3 m_worldAabbMax; // overall system bounds
+
+ btVector3 m_quantize; // scaling factor for quantization
- btVector3 m_quantize; // scaling factor for quantization
+ BP_FP_INT_TYPE m_numHandles; // number of active handles
+ BP_FP_INT_TYPE m_maxHandles; // max number of handles
+ Handle* m_pHandles; // handles pool
- BP_FP_INT_TYPE m_numHandles; // number of active handles
- BP_FP_INT_TYPE m_maxHandles; // max number of handles
- Handle* m_pHandles; // handles pool
-
- BP_FP_INT_TYPE m_firstFreeHandle; // free handles list
+ BP_FP_INT_TYPE m_firstFreeHandle; // free handles list
- Edge* m_pEdges[3]; // edge arrays for the 3 axes (each array has m_maxHandles * 2 + 2 sentinel entries)
+ Edge* m_pEdges[3]; // edge arrays for the 3 axes (each array has m_maxHandles * 2 + 2 sentinel entries)
void* m_pEdgesRawPtr[3];
btOverlappingPairCache* m_pairCache;
///btOverlappingPairCallback is an additional optional user callback for adding/removing overlapping pairs, similar interface to btOverlappingPairCache.
btOverlappingPairCallback* m_userPairCallback;
-
- bool m_ownsPairCache;
- int m_invalidPair;
+ bool m_ownsPairCache;
+
+ int m_invalidPair;
///additional dynamic aabb structure, used to accelerate ray cast queries.
///can be disabled using a optional argument in the constructor
- btDbvtBroadphase* m_raycastAccelerator;
- btOverlappingPairCache* m_nullPairCache;
-
+ btDbvtBroadphase* m_raycastAccelerator;
+ btOverlappingPairCache* m_nullPairCache;
// allocation/deallocation
BP_FP_INT_TYPE allocHandle();
void freeHandle(BP_FP_INT_TYPE handle);
-
- bool testOverlap2D(const Handle* pHandleA, const Handle* pHandleB,int axis0,int axis1);
+ bool testOverlap2D(const Handle* pHandleA, const Handle* pHandleB, int axis0, int axis1);
#ifdef DEBUG_BROADPHASE
- void debugPrintAxis(int axis,bool checkCardinality=true);
-#endif //DEBUG_BROADPHASE
+ void debugPrintAxis(int axis, bool checkCardinality = true);
+#endif //DEBUG_BROADPHASE
//Overlap* AddOverlap(BP_FP_INT_TYPE handleA, BP_FP_INT_TYPE handleB);
//void RemoveOverlap(BP_FP_INT_TYPE handleA, BP_FP_INT_TYPE handleB);
-
-
- void sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
- void sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
- void sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
- void sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
+ void sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps);
+ void sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps);
+ void sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps);
+ void sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps);
public:
+ btAxisSweep3Internal(const btVector3& worldAabbMin, const btVector3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel, BP_FP_INT_TYPE maxHandles = 16384, btOverlappingPairCache* pairCache = 0, bool disableRaycastAccelerator = false);
- btAxisSweep3Internal(const btVector3& worldAabbMin,const btVector3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel, BP_FP_INT_TYPE maxHandles = 16384, btOverlappingPairCache* pairCache=0,bool disableRaycastAccelerator = false);
-
- virtual ~btAxisSweep3Internal();
+ virtual ~btAxisSweep3Internal();
BP_FP_INT_TYPE getNumHandles() const
{
return m_numHandles;
}
- virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
-
- BP_FP_INT_TYPE addHandle(const btVector3& aabbMin,const btVector3& aabbMax, void* pOwner, int collisionFilterGroup, int collisionFilterMask,btDispatcher* dispatcher);
- void removeHandle(BP_FP_INT_TYPE handle,btDispatcher* dispatcher);
- void updateHandle(BP_FP_INT_TYPE handle, const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher);
- SIMD_FORCE_INLINE Handle* getHandle(BP_FP_INT_TYPE index) const {return m_pHandles + index;}
+ virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
+
+ BP_FP_INT_TYPE addHandle(const btVector3& aabbMin, const btVector3& aabbMax, void* pOwner, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher);
+ void removeHandle(BP_FP_INT_TYPE handle, btDispatcher* dispatcher);
+ void updateHandle(BP_FP_INT_TYPE handle, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* dispatcher);
+ SIMD_FORCE_INLINE Handle* getHandle(BP_FP_INT_TYPE index) const { return m_pHandles + index; }
virtual void resetPool(btDispatcher* dispatcher);
- void processAllOverlappingPairs(btOverlapCallback* callback);
+ void processAllOverlappingPairs(btOverlapCallback* callback);
//Broadphase Interface
- virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr , int collisionFilterGroup, int collisionFilterMask,btDispatcher* dispatcher);
- virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
- virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher);
- virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
-
- virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0), const btVector3& aabbMax = btVector3(0,0,0));
- virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback);
-
-
+ virtual btBroadphaseProxy* createProxy(const btVector3& aabbMin, const btVector3& aabbMax, int shapeType, void* userPtr, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher);
+ virtual void destroyProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher);
+ virtual void setAabb(btBroadphaseProxy* proxy, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* dispatcher);
+ virtual void getAabb(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const;
+
+ virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin = btVector3(0, 0, 0), const btVector3& aabbMax = btVector3(0, 0, 0));
+ virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback);
+
void quantize(BP_FP_INT_TYPE* out, const btVector3& point, int isMax) const;
///unQuantize should be conservative: aabbMin/aabbMax should be larger then 'getAabb' result
- void unQuantize(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
-
- bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
+ void unQuantize(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const;
+
+ bool testAabbOverlap(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1);
- btOverlappingPairCache* getOverlappingPairCache()
+ btOverlappingPairCache* getOverlappingPairCache()
{
return m_pairCache;
}
- const btOverlappingPairCache* getOverlappingPairCache() const
+ const btOverlappingPairCache* getOverlappingPairCache() const
{
return m_pairCache;
}
- void setOverlappingPairUserCallback(btOverlappingPairCallback* pairCallback)
+ void setOverlappingPairUserCallback(btOverlappingPairCallback* pairCallback)
{
m_userPairCallback = pairCallback;
}
- const btOverlappingPairCallback* getOverlappingPairUserCallback() const
+ const btOverlappingPairCallback* getOverlappingPairUserCallback() const
{
return m_userPairCallback;
}
///getAabb returns the axis aligned bounding box in the 'global' coordinate frame
///will add some transform later
- virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const
+ virtual void getBroadphaseAabb(btVector3& aabbMin, btVector3& aabbMax) const
{
aabbMin = m_worldAabbMin;
aabbMax = m_worldAabbMax;
}
- virtual void printStats()
+ virtual void printStats()
{
-/* printf("btAxisSweep3.h\n");
+ /* printf("btAxisSweep3.h\n");
printf("numHandles = %d, maxHandles = %d\n",m_numHandles,m_maxHandles);
printf("aabbMin=%f,%f,%f,aabbMax=%f,%f,%f\n",m_worldAabbMin.getX(),m_worldAabbMin.getY(),m_worldAabbMin.getZ(),
m_worldAabbMax.getX(),m_worldAabbMax.getY(),m_worldAabbMax.getZ());
*/
-
}
-
};
////////////////////////////////////////////////////////////////////
-
-
-
#ifdef DEBUG_BROADPHASE
#include <stdio.h>
@@ -209,75 +195,73 @@ template <typename BP_FP_INT_TYPE>
void btAxisSweep3<BP_FP_INT_TYPE>::debugPrintAxis(int axis, bool checkCardinality)
{
int numEdges = m_pHandles[0].m_maxEdges[axis];
- printf("SAP Axis %d, numEdges=%d\n",axis,numEdges);
+ printf("SAP Axis %d, numEdges=%d\n", axis, numEdges);
int i;
- for (i=0;i<numEdges+1;i++)
+ for (i = 0; i < numEdges + 1; i++)
{
Edge* pEdge = m_pEdges[axis] + i;
Handle* pHandlePrev = getHandle(pEdge->m_handle);
- int handleIndex = pEdge->IsMax()? pHandlePrev->m_maxEdges[axis] : pHandlePrev->m_minEdges[axis];
+ int handleIndex = pEdge->IsMax() ? pHandlePrev->m_maxEdges[axis] : pHandlePrev->m_minEdges[axis];
char beginOrEnd;
- beginOrEnd=pEdge->IsMax()?'E':'B';
- printf(" [%c,h=%d,p=%x,i=%d]\n",beginOrEnd,pEdge->m_handle,pEdge->m_pos,handleIndex);
+ beginOrEnd = pEdge->IsMax() ? 'E' : 'B';
+ printf(" [%c,h=%d,p=%x,i=%d]\n", beginOrEnd, pEdge->m_handle, pEdge->m_pos, handleIndex);
}
if (checkCardinality)
- btAssert(numEdges == m_numHandles*2+1);
+ btAssert(numEdges == m_numHandles * 2 + 1);
}
-#endif //DEBUG_BROADPHASE
+#endif //DEBUG_BROADPHASE
template <typename BP_FP_INT_TYPE>
-btBroadphaseProxy* btAxisSweep3Internal<BP_FP_INT_TYPE>::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, int collisionFilterGroup, int collisionFilterMask,btDispatcher* dispatcher)
+btBroadphaseProxy* btAxisSweep3Internal<BP_FP_INT_TYPE>::createProxy(const btVector3& aabbMin, const btVector3& aabbMax, int shapeType, void* userPtr, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher)
{
- (void)shapeType;
- BP_FP_INT_TYPE handleId = addHandle(aabbMin,aabbMax, userPtr,collisionFilterGroup,collisionFilterMask,dispatcher);
-
- Handle* handle = getHandle(handleId);
-
- if (m_raycastAccelerator)
- {
- btBroadphaseProxy* rayProxy = m_raycastAccelerator->createProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask,dispatcher);
- handle->m_dbvtProxy = rayProxy;
- }
- return handle;
-}
+ (void)shapeType;
+ BP_FP_INT_TYPE handleId = addHandle(aabbMin, aabbMax, userPtr, collisionFilterGroup, collisionFilterMask, dispatcher);
+ Handle* handle = getHandle(handleId);
+ if (m_raycastAccelerator)
+ {
+ btBroadphaseProxy* rayProxy = m_raycastAccelerator->createProxy(aabbMin, aabbMax, shapeType, userPtr, collisionFilterGroup, collisionFilterMask, dispatcher);
+ handle->m_dbvtProxy = rayProxy;
+ }
+ return handle;
+}
template <typename BP_FP_INT_TYPE>
-void btAxisSweep3Internal<BP_FP_INT_TYPE>::destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::destroyProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher)
{
Handle* handle = static_cast<Handle*>(proxy);
if (m_raycastAccelerator)
- m_raycastAccelerator->destroyProxy(handle->m_dbvtProxy,dispatcher);
+ m_raycastAccelerator->destroyProxy(handle->m_dbvtProxy, dispatcher);
removeHandle(static_cast<BP_FP_INT_TYPE>(handle->m_uniqueId), dispatcher);
}
template <typename BP_FP_INT_TYPE>
-void btAxisSweep3Internal<BP_FP_INT_TYPE>::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher)
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::setAabb(btBroadphaseProxy* proxy, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* dispatcher)
{
Handle* handle = static_cast<Handle*>(proxy);
handle->m_aabbMin = aabbMin;
handle->m_aabbMax = aabbMax;
- updateHandle(static_cast<BP_FP_INT_TYPE>(handle->m_uniqueId), aabbMin, aabbMax,dispatcher);
+ updateHandle(static_cast<BP_FP_INT_TYPE>(handle->m_uniqueId), aabbMin, aabbMax, dispatcher);
if (m_raycastAccelerator)
- m_raycastAccelerator->setAabb(handle->m_dbvtProxy,aabbMin,aabbMax,dispatcher);
-
+ m_raycastAccelerator->setAabb(handle->m_dbvtProxy, aabbMin, aabbMax, dispatcher);
}
template <typename BP_FP_INT_TYPE>
-void btAxisSweep3Internal<BP_FP_INT_TYPE>::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback,const btVector3& aabbMin,const btVector3& aabbMax)
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::rayTest(const btVector3& rayFrom, const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin, const btVector3& aabbMax)
{
if (m_raycastAccelerator)
{
- m_raycastAccelerator->rayTest(rayFrom,rayTo,rayCallback,aabbMin,aabbMax);
- } else
+ m_raycastAccelerator->rayTest(rayFrom, rayTo, rayCallback, aabbMin, aabbMax);
+ }
+ else
{
//choose axis?
BP_FP_INT_TYPE axis = 0;
//for each proxy
- for (BP_FP_INT_TYPE i=1;i<m_numHandles*2+1;i++)
+ for (BP_FP_INT_TYPE i = 1; i < m_numHandles * 2 + 1; i++)
{
if (m_pEdges[axis][i].IsMax())
{
@@ -288,22 +272,23 @@ void btAxisSweep3Internal<BP_FP_INT_TYPE>::rayTest(const btVector3& rayFrom,cons
}
template <typename BP_FP_INT_TYPE>
-void btAxisSweep3Internal<BP_FP_INT_TYPE>::aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback)
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback)
{
if (m_raycastAccelerator)
{
- m_raycastAccelerator->aabbTest(aabbMin,aabbMax,callback);
- } else
+ m_raycastAccelerator->aabbTest(aabbMin, aabbMax, callback);
+ }
+ else
{
//choose axis?
BP_FP_INT_TYPE axis = 0;
//for each proxy
- for (BP_FP_INT_TYPE i=1;i<m_numHandles*2+1;i++)
+ for (BP_FP_INT_TYPE i = 1; i < m_numHandles * 2 + 1; i++)
{
if (m_pEdges[axis][i].IsMax())
{
Handle* handle = getHandle(m_pEdges[axis][i].m_handle);
- if (TestAabbAgainstAabb2(aabbMin,aabbMax,handle->m_aabbMin,handle->m_aabbMax))
+ if (TestAabbAgainstAabb2(aabbMin, aabbMax, handle->m_aabbMin, handle->m_aabbMax))
{
callback.process(handle);
}
@@ -312,66 +297,60 @@ void btAxisSweep3Internal<BP_FP_INT_TYPE>::aabbTest(const btVector3& aabbMin, co
}
}
-
-
template <typename BP_FP_INT_TYPE>
-void btAxisSweep3Internal<BP_FP_INT_TYPE>::getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::getAabb(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const
{
Handle* pHandle = static_cast<Handle*>(proxy);
aabbMin = pHandle->m_aabbMin;
aabbMax = pHandle->m_aabbMax;
}
-
template <typename BP_FP_INT_TYPE>
-void btAxisSweep3Internal<BP_FP_INT_TYPE>::unQuantize(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::unQuantize(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const
{
Handle* pHandle = static_cast<Handle*>(proxy);
unsigned short vecInMin[3];
unsigned short vecInMax[3];
- vecInMin[0] = m_pEdges[0][pHandle->m_minEdges[0]].m_pos ;
- vecInMax[0] = m_pEdges[0][pHandle->m_maxEdges[0]].m_pos +1 ;
- vecInMin[1] = m_pEdges[1][pHandle->m_minEdges[1]].m_pos ;
- vecInMax[1] = m_pEdges[1][pHandle->m_maxEdges[1]].m_pos +1 ;
- vecInMin[2] = m_pEdges[2][pHandle->m_minEdges[2]].m_pos ;
- vecInMax[2] = m_pEdges[2][pHandle->m_maxEdges[2]].m_pos +1 ;
-
- aabbMin.setValue((btScalar)(vecInMin[0]) / (m_quantize.getX()),(btScalar)(vecInMin[1]) / (m_quantize.getY()),(btScalar)(vecInMin[2]) / (m_quantize.getZ()));
+ vecInMin[0] = m_pEdges[0][pHandle->m_minEdges[0]].m_pos;
+ vecInMax[0] = m_pEdges[0][pHandle->m_maxEdges[0]].m_pos + 1;
+ vecInMin[1] = m_pEdges[1][pHandle->m_minEdges[1]].m_pos;
+ vecInMax[1] = m_pEdges[1][pHandle->m_maxEdges[1]].m_pos + 1;
+ vecInMin[2] = m_pEdges[2][pHandle->m_minEdges[2]].m_pos;
+ vecInMax[2] = m_pEdges[2][pHandle->m_maxEdges[2]].m_pos + 1;
+
+ aabbMin.setValue((btScalar)(vecInMin[0]) / (m_quantize.getX()), (btScalar)(vecInMin[1]) / (m_quantize.getY()), (btScalar)(vecInMin[2]) / (m_quantize.getZ()));
aabbMin += m_worldAabbMin;
-
- aabbMax.setValue((btScalar)(vecInMax[0]) / (m_quantize.getX()),(btScalar)(vecInMax[1]) / (m_quantize.getY()),(btScalar)(vecInMax[2]) / (m_quantize.getZ()));
+
+ aabbMax.setValue((btScalar)(vecInMax[0]) / (m_quantize.getX()), (btScalar)(vecInMax[1]) / (m_quantize.getY()), (btScalar)(vecInMax[2]) / (m_quantize.getZ()));
aabbMax += m_worldAabbMin;
}
-
-
-
template <typename BP_FP_INT_TYPE>
-btAxisSweep3Internal<BP_FP_INT_TYPE>::btAxisSweep3Internal(const btVector3& worldAabbMin,const btVector3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel,BP_FP_INT_TYPE userMaxHandles, btOverlappingPairCache* pairCache , bool disableRaycastAccelerator)
-:m_bpHandleMask(handleMask),
-m_handleSentinel(handleSentinel),
-m_pairCache(pairCache),
-m_userPairCallback(0),
-m_ownsPairCache(false),
-m_invalidPair(0),
-m_raycastAccelerator(0)
+btAxisSweep3Internal<BP_FP_INT_TYPE>::btAxisSweep3Internal(const btVector3& worldAabbMin, const btVector3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel, BP_FP_INT_TYPE userMaxHandles, btOverlappingPairCache* pairCache, bool disableRaycastAccelerator)
+ : m_bpHandleMask(handleMask),
+ m_handleSentinel(handleSentinel),
+ m_pairCache(pairCache),
+ m_userPairCallback(0),
+ m_ownsPairCache(false),
+ m_invalidPair(0),
+ m_raycastAccelerator(0)
{
- BP_FP_INT_TYPE maxHandles = static_cast<BP_FP_INT_TYPE>(userMaxHandles+1);//need to add one sentinel handle
+ BP_FP_INT_TYPE maxHandles = static_cast<BP_FP_INT_TYPE>(userMaxHandles + 1); //need to add one sentinel handle
if (!m_pairCache)
{
- void* ptr = btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16);
- m_pairCache = new(ptr) btHashedOverlappingPairCache();
+ void* ptr = btAlignedAlloc(sizeof(btHashedOverlappingPairCache), 16);
+ m_pairCache = new (ptr) btHashedOverlappingPairCache();
m_ownsPairCache = true;
}
if (!disableRaycastAccelerator)
{
- m_nullPairCache = new (btAlignedAlloc(sizeof(btNullPairCache),16)) btNullPairCache();
- m_raycastAccelerator = new (btAlignedAlloc(sizeof(btDbvtBroadphase),16)) btDbvtBroadphase(m_nullPairCache);//m_pairCache);
- m_raycastAccelerator->m_deferedcollide = true;//don't add/remove pairs
+ m_nullPairCache = new (btAlignedAlloc(sizeof(btNullPairCache), 16)) btNullPairCache();
+ m_raycastAccelerator = new (btAlignedAlloc(sizeof(btDbvtBroadphase), 16)) btDbvtBroadphase(m_nullPairCache); //m_pairCache);
+ m_raycastAccelerator->m_deferedcollide = true; //don't add/remove pairs
}
//btAssert(bounds.HasVolume());
@@ -382,13 +361,13 @@ m_raycastAccelerator(0)
btVector3 aabbSize = m_worldAabbMax - m_worldAabbMin;
- BP_FP_INT_TYPE maxInt = m_handleSentinel;
+ BP_FP_INT_TYPE maxInt = m_handleSentinel;
- m_quantize = btVector3(btScalar(maxInt),btScalar(maxInt),btScalar(maxInt)) / aabbSize;
+ m_quantize = btVector3(btScalar(maxInt), btScalar(maxInt), btScalar(maxInt)) / aabbSize;
// allocate handles buffer, using btAlignedAlloc, and put all handles on free list
m_pHandles = new Handle[maxHandles];
-
+
m_maxHandles = maxHandles;
m_numHandles = 0;
@@ -404,14 +383,14 @@ m_raycastAccelerator(0)
// allocate edge buffers
for (int i = 0; i < 3; i++)
{
- m_pEdgesRawPtr[i] = btAlignedAlloc(sizeof(Edge)*maxHandles*2,16);
- m_pEdges[i] = new(m_pEdgesRawPtr[i]) Edge[maxHandles * 2];
+ m_pEdgesRawPtr[i] = btAlignedAlloc(sizeof(Edge) * maxHandles * 2, 16);
+ m_pEdges[i] = new (m_pEdgesRawPtr[i]) Edge[maxHandles * 2];
}
}
//removed overlap management
// make boundary sentinels
-
+
m_pHandles[0].m_clientObject = 0;
for (int axis = 0; axis < 3; axis++)
@@ -425,10 +404,8 @@ m_raycastAccelerator(0)
m_pEdges[axis][1].m_handle = 0;
#ifdef DEBUG_BROADPHASE
debugPrintAxis(axis);
-#endif //DEBUG_BROADPHASE
-
+#endif //DEBUG_BROADPHASE
}
-
}
template <typename BP_FP_INT_TYPE>
@@ -439,14 +416,14 @@ btAxisSweep3Internal<BP_FP_INT_TYPE>::~btAxisSweep3Internal()
m_nullPairCache->~btOverlappingPairCache();
btAlignedFree(m_nullPairCache);
m_raycastAccelerator->~btDbvtBroadphase();
- btAlignedFree (m_raycastAccelerator);
+ btAlignedFree(m_raycastAccelerator);
}
for (int i = 2; i >= 0; i--)
{
btAlignedFree(m_pEdgesRawPtr[i]);
}
- delete [] m_pHandles;
+ delete[] m_pHandles;
if (m_ownsPairCache)
{
@@ -470,13 +447,12 @@ void btAxisSweep3Internal<BP_FP_INT_TYPE>::quantize(BP_FP_INT_TYPE* out, const b
out[2] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getZ() & m_bpHandleMask) | isMax);
#else
btVector3 v = (point - m_worldAabbMin) * m_quantize;
- out[0]=(v[0]<=0)?(BP_FP_INT_TYPE)isMax:(v[0]>=m_handleSentinel)?(BP_FP_INT_TYPE)((m_handleSentinel&m_bpHandleMask)|isMax):(BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[0]&m_bpHandleMask)|isMax);
- out[1]=(v[1]<=0)?(BP_FP_INT_TYPE)isMax:(v[1]>=m_handleSentinel)?(BP_FP_INT_TYPE)((m_handleSentinel&m_bpHandleMask)|isMax):(BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[1]&m_bpHandleMask)|isMax);
- out[2]=(v[2]<=0)?(BP_FP_INT_TYPE)isMax:(v[2]>=m_handleSentinel)?(BP_FP_INT_TYPE)((m_handleSentinel&m_bpHandleMask)|isMax):(BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[2]&m_bpHandleMask)|isMax);
-#endif //OLD_CLAMPING_METHOD
+ out[0] = (v[0] <= 0) ? (BP_FP_INT_TYPE)isMax : (v[0] >= m_handleSentinel) ? (BP_FP_INT_TYPE)((m_handleSentinel & m_bpHandleMask) | isMax) : (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[0] & m_bpHandleMask) | isMax);
+ out[1] = (v[1] <= 0) ? (BP_FP_INT_TYPE)isMax : (v[1] >= m_handleSentinel) ? (BP_FP_INT_TYPE)((m_handleSentinel & m_bpHandleMask) | isMax) : (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[1] & m_bpHandleMask) | isMax);
+ out[2] = (v[2] <= 0) ? (BP_FP_INT_TYPE)isMax : (v[2] >= m_handleSentinel) ? (BP_FP_INT_TYPE)((m_handleSentinel & m_bpHandleMask) | isMax) : (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[2] & m_bpHandleMask) | isMax);
+#endif //OLD_CLAMPING_METHOD
}
-
template <typename BP_FP_INT_TYPE>
BP_FP_INT_TYPE btAxisSweep3Internal<BP_FP_INT_TYPE>::allocHandle()
{
@@ -500,9 +476,8 @@ void btAxisSweep3Internal<BP_FP_INT_TYPE>::freeHandle(BP_FP_INT_TYPE handle)
m_numHandles--;
}
-
template <typename BP_FP_INT_TYPE>
-BP_FP_INT_TYPE btAxisSweep3Internal<BP_FP_INT_TYPE>::addHandle(const btVector3& aabbMin,const btVector3& aabbMax, void* pOwner, int collisionFilterGroup, int collisionFilterMask,btDispatcher* dispatcher)
+BP_FP_INT_TYPE btAxisSweep3Internal<BP_FP_INT_TYPE>::addHandle(const btVector3& aabbMin, const btVector3& aabbMax, void* pOwner, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher)
{
// quantize the bounds
BP_FP_INT_TYPE min[3], max[3];
@@ -511,10 +486,9 @@ BP_FP_INT_TYPE btAxisSweep3Internal<BP_FP_INT_TYPE>::addHandle(const btVector3&
// allocate a handle
BP_FP_INT_TYPE handle = allocHandle();
-
Handle* pHandle = getHandle(handle);
-
+
pHandle->m_uniqueId = static_cast<int>(handle);
//pHandle->m_pOverlaps = 0;
pHandle->m_clientObject = pOwner;
@@ -524,11 +498,9 @@ BP_FP_INT_TYPE btAxisSweep3Internal<BP_FP_INT_TYPE>::addHandle(const btVector3&
// compute current limit of edge arrays
BP_FP_INT_TYPE limit = static_cast<BP_FP_INT_TYPE>(m_numHandles * 2);
-
// insert new edges just inside the max boundary edge
for (BP_FP_INT_TYPE axis = 0; axis < 3; axis++)
{
-
m_pHandles[0].m_maxEdges[axis] += 2;
m_pEdges[axis][limit + 1] = m_pEdges[axis][limit - 1];
@@ -544,22 +516,19 @@ BP_FP_INT_TYPE btAxisSweep3Internal<BP_FP_INT_TYPE>::addHandle(const btVector3&
}
// now sort the new edges to their correct position
- sortMinDown(0, pHandle->m_minEdges[0], dispatcher,false);
- sortMaxDown(0, pHandle->m_maxEdges[0], dispatcher,false);
- sortMinDown(1, pHandle->m_minEdges[1], dispatcher,false);
- sortMaxDown(1, pHandle->m_maxEdges[1], dispatcher,false);
- sortMinDown(2, pHandle->m_minEdges[2], dispatcher,true);
- sortMaxDown(2, pHandle->m_maxEdges[2], dispatcher,true);
-
+ sortMinDown(0, pHandle->m_minEdges[0], dispatcher, false);
+ sortMaxDown(0, pHandle->m_maxEdges[0], dispatcher, false);
+ sortMinDown(1, pHandle->m_minEdges[1], dispatcher, false);
+ sortMaxDown(1, pHandle->m_maxEdges[1], dispatcher, false);
+ sortMinDown(2, pHandle->m_minEdges[2], dispatcher, true);
+ sortMaxDown(2, pHandle->m_maxEdges[2], dispatcher, true);
return handle;
}
-
template <typename BP_FP_INT_TYPE>
-void btAxisSweep3Internal<BP_FP_INT_TYPE>::removeHandle(BP_FP_INT_TYPE handle,btDispatcher* dispatcher)
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::removeHandle(BP_FP_INT_TYPE handle, btDispatcher* dispatcher)
{
-
Handle* pHandle = getHandle(handle);
//explicitly remove the pairs containing the proxy
@@ -567,50 +536,43 @@ void btAxisSweep3Internal<BP_FP_INT_TYPE>::removeHandle(BP_FP_INT_TYPE handle,bt
///@todo: compare performance
if (!m_pairCache->hasDeferredRemoval())
{
- m_pairCache->removeOverlappingPairsContainingProxy(pHandle,dispatcher);
+ m_pairCache->removeOverlappingPairsContainingProxy(pHandle, dispatcher);
}
// compute current limit of edge arrays
int limit = static_cast<int>(m_numHandles * 2);
-
+
int axis;
- for (axis = 0;axis<3;axis++)
+ for (axis = 0; axis < 3; axis++)
{
m_pHandles[0].m_maxEdges[axis] -= 2;
}
// remove the edges by sorting them up to the end of the list
- for ( axis = 0; axis < 3; axis++)
+ for (axis = 0; axis < 3; axis++)
{
Edge* pEdges = m_pEdges[axis];
BP_FP_INT_TYPE max = pHandle->m_maxEdges[axis];
pEdges[max].m_pos = m_handleSentinel;
- sortMaxUp(axis,max,dispatcher,false);
-
+ sortMaxUp(axis, max, dispatcher, false);
BP_FP_INT_TYPE i = pHandle->m_minEdges[axis];
pEdges[i].m_pos = m_handleSentinel;
+ sortMinUp(axis, i, dispatcher, false);
- sortMinUp(axis,i,dispatcher,false);
+ pEdges[limit - 1].m_handle = 0;
+ pEdges[limit - 1].m_pos = m_handleSentinel;
- pEdges[limit-1].m_handle = 0;
- pEdges[limit-1].m_pos = m_handleSentinel;
-
#ifdef DEBUG_BROADPHASE
- debugPrintAxis(axis,false);
-#endif //DEBUG_BROADPHASE
-
-
+ debugPrintAxis(axis, false);
+#endif //DEBUG_BROADPHASE
}
-
// free the handle
freeHandle(handle);
-
-
}
template <typename BP_FP_INT_TYPE>
@@ -625,19 +587,16 @@ void btAxisSweep3Internal<BP_FP_INT_TYPE>::resetPool(btDispatcher* /*dispatcher*
m_pHandles[m_maxHandles - 1].SetNextFree(0);
}
}
-}
-
+}
//#include <stdio.h>
template <typename BP_FP_INT_TYPE>
-void btAxisSweep3Internal<BP_FP_INT_TYPE>::calculateOverlappingPairs(btDispatcher* dispatcher)
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::calculateOverlappingPairs(btDispatcher* dispatcher)
{
-
if (m_pairCache->hasDeferredRemoval())
{
-
- btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray();
+ btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray();
//perform a sort, to find duplicates and to sort 'invalid' pairs to the end
overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
@@ -645,18 +604,15 @@ void btAxisSweep3Internal<BP_FP_INT_TYPE>::calculateOverlappingPairs(btDispatche
overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
m_invalidPair = 0;
-
int i;
btBroadphasePair previousPair;
previousPair.m_pProxy0 = 0;
previousPair.m_pProxy1 = 0;
previousPair.m_algorithm = 0;
-
-
- for (i=0;i<overlappingPairArray.size();i++)
+
+ for (i = 0; i < overlappingPairArray.size(); i++)
{
-
btBroadphasePair& pair = overlappingPairArray[i];
bool isDuplicate = (pair == previousPair);
@@ -668,91 +624,90 @@ void btAxisSweep3Internal<BP_FP_INT_TYPE>::calculateOverlappingPairs(btDispatche
if (!isDuplicate)
{
///important to use an AABB test that is consistent with the broadphase
- bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1);
+ bool hasOverlap = testAabbOverlap(pair.m_pProxy0, pair.m_pProxy1);
if (hasOverlap)
{
- needsRemoval = false;//callback->processOverlap(pair);
- } else
+ needsRemoval = false; //callback->processOverlap(pair);
+ }
+ else
{
needsRemoval = true;
}
- } else
+ }
+ else
{
//remove duplicate
needsRemoval = true;
//should have no algorithm
btAssert(!pair.m_algorithm);
}
-
+
if (needsRemoval)
{
- m_pairCache->cleanOverlappingPair(pair,dispatcher);
+ m_pairCache->cleanOverlappingPair(pair, dispatcher);
- // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
- // m_overlappingPairArray.pop_back();
+ // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
+ // m_overlappingPairArray.pop_back();
pair.m_pProxy0 = 0;
pair.m_pProxy1 = 0;
m_invalidPair++;
- }
-
- }
+ }
+ }
- ///if you don't like to skip the invalid pairs in the array, execute following code:
- #define CLEAN_INVALID_PAIRS 1
- #ifdef CLEAN_INVALID_PAIRS
+///if you don't like to skip the invalid pairs in the array, execute following code:
+#define CLEAN_INVALID_PAIRS 1
+#ifdef CLEAN_INVALID_PAIRS
//perform a sort, to sort 'invalid' pairs to the end
overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
m_invalidPair = 0;
- #endif//CLEAN_INVALID_PAIRS
-
+#endif //CLEAN_INVALID_PAIRS
+
//printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size());
}
-
}
-
template <typename BP_FP_INT_TYPE>
-bool btAxisSweep3Internal<BP_FP_INT_TYPE>::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+bool btAxisSweep3Internal<BP_FP_INT_TYPE>::testAabbOverlap(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
{
const Handle* pHandleA = static_cast<Handle*>(proxy0);
const Handle* pHandleB = static_cast<Handle*>(proxy1);
-
+
//optimization 1: check the array index (memory address), instead of the m_pos
for (int axis = 0; axis < 3; axis++)
- {
- if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] ||
- pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis])
- {
- return false;
- }
- }
+ {
+ if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] ||
+ pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis])
+ {
+ return false;
+ }
+ }
return true;
}
template <typename BP_FP_INT_TYPE>
-bool btAxisSweep3Internal<BP_FP_INT_TYPE>::testOverlap2D(const Handle* pHandleA, const Handle* pHandleB,int axis0,int axis1)
+bool btAxisSweep3Internal<BP_FP_INT_TYPE>::testOverlap2D(const Handle* pHandleA, const Handle* pHandleB, int axis0, int axis1)
{
//optimization 1: check the array index (memory address), instead of the m_pos
- if (pHandleA->m_maxEdges[axis0] < pHandleB->m_minEdges[axis0] ||
+ if (pHandleA->m_maxEdges[axis0] < pHandleB->m_minEdges[axis0] ||
pHandleB->m_maxEdges[axis0] < pHandleA->m_minEdges[axis0] ||
pHandleA->m_maxEdges[axis1] < pHandleB->m_minEdges[axis1] ||
- pHandleB->m_maxEdges[axis1] < pHandleA->m_minEdges[axis1])
- {
- return false;
- }
+ pHandleB->m_maxEdges[axis1] < pHandleA->m_minEdges[axis1])
+ {
+ return false;
+ }
return true;
}
template <typename BP_FP_INT_TYPE>
-void btAxisSweep3Internal<BP_FP_INT_TYPE>::updateHandle(BP_FP_INT_TYPE handle, const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher)
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::updateHandle(BP_FP_INT_TYPE handle, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* dispatcher)
{
-// btAssert(bounds.IsFinite());
+ // btAssert(bounds.IsFinite());
//btAssert(bounds.HasVolume());
Handle* pHandle = getHandle(handle);
@@ -776,34 +731,28 @@ void btAxisSweep3Internal<BP_FP_INT_TYPE>::updateHandle(BP_FP_INT_TYPE handle, c
// expand (only adds overlaps)
if (dmin < 0)
- sortMinDown(axis, emin,dispatcher,true);
+ sortMinDown(axis, emin, dispatcher, true);
if (dmax > 0)
- sortMaxUp(axis, emax,dispatcher,true);
+ sortMaxUp(axis, emax, dispatcher, true);
// shrink (only removes overlaps)
if (dmin > 0)
- sortMinUp(axis, emin,dispatcher,true);
+ sortMinUp(axis, emin, dispatcher, true);
if (dmax < 0)
- sortMaxDown(axis, emax,dispatcher,true);
+ sortMaxDown(axis, emax, dispatcher, true);
#ifdef DEBUG_BROADPHASE
- debugPrintAxis(axis);
-#endif //DEBUG_BROADPHASE
+ debugPrintAxis(axis);
+#endif //DEBUG_BROADPHASE
}
-
-
}
-
-
-
// sorting a min edge downwards can only ever *add* overlaps
template <typename BP_FP_INT_TYPE>
void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* /* dispatcher */, bool updateOverlaps)
{
-
Edge* pEdge = m_pEdges[axis] + edge;
Edge* pPrev = pEdge - 1;
Handle* pHandleEdge = getHandle(pEdge->m_handle);
@@ -815,16 +764,15 @@ void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMinDown(int axis, BP_FP_INT_TYPE
if (pPrev->IsMax())
{
// if previous edge is a maximum check the bounds and add an overlap if necessary
- const int axis1 = (1 << axis) & 3;
- const int axis2 = (1 << axis1) & 3;
- if (updateOverlaps && testOverlap2D(pHandleEdge, pHandlePrev,axis1,axis2))
+ const int axis1 = (1 << axis) & 3;
+ const int axis2 = (1 << axis1) & 3;
+ if (updateOverlaps && testOverlap2D(pHandleEdge, pHandlePrev, axis1, axis2))
{
- m_pairCache->addOverlappingPair(pHandleEdge,pHandlePrev);
+ m_pairCache->addOverlappingPair(pHandleEdge, pHandlePrev);
if (m_userPairCallback)
- m_userPairCallback->addOverlappingPair(pHandleEdge,pHandlePrev);
+ m_userPairCallback->addOverlappingPair(pHandleEdge, pHandlePrev);
//AddOverlap(pEdge->m_handle, pPrev->m_handle);
-
}
// update edge reference in other handle
@@ -847,8 +795,7 @@ void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMinDown(int axis, BP_FP_INT_TYPE
#ifdef DEBUG_BROADPHASE
debugPrintAxis(axis);
-#endif //DEBUG_BROADPHASE
-
+#endif //DEBUG_BROADPHASE
}
// sorting a min edge upwards can only ever *remove* overlaps
@@ -867,25 +814,21 @@ void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMinUp(int axis, BP_FP_INT_TYPE ed
{
Handle* handle0 = getHandle(pEdge->m_handle);
Handle* handle1 = getHandle(pNext->m_handle);
- const int axis1 = (1 << axis) & 3;
- const int axis2 = (1 << axis1) & 3;
-
+ const int axis1 = (1 << axis) & 3;
+ const int axis2 = (1 << axis1) & 3;
+
// if next edge is maximum remove any overlap between the two handles
- if (updateOverlaps
+ if (updateOverlaps
#ifdef USE_OVERLAP_TEST_ON_REMOVES
- && testOverlap2D(handle0,handle1,axis1,axis2)
-#endif //USE_OVERLAP_TEST_ON_REMOVES
- )
+ && testOverlap2D(handle0, handle1, axis1, axis2)
+#endif //USE_OVERLAP_TEST_ON_REMOVES
+ )
{
-
-
- m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher);
+ m_pairCache->removeOverlappingPair(handle0, handle1, dispatcher);
if (m_userPairCallback)
- m_userPairCallback->removeOverlappingPair(handle0,handle1,dispatcher);
-
+ m_userPairCallback->removeOverlappingPair(handle0, handle1, dispatcher);
}
-
// update edge reference in other handle
pHandleNext->m_maxEdges[axis]--;
}
@@ -903,15 +846,12 @@ void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMinUp(int axis, BP_FP_INT_TYPE ed
pEdge++;
pNext++;
}
-
-
}
// sorting a max edge downwards can only ever *remove* overlaps
template <typename BP_FP_INT_TYPE>
void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps)
{
-
Edge* pEdge = m_pEdges[axis] + edge;
Edge* pPrev = pEdge - 1;
Handle* pHandleEdge = getHandle(pEdge->m_handle);
@@ -925,28 +865,25 @@ void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMaxDown(int axis, BP_FP_INT_TYPE
// if previous edge was a minimum remove any overlap between the two handles
Handle* handle0 = getHandle(pEdge->m_handle);
Handle* handle1 = getHandle(pPrev->m_handle);
- const int axis1 = (1 << axis) & 3;
- const int axis2 = (1 << axis1) & 3;
+ const int axis1 = (1 << axis) & 3;
+ const int axis2 = (1 << axis1) & 3;
- if (updateOverlaps
+ if (updateOverlaps
#ifdef USE_OVERLAP_TEST_ON_REMOVES
- && testOverlap2D(handle0,handle1,axis1,axis2)
-#endif //USE_OVERLAP_TEST_ON_REMOVES
- )
+ && testOverlap2D(handle0, handle1, axis1, axis2)
+#endif //USE_OVERLAP_TEST_ON_REMOVES
+ )
{
//this is done during the overlappingpairarray iteration/narrowphase collision
-
- m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher);
+ m_pairCache->removeOverlappingPair(handle0, handle1, dispatcher);
if (m_userPairCallback)
- m_userPairCallback->removeOverlappingPair(handle0,handle1,dispatcher);
-
-
-
+ m_userPairCallback->removeOverlappingPair(handle0, handle1, dispatcher);
}
// update edge reference in other handle
- pHandlePrev->m_minEdges[axis]++;;
+ pHandlePrev->m_minEdges[axis]++;
+ ;
}
else
pHandlePrev->m_maxEdges[axis]++;
@@ -963,11 +900,9 @@ void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMaxDown(int axis, BP_FP_INT_TYPE
pPrev--;
}
-
#ifdef DEBUG_BROADPHASE
debugPrintAxis(axis);
-#endif //DEBUG_BROADPHASE
-
+#endif //DEBUG_BROADPHASE
}
// sorting a max edge upwards can only ever *add* overlaps
@@ -982,19 +917,19 @@ void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMaxUp(int axis, BP_FP_INT_TYPE ed
{
Handle* pHandleNext = getHandle(pNext->m_handle);
- const int axis1 = (1 << axis) & 3;
- const int axis2 = (1 << axis1) & 3;
+ const int axis1 = (1 << axis) & 3;
+ const int axis2 = (1 << axis1) & 3;
if (!pNext->IsMax())
{
// if next edge is a minimum check the bounds and add an overlap if necessary
- if (updateOverlaps && testOverlap2D(pHandleEdge, pHandleNext,axis1,axis2))
+ if (updateOverlaps && testOverlap2D(pHandleEdge, pHandleNext, axis1, axis2))
{
Handle* handle0 = getHandle(pEdge->m_handle);
Handle* handle1 = getHandle(pNext->m_handle);
- m_pairCache->addOverlappingPair(handle0,handle1);
+ m_pairCache->addOverlappingPair(handle0, handle1);
if (m_userPairCallback)
- m_userPairCallback->addOverlappingPair(handle0,handle1);
+ m_userPairCallback->addOverlappingPair(handle0, handle1);
}
// update edge reference in other handle
@@ -1014,7 +949,6 @@ void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMaxUp(int axis, BP_FP_INT_TYPE ed
pEdge++;
pNext++;
}
-
}
#endif
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h
index fb68e0024e..b097eca5f5 100644
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h
+++ b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h
@@ -13,10 +13,8 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-#ifndef BT_BROADPHASE_INTERFACE_H
-#define BT_BROADPHASE_INTERFACE_H
-
-
+#ifndef BT_BROADPHASE_INTERFACE_H
+#define BT_BROADPHASE_INTERFACE_H
struct btDispatcherInfo;
class btDispatcher;
@@ -24,27 +22,23 @@ class btDispatcher;
class btOverlappingPairCache;
-
-
-struct btBroadphaseAabbCallback
+struct btBroadphaseAabbCallback
{
virtual ~btBroadphaseAabbCallback() {}
- virtual bool process(const btBroadphaseProxy* proxy) = 0;
+ virtual bool process(const btBroadphaseProxy* proxy) = 0;
};
-
-struct btBroadphaseRayCallback : public btBroadphaseAabbCallback
+struct btBroadphaseRayCallback : public btBroadphaseAabbCallback
{
///added some cached data to accelerate ray-AABB tests
- btVector3 m_rayDirectionInverse;
- unsigned int m_signs[3];
- btScalar m_lambda_max;
+ btVector3 m_rayDirectionInverse;
+ unsigned int m_signs[3];
+ btScalar m_lambda_max;
virtual ~btBroadphaseRayCallback() {}
-
+
protected:
-
- btBroadphaseRayCallback() {}
+ btBroadphaseRayCallback() {}
};
#include "LinearMath/btVector3.h"
@@ -57,30 +51,29 @@ class btBroadphaseInterface
public:
virtual ~btBroadphaseInterface() {}
- virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher) =0;
- virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)=0;
- virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher)=0;
- virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const =0;
+ virtual btBroadphaseProxy* createProxy(const btVector3& aabbMin, const btVector3& aabbMax, int shapeType, void* userPtr, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher) = 0;
+ virtual void destroyProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher) = 0;
+ virtual void setAabb(btBroadphaseProxy* proxy, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* dispatcher) = 0;
+ virtual void getAabb(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const = 0;
- virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0), const btVector3& aabbMax = btVector3(0,0,0)) = 0;
+ virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin = btVector3(0, 0, 0), const btVector3& aabbMax = btVector3(0, 0, 0)) = 0;
- virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback) = 0;
+ virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback) = 0;
///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
- virtual void calculateOverlappingPairs(btDispatcher* dispatcher)=0;
+ virtual void calculateOverlappingPairs(btDispatcher* dispatcher) = 0;
- virtual btOverlappingPairCache* getOverlappingPairCache()=0;
- virtual const btOverlappingPairCache* getOverlappingPairCache() const =0;
+ virtual btOverlappingPairCache* getOverlappingPairCache() = 0;
+ virtual const btOverlappingPairCache* getOverlappingPairCache() const = 0;
///getAabb returns the axis aligned bounding box in the 'global' coordinate frame
///will add some transform later
- virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const =0;
+ virtual void getBroadphaseAabb(btVector3& aabbMin, btVector3& aabbMax) const = 0;
///reset broadphase internal structures, to ensure determinism/reproducability
- virtual void resetPool(btDispatcher* dispatcher) { (void) dispatcher; };
-
- virtual void printStats() = 0;
+ virtual void resetPool(btDispatcher* dispatcher) { (void)dispatcher; };
+ virtual void printStats() = 0;
};
-#endif //BT_BROADPHASE_INTERFACE_H
+#endif //BT_BROADPHASE_INTERFACE_H
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp
index 0fd4ef46be..7ee065aac3 100644
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp
+++ b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp
@@ -15,4 +15,4 @@ subject to the following restrictions:
#include "btBroadphaseProxy.h"
-BT_NOT_EMPTY_FILE // fix warning LNK4221: This object file does not define any previously undefined public symbols, so it will not be used by any link operation that consumes this library
+BT_NOT_EMPTY_FILE // fix warning LNK4221: This object file does not define any previously undefined public symbols, so it will not be used by any link operation that consumes this library
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h
index f6e1202a69..825caeef56 100644
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h
+++ b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h
@@ -16,11 +16,10 @@ subject to the following restrictions:
#ifndef BT_BROADPHASE_PROXY_H
#define BT_BROADPHASE_PROXY_H
-#include "LinearMath/btScalar.h" //for SIMD_FORCE_INLINE
+#include "LinearMath/btScalar.h" //for SIMD_FORCE_INLINE
#include "LinearMath/btVector3.h"
#include "LinearMath/btAlignedAllocator.h"
-
/// btDispatcher uses these types
/// IMPORTANT NOTE:The types are ordered polyhedral, implicit convex and concave
/// to facilitate type checking
@@ -35,8 +34,8 @@ enum BroadphaseNativeTypes
CONVEX_HULL_SHAPE_PROXYTYPE,
CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE,
CUSTOM_POLYHEDRAL_SHAPE_TYPE,
-//implicit convex shapes
-IMPLICIT_CONVEX_SHAPES_START_HERE,
+ //implicit convex shapes
+ IMPLICIT_CONVEX_SHAPES_START_HERE,
SPHERE_SHAPE_PROXYTYPE,
MULTI_SPHERE_SHAPE_PROXYTYPE,
CAPSULE_SHAPE_PROXYTYPE,
@@ -49,8 +48,8 @@ IMPLICIT_CONVEX_SHAPES_START_HERE,
BOX_2D_SHAPE_PROXYTYPE,
CONVEX_2D_SHAPE_PROXYTYPE,
CUSTOM_CONVEX_SHAPE_TYPE,
-//concave shapes
-CONCAVE_SHAPES_START_HERE,
+ //concave shapes
+ CONCAVE_SHAPES_START_HERE,
//keep all the convex shapetype below here, for the check IsConvexShape in broadphase proxy!
TRIANGLE_MESH_SHAPE_PROXYTYPE,
SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE,
@@ -58,16 +57,16 @@ CONCAVE_SHAPES_START_HERE,
FAST_CONCAVE_MESH_PROXYTYPE,
//terrain
TERRAIN_SHAPE_PROXYTYPE,
-///Used for GIMPACT Trimesh integration
+ ///Used for GIMPACT Trimesh integration
GIMPACT_SHAPE_PROXYTYPE,
-///Multimaterial mesh
- MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE,
-
+ ///Multimaterial mesh
+ MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE,
+
EMPTY_SHAPE_PROXYTYPE,
STATIC_PLANE_PROXYTYPE,
CUSTOM_CONCAVE_SHAPE_TYPE,
- SDF_SHAPE_PROXYTYPE=CUSTOM_CONCAVE_SHAPE_TYPE,
-CONCAVE_SHAPES_END_HERE,
+ SDF_SHAPE_PROXYTYPE = CUSTOM_CONCAVE_SHAPE_TYPE,
+ CONCAVE_SHAPES_END_HERE,
COMPOUND_SHAPE_PROXYTYPE,
@@ -77,38 +76,37 @@ CONCAVE_SHAPES_END_HERE,
INVALID_SHAPE_PROXYTYPE,
MAX_BROADPHASE_COLLISION_TYPES
-
-};
+};
-///The btBroadphaseProxy is the main class that can be used with the Bullet broadphases.
+///The btBroadphaseProxy is the main class that can be used with the Bullet broadphases.
///It stores collision shape type information, collision filter information and a client object, typically a btCollisionObject or btRigidBody.
-ATTRIBUTE_ALIGNED16(struct) btBroadphaseProxy
+ATTRIBUTE_ALIGNED16(struct)
+btBroadphaseProxy
{
+ BT_DECLARE_ALIGNED_ALLOCATOR();
-BT_DECLARE_ALIGNED_ALLOCATOR();
-
///optional filtering to cull potential collisions
enum CollisionFilterGroups
{
- DefaultFilter = 1,
- StaticFilter = 2,
- KinematicFilter = 4,
- DebrisFilter = 8,
- SensorTrigger = 16,
- CharacterFilter = 32,
- AllFilter = -1 //all bits sets: DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorTrigger
+ DefaultFilter = 1,
+ StaticFilter = 2,
+ KinematicFilter = 4,
+ DebrisFilter = 8,
+ SensorTrigger = 16,
+ CharacterFilter = 32,
+ AllFilter = -1 //all bits sets: DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorTrigger
};
//Usually the client btCollisionObject or Rigidbody class
- void* m_clientObject;
- int m_collisionFilterGroup;
- int m_collisionFilterMask;
+ void* m_clientObject;
+ int m_collisionFilterGroup;
+ int m_collisionFilterMask;
- int m_uniqueId;//m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc.
+ int m_uniqueId; //m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc.
- btVector3 m_aabbMin;
- btVector3 m_aabbMax;
+ btVector3 m_aabbMin;
+ btVector3 m_aabbMax;
SIMD_FORCE_INLINE int getUid() const
{
@@ -116,47 +114,45 @@ BT_DECLARE_ALIGNED_ALLOCATOR();
}
//used for memory pools
- btBroadphaseProxy() :m_clientObject(0)
+ btBroadphaseProxy() : m_clientObject(0)
{
}
- btBroadphaseProxy(const btVector3& aabbMin,const btVector3& aabbMax,void* userPtr, int collisionFilterGroup, int collisionFilterMask)
- :m_clientObject(userPtr),
- m_collisionFilterGroup(collisionFilterGroup),
- m_collisionFilterMask(collisionFilterMask),
- m_aabbMin(aabbMin),
- m_aabbMax(aabbMax)
+ btBroadphaseProxy(const btVector3& aabbMin, const btVector3& aabbMax, void* userPtr, int collisionFilterGroup, int collisionFilterMask)
+ : m_clientObject(userPtr),
+ m_collisionFilterGroup(collisionFilterGroup),
+ m_collisionFilterMask(collisionFilterMask),
+ m_aabbMin(aabbMin),
+ m_aabbMax(aabbMax)
{
}
-
-
static SIMD_FORCE_INLINE bool isPolyhedral(int proxyType)
{
- return (proxyType < IMPLICIT_CONVEX_SHAPES_START_HERE);
+ return (proxyType < IMPLICIT_CONVEX_SHAPES_START_HERE);
}
- static SIMD_FORCE_INLINE bool isConvex(int proxyType)
+ static SIMD_FORCE_INLINE bool isConvex(int proxyType)
{
return (proxyType < CONCAVE_SHAPES_START_HERE);
}
- static SIMD_FORCE_INLINE bool isNonMoving(int proxyType)
+ static SIMD_FORCE_INLINE bool isNonMoving(int proxyType)
{
- return (isConcave(proxyType) && !(proxyType==GIMPACT_SHAPE_PROXYTYPE));
+ return (isConcave(proxyType) && !(proxyType == GIMPACT_SHAPE_PROXYTYPE));
}
- static SIMD_FORCE_INLINE bool isConcave(int proxyType)
+ static SIMD_FORCE_INLINE bool isConcave(int proxyType)
{
return ((proxyType > CONCAVE_SHAPES_START_HERE) &&
- (proxyType < CONCAVE_SHAPES_END_HERE));
+ (proxyType < CONCAVE_SHAPES_END_HERE));
}
- static SIMD_FORCE_INLINE bool isCompound(int proxyType)
+ static SIMD_FORCE_INLINE bool isCompound(int proxyType)
{
return (proxyType == COMPOUND_SHAPE_PROXYTYPE);
}
- static SIMD_FORCE_INLINE bool isSoftBody(int proxyType)
+ static SIMD_FORCE_INLINE bool isSoftBody(int proxyType)
{
return (proxyType == SOFTBODY_SHAPE_PROXYTYPE);
}
@@ -168,67 +164,62 @@ BT_DECLARE_ALIGNED_ALLOCATOR();
static SIMD_FORCE_INLINE bool isConvex2d(int proxyType)
{
- return (proxyType == BOX_2D_SHAPE_PROXYTYPE) || (proxyType == CONVEX_2D_SHAPE_PROXYTYPE);
+ return (proxyType == BOX_2D_SHAPE_PROXYTYPE) || (proxyType == CONVEX_2D_SHAPE_PROXYTYPE);
}
-
-
-}
-;
+};
class btCollisionAlgorithm;
struct btBroadphaseProxy;
-
-
///The btBroadphasePair class contains a pair of aabb-overlapping objects.
///A btDispatcher can search a btCollisionAlgorithm that performs exact/narrowphase collision detection on the actual collision shapes.
-ATTRIBUTE_ALIGNED16(struct) btBroadphasePair
+ATTRIBUTE_ALIGNED16(struct)
+btBroadphasePair
{
- btBroadphasePair ()
- :
- m_pProxy0(0),
- m_pProxy1(0),
- m_algorithm(0),
- m_internalInfo1(0)
+ btBroadphasePair()
+ : m_pProxy0(0),
+ m_pProxy1(0),
+ m_algorithm(0),
+ m_internalInfo1(0)
{
}
-BT_DECLARE_ALIGNED_ALLOCATOR();
+ BT_DECLARE_ALIGNED_ALLOCATOR();
btBroadphasePair(const btBroadphasePair& other)
- : m_pProxy0(other.m_pProxy0),
- m_pProxy1(other.m_pProxy1),
- m_algorithm(other.m_algorithm),
- m_internalInfo1(other.m_internalInfo1)
+ : m_pProxy0(other.m_pProxy0),
+ m_pProxy1(other.m_pProxy1),
+ m_algorithm(other.m_algorithm),
+ m_internalInfo1(other.m_internalInfo1)
{
}
- btBroadphasePair(btBroadphaseProxy& proxy0,btBroadphaseProxy& proxy1)
+ btBroadphasePair(btBroadphaseProxy & proxy0, btBroadphaseProxy & proxy1)
{
-
//keep them sorted, so the std::set operations work
if (proxy0.m_uniqueId < proxy1.m_uniqueId)
- {
- m_pProxy0 = &proxy0;
- m_pProxy1 = &proxy1;
- }
- else
- {
- m_pProxy0 = &proxy1;
- m_pProxy1 = &proxy0;
- }
+ {
+ m_pProxy0 = &proxy0;
+ m_pProxy1 = &proxy1;
+ }
+ else
+ {
+ m_pProxy0 = &proxy1;
+ m_pProxy1 = &proxy0;
+ }
m_algorithm = 0;
m_internalInfo1 = 0;
-
}
-
+
btBroadphaseProxy* m_pProxy0;
btBroadphaseProxy* m_pProxy1;
-
- mutable btCollisionAlgorithm* m_algorithm;
- union { void* m_internalInfo1; int m_internalTmpValue;};//don't use this data, it will be removed in future version.
+ mutable btCollisionAlgorithm* m_algorithm;
+ union {
+ void* m_internalInfo1;
+ int m_internalTmpValue;
+ }; //don't use this data, it will be removed in future version.
};
/*
@@ -240,31 +231,25 @@ SIMD_FORCE_INLINE bool operator<(const btBroadphasePair& a, const btBroadphasePa
}
*/
-
-
class btBroadphasePairSortPredicate
{
- public:
-
- bool operator() ( const btBroadphasePair& a, const btBroadphasePair& b ) const
- {
- const int uidA0 = a.m_pProxy0 ? a.m_pProxy0->m_uniqueId : -1;
- const int uidB0 = b.m_pProxy0 ? b.m_pProxy0->m_uniqueId : -1;
- const int uidA1 = a.m_pProxy1 ? a.m_pProxy1->m_uniqueId : -1;
- const int uidB1 = b.m_pProxy1 ? b.m_pProxy1->m_uniqueId : -1;
-
- return uidA0 > uidB0 ||
- (a.m_pProxy0 == b.m_pProxy0 && uidA1 > uidB1) ||
- (a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 == b.m_pProxy1 && a.m_algorithm > b.m_algorithm);
- }
+public:
+ bool operator()(const btBroadphasePair& a, const btBroadphasePair& b) const
+ {
+ const int uidA0 = a.m_pProxy0 ? a.m_pProxy0->m_uniqueId : -1;
+ const int uidB0 = b.m_pProxy0 ? b.m_pProxy0->m_uniqueId : -1;
+ const int uidA1 = a.m_pProxy1 ? a.m_pProxy1->m_uniqueId : -1;
+ const int uidB1 = b.m_pProxy1 ? b.m_pProxy1->m_uniqueId : -1;
+
+ return uidA0 > uidB0 ||
+ (a.m_pProxy0 == b.m_pProxy0 && uidA1 > uidB1) ||
+ (a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 == b.m_pProxy1 && a.m_algorithm > b.m_algorithm);
+ }
};
-
-SIMD_FORCE_INLINE bool operator==(const btBroadphasePair& a, const btBroadphasePair& b)
+SIMD_FORCE_INLINE bool operator==(const btBroadphasePair& a, const btBroadphasePair& b)
{
- return (a.m_pProxy0 == b.m_pProxy0) && (a.m_pProxy1 == b.m_pProxy1);
+ return (a.m_pProxy0 == b.m_pProxy0) && (a.m_pProxy1 == b.m_pProxy1);
}
-
-#endif //BT_BROADPHASE_PROXY_H
-
+#endif //BT_BROADPHASE_PROXY_H
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp
index c95d1be0f2..6e36d3bd73 100644
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp
+++ b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp
@@ -20,4 +20,3 @@ btCollisionAlgorithm::btCollisionAlgorithm(const btCollisionAlgorithmConstructio
{
m_dispatcher = ci.m_dispatcher1;
}
-
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h
index 405656236b..b00c0b1b4b 100644
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h
+++ b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h
@@ -25,57 +25,51 @@ class btManifoldResult;
class btCollisionObject;
struct btCollisionObjectWrapper;
struct btDispatcherInfo;
-class btPersistentManifold;
+class btPersistentManifold;
-typedef btAlignedObjectArray<btPersistentManifold*> btManifoldArray;
+typedef btAlignedObjectArray<btPersistentManifold*> btManifoldArray;
struct btCollisionAlgorithmConstructionInfo
{
btCollisionAlgorithmConstructionInfo()
- :m_dispatcher1(0),
- m_manifold(0)
+ : m_dispatcher1(0),
+ m_manifold(0)
{
}
- btCollisionAlgorithmConstructionInfo(btDispatcher* dispatcher,int temp)
- :m_dispatcher1(dispatcher)
+ btCollisionAlgorithmConstructionInfo(btDispatcher* dispatcher, int temp)
+ : m_dispatcher1(dispatcher)
{
(void)temp;
}
- btDispatcher* m_dispatcher1;
- btPersistentManifold* m_manifold;
-
-// int getDispatcherId();
+ btDispatcher* m_dispatcher1;
+ btPersistentManifold* m_manifold;
+ // int getDispatcherId();
};
-
///btCollisionAlgorithm is an collision interface that is compatible with the Broadphase and btDispatcher.
///It is persistent over frames
class btCollisionAlgorithm
{
-
protected:
-
- btDispatcher* m_dispatcher;
+ btDispatcher* m_dispatcher;
protected:
-// int getDispatcherId();
-
-public:
+ // int getDispatcherId();
- btCollisionAlgorithm() {};
+public:
+ btCollisionAlgorithm(){};
btCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci);
- virtual ~btCollisionAlgorithm() {};
+ virtual ~btCollisionAlgorithm(){};
- virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) = 0;
+ virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut) = 0;
- virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) = 0;
+ virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut) = 0;
- virtual void getAllContactManifolds(btManifoldArray& manifoldArray) = 0;
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray) = 0;
};
-
-#endif //BT_COLLISION_ALGORITHM_H
+#endif //BT_COLLISION_ALGORITHM_H
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvt.cpp b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvt.cpp
index d791d07418..37156fd589 100644
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvt.cpp
+++ b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvt.cpp
@@ -17,210 +17,225 @@ subject to the following restrictions:
#include "btDbvt.h"
//
-typedef btAlignedObjectArray<btDbvtNode*> tNodeArray;
-typedef btAlignedObjectArray<const btDbvtNode*> tConstNodeArray;
+typedef btAlignedObjectArray<btDbvtNode*> tNodeArray;
+typedef btAlignedObjectArray<const btDbvtNode*> tConstNodeArray;
//
struct btDbvtNodeEnumerator : btDbvt::ICollide
{
- tConstNodeArray nodes;
+ tConstNodeArray nodes;
void Process(const btDbvtNode* n) { nodes.push_back(n); }
};
//
-static DBVT_INLINE int indexof(const btDbvtNode* node)
+static DBVT_INLINE int indexof(const btDbvtNode* node)
{
- return(node->parent->childs[1]==node);
+ return (node->parent->childs[1] == node);
}
//
-static DBVT_INLINE btDbvtVolume merge( const btDbvtVolume& a,
+static DBVT_INLINE btDbvtVolume merge(const btDbvtVolume& a,
const btDbvtVolume& b)
{
-#if (DBVT_MERGE_IMPL==DBVT_IMPL_SSE)
- ATTRIBUTE_ALIGNED16( char locals[sizeof(btDbvtAabbMm)]);
- btDbvtVolume* ptr = (btDbvtVolume*) locals;
- btDbvtVolume& res=*ptr;
+#if (DBVT_MERGE_IMPL == DBVT_IMPL_SSE)
+ ATTRIBUTE_ALIGNED16(char locals[sizeof(btDbvtAabbMm)]);
+ btDbvtVolume* ptr = (btDbvtVolume*)locals;
+ btDbvtVolume& res = *ptr;
#else
- btDbvtVolume res;
+ btDbvtVolume res;
#endif
- Merge(a,b,res);
- return(res);
+ Merge(a, b, res);
+ return (res);
}
// volume+edge lengths
-static DBVT_INLINE btScalar size(const btDbvtVolume& a)
+static DBVT_INLINE btScalar size(const btDbvtVolume& a)
{
- const btVector3 edges=a.Lengths();
- return( edges.x()*edges.y()*edges.z()+
- edges.x()+edges.y()+edges.z());
+ const btVector3 edges = a.Lengths();
+ return (edges.x() * edges.y() * edges.z() +
+ edges.x() + edges.y() + edges.z());
}
//
-static void getmaxdepth(const btDbvtNode* node,int depth,int& maxdepth)
+static void getmaxdepth(const btDbvtNode* node, int depth, int& maxdepth)
{
- if(node->isinternal())
+ if (node->isinternal())
{
- getmaxdepth(node->childs[0],depth+1,maxdepth);
- getmaxdepth(node->childs[1],depth+1,maxdepth);
- } else maxdepth=btMax(maxdepth,depth);
+ getmaxdepth(node->childs[0], depth + 1, maxdepth);
+ getmaxdepth(node->childs[1], depth + 1, maxdepth);
+ }
+ else
+ maxdepth = btMax(maxdepth, depth);
}
//
-static DBVT_INLINE void deletenode( btDbvt* pdbvt,
- btDbvtNode* node)
+static DBVT_INLINE void deletenode(btDbvt* pdbvt,
+ btDbvtNode* node)
{
btAlignedFree(pdbvt->m_free);
- pdbvt->m_free=node;
+ pdbvt->m_free = node;
}
//
-static void recursedeletenode( btDbvt* pdbvt,
- btDbvtNode* node)
+static void recursedeletenode(btDbvt* pdbvt,
+ btDbvtNode* node)
{
- if(!node->isleaf())
+ if (!node->isleaf())
{
- recursedeletenode(pdbvt,node->childs[0]);
- recursedeletenode(pdbvt,node->childs[1]);
+ recursedeletenode(pdbvt, node->childs[0]);
+ recursedeletenode(pdbvt, node->childs[1]);
}
- if(node==pdbvt->m_root) pdbvt->m_root=0;
- deletenode(pdbvt,node);
+ if (node == pdbvt->m_root) pdbvt->m_root = 0;
+ deletenode(pdbvt, node);
}
//
-static DBVT_INLINE btDbvtNode* createnode( btDbvt* pdbvt,
- btDbvtNode* parent,
- void* data)
+static DBVT_INLINE btDbvtNode* createnode(btDbvt* pdbvt,
+ btDbvtNode* parent,
+ void* data)
{
- btDbvtNode* node;
- if(pdbvt->m_free)
- { node=pdbvt->m_free;pdbvt->m_free=0; }
+ btDbvtNode* node;
+ if (pdbvt->m_free)
+ {
+ node = pdbvt->m_free;
+ pdbvt->m_free = 0;
+ }
else
- { node=new(btAlignedAlloc(sizeof(btDbvtNode),16)) btDbvtNode(); }
- node->parent = parent;
- node->data = data;
- node->childs[1] = 0;
- return(node);
+ {
+ node = new (btAlignedAlloc(sizeof(btDbvtNode), 16)) btDbvtNode();
+ }
+ node->parent = parent;
+ node->data = data;
+ node->childs[1] = 0;
+ return (node);
}
//
-static DBVT_INLINE btDbvtNode* createnode( btDbvt* pdbvt,
- btDbvtNode* parent,
- const btDbvtVolume& volume,
- void* data)
+static DBVT_INLINE btDbvtNode* createnode(btDbvt* pdbvt,
+ btDbvtNode* parent,
+ const btDbvtVolume& volume,
+ void* data)
{
- btDbvtNode* node=createnode(pdbvt,parent,data);
- node->volume=volume;
- return(node);
+ btDbvtNode* node = createnode(pdbvt, parent, data);
+ node->volume = volume;
+ return (node);
}
//
-static DBVT_INLINE btDbvtNode* createnode( btDbvt* pdbvt,
- btDbvtNode* parent,
- const btDbvtVolume& volume0,
- const btDbvtVolume& volume1,
- void* data)
+static DBVT_INLINE btDbvtNode* createnode(btDbvt* pdbvt,
+ btDbvtNode* parent,
+ const btDbvtVolume& volume0,
+ const btDbvtVolume& volume1,
+ void* data)
{
- btDbvtNode* node=createnode(pdbvt,parent,data);
- Merge(volume0,volume1,node->volume);
- return(node);
+ btDbvtNode* node = createnode(pdbvt, parent, data);
+ Merge(volume0, volume1, node->volume);
+ return (node);
}
//
-static void insertleaf( btDbvt* pdbvt,
- btDbvtNode* root,
- btDbvtNode* leaf)
+static void insertleaf(btDbvt* pdbvt,
+ btDbvtNode* root,
+ btDbvtNode* leaf)
{
- if(!pdbvt->m_root)
+ if (!pdbvt->m_root)
{
- pdbvt->m_root = leaf;
- leaf->parent = 0;
+ pdbvt->m_root = leaf;
+ leaf->parent = 0;
}
else
{
- if(!root->isleaf())
+ if (!root->isleaf())
{
- do {
- root=root->childs[Select( leaf->volume,
- root->childs[0]->volume,
- root->childs[1]->volume)];
- } while(!root->isleaf());
+ do
+ {
+ root = root->childs[Select(leaf->volume,
+ root->childs[0]->volume,
+ root->childs[1]->volume)];
+ } while (!root->isleaf());
}
- btDbvtNode* prev=root->parent;
- btDbvtNode* node=createnode(pdbvt,prev,leaf->volume,root->volume,0);
- if(prev)
+ btDbvtNode* prev = root->parent;
+ btDbvtNode* node = createnode(pdbvt, prev, leaf->volume, root->volume, 0);
+ if (prev)
{
- prev->childs[indexof(root)] = node;
- node->childs[0] = root;root->parent=node;
- node->childs[1] = leaf;leaf->parent=node;
- do {
- if(!prev->volume.Contain(node->volume))
- Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume);
+ prev->childs[indexof(root)] = node;
+ node->childs[0] = root;
+ root->parent = node;
+ node->childs[1] = leaf;
+ leaf->parent = node;
+ do
+ {
+ if (!prev->volume.Contain(node->volume))
+ Merge(prev->childs[0]->volume, prev->childs[1]->volume, prev->volume);
else
break;
- node=prev;
- } while(0!=(prev=node->parent));
+ node = prev;
+ } while (0 != (prev = node->parent));
}
else
{
- node->childs[0] = root;root->parent=node;
- node->childs[1] = leaf;leaf->parent=node;
- pdbvt->m_root = node;
+ node->childs[0] = root;
+ root->parent = node;
+ node->childs[1] = leaf;
+ leaf->parent = node;
+ pdbvt->m_root = node;
}
}
}
//
-static btDbvtNode* removeleaf( btDbvt* pdbvt,
- btDbvtNode* leaf)
+static btDbvtNode* removeleaf(btDbvt* pdbvt,
+ btDbvtNode* leaf)
{
- if(leaf==pdbvt->m_root)
+ if (leaf == pdbvt->m_root)
{
- pdbvt->m_root=0;
- return(0);
+ pdbvt->m_root = 0;
+ return (0);
}
else
{
- btDbvtNode* parent=leaf->parent;
- btDbvtNode* prev=parent->parent;
- btDbvtNode* sibling=parent->childs[1-indexof(leaf)];
- if(prev)
+ btDbvtNode* parent = leaf->parent;
+ btDbvtNode* prev = parent->parent;
+ btDbvtNode* sibling = parent->childs[1 - indexof(leaf)];
+ if (prev)
{
- prev->childs[indexof(parent)]=sibling;
- sibling->parent=prev;
- deletenode(pdbvt,parent);
- while(prev)
+ prev->childs[indexof(parent)] = sibling;
+ sibling->parent = prev;
+ deletenode(pdbvt, parent);
+ while (prev)
{
- const btDbvtVolume pb=prev->volume;
- Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume);
- if(NotEqual(pb,prev->volume))
+ const btDbvtVolume pb = prev->volume;
+ Merge(prev->childs[0]->volume, prev->childs[1]->volume, prev->volume);
+ if (NotEqual(pb, prev->volume))
{
- prev=prev->parent;
- } else break;
+ prev = prev->parent;
+ }
+ else
+ break;
}
- return(prev?prev:pdbvt->m_root);
+ return (prev ? prev : pdbvt->m_root);
}
else
- {
- pdbvt->m_root=sibling;
- sibling->parent=0;
- deletenode(pdbvt,parent);
- return(pdbvt->m_root);
- }
+ {
+ pdbvt->m_root = sibling;
+ sibling->parent = 0;
+ deletenode(pdbvt, parent);
+ return (pdbvt->m_root);
+ }
}
}
//
-static void fetchleaves(btDbvt* pdbvt,
- btDbvtNode* root,
- tNodeArray& leaves,
- int depth=-1)
+static void fetchleaves(btDbvt* pdbvt,
+ btDbvtNode* root,
+ tNodeArray& leaves,
+ int depth = -1)
{
- if(root->isinternal()&&depth)
+ if (root->isinternal() && depth)
{
- fetchleaves(pdbvt,root->childs[0],leaves,depth-1);
- fetchleaves(pdbvt,root->childs[1],leaves,depth-1);
- deletenode(pdbvt,root);
+ fetchleaves(pdbvt, root->childs[0], leaves, depth - 1);
+ fetchleaves(pdbvt, root->childs[1], leaves, depth - 1);
+ deletenode(pdbvt, root);
}
else
{
@@ -229,51 +244,50 @@ static void fetchleaves(btDbvt* pdbvt,
}
//
-static bool leftOfAxis( const btDbvtNode* node,
- const btVector3& org,
- const btVector3& axis)
+static bool leftOfAxis(const btDbvtNode* node,
+ const btVector3& org,
+ const btVector3& axis)
{
return btDot(axis, node->volume.Center() - org) <= 0;
}
-
// Partitions leaves such that leaves[0, n) are on the
// left of axis, and leaves[n, count) are on the right
// of axis. returns N.
-static int split( btDbvtNode** leaves,
- int count,
- const btVector3& org,
- const btVector3& axis)
+static int split(btDbvtNode** leaves,
+ int count,
+ const btVector3& org,
+ const btVector3& axis)
{
- int begin=0;
- int end=count;
- for(;;)
+ int begin = 0;
+ int end = count;
+ for (;;)
{
- while(begin!=end && leftOfAxis(leaves[begin],org,axis))
+ while (begin != end && leftOfAxis(leaves[begin], org, axis))
{
++begin;
}
- if(begin==end)
+ if (begin == end)
{
break;
}
- while(begin!=end && !leftOfAxis(leaves[end-1],org,axis))
+ while (begin != end && !leftOfAxis(leaves[end - 1], org, axis))
{
--end;
}
- if(begin==end)
+ if (begin == end)
{
break;
}
// swap out of place nodes
--end;
- btDbvtNode* temp=leaves[begin];
- leaves[begin]=leaves[end];
- leaves[end]=temp;
+ btDbvtNode* temp = leaves[begin];
+ leaves[begin] = leaves[end];
+ leaves[end] = temp;
++begin;
}
@@ -281,150 +295,153 @@ static int split( btDbvtNode** leaves,
}
//
-static btDbvtVolume bounds( btDbvtNode** leaves,
- int count)
+static btDbvtVolume bounds(btDbvtNode** leaves,
+ int count)
{
-#if DBVT_MERGE_IMPL==DBVT_IMPL_SSE
- ATTRIBUTE_ALIGNED16(char locals[sizeof(btDbvtVolume)]);
- btDbvtVolume* ptr = (btDbvtVolume*) locals;
- btDbvtVolume& volume=*ptr;
- volume=leaves[0]->volume;
+#if DBVT_MERGE_IMPL == DBVT_IMPL_SSE
+ ATTRIBUTE_ALIGNED16(char locals[sizeof(btDbvtVolume)]);
+ btDbvtVolume* ptr = (btDbvtVolume*)locals;
+ btDbvtVolume& volume = *ptr;
+ volume = leaves[0]->volume;
#else
- btDbvtVolume volume=leaves[0]->volume;
+ btDbvtVolume volume = leaves[0]->volume;
#endif
- for(int i=1,ni=count;i<ni;++i)
+ for (int i = 1, ni = count; i < ni; ++i)
{
- Merge(volume,leaves[i]->volume,volume);
+ Merge(volume, leaves[i]->volume, volume);
}
- return(volume);
+ return (volume);
}
//
-static void bottomup( btDbvt* pdbvt,
- btDbvtNode** leaves,
- int count)
+static void bottomup(btDbvt* pdbvt,
+ btDbvtNode** leaves,
+ int count)
{
- while(count>1)
+ while (count > 1)
{
- btScalar minsize=SIMD_INFINITY;
- int minidx[2]={-1,-1};
- for(int i=0;i<count;++i)
+ btScalar minsize = SIMD_INFINITY;
+ int minidx[2] = {-1, -1};
+ for (int i = 0; i < count; ++i)
{
- for(int j=i+1;j<count;++j)
+ for (int j = i + 1; j < count; ++j)
{
- const btScalar sz=size(merge(leaves[i]->volume,leaves[j]->volume));
- if(sz<minsize)
+ const btScalar sz = size(merge(leaves[i]->volume, leaves[j]->volume));
+ if (sz < minsize)
{
- minsize = sz;
- minidx[0] = i;
- minidx[1] = j;
+ minsize = sz;
+ minidx[0] = i;
+ minidx[1] = j;
}
}
}
- btDbvtNode* n[] = {leaves[minidx[0]],leaves[minidx[1]]};
- btDbvtNode* p = createnode(pdbvt,0,n[0]->volume,n[1]->volume,0);
- p->childs[0] = n[0];
- p->childs[1] = n[1];
- n[0]->parent = p;
- n[1]->parent = p;
- leaves[minidx[0]] = p;
- leaves[minidx[1]] = leaves[count-1];
+ btDbvtNode* n[] = {leaves[minidx[0]], leaves[minidx[1]]};
+ btDbvtNode* p = createnode(pdbvt, 0, n[0]->volume, n[1]->volume, 0);
+ p->childs[0] = n[0];
+ p->childs[1] = n[1];
+ n[0]->parent = p;
+ n[1]->parent = p;
+ leaves[minidx[0]] = p;
+ leaves[minidx[1]] = leaves[count - 1];
--count;
}
}
//
-static btDbvtNode* topdown(btDbvt* pdbvt,
- btDbvtNode** leaves,
- int count,
- int bu_treshold)
+static btDbvtNode* topdown(btDbvt* pdbvt,
+ btDbvtNode** leaves,
+ int count,
+ int bu_treshold)
{
- static const btVector3 axis[]={btVector3(1,0,0),
- btVector3(0,1,0),
- btVector3(0,0,1)};
- btAssert(bu_treshold>2);
- if(count>1)
+ static const btVector3 axis[] = {btVector3(1, 0, 0),
+ btVector3(0, 1, 0),
+ btVector3(0, 0, 1)};
+ btAssert(bu_treshold > 2);
+ if (count > 1)
{
- if(count>bu_treshold)
+ if (count > bu_treshold)
{
- const btDbvtVolume vol=bounds(leaves,count);
- const btVector3 org=vol.Center();
- int partition;
- int bestaxis=-1;
- int bestmidp=count;
- int splitcount[3][2]={{0,0},{0,0},{0,0}};
+ const btDbvtVolume vol = bounds(leaves, count);
+ const btVector3 org = vol.Center();
+ int partition;
+ int bestaxis = -1;
+ int bestmidp = count;
+ int splitcount[3][2] = {{0, 0}, {0, 0}, {0, 0}};
int i;
- for( i=0;i<count;++i)
+ for (i = 0; i < count; ++i)
{
- const btVector3 x=leaves[i]->volume.Center()-org;
- for(int j=0;j<3;++j)
+ const btVector3 x = leaves[i]->volume.Center() - org;
+ for (int j = 0; j < 3; ++j)
{
- ++splitcount[j][btDot(x,axis[j])>0?1:0];
+ ++splitcount[j][btDot(x, axis[j]) > 0 ? 1 : 0];
}
}
- for( i=0;i<3;++i)
+ for (i = 0; i < 3; ++i)
{
- if((splitcount[i][0]>0)&&(splitcount[i][1]>0))
+ if ((splitcount[i][0] > 0) && (splitcount[i][1] > 0))
{
- const int midp=(int)btFabs(btScalar(splitcount[i][0]-splitcount[i][1]));
- if(midp<bestmidp)
+ const int midp = (int)btFabs(btScalar(splitcount[i][0] - splitcount[i][1]));
+ if (midp < bestmidp)
{
- bestaxis=i;
- bestmidp=midp;
+ bestaxis = i;
+ bestmidp = midp;
}
}
}
- if(bestaxis>=0)
+ if (bestaxis >= 0)
{
- partition=split(leaves,count,org,axis[bestaxis]);
- btAssert(partition!=0 && partition!=count);
+ partition = split(leaves, count, org, axis[bestaxis]);
+ btAssert(partition != 0 && partition != count);
}
else
{
- partition=count/2+1;
+ partition = count / 2 + 1;
}
- btDbvtNode* node=createnode(pdbvt,0,vol,0);
- node->childs[0]=topdown(pdbvt,&leaves[0],partition,bu_treshold);
- node->childs[1]=topdown(pdbvt,&leaves[partition],count-partition,bu_treshold);
- node->childs[0]->parent=node;
- node->childs[1]->parent=node;
- return(node);
+ btDbvtNode* node = createnode(pdbvt, 0, vol, 0);
+ node->childs[0] = topdown(pdbvt, &leaves[0], partition, bu_treshold);
+ node->childs[1] = topdown(pdbvt, &leaves[partition], count - partition, bu_treshold);
+ node->childs[0]->parent = node;
+ node->childs[1]->parent = node;
+ return (node);
}
else
{
- bottomup(pdbvt,leaves,count);
- return(leaves[0]);
+ bottomup(pdbvt, leaves, count);
+ return (leaves[0]);
}
}
- return(leaves[0]);
+ return (leaves[0]);
}
//
-static DBVT_INLINE btDbvtNode* sort(btDbvtNode* n,btDbvtNode*& r)
+static DBVT_INLINE btDbvtNode* sort(btDbvtNode* n, btDbvtNode*& r)
{
- btDbvtNode* p=n->parent;
+ btDbvtNode* p = n->parent;
btAssert(n->isinternal());
- if(p>n)
+ if (p > n)
{
- const int i=indexof(n);
- const int j=1-i;
- btDbvtNode* s=p->childs[j];
- btDbvtNode* q=p->parent;
- btAssert(n==p->childs[i]);
- if(q) q->childs[indexof(p)]=n; else r=n;
- s->parent=n;
- p->parent=n;
- n->parent=q;
- p->childs[0]=n->childs[0];
- p->childs[1]=n->childs[1];
- n->childs[0]->parent=p;
- n->childs[1]->parent=p;
- n->childs[i]=p;
- n->childs[j]=s;
- btSwap(p->volume,n->volume);
- return(p);
+ const int i = indexof(n);
+ const int j = 1 - i;
+ btDbvtNode* s = p->childs[j];
+ btDbvtNode* q = p->parent;
+ btAssert(n == p->childs[i]);
+ if (q)
+ q->childs[indexof(p)] = n;
+ else
+ r = n;
+ s->parent = n;
+ p->parent = n;
+ n->parent = q;
+ p->childs[0] = n->childs[0];
+ p->childs[1] = n->childs[1];
+ n->childs[0]->parent = p;
+ n->childs[1]->parent = p;
+ n->childs[i] = p;
+ n->childs[j] = s;
+ btSwap(p->volume, n->volume);
+ return (p);
}
- return(n);
+ return (n);
}
#if 0
@@ -442,11 +459,11 @@ static DBVT_INLINE btDbvtNode* walkup(btDbvtNode* n,int count)
//
btDbvt::btDbvt()
{
- m_root = 0;
- m_free = 0;
- m_lkhd = -1;
- m_leaves = 0;
- m_opath = 0;
+ m_root = 0;
+ m_free = 0;
+ m_lkhd = -1;
+ m_leaves = 0;
+ m_opath = 0;
}
//
@@ -456,228 +473,233 @@ btDbvt::~btDbvt()
}
//
-void btDbvt::clear()
+void btDbvt::clear()
{
- if(m_root)
- recursedeletenode(this,m_root);
+ if (m_root)
+ recursedeletenode(this, m_root);
btAlignedFree(m_free);
- m_free=0;
- m_lkhd = -1;
+ m_free = 0;
+ m_lkhd = -1;
m_stkStack.clear();
- m_opath = 0;
-
+ m_opath = 0;
}
//
-void btDbvt::optimizeBottomUp()
+void btDbvt::optimizeBottomUp()
{
- if(m_root)
+ if (m_root)
{
tNodeArray leaves;
leaves.reserve(m_leaves);
- fetchleaves(this,m_root,leaves);
- bottomup(this,&leaves[0],leaves.size());
- m_root=leaves[0];
+ fetchleaves(this, m_root, leaves);
+ bottomup(this, &leaves[0], leaves.size());
+ m_root = leaves[0];
}
}
//
-void btDbvt::optimizeTopDown(int bu_treshold)
+void btDbvt::optimizeTopDown(int bu_treshold)
{
- if(m_root)
+ if (m_root)
{
- tNodeArray leaves;
+ tNodeArray leaves;
leaves.reserve(m_leaves);
- fetchleaves(this,m_root,leaves);
- m_root=topdown(this,&leaves[0],leaves.size(),bu_treshold);
+ fetchleaves(this, m_root, leaves);
+ m_root = topdown(this, &leaves[0], leaves.size(), bu_treshold);
}
}
//
-void btDbvt::optimizeIncremental(int passes)
+void btDbvt::optimizeIncremental(int passes)
{
- if(passes<0) passes=m_leaves;
- if(m_root&&(passes>0))
+ if (passes < 0) passes = m_leaves;
+ if (m_root && (passes > 0))
{
- do {
- btDbvtNode* node=m_root;
- unsigned bit=0;
- while(node->isinternal())
+ do
+ {
+ btDbvtNode* node = m_root;
+ unsigned bit = 0;
+ while (node->isinternal())
{
- node=sort(node,m_root)->childs[(m_opath>>bit)&1];
- bit=(bit+1)&(sizeof(unsigned)*8-1);
+ node = sort(node, m_root)->childs[(m_opath >> bit) & 1];
+ bit = (bit + 1) & (sizeof(unsigned) * 8 - 1);
}
update(node);
++m_opath;
- } while(--passes);
+ } while (--passes);
}
}
//
-btDbvtNode* btDbvt::insert(const btDbvtVolume& volume,void* data)
+btDbvtNode* btDbvt::insert(const btDbvtVolume& volume, void* data)
{
- btDbvtNode* leaf=createnode(this,0,volume,data);
- insertleaf(this,m_root,leaf);
+ btDbvtNode* leaf = createnode(this, 0, volume, data);
+ insertleaf(this, m_root, leaf);
++m_leaves;
- return(leaf);
+ return (leaf);
}
//
-void btDbvt::update(btDbvtNode* leaf,int lookahead)
+void btDbvt::update(btDbvtNode* leaf, int lookahead)
{
- btDbvtNode* root=removeleaf(this,leaf);
- if(root)
+ btDbvtNode* root = removeleaf(this, leaf);
+ if (root)
{
- if(lookahead>=0)
+ if (lookahead >= 0)
{
- for(int i=0;(i<lookahead)&&root->parent;++i)
+ for (int i = 0; (i < lookahead) && root->parent; ++i)
{
- root=root->parent;
+ root = root->parent;
}
- } else root=m_root;
+ }
+ else
+ root = m_root;
}
- insertleaf(this,root,leaf);
+ insertleaf(this, root, leaf);
}
//
-void btDbvt::update(btDbvtNode* leaf,btDbvtVolume& volume)
+void btDbvt::update(btDbvtNode* leaf, btDbvtVolume& volume)
{
- btDbvtNode* root=removeleaf(this,leaf);
- if(root)
+ btDbvtNode* root = removeleaf(this, leaf);
+ if (root)
{
- if(m_lkhd>=0)
+ if (m_lkhd >= 0)
{
- for(int i=0;(i<m_lkhd)&&root->parent;++i)
+ for (int i = 0; (i < m_lkhd) && root->parent; ++i)
{
- root=root->parent;
+ root = root->parent;
}
- } else root=m_root;
+ }
+ else
+ root = m_root;
}
- leaf->volume=volume;
- insertleaf(this,root,leaf);
+ leaf->volume = volume;
+ insertleaf(this, root, leaf);
}
//
-bool btDbvt::update(btDbvtNode* leaf,btDbvtVolume& volume,const btVector3& velocity,btScalar margin)
+bool btDbvt::update(btDbvtNode* leaf, btDbvtVolume& volume, const btVector3& velocity, btScalar margin)
{
- if(leaf->volume.Contain(volume)) return(false);
- volume.Expand(btVector3(margin,margin,margin));
+ if (leaf->volume.Contain(volume)) return (false);
+ volume.Expand(btVector3(margin, margin, margin));
volume.SignedExpand(velocity);
- update(leaf,volume);
- return(true);
+ update(leaf, volume);
+ return (true);
}
//
-bool btDbvt::update(btDbvtNode* leaf,btDbvtVolume& volume,const btVector3& velocity)
+bool btDbvt::update(btDbvtNode* leaf, btDbvtVolume& volume, const btVector3& velocity)
{
- if(leaf->volume.Contain(volume)) return(false);
+ if (leaf->volume.Contain(volume)) return (false);
volume.SignedExpand(velocity);
- update(leaf,volume);
- return(true);
+ update(leaf, volume);
+ return (true);
}
//
-bool btDbvt::update(btDbvtNode* leaf,btDbvtVolume& volume,btScalar margin)
+bool btDbvt::update(btDbvtNode* leaf, btDbvtVolume& volume, btScalar margin)
{
- if(leaf->volume.Contain(volume)) return(false);
- volume.Expand(btVector3(margin,margin,margin));
- update(leaf,volume);
- return(true);
+ if (leaf->volume.Contain(volume)) return (false);
+ volume.Expand(btVector3(margin, margin, margin));
+ update(leaf, volume);
+ return (true);
}
//
-void btDbvt::remove(btDbvtNode* leaf)
+void btDbvt::remove(btDbvtNode* leaf)
{
- removeleaf(this,leaf);
- deletenode(this,leaf);
+ removeleaf(this, leaf);
+ deletenode(this, leaf);
--m_leaves;
}
//
-void btDbvt::write(IWriter* iwriter) const
+void btDbvt::write(IWriter* iwriter) const
{
- btDbvtNodeEnumerator nodes;
- nodes.nodes.reserve(m_leaves*2);
- enumNodes(m_root,nodes);
- iwriter->Prepare(m_root,nodes.nodes.size());
- for(int i=0;i<nodes.nodes.size();++i)
+ btDbvtNodeEnumerator nodes;
+ nodes.nodes.reserve(m_leaves * 2);
+ enumNodes(m_root, nodes);
+ iwriter->Prepare(m_root, nodes.nodes.size());
+ for (int i = 0; i < nodes.nodes.size(); ++i)
{
- const btDbvtNode* n=nodes.nodes[i];
- int p=-1;
- if(n->parent) p=nodes.nodes.findLinearSearch(n->parent);
- if(n->isinternal())
+ const btDbvtNode* n = nodes.nodes[i];
+ int p = -1;
+ if (n->parent) p = nodes.nodes.findLinearSearch(n->parent);
+ if (n->isinternal())
{
- const int c0=nodes.nodes.findLinearSearch(n->childs[0]);
- const int c1=nodes.nodes.findLinearSearch(n->childs[1]);
- iwriter->WriteNode(n,i,p,c0,c1);
+ const int c0 = nodes.nodes.findLinearSearch(n->childs[0]);
+ const int c1 = nodes.nodes.findLinearSearch(n->childs[1]);
+ iwriter->WriteNode(n, i, p, c0, c1);
}
else
{
- iwriter->WriteLeaf(n,i,p);
- }
+ iwriter->WriteLeaf(n, i, p);
+ }
}
}
//
-void btDbvt::clone(btDbvt& dest,IClone* iclone) const
+void btDbvt::clone(btDbvt& dest, IClone* iclone) const
{
dest.clear();
- if(m_root!=0)
- {
- btAlignedObjectArray<sStkCLN> stack;
+ if (m_root != 0)
+ {
+ btAlignedObjectArray<sStkCLN> stack;
stack.reserve(m_leaves);
- stack.push_back(sStkCLN(m_root,0));
- do {
- const int i=stack.size()-1;
- const sStkCLN e=stack[i];
- btDbvtNode* n=createnode(&dest,e.parent,e.node->volume,e.node->data);
+ stack.push_back(sStkCLN(m_root, 0));
+ do
+ {
+ const int i = stack.size() - 1;
+ const sStkCLN e = stack[i];
+ btDbvtNode* n = createnode(&dest, e.parent, e.node->volume, e.node->data);
stack.pop_back();
- if(e.parent!=0)
- e.parent->childs[i&1]=n;
+ if (e.parent != 0)
+ e.parent->childs[i & 1] = n;
else
- dest.m_root=n;
- if(e.node->isinternal())
+ dest.m_root = n;
+ if (e.node->isinternal())
{
- stack.push_back(sStkCLN(e.node->childs[0],n));
- stack.push_back(sStkCLN(e.node->childs[1],n));
+ stack.push_back(sStkCLN(e.node->childs[0], n));
+ stack.push_back(sStkCLN(e.node->childs[1], n));
}
else
{
iclone->CloneLeaf(n);
}
- } while(stack.size()>0);
+ } while (stack.size() > 0);
}
}
//
-int btDbvt::maxdepth(const btDbvtNode* node)
+int btDbvt::maxdepth(const btDbvtNode* node)
{
- int depth=0;
- if(node) getmaxdepth(node,1,depth);
- return(depth);
+ int depth = 0;
+ if (node) getmaxdepth(node, 1, depth);
+ return (depth);
}
//
-int btDbvt::countLeaves(const btDbvtNode* node)
+int btDbvt::countLeaves(const btDbvtNode* node)
{
- if(node->isinternal())
- return(countLeaves(node->childs[0])+countLeaves(node->childs[1]));
+ if (node->isinternal())
+ return (countLeaves(node->childs[0]) + countLeaves(node->childs[1]));
else
- return(1);
+ return (1);
}
//
-void btDbvt::extractLeaves(const btDbvtNode* node,btAlignedObjectArray<const btDbvtNode*>& leaves)
+void btDbvt::extractLeaves(const btDbvtNode* node, btAlignedObjectArray<const btDbvtNode*>& leaves)
{
- if(node->isinternal())
+ if (node->isinternal())
{
- extractLeaves(node->childs[0],leaves);
- extractLeaves(node->childs[1],leaves);
+ extractLeaves(node->childs[0], leaves);
+ extractLeaves(node->childs[1], leaves);
}
else
{
leaves.push_back(node);
- }
+ }
}
//
@@ -726,603 +748,608 @@ struct btDbvtBenchmark
{
struct NilPolicy : btDbvt::ICollide
{
- NilPolicy() : m_pcount(0),m_depth(-SIMD_INFINITY),m_checksort(true) {}
- void Process(const btDbvtNode*,const btDbvtNode*) { ++m_pcount; }
- void Process(const btDbvtNode*) { ++m_pcount; }
- void Process(const btDbvtNode*,btScalar depth)
+ NilPolicy() : m_pcount(0), m_depth(-SIMD_INFINITY), m_checksort(true) {}
+ void Process(const btDbvtNode*, const btDbvtNode*) { ++m_pcount; }
+ void Process(const btDbvtNode*) { ++m_pcount; }
+ void Process(const btDbvtNode*, btScalar depth)
{
++m_pcount;
- if(m_checksort)
- { if(depth>=m_depth) m_depth=depth; else printf("wrong depth: %f (should be >= %f)\r\n",depth,m_depth); }
+ if (m_checksort)
+ {
+ if (depth >= m_depth)
+ m_depth = depth;
+ else
+ printf("wrong depth: %f (should be >= %f)\r\n", depth, m_depth);
+ }
}
- int m_pcount;
- btScalar m_depth;
- bool m_checksort;
+ int m_pcount;
+ btScalar m_depth;
+ bool m_checksort;
};
struct P14 : btDbvt::ICollide
{
struct Node
{
- const btDbvtNode* leaf;
- btScalar depth;
+ const btDbvtNode* leaf;
+ btScalar depth;
};
- void Process(const btDbvtNode* leaf,btScalar depth)
+ void Process(const btDbvtNode* leaf, btScalar depth)
{
- Node n;
- n.leaf = leaf;
- n.depth = depth;
+ Node n;
+ n.leaf = leaf;
+ n.depth = depth;
}
- static int sortfnc(const Node& a,const Node& b)
+ static int sortfnc(const Node& a, const Node& b)
{
- if(a.depth<b.depth) return(+1);
- if(a.depth>b.depth) return(-1);
- return(0);
+ if (a.depth < b.depth) return (+1);
+ if (a.depth > b.depth) return (-1);
+ return (0);
}
- btAlignedObjectArray<Node> m_nodes;
+ btAlignedObjectArray<Node> m_nodes;
};
struct P15 : btDbvt::ICollide
{
struct Node
{
- const btDbvtNode* leaf;
- btScalar depth;
+ const btDbvtNode* leaf;
+ btScalar depth;
};
void Process(const btDbvtNode* leaf)
{
- Node n;
- n.leaf = leaf;
- n.depth = dot(leaf->volume.Center(),m_axis);
+ Node n;
+ n.leaf = leaf;
+ n.depth = dot(leaf->volume.Center(), m_axis);
}
- static int sortfnc(const Node& a,const Node& b)
+ static int sortfnc(const Node& a, const Node& b)
{
- if(a.depth<b.depth) return(+1);
- if(a.depth>b.depth) return(-1);
- return(0);
+ if (a.depth < b.depth) return (+1);
+ if (a.depth > b.depth) return (-1);
+ return (0);
}
- btAlignedObjectArray<Node> m_nodes;
- btVector3 m_axis;
+ btAlignedObjectArray<Node> m_nodes;
+ btVector3 m_axis;
};
- static btScalar RandUnit()
+ static btScalar RandUnit()
{
- return(rand()/(btScalar)RAND_MAX);
+ return (rand() / (btScalar)RAND_MAX);
}
- static btVector3 RandVector3()
+ static btVector3 RandVector3()
{
- return(btVector3(RandUnit(),RandUnit(),RandUnit()));
+ return (btVector3(RandUnit(), RandUnit(), RandUnit()));
}
- static btVector3 RandVector3(btScalar cs)
+ static btVector3 RandVector3(btScalar cs)
{
- return(RandVector3()*cs-btVector3(cs,cs,cs)/2);
+ return (RandVector3() * cs - btVector3(cs, cs, cs) / 2);
}
- static btDbvtVolume RandVolume(btScalar cs,btScalar eb,btScalar es)
+ static btDbvtVolume RandVolume(btScalar cs, btScalar eb, btScalar es)
{
- return(btDbvtVolume::FromCE(RandVector3(cs),btVector3(eb,eb,eb)+RandVector3()*es));
+ return (btDbvtVolume::FromCE(RandVector3(cs), btVector3(eb, eb, eb) + RandVector3() * es));
}
- static btTransform RandTransform(btScalar cs)
+ static btTransform RandTransform(btScalar cs)
{
- btTransform t;
+ btTransform t;
t.setOrigin(RandVector3(cs));
- t.setRotation(btQuaternion(RandUnit()*SIMD_PI*2,RandUnit()*SIMD_PI*2,RandUnit()*SIMD_PI*2).normalized());
- return(t);
+ t.setRotation(btQuaternion(RandUnit() * SIMD_PI * 2, RandUnit() * SIMD_PI * 2, RandUnit() * SIMD_PI * 2).normalized());
+ return (t);
}
- static void RandTree(btScalar cs,btScalar eb,btScalar es,int leaves,btDbvt& dbvt)
+ static void RandTree(btScalar cs, btScalar eb, btScalar es, int leaves, btDbvt& dbvt)
{
dbvt.clear();
- for(int i=0;i<leaves;++i)
+ for (int i = 0; i < leaves; ++i)
{
- dbvt.insert(RandVolume(cs,eb,es),0);
+ dbvt.insert(RandVolume(cs, eb, es), 0);
}
}
};
-void btDbvt::benchmark()
+void btDbvt::benchmark()
{
- static const btScalar cfgVolumeCenterScale = 100;
- static const btScalar cfgVolumeExentsBase = 1;
- static const btScalar cfgVolumeExentsScale = 4;
- static const int cfgLeaves = 8192;
- static const bool cfgEnable = true;
+ static const btScalar cfgVolumeCenterScale = 100;
+ static const btScalar cfgVolumeExentsBase = 1;
+ static const btScalar cfgVolumeExentsScale = 4;
+ static const int cfgLeaves = 8192;
+ static const bool cfgEnable = true;
//[1] btDbvtVolume intersections
- bool cfgBenchmark1_Enable = cfgEnable;
- static const int cfgBenchmark1_Iterations = 8;
- static const int cfgBenchmark1_Reference = 3499;
+ bool cfgBenchmark1_Enable = cfgEnable;
+ static const int cfgBenchmark1_Iterations = 8;
+ static const int cfgBenchmark1_Reference = 3499;
//[2] btDbvtVolume merges
- bool cfgBenchmark2_Enable = cfgEnable;
- static const int cfgBenchmark2_Iterations = 4;
- static const int cfgBenchmark2_Reference = 1945;
+ bool cfgBenchmark2_Enable = cfgEnable;
+ static const int cfgBenchmark2_Iterations = 4;
+ static const int cfgBenchmark2_Reference = 1945;
//[3] btDbvt::collideTT
- bool cfgBenchmark3_Enable = cfgEnable;
- static const int cfgBenchmark3_Iterations = 512;
- static const int cfgBenchmark3_Reference = 5485;
+ bool cfgBenchmark3_Enable = cfgEnable;
+ static const int cfgBenchmark3_Iterations = 512;
+ static const int cfgBenchmark3_Reference = 5485;
//[4] btDbvt::collideTT self
- bool cfgBenchmark4_Enable = cfgEnable;
- static const int cfgBenchmark4_Iterations = 512;
- static const int cfgBenchmark4_Reference = 2814;
+ bool cfgBenchmark4_Enable = cfgEnable;
+ static const int cfgBenchmark4_Iterations = 512;
+ static const int cfgBenchmark4_Reference = 2814;
//[5] btDbvt::collideTT xform
- bool cfgBenchmark5_Enable = cfgEnable;
- static const int cfgBenchmark5_Iterations = 512;
- static const btScalar cfgBenchmark5_OffsetScale = 2;
- static const int cfgBenchmark5_Reference = 7379;
+ bool cfgBenchmark5_Enable = cfgEnable;
+ static const int cfgBenchmark5_Iterations = 512;
+ static const btScalar cfgBenchmark5_OffsetScale = 2;
+ static const int cfgBenchmark5_Reference = 7379;
//[6] btDbvt::collideTT xform,self
- bool cfgBenchmark6_Enable = cfgEnable;
- static const int cfgBenchmark6_Iterations = 512;
- static const btScalar cfgBenchmark6_OffsetScale = 2;
- static const int cfgBenchmark6_Reference = 7270;
+ bool cfgBenchmark6_Enable = cfgEnable;
+ static const int cfgBenchmark6_Iterations = 512;
+ static const btScalar cfgBenchmark6_OffsetScale = 2;
+ static const int cfgBenchmark6_Reference = 7270;
//[7] btDbvt::rayTest
- bool cfgBenchmark7_Enable = cfgEnable;
- static const int cfgBenchmark7_Passes = 32;
- static const int cfgBenchmark7_Iterations = 65536;
- static const int cfgBenchmark7_Reference = 6307;
+ bool cfgBenchmark7_Enable = cfgEnable;
+ static const int cfgBenchmark7_Passes = 32;
+ static const int cfgBenchmark7_Iterations = 65536;
+ static const int cfgBenchmark7_Reference = 6307;
//[8] insert/remove
- bool cfgBenchmark8_Enable = cfgEnable;
- static const int cfgBenchmark8_Passes = 32;
- static const int cfgBenchmark8_Iterations = 65536;
- static const int cfgBenchmark8_Reference = 2105;
+ bool cfgBenchmark8_Enable = cfgEnable;
+ static const int cfgBenchmark8_Passes = 32;
+ static const int cfgBenchmark8_Iterations = 65536;
+ static const int cfgBenchmark8_Reference = 2105;
//[9] updates (teleport)
- bool cfgBenchmark9_Enable = cfgEnable;
- static const int cfgBenchmark9_Passes = 32;
- static const int cfgBenchmark9_Iterations = 65536;
- static const int cfgBenchmark9_Reference = 1879;
+ bool cfgBenchmark9_Enable = cfgEnable;
+ static const int cfgBenchmark9_Passes = 32;
+ static const int cfgBenchmark9_Iterations = 65536;
+ static const int cfgBenchmark9_Reference = 1879;
//[10] updates (jitter)
- bool cfgBenchmark10_Enable = cfgEnable;
- static const btScalar cfgBenchmark10_Scale = cfgVolumeCenterScale/10000;
- static const int cfgBenchmark10_Passes = 32;
- static const int cfgBenchmark10_Iterations = 65536;
- static const int cfgBenchmark10_Reference = 1244;
+ bool cfgBenchmark10_Enable = cfgEnable;
+ static const btScalar cfgBenchmark10_Scale = cfgVolumeCenterScale / 10000;
+ static const int cfgBenchmark10_Passes = 32;
+ static const int cfgBenchmark10_Iterations = 65536;
+ static const int cfgBenchmark10_Reference = 1244;
//[11] optimize (incremental)
- bool cfgBenchmark11_Enable = cfgEnable;
- static const int cfgBenchmark11_Passes = 64;
- static const int cfgBenchmark11_Iterations = 65536;
- static const int cfgBenchmark11_Reference = 2510;
+ bool cfgBenchmark11_Enable = cfgEnable;
+ static const int cfgBenchmark11_Passes = 64;
+ static const int cfgBenchmark11_Iterations = 65536;
+ static const int cfgBenchmark11_Reference = 2510;
//[12] btDbvtVolume notequal
- bool cfgBenchmark12_Enable = cfgEnable;
- static const int cfgBenchmark12_Iterations = 32;
- static const int cfgBenchmark12_Reference = 3677;
+ bool cfgBenchmark12_Enable = cfgEnable;
+ static const int cfgBenchmark12_Iterations = 32;
+ static const int cfgBenchmark12_Reference = 3677;
//[13] culling(OCL+fullsort)
- bool cfgBenchmark13_Enable = cfgEnable;
- static const int cfgBenchmark13_Iterations = 1024;
- static const int cfgBenchmark13_Reference = 2231;
+ bool cfgBenchmark13_Enable = cfgEnable;
+ static const int cfgBenchmark13_Iterations = 1024;
+ static const int cfgBenchmark13_Reference = 2231;
//[14] culling(OCL+qsort)
- bool cfgBenchmark14_Enable = cfgEnable;
- static const int cfgBenchmark14_Iterations = 8192;
- static const int cfgBenchmark14_Reference = 3500;
+ bool cfgBenchmark14_Enable = cfgEnable;
+ static const int cfgBenchmark14_Iterations = 8192;
+ static const int cfgBenchmark14_Reference = 3500;
//[15] culling(KDOP+qsort)
- bool cfgBenchmark15_Enable = cfgEnable;
- static const int cfgBenchmark15_Iterations = 8192;
- static const int cfgBenchmark15_Reference = 1151;
+ bool cfgBenchmark15_Enable = cfgEnable;
+ static const int cfgBenchmark15_Iterations = 8192;
+ static const int cfgBenchmark15_Reference = 1151;
//[16] insert/remove batch
- bool cfgBenchmark16_Enable = cfgEnable;
- static const int cfgBenchmark16_BatchCount = 256;
- static const int cfgBenchmark16_Passes = 16384;
- static const int cfgBenchmark16_Reference = 5138;
+ bool cfgBenchmark16_Enable = cfgEnable;
+ static const int cfgBenchmark16_BatchCount = 256;
+ static const int cfgBenchmark16_Passes = 16384;
+ static const int cfgBenchmark16_Reference = 5138;
//[17] select
- bool cfgBenchmark17_Enable = cfgEnable;
- static const int cfgBenchmark17_Iterations = 4;
- static const int cfgBenchmark17_Reference = 3390;
+ bool cfgBenchmark17_Enable = cfgEnable;
+ static const int cfgBenchmark17_Iterations = 4;
+ static const int cfgBenchmark17_Reference = 3390;
- btClock wallclock;
+ btClock wallclock;
printf("Benchmarking dbvt...\r\n");
- printf("\tWorld scale: %f\r\n",cfgVolumeCenterScale);
- printf("\tExtents base: %f\r\n",cfgVolumeExentsBase);
- printf("\tExtents range: %f\r\n",cfgVolumeExentsScale);
- printf("\tLeaves: %u\r\n",cfgLeaves);
- printf("\tsizeof(btDbvtVolume): %u bytes\r\n",sizeof(btDbvtVolume));
- printf("\tsizeof(btDbvtNode): %u bytes\r\n",sizeof(btDbvtNode));
- if(cfgBenchmark1_Enable)
- {// Benchmark 1
+ printf("\tWorld scale: %f\r\n", cfgVolumeCenterScale);
+ printf("\tExtents base: %f\r\n", cfgVolumeExentsBase);
+ printf("\tExtents range: %f\r\n", cfgVolumeExentsScale);
+ printf("\tLeaves: %u\r\n", cfgLeaves);
+ printf("\tsizeof(btDbvtVolume): %u bytes\r\n", sizeof(btDbvtVolume));
+ printf("\tsizeof(btDbvtNode): %u bytes\r\n", sizeof(btDbvtNode));
+ if (cfgBenchmark1_Enable)
+ { // Benchmark 1
srand(380843);
- btAlignedObjectArray<btDbvtVolume> volumes;
- btAlignedObjectArray<bool> results;
+ btAlignedObjectArray<btDbvtVolume> volumes;
+ btAlignedObjectArray<bool> results;
volumes.resize(cfgLeaves);
results.resize(cfgLeaves);
- for(int i=0;i<cfgLeaves;++i)
+ for (int i = 0; i < cfgLeaves; ++i)
{
- volumes[i]=btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
+ volumes[i] = btDbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale);
}
printf("[1] btDbvtVolume intersections: ");
wallclock.reset();
- for(int i=0;i<cfgBenchmark1_Iterations;++i)
+ for (int i = 0; i < cfgBenchmark1_Iterations; ++i)
{
- for(int j=0;j<cfgLeaves;++j)
+ for (int j = 0; j < cfgLeaves; ++j)
{
- for(int k=0;k<cfgLeaves;++k)
+ for (int k = 0; k < cfgLeaves; ++k)
{
- results[k]=Intersect(volumes[j],volumes[k]);
+ results[k] = Intersect(volumes[j], volumes[k]);
}
}
}
- const int time=(int)wallclock.getTimeMilliseconds();
- printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark1_Reference)*100/time);
+ const int time = (int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark1_Reference) * 100 / time);
}
- if(cfgBenchmark2_Enable)
- {// Benchmark 2
+ if (cfgBenchmark2_Enable)
+ { // Benchmark 2
srand(380843);
- btAlignedObjectArray<btDbvtVolume> volumes;
- btAlignedObjectArray<btDbvtVolume> results;
+ btAlignedObjectArray<btDbvtVolume> volumes;
+ btAlignedObjectArray<btDbvtVolume> results;
volumes.resize(cfgLeaves);
results.resize(cfgLeaves);
- for(int i=0;i<cfgLeaves;++i)
+ for (int i = 0; i < cfgLeaves; ++i)
{
- volumes[i]=btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
+ volumes[i] = btDbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale);
}
printf("[2] btDbvtVolume merges: ");
wallclock.reset();
- for(int i=0;i<cfgBenchmark2_Iterations;++i)
+ for (int i = 0; i < cfgBenchmark2_Iterations; ++i)
{
- for(int j=0;j<cfgLeaves;++j)
+ for (int j = 0; j < cfgLeaves; ++j)
{
- for(int k=0;k<cfgLeaves;++k)
+ for (int k = 0; k < cfgLeaves; ++k)
{
- Merge(volumes[j],volumes[k],results[k]);
+ Merge(volumes[j], volumes[k], results[k]);
}
}
}
- const int time=(int)wallclock.getTimeMilliseconds();
- printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark2_Reference)*100/time);
+ const int time = (int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark2_Reference) * 100 / time);
}
- if(cfgBenchmark3_Enable)
- {// Benchmark 3
+ if (cfgBenchmark3_Enable)
+ { // Benchmark 3
srand(380843);
- btDbvt dbvt[2];
- btDbvtBenchmark::NilPolicy policy;
- btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[0]);
- btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[1]);
+ btDbvt dbvt[2];
+ btDbvtBenchmark::NilPolicy policy;
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt[0]);
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt[1]);
dbvt[0].optimizeTopDown();
dbvt[1].optimizeTopDown();
printf("[3] btDbvt::collideTT: ");
wallclock.reset();
- for(int i=0;i<cfgBenchmark3_Iterations;++i)
+ for (int i = 0; i < cfgBenchmark3_Iterations; ++i)
{
- btDbvt::collideTT(dbvt[0].m_root,dbvt[1].m_root,policy);
+ btDbvt::collideTT(dbvt[0].m_root, dbvt[1].m_root, policy);
}
- const int time=(int)wallclock.getTimeMilliseconds();
- printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark3_Reference)*100/time);
+ const int time = (int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark3_Reference) * 100 / time);
}
- if(cfgBenchmark4_Enable)
- {// Benchmark 4
+ if (cfgBenchmark4_Enable)
+ { // Benchmark 4
srand(380843);
- btDbvt dbvt;
- btDbvtBenchmark::NilPolicy policy;
- btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ btDbvt dbvt;
+ btDbvtBenchmark::NilPolicy policy;
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
dbvt.optimizeTopDown();
printf("[4] btDbvt::collideTT self: ");
wallclock.reset();
- for(int i=0;i<cfgBenchmark4_Iterations;++i)
+ for (int i = 0; i < cfgBenchmark4_Iterations; ++i)
{
- btDbvt::collideTT(dbvt.m_root,dbvt.m_root,policy);
+ btDbvt::collideTT(dbvt.m_root, dbvt.m_root, policy);
}
- const int time=(int)wallclock.getTimeMilliseconds();
- printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark4_Reference)*100/time);
+ const int time = (int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark4_Reference) * 100 / time);
}
- if(cfgBenchmark5_Enable)
- {// Benchmark 5
+ if (cfgBenchmark5_Enable)
+ { // Benchmark 5
srand(380843);
- btDbvt dbvt[2];
- btAlignedObjectArray<btTransform> transforms;
- btDbvtBenchmark::NilPolicy policy;
+ btDbvt dbvt[2];
+ btAlignedObjectArray<btTransform> transforms;
+ btDbvtBenchmark::NilPolicy policy;
transforms.resize(cfgBenchmark5_Iterations);
- for(int i=0;i<transforms.size();++i)
+ for (int i = 0; i < transforms.size(); ++i)
{
- transforms[i]=btDbvtBenchmark::RandTransform(cfgVolumeCenterScale*cfgBenchmark5_OffsetScale);
+ transforms[i] = btDbvtBenchmark::RandTransform(cfgVolumeCenterScale * cfgBenchmark5_OffsetScale);
}
- btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[0]);
- btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[1]);
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt[0]);
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt[1]);
dbvt[0].optimizeTopDown();
dbvt[1].optimizeTopDown();
printf("[5] btDbvt::collideTT xform: ");
wallclock.reset();
- for(int i=0;i<cfgBenchmark5_Iterations;++i)
+ for (int i = 0; i < cfgBenchmark5_Iterations; ++i)
{
- btDbvt::collideTT(dbvt[0].m_root,dbvt[1].m_root,transforms[i],policy);
+ btDbvt::collideTT(dbvt[0].m_root, dbvt[1].m_root, transforms[i], policy);
}
- const int time=(int)wallclock.getTimeMilliseconds();
- printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark5_Reference)*100/time);
+ const int time = (int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark5_Reference) * 100 / time);
}
- if(cfgBenchmark6_Enable)
- {// Benchmark 6
+ if (cfgBenchmark6_Enable)
+ { // Benchmark 6
srand(380843);
- btDbvt dbvt;
- btAlignedObjectArray<btTransform> transforms;
- btDbvtBenchmark::NilPolicy policy;
+ btDbvt dbvt;
+ btAlignedObjectArray<btTransform> transforms;
+ btDbvtBenchmark::NilPolicy policy;
transforms.resize(cfgBenchmark6_Iterations);
- for(int i=0;i<transforms.size();++i)
+ for (int i = 0; i < transforms.size(); ++i)
{
- transforms[i]=btDbvtBenchmark::RandTransform(cfgVolumeCenterScale*cfgBenchmark6_OffsetScale);
+ transforms[i] = btDbvtBenchmark::RandTransform(cfgVolumeCenterScale * cfgBenchmark6_OffsetScale);
}
- btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
dbvt.optimizeTopDown();
printf("[6] btDbvt::collideTT xform,self: ");
wallclock.reset();
- for(int i=0;i<cfgBenchmark6_Iterations;++i)
+ for (int i = 0; i < cfgBenchmark6_Iterations; ++i)
{
- btDbvt::collideTT(dbvt.m_root,dbvt.m_root,transforms[i],policy);
+ btDbvt::collideTT(dbvt.m_root, dbvt.m_root, transforms[i], policy);
}
- const int time=(int)wallclock.getTimeMilliseconds();
- printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark6_Reference)*100/time);
+ const int time = (int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark6_Reference) * 100 / time);
}
- if(cfgBenchmark7_Enable)
- {// Benchmark 7
+ if (cfgBenchmark7_Enable)
+ { // Benchmark 7
srand(380843);
- btDbvt dbvt;
- btAlignedObjectArray<btVector3> rayorg;
- btAlignedObjectArray<btVector3> raydir;
- btDbvtBenchmark::NilPolicy policy;
+ btDbvt dbvt;
+ btAlignedObjectArray<btVector3> rayorg;
+ btAlignedObjectArray<btVector3> raydir;
+ btDbvtBenchmark::NilPolicy policy;
rayorg.resize(cfgBenchmark7_Iterations);
raydir.resize(cfgBenchmark7_Iterations);
- for(int i=0;i<rayorg.size();++i)
+ for (int i = 0; i < rayorg.size(); ++i)
{
- rayorg[i]=btDbvtBenchmark::RandVector3(cfgVolumeCenterScale*2);
- raydir[i]=btDbvtBenchmark::RandVector3(cfgVolumeCenterScale*2);
+ rayorg[i] = btDbvtBenchmark::RandVector3(cfgVolumeCenterScale * 2);
+ raydir[i] = btDbvtBenchmark::RandVector3(cfgVolumeCenterScale * 2);
}
- btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
dbvt.optimizeTopDown();
printf("[7] btDbvt::rayTest: ");
wallclock.reset();
- for(int i=0;i<cfgBenchmark7_Passes;++i)
+ for (int i = 0; i < cfgBenchmark7_Passes; ++i)
{
- for(int j=0;j<cfgBenchmark7_Iterations;++j)
+ for (int j = 0; j < cfgBenchmark7_Iterations; ++j)
{
- btDbvt::rayTest(dbvt.m_root,rayorg[j],rayorg[j]+raydir[j],policy);
+ btDbvt::rayTest(dbvt.m_root, rayorg[j], rayorg[j] + raydir[j], policy);
}
}
- const int time=(int)wallclock.getTimeMilliseconds();
- unsigned rays=cfgBenchmark7_Passes*cfgBenchmark7_Iterations;
- printf("%u ms (%i%%),(%u r/s)\r\n",time,(time-cfgBenchmark7_Reference)*100/time,(rays*1000)/time);
+ const int time = (int)wallclock.getTimeMilliseconds();
+ unsigned rays = cfgBenchmark7_Passes * cfgBenchmark7_Iterations;
+ printf("%u ms (%i%%),(%u r/s)\r\n", time, (time - cfgBenchmark7_Reference) * 100 / time, (rays * 1000) / time);
}
- if(cfgBenchmark8_Enable)
- {// Benchmark 8
+ if (cfgBenchmark8_Enable)
+ { // Benchmark 8
srand(380843);
- btDbvt dbvt;
- btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ btDbvt dbvt;
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
dbvt.optimizeTopDown();
printf("[8] insert/remove: ");
wallclock.reset();
- for(int i=0;i<cfgBenchmark8_Passes;++i)
+ for (int i = 0; i < cfgBenchmark8_Passes; ++i)
{
- for(int j=0;j<cfgBenchmark8_Iterations;++j)
+ for (int j = 0; j < cfgBenchmark8_Iterations; ++j)
{
- dbvt.remove(dbvt.insert(btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale),0));
+ dbvt.remove(dbvt.insert(btDbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale), 0));
}
}
- const int time=(int)wallclock.getTimeMilliseconds();
- const int ir=cfgBenchmark8_Passes*cfgBenchmark8_Iterations;
- printf("%u ms (%i%%),(%u ir/s)\r\n",time,(time-cfgBenchmark8_Reference)*100/time,ir*1000/time);
+ const int time = (int)wallclock.getTimeMilliseconds();
+ const int ir = cfgBenchmark8_Passes * cfgBenchmark8_Iterations;
+ printf("%u ms (%i%%),(%u ir/s)\r\n", time, (time - cfgBenchmark8_Reference) * 100 / time, ir * 1000 / time);
}
- if(cfgBenchmark9_Enable)
- {// Benchmark 9
+ if (cfgBenchmark9_Enable)
+ { // Benchmark 9
srand(380843);
- btDbvt dbvt;
- btAlignedObjectArray<const btDbvtNode*> leaves;
- btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ btDbvt dbvt;
+ btAlignedObjectArray<const btDbvtNode*> leaves;
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
dbvt.optimizeTopDown();
- dbvt.extractLeaves(dbvt.m_root,leaves);
+ dbvt.extractLeaves(dbvt.m_root, leaves);
printf("[9] updates (teleport): ");
wallclock.reset();
- for(int i=0;i<cfgBenchmark9_Passes;++i)
+ for (int i = 0; i < cfgBenchmark9_Passes; ++i)
{
- for(int j=0;j<cfgBenchmark9_Iterations;++j)
+ for (int j = 0; j < cfgBenchmark9_Iterations; ++j)
{
- dbvt.update(const_cast<btDbvtNode*>(leaves[rand()%cfgLeaves]),
- btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale));
+ dbvt.update(const_cast<btDbvtNode*>(leaves[rand() % cfgLeaves]),
+ btDbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale));
}
}
- const int time=(int)wallclock.getTimeMilliseconds();
- const int up=cfgBenchmark9_Passes*cfgBenchmark9_Iterations;
- printf("%u ms (%i%%),(%u u/s)\r\n",time,(time-cfgBenchmark9_Reference)*100/time,up*1000/time);
+ const int time = (int)wallclock.getTimeMilliseconds();
+ const int up = cfgBenchmark9_Passes * cfgBenchmark9_Iterations;
+ printf("%u ms (%i%%),(%u u/s)\r\n", time, (time - cfgBenchmark9_Reference) * 100 / time, up * 1000 / time);
}
- if(cfgBenchmark10_Enable)
- {// Benchmark 10
+ if (cfgBenchmark10_Enable)
+ { // Benchmark 10
srand(380843);
- btDbvt dbvt;
- btAlignedObjectArray<const btDbvtNode*> leaves;
- btAlignedObjectArray<btVector3> vectors;
+ btDbvt dbvt;
+ btAlignedObjectArray<const btDbvtNode*> leaves;
+ btAlignedObjectArray<btVector3> vectors;
vectors.resize(cfgBenchmark10_Iterations);
- for(int i=0;i<vectors.size();++i)
+ for (int i = 0; i < vectors.size(); ++i)
{
- vectors[i]=(btDbvtBenchmark::RandVector3()*2-btVector3(1,1,1))*cfgBenchmark10_Scale;
+ vectors[i] = (btDbvtBenchmark::RandVector3() * 2 - btVector3(1, 1, 1)) * cfgBenchmark10_Scale;
}
- btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
dbvt.optimizeTopDown();
- dbvt.extractLeaves(dbvt.m_root,leaves);
+ dbvt.extractLeaves(dbvt.m_root, leaves);
printf("[10] updates (jitter): ");
wallclock.reset();
- for(int i=0;i<cfgBenchmark10_Passes;++i)
+ for (int i = 0; i < cfgBenchmark10_Passes; ++i)
{
- for(int j=0;j<cfgBenchmark10_Iterations;++j)
- {
- const btVector3& d=vectors[j];
- btDbvtNode* l=const_cast<btDbvtNode*>(leaves[rand()%cfgLeaves]);
- btDbvtVolume v=btDbvtVolume::FromMM(l->volume.Mins()+d,l->volume.Maxs()+d);
- dbvt.update(l,v);
+ for (int j = 0; j < cfgBenchmark10_Iterations; ++j)
+ {
+ const btVector3& d = vectors[j];
+ btDbvtNode* l = const_cast<btDbvtNode*>(leaves[rand() % cfgLeaves]);
+ btDbvtVolume v = btDbvtVolume::FromMM(l->volume.Mins() + d, l->volume.Maxs() + d);
+ dbvt.update(l, v);
}
}
- const int time=(int)wallclock.getTimeMilliseconds();
- const int up=cfgBenchmark10_Passes*cfgBenchmark10_Iterations;
- printf("%u ms (%i%%),(%u u/s)\r\n",time,(time-cfgBenchmark10_Reference)*100/time,up*1000/time);
+ const int time = (int)wallclock.getTimeMilliseconds();
+ const int up = cfgBenchmark10_Passes * cfgBenchmark10_Iterations;
+ printf("%u ms (%i%%),(%u u/s)\r\n", time, (time - cfgBenchmark10_Reference) * 100 / time, up * 1000 / time);
}
- if(cfgBenchmark11_Enable)
- {// Benchmark 11
+ if (cfgBenchmark11_Enable)
+ { // Benchmark 11
srand(380843);
- btDbvt dbvt;
- btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ btDbvt dbvt;
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
dbvt.optimizeTopDown();
printf("[11] optimize (incremental): ");
- wallclock.reset();
- for(int i=0;i<cfgBenchmark11_Passes;++i)
+ wallclock.reset();
+ for (int i = 0; i < cfgBenchmark11_Passes; ++i)
{
dbvt.optimizeIncremental(cfgBenchmark11_Iterations);
}
- const int time=(int)wallclock.getTimeMilliseconds();
- const int op=cfgBenchmark11_Passes*cfgBenchmark11_Iterations;
- printf("%u ms (%i%%),(%u o/s)\r\n",time,(time-cfgBenchmark11_Reference)*100/time,op/time*1000);
+ const int time = (int)wallclock.getTimeMilliseconds();
+ const int op = cfgBenchmark11_Passes * cfgBenchmark11_Iterations;
+ printf("%u ms (%i%%),(%u o/s)\r\n", time, (time - cfgBenchmark11_Reference) * 100 / time, op / time * 1000);
}
- if(cfgBenchmark12_Enable)
- {// Benchmark 12
+ if (cfgBenchmark12_Enable)
+ { // Benchmark 12
srand(380843);
- btAlignedObjectArray<btDbvtVolume> volumes;
- btAlignedObjectArray<bool> results;
+ btAlignedObjectArray<btDbvtVolume> volumes;
+ btAlignedObjectArray<bool> results;
volumes.resize(cfgLeaves);
results.resize(cfgLeaves);
- for(int i=0;i<cfgLeaves;++i)
+ for (int i = 0; i < cfgLeaves; ++i)
{
- volumes[i]=btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
+ volumes[i] = btDbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale);
}
printf("[12] btDbvtVolume notequal: ");
wallclock.reset();
- for(int i=0;i<cfgBenchmark12_Iterations;++i)
+ for (int i = 0; i < cfgBenchmark12_Iterations; ++i)
{
- for(int j=0;j<cfgLeaves;++j)
+ for (int j = 0; j < cfgLeaves; ++j)
{
- for(int k=0;k<cfgLeaves;++k)
+ for (int k = 0; k < cfgLeaves; ++k)
{
- results[k]=NotEqual(volumes[j],volumes[k]);
+ results[k] = NotEqual(volumes[j], volumes[k]);
}
}
}
- const int time=(int)wallclock.getTimeMilliseconds();
- printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark12_Reference)*100/time);
+ const int time = (int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark12_Reference) * 100 / time);
}
- if(cfgBenchmark13_Enable)
- {// Benchmark 13
+ if (cfgBenchmark13_Enable)
+ { // Benchmark 13
srand(380843);
- btDbvt dbvt;
- btAlignedObjectArray<btVector3> vectors;
- btDbvtBenchmark::NilPolicy policy;
+ btDbvt dbvt;
+ btAlignedObjectArray<btVector3> vectors;
+ btDbvtBenchmark::NilPolicy policy;
vectors.resize(cfgBenchmark13_Iterations);
- for(int i=0;i<vectors.size();++i)
+ for (int i = 0; i < vectors.size(); ++i)
{
- vectors[i]=(btDbvtBenchmark::RandVector3()*2-btVector3(1,1,1)).normalized();
+ vectors[i] = (btDbvtBenchmark::RandVector3() * 2 - btVector3(1, 1, 1)).normalized();
}
- btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
dbvt.optimizeTopDown();
printf("[13] culling(OCL+fullsort): ");
- wallclock.reset();
- for(int i=0;i<cfgBenchmark13_Iterations;++i)
+ wallclock.reset();
+ for (int i = 0; i < cfgBenchmark13_Iterations; ++i)
{
- static const btScalar offset=0;
- policy.m_depth=-SIMD_INFINITY;
- dbvt.collideOCL(dbvt.m_root,&vectors[i],&offset,vectors[i],1,policy);
+ static const btScalar offset = 0;
+ policy.m_depth = -SIMD_INFINITY;
+ dbvt.collideOCL(dbvt.m_root, &vectors[i], &offset, vectors[i], 1, policy);
}
- const int time=(int)wallclock.getTimeMilliseconds();
- const int t=cfgBenchmark13_Iterations;
- printf("%u ms (%i%%),(%u t/s)\r\n",time,(time-cfgBenchmark13_Reference)*100/time,(t*1000)/time);
+ const int time = (int)wallclock.getTimeMilliseconds();
+ const int t = cfgBenchmark13_Iterations;
+ printf("%u ms (%i%%),(%u t/s)\r\n", time, (time - cfgBenchmark13_Reference) * 100 / time, (t * 1000) / time);
}
- if(cfgBenchmark14_Enable)
- {// Benchmark 14
+ if (cfgBenchmark14_Enable)
+ { // Benchmark 14
srand(380843);
- btDbvt dbvt;
- btAlignedObjectArray<btVector3> vectors;
- btDbvtBenchmark::P14 policy;
+ btDbvt dbvt;
+ btAlignedObjectArray<btVector3> vectors;
+ btDbvtBenchmark::P14 policy;
vectors.resize(cfgBenchmark14_Iterations);
- for(int i=0;i<vectors.size();++i)
+ for (int i = 0; i < vectors.size(); ++i)
{
- vectors[i]=(btDbvtBenchmark::RandVector3()*2-btVector3(1,1,1)).normalized();
+ vectors[i] = (btDbvtBenchmark::RandVector3() * 2 - btVector3(1, 1, 1)).normalized();
}
- btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
dbvt.optimizeTopDown();
policy.m_nodes.reserve(cfgLeaves);
printf("[14] culling(OCL+qsort): ");
- wallclock.reset();
- for(int i=0;i<cfgBenchmark14_Iterations;++i)
+ wallclock.reset();
+ for (int i = 0; i < cfgBenchmark14_Iterations; ++i)
{
- static const btScalar offset=0;
+ static const btScalar offset = 0;
policy.m_nodes.resize(0);
- dbvt.collideOCL(dbvt.m_root,&vectors[i],&offset,vectors[i],1,policy,false);
+ dbvt.collideOCL(dbvt.m_root, &vectors[i], &offset, vectors[i], 1, policy, false);
policy.m_nodes.quickSort(btDbvtBenchmark::P14::sortfnc);
}
- const int time=(int)wallclock.getTimeMilliseconds();
- const int t=cfgBenchmark14_Iterations;
- printf("%u ms (%i%%),(%u t/s)\r\n",time,(time-cfgBenchmark14_Reference)*100/time,(t*1000)/time);
+ const int time = (int)wallclock.getTimeMilliseconds();
+ const int t = cfgBenchmark14_Iterations;
+ printf("%u ms (%i%%),(%u t/s)\r\n", time, (time - cfgBenchmark14_Reference) * 100 / time, (t * 1000) / time);
}
- if(cfgBenchmark15_Enable)
- {// Benchmark 15
+ if (cfgBenchmark15_Enable)
+ { // Benchmark 15
srand(380843);
- btDbvt dbvt;
- btAlignedObjectArray<btVector3> vectors;
- btDbvtBenchmark::P15 policy;
+ btDbvt dbvt;
+ btAlignedObjectArray<btVector3> vectors;
+ btDbvtBenchmark::P15 policy;
vectors.resize(cfgBenchmark15_Iterations);
- for(int i=0;i<vectors.size();++i)
+ for (int i = 0; i < vectors.size(); ++i)
{
- vectors[i]=(btDbvtBenchmark::RandVector3()*2-btVector3(1,1,1)).normalized();
+ vectors[i] = (btDbvtBenchmark::RandVector3() * 2 - btVector3(1, 1, 1)).normalized();
}
- btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
dbvt.optimizeTopDown();
policy.m_nodes.reserve(cfgLeaves);
printf("[15] culling(KDOP+qsort): ");
- wallclock.reset();
- for(int i=0;i<cfgBenchmark15_Iterations;++i)
+ wallclock.reset();
+ for (int i = 0; i < cfgBenchmark15_Iterations; ++i)
{
- static const btScalar offset=0;
+ static const btScalar offset = 0;
policy.m_nodes.resize(0);
- policy.m_axis=vectors[i];
- dbvt.collideKDOP(dbvt.m_root,&vectors[i],&offset,1,policy);
+ policy.m_axis = vectors[i];
+ dbvt.collideKDOP(dbvt.m_root, &vectors[i], &offset, 1, policy);
policy.m_nodes.quickSort(btDbvtBenchmark::P15::sortfnc);
}
- const int time=(int)wallclock.getTimeMilliseconds();
- const int t=cfgBenchmark15_Iterations;
- printf("%u ms (%i%%),(%u t/s)\r\n",time,(time-cfgBenchmark15_Reference)*100/time,(t*1000)/time);
+ const int time = (int)wallclock.getTimeMilliseconds();
+ const int t = cfgBenchmark15_Iterations;
+ printf("%u ms (%i%%),(%u t/s)\r\n", time, (time - cfgBenchmark15_Reference) * 100 / time, (t * 1000) / time);
}
- if(cfgBenchmark16_Enable)
- {// Benchmark 16
+ if (cfgBenchmark16_Enable)
+ { // Benchmark 16
srand(380843);
- btDbvt dbvt;
- btAlignedObjectArray<btDbvtNode*> batch;
- btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ btDbvt dbvt;
+ btAlignedObjectArray<btDbvtNode*> batch;
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
dbvt.optimizeTopDown();
batch.reserve(cfgBenchmark16_BatchCount);
- printf("[16] insert/remove batch(%u): ",cfgBenchmark16_BatchCount);
+ printf("[16] insert/remove batch(%u): ", cfgBenchmark16_BatchCount);
wallclock.reset();
- for(int i=0;i<cfgBenchmark16_Passes;++i)
+ for (int i = 0; i < cfgBenchmark16_Passes; ++i)
{
- for(int j=0;j<cfgBenchmark16_BatchCount;++j)
+ for (int j = 0; j < cfgBenchmark16_BatchCount; ++j)
{
- batch.push_back(dbvt.insert(btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale),0));
+ batch.push_back(dbvt.insert(btDbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale), 0));
}
- for(int j=0;j<cfgBenchmark16_BatchCount;++j)
+ for (int j = 0; j < cfgBenchmark16_BatchCount; ++j)
{
dbvt.remove(batch[j]);
}
batch.resize(0);
}
- const int time=(int)wallclock.getTimeMilliseconds();
- const int ir=cfgBenchmark16_Passes*cfgBenchmark16_BatchCount;
- printf("%u ms (%i%%),(%u bir/s)\r\n",time,(time-cfgBenchmark16_Reference)*100/time,int(ir*1000.0/time));
+ const int time = (int)wallclock.getTimeMilliseconds();
+ const int ir = cfgBenchmark16_Passes * cfgBenchmark16_BatchCount;
+ printf("%u ms (%i%%),(%u bir/s)\r\n", time, (time - cfgBenchmark16_Reference) * 100 / time, int(ir * 1000.0 / time));
}
- if(cfgBenchmark17_Enable)
- {// Benchmark 17
+ if (cfgBenchmark17_Enable)
+ { // Benchmark 17
srand(380843);
- btAlignedObjectArray<btDbvtVolume> volumes;
- btAlignedObjectArray<int> results;
- btAlignedObjectArray<int> indices;
+ btAlignedObjectArray<btDbvtVolume> volumes;
+ btAlignedObjectArray<int> results;
+ btAlignedObjectArray<int> indices;
volumes.resize(cfgLeaves);
results.resize(cfgLeaves);
indices.resize(cfgLeaves);
- for(int i=0;i<cfgLeaves;++i)
+ for (int i = 0; i < cfgLeaves; ++i)
{
- indices[i]=i;
- volumes[i]=btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
+ indices[i] = i;
+ volumes[i] = btDbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale);
}
- for(int i=0;i<cfgLeaves;++i)
+ for (int i = 0; i < cfgLeaves; ++i)
{
- btSwap(indices[i],indices[rand()%cfgLeaves]);
+ btSwap(indices[i], indices[rand() % cfgLeaves]);
}
printf("[17] btDbvtVolume select: ");
wallclock.reset();
- for(int i=0;i<cfgBenchmark17_Iterations;++i)
+ for (int i = 0; i < cfgBenchmark17_Iterations; ++i)
{
- for(int j=0;j<cfgLeaves;++j)
+ for (int j = 0; j < cfgLeaves; ++j)
{
- for(int k=0;k<cfgLeaves;++k)
+ for (int k = 0; k < cfgLeaves; ++k)
{
- const int idx=indices[k];
- results[idx]=Select(volumes[idx],volumes[j],volumes[k]);
+ const int idx = indices[k];
+ results[idx] = Select(volumes[idx], volumes[j], volumes[k]);
}
}
}
- const int time=(int)wallclock.getTimeMilliseconds();
- printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark17_Reference)*100/time);
+ const int time = (int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark17_Reference) * 100 / time);
}
printf("\r\n\r\n");
}
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvt.h b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvt.h
index b5a0014580..a316dbf207 100644
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvt.h
+++ b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvt.h
@@ -26,50 +26,49 @@ subject to the following restrictions:
// Compile time configuration
//
-
// Implementation profiles
-#define DBVT_IMPL_GENERIC 0 // Generic implementation
-#define DBVT_IMPL_SSE 1 // SSE
+#define DBVT_IMPL_GENERIC 0 // Generic implementation
+#define DBVT_IMPL_SSE 1 // SSE
// Template implementation of ICollide
#ifdef _WIN32
-#if (defined (_MSC_VER) && _MSC_VER >= 1400)
-#define DBVT_USE_TEMPLATE 1
+#if (defined(_MSC_VER) && _MSC_VER >= 1400)
+#define DBVT_USE_TEMPLATE 1
#else
-#define DBVT_USE_TEMPLATE 0
+#define DBVT_USE_TEMPLATE 0
#endif
#else
-#define DBVT_USE_TEMPLATE 0
+#define DBVT_USE_TEMPLATE 0
#endif
// Use only intrinsics instead of inline asm
-#define DBVT_USE_INTRINSIC_SSE 1
+#define DBVT_USE_INTRINSIC_SSE 1
// Using memmov for collideOCL
-#define DBVT_USE_MEMMOVE 1
+#define DBVT_USE_MEMMOVE 1
// Enable benchmarking code
-#define DBVT_ENABLE_BENCHMARK 0
+#define DBVT_ENABLE_BENCHMARK 0
// Inlining
-#define DBVT_INLINE SIMD_FORCE_INLINE
+#define DBVT_INLINE SIMD_FORCE_INLINE
// Specific methods implementation
//SSE gives errors on a MSVC 7.1
-#if defined (BT_USE_SSE) //&& defined (_WIN32)
-#define DBVT_SELECT_IMPL DBVT_IMPL_SSE
-#define DBVT_MERGE_IMPL DBVT_IMPL_SSE
-#define DBVT_INT0_IMPL DBVT_IMPL_SSE
+#if defined(BT_USE_SSE) //&& defined (_WIN32)
+#define DBVT_SELECT_IMPL DBVT_IMPL_SSE
+#define DBVT_MERGE_IMPL DBVT_IMPL_SSE
+#define DBVT_INT0_IMPL DBVT_IMPL_SSE
#else
-#define DBVT_SELECT_IMPL DBVT_IMPL_GENERIC
-#define DBVT_MERGE_IMPL DBVT_IMPL_GENERIC
-#define DBVT_INT0_IMPL DBVT_IMPL_GENERIC
+#define DBVT_SELECT_IMPL DBVT_IMPL_GENERIC
+#define DBVT_MERGE_IMPL DBVT_IMPL_GENERIC
+#define DBVT_INT0_IMPL DBVT_IMPL_GENERIC
#endif
-#if (DBVT_SELECT_IMPL==DBVT_IMPL_SSE)|| \
- (DBVT_MERGE_IMPL==DBVT_IMPL_SSE)|| \
- (DBVT_INT0_IMPL==DBVT_IMPL_SSE)
+#if (DBVT_SELECT_IMPL == DBVT_IMPL_SSE) || \
+ (DBVT_MERGE_IMPL == DBVT_IMPL_SSE) || \
+ (DBVT_INT0_IMPL == DBVT_IMPL_SSE)
#include <emmintrin.h>
#endif
@@ -78,21 +77,24 @@ subject to the following restrictions:
//
#if DBVT_USE_TEMPLATE
-#define DBVT_VIRTUAL
+#define DBVT_VIRTUAL
#define DBVT_VIRTUAL_DTOR(a)
-#define DBVT_PREFIX template <typename T>
-#define DBVT_IPOLICY T& policy
-#define DBVT_CHECKTYPE static const ICollide& typechecker=*(T*)1;(void)typechecker;
+#define DBVT_PREFIX template <typename T>
+#define DBVT_IPOLICY T& policy
+#define DBVT_CHECKTYPE \
+ static const ICollide& typechecker = *(T*)1; \
+ (void)typechecker;
#else
-#define DBVT_VIRTUAL_DTOR(a) virtual ~a() {}
-#define DBVT_VIRTUAL virtual
+#define DBVT_VIRTUAL_DTOR(a) \
+ virtual ~a() {}
+#define DBVT_VIRTUAL virtual
#define DBVT_PREFIX
-#define DBVT_IPOLICY ICollide& policy
+#define DBVT_IPOLICY ICollide& policy
#define DBVT_CHECKTYPE
#endif
#if DBVT_USE_MEMMOVE
-#if !defined( __CELLOS_LV2__) && !defined(__MWERKS__)
+#if !defined(__CELLOS_LV2__) && !defined(__MWERKS__)
#include <memory.h>
#endif
#include <string.h>
@@ -122,194 +124,193 @@ subject to the following restrictions:
#error "DBVT_INT0_IMPL undefined"
#endif
-
//
// Defaults volumes
//
-/* btDbvtAabbMm */
-struct btDbvtAabbMm
+/* btDbvtAabbMm */
+struct btDbvtAabbMm
{
- DBVT_INLINE btVector3 Center() const { return((mi+mx)/2); }
- DBVT_INLINE btVector3 Lengths() const { return(mx-mi); }
- DBVT_INLINE btVector3 Extents() const { return((mx-mi)/2); }
- DBVT_INLINE const btVector3& Mins() const { return(mi); }
- DBVT_INLINE const btVector3& Maxs() const { return(mx); }
- static inline btDbvtAabbMm FromCE(const btVector3& c,const btVector3& e);
- static inline btDbvtAabbMm FromCR(const btVector3& c,btScalar r);
- static inline btDbvtAabbMm FromMM(const btVector3& mi,const btVector3& mx);
- static inline btDbvtAabbMm FromPoints(const btVector3* pts,int n);
- static inline btDbvtAabbMm FromPoints(const btVector3** ppts,int n);
- DBVT_INLINE void Expand(const btVector3& e);
- DBVT_INLINE void SignedExpand(const btVector3& e);
- DBVT_INLINE bool Contain(const btDbvtAabbMm& a) const;
- DBVT_INLINE int Classify(const btVector3& n,btScalar o,int s) const;
- DBVT_INLINE btScalar ProjectMinimum(const btVector3& v,unsigned signs) const;
- DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a,
- const btDbvtAabbMm& b);
-
- DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a,
- const btVector3& b);
-
- DBVT_INLINE friend btScalar Proximity( const btDbvtAabbMm& a,
- const btDbvtAabbMm& b);
- DBVT_INLINE friend int Select( const btDbvtAabbMm& o,
- const btDbvtAabbMm& a,
- const btDbvtAabbMm& b);
- DBVT_INLINE friend void Merge( const btDbvtAabbMm& a,
- const btDbvtAabbMm& b,
- btDbvtAabbMm& r);
- DBVT_INLINE friend bool NotEqual( const btDbvtAabbMm& a,
- const btDbvtAabbMm& b);
-
- DBVT_INLINE btVector3& tMins() { return(mi); }
- DBVT_INLINE btVector3& tMaxs() { return(mx); }
-
+ DBVT_INLINE btVector3 Center() const { return ((mi + mx) / 2); }
+ DBVT_INLINE btVector3 Lengths() const { return (mx - mi); }
+ DBVT_INLINE btVector3 Extents() const { return ((mx - mi) / 2); }
+ DBVT_INLINE const btVector3& Mins() const { return (mi); }
+ DBVT_INLINE const btVector3& Maxs() const { return (mx); }
+ static inline btDbvtAabbMm FromCE(const btVector3& c, const btVector3& e);
+ static inline btDbvtAabbMm FromCR(const btVector3& c, btScalar r);
+ static inline btDbvtAabbMm FromMM(const btVector3& mi, const btVector3& mx);
+ static inline btDbvtAabbMm FromPoints(const btVector3* pts, int n);
+ static inline btDbvtAabbMm FromPoints(const btVector3** ppts, int n);
+ DBVT_INLINE void Expand(const btVector3& e);
+ DBVT_INLINE void SignedExpand(const btVector3& e);
+ DBVT_INLINE bool Contain(const btDbvtAabbMm& a) const;
+ DBVT_INLINE int Classify(const btVector3& n, btScalar o, int s) const;
+ DBVT_INLINE btScalar ProjectMinimum(const btVector3& v, unsigned signs) const;
+ DBVT_INLINE friend bool Intersect(const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b);
+
+ DBVT_INLINE friend bool Intersect(const btDbvtAabbMm& a,
+ const btVector3& b);
+
+ DBVT_INLINE friend btScalar Proximity(const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b);
+ DBVT_INLINE friend int Select(const btDbvtAabbMm& o,
+ const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b);
+ DBVT_INLINE friend void Merge(const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b,
+ btDbvtAabbMm& r);
+ DBVT_INLINE friend bool NotEqual(const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b);
+
+ DBVT_INLINE btVector3& tMins() { return (mi); }
+ DBVT_INLINE btVector3& tMaxs() { return (mx); }
+
private:
- DBVT_INLINE void AddSpan(const btVector3& d,btScalar& smi,btScalar& smx) const;
+ DBVT_INLINE void AddSpan(const btVector3& d, btScalar& smi, btScalar& smx) const;
+
private:
- btVector3 mi,mx;
+ btVector3 mi, mx;
};
-// Types
-typedef btDbvtAabbMm btDbvtVolume;
+// Types
+typedef btDbvtAabbMm btDbvtVolume;
-/* btDbvtNode */
-struct btDbvtNode
+/* btDbvtNode */
+struct btDbvtNode
{
- btDbvtVolume volume;
- btDbvtNode* parent;
- DBVT_INLINE bool isleaf() const { return(childs[1]==0); }
- DBVT_INLINE bool isinternal() const { return(!isleaf()); }
- union
- {
- btDbvtNode* childs[2];
- void* data;
- int dataAsInt;
+ btDbvtVolume volume;
+ btDbvtNode* parent;
+ DBVT_INLINE bool isleaf() const { return (childs[1] == 0); }
+ DBVT_INLINE bool isinternal() const { return (!isleaf()); }
+ union {
+ btDbvtNode* childs[2];
+ void* data;
+ int dataAsInt;
};
};
typedef btAlignedObjectArray<const btDbvtNode*> btNodeStack;
-
///The btDbvt class implements a fast dynamic bounding volume tree based on axis aligned bounding boxes (aabb tree).
///This btDbvt is used for soft body collision detection and for the btDbvtBroadphase. It has a fast insert, remove and update of nodes.
///Unlike the btQuantizedBvh, nodes can be dynamically moved around, which allows for change in topology of the underlying data structure.
-struct btDbvt
+struct btDbvt
{
- /* Stack element */
- struct sStkNN
+ /* Stack element */
+ struct sStkNN
{
- const btDbvtNode* a;
- const btDbvtNode* b;
+ const btDbvtNode* a;
+ const btDbvtNode* b;
sStkNN() {}
- sStkNN(const btDbvtNode* na,const btDbvtNode* nb) : a(na),b(nb) {}
+ sStkNN(const btDbvtNode* na, const btDbvtNode* nb) : a(na), b(nb) {}
};
- struct sStkNP
+ struct sStkNP
{
- const btDbvtNode* node;
- int mask;
- sStkNP(const btDbvtNode* n,unsigned m) : node(n),mask(m) {}
+ const btDbvtNode* node;
+ int mask;
+ sStkNP(const btDbvtNode* n, unsigned m) : node(n), mask(m) {}
};
- struct sStkNPS
+ struct sStkNPS
{
- const btDbvtNode* node;
- int mask;
- btScalar value;
+ const btDbvtNode* node;
+ int mask;
+ btScalar value;
sStkNPS() {}
- sStkNPS(const btDbvtNode* n,unsigned m,btScalar v) : node(n),mask(m),value(v) {}
+ sStkNPS(const btDbvtNode* n, unsigned m, btScalar v) : node(n), mask(m), value(v) {}
};
- struct sStkCLN
+ struct sStkCLN
{
- const btDbvtNode* node;
- btDbvtNode* parent;
- sStkCLN(const btDbvtNode* n,btDbvtNode* p) : node(n),parent(p) {}
+ const btDbvtNode* node;
+ btDbvtNode* parent;
+ sStkCLN(const btDbvtNode* n, btDbvtNode* p) : node(n), parent(p) {}
};
// Policies/Interfaces
- /* ICollide */
- struct ICollide
- {
+ /* ICollide */
+ struct ICollide
+ {
DBVT_VIRTUAL_DTOR(ICollide)
- DBVT_VIRTUAL void Process(const btDbvtNode*,const btDbvtNode*) {}
- DBVT_VIRTUAL void Process(const btDbvtNode*) {}
- DBVT_VIRTUAL void Process(const btDbvtNode* n,btScalar) { Process(n); }
- DBVT_VIRTUAL bool Descent(const btDbvtNode*) { return(true); }
- DBVT_VIRTUAL bool AllLeaves(const btDbvtNode*) { return(true); }
+ DBVT_VIRTUAL void Process(const btDbvtNode*, const btDbvtNode*) {}
+ DBVT_VIRTUAL void Process(const btDbvtNode*) {}
+ DBVT_VIRTUAL void Process(const btDbvtNode* n, btScalar) { Process(n); }
+ DBVT_VIRTUAL bool Descent(const btDbvtNode*) { return (true); }
+ DBVT_VIRTUAL bool AllLeaves(const btDbvtNode*) { return (true); }
};
- /* IWriter */
- struct IWriter
+ /* IWriter */
+ struct IWriter
{
virtual ~IWriter() {}
- virtual void Prepare(const btDbvtNode* root,int numnodes)=0;
- virtual void WriteNode(const btDbvtNode*,int index,int parent,int child0,int child1)=0;
- virtual void WriteLeaf(const btDbvtNode*,int index,int parent)=0;
+ virtual void Prepare(const btDbvtNode* root, int numnodes) = 0;
+ virtual void WriteNode(const btDbvtNode*, int index, int parent, int child0, int child1) = 0;
+ virtual void WriteLeaf(const btDbvtNode*, int index, int parent) = 0;
};
- /* IClone */
- struct IClone
+ /* IClone */
+ struct IClone
{
- virtual ~IClone() {}
- virtual void CloneLeaf(btDbvtNode*) {}
+ virtual ~IClone() {}
+ virtual void CloneLeaf(btDbvtNode*) {}
};
// Constants
- enum {
- SIMPLE_STACKSIZE = 64,
- DOUBLE_STACKSIZE = SIMPLE_STACKSIZE*2
+ enum
+ {
+ SIMPLE_STACKSIZE = 64,
+ DOUBLE_STACKSIZE = SIMPLE_STACKSIZE * 2
};
// Fields
- btDbvtNode* m_root;
- btDbvtNode* m_free;
- int m_lkhd;
- int m_leaves;
- unsigned m_opath;
-
-
- btAlignedObjectArray<sStkNN> m_stkStack;
+ btDbvtNode* m_root;
+ btDbvtNode* m_free;
+ int m_lkhd;
+ int m_leaves;
+ unsigned m_opath;
+ btAlignedObjectArray<sStkNN> m_stkStack;
// Methods
btDbvt();
~btDbvt();
- void clear();
- bool empty() const { return(0==m_root); }
- void optimizeBottomUp();
- void optimizeTopDown(int bu_treshold=128);
- void optimizeIncremental(int passes);
- btDbvtNode* insert(const btDbvtVolume& box,void* data);
- void update(btDbvtNode* leaf,int lookahead=-1);
- void update(btDbvtNode* leaf,btDbvtVolume& volume);
- bool update(btDbvtNode* leaf,btDbvtVolume& volume,const btVector3& velocity,btScalar margin);
- bool update(btDbvtNode* leaf,btDbvtVolume& volume,const btVector3& velocity);
- bool update(btDbvtNode* leaf,btDbvtVolume& volume,btScalar margin);
- void remove(btDbvtNode* leaf);
- void write(IWriter* iwriter) const;
- void clone(btDbvt& dest,IClone* iclone=0) const;
- static int maxdepth(const btDbvtNode* node);
- static int countLeaves(const btDbvtNode* node);
- static void extractLeaves(const btDbvtNode* node,btAlignedObjectArray<const btDbvtNode*>& leaves);
+ void clear();
+ bool empty() const { return (0 == m_root); }
+ void optimizeBottomUp();
+ void optimizeTopDown(int bu_treshold = 128);
+ void optimizeIncremental(int passes);
+ btDbvtNode* insert(const btDbvtVolume& box, void* data);
+ void update(btDbvtNode* leaf, int lookahead = -1);
+ void update(btDbvtNode* leaf, btDbvtVolume& volume);
+ bool update(btDbvtNode* leaf, btDbvtVolume& volume, const btVector3& velocity, btScalar margin);
+ bool update(btDbvtNode* leaf, btDbvtVolume& volume, const btVector3& velocity);
+ bool update(btDbvtNode* leaf, btDbvtVolume& volume, btScalar margin);
+ void remove(btDbvtNode* leaf);
+ void write(IWriter* iwriter) const;
+ void clone(btDbvt& dest, IClone* iclone = 0) const;
+ static int maxdepth(const btDbvtNode* node);
+ static int countLeaves(const btDbvtNode* node);
+ static void extractLeaves(const btDbvtNode* node, btAlignedObjectArray<const btDbvtNode*>& leaves);
#if DBVT_ENABLE_BENCHMARK
- static void benchmark();
+ static void benchmark();
#else
- static void benchmark(){}
+ static void benchmark()
+ {
+ }
#endif
// DBVT_IPOLICY must support ICollide policy/interface
DBVT_PREFIX
- static void enumNodes( const btDbvtNode* root,
- DBVT_IPOLICY);
+ static void enumNodes(const btDbvtNode* root,
+ DBVT_IPOLICY);
DBVT_PREFIX
- static void enumLeaves( const btDbvtNode* root,
- DBVT_IPOLICY);
+ static void enumLeaves(const btDbvtNode* root,
+ DBVT_IPOLICY);
DBVT_PREFIX
- void collideTT( const btDbvtNode* root0,
- const btDbvtNode* root1,
- DBVT_IPOLICY);
+ void collideTT(const btDbvtNode* root0,
+ const btDbvtNode* root1,
+ DBVT_IPOLICY);
DBVT_PREFIX
- void collideTTpersistentStack( const btDbvtNode* root0,
- const btDbvtNode* root1,
- DBVT_IPOLICY);
+ void collideTTpersistentStack(const btDbvtNode* root0,
+ const btDbvtNode* root1,
+ DBVT_IPOLICY);
#if 0
DBVT_PREFIX
void collideTT( const btDbvtNode* root0,
@@ -325,82 +326,89 @@ struct btDbvt
#endif
DBVT_PREFIX
- void collideTV( const btDbvtNode* root,
- const btDbvtVolume& volume,
- DBVT_IPOLICY) const;
-
+ void collideTV(const btDbvtNode* root,
+ const btDbvtVolume& volume,
+ DBVT_IPOLICY) const;
+
DBVT_PREFIX
- void collideTVNoStackAlloc( const btDbvtNode* root,
- const btDbvtVolume& volume,
- btNodeStack& stack,
- DBVT_IPOLICY) const;
-
-
-
-
+ void collideTVNoStackAlloc(const btDbvtNode* root,
+ const btDbvtVolume& volume,
+ btNodeStack& stack,
+ DBVT_IPOLICY) const;
+
///rayTest is a re-entrant ray test, and can be called in parallel as long as the btAlignedAlloc is thread-safe (uses locking etc)
///rayTest is slower than rayTestInternal, because it builds a local stack, using memory allocations, and it recomputes signs/rayDirectionInverses each time
DBVT_PREFIX
- static void rayTest( const btDbvtNode* root,
- const btVector3& rayFrom,
- const btVector3& rayTo,
- DBVT_IPOLICY);
+ static void rayTest(const btDbvtNode* root,
+ const btVector3& rayFrom,
+ const btVector3& rayTo,
+ DBVT_IPOLICY);
///rayTestInternal is faster than rayTest, because it uses a persistent stack (to reduce dynamic memory allocations to a minimum) and it uses precomputed signs/rayInverseDirections
///rayTestInternal is used by btDbvtBroadphase to accelerate world ray casts
DBVT_PREFIX
- void rayTestInternal( const btDbvtNode* root,
- const btVector3& rayFrom,
- const btVector3& rayTo,
- const btVector3& rayDirectionInverse,
- unsigned int signs[3],
- btScalar lambda_max,
- const btVector3& aabbMin,
- const btVector3& aabbMax,
- btAlignedObjectArray<const btDbvtNode*>& stack,
- DBVT_IPOLICY) const;
+ void rayTestInternal(const btDbvtNode* root,
+ const btVector3& rayFrom,
+ const btVector3& rayTo,
+ const btVector3& rayDirectionInverse,
+ unsigned int signs[3],
+ btScalar lambda_max,
+ const btVector3& aabbMin,
+ const btVector3& aabbMax,
+ btAlignedObjectArray<const btDbvtNode*>& stack,
+ DBVT_IPOLICY) const;
DBVT_PREFIX
- static void collideKDOP(const btDbvtNode* root,
- const btVector3* normals,
- const btScalar* offsets,
- int count,
- DBVT_IPOLICY);
+ static void collideKDOP(const btDbvtNode* root,
+ const btVector3* normals,
+ const btScalar* offsets,
+ int count,
+ DBVT_IPOLICY);
DBVT_PREFIX
- static void collideOCL( const btDbvtNode* root,
- const btVector3* normals,
- const btScalar* offsets,
- const btVector3& sortaxis,
- int count,
- DBVT_IPOLICY,
- bool fullsort=true);
+ static void collideOCL(const btDbvtNode* root,
+ const btVector3* normals,
+ const btScalar* offsets,
+ const btVector3& sortaxis,
+ int count,
+ DBVT_IPOLICY,
+ bool fullsort = true);
DBVT_PREFIX
- static void collideTU( const btDbvtNode* root,
- DBVT_IPOLICY);
- // Helpers
- static DBVT_INLINE int nearest(const int* i,const btDbvt::sStkNPS* a,btScalar v,int l,int h)
+ static void collideTU(const btDbvtNode* root,
+ DBVT_IPOLICY);
+ // Helpers
+ static DBVT_INLINE int nearest(const int* i, const btDbvt::sStkNPS* a, btScalar v, int l, int h)
{
- int m=0;
- while(l<h)
+ int m = 0;
+ while (l < h)
{
- m=(l+h)>>1;
- if(a[i[m]].value>=v) l=m+1; else h=m;
+ m = (l + h) >> 1;
+ if (a[i[m]].value >= v)
+ l = m + 1;
+ else
+ h = m;
}
- return(h);
+ return (h);
}
- static DBVT_INLINE int allocate( btAlignedObjectArray<int>& ifree,
- btAlignedObjectArray<sStkNPS>& stock,
- const sStkNPS& value)
+ static DBVT_INLINE int allocate(btAlignedObjectArray<int>& ifree,
+ btAlignedObjectArray<sStkNPS>& stock,
+ const sStkNPS& value)
{
- int i;
- if(ifree.size()>0)
- { i=ifree[ifree.size()-1];ifree.pop_back();stock[i]=value; }
+ int i;
+ if (ifree.size() > 0)
+ {
+ i = ifree[ifree.size() - 1];
+ ifree.pop_back();
+ stock[i] = value;
+ }
else
- { i=stock.size();stock.push_back(value); }
- return(i);
+ {
+ i = stock.size();
+ stock.push_back(value);
+ }
+ return (i);
}
//
private:
- btDbvt(const btDbvt&) {}
+ btDbvt(const btDbvt&) {}
};
//
@@ -408,227 +416,252 @@ private:
//
//
-inline btDbvtAabbMm btDbvtAabbMm::FromCE(const btVector3& c,const btVector3& e)
+inline btDbvtAabbMm btDbvtAabbMm::FromCE(const btVector3& c, const btVector3& e)
{
btDbvtAabbMm box;
- box.mi=c-e;box.mx=c+e;
- return(box);
+ box.mi = c - e;
+ box.mx = c + e;
+ return (box);
}
//
-inline btDbvtAabbMm btDbvtAabbMm::FromCR(const btVector3& c,btScalar r)
+inline btDbvtAabbMm btDbvtAabbMm::FromCR(const btVector3& c, btScalar r)
{
- return(FromCE(c,btVector3(r,r,r)));
+ return (FromCE(c, btVector3(r, r, r)));
}
//
-inline btDbvtAabbMm btDbvtAabbMm::FromMM(const btVector3& mi,const btVector3& mx)
+inline btDbvtAabbMm btDbvtAabbMm::FromMM(const btVector3& mi, const btVector3& mx)
{
btDbvtAabbMm box;
- box.mi=mi;box.mx=mx;
- return(box);
+ box.mi = mi;
+ box.mx = mx;
+ return (box);
}
//
-inline btDbvtAabbMm btDbvtAabbMm::FromPoints(const btVector3* pts,int n)
+inline btDbvtAabbMm btDbvtAabbMm::FromPoints(const btVector3* pts, int n)
{
btDbvtAabbMm box;
- box.mi=box.mx=pts[0];
- for(int i=1;i<n;++i)
+ box.mi = box.mx = pts[0];
+ for (int i = 1; i < n; ++i)
{
box.mi.setMin(pts[i]);
box.mx.setMax(pts[i]);
}
- return(box);
+ return (box);
}
//
-inline btDbvtAabbMm btDbvtAabbMm::FromPoints(const btVector3** ppts,int n)
+inline btDbvtAabbMm btDbvtAabbMm::FromPoints(const btVector3** ppts, int n)
{
btDbvtAabbMm box;
- box.mi=box.mx=*ppts[0];
- for(int i=1;i<n;++i)
+ box.mi = box.mx = *ppts[0];
+ for (int i = 1; i < n; ++i)
{
box.mi.setMin(*ppts[i]);
box.mx.setMax(*ppts[i]);
}
- return(box);
+ return (box);
}
//
-DBVT_INLINE void btDbvtAabbMm::Expand(const btVector3& e)
+DBVT_INLINE void btDbvtAabbMm::Expand(const btVector3& e)
{
- mi-=e;mx+=e;
+ mi -= e;
+ mx += e;
}
//
-DBVT_INLINE void btDbvtAabbMm::SignedExpand(const btVector3& e)
+DBVT_INLINE void btDbvtAabbMm::SignedExpand(const btVector3& e)
{
- if(e.x()>0) mx.setX(mx.x()+e[0]); else mi.setX(mi.x()+e[0]);
- if(e.y()>0) mx.setY(mx.y()+e[1]); else mi.setY(mi.y()+e[1]);
- if(e.z()>0) mx.setZ(mx.z()+e[2]); else mi.setZ(mi.z()+e[2]);
+ if (e.x() > 0)
+ mx.setX(mx.x() + e[0]);
+ else
+ mi.setX(mi.x() + e[0]);
+ if (e.y() > 0)
+ mx.setY(mx.y() + e[1]);
+ else
+ mi.setY(mi.y() + e[1]);
+ if (e.z() > 0)
+ mx.setZ(mx.z() + e[2]);
+ else
+ mi.setZ(mi.z() + e[2]);
}
//
-DBVT_INLINE bool btDbvtAabbMm::Contain(const btDbvtAabbMm& a) const
+DBVT_INLINE bool btDbvtAabbMm::Contain(const btDbvtAabbMm& a) const
{
- return( (mi.x()<=a.mi.x())&&
- (mi.y()<=a.mi.y())&&
- (mi.z()<=a.mi.z())&&
- (mx.x()>=a.mx.x())&&
- (mx.y()>=a.mx.y())&&
- (mx.z()>=a.mx.z()));
+ return ((mi.x() <= a.mi.x()) &&
+ (mi.y() <= a.mi.y()) &&
+ (mi.z() <= a.mi.z()) &&
+ (mx.x() >= a.mx.x()) &&
+ (mx.y() >= a.mx.y()) &&
+ (mx.z() >= a.mx.z()));
}
//
-DBVT_INLINE int btDbvtAabbMm::Classify(const btVector3& n,btScalar o,int s) const
+DBVT_INLINE int btDbvtAabbMm::Classify(const btVector3& n, btScalar o, int s) const
{
- btVector3 pi,px;
- switch(s)
+ btVector3 pi, px;
+ switch (s)
{
- case (0+0+0): px=btVector3(mi.x(),mi.y(),mi.z());
- pi=btVector3(mx.x(),mx.y(),mx.z());break;
- case (1+0+0): px=btVector3(mx.x(),mi.y(),mi.z());
- pi=btVector3(mi.x(),mx.y(),mx.z());break;
- case (0+2+0): px=btVector3(mi.x(),mx.y(),mi.z());
- pi=btVector3(mx.x(),mi.y(),mx.z());break;
- case (1+2+0): px=btVector3(mx.x(),mx.y(),mi.z());
- pi=btVector3(mi.x(),mi.y(),mx.z());break;
- case (0+0+4): px=btVector3(mi.x(),mi.y(),mx.z());
- pi=btVector3(mx.x(),mx.y(),mi.z());break;
- case (1+0+4): px=btVector3(mx.x(),mi.y(),mx.z());
- pi=btVector3(mi.x(),mx.y(),mi.z());break;
- case (0+2+4): px=btVector3(mi.x(),mx.y(),mx.z());
- pi=btVector3(mx.x(),mi.y(),mi.z());break;
- case (1+2+4): px=btVector3(mx.x(),mx.y(),mx.z());
- pi=btVector3(mi.x(),mi.y(),mi.z());break;
+ case (0 + 0 + 0):
+ px = btVector3(mi.x(), mi.y(), mi.z());
+ pi = btVector3(mx.x(), mx.y(), mx.z());
+ break;
+ case (1 + 0 + 0):
+ px = btVector3(mx.x(), mi.y(), mi.z());
+ pi = btVector3(mi.x(), mx.y(), mx.z());
+ break;
+ case (0 + 2 + 0):
+ px = btVector3(mi.x(), mx.y(), mi.z());
+ pi = btVector3(mx.x(), mi.y(), mx.z());
+ break;
+ case (1 + 2 + 0):
+ px = btVector3(mx.x(), mx.y(), mi.z());
+ pi = btVector3(mi.x(), mi.y(), mx.z());
+ break;
+ case (0 + 0 + 4):
+ px = btVector3(mi.x(), mi.y(), mx.z());
+ pi = btVector3(mx.x(), mx.y(), mi.z());
+ break;
+ case (1 + 0 + 4):
+ px = btVector3(mx.x(), mi.y(), mx.z());
+ pi = btVector3(mi.x(), mx.y(), mi.z());
+ break;
+ case (0 + 2 + 4):
+ px = btVector3(mi.x(), mx.y(), mx.z());
+ pi = btVector3(mx.x(), mi.y(), mi.z());
+ break;
+ case (1 + 2 + 4):
+ px = btVector3(mx.x(), mx.y(), mx.z());
+ pi = btVector3(mi.x(), mi.y(), mi.z());
+ break;
}
- if((btDot(n,px)+o)<0) return(-1);
- if((btDot(n,pi)+o)>=0) return(+1);
- return(0);
+ if ((btDot(n, px) + o) < 0) return (-1);
+ if ((btDot(n, pi) + o) >= 0) return (+1);
+ return (0);
}
//
-DBVT_INLINE btScalar btDbvtAabbMm::ProjectMinimum(const btVector3& v,unsigned signs) const
+DBVT_INLINE btScalar btDbvtAabbMm::ProjectMinimum(const btVector3& v, unsigned signs) const
{
- const btVector3* b[]={&mx,&mi};
- const btVector3 p( b[(signs>>0)&1]->x(),
- b[(signs>>1)&1]->y(),
- b[(signs>>2)&1]->z());
- return(btDot(p,v));
+ const btVector3* b[] = {&mx, &mi};
+ const btVector3 p(b[(signs >> 0) & 1]->x(),
+ b[(signs >> 1) & 1]->y(),
+ b[(signs >> 2) & 1]->z());
+ return (btDot(p, v));
}
//
-DBVT_INLINE void btDbvtAabbMm::AddSpan(const btVector3& d,btScalar& smi,btScalar& smx) const
+DBVT_INLINE void btDbvtAabbMm::AddSpan(const btVector3& d, btScalar& smi, btScalar& smx) const
{
- for(int i=0;i<3;++i)
+ for (int i = 0; i < 3; ++i)
{
- if(d[i]<0)
- { smi+=mx[i]*d[i];smx+=mi[i]*d[i]; }
+ if (d[i] < 0)
+ {
+ smi += mx[i] * d[i];
+ smx += mi[i] * d[i];
+ }
else
- { smi+=mi[i]*d[i];smx+=mx[i]*d[i]; }
+ {
+ smi += mi[i] * d[i];
+ smx += mx[i] * d[i];
+ }
}
}
//
-DBVT_INLINE bool Intersect( const btDbvtAabbMm& a,
- const btDbvtAabbMm& b)
+DBVT_INLINE bool Intersect(const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b)
{
-#if DBVT_INT0_IMPL == DBVT_IMPL_SSE
- const __m128 rt(_mm_or_ps( _mm_cmplt_ps(_mm_load_ps(b.mx),_mm_load_ps(a.mi)),
- _mm_cmplt_ps(_mm_load_ps(a.mx),_mm_load_ps(b.mi))));
-#if defined (_WIN32)
- const __int32* pu((const __int32*)&rt);
+#if DBVT_INT0_IMPL == DBVT_IMPL_SSE
+ const __m128 rt(_mm_or_ps(_mm_cmplt_ps(_mm_load_ps(b.mx), _mm_load_ps(a.mi)),
+ _mm_cmplt_ps(_mm_load_ps(a.mx), _mm_load_ps(b.mi))));
+#if defined(_WIN32)
+ const __int32* pu((const __int32*)&rt);
#else
- const int* pu((const int*)&rt);
+ const int* pu((const int*)&rt);
#endif
- return((pu[0]|pu[1]|pu[2])==0);
+ return ((pu[0] | pu[1] | pu[2]) == 0);
#else
- return( (a.mi.x()<=b.mx.x())&&
- (a.mx.x()>=b.mi.x())&&
- (a.mi.y()<=b.mx.y())&&
- (a.mx.y()>=b.mi.y())&&
- (a.mi.z()<=b.mx.z())&&
- (a.mx.z()>=b.mi.z()));
+ return ((a.mi.x() <= b.mx.x()) &&
+ (a.mx.x() >= b.mi.x()) &&
+ (a.mi.y() <= b.mx.y()) &&
+ (a.mx.y() >= b.mi.y()) &&
+ (a.mi.z() <= b.mx.z()) &&
+ (a.mx.z() >= b.mi.z()));
#endif
}
-
-
//
-DBVT_INLINE bool Intersect( const btDbvtAabbMm& a,
- const btVector3& b)
+DBVT_INLINE bool Intersect(const btDbvtAabbMm& a,
+ const btVector3& b)
{
- return( (b.x()>=a.mi.x())&&
- (b.y()>=a.mi.y())&&
- (b.z()>=a.mi.z())&&
- (b.x()<=a.mx.x())&&
- (b.y()<=a.mx.y())&&
- (b.z()<=a.mx.z()));
+ return ((b.x() >= a.mi.x()) &&
+ (b.y() >= a.mi.y()) &&
+ (b.z() >= a.mi.z()) &&
+ (b.x() <= a.mx.x()) &&
+ (b.y() <= a.mx.y()) &&
+ (b.z() <= a.mx.z()));
}
-
-
-
-
//////////////////////////////////////
-
//
-DBVT_INLINE btScalar Proximity( const btDbvtAabbMm& a,
- const btDbvtAabbMm& b)
+DBVT_INLINE btScalar Proximity(const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b)
{
- const btVector3 d=(a.mi+a.mx)-(b.mi+b.mx);
- return(btFabs(d.x())+btFabs(d.y())+btFabs(d.z()));
+ const btVector3 d = (a.mi + a.mx) - (b.mi + b.mx);
+ return (btFabs(d.x()) + btFabs(d.y()) + btFabs(d.z()));
}
-
-
//
-DBVT_INLINE int Select( const btDbvtAabbMm& o,
- const btDbvtAabbMm& a,
- const btDbvtAabbMm& b)
+DBVT_INLINE int Select(const btDbvtAabbMm& o,
+ const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b)
{
-#if DBVT_SELECT_IMPL == DBVT_IMPL_SSE
-
-#if defined (_WIN32)
- static ATTRIBUTE_ALIGNED16(const unsigned __int32) mask[]={0x7fffffff,0x7fffffff,0x7fffffff,0x7fffffff};
+#if DBVT_SELECT_IMPL == DBVT_IMPL_SSE
+
+#if defined(_WIN32)
+ static ATTRIBUTE_ALIGNED16(const unsigned __int32) mask[] = {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff};
#else
- static ATTRIBUTE_ALIGNED16(const unsigned int) mask[]={0x7fffffff,0x7fffffff,0x7fffffff,0x00000000 /*0x7fffffff*/};
+ static ATTRIBUTE_ALIGNED16(const unsigned int) mask[] = {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x00000000 /*0x7fffffff*/};
#endif
///@todo: the intrinsic version is 11% slower
#if DBVT_USE_INTRINSIC_SSE
- union btSSEUnion ///NOTE: if we use more intrinsics, move btSSEUnion into the LinearMath directory
+ union btSSEUnion ///NOTE: if we use more intrinsics, move btSSEUnion into the LinearMath directory
{
- __m128 ssereg;
- float floats[4];
- int ints[4];
+ __m128 ssereg;
+ float floats[4];
+ int ints[4];
};
- __m128 omi(_mm_load_ps(o.mi));
- omi=_mm_add_ps(omi,_mm_load_ps(o.mx));
- __m128 ami(_mm_load_ps(a.mi));
- ami=_mm_add_ps(ami,_mm_load_ps(a.mx));
- ami=_mm_sub_ps(ami,omi);
- ami=_mm_and_ps(ami,_mm_load_ps((const float*)mask));
- __m128 bmi(_mm_load_ps(b.mi));
- bmi=_mm_add_ps(bmi,_mm_load_ps(b.mx));
- bmi=_mm_sub_ps(bmi,omi);
- bmi=_mm_and_ps(bmi,_mm_load_ps((const float*)mask));
- __m128 t0(_mm_movehl_ps(ami,ami));
- ami=_mm_add_ps(ami,t0);
- ami=_mm_add_ss(ami,_mm_shuffle_ps(ami,ami,1));
- __m128 t1(_mm_movehl_ps(bmi,bmi));
- bmi=_mm_add_ps(bmi,t1);
- bmi=_mm_add_ss(bmi,_mm_shuffle_ps(bmi,bmi,1));
-
+ __m128 omi(_mm_load_ps(o.mi));
+ omi = _mm_add_ps(omi, _mm_load_ps(o.mx));
+ __m128 ami(_mm_load_ps(a.mi));
+ ami = _mm_add_ps(ami, _mm_load_ps(a.mx));
+ ami = _mm_sub_ps(ami, omi);
+ ami = _mm_and_ps(ami, _mm_load_ps((const float*)mask));
+ __m128 bmi(_mm_load_ps(b.mi));
+ bmi = _mm_add_ps(bmi, _mm_load_ps(b.mx));
+ bmi = _mm_sub_ps(bmi, omi);
+ bmi = _mm_and_ps(bmi, _mm_load_ps((const float*)mask));
+ __m128 t0(_mm_movehl_ps(ami, ami));
+ ami = _mm_add_ps(ami, t0);
+ ami = _mm_add_ss(ami, _mm_shuffle_ps(ami, ami, 1));
+ __m128 t1(_mm_movehl_ps(bmi, bmi));
+ bmi = _mm_add_ps(bmi, t1);
+ bmi = _mm_add_ss(bmi, _mm_shuffle_ps(bmi, bmi, 1));
+
btSSEUnion tmp;
- tmp.ssereg = _mm_cmple_ss(bmi,ami);
- return tmp.ints[0]&1;
+ tmp.ssereg = _mm_cmple_ss(bmi, ami);
+ return tmp.ints[0] & 1;
#else
- ATTRIBUTE_ALIGNED16(__int32 r[1]);
+ ATTRIBUTE_ALIGNED16(__int32 r[1]);
__asm
{
mov eax,o
@@ -656,46 +689,52 @@ DBVT_INLINE int Select( const btDbvtAabbMm& o,
cmpless xmm2,xmm1
movss r,xmm2
}
- return(r[0]&1);
+ return (r[0] & 1);
#endif
#else
- return(Proximity(o,a)<Proximity(o,b)?0:1);
+ return (Proximity(o, a) < Proximity(o, b) ? 0 : 1);
#endif
}
//
-DBVT_INLINE void Merge( const btDbvtAabbMm& a,
- const btDbvtAabbMm& b,
- btDbvtAabbMm& r)
+DBVT_INLINE void Merge(const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b,
+ btDbvtAabbMm& r)
{
-#if DBVT_MERGE_IMPL==DBVT_IMPL_SSE
- __m128 ami(_mm_load_ps(a.mi));
- __m128 amx(_mm_load_ps(a.mx));
- __m128 bmi(_mm_load_ps(b.mi));
- __m128 bmx(_mm_load_ps(b.mx));
- ami=_mm_min_ps(ami,bmi);
- amx=_mm_max_ps(amx,bmx);
- _mm_store_ps(r.mi,ami);
- _mm_store_ps(r.mx,amx);
+#if DBVT_MERGE_IMPL == DBVT_IMPL_SSE
+ __m128 ami(_mm_load_ps(a.mi));
+ __m128 amx(_mm_load_ps(a.mx));
+ __m128 bmi(_mm_load_ps(b.mi));
+ __m128 bmx(_mm_load_ps(b.mx));
+ ami = _mm_min_ps(ami, bmi);
+ amx = _mm_max_ps(amx, bmx);
+ _mm_store_ps(r.mi, ami);
+ _mm_store_ps(r.mx, amx);
#else
- for(int i=0;i<3;++i)
+ for (int i = 0; i < 3; ++i)
{
- if(a.mi[i]<b.mi[i]) r.mi[i]=a.mi[i]; else r.mi[i]=b.mi[i];
- if(a.mx[i]>b.mx[i]) r.mx[i]=a.mx[i]; else r.mx[i]=b.mx[i];
+ if (a.mi[i] < b.mi[i])
+ r.mi[i] = a.mi[i];
+ else
+ r.mi[i] = b.mi[i];
+ if (a.mx[i] > b.mx[i])
+ r.mx[i] = a.mx[i];
+ else
+ r.mx[i] = b.mx[i];
}
#endif
}
//
-DBVT_INLINE bool NotEqual( const btDbvtAabbMm& a,
- const btDbvtAabbMm& b)
+DBVT_INLINE bool NotEqual(const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b)
{
- return( (a.mi.x()!=b.mi.x())||
- (a.mi.y()!=b.mi.y())||
- (a.mi.z()!=b.mi.z())||
- (a.mx.x()!=b.mx.x())||
- (a.mx.y()!=b.mx.y())||
- (a.mx.z()!=b.mx.z()));
+ return ((a.mi.x() != b.mi.x()) ||
+ (a.mi.y() != b.mi.y()) ||
+ (a.mi.z() != b.mi.z()) ||
+ (a.mx.x() != b.mx.x()) ||
+ (a.mx.y() != b.mx.y()) ||
+ (a.mx.z() != b.mx.z()));
}
//
@@ -704,162 +743,162 @@ DBVT_INLINE bool NotEqual( const btDbvtAabbMm& a,
//
DBVT_PREFIX
-inline void btDbvt::enumNodes( const btDbvtNode* root,
- DBVT_IPOLICY)
+inline void btDbvt::enumNodes(const btDbvtNode* root,
+ DBVT_IPOLICY)
{
DBVT_CHECKTYPE
- policy.Process(root);
- if(root->isinternal())
+ policy.Process(root);
+ if (root->isinternal())
{
- enumNodes(root->childs[0],policy);
- enumNodes(root->childs[1],policy);
+ enumNodes(root->childs[0], policy);
+ enumNodes(root->childs[1], policy);
}
}
//
DBVT_PREFIX
-inline void btDbvt::enumLeaves( const btDbvtNode* root,
- DBVT_IPOLICY)
+inline void btDbvt::enumLeaves(const btDbvtNode* root,
+ DBVT_IPOLICY)
{
DBVT_CHECKTYPE
- if(root->isinternal())
- {
- enumLeaves(root->childs[0],policy);
- enumLeaves(root->childs[1],policy);
- }
- else
- {
- policy.Process(root);
- }
+ if (root->isinternal())
+ {
+ enumLeaves(root->childs[0], policy);
+ enumLeaves(root->childs[1], policy);
+ }
+ else
+ {
+ policy.Process(root);
+ }
}
//
DBVT_PREFIX
-inline void btDbvt::collideTT( const btDbvtNode* root0,
- const btDbvtNode* root1,
- DBVT_IPOLICY)
+inline void btDbvt::collideTT(const btDbvtNode* root0,
+ const btDbvtNode* root1,
+ DBVT_IPOLICY)
{
DBVT_CHECKTYPE
- if(root0&&root1)
+ if (root0 && root1)
+ {
+ int depth = 1;
+ int treshold = DOUBLE_STACKSIZE - 4;
+ btAlignedObjectArray<sStkNN> stkStack;
+ stkStack.resize(DOUBLE_STACKSIZE);
+ stkStack[0] = sStkNN(root0, root1);
+ do
{
- int depth=1;
- int treshold=DOUBLE_STACKSIZE-4;
- btAlignedObjectArray<sStkNN> stkStack;
- stkStack.resize(DOUBLE_STACKSIZE);
- stkStack[0]=sStkNN(root0,root1);
- do {
- sStkNN p=stkStack[--depth];
- if(depth>treshold)
+ sStkNN p = stkStack[--depth];
+ if (depth > treshold)
+ {
+ stkStack.resize(stkStack.size() * 2);
+ treshold = stkStack.size() - 4;
+ }
+ if (p.a == p.b)
+ {
+ if (p.a->isinternal())
{
- stkStack.resize(stkStack.size()*2);
- treshold=stkStack.size()-4;
+ stkStack[depth++] = sStkNN(p.a->childs[0], p.a->childs[0]);
+ stkStack[depth++] = sStkNN(p.a->childs[1], p.a->childs[1]);
+ stkStack[depth++] = sStkNN(p.a->childs[0], p.a->childs[1]);
}
- if(p.a==p.b)
+ }
+ else if (Intersect(p.a->volume, p.b->volume))
+ {
+ if (p.a->isinternal())
{
- if(p.a->isinternal())
+ if (p.b->isinternal())
+ {
+ stkStack[depth++] = sStkNN(p.a->childs[0], p.b->childs[0]);
+ stkStack[depth++] = sStkNN(p.a->childs[1], p.b->childs[0]);
+ stkStack[depth++] = sStkNN(p.a->childs[0], p.b->childs[1]);
+ stkStack[depth++] = sStkNN(p.a->childs[1], p.b->childs[1]);
+ }
+ else
{
- stkStack[depth++]=sStkNN(p.a->childs[0],p.a->childs[0]);
- stkStack[depth++]=sStkNN(p.a->childs[1],p.a->childs[1]);
- stkStack[depth++]=sStkNN(p.a->childs[0],p.a->childs[1]);
+ stkStack[depth++] = sStkNN(p.a->childs[0], p.b);
+ stkStack[depth++] = sStkNN(p.a->childs[1], p.b);
}
}
- else if(Intersect(p.a->volume,p.b->volume))
+ else
{
- if(p.a->isinternal())
+ if (p.b->isinternal())
{
- if(p.b->isinternal())
- {
- stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]);
- stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]);
- stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]);
- stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]);
- }
- else
- {
- stkStack[depth++]=sStkNN(p.a->childs[0],p.b);
- stkStack[depth++]=sStkNN(p.a->childs[1],p.b);
- }
+ stkStack[depth++] = sStkNN(p.a, p.b->childs[0]);
+ stkStack[depth++] = sStkNN(p.a, p.b->childs[1]);
}
else
{
- if(p.b->isinternal())
- {
- stkStack[depth++]=sStkNN(p.a,p.b->childs[0]);
- stkStack[depth++]=sStkNN(p.a,p.b->childs[1]);
- }
- else
- {
- policy.Process(p.a,p.b);
- }
+ policy.Process(p.a, p.b);
}
}
- } while(depth);
- }
+ }
+ } while (depth);
+ }
}
-
-
DBVT_PREFIX
-inline void btDbvt::collideTTpersistentStack( const btDbvtNode* root0,
- const btDbvtNode* root1,
- DBVT_IPOLICY)
+inline void btDbvt::collideTTpersistentStack(const btDbvtNode* root0,
+ const btDbvtNode* root1,
+ DBVT_IPOLICY)
{
DBVT_CHECKTYPE
- if(root0&&root1)
+ if (root0 && root1)
+ {
+ int depth = 1;
+ int treshold = DOUBLE_STACKSIZE - 4;
+
+ m_stkStack.resize(DOUBLE_STACKSIZE);
+ m_stkStack[0] = sStkNN(root0, root1);
+ do
{
- int depth=1;
- int treshold=DOUBLE_STACKSIZE-4;
-
- m_stkStack.resize(DOUBLE_STACKSIZE);
- m_stkStack[0]=sStkNN(root0,root1);
- do {
- sStkNN p=m_stkStack[--depth];
- if(depth>treshold)
+ sStkNN p = m_stkStack[--depth];
+ if (depth > treshold)
+ {
+ m_stkStack.resize(m_stkStack.size() * 2);
+ treshold = m_stkStack.size() - 4;
+ }
+ if (p.a == p.b)
+ {
+ if (p.a->isinternal())
{
- m_stkStack.resize(m_stkStack.size()*2);
- treshold=m_stkStack.size()-4;
+ m_stkStack[depth++] = sStkNN(p.a->childs[0], p.a->childs[0]);
+ m_stkStack[depth++] = sStkNN(p.a->childs[1], p.a->childs[1]);
+ m_stkStack[depth++] = sStkNN(p.a->childs[0], p.a->childs[1]);
}
- if(p.a==p.b)
+ }
+ else if (Intersect(p.a->volume, p.b->volume))
+ {
+ if (p.a->isinternal())
{
- if(p.a->isinternal())
+ if (p.b->isinternal())
{
- m_stkStack[depth++]=sStkNN(p.a->childs[0],p.a->childs[0]);
- m_stkStack[depth++]=sStkNN(p.a->childs[1],p.a->childs[1]);
- m_stkStack[depth++]=sStkNN(p.a->childs[0],p.a->childs[1]);
+ m_stkStack[depth++] = sStkNN(p.a->childs[0], p.b->childs[0]);
+ m_stkStack[depth++] = sStkNN(p.a->childs[1], p.b->childs[0]);
+ m_stkStack[depth++] = sStkNN(p.a->childs[0], p.b->childs[1]);
+ m_stkStack[depth++] = sStkNN(p.a->childs[1], p.b->childs[1]);
+ }
+ else
+ {
+ m_stkStack[depth++] = sStkNN(p.a->childs[0], p.b);
+ m_stkStack[depth++] = sStkNN(p.a->childs[1], p.b);
}
}
- else if(Intersect(p.a->volume,p.b->volume))
+ else
{
- if(p.a->isinternal())
+ if (p.b->isinternal())
{
- if(p.b->isinternal())
- {
- m_stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]);
- m_stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]);
- m_stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]);
- m_stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]);
- }
- else
- {
- m_stkStack[depth++]=sStkNN(p.a->childs[0],p.b);
- m_stkStack[depth++]=sStkNN(p.a->childs[1],p.b);
- }
+ m_stkStack[depth++] = sStkNN(p.a, p.b->childs[0]);
+ m_stkStack[depth++] = sStkNN(p.a, p.b->childs[1]);
}
else
{
- if(p.b->isinternal())
- {
- m_stkStack[depth++]=sStkNN(p.a,p.b->childs[0]);
- m_stkStack[depth++]=sStkNN(p.a,p.b->childs[1]);
- }
- else
- {
- policy.Process(p.a,p.b);
- }
+ policy.Process(p.a, p.b);
}
}
- } while(depth);
- }
+ }
+ } while (depth);
+ }
}
#if 0
@@ -929,33 +968,35 @@ inline void btDbvt::collideTT( const btDbvtNode* root0,
const btTransform xform=xform0.inverse()*xform1;
collideTT(root0,root1,xform,policy);
}
-#endif
+#endif
DBVT_PREFIX
-inline void btDbvt::collideTV( const btDbvtNode* root,
- const btDbvtVolume& vol,
- DBVT_IPOLICY) const
+inline void btDbvt::collideTV(const btDbvtNode* root,
+ const btDbvtVolume& vol,
+ DBVT_IPOLICY) const
{
DBVT_CHECKTYPE
- if(root)
+ if (root)
{
- ATTRIBUTE_ALIGNED16(btDbvtVolume) volume(vol);
- btAlignedObjectArray<const btDbvtNode*> stack;
+ ATTRIBUTE_ALIGNED16(btDbvtVolume)
+ volume(vol);
+ btAlignedObjectArray<const btDbvtNode*> stack;
stack.resize(0);
#ifndef BT_DISABLE_STACK_TEMP_MEMORY
- char tempmemory[SIMPLE_STACKSIZE*sizeof(const btDbvtNode*)];
+ char tempmemory[SIMPLE_STACKSIZE * sizeof(const btDbvtNode*)];
stack.initializeFromBuffer(tempmemory, 0, SIMPLE_STACKSIZE);
#else
stack.reserve(SIMPLE_STACKSIZE);
-#endif //BT_DISABLE_STACK_TEMP_MEMORY
+#endif //BT_DISABLE_STACK_TEMP_MEMORY
stack.push_back(root);
- do {
- const btDbvtNode* n=stack[stack.size()-1];
+ do
+ {
+ const btDbvtNode* n = stack[stack.size() - 1];
stack.pop_back();
- if(Intersect(n->volume,volume))
+ if (Intersect(n->volume, volume))
{
- if(n->isinternal())
+ if (n->isinternal())
{
stack.push_back(n->childs[0]);
stack.push_back(n->childs[1]);
@@ -965,30 +1006,32 @@ inline void btDbvt::collideTV( const btDbvtNode* root,
policy.Process(n);
}
}
- } while(stack.size()>0);
+ } while (stack.size() > 0);
}
}
//
DBVT_PREFIX
-inline void btDbvt::collideTVNoStackAlloc( const btDbvtNode* root,
- const btDbvtVolume& vol,
- btNodeStack& stack,
- DBVT_IPOLICY) const
+inline void btDbvt::collideTVNoStackAlloc(const btDbvtNode* root,
+ const btDbvtVolume& vol,
+ btNodeStack& stack,
+ DBVT_IPOLICY) const
{
DBVT_CHECKTYPE
- if(root)
+ if (root)
{
- ATTRIBUTE_ALIGNED16(btDbvtVolume) volume(vol);
+ ATTRIBUTE_ALIGNED16(btDbvtVolume)
+ volume(vol);
stack.resize(0);
stack.reserve(SIMPLE_STACKSIZE);
stack.push_back(root);
- do {
- const btDbvtNode* n=stack[stack.size()-1];
+ do
+ {
+ const btDbvtNode* n = stack[stack.size() - 1];
stack.pop_back();
- if(Intersect(n->volume,volume))
+ if (Intersect(n->volume, volume))
{
- if(n->isinternal())
+ if (n->isinternal())
{
stack.push_back(n->childs[0]);
stack.push_back(n->childs[1]);
@@ -998,328 +1041,346 @@ inline void btDbvt::collideTVNoStackAlloc( const btDbvtNode* root,
policy.Process(n);
}
}
- } while(stack.size()>0);
+ } while (stack.size() > 0);
}
}
-
DBVT_PREFIX
-inline void btDbvt::rayTestInternal( const btDbvtNode* root,
- const btVector3& rayFrom,
- const btVector3& rayTo,
- const btVector3& rayDirectionInverse,
- unsigned int signs[3],
- btScalar lambda_max,
- const btVector3& aabbMin,
- const btVector3& aabbMax,
- btAlignedObjectArray<const btDbvtNode*>& stack,
- DBVT_IPOLICY ) const
+inline void btDbvt::rayTestInternal(const btDbvtNode* root,
+ const btVector3& rayFrom,
+ const btVector3& rayTo,
+ const btVector3& rayDirectionInverse,
+ unsigned int signs[3],
+ btScalar lambda_max,
+ const btVector3& aabbMin,
+ const btVector3& aabbMax,
+ btAlignedObjectArray<const btDbvtNode*>& stack,
+ DBVT_IPOLICY) const
{
- (void) rayTo;
+ (void)rayTo;
DBVT_CHECKTYPE
- if(root)
+ if (root)
{
btVector3 resultNormal;
- int depth=1;
- int treshold=DOUBLE_STACKSIZE-2;
+ int depth = 1;
+ int treshold = DOUBLE_STACKSIZE - 2;
stack.resize(DOUBLE_STACKSIZE);
- stack[0]=root;
+ stack[0] = root;
btVector3 bounds[2];
- do
+ do
{
- const btDbvtNode* node=stack[--depth];
- bounds[0] = node->volume.Mins()-aabbMax;
- bounds[1] = node->volume.Maxs()-aabbMin;
- btScalar tmin=1.f,lambda_min=0.f;
- unsigned int result1=false;
- result1 = btRayAabb2(rayFrom,rayDirectionInverse,signs,bounds,tmin,lambda_min,lambda_max);
- if(result1)
+ const btDbvtNode* node = stack[--depth];
+ bounds[0] = node->volume.Mins() - aabbMax;
+ bounds[1] = node->volume.Maxs() - aabbMin;
+ btScalar tmin = 1.f, lambda_min = 0.f;
+ unsigned int result1 = false;
+ result1 = btRayAabb2(rayFrom, rayDirectionInverse, signs, bounds, tmin, lambda_min, lambda_max);
+ if (result1)
{
- if(node->isinternal())
+ if (node->isinternal())
{
- if(depth>treshold)
+ if (depth > treshold)
{
- stack.resize(stack.size()*2);
- treshold=stack.size()-2;
+ stack.resize(stack.size() * 2);
+ treshold = stack.size() - 2;
}
- stack[depth++]=node->childs[0];
- stack[depth++]=node->childs[1];
+ stack[depth++] = node->childs[0];
+ stack[depth++] = node->childs[1];
}
else
{
policy.Process(node);
}
}
- } while(depth);
+ } while (depth);
}
}
//
DBVT_PREFIX
-inline void btDbvt::rayTest( const btDbvtNode* root,
- const btVector3& rayFrom,
- const btVector3& rayTo,
- DBVT_IPOLICY)
+inline void btDbvt::rayTest(const btDbvtNode* root,
+ const btVector3& rayFrom,
+ const btVector3& rayTo,
+ DBVT_IPOLICY)
{
DBVT_CHECKTYPE
- if(root)
- {
- btVector3 rayDir = (rayTo-rayFrom);
- rayDir.normalize ();
+ if (root)
+ {
+ btVector3 rayDir = (rayTo - rayFrom);
+ rayDir.normalize();
- ///what about division by zero? --> just set rayDirection[i] to INF/BT_LARGE_FLOAT
- btVector3 rayDirectionInverse;
- rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0];
- rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1];
- rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2];
- unsigned int signs[3] = { rayDirectionInverse[0] < 0.0, rayDirectionInverse[1] < 0.0, rayDirectionInverse[2] < 0.0};
+ ///what about division by zero? --> just set rayDirection[i] to INF/BT_LARGE_FLOAT
+ btVector3 rayDirectionInverse;
+ rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0];
+ rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1];
+ rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2];
+ unsigned int signs[3] = {rayDirectionInverse[0] < 0.0, rayDirectionInverse[1] < 0.0, rayDirectionInverse[2] < 0.0};
- btScalar lambda_max = rayDir.dot(rayTo-rayFrom);
+ btScalar lambda_max = rayDir.dot(rayTo - rayFrom);
- btVector3 resultNormal;
+ btVector3 resultNormal;
- btAlignedObjectArray<const btDbvtNode*> stack;
+ btAlignedObjectArray<const btDbvtNode*> stack;
- int depth=1;
- int treshold=DOUBLE_STACKSIZE-2;
+ int depth = 1;
+ int treshold = DOUBLE_STACKSIZE - 2;
- char tempmemory[DOUBLE_STACKSIZE * sizeof(const btDbvtNode*)];
+ char tempmemory[DOUBLE_STACKSIZE * sizeof(const btDbvtNode*)];
#ifndef BT_DISABLE_STACK_TEMP_MEMORY
- stack.initializeFromBuffer(tempmemory, DOUBLE_STACKSIZE, DOUBLE_STACKSIZE);
-#else//BT_DISABLE_STACK_TEMP_MEMORY
- stack.resize(DOUBLE_STACKSIZE);
-#endif //BT_DISABLE_STACK_TEMP_MEMORY
- stack[0]=root;
- btVector3 bounds[2];
- do {
- const btDbvtNode* node=stack[--depth];
+ stack.initializeFromBuffer(tempmemory, DOUBLE_STACKSIZE, DOUBLE_STACKSIZE);
+#else //BT_DISABLE_STACK_TEMP_MEMORY
+ stack.resize(DOUBLE_STACKSIZE);
+#endif //BT_DISABLE_STACK_TEMP_MEMORY
+ stack[0] = root;
+ btVector3 bounds[2];
+ do
+ {
+ const btDbvtNode* node = stack[--depth];
+
+ bounds[0] = node->volume.Mins();
+ bounds[1] = node->volume.Maxs();
- bounds[0] = node->volume.Mins();
- bounds[1] = node->volume.Maxs();
-
- btScalar tmin=1.f,lambda_min=0.f;
- unsigned int result1 = btRayAabb2(rayFrom,rayDirectionInverse,signs,bounds,tmin,lambda_min,lambda_max);
+ btScalar tmin = 1.f, lambda_min = 0.f;
+ unsigned int result1 = btRayAabb2(rayFrom, rayDirectionInverse, signs, bounds, tmin, lambda_min, lambda_max);
#ifdef COMPARE_BTRAY_AABB2
- btScalar param=1.f;
- bool result2 = btRayAabb(rayFrom,rayTo,node->volume.Mins(),node->volume.Maxs(),param,resultNormal);
- btAssert(result1 == result2);
-#endif //TEST_BTRAY_AABB2
+ btScalar param = 1.f;
+ bool result2 = btRayAabb(rayFrom, rayTo, node->volume.Mins(), node->volume.Maxs(), param, resultNormal);
+ btAssert(result1 == result2);
+#endif //TEST_BTRAY_AABB2
- if(result1)
+ if (result1)
+ {
+ if (node->isinternal())
{
- if(node->isinternal())
+ if (depth > treshold)
{
- if(depth>treshold)
- {
- stack.resize(stack.size()*2);
- treshold=stack.size()-2;
- }
- stack[depth++]=node->childs[0];
- stack[depth++]=node->childs[1];
- }
- else
- {
- policy.Process(node);
+ stack.resize(stack.size() * 2);
+ treshold = stack.size() - 2;
}
+ stack[depth++] = node->childs[0];
+ stack[depth++] = node->childs[1];
}
- } while(depth);
-
- }
+ else
+ {
+ policy.Process(node);
+ }
+ }
+ } while (depth);
+ }
}
//
DBVT_PREFIX
-inline void btDbvt::collideKDOP(const btDbvtNode* root,
- const btVector3* normals,
- const btScalar* offsets,
- int count,
- DBVT_IPOLICY)
+inline void btDbvt::collideKDOP(const btDbvtNode* root,
+ const btVector3* normals,
+ const btScalar* offsets,
+ int count,
+ DBVT_IPOLICY)
{
DBVT_CHECKTYPE
- if(root)
+ if (root)
+ {
+ const int inside = (1 << count) - 1;
+ btAlignedObjectArray<sStkNP> stack;
+ int signs[sizeof(unsigned) * 8];
+ btAssert(count < int(sizeof(signs) / sizeof(signs[0])));
+ for (int i = 0; i < count; ++i)
{
- const int inside=(1<<count)-1;
- btAlignedObjectArray<sStkNP> stack;
- int signs[sizeof(unsigned)*8];
- btAssert(count<int (sizeof(signs)/sizeof(signs[0])));
- for(int i=0;i<count;++i)
+ signs[i] = ((normals[i].x() >= 0) ? 1 : 0) +
+ ((normals[i].y() >= 0) ? 2 : 0) +
+ ((normals[i].z() >= 0) ? 4 : 0);
+ }
+ stack.reserve(SIMPLE_STACKSIZE);
+ stack.push_back(sStkNP(root, 0));
+ do
+ {
+ sStkNP se = stack[stack.size() - 1];
+ bool out = false;
+ stack.pop_back();
+ for (int i = 0, j = 1; (!out) && (i < count); ++i, j <<= 1)
{
- signs[i]= ((normals[i].x()>=0)?1:0)+
- ((normals[i].y()>=0)?2:0)+
- ((normals[i].z()>=0)?4:0);
- }
- stack.reserve(SIMPLE_STACKSIZE);
- stack.push_back(sStkNP(root,0));
- do {
- sStkNP se=stack[stack.size()-1];
- bool out=false;
- stack.pop_back();
- for(int i=0,j=1;(!out)&&(i<count);++i,j<<=1)
+ if (0 == (se.mask & j))
{
- if(0==(se.mask&j))
+ const int side = se.node->volume.Classify(normals[i], offsets[i], signs[i]);
+ switch (side)
{
- const int side=se.node->volume.Classify(normals[i],offsets[i],signs[i]);
- switch(side)
- {
- case -1: out=true;break;
- case +1: se.mask|=j;break;
- }
+ case -1:
+ out = true;
+ break;
+ case +1:
+ se.mask |= j;
+ break;
}
}
- if(!out)
+ }
+ if (!out)
+ {
+ if ((se.mask != inside) && (se.node->isinternal()))
{
- if((se.mask!=inside)&&(se.node->isinternal()))
- {
- stack.push_back(sStkNP(se.node->childs[0],se.mask));
- stack.push_back(sStkNP(se.node->childs[1],se.mask));
- }
- else
- {
- if(policy.AllLeaves(se.node)) enumLeaves(se.node,policy);
- }
+ stack.push_back(sStkNP(se.node->childs[0], se.mask));
+ stack.push_back(sStkNP(se.node->childs[1], se.mask));
}
- } while(stack.size());
- }
+ else
+ {
+ if (policy.AllLeaves(se.node)) enumLeaves(se.node, policy);
+ }
+ }
+ } while (stack.size());
+ }
}
//
DBVT_PREFIX
-inline void btDbvt::collideOCL( const btDbvtNode* root,
- const btVector3* normals,
- const btScalar* offsets,
- const btVector3& sortaxis,
- int count,
- DBVT_IPOLICY,
- bool fsort)
+inline void btDbvt::collideOCL(const btDbvtNode* root,
+ const btVector3* normals,
+ const btScalar* offsets,
+ const btVector3& sortaxis,
+ int count,
+ DBVT_IPOLICY,
+ bool fsort)
{
DBVT_CHECKTYPE
- if(root)
+ if (root)
+ {
+ const unsigned srtsgns = (sortaxis[0] >= 0 ? 1 : 0) +
+ (sortaxis[1] >= 0 ? 2 : 0) +
+ (sortaxis[2] >= 0 ? 4 : 0);
+ const int inside = (1 << count) - 1;
+ btAlignedObjectArray<sStkNPS> stock;
+ btAlignedObjectArray<int> ifree;
+ btAlignedObjectArray<int> stack;
+ int signs[sizeof(unsigned) * 8];
+ btAssert(count < int(sizeof(signs) / sizeof(signs[0])));
+ for (int i = 0; i < count; ++i)
{
- const unsigned srtsgns=(sortaxis[0]>=0?1:0)+
- (sortaxis[1]>=0?2:0)+
- (sortaxis[2]>=0?4:0);
- const int inside=(1<<count)-1;
- btAlignedObjectArray<sStkNPS> stock;
- btAlignedObjectArray<int> ifree;
- btAlignedObjectArray<int> stack;
- int signs[sizeof(unsigned)*8];
- btAssert(count<int (sizeof(signs)/sizeof(signs[0])));
- for(int i=0;i<count;++i)
+ signs[i] = ((normals[i].x() >= 0) ? 1 : 0) +
+ ((normals[i].y() >= 0) ? 2 : 0) +
+ ((normals[i].z() >= 0) ? 4 : 0);
+ }
+ stock.reserve(SIMPLE_STACKSIZE);
+ stack.reserve(SIMPLE_STACKSIZE);
+ ifree.reserve(SIMPLE_STACKSIZE);
+ stack.push_back(allocate(ifree, stock, sStkNPS(root, 0, root->volume.ProjectMinimum(sortaxis, srtsgns))));
+ do
+ {
+ const int id = stack[stack.size() - 1];
+ sStkNPS se = stock[id];
+ stack.pop_back();
+ ifree.push_back(id);
+ if (se.mask != inside)
{
- signs[i]= ((normals[i].x()>=0)?1:0)+
- ((normals[i].y()>=0)?2:0)+
- ((normals[i].z()>=0)?4:0);
- }
- stock.reserve(SIMPLE_STACKSIZE);
- stack.reserve(SIMPLE_STACKSIZE);
- ifree.reserve(SIMPLE_STACKSIZE);
- stack.push_back(allocate(ifree,stock,sStkNPS(root,0,root->volume.ProjectMinimum(sortaxis,srtsgns))));
- do {
- const int id=stack[stack.size()-1];
- sStkNPS se=stock[id];
- stack.pop_back();ifree.push_back(id);
- if(se.mask!=inside)
+ bool out = false;
+ for (int i = 0, j = 1; (!out) && (i < count); ++i, j <<= 1)
{
- bool out=false;
- for(int i=0,j=1;(!out)&&(i<count);++i,j<<=1)
+ if (0 == (se.mask & j))
{
- if(0==(se.mask&j))
+ const int side = se.node->volume.Classify(normals[i], offsets[i], signs[i]);
+ switch (side)
{
- const int side=se.node->volume.Classify(normals[i],offsets[i],signs[i]);
- switch(side)
- {
- case -1: out=true;break;
- case +1: se.mask|=j;break;
- }
+ case -1:
+ out = true;
+ break;
+ case +1:
+ se.mask |= j;
+ break;
}
}
- if(out) continue;
}
- if(policy.Descent(se.node))
+ if (out) continue;
+ }
+ if (policy.Descent(se.node))
+ {
+ if (se.node->isinternal())
{
- if(se.node->isinternal())
+ const btDbvtNode* pns[] = {se.node->childs[0], se.node->childs[1]};
+ sStkNPS nes[] = {sStkNPS(pns[0], se.mask, pns[0]->volume.ProjectMinimum(sortaxis, srtsgns)),
+ sStkNPS(pns[1], se.mask, pns[1]->volume.ProjectMinimum(sortaxis, srtsgns))};
+ const int q = nes[0].value < nes[1].value ? 1 : 0;
+ int j = stack.size();
+ if (fsort && (j > 0))
{
- const btDbvtNode* pns[]={ se.node->childs[0],se.node->childs[1]};
- sStkNPS nes[]={ sStkNPS(pns[0],se.mask,pns[0]->volume.ProjectMinimum(sortaxis,srtsgns)),
- sStkNPS(pns[1],se.mask,pns[1]->volume.ProjectMinimum(sortaxis,srtsgns))};
- const int q=nes[0].value<nes[1].value?1:0;
- int j=stack.size();
- if(fsort&&(j>0))
- {
- /* Insert 0 */
- j=nearest(&stack[0],&stock[0],nes[q].value,0,stack.size());
- stack.push_back(0);
-
- //void * memmove ( void * destination, const void * source, size_t num );
-
+ /* Insert 0 */
+ j = nearest(&stack[0], &stock[0], nes[q].value, 0, stack.size());
+ stack.push_back(0);
+
+ //void * memmove ( void * destination, const void * source, size_t num );
+
#if DBVT_USE_MEMMOVE
- {
- int num_items_to_move = stack.size()-1-j;
- if(num_items_to_move > 0)
- memmove(&stack[j+1],&stack[j],sizeof(int)*num_items_to_move);
- }
+ {
+ int num_items_to_move = stack.size() - 1 - j;
+ if (num_items_to_move > 0)
+ memmove(&stack[j + 1], &stack[j], sizeof(int) * num_items_to_move);
+ }
#else
- for(int k=stack.size()-1;k>j;--k) {
- stack[k]=stack[k-1];
- }
+ for (int k = stack.size() - 1; k > j; --k)
+ {
+ stack[k] = stack[k - 1];
+ }
#endif
- stack[j]=allocate(ifree,stock,nes[q]);
- /* Insert 1 */
- j=nearest(&stack[0],&stock[0],nes[1-q].value,j,stack.size());
- stack.push_back(0);
+ stack[j] = allocate(ifree, stock, nes[q]);
+ /* Insert 1 */
+ j = nearest(&stack[0], &stock[0], nes[1 - q].value, j, stack.size());
+ stack.push_back(0);
#if DBVT_USE_MEMMOVE
- {
- int num_items_to_move = stack.size()-1-j;
- if(num_items_to_move > 0)
- memmove(&stack[j+1],&stack[j],sizeof(int)*num_items_to_move);
- }
-#else
- for(int k=stack.size()-1;k>j;--k) {
- stack[k]=stack[k-1];
- }
-#endif
- stack[j]=allocate(ifree,stock,nes[1-q]);
+ {
+ int num_items_to_move = stack.size() - 1 - j;
+ if (num_items_to_move > 0)
+ memmove(&stack[j + 1], &stack[j], sizeof(int) * num_items_to_move);
}
- else
+#else
+ for (int k = stack.size() - 1; k > j; --k)
{
- stack.push_back(allocate(ifree,stock,nes[q]));
- stack.push_back(allocate(ifree,stock,nes[1-q]));
+ stack[k] = stack[k - 1];
}
+#endif
+ stack[j] = allocate(ifree, stock, nes[1 - q]);
}
else
{
- policy.Process(se.node,se.value);
+ stack.push_back(allocate(ifree, stock, nes[q]));
+ stack.push_back(allocate(ifree, stock, nes[1 - q]));
}
}
- } while(stack.size());
- }
+ else
+ {
+ policy.Process(se.node, se.value);
+ }
+ }
+ } while (stack.size());
+ }
}
//
DBVT_PREFIX
-inline void btDbvt::collideTU( const btDbvtNode* root,
- DBVT_IPOLICY)
+inline void btDbvt::collideTU(const btDbvtNode* root,
+ DBVT_IPOLICY)
{
DBVT_CHECKTYPE
- if(root)
+ if (root)
+ {
+ btAlignedObjectArray<const btDbvtNode*> stack;
+ stack.reserve(SIMPLE_STACKSIZE);
+ stack.push_back(root);
+ do
{
- btAlignedObjectArray<const btDbvtNode*> stack;
- stack.reserve(SIMPLE_STACKSIZE);
- stack.push_back(root);
- do {
- const btDbvtNode* n=stack[stack.size()-1];
- stack.pop_back();
- if(policy.Descent(n))
+ const btDbvtNode* n = stack[stack.size() - 1];
+ stack.pop_back();
+ if (policy.Descent(n))
+ {
+ if (n->isinternal())
{
- if(n->isinternal())
- { stack.push_back(n->childs[0]);stack.push_back(n->childs[1]); }
- else
- { policy.Process(n); }
+ stack.push_back(n->childs[0]);
+ stack.push_back(n->childs[1]);
}
- } while(stack.size()>0);
- }
+ else
+ {
+ policy.Process(n);
+ }
+ }
+ } while (stack.size() > 0);
+ }
}
//
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp
index 14cd1a31ea..7b39dbdc0f 100644
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp
+++ b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp
@@ -22,28 +22,27 @@ btScalar gDbvtMargin = btScalar(0.05);
// Profiling
//
-#if DBVT_BP_PROFILE||DBVT_BP_ENABLE_BENCHMARK
+#if DBVT_BP_PROFILE || DBVT_BP_ENABLE_BENCHMARK
#include <stdio.h>
#endif
#if DBVT_BP_PROFILE
-struct ProfileScope
+struct ProfileScope
{
- __forceinline ProfileScope(btClock& clock,unsigned long& value) :
- m_clock(&clock),m_value(&value),m_base(clock.getTimeMicroseconds())
+ __forceinline ProfileScope(btClock& clock, unsigned long& value) : m_clock(&clock), m_value(&value), m_base(clock.getTimeMicroseconds())
{
}
__forceinline ~ProfileScope()
{
- (*m_value)+=m_clock->getTimeMicroseconds()-m_base;
+ (*m_value) += m_clock->getTimeMicroseconds() - m_base;
}
- btClock* m_clock;
- unsigned long* m_value;
- unsigned long m_base;
+ btClock* m_clock;
+ unsigned long* m_value;
+ unsigned long m_base;
};
-#define SPC(_value_) ProfileScope spc_scope(m_clock,_value_)
+#define SPC(_value_) ProfileScope spc_scope(m_clock, _value_)
#else
-#define SPC(_value_)
+#define SPC(_value_)
#endif
//
@@ -52,66 +51,75 @@ struct ProfileScope
//
template <typename T>
-static inline void listappend(T* item,T*& list)
+static inline void listappend(T* item, T*& list)
{
- item->links[0]=0;
- item->links[1]=list;
- if(list) list->links[0]=item;
- list=item;
+ item->links[0] = 0;
+ item->links[1] = list;
+ if (list) list->links[0] = item;
+ list = item;
}
//
template <typename T>
-static inline void listremove(T* item,T*& list)
+static inline void listremove(T* item, T*& list)
{
- if(item->links[0]) item->links[0]->links[1]=item->links[1]; else list=item->links[1];
- if(item->links[1]) item->links[1]->links[0]=item->links[0];
+ if (item->links[0])
+ item->links[0]->links[1] = item->links[1];
+ else
+ list = item->links[1];
+ if (item->links[1]) item->links[1]->links[0] = item->links[0];
}
//
template <typename T>
-static inline int listcount(T* root)
+static inline int listcount(T* root)
{
- int n=0;
- while(root) { ++n;root=root->links[1]; }
- return(n);
+ int n = 0;
+ while (root)
+ {
+ ++n;
+ root = root->links[1];
+ }
+ return (n);
}
//
template <typename T>
-static inline void clear(T& value)
+static inline void clear(T& value)
{
- static const struct ZeroDummy : T {} zerodummy;
- value=zerodummy;
+ static const struct ZeroDummy : T
+ {
+ } zerodummy;
+ value = zerodummy;
}
//
// Colliders
//
-/* Tree collider */
-struct btDbvtTreeCollider : btDbvt::ICollide
+/* Tree collider */
+struct btDbvtTreeCollider : btDbvt::ICollide
{
- btDbvtBroadphase* pbp;
- btDbvtProxy* proxy;
+ btDbvtBroadphase* pbp;
+ btDbvtProxy* proxy;
btDbvtTreeCollider(btDbvtBroadphase* p) : pbp(p) {}
- void Process(const btDbvtNode* na,const btDbvtNode* nb)
+ void Process(const btDbvtNode* na, const btDbvtNode* nb)
{
- if(na!=nb)
+ if (na != nb)
{
- btDbvtProxy* pa=(btDbvtProxy*)na->data;
- btDbvtProxy* pb=(btDbvtProxy*)nb->data;
+ btDbvtProxy* pa = (btDbvtProxy*)na->data;
+ btDbvtProxy* pb = (btDbvtProxy*)nb->data;
#if DBVT_BP_SORTPAIRS
- if(pa->m_uniqueId>pb->m_uniqueId)
- btSwap(pa,pb);
+ if (pa->m_uniqueId > pb->m_uniqueId)
+ btSwap(pa, pb);
#endif
- pbp->m_paircache->addOverlappingPair(pa,pb);
+ pbp->m_paircache->addOverlappingPair(pa, pb);
++pbp->m_newpairs;
}
}
- void Process(const btDbvtNode* n)
+ void Process(const btDbvtNode* n)
{
- Process(n,proxy->leaf);
+ Process(n, proxy->leaf);
}
};
@@ -122,31 +130,31 @@ struct btDbvtTreeCollider : btDbvt::ICollide
//
btDbvtBroadphase::btDbvtBroadphase(btOverlappingPairCache* paircache)
{
- m_deferedcollide = false;
- m_needcleanup = true;
- m_releasepaircache = (paircache!=0)?false:true;
- m_prediction = 0;
- m_stageCurrent = 0;
- m_fixedleft = 0;
- m_fupdates = 1;
- m_dupdates = 0;
- m_cupdates = 10;
- m_newpairs = 1;
- m_updates_call = 0;
- m_updates_done = 0;
- m_updates_ratio = 0;
- m_paircache = paircache? paircache : new(btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache();
- m_gid = 0;
- m_pid = 0;
- m_cid = 0;
- for(int i=0;i<=STAGECOUNT;++i)
+ m_deferedcollide = false;
+ m_needcleanup = true;
+ m_releasepaircache = (paircache != 0) ? false : true;
+ m_prediction = 0;
+ m_stageCurrent = 0;
+ m_fixedleft = 0;
+ m_fupdates = 1;
+ m_dupdates = 0;
+ m_cupdates = 10;
+ m_newpairs = 1;
+ m_updates_call = 0;
+ m_updates_done = 0;
+ m_updates_ratio = 0;
+ m_paircache = paircache ? paircache : new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache), 16)) btHashedOverlappingPairCache();
+ m_gid = 0;
+ m_pid = 0;
+ m_cid = 0;
+ for (int i = 0; i <= STAGECOUNT; ++i)
{
- m_stageRoots[i]=0;
+ m_stageRoots[i] = 0;
}
#if BT_THREADSAFE
- m_rayTestStacks.resize(BT_MAX_THREAD_COUNT);
+ m_rayTestStacks.resize(BT_MAX_THREAD_COUNT);
#else
- m_rayTestStacks.resize(1);
+ m_rayTestStacks.resize(1);
#endif
#if DBVT_BP_PROFILE
clear(m_profiling);
@@ -156,7 +164,7 @@ btDbvtBroadphase::btDbvtBroadphase(btOverlappingPairCache* paircache)
//
btDbvtBroadphase::~btDbvtBroadphase()
{
- if(m_releasepaircache)
+ if (m_releasepaircache)
{
m_paircache->~btOverlappingPairCache();
btAlignedFree(m_paircache);
@@ -164,302 +172,294 @@ btDbvtBroadphase::~btDbvtBroadphase()
}
//
-btBroadphaseProxy* btDbvtBroadphase::createProxy( const btVector3& aabbMin,
- const btVector3& aabbMax,
- int /*shapeType*/,
- void* userPtr,
- int collisionFilterGroup,
- int collisionFilterMask,
- btDispatcher* /*dispatcher*/)
+btBroadphaseProxy* btDbvtBroadphase::createProxy(const btVector3& aabbMin,
+ const btVector3& aabbMax,
+ int /*shapeType*/,
+ void* userPtr,
+ int collisionFilterGroup,
+ int collisionFilterMask,
+ btDispatcher* /*dispatcher*/)
{
- btDbvtProxy* proxy=new(btAlignedAlloc(sizeof(btDbvtProxy),16)) btDbvtProxy( aabbMin,aabbMax,userPtr,
- collisionFilterGroup,
- collisionFilterMask);
+ btDbvtProxy* proxy = new (btAlignedAlloc(sizeof(btDbvtProxy), 16)) btDbvtProxy(aabbMin, aabbMax, userPtr,
+ collisionFilterGroup,
+ collisionFilterMask);
- btDbvtAabbMm aabb = btDbvtVolume::FromMM(aabbMin,aabbMax);
+ btDbvtAabbMm aabb = btDbvtVolume::FromMM(aabbMin, aabbMax);
//bproxy->aabb = btDbvtVolume::FromMM(aabbMin,aabbMax);
- proxy->stage = m_stageCurrent;
- proxy->m_uniqueId = ++m_gid;
- proxy->leaf = m_sets[0].insert(aabb,proxy);
- listappend(proxy,m_stageRoots[m_stageCurrent]);
- if(!m_deferedcollide)
+ proxy->stage = m_stageCurrent;
+ proxy->m_uniqueId = ++m_gid;
+ proxy->leaf = m_sets[0].insert(aabb, proxy);
+ listappend(proxy, m_stageRoots[m_stageCurrent]);
+ if (!m_deferedcollide)
{
- btDbvtTreeCollider collider(this);
- collider.proxy=proxy;
- m_sets[0].collideTV(m_sets[0].m_root,aabb,collider);
- m_sets[1].collideTV(m_sets[1].m_root,aabb,collider);
+ btDbvtTreeCollider collider(this);
+ collider.proxy = proxy;
+ m_sets[0].collideTV(m_sets[0].m_root, aabb, collider);
+ m_sets[1].collideTV(m_sets[1].m_root, aabb, collider);
}
- return(proxy);
+ return (proxy);
}
//
-void btDbvtBroadphase::destroyProxy( btBroadphaseProxy* absproxy,
- btDispatcher* dispatcher)
+void btDbvtBroadphase::destroyProxy(btBroadphaseProxy* absproxy,
+ btDispatcher* dispatcher)
{
- btDbvtProxy* proxy=(btDbvtProxy*)absproxy;
- if(proxy->stage==STAGECOUNT)
+ btDbvtProxy* proxy = (btDbvtProxy*)absproxy;
+ if (proxy->stage == STAGECOUNT)
m_sets[1].remove(proxy->leaf);
else
m_sets[0].remove(proxy->leaf);
- listremove(proxy,m_stageRoots[proxy->stage]);
- m_paircache->removeOverlappingPairsContainingProxy(proxy,dispatcher);
+ listremove(proxy, m_stageRoots[proxy->stage]);
+ m_paircache->removeOverlappingPairsContainingProxy(proxy, dispatcher);
btAlignedFree(proxy);
- m_needcleanup=true;
+ m_needcleanup = true;
}
-void btDbvtBroadphase::getAabb(btBroadphaseProxy* absproxy,btVector3& aabbMin, btVector3& aabbMax ) const
+void btDbvtBroadphase::getAabb(btBroadphaseProxy* absproxy, btVector3& aabbMin, btVector3& aabbMax) const
{
- btDbvtProxy* proxy=(btDbvtProxy*)absproxy;
+ btDbvtProxy* proxy = (btDbvtProxy*)absproxy;
aabbMin = proxy->m_aabbMin;
aabbMax = proxy->m_aabbMax;
}
-struct BroadphaseRayTester : btDbvt::ICollide
+struct BroadphaseRayTester : btDbvt::ICollide
{
btBroadphaseRayCallback& m_rayCallback;
BroadphaseRayTester(btBroadphaseRayCallback& orgCallback)
- :m_rayCallback(orgCallback)
+ : m_rayCallback(orgCallback)
{
}
- void Process(const btDbvtNode* leaf)
+ void Process(const btDbvtNode* leaf)
{
- btDbvtProxy* proxy=(btDbvtProxy*)leaf->data;
+ btDbvtProxy* proxy = (btDbvtProxy*)leaf->data;
m_rayCallback.process(proxy);
}
-};
+};
-void btDbvtBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback,const btVector3& aabbMin,const btVector3& aabbMax)
+void btDbvtBroadphase::rayTest(const btVector3& rayFrom, const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin, const btVector3& aabbMax)
{
BroadphaseRayTester callback(rayCallback);
- btAlignedObjectArray<const btDbvtNode*>* stack = &m_rayTestStacks[0];
+ btAlignedObjectArray<const btDbvtNode*>* stack = &m_rayTestStacks[0];
#if BT_THREADSAFE
- // for this function to be threadsafe, each thread must have a separate copy
- // of this stack. This could be thread-local static to avoid dynamic allocations,
- // instead of just a local.
- int threadIndex = btGetCurrentThreadIndex();
- btAlignedObjectArray<const btDbvtNode*> localStack;
- if (threadIndex < m_rayTestStacks.size())
- {
- // use per-thread preallocated stack if possible to avoid dynamic allocations
- stack = &m_rayTestStacks[threadIndex];
- }
- else
- {
- stack = &localStack;
- }
+ // for this function to be threadsafe, each thread must have a separate copy
+ // of this stack. This could be thread-local static to avoid dynamic allocations,
+ // instead of just a local.
+ int threadIndex = btGetCurrentThreadIndex();
+ btAlignedObjectArray<const btDbvtNode*> localStack;
+ //todo(erwincoumans, "why do we get tsan issue here?")
+ if (0)//threadIndex < m_rayTestStacks.size())
+ //if (threadIndex < m_rayTestStacks.size())
+ {
+ // use per-thread preallocated stack if possible to avoid dynamic allocations
+ stack = &m_rayTestStacks[threadIndex];
+ }
+ else
+ {
+ stack = &localStack;
+ }
#endif
- m_sets[0].rayTestInternal( m_sets[0].m_root,
- rayFrom,
- rayTo,
- rayCallback.m_rayDirectionInverse,
- rayCallback.m_signs,
- rayCallback.m_lambda_max,
- aabbMin,
- aabbMax,
- *stack,
- callback);
-
- m_sets[1].rayTestInternal( m_sets[1].m_root,
- rayFrom,
- rayTo,
- rayCallback.m_rayDirectionInverse,
- rayCallback.m_signs,
- rayCallback.m_lambda_max,
- aabbMin,
- aabbMax,
- *stack,
- callback);
-
+ m_sets[0].rayTestInternal(m_sets[0].m_root,
+ rayFrom,
+ rayTo,
+ rayCallback.m_rayDirectionInverse,
+ rayCallback.m_signs,
+ rayCallback.m_lambda_max,
+ aabbMin,
+ aabbMax,
+ *stack,
+ callback);
+
+ m_sets[1].rayTestInternal(m_sets[1].m_root,
+ rayFrom,
+ rayTo,
+ rayCallback.m_rayDirectionInverse,
+ rayCallback.m_signs,
+ rayCallback.m_lambda_max,
+ aabbMin,
+ aabbMax,
+ *stack,
+ callback);
}
-
-struct BroadphaseAabbTester : btDbvt::ICollide
+struct BroadphaseAabbTester : btDbvt::ICollide
{
btBroadphaseAabbCallback& m_aabbCallback;
BroadphaseAabbTester(btBroadphaseAabbCallback& orgCallback)
- :m_aabbCallback(orgCallback)
+ : m_aabbCallback(orgCallback)
{
}
- void Process(const btDbvtNode* leaf)
+ void Process(const btDbvtNode* leaf)
{
- btDbvtProxy* proxy=(btDbvtProxy*)leaf->data;
+ btDbvtProxy* proxy = (btDbvtProxy*)leaf->data;
m_aabbCallback.process(proxy);
}
-};
+};
-void btDbvtBroadphase::aabbTest(const btVector3& aabbMin,const btVector3& aabbMax,btBroadphaseAabbCallback& aabbCallback)
+void btDbvtBroadphase::aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& aabbCallback)
{
BroadphaseAabbTester callback(aabbCallback);
- const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(aabbMin,aabbMax);
- //process all children, that overlap with the given AABB bounds
- m_sets[0].collideTV(m_sets[0].m_root,bounds,callback);
- m_sets[1].collideTV(m_sets[1].m_root,bounds,callback);
-
+ const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds = btDbvtVolume::FromMM(aabbMin, aabbMax);
+ //process all children, that overlap with the given AABB bounds
+ m_sets[0].collideTV(m_sets[0].m_root, bounds, callback);
+ m_sets[1].collideTV(m_sets[1].m_root, bounds, callback);
}
-
-
//
-void btDbvtBroadphase::setAabb( btBroadphaseProxy* absproxy,
- const btVector3& aabbMin,
- const btVector3& aabbMax,
- btDispatcher* /*dispatcher*/)
+void btDbvtBroadphase::setAabb(btBroadphaseProxy* absproxy,
+ const btVector3& aabbMin,
+ const btVector3& aabbMax,
+ btDispatcher* /*dispatcher*/)
{
- btDbvtProxy* proxy=(btDbvtProxy*)absproxy;
- ATTRIBUTE_ALIGNED16(btDbvtVolume) aabb=btDbvtVolume::FromMM(aabbMin,aabbMax);
+ btDbvtProxy* proxy = (btDbvtProxy*)absproxy;
+ ATTRIBUTE_ALIGNED16(btDbvtVolume)
+ aabb = btDbvtVolume::FromMM(aabbMin, aabbMax);
#if DBVT_BP_PREVENTFALSEUPDATE
- if(NotEqual(aabb,proxy->leaf->volume))
+ if (NotEqual(aabb, proxy->leaf->volume))
#endif
{
- bool docollide=false;
- if(proxy->stage==STAGECOUNT)
- {/* fixed -> dynamic set */
+ bool docollide = false;
+ if (proxy->stage == STAGECOUNT)
+ { /* fixed -> dynamic set */
m_sets[1].remove(proxy->leaf);
- proxy->leaf=m_sets[0].insert(aabb,proxy);
- docollide=true;
+ proxy->leaf = m_sets[0].insert(aabb, proxy);
+ docollide = true;
}
else
- {/* dynamic set */
+ { /* dynamic set */
++m_updates_call;
- if(Intersect(proxy->leaf->volume,aabb))
- {/* Moving */
-
- const btVector3 delta=aabbMin-proxy->m_aabbMin;
- btVector3 velocity(((proxy->m_aabbMax-proxy->m_aabbMin)/2)*m_prediction);
- if(delta[0]<0) velocity[0]=-velocity[0];
- if(delta[1]<0) velocity[1]=-velocity[1];
- if(delta[2]<0) velocity[2]=-velocity[2];
+ if (Intersect(proxy->leaf->volume, aabb))
+ { /* Moving */
+
+ const btVector3 delta = aabbMin - proxy->m_aabbMin;
+ btVector3 velocity(((proxy->m_aabbMax - proxy->m_aabbMin) / 2) * m_prediction);
+ if (delta[0] < 0) velocity[0] = -velocity[0];
+ if (delta[1] < 0) velocity[1] = -velocity[1];
+ if (delta[2] < 0) velocity[2] = -velocity[2];
if (
m_sets[0].update(proxy->leaf, aabb, velocity, gDbvtMargin)
- )
+ )
{
++m_updates_done;
- docollide=true;
+ docollide = true;
}
}
else
- {/* Teleporting */
- m_sets[0].update(proxy->leaf,aabb);
+ { /* Teleporting */
+ m_sets[0].update(proxy->leaf, aabb);
++m_updates_done;
- docollide=true;
- }
+ docollide = true;
+ }
}
- listremove(proxy,m_stageRoots[proxy->stage]);
+ listremove(proxy, m_stageRoots[proxy->stage]);
proxy->m_aabbMin = aabbMin;
proxy->m_aabbMax = aabbMax;
- proxy->stage = m_stageCurrent;
- listappend(proxy,m_stageRoots[m_stageCurrent]);
- if(docollide)
+ proxy->stage = m_stageCurrent;
+ listappend(proxy, m_stageRoots[m_stageCurrent]);
+ if (docollide)
{
- m_needcleanup=true;
- if(!m_deferedcollide)
+ m_needcleanup = true;
+ if (!m_deferedcollide)
{
- btDbvtTreeCollider collider(this);
- m_sets[1].collideTTpersistentStack(m_sets[1].m_root,proxy->leaf,collider);
- m_sets[0].collideTTpersistentStack(m_sets[0].m_root,proxy->leaf,collider);
+ btDbvtTreeCollider collider(this);
+ m_sets[1].collideTTpersistentStack(m_sets[1].m_root, proxy->leaf, collider);
+ m_sets[0].collideTTpersistentStack(m_sets[0].m_root, proxy->leaf, collider);
}
- }
+ }
}
}
-
//
-void btDbvtBroadphase::setAabbForceUpdate( btBroadphaseProxy* absproxy,
- const btVector3& aabbMin,
- const btVector3& aabbMax,
- btDispatcher* /*dispatcher*/)
+void btDbvtBroadphase::setAabbForceUpdate(btBroadphaseProxy* absproxy,
+ const btVector3& aabbMin,
+ const btVector3& aabbMax,
+ btDispatcher* /*dispatcher*/)
{
- btDbvtProxy* proxy=(btDbvtProxy*)absproxy;
- ATTRIBUTE_ALIGNED16(btDbvtVolume) aabb=btDbvtVolume::FromMM(aabbMin,aabbMax);
- bool docollide=false;
- if(proxy->stage==STAGECOUNT)
- {/* fixed -> dynamic set */
+ btDbvtProxy* proxy = (btDbvtProxy*)absproxy;
+ ATTRIBUTE_ALIGNED16(btDbvtVolume)
+ aabb = btDbvtVolume::FromMM(aabbMin, aabbMax);
+ bool docollide = false;
+ if (proxy->stage == STAGECOUNT)
+ { /* fixed -> dynamic set */
m_sets[1].remove(proxy->leaf);
- proxy->leaf=m_sets[0].insert(aabb,proxy);
- docollide=true;
+ proxy->leaf = m_sets[0].insert(aabb, proxy);
+ docollide = true;
}
else
- {/* dynamic set */
+ { /* dynamic set */
++m_updates_call;
- /* Teleporting */
- m_sets[0].update(proxy->leaf,aabb);
+ /* Teleporting */
+ m_sets[0].update(proxy->leaf, aabb);
++m_updates_done;
- docollide=true;
+ docollide = true;
}
- listremove(proxy,m_stageRoots[proxy->stage]);
+ listremove(proxy, m_stageRoots[proxy->stage]);
proxy->m_aabbMin = aabbMin;
proxy->m_aabbMax = aabbMax;
- proxy->stage = m_stageCurrent;
- listappend(proxy,m_stageRoots[m_stageCurrent]);
- if(docollide)
+ proxy->stage = m_stageCurrent;
+ listappend(proxy, m_stageRoots[m_stageCurrent]);
+ if (docollide)
{
- m_needcleanup=true;
- if(!m_deferedcollide)
+ m_needcleanup = true;
+ if (!m_deferedcollide)
{
- btDbvtTreeCollider collider(this);
- m_sets[1].collideTTpersistentStack(m_sets[1].m_root,proxy->leaf,collider);
- m_sets[0].collideTTpersistentStack(m_sets[0].m_root,proxy->leaf,collider);
+ btDbvtTreeCollider collider(this);
+ m_sets[1].collideTTpersistentStack(m_sets[1].m_root, proxy->leaf, collider);
+ m_sets[0].collideTTpersistentStack(m_sets[0].m_root, proxy->leaf, collider);
}
- }
+ }
}
//
-void btDbvtBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
+void btDbvtBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
{
collide(dispatcher);
#if DBVT_BP_PROFILE
- if(0==(m_pid%DBVT_BP_PROFILING_RATE))
- {
- printf("fixed(%u) dynamics(%u) pairs(%u)\r\n",m_sets[1].m_leaves,m_sets[0].m_leaves,m_paircache->getNumOverlappingPairs());
- unsigned int total=m_profiling.m_total;
- if(total<=0) total=1;
- printf("ddcollide: %u%% (%uus)\r\n",(50+m_profiling.m_ddcollide*100)/total,m_profiling.m_ddcollide/DBVT_BP_PROFILING_RATE);
- printf("fdcollide: %u%% (%uus)\r\n",(50+m_profiling.m_fdcollide*100)/total,m_profiling.m_fdcollide/DBVT_BP_PROFILING_RATE);
- printf("cleanup: %u%% (%uus)\r\n",(50+m_profiling.m_cleanup*100)/total,m_profiling.m_cleanup/DBVT_BP_PROFILING_RATE);
- printf("total: %uus\r\n",total/DBVT_BP_PROFILING_RATE);
- const unsigned long sum=m_profiling.m_ddcollide+
- m_profiling.m_fdcollide+
- m_profiling.m_cleanup;
- printf("leaked: %u%% (%uus)\r\n",100-((50+sum*100)/total),(total-sum)/DBVT_BP_PROFILING_RATE);
- printf("job counts: %u%%\r\n",(m_profiling.m_jobcount*100)/((m_sets[0].m_leaves+m_sets[1].m_leaves)*DBVT_BP_PROFILING_RATE));
+ if (0 == (m_pid % DBVT_BP_PROFILING_RATE))
+ {
+ printf("fixed(%u) dynamics(%u) pairs(%u)\r\n", m_sets[1].m_leaves, m_sets[0].m_leaves, m_paircache->getNumOverlappingPairs());
+ unsigned int total = m_profiling.m_total;
+ if (total <= 0) total = 1;
+ printf("ddcollide: %u%% (%uus)\r\n", (50 + m_profiling.m_ddcollide * 100) / total, m_profiling.m_ddcollide / DBVT_BP_PROFILING_RATE);
+ printf("fdcollide: %u%% (%uus)\r\n", (50 + m_profiling.m_fdcollide * 100) / total, m_profiling.m_fdcollide / DBVT_BP_PROFILING_RATE);
+ printf("cleanup: %u%% (%uus)\r\n", (50 + m_profiling.m_cleanup * 100) / total, m_profiling.m_cleanup / DBVT_BP_PROFILING_RATE);
+ printf("total: %uus\r\n", total / DBVT_BP_PROFILING_RATE);
+ const unsigned long sum = m_profiling.m_ddcollide +
+ m_profiling.m_fdcollide +
+ m_profiling.m_cleanup;
+ printf("leaked: %u%% (%uus)\r\n", 100 - ((50 + sum * 100) / total), (total - sum) / DBVT_BP_PROFILING_RATE);
+ printf("job counts: %u%%\r\n", (m_profiling.m_jobcount * 100) / ((m_sets[0].m_leaves + m_sets[1].m_leaves) * DBVT_BP_PROFILING_RATE));
clear(m_profiling);
m_clock.reset();
}
#endif
performDeferredRemoval(dispatcher);
-
}
void btDbvtBroadphase::performDeferredRemoval(btDispatcher* dispatcher)
{
-
if (m_paircache->hasDeferredRemoval())
{
-
- btBroadphasePairArray& overlappingPairArray = m_paircache->getOverlappingPairArray();
+ btBroadphasePairArray& overlappingPairArray = m_paircache->getOverlappingPairArray();
//perform a sort, to find duplicates and to sort 'invalid' pairs to the end
overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
int invalidPair = 0;
-
int i;
btBroadphasePair previousPair;
previousPair.m_pProxy0 = 0;
previousPair.m_pProxy1 = 0;
previousPair.m_algorithm = 0;
-
-
- for (i=0;i<overlappingPairArray.size();i++)
+
+ for (i = 0; i < overlappingPairArray.size(); i++)
{
-
btBroadphasePair& pair = overlappingPairArray[i];
bool isDuplicate = (pair == previousPair);
@@ -471,34 +471,35 @@ void btDbvtBroadphase::performDeferredRemoval(btDispatcher* dispatcher)
if (!isDuplicate)
{
//important to perform AABB check that is consistent with the broadphase
- btDbvtProxy* pa=(btDbvtProxy*)pair.m_pProxy0;
- btDbvtProxy* pb=(btDbvtProxy*)pair.m_pProxy1;
- bool hasOverlap = Intersect(pa->leaf->volume,pb->leaf->volume);
+ btDbvtProxy* pa = (btDbvtProxy*)pair.m_pProxy0;
+ btDbvtProxy* pb = (btDbvtProxy*)pair.m_pProxy1;
+ bool hasOverlap = Intersect(pa->leaf->volume, pb->leaf->volume);
if (hasOverlap)
{
needsRemoval = false;
- } else
+ }
+ else
{
needsRemoval = true;
}
- } else
+ }
+ else
{
//remove duplicate
needsRemoval = true;
//should have no algorithm
btAssert(!pair.m_algorithm);
}
-
+
if (needsRemoval)
{
- m_paircache->cleanOverlappingPair(pair,dispatcher);
+ m_paircache->cleanOverlappingPair(pair, dispatcher);
pair.m_pProxy0 = 0;
pair.m_pProxy1 = 0;
invalidPair++;
- }
-
+ }
}
//perform a sort, to sort 'invalid' pairs to the end
@@ -508,7 +509,7 @@ void btDbvtBroadphase::performDeferredRemoval(btDispatcher* dispatcher)
}
//
-void btDbvtBroadphase::collide(btDispatcher* dispatcher)
+void btDbvtBroadphase::collide(btDispatcher* dispatcher)
{
/*printf("---------------------------------------------------------\n");
printf("m_sets[0].m_leaves=%d\n",m_sets[0].m_leaves);
@@ -525,295 +526,303 @@ void btDbvtBroadphase::collide(btDispatcher* dispatcher)
}
*/
-
-
SPC(m_profiling.m_total);
- /* optimize */
- m_sets[0].optimizeIncremental(1+(m_sets[0].m_leaves*m_dupdates)/100);
- if(m_fixedleft)
+ /* optimize */
+ m_sets[0].optimizeIncremental(1 + (m_sets[0].m_leaves * m_dupdates) / 100);
+ if (m_fixedleft)
{
- const int count=1+(m_sets[1].m_leaves*m_fupdates)/100;
- m_sets[1].optimizeIncremental(1+(m_sets[1].m_leaves*m_fupdates)/100);
- m_fixedleft=btMax<int>(0,m_fixedleft-count);
+ const int count = 1 + (m_sets[1].m_leaves * m_fupdates) / 100;
+ m_sets[1].optimizeIncremental(1 + (m_sets[1].m_leaves * m_fupdates) / 100);
+ m_fixedleft = btMax<int>(0, m_fixedleft - count);
}
- /* dynamic -> fixed set */
- m_stageCurrent=(m_stageCurrent+1)%STAGECOUNT;
- btDbvtProxy* current=m_stageRoots[m_stageCurrent];
- if(current)
+ /* dynamic -> fixed set */
+ m_stageCurrent = (m_stageCurrent + 1) % STAGECOUNT;
+ btDbvtProxy* current = m_stageRoots[m_stageCurrent];
+ if (current)
{
#if DBVT_BP_ACCURATESLEEPING
- btDbvtTreeCollider collider(this);
+ btDbvtTreeCollider collider(this);
#endif
- do {
- btDbvtProxy* next=current->links[1];
- listremove(current,m_stageRoots[current->stage]);
- listappend(current,m_stageRoots[STAGECOUNT]);
+ do
+ {
+ btDbvtProxy* next = current->links[1];
+ listremove(current, m_stageRoots[current->stage]);
+ listappend(current, m_stageRoots[STAGECOUNT]);
#if DBVT_BP_ACCURATESLEEPING
- m_paircache->removeOverlappingPairsContainingProxy(current,dispatcher);
- collider.proxy=current;
- btDbvt::collideTV(m_sets[0].m_root,current->aabb,collider);
- btDbvt::collideTV(m_sets[1].m_root,current->aabb,collider);
+ m_paircache->removeOverlappingPairsContainingProxy(current, dispatcher);
+ collider.proxy = current;
+ btDbvt::collideTV(m_sets[0].m_root, current->aabb, collider);
+ btDbvt::collideTV(m_sets[1].m_root, current->aabb, collider);
#endif
m_sets[0].remove(current->leaf);
- ATTRIBUTE_ALIGNED16(btDbvtVolume) curAabb=btDbvtVolume::FromMM(current->m_aabbMin,current->m_aabbMax);
- current->leaf = m_sets[1].insert(curAabb,current);
- current->stage = STAGECOUNT;
- current = next;
- } while(current);
- m_fixedleft=m_sets[1].m_leaves;
- m_needcleanup=true;
+ ATTRIBUTE_ALIGNED16(btDbvtVolume)
+ curAabb = btDbvtVolume::FromMM(current->m_aabbMin, current->m_aabbMax);
+ current->leaf = m_sets[1].insert(curAabb, current);
+ current->stage = STAGECOUNT;
+ current = next;
+ } while (current);
+ m_fixedleft = m_sets[1].m_leaves;
+ m_needcleanup = true;
}
- /* collide dynamics */
+ /* collide dynamics */
{
- btDbvtTreeCollider collider(this);
- if(m_deferedcollide)
+ btDbvtTreeCollider collider(this);
+ if (m_deferedcollide)
{
SPC(m_profiling.m_fdcollide);
- m_sets[0].collideTTpersistentStack(m_sets[0].m_root,m_sets[1].m_root,collider);
+ m_sets[0].collideTTpersistentStack(m_sets[0].m_root, m_sets[1].m_root, collider);
}
- if(m_deferedcollide)
+ if (m_deferedcollide)
{
SPC(m_profiling.m_ddcollide);
- m_sets[0].collideTTpersistentStack(m_sets[0].m_root,m_sets[0].m_root,collider);
+ m_sets[0].collideTTpersistentStack(m_sets[0].m_root, m_sets[0].m_root, collider);
}
}
- /* clean up */
- if(m_needcleanup)
+ /* clean up */
+ if (m_needcleanup)
{
SPC(m_profiling.m_cleanup);
- btBroadphasePairArray& pairs=m_paircache->getOverlappingPairArray();
- if(pairs.size()>0)
+ btBroadphasePairArray& pairs = m_paircache->getOverlappingPairArray();
+ if (pairs.size() > 0)
{
-
- int ni=btMin(pairs.size(),btMax<int>(m_newpairs,(pairs.size()*m_cupdates)/100));
- for(int i=0;i<ni;++i)
+ int ni = btMin(pairs.size(), btMax<int>(m_newpairs, (pairs.size() * m_cupdates) / 100));
+ for (int i = 0; i < ni; ++i)
{
- btBroadphasePair& p=pairs[(m_cid+i)%pairs.size()];
- btDbvtProxy* pa=(btDbvtProxy*)p.m_pProxy0;
- btDbvtProxy* pb=(btDbvtProxy*)p.m_pProxy1;
- if(!Intersect(pa->leaf->volume,pb->leaf->volume))
+ btBroadphasePair& p = pairs[(m_cid + i) % pairs.size()];
+ btDbvtProxy* pa = (btDbvtProxy*)p.m_pProxy0;
+ btDbvtProxy* pb = (btDbvtProxy*)p.m_pProxy1;
+ if (!Intersect(pa->leaf->volume, pb->leaf->volume))
{
#if DBVT_BP_SORTPAIRS
- if(pa->m_uniqueId>pb->m_uniqueId)
- btSwap(pa,pb);
+ if (pa->m_uniqueId > pb->m_uniqueId)
+ btSwap(pa, pb);
#endif
- m_paircache->removeOverlappingPair(pa,pb,dispatcher);
- --ni;--i;
+ m_paircache->removeOverlappingPair(pa, pb, dispatcher);
+ --ni;
+ --i;
}
}
- if(pairs.size()>0) m_cid=(m_cid+ni)%pairs.size(); else m_cid=0;
+ if (pairs.size() > 0)
+ m_cid = (m_cid + ni) % pairs.size();
+ else
+ m_cid = 0;
}
}
++m_pid;
- m_newpairs=1;
- m_needcleanup=false;
- if(m_updates_call>0)
- { m_updates_ratio=m_updates_done/(btScalar)m_updates_call; }
+ m_newpairs = 1;
+ m_needcleanup = false;
+ if (m_updates_call > 0)
+ {
+ m_updates_ratio = m_updates_done / (btScalar)m_updates_call;
+ }
else
- { m_updates_ratio=0; }
- m_updates_done/=2;
- m_updates_call/=2;
+ {
+ m_updates_ratio = 0;
+ }
+ m_updates_done /= 2;
+ m_updates_call /= 2;
}
//
-void btDbvtBroadphase::optimize()
+void btDbvtBroadphase::optimize()
{
m_sets[0].optimizeTopDown();
m_sets[1].optimizeTopDown();
}
//
-btOverlappingPairCache* btDbvtBroadphase::getOverlappingPairCache()
+btOverlappingPairCache* btDbvtBroadphase::getOverlappingPairCache()
{
- return(m_paircache);
+ return (m_paircache);
}
//
-const btOverlappingPairCache* btDbvtBroadphase::getOverlappingPairCache() const
+const btOverlappingPairCache* btDbvtBroadphase::getOverlappingPairCache() const
{
- return(m_paircache);
+ return (m_paircache);
}
//
-void btDbvtBroadphase::getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const
+void btDbvtBroadphase::getBroadphaseAabb(btVector3& aabbMin, btVector3& aabbMax) const
{
+ ATTRIBUTE_ALIGNED16(btDbvtVolume)
+ bounds;
- ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds;
-
- if(!m_sets[0].empty())
- if(!m_sets[1].empty()) Merge( m_sets[0].m_root->volume,
- m_sets[1].m_root->volume,bounds);
+ if (!m_sets[0].empty())
+ if (!m_sets[1].empty())
+ Merge(m_sets[0].m_root->volume,
+ m_sets[1].m_root->volume, bounds);
else
- bounds=m_sets[0].m_root->volume;
- else if(!m_sets[1].empty()) bounds=m_sets[1].m_root->volume;
+ bounds = m_sets[0].m_root->volume;
+ else if (!m_sets[1].empty())
+ bounds = m_sets[1].m_root->volume;
else
- bounds=btDbvtVolume::FromCR(btVector3(0,0,0),0);
- aabbMin=bounds.Mins();
- aabbMax=bounds.Maxs();
+ bounds = btDbvtVolume::FromCR(btVector3(0, 0, 0), 0);
+ aabbMin = bounds.Mins();
+ aabbMax = bounds.Maxs();
}
void btDbvtBroadphase::resetPool(btDispatcher* dispatcher)
{
-
int totalObjects = m_sets[0].m_leaves + m_sets[1].m_leaves;
if (!totalObjects)
{
//reset internal dynamic tree data structures
m_sets[0].clear();
m_sets[1].clear();
-
- m_deferedcollide = false;
- m_needcleanup = true;
- m_stageCurrent = 0;
- m_fixedleft = 0;
- m_fupdates = 1;
- m_dupdates = 0;
- m_cupdates = 10;
- m_newpairs = 1;
- m_updates_call = 0;
- m_updates_done = 0;
- m_updates_ratio = 0;
-
- m_gid = 0;
- m_pid = 0;
- m_cid = 0;
- for(int i=0;i<=STAGECOUNT;++i)
+
+ m_deferedcollide = false;
+ m_needcleanup = true;
+ m_stageCurrent = 0;
+ m_fixedleft = 0;
+ m_fupdates = 1;
+ m_dupdates = 0;
+ m_cupdates = 10;
+ m_newpairs = 1;
+ m_updates_call = 0;
+ m_updates_done = 0;
+ m_updates_ratio = 0;
+
+ m_gid = 0;
+ m_pid = 0;
+ m_cid = 0;
+ for (int i = 0; i <= STAGECOUNT; ++i)
{
- m_stageRoots[i]=0;
+ m_stageRoots[i] = 0;
}
}
}
//
-void btDbvtBroadphase::printStats()
-{}
+void btDbvtBroadphase::printStats()
+{
+}
//
#if DBVT_BP_ENABLE_BENCHMARK
-struct btBroadphaseBenchmark
+struct btBroadphaseBenchmark
{
- struct Experiment
+ struct Experiment
{
- const char* name;
- int object_count;
- int update_count;
- int spawn_count;
- int iterations;
- btScalar speed;
- btScalar amplitude;
+ const char* name;
+ int object_count;
+ int update_count;
+ int spawn_count;
+ int iterations;
+ btScalar speed;
+ btScalar amplitude;
};
- struct Object
+ struct Object
{
- btVector3 center;
- btVector3 extents;
- btBroadphaseProxy* proxy;
- btScalar time;
- void update(btScalar speed,btScalar amplitude,btBroadphaseInterface* pbi)
+ btVector3 center;
+ btVector3 extents;
+ btBroadphaseProxy* proxy;
+ btScalar time;
+ void update(btScalar speed, btScalar amplitude, btBroadphaseInterface* pbi)
{
- time += speed;
- center[0] = btCos(time*(btScalar)2.17)*amplitude+
- btSin(time)*amplitude/2;
- center[1] = btCos(time*(btScalar)1.38)*amplitude+
- btSin(time)*amplitude;
- center[2] = btSin(time*(btScalar)0.777)*amplitude;
- pbi->setAabb(proxy,center-extents,center+extents,0);
+ time += speed;
+ center[0] = btCos(time * (btScalar)2.17) * amplitude +
+ btSin(time) * amplitude / 2;
+ center[1] = btCos(time * (btScalar)1.38) * amplitude +
+ btSin(time) * amplitude;
+ center[2] = btSin(time * (btScalar)0.777) * amplitude;
+ pbi->setAabb(proxy, center - extents, center + extents, 0);
}
};
- static int UnsignedRand(int range=RAND_MAX-1) { return(rand()%(range+1)); }
- static btScalar UnitRand() { return(UnsignedRand(16384)/(btScalar)16384); }
- static void OutputTime(const char* name,btClock& c,unsigned count=0)
+ static int UnsignedRand(int range = RAND_MAX - 1) { return (rand() % (range + 1)); }
+ static btScalar UnitRand() { return (UnsignedRand(16384) / (btScalar)16384); }
+ static void OutputTime(const char* name, btClock& c, unsigned count = 0)
{
- const unsigned long us=c.getTimeMicroseconds();
- const unsigned long ms=(us+500)/1000;
- const btScalar sec=us/(btScalar)(1000*1000);
- if(count>0)
- printf("%s : %u us (%u ms), %.2f/s\r\n",name,us,ms,count/sec);
+ const unsigned long us = c.getTimeMicroseconds();
+ const unsigned long ms = (us + 500) / 1000;
+ const btScalar sec = us / (btScalar)(1000 * 1000);
+ if (count > 0)
+ printf("%s : %u us (%u ms), %.2f/s\r\n", name, us, ms, count / sec);
else
- printf("%s : %u us (%u ms)\r\n",name,us,ms);
+ printf("%s : %u us (%u ms)\r\n", name, us, ms);
}
};
-void btDbvtBroadphase::benchmark(btBroadphaseInterface* pbi)
+void btDbvtBroadphase::benchmark(btBroadphaseInterface* pbi)
{
- static const btBroadphaseBenchmark::Experiment experiments[]=
- {
- {"1024o.10%",1024,10,0,8192,(btScalar)0.005,(btScalar)100},
- /*{"4096o.10%",4096,10,0,8192,(btScalar)0.005,(btScalar)100},
+ static const btBroadphaseBenchmark::Experiment experiments[] =
+ {
+ {"1024o.10%", 1024, 10, 0, 8192, (btScalar)0.005, (btScalar)100},
+ /*{"4096o.10%",4096,10,0,8192,(btScalar)0.005,(btScalar)100},
{"8192o.10%",8192,10,0,8192,(btScalar)0.005,(btScalar)100},*/
- };
- static const int nexperiments=sizeof(experiments)/sizeof(experiments[0]);
- btAlignedObjectArray<btBroadphaseBenchmark::Object*> objects;
- btClock wallclock;
- /* Begin */
- for(int iexp=0;iexp<nexperiments;++iexp)
+ };
+ static const int nexperiments = sizeof(experiments) / sizeof(experiments[0]);
+ btAlignedObjectArray<btBroadphaseBenchmark::Object*> objects;
+ btClock wallclock;
+ /* Begin */
+ for (int iexp = 0; iexp < nexperiments; ++iexp)
{
- const btBroadphaseBenchmark::Experiment& experiment=experiments[iexp];
- const int object_count=experiment.object_count;
- const int update_count=(object_count*experiment.update_count)/100;
- const int spawn_count=(object_count*experiment.spawn_count)/100;
- const btScalar speed=experiment.speed;
- const btScalar amplitude=experiment.amplitude;
- printf("Experiment #%u '%s':\r\n",iexp,experiment.name);
- printf("\tObjects: %u\r\n",object_count);
- printf("\tUpdate: %u\r\n",update_count);
- printf("\tSpawn: %u\r\n",spawn_count);
- printf("\tSpeed: %f\r\n",speed);
- printf("\tAmplitude: %f\r\n",amplitude);
+ const btBroadphaseBenchmark::Experiment& experiment = experiments[iexp];
+ const int object_count = experiment.object_count;
+ const int update_count = (object_count * experiment.update_count) / 100;
+ const int spawn_count = (object_count * experiment.spawn_count) / 100;
+ const btScalar speed = experiment.speed;
+ const btScalar amplitude = experiment.amplitude;
+ printf("Experiment #%u '%s':\r\n", iexp, experiment.name);
+ printf("\tObjects: %u\r\n", object_count);
+ printf("\tUpdate: %u\r\n", update_count);
+ printf("\tSpawn: %u\r\n", spawn_count);
+ printf("\tSpeed: %f\r\n", speed);
+ printf("\tAmplitude: %f\r\n", amplitude);
srand(180673);
- /* Create objects */
+ /* Create objects */
wallclock.reset();
objects.reserve(object_count);
- for(int i=0;i<object_count;++i)
+ for (int i = 0; i < object_count; ++i)
{
- btBroadphaseBenchmark::Object* po=new btBroadphaseBenchmark::Object();
- po->center[0]=btBroadphaseBenchmark::UnitRand()*50;
- po->center[1]=btBroadphaseBenchmark::UnitRand()*50;
- po->center[2]=btBroadphaseBenchmark::UnitRand()*50;
- po->extents[0]=btBroadphaseBenchmark::UnitRand()*2+2;
- po->extents[1]=btBroadphaseBenchmark::UnitRand()*2+2;
- po->extents[2]=btBroadphaseBenchmark::UnitRand()*2+2;
- po->time=btBroadphaseBenchmark::UnitRand()*2000;
- po->proxy=pbi->createProxy(po->center-po->extents,po->center+po->extents,0,po,1,1,0,0);
+ btBroadphaseBenchmark::Object* po = new btBroadphaseBenchmark::Object();
+ po->center[0] = btBroadphaseBenchmark::UnitRand() * 50;
+ po->center[1] = btBroadphaseBenchmark::UnitRand() * 50;
+ po->center[2] = btBroadphaseBenchmark::UnitRand() * 50;
+ po->extents[0] = btBroadphaseBenchmark::UnitRand() * 2 + 2;
+ po->extents[1] = btBroadphaseBenchmark::UnitRand() * 2 + 2;
+ po->extents[2] = btBroadphaseBenchmark::UnitRand() * 2 + 2;
+ po->time = btBroadphaseBenchmark::UnitRand() * 2000;
+ po->proxy = pbi->createProxy(po->center - po->extents, po->center + po->extents, 0, po, 1, 1, 0, 0);
objects.push_back(po);
}
- btBroadphaseBenchmark::OutputTime("\tInitialization",wallclock);
- /* First update */
+ btBroadphaseBenchmark::OutputTime("\tInitialization", wallclock);
+ /* First update */
wallclock.reset();
- for(int i=0;i<objects.size();++i)
+ for (int i = 0; i < objects.size(); ++i)
{
- objects[i]->update(speed,amplitude,pbi);
+ objects[i]->update(speed, amplitude, pbi);
}
- btBroadphaseBenchmark::OutputTime("\tFirst update",wallclock);
- /* Updates */
+ btBroadphaseBenchmark::OutputTime("\tFirst update", wallclock);
+ /* Updates */
wallclock.reset();
- for(int i=0;i<experiment.iterations;++i)
+ for (int i = 0; i < experiment.iterations; ++i)
{
- for(int j=0;j<update_count;++j)
- {
- objects[j]->update(speed,amplitude,pbi);
+ for (int j = 0; j < update_count; ++j)
+ {
+ objects[j]->update(speed, amplitude, pbi);
}
pbi->calculateOverlappingPairs(0);
}
- btBroadphaseBenchmark::OutputTime("\tUpdate",wallclock,experiment.iterations);
- /* Clean up */
+ btBroadphaseBenchmark::OutputTime("\tUpdate", wallclock, experiment.iterations);
+ /* Clean up */
wallclock.reset();
- for(int i=0;i<objects.size();++i)
+ for (int i = 0; i < objects.size(); ++i)
{
- pbi->destroyProxy(objects[i]->proxy,0);
+ pbi->destroyProxy(objects[i]->proxy, 0);
delete objects[i];
}
objects.resize(0);
- btBroadphaseBenchmark::OutputTime("\tRelease",wallclock);
+ btBroadphaseBenchmark::OutputTime("\tRelease", wallclock);
}
-
}
#else
-void btDbvtBroadphase::benchmark(btBroadphaseInterface*)
-{}
+void btDbvtBroadphase::benchmark(btBroadphaseInterface*)
+{
+}
#endif
#if DBVT_BP_PROFILE
-#undef SPC
+#undef SPC
#endif
-
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h
index 90b333d846..a71feef53b 100644
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h
+++ b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h
@@ -24,16 +24,16 @@ subject to the following restrictions:
// Compile time config
//
-#define DBVT_BP_PROFILE 0
+#define DBVT_BP_PROFILE 0
//#define DBVT_BP_SORTPAIRS 1
-#define DBVT_BP_PREVENTFALSEUPDATE 0
-#define DBVT_BP_ACCURATESLEEPING 0
-#define DBVT_BP_ENABLE_BENCHMARK 0
+#define DBVT_BP_PREVENTFALSEUPDATE 0
+#define DBVT_BP_ACCURATESLEEPING 0
+#define DBVT_BP_ENABLE_BENCHMARK 0
//#define DBVT_BP_MARGIN (btScalar)0.05
extern btScalar gDbvtMargin;
#if DBVT_BP_PROFILE
-#define DBVT_BP_PROFILING_RATE 256
+#define DBVT_BP_PROFILING_RATE 256
#include "LinearMath/btQuickprof.h"
#endif
@@ -42,90 +42,90 @@ extern btScalar gDbvtMargin;
//
struct btDbvtProxy : btBroadphaseProxy
{
- /* Fields */
+ /* Fields */
//btDbvtAabbMm aabb;
- btDbvtNode* leaf;
- btDbvtProxy* links[2];
- int stage;
- /* ctor */
- btDbvtProxy(const btVector3& aabbMin,const btVector3& aabbMax,void* userPtr, int collisionFilterGroup, int collisionFilterMask) :
- btBroadphaseProxy(aabbMin,aabbMax,userPtr,collisionFilterGroup,collisionFilterMask)
+ btDbvtNode* leaf;
+ btDbvtProxy* links[2];
+ int stage;
+ /* ctor */
+ btDbvtProxy(const btVector3& aabbMin, const btVector3& aabbMax, void* userPtr, int collisionFilterGroup, int collisionFilterMask) : btBroadphaseProxy(aabbMin, aabbMax, userPtr, collisionFilterGroup, collisionFilterMask)
{
- links[0]=links[1]=0;
+ links[0] = links[1] = 0;
}
};
-typedef btAlignedObjectArray<btDbvtProxy*> btDbvtProxyArray;
+typedef btAlignedObjectArray<btDbvtProxy*> btDbvtProxyArray;
///The btDbvtBroadphase implements a broadphase using two dynamic AABB bounding volume hierarchies/trees (see btDbvt).
///One tree is used for static/non-moving objects, and another tree is used for dynamic objects. Objects can move from one tree to the other.
///This is a very fast broadphase, especially for very dynamic worlds where many objects are moving. Its insert/add and remove of objects is generally faster than the sweep and prune broadphases btAxisSweep3 and bt32BitAxisSweep3.
-struct btDbvtBroadphase : btBroadphaseInterface
+struct btDbvtBroadphase : btBroadphaseInterface
{
- /* Config */
- enum {
- DYNAMIC_SET = 0, /* Dynamic set index */
- FIXED_SET = 1, /* Fixed set index */
- STAGECOUNT = 2 /* Number of stages */
+ /* Config */
+ enum
+ {
+ DYNAMIC_SET = 0, /* Dynamic set index */
+ FIXED_SET = 1, /* Fixed set index */
+ STAGECOUNT = 2 /* Number of stages */
};
- /* Fields */
- btDbvt m_sets[2]; // Dbvt sets
- btDbvtProxy* m_stageRoots[STAGECOUNT+1]; // Stages list
- btOverlappingPairCache* m_paircache; // Pair cache
- btScalar m_prediction; // Velocity prediction
- int m_stageCurrent; // Current stage
- int m_fupdates; // % of fixed updates per frame
- int m_dupdates; // % of dynamic updates per frame
- int m_cupdates; // % of cleanup updates per frame
- int m_newpairs; // Number of pairs created
- int m_fixedleft; // Fixed optimization left
- unsigned m_updates_call; // Number of updates call
- unsigned m_updates_done; // Number of updates done
- btScalar m_updates_ratio; // m_updates_done/m_updates_call
- int m_pid; // Parse id
- int m_cid; // Cleanup index
- int m_gid; // Gen id
- bool m_releasepaircache; // Release pair cache on delete
- bool m_deferedcollide; // Defere dynamic/static collision to collide call
- bool m_needcleanup; // Need to run cleanup?
- btAlignedObjectArray< btAlignedObjectArray<const btDbvtNode*> > m_rayTestStacks;
+ /* Fields */
+ btDbvt m_sets[2]; // Dbvt sets
+ btDbvtProxy* m_stageRoots[STAGECOUNT + 1]; // Stages list
+ btOverlappingPairCache* m_paircache; // Pair cache
+ btScalar m_prediction; // Velocity prediction
+ int m_stageCurrent; // Current stage
+ int m_fupdates; // % of fixed updates per frame
+ int m_dupdates; // % of dynamic updates per frame
+ int m_cupdates; // % of cleanup updates per frame
+ int m_newpairs; // Number of pairs created
+ int m_fixedleft; // Fixed optimization left
+ unsigned m_updates_call; // Number of updates call
+ unsigned m_updates_done; // Number of updates done
+ btScalar m_updates_ratio; // m_updates_done/m_updates_call
+ int m_pid; // Parse id
+ int m_cid; // Cleanup index
+ int m_gid; // Gen id
+ bool m_releasepaircache; // Release pair cache on delete
+ bool m_deferedcollide; // Defere dynamic/static collision to collide call
+ bool m_needcleanup; // Need to run cleanup?
+ btAlignedObjectArray<btAlignedObjectArray<const btDbvtNode*> > m_rayTestStacks;
#if DBVT_BP_PROFILE
- btClock m_clock;
- struct {
- unsigned long m_total;
- unsigned long m_ddcollide;
- unsigned long m_fdcollide;
- unsigned long m_cleanup;
- unsigned long m_jobcount;
- } m_profiling;
+ btClock m_clock;
+ struct
+ {
+ unsigned long m_total;
+ unsigned long m_ddcollide;
+ unsigned long m_fdcollide;
+ unsigned long m_cleanup;
+ unsigned long m_jobcount;
+ } m_profiling;
#endif
- /* Methods */
- btDbvtBroadphase(btOverlappingPairCache* paircache=0);
+ /* Methods */
+ btDbvtBroadphase(btOverlappingPairCache* paircache = 0);
~btDbvtBroadphase();
- void collide(btDispatcher* dispatcher);
- void optimize();
-
- /* btBroadphaseInterface Implementation */
- btBroadphaseProxy* createProxy(const btVector3& aabbMin,const btVector3& aabbMax,int shapeType,void* userPtr, int collisionFilterGroup, int collisionFilterMask,btDispatcher* dispatcher);
- virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
- virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher);
- virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0), const btVector3& aabbMax = btVector3(0,0,0));
- virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback);
-
- virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
- virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
- virtual btOverlappingPairCache* getOverlappingPairCache();
- virtual const btOverlappingPairCache* getOverlappingPairCache() const;
- virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const;
- virtual void printStats();
+ void collide(btDispatcher* dispatcher);
+ void optimize();
+ /* btBroadphaseInterface Implementation */
+ btBroadphaseProxy* createProxy(const btVector3& aabbMin, const btVector3& aabbMax, int shapeType, void* userPtr, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher);
+ virtual void destroyProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher);
+ virtual void setAabb(btBroadphaseProxy* proxy, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* dispatcher);
+ virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin = btVector3(0, 0, 0), const btVector3& aabbMax = btVector3(0, 0, 0));
+ virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback);
+
+ virtual void getAabb(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const;
+ virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
+ virtual btOverlappingPairCache* getOverlappingPairCache();
+ virtual const btOverlappingPairCache* getOverlappingPairCache() const;
+ virtual void getBroadphaseAabb(btVector3& aabbMin, btVector3& aabbMax) const;
+ virtual void printStats();
///reset broadphase internal structures, to ensure determinism/reproducability
virtual void resetPool(btDispatcher* dispatcher);
- void performDeferredRemoval(btDispatcher* dispatcher);
-
- void setVelocityPrediction(btScalar prediction)
+ void performDeferredRemoval(btDispatcher* dispatcher);
+
+ void setVelocityPrediction(btScalar prediction)
{
m_prediction = prediction;
}
@@ -134,15 +134,13 @@ struct btDbvtBroadphase : btBroadphaseInterface
return m_prediction;
}
- ///this setAabbForceUpdate is similar to setAabb but always forces the aabb update.
+ ///this setAabbForceUpdate is similar to setAabb but always forces the aabb update.
///it is not part of the btBroadphaseInterface but specific to btDbvtBroadphase.
///it bypasses certain optimizations that prevent aabb updates (when the aabb shrinks), see
///http://code.google.com/p/bullet/issues/detail?id=223
- void setAabbForceUpdate( btBroadphaseProxy* absproxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* /*dispatcher*/);
-
- static void benchmark(btBroadphaseInterface*);
-
+ void setAabbForceUpdate(btBroadphaseProxy* absproxy, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* /*dispatcher*/);
+ static void benchmark(btBroadphaseInterface*);
};
#endif
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDispatcher.cpp b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDispatcher.cpp
index 20768225b3..d76d408aa6 100644
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDispatcher.cpp
+++ b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDispatcher.cpp
@@ -17,6 +17,4 @@ subject to the following restrictions:
btDispatcher::~btDispatcher()
{
-
}
-
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDispatcher.h b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDispatcher.h
index a0e4c18927..b09b7d4d42 100644
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDispatcher.h
+++ b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDispatcher.h
@@ -20,7 +20,7 @@ subject to the following restrictions:
class btCollisionAlgorithm;
struct btBroadphaseProxy;
class btRigidBody;
-class btCollisionObject;
+class btCollisionObject;
class btOverlappingPairCache;
struct btCollisionObjectWrapper;
@@ -35,35 +35,34 @@ struct btDispatcherInfo
DISPATCH_CONTINUOUS
};
btDispatcherInfo()
- :m_timeStep(btScalar(0.)),
- m_stepCount(0),
- m_dispatchFunc(DISPATCH_DISCRETE),
- m_timeOfImpact(btScalar(1.)),
- m_useContinuous(true),
- m_debugDraw(0),
- m_enableSatConvex(false),
- m_enableSPU(true),
- m_useEpa(true),
- m_allowedCcdPenetration(btScalar(0.04)),
- m_useConvexConservativeDistanceUtil(false),
- m_convexConservativeDistanceThreshold(0.0f),
- m_deterministicOverlappingPairs(false)
+ : m_timeStep(btScalar(0.)),
+ m_stepCount(0),
+ m_dispatchFunc(DISPATCH_DISCRETE),
+ m_timeOfImpact(btScalar(1.)),
+ m_useContinuous(true),
+ m_debugDraw(0),
+ m_enableSatConvex(false),
+ m_enableSPU(true),
+ m_useEpa(true),
+ m_allowedCcdPenetration(btScalar(0.04)),
+ m_useConvexConservativeDistanceUtil(false),
+ m_convexConservativeDistanceThreshold(0.0f),
+ m_deterministicOverlappingPairs(false)
{
-
}
- btScalar m_timeStep;
- int m_stepCount;
- int m_dispatchFunc;
- mutable btScalar m_timeOfImpact;
- bool m_useContinuous;
- class btIDebugDraw* m_debugDraw;
- bool m_enableSatConvex;
- bool m_enableSPU;
- bool m_useEpa;
- btScalar m_allowedCcdPenetration;
- bool m_useConvexConservativeDistanceUtil;
- btScalar m_convexConservativeDistanceThreshold;
- bool m_deterministicOverlappingPairs;
+ btScalar m_timeStep;
+ int m_stepCount;
+ int m_dispatchFunc;
+ mutable btScalar m_timeOfImpact;
+ bool m_useContinuous;
+ class btIDebugDraw* m_debugDraw;
+ bool m_enableSatConvex;
+ bool m_enableSPU;
+ bool m_useEpa;
+ btScalar m_allowedCcdPenetration;
+ bool m_useConvexConservativeDistanceUtil;
+ btScalar m_convexConservativeDistanceThreshold;
+ bool m_deterministicOverlappingPairs;
};
enum ebtDispatcherQueryType
@@ -76,40 +75,36 @@ enum ebtDispatcherQueryType
///For example for pairwise collision detection, calculating contact points stored in btPersistentManifold or user callbacks (game logic).
class btDispatcher
{
-
-
public:
- virtual ~btDispatcher() ;
+ virtual ~btDispatcher();
- virtual btCollisionAlgorithm* findAlgorithm(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btPersistentManifold* sharedManifold, ebtDispatcherQueryType queryType) = 0;
+ virtual btCollisionAlgorithm* findAlgorithm(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, btPersistentManifold* sharedManifold, ebtDispatcherQueryType queryType) = 0;
- virtual btPersistentManifold* getNewManifold(const btCollisionObject* b0,const btCollisionObject* b1)=0;
+ virtual btPersistentManifold* getNewManifold(const btCollisionObject* b0, const btCollisionObject* b1) = 0;
- virtual void releaseManifold(btPersistentManifold* manifold)=0;
+ virtual void releaseManifold(btPersistentManifold* manifold) = 0;
- virtual void clearManifold(btPersistentManifold* manifold)=0;
+ virtual void clearManifold(btPersistentManifold* manifold) = 0;
- virtual bool needsCollision(const btCollisionObject* body0,const btCollisionObject* body1) = 0;
+ virtual bool needsCollision(const btCollisionObject* body0, const btCollisionObject* body1) = 0;
- virtual bool needsResponse(const btCollisionObject* body0,const btCollisionObject* body1)=0;
+ virtual bool needsResponse(const btCollisionObject* body0, const btCollisionObject* body1) = 0;
- virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) =0;
+ virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache, const btDispatcherInfo& dispatchInfo, btDispatcher* dispatcher) = 0;
virtual int getNumManifolds() const = 0;
virtual btPersistentManifold* getManifoldByIndexInternal(int index) = 0;
- virtual btPersistentManifold** getInternalManifoldPointer() = 0;
+ virtual btPersistentManifold** getInternalManifoldPointer() = 0;
- virtual btPoolAllocator* getInternalManifoldPool() = 0;
+ virtual btPoolAllocator* getInternalManifoldPool() = 0;
- virtual const btPoolAllocator* getInternalManifoldPool() const = 0;
+ virtual const btPoolAllocator* getInternalManifoldPool() const = 0;
- virtual void* allocateCollisionAlgorithm(int size) = 0;
-
- virtual void freeCollisionAlgorithm(void* ptr) = 0;
+ virtual void* allocateCollisionAlgorithm(int size) = 0;
+ virtual void freeCollisionAlgorithm(void* ptr) = 0;
};
-
-#endif //BT_DISPATCHER_H
+#endif //BT_DISPATCHER_H
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp
index 9e3337c5f6..8ce1087c9f 100644
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp
+++ b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp
@@ -13,8 +13,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
-
#include "btOverlappingPairCache.h"
#include "btDispatcher.h"
@@ -23,121 +21,95 @@ subject to the following restrictions:
#include <stdio.h>
-
-
-
-
-btHashedOverlappingPairCache::btHashedOverlappingPairCache():
- m_overlapFilterCallback(0),
- m_ghostPairCallback(0)
+btHashedOverlappingPairCache::btHashedOverlappingPairCache() : m_overlapFilterCallback(0),
+ m_ghostPairCallback(0)
{
- int initialAllocatedSize= 2;
+ int initialAllocatedSize = 2;
m_overlappingPairArray.reserve(initialAllocatedSize);
growTables();
}
-
-
-
btHashedOverlappingPairCache::~btHashedOverlappingPairCache()
{
}
-
-
-void btHashedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher)
+void btHashedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair, btDispatcher* dispatcher)
{
if (pair.m_algorithm && dispatcher)
{
{
pair.m_algorithm->~btCollisionAlgorithm();
dispatcher->freeCollisionAlgorithm(pair.m_algorithm);
- pair.m_algorithm=0;
+ pair.m_algorithm = 0;
}
}
}
-
-
-
-void btHashedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
+void btHashedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy, btDispatcher* dispatcher)
{
-
- class CleanPairCallback : public btOverlapCallback
+ class CleanPairCallback : public btOverlapCallback
{
btBroadphaseProxy* m_cleanProxy;
- btOverlappingPairCache* m_pairCache;
+ btOverlappingPairCache* m_pairCache;
btDispatcher* m_dispatcher;
public:
- CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache,btDispatcher* dispatcher)
- :m_cleanProxy(cleanProxy),
- m_pairCache(pairCache),
- m_dispatcher(dispatcher)
+ CleanPairCallback(btBroadphaseProxy* cleanProxy, btOverlappingPairCache* pairCache, btDispatcher* dispatcher)
+ : m_cleanProxy(cleanProxy),
+ m_pairCache(pairCache),
+ m_dispatcher(dispatcher)
{
}
- virtual bool processOverlap(btBroadphasePair& pair)
+ virtual bool processOverlap(btBroadphasePair& pair)
{
if ((pair.m_pProxy0 == m_cleanProxy) ||
(pair.m_pProxy1 == m_cleanProxy))
{
- m_pairCache->cleanOverlappingPair(pair,m_dispatcher);
+ m_pairCache->cleanOverlappingPair(pair, m_dispatcher);
}
return false;
}
-
};
- CleanPairCallback cleanPairs(proxy,this,dispatcher);
-
- processAllOverlappingPairs(&cleanPairs,dispatcher);
+ CleanPairCallback cleanPairs(proxy, this, dispatcher);
+ processAllOverlappingPairs(&cleanPairs, dispatcher);
}
-
-
-
-void btHashedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
+void btHashedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher)
{
-
- class RemovePairCallback : public btOverlapCallback
+ class RemovePairCallback : public btOverlapCallback
{
btBroadphaseProxy* m_obsoleteProxy;
public:
RemovePairCallback(btBroadphaseProxy* obsoleteProxy)
- :m_obsoleteProxy(obsoleteProxy)
+ : m_obsoleteProxy(obsoleteProxy)
{
}
- virtual bool processOverlap(btBroadphasePair& pair)
+ virtual bool processOverlap(btBroadphasePair& pair)
{
return ((pair.m_pProxy0 == m_obsoleteProxy) ||
- (pair.m_pProxy1 == m_obsoleteProxy));
+ (pair.m_pProxy1 == m_obsoleteProxy));
}
-
};
-
RemovePairCallback removeCallback(proxy);
- processAllOverlappingPairs(&removeCallback,dispatcher);
+ processAllOverlappingPairs(&removeCallback, dispatcher);
}
-
-
-
-
btBroadphasePair* btHashedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
{
- if(proxy0->m_uniqueId>proxy1->m_uniqueId)
- btSwap(proxy0,proxy1);
+ if (proxy0->m_uniqueId > proxy1->m_uniqueId)
+ btSwap(proxy0, proxy1);
int proxyId1 = proxy0->getUid();
int proxyId2 = proxy1->getUid();
/*if (proxyId1 > proxyId2)
btSwap(proxyId1, proxyId2);*/
- int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1), static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1));
+ int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1), static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity() - 1));
if (hash >= m_hashTable.size())
{
@@ -162,9 +134,8 @@ btBroadphasePair* btHashedOverlappingPairCache::findPair(btBroadphaseProxy* prox
//#include <stdio.h>
-void btHashedOverlappingPairCache::growTables()
+void btHashedOverlappingPairCache::growTables()
{
-
int newCapacity = m_overlappingPairArray.capacity();
if (m_hashTable.size() < newCapacity)
@@ -175,10 +146,9 @@ void btHashedOverlappingPairCache::growTables()
m_hashTable.resize(newCapacity);
m_next.resize(newCapacity);
-
int i;
- for (i= 0; i < newCapacity; ++i)
+ for (i = 0; i < newCapacity; ++i)
{
m_hashTable[i] = BT_NULL_PAIR;
}
@@ -187,35 +157,31 @@ void btHashedOverlappingPairCache::growTables()
m_next[i] = BT_NULL_PAIR;
}
- for(i=0;i<curHashtableSize;i++)
+ for (i = 0; i < curHashtableSize; i++)
{
-
const btBroadphasePair& pair = m_overlappingPairArray[i];
int proxyId1 = pair.m_pProxy0->getUid();
int proxyId2 = pair.m_pProxy1->getUid();
/*if (proxyId1 > proxyId2)
btSwap(proxyId1, proxyId2);*/
- int hashValue = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask
+ int hashValue = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1), static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity() - 1)); // New hash value with new mask
m_next[i] = m_hashTable[hashValue];
m_hashTable[hashValue] = i;
}
-
-
}
}
btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
{
- if(proxy0->m_uniqueId>proxy1->m_uniqueId)
- btSwap(proxy0,proxy1);
+ if (proxy0->m_uniqueId > proxy1->m_uniqueId)
+ btSwap(proxy0, proxy1);
int proxyId1 = proxy0->getUid();
int proxyId2 = proxy1->getUid();
/*if (proxyId1 > proxyId2)
btSwap(proxyId1, proxyId2);*/
- int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask
-
+ int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1), static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity() - 1)); // New hash value with new mask
btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash);
if (pair != NULL)
@@ -237,7 +203,7 @@ btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProx
//this is where we add an actual pair, so also call the 'ghost'
if (m_ghostPairCallback)
- m_ghostPairCallback->addOverlappingPair(proxy0,proxy1);
+ m_ghostPairCallback->addOverlappingPair(proxy0, proxy1);
int newCapacity = m_overlappingPairArray.capacity();
@@ -245,15 +211,14 @@ btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProx
{
growTables();
//hash with new capacity
- hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1));
+ hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1), static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity() - 1));
}
-
- pair = new (mem) btBroadphasePair(*proxy0,*proxy1);
-// pair->m_pProxy0 = proxy0;
-// pair->m_pProxy1 = proxy1;
+
+ pair = new (mem) btBroadphasePair(*proxy0, *proxy1);
+ // pair->m_pProxy0 = proxy0;
+ // pair->m_pProxy1 = proxy1;
pair->m_algorithm = 0;
pair->m_internalTmpValue = 0;
-
m_next[count] = m_hashTable[hash];
m_hashTable[hash] = count;
@@ -261,19 +226,17 @@ btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProx
return pair;
}
-
-
-void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1,btDispatcher* dispatcher)
+void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, btDispatcher* dispatcher)
{
- if(proxy0->m_uniqueId>proxy1->m_uniqueId)
- btSwap(proxy0,proxy1);
+ if (proxy0->m_uniqueId > proxy1->m_uniqueId)
+ btSwap(proxy0, proxy1);
int proxyId1 = proxy0->getUid();
int proxyId2 = proxy1->getUid();
/*if (proxyId1 > proxyId2)
btSwap(proxyId1, proxyId2);*/
- int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1));
+ int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1), static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity() - 1));
btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash);
if (pair == NULL)
@@ -281,7 +244,7 @@ void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* pro
return 0;
}
- cleanOverlappingPair(*pair,dispatcher);
+ cleanOverlappingPair(*pair, dispatcher);
void* userData = pair->m_internalInfo1;
@@ -319,7 +282,7 @@ void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* pro
int lastPairIndex = m_overlappingPairArray.size() - 1;
if (m_ghostPairCallback)
- m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1,dispatcher);
+ m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1, dispatcher);
// If the removed pair is the last pair, we are done.
if (lastPairIndex == pairIndex)
@@ -330,8 +293,8 @@ void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* pro
// Remove the last pair from the hash table.
const btBroadphasePair* last = &m_overlappingPairArray[lastPairIndex];
- /* missing swap here too, Nat. */
- int lastHash = static_cast<int>(getHash(static_cast<unsigned int>(last->m_pProxy0->getUid()), static_cast<unsigned int>(last->m_pProxy1->getUid())) & (m_overlappingPairArray.capacity()-1));
+ /* missing swap here too, Nat. */
+ int lastHash = static_cast<int>(getHash(static_cast<unsigned int>(last->m_pProxy0->getUid()), static_cast<unsigned int>(last->m_pProxy1->getUid())) & (m_overlappingPairArray.capacity() - 1));
index = m_hashTable[lastHash];
btAssert(index != BT_NULL_PAIR);
@@ -366,20 +329,20 @@ void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* pro
}
//#include <stdio.h>
#include "LinearMath/btQuickprof.h"
-void btHashedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher)
+void btHashedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback, btDispatcher* dispatcher)
{
BT_PROFILE("btHashedOverlappingPairCache::processAllOverlappingPairs");
int i;
-// printf("m_overlappingPairArray.size()=%d\n",m_overlappingPairArray.size());
- for (i=0;i<m_overlappingPairArray.size();)
+ // printf("m_overlappingPairArray.size()=%d\n",m_overlappingPairArray.size());
+ for (i = 0; i < m_overlappingPairArray.size();)
{
-
btBroadphasePair* pair = &m_overlappingPairArray[i];
if (callback->processOverlap(*pair))
{
- removeOverlappingPair(pair->m_pProxy0,pair->m_pProxy1,dispatcher);
- } else
+ removeOverlappingPair(pair->m_pProxy0, pair->m_pProxy1, dispatcher);
+ }
+ else
{
i++;
}
@@ -388,83 +351,83 @@ void btHashedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback*
struct MyPairIndex
{
- int m_orgIndex;
- int m_uidA0;
- int m_uidA1;
+ int m_orgIndex;
+ int m_uidA0;
+ int m_uidA1;
};
class MyPairIndeSortPredicate
{
public:
-
- bool operator() ( const MyPairIndex& a, const MyPairIndex& b ) const
- {
- const int uidA0 = a.m_uidA0;
- const int uidB0 = b.m_uidA0;
- const int uidA1 = a.m_uidA1;
- const int uidB1 = b.m_uidA1;
- return uidA0 > uidB0 || (uidA0 == uidB0 && uidA1 > uidB1);
- }
+ bool operator()(const MyPairIndex& a, const MyPairIndex& b) const
+ {
+ const int uidA0 = a.m_uidA0;
+ const int uidB0 = b.m_uidA0;
+ const int uidA1 = a.m_uidA1;
+ const int uidB1 = b.m_uidA1;
+ return uidA0 > uidB0 || (uidA0 == uidB0 && uidA1 > uidB1);
+ }
};
-void btHashedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher, const struct btDispatcherInfo& dispatchInfo)
+void btHashedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback, btDispatcher* dispatcher, const struct btDispatcherInfo& dispatchInfo)
{
- if (dispatchInfo.m_deterministicOverlappingPairs)
- {
- btBroadphasePairArray& pa = getOverlappingPairArray();
- btAlignedObjectArray<MyPairIndex> indices;
- {
- BT_PROFILE("sortOverlappingPairs");
- indices.resize(pa.size());
- for (int i=0;i<indices.size();i++)
- {
- const btBroadphasePair& p = pa[i];
- const int uidA0 = p.m_pProxy0 ? p.m_pProxy0->m_uniqueId : -1;
- const int uidA1 = p.m_pProxy1 ? p.m_pProxy1->m_uniqueId : -1;
-
- indices[i].m_uidA0 = uidA0;
- indices[i].m_uidA1 = uidA1;
- indices[i].m_orgIndex = i;
- }
- indices.quickSort(MyPairIndeSortPredicate());
- }
- {
- BT_PROFILE("btHashedOverlappingPairCache::processAllOverlappingPairs");
- int i;
- for (i=0;i<indices.size();)
- {
- btBroadphasePair* pair = &pa[indices[i].m_orgIndex];
- if (callback->processOverlap(*pair))
- {
- removeOverlappingPair(pair->m_pProxy0,pair->m_pProxy1,dispatcher);
- } else
- {
- i++;
- }
- }
- }
- } else
- {
- processAllOverlappingPairs(callback, dispatcher);
- }
-}
+ if (dispatchInfo.m_deterministicOverlappingPairs)
+ {
+ btBroadphasePairArray& pa = getOverlappingPairArray();
+ btAlignedObjectArray<MyPairIndex> indices;
+ {
+ BT_PROFILE("sortOverlappingPairs");
+ indices.resize(pa.size());
+ for (int i = 0; i < indices.size(); i++)
+ {
+ const btBroadphasePair& p = pa[i];
+ const int uidA0 = p.m_pProxy0 ? p.m_pProxy0->m_uniqueId : -1;
+ const int uidA1 = p.m_pProxy1 ? p.m_pProxy1->m_uniqueId : -1;
+ indices[i].m_uidA0 = uidA0;
+ indices[i].m_uidA1 = uidA1;
+ indices[i].m_orgIndex = i;
+ }
+ indices.quickSort(MyPairIndeSortPredicate());
+ }
+ {
+ BT_PROFILE("btHashedOverlappingPairCache::processAllOverlappingPairs");
+ int i;
+ for (i = 0; i < indices.size();)
+ {
+ btBroadphasePair* pair = &pa[indices[i].m_orgIndex];
+ if (callback->processOverlap(*pair))
+ {
+ removeOverlappingPair(pair->m_pProxy0, pair->m_pProxy1, dispatcher);
+ }
+ else
+ {
+ i++;
+ }
+ }
+ }
+ }
+ else
+ {
+ processAllOverlappingPairs(callback, dispatcher);
+ }
+}
-void btHashedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher)
+void btHashedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher)
{
///need to keep hashmap in sync with pair address, so rebuild all
btBroadphasePairArray tmpPairs;
int i;
- for (i=0;i<m_overlappingPairArray.size();i++)
+ for (i = 0; i < m_overlappingPairArray.size(); i++)
{
tmpPairs.push_back(m_overlappingPairArray[i]);
}
- for (i=0;i<tmpPairs.size();i++)
+ for (i = 0; i < tmpPairs.size(); i++)
{
- removeOverlappingPair(tmpPairs[i].m_pProxy0,tmpPairs[i].m_pProxy1,dispatcher);
+ removeOverlappingPair(tmpPairs[i].m_pProxy0, tmpPairs[i].m_pProxy1, dispatcher);
}
-
+
for (i = 0; i < m_next.size(); i++)
{
m_next[i] = BT_NULL_PAIR;
@@ -472,31 +435,28 @@ void btHashedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher
tmpPairs.quickSort(btBroadphasePairSortPredicate());
- for (i=0;i<tmpPairs.size();i++)
+ for (i = 0; i < tmpPairs.size(); i++)
{
- addOverlappingPair(tmpPairs[i].m_pProxy0,tmpPairs[i].m_pProxy1);
+ addOverlappingPair(tmpPairs[i].m_pProxy0, tmpPairs[i].m_pProxy1);
}
-
-
}
-
-void* btSortedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1, btDispatcher* dispatcher )
+void* btSortedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, btDispatcher* dispatcher)
{
if (!hasDeferredRemoval())
{
- btBroadphasePair findPair(*proxy0,*proxy1);
+ btBroadphasePair findPair(*proxy0, *proxy1);
int findIndex = m_overlappingPairArray.findLinearSearch(findPair);
if (findIndex < m_overlappingPairArray.size())
{
btBroadphasePair& pair = m_overlappingPairArray[findIndex];
void* userData = pair.m_internalInfo1;
- cleanOverlappingPair(pair,dispatcher);
+ cleanOverlappingPair(pair, dispatcher);
if (m_ghostPairCallback)
- m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1,dispatcher);
-
- m_overlappingPairArray.swap(findIndex,m_overlappingPairArray.capacity()-1);
+ m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1, dispatcher);
+
+ m_overlappingPairArray.swap(findIndex, m_overlappingPairArray.capacity() - 1);
m_overlappingPairArray.pop_back();
return userData;
}
@@ -505,95 +465,73 @@ void* btSortedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* pro
return 0;
}
-
-
-
-
-
-
-
-btBroadphasePair* btSortedOverlappingPairCache::addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+btBroadphasePair* btSortedOverlappingPairCache::addOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
{
//don't add overlap with own
btAssert(proxy0 != proxy1);
- if (!needsBroadphaseCollision(proxy0,proxy1))
+ if (!needsBroadphaseCollision(proxy0, proxy1))
return 0;
-
+
void* mem = &m_overlappingPairArray.expandNonInitializing();
- btBroadphasePair* pair = new (mem) btBroadphasePair(*proxy0,*proxy1);
+ btBroadphasePair* pair = new (mem) btBroadphasePair(*proxy0, *proxy1);
- if (m_ghostPairCallback)
+ if (m_ghostPairCallback)
m_ghostPairCallback->addOverlappingPair(proxy0, proxy1);
return pair;
-
}
///this findPair becomes really slow. Either sort the list to speedup the query, or
///use a different solution. It is mainly used for Removing overlapping pairs. Removal could be delayed.
///we could keep a linked list in each proxy, and store pair in one of the proxies (with lowest memory address)
///Also we can use a 2D bitmap, which can be useful for a future GPU implementation
- btBroadphasePair* btSortedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+btBroadphasePair* btSortedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
{
- if (!needsBroadphaseCollision(proxy0,proxy1))
+ if (!needsBroadphaseCollision(proxy0, proxy1))
return 0;
- btBroadphasePair tmpPair(*proxy0,*proxy1);
+ btBroadphasePair tmpPair(*proxy0, *proxy1);
int findIndex = m_overlappingPairArray.findLinearSearch(tmpPair);
if (findIndex < m_overlappingPairArray.size())
{
//btAssert(it != m_overlappingPairSet.end());
- btBroadphasePair* pair = &m_overlappingPairArray[findIndex];
+ btBroadphasePair* pair = &m_overlappingPairArray[findIndex];
return pair;
}
return 0;
}
-
-
-
-
-
-
-
-
-
//#include <stdio.h>
-void btSortedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher)
+void btSortedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback, btDispatcher* dispatcher)
{
-
int i;
- for (i=0;i<m_overlappingPairArray.size();)
+ for (i = 0; i < m_overlappingPairArray.size();)
{
-
btBroadphasePair* pair = &m_overlappingPairArray[i];
if (callback->processOverlap(*pair))
{
- cleanOverlappingPair(*pair,dispatcher);
+ cleanOverlappingPair(*pair, dispatcher);
pair->m_pProxy0 = 0;
pair->m_pProxy1 = 0;
- m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
+ m_overlappingPairArray.swap(i, m_overlappingPairArray.size() - 1);
m_overlappingPairArray.pop_back();
- } else
+ }
+ else
{
i++;
}
}
}
-
-
-
-btSortedOverlappingPairCache::btSortedOverlappingPairCache():
- m_blockedForChanges(false),
- m_hasDeferredRemoval(true),
- m_overlapFilterCallback(0),
- m_ghostPairCallback(0)
+btSortedOverlappingPairCache::btSortedOverlappingPairCache() : m_blockedForChanges(false),
+ m_hasDeferredRemoval(true),
+ m_overlapFilterCallback(0),
+ m_ghostPairCallback(0)
{
- int initialAllocatedSize= 2;
+ int initialAllocatedSize = 2;
m_overlappingPairArray.reserve(initialAllocatedSize);
}
@@ -601,81 +539,73 @@ btSortedOverlappingPairCache::~btSortedOverlappingPairCache()
{
}
-void btSortedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher)
+void btSortedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair, btDispatcher* dispatcher)
{
if (pair.m_algorithm)
{
{
pair.m_algorithm->~btCollisionAlgorithm();
dispatcher->freeCollisionAlgorithm(pair.m_algorithm);
- pair.m_algorithm=0;
+ pair.m_algorithm = 0;
}
}
}
-
-void btSortedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
+void btSortedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy, btDispatcher* dispatcher)
{
-
- class CleanPairCallback : public btOverlapCallback
+ class CleanPairCallback : public btOverlapCallback
{
btBroadphaseProxy* m_cleanProxy;
- btOverlappingPairCache* m_pairCache;
+ btOverlappingPairCache* m_pairCache;
btDispatcher* m_dispatcher;
public:
- CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache,btDispatcher* dispatcher)
- :m_cleanProxy(cleanProxy),
- m_pairCache(pairCache),
- m_dispatcher(dispatcher)
+ CleanPairCallback(btBroadphaseProxy* cleanProxy, btOverlappingPairCache* pairCache, btDispatcher* dispatcher)
+ : m_cleanProxy(cleanProxy),
+ m_pairCache(pairCache),
+ m_dispatcher(dispatcher)
{
}
- virtual bool processOverlap(btBroadphasePair& pair)
+ virtual bool processOverlap(btBroadphasePair& pair)
{
if ((pair.m_pProxy0 == m_cleanProxy) ||
(pair.m_pProxy1 == m_cleanProxy))
{
- m_pairCache->cleanOverlappingPair(pair,m_dispatcher);
+ m_pairCache->cleanOverlappingPair(pair, m_dispatcher);
}
return false;
}
-
};
- CleanPairCallback cleanPairs(proxy,this,dispatcher);
-
- processAllOverlappingPairs(&cleanPairs,dispatcher);
+ CleanPairCallback cleanPairs(proxy, this, dispatcher);
+ processAllOverlappingPairs(&cleanPairs, dispatcher);
}
-
-void btSortedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
+void btSortedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher)
{
-
- class RemovePairCallback : public btOverlapCallback
+ class RemovePairCallback : public btOverlapCallback
{
btBroadphaseProxy* m_obsoleteProxy;
public:
RemovePairCallback(btBroadphaseProxy* obsoleteProxy)
- :m_obsoleteProxy(obsoleteProxy)
+ : m_obsoleteProxy(obsoleteProxy)
{
}
- virtual bool processOverlap(btBroadphasePair& pair)
+ virtual bool processOverlap(btBroadphasePair& pair)
{
return ((pair.m_pProxy0 == m_obsoleteProxy) ||
- (pair.m_pProxy1 == m_obsoleteProxy));
+ (pair.m_pProxy1 == m_obsoleteProxy));
}
-
};
RemovePairCallback removeCallback(proxy);
- processAllOverlappingPairs(&removeCallback,dispatcher);
+ processAllOverlappingPairs(&removeCallback, dispatcher);
}
-void btSortedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher)
+void btSortedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher)
{
//should already be sorted
}
-
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h
index 7a38d34f05..a85782bc8a 100644
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h
+++ b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h
@@ -16,7 +16,6 @@ subject to the following restrictions:
#ifndef BT_OVERLAPPING_PAIR_CACHE_H
#define BT_OVERLAPPING_PAIR_CACHE_H
-
#include "btBroadphaseInterface.h"
#include "btBroadphaseProxy.h"
#include "btOverlappingPairCallback.h"
@@ -24,177 +23,163 @@ subject to the following restrictions:
#include "LinearMath/btAlignedObjectArray.h"
class btDispatcher;
-typedef btAlignedObjectArray<btBroadphasePair> btBroadphasePairArray;
+typedef btAlignedObjectArray<btBroadphasePair> btBroadphasePairArray;
-struct btOverlapCallback
+struct btOverlapCallback
{
virtual ~btOverlapCallback()
- {}
+ {
+ }
//return true for deletion of the pair
- virtual bool processOverlap(btBroadphasePair& pair) = 0;
-
+ virtual bool processOverlap(btBroadphasePair& pair) = 0;
};
struct btOverlapFilterCallback
{
virtual ~btOverlapFilterCallback()
- {}
+ {
+ }
// return true when pairs need collision
- virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const = 0;
+ virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) const = 0;
};
-
-
-
-
-
-
-const int BT_NULL_PAIR=0xffffffff;
+const int BT_NULL_PAIR = 0xffffffff;
///The btOverlappingPairCache provides an interface for overlapping pair management (add, remove, storage), used by the btBroadphaseInterface broadphases.
///The btHashedOverlappingPairCache and btSortedOverlappingPairCache classes are two implementations.
class btOverlappingPairCache : public btOverlappingPairCallback
{
public:
- virtual ~btOverlappingPairCache() {} // this is needed so we can get to the derived class destructor
+ virtual ~btOverlappingPairCache() {} // this is needed so we can get to the derived class destructor
+
+ virtual btBroadphasePair* getOverlappingPairArrayPtr() = 0;
- virtual btBroadphasePair* getOverlappingPairArrayPtr() = 0;
-
- virtual const btBroadphasePair* getOverlappingPairArrayPtr() const = 0;
+ virtual const btBroadphasePair* getOverlappingPairArrayPtr() const = 0;
- virtual btBroadphasePairArray& getOverlappingPairArray() = 0;
+ virtual btBroadphasePairArray& getOverlappingPairArray() = 0;
- virtual void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher) = 0;
+ virtual void cleanOverlappingPair(btBroadphasePair& pair, btDispatcher* dispatcher) = 0;
virtual int getNumOverlappingPairs() const = 0;
- virtual void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher) = 0;
+ virtual void cleanProxyFromPairs(btBroadphaseProxy* proxy, btDispatcher* dispatcher) = 0;
- virtual void setOverlapFilterCallback(btOverlapFilterCallback* callback) = 0;
+ virtual void setOverlapFilterCallback(btOverlapFilterCallback* callback) = 0;
- virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher) = 0;
+ virtual void processAllOverlappingPairs(btOverlapCallback*, btDispatcher* dispatcher) = 0;
- virtual void processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher, const struct btDispatcherInfo& dispatchInfo)
+ virtual void processAllOverlappingPairs(btOverlapCallback* callback, btDispatcher* dispatcher, const struct btDispatcherInfo& dispatchInfo)
{
processAllOverlappingPairs(callback, dispatcher);
}
virtual btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) = 0;
- virtual bool hasDeferredRemoval() = 0;
-
- virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)=0;
-
- virtual void sortOverlappingPairs(btDispatcher* dispatcher) = 0;
+ virtual bool hasDeferredRemoval() = 0;
+ virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback) = 0;
+ virtual void sortOverlappingPairs(btDispatcher* dispatcher) = 0;
};
/// Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman, Codercorner, http://codercorner.com
-ATTRIBUTE_ALIGNED16(class) btHashedOverlappingPairCache : public btOverlappingPairCache
+ATTRIBUTE_ALIGNED16(class)
+btHashedOverlappingPairCache : public btOverlappingPairCache
{
- btBroadphasePairArray m_overlappingPairArray;
+ btBroadphasePairArray m_overlappingPairArray;
btOverlapFilterCallback* m_overlapFilterCallback;
protected:
-
- btAlignedObjectArray<int> m_hashTable;
- btAlignedObjectArray<int> m_next;
- btOverlappingPairCallback* m_ghostPairCallback;
-
+ btAlignedObjectArray<int> m_hashTable;
+ btAlignedObjectArray<int> m_next;
+ btOverlappingPairCallback* m_ghostPairCallback;
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
-
+
btHashedOverlappingPairCache();
virtual ~btHashedOverlappingPairCache();
-
- void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+ void removeOverlappingPairsContainingProxy(btBroadphaseProxy * proxy, btDispatcher * dispatcher);
+
+ virtual void* removeOverlappingPair(btBroadphaseProxy * proxy0, btBroadphaseProxy * proxy1, btDispatcher * dispatcher);
- virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher);
-
- SIMD_FORCE_INLINE bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const
+ SIMD_FORCE_INLINE bool needsBroadphaseCollision(btBroadphaseProxy * proxy0, btBroadphaseProxy * proxy1) const
{
if (m_overlapFilterCallback)
- return m_overlapFilterCallback->needBroadphaseCollision(proxy0,proxy1);
+ return m_overlapFilterCallback->needBroadphaseCollision(proxy0, proxy1);
bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
-
+
return collides;
}
// Add a pair and return the new pair. If the pair already exists,
// no new pair is created and the old one is returned.
- virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+ virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy * proxy0, btBroadphaseProxy * proxy1)
{
- if (!needsBroadphaseCollision(proxy0,proxy1))
+ if (!needsBroadphaseCollision(proxy0, proxy1))
return 0;
- return internalAddPair(proxy0,proxy1);
+ return internalAddPair(proxy0, proxy1);
}
-
-
- void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+ void cleanProxyFromPairs(btBroadphaseProxy * proxy, btDispatcher * dispatcher);
-
- virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher);
+ virtual void processAllOverlappingPairs(btOverlapCallback*, btDispatcher * dispatcher);
- virtual void processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher, const struct btDispatcherInfo& dispatchInfo);
+ virtual void processAllOverlappingPairs(btOverlapCallback * callback, btDispatcher * dispatcher, const struct btDispatcherInfo& dispatchInfo);
- virtual btBroadphasePair* getOverlappingPairArrayPtr()
+ virtual btBroadphasePair* getOverlappingPairArrayPtr()
{
return &m_overlappingPairArray[0];
}
- const btBroadphasePair* getOverlappingPairArrayPtr() const
+ const btBroadphasePair* getOverlappingPairArrayPtr() const
{
return &m_overlappingPairArray[0];
}
- btBroadphasePairArray& getOverlappingPairArray()
+ btBroadphasePairArray& getOverlappingPairArray()
{
return m_overlappingPairArray;
}
- const btBroadphasePairArray& getOverlappingPairArray() const
+ const btBroadphasePairArray& getOverlappingPairArray() const
{
return m_overlappingPairArray;
}
- void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher);
-
+ void cleanOverlappingPair(btBroadphasePair & pair, btDispatcher * dispatcher);
-
- btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1);
+ btBroadphasePair* findPair(btBroadphaseProxy * proxy0, btBroadphaseProxy * proxy1);
int GetCount() const { return m_overlappingPairArray.size(); }
-// btBroadphasePair* GetPairs() { return m_pairs; }
+ // btBroadphasePair* GetPairs() { return m_pairs; }
btOverlapFilterCallback* getOverlapFilterCallback()
{
return m_overlapFilterCallback;
}
- void setOverlapFilterCallback(btOverlapFilterCallback* callback)
+ void setOverlapFilterCallback(btOverlapFilterCallback * callback)
{
m_overlapFilterCallback = callback;
}
- int getNumOverlappingPairs() const
+ int getNumOverlappingPairs() const
{
return m_overlappingPairArray.size();
}
+
private:
-
- btBroadphasePair* internalAddPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
+ btBroadphasePair* internalAddPair(btBroadphaseProxy * proxy0, btBroadphaseProxy * proxy1);
- void growTables();
+ void growTables();
SIMD_FORCE_INLINE bool equalsPair(const btBroadphasePair& pair, int proxyId1, int proxyId2)
- {
+ {
return pair.m_pProxy0->getUid() == proxyId1 && pair.m_pProxy1->getUid() == proxyId2;
}
@@ -214,40 +199,37 @@ private:
}
*/
-
SIMD_FORCE_INLINE unsigned int getHash(unsigned int proxyId1, unsigned int proxyId2)
{
unsigned int key = proxyId1 | (proxyId2 << 16);
// Thomas Wang's hash
key += ~(key << 15);
- key ^= (key >> 10);
- key += (key << 3);
- key ^= (key >> 6);
+ key ^= (key >> 10);
+ key += (key << 3);
+ key ^= (key >> 6);
key += ~(key << 11);
- key ^= (key >> 16);
+ key ^= (key >> 16);
return key;
}
-
-
- SIMD_FORCE_INLINE btBroadphasePair* internalFindPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, int hash)
+ SIMD_FORCE_INLINE btBroadphasePair* internalFindPair(btBroadphaseProxy * proxy0, btBroadphaseProxy * proxy1, int hash)
{
int proxyId1 = proxy0->getUid();
int proxyId2 = proxy1->getUid();
- #if 0 // wrong, 'equalsPair' use unsorted uids, copy-past devil striked again. Nat.
+#if 0 // wrong, 'equalsPair' use unsorted uids, copy-past devil striked again. Nat.
if (proxyId1 > proxyId2)
btSwap(proxyId1, proxyId2);
- #endif
+#endif
int index = m_hashTable[hash];
-
- while( index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false)
+
+ while (index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false)
{
index = m_next[index];
}
- if ( index == BT_NULL_PAIR )
+ if (index == BT_NULL_PAIR)
{
return NULL;
}
@@ -257,155 +239,136 @@ private:
return &m_overlappingPairArray[index];
}
- virtual bool hasDeferredRemoval()
+ virtual bool hasDeferredRemoval()
{
return false;
}
- virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)
+ virtual void setInternalGhostPairCallback(btOverlappingPairCallback * ghostPairCallback)
{
m_ghostPairCallback = ghostPairCallback;
}
- virtual void sortOverlappingPairs(btDispatcher* dispatcher);
-
-
-
+ virtual void sortOverlappingPairs(btDispatcher * dispatcher);
};
-
-
-
///btSortedOverlappingPairCache maintains the objects with overlapping AABB
///Typically managed by the Broadphase, Axis3Sweep or btSimpleBroadphase
-class btSortedOverlappingPairCache : public btOverlappingPairCache
+class btSortedOverlappingPairCache : public btOverlappingPairCache
{
- protected:
- //avoid brute-force finding all the time
- btBroadphasePairArray m_overlappingPairArray;
+protected:
+ //avoid brute-force finding all the time
+ btBroadphasePairArray m_overlappingPairArray;
- //during the dispatch, check that user doesn't destroy/create proxy
- bool m_blockedForChanges;
+ //during the dispatch, check that user doesn't destroy/create proxy
+ bool m_blockedForChanges;
- ///by default, do the removal during the pair traversal
- bool m_hasDeferredRemoval;
-
- //if set, use the callback instead of the built in filter in needBroadphaseCollision
- btOverlapFilterCallback* m_overlapFilterCallback;
+ ///by default, do the removal during the pair traversal
+ bool m_hasDeferredRemoval;
- btOverlappingPairCallback* m_ghostPairCallback;
+ //if set, use the callback instead of the built in filter in needBroadphaseCollision
+ btOverlapFilterCallback* m_overlapFilterCallback;
- public:
-
- btSortedOverlappingPairCache();
- virtual ~btSortedOverlappingPairCache();
+ btOverlappingPairCallback* m_ghostPairCallback;
- virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher);
+public:
+ btSortedOverlappingPairCache();
+ virtual ~btSortedOverlappingPairCache();
- void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher);
+ virtual void processAllOverlappingPairs(btOverlapCallback*, btDispatcher* dispatcher);
- void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher);
-
- btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
+ void* removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, btDispatcher* dispatcher);
- btBroadphasePair* findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
-
-
- void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+ void cleanOverlappingPair(btBroadphasePair& pair, btDispatcher* dispatcher);
- void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+ btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1);
+ btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1);
- inline bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const
- {
- if (m_overlapFilterCallback)
- return m_overlapFilterCallback->needBroadphaseCollision(proxy0,proxy1);
+ void cleanProxyFromPairs(btBroadphaseProxy* proxy, btDispatcher* dispatcher);
- bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
- collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
-
- return collides;
- }
-
- btBroadphasePairArray& getOverlappingPairArray()
- {
- return m_overlappingPairArray;
- }
+ void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher);
- const btBroadphasePairArray& getOverlappingPairArray() const
- {
- return m_overlappingPairArray;
- }
+ inline bool needsBroadphaseCollision(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) const
+ {
+ if (m_overlapFilterCallback)
+ return m_overlapFilterCallback->needBroadphaseCollision(proxy0, proxy1);
-
+ bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
+ collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
+ return collides;
+ }
- btBroadphasePair* getOverlappingPairArrayPtr()
- {
- return &m_overlappingPairArray[0];
- }
+ btBroadphasePairArray& getOverlappingPairArray()
+ {
+ return m_overlappingPairArray;
+ }
- const btBroadphasePair* getOverlappingPairArrayPtr() const
- {
- return &m_overlappingPairArray[0];
- }
+ const btBroadphasePairArray& getOverlappingPairArray() const
+ {
+ return m_overlappingPairArray;
+ }
- int getNumOverlappingPairs() const
- {
- return m_overlappingPairArray.size();
- }
-
- btOverlapFilterCallback* getOverlapFilterCallback()
- {
- return m_overlapFilterCallback;
- }
+ btBroadphasePair* getOverlappingPairArrayPtr()
+ {
+ return &m_overlappingPairArray[0];
+ }
- void setOverlapFilterCallback(btOverlapFilterCallback* callback)
- {
- m_overlapFilterCallback = callback;
- }
+ const btBroadphasePair* getOverlappingPairArrayPtr() const
+ {
+ return &m_overlappingPairArray[0];
+ }
- virtual bool hasDeferredRemoval()
- {
- return m_hasDeferredRemoval;
- }
+ int getNumOverlappingPairs() const
+ {
+ return m_overlappingPairArray.size();
+ }
- virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)
- {
- m_ghostPairCallback = ghostPairCallback;
- }
+ btOverlapFilterCallback* getOverlapFilterCallback()
+ {
+ return m_overlapFilterCallback;
+ }
- virtual void sortOverlappingPairs(btDispatcher* dispatcher);
-
+ void setOverlapFilterCallback(btOverlapFilterCallback* callback)
+ {
+ m_overlapFilterCallback = callback;
+ }
-};
+ virtual bool hasDeferredRemoval()
+ {
+ return m_hasDeferredRemoval;
+ }
+ virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)
+ {
+ m_ghostPairCallback = ghostPairCallback;
+ }
+ virtual void sortOverlappingPairs(btDispatcher* dispatcher);
+};
///btNullPairCache skips add/removal of overlapping pairs. Userful for benchmarking and unit testing.
class btNullPairCache : public btOverlappingPairCache
{
-
- btBroadphasePairArray m_overlappingPairArray;
+ btBroadphasePairArray m_overlappingPairArray;
public:
-
- virtual btBroadphasePair* getOverlappingPairArrayPtr()
+ virtual btBroadphasePair* getOverlappingPairArrayPtr()
{
return &m_overlappingPairArray[0];
}
- const btBroadphasePair* getOverlappingPairArrayPtr() const
+ const btBroadphasePair* getOverlappingPairArrayPtr() const
{
return &m_overlappingPairArray[0];
}
- btBroadphasePairArray& getOverlappingPairArray()
+ btBroadphasePairArray& getOverlappingPairArray()
{
return m_overlappingPairArray;
}
-
- virtual void cleanOverlappingPair(btBroadphasePair& /*pair*/,btDispatcher* /*dispatcher*/)
- {
+ virtual void cleanOverlappingPair(btBroadphasePair& /*pair*/, btDispatcher* /*dispatcher*/)
+ {
}
virtual int getNumOverlappingPairs() const
@@ -413,16 +376,15 @@ public:
return 0;
}
- virtual void cleanProxyFromPairs(btBroadphaseProxy* /*proxy*/,btDispatcher* /*dispatcher*/)
+ virtual void cleanProxyFromPairs(btBroadphaseProxy* /*proxy*/, btDispatcher* /*dispatcher*/)
{
-
}
- virtual void setOverlapFilterCallback(btOverlapFilterCallback* /*callback*/)
+ virtual void setOverlapFilterCallback(btOverlapFilterCallback* /*callback*/)
{
}
- virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* /*dispatcher*/)
+ virtual void processAllOverlappingPairs(btOverlapCallback*, btDispatcher* /*dispatcher*/)
{
}
@@ -431,39 +393,33 @@ public:
return 0;
}
- virtual bool hasDeferredRemoval()
+ virtual bool hasDeferredRemoval()
{
return true;
}
- virtual void setInternalGhostPairCallback(btOverlappingPairCallback* /* ghostPairCallback */)
+ virtual void setInternalGhostPairCallback(btOverlappingPairCallback* /* ghostPairCallback */)
{
-
}
- virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/)
+ virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* /*proxy0*/, btBroadphaseProxy* /*proxy1*/)
{
return 0;
}
- virtual void* removeOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/,btDispatcher* /*dispatcher*/)
+ virtual void* removeOverlappingPair(btBroadphaseProxy* /*proxy0*/, btBroadphaseProxy* /*proxy1*/, btDispatcher* /*dispatcher*/)
{
return 0;
}
- virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/,btDispatcher* /*dispatcher*/)
+ virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/, btDispatcher* /*dispatcher*/)
{
}
-
- virtual void sortOverlappingPairs(btDispatcher* dispatcher)
+
+ virtual void sortOverlappingPairs(btDispatcher* dispatcher)
{
- (void) dispatcher;
+ (void)dispatcher;
}
-
-
};
-
-#endif //BT_OVERLAPPING_PAIR_CACHE_H
-
-
+#endif //BT_OVERLAPPING_PAIR_CACHE_H
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h
index 3e069fa5e2..d16c72542f 100644
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h
+++ b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h
@@ -18,26 +18,24 @@ subject to the following restrictions:
#define OVERLAPPING_PAIR_CALLBACK_H
class btDispatcher;
-struct btBroadphasePair;
+struct btBroadphasePair;
///The btOverlappingPairCallback class is an additional optional broadphase user callback for adding/removing overlapping pairs, similar interface to btOverlappingPairCache.
class btOverlappingPairCallback
{
protected:
- btOverlappingPairCallback() {}
-
+ btOverlappingPairCallback() {}
+
public:
virtual ~btOverlappingPairCallback()
{
-
}
-
- virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) = 0;
- virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher) = 0;
+ virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) = 0;
- virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy0,btDispatcher* dispatcher) = 0;
+ virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, btDispatcher* dispatcher) = 0;
+ virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy0, btDispatcher* dispatcher) = 0;
};
-#endif //OVERLAPPING_PAIR_CALLBACK_H
+#endif //OVERLAPPING_PAIR_CALLBACK_H
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp
index 875d89c53e..b814fd84d8 100644
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp
+++ b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp
@@ -21,43 +21,38 @@ subject to the following restrictions:
#define RAYAABB2
-btQuantizedBvh::btQuantizedBvh() :
- m_bulletVersion(BT_BULLET_VERSION),
- m_useQuantization(false),
- //m_traversalMode(TRAVERSAL_STACKLESS_CACHE_FRIENDLY)
- m_traversalMode(TRAVERSAL_STACKLESS)
- //m_traversalMode(TRAVERSAL_RECURSIVE)
- ,m_subtreeHeaderCount(0) //PCK: add this line
+btQuantizedBvh::btQuantizedBvh() : m_bulletVersion(BT_BULLET_VERSION),
+ m_useQuantization(false),
+ //m_traversalMode(TRAVERSAL_STACKLESS_CACHE_FRIENDLY)
+ m_traversalMode(TRAVERSAL_STACKLESS)
+ //m_traversalMode(TRAVERSAL_RECURSIVE)
+ ,
+ m_subtreeHeaderCount(0) //PCK: add this line
{
- m_bvhAabbMin.setValue(-SIMD_INFINITY,-SIMD_INFINITY,-SIMD_INFINITY);
- m_bvhAabbMax.setValue(SIMD_INFINITY,SIMD_INFINITY,SIMD_INFINITY);
+ m_bvhAabbMin.setValue(-SIMD_INFINITY, -SIMD_INFINITY, -SIMD_INFINITY);
+ m_bvhAabbMax.setValue(SIMD_INFINITY, SIMD_INFINITY, SIMD_INFINITY);
}
-
-
-
-
void btQuantizedBvh::buildInternal()
{
///assumes that caller filled in the m_quantizedLeafNodes
m_useQuantization = true;
int numLeafNodes = 0;
-
+
if (m_useQuantization)
{
//now we have an array of leafnodes in m_leafNodes
numLeafNodes = m_quantizedLeafNodes.size();
- m_quantizedContiguousNodes.resize(2*numLeafNodes);
-
+ m_quantizedContiguousNodes.resize(2 * numLeafNodes);
}
m_curNodeIndex = 0;
- buildTree(0,numLeafNodes);
+ buildTree(0, numLeafNodes);
///if the entire tree is small then subtree size, we need to create a header info for the tree
- if(m_useQuantization && !m_SubtreeHeaders.size())
+ if (m_useQuantization && !m_SubtreeHeaders.size())
{
btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[0]);
@@ -73,29 +68,24 @@ void btQuantizedBvh::buildInternal()
m_leafNodes.clear();
}
-
-
///just for debugging, to visualize the individual patches/subtrees
#ifdef DEBUG_PATCH_COLORS
-btVector3 color[4]=
-{
- btVector3(1,0,0),
- btVector3(0,1,0),
- btVector3(0,0,1),
- btVector3(0,1,1)
-};
-#endif //DEBUG_PATCH_COLORS
-
-
+btVector3 color[4] =
+ {
+ btVector3(1, 0, 0),
+ btVector3(0, 1, 0),
+ btVector3(0, 0, 1),
+ btVector3(0, 1, 1)};
+#endif //DEBUG_PATCH_COLORS
-void btQuantizedBvh::setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin)
+void btQuantizedBvh::setQuantizationValues(const btVector3& bvhAabbMin, const btVector3& bvhAabbMax, btScalar quantizationMargin)
{
//enlarge the AABB to avoid division by zero when initializing the quantization values
- btVector3 clampValue(quantizationMargin,quantizationMargin,quantizationMargin);
+ btVector3 clampValue(quantizationMargin, quantizationMargin, quantizationMargin);
m_bvhAabbMin = bvhAabbMin - clampValue;
m_bvhAabbMax = bvhAabbMax + clampValue;
btVector3 aabbSize = m_bvhAabbMax - m_bvhAabbMin;
- m_bvhQuantization = btVector3(btScalar(65533.0),btScalar(65533.0),btScalar(65533.0)) / aabbSize;
+ m_bvhQuantization = btVector3(btScalar(65533.0), btScalar(65533.0), btScalar(65533.0)) / aabbSize;
m_useQuantization = true;
@@ -103,25 +93,22 @@ void btQuantizedBvh::setQuantizationValues(const btVector3& bvhAabbMin,const btV
unsigned short vecIn[3];
btVector3 v;
{
- quantize(vecIn,m_bvhAabbMin,false);
+ quantize(vecIn, m_bvhAabbMin, false);
v = unQuantize(vecIn);
- m_bvhAabbMin.setMin(v-clampValue);
+ m_bvhAabbMin.setMin(v - clampValue);
}
- aabbSize = m_bvhAabbMax - m_bvhAabbMin;
- m_bvhQuantization = btVector3(btScalar(65533.0),btScalar(65533.0),btScalar(65533.0)) / aabbSize;
+ aabbSize = m_bvhAabbMax - m_bvhAabbMin;
+ m_bvhQuantization = btVector3(btScalar(65533.0), btScalar(65533.0), btScalar(65533.0)) / aabbSize;
{
- quantize(vecIn,m_bvhAabbMax,true);
+ quantize(vecIn, m_bvhAabbMax, true);
v = unQuantize(vecIn);
- m_bvhAabbMax.setMax(v+clampValue);
+ m_bvhAabbMax.setMax(v + clampValue);
}
aabbSize = m_bvhAabbMax - m_bvhAabbMin;
- m_bvhQuantization = btVector3(btScalar(65533.0),btScalar(65533.0),btScalar(65533.0)) / aabbSize;
+ m_bvhQuantization = btVector3(btScalar(65533.0), btScalar(65533.0), btScalar(65533.0)) / aabbSize;
}
}
-
-
-
btQuantizedBvh::~btQuantizedBvh()
{
}
@@ -129,104 +116,100 @@ btQuantizedBvh::~btQuantizedBvh()
#ifdef DEBUG_TREE_BUILDING
int gStackDepth = 0;
int gMaxStackDepth = 0;
-#endif //DEBUG_TREE_BUILDING
+#endif //DEBUG_TREE_BUILDING
-void btQuantizedBvh::buildTree (int startIndex,int endIndex)
+void btQuantizedBvh::buildTree(int startIndex, int endIndex)
{
#ifdef DEBUG_TREE_BUILDING
gStackDepth++;
if (gStackDepth > gMaxStackDepth)
gMaxStackDepth = gStackDepth;
-#endif //DEBUG_TREE_BUILDING
-
+#endif //DEBUG_TREE_BUILDING
int splitAxis, splitIndex, i;
- int numIndices =endIndex-startIndex;
+ int numIndices = endIndex - startIndex;
int curIndex = m_curNodeIndex;
- btAssert(numIndices>0);
+ btAssert(numIndices > 0);
- if (numIndices==1)
+ if (numIndices == 1)
{
#ifdef DEBUG_TREE_BUILDING
gStackDepth--;
-#endif //DEBUG_TREE_BUILDING
-
- assignInternalNodeFromLeafNode(m_curNodeIndex,startIndex);
+#endif //DEBUG_TREE_BUILDING
+
+ assignInternalNodeFromLeafNode(m_curNodeIndex, startIndex);
m_curNodeIndex++;
- return;
+ return;
}
//calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'.
-
- splitAxis = calcSplittingAxis(startIndex,endIndex);
- splitIndex = sortAndCalcSplittingIndex(startIndex,endIndex,splitAxis);
+ splitAxis = calcSplittingAxis(startIndex, endIndex);
+
+ splitIndex = sortAndCalcSplittingIndex(startIndex, endIndex, splitAxis);
int internalNodeIndex = m_curNodeIndex;
-
+
//set the min aabb to 'inf' or a max value, and set the max aabb to a -inf/minimum value.
//the aabb will be expanded during buildTree/mergeInternalNodeAabb with actual node values
- setInternalNodeAabbMin(m_curNodeIndex,m_bvhAabbMax);//can't use btVector3(SIMD_INFINITY,SIMD_INFINITY,SIMD_INFINITY)) because of quantization
- setInternalNodeAabbMax(m_curNodeIndex,m_bvhAabbMin);//can't use btVector3(-SIMD_INFINITY,-SIMD_INFINITY,-SIMD_INFINITY)) because of quantization
-
-
- for (i=startIndex;i<endIndex;i++)
+ setInternalNodeAabbMin(m_curNodeIndex, m_bvhAabbMax); //can't use btVector3(SIMD_INFINITY,SIMD_INFINITY,SIMD_INFINITY)) because of quantization
+ setInternalNodeAabbMax(m_curNodeIndex, m_bvhAabbMin); //can't use btVector3(-SIMD_INFINITY,-SIMD_INFINITY,-SIMD_INFINITY)) because of quantization
+
+ for (i = startIndex; i < endIndex; i++)
{
- mergeInternalNodeAabb(m_curNodeIndex,getAabbMin(i),getAabbMax(i));
+ mergeInternalNodeAabb(m_curNodeIndex, getAabbMin(i), getAabbMax(i));
}
m_curNodeIndex++;
-
//internalNode->m_escapeIndex;
-
+
int leftChildNodexIndex = m_curNodeIndex;
//build left child tree
- buildTree(startIndex,splitIndex);
+ buildTree(startIndex, splitIndex);
int rightChildNodexIndex = m_curNodeIndex;
//build right child tree
- buildTree(splitIndex,endIndex);
+ buildTree(splitIndex, endIndex);
#ifdef DEBUG_TREE_BUILDING
gStackDepth--;
-#endif //DEBUG_TREE_BUILDING
+#endif //DEBUG_TREE_BUILDING
int escapeIndex = m_curNodeIndex - curIndex;
if (m_useQuantization)
{
//escapeIndex is the number of nodes of this subtree
- const int sizeQuantizedNode =sizeof(btQuantizedBvhNode);
+ const int sizeQuantizedNode = sizeof(btQuantizedBvhNode);
const int treeSizeInBytes = escapeIndex * sizeQuantizedNode;
if (treeSizeInBytes > MAX_SUBTREE_SIZE_IN_BYTES)
{
- updateSubtreeHeaders(leftChildNodexIndex,rightChildNodexIndex);
+ updateSubtreeHeaders(leftChildNodexIndex, rightChildNodexIndex);
}
- } else
+ }
+ else
{
-
}
- setInternalNodeEscapeIndex(internalNodeIndex,escapeIndex);
-
+ setInternalNodeEscapeIndex(internalNodeIndex, escapeIndex);
}
-void btQuantizedBvh::updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex)
+void btQuantizedBvh::updateSubtreeHeaders(int leftChildNodexIndex, int rightChildNodexIndex)
{
btAssert(m_useQuantization);
btQuantizedBvhNode& leftChildNode = m_quantizedContiguousNodes[leftChildNodexIndex];
int leftSubTreeSize = leftChildNode.isLeafNode() ? 1 : leftChildNode.getEscapeIndex();
- int leftSubTreeSizeInBytes = leftSubTreeSize * static_cast<int>(sizeof(btQuantizedBvhNode));
-
+ int leftSubTreeSizeInBytes = leftSubTreeSize * static_cast<int>(sizeof(btQuantizedBvhNode));
+
btQuantizedBvhNode& rightChildNode = m_quantizedContiguousNodes[rightChildNodexIndex];
int rightSubTreeSize = rightChildNode.isLeafNode() ? 1 : rightChildNode.getEscapeIndex();
- int rightSubTreeSizeInBytes = rightSubTreeSize * static_cast<int>(sizeof(btQuantizedBvhNode));
+ int rightSubTreeSizeInBytes = rightSubTreeSize * static_cast<int>(sizeof(btQuantizedBvhNode));
- if(leftSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES)
+ if (leftSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES)
{
btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
subtree.setAabbFromQuantizeNode(leftChildNode);
@@ -234,7 +217,7 @@ void btQuantizedBvh::updateSubtreeHeaders(int leftChildNodexIndex,int rightChild
subtree.m_subtreeSize = leftSubTreeSize;
}
- if(rightSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES)
+ if (rightSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES)
{
btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
subtree.setAabbFromQuantizeNode(rightChildNode);
@@ -246,32 +229,31 @@ void btQuantizedBvh::updateSubtreeHeaders(int leftChildNodexIndex,int rightChild
m_subtreeHeaderCount = m_SubtreeHeaders.size();
}
-
-int btQuantizedBvh::sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis)
+int btQuantizedBvh::sortAndCalcSplittingIndex(int startIndex, int endIndex, int splitAxis)
{
int i;
- int splitIndex =startIndex;
+ int splitIndex = startIndex;
int numIndices = endIndex - startIndex;
btScalar splitValue;
- btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
- for (i=startIndex;i<endIndex;i++)
+ btVector3 means(btScalar(0.), btScalar(0.), btScalar(0.));
+ for (i = startIndex; i < endIndex; i++)
{
- btVector3 center = btScalar(0.5)*(getAabbMax(i)+getAabbMin(i));
- means+=center;
+ btVector3 center = btScalar(0.5) * (getAabbMax(i) + getAabbMin(i));
+ means += center;
}
- means *= (btScalar(1.)/(btScalar)numIndices);
-
+ means *= (btScalar(1.) / (btScalar)numIndices);
+
splitValue = means[splitAxis];
-
+
//sort leafNodes so all values larger then splitValue comes first, and smaller values start from 'splitIndex'.
- for (i=startIndex;i<endIndex;i++)
+ for (i = startIndex; i < endIndex; i++)
{
- btVector3 center = btScalar(0.5)*(getAabbMax(i)+getAabbMin(i));
+ btVector3 center = btScalar(0.5) * (getAabbMax(i) + getAabbMin(i));
if (center[splitAxis] > splitValue)
{
//swap
- swapLeafNodes(i,splitIndex);
+ swapLeafNodes(i, splitIndex);
splitIndex++;
}
}
@@ -281,56 +263,53 @@ int btQuantizedBvh::sortAndCalcSplittingIndex(int startIndex,int endIndex,int sp
//unbalanced1 is unsafe: it can cause stack overflows
//bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1)));
- //unbalanced2 should work too: always use center (perfect balanced trees)
+ //unbalanced2 should work too: always use center (perfect balanced trees)
//bool unbalanced2 = true;
//this should be safe too:
- int rangeBalancedIndices = numIndices/3;
- bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices)));
-
+ int rangeBalancedIndices = numIndices / 3;
+ bool unbalanced = ((splitIndex <= (startIndex + rangeBalancedIndices)) || (splitIndex >= (endIndex - 1 - rangeBalancedIndices)));
+
if (unbalanced)
{
- splitIndex = startIndex+ (numIndices>>1);
+ splitIndex = startIndex + (numIndices >> 1);
}
- bool unbal = (splitIndex==startIndex) || (splitIndex == (endIndex));
+ bool unbal = (splitIndex == startIndex) || (splitIndex == (endIndex));
(void)unbal;
btAssert(!unbal);
return splitIndex;
}
-
-int btQuantizedBvh::calcSplittingAxis(int startIndex,int endIndex)
+int btQuantizedBvh::calcSplittingAxis(int startIndex, int endIndex)
{
int i;
- btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
- btVector3 variance(btScalar(0.),btScalar(0.),btScalar(0.));
- int numIndices = endIndex-startIndex;
+ btVector3 means(btScalar(0.), btScalar(0.), btScalar(0.));
+ btVector3 variance(btScalar(0.), btScalar(0.), btScalar(0.));
+ int numIndices = endIndex - startIndex;
- for (i=startIndex;i<endIndex;i++)
+ for (i = startIndex; i < endIndex; i++)
{
- btVector3 center = btScalar(0.5)*(getAabbMax(i)+getAabbMin(i));
- means+=center;
+ btVector3 center = btScalar(0.5) * (getAabbMax(i) + getAabbMin(i));
+ means += center;
}
- means *= (btScalar(1.)/(btScalar)numIndices);
-
- for (i=startIndex;i<endIndex;i++)
+ means *= (btScalar(1.) / (btScalar)numIndices);
+
+ for (i = startIndex; i < endIndex; i++)
{
- btVector3 center = btScalar(0.5)*(getAabbMax(i)+getAabbMin(i));
- btVector3 diff2 = center-means;
+ btVector3 center = btScalar(0.5) * (getAabbMax(i) + getAabbMin(i));
+ btVector3 diff2 = center - means;
diff2 = diff2 * diff2;
variance += diff2;
}
- variance *= (btScalar(1.)/ ((btScalar)numIndices-1) );
-
+ variance *= (btScalar(1.) / ((btScalar)numIndices - 1));
+
return variance.maxAxis();
}
-
-
-void btQuantizedBvh::reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const
+void btQuantizedBvh::reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& aabbMin, const btVector3& aabbMax) const
{
//either choose recursive traversal (walkTree) or stackless (walkStacklessTree)
@@ -339,38 +318,37 @@ void btQuantizedBvh::reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallb
///quantize query AABB
unsigned short int quantizedQueryAabbMin[3];
unsigned short int quantizedQueryAabbMax[3];
- quantizeWithClamp(quantizedQueryAabbMin,aabbMin,0);
- quantizeWithClamp(quantizedQueryAabbMax,aabbMax,1);
+ quantizeWithClamp(quantizedQueryAabbMin, aabbMin, 0);
+ quantizeWithClamp(quantizedQueryAabbMax, aabbMax, 1);
switch (m_traversalMode)
{
- case TRAVERSAL_STACKLESS:
- walkStacklessQuantizedTree(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax,0,m_curNodeIndex);
- break;
- case TRAVERSAL_STACKLESS_CACHE_FRIENDLY:
- walkStacklessQuantizedTreeCacheFriendly(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
- break;
- case TRAVERSAL_RECURSIVE:
+ case TRAVERSAL_STACKLESS:
+ walkStacklessQuantizedTree(nodeCallback, quantizedQueryAabbMin, quantizedQueryAabbMax, 0, m_curNodeIndex);
+ break;
+ case TRAVERSAL_STACKLESS_CACHE_FRIENDLY:
+ walkStacklessQuantizedTreeCacheFriendly(nodeCallback, quantizedQueryAabbMin, quantizedQueryAabbMax);
+ break;
+ case TRAVERSAL_RECURSIVE:
{
const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[0];
- walkRecursiveQuantizedTreeAgainstQueryAabb(rootNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
+ walkRecursiveQuantizedTreeAgainstQueryAabb(rootNode, nodeCallback, quantizedQueryAabbMin, quantizedQueryAabbMax);
}
break;
- default:
- //unsupported
- btAssert(0);
+ default:
+ //unsupported
+ btAssert(0);
}
- } else
+ }
+ else
{
- walkStacklessTree(nodeCallback,aabbMin,aabbMax);
+ walkStacklessTree(nodeCallback, aabbMin, aabbMax);
}
}
-
int maxIterations = 0;
-
-void btQuantizedBvh::walkStacklessTree(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const
+void btQuantizedBvh::walkStacklessTree(btNodeOverlapCallback* nodeCallback, const btVector3& aabbMin, const btVector3& aabbMax) const
{
btAssert(!m_useQuantization);
@@ -384,24 +362,25 @@ void btQuantizedBvh::walkStacklessTree(btNodeOverlapCallback* nodeCallback,const
while (curIndex < m_curNodeIndex)
{
//catch bugs in tree data
- btAssert (walkIterations < m_curNodeIndex);
+ btAssert(walkIterations < m_curNodeIndex);
walkIterations++;
- aabbOverlap = TestAabbAgainstAabb2(aabbMin,aabbMax,rootNode->m_aabbMinOrg,rootNode->m_aabbMaxOrg);
+ aabbOverlap = TestAabbAgainstAabb2(aabbMin, aabbMax, rootNode->m_aabbMinOrg, rootNode->m_aabbMaxOrg);
isLeafNode = rootNode->m_escapeIndex == -1;
-
+
//PCK: unsigned instead of bool
if (isLeafNode && (aabbOverlap != 0))
{
- nodeCallback->processNode(rootNode->m_subPart,rootNode->m_triangleIndex);
- }
-
+ nodeCallback->processNode(rootNode->m_subPart, rootNode->m_triangleIndex);
+ }
+
//PCK: unsigned instead of bool
if ((aabbOverlap != 0) || isLeafNode)
{
rootNode++;
curIndex++;
- } else
+ }
+ else
{
escapeIndex = rootNode->m_escapeIndex;
rootNode += escapeIndex;
@@ -410,7 +389,6 @@ void btQuantizedBvh::walkStacklessTree(btNodeOverlapCallback* nodeCallback,const
}
if (maxIterations < walkIterations)
maxIterations = walkIterations;
-
}
/*
@@ -434,39 +412,38 @@ void btQuantizedBvh::walkTree(btOptimizedBvhNode* rootNode,btNodeOverlapCallback
}
*/
-void btQuantizedBvh::walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const
+void btQuantizedBvh::walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode, btNodeOverlapCallback* nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax) const
{
btAssert(m_useQuantization);
-
+
bool isLeafNode;
//PCK: unsigned instead of bool
unsigned aabbOverlap;
//PCK: unsigned instead of bool
- aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,currentNode->m_quantizedAabbMin,currentNode->m_quantizedAabbMax);
+ aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin, quantizedQueryAabbMax, currentNode->m_quantizedAabbMin, currentNode->m_quantizedAabbMax);
isLeafNode = currentNode->isLeafNode();
-
+
//PCK: unsigned instead of bool
if (aabbOverlap != 0)
{
if (isLeafNode)
{
- nodeCallback->processNode(currentNode->getPartId(),currentNode->getTriangleIndex());
- } else
+ nodeCallback->processNode(currentNode->getPartId(), currentNode->getTriangleIndex());
+ }
+ else
{
//process left and right children
- const btQuantizedBvhNode* leftChildNode = currentNode+1;
- walkRecursiveQuantizedTreeAgainstQueryAabb(leftChildNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
+ const btQuantizedBvhNode* leftChildNode = currentNode + 1;
+ walkRecursiveQuantizedTreeAgainstQueryAabb(leftChildNode, nodeCallback, quantizedQueryAabbMin, quantizedQueryAabbMax);
- const btQuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? leftChildNode+1:leftChildNode+leftChildNode->getEscapeIndex();
- walkRecursiveQuantizedTreeAgainstQueryAabb(rightChildNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
+ const btQuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? leftChildNode + 1 : leftChildNode + leftChildNode->getEscapeIndex();
+ walkRecursiveQuantizedTreeAgainstQueryAabb(rightChildNode, nodeCallback, quantizedQueryAabbMin, quantizedQueryAabbMax);
}
- }
+ }
}
-
-
-void btQuantizedBvh::walkStacklessTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const
+void btQuantizedBvh::walkStacklessTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex, int endNodeIndex) const
{
btAssert(!m_useQuantization);
@@ -475,11 +452,11 @@ void btQuantizedBvh::walkStacklessTreeAgainstRay(btNodeOverlapCallback* nodeCall
int walkIterations = 0;
bool isLeafNode;
//PCK: unsigned instead of bool
- unsigned aabbOverlap=0;
- unsigned rayBoxOverlap=0;
+ unsigned aabbOverlap = 0;
+ unsigned rayBoxOverlap = 0;
btScalar lambda_max = 1.0;
-
- /* Quick pruning by quantized box */
+
+ /* Quick pruning by quantized box */
btVector3 rayAabbMin = raySource;
btVector3 rayAabbMax = raySource;
rayAabbMin.setMin(rayTarget);
@@ -490,15 +467,15 @@ void btQuantizedBvh::walkStacklessTreeAgainstRay(btNodeOverlapCallback* nodeCall
rayAabbMax += aabbMax;
#ifdef RAYAABB2
- btVector3 rayDir = (rayTarget-raySource);
- rayDir.normalize ();
- lambda_max = rayDir.dot(rayTarget-raySource);
+ btVector3 rayDir = (rayTarget - raySource);
+ rayDir.normalize();
+ lambda_max = rayDir.dot(rayTarget - raySource);
///what about division by zero? --> just set rayDirection[i] to 1.0
btVector3 rayDirectionInverse;
rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0];
rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1];
rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2];
- unsigned int sign[3] = { rayDirectionInverse[0] < 0.0, rayDirectionInverse[1] < 0.0, rayDirectionInverse[2] < 0.0};
+ unsigned int sign[3] = {rayDirectionInverse[0] < 0.0, rayDirectionInverse[1] < 0.0, rayDirectionInverse[2] < 0.0};
#endif
btVector3 bounds[2];
@@ -507,7 +484,7 @@ void btQuantizedBvh::walkStacklessTreeAgainstRay(btNodeOverlapCallback* nodeCall
{
btScalar param = 1.0;
//catch bugs in tree data
- btAssert (walkIterations < m_curNodeIndex);
+ btAssert(walkIterations < m_curNodeIndex);
walkIterations++;
@@ -517,34 +494,35 @@ void btQuantizedBvh::walkStacklessTreeAgainstRay(btNodeOverlapCallback* nodeCall
bounds[0] -= aabbMax;
bounds[1] -= aabbMin;
- aabbOverlap = TestAabbAgainstAabb2(rayAabbMin,rayAabbMax,rootNode->m_aabbMinOrg,rootNode->m_aabbMaxOrg);
+ aabbOverlap = TestAabbAgainstAabb2(rayAabbMin, rayAabbMax, rootNode->m_aabbMinOrg, rootNode->m_aabbMaxOrg);
//perhaps profile if it is worth doing the aabbOverlap test first
#ifdef RAYAABB2
- ///careful with this check: need to check division by zero (above) and fix the unQuantize method
- ///thanks Joerg/hiker for the reproduction case!
- ///http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1858
- rayBoxOverlap = aabbOverlap ? btRayAabb2 (raySource, rayDirectionInverse, sign, bounds, param, 0.0f, lambda_max) : false;
+ ///careful with this check: need to check division by zero (above) and fix the unQuantize method
+ ///thanks Joerg/hiker for the reproduction case!
+ ///http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1858
+ rayBoxOverlap = aabbOverlap ? btRayAabb2(raySource, rayDirectionInverse, sign, bounds, param, 0.0f, lambda_max) : false;
#else
btVector3 normal;
- rayBoxOverlap = btRayAabb(raySource, rayTarget,bounds[0],bounds[1],param, normal);
+ rayBoxOverlap = btRayAabb(raySource, rayTarget, bounds[0], bounds[1], param, normal);
#endif
isLeafNode = rootNode->m_escapeIndex == -1;
-
+
//PCK: unsigned instead of bool
if (isLeafNode && (rayBoxOverlap != 0))
{
- nodeCallback->processNode(rootNode->m_subPart,rootNode->m_triangleIndex);
- }
-
+ nodeCallback->processNode(rootNode->m_subPart, rootNode->m_triangleIndex);
+ }
+
//PCK: unsigned instead of bool
if ((rayBoxOverlap != 0) || isLeafNode)
{
rootNode++;
curIndex++;
- } else
+ }
+ else
{
escapeIndex = rootNode->m_escapeIndex;
rootNode += escapeIndex;
@@ -553,15 +531,12 @@ void btQuantizedBvh::walkStacklessTreeAgainstRay(btNodeOverlapCallback* nodeCall
}
if (maxIterations < walkIterations)
maxIterations = walkIterations;
-
}
-
-
-void btQuantizedBvh::walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const
+void btQuantizedBvh::walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex, int endNodeIndex) const
{
btAssert(m_useQuantization);
-
+
int curIndex = startNodeIndex;
int walkIterations = 0;
int subTreeSize = endNodeIndex - startNodeIndex;
@@ -569,7 +544,7 @@ void btQuantizedBvh::walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback*
const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex];
int escapeIndex;
-
+
bool isLeafNode;
//PCK: unsigned instead of bool
unsigned boxBoxOverlap = 0;
@@ -578,14 +553,14 @@ void btQuantizedBvh::walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback*
btScalar lambda_max = 1.0;
#ifdef RAYAABB2
- btVector3 rayDirection = (rayTarget-raySource);
- rayDirection.normalize ();
- lambda_max = rayDirection.dot(rayTarget-raySource);
+ btVector3 rayDirection = (rayTarget - raySource);
+ rayDirection.normalize();
+ lambda_max = rayDirection.dot(rayTarget - raySource);
///what about division by zero? --> just set rayDirection[i] to 1.0
rayDirection[0] = rayDirection[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDirection[0];
rayDirection[1] = rayDirection[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDirection[1];
rayDirection[2] = rayDirection[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDirection[2];
- unsigned int sign[3] = { rayDirection[0] < 0.0, rayDirection[1] < 0.0, rayDirection[2] < 0.0};
+ unsigned int sign[3] = {rayDirection[0] < 0.0, rayDirection[1] < 0.0, rayDirection[2] < 0.0};
#endif
/* Quick pruning by quantized box */
@@ -600,37 +575,36 @@ void btQuantizedBvh::walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback*
unsigned short int quantizedQueryAabbMin[3];
unsigned short int quantizedQueryAabbMax[3];
- quantizeWithClamp(quantizedQueryAabbMin,rayAabbMin,0);
- quantizeWithClamp(quantizedQueryAabbMax,rayAabbMax,1);
+ quantizeWithClamp(quantizedQueryAabbMin, rayAabbMin, 0);
+ quantizeWithClamp(quantizedQueryAabbMax, rayAabbMax, 1);
while (curIndex < endNodeIndex)
{
-
//#define VISUALLY_ANALYZE_BVH 1
#ifdef VISUALLY_ANALYZE_BVH
//some code snippet to debugDraw aabb, to visually analyze bvh structure
static int drawPatch = 0;
//need some global access to a debugDrawer
extern btIDebugDraw* debugDrawerPtr;
- if (curIndex==drawPatch)
+ if (curIndex == drawPatch)
{
- btVector3 aabbMin,aabbMax;
+ btVector3 aabbMin, aabbMax;
aabbMin = unQuantize(rootNode->m_quantizedAabbMin);
aabbMax = unQuantize(rootNode->m_quantizedAabbMax);
- btVector3 color(1,0,0);
- debugDrawerPtr->drawAabb(aabbMin,aabbMax,color);
+ btVector3 color(1, 0, 0);
+ debugDrawerPtr->drawAabb(aabbMin, aabbMax, color);
}
-#endif//VISUALLY_ANALYZE_BVH
+#endif //VISUALLY_ANALYZE_BVH
//catch bugs in tree data
- btAssert (walkIterations < subTreeSize);
+ btAssert(walkIterations < subTreeSize);
walkIterations++;
//PCK: unsigned instead of bool
// only interested if this is closer than any previous hit
btScalar param = 1.0;
rayBoxOverlap = 0;
- boxBoxOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax);
+ boxBoxOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin, quantizedQueryAabbMax, rootNode->m_quantizedAabbMin, rootNode->m_quantizedAabbMax);
isLeafNode = rootNode->isLeafNode();
if (boxBoxOverlap)
{
@@ -655,24 +629,25 @@ void btQuantizedBvh::walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback*
///http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1858
//BT_PROFILE("btRayAabb2");
- rayBoxOverlap = btRayAabb2 (raySource, rayDirection, sign, bounds, param, 0.0f, lambda_max);
-
+ rayBoxOverlap = btRayAabb2(raySource, rayDirection, sign, bounds, param, 0.0f, lambda_max);
+
#else
- rayBoxOverlap = true;//btRayAabb(raySource, rayTarget, bounds[0], bounds[1], param, normal);
+ rayBoxOverlap = true; //btRayAabb(raySource, rayTarget, bounds[0], bounds[1], param, normal);
#endif
}
-
+
if (isLeafNode && rayBoxOverlap)
{
- nodeCallback->processNode(rootNode->getPartId(),rootNode->getTriangleIndex());
+ nodeCallback->processNode(rootNode->getPartId(), rootNode->getTriangleIndex());
}
-
+
//PCK: unsigned instead of bool
if ((rayBoxOverlap != 0) || isLeafNode)
{
rootNode++;
curIndex++;
- } else
+ }
+ else
{
escapeIndex = rootNode->getEscapeIndex();
rootNode += escapeIndex;
@@ -681,13 +656,12 @@ void btQuantizedBvh::walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback*
}
if (maxIterations < walkIterations)
maxIterations = walkIterations;
-
}
-void btQuantizedBvh::walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const
+void btQuantizedBvh::walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax, int startNodeIndex, int endNodeIndex) const
{
btAssert(m_useQuantization);
-
+
int curIndex = startNodeIndex;
int walkIterations = 0;
int subTreeSize = endNodeIndex - startNodeIndex;
@@ -695,49 +669,49 @@ void btQuantizedBvh::walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallb
const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex];
int escapeIndex;
-
+
bool isLeafNode;
//PCK: unsigned instead of bool
unsigned aabbOverlap;
while (curIndex < endNodeIndex)
{
-
//#define VISUALLY_ANALYZE_BVH 1
#ifdef VISUALLY_ANALYZE_BVH
//some code snippet to debugDraw aabb, to visually analyze bvh structure
static int drawPatch = 0;
//need some global access to a debugDrawer
extern btIDebugDraw* debugDrawerPtr;
- if (curIndex==drawPatch)
+ if (curIndex == drawPatch)
{
- btVector3 aabbMin,aabbMax;
+ btVector3 aabbMin, aabbMax;
aabbMin = unQuantize(rootNode->m_quantizedAabbMin);
aabbMax = unQuantize(rootNode->m_quantizedAabbMax);
- btVector3 color(1,0,0);
- debugDrawerPtr->drawAabb(aabbMin,aabbMax,color);
+ btVector3 color(1, 0, 0);
+ debugDrawerPtr->drawAabb(aabbMin, aabbMax, color);
}
-#endif//VISUALLY_ANALYZE_BVH
+#endif //VISUALLY_ANALYZE_BVH
//catch bugs in tree data
- btAssert (walkIterations < subTreeSize);
+ btAssert(walkIterations < subTreeSize);
walkIterations++;
//PCK: unsigned instead of bool
- aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax);
+ aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin, quantizedQueryAabbMax, rootNode->m_quantizedAabbMin, rootNode->m_quantizedAabbMax);
isLeafNode = rootNode->isLeafNode();
-
+
if (isLeafNode && aabbOverlap)
{
- nodeCallback->processNode(rootNode->getPartId(),rootNode->getTriangleIndex());
- }
-
+ nodeCallback->processNode(rootNode->getPartId(), rootNode->getTriangleIndex());
+ }
+
//PCK: unsigned instead of bool
if ((aabbOverlap != 0) || isLeafNode)
{
rootNode++;
curIndex++;
- } else
+ }
+ else
{
escapeIndex = rootNode->getEscapeIndex();
rootNode += escapeIndex;
@@ -746,40 +720,36 @@ void btQuantizedBvh::walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallb
}
if (maxIterations < walkIterations)
maxIterations = walkIterations;
-
}
//This traversal can be called from Playstation 3 SPU
-void btQuantizedBvh::walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const
+void btQuantizedBvh::walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax) const
{
btAssert(m_useQuantization);
int i;
-
- for (i=0;i<this->m_SubtreeHeaders.size();i++)
+ for (i = 0; i < this->m_SubtreeHeaders.size(); i++)
{
const btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
//PCK: unsigned instead of bool
- unsigned overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax);
+ unsigned overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin, quantizedQueryAabbMax, subtree.m_quantizedAabbMin, subtree.m_quantizedAabbMax);
if (overlap != 0)
{
- walkStacklessQuantizedTree(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax,
- subtree.m_rootNodeIndex,
- subtree.m_rootNodeIndex+subtree.m_subtreeSize);
+ walkStacklessQuantizedTree(nodeCallback, quantizedQueryAabbMin, quantizedQueryAabbMax,
+ subtree.m_rootNodeIndex,
+ subtree.m_rootNodeIndex + subtree.m_subtreeSize);
}
}
}
-
-void btQuantizedBvh::reportRayOverlappingNodex (btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const
+void btQuantizedBvh::reportRayOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const
{
- reportBoxCastOverlappingNodex(nodeCallback,raySource,rayTarget,btVector3(0,0,0),btVector3(0,0,0));
+ reportBoxCastOverlappingNodex(nodeCallback, raySource, rayTarget, btVector3(0, 0, 0), btVector3(0, 0, 0));
}
-
-void btQuantizedBvh::reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin,const btVector3& aabbMax) const
+void btQuantizedBvh::reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax) const
{
//always use stackless
@@ -803,31 +773,31 @@ void btQuantizedBvh::reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCa
reportAabbOverlappingNodex(nodeCallback,qaabbMin,qaabbMax);
}
*/
-
}
-
-void btQuantizedBvh::swapLeafNodes(int i,int splitIndex)
+void btQuantizedBvh::swapLeafNodes(int i, int splitIndex)
{
if (m_useQuantization)
{
- btQuantizedBvhNode tmp = m_quantizedLeafNodes[i];
- m_quantizedLeafNodes[i] = m_quantizedLeafNodes[splitIndex];
- m_quantizedLeafNodes[splitIndex] = tmp;
- } else
+ btQuantizedBvhNode tmp = m_quantizedLeafNodes[i];
+ m_quantizedLeafNodes[i] = m_quantizedLeafNodes[splitIndex];
+ m_quantizedLeafNodes[splitIndex] = tmp;
+ }
+ else
{
- btOptimizedBvhNode tmp = m_leafNodes[i];
- m_leafNodes[i] = m_leafNodes[splitIndex];
- m_leafNodes[splitIndex] = tmp;
+ btOptimizedBvhNode tmp = m_leafNodes[i];
+ m_leafNodes[i] = m_leafNodes[splitIndex];
+ m_leafNodes[splitIndex] = tmp;
}
}
-void btQuantizedBvh::assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex)
+void btQuantizedBvh::assignInternalNodeFromLeafNode(int internalNode, int leafNodeIndex)
{
if (m_useQuantization)
{
m_quantizedContiguousNodes[internalNode] = m_quantizedLeafNodes[leafNodeIndex];
- } else
+ }
+ else
{
m_contiguousNodes[internalNode] = m_leafNodes[leafNodeIndex];
}
@@ -844,11 +814,10 @@ static const unsigned BVH_ALIGNMENT_MASK = BVH_ALIGNMENT-1;
static const unsigned BVH_ALIGNMENT_BLOCKS = 2;
#endif
-
unsigned int btQuantizedBvh::getAlignmentSerializationPadding()
{
// I changed this to 0 since the extra padding is not needed or used.
- return 0;//BVH_ALIGNMENT_BLOCKS * BVH_ALIGNMENT;
+ return 0; //BVH_ALIGNMENT_BLOCKS * BVH_ALIGNMENT;
}
unsigned btQuantizedBvh::calculateSerializeBufferSize() const
@@ -862,12 +831,12 @@ unsigned btQuantizedBvh::calculateSerializeBufferSize() const
return baseSize + m_curNodeIndex * sizeof(btOptimizedBvhNode);
}
-bool btQuantizedBvh::serialize(void *o_alignedDataBuffer, unsigned /*i_dataBufferSize */, bool i_swapEndian) const
+bool btQuantizedBvh::serialize(void* o_alignedDataBuffer, unsigned /*i_dataBufferSize */, bool i_swapEndian) const
{
btAssert(m_subtreeHeaderCount == m_SubtreeHeaders.size());
m_subtreeHeaderCount = m_SubtreeHeaders.size();
-/* if (i_dataBufferSize < calculateSerializeBufferSize() || o_alignedDataBuffer == NULL || (((unsigned)o_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0))
+ /* if (i_dataBufferSize < calculateSerializeBufferSize() || o_alignedDataBuffer == NULL || (((unsigned)o_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0))
{
///check alignedment for buffer?
btAssert(0);
@@ -875,7 +844,7 @@ bool btQuantizedBvh::serialize(void *o_alignedDataBuffer, unsigned /*i_dataBuffe
}
*/
- btQuantizedBvh *targetBvh = (btQuantizedBvh *)o_alignedDataBuffer;
+ btQuantizedBvh* targetBvh = (btQuantizedBvh*)o_alignedDataBuffer;
// construct the class so the virtual function table, etc will be set up
// Also, m_leafNodes and m_quantizedLeafNodes will be initialized to default values by the constructor
@@ -885,10 +854,9 @@ bool btQuantizedBvh::serialize(void *o_alignedDataBuffer, unsigned /*i_dataBuffe
{
targetBvh->m_curNodeIndex = static_cast<int>(btSwapEndian(m_curNodeIndex));
-
- btSwapVector3Endian(m_bvhAabbMin,targetBvh->m_bvhAabbMin);
- btSwapVector3Endian(m_bvhAabbMax,targetBvh->m_bvhAabbMax);
- btSwapVector3Endian(m_bvhQuantization,targetBvh->m_bvhQuantization);
+ btSwapVector3Endian(m_bvhAabbMin, targetBvh->m_bvhAabbMin);
+ btSwapVector3Endian(m_bvhAabbMax, targetBvh->m_bvhAabbMax);
+ btSwapVector3Endian(m_bvhQuantization, targetBvh->m_bvhQuantization);
targetBvh->m_traversalMode = (btTraversalMode)btSwapEndian(m_traversalMode);
targetBvh->m_subtreeHeaderCount = static_cast<int>(btSwapEndian(m_subtreeHeaderCount));
@@ -905,12 +873,12 @@ bool btQuantizedBvh::serialize(void *o_alignedDataBuffer, unsigned /*i_dataBuffe
targetBvh->m_useQuantization = m_useQuantization;
- unsigned char *nodeData = (unsigned char *)targetBvh;
+ unsigned char* nodeData = (unsigned char*)targetBvh;
nodeData += sizeof(btQuantizedBvh);
-
- unsigned sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
+
+ unsigned sizeToAdd = 0; //(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
nodeData += sizeToAdd;
-
+
int nodeCount = m_curNodeIndex;
if (m_useQuantization)
@@ -936,7 +904,6 @@ bool btQuantizedBvh::serialize(void *o_alignedDataBuffer, unsigned /*i_dataBuffe
{
for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
{
-
targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0];
targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1];
targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2];
@@ -946,8 +913,6 @@ bool btQuantizedBvh::serialize(void *o_alignedDataBuffer, unsigned /*i_dataBuffe
targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2];
targetBvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex;
-
-
}
}
nodeData += sizeof(btQuantizedBvhNode) * nodeCount;
@@ -993,7 +958,7 @@ bool btQuantizedBvh::serialize(void *o_alignedDataBuffer, unsigned /*i_dataBuffe
targetBvh->m_contiguousNodes.initializeFromBuffer(NULL, 0, 0);
}
- sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
+ sizeToAdd = 0; //(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
nodeData += sizeToAdd;
// Now serialize the subtree headers
@@ -1048,14 +1013,13 @@ bool btQuantizedBvh::serialize(void *o_alignedDataBuffer, unsigned /*i_dataBuffe
return true;
}
-btQuantizedBvh *btQuantizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian)
+btQuantizedBvh* btQuantizedBvh::deSerializeInPlace(void* i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian)
{
-
- if (i_alignedDataBuffer == NULL)// || (((unsigned)i_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0))
+ if (i_alignedDataBuffer == NULL) // || (((unsigned)i_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0))
{
return NULL;
}
- btQuantizedBvh *bvh = (btQuantizedBvh *)i_alignedDataBuffer;
+ btQuantizedBvh* bvh = (btQuantizedBvh*)i_alignedDataBuffer;
if (i_swapEndian)
{
@@ -1077,12 +1041,12 @@ btQuantizedBvh *btQuantizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, un
return NULL;
}
- unsigned char *nodeData = (unsigned char *)bvh;
+ unsigned char* nodeData = (unsigned char*)bvh;
nodeData += sizeof(btQuantizedBvh);
-
- unsigned sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
+
+ unsigned sizeToAdd = 0; //(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
nodeData += sizeToAdd;
-
+
int nodeCount = bvh->m_curNodeIndex;
// Must call placement new to fill in virtual function table, etc, but we don't want to overwrite most data, so call a special version of the constructor
@@ -1120,7 +1084,7 @@ btQuantizedBvh *btQuantizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, un
{
btUnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg);
btUnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg);
-
+
bvh->m_contiguousNodes[nodeIndex].m_escapeIndex = static_cast<int>(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_escapeIndex));
bvh->m_contiguousNodes[nodeIndex].m_subPart = static_cast<int>(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_subPart));
bvh->m_contiguousNodes[nodeIndex].m_triangleIndex = static_cast<int>(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_triangleIndex));
@@ -1129,7 +1093,7 @@ btQuantizedBvh *btQuantizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, un
nodeData += sizeof(btOptimizedBvhNode) * nodeCount;
}
- sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
+ sizeToAdd = 0; //(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
nodeData += sizeToAdd;
// Now serialize the subtree headers
@@ -1155,13 +1119,11 @@ btQuantizedBvh *btQuantizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, un
}
// Constructor that prevents btVector3's default constructor from being called
-btQuantizedBvh::btQuantizedBvh(btQuantizedBvh &self, bool /* ownsMemory */) :
-m_bvhAabbMin(self.m_bvhAabbMin),
-m_bvhAabbMax(self.m_bvhAabbMax),
-m_bvhQuantization(self.m_bvhQuantization),
-m_bulletVersion(BT_BULLET_VERSION)
+btQuantizedBvh::btQuantizedBvh(btQuantizedBvh& self, bool /* ownsMemory */) : m_bvhAabbMin(self.m_bvhAabbMin),
+ m_bvhAabbMax(self.m_bvhAabbMax),
+ m_bvhQuantization(self.m_bvhQuantization),
+ m_bulletVersion(BT_BULLET_VERSION)
{
-
}
void btQuantizedBvh::deSerializeFloat(struct btQuantizedBvhFloatData& quantizedBvhFloatData)
@@ -1171,8 +1133,8 @@ void btQuantizedBvh::deSerializeFloat(struct btQuantizedBvhFloatData& quantizedB
m_bvhQuantization.deSerializeFloat(quantizedBvhFloatData.m_bvhQuantization);
m_curNodeIndex = quantizedBvhFloatData.m_curNodeIndex;
- m_useQuantization = quantizedBvhFloatData.m_useQuantization!=0;
-
+ m_useQuantization = quantizedBvhFloatData.m_useQuantization != 0;
+
{
int numElem = quantizedBvhFloatData.m_numContiguousLeafNodes;
m_contiguousNodes.resize(numElem);
@@ -1181,7 +1143,7 @@ void btQuantizedBvh::deSerializeFloat(struct btQuantizedBvhFloatData& quantizedB
{
btOptimizedBvhNodeFloatData* memPtr = quantizedBvhFloatData.m_contiguousNodesPtr;
- for (int i=0;i<numElem;i++,memPtr++)
+ for (int i = 0; i < numElem; i++, memPtr++)
{
m_contiguousNodes[i].m_aabbMaxOrg.deSerializeFloat(memPtr->m_aabbMaxOrg);
m_contiguousNodes[i].m_aabbMinOrg.deSerializeFloat(memPtr->m_aabbMinOrg);
@@ -1195,11 +1157,11 @@ void btQuantizedBvh::deSerializeFloat(struct btQuantizedBvhFloatData& quantizedB
{
int numElem = quantizedBvhFloatData.m_numQuantizedContiguousNodes;
m_quantizedContiguousNodes.resize(numElem);
-
+
if (numElem)
{
btQuantizedBvhNodeData* memPtr = quantizedBvhFloatData.m_quantizedContiguousNodesPtr;
- for (int i=0;i<numElem;i++,memPtr++)
+ for (int i = 0; i < numElem; i++, memPtr++)
{
m_quantizedContiguousNodes[i].m_escapeIndexOrTriangleIndex = memPtr->m_escapeIndexOrTriangleIndex;
m_quantizedContiguousNodes[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0];
@@ -1213,16 +1175,16 @@ void btQuantizedBvh::deSerializeFloat(struct btQuantizedBvhFloatData& quantizedB
}
m_traversalMode = btTraversalMode(quantizedBvhFloatData.m_traversalMode);
-
+
{
int numElem = quantizedBvhFloatData.m_numSubtreeHeaders;
m_SubtreeHeaders.resize(numElem);
if (numElem)
{
btBvhSubtreeInfoData* memPtr = quantizedBvhFloatData.m_subTreeInfoPtr;
- for (int i=0;i<numElem;i++,memPtr++)
+ for (int i = 0; i < numElem; i++, memPtr++)
{
- m_SubtreeHeaders[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0] ;
+ m_SubtreeHeaders[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0];
m_SubtreeHeaders[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
m_SubtreeHeaders[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
m_SubtreeHeaders[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
@@ -1242,8 +1204,8 @@ void btQuantizedBvh::deSerializeDouble(struct btQuantizedBvhDoubleData& quantize
m_bvhQuantization.deSerializeDouble(quantizedBvhDoubleData.m_bvhQuantization);
m_curNodeIndex = quantizedBvhDoubleData.m_curNodeIndex;
- m_useQuantization = quantizedBvhDoubleData.m_useQuantization!=0;
-
+ m_useQuantization = quantizedBvhDoubleData.m_useQuantization != 0;
+
{
int numElem = quantizedBvhDoubleData.m_numContiguousLeafNodes;
m_contiguousNodes.resize(numElem);
@@ -1252,7 +1214,7 @@ void btQuantizedBvh::deSerializeDouble(struct btQuantizedBvhDoubleData& quantize
{
btOptimizedBvhNodeDoubleData* memPtr = quantizedBvhDoubleData.m_contiguousNodesPtr;
- for (int i=0;i<numElem;i++,memPtr++)
+ for (int i = 0; i < numElem; i++, memPtr++)
{
m_contiguousNodes[i].m_aabbMaxOrg.deSerializeDouble(memPtr->m_aabbMaxOrg);
m_contiguousNodes[i].m_aabbMinOrg.deSerializeDouble(memPtr->m_aabbMinOrg);
@@ -1266,11 +1228,11 @@ void btQuantizedBvh::deSerializeDouble(struct btQuantizedBvhDoubleData& quantize
{
int numElem = quantizedBvhDoubleData.m_numQuantizedContiguousNodes;
m_quantizedContiguousNodes.resize(numElem);
-
+
if (numElem)
{
btQuantizedBvhNodeData* memPtr = quantizedBvhDoubleData.m_quantizedContiguousNodesPtr;
- for (int i=0;i<numElem;i++,memPtr++)
+ for (int i = 0; i < numElem; i++, memPtr++)
{
m_quantizedContiguousNodes[i].m_escapeIndexOrTriangleIndex = memPtr->m_escapeIndexOrTriangleIndex;
m_quantizedContiguousNodes[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0];
@@ -1284,16 +1246,16 @@ void btQuantizedBvh::deSerializeDouble(struct btQuantizedBvhDoubleData& quantize
}
m_traversalMode = btTraversalMode(quantizedBvhDoubleData.m_traversalMode);
-
+
{
int numElem = quantizedBvhDoubleData.m_numSubtreeHeaders;
m_SubtreeHeaders.resize(numElem);
if (numElem)
{
btBvhSubtreeInfoData* memPtr = quantizedBvhDoubleData.m_subTreeInfoPtr;
- for (int i=0;i<numElem;i++,memPtr++)
+ for (int i = 0; i < numElem; i++, memPtr++)
{
- m_SubtreeHeaders[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0] ;
+ m_SubtreeHeaders[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0];
m_SubtreeHeaders[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
m_SubtreeHeaders[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
m_SubtreeHeaders[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
@@ -1304,32 +1266,29 @@ void btQuantizedBvh::deSerializeDouble(struct btQuantizedBvhDoubleData& quantize
}
}
}
-
}
-
-
///fills the dataBuffer and returns the struct name (and 0 on failure)
-const char* btQuantizedBvh::serialize(void* dataBuffer, btSerializer* serializer) const
+const char* btQuantizedBvh::serialize(void* dataBuffer, btSerializer* serializer) const
{
btQuantizedBvhData* quantizedData = (btQuantizedBvhData*)dataBuffer;
-
+
m_bvhAabbMax.serialize(quantizedData->m_bvhAabbMax);
m_bvhAabbMin.serialize(quantizedData->m_bvhAabbMin);
m_bvhQuantization.serialize(quantizedData->m_bvhQuantization);
quantizedData->m_curNodeIndex = m_curNodeIndex;
quantizedData->m_useQuantization = m_useQuantization;
-
+
quantizedData->m_numContiguousLeafNodes = m_contiguousNodes.size();
- quantizedData->m_contiguousNodesPtr = (btOptimizedBvhNodeData*) (m_contiguousNodes.size() ? serializer->getUniquePointer((void*)&m_contiguousNodes[0]) : 0);
+ quantizedData->m_contiguousNodesPtr = (btOptimizedBvhNodeData*)(m_contiguousNodes.size() ? serializer->getUniquePointer((void*)&m_contiguousNodes[0]) : 0);
if (quantizedData->m_contiguousNodesPtr)
{
int sz = sizeof(btOptimizedBvhNodeData);
int numElem = m_contiguousNodes.size();
- btChunk* chunk = serializer->allocate(sz,numElem);
+ btChunk* chunk = serializer->allocate(sz, numElem);
btOptimizedBvhNodeData* memPtr = (btOptimizedBvhNodeData*)chunk->m_oldPtr;
- for (int i=0;i<numElem;i++,memPtr++)
+ for (int i = 0; i < numElem; i++, memPtr++)
{
m_contiguousNodes[i].m_aabbMaxOrg.serialize(memPtr->m_aabbMaxOrg);
m_contiguousNodes[i].m_aabbMinOrg.serialize(memPtr->m_aabbMinOrg);
@@ -1339,19 +1298,19 @@ const char* btQuantizedBvh::serialize(void* dataBuffer, btSerializer* serializer
// Fill padding with zeros to appease msan.
memset(memPtr->m_pad, 0, sizeof(memPtr->m_pad));
}
- serializer->finalizeChunk(chunk,"btOptimizedBvhNodeData",BT_ARRAY_CODE,(void*)&m_contiguousNodes[0]);
+ serializer->finalizeChunk(chunk, "btOptimizedBvhNodeData", BT_ARRAY_CODE, (void*)&m_contiguousNodes[0]);
}
quantizedData->m_numQuantizedContiguousNodes = m_quantizedContiguousNodes.size();
-// printf("quantizedData->m_numQuantizedContiguousNodes=%d\n",quantizedData->m_numQuantizedContiguousNodes);
- quantizedData->m_quantizedContiguousNodesPtr =(btQuantizedBvhNodeData*) (m_quantizedContiguousNodes.size() ? serializer->getUniquePointer((void*)&m_quantizedContiguousNodes[0]) : 0);
+ // printf("quantizedData->m_numQuantizedContiguousNodes=%d\n",quantizedData->m_numQuantizedContiguousNodes);
+ quantizedData->m_quantizedContiguousNodesPtr = (btQuantizedBvhNodeData*)(m_quantizedContiguousNodes.size() ? serializer->getUniquePointer((void*)&m_quantizedContiguousNodes[0]) : 0);
if (quantizedData->m_quantizedContiguousNodesPtr)
{
int sz = sizeof(btQuantizedBvhNodeData);
int numElem = m_quantizedContiguousNodes.size();
- btChunk* chunk = serializer->allocate(sz,numElem);
+ btChunk* chunk = serializer->allocate(sz, numElem);
btQuantizedBvhNodeData* memPtr = (btQuantizedBvhNodeData*)chunk->m_oldPtr;
- for (int i=0;i<numElem;i++,memPtr++)
+ for (int i = 0; i < numElem; i++, memPtr++)
{
memPtr->m_escapeIndexOrTriangleIndex = m_quantizedContiguousNodes[i].m_escapeIndexOrTriangleIndex;
memPtr->m_quantizedAabbMax[0] = m_quantizedContiguousNodes[i].m_quantizedAabbMax[0];
@@ -1361,20 +1320,20 @@ const char* btQuantizedBvh::serialize(void* dataBuffer, btSerializer* serializer
memPtr->m_quantizedAabbMin[1] = m_quantizedContiguousNodes[i].m_quantizedAabbMin[1];
memPtr->m_quantizedAabbMin[2] = m_quantizedContiguousNodes[i].m_quantizedAabbMin[2];
}
- serializer->finalizeChunk(chunk,"btQuantizedBvhNodeData",BT_ARRAY_CODE,(void*)&m_quantizedContiguousNodes[0]);
+ serializer->finalizeChunk(chunk, "btQuantizedBvhNodeData", BT_ARRAY_CODE, (void*)&m_quantizedContiguousNodes[0]);
}
quantizedData->m_traversalMode = int(m_traversalMode);
quantizedData->m_numSubtreeHeaders = m_SubtreeHeaders.size();
- quantizedData->m_subTreeInfoPtr = (btBvhSubtreeInfoData*) (m_SubtreeHeaders.size() ? serializer->getUniquePointer((void*)&m_SubtreeHeaders[0]) : 0);
+ quantizedData->m_subTreeInfoPtr = (btBvhSubtreeInfoData*)(m_SubtreeHeaders.size() ? serializer->getUniquePointer((void*)&m_SubtreeHeaders[0]) : 0);
if (quantizedData->m_subTreeInfoPtr)
{
int sz = sizeof(btBvhSubtreeInfoData);
int numElem = m_SubtreeHeaders.size();
- btChunk* chunk = serializer->allocate(sz,numElem);
+ btChunk* chunk = serializer->allocate(sz, numElem);
btBvhSubtreeInfoData* memPtr = (btBvhSubtreeInfoData*)chunk->m_oldPtr;
- for (int i=0;i<numElem;i++,memPtr++)
+ for (int i = 0; i < numElem; i++, memPtr++)
{
memPtr->m_quantizedAabbMax[0] = m_SubtreeHeaders[i].m_quantizedAabbMax[0];
memPtr->m_quantizedAabbMax[1] = m_SubtreeHeaders[i].m_quantizedAabbMax[1];
@@ -1386,12 +1345,7 @@ const char* btQuantizedBvh::serialize(void* dataBuffer, btSerializer* serializer
memPtr->m_rootNodeIndex = m_SubtreeHeaders[i].m_rootNodeIndex;
memPtr->m_subtreeSize = m_SubtreeHeaders[i].m_subtreeSize;
}
- serializer->finalizeChunk(chunk,"btBvhSubtreeInfoData",BT_ARRAY_CODE,(void*)&m_SubtreeHeaders[0]);
+ serializer->finalizeChunk(chunk, "btBvhSubtreeInfoData", BT_ARRAY_CODE, (void*)&m_SubtreeHeaders[0]);
}
return btQuantizedBvhDataName;
}
-
-
-
-
-
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.h b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.h
index 3dd5ac9bb6..1c47b9ccf2 100644
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.h
+++ b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.h
@@ -22,11 +22,11 @@ class btSerializer;
#ifdef DEBUG_CHECK_DEQUANTIZATION
#ifdef __SPU__
#define printf spu_printf
-#endif //__SPU__
+#endif //__SPU__
#include <stdio.h>
#include <stdlib.h>
-#endif //DEBUG_CHECK_DEQUANTIZATION
+#endif //DEBUG_CHECK_DEQUANTIZATION
#include "LinearMath/btVector3.h"
#include "LinearMath/btAlignedAllocator.h"
@@ -41,13 +41,10 @@ class btSerializer;
#define btQuantizedBvhDataName "btQuantizedBvhFloatData"
#endif
-
-
//http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vclrf__m128.asp
-
//Note: currently we have 16 bytes per quantized node
-#define MAX_SUBTREE_SIZE_IN_BYTES 2048
+#define MAX_SUBTREE_SIZE_IN_BYTES 2048
// 10 gives the potential for 1024 parts, with at most 2^21 (2097152) (minus one
// actually) triangles each (since the sign bit is reserved
@@ -55,15 +52,16 @@ class btSerializer;
///btQuantizedBvhNode is a compressed aabb node, 16 bytes.
///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).
-ATTRIBUTE_ALIGNED16 (struct) btQuantizedBvhNode
+ATTRIBUTE_ALIGNED16(struct)
+btQuantizedBvhNode
{
BT_DECLARE_ALIGNED_ALLOCATOR();
//12 bytes
- unsigned short int m_quantizedAabbMin[3];
- unsigned short int m_quantizedAabbMax[3];
+ unsigned short int m_quantizedAabbMin[3];
+ unsigned short int m_quantizedAabbMax[3];
//4 bytes
- int m_escapeIndexOrTriangleIndex;
+ int m_escapeIndexOrTriangleIndex;
bool isLeafNode() const
{
@@ -75,68 +73,67 @@ ATTRIBUTE_ALIGNED16 (struct) btQuantizedBvhNode
btAssert(!isLeafNode());
return -m_escapeIndexOrTriangleIndex;
}
- int getTriangleIndex() const
+ int getTriangleIndex() const
{
btAssert(isLeafNode());
- unsigned int x=0;
- unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);
+ unsigned int x = 0;
+ unsigned int y = (~(x & 0)) << (31 - MAX_NUM_PARTS_IN_BITS);
// Get only the lower bits where the triangle index is stored
- return (m_escapeIndexOrTriangleIndex&~(y));
+ return (m_escapeIndexOrTriangleIndex & ~(y));
}
- int getPartId() const
+ int getPartId() const
{
btAssert(isLeafNode());
// Get only the highest bits where the part index is stored
- return (m_escapeIndexOrTriangleIndex>>(31-MAX_NUM_PARTS_IN_BITS));
+ return (m_escapeIndexOrTriangleIndex >> (31 - MAX_NUM_PARTS_IN_BITS));
}
-}
-;
+};
/// btOptimizedBvhNode contains both internal and leaf node information.
/// Total node size is 44 bytes / node. You can use the compressed version of 16 bytes.
-ATTRIBUTE_ALIGNED16 (struct) btOptimizedBvhNode
+ATTRIBUTE_ALIGNED16(struct)
+btOptimizedBvhNode
{
BT_DECLARE_ALIGNED_ALLOCATOR();
//32 bytes
- btVector3 m_aabbMinOrg;
- btVector3 m_aabbMaxOrg;
+ btVector3 m_aabbMinOrg;
+ btVector3 m_aabbMaxOrg;
//4
- int m_escapeIndex;
+ int m_escapeIndex;
//8
//for child nodes
- int m_subPart;
- int m_triangleIndex;
+ int m_subPart;
+ int m_triangleIndex;
-//pad the size to 64 bytes
- char m_padding[20];
+ //pad the size to 64 bytes
+ char m_padding[20];
};
-
///btBvhSubtreeInfo provides info to gather a subtree of limited size
-ATTRIBUTE_ALIGNED16(class) btBvhSubtreeInfo
+ATTRIBUTE_ALIGNED16(class)
+btBvhSubtreeInfo
{
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
//12 bytes
- unsigned short int m_quantizedAabbMin[3];
- unsigned short int m_quantizedAabbMax[3];
+ unsigned short int m_quantizedAabbMin[3];
+ unsigned short int m_quantizedAabbMax[3];
//4 bytes, points to the root of the subtree
- int m_rootNodeIndex;
+ int m_rootNodeIndex;
//4 bytes
- int m_subtreeSize;
- int m_padding[3];
+ int m_subtreeSize;
+ int m_padding[3];
btBvhSubtreeInfo()
{
//memset(&m_padding[0], 0, sizeof(m_padding));
}
-
- void setAabbFromQuantizeNode(const btQuantizedBvhNode& quantizedNode)
+ void setAabbFromQuantizeNode(const btQuantizedBvhNode& quantizedNode)
{
m_quantizedAabbMin[0] = quantizedNode.m_quantizedAabbMin[0];
m_quantizedAabbMin[1] = quantizedNode.m_quantizedAabbMin[1];
@@ -145,14 +142,12 @@ public:
m_quantizedAabbMax[1] = quantizedNode.m_quantizedAabbMax[1];
m_quantizedAabbMax[2] = quantizedNode.m_quantizedAabbMax[2];
}
-}
-;
-
+};
class btNodeOverlapCallback
{
public:
- virtual ~btNodeOverlapCallback() {};
+ virtual ~btNodeOverlapCallback(){};
virtual void processNode(int subPart, int triangleIndex) = 0;
};
@@ -160,18 +155,16 @@ public:
#include "LinearMath/btAlignedAllocator.h"
#include "LinearMath/btAlignedObjectArray.h"
-
-
///for code readability:
-typedef btAlignedObjectArray<btOptimizedBvhNode> NodeArray;
-typedef btAlignedObjectArray<btQuantizedBvhNode> QuantizedNodeArray;
-typedef btAlignedObjectArray<btBvhSubtreeInfo> BvhSubtreeInfoArray;
-
+typedef btAlignedObjectArray<btOptimizedBvhNode> NodeArray;
+typedef btAlignedObjectArray<btQuantizedBvhNode> QuantizedNodeArray;
+typedef btAlignedObjectArray<btBvhSubtreeInfo> BvhSubtreeInfoArray;
///The btQuantizedBvh class stores an AABB tree that can be quickly traversed on CPU and Cell SPU.
///It is used by the btBvhTriangleMeshShape as midphase.
///It is recommended to use quantization for better performance and lower memory requirements.
-ATTRIBUTE_ALIGNED16(class) btQuantizedBvh
+ATTRIBUTE_ALIGNED16(class)
+btQuantizedBvh
{
public:
enum btTraversalMode
@@ -182,54 +175,47 @@ public:
};
protected:
+ btVector3 m_bvhAabbMin;
+ btVector3 m_bvhAabbMax;
+ btVector3 m_bvhQuantization;
+ int m_bulletVersion; //for serialization versioning. It could also be used to detect endianess.
- btVector3 m_bvhAabbMin;
- btVector3 m_bvhAabbMax;
- btVector3 m_bvhQuantization;
-
- int m_bulletVersion; //for serialization versioning. It could also be used to detect endianess.
-
- int m_curNodeIndex;
+ int m_curNodeIndex;
//quantization data
- bool m_useQuantization;
+ bool m_useQuantization;
+ NodeArray m_leafNodes;
+ NodeArray m_contiguousNodes;
+ QuantizedNodeArray m_quantizedLeafNodes;
+ QuantizedNodeArray m_quantizedContiguousNodes;
-
- NodeArray m_leafNodes;
- NodeArray m_contiguousNodes;
- QuantizedNodeArray m_quantizedLeafNodes;
- QuantizedNodeArray m_quantizedContiguousNodes;
-
- btTraversalMode m_traversalMode;
- BvhSubtreeInfoArray m_SubtreeHeaders;
+ btTraversalMode m_traversalMode;
+ BvhSubtreeInfoArray m_SubtreeHeaders;
//This is only used for serialization so we don't have to add serialization directly to btAlignedObjectArray
mutable int m_subtreeHeaderCount;
-
-
-
-
///two versions, one for quantized and normal nodes. This allows code-reuse while maintaining readability (no template/macro!)
///this might be refactored into a virtual, it is usually not calculated at run-time
- void setInternalNodeAabbMin(int nodeIndex, const btVector3& aabbMin)
+ void setInternalNodeAabbMin(int nodeIndex, const btVector3& aabbMin)
{
if (m_useQuantization)
{
- quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] ,aabbMin,0);
- } else
+ quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0], aabbMin, 0);
+ }
+ else
{
m_contiguousNodes[nodeIndex].m_aabbMinOrg = aabbMin;
-
}
}
- void setInternalNodeAabbMax(int nodeIndex,const btVector3& aabbMax)
+ void setInternalNodeAabbMax(int nodeIndex, const btVector3& aabbMax)
{
if (m_useQuantization)
{
- quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0],aabbMax,1);
- } else
+ quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0], aabbMax, 1);
+ }
+ else
{
m_contiguousNodes[nodeIndex].m_aabbMaxOrg = aabbMax;
}
@@ -243,115 +229,102 @@ protected:
}
//non-quantized
return m_leafNodes[nodeIndex].m_aabbMinOrg;
-
}
btVector3 getAabbMax(int nodeIndex) const
{
if (m_useQuantization)
{
return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMax[0]);
- }
+ }
//non-quantized
return m_leafNodes[nodeIndex].m_aabbMaxOrg;
-
}
-
- void setInternalNodeEscapeIndex(int nodeIndex, int escapeIndex)
+ void setInternalNodeEscapeIndex(int nodeIndex, int escapeIndex)
{
if (m_useQuantization)
{
m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = -escapeIndex;
- }
+ }
else
{
m_contiguousNodes[nodeIndex].m_escapeIndex = escapeIndex;
}
-
}
- void mergeInternalNodeAabb(int nodeIndex,const btVector3& newAabbMin,const btVector3& newAabbMax)
+ void mergeInternalNodeAabb(int nodeIndex, const btVector3& newAabbMin, const btVector3& newAabbMax)
{
if (m_useQuantization)
{
unsigned short int quantizedAabbMin[3];
unsigned short int quantizedAabbMax[3];
- quantize(quantizedAabbMin,newAabbMin,0);
- quantize(quantizedAabbMax,newAabbMax,1);
- for (int i=0;i<3;i++)
+ quantize(quantizedAabbMin, newAabbMin, 0);
+ quantize(quantizedAabbMax, newAabbMax, 1);
+ for (int i = 0; i < 3; i++)
{
if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] > quantizedAabbMin[i])
m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] = quantizedAabbMin[i];
if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] < quantizedAabbMax[i])
m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] = quantizedAabbMax[i];
-
}
- } else
+ }
+ else
{
//non-quantized
m_contiguousNodes[nodeIndex].m_aabbMinOrg.setMin(newAabbMin);
- m_contiguousNodes[nodeIndex].m_aabbMaxOrg.setMax(newAabbMax);
+ m_contiguousNodes[nodeIndex].m_aabbMaxOrg.setMax(newAabbMax);
}
}
- void swapLeafNodes(int firstIndex,int secondIndex);
+ void swapLeafNodes(int firstIndex, int secondIndex);
- void assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex);
+ void assignInternalNodeFromLeafNode(int internalNode, int leafNodeIndex);
protected:
+ void buildTree(int startIndex, int endIndex);
-
+ int calcSplittingAxis(int startIndex, int endIndex);
- void buildTree (int startIndex,int endIndex);
+ int sortAndCalcSplittingIndex(int startIndex, int endIndex, int splitAxis);
- int calcSplittingAxis(int startIndex,int endIndex);
+ void walkStacklessTree(btNodeOverlapCallback * nodeCallback, const btVector3& aabbMin, const btVector3& aabbMax) const;
- int sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis);
-
- void walkStacklessTree(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const;
-
- void walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const;
- void walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const;
- void walkStacklessTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const;
+ void walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback * nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex, int endNodeIndex) const;
+ void walkStacklessQuantizedTree(btNodeOverlapCallback * nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax, int startNodeIndex, int endNodeIndex) const;
+ void walkStacklessTreeAgainstRay(btNodeOverlapCallback * nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex, int endNodeIndex) const;
///tree traversal designed for small-memory processors like PS3 SPU
- void walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const;
+ void walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback * nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax) const;
///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal
- void walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const;
+ void walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode, btNodeOverlapCallback* nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax) const;
///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal
- void walkRecursiveQuantizedTreeAgainstQuantizedTree(const btQuantizedBvhNode* treeNodeA,const btQuantizedBvhNode* treeNodeB,btNodeOverlapCallback* nodeCallback) const;
-
+ void walkRecursiveQuantizedTreeAgainstQuantizedTree(const btQuantizedBvhNode* treeNodeA, const btQuantizedBvhNode* treeNodeB, btNodeOverlapCallback* nodeCallback) const;
-
-
- void updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex);
+ void updateSubtreeHeaders(int leftChildNodexIndex, int rightChildNodexIndex);
public:
-
BT_DECLARE_ALIGNED_ALLOCATOR();
btQuantizedBvh();
virtual ~btQuantizedBvh();
-
///***************************************** expert/internal use only *************************
- void setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin=btScalar(1.0));
- QuantizedNodeArray& getLeafNodeArray() { return m_quantizedLeafNodes; }
+ void setQuantizationValues(const btVector3& bvhAabbMin, const btVector3& bvhAabbMax, btScalar quantizationMargin = btScalar(1.0));
+ QuantizedNodeArray& getLeafNodeArray() { return m_quantizedLeafNodes; }
///buildInternal is expert use only: assumes that setQuantizationValues and LeafNodeArray are initialized
- void buildInternal();
+ void buildInternal();
///***************************************** expert/internal use only *************************
- void reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const;
- void reportRayOverlappingNodex (btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const;
- void reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin,const btVector3& aabbMax) const;
+ void reportAabbOverlappingNodex(btNodeOverlapCallback * nodeCallback, const btVector3& aabbMin, const btVector3& aabbMax) const;
+ void reportRayOverlappingNodex(btNodeOverlapCallback * nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const;
+ void reportBoxCastOverlappingNodex(btNodeOverlapCallback * nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax) const;
- SIMD_FORCE_INLINE void quantize(unsigned short* out, const btVector3& point,int isMax) const
+ SIMD_FORCE_INLINE void quantize(unsigned short* out, const btVector3& point, int isMax) const
{
-
btAssert(m_useQuantization);
btAssert(point.getX() <= m_bvhAabbMax.getX());
@@ -368,122 +341,114 @@ public:
///@todo: double-check this
if (isMax)
{
- out[0] = (unsigned short) (((unsigned short)(v.getX()+btScalar(1.)) | 1));
- out[1] = (unsigned short) (((unsigned short)(v.getY()+btScalar(1.)) | 1));
- out[2] = (unsigned short) (((unsigned short)(v.getZ()+btScalar(1.)) | 1));
- } else
+ out[0] = (unsigned short)(((unsigned short)(v.getX() + btScalar(1.)) | 1));
+ out[1] = (unsigned short)(((unsigned short)(v.getY() + btScalar(1.)) | 1));
+ out[2] = (unsigned short)(((unsigned short)(v.getZ() + btScalar(1.)) | 1));
+ }
+ else
{
- out[0] = (unsigned short) (((unsigned short)(v.getX()) & 0xfffe));
- out[1] = (unsigned short) (((unsigned short)(v.getY()) & 0xfffe));
- out[2] = (unsigned short) (((unsigned short)(v.getZ()) & 0xfffe));
+ out[0] = (unsigned short)(((unsigned short)(v.getX()) & 0xfffe));
+ out[1] = (unsigned short)(((unsigned short)(v.getY()) & 0xfffe));
+ out[2] = (unsigned short)(((unsigned short)(v.getZ()) & 0xfffe));
}
-
#ifdef DEBUG_CHECK_DEQUANTIZATION
btVector3 newPoint = unQuantize(out);
if (isMax)
{
if (newPoint.getX() < point.getX())
{
- printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX());
+ printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n", newPoint.getX() - point.getX(), newPoint.getX(), point.getX());
}
if (newPoint.getY() < point.getY())
{
- printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY());
+ printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n", newPoint.getY() - point.getY(), newPoint.getY(), point.getY());
}
if (newPoint.getZ() < point.getZ())
{
-
- printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ());
+ printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n", newPoint.getZ() - point.getZ(), newPoint.getZ(), point.getZ());
}
- } else
+ }
+ else
{
if (newPoint.getX() > point.getX())
{
- printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX());
+ printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n", newPoint.getX() - point.getX(), newPoint.getX(), point.getX());
}
if (newPoint.getY() > point.getY())
{
- printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY());
+ printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n", newPoint.getY() - point.getY(), newPoint.getY(), point.getY());
}
if (newPoint.getZ() > point.getZ())
{
- printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ());
+ printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n", newPoint.getZ() - point.getZ(), newPoint.getZ(), point.getZ());
}
}
-#endif //DEBUG_CHECK_DEQUANTIZATION
-
+#endif //DEBUG_CHECK_DEQUANTIZATION
}
-
- SIMD_FORCE_INLINE void quantizeWithClamp(unsigned short* out, const btVector3& point2,int isMax) const
+ SIMD_FORCE_INLINE void quantizeWithClamp(unsigned short* out, const btVector3& point2, int isMax) const
{
-
btAssert(m_useQuantization);
btVector3 clampedPoint(point2);
clampedPoint.setMax(m_bvhAabbMin);
clampedPoint.setMin(m_bvhAabbMax);
- quantize(out,clampedPoint,isMax);
-
+ quantize(out, clampedPoint, isMax);
}
-
- SIMD_FORCE_INLINE btVector3 unQuantize(const unsigned short* vecIn) const
+
+ SIMD_FORCE_INLINE btVector3 unQuantize(const unsigned short* vecIn) const
{
- btVector3 vecOut;
- vecOut.setValue(
+ btVector3 vecOut;
+ vecOut.setValue(
(btScalar)(vecIn[0]) / (m_bvhQuantization.getX()),
(btScalar)(vecIn[1]) / (m_bvhQuantization.getY()),
(btScalar)(vecIn[2]) / (m_bvhQuantization.getZ()));
- vecOut += m_bvhAabbMin;
- return vecOut;
+ vecOut += m_bvhAabbMin;
+ return vecOut;
}
///setTraversalMode let's you choose between stackless, recursive or stackless cache friendly tree traversal. Note this is only implemented for quantized trees.
- void setTraversalMode(btTraversalMode traversalMode)
+ void setTraversalMode(btTraversalMode traversalMode)
{
m_traversalMode = traversalMode;
}
-
- SIMD_FORCE_INLINE QuantizedNodeArray& getQuantizedNodeArray()
- {
- return m_quantizedContiguousNodes;
+ SIMD_FORCE_INLINE QuantizedNodeArray& getQuantizedNodeArray()
+ {
+ return m_quantizedContiguousNodes;
}
-
- SIMD_FORCE_INLINE BvhSubtreeInfoArray& getSubtreeInfoArray()
+ SIMD_FORCE_INLINE BvhSubtreeInfoArray& getSubtreeInfoArray()
{
return m_SubtreeHeaders;
}
-////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////
/////Calculate space needed to store BVH for serialization
unsigned calculateSerializeBufferSize() const;
/// Data buffer MUST be 16 byte aligned
- virtual bool serialize(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const;
+ virtual bool serialize(void* o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const;
///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
- static btQuantizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
+ static btQuantizedBvh* deSerializeInPlace(void* i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
static unsigned int getAlignmentSerializationPadding();
-//////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////
-
- virtual int calculateSerializeBufferSizeNew() const;
+ virtual int calculateSerializeBufferSizeNew() const;
///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-
- virtual void deSerializeFloat(struct btQuantizedBvhFloatData& quantizedBvhFloatData);
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
- virtual void deSerializeDouble(struct btQuantizedBvhDoubleData& quantizedBvhDoubleData);
+ virtual void deSerializeFloat(struct btQuantizedBvhFloatData & quantizedBvhFloatData);
+ virtual void deSerializeDouble(struct btQuantizedBvhDoubleData & quantizedBvhDoubleData);
-////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////
SIMD_FORCE_INLINE bool isQuantized()
{
@@ -494,38 +459,37 @@ private:
// Special "copy" constructor that allows for in-place deserialization
// Prevents btVector3's default constructor from being called, but doesn't inialize much else
// ownsMemory should most likely be false if deserializing, and if you are not, don't call this (it also changes the function signature, which we need)
- btQuantizedBvh(btQuantizedBvh &other, bool ownsMemory);
-
-}
-;
-
+ btQuantizedBvh(btQuantizedBvh & other, bool ownsMemory);
+};
-struct btBvhSubtreeInfoData
+// clang-format off
+// parser needs * with the name
+struct btBvhSubtreeInfoData
{
- int m_rootNodeIndex;
- int m_subtreeSize;
+ int m_rootNodeIndex;
+ int m_subtreeSize;
unsigned short m_quantizedAabbMin[3];
unsigned short m_quantizedAabbMax[3];
};
struct btOptimizedBvhNodeFloatData
{
- btVector3FloatData m_aabbMinOrg;
- btVector3FloatData m_aabbMaxOrg;
- int m_escapeIndex;
- int m_subPart;
- int m_triangleIndex;
+ btVector3FloatData m_aabbMinOrg;
+ btVector3FloatData m_aabbMaxOrg;
+ int m_escapeIndex;
+ int m_subPart;
+ int m_triangleIndex;
char m_pad[4];
};
struct btOptimizedBvhNodeDoubleData
{
- btVector3DoubleData m_aabbMinOrg;
- btVector3DoubleData m_aabbMaxOrg;
- int m_escapeIndex;
- int m_subPart;
- int m_triangleIndex;
- char m_pad[4];
+ btVector3DoubleData m_aabbMinOrg;
+ btVector3DoubleData m_aabbMaxOrg;
+ int m_escapeIndex;
+ int m_subPart;
+ int m_triangleIndex;
+ char m_pad[4];
};
@@ -569,13 +533,11 @@ struct btQuantizedBvhDoubleData
int m_numSubtreeHeaders;
btBvhSubtreeInfoData *m_subTreeInfoPtr;
};
+// clang-format on
-
-SIMD_FORCE_INLINE int btQuantizedBvh::calculateSerializeBufferSizeNew() const
+SIMD_FORCE_INLINE int btQuantizedBvh::calculateSerializeBufferSizeNew() const
{
return sizeof(btQuantizedBvhData);
}
-
-
-#endif //BT_QUANTIZED_BVH_H
+#endif //BT_QUANTIZED_BVH_H
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp
index 5f89f960e8..166cf771fe 100644
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp
+++ b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp
@@ -24,50 +24,45 @@ subject to the following restrictions:
#include <new>
-void btSimpleBroadphase::validate()
+void btSimpleBroadphase::validate()
{
- for (int i=0;i<m_numHandles;i++)
+ for (int i = 0; i < m_numHandles; i++)
{
- for (int j=i+1;j<m_numHandles;j++)
+ for (int j = i + 1; j < m_numHandles; j++)
{
btAssert(&m_pHandles[i] != &m_pHandles[j]);
}
}
-
}
btSimpleBroadphase::btSimpleBroadphase(int maxProxies, btOverlappingPairCache* overlappingPairCache)
- :m_pairCache(overlappingPairCache),
- m_ownsPairCache(false),
- m_invalidPair(0)
+ : m_pairCache(overlappingPairCache),
+ m_ownsPairCache(false),
+ m_invalidPair(0)
{
-
if (!overlappingPairCache)
{
- void* mem = btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16);
- m_pairCache = new (mem)btHashedOverlappingPairCache();
+ void* mem = btAlignedAlloc(sizeof(btHashedOverlappingPairCache), 16);
+ m_pairCache = new (mem) btHashedOverlappingPairCache();
m_ownsPairCache = true;
}
// allocate handles buffer and put all handles on free list
- m_pHandlesRawPtr = btAlignedAlloc(sizeof(btSimpleBroadphaseProxy)*maxProxies,16);
- m_pHandles = new(m_pHandlesRawPtr) btSimpleBroadphaseProxy[maxProxies];
+ m_pHandlesRawPtr = btAlignedAlloc(sizeof(btSimpleBroadphaseProxy) * maxProxies, 16);
+ m_pHandles = new (m_pHandlesRawPtr) btSimpleBroadphaseProxy[maxProxies];
m_maxHandles = maxProxies;
m_numHandles = 0;
m_firstFreeHandle = 0;
m_LastHandleIndex = -1;
-
{
for (int i = m_firstFreeHandle; i < maxProxies; i++)
{
m_pHandles[i].SetNextFree(i + 1);
- m_pHandles[i].m_uniqueId = i+2;//any UID will do, we just avoid too trivial values (0,1) for debugging purposes
+ m_pHandles[i].m_uniqueId = i + 2; //any UID will do, we just avoid too trivial values (0,1) for debugging purposes
}
m_pHandles[maxProxies - 1].SetNextFree(0);
-
}
-
}
btSimpleBroadphase::~btSimpleBroadphase()
@@ -81,26 +76,25 @@ btSimpleBroadphase::~btSimpleBroadphase()
}
}
-
-btBroadphaseProxy* btSimpleBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr , int collisionFilterGroup, int collisionFilterMask, btDispatcher* /*dispatcher*/)
+btBroadphaseProxy* btSimpleBroadphase::createProxy(const btVector3& aabbMin, const btVector3& aabbMax, int shapeType, void* userPtr, int collisionFilterGroup, int collisionFilterMask, btDispatcher* /*dispatcher*/)
{
if (m_numHandles >= m_maxHandles)
{
btAssert(0);
- return 0; //should never happen, but don't let the game crash ;-)
+ return 0; //should never happen, but don't let the game crash ;-)
}
- btAssert(aabbMin[0]<= aabbMax[0] && aabbMin[1]<= aabbMax[1] && aabbMin[2]<= aabbMax[2]);
+ btAssert(aabbMin[0] <= aabbMax[0] && aabbMin[1] <= aabbMax[1] && aabbMin[2] <= aabbMax[2]);
int newHandleIndex = allocHandle();
- btSimpleBroadphaseProxy* proxy = new (&m_pHandles[newHandleIndex])btSimpleBroadphaseProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask);
+ btSimpleBroadphaseProxy* proxy = new (&m_pHandles[newHandleIndex]) btSimpleBroadphaseProxy(aabbMin, aabbMax, shapeType, userPtr, collisionFilterGroup, collisionFilterMask);
return proxy;
}
-class RemovingOverlapCallback : public btOverlapCallback
+class RemovingOverlapCallback : public btOverlapCallback
{
protected:
- virtual bool processOverlap(btBroadphasePair& pair)
+ virtual bool processOverlap(btBroadphasePair& pair)
{
(void)pair;
btAssert(0);
@@ -110,12 +104,13 @@ protected:
class RemovePairContainingProxy
{
+ btBroadphaseProxy* m_targetProxy;
- btBroadphaseProxy* m_targetProxy;
- public:
+public:
virtual ~RemovePairContainingProxy()
{
}
+
protected:
virtual bool processOverlap(btBroadphasePair& pair)
{
@@ -126,38 +121,36 @@ protected:
};
};
-void btSimpleBroadphase::destroyProxy(btBroadphaseProxy* proxyOrg,btDispatcher* dispatcher)
+void btSimpleBroadphase::destroyProxy(btBroadphaseProxy* proxyOrg, btDispatcher* dispatcher)
{
-
- btSimpleBroadphaseProxy* proxy0 = static_cast<btSimpleBroadphaseProxy*>(proxyOrg);
- freeHandle(proxy0);
+ btSimpleBroadphaseProxy* proxy0 = static_cast<btSimpleBroadphaseProxy*>(proxyOrg);
+ freeHandle(proxy0);
- m_pairCache->removeOverlappingPairsContainingProxy(proxyOrg,dispatcher);
+ m_pairCache->removeOverlappingPairsContainingProxy(proxyOrg, dispatcher);
- //validate();
-
+ //validate();
}
-void btSimpleBroadphase::getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const
+void btSimpleBroadphase::getAabb(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const
{
const btSimpleBroadphaseProxy* sbp = getSimpleProxyFromProxy(proxy);
aabbMin = sbp->m_aabbMin;
aabbMax = sbp->m_aabbMax;
}
-void btSimpleBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* /*dispatcher*/)
+void btSimpleBroadphase::setAabb(btBroadphaseProxy* proxy, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* /*dispatcher*/)
{
btSimpleBroadphaseProxy* sbp = getSimpleProxyFromProxy(proxy);
sbp->m_aabbMin = aabbMin;
sbp->m_aabbMax = aabbMax;
}
-void btSimpleBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin,const btVector3& aabbMax)
+void btSimpleBroadphase::rayTest(const btVector3& rayFrom, const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin, const btVector3& aabbMax)
{
- for (int i=0; i <= m_LastHandleIndex; i++)
+ for (int i = 0; i <= m_LastHandleIndex; i++)
{
btSimpleBroadphaseProxy* proxy = &m_pHandles[i];
- if(!proxy->m_clientObject)
+ if (!proxy->m_clientObject)
{
continue;
}
@@ -165,69 +158,59 @@ void btSimpleBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo
}
}
-
-void btSimpleBroadphase::aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback)
+void btSimpleBroadphase::aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback)
{
- for (int i=0; i <= m_LastHandleIndex; i++)
+ for (int i = 0; i <= m_LastHandleIndex; i++)
{
btSimpleBroadphaseProxy* proxy = &m_pHandles[i];
- if(!proxy->m_clientObject)
+ if (!proxy->m_clientObject)
{
continue;
}
- if (TestAabbAgainstAabb2(aabbMin,aabbMax,proxy->m_aabbMin,proxy->m_aabbMax))
+ if (TestAabbAgainstAabb2(aabbMin, aabbMax, proxy->m_aabbMin, proxy->m_aabbMax))
{
callback.process(proxy);
}
}
}
-
-
-
-
-
-
-bool btSimpleBroadphase::aabbOverlap(btSimpleBroadphaseProxy* proxy0,btSimpleBroadphaseProxy* proxy1)
+bool btSimpleBroadphase::aabbOverlap(btSimpleBroadphaseProxy* proxy0, btSimpleBroadphaseProxy* proxy1)
{
- return proxy0->m_aabbMin[0] <= proxy1->m_aabbMax[0] && proxy1->m_aabbMin[0] <= proxy0->m_aabbMax[0] &&
+ return proxy0->m_aabbMin[0] <= proxy1->m_aabbMax[0] && proxy1->m_aabbMin[0] <= proxy0->m_aabbMax[0] &&
proxy0->m_aabbMin[1] <= proxy1->m_aabbMax[1] && proxy1->m_aabbMin[1] <= proxy0->m_aabbMax[1] &&
proxy0->m_aabbMin[2] <= proxy1->m_aabbMax[2] && proxy1->m_aabbMin[2] <= proxy0->m_aabbMax[2];
-
}
-
-
//then remove non-overlapping ones
class CheckOverlapCallback : public btOverlapCallback
{
public:
virtual bool processOverlap(btBroadphasePair& pair)
{
- return (!btSimpleBroadphase::aabbOverlap(static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy0),static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy1)));
+ return (!btSimpleBroadphase::aabbOverlap(static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy0), static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy1)));
}
};
-void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
+void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
{
//first check for new overlapping pairs
- int i,j;
+ int i, j;
if (m_numHandles >= 0)
{
int new_largest_index = -1;
- for (i=0; i <= m_LastHandleIndex; i++)
+ for (i = 0; i <= m_LastHandleIndex; i++)
{
btSimpleBroadphaseProxy* proxy0 = &m_pHandles[i];
- if(!proxy0->m_clientObject)
+ if (!proxy0->m_clientObject)
{
continue;
}
new_largest_index = i;
- for (j=i+1; j <= m_LastHandleIndex; j++)
+ for (j = i + 1; j <= m_LastHandleIndex; j++)
{
btSimpleBroadphaseProxy* proxy1 = &m_pHandles[j];
btAssert(proxy0 != proxy1);
- if(!proxy1->m_clientObject)
+ if (!proxy1->m_clientObject)
{
continue;
}
@@ -235,19 +218,20 @@ void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0);
btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1);
- if (aabbOverlap(p0,p1))
+ if (aabbOverlap(p0, p1))
{
- if ( !m_pairCache->findPair(proxy0,proxy1))
+ if (!m_pairCache->findPair(proxy0, proxy1))
{
- m_pairCache->addOverlappingPair(proxy0,proxy1);
+ m_pairCache->addOverlappingPair(proxy0, proxy1);
}
- } else
+ }
+ else
{
if (!m_pairCache->hasDeferredRemoval())
{
- if ( m_pairCache->findPair(proxy0,proxy1))
+ if (m_pairCache->findPair(proxy0, proxy1))
{
- m_pairCache->removeOverlappingPair(proxy0,proxy1,dispatcher);
+ m_pairCache->removeOverlappingPair(proxy0, proxy1, dispatcher);
}
}
}
@@ -258,8 +242,7 @@ void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
if (m_ownsPairCache && m_pairCache->hasDeferredRemoval())
{
-
- btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray();
+ btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray();
//perform a sort, to find duplicates and to sort 'invalid' pairs to the end
overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
@@ -267,16 +250,13 @@ void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
m_invalidPair = 0;
-
btBroadphasePair previousPair;
previousPair.m_pProxy0 = 0;
previousPair.m_pProxy1 = 0;
previousPair.m_algorithm = 0;
-
- for (i=0;i<overlappingPairArray.size();i++)
+ for (i = 0; i < overlappingPairArray.size(); i++)
{
-
btBroadphasePair& pair = overlappingPairArray[i];
bool isDuplicate = (pair == previousPair);
@@ -287,16 +267,18 @@ void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
if (!isDuplicate)
{
- bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1);
+ bool hasOverlap = testAabbOverlap(pair.m_pProxy0, pair.m_pProxy1);
if (hasOverlap)
{
- needsRemoval = false;//callback->processOverlap(pair);
- } else
+ needsRemoval = false; //callback->processOverlap(pair);
+ }
+ else
{
needsRemoval = true;
}
- } else
+ }
+ else
{
//remove duplicate
needsRemoval = true;
@@ -306,7 +288,7 @@ void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
if (needsRemoval)
{
- m_pairCache->cleanOverlappingPair(pair,dispatcher);
+ m_pairCache->cleanOverlappingPair(pair, dispatcher);
// m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
// m_overlappingPairArray.pop_back();
@@ -314,7 +296,6 @@ void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
pair.m_pProxy1 = 0;
m_invalidPair++;
}
-
}
///if you don't like to skip the invalid pairs in the array, execute following code:
@@ -326,21 +307,19 @@ void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
m_invalidPair = 0;
-#endif//CLEAN_INVALID_PAIRS
-
+#endif //CLEAN_INVALID_PAIRS
}
}
}
-
-bool btSimpleBroadphase::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+bool btSimpleBroadphase::testAabbOverlap(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
{
btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0);
btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1);
- return aabbOverlap(p0,p1);
+ return aabbOverlap(p0, p1);
}
-void btSimpleBroadphase::resetPool(btDispatcher* dispatcher)
+void btSimpleBroadphase::resetPool(btDispatcher* dispatcher)
{
//not yet
}
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h
index d7a18e400a..3e02fdc003 100644
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h
+++ b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h
@@ -16,57 +16,47 @@ subject to the following restrictions:
#ifndef BT_SIMPLE_BROADPHASE_H
#define BT_SIMPLE_BROADPHASE_H
-
#include "btOverlappingPairCache.h"
-
struct btSimpleBroadphaseProxy : public btBroadphaseProxy
{
- int m_nextFree;
-
-// int m_handleId;
+ int m_nextFree;
-
- btSimpleBroadphaseProxy() {};
+ // int m_handleId;
- btSimpleBroadphaseProxy(const btVector3& minpt,const btVector3& maxpt,int shapeType,void* userPtr, int collisionFilterGroup, int collisionFilterMask)
- :btBroadphaseProxy(minpt,maxpt,userPtr,collisionFilterGroup,collisionFilterMask)
+ btSimpleBroadphaseProxy(){};
+
+ btSimpleBroadphaseProxy(const btVector3& minpt, const btVector3& maxpt, int shapeType, void* userPtr, int collisionFilterGroup, int collisionFilterMask)
+ : btBroadphaseProxy(minpt, maxpt, userPtr, collisionFilterGroup, collisionFilterMask)
{
(void)shapeType;
}
-
-
- SIMD_FORCE_INLINE void SetNextFree(int next) {m_nextFree = next;}
- SIMD_FORCE_INLINE int GetNextFree() const {return m_nextFree;}
-
-
-
+ SIMD_FORCE_INLINE void SetNextFree(int next) { m_nextFree = next; }
+ SIMD_FORCE_INLINE int GetNextFree() const { return m_nextFree; }
};
///The SimpleBroadphase is just a unit-test for btAxisSweep3, bt32BitAxisSweep3, or btDbvtBroadphase, so use those classes instead.
///It is a brute force aabb culling broadphase based on O(n^2) aabb checks
class btSimpleBroadphase : public btBroadphaseInterface
{
-
protected:
+ int m_numHandles; // number of active handles
+ int m_maxHandles; // max number of handles
+ int m_LastHandleIndex;
- int m_numHandles; // number of active handles
- int m_maxHandles; // max number of handles
- int m_LastHandleIndex;
-
- btSimpleBroadphaseProxy* m_pHandles; // handles pool
+ btSimpleBroadphaseProxy* m_pHandles; // handles pool
void* m_pHandlesRawPtr;
- int m_firstFreeHandle; // free handles list
-
+ int m_firstFreeHandle; // free handles list
+
int allocHandle()
{
btAssert(m_numHandles < m_maxHandles);
int freeHandle = m_firstFreeHandle;
m_firstFreeHandle = m_pHandles[freeHandle].GetNextFree();
m_numHandles++;
- if(freeHandle > m_LastHandleIndex)
+ if (freeHandle > m_LastHandleIndex)
{
m_LastHandleIndex = freeHandle;
}
@@ -75,9 +65,9 @@ protected:
void freeHandle(btSimpleBroadphaseProxy* proxy)
{
- int handle = int(proxy-m_pHandles);
+ int handle = int(proxy - m_pHandles);
btAssert(handle >= 0 && handle < m_maxHandles);
- if(handle == m_LastHandleIndex)
+ if (handle == m_LastHandleIndex)
{
m_LastHandleIndex--;
}
@@ -89,20 +79,18 @@ protected:
m_numHandles--;
}
- btOverlappingPairCache* m_pairCache;
- bool m_ownsPairCache;
+ btOverlappingPairCache* m_pairCache;
+ bool m_ownsPairCache;
- int m_invalidPair;
+ int m_invalidPair;
-
-
- inline btSimpleBroadphaseProxy* getSimpleProxyFromProxy(btBroadphaseProxy* proxy)
+ inline btSimpleBroadphaseProxy* getSimpleProxyFromProxy(btBroadphaseProxy* proxy)
{
btSimpleBroadphaseProxy* proxy0 = static_cast<btSimpleBroadphaseProxy*>(proxy);
return proxy0;
}
- inline const btSimpleBroadphaseProxy* getSimpleProxyFromProxy(btBroadphaseProxy* proxy) const
+ inline const btSimpleBroadphaseProxy* getSimpleProxyFromProxy(btBroadphaseProxy* proxy) const
{
const btSimpleBroadphaseProxy* proxy0 = static_cast<const btSimpleBroadphaseProxy*>(proxy);
return proxy0;
@@ -111,61 +99,50 @@ protected:
///reset broadphase internal structures, to ensure determinism/reproducability
virtual void resetPool(btDispatcher* dispatcher);
-
- void validate();
+ void validate();
protected:
-
-
-
-
public:
- btSimpleBroadphase(int maxProxies=16384,btOverlappingPairCache* overlappingPairCache=0);
+ btSimpleBroadphase(int maxProxies = 16384, btOverlappingPairCache* overlappingPairCache = 0);
virtual ~btSimpleBroadphase();
+ static bool aabbOverlap(btSimpleBroadphaseProxy* proxy0, btSimpleBroadphaseProxy* proxy1);
- static bool aabbOverlap(btSimpleBroadphaseProxy* proxy0,btSimpleBroadphaseProxy* proxy1);
-
+ virtual btBroadphaseProxy* createProxy(const btVector3& aabbMin, const btVector3& aabbMax, int shapeType, void* userPtr, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher);
- virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr , int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher);
+ virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
- virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
+ virtual void destroyProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher);
+ virtual void setAabb(btBroadphaseProxy* proxy, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* dispatcher);
+ virtual void getAabb(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const;
- virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
- virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher);
- virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
+ virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin = btVector3(0, 0, 0), const btVector3& aabbMax = btVector3(0, 0, 0));
+ virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback);
- virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0),const btVector3& aabbMax=btVector3(0,0,0));
- virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback);
-
- btOverlappingPairCache* getOverlappingPairCache()
+ btOverlappingPairCache* getOverlappingPairCache()
{
return m_pairCache;
}
- const btOverlappingPairCache* getOverlappingPairCache() const
+ const btOverlappingPairCache* getOverlappingPairCache() const
{
return m_pairCache;
}
- bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
-
+ bool testAabbOverlap(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1);
///getAabb returns the axis aligned bounding box in the 'global' coordinate frame
///will add some transform later
- virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const
+ virtual void getBroadphaseAabb(btVector3& aabbMin, btVector3& aabbMax) const
{
- aabbMin.setValue(-BT_LARGE_FLOAT,-BT_LARGE_FLOAT,-BT_LARGE_FLOAT);
- aabbMax.setValue(BT_LARGE_FLOAT,BT_LARGE_FLOAT,BT_LARGE_FLOAT);
+ aabbMin.setValue(-BT_LARGE_FLOAT, -BT_LARGE_FLOAT, -BT_LARGE_FLOAT);
+ aabbMax.setValue(BT_LARGE_FLOAT, BT_LARGE_FLOAT, BT_LARGE_FLOAT);
}
- virtual void printStats()
+ virtual void printStats()
{
-// printf("btSimpleBroadphase.h\n");
-// printf("numHandles = %d, maxHandles = %d\n",m_numHandles,m_maxHandles);
+ // printf("btSimpleBroadphase.h\n");
+ // printf("numHandles = %d, maxHandles = %d\n",m_numHandles,m_maxHandles);
}
};
-
-
-#endif //BT_SIMPLE_BROADPHASE_H
-
+#endif //BT_SIMPLE_BROADPHASE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp
index e5bac8438e..7647f67360 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp
@@ -18,94 +18,95 @@ subject to the following restrictions:
#include "BulletCollision/CollisionShapes/btTriangleShape.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h"
-
-SphereTriangleDetector::SphereTriangleDetector(btSphereShape* sphere,btTriangleShape* triangle,btScalar contactBreakingThreshold)
-:m_sphere(sphere),
-m_triangle(triangle),
-m_contactBreakingThreshold(contactBreakingThreshold)
+SphereTriangleDetector::SphereTriangleDetector(btSphereShape* sphere, btTriangleShape* triangle, btScalar contactBreakingThreshold)
+ : m_sphere(sphere),
+ m_triangle(triangle),
+ m_contactBreakingThreshold(contactBreakingThreshold)
{
-
}
-void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults)
+void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input, Result& output, class btIDebugDraw* debugDraw, bool swapResults)
{
-
(void)debugDraw;
const btTransform& transformA = input.m_transformA;
const btTransform& transformB = input.m_transformB;
- btVector3 point,normal;
+ btVector3 point, normal;
btScalar timeOfImpact = btScalar(1.);
btScalar depth = btScalar(0.);
-// output.m_distance = btScalar(BT_LARGE_FLOAT);
+ // output.m_distance = btScalar(BT_LARGE_FLOAT);
//move sphere into triangle space
- btTransform sphereInTr = transformB.inverseTimes(transformA);
+ btTransform sphereInTr = transformB.inverseTimes(transformA);
- if (collide(sphereInTr.getOrigin(),point,normal,depth,timeOfImpact,m_contactBreakingThreshold))
+ if (collide(sphereInTr.getOrigin(), point, normal, depth, timeOfImpact, m_contactBreakingThreshold))
{
if (swapResults)
{
- btVector3 normalOnB = transformB.getBasis()*normal;
+ btVector3 normalOnB = transformB.getBasis() * normal;
btVector3 normalOnA = -normalOnB;
- btVector3 pointOnA = transformB*point+normalOnB*depth;
- output.addContactPoint(normalOnA,pointOnA,depth);
- } else
+ btVector3 pointOnA = transformB * point + normalOnB * depth;
+ output.addContactPoint(normalOnA, pointOnA, depth);
+ }
+ else
{
- output.addContactPoint(transformB.getBasis()*normal,transformB*point,depth);
+ output.addContactPoint(transformB.getBasis() * normal, transformB * point, depth);
}
}
-
}
-
-
// See also geometrictools.com
// Basic idea: D = |p - (lo + t0*lv)| where t0 = lv . (p - lo) / lv . lv
-btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to,const btVector3 &p, btVector3 &nearest);
+btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to, const btVector3& p, btVector3& nearest);
-btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to,const btVector3 &p, btVector3 &nearest) {
+btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to, const btVector3& p, btVector3& nearest)
+{
btVector3 diff = p - from;
btVector3 v = to - from;
btScalar t = v.dot(diff);
-
- if (t > 0) {
+
+ if (t > 0)
+ {
btScalar dotVV = v.dot(v);
- if (t < dotVV) {
+ if (t < dotVV)
+ {
t /= dotVV;
- diff -= t*v;
- } else {
+ diff -= t * v;
+ }
+ else
+ {
t = 1;
diff -= v;
}
- } else
+ }
+ else
t = 0;
- nearest = from + t*v;
- return diff.dot(diff);
+ nearest = from + t * v;
+ return diff.dot(diff);
}
-bool SphereTriangleDetector::facecontains(const btVector3 &p,const btVector3* vertices,btVector3& normal) {
+bool SphereTriangleDetector::facecontains(const btVector3& p, const btVector3* vertices, btVector3& normal)
+{
btVector3 lp(p);
btVector3 lnormal(normal);
-
+
return pointInTriangle(vertices, lnormal, &lp);
}
-bool SphereTriangleDetector::collide(const btVector3& sphereCenter,btVector3 &point, btVector3& resultNormal, btScalar& depth, btScalar &timeOfImpact, btScalar contactBreakingThreshold)
+bool SphereTriangleDetector::collide(const btVector3& sphereCenter, btVector3& point, btVector3& resultNormal, btScalar& depth, btScalar& timeOfImpact, btScalar contactBreakingThreshold)
{
-
const btVector3* vertices = &m_triangle->getVertexPtr(0);
-
+
btScalar radius = m_sphere->getRadius();
btScalar radiusWithThreshold = radius + contactBreakingThreshold;
- btVector3 normal = (vertices[1]-vertices[0]).cross(vertices[2]-vertices[0]);
+ btVector3 normal = (vertices[1] - vertices[0]).cross(vertices[2] - vertices[0]);
btScalar l2 = normal.length2();
bool hasContact = false;
btVector3 contactPoint;
- if (l2 >= SIMD_EPSILON*SIMD_EPSILON)
+ if (l2 >= SIMD_EPSILON * SIMD_EPSILON)
{
normal /= btSqrt(l2);
@@ -120,54 +121,59 @@ bool SphereTriangleDetector::collide(const btVector3& sphereCenter,btVector3 &po
}
bool isInsideContactPlane = distanceFromPlane < radiusWithThreshold;
-
+
// Check for contact / intersection
-
- if (isInsideContactPlane) {
- if (facecontains(sphereCenter, vertices, normal)) {
+
+ if (isInsideContactPlane)
+ {
+ if (facecontains(sphereCenter, vertices, normal))
+ {
// Inside the contact wedge - touches a point on the shell plane
hasContact = true;
- contactPoint = sphereCenter - normal*distanceFromPlane;
+ contactPoint = sphereCenter - normal * distanceFromPlane;
}
- else {
+ else
+ {
// Could be inside one of the contact capsules
- btScalar contactCapsuleRadiusSqr = radiusWithThreshold*radiusWithThreshold;
+ btScalar contactCapsuleRadiusSqr = radiusWithThreshold * radiusWithThreshold;
btScalar minDistSqr = contactCapsuleRadiusSqr;
btVector3 nearestOnEdge;
- for (int i = 0; i < m_triangle->getNumEdges(); i++) {
-
+ for (int i = 0; i < m_triangle->getNumEdges(); i++)
+ {
btVector3 pa;
btVector3 pb;
m_triangle->getEdge(i, pa, pb);
btScalar distanceSqr = SegmentSqrDistance(pa, pb, sphereCenter, nearestOnEdge);
- if (distanceSqr < minDistSqr) {
+ if (distanceSqr < minDistSqr)
+ {
// Yep, we're inside a capsule, and record the capsule with smallest distance
minDistSqr = distanceSqr;
hasContact = true;
contactPoint = nearestOnEdge;
}
-
}
}
}
}
- if (hasContact) {
+ if (hasContact)
+ {
btVector3 contactToCentre = sphereCenter - contactPoint;
btScalar distanceSqr = contactToCentre.length2();
- if (distanceSqr < radiusWithThreshold*radiusWithThreshold)
+ if (distanceSqr < radiusWithThreshold * radiusWithThreshold)
{
- if (distanceSqr>SIMD_EPSILON)
+ if (distanceSqr > SIMD_EPSILON)
{
btScalar distance = btSqrt(distanceSqr);
resultNormal = contactToCentre;
resultNormal.normalize();
point = contactPoint;
- depth = -(radius-distance);
- } else
+ depth = -(radius - distance);
+ }
+ else
{
resultNormal = normal;
point = contactPoint;
@@ -176,36 +182,34 @@ bool SphereTriangleDetector::collide(const btVector3& sphereCenter,btVector3 &po
return true;
}
}
-
+
return false;
}
-
-bool SphereTriangleDetector::pointInTriangle(const btVector3 vertices[], const btVector3 &normal, btVector3 *p )
+bool SphereTriangleDetector::pointInTriangle(const btVector3 vertices[], const btVector3& normal, btVector3* p)
{
const btVector3* p1 = &vertices[0];
const btVector3* p2 = &vertices[1];
const btVector3* p3 = &vertices[2];
- btVector3 edge1( *p2 - *p1 );
- btVector3 edge2( *p3 - *p2 );
- btVector3 edge3( *p1 - *p3 );
+ btVector3 edge1(*p2 - *p1);
+ btVector3 edge2(*p3 - *p2);
+ btVector3 edge3(*p1 - *p3);
+
+ btVector3 p1_to_p(*p - *p1);
+ btVector3 p2_to_p(*p - *p2);
+ btVector3 p3_to_p(*p - *p3);
- btVector3 p1_to_p( *p - *p1 );
- btVector3 p2_to_p( *p - *p2 );
- btVector3 p3_to_p( *p - *p3 );
+ btVector3 edge1_normal(edge1.cross(normal));
+ btVector3 edge2_normal(edge2.cross(normal));
+ btVector3 edge3_normal(edge3.cross(normal));
- btVector3 edge1_normal( edge1.cross(normal));
- btVector3 edge2_normal( edge2.cross(normal));
- btVector3 edge3_normal( edge3.cross(normal));
-
btScalar r1, r2, r3;
- r1 = edge1_normal.dot( p1_to_p );
- r2 = edge2_normal.dot( p2_to_p );
- r3 = edge3_normal.dot( p3_to_p );
- if ( ( r1 > 0 && r2 > 0 && r3 > 0 ) ||
- ( r1 <= 0 && r2 <= 0 && r3 <= 0 ) )
+ r1 = edge1_normal.dot(p1_to_p);
+ r2 = edge2_normal.dot(p2_to_p);
+ r3 = edge3_normal.dot(p3_to_p);
+ if ((r1 > 0 && r2 > 0 && r3 > 0) ||
+ (r1 <= 0 && r2 <= 0 && r3 <= 0))
return true;
return false;
-
}
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/SphereTriangleDetector.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/SphereTriangleDetector.h
index 22953af43f..d47e47530d 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/SphereTriangleDetector.h
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/SphereTriangleDetector.h
@@ -18,34 +18,26 @@ subject to the following restrictions:
#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
-
-
class btSphereShape;
class btTriangleShape;
-
-
/// sphere-triangle to match the btDiscreteCollisionDetectorInterface
struct SphereTriangleDetector : public btDiscreteCollisionDetectorInterface
{
- virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false);
+ virtual void getClosestPoints(const ClosestPointInput& input, Result& output, class btIDebugDraw* debugDraw, bool swapResults = false);
- SphereTriangleDetector(btSphereShape* sphere,btTriangleShape* triangle, btScalar contactBreakingThreshold);
+ SphereTriangleDetector(btSphereShape* sphere, btTriangleShape* triangle, btScalar contactBreakingThreshold);
- virtual ~SphereTriangleDetector() {};
+ virtual ~SphereTriangleDetector(){};
- bool collide(const btVector3& sphereCenter,btVector3 &point, btVector3& resultNormal, btScalar& depth, btScalar &timeOfImpact, btScalar contactBreakingThreshold);
+ bool collide(const btVector3& sphereCenter, btVector3& point, btVector3& resultNormal, btScalar& depth, btScalar& timeOfImpact, btScalar contactBreakingThreshold);
private:
-
-
- bool pointInTriangle(const btVector3 vertices[], const btVector3 &normal, btVector3 *p );
- bool facecontains(const btVector3 &p,const btVector3* vertices,btVector3& normal);
+ bool pointInTriangle(const btVector3 vertices[], const btVector3& normal, btVector3* p);
+ bool facecontains(const btVector3& p, const btVector3* vertices, btVector3& normal);
btSphereShape* m_sphere;
btTriangleShape* m_triangle;
- btScalar m_contactBreakingThreshold;
-
+ btScalar m_contactBreakingThreshold;
};
-#endif //BT_SPHERE_TRIANGLE_DETECTOR_H
-
+#endif //BT_SPHERE_TRIANGLE_DETECTOR_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp
index 57f1464935..ac5de45d27 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp
@@ -17,31 +17,31 @@ subject to the following restrictions:
#include "btCollisionDispatcher.h"
#include "btCollisionObject.h"
-btActivatingCollisionAlgorithm::btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci)
-:btCollisionAlgorithm(ci)
+btActivatingCollisionAlgorithm::btActivatingCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
+ : btCollisionAlgorithm(ci)
//,
//m_colObj0(0),
//m_colObj1(0)
{
}
-btActivatingCollisionAlgorithm::btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* ,const btCollisionObjectWrapper* )
-:btCollisionAlgorithm(ci)
+btActivatingCollisionAlgorithm::btActivatingCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper*, const btCollisionObjectWrapper*)
+ : btCollisionAlgorithm(ci)
//,
//m_colObj0(0),
//m_colObj1(0)
{
-// if (ci.m_dispatcher1->needsCollision(colObj0,colObj1))
-// {
-// m_colObj0 = colObj0;
-// m_colObj1 = colObj1;
-//
-// m_colObj0->activate();
-// m_colObj1->activate();
-// }
+ // if (ci.m_dispatcher1->needsCollision(colObj0,colObj1))
+ // {
+ // m_colObj0 = colObj0;
+ // m_colObj1 = colObj1;
+ //
+ // m_colObj0->activate();
+ // m_colObj1->activate();
+ // }
}
btActivatingCollisionAlgorithm::~btActivatingCollisionAlgorithm()
{
-// m_colObj0->activate();
-// m_colObj1->activate();
+ // m_colObj0->activate();
+ // m_colObj1->activate();
}
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h
index 0e19f1ea35..862060571b 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h
@@ -21,17 +21,15 @@ subject to the following restrictions:
///This class is not enabled yet (work-in-progress) to more aggressively activate objects.
class btActivatingCollisionAlgorithm : public btCollisionAlgorithm
{
-// btCollisionObject* m_colObj0;
-// btCollisionObject* m_colObj1;
+ // btCollisionObject* m_colObj0;
+ // btCollisionObject* m_colObj1;
protected:
+ btActivatingCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci);
- btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci);
-
- btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
+ btActivatingCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap);
public:
virtual ~btActivatingCollisionAlgorithm();
-
};
-#endif //__BT_ACTIVATING_COLLISION_ALGORITHM_H
+#endif //__BT_ACTIVATING_COLLISION_ALGORITHM_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp
index cabbb0bf6a..6873a95d90 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp
@@ -26,61 +26,55 @@ subject to the following restrictions:
#define USE_PERSISTENT_CONTACTS 1
-btBox2dBox2dCollisionAlgorithm::btBox2dBox2dCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* obj0Wrap,const btCollisionObjectWrapper* obj1Wrap)
-: btActivatingCollisionAlgorithm(ci,obj0Wrap,obj1Wrap),
-m_ownManifold(false),
-m_manifoldPtr(mf)
+btBox2dBox2dCollisionAlgorithm::btBox2dBox2dCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* obj0Wrap, const btCollisionObjectWrapper* obj1Wrap)
+ : btActivatingCollisionAlgorithm(ci, obj0Wrap, obj1Wrap),
+ m_ownManifold(false),
+ m_manifoldPtr(mf)
{
- if (!m_manifoldPtr && m_dispatcher->needsCollision(obj0Wrap->getCollisionObject(),obj1Wrap->getCollisionObject()))
+ if (!m_manifoldPtr && m_dispatcher->needsCollision(obj0Wrap->getCollisionObject(), obj1Wrap->getCollisionObject()))
{
- m_manifoldPtr = m_dispatcher->getNewManifold(obj0Wrap->getCollisionObject(),obj1Wrap->getCollisionObject());
+ m_manifoldPtr = m_dispatcher->getNewManifold(obj0Wrap->getCollisionObject(), obj1Wrap->getCollisionObject());
m_ownManifold = true;
}
}
btBox2dBox2dCollisionAlgorithm::~btBox2dBox2dCollisionAlgorithm()
{
-
if (m_ownManifold)
{
if (m_manifoldPtr)
m_dispatcher->releaseManifold(m_manifoldPtr);
}
-
}
-
-void b2CollidePolygons(btManifoldResult* manifold, const btBox2dShape* polyA, const btTransform& xfA, const btBox2dShape* polyB, const btTransform& xfB);
+void b2CollidePolygons(btManifoldResult* manifold, const btBox2dShape* polyA, const btTransform& xfA, const btBox2dShape* polyB, const btTransform& xfB);
//#include <stdio.h>
-void btBox2dBox2dCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+void btBox2dBox2dCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
{
if (!m_manifoldPtr)
return;
-
const btBox2dShape* box0 = (const btBox2dShape*)body0Wrap->getCollisionShape();
const btBox2dShape* box1 = (const btBox2dShape*)body1Wrap->getCollisionShape();
resultOut->setPersistentManifold(m_manifoldPtr);
- b2CollidePolygons(resultOut,box0,body0Wrap->getWorldTransform(),box1,body1Wrap->getWorldTransform());
+ b2CollidePolygons(resultOut, box0, body0Wrap->getWorldTransform(), box1, body1Wrap->getWorldTransform());
// refreshContactPoints is only necessary when using persistent contact points. otherwise all points are newly added
if (m_ownManifold)
{
resultOut->refreshContactPoints();
}
-
}
-btScalar btBox2dBox2dCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/,btCollisionObject* /*body1*/,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/)
+btScalar btBox2dBox2dCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/, btCollisionObject* /*body1*/, const btDispatcherInfo& /*dispatchInfo*/, btManifoldResult* /*resultOut*/)
{
//not yet
return 1.f;
}
-
struct ClipVertex
{
btVector3 v;
@@ -89,16 +83,16 @@ struct ClipVertex
//b2ContactID id;
};
-#define b2Dot(a,b) (a).dot(b)
-#define b2Mul(a,b) (a)*(b)
-#define b2MulT(a,b) (a).transpose()*(b)
-#define b2Cross(a,b) (a).cross(b)
-#define btCrossS(a,s) btVector3(s * a.getY(), -s * a.getX(),0.f)
+#define b2Dot(a, b) (a).dot(b)
+#define b2Mul(a, b) (a) * (b)
+#define b2MulT(a, b) (a).transpose() * (b)
+#define b2Cross(a, b) (a).cross(b)
+#define btCrossS(a, s) btVector3(s* a.getY(), -s* a.getX(), 0.f)
-int b2_maxManifoldPoints =2;
+int b2_maxManifoldPoints = 2;
static int ClipSegmentToLine(ClipVertex vOut[2], ClipVertex vIn[2],
- const btVector3& normal, btScalar offset)
+ const btVector3& normal, btScalar offset)
{
// Start with no output points
int numOut = 0;
@@ -133,7 +127,7 @@ static int ClipSegmentToLine(ClipVertex vOut[2], ClipVertex vIn[2],
// Find the separation between poly1 and poly2 for a give edge normal on poly1.
static btScalar EdgeSeparation(const btBox2dShape* poly1, const btTransform& xf1, int edge1,
- const btBox2dShape* poly2, const btTransform& xf2)
+ const btBox2dShape* poly2, const btTransform& xf2)
{
const btVector3* vertices1 = poly1->getVertices();
const btVector3* normals1 = poly1->getNormals();
@@ -151,8 +145,8 @@ static btScalar EdgeSeparation(const btBox2dShape* poly1, const btTransform& xf1
int index = 0;
btScalar minDot = BT_LARGE_FLOAT;
- if( count2 > 0 )
- index = (int) normal1.minDot( vertices2, count2, minDot);
+ if (count2 > 0)
+ index = (int)normal1.minDot(vertices2, count2, minDot);
btVector3 v1 = b2Mul(xf1, vertices1[edge1]);
btVector3 v2 = b2Mul(xf2, vertices2[index]);
@@ -162,8 +156,8 @@ static btScalar EdgeSeparation(const btBox2dShape* poly1, const btTransform& xf1
// Find the max separation between poly1 and poly2 using edge normals from poly1.
static btScalar FindMaxSeparation(int* edgeIndex,
- const btBox2dShape* poly1, const btTransform& xf1,
- const btBox2dShape* poly2, const btTransform& xf2)
+ const btBox2dShape* poly1, const btTransform& xf1,
+ const btBox2dShape* poly2, const btTransform& xf2)
{
int count1 = poly1->getVertexCount();
const btVector3* normals1 = poly1->getNormals();
@@ -174,9 +168,9 @@ static btScalar FindMaxSeparation(int* edgeIndex,
// Find edge normal on poly1 that has the largest projection onto d.
int edge = 0;
- btScalar maxDot;
- if( count1 > 0 )
- edge = (int) dLocal1.maxDot( normals1, count1, maxDot);
+ btScalar maxDot;
+ if (count1 > 0)
+ edge = (int)dLocal1.maxDot(normals1, count1, maxDot);
// Get the separation for the edge normal.
btScalar s = EdgeSeparation(poly1, xf1, edge, poly2, xf2);
@@ -224,7 +218,7 @@ static btScalar FindMaxSeparation(int* edgeIndex,
}
// Perform a local search for the best edge normal.
- for ( ; ; )
+ for (;;)
{
if (increment == -1)
edge = bestEdge - 1 >= 0 ? bestEdge - 1 : count1 - 1;
@@ -285,14 +279,14 @@ static void FindIncidentEdge(ClipVertex c[2],
int i2 = i1 + 1 < count2 ? i1 + 1 : 0;
c[0].v = b2Mul(xf2, vertices2[i1]);
-// c[0].id.features.referenceEdge = (unsigned char)edge1;
-// c[0].id.features.incidentEdge = (unsigned char)i1;
-// c[0].id.features.incidentVertex = 0;
+ // c[0].id.features.referenceEdge = (unsigned char)edge1;
+ // c[0].id.features.incidentEdge = (unsigned char)i1;
+ // c[0].id.features.incidentVertex = 0;
c[1].v = b2Mul(xf2, vertices2[i2]);
-// c[1].id.features.referenceEdge = (unsigned char)edge1;
-// c[1].id.features.incidentEdge = (unsigned char)i2;
-// c[1].id.features.incidentVertex = 1;
+ // c[1].id.features.referenceEdge = (unsigned char)edge1;
+ // c[1].id.features.incidentEdge = (unsigned char)i2;
+ // c[1].id.features.incidentVertex = 1;
}
// Find edge normal of max separation on A - return if separating axis is found
@@ -303,10 +297,9 @@ static void FindIncidentEdge(ClipVertex c[2],
// The normal points from 1 to 2
void b2CollidePolygons(btManifoldResult* manifold,
- const btBox2dShape* polyA, const btTransform& xfA,
- const btBox2dShape* polyB, const btTransform& xfB)
+ const btBox2dShape* polyA, const btTransform& xfA,
+ const btBox2dShape* polyB, const btTransform& xfB)
{
-
int edgeA = 0;
btScalar separationA = FindMaxSeparation(&edgeA, polyA, xfA, polyB, xfB);
if (separationA > 0.0f)
@@ -317,10 +310,10 @@ void b2CollidePolygons(btManifoldResult* manifold,
if (separationB > 0.0f)
return;
- const btBox2dShape* poly1; // reference poly
- const btBox2dShape* poly2; // incident poly
+ const btBox2dShape* poly1; // reference poly
+ const btBox2dShape* poly2; // incident poly
btTransform xf1, xf2;
- int edge1; // reference edge
+ int edge1; // reference edge
unsigned char flip;
const btScalar k_relativeTol = 0.98f;
const btScalar k_absoluteTol = 0.001f;
@@ -352,14 +345,13 @@ void b2CollidePolygons(btManifoldResult* manifold,
const btVector3* vertices1 = poly1->getVertices();
btVector3 v11 = vertices1[edge1];
- btVector3 v12 = edge1 + 1 < count1 ? vertices1[edge1+1] : vertices1[0];
+ btVector3 v12 = edge1 + 1 < count1 ? vertices1[edge1 + 1] : vertices1[0];
//btVector3 dv = v12 - v11;
btVector3 sideNormal = b2Mul(xf1.getBasis(), v12 - v11);
sideNormal.normalize();
btVector3 frontNormal = btCrossS(sideNormal, 1.0f);
-
-
+
v11 = b2Mul(xf1, v11);
v12 = b2Mul(xf1, v12);
@@ -369,13 +361,12 @@ void b2CollidePolygons(btManifoldResult* manifold,
// Clip incident edge against extruded edge1 side edges.
ClipVertex clipPoints1[2];
- clipPoints1[0].v.setValue(0,0,0);
- clipPoints1[1].v.setValue(0,0,0);
+ clipPoints1[0].v.setValue(0, 0, 0);
+ clipPoints1[1].v.setValue(0, 0, 0);
ClipVertex clipPoints2[2];
- clipPoints2[0].v.setValue(0,0,0);
- clipPoints2[1].v.setValue(0,0,0);
-
+ clipPoints2[0].v.setValue(0, 0, 0);
+ clipPoints2[1].v.setValue(0, 0, 0);
int np;
@@ -386,7 +377,7 @@ void b2CollidePolygons(btManifoldResult* manifold,
return;
// Clip to negative box side 1
- np = ClipSegmentToLine(clipPoints2, clipPoints1, sideNormal, sideOffset2);
+ np = ClipSegmentToLine(clipPoints2, clipPoints1, sideNormal, sideOffset2);
if (np < 2)
{
@@ -403,19 +394,18 @@ void b2CollidePolygons(btManifoldResult* manifold,
if (separation <= 0.0f)
{
-
//b2ManifoldPoint* cp = manifold->points + pointCount;
//btScalar separation = separation;
//cp->localPoint1 = b2MulT(xfA, clipPoints2[i].v);
//cp->localPoint2 = b2MulT(xfB, clipPoints2[i].v);
- manifold->addContactPoint(-manifoldNormal,clipPoints2[i].v,separation);
+ manifold->addContactPoint(-manifoldNormal, clipPoints2[i].v, separation);
-// cp->id = clipPoints2[i].id;
-// cp->id.features.flip = flip;
+ // cp->id = clipPoints2[i].id;
+ // cp->id.features.flip = flip;
++pointCount;
}
}
-// manifold->pointCount = pointCount;}
+ // manifold->pointCount = pointCount;}
}
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h
index 6ea6e89bda..3b66d1fd0b 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h
@@ -26,22 +26,22 @@ class btPersistentManifold;
///box-box collision detection
class btBox2dBox2dCollisionAlgorithm : public btActivatingCollisionAlgorithm
{
- bool m_ownManifold;
- btPersistentManifold* m_manifoldPtr;
-
+ bool m_ownManifold;
+ btPersistentManifold* m_manifoldPtr;
+
public:
btBox2dBox2dCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
: btActivatingCollisionAlgorithm(ci) {}
- virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
- virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
- btBox2dBox2dCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
+ btBox2dBox2dCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap);
virtual ~btBox2dBox2dCollisionAlgorithm();
- virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr && m_ownManifold)
{
@@ -49,18 +49,15 @@ public:
}
}
-
- struct CreateFunc :public btCollisionAlgorithmCreateFunc
+ struct CreateFunc : public btCollisionAlgorithmCreateFunc
{
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
{
int bbsize = sizeof(btBox2dBox2dCollisionAlgorithm);
void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize);
- return new(ptr) btBox2dBox2dCollisionAlgorithm(0,ci,body0Wrap,body1Wrap);
+ return new (ptr) btBox2dBox2dCollisionAlgorithm(0, ci, body0Wrap, body1Wrap);
}
};
-
};
-#endif //BT_BOX_2D_BOX_2D__COLLISION_ALGORITHM_H
-
+#endif //BT_BOX_2D_BOX_2D__COLLISION_ALGORITHM_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp
index ac68968f59..7a391e059a 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp
@@ -21,14 +21,14 @@ subject to the following restrictions:
#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
#define USE_PERSISTENT_CONTACTS 1
-btBoxBoxCollisionAlgorithm::btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
-: btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap),
-m_ownManifold(false),
-m_manifoldPtr(mf)
+btBoxBoxCollisionAlgorithm::btBoxBoxCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
+ : btActivatingCollisionAlgorithm(ci, body0Wrap, body1Wrap),
+ m_ownManifold(false),
+ m_manifoldPtr(mf)
{
- if (!m_manifoldPtr && m_dispatcher->needsCollision(body0Wrap->getCollisionObject(),body1Wrap->getCollisionObject()))
+ if (!m_manifoldPtr && m_dispatcher->needsCollision(body0Wrap->getCollisionObject(), body1Wrap->getCollisionObject()))
{
- m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(),body1Wrap->getCollisionObject());
+ m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(), body1Wrap->getCollisionObject());
m_ownManifold = true;
}
}
@@ -42,30 +42,27 @@ btBoxBoxCollisionAlgorithm::~btBoxBoxCollisionAlgorithm()
}
}
-void btBoxBoxCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+void btBoxBoxCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
{
if (!m_manifoldPtr)
return;
-
const btBoxShape* box0 = (btBoxShape*)body0Wrap->getCollisionShape();
const btBoxShape* box1 = (btBoxShape*)body1Wrap->getCollisionShape();
-
-
/// report a contact. internally this will be kept persistent, and contact reduction is done
resultOut->setPersistentManifold(m_manifoldPtr);
-#ifndef USE_PERSISTENT_CONTACTS
+#ifndef USE_PERSISTENT_CONTACTS
m_manifoldPtr->clearManifold();
-#endif //USE_PERSISTENT_CONTACTS
+#endif //USE_PERSISTENT_CONTACTS
btDiscreteCollisionDetectorInterface::ClosestPointInput input;
input.m_maximumDistanceSquared = BT_LARGE_FLOAT;
input.m_transformA = body0Wrap->getWorldTransform();
input.m_transformB = body1Wrap->getWorldTransform();
- btBoxBoxDetector detector(box0,box1);
- detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
+ btBoxBoxDetector detector(box0, box1);
+ detector.getClosestPoints(input, *resultOut, dispatchInfo.m_debugDraw);
#ifdef USE_PERSISTENT_CONTACTS
// refreshContactPoints is only necessary when using persistent contact points. otherwise all points are newly added
@@ -73,11 +70,10 @@ void btBoxBoxCollisionAlgorithm::processCollision (const btCollisionObjectWrappe
{
resultOut->refreshContactPoints();
}
-#endif //USE_PERSISTENT_CONTACTS
-
+#endif //USE_PERSISTENT_CONTACTS
}
-btScalar btBoxBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/,btCollisionObject* /*body1*/,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/)
+btScalar btBoxBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/, btCollisionObject* /*body1*/, const btDispatcherInfo& /*dispatchInfo*/, btManifoldResult* /*resultOut*/)
{
//not yet
return 1.f;
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h
index 59808df5a9..eb21065765 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h
@@ -26,22 +26,22 @@ class btPersistentManifold;
///box-box collision detection
class btBoxBoxCollisionAlgorithm : public btActivatingCollisionAlgorithm
{
- bool m_ownManifold;
- btPersistentManifold* m_manifoldPtr;
-
+ bool m_ownManifold;
+ btPersistentManifold* m_manifoldPtr;
+
public:
btBoxBoxCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
: btActivatingCollisionAlgorithm(ci) {}
- virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
- virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
- btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
+ btBoxBoxCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap);
virtual ~btBoxBoxCollisionAlgorithm();
- virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr && m_ownManifold)
{
@@ -49,18 +49,15 @@ public:
}
}
-
- struct CreateFunc :public btCollisionAlgorithmCreateFunc
+ struct CreateFunc : public btCollisionAlgorithmCreateFunc
{
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
{
int bbsize = sizeof(btBoxBoxCollisionAlgorithm);
void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize);
- return new(ptr) btBoxBoxCollisionAlgorithm(0,ci,body0Wrap,body1Wrap);
+ return new (ptr) btBoxBoxCollisionAlgorithm(0, ci, body0Wrap, body1Wrap);
}
};
-
};
-#endif //BT_BOX_BOX__COLLISION_ALGORITHM_H
-
+#endif //BT_BOX_BOX__COLLISION_ALGORITHM_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp
index 7043bde34f..202039956e 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp
@@ -24,14 +24,12 @@ subject to the following restrictions:
#include <float.h>
#include <string.h>
-btBoxBoxDetector::btBoxBoxDetector(const btBoxShape* box1,const btBoxShape* box2)
-: m_box1(box1),
-m_box2(box2)
+btBoxBoxDetector::btBoxBoxDetector(const btBoxShape* box1, const btBoxShape* box2)
+ : m_box1(box1),
+ m_box2(box2)
{
-
}
-
// 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.
@@ -48,67 +46,66 @@ m_box2(box2)
// collision functions. this function only fills in the position and depth
// fields.
struct dContactGeom;
-#define dDOTpq(a,b,p,q) ((a)[0]*(b)[0] + (a)[p]*(b)[q] + (a)[2*(p)]*(b)[2*(q)])
+#define dDOTpq(a, b, p, q) ((a)[0] * (b)[0] + (a)[p] * (b)[q] + (a)[2 * (p)] * (b)[2 * (q)])
#define dInfinity FLT_MAX
-
/*PURE_INLINE btScalar dDOT (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,1); }
PURE_INLINE btScalar dDOT13 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,3); }
PURE_INLINE btScalar dDOT31 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,3,1); }
PURE_INLINE btScalar dDOT33 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,3,3); }
*/
-static btScalar dDOT (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,1); }
-static btScalar dDOT44 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,4,4); }
-static btScalar dDOT41 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,4,1); }
-static btScalar dDOT14 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,4); }
-#define dMULTIPLYOP1_331(A,op,B,C) \
-{\
- (A)[0] op dDOT41((B),(C)); \
- (A)[1] op dDOT41((B+1),(C)); \
- (A)[2] op dDOT41((B+2),(C)); \
-}
+static btScalar dDOT(const btScalar* a, const btScalar* b) { return dDOTpq(a, b, 1, 1); }
+static btScalar dDOT44(const btScalar* a, const btScalar* b) { return dDOTpq(a, b, 4, 4); }
+static btScalar dDOT41(const btScalar* a, const btScalar* b) { return dDOTpq(a, b, 4, 1); }
+static btScalar dDOT14(const btScalar* a, const btScalar* b) { return dDOTpq(a, b, 1, 4); }
+#define dMULTIPLYOP1_331(A, op, B, C) \
+ { \
+ (A)[0] op dDOT41((B), (C)); \
+ (A)[1] op dDOT41((B + 1), (C)); \
+ (A)[2] op dDOT41((B + 2), (C)); \
+ }
-#define dMULTIPLYOP0_331(A,op,B,C) \
-{ \
- (A)[0] op dDOT((B),(C)); \
- (A)[1] op dDOT((B+4),(C)); \
- (A)[2] op dDOT((B+8),(C)); \
-}
+#define dMULTIPLYOP0_331(A, op, B, C) \
+ { \
+ (A)[0] op dDOT((B), (C)); \
+ (A)[1] op dDOT((B + 4), (C)); \
+ (A)[2] op dDOT((B + 8), (C)); \
+ }
-#define dMULTIPLY1_331(A,B,C) dMULTIPLYOP1_331(A,=,B,C)
-#define dMULTIPLY0_331(A,B,C) dMULTIPLYOP0_331(A,=,B,C)
+#define dMULTIPLY1_331(A, B, C) dMULTIPLYOP1_331(A, =, B, C)
+#define dMULTIPLY0_331(A, B, C) dMULTIPLYOP0_331(A, =, B, C)
-typedef btScalar dMatrix3[4*3];
+typedef btScalar dMatrix3[4 * 3];
-void dLineClosestApproach (const btVector3& pa, const btVector3& ua,
- const btVector3& pb, const btVector3& ub,
- btScalar *alpha, btScalar *beta);
-void dLineClosestApproach (const btVector3& pa, const btVector3& ua,
- const btVector3& pb, const btVector3& ub,
- btScalar *alpha, btScalar *beta)
+void dLineClosestApproach(const btVector3& pa, const btVector3& ua,
+ const btVector3& pb, const btVector3& ub,
+ btScalar* alpha, btScalar* beta);
+void dLineClosestApproach(const btVector3& pa, const btVector3& ua,
+ const btVector3& pb, const btVector3& ub,
+ btScalar* alpha, btScalar* beta)
{
- btVector3 p;
- p[0] = pb[0] - pa[0];
- p[1] = pb[1] - pa[1];
- p[2] = pb[2] - pa[2];
- btScalar uaub = dDOT(ua,ub);
- btScalar q1 = dDOT(ua,p);
- btScalar q2 = -dDOT(ub,p);
- btScalar d = 1-uaub*uaub;
- if (d <= btScalar(0.0001f)) {
- // @@@ this needs to be made more robust
- *alpha = 0;
- *beta = 0;
- }
- else {
- d = 1.f/d;
- *alpha = (q1 + uaub*q2)*d;
- *beta = (uaub*q1 + q2)*d;
- }
+ btVector3 p;
+ p[0] = pb[0] - pa[0];
+ p[1] = pb[1] - pa[1];
+ p[2] = pb[2] - pa[2];
+ btScalar uaub = dDOT(ua, ub);
+ btScalar q1 = dDOT(ua, p);
+ btScalar q2 = -dDOT(ub, p);
+ btScalar d = 1 - uaub * uaub;
+ if (d <= btScalar(0.0001f))
+ {
+ // @@@ this needs to be made more robust
+ *alpha = 0;
+ *beta = 0;
+ }
+ else
+ {
+ d = 1.f / d;
+ *alpha = (q1 + uaub * q2) * d;
+ *beta = (uaub * q1 + q2) * d;
+ }
}
-
-
// 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]).
@@ -117,60 +114,66 @@ void dLineClosestApproach (const btVector3& pa, const btVector3& ua,
// the number of intersection points is returned by the function (this will
// be in the range 0 to 8).
-static int intersectRectQuad2 (btScalar h[2], btScalar p[8], btScalar ret[16])
+static int intersectRectQuad2(btScalar h[2], btScalar p[8], btScalar ret[16])
{
- // q (and r) contain nq (and nr) coordinate points for the current (and
- // chopped) polygons
- int nq=4,nr=0;
- btScalar buffer[16];
- btScalar *q = p;
- btScalar *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]
- btScalar *pq = q;
- btScalar *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;
- }
- }
- btScalar *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;
- }
+ // q (and r) contain nq (and nr) coordinate points for the current (and
+ // chopped) polygons
+ int nq = 4, nr = 0;
+ btScalar buffer[16];
+ btScalar* q = p;
+ btScalar* 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]
+ btScalar* pq = q;
+ btScalar* 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;
+ }
+ }
+ btScalar* 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;
+ }
}
- pq += 2;
- }
- q = r;
- r = (q==ret) ? buffer : ret;
- nq = nr;
- }
- }
- done:
- if (q != ret) memcpy (ret,q,nr*2*sizeof(btScalar));
- return nr;
+done:
+ if (q != ret) memcpy(ret, q, nr * 2 * sizeof(btScalar));
+ return nr;
}
-
#define M__PI 3.14159265f
// given n points in the plane (array p, of size 2*n), generate m points that
@@ -181,538 +184,584 @@ static int intersectRectQuad2 (btScalar h[2], btScalar p[8], btScalar ret[16])
// 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 cullPoints2 (int n, btScalar p[], int m, int i0, int iret[]);
-void cullPoints2 (int n, btScalar p[], int m, int i0, int iret[])
+void cullPoints2(int n, btScalar p[], int m, int i0, int iret[]);
+void cullPoints2(int n, btScalar p[], int m, int i0, int iret[])
{
- // compute the centroid of the polygon in cx,cy
- int i,j;
- btScalar a,cx,cy,q;
- if (n==1) {
- cx = p[0];
- cy = p[1];
- }
- else if (n==2) {
- cx = btScalar(0.5)*(p[0] + p[2]);
- cy = btScalar(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];
- if (btFabs(a+q) > SIMD_EPSILON)
+ // compute the centroid of the polygon in cx,cy
+ int i, j;
+ btScalar a, cx, cy, q;
+ if (n == 1)
{
- a = 1.f/(btScalar(3.0)*(a+q));
- } else
+ cx = p[0];
+ cy = p[1];
+ }
+ else if (n == 2)
{
- a=BT_LARGE_FLOAT;
+ cx = btScalar(0.5) * (p[0] + p[2]);
+ cy = btScalar(0.5) * (p[1] + p[3]);
}
- 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
- btScalar A[8];
- for (i=0; i<n; i++) A[i] = btAtan2(p[i*2+1]-cy,p[i*2]-cx);
-
- // search for points that have angles closest to A[i0] + i*(2*pi/m).
- int avail[8];
- for (i=0; i<n; i++) avail[i] = 1;
- avail[i0] = 0;
- iret[0] = i0;
- iret++;
- for (j=1; j<m; j++) {
- a = btScalar(j)*(2*M__PI/m) + A[i0];
- if (a > M__PI) a -= 2*M__PI;
- btScalar maxdiff=1e9,diff;
-
- *iret = i0; // iret is not allowed to keep this value, but it sometimes does, when diff=#QNAN0
-
- for (i=0; i<n; i++) {
- if (avail[i]) {
- diff = btFabs (A[i]-a);
- if (diff > M__PI) diff = 2*M__PI - diff;
- if (diff < maxdiff) {
- maxdiff = diff;
- *iret = i;
+ 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];
+ if (btFabs(a + q) > SIMD_EPSILON)
+ {
+ a = 1.f / (btScalar(3.0) * (a + q));
+ }
+ else
+ {
+ a = BT_LARGE_FLOAT;
+ }
+ cx = a * (cx + q * (p[n * 2 - 2] + p[0]));
+ cy = a * (cy + q * (p[n * 2 - 1] + p[1]));
}
- }
- }
-#if defined(DEBUG) || defined (_DEBUG)
- btAssert (*iret != i0); // ensure iret got set
+
+ // compute the angle of each point w.r.t. the centroid
+ btScalar A[8];
+ for (i = 0; i < n; i++) A[i] = btAtan2(p[i * 2 + 1] - cy, p[i * 2] - cx);
+
+ // search for points that have angles closest to A[i0] + i*(2*pi/m).
+ int avail[8];
+ for (i = 0; i < n; i++) avail[i] = 1;
+ avail[i0] = 0;
+ iret[0] = i0;
+ iret++;
+ for (j = 1; j < m; j++)
+ {
+ a = btScalar(j) * (2 * M__PI / m) + A[i0];
+ if (a > M__PI) a -= 2 * M__PI;
+ btScalar maxdiff = 1e9, diff;
+
+ *iret = i0; // iret is not allowed to keep this value, but it sometimes does, when diff=#QNAN0
+
+ for (i = 0; i < n; i++)
+ {
+ if (avail[i])
+ {
+ diff = btFabs(A[i] - a);
+ if (diff > M__PI) diff = 2 * M__PI - diff;
+ if (diff < maxdiff)
+ {
+ maxdiff = diff;
+ *iret = i;
+ }
+ }
+ }
+#if defined(DEBUG) || defined(_DEBUG)
+ btAssert(*iret != i0); // ensure iret got set
#endif
- avail[*iret] = 0;
- iret++;
- }
+ avail[*iret] = 0;
+ iret++;
+ }
}
+int dBoxBox2(const btVector3& p1, const dMatrix3 R1,
+ const btVector3& side1, const btVector3& p2,
+ const dMatrix3 R2, const btVector3& side2,
+ btVector3& normal, btScalar* depth, int* return_code,
+ int maxc, dContactGeom* /*contact*/, int /*skip*/, btDiscreteCollisionDetectorInterface::Result& output);
+int dBoxBox2(const btVector3& p1, const dMatrix3 R1,
+ const btVector3& side1, const btVector3& p2,
+ const dMatrix3 R2, const btVector3& side2,
+ btVector3& normal, btScalar* depth, int* return_code,
+ int maxc, dContactGeom* /*contact*/, int /*skip*/, btDiscreteCollisionDetectorInterface::Result& output)
+{
+ const btScalar fudge_factor = btScalar(1.05);
+ btVector3 p, pp, normalC(0.f, 0.f, 0.f);
+ const btScalar* normalR = 0;
+ btScalar 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;
+ int i, j, invert_normal, code;
+
+ // get vector from centers of box 1 to box 2, relative to box 1
+ p = p2 - p1;
+ dMULTIPLY1_331(pp, R1, p); // get pp = p relative to body 1
+
+ // get side lengths / 2
+ A[0] = side1[0] * btScalar(0.5);
+ A[1] = side1[1] * btScalar(0.5);
+ A[2] = side1[2] * btScalar(0.5);
+ B[0] = side2[0] * btScalar(0.5);
+ B[1] = side2[1] * btScalar(0.5);
+ B[2] = side2[2] * btScalar(0.5);
+
+ // Rij is R1'*R2, i.e. the relative rotation between R1 and R2
+ R11 = dDOT44(R1 + 0, R2 + 0);
+ R12 = dDOT44(R1 + 0, R2 + 1);
+ R13 = dDOT44(R1 + 0, R2 + 2);
+ R21 = dDOT44(R1 + 1, R2 + 0);
+ R22 = dDOT44(R1 + 1, R2 + 1);
+ R23 = dDOT44(R1 + 1, R2 + 2);
+ R31 = dDOT44(R1 + 2, R2 + 0);
+ R32 = dDOT44(R1 + 2, R2 + 1);
+ R33 = dDOT44(R1 + 2, R2 + 2);
+
+ Q11 = btFabs(R11);
+ Q12 = btFabs(R12);
+ Q13 = btFabs(R13);
+ Q21 = btFabs(R21);
+ Q22 = btFabs(R22);
+ Q23 = btFabs(R23);
+ Q31 = btFabs(R31);
+ Q32 = btFabs(R32);
+ Q33 = btFabs(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.
+
+#define TST(expr1, expr2, norm, cc) \
+ s2 = btFabs(expr1) - (expr2); \
+ if (s2 > 0) return 0; \
+ if (s2 > s) \
+ { \
+ s = s2; \
+ normalR = norm; \
+ invert_normal = ((expr1) < 0); \
+ code = (cc); \
+ }
+ s = -dInfinity;
+ invert_normal = 0;
+ code = 0;
-int dBoxBox2 (const btVector3& p1, const dMatrix3 R1,
- const btVector3& side1, const btVector3& p2,
- const dMatrix3 R2, const btVector3& side2,
- btVector3& normal, btScalar *depth, int *return_code,
- int maxc, dContactGeom * /*contact*/, int /*skip*/,btDiscreteCollisionDetectorInterface::Result& output);
-int dBoxBox2 (const btVector3& p1, const dMatrix3 R1,
- const btVector3& side1, const btVector3& p2,
- const dMatrix3 R2, const btVector3& side2,
- btVector3& normal, btScalar *depth, int *return_code,
- int maxc, dContactGeom * /*contact*/, int /*skip*/,btDiscreteCollisionDetectorInterface::Result& output)
-{
- const btScalar fudge_factor = btScalar(1.05);
- btVector3 p,pp,normalC(0.f,0.f,0.f);
- const btScalar *normalR = 0;
- btScalar 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;
- int i,j,invert_normal,code;
-
- // get vector from centers of box 1 to box 2, relative to box 1
- p = p2 - p1;
- dMULTIPLY1_331 (pp,R1,p); // get pp = p relative to body 1
-
- // get side lengths / 2
- A[0] = side1[0]*btScalar(0.5);
- A[1] = side1[1]*btScalar(0.5);
- A[2] = side1[2]*btScalar(0.5);
- B[0] = side2[0]*btScalar(0.5);
- B[1] = side2[1]*btScalar(0.5);
- B[2] = side2[2]*btScalar(0.5);
-
- // Rij is R1'*R2, i.e. the relative rotation between R1 and R2
- R11 = dDOT44(R1+0,R2+0); R12 = dDOT44(R1+0,R2+1); R13 = dDOT44(R1+0,R2+2);
- R21 = dDOT44(R1+1,R2+0); R22 = dDOT44(R1+1,R2+1); R23 = dDOT44(R1+1,R2+2);
- R31 = dDOT44(R1+2,R2+0); R32 = dDOT44(R1+2,R2+1); R33 = dDOT44(R1+2,R2+2);
-
- Q11 = btFabs(R11); Q12 = btFabs(R12); Q13 = btFabs(R13);
- Q21 = btFabs(R21); Q22 = btFabs(R22); Q23 = btFabs(R23);
- Q31 = btFabs(R31); Q32 = btFabs(R32); Q33 = btFabs(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.
-
-#define TST(expr1,expr2,norm,cc) \
- s2 = btFabs(expr1) - (expr2); \
- if (s2 > 0) return 0; \
- if (s2 > s) { \
- s = s2; \
- normalR = norm; \
- invert_normal = ((expr1) < 0); \
- code = (cc); \
- }
-
- 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 (dDOT41(R2+0,p),(A[0]*Q11 + A[1]*Q21 + A[2]*Q31 + B[0]),R2+0,4);
- TST (dDOT41(R2+1,p),(A[0]*Q12 + A[1]*Q22 + A[2]*Q32 + B[1]),R2+1,5);
- TST (dDOT41(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.
+ // 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(dDOT41(R2 + 0, p), (A[0] * Q11 + A[1] * Q21 + A[2] * Q31 + B[0]), R2 + 0, 4);
+ TST(dDOT41(R2 + 1, p), (A[0] * Q12 + A[1] * Q22 + A[2] * Q32 + B[1]), R2 + 1, 5);
+ TST(dDOT41(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) \
- s2 = btFabs(expr1) - (expr2); \
- if (s2 > SIMD_EPSILON) return 0; \
- l = btSqrt((n1)*(n1) + (n2)*(n2) + (n3)*(n3)); \
- if (l > SIMD_EPSILON) { \
- 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) < 0); \
- code = (cc); \
- } \
- }
-
- btScalar fudge2 (1.0e-5f);
-
- Q11 += fudge2;
- Q12 += fudge2;
- Q13 += fudge2;
-
- Q21 += fudge2;
- Q22 += fudge2;
- Q23 += fudge2;
-
- Q31 += fudge2;
- Q32 += fudge2;
- Q33 += fudge2;
-
- // 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);
+#define TST(expr1, expr2, n1, n2, n3, cc) \
+ s2 = btFabs(expr1) - (expr2); \
+ if (s2 > SIMD_EPSILON) return 0; \
+ l = btSqrt((n1) * (n1) + (n2) * (n2) + (n3) * (n3)); \
+ if (l > SIMD_EPSILON) \
+ { \
+ 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) < 0); \
+ code = (cc); \
+ } \
+ }
+
+ btScalar fudge2(1.0e-5f);
+
+ Q11 += fudge2;
+ Q12 += fudge2;
+ Q13 += fudge2;
+
+ Q21 += fudge2;
+ Q22 += fudge2;
+ Q23 += fudge2;
+
+ Q31 += fudge2;
+ Q32 += fudge2;
+ Q33 += fudge2;
+
+ // 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
- 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
- btVector3 pa;
- btScalar sign;
- for (i=0; i<3; i++) pa[i] = p1[i];
- for (j=0; j<3; j++) {
- sign = (dDOT14(normal,R1+j) > 0) ? btScalar(1.0) : btScalar(-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
- btVector3 pb;
- for (i=0; i<3; i++) pb[i] = p2[i];
- for (j=0; j<3; j++) {
- sign = (dDOT14(normal,R2+j) > 0) ? btScalar(-1.0) : btScalar(1.0);
- for (i=0; i<3; i++) pb[i] += sign * B[j] * R2[i*4+j];
- }
-
- btScalar alpha,beta;
- btVector3 ua,ub;
- for (i=0; i<3; i++) ua[i] = R1[((code)-7)/3 + i*4];
- for (i=0; i<3; i++) ub[i] = R2[((code)-7)%3 + i*4];
-
- 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;
+ 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
{
-
- //contact[0].pos[i] = btScalar(0.5)*(pa[i]+pb[i]);
- //contact[0].depth = *depth;
- btVector3 pointInWorld;
+ 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
+ btVector3 pa;
+ btScalar sign;
+ for (i = 0; i < 3; i++) pa[i] = p1[i];
+ for (j = 0; j < 3; j++)
+ {
+ sign = (dDOT14(normal, R1 + j) > 0) ? btScalar(1.0) : btScalar(-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
+ btVector3 pb;
+ for (i = 0; i < 3; i++) pb[i] = p2[i];
+ for (j = 0; j < 3; j++)
+ {
+ sign = (dDOT14(normal, R2 + j) > 0) ? btScalar(-1.0) : btScalar(1.0);
+ for (i = 0; i < 3; i++) pb[i] += sign * B[j] * R2[i * 4 + j];
+ }
+
+ btScalar alpha, beta;
+ btVector3 ua, ub;
+ for (i = 0; i < 3; i++) ua[i] = R1[((code)-7) / 3 + i * 4];
+ for (i = 0; i < 3; i++) ub[i] = R2[((code)-7) % 3 + i * 4];
+
+ 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;
+
+ {
+ //contact[0].pos[i] = btScalar(0.5)*(pa[i]+pb[i]);
+ //contact[0].depth = *depth;
+ btVector3 pointInWorld;
#ifdef USE_CENTER_POINT
- for (i=0; i<3; i++)
- pointInWorld[i] = (pa[i]+pb[i])*btScalar(0.5);
- output.addContactPoint(-normal,pointInWorld,-*depth);
+ for (i = 0; i < 3; i++)
+ pointInWorld[i] = (pa[i] + pb[i]) * btScalar(0.5);
+ output.addContactPoint(-normal, pointInWorld, -*depth);
#else
- output.addContactPoint(-normal,pb,-*depth);
+ output.addContactPoint(-normal, pb, -*depth);
-#endif //
- *return_code = code;
+#endif //
+ *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).
+
+ const btScalar *Ra, *Rb, *pa, *pb, *Sa, *Sb;
+ if (code <= 3)
+ {
+ Ra = R1;
+ Rb = R2;
+ pa = p1;
+ pb = p2;
+ Sa = A;
+ Sb = B;
+ }
+ else
+ {
+ Ra = R2;
+ Rb = R1;
+ pa = p2;
+ pb = p1;
+ Sa = B;
+ Sb = A;
+ }
+
+ // nr = normal vector of reference face dotted with axes of incident box.
+ // anr = absolute values of nr.
+ btVector3 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];
}
- 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).
-
- const btScalar *Ra,*Rb,*pa,*pb,*Sa,*Sb;
- if (code <= 3) {
- Ra = R1;
- Rb = R2;
- pa = p1;
- pb = p2;
- Sa = A;
- Sb = B;
- }
- else {
- Ra = R2;
- Rb = R1;
- pa = p2;
- pb = p1;
- Sa = B;
- Sb = A;
- }
-
- // nr = normal vector of reference face dotted with axes of incident box.
- // anr = absolute values of nr.
- btVector3 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];
- }
- dMULTIPLY1_331 (nr,Rb,normal2);
- anr[0] = btFabs (nr[0]);
- anr[1] = btFabs (nr[1]);
- anr[2] = btFabs (nr[2]);
-
- // find the largest compontent of anr: this corresponds to the normal
- // for the indident face. the other axis numbers of the indicent 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
- btVector3 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
- btScalar quad[8]; // 2D coordinate of incident face (x,y pairs)
- btScalar c1,c2,m11,m12,m21,m22;
- c1 = dDOT14 (center,Ra+code1);
- c2 = dDOT14 (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 = dDOT44 (Ra+code1,Rb+a1);
- m12 = dDOT44 (Ra+code1,Rb+a2);
- m21 = dDOT44 (Ra+code2,Rb+a1);
- m22 = dDOT44 (Ra+code2,Rb+a2);
- {
- btScalar k1 = m11*Sb[a1];
- btScalar k2 = m21*Sb[a1];
- btScalar k3 = m12*Sb[a2];
- btScalar 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
- btScalar rect[2];
- rect[0] = Sa[code1];
- rect[1] = Sa[code2];
-
- // intersect the incident and reference faces
- btScalar ret[16];
- int n = intersectRectQuad2 (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.
- btScalar point[3*8]; // penetrating contact points
- btScalar dep[8]; // depths for those points
- btScalar det1 = 1.f/(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++) {
- btScalar k1 = m22*(ret[j*2]-c1) - m12*(ret[j*2+1]-c2);
- btScalar 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] - dDOT(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 < 1) return 0; // this should never happen
-
- // we can't generate more contacts than we actually have
- if (maxc > cnum) maxc = cnum;
- if (maxc < 1) maxc = 1;
-
- if (cnum <= maxc) {
-
- if (code<4)
- {
- // we have less contacts than we need, so we use them all
- for (j=0; j < cnum; j++)
+ dMULTIPLY1_331(nr, Rb, normal2);
+ anr[0] = btFabs(nr[0]);
+ anr[1] = btFabs(nr[1]);
+ anr[2] = btFabs(nr[2]);
+
+ // find the largest compontent of anr: this corresponds to the normal
+ // for the indident face. the other axis numbers of the indicent face
+ // are stored in a1,a2.
+ int lanr, a1, a2;
+ if (anr[1] > anr[0])
{
- btVector3 pointInWorld;
- for (i=0; i<3; i++)
- pointInWorld[i] = point[j*3+i] + pa[i];
- output.addContactPoint(-normal,pointInWorld,-dep[j]);
-
- }
- } else
- {
- // we have less contacts than we need, so we use them all
- for (j=0; j < cnum; j++)
+ if (anr[1] > anr[2])
{
- btVector3 pointInWorld;
- for (i=0; i<3; i++)
- pointInWorld[i] = point[j*3+i] + pa[i]-normal[i]*dep[j];
+ 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
+ btVector3 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
+ btScalar quad[8]; // 2D coordinate of incident face (x,y pairs)
+ btScalar c1, c2, m11, m12, m21, m22;
+ c1 = dDOT14(center, Ra + code1);
+ c2 = dDOT14(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 = dDOT44(Ra + code1, Rb + a1);
+ m12 = dDOT44(Ra + code1, Rb + a2);
+ m21 = dDOT44(Ra + code2, Rb + a1);
+ m22 = dDOT44(Ra + code2, Rb + a2);
+ {
+ btScalar k1 = m11 * Sb[a1];
+ btScalar k2 = m21 * Sb[a1];
+ btScalar k3 = m12 * Sb[a2];
+ btScalar 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
+ btScalar rect[2];
+ rect[0] = Sa[code1];
+ rect[1] = Sa[code2];
+
+ // intersect the incident and reference faces
+ btScalar ret[16];
+ int n = intersectRectQuad2(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.
+ btScalar point[3 * 8]; // penetrating contact points
+ btScalar dep[8]; // depths for those points
+ btScalar det1 = 1.f / (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++)
+ {
+ btScalar k1 = m22 * (ret[j * 2] - c1) - m12 * (ret[j * 2 + 1] - c2);
+ btScalar 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] - dDOT(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 < 1) return 0; // this should never happen
+
+ // we can't generate more contacts than we actually have
+ if (maxc > cnum) maxc = cnum;
+ if (maxc < 1) maxc = 1;
+
+ if (cnum <= maxc)
+ {
+ if (code < 4)
+ {
+ // we have less contacts than we need, so we use them all
+ for (j = 0; j < cnum; j++)
+ {
+ btVector3 pointInWorld;
+ for (i = 0; i < 3; i++)
+ pointInWorld[i] = point[j * 3 + i] + pa[i];
+ output.addContactPoint(-normal, pointInWorld, -dep[j]);
+ }
+ }
+ else
+ {
+ // we have less contacts than we need, so we use them all
+ for (j = 0; j < cnum; j++)
+ {
+ btVector3 pointInWorld;
+ for (i = 0; i < 3; i++)
+ pointInWorld[i] = point[j * 3 + i] + pa[i] - normal[i] * dep[j];
//pointInWorld[i] = point[j*3+i] + pa[i];
- output.addContactPoint(-normal,pointInWorld,-dep[j]);
+ output.addContactPoint(-normal, pointInWorld, -dep[j]);
+ }
}
- }
- }
- else {
- // 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;
- btScalar maxdepth = dep[0];
- for (i=1; i<cnum; i++) {
- if (dep[i] > maxdepth) {
- maxdepth = dep[i];
- i1 = i;
- }
- }
-
- int iret[8];
- cullPoints2 (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]];
-
- btVector3 posInWorld;
- for (i=0; i<3; i++)
- posInWorld[i] = point[iret[j]*3+i] + pa[i];
- if (code<4)
- {
- output.addContactPoint(-normal,posInWorld,-dep[iret[j]]);
- } else
+ }
+ else
+ {
+ // 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;
+ btScalar maxdepth = dep[0];
+ for (i = 1; i < cnum; i++)
{
- output.addContactPoint(-normal,posInWorld-normal*dep[iret[j]],-dep[iret[j]]);
+ if (dep[i] > maxdepth)
+ {
+ maxdepth = dep[i];
+ i1 = i;
+ }
}
- }
- cnum = maxc;
- }
- *return_code = code;
- return cnum;
+ int iret[8];
+ cullPoints2(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]];
+
+ btVector3 posInWorld;
+ for (i = 0; i < 3; i++)
+ posInWorld[i] = point[iret[j] * 3 + i] + pa[i];
+ if (code < 4)
+ {
+ output.addContactPoint(-normal, posInWorld, -dep[iret[j]]);
+ }
+ else
+ {
+ output.addContactPoint(-normal, posInWorld - normal * dep[iret[j]], -dep[iret[j]]);
+ }
+ }
+ cnum = maxc;
+ }
+
+ *return_code = code;
+ return cnum;
}
-void btBoxBoxDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* /*debugDraw*/,bool /*swapResults*/)
+void btBoxBoxDetector::getClosestPoints(const ClosestPointInput& input, Result& output, class btIDebugDraw* /*debugDraw*/, bool /*swapResults*/)
{
-
const btTransform& transformA = input.m_transformA;
const btTransform& transformB = input.m_transformB;
-
+
int skip = 0;
- dContactGeom *contact = 0;
+ dContactGeom* contact = 0;
dMatrix3 R1;
dMatrix3 R2;
- for (int j=0;j<3;j++)
+ for (int j = 0; j < 3; j++)
{
- R1[0+4*j] = transformA.getBasis()[j].x();
- R2[0+4*j] = transformB.getBasis()[j].x();
-
- R1[1+4*j] = transformA.getBasis()[j].y();
- R2[1+4*j] = transformB.getBasis()[j].y();
-
+ R1[0 + 4 * j] = transformA.getBasis()[j].x();
+ R2[0 + 4 * j] = transformB.getBasis()[j].x();
- R1[2+4*j] = transformA.getBasis()[j].z();
- R2[2+4*j] = transformB.getBasis()[j].z();
+ R1[1 + 4 * j] = transformA.getBasis()[j].y();
+ R2[1 + 4 * j] = transformB.getBasis()[j].y();
+ R1[2 + 4 * j] = transformA.getBasis()[j].z();
+ R2[2 + 4 * j] = transformB.getBasis()[j].z();
}
-
-
btVector3 normal;
btScalar depth;
int return_code;
int maxc = 4;
-
- dBoxBox2 (transformA.getOrigin(),
- R1,
- 2.f*m_box1->getHalfExtentsWithMargin(),
- transformB.getOrigin(),
- R2,
- 2.f*m_box2->getHalfExtentsWithMargin(),
- normal, &depth, &return_code,
- maxc, contact, skip,
- output
- );
-
+ dBoxBox2(transformA.getOrigin(),
+ R1,
+ 2.f * m_box1->getHalfExtentsWithMargin(),
+ transformB.getOrigin(),
+ R2,
+ 2.f * m_box2->getHalfExtentsWithMargin(),
+ normal, &depth, &return_code,
+ maxc, contact, skip,
+ output);
}
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btBoxBoxDetector.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btBoxBoxDetector.h
index 3924377705..9f7d988fc1 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btBoxBoxDetector.h
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btBoxBoxDetector.h
@@ -19,11 +19,9 @@ subject to the following restrictions:
#ifndef BT_BOX_BOX_DETECTOR_H
#define BT_BOX_BOX_DETECTOR_H
-
class btBoxShape;
#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
-
/// btBoxBoxDetector wraps the ODE box-box collision detector
/// re-distributed under the Zlib license with permission from Russell L. Smith
struct btBoxBoxDetector : public btDiscreteCollisionDetectorInterface
@@ -32,13 +30,11 @@ struct btBoxBoxDetector : public btDiscreteCollisionDetectorInterface
const btBoxShape* m_box2;
public:
+ btBoxBoxDetector(const btBoxShape* box1, const btBoxShape* box2);
- btBoxBoxDetector(const btBoxShape* box1,const btBoxShape* box2);
-
- virtual ~btBoxBoxDetector() {};
-
- virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false);
+ virtual ~btBoxBoxDetector(){};
+ virtual void getClosestPoints(const ClosestPointInput& input, Result& output, class btIDebugDraw* debugDraw, bool swapResults = false);
};
-#endif //BT_BOX_BOX_DETECTOR_H
+#endif //BT_BOX_BOX_DETECTOR_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionConfiguration.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionConfiguration.h
index 35f77d4e65..d6e15f555b 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionConfiguration.h
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionConfiguration.h
@@ -23,11 +23,9 @@ class btPoolAllocator;
///btCollisionConfiguration allows to configure Bullet collision detection
///stack allocator size, default collision algorithms and persistent manifold pool size
///@todo: describe the meaning
-class btCollisionConfiguration
+class btCollisionConfiguration
{
-
public:
-
virtual ~btCollisionConfiguration()
{
}
@@ -37,13 +35,9 @@ public:
virtual btPoolAllocator* getCollisionAlgorithmPool() = 0;
-
- virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1) =0;
+ virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0, int proxyType1) = 0;
virtual btCollisionAlgorithmCreateFunc* getClosestPointsAlgorithmCreateFunc(int proxyType0, int proxyType1) = 0;
-
-
};
-#endif //BT_COLLISION_CONFIGURATION
-
+#endif //BT_COLLISION_CONFIGURATION
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h
index 62ee66c4e9..bd81284939 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h
@@ -26,20 +26,18 @@ struct btCollisionAlgorithmConstructionInfo;
struct btCollisionAlgorithmCreateFunc
{
bool m_swapped;
-
+
btCollisionAlgorithmCreateFunc()
- :m_swapped(false)
+ : m_swapped(false)
{
}
virtual ~btCollisionAlgorithmCreateFunc(){};
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& , const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo&, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
{
-
(void)body0Wrap;
(void)body1Wrap;
return 0;
}
};
-#endif //BT_COLLISION_CREATE_FUNC
-
+#endif //BT_COLLISION_CREATE_FUNC
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp
index f8794dec47..25b2b1ea46 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp
@@ -13,8 +13,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
-
#include "btCollisionDispatcher.h"
#include "LinearMath/btQuickprof.h"
@@ -31,40 +29,34 @@ subject to the following restrictions:
#include <stdio.h>
#endif
-
-btCollisionDispatcher::btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration):
-m_dispatcherFlags(btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD),
- m_collisionConfiguration(collisionConfiguration)
+btCollisionDispatcher::btCollisionDispatcher(btCollisionConfiguration* collisionConfiguration) : m_dispatcherFlags(btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD),
+ m_collisionConfiguration(collisionConfiguration)
{
int i;
setNearCallback(defaultNearCallback);
-
+
m_collisionAlgorithmPoolAllocator = collisionConfiguration->getCollisionAlgorithmPool();
m_persistentManifoldPoolAllocator = collisionConfiguration->getPersistentManifoldPool();
- for (i=0;i<MAX_BROADPHASE_COLLISION_TYPES;i++)
+ for (i = 0; i < MAX_BROADPHASE_COLLISION_TYPES; i++)
{
- for (int j=0;j<MAX_BROADPHASE_COLLISION_TYPES;j++)
+ for (int j = 0; j < MAX_BROADPHASE_COLLISION_TYPES; j++)
{
- m_doubleDispatchContactPoints[i][j] = m_collisionConfiguration->getCollisionAlgorithmCreateFunc(i,j);
+ m_doubleDispatchContactPoints[i][j] = m_collisionConfiguration->getCollisionAlgorithmCreateFunc(i, j);
btAssert(m_doubleDispatchContactPoints[i][j]);
m_doubleDispatchClosestPoints[i][j] = m_collisionConfiguration->getClosestPointsAlgorithmCreateFunc(i, j);
-
}
}
-
-
}
-
-void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc *createFunc)
+void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc* createFunc)
{
m_doubleDispatchContactPoints[proxyType0][proxyType1] = createFunc;
}
-void btCollisionDispatcher::registerClosestPointsCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc *createFunc)
+void btCollisionDispatcher::registerClosestPointsCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc* createFunc)
{
m_doubleDispatchClosestPoints[proxyType0][proxyType1] = createFunc;
}
@@ -73,35 +65,33 @@ btCollisionDispatcher::~btCollisionDispatcher()
{
}
-btPersistentManifold* btCollisionDispatcher::getNewManifold(const btCollisionObject* body0,const btCollisionObject* body1)
-{
+btPersistentManifold* btCollisionDispatcher::getNewManifold(const btCollisionObject* body0, const btCollisionObject* body1)
+{
//btAssert(gNumManifold < 65535);
-
-
//optional relative contact breaking threshold, turned on by default (use setDispatcherFlags to switch off feature for improved performance)
-
- btScalar contactBreakingThreshold = (m_dispatcherFlags & btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD) ?
- btMin(body0->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold) , body1->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold))
- : gContactBreakingThreshold ;
-
- btScalar contactProcessingThreshold = btMin(body0->getContactProcessingThreshold(),body1->getContactProcessingThreshold());
-
- void* mem = m_persistentManifoldPoolAllocator->allocate( sizeof( btPersistentManifold ) );
- if (NULL == mem)
+
+ btScalar contactBreakingThreshold = (m_dispatcherFlags & btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD) ? btMin(body0->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold), body1->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold))
+ : gContactBreakingThreshold;
+
+ btScalar contactProcessingThreshold = btMin(body0->getContactProcessingThreshold(), body1->getContactProcessingThreshold());
+
+ void* mem = m_persistentManifoldPoolAllocator->allocate(sizeof(btPersistentManifold));
+ if (NULL == mem)
{
- //we got a pool memory overflow, by default we fallback to dynamically allocate memory. If we require a contiguous contact pool then assert.
- if ((m_dispatcherFlags&CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION)==0)
+ //we got a pool memory overflow, by default we fallback to dynamically allocate memory. If we require a contiguous contact pool then assert.
+ if ((m_dispatcherFlags & CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION) == 0)
{
- mem = btAlignedAlloc(sizeof(btPersistentManifold),16);
- } else
+ mem = btAlignedAlloc(sizeof(btPersistentManifold), 16);
+ }
+ else
{
btAssert(0);
//make sure to increase the m_defaultMaxPersistentManifoldPoolSize in the btDefaultCollisionConstructionInfo/btDefaultCollisionConfiguration
return 0;
}
}
- btPersistentManifold* manifold = new(mem) btPersistentManifold (body0,body1,0,contactBreakingThreshold,contactProcessingThreshold);
+ btPersistentManifold* manifold = new (mem) btPersistentManifold(body0, body1, 0, contactBreakingThreshold, contactProcessingThreshold);
manifold->m_index1a = m_manifoldsPtr.size();
m_manifoldsPtr.push_back(manifold);
@@ -113,17 +103,14 @@ void btCollisionDispatcher::clearManifold(btPersistentManifold* manifold)
manifold->clearManifold();
}
-
void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold)
{
-
-
//printf("releaseManifold: gNumManifold %d\n",gNumManifold);
clearManifold(manifold);
int findIndex = manifold->m_index1a;
btAssert(findIndex < m_manifoldsPtr.size());
- m_manifoldsPtr.swap(findIndex,m_manifoldsPtr.size()-1);
+ m_manifoldsPtr.swap(findIndex, m_manifoldsPtr.size() - 1);
m_manifoldsPtr[findIndex]->m_index1a = findIndex;
m_manifoldsPtr.pop_back();
@@ -131,19 +118,15 @@ void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold)
if (m_persistentManifoldPoolAllocator->validPtr(manifold))
{
m_persistentManifoldPoolAllocator->freeMemory(manifold);
- } else
+ }
+ else
{
btAlignedFree(manifold);
}
-
}
-
-
-
-btCollisionAlgorithm* btCollisionDispatcher::findAlgorithm(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btPersistentManifold* sharedManifold, ebtDispatcherQueryType algoType)
+btCollisionAlgorithm* btCollisionDispatcher::findAlgorithm(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, btPersistentManifold* sharedManifold, ebtDispatcherQueryType algoType)
{
-
btCollisionAlgorithmConstructionInfo ci;
ci.m_dispatcher1 = this;
@@ -161,21 +144,18 @@ btCollisionAlgorithm* btCollisionDispatcher::findAlgorithm(const btCollisionObje
return algo;
}
-
-
-
-bool btCollisionDispatcher::needsResponse(const btCollisionObject* body0,const btCollisionObject* body1)
+bool btCollisionDispatcher::needsResponse(const btCollisionObject* body0, const btCollisionObject* body1)
{
//here you can do filtering
- bool hasResponse =
+ bool hasResponse =
(body0->hasContactResponse() && body1->hasContactResponse());
//no response between two static/kinematic bodies:
hasResponse = hasResponse &&
- ((!body0->isStaticOrKinematicObject()) ||(! body1->isStaticOrKinematicObject()));
+ ((!body0->isStaticOrKinematicObject()) || (!body1->isStaticOrKinematicObject()));
return hasResponse;
}
-bool btCollisionDispatcher::needsCollision(const btCollisionObject* body0,const btCollisionObject* body1)
+bool btCollisionDispatcher::needsCollision(const btCollisionObject* body0, const btCollisionObject* body1)
{
btAssert(body0);
btAssert(body1);
@@ -192,31 +172,27 @@ bool btCollisionDispatcher::needsCollision(const btCollisionObject* body0,const
printf("warning btCollisionDispatcher::needsCollision: static-static collision!\n");
}
}
-#endif //BT_DEBUG
+#endif //BT_DEBUG
if ((!body0->isActive()) && (!body1->isActive()))
needsCollision = false;
else if ((!body0->checkCollideWith(body1)) || (!body1->checkCollideWith(body0)))
needsCollision = false;
-
- return needsCollision ;
+ return needsCollision;
}
-
-
///interface for iterating all overlapping collision pairs, no matter how those pairs are stored (array, set, map etc)
///this is useful for the collision dispatcher.
class btCollisionPairCallback : public btOverlapCallback
{
const btDispatcherInfo& m_dispatchInfo;
- btCollisionDispatcher* m_dispatcher;
+ btCollisionDispatcher* m_dispatcher;
public:
-
- btCollisionPairCallback(const btDispatcherInfo& dispatchInfo,btCollisionDispatcher* dispatcher)
- :m_dispatchInfo(dispatchInfo),
- m_dispatcher(dispatcher)
+ btCollisionPairCallback(const btDispatcherInfo& dispatchInfo, btCollisionDispatcher* dispatcher)
+ : m_dispatchInfo(dispatchInfo),
+ m_dispatcher(dispatcher)
{
}
@@ -228,87 +204,76 @@ public:
}
*/
-
virtual ~btCollisionPairCallback() {}
-
- virtual bool processOverlap(btBroadphasePair& pair)
+ virtual bool processOverlap(btBroadphasePair& pair)
{
- (*m_dispatcher->getNearCallback())(pair,*m_dispatcher,m_dispatchInfo);
+ (*m_dispatcher->getNearCallback())(pair, *m_dispatcher, m_dispatchInfo);
return false;
}
};
-
-
-
-void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher)
+void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache, const btDispatcherInfo& dispatchInfo, btDispatcher* dispatcher)
{
//m_blockedForChanges = true;
- btCollisionPairCallback collisionCallback(dispatchInfo,this);
+ btCollisionPairCallback collisionCallback(dispatchInfo, this);
- {
+ {
BT_PROFILE("processAllOverlappingPairs");
- pairCache->processAllOverlappingPairs(&collisionCallback,dispatcher, dispatchInfo);
+ pairCache->processAllOverlappingPairs(&collisionCallback, dispatcher, dispatchInfo);
}
//m_blockedForChanges = false;
-
}
-
-
//by default, Bullet will use this near callback
void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo)
{
- btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
- btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
+ btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
+ btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
+
+ if (dispatcher.needsCollision(colObj0, colObj1))
+ {
+ btCollisionObjectWrapper obj0Wrap(0, colObj0->getCollisionShape(), colObj0, colObj0->getWorldTransform(), -1, -1);
+ btCollisionObjectWrapper obj1Wrap(0, colObj1->getCollisionShape(), colObj1, colObj1->getWorldTransform(), -1, -1);
- if (dispatcher.needsCollision(colObj0,colObj1))
+ //dispatcher will keep algorithms persistent in the collision pair
+ if (!collisionPair.m_algorithm)
{
- btCollisionObjectWrapper obj0Wrap(0,colObj0->getCollisionShape(),colObj0,colObj0->getWorldTransform(),-1,-1);
- btCollisionObjectWrapper obj1Wrap(0,colObj1->getCollisionShape(),colObj1,colObj1->getWorldTransform(),-1,-1);
+ collisionPair.m_algorithm = dispatcher.findAlgorithm(&obj0Wrap, &obj1Wrap, 0, BT_CONTACT_POINT_ALGORITHMS);
+ }
+ if (collisionPair.m_algorithm)
+ {
+ btManifoldResult contactPointResult(&obj0Wrap, &obj1Wrap);
- //dispatcher will keep algorithms persistent in the collision pair
- if (!collisionPair.m_algorithm)
+ if (dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE)
{
- collisionPair.m_algorithm = dispatcher.findAlgorithm(&obj0Wrap,&obj1Wrap,0, BT_CONTACT_POINT_ALGORITHMS);
- }
+ //discrete collision detection query
- if (collisionPair.m_algorithm)
+ collisionPair.m_algorithm->processCollision(&obj0Wrap, &obj1Wrap, dispatchInfo, &contactPointResult);
+ }
+ else
{
- btManifoldResult contactPointResult(&obj0Wrap,&obj1Wrap);
-
- if (dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE)
- {
- //discrete collision detection query
-
- collisionPair.m_algorithm->processCollision(&obj0Wrap,&obj1Wrap,dispatchInfo,&contactPointResult);
- } else
- {
- //continuous collision detection query, time of impact (toi)
- btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0,colObj1,dispatchInfo,&contactPointResult);
- if (dispatchInfo.m_timeOfImpact > toi)
- dispatchInfo.m_timeOfImpact = toi;
-
- }
+ //continuous collision detection query, time of impact (toi)
+ btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0, colObj1, dispatchInfo, &contactPointResult);
+ if (dispatchInfo.m_timeOfImpact > toi)
+ dispatchInfo.m_timeOfImpact = toi;
}
}
-
+ }
}
-
void* btCollisionDispatcher::allocateCollisionAlgorithm(int size)
{
- void* mem = m_collisionAlgorithmPoolAllocator->allocate( size );
- if (NULL == mem)
- {
- //warn user for overflow?
- return btAlignedAlloc(static_cast<size_t>(size), 16);
- }
- return mem;
+ void* mem = m_collisionAlgorithmPoolAllocator->allocate(size);
+ if (NULL == mem)
+ {
+ //warn user for overflow?
+ return btAlignedAlloc(static_cast<size_t>(size), 16);
+ }
+ return mem;
}
void btCollisionDispatcher::freeCollisionAlgorithm(void* ptr)
@@ -316,7 +281,8 @@ void btCollisionDispatcher::freeCollisionAlgorithm(void* ptr)
if (m_collisionAlgorithmPoolAllocator->validPtr(ptr))
{
m_collisionAlgorithmPoolAllocator->freeMemory(ptr);
- } else
+ }
+ else
{
btAlignedFree(ptr);
}
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.h
index b97ee3c1ba..6b9f5e23a5 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.h
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.h
@@ -37,35 +37,30 @@ class btCollisionDispatcher;
///user can override this nearcallback for collision filtering and more finegrained control over collision detection
typedef void (*btNearCallback)(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo);
-
///btCollisionDispatcher supports algorithms that handle ConvexConvex and ConvexConcave collision pairs.
///Time of Impact, Closest Points and Penetration Depth.
class btCollisionDispatcher : public btDispatcher
{
-
protected:
+ int m_dispatcherFlags;
- int m_dispatcherFlags;
+ btAlignedObjectArray<btPersistentManifold*> m_manifoldsPtr;
- btAlignedObjectArray<btPersistentManifold*> m_manifoldsPtr;
+ btManifoldResult m_defaultManifoldResult;
- btManifoldResult m_defaultManifoldResult;
+ btNearCallback m_nearCallback;
- btNearCallback m_nearCallback;
-
- btPoolAllocator* m_collisionAlgorithmPoolAllocator;
+ btPoolAllocator* m_collisionAlgorithmPoolAllocator;
- btPoolAllocator* m_persistentManifoldPoolAllocator;
+ btPoolAllocator* m_persistentManifoldPoolAllocator;
btCollisionAlgorithmCreateFunc* m_doubleDispatchContactPoints[MAX_BROADPHASE_COLLISION_TYPES][MAX_BROADPHASE_COLLISION_TYPES];
btCollisionAlgorithmCreateFunc* m_doubleDispatchClosestPoints[MAX_BROADPHASE_COLLISION_TYPES][MAX_BROADPHASE_COLLISION_TYPES];
- btCollisionConfiguration* m_collisionConfiguration;
-
+ btCollisionConfiguration* m_collisionConfiguration;
public:
-
enum DispatcherFlags
{
CD_STATIC_STATIC_REPORTED = 1,
@@ -73,103 +68,100 @@ public:
CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION = 4
};
- int getDispatcherFlags() const
+ int getDispatcherFlags() const
{
return m_dispatcherFlags;
}
- void setDispatcherFlags(int flags)
+ void setDispatcherFlags(int flags)
{
m_dispatcherFlags = flags;
}
///registerCollisionCreateFunc allows registration of custom/alternative collision create functions
- void registerCollisionCreateFunc(int proxyType0,int proxyType1, btCollisionAlgorithmCreateFunc* createFunc);
+ void registerCollisionCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc* createFunc);
- void registerClosestPointsCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc *createFunc);
+ void registerClosestPointsCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc* createFunc);
- int getNumManifolds() const
- {
- return int( m_manifoldsPtr.size());
+ int getNumManifolds() const
+ {
+ return int(m_manifoldsPtr.size());
}
- btPersistentManifold** getInternalManifoldPointer()
+ btPersistentManifold** getInternalManifoldPointer()
{
- return m_manifoldsPtr.size()? &m_manifoldsPtr[0] : 0;
+ return m_manifoldsPtr.size() ? &m_manifoldsPtr[0] : 0;
}
- btPersistentManifold* getManifoldByIndexInternal(int index)
+ btPersistentManifold* getManifoldByIndexInternal(int index)
{
return m_manifoldsPtr[index];
}
- const btPersistentManifold* getManifoldByIndexInternal(int index) const
+ const btPersistentManifold* getManifoldByIndexInternal(int index) const
{
return m_manifoldsPtr[index];
}
- btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration);
+ btCollisionDispatcher(btCollisionConfiguration* collisionConfiguration);
virtual ~btCollisionDispatcher();
- virtual btPersistentManifold* getNewManifold(const btCollisionObject* b0,const btCollisionObject* b1);
-
- virtual void releaseManifold(btPersistentManifold* manifold);
+ virtual btPersistentManifold* getNewManifold(const btCollisionObject* b0, const btCollisionObject* b1);
+ virtual void releaseManifold(btPersistentManifold* manifold);
virtual void clearManifold(btPersistentManifold* manifold);
- btCollisionAlgorithm* findAlgorithm(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btPersistentManifold* sharedManifold, ebtDispatcherQueryType queryType);
-
- virtual bool needsCollision(const btCollisionObject* body0,const btCollisionObject* body1);
-
- virtual bool needsResponse(const btCollisionObject* body0,const btCollisionObject* body1);
-
- virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) ;
+ btCollisionAlgorithm* findAlgorithm(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, btPersistentManifold* sharedManifold, ebtDispatcherQueryType queryType);
+
+ virtual bool needsCollision(const btCollisionObject* body0, const btCollisionObject* body1);
+
+ virtual bool needsResponse(const btCollisionObject* body0, const btCollisionObject* body1);
- void setNearCallback(btNearCallback nearCallback)
+ virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache, const btDispatcherInfo& dispatchInfo, btDispatcher* dispatcher);
+
+ void setNearCallback(btNearCallback nearCallback)
{
- m_nearCallback = nearCallback;
+ m_nearCallback = nearCallback;
}
- btNearCallback getNearCallback() const
+ btNearCallback getNearCallback() const
{
return m_nearCallback;
}
//by default, Bullet will use this near callback
- static void defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo);
+ static void defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo);
- virtual void* allocateCollisionAlgorithm(int size);
+ virtual void* allocateCollisionAlgorithm(int size);
- virtual void freeCollisionAlgorithm(void* ptr);
+ virtual void freeCollisionAlgorithm(void* ptr);
- btCollisionConfiguration* getCollisionConfiguration()
+ btCollisionConfiguration* getCollisionConfiguration()
{
return m_collisionConfiguration;
}
- const btCollisionConfiguration* getCollisionConfiguration() const
+ const btCollisionConfiguration* getCollisionConfiguration() const
{
return m_collisionConfiguration;
}
- void setCollisionConfiguration(btCollisionConfiguration* config)
+ void setCollisionConfiguration(btCollisionConfiguration* config)
{
m_collisionConfiguration = config;
}
- virtual btPoolAllocator* getInternalManifoldPool()
+ virtual btPoolAllocator* getInternalManifoldPool()
{
return m_persistentManifoldPoolAllocator;
}
- virtual const btPoolAllocator* getInternalManifoldPool() const
+ virtual const btPoolAllocator* getInternalManifoldPool() const
{
return m_persistentManifoldPoolAllocator;
}
-
};
-#endif //BT_COLLISION__DISPATCHER_H
-
+#endif //BT_COLLISION__DISPATCHER_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.cpp
index 075860c503..6fe56538d2 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.cpp
@@ -13,8 +13,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
-
#include "btCollisionDispatcherMt.h"
#include "LinearMath/btQuickprof.h"
@@ -27,138 +25,132 @@ subject to the following restrictions:
#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h"
#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
-
-btCollisionDispatcherMt::btCollisionDispatcherMt( btCollisionConfiguration* config, int grainSize )
- : btCollisionDispatcher( config )
+btCollisionDispatcherMt::btCollisionDispatcherMt(btCollisionConfiguration* config, int grainSize)
+ : btCollisionDispatcher(config)
{
- m_batchUpdating = false;
- m_grainSize = grainSize; // iterations per task
+ m_batchUpdating = false;
+ m_grainSize = grainSize; // iterations per task
}
-
-btPersistentManifold* btCollisionDispatcherMt::getNewManifold( const btCollisionObject* body0, const btCollisionObject* body1 )
+btPersistentManifold* btCollisionDispatcherMt::getNewManifold(const btCollisionObject* body0, const btCollisionObject* body1)
{
- //optional relative contact breaking threshold, turned on by default (use setDispatcherFlags to switch off feature for improved performance)
-
- btScalar contactBreakingThreshold = ( m_dispatcherFlags & btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD ) ?
- btMin( body0->getCollisionShape()->getContactBreakingThreshold( gContactBreakingThreshold ), body1->getCollisionShape()->getContactBreakingThreshold( gContactBreakingThreshold ) )
- : gContactBreakingThreshold;
-
- btScalar contactProcessingThreshold = btMin( body0->getContactProcessingThreshold(), body1->getContactProcessingThreshold() );
-
- void* mem = m_persistentManifoldPoolAllocator->allocate( sizeof( btPersistentManifold ) );
- if ( NULL == mem )
- {
- //we got a pool memory overflow, by default we fallback to dynamically allocate memory. If we require a contiguous contact pool then assert.
- if ( ( m_dispatcherFlags&CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION ) == 0 )
- {
- mem = btAlignedAlloc( sizeof( btPersistentManifold ), 16 );
- }
- else
- {
- btAssert( 0 );
- //make sure to increase the m_defaultMaxPersistentManifoldPoolSize in the btDefaultCollisionConstructionInfo/btDefaultCollisionConfiguration
- return 0;
- }
- }
- btPersistentManifold* manifold = new( mem ) btPersistentManifold( body0, body1, 0, contactBreakingThreshold, contactProcessingThreshold );
- if ( !m_batchUpdating )
- {
- // batch updater will update manifold pointers array after finishing, so
- // only need to update array when not batch-updating
- //btAssert( !btThreadsAreRunning() );
- manifold->m_index1a = m_manifoldsPtr.size();
- m_manifoldsPtr.push_back( manifold );
- }
-
- return manifold;
+ //optional relative contact breaking threshold, turned on by default (use setDispatcherFlags to switch off feature for improved performance)
+
+ btScalar contactBreakingThreshold = (m_dispatcherFlags & btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD) ? btMin(body0->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold), body1->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold))
+ : gContactBreakingThreshold;
+
+ btScalar contactProcessingThreshold = btMin(body0->getContactProcessingThreshold(), body1->getContactProcessingThreshold());
+
+ void* mem = m_persistentManifoldPoolAllocator->allocate(sizeof(btPersistentManifold));
+ if (NULL == mem)
+ {
+ //we got a pool memory overflow, by default we fallback to dynamically allocate memory. If we require a contiguous contact pool then assert.
+ if ((m_dispatcherFlags & CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION) == 0)
+ {
+ mem = btAlignedAlloc(sizeof(btPersistentManifold), 16);
+ }
+ else
+ {
+ btAssert(0);
+ //make sure to increase the m_defaultMaxPersistentManifoldPoolSize in the btDefaultCollisionConstructionInfo/btDefaultCollisionConfiguration
+ return 0;
+ }
+ }
+ btPersistentManifold* manifold = new (mem) btPersistentManifold(body0, body1, 0, contactBreakingThreshold, contactProcessingThreshold);
+ if (!m_batchUpdating)
+ {
+ // batch updater will update manifold pointers array after finishing, so
+ // only need to update array when not batch-updating
+ //btAssert( !btThreadsAreRunning() );
+ manifold->m_index1a = m_manifoldsPtr.size();
+ m_manifoldsPtr.push_back(manifold);
+ }
+
+ return manifold;
}
-void btCollisionDispatcherMt::releaseManifold( btPersistentManifold* manifold )
+void btCollisionDispatcherMt::releaseManifold(btPersistentManifold* manifold)
{
- clearManifold( manifold );
- //btAssert( !btThreadsAreRunning() );
- if ( !m_batchUpdating )
- {
- // batch updater will update manifold pointers array after finishing, so
- // only need to update array when not batch-updating
- int findIndex = manifold->m_index1a;
- btAssert( findIndex < m_manifoldsPtr.size() );
- m_manifoldsPtr.swap( findIndex, m_manifoldsPtr.size() - 1 );
- m_manifoldsPtr[ findIndex ]->m_index1a = findIndex;
- m_manifoldsPtr.pop_back();
- }
-
- manifold->~btPersistentManifold();
- if ( m_persistentManifoldPoolAllocator->validPtr( manifold ) )
- {
- m_persistentManifoldPoolAllocator->freeMemory( manifold );
- }
- else
- {
- btAlignedFree( manifold );
- }
+ clearManifold(manifold);
+ //btAssert( !btThreadsAreRunning() );
+ if (!m_batchUpdating)
+ {
+ // batch updater will update manifold pointers array after finishing, so
+ // only need to update array when not batch-updating
+ int findIndex = manifold->m_index1a;
+ btAssert(findIndex < m_manifoldsPtr.size());
+ m_manifoldsPtr.swap(findIndex, m_manifoldsPtr.size() - 1);
+ m_manifoldsPtr[findIndex]->m_index1a = findIndex;
+ m_manifoldsPtr.pop_back();
+ }
+
+ manifold->~btPersistentManifold();
+ if (m_persistentManifoldPoolAllocator->validPtr(manifold))
+ {
+ m_persistentManifoldPoolAllocator->freeMemory(manifold);
+ }
+ else
+ {
+ btAlignedFree(manifold);
+ }
}
struct CollisionDispatcherUpdater : public btIParallelForBody
{
- btBroadphasePair* mPairArray;
- btNearCallback mCallback;
- btCollisionDispatcher* mDispatcher;
- const btDispatcherInfo* mInfo;
-
- CollisionDispatcherUpdater()
- {
- mPairArray = NULL;
- mCallback = NULL;
- mDispatcher = NULL;
- mInfo = NULL;
- }
- void forLoop( int iBegin, int iEnd ) const
- {
- for ( int i = iBegin; i < iEnd; ++i )
- {
- btBroadphasePair* pair = &mPairArray[ i ];
- mCallback( *pair, *mDispatcher, *mInfo );
- }
- }
+ btBroadphasePair* mPairArray;
+ btNearCallback mCallback;
+ btCollisionDispatcher* mDispatcher;
+ const btDispatcherInfo* mInfo;
+
+ CollisionDispatcherUpdater()
+ {
+ mPairArray = NULL;
+ mCallback = NULL;
+ mDispatcher = NULL;
+ mInfo = NULL;
+ }
+ void forLoop(int iBegin, int iEnd) const
+ {
+ for (int i = iBegin; i < iEnd; ++i)
+ {
+ btBroadphasePair* pair = &mPairArray[i];
+ mCallback(*pair, *mDispatcher, *mInfo);
+ }
+ }
};
-
-void btCollisionDispatcherMt::dispatchAllCollisionPairs( btOverlappingPairCache* pairCache, const btDispatcherInfo& info, btDispatcher* dispatcher )
+void btCollisionDispatcherMt::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache, const btDispatcherInfo& info, btDispatcher* dispatcher)
{
- int pairCount = pairCache->getNumOverlappingPairs();
- if ( pairCount == 0 )
- {
- return;
- }
- CollisionDispatcherUpdater updater;
- updater.mCallback = getNearCallback();
- updater.mPairArray = pairCache->getOverlappingPairArrayPtr();
- updater.mDispatcher = this;
- updater.mInfo = &info;
-
- m_batchUpdating = true;
- btParallelFor( 0, pairCount, m_grainSize, updater );
- m_batchUpdating = false;
-
- // reconstruct the manifolds array to ensure determinism
- m_manifoldsPtr.resizeNoInitialize( 0 );
-
- btBroadphasePair* pairs = pairCache->getOverlappingPairArrayPtr();
- for ( int i = 0; i < pairCount; ++i )
- {
- if (btCollisionAlgorithm* algo = pairs[ i ].m_algorithm)
- {
- algo->getAllContactManifolds( m_manifoldsPtr );
- }
- }
-
- // update the indices (used when releasing manifolds)
- for ( int i = 0; i < m_manifoldsPtr.size(); ++i )
- {
- m_manifoldsPtr[ i ]->m_index1a = i;
- }
+ int pairCount = pairCache->getNumOverlappingPairs();
+ if (pairCount == 0)
+ {
+ return;
+ }
+ CollisionDispatcherUpdater updater;
+ updater.mCallback = getNearCallback();
+ updater.mPairArray = pairCache->getOverlappingPairArrayPtr();
+ updater.mDispatcher = this;
+ updater.mInfo = &info;
+
+ m_batchUpdating = true;
+ btParallelFor(0, pairCount, m_grainSize, updater);
+ m_batchUpdating = false;
+
+ // reconstruct the manifolds array to ensure determinism
+ m_manifoldsPtr.resizeNoInitialize(0);
+
+ btBroadphasePair* pairs = pairCache->getOverlappingPairArrayPtr();
+ for (int i = 0; i < pairCount; ++i)
+ {
+ if (btCollisionAlgorithm* algo = pairs[i].m_algorithm)
+ {
+ algo->getAllContactManifolds(m_manifoldsPtr);
+ }
+ }
+
+ // update the indices (used when releasing manifolds)
+ for (int i = 0; i < m_manifoldsPtr.size(); ++i)
+ {
+ m_manifoldsPtr[i]->m_index1a = i;
+ }
}
-
-
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.h
index f1d7eafdc9..28eba7f32a 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.h
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.h
@@ -19,21 +19,19 @@ subject to the following restrictions:
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "LinearMath/btThreads.h"
-
class btCollisionDispatcherMt : public btCollisionDispatcher
{
public:
- btCollisionDispatcherMt( btCollisionConfiguration* config, int grainSize = 40 );
+ btCollisionDispatcherMt(btCollisionConfiguration* config, int grainSize = 40);
- virtual btPersistentManifold* getNewManifold( const btCollisionObject* body0, const btCollisionObject* body1 ) BT_OVERRIDE;
- virtual void releaseManifold( btPersistentManifold* manifold ) BT_OVERRIDE;
+ virtual btPersistentManifold* getNewManifold(const btCollisionObject* body0, const btCollisionObject* body1) BT_OVERRIDE;
+ virtual void releaseManifold(btPersistentManifold* manifold) BT_OVERRIDE;
- virtual void dispatchAllCollisionPairs( btOverlappingPairCache* pairCache, const btDispatcherInfo& info, btDispatcher* dispatcher ) BT_OVERRIDE;
+ virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache, const btDispatcherInfo& info, btDispatcher* dispatcher) BT_OVERRIDE;
protected:
- bool m_batchUpdating;
- int m_grainSize;
+ bool m_batchUpdating;
+ int m_grainSize;
};
-#endif //BT_COLLISION_DISPATCHER_MT_H
-
+#endif //BT_COLLISION_DISPATCHER_MT_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObject.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObject.cpp
index 05f96a14bc..98a02d0c45 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObject.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObject.cpp
@@ -13,42 +13,41 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#include "btCollisionObject.h"
#include "LinearMath/btSerializer.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
btCollisionObject::btCollisionObject()
- : m_interpolationLinearVelocity(0.f, 0.f, 0.f),
- m_interpolationAngularVelocity(0.f, 0.f, 0.f),
- m_anisotropicFriction(1.f,1.f,1.f),
- m_hasAnisotropicFriction(false),
- m_contactProcessingThreshold(BT_LARGE_FLOAT),
- m_broadphaseHandle(0),
- m_collisionShape(0),
- m_extensionPointer(0),
- m_rootCollisionShape(0),
- m_collisionFlags(btCollisionObject::CF_STATIC_OBJECT),
- m_islandTag1(-1),
- m_companionId(-1),
- m_worldArrayIndex(-1),
- m_activationState1(1),
- m_deactivationTime(btScalar(0.)),
- m_friction(btScalar(0.5)),
- m_restitution(btScalar(0.)),
- m_rollingFriction(0.0f),
- m_spinningFriction(0.f),
- m_contactDamping(.1),
- m_contactStiffness(BT_LARGE_FLOAT),
- m_internalType(CO_COLLISION_OBJECT),
- m_userObjectPointer(0),
- m_userIndex2(-1),
- m_userIndex(-1),
- m_hitFraction(btScalar(1.)),
- m_ccdSweptSphereRadius(btScalar(0.)),
- m_ccdMotionThreshold(btScalar(0.)),
- m_checkCollideWith(false),
- m_updateRevision(0)
+ : m_interpolationLinearVelocity(0.f, 0.f, 0.f),
+ m_interpolationAngularVelocity(0.f, 0.f, 0.f),
+ m_anisotropicFriction(1.f, 1.f, 1.f),
+ m_hasAnisotropicFriction(false),
+ m_contactProcessingThreshold(BT_LARGE_FLOAT),
+ m_broadphaseHandle(0),
+ m_collisionShape(0),
+ m_extensionPointer(0),
+ m_rootCollisionShape(0),
+ m_collisionFlags(btCollisionObject::CF_STATIC_OBJECT),
+ m_islandTag1(-1),
+ m_companionId(-1),
+ m_worldArrayIndex(-1),
+ m_activationState1(1),
+ m_deactivationTime(btScalar(0.)),
+ m_friction(btScalar(0.5)),
+ m_restitution(btScalar(0.)),
+ m_rollingFriction(0.0f),
+ m_spinningFriction(0.f),
+ m_contactDamping(.1),
+ m_contactStiffness(BT_LARGE_FLOAT),
+ m_internalType(CO_COLLISION_OBJECT),
+ m_userObjectPointer(0),
+ m_userIndex2(-1),
+ m_userIndex(-1),
+ m_hitFraction(btScalar(1.)),
+ m_ccdSweptSphereRadius(btScalar(0.)),
+ m_ccdMotionThreshold(btScalar(0.)),
+ m_checkCollideWith(false),
+ m_updateRevision(0)
{
m_worldTransform.setIdentity();
m_interpolationWorldTransform.setIdentity();
@@ -59,8 +58,8 @@ btCollisionObject::~btCollisionObject()
}
void btCollisionObject::setActivationState(int newState) const
-{
- if ( (m_activationState1 != DISABLE_DEACTIVATION) && (m_activationState1 != DISABLE_SIMULATION))
+{
+ if ((m_activationState1 != DISABLE_DEACTIVATION) && (m_activationState1 != DISABLE_SIMULATION))
m_activationState1 = newState;
}
@@ -71,7 +70,7 @@ void btCollisionObject::forceActivationState(int newState) const
void btCollisionObject::activate(bool forceActivation) const
{
- if (forceActivation || !(m_collisionFlags & (CF_STATIC_OBJECT|CF_KINEMATIC_OBJECT)))
+ if (forceActivation || !(m_collisionFlags & (CF_STATIC_OBJECT | CF_KINEMATIC_OBJECT)))
{
setActivationState(ACTIVE_TAG);
m_deactivationTime = btScalar(0.);
@@ -80,7 +79,6 @@ void btCollisionObject::activate(bool forceActivation) const
const char* btCollisionObject::serialize(void* dataBuffer, btSerializer* serializer) const
{
-
btCollisionObjectData* dataOut = (btCollisionObjectData*)dataBuffer;
m_worldTransform.serialize(dataOut->m_worldTransform);
@@ -92,7 +90,7 @@ const char* btCollisionObject::serialize(void* dataBuffer, btSerializer* seriali
dataOut->m_contactProcessingThreshold = m_contactProcessingThreshold;
dataOut->m_broadphaseHandle = 0;
dataOut->m_collisionShape = serializer->getUniquePointer(m_collisionShape);
- dataOut->m_rootCollisionShape = 0;//@todo
+ dataOut->m_rootCollisionShape = 0; //@todo
dataOut->m_collisionFlags = m_collisionFlags;
dataOut->m_islandTag1 = m_islandTag1;
dataOut->m_companionId = m_companionId;
@@ -104,8 +102,8 @@ const char* btCollisionObject::serialize(void* dataBuffer, btSerializer* seriali
dataOut->m_contactStiffness = m_contactStiffness;
dataOut->m_restitution = m_restitution;
dataOut->m_internalType = m_internalType;
-
- char* name = (char*) serializer->findNameForPointer(this);
+
+ char* name = (char*)serializer->findNameForPointer(this);
dataOut->m_name = (char*)serializer->getUniquePointer(name);
if (dataOut->m_name)
{
@@ -130,11 +128,10 @@ const char* btCollisionObject::serialize(void* dataBuffer, btSerializer* seriali
return btCollisionObjectDataName;
}
-
void btCollisionObject::serializeSingleObject(class btSerializer* serializer) const
{
int len = calculateSerializeBufferSize();
- btChunk* chunk = serializer->allocate(len,1);
+ btChunk* chunk = serializer->allocate(len, 1);
const char* structType = serialize(chunk->m_oldPtr, serializer);
- serializer->finalizeChunk(chunk,structType,BT_COLLISIONOBJECT_CODE,(void*)this);
+ serializer->finalizeChunk(chunk, structType, BT_COLLISIONOBJECT_CODE, (void*)this);
}
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObject.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObject.h
index 135f8a033c..56b3d89e56 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObject.h
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObject.h
@@ -25,8 +25,8 @@ subject to the following restrictions:
#define DISABLE_DEACTIVATION 4
#define DISABLE_SIMULATION 5
-struct btBroadphaseProxy;
-class btCollisionShape;
+struct btBroadphaseProxy;
+class btCollisionShape;
struct btCollisionShapeData;
#include "LinearMath/btMotionState.h"
#include "LinearMath/btAlignedAllocator.h"
@@ -42,123 +42,118 @@ typedef btAlignedObjectArray<class btCollisionObject*> btCollisionObjectArray;
#define btCollisionObjectDataName "btCollisionObjectFloatData"
#endif
-
-/// btCollisionObject can be used to manage collision detection objects.
+/// btCollisionObject can be used to manage collision detection objects.
/// btCollisionObject maintains all information that is needed for a collision detection: Shape, Transform and AABB proxy.
/// They can be added to the btCollisionWorld.
-ATTRIBUTE_ALIGNED16(class) btCollisionObject
+ATTRIBUTE_ALIGNED16(class)
+btCollisionObject
{
-
protected:
-
- btTransform m_worldTransform;
+ btTransform m_worldTransform;
///m_interpolationWorldTransform is used for CCD and interpolation
///it can be either previous or future (predicted) transform
- btTransform m_interpolationWorldTransform;
- //those two are experimental: just added for bullet time effect, so you can still apply impulses (directly modifying velocities)
+ btTransform m_interpolationWorldTransform;
+ //those two are experimental: just added for bullet time effect, so you can still apply impulses (directly modifying velocities)
//without destroying the continuous interpolated motion (which uses this interpolation velocities)
- btVector3 m_interpolationLinearVelocity;
- btVector3 m_interpolationAngularVelocity;
-
- btVector3 m_anisotropicFriction;
- int m_hasAnisotropicFriction;
- btScalar m_contactProcessingThreshold;
-
- btBroadphaseProxy* m_broadphaseHandle;
- btCollisionShape* m_collisionShape;
+ btVector3 m_interpolationLinearVelocity;
+ btVector3 m_interpolationAngularVelocity;
+
+ btVector3 m_anisotropicFriction;
+ int m_hasAnisotropicFriction;
+ btScalar m_contactProcessingThreshold;
+
+ btBroadphaseProxy* m_broadphaseHandle;
+ btCollisionShape* m_collisionShape;
///m_extensionPointer is used by some internal low-level Bullet extensions.
- void* m_extensionPointer;
-
+ void* m_extensionPointer;
+
///m_rootCollisionShape is temporarily used to store the original collision shape
///The m_collisionShape might be temporarily replaced by a child collision shape during collision detection purposes
///If it is NULL, the m_collisionShape is not temporarily replaced.
- btCollisionShape* m_rootCollisionShape;
+ btCollisionShape* m_rootCollisionShape;
- int m_collisionFlags;
+ int m_collisionFlags;
- int m_islandTag1;
- int m_companionId;
- int m_worldArrayIndex; // index of object in world's collisionObjects array
+ int m_islandTag1;
+ int m_companionId;
+ int m_worldArrayIndex; // index of object in world's collisionObjects array
- mutable int m_activationState1;
- mutable btScalar m_deactivationTime;
+ mutable int m_activationState1;
+ mutable btScalar m_deactivationTime;
- btScalar m_friction;
- btScalar m_restitution;
- btScalar m_rollingFriction;//torsional friction orthogonal to contact normal (useful to stop spheres rolling forever)
- btScalar m_spinningFriction; // torsional friction around the contact normal (useful for grasping)
- btScalar m_contactDamping;
- btScalar m_contactStiffness;
-
-
+ btScalar m_friction;
+ btScalar m_restitution;
+ btScalar m_rollingFriction; //torsional friction orthogonal to contact normal (useful to stop spheres rolling forever)
+ btScalar m_spinningFriction; // torsional friction around the contact normal (useful for grasping)
+ btScalar m_contactDamping;
+ btScalar m_contactStiffness;
///m_internalType is reserved to distinguish Bullet's btCollisionObject, btRigidBody, btSoftBody, btGhostObject etc.
///do not assign your own m_internalType unless you write a new dynamics object class.
- int m_internalType;
+ int m_internalType;
///users can point to their objects, m_userPointer is not used by Bullet, see setUserPointer/getUserPointer
- void* m_userObjectPointer;
+ void* m_userObjectPointer;
- int m_userIndex2;
-
- int m_userIndex;
+ int m_userIndex2;
+
+ int m_userIndex;
///time of impact calculation
- btScalar m_hitFraction;
-
+ btScalar m_hitFraction;
+
///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm::
- btScalar m_ccdSweptSphereRadius;
+ btScalar m_ccdSweptSphereRadius;
/// Don't do continuous collision detection if the motion (in one step) is less then m_ccdMotionThreshold
- btScalar m_ccdMotionThreshold;
-
+ btScalar m_ccdMotionThreshold;
+
/// If some object should have elaborate collision filtering by sub-classes
- int m_checkCollideWith;
+ int m_checkCollideWith;
btAlignedObjectArray<const btCollisionObject*> m_objectsWithoutCollisionCheck;
///internal update revision number. It will be increased when the object changes. This allows some subsystems to perform lazy evaluation.
- int m_updateRevision;
+ int m_updateRevision;
- btVector3 m_customDebugColorRGB;
+ btVector3 m_customDebugColorRGB;
public:
-
BT_DECLARE_ALIGNED_ALLOCATOR();
enum CollisionFlags
{
- CF_STATIC_OBJECT= 1,
- CF_KINEMATIC_OBJECT= 2,
+ CF_STATIC_OBJECT = 1,
+ CF_KINEMATIC_OBJECT = 2,
CF_NO_CONTACT_RESPONSE = 4,
- CF_CUSTOM_MATERIAL_CALLBACK = 8,//this allows per-triangle material (friction/restitution)
+ CF_CUSTOM_MATERIAL_CALLBACK = 8, //this allows per-triangle material (friction/restitution)
CF_CHARACTER_OBJECT = 16,
- CF_DISABLE_VISUALIZE_OBJECT = 32, //disable debug drawing
- CF_DISABLE_SPU_COLLISION_PROCESSING = 64,//disable parallel/SPU processing
+ CF_DISABLE_VISUALIZE_OBJECT = 32, //disable debug drawing
+ CF_DISABLE_SPU_COLLISION_PROCESSING = 64, //disable parallel/SPU processing
CF_HAS_CONTACT_STIFFNESS_DAMPING = 128,
CF_HAS_CUSTOM_DEBUG_RENDERING_COLOR = 256,
CF_HAS_FRICTION_ANCHOR = 512,
CF_HAS_COLLISION_SOUND_TRIGGER = 1024
};
- enum CollisionObjectTypes
+ enum CollisionObjectTypes
{
- CO_COLLISION_OBJECT =1,
- CO_RIGID_BODY=2,
+ CO_COLLISION_OBJECT = 1,
+ CO_RIGID_BODY = 2,
///CO_GHOST_OBJECT keeps track of all objects overlapping its AABB and that pass its collision filter
///It is useful for collision sensors, explosion objects, character controller etc.
- CO_GHOST_OBJECT=4,
- CO_SOFT_BODY=8,
- CO_HF_FLUID=16,
- CO_USER_TYPE=32,
- CO_FEATHERSTONE_LINK=64
+ CO_GHOST_OBJECT = 4,
+ CO_SOFT_BODY = 8,
+ CO_HF_FLUID = 16,
+ CO_USER_TYPE = 32,
+ CO_FEATHERSTONE_LINK = 64
};
enum AnisotropicFrictionFlags
{
- CF_ANISOTROPIC_FRICTION_DISABLED=0,
+ CF_ANISOTROPIC_FRICTION_DISABLED = 0,
CF_ANISOTROPIC_FRICTION = 1,
CF_ANISOTROPIC_ROLLING_FRICTION = 2
};
@@ -166,76 +161,77 @@ public:
SIMD_FORCE_INLINE bool mergesSimulationIslands() const
{
///static objects, kinematic and object without contact response don't merge islands
- return ((m_collisionFlags & (CF_STATIC_OBJECT | CF_KINEMATIC_OBJECT | CF_NO_CONTACT_RESPONSE) )==0);
+ return ((m_collisionFlags & (CF_STATIC_OBJECT | CF_KINEMATIC_OBJECT | CF_NO_CONTACT_RESPONSE)) == 0);
}
const btVector3& getAnisotropicFriction() const
{
return m_anisotropicFriction;
}
- void setAnisotropicFriction(const btVector3& anisotropicFriction, int frictionMode = CF_ANISOTROPIC_FRICTION)
+ void setAnisotropicFriction(const btVector3& anisotropicFriction, int frictionMode = CF_ANISOTROPIC_FRICTION)
{
m_anisotropicFriction = anisotropicFriction;
- bool isUnity = (anisotropicFriction[0]!=1.f) || (anisotropicFriction[1]!=1.f) || (anisotropicFriction[2]!=1.f);
- m_hasAnisotropicFriction = isUnity?frictionMode : 0;
+ bool isUnity = (anisotropicFriction[0] != 1.f) || (anisotropicFriction[1] != 1.f) || (anisotropicFriction[2] != 1.f);
+ m_hasAnisotropicFriction = isUnity ? frictionMode : 0;
}
- bool hasAnisotropicFriction(int frictionMode = CF_ANISOTROPIC_FRICTION) const
+ bool hasAnisotropicFriction(int frictionMode = CF_ANISOTROPIC_FRICTION) const
{
- return (m_hasAnisotropicFriction&frictionMode)!=0;
+ return (m_hasAnisotropicFriction & frictionMode) != 0;
}
///the constraint solver can discard solving contacts, if the distance is above this threshold. 0 by default.
///Note that using contacts with positive distance can improve stability. It increases, however, the chance of colliding with degerate contacts, such as 'interior' triangle edges
- void setContactProcessingThreshold( btScalar contactProcessingThreshold)
+ void setContactProcessingThreshold(btScalar contactProcessingThreshold)
{
m_contactProcessingThreshold = contactProcessingThreshold;
}
- btScalar getContactProcessingThreshold() const
+ btScalar getContactProcessingThreshold() const
{
return m_contactProcessingThreshold;
}
- SIMD_FORCE_INLINE bool isStaticObject() const {
+ SIMD_FORCE_INLINE bool isStaticObject() const
+ {
return (m_collisionFlags & CF_STATIC_OBJECT) != 0;
}
- SIMD_FORCE_INLINE bool isKinematicObject() const
+ SIMD_FORCE_INLINE bool isKinematicObject() const
{
return (m_collisionFlags & CF_KINEMATIC_OBJECT) != 0;
}
- SIMD_FORCE_INLINE bool isStaticOrKinematicObject() const
+ SIMD_FORCE_INLINE bool isStaticOrKinematicObject() const
{
- return (m_collisionFlags & (CF_KINEMATIC_OBJECT | CF_STATIC_OBJECT)) != 0 ;
+ return (m_collisionFlags & (CF_KINEMATIC_OBJECT | CF_STATIC_OBJECT)) != 0;
}
- SIMD_FORCE_INLINE bool hasContactResponse() const {
- return (m_collisionFlags & CF_NO_CONTACT_RESPONSE)==0;
+ SIMD_FORCE_INLINE bool hasContactResponse() const
+ {
+ return (m_collisionFlags & CF_NO_CONTACT_RESPONSE) == 0;
}
-
btCollisionObject();
virtual ~btCollisionObject();
- virtual void setCollisionShape(btCollisionShape* collisionShape)
+ virtual void setCollisionShape(btCollisionShape * collisionShape)
{
m_updateRevision++;
m_collisionShape = collisionShape;
m_rootCollisionShape = collisionShape;
}
- SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const
+ SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const
{
return m_collisionShape;
}
- SIMD_FORCE_INLINE btCollisionShape* getCollisionShape()
+ SIMD_FORCE_INLINE btCollisionShape* getCollisionShape()
{
return m_collisionShape;
}
- void setIgnoreCollisionCheck(const btCollisionObject* co, bool ignoreCollisionCheck)
+ void setIgnoreCollisionCheck(const btCollisionObject* co, bool ignoreCollisionCheck)
{
if (ignoreCollisionCheck)
{
@@ -253,7 +249,7 @@ public:
m_checkCollideWith = m_objectsWithoutCollisionCheck.size() > 0;
}
- virtual bool checkCollideWithOverride(const btCollisionObject* co) const
+ virtual bool checkCollideWithOverride(const btCollisionObject* co) const
{
int index = m_objectsWithoutCollisionCheck.findLinearSearch(co);
if (index < m_objectsWithoutCollisionCheck.size())
@@ -263,317 +259,309 @@ public:
return true;
}
-
-
-
- ///Avoid using this internal API call, the extension pointer is used by some Bullet extensions.
+ ///Avoid using this internal API call, the extension pointer is used by some Bullet extensions.
///If you need to store your own user pointer, use 'setUserPointer/getUserPointer' instead.
- void* internalGetExtensionPointer() const
+ void* internalGetExtensionPointer() const
{
return m_extensionPointer;
}
///Avoid using this internal API call, the extension pointer is used by some Bullet extensions
///If you need to store your own user pointer, use 'setUserPointer/getUserPointer' instead.
- void internalSetExtensionPointer(void* pointer)
+ void internalSetExtensionPointer(void* pointer)
{
m_extensionPointer = pointer;
}
- SIMD_FORCE_INLINE int getActivationState() const { return m_activationState1;}
-
+ SIMD_FORCE_INLINE int getActivationState() const { return m_activationState1; }
+
void setActivationState(int newState) const;
- void setDeactivationTime(btScalar time)
+ void setDeactivationTime(btScalar time)
{
m_deactivationTime = time;
}
- btScalar getDeactivationTime() const
+ btScalar getDeactivationTime() const
{
return m_deactivationTime;
}
void forceActivationState(int newState) const;
- void activate(bool forceActivation = false) const;
+ void activate(bool forceActivation = false) const;
SIMD_FORCE_INLINE bool isActive() const
{
return ((getActivationState() != ISLAND_SLEEPING) && (getActivationState() != DISABLE_SIMULATION));
}
- void setRestitution(btScalar rest)
+ void setRestitution(btScalar rest)
{
m_updateRevision++;
m_restitution = rest;
}
- btScalar getRestitution() const
+ btScalar getRestitution() const
{
return m_restitution;
}
- void setFriction(btScalar frict)
+ void setFriction(btScalar frict)
{
m_updateRevision++;
m_friction = frict;
}
- btScalar getFriction() const
+ btScalar getFriction() const
{
return m_friction;
}
- void setRollingFriction(btScalar frict)
+ void setRollingFriction(btScalar frict)
{
m_updateRevision++;
m_rollingFriction = frict;
}
- btScalar getRollingFriction() const
+ btScalar getRollingFriction() const
{
return m_rollingFriction;
}
- void setSpinningFriction(btScalar frict)
- {
- m_updateRevision++;
- m_spinningFriction = frict;
- }
- btScalar getSpinningFriction() const
- {
- return m_spinningFriction;
- }
- void setContactStiffnessAndDamping(btScalar stiffness, btScalar damping)
+ void setSpinningFriction(btScalar frict)
+ {
+ m_updateRevision++;
+ m_spinningFriction = frict;
+ }
+ btScalar getSpinningFriction() const
+ {
+ return m_spinningFriction;
+ }
+ void setContactStiffnessAndDamping(btScalar stiffness, btScalar damping)
{
m_updateRevision++;
m_contactStiffness = stiffness;
m_contactDamping = damping;
-
- m_collisionFlags |=CF_HAS_CONTACT_STIFFNESS_DAMPING;
-
- //avoid divisions by zero...
- if (m_contactStiffness< SIMD_EPSILON)
- {
- m_contactStiffness = SIMD_EPSILON;
- }
- }
-
- btScalar getContactStiffness() const
+
+ m_collisionFlags |= CF_HAS_CONTACT_STIFFNESS_DAMPING;
+
+ //avoid divisions by zero...
+ if (m_contactStiffness < SIMD_EPSILON)
+ {
+ m_contactStiffness = SIMD_EPSILON;
+ }
+ }
+
+ btScalar getContactStiffness() const
{
return m_contactStiffness;
}
-
- btScalar getContactDamping() const
+
+ btScalar getContactDamping() const
{
return m_contactDamping;
}
-
+
///reserved for Bullet internal usage
- int getInternalType() const
+ int getInternalType() const
{
return m_internalType;
}
- btTransform& getWorldTransform()
+ btTransform& getWorldTransform()
{
return m_worldTransform;
}
- const btTransform& getWorldTransform() const
+ const btTransform& getWorldTransform() const
{
return m_worldTransform;
}
- void setWorldTransform(const btTransform& worldTrans)
+ void setWorldTransform(const btTransform& worldTrans)
{
m_updateRevision++;
m_worldTransform = worldTrans;
}
-
- SIMD_FORCE_INLINE btBroadphaseProxy* getBroadphaseHandle()
+ SIMD_FORCE_INLINE btBroadphaseProxy* getBroadphaseHandle()
{
return m_broadphaseHandle;
}
- SIMD_FORCE_INLINE const btBroadphaseProxy* getBroadphaseHandle() const
+ SIMD_FORCE_INLINE const btBroadphaseProxy* getBroadphaseHandle() const
{
return m_broadphaseHandle;
}
- void setBroadphaseHandle(btBroadphaseProxy* handle)
+ void setBroadphaseHandle(btBroadphaseProxy * handle)
{
m_broadphaseHandle = handle;
}
-
- const btTransform& getInterpolationWorldTransform() const
+ const btTransform& getInterpolationWorldTransform() const
{
return m_interpolationWorldTransform;
}
- btTransform& getInterpolationWorldTransform()
+ btTransform& getInterpolationWorldTransform()
{
return m_interpolationWorldTransform;
}
- void setInterpolationWorldTransform(const btTransform& trans)
+ void setInterpolationWorldTransform(const btTransform& trans)
{
m_updateRevision++;
m_interpolationWorldTransform = trans;
}
- void setInterpolationLinearVelocity(const btVector3& linvel)
+ void setInterpolationLinearVelocity(const btVector3& linvel)
{
m_updateRevision++;
m_interpolationLinearVelocity = linvel;
}
- void setInterpolationAngularVelocity(const btVector3& angvel)
+ void setInterpolationAngularVelocity(const btVector3& angvel)
{
m_updateRevision++;
m_interpolationAngularVelocity = angvel;
}
- const btVector3& getInterpolationLinearVelocity() const
+ const btVector3& getInterpolationLinearVelocity() const
{
return m_interpolationLinearVelocity;
}
- const btVector3& getInterpolationAngularVelocity() const
+ const btVector3& getInterpolationAngularVelocity() const
{
return m_interpolationAngularVelocity;
}
SIMD_FORCE_INLINE int getIslandTag() const
{
- return m_islandTag1;
+ return m_islandTag1;
}
- void setIslandTag(int tag)
+ void setIslandTag(int tag)
{
m_islandTag1 = tag;
}
SIMD_FORCE_INLINE int getCompanionId() const
{
- return m_companionId;
+ return m_companionId;
}
- void setCompanionId(int id)
+ void setCompanionId(int id)
{
m_companionId = id;
}
- SIMD_FORCE_INLINE int getWorldArrayIndex() const
- {
- return m_worldArrayIndex;
- }
+ SIMD_FORCE_INLINE int getWorldArrayIndex() const
+ {
+ return m_worldArrayIndex;
+ }
- // only should be called by CollisionWorld
- void setWorldArrayIndex(int ix)
- {
- m_worldArrayIndex = ix;
- }
+ // only should be called by CollisionWorld
+ void setWorldArrayIndex(int ix)
+ {
+ m_worldArrayIndex = ix;
+ }
- SIMD_FORCE_INLINE btScalar getHitFraction() const
+ SIMD_FORCE_INLINE btScalar getHitFraction() const
{
- return m_hitFraction;
+ return m_hitFraction;
}
- void setHitFraction(btScalar hitFraction)
+ void setHitFraction(btScalar hitFraction)
{
m_hitFraction = hitFraction;
}
-
- SIMD_FORCE_INLINE int getCollisionFlags() const
+ SIMD_FORCE_INLINE int getCollisionFlags() const
{
return m_collisionFlags;
}
- void setCollisionFlags(int flags)
+ void setCollisionFlags(int flags)
{
m_collisionFlags = flags;
}
-
+
///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm::
- btScalar getCcdSweptSphereRadius() const
+ btScalar getCcdSweptSphereRadius() const
{
return m_ccdSweptSphereRadius;
}
///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm::
- void setCcdSweptSphereRadius(btScalar radius)
+ void setCcdSweptSphereRadius(btScalar radius)
{
m_ccdSweptSphereRadius = radius;
}
- btScalar getCcdMotionThreshold() const
+ btScalar getCcdMotionThreshold() const
{
return m_ccdMotionThreshold;
}
- btScalar getCcdSquareMotionThreshold() const
+ btScalar getCcdSquareMotionThreshold() const
{
- return m_ccdMotionThreshold*m_ccdMotionThreshold;
+ return m_ccdMotionThreshold * m_ccdMotionThreshold;
}
-
-
/// Don't do continuous collision detection if the motion (in one step) is less then m_ccdMotionThreshold
- void setCcdMotionThreshold(btScalar ccdMotionThreshold)
+ void setCcdMotionThreshold(btScalar ccdMotionThreshold)
{
m_ccdMotionThreshold = ccdMotionThreshold;
}
///users can point to their objects, userPointer is not used by Bullet
- void* getUserPointer() const
+ void* getUserPointer() const
{
return m_userObjectPointer;
}
- int getUserIndex() const
+ int getUserIndex() const
{
return m_userIndex;
}
-
- int getUserIndex2() const
+
+ int getUserIndex2() const
{
return m_userIndex2;
}
-
+
///users can point to their objects, userPointer is not used by Bullet
- void setUserPointer(void* userPointer)
+ void setUserPointer(void* userPointer)
{
m_userObjectPointer = userPointer;
}
///users can point to their objects, userPointer is not used by Bullet
- void setUserIndex(int index)
+ void setUserIndex(int index)
{
m_userIndex = index;
}
-
- void setUserIndex2(int index)
+
+ void setUserIndex2(int index)
{
m_userIndex2 = index;
}
- int getUpdateRevisionInternal() const
+ int getUpdateRevisionInternal() const
{
return m_updateRevision;
}
- void setCustomDebugColor(const btVector3& colorRGB)
+ void setCustomDebugColor(const btVector3& colorRGB)
{
m_customDebugColorRGB = colorRGB;
m_collisionFlags |= CF_HAS_CUSTOM_DEBUG_RENDERING_COLOR;
}
- void removeCustomDebugColor()
+ void removeCustomDebugColor()
{
m_collisionFlags &= ~CF_HAS_CUSTOM_DEBUG_RENDERING_COLOR;
}
- bool getCustomDebugColor(btVector3& colorRGB) const
+ bool getCustomDebugColor(btVector3 & colorRGB) const
{
- bool hasCustomColor = (0!=(m_collisionFlags&CF_HAS_CUSTOM_DEBUG_RENDERING_COLOR));
+ bool hasCustomColor = (0 != (m_collisionFlags & CF_HAS_CUSTOM_DEBUG_RENDERING_COLOR));
if (hasCustomColor)
{
colorRGB = m_customDebugColorRGB;
@@ -589,15 +577,16 @@ public:
return true;
}
- virtual int calculateSerializeBufferSize() const;
+ virtual int calculateSerializeBufferSize() const;
///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const;
-
- virtual void serializeSingleObject(class btSerializer* serializer) const;
+ virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const;
+ virtual void serializeSingleObject(class btSerializer * serializer) const;
};
+// clang-format off
+
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
struct btCollisionObjectDoubleData
{
@@ -667,14 +656,11 @@ struct btCollisionObjectFloatData
int m_collisionFilterMask;
int m_uniqueId;
};
+// clang-format on
-
-
-SIMD_FORCE_INLINE int btCollisionObject::calculateSerializeBufferSize() const
+SIMD_FORCE_INLINE int btCollisionObject::calculateSerializeBufferSize() const
{
return sizeof(btCollisionObjectData);
}
-
-
-#endif //BT_COLLISION_OBJECT_H
+#endif //BT_COLLISION_OBJECT_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h
index 952440b7de..1cc4a5ac5f 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h
@@ -1,25 +1,25 @@
#ifndef BT_COLLISION_OBJECT_WRAPPER_H
#define BT_COLLISION_OBJECT_WRAPPER_H
-///btCollisionObjectWrapperis an internal data structure.
+///btCollisionObjectWrapperis an internal data structure.
///Most users can ignore this and use btCollisionObject and btCollisionShape instead
class btCollisionShape;
class btCollisionObject;
class btTransform;
-#include "LinearMath/btScalar.h" // for SIMD_FORCE_INLINE definition
+#include "LinearMath/btScalar.h" // for SIMD_FORCE_INLINE definition
#define BT_DECLARE_STACK_ONLY_OBJECT \
- private: \
- void* operator new(size_t size); \
- void operator delete(void*);
+private: \
+ void* operator new(size_t size); \
+ void operator delete(void*);
struct btCollisionObjectWrapper;
struct btCollisionObjectWrapper
{
-BT_DECLARE_STACK_ONLY_OBJECT
+ BT_DECLARE_STACK_ONLY_OBJECT
private:
- btCollisionObjectWrapper(const btCollisionObjectWrapper&); // not implemented. Not allowed.
+ btCollisionObjectWrapper(const btCollisionObjectWrapper&); // not implemented. Not allowed.
btCollisionObjectWrapper* operator=(const btCollisionObjectWrapper&);
public:
@@ -27,17 +27,17 @@ public:
const btCollisionShape* m_shape;
const btCollisionObject* m_collisionObject;
const btTransform& m_worldTransform;
- int m_partId;
- int m_index;
+ int m_partId;
+ int m_index;
btCollisionObjectWrapper(const btCollisionObjectWrapper* parent, const btCollisionShape* shape, const btCollisionObject* collisionObject, const btTransform& worldTransform, int partId, int index)
- : m_parent(parent), m_shape(shape), m_collisionObject(collisionObject), m_worldTransform(worldTransform),
- m_partId(partId), m_index(index)
- {}
+ : m_parent(parent), m_shape(shape), m_collisionObject(collisionObject), m_worldTransform(worldTransform), m_partId(partId), m_index(index)
+ {
+ }
SIMD_FORCE_INLINE const btTransform& getWorldTransform() const { return m_worldTransform; }
SIMD_FORCE_INLINE const btCollisionObject* getCollisionObject() const { return m_collisionObject; }
SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const { return m_shape; }
};
-#endif //BT_COLLISION_OBJECT_WRAPPER_H
+#endif //BT_COLLISION_OBJECT_WRAPPER_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.cpp
index 3de8d6995e..b30ce03164 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.cpp
@@ -22,6 +22,7 @@ subject to the following restrictions:
#include "BulletCollision/CollisionShapes/btSphereShape.h" //for raycasting
#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" //for raycasting
#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h" //for raycasting
+#include "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h" //for raycasting
#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
#include "BulletCollision/CollisionShapes/btCompoundShape.h"
#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
@@ -38,7 +39,6 @@ subject to the following restrictions:
//#define DISABLE_DBVT_COMPOUNDSHAPE_RAYCAST_ACCELERATION
-
//#define USE_BRUTEFORCE_RAYBROADPHASE 1
//RECALCULATE_AABB is slower, but benefit is that you don't need to call 'stepSimulation' or 'updateAabbs' before using a rayTest
//#define RECALCULATE_AABB_RAYCAST 1
@@ -48,7 +48,6 @@ subject to the following restrictions:
#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h"
-
///for debug drawing
//for debug rendering
@@ -65,25 +64,21 @@ subject to the following restrictions:
#include "BulletCollision/CollisionShapes/btTriangleMeshShape.h"
#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
-
-
-btCollisionWorld::btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache, btCollisionConfiguration* collisionConfiguration)
-:m_dispatcher1(dispatcher),
-m_broadphasePairCache(pairCache),
-m_debugDrawer(0),
-m_forceUpdateAllAabbs(true)
+btCollisionWorld::btCollisionWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btCollisionConfiguration* collisionConfiguration)
+ : m_dispatcher1(dispatcher),
+ m_broadphasePairCache(pairCache),
+ m_debugDrawer(0),
+ m_forceUpdateAllAabbs(true)
{
}
-
btCollisionWorld::~btCollisionWorld()
{
-
//clean up remaining objects
int i;
- for (i=0;i<m_collisionObjects.size();i++)
+ for (i = 0; i < m_collisionObjects.size(); i++)
{
- btCollisionObject* collisionObject= m_collisionObjects[i];
+ btCollisionObject* collisionObject = m_collisionObjects[i];
btBroadphaseProxy* bp = collisionObject->getBroadphaseHandle();
if (bp)
@@ -91,74 +86,83 @@ btCollisionWorld::~btCollisionWorld()
//
// only clear the cached algorithms
//
- getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1);
- getBroadphase()->destroyProxy(bp,m_dispatcher1);
+ getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp, m_dispatcher1);
+ getBroadphase()->destroyProxy(bp, m_dispatcher1);
collisionObject->setBroadphaseHandle(0);
}
}
-
-
}
-
-
-
-
-
-
-
-
-
-void btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup, int collisionFilterMask)
+void btCollisionWorld::refreshBroadphaseProxy(btCollisionObject* collisionObject)
{
+ if (collisionObject->getBroadphaseHandle())
+ {
+ int collisionFilterGroup = collisionObject->getBroadphaseHandle()->m_collisionFilterGroup;
+ int collisionFilterMask = collisionObject->getBroadphaseHandle()->m_collisionFilterMask;
+
+ getBroadphase()->destroyProxy(collisionObject->getBroadphaseHandle(), getDispatcher());
+
+ //calculate new AABB
+ btTransform trans = collisionObject->getWorldTransform();
+
+ btVector3 minAabb;
+ btVector3 maxAabb;
+ collisionObject->getCollisionShape()->getAabb(trans, minAabb, maxAabb);
+
+ int type = collisionObject->getCollisionShape()->getShapeType();
+ collisionObject->setBroadphaseHandle(getBroadphase()->createProxy(
+ minAabb,
+ maxAabb,
+ type,
+ collisionObject,
+ collisionFilterGroup,
+ collisionFilterMask,
+ m_dispatcher1));
+ }
+}
+void btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup, int collisionFilterMask)
+{
btAssert(collisionObject);
//check that the object isn't already added
- btAssert( m_collisionObjects.findLinearSearch(collisionObject) == m_collisionObjects.size());
- btAssert(collisionObject->getWorldArrayIndex() == -1); // do not add the same object to more than one collision world
+ btAssert(m_collisionObjects.findLinearSearch(collisionObject) == m_collisionObjects.size());
+ btAssert(collisionObject->getWorldArrayIndex() == -1); // do not add the same object to more than one collision world
- collisionObject->setWorldArrayIndex(m_collisionObjects.size());
+ collisionObject->setWorldArrayIndex(m_collisionObjects.size());
m_collisionObjects.push_back(collisionObject);
//calculate new AABB
btTransform trans = collisionObject->getWorldTransform();
- btVector3 minAabb;
- btVector3 maxAabb;
- collisionObject->getCollisionShape()->getAabb(trans,minAabb,maxAabb);
+ btVector3 minAabb;
+ btVector3 maxAabb;
+ collisionObject->getCollisionShape()->getAabb(trans, minAabb, maxAabb);
int type = collisionObject->getCollisionShape()->getShapeType();
- collisionObject->setBroadphaseHandle( getBroadphase()->createProxy(
+ collisionObject->setBroadphaseHandle(getBroadphase()->createProxy(
minAabb,
maxAabb,
type,
collisionObject,
collisionFilterGroup,
collisionFilterMask,
- m_dispatcher1)) ;
-
-
-
-
-
+ m_dispatcher1));
}
-
-
-void btCollisionWorld::updateSingleAabb(btCollisionObject* colObj)
+void btCollisionWorld::updateSingleAabb(btCollisionObject* colObj)
{
- btVector3 minAabb,maxAabb;
- colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb);
+ btVector3 minAabb, maxAabb;
+ colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb, maxAabb);
//need to increase the aabb for contact thresholds
- btVector3 contactThreshold(gContactBreakingThreshold,gContactBreakingThreshold,gContactBreakingThreshold);
+ btVector3 contactThreshold(gContactBreakingThreshold, gContactBreakingThreshold, gContactBreakingThreshold);
minAabb -= contactThreshold;
maxAabb += contactThreshold;
- if(getDispatchInfo().m_useContinuous && colObj->getInternalType()==btCollisionObject::CO_RIGID_BODY && !colObj->isStaticOrKinematicObject())
+ if (getDispatchInfo().m_useContinuous && colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY && !colObj->isStaticOrKinematicObject())
{
- btVector3 minAabb2,maxAabb2;
- colObj->getCollisionShape()->getAabb(colObj->getInterpolationWorldTransform(),minAabb2,maxAabb2);
+ btVector3 minAabb2, maxAabb2;
+ colObj->getCollisionShape()->getAabb(colObj->getInterpolationWorldTransform(), minAabb2, maxAabb2);
minAabb2 -= contactThreshold;
maxAabb2 += contactThreshold;
minAabb.setMin(minAabb2);
@@ -168,10 +172,11 @@ void btCollisionWorld::updateSingleAabb(btCollisionObject* colObj)
btBroadphaseInterface* bp = (btBroadphaseInterface*)m_broadphasePairCache;
//moving objects should be moderately sized, probably something wrong if not
- if ( colObj->isStaticObject() || ((maxAabb-minAabb).length2() < btScalar(1e12)))
+ if (colObj->isStaticObject() || ((maxAabb - minAabb).length2() < btScalar(1e12)))
{
- bp->setAabb(colObj->getBroadphaseHandle(),minAabb,maxAabb, m_dispatcher1);
- } else
+ bp->setAabb(colObj->getBroadphaseHandle(), minAabb, maxAabb, m_dispatcher1);
+ }
+ else
{
//something went wrong, investigate
//this assert is unwanted in 3D modelers (danger of loosing work)
@@ -189,15 +194,15 @@ void btCollisionWorld::updateSingleAabb(btCollisionObject* colObj)
}
}
-void btCollisionWorld::updateAabbs()
+void btCollisionWorld::updateAabbs()
{
BT_PROFILE("updateAabbs");
btTransform predictedTrans;
- for ( int i=0;i<m_collisionObjects.size();i++)
+ for (int i = 0; i < m_collisionObjects.size(); i++)
{
btCollisionObject* colObj = m_collisionObjects[i];
- btAssert(colObj->getWorldArrayIndex() == i);
+ btAssert(colObj->getWorldArrayIndex() == i);
//only update aabb of active objects
if (m_forceUpdateAllAabbs || colObj->isActive())
@@ -207,14 +212,13 @@ void btCollisionWorld::updateAabbs()
}
}
-
-void btCollisionWorld::computeOverlappingPairs()
+void btCollisionWorld::computeOverlappingPairs()
{
BT_PROFILE("calculateOverlappingPairs");
m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1);
}
-void btCollisionWorld::performDiscreteCollisionDetection()
+void btCollisionWorld::performDiscreteCollisionDetection()
{
BT_PROFILE("performDiscreteCollisionDetection");
@@ -228,69 +232,61 @@ void btCollisionWorld::performDiscreteCollisionDetection()
{
BT_PROFILE("dispatchAllCollisionPairs");
if (dispatcher)
- dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1);
+ dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(), dispatchInfo, m_dispatcher1);
}
-
}
-
-
-void btCollisionWorld::removeCollisionObject(btCollisionObject* collisionObject)
+void btCollisionWorld::removeCollisionObject(btCollisionObject* collisionObject)
{
-
-
//bool removeFromBroadphase = false;
{
-
btBroadphaseProxy* bp = collisionObject->getBroadphaseHandle();
if (bp)
{
//
// only clear the cached algorithms
//
- getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1);
- getBroadphase()->destroyProxy(bp,m_dispatcher1);
+ getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp, m_dispatcher1);
+ getBroadphase()->destroyProxy(bp, m_dispatcher1);
collisionObject->setBroadphaseHandle(0);
}
}
-
- int iObj = collisionObject->getWorldArrayIndex();
-// btAssert(iObj >= 0 && iObj < m_collisionObjects.size()); // trying to remove an object that was never added or already removed previously?
- if (iObj >= 0 && iObj < m_collisionObjects.size())
- {
- btAssert(collisionObject == m_collisionObjects[iObj]);
- m_collisionObjects.swap(iObj, m_collisionObjects.size()-1);
- m_collisionObjects.pop_back();
- if (iObj < m_collisionObjects.size())
- {
- m_collisionObjects[iObj]->setWorldArrayIndex(iObj);
- }
- }
- else
- {
- // slow linear search
- //swapremove
- m_collisionObjects.remove(collisionObject);
- }
- collisionObject->setWorldArrayIndex(-1);
+ int iObj = collisionObject->getWorldArrayIndex();
+ // btAssert(iObj >= 0 && iObj < m_collisionObjects.size()); // trying to remove an object that was never added or already removed previously?
+ if (iObj >= 0 && iObj < m_collisionObjects.size())
+ {
+ btAssert(collisionObject == m_collisionObjects[iObj]);
+ m_collisionObjects.swap(iObj, m_collisionObjects.size() - 1);
+ m_collisionObjects.pop_back();
+ if (iObj < m_collisionObjects.size())
+ {
+ m_collisionObjects[iObj]->setWorldArrayIndex(iObj);
+ }
+ }
+ else
+ {
+ // slow linear search
+ //swapremove
+ m_collisionObjects.remove(collisionObject);
+ }
+ collisionObject->setWorldArrayIndex(-1);
}
-
-void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans,
- btCollisionObject* collisionObject,
- const btCollisionShape* collisionShape,
- const btTransform& colObjWorldTransform,
- RayResultCallback& resultCallback)
+void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans, const btTransform& rayToTrans,
+ btCollisionObject* collisionObject,
+ const btCollisionShape* collisionShape,
+ const btTransform& colObjWorldTransform,
+ RayResultCallback& resultCallback)
{
- btCollisionObjectWrapper colObWrap(0,collisionShape,collisionObject,colObjWorldTransform,-1,-1);
- btCollisionWorld::rayTestSingleInternal(rayFromTrans,rayToTrans,&colObWrap,resultCallback);
+ btCollisionObjectWrapper colObWrap(0, collisionShape, collisionObject, colObjWorldTransform, -1, -1);
+ btCollisionWorld::rayTestSingleInternal(rayFromTrans, rayToTrans, &colObWrap, resultCallback);
}
-void btCollisionWorld::rayTestSingleInternal(const btTransform& rayFromTrans,const btTransform& rayToTrans,
- const btCollisionObjectWrapper* collisionObjectWrap,
- RayResultCallback& resultCallback)
+void btCollisionWorld::rayTestSingleInternal(const btTransform& rayFromTrans, const btTransform& rayToTrans,
+ const btCollisionObjectWrapper* collisionObjectWrap,
+ RayResultCallback& resultCallback)
{
btSphereShape pointShape(btScalar(0.0));
pointShape.setMargin(0.f);
@@ -304,12 +300,12 @@ void btCollisionWorld::rayTestSingleInternal(const btTransform& rayFromTrans,con
btConvexCast::CastResult castResult;
castResult.m_fraction = resultCallback.m_closestHitFraction;
- btConvexShape* convexShape = (btConvexShape*) collisionShape;
- btVoronoiSimplexSolver simplexSolver;
- btSubsimplexConvexCast subSimplexConvexCaster(castShape,convexShape,&simplexSolver);
-
- btGjkConvexCast gjkConvexCaster(castShape,convexShape,&simplexSolver);
-
+ btConvexShape* convexShape = (btConvexShape*)collisionShape;
+ btVoronoiSimplexSolver simplexSolver;
+ btSubsimplexConvexCast subSimplexConvexCaster(castShape, convexShape, &simplexSolver);
+
+ btGjkConvexCast gjkConvexCaster(castShape, convexShape, &simplexSolver);
+
//btContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0);
btConvexCast* convexCasterPtr = 0;
@@ -318,10 +314,10 @@ void btCollisionWorld::rayTestSingleInternal(const btTransform& rayFromTrans,con
convexCasterPtr = &gjkConvexCaster;
else
convexCasterPtr = &subSimplexConvexCaster;
-
+
btConvexCast& convexCaster = *convexCasterPtr;
- if (convexCaster.calcTimeOfImpact(rayFromTrans,rayToTrans,colObjWorldTransform,colObjWorldTransform,castResult))
+ if (convexCaster.calcTimeOfImpact(rayFromTrans, rayToTrans, colObjWorldTransform, colObjWorldTransform, castResult))
{
//add hit
if (castResult.m_normal.length2() > btScalar(0.0001))
@@ -332,81 +328,75 @@ void btCollisionWorld::rayTestSingleInternal(const btTransform& rayFromTrans,con
#ifdef USE_SUBSIMPLEX_CONVEX_CAST
//rotate normal into worldspace
castResult.m_normal = rayFromTrans.getBasis() * castResult.m_normal;
-#endif //USE_SUBSIMPLEX_CONVEX_CAST
+#endif //USE_SUBSIMPLEX_CONVEX_CAST
castResult.m_normal.normalize();
- btCollisionWorld::LocalRayResult localRayResult
- (
+ btCollisionWorld::LocalRayResult localRayResult(
collisionObjectWrap->getCollisionObject(),
0,
castResult.m_normal,
- castResult.m_fraction
- );
+ castResult.m_fraction);
bool normalInWorldSpace = true;
resultCallback.addSingleResult(localRayResult, normalInWorldSpace);
-
}
}
}
- } else {
+ }
+ else
+ {
if (collisionShape->isConcave())
{
-
//ConvexCast::CastResult
- struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback
+ struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback
+ {
+ btCollisionWorld::RayResultCallback* m_resultCallback;
+ const btCollisionObject* m_collisionObject;
+ const btConcaveShape* m_triangleMesh;
+
+ btTransform m_colObjWorldTransform;
+
+ BridgeTriangleRaycastCallback(const btVector3& from, const btVector3& to,
+ btCollisionWorld::RayResultCallback* resultCallback, const btCollisionObject* collisionObject, const btConcaveShape* triangleMesh, const btTransform& colObjWorldTransform) : //@BP Mod
+ btTriangleRaycastCallback(from, to, resultCallback->m_flags),
+ m_resultCallback(resultCallback),
+ m_collisionObject(collisionObject),
+ m_triangleMesh(triangleMesh),
+ m_colObjWorldTransform(colObjWorldTransform)
{
- btCollisionWorld::RayResultCallback* m_resultCallback;
- const btCollisionObject* m_collisionObject;
- const btConcaveShape* m_triangleMesh;
-
- btTransform m_colObjWorldTransform;
-
- BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to,
- btCollisionWorld::RayResultCallback* resultCallback, const btCollisionObject* collisionObject,const btConcaveShape* triangleMesh,const btTransform& colObjWorldTransform):
- //@BP Mod
- btTriangleRaycastCallback(from,to, resultCallback->m_flags),
- m_resultCallback(resultCallback),
- m_collisionObject(collisionObject),
- m_triangleMesh(triangleMesh),
- m_colObjWorldTransform(colObjWorldTransform)
- {
- }
-
-
- virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex )
- {
- btCollisionWorld::LocalShapeInfo shapeInfo;
- shapeInfo.m_shapePart = partId;
- shapeInfo.m_triangleIndex = triangleIndex;
+ }
- btVector3 hitNormalWorld = m_colObjWorldTransform.getBasis() * hitNormalLocal;
+ virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex)
+ {
+ btCollisionWorld::LocalShapeInfo shapeInfo;
+ shapeInfo.m_shapePart = partId;
+ shapeInfo.m_triangleIndex = triangleIndex;
- btCollisionWorld::LocalRayResult rayResult
- (m_collisionObject,
- &shapeInfo,
- hitNormalWorld,
- hitFraction);
+ btVector3 hitNormalWorld = m_colObjWorldTransform.getBasis() * hitNormalLocal;
- bool normalInWorldSpace = true;
- return m_resultCallback->addSingleResult(rayResult,normalInWorldSpace);
- }
+ btCollisionWorld::LocalRayResult rayResult(m_collisionObject,
+ &shapeInfo,
+ hitNormalWorld,
+ hitFraction);
- };
+ bool normalInWorldSpace = true;
+ return m_resultCallback->addSingleResult(rayResult, normalInWorldSpace);
+ }
+ };
btTransform worldTocollisionObject = colObjWorldTransform.inverse();
btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin();
btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin();
// BT_PROFILE("rayTestConcave");
- if (collisionShape->getShapeType()==TRIANGLE_MESH_SHAPE_PROXYTYPE)
+ if (collisionShape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
{
///optimized version for btBvhTriangleMeshShape
btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape;
-
- BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObjectWrap->getCollisionObject(),triangleMesh,colObjWorldTransform);
+
+ BridgeTriangleRaycastCallback rcb(rayFromLocal, rayToLocal, &resultCallback, collisionObjectWrap->getCollisionObject(), triangleMesh, colObjWorldTransform);
rcb.m_hitFraction = resultCallback.m_closestHitFraction;
- triangleMesh->performRaycast(&rcb,rayFromLocal,rayToLocal);
+ triangleMesh->performRaycast(&rcb, rayFromLocal, rayToLocal);
}
else if (collisionShape->getShapeType() == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE)
{
@@ -418,12 +408,24 @@ void btCollisionWorld::rayTestSingleInternal(const btTransform& rayFromTrans,con
btVector3 scale = scaledTriangleMesh->getLocalScaling();
btVector3 rayFromLocalScaled = rayFromLocal / scale;
btVector3 rayToLocalScaled = rayToLocal / scale;
-
+
//perform raycast in the underlying btBvhTriangleMeshShape
BridgeTriangleRaycastCallback rcb(rayFromLocalScaled, rayToLocalScaled, &resultCallback, collisionObjectWrap->getCollisionObject(), triangleMesh, colObjWorldTransform);
rcb.m_hitFraction = resultCallback.m_closestHitFraction;
triangleMesh->performRaycast(&rcb, rayFromLocalScaled, rayToLocalScaled);
}
+ else if (collisionShape->getShapeType()==TERRAIN_SHAPE_PROXYTYPE)
+ {
+ ///optimized version for btHeightfieldTerrainShape
+ btHeightfieldTerrainShape* heightField = (btHeightfieldTerrainShape*)collisionShape;
+ btTransform worldTocollisionObject = colObjWorldTransform.inverse();
+ btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin();
+ btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin();
+
+ BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObjectWrap->getCollisionObject(),heightField,colObjWorldTransform);
+ rcb.m_hitFraction = resultCallback.m_closestHitFraction;
+ heightField->performRaycast(&rcb, rayFromLocal, rayToLocal);
+ }
else
{
//generic (slower) case
@@ -439,45 +441,40 @@ void btCollisionWorld::rayTestSingleInternal(const btTransform& rayFromTrans,con
struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback
{
btCollisionWorld::RayResultCallback* m_resultCallback;
- const btCollisionObject* m_collisionObject;
- btConcaveShape* m_triangleMesh;
+ const btCollisionObject* m_collisionObject;
+ btConcaveShape* m_triangleMesh;
btTransform m_colObjWorldTransform;
- BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to,
- btCollisionWorld::RayResultCallback* resultCallback, const btCollisionObject* collisionObject,btConcaveShape* triangleMesh, const btTransform& colObjWorldTransform):
- //@BP Mod
- btTriangleRaycastCallback(from,to, resultCallback->m_flags),
- m_resultCallback(resultCallback),
- m_collisionObject(collisionObject),
- m_triangleMesh(triangleMesh),
- m_colObjWorldTransform(colObjWorldTransform)
+ BridgeTriangleRaycastCallback(const btVector3& from, const btVector3& to,
+ btCollisionWorld::RayResultCallback* resultCallback, const btCollisionObject* collisionObject, btConcaveShape* triangleMesh, const btTransform& colObjWorldTransform) : //@BP Mod
+ btTriangleRaycastCallback(from, to, resultCallback->m_flags),
+ m_resultCallback(resultCallback),
+ m_collisionObject(collisionObject),
+ m_triangleMesh(triangleMesh),
+ m_colObjWorldTransform(colObjWorldTransform)
{
}
-
- virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex )
+ virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex)
{
- btCollisionWorld::LocalShapeInfo shapeInfo;
+ btCollisionWorld::LocalShapeInfo shapeInfo;
shapeInfo.m_shapePart = partId;
shapeInfo.m_triangleIndex = triangleIndex;
btVector3 hitNormalWorld = m_colObjWorldTransform.getBasis() * hitNormalLocal;
- btCollisionWorld::LocalRayResult rayResult
- (m_collisionObject,
- &shapeInfo,
- hitNormalWorld,
- hitFraction);
+ btCollisionWorld::LocalRayResult rayResult(m_collisionObject,
+ &shapeInfo,
+ hitNormalWorld,
+ hitFraction);
- bool normalInWorldSpace = true;
- return m_resultCallback->addSingleResult(rayResult,normalInWorldSpace);
+ bool normalInWorldSpace = true;
+ return m_resultCallback->addSingleResult(rayResult, normalInWorldSpace);
}
-
};
-
- BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObjectWrap->getCollisionObject(),concaveShape, colObjWorldTransform);
+ BridgeTriangleRaycastCallback rcb(rayFromLocal, rayToLocal, &resultCallback, collisionObjectWrap->getCollisionObject(), concaveShape, colObjWorldTransform);
rcb.m_hitFraction = resultCallback.m_closestHitFraction;
btVector3 rayAabbMinLocal = rayFromLocal;
@@ -485,9 +482,11 @@ void btCollisionWorld::rayTestSingleInternal(const btTransform& rayFromTrans,con
btVector3 rayAabbMaxLocal = rayFromLocal;
rayAabbMaxLocal.setMax(rayToLocal);
- concaveShape->processAllTriangles(&rcb,rayAabbMinLocal,rayAabbMaxLocal);
+ concaveShape->processAllTriangles(&rcb, rayAabbMinLocal, rayAabbMaxLocal);
}
- } else {
+ }
+ else
+ {
// BT_PROFILE("rayTestCompound");
if (collisionShape->isCompound())
{
@@ -495,10 +494,10 @@ void btCollisionWorld::rayTestSingleInternal(const btTransform& rayFromTrans,con
{
RayResultCallback* m_userCallback;
int m_i;
-
- LocalInfoAdder2 (int i, RayResultCallback *user)
+
+ LocalInfoAdder2(int i, RayResultCallback* user)
: m_userCallback(user), m_i(i)
- {
+ {
m_closestHitFraction = m_userCallback->m_closestHitFraction;
m_flags = m_userCallback->m_flags;
}
@@ -507,7 +506,7 @@ void btCollisionWorld::rayTestSingleInternal(const btTransform& rayFromTrans,con
return m_userCallback->needsCollision(p);
}
- virtual btScalar addSingleResult (btCollisionWorld::LocalRayResult &r, bool b)
+ virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& r, bool b)
{
btCollisionWorld::LocalShapeInfo shapeInfo;
shapeInfo.m_shapePart = -1;
@@ -520,7 +519,7 @@ void btCollisionWorld::rayTestSingleInternal(const btTransform& rayFromTrans,con
return result;
}
};
-
+
struct RayTester : btDbvt::ICollide
{
const btCollisionObject* m_collisionObject;
@@ -529,33 +528,29 @@ void btCollisionWorld::rayTestSingleInternal(const btTransform& rayFromTrans,con
const btTransform& m_rayFromTrans;
const btTransform& m_rayToTrans;
RayResultCallback& m_resultCallback;
-
+
RayTester(const btCollisionObject* collisionObject,
- const btCompoundShape* compoundShape,
- const btTransform& colObjWorldTransform,
- const btTransform& rayFromTrans,
- const btTransform& rayToTrans,
- RayResultCallback& resultCallback):
- m_collisionObject(collisionObject),
- m_compoundShape(compoundShape),
- m_colObjWorldTransform(colObjWorldTransform),
- m_rayFromTrans(rayFromTrans),
- m_rayToTrans(rayToTrans),
- m_resultCallback(resultCallback)
+ const btCompoundShape* compoundShape,
+ const btTransform& colObjWorldTransform,
+ const btTransform& rayFromTrans,
+ const btTransform& rayToTrans,
+ RayResultCallback& resultCallback) : m_collisionObject(collisionObject),
+ m_compoundShape(compoundShape),
+ m_colObjWorldTransform(colObjWorldTransform),
+ m_rayFromTrans(rayFromTrans),
+ m_rayToTrans(rayToTrans),
+ m_resultCallback(resultCallback)
{
-
}
-
+
void ProcessLeaf(int i)
{
const btCollisionShape* childCollisionShape = m_compoundShape->getChildShape(i);
const btTransform& childTrans = m_compoundShape->getChildTransform(i);
btTransform childWorldTrans = m_colObjWorldTransform * childTrans;
-
- btCollisionObjectWrapper tmpOb(0,childCollisionShape,m_collisionObject,childWorldTrans,-1,i);
- // replace collision shape so that callback can determine the triangle
-
+ btCollisionObjectWrapper tmpOb(0, childCollisionShape, m_collisionObject, childWorldTrans, -1, i);
+ // replace collision shape so that callback can determine the triangle
LocalInfoAdder2 my_cb(i, &m_resultCallback);
@@ -564,19 +559,17 @@ void btCollisionWorld::rayTestSingleInternal(const btTransform& rayFromTrans,con
m_rayToTrans,
&tmpOb,
my_cb);
-
}
-
+
void Process(const btDbvtNode* leaf)
{
ProcessLeaf(leaf->dataAsInt);
}
};
-
+
const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(collisionShape);
const btDbvt* dbvt = compoundShape->getDynamicAabbTree();
-
RayTester rayCB(
collisionObjectWrap->getCollisionObject(),
compoundShape,
@@ -584,39 +577,39 @@ void btCollisionWorld::rayTestSingleInternal(const btTransform& rayFromTrans,con
rayFromTrans,
rayToTrans,
resultCallback);
-#ifndef DISABLE_DBVT_COMPOUNDSHAPE_RAYCAST_ACCELERATION
+#ifndef DISABLE_DBVT_COMPOUNDSHAPE_RAYCAST_ACCELERATION
if (dbvt)
{
btVector3 localRayFrom = colObjWorldTransform.inverseTimes(rayFromTrans).getOrigin();
btVector3 localRayTo = colObjWorldTransform.inverseTimes(rayToTrans).getOrigin();
- btDbvt::rayTest(dbvt->m_root, localRayFrom , localRayTo, rayCB);
+ btDbvt::rayTest(dbvt->m_root, localRayFrom, localRayTo, rayCB);
}
else
-#endif //DISABLE_DBVT_COMPOUNDSHAPE_RAYCAST_ACCELERATION
+#endif //DISABLE_DBVT_COMPOUNDSHAPE_RAYCAST_ACCELERATION
{
for (int i = 0, n = compoundShape->getNumChildShapes(); i < n; ++i)
{
rayCB.ProcessLeaf(i);
- }
+ }
}
}
}
}
}
-void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const btTransform& convexFromTrans,const btTransform& convexToTrans,
- btCollisionObject* collisionObject,
- const btCollisionShape* collisionShape,
- const btTransform& colObjWorldTransform,
- ConvexResultCallback& resultCallback, btScalar allowedPenetration)
+void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape, const btTransform& convexFromTrans, const btTransform& convexToTrans,
+ btCollisionObject* collisionObject,
+ const btCollisionShape* collisionShape,
+ const btTransform& colObjWorldTransform,
+ ConvexResultCallback& resultCallback, btScalar allowedPenetration)
{
- btCollisionObjectWrapper tmpOb(0,collisionShape,collisionObject,colObjWorldTransform,-1,-1);
- btCollisionWorld::objectQuerySingleInternal(castShape,convexFromTrans,convexToTrans,&tmpOb,resultCallback,allowedPenetration);
+ btCollisionObjectWrapper tmpOb(0, collisionShape, collisionObject, colObjWorldTransform, -1, -1);
+ btCollisionWorld::objectQuerySingleInternal(castShape, convexFromTrans, convexToTrans, &tmpOb, resultCallback, allowedPenetration);
}
-void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape,const btTransform& convexFromTrans,const btTransform& convexToTrans,
- const btCollisionObjectWrapper* colObjWrap,
- ConvexResultCallback& resultCallback, btScalar allowedPenetration)
+void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape, const btTransform& convexFromTrans, const btTransform& convexToTrans,
+ const btCollisionObjectWrapper* colObjWrap,
+ ConvexResultCallback& resultCallback, btScalar allowedPenetration)
{
const btCollisionShape* collisionShape = colObjWrap->getCollisionShape();
const btTransform& colObjWorldTransform = colObjWrap->getWorldTransform();
@@ -626,21 +619,19 @@ void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape,
//BT_PROFILE("convexSweepConvex");
btConvexCast::CastResult castResult;
castResult.m_allowedPenetration = allowedPenetration;
- castResult.m_fraction = resultCallback.m_closestHitFraction;//btScalar(1.);//??
+ castResult.m_fraction = resultCallback.m_closestHitFraction; //btScalar(1.);//??
- btConvexShape* convexShape = (btConvexShape*) collisionShape;
- btVoronoiSimplexSolver simplexSolver;
- btGjkEpaPenetrationDepthSolver gjkEpaPenetrationSolver;
+ btConvexShape* convexShape = (btConvexShape*)collisionShape;
+ btVoronoiSimplexSolver simplexSolver;
+ btGjkEpaPenetrationDepthSolver gjkEpaPenetrationSolver;
- btContinuousConvexCollision convexCaster1(castShape,convexShape,&simplexSolver,&gjkEpaPenetrationSolver);
+ btContinuousConvexCollision convexCaster1(castShape, convexShape, &simplexSolver, &gjkEpaPenetrationSolver);
//btGjkConvexCast convexCaster2(castShape,convexShape,&simplexSolver);
//btSubsimplexConvexCast convexCaster3(castShape,convexShape,&simplexSolver);
btConvexCast* castPtr = &convexCaster1;
-
-
- if (castPtr->calcTimeOfImpact(convexFromTrans,convexToTrans,colObjWorldTransform,colObjWorldTransform,castResult))
+ if (castPtr->calcTimeOfImpact(convexFromTrans, convexToTrans, colObjWorldTransform, colObjWorldTransform, castResult))
{
//add hit
if (castResult.m_normal.length2() > btScalar(0.0001))
@@ -648,25 +639,24 @@ void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape,
if (castResult.m_fraction < resultCallback.m_closestHitFraction)
{
castResult.m_normal.normalize();
- btCollisionWorld::LocalConvexResult localConvexResult
- (
+ btCollisionWorld::LocalConvexResult localConvexResult(
colObjWrap->getCollisionObject(),
0,
castResult.m_normal,
castResult.m_hitPoint,
- castResult.m_fraction
- );
+ castResult.m_fraction);
bool normalInWorldSpace = true;
resultCallback.addSingleResult(localConvexResult, normalInWorldSpace);
-
}
}
}
- } else {
+ }
+ else
+ {
if (collisionShape->isConcave())
{
- if (collisionShape->getShapeType()==TRIANGLE_MESH_SHAPE_PROXYTYPE)
+ if (collisionShape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
{
//BT_PROFILE("convexSweepbtBvhTriangleMesh");
btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape;
@@ -680,62 +670,57 @@ void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape,
struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback
{
btCollisionWorld::ConvexResultCallback* m_resultCallback;
- const btCollisionObject* m_collisionObject;
- btTriangleMeshShape* m_triangleMesh;
-
- BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to,
- btCollisionWorld::ConvexResultCallback* resultCallback, const btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh, const btTransform& triangleToWorld):
- btTriangleConvexcastCallback(castShape, from,to, triangleToWorld, triangleMesh->getMargin()),
- m_resultCallback(resultCallback),
- m_collisionObject(collisionObject),
- m_triangleMesh(triangleMesh)
+ const btCollisionObject* m_collisionObject;
+ btTriangleMeshShape* m_triangleMesh;
+
+ BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from, const btTransform& to,
+ btCollisionWorld::ConvexResultCallback* resultCallback, const btCollisionObject* collisionObject, btTriangleMeshShape* triangleMesh, const btTransform& triangleToWorld) : btTriangleConvexcastCallback(castShape, from, to, triangleToWorld, triangleMesh->getMargin()),
+ m_resultCallback(resultCallback),
+ m_collisionObject(collisionObject),
+ m_triangleMesh(triangleMesh)
{
}
-
- virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex )
+ virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex)
{
- btCollisionWorld::LocalShapeInfo shapeInfo;
+ btCollisionWorld::LocalShapeInfo shapeInfo;
shapeInfo.m_shapePart = partId;
shapeInfo.m_triangleIndex = triangleIndex;
if (hitFraction <= m_resultCallback->m_closestHitFraction)
{
+ btCollisionWorld::LocalConvexResult convexResult(m_collisionObject,
+ &shapeInfo,
+ hitNormalLocal,
+ hitPointLocal,
+ hitFraction);
- btCollisionWorld::LocalConvexResult convexResult
- (m_collisionObject,
- &shapeInfo,
- hitNormalLocal,
- hitPointLocal,
- hitFraction);
-
- bool normalInWorldSpace = true;
+ bool normalInWorldSpace = true;
-
- return m_resultCallback->addSingleResult(convexResult,normalInWorldSpace);
+ return m_resultCallback->addSingleResult(convexResult, normalInWorldSpace);
}
return hitFraction;
}
-
};
- BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,colObjWrap->getCollisionObject(),triangleMesh, colObjWorldTransform);
+ BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans, convexToTrans, &resultCallback, colObjWrap->getCollisionObject(), triangleMesh, colObjWorldTransform);
tccb.m_hitFraction = resultCallback.m_closestHitFraction;
tccb.m_allowedPenetration = allowedPenetration;
btVector3 boxMinLocal, boxMaxLocal;
castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal);
- triangleMesh->performConvexcast(&tccb,convexFromLocal,convexToLocal,boxMinLocal, boxMaxLocal);
- } else
+ triangleMesh->performConvexcast(&tccb, convexFromLocal, convexToLocal, boxMinLocal, boxMaxLocal);
+ }
+ else
{
- if (collisionShape->getShapeType()==STATIC_PLANE_PROXYTYPE)
+ if (collisionShape->getShapeType() == STATIC_PLANE_PROXYTYPE)
{
btConvexCast::CastResult castResult;
castResult.m_allowedPenetration = allowedPenetration;
castResult.m_fraction = resultCallback.m_closestHitFraction;
- btStaticPlaneShape* planeShape = (btStaticPlaneShape*) collisionShape;
- btContinuousConvexCollision convexCaster1(castShape,planeShape);
+ btStaticPlaneShape* planeShape = (btStaticPlaneShape*)collisionShape;
+ btContinuousConvexCollision convexCaster1(castShape, planeShape);
btConvexCast* castPtr = &convexCaster1;
- if (castPtr->calcTimeOfImpact(convexFromTrans,convexToTrans,colObjWorldTransform,colObjWorldTransform,castResult))
+ if (castPtr->calcTimeOfImpact(convexFromTrans, convexToTrans, colObjWorldTransform, colObjWorldTransform, castResult))
{
//add hit
if (castResult.m_normal.length2() > btScalar(0.0001))
@@ -743,22 +728,20 @@ void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape,
if (castResult.m_fraction < resultCallback.m_closestHitFraction)
{
castResult.m_normal.normalize();
- btCollisionWorld::LocalConvexResult localConvexResult
- (
+ btCollisionWorld::LocalConvexResult localConvexResult(
colObjWrap->getCollisionObject(),
0,
castResult.m_normal,
castResult.m_hitPoint,
- castResult.m_fraction
- );
+ castResult.m_fraction);
bool normalInWorldSpace = true;
resultCallback.addSingleResult(localConvexResult, normalInWorldSpace);
}
}
}
-
- } else
+ }
+ else
{
//BT_PROFILE("convexSweepConcave");
btConcaveShape* concaveShape = (btConcaveShape*)collisionShape;
@@ -772,44 +755,39 @@ void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape,
struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback
{
btCollisionWorld::ConvexResultCallback* m_resultCallback;
- const btCollisionObject* m_collisionObject;
- btConcaveShape* m_triangleMesh;
-
- BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to,
- btCollisionWorld::ConvexResultCallback* resultCallback, const btCollisionObject* collisionObject,btConcaveShape* triangleMesh, const btTransform& triangleToWorld):
- btTriangleConvexcastCallback(castShape, from,to, triangleToWorld, triangleMesh->getMargin()),
- m_resultCallback(resultCallback),
- m_collisionObject(collisionObject),
- m_triangleMesh(triangleMesh)
+ const btCollisionObject* m_collisionObject;
+ btConcaveShape* m_triangleMesh;
+
+ BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from, const btTransform& to,
+ btCollisionWorld::ConvexResultCallback* resultCallback, const btCollisionObject* collisionObject, btConcaveShape* triangleMesh, const btTransform& triangleToWorld) : btTriangleConvexcastCallback(castShape, from, to, triangleToWorld, triangleMesh->getMargin()),
+ m_resultCallback(resultCallback),
+ m_collisionObject(collisionObject),
+ m_triangleMesh(triangleMesh)
{
}
-
- virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex )
+ virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex)
{
- btCollisionWorld::LocalShapeInfo shapeInfo;
+ btCollisionWorld::LocalShapeInfo shapeInfo;
shapeInfo.m_shapePart = partId;
shapeInfo.m_triangleIndex = triangleIndex;
if (hitFraction <= m_resultCallback->m_closestHitFraction)
{
+ btCollisionWorld::LocalConvexResult convexResult(m_collisionObject,
+ &shapeInfo,
+ hitNormalLocal,
+ hitPointLocal,
+ hitFraction);
- btCollisionWorld::LocalConvexResult convexResult
- (m_collisionObject,
- &shapeInfo,
- hitNormalLocal,
- hitPointLocal,
- hitFraction);
-
- bool normalInWorldSpace = true;
+ bool normalInWorldSpace = true;
- return m_resultCallback->addSingleResult(convexResult,normalInWorldSpace);
+ return m_resultCallback->addSingleResult(convexResult, normalInWorldSpace);
}
return hitFraction;
}
-
};
- BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,colObjWrap->getCollisionObject(),concaveShape, colObjWorldTransform);
+ BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans, convexToTrans, &resultCallback, colObjWrap->getCollisionObject(), concaveShape, colObjWorldTransform);
tccb.m_hitFraction = resultCallback.m_closestHitFraction;
tccb.m_allowedPenetration = allowedPenetration;
btVector3 boxMinLocal, boxMaxLocal;
@@ -821,35 +799,37 @@ void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape,
rayAabbMaxLocal.setMax(convexToLocal);
rayAabbMinLocal += boxMinLocal;
rayAabbMaxLocal += boxMaxLocal;
- concaveShape->processAllTriangles(&tccb,rayAabbMinLocal,rayAabbMaxLocal);
+ concaveShape->processAllTriangles(&tccb, rayAabbMinLocal, rayAabbMaxLocal);
}
}
- } else {
+ }
+ else
+ {
if (collisionShape->isCompound())
{
- struct btCompoundLeafCallback : btDbvt::ICollide
+ struct btCompoundLeafCallback : btDbvt::ICollide
{
btCompoundLeafCallback(
- const btCollisionObjectWrapper* colObjWrap,
- const btConvexShape* castShape,
- const btTransform& convexFromTrans,
- const btTransform& convexToTrans,
- btScalar allowedPenetration,
- const btCompoundShape* compoundShape,
- const btTransform& colObjWorldTransform,
- ConvexResultCallback& resultCallback)
- :
- m_colObjWrap(colObjWrap),
- m_castShape(castShape),
- m_convexFromTrans(convexFromTrans),
- m_convexToTrans(convexToTrans),
- m_allowedPenetration(allowedPenetration),
- m_compoundShape(compoundShape),
- m_colObjWorldTransform(colObjWorldTransform),
- m_resultCallback(resultCallback) {
+ const btCollisionObjectWrapper* colObjWrap,
+ const btConvexShape* castShape,
+ const btTransform& convexFromTrans,
+ const btTransform& convexToTrans,
+ btScalar allowedPenetration,
+ const btCompoundShape* compoundShape,
+ const btTransform& colObjWorldTransform,
+ ConvexResultCallback& resultCallback)
+ : m_colObjWrap(colObjWrap),
+ m_castShape(castShape),
+ m_convexFromTrans(convexFromTrans),
+ m_convexToTrans(convexToTrans),
+ m_allowedPenetration(allowedPenetration),
+ m_compoundShape(compoundShape),
+ m_colObjWorldTransform(colObjWorldTransform),
+ m_resultCallback(resultCallback)
+ {
}
- const btCollisionObjectWrapper* m_colObjWrap;
+ const btCollisionObjectWrapper* m_colObjWrap;
const btConvexShape* m_castShape;
const btTransform& m_convexFromTrans;
const btTransform& m_convexToTrans;
@@ -859,16 +839,16 @@ void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape,
ConvexResultCallback& m_resultCallback;
public:
-
- void ProcessChild(int index, const btTransform& childTrans, const btCollisionShape* childCollisionShape)
+ void ProcessChild(int index, const btTransform& childTrans, const btCollisionShape* childCollisionShape)
{
btTransform childWorldTrans = m_colObjWorldTransform * childTrans;
- struct LocalInfoAdder : public ConvexResultCallback {
+ struct LocalInfoAdder : public ConvexResultCallback
+ {
ConvexResultCallback* m_userCallback;
int m_i;
- LocalInfoAdder(int i, ConvexResultCallback *user)
+ LocalInfoAdder(int i, ConvexResultCallback* user)
: m_userCallback(user), m_i(i)
{
m_closestHitFraction = m_userCallback->m_closestHitFraction;
@@ -877,9 +857,9 @@ void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape,
{
return m_userCallback->needsCollision(p);
}
- virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& r, bool b)
+ virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& r, bool b)
{
- btCollisionWorld::LocalShapeInfo shapeInfo;
+ btCollisionWorld::LocalShapeInfo shapeInfo;
shapeInfo.m_shapePart = -1;
shapeInfo.m_triangleIndex = m_i;
if (r.m_localShapeInfo == NULL)
@@ -887,7 +867,6 @@ void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape,
const btScalar result = m_userCallback->addSingleResult(r, b);
m_closestHitFraction = m_userCallback->m_closestHitFraction;
return result;
-
}
};
@@ -898,7 +877,7 @@ void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape,
objectQuerySingleInternal(m_castShape, m_convexFromTrans, m_convexToTrans, &tmpObj, my_cb, m_allowedPenetration);
}
- void Process(const btDbvtNode* leaf)
+ void Process(const btDbvtNode* leaf)
{
// Processing leaf node
int index = leaf->dataAsInt;
@@ -923,15 +902,18 @@ void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape,
fromLocalAabbMax.setMax(toLocalAabbMax);
btCompoundLeafCallback callback(colObjWrap, castShape, convexFromTrans, convexToTrans,
- allowedPenetration, compoundShape, colObjWorldTransform, resultCallback);
+ allowedPenetration, compoundShape, colObjWorldTransform, resultCallback);
const btDbvt* tree = compoundShape->getDynamicAabbTree();
- if (tree) {
- const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds = btDbvtVolume::FromMM(fromLocalAabbMin, fromLocalAabbMax);
+ if (tree)
+ {
+ const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds = btDbvtVolume::FromMM(fromLocalAabbMin, fromLocalAabbMax);
tree->collideTV(tree->m_root, bounds, callback);
- } else {
+ }
+ else
+ {
int i;
- for (i=0;i<compoundShape->getNumChildShapes();i++)
+ for (i = 0; i < compoundShape->getNumChildShapes(); i++)
{
const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i);
btTransform childTrans = compoundShape->getChildTransform(i);
@@ -943,33 +925,31 @@ void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape,
}
}
-
struct btSingleRayCallback : public btBroadphaseRayCallback
{
-
- btVector3 m_rayFromWorld;
- btVector3 m_rayToWorld;
- btTransform m_rayFromTrans;
- btTransform m_rayToTrans;
- btVector3 m_hitNormal;
-
- const btCollisionWorld* m_world;
- btCollisionWorld::RayResultCallback& m_resultCallback;
-
- btSingleRayCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld,const btCollisionWorld* world,btCollisionWorld::RayResultCallback& resultCallback)
- :m_rayFromWorld(rayFromWorld),
- m_rayToWorld(rayToWorld),
- m_world(world),
- m_resultCallback(resultCallback)
+ btVector3 m_rayFromWorld;
+ btVector3 m_rayToWorld;
+ btTransform m_rayFromTrans;
+ btTransform m_rayToTrans;
+ btVector3 m_hitNormal;
+
+ const btCollisionWorld* m_world;
+ btCollisionWorld::RayResultCallback& m_resultCallback;
+
+ btSingleRayCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld, const btCollisionWorld* world, btCollisionWorld::RayResultCallback& resultCallback)
+ : m_rayFromWorld(rayFromWorld),
+ m_rayToWorld(rayToWorld),
+ m_world(world),
+ m_resultCallback(resultCallback)
{
m_rayFromTrans.setIdentity();
m_rayFromTrans.setOrigin(m_rayFromWorld);
m_rayToTrans.setIdentity();
m_rayToTrans.setOrigin(m_rayToWorld);
- btVector3 rayDir = (rayToWorld-rayFromWorld);
+ btVector3 rayDir = (rayToWorld - rayFromWorld);
- rayDir.normalize ();
+ rayDir.normalize();
///what about division by zero? --> just set rayDirection[i] to INF/BT_LARGE_FLOAT
m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0];
m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1];
@@ -978,22 +958,19 @@ struct btSingleRayCallback : public btBroadphaseRayCallback
m_signs[1] = m_rayDirectionInverse[1] < 0.0;
m_signs[2] = m_rayDirectionInverse[2] < 0.0;
- m_lambda_max = rayDir.dot(m_rayToWorld-m_rayFromWorld);
-
+ m_lambda_max = rayDir.dot(m_rayToWorld - m_rayFromWorld);
}
-
-
- virtual bool process(const btBroadphaseProxy* proxy)
+ virtual bool process(const btBroadphaseProxy* proxy)
{
///terminate further ray tests, once the closestHitFraction reached zero
if (m_resultCallback.m_closestHitFraction == btScalar(0.f))
return false;
- btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
+ btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
//only perform raycast if filterMask matches
- if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
+ if (m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
{
//RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
//btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
@@ -1011,57 +988,53 @@ struct btSingleRayCallback : public btBroadphaseRayCallback
//culling already done by broadphase
//if (btRayAabb(m_rayFromWorld,m_rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,m_hitNormal))
{
- m_world->rayTestSingle(m_rayFromTrans,m_rayToTrans,
- collisionObject,
- collisionObject->getCollisionShape(),
- collisionObject->getWorldTransform(),
- m_resultCallback);
+ m_world->rayTestSingle(m_rayFromTrans, m_rayToTrans,
+ collisionObject,
+ collisionObject->getCollisionShape(),
+ collisionObject->getWorldTransform(),
+ m_resultCallback);
}
}
return true;
}
};
-void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const
+void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const
{
//BT_PROFILE("rayTest");
/// use the broadphase to accelerate the search for objects, based on their aabb
/// and for each object with ray-aabb overlap, perform an exact ray test
- btSingleRayCallback rayCB(rayFromWorld,rayToWorld,this,resultCallback);
+ btSingleRayCallback rayCB(rayFromWorld, rayToWorld, this, resultCallback);
#ifndef USE_BRUTEFORCE_RAYBROADPHASE
- m_broadphasePairCache->rayTest(rayFromWorld,rayToWorld,rayCB);
+ m_broadphasePairCache->rayTest(rayFromWorld, rayToWorld, rayCB);
#else
- for (int i=0;i<this->getNumCollisionObjects();i++)
+ for (int i = 0; i < this->getNumCollisionObjects(); i++)
{
rayCB.process(m_collisionObjects[i]->getBroadphaseHandle());
- }
-#endif //USE_BRUTEFORCE_RAYBROADPHASE
-
+ }
+#endif //USE_BRUTEFORCE_RAYBROADPHASE
}
-
struct btSingleSweepCallback : public btBroadphaseRayCallback
{
-
- btTransform m_convexFromTrans;
- btTransform m_convexToTrans;
- btVector3 m_hitNormal;
- const btCollisionWorld* m_world;
- btCollisionWorld::ConvexResultCallback& m_resultCallback;
- btScalar m_allowedCcdPenetration;
+ btTransform m_convexFromTrans;
+ btTransform m_convexToTrans;
+ btVector3 m_hitNormal;
+ const btCollisionWorld* m_world;
+ btCollisionWorld::ConvexResultCallback& m_resultCallback;
+ btScalar m_allowedCcdPenetration;
const btConvexShape* m_castShape;
-
- btSingleSweepCallback(const btConvexShape* castShape, const btTransform& convexFromTrans,const btTransform& convexToTrans,const btCollisionWorld* world,btCollisionWorld::ConvexResultCallback& resultCallback,btScalar allowedPenetration)
- :m_convexFromTrans(convexFromTrans),
- m_convexToTrans(convexToTrans),
- m_world(world),
- m_resultCallback(resultCallback),
- m_allowedCcdPenetration(allowedPenetration),
- m_castShape(castShape)
+ btSingleSweepCallback(const btConvexShape* castShape, const btTransform& convexFromTrans, const btTransform& convexToTrans, const btCollisionWorld* world, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedPenetration)
+ : m_convexFromTrans(convexFromTrans),
+ m_convexToTrans(convexToTrans),
+ m_world(world),
+ m_resultCallback(resultCallback),
+ m_allowedCcdPenetration(allowedPenetration),
+ m_castShape(castShape)
{
- btVector3 unnormalizedRayDir = (m_convexToTrans.getOrigin()-m_convexFromTrans.getOrigin());
+ btVector3 unnormalizedRayDir = (m_convexToTrans.getOrigin() - m_convexFromTrans.getOrigin());
btVector3 rayDir = unnormalizedRayDir.normalized();
///what about division by zero? --> just set rayDirection[i] to INF/BT_LARGE_FLOAT
m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0];
@@ -1072,109 +1045,102 @@ struct btSingleSweepCallback : public btBroadphaseRayCallback
m_signs[2] = m_rayDirectionInverse[2] < 0.0;
m_lambda_max = rayDir.dot(unnormalizedRayDir);
-
}
- virtual bool process(const btBroadphaseProxy* proxy)
+ virtual bool process(const btBroadphaseProxy* proxy)
{
///terminate further convex sweep tests, once the closestHitFraction reached zero
if (m_resultCallback.m_closestHitFraction == btScalar(0.f))
return false;
- btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
+ btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
//only perform raycast if filterMask matches
- if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) {
+ if (m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
+ {
//RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
- m_world->objectQuerySingle(m_castShape, m_convexFromTrans,m_convexToTrans,
- collisionObject,
- collisionObject->getCollisionShape(),
- collisionObject->getWorldTransform(),
- m_resultCallback,
- m_allowedCcdPenetration);
+ m_world->objectQuerySingle(m_castShape, m_convexFromTrans, m_convexToTrans,
+ collisionObject,
+ collisionObject->getCollisionShape(),
+ collisionObject->getWorldTransform(),
+ m_resultCallback,
+ m_allowedCcdPenetration);
}
return true;
}
};
-
-
-void btCollisionWorld::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration) const
+void btCollisionWorld::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration) const
{
-
BT_PROFILE("convexSweepTest");
/// use the broadphase to accelerate the search for objects, based on their aabb
/// and for each object with ray-aabb overlap, perform an exact ray test
/// unfortunately the implementation for rayTest and convexSweepTest duplicated, albeit practically identical
-
-
- btTransform convexFromTrans,convexToTrans;
+ btTransform convexFromTrans, convexToTrans;
convexFromTrans = convexFromWorld;
convexToTrans = convexToWorld;
btVector3 castShapeAabbMin, castShapeAabbMax;
/* Compute AABB that encompasses angular movement */
{
btVector3 linVel, angVel;
- btTransformUtil::calculateVelocity (convexFromTrans, convexToTrans, 1.0f, linVel, angVel);
+ btTransformUtil::calculateVelocity(convexFromTrans, convexToTrans, 1.0f, linVel, angVel);
btVector3 zeroLinVel;
- zeroLinVel.setValue(0,0,0);
+ zeroLinVel.setValue(0, 0, 0);
btTransform R;
- R.setIdentity ();
- R.setRotation (convexFromTrans.getRotation());
- castShape->calculateTemporalAabb (R, zeroLinVel, angVel, 1.0f, castShapeAabbMin, castShapeAabbMax);
+ R.setIdentity();
+ R.setRotation(convexFromTrans.getRotation());
+ castShape->calculateTemporalAabb(R, zeroLinVel, angVel, 1.0f, castShapeAabbMin, castShapeAabbMax);
}
#ifndef USE_BRUTEFORCE_RAYBROADPHASE
- btSingleSweepCallback convexCB(castShape,convexFromWorld,convexToWorld,this,resultCallback,allowedCcdPenetration);
+ btSingleSweepCallback convexCB(castShape, convexFromWorld, convexToWorld, this, resultCallback, allowedCcdPenetration);
- m_broadphasePairCache->rayTest(convexFromTrans.getOrigin(),convexToTrans.getOrigin(),convexCB,castShapeAabbMin,castShapeAabbMax);
+ m_broadphasePairCache->rayTest(convexFromTrans.getOrigin(), convexToTrans.getOrigin(), convexCB, castShapeAabbMin, castShapeAabbMax);
#else
/// go over all objects, and if the ray intersects their aabb + cast shape aabb,
// do a ray-shape query using convexCaster (CCD)
int i;
- for (i=0;i<m_collisionObjects.size();i++)
+ for (i = 0; i < m_collisionObjects.size(); i++)
{
- btCollisionObject* collisionObject= m_collisionObjects[i];
+ btCollisionObject* collisionObject = m_collisionObjects[i];
//only perform raycast if filterMask matches
- if(resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) {
+ if (resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
+ {
//RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
- btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
- collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
- AabbExpand (collisionObjectAabbMin, collisionObjectAabbMax, castShapeAabbMin, castShapeAabbMax);
- btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing
+ btVector3 collisionObjectAabbMin, collisionObjectAabbMax;
+ collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(), collisionObjectAabbMin, collisionObjectAabbMax);
+ AabbExpand(collisionObjectAabbMin, collisionObjectAabbMax, castShapeAabbMin, castShapeAabbMax);
+ btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing
btVector3 hitNormal;
- if (btRayAabb(convexFromWorld.getOrigin(),convexToWorld.getOrigin(),collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal))
+ if (btRayAabb(convexFromWorld.getOrigin(), convexToWorld.getOrigin(), collisionObjectAabbMin, collisionObjectAabbMax, hitLambda, hitNormal))
{
- objectQuerySingle(castShape, convexFromTrans,convexToTrans,
- collisionObject,
- collisionObject->getCollisionShape(),
- collisionObject->getWorldTransform(),
- resultCallback,
- allowedCcdPenetration);
+ objectQuerySingle(castShape, convexFromTrans, convexToTrans,
+ collisionObject,
+ collisionObject->getCollisionShape(),
+ collisionObject->getWorldTransform(),
+ resultCallback,
+ allowedCcdPenetration);
}
}
}
-#endif //USE_BRUTEFORCE_RAYBROADPHASE
+#endif //USE_BRUTEFORCE_RAYBROADPHASE
}
-
-
struct btBridgedManifoldResult : public btManifoldResult
{
+ btCollisionWorld::ContactResultCallback& m_resultCallback;
- btCollisionWorld::ContactResultCallback& m_resultCallback;
-
- btBridgedManifoldResult( const btCollisionObjectWrapper* obj0Wrap,const btCollisionObjectWrapper* obj1Wrap,btCollisionWorld::ContactResultCallback& resultCallback )
- :btManifoldResult(obj0Wrap,obj1Wrap),
- m_resultCallback(resultCallback)
+ btBridgedManifoldResult(const btCollisionObjectWrapper* obj0Wrap, const btCollisionObjectWrapper* obj1Wrap, btCollisionWorld::ContactResultCallback& resultCallback)
+ : btManifoldResult(obj0Wrap, obj1Wrap),
+ m_resultCallback(resultCallback)
{
}
- virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)
+ virtual void addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar depth)
{
bool isSwapped = m_manifoldPtr->getBody0() != m_body0Wrap->getCollisionObject();
btVector3 pointA = pointInWorld + normalOnBInWorld * depth;
@@ -1182,78 +1148,74 @@ struct btBridgedManifoldResult : public btManifoldResult
btVector3 localB;
if (isSwapped)
{
- localA = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointA );
+ localA = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointA);
localB = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld);
- } else
+ }
+ else
{
- localA = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointA );
+ localA = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointA);
localB = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld);
}
-
- btManifoldPoint newPt(localA,localB,normalOnBInWorld,depth);
+
+ btManifoldPoint newPt(localA, localB, normalOnBInWorld, depth);
newPt.m_positionWorldOnA = pointA;
newPt.m_positionWorldOnB = pointInWorld;
-
- //BP mod, store contact triangles.
+
+ //BP mod, store contact triangles.
if (isSwapped)
{
newPt.m_partId0 = m_partId1;
newPt.m_partId1 = m_partId0;
- newPt.m_index0 = m_index1;
- newPt.m_index1 = m_index0;
- } else
+ newPt.m_index0 = m_index1;
+ newPt.m_index1 = m_index0;
+ }
+ else
{
newPt.m_partId0 = m_partId0;
newPt.m_partId1 = m_partId1;
- newPt.m_index0 = m_index0;
- newPt.m_index1 = m_index1;
+ newPt.m_index0 = m_index0;
+ newPt.m_index1 = m_index1;
}
//experimental feature info, for per-triangle material etc.
- const btCollisionObjectWrapper* obj0Wrap = isSwapped? m_body1Wrap : m_body0Wrap;
- const btCollisionObjectWrapper* obj1Wrap = isSwapped? m_body0Wrap : m_body1Wrap;
- m_resultCallback.addSingleResult(newPt,obj0Wrap,newPt.m_partId0,newPt.m_index0,obj1Wrap,newPt.m_partId1,newPt.m_index1);
-
+ const btCollisionObjectWrapper* obj0Wrap = isSwapped ? m_body1Wrap : m_body0Wrap;
+ const btCollisionObjectWrapper* obj1Wrap = isSwapped ? m_body0Wrap : m_body1Wrap;
+ m_resultCallback.addSingleResult(newPt, obj0Wrap, newPt.m_partId0, newPt.m_index0, obj1Wrap, newPt.m_partId1, newPt.m_index1);
}
-
};
-
-
struct btSingleContactCallback : public btBroadphaseAabbCallback
{
-
btCollisionObject* m_collisionObject;
- btCollisionWorld* m_world;
- btCollisionWorld::ContactResultCallback& m_resultCallback;
-
-
- btSingleContactCallback(btCollisionObject* collisionObject, btCollisionWorld* world,btCollisionWorld::ContactResultCallback& resultCallback)
- :m_collisionObject(collisionObject),
- m_world(world),
- m_resultCallback(resultCallback)
+ btCollisionWorld* m_world;
+ btCollisionWorld::ContactResultCallback& m_resultCallback;
+
+ btSingleContactCallback(btCollisionObject* collisionObject, btCollisionWorld* world, btCollisionWorld::ContactResultCallback& resultCallback)
+ : m_collisionObject(collisionObject),
+ m_world(world),
+ m_resultCallback(resultCallback)
{
}
- virtual bool process(const btBroadphaseProxy* proxy)
+ virtual bool process(const btBroadphaseProxy* proxy)
{
- btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
+ btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
if (collisionObject == m_collisionObject)
return true;
//only perform raycast if filterMask matches
- if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
+ if (m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
{
- btCollisionObjectWrapper ob0(0,m_collisionObject->getCollisionShape(),m_collisionObject,m_collisionObject->getWorldTransform(),-1,-1);
- btCollisionObjectWrapper ob1(0,collisionObject->getCollisionShape(),collisionObject,collisionObject->getWorldTransform(),-1,-1);
+ btCollisionObjectWrapper ob0(0, m_collisionObject->getCollisionShape(), m_collisionObject, m_collisionObject->getWorldTransform(), -1, -1);
+ btCollisionObjectWrapper ob1(0, collisionObject->getCollisionShape(), collisionObject, collisionObject->getWorldTransform(), -1, -1);
- btCollisionAlgorithm* algorithm = m_world->getDispatcher()->findAlgorithm(&ob0,&ob1,0, BT_CLOSEST_POINT_ALGORITHMS);
+ btCollisionAlgorithm* algorithm = m_world->getDispatcher()->findAlgorithm(&ob0, &ob1, 0, BT_CLOSEST_POINT_ALGORITHMS);
if (algorithm)
{
- btBridgedManifoldResult contactPointResult(&ob0,&ob1, m_resultCallback);
+ btBridgedManifoldResult contactPointResult(&ob0, &ob1, m_resultCallback);
//discrete collision detection query
-
- algorithm->processCollision(&ob0,&ob1, m_world->getDispatchInfo(),&contactPointResult);
+
+ algorithm->processCollision(&ob0, &ob1, m_world->getDispatchInfo(), &contactPointResult);
algorithm->~btCollisionAlgorithm();
m_world->getDispatcher()->freeCollisionAlgorithm(algorithm);
@@ -1263,271 +1225,247 @@ struct btSingleContactCallback : public btBroadphaseAabbCallback
}
};
-
///contactTest performs a discrete collision test against all objects in the btCollisionWorld, and calls the resultCallback.
///it reports one or more contact points for every overlapping object (including the one with deepest penetration)
-void btCollisionWorld::contactTest( btCollisionObject* colObj, ContactResultCallback& resultCallback)
+void btCollisionWorld::contactTest(btCollisionObject* colObj, ContactResultCallback& resultCallback)
{
- btVector3 aabbMin,aabbMax;
- colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(),aabbMin,aabbMax);
- btSingleContactCallback contactCB(colObj,this,resultCallback);
-
- m_broadphasePairCache->aabbTest(aabbMin,aabbMax,contactCB);
-}
+ btVector3 aabbMin, aabbMax;
+ colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), aabbMin, aabbMax);
+ btSingleContactCallback contactCB(colObj, this, resultCallback);
+ m_broadphasePairCache->aabbTest(aabbMin, aabbMax, contactCB);
+}
///contactTest performs a discrete collision test between two collision objects and calls the resultCallback if overlap if detected.
///it reports one or more contact points (including the one with deepest penetration)
-void btCollisionWorld::contactPairTest(btCollisionObject* colObjA, btCollisionObject* colObjB, ContactResultCallback& resultCallback)
+void btCollisionWorld::contactPairTest(btCollisionObject* colObjA, btCollisionObject* colObjB, ContactResultCallback& resultCallback)
{
- btCollisionObjectWrapper obA(0,colObjA->getCollisionShape(),colObjA,colObjA->getWorldTransform(),-1,-1);
- btCollisionObjectWrapper obB(0,colObjB->getCollisionShape(),colObjB,colObjB->getWorldTransform(),-1,-1);
+ btCollisionObjectWrapper obA(0, colObjA->getCollisionShape(), colObjA, colObjA->getWorldTransform(), -1, -1);
+ btCollisionObjectWrapper obB(0, colObjB->getCollisionShape(), colObjB, colObjB->getWorldTransform(), -1, -1);
- btCollisionAlgorithm* algorithm = getDispatcher()->findAlgorithm(&obA,&obB, 0, BT_CLOSEST_POINT_ALGORITHMS);
+ btCollisionAlgorithm* algorithm = getDispatcher()->findAlgorithm(&obA, &obB, 0, BT_CLOSEST_POINT_ALGORITHMS);
if (algorithm)
{
- btBridgedManifoldResult contactPointResult(&obA,&obB, resultCallback);
+ btBridgedManifoldResult contactPointResult(&obA, &obB, resultCallback);
contactPointResult.m_closestPointDistanceThreshold = resultCallback.m_closestDistanceThreshold;
//discrete collision detection query
- algorithm->processCollision(&obA,&obB, getDispatchInfo(),&contactPointResult);
+ algorithm->processCollision(&obA, &obB, getDispatchInfo(), &contactPointResult);
algorithm->~btCollisionAlgorithm();
getDispatcher()->freeCollisionAlgorithm(algorithm);
}
-
}
-
-
-
class DebugDrawcallback : public btTriangleCallback, public btInternalTriangleIndexCallback
{
- btIDebugDraw* m_debugDrawer;
- btVector3 m_color;
- btTransform m_worldTrans;
+ btIDebugDraw* m_debugDrawer;
+ btVector3 m_color;
+ btTransform m_worldTrans;
public:
+ DebugDrawcallback(btIDebugDraw* debugDrawer, const btTransform& worldTrans, const btVector3& color) : m_debugDrawer(debugDrawer),
+ m_color(color),
+ m_worldTrans(worldTrans)
+ {
+ }
- DebugDrawcallback(btIDebugDraw* debugDrawer,const btTransform& worldTrans,const btVector3& color) :
- m_debugDrawer(debugDrawer),
- m_color(color),
- m_worldTrans(worldTrans)
- {
- }
-
- virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex)
- {
- processTriangle(triangle,partId,triangleIndex);
- }
-
- virtual void processTriangle(btVector3* triangle,int partId, int triangleIndex)
- {
- (void)partId;
- (void)triangleIndex;
-
- btVector3 wv0,wv1,wv2;
- wv0 = m_worldTrans*triangle[0];
- wv1 = m_worldTrans*triangle[1];
- wv2 = m_worldTrans*triangle[2];
- btVector3 center = (wv0+wv1+wv2)*btScalar(1./3.);
-
- if (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawNormals )
- {
- btVector3 normal = (wv1-wv0).cross(wv2-wv0);
- normal.normalize();
- btVector3 normalColor(1,1,0);
- m_debugDrawer->drawLine(center,center+normal,normalColor);
- }
- m_debugDrawer->drawLine(wv0,wv1,m_color);
- m_debugDrawer->drawLine(wv1,wv2,m_color);
- m_debugDrawer->drawLine(wv2,wv0,m_color);
- }
-};
+ virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
+ {
+ processTriangle(triangle, partId, triangleIndex);
+ }
+ virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
+ {
+ (void)partId;
+ (void)triangleIndex;
+
+ btVector3 wv0, wv1, wv2;
+ wv0 = m_worldTrans * triangle[0];
+ wv1 = m_worldTrans * triangle[1];
+ wv2 = m_worldTrans * triangle[2];
+ btVector3 center = (wv0 + wv1 + wv2) * btScalar(1. / 3.);
+
+ if (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawNormals)
+ {
+ btVector3 normal = (wv1 - wv0).cross(wv2 - wv0);
+ normal.normalize();
+ btVector3 normalColor(1, 1, 0);
+ m_debugDrawer->drawLine(center, center + normal, normalColor);
+ }
+ m_debugDrawer->drawLine(wv0, wv1, m_color);
+ m_debugDrawer->drawLine(wv1, wv2, m_color);
+ m_debugDrawer->drawLine(wv2, wv0, m_color);
+ }
+};
void btCollisionWorld::debugDrawObject(const btTransform& worldTransform, const btCollisionShape* shape, const btVector3& color)
{
// Draw a small simplex at the center of the object
if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawFrames)
{
- getDebugDrawer()->drawTransform(worldTransform,.1);
+ getDebugDrawer()->drawTransform(worldTransform, .1);
}
if (shape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE)
{
const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(shape);
- for (int i=compoundShape->getNumChildShapes()-1;i>=0;i--)
+ for (int i = compoundShape->getNumChildShapes() - 1; i >= 0; i--)
{
btTransform childTrans = compoundShape->getChildTransform(i);
const btCollisionShape* colShape = compoundShape->getChildShape(i);
- debugDrawObject(worldTransform*childTrans,colShape,color);
+ debugDrawObject(worldTransform * childTrans, colShape, color);
}
-
- } else
+ }
+ else
{
+ switch (shape->getShapeType())
+ {
+ case BOX_SHAPE_PROXYTYPE:
+ {
+ const btBoxShape* boxShape = static_cast<const btBoxShape*>(shape);
+ btVector3 halfExtents = boxShape->getHalfExtentsWithMargin();
+ getDebugDrawer()->drawBox(-halfExtents, halfExtents, worldTransform, color);
+ break;
+ }
+
+ case SPHERE_SHAPE_PROXYTYPE:
+ {
+ const btSphereShape* sphereShape = static_cast<const btSphereShape*>(shape);
+ btScalar radius = sphereShape->getMargin(); //radius doesn't include the margin, so draw with margin
+
+ getDebugDrawer()->drawSphere(radius, worldTransform, color);
+ break;
+ }
+ case MULTI_SPHERE_SHAPE_PROXYTYPE:
+ {
+ const btMultiSphereShape* multiSphereShape = static_cast<const btMultiSphereShape*>(shape);
+
+ btTransform childTransform;
+ childTransform.setIdentity();
+
+ for (int i = multiSphereShape->getSphereCount() - 1; i >= 0; i--)
+ {
+ childTransform.setOrigin(multiSphereShape->getSpherePosition(i));
+ getDebugDrawer()->drawSphere(multiSphereShape->getSphereRadius(i), worldTransform * childTransform, color);
+ }
+
+ break;
+ }
+ case CAPSULE_SHAPE_PROXYTYPE:
+ {
+ const btCapsuleShape* capsuleShape = static_cast<const btCapsuleShape*>(shape);
- switch (shape->getShapeType())
- {
-
- case BOX_SHAPE_PROXYTYPE:
- {
- const btBoxShape* boxShape = static_cast<const btBoxShape*>(shape);
- btVector3 halfExtents = boxShape->getHalfExtentsWithMargin();
- getDebugDrawer()->drawBox(-halfExtents,halfExtents,worldTransform,color);
- break;
- }
-
- case SPHERE_SHAPE_PROXYTYPE:
- {
- const btSphereShape* sphereShape = static_cast<const btSphereShape*>(shape);
- btScalar radius = sphereShape->getMargin();//radius doesn't include the margin, so draw with margin
-
- getDebugDrawer()->drawSphere(radius, worldTransform, color);
- break;
- }
- case MULTI_SPHERE_SHAPE_PROXYTYPE:
- {
- const btMultiSphereShape* multiSphereShape = static_cast<const btMultiSphereShape*>(shape);
-
- btTransform childTransform;
- childTransform.setIdentity();
-
- for (int i = multiSphereShape->getSphereCount()-1; i>=0;i--)
- {
- childTransform.setOrigin(multiSphereShape->getSpherePosition(i));
- getDebugDrawer()->drawSphere(multiSphereShape->getSphereRadius(i), worldTransform*childTransform, color);
- }
-
- break;
- }
- case CAPSULE_SHAPE_PROXYTYPE:
- {
- const btCapsuleShape* capsuleShape = static_cast<const btCapsuleShape*>(shape);
-
- btScalar radius = capsuleShape->getRadius();
- btScalar halfHeight = capsuleShape->getHalfHeight();
-
- int upAxis = capsuleShape->getUpAxis();
- getDebugDrawer()->drawCapsule(radius, halfHeight, upAxis, worldTransform, color);
- break;
- }
- case CONE_SHAPE_PROXYTYPE:
- {
- const btConeShape* coneShape = static_cast<const btConeShape*>(shape);
- btScalar radius = coneShape->getRadius();//+coneShape->getMargin();
- btScalar height = coneShape->getHeight();//+coneShape->getMargin();
-
- int upAxis= coneShape->getConeUpIndex();
- getDebugDrawer()->drawCone(radius, height, upAxis, worldTransform, color);
- break;
-
- }
- case CYLINDER_SHAPE_PROXYTYPE:
- {
- const btCylinderShape* cylinder = static_cast<const btCylinderShape*>(shape);
- int upAxis = cylinder->getUpAxis();
- btScalar radius = cylinder->getRadius();
- btScalar halfHeight = cylinder->getHalfExtentsWithMargin()[upAxis];
- getDebugDrawer()->drawCylinder(radius, halfHeight, upAxis, worldTransform, color);
- break;
- }
-
- case STATIC_PLANE_PROXYTYPE:
- {
- const btStaticPlaneShape* staticPlaneShape = static_cast<const btStaticPlaneShape*>(shape);
- btScalar planeConst = staticPlaneShape->getPlaneConstant();
- const btVector3& planeNormal = staticPlaneShape->getPlaneNormal();
- getDebugDrawer()->drawPlane(planeNormal, planeConst,worldTransform, color);
- break;
-
- }
- default:
- {
-
- /// for polyhedral shapes
- if (shape->isPolyhedral())
- {
- btPolyhedralConvexShape* polyshape = (btPolyhedralConvexShape*) shape;
-
- int i;
- if (polyshape->getConvexPolyhedron())
- {
- const btConvexPolyhedron* poly = polyshape->getConvexPolyhedron();
- for (i=0;i<poly->m_faces.size();i++)
- {
- btVector3 centroid(0,0,0);
- int numVerts = poly->m_faces[i].m_indices.size();
- if (numVerts)
- {
- int lastV = poly->m_faces[i].m_indices[numVerts-1];
- for (int v=0;v<poly->m_faces[i].m_indices.size();v++)
- {
- int curVert = poly->m_faces[i].m_indices[v];
- centroid+=poly->m_vertices[curVert];
- getDebugDrawer()->drawLine(worldTransform*poly->m_vertices[lastV],worldTransform*poly->m_vertices[curVert],color);
- lastV = curVert;
- }
- }
- centroid*= btScalar(1.f)/btScalar(numVerts);
- if (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawNormals)
- {
- btVector3 normalColor(1,1,0);
- btVector3 faceNormal(poly->m_faces[i].m_plane[0],poly->m_faces[i].m_plane[1],poly->m_faces[i].m_plane[2]);
- getDebugDrawer()->drawLine(worldTransform*centroid,worldTransform*(centroid+faceNormal),normalColor);
- }
-
- }
-
-
- } else
- {
- for (i=0;i<polyshape->getNumEdges();i++)
- {
- btVector3 a,b;
- polyshape->getEdge(i,a,b);
- btVector3 wa = worldTransform * a;
- btVector3 wb = worldTransform * b;
- getDebugDrawer()->drawLine(wa,wb,color);
- }
- }
-
-
- }
-
- if (shape->isConcave())
- {
- btConcaveShape* concaveMesh = (btConcaveShape*) shape;
-
- ///@todo pass camera, for some culling? no -> we are not a graphics lib
- btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
- btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
-
- DebugDrawcallback drawCallback(getDebugDrawer(),worldTransform,color);
- concaveMesh->processAllTriangles(&drawCallback,aabbMin,aabbMax);
-
- }
-
- if (shape->getShapeType() == CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE)
- {
- btConvexTriangleMeshShape* convexMesh = (btConvexTriangleMeshShape*) shape;
- //todo: pass camera for some culling
- btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
- btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
- //DebugDrawcallback drawCallback;
- DebugDrawcallback drawCallback(getDebugDrawer(),worldTransform,color);
- convexMesh->getMeshInterface()->InternalProcessAllTriangles(&drawCallback,aabbMin,aabbMax);
- }
-
-
-
- }
-
+ btScalar radius = capsuleShape->getRadius();
+ btScalar halfHeight = capsuleShape->getHalfHeight();
+
+ int upAxis = capsuleShape->getUpAxis();
+ getDebugDrawer()->drawCapsule(radius, halfHeight, upAxis, worldTransform, color);
+ break;
+ }
+ case CONE_SHAPE_PROXYTYPE:
+ {
+ const btConeShape* coneShape = static_cast<const btConeShape*>(shape);
+ btScalar radius = coneShape->getRadius(); //+coneShape->getMargin();
+ btScalar height = coneShape->getHeight(); //+coneShape->getMargin();
+
+ int upAxis = coneShape->getConeUpIndex();
+ getDebugDrawer()->drawCone(radius, height, upAxis, worldTransform, color);
+ break;
+ }
+ case CYLINDER_SHAPE_PROXYTYPE:
+ {
+ const btCylinderShape* cylinder = static_cast<const btCylinderShape*>(shape);
+ int upAxis = cylinder->getUpAxis();
+ btScalar radius = cylinder->getRadius();
+ btScalar halfHeight = cylinder->getHalfExtentsWithMargin()[upAxis];
+ getDebugDrawer()->drawCylinder(radius, halfHeight, upAxis, worldTransform, color);
+ break;
+ }
+
+ case STATIC_PLANE_PROXYTYPE:
+ {
+ const btStaticPlaneShape* staticPlaneShape = static_cast<const btStaticPlaneShape*>(shape);
+ btScalar planeConst = staticPlaneShape->getPlaneConstant();
+ const btVector3& planeNormal = staticPlaneShape->getPlaneNormal();
+ getDebugDrawer()->drawPlane(planeNormal, planeConst, worldTransform, color);
+ break;
+ }
+ default:
+ {
+ /// for polyhedral shapes
+ if (shape->isPolyhedral())
+ {
+ btPolyhedralConvexShape* polyshape = (btPolyhedralConvexShape*)shape;
+
+ int i;
+ if (polyshape->getConvexPolyhedron())
+ {
+ const btConvexPolyhedron* poly = polyshape->getConvexPolyhedron();
+ for (i = 0; i < poly->m_faces.size(); i++)
+ {
+ btVector3 centroid(0, 0, 0);
+ int numVerts = poly->m_faces[i].m_indices.size();
+ if (numVerts)
+ {
+ int lastV = poly->m_faces[i].m_indices[numVerts - 1];
+ for (int v = 0; v < poly->m_faces[i].m_indices.size(); v++)
+ {
+ int curVert = poly->m_faces[i].m_indices[v];
+ centroid += poly->m_vertices[curVert];
+ getDebugDrawer()->drawLine(worldTransform * poly->m_vertices[lastV], worldTransform * poly->m_vertices[curVert], color);
+ lastV = curVert;
+ }
+ }
+ centroid *= btScalar(1.f) / btScalar(numVerts);
+ if (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawNormals)
+ {
+ btVector3 normalColor(1, 1, 0);
+ btVector3 faceNormal(poly->m_faces[i].m_plane[0], poly->m_faces[i].m_plane[1], poly->m_faces[i].m_plane[2]);
+ getDebugDrawer()->drawLine(worldTransform * centroid, worldTransform * (centroid + faceNormal), normalColor);
+ }
+ }
+ }
+ else
+ {
+ for (i = 0; i < polyshape->getNumEdges(); i++)
+ {
+ btVector3 a, b;
+ polyshape->getEdge(i, a, b);
+ btVector3 wa = worldTransform * a;
+ btVector3 wb = worldTransform * b;
+ getDebugDrawer()->drawLine(wa, wb, color);
+ }
+ }
+ }
+
+ if (shape->isConcave())
+ {
+ btConcaveShape* concaveMesh = (btConcaveShape*)shape;
+
+ ///@todo pass camera, for some culling? no -> we are not a graphics lib
+ btVector3 aabbMax(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
+ btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
+
+ DebugDrawcallback drawCallback(getDebugDrawer(), worldTransform, color);
+ concaveMesh->processAllTriangles(&drawCallback, aabbMin, aabbMax);
+ }
+
+ if (shape->getShapeType() == CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE)
+ {
+ btConvexTriangleMeshShape* convexMesh = (btConvexTriangleMeshShape*)shape;
+ //todo: pass camera for some culling
+ btVector3 aabbMax(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
+ btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
+ //DebugDrawcallback drawCallback;
+ DebugDrawcallback drawCallback(getDebugDrawer(), worldTransform, color);
+ convexMesh->getMeshInterface()->InternalProcessAllTriangles(&drawCallback, aabbMin, aabbMax);
+ }
+ }
}
}
}
-
-void btCollisionWorld::debugDrawWorld()
+void btCollisionWorld::debugDrawWorld()
{
if (getDebugDrawer())
{
@@ -1535,25 +1473,23 @@ void btCollisionWorld::debugDrawWorld()
btIDebugDraw::DefaultColors defaultColors = getDebugDrawer()->getDefaultColors();
- if ( getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints)
+ if (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints)
{
-
-
if (getDispatcher())
{
int numManifolds = getDispatcher()->getNumManifolds();
-
- for (int i=0;i<numManifolds;i++)
+
+ for (int i = 0; i < numManifolds; i++)
{
btPersistentManifold* contactManifold = getDispatcher()->getManifoldByIndexInternal(i);
//btCollisionObject* obA = static_cast<btCollisionObject*>(contactManifold->getBody0());
//btCollisionObject* obB = static_cast<btCollisionObject*>(contactManifold->getBody1());
int numContacts = contactManifold->getNumContacts();
- for (int j=0;j<numContacts;j++)
+ for (int j = 0; j < numContacts; j++)
{
btManifoldPoint& cp = contactManifold->getContactPoint(j);
- getDebugDrawer()->drawContactPoint(cp.m_positionWorldOnB,cp.m_normalWorldOnB,cp.getDistance(),cp.getLifeTime(),defaultColors.m_contactPoint);
+ getDebugDrawer()->drawContactPoint(cp.m_positionWorldOnB, cp.m_normalWorldOnB, cp.getDistance(), cp.getLifeTime(), defaultColors.m_contactPoint);
}
}
}
@@ -1563,58 +1499,63 @@ void btCollisionWorld::debugDrawWorld()
{
int i;
- for ( i=0;i<m_collisionObjects.size();i++)
+ for (i = 0; i < m_collisionObjects.size(); i++)
{
btCollisionObject* colObj = m_collisionObjects[i];
- if ((colObj->getCollisionFlags() & btCollisionObject::CF_DISABLE_VISUALIZE_OBJECT)==0)
+ if ((colObj->getCollisionFlags() & btCollisionObject::CF_DISABLE_VISUALIZE_OBJECT) == 0)
{
if (getDebugDrawer() && (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawWireframe))
{
- btVector3 color(btScalar(0.4),btScalar(0.4),btScalar(0.4));
+ btVector3 color(btScalar(0.4), btScalar(0.4), btScalar(0.4));
- switch(colObj->getActivationState())
+ switch (colObj->getActivationState())
{
- case ACTIVE_TAG:
- color = defaultColors.m_activeObject; break;
- case ISLAND_SLEEPING:
- color = defaultColors.m_deactivatedObject;break;
- case WANTS_DEACTIVATION:
- color = defaultColors.m_wantsDeactivationObject;break;
- case DISABLE_DEACTIVATION:
- color = defaultColors.m_disabledDeactivationObject;break;
- case DISABLE_SIMULATION:
- color = defaultColors.m_disabledSimulationObject;break;
- default:
+ case ACTIVE_TAG:
+ color = defaultColors.m_activeObject;
+ break;
+ case ISLAND_SLEEPING:
+ color = defaultColors.m_deactivatedObject;
+ break;
+ case WANTS_DEACTIVATION:
+ color = defaultColors.m_wantsDeactivationObject;
+ break;
+ case DISABLE_DEACTIVATION:
+ color = defaultColors.m_disabledDeactivationObject;
+ break;
+ case DISABLE_SIMULATION:
+ color = defaultColors.m_disabledSimulationObject;
+ break;
+ default:
{
- color = btVector3(btScalar(.3),btScalar(0.3),btScalar(0.3));
+ color = btVector3(btScalar(.3), btScalar(0.3), btScalar(0.3));
}
};
colObj->getCustomDebugColor(color);
- debugDrawObject(colObj->getWorldTransform(),colObj->getCollisionShape(),color);
+ debugDrawObject(colObj->getWorldTransform(), colObj->getCollisionShape(), color);
}
if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
{
- btVector3 minAabb,maxAabb;
+ btVector3 minAabb, maxAabb;
btVector3 colorvec = defaultColors.m_aabb;
- colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb);
- btVector3 contactThreshold(gContactBreakingThreshold,gContactBreakingThreshold,gContactBreakingThreshold);
+ colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb, maxAabb);
+ btVector3 contactThreshold(gContactBreakingThreshold, gContactBreakingThreshold, gContactBreakingThreshold);
minAabb -= contactThreshold;
maxAabb += contactThreshold;
- btVector3 minAabb2,maxAabb2;
+ btVector3 minAabb2, maxAabb2;
- if(getDispatchInfo().m_useContinuous && colObj->getInternalType()==btCollisionObject::CO_RIGID_BODY && !colObj->isStaticOrKinematicObject())
+ if (getDispatchInfo().m_useContinuous && colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY && !colObj->isStaticOrKinematicObject())
{
- colObj->getCollisionShape()->getAabb(colObj->getInterpolationWorldTransform(),minAabb2,maxAabb2);
+ colObj->getCollisionShape()->getAabb(colObj->getInterpolationWorldTransform(), minAabb2, maxAabb2);
minAabb2 -= contactThreshold;
maxAabb2 += contactThreshold;
minAabb.setMin(minAabb2);
maxAabb.setMax(maxAabb2);
}
- m_debugDrawer->drawAabb(minAabb,maxAabb,colorvec);
+ m_debugDrawer->drawAabb(minAabb, maxAabb, colorvec);
}
}
}
@@ -1622,28 +1563,27 @@ void btCollisionWorld::debugDrawWorld()
}
}
-
-void btCollisionWorld::serializeCollisionObjects(btSerializer* serializer)
+void btCollisionWorld::serializeCollisionObjects(btSerializer* serializer)
{
int i;
///keep track of shapes already serialized
- btHashMap<btHashPtr,btCollisionShape*> serializedShapes;
+ btHashMap<btHashPtr, btCollisionShape*> serializedShapes;
- for (i=0;i<m_collisionObjects.size();i++)
+ for (i = 0; i < m_collisionObjects.size(); i++)
{
btCollisionObject* colObj = m_collisionObjects[i];
btCollisionShape* shape = colObj->getCollisionShape();
if (!serializedShapes.find(shape))
{
- serializedShapes.insert(shape,shape);
+ serializedShapes.insert(shape, shape);
shape->serializeSingleShape(serializer);
}
}
//serialize all collision objects
- for (i=0;i<m_collisionObjects.size();i++)
+ for (i = 0; i < m_collisionObjects.size(); i++)
{
btCollisionObject* colObj = m_collisionObjects[i];
if (colObj->getInternalType() == btCollisionObject::CO_COLLISION_OBJECT)
@@ -1653,8 +1593,6 @@ void btCollisionWorld::serializeCollisionObjects(btSerializer* serializer)
}
}
-
-
void btCollisionWorld::serializeContactManifolds(btSerializer* serializer)
{
if (serializer->getSerializationFlags() & BT_SERIALIZE_CONTACT_MANIFOLDS)
@@ -1663,7 +1601,7 @@ void btCollisionWorld::serializeContactManifolds(btSerializer* serializer)
for (int i = 0; i < numManifolds; i++)
{
const btPersistentManifold* manifold = getDispatcher()->getInternalManifoldPointer()[i];
- //don't serialize empty manifolds, they just take space
+ //don't serialize empty manifolds, they just take space
//(may have to do it anyway if it destroys determinism)
if (manifold->getNumContacts() == 0)
continue;
@@ -1675,16 +1613,13 @@ void btCollisionWorld::serializeContactManifolds(btSerializer* serializer)
}
}
-
-void btCollisionWorld::serialize(btSerializer* serializer)
+void btCollisionWorld::serialize(btSerializer* serializer)
{
-
serializer->startSerialization();
-
+
serializeCollisionObjects(serializer);
serializeContactManifolds(serializer);
-
+
serializer->finishSerialization();
}
-
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.h
index 886476e8ad..fd0e5b9bbd 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.h
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.h
@@ -13,7 +13,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
/**
* @mainpage Bullet Documentation
*
@@ -66,8 +65,6 @@ subject to the following restrictions:
* For up-to-data information and copyright and contributors list check out the Bullet_User_Manual.pdf
*
*/
-
-
#ifndef BT_COLLISION_WORLD_H
#define BT_COLLISION_WORLD_H
@@ -87,147 +84,138 @@ class btSerializer;
///CollisionWorld is interface and container for the collision detection
class btCollisionWorld
{
-
-
protected:
+ btAlignedObjectArray<btCollisionObject*> m_collisionObjects;
- btAlignedObjectArray<btCollisionObject*> m_collisionObjects;
-
- btDispatcher* m_dispatcher1;
+ btDispatcher* m_dispatcher1;
- btDispatcherInfo m_dispatchInfo;
+ btDispatcherInfo m_dispatchInfo;
- btBroadphaseInterface* m_broadphasePairCache;
+ btBroadphaseInterface* m_broadphasePairCache;
- btIDebugDraw* m_debugDrawer;
+ btIDebugDraw* m_debugDrawer;
///m_forceUpdateAllAabbs can be set to false as an optimization to only update active object AABBs
///it is true by default, because it is error-prone (setting the position of static objects wouldn't update their AABB)
bool m_forceUpdateAllAabbs;
- void serializeCollisionObjects(btSerializer* serializer);
+ void serializeCollisionObjects(btSerializer* serializer);
void serializeContactManifolds(btSerializer* serializer);
-
public:
-
//this constructor doesn't own the dispatcher and paircache/broadphase
- btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphasePairCache, btCollisionConfiguration* collisionConfiguration);
+ btCollisionWorld(btDispatcher* dispatcher, btBroadphaseInterface* broadphasePairCache, btCollisionConfiguration* collisionConfiguration);
virtual ~btCollisionWorld();
- void setBroadphase(btBroadphaseInterface* pairCache)
+ void setBroadphase(btBroadphaseInterface* pairCache)
{
m_broadphasePairCache = pairCache;
}
- const btBroadphaseInterface* getBroadphase() const
+ const btBroadphaseInterface* getBroadphase() const
{
return m_broadphasePairCache;
}
- btBroadphaseInterface* getBroadphase()
+ btBroadphaseInterface* getBroadphase()
{
return m_broadphasePairCache;
}
- btOverlappingPairCache* getPairCache()
+ btOverlappingPairCache* getPairCache()
{
return m_broadphasePairCache->getOverlappingPairCache();
}
-
- btDispatcher* getDispatcher()
+ btDispatcher* getDispatcher()
{
return m_dispatcher1;
}
- const btDispatcher* getDispatcher() const
+ const btDispatcher* getDispatcher() const
{
return m_dispatcher1;
}
- void updateSingleAabb(btCollisionObject* colObj);
+ void updateSingleAabb(btCollisionObject* colObj);
- virtual void updateAabbs();
+ virtual void updateAabbs();
///the computeOverlappingPairs is usually already called by performDiscreteCollisionDetection (or stepSimulation)
///it can be useful to use if you perform ray tests without collision detection/simulation
- virtual void computeOverlappingPairs();
+ virtual void computeOverlappingPairs();
-
- virtual void setDebugDrawer(btIDebugDraw* debugDrawer)
+ virtual void setDebugDrawer(btIDebugDraw* debugDrawer)
{
- m_debugDrawer = debugDrawer;
+ m_debugDrawer = debugDrawer;
}
- virtual btIDebugDraw* getDebugDrawer()
+ virtual btIDebugDraw* getDebugDrawer()
{
return m_debugDrawer;
}
- virtual void debugDrawWorld();
+ virtual void debugDrawWorld();
virtual void debugDrawObject(const btTransform& worldTransform, const btCollisionShape* shape, const btVector3& color);
-
///LocalShapeInfo gives extra information for complex shapes
///Currently, only btTriangleMeshShape is available, so it just contains triangleIndex and subpart
- struct LocalShapeInfo
+ struct LocalShapeInfo
{
- int m_shapePart;
- int m_triangleIndex;
-
+ int m_shapePart;
+ int m_triangleIndex;
+
//const btCollisionShape* m_shapeTemp;
//const btTransform* m_shapeLocalTransform;
};
- struct LocalRayResult
+ struct LocalRayResult
{
- LocalRayResult(const btCollisionObject* collisionObject,
- LocalShapeInfo* localShapeInfo,
- const btVector3& hitNormalLocal,
- btScalar hitFraction)
- :m_collisionObject(collisionObject),
- m_localShapeInfo(localShapeInfo),
- m_hitNormalLocal(hitNormalLocal),
- m_hitFraction(hitFraction)
+ LocalRayResult(const btCollisionObject* collisionObject,
+ LocalShapeInfo* localShapeInfo,
+ const btVector3& hitNormalLocal,
+ btScalar hitFraction)
+ : m_collisionObject(collisionObject),
+ m_localShapeInfo(localShapeInfo),
+ m_hitNormalLocal(hitNormalLocal),
+ m_hitFraction(hitFraction)
{
}
- const btCollisionObject* m_collisionObject;
- LocalShapeInfo* m_localShapeInfo;
- btVector3 m_hitNormalLocal;
- btScalar m_hitFraction;
-
+ const btCollisionObject* m_collisionObject;
+ LocalShapeInfo* m_localShapeInfo;
+ btVector3 m_hitNormalLocal;
+ btScalar m_hitFraction;
};
///RayResultCallback is used to report new raycast results
- struct RayResultCallback
+ struct RayResultCallback
{
- btScalar m_closestHitFraction;
- const btCollisionObject* m_collisionObject;
- int m_collisionFilterGroup;
- int m_collisionFilterMask;
+ btScalar m_closestHitFraction;
+ const btCollisionObject* m_collisionObject;
+ int m_collisionFilterGroup;
+ int m_collisionFilterMask;
//@BP Mod - Custom flags, currently used to enable backface culling on tri-meshes, see btRaycastCallback.h. Apply any of the EFlags defined there on m_flags here to invoke.
unsigned int m_flags;
virtual ~RayResultCallback()
{
}
- bool hasHit() const
+ bool hasHit() const
{
return (m_collisionObject != 0);
}
RayResultCallback()
- :m_closestHitFraction(btScalar(1.)),
- m_collisionObject(0),
- m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
- m_collisionFilterMask(btBroadphaseProxy::AllFilter),
- //@BP Mod
- m_flags(0)
+ : m_closestHitFraction(btScalar(1.)),
+ m_collisionObject(0),
+ m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
+ m_collisionFilterMask(btBroadphaseProxy::AllFilter),
+ //@BP Mod
+ m_flags(0)
{
}
@@ -238,62 +226,62 @@ public:
return collides;
}
-
- virtual btScalar addSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace) = 0;
+ virtual btScalar addSingleResult(LocalRayResult& rayResult, bool normalInWorldSpace) = 0;
};
- struct ClosestRayResultCallback : public RayResultCallback
+ struct ClosestRayResultCallback : public RayResultCallback
{
- ClosestRayResultCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld)
- :m_rayFromWorld(rayFromWorld),
- m_rayToWorld(rayToWorld)
+ ClosestRayResultCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld)
+ : m_rayFromWorld(rayFromWorld),
+ m_rayToWorld(rayToWorld)
{
}
- btVector3 m_rayFromWorld;//used to calculate hitPointWorld from hitFraction
- btVector3 m_rayToWorld;
+ btVector3 m_rayFromWorld; //used to calculate hitPointWorld from hitFraction
+ btVector3 m_rayToWorld;
+
+ btVector3 m_hitNormalWorld;
+ btVector3 m_hitPointWorld;
- btVector3 m_hitNormalWorld;
- btVector3 m_hitPointWorld;
-
- virtual btScalar addSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace)
+ virtual btScalar addSingleResult(LocalRayResult& rayResult, bool normalInWorldSpace)
{
//caller already does the filter on the m_closestHitFraction
btAssert(rayResult.m_hitFraction <= m_closestHitFraction);
-
+
m_closestHitFraction = rayResult.m_hitFraction;
m_collisionObject = rayResult.m_collisionObject;
if (normalInWorldSpace)
{
m_hitNormalWorld = rayResult.m_hitNormalLocal;
- } else
+ }
+ else
{
///need to transform normal into worldspace
- m_hitNormalWorld = m_collisionObject->getWorldTransform().getBasis()*rayResult.m_hitNormalLocal;
+ m_hitNormalWorld = m_collisionObject->getWorldTransform().getBasis() * rayResult.m_hitNormalLocal;
}
- m_hitPointWorld.setInterpolate3(m_rayFromWorld,m_rayToWorld,rayResult.m_hitFraction);
+ m_hitPointWorld.setInterpolate3(m_rayFromWorld, m_rayToWorld, rayResult.m_hitFraction);
return rayResult.m_hitFraction;
}
};
- struct AllHitsRayResultCallback : public RayResultCallback
+ struct AllHitsRayResultCallback : public RayResultCallback
{
- AllHitsRayResultCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld)
- :m_rayFromWorld(rayFromWorld),
- m_rayToWorld(rayToWorld)
+ AllHitsRayResultCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld)
+ : m_rayFromWorld(rayFromWorld),
+ m_rayToWorld(rayToWorld)
{
}
- btAlignedObjectArray<const btCollisionObject*> m_collisionObjects;
+ btAlignedObjectArray<const btCollisionObject*> m_collisionObjects;
- btVector3 m_rayFromWorld;//used to calculate hitPointWorld from hitFraction
- btVector3 m_rayToWorld;
+ btVector3 m_rayFromWorld; //used to calculate hitPointWorld from hitFraction
+ btVector3 m_rayToWorld;
- btAlignedObjectArray<btVector3> m_hitNormalWorld;
- btAlignedObjectArray<btVector3> m_hitPointWorld;
+ btAlignedObjectArray<btVector3> m_hitNormalWorld;
+ btAlignedObjectArray<btVector3> m_hitPointWorld;
btAlignedObjectArray<btScalar> m_hitFractions;
-
- virtual btScalar addSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace)
+
+ virtual btScalar addSingleResult(LocalRayResult& rayResult, bool normalInWorldSpace)
{
m_collisionObject = rayResult.m_collisionObject;
m_collisionObjects.push_back(rayResult.m_collisionObject);
@@ -301,69 +289,66 @@ public:
if (normalInWorldSpace)
{
hitNormalWorld = rayResult.m_hitNormalLocal;
- } else
+ }
+ else
{
///need to transform normal into worldspace
- hitNormalWorld = m_collisionObject->getWorldTransform().getBasis()*rayResult.m_hitNormalLocal;
+ hitNormalWorld = m_collisionObject->getWorldTransform().getBasis() * rayResult.m_hitNormalLocal;
}
m_hitNormalWorld.push_back(hitNormalWorld);
btVector3 hitPointWorld;
- hitPointWorld.setInterpolate3(m_rayFromWorld,m_rayToWorld,rayResult.m_hitFraction);
+ hitPointWorld.setInterpolate3(m_rayFromWorld, m_rayToWorld, rayResult.m_hitFraction);
m_hitPointWorld.push_back(hitPointWorld);
m_hitFractions.push_back(rayResult.m_hitFraction);
return m_closestHitFraction;
}
};
-
struct LocalConvexResult
{
- LocalConvexResult(const btCollisionObject* hitCollisionObject,
- LocalShapeInfo* localShapeInfo,
- const btVector3& hitNormalLocal,
- const btVector3& hitPointLocal,
- btScalar hitFraction
- )
- :m_hitCollisionObject(hitCollisionObject),
- m_localShapeInfo(localShapeInfo),
- m_hitNormalLocal(hitNormalLocal),
- m_hitPointLocal(hitPointLocal),
- m_hitFraction(hitFraction)
+ LocalConvexResult(const btCollisionObject* hitCollisionObject,
+ LocalShapeInfo* localShapeInfo,
+ const btVector3& hitNormalLocal,
+ const btVector3& hitPointLocal,
+ btScalar hitFraction)
+ : m_hitCollisionObject(hitCollisionObject),
+ m_localShapeInfo(localShapeInfo),
+ m_hitNormalLocal(hitNormalLocal),
+ m_hitPointLocal(hitPointLocal),
+ m_hitFraction(hitFraction)
{
}
- const btCollisionObject* m_hitCollisionObject;
- LocalShapeInfo* m_localShapeInfo;
- btVector3 m_hitNormalLocal;
- btVector3 m_hitPointLocal;
- btScalar m_hitFraction;
+ const btCollisionObject* m_hitCollisionObject;
+ LocalShapeInfo* m_localShapeInfo;
+ btVector3 m_hitNormalLocal;
+ btVector3 m_hitPointLocal;
+ btScalar m_hitFraction;
};
///RayResultCallback is used to report new raycast results
- struct ConvexResultCallback
+ struct ConvexResultCallback
{
- btScalar m_closestHitFraction;
- int m_collisionFilterGroup;
- int m_collisionFilterMask;
-
+ btScalar m_closestHitFraction;
+ int m_collisionFilterGroup;
+ int m_collisionFilterMask;
+
ConvexResultCallback()
- :m_closestHitFraction(btScalar(1.)),
- m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
- m_collisionFilterMask(btBroadphaseProxy::AllFilter)
+ : m_closestHitFraction(btScalar(1.)),
+ m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
+ m_collisionFilterMask(btBroadphaseProxy::AllFilter)
{
}
virtual ~ConvexResultCallback()
{
}
-
- bool hasHit() const
+
+ bool hasHit() const
{
return (m_closestHitFraction < btScalar(1.));
}
-
-
virtual bool needsCollision(btBroadphaseProxy* proxy0) const
{
bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0;
@@ -371,39 +356,40 @@ public:
return collides;
}
- virtual btScalar addSingleResult(LocalConvexResult& convexResult,bool normalInWorldSpace) = 0;
+ virtual btScalar addSingleResult(LocalConvexResult& convexResult, bool normalInWorldSpace) = 0;
};
- struct ClosestConvexResultCallback : public ConvexResultCallback
+ struct ClosestConvexResultCallback : public ConvexResultCallback
{
- ClosestConvexResultCallback(const btVector3& convexFromWorld,const btVector3& convexToWorld)
- :m_convexFromWorld(convexFromWorld),
- m_convexToWorld(convexToWorld),
- m_hitCollisionObject(0)
+ ClosestConvexResultCallback(const btVector3& convexFromWorld, const btVector3& convexToWorld)
+ : m_convexFromWorld(convexFromWorld),
+ m_convexToWorld(convexToWorld),
+ m_hitCollisionObject(0)
{
}
- btVector3 m_convexFromWorld;//used to calculate hitPointWorld from hitFraction
- btVector3 m_convexToWorld;
+ btVector3 m_convexFromWorld; //used to calculate hitPointWorld from hitFraction
+ btVector3 m_convexToWorld;
- btVector3 m_hitNormalWorld;
- btVector3 m_hitPointWorld;
- const btCollisionObject* m_hitCollisionObject;
-
- virtual btScalar addSingleResult(LocalConvexResult& convexResult,bool normalInWorldSpace)
+ btVector3 m_hitNormalWorld;
+ btVector3 m_hitPointWorld;
+ const btCollisionObject* m_hitCollisionObject;
+
+ virtual btScalar addSingleResult(LocalConvexResult& convexResult, bool normalInWorldSpace)
{
-//caller already does the filter on the m_closestHitFraction
+ //caller already does the filter on the m_closestHitFraction
btAssert(convexResult.m_hitFraction <= m_closestHitFraction);
-
+
m_closestHitFraction = convexResult.m_hitFraction;
m_hitCollisionObject = convexResult.m_hitCollisionObject;
if (normalInWorldSpace)
{
m_hitNormalWorld = convexResult.m_hitNormalLocal;
- } else
+ }
+ else
{
///need to transform normal into worldspace
- m_hitNormalWorld = m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal;
+ m_hitNormalWorld = m_hitCollisionObject->getWorldTransform().getBasis() * convexResult.m_hitNormalLocal;
}
m_hitPointWorld = convexResult.m_hitPointLocal;
return convexResult.m_hitFraction;
@@ -411,23 +397,23 @@ public:
};
///ContactResultCallback is used to report contact points
- struct ContactResultCallback
+ struct ContactResultCallback
{
- int m_collisionFilterGroup;
- int m_collisionFilterMask;
- btScalar m_closestDistanceThreshold;
+ int m_collisionFilterGroup;
+ int m_collisionFilterMask;
+ btScalar m_closestDistanceThreshold;
ContactResultCallback()
- :m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
- m_collisionFilterMask(btBroadphaseProxy::AllFilter),
- m_closestDistanceThreshold(0)
+ : m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
+ m_collisionFilterMask(btBroadphaseProxy::AllFilter),
+ m_closestDistanceThreshold(0)
{
}
virtual ~ContactResultCallback()
{
}
-
+
virtual bool needsCollision(btBroadphaseProxy* proxy0) const
{
bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0;
@@ -435,58 +421,57 @@ public:
return collides;
}
- virtual btScalar addSingleResult(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap,int partId0,int index0,const btCollisionObjectWrapper* colObj1Wrap,int partId1,int index1) = 0;
+ virtual btScalar addSingleResult(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap, int partId0, int index0, const btCollisionObjectWrapper* colObj1Wrap, int partId1, int index1) = 0;
};
-
-
- int getNumCollisionObjects() const
+ int getNumCollisionObjects() const
{
return int(m_collisionObjects.size());
}
/// rayTest performs a raycast on all objects in the btCollisionWorld, and calls the resultCallback
/// This allows for several queries: first hit, all hits, any hit, dependent on the value returned by the callback.
- virtual void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const;
+ virtual void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const;
/// convexTest performs a swept convex cast on all objects in the btCollisionWorld, and calls the resultCallback
/// This allows for several queries: first hit, all hits, any hit, dependent on the value return by the callback.
- void convexSweepTest (const btConvexShape* castShape, const btTransform& from, const btTransform& to, ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration = btScalar(0.)) const;
+ void convexSweepTest(const btConvexShape* castShape, const btTransform& from, const btTransform& to, ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration = btScalar(0.)) const;
///contactTest performs a discrete collision test between colObj against all objects in the btCollisionWorld, and calls the resultCallback.
///it reports one or more contact points for every overlapping object (including the one with deepest penetration)
- void contactTest(btCollisionObject* colObj, ContactResultCallback& resultCallback);
+ void contactTest(btCollisionObject* colObj, ContactResultCallback& resultCallback);
///contactTest performs a discrete collision test between two collision objects and calls the resultCallback if overlap if detected.
///it reports one or more contact points (including the one with deepest penetration)
- void contactPairTest(btCollisionObject* colObjA, btCollisionObject* colObjB, ContactResultCallback& resultCallback);
-
+ void contactPairTest(btCollisionObject* colObjA, btCollisionObject* colObjB, ContactResultCallback& resultCallback);
/// rayTestSingle performs a raycast call and calls the resultCallback. It is used internally by rayTest.
/// In a future implementation, we consider moving the ray test as a virtual method in btCollisionShape.
/// This allows more customization.
- static void rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans,
- btCollisionObject* collisionObject,
- const btCollisionShape* collisionShape,
- const btTransform& colObjWorldTransform,
- RayResultCallback& resultCallback);
+ static void rayTestSingle(const btTransform& rayFromTrans, const btTransform& rayToTrans,
+ btCollisionObject* collisionObject,
+ const btCollisionShape* collisionShape,
+ const btTransform& colObjWorldTransform,
+ RayResultCallback& resultCallback);
- static void rayTestSingleInternal(const btTransform& rayFromTrans,const btTransform& rayToTrans,
- const btCollisionObjectWrapper* collisionObjectWrap,
- RayResultCallback& resultCallback);
+ static void rayTestSingleInternal(const btTransform& rayFromTrans, const btTransform& rayToTrans,
+ const btCollisionObjectWrapper* collisionObjectWrap,
+ RayResultCallback& resultCallback);
/// objectQuerySingle performs a collision detection query and calls the resultCallback. It is used internally by rayTest.
- static void objectQuerySingle(const btConvexShape* castShape, const btTransform& rayFromTrans,const btTransform& rayToTrans,
- btCollisionObject* collisionObject,
- const btCollisionShape* collisionShape,
- const btTransform& colObjWorldTransform,
- ConvexResultCallback& resultCallback, btScalar allowedPenetration);
+ static void objectQuerySingle(const btConvexShape* castShape, const btTransform& rayFromTrans, const btTransform& rayToTrans,
+ btCollisionObject* collisionObject,
+ const btCollisionShape* collisionShape,
+ const btTransform& colObjWorldTransform,
+ ConvexResultCallback& resultCallback, btScalar allowedPenetration);
- static void objectQuerySingleInternal(const btConvexShape* castShape,const btTransform& convexFromTrans,const btTransform& convexToTrans,
- const btCollisionObjectWrapper* colObjWrap,
- ConvexResultCallback& resultCallback, btScalar allowedPenetration);
+ static void objectQuerySingleInternal(const btConvexShape* castShape, const btTransform& convexFromTrans, const btTransform& convexToTrans,
+ const btCollisionObjectWrapper* colObjWrap,
+ ConvexResultCallback& resultCallback, btScalar allowedPenetration);
- virtual void addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup=btBroadphaseProxy::DefaultFilter, int collisionFilterMask=btBroadphaseProxy::AllFilter);
+ virtual void addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup = btBroadphaseProxy::DefaultFilter, int collisionFilterMask = btBroadphaseProxy::AllFilter);
+
+ virtual void refreshBroadphaseProxy(btCollisionObject* collisionObject);
btCollisionObjectArray& getCollisionObjectArray()
{
@@ -498,10 +483,9 @@ public:
return m_collisionObjects;
}
+ virtual void removeCollisionObject(btCollisionObject* collisionObject);
- virtual void removeCollisionObject(btCollisionObject* collisionObject);
-
- virtual void performDiscreteCollisionDetection();
+ virtual void performDiscreteCollisionDetection();
btDispatcherInfo& getDispatchInfo()
{
@@ -512,20 +496,18 @@ public:
{
return m_dispatchInfo;
}
-
- bool getForceUpdateAllAabbs() const
+
+ bool getForceUpdateAllAabbs() const
{
return m_forceUpdateAllAabbs;
}
- void setForceUpdateAllAabbs( bool forceUpdateAllAabbs)
+ void setForceUpdateAllAabbs(bool forceUpdateAllAabbs)
{
m_forceUpdateAllAabbs = forceUpdateAllAabbs;
}
///Preliminary serialization test for Bullet 2.76. Loading those files requires a separate parser (Bullet/Demos/SerializeDemo)
- virtual void serialize(btSerializer* serializer);
-
+ virtual void serialize(btSerializer* serializer);
};
-
-#endif //BT_COLLISION_WORLD_H
+#endif //BT_COLLISION_WORLD_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp
index f2b0837808..9f422dc157 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp
@@ -15,269 +15,251 @@ subject to the following restrictions:
#include "btCollisionWorldImporter.h"
#include "btBulletCollisionCommon.h"
-#include "LinearMath/btSerializer.h" //for btBulletSerializedArrays definition
+#include "LinearMath/btSerializer.h" //for btBulletSerializedArrays definition
#ifdef SUPPORT_GIMPACT_SHAPE_IMPORT
#include "BulletCollision/Gimpact/btGImpactShape.h"
-#endif //SUPPORT_GIMPACT_SHAPE_IMPORT
+#endif //SUPPORT_GIMPACT_SHAPE_IMPORT
btCollisionWorldImporter::btCollisionWorldImporter(btCollisionWorld* world)
-:m_collisionWorld(world),
-m_verboseMode(0)
+ : m_collisionWorld(world),
+ m_verboseMode(0)
{
-
}
btCollisionWorldImporter::~btCollisionWorldImporter()
{
}
-
-
-
-
-bool btCollisionWorldImporter::convertAllObjects( btBulletSerializedArrays* arrays)
+bool btCollisionWorldImporter::convertAllObjects(btBulletSerializedArrays* arrays)
{
-
m_shapeMap.clear();
m_bodyMap.clear();
int i;
- for (i=0;i<arrays->m_bvhsDouble.size();i++)
+ for (i = 0; i < arrays->m_bvhsDouble.size(); i++)
{
btOptimizedBvh* bvh = createOptimizedBvh();
btQuantizedBvhDoubleData* bvhData = arrays->m_bvhsDouble[i];
bvh->deSerializeDouble(*bvhData);
- m_bvhMap.insert(arrays->m_bvhsDouble[i],bvh);
+ m_bvhMap.insert(arrays->m_bvhsDouble[i], bvh);
}
- for (i=0;i<arrays->m_bvhsFloat.size();i++)
- {
- btOptimizedBvh* bvh = createOptimizedBvh();
- btQuantizedBvhFloatData* bvhData = arrays->m_bvhsFloat[i];
+ for (i = 0; i < arrays->m_bvhsFloat.size(); i++)
+ {
+ btOptimizedBvh* bvh = createOptimizedBvh();
+ btQuantizedBvhFloatData* bvhData = arrays->m_bvhsFloat[i];
bvh->deSerializeFloat(*bvhData);
- m_bvhMap.insert(arrays->m_bvhsFloat[i],bvh);
+ m_bvhMap.insert(arrays->m_bvhsFloat[i], bvh);
}
-
-
-
-
- for (i=0;i<arrays->m_colShapeData.size();i++)
+ for (i = 0; i < arrays->m_colShapeData.size(); i++)
{
btCollisionShapeData* shapeData = arrays->m_colShapeData[i];
btCollisionShape* shape = convertCollisionShape(shapeData);
if (shape)
{
- // printf("shapeMap.insert(%x,%x)\n",shapeData,shape);
- m_shapeMap.insert(shapeData,shape);
+ // printf("shapeMap.insert(%x,%x)\n",shapeData,shape);
+ m_shapeMap.insert(shapeData, shape);
}
- if (shape&& shapeData->m_name)
+ if (shape && shapeData->m_name)
{
char* newname = duplicateName(shapeData->m_name);
- m_objectNameMap.insert(shape,newname);
- m_nameShapeMap.insert(newname,shape);
+ m_objectNameMap.insert(shape, newname);
+ m_nameShapeMap.insert(newname, shape);
}
}
-
- for (i=0;i<arrays->m_collisionObjectDataDouble.size();i++)
+ for (i = 0; i < arrays->m_collisionObjectDataDouble.size(); i++)
{
- btCollisionObjectDoubleData* colObjData = arrays->m_collisionObjectDataDouble[i];
- btCollisionShape** shapePtr = m_shapeMap.find(colObjData->m_collisionShape);
- if (shapePtr && *shapePtr)
- {
- btTransform startTransform;
- colObjData->m_worldTransform.m_origin.m_floats[3] = 0.f;
- startTransform.deSerializeDouble(colObjData->m_worldTransform);
-
- btCollisionShape* shape = (btCollisionShape*)*shapePtr;
- btCollisionObject* body = createCollisionObject(startTransform,shape,colObjData->m_name);
- body->setFriction(btScalar(colObjData->m_friction));
- body->setRestitution(btScalar(colObjData->m_restitution));
+ btCollisionObjectDoubleData* colObjData = arrays->m_collisionObjectDataDouble[i];
+ btCollisionShape** shapePtr = m_shapeMap.find(colObjData->m_collisionShape);
+ if (shapePtr && *shapePtr)
+ {
+ btTransform startTransform;
+ colObjData->m_worldTransform.m_origin.m_floats[3] = 0.f;
+ startTransform.deSerializeDouble(colObjData->m_worldTransform);
+
+ btCollisionShape* shape = (btCollisionShape*)*shapePtr;
+ btCollisionObject* body = createCollisionObject(startTransform, shape, colObjData->m_name);
+ body->setFriction(btScalar(colObjData->m_friction));
+ body->setRestitution(btScalar(colObjData->m_restitution));
#ifdef USE_INTERNAL_EDGE_UTILITY
- if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
- {
- btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*)shape;
- if (trimesh->getTriangleInfoMap())
- {
- body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
- }
- }
-#endif //USE_INTERNAL_EDGE_UTILITY
- m_bodyMap.insert(colObjData,body);
- } else
- {
- printf("error: no shape found\n");
- }
+ if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
+ {
+ btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*)shape;
+ if (trimesh->getTriangleInfoMap())
+ {
+ body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
+ }
+ }
+#endif //USE_INTERNAL_EDGE_UTILITY
+ m_bodyMap.insert(colObjData, body);
+ }
+ else
+ {
+ printf("error: no shape found\n");
+ }
}
- for (i=0;i<arrays->m_collisionObjectDataFloat.size();i++)
+ for (i = 0; i < arrays->m_collisionObjectDataFloat.size(); i++)
{
- btCollisionObjectFloatData* colObjData = arrays->m_collisionObjectDataFloat[i];
- btCollisionShape** shapePtr = m_shapeMap.find(colObjData->m_collisionShape);
- if (shapePtr && *shapePtr)
- {
- btTransform startTransform;
- colObjData->m_worldTransform.m_origin.m_floats[3] = 0.f;
- startTransform.deSerializeFloat(colObjData->m_worldTransform);
+ btCollisionObjectFloatData* colObjData = arrays->m_collisionObjectDataFloat[i];
+ btCollisionShape** shapePtr = m_shapeMap.find(colObjData->m_collisionShape);
+ if (shapePtr && *shapePtr)
+ {
+ btTransform startTransform;
+ colObjData->m_worldTransform.m_origin.m_floats[3] = 0.f;
+ startTransform.deSerializeFloat(colObjData->m_worldTransform);
- btCollisionShape* shape = (btCollisionShape*)*shapePtr;
- btCollisionObject* body = createCollisionObject(startTransform,shape,colObjData->m_name);
+ btCollisionShape* shape = (btCollisionShape*)*shapePtr;
+ btCollisionObject* body = createCollisionObject(startTransform, shape, colObjData->m_name);
#ifdef USE_INTERNAL_EDGE_UTILITY
- if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
- {
- btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*)shape;
- if (trimesh->getTriangleInfoMap())
- {
- body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
- }
- }
-#endif //USE_INTERNAL_EDGE_UTILITY
- m_bodyMap.insert(colObjData,body);
- } else
- {
- printf("error: no shape found\n");
- }
- }
+ if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
+ {
+ btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*)shape;
+ if (trimesh->getTriangleInfoMap())
+ {
+ body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
+ }
+ }
+#endif //USE_INTERNAL_EDGE_UTILITY
+ m_bodyMap.insert(colObjData, body);
+ }
+ else
+ {
+ printf("error: no shape found\n");
+ }
+ }
return true;
}
-
-
void btCollisionWorldImporter::deleteAllData()
{
int i;
- for (i=0;i<m_allocatedCollisionObjects.size();i++)
+ for (i = 0; i < m_allocatedCollisionObjects.size(); i++)
{
- if(m_collisionWorld)
+ if (m_collisionWorld)
m_collisionWorld->removeCollisionObject(m_allocatedCollisionObjects[i]);
delete m_allocatedCollisionObjects[i];
}
m_allocatedCollisionObjects.clear();
-
- for (i=0;i<m_allocatedCollisionShapes.size();i++)
+ for (i = 0; i < m_allocatedCollisionShapes.size(); i++)
{
delete m_allocatedCollisionShapes[i];
}
m_allocatedCollisionShapes.clear();
-
- for (i=0;i<m_allocatedBvhs.size();i++)
+ for (i = 0; i < m_allocatedBvhs.size(); i++)
{
delete m_allocatedBvhs[i];
}
m_allocatedBvhs.clear();
- for (i=0;i<m_allocatedTriangleInfoMaps.size();i++)
+ for (i = 0; i < m_allocatedTriangleInfoMaps.size(); i++)
{
delete m_allocatedTriangleInfoMaps[i];
}
m_allocatedTriangleInfoMaps.clear();
- for (i=0;i<m_allocatedTriangleIndexArrays.size();i++)
+ for (i = 0; i < m_allocatedTriangleIndexArrays.size(); i++)
{
delete m_allocatedTriangleIndexArrays[i];
}
m_allocatedTriangleIndexArrays.clear();
- for (i=0;i<m_allocatedNames.size();i++)
+ for (i = 0; i < m_allocatedNames.size(); i++)
{
delete[] m_allocatedNames[i];
}
m_allocatedNames.clear();
- for (i=0;i<m_allocatedbtStridingMeshInterfaceDatas.size();i++)
+ for (i = 0; i < m_allocatedbtStridingMeshInterfaceDatas.size(); i++)
{
btStridingMeshInterfaceData* curData = m_allocatedbtStridingMeshInterfaceDatas[i];
- for(int a = 0;a < curData->m_numMeshParts;a++)
+ for (int a = 0; a < curData->m_numMeshParts; a++)
{
btMeshPartData* curPart = &curData->m_meshPartsPtr[a];
- if(curPart->m_vertices3f)
- delete [] curPart->m_vertices3f;
+ if (curPart->m_vertices3f)
+ delete[] curPart->m_vertices3f;
- if(curPart->m_vertices3d)
- delete [] curPart->m_vertices3d;
+ if (curPart->m_vertices3d)
+ delete[] curPart->m_vertices3d;
- if(curPart->m_indices32)
- delete [] curPart->m_indices32;
+ if (curPart->m_indices32)
+ delete[] curPart->m_indices32;
- if(curPart->m_3indices16)
- delete [] curPart->m_3indices16;
+ if (curPart->m_3indices16)
+ delete[] curPart->m_3indices16;
- if(curPart->m_indices16)
- delete [] curPart->m_indices16;
+ if (curPart->m_indices16)
+ delete[] curPart->m_indices16;
if (curPart->m_3indices8)
- delete [] curPart->m_3indices8;
-
+ delete[] curPart->m_3indices8;
}
- delete [] curData->m_meshPartsPtr;
+ delete[] curData->m_meshPartsPtr;
delete curData;
}
m_allocatedbtStridingMeshInterfaceDatas.clear();
- for (i=0;i<m_indexArrays.size();i++)
+ for (i = 0; i < m_indexArrays.size(); i++)
{
btAlignedFree(m_indexArrays[i]);
}
- m_indexArrays.clear();
+ m_indexArrays.clear();
- for (i=0;i<m_shortIndexArrays.size();i++)
+ for (i = 0; i < m_shortIndexArrays.size(); i++)
{
btAlignedFree(m_shortIndexArrays[i]);
}
- m_shortIndexArrays.clear();
+ m_shortIndexArrays.clear();
- for (i=0;i<m_charIndexArrays.size();i++)
+ for (i = 0; i < m_charIndexArrays.size(); i++)
{
btAlignedFree(m_charIndexArrays[i]);
}
- m_charIndexArrays.clear();
+ m_charIndexArrays.clear();
- for (i=0;i<m_floatVertexArrays.size();i++)
+ for (i = 0; i < m_floatVertexArrays.size(); i++)
{
btAlignedFree(m_floatVertexArrays[i]);
}
- m_floatVertexArrays.clear();
+ m_floatVertexArrays.clear();
- for (i=0;i<m_doubleVertexArrays.size();i++)
+ for (i = 0; i < m_doubleVertexArrays.size(); i++)
{
btAlignedFree(m_doubleVertexArrays[i]);
}
- m_doubleVertexArrays.clear();
-
-
+ m_doubleVertexArrays.clear();
}
-
-
-btCollisionShape* btCollisionWorldImporter::convertCollisionShape( btCollisionShapeData* shapeData )
+btCollisionShape* btCollisionWorldImporter::convertCollisionShape(btCollisionShapeData* shapeData)
{
btCollisionShape* shape = 0;
switch (shapeData->m_shapeType)
- {
- case STATIC_PLANE_PROXYTYPE:
+ {
+ case STATIC_PLANE_PROXYTYPE:
{
btStaticPlaneShapeData* planeData = (btStaticPlaneShapeData*)shapeData;
- btVector3 planeNormal,localScaling;
+ btVector3 planeNormal, localScaling;
planeNormal.deSerializeFloat(planeData->m_planeNormal);
localScaling.deSerializeFloat(planeData->m_localScaling);
- shape = createPlaneShape(planeNormal,planeData->m_planeConstant);
+ shape = createPlaneShape(planeNormal, planeData->m_planeConstant);
shape->setLocalScaling(localScaling);
break;
}
- case SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE:
+ case SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE:
{
- btScaledTriangleMeshShapeData* scaledMesh = (btScaledTriangleMeshShapeData*) shapeData;
- btCollisionShapeData* colShapeData = (btCollisionShapeData*) &scaledMesh->m_trimeshShapeData;
+ btScaledTriangleMeshShapeData* scaledMesh = (btScaledTriangleMeshShapeData*)shapeData;
+ btCollisionShapeData* colShapeData = (btCollisionShapeData*)&scaledMesh->m_trimeshShapeData;
colShapeData->m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;
btCollisionShape* childShape = convertCollisionShape(colShapeData);
btBvhTriangleMeshShape* meshShape = (btBvhTriangleMeshShape*)childShape;
@@ -288,15 +270,14 @@ btCollisionShape* btCollisionWorldImporter::convertCollisionShape( btCollisionS
break;
}
#ifdef SUPPORT_GIMPACT_SHAPE_IMPORT
- case GIMPACT_SHAPE_PROXYTYPE:
+ case GIMPACT_SHAPE_PROXYTYPE:
{
- btGImpactMeshShapeData* gimpactData = (btGImpactMeshShapeData*) shapeData;
+ btGImpactMeshShapeData* gimpactData = (btGImpactMeshShapeData*)shapeData;
if (gimpactData->m_gimpactSubType == CONST_GIMPACT_TRIMESH_SHAPE)
{
btStridingMeshInterfaceData* interfaceData = createStridingMeshInterfaceData(&gimpactData->m_meshInterface);
btTriangleIndexVertexArray* meshInterface = createMeshInterface(*interfaceData);
-
btGImpactMeshShape* gimpactShape = createGimpactShape(meshInterface);
btVector3 localScaling;
localScaling.deSerializeFloat(gimpactData->m_localScaling);
@@ -304,47 +285,45 @@ btCollisionShape* btCollisionWorldImporter::convertCollisionShape( btCollisionS
gimpactShape->setMargin(btScalar(gimpactData->m_collisionMargin));
gimpactShape->updateBound();
shape = gimpactShape;
- } else
+ }
+ else
{
printf("unsupported gimpact sub type\n");
}
break;
}
-#endif //SUPPORT_GIMPACT_SHAPE_IMPORT
- //The btCapsuleShape* API has issue passing the margin/scaling/halfextents unmodified through the API
- //so deal with this
+#endif //SUPPORT_GIMPACT_SHAPE_IMPORT \
+ //The btCapsuleShape* API has issue passing the margin/scaling/halfextents unmodified through the API \
+ //so deal with this
case CAPSULE_SHAPE_PROXYTYPE:
{
btCapsuleShapeData* capData = (btCapsuleShapeData*)shapeData;
-
switch (capData->m_upAxis)
{
- case 0:
+ case 0:
{
- shape = createCapsuleShapeX(1,1);
+ shape = createCapsuleShapeX(1, 1);
break;
}
- case 1:
+ case 1:
{
- shape = createCapsuleShapeY(1,1);
+ shape = createCapsuleShapeY(1, 1);
break;
}
- case 2:
+ case 2:
{
- shape = createCapsuleShapeZ(1,1);
+ shape = createCapsuleShapeZ(1, 1);
break;
}
- default:
+ default:
{
printf("error: wrong up axis for btCapsuleShape\n");
}
-
-
};
if (shape)
{
- btCapsuleShape* cap = (btCapsuleShape*) shape;
+ btCapsuleShape* cap = (btCapsuleShape*)shape;
cap->deSerializeFloat(capData);
}
break;
@@ -355,163 +334,156 @@ btCollisionShape* btCollisionWorldImporter::convertCollisionShape( btCollisionS
case SPHERE_SHAPE_PROXYTYPE:
case MULTI_SPHERE_SHAPE_PROXYTYPE:
case CONVEX_HULL_SHAPE_PROXYTYPE:
+ {
+ btConvexInternalShapeData* bsd = (btConvexInternalShapeData*)shapeData;
+ btVector3 implicitShapeDimensions;
+ implicitShapeDimensions.deSerializeFloat(bsd->m_implicitShapeDimensions);
+ btVector3 localScaling;
+ localScaling.deSerializeFloat(bsd->m_localScaling);
+ btVector3 margin(bsd->m_collisionMargin, bsd->m_collisionMargin, bsd->m_collisionMargin);
+ switch (shapeData->m_shapeType)
{
- btConvexInternalShapeData* bsd = (btConvexInternalShapeData*)shapeData;
- btVector3 implicitShapeDimensions;
- implicitShapeDimensions.deSerializeFloat(bsd->m_implicitShapeDimensions);
- btVector3 localScaling;
- localScaling.deSerializeFloat(bsd->m_localScaling);
- btVector3 margin(bsd->m_collisionMargin,bsd->m_collisionMargin,bsd->m_collisionMargin);
- switch (shapeData->m_shapeType)
+ case BOX_SHAPE_PROXYTYPE:
{
- case BOX_SHAPE_PROXYTYPE:
- {
- btBoxShape* box= (btBoxShape*)createBoxShape(implicitShapeDimensions/localScaling+margin);
- //box->initializePolyhedralFeatures();
- shape = box;
+ btBoxShape* box = (btBoxShape*)createBoxShape(implicitShapeDimensions / localScaling + margin);
+ //box->initializePolyhedralFeatures();
+ shape = box;
+ break;
+ }
+ case SPHERE_SHAPE_PROXYTYPE:
+ {
+ shape = createSphereShape(implicitShapeDimensions.getX());
+ break;
+ }
+
+ case CYLINDER_SHAPE_PROXYTYPE:
+ {
+ btCylinderShapeData* cylData = (btCylinderShapeData*)shapeData;
+ btVector3 halfExtents = implicitShapeDimensions + margin;
+ switch (cylData->m_upAxis)
+ {
+ case 0:
+ {
+ shape = createCylinderShapeX(halfExtents.getY(), halfExtents.getX());
break;
}
- case SPHERE_SHAPE_PROXYTYPE:
+ case 1:
{
- shape = createSphereShape(implicitShapeDimensions.getX());
+ shape = createCylinderShapeY(halfExtents.getX(), halfExtents.getY());
break;
}
-
- case CYLINDER_SHAPE_PROXYTYPE:
+ case 2:
{
- btCylinderShapeData* cylData = (btCylinderShapeData*) shapeData;
- btVector3 halfExtents = implicitShapeDimensions+margin;
- switch (cylData->m_upAxis)
- {
- case 0:
- {
- shape = createCylinderShapeX(halfExtents.getY(),halfExtents.getX());
- break;
- }
- case 1:
- {
- shape = createCylinderShapeY(halfExtents.getX(),halfExtents.getY());
- break;
- }
- case 2:
- {
- shape = createCylinderShapeZ(halfExtents.getX(),halfExtents.getZ());
- break;
- }
- default:
- {
- printf("unknown Cylinder up axis\n");
- }
-
- };
-
-
-
+ shape = createCylinderShapeZ(halfExtents.getX(), halfExtents.getZ());
break;
}
- case CONE_SHAPE_PROXYTYPE:
+ default:
{
- btConeShapeData* conData = (btConeShapeData*) shapeData;
- btVector3 halfExtents = implicitShapeDimensions;//+margin;
- switch (conData->m_upIndex)
- {
- case 0:
- {
- shape = createConeShapeX(halfExtents.getY(),halfExtents.getX());
- break;
- }
- case 1:
- {
- shape = createConeShapeY(halfExtents.getX(),halfExtents.getY());
- break;
- }
- case 2:
- {
- shape = createConeShapeZ(halfExtents.getX(),halfExtents.getZ());
- break;
- }
- default:
- {
- printf("unknown Cone up axis\n");
- }
-
- };
-
-
+ printf("unknown Cylinder up axis\n");
+ }
+ };
+ break;
+ }
+ case CONE_SHAPE_PROXYTYPE:
+ {
+ btConeShapeData* conData = (btConeShapeData*)shapeData;
+ btVector3 halfExtents = implicitShapeDimensions; //+margin;
+ switch (conData->m_upIndex)
+ {
+ case 0:
+ {
+ shape = createConeShapeX(halfExtents.getY(), halfExtents.getX());
break;
}
- case MULTI_SPHERE_SHAPE_PROXYTYPE:
+ case 1:
{
- btMultiSphereShapeData* mss = (btMultiSphereShapeData*)bsd;
- int numSpheres = mss->m_localPositionArraySize;
-
- btAlignedObjectArray<btVector3> tmpPos;
- btAlignedObjectArray<btScalar> radii;
- radii.resize(numSpheres);
- tmpPos.resize(numSpheres);
- int i;
- for ( i=0;i<numSpheres;i++)
- {
- tmpPos[i].deSerializeFloat(mss->m_localPositionArrayPtr[i].m_pos);
- radii[i] = mss->m_localPositionArrayPtr[i].m_radius;
- }
- shape = createMultiSphereShape(&tmpPos[0],&radii[0],numSpheres);
+ shape = createConeShapeY(halfExtents.getX(), halfExtents.getY());
break;
}
- case CONVEX_HULL_SHAPE_PROXYTYPE:
+ case 2:
{
- // int sz = sizeof(btConvexHullShapeData);
- // int sz2 = sizeof(btConvexInternalShapeData);
- // int sz3 = sizeof(btCollisionShapeData);
- btConvexHullShapeData* convexData = (btConvexHullShapeData*)bsd;
- int numPoints = convexData->m_numUnscaledPoints;
-
- btAlignedObjectArray<btVector3> tmpPoints;
- tmpPoints.resize(numPoints);
- int i;
- for ( i=0;i<numPoints;i++)
- {
-#ifdef BT_USE_DOUBLE_PRECISION
- if (convexData->m_unscaledPointsDoublePtr)
- tmpPoints[i].deSerialize(convexData->m_unscaledPointsDoublePtr[i]);
- if (convexData->m_unscaledPointsFloatPtr)
- tmpPoints[i].deSerializeFloat(convexData->m_unscaledPointsFloatPtr[i]);
-#else
- if (convexData->m_unscaledPointsFloatPtr)
- tmpPoints[i].deSerialize(convexData->m_unscaledPointsFloatPtr[i]);
- if (convexData->m_unscaledPointsDoublePtr)
- tmpPoints[i].deSerializeDouble(convexData->m_unscaledPointsDoublePtr[i]);
-#endif //BT_USE_DOUBLE_PRECISION
- }
- btConvexHullShape* hullShape = createConvexHullShape();
- for (i=0;i<numPoints;i++)
- {
- hullShape->addPoint(tmpPoints[i]);
- }
- hullShape->setMargin(bsd->m_collisionMargin);
- //hullShape->initializePolyhedralFeatures();
- shape = hullShape;
+ shape = createConeShapeZ(halfExtents.getX(), halfExtents.getZ());
break;
}
- default:
+ default:
{
- printf("error: cannot create shape type (%d)\n",shapeData->m_shapeType);
+ printf("unknown Cone up axis\n");
}
- }
+ };
- if (shape)
+ break;
+ }
+ case MULTI_SPHERE_SHAPE_PROXYTYPE:
+ {
+ btMultiSphereShapeData* mss = (btMultiSphereShapeData*)bsd;
+ int numSpheres = mss->m_localPositionArraySize;
+
+ btAlignedObjectArray<btVector3> tmpPos;
+ btAlignedObjectArray<btScalar> radii;
+ radii.resize(numSpheres);
+ tmpPos.resize(numSpheres);
+ int i;
+ for (i = 0; i < numSpheres; i++)
+ {
+ tmpPos[i].deSerializeFloat(mss->m_localPositionArrayPtr[i].m_pos);
+ radii[i] = mss->m_localPositionArrayPtr[i].m_radius;
+ }
+ shape = createMultiSphereShape(&tmpPos[0], &radii[0], numSpheres);
+ break;
+ }
+ case CONVEX_HULL_SHAPE_PROXYTYPE:
{
- shape->setMargin(bsd->m_collisionMargin);
+ // int sz = sizeof(btConvexHullShapeData);
+ // int sz2 = sizeof(btConvexInternalShapeData);
+ // int sz3 = sizeof(btCollisionShapeData);
+ btConvexHullShapeData* convexData = (btConvexHullShapeData*)bsd;
+ int numPoints = convexData->m_numUnscaledPoints;
+
+ btAlignedObjectArray<btVector3> tmpPoints;
+ tmpPoints.resize(numPoints);
+ int i;
+ for (i = 0; i < numPoints; i++)
+ {
+#ifdef BT_USE_DOUBLE_PRECISION
+ if (convexData->m_unscaledPointsDoublePtr)
+ tmpPoints[i].deSerialize(convexData->m_unscaledPointsDoublePtr[i]);
+ if (convexData->m_unscaledPointsFloatPtr)
+ tmpPoints[i].deSerializeFloat(convexData->m_unscaledPointsFloatPtr[i]);
+#else
+ if (convexData->m_unscaledPointsFloatPtr)
+ tmpPoints[i].deSerialize(convexData->m_unscaledPointsFloatPtr[i]);
+ if (convexData->m_unscaledPointsDoublePtr)
+ tmpPoints[i].deSerializeDouble(convexData->m_unscaledPointsDoublePtr[i]);
+#endif //BT_USE_DOUBLE_PRECISION
+ }
+ btConvexHullShape* hullShape = createConvexHullShape();
+ for (i = 0; i < numPoints; i++)
+ {
+ hullShape->addPoint(tmpPoints[i]);
+ }
+ hullShape->setMargin(bsd->m_collisionMargin);
+ //hullShape->initializePolyhedralFeatures();
+ shape = hullShape;
+ break;
+ }
+ default:
+ {
+ printf("error: cannot create shape type (%d)\n", shapeData->m_shapeType);
+ }
+ }
- btVector3 localScaling;
- localScaling.deSerializeFloat(bsd->m_localScaling);
- shape->setLocalScaling(localScaling);
+ if (shape)
+ {
+ shape->setMargin(bsd->m_collisionMargin);
- }
- break;
+ btVector3 localScaling;
+ localScaling.deSerializeFloat(bsd->m_localScaling);
+ shape->setLocalScaling(localScaling);
}
+ break;
+ }
case TRIANGLE_MESH_SHAPE_PROXYTYPE:
{
btTriangleMeshShapeData* trimesh = (btTriangleMeshShapeData*)shapeData;
@@ -522,10 +494,10 @@ btCollisionShape* btCollisionWorldImporter::convertCollisionShape( btCollisionS
return 0;
}
- btVector3 scaling; scaling.deSerializeFloat(trimesh->m_meshInterface.m_scaling);
+ btVector3 scaling;
+ scaling.deSerializeFloat(trimesh->m_meshInterface.m_scaling);
meshInterface->setScaling(scaling);
-
btOptimizedBvh* bvh = 0;
#if 1
if (trimesh->m_quantizedFloatBvh)
@@ -534,7 +506,8 @@ btCollisionShape* btCollisionWorldImporter::convertCollisionShape( btCollisionS
if (bvhPtr && *bvhPtr)
{
bvh = *bvhPtr;
- } else
+ }
+ else
{
bvh = createOptimizedBvh();
bvh->deSerializeFloat(*trimesh->m_quantizedFloatBvh);
@@ -546,7 +519,8 @@ btCollisionShape* btCollisionWorldImporter::convertCollisionShape( btCollisionS
if (bvhPtr && *bvhPtr)
{
bvh = *bvhPtr;
- } else
+ }
+ else
{
bvh = createOptimizedBvh();
bvh->deSerializeDouble(*trimesh->m_quantizedDoubleBvh);
@@ -554,8 +528,7 @@ btCollisionShape* btCollisionWorldImporter::convertCollisionShape( btCollisionS
}
#endif
-
- btBvhTriangleMeshShape* trimeshShape = createBvhTriangleMeshShape(meshInterface,bvh);
+ btBvhTriangleMeshShape* trimeshShape = createBvhTriangleMeshShape(meshInterface, bvh);
trimeshShape->setMargin(trimesh->m_collisionMargin);
shape = trimeshShape;
@@ -567,71 +540,66 @@ btCollisionShape* btCollisionWorldImporter::convertCollisionShape( btCollisionS
#ifdef USE_INTERNAL_EDGE_UTILITY
gContactAddedCallback = btAdjustInternalEdgeContactsCallback;
-#endif //USE_INTERNAL_EDGE_UTILITY
-
+#endif //USE_INTERNAL_EDGE_UTILITY
}
//printf("trimesh->m_collisionMargin=%f\n",trimesh->m_collisionMargin);
break;
}
case COMPOUND_SHAPE_PROXYTYPE:
- {
- btCompoundShapeData* compoundData = (btCompoundShapeData*)shapeData;
- btCompoundShape* compoundShape = createCompoundShape();
-
- //btCompoundShapeChildData* childShapeDataArray = &compoundData->m_childShapePtr[0];
+ {
+ btCompoundShapeData* compoundData = (btCompoundShapeData*)shapeData;
+ btCompoundShape* compoundShape = createCompoundShape();
+ //btCompoundShapeChildData* childShapeDataArray = &compoundData->m_childShapePtr[0];
- btAlignedObjectArray<btCollisionShape*> childShapes;
- for (int i=0;i<compoundData->m_numChildShapes;i++)
- {
- //btCompoundShapeChildData* ptr = &compoundData->m_childShapePtr[i];
+ btAlignedObjectArray<btCollisionShape*> childShapes;
+ for (int i = 0; i < compoundData->m_numChildShapes; i++)
+ {
+ //btCompoundShapeChildData* ptr = &compoundData->m_childShapePtr[i];
- btCollisionShapeData* cd = compoundData->m_childShapePtr[i].m_childShape;
+ btCollisionShapeData* cd = compoundData->m_childShapePtr[i].m_childShape;
- btCollisionShape* childShape = convertCollisionShape(cd);
- if (childShape)
- {
- btTransform localTransform;
- localTransform.deSerializeFloat(compoundData->m_childShapePtr[i].m_transform);
- compoundShape->addChildShape(localTransform,childShape);
- } else
- {
+ btCollisionShape* childShape = convertCollisionShape(cd);
+ if (childShape)
+ {
+ btTransform localTransform;
+ localTransform.deSerializeFloat(compoundData->m_childShapePtr[i].m_transform);
+ compoundShape->addChildShape(localTransform, childShape);
+ }
+ else
+ {
#ifdef _DEBUG
- printf("error: couldn't create childShape for compoundShape\n");
+ printf("error: couldn't create childShape for compoundShape\n");
#endif
- }
-
}
- shape = compoundShape;
-
- break;
}
+ shape = compoundShape;
+
+ break;
+ }
case SOFTBODY_SHAPE_PROXYTYPE:
- {
- return 0;
- }
+ {
+ return 0;
+ }
default:
- {
+ {
#ifdef _DEBUG
- printf("unsupported shape type (%d)\n",shapeData->m_shapeType);
+ printf("unsupported shape type (%d)\n", shapeData->m_shapeType);
#endif
- }
}
+ }
- return shape;
-
+ return shape;
}
-
-
char* btCollisionWorldImporter::duplicateName(const char* name)
{
if (name)
{
int l = (int)strlen(name);
- char* newName = new char[l+1];
- memcpy(newName,name,l);
+ char* newName = new char[l + 1];
+ memcpy(newName, name, l);
newName[l] = 0;
m_allocatedNames.push_back(newName);
return newName;
@@ -639,53 +607,43 @@ char* btCollisionWorldImporter::duplicateName(const char* name)
return 0;
}
-
-
-
-
-
-
-
-
-
-
-btTriangleIndexVertexArray* btCollisionWorldImporter::createMeshInterface(btStridingMeshInterfaceData& meshData)
+btTriangleIndexVertexArray* btCollisionWorldImporter::createMeshInterface(btStridingMeshInterfaceData& meshData)
{
btTriangleIndexVertexArray* meshInterface = createTriangleMeshContainer();
- for (int i=0;i<meshData.m_numMeshParts;i++)
+ for (int i = 0; i < meshData.m_numMeshParts; i++)
{
btIndexedMesh meshPart;
meshPart.m_numTriangles = meshData.m_meshPartsPtr[i].m_numTriangles;
meshPart.m_numVertices = meshData.m_meshPartsPtr[i].m_numVertices;
-
if (meshData.m_meshPartsPtr[i].m_indices32)
{
meshPart.m_indexType = PHY_INTEGER;
- meshPart.m_triangleIndexStride = 3*sizeof(int);
- int* indexArray = (int*)btAlignedAlloc(sizeof(int)*3*meshPart.m_numTriangles,16);
+ meshPart.m_triangleIndexStride = 3 * sizeof(int);
+ int* indexArray = (int*)btAlignedAlloc(sizeof(int) * 3 * meshPart.m_numTriangles, 16);
m_indexArrays.push_back(indexArray);
- for (int j=0;j<3*meshPart.m_numTriangles;j++)
+ for (int j = 0; j < 3 * meshPart.m_numTriangles; j++)
{
indexArray[j] = meshData.m_meshPartsPtr[i].m_indices32[j].m_value;
}
meshPart.m_triangleIndexBase = (const unsigned char*)indexArray;
- } else
+ }
+ else
{
if (meshData.m_meshPartsPtr[i].m_3indices16)
{
meshPart.m_indexType = PHY_SHORT;
- meshPart.m_triangleIndexStride = sizeof(short int)*3;//sizeof(btShortIntIndexTripletData);
+ meshPart.m_triangleIndexStride = sizeof(short int) * 3; //sizeof(btShortIntIndexTripletData);
- short int* indexArray = (short int*)btAlignedAlloc(sizeof(short int)*3*meshPart.m_numTriangles,16);
+ short int* indexArray = (short int*)btAlignedAlloc(sizeof(short int) * 3 * meshPart.m_numTriangles, 16);
m_shortIndexArrays.push_back(indexArray);
- for (int j=0;j<meshPart.m_numTriangles;j++)
+ for (int j = 0; j < meshPart.m_numTriangles; j++)
{
- indexArray[3*j] = meshData.m_meshPartsPtr[i].m_3indices16[j].m_values[0];
- indexArray[3*j+1] = meshData.m_meshPartsPtr[i].m_3indices16[j].m_values[1];
- indexArray[3*j+2] = meshData.m_meshPartsPtr[i].m_3indices16[j].m_values[2];
+ indexArray[3 * j] = meshData.m_meshPartsPtr[i].m_3indices16[j].m_values[0];
+ indexArray[3 * j + 1] = meshData.m_meshPartsPtr[i].m_3indices16[j].m_values[1];
+ indexArray[3 * j + 2] = meshData.m_meshPartsPtr[i].m_3indices16[j].m_values[2];
}
meshPart.m_triangleIndexBase = (const unsigned char*)indexArray;
@@ -693,10 +651,10 @@ btTriangleIndexVertexArray* btCollisionWorldImporter::createMeshInterface(btStri
if (meshData.m_meshPartsPtr[i].m_indices16)
{
meshPart.m_indexType = PHY_SHORT;
- meshPart.m_triangleIndexStride = 3*sizeof(short int);
- short int* indexArray = (short int*)btAlignedAlloc(sizeof(short int)*3*meshPart.m_numTriangles,16);
+ meshPart.m_triangleIndexStride = 3 * sizeof(short int);
+ short int* indexArray = (short int*)btAlignedAlloc(sizeof(short int) * 3 * meshPart.m_numTriangles, 16);
m_shortIndexArrays.push_back(indexArray);
- for (int j=0;j<3*meshPart.m_numTriangles;j++)
+ for (int j = 0; j < 3 * meshPart.m_numTriangles; j++)
{
indexArray[j] = meshData.m_meshPartsPtr[i].m_indices16[j].m_value;
}
@@ -707,16 +665,16 @@ btTriangleIndexVertexArray* btCollisionWorldImporter::createMeshInterface(btStri
if (meshData.m_meshPartsPtr[i].m_3indices8)
{
meshPart.m_indexType = PHY_UCHAR;
- meshPart.m_triangleIndexStride = sizeof(unsigned char)*3;
+ meshPart.m_triangleIndexStride = sizeof(unsigned char) * 3;
- unsigned char* indexArray = (unsigned char*)btAlignedAlloc(sizeof(unsigned char)*3*meshPart.m_numTriangles,16);
+ unsigned char* indexArray = (unsigned char*)btAlignedAlloc(sizeof(unsigned char) * 3 * meshPart.m_numTriangles, 16);
m_charIndexArrays.push_back(indexArray);
- for (int j=0;j<meshPart.m_numTriangles;j++)
+ for (int j = 0; j < meshPart.m_numTriangles; j++)
{
- indexArray[3*j] = meshData.m_meshPartsPtr[i].m_3indices8[j].m_values[0];
- indexArray[3*j+1] = meshData.m_meshPartsPtr[i].m_3indices8[j].m_values[1];
- indexArray[3*j+2] = meshData.m_meshPartsPtr[i].m_3indices8[j].m_values[2];
+ indexArray[3 * j] = meshData.m_meshPartsPtr[i].m_3indices8[j].m_values[0];
+ indexArray[3 * j + 1] = meshData.m_meshPartsPtr[i].m_3indices8[j].m_values[1];
+ indexArray[3 * j + 2] = meshData.m_meshPartsPtr[i].m_3indices8[j].m_values[2];
}
meshPart.m_triangleIndexBase = (const unsigned char*)indexArray;
@@ -727,10 +685,10 @@ btTriangleIndexVertexArray* btCollisionWorldImporter::createMeshInterface(btStri
{
meshPart.m_vertexType = PHY_FLOAT;
meshPart.m_vertexStride = sizeof(btVector3FloatData);
- btVector3FloatData* vertices = (btVector3FloatData*) btAlignedAlloc(sizeof(btVector3FloatData)*meshPart.m_numVertices,16);
+ btVector3FloatData* vertices = (btVector3FloatData*)btAlignedAlloc(sizeof(btVector3FloatData) * meshPart.m_numVertices, 16);
m_floatVertexArrays.push_back(vertices);
- for (int j=0;j<meshPart.m_numVertices;j++)
+ for (int j = 0; j < meshPart.m_numVertices; j++)
{
vertices[j].m_floats[0] = meshData.m_meshPartsPtr[i].m_vertices3f[j].m_floats[0];
vertices[j].m_floats[1] = meshData.m_meshPartsPtr[i].m_vertices3f[j].m_floats[1];
@@ -738,16 +696,16 @@ btTriangleIndexVertexArray* btCollisionWorldImporter::createMeshInterface(btStri
vertices[j].m_floats[3] = meshData.m_meshPartsPtr[i].m_vertices3f[j].m_floats[3];
}
meshPart.m_vertexBase = (const unsigned char*)vertices;
- } else
+ }
+ else
{
meshPart.m_vertexType = PHY_DOUBLE;
meshPart.m_vertexStride = sizeof(btVector3DoubleData);
-
- btVector3DoubleData* vertices = (btVector3DoubleData*) btAlignedAlloc(sizeof(btVector3DoubleData)*meshPart.m_numVertices,16);
+ btVector3DoubleData* vertices = (btVector3DoubleData*)btAlignedAlloc(sizeof(btVector3DoubleData) * meshPart.m_numVertices, 16);
m_doubleVertexArrays.push_back(vertices);
- for (int j=0;j<meshPart.m_numVertices;j++)
+ for (int j = 0; j < meshPart.m_numVertices; j++)
{
vertices[j].m_floats[0] = meshData.m_meshPartsPtr[i].m_vertices3d[j].m_floats[0];
vertices[j].m_floats[1] = meshData.m_meshPartsPtr[i].m_vertices3d[j].m_floats[1];
@@ -759,14 +717,13 @@ btTriangleIndexVertexArray* btCollisionWorldImporter::createMeshInterface(btStri
if (meshPart.m_triangleIndexBase && meshPart.m_vertexBase)
{
- meshInterface->addIndexedMesh(meshPart,meshPart.m_indexType);
+ meshInterface->addIndexedMesh(meshPart, meshPart.m_indexType);
}
}
return meshInterface;
}
-
btStridingMeshInterfaceData* btCollisionWorldImporter::createStridingMeshInterfaceData(btStridingMeshInterfaceData* interfaceData)
{
//create a new btStridingMeshInterfaceData that is an exact copy of shapedata and store it in the WorldImporter
@@ -776,7 +733,7 @@ btStridingMeshInterfaceData* btCollisionWorldImporter::createStridingMeshInterfa
newData->m_numMeshParts = interfaceData->m_numMeshParts;
newData->m_meshPartsPtr = new btMeshPartData[newData->m_numMeshParts];
- for(int i = 0;i < newData->m_numMeshParts;i++)
+ for (int i = 0; i < newData->m_numMeshParts; i++)
{
btMeshPartData* curPart = &interfaceData->m_meshPartsPtr[i];
btMeshPartData* curNewPart = &newData->m_meshPartsPtr[i];
@@ -784,18 +741,18 @@ btStridingMeshInterfaceData* btCollisionWorldImporter::createStridingMeshInterfa
curNewPart->m_numTriangles = curPart->m_numTriangles;
curNewPart->m_numVertices = curPart->m_numVertices;
- if(curPart->m_vertices3f)
+ if (curPart->m_vertices3f)
{
curNewPart->m_vertices3f = new btVector3FloatData[curNewPart->m_numVertices];
- memcpy(curNewPart->m_vertices3f,curPart->m_vertices3f,sizeof(btVector3FloatData) * curNewPart->m_numVertices);
+ memcpy(curNewPart->m_vertices3f, curPart->m_vertices3f, sizeof(btVector3FloatData) * curNewPart->m_numVertices);
}
else
curNewPart->m_vertices3f = NULL;
- if(curPart->m_vertices3d)
+ if (curPart->m_vertices3d)
{
curNewPart->m_vertices3d = new btVector3DoubleData[curNewPart->m_numVertices];
- memcpy(curNewPart->m_vertices3d,curPart->m_vertices3d,sizeof(btVector3DoubleData) * curNewPart->m_numVertices);
+ memcpy(curNewPart->m_vertices3d, curPart->m_vertices3d, sizeof(btVector3DoubleData) * curNewPart->m_numVertices);
}
else
curNewPart->m_vertices3d = NULL;
@@ -803,63 +760,60 @@ btStridingMeshInterfaceData* btCollisionWorldImporter::createStridingMeshInterfa
int numIndices = curNewPart->m_numTriangles * 3;
///the m_3indices8 was not initialized in some Bullet versions, this can cause crashes at loading time
///we catch it by only dealing with m_3indices8 if none of the other indices are initialized
- bool uninitialized3indices8Workaround =false;
+ bool uninitialized3indices8Workaround = false;
- if(curPart->m_indices32)
+ if (curPart->m_indices32)
{
- uninitialized3indices8Workaround=true;
+ uninitialized3indices8Workaround = true;
curNewPart->m_indices32 = new btIntIndexData[numIndices];
- memcpy(curNewPart->m_indices32,curPart->m_indices32,sizeof(btIntIndexData) * numIndices);
+ memcpy(curNewPart->m_indices32, curPart->m_indices32, sizeof(btIntIndexData) * numIndices);
}
else
curNewPart->m_indices32 = NULL;
- if(curPart->m_3indices16)
+ if (curPart->m_3indices16)
{
- uninitialized3indices8Workaround=true;
+ uninitialized3indices8Workaround = true;
curNewPart->m_3indices16 = new btShortIntIndexTripletData[curNewPart->m_numTriangles];
- memcpy(curNewPart->m_3indices16,curPart->m_3indices16,sizeof(btShortIntIndexTripletData) * curNewPart->m_numTriangles);
+ memcpy(curNewPart->m_3indices16, curPart->m_3indices16, sizeof(btShortIntIndexTripletData) * curNewPart->m_numTriangles);
}
else
curNewPart->m_3indices16 = NULL;
- if(curPart->m_indices16)
+ if (curPart->m_indices16)
{
- uninitialized3indices8Workaround=true;
+ uninitialized3indices8Workaround = true;
curNewPart->m_indices16 = new btShortIntIndexData[numIndices];
- memcpy(curNewPart->m_indices16,curPart->m_indices16,sizeof(btShortIntIndexData) * numIndices);
+ memcpy(curNewPart->m_indices16, curPart->m_indices16, sizeof(btShortIntIndexData) * numIndices);
}
else
curNewPart->m_indices16 = NULL;
- if(!uninitialized3indices8Workaround && curPart->m_3indices8)
+ if (!uninitialized3indices8Workaround && curPart->m_3indices8)
{
curNewPart->m_3indices8 = new btCharIndexTripletData[curNewPart->m_numTriangles];
- memcpy(curNewPart->m_3indices8,curPart->m_3indices8,sizeof(btCharIndexTripletData) * curNewPart->m_numTriangles);
+ memcpy(curNewPart->m_3indices8, curPart->m_3indices8, sizeof(btCharIndexTripletData) * curNewPart->m_numTriangles);
}
else
curNewPart->m_3indices8 = NULL;
-
}
m_allocatedbtStridingMeshInterfaceDatas.push_back(newData);
- return(newData);
+ return (newData);
}
#ifdef USE_INTERNAL_EDGE_UTILITY
-extern ContactAddedCallback gContactAddedCallback;
+extern ContactAddedCallback gContactAddedCallback;
-static bool btAdjustInternalEdgeContactsCallback(btManifoldPoint& cp, const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1)
+static bool btAdjustInternalEdgeContactsCallback(btManifoldPoint& cp, const btCollisionObject* colObj0, int partId0, int index0, const btCollisionObject* colObj1, int partId1, int index1)
{
-
- btAdjustInternalEdgeContacts(cp,colObj1,colObj0, partId1,index1);
- //btAdjustInternalEdgeContacts(cp,colObj1,colObj0, partId1,index1, BT_TRIANGLE_CONVEX_BACKFACE_MODE);
- //btAdjustInternalEdgeContacts(cp,colObj1,colObj0, partId1,index1, BT_TRIANGLE_CONVEX_DOUBLE_SIDED+BT_TRIANGLE_CONCAVE_DOUBLE_SIDED);
+ btAdjustInternalEdgeContacts(cp, colObj1, colObj0, partId1, index1);
+ //btAdjustInternalEdgeContacts(cp,colObj1,colObj0, partId1,index1, BT_TRIANGLE_CONVEX_BACKFACE_MODE);
+ //btAdjustInternalEdgeContacts(cp,colObj1,colObj0, partId1,index1, BT_TRIANGLE_CONVEX_DOUBLE_SIDED+BT_TRIANGLE_CONCAVE_DOUBLE_SIDED);
return true;
}
-#endif //USE_INTERNAL_EDGE_UTILITY
-
+#endif //USE_INTERNAL_EDGE_UTILITY
/*
btRigidBody* btWorldImporter::createRigidBody(bool isDynamic, btScalar mass, const btTransform& startTransform,btCollisionShape* shape,const char* bodyName)
@@ -898,29 +852,27 @@ btCollisionObject* btCollisionWorldImporter::getCollisionObjectByName(const char
return 0;
}
-btCollisionObject* btCollisionWorldImporter::createCollisionObject(const btTransform& startTransform,btCollisionShape* shape, const char* bodyName)
+btCollisionObject* btCollisionWorldImporter::createCollisionObject(const btTransform& startTransform, btCollisionShape* shape, const char* bodyName)
{
btCollisionObject* colObj = new btCollisionObject();
colObj->setWorldTransform(startTransform);
colObj->setCollisionShape(shape);
- m_collisionWorld->addCollisionObject(colObj);//todo: flags etc
+ m_collisionWorld->addCollisionObject(colObj); //todo: flags etc
if (bodyName)
{
char* newname = duplicateName(bodyName);
- m_objectNameMap.insert(colObj,newname);
- m_nameColObjMap.insert(newname,colObj);
+ m_objectNameMap.insert(colObj, newname);
+ m_nameColObjMap.insert(newname, colObj);
}
m_allocatedCollisionObjects.push_back(colObj);
return colObj;
}
-
-
-btCollisionShape* btCollisionWorldImporter::createPlaneShape(const btVector3& planeNormal,btScalar planeConstant)
+btCollisionShape* btCollisionWorldImporter::createPlaneShape(const btVector3& planeNormal, btScalar planeConstant)
{
- btStaticPlaneShape* shape = new btStaticPlaneShape(planeNormal,planeConstant);
+ btStaticPlaneShape* shape = new btStaticPlaneShape(planeNormal, planeConstant);
m_allocatedCollisionShapes.push_back(shape);
return shape;
}
@@ -937,85 +889,83 @@ btCollisionShape* btCollisionWorldImporter::createSphereShape(btScalar radius)
return shape;
}
-
btCollisionShape* btCollisionWorldImporter::createCapsuleShapeX(btScalar radius, btScalar height)
{
- btCapsuleShapeX* shape = new btCapsuleShapeX(radius,height);
+ btCapsuleShapeX* shape = new btCapsuleShapeX(radius, height);
m_allocatedCollisionShapes.push_back(shape);
return shape;
}
btCollisionShape* btCollisionWorldImporter::createCapsuleShapeY(btScalar radius, btScalar height)
{
- btCapsuleShape* shape = new btCapsuleShape(radius,height);
+ btCapsuleShape* shape = new btCapsuleShape(radius, height);
m_allocatedCollisionShapes.push_back(shape);
return shape;
}
btCollisionShape* btCollisionWorldImporter::createCapsuleShapeZ(btScalar radius, btScalar height)
{
- btCapsuleShapeZ* shape = new btCapsuleShapeZ(radius,height);
+ btCapsuleShapeZ* shape = new btCapsuleShapeZ(radius, height);
m_allocatedCollisionShapes.push_back(shape);
return shape;
}
-btCollisionShape* btCollisionWorldImporter::createCylinderShapeX(btScalar radius,btScalar height)
+btCollisionShape* btCollisionWorldImporter::createCylinderShapeX(btScalar radius, btScalar height)
{
- btCylinderShapeX* shape = new btCylinderShapeX(btVector3(height,radius,radius));
+ btCylinderShapeX* shape = new btCylinderShapeX(btVector3(height, radius, radius));
m_allocatedCollisionShapes.push_back(shape);
return shape;
}
-btCollisionShape* btCollisionWorldImporter::createCylinderShapeY(btScalar radius,btScalar height)
+btCollisionShape* btCollisionWorldImporter::createCylinderShapeY(btScalar radius, btScalar height)
{
- btCylinderShape* shape = new btCylinderShape(btVector3(radius,height,radius));
+ btCylinderShape* shape = new btCylinderShape(btVector3(radius, height, radius));
m_allocatedCollisionShapes.push_back(shape);
return shape;
}
-btCollisionShape* btCollisionWorldImporter::createCylinderShapeZ(btScalar radius,btScalar height)
+btCollisionShape* btCollisionWorldImporter::createCylinderShapeZ(btScalar radius, btScalar height)
{
- btCylinderShapeZ* shape = new btCylinderShapeZ(btVector3(radius,radius,height));
+ btCylinderShapeZ* shape = new btCylinderShapeZ(btVector3(radius, radius, height));
m_allocatedCollisionShapes.push_back(shape);
return shape;
}
-btCollisionShape* btCollisionWorldImporter::createConeShapeX(btScalar radius,btScalar height)
+btCollisionShape* btCollisionWorldImporter::createConeShapeX(btScalar radius, btScalar height)
{
- btConeShapeX* shape = new btConeShapeX(radius,height);
+ btConeShapeX* shape = new btConeShapeX(radius, height);
m_allocatedCollisionShapes.push_back(shape);
return shape;
}
-btCollisionShape* btCollisionWorldImporter::createConeShapeY(btScalar radius,btScalar height)
+btCollisionShape* btCollisionWorldImporter::createConeShapeY(btScalar radius, btScalar height)
{
- btConeShape* shape = new btConeShape(radius,height);
+ btConeShape* shape = new btConeShape(radius, height);
m_allocatedCollisionShapes.push_back(shape);
return shape;
}
-btCollisionShape* btCollisionWorldImporter::createConeShapeZ(btScalar radius,btScalar height)
+btCollisionShape* btCollisionWorldImporter::createConeShapeZ(btScalar radius, btScalar height)
{
- btConeShapeZ* shape = new btConeShapeZ(radius,height);
+ btConeShapeZ* shape = new btConeShapeZ(radius, height);
m_allocatedCollisionShapes.push_back(shape);
return shape;
}
-btTriangleIndexVertexArray* btCollisionWorldImporter::createTriangleMeshContainer()
+btTriangleIndexVertexArray* btCollisionWorldImporter::createTriangleMeshContainer()
{
btTriangleIndexVertexArray* in = new btTriangleIndexVertexArray();
m_allocatedTriangleIndexArrays.push_back(in);
return in;
}
-btOptimizedBvh* btCollisionWorldImporter::createOptimizedBvh()
+btOptimizedBvh* btCollisionWorldImporter::createOptimizedBvh()
{
btOptimizedBvh* bvh = new btOptimizedBvh();
m_allocatedBvhs.push_back(bvh);
return bvh;
}
-
btTriangleInfoMap* btCollisionWorldImporter::createTriangleInfoMap()
{
btTriangleInfoMap* tim = new btTriangleInfoMap();
@@ -1027,16 +977,15 @@ btBvhTriangleMeshShape* btCollisionWorldImporter::createBvhTriangleMeshShape(btS
{
if (bvh)
{
- btBvhTriangleMeshShape* bvhTriMesh = new btBvhTriangleMeshShape(trimesh,bvh->isQuantized(), false);
+ btBvhTriangleMeshShape* bvhTriMesh = new btBvhTriangleMeshShape(trimesh, bvh->isQuantized(), false);
bvhTriMesh->setOptimizedBvh(bvh);
m_allocatedCollisionShapes.push_back(bvhTriMesh);
return bvhTriMesh;
}
- btBvhTriangleMeshShape* ts = new btBvhTriangleMeshShape(trimesh,true);
+ btBvhTriangleMeshShape* ts = new btBvhTriangleMeshShape(trimesh, true);
m_allocatedCollisionShapes.push_back(ts);
return ts;
-
}
btCollisionShape* btCollisionWorldImporter::createConvexTriangleMeshShape(btStridingMeshInterface* trimesh)
{
@@ -1048,9 +997,8 @@ btGImpactMeshShape* btCollisionWorldImporter::createGimpactShape(btStridingMeshI
btGImpactMeshShape* shape = new btGImpactMeshShape(trimesh);
m_allocatedCollisionShapes.push_back(shape);
return shape;
-
}
-#endif //SUPPORT_GIMPACT_SHAPE_IMPORT
+#endif //SUPPORT_GIMPACT_SHAPE_IMPORT
btConvexHullShape* btCollisionWorldImporter::createConvexHullShape()
{
@@ -1066,25 +1014,22 @@ btCompoundShape* btCollisionWorldImporter::createCompoundShape()
return shape;
}
-
-btScaledBvhTriangleMeshShape* btCollisionWorldImporter::createScaledTrangleMeshShape(btBvhTriangleMeshShape* meshShape,const btVector3& localScaling)
+btScaledBvhTriangleMeshShape* btCollisionWorldImporter::createScaledTrangleMeshShape(btBvhTriangleMeshShape* meshShape, const btVector3& localScaling)
{
- btScaledBvhTriangleMeshShape* shape = new btScaledBvhTriangleMeshShape(meshShape,localScaling);
+ btScaledBvhTriangleMeshShape* shape = new btScaledBvhTriangleMeshShape(meshShape, localScaling);
m_allocatedCollisionShapes.push_back(shape);
return shape;
}
-btMultiSphereShape* btCollisionWorldImporter::createMultiSphereShape(const btVector3* positions,const btScalar* radi,int numSpheres)
+btMultiSphereShape* btCollisionWorldImporter::createMultiSphereShape(const btVector3* positions, const btScalar* radi, int numSpheres)
{
btMultiSphereShape* shape = new btMultiSphereShape(positions, radi, numSpheres);
m_allocatedCollisionShapes.push_back(shape);
return shape;
}
-
-
- // query for data
-int btCollisionWorldImporter::getNumCollisionShapes() const
+// query for data
+int btCollisionWorldImporter::getNumCollisionShapes() const
{
return m_allocatedCollisionShapes.size();
}
@@ -1097,23 +1042,21 @@ btCollisionShape* btCollisionWorldImporter::getCollisionShapeByIndex(int index)
btCollisionShape* btCollisionWorldImporter::getCollisionShapeByName(const char* name)
{
btCollisionShape** shapePtr = m_nameShapeMap.find(name);
- if (shapePtr&& *shapePtr)
+ if (shapePtr && *shapePtr)
{
return *shapePtr;
}
return 0;
}
-
-const char* btCollisionWorldImporter::getNameForPointer(const void* ptr) const
+const char* btCollisionWorldImporter::getNameForPointer(const void* ptr) const
{
- const char*const * namePtr = m_objectNameMap.find(ptr);
+ const char* const* namePtr = m_objectNameMap.find(ptr);
if (namePtr && *namePtr)
return *namePtr;
return 0;
}
-
int btCollisionWorldImporter::getNumRigidBodies() const
{
return m_allocatedRigidBodies.size();
@@ -1124,12 +1067,11 @@ btCollisionObject* btCollisionWorldImporter::getRigidBodyByIndex(int index) cons
return m_allocatedRigidBodies[index];
}
-
int btCollisionWorldImporter::getNumBvhs() const
{
return m_allocatedBvhs.size();
}
- btOptimizedBvh* btCollisionWorldImporter::getBvhByIndex(int index) const
+btOptimizedBvh* btCollisionWorldImporter::getBvhByIndex(int index) const
{
return m_allocatedBvhs[index];
}
@@ -1143,5 +1085,3 @@ btTriangleInfoMap* btCollisionWorldImporter::getTriangleInfoMapByIndex(int index
{
return m_allocatedTriangleInfoMaps[index];
}
-
-
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorldImporter.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorldImporter.h
index 81c6142726..5e8bc95341 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorldImporter.h
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorldImporter.h
@@ -13,7 +13,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#ifndef BT_COLLISION_WORLD_IMPORTER_H
#define BT_COLLISION_WORLD_IMPORTER_H
@@ -26,7 +25,6 @@ class btCollisionShape;
class btCollisionObject;
struct btBulletSerializedArrays;
-
struct ConstraintInput;
class btCollisionWorld;
struct btCollisionShapeData;
@@ -46,9 +44,6 @@ class btSliderConstraint;
class btGearConstraint;
struct btContactSolverInfo;
-
-
-
class btCollisionWorldImporter
{
protected:
@@ -56,60 +51,53 @@ protected:
int m_verboseMode;
- btAlignedObjectArray<btCollisionShape*> m_allocatedCollisionShapes;
+ btAlignedObjectArray<btCollisionShape*> m_allocatedCollisionShapes;
btAlignedObjectArray<btCollisionObject*> m_allocatedRigidBodies;
- btAlignedObjectArray<btOptimizedBvh*> m_allocatedBvhs;
+ btAlignedObjectArray<btOptimizedBvh*> m_allocatedBvhs;
btAlignedObjectArray<btTriangleInfoMap*> m_allocatedTriangleInfoMaps;
btAlignedObjectArray<btTriangleIndexVertexArray*> m_allocatedTriangleIndexArrays;
btAlignedObjectArray<btStridingMeshInterfaceData*> m_allocatedbtStridingMeshInterfaceDatas;
btAlignedObjectArray<btCollisionObject*> m_allocatedCollisionObjects;
+ btAlignedObjectArray<char*> m_allocatedNames;
- btAlignedObjectArray<char*> m_allocatedNames;
+ btAlignedObjectArray<int*> m_indexArrays;
+ btAlignedObjectArray<short int*> m_shortIndexArrays;
+ btAlignedObjectArray<unsigned char*> m_charIndexArrays;
- btAlignedObjectArray<int*> m_indexArrays;
- btAlignedObjectArray<short int*> m_shortIndexArrays;
- btAlignedObjectArray<unsigned char*> m_charIndexArrays;
+ btAlignedObjectArray<btVector3FloatData*> m_floatVertexArrays;
+ btAlignedObjectArray<btVector3DoubleData*> m_doubleVertexArrays;
- btAlignedObjectArray<btVector3FloatData*> m_floatVertexArrays;
- btAlignedObjectArray<btVector3DoubleData*> m_doubleVertexArrays;
+ btHashMap<btHashPtr, btOptimizedBvh*> m_bvhMap;
+ btHashMap<btHashPtr, btTriangleInfoMap*> m_timMap;
+ btHashMap<btHashString, btCollisionShape*> m_nameShapeMap;
+ btHashMap<btHashString, btCollisionObject*> m_nameColObjMap;
- btHashMap<btHashPtr,btOptimizedBvh*> m_bvhMap;
- btHashMap<btHashPtr,btTriangleInfoMap*> m_timMap;
-
- btHashMap<btHashString,btCollisionShape*> m_nameShapeMap;
- btHashMap<btHashString,btCollisionObject*> m_nameColObjMap;
-
- btHashMap<btHashPtr,const char*> m_objectNameMap;
-
- btHashMap<btHashPtr,btCollisionShape*> m_shapeMap;
- btHashMap<btHashPtr,btCollisionObject*> m_bodyMap;
+ btHashMap<btHashPtr, const char*> m_objectNameMap;
+ btHashMap<btHashPtr, btCollisionShape*> m_shapeMap;
+ btHashMap<btHashPtr, btCollisionObject*> m_bodyMap;
//methods
+ char* duplicateName(const char* name);
-
- char* duplicateName(const char* name);
-
- btCollisionShape* convertCollisionShape( btCollisionShapeData* shapeData );
-
+ btCollisionShape* convertCollisionShape(btCollisionShapeData* shapeData);
public:
-
btCollisionWorldImporter(btCollisionWorld* world);
virtual ~btCollisionWorldImporter();
- bool convertAllObjects( btBulletSerializedArrays* arrays);
+ bool convertAllObjects(btBulletSerializedArrays* arrays);
- ///delete all memory collision shapes, rigid bodies, constraints etc. allocated during the load.
+ ///delete all memory collision shapes, rigid bodies, constraints etc. allocated during the load.
///make sure you don't use the dynamics world containing objects after you call this method
virtual void deleteAllData();
- void setVerboseMode(int verboseMode)
+ void setVerboseMode(int verboseMode)
{
m_verboseMode = verboseMode;
}
@@ -119,14 +107,14 @@ public:
return m_verboseMode;
}
- // query for data
- int getNumCollisionShapes() const;
+ // query for data
+ int getNumCollisionShapes() const;
btCollisionShape* getCollisionShapeByIndex(int index);
int getNumRigidBodies() const;
btCollisionObject* getRigidBodyByIndex(int index) const;
int getNumBvhs() const;
- btOptimizedBvh* getBvhByIndex(int index) const;
+ btOptimizedBvh* getBvhByIndex(int index) const;
int getNumTriangleInfoMaps() const;
btTriangleInfoMap* getTriangleInfoMapByIndex(int index) const;
@@ -134,56 +122,48 @@ public:
btCollisionShape* getCollisionShapeByName(const char* name);
btCollisionObject* getCollisionObjectByName(const char* name);
-
- const char* getNameForPointer(const void* ptr) const;
+ const char* getNameForPointer(const void* ptr) const;
///those virtuals are called by load and can be overridden by the user
-
-
//bodies
- virtual btCollisionObject* createCollisionObject( const btTransform& startTransform, btCollisionShape* shape,const char* bodyName);
+ virtual btCollisionObject* createCollisionObject(const btTransform& startTransform, btCollisionShape* shape, const char* bodyName);
///shapes
- virtual btCollisionShape* createPlaneShape(const btVector3& planeNormal,btScalar planeConstant);
+ virtual btCollisionShape* createPlaneShape(const btVector3& planeNormal, btScalar planeConstant);
virtual btCollisionShape* createBoxShape(const btVector3& halfExtents);
virtual btCollisionShape* createSphereShape(btScalar radius);
virtual btCollisionShape* createCapsuleShapeX(btScalar radius, btScalar height);
virtual btCollisionShape* createCapsuleShapeY(btScalar radius, btScalar height);
virtual btCollisionShape* createCapsuleShapeZ(btScalar radius, btScalar height);
- virtual btCollisionShape* createCylinderShapeX(btScalar radius,btScalar height);
- virtual btCollisionShape* createCylinderShapeY(btScalar radius,btScalar height);
- virtual btCollisionShape* createCylinderShapeZ(btScalar radius,btScalar height);
- virtual btCollisionShape* createConeShapeX(btScalar radius,btScalar height);
- virtual btCollisionShape* createConeShapeY(btScalar radius,btScalar height);
- virtual btCollisionShape* createConeShapeZ(btScalar radius,btScalar height);
- virtual class btTriangleIndexVertexArray* createTriangleMeshContainer();
- virtual btBvhTriangleMeshShape* createBvhTriangleMeshShape(btStridingMeshInterface* trimesh, btOptimizedBvh* bvh);
+ virtual btCollisionShape* createCylinderShapeX(btScalar radius, btScalar height);
+ virtual btCollisionShape* createCylinderShapeY(btScalar radius, btScalar height);
+ virtual btCollisionShape* createCylinderShapeZ(btScalar radius, btScalar height);
+ virtual btCollisionShape* createConeShapeX(btScalar radius, btScalar height);
+ virtual btCollisionShape* createConeShapeY(btScalar radius, btScalar height);
+ virtual btCollisionShape* createConeShapeZ(btScalar radius, btScalar height);
+ virtual class btTriangleIndexVertexArray* createTriangleMeshContainer();
+ virtual btBvhTriangleMeshShape* createBvhTriangleMeshShape(btStridingMeshInterface* trimesh, btOptimizedBvh* bvh);
virtual btCollisionShape* createConvexTriangleMeshShape(btStridingMeshInterface* trimesh);
#ifdef SUPPORT_GIMPACT_SHAPE_IMPORT
virtual btGImpactMeshShape* createGimpactShape(btStridingMeshInterface* trimesh);
-#endif //SUPPORT_GIMPACT_SHAPE_IMPORT
+#endif //SUPPORT_GIMPACT_SHAPE_IMPORT
virtual btStridingMeshInterfaceData* createStridingMeshInterfaceData(btStridingMeshInterfaceData* interfaceData);
virtual class btConvexHullShape* createConvexHullShape();
virtual class btCompoundShape* createCompoundShape();
- virtual class btScaledBvhTriangleMeshShape* createScaledTrangleMeshShape(btBvhTriangleMeshShape* meshShape,const btVector3& localScalingbtBvhTriangleMeshShape);
+ virtual class btScaledBvhTriangleMeshShape* createScaledTrangleMeshShape(btBvhTriangleMeshShape* meshShape, const btVector3& localScalingbtBvhTriangleMeshShape);
- virtual class btMultiSphereShape* createMultiSphereShape(const btVector3* positions,const btScalar* radi,int numSpheres);
+ virtual class btMultiSphereShape* createMultiSphereShape(const btVector3* positions, const btScalar* radi, int numSpheres);
virtual btTriangleIndexVertexArray* createMeshInterface(btStridingMeshInterfaceData& meshData);
///acceleration and connectivity structures
- virtual btOptimizedBvh* createOptimizedBvh();
+ virtual btOptimizedBvh* createOptimizedBvh();
virtual btTriangleInfoMap* createTriangleInfoMap();
-
-
-
-
};
-
-#endif //BT_WORLD_IMPORTER_H
+#endif //BT_WORLD_IMPORTER_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp
index 91b7809c17..633bee4825 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp
@@ -25,62 +25,58 @@ subject to the following restrictions:
btShapePairCallback gCompoundChildShapePairCallback = 0;
-btCompoundCollisionAlgorithm::btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped)
-:btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap),
-m_isSwapped(isSwapped),
-m_sharedManifold(ci.m_manifold)
+btCompoundCollisionAlgorithm::btCompoundCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped)
+ : btActivatingCollisionAlgorithm(ci, body0Wrap, body1Wrap),
+ m_isSwapped(isSwapped),
+ m_sharedManifold(ci.m_manifold)
{
m_ownsManifold = false;
- const btCollisionObjectWrapper* colObjWrap = m_isSwapped? body1Wrap : body0Wrap;
- btAssert (colObjWrap->getCollisionShape()->isCompound());
-
+ const btCollisionObjectWrapper* colObjWrap = m_isSwapped ? body1Wrap : body0Wrap;
+ btAssert(colObjWrap->getCollisionShape()->isCompound());
+
const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(colObjWrap->getCollisionShape());
m_compoundShapeRevision = compoundShape->getUpdateRevision();
-
-
- preallocateChildAlgorithms(body0Wrap,body1Wrap);
+
+ preallocateChildAlgorithms(body0Wrap, body1Wrap);
}
-void btCompoundCollisionAlgorithm::preallocateChildAlgorithms(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+void btCompoundCollisionAlgorithm::preallocateChildAlgorithms(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
{
- const btCollisionObjectWrapper* colObjWrap = m_isSwapped? body1Wrap : body0Wrap;
- const btCollisionObjectWrapper* otherObjWrap = m_isSwapped? body0Wrap : body1Wrap;
- btAssert (colObjWrap->getCollisionShape()->isCompound());
-
+ const btCollisionObjectWrapper* colObjWrap = m_isSwapped ? body1Wrap : body0Wrap;
+ const btCollisionObjectWrapper* otherObjWrap = m_isSwapped ? body0Wrap : body1Wrap;
+ btAssert(colObjWrap->getCollisionShape()->isCompound());
+
const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(colObjWrap->getCollisionShape());
int numChildren = compoundShape->getNumChildShapes();
int i;
-
+
m_childCollisionAlgorithms.resize(numChildren);
- for (i=0;i<numChildren;i++)
+ for (i = 0; i < numChildren; i++)
{
if (compoundShape->getDynamicAabbTree())
{
m_childCollisionAlgorithms[i] = 0;
- } else
+ }
+ else
{
-
const btCollisionShape* childShape = compoundShape->getChildShape(i);
- btCollisionObjectWrapper childWrap(colObjWrap,childShape,colObjWrap->getCollisionObject(),colObjWrap->getWorldTransform(),-1,i);//wrong child trans, but unused (hopefully)
- m_childCollisionAlgorithms[i] = m_dispatcher->findAlgorithm(&childWrap,otherObjWrap,m_sharedManifold, BT_CONTACT_POINT_ALGORITHMS);
-
+ btCollisionObjectWrapper childWrap(colObjWrap, childShape, colObjWrap->getCollisionObject(), colObjWrap->getWorldTransform(), -1, i); //wrong child trans, but unused (hopefully)
+ m_childCollisionAlgorithms[i] = m_dispatcher->findAlgorithm(&childWrap, otherObjWrap, m_sharedManifold, BT_CONTACT_POINT_ALGORITHMS);
btAlignedObjectArray<btCollisionAlgorithm*> m_childCollisionAlgorithmsContact;
btAlignedObjectArray<btCollisionAlgorithm*> m_childCollisionAlgorithmsClosestPoints;
-
-
}
}
}
-void btCompoundCollisionAlgorithm::removeChildAlgorithms()
+void btCompoundCollisionAlgorithm::removeChildAlgorithms()
{
int numChildren = m_childCollisionAlgorithms.size();
int i;
- for (i=0;i<numChildren;i++)
+ for (i = 0; i < numChildren; i++)
{
if (m_childCollisionAlgorithms[i])
{
@@ -95,66 +91,56 @@ btCompoundCollisionAlgorithm::~btCompoundCollisionAlgorithm()
removeChildAlgorithms();
}
-
-
-
-struct btCompoundLeafCallback : btDbvt::ICollide
+struct btCompoundLeafCallback : btDbvt::ICollide
{
-
public:
-
const btCollisionObjectWrapper* m_compoundColObjWrap;
const btCollisionObjectWrapper* m_otherObjWrap;
btDispatcher* m_dispatcher;
const btDispatcherInfo& m_dispatchInfo;
- btManifoldResult* m_resultOut;
- btCollisionAlgorithm** m_childCollisionAlgorithms;
- btPersistentManifold* m_sharedManifold;
-
- btCompoundLeafCallback (const btCollisionObjectWrapper* compoundObjWrap,const btCollisionObjectWrapper* otherObjWrap,btDispatcher* dispatcher,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut,btCollisionAlgorithm** childCollisionAlgorithms,btPersistentManifold* sharedManifold)
- :m_compoundColObjWrap(compoundObjWrap),m_otherObjWrap(otherObjWrap),m_dispatcher(dispatcher),m_dispatchInfo(dispatchInfo),m_resultOut(resultOut),
- m_childCollisionAlgorithms(childCollisionAlgorithms),
- m_sharedManifold(sharedManifold)
- {
+ btManifoldResult* m_resultOut;
+ btCollisionAlgorithm** m_childCollisionAlgorithms;
+ btPersistentManifold* m_sharedManifold;
+ btCompoundLeafCallback(const btCollisionObjectWrapper* compoundObjWrap, const btCollisionObjectWrapper* otherObjWrap, btDispatcher* dispatcher, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut, btCollisionAlgorithm** childCollisionAlgorithms, btPersistentManifold* sharedManifold)
+ : m_compoundColObjWrap(compoundObjWrap), m_otherObjWrap(otherObjWrap), m_dispatcher(dispatcher), m_dispatchInfo(dispatchInfo), m_resultOut(resultOut), m_childCollisionAlgorithms(childCollisionAlgorithms), m_sharedManifold(sharedManifold)
+ {
}
-
- void ProcessChildShape(const btCollisionShape* childShape,int index)
+ void ProcessChildShape(const btCollisionShape* childShape, int index)
{
- btAssert(index>=0);
+ btAssert(index >= 0);
const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(m_compoundColObjWrap->getCollisionShape());
- btAssert(index<compoundShape->getNumChildShapes());
+ btAssert(index < compoundShape->getNumChildShapes());
+ if (gCompoundChildShapePairCallback)
+ {
+ if (!gCompoundChildShapePairCallback(m_otherObjWrap->getCollisionShape(), childShape))
+ return;
+ }
//backup
- btTransform orgTrans = m_compoundColObjWrap->getWorldTransform();
-
+ btTransform orgTrans = m_compoundColObjWrap->getWorldTransform();
+
const btTransform& childTrans = compoundShape->getChildTransform(index);
- btTransform newChildWorldTrans = orgTrans*childTrans ;
+ btTransform newChildWorldTrans = orgTrans * childTrans;
//perform an AABB check first
- btVector3 aabbMin0,aabbMax0;
- childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0);
+ btVector3 aabbMin0, aabbMax0;
+ childShape->getAabb(newChildWorldTrans, aabbMin0, aabbMax0);
btVector3 extendAabb(m_resultOut->m_closestPointDistanceThreshold, m_resultOut->m_closestPointDistanceThreshold, m_resultOut->m_closestPointDistanceThreshold);
aabbMin0 -= extendAabb;
aabbMax0 += extendAabb;
btVector3 aabbMin1, aabbMax1;
- m_otherObjWrap->getCollisionShape()->getAabb(m_otherObjWrap->getWorldTransform(),aabbMin1,aabbMax1);
+ m_otherObjWrap->getCollisionShape()->getAabb(m_otherObjWrap->getWorldTransform(), aabbMin1, aabbMax1);
- if (gCompoundChildShapePairCallback)
- {
- if (!gCompoundChildShapePairCallback(m_otherObjWrap->getCollisionShape(), childShape))
- return;
- }
- if (TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
+ if (TestAabbAgainstAabb2(aabbMin0, aabbMax0, aabbMin1, aabbMax1))
{
+ btCollisionObjectWrapper compoundWrap(this->m_compoundColObjWrap, childShape, m_compoundColObjWrap->getCollisionObject(), newChildWorldTrans, -1, index);
- btCollisionObjectWrapper compoundWrap(this->m_compoundColObjWrap,childShape,m_compoundColObjWrap->getCollisionObject(),newChildWorldTrans,-1,index);
-
btCollisionAlgorithm* algo = 0;
bool allocatedAlgorithm = false;
@@ -172,7 +158,7 @@ public:
}
algo = m_childCollisionAlgorithms[index];
}
-
+
const btCollisionObjectWrapper* tmpWrap = 0;
///detect swapping case
@@ -180,15 +166,16 @@ public:
{
tmpWrap = m_resultOut->getBody0Wrap();
m_resultOut->setBody0Wrap(&compoundWrap);
- m_resultOut->setShapeIdentifiersA(-1,index);
- } else
+ m_resultOut->setShapeIdentifiersA(-1, index);
+ }
+ else
{
tmpWrap = m_resultOut->getBody1Wrap();
m_resultOut->setBody1Wrap(&compoundWrap);
- m_resultOut->setShapeIdentifiersB(-1,index);
+ m_resultOut->setShapeIdentifiersB(-1, index);
}
- algo->processCollision(&compoundWrap,m_otherObjWrap,m_dispatchInfo,m_resultOut);
+ algo->processCollision(&compoundWrap, m_otherObjWrap, m_dispatchInfo, m_resultOut);
#if 0
if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
@@ -202,18 +189,19 @@ public:
if (m_resultOut->getBody0Internal() == m_compoundColObjWrap->getCollisionObject())
{
m_resultOut->setBody0Wrap(tmpWrap);
- } else
+ }
+ else
{
m_resultOut->setBody1Wrap(tmpWrap);
}
- if(allocatedAlgorithm)
+ if (allocatedAlgorithm)
{
algo->~btCollisionAlgorithm();
m_dispatcher->freeCollisionAlgorithm(algo);
- }
+ }
}
}
- void Process(const btDbvtNode* leaf)
+ void Process(const btDbvtNode* leaf)
{
int index = leaf->dataAsInt;
@@ -230,22 +218,16 @@ public:
}
#endif
- ProcessChildShape(childShape,index);
-
+ ProcessChildShape(childShape, index);
}
};
-
-
-
-
-
-void btCompoundCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+void btCompoundCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
{
- const btCollisionObjectWrapper* colObjWrap = m_isSwapped? body1Wrap : body0Wrap;
- const btCollisionObjectWrapper* otherObjWrap = m_isSwapped? body0Wrap : body1Wrap;
+ const btCollisionObjectWrapper* colObjWrap = m_isSwapped ? body1Wrap : body0Wrap;
+ const btCollisionObjectWrapper* otherObjWrap = m_isSwapped ? body0Wrap : body1Wrap;
- btAssert (colObjWrap->getCollisionShape()->isCompound());
+ btAssert(colObjWrap->getCollisionShape()->isCompound());
const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(colObjWrap->getCollisionShape());
///btCompoundShape might have changed:
@@ -254,17 +236,17 @@ void btCompoundCollisionAlgorithm::processCollision (const btCollisionObjectWrap
{
///clear and update all
removeChildAlgorithms();
-
- preallocateChildAlgorithms(body0Wrap,body1Wrap);
+
+ preallocateChildAlgorithms(body0Wrap, body1Wrap);
m_compoundShapeRevision = compoundShape->getUpdateRevision();
}
- if (m_childCollisionAlgorithms.size()==0)
+ if (m_childCollisionAlgorithms.size() == 0)
return;
const btDbvt* tree = compoundShape->getDynamicAabbTree();
//use a dynamic aabb tree to cull potential child-overlaps
- btCompoundLeafCallback callback(colObjWrap,otherObjWrap,m_dispatcher,dispatchInfo,resultOut,&m_childCollisionAlgorithms[0],m_sharedManifold);
+ btCompoundLeafCallback callback(colObjWrap, otherObjWrap, m_dispatcher, dispatchInfo, resultOut, &m_childCollisionAlgorithms[0], m_sharedManifold);
///we need to refresh all contact manifolds
///note that we should actually recursively traverse all children, btCompoundShape can nested more then 1 level deep
@@ -272,18 +254,18 @@ void btCompoundCollisionAlgorithm::processCollision (const btCollisionObjectWrap
{
int i;
manifoldArray.resize(0);
- for (i=0;i<m_childCollisionAlgorithms.size();i++)
+ for (i = 0; i < m_childCollisionAlgorithms.size(); i++)
{
if (m_childCollisionAlgorithms[i])
{
m_childCollisionAlgorithms[i]->getAllContactManifolds(manifoldArray);
- for (int m=0;m<manifoldArray.size();m++)
+ for (int m = 0; m < manifoldArray.size(); m++)
{
if (manifoldArray[m]->getNumContacts())
{
resultOut->setPersistentManifold(manifoldArray[m]);
resultOut->refreshContactPoints();
- resultOut->setPersistentManifold(0);//??necessary?
+ resultOut->setPersistentManifold(0); //??necessary?
}
}
manifoldArray.resize(0);
@@ -293,57 +275,56 @@ void btCompoundCollisionAlgorithm::processCollision (const btCollisionObjectWrap
if (tree)
{
-
- btVector3 localAabbMin,localAabbMax;
+ btVector3 localAabbMin, localAabbMax;
btTransform otherInCompoundSpace;
otherInCompoundSpace = colObjWrap->getWorldTransform().inverse() * otherObjWrap->getWorldTransform();
- otherObjWrap->getCollisionShape()->getAabb(otherInCompoundSpace,localAabbMin,localAabbMax);
+ otherObjWrap->getCollisionShape()->getAabb(otherInCompoundSpace, localAabbMin, localAabbMax);
btVector3 extraExtends(resultOut->m_closestPointDistanceThreshold, resultOut->m_closestPointDistanceThreshold, resultOut->m_closestPointDistanceThreshold);
localAabbMin -= extraExtends;
localAabbMax += extraExtends;
- const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
+ const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds = btDbvtVolume::FromMM(localAabbMin, localAabbMax);
//process all children, that overlap with the given AABB bounds
- tree->collideTVNoStackAlloc(tree->m_root,bounds,stack2,callback);
-
- } else
+ tree->collideTVNoStackAlloc(tree->m_root, bounds, stack2, callback);
+ }
+ else
{
//iterate over all children, perform an AABB check inside ProcessChildShape
int numChildren = m_childCollisionAlgorithms.size();
int i;
- for (i=0;i<numChildren;i++)
+ for (i = 0; i < numChildren; i++)
{
- callback.ProcessChildShape(compoundShape->getChildShape(i),i);
+ callback.ProcessChildShape(compoundShape->getChildShape(i), i);
}
}
{
- //iterate over all children, perform an AABB check inside ProcessChildShape
+ //iterate over all children, perform an AABB check inside ProcessChildShape
int numChildren = m_childCollisionAlgorithms.size();
int i;
manifoldArray.resize(0);
- const btCollisionShape* childShape = 0;
- btTransform orgTrans;
-
- btTransform newChildWorldTrans;
- btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1;
-
- for (i=0;i<numChildren;i++)
+ const btCollisionShape* childShape = 0;
+ btTransform orgTrans;
+
+ btTransform newChildWorldTrans;
+ btVector3 aabbMin0, aabbMax0, aabbMin1, aabbMax1;
+
+ for (i = 0; i < numChildren; i++)
{
if (m_childCollisionAlgorithms[i])
{
childShape = compoundShape->getChildShape(i);
- //if not longer overlapping, remove the algorithm
+ //if not longer overlapping, remove the algorithm
orgTrans = colObjWrap->getWorldTransform();
-
+
const btTransform& childTrans = compoundShape->getChildTransform(i);
- newChildWorldTrans = orgTrans*childTrans ;
+ newChildWorldTrans = orgTrans * childTrans;
//perform an AABB check first
- childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0);
- otherObjWrap->getCollisionShape()->getAabb(otherObjWrap->getWorldTransform(),aabbMin1,aabbMax1);
+ childShape->getAabb(newChildWorldTrans, aabbMin0, aabbMax0);
+ otherObjWrap->getCollisionShape()->getAabb(otherObjWrap->getWorldTransform(), aabbMin1, aabbMax1);
- if (!TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
+ if (!TestAabbAgainstAabb2(aabbMin0, aabbMax0, aabbMin1, aabbMax1))
{
m_childCollisionAlgorithms[i]->~btCollisionAlgorithm();
m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]);
@@ -354,15 +335,15 @@ void btCompoundCollisionAlgorithm::processCollision (const btCollisionObjectWrap
}
}
-btScalar btCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+btScalar btCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
{
btAssert(0);
//needs to be fixed, using btCollisionObjectWrapper and NOT modifying internal data structures
- btCollisionObject* colObj = m_isSwapped? body1 : body0;
- btCollisionObject* otherObj = m_isSwapped? body0 : body1;
+ btCollisionObject* colObj = m_isSwapped ? body1 : body0;
+ btCollisionObject* otherObj = m_isSwapped ? body0 : body1;
+
+ btAssert(colObj->getCollisionShape()->isCompound());
- btAssert (colObj->getCollisionShape()->isCompound());
-
btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
//We will use the OptimizedBVH, AABB tree to cull potential child-overlaps
@@ -376,33 +357,29 @@ btScalar btCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject*
int numChildren = m_childCollisionAlgorithms.size();
int i;
- btTransform orgTrans;
- btScalar frac;
- for (i=0;i<numChildren;i++)
+ btTransform orgTrans;
+ btScalar frac;
+ for (i = 0; i < numChildren; i++)
{
//btCollisionShape* childShape = compoundShape->getChildShape(i);
//backup
- orgTrans = colObj->getWorldTransform();
-
+ orgTrans = colObj->getWorldTransform();
+
const btTransform& childTrans = compoundShape->getChildTransform(i);
//btTransform newChildWorldTrans = orgTrans*childTrans ;
- colObj->setWorldTransform( orgTrans*childTrans );
+ colObj->setWorldTransform(orgTrans * childTrans);
//btCollisionShape* tmpShape = colObj->getCollisionShape();
//colObj->internalSetTemporaryCollisionShape( childShape );
- frac = m_childCollisionAlgorithms[i]->calculateTimeOfImpact(colObj,otherObj,dispatchInfo,resultOut);
- if (frac<hitFraction)
+ frac = m_childCollisionAlgorithms[i]->calculateTimeOfImpact(colObj, otherObj, dispatchInfo, resultOut);
+ if (frac < hitFraction)
{
hitFraction = frac;
}
//revert back
//colObj->internalSetTemporaryCollisionShape( tmpShape);
- colObj->setWorldTransform( orgTrans);
+ colObj->setWorldTransform(orgTrans);
}
return hitFraction;
-
}
-
-
-
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h
index d2086fbc02..4ea5e77185 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h
@@ -35,7 +35,7 @@ typedef bool (*btShapePairCallback)(const btCollisionShape* pShape0, const btCol
extern btShapePairCallback gCompoundChildShapePairCallback;
/// btCompoundCollisionAlgorithm supports collision between CompoundCollisionShapes and other collision shapes
-class btCompoundCollisionAlgorithm : public btActivatingCollisionAlgorithm
+class btCompoundCollisionAlgorithm : public btActivatingCollisionAlgorithm
{
btNodeStack stack2;
btManifoldArray manifoldArray;
@@ -44,61 +44,56 @@ protected:
btAlignedObjectArray<btCollisionAlgorithm*> m_childCollisionAlgorithms;
bool m_isSwapped;
- class btPersistentManifold* m_sharedManifold;
- bool m_ownsManifold;
+ class btPersistentManifold* m_sharedManifold;
+ bool m_ownsManifold;
+ int m_compoundShapeRevision; //to keep track of changes, so that childAlgorithm array can be updated
- int m_compoundShapeRevision;//to keep track of changes, so that childAlgorithm array can be updated
-
- void removeChildAlgorithms();
-
- void preallocateChildAlgorithms(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
+ void removeChildAlgorithms();
-public:
+ void preallocateChildAlgorithms(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap);
- btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped);
+public:
+ btCompoundCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped);
virtual ~btCompoundCollisionAlgorithm();
- btCollisionAlgorithm* getChildAlgorithm (int n) const
+ btCollisionAlgorithm* getChildAlgorithm(int n) const
{
return m_childCollisionAlgorithms[n];
}
+ virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
- virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
- btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
-
- virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
int i;
- for (i=0;i<m_childCollisionAlgorithms.size();i++)
+ for (i = 0; i < m_childCollisionAlgorithms.size(); i++)
{
if (m_childCollisionAlgorithms[i])
m_childCollisionAlgorithms[i]->getAllContactManifolds(manifoldArray);
}
}
-
- struct CreateFunc :public btCollisionAlgorithmCreateFunc
+ struct CreateFunc : public btCollisionAlgorithmCreateFunc
{
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm));
- return new(mem) btCompoundCollisionAlgorithm(ci,body0Wrap,body1Wrap,false);
+ return new (mem) btCompoundCollisionAlgorithm(ci, body0Wrap, body1Wrap, false);
}
};
- struct SwappedCreateFunc :public btCollisionAlgorithmCreateFunc
+ struct SwappedCreateFunc : public btCollisionAlgorithmCreateFunc
{
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm));
- return new(mem) btCompoundCollisionAlgorithm(ci,body0Wrap,body1Wrap,true);
+ return new (mem) btCompoundCollisionAlgorithm(ci, body0Wrap, body1Wrap, true);
}
};
-
};
-#endif //BT_COMPOUND_COLLISION_ALGORITHM_H
+#endif //BT_COMPOUND_COLLISION_ALGORITHM_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp
index 20b542f670..044b60dbb1 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp
@@ -29,29 +29,25 @@ subject to the following restrictions:
btShapePairCallback gCompoundCompoundChildShapePairCallback = 0;
-btCompoundCompoundCollisionAlgorithm::btCompoundCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped)
-:btCompoundCollisionAlgorithm(ci,body0Wrap,body1Wrap,isSwapped)
+btCompoundCompoundCollisionAlgorithm::btCompoundCompoundCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped)
+ : btCompoundCollisionAlgorithm(ci, body0Wrap, body1Wrap, isSwapped)
{
-
- void* ptr = btAlignedAlloc(sizeof(btHashedSimplePairCache),16);
- m_childCollisionAlgorithmCache= new(ptr) btHashedSimplePairCache();
+ void* ptr = btAlignedAlloc(sizeof(btHashedSimplePairCache), 16);
+ m_childCollisionAlgorithmCache = new (ptr) btHashedSimplePairCache();
const btCollisionObjectWrapper* col0ObjWrap = body0Wrap;
- btAssert (col0ObjWrap->getCollisionShape()->isCompound());
+ btAssert(col0ObjWrap->getCollisionShape()->isCompound());
const btCollisionObjectWrapper* col1ObjWrap = body1Wrap;
- btAssert (col1ObjWrap->getCollisionShape()->isCompound());
-
+ btAssert(col1ObjWrap->getCollisionShape()->isCompound());
+
const btCompoundShape* compoundShape0 = static_cast<const btCompoundShape*>(col0ObjWrap->getCollisionShape());
m_compoundShapeRevision0 = compoundShape0->getUpdateRevision();
const btCompoundShape* compoundShape1 = static_cast<const btCompoundShape*>(col1ObjWrap->getCollisionShape());
m_compoundShapeRevision1 = compoundShape1->getUpdateRevision();
-
-
}
-
btCompoundCompoundCollisionAlgorithm::~btCompoundCompoundCollisionAlgorithm()
{
removeChildAlgorithms();
@@ -59,32 +55,30 @@ btCompoundCompoundCollisionAlgorithm::~btCompoundCompoundCollisionAlgorithm()
btAlignedFree(m_childCollisionAlgorithmCache);
}
-void btCompoundCompoundCollisionAlgorithm::getAllContactManifolds(btManifoldArray& manifoldArray)
+void btCompoundCompoundCollisionAlgorithm::getAllContactManifolds(btManifoldArray& manifoldArray)
{
int i;
btSimplePairArray& pairs = m_childCollisionAlgorithmCache->getOverlappingPairArray();
- for (i=0;i<pairs.size();i++)
+ for (i = 0; i < pairs.size(); i++)
{
if (pairs[i].m_userPointer)
{
-
((btCollisionAlgorithm*)pairs[i].m_userPointer)->getAllContactManifolds(manifoldArray);
}
}
}
-
-void btCompoundCompoundCollisionAlgorithm::removeChildAlgorithms()
+void btCompoundCompoundCollisionAlgorithm::removeChildAlgorithms()
{
btSimplePairArray& pairs = m_childCollisionAlgorithmCache->getOverlappingPairArray();
int numChildren = pairs.size();
int i;
- for (i=0;i<numChildren;i++)
+ for (i = 0; i < numChildren; i++)
{
if (pairs[i].m_userPointer)
{
- btCollisionAlgorithm* algo = (btCollisionAlgorithm*) pairs[i].m_userPointer;
+ btCollisionAlgorithm* algo = (btCollisionAlgorithm*)pairs[i].m_userPointer;
algo->~btCollisionAlgorithm();
m_dispatcher->freeCollisionAlgorithm(algo);
}
@@ -92,77 +86,65 @@ void btCompoundCompoundCollisionAlgorithm::removeChildAlgorithms()
m_childCollisionAlgorithmCache->removeAllPairs();
}
-struct btCompoundCompoundLeafCallback : btDbvt::ICollide
+struct btCompoundCompoundLeafCallback : btDbvt::ICollide
{
int m_numOverlapPairs;
-
const btCollisionObjectWrapper* m_compound0ColObjWrap;
const btCollisionObjectWrapper* m_compound1ColObjWrap;
btDispatcher* m_dispatcher;
const btDispatcherInfo& m_dispatchInfo;
- btManifoldResult* m_resultOut;
-
-
- class btHashedSimplePairCache* m_childCollisionAlgorithmCache;
-
- btPersistentManifold* m_sharedManifold;
-
- btCompoundCompoundLeafCallback (const btCollisionObjectWrapper* compound1ObjWrap,
- const btCollisionObjectWrapper* compound0ObjWrap,
- btDispatcher* dispatcher,
- const btDispatcherInfo& dispatchInfo,
- btManifoldResult* resultOut,
- btHashedSimplePairCache* childAlgorithmsCache,
- btPersistentManifold* sharedManifold)
- :m_numOverlapPairs(0),m_compound0ColObjWrap(compound1ObjWrap),m_compound1ColObjWrap(compound0ObjWrap),m_dispatcher(dispatcher),m_dispatchInfo(dispatchInfo),m_resultOut(resultOut),
- m_childCollisionAlgorithmCache(childAlgorithmsCache),
- m_sharedManifold(sharedManifold)
- {
+ btManifoldResult* m_resultOut;
- }
+ class btHashedSimplePairCache* m_childCollisionAlgorithmCache;
+ btPersistentManifold* m_sharedManifold;
+ btCompoundCompoundLeafCallback(const btCollisionObjectWrapper* compound1ObjWrap,
+ const btCollisionObjectWrapper* compound0ObjWrap,
+ btDispatcher* dispatcher,
+ const btDispatcherInfo& dispatchInfo,
+ btManifoldResult* resultOut,
+ btHashedSimplePairCache* childAlgorithmsCache,
+ btPersistentManifold* sharedManifold)
+ : m_numOverlapPairs(0), m_compound0ColObjWrap(compound1ObjWrap), m_compound1ColObjWrap(compound0ObjWrap), m_dispatcher(dispatcher), m_dispatchInfo(dispatchInfo), m_resultOut(resultOut), m_childCollisionAlgorithmCache(childAlgorithmsCache), m_sharedManifold(sharedManifold)
+ {
+ }
-
- void Process(const btDbvtNode* leaf0,const btDbvtNode* leaf1)
+ void Process(const btDbvtNode* leaf0, const btDbvtNode* leaf1)
{
BT_PROFILE("btCompoundCompoundLeafCallback::Process");
m_numOverlapPairs++;
-
int childIndex0 = leaf0->dataAsInt;
int childIndex1 = leaf1->dataAsInt;
-
-
- btAssert(childIndex0>=0);
- btAssert(childIndex1>=0);
+ btAssert(childIndex0 >= 0);
+ btAssert(childIndex1 >= 0);
const btCompoundShape* compoundShape0 = static_cast<const btCompoundShape*>(m_compound0ColObjWrap->getCollisionShape());
- btAssert(childIndex0<compoundShape0->getNumChildShapes());
+ btAssert(childIndex0 < compoundShape0->getNumChildShapes());
const btCompoundShape* compoundShape1 = static_cast<const btCompoundShape*>(m_compound1ColObjWrap->getCollisionShape());
- btAssert(childIndex1<compoundShape1->getNumChildShapes());
+ btAssert(childIndex1 < compoundShape1->getNumChildShapes());
const btCollisionShape* childShape0 = compoundShape0->getChildShape(childIndex0);
const btCollisionShape* childShape1 = compoundShape1->getChildShape(childIndex1);
//backup
- btTransform orgTrans0 = m_compound0ColObjWrap->getWorldTransform();
+ btTransform orgTrans0 = m_compound0ColObjWrap->getWorldTransform();
const btTransform& childTrans0 = compoundShape0->getChildTransform(childIndex0);
- btTransform newChildWorldTrans0 = orgTrans0*childTrans0 ;
-
- btTransform orgTrans1 = m_compound1ColObjWrap->getWorldTransform();
+ btTransform newChildWorldTrans0 = orgTrans0 * childTrans0;
+
+ btTransform orgTrans1 = m_compound1ColObjWrap->getWorldTransform();
const btTransform& childTrans1 = compoundShape1->getChildTransform(childIndex1);
- btTransform newChildWorldTrans1 = orgTrans1*childTrans1 ;
-
+ btTransform newChildWorldTrans1 = orgTrans1 * childTrans1;
//perform an AABB check first
- btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1;
- childShape0->getAabb(newChildWorldTrans0,aabbMin0,aabbMax0);
- childShape1->getAabb(newChildWorldTrans1,aabbMin1,aabbMax1);
-
+ btVector3 aabbMin0, aabbMax0, aabbMin1, aabbMax1;
+ childShape0->getAabb(newChildWorldTrans0, aabbMin0, aabbMax0);
+ childShape1->getAabb(newChildWorldTrans1, aabbMin1, aabbMax1);
+
btVector3 thresholdVec(m_resultOut->m_closestPointDistanceThreshold, m_resultOut->m_closestPointDistanceThreshold, m_resultOut->m_closestPointDistanceThreshold);
aabbMin0 -= thresholdVec;
@@ -170,17 +152,16 @@ struct btCompoundCompoundLeafCallback : btDbvt::ICollide
if (gCompoundCompoundChildShapePairCallback)
{
- if (!gCompoundCompoundChildShapePairCallback(childShape0,childShape1))
+ if (!gCompoundCompoundChildShapePairCallback(childShape0, childShape1))
return;
}
- if (TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
+ if (TestAabbAgainstAabb2(aabbMin0, aabbMax0, aabbMin1, aabbMax1))
{
- btCollisionObjectWrapper compoundWrap0(this->m_compound0ColObjWrap,childShape0, m_compound0ColObjWrap->getCollisionObject(),newChildWorldTrans0,-1,childIndex0);
- btCollisionObjectWrapper compoundWrap1(this->m_compound1ColObjWrap,childShape1,m_compound1ColObjWrap->getCollisionObject(),newChildWorldTrans1,-1,childIndex1);
-
+ btCollisionObjectWrapper compoundWrap0(this->m_compound0ColObjWrap, childShape0, m_compound0ColObjWrap->getCollisionObject(), newChildWorldTrans0, -1, childIndex0);
+ btCollisionObjectWrapper compoundWrap1(this->m_compound1ColObjWrap, childShape1, m_compound1ColObjWrap->getCollisionObject(), newChildWorldTrans1, -1, childIndex1);
- btSimplePair* pair = m_childCollisionAlgorithmCache->findPair(childIndex0,childIndex1);
+ btSimplePair* pair = m_childCollisionAlgorithmCache->findPair(childIndex0, childIndex1);
bool removePair = false;
btCollisionAlgorithm* colAlgo = 0;
if (m_resultOut->m_closestPointDistanceThreshold > 0)
@@ -193,7 +174,6 @@ struct btCompoundCompoundLeafCallback : btDbvt::ICollide
if (pair)
{
colAlgo = (btCollisionAlgorithm*)pair->m_userPointer;
-
}
else
{
@@ -205,7 +185,7 @@ struct btCompoundCompoundLeafCallback : btDbvt::ICollide
}
btAssert(colAlgo);
-
+
const btCollisionObjectWrapper* tmpWrap0 = 0;
const btCollisionObjectWrapper* tmpWrap1 = 0;
@@ -215,105 +195,100 @@ struct btCompoundCompoundLeafCallback : btDbvt::ICollide
m_resultOut->setBody0Wrap(&compoundWrap0);
m_resultOut->setBody1Wrap(&compoundWrap1);
- m_resultOut->setShapeIdentifiersA(-1,childIndex0);
- m_resultOut->setShapeIdentifiersB(-1,childIndex1);
+ m_resultOut->setShapeIdentifiersA(-1, childIndex0);
+ m_resultOut->setShapeIdentifiersB(-1, childIndex1);
+ colAlgo->processCollision(&compoundWrap0, &compoundWrap1, m_dispatchInfo, m_resultOut);
- colAlgo->processCollision(&compoundWrap0,&compoundWrap1,m_dispatchInfo,m_resultOut);
-
m_resultOut->setBody0Wrap(tmpWrap0);
m_resultOut->setBody1Wrap(tmpWrap1);
-
+
if (removePair)
{
colAlgo->~btCollisionAlgorithm();
m_dispatcher->freeCollisionAlgorithm(colAlgo);
}
-
}
}
};
-
-static DBVT_INLINE bool MyIntersect( const btDbvtAabbMm& a,
- const btDbvtAabbMm& b, const btTransform& xform, btScalar distanceThreshold)
+static DBVT_INLINE bool MyIntersect(const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b, const btTransform& xform, btScalar distanceThreshold)
{
- btVector3 newmin,newmax;
- btTransformAabb(b.Mins(),b.Maxs(),0.f,xform,newmin,newmax);
+ btVector3 newmin, newmax;
+ btTransformAabb(b.Mins(), b.Maxs(), 0.f, xform, newmin, newmax);
newmin -= btVector3(distanceThreshold, distanceThreshold, distanceThreshold);
newmax += btVector3(distanceThreshold, distanceThreshold, distanceThreshold);
- btDbvtAabbMm newb = btDbvtAabbMm::FromMM(newmin,newmax);
- return Intersect(a,newb);
+ btDbvtAabbMm newb = btDbvtAabbMm::FromMM(newmin, newmax);
+ return Intersect(a, newb);
}
-
-static inline void MycollideTT( const btDbvtNode* root0,
- const btDbvtNode* root1,
- const btTransform& xform,
- btCompoundCompoundLeafCallback* callback, btScalar distanceThreshold)
+static inline void MycollideTT(const btDbvtNode* root0,
+ const btDbvtNode* root1,
+ const btTransform& xform,
+ btCompoundCompoundLeafCallback* callback, btScalar distanceThreshold)
{
-
- if(root0&&root1)
- {
- int depth=1;
- int treshold=btDbvt::DOUBLE_STACKSIZE-4;
- btAlignedObjectArray<btDbvt::sStkNN> stkStack;
+ if (root0 && root1)
+ {
+ int depth = 1;
+ int treshold = btDbvt::DOUBLE_STACKSIZE - 4;
+ btAlignedObjectArray<btDbvt::sStkNN> stkStack;
#ifdef USE_LOCAL_STACK
- ATTRIBUTE_ALIGNED16(btDbvt::sStkNN localStack[btDbvt::DOUBLE_STACKSIZE]);
- stkStack.initializeFromBuffer(&localStack,btDbvt::DOUBLE_STACKSIZE,btDbvt::DOUBLE_STACKSIZE);
+ ATTRIBUTE_ALIGNED16(btDbvt::sStkNN localStack[btDbvt::DOUBLE_STACKSIZE]);
+ stkStack.initializeFromBuffer(&localStack, btDbvt::DOUBLE_STACKSIZE, btDbvt::DOUBLE_STACKSIZE);
#else
- stkStack.resize(btDbvt::DOUBLE_STACKSIZE);
+ stkStack.resize(btDbvt::DOUBLE_STACKSIZE);
#endif
- stkStack[0]=btDbvt::sStkNN(root0,root1);
- do {
- btDbvt::sStkNN p=stkStack[--depth];
- if(MyIntersect(p.a->volume,p.b->volume,xform, distanceThreshold))
+ stkStack[0] = btDbvt::sStkNN(root0, root1);
+ do
+ {
+ btDbvt::sStkNN p = stkStack[--depth];
+ if (MyIntersect(p.a->volume, p.b->volume, xform, distanceThreshold))
+ {
+ if (depth > treshold)
{
- if(depth>treshold)
+ stkStack.resize(stkStack.size() * 2);
+ treshold = stkStack.size() - 4;
+ }
+ if (p.a->isinternal())
+ {
+ if (p.b->isinternal())
{
- stkStack.resize(stkStack.size()*2);
- treshold=stkStack.size()-4;
+ stkStack[depth++] = btDbvt::sStkNN(p.a->childs[0], p.b->childs[0]);
+ stkStack[depth++] = btDbvt::sStkNN(p.a->childs[1], p.b->childs[0]);
+ stkStack[depth++] = btDbvt::sStkNN(p.a->childs[0], p.b->childs[1]);
+ stkStack[depth++] = btDbvt::sStkNN(p.a->childs[1], p.b->childs[1]);
}
- if(p.a->isinternal())
+ else
{
- if(p.b->isinternal())
- {
- stkStack[depth++]=btDbvt::sStkNN(p.a->childs[0],p.b->childs[0]);
- stkStack[depth++]=btDbvt::sStkNN(p.a->childs[1],p.b->childs[0]);
- stkStack[depth++]=btDbvt::sStkNN(p.a->childs[0],p.b->childs[1]);
- stkStack[depth++]=btDbvt::sStkNN(p.a->childs[1],p.b->childs[1]);
- }
- else
- {
- stkStack[depth++]=btDbvt::sStkNN(p.a->childs[0],p.b);
- stkStack[depth++]=btDbvt::sStkNN(p.a->childs[1],p.b);
- }
+ stkStack[depth++] = btDbvt::sStkNN(p.a->childs[0], p.b);
+ stkStack[depth++] = btDbvt::sStkNN(p.a->childs[1], p.b);
+ }
+ }
+ else
+ {
+ if (p.b->isinternal())
+ {
+ stkStack[depth++] = btDbvt::sStkNN(p.a, p.b->childs[0]);
+ stkStack[depth++] = btDbvt::sStkNN(p.a, p.b->childs[1]);
}
else
{
- if(p.b->isinternal())
- {
- stkStack[depth++]=btDbvt::sStkNN(p.a,p.b->childs[0]);
- stkStack[depth++]=btDbvt::sStkNN(p.a,p.b->childs[1]);
- }
- else
- {
- callback->Process(p.a,p.b);
- }
+ callback->Process(p.a, p.b);
}
}
- } while(depth);
- }
+ }
+ } while (depth);
+ }
}
-void btCompoundCompoundCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+void btCompoundCompoundCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
{
-
const btCollisionObjectWrapper* col0ObjWrap = body0Wrap;
- const btCollisionObjectWrapper* col1ObjWrap= body1Wrap;
+ const btCollisionObjectWrapper* col1ObjWrap = body1Wrap;
- btAssert (col0ObjWrap->getCollisionShape()->isCompound());
- btAssert (col1ObjWrap->getCollisionShape()->isCompound());
+ btAssert(col0ObjWrap->getCollisionShape()->isCompound());
+ btAssert(col1ObjWrap->getCollisionShape()->isCompound());
const btCompoundShape* compoundShape0 = static_cast<const btCompoundShape*>(col0ObjWrap->getCollisionShape());
const btCompoundShape* compoundShape1 = static_cast<const btCompoundShape*>(col1ObjWrap->getCollisionShape());
@@ -321,7 +296,7 @@ void btCompoundCompoundCollisionAlgorithm::processCollision (const btCollisionOb
const btDbvt* tree1 = compoundShape1->getDynamicAabbTree();
if (!tree0 || !tree1)
{
- return btCompoundCollisionAlgorithm::processCollision(body0Wrap,body1Wrap,dispatchInfo,resultOut);
+ return btCompoundCollisionAlgorithm::processCollision(body0Wrap, body1Wrap, dispatchInfo, resultOut);
}
///btCompoundShape might have changed:
////make sure the internal child collision algorithm caches are still valid
@@ -331,28 +306,26 @@ void btCompoundCompoundCollisionAlgorithm::processCollision (const btCollisionOb
removeChildAlgorithms();
m_compoundShapeRevision0 = compoundShape0->getUpdateRevision();
m_compoundShapeRevision1 = compoundShape1->getUpdateRevision();
-
}
-
///we need to refresh all contact manifolds
///note that we should actually recursively traverse all children, btCompoundShape can nested more then 1 level deep
///so we should add a 'refreshManifolds' in the btCollisionAlgorithm
{
int i;
btManifoldArray manifoldArray;
-#ifdef USE_LOCAL_STACK
+#ifdef USE_LOCAL_STACK
btPersistentManifold localManifolds[4];
- manifoldArray.initializeFromBuffer(&localManifolds,0,4);
+ manifoldArray.initializeFromBuffer(&localManifolds, 0, 4);
#endif
btSimplePairArray& pairs = m_childCollisionAlgorithmCache->getOverlappingPairArray();
- for (i=0;i<pairs.size();i++)
+ for (i = 0; i < pairs.size(); i++)
{
if (pairs[i].m_userPointer)
{
- btCollisionAlgorithm* algo = (btCollisionAlgorithm*) pairs[i].m_userPointer;
+ btCollisionAlgorithm* algo = (btCollisionAlgorithm*)pairs[i].m_userPointer;
algo->getAllContactManifolds(manifoldArray);
- for (int m=0;m<manifoldArray.size();m++)
+ for (int m = 0; m < manifoldArray.size(); m++)
{
if (manifoldArray[m]->getNumContacts())
{
@@ -366,35 +339,27 @@ void btCompoundCompoundCollisionAlgorithm::processCollision (const btCollisionOb
}
}
+ btCompoundCompoundLeafCallback callback(col0ObjWrap, col1ObjWrap, this->m_dispatcher, dispatchInfo, resultOut, this->m_childCollisionAlgorithmCache, m_sharedManifold);
-
-
- btCompoundCompoundLeafCallback callback(col0ObjWrap,col1ObjWrap,this->m_dispatcher,dispatchInfo,resultOut,this->m_childCollisionAlgorithmCache,m_sharedManifold);
-
-
- const btTransform xform=col0ObjWrap->getWorldTransform().inverse()*col1ObjWrap->getWorldTransform();
- MycollideTT(tree0->m_root,tree1->m_root,xform,&callback, resultOut->m_closestPointDistanceThreshold);
+ const btTransform xform = col0ObjWrap->getWorldTransform().inverse() * col1ObjWrap->getWorldTransform();
+ MycollideTT(tree0->m_root, tree1->m_root, xform, &callback, resultOut->m_closestPointDistanceThreshold);
//printf("#compound-compound child/leaf overlap =%d \r",callback.m_numOverlapPairs);
//remove non-overlapping child pairs
{
- btAssert(m_removePairs.size()==0);
+ btAssert(m_removePairs.size() == 0);
//iterate over all children, perform an AABB check inside ProcessChildShape
btSimplePairArray& pairs = m_childCollisionAlgorithmCache->getOverlappingPairArray();
-
+
int i;
- btManifoldArray manifoldArray;
-
-
-
-
-
- btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1;
-
- for (i=0;i<pairs.size();i++)
+ btManifoldArray manifoldArray;
+
+ btVector3 aabbMin0, aabbMax0, aabbMin1, aabbMax1;
+
+ for (i = 0; i < pairs.size(); i++)
{
if (pairs[i].m_userPointer)
{
@@ -402,52 +367,47 @@ void btCompoundCompoundCollisionAlgorithm::processCollision (const btCollisionOb
{
const btCollisionShape* childShape0 = 0;
-
- btTransform newChildWorldTrans0;
+
+ btTransform newChildWorldTrans0;
childShape0 = compoundShape0->getChildShape(pairs[i].m_indexA);
const btTransform& childTrans0 = compoundShape0->getChildTransform(pairs[i].m_indexA);
- newChildWorldTrans0 = col0ObjWrap->getWorldTransform()*childTrans0 ;
- childShape0->getAabb(newChildWorldTrans0,aabbMin0,aabbMax0);
+ newChildWorldTrans0 = col0ObjWrap->getWorldTransform() * childTrans0;
+ childShape0->getAabb(newChildWorldTrans0, aabbMin0, aabbMax0);
}
btVector3 thresholdVec(resultOut->m_closestPointDistanceThreshold, resultOut->m_closestPointDistanceThreshold, resultOut->m_closestPointDistanceThreshold);
aabbMin0 -= thresholdVec;
aabbMax0 += thresholdVec;
{
const btCollisionShape* childShape1 = 0;
- btTransform newChildWorldTrans1;
+ btTransform newChildWorldTrans1;
childShape1 = compoundShape1->getChildShape(pairs[i].m_indexB);
const btTransform& childTrans1 = compoundShape1->getChildTransform(pairs[i].m_indexB);
- newChildWorldTrans1 = col1ObjWrap->getWorldTransform()*childTrans1 ;
- childShape1->getAabb(newChildWorldTrans1,aabbMin1,aabbMax1);
+ newChildWorldTrans1 = col1ObjWrap->getWorldTransform() * childTrans1;
+ childShape1->getAabb(newChildWorldTrans1, aabbMin1, aabbMax1);
}
-
+
aabbMin1 -= thresholdVec;
aabbMax1 += thresholdVec;
- if (!TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
+ if (!TestAabbAgainstAabb2(aabbMin0, aabbMax0, aabbMin1, aabbMax1))
{
algo->~btCollisionAlgorithm();
m_dispatcher->freeCollisionAlgorithm(algo);
- m_removePairs.push_back(btSimplePair(pairs[i].m_indexA,pairs[i].m_indexB));
+ m_removePairs.push_back(btSimplePair(pairs[i].m_indexA, pairs[i].m_indexB));
}
}
}
- for (int i=0;i<m_removePairs.size();i++)
+ for (int i = 0; i < m_removePairs.size(); i++)
{
- m_childCollisionAlgorithmCache->removeOverlappingPair(m_removePairs[i].m_indexA,m_removePairs[i].m_indexB);
+ m_childCollisionAlgorithmCache->removeOverlappingPair(m_removePairs[i].m_indexA, m_removePairs[i].m_indexB);
}
m_removePairs.clear();
}
-
}
-btScalar btCompoundCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+btScalar btCompoundCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
{
btAssert(0);
return 0.f;
-
}
-
-
-
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h
index f29f7a709a..a940d840e0 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h
@@ -34,54 +34,49 @@ class btCollisionObject;
class btCollisionShape;
+extern btShapePairCallback gCompoundCompoundChildShapePairCallback;
+
/// btCompoundCompoundCollisionAlgorithm supports collision between two btCompoundCollisionShape shapes
-class btCompoundCompoundCollisionAlgorithm : public btCompoundCollisionAlgorithm
+class btCompoundCompoundCollisionAlgorithm : public btCompoundCollisionAlgorithm
{
-
- class btHashedSimplePairCache* m_childCollisionAlgorithmCache;
+ class btHashedSimplePairCache* m_childCollisionAlgorithmCache;
btSimplePairArray m_removePairs;
+ int m_compoundShapeRevision0; //to keep track of changes, so that childAlgorithm array can be updated
+ int m_compoundShapeRevision1;
- int m_compoundShapeRevision0;//to keep track of changes, so that childAlgorithm array can be updated
- int m_compoundShapeRevision1;
-
- void removeChildAlgorithms();
-
-// void preallocateChildAlgorithms(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
+ void removeChildAlgorithms();
-public:
+ // void preallocateChildAlgorithms(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
- btCompoundCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped);
+public:
+ btCompoundCompoundCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped);
virtual ~btCompoundCompoundCollisionAlgorithm();
-
+ virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
- virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
- btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray);
- virtual void getAllContactManifolds(btManifoldArray& manifoldArray);
-
-
- struct CreateFunc :public btCollisionAlgorithmCreateFunc
+ struct CreateFunc : public btCollisionAlgorithmCreateFunc
{
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCompoundCollisionAlgorithm));
- return new(mem) btCompoundCompoundCollisionAlgorithm(ci,body0Wrap,body1Wrap,false);
+ return new (mem) btCompoundCompoundCollisionAlgorithm(ci, body0Wrap, body1Wrap, false);
}
};
- struct SwappedCreateFunc :public btCollisionAlgorithmCreateFunc
+ struct SwappedCreateFunc : public btCollisionAlgorithmCreateFunc
{
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCompoundCollisionAlgorithm));
- return new(mem) btCompoundCompoundCollisionAlgorithm(ci,body0Wrap,body1Wrap,true);
+ return new (mem) btCompoundCompoundCollisionAlgorithm(ci, body0Wrap, body1Wrap, true);
}
};
-
};
-#endif //BT_COMPOUND_COMPOUND_COLLISION_ALGORITHM_H
+#endif //BT_COMPOUND_COMPOUND_COLLISION_ALGORITHM_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp
index 1cb3d2e7a1..9087f84398 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp
@@ -22,7 +22,6 @@ subject to the following restrictions:
#include "BulletCollision/CollisionShapes/btConvexShape.h"
#include "BulletCollision/CollisionShapes/btCapsuleShape.h"
-
#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
@@ -34,8 +33,6 @@ subject to the following restrictions:
#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h"
-
-
#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h"
@@ -45,31 +42,28 @@ subject to the following restrictions:
#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
-btConvex2dConvex2dAlgorithm::CreateFunc::CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver)
+btConvex2dConvex2dAlgorithm::CreateFunc::CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver)
{
m_simplexSolver = simplexSolver;
m_pdSolver = pdSolver;
}
-btConvex2dConvex2dAlgorithm::CreateFunc::~CreateFunc()
-{
+btConvex2dConvex2dAlgorithm::CreateFunc::~CreateFunc()
+{
}
-btConvex2dConvex2dAlgorithm::btConvex2dConvex2dAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver,int /* numPerturbationIterations */, int /* minimumPointsPerturbationThreshold */)
-: btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap),
-m_simplexSolver(simplexSolver),
-m_pdSolver(pdSolver),
-m_ownManifold (false),
-m_manifoldPtr(mf),
-m_lowLevelOfDetail(false)
+btConvex2dConvex2dAlgorithm::btConvex2dConvex2dAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver, int /* numPerturbationIterations */, int /* minimumPointsPerturbationThreshold */)
+ : btActivatingCollisionAlgorithm(ci, body0Wrap, body1Wrap),
+ m_simplexSolver(simplexSolver),
+ m_pdSolver(pdSolver),
+ m_ownManifold(false),
+ m_manifoldPtr(mf),
+ m_lowLevelOfDetail(false)
{
(void)body0Wrap;
(void)body1Wrap;
}
-
-
-
btConvex2dConvex2dAlgorithm::~btConvex2dConvex2dAlgorithm()
{
if (m_ownManifold)
@@ -79,26 +73,22 @@ btConvex2dConvex2dAlgorithm::~btConvex2dConvex2dAlgorithm()
}
}
-void btConvex2dConvex2dAlgorithm ::setLowLevelOfDetail(bool useLowLevel)
+void btConvex2dConvex2dAlgorithm ::setLowLevelOfDetail(bool useLowLevel)
{
m_lowLevelOfDetail = useLowLevel;
}
-
-
extern btScalar gContactBreakingThreshold;
-
//
// Convex-Convex collision algorithm
//
-void btConvex2dConvex2dAlgorithm ::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+void btConvex2dConvex2dAlgorithm ::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
{
-
if (!m_manifoldPtr)
{
//swapped?
- m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(),body1Wrap->getCollisionObject());
+ m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(), body1Wrap->getCollisionObject());
m_ownManifold = true;
}
resultOut->setPersistentManifold(m_manifoldPtr);
@@ -106,49 +96,41 @@ void btConvex2dConvex2dAlgorithm ::processCollision (const btCollisionObjectWrap
//comment-out next line to test multi-contact generation
//resultOut->getPersistentManifold()->clearManifold();
-
const btConvexShape* min0 = static_cast<const btConvexShape*>(body0Wrap->getCollisionShape());
const btConvexShape* min1 = static_cast<const btConvexShape*>(body1Wrap->getCollisionShape());
- btVector3 normalOnB;
- btVector3 pointOnBWorld;
+ btVector3 normalOnB;
+ btVector3 pointOnBWorld;
{
-
-
btGjkPairDetector::ClosestPointInput input;
- btGjkPairDetector gjkPairDetector(min0,min1,m_simplexSolver,m_pdSolver);
+ btGjkPairDetector gjkPairDetector(min0, min1, m_simplexSolver, m_pdSolver);
//TODO: if (dispatchInfo.m_useContinuous)
gjkPairDetector.setMinkowskiA(min0);
gjkPairDetector.setMinkowskiB(min1);
{
input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactBreakingThreshold();
- input.m_maximumDistanceSquared*= input.m_maximumDistanceSquared;
+ input.m_maximumDistanceSquared *= input.m_maximumDistanceSquared;
}
input.m_transformA = body0Wrap->getWorldTransform();
input.m_transformB = body1Wrap->getWorldTransform();
- gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
+ gjkPairDetector.getClosestPoints(input, *resultOut, dispatchInfo.m_debugDraw);
- btVector3 v0,v1;
+ btVector3 v0, v1;
btVector3 sepNormalWorldSpace;
-
}
if (m_ownManifold)
{
resultOut->refreshContactPoints();
}
-
}
-
-
-
-btScalar btConvex2dConvex2dAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+btScalar btConvex2dConvex2dAlgorithm::calculateTimeOfImpact(btCollisionObject* col0, btCollisionObject* col1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
{
(void)resultOut;
(void)dispatchInfo;
@@ -158,7 +140,6 @@ btScalar btConvex2dConvex2dAlgorithm::calculateTimeOfImpact(btCollisionObject* c
///col0->m_worldTransform,
btScalar resultFraction = btScalar(1.);
-
btScalar squareMot0 = (col0->getInterpolationWorldTransform().getOrigin() - col0->getWorldTransform().getOrigin()).length2();
btScalar squareMot1 = (col1->getInterpolationWorldTransform().getOrigin() - col1->getWorldTransform().getOrigin()).length2();
@@ -166,77 +147,65 @@ btScalar btConvex2dConvex2dAlgorithm::calculateTimeOfImpact(btCollisionObject* c
squareMot1 < col1->getCcdSquareMotionThreshold())
return resultFraction;
-
//An adhoc way of testing the Continuous Collision Detection algorithms
//One object is approximated as a sphere, to simplify things
//Starting in penetration should report no time of impact
//For proper CCD, better accuracy and handling of 'allowed' penetration should be added
//also the mainloop of the physics should have a kind of toi queue (something like Brian Mirtich's application of Timewarp for Rigidbodies)
-
/// Convex0 against sphere for Convex1
{
btConvexShape* convex0 = static_cast<btConvexShape*>(col0->getCollisionShape());
- btSphereShape sphere1(col1->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation
+ btSphereShape sphere1(col1->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation
btConvexCast::CastResult result;
btVoronoiSimplexSolver voronoiSimplex;
//SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex);
///Simplification, one object is simplified as a sphere
- btGjkConvexCast ccd1( convex0 ,&sphere1,&voronoiSimplex);
+ btGjkConvexCast ccd1(convex0, &sphere1, &voronoiSimplex);
//ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0);
- if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(),
- col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result))
+ if (ccd1.calcTimeOfImpact(col0->getWorldTransform(), col0->getInterpolationWorldTransform(),
+ col1->getWorldTransform(), col1->getInterpolationWorldTransform(), result))
{
-
//store result.m_fraction in both bodies
- if (col0->getHitFraction()> result.m_fraction)
- col0->setHitFraction( result.m_fraction );
+ if (col0->getHitFraction() > result.m_fraction)
+ col0->setHitFraction(result.m_fraction);
if (col1->getHitFraction() > result.m_fraction)
- col1->setHitFraction( result.m_fraction);
+ col1->setHitFraction(result.m_fraction);
if (resultFraction > result.m_fraction)
resultFraction = result.m_fraction;
-
}
-
-
-
-
}
/// Sphere (for convex0) against Convex1
{
btConvexShape* convex1 = static_cast<btConvexShape*>(col1->getCollisionShape());
- btSphereShape sphere0(col0->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation
+ btSphereShape sphere0(col0->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation
btConvexCast::CastResult result;
btVoronoiSimplexSolver voronoiSimplex;
//SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex);
///Simplification, one object is simplified as a sphere
- btGjkConvexCast ccd1(&sphere0,convex1,&voronoiSimplex);
+ btGjkConvexCast ccd1(&sphere0, convex1, &voronoiSimplex);
//ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0);
- if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(),
- col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result))
+ if (ccd1.calcTimeOfImpact(col0->getWorldTransform(), col0->getInterpolationWorldTransform(),
+ col1->getWorldTransform(), col1->getInterpolationWorldTransform(), result))
{
-
//store result.m_fraction in both bodies
- if (col0->getHitFraction() > result.m_fraction)
- col0->setHitFraction( result.m_fraction);
+ if (col0->getHitFraction() > result.m_fraction)
+ col0->setHitFraction(result.m_fraction);
if (col1->getHitFraction() > result.m_fraction)
- col1->setHitFraction( result.m_fraction);
+ col1->setHitFraction(result.m_fraction);
if (resultFraction > result.m_fraction)
resultFraction = result.m_fraction;
-
}
}
return resultFraction;
-
}
-
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h
index 24d1336778..9fca463fbe 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h
@@ -23,70 +23,61 @@ subject to the following restrictions:
#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
-#include "LinearMath/btTransformUtil.h" //for btConvexSeparatingDistanceUtil
+#include "LinearMath/btTransformUtil.h" //for btConvexSeparatingDistanceUtil
class btConvexPenetrationDepthSolver;
-
///The convex2dConvex2dAlgorithm collision algorithm support 2d collision detection for btConvex2dShape
///Currently it requires the btMinkowskiPenetrationDepthSolver, it has support for 2d penetration depth computation
class btConvex2dConvex2dAlgorithm : public btActivatingCollisionAlgorithm
{
- btSimplexSolverInterface* m_simplexSolver;
+ btSimplexSolverInterface* m_simplexSolver;
btConvexPenetrationDepthSolver* m_pdSolver;
-
- bool m_ownManifold;
- btPersistentManifold* m_manifoldPtr;
- bool m_lowLevelOfDetail;
-
-public:
-
- btConvex2dConvex2dAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold);
+ bool m_ownManifold;
+ btPersistentManifold* m_manifoldPtr;
+ bool m_lowLevelOfDetail;
+public:
+ btConvex2dConvex2dAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold);
virtual ~btConvex2dConvex2dAlgorithm();
- virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
- virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
- virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
///should we use m_ownManifold to avoid adding duplicates?
if (m_manifoldPtr && m_ownManifold)
manifoldArray.push_back(m_manifoldPtr);
}
+ void setLowLevelOfDetail(bool useLowLevel);
- void setLowLevelOfDetail(bool useLowLevel);
-
-
- const btPersistentManifold* getManifold()
+ const btPersistentManifold* getManifold()
{
return m_manifoldPtr;
}
- struct CreateFunc :public btCollisionAlgorithmCreateFunc
+ struct CreateFunc : public btCollisionAlgorithmCreateFunc
{
-
- btConvexPenetrationDepthSolver* m_pdSolver;
- btSimplexSolverInterface* m_simplexSolver;
+ btConvexPenetrationDepthSolver* m_pdSolver;
+ btSimplexSolverInterface* m_simplexSolver;
int m_numPerturbationIterations;
int m_minimumPointsPerturbationThreshold;
- CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver);
-
+ CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver);
+
virtual ~CreateFunc();
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvex2dConvex2dAlgorithm));
- return new(mem) btConvex2dConvex2dAlgorithm(ci.m_manifold,ci,body0Wrap,body1Wrap,m_simplexSolver,m_pdSolver,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold);
+ return new (mem) btConvex2dConvex2dAlgorithm(ci.m_manifold, ci, body0Wrap, body1Wrap, m_simplexSolver, m_pdSolver, m_numPerturbationIterations, m_minimumPointsPerturbationThreshold);
}
};
-
-
};
-#endif //BT_CONVEX_2D_CONVEX_2D_ALGORITHM_H
+#endif //BT_CONVEX_2D_CONVEX_2D_ALGORITHM_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp
index d8cbe96142..e50f85e2bb 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp
@@ -13,7 +13,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#include "btConvexConcaveCollisionAlgorithm.h"
#include "LinearMath/btQuickprof.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
@@ -29,10 +28,10 @@ subject to the following restrictions:
#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
#include "BulletCollision/CollisionShapes/btSdfCollisionShape.h"
-btConvexConcaveCollisionAlgorithm::btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped)
-: btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap),
-m_btConvexTriangleCallback(ci.m_dispatcher1,body0Wrap,body1Wrap,isSwapped),
-m_isSwapped(isSwapped)
+btConvexConcaveCollisionAlgorithm::btConvexConcaveCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped)
+ : btActivatingCollisionAlgorithm(ci, body0Wrap, body1Wrap),
+ m_btConvexTriangleCallback(ci.m_dispatcher1, body0Wrap, body1Wrap, isSwapped),
+ m_isSwapped(isSwapped)
{
}
@@ -40,7 +39,7 @@ btConvexConcaveCollisionAlgorithm::~btConvexConcaveCollisionAlgorithm()
{
}
-void btConvexConcaveCollisionAlgorithm::getAllContactManifolds(btManifoldArray& manifoldArray)
+void btConvexConcaveCollisionAlgorithm::getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_btConvexTriangleCallback.m_manifoldPtr)
{
@@ -48,38 +47,32 @@ void btConvexConcaveCollisionAlgorithm::getAllContactManifolds(btManifoldArray&
}
}
-
-btConvexTriangleCallback::btConvexTriangleCallback(btDispatcher* dispatcher,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped):
- m_dispatcher(dispatcher),
- m_dispatchInfoPtr(0)
+btConvexTriangleCallback::btConvexTriangleCallback(btDispatcher* dispatcher, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped) : m_dispatcher(dispatcher),
+ m_dispatchInfoPtr(0)
{
- m_convexBodyWrap = isSwapped? body1Wrap:body0Wrap;
- m_triBodyWrap = isSwapped? body0Wrap:body1Wrap;
-
- //
- // create the manifold from the dispatcher 'manifold pool'
- //
- m_manifoldPtr = m_dispatcher->getNewManifold(m_convexBodyWrap->getCollisionObject(),m_triBodyWrap->getCollisionObject());
+ m_convexBodyWrap = isSwapped ? body1Wrap : body0Wrap;
+ m_triBodyWrap = isSwapped ? body0Wrap : body1Wrap;
+
+ //
+ // create the manifold from the dispatcher 'manifold pool'
+ //
+ m_manifoldPtr = m_dispatcher->getNewManifold(m_convexBodyWrap->getCollisionObject(), m_triBodyWrap->getCollisionObject());
- clearCache();
+ clearCache();
}
btConvexTriangleCallback::~btConvexTriangleCallback()
{
clearCache();
- m_dispatcher->releaseManifold( m_manifoldPtr );
-
+ m_dispatcher->releaseManifold(m_manifoldPtr);
}
-
-void btConvexTriangleCallback::clearCache()
+void btConvexTriangleCallback::clearCache()
{
m_dispatcher->clearManifold(m_manifoldPtr);
}
-
-void btConvexTriangleCallback::processTriangle(btVector3* triangle,int
-partId, int triangleIndex)
+void btConvexTriangleCallback::processTriangle(btVector3* triangle, int partId, int triangleIndex)
{
BT_PROFILE("btConvexTriangleCallback::processTriangle");
@@ -88,16 +81,12 @@ partId, int triangleIndex)
return;
}
- //just for debugging purposes
- //printf("triangle %d",m_triangleCount++);
-
-
+ //just for debugging purposes
+ //printf("triangle %d",m_triangleCount++);
btCollisionAlgorithmConstructionInfo ci;
ci.m_dispatcher1 = m_dispatcher;
-
-
#if 0
///debug drawing of the overlapping triangles
@@ -111,16 +100,15 @@ partId, int triangleIndex)
m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(triangle[0]),color);
}
#endif
-
+
if (m_convexBodyWrap->getCollisionShape()->isConvex())
{
- btTriangleShape tm(triangle[0],triangle[1],triangle[2]);
+ btTriangleShape tm(triangle[0], triangle[1], triangle[2]);
tm.setMargin(m_collisionMarginTriangle);
-
-
- btCollisionObjectWrapper triObWrap(m_triBodyWrap,&tm,m_triBodyWrap->getCollisionObject(),m_triBodyWrap->getWorldTransform(),partId,triangleIndex);//correct transform?
+
+ btCollisionObjectWrapper triObWrap(m_triBodyWrap, &tm, m_triBodyWrap->getCollisionObject(), m_triBodyWrap->getWorldTransform(), partId, triangleIndex); //correct transform?
btCollisionAlgorithm* colAlgo = 0;
-
+
if (m_resultOut->m_closestPointDistanceThreshold > 0)
{
colAlgo = ci.m_dispatcher1->findAlgorithm(m_convexBodyWrap, &triObWrap, 0, BT_CLOSEST_POINT_ALGORITHMS);
@@ -135,36 +123,32 @@ partId, int triangleIndex)
{
tmpWrap = m_resultOut->getBody0Wrap();
m_resultOut->setBody0Wrap(&triObWrap);
- m_resultOut->setShapeIdentifiersA(partId,triangleIndex);
+ m_resultOut->setShapeIdentifiersA(partId, triangleIndex);
}
else
{
tmpWrap = m_resultOut->getBody1Wrap();
m_resultOut->setBody1Wrap(&triObWrap);
- m_resultOut->setShapeIdentifiersB(partId,triangleIndex);
+ m_resultOut->setShapeIdentifiersB(partId, triangleIndex);
}
-
- colAlgo->processCollision(m_convexBodyWrap,&triObWrap,*m_dispatchInfoPtr,m_resultOut);
+
+ colAlgo->processCollision(m_convexBodyWrap, &triObWrap, *m_dispatchInfoPtr, m_resultOut);
if (m_resultOut->getBody0Internal() == m_triBodyWrap->getCollisionObject())
{
m_resultOut->setBody0Wrap(tmpWrap);
- } else
+ }
+ else
{
m_resultOut->setBody1Wrap(tmpWrap);
}
-
-
colAlgo->~btCollisionAlgorithm();
ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo);
}
-
}
-
-
-void btConvexTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle, const btDispatcherInfo& dispatchInfo, const btCollisionObjectWrapper* convexBodyWrap, const btCollisionObjectWrapper* triBodyWrap, btManifoldResult* resultOut)
+void btConvexTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle, const btDispatcherInfo& dispatchInfo, const btCollisionObjectWrapper* convexBodyWrap, const btCollisionObjectWrapper* triBodyWrap, btManifoldResult* resultOut)
{
m_convexBodyWrap = convexBodyWrap;
m_triBodyWrap = triBodyWrap;
@@ -185,16 +169,14 @@ void btConvexTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTr
m_aabbMax += extra;
m_aabbMin -= extra;
-
}
void btConvexConcaveCollisionAlgorithm::clearCache()
{
m_btConvexTriangleCallback.clearCache();
-
}
-void btConvexConcaveCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
+void btConvexConcaveCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
{
BT_PROFILE("btConvexConcaveCollisionAlgorithm::processCollision");
@@ -208,7 +190,6 @@ void btConvexConcaveCollisionAlgorithm::processCollision (const btCollisionObjec
btSdfCollisionShape* sdfShape = (btSdfCollisionShape*)triBodyWrap->getCollisionShape();
if (convexBodyWrap->getCollisionShape()->isConvex())
{
-
btConvexShape* convex = (btConvexShape*)convexBodyWrap->getCollisionShape();
btAlignedObjectArray<btVector3> queryVertices;
@@ -229,7 +210,6 @@ void btConvexConcaveCollisionAlgorithm::processCollision (const btCollisionObjec
queryVertices.push_back(btVector3(0, 0, 0));
btSphereShape* sphere = (btSphereShape*)convex;
maxDist = sphere->getRadius() + SIMD_EPSILON;
-
}
if (queryVertices.size())
{
@@ -240,7 +220,7 @@ void btConvexConcaveCollisionAlgorithm::processCollision (const btCollisionObjec
for (int v = 0; v < queryVertices.size(); v++)
{
const btVector3& vtx = queryVertices[v];
- btVector3 vtxWorldSpace = convexBodyWrap->getWorldTransform()*vtx;
+ btVector3 vtxWorldSpace = convexBodyWrap->getWorldTransform() * vtx;
btVector3 vtxInSdf = triBodyWrap->getWorldTransform().invXform(vtxWorldSpace);
btVector3 normalLocal;
@@ -250,58 +230,52 @@ void btConvexConcaveCollisionAlgorithm::processCollision (const btCollisionObjec
if (dist <= maxDist)
{
normalLocal.safeNormalize();
- btVector3 normal = triBodyWrap->getWorldTransform().getBasis()*normalLocal;
+ btVector3 normal = triBodyWrap->getWorldTransform().getBasis() * normalLocal;
if (convex->getShapeType() == SPHERE_SHAPE_PROXYTYPE)
{
btSphereShape* sphere = (btSphereShape*)convex;
dist -= sphere->getRadius();
- vtxWorldSpace -= sphere->getRadius()*normal;
-
+ vtxWorldSpace -= sphere->getRadius() * normal;
}
- resultOut->addContactPoint(normal,vtxWorldSpace-normal*dist, dist);
+ resultOut->addContactPoint(normal, vtxWorldSpace - normal * dist, dist);
}
}
}
resultOut->refreshContactPoints();
}
-
}
- } else
+ }
+ else
{
- const btConcaveShape* concaveShape = static_cast<const btConcaveShape*>( triBodyWrap->getCollisionShape());
-
+ const btConcaveShape* concaveShape = static_cast<const btConcaveShape*>(triBodyWrap->getCollisionShape());
+
if (convexBodyWrap->getCollisionShape()->isConvex())
{
btScalar collisionMarginTriangle = concaveShape->getMargin();
-
+
resultOut->setPersistentManifold(m_btConvexTriangleCallback.m_manifoldPtr);
- m_btConvexTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle,dispatchInfo,convexBodyWrap,triBodyWrap,resultOut);
+ m_btConvexTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle, dispatchInfo, convexBodyWrap, triBodyWrap, resultOut);
- m_btConvexTriangleCallback.m_manifoldPtr->setBodies(convexBodyWrap->getCollisionObject(),triBodyWrap->getCollisionObject());
+ m_btConvexTriangleCallback.m_manifoldPtr->setBodies(convexBodyWrap->getCollisionObject(), triBodyWrap->getCollisionObject());
+
+ concaveShape->processAllTriangles(&m_btConvexTriangleCallback, m_btConvexTriangleCallback.getAabbMin(), m_btConvexTriangleCallback.getAabbMax());
- concaveShape->processAllTriangles( &m_btConvexTriangleCallback,m_btConvexTriangleCallback.getAabbMin(),m_btConvexTriangleCallback.getAabbMax());
-
resultOut->refreshContactPoints();
m_btConvexTriangleCallback.clearWrapperData();
-
}
}
-
}
-
}
-
-btScalar btConvexConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+btScalar btConvexConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
{
(void)resultOut;
(void)dispatchInfo;
btCollisionObject* convexbody = m_isSwapped ? body1 : body0;
btCollisionObject* triBody = m_isSwapped ? body0 : body1;
-
//quick approximation using raycast, todo: hook up to the continuous collision detection (one of the btConvexCast)
//only perform CCD above a certain threshold, this prevents blocking on the long run
@@ -320,25 +294,23 @@ btScalar btConvexConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObj
btTransform convexFromLocal = triInv * convexbody->getWorldTransform();
btTransform convexToLocal = triInv * convexbody->getInterpolationWorldTransform();
- struct LocalTriangleSphereCastCallback : public btTriangleCallback
+ struct LocalTriangleSphereCastCallback : public btTriangleCallback
{
btTransform m_ccdSphereFromTrans;
btTransform m_ccdSphereToTrans;
- btTransform m_meshTransform;
+ btTransform m_meshTransform;
- btScalar m_ccdSphereRadius;
- btScalar m_hitFraction;
-
+ btScalar m_ccdSphereRadius;
+ btScalar m_hitFraction;
- LocalTriangleSphereCastCallback(const btTransform& from,const btTransform& to,btScalar ccdSphereRadius,btScalar hitFraction)
- :m_ccdSphereFromTrans(from),
- m_ccdSphereToTrans(to),
- m_ccdSphereRadius(ccdSphereRadius),
- m_hitFraction(hitFraction)
- {
+ LocalTriangleSphereCastCallback(const btTransform& from, const btTransform& to, btScalar ccdSphereRadius, btScalar hitFraction)
+ : m_ccdSphereFromTrans(from),
+ m_ccdSphereToTrans(to),
+ m_ccdSphereRadius(ccdSphereRadius),
+ m_hitFraction(hitFraction)
+ {
}
-
-
+
virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
{
BT_PROFILE("processTriangle");
@@ -349,29 +321,23 @@ btScalar btConvexConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObj
ident.setIdentity();
btConvexCast::CastResult castResult;
castResult.m_fraction = m_hitFraction;
- btSphereShape pointShape(m_ccdSphereRadius);
- btTriangleShape triShape(triangle[0],triangle[1],triangle[2]);
- btVoronoiSimplexSolver simplexSolver;
- btSubsimplexConvexCast convexCaster(&pointShape,&triShape,&simplexSolver);
+ btSphereShape pointShape(m_ccdSphereRadius);
+ btTriangleShape triShape(triangle[0], triangle[1], triangle[2]);
+ btVoronoiSimplexSolver simplexSolver;
+ btSubsimplexConvexCast convexCaster(&pointShape, &triShape, &simplexSolver);
//GjkConvexCast convexCaster(&pointShape,convexShape,&simplexSolver);
//ContinuousConvexCollision convexCaster(&pointShape,convexShape,&simplexSolver,0);
//local space?
- if (convexCaster.calcTimeOfImpact(m_ccdSphereFromTrans,m_ccdSphereToTrans,
- ident,ident,castResult))
+ if (convexCaster.calcTimeOfImpact(m_ccdSphereFromTrans, m_ccdSphereToTrans,
+ ident, ident, castResult))
{
if (m_hitFraction > castResult.m_fraction)
m_hitFraction = castResult.m_fraction;
}
-
}
-
};
-
-
-
-
if (triBody->getCollisionShape()->isConcave())
{
btVector3 rayAabbMin = convexFromLocal.getOrigin();
@@ -379,33 +345,30 @@ btScalar btConvexConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObj
btVector3 rayAabbMax = convexFromLocal.getOrigin();
rayAabbMax.setMax(convexToLocal.getOrigin());
btScalar ccdRadius0 = convexbody->getCcdSweptSphereRadius();
- rayAabbMin -= btVector3(ccdRadius0,ccdRadius0,ccdRadius0);
- rayAabbMax += btVector3(ccdRadius0,ccdRadius0,ccdRadius0);
+ rayAabbMin -= btVector3(ccdRadius0, ccdRadius0, ccdRadius0);
+ rayAabbMax += btVector3(ccdRadius0, ccdRadius0, ccdRadius0);
- btScalar curHitFraction = btScalar(1.); //is this available?
- LocalTriangleSphereCastCallback raycastCallback(convexFromLocal,convexToLocal,
- convexbody->getCcdSweptSphereRadius(),curHitFraction);
+ btScalar curHitFraction = btScalar(1.); //is this available?
+ LocalTriangleSphereCastCallback raycastCallback(convexFromLocal, convexToLocal,
+ convexbody->getCcdSweptSphereRadius(), curHitFraction);
raycastCallback.m_hitFraction = convexbody->getHitFraction();
btCollisionObject* concavebody = triBody;
- btConcaveShape* triangleMesh = (btConcaveShape*) concavebody->getCollisionShape();
-
+ btConcaveShape* triangleMesh = (btConcaveShape*)concavebody->getCollisionShape();
+
if (triangleMesh)
{
- triangleMesh->processAllTriangles(&raycastCallback,rayAabbMin,rayAabbMax);
+ triangleMesh->processAllTriangles(&raycastCallback, rayAabbMin, rayAabbMax);
}
-
-
if (raycastCallback.m_hitFraction < convexbody->getHitFraction())
{
- convexbody->setHitFraction( raycastCallback.m_hitFraction);
+ convexbody->setHitFraction(raycastCallback.m_hitFraction);
return raycastCallback.m_hitFraction;
}
}
return btScalar(1.);
-
}
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h
index 93d842ef50..b72e402981 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h
@@ -26,42 +26,40 @@ class btDispatcher;
#include "btCollisionCreateFunc.h"
///For each triangle in the concave mesh that overlaps with the AABB of a convex (m_convexProxy), processTriangle is called.
-ATTRIBUTE_ALIGNED16(class) btConvexTriangleCallback : public btTriangleCallback
+ATTRIBUTE_ALIGNED16(class)
+btConvexTriangleCallback : public btTriangleCallback
{
-
- btVector3 m_aabbMin;
- btVector3 m_aabbMax ;
+ btVector3 m_aabbMin;
+ btVector3 m_aabbMax;
const btCollisionObjectWrapper* m_convexBodyWrap;
const btCollisionObjectWrapper* m_triBodyWrap;
-
-
btManifoldResult* m_resultOut;
- btDispatcher* m_dispatcher;
+ btDispatcher* m_dispatcher;
const btDispatcherInfo* m_dispatchInfoPtr;
btScalar m_collisionMarginTriangle;
-
+
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
-
-int m_triangleCount;
-
- btPersistentManifold* m_manifoldPtr;
- btConvexTriangleCallback(btDispatcher* dispatcher,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped);
+ int m_triangleCount;
+
+ btPersistentManifold* m_manifoldPtr;
- void setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,const btCollisionObjectWrapper* convexBodyWrap, const btCollisionObjectWrapper* triBodyWrap, btManifoldResult* resultOut);
+ btConvexTriangleCallback(btDispatcher * dispatcher, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped);
- void clearWrapperData()
+ void setTimeStepAndCounters(btScalar collisionMarginTriangle, const btDispatcherInfo& dispatchInfo, const btCollisionObjectWrapper* convexBodyWrap, const btCollisionObjectWrapper* triBodyWrap, btManifoldResult* resultOut);
+
+ void clearWrapperData()
{
m_convexBodyWrap = 0;
m_triBodyWrap = 0;
}
virtual ~btConvexTriangleCallback();
- virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex);
-
+ virtual void processTriangle(btVector3 * triangle, int partId, int triangleIndex);
+
void clearCache();
SIMD_FORCE_INLINE const btVector3& getAabbMin() const
@@ -72,56 +70,48 @@ int m_triangleCount;
{
return m_aabbMax;
}
-
};
-
-
-
/// btConvexConcaveCollisionAlgorithm supports collision between convex shapes and (concave) trianges meshes.
-ATTRIBUTE_ALIGNED16(class) btConvexConcaveCollisionAlgorithm : public btActivatingCollisionAlgorithm
+ATTRIBUTE_ALIGNED16(class)
+btConvexConcaveCollisionAlgorithm : public btActivatingCollisionAlgorithm
{
-
btConvexTriangleCallback m_btConvexTriangleCallback;
- bool m_isSwapped;
-
-
+ bool m_isSwapped;
public:
-
BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped);
+
+ btConvexConcaveCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped);
virtual ~btConvexConcaveCollisionAlgorithm();
- virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
+
+ btScalar calculateTimeOfImpact(btCollisionObject * body0, btCollisionObject * body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
- btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual void getAllContactManifolds(btManifoldArray & manifoldArray);
- virtual void getAllContactManifolds(btManifoldArray& manifoldArray);
-
- void clearCache();
+ void clearCache();
- struct CreateFunc :public btCollisionAlgorithmCreateFunc
+ struct CreateFunc : public btCollisionAlgorithmCreateFunc
{
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm));
- return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0Wrap,body1Wrap,false);
+ return new (mem) btConvexConcaveCollisionAlgorithm(ci, body0Wrap, body1Wrap, false);
}
};
- struct SwappedCreateFunc :public btCollisionAlgorithmCreateFunc
+ struct SwappedCreateFunc : public btCollisionAlgorithmCreateFunc
{
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm));
- return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0Wrap,body1Wrap,true);
+ return new (mem) btConvexConcaveCollisionAlgorithm(ci, body0Wrap, body1Wrap, true);
}
};
-
};
-#endif //BT_CONVEX_CONCAVE_COLLISION_ALGORITHM_H
+#endif //BT_CONVEX_CONCAVE_COLLISION_ALGORITHM_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp
index 3e8bc6e426..44dd3c553e 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp
@@ -30,8 +30,6 @@ subject to the following restrictions:
#include "BulletCollision/CollisionShapes/btTriangleShape.h"
#include "BulletCollision/CollisionShapes/btConvexPolyhedron.h"
-
-
#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
@@ -43,8 +41,6 @@ subject to the following restrictions:
#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h"
-
-
#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h"
@@ -57,8 +53,6 @@ subject to the following restrictions:
///////////
-
-
static SIMD_FORCE_INLINE void segmentsClosestPoints(
btVector3& ptsVector,
btVector3& offsetA,
@@ -66,43 +60,49 @@ static SIMD_FORCE_INLINE void segmentsClosestPoints(
btScalar& tA, btScalar& tB,
const btVector3& translation,
const btVector3& dirA, btScalar hlenA,
- const btVector3& dirB, btScalar hlenB )
+ const btVector3& dirB, btScalar hlenB)
{
// compute the parameters of the closest points on each line segment
- btScalar dirA_dot_dirB = btDot(dirA,dirB);
- btScalar dirA_dot_trans = btDot(dirA,translation);
- btScalar dirB_dot_trans = btDot(dirB,translation);
+ btScalar dirA_dot_dirB = btDot(dirA, dirB);
+ btScalar dirA_dot_trans = btDot(dirA, translation);
+ btScalar dirB_dot_trans = btDot(dirB, translation);
btScalar denom = 1.0f - dirA_dot_dirB * dirA_dot_dirB;
- if ( denom == 0.0f ) {
+ if (denom == 0.0f)
+ {
tA = 0.0f;
- } else {
- tA = ( dirA_dot_trans - dirB_dot_trans * dirA_dot_dirB ) / denom;
- if ( tA < -hlenA )
+ }
+ else
+ {
+ tA = (dirA_dot_trans - dirB_dot_trans * dirA_dot_dirB) / denom;
+ if (tA < -hlenA)
tA = -hlenA;
- else if ( tA > hlenA )
+ else if (tA > hlenA)
tA = hlenA;
}
tB = tA * dirA_dot_dirB - dirB_dot_trans;
- if ( tB < -hlenB ) {
+ if (tB < -hlenB)
+ {
tB = -hlenB;
tA = tB * dirA_dot_dirB + dirA_dot_trans;
- if ( tA < -hlenA )
+ if (tA < -hlenA)
tA = -hlenA;
- else if ( tA > hlenA )
+ else if (tA > hlenA)
tA = hlenA;
- } else if ( tB > hlenB ) {
+ }
+ else if (tB > hlenB)
+ {
tB = hlenB;
tA = tB * dirA_dot_dirB + dirA_dot_trans;
- if ( tA < -hlenA )
+ if (tA < -hlenA)
tA = -hlenA;
- else if ( tA > hlenA )
+ else if (tA > hlenA)
tA = hlenA;
}
@@ -114,19 +114,18 @@ static SIMD_FORCE_INLINE void segmentsClosestPoints(
ptsVector = translation - offsetA + offsetB;
}
-
static SIMD_FORCE_INLINE btScalar capsuleCapsuleDistance(
btVector3& normalOnB,
btVector3& pointOnB,
btScalar capsuleLengthA,
- btScalar capsuleRadiusA,
+ btScalar capsuleRadiusA,
btScalar capsuleLengthB,
- btScalar capsuleRadiusB,
+ btScalar capsuleRadiusB,
int capsuleAxisA,
int capsuleAxisB,
const btTransform& transformA,
const btTransform& transformB,
- btScalar distanceThreshold )
+ btScalar distanceThreshold)
{
btVector3 directionA = transformA.getBasis().getColumn(capsuleAxisA);
btVector3 translationA = transformA.getOrigin();
@@ -139,47 +138,38 @@ static SIMD_FORCE_INLINE btScalar capsuleCapsuleDistance(
// compute the closest points of the capsule line segments
- btVector3 ptsVector; // the vector between the closest points
-
- btVector3 offsetA, offsetB; // offsets from segment centers to their closest points
- btScalar tA, tB; // parameters on line segment
+ btVector3 ptsVector; // the vector between the closest points
+
+ btVector3 offsetA, offsetB; // offsets from segment centers to their closest points
+ btScalar tA, tB; // parameters on line segment
- segmentsClosestPoints( ptsVector, offsetA, offsetB, tA, tB, translation,
- directionA, capsuleLengthA, directionB, capsuleLengthB );
+ segmentsClosestPoints(ptsVector, offsetA, offsetB, tA, tB, translation,
+ directionA, capsuleLengthA, directionB, capsuleLengthB);
btScalar distance = ptsVector.length() - capsuleRadiusA - capsuleRadiusB;
- if ( distance > distanceThreshold )
+ if (distance > distanceThreshold)
return distance;
btScalar lenSqr = ptsVector.length2();
- if (lenSqr<= (SIMD_EPSILON*SIMD_EPSILON))
+ if (lenSqr <= (SIMD_EPSILON * SIMD_EPSILON))
{
//degenerate case where 2 capsules are likely at the same location: take a vector tangential to 'directionA'
btVector3 q;
- btPlaneSpace1(directionA,normalOnB,q);
- } else
+ btPlaneSpace1(directionA, normalOnB, q);
+ }
+ else
{
// compute the contact normal
- normalOnB = ptsVector*-btRecipSqrt(lenSqr);
+ normalOnB = ptsVector * -btRecipSqrt(lenSqr);
}
- pointOnB = transformB.getOrigin()+offsetB + normalOnB * capsuleRadiusB;
+ pointOnB = transformB.getOrigin() + offsetB + normalOnB * capsuleRadiusB;
return distance;
}
-
-
-
-
-
-
//////////
-
-
-
-
btConvexConvexAlgorithm::CreateFunc::CreateFunc(btConvexPenetrationDepthSolver* pdSolver)
{
m_numPerturbationIterations = 0;
@@ -187,30 +177,27 @@ btConvexConvexAlgorithm::CreateFunc::CreateFunc(btConvexPenetrationDepthSolver*
m_pdSolver = pdSolver;
}
-btConvexConvexAlgorithm::CreateFunc::~CreateFunc()
-{
+btConvexConvexAlgorithm::CreateFunc::~CreateFunc()
+{
}
-btConvexConvexAlgorithm::btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btConvexPenetrationDepthSolver* pdSolver,int numPerturbationIterations, int minimumPointsPerturbationThreshold)
-: btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap),
-m_pdSolver(pdSolver),
-m_ownManifold (false),
-m_manifoldPtr(mf),
-m_lowLevelOfDetail(false),
+btConvexConvexAlgorithm::btConvexConvexAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold)
+ : btActivatingCollisionAlgorithm(ci, body0Wrap, body1Wrap),
+ m_pdSolver(pdSolver),
+ m_ownManifold(false),
+ m_manifoldPtr(mf),
+ m_lowLevelOfDetail(false),
#ifdef USE_SEPDISTANCE_UTIL2
-m_sepDistance((static_cast<btConvexShape*>(body0->getCollisionShape()))->getAngularMotionDisc(),
- (static_cast<btConvexShape*>(body1->getCollisionShape()))->getAngularMotionDisc()),
+ m_sepDistance((static_cast<btConvexShape*>(body0->getCollisionShape()))->getAngularMotionDisc(),
+ (static_cast<btConvexShape*>(body1->getCollisionShape()))->getAngularMotionDisc()),
#endif
-m_numPerturbationIterations(numPerturbationIterations),
-m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold)
+ m_numPerturbationIterations(numPerturbationIterations),
+ m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold)
{
(void)body0Wrap;
(void)body1Wrap;
}
-
-
-
btConvexConvexAlgorithm::~btConvexConvexAlgorithm()
{
if (m_ownManifold)
@@ -220,112 +207,105 @@ btConvexConvexAlgorithm::~btConvexConvexAlgorithm()
}
}
-void btConvexConvexAlgorithm ::setLowLevelOfDetail(bool useLowLevel)
+void btConvexConvexAlgorithm ::setLowLevelOfDetail(bool useLowLevel)
{
m_lowLevelOfDetail = useLowLevel;
}
-
struct btPerturbedContactResult : public btManifoldResult
{
btManifoldResult* m_originalManifoldResult;
btTransform m_transformA;
btTransform m_transformB;
- btTransform m_unPerturbedTransform;
- bool m_perturbA;
- btIDebugDraw* m_debugDrawer;
-
-
- btPerturbedContactResult(btManifoldResult* originalResult,const btTransform& transformA,const btTransform& transformB,const btTransform& unPerturbedTransform,bool perturbA,btIDebugDraw* debugDrawer)
- :m_originalManifoldResult(originalResult),
- m_transformA(transformA),
- m_transformB(transformB),
- m_unPerturbedTransform(unPerturbedTransform),
- m_perturbA(perturbA),
- m_debugDrawer(debugDrawer)
+ btTransform m_unPerturbedTransform;
+ bool m_perturbA;
+ btIDebugDraw* m_debugDrawer;
+
+ btPerturbedContactResult(btManifoldResult* originalResult, const btTransform& transformA, const btTransform& transformB, const btTransform& unPerturbedTransform, bool perturbA, btIDebugDraw* debugDrawer)
+ : m_originalManifoldResult(originalResult),
+ m_transformA(transformA),
+ m_transformB(transformB),
+ m_unPerturbedTransform(unPerturbedTransform),
+ m_perturbA(perturbA),
+ m_debugDrawer(debugDrawer)
{
}
- virtual ~ btPerturbedContactResult()
+ virtual ~btPerturbedContactResult()
{
}
- virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar orgDepth)
+ virtual void addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar orgDepth)
{
- btVector3 endPt,startPt;
+ btVector3 endPt, startPt;
btScalar newDepth;
btVector3 newNormal;
if (m_perturbA)
{
- btVector3 endPtOrg = pointInWorld + normalOnBInWorld*orgDepth;
- endPt = (m_unPerturbedTransform*m_transformA.inverse())(endPtOrg);
- newDepth = (endPt - pointInWorld).dot(normalOnBInWorld);
- startPt = endPt - normalOnBInWorld*newDepth;
- } else
+ btVector3 endPtOrg = pointInWorld + normalOnBInWorld * orgDepth;
+ endPt = (m_unPerturbedTransform * m_transformA.inverse())(endPtOrg);
+ newDepth = (endPt - pointInWorld).dot(normalOnBInWorld);
+ startPt = endPt - normalOnBInWorld * newDepth;
+ }
+ else
{
- endPt = pointInWorld + normalOnBInWorld*orgDepth;
- startPt = (m_unPerturbedTransform*m_transformB.inverse())(pointInWorld);
- newDepth = (endPt - startPt).dot(normalOnBInWorld);
-
+ endPt = pointInWorld + normalOnBInWorld * orgDepth;
+ startPt = (m_unPerturbedTransform * m_transformB.inverse())(pointInWorld);
+ newDepth = (endPt - startPt).dot(normalOnBInWorld);
}
//#define DEBUG_CONTACTS 1
#ifdef DEBUG_CONTACTS
- m_debugDrawer->drawLine(startPt,endPt,btVector3(1,0,0));
- m_debugDrawer->drawSphere(startPt,0.05,btVector3(0,1,0));
- m_debugDrawer->drawSphere(endPt,0.05,btVector3(0,0,1));
-#endif //DEBUG_CONTACTS
+ m_debugDrawer->drawLine(startPt, endPt, btVector3(1, 0, 0));
+ m_debugDrawer->drawSphere(startPt, 0.05, btVector3(0, 1, 0));
+ m_debugDrawer->drawSphere(endPt, 0.05, btVector3(0, 0, 1));
+#endif //DEBUG_CONTACTS
-
- m_originalManifoldResult->addContactPoint(normalOnBInWorld,startPt,newDepth);
+ m_originalManifoldResult->addContactPoint(normalOnBInWorld, startPt, newDepth);
}
-
};
extern btScalar gContactBreakingThreshold;
-
//
// Convex-Convex collision algorithm
//
-void btConvexConvexAlgorithm ::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+void btConvexConvexAlgorithm ::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
{
-
if (!m_manifoldPtr)
{
//swapped?
- m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(),body1Wrap->getCollisionObject());
+ m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(), body1Wrap->getCollisionObject());
m_ownManifold = true;
}
resultOut->setPersistentManifold(m_manifoldPtr);
//comment-out next line to test multi-contact generation
//resultOut->getPersistentManifold()->clearManifold();
-
const btConvexShape* min0 = static_cast<const btConvexShape*>(body0Wrap->getCollisionShape());
const btConvexShape* min1 = static_cast<const btConvexShape*>(body1Wrap->getCollisionShape());
- btVector3 normalOnB;
- btVector3 pointOnBWorld;
+ btVector3 normalOnB;
+ btVector3 pointOnBWorld;
#ifndef BT_DISABLE_CAPSULE_CAPSULE_COLLIDER
if ((min0->getShapeType() == CAPSULE_SHAPE_PROXYTYPE) && (min1->getShapeType() == CAPSULE_SHAPE_PROXYTYPE))
{
//m_manifoldPtr->clearManifold();
- btCapsuleShape* capsuleA = (btCapsuleShape*) min0;
- btCapsuleShape* capsuleB = (btCapsuleShape*) min1;
-
- btScalar threshold = m_manifoldPtr->getContactBreakingThreshold();
+ btCapsuleShape* capsuleA = (btCapsuleShape*)min0;
+ btCapsuleShape* capsuleB = (btCapsuleShape*)min1;
- btScalar dist = capsuleCapsuleDistance(normalOnB, pointOnBWorld,capsuleA->getHalfHeight(),capsuleA->getRadius(),
- capsuleB->getHalfHeight(),capsuleB->getRadius(),capsuleA->getUpAxis(),capsuleB->getUpAxis(),
- body0Wrap->getWorldTransform(),body1Wrap->getWorldTransform(),threshold);
+ btScalar threshold = m_manifoldPtr->getContactBreakingThreshold()+ resultOut->m_closestPointDistanceThreshold;
- if (dist<threshold)
+ btScalar dist = capsuleCapsuleDistance(normalOnB, pointOnBWorld, capsuleA->getHalfHeight(), capsuleA->getRadius(),
+ capsuleB->getHalfHeight(), capsuleB->getRadius(), capsuleA->getUpAxis(), capsuleB->getUpAxis(),
+ body0Wrap->getWorldTransform(), body1Wrap->getWorldTransform(), threshold);
+
+ if (dist < threshold)
{
- btAssert(normalOnB.length2()>=(SIMD_EPSILON*SIMD_EPSILON));
- resultOut->addContactPoint(normalOnB,pointOnBWorld,dist);
+ btAssert(normalOnB.length2() >= (SIMD_EPSILON * SIMD_EPSILON));
+ resultOut->addContactPoint(normalOnB, pointOnBWorld, dist);
}
resultOut->refreshContactPoints();
return;
@@ -335,19 +315,19 @@ void btConvexConvexAlgorithm ::processCollision (const btCollisionObjectWrapper*
{
//m_manifoldPtr->clearManifold();
- btCapsuleShape* capsuleA = (btCapsuleShape*) min0;
- btSphereShape* capsuleB = (btSphereShape*) min1;
-
- btScalar threshold = m_manifoldPtr->getContactBreakingThreshold();
+ btCapsuleShape* capsuleA = (btCapsuleShape*)min0;
+ btSphereShape* capsuleB = (btSphereShape*)min1;
+
+ btScalar threshold = m_manifoldPtr->getContactBreakingThreshold()+ resultOut->m_closestPointDistanceThreshold;
- btScalar dist = capsuleCapsuleDistance(normalOnB, pointOnBWorld,capsuleA->getHalfHeight(),capsuleA->getRadius(),
- 0.,capsuleB->getRadius(),capsuleA->getUpAxis(),1,
- body0Wrap->getWorldTransform(),body1Wrap->getWorldTransform(),threshold);
+ btScalar dist = capsuleCapsuleDistance(normalOnB, pointOnBWorld, capsuleA->getHalfHeight(), capsuleA->getRadius(),
+ 0., capsuleB->getRadius(), capsuleA->getUpAxis(), 1,
+ body0Wrap->getWorldTransform(), body1Wrap->getWorldTransform(), threshold);
- if (dist<threshold)
+ if (dist < threshold)
{
- btAssert(normalOnB.length2()>=(SIMD_EPSILON*SIMD_EPSILON));
- resultOut->addContactPoint(normalOnB,pointOnBWorld,dist);
+ btAssert(normalOnB.length2() >= (SIMD_EPSILON * SIMD_EPSILON));
+ resultOut->addContactPoint(normalOnB, pointOnBWorld, dist);
}
resultOut->refreshContactPoints();
return;
@@ -357,252 +337,227 @@ void btConvexConvexAlgorithm ::processCollision (const btCollisionObjectWrapper*
{
//m_manifoldPtr->clearManifold();
- btSphereShape* capsuleA = (btSphereShape*) min0;
- btCapsuleShape* capsuleB = (btCapsuleShape*) min1;
-
- btScalar threshold = m_manifoldPtr->getContactBreakingThreshold();
+ btSphereShape* capsuleA = (btSphereShape*)min0;
+ btCapsuleShape* capsuleB = (btCapsuleShape*)min1;
+
+ btScalar threshold = m_manifoldPtr->getContactBreakingThreshold()+ resultOut->m_closestPointDistanceThreshold;
- btScalar dist = capsuleCapsuleDistance(normalOnB, pointOnBWorld,0.,capsuleA->getRadius(),
- capsuleB->getHalfHeight(),capsuleB->getRadius(),1,capsuleB->getUpAxis(),
- body0Wrap->getWorldTransform(),body1Wrap->getWorldTransform(),threshold);
+ btScalar dist = capsuleCapsuleDistance(normalOnB, pointOnBWorld, 0., capsuleA->getRadius(),
+ capsuleB->getHalfHeight(), capsuleB->getRadius(), 1, capsuleB->getUpAxis(),
+ body0Wrap->getWorldTransform(), body1Wrap->getWorldTransform(), threshold);
- if (dist<threshold)
+ if (dist < threshold)
{
- btAssert(normalOnB.length2()>=(SIMD_EPSILON*SIMD_EPSILON));
- resultOut->addContactPoint(normalOnB,pointOnBWorld,dist);
+ btAssert(normalOnB.length2() >= (SIMD_EPSILON * SIMD_EPSILON));
+ resultOut->addContactPoint(normalOnB, pointOnBWorld, dist);
}
resultOut->refreshContactPoints();
return;
}
-#endif //BT_DISABLE_CAPSULE_CAPSULE_COLLIDER
-
-
-
+#endif //BT_DISABLE_CAPSULE_CAPSULE_COLLIDER
#ifdef USE_SEPDISTANCE_UTIL2
if (dispatchInfo.m_useConvexConservativeDistanceUtil)
{
- m_sepDistance.updateSeparatingDistance(body0->getWorldTransform(),body1->getWorldTransform());
+ m_sepDistance.updateSeparatingDistance(body0->getWorldTransform(), body1->getWorldTransform());
}
- if (!dispatchInfo.m_useConvexConservativeDistanceUtil || m_sepDistance.getConservativeSeparatingDistance()<=0.f)
-#endif //USE_SEPDISTANCE_UTIL2
+ if (!dispatchInfo.m_useConvexConservativeDistanceUtil || m_sepDistance.getConservativeSeparatingDistance() <= 0.f)
+#endif //USE_SEPDISTANCE_UTIL2
{
-
-
- btGjkPairDetector::ClosestPointInput input;
- btVoronoiSimplexSolver simplexSolver;
- btGjkPairDetector gjkPairDetector( min0, min1, &simplexSolver, m_pdSolver );
- //TODO: if (dispatchInfo.m_useContinuous)
- gjkPairDetector.setMinkowskiA(min0);
- gjkPairDetector.setMinkowskiB(min1);
+ btGjkPairDetector::ClosestPointInput input;
+ btVoronoiSimplexSolver simplexSolver;
+ btGjkPairDetector gjkPairDetector(min0, min1, &simplexSolver, m_pdSolver);
+ //TODO: if (dispatchInfo.m_useContinuous)
+ gjkPairDetector.setMinkowskiA(min0);
+ gjkPairDetector.setMinkowskiB(min1);
#ifdef USE_SEPDISTANCE_UTIL2
- if (dispatchInfo.m_useConvexConservativeDistanceUtil)
- {
- input.m_maximumDistanceSquared = BT_LARGE_FLOAT;
- } else
-#endif //USE_SEPDISTANCE_UTIL2
- {
- //if (dispatchInfo.m_convexMaxDistanceUseCPT)
- //{
- // input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactProcessingThreshold();
- //} else
- //{
- input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactBreakingThreshold()+resultOut->m_closestPointDistanceThreshold;
-// }
-
- input.m_maximumDistanceSquared*= input.m_maximumDistanceSquared;
- }
-
- input.m_transformA = body0Wrap->getWorldTransform();
- input.m_transformB = body1Wrap->getWorldTransform();
-
-
-
-
-
-#ifdef USE_SEPDISTANCE_UTIL2
- btScalar sepDist = 0.f;
- if (dispatchInfo.m_useConvexConservativeDistanceUtil)
- {
- sepDist = gjkPairDetector.getCachedSeparatingDistance();
- if (sepDist>SIMD_EPSILON)
+ if (dispatchInfo.m_useConvexConservativeDistanceUtil)
{
- sepDist += dispatchInfo.m_convexConservativeDistanceThreshold;
- //now perturbe directions to get multiple contact points
-
+ input.m_maximumDistanceSquared = BT_LARGE_FLOAT;
+ }
+ else
+#endif //USE_SEPDISTANCE_UTIL2
+ {
+ //if (dispatchInfo.m_convexMaxDistanceUseCPT)
+ //{
+ // input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactProcessingThreshold();
+ //} else
+ //{
+ input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactBreakingThreshold() + resultOut->m_closestPointDistanceThreshold;
+ // }
+
+ input.m_maximumDistanceSquared *= input.m_maximumDistanceSquared;
}
- }
-#endif //USE_SEPDISTANCE_UTIL2
-
- if (min0->isPolyhedral() && min1->isPolyhedral())
- {
+ input.m_transformA = body0Wrap->getWorldTransform();
+ input.m_transformB = body1Wrap->getWorldTransform();
- struct btDummyResult : public btDiscreteCollisionDetectorInterface::Result
+#ifdef USE_SEPDISTANCE_UTIL2
+ btScalar sepDist = 0.f;
+ if (dispatchInfo.m_useConvexConservativeDistanceUtil)
{
- btVector3 m_normalOnBInWorld;
- btVector3 m_pointInWorld;
- btScalar m_depth;
- bool m_hasContact;
-
-
- btDummyResult()
- : m_hasContact(false)
+ sepDist = gjkPairDetector.getCachedSeparatingDistance();
+ if (sepDist > SIMD_EPSILON)
{
+ sepDist += dispatchInfo.m_convexConservativeDistanceThreshold;
+ //now perturbe directions to get multiple contact points
}
-
-
- virtual void setShapeIdentifiersA(int partId0,int index0){}
- virtual void setShapeIdentifiersB(int partId1,int index1){}
- virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)
- {
- m_hasContact = true;
- m_normalOnBInWorld = normalOnBInWorld;
- m_pointInWorld = pointInWorld;
- m_depth = depth;
- }
- };
+ }
+#endif //USE_SEPDISTANCE_UTIL2
-
- struct btWithoutMarginResult : public btDiscreteCollisionDetectorInterface::Result
+ if (min0->isPolyhedral() && min1->isPolyhedral())
{
- btDiscreteCollisionDetectorInterface::Result* m_originalResult;
- btVector3 m_reportedNormalOnWorld;
- btScalar m_marginOnA;
- btScalar m_marginOnB;
- btScalar m_reportedDistance;
-
- bool m_foundResult;
- btWithoutMarginResult(btDiscreteCollisionDetectorInterface::Result* result, btScalar marginOnA, btScalar marginOnB)
- :m_originalResult(result),
- m_marginOnA(marginOnA),
- m_marginOnB(marginOnB),
- m_foundResult(false)
- {
- }
-
- virtual void setShapeIdentifiersA(int partId0,int index0){}
- virtual void setShapeIdentifiersB(int partId1,int index1){}
- virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorldOrg,btScalar depthOrg)
+ struct btDummyResult : public btDiscreteCollisionDetectorInterface::Result
{
- m_reportedDistance = depthOrg;
- m_reportedNormalOnWorld = normalOnBInWorld;
-
- btVector3 adjustedPointB = pointInWorldOrg - normalOnBInWorld*m_marginOnB;
- m_reportedDistance = depthOrg+(m_marginOnA+m_marginOnB);
- if (m_reportedDistance<0.f)
+ btVector3 m_normalOnBInWorld;
+ btVector3 m_pointInWorld;
+ btScalar m_depth;
+ bool m_hasContact;
+
+ btDummyResult()
+ : m_hasContact(false)
{
- m_foundResult = true;
}
- m_originalResult->addContactPoint(normalOnBInWorld,adjustedPointB,m_reportedDistance);
- }
- };
-
- btDummyResult dummy;
-
-///btBoxShape is an exception: its vertices are created WITH margin so don't subtract it
+ virtual void setShapeIdentifiersA(int partId0, int index0) {}
+ virtual void setShapeIdentifiersB(int partId1, int index1) {}
+ virtual void addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar depth)
+ {
+ m_hasContact = true;
+ m_normalOnBInWorld = normalOnBInWorld;
+ m_pointInWorld = pointInWorld;
+ m_depth = depth;
+ }
+ };
- btScalar min0Margin = min0->getShapeType()==BOX_SHAPE_PROXYTYPE? 0.f : min0->getMargin();
- btScalar min1Margin = min1->getShapeType()==BOX_SHAPE_PROXYTYPE? 0.f : min1->getMargin();
+ struct btWithoutMarginResult : public btDiscreteCollisionDetectorInterface::Result
+ {
+ btDiscreteCollisionDetectorInterface::Result* m_originalResult;
+ btVector3 m_reportedNormalOnWorld;
+ btScalar m_marginOnA;
+ btScalar m_marginOnB;
+ btScalar m_reportedDistance;
+
+ bool m_foundResult;
+ btWithoutMarginResult(btDiscreteCollisionDetectorInterface::Result* result, btScalar marginOnA, btScalar marginOnB)
+ : m_originalResult(result),
+ m_marginOnA(marginOnA),
+ m_marginOnB(marginOnB),
+ m_foundResult(false)
+ {
+ }
- btWithoutMarginResult withoutMargin(resultOut, min0Margin,min1Margin);
+ virtual void setShapeIdentifiersA(int partId0, int index0) {}
+ virtual void setShapeIdentifiersB(int partId1, int index1) {}
+ virtual void addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorldOrg, btScalar depthOrg)
+ {
+ m_reportedDistance = depthOrg;
+ m_reportedNormalOnWorld = normalOnBInWorld;
- btPolyhedralConvexShape* polyhedronA = (btPolyhedralConvexShape*) min0;
- btPolyhedralConvexShape* polyhedronB = (btPolyhedralConvexShape*) min1;
- if (polyhedronA->getConvexPolyhedron() && polyhedronB->getConvexPolyhedron())
- {
+ btVector3 adjustedPointB = pointInWorldOrg - normalOnBInWorld * m_marginOnB;
+ m_reportedDistance = depthOrg + (m_marginOnA + m_marginOnB);
+ if (m_reportedDistance < 0.f)
+ {
+ m_foundResult = true;
+ }
+ m_originalResult->addContactPoint(normalOnBInWorld, adjustedPointB, m_reportedDistance);
+ }
+ };
+ btDummyResult dummy;
-
+ ///btBoxShape is an exception: its vertices are created WITH margin so don't subtract it
- btScalar threshold = m_manifoldPtr->getContactBreakingThreshold();
+ btScalar min0Margin = min0->getShapeType() == BOX_SHAPE_PROXYTYPE ? 0.f : min0->getMargin();
+ btScalar min1Margin = min1->getShapeType() == BOX_SHAPE_PROXYTYPE ? 0.f : min1->getMargin();
- btScalar minDist = -1e30f;
- btVector3 sepNormalWorldSpace;
- bool foundSepAxis = true;
+ btWithoutMarginResult withoutMargin(resultOut, min0Margin, min1Margin);
- if (dispatchInfo.m_enableSatConvex)
- {
- foundSepAxis = btPolyhedralContactClipping::findSeparatingAxis(
- *polyhedronA->getConvexPolyhedron(), *polyhedronB->getConvexPolyhedron(),
- body0Wrap->getWorldTransform(),
- body1Wrap->getWorldTransform(),
- sepNormalWorldSpace,*resultOut);
- } else
+ btPolyhedralConvexShape* polyhedronA = (btPolyhedralConvexShape*)min0;
+ btPolyhedralConvexShape* polyhedronB = (btPolyhedralConvexShape*)min1;
+ if (polyhedronA->getConvexPolyhedron() && polyhedronB->getConvexPolyhedron())
{
+ btScalar threshold = m_manifoldPtr->getContactBreakingThreshold()+ resultOut->m_closestPointDistanceThreshold;
+
+ btScalar minDist = -1e30f;
+ btVector3 sepNormalWorldSpace;
+ bool foundSepAxis = true;
+
+ if (dispatchInfo.m_enableSatConvex)
+ {
+ foundSepAxis = btPolyhedralContactClipping::findSeparatingAxis(
+ *polyhedronA->getConvexPolyhedron(), *polyhedronB->getConvexPolyhedron(),
+ body0Wrap->getWorldTransform(),
+ body1Wrap->getWorldTransform(),
+ sepNormalWorldSpace, *resultOut);
+ }
+ else
+ {
#ifdef ZERO_MARGIN
- gjkPairDetector.setIgnoreMargin(true);
- gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
+ gjkPairDetector.setIgnoreMargin(true);
+ gjkPairDetector.getClosestPoints(input, *resultOut, dispatchInfo.m_debugDraw);
#else
+ gjkPairDetector.getClosestPoints(input, withoutMargin, dispatchInfo.m_debugDraw);
+ //gjkPairDetector.getClosestPoints(input,dummy,dispatchInfo.m_debugDraw);
+#endif //ZERO_MARGIN \
+ //btScalar l2 = gjkPairDetector.getCachedSeparatingAxis().length2(); \
+ //if (l2>SIMD_EPSILON)
+ {
+ sepNormalWorldSpace = withoutMargin.m_reportedNormalOnWorld; //gjkPairDetector.getCachedSeparatingAxis()*(1.f/l2);
+ //minDist = -1e30f;//gjkPairDetector.getCachedSeparatingDistance();
+ minDist = withoutMargin.m_reportedDistance; //gjkPairDetector.getCachedSeparatingDistance()+min0->getMargin()+min1->getMargin();
- gjkPairDetector.getClosestPoints(input,withoutMargin,dispatchInfo.m_debugDraw);
- //gjkPairDetector.getClosestPoints(input,dummy,dispatchInfo.m_debugDraw);
-#endif //ZERO_MARGIN
- //btScalar l2 = gjkPairDetector.getCachedSeparatingAxis().length2();
- //if (l2>SIMD_EPSILON)
- {
- sepNormalWorldSpace = withoutMargin.m_reportedNormalOnWorld;//gjkPairDetector.getCachedSeparatingAxis()*(1.f/l2);
- //minDist = -1e30f;//gjkPairDetector.getCachedSeparatingDistance();
- minDist = withoutMargin.m_reportedDistance;//gjkPairDetector.getCachedSeparatingDistance()+min0->getMargin()+min1->getMargin();
-
#ifdef ZERO_MARGIN
- foundSepAxis = true;//gjkPairDetector.getCachedSeparatingDistance()<0.f;
+ foundSepAxis = true; //gjkPairDetector.getCachedSeparatingDistance()<0.f;
#else
- foundSepAxis = withoutMargin.m_foundResult && minDist<0;//-(min0->getMargin()+min1->getMargin());
+ foundSepAxis = withoutMargin.m_foundResult && minDist < 0; //-(min0->getMargin()+min1->getMargin());
#endif
+ }
}
- }
- if (foundSepAxis)
- {
-
-// printf("sepNormalWorldSpace=%f,%f,%f\n",sepNormalWorldSpace.getX(),sepNormalWorldSpace.getY(),sepNormalWorldSpace.getZ());
-
- worldVertsB1.resize(0);
- btPolyhedralContactClipping::clipHullAgainstHull(sepNormalWorldSpace, *polyhedronA->getConvexPolyhedron(), *polyhedronB->getConvexPolyhedron(),
- body0Wrap->getWorldTransform(),
- body1Wrap->getWorldTransform(), minDist-threshold, threshold, worldVertsB1,worldVertsB2,
- *resultOut);
-
- }
- if (m_ownManifold)
- {
- resultOut->refreshContactPoints();
- }
- return;
-
- } else
- {
-
+ if (foundSepAxis)
+ {
+ // printf("sepNormalWorldSpace=%f,%f,%f\n",sepNormalWorldSpace.getX(),sepNormalWorldSpace.getY(),sepNormalWorldSpace.getZ());
- //we can also deal with convex versus triangle (without connectivity data)
- if (dispatchInfo.m_enableSatConvex && polyhedronA->getConvexPolyhedron() && polyhedronB->getShapeType()==TRIANGLE_SHAPE_PROXYTYPE)
+ worldVertsB1.resize(0);
+ btPolyhedralContactClipping::clipHullAgainstHull(sepNormalWorldSpace, *polyhedronA->getConvexPolyhedron(), *polyhedronB->getConvexPolyhedron(),
+ body0Wrap->getWorldTransform(),
+ body1Wrap->getWorldTransform(), minDist - threshold, threshold, worldVertsB1, worldVertsB2,
+ *resultOut);
+ }
+ if (m_ownManifold)
+ {
+ resultOut->refreshContactPoints();
+ }
+ return;
+ }
+ else
{
+ //we can also deal with convex versus triangle (without connectivity data)
+ if (dispatchInfo.m_enableSatConvex && polyhedronA->getConvexPolyhedron() && polyhedronB->getShapeType() == TRIANGLE_SHAPE_PROXYTYPE)
+ {
+ btVertexArray worldSpaceVertices;
+ btTriangleShape* tri = (btTriangleShape*)polyhedronB;
+ worldSpaceVertices.push_back(body1Wrap->getWorldTransform() * tri->m_vertices1[0]);
+ worldSpaceVertices.push_back(body1Wrap->getWorldTransform() * tri->m_vertices1[1]);
+ worldSpaceVertices.push_back(body1Wrap->getWorldTransform() * tri->m_vertices1[2]);
+ //tri->initializePolyhedralFeatures();
- btVertexArray worldSpaceVertices;
- btTriangleShape* tri = (btTriangleShape*)polyhedronB;
- worldSpaceVertices.push_back( body1Wrap->getWorldTransform()*tri->m_vertices1[0]);
- worldSpaceVertices.push_back( body1Wrap->getWorldTransform()*tri->m_vertices1[1]);
- worldSpaceVertices.push_back( body1Wrap->getWorldTransform()*tri->m_vertices1[2]);
-
- //tri->initializePolyhedralFeatures();
+ btScalar threshold = m_manifoldPtr->getContactBreakingThreshold()+ resultOut->m_closestPointDistanceThreshold;
- btScalar threshold = m_manifoldPtr->getContactBreakingThreshold();
+ btVector3 sepNormalWorldSpace;
+ btScalar minDist = -1e30f;
+ btScalar maxDist = threshold;
- btVector3 sepNormalWorldSpace;
- btScalar minDist =-1e30f;
- btScalar maxDist = threshold;
-
- bool foundSepAxis = false;
- bool useSatSepNormal = true;
+ bool foundSepAxis = false;
+ bool useSatSepNormal = true;
- if (useSatSepNormal)
- {
+ if (useSatSepNormal)
+ {
#if 0
if (0)
{
@@ -610,113 +565,107 @@ void btConvexConvexAlgorithm ::processCollision (const btCollisionObjectWrapper*
polyhedronB->initializePolyhedralFeatures();
} else
#endif
- {
+ {
+ btVector3 uniqueEdges[3] = {tri->m_vertices1[1] - tri->m_vertices1[0],
+ tri->m_vertices1[2] - tri->m_vertices1[1],
+ tri->m_vertices1[0] - tri->m_vertices1[2]};
- btVector3 uniqueEdges[3] = {tri->m_vertices1[1]-tri->m_vertices1[0],
- tri->m_vertices1[2]-tri->m_vertices1[1],
- tri->m_vertices1[0]-tri->m_vertices1[2]};
+ uniqueEdges[0].normalize();
+ uniqueEdges[1].normalize();
+ uniqueEdges[2].normalize();
- uniqueEdges[0].normalize();
- uniqueEdges[1].normalize();
- uniqueEdges[2].normalize();
+ btConvexPolyhedron polyhedron;
+ polyhedron.m_vertices.push_back(tri->m_vertices1[2]);
+ polyhedron.m_vertices.push_back(tri->m_vertices1[0]);
+ polyhedron.m_vertices.push_back(tri->m_vertices1[1]);
- btConvexPolyhedron polyhedron;
- polyhedron.m_vertices.push_back(tri->m_vertices1[2]);
- polyhedron.m_vertices.push_back(tri->m_vertices1[0]);
- polyhedron.m_vertices.push_back(tri->m_vertices1[1]);
-
-
- {
- btFace combinedFaceA;
- combinedFaceA.m_indices.push_back(0);
- combinedFaceA.m_indices.push_back(1);
- combinedFaceA.m_indices.push_back(2);
- btVector3 faceNormal = uniqueEdges[0].cross(uniqueEdges[1]);
- faceNormal.normalize();
- btScalar planeEq=1e30f;
- for (int v=0;v<combinedFaceA.m_indices.size();v++)
{
- btScalar eq = tri->m_vertices1[combinedFaceA.m_indices[v]].dot(faceNormal);
- if (planeEq>eq)
+ btFace combinedFaceA;
+ combinedFaceA.m_indices.push_back(0);
+ combinedFaceA.m_indices.push_back(1);
+ combinedFaceA.m_indices.push_back(2);
+ btVector3 faceNormal = uniqueEdges[0].cross(uniqueEdges[1]);
+ faceNormal.normalize();
+ btScalar planeEq = 1e30f;
+ for (int v = 0; v < combinedFaceA.m_indices.size(); v++)
{
- planeEq=eq;
+ btScalar eq = tri->m_vertices1[combinedFaceA.m_indices[v]].dot(faceNormal);
+ if (planeEq > eq)
+ {
+ planeEq = eq;
+ }
}
+ combinedFaceA.m_plane[0] = faceNormal[0];
+ combinedFaceA.m_plane[1] = faceNormal[1];
+ combinedFaceA.m_plane[2] = faceNormal[2];
+ combinedFaceA.m_plane[3] = -planeEq;
+ polyhedron.m_faces.push_back(combinedFaceA);
}
- combinedFaceA.m_plane[0] = faceNormal[0];
- combinedFaceA.m_plane[1] = faceNormal[1];
- combinedFaceA.m_plane[2] = faceNormal[2];
- combinedFaceA.m_plane[3] = -planeEq;
- polyhedron.m_faces.push_back(combinedFaceA);
- }
- {
- btFace combinedFaceB;
- combinedFaceB.m_indices.push_back(0);
- combinedFaceB.m_indices.push_back(2);
- combinedFaceB.m_indices.push_back(1);
- btVector3 faceNormal = -uniqueEdges[0].cross(uniqueEdges[1]);
- faceNormal.normalize();
- btScalar planeEq=1e30f;
- for (int v=0;v<combinedFaceB.m_indices.size();v++)
{
- btScalar eq = tri->m_vertices1[combinedFaceB.m_indices[v]].dot(faceNormal);
- if (planeEq>eq)
+ btFace combinedFaceB;
+ combinedFaceB.m_indices.push_back(0);
+ combinedFaceB.m_indices.push_back(2);
+ combinedFaceB.m_indices.push_back(1);
+ btVector3 faceNormal = -uniqueEdges[0].cross(uniqueEdges[1]);
+ faceNormal.normalize();
+ btScalar planeEq = 1e30f;
+ for (int v = 0; v < combinedFaceB.m_indices.size(); v++)
{
- planeEq=eq;
+ btScalar eq = tri->m_vertices1[combinedFaceB.m_indices[v]].dot(faceNormal);
+ if (planeEq > eq)
+ {
+ planeEq = eq;
+ }
}
+
+ combinedFaceB.m_plane[0] = faceNormal[0];
+ combinedFaceB.m_plane[1] = faceNormal[1];
+ combinedFaceB.m_plane[2] = faceNormal[2];
+ combinedFaceB.m_plane[3] = -planeEq;
+ polyhedron.m_faces.push_back(combinedFaceB);
}
- combinedFaceB.m_plane[0] = faceNormal[0];
- combinedFaceB.m_plane[1] = faceNormal[1];
- combinedFaceB.m_plane[2] = faceNormal[2];
- combinedFaceB.m_plane[3] = -planeEq;
- polyhedron.m_faces.push_back(combinedFaceB);
- }
+ polyhedron.m_uniqueEdges.push_back(uniqueEdges[0]);
+ polyhedron.m_uniqueEdges.push_back(uniqueEdges[1]);
+ polyhedron.m_uniqueEdges.push_back(uniqueEdges[2]);
+ polyhedron.initialize2();
-
- polyhedron.m_uniqueEdges.push_back(uniqueEdges[0]);
- polyhedron.m_uniqueEdges.push_back(uniqueEdges[1]);
- polyhedron.m_uniqueEdges.push_back(uniqueEdges[2]);
- polyhedron.initialize2();
+ polyhedronB->setPolyhedralFeatures(polyhedron);
+ }
- polyhedronB->setPolyhedralFeatures(polyhedron);
+ foundSepAxis = btPolyhedralContactClipping::findSeparatingAxis(
+ *polyhedronA->getConvexPolyhedron(), *polyhedronB->getConvexPolyhedron(),
+ body0Wrap->getWorldTransform(),
+ body1Wrap->getWorldTransform(),
+ sepNormalWorldSpace, *resultOut);
+ // printf("sepNormalWorldSpace=%f,%f,%f\n",sepNormalWorldSpace.getX(),sepNormalWorldSpace.getY(),sepNormalWorldSpace.getZ());
}
-
-
-
- foundSepAxis = btPolyhedralContactClipping::findSeparatingAxis(
- *polyhedronA->getConvexPolyhedron(), *polyhedronB->getConvexPolyhedron(),
- body0Wrap->getWorldTransform(),
- body1Wrap->getWorldTransform(),
- sepNormalWorldSpace,*resultOut);
- // printf("sepNormalWorldSpace=%f,%f,%f\n",sepNormalWorldSpace.getX(),sepNormalWorldSpace.getY(),sepNormalWorldSpace.getZ());
-
- }
- else
- {
+ else
+ {
#ifdef ZERO_MARGIN
- gjkPairDetector.setIgnoreMargin(true);
- gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
+ gjkPairDetector.setIgnoreMargin(true);
+ gjkPairDetector.getClosestPoints(input, *resultOut, dispatchInfo.m_debugDraw);
#else
- gjkPairDetector.getClosestPoints(input,dummy,dispatchInfo.m_debugDraw);
-#endif//ZERO_MARGIN
-
- if (dummy.m_hasContact && dummy.m_depth<0)
- {
-
- if (foundSepAxis)
+ gjkPairDetector.getClosestPoints(input, dummy, dispatchInfo.m_debugDraw);
+#endif //ZERO_MARGIN
+
+ if (dummy.m_hasContact && dummy.m_depth < 0)
{
- if (dummy.m_normalOnBInWorld.dot(sepNormalWorldSpace)<0.99)
+ if (foundSepAxis)
{
- printf("?\n");
+ if (dummy.m_normalOnBInWorld.dot(sepNormalWorldSpace) < 0.99)
+ {
+ printf("?\n");
+ }
}
- } else
- {
- printf("!\n");
+ else
+ {
+ printf("!\n");
+ }
+ sepNormalWorldSpace.setValue(0, 0, 1); // = dummy.m_normalOnBInWorld;
+ //minDist = dummy.m_depth;
+ foundSepAxis = true;
}
- sepNormalWorldSpace.setValue(0,0,1);// = dummy.m_normalOnBInWorld;
- //minDist = dummy.m_depth;
- foundSepAxis = true;
- }
#if 0
btScalar l2 = gjkPairDetector.getCachedSeparatingAxis().length2();
if (l2>SIMD_EPSILON)
@@ -728,145 +677,131 @@ void btConvexConvexAlgorithm ::processCollision (const btCollisionObjectWrapper*
foundSepAxis = true;
}
#endif
- }
+ }
-
- if (foundSepAxis)
- {
- worldVertsB2.resize(0);
- btPolyhedralContactClipping::clipFaceAgainstHull(sepNormalWorldSpace, *polyhedronA->getConvexPolyhedron(),
- body0Wrap->getWorldTransform(), worldSpaceVertices, worldVertsB2,minDist-threshold, maxDist, *resultOut);
- }
-
-
- if (m_ownManifold)
- {
- resultOut->refreshContactPoints();
+ if (foundSepAxis)
+ {
+ worldVertsB2.resize(0);
+ btPolyhedralContactClipping::clipFaceAgainstHull(sepNormalWorldSpace, *polyhedronA->getConvexPolyhedron(),
+ body0Wrap->getWorldTransform(), worldSpaceVertices, worldVertsB2, minDist - threshold, maxDist, *resultOut);
+ }
+
+ if (m_ownManifold)
+ {
+ resultOut->refreshContactPoints();
+ }
+
+ return;
}
-
- return;
}
-
-
}
+ gjkPairDetector.getClosestPoints(input, *resultOut, dispatchInfo.m_debugDraw);
- }
-
- gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
+ //now perform 'm_numPerturbationIterations' collision queries with the perturbated collision objects
- //now perform 'm_numPerturbationIterations' collision queries with the perturbated collision objects
-
- //perform perturbation when more then 'm_minimumPointsPerturbationThreshold' points
- if (m_numPerturbationIterations && resultOut->getPersistentManifold()->getNumContacts() < m_minimumPointsPerturbationThreshold)
- {
-
- int i;
- btVector3 v0,v1;
- btVector3 sepNormalWorldSpace;
- btScalar l2 = gjkPairDetector.getCachedSeparatingAxis().length2();
-
- if (l2>SIMD_EPSILON)
+ //perform perturbation when more then 'm_minimumPointsPerturbationThreshold' points
+ if (m_numPerturbationIterations && resultOut->getPersistentManifold()->getNumContacts() < m_minimumPointsPerturbationThreshold)
{
- sepNormalWorldSpace = gjkPairDetector.getCachedSeparatingAxis()*(1.f/l2);
-
- btPlaneSpace1(sepNormalWorldSpace,v0,v1);
-
+ int i;
+ btVector3 v0, v1;
+ btVector3 sepNormalWorldSpace;
+ btScalar l2 = gjkPairDetector.getCachedSeparatingAxis().length2();
- bool perturbeA = true;
- const btScalar angleLimit = 0.125f * SIMD_PI;
- btScalar perturbeAngle;
- btScalar radiusA = min0->getAngularMotionDisc();
- btScalar radiusB = min1->getAngularMotionDisc();
- if (radiusA < radiusB)
- {
- perturbeAngle = gContactBreakingThreshold /radiusA;
- perturbeA = true;
- } else
+ if (l2 > SIMD_EPSILON)
{
- perturbeAngle = gContactBreakingThreshold / radiusB;
- perturbeA = false;
- }
- if ( perturbeAngle > angleLimit )
- perturbeAngle = angleLimit;
+ sepNormalWorldSpace = gjkPairDetector.getCachedSeparatingAxis() * (1.f / l2);
- btTransform unPerturbedTransform;
- if (perturbeA)
- {
- unPerturbedTransform = input.m_transformA;
- } else
- {
- unPerturbedTransform = input.m_transformB;
- }
-
- for ( i=0;i<m_numPerturbationIterations;i++)
- {
- if (v0.length2()>SIMD_EPSILON)
+ btPlaneSpace1(sepNormalWorldSpace, v0, v1);
+
+ bool perturbeA = true;
+ const btScalar angleLimit = 0.125f * SIMD_PI;
+ btScalar perturbeAngle;
+ btScalar radiusA = min0->getAngularMotionDisc();
+ btScalar radiusB = min1->getAngularMotionDisc();
+ if (radiusA < radiusB)
{
- btQuaternion perturbeRot(v0,perturbeAngle);
- btScalar iterationAngle = i*(SIMD_2_PI/btScalar(m_numPerturbationIterations));
- btQuaternion rotq(sepNormalWorldSpace,iterationAngle);
-
-
+ perturbeAngle = gContactBreakingThreshold / radiusA;
+ perturbeA = true;
+ }
+ else
+ {
+ perturbeAngle = gContactBreakingThreshold / radiusB;
+ perturbeA = false;
+ }
+ if (perturbeAngle > angleLimit)
+ perturbeAngle = angleLimit;
+
+ btTransform unPerturbedTransform;
if (perturbeA)
{
- input.m_transformA.setBasis( btMatrix3x3(rotq.inverse()*perturbeRot*rotq)*body0Wrap->getWorldTransform().getBasis());
- input.m_transformB = body1Wrap->getWorldTransform();
- #ifdef DEBUG_CONTACTS
- dispatchInfo.m_debugDraw->drawTransform(input.m_transformA,10.0);
- #endif //DEBUG_CONTACTS
- } else
+ unPerturbedTransform = input.m_transformA;
+ }
+ else
{
- input.m_transformA = body0Wrap->getWorldTransform();
- input.m_transformB.setBasis( btMatrix3x3(rotq.inverse()*perturbeRot*rotq)*body1Wrap->getWorldTransform().getBasis());
- #ifdef DEBUG_CONTACTS
- dispatchInfo.m_debugDraw->drawTransform(input.m_transformB,10.0);
- #endif
+ unPerturbedTransform = input.m_transformB;
}
-
- btPerturbedContactResult perturbedResultOut(resultOut,input.m_transformA,input.m_transformB,unPerturbedTransform,perturbeA,dispatchInfo.m_debugDraw);
- gjkPairDetector.getClosestPoints(input,perturbedResultOut,dispatchInfo.m_debugDraw);
+
+ for (i = 0; i < m_numPerturbationIterations; i++)
+ {
+ if (v0.length2() > SIMD_EPSILON)
+ {
+ btQuaternion perturbeRot(v0, perturbeAngle);
+ btScalar iterationAngle = i * (SIMD_2_PI / btScalar(m_numPerturbationIterations));
+ btQuaternion rotq(sepNormalWorldSpace, iterationAngle);
+
+ if (perturbeA)
+ {
+ input.m_transformA.setBasis(btMatrix3x3(rotq.inverse() * perturbeRot * rotq) * body0Wrap->getWorldTransform().getBasis());
+ input.m_transformB = body1Wrap->getWorldTransform();
+#ifdef DEBUG_CONTACTS
+ dispatchInfo.m_debugDraw->drawTransform(input.m_transformA, 10.0);
+#endif //DEBUG_CONTACTS
+ }
+ else
+ {
+ input.m_transformA = body0Wrap->getWorldTransform();
+ input.m_transformB.setBasis(btMatrix3x3(rotq.inverse() * perturbeRot * rotq) * body1Wrap->getWorldTransform().getBasis());
+#ifdef DEBUG_CONTACTS
+ dispatchInfo.m_debugDraw->drawTransform(input.m_transformB, 10.0);
+#endif
+ }
+
+ btPerturbedContactResult perturbedResultOut(resultOut, input.m_transformA, input.m_transformB, unPerturbedTransform, perturbeA, dispatchInfo.m_debugDraw);
+ gjkPairDetector.getClosestPoints(input, perturbedResultOut, dispatchInfo.m_debugDraw);
+ }
}
}
}
- }
-
-
#ifdef USE_SEPDISTANCE_UTIL2
- if (dispatchInfo.m_useConvexConservativeDistanceUtil && (sepDist>SIMD_EPSILON))
- {
- m_sepDistance.initSeparatingDistance(gjkPairDetector.getCachedSeparatingAxis(),sepDist,body0->getWorldTransform(),body1->getWorldTransform());
- }
-#endif //USE_SEPDISTANCE_UTIL2
-
-
+ if (dispatchInfo.m_useConvexConservativeDistanceUtil && (sepDist > SIMD_EPSILON))
+ {
+ m_sepDistance.initSeparatingDistance(gjkPairDetector.getCachedSeparatingAxis(), sepDist, body0->getWorldTransform(), body1->getWorldTransform());
+ }
+#endif //USE_SEPDISTANCE_UTIL2
}
if (m_ownManifold)
{
resultOut->refreshContactPoints();
}
-
}
-
-
bool disableCcd = false;
-btScalar btConvexConvexAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+btScalar btConvexConvexAlgorithm::calculateTimeOfImpact(btCollisionObject* col0, btCollisionObject* col1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
{
(void)resultOut;
(void)dispatchInfo;
///Rather then checking ALL pairs, only calculate TOI when motion exceeds threshold
-
+
///Linear motion for one of objects needs to exceed m_ccdSquareMotionThreshold
///col0->m_worldTransform,
btScalar resultFraction = btScalar(1.);
-
btScalar squareMot0 = (col0->getInterpolationWorldTransform().getOrigin() - col0->getWorldTransform().getOrigin()).length2();
btScalar squareMot1 = (col1->getInterpolationWorldTransform().getOrigin() - col1->getWorldTransform().getOrigin()).length2();
-
+
if (squareMot0 < col0->getCcdSquareMotionThreshold() &&
squareMot1 < col1->getCcdSquareMotionThreshold())
return resultFraction;
@@ -874,77 +809,65 @@ btScalar btConvexConvexAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,
if (disableCcd)
return btScalar(1.);
-
//An adhoc way of testing the Continuous Collision Detection algorithms
//One object is approximated as a sphere, to simplify things
//Starting in penetration should report no time of impact
//For proper CCD, better accuracy and handling of 'allowed' penetration should be added
//also the mainloop of the physics should have a kind of toi queue (something like Brian Mirtich's application of Timewarp for Rigidbodies)
-
/// Convex0 against sphere for Convex1
{
btConvexShape* convex0 = static_cast<btConvexShape*>(col0->getCollisionShape());
- btSphereShape sphere1(col1->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation
+ btSphereShape sphere1(col1->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation
btConvexCast::CastResult result;
btVoronoiSimplexSolver voronoiSimplex;
//SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex);
///Simplification, one object is simplified as a sphere
- btGjkConvexCast ccd1( convex0 ,&sphere1,&voronoiSimplex);
+ btGjkConvexCast ccd1(convex0, &sphere1, &voronoiSimplex);
//ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0);
- if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(),
- col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result))
+ if (ccd1.calcTimeOfImpact(col0->getWorldTransform(), col0->getInterpolationWorldTransform(),
+ col1->getWorldTransform(), col1->getInterpolationWorldTransform(), result))
{
-
//store result.m_fraction in both bodies
-
- if (col0->getHitFraction()> result.m_fraction)
- col0->setHitFraction( result.m_fraction );
+
+ if (col0->getHitFraction() > result.m_fraction)
+ col0->setHitFraction(result.m_fraction);
if (col1->getHitFraction() > result.m_fraction)
- col1->setHitFraction( result.m_fraction);
+ col1->setHitFraction(result.m_fraction);
if (resultFraction > result.m_fraction)
resultFraction = result.m_fraction;
-
}
-
-
-
-
}
/// Sphere (for convex0) against Convex1
{
btConvexShape* convex1 = static_cast<btConvexShape*>(col1->getCollisionShape());
- btSphereShape sphere0(col0->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation
+ btSphereShape sphere0(col0->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation
btConvexCast::CastResult result;
btVoronoiSimplexSolver voronoiSimplex;
//SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex);
///Simplification, one object is simplified as a sphere
- btGjkConvexCast ccd1(&sphere0,convex1,&voronoiSimplex);
+ btGjkConvexCast ccd1(&sphere0, convex1, &voronoiSimplex);
//ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0);
- if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(),
- col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result))
+ if (ccd1.calcTimeOfImpact(col0->getWorldTransform(), col0->getInterpolationWorldTransform(),
+ col1->getWorldTransform(), col1->getInterpolationWorldTransform(), result))
{
-
//store result.m_fraction in both bodies
-
- if (col0->getHitFraction() > result.m_fraction)
- col0->setHitFraction( result.m_fraction);
+
+ if (col0->getHitFraction() > result.m_fraction)
+ col0->setHitFraction(result.m_fraction);
if (col1->getHitFraction() > result.m_fraction)
- col1->setHitFraction( result.m_fraction);
+ col1->setHitFraction(result.m_fraction);
if (resultFraction > result.m_fraction)
resultFraction = result.m_fraction;
-
}
}
-
- return resultFraction;
+ return resultFraction;
}
-
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h
index cd75ba12d7..eac5b4d824 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h
@@ -23,7 +23,7 @@ subject to the following restrictions:
#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
#include "btCollisionCreateFunc.h"
#include "btCollisionDispatcher.h"
-#include "LinearMath/btTransformUtil.h" //for btConvexSeparatingDistanceUtil
+#include "LinearMath/btTransformUtil.h" //for btConvexSeparatingDistanceUtil
#include "BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h"
class btConvexPenetrationDepthSolver;
@@ -41,69 +41,61 @@ class btConvexPenetrationDepthSolver;
class btConvexConvexAlgorithm : public btActivatingCollisionAlgorithm
{
#ifdef USE_SEPDISTANCE_UTIL2
- btConvexSeparatingDistanceUtil m_sepDistance;
+ btConvexSeparatingDistanceUtil m_sepDistance;
#endif
btConvexPenetrationDepthSolver* m_pdSolver;
btVertexArray worldVertsB1;
btVertexArray worldVertsB2;
-
- bool m_ownManifold;
- btPersistentManifold* m_manifoldPtr;
- bool m_lowLevelOfDetail;
-
+
+ bool m_ownManifold;
+ btPersistentManifold* m_manifoldPtr;
+ bool m_lowLevelOfDetail;
+
int m_numPerturbationIterations;
int m_minimumPointsPerturbationThreshold;
-
///cache separating vector to speedup collision detection
-
public:
-
- btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold);
+ btConvexConvexAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold);
virtual ~btConvexConvexAlgorithm();
- virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
- virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
- virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
///should we use m_ownManifold to avoid adding duplicates?
if (m_manifoldPtr && m_ownManifold)
manifoldArray.push_back(m_manifoldPtr);
}
+ void setLowLevelOfDetail(bool useLowLevel);
- void setLowLevelOfDetail(bool useLowLevel);
-
-
- const btPersistentManifold* getManifold()
+ const btPersistentManifold* getManifold()
{
return m_manifoldPtr;
}
- struct CreateFunc :public btCollisionAlgorithmCreateFunc
+ struct CreateFunc : public btCollisionAlgorithmCreateFunc
{
-
- btConvexPenetrationDepthSolver* m_pdSolver;
+ btConvexPenetrationDepthSolver* m_pdSolver;
int m_numPerturbationIterations;
int m_minimumPointsPerturbationThreshold;
CreateFunc(btConvexPenetrationDepthSolver* pdSolver);
-
+
virtual ~CreateFunc();
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConvexAlgorithm));
- return new(mem) btConvexConvexAlgorithm(ci.m_manifold,ci,body0Wrap,body1Wrap,m_pdSolver,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold);
+ return new (mem) btConvexConvexAlgorithm(ci.m_manifold, ci, body0Wrap, body1Wrap, m_pdSolver, m_numPerturbationIterations, m_minimumPointsPerturbationThreshold);
}
};
-
-
};
-#endif //BT_CONVEX_CONVEX_ALGORITHM_H
+#endif //BT_CONVEX_CONVEX_ALGORITHM_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp
index cce2d95bcf..ba1bc06b69 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp
@@ -23,25 +23,24 @@ subject to the following restrictions:
//#include <stdio.h>
-btConvexPlaneCollisionAlgorithm::btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap, bool isSwapped, int numPerturbationIterations,int minimumPointsPerturbationThreshold)
-: btCollisionAlgorithm(ci),
-m_ownManifold(false),
-m_manifoldPtr(mf),
-m_isSwapped(isSwapped),
-m_numPerturbationIterations(numPerturbationIterations),
-m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold)
+btConvexPlaneCollisionAlgorithm::btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* col0Wrap, const btCollisionObjectWrapper* col1Wrap, bool isSwapped, int numPerturbationIterations, int minimumPointsPerturbationThreshold)
+ : btCollisionAlgorithm(ci),
+ m_ownManifold(false),
+ m_manifoldPtr(mf),
+ m_isSwapped(isSwapped),
+ m_numPerturbationIterations(numPerturbationIterations),
+ m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold)
{
- const btCollisionObjectWrapper* convexObjWrap = m_isSwapped? col1Wrap : col0Wrap;
- const btCollisionObjectWrapper* planeObjWrap = m_isSwapped? col0Wrap : col1Wrap;
+ const btCollisionObjectWrapper* convexObjWrap = m_isSwapped ? col1Wrap : col0Wrap;
+ const btCollisionObjectWrapper* planeObjWrap = m_isSwapped ? col0Wrap : col1Wrap;
- if (!m_manifoldPtr && m_dispatcher->needsCollision(convexObjWrap->getCollisionObject(),planeObjWrap->getCollisionObject()))
+ if (!m_manifoldPtr && m_dispatcher->needsCollision(convexObjWrap->getCollisionObject(), planeObjWrap->getCollisionObject()))
{
- m_manifoldPtr = m_dispatcher->getNewManifold(convexObjWrap->getCollisionObject(),planeObjWrap->getCollisionObject());
+ m_manifoldPtr = m_dispatcher->getNewManifold(convexObjWrap->getCollisionObject(), planeObjWrap->getCollisionObject());
m_ownManifold = true;
}
}
-
btConvexPlaneCollisionAlgorithm::~btConvexPlaneCollisionAlgorithm()
{
if (m_ownManifold)
@@ -51,32 +50,32 @@ btConvexPlaneCollisionAlgorithm::~btConvexPlaneCollisionAlgorithm()
}
}
-void btConvexPlaneCollisionAlgorithm::collideSingleContact (const btQuaternion& perturbeRot, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+void btConvexPlaneCollisionAlgorithm::collideSingleContact(const btQuaternion& perturbeRot, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
{
- const btCollisionObjectWrapper* convexObjWrap = m_isSwapped? body1Wrap : body0Wrap;
- const btCollisionObjectWrapper* planeObjWrap = m_isSwapped? body0Wrap: body1Wrap;
+ const btCollisionObjectWrapper* convexObjWrap = m_isSwapped ? body1Wrap : body0Wrap;
+ const btCollisionObjectWrapper* planeObjWrap = m_isSwapped ? body0Wrap : body1Wrap;
- btConvexShape* convexShape = (btConvexShape*) convexObjWrap->getCollisionShape();
- btStaticPlaneShape* planeShape = (btStaticPlaneShape*) planeObjWrap->getCollisionShape();
+ btConvexShape* convexShape = (btConvexShape*)convexObjWrap->getCollisionShape();
+ btStaticPlaneShape* planeShape = (btStaticPlaneShape*)planeObjWrap->getCollisionShape();
- bool hasCollision = false;
+ bool hasCollision = false;
const btVector3& planeNormal = planeShape->getPlaneNormal();
const btScalar& planeConstant = planeShape->getPlaneConstant();
-
+
btTransform convexWorldTransform = convexObjWrap->getWorldTransform();
btTransform convexInPlaneTrans;
- convexInPlaneTrans= planeObjWrap->getWorldTransform().inverse() * convexWorldTransform;
+ convexInPlaneTrans = planeObjWrap->getWorldTransform().inverse() * convexWorldTransform;
//now perturbe the convex-world transform
- convexWorldTransform.getBasis()*=btMatrix3x3(perturbeRot);
+ convexWorldTransform.getBasis() *= btMatrix3x3(perturbeRot);
btTransform planeInConvex;
- planeInConvex= convexWorldTransform.inverse() * planeObjWrap->getWorldTransform();
-
- btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal);
+ planeInConvex = convexWorldTransform.inverse() * planeObjWrap->getWorldTransform();
+
+ btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis() * -planeNormal);
btVector3 vtxInPlane = convexInPlaneTrans(vtx);
btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant);
- btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal;
+ btVector3 vtxInPlaneProjected = vtxInPlane - distance * planeNormal;
btVector3 vtxInPlaneWorld = planeObjWrap->getWorldTransform() * vtxInPlaneProjected;
hasCollision = distance < m_manifoldPtr->getContactBreakingThreshold();
@@ -86,70 +85,69 @@ void btConvexPlaneCollisionAlgorithm::collideSingleContact (const btQuaternion&
/// report a contact. internally this will be kept persistent, and contact reduction is done
btVector3 normalOnSurfaceB = planeObjWrap->getWorldTransform().getBasis() * planeNormal;
btVector3 pOnB = vtxInPlaneWorld;
- resultOut->addContactPoint(normalOnSurfaceB,pOnB,distance);
+ resultOut->addContactPoint(normalOnSurfaceB, pOnB, distance);
}
}
-
-void btConvexPlaneCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+void btConvexPlaneCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
{
(void)dispatchInfo;
if (!m_manifoldPtr)
return;
- const btCollisionObjectWrapper* convexObjWrap = m_isSwapped? body1Wrap : body0Wrap;
- const btCollisionObjectWrapper* planeObjWrap = m_isSwapped? body0Wrap: body1Wrap;
+ const btCollisionObjectWrapper* convexObjWrap = m_isSwapped ? body1Wrap : body0Wrap;
+ const btCollisionObjectWrapper* planeObjWrap = m_isSwapped ? body0Wrap : body1Wrap;
- btConvexShape* convexShape = (btConvexShape*) convexObjWrap->getCollisionShape();
- btStaticPlaneShape* planeShape = (btStaticPlaneShape*) planeObjWrap->getCollisionShape();
+ btConvexShape* convexShape = (btConvexShape*)convexObjWrap->getCollisionShape();
+ btStaticPlaneShape* planeShape = (btStaticPlaneShape*)planeObjWrap->getCollisionShape();
bool hasCollision = false;
const btVector3& planeNormal = planeShape->getPlaneNormal();
const btScalar& planeConstant = planeShape->getPlaneConstant();
btTransform planeInConvex;
- planeInConvex= convexObjWrap->getWorldTransform().inverse() * planeObjWrap->getWorldTransform();
+ planeInConvex = convexObjWrap->getWorldTransform().inverse() * planeObjWrap->getWorldTransform();
btTransform convexInPlaneTrans;
- convexInPlaneTrans= planeObjWrap->getWorldTransform().inverse() * convexObjWrap->getWorldTransform();
+ convexInPlaneTrans = planeObjWrap->getWorldTransform().inverse() * convexObjWrap->getWorldTransform();
- btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal);
+ btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis() * -planeNormal);
btVector3 vtxInPlane = convexInPlaneTrans(vtx);
btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant);
- btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal;
+ btVector3 vtxInPlaneProjected = vtxInPlane - distance * planeNormal;
btVector3 vtxInPlaneWorld = planeObjWrap->getWorldTransform() * vtxInPlaneProjected;
- hasCollision = distance < m_manifoldPtr->getContactBreakingThreshold();
+ hasCollision = distance < m_manifoldPtr->getContactBreakingThreshold()+ resultOut->m_closestPointDistanceThreshold;
resultOut->setPersistentManifold(m_manifoldPtr);
if (hasCollision)
{
/// report a contact. internally this will be kept persistent, and contact reduction is done
btVector3 normalOnSurfaceB = planeObjWrap->getWorldTransform().getBasis() * planeNormal;
btVector3 pOnB = vtxInPlaneWorld;
- resultOut->addContactPoint(normalOnSurfaceB,pOnB,distance);
+ resultOut->addContactPoint(normalOnSurfaceB, pOnB, distance);
}
//the perturbation algorithm doesn't work well with implicit surfaces such as spheres, cylinder and cones:
//they keep on rolling forever because of the additional off-center contact points
//so only enable the feature for polyhedral shapes (btBoxShape, btConvexHullShape etc)
- if (convexShape->isPolyhedral() && resultOut->getPersistentManifold()->getNumContacts()<m_minimumPointsPerturbationThreshold)
+ if (convexShape->isPolyhedral() && resultOut->getPersistentManifold()->getNumContacts() < m_minimumPointsPerturbationThreshold)
{
- btVector3 v0,v1;
- btPlaneSpace1(planeNormal,v0,v1);
+ btVector3 v0, v1;
+ btPlaneSpace1(planeNormal, v0, v1);
//now perform 'm_numPerturbationIterations' collision queries with the perturbated collision objects
const btScalar angleLimit = 0.125f * SIMD_PI;
btScalar perturbeAngle;
btScalar radius = convexShape->getAngularMotionDisc();
perturbeAngle = gContactBreakingThreshold / radius;
- if ( perturbeAngle > angleLimit )
- perturbeAngle = angleLimit;
+ if (perturbeAngle > angleLimit)
+ perturbeAngle = angleLimit;
- btQuaternion perturbeRot(v0,perturbeAngle);
- for (int i=0;i<m_numPerturbationIterations;i++)
+ btQuaternion perturbeRot(v0, perturbeAngle);
+ for (int i = 0; i < m_numPerturbationIterations; i++)
{
- btScalar iterationAngle = i*(SIMD_2_PI/btScalar(m_numPerturbationIterations));
- btQuaternion rotq(planeNormal,iterationAngle);
- collideSingleContact(rotq.inverse()*perturbeRot*rotq,body0Wrap,body1Wrap,dispatchInfo,resultOut);
+ btScalar iterationAngle = i * (SIMD_2_PI / btScalar(m_numPerturbationIterations));
+ btQuaternion rotq(planeNormal, iterationAngle);
+ collideSingleContact(rotq.inverse() * perturbeRot * rotq, body0Wrap, body1Wrap, dispatchInfo, resultOut);
}
}
@@ -162,7 +160,7 @@ void btConvexPlaneCollisionAlgorithm::processCollision (const btCollisionObjectW
}
}
-btScalar btConvexPlaneCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+btScalar btConvexPlaneCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0, btCollisionObject* col1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
{
(void)resultOut;
(void)dispatchInfo;
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h
index d28c430c4c..b693da118f 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h
@@ -28,25 +28,24 @@ class btPersistentManifold;
/// Other features are frame-coherency (persistent data) and collision response.
class btConvexPlaneCollisionAlgorithm : public btCollisionAlgorithm
{
- bool m_ownManifold;
- btPersistentManifold* m_manifoldPtr;
- bool m_isSwapped;
- int m_numPerturbationIterations;
- int m_minimumPointsPerturbationThreshold;
+ bool m_ownManifold;
+ btPersistentManifold* m_manifoldPtr;
+ bool m_isSwapped;
+ int m_numPerturbationIterations;
+ int m_minimumPointsPerturbationThreshold;
public:
-
- btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap, bool isSwapped, int numPerturbationIterations,int minimumPointsPerturbationThreshold);
+ btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped, int numPerturbationIterations, int minimumPointsPerturbationThreshold);
virtual ~btConvexPlaneCollisionAlgorithm();
- virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
- void collideSingleContact (const btQuaternion& perturbeRot, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ void collideSingleContact(const btQuaternion& perturbeRot, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
- virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
- virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr && m_ownManifold)
{
@@ -54,31 +53,30 @@ public:
}
}
- struct CreateFunc :public btCollisionAlgorithmCreateFunc
+ struct CreateFunc : public btCollisionAlgorithmCreateFunc
{
- int m_numPerturbationIterations;
+ int m_numPerturbationIterations;
int m_minimumPointsPerturbationThreshold;
-
- CreateFunc()
+
+ CreateFunc()
: m_numPerturbationIterations(1),
- m_minimumPointsPerturbationThreshold(0)
+ m_minimumPointsPerturbationThreshold(0)
{
}
-
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexPlaneCollisionAlgorithm));
if (!m_swapped)
{
- return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0Wrap,body1Wrap,false,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold);
- } else
+ return new (mem) btConvexPlaneCollisionAlgorithm(0, ci, body0Wrap, body1Wrap, false, m_numPerturbationIterations, m_minimumPointsPerturbationThreshold);
+ }
+ else
{
- return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0Wrap,body1Wrap,true,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold);
+ return new (mem) btConvexPlaneCollisionAlgorithm(0, ci, body0Wrap, body1Wrap, true, m_numPerturbationIterations, m_minimumPointsPerturbationThreshold);
}
}
};
-
};
-#endif //BT_CONVEX_PLANE_COLLISION_ALGORITHM_H
-
+#endif //BT_CONVEX_PLANE_COLLISION_ALGORITHM_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp
index f6e4e57b0a..ef3ea9e394 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp
@@ -26,114 +26,108 @@ subject to the following restrictions:
#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h"
#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h"
-#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
+#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
#include "BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h"
#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h"
#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
-
-
#include "LinearMath/btPoolAllocator.h"
-
-
-
-
btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo)
//btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(btStackAlloc* stackAlloc,btPoolAllocator* persistentManifoldPool,btPoolAllocator* collisionAlgorithmPool)
{
-
- void* mem = NULL;
+ void* mem = NULL;
if (constructionInfo.m_useEpaPenetrationAlgorithm)
{
- mem = btAlignedAlloc(sizeof(btGjkEpaPenetrationDepthSolver),16);
- m_pdSolver = new (mem)btGjkEpaPenetrationDepthSolver;
- }else
+ mem = btAlignedAlloc(sizeof(btGjkEpaPenetrationDepthSolver), 16);
+ m_pdSolver = new (mem) btGjkEpaPenetrationDepthSolver;
+ }
+ else
{
- mem = btAlignedAlloc(sizeof(btMinkowskiPenetrationDepthSolver),16);
- m_pdSolver = new (mem)btMinkowskiPenetrationDepthSolver;
+ mem = btAlignedAlloc(sizeof(btMinkowskiPenetrationDepthSolver), 16);
+ m_pdSolver = new (mem) btMinkowskiPenetrationDepthSolver;
}
-
+
//default CreationFunctions, filling the m_doubleDispatch table
- mem = btAlignedAlloc(sizeof(btConvexConvexAlgorithm::CreateFunc),16);
- m_convexConvexCreateFunc = new(mem) btConvexConvexAlgorithm::CreateFunc(m_pdSolver);
- mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16);
- m_convexConcaveCreateFunc = new (mem)btConvexConcaveCollisionAlgorithm::CreateFunc;
- mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16);
- m_swappedConvexConcaveCreateFunc = new (mem)btConvexConcaveCollisionAlgorithm::SwappedCreateFunc;
- mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::CreateFunc),16);
- m_compoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::CreateFunc;
-
- mem = btAlignedAlloc(sizeof(btCompoundCompoundCollisionAlgorithm::CreateFunc),16);
- m_compoundCompoundCreateFunc = new (mem)btCompoundCompoundCollisionAlgorithm::CreateFunc;
-
- mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::SwappedCreateFunc),16);
- m_swappedCompoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::SwappedCreateFunc;
- mem = btAlignedAlloc(sizeof(btEmptyAlgorithm::CreateFunc),16);
- m_emptyCreateFunc = new(mem) btEmptyAlgorithm::CreateFunc;
-
- mem = btAlignedAlloc(sizeof(btSphereSphereCollisionAlgorithm::CreateFunc),16);
- m_sphereSphereCF = new(mem) btSphereSphereCollisionAlgorithm::CreateFunc;
+ mem = btAlignedAlloc(sizeof(btConvexConvexAlgorithm::CreateFunc), 16);
+ m_convexConvexCreateFunc = new (mem) btConvexConvexAlgorithm::CreateFunc(m_pdSolver);
+ mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc), 16);
+ m_convexConcaveCreateFunc = new (mem) btConvexConcaveCollisionAlgorithm::CreateFunc;
+ mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc), 16);
+ m_swappedConvexConcaveCreateFunc = new (mem) btConvexConcaveCollisionAlgorithm::SwappedCreateFunc;
+ mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::CreateFunc), 16);
+ m_compoundCreateFunc = new (mem) btCompoundCollisionAlgorithm::CreateFunc;
+
+ mem = btAlignedAlloc(sizeof(btCompoundCompoundCollisionAlgorithm::CreateFunc), 16);
+ m_compoundCompoundCreateFunc = new (mem) btCompoundCompoundCollisionAlgorithm::CreateFunc;
+
+ mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::SwappedCreateFunc), 16);
+ m_swappedCompoundCreateFunc = new (mem) btCompoundCollisionAlgorithm::SwappedCreateFunc;
+ mem = btAlignedAlloc(sizeof(btEmptyAlgorithm::CreateFunc), 16);
+ m_emptyCreateFunc = new (mem) btEmptyAlgorithm::CreateFunc;
+
+ mem = btAlignedAlloc(sizeof(btSphereSphereCollisionAlgorithm::CreateFunc), 16);
+ m_sphereSphereCF = new (mem) btSphereSphereCollisionAlgorithm::CreateFunc;
#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
- mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16);
- m_sphereBoxCF = new(mem) btSphereBoxCollisionAlgorithm::CreateFunc;
- mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16);
- m_boxSphereCF = new (mem)btSphereBoxCollisionAlgorithm::CreateFunc;
+ mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc), 16);
+ m_sphereBoxCF = new (mem) btSphereBoxCollisionAlgorithm::CreateFunc;
+ mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc), 16);
+ m_boxSphereCF = new (mem) btSphereBoxCollisionAlgorithm::CreateFunc;
m_boxSphereCF->m_swapped = true;
-#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
+#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
- mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16);
- m_sphereTriangleCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc;
- mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16);
- m_triangleSphereCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc;
+ mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc), 16);
+ m_sphereTriangleCF = new (mem) btSphereTriangleCollisionAlgorithm::CreateFunc;
+ mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc), 16);
+ m_triangleSphereCF = new (mem) btSphereTriangleCollisionAlgorithm::CreateFunc;
m_triangleSphereCF->m_swapped = true;
-
- mem = btAlignedAlloc(sizeof(btBoxBoxCollisionAlgorithm::CreateFunc),16);
- m_boxBoxCF = new(mem)btBoxBoxCollisionAlgorithm::CreateFunc;
+
+ mem = btAlignedAlloc(sizeof(btBoxBoxCollisionAlgorithm::CreateFunc), 16);
+ m_boxBoxCF = new (mem) btBoxBoxCollisionAlgorithm::CreateFunc;
//convex versus plane
- mem = btAlignedAlloc (sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc),16);
+ mem = btAlignedAlloc(sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc), 16);
m_convexPlaneCF = new (mem) btConvexPlaneCollisionAlgorithm::CreateFunc;
- mem = btAlignedAlloc (sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc),16);
+ mem = btAlignedAlloc(sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc), 16);
m_planeConvexCF = new (mem) btConvexPlaneCollisionAlgorithm::CreateFunc;
m_planeConvexCF->m_swapped = true;
-
+
///calculate maximum element size, big enough to fit any collision algorithm in the memory pool
int maxSize = sizeof(btConvexConvexAlgorithm);
int maxSize2 = sizeof(btConvexConcaveCollisionAlgorithm);
int maxSize3 = sizeof(btCompoundCollisionAlgorithm);
int maxSize4 = sizeof(btCompoundCompoundCollisionAlgorithm);
- int collisionAlgorithmMaxElementSize = btMax(maxSize,constructionInfo.m_customCollisionAlgorithmMaxElementSize);
- collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize2);
- collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize3);
- collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize4);
-
+ int collisionAlgorithmMaxElementSize = btMax(maxSize, constructionInfo.m_customCollisionAlgorithmMaxElementSize);
+ collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize, maxSize2);
+ collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize, maxSize3);
+ collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize, maxSize4);
+
if (constructionInfo.m_persistentManifoldPool)
{
m_ownsPersistentManifoldPool = false;
m_persistentManifoldPool = constructionInfo.m_persistentManifoldPool;
- } else
+ }
+ else
{
m_ownsPersistentManifoldPool = true;
- void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16);
- m_persistentManifoldPool = new (mem) btPoolAllocator(sizeof(btPersistentManifold),constructionInfo.m_defaultMaxPersistentManifoldPoolSize);
+ void* mem = btAlignedAlloc(sizeof(btPoolAllocator), 16);
+ m_persistentManifoldPool = new (mem) btPoolAllocator(sizeof(btPersistentManifold), constructionInfo.m_defaultMaxPersistentManifoldPoolSize);
}
-
- collisionAlgorithmMaxElementSize = (collisionAlgorithmMaxElementSize+16)&0xffffffffffff0;
+
+ collisionAlgorithmMaxElementSize = (collisionAlgorithmMaxElementSize + 16) & 0xffffffffffff0;
if (constructionInfo.m_collisionAlgorithmPool)
{
m_ownsCollisionAlgorithmPool = false;
m_collisionAlgorithmPool = constructionInfo.m_collisionAlgorithmPool;
- } else
+ }
+ else
{
m_ownsCollisionAlgorithmPool = true;
- void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16);
- m_collisionAlgorithmPool = new(mem) btPoolAllocator(collisionAlgorithmMaxElementSize,constructionInfo.m_defaultMaxCollisionAlgorithmPoolSize);
+ void* mem = btAlignedAlloc(sizeof(btPoolAllocator), 16);
+ m_collisionAlgorithmPool = new (mem) btPoolAllocator(collisionAlgorithmMaxElementSize, constructionInfo.m_defaultMaxCollisionAlgorithmPoolSize);
}
-
-
}
btDefaultCollisionConfiguration::~btDefaultCollisionConfiguration()
@@ -150,83 +144,78 @@ btDefaultCollisionConfiguration::~btDefaultCollisionConfiguration()
}
m_convexConvexCreateFunc->~btCollisionAlgorithmCreateFunc();
- btAlignedFree( m_convexConvexCreateFunc);
+ btAlignedFree(m_convexConvexCreateFunc);
m_convexConcaveCreateFunc->~btCollisionAlgorithmCreateFunc();
- btAlignedFree( m_convexConcaveCreateFunc);
+ btAlignedFree(m_convexConcaveCreateFunc);
m_swappedConvexConcaveCreateFunc->~btCollisionAlgorithmCreateFunc();
- btAlignedFree( m_swappedConvexConcaveCreateFunc);
+ btAlignedFree(m_swappedConvexConcaveCreateFunc);
m_compoundCreateFunc->~btCollisionAlgorithmCreateFunc();
- btAlignedFree( m_compoundCreateFunc);
+ btAlignedFree(m_compoundCreateFunc);
m_compoundCompoundCreateFunc->~btCollisionAlgorithmCreateFunc();
btAlignedFree(m_compoundCompoundCreateFunc);
m_swappedCompoundCreateFunc->~btCollisionAlgorithmCreateFunc();
- btAlignedFree( m_swappedCompoundCreateFunc);
+ btAlignedFree(m_swappedCompoundCreateFunc);
m_emptyCreateFunc->~btCollisionAlgorithmCreateFunc();
- btAlignedFree( m_emptyCreateFunc);
+ btAlignedFree(m_emptyCreateFunc);
m_sphereSphereCF->~btCollisionAlgorithmCreateFunc();
- btAlignedFree( m_sphereSphereCF);
+ btAlignedFree(m_sphereSphereCF);
#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
m_sphereBoxCF->~btCollisionAlgorithmCreateFunc();
- btAlignedFree( m_sphereBoxCF);
+ btAlignedFree(m_sphereBoxCF);
m_boxSphereCF->~btCollisionAlgorithmCreateFunc();
- btAlignedFree( m_boxSphereCF);
-#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
+ btAlignedFree(m_boxSphereCF);
+#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
m_sphereTriangleCF->~btCollisionAlgorithmCreateFunc();
- btAlignedFree( m_sphereTriangleCF);
+ btAlignedFree(m_sphereTriangleCF);
m_triangleSphereCF->~btCollisionAlgorithmCreateFunc();
- btAlignedFree( m_triangleSphereCF);
+ btAlignedFree(m_triangleSphereCF);
m_boxBoxCF->~btCollisionAlgorithmCreateFunc();
- btAlignedFree( m_boxBoxCF);
+ btAlignedFree(m_boxBoxCF);
m_convexPlaneCF->~btCollisionAlgorithmCreateFunc();
- btAlignedFree( m_convexPlaneCF);
+ btAlignedFree(m_convexPlaneCF);
m_planeConvexCF->~btCollisionAlgorithmCreateFunc();
- btAlignedFree( m_planeConvexCF);
+ btAlignedFree(m_planeConvexCF);
m_pdSolver->~btConvexPenetrationDepthSolver();
-
- btAlignedFree(m_pdSolver);
-
+ btAlignedFree(m_pdSolver);
}
btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getClosestPointsAlgorithmCreateFunc(int proxyType0, int proxyType1)
{
-
-
if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1 == SPHERE_SHAPE_PROXYTYPE))
{
- return m_sphereSphereCF;
+ return m_sphereSphereCF;
}
#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1 == BOX_SHAPE_PROXYTYPE))
{
- return m_sphereBoxCF;
+ return m_sphereBoxCF;
}
if ((proxyType0 == BOX_SHAPE_PROXYTYPE) && (proxyType1 == SPHERE_SHAPE_PROXYTYPE))
{
- return m_boxSphereCF;
+ return m_boxSphereCF;
}
-#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
-
+#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1 == TRIANGLE_SHAPE_PROXYTYPE))
{
- return m_sphereTriangleCF;
+ return m_sphereTriangleCF;
}
if ((proxyType0 == TRIANGLE_SHAPE_PROXYTYPE) && (proxyType1 == SPHERE_SHAPE_PROXYTYPE))
{
- return m_triangleSphereCF;
+ return m_triangleSphereCF;
}
if (btBroadphaseProxy::isConvex(proxyType0) && (proxyType1 == STATIC_PLANE_PROXYTYPE))
@@ -239,8 +228,6 @@ btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getClosestPoint
return m_planeConvexCF;
}
-
-
if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConvex(proxyType1))
{
return m_convexConvexCreateFunc;
@@ -256,7 +243,6 @@ btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getClosestPoint
return m_swappedConvexConcaveCreateFunc;
}
-
if (btBroadphaseProxy::isCompound(proxyType0) && btBroadphaseProxy::isCompound(proxyType1))
{
return m_compoundCompoundCreateFunc;
@@ -276,46 +262,41 @@ btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getClosestPoint
//failed to find an algorithm
return m_emptyCreateFunc;
-
}
-btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1)
+btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0, int proxyType1)
{
-
-
-
- if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1==SPHERE_SHAPE_PROXYTYPE))
+ if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1 == SPHERE_SHAPE_PROXYTYPE))
{
- return m_sphereSphereCF;
+ return m_sphereSphereCF;
}
#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
- if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1==BOX_SHAPE_PROXYTYPE))
+ if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1 == BOX_SHAPE_PROXYTYPE))
{
- return m_sphereBoxCF;
+ return m_sphereBoxCF;
}
- if ((proxyType0 == BOX_SHAPE_PROXYTYPE ) && (proxyType1==SPHERE_SHAPE_PROXYTYPE))
+ if ((proxyType0 == BOX_SHAPE_PROXYTYPE) && (proxyType1 == SPHERE_SHAPE_PROXYTYPE))
{
- return m_boxSphereCF;
+ return m_boxSphereCF;
}
-#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
-
+#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
- if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE ) && (proxyType1==TRIANGLE_SHAPE_PROXYTYPE))
+ if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1 == TRIANGLE_SHAPE_PROXYTYPE))
{
- return m_sphereTriangleCF;
+ return m_sphereTriangleCF;
}
- if ((proxyType0 == TRIANGLE_SHAPE_PROXYTYPE ) && (proxyType1==SPHERE_SHAPE_PROXYTYPE))
+ if ((proxyType0 == TRIANGLE_SHAPE_PROXYTYPE) && (proxyType1 == SPHERE_SHAPE_PROXYTYPE))
{
- return m_triangleSphereCF;
- }
+ return m_triangleSphereCF;
+ }
if ((proxyType0 == BOX_SHAPE_PROXYTYPE) && (proxyType1 == BOX_SHAPE_PROXYTYPE))
{
return m_boxBoxCF;
}
-
+
if (btBroadphaseProxy::isConvex(proxyType0) && (proxyType1 == STATIC_PLANE_PROXYTYPE))
{
return m_convexPlaneCF;
@@ -325,8 +306,6 @@ btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlg
{
return m_planeConvexCF;
}
-
-
if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConvex(proxyType1))
{
@@ -343,7 +322,6 @@ btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlg
return m_swappedConvexConcaveCreateFunc;
}
-
if (btBroadphaseProxy::isCompound(proxyType0) && btBroadphaseProxy::isCompound(proxyType1))
{
return m_compoundCompoundCreateFunc;
@@ -352,7 +330,8 @@ btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlg
if (btBroadphaseProxy::isCompound(proxyType0))
{
return m_compoundCreateFunc;
- } else
+ }
+ else
{
if (btBroadphaseProxy::isCompound(proxyType1))
{
@@ -366,17 +345,17 @@ btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlg
void btDefaultCollisionConfiguration::setConvexConvexMultipointIterations(int numPerturbationIterations, int minimumPointsPerturbationThreshold)
{
- btConvexConvexAlgorithm::CreateFunc* convexConvex = (btConvexConvexAlgorithm::CreateFunc*) m_convexConvexCreateFunc;
+ btConvexConvexAlgorithm::CreateFunc* convexConvex = (btConvexConvexAlgorithm::CreateFunc*)m_convexConvexCreateFunc;
convexConvex->m_numPerturbationIterations = numPerturbationIterations;
convexConvex->m_minimumPointsPerturbationThreshold = minimumPointsPerturbationThreshold;
}
-void btDefaultCollisionConfiguration::setPlaneConvexMultipointIterations(int numPerturbationIterations, int minimumPointsPerturbationThreshold)
+void btDefaultCollisionConfiguration::setPlaneConvexMultipointIterations(int numPerturbationIterations, int minimumPointsPerturbationThreshold)
{
btConvexPlaneCollisionAlgorithm::CreateFunc* cpCF = (btConvexPlaneCollisionAlgorithm::CreateFunc*)m_convexPlaneCF;
cpCF->m_numPerturbationIterations = numPerturbationIterations;
cpCF->m_minimumPointsPerturbationThreshold = minimumPointsPerturbationThreshold;
-
+
btConvexPlaneCollisionAlgorithm::CreateFunc* pcCF = (btConvexPlaneCollisionAlgorithm::CreateFunc*)m_planeConvexCF;
pcCF->m_numPerturbationIterations = numPerturbationIterations;
pcCF->m_minimumPointsPerturbationThreshold = minimumPointsPerturbationThreshold;
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h
index 17c7596cff..b39a3f41de 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h
@@ -20,76 +20,68 @@ subject to the following restrictions:
class btVoronoiSimplexSolver;
class btConvexPenetrationDepthSolver;
-struct btDefaultCollisionConstructionInfo
+struct btDefaultCollisionConstructionInfo
{
- btPoolAllocator* m_persistentManifoldPool;
- btPoolAllocator* m_collisionAlgorithmPool;
- int m_defaultMaxPersistentManifoldPoolSize;
- int m_defaultMaxCollisionAlgorithmPoolSize;
- int m_customCollisionAlgorithmMaxElementSize;
- int m_useEpaPenetrationAlgorithm;
+ btPoolAllocator* m_persistentManifoldPool;
+ btPoolAllocator* m_collisionAlgorithmPool;
+ int m_defaultMaxPersistentManifoldPoolSize;
+ int m_defaultMaxCollisionAlgorithmPoolSize;
+ int m_customCollisionAlgorithmMaxElementSize;
+ int m_useEpaPenetrationAlgorithm;
btDefaultCollisionConstructionInfo()
- :m_persistentManifoldPool(0),
- m_collisionAlgorithmPool(0),
- m_defaultMaxPersistentManifoldPoolSize(4096),
- m_defaultMaxCollisionAlgorithmPoolSize(4096),
- m_customCollisionAlgorithmMaxElementSize(0),
- m_useEpaPenetrationAlgorithm(true)
+ : m_persistentManifoldPool(0),
+ m_collisionAlgorithmPool(0),
+ m_defaultMaxPersistentManifoldPoolSize(4096),
+ m_defaultMaxCollisionAlgorithmPoolSize(4096),
+ m_customCollisionAlgorithmMaxElementSize(0),
+ m_useEpaPenetrationAlgorithm(true)
{
}
};
-
-
///btCollisionConfiguration allows to configure Bullet collision detection
///stack allocator, pool memory allocators
///@todo: describe the meaning
-class btDefaultCollisionConfiguration : public btCollisionConfiguration
+class btDefaultCollisionConfiguration : public btCollisionConfiguration
{
-
protected:
+ int m_persistentManifoldPoolSize;
- int m_persistentManifoldPoolSize;
-
-
- btPoolAllocator* m_persistentManifoldPool;
- bool m_ownsPersistentManifoldPool;
+ btPoolAllocator* m_persistentManifoldPool;
+ bool m_ownsPersistentManifoldPool;
-
- btPoolAllocator* m_collisionAlgorithmPool;
- bool m_ownsCollisionAlgorithmPool;
+ btPoolAllocator* m_collisionAlgorithmPool;
+ bool m_ownsCollisionAlgorithmPool;
//default penetration depth solver
- btConvexPenetrationDepthSolver* m_pdSolver;
-
+ btConvexPenetrationDepthSolver* m_pdSolver;
+
//default CreationFunctions, filling the m_doubleDispatch table
- btCollisionAlgorithmCreateFunc* m_convexConvexCreateFunc;
- btCollisionAlgorithmCreateFunc* m_convexConcaveCreateFunc;
- btCollisionAlgorithmCreateFunc* m_swappedConvexConcaveCreateFunc;
- btCollisionAlgorithmCreateFunc* m_compoundCreateFunc;
- btCollisionAlgorithmCreateFunc* m_compoundCompoundCreateFunc;
-
- btCollisionAlgorithmCreateFunc* m_swappedCompoundCreateFunc;
+ btCollisionAlgorithmCreateFunc* m_convexConvexCreateFunc;
+ btCollisionAlgorithmCreateFunc* m_convexConcaveCreateFunc;
+ btCollisionAlgorithmCreateFunc* m_swappedConvexConcaveCreateFunc;
+ btCollisionAlgorithmCreateFunc* m_compoundCreateFunc;
+ btCollisionAlgorithmCreateFunc* m_compoundCompoundCreateFunc;
+
+ btCollisionAlgorithmCreateFunc* m_swappedCompoundCreateFunc;
btCollisionAlgorithmCreateFunc* m_emptyCreateFunc;
btCollisionAlgorithmCreateFunc* m_sphereSphereCF;
btCollisionAlgorithmCreateFunc* m_sphereBoxCF;
btCollisionAlgorithmCreateFunc* m_boxSphereCF;
btCollisionAlgorithmCreateFunc* m_boxBoxCF;
- btCollisionAlgorithmCreateFunc* m_sphereTriangleCF;
- btCollisionAlgorithmCreateFunc* m_triangleSphereCF;
- btCollisionAlgorithmCreateFunc* m_planeConvexCF;
- btCollisionAlgorithmCreateFunc* m_convexPlaneCF;
-
-public:
-
+ btCollisionAlgorithmCreateFunc* m_sphereTriangleCF;
+ btCollisionAlgorithmCreateFunc* m_triangleSphereCF;
+ btCollisionAlgorithmCreateFunc* m_planeConvexCF;
+ btCollisionAlgorithmCreateFunc* m_convexPlaneCF;
+public:
btDefaultCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo = btDefaultCollisionConstructionInfo());
virtual ~btDefaultCollisionConfiguration();
- ///memory pools
+ ///memory pools
virtual btPoolAllocator* getPersistentManifoldPool()
{
return m_persistentManifoldPool;
@@ -100,8 +92,7 @@ public:
return m_collisionAlgorithmPool;
}
-
- virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1);
+ virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0, int proxyType1);
virtual btCollisionAlgorithmCreateFunc* getClosestPointsAlgorithmCreateFunc(int proxyType0, int proxyType1);
@@ -112,11 +103,9 @@ public:
///3 is a good value for both params, if you want to enable the feature. This is because the default contact cache contains a maximum of 4 points, and one collision query at the unperturbed orientation is performed first.
///See Bullet/Demos/CollisionDemo for an example how this feature gathers multiple points.
///@todo we could add a per-object setting of those parameters, for level-of-detail collision detection.
- void setConvexConvexMultipointIterations(int numPerturbationIterations=3, int minimumPointsPerturbationThreshold = 3);
-
- void setPlaneConvexMultipointIterations(int numPerturbationIterations=3, int minimumPointsPerturbationThreshold = 3);
+ void setConvexConvexMultipointIterations(int numPerturbationIterations = 3, int minimumPointsPerturbationThreshold = 3);
+ void setPlaneConvexMultipointIterations(int numPerturbationIterations = 3, int minimumPointsPerturbationThreshold = 3);
};
-#endif //BT_DEFAULT_COLLISION_CONFIGURATION
-
+#endif //BT_DEFAULT_COLLISION_CONFIGURATION
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp
index 5fa1c8be5e..7cd41bdb33 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp
@@ -15,20 +15,16 @@ subject to the following restrictions:
#include "btEmptyCollisionAlgorithm.h"
-
-
btEmptyAlgorithm::btEmptyAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
: btCollisionAlgorithm(ci)
{
}
-void btEmptyAlgorithm::processCollision (const btCollisionObjectWrapper* ,const btCollisionObjectWrapper* ,const btDispatcherInfo& ,btManifoldResult* )
+void btEmptyAlgorithm::processCollision(const btCollisionObjectWrapper*, const btCollisionObjectWrapper*, const btDispatcherInfo&, btManifoldResult*)
{
}
-btScalar btEmptyAlgorithm::calculateTimeOfImpact(btCollisionObject* ,btCollisionObject* ,const btDispatcherInfo& ,btManifoldResult* )
+btScalar btEmptyAlgorithm::calculateTimeOfImpact(btCollisionObject*, btCollisionObject*, const btDispatcherInfo&, btManifoldResult*)
{
return btScalar(1.);
}
-
-
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h
index cb0f152183..65ef83e094 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h
@@ -25,30 +25,28 @@ subject to the following restrictions:
///The dispatcher can dispatch a persistent btEmptyAlgorithm to avoid a search every frame.
class btEmptyAlgorithm : public btCollisionAlgorithm
{
-
public:
-
btEmptyAlgorithm(const btCollisionAlgorithmConstructionInfo& ci);
- virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
- virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
- virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
}
- struct CreateFunc :public btCollisionAlgorithmCreateFunc
+ struct CreateFunc : public btCollisionAlgorithmCreateFunc
{
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
- {
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
+ {
(void)body0Wrap;
(void)body1Wrap;
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btEmptyAlgorithm));
- return new(mem) btEmptyAlgorithm(ci);
+ return new (mem) btEmptyAlgorithm(ci);
}
};
} ATTRIBUTE_ALIGNED(16);
-#endif //BT_EMPTY_ALGORITH
+#endif //BT_EMPTY_ALGORITH
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btGhostObject.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btGhostObject.cpp
index 86141fa689..00f16fd0a8 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btGhostObject.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btGhostObject.cpp
@@ -29,60 +29,58 @@ btGhostObject::~btGhostObject()
btAssert(!m_overlappingObjects.size());
}
-
-void btGhostObject::addOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btBroadphaseProxy* thisProxy)
+void btGhostObject::addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy)
{
btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
btAssert(otherObject);
///if this linearSearch becomes too slow (too many overlapping objects) we should add a more appropriate data structure
int index = m_overlappingObjects.findLinearSearch(otherObject);
- if (index==m_overlappingObjects.size())
+ if (index == m_overlappingObjects.size())
{
//not found
m_overlappingObjects.push_back(otherObject);
}
}
-void btGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy)
+void btGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btDispatcher* dispatcher, btBroadphaseProxy* thisProxy)
{
btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
btAssert(otherObject);
int index = m_overlappingObjects.findLinearSearch(otherObject);
- if (index<m_overlappingObjects.size())
+ if (index < m_overlappingObjects.size())
{
- m_overlappingObjects[index] = m_overlappingObjects[m_overlappingObjects.size()-1];
+ m_overlappingObjects[index] = m_overlappingObjects[m_overlappingObjects.size() - 1];
m_overlappingObjects.pop_back();
}
}
-
btPairCachingGhostObject::btPairCachingGhostObject()
{
- m_hashPairCache = new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache();
+ m_hashPairCache = new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache), 16)) btHashedOverlappingPairCache();
}
btPairCachingGhostObject::~btPairCachingGhostObject()
{
m_hashPairCache->~btHashedOverlappingPairCache();
- btAlignedFree( m_hashPairCache );
+ btAlignedFree(m_hashPairCache);
}
-void btPairCachingGhostObject::addOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btBroadphaseProxy* thisProxy)
+void btPairCachingGhostObject::addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy)
{
- btBroadphaseProxy*actualThisProxy = thisProxy ? thisProxy : getBroadphaseHandle();
+ btBroadphaseProxy* actualThisProxy = thisProxy ? thisProxy : getBroadphaseHandle();
btAssert(actualThisProxy);
btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
btAssert(otherObject);
int index = m_overlappingObjects.findLinearSearch(otherObject);
- if (index==m_overlappingObjects.size())
+ if (index == m_overlappingObjects.size())
{
m_overlappingObjects.push_back(otherObject);
- m_hashPairCache->addOverlappingPair(actualThisProxy,otherProxy);
+ m_hashPairCache->addOverlappingPair(actualThisProxy, otherProxy);
}
}
-void btPairCachingGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy1)
+void btPairCachingGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btDispatcher* dispatcher, btBroadphaseProxy* thisProxy1)
{
btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
btBroadphaseProxy* actualThisProxy = thisProxy1 ? thisProxy1 : getBroadphaseHandle();
@@ -90,82 +88,79 @@ void btPairCachingGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy
btAssert(otherObject);
int index = m_overlappingObjects.findLinearSearch(otherObject);
- if (index<m_overlappingObjects.size())
+ if (index < m_overlappingObjects.size())
{
- m_overlappingObjects[index] = m_overlappingObjects[m_overlappingObjects.size()-1];
+ m_overlappingObjects[index] = m_overlappingObjects[m_overlappingObjects.size() - 1];
m_overlappingObjects.pop_back();
- m_hashPairCache->removeOverlappingPair(actualThisProxy,otherProxy,dispatcher);
+ m_hashPairCache->removeOverlappingPair(actualThisProxy, otherProxy, dispatcher);
}
}
-
-void btGhostObject::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration) const
+void btGhostObject::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration) const
{
- btTransform convexFromTrans,convexToTrans;
+ btTransform convexFromTrans, convexToTrans;
convexFromTrans = convexFromWorld;
convexToTrans = convexToWorld;
btVector3 castShapeAabbMin, castShapeAabbMax;
/* Compute AABB that encompasses angular movement */
{
btVector3 linVel, angVel;
- btTransformUtil::calculateVelocity (convexFromTrans, convexToTrans, 1.0, linVel, angVel);
+ btTransformUtil::calculateVelocity(convexFromTrans, convexToTrans, 1.0, linVel, angVel);
btTransform R;
- R.setIdentity ();
- R.setRotation (convexFromTrans.getRotation());
- castShape->calculateTemporalAabb (R, linVel, angVel, 1.0, castShapeAabbMin, castShapeAabbMax);
+ R.setIdentity();
+ R.setRotation(convexFromTrans.getRotation());
+ castShape->calculateTemporalAabb(R, linVel, angVel, 1.0, castShapeAabbMin, castShapeAabbMax);
}
/// go over all objects, and if the ray intersects their aabb + cast shape aabb,
// do a ray-shape query using convexCaster (CCD)
int i;
- for (i=0;i<m_overlappingObjects.size();i++)
+ for (i = 0; i < m_overlappingObjects.size(); i++)
{
- btCollisionObject* collisionObject= m_overlappingObjects[i];
+ btCollisionObject* collisionObject = m_overlappingObjects[i];
//only perform raycast if filterMask matches
- if(resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) {
+ if (resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
+ {
//RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
- btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
- collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
- AabbExpand (collisionObjectAabbMin, collisionObjectAabbMax, castShapeAabbMin, castShapeAabbMax);
- btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing
+ btVector3 collisionObjectAabbMin, collisionObjectAabbMax;
+ collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(), collisionObjectAabbMin, collisionObjectAabbMax);
+ AabbExpand(collisionObjectAabbMin, collisionObjectAabbMax, castShapeAabbMin, castShapeAabbMax);
+ btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing
btVector3 hitNormal;
- if (btRayAabb(convexFromWorld.getOrigin(),convexToWorld.getOrigin(),collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal))
+ if (btRayAabb(convexFromWorld.getOrigin(), convexToWorld.getOrigin(), collisionObjectAabbMin, collisionObjectAabbMax, hitLambda, hitNormal))
{
- btCollisionWorld::objectQuerySingle(castShape, convexFromTrans,convexToTrans,
- collisionObject,
- collisionObject->getCollisionShape(),
- collisionObject->getWorldTransform(),
- resultCallback,
- allowedCcdPenetration);
+ btCollisionWorld::objectQuerySingle(castShape, convexFromTrans, convexToTrans,
+ collisionObject,
+ collisionObject->getCollisionShape(),
+ collisionObject->getWorldTransform(),
+ resultCallback,
+ allowedCcdPenetration);
}
}
}
-
}
-void btGhostObject::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const
+void btGhostObject::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const
{
btTransform rayFromTrans;
rayFromTrans.setIdentity();
rayFromTrans.setOrigin(rayFromWorld);
- btTransform rayToTrans;
+ btTransform rayToTrans;
rayToTrans.setIdentity();
rayToTrans.setOrigin(rayToWorld);
-
int i;
- for (i=0;i<m_overlappingObjects.size();i++)
+ for (i = 0; i < m_overlappingObjects.size(); i++)
{
- btCollisionObject* collisionObject= m_overlappingObjects[i];
+ btCollisionObject* collisionObject = m_overlappingObjects[i];
//only perform raycast if filterMask matches
- if(resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
+ if (resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
{
- btCollisionWorld::rayTestSingle(rayFromTrans,rayToTrans,
- collisionObject,
- collisionObject->getCollisionShape(),
- collisionObject->getWorldTransform(),
- resultCallback);
+ btCollisionWorld::rayTestSingle(rayFromTrans, rayToTrans,
+ collisionObject,
+ collisionObject->getCollisionShape(),
+ collisionObject->getWorldTransform(),
+ resultCallback);
}
}
}
-
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btGhostObject.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btGhostObject.h
index 8ec8613857..aa7f48d5cb 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btGhostObject.h
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btGhostObject.h
@@ -16,7 +16,6 @@ subject to the following restrictions:
#ifndef BT_GHOST_OBJECT_H
#define BT_GHOST_OBJECT_H
-
#include "btCollisionObject.h"
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h"
#include "LinearMath/btAlignedAllocator.h"
@@ -31,48 +30,47 @@ class btDispatcher;
///By default, this overlap is based on the AABB
///This is useful for creating a character controller, collision sensors/triggers, explosions etc.
///We plan on adding rayTest and other queries for the btGhostObject
-ATTRIBUTE_ALIGNED16(class) btGhostObject : public btCollisionObject
+ATTRIBUTE_ALIGNED16(class)
+btGhostObject : public btCollisionObject
{
protected:
-
btAlignedObjectArray<btCollisionObject*> m_overlappingObjects;
public:
-
btGhostObject();
virtual ~btGhostObject();
- void convexSweepTest(const class btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration = 0.f) const;
+ void convexSweepTest(const class btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration = 0.f) const;
- void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const;
+ void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const;
///this method is mainly for expert/internal use only.
- virtual void addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy=0);
+ virtual void addOverlappingObjectInternal(btBroadphaseProxy * otherProxy, btBroadphaseProxy* thisProxy = 0);
///this method is mainly for expert/internal use only.
- virtual void removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy=0);
+ virtual void removeOverlappingObjectInternal(btBroadphaseProxy * otherProxy, btDispatcher * dispatcher, btBroadphaseProxy* thisProxy = 0);
- int getNumOverlappingObjects() const
+ int getNumOverlappingObjects() const
{
return m_overlappingObjects.size();
}
- btCollisionObject* getOverlappingObject(int index)
+ btCollisionObject* getOverlappingObject(int index)
{
return m_overlappingObjects[index];
}
- const btCollisionObject* getOverlappingObject(int index) const
+ const btCollisionObject* getOverlappingObject(int index) const
{
return m_overlappingObjects[index];
}
- btAlignedObjectArray<btCollisionObject*>& getOverlappingPairs()
+ btAlignedObjectArray<btCollisionObject*>& getOverlappingPairs()
{
return m_overlappingObjects;
}
- const btAlignedObjectArray<btCollisionObject*> getOverlappingPairs() const
+ const btAlignedObjectArray<btCollisionObject*> getOverlappingPairs() const
{
return m_overlappingObjects;
}
@@ -81,49 +79,43 @@ public:
// internal cast
//
- static const btGhostObject* upcast(const btCollisionObject* colObj)
+ static const btGhostObject* upcast(const btCollisionObject* colObj)
{
- if (colObj->getInternalType()==CO_GHOST_OBJECT)
+ if (colObj->getInternalType() == CO_GHOST_OBJECT)
return (const btGhostObject*)colObj;
return 0;
}
- static btGhostObject* upcast(btCollisionObject* colObj)
+ static btGhostObject* upcast(btCollisionObject * colObj)
{
- if (colObj->getInternalType()==CO_GHOST_OBJECT)
+ if (colObj->getInternalType() == CO_GHOST_OBJECT)
return (btGhostObject*)colObj;
return 0;
}
-
};
-class btPairCachingGhostObject : public btGhostObject
+class btPairCachingGhostObject : public btGhostObject
{
- btHashedOverlappingPairCache* m_hashPairCache;
+ btHashedOverlappingPairCache* m_hashPairCache;
public:
-
btPairCachingGhostObject();
virtual ~btPairCachingGhostObject();
///this method is mainly for expert/internal use only.
- virtual void addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy=0);
+ virtual void addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy = 0);
- virtual void removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy=0);
+ virtual void removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btDispatcher* dispatcher, btBroadphaseProxy* thisProxy = 0);
- btHashedOverlappingPairCache* getOverlappingPairCache()
+ btHashedOverlappingPairCache* getOverlappingPairCache()
{
return m_hashPairCache;
}
-
};
-
-
///The btGhostPairCallback interfaces and forwards adding and removal of overlapping pairs from the btBroadphaseInterface to btGhostObject.
class btGhostPairCallback : public btOverlappingPairCallback
{
-
public:
btGhostPairCallback()
{
@@ -131,15 +123,14 @@ public:
virtual ~btGhostPairCallback()
{
-
}
- virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+ virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
{
- btCollisionObject* colObj0 = (btCollisionObject*) proxy0->m_clientObject;
- btCollisionObject* colObj1 = (btCollisionObject*) proxy1->m_clientObject;
- btGhostObject* ghost0 = btGhostObject::upcast(colObj0);
- btGhostObject* ghost1 = btGhostObject::upcast(colObj1);
+ btCollisionObject* colObj0 = (btCollisionObject*)proxy0->m_clientObject;
+ btCollisionObject* colObj1 = (btCollisionObject*)proxy1->m_clientObject;
+ btGhostObject* ghost0 = btGhostObject::upcast(colObj0);
+ btGhostObject* ghost1 = btGhostObject::upcast(colObj1);
if (ghost0)
ghost0->addOverlappingObjectInternal(proxy1, proxy0);
if (ghost1)
@@ -147,29 +138,25 @@ public:
return 0;
}
- virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher)
+ virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, btDispatcher* dispatcher)
{
- btCollisionObject* colObj0 = (btCollisionObject*) proxy0->m_clientObject;
- btCollisionObject* colObj1 = (btCollisionObject*) proxy1->m_clientObject;
- btGhostObject* ghost0 = btGhostObject::upcast(colObj0);
- btGhostObject* ghost1 = btGhostObject::upcast(colObj1);
+ btCollisionObject* colObj0 = (btCollisionObject*)proxy0->m_clientObject;
+ btCollisionObject* colObj1 = (btCollisionObject*)proxy1->m_clientObject;
+ btGhostObject* ghost0 = btGhostObject::upcast(colObj0);
+ btGhostObject* ghost1 = btGhostObject::upcast(colObj1);
if (ghost0)
- ghost0->removeOverlappingObjectInternal(proxy1,dispatcher,proxy0);
+ ghost0->removeOverlappingObjectInternal(proxy1, dispatcher, proxy0);
if (ghost1)
- ghost1->removeOverlappingObjectInternal(proxy0,dispatcher,proxy1);
+ ghost1->removeOverlappingObjectInternal(proxy0, dispatcher, proxy1);
return 0;
}
- virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/,btDispatcher* /*dispatcher*/)
+ virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/, btDispatcher* /*dispatcher*/)
{
btAssert(0);
//need to keep track of all ghost objects and call them here
//m_hashPairCache->removeOverlappingPairsContainingProxy(proxy0,dispatcher);
}
-
-
-
};
#endif
-
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp
index 8271981b29..b686d98d1e 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp
@@ -13,64 +13,49 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
-
#include "btHashedSimplePairCache.h"
-
#include <stdio.h>
#ifdef BT_DEBUG_COLLISION_PAIRS
-int gOverlappingSimplePairs = 0;
-int gRemoveSimplePairs =0;
-int gAddedSimplePairs =0;
-int gFindSimplePairs =0;
-#endif //BT_DEBUG_COLLISION_PAIRS
-
-
+int gOverlappingSimplePairs = 0;
+int gRemoveSimplePairs = 0;
+int gAddedSimplePairs = 0;
+int gFindSimplePairs = 0;
+#endif //BT_DEBUG_COLLISION_PAIRS
-btHashedSimplePairCache::btHashedSimplePairCache() {
- int initialAllocatedSize= 2;
+btHashedSimplePairCache::btHashedSimplePairCache()
+{
+ int initialAllocatedSize = 2;
m_overlappingPairArray.reserve(initialAllocatedSize);
growTables();
}
-
-
-
btHashedSimplePairCache::~btHashedSimplePairCache()
{
}
-
-
-
-
-
void btHashedSimplePairCache::removeAllPairs()
{
m_overlappingPairArray.clear();
m_hashTable.clear();
m_next.clear();
- int initialAllocatedSize= 2;
+ int initialAllocatedSize = 2;
m_overlappingPairArray.reserve(initialAllocatedSize);
growTables();
}
-
-
btSimplePair* btHashedSimplePairCache::findPair(int indexA, int indexB)
{
#ifdef BT_DEBUG_COLLISION_PAIRS
gFindSimplePairs++;
#endif
-
-
+
/*if (indexA > indexB)
btSwap(indexA, indexB);*/
- int hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA), static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity()-1));
+ int hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA), static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity() - 1));
if (hash >= m_hashTable.size())
{
@@ -95,9 +80,8 @@ btSimplePair* btHashedSimplePairCache::findPair(int indexA, int indexB)
//#include <stdio.h>
-void btHashedSimplePairCache::growTables()
+void btHashedSimplePairCache::growTables()
{
-
int newCapacity = m_overlappingPairArray.capacity();
if (m_hashTable.size() < newCapacity)
@@ -108,10 +92,9 @@ void btHashedSimplePairCache::growTables()
m_hashTable.resize(newCapacity);
m_next.resize(newCapacity);
-
int i;
- for (i= 0; i < newCapacity; ++i)
+ for (i = 0; i < newCapacity; ++i)
{
m_hashTable[i] = BT_SIMPLE_NULL_PAIR;
}
@@ -120,27 +103,22 @@ void btHashedSimplePairCache::growTables()
m_next[i] = BT_SIMPLE_NULL_PAIR;
}
- for(i=0;i<curHashtableSize;i++)
+ for (i = 0; i < curHashtableSize; i++)
{
-
const btSimplePair& pair = m_overlappingPairArray[i];
int indexA = pair.m_indexA;
int indexB = pair.m_indexB;
-
- int hashValue = static_cast<int>(getHash(static_cast<unsigned int>(indexA),static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask
+
+ int hashValue = static_cast<int>(getHash(static_cast<unsigned int>(indexA), static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity() - 1)); // New hash value with new mask
m_next[i] = m_hashTable[hashValue];
m_hashTable[hashValue] = i;
}
-
-
}
}
btSimplePair* btHashedSimplePairCache::internalAddPair(int indexA, int indexB)
{
-
- int hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA),static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask
-
+ int hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA), static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity() - 1)); // New hash value with new mask
btSimplePair* pair = internalFindPair(indexA, indexB, hash);
if (pair != NULL)
@@ -158,32 +136,29 @@ btSimplePair* btHashedSimplePairCache::internalAddPair(int indexA, int indexB)
{
growTables();
//hash with new capacity
- hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA),static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity()-1));
+ hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA), static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity() - 1));
}
-
- pair = new (mem) btSimplePair(indexA,indexB);
+
+ pair = new (mem) btSimplePair(indexA, indexB);
pair->m_userPointer = 0;
-
+
m_next[count] = m_hashTable[hash];
m_hashTable[hash] = count;
return pair;
}
-
-
void* btHashedSimplePairCache::removeOverlappingPair(int indexA, int indexB)
{
#ifdef BT_DEBUG_COLLISION_PAIRS
gRemoveSimplePairs++;
#endif
-
/*if (indexA > indexB)
btSwap(indexA, indexB);*/
- int hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA),static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity()-1));
+ int hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA), static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity() - 1));
btSimplePair* pair = internalFindPair(indexA, indexB, hash);
if (pair == NULL)
@@ -191,10 +166,8 @@ void* btHashedSimplePairCache::removeOverlappingPair(int indexA, int indexB)
return 0;
}
-
void* userData = pair->m_userPointer;
-
int pairIndex = int(pair - &m_overlappingPairArray[0]);
btAssert(pairIndex < m_overlappingPairArray.size());
@@ -234,8 +207,8 @@ void* btHashedSimplePairCache::removeOverlappingPair(int indexA, int indexB)
// Remove the last pair from the hash table.
const btSimplePair* last = &m_overlappingPairArray[lastPairIndex];
- /* missing swap here too, Nat. */
- int lastHash = static_cast<int>(getHash(static_cast<unsigned int>(last->m_indexA), static_cast<unsigned int>(last->m_indexB)) & (m_overlappingPairArray.capacity()-1));
+ /* missing swap here too, Nat. */
+ int lastHash = static_cast<int>(getHash(static_cast<unsigned int>(last->m_indexA), static_cast<unsigned int>(last->m_indexB)) & (m_overlappingPairArray.capacity() - 1));
index = m_hashTable[lastHash];
btAssert(index != BT_SIMPLE_NULL_PAIR);
@@ -269,13 +242,3 @@ void* btHashedSimplePairCache::removeOverlappingPair(int indexA, int indexB)
return userData;
}
//#include <stdio.h>
-
-
-
-
-
-
-
-
-
-
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btHashedSimplePairCache.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btHashedSimplePairCache.h
index 318981cda1..fd38a4f0e1 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btHashedSimplePairCache.h
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btHashedSimplePairCache.h
@@ -16,144 +16,126 @@ subject to the following restrictions:
#ifndef BT_HASHED_SIMPLE_PAIR_CACHE_H
#define BT_HASHED_SIMPLE_PAIR_CACHE_H
-
-
#include "LinearMath/btAlignedObjectArray.h"
-const int BT_SIMPLE_NULL_PAIR=0xffffffff;
+const int BT_SIMPLE_NULL_PAIR = 0xffffffff;
struct btSimplePair
{
- btSimplePair(int indexA,int indexB)
- :m_indexA(indexA),
- m_indexB(indexB),
- m_userPointer(0)
+ btSimplePair(int indexA, int indexB)
+ : m_indexA(indexA),
+ m_indexB(indexB),
+ m_userPointer(0)
{
}
int m_indexA;
int m_indexB;
- union
- {
- void* m_userPointer;
- int m_userValue;
+ union {
+ void* m_userPointer;
+ int m_userValue;
};
};
-typedef btAlignedObjectArray<btSimplePair> btSimplePairArray;
-
+typedef btAlignedObjectArray<btSimplePair> btSimplePairArray;
#ifdef BT_DEBUG_COLLISION_PAIRS
extern int gOverlappingSimplePairs;
extern int gRemoveSimplePairs;
extern int gAddedSimplePairs;
extern int gFindSimplePairs;
-#endif //BT_DEBUG_COLLISION_PAIRS
-
-
+#endif //BT_DEBUG_COLLISION_PAIRS
class btHashedSimplePairCache
{
- btSimplePairArray m_overlappingPairArray;
-
+ btSimplePairArray m_overlappingPairArray;
protected:
-
- btAlignedObjectArray<int> m_hashTable;
- btAlignedObjectArray<int> m_next;
-
+ btAlignedObjectArray<int> m_hashTable;
+ btAlignedObjectArray<int> m_next;
public:
btHashedSimplePairCache();
virtual ~btHashedSimplePairCache();
-
+
void removeAllPairs();
- virtual void* removeOverlappingPair(int indexA,int indexB);
-
+ virtual void* removeOverlappingPair(int indexA, int indexB);
+
// Add a pair and return the new pair. If the pair already exists,
// no new pair is created and the old one is returned.
- virtual btSimplePair* addOverlappingPair(int indexA,int indexB)
+ virtual btSimplePair* addOverlappingPair(int indexA, int indexB)
{
#ifdef BT_DEBUG_COLLISION_PAIRS
gAddedSimplePairs++;
#endif
- return internalAddPair(indexA,indexB);
+ return internalAddPair(indexA, indexB);
}
-
- virtual btSimplePair* getOverlappingPairArrayPtr()
+ virtual btSimplePair* getOverlappingPairArrayPtr()
{
return &m_overlappingPairArray[0];
}
- const btSimplePair* getOverlappingPairArrayPtr() const
+ const btSimplePair* getOverlappingPairArrayPtr() const
{
return &m_overlappingPairArray[0];
}
- btSimplePairArray& getOverlappingPairArray()
+ btSimplePairArray& getOverlappingPairArray()
{
return m_overlappingPairArray;
}
- const btSimplePairArray& getOverlappingPairArray() const
+ const btSimplePairArray& getOverlappingPairArray() const
{
return m_overlappingPairArray;
}
-
- btSimplePair* findPair(int indexA,int indexB);
+ btSimplePair* findPair(int indexA, int indexB);
int GetCount() const { return m_overlappingPairArray.size(); }
- int getNumOverlappingPairs() const
+ int getNumOverlappingPairs() const
{
return m_overlappingPairArray.size();
}
+
private:
-
- btSimplePair* internalAddPair(int indexA, int indexB);
+ btSimplePair* internalAddPair(int indexA, int indexB);
- void growTables();
+ void growTables();
SIMD_FORCE_INLINE bool equalsPair(const btSimplePair& pair, int indexA, int indexB)
- {
+ {
return pair.m_indexA == indexA && pair.m_indexB == indexB;
}
-
-
SIMD_FORCE_INLINE unsigned int getHash(unsigned int indexA, unsigned int indexB)
{
unsigned int key = indexA | (indexB << 16);
// Thomas Wang's hash
key += ~(key << 15);
- key ^= (key >> 10);
- key += (key << 3);
- key ^= (key >> 6);
+ key ^= (key >> 10);
+ key += (key << 3);
+ key ^= (key >> 6);
key += ~(key << 11);
- key ^= (key >> 16);
+ key ^= (key >> 16);
return key;
}
-
-
-
-
- SIMD_FORCE_INLINE btSimplePair* internalFindPair(int proxyIdA , int proxyIdB, int hash)
+ SIMD_FORCE_INLINE btSimplePair* internalFindPair(int proxyIdA, int proxyIdB, int hash)
{
-
int index = m_hashTable[hash];
-
- while( index != BT_SIMPLE_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyIdA, proxyIdB) == false)
+
+ while (index != BT_SIMPLE_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyIdA, proxyIdB) == false)
{
index = m_next[index];
}
- if ( index == BT_SIMPLE_NULL_PAIR )
+ if (index == BT_SIMPLE_NULL_PAIR)
{
return NULL;
}
@@ -162,13 +144,6 @@ private:
return &m_overlappingPairArray[index];
}
-
-
};
-
-
-
-#endif //BT_HASHED_SIMPLE_PAIR_CACHE_H
-
-
+#endif //BT_HASHED_SIMPLE_PAIR_CACHE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp
index 898320ee1a..e74c83f9f1 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp
@@ -12,50 +12,44 @@
#ifdef DEBUG_INTERNAL_EDGE
#include <stdio.h>
-#endif //DEBUG_INTERNAL_EDGE
-
+#endif //DEBUG_INTERNAL_EDGE
#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
static btIDebugDraw* gDebugDrawer = 0;
-void btSetDebugDrawer(btIDebugDraw* debugDrawer)
+void btSetDebugDrawer(btIDebugDraw* debugDrawer)
{
gDebugDrawer = debugDrawer;
}
-static void btDebugDrawLine(const btVector3& from,const btVector3& to, const btVector3& color)
+static void btDebugDrawLine(const btVector3& from, const btVector3& to, const btVector3& color)
{
if (gDebugDrawer)
- gDebugDrawer->drawLine(from,to,color);
+ gDebugDrawer->drawLine(from, to, color);
}
-#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
-
+#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
-static int btGetHash(int partId, int triangleIndex)
+static int btGetHash(int partId, int triangleIndex)
{
- int hash = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | triangleIndex;
+ int hash = (partId << (31 - MAX_NUM_PARTS_IN_BITS)) | triangleIndex;
return hash;
}
-
-
-static btScalar btGetAngle(const btVector3& edgeA, const btVector3& normalA,const btVector3& normalB)
+static btScalar btGetAngle(const btVector3& edgeA, const btVector3& normalA, const btVector3& normalB)
{
- const btVector3 refAxis0 = edgeA;
- const btVector3 refAxis1 = normalA;
+ const btVector3 refAxis0 = edgeA;
+ const btVector3 refAxis1 = normalA;
const btVector3 swingAxis = normalB;
btScalar angle = btAtan2(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1));
- return angle;
+ return angle;
}
-
struct btConnectivityProcessor : public btTriangleCallback
{
- int m_partIdA;
- int m_triangleIndexA;
- btVector3* m_triangleVerticesA;
- btTriangleInfoMap* m_triangleInfoMap;
-
+ int m_partIdA;
+ int m_triangleIndexA;
+ btVector3* m_triangleVerticesA;
+ btTriangleInfoMap* m_triangleInfoMap;
virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
{
@@ -69,18 +63,17 @@ struct btConnectivityProcessor : public btTriangleCallback
//search for shared vertices and edges
int numshared = 0;
- int sharedVertsA[3]={-1,-1,-1};
- int sharedVertsB[3]={-1,-1,-1};
+ int sharedVertsA[3] = {-1, -1, -1};
+ int sharedVertsB[3] = {-1, -1, -1};
///skip degenerate triangles
- btScalar crossBSqr = ((triangle[1]-triangle[0]).cross(triangle[2]-triangle[0])).length2();
+ btScalar crossBSqr = ((triangle[1] - triangle[0]).cross(triangle[2] - triangle[0])).length2();
if (crossBSqr < m_triangleInfoMap->m_equalVertexThreshold)
return;
-
- btScalar crossASqr = ((m_triangleVerticesA[1]-m_triangleVerticesA[0]).cross(m_triangleVerticesA[2]-m_triangleVerticesA[0])).length2();
+ btScalar crossASqr = ((m_triangleVerticesA[1] - m_triangleVerticesA[0]).cross(m_triangleVerticesA[2] - m_triangleVerticesA[0])).length2();
///skip degenerate triangles
- if (crossASqr< m_triangleInfoMap->m_equalVertexThreshold)
+ if (crossASqr < m_triangleInfoMap->m_equalVertexThreshold)
return;
#if 0
@@ -96,36 +89,36 @@ struct btConnectivityProcessor : public btTriangleCallback
triangle[2].getX(),triangle[2].getY(),triangle[2].getZ());
#endif
- for (int i=0;i<3;i++)
+ for (int i = 0; i < 3; i++)
{
- for (int j=0;j<3;j++)
+ for (int j = 0; j < 3; j++)
{
- if ( (m_triangleVerticesA[i]-triangle[j]).length2() < m_triangleInfoMap->m_equalVertexThreshold)
+ if ((m_triangleVerticesA[i] - triangle[j]).length2() < m_triangleInfoMap->m_equalVertexThreshold)
{
sharedVertsA[numshared] = i;
sharedVertsB[numshared] = j;
numshared++;
///degenerate case
- if(numshared >= 3)
+ if (numshared >= 3)
return;
}
}
///degenerate case
- if(numshared >= 3)
+ if (numshared >= 3)
return;
}
switch (numshared)
{
- case 0:
+ case 0:
{
break;
}
- case 1:
+ case 1:
{
//shared vertex
break;
}
- case 2:
+ case 2:
{
//shared edge
//we need to make sure the edge is in the order V2V0 and not V0V2 so that the signs are correct
@@ -138,26 +131,25 @@ struct btConnectivityProcessor : public btTriangleCallback
sharedVertsB[0] = tmp;
}
- int hash = btGetHash(m_partIdA,m_triangleIndexA);
+ int hash = btGetHash(m_partIdA, m_triangleIndexA);
btTriangleInfo* info = m_triangleInfoMap->find(hash);
if (!info)
{
btTriangleInfo tmp;
- m_triangleInfoMap->insert(hash,tmp);
+ m_triangleInfoMap->insert(hash, tmp);
info = m_triangleInfoMap->find(hash);
}
- int sumvertsA = sharedVertsA[0]+sharedVertsA[1];
- int otherIndexA = 3-sumvertsA;
+ int sumvertsA = sharedVertsA[0] + sharedVertsA[1];
+ int otherIndexA = 3 - sumvertsA;
-
- btVector3 edge(m_triangleVerticesA[sharedVertsA[1]]-m_triangleVerticesA[sharedVertsA[0]]);
+ btVector3 edge(m_triangleVerticesA[sharedVertsA[1]] - m_triangleVerticesA[sharedVertsA[0]]);
- btTriangleShape tA(m_triangleVerticesA[0],m_triangleVerticesA[1],m_triangleVerticesA[2]);
- int otherIndexB = 3-(sharedVertsB[0]+sharedVertsB[1]);
+ btTriangleShape tA(m_triangleVerticesA[0], m_triangleVerticesA[1], m_triangleVerticesA[2]);
+ int otherIndexB = 3 - (sharedVertsB[0] + sharedVertsB[1]);
- btTriangleShape tB(triangle[sharedVertsB[1]],triangle[sharedVertsB[0]],triangle[otherIndexB]);
+ btTriangleShape tB(triangle[sharedVertsB[1]], triangle[sharedVertsB[0]], triangle[otherIndexB]);
//btTriangleShape tB(triangle[0],triangle[1],triangle[2]);
btVector3 normalA;
@@ -168,26 +160,25 @@ struct btConnectivityProcessor : public btTriangleCallback
btVector3 edgeCrossA = edge.cross(normalA).normalize();
{
- btVector3 tmp = m_triangleVerticesA[otherIndexA]-m_triangleVerticesA[sharedVertsA[0]];
+ btVector3 tmp = m_triangleVerticesA[otherIndexA] - m_triangleVerticesA[sharedVertsA[0]];
if (edgeCrossA.dot(tmp) < 0)
{
- edgeCrossA*=-1;
+ edgeCrossA *= -1;
}
}
btVector3 edgeCrossB = edge.cross(normalB).normalize();
{
- btVector3 tmp = triangle[otherIndexB]-triangle[sharedVertsB[0]];
+ btVector3 tmp = triangle[otherIndexB] - triangle[sharedVertsB[0]];
if (edgeCrossB.dot(tmp) < 0)
{
- edgeCrossB*=-1;
+ edgeCrossB *= -1;
}
}
- btScalar angle2 = 0;
- btScalar ang4 = 0.f;
-
+ btScalar angle2 = 0;
+ btScalar ang4 = 0.f;
btVector3 calculatedEdge = edgeCrossA.cross(edgeCrossB);
btScalar len2 = calculatedEdge.length2();
@@ -196,52 +187,47 @@ struct btConnectivityProcessor : public btTriangleCallback
//btVector3 calculatedNormalB = normalA;
bool isConvex = false;
- if (len2<m_triangleInfoMap->m_planarEpsilon)
+ if (len2 < m_triangleInfoMap->m_planarEpsilon)
{
angle2 = 0.f;
ang4 = 0.f;
- } else
+ }
+ else
{
-
calculatedEdge.normalize();
btVector3 calculatedNormalA = calculatedEdge.cross(edgeCrossA);
calculatedNormalA.normalize();
- angle2 = btGetAngle(calculatedNormalA,edgeCrossA,edgeCrossB);
- ang4 = SIMD_PI-angle2;
+ angle2 = btGetAngle(calculatedNormalA, edgeCrossA, edgeCrossB);
+ ang4 = SIMD_PI - angle2;
btScalar dotA = normalA.dot(edgeCrossB);
///@todo: check if we need some epsilon, due to floating point imprecision
- isConvex = (dotA<0.);
+ isConvex = (dotA < 0.);
correctedAngle = isConvex ? ang4 : -ang4;
}
-
-
-
-
- //alternatively use
+ //alternatively use
//btVector3 calculatedNormalB2 = quatRotate(orn,normalA);
-
switch (sumvertsA)
{
- case 1:
+ case 1:
{
- btVector3 edge = m_triangleVerticesA[0]-m_triangleVerticesA[1];
- btQuaternion orn(edge,-correctedAngle);
- btVector3 computedNormalB = quatRotate(orn,normalA);
+ btVector3 edge = m_triangleVerticesA[0] - m_triangleVerticesA[1];
+ btQuaternion orn(edge, -correctedAngle);
+ btVector3 computedNormalB = quatRotate(orn, normalA);
btScalar bla = computedNormalB.dot(normalB);
- if (bla<0)
+ if (bla < 0)
{
- computedNormalB*=-1;
+ computedNormalB *= -1;
info->m_flags |= TRI_INFO_V0V1_SWAP_NORMALB;
}
#ifdef DEBUG_INTERNAL_EDGE
- if ((computedNormalB-normalB).length()>0.0001)
+ if ((computedNormalB - normalB).length() > 0.0001)
{
printf("warning: normals not identical\n");
}
-#endif//DEBUG_INTERNAL_EDGE
+#endif //DEBUG_INTERNAL_EDGE
info->m_edgeV0V1Angle = -correctedAngle;
@@ -249,44 +235,44 @@ struct btConnectivityProcessor : public btTriangleCallback
info->m_flags |= TRI_INFO_V0V1_CONVEX;
break;
}
- case 2:
+ case 2:
{
- btVector3 edge = m_triangleVerticesA[2]-m_triangleVerticesA[0];
- btQuaternion orn(edge,-correctedAngle);
- btVector3 computedNormalB = quatRotate(orn,normalA);
- if (computedNormalB.dot(normalB)<0)
+ btVector3 edge = m_triangleVerticesA[2] - m_triangleVerticesA[0];
+ btQuaternion orn(edge, -correctedAngle);
+ btVector3 computedNormalB = quatRotate(orn, normalA);
+ if (computedNormalB.dot(normalB) < 0)
{
- computedNormalB*=-1;
+ computedNormalB *= -1;
info->m_flags |= TRI_INFO_V2V0_SWAP_NORMALB;
}
#ifdef DEBUG_INTERNAL_EDGE
- if ((computedNormalB-normalB).length()>0.0001)
+ if ((computedNormalB - normalB).length() > 0.0001)
{
printf("warning: normals not identical\n");
}
-#endif //DEBUG_INTERNAL_EDGE
+#endif //DEBUG_INTERNAL_EDGE
info->m_edgeV2V0Angle = -correctedAngle;
if (isConvex)
info->m_flags |= TRI_INFO_V2V0_CONVEX;
- break;
+ break;
}
- case 3:
+ case 3:
{
- btVector3 edge = m_triangleVerticesA[1]-m_triangleVerticesA[2];
- btQuaternion orn(edge,-correctedAngle);
- btVector3 computedNormalB = quatRotate(orn,normalA);
- if (computedNormalB.dot(normalB)<0)
+ btVector3 edge = m_triangleVerticesA[1] - m_triangleVerticesA[2];
+ btQuaternion orn(edge, -correctedAngle);
+ btVector3 computedNormalB = quatRotate(orn, normalA);
+ if (computedNormalB.dot(normalB) < 0)
{
info->m_flags |= TRI_INFO_V1V2_SWAP_NORMALB;
- computedNormalB*=-1;
+ computedNormalB *= -1;
}
#ifdef DEBUG_INTERNAL_EDGE
- if ((computedNormalB-normalB).length()>0.0001)
+ if ((computedNormalB - normalB).length() > 0.0001)
{
printf("warning: normals not identical\n");
}
-#endif //DEBUG_INTERNAL_EDGE
+#endif //DEBUG_INTERNAL_EDGE
info->m_edgeV1V2Angle = -correctedAngle;
if (isConvex)
@@ -297,18 +283,17 @@ struct btConnectivityProcessor : public btTriangleCallback
break;
}
- default:
+ default:
{
// printf("warning: duplicate triangle\n");
}
-
}
}
};
/////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////
-void btGenerateInternalEdgeInfo (btBvhTriangleMeshShape*trimeshShape, btTriangleInfoMap* triangleInfoMap)
+void btGenerateInternalEdgeInfo(btBvhTriangleMeshShape* trimeshShape, btTriangleInfoMap* triangleInfoMap)
{
//the user pointer shouldn't already be used for other purposes, we intend to store connectivity info there!
if (trimeshShape->getTriangleInfoMap())
@@ -319,46 +304,45 @@ void btGenerateInternalEdgeInfo (btBvhTriangleMeshShape*trimeshShape, btTriangle
btStridingMeshInterface* meshInterface = trimeshShape->getMeshInterface();
const btVector3& meshScaling = meshInterface->getScaling();
- for (int partId = 0; partId< meshInterface->getNumSubParts();partId++)
+ for (int partId = 0; partId < meshInterface->getNumSubParts(); partId++)
{
- const unsigned char *vertexbase = 0;
+ const unsigned char* vertexbase = 0;
int numverts = 0;
PHY_ScalarType type = PHY_INTEGER;
int stride = 0;
- const unsigned char *indexbase = 0;
+ const unsigned char* indexbase = 0;
int indexstride = 0;
int numfaces = 0;
PHY_ScalarType indicestype = PHY_INTEGER;
//PHY_ScalarType indexType=0;
btVector3 triangleVerts[3];
- meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase,numverts, type,stride,&indexbase,indexstride,numfaces,indicestype,partId);
- btVector3 aabbMin,aabbMax;
+ meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase, numverts, type, stride, &indexbase, indexstride, numfaces, indicestype, partId);
+ btVector3 aabbMin, aabbMax;
- for (int triangleIndex = 0 ; triangleIndex < numfaces;triangleIndex++)
+ for (int triangleIndex = 0; triangleIndex < numfaces; triangleIndex++)
{
- unsigned int* gfxbase = (unsigned int*)(indexbase+triangleIndex*indexstride);
+ unsigned int* gfxbase = (unsigned int*)(indexbase + triangleIndex * indexstride);
- for (int j=2;j>=0;j--)
+ for (int j = 2; j >= 0; j--)
{
-
- int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
+ int graphicsindex = indicestype == PHY_SHORT ? ((unsigned short*)gfxbase)[j] : gfxbase[j];
if (type == PHY_FLOAT)
{
- float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
+ float* graphicsbase = (float*)(vertexbase + graphicsindex * stride);
triangleVerts[j] = btVector3(
- graphicsbase[0]*meshScaling.getX(),
- graphicsbase[1]*meshScaling.getY(),
- graphicsbase[2]*meshScaling.getZ());
+ graphicsbase[0] * meshScaling.getX(),
+ graphicsbase[1] * meshScaling.getY(),
+ graphicsbase[2] * meshScaling.getZ());
}
else
{
- double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
- triangleVerts[j] = btVector3( btScalar(graphicsbase[0]*meshScaling.getX()), btScalar(graphicsbase[1]*meshScaling.getY()), btScalar(graphicsbase[2]*meshScaling.getZ()));
+ double* graphicsbase = (double*)(vertexbase + graphicsindex * stride);
+ triangleVerts[j] = btVector3(btScalar(graphicsbase[0] * meshScaling.getX()), btScalar(graphicsbase[1] * meshScaling.getY()), btScalar(graphicsbase[2] * meshScaling.getZ()));
}
}
- aabbMin.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
- aabbMax.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
+ aabbMin.setValue(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
+ aabbMax.setValue(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
aabbMin.setMin(triangleVerts[0]);
aabbMax.setMax(triangleVerts[0]);
aabbMin.setMin(triangleVerts[1]);
@@ -370,140 +354,127 @@ void btGenerateInternalEdgeInfo (btBvhTriangleMeshShape*trimeshShape, btTriangle
connectivityProcessor.m_partIdA = partId;
connectivityProcessor.m_triangleIndexA = triangleIndex;
connectivityProcessor.m_triangleVerticesA = &triangleVerts[0];
- connectivityProcessor.m_triangleInfoMap = triangleInfoMap;
+ connectivityProcessor.m_triangleInfoMap = triangleInfoMap;
- trimeshShape->processAllTriangles(&connectivityProcessor,aabbMin,aabbMax);
+ trimeshShape->processAllTriangles(&connectivityProcessor, aabbMin, aabbMax);
}
-
}
-
}
-
-
-
// Given a point and a line segment (defined by two points), compute the closest point
// in the line. Cap the point at the endpoints of the line segment.
-void btNearestPointInLineSegment(const btVector3 &point, const btVector3& line0, const btVector3& line1, btVector3& nearestPoint)
+void btNearestPointInLineSegment(const btVector3& point, const btVector3& line0, const btVector3& line1, btVector3& nearestPoint)
{
- btVector3 lineDelta = line1 - line0;
+ btVector3 lineDelta = line1 - line0;
// Handle degenerate lines
- if ( lineDelta.fuzzyZero())
+ if (lineDelta.fuzzyZero())
{
nearestPoint = line0;
}
else
{
- btScalar delta = (point-line0).dot(lineDelta) / (lineDelta).dot(lineDelta);
+ btScalar delta = (point - line0).dot(lineDelta) / (lineDelta).dot(lineDelta);
// Clamp the point to conform to the segment's endpoints
- if ( delta < 0 )
+ if (delta < 0)
delta = 0;
- else if ( delta > 1 )
+ else if (delta > 1)
delta = 1;
- nearestPoint = line0 + lineDelta*delta;
+ nearestPoint = line0 + lineDelta * delta;
}
}
-
-
-
-bool btClampNormal(const btVector3& edge,const btVector3& tri_normal_org,const btVector3& localContactNormalOnB, btScalar correctedEdgeAngle, btVector3 & clampedLocalNormal)
+bool btClampNormal(const btVector3& edge, const btVector3& tri_normal_org, const btVector3& localContactNormalOnB, btScalar correctedEdgeAngle, btVector3& clampedLocalNormal)
{
btVector3 tri_normal = tri_normal_org;
//we only have a local triangle normal, not a local contact normal -> only normal in world space...
//either compute the current angle all in local space, or all in world space
btVector3 edgeCross = edge.cross(tri_normal).normalize();
- btScalar curAngle = btGetAngle(edgeCross,tri_normal,localContactNormalOnB);
+ btScalar curAngle = btGetAngle(edgeCross, tri_normal, localContactNormalOnB);
- if (correctedEdgeAngle<0)
+ if (correctedEdgeAngle < 0)
{
if (curAngle < correctedEdgeAngle)
{
- btScalar diffAngle = correctedEdgeAngle-curAngle;
- btQuaternion rotation(edge,diffAngle );
- clampedLocalNormal = btMatrix3x3(rotation)*localContactNormalOnB;
+ btScalar diffAngle = correctedEdgeAngle - curAngle;
+ btQuaternion rotation(edge, diffAngle);
+ clampedLocalNormal = btMatrix3x3(rotation) * localContactNormalOnB;
return true;
}
}
- if (correctedEdgeAngle>=0)
+ if (correctedEdgeAngle >= 0)
{
if (curAngle > correctedEdgeAngle)
{
- btScalar diffAngle = correctedEdgeAngle-curAngle;
- btQuaternion rotation(edge,diffAngle );
- clampedLocalNormal = btMatrix3x3(rotation)*localContactNormalOnB;
+ btScalar diffAngle = correctedEdgeAngle - curAngle;
+ btQuaternion rotation(edge, diffAngle);
+ clampedLocalNormal = btMatrix3x3(rotation) * localContactNormalOnB;
return true;
}
}
return false;
}
-
-
/// Changes a btManifoldPoint collision normal to the normal from the mesh.
-void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap,const btCollisionObjectWrapper* colObj1Wrap, int partId0, int index0, int normalAdjustFlags)
+void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap, const btCollisionObjectWrapper* colObj1Wrap, int partId0, int index0, int normalAdjustFlags)
{
//btAssert(colObj0->getCollisionShape()->getShapeType() == TRIANGLE_SHAPE_PROXYTYPE);
if (colObj0Wrap->getCollisionShape()->getShapeType() != TRIANGLE_SHAPE_PROXYTYPE)
return;
btBvhTriangleMeshShape* trimesh = 0;
-
- if( colObj0Wrap->getCollisionObject()->getCollisionShape()->getShapeType() == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE )
+
+ if (colObj0Wrap->getCollisionObject()->getCollisionShape()->getShapeType() == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE)
{
trimesh = ((btScaledBvhTriangleMeshShape*)colObj0Wrap->getCollisionObject()->getCollisionShape())->getChildShape();
}
else
{
- if (colObj0Wrap->getCollisionObject()->getCollisionShape()->getShapeType()==TRIANGLE_MESH_SHAPE_PROXYTYPE)
+ if (colObj0Wrap->getCollisionObject()->getCollisionShape()->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
{
trimesh = (btBvhTriangleMeshShape*)colObj0Wrap->getCollisionObject()->getCollisionShape();
}
}
- if (trimesh==0)
+ if (trimesh == 0)
return;
- btTriangleInfoMap* triangleInfoMapPtr = (btTriangleInfoMap*) trimesh->getTriangleInfoMap();
+ btTriangleInfoMap* triangleInfoMapPtr = (btTriangleInfoMap*)trimesh->getTriangleInfoMap();
if (!triangleInfoMapPtr)
return;
- int hash = btGetHash(partId0,index0);
-
+ int hash = btGetHash(partId0, index0);
btTriangleInfo* info = triangleInfoMapPtr->find(hash);
if (!info)
return;
- btScalar frontFacing = (normalAdjustFlags & BT_TRIANGLE_CONVEX_BACKFACE_MODE)==0? 1.f : -1.f;
-
+ btScalar frontFacing = (normalAdjustFlags & BT_TRIANGLE_CONVEX_BACKFACE_MODE) == 0 ? 1.f : -1.f;
+
const btTriangleShape* tri_shape = static_cast<const btTriangleShape*>(colObj0Wrap->getCollisionShape());
- btVector3 v0,v1,v2;
- tri_shape->getVertex(0,v0);
- tri_shape->getVertex(1,v1);
- tri_shape->getVertex(2,v2);
+ btVector3 v0, v1, v2;
+ tri_shape->getVertex(0, v0);
+ tri_shape->getVertex(1, v1);
+ tri_shape->getVertex(2, v2);
//btVector3 center = (v0+v1+v2)*btScalar(1./3.);
- btVector3 red(1,0,0), green(0,1,0),blue(0,0,1),white(1,1,1),black(0,0,0);
+ btVector3 red(1, 0, 0), green(0, 1, 0), blue(0, 0, 1), white(1, 1, 1), black(0, 0, 0);
btVector3 tri_normal;
tri_shape->calcNormal(tri_normal);
//btScalar dot = tri_normal.dot(cp.m_normalWorldOnB);
btVector3 nearest;
- btNearestPointInLineSegment(cp.m_localPointB,v0,v1,nearest);
+ btNearestPointInLineSegment(cp.m_localPointB, v0, v1, nearest);
btVector3 contact = cp.m_localPointB;
#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
const btTransform& tr = colObj0->getWorldTransform();
- btDebugDrawLine(tr*nearest,tr*cp.m_localPointB,red);
-#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
-
-
+ btDebugDrawLine(tr * nearest, tr * cp.m_localPointB, red);
+#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
bool isNearEdge = false;
@@ -511,334 +482,325 @@ void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObjectWr
int numConvexEdgeHits = 0;
btVector3 localContactNormalOnB = colObj0Wrap->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB;
- localContactNormalOnB.normalize();//is this necessary?
-
+ localContactNormalOnB.normalize(); //is this necessary?
+
// Get closest edge
- int bestedge=-1;
- btScalar disttobestedge=BT_LARGE_FLOAT;
+ int bestedge = -1;
+ btScalar disttobestedge = BT_LARGE_FLOAT;
//
// Edge 0 -> 1
- if (btFabs(info->m_edgeV0V1Angle)< triangleInfoMapPtr->m_maxEdgeAngleThreshold)
- {
- btVector3 nearest;
- btNearestPointInLineSegment( cp.m_localPointB, v0, v1, nearest );
- btScalar len=(contact-nearest).length();
- //
- if( len < disttobestedge )
- {
- bestedge=0;
- disttobestedge=len;
- }
- }
+ if (btFabs(info->m_edgeV0V1Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
+ {
+ btVector3 nearest;
+ btNearestPointInLineSegment(cp.m_localPointB, v0, v1, nearest);
+ btScalar len = (contact - nearest).length();
+ //
+ if (len < disttobestedge)
+ {
+ bestedge = 0;
+ disttobestedge = len;
+ }
+ }
// Edge 1 -> 2
- if (btFabs(info->m_edgeV1V2Angle)< triangleInfoMapPtr->m_maxEdgeAngleThreshold)
- {
- btVector3 nearest;
- btNearestPointInLineSegment( cp.m_localPointB, v1, v2, nearest );
- btScalar len=(contact-nearest).length();
- //
- if( len < disttobestedge )
- {
- bestedge=1;
- disttobestedge=len;
- }
- }
+ if (btFabs(info->m_edgeV1V2Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
+ {
+ btVector3 nearest;
+ btNearestPointInLineSegment(cp.m_localPointB, v1, v2, nearest);
+ btScalar len = (contact - nearest).length();
+ //
+ if (len < disttobestedge)
+ {
+ bestedge = 1;
+ disttobestedge = len;
+ }
+ }
// Edge 2 -> 0
- if (btFabs(info->m_edgeV2V0Angle)< triangleInfoMapPtr->m_maxEdgeAngleThreshold)
- {
- btVector3 nearest;
- btNearestPointInLineSegment( cp.m_localPointB, v2, v0, nearest );
- btScalar len=(contact-nearest).length();
- //
- if( len < disttobestedge )
- {
- bestedge=2;
- disttobestedge=len;
- }
- }
-
+ if (btFabs(info->m_edgeV2V0Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
+ {
+ btVector3 nearest;
+ btNearestPointInLineSegment(cp.m_localPointB, v2, v0, nearest);
+ btScalar len = (contact - nearest).length();
+ //
+ if (len < disttobestedge)
+ {
+ bestedge = 2;
+ disttobestedge = len;
+ }
+ }
+
#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- btVector3 upfix=tri_normal * btVector3(0.1f,0.1f,0.1f);
- btDebugDrawLine(tr * v0 + upfix, tr * v1 + upfix, red );
-#endif
- if (btFabs(info->m_edgeV0V1Angle)< triangleInfoMapPtr->m_maxEdgeAngleThreshold)
+ btVector3 upfix = tri_normal * btVector3(0.1f, 0.1f, 0.1f);
+ btDebugDrawLine(tr * v0 + upfix, tr * v1 + upfix, red);
+#endif
+ if (btFabs(info->m_edgeV0V1Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
{
#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- btDebugDrawLine(tr*contact,tr*(contact+cp.m_normalWorldOnB*10),black);
+ btDebugDrawLine(tr * contact, tr * (contact + cp.m_normalWorldOnB * 10), black);
#endif
- btScalar len = (contact-nearest).length();
- if(len<triangleInfoMapPtr->m_edgeDistanceThreshold)
- if( bestedge==0 )
- {
- btVector3 edge(v0-v1);
- isNearEdge = true;
-
- if (info->m_edgeV0V1Angle==btScalar(0))
- {
- numConcaveEdgeHits++;
- } else
+ btScalar len = (contact - nearest).length();
+ if (len < triangleInfoMapPtr->m_edgeDistanceThreshold)
+ if (bestedge == 0)
{
+ btVector3 edge(v0 - v1);
+ isNearEdge = true;
- bool isEdgeConvex = (info->m_flags & TRI_INFO_V0V1_CONVEX);
- btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1);
- #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- btDebugDrawLine(tr*nearest,tr*(nearest+swapFactor*tri_normal*10),white);
- #endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+ if (info->m_edgeV0V1Angle == btScalar(0))
+ {
+ numConcaveEdgeHits++;
+ }
+ else
+ {
+ bool isEdgeConvex = (info->m_flags & TRI_INFO_V0V1_CONVEX);
+ btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1);
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+ btDebugDrawLine(tr * nearest, tr * (nearest + swapFactor * tri_normal * 10), white);
+#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
- btVector3 nA = swapFactor * tri_normal;
+ btVector3 nA = swapFactor * tri_normal;
- btQuaternion orn(edge,info->m_edgeV0V1Angle);
- btVector3 computedNormalB = quatRotate(orn,tri_normal);
- if (info->m_flags & TRI_INFO_V0V1_SWAP_NORMALB)
- computedNormalB*=-1;
- btVector3 nB = swapFactor*computedNormalB;
+ btQuaternion orn(edge, info->m_edgeV0V1Angle);
+ btVector3 computedNormalB = quatRotate(orn, tri_normal);
+ if (info->m_flags & TRI_INFO_V0V1_SWAP_NORMALB)
+ computedNormalB *= -1;
+ btVector3 nB = swapFactor * computedNormalB;
- btScalar NdotA = localContactNormalOnB.dot(nA);
- btScalar NdotB = localContactNormalOnB.dot(nB);
- bool backFacingNormal = (NdotA< triangleInfoMapPtr->m_convexEpsilon) && (NdotB<triangleInfoMapPtr->m_convexEpsilon);
+ btScalar NdotA = localContactNormalOnB.dot(nA);
+ btScalar NdotB = localContactNormalOnB.dot(nB);
+ bool backFacingNormal = (NdotA < triangleInfoMapPtr->m_convexEpsilon) && (NdotB < triangleInfoMapPtr->m_convexEpsilon);
#ifdef DEBUG_INTERNAL_EDGE
- {
-
- btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+tr.getBasis()*(nB*20),red);
- }
-#endif //DEBUG_INTERNAL_EDGE
-
+ {
+ btDebugDrawLine(cp.getPositionWorldOnB(), cp.getPositionWorldOnB() + tr.getBasis() * (nB * 20), red);
+ }
+#endif //DEBUG_INTERNAL_EDGE
- if (backFacingNormal)
- {
- numConcaveEdgeHits++;
- }
- else
- {
- numConvexEdgeHits++;
- btVector3 clampedLocalNormal;
- bool isClamped = btClampNormal(edge,swapFactor*tri_normal,localContactNormalOnB, info->m_edgeV0V1Angle,clampedLocalNormal);
- if (isClamped)
+ if (backFacingNormal)
+ {
+ numConcaveEdgeHits++;
+ }
+ else
{
- if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED)!=0) || (clampedLocalNormal.dot(frontFacing*tri_normal)>0))
+ numConvexEdgeHits++;
+ btVector3 clampedLocalNormal;
+ bool isClamped = btClampNormal(edge, swapFactor * tri_normal, localContactNormalOnB, info->m_edgeV0V1Angle, clampedLocalNormal);
+ if (isClamped)
{
- btVector3 newNormal = colObj0Wrap->getWorldTransform().getBasis() * clampedLocalNormal;
- // cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB);
- cp.m_normalWorldOnB = newNormal;
- // Reproject collision point along normal. (what about cp.m_distance1?)
- cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
- cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
-
+ if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED) != 0) || (clampedLocalNormal.dot(frontFacing * tri_normal) > 0))
+ {
+ btVector3 newNormal = colObj0Wrap->getWorldTransform().getBasis() * clampedLocalNormal;
+ // cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB);
+ cp.m_normalWorldOnB = newNormal;
+ // Reproject collision point along normal. (what about cp.m_distance1?)
+ cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
+ cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
+ }
}
}
}
}
- }
}
- btNearestPointInLineSegment(contact,v1,v2,nearest);
+ btNearestPointInLineSegment(contact, v1, v2, nearest);
#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- btDebugDrawLine(tr*nearest,tr*cp.m_localPointB,green);
-#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+ btDebugDrawLine(tr * nearest, tr * cp.m_localPointB, green);
+#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- btDebugDrawLine(tr * v1 + upfix, tr * v2 + upfix , green );
-#endif
+ btDebugDrawLine(tr * v1 + upfix, tr * v2 + upfix, green);
+#endif
- if (btFabs(info->m_edgeV1V2Angle)< triangleInfoMapPtr->m_maxEdgeAngleThreshold)
+ if (btFabs(info->m_edgeV1V2Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
{
#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- btDebugDrawLine(tr*contact,tr*(contact+cp.m_normalWorldOnB*10),black);
-#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
-
-
-
- btScalar len = (contact-nearest).length();
- if(len<triangleInfoMapPtr->m_edgeDistanceThreshold)
- if( bestedge==1 )
- {
- isNearEdge = true;
-#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- btDebugDrawLine(tr*nearest,tr*(nearest+tri_normal*10),white);
-#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+ btDebugDrawLine(tr * contact, tr * (contact + cp.m_normalWorldOnB * 10), black);
+#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
- btVector3 edge(v1-v2);
-
- isNearEdge = true;
-
- if (info->m_edgeV1V2Angle == btScalar(0))
+ btScalar len = (contact - nearest).length();
+ if (len < triangleInfoMapPtr->m_edgeDistanceThreshold)
+ if (bestedge == 1)
{
- numConcaveEdgeHits++;
- } else
- {
- bool isEdgeConvex = (info->m_flags & TRI_INFO_V1V2_CONVEX)!=0;
- btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1);
- #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- btDebugDrawLine(tr*nearest,tr*(nearest+swapFactor*tri_normal*10),white);
- #endif //BT_INTERNAL_EDGE_DEBUG_DRAW
-
- btVector3 nA = swapFactor * tri_normal;
-
- btQuaternion orn(edge,info->m_edgeV1V2Angle);
- btVector3 computedNormalB = quatRotate(orn,tri_normal);
- if (info->m_flags & TRI_INFO_V1V2_SWAP_NORMALB)
- computedNormalB*=-1;
- btVector3 nB = swapFactor*computedNormalB;
-
-#ifdef DEBUG_INTERNAL_EDGE
- {
- btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+tr.getBasis()*(nB*20),red);
- }
-#endif //DEBUG_INTERNAL_EDGE
+ isNearEdge = true;
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+ btDebugDrawLine(tr * nearest, tr * (nearest + tri_normal * 10), white);
+#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+ btVector3 edge(v1 - v2);
- btScalar NdotA = localContactNormalOnB.dot(nA);
- btScalar NdotB = localContactNormalOnB.dot(nB);
- bool backFacingNormal = (NdotA< triangleInfoMapPtr->m_convexEpsilon) && (NdotB<triangleInfoMapPtr->m_convexEpsilon);
+ isNearEdge = true;
- if (backFacingNormal)
+ if (info->m_edgeV1V2Angle == btScalar(0))
{
numConcaveEdgeHits++;
}
else
{
- numConvexEdgeHits++;
- btVector3 localContactNormalOnB = colObj0Wrap->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB;
- btVector3 clampedLocalNormal;
- bool isClamped = btClampNormal(edge,swapFactor*tri_normal,localContactNormalOnB, info->m_edgeV1V2Angle,clampedLocalNormal);
- if (isClamped)
+ bool isEdgeConvex = (info->m_flags & TRI_INFO_V1V2_CONVEX) != 0;
+ btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1);
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+ btDebugDrawLine(tr * nearest, tr * (nearest + swapFactor * tri_normal * 10), white);
+#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+ btVector3 nA = swapFactor * tri_normal;
+
+ btQuaternion orn(edge, info->m_edgeV1V2Angle);
+ btVector3 computedNormalB = quatRotate(orn, tri_normal);
+ if (info->m_flags & TRI_INFO_V1V2_SWAP_NORMALB)
+ computedNormalB *= -1;
+ btVector3 nB = swapFactor * computedNormalB;
+
+#ifdef DEBUG_INTERNAL_EDGE
+ {
+ btDebugDrawLine(cp.getPositionWorldOnB(), cp.getPositionWorldOnB() + tr.getBasis() * (nB * 20), red);
+ }
+#endif //DEBUG_INTERNAL_EDGE
+
+ btScalar NdotA = localContactNormalOnB.dot(nA);
+ btScalar NdotB = localContactNormalOnB.dot(nB);
+ bool backFacingNormal = (NdotA < triangleInfoMapPtr->m_convexEpsilon) && (NdotB < triangleInfoMapPtr->m_convexEpsilon);
+
+ if (backFacingNormal)
+ {
+ numConcaveEdgeHits++;
+ }
+ else
{
- if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED)!=0) || (clampedLocalNormal.dot(frontFacing*tri_normal)>0))
+ numConvexEdgeHits++;
+ btVector3 localContactNormalOnB = colObj0Wrap->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB;
+ btVector3 clampedLocalNormal;
+ bool isClamped = btClampNormal(edge, swapFactor * tri_normal, localContactNormalOnB, info->m_edgeV1V2Angle, clampedLocalNormal);
+ if (isClamped)
{
- btVector3 newNormal = colObj0Wrap->getWorldTransform().getBasis() * clampedLocalNormal;
- // cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB);
- cp.m_normalWorldOnB = newNormal;
- // Reproject collision point along normal.
- cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
- cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
+ if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED) != 0) || (clampedLocalNormal.dot(frontFacing * tri_normal) > 0))
+ {
+ btVector3 newNormal = colObj0Wrap->getWorldTransform().getBasis() * clampedLocalNormal;
+ // cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB);
+ cp.m_normalWorldOnB = newNormal;
+ // Reproject collision point along normal.
+ cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
+ cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
+ }
}
}
}
}
- }
}
- btNearestPointInLineSegment(contact,v2,v0,nearest);
+ btNearestPointInLineSegment(contact, v2, v0, nearest);
#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- btDebugDrawLine(tr*nearest,tr*cp.m_localPointB,blue);
-#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+ btDebugDrawLine(tr * nearest, tr * cp.m_localPointB, blue);
+#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- btDebugDrawLine(tr * v2 + upfix, tr * v0 + upfix , blue );
-#endif
+ btDebugDrawLine(tr * v2 + upfix, tr * v0 + upfix, blue);
+#endif
- if (btFabs(info->m_edgeV2V0Angle)< triangleInfoMapPtr->m_maxEdgeAngleThreshold)
+ if (btFabs(info->m_edgeV2V0Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
{
-
-#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- btDebugDrawLine(tr*contact,tr*(contact+cp.m_normalWorldOnB*10),black);
-#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
-
- btScalar len = (contact-nearest).length();
- if(len<triangleInfoMapPtr->m_edgeDistanceThreshold)
- if( bestedge==2 )
- {
- isNearEdge = true;
#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- btDebugDrawLine(tr*nearest,tr*(nearest+tri_normal*10),white);
-#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+ btDebugDrawLine(tr * contact, tr * (contact + cp.m_normalWorldOnB * 10), black);
+#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
- btVector3 edge(v2-v0);
-
- if (info->m_edgeV2V0Angle==btScalar(0))
- {
- numConcaveEdgeHits++;
- } else
+ btScalar len = (contact - nearest).length();
+ if (len < triangleInfoMapPtr->m_edgeDistanceThreshold)
+ if (bestedge == 2)
{
+ isNearEdge = true;
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+ btDebugDrawLine(tr * nearest, tr * (nearest + tri_normal * 10), white);
+#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
- bool isEdgeConvex = (info->m_flags & TRI_INFO_V2V0_CONVEX)!=0;
- btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1);
- #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- btDebugDrawLine(tr*nearest,tr*(nearest+swapFactor*tri_normal*10),white);
- #endif //BT_INTERNAL_EDGE_DEBUG_DRAW
-
- btVector3 nA = swapFactor * tri_normal;
- btQuaternion orn(edge,info->m_edgeV2V0Angle);
- btVector3 computedNormalB = quatRotate(orn,tri_normal);
- if (info->m_flags & TRI_INFO_V2V0_SWAP_NORMALB)
- computedNormalB*=-1;
- btVector3 nB = swapFactor*computedNormalB;
-
-#ifdef DEBUG_INTERNAL_EDGE
- {
- btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+tr.getBasis()*(nB*20),red);
- }
-#endif //DEBUG_INTERNAL_EDGE
-
- btScalar NdotA = localContactNormalOnB.dot(nA);
- btScalar NdotB = localContactNormalOnB.dot(nB);
- bool backFacingNormal = (NdotA< triangleInfoMapPtr->m_convexEpsilon) && (NdotB<triangleInfoMapPtr->m_convexEpsilon);
+ btVector3 edge(v2 - v0);
- if (backFacingNormal)
+ if (info->m_edgeV2V0Angle == btScalar(0))
{
numConcaveEdgeHits++;
}
else
{
- numConvexEdgeHits++;
- // printf("hitting convex edge\n");
+ bool isEdgeConvex = (info->m_flags & TRI_INFO_V2V0_CONVEX) != 0;
+ btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1);
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+ btDebugDrawLine(tr * nearest, tr * (nearest + swapFactor * tri_normal * 10), white);
+#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+ btVector3 nA = swapFactor * tri_normal;
+ btQuaternion orn(edge, info->m_edgeV2V0Angle);
+ btVector3 computedNormalB = quatRotate(orn, tri_normal);
+ if (info->m_flags & TRI_INFO_V2V0_SWAP_NORMALB)
+ computedNormalB *= -1;
+ btVector3 nB = swapFactor * computedNormalB;
+
+#ifdef DEBUG_INTERNAL_EDGE
+ {
+ btDebugDrawLine(cp.getPositionWorldOnB(), cp.getPositionWorldOnB() + tr.getBasis() * (nB * 20), red);
+ }
+#endif //DEBUG_INTERNAL_EDGE
+ btScalar NdotA = localContactNormalOnB.dot(nA);
+ btScalar NdotB = localContactNormalOnB.dot(nB);
+ bool backFacingNormal = (NdotA < triangleInfoMapPtr->m_convexEpsilon) && (NdotB < triangleInfoMapPtr->m_convexEpsilon);
- btVector3 localContactNormalOnB = colObj0Wrap->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB;
- btVector3 clampedLocalNormal;
- bool isClamped = btClampNormal(edge,swapFactor*tri_normal,localContactNormalOnB,info->m_edgeV2V0Angle,clampedLocalNormal);
- if (isClamped)
+ if (backFacingNormal)
+ {
+ numConcaveEdgeHits++;
+ }
+ else
{
- if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED)!=0) || (clampedLocalNormal.dot(frontFacing*tri_normal)>0))
+ numConvexEdgeHits++;
+ // printf("hitting convex edge\n");
+
+ btVector3 localContactNormalOnB = colObj0Wrap->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB;
+ btVector3 clampedLocalNormal;
+ bool isClamped = btClampNormal(edge, swapFactor * tri_normal, localContactNormalOnB, info->m_edgeV2V0Angle, clampedLocalNormal);
+ if (isClamped)
{
- btVector3 newNormal = colObj0Wrap->getWorldTransform().getBasis() * clampedLocalNormal;
- // cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB);
- cp.m_normalWorldOnB = newNormal;
- // Reproject collision point along normal.
- cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
- cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
+ if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED) != 0) || (clampedLocalNormal.dot(frontFacing * tri_normal) > 0))
+ {
+ btVector3 newNormal = colObj0Wrap->getWorldTransform().getBasis() * clampedLocalNormal;
+ // cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB);
+ cp.m_normalWorldOnB = newNormal;
+ // Reproject collision point along normal.
+ cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
+ cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
+ }
}
}
- }
+ }
}
-
-
- }
}
#ifdef DEBUG_INTERNAL_EDGE
{
- btVector3 color(0,1,1);
- btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+cp.m_normalWorldOnB*10,color);
+ btVector3 color(0, 1, 1);
+ btDebugDrawLine(cp.getPositionWorldOnB(), cp.getPositionWorldOnB() + cp.m_normalWorldOnB * 10, color);
}
-#endif //DEBUG_INTERNAL_EDGE
+#endif //DEBUG_INTERNAL_EDGE
if (isNearEdge)
{
-
- if (numConcaveEdgeHits>0)
+ if (numConcaveEdgeHits > 0)
{
- if ((normalAdjustFlags & BT_TRIANGLE_CONCAVE_DOUBLE_SIDED)!=0)
+ if ((normalAdjustFlags & BT_TRIANGLE_CONCAVE_DOUBLE_SIDED) != 0)
{
//fix tri_normal so it pointing the same direction as the current local contact normal
if (tri_normal.dot(localContactNormalOnB) < 0)
{
tri_normal *= -1;
}
- cp.m_normalWorldOnB = colObj0Wrap->getWorldTransform().getBasis()*tri_normal;
- } else
+ cp.m_normalWorldOnB = colObj0Wrap->getWorldTransform().getBasis() * tri_normal;
+ }
+ else
{
- btVector3 newNormal = tri_normal *frontFacing;
+ btVector3 newNormal = tri_normal * frontFacing;
//if the tri_normal is pointing opposite direction as the current local contact normal, skip it
- btScalar d = newNormal.dot(localContactNormalOnB) ;
- if (d< 0)
+ btScalar d = newNormal.dot(localContactNormalOnB);
+ if (d < 0)
{
return;
}
//modify the normal to be the triangle normal (or backfacing normal)
- cp.m_normalWorldOnB = colObj0Wrap->getWorldTransform().getBasis() *newNormal;
+ cp.m_normalWorldOnB = colObj0Wrap->getWorldTransform().getBasis() * newNormal;
}
-
+
// Reproject collision point along normal.
cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h
index 7d9aafeee6..9d9cff040f 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h
@@ -16,32 +16,26 @@ struct btCollisionObjectWrapper;
class btManifoldPoint;
class btIDebugDraw;
-
-
enum btInternalEdgeAdjustFlags
{
BT_TRIANGLE_CONVEX_BACKFACE_MODE = 1,
- BT_TRIANGLE_CONCAVE_DOUBLE_SIDED = 2, //double sided options are experimental, single sided is recommended
+ BT_TRIANGLE_CONCAVE_DOUBLE_SIDED = 2, //double sided options are experimental, single sided is recommended
BT_TRIANGLE_CONVEX_DOUBLE_SIDED = 4
};
-
///Call btGenerateInternalEdgeInfo to create triangle info, store in the shape 'userInfo'
-void btGenerateInternalEdgeInfo (btBvhTriangleMeshShape*trimeshShape, btTriangleInfoMap* triangleInfoMap);
-
+void btGenerateInternalEdgeInfo(btBvhTriangleMeshShape* trimeshShape, btTriangleInfoMap* triangleInfoMap);
///Call the btFixMeshNormal to adjust the collision normal, using the triangle info map (generated using btGenerateInternalEdgeInfo)
///If this info map is missing, or the triangle is not store in this map, nothing will be done
-void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObjectWrapper* trimeshColObj0Wrap,const btCollisionObjectWrapper* otherColObj1Wrap, int partId0, int index0, int normalAdjustFlags = 0);
+void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObjectWrapper* trimeshColObj0Wrap, const btCollisionObjectWrapper* otherColObj1Wrap, int partId0, int index0, int normalAdjustFlags = 0);
///Enable the BT_INTERNAL_EDGE_DEBUG_DRAW define and call btSetDebugDrawer, to get visual info to see if the internal edge utility works properly.
///If the utility doesn't work properly, you might have to adjust the threshold values in btTriangleInfoMap
//#define BT_INTERNAL_EDGE_DEBUG_DRAW
#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
-void btSetDebugDrawer(btIDebugDraw* debugDrawer);
-#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
-
-
-#endif //BT_INTERNAL_EDGE_UTILITY_H
+void btSetDebugDrawer(btIDebugDraw* debugDrawer);
+#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+#endif //BT_INTERNAL_EDGE_UTILITY_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btManifoldResult.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btManifoldResult.cpp
index 23c73c8825..770eb24369 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btManifoldResult.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btManifoldResult.cpp
@@ -13,106 +13,102 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#include "btManifoldResult.h"
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
///This is to allow MaterialCombiner/Custom Friction/Restitution values
-ContactAddedCallback gContactAddedCallback=0;
+ContactAddedCallback gContactAddedCallback = 0;
-CalculateCombinedCallback gCalculateCombinedRestitutionCallback = &btManifoldResult::calculateCombinedRestitution;
-CalculateCombinedCallback gCalculateCombinedFrictionCallback = &btManifoldResult::calculateCombinedFriction;
-CalculateCombinedCallback gCalculateCombinedRollingFrictionCallback = &btManifoldResult::calculateCombinedRollingFriction;
-CalculateCombinedCallback gCalculateCombinedSpinningFrictionCallback = &btManifoldResult::calculateCombinedSpinningFriction;
-CalculateCombinedCallback gCalculateCombinedContactDampingCallback = &btManifoldResult::calculateCombinedContactDamping;
-CalculateCombinedCallback gCalculateCombinedContactStiffnessCallback = &btManifoldResult::calculateCombinedContactStiffness;
+CalculateCombinedCallback gCalculateCombinedRestitutionCallback = &btManifoldResult::calculateCombinedRestitution;
+CalculateCombinedCallback gCalculateCombinedFrictionCallback = &btManifoldResult::calculateCombinedFriction;
+CalculateCombinedCallback gCalculateCombinedRollingFrictionCallback = &btManifoldResult::calculateCombinedRollingFriction;
+CalculateCombinedCallback gCalculateCombinedSpinningFrictionCallback = &btManifoldResult::calculateCombinedSpinningFriction;
+CalculateCombinedCallback gCalculateCombinedContactDampingCallback = &btManifoldResult::calculateCombinedContactDamping;
+CalculateCombinedCallback gCalculateCombinedContactStiffnessCallback = &btManifoldResult::calculateCombinedContactStiffness;
-btScalar btManifoldResult::calculateCombinedRollingFriction(const btCollisionObject* body0,const btCollisionObject* body1)
+btScalar btManifoldResult::calculateCombinedRollingFriction(const btCollisionObject* body0, const btCollisionObject* body1)
{
btScalar friction = body0->getRollingFriction() * body1->getFriction() + body1->getRollingFriction() * body0->getFriction();
- const btScalar MAX_FRICTION = btScalar(10.);
+ const btScalar MAX_FRICTION = btScalar(10.);
if (friction < -MAX_FRICTION)
friction = -MAX_FRICTION;
if (friction > MAX_FRICTION)
friction = MAX_FRICTION;
return friction;
-
}
-btScalar btManifoldResult::calculateCombinedSpinningFriction(const btCollisionObject* body0,const btCollisionObject* body1)
+btScalar btManifoldResult::calculateCombinedSpinningFriction(const btCollisionObject* body0, const btCollisionObject* body1)
{
- btScalar friction = body0->getSpinningFriction() * body1->getFriction() + body1->getSpinningFriction() * body0->getFriction();
-
- const btScalar MAX_FRICTION = btScalar(10.);
- if (friction < -MAX_FRICTION)
- friction = -MAX_FRICTION;
- if (friction > MAX_FRICTION)
- friction = MAX_FRICTION;
- return friction;
+ btScalar friction = body0->getSpinningFriction() * body1->getFriction() + body1->getSpinningFriction() * body0->getFriction();
+
+ const btScalar MAX_FRICTION = btScalar(10.);
+ if (friction < -MAX_FRICTION)
+ friction = -MAX_FRICTION;
+ if (friction > MAX_FRICTION)
+ friction = MAX_FRICTION;
+ return friction;
}
///User can override this material combiner by implementing gContactAddedCallback and setting body0->m_collisionFlags |= btCollisionObject::customMaterialCallback;
-btScalar btManifoldResult::calculateCombinedFriction(const btCollisionObject* body0,const btCollisionObject* body1)
+btScalar btManifoldResult::calculateCombinedFriction(const btCollisionObject* body0, const btCollisionObject* body1)
{
btScalar friction = body0->getFriction() * body1->getFriction();
- const btScalar MAX_FRICTION = btScalar(10.);
+ const btScalar MAX_FRICTION = btScalar(10.);
if (friction < -MAX_FRICTION)
friction = -MAX_FRICTION;
if (friction > MAX_FRICTION)
friction = MAX_FRICTION;
return friction;
-
}
-btScalar btManifoldResult::calculateCombinedRestitution(const btCollisionObject* body0,const btCollisionObject* body1)
+btScalar btManifoldResult::calculateCombinedRestitution(const btCollisionObject* body0, const btCollisionObject* body1)
{
return body0->getRestitution() * body1->getRestitution();
}
-btScalar btManifoldResult::calculateCombinedContactDamping(const btCollisionObject* body0,const btCollisionObject* body1)
+btScalar btManifoldResult::calculateCombinedContactDamping(const btCollisionObject* body0, const btCollisionObject* body1)
{
- return body0->getContactDamping() + body1->getContactDamping();
+ return body0->getContactDamping() + body1->getContactDamping();
}
-btScalar btManifoldResult::calculateCombinedContactStiffness(const btCollisionObject* body0,const btCollisionObject* body1)
+btScalar btManifoldResult::calculateCombinedContactStiffness(const btCollisionObject* body0, const btCollisionObject* body1)
{
-
- btScalar s0 = body0->getContactStiffness();
- btScalar s1 = body1->getContactStiffness();
-
- btScalar tmp0 = btScalar(1)/s0;
- btScalar tmp1 = btScalar(1)/s1;
- btScalar combinedStiffness = btScalar(1) / (tmp0+tmp1);
- return combinedStiffness;
-}
+ btScalar s0 = body0->getContactStiffness();
+ btScalar s1 = body1->getContactStiffness();
+ btScalar tmp0 = btScalar(1) / s0;
+ btScalar tmp1 = btScalar(1) / s1;
+ btScalar combinedStiffness = btScalar(1) / (tmp0 + tmp1);
+ return combinedStiffness;
+}
-btManifoldResult::btManifoldResult(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
- :m_manifoldPtr(0),
- m_body0Wrap(body0Wrap),
- m_body1Wrap(body1Wrap)
+btManifoldResult::btManifoldResult(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
+ : m_manifoldPtr(0),
+ m_body0Wrap(body0Wrap),
+ m_body1Wrap(body1Wrap)
#ifdef DEBUG_PART_INDEX
- ,m_partId0(-1),
- m_partId1(-1),
- m_index0(-1),
- m_index1(-1)
-#endif //DEBUG_PART_INDEX
- , m_closestPointDistanceThreshold(0)
+ ,
+ m_partId0(-1),
+ m_partId1(-1),
+ m_index0(-1),
+ m_index1(-1)
+#endif //DEBUG_PART_INDEX
+ ,
+ m_closestPointDistanceThreshold(0)
{
}
-
-void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)
+void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar depth)
{
btAssert(m_manifoldPtr);
//order in manifold needs to match
if (depth > m_manifoldPtr->getContactBreakingThreshold())
-// if (depth > m_manifoldPtr->getContactProcessingThreshold())
+ // if (depth > m_manifoldPtr->getContactProcessingThreshold())
return;
bool isSwapped = m_manifoldPtr->getBody0() != m_body0Wrap->getCollisionObject();
@@ -122,81 +118,82 @@ void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const b
btVector3 localA;
btVector3 localB;
-
+
if (isSwapped)
{
- localA = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointA );
+ localA = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointA);
localB = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld);
- } else
+ }
+ else
{
- localA = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointA );
+ localA = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointA);
localB = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld);
}
- btManifoldPoint newPt(localA,localB,normalOnBInWorld,depth);
+ btManifoldPoint newPt(localA, localB, normalOnBInWorld, depth);
newPt.m_positionWorldOnA = pointA;
newPt.m_positionWorldOnB = pointInWorld;
-
+
int insertIndex = m_manifoldPtr->getCacheEntry(newPt);
- newPt.m_combinedFriction = gCalculateCombinedFrictionCallback(m_body0Wrap->getCollisionObject(),m_body1Wrap->getCollisionObject());
- newPt.m_combinedRestitution = gCalculateCombinedRestitutionCallback(m_body0Wrap->getCollisionObject(),m_body1Wrap->getCollisionObject());
- newPt.m_combinedRollingFriction = gCalculateCombinedRollingFrictionCallback(m_body0Wrap->getCollisionObject(),m_body1Wrap->getCollisionObject());
- newPt.m_combinedSpinningFriction = gCalculateCombinedSpinningFrictionCallback(m_body0Wrap->getCollisionObject(),m_body1Wrap->getCollisionObject());
-
- if ( (m_body0Wrap->getCollisionObject()->getCollisionFlags()& btCollisionObject::CF_HAS_CONTACT_STIFFNESS_DAMPING) ||
- (m_body1Wrap->getCollisionObject()->getCollisionFlags()& btCollisionObject::CF_HAS_CONTACT_STIFFNESS_DAMPING))
- {
- newPt.m_combinedContactDamping1 = gCalculateCombinedContactDampingCallback(m_body0Wrap->getCollisionObject(),m_body1Wrap->getCollisionObject());
- newPt.m_combinedContactStiffness1 = gCalculateCombinedContactStiffnessCallback(m_body0Wrap->getCollisionObject(),m_body1Wrap->getCollisionObject());
- newPt.m_contactPointFlags |= BT_CONTACT_FLAG_CONTACT_STIFFNESS_DAMPING;
- }
-
- if ( (m_body0Wrap->getCollisionObject()->getCollisionFlags()& btCollisionObject::CF_HAS_FRICTION_ANCHOR) ||
- (m_body1Wrap->getCollisionObject()->getCollisionFlags()& btCollisionObject::CF_HAS_FRICTION_ANCHOR))
- {
- newPt.m_contactPointFlags |= BT_CONTACT_FLAG_FRICTION_ANCHOR;
- }
-
- btPlaneSpace1(newPt.m_normalWorldOnB,newPt.m_lateralFrictionDir1,newPt.m_lateralFrictionDir2);
-
-
-
- //BP mod, store contact triangles.
+ newPt.m_combinedFriction = gCalculateCombinedFrictionCallback(m_body0Wrap->getCollisionObject(), m_body1Wrap->getCollisionObject());
+ newPt.m_combinedRestitution = gCalculateCombinedRestitutionCallback(m_body0Wrap->getCollisionObject(), m_body1Wrap->getCollisionObject());
+ newPt.m_combinedRollingFriction = gCalculateCombinedRollingFrictionCallback(m_body0Wrap->getCollisionObject(), m_body1Wrap->getCollisionObject());
+ newPt.m_combinedSpinningFriction = gCalculateCombinedSpinningFrictionCallback(m_body0Wrap->getCollisionObject(), m_body1Wrap->getCollisionObject());
+
+ if ((m_body0Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_HAS_CONTACT_STIFFNESS_DAMPING) ||
+ (m_body1Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_HAS_CONTACT_STIFFNESS_DAMPING))
+ {
+ newPt.m_combinedContactDamping1 = gCalculateCombinedContactDampingCallback(m_body0Wrap->getCollisionObject(), m_body1Wrap->getCollisionObject());
+ newPt.m_combinedContactStiffness1 = gCalculateCombinedContactStiffnessCallback(m_body0Wrap->getCollisionObject(), m_body1Wrap->getCollisionObject());
+ newPt.m_contactPointFlags |= BT_CONTACT_FLAG_CONTACT_STIFFNESS_DAMPING;
+ }
+
+ if ((m_body0Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_HAS_FRICTION_ANCHOR) ||
+ (m_body1Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_HAS_FRICTION_ANCHOR))
+ {
+ newPt.m_contactPointFlags |= BT_CONTACT_FLAG_FRICTION_ANCHOR;
+ }
+
+ btPlaneSpace1(newPt.m_normalWorldOnB, newPt.m_lateralFrictionDir1, newPt.m_lateralFrictionDir2);
+
+ //BP mod, store contact triangles.
if (isSwapped)
{
newPt.m_partId0 = m_partId1;
newPt.m_partId1 = m_partId0;
- newPt.m_index0 = m_index1;
- newPt.m_index1 = m_index0;
- } else
+ newPt.m_index0 = m_index1;
+ newPt.m_index1 = m_index0;
+ }
+ else
{
newPt.m_partId0 = m_partId0;
newPt.m_partId1 = m_partId1;
- newPt.m_index0 = m_index0;
- newPt.m_index1 = m_index1;
+ newPt.m_index0 = m_index0;
+ newPt.m_index1 = m_index1;
}
//printf("depth=%f\n",depth);
///@todo, check this for any side effects
if (insertIndex >= 0)
{
//const btManifoldPoint& oldPoint = m_manifoldPtr->getContactPoint(insertIndex);
- m_manifoldPtr->replaceContactPoint(newPt,insertIndex);
- } else
+ m_manifoldPtr->replaceContactPoint(newPt, insertIndex);
+ }
+ else
{
insertIndex = m_manifoldPtr->addManifoldPoint(newPt);
}
-
+
//User can override friction and/or restitution
if (gContactAddedCallback &&
//and if either of the two bodies requires custom material
- ((m_body0Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK) ||
- (m_body1Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK)))
+ ((m_body0Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK) ||
+ (m_body1Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK)))
{
//experimental feature info, for per-triangle material etc.
- const btCollisionObjectWrapper* obj0Wrap = isSwapped? m_body1Wrap : m_body0Wrap;
- const btCollisionObjectWrapper* obj1Wrap = isSwapped? m_body0Wrap : m_body1Wrap;
- (*gContactAddedCallback)(m_manifoldPtr->getContactPoint(insertIndex),obj0Wrap,newPt.m_partId0,newPt.m_index0,obj1Wrap,newPt.m_partId1,newPt.m_index1);
+ const btCollisionObjectWrapper* obj0Wrap = isSwapped ? m_body1Wrap : m_body0Wrap;
+ const btCollisionObjectWrapper* obj1Wrap = isSwapped ? m_body0Wrap : m_body1Wrap;
+ (*gContactAddedCallback)(m_manifoldPtr->getContactPoint(insertIndex), obj0Wrap, newPt.m_partId0, newPt.m_index0, obj1Wrap, newPt.m_partId1, newPt.m_index1);
}
if (gContactStartedCallback && isNewCollision)
@@ -204,4 +201,3 @@ void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const b
gContactStartedCallback(m_manifoldPtr);
}
}
-
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btManifoldResult.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btManifoldResult.h
index 12cdafd1b6..6c0a2d9a43 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btManifoldResult.h
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btManifoldResult.h
@@ -13,7 +13,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#ifndef BT_MANIFOLD_RESULT_H
#define BT_MANIFOLD_RESULT_H
@@ -29,85 +28,81 @@ class btManifoldPoint;
#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-typedef bool (*ContactAddedCallback)(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap,int partId0,int index0,const btCollisionObjectWrapper* colObj1Wrap,int partId1,int index1);
-extern ContactAddedCallback gContactAddedCallback;
+typedef bool (*ContactAddedCallback)(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap, int partId0, int index0, const btCollisionObjectWrapper* colObj1Wrap, int partId1, int index1);
+extern ContactAddedCallback gContactAddedCallback;
//#define DEBUG_PART_INDEX 1
/// These callbacks are used to customize the algorith that combine restitution, friction, damping, Stiffness
-typedef btScalar (*CalculateCombinedCallback)(const btCollisionObject* body0,const btCollisionObject* body1);
+typedef btScalar (*CalculateCombinedCallback)(const btCollisionObject* body0, const btCollisionObject* body1);
-extern CalculateCombinedCallback gCalculateCombinedRestitutionCallback;
-extern CalculateCombinedCallback gCalculateCombinedFrictionCallback;
-extern CalculateCombinedCallback gCalculateCombinedRollingFrictionCallback;
-extern CalculateCombinedCallback gCalculateCombinedSpinningFrictionCallback;
-extern CalculateCombinedCallback gCalculateCombinedContactDampingCallback;
-extern CalculateCombinedCallback gCalculateCombinedContactStiffnessCallback;
+extern CalculateCombinedCallback gCalculateCombinedRestitutionCallback;
+extern CalculateCombinedCallback gCalculateCombinedFrictionCallback;
+extern CalculateCombinedCallback gCalculateCombinedRollingFrictionCallback;
+extern CalculateCombinedCallback gCalculateCombinedSpinningFrictionCallback;
+extern CalculateCombinedCallback gCalculateCombinedContactDampingCallback;
+extern CalculateCombinedCallback gCalculateCombinedContactStiffnessCallback;
///btManifoldResult is a helper class to manage contact results.
class btManifoldResult : public btDiscreteCollisionDetectorInterface::Result
{
protected:
-
btPersistentManifold* m_manifoldPtr;
const btCollisionObjectWrapper* m_body0Wrap;
const btCollisionObjectWrapper* m_body1Wrap;
- int m_partId0;
+ int m_partId0;
int m_partId1;
int m_index0;
int m_index1;
-
-
-public:
+public:
btManifoldResult()
:
#ifdef DEBUG_PART_INDEX
-
- m_partId0(-1),
- m_partId1(-1),
- m_index0(-1),
- m_index1(-1)
-#endif //DEBUG_PART_INDEX
- m_closestPointDistanceThreshold(0)
+
+ m_partId0(-1),
+ m_partId1(-1),
+ m_index0(-1),
+ m_index1(-1)
+#endif //DEBUG_PART_INDEX
+ m_closestPointDistanceThreshold(0)
{
}
- btManifoldResult(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
+ btManifoldResult(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap);
- virtual ~btManifoldResult() {};
+ virtual ~btManifoldResult(){};
- void setPersistentManifold(btPersistentManifold* manifoldPtr)
+ void setPersistentManifold(btPersistentManifold* manifoldPtr)
{
m_manifoldPtr = manifoldPtr;
}
- const btPersistentManifold* getPersistentManifold() const
+ const btPersistentManifold* getPersistentManifold() const
{
return m_manifoldPtr;
}
- btPersistentManifold* getPersistentManifold()
+ btPersistentManifold* getPersistentManifold()
{
return m_manifoldPtr;
}
- virtual void setShapeIdentifiersA(int partId0,int index0)
+ virtual void setShapeIdentifiersA(int partId0, int index0)
{
- m_partId0=partId0;
- m_index0=index0;
+ m_partId0 = partId0;
+ m_index0 = index0;
}
- virtual void setShapeIdentifiersB( int partId1,int index1)
+ virtual void setShapeIdentifiersB(int partId1, int index1)
{
- m_partId1=partId1;
- m_index1=index1;
+ m_partId1 = partId1;
+ m_index1 = index1;
}
+ virtual void addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar depth);
- virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth);
-
- SIMD_FORCE_INLINE void refreshContactPoints()
+ SIMD_FORCE_INLINE void refreshContactPoints()
{
btAssert(m_manifoldPtr);
if (!m_manifoldPtr->getNumContacts())
@@ -117,10 +112,11 @@ public:
if (isSwapped)
{
- m_manifoldPtr->refreshContactPoints(m_body1Wrap->getCollisionObject()->getWorldTransform(),m_body0Wrap->getCollisionObject()->getWorldTransform());
- } else
+ m_manifoldPtr->refreshContactPoints(m_body1Wrap->getCollisionObject()->getWorldTransform(), m_body0Wrap->getCollisionObject()->getWorldTransform());
+ }
+ else
{
- m_manifoldPtr->refreshContactPoints(m_body0Wrap->getCollisionObject()->getWorldTransform(),m_body1Wrap->getCollisionObject()->getWorldTransform());
+ m_manifoldPtr->refreshContactPoints(m_body0Wrap->getCollisionObject()->getWorldTransform(), m_body1Wrap->getCollisionObject()->getWorldTransform());
}
}
@@ -153,15 +149,15 @@ public:
return m_body1Wrap->getCollisionObject();
}
- btScalar m_closestPointDistanceThreshold;
+ btScalar m_closestPointDistanceThreshold;
/// in the future we can let the user override the methods to combine restitution and friction
- static btScalar calculateCombinedRestitution(const btCollisionObject* body0,const btCollisionObject* body1);
- static btScalar calculateCombinedFriction(const btCollisionObject* body0,const btCollisionObject* body1);
- static btScalar calculateCombinedRollingFriction(const btCollisionObject* body0,const btCollisionObject* body1);
- static btScalar calculateCombinedSpinningFriction(const btCollisionObject* body0,const btCollisionObject* body1);
- static btScalar calculateCombinedContactDamping(const btCollisionObject* body0,const btCollisionObject* body1);
- static btScalar calculateCombinedContactStiffness(const btCollisionObject* body0,const btCollisionObject* body1);
+ static btScalar calculateCombinedRestitution(const btCollisionObject* body0, const btCollisionObject* body1);
+ static btScalar calculateCombinedFriction(const btCollisionObject* body0, const btCollisionObject* body1);
+ static btScalar calculateCombinedRollingFriction(const btCollisionObject* body0, const btCollisionObject* body1);
+ static btScalar calculateCombinedSpinningFriction(const btCollisionObject* body0, const btCollisionObject* body1);
+ static btScalar calculateCombinedContactDamping(const btCollisionObject* body0, const btCollisionObject* body1);
+ static btScalar calculateCombinedContactStiffness(const btCollisionObject* body0, const btCollisionObject* body1);
};
-#endif //BT_MANIFOLD_RESULT_H
+#endif //BT_MANIFOLD_RESULT_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp
index 91c76a8dac..e5097ccbbf 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp
@@ -14,7 +14,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#include "LinearMath/btScalar.h"
#include "btSimulationIslandManager.h"
#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
@@ -25,8 +24,7 @@ subject to the following restrictions:
//#include <stdio.h>
#include "LinearMath/btQuickprof.h"
-btSimulationIslandManager::btSimulationIslandManager():
-m_splitIslands(true)
+btSimulationIslandManager::btSimulationIslandManager() : m_splitIslands(true)
{
}
@@ -34,53 +32,47 @@ btSimulationIslandManager::~btSimulationIslandManager()
{
}
-
void btSimulationIslandManager::initUnionFind(int n)
{
- m_unionFind.reset(n);
+ m_unionFind.reset(n);
}
-
-void btSimulationIslandManager::findUnions(btDispatcher* /* dispatcher */,btCollisionWorld* colWorld)
+void btSimulationIslandManager::findUnions(btDispatcher* /* dispatcher */, btCollisionWorld* colWorld)
{
-
{
btOverlappingPairCache* pairCachePtr = colWorld->getPairCache();
const int numOverlappingPairs = pairCachePtr->getNumOverlappingPairs();
if (numOverlappingPairs)
{
- btBroadphasePair* pairPtr = pairCachePtr->getOverlappingPairArrayPtr();
-
- for (int i=0;i<numOverlappingPairs;i++)
- {
- const btBroadphasePair& collisionPair = pairPtr[i];
- btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
- btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
+ btBroadphasePair* pairPtr = pairCachePtr->getOverlappingPairArrayPtr();
- if (((colObj0) && ((colObj0)->mergesSimulationIslands())) &&
- ((colObj1) && ((colObj1)->mergesSimulationIslands())))
+ for (int i = 0; i < numOverlappingPairs; i++)
{
+ const btBroadphasePair& collisionPair = pairPtr[i];
+ btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
+ btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
- m_unionFind.unite((colObj0)->getIslandTag(),
- (colObj1)->getIslandTag());
+ if (((colObj0) && ((colObj0)->mergesSimulationIslands())) &&
+ ((colObj1) && ((colObj1)->mergesSimulationIslands())))
+ {
+ m_unionFind.unite((colObj0)->getIslandTag(),
+ (colObj1)->getIslandTag());
+ }
}
}
- }
}
}
#ifdef STATIC_SIMULATION_ISLAND_OPTIMIZATION
-void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher)
+void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld, btDispatcher* dispatcher)
{
-
- // put the index into m_controllers into m_tag
+ // put the index into m_controllers into m_tag
int index = 0;
{
-
int i;
- for (i=0;i<colWorld->getCollisionObjectArray().size(); i++)
+ for (i = 0; i < colWorld->getCollisionObjectArray().size(); i++)
{
- btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i];
+ btCollisionObject* collisionObject = colWorld->getCollisionObjectArray()[i];
//Adding filtering here
if (!collisionObject->isStaticOrKinematicObject())
{
@@ -92,28 +84,29 @@ void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWor
}
// do the union find
- initUnionFind( index );
+ initUnionFind(index);
- findUnions(dispatcher,colWorld);
+ findUnions(dispatcher, colWorld);
}
-void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld)
+void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld)
{
- // put the islandId ('find' value) into m_tag
+ // put the islandId ('find' value) into m_tag
{
int index = 0;
int i;
- for (i=0;i<colWorld->getCollisionObjectArray().size();i++)
+ for (i = 0; i < colWorld->getCollisionObjectArray().size(); i++)
{
- btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i];
+ btCollisionObject* collisionObject = colWorld->getCollisionObjectArray()[i];
if (!collisionObject->isStaticOrKinematicObject())
{
- collisionObject->setIslandTag( m_unionFind.find(index) );
+ collisionObject->setIslandTag(m_unionFind.find(index));
//Set the correct object offset in Collision Object Array
m_unionFind.getElement(index).m_sz = i;
collisionObject->setCompanionId(-1);
index++;
- } else
+ }
+ else
{
collisionObject->setIslandTag(-1);
collisionObject->setCompanionId(-2);
@@ -122,49 +115,44 @@ void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* c
}
}
-
-#else //STATIC_SIMULATION_ISLAND_OPTIMIZATION
-void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher)
+#else //STATIC_SIMULATION_ISLAND_OPTIMIZATION
+void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld, btDispatcher* dispatcher)
{
+ initUnionFind(int(colWorld->getCollisionObjectArray().size()));
- initUnionFind( int (colWorld->getCollisionObjectArray().size()));
-
- // put the index into m_controllers into m_tag
+ // put the index into m_controllers into m_tag
{
-
int index = 0;
int i;
- for (i=0;i<colWorld->getCollisionObjectArray().size(); i++)
+ for (i = 0; i < colWorld->getCollisionObjectArray().size(); i++)
{
- btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i];
+ btCollisionObject* collisionObject = colWorld->getCollisionObjectArray()[i];
collisionObject->setIslandTag(index);
collisionObject->setCompanionId(-1);
collisionObject->setHitFraction(btScalar(1.));
index++;
-
}
}
// do the union find
- findUnions(dispatcher,colWorld);
+ findUnions(dispatcher, colWorld);
}
-void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld)
+void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld)
{
- // put the islandId ('find' value) into m_tag
+ // put the islandId ('find' value) into m_tag
{
-
-
int index = 0;
int i;
- for (i=0;i<colWorld->getCollisionObjectArray().size();i++)
+ for (i = 0; i < colWorld->getCollisionObjectArray().size(); i++)
{
- btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i];
+ btCollisionObject* collisionObject = colWorld->getCollisionObjectArray()[i];
if (!collisionObject->isStaticOrKinematicObject())
{
- collisionObject->setIslandTag( m_unionFind.find(index) );
+ collisionObject->setIslandTag(m_unionFind.find(index));
collisionObject->setCompanionId(-1);
- } else
+ }
+ else
{
collisionObject->setIslandTag(-1);
collisionObject->setCompanionId(-2);
@@ -174,72 +162,59 @@ void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* col
}
}
-#endif //STATIC_SIMULATION_ISLAND_OPTIMIZATION
+#endif //STATIC_SIMULATION_ISLAND_OPTIMIZATION
-inline int getIslandId(const btPersistentManifold* lhs)
+inline int getIslandId(const btPersistentManifold* lhs)
{
int islandId;
const btCollisionObject* rcolObj0 = static_cast<const btCollisionObject*>(lhs->getBody0());
const btCollisionObject* rcolObj1 = static_cast<const btCollisionObject*>(lhs->getBody1());
- islandId= rcolObj0->getIslandTag()>=0?rcolObj0->getIslandTag():rcolObj1->getIslandTag();
+ islandId = rcolObj0->getIslandTag() >= 0 ? rcolObj0->getIslandTag() : rcolObj1->getIslandTag();
return islandId;
-
}
-
-
/// function object that routes calls to operator<
class btPersistentManifoldSortPredicate
{
- public:
-
- SIMD_FORCE_INLINE bool operator() ( const btPersistentManifold* lhs, const btPersistentManifold* rhs ) const
- {
- return getIslandId(lhs) < getIslandId(rhs);
- }
+public:
+ SIMD_FORCE_INLINE bool operator()(const btPersistentManifold* lhs, const btPersistentManifold* rhs) const
+ {
+ return getIslandId(lhs) < getIslandId(rhs);
+ }
};
class btPersistentManifoldSortPredicateDeterministic
{
public:
-
- SIMD_FORCE_INLINE bool operator() (const btPersistentManifold* lhs, const btPersistentManifold* rhs) const
+ SIMD_FORCE_INLINE bool operator()(const btPersistentManifold* lhs, const btPersistentManifold* rhs) const
{
return (
- (getIslandId(lhs) < getIslandId(rhs))
- || ((getIslandId(lhs) == getIslandId(rhs)) && lhs->getBody0()->getBroadphaseHandle()->m_uniqueId < rhs->getBody0()->getBroadphaseHandle()->m_uniqueId)
- ||((getIslandId(lhs) == getIslandId(rhs)) && (lhs->getBody0()->getBroadphaseHandle()->m_uniqueId == rhs->getBody0()->getBroadphaseHandle()->m_uniqueId) &&
- (lhs->getBody1()->getBroadphaseHandle()->m_uniqueId < rhs->getBody1()->getBroadphaseHandle()->m_uniqueId))
- );
-
+ (getIslandId(lhs) < getIslandId(rhs)) || ((getIslandId(lhs) == getIslandId(rhs)) && lhs->getBody0()->getBroadphaseHandle()->m_uniqueId < rhs->getBody0()->getBroadphaseHandle()->m_uniqueId) || ((getIslandId(lhs) == getIslandId(rhs)) && (lhs->getBody0()->getBroadphaseHandle()->m_uniqueId == rhs->getBody0()->getBroadphaseHandle()->m_uniqueId) && (lhs->getBody1()->getBroadphaseHandle()->m_uniqueId < rhs->getBody1()->getBroadphaseHandle()->m_uniqueId)));
}
};
-
-void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld)
+void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher, btCollisionWorld* collisionWorld)
{
-
BT_PROFILE("islandUnionFindAndQuickSort");
-
+
btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
m_islandmanifold.resize(0);
//we are going to sort the unionfind array, and store the element id in the size
//afterwards, we clean unionfind, to make sure no-one uses it anymore
-
+
getUnionFind().sortIslands();
int numElem = getUnionFind().getNumElements();
- int endIslandIndex=1;
+ int endIslandIndex = 1;
int startIslandIndex;
-
//update the sleeping state for bodies, if all are sleeping
- for ( startIslandIndex=0;startIslandIndex<numElem;startIslandIndex = endIslandIndex)
+ for (startIslandIndex = 0; startIslandIndex < numElem; startIslandIndex = endIslandIndex)
{
int islandId = getUnionFind().getElement(startIslandIndex).m_id;
- for (endIslandIndex = startIslandIndex+1;(endIslandIndex<numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId);endIslandIndex++)
+ for (endIslandIndex = startIslandIndex + 1; (endIslandIndex < numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId); endIslandIndex++)
{
}
@@ -248,69 +223,68 @@ void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisio
bool allSleeping = true;
int idx;
- for (idx=startIslandIndex;idx<endIslandIndex;idx++)
+ for (idx = startIslandIndex; idx < endIslandIndex; idx++)
{
int i = getUnionFind().getElement(idx).m_sz;
btCollisionObject* colObj0 = collisionObjects[i];
if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
{
-// printf("error in island management\n");
+ // printf("error in island management\n");
}
btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
if (colObj0->getIslandTag() == islandId)
{
- if (colObj0->getActivationState()== ACTIVE_TAG ||
- colObj0->getActivationState()== DISABLE_DEACTIVATION)
+ if (colObj0->getActivationState() == ACTIVE_TAG ||
+ colObj0->getActivationState() == DISABLE_DEACTIVATION)
{
allSleeping = false;
break;
}
}
}
-
if (allSleeping)
{
int idx;
- for (idx=startIslandIndex;idx<endIslandIndex;idx++)
+ for (idx = startIslandIndex; idx < endIslandIndex; idx++)
{
int i = getUnionFind().getElement(idx).m_sz;
btCollisionObject* colObj0 = collisionObjects[i];
if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
{
-// printf("error in island management\n");
+ // printf("error in island management\n");
}
btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
if (colObj0->getIslandTag() == islandId)
{
- colObj0->setActivationState( ISLAND_SLEEPING );
+ colObj0->setActivationState(ISLAND_SLEEPING);
}
}
- } else
+ }
+ else
{
-
int idx;
- for (idx=startIslandIndex;idx<endIslandIndex;idx++)
+ for (idx = startIslandIndex; idx < endIslandIndex; idx++)
{
int i = getUnionFind().getElement(idx).m_sz;
btCollisionObject* colObj0 = collisionObjects[i];
if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
{
-// printf("error in island management\n");
+ // printf("error in island management\n");
}
btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
if (colObj0->getIslandTag() == islandId)
{
- if ( colObj0->getActivationState() == ISLAND_SLEEPING)
+ if (colObj0->getActivationState() == ISLAND_SLEEPING)
{
- colObj0->setActivationState( WANTS_DEACTIVATION);
+ colObj0->setActivationState(WANTS_DEACTIVATION);
colObj0->setDeactivationTime(0.f);
}
}
@@ -318,34 +292,30 @@ void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisio
}
}
-
int i;
int maxNumManifolds = dispatcher->getNumManifolds();
-//#define SPLIT_ISLANDS 1
-//#ifdef SPLIT_ISLANDS
+ //#define SPLIT_ISLANDS 1
+ //#ifdef SPLIT_ISLANDS
-
-//#endif //SPLIT_ISLANDS
+ //#endif //SPLIT_ISLANDS
-
- for (i=0;i<maxNumManifolds ;i++)
+ for (i = 0; i < maxNumManifolds; i++)
{
- btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i);
- if (collisionWorld->getDispatchInfo().m_deterministicOverlappingPairs)
- {
+ btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i);
+ if (collisionWorld->getDispatchInfo().m_deterministicOverlappingPairs)
+ {
if (manifold->getNumContacts() == 0)
continue;
- }
+ }
- const btCollisionObject* colObj0 = static_cast<const btCollisionObject*>(manifold->getBody0());
- const btCollisionObject* colObj1 = static_cast<const btCollisionObject*>(manifold->getBody1());
-
- ///@todo: check sleeping conditions!
- if (((colObj0) && colObj0->getActivationState() != ISLAND_SLEEPING) ||
+ const btCollisionObject* colObj0 = static_cast<const btCollisionObject*>(manifold->getBody0());
+ const btCollisionObject* colObj1 = static_cast<const btCollisionObject*>(manifold->getBody1());
+
+ ///@todo: check sleeping conditions!
+ if (((colObj0) && colObj0->getActivationState() != ISLAND_SLEEPING) ||
((colObj1) && colObj1->getActivationState() != ISLAND_SLEEPING))
{
-
//kinematic objects don't merge islands, but wake up all connected objects
if (colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING)
{
@@ -357,36 +327,34 @@ void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisio
if (colObj1->hasContactResponse())
colObj0->activate();
}
- if(m_splitIslands)
- {
+ if (m_splitIslands)
+ {
//filtering for response
- if (dispatcher->needsResponse(colObj0,colObj1))
+ if (dispatcher->needsResponse(colObj0, colObj1))
m_islandmanifold.push_back(manifold);
}
}
}
}
-
-
///@todo: this is random access, it can be walked 'cache friendly'!
-void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld, IslandCallback* callback)
+void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher, btCollisionWorld* collisionWorld, IslandCallback* callback)
{
btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
- buildIslands(dispatcher,collisionWorld);
+ buildIslands(dispatcher, collisionWorld);
- int endIslandIndex=1;
+ int endIslandIndex = 1;
int startIslandIndex;
int numElem = getUnionFind().getNumElements();
BT_PROFILE("processIslands");
- if(!m_splitIslands)
+ if (!m_splitIslands)
{
btPersistentManifold** manifold = dispatcher->getInternalManifoldPointer();
int maxNumManifolds = dispatcher->getNumManifolds();
- callback->processIsland(&collisionObjects[0],collisionObjects.size(),manifold,maxNumManifolds, -1);
+ callback->processIsland(&collisionObjects[0], collisionObjects.size(), manifold, maxNumManifolds, -1);
}
else
{
@@ -394,7 +362,7 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,
// Sort the vector using predicate and std::sort
//std::sort(islandmanifold.begin(), islandmanifold.end(), btPersistentManifoldSortPredicate);
- int numManifolds = int (m_islandmanifold.size());
+ int numManifolds = int(m_islandmanifold.size());
//tried a radix sort, but quicksort/heapsort seems still faster
//@todo rewrite island management
@@ -403,7 +371,8 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,
if (collisionWorld->getDispatchInfo().m_deterministicOverlappingPairs)
{
m_islandmanifold.quickSort(btPersistentManifoldSortPredicateDeterministic());
- } else
+ }
+ else
{
m_islandmanifold.quickSort(btPersistentManifoldSortPredicate());
}
@@ -417,55 +386,49 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,
//int islandId;
-
-
- // printf("Start Islands\n");
+ // printf("Start Islands\n");
//traverse the simulation islands, and call the solver, unless all objects are sleeping/deactivated
- for ( startIslandIndex=0;startIslandIndex<numElem;startIslandIndex = endIslandIndex)
+ for (startIslandIndex = 0; startIslandIndex < numElem; startIslandIndex = endIslandIndex)
{
int islandId = getUnionFind().getElement(startIslandIndex).m_id;
+ bool islandSleeping = true;
- bool islandSleeping = true;
-
- for (endIslandIndex = startIslandIndex;(endIslandIndex<numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId);endIslandIndex++)
- {
- int i = getUnionFind().getElement(endIslandIndex).m_sz;
- btCollisionObject* colObj0 = collisionObjects[i];
- m_islandBodies.push_back(colObj0);
- if (colObj0->isActive())
- islandSleeping = false;
- }
-
+ for (endIslandIndex = startIslandIndex; (endIslandIndex < numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId); endIslandIndex++)
+ {
+ int i = getUnionFind().getElement(endIslandIndex).m_sz;
+ btCollisionObject* colObj0 = collisionObjects[i];
+ m_islandBodies.push_back(colObj0);
+ if (colObj0->isActive())
+ islandSleeping = false;
+ }
//find the accompanying contact manifold for this islandId
int numIslandManifolds = 0;
btPersistentManifold** startManifold = 0;
- if (startManifoldIndex<numManifolds)
+ if (startManifoldIndex < numManifolds)
{
int curIslandId = getIslandId(m_islandmanifold[startManifoldIndex]);
if (curIslandId == islandId)
{
startManifold = &m_islandmanifold[startManifoldIndex];
-
- for (endManifoldIndex = startManifoldIndex+1;(endManifoldIndex<numManifolds) && (islandId == getIslandId(m_islandmanifold[endManifoldIndex]));endManifoldIndex++)
- {
+ for (endManifoldIndex = startManifoldIndex + 1; (endManifoldIndex < numManifolds) && (islandId == getIslandId(m_islandmanifold[endManifoldIndex])); endManifoldIndex++)
+ {
}
/// Process the actual simulation, only if not sleeping/deactivated
- numIslandManifolds = endManifoldIndex-startManifoldIndex;
+ numIslandManifolds = endManifoldIndex - startManifoldIndex;
}
-
}
if (!islandSleeping)
{
- callback->processIsland(&m_islandBodies[0],m_islandBodies.size(),startManifold,numIslandManifolds, islandId);
- // printf("Island callback of size:%d bodies, %d manifolds\n",islandBodies.size(),numIslandManifolds);
+ callback->processIsland(&m_islandBodies[0], m_islandBodies.size(), startManifold, numIslandManifolds, islandId);
+ // printf("Island callback of size:%d bodies, %d manifolds\n",islandBodies.size(),numIslandManifolds);
}
-
+
if (numIslandManifolds)
{
startManifoldIndex = endManifoldIndex;
@@ -473,6 +436,5 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,
m_islandBodies.resize(0);
}
- } // else if(!splitIslands)
-
+ } // else if(!splitIslands)
}
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.h
index e24c6afeca..6c2802141c 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.h
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.h
@@ -26,45 +26,39 @@ class btCollisionWorld;
class btDispatcher;
class btPersistentManifold;
-
///SimulationIslandManager creates and handles simulation islands, using btUnionFind
class btSimulationIslandManager
{
btUnionFind m_unionFind;
- btAlignedObjectArray<btPersistentManifold*> m_islandmanifold;
- btAlignedObjectArray<btCollisionObject* > m_islandBodies;
-
+ btAlignedObjectArray<btPersistentManifold*> m_islandmanifold;
+ btAlignedObjectArray<btCollisionObject*> m_islandBodies;
+
bool m_splitIslands;
-
+
public:
btSimulationIslandManager();
virtual ~btSimulationIslandManager();
+ void initUnionFind(int n);
- void initUnionFind(int n);
-
-
- btUnionFind& getUnionFind() { return m_unionFind;}
-
- virtual void updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher);
- virtual void storeIslandActivationState(btCollisionWorld* world);
+ btUnionFind& getUnionFind() { return m_unionFind; }
+ virtual void updateActivationState(btCollisionWorld* colWorld, btDispatcher* dispatcher);
+ virtual void storeIslandActivationState(btCollisionWorld* world);
- void findUnions(btDispatcher* dispatcher,btCollisionWorld* colWorld);
+ void findUnions(btDispatcher* dispatcher, btCollisionWorld* colWorld);
-
-
- struct IslandCallback
+ struct IslandCallback
{
- virtual ~IslandCallback() {};
+ virtual ~IslandCallback(){};
- virtual void processIsland(btCollisionObject** bodies,int numBodies,class btPersistentManifold** manifolds,int numManifolds, int islandId) = 0;
+ virtual void processIsland(btCollisionObject** bodies, int numBodies, class btPersistentManifold** manifolds, int numManifolds, int islandId) = 0;
};
- void buildAndProcessIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld, IslandCallback* callback);
+ void buildAndProcessIslands(btDispatcher* dispatcher, btCollisionWorld* collisionWorld, IslandCallback* callback);
- void buildIslands(btDispatcher* dispatcher,btCollisionWorld* colWorld);
+ void buildIslands(btDispatcher* dispatcher, btCollisionWorld* colWorld);
bool getSplitIslands()
{
@@ -74,8 +68,6 @@ public:
{
m_splitIslands = doSplitIslands;
}
-
};
-#endif //BT_SIMULATION_ISLAND_MANAGER_H
-
+#endif //BT_SIMULATION_ISLAND_MANAGER_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp
index e8b567e0ef..bc68b285b8 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp
@@ -21,23 +21,22 @@ subject to the following restrictions:
#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
//#include <stdio.h>
-btSphereBoxCollisionAlgorithm::btSphereBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap, bool isSwapped)
-: btActivatingCollisionAlgorithm(ci,col0Wrap,col1Wrap),
-m_ownManifold(false),
-m_manifoldPtr(mf),
-m_isSwapped(isSwapped)
+btSphereBoxCollisionAlgorithm::btSphereBoxCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* col0Wrap, const btCollisionObjectWrapper* col1Wrap, bool isSwapped)
+ : btActivatingCollisionAlgorithm(ci, col0Wrap, col1Wrap),
+ m_ownManifold(false),
+ m_manifoldPtr(mf),
+ m_isSwapped(isSwapped)
{
- const btCollisionObjectWrapper* sphereObjWrap = m_isSwapped? col1Wrap : col0Wrap;
- const btCollisionObjectWrapper* boxObjWrap = m_isSwapped? col0Wrap : col1Wrap;
-
- if (!m_manifoldPtr && m_dispatcher->needsCollision(sphereObjWrap->getCollisionObject(),boxObjWrap->getCollisionObject()))
+ const btCollisionObjectWrapper* sphereObjWrap = m_isSwapped ? col1Wrap : col0Wrap;
+ const btCollisionObjectWrapper* boxObjWrap = m_isSwapped ? col0Wrap : col1Wrap;
+
+ if (!m_manifoldPtr && m_dispatcher->needsCollision(sphereObjWrap->getCollisionObject(), boxObjWrap->getCollisionObject()))
{
- m_manifoldPtr = m_dispatcher->getNewManifold(sphereObjWrap->getCollisionObject(),boxObjWrap->getCollisionObject());
+ m_manifoldPtr = m_dispatcher->getNewManifold(sphereObjWrap->getCollisionObject(), boxObjWrap->getCollisionObject());
m_ownManifold = true;
}
}
-
btSphereBoxCollisionAlgorithm::~btSphereBoxCollisionAlgorithm()
{
if (m_ownManifold)
@@ -47,17 +46,15 @@ btSphereBoxCollisionAlgorithm::~btSphereBoxCollisionAlgorithm()
}
}
-
-
-void btSphereBoxCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
+void btSphereBoxCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
{
(void)dispatchInfo;
(void)resultOut;
if (!m_manifoldPtr)
return;
- const btCollisionObjectWrapper* sphereObjWrap = m_isSwapped? body1Wrap : body0Wrap;
- const btCollisionObjectWrapper* boxObjWrap = m_isSwapped? body0Wrap : body1Wrap;
+ const btCollisionObjectWrapper* sphereObjWrap = m_isSwapped ? body1Wrap : body0Wrap;
+ const btCollisionObjectWrapper* boxObjWrap = m_isSwapped ? body0Wrap : body1Wrap;
btVector3 pOnBox;
@@ -83,10 +80,9 @@ void btSphereBoxCollisionAlgorithm::processCollision (const btCollisionObjectWra
resultOut->refreshContactPoints();
}
}
-
}
-btScalar btSphereBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+btScalar btSphereBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0, btCollisionObject* col1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
{
(void)resultOut;
(void)dispatchInfo;
@@ -97,27 +93,26 @@ btScalar btSphereBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject*
return btScalar(1.);
}
-
-bool btSphereBoxCollisionAlgorithm::getSphereDistance(const btCollisionObjectWrapper* boxObjWrap, btVector3& pointOnBox, btVector3& normal, btScalar& penetrationDepth, const btVector3& sphereCenter, btScalar fRadius, btScalar maxContactDistance )
+bool btSphereBoxCollisionAlgorithm::getSphereDistance(const btCollisionObjectWrapper* boxObjWrap, btVector3& pointOnBox, btVector3& normal, btScalar& penetrationDepth, const btVector3& sphereCenter, btScalar fRadius, btScalar maxContactDistance)
{
- const btBoxShape* boxShape= (const btBoxShape*)boxObjWrap->getCollisionShape();
- btVector3 const &boxHalfExtent = boxShape->getHalfExtentsWithoutMargin();
+ const btBoxShape* boxShape = (const btBoxShape*)boxObjWrap->getCollisionShape();
+ btVector3 const& boxHalfExtent = boxShape->getHalfExtentsWithoutMargin();
btScalar boxMargin = boxShape->getMargin();
penetrationDepth = 1.0f;
// convert the sphere position to the box's local space
- btTransform const &m44T = boxObjWrap->getWorldTransform();
+ btTransform const& m44T = boxObjWrap->getWorldTransform();
btVector3 sphereRelPos = m44T.invXform(sphereCenter);
// Determine the closest point to the sphere center in the box
btVector3 closestPoint = sphereRelPos;
- closestPoint.setX( btMin(boxHalfExtent.getX(), closestPoint.getX()) );
- closestPoint.setX( btMax(-boxHalfExtent.getX(), closestPoint.getX()) );
- closestPoint.setY( btMin(boxHalfExtent.getY(), closestPoint.getY()) );
- closestPoint.setY( btMax(-boxHalfExtent.getY(), closestPoint.getY()) );
- closestPoint.setZ( btMin(boxHalfExtent.getZ(), closestPoint.getZ()) );
- closestPoint.setZ( btMax(-boxHalfExtent.getZ(), closestPoint.getZ()) );
-
+ closestPoint.setX(btMin(boxHalfExtent.getX(), closestPoint.getX()));
+ closestPoint.setX(btMax(-boxHalfExtent.getX(), closestPoint.getX()));
+ closestPoint.setY(btMin(boxHalfExtent.getY(), closestPoint.getY()));
+ closestPoint.setY(btMax(-boxHalfExtent.getY(), closestPoint.getY()));
+ closestPoint.setZ(btMin(boxHalfExtent.getZ(), closestPoint.getZ()));
+ closestPoint.setZ(btMax(-boxHalfExtent.getZ(), closestPoint.getZ()));
+
btScalar intersectionDist = fRadius + boxMargin;
btScalar contactDist = intersectionDist + maxContactDistance;
normal = sphereRelPos - closestPoint;
@@ -136,42 +131,42 @@ bool btSphereBoxCollisionAlgorithm::getSphereDistance(const btCollisionObjectWra
{
distance = -getSpherePenetration(boxHalfExtent, sphereRelPos, closestPoint, normal);
}
- else //compute the penetration details
+ else //compute the penetration details
{
distance = normal.length();
normal /= distance;
}
pointOnBox = closestPoint + normal * boxMargin;
-// v3PointOnSphere = sphereRelPos - (normal * fRadius);
+ // v3PointOnSphere = sphereRelPos - (normal * fRadius);
penetrationDepth = distance - intersectionDist;
// transform back in world space
btVector3 tmp = m44T(pointOnBox);
pointOnBox = tmp;
-// tmp = m44T(v3PointOnSphere);
-// v3PointOnSphere = tmp;
+ // tmp = m44T(v3PointOnSphere);
+ // v3PointOnSphere = tmp;
tmp = m44T.getBasis() * normal;
normal = tmp;
return true;
}
-btScalar btSphereBoxCollisionAlgorithm::getSpherePenetration( btVector3 const &boxHalfExtent, btVector3 const &sphereRelPos, btVector3 &closestPoint, btVector3& normal )
+btScalar btSphereBoxCollisionAlgorithm::getSpherePenetration(btVector3 const& boxHalfExtent, btVector3 const& sphereRelPos, btVector3& closestPoint, btVector3& normal)
{
//project the center of the sphere on the closest face of the box
btScalar faceDist = boxHalfExtent.getX() - sphereRelPos.getX();
btScalar minDist = faceDist;
- closestPoint.setX( boxHalfExtent.getX() );
- normal.setValue(btScalar(1.0f), btScalar(0.0f), btScalar(0.0f));
+ closestPoint.setX(boxHalfExtent.getX());
+ normal.setValue(btScalar(1.0f), btScalar(0.0f), btScalar(0.0f));
faceDist = boxHalfExtent.getX() + sphereRelPos.getX();
if (faceDist < minDist)
{
minDist = faceDist;
closestPoint = sphereRelPos;
- closestPoint.setX( -boxHalfExtent.getX() );
- normal.setValue(btScalar(-1.0f), btScalar(0.0f), btScalar(0.0f));
+ closestPoint.setX(-boxHalfExtent.getX());
+ normal.setValue(btScalar(-1.0f), btScalar(0.0f), btScalar(0.0f));
}
faceDist = boxHalfExtent.getY() - sphereRelPos.getY();
@@ -179,8 +174,8 @@ btScalar btSphereBoxCollisionAlgorithm::getSpherePenetration( btVector3 const &b
{
minDist = faceDist;
closestPoint = sphereRelPos;
- closestPoint.setY( boxHalfExtent.getY() );
- normal.setValue(btScalar(0.0f), btScalar(1.0f), btScalar(0.0f));
+ closestPoint.setY(boxHalfExtent.getY());
+ normal.setValue(btScalar(0.0f), btScalar(1.0f), btScalar(0.0f));
}
faceDist = boxHalfExtent.getY() + sphereRelPos.getY();
@@ -188,8 +183,8 @@ btScalar btSphereBoxCollisionAlgorithm::getSpherePenetration( btVector3 const &b
{
minDist = faceDist;
closestPoint = sphereRelPos;
- closestPoint.setY( -boxHalfExtent.getY() );
- normal.setValue(btScalar(0.0f), btScalar(-1.0f), btScalar(0.0f));
+ closestPoint.setY(-boxHalfExtent.getY());
+ normal.setValue(btScalar(0.0f), btScalar(-1.0f), btScalar(0.0f));
}
faceDist = boxHalfExtent.getZ() - sphereRelPos.getZ();
@@ -197,8 +192,8 @@ btScalar btSphereBoxCollisionAlgorithm::getSpherePenetration( btVector3 const &b
{
minDist = faceDist;
closestPoint = sphereRelPos;
- closestPoint.setZ( boxHalfExtent.getZ() );
- normal.setValue(btScalar(0.0f), btScalar(0.0f), btScalar(1.0f));
+ closestPoint.setZ(boxHalfExtent.getZ());
+ normal.setValue(btScalar(0.0f), btScalar(0.0f), btScalar(1.0f));
}
faceDist = boxHalfExtent.getZ() + sphereRelPos.getZ();
@@ -206,8 +201,8 @@ btScalar btSphereBoxCollisionAlgorithm::getSpherePenetration( btVector3 const &b
{
minDist = faceDist;
closestPoint = sphereRelPos;
- closestPoint.setZ( -boxHalfExtent.getZ() );
- normal.setValue(btScalar(0.0f), btScalar(0.0f), btScalar(-1.0f));
+ closestPoint.setZ(-boxHalfExtent.getZ());
+ normal.setValue(btScalar(0.0f), btScalar(0.0f), btScalar(-1.0f));
}
return minDist;
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h
index eefaedc9e7..3348bc89af 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h
@@ -28,21 +28,20 @@ class btPersistentManifold;
/// Other features are frame-coherency (persistent data) and collision response.
class btSphereBoxCollisionAlgorithm : public btActivatingCollisionAlgorithm
{
- bool m_ownManifold;
- btPersistentManifold* m_manifoldPtr;
- bool m_isSwapped;
-
-public:
+ bool m_ownManifold;
+ btPersistentManifold* m_manifoldPtr;
+ bool m_isSwapped;
- btSphereBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap, bool isSwapped);
+public:
+ btSphereBoxCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped);
virtual ~btSphereBoxCollisionAlgorithm();
- virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
- virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
- virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr && m_ownManifold)
{
@@ -50,26 +49,25 @@ public:
}
}
- bool getSphereDistance( const btCollisionObjectWrapper* boxObjWrap, btVector3& v3PointOnBox, btVector3& normal, btScalar& penetrationDepth, const btVector3& v3SphereCenter, btScalar fRadius, btScalar maxContactDistance );
+ bool getSphereDistance(const btCollisionObjectWrapper* boxObjWrap, btVector3& v3PointOnBox, btVector3& normal, btScalar& penetrationDepth, const btVector3& v3SphereCenter, btScalar fRadius, btScalar maxContactDistance);
+
+ btScalar getSpherePenetration(btVector3 const& boxHalfExtent, btVector3 const& sphereRelPos, btVector3& closestPoint, btVector3& normal);
- btScalar getSpherePenetration( btVector3 const &boxHalfExtent, btVector3 const &sphereRelPos, btVector3 &closestPoint, btVector3& normal );
-
- struct CreateFunc :public btCollisionAlgorithmCreateFunc
+ struct CreateFunc : public btCollisionAlgorithmCreateFunc
{
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereBoxCollisionAlgorithm));
if (!m_swapped)
{
- return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0Wrap,body1Wrap,false);
- } else
+ return new (mem) btSphereBoxCollisionAlgorithm(0, ci, body0Wrap, body1Wrap, false);
+ }
+ else
{
- return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0Wrap,body1Wrap,true);
+ return new (mem) btSphereBoxCollisionAlgorithm(0, ci, body0Wrap, body1Wrap, true);
}
}
};
-
};
-#endif //BT_SPHERE_BOX_COLLISION_ALGORITHM_H
-
+#endif //BT_SPHERE_BOX_COLLISION_ALGORITHM_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp
index 27eaec3059..7fa0559f97 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp
@@ -20,14 +20,14 @@ subject to the following restrictions:
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
-btSphereSphereCollisionAlgorithm::btSphereSphereCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap)
-: btActivatingCollisionAlgorithm(ci,col0Wrap,col1Wrap),
-m_ownManifold(false),
-m_manifoldPtr(mf)
+btSphereSphereCollisionAlgorithm::btSphereSphereCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* col0Wrap, const btCollisionObjectWrapper* col1Wrap)
+ : btActivatingCollisionAlgorithm(ci, col0Wrap, col1Wrap),
+ m_ownManifold(false),
+ m_manifoldPtr(mf)
{
if (!m_manifoldPtr)
{
- m_manifoldPtr = m_dispatcher->getNewManifold(col0Wrap->getCollisionObject(),col1Wrap->getCollisionObject());
+ m_manifoldPtr = m_dispatcher->getNewManifold(col0Wrap->getCollisionObject(), col1Wrap->getCollisionObject());
m_ownManifold = true;
}
}
@@ -41,7 +41,7 @@ btSphereSphereCollisionAlgorithm::~btSphereSphereCollisionAlgorithm()
}
}
-void btSphereSphereCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+void btSphereSphereCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* col0Wrap, const btCollisionObjectWrapper* col1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
{
(void)dispatchInfo;
@@ -53,27 +53,27 @@ void btSphereSphereCollisionAlgorithm::processCollision (const btCollisionObject
btSphereShape* sphere0 = (btSphereShape*)col0Wrap->getCollisionShape();
btSphereShape* sphere1 = (btSphereShape*)col1Wrap->getCollisionShape();
- btVector3 diff = col0Wrap->getWorldTransform().getOrigin()- col1Wrap->getWorldTransform().getOrigin();
+ btVector3 diff = col0Wrap->getWorldTransform().getOrigin() - col1Wrap->getWorldTransform().getOrigin();
btScalar len = diff.length();
btScalar radius0 = sphere0->getRadius();
btScalar radius1 = sphere1->getRadius();
#ifdef CLEAR_MANIFOLD
- m_manifoldPtr->clearManifold(); //don't do this, it disables warmstarting
+ m_manifoldPtr->clearManifold(); //don't do this, it disables warmstarting
#endif
///iff distance positive, don't generate a new contact
- if ( len > (radius0+radius1+resultOut->m_closestPointDistanceThreshold))
+ if (len > (radius0 + radius1 + resultOut->m_closestPointDistanceThreshold))
{
#ifndef CLEAR_MANIFOLD
resultOut->refreshContactPoints();
-#endif //CLEAR_MANIFOLD
+#endif //CLEAR_MANIFOLD
return;
}
///distance (negative means penetration)
- btScalar dist = len - (radius0+radius1);
+ btScalar dist = len - (radius0 + radius1);
- btVector3 normalOnSurfaceB(1,0,0);
+ btVector3 normalOnSurfaceB(1, 0, 0);
if (len > SIMD_EPSILON)
{
normalOnSurfaceB = diff / len;
@@ -82,20 +82,18 @@ void btSphereSphereCollisionAlgorithm::processCollision (const btCollisionObject
///point on A (worldspace)
///btVector3 pos0 = col0->getWorldTransform().getOrigin() - radius0 * normalOnSurfaceB;
///point on B (worldspace)
- btVector3 pos1 = col1Wrap->getWorldTransform().getOrigin() + radius1* normalOnSurfaceB;
+ btVector3 pos1 = col1Wrap->getWorldTransform().getOrigin() + radius1 * normalOnSurfaceB;
/// report a contact. internally this will be kept persistent, and contact reduction is done
-
-
- resultOut->addContactPoint(normalOnSurfaceB,pos1,dist);
+
+ resultOut->addContactPoint(normalOnSurfaceB, pos1, dist);
#ifndef CLEAR_MANIFOLD
resultOut->refreshContactPoints();
-#endif //CLEAR_MANIFOLD
-
+#endif //CLEAR_MANIFOLD
}
-btScalar btSphereSphereCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+btScalar btSphereSphereCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0, btCollisionObject* col1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
{
(void)col0;
(void)col1;
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h
index 3517a568a9..b08d0df76d 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h
@@ -28,39 +28,37 @@ class btPersistentManifold;
/// Also provides the most basic sample for custom/user btCollisionAlgorithm
class btSphereSphereCollisionAlgorithm : public btActivatingCollisionAlgorithm
{
- bool m_ownManifold;
- btPersistentManifold* m_manifoldPtr;
-
+ bool m_ownManifold;
+ btPersistentManifold* m_manifoldPtr;
+
public:
- btSphereSphereCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap);
+ btSphereSphereCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* col0Wrap, const btCollisionObjectWrapper* col1Wrap);
btSphereSphereCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
: btActivatingCollisionAlgorithm(ci) {}
- virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
- virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
- virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr && m_ownManifold)
{
manifoldArray.push_back(m_manifoldPtr);
}
}
-
+
virtual ~btSphereSphereCollisionAlgorithm();
- struct CreateFunc :public btCollisionAlgorithmCreateFunc
+ struct CreateFunc : public btCollisionAlgorithmCreateFunc
{
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap)
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* col0Wrap, const btCollisionObjectWrapper* col1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereSphereCollisionAlgorithm));
- return new(mem) btSphereSphereCollisionAlgorithm(0,ci,col0Wrap,col1Wrap);
+ return new (mem) btSphereSphereCollisionAlgorithm(0, ci, col0Wrap, col1Wrap);
}
};
-
};
-#endif //BT_SPHERE_SPHERE_COLLISION_ALGORITHM_H
-
+#endif //BT_SPHERE_SPHERE_COLLISION_ALGORITHM_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp
index 86d4e74400..1bc3056c01 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp
@@ -13,7 +13,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#include "btSphereTriangleCollisionAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h"
@@ -21,15 +20,15 @@ subject to the following restrictions:
#include "SphereTriangleDetector.h"
#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
-btSphereTriangleCollisionAlgorithm::btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool swapped)
-: btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap),
-m_ownManifold(false),
-m_manifoldPtr(mf),
-m_swapped(swapped)
+btSphereTriangleCollisionAlgorithm::btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool swapped)
+ : btActivatingCollisionAlgorithm(ci, body0Wrap, body1Wrap),
+ m_ownManifold(false),
+ m_manifoldPtr(mf),
+ m_swapped(swapped)
{
if (!m_manifoldPtr)
{
- m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(),body1Wrap->getCollisionObject());
+ m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(), body1Wrap->getCollisionObject());
m_ownManifold = true;
}
}
@@ -43,36 +42,35 @@ btSphereTriangleCollisionAlgorithm::~btSphereTriangleCollisionAlgorithm()
}
}
-void btSphereTriangleCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+void btSphereTriangleCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* col0Wrap, const btCollisionObjectWrapper* col1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
{
if (!m_manifoldPtr)
return;
- const btCollisionObjectWrapper* sphereObjWrap = m_swapped? col1Wrap : col0Wrap;
- const btCollisionObjectWrapper* triObjWrap = m_swapped? col0Wrap : col1Wrap;
+ const btCollisionObjectWrapper* sphereObjWrap = m_swapped ? col1Wrap : col0Wrap;
+ const btCollisionObjectWrapper* triObjWrap = m_swapped ? col0Wrap : col1Wrap;
btSphereShape* sphere = (btSphereShape*)sphereObjWrap->getCollisionShape();
btTriangleShape* triangle = (btTriangleShape*)triObjWrap->getCollisionShape();
-
+
/// report a contact. internally this will be kept persistent, and contact reduction is done
resultOut->setPersistentManifold(m_manifoldPtr);
- SphereTriangleDetector detector(sphere,triangle, m_manifoldPtr->getContactBreakingThreshold()+ resultOut->m_closestPointDistanceThreshold);
-
+ SphereTriangleDetector detector(sphere, triangle, m_manifoldPtr->getContactBreakingThreshold() + resultOut->m_closestPointDistanceThreshold);
+
btDiscreteCollisionDetectorInterface::ClosestPointInput input;
- input.m_maximumDistanceSquared = btScalar(BT_LARGE_FLOAT);///@todo: tighter bounds
+ input.m_maximumDistanceSquared = btScalar(BT_LARGE_FLOAT); ///@todo: tighter bounds
input.m_transformA = sphereObjWrap->getWorldTransform();
input.m_transformB = triObjWrap->getWorldTransform();
bool swapResults = m_swapped;
- detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw,swapResults);
+ detector.getClosestPoints(input, *resultOut, dispatchInfo.m_debugDraw, swapResults);
if (m_ownManifold)
resultOut->refreshContactPoints();
-
}
-btScalar btSphereTriangleCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+btScalar btSphereTriangleCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0, btCollisionObject* col1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
{
(void)resultOut;
(void)dispatchInfo;
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h
index 6b6e39a72b..d660222f16 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h
@@ -27,43 +27,39 @@ class btPersistentManifold;
/// Also provides the most basic sample for custom/user btCollisionAlgorithm
class btSphereTriangleCollisionAlgorithm : public btActivatingCollisionAlgorithm
{
- bool m_ownManifold;
- btPersistentManifold* m_manifoldPtr;
- bool m_swapped;
-
+ bool m_ownManifold;
+ btPersistentManifold* m_manifoldPtr;
+ bool m_swapped;
+
public:
- btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool swapped);
+ btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool swapped);
btSphereTriangleCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
: btActivatingCollisionAlgorithm(ci) {}
- virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
- virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
- virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr && m_ownManifold)
{
manifoldArray.push_back(m_manifoldPtr);
}
}
-
+
virtual ~btSphereTriangleCollisionAlgorithm();
- struct CreateFunc :public btCollisionAlgorithmCreateFunc
+ struct CreateFunc : public btCollisionAlgorithmCreateFunc
{
-
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
{
-
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereTriangleCollisionAlgorithm));
- return new(mem) btSphereTriangleCollisionAlgorithm(ci.m_manifold,ci,body0Wrap,body1Wrap,m_swapped);
+ return new (mem) btSphereTriangleCollisionAlgorithm(ci.m_manifold, ci, body0Wrap, body1Wrap, m_swapped);
}
};
-
};
-#endif //BT_SPHERE_TRIANGLE_COLLISION_ALGORITHM_H
-
+#endif //BT_SPHERE_TRIANGLE_COLLISION_ALGORITHM_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btUnionFind.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btUnionFind.cpp
index 5222933595..816bf1e6ad 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btUnionFind.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btUnionFind.cpp
@@ -15,68 +15,60 @@ subject to the following restrictions:
#include "btUnionFind.h"
-
-
btUnionFind::~btUnionFind()
{
Free();
-
}
btUnionFind::btUnionFind()
-{
-
+{
}
-void btUnionFind::allocate(int N)
+void btUnionFind::allocate(int N)
{
m_elements.resize(N);
}
-void btUnionFind::Free()
+void btUnionFind::Free()
{
m_elements.clear();
}
-
-void btUnionFind::reset(int N)
+void btUnionFind::reset(int N)
{
allocate(N);
- for (int i = 0; i < N; i++)
- {
- m_elements[i].m_id = i; m_elements[i].m_sz = 1;
- }
+ for (int i = 0; i < N; i++)
+ {
+ m_elements[i].m_id = i;
+ m_elements[i].m_sz = 1;
+ }
}
-
class btUnionFindElementSortPredicate
{
- public:
-
- bool operator() ( const btElement& lhs, const btElement& rhs ) const
- {
- return lhs.m_id < rhs.m_id;
- }
+public:
+ bool operator()(const btElement& lhs, const btElement& rhs) const
+ {
+ return lhs.m_id < rhs.m_id;
+ }
};
///this is a special operation, destroying the content of btUnionFind.
///it sorts the elements, based on island id, in order to make it easy to iterate over islands
-void btUnionFind::sortIslands()
+void btUnionFind::sortIslands()
{
-
//first store the original body index, and islandId
int numElements = m_elements.size();
-
- for (int i=0;i<numElements;i++)
+
+ for (int i = 0; i < numElements; i++)
{
m_elements[i].m_id = find(i);
#ifndef STATIC_SIMULATION_ISLAND_OPTIMIZATION
m_elements[i].m_sz = i;
-#endif //STATIC_SIMULATION_ISLAND_OPTIMIZATION
+#endif //STATIC_SIMULATION_ISLAND_OPTIMIZATION
}
-
- // Sort the vector using predicate and std::sort
- //std::sort(m_elements.begin(), m_elements.end(), btUnionFindElementSortPredicate);
- m_elements.quickSort(btUnionFindElementSortPredicate());
+ // Sort the vector using predicate and std::sort
+ //std::sort(m_elements.begin(), m_elements.end(), btUnionFindElementSortPredicate);
+ m_elements.quickSort(btUnionFindElementSortPredicate());
}
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btUnionFind.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btUnionFind.h
index ef2a29202f..d422ef55eb 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btUnionFind.h
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btUnionFind.h
@@ -23,107 +23,101 @@ subject to the following restrictions:
///see for discussion of static island optimizations by Vroonsh here: http://code.google.com/p/bullet/issues/detail?id=406
#define STATIC_SIMULATION_ISLAND_OPTIMIZATION 1
-struct btElement
+struct btElement
{
- int m_id;
- int m_sz;
+ int m_id;
+ int m_sz;
};
///UnionFind calculates connected subsets
// Implements weighted Quick Union with path compression
// optimization: could use short ints instead of ints (halving memory, would limit the number of rigid bodies to 64k, sounds reasonable)
class btUnionFind
- {
- private:
- btAlignedObjectArray<btElement> m_elements;
-
- public:
-
- btUnionFind();
- ~btUnionFind();
-
-
- //this is a special operation, destroying the content of btUnionFind.
- //it sorts the elements, based on island id, in order to make it easy to iterate over islands
- void sortIslands();
-
- void reset(int N);
-
- SIMD_FORCE_INLINE int getNumElements() const
- {
- return int(m_elements.size());
- }
- SIMD_FORCE_INLINE bool isRoot(int x) const
- {
- return (x == m_elements[x].m_id);
- }
-
- btElement& getElement(int index)
- {
- return m_elements[index];
- }
- const btElement& getElement(int index) const
- {
- return m_elements[index];
- }
-
- void allocate(int N);
- void Free();
-
-
-
-
- int find(int p, int q)
- {
- return (find(p) == find(q));
- }
-
- void unite(int p, int q)
- {
- int i = find(p), j = find(q);
- if (i == j)
- return;
+{
+private:
+ btAlignedObjectArray<btElement> m_elements;
+
+public:
+ btUnionFind();
+ ~btUnionFind();
+
+ //this is a special operation, destroying the content of btUnionFind.
+ //it sorts the elements, based on island id, in order to make it easy to iterate over islands
+ void sortIslands();
+
+ void reset(int N);
+
+ SIMD_FORCE_INLINE int getNumElements() const
+ {
+ return int(m_elements.size());
+ }
+ SIMD_FORCE_INLINE bool isRoot(int x) const
+ {
+ return (x == m_elements[x].m_id);
+ }
+
+ btElement& getElement(int index)
+ {
+ return m_elements[index];
+ }
+ const btElement& getElement(int index) const
+ {
+ return m_elements[index];
+ }
+
+ void allocate(int N);
+ void Free();
+
+ int find(int p, int q)
+ {
+ return (find(p) == find(q));
+ }
+
+ void unite(int p, int q)
+ {
+ int i = find(p), j = find(q);
+ if (i == j)
+ return;
#ifndef USE_PATH_COMPRESSION
- //weighted quick union, this keeps the 'trees' balanced, and keeps performance of unite O( log(n) )
- if (m_elements[i].m_sz < m_elements[j].m_sz)
- {
- m_elements[i].m_id = j; m_elements[j].m_sz += m_elements[i].m_sz;
- }
- else
- {
- m_elements[j].m_id = i; m_elements[i].m_sz += m_elements[j].m_sz;
- }
-#else
- m_elements[i].m_id = j; m_elements[j].m_sz += m_elements[i].m_sz;
-#endif //USE_PATH_COMPRESSION
+ //weighted quick union, this keeps the 'trees' balanced, and keeps performance of unite O( log(n) )
+ if (m_elements[i].m_sz < m_elements[j].m_sz)
+ {
+ m_elements[i].m_id = j;
+ m_elements[j].m_sz += m_elements[i].m_sz;
+ }
+ else
+ {
+ m_elements[j].m_id = i;
+ m_elements[i].m_sz += m_elements[j].m_sz;
}
+#else
+ m_elements[i].m_id = j;
+ m_elements[j].m_sz += m_elements[i].m_sz;
+#endif //USE_PATH_COMPRESSION
+ }
+
+ int find(int x)
+ {
+ //btAssert(x < m_N);
+ //btAssert(x >= 0);
- int find(int x)
- {
+ while (x != m_elements[x].m_id)
+ {
+ //not really a reason not to use path compression, and it flattens the trees/improves find performance dramatically
+
+#ifdef USE_PATH_COMPRESSION
+ const btElement* elementPtr = &m_elements[m_elements[x].m_id];
+ m_elements[x].m_id = elementPtr->m_id;
+ x = elementPtr->m_id;
+#else //
+ x = m_elements[x].m_id;
+#endif
//btAssert(x < m_N);
//btAssert(x >= 0);
-
- while (x != m_elements[x].m_id)
- {
- //not really a reason not to use path compression, and it flattens the trees/improves find performance dramatically
-
- #ifdef USE_PATH_COMPRESSION
- const btElement* elementPtr = &m_elements[m_elements[x].m_id];
- m_elements[x].m_id = elementPtr->m_id;
- x = elementPtr->m_id;
- #else//
- x = m_elements[x].m_id;
- #endif
- //btAssert(x < m_N);
- //btAssert(x >= 0);
-
- }
- return x;
}
+ return x;
+ }
+};
-
- };
-
-
-#endif //BT_UNION_FIND_H
+#endif //BT_UNION_FIND_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btBox2dShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btBox2dShape.cpp
index ecce028c2e..a3d8075daf 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btBox2dShape.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btBox2dShape.cpp
@@ -15,28 +15,23 @@ subject to the following restrictions:
#include "btBox2dShape.h"
+//{
-//{
-
-
-void btBox2dShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+void btBox2dShape::getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
{
- btTransformAabb(getHalfExtentsWithoutMargin(),getMargin(),t,aabbMin,aabbMax);
+ btTransformAabb(getHalfExtentsWithoutMargin(), getMargin(), t, aabbMin, aabbMax);
}
-
-void btBox2dShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+void btBox2dShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
{
//btScalar margin = btScalar(0.);
btVector3 halfExtents = getHalfExtentsWithMargin();
- btScalar lx=btScalar(2.)*(halfExtents.x());
- btScalar ly=btScalar(2.)*(halfExtents.y());
- btScalar lz=btScalar(2.)*(halfExtents.z());
-
- inertia.setValue(mass/(btScalar(12.0)) * (ly*ly + lz*lz),
- mass/(btScalar(12.0)) * (lx*lx + lz*lz),
- mass/(btScalar(12.0)) * (lx*lx + ly*ly));
+ btScalar lx = btScalar(2.) * (halfExtents.x());
+ btScalar ly = btScalar(2.) * (halfExtents.y());
+ btScalar lz = btScalar(2.) * (halfExtents.z());
+ inertia.setValue(mass / (btScalar(12.0)) * (ly * ly + lz * lz),
+ mass / (btScalar(12.0)) * (lx * lx + lz * lz),
+ mass / (btScalar(12.0)) * (lx * lx + ly * ly));
}
-
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btBox2dShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btBox2dShape.h
index 22bee4f2c8..7e085f9e2e 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btBox2dShape.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btBox2dShape.h
@@ -23,9 +23,9 @@ subject to the following restrictions:
#include "LinearMath/btMinMax.h"
///The btBox2dShape is a box primitive around the origin, its sides axis aligned with length specified by half extents, in local shape coordinates. When used as part of a btCollisionObject or btRigidBody it will be an oriented box in world space.
-ATTRIBUTE_ALIGNED16(class) btBox2dShape: public btPolyhedralConvexShape
+ATTRIBUTE_ALIGNED16(class)
+btBox2dShape : public btPolyhedralConvexShape
{
-
//btVector3 m_boxHalfExtents1; //use m_implicitShapeDimensions instead
btVector3 m_centroid;
@@ -33,79 +33,75 @@ ATTRIBUTE_ALIGNED16(class) btBox2dShape: public btPolyhedralConvexShape
btVector3 m_normals[4];
public:
-
BT_DECLARE_ALIGNED_ALLOCATOR();
btVector3 getHalfExtentsWithMargin() const
{
btVector3 halfExtents = getHalfExtentsWithoutMargin();
- btVector3 margin(getMargin(),getMargin(),getMargin());
+ btVector3 margin(getMargin(), getMargin(), getMargin());
halfExtents += margin;
return halfExtents;
}
-
+
const btVector3& getHalfExtentsWithoutMargin() const
{
- return m_implicitShapeDimensions;//changed in Bullet 2.63: assume the scaling and margin are included
+ return m_implicitShapeDimensions; //changed in Bullet 2.63: assume the scaling and margin are included
}
-
- virtual btVector3 localGetSupportingVertex(const btVector3& vec) const
+ virtual btVector3 localGetSupportingVertex(const btVector3& vec) const
{
btVector3 halfExtents = getHalfExtentsWithoutMargin();
- btVector3 margin(getMargin(),getMargin(),getMargin());
+ btVector3 margin(getMargin(), getMargin(), getMargin());
halfExtents += margin;
-
+
return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
- btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
- btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
+ btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
+ btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
}
- SIMD_FORCE_INLINE btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+ SIMD_FORCE_INLINE btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const
{
const btVector3& halfExtents = getHalfExtentsWithoutMargin();
-
+
return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
- btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
- btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
+ btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
+ btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
}
- virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
{
const btVector3& halfExtents = getHalfExtentsWithoutMargin();
-
- for (int i=0;i<numVectors;i++)
+
+ for (int i = 0; i < numVectors; i++)
{
const btVector3& vec = vectors[i];
supportVerticesOut[i].setValue(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
- btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
- btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
+ btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
+ btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
}
-
}
-
///a btBox2dShape is a flat 2D box in the X-Y plane (Z extents are zero)
- btBox2dShape( const btVector3& boxHalfExtents)
+ btBox2dShape(const btVector3& boxHalfExtents)
: btPolyhedralConvexShape(),
- m_centroid(0,0,0)
+ m_centroid(0, 0, 0)
{
- m_vertices[0].setValue(-boxHalfExtents.getX(),-boxHalfExtents.getY(),0);
- m_vertices[1].setValue(boxHalfExtents.getX(),-boxHalfExtents.getY(),0);
- m_vertices[2].setValue(boxHalfExtents.getX(),boxHalfExtents.getY(),0);
- m_vertices[3].setValue(-boxHalfExtents.getX(),boxHalfExtents.getY(),0);
+ m_vertices[0].setValue(-boxHalfExtents.getX(), -boxHalfExtents.getY(), 0);
+ m_vertices[1].setValue(boxHalfExtents.getX(), -boxHalfExtents.getY(), 0);
+ m_vertices[2].setValue(boxHalfExtents.getX(), boxHalfExtents.getY(), 0);
+ m_vertices[3].setValue(-boxHalfExtents.getX(), boxHalfExtents.getY(), 0);
- m_normals[0].setValue(0,-1,0);
- m_normals[1].setValue(1,0,0);
- m_normals[2].setValue(0,1,0);
- m_normals[3].setValue(-1,0,0);
+ m_normals[0].setValue(0, -1, 0);
+ m_normals[1].setValue(1, 0, 0);
+ m_normals[2].setValue(0, 1, 0);
+ m_normals[3].setValue(-1, 0, 0);
btScalar minDimension = boxHalfExtents.getX();
- if (minDimension>boxHalfExtents.getY())
+ if (minDimension > boxHalfExtents.getY())
minDimension = boxHalfExtents.getY();
m_shapeType = BOX_2D_SHAPE_PROXYTYPE;
- btVector3 margin(getMargin(),getMargin(),getMargin());
+ btVector3 margin(getMargin(), getMargin(), getMargin());
m_implicitShapeDimensions = (boxHalfExtents * m_localScaling) - margin;
setSafeMargin(minDimension);
@@ -114,42 +110,34 @@ public:
virtual void setMargin(btScalar collisionMargin)
{
//correct the m_implicitShapeDimensions for the margin
- btVector3 oldMargin(getMargin(),getMargin(),getMargin());
- btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
-
+ btVector3 oldMargin(getMargin(), getMargin(), getMargin());
+ btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions + oldMargin;
+
btConvexInternalShape::setMargin(collisionMargin);
- btVector3 newMargin(getMargin(),getMargin(),getMargin());
+ btVector3 newMargin(getMargin(), getMargin(), getMargin());
m_implicitShapeDimensions = implicitShapeDimensionsWithMargin - newMargin;
-
}
- virtual void setLocalScaling(const btVector3& scaling)
+ virtual void setLocalScaling(const btVector3& scaling)
{
- btVector3 oldMargin(getMargin(),getMargin(),getMargin());
- btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
+ btVector3 oldMargin(getMargin(), getMargin(), getMargin());
+ btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions + oldMargin;
btVector3 unScaledImplicitShapeDimensionsWithMargin = implicitShapeDimensionsWithMargin / m_localScaling;
btConvexInternalShape::setLocalScaling(scaling);
m_implicitShapeDimensions = (unScaledImplicitShapeDimensionsWithMargin * m_localScaling) - oldMargin;
-
}
- virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
-
-
-
- virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
-
-
+ virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
+ virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
-
- int getVertexCount() const
+ int getVertexCount() const
{
return 4;
}
- virtual int getNumVertices()const
+ virtual int getNumVertices() const
{
return 4;
}
@@ -164,82 +152,70 @@ public:
return &m_normals[0];
}
-
-
-
-
-
-
- virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const
+ virtual void getPlane(btVector3 & planeNormal, btVector3 & planeSupport, int i) const
{
//this plane might not be aligned...
- btVector4 plane ;
- getPlaneEquation(plane,i);
- planeNormal = btVector3(plane.getX(),plane.getY(),plane.getZ());
+ btVector4 plane;
+ getPlaneEquation(plane, i);
+ planeNormal = btVector3(plane.getX(), plane.getY(), plane.getZ());
planeSupport = localGetSupportingVertex(-planeNormal);
}
-
const btVector3& getCentroid() const
{
return m_centroid;
}
-
+
virtual int getNumPlanes() const
{
return 6;
- }
-
-
+ }
virtual int getNumEdges() const
{
return 12;
}
-
- virtual void getVertex(int i,btVector3& vtx) const
+ virtual void getVertex(int i, btVector3& vtx) const
{
btVector3 halfExtents = getHalfExtentsWithoutMargin();
vtx = btVector3(
- halfExtents.x() * (1-(i&1)) - halfExtents.x() * (i&1),
- halfExtents.y() * (1-((i&2)>>1)) - halfExtents.y() * ((i&2)>>1),
- halfExtents.z() * (1-((i&4)>>2)) - halfExtents.z() * ((i&4)>>2));
+ halfExtents.x() * (1 - (i & 1)) - halfExtents.x() * (i & 1),
+ halfExtents.y() * (1 - ((i & 2) >> 1)) - halfExtents.y() * ((i & 2) >> 1),
+ halfExtents.z() * (1 - ((i & 4) >> 2)) - halfExtents.z() * ((i & 4) >> 2));
}
-
- virtual void getPlaneEquation(btVector4& plane,int i) const
+ virtual void getPlaneEquation(btVector4 & plane, int i) const
{
btVector3 halfExtents = getHalfExtentsWithoutMargin();
switch (i)
{
- case 0:
- plane.setValue(btScalar(1.),btScalar(0.),btScalar(0.),-halfExtents.x());
- break;
- case 1:
- plane.setValue(btScalar(-1.),btScalar(0.),btScalar(0.),-halfExtents.x());
- break;
- case 2:
- plane.setValue(btScalar(0.),btScalar(1.),btScalar(0.),-halfExtents.y());
- break;
- case 3:
- plane.setValue(btScalar(0.),btScalar(-1.),btScalar(0.),-halfExtents.y());
- break;
- case 4:
- plane.setValue(btScalar(0.),btScalar(0.),btScalar(1.),-halfExtents.z());
- break;
- case 5:
- plane.setValue(btScalar(0.),btScalar(0.),btScalar(-1.),-halfExtents.z());
- break;
- default:
- btAssert(0);
+ case 0:
+ plane.setValue(btScalar(1.), btScalar(0.), btScalar(0.), -halfExtents.x());
+ break;
+ case 1:
+ plane.setValue(btScalar(-1.), btScalar(0.), btScalar(0.), -halfExtents.x());
+ break;
+ case 2:
+ plane.setValue(btScalar(0.), btScalar(1.), btScalar(0.), -halfExtents.y());
+ break;
+ case 3:
+ plane.setValue(btScalar(0.), btScalar(-1.), btScalar(0.), -halfExtents.y());
+ break;
+ case 4:
+ plane.setValue(btScalar(0.), btScalar(0.), btScalar(1.), -halfExtents.z());
+ break;
+ case 5:
+ plane.setValue(btScalar(0.), btScalar(0.), btScalar(-1.), -halfExtents.z());
+ break;
+ default:
+ btAssert(0);
}
}
-
- virtual void getEdge(int i,btVector3& pa,btVector3& pb) const
+ virtual void getEdge(int i, btVector3& pa, btVector3& pb) const
//virtual void getEdge(int i,Edge& edge) const
{
int edgeVert0 = 0;
@@ -247,126 +223,117 @@ public:
switch (i)
{
- case 0:
+ case 0:
edgeVert0 = 0;
edgeVert1 = 1;
- break;
- case 1:
+ break;
+ case 1:
edgeVert0 = 0;
edgeVert1 = 2;
- break;
- case 2:
- edgeVert0 = 1;
- edgeVert1 = 3;
-
- break;
- case 3:
- edgeVert0 = 2;
- edgeVert1 = 3;
- break;
- case 4:
- edgeVert0 = 0;
- edgeVert1 = 4;
- break;
- case 5:
- edgeVert0 = 1;
- edgeVert1 = 5;
-
- break;
- case 6:
- edgeVert0 = 2;
- edgeVert1 = 6;
- break;
- case 7:
- edgeVert0 = 3;
- edgeVert1 = 7;
- break;
- case 8:
- edgeVert0 = 4;
- edgeVert1 = 5;
- break;
- case 9:
- edgeVert0 = 4;
- edgeVert1 = 6;
- break;
- case 10:
- edgeVert0 = 5;
- edgeVert1 = 7;
- break;
- case 11:
- edgeVert0 = 6;
- edgeVert1 = 7;
- break;
- default:
- btAssert(0);
-
+ break;
+ case 2:
+ edgeVert0 = 1;
+ edgeVert1 = 3;
+
+ break;
+ case 3:
+ edgeVert0 = 2;
+ edgeVert1 = 3;
+ break;
+ case 4:
+ edgeVert0 = 0;
+ edgeVert1 = 4;
+ break;
+ case 5:
+ edgeVert0 = 1;
+ edgeVert1 = 5;
+
+ break;
+ case 6:
+ edgeVert0 = 2;
+ edgeVert1 = 6;
+ break;
+ case 7:
+ edgeVert0 = 3;
+ edgeVert1 = 7;
+ break;
+ case 8:
+ edgeVert0 = 4;
+ edgeVert1 = 5;
+ break;
+ case 9:
+ edgeVert0 = 4;
+ edgeVert1 = 6;
+ break;
+ case 10:
+ edgeVert0 = 5;
+ edgeVert1 = 7;
+ break;
+ case 11:
+ edgeVert0 = 6;
+ edgeVert1 = 7;
+ break;
+ default:
+ btAssert(0);
}
- getVertex(edgeVert0,pa );
- getVertex(edgeVert1,pb );
+ getVertex(edgeVert0, pa);
+ getVertex(edgeVert1, pb);
}
-
-
-
-
- virtual bool isInside(const btVector3& pt,btScalar tolerance) const
+ virtual bool isInside(const btVector3& pt, btScalar tolerance) const
{
btVector3 halfExtents = getHalfExtentsWithoutMargin();
//btScalar minDist = 2*tolerance;
-
- bool result = (pt.x() <= (halfExtents.x()+tolerance)) &&
- (pt.x() >= (-halfExtents.x()-tolerance)) &&
- (pt.y() <= (halfExtents.y()+tolerance)) &&
- (pt.y() >= (-halfExtents.y()-tolerance)) &&
- (pt.z() <= (halfExtents.z()+tolerance)) &&
- (pt.z() >= (-halfExtents.z()-tolerance));
-
+
+ bool result = (pt.x() <= (halfExtents.x() + tolerance)) &&
+ (pt.x() >= (-halfExtents.x() - tolerance)) &&
+ (pt.y() <= (halfExtents.y() + tolerance)) &&
+ (pt.y() >= (-halfExtents.y() - tolerance)) &&
+ (pt.z() <= (halfExtents.z() + tolerance)) &&
+ (pt.z() >= (-halfExtents.z() - tolerance));
+
return result;
}
-
//debugging
- virtual const char* getName()const
+ virtual const char* getName() const
{
return "Box2d";
}
- virtual int getNumPreferredPenetrationDirections() const
+ virtual int getNumPreferredPenetrationDirections() const
{
return 6;
}
-
- virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
+
+ virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
{
switch (index)
{
- case 0:
- penetrationVector.setValue(btScalar(1.),btScalar(0.),btScalar(0.));
- break;
- case 1:
- penetrationVector.setValue(btScalar(-1.),btScalar(0.),btScalar(0.));
- break;
- case 2:
- penetrationVector.setValue(btScalar(0.),btScalar(1.),btScalar(0.));
- break;
- case 3:
- penetrationVector.setValue(btScalar(0.),btScalar(-1.),btScalar(0.));
- break;
- case 4:
- penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(1.));
- break;
- case 5:
- penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(-1.));
- break;
- default:
- btAssert(0);
+ case 0:
+ penetrationVector.setValue(btScalar(1.), btScalar(0.), btScalar(0.));
+ break;
+ case 1:
+ penetrationVector.setValue(btScalar(-1.), btScalar(0.), btScalar(0.));
+ break;
+ case 2:
+ penetrationVector.setValue(btScalar(0.), btScalar(1.), btScalar(0.));
+ break;
+ case 3:
+ penetrationVector.setValue(btScalar(0.), btScalar(-1.), btScalar(0.));
+ break;
+ case 4:
+ penetrationVector.setValue(btScalar(0.), btScalar(0.), btScalar(1.));
+ break;
+ case 5:
+ penetrationVector.setValue(btScalar(0.), btScalar(0.), btScalar(-1.));
+ break;
+ default:
+ btAssert(0);
}
}
-
};
-#endif //BT_OBB_BOX_2D_SHAPE_H
-
-
+#endif //BT_OBB_BOX_2D_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btBoxShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btBoxShape.cpp
index 72eeb38911..cb91d023e4 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btBoxShape.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btBoxShape.cpp
@@ -14,38 +14,32 @@ subject to the following restrictions:
*/
#include "btBoxShape.h"
-btBoxShape::btBoxShape( const btVector3& boxHalfExtents)
-: btPolyhedralConvexShape()
+btBoxShape::btBoxShape(const btVector3& boxHalfExtents)
+ : btPolyhedralConvexShape()
{
m_shapeType = BOX_SHAPE_PROXYTYPE;
- btVector3 margin(getMargin(),getMargin(),getMargin());
+ btVector3 margin(getMargin(), getMargin(), getMargin());
m_implicitShapeDimensions = (boxHalfExtents * m_localScaling) - margin;
setSafeMargin(boxHalfExtents);
};
-
-
-
-void btBoxShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+void btBoxShape::getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
{
- btTransformAabb(getHalfExtentsWithoutMargin(),getMargin(),t,aabbMin,aabbMax);
+ btTransformAabb(getHalfExtentsWithoutMargin(), getMargin(), t, aabbMin, aabbMax);
}
-
-void btBoxShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+void btBoxShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
{
//btScalar margin = btScalar(0.);
btVector3 halfExtents = getHalfExtentsWithMargin();
- btScalar lx=btScalar(2.)*(halfExtents.x());
- btScalar ly=btScalar(2.)*(halfExtents.y());
- btScalar lz=btScalar(2.)*(halfExtents.z());
-
- inertia.setValue(mass/(btScalar(12.0)) * (ly*ly + lz*lz),
- mass/(btScalar(12.0)) * (lx*lx + lz*lz),
- mass/(btScalar(12.0)) * (lx*lx + ly*ly));
+ btScalar lx = btScalar(2.) * (halfExtents.x());
+ btScalar ly = btScalar(2.) * (halfExtents.y());
+ btScalar lz = btScalar(2.) * (halfExtents.z());
+ inertia.setValue(mass / (btScalar(12.0)) * (ly * ly + lz * lz),
+ mass / (btScalar(12.0)) * (lx * lx + lz * lz),
+ mass / (btScalar(12.0)) * (lx * lx + ly * ly));
}
-
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btBoxShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btBoxShape.h
index 715e3f2ab9..3c65505d5b 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btBoxShape.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btBoxShape.h
@@ -23,112 +23,102 @@ subject to the following restrictions:
#include "LinearMath/btMinMax.h"
///The btBoxShape is a box primitive around the origin, its sides axis aligned with length specified by half extents, in local shape coordinates. When used as part of a btCollisionObject or btRigidBody it will be an oriented box in world space.
-ATTRIBUTE_ALIGNED16(class) btBoxShape: public btPolyhedralConvexShape
+ATTRIBUTE_ALIGNED16(class)
+btBoxShape : public btPolyhedralConvexShape
{
-
//btVector3 m_boxHalfExtents1; //use m_implicitShapeDimensions instead
-
public:
-
-BT_DECLARE_ALIGNED_ALLOCATOR();
+ BT_DECLARE_ALIGNED_ALLOCATOR();
btVector3 getHalfExtentsWithMargin() const
{
btVector3 halfExtents = getHalfExtentsWithoutMargin();
- btVector3 margin(getMargin(),getMargin(),getMargin());
+ btVector3 margin(getMargin(), getMargin(), getMargin());
halfExtents += margin;
return halfExtents;
}
-
+
const btVector3& getHalfExtentsWithoutMargin() const
{
- return m_implicitShapeDimensions;//scaling is included, margin is not
+ return m_implicitShapeDimensions; //scaling is included, margin is not
}
-
- virtual btVector3 localGetSupportingVertex(const btVector3& vec) const
+ virtual btVector3 localGetSupportingVertex(const btVector3& vec) const
{
btVector3 halfExtents = getHalfExtentsWithoutMargin();
- btVector3 margin(getMargin(),getMargin(),getMargin());
+ btVector3 margin(getMargin(), getMargin(), getMargin());
halfExtents += margin;
-
+
return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
- btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
- btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
+ btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
+ btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
}
- SIMD_FORCE_INLINE btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+ SIMD_FORCE_INLINE btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const
{
const btVector3& halfExtents = getHalfExtentsWithoutMargin();
-
+
return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
- btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
- btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
+ btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
+ btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
}
- virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
{
const btVector3& halfExtents = getHalfExtentsWithoutMargin();
-
- for (int i=0;i<numVectors;i++)
+
+ for (int i = 0; i < numVectors; i++)
{
const btVector3& vec = vectors[i];
supportVerticesOut[i].setValue(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
- btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
- btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
+ btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
+ btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
}
-
}
-
- btBoxShape( const btVector3& boxHalfExtents);
+ btBoxShape(const btVector3& boxHalfExtents);
virtual void setMargin(btScalar collisionMargin)
{
//correct the m_implicitShapeDimensions for the margin
- btVector3 oldMargin(getMargin(),getMargin(),getMargin());
- btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
-
+ btVector3 oldMargin(getMargin(), getMargin(), getMargin());
+ btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions + oldMargin;
+
btConvexInternalShape::setMargin(collisionMargin);
- btVector3 newMargin(getMargin(),getMargin(),getMargin());
+ btVector3 newMargin(getMargin(), getMargin(), getMargin());
m_implicitShapeDimensions = implicitShapeDimensionsWithMargin - newMargin;
-
}
- virtual void setLocalScaling(const btVector3& scaling)
+ virtual void setLocalScaling(const btVector3& scaling)
{
- btVector3 oldMargin(getMargin(),getMargin(),getMargin());
- btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
+ btVector3 oldMargin(getMargin(), getMargin(), getMargin());
+ btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions + oldMargin;
btVector3 unScaledImplicitShapeDimensionsWithMargin = implicitShapeDimensionsWithMargin / m_localScaling;
btConvexInternalShape::setLocalScaling(scaling);
m_implicitShapeDimensions = (unScaledImplicitShapeDimensionsWithMargin * m_localScaling) - oldMargin;
-
}
- virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+ virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
-
+ virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
- virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
-
- virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const
+ virtual void getPlane(btVector3 & planeNormal, btVector3 & planeSupport, int i) const
{
//this plane might not be aligned...
- btVector4 plane ;
- getPlaneEquation(plane,i);
- planeNormal = btVector3(plane.getX(),plane.getY(),plane.getZ());
+ btVector4 plane;
+ getPlaneEquation(plane, i);
+ planeNormal = btVector3(plane.getX(), plane.getY(), plane.getZ());
planeSupport = localGetSupportingVertex(-planeNormal);
}
-
virtual int getNumPlanes() const
{
return 6;
- }
-
- virtual int getNumVertices() const
+ }
+
+ virtual int getNumVertices() const
{
return 8;
}
@@ -138,49 +128,46 @@ BT_DECLARE_ALIGNED_ALLOCATOR();
return 12;
}
-
- virtual void getVertex(int i,btVector3& vtx) const
+ virtual void getVertex(int i, btVector3& vtx) const
{
btVector3 halfExtents = getHalfExtentsWithMargin();
vtx = btVector3(
- halfExtents.x() * (1-(i&1)) - halfExtents.x() * (i&1),
- halfExtents.y() * (1-((i&2)>>1)) - halfExtents.y() * ((i&2)>>1),
- halfExtents.z() * (1-((i&4)>>2)) - halfExtents.z() * ((i&4)>>2));
+ halfExtents.x() * (1 - (i & 1)) - halfExtents.x() * (i & 1),
+ halfExtents.y() * (1 - ((i & 2) >> 1)) - halfExtents.y() * ((i & 2) >> 1),
+ halfExtents.z() * (1 - ((i & 4) >> 2)) - halfExtents.z() * ((i & 4) >> 2));
}
-
- virtual void getPlaneEquation(btVector4& plane,int i) const
+ virtual void getPlaneEquation(btVector4 & plane, int i) const
{
btVector3 halfExtents = getHalfExtentsWithoutMargin();
switch (i)
{
- case 0:
- plane.setValue(btScalar(1.),btScalar(0.),btScalar(0.),-halfExtents.x());
- break;
- case 1:
- plane.setValue(btScalar(-1.),btScalar(0.),btScalar(0.),-halfExtents.x());
- break;
- case 2:
- plane.setValue(btScalar(0.),btScalar(1.),btScalar(0.),-halfExtents.y());
- break;
- case 3:
- plane.setValue(btScalar(0.),btScalar(-1.),btScalar(0.),-halfExtents.y());
- break;
- case 4:
- plane.setValue(btScalar(0.),btScalar(0.),btScalar(1.),-halfExtents.z());
- break;
- case 5:
- plane.setValue(btScalar(0.),btScalar(0.),btScalar(-1.),-halfExtents.z());
- break;
- default:
- btAssert(0);
+ case 0:
+ plane.setValue(btScalar(1.), btScalar(0.), btScalar(0.), -halfExtents.x());
+ break;
+ case 1:
+ plane.setValue(btScalar(-1.), btScalar(0.), btScalar(0.), -halfExtents.x());
+ break;
+ case 2:
+ plane.setValue(btScalar(0.), btScalar(1.), btScalar(0.), -halfExtents.y());
+ break;
+ case 3:
+ plane.setValue(btScalar(0.), btScalar(-1.), btScalar(0.), -halfExtents.y());
+ break;
+ case 4:
+ plane.setValue(btScalar(0.), btScalar(0.), btScalar(1.), -halfExtents.z());
+ break;
+ case 5:
+ plane.setValue(btScalar(0.), btScalar(0.), btScalar(-1.), -halfExtents.z());
+ break;
+ default:
+ btAssert(0);
}
}
-
- virtual void getEdge(int i,btVector3& pa,btVector3& pb) const
+ virtual void getEdge(int i, btVector3& pa, btVector3& pb) const
//virtual void getEdge(int i,Edge& edge) const
{
int edgeVert0 = 0;
@@ -188,127 +175,117 @@ BT_DECLARE_ALIGNED_ALLOCATOR();
switch (i)
{
- case 0:
+ case 0:
edgeVert0 = 0;
edgeVert1 = 1;
- break;
- case 1:
+ break;
+ case 1:
edgeVert0 = 0;
edgeVert1 = 2;
- break;
- case 2:
- edgeVert0 = 1;
- edgeVert1 = 3;
-
- break;
- case 3:
- edgeVert0 = 2;
- edgeVert1 = 3;
- break;
- case 4:
- edgeVert0 = 0;
- edgeVert1 = 4;
- break;
- case 5:
- edgeVert0 = 1;
- edgeVert1 = 5;
-
- break;
- case 6:
- edgeVert0 = 2;
- edgeVert1 = 6;
- break;
- case 7:
- edgeVert0 = 3;
- edgeVert1 = 7;
- break;
- case 8:
- edgeVert0 = 4;
- edgeVert1 = 5;
- break;
- case 9:
- edgeVert0 = 4;
- edgeVert1 = 6;
- break;
- case 10:
- edgeVert0 = 5;
- edgeVert1 = 7;
- break;
- case 11:
- edgeVert0 = 6;
- edgeVert1 = 7;
- break;
- default:
- btAssert(0);
-
+ break;
+ case 2:
+ edgeVert0 = 1;
+ edgeVert1 = 3;
+
+ break;
+ case 3:
+ edgeVert0 = 2;
+ edgeVert1 = 3;
+ break;
+ case 4:
+ edgeVert0 = 0;
+ edgeVert1 = 4;
+ break;
+ case 5:
+ edgeVert0 = 1;
+ edgeVert1 = 5;
+
+ break;
+ case 6:
+ edgeVert0 = 2;
+ edgeVert1 = 6;
+ break;
+ case 7:
+ edgeVert0 = 3;
+ edgeVert1 = 7;
+ break;
+ case 8:
+ edgeVert0 = 4;
+ edgeVert1 = 5;
+ break;
+ case 9:
+ edgeVert0 = 4;
+ edgeVert1 = 6;
+ break;
+ case 10:
+ edgeVert0 = 5;
+ edgeVert1 = 7;
+ break;
+ case 11:
+ edgeVert0 = 6;
+ edgeVert1 = 7;
+ break;
+ default:
+ btAssert(0);
}
- getVertex(edgeVert0,pa );
- getVertex(edgeVert1,pb );
+ getVertex(edgeVert0, pa);
+ getVertex(edgeVert1, pb);
}
-
-
-
-
- virtual bool isInside(const btVector3& pt,btScalar tolerance) const
+ virtual bool isInside(const btVector3& pt, btScalar tolerance) const
{
btVector3 halfExtents = getHalfExtentsWithoutMargin();
//btScalar minDist = 2*tolerance;
-
- bool result = (pt.x() <= (halfExtents.x()+tolerance)) &&
- (pt.x() >= (-halfExtents.x()-tolerance)) &&
- (pt.y() <= (halfExtents.y()+tolerance)) &&
- (pt.y() >= (-halfExtents.y()-tolerance)) &&
- (pt.z() <= (halfExtents.z()+tolerance)) &&
- (pt.z() >= (-halfExtents.z()-tolerance));
-
+
+ bool result = (pt.x() <= (halfExtents.x() + tolerance)) &&
+ (pt.x() >= (-halfExtents.x() - tolerance)) &&
+ (pt.y() <= (halfExtents.y() + tolerance)) &&
+ (pt.y() >= (-halfExtents.y() - tolerance)) &&
+ (pt.z() <= (halfExtents.z() + tolerance)) &&
+ (pt.z() >= (-halfExtents.z() - tolerance));
+
return result;
}
-
//debugging
- virtual const char* getName()const
+ virtual const char* getName() const
{
return "Box";
}
- virtual int getNumPreferredPenetrationDirections() const
+ virtual int getNumPreferredPenetrationDirections() const
{
return 6;
}
-
- virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
+
+ virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
{
switch (index)
{
- case 0:
- penetrationVector.setValue(btScalar(1.),btScalar(0.),btScalar(0.));
- break;
- case 1:
- penetrationVector.setValue(btScalar(-1.),btScalar(0.),btScalar(0.));
- break;
- case 2:
- penetrationVector.setValue(btScalar(0.),btScalar(1.),btScalar(0.));
- break;
- case 3:
- penetrationVector.setValue(btScalar(0.),btScalar(-1.),btScalar(0.));
- break;
- case 4:
- penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(1.));
- break;
- case 5:
- penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(-1.));
- break;
- default:
- btAssert(0);
+ case 0:
+ penetrationVector.setValue(btScalar(1.), btScalar(0.), btScalar(0.));
+ break;
+ case 1:
+ penetrationVector.setValue(btScalar(-1.), btScalar(0.), btScalar(0.));
+ break;
+ case 2:
+ penetrationVector.setValue(btScalar(0.), btScalar(1.), btScalar(0.));
+ break;
+ case 3:
+ penetrationVector.setValue(btScalar(0.), btScalar(-1.), btScalar(0.));
+ break;
+ case 4:
+ penetrationVector.setValue(btScalar(0.), btScalar(0.), btScalar(1.));
+ break;
+ case 5:
+ penetrationVector.setValue(btScalar(0.), btScalar(0.), btScalar(-1.));
+ break;
+ default:
+ btAssert(0);
}
}
-
};
-
-#endif //BT_OBB_BOX_MINKOWSKI_H
-
-
+#endif //BT_OBB_BOX_MINKOWSKI_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp
index 61f465cb72..d663b3d6d6 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp
@@ -22,11 +22,11 @@ subject to the following restrictions:
///Bvh Concave triangle mesh is a static-triangle mesh shape with Bounding Volume Hierarchy optimization.
///Uses an interface to access the triangles to allow for sharing graphics/physics triangles.
btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh)
-:btTriangleMeshShape(meshInterface),
-m_bvh(0),
-m_triangleInfoMap(0),
-m_useQuantizedAabbCompression(useQuantizedAabbCompression),
-m_ownsBvh(false)
+ : btTriangleMeshShape(meshInterface),
+ m_bvh(0),
+ m_triangleInfoMap(0),
+ m_useQuantizedAabbCompression(useQuantizedAabbCompression),
+ m_ownsBvh(false)
{
m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;
//construct bvh from meshInterface
@@ -37,16 +37,15 @@ m_ownsBvh(false)
buildOptimizedBvh();
}
-#endif //DISABLE_BVH
-
+#endif //DISABLE_BVH
}
-btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,bool buildBvh)
-:btTriangleMeshShape(meshInterface),
-m_bvh(0),
-m_triangleInfoMap(0),
-m_useQuantizedAabbCompression(useQuantizedAabbCompression),
-m_ownsBvh(false)
+btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax, bool buildBvh)
+ : btTriangleMeshShape(meshInterface),
+ m_bvh(0),
+ m_triangleInfoMap(0),
+ m_useQuantizedAabbCompression(useQuantizedAabbCompression),
+ m_ownsBvh(false)
{
m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;
//construct bvh from meshInterface
@@ -54,30 +53,28 @@ m_ownsBvh(false)
if (buildBvh)
{
- void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16);
+ void* mem = btAlignedAlloc(sizeof(btOptimizedBvh), 16);
m_bvh = new (mem) btOptimizedBvh();
-
- m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax);
+
+ m_bvh->build(meshInterface, m_useQuantizedAabbCompression, bvhAabbMin, bvhAabbMax);
m_ownsBvh = true;
}
-#endif //DISABLE_BVH
-
+#endif //DISABLE_BVH
}
-void btBvhTriangleMeshShape::partialRefitTree(const btVector3& aabbMin,const btVector3& aabbMax)
+void btBvhTriangleMeshShape::partialRefitTree(const btVector3& aabbMin, const btVector3& aabbMax)
{
- m_bvh->refitPartial( m_meshInterface,aabbMin,aabbMax );
-
+ m_bvh->refitPartial(m_meshInterface, aabbMin, aabbMax);
+
m_localAabbMin.setMin(aabbMin);
m_localAabbMax.setMax(aabbMax);
}
-
-void btBvhTriangleMeshShape::refitTree(const btVector3& aabbMin,const btVector3& aabbMax)
+void btBvhTriangleMeshShape::refitTree(const btVector3& aabbMin, const btVector3& aabbMax)
{
- m_bvh->refit( m_meshInterface, aabbMin,aabbMax );
-
+ m_bvh->refit(m_meshInterface, aabbMin, aabbMax);
+
recalcLocalAabb();
}
@@ -90,27 +87,27 @@ btBvhTriangleMeshShape::~btBvhTriangleMeshShape()
}
}
-void btBvhTriangleMeshShape::performRaycast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget)
+void btBvhTriangleMeshShape::performRaycast(btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget)
{
- struct MyNodeOverlapCallback : public btNodeOverlapCallback
+ struct MyNodeOverlapCallback : public btNodeOverlapCallback
{
- btStridingMeshInterface* m_meshInterface;
+ btStridingMeshInterface* m_meshInterface;
btTriangleCallback* m_callback;
- MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
- :m_meshInterface(meshInterface),
- m_callback(callback)
+ MyNodeOverlapCallback(btTriangleCallback* callback, btStridingMeshInterface* meshInterface)
+ : m_meshInterface(meshInterface),
+ m_callback(callback)
{
}
-
+
virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
{
btVector3 m_triangle[3];
- const unsigned char *vertexbase;
+ const unsigned char* vertexbase;
int numverts;
PHY_ScalarType type;
int stride;
- const unsigned char *indexbase;
+ const unsigned char* indexbase;
int indexstride;
int numfaces;
PHY_ScalarType indicestype;
@@ -126,60 +123,60 @@ void btBvhTriangleMeshShape::performRaycast (btTriangleCallback* callback, const
indicestype,
nodeSubPart);
- unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
- btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
-
+ unsigned int* gfxbase = (unsigned int*)(indexbase + nodeTriangleIndex * indexstride);
+ btAssert(indicestype == PHY_INTEGER || indicestype == PHY_SHORT);
+
const btVector3& meshScaling = m_meshInterface->getScaling();
- for (int j=2;j>=0;j--)
+ for (int j = 2; j >= 0; j--)
{
- int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
-
+ int graphicsindex = indicestype == PHY_SHORT ? ((unsigned short*)gfxbase)[j] : gfxbase[j];
+
if (type == PHY_FLOAT)
{
- float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
-
- m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
+ float* graphicsbase = (float*)(vertexbase + graphicsindex * stride);
+
+ m_triangle[j] = btVector3(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
}
else
{
- double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
-
- m_triangle[j] = btVector3(btScalar(graphicsbase[0])*meshScaling.getX(),btScalar(graphicsbase[1])*meshScaling.getY(),btScalar(graphicsbase[2])*meshScaling.getZ());
+ double* graphicsbase = (double*)(vertexbase + graphicsindex * stride);
+
+ m_triangle[j] = btVector3(btScalar(graphicsbase[0]) * meshScaling.getX(), btScalar(graphicsbase[1]) * meshScaling.getY(), btScalar(graphicsbase[2]) * meshScaling.getZ());
}
}
/* Perform ray vs. triangle collision here */
- m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
+ m_callback->processTriangle(m_triangle, nodeSubPart, nodeTriangleIndex);
m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
}
};
- MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface);
+ MyNodeOverlapCallback myNodeCallback(callback, m_meshInterface);
- m_bvh->reportRayOverlappingNodex(&myNodeCallback,raySource,rayTarget);
+ m_bvh->reportRayOverlappingNodex(&myNodeCallback, raySource, rayTarget);
}
-void btBvhTriangleMeshShape::performConvexcast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax)
+void btBvhTriangleMeshShape::performConvexcast(btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax)
{
- struct MyNodeOverlapCallback : public btNodeOverlapCallback
+ struct MyNodeOverlapCallback : public btNodeOverlapCallback
{
- btStridingMeshInterface* m_meshInterface;
+ btStridingMeshInterface* m_meshInterface;
btTriangleCallback* m_callback;
- MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
- :m_meshInterface(meshInterface),
- m_callback(callback)
+ MyNodeOverlapCallback(btTriangleCallback* callback, btStridingMeshInterface* meshInterface)
+ : m_meshInterface(meshInterface),
+ m_callback(callback)
{
}
-
+
virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
{
btVector3 m_triangle[3];
- const unsigned char *vertexbase;
+ const unsigned char* vertexbase;
int numverts;
PHY_ScalarType type;
int stride;
- const unsigned char *indexbase;
+ const unsigned char* indexbase;
int indexstride;
int numfaces;
PHY_ScalarType indicestype;
@@ -195,77 +192,74 @@ void btBvhTriangleMeshShape::performConvexcast (btTriangleCallback* callback, co
indicestype,
nodeSubPart);
- unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
- btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
-
+ unsigned int* gfxbase = (unsigned int*)(indexbase + nodeTriangleIndex * indexstride);
+ btAssert(indicestype == PHY_INTEGER || indicestype == PHY_SHORT);
+
const btVector3& meshScaling = m_meshInterface->getScaling();
- for (int j=2;j>=0;j--)
+ for (int j = 2; j >= 0; j--)
{
- int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
+ int graphicsindex = indicestype == PHY_SHORT ? ((unsigned short*)gfxbase)[j] : gfxbase[j];
if (type == PHY_FLOAT)
{
- float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
+ float* graphicsbase = (float*)(vertexbase + graphicsindex * stride);
- m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
+ m_triangle[j] = btVector3(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
}
else
{
- double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
-
- m_triangle[j] = btVector3(btScalar(graphicsbase[0])*meshScaling.getX(),btScalar(graphicsbase[1])*meshScaling.getY(),btScalar(graphicsbase[2])*meshScaling.getZ());
+ double* graphicsbase = (double*)(vertexbase + graphicsindex * stride);
+
+ m_triangle[j] = btVector3(btScalar(graphicsbase[0]) * meshScaling.getX(), btScalar(graphicsbase[1]) * meshScaling.getY(), btScalar(graphicsbase[2]) * meshScaling.getZ());
}
}
/* Perform ray vs. triangle collision here */
- m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
+ m_callback->processTriangle(m_triangle, nodeSubPart, nodeTriangleIndex);
m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
}
};
- MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface);
+ MyNodeOverlapCallback myNodeCallback(callback, m_meshInterface);
- m_bvh->reportBoxCastOverlappingNodex (&myNodeCallback, raySource, rayTarget, aabbMin, aabbMax);
+ m_bvh->reportBoxCastOverlappingNodex(&myNodeCallback, raySource, rayTarget, aabbMin, aabbMax);
}
//perform bvh tree traversal and report overlapping triangles to 'callback'
-void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
+void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
{
-
#ifdef DISABLE_BVH
//brute force traverse all triangles
- btTriangleMeshShape::processAllTriangles(callback,aabbMin,aabbMax);
+ btTriangleMeshShape::processAllTriangles(callback, aabbMin, aabbMax);
#else
//first get all the nodes
-
- struct MyNodeOverlapCallback : public btNodeOverlapCallback
+ struct MyNodeOverlapCallback : public btNodeOverlapCallback
{
- btStridingMeshInterface* m_meshInterface;
- btTriangleCallback* m_callback;
- btVector3 m_triangle[3];
+ btStridingMeshInterface* m_meshInterface;
+ btTriangleCallback* m_callback;
+ btVector3 m_triangle[3];
int m_numOverlap;
- MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
- :m_meshInterface(meshInterface),
- m_callback(callback),
- m_numOverlap(0)
+ MyNodeOverlapCallback(btTriangleCallback* callback, btStridingMeshInterface* meshInterface)
+ : m_meshInterface(meshInterface),
+ m_callback(callback),
+ m_numOverlap(0)
{
}
-
+
virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
{
m_numOverlap++;
- const unsigned char *vertexbase;
+ const unsigned char* vertexbase;
int numverts;
PHY_ScalarType type;
int stride;
- const unsigned char *indexbase;
+ const unsigned char* indexbase;
int indexstride;
int numfaces;
PHY_ScalarType indicestype;
-
m_meshInterface->getLockedReadOnlyVertexIndexBase(
&vertexbase,
@@ -278,67 +272,62 @@ void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,co
indicestype,
nodeSubPart);
- unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
- btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT||indicestype==PHY_UCHAR);
-
+ unsigned int* gfxbase = (unsigned int*)(indexbase + nodeTriangleIndex * indexstride);
+ btAssert(indicestype == PHY_INTEGER || indicestype == PHY_SHORT || indicestype == PHY_UCHAR);
+
const btVector3& meshScaling = m_meshInterface->getScaling();
- for (int j=2;j>=0;j--)
+ for (int j = 2; j >= 0; j--)
{
-
- int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:indicestype==PHY_INTEGER?gfxbase[j]:((unsigned char*)gfxbase)[j];
-
+ int graphicsindex = indicestype == PHY_SHORT ? ((unsigned short*)gfxbase)[j] : indicestype == PHY_INTEGER ? gfxbase[j] : ((unsigned char*)gfxbase)[j];
#ifdef DEBUG_TRIANGLE_MESH
- printf("%d ,",graphicsindex);
-#endif //DEBUG_TRIANGLE_MESH
+ printf("%d ,", graphicsindex);
+#endif //DEBUG_TRIANGLE_MESH
if (type == PHY_FLOAT)
{
- float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
-
+ float* graphicsbase = (float*)(vertexbase + graphicsindex * stride);
+
m_triangle[j] = btVector3(
- graphicsbase[0]*meshScaling.getX(),
- graphicsbase[1]*meshScaling.getY(),
- graphicsbase[2]*meshScaling.getZ());
+ graphicsbase[0] * meshScaling.getX(),
+ graphicsbase[1] * meshScaling.getY(),
+ graphicsbase[2] * meshScaling.getZ());
}
else
{
- double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
+ double* graphicsbase = (double*)(vertexbase + graphicsindex * stride);
m_triangle[j] = btVector3(
- btScalar(graphicsbase[0])*meshScaling.getX(),
- btScalar(graphicsbase[1])*meshScaling.getY(),
- btScalar(graphicsbase[2])*meshScaling.getZ());
+ btScalar(graphicsbase[0]) * meshScaling.getX(),
+ btScalar(graphicsbase[1]) * meshScaling.getY(),
+ btScalar(graphicsbase[2]) * meshScaling.getZ());
}
#ifdef DEBUG_TRIANGLE_MESH
- printf("triangle vertices:%f,%f,%f\n",triangle[j].x(),triangle[j].y(),triangle[j].z());
-#endif //DEBUG_TRIANGLE_MESH
+ printf("triangle vertices:%f,%f,%f\n", triangle[j].x(), triangle[j].y(), triangle[j].z());
+#endif //DEBUG_TRIANGLE_MESH
}
- m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
+ m_callback->processTriangle(m_triangle, nodeSubPart, nodeTriangleIndex);
m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
}
-
};
- MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface);
-
- m_bvh->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax);
-
-#endif//DISABLE_BVH
+ MyNodeOverlapCallback myNodeCallback(callback, m_meshInterface);
+ m_bvh->reportAabbOverlappingNodex(&myNodeCallback, aabbMin, aabbMax);
+#endif //DISABLE_BVH
}
-void btBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling)
+void btBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling)
{
- if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON)
- {
- btTriangleMeshShape::setLocalScaling(scaling);
- buildOptimizedBvh();
- }
+ if ((getLocalScaling() - scaling).length2() > SIMD_EPSILON)
+ {
+ btTriangleMeshShape::setLocalScaling(scaling);
+ buildOptimizedBvh();
+ }
}
-void btBvhTriangleMeshShape::buildOptimizedBvh()
+void btBvhTriangleMeshShape::buildOptimizedBvh()
{
if (m_ownsBvh)
{
@@ -346,43 +335,39 @@ void btBvhTriangleMeshShape::buildOptimizedBvh()
btAlignedFree(m_bvh);
}
///m_localAabbMin/m_localAabbMax is already re-calculated in btTriangleMeshShape. We could just scale aabb, but this needs some more work
- void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16);
- m_bvh = new(mem) btOptimizedBvh();
+ void* mem = btAlignedAlloc(sizeof(btOptimizedBvh), 16);
+ m_bvh = new (mem) btOptimizedBvh();
//rebuild the bvh...
- m_bvh->build(m_meshInterface,m_useQuantizedAabbCompression,m_localAabbMin,m_localAabbMax);
+ m_bvh->build(m_meshInterface, m_useQuantizedAabbCompression, m_localAabbMin, m_localAabbMax);
m_ownsBvh = true;
}
-void btBvhTriangleMeshShape::setOptimizedBvh(btOptimizedBvh* bvh, const btVector3& scaling)
+void btBvhTriangleMeshShape::setOptimizedBvh(btOptimizedBvh* bvh, const btVector3& scaling)
{
- btAssert(!m_bvh);
- btAssert(!m_ownsBvh);
-
- m_bvh = bvh;
- m_ownsBvh = false;
- // update the scaling without rebuilding the bvh
- if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON)
- {
- btTriangleMeshShape::setLocalScaling(scaling);
- }
-}
-
+ btAssert(!m_bvh);
+ btAssert(!m_ownsBvh);
+ m_bvh = bvh;
+ m_ownsBvh = false;
+ // update the scaling without rebuilding the bvh
+ if ((getLocalScaling() - scaling).length2() > SIMD_EPSILON)
+ {
+ btTriangleMeshShape::setLocalScaling(scaling);
+ }
+}
///fills the dataBuffer and returns the struct name (and 0 on failure)
-const char* btBvhTriangleMeshShape::serialize(void* dataBuffer, btSerializer* serializer) const
+const char* btBvhTriangleMeshShape::serialize(void* dataBuffer, btSerializer* serializer) const
{
- btTriangleMeshShapeData* trimeshData = (btTriangleMeshShapeData*) dataBuffer;
+ btTriangleMeshShapeData* trimeshData = (btTriangleMeshShapeData*)dataBuffer;
- btCollisionShape::serialize(&trimeshData->m_collisionShapeData,serializer);
+ btCollisionShape::serialize(&trimeshData->m_collisionShapeData, serializer);
m_meshInterface->serialize(&trimeshData->m_meshInterface, serializer);
trimeshData->m_collisionMargin = float(m_collisionMargin);
-
-
- if (m_bvh && !(serializer->getSerializationFlags()&BT_SERIALIZE_NO_BVH))
+ if (m_bvh && !(serializer->getSerializationFlags() & BT_SERIALIZE_NO_BVH))
{
void* chunk = serializer->findPointer(m_bvh);
if (chunk)
@@ -391,48 +376,49 @@ const char* btBvhTriangleMeshShape::serialize(void* dataBuffer, btSerializer* se
trimeshData->m_quantizedDoubleBvh = (btQuantizedBvhData*)chunk;
trimeshData->m_quantizedFloatBvh = 0;
#else
- trimeshData->m_quantizedFloatBvh = (btQuantizedBvhData*)chunk;
- trimeshData->m_quantizedDoubleBvh= 0;
-#endif //BT_USE_DOUBLE_PRECISION
- } else
+ trimeshData->m_quantizedFloatBvh = (btQuantizedBvhData*)chunk;
+ trimeshData->m_quantizedDoubleBvh = 0;
+#endif //BT_USE_DOUBLE_PRECISION
+ }
+ else
{
-
#ifdef BT_USE_DOUBLE_PRECISION
trimeshData->m_quantizedDoubleBvh = (btQuantizedBvhData*)serializer->getUniquePointer(m_bvh);
trimeshData->m_quantizedFloatBvh = 0;
#else
- trimeshData->m_quantizedFloatBvh = (btQuantizedBvhData*)serializer->getUniquePointer(m_bvh);
- trimeshData->m_quantizedDoubleBvh= 0;
-#endif //BT_USE_DOUBLE_PRECISION
-
+ trimeshData->m_quantizedFloatBvh = (btQuantizedBvhData*)serializer->getUniquePointer(m_bvh);
+ trimeshData->m_quantizedDoubleBvh = 0;
+#endif //BT_USE_DOUBLE_PRECISION
+
int sz = m_bvh->calculateSerializeBufferSizeNew();
- btChunk* chunk = serializer->allocate(sz,1);
+ btChunk* chunk = serializer->allocate(sz, 1);
const char* structType = m_bvh->serialize(chunk->m_oldPtr, serializer);
- serializer->finalizeChunk(chunk,structType,BT_QUANTIZED_BVH_CODE,m_bvh);
+ serializer->finalizeChunk(chunk, structType, BT_QUANTIZED_BVH_CODE, m_bvh);
}
- } else
+ }
+ else
{
trimeshData->m_quantizedFloatBvh = 0;
trimeshData->m_quantizedDoubleBvh = 0;
}
-
-
- if (m_triangleInfoMap && !(serializer->getSerializationFlags()&BT_SERIALIZE_NO_TRIANGLEINFOMAP))
+ if (m_triangleInfoMap && !(serializer->getSerializationFlags() & BT_SERIALIZE_NO_TRIANGLEINFOMAP))
{
void* chunk = serializer->findPointer(m_triangleInfoMap);
if (chunk)
{
trimeshData->m_triangleInfoMap = (btTriangleInfoMapData*)chunk;
- } else
+ }
+ else
{
trimeshData->m_triangleInfoMap = (btTriangleInfoMapData*)serializer->getUniquePointer(m_triangleInfoMap);
int sz = m_triangleInfoMap->calculateSerializeBufferSize();
- btChunk* chunk = serializer->allocate(sz,1);
+ btChunk* chunk = serializer->allocate(sz, 1);
const char* structType = m_triangleInfoMap->serialize(chunk->m_oldPtr, serializer);
- serializer->finalizeChunk(chunk,structType,BT_TRIANLGE_INFO_MAP,m_triangleInfoMap);
+ serializer->finalizeChunk(chunk, structType, BT_TRIANLGE_INFO_MAP, m_triangleInfoMap);
}
- } else
+ }
+ else
{
trimeshData->m_triangleInfoMap = 0;
}
@@ -443,28 +429,24 @@ const char* btBvhTriangleMeshShape::serialize(void* dataBuffer, btSerializer* se
return "btTriangleMeshShapeData";
}
-void btBvhTriangleMeshShape::serializeSingleBvh(btSerializer* serializer) const
+void btBvhTriangleMeshShape::serializeSingleBvh(btSerializer* serializer) const
{
if (m_bvh)
{
- int len = m_bvh->calculateSerializeBufferSizeNew(); //make sure not to use calculateSerializeBufferSize because it is used for in-place
- btChunk* chunk = serializer->allocate(len,1);
+ int len = m_bvh->calculateSerializeBufferSizeNew(); //make sure not to use calculateSerializeBufferSize because it is used for in-place
+ btChunk* chunk = serializer->allocate(len, 1);
const char* structType = m_bvh->serialize(chunk->m_oldPtr, serializer);
- serializer->finalizeChunk(chunk,structType,BT_QUANTIZED_BVH_CODE,(void*)m_bvh);
+ serializer->finalizeChunk(chunk, structType, BT_QUANTIZED_BVH_CODE, (void*)m_bvh);
}
}
-void btBvhTriangleMeshShape::serializeSingleTriangleInfoMap(btSerializer* serializer) const
+void btBvhTriangleMeshShape::serializeSingleTriangleInfoMap(btSerializer* serializer) const
{
if (m_triangleInfoMap)
{
int len = m_triangleInfoMap->calculateSerializeBufferSize();
- btChunk* chunk = serializer->allocate(len,1);
+ btChunk* chunk = serializer->allocate(len, 1);
const char* structType = m_triangleInfoMap->serialize(chunk->m_oldPtr, serializer);
- serializer->finalizeChunk(chunk,structType,BT_TRIANLGE_INFO_MAP,(void*)m_triangleInfoMap);
+ serializer->finalizeChunk(chunk, structType, BT_TRIANLGE_INFO_MAP, (void*)m_triangleInfoMap);
}
}
-
-
-
-
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h
index 1fa4995d16..8b2f2ee85e 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h
@@ -23,103 +23,99 @@ subject to the following restrictions:
///The btBvhTriangleMeshShape is a static-triangle mesh shape, it can only be used for fixed/non-moving objects.
///If you required moving concave triangle meshes, it is recommended to perform convex decomposition
-///using HACD, see Bullet/Demos/ConvexDecompositionDemo.
+///using HACD, see Bullet/Demos/ConvexDecompositionDemo.
///Alternatively, you can use btGimpactMeshShape for moving concave triangle meshes.
-///btBvhTriangleMeshShape has several optimizations, such as bounding volume hierarchy and
-///cache friendly traversal for PlayStation 3 Cell SPU.
+///btBvhTriangleMeshShape has several optimizations, such as bounding volume hierarchy and
+///cache friendly traversal for PlayStation 3 Cell SPU.
///It is recommended to enable useQuantizedAabbCompression for better memory usage.
///It takes a triangle mesh as input, for example a btTriangleMesh or btTriangleIndexVertexArray. The btBvhTriangleMeshShape class allows for triangle mesh deformations by a refit or partialRefit method.
///Instead of building the bounding volume hierarchy acceleration structure, it is also possible to serialize (save) and deserialize (load) the structure from disk.
///See Demos\ConcaveDemo\ConcavePhysicsDemo.cpp for an example.
-ATTRIBUTE_ALIGNED16(class) btBvhTriangleMeshShape : public btTriangleMeshShape
+ATTRIBUTE_ALIGNED16(class)
+btBvhTriangleMeshShape : public btTriangleMeshShape
{
-
- btOptimizedBvh* m_bvh;
- btTriangleInfoMap* m_triangleInfoMap;
+ btOptimizedBvh* m_bvh;
+ btTriangleInfoMap* m_triangleInfoMap;
bool m_useQuantizedAabbCompression;
bool m_ownsBvh;
#ifdef __clang__
- bool m_pad[11] __attribute__((unused));////need padding due to alignment
+ bool m_pad[11] __attribute__((unused)); ////need padding due to alignment
#else
- bool m_pad[11];////need padding due to alignment
+ bool m_pad[11]; ////need padding due to alignment
#endif
public:
-
BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh = true);
+ btBvhTriangleMeshShape(btStridingMeshInterface * meshInterface, bool useQuantizedAabbCompression, bool buildBvh = true);
///optionally pass in a larger bvh aabb, used for quantization. This allows for deformations within this aabb
- btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax, bool buildBvh = true);
-
+ btBvhTriangleMeshShape(btStridingMeshInterface * meshInterface, bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax, bool buildBvh = true);
+
virtual ~btBvhTriangleMeshShape();
- bool getOwnsBvh () const
+ bool getOwnsBvh() const
{
return m_ownsBvh;
}
+ void performRaycast(btTriangleCallback * callback, const btVector3& raySource, const btVector3& rayTarget);
+ void performConvexcast(btTriangleCallback * callback, const btVector3& boxSource, const btVector3& boxTarget, const btVector3& boxMin, const btVector3& boxMax);
-
- void performRaycast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget);
- void performConvexcast (btTriangleCallback* callback, const btVector3& boxSource, const btVector3& boxTarget, const btVector3& boxMin, const btVector3& boxMax);
-
- virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+ virtual void processAllTriangles(btTriangleCallback * callback, const btVector3& aabbMin, const btVector3& aabbMax) const;
- void refitTree(const btVector3& aabbMin,const btVector3& aabbMax);
+ void refitTree(const btVector3& aabbMin, const btVector3& aabbMax);
///for a fast incremental refit of parts of the tree. Note: the entire AABB of the tree will become more conservative, it never shrinks
- void partialRefitTree(const btVector3& aabbMin,const btVector3& aabbMax);
+ void partialRefitTree(const btVector3& aabbMin, const btVector3& aabbMax);
//debugging
- virtual const char* getName()const {return "BVHTRIANGLEMESH";}
+ virtual const char* getName() const { return "BVHTRIANGLEMESH"; }
+ virtual void setLocalScaling(const btVector3& scaling);
- virtual void setLocalScaling(const btVector3& scaling);
-
- btOptimizedBvh* getOptimizedBvh()
+ btOptimizedBvh* getOptimizedBvh()
{
return m_bvh;
}
- void setOptimizedBvh(btOptimizedBvh* bvh, const btVector3& localScaling=btVector3(1,1,1));
+ void setOptimizedBvh(btOptimizedBvh * bvh, const btVector3& localScaling = btVector3(1, 1, 1));
- void buildOptimizedBvh();
+ void buildOptimizedBvh();
- bool usesQuantizedAabbCompression() const
+ bool usesQuantizedAabbCompression() const
{
- return m_useQuantizedAabbCompression;
+ return m_useQuantizedAabbCompression;
}
- void setTriangleInfoMap(btTriangleInfoMap* triangleInfoMap)
+ void setTriangleInfoMap(btTriangleInfoMap * triangleInfoMap)
{
m_triangleInfoMap = triangleInfoMap;
}
- const btTriangleInfoMap* getTriangleInfoMap() const
+ const btTriangleInfoMap* getTriangleInfoMap() const
{
return m_triangleInfoMap;
}
-
- btTriangleInfoMap* getTriangleInfoMap()
+
+ btTriangleInfoMap* getTriangleInfoMap()
{
return m_triangleInfoMap;
}
- virtual int calculateSerializeBufferSize() const;
+ virtual int calculateSerializeBufferSize() const;
///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-
- virtual void serializeSingleBvh(btSerializer* serializer) const;
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
- virtual void serializeSingleTriangleInfoMap(btSerializer* serializer) const;
+ virtual void serializeSingleBvh(btSerializer * serializer) const;
+ virtual void serializeSingleTriangleInfoMap(btSerializer * serializer) const;
};
+// clang-format off
+
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
struct btTriangleMeshShapeData
{
@@ -138,12 +134,11 @@ struct btTriangleMeshShapeData
};
+// clang-format on
-SIMD_FORCE_INLINE int btBvhTriangleMeshShape::calculateSerializeBufferSize() const
+SIMD_FORCE_INLINE int btBvhTriangleMeshShape::calculateSerializeBufferSize() const
{
return sizeof(btTriangleMeshShapeData);
}
-
-
-#endif //BT_BVH_TRIANGLE_MESH_SHAPE_H
+#endif //BT_BVH_TRIANGLE_MESH_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btCapsuleShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btCapsuleShape.cpp
index 0345501ce2..7c33774284 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btCapsuleShape.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btCapsuleShape.cpp
@@ -13,24 +13,21 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#include "btCapsuleShape.h"
#include "LinearMath/btQuaternion.h"
-btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) : btConvexInternalShape ()
+btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) : btConvexInternalShape()
{
m_collisionMargin = radius;
m_shapeType = CAPSULE_SHAPE_PROXYTYPE;
m_upAxis = 1;
- m_implicitShapeDimensions.setValue(radius,0.5f*height,radius);
+ m_implicitShapeDimensions.setValue(radius, 0.5f * height, radius);
}
-
- btVector3 btCapsuleShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const
+btVector3 btCapsuleShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0) const
{
-
- btVector3 supVec(0,0,0);
+ btVector3 supVec(0, 0, 0);
btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
@@ -38,20 +35,19 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) : btConvexInter
btScalar lenSqr = vec.length2();
if (lenSqr < btScalar(0.0001))
{
- vec.setValue(1,0,0);
- } else
+ vec.setValue(1, 0, 0);
+ }
+ else
{
- btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
+ btScalar rlen = btScalar(1.) / btSqrt(lenSqr);
vec *= rlen;
}
btVector3 vtx;
btScalar newDot;
-
-
{
- btVector3 pos(0,0,0);
+ btVector3 pos(0, 0, 0);
pos[getUpAxis()] = getHalfHeight();
vtx = pos;
@@ -63,7 +59,7 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) : btConvexInter
}
}
{
- btVector3 pos(0,0,0);
+ btVector3 pos(0, 0, 0);
pos[getUpAxis()] = -getHalfHeight();
vtx = pos;
@@ -76,15 +72,11 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) : btConvexInter
}
return supVec;
-
}
- void btCapsuleShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+void btCapsuleShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
{
-
-
-
- for (int j=0;j<numVectors;j++)
+ for (int j = 0; j < numVectors; j++)
{
btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
const btVector3& vec = vectors[j];
@@ -92,7 +84,7 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) : btConvexInter
btVector3 vtx;
btScalar newDot;
{
- btVector3 pos(0,0,0);
+ btVector3 pos(0, 0, 0);
pos[getUpAxis()] = getHalfHeight();
vtx = pos;
newDot = vec.dot(vtx);
@@ -103,7 +95,7 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) : btConvexInter
}
}
{
- btVector3 pos(0,0,0);
+ btVector3 pos(0, 0, 0);
pos[getUpAxis()] = -getHalfHeight();
vtx = pos;
newDot = vec.dot(vtx);
@@ -113,57 +105,44 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) : btConvexInter
supportVerticesOut[j] = vtx;
}
}
-
}
}
-
-void btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+void btCapsuleShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
{
//as an approximation, take the inertia of the box that bounds the spheres
btTransform ident;
ident.setIdentity();
-
btScalar radius = getRadius();
- btVector3 halfExtents(radius,radius,radius);
- halfExtents[getUpAxis()]+=getHalfHeight();
+ btVector3 halfExtents(radius, radius, radius);
+ halfExtents[getUpAxis()] += getHalfHeight();
- btScalar lx=btScalar(2.)*(halfExtents[0]);
- btScalar ly=btScalar(2.)*(halfExtents[1]);
- btScalar lz=btScalar(2.)*(halfExtents[2]);
- const btScalar x2 = lx*lx;
- const btScalar y2 = ly*ly;
- const btScalar z2 = lz*lz;
+ btScalar lx = btScalar(2.) * (halfExtents[0]);
+ btScalar ly = btScalar(2.) * (halfExtents[1]);
+ btScalar lz = btScalar(2.) * (halfExtents[2]);
+ const btScalar x2 = lx * lx;
+ const btScalar y2 = ly * ly;
+ const btScalar z2 = lz * lz;
const btScalar scaledmass = mass * btScalar(.08333333);
- inertia[0] = scaledmass * (y2+z2);
- inertia[1] = scaledmass * (x2+z2);
- inertia[2] = scaledmass * (x2+y2);
-
+ inertia[0] = scaledmass * (y2 + z2);
+ inertia[1] = scaledmass * (x2 + z2);
+ inertia[2] = scaledmass * (x2 + y2);
}
-btCapsuleShapeX::btCapsuleShapeX(btScalar radius,btScalar height)
+btCapsuleShapeX::btCapsuleShapeX(btScalar radius, btScalar height)
{
m_collisionMargin = radius;
m_upAxis = 0;
- m_implicitShapeDimensions.setValue(0.5f*height, radius,radius);
+ m_implicitShapeDimensions.setValue(0.5f * height, radius, radius);
}
-
-
-
-
-
-btCapsuleShapeZ::btCapsuleShapeZ(btScalar radius,btScalar height)
+btCapsuleShapeZ::btCapsuleShapeZ(btScalar radius, btScalar height)
{
m_collisionMargin = radius;
m_upAxis = 2;
- m_implicitShapeDimensions.setValue(radius,radius,0.5f*height);
+ m_implicitShapeDimensions.setValue(radius, radius, 0.5f * height);
}
-
-
-
-
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btCapsuleShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btCapsuleShape.h
index 5a3362834a..138d0c0f7c 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btCapsuleShape.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btCapsuleShape.h
@@ -17,99 +17,96 @@ subject to the following restrictions:
#define BT_CAPSULE_SHAPE_H
#include "btConvexInternalShape.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
-
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
///The btCapsuleShape represents a capsule around the Y axis, there is also the btCapsuleShapeX aligned around the X axis and btCapsuleShapeZ around the Z axis.
///The total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps.
///The btCapsuleShape is a convex hull of two spheres. The btMultiSphereShape is a more general collision shape that takes the convex hull of multiple sphere, so it can also represent a capsule when just using two spheres.
-ATTRIBUTE_ALIGNED16(class) btCapsuleShape : public btConvexInternalShape
+ATTRIBUTE_ALIGNED16(class)
+btCapsuleShape : public btConvexInternalShape
{
protected:
- int m_upAxis;
+ int m_upAxis;
protected:
///only used for btCapsuleShapeZ and btCapsuleShapeX subclasses.
- btCapsuleShape() : btConvexInternalShape() {m_shapeType = CAPSULE_SHAPE_PROXYTYPE;};
+ btCapsuleShape() : btConvexInternalShape() { m_shapeType = CAPSULE_SHAPE_PROXYTYPE; };
public:
-
BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btCapsuleShape(btScalar radius,btScalar height);
+
+ btCapsuleShape(btScalar radius, btScalar height);
///CollisionShape Interface
- virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+ virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
/// btConvexShape Interface
- virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
+
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const;
- virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
-
virtual void setMargin(btScalar collisionMargin)
{
//don't override the margin for capsules, their entire radius == margin
(void)collisionMargin;
}
- virtual void getAabb (const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
+ virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
{
- btVector3 halfExtents(getRadius(),getRadius(),getRadius());
- halfExtents[m_upAxis] = getRadius() + getHalfHeight();
- btMatrix3x3 abs_b = t.getBasis().absolute();
- btVector3 center = t.getOrigin();
- btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
-
- aabbMin = center - extent;
- aabbMax = center + extent;
+ btVector3 halfExtents(getRadius(), getRadius(), getRadius());
+ halfExtents[m_upAxis] = getRadius() + getHalfHeight();
+ btMatrix3x3 abs_b = t.getBasis().absolute();
+ btVector3 center = t.getOrigin();
+ btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
+
+ aabbMin = center - extent;
+ aabbMax = center + extent;
}
- virtual const char* getName()const
+ virtual const char* getName() const
{
return "CapsuleShape";
}
- int getUpAxis() const
+ int getUpAxis() const
{
return m_upAxis;
}
- btScalar getRadius() const
+ btScalar getRadius() const
{
- int radiusAxis = (m_upAxis+2)%3;
+ int radiusAxis = (m_upAxis + 2) % 3;
return m_implicitShapeDimensions[radiusAxis];
}
- btScalar getHalfHeight() const
+ btScalar getHalfHeight() const
{
return m_implicitShapeDimensions[m_upAxis];
}
- virtual void setLocalScaling(const btVector3& scaling)
+ virtual void setLocalScaling(const btVector3& scaling)
{
btVector3 unScaledImplicitShapeDimensions = m_implicitShapeDimensions / m_localScaling;
- btConvexInternalShape::setLocalScaling(scaling);
+ btConvexInternalShape::setLocalScaling(scaling);
m_implicitShapeDimensions = (unScaledImplicitShapeDimensions * scaling);
//update m_collisionMargin, since entire radius==margin
- int radiusAxis = (m_upAxis+2)%3;
+ int radiusAxis = (m_upAxis + 2) % 3;
m_collisionMargin = m_implicitShapeDimensions[radiusAxis];
}
- virtual btVector3 getAnisotropicRollingFrictionDirection() const
+ virtual btVector3 getAnisotropicRollingFrictionDirection() const
{
- btVector3 aniDir(0,0,0);
- aniDir[getUpAxis()]=1;
+ btVector3 aniDir(0, 0, 0);
+ aniDir[getUpAxis()] = 1;
return aniDir;
}
-
- virtual int calculateSerializeBufferSize() const;
+ virtual int calculateSerializeBufferSize() const;
///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-
- SIMD_FORCE_INLINE void deSerializeFloat(struct btCapsuleShapeData* dataBuffer);
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+ SIMD_FORCE_INLINE void deSerializeFloat(struct btCapsuleShapeData * dataBuffer);
};
///btCapsuleShapeX represents a capsule around the Z axis
@@ -117,17 +114,13 @@ public:
class btCapsuleShapeX : public btCapsuleShape
{
public:
+ btCapsuleShapeX(btScalar radius, btScalar height);
- btCapsuleShapeX(btScalar radius,btScalar height);
-
//debugging
- virtual const char* getName()const
+ virtual const char* getName() const
{
return "CapsuleX";
}
-
-
-
};
///btCapsuleShapeZ represents a capsule around the Z axis
@@ -135,38 +128,36 @@ public:
class btCapsuleShapeZ : public btCapsuleShape
{
public:
- btCapsuleShapeZ(btScalar radius,btScalar height);
+ btCapsuleShapeZ(btScalar radius, btScalar height);
- //debugging
- virtual const char* getName()const
+ //debugging
+ virtual const char* getName() const
{
return "CapsuleZ";
}
-
-
};
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btCapsuleShapeData
+struct btCapsuleShapeData
{
- btConvexInternalShapeData m_convexInternalShapeData;
+ btConvexInternalShapeData m_convexInternalShapeData;
- int m_upAxis;
+ int m_upAxis;
- char m_padding[4];
+ char m_padding[4];
};
-SIMD_FORCE_INLINE int btCapsuleShape::calculateSerializeBufferSize() const
+SIMD_FORCE_INLINE int btCapsuleShape::calculateSerializeBufferSize() const
{
return sizeof(btCapsuleShapeData);
}
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
-SIMD_FORCE_INLINE const char* btCapsuleShape::serialize(void* dataBuffer, btSerializer* serializer) const
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE const char* btCapsuleShape::serialize(void* dataBuffer, btSerializer* serializer) const
{
- btCapsuleShapeData* shapeData = (btCapsuleShapeData*) dataBuffer;
+ btCapsuleShapeData* shapeData = (btCapsuleShapeData*)dataBuffer;
- btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData,serializer);
+ btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData, serializer);
shapeData->m_upAxis = m_upAxis;
@@ -179,7 +170,7 @@ SIMD_FORCE_INLINE const char* btCapsuleShape::serialize(void* dataBuffer, btSeri
return "btCapsuleShapeData";
}
-SIMD_FORCE_INLINE void btCapsuleShape::deSerializeFloat(btCapsuleShapeData* dataBuffer)
+SIMD_FORCE_INLINE void btCapsuleShape::deSerializeFloat(btCapsuleShapeData* dataBuffer)
{
m_implicitShapeDimensions.deSerializeFloat(dataBuffer->m_convexInternalShapeData.m_implicitShapeDimensions);
m_collisionMargin = dataBuffer->m_convexInternalShapeData.m_collisionMargin;
@@ -188,4 +179,4 @@ SIMD_FORCE_INLINE void btCapsuleShape::deSerializeFloat(btCapsuleShapeData* data
m_upAxis = dataBuffer->m_upAxis;
}
-#endif //BT_CAPSULE_SHAPE_H
+#endif //BT_CAPSULE_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btCollisionMargin.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btCollisionMargin.h
index 474bf1fb49..abd8ab3eb5 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btCollisionMargin.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btCollisionMargin.h
@@ -19,9 +19,6 @@ subject to the following restrictions:
///The CONVEX_DISTANCE_MARGIN is a default collision margin for convex collision shapes derived from btConvexInternalShape.
///This collision margin is used by Gjk and some other algorithms
///Note that when creating small objects, you need to make sure to set a smaller collision margin, using the 'setMargin' API
-#define CONVEX_DISTANCE_MARGIN btScalar(0.04)// btScalar(0.1)//;//btScalar(0.01)
-
-
-
-#endif //BT_COLLISION_MARGIN_H
+#define CONVEX_DISTANCE_MARGIN btScalar(0.04) // btScalar(0.1)//;//btScalar(0.01)
+#endif //BT_COLLISION_MARGIN_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btCollisionShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btCollisionShape.cpp
index 823e2788f2..0b3640a65b 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btCollisionShape.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btCollisionShape.cpp
@@ -20,47 +20,44 @@ subject to the following restrictions:
can be used by probes that are checking whether the
library is actually installed.
*/
-extern "C"
+extern "C"
{
-void btBulletCollisionProbe ();
+ void btBulletCollisionProbe();
-void btBulletCollisionProbe () {}
+ void btBulletCollisionProbe() {}
}
-
-
-void btCollisionShape::getBoundingSphere(btVector3& center,btScalar& radius) const
+void btCollisionShape::getBoundingSphere(btVector3& center, btScalar& radius) const
{
btTransform tr;
tr.setIdentity();
- btVector3 aabbMin,aabbMax;
+ btVector3 aabbMin, aabbMax;
- getAabb(tr,aabbMin,aabbMax);
+ getAabb(tr, aabbMin, aabbMax);
- radius = (aabbMax-aabbMin).length()*btScalar(0.5);
- center = (aabbMin+aabbMax)*btScalar(0.5);
+ radius = (aabbMax - aabbMin).length() * btScalar(0.5);
+ center = (aabbMin + aabbMax) * btScalar(0.5);
}
-
-btScalar btCollisionShape::getContactBreakingThreshold(btScalar defaultContactThreshold) const
+btScalar btCollisionShape::getContactBreakingThreshold(btScalar defaultContactThreshold) const
{
return getAngularMotionDisc() * defaultContactThreshold;
}
-btScalar btCollisionShape::getAngularMotionDisc() const
+btScalar btCollisionShape::getAngularMotionDisc() const
{
///@todo cache this value, to improve performance
- btVector3 center;
+ btVector3 center;
btScalar disc;
- getBoundingSphere(center,disc);
+ getBoundingSphere(center, disc);
disc += (center).length();
return disc;
}
-void btCollisionShape::calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax) const
+void btCollisionShape::calculateTemporalAabb(const btTransform& curTrans, const btVector3& linvel, const btVector3& angvel, btScalar timeStep, btVector3& temporalAabbMin, btVector3& temporalAabbMax) const
{
//start with static aabb
- getAabb(curTrans,temporalAabbMin,temporalAabbMax);
+ getAabb(curTrans, temporalAabbMin, temporalAabbMax);
btScalar temporalAabbMaxx = temporalAabbMax.getX();
btScalar temporalAabbMaxy = temporalAabbMax.getY();
@@ -70,36 +67,36 @@ void btCollisionShape::calculateTemporalAabb(const btTransform& curTrans,const b
btScalar temporalAabbMinz = temporalAabbMin.getZ();
// add linear motion
- btVector3 linMotion = linvel*timeStep;
+ btVector3 linMotion = linvel * timeStep;
///@todo: simd would have a vector max/min operation, instead of per-element access
if (linMotion.x() > btScalar(0.))
- temporalAabbMaxx += linMotion.x();
+ temporalAabbMaxx += linMotion.x();
else
temporalAabbMinx += linMotion.x();
if (linMotion.y() > btScalar(0.))
- temporalAabbMaxy += linMotion.y();
+ temporalAabbMaxy += linMotion.y();
else
temporalAabbMiny += linMotion.y();
if (linMotion.z() > btScalar(0.))
- temporalAabbMaxz += linMotion.z();
+ temporalAabbMaxz += linMotion.z();
else
temporalAabbMinz += linMotion.z();
//add conservative angular motion
btScalar angularMotion = angvel.length() * getAngularMotionDisc() * timeStep;
- btVector3 angularMotion3d(angularMotion,angularMotion,angularMotion);
- temporalAabbMin = btVector3(temporalAabbMinx,temporalAabbMiny,temporalAabbMinz);
- temporalAabbMax = btVector3(temporalAabbMaxx,temporalAabbMaxy,temporalAabbMaxz);
+ btVector3 angularMotion3d(angularMotion, angularMotion, angularMotion);
+ temporalAabbMin = btVector3(temporalAabbMinx, temporalAabbMiny, temporalAabbMinz);
+ temporalAabbMax = btVector3(temporalAabbMaxx, temporalAabbMaxy, temporalAabbMaxz);
temporalAabbMin -= angularMotion3d;
temporalAabbMax += angularMotion3d;
}
///fills the dataBuffer and returns the struct name (and 0 on failure)
-const char* btCollisionShape::serialize(void* dataBuffer, btSerializer* serializer) const
+const char* btCollisionShape::serialize(void* dataBuffer, btSerializer* serializer) const
{
- btCollisionShapeData* shapeData = (btCollisionShapeData*) dataBuffer;
- char* name = (char*) serializer->findNameForPointer(this);
+ btCollisionShapeData* shapeData = (btCollisionShapeData*)dataBuffer;
+ char* name = (char*)serializer->findNameForPointer(this);
shapeData->m_name = (char*)serializer->getUniquePointer(name);
if (shapeData->m_name)
{
@@ -113,10 +110,10 @@ const char* btCollisionShape::serialize(void* dataBuffer, btSerializer* serializ
return "btCollisionShapeData";
}
-void btCollisionShape::serializeSingleShape(btSerializer* serializer) const
+void btCollisionShape::serializeSingleShape(btSerializer* serializer) const
{
int len = calculateSerializeBufferSize();
- btChunk* chunk = serializer->allocate(len,1);
+ btChunk* chunk = serializer->allocate(len, 1);
const char* structType = serialize(chunk->m_oldPtr, serializer);
- serializer->finalizeChunk(chunk,structType,BT_SHAPE_CODE,(void*)this);
+ serializer->finalizeChunk(chunk, structType, BT_SHAPE_CODE, (void*)this);
} \ No newline at end of file
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btCollisionShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btCollisionShape.h
index 6c4916fbd4..c80e105a4d 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btCollisionShape.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btCollisionShape.h
@@ -19,12 +19,12 @@ subject to the following restrictions:
#include "LinearMath/btTransform.h"
#include "LinearMath/btVector3.h"
#include "LinearMath/btMatrix3x3.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" //for the shape types
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" //for the shape types
class btSerializer;
-
///The btCollisionShape class provides an interface for collision shapes that can be shared among btCollisionObjects.
-ATTRIBUTE_ALIGNED16(class) btCollisionShape
+ATTRIBUTE_ALIGNED16(class)
+btCollisionShape
{
protected:
int m_shapeType;
@@ -32,10 +32,9 @@ protected:
int m_userIndex;
public:
-
BT_DECLARE_ALIGNED_ALLOCATOR();
- btCollisionShape() : m_shapeType (INVALID_SHAPE_PROXYTYPE), m_userPointer(0), m_userIndex(-1)
+ btCollisionShape() : m_shapeType(INVALID_SHAPE_PROXYTYPE), m_userPointer(0), m_userIndex(-1)
{
}
@@ -44,50 +43,47 @@ public:
}
///getAabb returns the axis aligned bounding box in the coordinate frame of the given transform t.
- virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0;
+ virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const = 0;
- virtual void getBoundingSphere(btVector3& center,btScalar& radius) const;
+ virtual void getBoundingSphere(btVector3 & center, btScalar & radius) const;
///getAngularMotionDisc returns the maximum radius needed for Conservative Advancement to handle time-of-impact with rotations.
- virtual btScalar getAngularMotionDisc() const;
-
- virtual btScalar getContactBreakingThreshold(btScalar defaultContactThresholdFactor) const;
+ virtual btScalar getAngularMotionDisc() const;
+ virtual btScalar getContactBreakingThreshold(btScalar defaultContactThresholdFactor) const;
///calculateTemporalAabb calculates the enclosing aabb for the moving object over interval [0..timeStep)
///result is conservative
- void calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax) const;
-
+ void calculateTemporalAabb(const btTransform& curTrans, const btVector3& linvel, const btVector3& angvel, btScalar timeStep, btVector3& temporalAabbMin, btVector3& temporalAabbMax) const;
-
- SIMD_FORCE_INLINE bool isPolyhedral() const
+ SIMD_FORCE_INLINE bool isPolyhedral() const
{
return btBroadphaseProxy::isPolyhedral(getShapeType());
}
- SIMD_FORCE_INLINE bool isConvex2d() const
+ SIMD_FORCE_INLINE bool isConvex2d() const
{
return btBroadphaseProxy::isConvex2d(getShapeType());
}
- SIMD_FORCE_INLINE bool isConvex() const
+ SIMD_FORCE_INLINE bool isConvex() const
{
return btBroadphaseProxy::isConvex(getShapeType());
}
- SIMD_FORCE_INLINE bool isNonMoving() const
+ SIMD_FORCE_INLINE bool isNonMoving() const
{
return btBroadphaseProxy::isNonMoving(getShapeType());
}
- SIMD_FORCE_INLINE bool isConcave() const
+ SIMD_FORCE_INLINE bool isConcave() const
{
return btBroadphaseProxy::isConcave(getShapeType());
}
- SIMD_FORCE_INLINE bool isCompound() const
+ SIMD_FORCE_INLINE bool isCompound() const
{
return btBroadphaseProxy::isCompound(getShapeType());
}
- SIMD_FORCE_INLINE bool isSoftBody() const
+ SIMD_FORCE_INLINE bool isSoftBody() const
{
return btBroadphaseProxy::isSoftBody(getShapeType());
}
@@ -99,35 +95,35 @@ public:
}
#ifndef __SPU__
- virtual void setLocalScaling(const btVector3& scaling) =0;
- virtual const btVector3& getLocalScaling() const =0;
- virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const = 0;
-
+ virtual void setLocalScaling(const btVector3& scaling) = 0;
+ virtual const btVector3& getLocalScaling() const = 0;
+ virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const = 0;
-//debugging support
- virtual const char* getName()const =0 ;
-#endif //__SPU__
+ //debugging support
+ virtual const char* getName() const = 0;
+#endif //__SPU__
-
- int getShapeType() const { return m_shapeType; }
+ int getShapeType() const
+ {
+ return m_shapeType;
+ }
///the getAnisotropicRollingFrictionDirection can be used in combination with setAnisotropicFriction
///See Bullet/Demos/RollingFrictionDemo for an example
- virtual btVector3 getAnisotropicRollingFrictionDirection() const
+ virtual btVector3 getAnisotropicRollingFrictionDirection() const
{
- return btVector3(1,1,1);
+ return btVector3(1, 1, 1);
}
- virtual void setMargin(btScalar margin) = 0;
- virtual btScalar getMargin() const = 0;
+ virtual void setMargin(btScalar margin) = 0;
+ virtual btScalar getMargin() const = 0;
-
///optional user data pointer
- void setUserPointer(void* userPtr)
+ void setUserPointer(void* userPtr)
{
m_userPointer = userPtr;
}
- void* getUserPointer() const
+ void* getUserPointer() const
{
return m_userPointer;
}
@@ -141,16 +137,16 @@ public:
return m_userIndex;
}
-
- virtual int calculateSerializeBufferSize() const;
+ virtual int calculateSerializeBufferSize() const;
///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-
- virtual void serializeSingleShape(btSerializer* serializer) const;
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-};
+ virtual void serializeSingleShape(btSerializer * serializer) const;
+};
+// clang-format off
+// parser needs * with the name
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
struct btCollisionShapeData
{
@@ -158,13 +154,10 @@ struct btCollisionShapeData
int m_shapeType;
char m_padding[4];
};
-
-SIMD_FORCE_INLINE int btCollisionShape::calculateSerializeBufferSize() const
+// clang-format on
+SIMD_FORCE_INLINE int btCollisionShape::calculateSerializeBufferSize() const
{
return sizeof(btCollisionShapeData);
}
-
-
-#endif //BT_COLLISION_SHAPE_H
-
+#endif //BT_COLLISION_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btCompoundShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btCompoundShape.cpp
index 85572da307..fd7828b104 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btCompoundShape.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btCompoundShape.cpp
@@ -19,26 +19,25 @@ subject to the following restrictions:
#include "LinearMath/btSerializer.h"
btCompoundShape::btCompoundShape(bool enableDynamicAabbTree, const int initialChildCapacity)
-: m_localAabbMin(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)),
-m_localAabbMax(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)),
-m_dynamicAabbTree(0),
-m_updateRevision(1),
-m_collisionMargin(btScalar(0.)),
-m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.))
+ : m_localAabbMin(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT)),
+ m_localAabbMax(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT)),
+ m_dynamicAabbTree(0),
+ m_updateRevision(1),
+ m_collisionMargin(btScalar(0.)),
+ m_localScaling(btScalar(1.), btScalar(1.), btScalar(1.))
{
m_shapeType = COMPOUND_SHAPE_PROXYTYPE;
if (enableDynamicAabbTree)
{
- void* mem = btAlignedAlloc(sizeof(btDbvt),16);
- m_dynamicAabbTree = new(mem) btDbvt();
- btAssert(mem==m_dynamicAabbTree);
+ void* mem = btAlignedAlloc(sizeof(btDbvt), 16);
+ m_dynamicAabbTree = new (mem) btDbvt();
+ btAssert(mem == m_dynamicAabbTree);
}
m_children.reserve(initialChildCapacity);
}
-
btCompoundShape::~btCompoundShape()
{
if (m_dynamicAabbTree)
@@ -48,7 +47,7 @@ btCompoundShape::~btCompoundShape()
}
}
-void btCompoundShape::addChildShape(const btTransform& localTransform,btCollisionShape* shape)
+void btCompoundShape::addChildShape(const btTransform& localTransform, btCollisionShape* shape)
{
m_updateRevision++;
//m_childTransforms.push_back(localTransform);
@@ -60,11 +59,10 @@ void btCompoundShape::addChildShape(const btTransform& localTransform,btCollisio
child.m_childShapeType = shape->getShapeType();
child.m_childMargin = shape->getMargin();
-
//extend the local aabbMin/aabbMax
- btVector3 localAabbMin,localAabbMax;
- shape->getAabb(localTransform,localAabbMin,localAabbMax);
- for (int i=0;i<3;i++)
+ btVector3 localAabbMin, localAabbMax;
+ shape->getAabb(localTransform, localAabbMin, localAabbMax);
+ for (int i = 0; i < 3; i++)
{
if (m_localAabbMin[i] > localAabbMin[i])
{
@@ -74,31 +72,30 @@ void btCompoundShape::addChildShape(const btTransform& localTransform,btCollisio
{
m_localAabbMax[i] = localAabbMax[i];
}
-
}
if (m_dynamicAabbTree)
{
- const btDbvtVolume bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
+ const btDbvtVolume bounds = btDbvtVolume::FromMM(localAabbMin, localAabbMax);
size_t index = m_children.size();
- child.m_node = m_dynamicAabbTree->insert(bounds,reinterpret_cast<void*>(index) );
+ child.m_node = m_dynamicAabbTree->insert(bounds, reinterpret_cast<void*>(index));
}
m_children.push_back(child);
-
}
-void btCompoundShape::updateChildTransform(int childIndex, const btTransform& newChildTransform,bool shouldRecalculateLocalAabb)
+void btCompoundShape::updateChildTransform(int childIndex, const btTransform& newChildTransform, bool shouldRecalculateLocalAabb)
{
m_children[childIndex].m_transform = newChildTransform;
if (m_dynamicAabbTree)
{
///update the dynamic aabb tree
- btVector3 localAabbMin,localAabbMax;
- m_children[childIndex].m_childShape->getAabb(newChildTransform,localAabbMin,localAabbMax);
- ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
+ btVector3 localAabbMin, localAabbMax;
+ m_children[childIndex].m_childShape->getAabb(newChildTransform, localAabbMin, localAabbMax);
+ ATTRIBUTE_ALIGNED16(btDbvtVolume)
+ bounds = btDbvtVolume::FromMM(localAabbMin, localAabbMax);
//int index = m_children.size()-1;
- m_dynamicAabbTree->update(m_children[childIndex].m_node,bounds);
+ m_dynamicAabbTree->update(m_children[childIndex].m_node, bounds);
}
if (shouldRecalculateLocalAabb)
@@ -110,35 +107,30 @@ void btCompoundShape::updateChildTransform(int childIndex, const btTransform& ne
void btCompoundShape::removeChildShapeByIndex(int childShapeIndex)
{
m_updateRevision++;
- btAssert(childShapeIndex >=0 && childShapeIndex < m_children.size());
+ btAssert(childShapeIndex >= 0 && childShapeIndex < m_children.size());
if (m_dynamicAabbTree)
{
m_dynamicAabbTree->remove(m_children[childShapeIndex].m_node);
}
- m_children.swap(childShapeIndex,m_children.size()-1);
- if (m_dynamicAabbTree)
+ m_children.swap(childShapeIndex, m_children.size() - 1);
+ if (m_dynamicAabbTree)
m_children[childShapeIndex].m_node->dataAsInt = childShapeIndex;
m_children.pop_back();
-
}
-
-
void btCompoundShape::removeChildShape(btCollisionShape* shape)
{
m_updateRevision++;
// Find the children containing the shape specified, and remove those children.
//note: there might be multiple children using the same shape!
- for(int i = m_children.size()-1; i >= 0 ; i--)
+ for (int i = m_children.size() - 1; i >= 0; i--)
{
- if(m_children[i].m_childShape == shape)
+ if (m_children[i].m_childShape == shape)
{
removeChildShapeByIndex(i);
}
}
-
-
recalculateLocalAabb();
}
@@ -147,15 +139,15 @@ void btCompoundShape::recalculateLocalAabb()
// Recalculate the local aabb
// Brute force, it iterates over all the shapes left.
- m_localAabbMin = btVector3(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
- m_localAabbMax = btVector3(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
+ m_localAabbMin = btVector3(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
+ m_localAabbMax = btVector3(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
//extend the local aabbMin/aabbMax
for (int j = 0; j < m_children.size(); j++)
{
- btVector3 localAabbMin,localAabbMax;
+ btVector3 localAabbMin, localAabbMax;
m_children[j].m_childShape->getAabb(m_children[j].m_transform, localAabbMin, localAabbMax);
- for (int i=0;i<3;i++)
+ for (int i = 0; i < 3; i++)
{
if (m_localAabbMin[i] > localAabbMin[i])
m_localAabbMin[i] = localAabbMin[i];
@@ -166,53 +158,47 @@ void btCompoundShape::recalculateLocalAabb()
}
///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
-void btCompoundShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const
+void btCompoundShape::getAabb(const btTransform& trans, btVector3& aabbMin, btVector3& aabbMax) const
{
- btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin);
- btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin);
-
+ btVector3 localHalfExtents = btScalar(0.5) * (m_localAabbMax - m_localAabbMin);
+ btVector3 localCenter = btScalar(0.5) * (m_localAabbMax + m_localAabbMin);
+
//avoid an illegal AABB when there are no children
if (!m_children.size())
{
- localHalfExtents.setValue(0,0,0);
- localCenter.setValue(0,0,0);
+ localHalfExtents.setValue(0, 0, 0);
+ localCenter.setValue(0, 0, 0);
}
- localHalfExtents += btVector3(getMargin(),getMargin(),getMargin());
-
+ localHalfExtents += btVector3(getMargin(), getMargin(), getMargin());
- btMatrix3x3 abs_b = trans.getBasis().absolute();
+ btMatrix3x3 abs_b = trans.getBasis().absolute();
btVector3 center = trans(localCenter);
- btVector3 extent = localHalfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
- aabbMin = center-extent;
- aabbMax = center+extent;
-
+ btVector3 extent = localHalfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
+ aabbMin = center - extent;
+ aabbMax = center + extent;
}
-void btCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+void btCompoundShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
{
//approximation: take the inertia from the aabb for now
btTransform ident;
ident.setIdentity();
- btVector3 aabbMin,aabbMax;
- getAabb(ident,aabbMin,aabbMax);
+ btVector3 aabbMin, aabbMax;
+ getAabb(ident, aabbMin, aabbMax);
- btVector3 halfExtents = (aabbMax-aabbMin)*btScalar(0.5);
+ btVector3 halfExtents = (aabbMax - aabbMin) * btScalar(0.5);
- btScalar lx=btScalar(2.)*(halfExtents.x());
- btScalar ly=btScalar(2.)*(halfExtents.y());
- btScalar lz=btScalar(2.)*(halfExtents.z());
-
- inertia[0] = mass/(btScalar(12.0)) * (ly*ly + lz*lz);
- inertia[1] = mass/(btScalar(12.0)) * (lx*lx + lz*lz);
- inertia[2] = mass/(btScalar(12.0)) * (lx*lx + ly*ly);
+ btScalar lx = btScalar(2.) * (halfExtents.x());
+ btScalar ly = btScalar(2.) * (halfExtents.y());
+ btScalar lz = btScalar(2.) * (halfExtents.z());
+ inertia[0] = mass / (btScalar(12.0)) * (ly * ly + lz * lz);
+ inertia[1] = mass / (btScalar(12.0)) * (lx * lx + lz * lz);
+ inertia[2] = mass / (btScalar(12.0)) * (lx * lx + ly * ly);
}
-
-
-
void btCompoundShape::calculatePrincipalAxisTransform(const btScalar* masses, btTransform& principal, btVector3& inertia) const
{
int n = m_children.size();
@@ -223,18 +209,18 @@ void btCompoundShape::calculatePrincipalAxisTransform(const btScalar* masses, bt
for (k = 0; k < n; k++)
{
- btAssert(masses[k]>0);
+ btAssert(masses[k] > 0);
center += m_children[k].m_transform.getOrigin() * masses[k];
totalMass += masses[k];
}
- btAssert(totalMass>0);
+ btAssert(totalMass > 0);
center /= totalMass;
principal.setOrigin(center);
btMatrix3x3 tensor(0, 0, 0, 0, 0, 0, 0, 0, 0);
- for ( k = 0; k < n; k++)
+ for (k = 0; k < n; k++)
{
btVector3 i;
m_children[k].m_childShape->calculateLocalInertia(masses[k], i);
@@ -259,8 +245,8 @@ void btCompoundShape::calculatePrincipalAxisTransform(const btScalar* masses, bt
j[0].setValue(o2, 0, 0);
j[1].setValue(0, o2, 0);
j[2].setValue(0, 0, o2);
- j[0] += o * -o.x();
- j[1] += o * -o.y();
+ j[0] += o * -o.x();
+ j[1] += o * -o.y();
j[2] += o * -o.z();
//add inertia tensor of pointmass
@@ -273,59 +259,50 @@ void btCompoundShape::calculatePrincipalAxisTransform(const btScalar* masses, bt
inertia.setValue(tensor[0][0], tensor[1][1], tensor[2][2]);
}
-
-
-
-
void btCompoundShape::setLocalScaling(const btVector3& scaling)
{
-
- for(int i = 0; i < m_children.size(); i++)
+ for (int i = 0; i < m_children.size(); i++)
{
btTransform childTrans = getChildTransform(i);
btVector3 childScale = m_children[i].m_childShape->getLocalScaling();
-// childScale = childScale * (childTrans.getBasis() * scaling);
+ // childScale = childScale * (childTrans.getBasis() * scaling);
childScale = childScale * scaling / m_localScaling;
m_children[i].m_childShape->setLocalScaling(childScale);
childTrans.setOrigin((childTrans.getOrigin()) * scaling / m_localScaling);
- updateChildTransform(i, childTrans,false);
+ updateChildTransform(i, childTrans, false);
}
-
+
m_localScaling = scaling;
recalculateLocalAabb();
-
}
-
void btCompoundShape::createAabbTreeFromChildren()
{
- if ( !m_dynamicAabbTree )
- {
- void* mem = btAlignedAlloc(sizeof(btDbvt),16);
- m_dynamicAabbTree = new(mem) btDbvt();
- btAssert(mem==m_dynamicAabbTree);
+ if (!m_dynamicAabbTree)
+ {
+ void* mem = btAlignedAlloc(sizeof(btDbvt), 16);
+ m_dynamicAabbTree = new (mem) btDbvt();
+ btAssert(mem == m_dynamicAabbTree);
- for ( int index = 0; index < m_children.size(); index++ )
- {
- btCompoundShapeChild &child = m_children[index];
+ for (int index = 0; index < m_children.size(); index++)
+ {
+ btCompoundShapeChild& child = m_children[index];
- //extend the local aabbMin/aabbMax
- btVector3 localAabbMin,localAabbMax;
- child.m_childShape->getAabb(child.m_transform,localAabbMin,localAabbMax);
+ //extend the local aabbMin/aabbMax
+ btVector3 localAabbMin, localAabbMax;
+ child.m_childShape->getAabb(child.m_transform, localAabbMin, localAabbMax);
- const btDbvtVolume bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
+ const btDbvtVolume bounds = btDbvtVolume::FromMM(localAabbMin, localAabbMax);
size_t index2 = index;
- child.m_node = m_dynamicAabbTree->insert(bounds, reinterpret_cast<void*>(index2) );
- }
- }
+ child.m_node = m_dynamicAabbTree->insert(bounds, reinterpret_cast<void*>(index2));
+ }
+ }
}
-
///fills the dataBuffer and returns the struct name (and 0 on failure)
-const char* btCompoundShape::serialize(void* dataBuffer, btSerializer* serializer) const
+const char* btCompoundShape::serialize(void* dataBuffer, btSerializer* serializer) const
{
-
- btCompoundShapeData* shapeData = (btCompoundShapeData*) dataBuffer;
+ btCompoundShapeData* shapeData = (btCompoundShapeData*)dataBuffer;
btCollisionShape::serialize(&shapeData->m_collisionShapeData, serializer);
shapeData->m_collisionMargin = float(m_collisionMargin);
@@ -333,27 +310,26 @@ const char* btCompoundShape::serialize(void* dataBuffer, btSerializer* serialize
shapeData->m_childShapePtr = 0;
if (shapeData->m_numChildShapes)
{
- btChunk* chunk = serializer->allocate(sizeof(btCompoundShapeChildData),shapeData->m_numChildShapes);
+ btChunk* chunk = serializer->allocate(sizeof(btCompoundShapeChildData), shapeData->m_numChildShapes);
btCompoundShapeChildData* memPtr = (btCompoundShapeChildData*)chunk->m_oldPtr;
shapeData->m_childShapePtr = (btCompoundShapeChildData*)serializer->getUniquePointer(memPtr);
- for (int i=0;i<shapeData->m_numChildShapes;i++,memPtr++)
+ for (int i = 0; i < shapeData->m_numChildShapes; i++, memPtr++)
{
memPtr->m_childMargin = float(m_children[i].m_childMargin);
memPtr->m_childShape = (btCollisionShapeData*)serializer->getUniquePointer(m_children[i].m_childShape);
//don't serialize shapes that already have been serialized
if (!serializer->findPointer(m_children[i].m_childShape))
{
- btChunk* chunk = serializer->allocate(m_children[i].m_childShape->calculateSerializeBufferSize(),1);
- const char* structType = m_children[i].m_childShape->serialize(chunk->m_oldPtr,serializer);
- serializer->finalizeChunk(chunk,structType,BT_SHAPE_CODE,m_children[i].m_childShape);
- }
+ btChunk* chunk = serializer->allocate(m_children[i].m_childShape->calculateSerializeBufferSize(), 1);
+ const char* structType = m_children[i].m_childShape->serialize(chunk->m_oldPtr, serializer);
+ serializer->finalizeChunk(chunk, structType, BT_SHAPE_CODE, m_children[i].m_childShape);
+ }
memPtr->m_childShapeType = m_children[i].m_childShapeType;
m_children[i].m_transform.serializeFloat(memPtr->m_transform);
}
- serializer->finalizeChunk(chunk,"btCompoundShapeChildData",BT_ARRAY_CODE,chunk->m_oldPtr);
+ serializer->finalizeChunk(chunk, "btCompoundShapeChildData", BT_ARRAY_CODE, chunk->m_oldPtr);
}
return "btCompoundShapeData";
}
-
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btCompoundShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btCompoundShape.h
index 2cbcd1bfca..7e2d0eb817 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btCompoundShape.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btCompoundShape.h
@@ -27,45 +27,47 @@ subject to the following restrictions:
//class btOptimizedBvh;
struct btDbvt;
-ATTRIBUTE_ALIGNED16(struct) btCompoundShapeChild
+ATTRIBUTE_ALIGNED16(struct)
+btCompoundShapeChild
{
BT_DECLARE_ALIGNED_ALLOCATOR();
- btTransform m_transform;
- btCollisionShape* m_childShape;
- int m_childShapeType;
- btScalar m_childMargin;
- struct btDbvtNode* m_node;
+ btTransform m_transform;
+ btCollisionShape* m_childShape;
+ int m_childShapeType;
+ btScalar m_childMargin;
+ struct btDbvtNode* m_node;
};
SIMD_FORCE_INLINE bool operator==(const btCompoundShapeChild& c1, const btCompoundShapeChild& c2)
{
- return ( c1.m_transform == c2.m_transform &&
- c1.m_childShape == c2.m_childShape &&
- c1.m_childShapeType == c2.m_childShapeType &&
- c1.m_childMargin == c2.m_childMargin );
+ return (c1.m_transform == c2.m_transform &&
+ c1.m_childShape == c2.m_childShape &&
+ c1.m_childShapeType == c2.m_childShapeType &&
+ c1.m_childMargin == c2.m_childMargin);
}
/// The btCompoundShape allows to store multiple other btCollisionShapes
/// This allows for moving concave collision objects. This is more general then the static concave btBvhTriangleMeshShape.
-/// It has an (optional) dynamic aabb tree to accelerate early rejection tests.
+/// It has an (optional) dynamic aabb tree to accelerate early rejection tests.
/// @todo: This aabb tree can also be use to speed up ray tests on btCompoundShape, see http://code.google.com/p/bullet/issues/detail?id=25
/// Currently, removal of child shapes is only supported when disabling the aabb tree (pass 'false' in the constructor of btCompoundShape)
-ATTRIBUTE_ALIGNED16(class) btCompoundShape : public btCollisionShape
+ATTRIBUTE_ALIGNED16(class)
+btCompoundShape : public btCollisionShape
{
protected:
btAlignedObjectArray<btCompoundShapeChild> m_children;
- btVector3 m_localAabbMin;
- btVector3 m_localAabbMax;
+ btVector3 m_localAabbMin;
+ btVector3 m_localAabbMax;
- btDbvt* m_dynamicAabbTree;
+ btDbvt* m_dynamicAabbTree;
///increment m_updateRevision when adding/removing/replacing child shapes, so that some caches can be updated
- int m_updateRevision;
+ int m_updateRevision;
- btScalar m_collisionMargin;
+ btScalar m_collisionMargin;
- btVector3 m_localScaling;
+ btVector3 m_localScaling;
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
@@ -74,17 +76,16 @@ public:
virtual ~btCompoundShape();
- void addChildShape(const btTransform& localTransform,btCollisionShape* shape);
+ void addChildShape(const btTransform& localTransform, btCollisionShape* shape);
/// Remove all children shapes that contain the specified shape
- virtual void removeChildShape(btCollisionShape* shape);
+ virtual void removeChildShape(btCollisionShape * shape);
void removeChildShapeByIndex(int childShapeindex);
-
- int getNumChildShapes() const
+ int getNumChildShapes() const
{
- return int (m_children.size());
+ return int(m_children.size());
}
btCollisionShape* getChildShape(int index)
@@ -96,18 +97,17 @@ public:
return m_children[index].m_childShape;
}
- btTransform& getChildTransform(int index)
+ btTransform& getChildTransform(int index)
{
return m_children[index].m_transform;
}
- const btTransform& getChildTransform(int index) const
+ const btTransform& getChildTransform(int index) const
{
return m_children[index].m_transform;
}
///set a new transform for a child, and update internal data structures (local aabb and dynamic tree)
- void updateChildTransform(int childIndex, const btTransform& newChildTransform, bool shouldRecalculateLocalAabb = true);
-
+ void updateChildTransform(int childIndex, const btTransform& newChildTransform, bool shouldRecalculateLocalAabb = true);
btCompoundShapeChild* getChildList()
{
@@ -115,40 +115,40 @@ public:
}
///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
- virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+ virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
/** Re-calculate the local Aabb. Is called at the end of removeChildShapes.
Use this yourself if you modify the children or their transforms. */
- virtual void recalculateLocalAabb();
+ virtual void recalculateLocalAabb();
- virtual void setLocalScaling(const btVector3& scaling);
+ virtual void setLocalScaling(const btVector3& scaling);
- virtual const btVector3& getLocalScaling() const
+ virtual const btVector3& getLocalScaling() const
{
return m_localScaling;
}
- virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+ virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
- virtual void setMargin(btScalar margin)
+ virtual void setMargin(btScalar margin)
{
m_collisionMargin = margin;
}
- virtual btScalar getMargin() const
+ virtual btScalar getMargin() const
{
return m_collisionMargin;
}
- virtual const char* getName()const
+ virtual const char* getName() const
{
return "Compound";
}
- const btDbvt* getDynamicAabbTree() const
+ const btDbvt* getDynamicAabbTree() const
{
return m_dynamicAabbTree;
}
-
- btDbvt* getDynamicAabbTree()
+
+ btDbvt* getDynamicAabbTree()
{
return m_dynamicAabbTree;
}
@@ -162,19 +162,19 @@ public:
///of the collision object by the principal transform.
void calculatePrincipalAxisTransform(const btScalar* masses, btTransform& principal, btVector3& inertia) const;
- int getUpdateRevision() const
+ int getUpdateRevision() const
{
return m_updateRevision;
}
- virtual int calculateSerializeBufferSize() const;
+ virtual int calculateSerializeBufferSize() const;
///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-
-
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
};
+// clang-format off
+
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
struct btCompoundShapeChildData
{
@@ -197,16 +197,11 @@ struct btCompoundShapeData
};
+// clang-format on
-SIMD_FORCE_INLINE int btCompoundShape::calculateSerializeBufferSize() const
+SIMD_FORCE_INLINE int btCompoundShape::calculateSerializeBufferSize() const
{
return sizeof(btCompoundShapeData);
}
-
-
-
-
-
-
-#endif //BT_COMPOUND_SHAPE_H
+#endif //BT_COMPOUND_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btConcaveShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btConcaveShape.cpp
index 58ff84a5b0..5d396844dd 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btConcaveShape.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btConcaveShape.cpp
@@ -13,15 +13,12 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#include "btConcaveShape.h"
btConcaveShape::btConcaveShape() : m_collisionMargin(btScalar(0.))
{
-
}
btConcaveShape::~btConcaveShape()
{
-
}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btConcaveShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btConcaveShape.h
index 2917cc5b60..716624e182 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btConcaveShape.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btConcaveShape.h
@@ -17,12 +17,13 @@ subject to the following restrictions:
#define BT_CONCAVE_SHAPE_H
#include "btCollisionShape.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
#include "btTriangleCallback.h"
/// PHY_ScalarType enumerates possible scalar types.
/// See the btStridingMeshInterface or btHeightfieldTerrainShape for its use
-typedef enum PHY_ScalarType {
+typedef enum PHY_ScalarType
+{
PHY_FLOAT,
PHY_DOUBLE,
PHY_INTEGER,
@@ -33,30 +34,29 @@ typedef enum PHY_ScalarType {
///The btConcaveShape class provides an interface for non-moving (static) concave shapes.
///It has been implemented by the btStaticPlaneShape, btBvhTriangleMeshShape and btHeightfieldTerrainShape.
-ATTRIBUTE_ALIGNED16(class) btConcaveShape : public btCollisionShape
+ATTRIBUTE_ALIGNED16(class)
+btConcaveShape : public btCollisionShape
{
protected:
btScalar m_collisionMargin;
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
-
+
btConcaveShape();
virtual ~btConcaveShape();
- virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const = 0;
+ virtual void processAllTriangles(btTriangleCallback * callback, const btVector3& aabbMin, const btVector3& aabbMax) const = 0;
- virtual btScalar getMargin() const {
+ virtual btScalar getMargin() const
+ {
return m_collisionMargin;
}
virtual void setMargin(btScalar collisionMargin)
{
m_collisionMargin = collisionMargin;
}
-
-
-
};
-#endif //BT_CONCAVE_SHAPE_H
+#endif //BT_CONCAVE_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btConeShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btConeShape.cpp
index 2d83c8bfba..64a6f272ca 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btConeShape.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btConeShape.cpp
@@ -15,11 +15,9 @@ subject to the following restrictions:
#include "btConeShape.h"
-
-
-btConeShape::btConeShape (btScalar radius,btScalar height): btConvexInternalShape (),
-m_radius (radius),
-m_height(height)
+btConeShape::btConeShape(btScalar radius, btScalar height) : btConvexInternalShape(),
+ m_radius(radius),
+ m_height(height)
{
m_shapeType = CONE_SHAPE_PROXYTYPE;
setConeUpIndex(1);
@@ -27,42 +25,40 @@ m_height(height)
m_sinAngle = (m_radius / btSqrt(m_radius * m_radius + m_height * m_height));
}
-btConeShapeZ::btConeShapeZ (btScalar radius,btScalar height):
-btConeShape(radius,height)
+btConeShapeZ::btConeShapeZ(btScalar radius, btScalar height) : btConeShape(radius, height)
{
setConeUpIndex(2);
}
-btConeShapeX::btConeShapeX (btScalar radius,btScalar height):
-btConeShape(radius,height)
+btConeShapeX::btConeShapeX(btScalar radius, btScalar height) : btConeShape(radius, height)
{
setConeUpIndex(0);
}
///choose upAxis index
-void btConeShape::setConeUpIndex(int upIndex)
+void btConeShape::setConeUpIndex(int upIndex)
{
switch (upIndex)
{
- case 0:
+ case 0:
m_coneIndices[0] = 1;
m_coneIndices[1] = 0;
m_coneIndices[2] = 2;
- break;
- case 1:
+ break;
+ case 1:
m_coneIndices[0] = 0;
m_coneIndices[1] = 1;
m_coneIndices[2] = 2;
- break;
- case 2:
+ break;
+ case 2:
m_coneIndices[0] = 0;
m_coneIndices[1] = 2;
m_coneIndices[2] = 1;
- break;
- default:
- btAssert(0);
+ break;
+ default:
+ btAssert(0);
};
-
+
m_implicitShapeDimensions[m_coneIndices[0]] = m_radius;
m_implicitShapeDimensions[m_coneIndices[1]] = m_height;
m_implicitShapeDimensions[m_coneIndices[2]] = m_radius;
@@ -70,72 +66,71 @@ void btConeShape::setConeUpIndex(int upIndex)
btVector3 btConeShape::coneLocalSupport(const btVector3& v) const
{
-
btScalar halfHeight = m_height * btScalar(0.5);
- if (v[m_coneIndices[1]] > v.length() * m_sinAngle)
- {
- btVector3 tmp;
-
- tmp[m_coneIndices[0]] = btScalar(0.);
- tmp[m_coneIndices[1]] = halfHeight;
- tmp[m_coneIndices[2]] = btScalar(0.);
- return tmp;
- }
- else {
- btScalar s = btSqrt(v[m_coneIndices[0]] * v[m_coneIndices[0]] + v[m_coneIndices[2]] * v[m_coneIndices[2]]);
- if (s > SIMD_EPSILON) {
- btScalar d = m_radius / s;
- btVector3 tmp;
- tmp[m_coneIndices[0]] = v[m_coneIndices[0]] * d;
- tmp[m_coneIndices[1]] = -halfHeight;
- tmp[m_coneIndices[2]] = v[m_coneIndices[2]] * d;
- return tmp;
- }
- else {
+ if (v[m_coneIndices[1]] > v.length() * m_sinAngle)
+ {
btVector3 tmp;
+
tmp[m_coneIndices[0]] = btScalar(0.);
- tmp[m_coneIndices[1]] = -halfHeight;
+ tmp[m_coneIndices[1]] = halfHeight;
tmp[m_coneIndices[2]] = btScalar(0.);
return tmp;
}
- }
-
+ else
+ {
+ btScalar s = btSqrt(v[m_coneIndices[0]] * v[m_coneIndices[0]] + v[m_coneIndices[2]] * v[m_coneIndices[2]]);
+ if (s > SIMD_EPSILON)
+ {
+ btScalar d = m_radius / s;
+ btVector3 tmp;
+ tmp[m_coneIndices[0]] = v[m_coneIndices[0]] * d;
+ tmp[m_coneIndices[1]] = -halfHeight;
+ tmp[m_coneIndices[2]] = v[m_coneIndices[2]] * d;
+ return tmp;
+ }
+ else
+ {
+ btVector3 tmp;
+ tmp[m_coneIndices[0]] = btScalar(0.);
+ tmp[m_coneIndices[1]] = -halfHeight;
+ tmp[m_coneIndices[2]] = btScalar(0.);
+ return tmp;
+ }
+ }
}
-btVector3 btConeShape::localGetSupportingVertexWithoutMargin(const btVector3& vec) const
+btVector3 btConeShape::localGetSupportingVertexWithoutMargin(const btVector3& vec) const
{
- return coneLocalSupport(vec);
+ return coneLocalSupport(vec);
}
-void btConeShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+void btConeShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
{
- for (int i=0;i<numVectors;i++)
+ for (int i = 0; i < numVectors; i++)
{
const btVector3& vec = vectors[i];
supportVerticesOut[i] = coneLocalSupport(vec);
}
}
-
-btVector3 btConeShape::localGetSupportingVertex(const btVector3& vec) const
+btVector3 btConeShape::localGetSupportingVertex(const btVector3& vec) const
{
btVector3 supVertex = coneLocalSupport(vec);
- if ( getMargin()!=btScalar(0.) )
+ if (getMargin() != btScalar(0.))
{
btVector3 vecnorm = vec;
- if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
+ if (vecnorm.length2() < (SIMD_EPSILON * SIMD_EPSILON))
{
- vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
- }
+ vecnorm.setValue(btScalar(-1.), btScalar(-1.), btScalar(-1.));
+ }
vecnorm.normalize();
- supVertex+= getMargin() * vecnorm;
+ supVertex += getMargin() * vecnorm;
}
return supVertex;
}
-
-void btConeShape::setLocalScaling(const btVector3& scaling)
+void btConeShape::setLocalScaling(const btVector3& scaling)
{
int axis = m_coneIndices[1];
int r1 = m_coneIndices[0];
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btConeShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btConeShape.h
index 3b44e3f272..49f26bc4e5 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btConeShape.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btConeShape.h
@@ -17,31 +17,30 @@ subject to the following restrictions:
#define BT_CONE_MINKOWSKI_H
#include "btConvexInternalShape.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
///The btConeShape implements a cone shape primitive, centered around the origin and aligned with the Y axis. The btConeShapeX is aligned around the X axis and btConeShapeZ around the Z axis.
-ATTRIBUTE_ALIGNED16(class) btConeShape : public btConvexInternalShape
+ATTRIBUTE_ALIGNED16(class)
+btConeShape : public btConvexInternalShape
{
-
btScalar m_sinAngle;
btScalar m_radius;
btScalar m_height;
- int m_coneIndices[3];
+ int m_coneIndices[3];
btVector3 coneLocalSupport(const btVector3& v) const;
-
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btConeShape (btScalar radius,btScalar height);
-
- virtual btVector3 localGetSupportingVertex(const btVector3& vec) const;
- virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
- virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
- btScalar getRadius() const { return m_radius;}
- btScalar getHeight() const { return m_height;}
+ btConeShape(btScalar radius, btScalar height);
+
+ virtual btVector3 localGetSupportingVertex(const btVector3& vec) const;
+ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const;
+
+ btScalar getRadius() const { return m_radius; }
+ btScalar getHeight() const { return m_height; }
void setRadius(const btScalar radius)
{
@@ -52,124 +51,115 @@ public:
m_height = height;
}
-
- virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const
+ virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const
{
btTransform identity;
identity.setIdentity();
- btVector3 aabbMin,aabbMax;
- getAabb(identity,aabbMin,aabbMax);
+ btVector3 aabbMin, aabbMax;
+ getAabb(identity, aabbMin, aabbMax);
- btVector3 halfExtents = (aabbMax-aabbMin)*btScalar(0.5);
+ btVector3 halfExtents = (aabbMax - aabbMin) * btScalar(0.5);
btScalar margin = getMargin();
- btScalar lx=btScalar(2.)*(halfExtents.x()+margin);
- btScalar ly=btScalar(2.)*(halfExtents.y()+margin);
- btScalar lz=btScalar(2.)*(halfExtents.z()+margin);
- const btScalar x2 = lx*lx;
- const btScalar y2 = ly*ly;
- const btScalar z2 = lz*lz;
+ btScalar lx = btScalar(2.) * (halfExtents.x() + margin);
+ btScalar ly = btScalar(2.) * (halfExtents.y() + margin);
+ btScalar lz = btScalar(2.) * (halfExtents.z() + margin);
+ const btScalar x2 = lx * lx;
+ const btScalar y2 = ly * ly;
+ const btScalar z2 = lz * lz;
const btScalar scaledmass = mass * btScalar(0.08333333);
- inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2));
+ inertia = scaledmass * (btVector3(y2 + z2, x2 + z2, x2 + y2));
-// inertia.x() = scaledmass * (y2+z2);
-// inertia.y() = scaledmass * (x2+z2);
-// inertia.z() = scaledmass * (x2+y2);
+ // inertia.x() = scaledmass * (y2+z2);
+ // inertia.y() = scaledmass * (x2+z2);
+ // inertia.z() = scaledmass * (x2+y2);
}
+ virtual const char* getName() const
+ {
+ return "Cone";
+ }
- virtual const char* getName()const
- {
- return "Cone";
- }
-
- ///choose upAxis index
- void setConeUpIndex(int upIndex);
-
- int getConeUpIndex() const
- {
- return m_coneIndices[1];
- }
-
- virtual btVector3 getAnisotropicRollingFrictionDirection() const
+ ///choose upAxis index
+ void setConeUpIndex(int upIndex);
+
+ int getConeUpIndex() const
{
- return btVector3 (0,1,0);
+ return m_coneIndices[1];
}
- virtual void setLocalScaling(const btVector3& scaling);
-
-
- virtual int calculateSerializeBufferSize() const;
-
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-
+ virtual btVector3 getAnisotropicRollingFrictionDirection() const
+ {
+ return btVector3(0, 1, 0);
+ }
+
+ virtual void setLocalScaling(const btVector3& scaling);
+ virtual int calculateSerializeBufferSize() const;
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
};
///btConeShape implements a Cone shape, around the X axis
class btConeShapeX : public btConeShape
{
- public:
- btConeShapeX(btScalar radius,btScalar height);
+public:
+ btConeShapeX(btScalar radius, btScalar height);
- virtual btVector3 getAnisotropicRollingFrictionDirection() const
+ virtual btVector3 getAnisotropicRollingFrictionDirection() const
{
- return btVector3 (1,0,0);
+ return btVector3(1, 0, 0);
}
//debugging
- virtual const char* getName()const
+ virtual const char* getName() const
{
return "ConeX";
}
-
-
};
///btConeShapeZ implements a Cone shape, around the Z axis
class btConeShapeZ : public btConeShape
{
public:
- btConeShapeZ(btScalar radius,btScalar height);
+ btConeShapeZ(btScalar radius, btScalar height);
- virtual btVector3 getAnisotropicRollingFrictionDirection() const
+ virtual btVector3 getAnisotropicRollingFrictionDirection() const
{
- return btVector3 (0,0,1);
+ return btVector3(0, 0, 1);
}
//debugging
- virtual const char* getName()const
+ virtual const char* getName() const
{
return "ConeZ";
}
-
-
};
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btConeShapeData
+struct btConeShapeData
{
- btConvexInternalShapeData m_convexInternalShapeData;
-
- int m_upIndex;
-
- char m_padding[4];
+ btConvexInternalShapeData m_convexInternalShapeData;
+
+ int m_upIndex;
+
+ char m_padding[4];
};
-SIMD_FORCE_INLINE int btConeShape::calculateSerializeBufferSize() const
+SIMD_FORCE_INLINE int btConeShape::calculateSerializeBufferSize() const
{
return sizeof(btConeShapeData);
}
///fills the dataBuffer and returns the struct name (and 0 on failure)
-SIMD_FORCE_INLINE const char* btConeShape::serialize(void* dataBuffer, btSerializer* serializer) const
+SIMD_FORCE_INLINE const char* btConeShape::serialize(void* dataBuffer, btSerializer* serializer) const
{
- btConeShapeData* shapeData = (btConeShapeData*) dataBuffer;
+ btConeShapeData* shapeData = (btConeShapeData*)dataBuffer;
- btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData,serializer);
+ btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData, serializer);
shapeData->m_upIndex = m_coneIndices[1];
@@ -182,5 +172,4 @@ SIMD_FORCE_INLINE const char* btConeShape::serialize(void* dataBuffer, btSeriali
return "btConeShapeData";
}
-#endif //BT_CONE_MINKOWSKI_H
-
+#endif //BT_CONE_MINKOWSKI_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvex2dShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvex2dShape.cpp
index 10ea3e981a..7d3d1d362f 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvex2dShape.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvex2dShape.cpp
@@ -15,54 +15,48 @@ subject to the following restrictions:
#include "btConvex2dShape.h"
-btConvex2dShape::btConvex2dShape( btConvexShape* convexChildShape):
-btConvexShape (), m_childConvexShape(convexChildShape)
+btConvex2dShape::btConvex2dShape(btConvexShape* convexChildShape) : btConvexShape(), m_childConvexShape(convexChildShape)
{
m_shapeType = CONVEX_2D_SHAPE_PROXYTYPE;
}
-
+
btConvex2dShape::~btConvex2dShape()
{
}
-
-
-btVector3 btConvex2dShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+btVector3 btConvex2dShape::localGetSupportingVertexWithoutMargin(const btVector3& vec) const
{
return m_childConvexShape->localGetSupportingVertexWithoutMargin(vec);
}
-void btConvex2dShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+void btConvex2dShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
{
- m_childConvexShape->batchedUnitVectorGetSupportingVertexWithoutMargin(vectors,supportVerticesOut,numVectors);
+ m_childConvexShape->batchedUnitVectorGetSupportingVertexWithoutMargin(vectors, supportVerticesOut, numVectors);
}
-
-btVector3 btConvex2dShape::localGetSupportingVertex(const btVector3& vec)const
+btVector3 btConvex2dShape::localGetSupportingVertex(const btVector3& vec) const
{
return m_childConvexShape->localGetSupportingVertex(vec);
}
-
-void btConvex2dShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+void btConvex2dShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
{
///this linear upscaling is not realistic, but we don't deal with large mass ratios...
- m_childConvexShape->calculateLocalInertia(mass,inertia);
+ m_childConvexShape->calculateLocalInertia(mass, inertia);
}
-
- ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
-void btConvex2dShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+void btConvex2dShape::getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
{
- m_childConvexShape->getAabb(t,aabbMin,aabbMax);
+ m_childConvexShape->getAabb(t, aabbMin, aabbMax);
}
-void btConvex2dShape::getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+void btConvex2dShape::getAabbSlow(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
{
- m_childConvexShape->getAabbSlow(t,aabbMin,aabbMax);
+ m_childConvexShape->getAabbSlow(t, aabbMin, aabbMax);
}
-void btConvex2dShape::setLocalScaling(const btVector3& scaling)
+void btConvex2dShape::setLocalScaling(const btVector3& scaling)
{
m_childConvexShape->setLocalScaling(scaling);
}
@@ -72,21 +66,21 @@ const btVector3& btConvex2dShape::getLocalScaling() const
return m_childConvexShape->getLocalScaling();
}
-void btConvex2dShape::setMargin(btScalar margin)
+void btConvex2dShape::setMargin(btScalar margin)
{
m_childConvexShape->setMargin(margin);
}
-btScalar btConvex2dShape::getMargin() const
+btScalar btConvex2dShape::getMargin() const
{
return m_childConvexShape->getMargin();
}
-int btConvex2dShape::getNumPreferredPenetrationDirections() const
+int btConvex2dShape::getNumPreferredPenetrationDirections() const
{
return m_childConvexShape->getNumPreferredPenetrationDirections();
}
-
-void btConvex2dShape::getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
+
+void btConvex2dShape::getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
{
- m_childConvexShape->getPreferredPenetrationDirection(index,penetrationVector);
+ m_childConvexShape->getPreferredPenetrationDirection(index, penetrationVector);
}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvex2dShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvex2dShape.h
index bbd1caf42f..cd4f1ef7b8 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvex2dShape.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvex2dShape.h
@@ -17,66 +17,61 @@ subject to the following restrictions:
#define BT_CONVEX_2D_SHAPE_H
#include "BulletCollision/CollisionShapes/btConvexShape.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
///The btConvex2dShape allows to use arbitrary convex shapes as 2d convex shapes, with the Z component assumed to be 0.
///For 2d boxes, the btBox2dShape is recommended.
-ATTRIBUTE_ALIGNED16(class) btConvex2dShape : public btConvexShape
+ATTRIBUTE_ALIGNED16(class)
+btConvex2dShape : public btConvexShape
{
- btConvexShape* m_childConvexShape;
+ btConvexShape* m_childConvexShape;
- public:
-
+public:
BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btConvex2dShape( btConvexShape* convexChildShape);
-
+
+ btConvex2dShape(btConvexShape * convexChildShape);
+
virtual ~btConvex2dShape();
-
- virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
- virtual btVector3 localGetSupportingVertex(const btVector3& vec)const;
+ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
+
+ virtual btVector3 localGetSupportingVertex(const btVector3& vec) const;
- virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const;
- virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+ virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
- btConvexShape* getChildShape()
+ btConvexShape* getChildShape()
{
return m_childConvexShape;
}
- const btConvexShape* getChildShape() const
+ const btConvexShape* getChildShape() const
{
return m_childConvexShape;
}
- virtual const char* getName()const
+ virtual const char* getName() const
{
return "Convex2dShape";
}
-
-
///////////////////////////
-
///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
- void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
-
- virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+ void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
- virtual void setLocalScaling(const btVector3& scaling) ;
- virtual const btVector3& getLocalScaling() const ;
+ virtual void getAabbSlow(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
- virtual void setMargin(btScalar margin);
- virtual btScalar getMargin() const;
+ virtual void setLocalScaling(const btVector3& scaling);
+ virtual const btVector3& getLocalScaling() const;
- virtual int getNumPreferredPenetrationDirections() const;
-
- virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const;
+ virtual void setMargin(btScalar margin);
+ virtual btScalar getMargin() const;
+ virtual int getNumPreferredPenetrationDirections() const;
+ virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const;
};
-#endif //BT_CONVEX_2D_SHAPE_H
+#endif //BT_CONVEX_2D_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexHullShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexHullShape.cpp
index a7a9598406..703de45922 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexHullShape.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexHullShape.cpp
@@ -13,7 +13,7 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-#if defined (_WIN32) || defined (__i386__)
+#if defined(_WIN32) || defined(__i386__)
#define BT_USE_SSE_IN_API
#endif
@@ -25,14 +25,14 @@ subject to the following restrictions:
#include "btConvexPolyhedron.h"
#include "LinearMath/btConvexHullComputer.h"
-btConvexHullShape ::btConvexHullShape (const btScalar* points,int numPoints,int stride) : btPolyhedralConvexAabbCachingShape ()
+btConvexHullShape ::btConvexHullShape(const btScalar* points, int numPoints, int stride) : btPolyhedralConvexAabbCachingShape()
{
m_shapeType = CONVEX_HULL_SHAPE_PROXYTYPE;
m_unscaledPoints.resize(numPoints);
unsigned char* pointsAddress = (unsigned char*)points;
- for (int i=0;i<numPoints;i++)
+ for (int i = 0; i < numPoints; i++)
{
btScalar* point = (btScalar*)pointsAddress;
m_unscaledPoints[i] = btVector3(point[0], point[1], point[2]);
@@ -40,11 +40,8 @@ btConvexHullShape ::btConvexHullShape (const btScalar* points,int numPoints,int
}
recalcLocalAabb();
-
}
-
-
void btConvexHullShape::setLocalScaling(const btVector3& scaling)
{
m_localScaling = scaling;
@@ -56,90 +53,81 @@ void btConvexHullShape::addPoint(const btVector3& point, bool recalculateLocalAa
m_unscaledPoints.push_back(point);
if (recalculateLocalAabb)
recalcLocalAabb();
-
}
-btVector3 btConvexHullShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+btVector3 btConvexHullShape::localGetSupportingVertexWithoutMargin(const btVector3& vec) const
{
- btVector3 supVec(btScalar(0.),btScalar(0.),btScalar(0.));
+ btVector3 supVec(btScalar(0.), btScalar(0.), btScalar(0.));
btScalar maxDot = btScalar(-BT_LARGE_FLOAT);
- // Here we take advantage of dot(a, b*c) = dot(a*b, c). Note: This is true mathematically, but not numerically.
- if( 0 < m_unscaledPoints.size() )
- {
- btVector3 scaled = vec * m_localScaling;
- int index = (int) scaled.maxDot( &m_unscaledPoints[0], m_unscaledPoints.size(), maxDot); // FIXME: may violate encapsulation of m_unscaledPoints
- return m_unscaledPoints[index] * m_localScaling;
- }
+ // Here we take advantage of dot(a, b*c) = dot(a*b, c). Note: This is true mathematically, but not numerically.
+ if (0 < m_unscaledPoints.size())
+ {
+ btVector3 scaled = vec * m_localScaling;
+ int index = (int)scaled.maxDot(&m_unscaledPoints[0], m_unscaledPoints.size(), maxDot); // FIXME: may violate encapsulation of m_unscaledPoints
+ return m_unscaledPoints[index] * m_localScaling;
+ }
- return supVec;
+ return supVec;
}
-void btConvexHullShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+void btConvexHullShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
{
btScalar newDot;
//use 'w' component of supportVerticesOut?
{
- for (int i=0;i<numVectors;i++)
+ for (int i = 0; i < numVectors; i++)
{
supportVerticesOut[i][3] = btScalar(-BT_LARGE_FLOAT);
}
}
- for (int j=0;j<numVectors;j++)
- {
- btVector3 vec = vectors[j] * m_localScaling; // dot(a*b,c) = dot(a,b*c)
- if( 0 < m_unscaledPoints.size() )
- {
- int i = (int) vec.maxDot( &m_unscaledPoints[0], m_unscaledPoints.size(), newDot);
- supportVerticesOut[j] = getScaledPoint(i);
- supportVerticesOut[j][3] = newDot;
- }
- else
- supportVerticesOut[j][3] = -BT_LARGE_FLOAT;
- }
-
-
-
+ for (int j = 0; j < numVectors; j++)
+ {
+ btVector3 vec = vectors[j] * m_localScaling; // dot(a*b,c) = dot(a,b*c)
+ if (0 < m_unscaledPoints.size())
+ {
+ int i = (int)vec.maxDot(&m_unscaledPoints[0], m_unscaledPoints.size(), newDot);
+ supportVerticesOut[j] = getScaledPoint(i);
+ supportVerticesOut[j][3] = newDot;
+ }
+ else
+ supportVerticesOut[j][3] = -BT_LARGE_FLOAT;
+ }
}
-
-
-btVector3 btConvexHullShape::localGetSupportingVertex(const btVector3& vec)const
+btVector3 btConvexHullShape::localGetSupportingVertex(const btVector3& vec) const
{
btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec);
- if ( getMargin()!=btScalar(0.) )
+ if (getMargin() != btScalar(0.))
{
btVector3 vecnorm = vec;
- if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
+ if (vecnorm.length2() < (SIMD_EPSILON * SIMD_EPSILON))
{
- vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
- }
+ vecnorm.setValue(btScalar(-1.), btScalar(-1.), btScalar(-1.));
+ }
vecnorm.normalize();
- supVertex+= getMargin() * vecnorm;
+ supVertex += getMargin() * vecnorm;
}
return supVertex;
}
-
void btConvexHullShape::optimizeConvexHull()
{
btConvexHullComputer conv;
- conv.compute(&m_unscaledPoints[0].getX(), sizeof(btVector3),m_unscaledPoints.size(),0.f,0.f);
+ conv.compute(&m_unscaledPoints[0].getX(), sizeof(btVector3), m_unscaledPoints.size(), 0.f, 0.f);
int numVerts = conv.vertices.size();
m_unscaledPoints.resize(0);
- for (int i=0;i<numVerts;i++)
- {
- m_unscaledPoints.push_back(conv.vertices[i]);
- }
+ for (int i = 0; i < numVerts; i++)
+ {
+ m_unscaledPoints.push_back(conv.vertices[i]);
+ }
}
-
-
//currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection
//Please note that you can debug-draw btConvexHullShape with the Raytracer Demo
-int btConvexHullShape::getNumVertices() const
+int btConvexHullShape::getNumVertices() const
{
return m_unscaledPoints.size();
}
@@ -149,67 +137,65 @@ int btConvexHullShape::getNumEdges() const
return m_unscaledPoints.size();
}
-void btConvexHullShape::getEdge(int i,btVector3& pa,btVector3& pb) const
+void btConvexHullShape::getEdge(int i, btVector3& pa, btVector3& pb) const
{
-
- int index0 = i%m_unscaledPoints.size();
- int index1 = (i+1)%m_unscaledPoints.size();
+ int index0 = i % m_unscaledPoints.size();
+ int index1 = (i + 1) % m_unscaledPoints.size();
pa = getScaledPoint(index0);
pb = getScaledPoint(index1);
}
-void btConvexHullShape::getVertex(int i,btVector3& vtx) const
+void btConvexHullShape::getVertex(int i, btVector3& vtx) const
{
vtx = getScaledPoint(i);
}
-int btConvexHullShape::getNumPlanes() const
+int btConvexHullShape::getNumPlanes() const
{
return 0;
}
-void btConvexHullShape::getPlane(btVector3& ,btVector3& ,int ) const
+void btConvexHullShape::getPlane(btVector3&, btVector3&, int) const
{
-
btAssert(0);
}
//not yet
-bool btConvexHullShape::isInside(const btVector3& ,btScalar ) const
+bool btConvexHullShape::isInside(const btVector3&, btScalar) const
{
btAssert(0);
return false;
}
///fills the dataBuffer and returns the struct name (and 0 on failure)
-const char* btConvexHullShape::serialize(void* dataBuffer, btSerializer* serializer) const
+const char* btConvexHullShape::serialize(void* dataBuffer, btSerializer* serializer) const
{
//int szc = sizeof(btConvexHullShapeData);
- btConvexHullShapeData* shapeData = (btConvexHullShapeData*) dataBuffer;
+ btConvexHullShapeData* shapeData = (btConvexHullShapeData*)dataBuffer;
btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData, serializer);
int numElem = m_unscaledPoints.size();
shapeData->m_numUnscaledPoints = numElem;
#ifdef BT_USE_DOUBLE_PRECISION
shapeData->m_unscaledPointsFloatPtr = 0;
- shapeData->m_unscaledPointsDoublePtr = numElem ? (btVector3Data*)serializer->getUniquePointer((void*)&m_unscaledPoints[0]): 0;
+ shapeData->m_unscaledPointsDoublePtr = numElem ? (btVector3Data*)serializer->getUniquePointer((void*)&m_unscaledPoints[0]) : 0;
#else
- shapeData->m_unscaledPointsFloatPtr = numElem ? (btVector3Data*)serializer->getUniquePointer((void*)&m_unscaledPoints[0]): 0;
+ shapeData->m_unscaledPointsFloatPtr = numElem ? (btVector3Data*)serializer->getUniquePointer((void*)&m_unscaledPoints[0]) : 0;
shapeData->m_unscaledPointsDoublePtr = 0;
#endif
-
+
if (numElem)
{
int sz = sizeof(btVector3Data);
- // int sz2 = sizeof(btVector3DoubleData);
- // int sz3 = sizeof(btVector3FloatData);
- btChunk* chunk = serializer->allocate(sz,numElem);
+ // int sz2 = sizeof(btVector3DoubleData);
+ // int sz3 = sizeof(btVector3FloatData);
+ btChunk* chunk = serializer->allocate(sz, numElem);
btVector3Data* memPtr = (btVector3Data*)chunk->m_oldPtr;
- for (int i=0;i<numElem;i++,memPtr++)
+ for (int i = 0; i < numElem; i++, memPtr++)
{
m_unscaledPoints[i].serialize(*memPtr);
}
- serializer->finalizeChunk(chunk,btVector3DataName,BT_ARRAY_CODE,(void*)&m_unscaledPoints[0]);
+ serializer->finalizeChunk(chunk, btVector3DataName, BT_ARRAY_CODE, (void*)&m_unscaledPoints[0]);
}
// Fill padding with zeros to appease msan.
@@ -218,45 +204,41 @@ const char* btConvexHullShape::serialize(void* dataBuffer, btSerializer* seriali
return "btConvexHullShapeData";
}
-void btConvexHullShape::project(const btTransform& trans, const btVector3& dir, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin,btVector3& witnesPtMax) const
+void btConvexHullShape::project(const btTransform& trans, const btVector3& dir, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin, btVector3& witnesPtMax) const
{
#if 1
minProj = FLT_MAX;
maxProj = -FLT_MAX;
int numVerts = m_unscaledPoints.size();
- for(int i=0;i<numVerts;i++)
+ for (int i = 0; i < numVerts; i++)
{
btVector3 vtx = m_unscaledPoints[i] * m_localScaling;
btVector3 pt = trans * vtx;
btScalar dp = pt.dot(dir);
- if(dp < minProj)
+ if (dp < minProj)
{
minProj = dp;
witnesPtMin = pt;
}
- if(dp > maxProj)
+ if (dp > maxProj)
{
maxProj = dp;
- witnesPtMax=pt;
+ witnesPtMax = pt;
}
}
#else
- btVector3 localAxis = dir*trans.getBasis();
- witnesPtMin = trans(localGetSupportingVertex(localAxis));
+ btVector3 localAxis = dir * trans.getBasis();
+ witnesPtMin = trans(localGetSupportingVertex(localAxis));
witnesPtMax = trans(localGetSupportingVertex(-localAxis));
minProj = witnesPtMin.dot(dir);
maxProj = witnesPtMax.dot(dir);
#endif
- if(minProj>maxProj)
+ if (minProj > maxProj)
{
- btSwap(minProj,maxProj);
- btSwap(witnesPtMin,witnesPtMax);
+ btSwap(minProj, maxProj);
+ btSwap(witnesPtMin, witnesPtMax);
}
-
-
}
-
-
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexHullShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexHullShape.h
index 0c12aeef15..96136d7dd7 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexHullShape.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexHullShape.h
@@ -17,28 +17,26 @@ subject to the following restrictions:
#define BT_CONVEX_HULL_SHAPE_H
#include "btPolyhedralConvexShape.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
#include "LinearMath/btAlignedObjectArray.h"
-
///The btConvexHullShape implements an implicit convex hull of an array of vertices.
///Bullet provides a general and fast collision detector for convex shapes based on GJK and EPA using localGetSupportingVertex.
-ATTRIBUTE_ALIGNED16(class) btConvexHullShape : public btPolyhedralConvexAabbCachingShape
+ATTRIBUTE_ALIGNED16(class)
+btConvexHullShape : public btPolyhedralConvexAabbCachingShape
{
- btAlignedObjectArray<btVector3> m_unscaledPoints;
+ btAlignedObjectArray<btVector3> m_unscaledPoints;
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
-
///this constructor optionally takes in a pointer to points. Each point is assumed to be 3 consecutive btScalar (x,y,z), the striding defines the number of bytes between each point, in memory.
///It is easier to not pass any points in the constructor, and just add one point at a time, using addPoint.
///btConvexHullShape make an internal copy of the points.
- btConvexHullShape(const btScalar* points=0,int numPoints=0, int stride=sizeof(btVector3));
+ btConvexHullShape(const btScalar* points = 0, int numPoints = 0, int stride = sizeof(btVector3));
void addPoint(const btVector3& point, bool recalculateLocalAabb = true);
-
btVector3* getUnscaledPoints()
{
return &m_unscaledPoints[0];
@@ -55,48 +53,46 @@ public:
return getUnscaledPoints();
}
- void optimizeConvexHull();
-
- SIMD_FORCE_INLINE btVector3 getScaledPoint(int i) const
+ void optimizeConvexHull();
+
+ SIMD_FORCE_INLINE btVector3 getScaledPoint(int i) const
{
return m_unscaledPoints[i] * m_localScaling;
}
- SIMD_FORCE_INLINE int getNumPoints() const
+ SIMD_FORCE_INLINE int getNumPoints() const
{
return m_unscaledPoints.size();
}
- virtual btVector3 localGetSupportingVertex(const btVector3& vec)const;
- virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
- virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
-
-
- virtual void project(const btTransform& trans, const btVector3& dir, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin,btVector3& witnesPtMax) const;
+ virtual btVector3 localGetSupportingVertex(const btVector3& vec) const;
+ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const;
+ virtual void project(const btTransform& trans, const btVector3& dir, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin, btVector3& witnesPtMax) const;
//debugging
- virtual const char* getName()const {return "Convex";}
+ virtual const char* getName() const { return "Convex"; }
-
- virtual int getNumVertices() const;
+ virtual int getNumVertices() const;
virtual int getNumEdges() const;
- virtual void getEdge(int i,btVector3& pa,btVector3& pb) const;
- virtual void getVertex(int i,btVector3& vtx) const;
- virtual int getNumPlanes() const;
- virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const;
- virtual bool isInside(const btVector3& pt,btScalar tolerance) const;
+ virtual void getEdge(int i, btVector3& pa, btVector3& pb) const;
+ virtual void getVertex(int i, btVector3& vtx) const;
+ virtual int getNumPlanes() const;
+ virtual void getPlane(btVector3 & planeNormal, btVector3 & planeSupport, int i) const;
+ virtual bool isInside(const btVector3& pt, btScalar tolerance) const;
///in case we receive negative scaling
- virtual void setLocalScaling(const btVector3& scaling);
+ virtual void setLocalScaling(const btVector3& scaling);
- virtual int calculateSerializeBufferSize() const;
+ virtual int calculateSerializeBufferSize() const;
///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
};
+// clang-format off
+
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
struct btConvexHullShapeData
{
@@ -110,12 +106,11 @@ struct btConvexHullShapeData
};
+// clang-format on
-SIMD_FORCE_INLINE int btConvexHullShape::calculateSerializeBufferSize() const
+SIMD_FORCE_INLINE int btConvexHullShape::calculateSerializeBufferSize() const
{
return sizeof(btConvexHullShapeData);
}
-
-#endif //BT_CONVEX_HULL_SHAPE_H
-
+#endif //BT_CONVEX_HULL_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexInternalShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexInternalShape.cpp
index 083d60b1b1..4d598b1aa2 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexInternalShape.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexInternalShape.cpp
@@ -13,139 +13,125 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#include "btConvexInternalShape.h"
-
-
btConvexInternalShape::btConvexInternalShape()
-: m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)),
-m_collisionMargin(CONVEX_DISTANCE_MARGIN)
+ : m_localScaling(btScalar(1.), btScalar(1.), btScalar(1.)),
+ m_collisionMargin(CONVEX_DISTANCE_MARGIN)
{
}
-
-void btConvexInternalShape::setLocalScaling(const btVector3& scaling)
+void btConvexInternalShape::setLocalScaling(const btVector3& scaling)
{
m_localScaling = scaling.absolute();
}
-
-
-void btConvexInternalShape::getAabbSlow(const btTransform& trans,btVector3&minAabb,btVector3&maxAabb) const
+void btConvexInternalShape::getAabbSlow(const btTransform& trans, btVector3& minAabb, btVector3& maxAabb) const
{
#ifndef __SPU__
//use localGetSupportingVertexWithoutMargin?
btScalar margin = getMargin();
- for (int i=0;i<3;i++)
+ for (int i = 0; i < 3; i++)
{
- btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.));
+ btVector3 vec(btScalar(0.), btScalar(0.), btScalar(0.));
vec[i] = btScalar(1.);
- btVector3 sv = localGetSupportingVertex(vec*trans.getBasis());
+ btVector3 sv = localGetSupportingVertex(vec * trans.getBasis());
btVector3 tmp = trans(sv);
- maxAabb[i] = tmp[i]+margin;
+ maxAabb[i] = tmp[i] + margin;
vec[i] = btScalar(-1.);
- tmp = trans(localGetSupportingVertex(vec*trans.getBasis()));
- minAabb[i] = tmp[i]-margin;
+ tmp = trans(localGetSupportingVertex(vec * trans.getBasis()));
+ minAabb[i] = tmp[i] - margin;
}
#endif
}
-
-
-btVector3 btConvexInternalShape::localGetSupportingVertex(const btVector3& vec)const
+btVector3 btConvexInternalShape::localGetSupportingVertex(const btVector3& vec) const
{
#ifndef __SPU__
- btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec);
+ btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec);
- if ( getMargin()!=btScalar(0.) )
+ if (getMargin() != btScalar(0.))
{
btVector3 vecnorm = vec;
- if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
+ if (vecnorm.length2() < (SIMD_EPSILON * SIMD_EPSILON))
{
- vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
- }
+ vecnorm.setValue(btScalar(-1.), btScalar(-1.), btScalar(-1.));
+ }
vecnorm.normalize();
- supVertex+= getMargin() * vecnorm;
+ supVertex += getMargin() * vecnorm;
}
return supVertex;
#else
btAssert(0);
- return btVector3(0,0,0);
-#endif //__SPU__
-
- }
-
+ return btVector3(0, 0, 0);
+#endif //__SPU__
+}
btConvexInternalAabbCachingShape::btConvexInternalAabbCachingShape()
- : btConvexInternalShape(),
-m_localAabbMin(1,1,1),
-m_localAabbMax(-1,-1,-1),
-m_isLocalAabbValid(false)
+ : btConvexInternalShape(),
+ m_localAabbMin(1, 1, 1),
+ m_localAabbMax(-1, -1, -1),
+ m_isLocalAabbValid(false)
{
}
-
-void btConvexInternalAabbCachingShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const
+void btConvexInternalAabbCachingShape::getAabb(const btTransform& trans, btVector3& aabbMin, btVector3& aabbMax) const
{
- getNonvirtualAabb(trans,aabbMin,aabbMax,getMargin());
+ getNonvirtualAabb(trans, aabbMin, aabbMax, getMargin());
}
-void btConvexInternalAabbCachingShape::setLocalScaling(const btVector3& scaling)
+void btConvexInternalAabbCachingShape::setLocalScaling(const btVector3& scaling)
{
btConvexInternalShape::setLocalScaling(scaling);
recalcLocalAabb();
}
-
-void btConvexInternalAabbCachingShape::recalcLocalAabb()
+void btConvexInternalAabbCachingShape::recalcLocalAabb()
{
m_isLocalAabbValid = true;
-
- #if 1
+
+#if 1
static const btVector3 _directions[] =
- {
- btVector3( 1., 0., 0.),
- btVector3( 0., 1., 0.),
- btVector3( 0., 0., 1.),
- btVector3( -1., 0., 0.),
- btVector3( 0., -1., 0.),
- btVector3( 0., 0., -1.)
- };
-
+ {
+ btVector3(1., 0., 0.),
+ btVector3(0., 1., 0.),
+ btVector3(0., 0., 1.),
+ btVector3(-1., 0., 0.),
+ btVector3(0., -1., 0.),
+ btVector3(0., 0., -1.)};
+
btVector3 _supporting[] =
- {
- btVector3( 0., 0., 0.),
- btVector3( 0., 0., 0.),
- btVector3( 0., 0., 0.),
- btVector3( 0., 0., 0.),
- btVector3( 0., 0., 0.),
- btVector3( 0., 0., 0.)
- };
-
+ {
+ btVector3(0., 0., 0.),
+ btVector3(0., 0., 0.),
+ btVector3(0., 0., 0.),
+ btVector3(0., 0., 0.),
+ btVector3(0., 0., 0.),
+ btVector3(0., 0., 0.)};
+
batchedUnitVectorGetSupportingVertexWithoutMargin(_directions, _supporting, 6);
-
- for ( int i = 0; i < 3; ++i )
+
+ for (int i = 0; i < 3; ++i)
{
m_localAabbMax[i] = _supporting[i][i] + m_collisionMargin;
m_localAabbMin[i] = _supporting[i + 3][i] - m_collisionMargin;
}
-
- #else
- for (int i=0;i<3;i++)
+#else
+
+ for (int i = 0; i < 3; i++)
{
- btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.));
+ btVector3 vec(btScalar(0.), btScalar(0.), btScalar(0.));
vec[i] = btScalar(1.);
btVector3 tmp = localGetSupportingVertex(vec);
- m_localAabbMax[i] = tmp[i]+m_collisionMargin;
+ m_localAabbMax[i] = tmp[i] + m_collisionMargin;
vec[i] = btScalar(-1.);
tmp = localGetSupportingVertex(vec);
- m_localAabbMin[i] = tmp[i]-m_collisionMargin;
+ m_localAabbMin[i] = tmp[i] - m_collisionMargin;
}
- #endif
+#endif
}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexInternalShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexInternalShape.h
index 1213b82fbe..a28c57de4b 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexInternalShape.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexInternalShape.h
@@ -19,39 +19,35 @@ subject to the following restrictions:
#include "btConvexShape.h"
#include "LinearMath/btAabbUtil2.h"
-
///The btConvexInternalShape is an internal base class, shared by most convex shape implementations.
///The btConvexInternalShape uses a default collision margin set to CONVEX_DISTANCE_MARGIN.
///This collision margin used by Gjk and some other algorithms, see also btCollisionMargin.h
-///Note that when creating small shapes (derived from btConvexInternalShape),
+///Note that when creating small shapes (derived from btConvexInternalShape),
///you need to make sure to set a smaller collision margin, using the 'setMargin' API
///There is a automatic mechanism 'setSafeMargin' used by btBoxShape and btCylinderShape
-ATTRIBUTE_ALIGNED16(class) btConvexInternalShape : public btConvexShape
+ATTRIBUTE_ALIGNED16(class)
+btConvexInternalShape : public btConvexShape
{
-
- protected:
-
+protected:
//local scaling. collisionMargin is not scaled !
- btVector3 m_localScaling;
+ btVector3 m_localScaling;
+
+ btVector3 m_implicitShapeDimensions;
- btVector3 m_implicitShapeDimensions;
-
- btScalar m_collisionMargin;
+ btScalar m_collisionMargin;
- btScalar m_padding;
+ btScalar m_padding;
btConvexInternalShape();
public:
-
BT_DECLARE_ALIGNED_ALLOCATOR();
virtual ~btConvexInternalShape()
{
-
}
- virtual btVector3 localGetSupportingVertex(const btVector3& vec)const;
+ virtual btVector3 localGetSupportingVertex(const btVector3& vec) const;
const btVector3& getImplicitShapeDimensions() const
{
@@ -62,110 +58,102 @@ public:
///changing a collision shape while the body is in the world is not recommended,
///it is best to remove the body from the world, then make the change, and re-add it
///alternatively flush the contact points, see documentation for 'cleanProxyFromPairs'
- void setImplicitShapeDimensions(const btVector3& dimensions)
+ void setImplicitShapeDimensions(const btVector3& dimensions)
{
m_implicitShapeDimensions = dimensions;
}
- void setSafeMargin(btScalar minDimension, btScalar defaultMarginMultiplier = 0.1f)
+ void setSafeMargin(btScalar minDimension, btScalar defaultMarginMultiplier = 0.1f)
{
- btScalar safeMargin = defaultMarginMultiplier*minDimension;
+ btScalar safeMargin = defaultMarginMultiplier * minDimension;
if (safeMargin < getMargin())
{
setMargin(safeMargin);
}
}
- void setSafeMargin(const btVector3& halfExtents, btScalar defaultMarginMultiplier = 0.1f)
+ void setSafeMargin(const btVector3& halfExtents, btScalar defaultMarginMultiplier = 0.1f)
{
//see http://code.google.com/p/bullet/issues/detail?id=349
//this margin check could could be added to other collision shapes too,
//or add some assert/warning somewhere
- btScalar minDimension=halfExtents[halfExtents.minAxis()];
+ btScalar minDimension = halfExtents[halfExtents.minAxis()];
setSafeMargin(minDimension, defaultMarginMultiplier);
}
///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
- void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+ void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
{
- getAabbSlow(t,aabbMin,aabbMax);
+ getAabbSlow(t, aabbMin, aabbMax);
}
+ virtual void getAabbSlow(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
-
- virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
-
-
- virtual void setLocalScaling(const btVector3& scaling);
- virtual const btVector3& getLocalScaling() const
+ virtual void setLocalScaling(const btVector3& scaling);
+ virtual const btVector3& getLocalScaling() const
{
return m_localScaling;
}
- const btVector3& getLocalScalingNV() const
+ const btVector3& getLocalScalingNV() const
{
return m_localScaling;
}
- virtual void setMargin(btScalar margin)
+ virtual void setMargin(btScalar margin)
{
m_collisionMargin = margin;
}
- virtual btScalar getMargin() const
+ virtual btScalar getMargin() const
{
return m_collisionMargin;
}
- btScalar getMarginNV() const
+ btScalar getMarginNV() const
{
return m_collisionMargin;
}
- virtual int getNumPreferredPenetrationDirections() const
+ virtual int getNumPreferredPenetrationDirections() const
{
return 0;
}
-
- virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
+
+ virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
{
(void)penetrationVector;
(void)index;
btAssert(0);
}
- virtual int calculateSerializeBufferSize() const;
+ virtual int calculateSerializeBufferSize() const;
///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-
-
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
};
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btConvexInternalShapeData
+struct btConvexInternalShapeData
{
- btCollisionShapeData m_collisionShapeData;
+ btCollisionShapeData m_collisionShapeData;
- btVector3FloatData m_localScaling;
+ btVector3FloatData m_localScaling;
- btVector3FloatData m_implicitShapeDimensions;
-
- float m_collisionMargin;
+ btVector3FloatData m_implicitShapeDimensions;
- int m_padding;
+ float m_collisionMargin;
+ int m_padding;
};
-
-
-SIMD_FORCE_INLINE int btConvexInternalShape::calculateSerializeBufferSize() const
+SIMD_FORCE_INLINE int btConvexInternalShape::calculateSerializeBufferSize() const
{
return sizeof(btConvexInternalShapeData);
}
///fills the dataBuffer and returns the struct name (and 0 on failure)
-SIMD_FORCE_INLINE const char* btConvexInternalShape::serialize(void* dataBuffer, btSerializer* serializer) const
+SIMD_FORCE_INLINE const char* btConvexInternalShape::serialize(void* dataBuffer, btSerializer* serializer) const
{
- btConvexInternalShapeData* shapeData = (btConvexInternalShapeData*) dataBuffer;
+ btConvexInternalShapeData* shapeData = (btConvexInternalShapeData*)dataBuffer;
btCollisionShape::serialize(&shapeData->m_collisionShapeData, serializer);
m_implicitShapeDimensions.serializeFloat(shapeData->m_implicitShapeDimensions);
@@ -178,50 +166,43 @@ SIMD_FORCE_INLINE const char* btConvexInternalShape::serialize(void* dataBuffer,
return "btConvexInternalShapeData";
}
-
-
-
///btConvexInternalAabbCachingShape adds local aabb caching for convex shapes, to avoid expensive bounding box calculations
class btConvexInternalAabbCachingShape : public btConvexInternalShape
{
- btVector3 m_localAabbMin;
- btVector3 m_localAabbMax;
- bool m_isLocalAabbValid;
-
+ btVector3 m_localAabbMin;
+ btVector3 m_localAabbMax;
+ bool m_isLocalAabbValid;
+
protected:
-
btConvexInternalAabbCachingShape();
-
- void setCachedLocalAabb (const btVector3& aabbMin, const btVector3& aabbMax)
+
+ void setCachedLocalAabb(const btVector3& aabbMin, const btVector3& aabbMax)
{
m_isLocalAabbValid = true;
m_localAabbMin = aabbMin;
m_localAabbMax = aabbMax;
}
- inline void getCachedLocalAabb (btVector3& aabbMin, btVector3& aabbMax) const
+ inline void getCachedLocalAabb(btVector3& aabbMin, btVector3& aabbMax) const
{
btAssert(m_isLocalAabbValid);
aabbMin = m_localAabbMin;
aabbMax = m_localAabbMax;
}
- inline void getNonvirtualAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax, btScalar margin) const
+ inline void getNonvirtualAabb(const btTransform& trans, btVector3& aabbMin, btVector3& aabbMax, btScalar margin) const
{
-
//lazy evaluation of local aabb
btAssert(m_isLocalAabbValid);
- btTransformAabb(m_localAabbMin,m_localAabbMax,margin,trans,aabbMin,aabbMax);
+ btTransformAabb(m_localAabbMin, m_localAabbMax, margin, trans, aabbMin, aabbMax);
}
-
-public:
-
- virtual void setLocalScaling(const btVector3& scaling);
- virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+public:
+ virtual void setLocalScaling(const btVector3& scaling);
- void recalcLocalAabb();
+ virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
+ void recalcLocalAabb();
};
-#endif //BT_CONVEX_INTERNAL_SHAPE_H
+#endif //BT_CONVEX_INTERNAL_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp
index ad1d1bf78f..f00a440fa3 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp
@@ -25,81 +25,73 @@ void btConvexPointCloudShape::setLocalScaling(const btVector3& scaling)
}
#ifndef __SPU__
-btVector3 btConvexPointCloudShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const
+btVector3 btConvexPointCloudShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0) const
{
- btVector3 supVec(btScalar(0.),btScalar(0.),btScalar(0.));
+ btVector3 supVec(btScalar(0.), btScalar(0.), btScalar(0.));
btScalar maxDot = btScalar(-BT_LARGE_FLOAT);
btVector3 vec = vec0;
btScalar lenSqr = vec.length2();
if (lenSqr < btScalar(0.0001))
{
- vec.setValue(1,0,0);
- } else
+ vec.setValue(1, 0, 0);
+ }
+ else
{
- btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
+ btScalar rlen = btScalar(1.) / btSqrt(lenSqr);
vec *= rlen;
}
-
- if( m_numPoints > 0 )
- {
- // Here we take advantage of dot(a*b, c) = dot( a, b*c) to do less work. Note this transformation is true mathematically, not numerically.
- // btVector3 scaled = vec * m_localScaling;
- int index = (int) vec.maxDot( &m_unscaledPoints[0], m_numPoints, maxDot); //FIXME: may violate encapsulation of m_unscaledPoints
- return getScaledPoint(index);
- }
+
+ if (m_numPoints > 0)
+ {
+ // Here we take advantage of dot(a*b, c) = dot( a, b*c) to do less work. Note this transformation is true mathematically, not numerically.
+ // btVector3 scaled = vec * m_localScaling;
+ int index = (int)vec.maxDot(&m_unscaledPoints[0], m_numPoints, maxDot); //FIXME: may violate encapsulation of m_unscaledPoints
+ return getScaledPoint(index);
+ }
return supVec;
}
-void btConvexPointCloudShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+void btConvexPointCloudShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
{
- for( int j = 0; j < numVectors; j++ )
- {
- const btVector3& vec = vectors[j] * m_localScaling; // dot( a*c, b) = dot(a, b*c)
- btScalar maxDot;
- int index = (int) vec.maxDot( &m_unscaledPoints[0], m_numPoints, maxDot);
- supportVerticesOut[j][3] = btScalar(-BT_LARGE_FLOAT);
- if( 0 <= index )
- {
- //WARNING: don't swap next lines, the w component would get overwritten!
- supportVerticesOut[j] = getScaledPoint(index);
- supportVerticesOut[j][3] = maxDot;
- }
- }
-
+ for (int j = 0; j < numVectors; j++)
+ {
+ const btVector3& vec = vectors[j] * m_localScaling; // dot( a*c, b) = dot(a, b*c)
+ btScalar maxDot;
+ int index = (int)vec.maxDot(&m_unscaledPoints[0], m_numPoints, maxDot);
+ supportVerticesOut[j][3] = btScalar(-BT_LARGE_FLOAT);
+ if (0 <= index)
+ {
+ //WARNING: don't swap next lines, the w component would get overwritten!
+ supportVerticesOut[j] = getScaledPoint(index);
+ supportVerticesOut[j][3] = maxDot;
+ }
+ }
}
-
-
-btVector3 btConvexPointCloudShape::localGetSupportingVertex(const btVector3& vec)const
+btVector3 btConvexPointCloudShape::localGetSupportingVertex(const btVector3& vec) const
{
btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec);
- if ( getMargin()!=btScalar(0.) )
+ if (getMargin() != btScalar(0.))
{
btVector3 vecnorm = vec;
- if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
+ if (vecnorm.length2() < (SIMD_EPSILON * SIMD_EPSILON))
{
- vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
- }
+ vecnorm.setValue(btScalar(-1.), btScalar(-1.), btScalar(-1.));
+ }
vecnorm.normalize();
- supVertex+= getMargin() * vecnorm;
+ supVertex += getMargin() * vecnorm;
}
return supVertex;
}
-
#endif
-
-
-
-
-
//currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection
//Please note that you can debug-draw btConvexHullShape with the Raytracer Demo
-int btConvexPointCloudShape::getNumVertices() const
+int btConvexPointCloudShape::getNumVertices() const
{
return m_numPoints;
}
@@ -109,31 +101,29 @@ int btConvexPointCloudShape::getNumEdges() const
return 0;
}
-void btConvexPointCloudShape::getEdge(int i,btVector3& pa,btVector3& pb) const
+void btConvexPointCloudShape::getEdge(int i, btVector3& pa, btVector3& pb) const
{
- btAssert (0);
+ btAssert(0);
}
-void btConvexPointCloudShape::getVertex(int i,btVector3& vtx) const
+void btConvexPointCloudShape::getVertex(int i, btVector3& vtx) const
{
- vtx = m_unscaledPoints[i]*m_localScaling;
+ vtx = m_unscaledPoints[i] * m_localScaling;
}
-int btConvexPointCloudShape::getNumPlanes() const
+int btConvexPointCloudShape::getNumPlanes() const
{
return 0;
}
-void btConvexPointCloudShape::getPlane(btVector3& ,btVector3& ,int ) const
+void btConvexPointCloudShape::getPlane(btVector3&, btVector3&, int) const
{
-
btAssert(0);
}
//not yet
-bool btConvexPointCloudShape::isInside(const btVector3& ,btScalar ) const
+bool btConvexPointCloudShape::isInside(const btVector3&, btScalar) const
{
btAssert(0);
return false;
}
-
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPointCloudShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPointCloudShape.h
index 54b5afac3e..c7d554a4d3 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPointCloudShape.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPointCloudShape.h
@@ -17,11 +17,12 @@ subject to the following restrictions:
#define BT_CONVEX_POINT_CLOUD_SHAPE_H
#include "btPolyhedralConvexShape.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
#include "LinearMath/btAlignedObjectArray.h"
///The btConvexPointCloudShape implements an implicit convex hull of an array of vertices.
-ATTRIBUTE_ALIGNED16(class) btConvexPointCloudShape : public btPolyhedralConvexAabbCachingShape
+ATTRIBUTE_ALIGNED16(class)
+btConvexPointCloudShape : public btPolyhedralConvexAabbCachingShape
{
btVector3* m_unscaledPoints;
int m_numPoints;
@@ -31,13 +32,13 @@ public:
btConvexPointCloudShape()
{
- m_localScaling.setValue(1.f,1.f,1.f);
+ m_localScaling.setValue(1.f, 1.f, 1.f);
m_shapeType = CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE;
m_unscaledPoints = 0;
m_numPoints = 0;
}
- btConvexPointCloudShape(btVector3* points,int numPoints, const btVector3& localScaling,bool computeAabb = true)
+ btConvexPointCloudShape(btVector3 * points, int numPoints, const btVector3& localScaling, bool computeAabb = true)
{
m_localScaling = localScaling;
m_shapeType = CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE;
@@ -48,7 +49,7 @@ public:
recalcLocalAabb();
}
- void setPoints (btVector3* points, int numPoints, bool computeAabb = true,const btVector3& localScaling=btVector3(1.f,1.f,1.f))
+ void setPoints(btVector3 * points, int numPoints, bool computeAabb = true, const btVector3& localScaling = btVector3(1.f, 1.f, 1.f))
{
m_unscaledPoints = points;
m_numPoints = numPoints;
@@ -58,48 +59,45 @@ public:
recalcLocalAabb();
}
- SIMD_FORCE_INLINE btVector3* getUnscaledPoints()
+ SIMD_FORCE_INLINE btVector3* getUnscaledPoints()
{
return m_unscaledPoints;
}
- SIMD_FORCE_INLINE const btVector3* getUnscaledPoints() const
+ SIMD_FORCE_INLINE const btVector3* getUnscaledPoints() const
{
return m_unscaledPoints;
}
- SIMD_FORCE_INLINE int getNumPoints() const
+ SIMD_FORCE_INLINE int getNumPoints() const
{
return m_numPoints;
}
- SIMD_FORCE_INLINE btVector3 getScaledPoint( int index) const
+ SIMD_FORCE_INLINE btVector3 getScaledPoint(int index) const
{
return m_unscaledPoints[index] * m_localScaling;
}
#ifndef __SPU__
- virtual btVector3 localGetSupportingVertex(const btVector3& vec)const;
- virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
- virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+ virtual btVector3 localGetSupportingVertex(const btVector3& vec) const;
+ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const;
#endif
-
//debugging
- virtual const char* getName()const {return "ConvexPointCloud";}
+ virtual const char* getName() const { return "ConvexPointCloud"; }
- virtual int getNumVertices() const;
+ virtual int getNumVertices() const;
virtual int getNumEdges() const;
- virtual void getEdge(int i,btVector3& pa,btVector3& pb) const;
- virtual void getVertex(int i,btVector3& vtx) const;
- virtual int getNumPlanes() const;
- virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const;
- virtual bool isInside(const btVector3& pt,btScalar tolerance) const;
+ virtual void getEdge(int i, btVector3& pa, btVector3& pb) const;
+ virtual void getVertex(int i, btVector3& vtx) const;
+ virtual int getNumPlanes() const;
+ virtual void getPlane(btVector3 & planeNormal, btVector3 & planeSupport, int i) const;
+ virtual bool isInside(const btVector3& pt, btScalar tolerance) const;
///in case we receive negative scaling
- virtual void setLocalScaling(const btVector3& scaling);
+ virtual void setLocalScaling(const btVector3& scaling);
};
-
-#endif //BT_CONVEX_POINT_CLOUD_SHAPE_H
-
+#endif //BT_CONVEX_POINT_CLOUD_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp
index 0fea00df5c..65b669e1c0 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp
@@ -13,7 +13,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
///This file was written by Erwin Coumans
///Separating axis rest based on work from Pierre Terdiman, see
///And contact clipping based on work from Simon Hobbs
@@ -21,49 +20,45 @@ subject to the following restrictions:
#include "btConvexPolyhedron.h"
#include "LinearMath/btHashMap.h"
-
btConvexPolyhedron::btConvexPolyhedron()
{
-
}
btConvexPolyhedron::~btConvexPolyhedron()
{
-
}
-
inline bool IsAlmostZero(const btVector3& v)
{
- if(btFabs(v.x())>1e-6 || btFabs(v.y())>1e-6 || btFabs(v.z())>1e-6) return false;
+ if (btFabs(v.x()) > 1e-6 || btFabs(v.y()) > 1e-6 || btFabs(v.z()) > 1e-6) return false;
return true;
}
struct btInternalVertexPair
{
- btInternalVertexPair(short int v0,short int v1)
- :m_v0(v0),
- m_v1(v1)
+ btInternalVertexPair(short int v0, short int v1)
+ : m_v0(v0),
+ m_v1(v1)
{
- if (m_v1>m_v0)
- btSwap(m_v0,m_v1);
+ if (m_v1 > m_v0)
+ btSwap(m_v0, m_v1);
}
short int m_v0;
short int m_v1;
int getHash() const
{
- return m_v0+(m_v1<<16);
+ return m_v0 + (m_v1 << 16);
}
bool equals(const btInternalVertexPair& other) const
{
- return m_v0==other.m_v0 && m_v1==other.m_v1;
+ return m_v0 == other.m_v0 && m_v1 == other.m_v1;
}
};
struct btInternalEdge
{
btInternalEdge()
- :m_face0(-1),
- m_face1(-1)
+ : m_face0(-1),
+ m_face1(-1)
{
}
short int m_face0;
@@ -75,23 +70,31 @@ struct btInternalEdge
#ifdef TEST_INTERNAL_OBJECTS
bool btConvexPolyhedron::testContainment() const
{
- for(int p=0;p<8;p++)
+ for (int p = 0; p < 8; p++)
{
btVector3 LocalPt;
- if(p==0) LocalPt = m_localCenter + btVector3(m_extents[0], m_extents[1], m_extents[2]);
- else if(p==1) LocalPt = m_localCenter + btVector3(m_extents[0], m_extents[1], -m_extents[2]);
- else if(p==2) LocalPt = m_localCenter + btVector3(m_extents[0], -m_extents[1], m_extents[2]);
- else if(p==3) LocalPt = m_localCenter + btVector3(m_extents[0], -m_extents[1], -m_extents[2]);
- else if(p==4) LocalPt = m_localCenter + btVector3(-m_extents[0], m_extents[1], m_extents[2]);
- else if(p==5) LocalPt = m_localCenter + btVector3(-m_extents[0], m_extents[1], -m_extents[2]);
- else if(p==6) LocalPt = m_localCenter + btVector3(-m_extents[0], -m_extents[1], m_extents[2]);
- else if(p==7) LocalPt = m_localCenter + btVector3(-m_extents[0], -m_extents[1], -m_extents[2]);
-
- for(int i=0;i<m_faces.size();i++)
+ if (p == 0)
+ LocalPt = m_localCenter + btVector3(m_extents[0], m_extents[1], m_extents[2]);
+ else if (p == 1)
+ LocalPt = m_localCenter + btVector3(m_extents[0], m_extents[1], -m_extents[2]);
+ else if (p == 2)
+ LocalPt = m_localCenter + btVector3(m_extents[0], -m_extents[1], m_extents[2]);
+ else if (p == 3)
+ LocalPt = m_localCenter + btVector3(m_extents[0], -m_extents[1], -m_extents[2]);
+ else if (p == 4)
+ LocalPt = m_localCenter + btVector3(-m_extents[0], m_extents[1], m_extents[2]);
+ else if (p == 5)
+ LocalPt = m_localCenter + btVector3(-m_extents[0], m_extents[1], -m_extents[2]);
+ else if (p == 6)
+ LocalPt = m_localCenter + btVector3(-m_extents[0], -m_extents[1], m_extents[2]);
+ else if (p == 7)
+ LocalPt = m_localCenter + btVector3(-m_extents[0], -m_extents[1], -m_extents[2]);
+
+ for (int i = 0; i < m_faces.size(); i++)
{
const btVector3 Normal(m_faces[i].m_plane[0], m_faces[i].m_plane[1], m_faces[i].m_plane[2]);
const btScalar d = LocalPt.dot(Normal) + m_faces[i].m_plane[3];
- if(d>0.0f)
+ if (d > 0.0f)
return false;
}
}
@@ -99,33 +102,28 @@ bool btConvexPolyhedron::testContainment() const
}
#endif
-void btConvexPolyhedron::initialize()
+void btConvexPolyhedron::initialize()
{
+ btHashMap<btInternalVertexPair, btInternalEdge> edges;
- btHashMap<btInternalVertexPair,btInternalEdge> edges;
-
-
-
-
- for(int i=0;i<m_faces.size();i++)
+ for (int i = 0; i < m_faces.size(); i++)
{
int numVertices = m_faces[i].m_indices.size();
int NbTris = numVertices;
- for(int j=0;j<NbTris;j++)
+ for (int j = 0; j < NbTris; j++)
{
- int k = (j+1)%numVertices;
- btInternalVertexPair vp(m_faces[i].m_indices[j],m_faces[i].m_indices[k]);
+ int k = (j + 1) % numVertices;
+ btInternalVertexPair vp(m_faces[i].m_indices[j], m_faces[i].m_indices[k]);
btInternalEdge* edptr = edges.find(vp);
- btVector3 edge = m_vertices[vp.m_v1]-m_vertices[vp.m_v0];
+ btVector3 edge = m_vertices[vp.m_v1] - m_vertices[vp.m_v0];
edge.normalize();
bool found = false;
- for (int p=0;p<m_uniqueEdges.size();p++)
+ for (int p = 0; p < m_uniqueEdges.size(); p++)
{
-
- if (IsAlmostZero(m_uniqueEdges[p]-edge) ||
- IsAlmostZero(m_uniqueEdges[p]+edge))
+ if (IsAlmostZero(m_uniqueEdges[p] - edge) ||
+ IsAlmostZero(m_uniqueEdges[p] + edge))
{
found = true;
break;
@@ -139,112 +137,107 @@ void btConvexPolyhedron::initialize()
if (edptr)
{
- btAssert(edptr->m_face0>=0);
- btAssert(edptr->m_face1<0);
+ btAssert(edptr->m_face0 >= 0);
+ btAssert(edptr->m_face1 < 0);
edptr->m_face1 = i;
- } else
+ }
+ else
{
btInternalEdge ed;
ed.m_face0 = i;
- edges.insert(vp,ed);
+ edges.insert(vp, ed);
}
}
}
#ifdef USE_CONNECTED_FACES
- for(int i=0;i<m_faces.size();i++)
+ for (int i = 0; i < m_faces.size(); i++)
{
int numVertices = m_faces[i].m_indices.size();
m_faces[i].m_connectedFaces.resize(numVertices);
- for(int j=0;j<numVertices;j++)
+ for (int j = 0; j < numVertices; j++)
{
- int k = (j+1)%numVertices;
- btInternalVertexPair vp(m_faces[i].m_indices[j],m_faces[i].m_indices[k]);
+ int k = (j + 1) % numVertices;
+ btInternalVertexPair vp(m_faces[i].m_indices[j], m_faces[i].m_indices[k]);
btInternalEdge* edptr = edges.find(vp);
btAssert(edptr);
- btAssert(edptr->m_face0>=0);
- btAssert(edptr->m_face1>=0);
+ btAssert(edptr->m_face0 >= 0);
+ btAssert(edptr->m_face1 >= 0);
- int connectedFace = (edptr->m_face0==i)?edptr->m_face1:edptr->m_face0;
+ int connectedFace = (edptr->m_face0 == i) ? edptr->m_face1 : edptr->m_face0;
m_faces[i].m_connectedFaces[j] = connectedFace;
}
}
-#endif//USE_CONNECTED_FACES
+#endif //USE_CONNECTED_FACES
initialize2();
}
-void btConvexPolyhedron::initialize2()
+void btConvexPolyhedron::initialize2()
{
m_localCenter.setValue(0, 0, 0);
btScalar TotalArea = 0.0f;
- for(int i=0;i<m_faces.size();i++)
+ for (int i = 0; i < m_faces.size(); i++)
{
int numVertices = m_faces[i].m_indices.size();
- int NbTris = numVertices-2;
-
+ int NbTris = numVertices - 2;
+
const btVector3& p0 = m_vertices[m_faces[i].m_indices[0]];
- for(int j=1;j<=NbTris;j++)
+ for (int j = 1; j <= NbTris; j++)
{
- int k = (j+1)%numVertices;
+ int k = (j + 1) % numVertices;
const btVector3& p1 = m_vertices[m_faces[i].m_indices[j]];
const btVector3& p2 = m_vertices[m_faces[i].m_indices[k]];
btScalar Area = ((p0 - p1).cross(p0 - p2)).length() * 0.5f;
- btVector3 Center = (p0+p1+p2)/3.0f;
+ btVector3 Center = (p0 + p1 + p2) / 3.0f;
m_localCenter += Area * Center;
TotalArea += Area;
}
}
m_localCenter /= TotalArea;
-
-
-
#ifdef TEST_INTERNAL_OBJECTS
- if(1)
+ if (1)
{
m_radius = FLT_MAX;
- for(int i=0;i<m_faces.size();i++)
+ for (int i = 0; i < m_faces.size(); i++)
{
const btVector3 Normal(m_faces[i].m_plane[0], m_faces[i].m_plane[1], m_faces[i].m_plane[2]);
const btScalar dist = btFabs(m_localCenter.dot(Normal) + m_faces[i].m_plane[3]);
- if(dist<m_radius)
+ if (dist < m_radius)
m_radius = dist;
}
-
btScalar MinX = FLT_MAX;
btScalar MinY = FLT_MAX;
btScalar MinZ = FLT_MAX;
btScalar MaxX = -FLT_MAX;
btScalar MaxY = -FLT_MAX;
btScalar MaxZ = -FLT_MAX;
- for(int i=0; i<m_vertices.size(); i++)
+ for (int i = 0; i < m_vertices.size(); i++)
{
const btVector3& pt = m_vertices[i];
- if(pt.x()<MinX) MinX = pt.x();
- if(pt.x()>MaxX) MaxX = pt.x();
- if(pt.y()<MinY) MinY = pt.y();
- if(pt.y()>MaxY) MaxY = pt.y();
- if(pt.z()<MinZ) MinZ = pt.z();
- if(pt.z()>MaxZ) MaxZ = pt.z();
+ if (pt.x() < MinX) MinX = pt.x();
+ if (pt.x() > MaxX) MaxX = pt.x();
+ if (pt.y() < MinY) MinY = pt.y();
+ if (pt.y() > MaxY) MaxY = pt.y();
+ if (pt.z() < MinZ) MinZ = pt.z();
+ if (pt.z() > MaxZ) MaxZ = pt.z();
}
- mC.setValue(MaxX+MinX, MaxY+MinY, MaxZ+MinZ);
- mE.setValue(MaxX-MinX, MaxY-MinY, MaxZ-MinZ);
-
-
+ mC.setValue(MaxX + MinX, MaxY + MinY, MaxZ + MinZ);
+ mE.setValue(MaxX - MinX, MaxY - MinY, MaxZ - MinZ);
-// const btScalar r = m_radius / sqrtf(2.0f);
+ // const btScalar r = m_radius / sqrtf(2.0f);
const btScalar r = m_radius / sqrtf(3.0f);
const int LargestExtent = mE.maxAxis();
- const btScalar Step = (mE[LargestExtent]*0.5f - r)/1024.0f;
+ const btScalar Step = (mE[LargestExtent] * 0.5f - r) / 1024.0f;
m_extents[0] = m_extents[1] = m_extents[2] = r;
- m_extents[LargestExtent] = mE[LargestExtent]*0.5f;
+ m_extents[LargestExtent] = mE[LargestExtent] * 0.5f;
bool FoundBox = false;
- for(int j=0;j<1024;j++)
+ for (int j = 0; j < 1024; j++)
{
- if(testContainment())
+ if (testContainment())
{
FoundBox = true;
break;
@@ -252,25 +245,25 @@ void btConvexPolyhedron::initialize2()
m_extents[LargestExtent] -= Step;
}
- if(!FoundBox)
+ if (!FoundBox)
{
m_extents[0] = m_extents[1] = m_extents[2] = r;
}
else
{
// Refine the box
- const btScalar Step = (m_radius - r)/1024.0f;
- const int e0 = (1<<LargestExtent) & 3;
- const int e1 = (1<<e0) & 3;
+ const btScalar Step = (m_radius - r) / 1024.0f;
+ const int e0 = (1 << LargestExtent) & 3;
+ const int e1 = (1 << e0) & 3;
- for(int j=0;j<1024;j++)
+ for (int j = 0; j < 1024; j++)
{
const btScalar Saved0 = m_extents[e0];
const btScalar Saved1 = m_extents[e1];
m_extents[e0] += Step;
m_extents[e1] += Step;
- if(!testContainment())
+ if (!testContainment())
{
m_extents[e0] = Saved0;
m_extents[e1] = Saved1;
@@ -281,29 +274,29 @@ void btConvexPolyhedron::initialize2()
}
#endif
}
-void btConvexPolyhedron::project(const btTransform& trans, const btVector3& dir, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin,btVector3& witnesPtMax) const
+void btConvexPolyhedron::project(const btTransform& trans, const btVector3& dir, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin, btVector3& witnesPtMax) const
{
minProj = FLT_MAX;
maxProj = -FLT_MAX;
int numVerts = m_vertices.size();
- for(int i=0;i<numVerts;i++)
+ for (int i = 0; i < numVerts; i++)
{
btVector3 pt = trans * m_vertices[i];
btScalar dp = pt.dot(dir);
- if(dp < minProj)
+ if (dp < minProj)
{
minProj = dp;
witnesPtMin = pt;
}
- if(dp > maxProj)
+ if (dp > maxProj)
{
maxProj = dp;
witnesPtMax = pt;
}
}
- if(minProj>maxProj)
+ if (minProj > maxProj)
{
- btSwap(minProj,maxProj);
- btSwap(witnesPtMin,witnesPtMax);
+ btSwap(minProj, maxProj);
+ btSwap(witnesPtMin, witnesPtMax);
}
}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPolyhedron.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPolyhedron.h
index c5aa20f453..638aa9b3df 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPolyhedron.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPolyhedron.h
@@ -13,10 +13,8 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
///This file was written by Erwin Coumans
-
#ifndef _BT_POLYHEDRAL_FEATURES_H
#define _BT_POLYHEDRAL_FEATURES_H
@@ -25,42 +23,37 @@ subject to the following restrictions:
#define TEST_INTERNAL_OBJECTS 1
-
struct btFace
{
- btAlignedObjectArray<int> m_indices;
-// btAlignedObjectArray<int> m_connectedFaces;
- btScalar m_plane[4];
+ btAlignedObjectArray<int> m_indices;
+ // btAlignedObjectArray<int> m_connectedFaces;
+ btScalar m_plane[4];
};
-
-ATTRIBUTE_ALIGNED16(class) btConvexPolyhedron
+ATTRIBUTE_ALIGNED16(class)
+btConvexPolyhedron
{
- public:
-
+public:
BT_DECLARE_ALIGNED_ALLOCATOR();
-
+
btConvexPolyhedron();
- virtual ~btConvexPolyhedron();
+ virtual ~btConvexPolyhedron();
- btAlignedObjectArray<btVector3> m_vertices;
- btAlignedObjectArray<btFace> m_faces;
+ btAlignedObjectArray<btVector3> m_vertices;
+ btAlignedObjectArray<btFace> m_faces;
btAlignedObjectArray<btVector3> m_uniqueEdges;
- btVector3 m_localCenter;
- btVector3 m_extents;
- btScalar m_radius;
- btVector3 mC;
- btVector3 mE;
+ btVector3 m_localCenter;
+ btVector3 m_extents;
+ btScalar m_radius;
+ btVector3 mC;
+ btVector3 mE;
- void initialize();
- void initialize2();
+ void initialize();
+ void initialize2();
bool testContainment() const;
- void project(const btTransform& trans, const btVector3& dir, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin,btVector3& witnesPtMax) const;
+ void project(const btTransform& trans, const btVector3& dir, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin, btVector3& witnesPtMax) const;
};
-
-#endif //_BT_POLYHEDRAL_FEATURES_H
-
-
+#endif //_BT_POLYHEDRAL_FEATURES_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexShape.cpp
index 2f84858598..f8fb0aa9fd 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexShape.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexShape.cpp
@@ -13,7 +13,7 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-#if defined (_WIN32) || defined (__i386__)
+#if defined(_WIN32) || defined(__i386__)
#define BT_USE_SSE_IN_API
#endif
@@ -27,30 +27,28 @@ subject to the following restrictions:
#include "btConvexPointCloudShape.h"
///not supported on IBM SDK, until we fix the alignment of btVector3
-#if defined (__CELLOS_LV2__) && defined (__SPU__)
+#if defined(__CELLOS_LV2__) && defined(__SPU__)
#include <spu_intrinsics.h>
-static inline vec_float4 vec_dot3( vec_float4 vec0, vec_float4 vec1 )
+static inline vec_float4 vec_dot3(vec_float4 vec0, vec_float4 vec1)
{
- vec_float4 result;
- result = spu_mul( vec0, vec1 );
- result = spu_madd( spu_rlqwbyte( vec0, 4 ), spu_rlqwbyte( vec1, 4 ), result );
- return spu_madd( spu_rlqwbyte( vec0, 8 ), spu_rlqwbyte( vec1, 8 ), result );
+ vec_float4 result;
+ result = spu_mul(vec0, vec1);
+ result = spu_madd(spu_rlqwbyte(vec0, 4), spu_rlqwbyte(vec1, 4), result);
+ return spu_madd(spu_rlqwbyte(vec0, 8), spu_rlqwbyte(vec1, 8), result);
}
-#endif //__SPU__
+#endif //__SPU__
-btConvexShape::btConvexShape ()
+btConvexShape::btConvexShape()
{
}
btConvexShape::~btConvexShape()
{
-
}
-
-void btConvexShape::project(const btTransform& trans, const btVector3& dir, btScalar& min, btScalar& max, btVector3& witnesPtMin,btVector3& witnesPtMax) const
+void btConvexShape::project(const btTransform& trans, const btVector3& dir, btScalar& min, btScalar& max, btVector3& witnesPtMin, btVector3& witnesPtMax) const
{
- btVector3 localAxis = dir*trans.getBasis();
+ btVector3 localAxis = dir * trans.getBasis();
btVector3 vtx1 = trans(localGetSupportingVertex(localAxis));
btVector3 vtx2 = trans(localGetSupportingVertex(-localAxis));
@@ -58,8 +56,8 @@ void btConvexShape::project(const btTransform& trans, const btVector3& dir, btSc
max = vtx2.dot(dir);
witnesPtMax = vtx2;
witnesPtMin = vtx1;
-
- if(min>max)
+
+ if (min > max)
{
btScalar tmp = min;
min = max;
@@ -69,391 +67,392 @@ void btConvexShape::project(const btTransform& trans, const btVector3& dir, btSc
}
}
-
-static btVector3 convexHullSupport (const btVector3& localDirOrg, const btVector3* points, int numPoints, const btVector3& localScaling)
-{
-
+static btVector3 convexHullSupport(const btVector3& localDirOrg, const btVector3* points, int numPoints, const btVector3& localScaling)
+{
btVector3 vec = localDirOrg * localScaling;
-#if defined (__CELLOS_LV2__) && defined (__SPU__)
+#if defined(__CELLOS_LV2__) && defined(__SPU__)
btVector3 localDir = vec;
- vec_float4 v_distMax = {-FLT_MAX,0,0,0};
- vec_int4 v_idxMax = {-999,0,0,0};
- int v=0;
+ vec_float4 v_distMax = {-FLT_MAX, 0, 0, 0};
+ vec_int4 v_idxMax = {-999, 0, 0, 0};
+ int v = 0;
int numverts = numPoints;
- for(;v<(int)numverts-4;v+=4) {
- vec_float4 p0 = vec_dot3(points[v ].get128(),localDir.get128());
- vec_float4 p1 = vec_dot3(points[v+1].get128(),localDir.get128());
- vec_float4 p2 = vec_dot3(points[v+2].get128(),localDir.get128());
- vec_float4 p3 = vec_dot3(points[v+3].get128(),localDir.get128());
- const vec_int4 i0 = {v ,0,0,0};
- const vec_int4 i1 = {v+1,0,0,0};
- const vec_int4 i2 = {v+2,0,0,0};
- const vec_int4 i3 = {v+3,0,0,0};
- vec_uint4 retGt01 = spu_cmpgt(p0,p1);
- vec_float4 pmax01 = spu_sel(p1,p0,retGt01);
- vec_int4 imax01 = spu_sel(i1,i0,retGt01);
- vec_uint4 retGt23 = spu_cmpgt(p2,p3);
- vec_float4 pmax23 = spu_sel(p3,p2,retGt23);
- vec_int4 imax23 = spu_sel(i3,i2,retGt23);
- vec_uint4 retGt0123 = spu_cmpgt(pmax01,pmax23);
- vec_float4 pmax0123 = spu_sel(pmax23,pmax01,retGt0123);
- vec_int4 imax0123 = spu_sel(imax23,imax01,retGt0123);
- vec_uint4 retGtMax = spu_cmpgt(v_distMax,pmax0123);
- v_distMax = spu_sel(pmax0123,v_distMax,retGtMax);
- v_idxMax = spu_sel(imax0123,v_idxMax,retGtMax);
+ for (; v < (int)numverts - 4; v += 4)
+ {
+ vec_float4 p0 = vec_dot3(points[v].get128(), localDir.get128());
+ vec_float4 p1 = vec_dot3(points[v + 1].get128(), localDir.get128());
+ vec_float4 p2 = vec_dot3(points[v + 2].get128(), localDir.get128());
+ vec_float4 p3 = vec_dot3(points[v + 3].get128(), localDir.get128());
+ const vec_int4 i0 = {v, 0, 0, 0};
+ const vec_int4 i1 = {v + 1, 0, 0, 0};
+ const vec_int4 i2 = {v + 2, 0, 0, 0};
+ const vec_int4 i3 = {v + 3, 0, 0, 0};
+ vec_uint4 retGt01 = spu_cmpgt(p0, p1);
+ vec_float4 pmax01 = spu_sel(p1, p0, retGt01);
+ vec_int4 imax01 = spu_sel(i1, i0, retGt01);
+ vec_uint4 retGt23 = spu_cmpgt(p2, p3);
+ vec_float4 pmax23 = spu_sel(p3, p2, retGt23);
+ vec_int4 imax23 = spu_sel(i3, i2, retGt23);
+ vec_uint4 retGt0123 = spu_cmpgt(pmax01, pmax23);
+ vec_float4 pmax0123 = spu_sel(pmax23, pmax01, retGt0123);
+ vec_int4 imax0123 = spu_sel(imax23, imax01, retGt0123);
+ vec_uint4 retGtMax = spu_cmpgt(v_distMax, pmax0123);
+ v_distMax = spu_sel(pmax0123, v_distMax, retGtMax);
+ v_idxMax = spu_sel(imax0123, v_idxMax, retGtMax);
}
- for(;v<(int)numverts;v++) {
- vec_float4 p = vec_dot3(points[v].get128(),localDir.get128());
- const vec_int4 i = {v,0,0,0};
- vec_uint4 retGtMax = spu_cmpgt(v_distMax,p);
- v_distMax = spu_sel(p,v_distMax,retGtMax);
- v_idxMax = spu_sel(i,v_idxMax,retGtMax);
+ for (; v < (int)numverts; v++)
+ {
+ vec_float4 p = vec_dot3(points[v].get128(), localDir.get128());
+ const vec_int4 i = {v, 0, 0, 0};
+ vec_uint4 retGtMax = spu_cmpgt(v_distMax, p);
+ v_distMax = spu_sel(p, v_distMax, retGtMax);
+ v_idxMax = spu_sel(i, v_idxMax, retGtMax);
}
- int ptIndex = spu_extract(v_idxMax,0);
- const btVector3& supVec= points[ptIndex] * localScaling;
+ int ptIndex = spu_extract(v_idxMax, 0);
+ const btVector3& supVec = points[ptIndex] * localScaling;
return supVec;
#else
btScalar maxDot;
- long ptIndex = vec.maxDot( points, numPoints, maxDot);
+ long ptIndex = vec.maxDot(points, numPoints, maxDot);
btAssert(ptIndex >= 0);
- if (ptIndex<0)
+ if (ptIndex < 0)
{
ptIndex = 0;
}
btVector3 supVec = points[ptIndex] * localScaling;
return supVec;
-#endif //__SPU__
+#endif //__SPU__
}
-btVector3 btConvexShape::localGetSupportVertexWithoutMarginNonVirtual (const btVector3& localDir) const
+btVector3 btConvexShape::localGetSupportVertexWithoutMarginNonVirtual(const btVector3& localDir) const
{
switch (m_shapeType)
{
- case SPHERE_SHAPE_PROXYTYPE:
- {
- return btVector3(0,0,0);
- }
- case BOX_SHAPE_PROXYTYPE:
- {
- btBoxShape* convexShape = (btBoxShape*)this;
- const btVector3& halfExtents = convexShape->getImplicitShapeDimensions();
-
-#if defined( __APPLE__ ) && (defined( BT_USE_SSE )||defined( BT_USE_NEON ))
- #if defined( BT_USE_SSE )
- return btVector3( _mm_xor_ps( _mm_and_ps( localDir.mVec128, (__m128){-0.0f, -0.0f, -0.0f, -0.0f }), halfExtents.mVec128 ));
- #elif defined( BT_USE_NEON )
- return btVector3( (float32x4_t) (((uint32x4_t) localDir.mVec128 & (uint32x4_t){ 0x80000000, 0x80000000, 0x80000000, 0x80000000}) ^ (uint32x4_t) halfExtents.mVec128 ));
- #else
- #error unknown vector arch
- #endif
-#else
- return btVector3(btFsels(localDir.x(), halfExtents.x(), -halfExtents.x()),
- btFsels(localDir.y(), halfExtents.y(), -halfExtents.y()),
- btFsels(localDir.z(), halfExtents.z(), -halfExtents.z()));
-#endif
- }
- case TRIANGLE_SHAPE_PROXYTYPE:
- {
- btTriangleShape* triangleShape = (btTriangleShape*)this;
- btVector3 dir(localDir.getX(),localDir.getY(),localDir.getZ());
- btVector3* vertices = &triangleShape->m_vertices1[0];
- btVector3 dots = dir.dot3(vertices[0], vertices[1], vertices[2]);
- btVector3 sup = vertices[dots.maxAxis()];
- return btVector3(sup.getX(),sup.getY(),sup.getZ());
- }
- case CYLINDER_SHAPE_PROXYTYPE:
- {
- btCylinderShape* cylShape = (btCylinderShape*)this;
- //mapping of halfextents/dimension onto radius/height depends on how cylinder local orientation is (upAxis)
-
- btVector3 halfExtents = cylShape->getImplicitShapeDimensions();
- btVector3 v(localDir.getX(),localDir.getY(),localDir.getZ());
- int cylinderUpAxis = cylShape->getUpAxis();
- int XX(1),YY(0),ZZ(2);
-
- switch (cylinderUpAxis)
- {
- case 0:
+ case SPHERE_SHAPE_PROXYTYPE:
{
- XX = 1;
- YY = 0;
- ZZ = 2;
+ return btVector3(0, 0, 0);
}
- break;
- case 1:
+ case BOX_SHAPE_PROXYTYPE:
{
- XX = 0;
- YY = 1;
- ZZ = 2;
+ btBoxShape* convexShape = (btBoxShape*)this;
+ const btVector3& halfExtents = convexShape->getImplicitShapeDimensions();
+
+#if defined(__APPLE__) && (defined(BT_USE_SSE) || defined(BT_USE_NEON))
+#if defined(BT_USE_SSE)
+ return btVector3(_mm_xor_ps(_mm_and_ps(localDir.mVec128, (__m128){-0.0f, -0.0f, -0.0f, -0.0f}), halfExtents.mVec128));
+#elif defined(BT_USE_NEON)
+ return btVector3((float32x4_t)(((uint32x4_t)localDir.mVec128 & (uint32x4_t){0x80000000, 0x80000000, 0x80000000, 0x80000000}) ^ (uint32x4_t)halfExtents.mVec128));
+#else
+#error unknown vector arch
+#endif
+#else
+ return btVector3(btFsels(localDir.x(), halfExtents.x(), -halfExtents.x()),
+ btFsels(localDir.y(), halfExtents.y(), -halfExtents.y()),
+ btFsels(localDir.z(), halfExtents.z(), -halfExtents.z()));
+#endif
}
- break;
- case 2:
+ case TRIANGLE_SHAPE_PROXYTYPE:
{
- XX = 0;
- YY = 2;
- ZZ = 1;
-
+ btTriangleShape* triangleShape = (btTriangleShape*)this;
+ btVector3 dir(localDir.getX(), localDir.getY(), localDir.getZ());
+ btVector3* vertices = &triangleShape->m_vertices1[0];
+ btVector3 dots = dir.dot3(vertices[0], vertices[1], vertices[2]);
+ btVector3 sup = vertices[dots.maxAxis()];
+ return btVector3(sup.getX(), sup.getY(), sup.getZ());
}
- break;
- default:
- btAssert(0);
- break;
- };
-
- btScalar radius = halfExtents[XX];
- btScalar halfHeight = halfExtents[cylinderUpAxis];
+ case CYLINDER_SHAPE_PROXYTYPE:
+ {
+ btCylinderShape* cylShape = (btCylinderShape*)this;
+ //mapping of halfextents/dimension onto radius/height depends on how cylinder local orientation is (upAxis)
- btVector3 tmp;
- btScalar d ;
+ btVector3 halfExtents = cylShape->getImplicitShapeDimensions();
+ btVector3 v(localDir.getX(), localDir.getY(), localDir.getZ());
+ int cylinderUpAxis = cylShape->getUpAxis();
+ int XX(1), YY(0), ZZ(2);
- btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]);
- if (s != btScalar(0.0))
- {
- d = radius / s;
- tmp[XX] = v[XX] * d;
- tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
- tmp[ZZ] = v[ZZ] * d;
- return btVector3(tmp.getX(),tmp.getY(),tmp.getZ());
- } else {
- tmp[XX] = radius;
- tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
- tmp[ZZ] = btScalar(0.0);
- return btVector3(tmp.getX(),tmp.getY(),tmp.getZ());
+ switch (cylinderUpAxis)
+ {
+ case 0:
+ {
+ XX = 1;
+ YY = 0;
+ ZZ = 2;
+ }
+ break;
+ case 1:
+ {
+ XX = 0;
+ YY = 1;
+ ZZ = 2;
+ }
+ break;
+ case 2:
+ {
+ XX = 0;
+ YY = 2;
+ ZZ = 1;
+ }
+ break;
+ default:
+ btAssert(0);
+ break;
+ };
+
+ btScalar radius = halfExtents[XX];
+ btScalar halfHeight = halfExtents[cylinderUpAxis];
+
+ btVector3 tmp;
+ btScalar d;
+
+ btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]);
+ if (s != btScalar(0.0))
+ {
+ d = radius / s;
+ tmp[XX] = v[XX] * d;
+ tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
+ tmp[ZZ] = v[ZZ] * d;
+ return btVector3(tmp.getX(), tmp.getY(), tmp.getZ());
+ }
+ else
+ {
+ tmp[XX] = radius;
+ tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
+ tmp[ZZ] = btScalar(0.0);
+ return btVector3(tmp.getX(), tmp.getY(), tmp.getZ());
+ }
}
- }
- case CAPSULE_SHAPE_PROXYTYPE:
- {
- btVector3 vec0(localDir.getX(),localDir.getY(),localDir.getZ());
+ case CAPSULE_SHAPE_PROXYTYPE:
+ {
+ btVector3 vec0(localDir.getX(), localDir.getY(), localDir.getZ());
- btCapsuleShape* capsuleShape = (btCapsuleShape*)this;
- btScalar halfHeight = capsuleShape->getHalfHeight();
- int capsuleUpAxis = capsuleShape->getUpAxis();
+ btCapsuleShape* capsuleShape = (btCapsuleShape*)this;
+ btScalar halfHeight = capsuleShape->getHalfHeight();
+ int capsuleUpAxis = capsuleShape->getUpAxis();
- btVector3 supVec(0,0,0);
+ btVector3 supVec(0, 0, 0);
- btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
+ btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
- btVector3 vec = vec0;
- btScalar lenSqr = vec.length2();
- if (lenSqr < SIMD_EPSILON*SIMD_EPSILON)
- {
- vec.setValue(1,0,0);
- } else
- {
- btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
- vec *= rlen;
- }
- btVector3 vtx;
- btScalar newDot;
- {
- btVector3 pos(0,0,0);
- pos[capsuleUpAxis] = halfHeight;
+ btVector3 vec = vec0;
+ btScalar lenSqr = vec.length2();
+ if (lenSqr < SIMD_EPSILON * SIMD_EPSILON)
+ {
+ vec.setValue(1, 0, 0);
+ }
+ else
+ {
+ btScalar rlen = btScalar(1.) / btSqrt(lenSqr);
+ vec *= rlen;
+ }
+ btVector3 vtx;
+ btScalar newDot;
+ {
+ btVector3 pos(0, 0, 0);
+ pos[capsuleUpAxis] = halfHeight;
- vtx = pos;
- newDot = vec.dot(vtx);
-
+ vtx = pos;
+ newDot = vec.dot(vtx);
- if (newDot > maxDot)
+ if (newDot > maxDot)
+ {
+ maxDot = newDot;
+ supVec = vtx;
+ }
+ }
{
- maxDot = newDot;
- supVec = vtx;
+ btVector3 pos(0, 0, 0);
+ pos[capsuleUpAxis] = -halfHeight;
+
+ vtx = pos;
+ newDot = vec.dot(vtx);
+ if (newDot > maxDot)
+ {
+ maxDot = newDot;
+ supVec = vtx;
+ }
}
+ return btVector3(supVec.getX(), supVec.getY(), supVec.getZ());
}
+ case CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE:
{
- btVector3 pos(0,0,0);
- pos[capsuleUpAxis] = -halfHeight;
-
- vtx = pos;
- newDot = vec.dot(vtx);
- if (newDot > maxDot)
- {
- maxDot = newDot;
- supVec = vtx;
- }
+ btConvexPointCloudShape* convexPointCloudShape = (btConvexPointCloudShape*)this;
+ btVector3* points = convexPointCloudShape->getUnscaledPoints();
+ int numPoints = convexPointCloudShape->getNumPoints();
+ return convexHullSupport(localDir, points, numPoints, convexPointCloudShape->getLocalScalingNV());
}
- return btVector3(supVec.getX(),supVec.getY(),supVec.getZ());
- }
- case CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE:
- {
- btConvexPointCloudShape* convexPointCloudShape = (btConvexPointCloudShape*)this;
- btVector3* points = convexPointCloudShape->getUnscaledPoints ();
- int numPoints = convexPointCloudShape->getNumPoints ();
- return convexHullSupport (localDir, points, numPoints,convexPointCloudShape->getLocalScalingNV());
- }
- case CONVEX_HULL_SHAPE_PROXYTYPE:
- {
- btConvexHullShape* convexHullShape = (btConvexHullShape*)this;
- btVector3* points = convexHullShape->getUnscaledPoints();
- int numPoints = convexHullShape->getNumPoints ();
- return convexHullSupport (localDir, points, numPoints,convexHullShape->getLocalScalingNV());
- }
- default:
+ case CONVEX_HULL_SHAPE_PROXYTYPE:
+ {
+ btConvexHullShape* convexHullShape = (btConvexHullShape*)this;
+ btVector3* points = convexHullShape->getUnscaledPoints();
+ int numPoints = convexHullShape->getNumPoints();
+ return convexHullSupport(localDir, points, numPoints, convexHullShape->getLocalScalingNV());
+ }
+ default:
#ifndef __SPU__
- return this->localGetSupportingVertexWithoutMargin (localDir);
+ return this->localGetSupportingVertexWithoutMargin(localDir);
#else
- btAssert (0);
+ btAssert(0);
#endif
}
// should never reach here
- btAssert (0);
- return btVector3 (btScalar(0.0f), btScalar(0.0f), btScalar(0.0f));
+ btAssert(0);
+ return btVector3(btScalar(0.0f), btScalar(0.0f), btScalar(0.0f));
}
-btVector3 btConvexShape::localGetSupportVertexNonVirtual (const btVector3& localDir) const
+btVector3 btConvexShape::localGetSupportVertexNonVirtual(const btVector3& localDir) const
{
btVector3 localDirNorm = localDir;
- if (localDirNorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
+ if (localDirNorm.length2() < (SIMD_EPSILON * SIMD_EPSILON))
{
- localDirNorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
+ localDirNorm.setValue(btScalar(-1.), btScalar(-1.), btScalar(-1.));
}
- localDirNorm.normalize ();
+ localDirNorm.normalize();
- return localGetSupportVertexWithoutMarginNonVirtual(localDirNorm)+ getMarginNonVirtual() * localDirNorm;
+ return localGetSupportVertexWithoutMarginNonVirtual(localDirNorm) + getMarginNonVirtual() * localDirNorm;
}
/* TODO: This should be bumped up to btCollisionShape () */
-btScalar btConvexShape::getMarginNonVirtual () const
+btScalar btConvexShape::getMarginNonVirtual() const
{
switch (m_shapeType)
{
- case SPHERE_SHAPE_PROXYTYPE:
- {
- btSphereShape* sphereShape = (btSphereShape*)this;
- return sphereShape->getRadius ();
- }
- case BOX_SHAPE_PROXYTYPE:
- {
- btBoxShape* convexShape = (btBoxShape*)this;
- return convexShape->getMarginNV ();
- }
- case TRIANGLE_SHAPE_PROXYTYPE:
- {
- btTriangleShape* triangleShape = (btTriangleShape*)this;
- return triangleShape->getMarginNV ();
- }
- case CYLINDER_SHAPE_PROXYTYPE:
- {
- btCylinderShape* cylShape = (btCylinderShape*)this;
- return cylShape->getMarginNV();
- }
- case CONE_SHAPE_PROXYTYPE:
- {
- btConeShape* conShape = (btConeShape*)this;
- return conShape->getMarginNV();
- }
- case CAPSULE_SHAPE_PROXYTYPE:
- {
- btCapsuleShape* capsuleShape = (btCapsuleShape*)this;
- return capsuleShape->getMarginNV();
- }
- case CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE:
- /* fall through */
- case CONVEX_HULL_SHAPE_PROXYTYPE:
- {
- btPolyhedralConvexShape* convexHullShape = (btPolyhedralConvexShape*)this;
- return convexHullShape->getMarginNV();
- }
- default:
+ case SPHERE_SHAPE_PROXYTYPE:
+ {
+ btSphereShape* sphereShape = (btSphereShape*)this;
+ return sphereShape->getRadius();
+ }
+ case BOX_SHAPE_PROXYTYPE:
+ {
+ btBoxShape* convexShape = (btBoxShape*)this;
+ return convexShape->getMarginNV();
+ }
+ case TRIANGLE_SHAPE_PROXYTYPE:
+ {
+ btTriangleShape* triangleShape = (btTriangleShape*)this;
+ return triangleShape->getMarginNV();
+ }
+ case CYLINDER_SHAPE_PROXYTYPE:
+ {
+ btCylinderShape* cylShape = (btCylinderShape*)this;
+ return cylShape->getMarginNV();
+ }
+ case CONE_SHAPE_PROXYTYPE:
+ {
+ btConeShape* conShape = (btConeShape*)this;
+ return conShape->getMarginNV();
+ }
+ case CAPSULE_SHAPE_PROXYTYPE:
+ {
+ btCapsuleShape* capsuleShape = (btCapsuleShape*)this;
+ return capsuleShape->getMarginNV();
+ }
+ case CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE:
+ /* fall through */
+ case CONVEX_HULL_SHAPE_PROXYTYPE:
+ {
+ btPolyhedralConvexShape* convexHullShape = (btPolyhedralConvexShape*)this;
+ return convexHullShape->getMarginNV();
+ }
+ default:
#ifndef __SPU__
- return this->getMargin ();
+ return this->getMargin();
#else
- btAssert (0);
+ btAssert(0);
#endif
}
// should never reach here
- btAssert (0);
+ btAssert(0);
return btScalar(0.0f);
}
#ifndef __SPU__
-void btConvexShape::getAabbNonVirtual (const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
+void btConvexShape::getAabbNonVirtual(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
{
switch (m_shapeType)
{
- case SPHERE_SHAPE_PROXYTYPE:
- {
- btSphereShape* sphereShape = (btSphereShape*)this;
- btScalar radius = sphereShape->getImplicitShapeDimensions().getX();// * convexShape->getLocalScaling().getX();
- btScalar margin = radius + sphereShape->getMarginNonVirtual();
- const btVector3& center = t.getOrigin();
- btVector3 extent(margin,margin,margin);
- aabbMin = center - extent;
- aabbMax = center + extent;
- }
- break;
- case CYLINDER_SHAPE_PROXYTYPE:
- /* fall through */
- case BOX_SHAPE_PROXYTYPE:
- {
- btBoxShape* convexShape = (btBoxShape*)this;
- btScalar margin=convexShape->getMarginNonVirtual();
- btVector3 halfExtents = convexShape->getImplicitShapeDimensions();
- halfExtents += btVector3(margin,margin,margin);
- btMatrix3x3 abs_b = t.getBasis().absolute();
- btVector3 center = t.getOrigin();
- btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
-
- aabbMin = center - extent;
- aabbMax = center + extent;
+ case SPHERE_SHAPE_PROXYTYPE:
+ {
+ btSphereShape* sphereShape = (btSphereShape*)this;
+ btScalar radius = sphereShape->getImplicitShapeDimensions().getX(); // * convexShape->getLocalScaling().getX();
+ btScalar margin = radius + sphereShape->getMarginNonVirtual();
+ const btVector3& center = t.getOrigin();
+ btVector3 extent(margin, margin, margin);
+ aabbMin = center - extent;
+ aabbMax = center + extent;
+ }
break;
- }
- case TRIANGLE_SHAPE_PROXYTYPE:
- {
- btTriangleShape* triangleShape = (btTriangleShape*)this;
- btScalar margin = triangleShape->getMarginNonVirtual();
- for (int i=0;i<3;i++)
+ case CYLINDER_SHAPE_PROXYTYPE:
+ /* fall through */
+ case BOX_SHAPE_PROXYTYPE:
+ {
+ btBoxShape* convexShape = (btBoxShape*)this;
+ btScalar margin = convexShape->getMarginNonVirtual();
+ btVector3 halfExtents = convexShape->getImplicitShapeDimensions();
+ halfExtents += btVector3(margin, margin, margin);
+ btMatrix3x3 abs_b = t.getBasis().absolute();
+ btVector3 center = t.getOrigin();
+ btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
+
+ aabbMin = center - extent;
+ aabbMax = center + extent;
+ break;
+ }
+ case TRIANGLE_SHAPE_PROXYTYPE:
{
- btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.));
- vec[i] = btScalar(1.);
+ btTriangleShape* triangleShape = (btTriangleShape*)this;
+ btScalar margin = triangleShape->getMarginNonVirtual();
+ for (int i = 0; i < 3; i++)
+ {
+ btVector3 vec(btScalar(0.), btScalar(0.), btScalar(0.));
+ vec[i] = btScalar(1.);
- btVector3 sv = localGetSupportVertexWithoutMarginNonVirtual(vec*t.getBasis());
+ btVector3 sv = localGetSupportVertexWithoutMarginNonVirtual(vec * t.getBasis());
- btVector3 tmp = t(sv);
- aabbMax[i] = tmp[i]+margin;
- vec[i] = btScalar(-1.);
- tmp = t(localGetSupportVertexWithoutMarginNonVirtual(vec*t.getBasis()));
- aabbMin[i] = tmp[i]-margin;
- }
- }
- break;
- case CAPSULE_SHAPE_PROXYTYPE:
- {
- btCapsuleShape* capsuleShape = (btCapsuleShape*)this;
- btVector3 halfExtents(capsuleShape->getRadius(),capsuleShape->getRadius(),capsuleShape->getRadius());
- int m_upAxis = capsuleShape->getUpAxis();
- halfExtents[m_upAxis] = capsuleShape->getRadius() + capsuleShape->getHalfHeight();
- btMatrix3x3 abs_b = t.getBasis().absolute();
- btVector3 center = t.getOrigin();
- btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
- aabbMin = center - extent;
- aabbMax = center + extent;
- }
- break;
- case CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE:
- case CONVEX_HULL_SHAPE_PROXYTYPE:
- {
- btPolyhedralConvexAabbCachingShape* convexHullShape = (btPolyhedralConvexAabbCachingShape*)this;
- btScalar margin = convexHullShape->getMarginNonVirtual();
- convexHullShape->getNonvirtualAabb (t, aabbMin, aabbMax, margin);
- }
- break;
- default:
+ btVector3 tmp = t(sv);
+ aabbMax[i] = tmp[i] + margin;
+ vec[i] = btScalar(-1.);
+ tmp = t(localGetSupportVertexWithoutMarginNonVirtual(vec * t.getBasis()));
+ aabbMin[i] = tmp[i] - margin;
+ }
+ }
+ break;
+ case CAPSULE_SHAPE_PROXYTYPE:
+ {
+ btCapsuleShape* capsuleShape = (btCapsuleShape*)this;
+ btVector3 halfExtents(capsuleShape->getRadius(), capsuleShape->getRadius(), capsuleShape->getRadius());
+ int m_upAxis = capsuleShape->getUpAxis();
+ halfExtents[m_upAxis] = capsuleShape->getRadius() + capsuleShape->getHalfHeight();
+ btMatrix3x3 abs_b = t.getBasis().absolute();
+ btVector3 center = t.getOrigin();
+ btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
+ aabbMin = center - extent;
+ aabbMax = center + extent;
+ }
+ break;
+ case CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE:
+ case CONVEX_HULL_SHAPE_PROXYTYPE:
+ {
+ btPolyhedralConvexAabbCachingShape* convexHullShape = (btPolyhedralConvexAabbCachingShape*)this;
+ btScalar margin = convexHullShape->getMarginNonVirtual();
+ convexHullShape->getNonvirtualAabb(t, aabbMin, aabbMax, margin);
+ }
+ break;
+ default:
#ifndef __SPU__
- this->getAabb (t, aabbMin, aabbMax);
+ this->getAabb(t, aabbMin, aabbMax);
#else
- btAssert (0);
+ btAssert(0);
#endif
- break;
+ break;
}
// should never reach here
- btAssert (0);
+ btAssert(0);
}
-#endif //__SPU__
+#endif //__SPU__
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexShape.h
index 875f2ac195..d3b3ed816e 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexShape.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexShape.h
@@ -28,58 +28,48 @@ subject to the following restrictions:
/// The btConvexShape is an abstract shape interface, implemented by all convex shapes such as btBoxShape, btConvexHullShape etc.
/// It describes general convex shapes using the localGetSupportingVertex interface, used by collision detectors such as btGjkPairDetector.
-ATTRIBUTE_ALIGNED16(class) btConvexShape : public btCollisionShape
+ATTRIBUTE_ALIGNED16(class)
+btConvexShape : public btCollisionShape
{
-
-
public:
-
BT_DECLARE_ALIGNED_ALLOCATOR();
- btConvexShape ();
+ btConvexShape();
virtual ~btConvexShape();
- virtual btVector3 localGetSupportingVertex(const btVector3& vec)const = 0;
-
- ////////
- #ifndef __SPU__
- virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const=0;
- #endif //#ifndef __SPU__
+ virtual btVector3 localGetSupportingVertex(const btVector3& vec) const = 0;
- btVector3 localGetSupportVertexWithoutMarginNonVirtual (const btVector3& vec) const;
- btVector3 localGetSupportVertexNonVirtual (const btVector3& vec) const;
- btScalar getMarginNonVirtual () const;
- void getAabbNonVirtual (const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
+////////
+#ifndef __SPU__
+ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const = 0;
+#endif //#ifndef __SPU__
+ btVector3 localGetSupportVertexWithoutMarginNonVirtual(const btVector3& vec) const;
+ btVector3 localGetSupportVertexNonVirtual(const btVector3& vec) const;
+ btScalar getMarginNonVirtual() const;
+ void getAabbNonVirtual(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
- virtual void project(const btTransform& trans, const btVector3& dir, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin,btVector3& witnesPtMax) const;
+ virtual void project(const btTransform& trans, const btVector3& dir, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin, btVector3& witnesPtMax) const;
-
//notice that the vectors should be unit length
- virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const= 0;
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const = 0;
///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
- void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0;
+ void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const = 0;
- virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0;
+ virtual void getAabbSlow(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const = 0;
- virtual void setLocalScaling(const btVector3& scaling) =0;
- virtual const btVector3& getLocalScaling() const =0;
+ virtual void setLocalScaling(const btVector3& scaling) = 0;
+ virtual const btVector3& getLocalScaling() const = 0;
- virtual void setMargin(btScalar margin)=0;
+ virtual void setMargin(btScalar margin) = 0;
- virtual btScalar getMargin() const=0;
+ virtual btScalar getMargin() const = 0;
- virtual int getNumPreferredPenetrationDirections() const=0;
-
- virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const=0;
+ virtual int getNumPreferredPenetrationDirections() const = 0;
-
-
-
+ virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const = 0;
};
-
-
-#endif //BT_CONVEX_SHAPE_INTERFACE1
+#endif //BT_CONVEX_SHAPE_INTERFACE1
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp
index 0f9ced554b..f6987cc760 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp
@@ -19,42 +19,37 @@ subject to the following restrictions:
#include "LinearMath/btQuaternion.h"
#include "BulletCollision/CollisionShapes/btStridingMeshInterface.h"
-
-btConvexTriangleMeshShape ::btConvexTriangleMeshShape (btStridingMeshInterface* meshInterface, bool calcAabb)
-: btPolyhedralConvexAabbCachingShape(), m_stridingMesh(meshInterface)
+btConvexTriangleMeshShape ::btConvexTriangleMeshShape(btStridingMeshInterface* meshInterface, bool calcAabb)
+ : btPolyhedralConvexAabbCachingShape(), m_stridingMesh(meshInterface)
{
m_shapeType = CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE;
- if ( calcAabb )
+ if (calcAabb)
recalcLocalAabb();
}
-
-
-
///It's not nice to have all this virtual function overhead, so perhaps we can also gather the points once
///but then we are duplicating
-class LocalSupportVertexCallback: public btInternalTriangleIndexCallback
+class LocalSupportVertexCallback : public btInternalTriangleIndexCallback
{
-
btVector3 m_supportVertexLocal;
-public:
+public:
btScalar m_maxDot;
btVector3 m_supportVecLocal;
LocalSupportVertexCallback(const btVector3& supportVecLocal)
- : m_supportVertexLocal(btScalar(0.),btScalar(0.),btScalar(0.)),
- m_maxDot(btScalar(-BT_LARGE_FLOAT)),
- m_supportVecLocal(supportVecLocal)
+ : m_supportVertexLocal(btScalar(0.), btScalar(0.), btScalar(0.)),
+ m_maxDot(btScalar(-BT_LARGE_FLOAT)),
+ m_supportVecLocal(supportVecLocal)
{
}
- virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex)
+ virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
{
(void)triangleIndex;
(void)partId;
- for (int i=0;i<3;i++)
+ for (int i = 0; i < 3; i++)
{
btScalar dot = m_supportVecLocal.dot(triangle[i]);
if (dot > m_maxDot)
@@ -64,99 +59,82 @@ public:
}
}
}
-
- btVector3 GetSupportVertexLocal()
+
+ btVector3 GetSupportVertexLocal()
{
return m_supportVertexLocal;
}
-
};
-
-
-
-
-btVector3 btConvexTriangleMeshShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const
+btVector3 btConvexTriangleMeshShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0) const
{
- btVector3 supVec(btScalar(0.),btScalar(0.),btScalar(0.));
+ btVector3 supVec(btScalar(0.), btScalar(0.), btScalar(0.));
btVector3 vec = vec0;
btScalar lenSqr = vec.length2();
if (lenSqr < btScalar(0.0001))
{
- vec.setValue(1,0,0);
- } else
+ vec.setValue(1, 0, 0);
+ }
+ else
{
- btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
+ btScalar rlen = btScalar(1.) / btSqrt(lenSqr);
vec *= rlen;
}
- LocalSupportVertexCallback supportCallback(vec);
- btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
- m_stridingMesh->InternalProcessAllTriangles(&supportCallback,-aabbMax,aabbMax);
+ LocalSupportVertexCallback supportCallback(vec);
+ btVector3 aabbMax(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
+ m_stridingMesh->InternalProcessAllTriangles(&supportCallback, -aabbMax, aabbMax);
supVec = supportCallback.GetSupportVertexLocal();
return supVec;
}
-void btConvexTriangleMeshShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+void btConvexTriangleMeshShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
{
//use 'w' component of supportVerticesOut?
{
- for (int i=0;i<numVectors;i++)
+ for (int i = 0; i < numVectors; i++)
{
supportVerticesOut[i][3] = btScalar(-BT_LARGE_FLOAT);
}
}
-
- ///@todo: could do the batch inside the callback!
+ ///@todo: could do the batch inside the callback!
- for (int j=0;j<numVectors;j++)
+ for (int j = 0; j < numVectors; j++)
{
const btVector3& vec = vectors[j];
- LocalSupportVertexCallback supportCallback(vec);
- btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
- m_stridingMesh->InternalProcessAllTriangles(&supportCallback,-aabbMax,aabbMax);
+ LocalSupportVertexCallback supportCallback(vec);
+ btVector3 aabbMax(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
+ m_stridingMesh->InternalProcessAllTriangles(&supportCallback, -aabbMax, aabbMax);
supportVerticesOut[j] = supportCallback.GetSupportVertexLocal();
}
-
}
-
-
-btVector3 btConvexTriangleMeshShape::localGetSupportingVertex(const btVector3& vec)const
+btVector3 btConvexTriangleMeshShape::localGetSupportingVertex(const btVector3& vec) const
{
btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec);
- if ( getMargin()!=btScalar(0.) )
+ if (getMargin() != btScalar(0.))
{
btVector3 vecnorm = vec;
- if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
+ if (vecnorm.length2() < (SIMD_EPSILON * SIMD_EPSILON))
{
- vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
- }
+ vecnorm.setValue(btScalar(-1.), btScalar(-1.), btScalar(-1.));
+ }
vecnorm.normalize();
- supVertex+= getMargin() * vecnorm;
+ supVertex += getMargin() * vecnorm;
}
return supVertex;
}
-
-
-
-
-
-
-
-
//currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection
//Please note that you can debug-draw btConvexTriangleMeshShape with the Raytracer Demo
-int btConvexTriangleMeshShape::getNumVertices() const
+int btConvexTriangleMeshShape::getNumVertices() const
{
//cache this?
return 0;
-
}
int btConvexTriangleMeshShape::getNumEdges() const
@@ -164,44 +142,40 @@ int btConvexTriangleMeshShape::getNumEdges() const
return 0;
}
-void btConvexTriangleMeshShape::getEdge(int ,btVector3& ,btVector3& ) const
+void btConvexTriangleMeshShape::getEdge(int, btVector3&, btVector3&) const
{
- btAssert(0);
+ btAssert(0);
}
-void btConvexTriangleMeshShape::getVertex(int ,btVector3& ) const
+void btConvexTriangleMeshShape::getVertex(int, btVector3&) const
{
btAssert(0);
}
-int btConvexTriangleMeshShape::getNumPlanes() const
+int btConvexTriangleMeshShape::getNumPlanes() const
{
return 0;
}
-void btConvexTriangleMeshShape::getPlane(btVector3& ,btVector3& ,int ) const
+void btConvexTriangleMeshShape::getPlane(btVector3&, btVector3&, int) const
{
btAssert(0);
}
//not yet
-bool btConvexTriangleMeshShape::isInside(const btVector3& ,btScalar ) const
+bool btConvexTriangleMeshShape::isInside(const btVector3&, btScalar) const
{
btAssert(0);
return false;
}
-
-
-void btConvexTriangleMeshShape::setLocalScaling(const btVector3& scaling)
+void btConvexTriangleMeshShape::setLocalScaling(const btVector3& scaling)
{
m_stridingMesh->setScaling(scaling);
-
+
recalcLocalAabb();
-
}
-
const btVector3& btConvexTriangleMeshShape::getLocalScaling() const
{
return m_stridingMesh->getScaling();
@@ -209,107 +183,101 @@ const btVector3& btConvexTriangleMeshShape::getLocalScaling() const
void btConvexTriangleMeshShape::calculatePrincipalAxisTransform(btTransform& principal, btVector3& inertia, btScalar& volume) const
{
- class CenterCallback: public btInternalTriangleIndexCallback
- {
- bool first;
- btVector3 ref;
- btVector3 sum;
- btScalar volume;
-
- public:
-
- CenterCallback() : first(true), ref(0, 0, 0), sum(0, 0, 0), volume(0)
- {
- }
-
- virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
- {
- (void) triangleIndex;
- (void) partId;
- if (first)
- {
- ref = triangle[0];
- first = false;
- }
- else
- {
- btScalar vol = btFabs((triangle[0] - ref).triple(triangle[1] - ref, triangle[2] - ref));
- sum += (btScalar(0.25) * vol) * ((triangle[0] + triangle[1] + triangle[2] + ref));
- volume += vol;
- }
- }
-
- btVector3 getCenter()
- {
- return (volume > 0) ? sum / volume : ref;
- }
-
- btScalar getVolume()
- {
- return volume * btScalar(1. / 6);
- }
-
- };
-
- class InertiaCallback: public btInternalTriangleIndexCallback
- {
- btMatrix3x3 sum;
- btVector3 center;
-
- public:
-
- InertiaCallback(btVector3& center) : sum(0, 0, 0, 0, 0, 0, 0, 0, 0), center(center)
- {
- }
-
- virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
- {
- (void) triangleIndex;
- (void) partId;
- btMatrix3x3 i;
- btVector3 a = triangle[0] - center;
- btVector3 b = triangle[1] - center;
- btVector3 c = triangle[2] - center;
- btScalar volNeg = -btFabs(a.triple(b, c)) * btScalar(1. / 6);
- for (int j = 0; j < 3; j++)
- {
- for (int k = 0; k <= j; k++)
- {
- i[j][k] = i[k][j] = volNeg * (btScalar(0.1) * (a[j] * a[k] + b[j] * b[k] + c[j] * c[k])
- + btScalar(0.05) * (a[j] * b[k] + a[k] * b[j] + a[j] * c[k] + a[k] * c[j] + b[j] * c[k] + b[k] * c[j]));
- }
- }
- btScalar i00 = -i[0][0];
- btScalar i11 = -i[1][1];
- btScalar i22 = -i[2][2];
- i[0][0] = i11 + i22;
- i[1][1] = i22 + i00;
- i[2][2] = i00 + i11;
- sum[0] += i[0];
- sum[1] += i[1];
- sum[2] += i[2];
- }
-
- btMatrix3x3& getInertia()
- {
- return sum;
- }
-
- };
-
- CenterCallback centerCallback;
- btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
- m_stridingMesh->InternalProcessAllTriangles(&centerCallback, -aabbMax, aabbMax);
- btVector3 center = centerCallback.getCenter();
- principal.setOrigin(center);
- volume = centerCallback.getVolume();
-
- InertiaCallback inertiaCallback(center);
- m_stridingMesh->InternalProcessAllTriangles(&inertiaCallback, -aabbMax, aabbMax);
-
- btMatrix3x3& i = inertiaCallback.getInertia();
- i.diagonalize(principal.getBasis(), btScalar(0.00001), 20);
- inertia.setValue(i[0][0], i[1][1], i[2][2]);
- inertia /= volume;
-}
+ class CenterCallback : public btInternalTriangleIndexCallback
+ {
+ bool first;
+ btVector3 ref;
+ btVector3 sum;
+ btScalar volume;
+
+ public:
+ CenterCallback() : first(true), ref(0, 0, 0), sum(0, 0, 0), volume(0)
+ {
+ }
+
+ virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
+ {
+ (void)triangleIndex;
+ (void)partId;
+ if (first)
+ {
+ ref = triangle[0];
+ first = false;
+ }
+ else
+ {
+ btScalar vol = btFabs((triangle[0] - ref).triple(triangle[1] - ref, triangle[2] - ref));
+ sum += (btScalar(0.25) * vol) * ((triangle[0] + triangle[1] + triangle[2] + ref));
+ volume += vol;
+ }
+ }
+ btVector3 getCenter()
+ {
+ return (volume > 0) ? sum / volume : ref;
+ }
+
+ btScalar getVolume()
+ {
+ return volume * btScalar(1. / 6);
+ }
+ };
+
+ class InertiaCallback : public btInternalTriangleIndexCallback
+ {
+ btMatrix3x3 sum;
+ btVector3 center;
+
+ public:
+ InertiaCallback(btVector3& center) : sum(0, 0, 0, 0, 0, 0, 0, 0, 0), center(center)
+ {
+ }
+
+ virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
+ {
+ (void)triangleIndex;
+ (void)partId;
+ btMatrix3x3 i;
+ btVector3 a = triangle[0] - center;
+ btVector3 b = triangle[1] - center;
+ btVector3 c = triangle[2] - center;
+ btScalar volNeg = -btFabs(a.triple(b, c)) * btScalar(1. / 6);
+ for (int j = 0; j < 3; j++)
+ {
+ for (int k = 0; k <= j; k++)
+ {
+ i[j][k] = i[k][j] = volNeg * (btScalar(0.1) * (a[j] * a[k] + b[j] * b[k] + c[j] * c[k]) + btScalar(0.05) * (a[j] * b[k] + a[k] * b[j] + a[j] * c[k] + a[k] * c[j] + b[j] * c[k] + b[k] * c[j]));
+ }
+ }
+ btScalar i00 = -i[0][0];
+ btScalar i11 = -i[1][1];
+ btScalar i22 = -i[2][2];
+ i[0][0] = i11 + i22;
+ i[1][1] = i22 + i00;
+ i[2][2] = i00 + i11;
+ sum[0] += i[0];
+ sum[1] += i[1];
+ sum[2] += i[2];
+ }
+
+ btMatrix3x3& getInertia()
+ {
+ return sum;
+ }
+ };
+
+ CenterCallback centerCallback;
+ btVector3 aabbMax(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
+ m_stridingMesh->InternalProcessAllTriangles(&centerCallback, -aabbMax, aabbMax);
+ btVector3 center = centerCallback.getCenter();
+ principal.setOrigin(center);
+ volume = centerCallback.getVolume();
+
+ InertiaCallback inertiaCallback(center);
+ m_stridingMesh->InternalProcessAllTriangles(&inertiaCallback, -aabbMax, aabbMax);
+
+ btMatrix3x3& i = inertiaCallback.getInertia();
+ i.diagonalize(principal.getBasis(), btScalar(0.00001), 20);
+ inertia.setValue(i[0][0], i[1][1], i[2][2]);
+ inertia /= volume;
+}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h
index f338865ca1..6dac9fff04 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h
@@ -15,24 +15,22 @@ subject to the following restrictions:
#ifndef BT_CONVEX_TRIANGLEMESH_SHAPE_H
#define BT_CONVEX_TRIANGLEMESH_SHAPE_H
-
#include "btPolyhedralConvexShape.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
-
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
/// The btConvexTriangleMeshShape is a convex hull of a triangle mesh, but the performance is not as good as btConvexHullShape.
/// A small benefit of this class is that it uses the btStridingMeshInterface, so you can avoid the duplication of the triangle mesh data. Nevertheless, most users should use the much better performing btConvexHullShape instead.
-ATTRIBUTE_ALIGNED16(class) btConvexTriangleMeshShape : public btPolyhedralConvexAabbCachingShape
+ATTRIBUTE_ALIGNED16(class)
+btConvexTriangleMeshShape : public btPolyhedralConvexAabbCachingShape
{
-
- class btStridingMeshInterface* m_stridingMesh;
+ class btStridingMeshInterface* m_stridingMesh;
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btConvexTriangleMeshShape(btStridingMeshInterface* meshInterface, bool calcAabb = true);
- class btStridingMeshInterface* getMeshInterface()
+ btConvexTriangleMeshShape(btStridingMeshInterface * meshInterface, bool calcAabb = true);
+
+ class btStridingMeshInterface* getMeshInterface()
{
return m_stridingMesh;
}
@@ -40,24 +38,23 @@ public:
{
return m_stridingMesh;
}
-
- virtual btVector3 localGetSupportingVertex(const btVector3& vec)const;
- virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
- virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
-
+
+ virtual btVector3 localGetSupportingVertex(const btVector3& vec) const;
+ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const;
+
//debugging
- virtual const char* getName()const {return "ConvexTrimesh";}
-
- virtual int getNumVertices() const;
+ virtual const char* getName() const { return "ConvexTrimesh"; }
+
+ virtual int getNumVertices() const;
virtual int getNumEdges() const;
- virtual void getEdge(int i,btVector3& pa,btVector3& pb) const;
- virtual void getVertex(int i,btVector3& vtx) const;
- virtual int getNumPlanes() const;
- virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const;
- virtual bool isInside(const btVector3& pt,btScalar tolerance) const;
+ virtual void getEdge(int i, btVector3& pa, btVector3& pb) const;
+ virtual void getVertex(int i, btVector3& vtx) const;
+ virtual int getNumPlanes() const;
+ virtual void getPlane(btVector3 & planeNormal, btVector3 & planeSupport, int i) const;
+ virtual bool isInside(const btVector3& pt, btScalar tolerance) const;
-
- virtual void setLocalScaling(const btVector3& scaling);
+ virtual void setLocalScaling(const btVector3& scaling);
virtual const btVector3& getLocalScaling() const;
///computes the exact moment of inertia and the transform from the coordinate system defined by the principal axes of the moment of inertia
@@ -65,13 +62,7 @@ public:
///by the mass. The resulting transform "principal" has to be applied inversely to the mesh in order for the local coordinate system of the
///shape to be centered at the center of mass and to coincide with the principal axes. This also necessitates a correction of the world transform
///of the collision object by the principal transform. This method also computes the volume of the convex mesh.
- void calculatePrincipalAxisTransform(btTransform& principal, btVector3& inertia, btScalar& volume) const;
-
+ void calculatePrincipalAxisTransform(btTransform & principal, btVector3 & inertia, btScalar & volume) const;
};
-
-
-#endif //BT_CONVEX_TRIANGLEMESH_SHAPE_H
-
-
-
+#endif //BT_CONVEX_TRIANGLEMESH_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btCylinderShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btCylinderShape.cpp
index 604b3fc770..66dbb8e53d 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btCylinderShape.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btCylinderShape.cpp
@@ -15,11 +15,11 @@ subject to the following restrictions:
#include "btCylinderShape.h"
-btCylinderShape::btCylinderShape (const btVector3& halfExtents)
-:btConvexInternalShape(),
-m_upAxis(1)
+btCylinderShape::btCylinderShape(const btVector3& halfExtents)
+ : btConvexInternalShape(),
+ m_upAxis(1)
{
- btVector3 margin(getMargin(),getMargin(),getMargin());
+ btVector3 margin(getMargin(), getMargin(), getMargin());
m_implicitShapeDimensions = (halfExtents * m_localScaling) - margin;
setSafeMargin(halfExtents);
@@ -27,30 +27,25 @@ m_upAxis(1)
m_shapeType = CYLINDER_SHAPE_PROXYTYPE;
}
-
-btCylinderShapeX::btCylinderShapeX (const btVector3& halfExtents)
-:btCylinderShape(halfExtents)
+btCylinderShapeX::btCylinderShapeX(const btVector3& halfExtents)
+ : btCylinderShape(halfExtents)
{
m_upAxis = 0;
-
}
-
-btCylinderShapeZ::btCylinderShapeZ (const btVector3& halfExtents)
-:btCylinderShape(halfExtents)
+btCylinderShapeZ::btCylinderShapeZ(const btVector3& halfExtents)
+ : btCylinderShape(halfExtents)
{
m_upAxis = 2;
-
}
-void btCylinderShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+void btCylinderShape::getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
{
- btTransformAabb(getHalfExtentsWithoutMargin(),getMargin(),t,aabbMin,aabbMax);
+ btTransformAabb(getHalfExtentsWithoutMargin(), getMargin(), t, aabbMin, aabbMax);
}
-void btCylinderShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+void btCylinderShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
{
-
//Until Bullet 2.77 a box approximation was used, so uncomment this if you need backwards compatibility
//#define USE_BOX_INERTIA_APPROXIMATION 1
#ifndef USE_BOX_INERTIA_APPROXIMATION
@@ -64,25 +59,25 @@ void btCylinderShape::calculateLocalInertia(btScalar mass,btVector3& inertia) co
*
*/
- btScalar radius2; // square of cylinder radius
- btScalar height2; // square of cylinder height
- btVector3 halfExtents = getHalfExtentsWithMargin(); // get cylinder dimension
+ btScalar radius2; // square of cylinder radius
+ btScalar height2; // square of cylinder height
+ btVector3 halfExtents = getHalfExtentsWithMargin(); // get cylinder dimension
btScalar div12 = mass / 12.f;
btScalar div4 = mass / 4.f;
btScalar div2 = mass / 2.f;
int idxRadius, idxHeight;
- switch (m_upAxis) // get indices of radius and height of cylinder
+ switch (m_upAxis) // get indices of radius and height of cylinder
{
- case 0: // cylinder is aligned along x
+ case 0: // cylinder is aligned along x
idxRadius = 1;
idxHeight = 0;
break;
- case 2: // cylinder is aligned along z
+ case 2: // cylinder is aligned along z
idxRadius = 0;
idxHeight = 2;
break;
- default: // cylinder is aligned along y
+ default: // cylinder is aligned along y
idxRadius = 0;
idxHeight = 1;
}
@@ -95,188 +90,164 @@ void btCylinderShape::calculateLocalInertia(btScalar mass,btVector3& inertia) co
btScalar t1 = div12 * height2 + div4 * radius2;
btScalar t2 = div2 * radius2;
- switch (m_upAxis) // set diagonal elements of inertia tensor
+ switch (m_upAxis) // set diagonal elements of inertia tensor
{
- case 0: // cylinder is aligned along x
- inertia.setValue(t2,t1,t1);
+ case 0: // cylinder is aligned along x
+ inertia.setValue(t2, t1, t1);
break;
- case 2: // cylinder is aligned along z
- inertia.setValue(t1,t1,t2);
+ case 2: // cylinder is aligned along z
+ inertia.setValue(t1, t1, t2);
break;
- default: // cylinder is aligned along y
- inertia.setValue(t1,t2,t1);
+ default: // cylinder is aligned along y
+ inertia.setValue(t1, t2, t1);
}
-#else //USE_BOX_INERTIA_APPROXIMATION
+#else //USE_BOX_INERTIA_APPROXIMATION
//approximation of box shape
btVector3 halfExtents = getHalfExtentsWithMargin();
- btScalar lx=btScalar(2.)*(halfExtents.x());
- btScalar ly=btScalar(2.)*(halfExtents.y());
- btScalar lz=btScalar(2.)*(halfExtents.z());
+ btScalar lx = btScalar(2.) * (halfExtents.x());
+ btScalar ly = btScalar(2.) * (halfExtents.y());
+ btScalar lz = btScalar(2.) * (halfExtents.z());
- inertia.setValue(mass/(btScalar(12.0)) * (ly*ly + lz*lz),
- mass/(btScalar(12.0)) * (lx*lx + lz*lz),
- mass/(btScalar(12.0)) * (lx*lx + ly*ly));
-#endif //USE_BOX_INERTIA_APPROXIMATION
+ inertia.setValue(mass / (btScalar(12.0)) * (ly * ly + lz * lz),
+ mass / (btScalar(12.0)) * (lx * lx + lz * lz),
+ mass / (btScalar(12.0)) * (lx * lx + ly * ly));
+#endif //USE_BOX_INERTIA_APPROXIMATION
}
-
-SIMD_FORCE_INLINE btVector3 CylinderLocalSupportX(const btVector3& halfExtents,const btVector3& v)
+SIMD_FORCE_INLINE btVector3 CylinderLocalSupportX(const btVector3& halfExtents, const btVector3& v)
{
-const int cylinderUpAxis = 0;
-const int XX = 1;
-const int YY = 0;
-const int ZZ = 2;
+ const int cylinderUpAxis = 0;
+ const int XX = 1;
+ const int YY = 0;
+ const int ZZ = 2;
//mapping depends on how cylinder local orientation is
// extents of the cylinder is: X,Y is for radius, and Z for height
-
btScalar radius = halfExtents[XX];
btScalar halfHeight = halfExtents[cylinderUpAxis];
+ btVector3 tmp;
+ btScalar d;
- btVector3 tmp;
- btScalar d ;
-
- btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]);
- if (s != btScalar(0.0))
+ btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]);
+ if (s != btScalar(0.0))
{
- d = radius / s;
+ d = radius / s;
tmp[XX] = v[XX] * d;
tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
tmp[ZZ] = v[ZZ] * d;
return tmp;
}
- else
+ else
{
- tmp[XX] = radius;
+ tmp[XX] = radius;
tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
tmp[ZZ] = btScalar(0.0);
return tmp;
- }
-
-
+ }
}
-
-
-
-
-
-inline btVector3 CylinderLocalSupportY(const btVector3& halfExtents,const btVector3& v)
+inline btVector3 CylinderLocalSupportY(const btVector3& halfExtents, const btVector3& v)
{
-
-const int cylinderUpAxis = 1;
-const int XX = 0;
-const int YY = 1;
-const int ZZ = 2;
-
+ const int cylinderUpAxis = 1;
+ const int XX = 0;
+ const int YY = 1;
+ const int ZZ = 2;
btScalar radius = halfExtents[XX];
btScalar halfHeight = halfExtents[cylinderUpAxis];
+ btVector3 tmp;
+ btScalar d;
- btVector3 tmp;
- btScalar d ;
-
- btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]);
- if (s != btScalar(0.0))
+ btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]);
+ if (s != btScalar(0.0))
{
- d = radius / s;
+ d = radius / s;
tmp[XX] = v[XX] * d;
tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
tmp[ZZ] = v[ZZ] * d;
return tmp;
}
- else
+ else
{
- tmp[XX] = radius;
+ tmp[XX] = radius;
tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
tmp[ZZ] = btScalar(0.0);
return tmp;
- }
-
+ }
}
-inline btVector3 CylinderLocalSupportZ(const btVector3& halfExtents,const btVector3& v)
+inline btVector3 CylinderLocalSupportZ(const btVector3& halfExtents, const btVector3& v)
{
-const int cylinderUpAxis = 2;
-const int XX = 0;
-const int YY = 2;
-const int ZZ = 1;
+ const int cylinderUpAxis = 2;
+ const int XX = 0;
+ const int YY = 2;
+ const int ZZ = 1;
//mapping depends on how cylinder local orientation is
// extents of the cylinder is: X,Y is for radius, and Z for height
-
btScalar radius = halfExtents[XX];
btScalar halfHeight = halfExtents[cylinderUpAxis];
+ btVector3 tmp;
+ btScalar d;
- btVector3 tmp;
- btScalar d ;
-
- btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]);
- if (s != btScalar(0.0))
+ btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]);
+ if (s != btScalar(0.0))
{
- d = radius / s;
+ d = radius / s;
tmp[XX] = v[XX] * d;
tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
tmp[ZZ] = v[ZZ] * d;
return tmp;
}
- else
+ else
{
- tmp[XX] = radius;
+ tmp[XX] = radius;
tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
tmp[ZZ] = btScalar(0.0);
return tmp;
- }
-
-
+ }
}
-btVector3 btCylinderShapeX::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+btVector3 btCylinderShapeX::localGetSupportingVertexWithoutMargin(const btVector3& vec) const
{
- return CylinderLocalSupportX(getHalfExtentsWithoutMargin(),vec);
+ return CylinderLocalSupportX(getHalfExtentsWithoutMargin(), vec);
}
-
-btVector3 btCylinderShapeZ::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+btVector3 btCylinderShapeZ::localGetSupportingVertexWithoutMargin(const btVector3& vec) const
{
- return CylinderLocalSupportZ(getHalfExtentsWithoutMargin(),vec);
+ return CylinderLocalSupportZ(getHalfExtentsWithoutMargin(), vec);
}
-btVector3 btCylinderShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+btVector3 btCylinderShape::localGetSupportingVertexWithoutMargin(const btVector3& vec) const
{
- return CylinderLocalSupportY(getHalfExtentsWithoutMargin(),vec);
+ return CylinderLocalSupportY(getHalfExtentsWithoutMargin(), vec);
}
-void btCylinderShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+void btCylinderShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
{
- for (int i=0;i<numVectors;i++)
+ for (int i = 0; i < numVectors; i++)
{
- supportVerticesOut[i] = CylinderLocalSupportY(getHalfExtentsWithoutMargin(),vectors[i]);
+ supportVerticesOut[i] = CylinderLocalSupportY(getHalfExtentsWithoutMargin(), vectors[i]);
}
}
-void btCylinderShapeZ::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+void btCylinderShapeZ::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
{
- for (int i=0;i<numVectors;i++)
+ for (int i = 0; i < numVectors; i++)
{
- supportVerticesOut[i] = CylinderLocalSupportZ(getHalfExtentsWithoutMargin(),vectors[i]);
+ supportVerticesOut[i] = CylinderLocalSupportZ(getHalfExtentsWithoutMargin(), vectors[i]);
}
}
-
-
-
-void btCylinderShapeX::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+void btCylinderShapeX::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
{
- for (int i=0;i<numVectors;i++)
+ for (int i = 0; i < numVectors; i++)
{
- supportVerticesOut[i] = CylinderLocalSupportX(getHalfExtentsWithoutMargin(),vectors[i]);
+ supportVerticesOut[i] = CylinderLocalSupportX(getHalfExtentsWithoutMargin(), vectors[i]);
}
}
-
-
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btCylinderShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btCylinderShape.h
index a214a827c9..d3f64508ba 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btCylinderShape.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btCylinderShape.h
@@ -17,90 +17,84 @@ subject to the following restrictions:
#define BT_CYLINDER_MINKOWSKI_H
#include "btBoxShape.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
#include "LinearMath/btVector3.h"
/// The btCylinderShape class implements a cylinder shape primitive, centered around the origin. Its central axis aligned with the Y axis. btCylinderShapeX is aligned with the X axis and btCylinderShapeZ around the Z axis.
-ATTRIBUTE_ALIGNED16(class) btCylinderShape : public btConvexInternalShape
+ATTRIBUTE_ALIGNED16(class)
+btCylinderShape : public btConvexInternalShape
{
-
protected:
-
- int m_upAxis;
+ int m_upAxis;
public:
-
-BT_DECLARE_ALIGNED_ALLOCATOR();
+ BT_DECLARE_ALIGNED_ALLOCATOR();
btVector3 getHalfExtentsWithMargin() const
{
btVector3 halfExtents = getHalfExtentsWithoutMargin();
- btVector3 margin(getMargin(),getMargin(),getMargin());
+ btVector3 margin(getMargin(), getMargin(), getMargin());
halfExtents += margin;
return halfExtents;
}
-
+
const btVector3& getHalfExtentsWithoutMargin() const
{
- return m_implicitShapeDimensions;//changed in Bullet 2.63: assume the scaling and margin are included
+ return m_implicitShapeDimensions; //changed in Bullet 2.63: assume the scaling and margin are included
}
- btCylinderShape (const btVector3& halfExtents);
-
- void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+ btCylinderShape(const btVector3& halfExtents);
+
+ void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
- virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+ virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
- virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
- virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const;
virtual void setMargin(btScalar collisionMargin)
{
//correct the m_implicitShapeDimensions for the margin
- btVector3 oldMargin(getMargin(),getMargin(),getMargin());
- btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
-
+ btVector3 oldMargin(getMargin(), getMargin(), getMargin());
+ btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions + oldMargin;
+
btConvexInternalShape::setMargin(collisionMargin);
- btVector3 newMargin(getMargin(),getMargin(),getMargin());
+ btVector3 newMargin(getMargin(), getMargin(), getMargin());
m_implicitShapeDimensions = implicitShapeDimensionsWithMargin - newMargin;
-
}
- virtual btVector3 localGetSupportingVertex(const btVector3& vec) const
+ virtual btVector3 localGetSupportingVertex(const btVector3& vec) const
{
-
btVector3 supVertex;
supVertex = localGetSupportingVertexWithoutMargin(vec);
-
- if ( getMargin()!=btScalar(0.) )
+
+ if (getMargin() != btScalar(0.))
{
btVector3 vecnorm = vec;
- if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
+ if (vecnorm.length2() < (SIMD_EPSILON * SIMD_EPSILON))
{
- vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
- }
+ vecnorm.setValue(btScalar(-1.), btScalar(-1.), btScalar(-1.));
+ }
vecnorm.normalize();
- supVertex+= getMargin() * vecnorm;
+ supVertex += getMargin() * vecnorm;
}
return supVertex;
}
-
//use box inertia
// virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
-
- int getUpAxis() const
+ int getUpAxis() const
{
return m_upAxis;
}
- virtual btVector3 getAnisotropicRollingFrictionDirection() const
+ virtual btVector3 getAnisotropicRollingFrictionDirection() const
{
- btVector3 aniDir(0,0,0);
- aniDir[getUpAxis()]=1;
+ btVector3 aniDir(0, 0, 0);
+ aniDir[getUpAxis()] = 1;
return aniDir;
}
@@ -109,43 +103,41 @@ BT_DECLARE_ALIGNED_ALLOCATOR();
return getHalfExtentsWithMargin().getX();
}
- virtual void setLocalScaling(const btVector3& scaling)
+ virtual void setLocalScaling(const btVector3& scaling)
{
- btVector3 oldMargin(getMargin(),getMargin(),getMargin());
- btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
+ btVector3 oldMargin(getMargin(), getMargin(), getMargin());
+ btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions + oldMargin;
btVector3 unScaledImplicitShapeDimensionsWithMargin = implicitShapeDimensionsWithMargin / m_localScaling;
btConvexInternalShape::setLocalScaling(scaling);
m_implicitShapeDimensions = (unScaledImplicitShapeDimensionsWithMargin * m_localScaling) - oldMargin;
-
}
//debugging
- virtual const char* getName()const
+ virtual const char* getName() const
{
return "CylinderY";
}
- virtual int calculateSerializeBufferSize() const;
+ virtual int calculateSerializeBufferSize() const;
///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
};
class btCylinderShapeX : public btCylinderShape
{
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btCylinderShapeX (const btVector3& halfExtents);
-
- virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
- virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
-
- //debugging
- virtual const char* getName()const
+
+ btCylinderShapeX(const btVector3& halfExtents);
+
+ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const;
+
+ //debugging
+ virtual const char* getName() const
{
return "CylinderX";
}
@@ -154,21 +146,20 @@ public:
{
return getHalfExtentsWithMargin().getY();
}
-
};
class btCylinderShapeZ : public btCylinderShape
{
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btCylinderShapeZ (const btVector3& halfExtents);
- virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
- virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+ btCylinderShapeZ(const btVector3& halfExtents);
+
+ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const;
- //debugging
- virtual const char* getName()const
+ //debugging
+ virtual const char* getName() const
{
return "CylinderZ";
}
@@ -177,30 +168,29 @@ public:
{
return getHalfExtentsWithMargin().getX();
}
-
};
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btCylinderShapeData
+struct btCylinderShapeData
{
- btConvexInternalShapeData m_convexInternalShapeData;
+ btConvexInternalShapeData m_convexInternalShapeData;
- int m_upAxis;
+ int m_upAxis;
- char m_padding[4];
+ char m_padding[4];
};
-SIMD_FORCE_INLINE int btCylinderShape::calculateSerializeBufferSize() const
+SIMD_FORCE_INLINE int btCylinderShape::calculateSerializeBufferSize() const
{
return sizeof(btCylinderShapeData);
}
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
-SIMD_FORCE_INLINE const char* btCylinderShape::serialize(void* dataBuffer, btSerializer* serializer) const
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE const char* btCylinderShape::serialize(void* dataBuffer, btSerializer* serializer) const
{
- btCylinderShapeData* shapeData = (btCylinderShapeData*) dataBuffer;
+ btCylinderShapeData* shapeData = (btCylinderShapeData*)dataBuffer;
- btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData,serializer);
+ btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData, serializer);
shapeData->m_upAxis = m_upAxis;
@@ -213,7 +203,4 @@ SIMD_FORCE_INLINE const char* btCylinderShape::serialize(void* dataBuffer, btSer
return "btCylinderShapeData";
}
-
-
-#endif //BT_CYLINDER_MINKOWSKI_H
-
+#endif //BT_CYLINDER_MINKOWSKI_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btEmptyShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btEmptyShape.cpp
index a9e6df5c58..4699555bd8 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btEmptyShape.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btEmptyShape.cpp
@@ -15,36 +15,28 @@ subject to the following restrictions:
#include "btEmptyShape.h"
-
#include "btCollisionShape.h"
-
-btEmptyShape::btEmptyShape() : btConcaveShape ()
+btEmptyShape::btEmptyShape() : btConcaveShape()
{
m_shapeType = EMPTY_SHAPE_PROXYTYPE;
}
-
btEmptyShape::~btEmptyShape()
{
}
-
- ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
-void btEmptyShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+void btEmptyShape::getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
{
- btVector3 margin(getMargin(),getMargin(),getMargin());
+ btVector3 margin(getMargin(), getMargin(), getMargin());
aabbMin = t.getOrigin() - margin;
aabbMax = t.getOrigin() + margin;
-
}
-void btEmptyShape::calculateLocalInertia(btScalar ,btVector3& ) const
+void btEmptyShape::calculateLocalInertia(btScalar, btVector3&) const
{
btAssert(0);
}
-
-
-
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btEmptyShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btEmptyShape.h
index 069a79402b..d2e21173b2 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btEmptyShape.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btEmptyShape.h
@@ -23,50 +23,43 @@ subject to the following restrictions:
#include "LinearMath/btMatrix3x3.h"
#include "btCollisionMargin.h"
-
-
-
/// The btEmptyShape is a collision shape without actual collision detection shape, so most users should ignore this class.
/// It can be replaced by another shape during runtime, but the inertia tensor should be recomputed.
-ATTRIBUTE_ALIGNED16(class) btEmptyShape : public btConcaveShape
+ATTRIBUTE_ALIGNED16(class)
+btEmptyShape : public btConcaveShape
{
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
-
+
btEmptyShape();
virtual ~btEmptyShape();
-
///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
- void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+ void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
-
- virtual void setLocalScaling(const btVector3& scaling)
+ virtual void setLocalScaling(const btVector3& scaling)
{
m_localScaling = scaling;
}
- virtual const btVector3& getLocalScaling() const
+ virtual const btVector3& getLocalScaling() const
{
return m_localScaling;
}
- virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
-
- virtual const char* getName()const
+ virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
+
+ virtual const char* getName() const
{
return "Empty";
}
- virtual void processAllTriangles(btTriangleCallback* ,const btVector3& ,const btVector3& ) const
+ virtual void processAllTriangles(btTriangleCallback*, const btVector3&, const btVector3&) const
{
}
protected:
- btVector3 m_localScaling;
-
+ btVector3 m_localScaling;
};
-
-
-#endif //BT_EMPTY_SHAPE_H
+#endif //BT_EMPTY_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp
index 441a89c6bb..4adf27e6bb 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp
@@ -17,23 +17,17 @@ subject to the following restrictions:
#include "LinearMath/btTransformUtil.h"
-
-
-btHeightfieldTerrainShape::btHeightfieldTerrainShape
-(
-int heightStickWidth, int heightStickLength, const void* heightfieldData,
-btScalar heightScale, btScalar minHeight, btScalar maxHeight,int upAxis,
-PHY_ScalarType hdt, bool flipQuadEdges
-)
+btHeightfieldTerrainShape::btHeightfieldTerrainShape(
+ int heightStickWidth, int heightStickLength, const void* heightfieldData,
+ btScalar heightScale, btScalar minHeight, btScalar maxHeight, int upAxis,
+ PHY_ScalarType hdt, bool flipQuadEdges)
{
initialize(heightStickWidth, heightStickLength, heightfieldData,
- heightScale, minHeight, maxHeight, upAxis, hdt,
- flipQuadEdges);
+ heightScale, minHeight, maxHeight, upAxis, hdt,
+ flipQuadEdges);
}
-
-
-btHeightfieldTerrainShape::btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength,const void* heightfieldData,btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges)
+btHeightfieldTerrainShape::btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength, const void* heightfieldData, btScalar maxHeight, int upAxis, bool useFloatData, bool flipQuadEdges)
{
// legacy constructor: support only float or unsigned char,
// and min height is zero
@@ -45,27 +39,23 @@ btHeightfieldTerrainShape::btHeightfieldTerrainShape(int heightStickWidth, int h
btScalar heightScale = maxHeight / 65535;
initialize(heightStickWidth, heightStickLength, heightfieldData,
- heightScale, minHeight, maxHeight, upAxis, hdt,
- flipQuadEdges);
+ heightScale, minHeight, maxHeight, upAxis, hdt,
+ flipQuadEdges);
}
-
-
-void btHeightfieldTerrainShape::initialize
-(
-int heightStickWidth, int heightStickLength, const void* heightfieldData,
-btScalar heightScale, btScalar minHeight, btScalar maxHeight, int upAxis,
-PHY_ScalarType hdt, bool flipQuadEdges
-)
+void btHeightfieldTerrainShape::initialize(
+ int heightStickWidth, int heightStickLength, const void* heightfieldData,
+ btScalar heightScale, btScalar minHeight, btScalar maxHeight, int upAxis,
+ PHY_ScalarType hdt, bool flipQuadEdges)
{
// validation
- btAssert(heightStickWidth > 1);// && "bad width");
- btAssert(heightStickLength > 1);// && "bad length");
- btAssert(heightfieldData);// && "null heightfield data");
+ btAssert(heightStickWidth > 1); // && "bad width");
+ btAssert(heightStickLength > 1); // && "bad length");
+ btAssert(heightfieldData); // && "null heightfield data");
// btAssert(heightScale) -- do we care? Trust caller here
- btAssert(minHeight <= maxHeight);// && "bad min/max height");
- btAssert(upAxis >= 0 && upAxis < 3);// && "bad upAxis--should be in range [0,2]");
- btAssert(hdt != PHY_UCHAR || hdt != PHY_FLOAT || hdt != PHY_SHORT);// && "Bad height data type enum");
+ btAssert(minHeight <= maxHeight); // && "bad min/max height");
+ btAssert(upAxis >= 0 && upAxis < 3); // && "bad upAxis--should be in range [0,2]");
+ btAssert(hdt != PHY_UCHAR || hdt != PHY_FLOAT || hdt != PHY_SHORT); // && "Bad height data type enum");
// initialize member variables
m_shapeType = TERRAIN_SHAPE_PROXYTYPE;
@@ -73,8 +63,8 @@ PHY_ScalarType hdt, bool flipQuadEdges
m_heightStickLength = heightStickLength;
m_minHeight = minHeight;
m_maxHeight = maxHeight;
- m_width = (btScalar) (heightStickWidth - 1);
- m_length = (btScalar) (heightStickLength - 1);
+ m_width = (btScalar)(heightStickWidth - 1);
+ m_length = (btScalar)(heightStickLength - 1);
m_heightScale = heightScale;
m_heightfieldDataUnknown = heightfieldData;
m_heightDataType = hdt;
@@ -83,32 +73,36 @@ PHY_ScalarType hdt, bool flipQuadEdges
m_useZigzagSubdivision = false;
m_upAxis = upAxis;
m_localScaling.setValue(btScalar(1.), btScalar(1.), btScalar(1.));
+ m_vboundsGrid = NULL;
+ m_vboundsChunkSize = 0;
+ m_vboundsGridWidth = 0;
+ m_vboundsGridLength = 0;
// determine min/max axis-aligned bounding box (aabb) values
switch (m_upAxis)
{
- case 0:
+ case 0:
{
m_localAabbMin.setValue(m_minHeight, 0, 0);
m_localAabbMax.setValue(m_maxHeight, m_width, m_length);
break;
}
- case 1:
+ case 1:
{
m_localAabbMin.setValue(0, m_minHeight, 0);
m_localAabbMax.setValue(m_width, m_maxHeight, m_length);
break;
};
- case 2:
+ case 2:
{
m_localAabbMin.setValue(0, 0, m_minHeight);
m_localAabbMax.setValue(m_width, m_length, m_maxHeight);
break;
}
- default:
+ default:
{
//need to get valid m_upAxis
- btAssert(0);// && "Bad m_upAxis");
+ btAssert(0); // && "Bad m_upAxis");
}
}
@@ -116,62 +110,58 @@ PHY_ScalarType hdt, bool flipQuadEdges
m_localOrigin = btScalar(0.5) * (m_localAabbMin + m_localAabbMax);
}
-
-
btHeightfieldTerrainShape::~btHeightfieldTerrainShape()
{
+ clearAccelerator();
}
-
-
-void btHeightfieldTerrainShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+void btHeightfieldTerrainShape::getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
{
- btVector3 halfExtents = (m_localAabbMax-m_localAabbMin)* m_localScaling * btScalar(0.5);
+ btVector3 halfExtents = (m_localAabbMax - m_localAabbMin) * m_localScaling * btScalar(0.5);
btVector3 localOrigin(0, 0, 0);
localOrigin[m_upAxis] = (m_minHeight + m_maxHeight) * btScalar(0.5);
localOrigin *= m_localScaling;
- btMatrix3x3 abs_b = t.getBasis().absolute();
+ btMatrix3x3 abs_b = t.getBasis().absolute();
btVector3 center = t.getOrigin();
- btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
- extent += btVector3(getMargin(),getMargin(),getMargin());
+ btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
+ extent += btVector3(getMargin(), getMargin(), getMargin());
aabbMin = center - extent;
aabbMax = center + extent;
}
-
/// This returns the "raw" (user's initial) height, not the actual height.
/// The actual height needs to be adjusted to be relative to the center
/// of the heightfield's AABB.
btScalar
-btHeightfieldTerrainShape::getRawHeightFieldValue(int x,int y) const
+btHeightfieldTerrainShape::getRawHeightFieldValue(int x, int y) const
{
btScalar val = 0.f;
switch (m_heightDataType)
{
- case PHY_FLOAT:
+ case PHY_FLOAT:
{
- val = m_heightfieldDataFloat[(y*m_heightStickWidth)+x];
+ val = m_heightfieldDataFloat[(y * m_heightStickWidth) + x];
break;
}
- case PHY_UCHAR:
+ case PHY_UCHAR:
{
- unsigned char heightFieldValue = m_heightfieldDataUnsignedChar[(y*m_heightStickWidth)+x];
+ unsigned char heightFieldValue = m_heightfieldDataUnsignedChar[(y * m_heightStickWidth) + x];
val = heightFieldValue * m_heightScale;
break;
}
- case PHY_SHORT:
+ case PHY_SHORT:
{
short hfValue = m_heightfieldDataShort[(y * m_heightStickWidth) + x];
val = hfValue * m_heightScale;
break;
}
- default:
+ default:
{
btAssert(!"Bad m_heightDataType");
}
@@ -180,74 +170,63 @@ btHeightfieldTerrainShape::getRawHeightFieldValue(int x,int y) const
return val;
}
-
-
-
/// this returns the vertex in bullet-local coordinates
-void btHeightfieldTerrainShape::getVertex(int x,int y,btVector3& vertex) const
+void btHeightfieldTerrainShape::getVertex(int x, int y, btVector3& vertex) const
{
- btAssert(x>=0);
- btAssert(y>=0);
- btAssert(x<m_heightStickWidth);
- btAssert(y<m_heightStickLength);
+ btAssert(x >= 0);
+ btAssert(y >= 0);
+ btAssert(x < m_heightStickWidth);
+ btAssert(y < m_heightStickLength);
- btScalar height = getRawHeightFieldValue(x,y);
+ btScalar height = getRawHeightFieldValue(x, y);
switch (m_upAxis)
{
- case 0:
+ case 0:
{
- vertex.setValue(
- height - m_localOrigin.getX(),
- (-m_width/btScalar(2.0)) + x,
- (-m_length/btScalar(2.0) ) + y
- );
+ vertex.setValue(
+ height - m_localOrigin.getX(),
+ (-m_width / btScalar(2.0)) + x,
+ (-m_length / btScalar(2.0)) + y);
break;
}
- case 1:
+ case 1:
{
vertex.setValue(
- (-m_width/btScalar(2.0)) + x,
- height - m_localOrigin.getY(),
- (-m_length/btScalar(2.0)) + y
- );
+ (-m_width / btScalar(2.0)) + x,
+ height - m_localOrigin.getY(),
+ (-m_length / btScalar(2.0)) + y);
break;
};
- case 2:
+ case 2:
{
vertex.setValue(
- (-m_width/btScalar(2.0)) + x,
- (-m_length/btScalar(2.0)) + y,
- height - m_localOrigin.getZ()
- );
+ (-m_width / btScalar(2.0)) + x,
+ (-m_length / btScalar(2.0)) + y,
+ height - m_localOrigin.getZ());
break;
}
- default:
+ default:
{
//need to get valid m_upAxis
btAssert(0);
}
}
- vertex*=m_localScaling;
+ vertex *= m_localScaling;
}
-
-
static inline int
-getQuantized
-(
-btScalar x
-)
+getQuantized(
+ btScalar x)
{
- if (x < 0.0) {
- return (int) (x - 0.5);
+ if (x < 0.0)
+ {
+ return (int)(x - 0.5);
}
- return (int) (x + 0.5);
+ return (int)(x + 0.5);
}
-
-
/// given input vector, return quantized version
/**
This routine is basically determining the gridpoint indices for a given
@@ -257,7 +236,7 @@ btScalar x
"with clamp" means that we restrict the point to be in the heightfield's
axis-aligned bounding box.
*/
-void btHeightfieldTerrainShape::quantizeWithClamp(int* out, const btVector3& point,int /*isMax*/) const
+void btHeightfieldTerrainShape::quantizeWithClamp(int* out, const btVector3& point, int /*isMax*/) const
{
btVector3 clampedPoint(point);
clampedPoint.setMax(m_localAabbMin);
@@ -266,11 +245,8 @@ void btHeightfieldTerrainShape::quantizeWithClamp(int* out, const btVector3& poi
out[0] = getQuantized(clampedPoint.getX());
out[1] = getQuantized(clampedPoint.getY());
out[2] = getQuantized(clampedPoint.getZ());
-
}
-
-
/// process all triangles within the provided axis-aligned bounding box
/**
basic algorithm:
@@ -278,128 +254,125 @@ void btHeightfieldTerrainShape::quantizeWithClamp(int* out, const btVector3& poi
- convert input aabb to a range of heightfield grid points (quantize)
- iterate over all triangles in that subset of the grid
*/
-void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
+void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
{
// scale down the input aabb's so they are in local (non-scaled) coordinates
- btVector3 localAabbMin = aabbMin*btVector3(1.f/m_localScaling[0],1.f/m_localScaling[1],1.f/m_localScaling[2]);
- btVector3 localAabbMax = aabbMax*btVector3(1.f/m_localScaling[0],1.f/m_localScaling[1],1.f/m_localScaling[2]);
+ btVector3 localAabbMin = aabbMin * btVector3(1.f / m_localScaling[0], 1.f / m_localScaling[1], 1.f / m_localScaling[2]);
+ btVector3 localAabbMax = aabbMax * btVector3(1.f / m_localScaling[0], 1.f / m_localScaling[1], 1.f / m_localScaling[2]);
// account for local origin
localAabbMin += m_localOrigin;
localAabbMax += m_localOrigin;
//quantize the aabbMin and aabbMax, and adjust the start/end ranges
- int quantizedAabbMin[3];
- int quantizedAabbMax[3];
- quantizeWithClamp(quantizedAabbMin, localAabbMin,0);
- quantizeWithClamp(quantizedAabbMax, localAabbMax,1);
-
+ int quantizedAabbMin[3];
+ int quantizedAabbMax[3];
+ quantizeWithClamp(quantizedAabbMin, localAabbMin, 0);
+ quantizeWithClamp(quantizedAabbMax, localAabbMax, 1);
+
// expand the min/max quantized values
// this is to catch the case where the input aabb falls between grid points!
- for (int i = 0; i < 3; ++i) {
+ for (int i = 0; i < 3; ++i)
+ {
quantizedAabbMin[i]--;
quantizedAabbMax[i]++;
- }
+ }
- int startX=0;
- int endX=m_heightStickWidth-1;
- int startJ=0;
- int endJ=m_heightStickLength-1;
+ int startX = 0;
+ int endX = m_heightStickWidth - 1;
+ int startJ = 0;
+ int endJ = m_heightStickLength - 1;
switch (m_upAxis)
{
- case 0:
+ case 0:
{
- if (quantizedAabbMin[1]>startX)
+ if (quantizedAabbMin[1] > startX)
startX = quantizedAabbMin[1];
- if (quantizedAabbMax[1]<endX)
+ if (quantizedAabbMax[1] < endX)
endX = quantizedAabbMax[1];
- if (quantizedAabbMin[2]>startJ)
+ if (quantizedAabbMin[2] > startJ)
startJ = quantizedAabbMin[2];
- if (quantizedAabbMax[2]<endJ)
+ if (quantizedAabbMax[2] < endJ)
endJ = quantizedAabbMax[2];
break;
}
- case 1:
+ case 1:
{
- if (quantizedAabbMin[0]>startX)
+ if (quantizedAabbMin[0] > startX)
startX = quantizedAabbMin[0];
- if (quantizedAabbMax[0]<endX)
+ if (quantizedAabbMax[0] < endX)
endX = quantizedAabbMax[0];
- if (quantizedAabbMin[2]>startJ)
+ if (quantizedAabbMin[2] > startJ)
startJ = quantizedAabbMin[2];
- if (quantizedAabbMax[2]<endJ)
+ if (quantizedAabbMax[2] < endJ)
endJ = quantizedAabbMax[2];
break;
};
- case 2:
+ case 2:
{
- if (quantizedAabbMin[0]>startX)
+ if (quantizedAabbMin[0] > startX)
startX = quantizedAabbMin[0];
- if (quantizedAabbMax[0]<endX)
+ if (quantizedAabbMax[0] < endX)
endX = quantizedAabbMax[0];
- if (quantizedAabbMin[1]>startJ)
+ if (quantizedAabbMin[1] > startJ)
startJ = quantizedAabbMin[1];
- if (quantizedAabbMax[1]<endJ)
+ if (quantizedAabbMax[1] < endJ)
endJ = quantizedAabbMax[1];
break;
}
- default:
+ default:
{
//need to get valid m_upAxis
btAssert(0);
}
}
-
-
+ // TODO If m_vboundsGrid is available, use it to determine if we really need to process this area
- for(int j=startJ; j<endJ; j++)
+ for (int j = startJ; j < endJ; j++)
{
- for(int x=startX; x<endX; x++)
+ for (int x = startX; x < endX; x++)
{
btVector3 vertices[3];
- if (m_flipQuadEdges || (m_useDiamondSubdivision && !((j+x) & 1))|| (m_useZigzagSubdivision && !(j & 1)))
+ if (m_flipQuadEdges || (m_useDiamondSubdivision && !((j + x) & 1)) || (m_useZigzagSubdivision && !(j & 1)))
{
- //first triangle
- getVertex(x,j,vertices[0]);
- getVertex(x, j + 1, vertices[1]);
- getVertex(x + 1, j + 1, vertices[2]);
- callback->processTriangle(vertices,x,j);
- //second triangle
- // getVertex(x,j,vertices[0]);//already got this vertex before, thanks to Danny Chapman
- getVertex(x+1,j+1,vertices[1]);
- getVertex(x + 1, j, vertices[2]);
- callback->processTriangle(vertices, x, j);
-
- } else
+ //first triangle
+ getVertex(x, j, vertices[0]);
+ getVertex(x, j + 1, vertices[1]);
+ getVertex(x + 1, j + 1, vertices[2]);
+ callback->processTriangle(vertices, x, j);
+ //second triangle
+ // getVertex(x,j,vertices[0]);//already got this vertex before, thanks to Danny Chapman
+ getVertex(x + 1, j + 1, vertices[1]);
+ getVertex(x + 1, j, vertices[2]);
+ callback->processTriangle(vertices, x, j);
+ }
+ else
{
- //first triangle
- getVertex(x,j,vertices[0]);
- getVertex(x,j+1,vertices[1]);
- getVertex(x+1,j,vertices[2]);
- callback->processTriangle(vertices,x,j);
- //second triangle
- getVertex(x+1,j,vertices[0]);
- //getVertex(x,j+1,vertices[1]);
- getVertex(x+1,j+1,vertices[2]);
- callback->processTriangle(vertices,x,j);
+ //first triangle
+ getVertex(x, j, vertices[0]);
+ getVertex(x, j + 1, vertices[1]);
+ getVertex(x + 1, j, vertices[2]);
+ callback->processTriangle(vertices, x, j);
+ //second triangle
+ getVertex(x + 1, j, vertices[0]);
+ //getVertex(x,j+1,vertices[1]);
+ getVertex(x + 1, j + 1, vertices[2]);
+ callback->processTriangle(vertices, x, j);
}
}
}
-
-
-
}
-void btHeightfieldTerrainShape::calculateLocalInertia(btScalar ,btVector3& inertia) const
+void btHeightfieldTerrainShape::calculateLocalInertia(btScalar, btVector3& inertia) const
{
//moving concave objects not supported
-
- inertia.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+
+ inertia.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
}
-void btHeightfieldTerrainShape::setLocalScaling(const btVector3& scaling)
+void btHeightfieldTerrainShape::setLocalScaling(const btVector3& scaling)
{
m_localScaling = scaling;
}
@@ -407,3 +380,416 @@ const btVector3& btHeightfieldTerrainShape::getLocalScaling() const
{
return m_localScaling;
}
+
+
+
+struct GridRaycastState
+{
+ int x; // Next quad coords
+ int z;
+ int prev_x; // Previous quad coords
+ int prev_z;
+ btScalar param; // Exit param for previous quad
+ btScalar prevParam; // Enter param for previous quad
+ btScalar maxDistanceFlat;
+ btScalar maxDistance3d;
+};
+
+
+// TODO Does it really need to take 3D vectors?
+/// Iterates through a virtual 2D grid of unit-sized square cells,
+/// and executes an action on each cell intersecting the given segment, ordered from begin to end.
+/// Initially inspired by http://www.cse.yorku.ca/~amana/research/grid.pdf
+template <typename Action_T>
+void gridRaycast(Action_T &quadAction, const btVector3 &beginPos, const btVector3 &endPos)
+{
+ GridRaycastState rs;
+ rs.maxDistance3d = beginPos.distance(endPos);
+ if (rs.maxDistance3d < 0.0001)
+ // Consider the ray is too small to hit anything
+ return;
+
+ btScalar rayDirectionFlatX = endPos[0] - beginPos[0];
+ btScalar rayDirectionFlatZ = endPos[2] - beginPos[2];
+ rs.maxDistanceFlat = btSqrt(rayDirectionFlatX * rayDirectionFlatX + rayDirectionFlatZ * rayDirectionFlatZ);
+
+ if(rs.maxDistanceFlat < 0.0001)
+ {
+ // Consider the ray vertical
+ rayDirectionFlatX = 0;
+ rayDirectionFlatZ = 0;
+ }
+ else
+ {
+ rayDirectionFlatX /= rs.maxDistanceFlat;
+ rayDirectionFlatZ /= rs.maxDistanceFlat;
+ }
+
+ const int xiStep = rayDirectionFlatX > 0 ? 1 : rayDirectionFlatX < 0 ? -1 : 0;
+ const int ziStep = rayDirectionFlatZ > 0 ? 1 : rayDirectionFlatZ < 0 ? -1 : 0;
+
+ const float infinite = 9999999;
+ const btScalar paramDeltaX = xiStep != 0 ? 1.f / btFabs(rayDirectionFlatX) : infinite;
+ const btScalar paramDeltaZ = ziStep != 0 ? 1.f / btFabs(rayDirectionFlatZ) : infinite;
+
+ // pos = param * dir
+ btScalar paramCrossX; // At which value of `param` we will cross a x-axis lane?
+ btScalar paramCrossZ; // At which value of `param` we will cross a z-axis lane?
+
+ // paramCrossX and paramCrossZ are initialized as being the first cross
+ // X initialization
+ if (xiStep != 0)
+ {
+ if (xiStep == 1)
+ paramCrossX = (ceil(beginPos[0]) - beginPos[0]) * paramDeltaX;
+ else
+ paramCrossX = (beginPos[0] - floor(beginPos[0])) * paramDeltaX;
+ }
+ else
+ paramCrossX = infinite; // Will never cross on X
+
+ // Z initialization
+ if (ziStep != 0)
+ {
+ if (ziStep == 1)
+ paramCrossZ = (ceil(beginPos[2]) - beginPos[2]) * paramDeltaZ;
+ else
+ paramCrossZ = (beginPos[2] - floor(beginPos[2])) * paramDeltaZ;
+ }
+ else
+ paramCrossZ = infinite; // Will never cross on Z
+
+ rs.x = static_cast<int>(floor(beginPos[0]));
+ rs.z = static_cast<int>(floor(beginPos[2]));
+
+ // Workaround cases where the ray starts at an integer position
+ if (paramCrossX == 0.0)
+ {
+ paramCrossX += paramDeltaX;
+ // If going backwards, we should ignore the position we would get by the above flooring,
+ // because the ray is not heading in that direction
+ if (xiStep == -1)
+ rs.x -= 1;
+ }
+
+ if (paramCrossZ == 0.0)
+ {
+ paramCrossZ += paramDeltaZ;
+ if (ziStep == -1)
+ rs.z -= 1;
+ }
+
+ rs.prev_x = rs.x;
+ rs.prev_z = rs.z;
+ rs.param = 0;
+
+ while (true)
+ {
+ rs.prev_x = rs.x;
+ rs.prev_z = rs.z;
+ rs.prevParam = rs.param;
+
+ if (paramCrossX < paramCrossZ)
+ {
+ // X lane
+ rs.x += xiStep;
+ // Assign before advancing the param,
+ // to be in sync with the initialization step
+ rs.param = paramCrossX;
+ paramCrossX += paramDeltaX;
+ }
+ else
+ {
+ // Z lane
+ rs.z += ziStep;
+ rs.param = paramCrossZ;
+ paramCrossZ += paramDeltaZ;
+ }
+
+ if (rs.param > rs.maxDistanceFlat)
+ {
+ rs.param = rs.maxDistanceFlat;
+ quadAction(rs);
+ break;
+ }
+ else
+ quadAction(rs);
+ }
+}
+
+
+struct ProcessTrianglesAction
+{
+ const btHeightfieldTerrainShape *shape;
+ bool flipQuadEdges;
+ bool useDiamondSubdivision;
+ int width;
+ int length;
+ btTriangleCallback* callback;
+
+ void exec(int x, int z) const
+ {
+ if(x < 0 || z < 0 || x >= width || z >= length)
+ return;
+
+ btVector3 vertices[3];
+
+ // Check quad
+ if (flipQuadEdges || (useDiamondSubdivision && (((z + x) & 1) > 0)))
+ {
+ // First triangle
+ shape->getVertex(x, z, vertices[0]);
+ shape->getVertex(x + 1, z, vertices[1]);
+ shape->getVertex(x + 1, z + 1, vertices[2]);
+ callback->processTriangle(vertices, x, z);
+
+ // Second triangle
+ shape->getVertex(x, z, vertices[0]);
+ shape->getVertex(x + 1, z + 1, vertices[1]);
+ shape->getVertex(x, z + 1, vertices[2]);
+ callback->processTriangle(vertices, x, z);
+ }
+ else
+ {
+ // First triangle
+ shape->getVertex(x, z, vertices[0]);
+ shape->getVertex(x, z + 1, vertices[1]);
+ shape->getVertex(x + 1, z, vertices[2]);
+ callback->processTriangle(vertices, x, z);
+
+ // Second triangle
+ shape->getVertex(x + 1, z, vertices[0]);
+ shape->getVertex(x, z + 1, vertices[1]);
+ shape->getVertex(x + 1, z + 1, vertices[2]);
+ callback->processTriangle(vertices, x, z);
+ }
+ }
+
+ void operator ()(const GridRaycastState &bs) const
+ {
+ exec(bs.prev_x, bs.prev_z);
+ }
+};
+
+
+struct ProcessVBoundsAction
+{
+ const btHeightfieldTerrainShape::Range *vbounds;
+ int width;
+ int length;
+ int chunkSize;
+
+ btVector3 rayBegin;
+ btVector3 rayEnd;
+ btVector3 rayDir;
+
+ ProcessTrianglesAction processTriangles;
+
+ void operator ()(const GridRaycastState &rs) const
+ {
+ int x = rs.prev_x;
+ int z = rs.prev_z;
+
+ if(x < 0 || z < 0 || x >= width || z >= length)
+ return;
+
+ const btHeightfieldTerrainShape::Range chunk = vbounds[x + z * width];
+
+ btVector3 enterPos;
+ btVector3 exitPos;
+
+ if (rs.maxDistanceFlat > 0.0001)
+ {
+ btScalar flatTo3d = chunkSize * rs.maxDistance3d / rs.maxDistanceFlat;
+ btScalar enterParam3d = rs.prevParam * flatTo3d;
+ btScalar exitParam3d = rs.param * flatTo3d;
+ enterPos = rayBegin + rayDir * enterParam3d;
+ exitPos = rayBegin + rayDir * exitParam3d;
+
+ // We did enter the flat projection of the AABB,
+ // but we have to check if we intersect it on the vertical axis
+ if (enterPos[1] > chunk.max && exitPos[1] > chunk.max)
+ return;
+ if (enterPos[1] < chunk.min && exitPos[1] < chunk.min)
+ return;
+ }
+ else
+ {
+ // Consider the ray vertical
+ // (though we shouldn't reach this often because there is an early check up-front)
+ enterPos = rayBegin;
+ exitPos = rayEnd;
+ }
+
+ gridRaycast(processTriangles, enterPos, exitPos);
+ // Note: it could be possible to have more than one grid at different levels,
+ // to do this there would be a branch using a pointer to another ProcessVBoundsAction
+ }
+};
+
+
+// TODO How do I interrupt the ray when there is a hit? `callback` does not return any result
+/// Performs a raycast using a hierarchical Bresenham algorithm.
+/// Does not allocate any memory by itself.
+void btHeightfieldTerrainShape::performRaycast(btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget) const
+{
+ // Transform to cell-local
+ btVector3 beginPos = raySource / m_localScaling;
+ btVector3 endPos = rayTarget / m_localScaling;
+ beginPos += m_localOrigin;
+ endPos += m_localOrigin;
+
+ ProcessTrianglesAction processTriangles;
+ processTriangles.shape = this;
+ processTriangles.flipQuadEdges = m_flipQuadEdges;
+ processTriangles.useDiamondSubdivision = m_useDiamondSubdivision;
+ processTriangles.callback = callback;
+ processTriangles.width = m_heightStickWidth - 1;
+ processTriangles.length = m_heightStickLength - 1;
+
+ // TODO Transform vectors to account for m_upAxis
+ int iBeginX = static_cast<int>(floor(beginPos[0]));
+ int iBeginZ = static_cast<int>(floor(beginPos[2]));
+ int iEndX = static_cast<int>(floor(endPos[0]));
+ int iEndZ = static_cast<int>(floor(endPos[2]));
+
+ if (iBeginX == iEndX && iBeginZ == iEndZ)
+ {
+ // The ray will never cross quads within the plane,
+ // so directly process triangles within one quad
+ // (typically, vertical rays should end up here)
+ processTriangles.exec(iBeginX, iEndZ);
+ return;
+ }
+
+ if (m_vboundsGrid == NULL)
+ {
+ // Process all quads intersecting the flat projection of the ray
+ gridRaycast(processTriangles, beginPos, endPos);
+ }
+ else
+ {
+ btVector3 rayDiff = endPos - beginPos;
+ btScalar flatDistance2 = rayDiff[0] * rayDiff[0] + rayDiff[2] * rayDiff[2];
+ if (flatDistance2 < m_vboundsChunkSize * m_vboundsChunkSize)
+ {
+ // Don't use chunks, the ray is too short in the plane
+ gridRaycast(processTriangles, beginPos, endPos);
+ }
+
+ ProcessVBoundsAction processVBounds;
+ processVBounds.width = m_vboundsGridWidth;
+ processVBounds.length = m_vboundsGridLength;
+ processVBounds.vbounds = m_vboundsGrid;
+ processVBounds.rayBegin = beginPos;
+ processVBounds.rayEnd = endPos;
+ processVBounds.rayDir = rayDiff.normalized();
+ processVBounds.processTriangles = processTriangles;
+ processVBounds.chunkSize = m_vboundsChunkSize;
+ // The ray is long, run raycast on a higher-level grid
+ gridRaycast(processVBounds, beginPos / m_vboundsChunkSize, endPos / m_vboundsChunkSize);
+ }
+}
+
+
+/// Builds a grid data structure storing the min and max heights of the terrain in chunks.
+/// if chunkSize is zero, that accelerator is removed.
+/// If you modify the heights, you need to rebuild this accelerator.
+void btHeightfieldTerrainShape::buildAccelerator(int chunkSize)
+{
+ if (chunkSize <= 0)
+ {
+ clearAccelerator();
+ return;
+ }
+
+ m_vboundsChunkSize = chunkSize;
+ int nChunksX = m_heightStickWidth / chunkSize;
+ int nChunksZ = m_heightStickLength / chunkSize;
+
+ if (m_heightStickWidth % chunkSize > 0)
+ ++nChunksX; // In case terrain size isn't dividable by chunk size
+ if (m_heightStickLength % chunkSize > 0)
+ ++nChunksZ;
+
+ if(m_vboundsGridWidth != nChunksX || m_vboundsGridLength != nChunksZ)
+ {
+ clearAccelerator();
+ m_vboundsGridWidth = nChunksX;
+ m_vboundsGridLength = nChunksZ;
+ }
+
+ if (nChunksX == 0 || nChunksZ == 0)
+ return;
+
+ // TODO What is the recommended way to allocate this?
+ // This data structure is only reallocated if the required size changed
+ if (m_vboundsGrid == NULL)
+ m_vboundsGrid = new Range[nChunksX * nChunksZ];
+
+ // Compute min and max height for all chunks
+ for (int cz = 0; cz < nChunksZ; ++cz)
+ {
+ int z0 = cz * chunkSize;
+
+ for (int cx = 0; cx < nChunksX; ++cx)
+ {
+ int x0 = cx * chunkSize;
+
+ Range r;
+
+ r.min = getRawHeightFieldValue(x0, z0);
+ r.max = r.min;
+
+ // Compute min and max height for this chunk.
+ // We have to include one extra cell to account for neighbors.
+ // Here is why:
+ // Say we have a flat terrain, and a plateau that fits a chunk perfectly.
+ //
+ // Left Right
+ // 0---0---0---1---1---1
+ // | | | | | |
+ // 0---0---0---1---1---1
+ // | | | | | |
+ // 0---0---0---1---1---1
+ // x
+ //
+ // If the AABB for the Left chunk did not share vertices with the Right,
+ // then we would fail collision tests at x due to a gap.
+ //
+ for (int z = z0; z < z0 + chunkSize + 1; ++z)
+ {
+ if (z >= m_heightStickLength)
+ continue;
+
+ for (int x = x0; x < x0 + chunkSize + 1; ++x)
+ {
+ if (x >= m_heightStickWidth)
+ continue;
+
+ btScalar height = getRawHeightFieldValue(x, z);
+
+ if (height < r.min)
+ r.min = height;
+ else if (height > r.max)
+ r.max = height;
+ }
+ }
+
+ m_vboundsGrid[cx + cz * nChunksX] = r;
+ }
+ }
+}
+
+
+void btHeightfieldTerrainShape::clearAccelerator()
+{
+ if (m_vboundsGrid)
+ {
+ // TODO What is the recommended way to deallocate this?
+ delete[] m_vboundsGrid;
+ m_vboundsGrid = 0;
+ }
+}
+
+
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h
index 4a7a4a4bda..e23b548cb2 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h
@@ -18,6 +18,7 @@ subject to the following restrictions:
#include "btConcaveShape.h"
+
///btHeightfieldTerrainShape simulates a 2D heightfield terrain
/**
The caller is responsible for maintaining the heightfield array; this
@@ -68,43 +69,52 @@ subject to the following restrictions:
For usage and testing see the TerrainDemo.
*/
-ATTRIBUTE_ALIGNED16(class) btHeightfieldTerrainShape : public btConcaveShape
+ATTRIBUTE_ALIGNED16(class)
+btHeightfieldTerrainShape : public btConcaveShape
{
+public:
+ struct Range {
+ btScalar min;
+ btScalar max;
+ };
+
protected:
- btVector3 m_localAabbMin;
- btVector3 m_localAabbMax;
- btVector3 m_localOrigin;
+ btVector3 m_localAabbMin;
+ btVector3 m_localAabbMax;
+ btVector3 m_localOrigin;
///terrain data
- int m_heightStickWidth;
+ int m_heightStickWidth;
int m_heightStickLength;
- btScalar m_minHeight;
- btScalar m_maxHeight;
+ btScalar m_minHeight;
+ btScalar m_maxHeight;
btScalar m_width;
btScalar m_length;
btScalar m_heightScale;
- union
- {
- const unsigned char* m_heightfieldDataUnsignedChar;
- const short* m_heightfieldDataShort;
- const btScalar* m_heightfieldDataFloat;
- const void* m_heightfieldDataUnknown;
+ union {
+ const unsigned char* m_heightfieldDataUnsignedChar;
+ const short* m_heightfieldDataShort;
+ const btScalar* m_heightfieldDataFloat;
+ const void* m_heightfieldDataUnknown;
};
- PHY_ScalarType m_heightDataType;
- bool m_flipQuadEdges;
- bool m_useDiamondSubdivision;
+ PHY_ScalarType m_heightDataType;
+ bool m_flipQuadEdges;
+ bool m_useDiamondSubdivision;
bool m_useZigzagSubdivision;
- int m_upAxis;
-
- btVector3 m_localScaling;
+ int m_upAxis;
- virtual btScalar getRawHeightFieldValue(int x,int y) const;
- void quantizeWithClamp(int* out, const btVector3& point,int isMax) const;
- void getVertex(int x,int y,btVector3& vertex) const;
+ btVector3 m_localScaling;
+ // Accelerator
+ Range *m_vboundsGrid;
+ int m_vboundsGridWidth;
+ int m_vboundsGridLength;
+ int m_vboundsChunkSize;
+ virtual btScalar getRawHeightFieldValue(int x, int y) const;
+ void quantizeWithClamp(int* out, const btVector3& point, int isMax) const;
/// protected initialization
/**
@@ -112,25 +122,24 @@ protected:
backwards-compatible without a lot of copy/paste.
*/
void initialize(int heightStickWidth, int heightStickLength,
- const void* heightfieldData, btScalar heightScale,
- btScalar minHeight, btScalar maxHeight, int upAxis,
- PHY_ScalarType heightDataType, bool flipQuadEdges);
+ const void* heightfieldData, btScalar heightScale,
+ btScalar minHeight, btScalar maxHeight, int upAxis,
+ PHY_ScalarType heightDataType, bool flipQuadEdges);
public:
-
BT_DECLARE_ALIGNED_ALLOCATOR();
-
+
/// preferred constructor
/**
This constructor supports a range of heightfield
data types, and allows for a non-zero minimum height value.
heightScale is needed for any integer-based heightfield data types.
*/
- btHeightfieldTerrainShape(int heightStickWidth,int heightStickLength,
- const void* heightfieldData, btScalar heightScale,
- btScalar minHeight, btScalar maxHeight,
- int upAxis, PHY_ScalarType heightDataType,
- bool flipQuadEdges);
+ btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength,
+ const void* heightfieldData, btScalar heightScale,
+ btScalar minHeight, btScalar maxHeight,
+ int upAxis, PHY_ScalarType heightDataType,
+ bool flipQuadEdges);
/// legacy constructor
/**
@@ -139,29 +148,34 @@ public:
compatibility reasons, heightScale is calculated as maxHeight / 65535
(and is only used when useFloatData = false).
*/
- btHeightfieldTerrainShape(int heightStickWidth,int heightStickLength,const void* heightfieldData, btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges);
+ btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength, const void* heightfieldData, btScalar maxHeight, int upAxis, bool useFloatData, bool flipQuadEdges);
virtual ~btHeightfieldTerrainShape();
+ void setUseDiamondSubdivision(bool useDiamondSubdivision = true) { m_useDiamondSubdivision = useDiamondSubdivision; }
- void setUseDiamondSubdivision(bool useDiamondSubdivision=true) { m_useDiamondSubdivision = useDiamondSubdivision;}
+ ///could help compatibility with Ogre heightfields. See https://code.google.com/p/bullet/issues/detail?id=625
+ void setUseZigzagSubdivision(bool useZigzagSubdivision = true) { m_useZigzagSubdivision = useZigzagSubdivision; }
- ///could help compatibility with Ogre heightfields. See https://code.google.com/p/bullet/issues/detail?id=625
- void setUseZigzagSubdivision(bool useZigzagSubdivision=true) { m_useZigzagSubdivision = useZigzagSubdivision;}
+ virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
- virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+ virtual void processAllTriangles(btTriangleCallback * callback, const btVector3& aabbMin, const btVector3& aabbMax) const;
- virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+ virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
- virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+ virtual void setLocalScaling(const btVector3& scaling);
- virtual void setLocalScaling(const btVector3& scaling);
-
virtual const btVector3& getLocalScaling() const;
- //debugging
- virtual const char* getName()const {return "HEIGHTFIELD";}
+ void getVertex(int x,int y,btVector3& vertex) const;
+ void performRaycast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget) const;
+
+ void buildAccelerator(int chunkSize=16);
+ void clearAccelerator();
+
+ //debugging
+ virtual const char* getName() const { return "HEIGHTFIELD"; }
};
-#endif //BT_HEIGHTFIELD_TERRAIN_SHAPE_H
+#endif //BT_HEIGHTFIELD_TERRAIN_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btMaterial.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btMaterial.h
index 866f9b4da4..c9a436bf26 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btMaterial.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btMaterial.h
@@ -21,15 +21,18 @@ subject to the following restrictions:
// Material class to be used by btMultimaterialTriangleMeshShape to store triangle properties
class btMaterial
{
- // public members so that materials can change due to world events
+ // public members so that materials can change due to world events
public:
- btScalar m_friction;
- btScalar m_restitution;
- int pad[2];
-
- btMaterial(){}
- btMaterial(btScalar fric, btScalar rest) { m_friction = fric; m_restitution = rest; }
+ btScalar m_friction;
+ btScalar m_restitution;
+ int pad[2];
+
+ btMaterial() {}
+ btMaterial(btScalar fric, btScalar rest)
+ {
+ m_friction = fric;
+ m_restitution = rest;
+ }
};
-#endif // BT_MATERIAL_H
-
+#endif // BT_MATERIAL_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btMiniSDF.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btMiniSDF.cpp
index afe45e1d2d..13c0a343f1 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btMiniSDF.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btMiniSDF.cpp
@@ -10,31 +10,31 @@
//
#include <limits.h>
-#include <string.h> //memcpy
+#include <string.h> //memcpy
struct btSdfDataStream
{
const char* m_data;
int m_size;
-
+
int m_currentOffset;
-
+
btSdfDataStream(const char* data, int size)
- :m_data(data),
- m_size(size),
- m_currentOffset(0)
+ : m_data(data),
+ m_size(size),
+ m_currentOffset(0)
{
-
}
- template<class T> bool read(T& val)
+ template <class T>
+ bool read(T& val)
{
int bytes = sizeof(T);
- if (m_currentOffset+bytes<=m_size)
+ if (m_currentOffset + bytes <= m_size)
{
char* dest = (char*)&val;
- memcpy(dest,&m_data[m_currentOffset],bytes);
- m_currentOffset+=bytes;
+ memcpy(dest, &m_data[m_currentOffset], bytes);
+ m_currentOffset += bytes;
return true;
}
btAssert(0);
@@ -42,137 +42,133 @@ struct btSdfDataStream
}
};
-
bool btMiniSDF::load(const char* data, int size)
{
- int fileSize = -1;
+ int fileSize = -1;
- btSdfDataStream ds(data,size);
- {
- double buf[6];
- ds.read(buf);
- m_domain.m_min[0] = buf[0];
- m_domain.m_min[1] = buf[1];
- m_domain.m_min[2] = buf[2];
- m_domain.m_min[3] = 0;
- m_domain.m_max[0] = buf[3];
- m_domain.m_max[1] = buf[4];
- m_domain.m_max[2] = buf[5];
- m_domain.m_max[3] = 0;
- }
- {
- unsigned int buf2[3];
- ds.read(buf2);
- m_resolution[0] = buf2[0];
- m_resolution[1] = buf2[1];
- m_resolution[2] = buf2[2];
- }
- {
- double buf[3];
- ds.read(buf);
- m_cell_size[0] = buf[0];
- m_cell_size[1] = buf[1];
- m_cell_size[2] = buf[2];
- }
- {
- double buf[3];
- ds.read(buf);
- m_inv_cell_size[0] = buf[0];
- m_inv_cell_size[1] = buf[1];
- m_inv_cell_size[2] = buf[2];
- }
- {
- unsigned long long int cells;
- ds.read(cells);
- m_n_cells = cells;
- }
- {
- unsigned long long int fields;
- ds.read(fields);
- m_n_fields = fields;
- }
+ btSdfDataStream ds(data, size);
+ {
+ double buf[6];
+ ds.read(buf);
+ m_domain.m_min[0] = buf[0];
+ m_domain.m_min[1] = buf[1];
+ m_domain.m_min[2] = buf[2];
+ m_domain.m_min[3] = 0;
+ m_domain.m_max[0] = buf[3];
+ m_domain.m_max[1] = buf[4];
+ m_domain.m_max[2] = buf[5];
+ m_domain.m_max[3] = 0;
+ }
+ {
+ unsigned int buf2[3];
+ ds.read(buf2);
+ m_resolution[0] = buf2[0];
+ m_resolution[1] = buf2[1];
+ m_resolution[2] = buf2[2];
+ }
+ {
+ double buf[3];
+ ds.read(buf);
+ m_cell_size[0] = buf[0];
+ m_cell_size[1] = buf[1];
+ m_cell_size[2] = buf[2];
+ }
+ {
+ double buf[3];
+ ds.read(buf);
+ m_inv_cell_size[0] = buf[0];
+ m_inv_cell_size[1] = buf[1];
+ m_inv_cell_size[2] = buf[2];
+ }
+ {
+ unsigned long long int cells;
+ ds.read(cells);
+ m_n_cells = cells;
+ }
+ {
+ unsigned long long int fields;
+ ds.read(fields);
+ m_n_fields = fields;
+ }
-
- unsigned long long int nodes0;
- std::size_t n_nodes0;
- ds.read(nodes0);
- n_nodes0 = nodes0;
- if (n_nodes0 > 1024 * 1024 * 1024)
- {
- return m_isValid;
- }
- m_nodes.resize(n_nodes0);
- for (unsigned int i=0;i<n_nodes0;i++)
+ unsigned long long int nodes0;
+ std::size_t n_nodes0;
+ ds.read(nodes0);
+ n_nodes0 = nodes0;
+ if (n_nodes0 > 1024 * 1024 * 1024)
+ {
+ return m_isValid;
+ }
+ m_nodes.resize(n_nodes0);
+ for (unsigned int i = 0; i < n_nodes0; i++)
+ {
+ unsigned long long int n_nodes1;
+ ds.read(n_nodes1);
+ btAlignedObjectArray<double>& nodes = m_nodes[i];
+ nodes.resize(n_nodes1);
+ for (int j = 0; j < nodes.size(); j++)
{
- unsigned long long int n_nodes1;
- ds.read(n_nodes1);
- btAlignedObjectArray<double>& nodes = m_nodes[i];
- nodes.resize(n_nodes1);
- for ( int j=0;j<nodes.size();j++)
- {
- double& node = nodes[j];
- ds.read(node);
- }
+ double& node = nodes[j];
+ ds.read(node);
}
+ }
- unsigned long long int n_cells0;
- ds.read(n_cells0);
- m_cells.resize(n_cells0);
- for (int i=0;i<n_cells0;i++)
+ unsigned long long int n_cells0;
+ ds.read(n_cells0);
+ m_cells.resize(n_cells0);
+ for (int i = 0; i < n_cells0; i++)
+ {
+ unsigned long long int n_cells1;
+ btAlignedObjectArray<btCell32>& cells = m_cells[i];
+ ds.read(n_cells1);
+ cells.resize(n_cells1);
+ for (int j = 0; j < n_cells1; j++)
{
- unsigned long long int n_cells1;
- btAlignedObjectArray<btCell32 >& cells = m_cells[i];
- ds.read(n_cells1);
- cells.resize(n_cells1);
- for (int j=0;j<n_cells1;j++)
- {
- btCell32& cell = cells[j];
- ds.read(cell);
- }
+ btCell32& cell = cells[j];
+ ds.read(cell);
}
+ }
+
+ {
+ unsigned long long int n_cell_maps0;
+ ds.read(n_cell_maps0);
+ m_cell_map.resize(n_cell_maps0);
+ for (int i = 0; i < n_cell_maps0; i++)
{
- unsigned long long int n_cell_maps0;
- ds.read(n_cell_maps0);
-
- m_cell_map.resize(n_cell_maps0);
- for (int i=0;i<n_cell_maps0;i++)
+ unsigned long long int n_cell_maps1;
+ btAlignedObjectArray<unsigned int>& cell_maps = m_cell_map[i];
+ ds.read(n_cell_maps1);
+ cell_maps.resize(n_cell_maps1);
+ for (int j = 0; j < n_cell_maps1; j++)
{
- unsigned long long int n_cell_maps1;
- btAlignedObjectArray<unsigned int>& cell_maps = m_cell_map[i];
- ds.read(n_cell_maps1);
- cell_maps.resize(n_cell_maps1);
- for (int j=0;j<n_cell_maps1;j++)
- {
- unsigned int& cell_map = cell_maps[j];
- ds.read(cell_map);
- }
+ unsigned int& cell_map = cell_maps[j];
+ ds.read(cell_map);
}
}
+ }
- m_isValid = (ds.m_currentOffset == ds.m_size);
- return m_isValid;
+ m_isValid = (ds.m_currentOffset == ds.m_size);
+ return m_isValid;
}
-
-unsigned int btMiniSDF::multiToSingleIndex(btMultiIndex const & ijk) const
+unsigned int btMiniSDF::multiToSingleIndex(btMultiIndex const& ijk) const
{
return m_resolution[1] * m_resolution[0] * ijk.ijk[2] + m_resolution[0] * ijk.ijk[1] + ijk.ijk[0];
}
-
+
btAlignedBox3d
btMiniSDF::subdomain(btMultiIndex const& ijk) const
{
btAssert(m_isValid);
btVector3 tmp;
- tmp.m_floats[0] = m_cell_size[0]*(double)ijk.ijk[0];
- tmp.m_floats[1] = m_cell_size[1]*(double)ijk.ijk[1];
- tmp.m_floats[2] = m_cell_size[2]*(double)ijk.ijk[2];
-
+ tmp.m_floats[0] = m_cell_size[0] * (double)ijk.ijk[0];
+ tmp.m_floats[1] = m_cell_size[1] * (double)ijk.ijk[1];
+ tmp.m_floats[2] = m_cell_size[2] * (double)ijk.ijk[2];
btVector3 origin = m_domain.min() + tmp;
- btAlignedBox3d box = btAlignedBox3d (origin, origin + m_cell_size);
+ btAlignedBox3d box = btAlignedBox3d(origin, origin + m_cell_size);
return box;
}
@@ -181,8 +177,8 @@ btMiniSDF::singleToMultiIndex(unsigned int l) const
{
btAssert(m_isValid);
unsigned int n01 = m_resolution[0] * m_resolution[1];
- unsigned int k = l / n01;
- unsigned int temp = l % n01;
+ unsigned int k = l / n01;
+ unsigned int temp = l % n01;
unsigned int j = temp / m_resolution[0];
unsigned int i = temp % m_resolution[0];
btMultiIndex mi;
@@ -199,59 +195,57 @@ btMiniSDF::subdomain(unsigned int l) const
return subdomain(singleToMultiIndex(l));
}
-
btShapeMatrix
btMiniSDF::shape_function_(btVector3 const& xi, btShapeGradients* gradient) const
{
btAssert(m_isValid);
btShapeMatrix res;
-
+
btScalar x = xi[0];
btScalar y = xi[1];
btScalar z = xi[2];
- btScalar x2 = x*x;
- btScalar y2 = y*y;
- btScalar z2 = z*z;
-
- btScalar _1mx = 1.0 - x;
- btScalar _1my = 1.0 - y;
- btScalar _1mz = 1.0 - z;
+ btScalar x2 = x * x;
+ btScalar y2 = y * y;
+ btScalar z2 = z * z;
- btScalar _1px = 1.0 + x;
- btScalar _1py = 1.0 + y;
- btScalar _1pz = 1.0 + z;
+ btScalar _1mx = 1.0 - x;
+ btScalar _1my = 1.0 - y;
+ btScalar _1mz = 1.0 - z;
- btScalar _1m3x = 1.0 - 3.0 * x;
- btScalar _1m3y = 1.0 - 3.0 * y;
- btScalar _1m3z = 1.0 - 3.0 * z;
+ btScalar _1px = 1.0 + x;
+ btScalar _1py = 1.0 + y;
+ btScalar _1pz = 1.0 + z;
- btScalar _1p3x = 1.0 + 3.0 * x;
- btScalar _1p3y = 1.0 + 3.0 * y;
- btScalar _1p3z = 1.0 + 3.0 * z;
+ btScalar _1m3x = 1.0 - 3.0 * x;
+ btScalar _1m3y = 1.0 - 3.0 * y;
+ btScalar _1m3z = 1.0 - 3.0 * z;
- btScalar _1mxt1my = _1mx * _1my;
- btScalar _1mxt1py = _1mx * _1py;
- btScalar _1pxt1my = _1px * _1my;
- btScalar _1pxt1py = _1px * _1py;
+ btScalar _1p3x = 1.0 + 3.0 * x;
+ btScalar _1p3y = 1.0 + 3.0 * y;
+ btScalar _1p3z = 1.0 + 3.0 * z;
- btScalar _1mxt1mz = _1mx * _1mz;
- btScalar _1mxt1pz = _1mx * _1pz;
- btScalar _1pxt1mz = _1px * _1mz;
- btScalar _1pxt1pz = _1px * _1pz;
+ btScalar _1mxt1my = _1mx * _1my;
+ btScalar _1mxt1py = _1mx * _1py;
+ btScalar _1pxt1my = _1px * _1my;
+ btScalar _1pxt1py = _1px * _1py;
- btScalar _1myt1mz = _1my * _1mz;
- btScalar _1myt1pz = _1my * _1pz;
- btScalar _1pyt1mz = _1py * _1mz;
- btScalar _1pyt1pz = _1py * _1pz;
+ btScalar _1mxt1mz = _1mx * _1mz;
+ btScalar _1mxt1pz = _1mx * _1pz;
+ btScalar _1pxt1mz = _1px * _1mz;
+ btScalar _1pxt1pz = _1px * _1pz;
- btScalar _1mx2 = 1.0 - x2;
- btScalar _1my2 = 1.0 - y2;
- btScalar _1mz2 = 1.0 - z2;
+ btScalar _1myt1mz = _1my * _1mz;
+ btScalar _1myt1pz = _1my * _1pz;
+ btScalar _1pyt1mz = _1py * _1mz;
+ btScalar _1pyt1pz = _1py * _1pz;
+ btScalar _1mx2 = 1.0 - x2;
+ btScalar _1my2 = 1.0 - y2;
+ btScalar _1mz2 = 1.0 - z2;
// Corner nodes.
- btScalar fac = 1.0 / 64.0 * (9.0 * (x2 + y2 + z2) - 19.0);
+ btScalar fac = 1.0 / 64.0 * (9.0 * (x2 + y2 + z2) - 19.0);
res[0] = fac * _1mxt1my * _1mz;
res[1] = fac * _1pxt1my * _1mz;
res[2] = fac * _1mxt1py * _1mz;
@@ -264,10 +258,10 @@ btMiniSDF::shape_function_(btVector3 const& xi, btShapeGradients* gradient) cons
// Edge nodes.
fac = 9.0 / 64.0 * _1mx2;
- btScalar fact1m3x = fac * _1m3x;
- btScalar fact1p3x = fac * _1p3x;
- res[ 8] = fact1m3x * _1myt1mz;
- res[ 9] = fact1p3x * _1myt1mz;
+ btScalar fact1m3x = fac * _1m3x;
+ btScalar fact1p3x = fac * _1p3x;
+ res[8] = fact1m3x * _1myt1mz;
+ res[9] = fact1p3x * _1myt1mz;
res[10] = fact1m3x * _1myt1pz;
res[11] = fact1p3x * _1myt1pz;
res[12] = fact1m3x * _1pyt1mz;
@@ -276,8 +270,8 @@ btMiniSDF::shape_function_(btVector3 const& xi, btShapeGradients* gradient) cons
res[15] = fact1p3x * _1pyt1pz;
fac = 9.0 / 64.0 * _1my2;
- btScalar fact1m3y = fac * _1m3y;
- btScalar fact1p3y = fac * _1p3y;
+ btScalar fact1m3y = fac * _1m3y;
+ btScalar fact1p3y = fac * _1p3y;
res[16] = fact1m3y * _1mxt1mz;
res[17] = fact1p3y * _1mxt1mz;
res[18] = fact1m3y * _1pxt1mz;
@@ -288,8 +282,8 @@ btMiniSDF::shape_function_(btVector3 const& xi, btShapeGradients* gradient) cons
res[23] = fact1p3y * _1pxt1pz;
fac = 9.0 / 64.0 * _1mz2;
- btScalar fact1m3z = fac * _1m3z;
- btScalar fact1p3z = fac * _1p3z;
+ btScalar fact1m3z = fac * _1m3z;
+ btScalar fact1p3z = fac * _1p3z;
res[24] = fact1m3z * _1mxt1my;
res[25] = fact1p3z * _1mxt1my;
res[26] = fact1m3z * _1mxt1py;
@@ -309,7 +303,7 @@ btMiniSDF::shape_function_(btVector3 const& xi, btShapeGradients* gradient) cons
btScalar _18x = 18.0 * x;
btScalar _18y = 18.0 * y;
btScalar _18z = 18.0 * z;
-
+
btScalar _3m9x2 = 3.0 - 9.0 * x2;
btScalar _3m9y2 = 3.0 - 9.0 * y2;
btScalar _3m9z2 = 3.0 - 9.0 * z2;
@@ -325,132 +319,128 @@ btMiniSDF::shape_function_(btVector3 const& xi, btShapeGradients* gradient) cons
btScalar _18zm9tx2py2p3z2m19 = _18z - _9tx2py2p3z2m19;
btScalar _18zp9tx2py2p3z2m19 = _18z + _9tx2py2p3z2m19;
- dN(0,0) =_18xm9t3x2py2pz2m19 * _1myt1mz;
- dN(0,1) =_1mxt1mz * _18ym9tx2p3y2pz2m19;
- dN(0,2) =_1mxt1my * _18zm9tx2py2p3z2m19;
- dN(1,0) =_18xp9t3x2py2pz2m19 * _1myt1mz;
- dN(1,1) =_1pxt1mz * _18ym9tx2p3y2pz2m19;
- dN(1,2) =_1pxt1my * _18zm9tx2py2p3z2m19;
- dN(2,0) =_18xm9t3x2py2pz2m19 * _1pyt1mz;
- dN(2,1) =_1mxt1mz * _18yp9tx2p3y2pz2m19;
- dN(2,2) =_1mxt1py * _18zm9tx2py2p3z2m19;
- dN(3,0) =_18xp9t3x2py2pz2m19 * _1pyt1mz;
- dN(3,1) =_1pxt1mz * _18yp9tx2p3y2pz2m19;
- dN(3,2) =_1pxt1py * _18zm9tx2py2p3z2m19;
- dN(4,0) =_18xm9t3x2py2pz2m19 * _1myt1pz;
- dN(4,1) =_1mxt1pz * _18ym9tx2p3y2pz2m19;
- dN(4,2) =_1mxt1my * _18zp9tx2py2p3z2m19;
- dN(5,0) =_18xp9t3x2py2pz2m19 * _1myt1pz;
- dN(5,1) =_1pxt1pz * _18ym9tx2p3y2pz2m19;
- dN(5,2) =_1pxt1my * _18zp9tx2py2p3z2m19;
- dN(6,0) =_18xm9t3x2py2pz2m19 * _1pyt1pz;
- dN(6,1) =_1mxt1pz * _18yp9tx2p3y2pz2m19;
- dN(6,2) =_1mxt1py * _18zp9tx2py2p3z2m19;
- dN(7,0) =_18xp9t3x2py2pz2m19 * _1pyt1pz;
- dN(7,1) =_1pxt1pz * _18yp9tx2p3y2pz2m19;
- dN(7,2) =_1pxt1py * _18zp9tx2py2p3z2m19;
+ dN(0, 0) = _18xm9t3x2py2pz2m19 * _1myt1mz;
+ dN(0, 1) = _1mxt1mz * _18ym9tx2p3y2pz2m19;
+ dN(0, 2) = _1mxt1my * _18zm9tx2py2p3z2m19;
+ dN(1, 0) = _18xp9t3x2py2pz2m19 * _1myt1mz;
+ dN(1, 1) = _1pxt1mz * _18ym9tx2p3y2pz2m19;
+ dN(1, 2) = _1pxt1my * _18zm9tx2py2p3z2m19;
+ dN(2, 0) = _18xm9t3x2py2pz2m19 * _1pyt1mz;
+ dN(2, 1) = _1mxt1mz * _18yp9tx2p3y2pz2m19;
+ dN(2, 2) = _1mxt1py * _18zm9tx2py2p3z2m19;
+ dN(3, 0) = _18xp9t3x2py2pz2m19 * _1pyt1mz;
+ dN(3, 1) = _1pxt1mz * _18yp9tx2p3y2pz2m19;
+ dN(3, 2) = _1pxt1py * _18zm9tx2py2p3z2m19;
+ dN(4, 0) = _18xm9t3x2py2pz2m19 * _1myt1pz;
+ dN(4, 1) = _1mxt1pz * _18ym9tx2p3y2pz2m19;
+ dN(4, 2) = _1mxt1my * _18zp9tx2py2p3z2m19;
+ dN(5, 0) = _18xp9t3x2py2pz2m19 * _1myt1pz;
+ dN(5, 1) = _1pxt1pz * _18ym9tx2p3y2pz2m19;
+ dN(5, 2) = _1pxt1my * _18zp9tx2py2p3z2m19;
+ dN(6, 0) = _18xm9t3x2py2pz2m19 * _1pyt1pz;
+ dN(6, 1) = _1mxt1pz * _18yp9tx2p3y2pz2m19;
+ dN(6, 2) = _1mxt1py * _18zp9tx2py2p3z2m19;
+ dN(7, 0) = _18xp9t3x2py2pz2m19 * _1pyt1pz;
+ dN(7, 1) = _1pxt1pz * _18yp9tx2p3y2pz2m19;
+ dN(7, 2) = _1pxt1py * _18zp9tx2py2p3z2m19;
dN.topRowsDivide(8, 64.0);
btScalar _m3m9x2m2x = -_3m9x2 - _2x;
- btScalar _p3m9x2m2x = _3m9x2 - _2x;
+ btScalar _p3m9x2m2x = _3m9x2 - _2x;
btScalar _1mx2t1m3x = _1mx2 * _1m3x;
btScalar _1mx2t1p3x = _1mx2 * _1p3x;
- dN( 8,0) = _m3m9x2m2x * _1myt1mz,
- dN( 8,1) = -_1mx2t1m3x * _1mz,
- dN( 8,2) = -_1mx2t1m3x * _1my;
- dN( 9,0) = _p3m9x2m2x * _1myt1mz,
- dN( 9,1) = -_1mx2t1p3x * _1mz,
- dN( 9,2) = -_1mx2t1p3x * _1my;
- dN(10,0) = _m3m9x2m2x * _1myt1pz,
- dN(10,1) = -_1mx2t1m3x * _1pz,
- dN(10,2) = _1mx2t1m3x * _1my;
- dN(11,0) = _p3m9x2m2x * _1myt1pz,
- dN(11,1) = -_1mx2t1p3x * _1pz,
- dN(11,2) = _1mx2t1p3x * _1my;
- dN(12,0) = _m3m9x2m2x * _1pyt1mz,
- dN(12,1) = _1mx2t1m3x * _1mz,
- dN(12,2) = -_1mx2t1m3x * _1py;
- dN(13,0) = _p3m9x2m2x * _1pyt1mz,
- dN(13,1) = _1mx2t1p3x * _1mz,
- dN(13,2) = -_1mx2t1p3x * _1py;
- dN(14,0) = _m3m9x2m2x * _1pyt1pz,
- dN(14,1) = _1mx2t1m3x * _1pz,
- dN(14,2) = _1mx2t1m3x * _1py;
- dN(15,0) = _p3m9x2m2x * _1pyt1pz,
- dN(15,1) = _1mx2t1p3x * _1pz,
- dN(15,2) = _1mx2t1p3x * _1py;
+ dN(8, 0) = _m3m9x2m2x * _1myt1mz,
+ dN(8, 1) = -_1mx2t1m3x * _1mz,
+ dN(8, 2) = -_1mx2t1m3x * _1my;
+ dN(9, 0) = _p3m9x2m2x * _1myt1mz,
+ dN(9, 1) = -_1mx2t1p3x * _1mz,
+ dN(9, 2) = -_1mx2t1p3x * _1my;
+ dN(10, 0) = _m3m9x2m2x * _1myt1pz,
+ dN(10, 1) = -_1mx2t1m3x * _1pz,
+ dN(10, 2) = _1mx2t1m3x * _1my;
+ dN(11, 0) = _p3m9x2m2x * _1myt1pz,
+ dN(11, 1) = -_1mx2t1p3x * _1pz,
+ dN(11, 2) = _1mx2t1p3x * _1my;
+ dN(12, 0) = _m3m9x2m2x * _1pyt1mz,
+ dN(12, 1) = _1mx2t1m3x * _1mz,
+ dN(12, 2) = -_1mx2t1m3x * _1py;
+ dN(13, 0) = _p3m9x2m2x * _1pyt1mz,
+ dN(13, 1) = _1mx2t1p3x * _1mz,
+ dN(13, 2) = -_1mx2t1p3x * _1py;
+ dN(14, 0) = _m3m9x2m2x * _1pyt1pz,
+ dN(14, 1) = _1mx2t1m3x * _1pz,
+ dN(14, 2) = _1mx2t1m3x * _1py;
+ dN(15, 0) = _p3m9x2m2x * _1pyt1pz,
+ dN(15, 1) = _1mx2t1p3x * _1pz,
+ dN(15, 2) = _1mx2t1p3x * _1py;
btScalar _m3m9y2m2y = -_3m9y2 - _2y;
- btScalar _p3m9y2m2y = _3m9y2 - _2y;
+ btScalar _p3m9y2m2y = _3m9y2 - _2y;
btScalar _1my2t1m3y = _1my2 * _1m3y;
btScalar _1my2t1p3y = _1my2 * _1p3y;
- dN(16,0) = -_1my2t1m3y * _1mz,
- dN(16,1) = _m3m9y2m2y * _1mxt1mz,
- dN(16,2) = -_1my2t1m3y * _1mx;
- dN(17,0) = -_1my2t1p3y * _1mz,
- dN(17,1) = _p3m9y2m2y * _1mxt1mz,
- dN(17,2) = -_1my2t1p3y * _1mx;
- dN(18,0) = _1my2t1m3y * _1mz,
- dN(18,1) = _m3m9y2m2y * _1pxt1mz,
- dN(18,2) = -_1my2t1m3y * _1px;
- dN(19,0) = _1my2t1p3y * _1mz,
- dN(19,1) = _p3m9y2m2y * _1pxt1mz,
- dN(19,2) = -_1my2t1p3y * _1px;
- dN(20,0) = -_1my2t1m3y * _1pz,
- dN(20,1) = _m3m9y2m2y * _1mxt1pz,
- dN(20,2) = _1my2t1m3y * _1mx;
- dN(21,0) = -_1my2t1p3y * _1pz,
- dN(21,1) = _p3m9y2m2y * _1mxt1pz,
- dN(21,2) = _1my2t1p3y * _1mx;
- dN(22,0) = _1my2t1m3y * _1pz,
- dN(22,1) = _m3m9y2m2y * _1pxt1pz,
- dN(22,2) = _1my2t1m3y * _1px;
- dN(23,0) = _1my2t1p3y * _1pz,
- dN(23,1) = _p3m9y2m2y * _1pxt1pz,
- dN(23,2) = _1my2t1p3y * _1px;
-
+ dN(16, 0) = -_1my2t1m3y * _1mz,
+ dN(16, 1) = _m3m9y2m2y * _1mxt1mz,
+ dN(16, 2) = -_1my2t1m3y * _1mx;
+ dN(17, 0) = -_1my2t1p3y * _1mz,
+ dN(17, 1) = _p3m9y2m2y * _1mxt1mz,
+ dN(17, 2) = -_1my2t1p3y * _1mx;
+ dN(18, 0) = _1my2t1m3y * _1mz,
+ dN(18, 1) = _m3m9y2m2y * _1pxt1mz,
+ dN(18, 2) = -_1my2t1m3y * _1px;
+ dN(19, 0) = _1my2t1p3y * _1mz,
+ dN(19, 1) = _p3m9y2m2y * _1pxt1mz,
+ dN(19, 2) = -_1my2t1p3y * _1px;
+ dN(20, 0) = -_1my2t1m3y * _1pz,
+ dN(20, 1) = _m3m9y2m2y * _1mxt1pz,
+ dN(20, 2) = _1my2t1m3y * _1mx;
+ dN(21, 0) = -_1my2t1p3y * _1pz,
+ dN(21, 1) = _p3m9y2m2y * _1mxt1pz,
+ dN(21, 2) = _1my2t1p3y * _1mx;
+ dN(22, 0) = _1my2t1m3y * _1pz,
+ dN(22, 1) = _m3m9y2m2y * _1pxt1pz,
+ dN(22, 2) = _1my2t1m3y * _1px;
+ dN(23, 0) = _1my2t1p3y * _1pz,
+ dN(23, 1) = _p3m9y2m2y * _1pxt1pz,
+ dN(23, 2) = _1my2t1p3y * _1px;
btScalar _m3m9z2m2z = -_3m9z2 - _2z;
- btScalar _p3m9z2m2z = _3m9z2 - _2z;
+ btScalar _p3m9z2m2z = _3m9z2 - _2z;
btScalar _1mz2t1m3z = _1mz2 * _1m3z;
btScalar _1mz2t1p3z = _1mz2 * _1p3z;
- dN(24,0) = -_1mz2t1m3z * _1my,
- dN(24,1) = -_1mz2t1m3z * _1mx,
- dN(24,2) = _m3m9z2m2z * _1mxt1my;
- dN(25,0) = -_1mz2t1p3z * _1my,
- dN(25,1) = -_1mz2t1p3z * _1mx,
- dN(25,2) = _p3m9z2m2z * _1mxt1my;
- dN(26,0) = -_1mz2t1m3z * _1py,
- dN(26,1) = _1mz2t1m3z * _1mx,
- dN(26,2) = _m3m9z2m2z * _1mxt1py;
- dN(27,0) = -_1mz2t1p3z * _1py,
- dN(27,1) = _1mz2t1p3z * _1mx,
- dN(27,2) = _p3m9z2m2z * _1mxt1py;
- dN(28,0) = _1mz2t1m3z * _1my,
- dN(28,1) = -_1mz2t1m3z * _1px,
- dN(28,2) = _m3m9z2m2z * _1pxt1my;
- dN(29,0) = _1mz2t1p3z * _1my,
- dN(29,1) = -_1mz2t1p3z * _1px,
- dN(29,2) = _p3m9z2m2z * _1pxt1my;
- dN(30,0) = _1mz2t1m3z * _1py,
- dN(30,1) = _1mz2t1m3z * _1px,
- dN(30,2) = _m3m9z2m2z * _1pxt1py;
- dN(31,0) = _1mz2t1p3z * _1py,
- dN(31,1) = _1mz2t1p3z * _1px,
- dN(31,2) = _p3m9z2m2z * _1pxt1py;
+ dN(24, 0) = -_1mz2t1m3z * _1my,
+ dN(24, 1) = -_1mz2t1m3z * _1mx,
+ dN(24, 2) = _m3m9z2m2z * _1mxt1my;
+ dN(25, 0) = -_1mz2t1p3z * _1my,
+ dN(25, 1) = -_1mz2t1p3z * _1mx,
+ dN(25, 2) = _p3m9z2m2z * _1mxt1my;
+ dN(26, 0) = -_1mz2t1m3z * _1py,
+ dN(26, 1) = _1mz2t1m3z * _1mx,
+ dN(26, 2) = _m3m9z2m2z * _1mxt1py;
+ dN(27, 0) = -_1mz2t1p3z * _1py,
+ dN(27, 1) = _1mz2t1p3z * _1mx,
+ dN(27, 2) = _p3m9z2m2z * _1mxt1py;
+ dN(28, 0) = _1mz2t1m3z * _1my,
+ dN(28, 1) = -_1mz2t1m3z * _1px,
+ dN(28, 2) = _m3m9z2m2z * _1pxt1my;
+ dN(29, 0) = _1mz2t1p3z * _1my,
+ dN(29, 1) = -_1mz2t1p3z * _1px,
+ dN(29, 2) = _p3m9z2m2z * _1pxt1my;
+ dN(30, 0) = _1mz2t1m3z * _1py,
+ dN(30, 1) = _1mz2t1m3z * _1px,
+ dN(30, 2) = _m3m9z2m2z * _1pxt1py;
+ dN(31, 0) = _1mz2t1p3z * _1py,
+ dN(31, 1) = _1mz2t1p3z * _1px,
+ dN(31, 2) = _p3m9z2m2z * _1pxt1py;
dN.bottomRowsMul(32u - 8u, 9.0 / 64.0);
-
}
return res;
}
-
-
bool btMiniSDF::interpolate(unsigned int field_id, double& dist, btVector3 const& x,
- btVector3* gradient) const
+ btVector3* gradient) const
{
btAssert(m_isValid);
if (!m_isValid)
@@ -459,15 +449,15 @@ bool btMiniSDF::interpolate(unsigned int field_id, double& dist, btVector3 const
if (!m_domain.contains(x))
return false;
- btVector3 tmpmi = ((x - m_domain.min())*(m_inv_cell_size));//.cast<unsigned int>().eval();
- unsigned int mi[3] = {(unsigned int )tmpmi[0],(unsigned int )tmpmi[1],(unsigned int )tmpmi[2]};
+ btVector3 tmpmi = ((x - m_domain.min()) * (m_inv_cell_size)); //.cast<unsigned int>().eval();
+ unsigned int mi[3] = {(unsigned int)tmpmi[0], (unsigned int)tmpmi[1], (unsigned int)tmpmi[2]};
if (mi[0] >= m_resolution[0])
- mi[0] = m_resolution[0]-1;
+ mi[0] = m_resolution[0] - 1;
if (mi[1] >= m_resolution[1])
- mi[1] = m_resolution[1]-1;
+ mi[1] = m_resolution[1] - 1;
if (mi[2] >= m_resolution[2])
- mi[2] = m_resolution[2]-1;
- btMultiIndex mui;
+ mi[2] = m_resolution[2] - 1;
+ btMultiIndex mui;
mui.ijk[0] = mi[0];
mui.ijk[1] = mi[1];
mui.ijk[2] = mi[2];
@@ -478,12 +468,12 @@ bool btMiniSDF::interpolate(unsigned int field_id, double& dist, btVector3 const
btAlignedBox3d sd = subdomain(i);
i = i_;
- btVector3 d = sd.m_max-sd.m_min;//.diagonal().eval();
+ btVector3 d = sd.m_max - sd.m_min; //.diagonal().eval();
btVector3 denom = (sd.max() - sd.min());
- btVector3 c0 = btVector3(2.0,2.0,2.0)/denom;
- btVector3 c1 = (sd.max() + sd.min())/denom;
- btVector3 xi = (c0*x - c1);
+ btVector3 c0 = btVector3(2.0, 2.0, 2.0) / denom;
+ btVector3 c1 = (sd.max() + sd.min()) / denom;
+ btVector3 xi = (c0 * x - c1);
btCell32 const& cell = m_cells[field_id][i];
if (!gradient)
@@ -497,7 +487,8 @@ bool btMiniSDF::interpolate(unsigned int field_id, double& dist, btVector3 const
double c = m_nodes[field_id][v];
if (c == DBL_MAX)
{
- return false;;
+ return false;
+ ;
}
phi += c * N[j];
}
@@ -529,4 +520,3 @@ bool btMiniSDF::interpolate(unsigned int field_id, double& dist, btVector3 const
dist = phi;
return true;
}
-
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btMiniSDF.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btMiniSDF.h
index 3de90e4f8a..b60fd102fd 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btMiniSDF.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btMiniSDF.h
@@ -5,7 +5,6 @@
#include "LinearMath/btAabbUtil2.h"
#include "LinearMath/btAlignedObjectArray.h"
-
struct btMultiIndex
{
unsigned int ijk[3];
@@ -25,7 +24,6 @@ struct btAlignedBox3d
{
return m_max;
}
-
bool contains(const btVector3& x) const
{
@@ -33,8 +31,8 @@ struct btAlignedBox3d
}
btAlignedBox3d(const btVector3& mn, const btVector3& mx)
- :m_min(mn),
- m_max(mx)
+ : m_min(mn),
+ m_max(mx)
{
}
@@ -47,39 +45,38 @@ struct btShapeMatrix
{
double m_vec[32];
- inline double& operator[](int i)
+ inline double& operator[](int i)
{
return m_vec[i];
}
- inline const double& operator[](int i) const
+ inline const double& operator[](int i) const
{
return m_vec[i];
}
-
};
struct btShapeGradients
{
- btVector3 m_vec[32];
+ btVector3 m_vec[32];
void topRowsDivide(int row, double denom)
{
- for (int i=0;i<row;i++)
+ for (int i = 0; i < row; i++)
{
m_vec[i] /= denom;
}
}
-
+
void bottomRowsMul(int row, double val)
{
- for (int i=32-row;i<32;i++)
+ for (int i = 32 - row; i < 32; i++)
{
m_vec[i] *= val;
}
}
-
- inline btScalar& operator()(int i, int j)
+
+ inline btScalar& operator()(int i, int j)
{
return m_vec[i][j];
}
@@ -92,7 +89,6 @@ struct btCell32
struct btMiniSDF
{
-
btAlignedBox3d m_domain;
unsigned int m_resolution[3];
btVector3 m_cell_size;
@@ -101,13 +97,12 @@ struct btMiniSDF
std::size_t m_n_fields;
bool m_isValid;
-
btAlignedObjectArray<btAlignedObjectArray<double> > m_nodes;
- btAlignedObjectArray<btAlignedObjectArray<btCell32 > > m_cells;
+ btAlignedObjectArray<btAlignedObjectArray<btCell32> > m_cells;
btAlignedObjectArray<btAlignedObjectArray<unsigned int> > m_cell_map;
btMiniSDF()
- :m_isValid(false)
+ : m_isValid(false)
{
}
bool load(const char* data, int size);
@@ -115,20 +110,18 @@ struct btMiniSDF
{
return m_isValid;
}
- unsigned int multiToSingleIndex(btMultiIndex const & ijk) const;
-
+ unsigned int multiToSingleIndex(btMultiIndex const& ijk) const;
+
btAlignedBox3d subdomain(btMultiIndex const& ijk) const;
btMultiIndex singleToMultiIndex(unsigned int l) const;
btAlignedBox3d subdomain(unsigned int l) const;
-
btShapeMatrix
shape_function_(btVector3 const& xi, btShapeGradients* gradient = 0) const;
bool interpolate(unsigned int field_id, double& dist, btVector3 const& x, btVector3* gradient) const;
};
-
-#endif //MINISDF_H
+#endif //MINISDF_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp
index 899ef50056..d4b6a651de 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp
@@ -13,65 +13,59 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#include "btMinkowskiSumShape.h"
-
-btMinkowskiSumShape::btMinkowskiSumShape(const btConvexShape* shapeA,const btConvexShape* shapeB)
-: btConvexInternalShape (),
-m_shapeA(shapeA),
-m_shapeB(shapeB)
+btMinkowskiSumShape::btMinkowskiSumShape(const btConvexShape* shapeA, const btConvexShape* shapeB)
+ : btConvexInternalShape(),
+ m_shapeA(shapeA),
+ m_shapeB(shapeB)
{
m_shapeType = MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE;
m_transA.setIdentity();
m_transB.setIdentity();
}
-btVector3 btMinkowskiSumShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+btVector3 btMinkowskiSumShape::localGetSupportingVertexWithoutMargin(const btVector3& vec) const
{
- btVector3 supVertexA = m_transA(m_shapeA->localGetSupportingVertexWithoutMargin(vec*m_transA.getBasis()));
- btVector3 supVertexB = m_transB(m_shapeB->localGetSupportingVertexWithoutMargin(-vec*m_transB.getBasis()));
- return supVertexA - supVertexB;
+ btVector3 supVertexA = m_transA(m_shapeA->localGetSupportingVertexWithoutMargin(vec * m_transA.getBasis()));
+ btVector3 supVertexB = m_transB(m_shapeB->localGetSupportingVertexWithoutMargin(-vec * m_transB.getBasis()));
+ return supVertexA - supVertexB;
}
-void btMinkowskiSumShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+void btMinkowskiSumShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
{
///@todo: could make recursive use of batching. probably this shape is not used frequently.
- for (int i=0;i<numVectors;i++)
+ for (int i = 0; i < numVectors; i++)
{
supportVerticesOut[i] = localGetSupportingVertexWithoutMargin(vectors[i]);
}
-
}
-
-
-btScalar btMinkowskiSumShape::getMargin() const
+btScalar btMinkowskiSumShape::getMargin() const
{
return m_shapeA->getMargin() + m_shapeB->getMargin();
}
-
-void btMinkowskiSumShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+void btMinkowskiSumShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
{
(void)mass;
//inertia of the AABB of the Minkowski sum
btTransform identity;
identity.setIdentity();
- btVector3 aabbMin,aabbMax;
- getAabb(identity,aabbMin,aabbMax);
+ btVector3 aabbMin, aabbMax;
+ getAabb(identity, aabbMin, aabbMax);
- btVector3 halfExtents = (aabbMax-aabbMin)*btScalar(0.5);
+ btVector3 halfExtents = (aabbMax - aabbMin) * btScalar(0.5);
btScalar margin = getMargin();
- btScalar lx=btScalar(2.)*(halfExtents.x()+margin);
- btScalar ly=btScalar(2.)*(halfExtents.y()+margin);
- btScalar lz=btScalar(2.)*(halfExtents.z()+margin);
- const btScalar x2 = lx*lx;
- const btScalar y2 = ly*ly;
- const btScalar z2 = lz*lz;
+ btScalar lx = btScalar(2.) * (halfExtents.x() + margin);
+ btScalar ly = btScalar(2.) * (halfExtents.y() + margin);
+ btScalar lz = btScalar(2.) * (halfExtents.z() + margin);
+ const btScalar x2 = lx * lx;
+ const btScalar y2 = ly * ly;
+ const btScalar z2 = lz * lz;
const btScalar scaledmass = mass * btScalar(0.08333333);
- inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2));
+ inertia = scaledmass * (btVector3(y2 + z2, x2 + z2, x2 + y2));
}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btMinkowskiSumShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btMinkowskiSumShape.h
index a3f9a47239..3b5150f6d5 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btMinkowskiSumShape.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btMinkowskiSumShape.h
@@ -17,46 +17,43 @@ subject to the following restrictions:
#define BT_MINKOWSKI_SUM_SHAPE_H
#include "btConvexInternalShape.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
/// The btMinkowskiSumShape is only for advanced users. This shape represents implicit based minkowski sum of two convex implicit shapes.
-ATTRIBUTE_ALIGNED16(class) btMinkowskiSumShape : public btConvexInternalShape
+ATTRIBUTE_ALIGNED16(class)
+btMinkowskiSumShape : public btConvexInternalShape
{
-
- btTransform m_transA;
- btTransform m_transB;
- const btConvexShape* m_shapeA;
- const btConvexShape* m_shapeB;
+ btTransform m_transA;
+ btTransform m_transB;
+ const btConvexShape* m_shapeA;
+ const btConvexShape* m_shapeB;
public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
-BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btMinkowskiSumShape(const btConvexShape* shapeA,const btConvexShape* shapeB);
-
- virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
-
- virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+ btMinkowskiSumShape(const btConvexShape* shapeA, const btConvexShape* shapeB);
+ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
- virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const;
- void setTransformA(const btTransform& transA) { m_transA = transA;}
- void setTransformB(const btTransform& transB) { m_transB = transB;}
+ virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
- const btTransform& getTransformA()const { return m_transA;}
- const btTransform& GetTransformB()const { return m_transB;}
+ void setTransformA(const btTransform& transA) { m_transA = transA; }
+ void setTransformB(const btTransform& transB) { m_transB = transB; }
+ const btTransform& getTransformA() const { return m_transA; }
+ const btTransform& GetTransformB() const { return m_transB; }
- virtual btScalar getMargin() const;
+ virtual btScalar getMargin() const;
- const btConvexShape* getShapeA() const { return m_shapeA;}
- const btConvexShape* getShapeB() const { return m_shapeB;}
+ const btConvexShape* getShapeA() const { return m_shapeA; }
+ const btConvexShape* getShapeB() const { return m_shapeB; }
- virtual const char* getName()const
+ virtual const char* getName() const
{
return "MinkowskiSum";
}
};
-#endif //BT_MINKOWSKI_SUM_SHAPE_H
+#endif //BT_MINKOWSKI_SUM_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btMultiSphereShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btMultiSphereShape.cpp
index 4195fa3138..c0cc55dfb0 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btMultiSphereShape.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btMultiSphereShape.cpp
@@ -13,7 +13,7 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-#if defined (_WIN32) || defined (__i386__)
+#if defined(_WIN32) || defined(__i386__)
#define BT_USE_SSE_IN_API
#endif
@@ -22,43 +22,41 @@ subject to the following restrictions:
#include "LinearMath/btQuaternion.h"
#include "LinearMath/btSerializer.h"
-btMultiSphereShape::btMultiSphereShape (const btVector3* positions,const btScalar* radi,int numSpheres)
-:btConvexInternalAabbCachingShape ()
+btMultiSphereShape::btMultiSphereShape(const btVector3* positions, const btScalar* radi, int numSpheres)
+ : btConvexInternalAabbCachingShape()
{
m_shapeType = MULTI_SPHERE_SHAPE_PROXYTYPE;
//btScalar startMargin = btScalar(BT_LARGE_FLOAT);
m_localPositionArray.resize(numSpheres);
m_radiArray.resize(numSpheres);
- for (int i=0;i<numSpheres;i++)
+ for (int i = 0; i < numSpheres; i++)
{
m_localPositionArray[i] = positions[i];
m_radiArray[i] = radi[i];
-
}
recalcLocalAabb();
-
}
#ifndef MIN
- #define MIN( _a, _b) ((_a) < (_b) ? (_a) : (_b))
+#define MIN(_a, _b) ((_a) < (_b) ? (_a) : (_b))
#endif
- btVector3 btMultiSphereShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const
+btVector3 btMultiSphereShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0) const
{
- btVector3 supVec(0,0,0);
+ btVector3 supVec(0, 0, 0);
btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
-
btVector3 vec = vec0;
btScalar lenSqr = vec.length2();
- if (lenSqr < (SIMD_EPSILON*SIMD_EPSILON))
+ if (lenSqr < (SIMD_EPSILON * SIMD_EPSILON))
{
- vec.setValue(1,0,0);
- } else
+ vec.setValue(1, 0, 0);
+ }
+ else
{
- btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
+ btScalar rlen = btScalar(1.) / btSqrt(lenSqr);
vec *= rlen;
}
@@ -69,32 +67,30 @@ btMultiSphereShape::btMultiSphereShape (const btVector3* positions,const btScala
const btScalar* rad = &m_radiArray[0];
int numSpheres = m_localPositionArray.size();
- for( int k = 0; k < numSpheres; k+= 128 )
+ for (int k = 0; k < numSpheres; k += 128)
{
btVector3 temp[128];
- int inner_count = MIN( numSpheres - k, 128 );
- for( long i = 0; i < inner_count; i++ )
- {
- temp[i] = (*pos)*m_localScaling +vec*m_localScaling*(*rad) - vec * getMargin();
- pos++;
- rad++;
- }
- long i = vec.maxDot( temp, inner_count, newDot);
- if( newDot > maxDot )
+ int inner_count = MIN(numSpheres - k, 128);
+ for (long i = 0; i < inner_count; i++)
+ {
+ temp[i] = (*pos) * m_localScaling + vec * m_localScaling * (*rad) - vec * getMargin();
+ pos++;
+ rad++;
+ }
+ long i = vec.maxDot(temp, inner_count, newDot);
+ if (newDot > maxDot)
{
maxDot = newDot;
supVec = temp[i];
}
- }
+ }
return supVec;
-
}
- void btMultiSphereShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+void btMultiSphereShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
{
-
- for (int j=0;j<numVectors;j++)
+ for (int j = 0; j < numVectors; j++)
{
btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
@@ -107,73 +103,63 @@ btMultiSphereShape::btMultiSphereShape (const btVector3* positions,const btScala
const btScalar* rad = &m_radiArray[0];
int numSpheres = m_localPositionArray.size();
- for( int k = 0; k < numSpheres; k+= 128 )
- {
- btVector3 temp[128];
- int inner_count = MIN( numSpheres - k, 128 );
- for( long i = 0; i < inner_count; i++ )
- {
- temp[i] = (*pos)*m_localScaling +vec*m_localScaling*(*rad) - vec * getMargin();
- pos++;
- rad++;
- }
- long i = vec.maxDot( temp, inner_count, newDot);
- if( newDot > maxDot )
- {
- maxDot = newDot;
- supportVerticesOut[j] = temp[i];
- }
- }
-
+ for (int k = 0; k < numSpheres; k += 128)
+ {
+ btVector3 temp[128];
+ int inner_count = MIN(numSpheres - k, 128);
+ for (long i = 0; i < inner_count; i++)
+ {
+ temp[i] = (*pos) * m_localScaling + vec * m_localScaling * (*rad) - vec * getMargin();
+ pos++;
+ rad++;
+ }
+ long i = vec.maxDot(temp, inner_count, newDot);
+ if (newDot > maxDot)
+ {
+ maxDot = newDot;
+ supportVerticesOut[j] = temp[i];
+ }
+ }
}
}
-
-
-
-
-
-
-
-void btMultiSphereShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+void btMultiSphereShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
{
//as an approximation, take the inertia of the box that bounds the spheres
- btVector3 localAabbMin,localAabbMax;
- getCachedLocalAabb(localAabbMin,localAabbMax);
- btVector3 halfExtents = (localAabbMax-localAabbMin)*btScalar(0.5);
+ btVector3 localAabbMin, localAabbMax;
+ getCachedLocalAabb(localAabbMin, localAabbMax);
+ btVector3 halfExtents = (localAabbMax - localAabbMin) * btScalar(0.5);
- btScalar lx=btScalar(2.)*(halfExtents.x());
- btScalar ly=btScalar(2.)*(halfExtents.y());
- btScalar lz=btScalar(2.)*(halfExtents.z());
-
- inertia.setValue(mass/(btScalar(12.0)) * (ly*ly + lz*lz),
- mass/(btScalar(12.0)) * (lx*lx + lz*lz),
- mass/(btScalar(12.0)) * (lx*lx + ly*ly));
+ btScalar lx = btScalar(2.) * (halfExtents.x());
+ btScalar ly = btScalar(2.) * (halfExtents.y());
+ btScalar lz = btScalar(2.) * (halfExtents.z());
+ inertia.setValue(mass / (btScalar(12.0)) * (ly * ly + lz * lz),
+ mass / (btScalar(12.0)) * (lx * lx + lz * lz),
+ mass / (btScalar(12.0)) * (lx * lx + ly * ly));
}
-
///fills the dataBuffer and returns the struct name (and 0 on failure)
-const char* btMultiSphereShape::serialize(void* dataBuffer, btSerializer* serializer) const
+const char* btMultiSphereShape::serialize(void* dataBuffer, btSerializer* serializer) const
{
- btMultiSphereShapeData* shapeData = (btMultiSphereShapeData*) dataBuffer;
+ btMultiSphereShapeData* shapeData = (btMultiSphereShapeData*)dataBuffer;
btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData, serializer);
int numElem = m_localPositionArray.size();
- shapeData->m_localPositionArrayPtr = numElem ? (btPositionAndRadius*)serializer->getUniquePointer((void*)&m_localPositionArray[0]): 0;
-
+ shapeData->m_localPositionArrayPtr = numElem ? (btPositionAndRadius*)serializer->getUniquePointer((void*)&m_localPositionArray[0]) : 0;
+
shapeData->m_localPositionArraySize = numElem;
if (numElem)
{
- btChunk* chunk = serializer->allocate(sizeof(btPositionAndRadius),numElem);
+ btChunk* chunk = serializer->allocate(sizeof(btPositionAndRadius), numElem);
btPositionAndRadius* memPtr = (btPositionAndRadius*)chunk->m_oldPtr;
- for (int i=0;i<numElem;i++,memPtr++)
+ for (int i = 0; i < numElem; i++, memPtr++)
{
m_localPositionArray[i].serializeFloat(memPtr->m_pos);
memPtr->m_radius = float(m_radiArray[i]);
}
- serializer->finalizeChunk(chunk,"btPositionAndRadius",BT_ARRAY_CODE,(void*)&m_localPositionArray[0]);
+ serializer->finalizeChunk(chunk, "btPositionAndRadius", BT_ARRAY_CODE, (void*)&m_localPositionArray[0]);
}
// Fill padding with zeros to appease msan.
@@ -181,5 +167,3 @@ const char* btMultiSphereShape::serialize(void* dataBuffer, btSerializer* serial
return "btMultiSphereShapeData";
}
-
-
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btMultiSphereShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btMultiSphereShape.h
index 5d3b402684..2d79c07ca4 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btMultiSphereShape.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btMultiSphereShape.h
@@ -17,69 +17,65 @@ subject to the following restrictions:
#define BT_MULTI_SPHERE_MINKOWSKI_H
#include "btConvexInternalShape.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
#include "LinearMath/btAlignedObjectArray.h"
#include "LinearMath/btAabbUtil2.h"
-
-
///The btMultiSphereShape represents the convex hull of a collection of spheres. You can create special capsules or other smooth volumes.
///It is possible to animate the spheres for deformation, but call 'recalcLocalAabb' after changing any sphere position/radius
-ATTRIBUTE_ALIGNED16(class) btMultiSphereShape : public btConvexInternalAabbCachingShape
+ATTRIBUTE_ALIGNED16(class)
+btMultiSphereShape : public btConvexInternalAabbCachingShape
{
-
btAlignedObjectArray<btVector3> m_localPositionArray;
- btAlignedObjectArray<btScalar> m_radiArray;
-
+ btAlignedObjectArray<btScalar> m_radiArray;
+
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btMultiSphereShape (const btVector3* positions,const btScalar* radi,int numSpheres);
+
+ btMultiSphereShape(const btVector3* positions, const btScalar* radi, int numSpheres);
///CollisionShape Interface
- virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+ virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
/// btConvexShape Interface
- virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
- virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
-
- int getSphereCount() const
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const;
+
+ int getSphereCount() const
{
return m_localPositionArray.size();
}
- const btVector3& getSpherePosition(int index) const
+ const btVector3& getSpherePosition(int index) const
{
return m_localPositionArray[index];
}
- btScalar getSphereRadius(int index) const
+ btScalar getSphereRadius(int index) const
{
return m_radiArray[index];
}
-
- virtual const char* getName()const
+ virtual const char* getName() const
{
return "MultiSphere";
}
- virtual int calculateSerializeBufferSize() const;
+ virtual int calculateSerializeBufferSize() const;
///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-
-
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
};
-
-struct btPositionAndRadius
+struct btPositionAndRadius
{
- btVector3FloatData m_pos;
- float m_radius;
+ btVector3FloatData m_pos;
+ float m_radius;
};
+// clang-format off
+
struct btMultiSphereShapeData
{
btConvexInternalShapeData m_convexInternalShapeData;
@@ -89,13 +85,11 @@ struct btMultiSphereShapeData
char m_padding[4];
};
+// clang-format on
-
-SIMD_FORCE_INLINE int btMultiSphereShape::calculateSerializeBufferSize() const
+SIMD_FORCE_INLINE int btMultiSphereShape::calculateSerializeBufferSize() const
{
return sizeof(btMultiSphereShapeData);
}
-
-
-#endif //BT_MULTI_SPHERE_MINKOWSKI_H
+#endif //BT_MULTI_SPHERE_MINKOWSKI_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp
index 58799ac96a..30108c9e7b 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp
@@ -19,27 +19,25 @@ subject to the following restrictions:
#include "BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h"
//#include "BulletCollision/CollisionShapes/btOptimizedBvh.h"
-
///Obtains the material for a specific triangle
-const btMaterial * btMultimaterialTriangleMeshShape::getMaterialProperties(int partID, int triIndex)
+const btMaterial *btMultimaterialTriangleMeshShape::getMaterialProperties(int partID, int triIndex)
{
- const unsigned char * materialBase = 0;
- int numMaterials;
- PHY_ScalarType materialType;
- int materialStride;
- const unsigned char * triangleMaterialBase = 0;
- int numTriangles;
- int triangleMaterialStride;
- PHY_ScalarType triangleType;
-
- ((btTriangleIndexVertexMaterialArray*)m_meshInterface)->getLockedReadOnlyMaterialBase(&materialBase, numMaterials, materialType, materialStride,
- &triangleMaterialBase, numTriangles, triangleMaterialStride, triangleType, partID);
-
- // return the pointer to the place with the friction for the triangle
- // TODO: This depends on whether it's a moving mesh or not
- // BUG IN GIMPACT
- //return (btScalar*)(&materialBase[triangleMaterialBase[(triIndex-1) * triangleMaterialStride] * materialStride]);
- int * matInd = (int *)(&(triangleMaterialBase[(triIndex * triangleMaterialStride)]));
- btMaterial *matVal = (btMaterial *)(&(materialBase[*matInd * materialStride]));
- return (matVal);
+ const unsigned char *materialBase = 0;
+ int numMaterials;
+ PHY_ScalarType materialType;
+ int materialStride;
+ const unsigned char *triangleMaterialBase = 0;
+ int numTriangles;
+ int triangleMaterialStride;
+ PHY_ScalarType triangleType;
+
+ ((btTriangleIndexVertexMaterialArray *)m_meshInterface)->getLockedReadOnlyMaterialBase(&materialBase, numMaterials, materialType, materialStride, &triangleMaterialBase, numTriangles, triangleMaterialStride, triangleType, partID);
+
+ // return the pointer to the place with the friction for the triangle
+ // TODO: This depends on whether it's a moving mesh or not
+ // BUG IN GIMPACT
+ //return (btScalar*)(&materialBase[triangleMaterialBase[(triIndex-1) * triangleMaterialStride] * materialStride]);
+ int *matInd = (int *)(&(triangleMaterialBase[(triIndex * triangleMaterialStride)]));
+ btMaterial *matVal = (btMaterial *)(&(materialBase[*matInd * materialStride]));
+ return (matVal);
}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h
index 5ebaede4a8..d1d42f8e04 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h
@@ -22,82 +22,80 @@ subject to the following restrictions:
#include "btMaterial.h"
///The BvhTriangleMaterialMeshShape extends the btBvhTriangleMeshShape. Its main contribution is the interface into a material array, which allows per-triangle friction and restitution.
-ATTRIBUTE_ALIGNED16(class) btMultimaterialTriangleMeshShape : public btBvhTriangleMeshShape
+ATTRIBUTE_ALIGNED16(class)
+btMultimaterialTriangleMeshShape : public btBvhTriangleMeshShape
{
- btAlignedObjectArray <btMaterial*> m_materialList;
+ btAlignedObjectArray<btMaterial *> m_materialList;
public:
-
BT_DECLARE_ALIGNED_ALLOCATOR();
- btMultimaterialTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh = true):
- btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression, buildBvh)
- {
- m_shapeType = MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE;
-
- const unsigned char *vertexbase;
- int numverts;
- PHY_ScalarType type;
- int stride;
- const unsigned char *indexbase;
- int indexstride;
- int numfaces;
- PHY_ScalarType indicestype;
-
- //m_materialLookup = (int**)(btAlignedAlloc(sizeof(int*) * meshInterface->getNumSubParts(), 16));
-
- for(int i = 0; i < meshInterface->getNumSubParts(); i++)
- {
- m_meshInterface->getLockedReadOnlyVertexIndexBase(
- &vertexbase,
- numverts,
- type,
- stride,
- &indexbase,
- indexstride,
- numfaces,
- indicestype,
- i);
- //m_materialLookup[i] = (int*)(btAlignedAlloc(sizeof(int) * numfaces, 16));
- }
- }
+ btMultimaterialTriangleMeshShape(btStridingMeshInterface * meshInterface, bool useQuantizedAabbCompression, bool buildBvh = true) : btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression, buildBvh)
+ {
+ m_shapeType = MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE;
+
+ const unsigned char *vertexbase;
+ int numverts;
+ PHY_ScalarType type;
+ int stride;
+ const unsigned char *indexbase;
+ int indexstride;
+ int numfaces;
+ PHY_ScalarType indicestype;
+
+ //m_materialLookup = (int**)(btAlignedAlloc(sizeof(int*) * meshInterface->getNumSubParts(), 16));
+
+ for (int i = 0; i < meshInterface->getNumSubParts(); i++)
+ {
+ m_meshInterface->getLockedReadOnlyVertexIndexBase(
+ &vertexbase,
+ numverts,
+ type,
+ stride,
+ &indexbase,
+ indexstride,
+ numfaces,
+ indicestype,
+ i);
+ //m_materialLookup[i] = (int*)(btAlignedAlloc(sizeof(int) * numfaces, 16));
+ }
+ }
///optionally pass in a larger bvh aabb, used for quantization. This allows for deformations within this aabb
- btMultimaterialTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax, bool buildBvh = true):
- btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression, bvhAabbMin, bvhAabbMax, buildBvh)
- {
- m_shapeType = MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE;
-
- const unsigned char *vertexbase;
- int numverts;
- PHY_ScalarType type;
- int stride;
- const unsigned char *indexbase;
- int indexstride;
- int numfaces;
- PHY_ScalarType indicestype;
-
- //m_materialLookup = (int**)(btAlignedAlloc(sizeof(int*) * meshInterface->getNumSubParts(), 16));
-
- for(int i = 0; i < meshInterface->getNumSubParts(); i++)
- {
- m_meshInterface->getLockedReadOnlyVertexIndexBase(
- &vertexbase,
- numverts,
- type,
- stride,
- &indexbase,
- indexstride,
- numfaces,
- indicestype,
- i);
- //m_materialLookup[i] = (int*)(btAlignedAlloc(sizeof(int) * numfaces * 2, 16));
- }
- }
-
- virtual ~btMultimaterialTriangleMeshShape()
- {
-/*
+ btMultimaterialTriangleMeshShape(btStridingMeshInterface * meshInterface, bool useQuantizedAabbCompression, const btVector3 &bvhAabbMin, const btVector3 &bvhAabbMax, bool buildBvh = true) : btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression, bvhAabbMin, bvhAabbMax, buildBvh)
+ {
+ m_shapeType = MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE;
+
+ const unsigned char *vertexbase;
+ int numverts;
+ PHY_ScalarType type;
+ int stride;
+ const unsigned char *indexbase;
+ int indexstride;
+ int numfaces;
+ PHY_ScalarType indicestype;
+
+ //m_materialLookup = (int**)(btAlignedAlloc(sizeof(int*) * meshInterface->getNumSubParts(), 16));
+
+ for (int i = 0; i < meshInterface->getNumSubParts(); i++)
+ {
+ m_meshInterface->getLockedReadOnlyVertexIndexBase(
+ &vertexbase,
+ numverts,
+ type,
+ stride,
+ &indexbase,
+ indexstride,
+ numfaces,
+ indicestype,
+ i);
+ //m_materialLookup[i] = (int*)(btAlignedAlloc(sizeof(int) * numfaces * 2, 16));
+ }
+ }
+
+ virtual ~btMultimaterialTriangleMeshShape()
+ {
+ /*
for(int i = 0; i < m_meshInterface->getNumSubParts(); i++)
{
btAlignedFree(m_materialValues[i]);
@@ -106,14 +104,12 @@ public:
btAlignedFree(m_materialValues);
m_materialLookup = NULL;
*/
- }
+ }
//debugging
- virtual const char* getName()const {return "MULTIMATERIALTRIANGLEMESH";}
-
- ///Obtains the material for a specific triangle
- const btMaterial * getMaterialProperties(int partID, int triIndex);
+ virtual const char *getName() const { return "MULTIMATERIALTRIANGLEMESH"; }
-}
-;
+ ///Obtains the material for a specific triangle
+ const btMaterial *getMaterialProperties(int partID, int triIndex);
+};
-#endif //BT_BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H
+#endif //BT_BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btOptimizedBvh.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btOptimizedBvh.cpp
index 6f36775f7c..687399e0a9 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btOptimizedBvh.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btOptimizedBvh.cpp
@@ -13,51 +13,46 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#include "btOptimizedBvh.h"
#include "btStridingMeshInterface.h"
#include "LinearMath/btAabbUtil2.h"
#include "LinearMath/btIDebugDraw.h"
-
btOptimizedBvh::btOptimizedBvh()
-{
+{
}
btOptimizedBvh::~btOptimizedBvh()
{
}
-
void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax)
{
m_useQuantization = useQuantizedAabbCompression;
-
// NodeArray triangleNodes;
- struct NodeTriangleCallback : public btInternalTriangleIndexCallback
+ struct NodeTriangleCallback : public btInternalTriangleIndexCallback
{
-
- NodeArray& m_triangleNodes;
+ NodeArray& m_triangleNodes;
NodeTriangleCallback& operator=(NodeTriangleCallback& other)
{
m_triangleNodes.copyFromArray(other.m_triangleNodes);
return *this;
}
-
- NodeTriangleCallback(NodeArray& triangleNodes)
- :m_triangleNodes(triangleNodes)
+
+ NodeTriangleCallback(NodeArray& triangleNodes)
+ : m_triangleNodes(triangleNodes)
{
}
- virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex)
+ virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
{
btOptimizedBvhNode node;
- btVector3 aabbMin,aabbMax;
- aabbMin.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
- aabbMax.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
+ btVector3 aabbMin, aabbMax;
+ aabbMin.setValue(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
+ aabbMax.setValue(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
aabbMin.setMin(triangle[0]);
aabbMax.setMax(triangle[0]);
aabbMin.setMin(triangle[1]);
@@ -70,17 +65,17 @@ void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantized
node.m_aabbMaxOrg = aabbMax;
node.m_escapeIndex = -1;
-
+
//for child nodes
node.m_subPart = partId;
node.m_triangleIndex = triangleIndex;
m_triangleNodes.push_back(node);
}
};
- struct QuantizedNodeTriangleCallback : public btInternalTriangleIndexCallback
+ struct QuantizedNodeTriangleCallback : public btInternalTriangleIndexCallback
{
- QuantizedNodeArray& m_triangleNodes;
- const btQuantizedBvh* m_optimizedTree; // for quantization
+ QuantizedNodeArray& m_triangleNodes;
+ const btQuantizedBvh* m_optimizedTree; // for quantization
QuantizedNodeTriangleCallback& operator=(QuantizedNodeTriangleCallback& other)
{
@@ -89,23 +84,23 @@ void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantized
return *this;
}
- QuantizedNodeTriangleCallback(QuantizedNodeArray& triangleNodes,const btQuantizedBvh* tree)
- :m_triangleNodes(triangleNodes),m_optimizedTree(tree)
+ QuantizedNodeTriangleCallback(QuantizedNodeArray& triangleNodes, const btQuantizedBvh* tree)
+ : m_triangleNodes(triangleNodes), m_optimizedTree(tree)
{
}
- virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex)
+ virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
{
// The partId and triangle index must fit in the same (positive) integer
- btAssert(partId < (1<<MAX_NUM_PARTS_IN_BITS));
- btAssert(triangleIndex < (1<<(31-MAX_NUM_PARTS_IN_BITS)));
+ btAssert(partId < (1 << MAX_NUM_PARTS_IN_BITS));
+ btAssert(triangleIndex < (1 << (31 - MAX_NUM_PARTS_IN_BITS)));
//negative indices are reserved for escapeIndex
- btAssert(triangleIndex>=0);
+ btAssert(triangleIndex >= 0);
btQuantizedBvhNode node;
- btVector3 aabbMin,aabbMax;
- aabbMin.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
- aabbMax.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
+ btVector3 aabbMin, aabbMax;
+ aabbMin.setValue(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
+ aabbMax.setValue(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
aabbMin.setMin(triangle[0]);
aabbMax.setMax(triangle[0]);
aabbMin.setMin(triangle[1]);
@@ -132,59 +127,52 @@ void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantized
aabbMin.setZ(aabbMin.z() - MIN_AABB_HALF_DIMENSION);
}
- m_optimizedTree->quantize(&node.m_quantizedAabbMin[0],aabbMin,0);
- m_optimizedTree->quantize(&node.m_quantizedAabbMax[0],aabbMax,1);
+ m_optimizedTree->quantize(&node.m_quantizedAabbMin[0], aabbMin, 0);
+ m_optimizedTree->quantize(&node.m_quantizedAabbMax[0], aabbMax, 1);
- node.m_escapeIndexOrTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | triangleIndex;
+ node.m_escapeIndexOrTriangleIndex = (partId << (31 - MAX_NUM_PARTS_IN_BITS)) | triangleIndex;
m_triangleNodes.push_back(node);
}
};
-
-
int numLeafNodes = 0;
-
if (m_useQuantization)
{
-
//initialize quantization values
- setQuantizationValues(bvhAabbMin,bvhAabbMax);
+ setQuantizationValues(bvhAabbMin, bvhAabbMax);
- QuantizedNodeTriangleCallback callback(m_quantizedLeafNodes,this);
+ QuantizedNodeTriangleCallback callback(m_quantizedLeafNodes, this);
-
- triangles->InternalProcessAllTriangles(&callback,m_bvhAabbMin,m_bvhAabbMax);
+ triangles->InternalProcessAllTriangles(&callback, m_bvhAabbMin, m_bvhAabbMax);
//now we have an array of leafnodes in m_leafNodes
numLeafNodes = m_quantizedLeafNodes.size();
-
- m_quantizedContiguousNodes.resize(2*numLeafNodes);
-
-
- } else
+ m_quantizedContiguousNodes.resize(2 * numLeafNodes);
+ }
+ else
{
- NodeTriangleCallback callback(m_leafNodes);
+ NodeTriangleCallback callback(m_leafNodes);
- btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
- btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+ btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
+ btVector3 aabbMax(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
- triangles->InternalProcessAllTriangles(&callback,aabbMin,aabbMax);
+ triangles->InternalProcessAllTriangles(&callback, aabbMin, aabbMax);
//now we have an array of leafnodes in m_leafNodes
numLeafNodes = m_leafNodes.size();
- m_contiguousNodes.resize(2*numLeafNodes);
+ m_contiguousNodes.resize(2 * numLeafNodes);
}
m_curNodeIndex = 0;
- buildTree(0,numLeafNodes);
+ buildTree(0, numLeafNodes);
///if the entire tree is small then subtree size, we need to create a header info for the tree
- if(m_useQuantization && !m_SubtreeHeaders.size())
+ if (m_useQuantization && !m_SubtreeHeaders.size())
{
btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[0]);
@@ -200,37 +188,29 @@ void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantized
m_leafNodes.clear();
}
-
-
-
-void btOptimizedBvh::refit(btStridingMeshInterface* meshInterface,const btVector3& aabbMin,const btVector3& aabbMax)
+void btOptimizedBvh::refit(btStridingMeshInterface* meshInterface, const btVector3& aabbMin, const btVector3& aabbMax)
{
if (m_useQuantization)
{
+ setQuantizationValues(aabbMin, aabbMax);
- setQuantizationValues(aabbMin,aabbMax);
-
- updateBvhNodes(meshInterface,0,m_curNodeIndex,0);
+ updateBvhNodes(meshInterface, 0, m_curNodeIndex, 0);
///now update all subtree headers
int i;
- for (i=0;i<m_SubtreeHeaders.size();i++)
+ for (i = 0; i < m_SubtreeHeaders.size(); i++)
{
btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[subtree.m_rootNodeIndex]);
}
-
- } else
+ }
+ else
{
-
}
}
-
-
-
-void btOptimizedBvh::refitPartial(btStridingMeshInterface* meshInterface,const btVector3& aabbMin,const btVector3& aabbMax)
+void btOptimizedBvh::refitPartial(btStridingMeshInterface* meshInterface, const btVector3& aabbMin, const btVector3& aabbMax)
{
//incrementally initialize quantization values
btAssert(m_useQuantization);
@@ -245,147 +225,135 @@ void btOptimizedBvh::refitPartial(btStridingMeshInterface* meshInterface,const b
///we should update all quantization values, using updateBvhNodes(meshInterface);
///but we only update chunks that overlap the given aabb
-
- unsigned short quantizedQueryAabbMin[3];
- unsigned short quantizedQueryAabbMax[3];
- quantize(&quantizedQueryAabbMin[0],aabbMin,0);
- quantize(&quantizedQueryAabbMax[0],aabbMax,1);
+ unsigned short quantizedQueryAabbMin[3];
+ unsigned short quantizedQueryAabbMax[3];
+
+ quantize(&quantizedQueryAabbMin[0], aabbMin, 0);
+ quantize(&quantizedQueryAabbMax[0], aabbMax, 1);
int i;
- for (i=0;i<this->m_SubtreeHeaders.size();i++)
+ for (i = 0; i < this->m_SubtreeHeaders.size(); i++)
{
btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
//PCK: unsigned instead of bool
- unsigned overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax);
+ unsigned overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin, quantizedQueryAabbMax, subtree.m_quantizedAabbMin, subtree.m_quantizedAabbMax);
if (overlap != 0)
{
- updateBvhNodes(meshInterface,subtree.m_rootNodeIndex,subtree.m_rootNodeIndex+subtree.m_subtreeSize,i);
+ updateBvhNodes(meshInterface, subtree.m_rootNodeIndex, subtree.m_rootNodeIndex + subtree.m_subtreeSize, i);
subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[subtree.m_rootNodeIndex]);
}
}
-
}
-void btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface,int firstNode,int endNode,int index)
+void btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface, int firstNode, int endNode, int index)
{
(void)index;
btAssert(m_useQuantization);
- int curNodeSubPart=-1;
+ int curNodeSubPart = -1;
//get access info to trianglemesh data
- const unsigned char *vertexbase = 0;
- int numverts = 0;
- PHY_ScalarType type = PHY_INTEGER;
- int stride = 0;
- const unsigned char *indexbase = 0;
- int indexstride = 0;
- int numfaces = 0;
- PHY_ScalarType indicestype = PHY_INTEGER;
-
- btVector3 triangleVerts[3];
- btVector3 aabbMin,aabbMax;
- const btVector3& meshScaling = meshInterface->getScaling();
-
- int i;
- for (i=endNode-1;i>=firstNode;i--)
+ const unsigned char* vertexbase = 0;
+ int numverts = 0;
+ PHY_ScalarType type = PHY_INTEGER;
+ int stride = 0;
+ const unsigned char* indexbase = 0;
+ int indexstride = 0;
+ int numfaces = 0;
+ PHY_ScalarType indicestype = PHY_INTEGER;
+
+ btVector3 triangleVerts[3];
+ btVector3 aabbMin, aabbMax;
+ const btVector3& meshScaling = meshInterface->getScaling();
+
+ int i;
+ for (i = endNode - 1; i >= firstNode; i--)
+ {
+ btQuantizedBvhNode& curNode = m_quantizedContiguousNodes[i];
+ if (curNode.isLeafNode())
{
+ //recalc aabb from triangle data
+ int nodeSubPart = curNode.getPartId();
+ int nodeTriangleIndex = curNode.getTriangleIndex();
+ if (nodeSubPart != curNodeSubPart)
+ {
+ if (curNodeSubPart >= 0)
+ meshInterface->unLockReadOnlyVertexBase(curNodeSubPart);
+ meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase, numverts, type, stride, &indexbase, indexstride, numfaces, indicestype, nodeSubPart);
+ curNodeSubPart = nodeSubPart;
+ btAssert(indicestype == PHY_INTEGER || indicestype == PHY_SHORT);
+ }
+ //triangles->getLockedReadOnlyVertexIndexBase(vertexBase,numVerts,
- btQuantizedBvhNode& curNode = m_quantizedContiguousNodes[i];
- if (curNode.isLeafNode())
+ unsigned int* gfxbase = (unsigned int*)(indexbase + nodeTriangleIndex * indexstride);
+
+ for (int j = 2; j >= 0; j--)
{
- //recalc aabb from triangle data
- int nodeSubPart = curNode.getPartId();
- int nodeTriangleIndex = curNode.getTriangleIndex();
- if (nodeSubPart != curNodeSubPart)
+ int graphicsindex = indicestype == PHY_SHORT ? ((unsigned short*)gfxbase)[j] : gfxbase[j];
+ if (type == PHY_FLOAT)
{
- if (curNodeSubPart >= 0)
- meshInterface->unLockReadOnlyVertexBase(curNodeSubPart);
- meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase,numverts, type,stride,&indexbase,indexstride,numfaces,indicestype,nodeSubPart);
-
- curNodeSubPart = nodeSubPart;
- btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
+ float* graphicsbase = (float*)(vertexbase + graphicsindex * stride);
+ triangleVerts[j] = btVector3(
+ graphicsbase[0] * meshScaling.getX(),
+ graphicsbase[1] * meshScaling.getY(),
+ graphicsbase[2] * meshScaling.getZ());
}
- //triangles->getLockedReadOnlyVertexIndexBase(vertexBase,numVerts,
-
- unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
-
-
- for (int j=2;j>=0;j--)
+ else
{
-
- int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
- if (type == PHY_FLOAT)
- {
- float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
- triangleVerts[j] = btVector3(
- graphicsbase[0]*meshScaling.getX(),
- graphicsbase[1]*meshScaling.getY(),
- graphicsbase[2]*meshScaling.getZ());
- }
- else
- {
- double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
- triangleVerts[j] = btVector3( btScalar(graphicsbase[0]*meshScaling.getX()), btScalar(graphicsbase[1]*meshScaling.getY()), btScalar(graphicsbase[2]*meshScaling.getZ()));
- }
+ double* graphicsbase = (double*)(vertexbase + graphicsindex * stride);
+ triangleVerts[j] = btVector3(btScalar(graphicsbase[0] * meshScaling.getX()), btScalar(graphicsbase[1] * meshScaling.getY()), btScalar(graphicsbase[2] * meshScaling.getZ()));
}
+ }
+ aabbMin.setValue(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
+ aabbMax.setValue(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
+ aabbMin.setMin(triangleVerts[0]);
+ aabbMax.setMax(triangleVerts[0]);
+ aabbMin.setMin(triangleVerts[1]);
+ aabbMax.setMax(triangleVerts[1]);
+ aabbMin.setMin(triangleVerts[2]);
+ aabbMax.setMax(triangleVerts[2]);
+
+ quantize(&curNode.m_quantizedAabbMin[0], aabbMin, 0);
+ quantize(&curNode.m_quantizedAabbMax[0], aabbMax, 1);
+ }
+ else
+ {
+ //combine aabb from both children
-
- aabbMin.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
- aabbMax.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
- aabbMin.setMin(triangleVerts[0]);
- aabbMax.setMax(triangleVerts[0]);
- aabbMin.setMin(triangleVerts[1]);
- aabbMax.setMax(triangleVerts[1]);
- aabbMin.setMin(triangleVerts[2]);
- aabbMax.setMax(triangleVerts[2]);
-
- quantize(&curNode.m_quantizedAabbMin[0],aabbMin,0);
- quantize(&curNode.m_quantizedAabbMax[0],aabbMax,1);
-
- } else
- {
- //combine aabb from both children
+ btQuantizedBvhNode* leftChildNode = &m_quantizedContiguousNodes[i + 1];
- btQuantizedBvhNode* leftChildNode = &m_quantizedContiguousNodes[i+1];
-
- btQuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? &m_quantizedContiguousNodes[i+2] :
- &m_quantizedContiguousNodes[i+1+leftChildNode->getEscapeIndex()];
-
+ btQuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? &m_quantizedContiguousNodes[i + 2] : &m_quantizedContiguousNodes[i + 1 + leftChildNode->getEscapeIndex()];
+ {
+ for (int i = 0; i < 3; i++)
{
- for (int i=0;i<3;i++)
- {
- curNode.m_quantizedAabbMin[i] = leftChildNode->m_quantizedAabbMin[i];
- if (curNode.m_quantizedAabbMin[i]>rightChildNode->m_quantizedAabbMin[i])
- curNode.m_quantizedAabbMin[i]=rightChildNode->m_quantizedAabbMin[i];
-
- curNode.m_quantizedAabbMax[i] = leftChildNode->m_quantizedAabbMax[i];
- if (curNode.m_quantizedAabbMax[i] < rightChildNode->m_quantizedAabbMax[i])
- curNode.m_quantizedAabbMax[i] = rightChildNode->m_quantizedAabbMax[i];
- }
+ curNode.m_quantizedAabbMin[i] = leftChildNode->m_quantizedAabbMin[i];
+ if (curNode.m_quantizedAabbMin[i] > rightChildNode->m_quantizedAabbMin[i])
+ curNode.m_quantizedAabbMin[i] = rightChildNode->m_quantizedAabbMin[i];
+
+ curNode.m_quantizedAabbMax[i] = leftChildNode->m_quantizedAabbMax[i];
+ if (curNode.m_quantizedAabbMax[i] < rightChildNode->m_quantizedAabbMax[i])
+ curNode.m_quantizedAabbMax[i] = rightChildNode->m_quantizedAabbMax[i];
}
}
-
}
+ }
- if (curNodeSubPart >= 0)
- meshInterface->unLockReadOnlyVertexBase(curNodeSubPart);
-
-
+ if (curNodeSubPart >= 0)
+ meshInterface->unLockReadOnlyVertexBase(curNodeSubPart);
}
///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
-btOptimizedBvh* btOptimizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian)
+btOptimizedBvh* btOptimizedBvh::deSerializeInPlace(void* i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian)
{
- btQuantizedBvh* bvh = btQuantizedBvh::deSerializeInPlace(i_alignedDataBuffer,i_dataBufferSize,i_swapEndian);
-
+ btQuantizedBvh* bvh = btQuantizedBvh::deSerializeInPlace(i_alignedDataBuffer, i_dataBufferSize, i_swapEndian);
+
//we don't add additional data so just do a static upcast
return static_cast<btOptimizedBvh*>(bvh);
}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btOptimizedBvh.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btOptimizedBvh.h
index 715961f552..22f131c8b2 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btOptimizedBvh.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btOptimizedBvh.h
@@ -22,44 +22,35 @@ subject to the following restrictions:
class btStridingMeshInterface;
-
///The btOptimizedBvh extends the btQuantizedBvh to create AABB tree for triangle meshes, through the btStridingMeshInterface.
-ATTRIBUTE_ALIGNED16(class) btOptimizedBvh : public btQuantizedBvh
+ATTRIBUTE_ALIGNED16(class)
+btOptimizedBvh : public btQuantizedBvh
{
-
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
protected:
-
public:
-
btOptimizedBvh();
virtual ~btOptimizedBvh();
- void build(btStridingMeshInterface* triangles,bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax);
+ void build(btStridingMeshInterface * triangles, bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax);
- void refit(btStridingMeshInterface* triangles,const btVector3& aabbMin,const btVector3& aabbMax);
+ void refit(btStridingMeshInterface * triangles, const btVector3& aabbMin, const btVector3& aabbMax);
- void refitPartial(btStridingMeshInterface* triangles,const btVector3& aabbMin, const btVector3& aabbMax);
+ void refitPartial(btStridingMeshInterface * triangles, const btVector3& aabbMin, const btVector3& aabbMax);
- void updateBvhNodes(btStridingMeshInterface* meshInterface,int firstNode,int endNode,int index);
+ void updateBvhNodes(btStridingMeshInterface * meshInterface, int firstNode, int endNode, int index);
/// Data buffer MUST be 16 byte aligned
- virtual bool serializeInPlace(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const
+ virtual bool serializeInPlace(void* o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const
{
- return btQuantizedBvh::serialize(o_alignedDataBuffer,i_dataBufferSize,i_swapEndian);
-
+ return btQuantizedBvh::serialize(o_alignedDataBuffer, i_dataBufferSize, i_swapEndian);
}
///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
- static btOptimizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
-
-
+ static btOptimizedBvh* deSerializeInPlace(void* i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
};
-
-#endif //BT_OPTIMIZED_BVH_H
-
-
+#endif //BT_OPTIMIZED_BVH_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp
index d51b6760fc..521ecfc760 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp
@@ -12,7 +12,7 @@ subject to the following restrictions:
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
-#if defined (_WIN32) || defined (__i386__)
+#if defined(_WIN32) || defined(__i386__)
#define BT_USE_SSE_IN_API
#endif
@@ -23,11 +23,9 @@ subject to the following restrictions:
#include "LinearMath/btGeometryUtil.h"
#include "LinearMath/btGrahamScan2dConvexHull.h"
-
-btPolyhedralConvexShape::btPolyhedralConvexShape() :btConvexInternalShape(),
-m_polyhedron(0)
+btPolyhedralConvexShape::btPolyhedralConvexShape() : btConvexInternalShape(),
+ m_polyhedron(0)
{
-
}
btPolyhedralConvexShape::~btPolyhedralConvexShape()
@@ -44,65 +42,65 @@ void btPolyhedralConvexShape::setPolyhedralFeatures(btConvexPolyhedron& polyhedr
if (m_polyhedron)
{
*m_polyhedron = polyhedron;
- } else
+ }
+ else
{
- void* mem = btAlignedAlloc(sizeof(btConvexPolyhedron),16);
+ void* mem = btAlignedAlloc(sizeof(btConvexPolyhedron), 16);
m_polyhedron = new (mem) btConvexPolyhedron(polyhedron);
}
}
-bool btPolyhedralConvexShape::initializePolyhedralFeatures(int shiftVerticesByMargin)
+bool btPolyhedralConvexShape::initializePolyhedralFeatures(int shiftVerticesByMargin)
{
-
if (m_polyhedron)
{
m_polyhedron->~btConvexPolyhedron();
btAlignedFree(m_polyhedron);
}
-
- void* mem = btAlignedAlloc(sizeof(btConvexPolyhedron),16);
+
+ void* mem = btAlignedAlloc(sizeof(btConvexPolyhedron), 16);
m_polyhedron = new (mem) btConvexPolyhedron;
btAlignedObjectArray<btVector3> orgVertices;
- for (int i=0;i<getNumVertices();i++)
+ for (int i = 0; i < getNumVertices(); i++)
{
btVector3& newVertex = orgVertices.expand();
- getVertex(i,newVertex);
+ getVertex(i, newVertex);
}
-
+
btConvexHullComputer conv;
-
+
if (shiftVerticesByMargin)
{
btAlignedObjectArray<btVector3> planeEquations;
- btGeometryUtil::getPlaneEquationsFromVertices(orgVertices,planeEquations);
+ btGeometryUtil::getPlaneEquationsFromVertices(orgVertices, planeEquations);
btAlignedObjectArray<btVector3> shiftedPlaneEquations;
- for (int p=0;p<planeEquations.size();p++)
+ for (int p = 0; p < planeEquations.size(); p++)
{
- btVector3 plane = planeEquations[p];
- // btScalar margin = getMargin();
- plane[3] -= getMargin();
- shiftedPlaneEquations.push_back(plane);
+ btVector3 plane = planeEquations[p];
+ // btScalar margin = getMargin();
+ plane[3] -= getMargin();
+ shiftedPlaneEquations.push_back(plane);
}
btAlignedObjectArray<btVector3> tmpVertices;
- btGeometryUtil::getVerticesFromPlaneEquations(shiftedPlaneEquations,tmpVertices);
-
- conv.compute(&tmpVertices[0].getX(), sizeof(btVector3),tmpVertices.size(),0.f,0.f);
- } else
+ btGeometryUtil::getVerticesFromPlaneEquations(shiftedPlaneEquations, tmpVertices);
+
+ conv.compute(&tmpVertices[0].getX(), sizeof(btVector3), tmpVertices.size(), 0.f, 0.f);
+ }
+ else
{
-
- conv.compute(&orgVertices[0].getX(), sizeof(btVector3),orgVertices.size(),0.f,0.f);
+ conv.compute(&orgVertices[0].getX(), sizeof(btVector3), orgVertices.size(), 0.f, 0.f);
}
#ifndef BT_RECONSTRUCT_FACES
-
+
int numVertices = conv.vertices.size();
m_polyhedron->m_vertices.resize(numVertices);
- for (int p=0;p<numVertices;p++)
+ for (int p = 0; p < numVertices; p++)
{
m_polyhedron->m_vertices[p] = conv.vertices[p];
}
@@ -115,78 +113,72 @@ bool btPolyhedralConvexShape::initializePolyhedralFeatures(int shiftVerticesByMa
btFace combinedFace;
const btConvexHullComputer::Edge* edge = &conv.edges[conv.faces[j]];
v0 = edge->getSourceVertex();
- int prevVertex=v0;
+ int prevVertex = v0;
combinedFace.m_indices.push_back(v0);
v1 = edge->getTargetVertex();
while (v1 != v0)
{
-
btVector3 wa = conv.vertices[prevVertex];
btVector3 wb = conv.vertices[v1];
- btVector3 newEdge = wb-wa;
+ btVector3 newEdge = wb - wa;
newEdge.normalize();
- if (numEdges<2)
+ if (numEdges < 2)
edges[numEdges++] = newEdge;
-
//face->addIndex(v1);
combinedFace.m_indices.push_back(v1);
edge = edge->getNextEdgeOfFace();
prevVertex = v1;
int v01 = edge->getSourceVertex();
v1 = edge->getTargetVertex();
-
}
-
+
btAssert(combinedFace.m_indices.size() > 2);
btVector3 faceNormal = edges[0].cross(edges[1]);
faceNormal.normalize();
- btScalar planeEq=1e30f;
+ btScalar planeEq = 1e30f;
- for (int v=0;v<combinedFace.m_indices.size();v++)
+ for (int v = 0; v < combinedFace.m_indices.size(); v++)
{
btScalar eq = m_polyhedron->m_vertices[combinedFace.m_indices[v]].dot(faceNormal);
- if (planeEq>eq)
+ if (planeEq > eq)
{
- planeEq=eq;
+ planeEq = eq;
}
}
combinedFace.m_plane[0] = faceNormal.getX();
combinedFace.m_plane[1] = faceNormal.getY();
combinedFace.m_plane[2] = faceNormal.getZ();
combinedFace.m_plane[3] = -planeEq;
-
+
m_polyhedron->m_faces.push_back(combinedFace);
}
-
-#else//BT_RECONSTRUCT_FACES
+#else //BT_RECONSTRUCT_FACES
btAlignedObjectArray<btVector3> faceNormals;
int numFaces = conv.faces.size();
faceNormals.resize(numFaces);
btConvexHullComputer* convexUtil = &conv;
-
- btAlignedObjectArray<btFace> tmpFaces;
+ btAlignedObjectArray<btFace> tmpFaces;
tmpFaces.resize(numFaces);
int numVertices = convexUtil->vertices.size();
m_polyhedron->m_vertices.resize(numVertices);
- for (int p=0;p<numVertices;p++)
+ for (int p = 0; p < numVertices; p++)
{
m_polyhedron->m_vertices[p] = convexUtil->vertices[p];
}
-
- for (int i=0;i<numFaces;i++)
+ for (int i = 0; i < numFaces; i++)
{
int face = convexUtil->faces[i];
//printf("face=%d\n",face);
- const btConvexHullComputer::Edge* firstEdge = &convexUtil->edges[face];
- const btConvexHullComputer::Edge* edge = firstEdge;
+ const btConvexHullComputer::Edge* firstEdge = &convexUtil->edges[face];
+ const btConvexHullComputer::Edge* edge = firstEdge;
btVector3 edges[3];
int numEdges = 0;
@@ -194,25 +186,23 @@ bool btPolyhedralConvexShape::initializePolyhedralFeatures(int shiftVerticesByMa
do
{
-
int src = edge->getSourceVertex();
tmpFaces[i].m_indices.push_back(src);
int targ = edge->getTargetVertex();
btVector3 wa = convexUtil->vertices[src];
btVector3 wb = convexUtil->vertices[targ];
- btVector3 newEdge = wb-wa;
+ btVector3 newEdge = wb - wa;
newEdge.normalize();
- if (numEdges<2)
+ if (numEdges < 2)
edges[numEdges++] = newEdge;
edge = edge->getNextEdgeOfFace();
- } while (edge!=firstEdge);
+ } while (edge != firstEdge);
btScalar planeEq = 1e30f;
-
- if (numEdges==2)
+ if (numEdges == 2)
{
faceNormals[i] = edges[0].cross(edges[1]);
faceNormals[i].normalize();
@@ -220,20 +210,19 @@ bool btPolyhedralConvexShape::initializePolyhedralFeatures(int shiftVerticesByMa
tmpFaces[i].m_plane[1] = faceNormals[i].getY();
tmpFaces[i].m_plane[2] = faceNormals[i].getZ();
tmpFaces[i].m_plane[3] = planeEq;
-
}
else
{
- btAssert(0);//degenerate?
+ btAssert(0); //degenerate?
faceNormals[i].setZero();
}
- for (int v=0;v<tmpFaces[i].m_indices.size();v++)
+ for (int v = 0; v < tmpFaces[i].m_indices.size(); v++)
{
btScalar eq = m_polyhedron->m_vertices[tmpFaces[i].m_indices[v]].dot(faceNormals[i]);
- if (planeEq>eq)
+ if (planeEq > eq)
{
- planeEq=eq;
+ planeEq = eq;
}
}
tmpFaces[i].m_plane[3] = -planeEq;
@@ -241,89 +230,86 @@ bool btPolyhedralConvexShape::initializePolyhedralFeatures(int shiftVerticesByMa
//merge coplanar faces and copy them to m_polyhedron
- btScalar faceWeldThreshold= 0.999f;
+ btScalar faceWeldThreshold = 0.999f;
btAlignedObjectArray<int> todoFaces;
- for (int i=0;i<tmpFaces.size();i++)
+ for (int i = 0; i < tmpFaces.size(); i++)
todoFaces.push_back(i);
while (todoFaces.size())
{
btAlignedObjectArray<int> coplanarFaceGroup;
- int refFace = todoFaces[todoFaces.size()-1];
+ int refFace = todoFaces[todoFaces.size() - 1];
coplanarFaceGroup.push_back(refFace);
btFace& faceA = tmpFaces[refFace];
todoFaces.pop_back();
- btVector3 faceNormalA(faceA.m_plane[0],faceA.m_plane[1],faceA.m_plane[2]);
- for (int j=todoFaces.size()-1;j>=0;j--)
+ btVector3 faceNormalA(faceA.m_plane[0], faceA.m_plane[1], faceA.m_plane[2]);
+ for (int j = todoFaces.size() - 1; j >= 0; j--)
{
int i = todoFaces[j];
btFace& faceB = tmpFaces[i];
- btVector3 faceNormalB(faceB.m_plane[0],faceB.m_plane[1],faceB.m_plane[2]);
- if (faceNormalA.dot(faceNormalB)>faceWeldThreshold)
+ btVector3 faceNormalB(faceB.m_plane[0], faceB.m_plane[1], faceB.m_plane[2]);
+ if (faceNormalA.dot(faceNormalB) > faceWeldThreshold)
{
coplanarFaceGroup.push_back(i);
todoFaces.remove(i);
}
}
-
bool did_merge = false;
- if (coplanarFaceGroup.size()>1)
+ if (coplanarFaceGroup.size() > 1)
{
//do the merge: use Graham Scan 2d convex hull
btAlignedObjectArray<GrahamVector3> orgpoints;
- btVector3 averageFaceNormal(0,0,0);
+ btVector3 averageFaceNormal(0, 0, 0);
- for (int i=0;i<coplanarFaceGroup.size();i++)
+ for (int i = 0; i < coplanarFaceGroup.size(); i++)
{
-// m_polyhedron->m_faces.push_back(tmpFaces[coplanarFaceGroup[i]]);
+ // m_polyhedron->m_faces.push_back(tmpFaces[coplanarFaceGroup[i]]);
btFace& face = tmpFaces[coplanarFaceGroup[i]];
- btVector3 faceNormal(face.m_plane[0],face.m_plane[1],face.m_plane[2]);
- averageFaceNormal+=faceNormal;
- for (int f=0;f<face.m_indices.size();f++)
+ btVector3 faceNormal(face.m_plane[0], face.m_plane[1], face.m_plane[2]);
+ averageFaceNormal += faceNormal;
+ for (int f = 0; f < face.m_indices.size(); f++)
{
int orgIndex = face.m_indices[f];
btVector3 pt = m_polyhedron->m_vertices[orgIndex];
-
+
bool found = false;
- for (int i=0;i<orgpoints.size();i++)
+ for (int i = 0; i < orgpoints.size(); i++)
{
//if ((orgpoints[i].m_orgIndex == orgIndex) || ((rotatedPt-orgpoints[i]).length2()<0.0001))
if (orgpoints[i].m_orgIndex == orgIndex)
{
- found=true;
+ found = true;
break;
}
}
if (!found)
- orgpoints.push_back(GrahamVector3(pt,orgIndex));
+ orgpoints.push_back(GrahamVector3(pt, orgIndex));
}
}
-
-
btFace combinedFace;
- for (int i=0;i<4;i++)
+ for (int i = 0; i < 4; i++)
combinedFace.m_plane[i] = tmpFaces[coplanarFaceGroup[0]].m_plane[i];
btAlignedObjectArray<GrahamVector3> hull;
averageFaceNormal.normalize();
- GrahamScanConvexHull2D(orgpoints,hull,averageFaceNormal);
+ GrahamScanConvexHull2D(orgpoints, hull, averageFaceNormal);
- for (int i=0;i<hull.size();i++)
+ for (int i = 0; i < hull.size(); i++)
{
combinedFace.m_indices.push_back(hull[i].m_orgIndex);
- for(int k = 0; k < orgpoints.size(); k++)
+ for (int k = 0; k < orgpoints.size(); k++)
{
- if(orgpoints[k].m_orgIndex == hull[i].m_orgIndex)
+ if (orgpoints[k].m_orgIndex == hull[i].m_orgIndex)
{
- orgpoints[k].m_orgIndex = -1; // invalidate...
+ orgpoints[k].m_orgIndex = -1; // invalidate...
break;
}
}
@@ -331,38 +317,41 @@ bool btPolyhedralConvexShape::initializePolyhedralFeatures(int shiftVerticesByMa
// are there rejected vertices?
bool reject_merge = false;
-
-
- for(int i = 0; i < orgpoints.size(); i++) {
- if(orgpoints[i].m_orgIndex == -1)
- continue; // this is in the hull...
+ for (int i = 0; i < orgpoints.size(); i++)
+ {
+ if (orgpoints[i].m_orgIndex == -1)
+ continue; // this is in the hull...
// this vertex is rejected -- is anybody else using this vertex?
- for(int j = 0; j < tmpFaces.size(); j++) {
-
+ for (int j = 0; j < tmpFaces.size(); j++)
+ {
btFace& face = tmpFaces[j];
// is this a face of the current coplanar group?
bool is_in_current_group = false;
- for(int k = 0; k < coplanarFaceGroup.size(); k++) {
- if(coplanarFaceGroup[k] == j) {
+ for (int k = 0; k < coplanarFaceGroup.size(); k++)
+ {
+ if (coplanarFaceGroup[k] == j)
+ {
is_in_current_group = true;
break;
}
}
- if(is_in_current_group) // ignore this face...
+ if (is_in_current_group) // ignore this face...
continue;
// does this face use this rejected vertex?
- for(int v = 0; v < face.m_indices.size(); v++) {
- if(face.m_indices[v] == orgpoints[i].m_orgIndex) {
+ for (int v = 0; v < face.m_indices.size(); v++)
+ {
+ if (face.m_indices[v] == orgpoints[i].m_orgIndex)
+ {
// this rejected vertex is used in another face -- reject merge
reject_merge = true;
break;
}
}
- if(reject_merge)
+ if (reject_merge)
break;
}
- if(reject_merge)
+ if (reject_merge)
break;
}
@@ -373,21 +362,17 @@ bool btPolyhedralConvexShape::initializePolyhedralFeatures(int shiftVerticesByMa
m_polyhedron->m_faces.push_back(combinedFace);
}
}
- if(!did_merge)
+ if (!did_merge)
{
- for (int i=0;i<coplanarFaceGroup.size();i++)
+ for (int i = 0; i < coplanarFaceGroup.size(); i++)
{
btFace face = tmpFaces[coplanarFaceGroup[i]];
m_polyhedron->m_faces.push_back(face);
}
-
- }
-
-
-
+ }
}
-#endif //BT_RECONSTRUCT_FACES
+#endif //BT_RECONSTRUCT_FACES
m_polyhedron->initialize();
@@ -395,14 +380,12 @@ bool btPolyhedralConvexShape::initializePolyhedralFeatures(int shiftVerticesByMa
}
#ifndef MIN
- #define MIN(_a, _b) ((_a) < (_b) ? (_a) : (_b))
+#define MIN(_a, _b) ((_a) < (_b) ? (_a) : (_b))
#endif
-btVector3 btPolyhedralConvexShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const
+btVector3 btPolyhedralConvexShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0) const
{
-
-
- btVector3 supVec(0,0,0);
+ btVector3 supVec(0, 0, 0);
#ifndef __SPU__
int i;
btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
@@ -411,37 +394,36 @@ btVector3 btPolyhedralConvexShape::localGetSupportingVertexWithoutMargin(const b
btScalar lenSqr = vec.length2();
if (lenSqr < btScalar(0.0001))
{
- vec.setValue(1,0,0);
- } else
+ vec.setValue(1, 0, 0);
+ }
+ else
{
- btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
+ btScalar rlen = btScalar(1.) / btSqrt(lenSqr);
vec *= rlen;
}
btVector3 vtx;
btScalar newDot;
- for( int k = 0; k < getNumVertices(); k += 128 )
- {
- btVector3 temp[128];
- int inner_count = MIN(getNumVertices() - k, 128);
- for( i = 0; i < inner_count; i++ )
- getVertex(i,temp[i]);
- i = (int) vec.maxDot( temp, inner_count, newDot);
+ for (int k = 0; k < getNumVertices(); k += 128)
+ {
+ btVector3 temp[128];
+ int inner_count = MIN(getNumVertices() - k, 128);
+ for (i = 0; i < inner_count; i++)
+ getVertex(i, temp[i]);
+ i = (int)vec.maxDot(temp, inner_count, newDot);
if (newDot > maxDot)
{
maxDot = newDot;
supVec = temp[i];
- }
- }
-
-#endif //__SPU__
+ }
+ }
+
+#endif //__SPU__
return supVec;
}
-
-
-void btPolyhedralConvexShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+void btPolyhedralConvexShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
{
#ifndef __SPU__
int i;
@@ -449,36 +431,34 @@ void btPolyhedralConvexShape::batchedUnitVectorGetSupportingVertexWithoutMargin(
btVector3 vtx;
btScalar newDot;
- for (i=0;i<numVectors;i++)
+ for (i = 0; i < numVectors; i++)
{
supportVerticesOut[i][3] = btScalar(-BT_LARGE_FLOAT);
}
- for (int j=0;j<numVectors;j++)
+ for (int j = 0; j < numVectors; j++)
{
- const btVector3& vec = vectors[j];
-
- for( int k = 0; k < getNumVertices(); k += 128 )
- {
- btVector3 temp[128];
- int inner_count = MIN(getNumVertices() - k, 128);
- for( i = 0; i < inner_count; i++ )
- getVertex(i,temp[i]);
- i = (int) vec.maxDot( temp, inner_count, newDot);
- if (newDot > supportVerticesOut[j][3])
- {
+ const btVector3& vec = vectors[j];
+
+ for (int k = 0; k < getNumVertices(); k += 128)
+ {
+ btVector3 temp[128];
+ int inner_count = MIN(getNumVertices() - k, 128);
+ for (i = 0; i < inner_count; i++)
+ getVertex(i, temp[i]);
+ i = (int)vec.maxDot(temp, inner_count, newDot);
+ if (newDot > supportVerticesOut[j][3])
+ {
supportVerticesOut[j] = temp[i];
supportVerticesOut[j][3] = newDot;
- }
- }
- }
+ }
+ }
+ }
-#endif //__SPU__
+#endif //__SPU__
}
-
-
-void btPolyhedralConvexShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+void btPolyhedralConvexShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
{
#ifndef __SPU__
//not yet, return box inertia
@@ -487,81 +467,77 @@ void btPolyhedralConvexShape::calculateLocalInertia(btScalar mass,btVector3& ine
btTransform ident;
ident.setIdentity();
- btVector3 aabbMin,aabbMax;
- getAabb(ident,aabbMin,aabbMax);
- btVector3 halfExtents = (aabbMax-aabbMin)*btScalar(0.5);
-
- btScalar lx=btScalar(2.)*(halfExtents.x()+margin);
- btScalar ly=btScalar(2.)*(halfExtents.y()+margin);
- btScalar lz=btScalar(2.)*(halfExtents.z()+margin);
- const btScalar x2 = lx*lx;
- const btScalar y2 = ly*ly;
- const btScalar z2 = lz*lz;
+ btVector3 aabbMin, aabbMax;
+ getAabb(ident, aabbMin, aabbMax);
+ btVector3 halfExtents = (aabbMax - aabbMin) * btScalar(0.5);
+
+ btScalar lx = btScalar(2.) * (halfExtents.x() + margin);
+ btScalar ly = btScalar(2.) * (halfExtents.y() + margin);
+ btScalar lz = btScalar(2.) * (halfExtents.z() + margin);
+ const btScalar x2 = lx * lx;
+ const btScalar y2 = ly * ly;
+ const btScalar z2 = lz * lz;
const btScalar scaledmass = mass * btScalar(0.08333333);
- inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2));
-#endif //__SPU__
+ inertia = scaledmass * (btVector3(y2 + z2, x2 + z2, x2 + y2));
+#endif //__SPU__
}
-
-
-void btPolyhedralConvexAabbCachingShape::setLocalScaling(const btVector3& scaling)
+void btPolyhedralConvexAabbCachingShape::setLocalScaling(const btVector3& scaling)
{
btConvexInternalShape::setLocalScaling(scaling);
recalcLocalAabb();
}
btPolyhedralConvexAabbCachingShape::btPolyhedralConvexAabbCachingShape()
-:btPolyhedralConvexShape(),
-m_localAabbMin(1,1,1),
-m_localAabbMax(-1,-1,-1),
-m_isLocalAabbValid(false)
+ : btPolyhedralConvexShape(),
+ m_localAabbMin(1, 1, 1),
+ m_localAabbMax(-1, -1, -1),
+ m_isLocalAabbValid(false)
{
}
-void btPolyhedralConvexAabbCachingShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const
+void btPolyhedralConvexAabbCachingShape::getAabb(const btTransform& trans, btVector3& aabbMin, btVector3& aabbMax) const
{
- getNonvirtualAabb(trans,aabbMin,aabbMax,getMargin());
+ getNonvirtualAabb(trans, aabbMin, aabbMax, getMargin());
}
-void btPolyhedralConvexAabbCachingShape::recalcLocalAabb()
+void btPolyhedralConvexAabbCachingShape::recalcLocalAabb()
{
m_isLocalAabbValid = true;
-
- #if 1
+
+#if 1
static const btVector3 _directions[] =
- {
- btVector3( 1., 0., 0.),
- btVector3( 0., 1., 0.),
- btVector3( 0., 0., 1.),
- btVector3( -1., 0., 0.),
- btVector3( 0., -1., 0.),
- btVector3( 0., 0., -1.)
- };
-
+ {
+ btVector3(1., 0., 0.),
+ btVector3(0., 1., 0.),
+ btVector3(0., 0., 1.),
+ btVector3(-1., 0., 0.),
+ btVector3(0., -1., 0.),
+ btVector3(0., 0., -1.)};
+
btVector3 _supporting[] =
- {
- btVector3( 0., 0., 0.),
- btVector3( 0., 0., 0.),
- btVector3( 0., 0., 0.),
- btVector3( 0., 0., 0.),
- btVector3( 0., 0., 0.),
- btVector3( 0., 0., 0.)
- };
-
+ {
+ btVector3(0., 0., 0.),
+ btVector3(0., 0., 0.),
+ btVector3(0., 0., 0.),
+ btVector3(0., 0., 0.),
+ btVector3(0., 0., 0.),
+ btVector3(0., 0., 0.)};
+
batchedUnitVectorGetSupportingVertexWithoutMargin(_directions, _supporting, 6);
-
- for ( int i = 0; i < 3; ++i )
+
+ for (int i = 0; i < 3; ++i)
{
m_localAabbMax[i] = _supporting[i][i] + m_collisionMargin;
m_localAabbMin[i] = _supporting[i + 3][i] - m_collisionMargin;
}
-
- #else
- for (int i=0;i<3;i++)
+#else
+
+ for (int i = 0; i < 3; i++)
{
- btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.));
+ btVector3 vec(btScalar(0.), btScalar(0.), btScalar(0.));
vec[i] = btScalar(1.);
btVector3 tmp = localGetSupportingVertex(vec);
m_localAabbMax[i] = tmp[i];
@@ -569,9 +545,5 @@ void btPolyhedralConvexAabbCachingShape::recalcLocalAabb()
tmp = localGetSupportingVertex(vec);
m_localAabbMin[i] = tmp[i];
}
- #endif
+#endif
}
-
-
-
-
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h
index b7ddb6e060..b3ffab7a23 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h
@@ -20,20 +20,15 @@ subject to the following restrictions:
#include "btConvexInternalShape.h"
class btConvexPolyhedron;
-
///The btPolyhedralConvexShape is an internal interface class for polyhedral convex shapes.
-ATTRIBUTE_ALIGNED16(class) btPolyhedralConvexShape : public btConvexInternalShape
+ATTRIBUTE_ALIGNED16(class)
+btPolyhedralConvexShape : public btConvexInternalShape
{
-
-
protected:
-
btConvexPolyhedron* m_polyhedron;
public:
-
BT_DECLARE_ALIGNED_ALLOCATOR();
-
btPolyhedralConvexShape();
@@ -41,55 +36,49 @@ public:
///optional method mainly used to generate multiple contact points by clipping polyhedral features (faces/edges)
///experimental/work-in-progress
- virtual bool initializePolyhedralFeatures(int shiftVerticesByMargin=0);
+ virtual bool initializePolyhedralFeatures(int shiftVerticesByMargin = 0);
- virtual void setPolyhedralFeatures(btConvexPolyhedron& polyhedron);
-
+ virtual void setPolyhedralFeatures(btConvexPolyhedron & polyhedron);
- const btConvexPolyhedron* getConvexPolyhedron() const
+ const btConvexPolyhedron* getConvexPolyhedron() const
{
return m_polyhedron;
}
//brute force implementations
- virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
- virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
-
- virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
-
-
- virtual int getNumVertices() const = 0 ;
+ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const;
+
+ virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
+
+ virtual int getNumVertices() const = 0;
virtual int getNumEdges() const = 0;
- virtual void getEdge(int i,btVector3& pa,btVector3& pb) const = 0;
- virtual void getVertex(int i,btVector3& vtx) const = 0;
- virtual int getNumPlanes() const = 0;
- virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const = 0;
-// virtual int getIndex(int i) const = 0 ;
-
- virtual bool isInside(const btVector3& pt,btScalar tolerance) const = 0;
-
-};
+ virtual void getEdge(int i, btVector3& pa, btVector3& pb) const = 0;
+ virtual void getVertex(int i, btVector3& vtx) const = 0;
+ virtual int getNumPlanes() const = 0;
+ virtual void getPlane(btVector3 & planeNormal, btVector3 & planeSupport, int i) const = 0;
+ // virtual int getIndex(int i) const = 0 ;
+ virtual bool isInside(const btVector3& pt, btScalar tolerance) const = 0;
+};
///The btPolyhedralConvexAabbCachingShape adds aabb caching to the btPolyhedralConvexShape
class btPolyhedralConvexAabbCachingShape : public btPolyhedralConvexShape
{
+ btVector3 m_localAabbMin;
+ btVector3 m_localAabbMax;
+ bool m_isLocalAabbValid;
- btVector3 m_localAabbMin;
- btVector3 m_localAabbMax;
- bool m_isLocalAabbValid;
-
protected:
-
- void setCachedLocalAabb (const btVector3& aabbMin, const btVector3& aabbMax)
+ void setCachedLocalAabb(const btVector3& aabbMin, const btVector3& aabbMax)
{
m_isLocalAabbValid = true;
m_localAabbMin = aabbMin;
m_localAabbMax = aabbMax;
}
- inline void getCachedLocalAabb (btVector3& aabbMin, btVector3& aabbMax) const
+ inline void getCachedLocalAabb(btVector3& aabbMin, btVector3& aabbMax) const
{
btAssert(m_isLocalAabbValid);
aabbMin = m_localAabbMin;
@@ -97,25 +86,21 @@ protected:
}
protected:
-
btPolyhedralConvexAabbCachingShape();
-
+
public:
-
- inline void getNonvirtualAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax, btScalar margin) const
+ inline void getNonvirtualAabb(const btTransform& trans, btVector3& aabbMin, btVector3& aabbMax, btScalar margin) const
{
-
//lazy evaluation of local aabb
btAssert(m_isLocalAabbValid);
- btTransformAabb(m_localAabbMin,m_localAabbMax,margin,trans,aabbMin,aabbMax);
+ btTransformAabb(m_localAabbMin, m_localAabbMax, margin, trans, aabbMin, aabbMax);
}
- virtual void setLocalScaling(const btVector3& scaling);
-
- virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+ virtual void setLocalScaling(const btVector3& scaling);
- void recalcLocalAabb();
+ virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
+ void recalcLocalAabb();
};
-#endif //BT_POLYHEDRAL_CONVEX_SHAPE_H
+#endif //BT_POLYHEDRAL_CONVEX_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp
index 6a337c786c..f427319974 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp
@@ -13,11 +13,10 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#include "btScaledBvhTriangleMeshShape.h"
-btScaledBvhTriangleMeshShape::btScaledBvhTriangleMeshShape(btBvhTriangleMeshShape* childShape,const btVector3& localScaling)
-:m_localScaling(localScaling),m_bvhTriMeshShape(childShape)
+btScaledBvhTriangleMeshShape::btScaledBvhTriangleMeshShape(btBvhTriangleMeshShape* childShape, const btVector3& localScaling)
+ : m_localScaling(localScaling), m_bvhTriMeshShape(childShape)
{
m_shapeType = SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE;
}
@@ -26,55 +25,51 @@ btScaledBvhTriangleMeshShape::~btScaledBvhTriangleMeshShape()
{
}
-
class btScaledTriangleCallback : public btTriangleCallback
{
btTriangleCallback* m_originalCallback;
- btVector3 m_localScaling;
+ btVector3 m_localScaling;
public:
-
- btScaledTriangleCallback(btTriangleCallback* originalCallback,const btVector3& localScaling)
- :m_originalCallback(originalCallback),
- m_localScaling(localScaling)
+ btScaledTriangleCallback(btTriangleCallback* originalCallback, const btVector3& localScaling)
+ : m_originalCallback(originalCallback),
+ m_localScaling(localScaling)
{
}
virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
{
btVector3 newTriangle[3];
- newTriangle[0] = triangle[0]*m_localScaling;
- newTriangle[1] = triangle[1]*m_localScaling;
- newTriangle[2] = triangle[2]*m_localScaling;
- m_originalCallback->processTriangle(&newTriangle[0],partId,triangleIndex);
+ newTriangle[0] = triangle[0] * m_localScaling;
+ newTriangle[1] = triangle[1] * m_localScaling;
+ newTriangle[2] = triangle[2] * m_localScaling;
+ m_originalCallback->processTriangle(&newTriangle[0], partId, triangleIndex);
}
};
-void btScaledBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
+void btScaledBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
{
- btScaledTriangleCallback scaledCallback(callback,m_localScaling);
-
- btVector3 invLocalScaling(1.f/m_localScaling.getX(),1.f/m_localScaling.getY(),1.f/m_localScaling.getZ());
- btVector3 scaledAabbMin,scaledAabbMax;
+ btScaledTriangleCallback scaledCallback(callback, m_localScaling);
+
+ btVector3 invLocalScaling(1.f / m_localScaling.getX(), 1.f / m_localScaling.getY(), 1.f / m_localScaling.getZ());
+ btVector3 scaledAabbMin, scaledAabbMax;
///support negative scaling
scaledAabbMin[0] = m_localScaling.getX() >= 0. ? aabbMin[0] * invLocalScaling[0] : aabbMax[0] * invLocalScaling[0];
scaledAabbMin[1] = m_localScaling.getY() >= 0. ? aabbMin[1] * invLocalScaling[1] : aabbMax[1] * invLocalScaling[1];
scaledAabbMin[2] = m_localScaling.getZ() >= 0. ? aabbMin[2] * invLocalScaling[2] : aabbMax[2] * invLocalScaling[2];
scaledAabbMin[3] = 0.f;
-
+
scaledAabbMax[0] = m_localScaling.getX() <= 0. ? aabbMin[0] * invLocalScaling[0] : aabbMax[0] * invLocalScaling[0];
scaledAabbMax[1] = m_localScaling.getY() <= 0. ? aabbMin[1] * invLocalScaling[1] : aabbMax[1] * invLocalScaling[1];
scaledAabbMax[2] = m_localScaling.getZ() <= 0. ? aabbMin[2] * invLocalScaling[2] : aabbMax[2] * invLocalScaling[2];
scaledAabbMax[3] = 0.f;
-
-
- m_bvhTriMeshShape->processAllTriangles(&scaledCallback,scaledAabbMin,scaledAabbMax);
-}
+ m_bvhTriMeshShape->processAllTriangles(&scaledCallback, scaledAabbMin, scaledAabbMax);
+}
-void btScaledBvhTriangleMeshShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const
+void btScaledBvhTriangleMeshShape::getAabb(const btTransform& trans, btVector3& aabbMin, btVector3& aabbMax) const
{
btVector3 localAabbMin = m_bvhTriMeshShape->getLocalAabbMin();
btVector3 localAabbMax = m_bvhTriMeshShape->getLocalAabbMax();
@@ -89,22 +84,21 @@ void btScaledBvhTriangleMeshShape::getAabb(const btTransform& trans,btVector3& a
localAabbMax[1] = (m_localScaling.getY() <= 0.) ? tmpLocalAabbMin[1] : tmpLocalAabbMax[1];
localAabbMax[2] = (m_localScaling.getZ() <= 0.) ? tmpLocalAabbMin[2] : tmpLocalAabbMax[2];
- btVector3 localHalfExtents = btScalar(0.5)*(localAabbMax-localAabbMin);
+ btVector3 localHalfExtents = btScalar(0.5) * (localAabbMax - localAabbMin);
btScalar margin = m_bvhTriMeshShape->getMargin();
- localHalfExtents += btVector3(margin,margin,margin);
- btVector3 localCenter = btScalar(0.5)*(localAabbMax+localAabbMin);
-
- btMatrix3x3 abs_b = trans.getBasis().absolute();
+ localHalfExtents += btVector3(margin, margin, margin);
+ btVector3 localCenter = btScalar(0.5) * (localAabbMax + localAabbMin);
+
+ btMatrix3x3 abs_b = trans.getBasis().absolute();
btVector3 center = trans(localCenter);
- btVector3 extent = localHalfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
+ btVector3 extent = localHalfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
aabbMin = center - extent;
aabbMax = center + extent;
-
}
-void btScaledBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling)
+void btScaledBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling)
{
m_localScaling = scaling;
}
@@ -114,8 +108,8 @@ const btVector3& btScaledBvhTriangleMeshShape::getLocalScaling() const
return m_localScaling;
}
-void btScaledBvhTriangleMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+void btScaledBvhTriangleMeshShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
{
///don't make this a movable object!
-// btAssert(0);
+ // btAssert(0);
}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h
index 39049eaf08..4d6feb61af 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h
@@ -18,78 +18,69 @@ subject to the following restrictions:
#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
-
///The btScaledBvhTriangleMeshShape allows to instance a scaled version of an existing btBvhTriangleMeshShape.
///Note that each btBvhTriangleMeshShape still can have its own local scaling, independent from this btScaledBvhTriangleMeshShape 'localScaling'
-ATTRIBUTE_ALIGNED16(class) btScaledBvhTriangleMeshShape : public btConcaveShape
+ATTRIBUTE_ALIGNED16(class)
+btScaledBvhTriangleMeshShape : public btConcaveShape
{
-
-
- btVector3 m_localScaling;
+ btVector3 m_localScaling;
- btBvhTriangleMeshShape* m_bvhTriMeshShape;
+ btBvhTriangleMeshShape* m_bvhTriMeshShape;
public:
-
BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btScaledBvhTriangleMeshShape(btBvhTriangleMeshShape* childShape,const btVector3& localScaling);
+ btScaledBvhTriangleMeshShape(btBvhTriangleMeshShape * childShape, const btVector3& localScaling);
virtual ~btScaledBvhTriangleMeshShape();
-
- virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
- virtual void setLocalScaling(const btVector3& scaling);
+ virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
+ virtual void setLocalScaling(const btVector3& scaling);
virtual const btVector3& getLocalScaling() const;
- virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+ virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
- virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+ virtual void processAllTriangles(btTriangleCallback * callback, const btVector3& aabbMin, const btVector3& aabbMax) const;
- btBvhTriangleMeshShape* getChildShape()
+ btBvhTriangleMeshShape* getChildShape()
{
return m_bvhTriMeshShape;
}
- const btBvhTriangleMeshShape* getChildShape() const
+ const btBvhTriangleMeshShape* getChildShape() const
{
return m_bvhTriMeshShape;
}
//debugging
- virtual const char* getName()const {return "SCALEDBVHTRIANGLEMESH";}
+ virtual const char* getName() const { return "SCALEDBVHTRIANGLEMESH"; }
- virtual int calculateSerializeBufferSize() const;
+ virtual int calculateSerializeBufferSize() const;
///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
};
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btScaledTriangleMeshShapeData
+struct btScaledTriangleMeshShapeData
{
- btTriangleMeshShapeData m_trimeshShapeData;
+ btTriangleMeshShapeData m_trimeshShapeData;
- btVector3FloatData m_localScaling;
+ btVector3FloatData m_localScaling;
};
-
-SIMD_FORCE_INLINE int btScaledBvhTriangleMeshShape::calculateSerializeBufferSize() const
+SIMD_FORCE_INLINE int btScaledBvhTriangleMeshShape::calculateSerializeBufferSize() const
{
return sizeof(btScaledTriangleMeshShapeData);
}
-
///fills the dataBuffer and returns the struct name (and 0 on failure)
-SIMD_FORCE_INLINE const char* btScaledBvhTriangleMeshShape::serialize(void* dataBuffer, btSerializer* serializer) const
+SIMD_FORCE_INLINE const char* btScaledBvhTriangleMeshShape::serialize(void* dataBuffer, btSerializer* serializer) const
{
- btScaledTriangleMeshShapeData* scaledMeshData = (btScaledTriangleMeshShapeData*) dataBuffer;
- m_bvhTriMeshShape->serialize(&scaledMeshData->m_trimeshShapeData,serializer);
+ btScaledTriangleMeshShapeData* scaledMeshData = (btScaledTriangleMeshShapeData*)dataBuffer;
+ m_bvhTriMeshShape->serialize(&scaledMeshData->m_trimeshShapeData, serializer);
scaledMeshData->m_trimeshShapeData.m_collisionShapeData.m_shapeType = SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE;
m_localScaling.serializeFloat(scaledMeshData->m_localScaling);
return "btScaledTriangleMeshShapeData";
}
-
-#endif //BT_SCALED_BVH_TRIANGLE_MESH_SHAPE_H
+#endif //BT_SCALED_BVH_TRIANGLE_MESH_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btSdfCollisionShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btSdfCollisionShape.cpp
index 828acda470..4a95dbea4f 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btSdfCollisionShape.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btSdfCollisionShape.cpp
@@ -9,10 +9,9 @@ struct btSdfCollisionShapeInternalData
btMiniSDF m_sdf;
btSdfCollisionShapeInternalData()
- :m_localScaling(1,1,1),
- m_margin(0)
+ : m_localScaling(1, 1, 1),
+ m_margin(0)
{
-
}
};
@@ -26,8 +25,6 @@ btSdfCollisionShape::btSdfCollisionShape()
m_shapeType = SDF_SHAPE_PROXYTYPE;
m_data = new btSdfCollisionShapeInternalData();
-
-
//"E:/develop/bullet3/data/toys/ground_hole64_64_8.cdf");//ground_cube.cdf");
/*unsigned int field_id=0;
Eigen::Vector3d x (1,10,1);
@@ -35,25 +32,22 @@ btSdfCollisionShape::btSdfCollisionShape()
double dist = m_data->m_sdf.interpolate(field_id, x, &gradient);
printf("dist=%g\n", dist);
*/
-
}
btSdfCollisionShape::~btSdfCollisionShape()
{
delete m_data;
}
-void btSdfCollisionShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+void btSdfCollisionShape::getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
{
btAssert(m_data->m_sdf.isValid());
btVector3 localAabbMin = m_data->m_sdf.m_domain.m_min;
btVector3 localAabbMax = m_data->m_sdf.m_domain.m_max;
btScalar margin(0);
- btTransformAabb(localAabbMin,localAabbMax,margin,t,aabbMin,aabbMax);
-
+ btTransformAabb(localAabbMin, localAabbMax, margin, t, aabbMin, aabbMax);
}
-
-void btSdfCollisionShape::setLocalScaling(const btVector3& scaling)
+void btSdfCollisionShape::setLocalScaling(const btVector3& scaling)
{
m_data->m_localScaling = scaling;
}
@@ -61,39 +55,38 @@ const btVector3& btSdfCollisionShape::getLocalScaling() const
{
return m_data->m_localScaling;
}
-void btSdfCollisionShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+void btSdfCollisionShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
{
- inertia.setValue(0,0,0);
+ inertia.setValue(0, 0, 0);
}
-const char* btSdfCollisionShape::getName()const
+const char* btSdfCollisionShape::getName() const
{
return "btSdfCollisionShape";
}
-void btSdfCollisionShape::setMargin(btScalar margin)
+void btSdfCollisionShape::setMargin(btScalar margin)
{
m_data->m_margin = margin;
}
-btScalar btSdfCollisionShape::getMargin() const
+btScalar btSdfCollisionShape::getMargin() const
{
return m_data->m_margin;
}
-void btSdfCollisionShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
+void btSdfCollisionShape::processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
{
//not yet
}
-
bool btSdfCollisionShape::queryPoint(const btVector3& ptInSDF, btScalar& distOut, btVector3& normal)
{
int field = 0;
btVector3 grad;
double dist;
- bool hasResult = m_data->m_sdf.interpolate(field,dist, ptInSDF,&grad);
+ bool hasResult = m_data->m_sdf.interpolate(field, dist, ptInSDF, &grad);
if (hasResult)
{
- normal.setValue(grad[0],grad[1],grad[2]);
- distOut= dist;
+ normal.setValue(grad[0], grad[1], grad[2]);
+ distOut = dist;
}
return hasResult;
}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btSdfCollisionShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btSdfCollisionShape.h
index 6e32db9cd8..3989d6245e 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btSdfCollisionShape.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btSdfCollisionShape.h
@@ -8,23 +8,22 @@ class btSdfCollisionShape : public btConcaveShape
struct btSdfCollisionShapeInternalData* m_data;
public:
-
btSdfCollisionShape();
virtual ~btSdfCollisionShape();
-
+
bool initializeSDF(const char* sdfData, int sizeInBytes);
- virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
- virtual void setLocalScaling(const btVector3& scaling);
+ virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
+ virtual void setLocalScaling(const btVector3& scaling);
virtual const btVector3& getLocalScaling() const;
- virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
- virtual const char* getName()const;
- virtual void setMargin(btScalar margin);
- virtual btScalar getMargin() const;
+ virtual void calculateLocalInertia(btScalar mass, btVector3& inertia) const;
+ virtual const char* getName() const;
+ virtual void setMargin(btScalar margin);
+ virtual btScalar getMargin() const;
- virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+ virtual void processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const;
bool queryPoint(const btVector3& ptInSDF, btScalar& distOut, btVector3& normal);
};
-#endif //BT_SDF_COLLISION_SHAPE_H
+#endif //BT_SDF_COLLISION_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btShapeHull.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btShapeHull.cpp
index 9f712fe555..a2c490faf9 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btShapeHull.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btShapeHull.cpp
@@ -15,53 +15,48 @@ subject to the following restrictions:
//btShapeHull was implemented by John McCutchan.
-
#include "btShapeHull.h"
#include "LinearMath/btConvexHull.h"
#define NUM_UNITSPHERE_POINTS 42
#define NUM_UNITSPHERE_POINTS_HIGHRES 256
-
-btShapeHull::btShapeHull (const btConvexShape* shape)
+btShapeHull::btShapeHull(const btConvexShape* shape)
{
m_shape = shape;
- m_vertices.clear ();
+ m_vertices.clear();
m_indices.clear();
m_numIndices = 0;
}
-btShapeHull::~btShapeHull ()
+btShapeHull::~btShapeHull()
{
- m_indices.clear();
- m_vertices.clear ();
+ m_indices.clear();
+ m_vertices.clear();
}
-bool
-btShapeHull::buildHull (btScalar /*margin*/, int highres)
+bool btShapeHull::buildHull(btScalar /*margin*/, int highres)
{
- int numSampleDirections = highres? NUM_UNITSPHERE_POINTS_HIGHRES:NUM_UNITSPHERE_POINTS;
- {
- int numPDA = m_shape->getNumPreferredPenetrationDirections();
- if (numPDA)
- {
- for (int i=0;i<numPDA;i++)
- {
- btVector3 norm;
- m_shape->getPreferredPenetrationDirection(i,norm);
- getUnitSpherePoints(highres)[numSampleDirections] = norm;
- numSampleDirections++;
- }
- }
- }
-
- btVector3 supportPoints[NUM_UNITSPHERE_POINTS_HIGHRES+MAX_PREFERRED_PENETRATION_DIRECTIONS*2];
+
+ int numSampleDirections = highres ? NUM_UNITSPHERE_POINTS_HIGHRES : NUM_UNITSPHERE_POINTS;
+ btVector3 supportPoints[NUM_UNITSPHERE_POINTS_HIGHRES + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2];
int i;
for (i = 0; i < numSampleDirections; i++)
{
supportPoints[i] = m_shape->localGetSupportingVertex(getUnitSpherePoints(highres)[i]);
}
+ int numPDA = m_shape->getNumPreferredPenetrationDirections();
+ if (numPDA)
+ {
+ for (int s = 0; s < numPDA; s++)
+ {
+ btVector3 norm;
+ m_shape->getPreferredPenetrationDirection(s, norm);
+ supportPoints[i++] = m_shape->localGetSupportingVertex(norm);
+ numSampleDirections++;
+ }
+ }
HullDesc hd;
hd.mFlags = QF_TRIANGLES;
hd.mVcount = static_cast<unsigned int>(numSampleDirections);
@@ -71,18 +66,17 @@ btShapeHull::buildHull (btScalar /*margin*/, int highres)
hd.mVertexStride = sizeof(btVector3);
#else
hd.mVertices = &supportPoints[0];
- hd.mVertexStride = sizeof (btVector3);
+ hd.mVertexStride = sizeof(btVector3);
#endif
HullLibrary hl;
HullResult hr;
- if (hl.CreateConvexHull (hd, hr) == QE_FAIL)
+ if (hl.CreateConvexHull(hd, hr) == QE_FAIL)
{
return false;
}
- m_vertices.resize (static_cast<int>(hr.mNumOutputVertices));
-
+ m_vertices.resize(static_cast<int>(hr.mNumOutputVertices));
for (i = 0; i < static_cast<int>(hr.mNumOutputVertices); i++)
{
@@ -96,338 +90,332 @@ btShapeHull::buildHull (btScalar /*margin*/, int highres)
}
// free temporary hull result that we just copied
- hl.ReleaseResult (hr);
+ hl.ReleaseResult(hr);
return true;
}
-int
-btShapeHull::numTriangles () const
+int btShapeHull::numTriangles() const
{
return static_cast<int>(m_numIndices / 3);
}
-int
-btShapeHull::numVertices () const
+int btShapeHull::numVertices() const
{
- return m_vertices.size ();
+ return m_vertices.size();
}
-int
-btShapeHull::numIndices () const
+int btShapeHull::numIndices() const
{
return static_cast<int>(m_numIndices);
}
-
btVector3* btShapeHull::getUnitSpherePoints(int highres)
{
static btVector3 sUnitSpherePointsHighres[NUM_UNITSPHERE_POINTS_HIGHRES + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2] =
- {
- btVector3(btScalar(0.997604), btScalar(0.067004), btScalar(0.017144)),
- btVector3(btScalar(0.984139), btScalar(-0.086784), btScalar(-0.154427)),
- btVector3(btScalar(0.971065), btScalar(0.124164), btScalar(-0.203224)),
- btVector3(btScalar(0.955844), btScalar(0.291173), btScalar(-0.037704)),
- btVector3(btScalar(0.957405), btScalar(0.212238), btScalar(0.195157)),
- btVector3(btScalar(0.971650), btScalar(-0.012709), btScalar(0.235561)),
- btVector3(btScalar(0.984920), btScalar(-0.161831), btScalar(0.059695)),
- btVector3(btScalar(0.946673), btScalar(-0.299288), btScalar(-0.117536)),
- btVector3(btScalar(0.922670), btScalar(-0.219186), btScalar(-0.317019)),
- btVector3(btScalar(0.928134), btScalar(-0.007265), btScalar(-0.371867)),
- btVector3(btScalar(0.875642), btScalar(0.198434), btScalar(-0.439988)),
- btVector3(btScalar(0.908035), btScalar(0.325975), btScalar(-0.262562)),
- btVector3(btScalar(0.864519), btScalar(0.488706), btScalar(-0.116755)),
- btVector3(btScalar(0.893009), btScalar(0.428046), btScalar(0.137185)),
- btVector3(btScalar(0.857494), btScalar(0.362137), btScalar(0.364776)),
- btVector3(btScalar(0.900815), btScalar(0.132524), btScalar(0.412987)),
- btVector3(btScalar(0.934964), btScalar(-0.241739), btScalar(0.259179)),
- btVector3(btScalar(0.894570), btScalar(-0.103504), btScalar(0.434263)),
- btVector3(btScalar(0.922085), btScalar(-0.376668), btScalar(0.086241)),
- btVector3(btScalar(0.862177), btScalar(-0.499154), btScalar(-0.085330)),
- btVector3(btScalar(0.861982), btScalar(-0.420218), btScalar(-0.282861)),
- btVector3(btScalar(0.818076), btScalar(-0.328256), btScalar(-0.471804)),
- btVector3(btScalar(0.762657), btScalar(-0.179329), btScalar(-0.621124)),
- btVector3(btScalar(0.826857), btScalar(0.019760), btScalar(-0.561786)),
- btVector3(btScalar(0.731434), btScalar(0.206599), btScalar(-0.649817)),
- btVector3(btScalar(0.769486), btScalar(0.379052), btScalar(-0.513770)),
- btVector3(btScalar(0.796806), btScalar(0.507176), btScalar(-0.328145)),
- btVector3(btScalar(0.679722), btScalar(0.684101), btScalar(-0.264123)),
- btVector3(btScalar(0.786854), btScalar(0.614886), btScalar(0.050912)),
- btVector3(btScalar(0.769486), btScalar(0.571141), btScalar(0.285139)),
- btVector3(btScalar(0.707432), btScalar(0.492789), btScalar(0.506288)),
- btVector3(btScalar(0.774560), btScalar(0.268037), btScalar(0.572652)),
- btVector3(btScalar(0.796220), btScalar(0.031230), btScalar(0.604077)),
- btVector3(btScalar(0.837395), btScalar(-0.320285), btScalar(0.442461)),
- btVector3(btScalar(0.848127), btScalar(-0.450548), btScalar(0.278307)),
- btVector3(btScalar(0.775536), btScalar(-0.206354), btScalar(0.596465)),
- btVector3(btScalar(0.816320), btScalar(-0.567007), btScalar(0.109469)),
- btVector3(btScalar(0.741191), btScalar(-0.668690), btScalar(-0.056832)),
- btVector3(btScalar(0.755632), btScalar(-0.602975), btScalar(-0.254949)),
- btVector3(btScalar(0.720311), btScalar(-0.521318), btScalar(-0.457165)),
- btVector3(btScalar(0.670746), btScalar(-0.386583), btScalar(-0.632835)),
- btVector3(btScalar(0.587031), btScalar(-0.219769), btScalar(-0.778836)),
- btVector3(btScalar(0.676015), btScalar(-0.003182), btScalar(-0.736676)),
- btVector3(btScalar(0.566932), btScalar(0.186963), btScalar(-0.802064)),
- btVector3(btScalar(0.618254), btScalar(0.398105), btScalar(-0.677533)),
- btVector3(btScalar(0.653964), btScalar(0.575224), btScalar(-0.490933)),
- btVector3(btScalar(0.525367), btScalar(0.743205), btScalar(-0.414028)),
- btVector3(btScalar(0.506439), btScalar(0.836528), btScalar(-0.208885)),
- btVector3(btScalar(0.651427), btScalar(0.756426), btScalar(-0.056247)),
- btVector3(btScalar(0.641670), btScalar(0.745149), btScalar(0.180908)),
- btVector3(btScalar(0.602643), btScalar(0.687211), btScalar(0.405180)),
- btVector3(btScalar(0.516586), btScalar(0.596999), btScalar(0.613447)),
- btVector3(btScalar(0.602252), btScalar(0.387801), btScalar(0.697573)),
- btVector3(btScalar(0.646549), btScalar(0.153911), btScalar(0.746956)),
- btVector3(btScalar(0.650842), btScalar(-0.087756), btScalar(0.753983)),
- btVector3(btScalar(0.740411), btScalar(-0.497404), btScalar(0.451830)),
- btVector3(btScalar(0.726946), btScalar(-0.619890), btScalar(0.295093)),
- btVector3(btScalar(0.637768), btScalar(-0.313092), btScalar(0.703624)),
- btVector3(btScalar(0.678942), btScalar(-0.722934), btScalar(0.126645)),
- btVector3(btScalar(0.489072), btScalar(-0.867195), btScalar(-0.092942)),
- btVector3(btScalar(0.622742), btScalar(-0.757541), btScalar(-0.194636)),
- btVector3(btScalar(0.596788), btScalar(-0.693576), btScalar(-0.403098)),
- btVector3(btScalar(0.550150), btScalar(-0.582172), btScalar(-0.598287)),
- btVector3(btScalar(0.474436), btScalar(-0.429745), btScalar(-0.768101)),
- btVector3(btScalar(0.372574), btScalar(-0.246016), btScalar(-0.894583)),
- btVector3(btScalar(0.480095), btScalar(-0.026513), btScalar(-0.876626)),
- btVector3(btScalar(0.352474), btScalar(0.177242), btScalar(-0.918787)),
- btVector3(btScalar(0.441848), btScalar(0.374386), btScalar(-0.814946)),
- btVector3(btScalar(0.492389), btScalar(0.582223), btScalar(-0.646693)),
- btVector3(btScalar(0.343498), btScalar(0.866080), btScalar(-0.362693)),
- btVector3(btScalar(0.362036), btScalar(0.745149), btScalar(-0.559639)),
- btVector3(btScalar(0.334131), btScalar(0.937044), btScalar(-0.099774)),
- btVector3(btScalar(0.486925), btScalar(0.871718), btScalar(0.052473)),
- btVector3(btScalar(0.452776), btScalar(0.845665), btScalar(0.281820)),
- btVector3(btScalar(0.399503), btScalar(0.771785), btScalar(0.494576)),
- btVector3(btScalar(0.296469), btScalar(0.673018), btScalar(0.677469)),
- btVector3(btScalar(0.392088), btScalar(0.479179), btScalar(0.785213)),
- btVector3(btScalar(0.452190), btScalar(0.252094), btScalar(0.855286)),
- btVector3(btScalar(0.478339), btScalar(0.013149), btScalar(0.877928)),
- btVector3(btScalar(0.481656), btScalar(-0.219380), btScalar(0.848259)),
- btVector3(btScalar(0.615327), btScalar(-0.494293), btScalar(0.613837)),
- btVector3(btScalar(0.594642), btScalar(-0.650414), btScalar(0.472325)),
- btVector3(btScalar(0.562249), btScalar(-0.771345), btScalar(0.297631)),
- btVector3(btScalar(0.467411), btScalar(-0.437133), btScalar(0.768231)),
- btVector3(btScalar(0.519513), btScalar(-0.847947), btScalar(0.103808)),
- btVector3(btScalar(0.297640), btScalar(-0.938159), btScalar(-0.176288)),
- btVector3(btScalar(0.446727), btScalar(-0.838615), btScalar(-0.311359)),
- btVector3(btScalar(0.331790), btScalar(-0.942437), btScalar(0.040762)),
- btVector3(btScalar(0.413358), btScalar(-0.748403), btScalar(-0.518259)),
- btVector3(btScalar(0.347596), btScalar(-0.621640), btScalar(-0.701737)),
- btVector3(btScalar(0.249831), btScalar(-0.456186), btScalar(-0.853984)),
- btVector3(btScalar(0.131772), btScalar(-0.262931), btScalar(-0.955678)),
- btVector3(btScalar(0.247099), btScalar(-0.042261), btScalar(-0.967975)),
- btVector3(btScalar(0.113624), btScalar(0.165965), btScalar(-0.979491)),
- btVector3(btScalar(0.217438), btScalar(0.374580), btScalar(-0.901220)),
- btVector3(btScalar(0.307983), btScalar(0.554615), btScalar(-0.772786)),
- btVector3(btScalar(0.166702), btScalar(0.953181), btScalar(-0.252021)),
- btVector3(btScalar(0.172751), btScalar(0.844499), btScalar(-0.506743)),
- btVector3(btScalar(0.177630), btScalar(0.711125), btScalar(-0.679876)),
- btVector3(btScalar(0.120064), btScalar(0.992260), btScalar(-0.030482)),
- btVector3(btScalar(0.289640), btScalar(0.949098), btScalar(0.122546)),
- btVector3(btScalar(0.239879), btScalar(0.909047), btScalar(0.340377)),
- btVector3(btScalar(0.181142), btScalar(0.821363), btScalar(0.540641)),
- btVector3(btScalar(0.066986), btScalar(0.719097), btScalar(0.691327)),
- btVector3(btScalar(0.156750), btScalar(0.545478), btScalar(0.823079)),
- btVector3(btScalar(0.236172), btScalar(0.342306), btScalar(0.909353)),
- btVector3(btScalar(0.277541), btScalar(0.112693), btScalar(0.953856)),
- btVector3(btScalar(0.295299), btScalar(-0.121974), btScalar(0.947415)),
- btVector3(btScalar(0.287883), btScalar(-0.349254), btScalar(0.891591)),
- btVector3(btScalar(0.437165), btScalar(-0.634666), btScalar(0.636869)),
- btVector3(btScalar(0.407113), btScalar(-0.784954), btScalar(0.466664)),
- btVector3(btScalar(0.375111), btScalar(-0.888193), btScalar(0.264839)),
- btVector3(btScalar(0.275394), btScalar(-0.560591), btScalar(0.780723)),
- btVector3(btScalar(0.122015), btScalar(-0.992209), btScalar(-0.024821)),
- btVector3(btScalar(0.087866), btScalar(-0.966156), btScalar(-0.241676)),
- btVector3(btScalar(0.239489), btScalar(-0.885665), btScalar(-0.397437)),
- btVector3(btScalar(0.167287), btScalar(-0.965184), btScalar(0.200817)),
- btVector3(btScalar(0.201632), btScalar(-0.776789), btScalar(-0.596335)),
- btVector3(btScalar(0.122015), btScalar(-0.637971), btScalar(-0.760098)),
- btVector3(btScalar(0.008054), btScalar(-0.464741), btScalar(-0.885214)),
- btVector3(btScalar(-0.116054), btScalar(-0.271096), btScalar(-0.955482)),
- btVector3(btScalar(-0.000727), btScalar(-0.056065), btScalar(-0.998424)),
- btVector3(btScalar(-0.134007), btScalar(0.152939), btScalar(-0.978905)),
- btVector3(btScalar(-0.025900), btScalar(0.366026), btScalar(-0.930108)),
- btVector3(btScalar(0.081231), btScalar(0.557337), btScalar(-0.826072)),
- btVector3(btScalar(-0.002874), btScalar(0.917213), btScalar(-0.398023)),
- btVector3(btScalar(-0.050683), btScalar(0.981761), btScalar(-0.182534)),
- btVector3(btScalar(-0.040536), btScalar(0.710153), btScalar(-0.702713)),
- btVector3(btScalar(-0.139081), btScalar(0.827973), btScalar(-0.543048)),
- btVector3(btScalar(-0.101029), btScalar(0.994010), btScalar(0.041152)),
- btVector3(btScalar(0.069328), btScalar(0.978067), btScalar(0.196133)),
- btVector3(btScalar(0.023860), btScalar(0.911380), btScalar(0.410645)),
- btVector3(btScalar(-0.153521), btScalar(0.736789), btScalar(0.658145)),
- btVector3(btScalar(-0.070002), btScalar(0.591750), btScalar(0.802780)),
- btVector3(btScalar(0.002590), btScalar(0.312948), btScalar(0.949562)),
- btVector3(btScalar(0.090988), btScalar(-0.020680), btScalar(0.995627)),
- btVector3(btScalar(0.088842), btScalar(-0.250099), btScalar(0.964006)),
- btVector3(btScalar(0.083378), btScalar(-0.470185), btScalar(0.878318)),
- btVector3(btScalar(0.240074), btScalar(-0.749764), btScalar(0.616374)),
- btVector3(btScalar(0.210803), btScalar(-0.885860), btScalar(0.412987)),
- btVector3(btScalar(0.077524), btScalar(-0.660524), btScalar(0.746565)),
- btVector3(btScalar(-0.096736), btScalar(-0.990070), btScalar(-0.100945)),
- btVector3(btScalar(-0.052634), btScalar(-0.990264), btScalar(0.127426)),
- btVector3(btScalar(-0.106102), btScalar(-0.938354), btScalar(-0.328340)),
- btVector3(btScalar(0.013323), btScalar(-0.863112), btScalar(-0.504596)),
- btVector3(btScalar(-0.002093), btScalar(-0.936993), btScalar(0.349161)),
- btVector3(btScalar(-0.106297), btScalar(-0.636610), btScalar(-0.763612)),
- btVector3(btScalar(-0.229430), btScalar(-0.463769), btScalar(-0.855546)),
- btVector3(btScalar(-0.245236), btScalar(-0.066175), btScalar(-0.966999)),
- btVector3(btScalar(-0.351587), btScalar(-0.270513), btScalar(-0.896145)),
- btVector3(btScalar(-0.370906), btScalar(0.133108), btScalar(-0.918982)),
- btVector3(btScalar(-0.264360), btScalar(0.346000), btScalar(-0.900049)),
- btVector3(btScalar(-0.151375), btScalar(0.543728), btScalar(-0.825291)),
- btVector3(btScalar(-0.218697), btScalar(0.912741), btScalar(-0.344346)),
- btVector3(btScalar(-0.274507), btScalar(0.953764), btScalar(-0.121635)),
- btVector3(btScalar(-0.259677), btScalar(0.692266), btScalar(-0.673044)),
- btVector3(btScalar(-0.350416), btScalar(0.798810), btScalar(-0.488786)),
- btVector3(btScalar(-0.320170), btScalar(0.941127), btScalar(0.108297)),
- btVector3(btScalar(-0.147667), btScalar(0.952792), btScalar(0.265034)),
- btVector3(btScalar(-0.188061), btScalar(0.860636), btScalar(0.472910)),
- btVector3(btScalar(-0.370906), btScalar(0.739900), btScalar(0.560941)),
- btVector3(btScalar(-0.297143), btScalar(0.585334), btScalar(0.754178)),
- btVector3(btScalar(-0.189622), btScalar(0.428241), btScalar(0.883393)),
- btVector3(btScalar(-0.091272), btScalar(0.098695), btScalar(0.990747)),
- btVector3(btScalar(-0.256945), btScalar(0.228375), btScalar(0.938827)),
- btVector3(btScalar(-0.111761), btScalar(-0.133251), btScalar(0.984696)),
- btVector3(btScalar(-0.118006), btScalar(-0.356253), btScalar(0.926725)),
- btVector3(btScalar(-0.119372), btScalar(-0.563896), btScalar(0.817029)),
- btVector3(btScalar(0.041228), btScalar(-0.833949), btScalar(0.550010)),
- btVector3(btScalar(-0.121909), btScalar(-0.736543), btScalar(0.665172)),
- btVector3(btScalar(-0.307681), btScalar(-0.931160), btScalar(-0.195026)),
- btVector3(btScalar(-0.283679), btScalar(-0.957990), btScalar(0.041348)),
- btVector3(btScalar(-0.227284), btScalar(-0.935243), btScalar(0.270890)),
- btVector3(btScalar(-0.293436), btScalar(-0.858252), btScalar(-0.420860)),
- btVector3(btScalar(-0.175767), btScalar(-0.780677), btScalar(-0.599262)),
- btVector3(btScalar(-0.170108), btScalar(-0.858835), btScalar(0.482865)),
- btVector3(btScalar(-0.332854), btScalar(-0.635055), btScalar(-0.696857)),
- btVector3(btScalar(-0.447791), btScalar(-0.445299), btScalar(-0.775128)),
- btVector3(btScalar(-0.470622), btScalar(-0.074146), btScalar(-0.879164)),
- btVector3(btScalar(-0.639417), btScalar(-0.340505), btScalar(-0.689049)),
- btVector3(btScalar(-0.598438), btScalar(0.104722), btScalar(-0.794256)),
- btVector3(btScalar(-0.488575), btScalar(0.307699), btScalar(-0.816313)),
- btVector3(btScalar(-0.379882), btScalar(0.513592), btScalar(-0.769077)),
- btVector3(btScalar(-0.425740), btScalar(0.862775), btScalar(-0.272516)),
- btVector3(btScalar(-0.480769), btScalar(0.875412), btScalar(-0.048439)),
- btVector3(btScalar(-0.467890), btScalar(0.648716), btScalar(-0.600043)),
- btVector3(btScalar(-0.543799), btScalar(0.730956), btScalar(-0.411881)),
- btVector3(btScalar(-0.516284), btScalar(0.838277), btScalar(0.174076)),
- btVector3(btScalar(-0.353343), btScalar(0.876384), btScalar(0.326519)),
- btVector3(btScalar(-0.572875), btScalar(0.614497), btScalar(0.542007)),
- btVector3(btScalar(-0.503600), btScalar(0.497261), btScalar(0.706161)),
- btVector3(btScalar(-0.530920), btScalar(0.754870), btScalar(0.384685)),
- btVector3(btScalar(-0.395884), btScalar(0.366414), btScalar(0.841818)),
- btVector3(btScalar(-0.300656), btScalar(0.001678), btScalar(0.953661)),
- btVector3(btScalar(-0.461060), btScalar(0.146912), btScalar(0.875000)),
- btVector3(btScalar(-0.315486), btScalar(-0.232212), btScalar(0.919893)),
- btVector3(btScalar(-0.323682), btScalar(-0.449187), btScalar(0.832644)),
- btVector3(btScalar(-0.318999), btScalar(-0.639527), btScalar(0.699134)),
- btVector3(btScalar(-0.496771), btScalar(-0.866029), btScalar(-0.055271)),
- btVector3(btScalar(-0.496771), btScalar(-0.816257), btScalar(-0.294377)),
- btVector3(btScalar(-0.456377), btScalar(-0.869528), btScalar(0.188130)),
- btVector3(btScalar(-0.380858), btScalar(-0.827144), btScalar(0.412792)),
- btVector3(btScalar(-0.449352), btScalar(-0.727405), btScalar(-0.518259)),
- btVector3(btScalar(-0.570533), btScalar(-0.551064), btScalar(-0.608632)),
- btVector3(btScalar(-0.656394), btScalar(-0.118280), btScalar(-0.744874)),
- btVector3(btScalar(-0.756696), btScalar(-0.438105), btScalar(-0.484882)),
- btVector3(btScalar(-0.801773), btScalar(-0.204798), btScalar(-0.561005)),
- btVector3(btScalar(-0.785186), btScalar(0.038618), btScalar(-0.617805)),
- btVector3(btScalar(-0.709082), btScalar(0.262399), btScalar(-0.654306)),
- btVector3(btScalar(-0.583412), btScalar(0.462265), btScalar(-0.667383)),
- btVector3(btScalar(-0.616001), btScalar(0.761286), btScalar(-0.201272)),
- btVector3(btScalar(-0.660687), btScalar(0.750204), btScalar(0.020072)),
- btVector3(btScalar(-0.744987), btScalar(0.435823), btScalar(-0.504791)),
- btVector3(btScalar(-0.713765), btScalar(0.605554), btScalar(-0.351373)),
- btVector3(btScalar(-0.686251), btScalar(0.687600), btScalar(0.236927)),
- btVector3(btScalar(-0.680201), btScalar(0.429407), btScalar(0.593732)),
- btVector3(btScalar(-0.733474), btScalar(0.546450), btScalar(0.403814)),
- btVector3(btScalar(-0.591023), btScalar(0.292923), btScalar(0.751445)),
- btVector3(btScalar(-0.500283), btScalar(-0.080757), btScalar(0.861922)),
- btVector3(btScalar(-0.643710), btScalar(0.070115), btScalar(0.761985)),
- btVector3(btScalar(-0.506332), btScalar(-0.308425), btScalar(0.805122)),
- btVector3(btScalar(-0.503015), btScalar(-0.509847), btScalar(0.697573)),
- btVector3(btScalar(-0.482525), btScalar(-0.682105), btScalar(0.549229)),
- btVector3(btScalar(-0.680396), btScalar(-0.716323), btScalar(-0.153451)),
- btVector3(btScalar(-0.658346), btScalar(-0.746264), btScalar(0.097562)),
- btVector3(btScalar(-0.653272), btScalar(-0.646915), btScalar(-0.392948)),
- btVector3(btScalar(-0.590828), btScalar(-0.732655), btScalar(0.337645)),
- btVector3(btScalar(-0.819140), btScalar(-0.518013), btScalar(-0.246166)),
- btVector3(btScalar(-0.900513), btScalar(-0.282178), btScalar(-0.330487)),
- btVector3(btScalar(-0.914953), btScalar(-0.028652), btScalar(-0.402122)),
- btVector3(btScalar(-0.859924), btScalar(0.220209), btScalar(-0.459898)),
- btVector3(btScalar(-0.777185), btScalar(0.613720), btScalar(-0.137836)),
- btVector3(btScalar(-0.805285), btScalar(0.586889), btScalar(0.082728)),
- btVector3(btScalar(-0.872413), btScalar(0.406077), btScalar(-0.271735)),
- btVector3(btScalar(-0.859339), btScalar(0.448072), btScalar(0.246101)),
- btVector3(btScalar(-0.757671), btScalar(0.216320), btScalar(0.615594)),
- btVector3(btScalar(-0.826165), btScalar(0.348139), btScalar(0.442851)),
- btVector3(btScalar(-0.671810), btScalar(-0.162803), btScalar(0.722557)),
- btVector3(btScalar(-0.796504), btScalar(-0.004543), btScalar(0.604468)),
- btVector3(btScalar(-0.676298), btScalar(-0.378223), btScalar(0.631794)),
- btVector3(btScalar(-0.668883), btScalar(-0.558258), btScalar(0.490673)),
- btVector3(btScalar(-0.821287), btScalar(-0.570118), btScalar(0.006994)),
- btVector3(btScalar(-0.767428), btScalar(-0.587810), btScalar(0.255470)),
- btVector3(btScalar(-0.933296), btScalar(-0.349837), btScalar(-0.079865)),
- btVector3(btScalar(-0.982667), btScalar(-0.100393), btScalar(-0.155208)),
- btVector3(btScalar(-0.961396), btScalar(0.160910), btScalar(-0.222938)),
- btVector3(btScalar(-0.934858), btScalar(0.354555), btScalar(-0.006864)),
- btVector3(btScalar(-0.941687), btScalar(0.229736), btScalar(0.245711)),
- btVector3(btScalar(-0.884317), btScalar(0.131552), btScalar(0.447536)),
- btVector3(btScalar(-0.810359), btScalar(-0.219769), btScalar(0.542788)),
- btVector3(btScalar(-0.915929), btScalar(-0.210048), btScalar(0.341743)),
- btVector3(btScalar(-0.816799), btScalar(-0.407192), btScalar(0.408303)),
- btVector3(btScalar(-0.903050), btScalar(-0.392416), btScalar(0.174076)),
- btVector3(btScalar(-0.980325), btScalar(-0.170969), btScalar(0.096586)),
- btVector3(btScalar(-0.995936), btScalar(0.084891), btScalar(0.029441)),
- btVector3(btScalar(-0.960031), btScalar(0.002650), btScalar(0.279283)),
- };
+ {
+ btVector3(btScalar(0.997604), btScalar(0.067004), btScalar(0.017144)),
+ btVector3(btScalar(0.984139), btScalar(-0.086784), btScalar(-0.154427)),
+ btVector3(btScalar(0.971065), btScalar(0.124164), btScalar(-0.203224)),
+ btVector3(btScalar(0.955844), btScalar(0.291173), btScalar(-0.037704)),
+ btVector3(btScalar(0.957405), btScalar(0.212238), btScalar(0.195157)),
+ btVector3(btScalar(0.971650), btScalar(-0.012709), btScalar(0.235561)),
+ btVector3(btScalar(0.984920), btScalar(-0.161831), btScalar(0.059695)),
+ btVector3(btScalar(0.946673), btScalar(-0.299288), btScalar(-0.117536)),
+ btVector3(btScalar(0.922670), btScalar(-0.219186), btScalar(-0.317019)),
+ btVector3(btScalar(0.928134), btScalar(-0.007265), btScalar(-0.371867)),
+ btVector3(btScalar(0.875642), btScalar(0.198434), btScalar(-0.439988)),
+ btVector3(btScalar(0.908035), btScalar(0.325975), btScalar(-0.262562)),
+ btVector3(btScalar(0.864519), btScalar(0.488706), btScalar(-0.116755)),
+ btVector3(btScalar(0.893009), btScalar(0.428046), btScalar(0.137185)),
+ btVector3(btScalar(0.857494), btScalar(0.362137), btScalar(0.364776)),
+ btVector3(btScalar(0.900815), btScalar(0.132524), btScalar(0.412987)),
+ btVector3(btScalar(0.934964), btScalar(-0.241739), btScalar(0.259179)),
+ btVector3(btScalar(0.894570), btScalar(-0.103504), btScalar(0.434263)),
+ btVector3(btScalar(0.922085), btScalar(-0.376668), btScalar(0.086241)),
+ btVector3(btScalar(0.862177), btScalar(-0.499154), btScalar(-0.085330)),
+ btVector3(btScalar(0.861982), btScalar(-0.420218), btScalar(-0.282861)),
+ btVector3(btScalar(0.818076), btScalar(-0.328256), btScalar(-0.471804)),
+ btVector3(btScalar(0.762657), btScalar(-0.179329), btScalar(-0.621124)),
+ btVector3(btScalar(0.826857), btScalar(0.019760), btScalar(-0.561786)),
+ btVector3(btScalar(0.731434), btScalar(0.206599), btScalar(-0.649817)),
+ btVector3(btScalar(0.769486), btScalar(0.379052), btScalar(-0.513770)),
+ btVector3(btScalar(0.796806), btScalar(0.507176), btScalar(-0.328145)),
+ btVector3(btScalar(0.679722), btScalar(0.684101), btScalar(-0.264123)),
+ btVector3(btScalar(0.786854), btScalar(0.614886), btScalar(0.050912)),
+ btVector3(btScalar(0.769486), btScalar(0.571141), btScalar(0.285139)),
+ btVector3(btScalar(0.707432), btScalar(0.492789), btScalar(0.506288)),
+ btVector3(btScalar(0.774560), btScalar(0.268037), btScalar(0.572652)),
+ btVector3(btScalar(0.796220), btScalar(0.031230), btScalar(0.604077)),
+ btVector3(btScalar(0.837395), btScalar(-0.320285), btScalar(0.442461)),
+ btVector3(btScalar(0.848127), btScalar(-0.450548), btScalar(0.278307)),
+ btVector3(btScalar(0.775536), btScalar(-0.206354), btScalar(0.596465)),
+ btVector3(btScalar(0.816320), btScalar(-0.567007), btScalar(0.109469)),
+ btVector3(btScalar(0.741191), btScalar(-0.668690), btScalar(-0.056832)),
+ btVector3(btScalar(0.755632), btScalar(-0.602975), btScalar(-0.254949)),
+ btVector3(btScalar(0.720311), btScalar(-0.521318), btScalar(-0.457165)),
+ btVector3(btScalar(0.670746), btScalar(-0.386583), btScalar(-0.632835)),
+ btVector3(btScalar(0.587031), btScalar(-0.219769), btScalar(-0.778836)),
+ btVector3(btScalar(0.676015), btScalar(-0.003182), btScalar(-0.736676)),
+ btVector3(btScalar(0.566932), btScalar(0.186963), btScalar(-0.802064)),
+ btVector3(btScalar(0.618254), btScalar(0.398105), btScalar(-0.677533)),
+ btVector3(btScalar(0.653964), btScalar(0.575224), btScalar(-0.490933)),
+ btVector3(btScalar(0.525367), btScalar(0.743205), btScalar(-0.414028)),
+ btVector3(btScalar(0.506439), btScalar(0.836528), btScalar(-0.208885)),
+ btVector3(btScalar(0.651427), btScalar(0.756426), btScalar(-0.056247)),
+ btVector3(btScalar(0.641670), btScalar(0.745149), btScalar(0.180908)),
+ btVector3(btScalar(0.602643), btScalar(0.687211), btScalar(0.405180)),
+ btVector3(btScalar(0.516586), btScalar(0.596999), btScalar(0.613447)),
+ btVector3(btScalar(0.602252), btScalar(0.387801), btScalar(0.697573)),
+ btVector3(btScalar(0.646549), btScalar(0.153911), btScalar(0.746956)),
+ btVector3(btScalar(0.650842), btScalar(-0.087756), btScalar(0.753983)),
+ btVector3(btScalar(0.740411), btScalar(-0.497404), btScalar(0.451830)),
+ btVector3(btScalar(0.726946), btScalar(-0.619890), btScalar(0.295093)),
+ btVector3(btScalar(0.637768), btScalar(-0.313092), btScalar(0.703624)),
+ btVector3(btScalar(0.678942), btScalar(-0.722934), btScalar(0.126645)),
+ btVector3(btScalar(0.489072), btScalar(-0.867195), btScalar(-0.092942)),
+ btVector3(btScalar(0.622742), btScalar(-0.757541), btScalar(-0.194636)),
+ btVector3(btScalar(0.596788), btScalar(-0.693576), btScalar(-0.403098)),
+ btVector3(btScalar(0.550150), btScalar(-0.582172), btScalar(-0.598287)),
+ btVector3(btScalar(0.474436), btScalar(-0.429745), btScalar(-0.768101)),
+ btVector3(btScalar(0.372574), btScalar(-0.246016), btScalar(-0.894583)),
+ btVector3(btScalar(0.480095), btScalar(-0.026513), btScalar(-0.876626)),
+ btVector3(btScalar(0.352474), btScalar(0.177242), btScalar(-0.918787)),
+ btVector3(btScalar(0.441848), btScalar(0.374386), btScalar(-0.814946)),
+ btVector3(btScalar(0.492389), btScalar(0.582223), btScalar(-0.646693)),
+ btVector3(btScalar(0.343498), btScalar(0.866080), btScalar(-0.362693)),
+ btVector3(btScalar(0.362036), btScalar(0.745149), btScalar(-0.559639)),
+ btVector3(btScalar(0.334131), btScalar(0.937044), btScalar(-0.099774)),
+ btVector3(btScalar(0.486925), btScalar(0.871718), btScalar(0.052473)),
+ btVector3(btScalar(0.452776), btScalar(0.845665), btScalar(0.281820)),
+ btVector3(btScalar(0.399503), btScalar(0.771785), btScalar(0.494576)),
+ btVector3(btScalar(0.296469), btScalar(0.673018), btScalar(0.677469)),
+ btVector3(btScalar(0.392088), btScalar(0.479179), btScalar(0.785213)),
+ btVector3(btScalar(0.452190), btScalar(0.252094), btScalar(0.855286)),
+ btVector3(btScalar(0.478339), btScalar(0.013149), btScalar(0.877928)),
+ btVector3(btScalar(0.481656), btScalar(-0.219380), btScalar(0.848259)),
+ btVector3(btScalar(0.615327), btScalar(-0.494293), btScalar(0.613837)),
+ btVector3(btScalar(0.594642), btScalar(-0.650414), btScalar(0.472325)),
+ btVector3(btScalar(0.562249), btScalar(-0.771345), btScalar(0.297631)),
+ btVector3(btScalar(0.467411), btScalar(-0.437133), btScalar(0.768231)),
+ btVector3(btScalar(0.519513), btScalar(-0.847947), btScalar(0.103808)),
+ btVector3(btScalar(0.297640), btScalar(-0.938159), btScalar(-0.176288)),
+ btVector3(btScalar(0.446727), btScalar(-0.838615), btScalar(-0.311359)),
+ btVector3(btScalar(0.331790), btScalar(-0.942437), btScalar(0.040762)),
+ btVector3(btScalar(0.413358), btScalar(-0.748403), btScalar(-0.518259)),
+ btVector3(btScalar(0.347596), btScalar(-0.621640), btScalar(-0.701737)),
+ btVector3(btScalar(0.249831), btScalar(-0.456186), btScalar(-0.853984)),
+ btVector3(btScalar(0.131772), btScalar(-0.262931), btScalar(-0.955678)),
+ btVector3(btScalar(0.247099), btScalar(-0.042261), btScalar(-0.967975)),
+ btVector3(btScalar(0.113624), btScalar(0.165965), btScalar(-0.979491)),
+ btVector3(btScalar(0.217438), btScalar(0.374580), btScalar(-0.901220)),
+ btVector3(btScalar(0.307983), btScalar(0.554615), btScalar(-0.772786)),
+ btVector3(btScalar(0.166702), btScalar(0.953181), btScalar(-0.252021)),
+ btVector3(btScalar(0.172751), btScalar(0.844499), btScalar(-0.506743)),
+ btVector3(btScalar(0.177630), btScalar(0.711125), btScalar(-0.679876)),
+ btVector3(btScalar(0.120064), btScalar(0.992260), btScalar(-0.030482)),
+ btVector3(btScalar(0.289640), btScalar(0.949098), btScalar(0.122546)),
+ btVector3(btScalar(0.239879), btScalar(0.909047), btScalar(0.340377)),
+ btVector3(btScalar(0.181142), btScalar(0.821363), btScalar(0.540641)),
+ btVector3(btScalar(0.066986), btScalar(0.719097), btScalar(0.691327)),
+ btVector3(btScalar(0.156750), btScalar(0.545478), btScalar(0.823079)),
+ btVector3(btScalar(0.236172), btScalar(0.342306), btScalar(0.909353)),
+ btVector3(btScalar(0.277541), btScalar(0.112693), btScalar(0.953856)),
+ btVector3(btScalar(0.295299), btScalar(-0.121974), btScalar(0.947415)),
+ btVector3(btScalar(0.287883), btScalar(-0.349254), btScalar(0.891591)),
+ btVector3(btScalar(0.437165), btScalar(-0.634666), btScalar(0.636869)),
+ btVector3(btScalar(0.407113), btScalar(-0.784954), btScalar(0.466664)),
+ btVector3(btScalar(0.375111), btScalar(-0.888193), btScalar(0.264839)),
+ btVector3(btScalar(0.275394), btScalar(-0.560591), btScalar(0.780723)),
+ btVector3(btScalar(0.122015), btScalar(-0.992209), btScalar(-0.024821)),
+ btVector3(btScalar(0.087866), btScalar(-0.966156), btScalar(-0.241676)),
+ btVector3(btScalar(0.239489), btScalar(-0.885665), btScalar(-0.397437)),
+ btVector3(btScalar(0.167287), btScalar(-0.965184), btScalar(0.200817)),
+ btVector3(btScalar(0.201632), btScalar(-0.776789), btScalar(-0.596335)),
+ btVector3(btScalar(0.122015), btScalar(-0.637971), btScalar(-0.760098)),
+ btVector3(btScalar(0.008054), btScalar(-0.464741), btScalar(-0.885214)),
+ btVector3(btScalar(-0.116054), btScalar(-0.271096), btScalar(-0.955482)),
+ btVector3(btScalar(-0.000727), btScalar(-0.056065), btScalar(-0.998424)),
+ btVector3(btScalar(-0.134007), btScalar(0.152939), btScalar(-0.978905)),
+ btVector3(btScalar(-0.025900), btScalar(0.366026), btScalar(-0.930108)),
+ btVector3(btScalar(0.081231), btScalar(0.557337), btScalar(-0.826072)),
+ btVector3(btScalar(-0.002874), btScalar(0.917213), btScalar(-0.398023)),
+ btVector3(btScalar(-0.050683), btScalar(0.981761), btScalar(-0.182534)),
+ btVector3(btScalar(-0.040536), btScalar(0.710153), btScalar(-0.702713)),
+ btVector3(btScalar(-0.139081), btScalar(0.827973), btScalar(-0.543048)),
+ btVector3(btScalar(-0.101029), btScalar(0.994010), btScalar(0.041152)),
+ btVector3(btScalar(0.069328), btScalar(0.978067), btScalar(0.196133)),
+ btVector3(btScalar(0.023860), btScalar(0.911380), btScalar(0.410645)),
+ btVector3(btScalar(-0.153521), btScalar(0.736789), btScalar(0.658145)),
+ btVector3(btScalar(-0.070002), btScalar(0.591750), btScalar(0.802780)),
+ btVector3(btScalar(0.002590), btScalar(0.312948), btScalar(0.949562)),
+ btVector3(btScalar(0.090988), btScalar(-0.020680), btScalar(0.995627)),
+ btVector3(btScalar(0.088842), btScalar(-0.250099), btScalar(0.964006)),
+ btVector3(btScalar(0.083378), btScalar(-0.470185), btScalar(0.878318)),
+ btVector3(btScalar(0.240074), btScalar(-0.749764), btScalar(0.616374)),
+ btVector3(btScalar(0.210803), btScalar(-0.885860), btScalar(0.412987)),
+ btVector3(btScalar(0.077524), btScalar(-0.660524), btScalar(0.746565)),
+ btVector3(btScalar(-0.096736), btScalar(-0.990070), btScalar(-0.100945)),
+ btVector3(btScalar(-0.052634), btScalar(-0.990264), btScalar(0.127426)),
+ btVector3(btScalar(-0.106102), btScalar(-0.938354), btScalar(-0.328340)),
+ btVector3(btScalar(0.013323), btScalar(-0.863112), btScalar(-0.504596)),
+ btVector3(btScalar(-0.002093), btScalar(-0.936993), btScalar(0.349161)),
+ btVector3(btScalar(-0.106297), btScalar(-0.636610), btScalar(-0.763612)),
+ btVector3(btScalar(-0.229430), btScalar(-0.463769), btScalar(-0.855546)),
+ btVector3(btScalar(-0.245236), btScalar(-0.066175), btScalar(-0.966999)),
+ btVector3(btScalar(-0.351587), btScalar(-0.270513), btScalar(-0.896145)),
+ btVector3(btScalar(-0.370906), btScalar(0.133108), btScalar(-0.918982)),
+ btVector3(btScalar(-0.264360), btScalar(0.346000), btScalar(-0.900049)),
+ btVector3(btScalar(-0.151375), btScalar(0.543728), btScalar(-0.825291)),
+ btVector3(btScalar(-0.218697), btScalar(0.912741), btScalar(-0.344346)),
+ btVector3(btScalar(-0.274507), btScalar(0.953764), btScalar(-0.121635)),
+ btVector3(btScalar(-0.259677), btScalar(0.692266), btScalar(-0.673044)),
+ btVector3(btScalar(-0.350416), btScalar(0.798810), btScalar(-0.488786)),
+ btVector3(btScalar(-0.320170), btScalar(0.941127), btScalar(0.108297)),
+ btVector3(btScalar(-0.147667), btScalar(0.952792), btScalar(0.265034)),
+ btVector3(btScalar(-0.188061), btScalar(0.860636), btScalar(0.472910)),
+ btVector3(btScalar(-0.370906), btScalar(0.739900), btScalar(0.560941)),
+ btVector3(btScalar(-0.297143), btScalar(0.585334), btScalar(0.754178)),
+ btVector3(btScalar(-0.189622), btScalar(0.428241), btScalar(0.883393)),
+ btVector3(btScalar(-0.091272), btScalar(0.098695), btScalar(0.990747)),
+ btVector3(btScalar(-0.256945), btScalar(0.228375), btScalar(0.938827)),
+ btVector3(btScalar(-0.111761), btScalar(-0.133251), btScalar(0.984696)),
+ btVector3(btScalar(-0.118006), btScalar(-0.356253), btScalar(0.926725)),
+ btVector3(btScalar(-0.119372), btScalar(-0.563896), btScalar(0.817029)),
+ btVector3(btScalar(0.041228), btScalar(-0.833949), btScalar(0.550010)),
+ btVector3(btScalar(-0.121909), btScalar(-0.736543), btScalar(0.665172)),
+ btVector3(btScalar(-0.307681), btScalar(-0.931160), btScalar(-0.195026)),
+ btVector3(btScalar(-0.283679), btScalar(-0.957990), btScalar(0.041348)),
+ btVector3(btScalar(-0.227284), btScalar(-0.935243), btScalar(0.270890)),
+ btVector3(btScalar(-0.293436), btScalar(-0.858252), btScalar(-0.420860)),
+ btVector3(btScalar(-0.175767), btScalar(-0.780677), btScalar(-0.599262)),
+ btVector3(btScalar(-0.170108), btScalar(-0.858835), btScalar(0.482865)),
+ btVector3(btScalar(-0.332854), btScalar(-0.635055), btScalar(-0.696857)),
+ btVector3(btScalar(-0.447791), btScalar(-0.445299), btScalar(-0.775128)),
+ btVector3(btScalar(-0.470622), btScalar(-0.074146), btScalar(-0.879164)),
+ btVector3(btScalar(-0.639417), btScalar(-0.340505), btScalar(-0.689049)),
+ btVector3(btScalar(-0.598438), btScalar(0.104722), btScalar(-0.794256)),
+ btVector3(btScalar(-0.488575), btScalar(0.307699), btScalar(-0.816313)),
+ btVector3(btScalar(-0.379882), btScalar(0.513592), btScalar(-0.769077)),
+ btVector3(btScalar(-0.425740), btScalar(0.862775), btScalar(-0.272516)),
+ btVector3(btScalar(-0.480769), btScalar(0.875412), btScalar(-0.048439)),
+ btVector3(btScalar(-0.467890), btScalar(0.648716), btScalar(-0.600043)),
+ btVector3(btScalar(-0.543799), btScalar(0.730956), btScalar(-0.411881)),
+ btVector3(btScalar(-0.516284), btScalar(0.838277), btScalar(0.174076)),
+ btVector3(btScalar(-0.353343), btScalar(0.876384), btScalar(0.326519)),
+ btVector3(btScalar(-0.572875), btScalar(0.614497), btScalar(0.542007)),
+ btVector3(btScalar(-0.503600), btScalar(0.497261), btScalar(0.706161)),
+ btVector3(btScalar(-0.530920), btScalar(0.754870), btScalar(0.384685)),
+ btVector3(btScalar(-0.395884), btScalar(0.366414), btScalar(0.841818)),
+ btVector3(btScalar(-0.300656), btScalar(0.001678), btScalar(0.953661)),
+ btVector3(btScalar(-0.461060), btScalar(0.146912), btScalar(0.875000)),
+ btVector3(btScalar(-0.315486), btScalar(-0.232212), btScalar(0.919893)),
+ btVector3(btScalar(-0.323682), btScalar(-0.449187), btScalar(0.832644)),
+ btVector3(btScalar(-0.318999), btScalar(-0.639527), btScalar(0.699134)),
+ btVector3(btScalar(-0.496771), btScalar(-0.866029), btScalar(-0.055271)),
+ btVector3(btScalar(-0.496771), btScalar(-0.816257), btScalar(-0.294377)),
+ btVector3(btScalar(-0.456377), btScalar(-0.869528), btScalar(0.188130)),
+ btVector3(btScalar(-0.380858), btScalar(-0.827144), btScalar(0.412792)),
+ btVector3(btScalar(-0.449352), btScalar(-0.727405), btScalar(-0.518259)),
+ btVector3(btScalar(-0.570533), btScalar(-0.551064), btScalar(-0.608632)),
+ btVector3(btScalar(-0.656394), btScalar(-0.118280), btScalar(-0.744874)),
+ btVector3(btScalar(-0.756696), btScalar(-0.438105), btScalar(-0.484882)),
+ btVector3(btScalar(-0.801773), btScalar(-0.204798), btScalar(-0.561005)),
+ btVector3(btScalar(-0.785186), btScalar(0.038618), btScalar(-0.617805)),
+ btVector3(btScalar(-0.709082), btScalar(0.262399), btScalar(-0.654306)),
+ btVector3(btScalar(-0.583412), btScalar(0.462265), btScalar(-0.667383)),
+ btVector3(btScalar(-0.616001), btScalar(0.761286), btScalar(-0.201272)),
+ btVector3(btScalar(-0.660687), btScalar(0.750204), btScalar(0.020072)),
+ btVector3(btScalar(-0.744987), btScalar(0.435823), btScalar(-0.504791)),
+ btVector3(btScalar(-0.713765), btScalar(0.605554), btScalar(-0.351373)),
+ btVector3(btScalar(-0.686251), btScalar(0.687600), btScalar(0.236927)),
+ btVector3(btScalar(-0.680201), btScalar(0.429407), btScalar(0.593732)),
+ btVector3(btScalar(-0.733474), btScalar(0.546450), btScalar(0.403814)),
+ btVector3(btScalar(-0.591023), btScalar(0.292923), btScalar(0.751445)),
+ btVector3(btScalar(-0.500283), btScalar(-0.080757), btScalar(0.861922)),
+ btVector3(btScalar(-0.643710), btScalar(0.070115), btScalar(0.761985)),
+ btVector3(btScalar(-0.506332), btScalar(-0.308425), btScalar(0.805122)),
+ btVector3(btScalar(-0.503015), btScalar(-0.509847), btScalar(0.697573)),
+ btVector3(btScalar(-0.482525), btScalar(-0.682105), btScalar(0.549229)),
+ btVector3(btScalar(-0.680396), btScalar(-0.716323), btScalar(-0.153451)),
+ btVector3(btScalar(-0.658346), btScalar(-0.746264), btScalar(0.097562)),
+ btVector3(btScalar(-0.653272), btScalar(-0.646915), btScalar(-0.392948)),
+ btVector3(btScalar(-0.590828), btScalar(-0.732655), btScalar(0.337645)),
+ btVector3(btScalar(-0.819140), btScalar(-0.518013), btScalar(-0.246166)),
+ btVector3(btScalar(-0.900513), btScalar(-0.282178), btScalar(-0.330487)),
+ btVector3(btScalar(-0.914953), btScalar(-0.028652), btScalar(-0.402122)),
+ btVector3(btScalar(-0.859924), btScalar(0.220209), btScalar(-0.459898)),
+ btVector3(btScalar(-0.777185), btScalar(0.613720), btScalar(-0.137836)),
+ btVector3(btScalar(-0.805285), btScalar(0.586889), btScalar(0.082728)),
+ btVector3(btScalar(-0.872413), btScalar(0.406077), btScalar(-0.271735)),
+ btVector3(btScalar(-0.859339), btScalar(0.448072), btScalar(0.246101)),
+ btVector3(btScalar(-0.757671), btScalar(0.216320), btScalar(0.615594)),
+ btVector3(btScalar(-0.826165), btScalar(0.348139), btScalar(0.442851)),
+ btVector3(btScalar(-0.671810), btScalar(-0.162803), btScalar(0.722557)),
+ btVector3(btScalar(-0.796504), btScalar(-0.004543), btScalar(0.604468)),
+ btVector3(btScalar(-0.676298), btScalar(-0.378223), btScalar(0.631794)),
+ btVector3(btScalar(-0.668883), btScalar(-0.558258), btScalar(0.490673)),
+ btVector3(btScalar(-0.821287), btScalar(-0.570118), btScalar(0.006994)),
+ btVector3(btScalar(-0.767428), btScalar(-0.587810), btScalar(0.255470)),
+ btVector3(btScalar(-0.933296), btScalar(-0.349837), btScalar(-0.079865)),
+ btVector3(btScalar(-0.982667), btScalar(-0.100393), btScalar(-0.155208)),
+ btVector3(btScalar(-0.961396), btScalar(0.160910), btScalar(-0.222938)),
+ btVector3(btScalar(-0.934858), btScalar(0.354555), btScalar(-0.006864)),
+ btVector3(btScalar(-0.941687), btScalar(0.229736), btScalar(0.245711)),
+ btVector3(btScalar(-0.884317), btScalar(0.131552), btScalar(0.447536)),
+ btVector3(btScalar(-0.810359), btScalar(-0.219769), btScalar(0.542788)),
+ btVector3(btScalar(-0.915929), btScalar(-0.210048), btScalar(0.341743)),
+ btVector3(btScalar(-0.816799), btScalar(-0.407192), btScalar(0.408303)),
+ btVector3(btScalar(-0.903050), btScalar(-0.392416), btScalar(0.174076)),
+ btVector3(btScalar(-0.980325), btScalar(-0.170969), btScalar(0.096586)),
+ btVector3(btScalar(-0.995936), btScalar(0.084891), btScalar(0.029441)),
+ btVector3(btScalar(-0.960031), btScalar(0.002650), btScalar(0.279283)),
+ };
static btVector3 sUnitSpherePoints[NUM_UNITSPHERE_POINTS + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2] =
- {
- btVector3(btScalar(0.000000) , btScalar(-0.000000),btScalar(-1.000000)),
- btVector3(btScalar(0.723608) , btScalar(-0.525725),btScalar(-0.447219)),
- btVector3(btScalar(-0.276388) , btScalar(-0.850649),btScalar(-0.447219)),
- btVector3(btScalar(-0.894426) , btScalar(-0.000000),btScalar(-0.447216)),
- btVector3(btScalar(-0.276388) , btScalar(0.850649),btScalar(-0.447220)),
- btVector3(btScalar(0.723608) , btScalar(0.525725),btScalar(-0.447219)),
- btVector3(btScalar(0.276388) , btScalar(-0.850649),btScalar(0.447220)),
- btVector3(btScalar(-0.723608) , btScalar(-0.525725),btScalar(0.447219)),
- btVector3(btScalar(-0.723608) , btScalar(0.525725),btScalar(0.447219)),
- btVector3(btScalar(0.276388) , btScalar(0.850649),btScalar(0.447219)),
- btVector3(btScalar(0.894426) , btScalar(0.000000),btScalar(0.447216)),
- btVector3(btScalar(-0.000000) , btScalar(0.000000),btScalar(1.000000)),
- btVector3(btScalar(0.425323) , btScalar(-0.309011),btScalar(-0.850654)),
- btVector3(btScalar(-0.162456) , btScalar(-0.499995),btScalar(-0.850654)),
- btVector3(btScalar(0.262869) , btScalar(-0.809012),btScalar(-0.525738)),
- btVector3(btScalar(0.425323) , btScalar(0.309011),btScalar(-0.850654)),
- btVector3(btScalar(0.850648) , btScalar(-0.000000),btScalar(-0.525736)),
- btVector3(btScalar(-0.525730) , btScalar(-0.000000),btScalar(-0.850652)),
- btVector3(btScalar(-0.688190) , btScalar(-0.499997),btScalar(-0.525736)),
- btVector3(btScalar(-0.162456) , btScalar(0.499995),btScalar(-0.850654)),
- btVector3(btScalar(-0.688190) , btScalar(0.499997),btScalar(-0.525736)),
- btVector3(btScalar(0.262869) , btScalar(0.809012),btScalar(-0.525738)),
- btVector3(btScalar(0.951058) , btScalar(0.309013),btScalar(0.000000)),
- btVector3(btScalar(0.951058) , btScalar(-0.309013),btScalar(0.000000)),
- btVector3(btScalar(0.587786) , btScalar(-0.809017),btScalar(0.000000)),
- btVector3(btScalar(0.000000) , btScalar(-1.000000),btScalar(0.000000)),
- btVector3(btScalar(-0.587786) , btScalar(-0.809017),btScalar(0.000000)),
- btVector3(btScalar(-0.951058) , btScalar(-0.309013),btScalar(-0.000000)),
- btVector3(btScalar(-0.951058) , btScalar(0.309013),btScalar(-0.000000)),
- btVector3(btScalar(-0.587786) , btScalar(0.809017),btScalar(-0.000000)),
- btVector3(btScalar(-0.000000) , btScalar(1.000000),btScalar(-0.000000)),
- btVector3(btScalar(0.587786) , btScalar(0.809017),btScalar(-0.000000)),
- btVector3(btScalar(0.688190) , btScalar(-0.499997),btScalar(0.525736)),
- btVector3(btScalar(-0.262869) , btScalar(-0.809012),btScalar(0.525738)),
- btVector3(btScalar(-0.850648) , btScalar(0.000000),btScalar(0.525736)),
- btVector3(btScalar(-0.262869) , btScalar(0.809012),btScalar(0.525738)),
- btVector3(btScalar(0.688190) , btScalar(0.499997),btScalar(0.525736)),
- btVector3(btScalar(0.525730) , btScalar(0.000000),btScalar(0.850652)),
- btVector3(btScalar(0.162456) , btScalar(-0.499995),btScalar(0.850654)),
- btVector3(btScalar(-0.425323) , btScalar(-0.309011),btScalar(0.850654)),
- btVector3(btScalar(-0.425323) , btScalar(0.309011),btScalar(0.850654)),
- btVector3(btScalar(0.162456) , btScalar(0.499995),btScalar(0.850654))
- };
+ {
+ btVector3(btScalar(0.000000), btScalar(-0.000000), btScalar(-1.000000)),
+ btVector3(btScalar(0.723608), btScalar(-0.525725), btScalar(-0.447219)),
+ btVector3(btScalar(-0.276388), btScalar(-0.850649), btScalar(-0.447219)),
+ btVector3(btScalar(-0.894426), btScalar(-0.000000), btScalar(-0.447216)),
+ btVector3(btScalar(-0.276388), btScalar(0.850649), btScalar(-0.447220)),
+ btVector3(btScalar(0.723608), btScalar(0.525725), btScalar(-0.447219)),
+ btVector3(btScalar(0.276388), btScalar(-0.850649), btScalar(0.447220)),
+ btVector3(btScalar(-0.723608), btScalar(-0.525725), btScalar(0.447219)),
+ btVector3(btScalar(-0.723608), btScalar(0.525725), btScalar(0.447219)),
+ btVector3(btScalar(0.276388), btScalar(0.850649), btScalar(0.447219)),
+ btVector3(btScalar(0.894426), btScalar(0.000000), btScalar(0.447216)),
+ btVector3(btScalar(-0.000000), btScalar(0.000000), btScalar(1.000000)),
+ btVector3(btScalar(0.425323), btScalar(-0.309011), btScalar(-0.850654)),
+ btVector3(btScalar(-0.162456), btScalar(-0.499995), btScalar(-0.850654)),
+ btVector3(btScalar(0.262869), btScalar(-0.809012), btScalar(-0.525738)),
+ btVector3(btScalar(0.425323), btScalar(0.309011), btScalar(-0.850654)),
+ btVector3(btScalar(0.850648), btScalar(-0.000000), btScalar(-0.525736)),
+ btVector3(btScalar(-0.525730), btScalar(-0.000000), btScalar(-0.850652)),
+ btVector3(btScalar(-0.688190), btScalar(-0.499997), btScalar(-0.525736)),
+ btVector3(btScalar(-0.162456), btScalar(0.499995), btScalar(-0.850654)),
+ btVector3(btScalar(-0.688190), btScalar(0.499997), btScalar(-0.525736)),
+ btVector3(btScalar(0.262869), btScalar(0.809012), btScalar(-0.525738)),
+ btVector3(btScalar(0.951058), btScalar(0.309013), btScalar(0.000000)),
+ btVector3(btScalar(0.951058), btScalar(-0.309013), btScalar(0.000000)),
+ btVector3(btScalar(0.587786), btScalar(-0.809017), btScalar(0.000000)),
+ btVector3(btScalar(0.000000), btScalar(-1.000000), btScalar(0.000000)),
+ btVector3(btScalar(-0.587786), btScalar(-0.809017), btScalar(0.000000)),
+ btVector3(btScalar(-0.951058), btScalar(-0.309013), btScalar(-0.000000)),
+ btVector3(btScalar(-0.951058), btScalar(0.309013), btScalar(-0.000000)),
+ btVector3(btScalar(-0.587786), btScalar(0.809017), btScalar(-0.000000)),
+ btVector3(btScalar(-0.000000), btScalar(1.000000), btScalar(-0.000000)),
+ btVector3(btScalar(0.587786), btScalar(0.809017), btScalar(-0.000000)),
+ btVector3(btScalar(0.688190), btScalar(-0.499997), btScalar(0.525736)),
+ btVector3(btScalar(-0.262869), btScalar(-0.809012), btScalar(0.525738)),
+ btVector3(btScalar(-0.850648), btScalar(0.000000), btScalar(0.525736)),
+ btVector3(btScalar(-0.262869), btScalar(0.809012), btScalar(0.525738)),
+ btVector3(btScalar(0.688190), btScalar(0.499997), btScalar(0.525736)),
+ btVector3(btScalar(0.525730), btScalar(0.000000), btScalar(0.850652)),
+ btVector3(btScalar(0.162456), btScalar(-0.499995), btScalar(0.850654)),
+ btVector3(btScalar(-0.425323), btScalar(-0.309011), btScalar(0.850654)),
+ btVector3(btScalar(-0.425323), btScalar(0.309011), btScalar(0.850654)),
+ btVector3(btScalar(0.162456), btScalar(0.499995), btScalar(0.850654))};
if (highres)
return sUnitSpherePointsHighres;
return sUnitSpherePoints;
}
-
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btShapeHull.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btShapeHull.h
index 78ea4b6501..54439f9ca2 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btShapeHull.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btShapeHull.h
@@ -21,32 +21,31 @@ subject to the following restrictions:
#include "LinearMath/btAlignedObjectArray.h"
#include "BulletCollision/CollisionShapes/btConvexShape.h"
-
///The btShapeHull class takes a btConvexShape, builds a simplified convex hull using btConvexHull and provides triangle indices and vertices.
///It can be useful for to simplify a complex convex object and for visualization of a non-polyhedral convex object.
///It approximates the convex hull using the supporting vertex of 42 directions.
-ATTRIBUTE_ALIGNED16(class) btShapeHull
+ATTRIBUTE_ALIGNED16(class)
+btShapeHull
{
protected:
-
btAlignedObjectArray<btVector3> m_vertices;
btAlignedObjectArray<unsigned int> m_indices;
unsigned int m_numIndices;
const btConvexShape* m_shape;
- static btVector3* getUnitSpherePoints(int highres=0);
+ static btVector3* getUnitSpherePoints(int highres = 0);
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btShapeHull (const btConvexShape* shape);
- ~btShapeHull ();
- bool buildHull (btScalar margin, int highres=0);
+ btShapeHull(const btConvexShape* shape);
+ ~btShapeHull();
+
+ bool buildHull(btScalar margin, int highres = 0);
- int numTriangles () const;
- int numVertices () const;
- int numIndices () const;
+ int numTriangles() const;
+ int numVertices() const;
+ int numIndices() const;
const btVector3* getVertexPointer() const
{
@@ -58,4 +57,4 @@ public:
}
};
-#endif //BT_SHAPE_HULL_H
+#endif //BT_SHAPE_HULL_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btSphereShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btSphereShape.cpp
index b9a736c0fd..027db2e104 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btSphereShape.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btSphereShape.cpp
@@ -18,54 +18,48 @@ subject to the following restrictions:
#include "LinearMath/btQuaternion.h"
-btVector3 btSphereShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+btVector3 btSphereShape::localGetSupportingVertexWithoutMargin(const btVector3& vec) const
{
(void)vec;
- return btVector3(btScalar(0.),btScalar(0.),btScalar(0.));
+ return btVector3(btScalar(0.), btScalar(0.), btScalar(0.));
}
-void btSphereShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+void btSphereShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
{
(void)vectors;
- for (int i=0;i<numVectors;i++)
+ for (int i = 0; i < numVectors; i++)
{
- supportVerticesOut[i].setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+ supportVerticesOut[i].setValue(btScalar(0.), btScalar(0.), btScalar(0.));
}
}
-
-btVector3 btSphereShape::localGetSupportingVertex(const btVector3& vec)const
+btVector3 btSphereShape::localGetSupportingVertex(const btVector3& vec) const
{
btVector3 supVertex;
supVertex = localGetSupportingVertexWithoutMargin(vec);
btVector3 vecnorm = vec;
- if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
+ if (vecnorm.length2() < (SIMD_EPSILON * SIMD_EPSILON))
{
- vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
- }
+ vecnorm.setValue(btScalar(-1.), btScalar(-1.), btScalar(-1.));
+ }
vecnorm.normalize();
- supVertex+= getMargin() * vecnorm;
+ supVertex += getMargin() * vecnorm;
return supVertex;
}
-
//broken due to scaling
-void btSphereShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+void btSphereShape::getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
{
const btVector3& center = t.getOrigin();
- btVector3 extent(getMargin(),getMargin(),getMargin());
+ btVector3 extent(getMargin(), getMargin(), getMargin());
aabbMin = center - extent;
aabbMax = center + extent;
}
-
-
-void btSphereShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+void btSphereShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
{
- btScalar elem = btScalar(0.4) * mass * getMargin()*getMargin();
- inertia.setValue(elem,elem,elem);
-
+ btScalar elem = btScalar(0.4) * mass * getMargin() * getMargin();
+ inertia.setValue(elem, elem, elem);
}
-
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btSphereShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btSphereShape.h
index 50561f7f54..75e4fd8e18 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btSphereShape.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btSphereShape.h
@@ -16,17 +16,17 @@ subject to the following restrictions:
#define BT_SPHERE_MINKOWSKI_H
#include "btConvexInternalShape.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
///The btSphereShape implements an implicit sphere, centered around a local origin with radius.
-ATTRIBUTE_ALIGNED16(class) btSphereShape : public btConvexInternalShape
+ATTRIBUTE_ALIGNED16(class)
+btSphereShape : public btConvexInternalShape
{
-
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
- btSphereShape (btScalar radius) : btConvexInternalShape ()
+ btSphereShape(btScalar radius) : btConvexInternalShape()
{
m_shapeType = SPHERE_SHAPE_PROXYTYPE;
m_localScaling.setValue(1.0, 1.0, 1.0);
@@ -35,42 +35,37 @@ public:
m_collisionMargin = radius;
m_padding = 0;
}
-
- virtual btVector3 localGetSupportingVertex(const btVector3& vec)const;
- virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
- //notice that the vectors should be unit length
- virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
-
- virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+ virtual btVector3 localGetSupportingVertex(const btVector3& vec) const;
+ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
+ //notice that the vectors should be unit length
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const;
- virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+ virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
+ virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
- btScalar getRadius() const { return m_implicitShapeDimensions.getX() * m_localScaling.getX();}
+ btScalar getRadius() const { return m_implicitShapeDimensions.getX() * m_localScaling.getX(); }
- void setUnscaledRadius(btScalar radius)
+ void setUnscaledRadius(btScalar radius)
{
m_implicitShapeDimensions.setX(radius);
btConvexInternalShape::setMargin(radius);
}
//debugging
- virtual const char* getName()const {return "SPHERE";}
+ virtual const char* getName() const { return "SPHERE"; }
- virtual void setMargin(btScalar margin)
+ virtual void setMargin(btScalar margin)
{
btConvexInternalShape::setMargin(margin);
}
- virtual btScalar getMargin() const
+ virtual btScalar getMargin() const
{
//to improve gjk behaviour, use radius+margin as the full margin, so never get into the penetration case
//this means, non-uniform scaling is not supported anymore
return getRadius();
}
-
-
};
-
-#endif //BT_SPHERE_MINKOWSKI_H
+#endif //BT_SPHERE_MINKOWSKI_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp
index b5e0e716d4..9238c919d5 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp
@@ -17,24 +17,18 @@ subject to the following restrictions:
#include "LinearMath/btTransformUtil.h"
-
-btStaticPlaneShape::btStaticPlaneShape(const btVector3& planeNormal,btScalar planeConstant)
-: btConcaveShape (), m_planeNormal(planeNormal.normalized()),
-m_planeConstant(planeConstant),
-m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.))
+btStaticPlaneShape::btStaticPlaneShape(const btVector3& planeNormal, btScalar planeConstant)
+ : btConcaveShape(), m_planeNormal(planeNormal.normalized()), m_planeConstant(planeConstant), m_localScaling(btScalar(1.), btScalar(1.), btScalar(1.))
{
m_shapeType = STATIC_PLANE_PROXYTYPE;
// btAssert( btFuzzyZero(m_planeNormal.length() - btScalar(1.)) );
}
-
btStaticPlaneShape::~btStaticPlaneShape()
{
}
-
-
-void btStaticPlaneShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+void btStaticPlaneShape::getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
{
(void)t;
/*
@@ -47,55 +41,49 @@ void btStaticPlaneShape::getAabb(const btTransform& t,btVector3& aabbMin,btVecto
aabbMax.setMax(center - infvec*m_planeNormal);
*/
- aabbMin.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
- aabbMax.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
-
+ aabbMin.setValue(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
+ aabbMax.setValue(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
}
-
-
-
-void btStaticPlaneShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
+void btStaticPlaneShape::processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
{
-
btVector3 halfExtents = (aabbMax - aabbMin) * btScalar(0.5);
btScalar radius = halfExtents.length();
btVector3 center = (aabbMax + aabbMin) * btScalar(0.5);
-
+
//this is where the triangles are generated, given AABB and plane equation (normal/constant)
- btVector3 tangentDir0,tangentDir1;
+ btVector3 tangentDir0, tangentDir1;
//tangentDir0/tangentDir1 can be precalculated
- btPlaneSpace1(m_planeNormal,tangentDir0,tangentDir1);
+ btPlaneSpace1(m_planeNormal, tangentDir0, tangentDir1);
- btVector3 projectedCenter = center - (m_planeNormal.dot(center) - m_planeConstant)*m_planeNormal;
-
- btVector3 triangle[3];
- triangle[0] = projectedCenter + tangentDir0*radius + tangentDir1*radius;
- triangle[1] = projectedCenter + tangentDir0*radius - tangentDir1*radius;
- triangle[2] = projectedCenter - tangentDir0*radius - tangentDir1*radius;
+ btVector3 projectedCenter = center - (m_planeNormal.dot(center) - m_planeConstant) * m_planeNormal;
- callback->processTriangle(triangle,0,0);
+ btVector3 triangle[3];
+ triangle[0] = projectedCenter + tangentDir0 * radius + tangentDir1 * radius;
+ triangle[1] = projectedCenter + tangentDir0 * radius - tangentDir1 * radius;
+ triangle[2] = projectedCenter - tangentDir0 * radius - tangentDir1 * radius;
- triangle[0] = projectedCenter - tangentDir0*radius - tangentDir1*radius;
- triangle[1] = projectedCenter - tangentDir0*radius + tangentDir1*radius;
- triangle[2] = projectedCenter + tangentDir0*radius + tangentDir1*radius;
+ callback->processTriangle(triangle, 0, 0);
- callback->processTriangle(triangle,0,1);
+ triangle[0] = projectedCenter - tangentDir0 * radius - tangentDir1 * radius;
+ triangle[1] = projectedCenter - tangentDir0 * radius + tangentDir1 * radius;
+ triangle[2] = projectedCenter + tangentDir0 * radius + tangentDir1 * radius;
+ callback->processTriangle(triangle, 0, 1);
}
-void btStaticPlaneShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+void btStaticPlaneShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
{
(void)mass;
//moving concave objects not supported
-
- inertia.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+
+ inertia.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
}
-void btStaticPlaneShape::setLocalScaling(const btVector3& scaling)
+void btStaticPlaneShape::setLocalScaling(const btVector3& scaling)
{
m_localScaling = scaling;
}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btStaticPlaneShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btStaticPlaneShape.h
index 5e9eccc77d..1cda8bbc75 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btStaticPlaneShape.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btStaticPlaneShape.h
@@ -18,78 +18,74 @@ subject to the following restrictions:
#include "btConcaveShape.h"
-
///The btStaticPlaneShape simulates an infinite non-moving (static) collision plane.
-ATTRIBUTE_ALIGNED16(class) btStaticPlaneShape : public btConcaveShape
+ATTRIBUTE_ALIGNED16(class)
+btStaticPlaneShape : public btConcaveShape
{
protected:
- btVector3 m_localAabbMin;
- btVector3 m_localAabbMax;
-
- btVector3 m_planeNormal;
- btScalar m_planeConstant;
- btVector3 m_localScaling;
+ btVector3 m_localAabbMin;
+ btVector3 m_localAabbMax;
+
+ btVector3 m_planeNormal;
+ btScalar m_planeConstant;
+ btVector3 m_localScaling;
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
- btStaticPlaneShape(const btVector3& planeNormal,btScalar planeConstant);
+ btStaticPlaneShape(const btVector3& planeNormal, btScalar planeConstant);
virtual ~btStaticPlaneShape();
+ virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
- virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
-
- virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+ virtual void processAllTriangles(btTriangleCallback * callback, const btVector3& aabbMin, const btVector3& aabbMax) const;
- virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+ virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
- virtual void setLocalScaling(const btVector3& scaling);
+ virtual void setLocalScaling(const btVector3& scaling);
virtual const btVector3& getLocalScaling() const;
-
- const btVector3& getPlaneNormal() const
+
+ const btVector3& getPlaneNormal() const
{
- return m_planeNormal;
+ return m_planeNormal;
}
- const btScalar& getPlaneConstant() const
+ const btScalar& getPlaneConstant() const
{
- return m_planeConstant;
+ return m_planeConstant;
}
//debugging
- virtual const char* getName()const {return "STATICPLANE";}
+ virtual const char* getName() const { return "STATICPLANE"; }
- virtual int calculateSerializeBufferSize() const;
+ virtual int calculateSerializeBufferSize() const;
///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-
-
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
};
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btStaticPlaneShapeData
+struct btStaticPlaneShapeData
{
- btCollisionShapeData m_collisionShapeData;
+ btCollisionShapeData m_collisionShapeData;
- btVector3FloatData m_localScaling;
- btVector3FloatData m_planeNormal;
- float m_planeConstant;
- char m_pad[4];
+ btVector3FloatData m_localScaling;
+ btVector3FloatData m_planeNormal;
+ float m_planeConstant;
+ char m_pad[4];
};
-
-SIMD_FORCE_INLINE int btStaticPlaneShape::calculateSerializeBufferSize() const
+SIMD_FORCE_INLINE int btStaticPlaneShape::calculateSerializeBufferSize() const
{
return sizeof(btStaticPlaneShapeData);
}
///fills the dataBuffer and returns the struct name (and 0 on failure)
-SIMD_FORCE_INLINE const char* btStaticPlaneShape::serialize(void* dataBuffer, btSerializer* serializer) const
+SIMD_FORCE_INLINE const char* btStaticPlaneShape::serialize(void* dataBuffer, btSerializer* serializer) const
{
- btStaticPlaneShapeData* planeData = (btStaticPlaneShapeData*) dataBuffer;
- btCollisionShape::serialize(&planeData->m_collisionShapeData,serializer);
+ btStaticPlaneShapeData* planeData = (btStaticPlaneShapeData*)dataBuffer;
+ btCollisionShape::serialize(&planeData->m_collisionShapeData, serializer);
m_localScaling.serializeFloat(planeData->m_localScaling);
m_planeNormal.serializeFloat(planeData->m_planeNormal);
@@ -104,8 +100,4 @@ SIMD_FORCE_INLINE const char* btStaticPlaneShape::serialize(void* dataBuffer, bt
return "btStaticPlaneShapeData";
}
-
-#endif //BT_STATIC_PLANE_SHAPE_H
-
-
-
+#endif //BT_STATIC_PLANE_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp
index 78ddeb3704..eb288e99c9 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp
@@ -18,32 +18,30 @@ subject to the following restrictions:
btStridingMeshInterface::~btStridingMeshInterface()
{
-
}
-
-void btStridingMeshInterface::InternalProcessAllTriangles(btInternalTriangleIndexCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
+void btStridingMeshInterface::InternalProcessAllTriangles(btInternalTriangleIndexCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
{
(void)aabbMin;
(void)aabbMax;
int numtotalphysicsverts = 0;
- int part,graphicssubparts = getNumSubParts();
- const unsigned char * vertexbase;
- const unsigned char * indexbase;
+ int part, graphicssubparts = getNumSubParts();
+ const unsigned char* vertexbase;
+ const unsigned char* indexbase;
int indexstride;
PHY_ScalarType type;
PHY_ScalarType gfxindextype;
- int stride,numverts,numtriangles;
+ int stride, numverts, numtriangles;
int gfxindex;
btVector3 triangle[3];
btVector3 meshScaling = getScaling();
///if the number of parts is big, the performance might drop due to the innerloop switch on indextype
- for (part=0;part<graphicssubparts ;part++)
+ for (part = 0; part < graphicssubparts; part++)
{
- getLockedReadOnlyVertexIndexBase(&vertexbase,numverts,type,stride,&indexbase,indexstride,numtriangles,gfxindextype,part);
- numtotalphysicsverts+=numtriangles*3; //upper bound
+ getLockedReadOnlyVertexIndexBase(&vertexbase, numverts, type, stride, &indexbase, indexstride, numtriangles, gfxindextype, part);
+ numtotalphysicsverts += numtriangles * 3; //upper bound
///unlike that developers want to pass in double-precision meshes in single-precision Bullet build
///so disable this feature by default
@@ -51,143 +49,141 @@ void btStridingMeshInterface::InternalProcessAllTriangles(btInternalTriangleInde
switch (type)
{
- case PHY_FLOAT:
- {
-
- float* graphicsbase;
-
- switch (gfxindextype)
- {
- case PHY_INTEGER:
- {
- for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
- {
- unsigned int* tri_indices= (unsigned int*)(indexbase+gfxindex*indexstride);
- graphicsbase = (float*)(vertexbase+tri_indices[0]*stride);
- triangle[0].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
- graphicsbase = (float*)(vertexbase+tri_indices[1]*stride);
- triangle[1].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(), graphicsbase[2]*meshScaling.getZ());
- graphicsbase = (float*)(vertexbase+tri_indices[2]*stride);
- triangle[2].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(), graphicsbase[2]*meshScaling.getZ());
- callback->internalProcessTriangleIndex(triangle,part,gfxindex);
- }
- break;
- }
- case PHY_SHORT:
- {
- for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
- {
- unsigned short int* tri_indices= (unsigned short int*)(indexbase+gfxindex*indexstride);
- graphicsbase = (float*)(vertexbase+tri_indices[0]*stride);
- triangle[0].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
- graphicsbase = (float*)(vertexbase+tri_indices[1]*stride);
- triangle[1].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(), graphicsbase[2]*meshScaling.getZ());
- graphicsbase = (float*)(vertexbase+tri_indices[2]*stride);
- triangle[2].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(), graphicsbase[2]*meshScaling.getZ());
- callback->internalProcessTriangleIndex(triangle,part,gfxindex);
- }
- break;
- }
- case PHY_UCHAR:
- {
- for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
- {
- unsigned char* tri_indices= (unsigned char*)(indexbase+gfxindex*indexstride);
- graphicsbase = (float*)(vertexbase+tri_indices[0]*stride);
- triangle[0].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
- graphicsbase = (float*)(vertexbase+tri_indices[1]*stride);
- triangle[1].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(), graphicsbase[2]*meshScaling.getZ());
- graphicsbase = (float*)(vertexbase+tri_indices[2]*stride);
- triangle[2].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(), graphicsbase[2]*meshScaling.getZ());
- callback->internalProcessTriangleIndex(triangle,part,gfxindex);
- }
- break;
- }
- default:
- btAssert((gfxindextype == PHY_INTEGER) || (gfxindextype == PHY_SHORT));
- }
- break;
- }
-
- case PHY_DOUBLE:
+ case PHY_FLOAT:
+ {
+ float* graphicsbase;
+
+ switch (gfxindextype)
+ {
+ case PHY_INTEGER:
+ {
+ for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
+ {
+ unsigned int* tri_indices = (unsigned int*)(indexbase + gfxindex * indexstride);
+ graphicsbase = (float*)(vertexbase + tri_indices[0] * stride);
+ triangle[0].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
+ graphicsbase = (float*)(vertexbase + tri_indices[1] * stride);
+ triangle[1].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
+ graphicsbase = (float*)(vertexbase + tri_indices[2] * stride);
+ triangle[2].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
+ callback->internalProcessTriangleIndex(triangle, part, gfxindex);
+ }
+ break;
+ }
+ case PHY_SHORT:
+ {
+ for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
+ {
+ unsigned short int* tri_indices = (unsigned short int*)(indexbase + gfxindex * indexstride);
+ graphicsbase = (float*)(vertexbase + tri_indices[0] * stride);
+ triangle[0].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
+ graphicsbase = (float*)(vertexbase + tri_indices[1] * stride);
+ triangle[1].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
+ graphicsbase = (float*)(vertexbase + tri_indices[2] * stride);
+ triangle[2].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
+ callback->internalProcessTriangleIndex(triangle, part, gfxindex);
+ }
+ break;
+ }
+ case PHY_UCHAR:
+ {
+ for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
+ {
+ unsigned char* tri_indices = (unsigned char*)(indexbase + gfxindex * indexstride);
+ graphicsbase = (float*)(vertexbase + tri_indices[0] * stride);
+ triangle[0].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
+ graphicsbase = (float*)(vertexbase + tri_indices[1] * stride);
+ triangle[1].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
+ graphicsbase = (float*)(vertexbase + tri_indices[2] * stride);
+ triangle[2].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
+ callback->internalProcessTriangleIndex(triangle, part, gfxindex);
+ }
+ break;
+ }
+ default:
+ btAssert((gfxindextype == PHY_INTEGER) || (gfxindextype == PHY_SHORT));
+ }
+ break;
+ }
+
+ case PHY_DOUBLE:
{
double* graphicsbase;
switch (gfxindextype)
{
- case PHY_INTEGER:
+ case PHY_INTEGER:
{
- for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
+ for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
{
- unsigned int* tri_indices= (unsigned int*)(indexbase+gfxindex*indexstride);
- graphicsbase = (double*)(vertexbase+tri_indices[0]*stride);
- triangle[0].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(),(btScalar)graphicsbase[2]*meshScaling.getZ());
- graphicsbase = (double*)(vertexbase+tri_indices[1]*stride);
- triangle[1].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(), (btScalar)graphicsbase[2]*meshScaling.getZ());
- graphicsbase = (double*)(vertexbase+tri_indices[2]*stride);
- triangle[2].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(), (btScalar)graphicsbase[2]*meshScaling.getZ());
- callback->internalProcessTriangleIndex(triangle,part,gfxindex);
+ unsigned int* tri_indices = (unsigned int*)(indexbase + gfxindex * indexstride);
+ graphicsbase = (double*)(vertexbase + tri_indices[0] * stride);
+ triangle[0].setValue((btScalar)graphicsbase[0] * meshScaling.getX(), (btScalar)graphicsbase[1] * meshScaling.getY(), (btScalar)graphicsbase[2] * meshScaling.getZ());
+ graphicsbase = (double*)(vertexbase + tri_indices[1] * stride);
+ triangle[1].setValue((btScalar)graphicsbase[0] * meshScaling.getX(), (btScalar)graphicsbase[1] * meshScaling.getY(), (btScalar)graphicsbase[2] * meshScaling.getZ());
+ graphicsbase = (double*)(vertexbase + tri_indices[2] * stride);
+ triangle[2].setValue((btScalar)graphicsbase[0] * meshScaling.getX(), (btScalar)graphicsbase[1] * meshScaling.getY(), (btScalar)graphicsbase[2] * meshScaling.getZ());
+ callback->internalProcessTriangleIndex(triangle, part, gfxindex);
}
break;
}
- case PHY_SHORT:
+ case PHY_SHORT:
{
- for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
+ for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
{
- unsigned short int* tri_indices= (unsigned short int*)(indexbase+gfxindex*indexstride);
- graphicsbase = (double*)(vertexbase+tri_indices[0]*stride);
- triangle[0].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(),(btScalar)graphicsbase[2]*meshScaling.getZ());
- graphicsbase = (double*)(vertexbase+tri_indices[1]*stride);
- triangle[1].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(), (btScalar)graphicsbase[2]*meshScaling.getZ());
- graphicsbase = (double*)(vertexbase+tri_indices[2]*stride);
- triangle[2].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(), (btScalar)graphicsbase[2]*meshScaling.getZ());
- callback->internalProcessTriangleIndex(triangle,part,gfxindex);
+ unsigned short int* tri_indices = (unsigned short int*)(indexbase + gfxindex * indexstride);
+ graphicsbase = (double*)(vertexbase + tri_indices[0] * stride);
+ triangle[0].setValue((btScalar)graphicsbase[0] * meshScaling.getX(), (btScalar)graphicsbase[1] * meshScaling.getY(), (btScalar)graphicsbase[2] * meshScaling.getZ());
+ graphicsbase = (double*)(vertexbase + tri_indices[1] * stride);
+ triangle[1].setValue((btScalar)graphicsbase[0] * meshScaling.getX(), (btScalar)graphicsbase[1] * meshScaling.getY(), (btScalar)graphicsbase[2] * meshScaling.getZ());
+ graphicsbase = (double*)(vertexbase + tri_indices[2] * stride);
+ triangle[2].setValue((btScalar)graphicsbase[0] * meshScaling.getX(), (btScalar)graphicsbase[1] * meshScaling.getY(), (btScalar)graphicsbase[2] * meshScaling.getZ());
+ callback->internalProcessTriangleIndex(triangle, part, gfxindex);
}
break;
}
- case PHY_UCHAR:
+ case PHY_UCHAR:
{
- for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
+ for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
{
- unsigned char* tri_indices= (unsigned char*)(indexbase+gfxindex*indexstride);
- graphicsbase = (double*)(vertexbase+tri_indices[0]*stride);
- triangle[0].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(),(btScalar)graphicsbase[2]*meshScaling.getZ());
- graphicsbase = (double*)(vertexbase+tri_indices[1]*stride);
- triangle[1].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(), (btScalar)graphicsbase[2]*meshScaling.getZ());
- graphicsbase = (double*)(vertexbase+tri_indices[2]*stride);
- triangle[2].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(), (btScalar)graphicsbase[2]*meshScaling.getZ());
- callback->internalProcessTriangleIndex(triangle,part,gfxindex);
+ unsigned char* tri_indices = (unsigned char*)(indexbase + gfxindex * indexstride);
+ graphicsbase = (double*)(vertexbase + tri_indices[0] * stride);
+ triangle[0].setValue((btScalar)graphicsbase[0] * meshScaling.getX(), (btScalar)graphicsbase[1] * meshScaling.getY(), (btScalar)graphicsbase[2] * meshScaling.getZ());
+ graphicsbase = (double*)(vertexbase + tri_indices[1] * stride);
+ triangle[1].setValue((btScalar)graphicsbase[0] * meshScaling.getX(), (btScalar)graphicsbase[1] * meshScaling.getY(), (btScalar)graphicsbase[2] * meshScaling.getZ());
+ graphicsbase = (double*)(vertexbase + tri_indices[2] * stride);
+ triangle[2].setValue((btScalar)graphicsbase[0] * meshScaling.getX(), (btScalar)graphicsbase[1] * meshScaling.getY(), (btScalar)graphicsbase[2] * meshScaling.getZ());
+ callback->internalProcessTriangleIndex(triangle, part, gfxindex);
}
break;
}
- default:
- btAssert((gfxindextype == PHY_INTEGER) || (gfxindextype == PHY_SHORT));
+ default:
+ btAssert((gfxindextype == PHY_INTEGER) || (gfxindextype == PHY_SHORT));
}
break;
}
- default:
- btAssert((type == PHY_FLOAT) || (type == PHY_DOUBLE));
+ default:
+ btAssert((type == PHY_FLOAT) || (type == PHY_DOUBLE));
}
unLockReadOnlyVertexBase(part);
}
}
-void btStridingMeshInterface::calculateAabbBruteForce(btVector3& aabbMin,btVector3& aabbMax)
+void btStridingMeshInterface::calculateAabbBruteForce(btVector3& aabbMin, btVector3& aabbMax)
{
-
- struct AabbCalculationCallback : public btInternalTriangleIndexCallback
+ struct AabbCalculationCallback : public btInternalTriangleIndexCallback
{
- btVector3 m_aabbMin;
- btVector3 m_aabbMax;
+ btVector3 m_aabbMin;
+ btVector3 m_aabbMax;
AabbCalculationCallback()
{
- m_aabbMin.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
- m_aabbMax.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
+ m_aabbMin.setValue(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
+ m_aabbMax.setValue(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
}
- virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex)
+ virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
{
(void)partId;
(void)triangleIndex;
@@ -202,21 +198,19 @@ void btStridingMeshInterface::calculateAabbBruteForce(btVector3& aabbMin,btVecto
};
//first calculate the total aabb for all triangles
- AabbCalculationCallback aabbCallback;
- aabbMin.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
- aabbMax.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
- InternalProcessAllTriangles(&aabbCallback,aabbMin,aabbMax);
+ AabbCalculationCallback aabbCallback;
+ aabbMin.setValue(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
+ aabbMax.setValue(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
+ InternalProcessAllTriangles(&aabbCallback, aabbMin, aabbMax);
aabbMin = aabbCallback.m_aabbMin;
aabbMax = aabbCallback.m_aabbMax;
}
-
-
///fills the dataBuffer and returns the struct name (and 0 on failure)
-const char* btStridingMeshInterface::serialize(void* dataBuffer, btSerializer* serializer) const
+const char* btStridingMeshInterface::serialize(void* dataBuffer, btSerializer* serializer) const
{
- btStridingMeshInterfaceData* trimeshData = (btStridingMeshInterfaceData*) dataBuffer;
+ btStridingMeshInterfaceData* trimeshData = (btStridingMeshInterfaceData*)dataBuffer;
trimeshData->m_numMeshParts = getNumSubParts();
@@ -226,29 +220,28 @@ const char* btStridingMeshInterface::serialize(void* dataBuffer, btSerializer* s
if (trimeshData->m_numMeshParts)
{
- btChunk* chunk = serializer->allocate(sizeof(btMeshPartData),trimeshData->m_numMeshParts);
+ btChunk* chunk = serializer->allocate(sizeof(btMeshPartData), trimeshData->m_numMeshParts);
btMeshPartData* memPtr = (btMeshPartData*)chunk->m_oldPtr;
- trimeshData->m_meshPartsPtr = (btMeshPartData *)serializer->getUniquePointer(memPtr);
-
+ trimeshData->m_meshPartsPtr = (btMeshPartData*)serializer->getUniquePointer(memPtr);
- // int numtotalphysicsverts = 0;
- int part,graphicssubparts = getNumSubParts();
- const unsigned char * vertexbase;
- const unsigned char * indexbase;
+ // int numtotalphysicsverts = 0;
+ int part, graphicssubparts = getNumSubParts();
+ const unsigned char* vertexbase;
+ const unsigned char* indexbase;
int indexstride;
PHY_ScalarType type;
PHY_ScalarType gfxindextype;
- int stride,numverts,numtriangles;
+ int stride, numverts, numtriangles;
int gfxindex;
- // btVector3 triangle[3];
+ // btVector3 triangle[3];
- // btVector3 meshScaling = getScaling();
+ // btVector3 meshScaling = getScaling();
///if the number of parts is big, the performance might drop due to the innerloop switch on indextype
- for (part=0;part<graphicssubparts ;part++,memPtr++)
+ for (part = 0; part < graphicssubparts; part++, memPtr++)
{
- getLockedReadOnlyVertexIndexBase(&vertexbase,numverts,type,stride,&indexbase,indexstride,numtriangles,gfxindextype,part);
- memPtr->m_numTriangles = numtriangles;//indices = 3*numtriangles
+ getLockedReadOnlyVertexIndexBase(&vertexbase, numverts, type, stride, &indexbase, indexstride, numtriangles, gfxindextype, part);
+ memPtr->m_numTriangles = numtriangles; //indices = 3*numtriangles
memPtr->m_numVertices = numverts;
memPtr->m_indices16 = 0;
memPtr->m_indices32 = 0;
@@ -257,39 +250,38 @@ const char* btStridingMeshInterface::serialize(void* dataBuffer, btSerializer* s
memPtr->m_vertices3f = 0;
memPtr->m_vertices3d = 0;
-
switch (gfxindextype)
{
- case PHY_INTEGER:
+ case PHY_INTEGER:
{
- int numindices = numtriangles*3;
-
+ int numindices = numtriangles * 3;
+
if (numindices)
{
- btChunk* chunk = serializer->allocate(sizeof(btIntIndexData),numindices);
+ btChunk* chunk = serializer->allocate(sizeof(btIntIndexData), numindices);
btIntIndexData* tmpIndices = (btIntIndexData*)chunk->m_oldPtr;
memPtr->m_indices32 = (btIntIndexData*)serializer->getUniquePointer(tmpIndices);
- for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
+ for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
{
- unsigned int* tri_indices= (unsigned int*)(indexbase+gfxindex*indexstride);
- tmpIndices[gfxindex*3].m_value = tri_indices[0];
- tmpIndices[gfxindex*3+1].m_value = tri_indices[1];
- tmpIndices[gfxindex*3+2].m_value = tri_indices[2];
+ unsigned int* tri_indices = (unsigned int*)(indexbase + gfxindex * indexstride);
+ tmpIndices[gfxindex * 3].m_value = tri_indices[0];
+ tmpIndices[gfxindex * 3 + 1].m_value = tri_indices[1];
+ tmpIndices[gfxindex * 3 + 2].m_value = tri_indices[2];
}
- serializer->finalizeChunk(chunk,"btIntIndexData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr);
+ serializer->finalizeChunk(chunk, "btIntIndexData", BT_ARRAY_CODE, (void*)chunk->m_oldPtr);
}
break;
}
- case PHY_SHORT:
+ case PHY_SHORT:
{
if (numtriangles)
{
- btChunk* chunk = serializer->allocate(sizeof(btShortIntIndexTripletData),numtriangles);
+ btChunk* chunk = serializer->allocate(sizeof(btShortIntIndexTripletData), numtriangles);
btShortIntIndexTripletData* tmpIndices = (btShortIntIndexTripletData*)chunk->m_oldPtr;
- memPtr->m_3indices16 = (btShortIntIndexTripletData*) serializer->getUniquePointer(tmpIndices);
- for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
+ memPtr->m_3indices16 = (btShortIntIndexTripletData*)serializer->getUniquePointer(tmpIndices);
+ for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
{
- unsigned short int* tri_indices= (unsigned short int*)(indexbase+gfxindex*indexstride);
+ unsigned short int* tri_indices = (unsigned short int*)(indexbase + gfxindex * indexstride);
tmpIndices[gfxindex].m_values[0] = tri_indices[0];
tmpIndices[gfxindex].m_values[1] = tri_indices[1];
tmpIndices[gfxindex].m_values[2] = tri_indices[2];
@@ -297,7 +289,7 @@ const char* btStridingMeshInterface::serialize(void* dataBuffer, btSerializer* s
tmpIndices[gfxindex].m_pad[0] = 0;
tmpIndices[gfxindex].m_pad[1] = 0;
}
- serializer->finalizeChunk(chunk,"btShortIntIndexTripletData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr);
+ serializer->finalizeChunk(chunk, "btShortIntIndexTripletData", BT_ARRAY_CODE, (void*)chunk->m_oldPtr);
}
break;
}
@@ -305,23 +297,23 @@ const char* btStridingMeshInterface::serialize(void* dataBuffer, btSerializer* s
{
if (numtriangles)
{
- btChunk* chunk = serializer->allocate(sizeof(btCharIndexTripletData),numtriangles);
+ btChunk* chunk = serializer->allocate(sizeof(btCharIndexTripletData), numtriangles);
btCharIndexTripletData* tmpIndices = (btCharIndexTripletData*)chunk->m_oldPtr;
- memPtr->m_3indices8 = (btCharIndexTripletData*) serializer->getUniquePointer(tmpIndices);
- for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
+ memPtr->m_3indices8 = (btCharIndexTripletData*)serializer->getUniquePointer(tmpIndices);
+ for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
{
- unsigned char* tri_indices= (unsigned char*)(indexbase+gfxindex*indexstride);
+ unsigned char* tri_indices = (unsigned char*)(indexbase + gfxindex * indexstride);
tmpIndices[gfxindex].m_values[0] = tri_indices[0];
tmpIndices[gfxindex].m_values[1] = tri_indices[1];
tmpIndices[gfxindex].m_values[2] = tri_indices[2];
// Fill padding with zeros to appease msan.
tmpIndices[gfxindex].m_pad = 0;
}
- serializer->finalizeChunk(chunk,"btCharIndexTripletData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr);
+ serializer->finalizeChunk(chunk, "btCharIndexTripletData", BT_ARRAY_CODE, (void*)chunk->m_oldPtr);
}
break;
}
- default:
+ default:
{
btAssert(0);
//unknown index type
@@ -330,54 +322,54 @@ const char* btStridingMeshInterface::serialize(void* dataBuffer, btSerializer* s
switch (type)
{
- case PHY_FLOAT:
- {
- float* graphicsbase;
-
- if (numverts)
- {
- btChunk* chunk = serializer->allocate(sizeof(btVector3FloatData),numverts);
- btVector3FloatData* tmpVertices = (btVector3FloatData*) chunk->m_oldPtr;
- memPtr->m_vertices3f = (btVector3FloatData *)serializer->getUniquePointer(tmpVertices);
- for (int i=0;i<numverts;i++)
- {
- graphicsbase = (float*)(vertexbase+i*stride);
- tmpVertices[i].m_floats[0] = graphicsbase[0];
- tmpVertices[i].m_floats[1] = graphicsbase[1];
- tmpVertices[i].m_floats[2] = graphicsbase[2];
- }
- serializer->finalizeChunk(chunk,"btVector3FloatData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr);
- }
- break;
+ case PHY_FLOAT:
+ {
+ float* graphicsbase;
+
+ if (numverts)
+ {
+ btChunk* chunk = serializer->allocate(sizeof(btVector3FloatData), numverts);
+ btVector3FloatData* tmpVertices = (btVector3FloatData*)chunk->m_oldPtr;
+ memPtr->m_vertices3f = (btVector3FloatData*)serializer->getUniquePointer(tmpVertices);
+ for (int i = 0; i < numverts; i++)
+ {
+ graphicsbase = (float*)(vertexbase + i * stride);
+ tmpVertices[i].m_floats[0] = graphicsbase[0];
+ tmpVertices[i].m_floats[1] = graphicsbase[1];
+ tmpVertices[i].m_floats[2] = graphicsbase[2];
+ }
+ serializer->finalizeChunk(chunk, "btVector3FloatData", BT_ARRAY_CODE, (void*)chunk->m_oldPtr);
+ }
+ break;
}
- case PHY_DOUBLE:
+ case PHY_DOUBLE:
{
if (numverts)
{
- btChunk* chunk = serializer->allocate(sizeof(btVector3DoubleData),numverts);
- btVector3DoubleData* tmpVertices = (btVector3DoubleData*) chunk->m_oldPtr;
- memPtr->m_vertices3d = (btVector3DoubleData *) serializer->getUniquePointer(tmpVertices);
- for (int i=0;i<numverts;i++)
- {
- double* graphicsbase = (double*)(vertexbase+i*stride);//for now convert to float, might leave it at double
- tmpVertices[i].m_floats[0] = graphicsbase[0];
- tmpVertices[i].m_floats[1] = graphicsbase[1];
- tmpVertices[i].m_floats[2] = graphicsbase[2];
- }
- serializer->finalizeChunk(chunk,"btVector3DoubleData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr);
+ btChunk* chunk = serializer->allocate(sizeof(btVector3DoubleData), numverts);
+ btVector3DoubleData* tmpVertices = (btVector3DoubleData*)chunk->m_oldPtr;
+ memPtr->m_vertices3d = (btVector3DoubleData*)serializer->getUniquePointer(tmpVertices);
+ for (int i = 0; i < numverts; i++)
+ {
+ double* graphicsbase = (double*)(vertexbase + i * stride); //for now convert to float, might leave it at double
+ tmpVertices[i].m_floats[0] = graphicsbase[0];
+ tmpVertices[i].m_floats[1] = graphicsbase[1];
+ tmpVertices[i].m_floats[2] = graphicsbase[2];
+ }
+ serializer->finalizeChunk(chunk, "btVector3DoubleData", BT_ARRAY_CODE, (void*)chunk->m_oldPtr);
}
break;
}
- default:
- btAssert((type == PHY_FLOAT) || (type == PHY_DOUBLE));
+ default:
+ btAssert((type == PHY_FLOAT) || (type == PHY_DOUBLE));
}
unLockReadOnlyVertexBase(part);
}
- serializer->finalizeChunk(chunk,"btMeshPartData",BT_ARRAY_CODE,chunk->m_oldPtr);
+ serializer->finalizeChunk(chunk, "btMeshPartData", BT_ARRAY_CODE, chunk->m_oldPtr);
}
// Fill padding with zeros to appease msan.
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.h
index 9fbe139768..7d729ee0d7 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.h
@@ -20,110 +20,102 @@ subject to the following restrictions:
#include "btTriangleCallback.h"
#include "btConcaveShape.h"
-
-
-
-
/// The btStridingMeshInterface is the interface class for high performance generic access to triangle meshes, used in combination with btBvhTriangleMeshShape and some other collision shapes.
/// Using index striding of 3*sizeof(integer) it can use triangle arrays, using index striding of 1*sizeof(integer) it can handle triangle strips.
/// It allows for sharing graphics and collision meshes. Also it provides locking/unlocking of graphics meshes that are in gpu memory.
-ATTRIBUTE_ALIGNED16(class ) btStridingMeshInterface
+ATTRIBUTE_ALIGNED16(class)
+btStridingMeshInterface
{
- protected:
-
- btVector3 m_scaling;
-
- public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btStridingMeshInterface() :m_scaling(btScalar(1.),btScalar(1.),btScalar(1.))
- {
-
- }
-
- virtual ~btStridingMeshInterface();
-
-
-
- virtual void InternalProcessAllTriangles(btInternalTriangleIndexCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
-
- ///brute force method to calculate aabb
- void calculateAabbBruteForce(btVector3& aabbMin,btVector3& aabbMax);
-
- /// get read and write access to a subpart of a triangle mesh
- /// this subpart has a continuous array of vertices and indices
- /// in this way the mesh can be handled as chunks of memory with striding
- /// very similar to OpenGL vertexarray support
- /// make a call to unLockVertexBase when the read and write access is finished
- virtual void getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0)=0;
-
- virtual void getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0) const=0;
-
- /// unLockVertexBase finishes the access to a subpart of the triangle mesh
- /// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished
- virtual void unLockVertexBase(int subpart)=0;
-
- virtual void unLockReadOnlyVertexBase(int subpart) const=0;
-
-
- /// getNumSubParts returns the number of seperate subparts
- /// each subpart has a continuous array of vertices and indices
- virtual int getNumSubParts() const=0;
-
- virtual void preallocateVertices(int numverts)=0;
- virtual void preallocateIndices(int numindices)=0;
-
- virtual bool hasPremadeAabb() const { return false; }
- virtual void setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax ) const
- {
- (void) aabbMin;
- (void) aabbMax;
- }
- virtual void getPremadeAabb(btVector3* aabbMin, btVector3* aabbMax ) const
- {
- (void) aabbMin;
- (void) aabbMax;
- }
-
- const btVector3& getScaling() const {
- return m_scaling;
- }
- void setScaling(const btVector3& scaling)
- {
- m_scaling = scaling;
- }
-
- virtual int calculateSerializeBufferSize() const;
-
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-
-
+protected:
+ btVector3 m_scaling;
+
+public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btStridingMeshInterface() : m_scaling(btScalar(1.), btScalar(1.), btScalar(1.))
+ {
+ }
+
+ virtual ~btStridingMeshInterface();
+
+ virtual void InternalProcessAllTriangles(btInternalTriangleIndexCallback * callback, const btVector3& aabbMin, const btVector3& aabbMax) const;
+
+ ///brute force method to calculate aabb
+ void calculateAabbBruteForce(btVector3 & aabbMin, btVector3 & aabbMax);
+
+ /// get read and write access to a subpart of a triangle mesh
+ /// this subpart has a continuous array of vertices and indices
+ /// in this way the mesh can be handled as chunks of memory with striding
+ /// very similar to OpenGL vertexarray support
+ /// make a call to unLockVertexBase when the read and write access is finished
+ virtual void getLockedVertexIndexBase(unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& stride, unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart = 0) = 0;
+
+ virtual void getLockedReadOnlyVertexIndexBase(const unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& stride, const unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart = 0) const = 0;
+
+ /// unLockVertexBase finishes the access to a subpart of the triangle mesh
+ /// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished
+ virtual void unLockVertexBase(int subpart) = 0;
+
+ virtual void unLockReadOnlyVertexBase(int subpart) const = 0;
+
+ /// getNumSubParts returns the number of seperate subparts
+ /// each subpart has a continuous array of vertices and indices
+ virtual int getNumSubParts() const = 0;
+
+ virtual void preallocateVertices(int numverts) = 0;
+ virtual void preallocateIndices(int numindices) = 0;
+
+ virtual bool hasPremadeAabb() const { return false; }
+ virtual void setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax) const
+ {
+ (void)aabbMin;
+ (void)aabbMax;
+ }
+ virtual void getPremadeAabb(btVector3 * aabbMin, btVector3 * aabbMax) const
+ {
+ (void)aabbMin;
+ (void)aabbMax;
+ }
+
+ const btVector3& getScaling() const
+ {
+ return m_scaling;
+ }
+ void setScaling(const btVector3& scaling)
+ {
+ m_scaling = scaling;
+ }
+
+ virtual int calculateSerializeBufferSize() const;
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
};
-struct btIntIndexData
+struct btIntIndexData
{
- int m_value;
+ int m_value;
};
-struct btShortIntIndexData
+struct btShortIntIndexData
{
short m_value;
char m_pad[2];
};
-struct btShortIntIndexTripletData
+struct btShortIntIndexTripletData
{
- short m_values[3];
- char m_pad[2];
+ short m_values[3];
+ char m_pad[2];
};
-struct btCharIndexTripletData
+struct btCharIndexTripletData
{
unsigned char m_values[3];
- char m_pad;
+ char m_pad;
};
+// clang-format off
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
struct btMeshPartData
@@ -151,14 +143,11 @@ struct btStridingMeshInterfaceData
char m_padding[4];
};
+// clang-format on
-
-
-SIMD_FORCE_INLINE int btStridingMeshInterface::calculateSerializeBufferSize() const
+SIMD_FORCE_INLINE int btStridingMeshInterface::calculateSerializeBufferSize() const
{
return sizeof(btStridingMeshInterfaceData);
}
-
-
-#endif //BT_STRIDING_MESHINTERFACE_H
+#endif //BT_STRIDING_MESHINTERFACE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btTetrahedronShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btTetrahedronShape.cpp
index 52f346bf72..c4d33c429f 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btTetrahedronShape.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btTetrahedronShape.cpp
@@ -16,29 +16,29 @@ subject to the following restrictions:
#include "btTetrahedronShape.h"
#include "LinearMath/btMatrix3x3.h"
-btBU_Simplex1to4::btBU_Simplex1to4() : btPolyhedralConvexAabbCachingShape (),
-m_numVertices(0)
+btBU_Simplex1to4::btBU_Simplex1to4() : btPolyhedralConvexAabbCachingShape(),
+ m_numVertices(0)
{
m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE;
}
-btBU_Simplex1to4::btBU_Simplex1to4(const btVector3& pt0) : btPolyhedralConvexAabbCachingShape (),
-m_numVertices(0)
+btBU_Simplex1to4::btBU_Simplex1to4(const btVector3& pt0) : btPolyhedralConvexAabbCachingShape(),
+ m_numVertices(0)
{
m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE;
addVertex(pt0);
}
-btBU_Simplex1to4::btBU_Simplex1to4(const btVector3& pt0,const btVector3& pt1) : btPolyhedralConvexAabbCachingShape (),
-m_numVertices(0)
+btBU_Simplex1to4::btBU_Simplex1to4(const btVector3& pt0, const btVector3& pt1) : btPolyhedralConvexAabbCachingShape(),
+ m_numVertices(0)
{
m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE;
addVertex(pt0);
addVertex(pt1);
}
-btBU_Simplex1to4::btBU_Simplex1to4(const btVector3& pt0,const btVector3& pt1,const btVector3& pt2) : btPolyhedralConvexAabbCachingShape (),
-m_numVertices(0)
+btBU_Simplex1to4::btBU_Simplex1to4(const btVector3& pt0, const btVector3& pt1, const btVector3& pt2) : btPolyhedralConvexAabbCachingShape(),
+ m_numVertices(0)
{
m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE;
addVertex(pt0);
@@ -46,8 +46,8 @@ m_numVertices(0)
addVertex(pt2);
}
-btBU_Simplex1to4::btBU_Simplex1to4(const btVector3& pt0,const btVector3& pt1,const btVector3& pt2,const btVector3& pt3) : btPolyhedralConvexAabbCachingShape (),
-m_numVertices(0)
+btBU_Simplex1to4::btBU_Simplex1to4(const btVector3& pt0, const btVector3& pt1, const btVector3& pt2, const btVector3& pt3) : btPolyhedralConvexAabbCachingShape(),
+ m_numVertices(0)
{
m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE;
addVertex(pt0);
@@ -56,17 +56,16 @@ m_numVertices(0)
addVertex(pt3);
}
-
-void btBU_Simplex1to4::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+void btBU_Simplex1to4::getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
{
#if 1
- btPolyhedralConvexAabbCachingShape::getAabb(t,aabbMin,aabbMax);
+ btPolyhedralConvexAabbCachingShape::getAabb(t, aabbMin, aabbMax);
#else
- aabbMin.setValue(BT_LARGE_FLOAT,BT_LARGE_FLOAT,BT_LARGE_FLOAT);
- aabbMax.setValue(-BT_LARGE_FLOAT,-BT_LARGE_FLOAT,-BT_LARGE_FLOAT);
+ aabbMin.setValue(BT_LARGE_FLOAT, BT_LARGE_FLOAT, BT_LARGE_FLOAT);
+ aabbMax.setValue(-BT_LARGE_FLOAT, -BT_LARGE_FLOAT, -BT_LARGE_FLOAT);
//just transform the vertices in worldspace, and take their AABB
- for (int i=0;i<m_numVertices;i++)
+ for (int i = 0; i < m_numVertices; i++)
{
btVector3 worldVertex = t(m_vertices[i]);
aabbMin.setMin(worldVertex);
@@ -75,18 +74,13 @@ void btBU_Simplex1to4::getAabb(const btTransform& t,btVector3& aabbMin,btVector3
#endif
}
-
-
-
-
void btBU_Simplex1to4::addVertex(const btVector3& pt)
{
m_vertices[m_numVertices++] = pt;
recalcLocalAabb();
}
-
-int btBU_Simplex1to4::getNumVertices() const
+int btBU_Simplex1to4::getNumVertices() const
{
return m_numVertices;
}
@@ -97,122 +91,113 @@ int btBU_Simplex1to4::getNumEdges() const
switch (m_numVertices)
{
- case 0:
- return 0;
- case 1: return 0;
- case 2: return 1;
- case 3: return 3;
- case 4: return 6;
-
-
+ case 0:
+ return 0;
+ case 1:
+ return 0;
+ case 2:
+ return 1;
+ case 3:
+ return 3;
+ case 4:
+ return 6;
}
return 0;
}
-void btBU_Simplex1to4::getEdge(int i,btVector3& pa,btVector3& pb) const
+void btBU_Simplex1to4::getEdge(int i, btVector3& pa, btVector3& pb) const
{
-
- switch (m_numVertices)
+ switch (m_numVertices)
{
-
- case 2:
- pa = m_vertices[0];
- pb = m_vertices[1];
- break;
- case 3:
- switch (i)
- {
- case 0:
- pa = m_vertices[0];
- pb = m_vertices[1];
- break;
- case 1:
- pa = m_vertices[1];
- pb = m_vertices[2];
- break;
case 2:
- pa = m_vertices[2];
- pb = m_vertices[0];
- break;
-
- }
- break;
- case 4:
- switch (i)
- {
- case 0:
pa = m_vertices[0];
pb = m_vertices[1];
break;
- case 1:
- pa = m_vertices[1];
- pb = m_vertices[2];
- break;
- case 2:
- pa = m_vertices[2];
- pb = m_vertices[0];
- break;
case 3:
- pa = m_vertices[0];
- pb = m_vertices[3];
+ switch (i)
+ {
+ case 0:
+ pa = m_vertices[0];
+ pb = m_vertices[1];
+ break;
+ case 1:
+ pa = m_vertices[1];
+ pb = m_vertices[2];
+ break;
+ case 2:
+ pa = m_vertices[2];
+ pb = m_vertices[0];
+ break;
+ }
break;
case 4:
- pa = m_vertices[1];
- pb = m_vertices[3];
- break;
- case 5:
- pa = m_vertices[2];
- pb = m_vertices[3];
- break;
- }
-
+ switch (i)
+ {
+ case 0:
+ pa = m_vertices[0];
+ pb = m_vertices[1];
+ break;
+ case 1:
+ pa = m_vertices[1];
+ pb = m_vertices[2];
+ break;
+ case 2:
+ pa = m_vertices[2];
+ pb = m_vertices[0];
+ break;
+ case 3:
+ pa = m_vertices[0];
+ pb = m_vertices[3];
+ break;
+ case 4:
+ pa = m_vertices[1];
+ pb = m_vertices[3];
+ break;
+ case 5:
+ pa = m_vertices[2];
+ pb = m_vertices[3];
+ break;
+ }
}
-
-
-
-
}
-void btBU_Simplex1to4::getVertex(int i,btVector3& vtx) const
+void btBU_Simplex1to4::getVertex(int i, btVector3& vtx) const
{
vtx = m_vertices[i];
}
-int btBU_Simplex1to4::getNumPlanes() const
+int btBU_Simplex1to4::getNumPlanes() const
{
switch (m_numVertices)
{
- case 0:
+ case 0:
return 0;
- case 1:
+ case 1:
return 0;
- case 2:
+ case 2:
return 0;
- case 3:
+ case 3:
return 2;
- case 4:
+ case 4:
return 4;
- default:
+ default:
{
}
}
return 0;
}
-
-void btBU_Simplex1to4::getPlane(btVector3&, btVector3& ,int ) const
+void btBU_Simplex1to4::getPlane(btVector3&, btVector3&, int) const
{
-
}
-int btBU_Simplex1to4::getIndex(int ) const
+int btBU_Simplex1to4::getIndex(int) const
{
return 0;
}
-bool btBU_Simplex1to4::isInside(const btVector3& ,btScalar ) const
+bool btBU_Simplex1to4::isInside(const btVector3&, btScalar) const
{
return false;
}
-
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btTetrahedronShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btTetrahedronShape.h
index b69209835e..f5e2209ed0 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btTetrahedronShape.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btTetrahedronShape.h
@@ -16,61 +16,56 @@ subject to the following restrictions:
#ifndef BT_SIMPLEX_1TO4_SHAPE
#define BT_SIMPLEX_1TO4_SHAPE
-
#include "btPolyhedralConvexShape.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
-
///The btBU_Simplex1to4 implements tetrahedron, triangle, line, vertex collision shapes. In most cases it is better to use btConvexHullShape instead.
-ATTRIBUTE_ALIGNED16(class) btBU_Simplex1to4 : public btPolyhedralConvexAabbCachingShape
+ATTRIBUTE_ALIGNED16(class)
+btBU_Simplex1to4 : public btPolyhedralConvexAabbCachingShape
{
protected:
-
- int m_numVertices;
- btVector3 m_vertices[4];
+ int m_numVertices;
+ btVector3 m_vertices[4];
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
-
+
btBU_Simplex1to4();
btBU_Simplex1to4(const btVector3& pt0);
- btBU_Simplex1to4(const btVector3& pt0,const btVector3& pt1);
- btBU_Simplex1to4(const btVector3& pt0,const btVector3& pt1,const btVector3& pt2);
- btBU_Simplex1to4(const btVector3& pt0,const btVector3& pt1,const btVector3& pt2,const btVector3& pt3);
+ btBU_Simplex1to4(const btVector3& pt0, const btVector3& pt1);
+ btBU_Simplex1to4(const btVector3& pt0, const btVector3& pt1, const btVector3& pt2);
+ btBU_Simplex1to4(const btVector3& pt0, const btVector3& pt1, const btVector3& pt2, const btVector3& pt3);
-
- void reset()
+ void reset()
{
m_numVertices = 0;
}
-
- virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+ virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
void addVertex(const btVector3& pt);
//PolyhedralConvexShape interface
- virtual int getNumVertices() const;
+ virtual int getNumVertices() const;
virtual int getNumEdges() const;
- virtual void getEdge(int i,btVector3& pa,btVector3& pb) const;
-
- virtual void getVertex(int i,btVector3& vtx) const;
+ virtual void getEdge(int i, btVector3& pa, btVector3& pb) const;
- virtual int getNumPlanes() const;
+ virtual void getVertex(int i, btVector3& vtx) const;
- virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i) const;
+ virtual int getNumPlanes() const;
- virtual int getIndex(int i) const;
+ virtual void getPlane(btVector3 & planeNormal, btVector3 & planeSupport, int i) const;
- virtual bool isInside(const btVector3& pt,btScalar tolerance) const;
+ virtual int getIndex(int i) const;
+ virtual bool isInside(const btVector3& pt, btScalar tolerance) const;
///getName is for debugging
- virtual const char* getName()const { return "btBU_Simplex1to4";}
-
+ virtual const char* getName() const { return "btBU_Simplex1to4"; }
};
-#endif //BT_SIMPLEX_1TO4_SHAPE
+#endif //BT_SIMPLEX_1TO4_SHAPE
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleBuffer.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleBuffer.cpp
index 3027e65b25..3b6db2b39f 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleBuffer.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleBuffer.cpp
@@ -15,21 +15,14 @@ subject to the following restrictions:
#include "btTriangleBuffer.h"
-
-
-
-
-
-
-void btTriangleBuffer::processTriangle(btVector3* triangle,int partId,int triangleIndex)
+void btTriangleBuffer::processTriangle(btVector3* triangle, int partId, int triangleIndex)
{
- btTriangle tri;
- tri.m_vertex0 = triangle[0];
- tri.m_vertex1 = triangle[1];
- tri.m_vertex2 = triangle[2];
- tri.m_partId = partId;
- tri.m_triangleIndex = triangleIndex;
-
- m_triangleBuffer.push_back(tri);
+ btTriangle tri;
+ tri.m_vertex0 = triangle[0];
+ tri.m_vertex1 = triangle[1];
+ tri.m_vertex2 = triangle[2];
+ tri.m_partId = partId;
+ tri.m_triangleIndex = triangleIndex;
+
+ m_triangleBuffer.push_back(tri);
}
-
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleBuffer.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleBuffer.h
index b71fc8b374..a89b9cd8a4 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleBuffer.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleBuffer.h
@@ -19,13 +19,13 @@ subject to the following restrictions:
#include "btTriangleCallback.h"
#include "LinearMath/btAlignedObjectArray.h"
-struct btTriangle
+struct btTriangle
{
- btVector3 m_vertex0;
- btVector3 m_vertex1;
- btVector3 m_vertex2;
- int m_partId;
- int m_triangleIndex;
+ btVector3 m_vertex0;
+ btVector3 m_vertex1;
+ btVector3 m_vertex2;
+ int m_partId;
+ int m_triangleIndex;
};
///The btTriangleBuffer callback can be useful to collect and store overlapping triangles between AABB and concave objects that support 'processAllTriangles'
@@ -39,31 +39,25 @@ struct btTriangle
/// }
class btTriangleBuffer : public btTriangleCallback
{
+ btAlignedObjectArray<btTriangle> m_triangleBuffer;
- btAlignedObjectArray<btTriangle> m_triangleBuffer;
-
public:
-
-
virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex);
-
- int getNumTriangles() const
+
+ int getNumTriangles() const
{
return int(m_triangleBuffer.size());
}
-
- const btTriangle& getTriangle(int index) const
+
+ const btTriangle& getTriangle(int index) const
{
return m_triangleBuffer[index];
}
- void clearBuffer()
+ void clearBuffer()
{
m_triangleBuffer.clear();
}
-
};
-
-#endif //BT_TRIANGLE_BUFFER_H
-
+#endif //BT_TRIANGLE_BUFFER_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleCallback.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleCallback.cpp
index f558bf6d24..5bd2c595fe 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleCallback.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleCallback.cpp
@@ -17,12 +17,8 @@ subject to the following restrictions:
btTriangleCallback::~btTriangleCallback()
{
-
}
-
btInternalTriangleIndexCallback::~btInternalTriangleIndexCallback()
{
-
}
-
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleCallback.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleCallback.h
index 461c57f877..d3644891ee 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleCallback.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleCallback.h
@@ -18,13 +18,11 @@ subject to the following restrictions:
#include "LinearMath/btVector3.h"
-
///The btTriangleCallback provides a callback for each overlapping triangle when calling processAllTriangles.
///This callback is called by processAllTriangles for all btConcaveShape derived class, such as btBvhTriangleMeshShape, btStaticPlaneShape and btHeightfieldTerrainShape.
class btTriangleCallback
{
public:
-
virtual ~btTriangleCallback();
virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex) = 0;
};
@@ -32,11 +30,8 @@ public:
class btInternalTriangleIndexCallback
{
public:
-
virtual ~btInternalTriangleIndexCallback();
- virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) = 0;
+ virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex) = 0;
};
-
-
-#endif //BT_TRIANGLE_CALLBACK_H
+#endif //BT_TRIANGLE_CALLBACK_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp
index a665024cb6..dae4255194 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp
@@ -15,81 +15,76 @@ subject to the following restrictions:
#include "btTriangleIndexVertexArray.h"
-btTriangleIndexVertexArray::btTriangleIndexVertexArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,int numVertices,btScalar* vertexBase,int vertexStride)
-: m_hasAabb(0)
+btTriangleIndexVertexArray::btTriangleIndexVertexArray(int numTriangles, int* triangleIndexBase, int triangleIndexStride, int numVertices, btScalar* vertexBase, int vertexStride)
+ : m_hasAabb(0)
{
btIndexedMesh mesh;
mesh.m_numTriangles = numTriangles;
- mesh.m_triangleIndexBase = (const unsigned char *)triangleIndexBase;
+ mesh.m_triangleIndexBase = (const unsigned char*)triangleIndexBase;
mesh.m_triangleIndexStride = triangleIndexStride;
mesh.m_numVertices = numVertices;
- mesh.m_vertexBase = (const unsigned char *)vertexBase;
+ mesh.m_vertexBase = (const unsigned char*)vertexBase;
mesh.m_vertexStride = vertexStride;
addIndexedMesh(mesh);
-
}
btTriangleIndexVertexArray::~btTriangleIndexVertexArray()
{
-
}
-void btTriangleIndexVertexArray::getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart)
+void btTriangleIndexVertexArray::getLockedVertexIndexBase(unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& vertexStride, unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart)
{
- btAssert(subpart< getNumSubParts() );
+ btAssert(subpart < getNumSubParts());
btIndexedMesh& mesh = m_indexedMeshes[subpart];
numverts = mesh.m_numVertices;
- (*vertexbase) = (unsigned char *) mesh.m_vertexBase;
+ (*vertexbase) = (unsigned char*)mesh.m_vertexBase;
- type = mesh.m_vertexType;
+ type = mesh.m_vertexType;
vertexStride = mesh.m_vertexStride;
numfaces = mesh.m_numTriangles;
- (*indexbase) = (unsigned char *)mesh.m_triangleIndexBase;
+ (*indexbase) = (unsigned char*)mesh.m_triangleIndexBase;
indexstride = mesh.m_triangleIndexStride;
indicestype = mesh.m_indexType;
}
-void btTriangleIndexVertexArray::getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart) const
+void btTriangleIndexVertexArray::getLockedReadOnlyVertexIndexBase(const unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& vertexStride, const unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart) const
{
const btIndexedMesh& mesh = m_indexedMeshes[subpart];
numverts = mesh.m_numVertices;
- (*vertexbase) = (const unsigned char *)mesh.m_vertexBase;
+ (*vertexbase) = (const unsigned char*)mesh.m_vertexBase;
+
+ type = mesh.m_vertexType;
- type = mesh.m_vertexType;
-
vertexStride = mesh.m_vertexStride;
numfaces = mesh.m_numTriangles;
- (*indexbase) = (const unsigned char *)mesh.m_triangleIndexBase;
+ (*indexbase) = (const unsigned char*)mesh.m_triangleIndexBase;
indexstride = mesh.m_triangleIndexStride;
indicestype = mesh.m_indexType;
}
-bool btTriangleIndexVertexArray::hasPremadeAabb() const
+bool btTriangleIndexVertexArray::hasPremadeAabb() const
{
return (m_hasAabb == 1);
}
-
-void btTriangleIndexVertexArray::setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax ) const
+void btTriangleIndexVertexArray::setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax) const
{
m_aabbMin = aabbMin;
m_aabbMax = aabbMax;
- m_hasAabb = 1; // this is intentionally an int see notes in header
+ m_hasAabb = 1; // this is intentionally an int see notes in header
}
-void btTriangleIndexVertexArray::getPremadeAabb(btVector3* aabbMin, btVector3* aabbMax ) const
+void btTriangleIndexVertexArray::getPremadeAabb(btVector3* aabbMin, btVector3* aabbMax) const
{
*aabbMin = m_aabbMin;
*aabbMax = m_aabbMax;
}
-
-
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h
index b7a6f74361..8ebb22baae 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h
@@ -20,62 +20,59 @@ subject to the following restrictions:
#include "LinearMath/btAlignedObjectArray.h"
#include "LinearMath/btScalar.h"
-
///The btIndexedMesh indexes a single vertex and index array. Multiple btIndexedMesh objects can be passed into a btTriangleIndexVertexArray using addIndexedMesh.
///Instead of the number of indices, we pass the number of triangles.
-ATTRIBUTE_ALIGNED16( struct) btIndexedMesh
+ATTRIBUTE_ALIGNED16(struct)
+btIndexedMesh
{
BT_DECLARE_ALIGNED_ALLOCATOR();
- int m_numTriangles;
- const unsigned char * m_triangleIndexBase;
- // Size in byte of the indices for one triangle (3*sizeof(index_type) if the indices are tightly packed)
- int m_triangleIndexStride;
- int m_numVertices;
- const unsigned char * m_vertexBase;
- // Size of a vertex, in bytes
- int m_vertexStride;
-
- // The index type is set when adding an indexed mesh to the
- // btTriangleIndexVertexArray, do not set it manually
- PHY_ScalarType m_indexType;
-
- // The vertex type has a default type similar to Bullet's precision mode (float or double)
- // but can be set manually if you for example run Bullet with double precision but have
- // mesh data in single precision..
- PHY_ScalarType m_vertexType;
-
-
- btIndexedMesh()
- :m_indexType(PHY_INTEGER),
+ int m_numTriangles;
+ const unsigned char* m_triangleIndexBase;
+ // Size in byte of the indices for one triangle (3*sizeof(index_type) if the indices are tightly packed)
+ int m_triangleIndexStride;
+ int m_numVertices;
+ const unsigned char* m_vertexBase;
+ // Size of a vertex, in bytes
+ int m_vertexStride;
+
+ // The index type is set when adding an indexed mesh to the
+ // btTriangleIndexVertexArray, do not set it manually
+ PHY_ScalarType m_indexType;
+
+ // The vertex type has a default type similar to Bullet's precision mode (float or double)
+ // but can be set manually if you for example run Bullet with double precision but have
+ // mesh data in single precision..
+ PHY_ScalarType m_vertexType;
+
+ btIndexedMesh()
+ : m_indexType(PHY_INTEGER),
#ifdef BT_USE_DOUBLE_PRECISION
- m_vertexType(PHY_DOUBLE)
-#else // BT_USE_DOUBLE_PRECISION
- m_vertexType(PHY_FLOAT)
-#endif // BT_USE_DOUBLE_PRECISION
- {
- }
-}
-;
-
+ m_vertexType(PHY_DOUBLE)
+#else // BT_USE_DOUBLE_PRECISION
+ m_vertexType(PHY_FLOAT)
+#endif // BT_USE_DOUBLE_PRECISION
+ {
+ }
+};
-typedef btAlignedObjectArray<btIndexedMesh> IndexedMeshArray;
+typedef btAlignedObjectArray<btIndexedMesh> IndexedMeshArray;
///The btTriangleIndexVertexArray allows to access multiple triangle meshes, by indexing into existing triangle/index arrays.
///Additional meshes can be added using addIndexedMesh
///No duplicate is made of the vertex/index data, it only indexes into external vertex/index arrays.
///So keep those arrays around during the lifetime of this btTriangleIndexVertexArray.
-ATTRIBUTE_ALIGNED16( class) btTriangleIndexVertexArray : public btStridingMeshInterface
+ATTRIBUTE_ALIGNED16(class)
+btTriangleIndexVertexArray : public btStridingMeshInterface
{
protected:
- IndexedMeshArray m_indexedMeshes;
+ IndexedMeshArray m_indexedMeshes;
int m_pad[2];
- mutable int m_hasAabb; // using int instead of bool to maintain alignment
+ mutable int m_hasAabb; // using int instead of bool to maintain alignment
mutable btVector3 m_aabbMin;
mutable btVector3 m_aabbMax;
public:
-
BT_DECLARE_ALIGNED_ALLOCATOR();
btTriangleIndexVertexArray() : m_hasAabb(0)
@@ -85,49 +82,47 @@ public:
virtual ~btTriangleIndexVertexArray();
//just to be backwards compatible
- btTriangleIndexVertexArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,int numVertices,btScalar* vertexBase,int vertexStride);
-
- void addIndexedMesh(const btIndexedMesh& mesh, PHY_ScalarType indexType = PHY_INTEGER)
+ btTriangleIndexVertexArray(int numTriangles, int* triangleIndexBase, int triangleIndexStride, int numVertices, btScalar* vertexBase, int vertexStride);
+
+ void addIndexedMesh(const btIndexedMesh& mesh, PHY_ScalarType indexType = PHY_INTEGER)
{
m_indexedMeshes.push_back(mesh);
- m_indexedMeshes[m_indexedMeshes.size()-1].m_indexType = indexType;
+ m_indexedMeshes[m_indexedMeshes.size() - 1].m_indexType = indexType;
}
-
-
- virtual void getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0);
- virtual void getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0) const;
+ virtual void getLockedVertexIndexBase(unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& vertexStride, unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart = 0);
+
+ virtual void getLockedReadOnlyVertexIndexBase(const unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& vertexStride, const unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart = 0) const;
/// unLockVertexBase finishes the access to a subpart of the triangle mesh
/// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished
- virtual void unLockVertexBase(int subpart) {(void)subpart;}
+ virtual void unLockVertexBase(int subpart) { (void)subpart; }
- virtual void unLockReadOnlyVertexBase(int subpart) const {(void)subpart;}
+ virtual void unLockReadOnlyVertexBase(int subpart) const { (void)subpart; }
/// getNumSubParts returns the number of seperate subparts
/// each subpart has a continuous array of vertices and indices
- virtual int getNumSubParts() const {
+ virtual int getNumSubParts() const
+ {
return (int)m_indexedMeshes.size();
}
- IndexedMeshArray& getIndexedMeshArray()
+ IndexedMeshArray& getIndexedMeshArray()
{
return m_indexedMeshes;
}
- const IndexedMeshArray& getIndexedMeshArray() const
+ const IndexedMeshArray& getIndexedMeshArray() const
{
return m_indexedMeshes;
}
- virtual void preallocateVertices(int numverts){(void) numverts;}
- virtual void preallocateIndices(int numindices){(void) numindices;}
-
- virtual bool hasPremadeAabb() const;
- virtual void setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax ) const;
- virtual void getPremadeAabb(btVector3* aabbMin, btVector3* aabbMax ) const;
+ virtual void preallocateVertices(int numverts) { (void)numverts; }
+ virtual void preallocateIndices(int numindices) { (void)numindices; }
-}
-;
+ virtual bool hasPremadeAabb() const;
+ virtual void setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax) const;
+ virtual void getPremadeAabb(btVector3 * aabbMin, btVector3 * aabbMax) const;
+};
-#endif //BT_TRIANGLE_INDEX_VERTEX_ARRAY_H
+#endif //BT_TRIANGLE_INDEX_VERTEX_ARRAY_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp
index dc562941ad..4bf133d7ac 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp
@@ -17,70 +17,68 @@ subject to the following restrictions:
#include "btTriangleIndexVertexMaterialArray.h"
-btTriangleIndexVertexMaterialArray::btTriangleIndexVertexMaterialArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,
- int numVertices,btScalar* vertexBase,int vertexStride,
- int numMaterials, unsigned char* materialBase, int materialStride,
- int* triangleMaterialsBase, int materialIndexStride) :
-btTriangleIndexVertexArray(numTriangles, triangleIndexBase, triangleIndexStride, numVertices, vertexBase, vertexStride)
+btTriangleIndexVertexMaterialArray::btTriangleIndexVertexMaterialArray(int numTriangles, int* triangleIndexBase, int triangleIndexStride,
+ int numVertices, btScalar* vertexBase, int vertexStride,
+ int numMaterials, unsigned char* materialBase, int materialStride,
+ int* triangleMaterialsBase, int materialIndexStride) : btTriangleIndexVertexArray(numTriangles, triangleIndexBase, triangleIndexStride, numVertices, vertexBase, vertexStride)
{
- btMaterialProperties mat;
+ btMaterialProperties mat;
- mat.m_numMaterials = numMaterials;
- mat.m_materialBase = materialBase;
- mat.m_materialStride = materialStride;
+ mat.m_numMaterials = numMaterials;
+ mat.m_materialBase = materialBase;
+ mat.m_materialStride = materialStride;
#ifdef BT_USE_DOUBLE_PRECISION
- mat.m_materialType = PHY_DOUBLE;
+ mat.m_materialType = PHY_DOUBLE;
#else
- mat.m_materialType = PHY_FLOAT;
+ mat.m_materialType = PHY_FLOAT;
#endif
- mat.m_numTriangles = numTriangles;
- mat.m_triangleMaterialsBase = (unsigned char *)triangleMaterialsBase;
- mat.m_triangleMaterialStride = materialIndexStride;
- mat.m_triangleType = PHY_INTEGER;
+ mat.m_numTriangles = numTriangles;
+ mat.m_triangleMaterialsBase = (unsigned char*)triangleMaterialsBase;
+ mat.m_triangleMaterialStride = materialIndexStride;
+ mat.m_triangleType = PHY_INTEGER;
- addMaterialProperties(mat);
+ addMaterialProperties(mat);
}
-
-void btTriangleIndexVertexMaterialArray::getLockedMaterialBase(unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
- unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart)
+void btTriangleIndexVertexMaterialArray::getLockedMaterialBase(unsigned char** materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
+ unsigned char** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart)
{
- btAssert(subpart< getNumSubParts() );
+ btAssert(subpart < getNumSubParts());
- btMaterialProperties& mats = m_materials[subpart];
+ btMaterialProperties& mats = m_materials[subpart];
- numMaterials = mats.m_numMaterials;
- (*materialBase) = (unsigned char *) mats.m_materialBase;
+ numMaterials = mats.m_numMaterials;
+ (*materialBase) = (unsigned char*)mats.m_materialBase;
#ifdef BT_USE_DOUBLE_PRECISION
- materialType = PHY_DOUBLE;
+ materialType = PHY_DOUBLE;
#else
- materialType = PHY_FLOAT;
+ materialType = PHY_FLOAT;
#endif
- materialStride = mats.m_materialStride;
+ materialStride = mats.m_materialStride;
- numTriangles = mats.m_numTriangles;
- (*triangleMaterialBase) = (unsigned char *)mats.m_triangleMaterialsBase;
- triangleMaterialStride = mats.m_triangleMaterialStride;
- triangleType = mats.m_triangleType;
+ numTriangles = mats.m_numTriangles;
+ (*triangleMaterialBase) = (unsigned char*)mats.m_triangleMaterialsBase;
+ triangleMaterialStride = mats.m_triangleMaterialStride;
+ triangleType = mats.m_triangleType;
}
-void btTriangleIndexVertexMaterialArray::getLockedReadOnlyMaterialBase(const unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
- const unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart)
+void btTriangleIndexVertexMaterialArray::getLockedReadOnlyMaterialBase(const unsigned char** materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
+ const unsigned char** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart)
{
- btMaterialProperties& mats = m_materials[subpart];
+ btMaterialProperties& mats = m_materials[subpart];
- numMaterials = mats.m_numMaterials;
- (*materialBase) = (const unsigned char *) mats.m_materialBase;
+ numMaterials = mats.m_numMaterials;
+ (*materialBase) = (const unsigned char*)mats.m_materialBase;
#ifdef BT_USE_DOUBLE_PRECISION
- materialType = PHY_DOUBLE;
+ materialType = PHY_DOUBLE;
#else
- materialType = PHY_FLOAT;
+ materialType = PHY_FLOAT;
#endif
- materialStride = mats.m_materialStride;
+ materialStride = mats.m_materialStride;
- numTriangles = mats.m_numTriangles;
- (*triangleMaterialBase) = (const unsigned char *)mats.m_triangleMaterialsBase;
- triangleMaterialStride = mats.m_triangleMaterialStride;
- triangleType = mats.m_triangleType;
+ numTriangles = mats.m_numTriangles;
+ (*triangleMaterialBase) = (const unsigned char*)mats.m_triangleMaterialsBase;
+ triangleMaterialStride = mats.m_triangleMaterialStride;
+ triangleType = mats.m_triangleType;
}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h
index ba4f7b4607..315b1e21f3 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h
@@ -20,26 +20,26 @@ subject to the following restrictions:
#include "btTriangleIndexVertexArray.h"
-
-ATTRIBUTE_ALIGNED16( struct) btMaterialProperties
+ATTRIBUTE_ALIGNED16(struct)
+btMaterialProperties
{
- ///m_materialBase ==========> 2 btScalar values make up one material, friction then restitution
- int m_numMaterials;
- const unsigned char * m_materialBase;
- int m_materialStride;
- PHY_ScalarType m_materialType;
- ///m_numTriangles <=========== This exists in the btIndexedMesh object for the same subpart, but since we're
- /// padding the structure, it can be reproduced at no real cost
- ///m_triangleMaterials =====> 1 integer value makes up one entry
- /// eg: m_triangleMaterials[1] = 5; // This will set triangle 2 to use material 5
- int m_numTriangles;
- const unsigned char * m_triangleMaterialsBase;
- int m_triangleMaterialStride;
- ///m_triangleType <========== Automatically set in addMaterialProperties
- PHY_ScalarType m_triangleType;
+ ///m_materialBase ==========> 2 btScalar values make up one material, friction then restitution
+ int m_numMaterials;
+ const unsigned char* m_materialBase;
+ int m_materialStride;
+ PHY_ScalarType m_materialType;
+ ///m_numTriangles <=========== This exists in the btIndexedMesh object for the same subpart, but since we're
+ /// padding the structure, it can be reproduced at no real cost
+ ///m_triangleMaterials =====> 1 integer value makes up one entry
+ /// eg: m_triangleMaterials[1] = 5; // This will set triangle 2 to use material 5
+ int m_numTriangles;
+ const unsigned char* m_triangleMaterialsBase;
+ int m_triangleMaterialStride;
+ ///m_triangleType <========== Automatically set in addMaterialProperties
+ PHY_ScalarType m_triangleType;
};
-typedef btAlignedObjectArray<btMaterialProperties> MaterialArray;
+typedef btAlignedObjectArray<btMaterialProperties> MaterialArray;
///Teh btTriangleIndexVertexMaterialArray is built on TriangleIndexVertexArray
///The addition of a material array allows for the utilization of the partID and
@@ -47,38 +47,37 @@ typedef btAlignedObjectArray<btMaterialProperties> MaterialArray;
///TriangleIndexVertexArray, no duplicate is made of the material data, so it
///is the users responsibility to maintain the array during the lifetime of the
///TriangleIndexVertexMaterialArray.
-ATTRIBUTE_ALIGNED16(class) btTriangleIndexVertexMaterialArray : public btTriangleIndexVertexArray
+ATTRIBUTE_ALIGNED16(class)
+btTriangleIndexVertexMaterialArray : public btTriangleIndexVertexArray
{
protected:
- MaterialArray m_materials;
-
+ MaterialArray m_materials;
+
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
- btTriangleIndexVertexMaterialArray()
+ btTriangleIndexVertexMaterialArray()
{
}
- btTriangleIndexVertexMaterialArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,
- int numVertices,btScalar* vertexBase,int vertexStride,
- int numMaterials, unsigned char* materialBase, int materialStride,
- int* triangleMaterialsBase, int materialIndexStride);
-
- virtual ~btTriangleIndexVertexMaterialArray() {}
+ btTriangleIndexVertexMaterialArray(int numTriangles, int* triangleIndexBase, int triangleIndexStride,
+ int numVertices, btScalar* vertexBase, int vertexStride,
+ int numMaterials, unsigned char* materialBase, int materialStride,
+ int* triangleMaterialsBase, int materialIndexStride);
- void addMaterialProperties(const btMaterialProperties& mat, PHY_ScalarType triangleType = PHY_INTEGER)
- {
- m_materials.push_back(mat);
- m_materials[m_materials.size()-1].m_triangleType = triangleType;
- }
+ virtual ~btTriangleIndexVertexMaterialArray() {}
- virtual void getLockedMaterialBase(unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
- unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType ,int subpart = 0);
+ void addMaterialProperties(const btMaterialProperties& mat, PHY_ScalarType triangleType = PHY_INTEGER)
+ {
+ m_materials.push_back(mat);
+ m_materials[m_materials.size() - 1].m_triangleType = triangleType;
+ }
- virtual void getLockedReadOnlyMaterialBase(const unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
- const unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart = 0);
+ virtual void getLockedMaterialBase(unsigned char** materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
+ unsigned char** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart = 0);
-}
-;
+ virtual void getLockedReadOnlyMaterialBase(const unsigned char** materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
+ const unsigned char** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart = 0);
+};
-#endif //BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H
+#endif //BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleInfoMap.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleInfoMap.h
index 6427589590..8ee35ef5fa 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleInfoMap.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleInfoMap.h
@@ -16,11 +16,9 @@ subject to the following restrictions:
#ifndef _BT_TRIANGLE_INFO_MAP_H
#define _BT_TRIANGLE_INFO_MAP_H
-
#include "LinearMath/btHashMap.h"
#include "LinearMath/btSerializer.h"
-
///for btTriangleInfo m_flags
#define TRI_INFO_V0V1_CONVEX 1
#define TRI_INFO_V1V2_CONVEX 2
@@ -30,61 +28,58 @@ subject to the following restrictions:
#define TRI_INFO_V1V2_SWAP_NORMALB 16
#define TRI_INFO_V2V0_SWAP_NORMALB 32
-
///The btTriangleInfo structure stores information to adjust collision normals to avoid collisions against internal edges
-///it can be generated using
-struct btTriangleInfo
+///it can be generated using
+struct btTriangleInfo
{
btTriangleInfo()
{
m_edgeV0V1Angle = SIMD_2_PI;
m_edgeV1V2Angle = SIMD_2_PI;
m_edgeV2V0Angle = SIMD_2_PI;
- m_flags=0;
+ m_flags = 0;
}
- int m_flags;
-
- btScalar m_edgeV0V1Angle;
- btScalar m_edgeV1V2Angle;
- btScalar m_edgeV2V0Angle;
+ int m_flags;
+ btScalar m_edgeV0V1Angle;
+ btScalar m_edgeV1V2Angle;
+ btScalar m_edgeV2V0Angle;
};
-typedef btHashMap<btHashInt,btTriangleInfo> btInternalTriangleInfoMap;
-
+typedef btHashMap<btHashInt, btTriangleInfo> btInternalTriangleInfoMap;
///The btTriangleInfoMap stores edge angle information for some triangles. You can compute this information yourself or using btGenerateInternalEdgeInfo.
-struct btTriangleInfoMap : public btInternalTriangleInfoMap
+struct btTriangleInfoMap : public btInternalTriangleInfoMap
{
- btScalar m_convexEpsilon;///used to determine if an edge or contact normal is convex, using the dot product
- btScalar m_planarEpsilon; ///used to determine if a triangle edge is planar with zero angle
- btScalar m_equalVertexThreshold; ///used to compute connectivity: if the distance between two vertices is smaller than m_equalVertexThreshold, they are considered to be 'shared'
- btScalar m_edgeDistanceThreshold; ///used to determine edge contacts: if the closest distance between a contact point and an edge is smaller than this distance threshold it is considered to "hit the edge"
- btScalar m_maxEdgeAngleThreshold; //ignore edges that connect triangles at an angle larger than this m_maxEdgeAngleThreshold
- btScalar m_zeroAreaThreshold; ///used to determine if a triangle is degenerate (length squared of cross product of 2 triangle edges < threshold)
-
-
+ btScalar m_convexEpsilon; ///used to determine if an edge or contact normal is convex, using the dot product
+ btScalar m_planarEpsilon; ///used to determine if a triangle edge is planar with zero angle
+ btScalar m_equalVertexThreshold; ///used to compute connectivity: if the distance between two vertices is smaller than m_equalVertexThreshold, they are considered to be 'shared'
+ btScalar m_edgeDistanceThreshold; ///used to determine edge contacts: if the closest distance between a contact point and an edge is smaller than this distance threshold it is considered to "hit the edge"
+ btScalar m_maxEdgeAngleThreshold; //ignore edges that connect triangles at an angle larger than this m_maxEdgeAngleThreshold
+ btScalar m_zeroAreaThreshold; ///used to determine if a triangle is degenerate (length squared of cross product of 2 triangle edges < threshold)
+
btTriangleInfoMap()
{
m_convexEpsilon = 0.00f;
m_planarEpsilon = 0.0001f;
- m_equalVertexThreshold = btScalar(0.0001)*btScalar(0.0001);
+ m_equalVertexThreshold = btScalar(0.0001) * btScalar(0.0001);
m_edgeDistanceThreshold = btScalar(0.1);
- m_zeroAreaThreshold = btScalar(0.0001)*btScalar(0.0001);
+ m_zeroAreaThreshold = btScalar(0.0001) * btScalar(0.0001);
m_maxEdgeAngleThreshold = SIMD_2_PI;
}
virtual ~btTriangleInfoMap() {}
- virtual int calculateSerializeBufferSize() const;
+ virtual int calculateSerializeBufferSize() const;
///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-
- void deSerialize(struct btTriangleInfoMapData& data);
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+ void deSerialize(struct btTriangleInfoMapData& data);
};
+// clang-format off
+
///those fields have to be float and not btScalar for the serialization to work properly
struct btTriangleInfoData
{
@@ -114,86 +109,86 @@ struct btTriangleInfoMapData
char m_padding[4];
};
-SIMD_FORCE_INLINE int btTriangleInfoMap::calculateSerializeBufferSize() const
+// clang-format on
+
+SIMD_FORCE_INLINE int btTriangleInfoMap::calculateSerializeBufferSize() const
{
return sizeof(btTriangleInfoMapData);
}
///fills the dataBuffer and returns the struct name (and 0 on failure)
-SIMD_FORCE_INLINE const char* btTriangleInfoMap::serialize(void* dataBuffer, btSerializer* serializer) const
+SIMD_FORCE_INLINE const char* btTriangleInfoMap::serialize(void* dataBuffer, btSerializer* serializer) const
{
- btTriangleInfoMapData* tmapData = (btTriangleInfoMapData*) dataBuffer;
+ btTriangleInfoMapData* tmapData = (btTriangleInfoMapData*)dataBuffer;
tmapData->m_convexEpsilon = (float)m_convexEpsilon;
tmapData->m_planarEpsilon = (float)m_planarEpsilon;
- tmapData->m_equalVertexThreshold =(float) m_equalVertexThreshold;
+ tmapData->m_equalVertexThreshold = (float)m_equalVertexThreshold;
tmapData->m_edgeDistanceThreshold = (float)m_edgeDistanceThreshold;
tmapData->m_zeroAreaThreshold = (float)m_zeroAreaThreshold;
-
+
tmapData->m_hashTableSize = m_hashTable.size();
tmapData->m_hashTablePtr = tmapData->m_hashTableSize ? (int*)serializer->getUniquePointer((void*)&m_hashTable[0]) : 0;
if (tmapData->m_hashTablePtr)
- {
+ {
//serialize an int buffer
int sz = sizeof(int);
int numElem = tmapData->m_hashTableSize;
- btChunk* chunk = serializer->allocate(sz,numElem);
+ btChunk* chunk = serializer->allocate(sz, numElem);
int* memPtr = (int*)chunk->m_oldPtr;
- for (int i=0;i<numElem;i++,memPtr++)
+ for (int i = 0; i < numElem; i++, memPtr++)
{
*memPtr = m_hashTable[i];
}
- serializer->finalizeChunk(chunk,"int",BT_ARRAY_CODE,(void*)&m_hashTable[0]);
-
+ serializer->finalizeChunk(chunk, "int", BT_ARRAY_CODE, (void*)&m_hashTable[0]);
}
tmapData->m_nextSize = m_next.size();
- tmapData->m_nextPtr = tmapData->m_nextSize? (int*)serializer->getUniquePointer((void*)&m_next[0]): 0;
+ tmapData->m_nextPtr = tmapData->m_nextSize ? (int*)serializer->getUniquePointer((void*)&m_next[0]) : 0;
if (tmapData->m_nextPtr)
{
int sz = sizeof(int);
int numElem = tmapData->m_nextSize;
- btChunk* chunk = serializer->allocate(sz,numElem);
+ btChunk* chunk = serializer->allocate(sz, numElem);
int* memPtr = (int*)chunk->m_oldPtr;
- for (int i=0;i<numElem;i++,memPtr++)
+ for (int i = 0; i < numElem; i++, memPtr++)
{
*memPtr = m_next[i];
}
- serializer->finalizeChunk(chunk,"int",BT_ARRAY_CODE,(void*)&m_next[0]);
+ serializer->finalizeChunk(chunk, "int", BT_ARRAY_CODE, (void*)&m_next[0]);
}
-
+
tmapData->m_numValues = m_valueArray.size();
- tmapData->m_valueArrayPtr = tmapData->m_numValues ? (btTriangleInfoData*)serializer->getUniquePointer((void*)&m_valueArray[0]): 0;
+ tmapData->m_valueArrayPtr = tmapData->m_numValues ? (btTriangleInfoData*)serializer->getUniquePointer((void*)&m_valueArray[0]) : 0;
if (tmapData->m_valueArrayPtr)
{
int sz = sizeof(btTriangleInfoData);
int numElem = tmapData->m_numValues;
- btChunk* chunk = serializer->allocate(sz,numElem);
+ btChunk* chunk = serializer->allocate(sz, numElem);
btTriangleInfoData* memPtr = (btTriangleInfoData*)chunk->m_oldPtr;
- for (int i=0;i<numElem;i++,memPtr++)
+ for (int i = 0; i < numElem; i++, memPtr++)
{
memPtr->m_edgeV0V1Angle = (float)m_valueArray[i].m_edgeV0V1Angle;
memPtr->m_edgeV1V2Angle = (float)m_valueArray[i].m_edgeV1V2Angle;
memPtr->m_edgeV2V0Angle = (float)m_valueArray[i].m_edgeV2V0Angle;
memPtr->m_flags = m_valueArray[i].m_flags;
}
- serializer->finalizeChunk(chunk,"btTriangleInfoData",BT_ARRAY_CODE,(void*) &m_valueArray[0]);
+ serializer->finalizeChunk(chunk, "btTriangleInfoData", BT_ARRAY_CODE, (void*)&m_valueArray[0]);
}
-
+
tmapData->m_numKeys = m_keyArray.size();
tmapData->m_keyArrayPtr = tmapData->m_numKeys ? (int*)serializer->getUniquePointer((void*)&m_keyArray[0]) : 0;
if (tmapData->m_keyArrayPtr)
{
int sz = sizeof(int);
int numElem = tmapData->m_numValues;
- btChunk* chunk = serializer->allocate(sz,numElem);
+ btChunk* chunk = serializer->allocate(sz, numElem);
int* memPtr = (int*)chunk->m_oldPtr;
- for (int i=0;i<numElem;i++,memPtr++)
+ for (int i = 0; i < numElem; i++, memPtr++)
{
*memPtr = m_keyArray[i].getUid1();
}
- serializer->finalizeChunk(chunk,"int",BT_ARRAY_CODE,(void*) &m_keyArray[0]);
-
+ serializer->finalizeChunk(chunk, "int", BT_ARRAY_CODE, (void*)&m_keyArray[0]);
}
// Fill padding with zeros to appease msan.
@@ -205,44 +200,39 @@ SIMD_FORCE_INLINE const char* btTriangleInfoMap::serialize(void* dataBuffer, btS
return "btTriangleInfoMapData";
}
-
-
///fills the dataBuffer and returns the struct name (and 0 on failure)
-SIMD_FORCE_INLINE void btTriangleInfoMap::deSerialize(btTriangleInfoMapData& tmapData )
+SIMD_FORCE_INLINE void btTriangleInfoMap::deSerialize(btTriangleInfoMapData& tmapData)
{
-
-
m_convexEpsilon = tmapData.m_convexEpsilon;
m_planarEpsilon = tmapData.m_planarEpsilon;
m_equalVertexThreshold = tmapData.m_equalVertexThreshold;
m_edgeDistanceThreshold = tmapData.m_edgeDistanceThreshold;
m_zeroAreaThreshold = tmapData.m_zeroAreaThreshold;
m_hashTable.resize(tmapData.m_hashTableSize);
- int i =0;
- for (i=0;i<tmapData.m_hashTableSize;i++)
+ int i = 0;
+ for (i = 0; i < tmapData.m_hashTableSize; i++)
{
m_hashTable[i] = tmapData.m_hashTablePtr[i];
}
m_next.resize(tmapData.m_nextSize);
- for (i=0;i<tmapData.m_nextSize;i++)
+ for (i = 0; i < tmapData.m_nextSize; i++)
{
m_next[i] = tmapData.m_nextPtr[i];
}
m_valueArray.resize(tmapData.m_numValues);
- for (i=0;i<tmapData.m_numValues;i++)
+ for (i = 0; i < tmapData.m_numValues; i++)
{
m_valueArray[i].m_edgeV0V1Angle = tmapData.m_valueArrayPtr[i].m_edgeV0V1Angle;
m_valueArray[i].m_edgeV1V2Angle = tmapData.m_valueArrayPtr[i].m_edgeV1V2Angle;
m_valueArray[i].m_edgeV2V0Angle = tmapData.m_valueArrayPtr[i].m_edgeV2V0Angle;
m_valueArray[i].m_flags = tmapData.m_valueArrayPtr[i].m_flags;
}
-
- m_keyArray.resize(tmapData.m_numKeys,btHashInt(0));
- for (i=0;i<tmapData.m_numKeys;i++)
+
+ m_keyArray.resize(tmapData.m_numKeys, btHashInt(0));
+ for (i = 0; i < tmapData.m_numKeys; i++)
{
m_keyArray[i].setUid1(tmapData.m_keyArrayPtr[i]);
}
}
-
-#endif //_BT_TRIANGLE_INFO_MAP_H
+#endif //_BT_TRIANGLE_INFO_MAP_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleMesh.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleMesh.cpp
index e4de732093..abd8c22786 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleMesh.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleMesh.cpp
@@ -13,38 +13,36 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#include "btTriangleMesh.h"
-
-
-btTriangleMesh::btTriangleMesh (bool use32bitIndices,bool use4componentVertices)
-:m_use32bitIndices(use32bitIndices),
-m_use4componentVertices(use4componentVertices),
-m_weldingThreshold(0.0)
+btTriangleMesh::btTriangleMesh(bool use32bitIndices, bool use4componentVertices)
+ : m_use32bitIndices(use32bitIndices),
+ m_use4componentVertices(use4componentVertices),
+ m_weldingThreshold(0.0)
{
btIndexedMesh meshIndex;
meshIndex.m_numTriangles = 0;
meshIndex.m_numVertices = 0;
meshIndex.m_indexType = PHY_INTEGER;
meshIndex.m_triangleIndexBase = 0;
- meshIndex.m_triangleIndexStride = 3*sizeof(int);
+ meshIndex.m_triangleIndexStride = 3 * sizeof(int);
meshIndex.m_vertexBase = 0;
meshIndex.m_vertexStride = sizeof(btVector3);
m_indexedMeshes.push_back(meshIndex);
if (m_use32bitIndices)
{
- m_indexedMeshes[0].m_numTriangles = m_32bitIndices.size()/3;
+ m_indexedMeshes[0].m_numTriangles = m_32bitIndices.size() / 3;
m_indexedMeshes[0].m_triangleIndexBase = 0;
m_indexedMeshes[0].m_indexType = PHY_INTEGER;
- m_indexedMeshes[0].m_triangleIndexStride = 3*sizeof(int);
- } else
+ m_indexedMeshes[0].m_triangleIndexStride = 3 * sizeof(int);
+ }
+ else
{
- m_indexedMeshes[0].m_numTriangles = m_16bitIndices.size()/3;
+ m_indexedMeshes[0].m_numTriangles = m_16bitIndices.size() / 3;
m_indexedMeshes[0].m_triangleIndexBase = 0;
m_indexedMeshes[0].m_indexType = PHY_SHORT;
- m_indexedMeshes[0].m_triangleIndexStride = 3*sizeof(short int);
+ m_indexedMeshes[0].m_triangleIndexStride = 3 * sizeof(short int);
}
if (m_use4componentVertices)
@@ -52,48 +50,48 @@ m_weldingThreshold(0.0)
m_indexedMeshes[0].m_numVertices = m_4componentVertices.size();
m_indexedMeshes[0].m_vertexBase = 0;
m_indexedMeshes[0].m_vertexStride = sizeof(btVector3);
- } else
+ }
+ else
{
- m_indexedMeshes[0].m_numVertices = m_3componentVertices.size()/3;
+ m_indexedMeshes[0].m_numVertices = m_3componentVertices.size() / 3;
m_indexedMeshes[0].m_vertexBase = 0;
- m_indexedMeshes[0].m_vertexStride = 3*sizeof(btScalar);
+ m_indexedMeshes[0].m_vertexStride = 3 * sizeof(btScalar);
}
-
-
}
-void btTriangleMesh::addIndex(int index)
+void btTriangleMesh::addIndex(int index)
{
if (m_use32bitIndices)
{
m_32bitIndices.push_back(index);
- m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*) &m_32bitIndices[0];
- } else
+ m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*)&m_32bitIndices[0];
+ }
+ else
{
m_16bitIndices.push_back(index);
- m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*) &m_16bitIndices[0];
+ m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*)&m_16bitIndices[0];
}
}
-void btTriangleMesh::addTriangleIndices(int index1, int index2, int index3 )
+void btTriangleMesh::addTriangleIndices(int index1, int index2, int index3)
{
m_indexedMeshes[0].m_numTriangles++;
- addIndex( index1 );
- addIndex( index2 );
- addIndex( index3 );
+ addIndex(index1);
+ addIndex(index2);
+ addIndex(index3);
}
-int btTriangleMesh::findOrAddVertex(const btVector3& vertex, bool removeDuplicateVertices)
+int btTriangleMesh::findOrAddVertex(const btVector3& vertex, bool removeDuplicateVertices)
{
//return index of new/existing vertex
///@todo: could use acceleration structure for this
if (m_use4componentVertices)
{
if (removeDuplicateVertices)
+ {
+ for (int i = 0; i < m_4componentVertices.size(); i++)
{
- for (int i=0;i< m_4componentVertices.size();i++)
- {
- if ((m_4componentVertices[i]-vertex).length2() <= m_weldingThreshold)
+ if ((m_4componentVertices[i] - vertex).length2() <= m_weldingThreshold)
{
return i;
}
@@ -103,19 +101,18 @@ int btTriangleMesh::findOrAddVertex(const btVector3& vertex, bool removeDuplicat
m_4componentVertices.push_back(vertex);
m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_4componentVertices[0];
- return m_4componentVertices.size()-1;
-
- } else
+ return m_4componentVertices.size() - 1;
+ }
+ else
{
-
if (removeDuplicateVertices)
{
- for (int i=0;i< m_3componentVertices.size();i+=3)
+ for (int i = 0; i < m_3componentVertices.size(); i += 3)
{
- btVector3 vtx(m_3componentVertices[i],m_3componentVertices[i+1],m_3componentVertices[i+2]);
- if ((vtx-vertex).length2() <= m_weldingThreshold)
+ btVector3 vtx(m_3componentVertices[i], m_3componentVertices[i + 1], m_3componentVertices[i + 2]);
+ if ((vtx - vertex).length2() <= m_weldingThreshold)
{
- return i/3;
+ return i / 3;
}
}
}
@@ -124,17 +121,16 @@ int btTriangleMesh::findOrAddVertex(const btVector3& vertex, bool removeDuplicat
m_3componentVertices.push_back(vertex.getZ());
m_indexedMeshes[0].m_numVertices++;
m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_3componentVertices[0];
- return (m_3componentVertices.size()/3)-1;
+ return (m_3componentVertices.size() / 3) - 1;
}
-
}
-
-void btTriangleMesh::addTriangle(const btVector3& vertex0,const btVector3& vertex1,const btVector3& vertex2,bool removeDuplicateVertices)
+
+void btTriangleMesh::addTriangle(const btVector3& vertex0, const btVector3& vertex1, const btVector3& vertex2, bool removeDuplicateVertices)
{
m_indexedMeshes[0].m_numTriangles++;
- addIndex(findOrAddVertex(vertex0,removeDuplicateVertices));
- addIndex(findOrAddVertex(vertex1,removeDuplicateVertices));
- addIndex(findOrAddVertex(vertex2,removeDuplicateVertices));
+ addIndex(findOrAddVertex(vertex0, removeDuplicateVertices));
+ addIndex(findOrAddVertex(vertex1, removeDuplicateVertices));
+ addIndex(findOrAddVertex(vertex2, removeDuplicateVertices));
}
int btTriangleMesh::getNumTriangles() const
@@ -151,7 +147,8 @@ void btTriangleMesh::preallocateVertices(int numverts)
if (m_use4componentVertices)
{
m_4componentVertices.reserve(numverts);
- } else
+ }
+ else
{
m_3componentVertices.reserve(numverts);
}
@@ -162,7 +159,8 @@ void btTriangleMesh::preallocateIndices(int numindices)
if (m_use32bitIndices)
{
m_32bitIndices.reserve(numindices);
- } else
+ }
+ else
{
m_16bitIndices.reserve(numindices);
}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleMesh.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleMesh.h
index ac4afa7f6b..a8a362355c 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleMesh.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleMesh.h
@@ -26,47 +26,44 @@ subject to the following restrictions:
///Performance of btTriangleMesh and btTriangleIndexVertexArray used in a btBvhTriangleMeshShape is the same.
class btTriangleMesh : public btTriangleIndexVertexArray
{
- btAlignedObjectArray<btVector3> m_4componentVertices;
- btAlignedObjectArray<btScalar> m_3componentVertices;
+ btAlignedObjectArray<btVector3> m_4componentVertices;
+ btAlignedObjectArray<btScalar> m_3componentVertices;
- btAlignedObjectArray<unsigned int> m_32bitIndices;
- btAlignedObjectArray<unsigned short int> m_16bitIndices;
- bool m_use32bitIndices;
- bool m_use4componentVertices;
-
+ btAlignedObjectArray<unsigned int> m_32bitIndices;
+ btAlignedObjectArray<unsigned short int> m_16bitIndices;
+ bool m_use32bitIndices;
+ bool m_use4componentVertices;
- public:
- btScalar m_weldingThreshold;
+public:
+ btScalar m_weldingThreshold;
- btTriangleMesh (bool use32bitIndices=true,bool use4componentVertices=true);
+ btTriangleMesh(bool use32bitIndices = true, bool use4componentVertices = true);
- bool getUse32bitIndices() const
- {
- return m_use32bitIndices;
- }
+ bool getUse32bitIndices() const
+ {
+ return m_use32bitIndices;
+ }
- bool getUse4componentVertices() const
- {
- return m_use4componentVertices;
- }
- ///By default addTriangle won't search for duplicate vertices, because the search is very slow for large triangle meshes.
- ///In general it is better to directly use btTriangleIndexVertexArray instead.
- void addTriangle(const btVector3& vertex0,const btVector3& vertex1,const btVector3& vertex2, bool removeDuplicateVertices=false);
+ bool getUse4componentVertices() const
+ {
+ return m_use4componentVertices;
+ }
+ ///By default addTriangle won't search for duplicate vertices, because the search is very slow for large triangle meshes.
+ ///In general it is better to directly use btTriangleIndexVertexArray instead.
+ void addTriangle(const btVector3& vertex0, const btVector3& vertex1, const btVector3& vertex2, bool removeDuplicateVertices = false);
- ///Add a triangle using its indices. Make sure the indices are pointing within the vertices array, so add the vertices first (and to be sure, avoid removal of duplicate vertices)
- void addTriangleIndices(int index1, int index2, int index3 );
-
- int getNumTriangles() const;
+ ///Add a triangle using its indices. Make sure the indices are pointing within the vertices array, so add the vertices first (and to be sure, avoid removal of duplicate vertices)
+ void addTriangleIndices(int index1, int index2, int index3);
- virtual void preallocateVertices(int numverts);
- virtual void preallocateIndices(int numindices);
+ int getNumTriangles() const;
- ///findOrAddVertex is an internal method, use addTriangle instead
- int findOrAddVertex(const btVector3& vertex, bool removeDuplicateVertices);
- ///addIndex is an internal method, use addTriangle instead
- void addIndex(int index);
-
-};
+ virtual void preallocateVertices(int numverts);
+ virtual void preallocateIndices(int numindices);
-#endif //BT_TRIANGLE_MESH_H
+ ///findOrAddVertex is an internal method, use addTriangle instead
+ int findOrAddVertex(const btVector3& vertex, bool removeDuplicateVertices);
+ ///addIndex is an internal method, use addTriangle instead
+ void addIndex(int index);
+};
+#endif //BT_TRIANGLE_MESH_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp
index 0e17951405..aec239063c 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp
@@ -20,12 +20,11 @@ subject to the following restrictions:
#include "LinearMath/btAabbUtil2.h"
#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
-
btTriangleMeshShape::btTriangleMeshShape(btStridingMeshInterface* meshInterface)
-: btConcaveShape (), m_meshInterface(meshInterface)
+ : btConcaveShape(), m_meshInterface(meshInterface)
{
m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;
- if(meshInterface->hasPremadeAabb())
+ if (meshInterface->hasPremadeAabb())
{
meshInterface->getPremadeAabb(&m_localAabbMin, &m_localAabbMax);
}
@@ -35,69 +34,60 @@ btTriangleMeshShape::btTriangleMeshShape(btStridingMeshInterface* meshInterface)
}
}
-
btTriangleMeshShape::~btTriangleMeshShape()
{
-
}
-
-
-
-void btTriangleMeshShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const
+void btTriangleMeshShape::getAabb(const btTransform& trans, btVector3& aabbMin, btVector3& aabbMax) const
{
+ btVector3 localHalfExtents = btScalar(0.5) * (m_localAabbMax - m_localAabbMin);
+ localHalfExtents += btVector3(getMargin(), getMargin(), getMargin());
+ btVector3 localCenter = btScalar(0.5) * (m_localAabbMax + m_localAabbMin);
- btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin);
- localHalfExtents += btVector3(getMargin(),getMargin(),getMargin());
- btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin);
-
- btMatrix3x3 abs_b = trans.getBasis().absolute();
+ btMatrix3x3 abs_b = trans.getBasis().absolute();
btVector3 center = trans(localCenter);
- btVector3 extent = localHalfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
+ btVector3 extent = localHalfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
aabbMin = center - extent;
aabbMax = center + extent;
}
-void btTriangleMeshShape::recalcLocalAabb()
+void btTriangleMeshShape::recalcLocalAabb()
{
- for (int i=0;i<3;i++)
+ for (int i = 0; i < 3; i++)
{
- btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.));
+ btVector3 vec(btScalar(0.), btScalar(0.), btScalar(0.));
vec[i] = btScalar(1.);
btVector3 tmp = localGetSupportingVertex(vec);
- m_localAabbMax[i] = tmp[i]+m_collisionMargin;
+ m_localAabbMax[i] = tmp[i] + m_collisionMargin;
vec[i] = btScalar(-1.);
tmp = localGetSupportingVertex(vec);
- m_localAabbMin[i] = tmp[i]-m_collisionMargin;
+ m_localAabbMin[i] = tmp[i] - m_collisionMargin;
}
}
-
-
class SupportVertexCallback : public btTriangleCallback
{
-
btVector3 m_supportVertexLocal;
-public:
- btTransform m_worldTrans;
+public:
+ btTransform m_worldTrans;
btScalar m_maxDot;
btVector3 m_supportVecLocal;
- SupportVertexCallback(const btVector3& supportVecWorld,const btTransform& trans)
- : m_supportVertexLocal(btScalar(0.),btScalar(0.),btScalar(0.)), m_worldTrans(trans) ,m_maxDot(btScalar(-BT_LARGE_FLOAT))
-
+ SupportVertexCallback(const btVector3& supportVecWorld, const btTransform& trans)
+ : m_supportVertexLocal(btScalar(0.), btScalar(0.), btScalar(0.)), m_worldTrans(trans), m_maxDot(btScalar(-BT_LARGE_FLOAT))
+
{
m_supportVecLocal = supportVecWorld * m_worldTrans.getBasis();
}
- virtual void processTriangle( btVector3* triangle,int partId, int triangleIndex)
+ virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
{
(void)partId;
(void)triangleIndex;
- for (int i=0;i<3;i++)
+ for (int i = 0; i < 3; i++)
{
btScalar dot = m_supportVecLocal.dot(triangle[i]);
if (dot > m_maxDot)
@@ -113,14 +103,12 @@ public:
return m_worldTrans(m_supportVertexLocal);
}
- btVector3 GetSupportVertexLocal()
+ btVector3 GetSupportVertexLocal()
{
return m_supportVertexLocal;
}
-
};
-
void btTriangleMeshShape::setLocalScaling(const btVector3& scaling)
{
m_meshInterface->setScaling(scaling);
@@ -132,60 +120,46 @@ const btVector3& btTriangleMeshShape::getLocalScaling() const
return m_meshInterface->getScaling();
}
-
-
-
-
-
//#define DEBUG_TRIANGLE_MESH
-
-
-void btTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
+void btTriangleMeshShape::processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
{
- struct FilteredCallback : public btInternalTriangleIndexCallback
+ struct FilteredCallback : public btInternalTriangleIndexCallback
{
btTriangleCallback* m_callback;
btVector3 m_aabbMin;
btVector3 m_aabbMax;
- FilteredCallback(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax)
- :m_callback(callback),
- m_aabbMin(aabbMin),
- m_aabbMax(aabbMax)
+ FilteredCallback(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax)
+ : m_callback(callback),
+ m_aabbMin(aabbMin),
+ m_aabbMax(aabbMax)
{
}
- virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex)
+ virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
{
- if (TestTriangleAgainstAabb2(&triangle[0],m_aabbMin,m_aabbMax))
+ if (TestTriangleAgainstAabb2(&triangle[0], m_aabbMin, m_aabbMax))
{
//check aabb in triangle-space, before doing this
- m_callback->processTriangle(triangle,partId,triangleIndex);
+ m_callback->processTriangle(triangle, partId, triangleIndex);
}
-
}
-
};
- FilteredCallback filterCallback(callback,aabbMin,aabbMax);
+ FilteredCallback filterCallback(callback, aabbMin, aabbMax);
- m_meshInterface->InternalProcessAllTriangles(&filterCallback,aabbMin,aabbMax);
+ m_meshInterface->InternalProcessAllTriangles(&filterCallback, aabbMin, aabbMax);
}
-
-
-
-
-void btTriangleMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+void btTriangleMeshShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
{
(void)mass;
//moving concave objects not supported
btAssert(0);
- inertia.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+ inertia.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
}
-
btVector3 btTriangleMeshShape::localGetSupportingVertex(const btVector3& vec) const
{
btVector3 supportVertex;
@@ -193,15 +167,13 @@ btVector3 btTriangleMeshShape::localGetSupportingVertex(const btVector3& vec) co
btTransform ident;
ident.setIdentity();
- SupportVertexCallback supportCallback(vec,ident);
+ SupportVertexCallback supportCallback(vec, ident);
+
+ btVector3 aabbMax(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
+
+ processAllTriangles(&supportCallback, -aabbMax, aabbMax);
- btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
-
- processAllTriangles(&supportCallback,-aabbMax,aabbMax);
-
supportVertex = supportCallback.GetSupportVertexLocal();
return supportVertex;
}
-
-
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleMeshShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleMeshShape.h
index 453e58005a..4a70e283fa 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleMeshShape.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleMeshShape.h
@@ -19,18 +19,18 @@ subject to the following restrictions:
#include "btConcaveShape.h"
#include "btStridingMeshInterface.h"
-
///The btTriangleMeshShape is an internal concave triangle mesh interface. Don't use this class directly, use btBvhTriangleMeshShape instead.
-ATTRIBUTE_ALIGNED16(class) btTriangleMeshShape : public btConcaveShape
+ATTRIBUTE_ALIGNED16(class)
+btTriangleMeshShape : public btConcaveShape
{
protected:
- btVector3 m_localAabbMin;
- btVector3 m_localAabbMax;
+ btVector3 m_localAabbMin;
+ btVector3 m_localAabbMax;
btStridingMeshInterface* m_meshInterface;
///btTriangleMeshShape constructor has been disabled/protected, so that users will not mistakenly use this class.
///Don't use btTriangleMeshShape but use btBvhTriangleMeshShape instead!
- btTriangleMeshShape(btStridingMeshInterface* meshInterface);
+ btTriangleMeshShape(btStridingMeshInterface * meshInterface);
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
@@ -39,23 +39,23 @@ public:
virtual btVector3 localGetSupportingVertex(const btVector3& vec) const;
- virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const
{
btAssert(0);
return localGetSupportingVertex(vec);
}
- void recalcLocalAabb();
+ void recalcLocalAabb();
- virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+ virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
- virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+ virtual void processAllTriangles(btTriangleCallback * callback, const btVector3& aabbMin, const btVector3& aabbMax) const;
- virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+ virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
- virtual void setLocalScaling(const btVector3& scaling);
+ virtual void setLocalScaling(const btVector3& scaling);
virtual const btVector3& getLocalScaling() const;
-
+
btStridingMeshInterface* getMeshInterface()
{
return m_meshInterface;
@@ -75,16 +75,8 @@ public:
return m_localAabbMax;
}
-
-
//debugging
- virtual const char* getName()const {return "TRIANGLEMESH";}
-
-
-
+ virtual const char* getName() const { return "TRIANGLEMESH"; }
};
-
-
-
-#endif //BT_TRIANGLE_MESH_SHAPE_H
+#endif //BT_TRIANGLE_MESH_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleShape.h
index a8a80f82fe..190cbdae69 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleShape.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleShape.h
@@ -19,15 +19,13 @@ subject to the following restrictions:
#include "btConvexShape.h"
#include "btBoxShape.h"
-ATTRIBUTE_ALIGNED16(class) btTriangleShape : public btPolyhedralConvexShape
+ATTRIBUTE_ALIGNED16(class)
+btTriangleShape : public btPolyhedralConvexShape
{
-
-
public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
-BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btVector3 m_vertices1[3];
+ btVector3 m_vertices1[3];
virtual int getNumVertices() const
{
@@ -43,7 +41,7 @@ BT_DECLARE_ALIGNED_ALLOCATOR();
{
return m_vertices1[index];
}
- virtual void getVertex(int index,btVector3& vert) const
+ virtual void getVertex(int index, btVector3& vert) const
{
vert = m_vertices1[index];
}
@@ -52,83 +50,79 @@ BT_DECLARE_ALIGNED_ALLOCATOR();
{
return 3;
}
-
- virtual void getEdge(int i,btVector3& pa,btVector3& pb) const
+
+ virtual void getEdge(int i, btVector3& pa, btVector3& pb) const
{
- getVertex(i,pa);
- getVertex((i+1)%3,pb);
+ getVertex(i, pa);
+ getVertex((i + 1) % 3, pb);
}
-
- virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax)const
+ virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
{
-// btAssert(0);
- getAabbSlow(t,aabbMin,aabbMax);
+ // btAssert(0);
+ getAabbSlow(t, aabbMin, aabbMax);
}
- btVector3 localGetSupportingVertexWithoutMargin(const btVector3& dir)const
+ btVector3 localGetSupportingVertexWithoutMargin(const btVector3& dir) const
{
- btVector3 dots = dir.dot3(m_vertices1[0], m_vertices1[1], m_vertices1[2]);
- return m_vertices1[dots.maxAxis()];
-
+ btVector3 dots = dir.dot3(m_vertices1[0], m_vertices1[1], m_vertices1[2]);
+ return m_vertices1[dots.maxAxis()];
}
- virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
{
- for (int i=0;i<numVectors;i++)
+ for (int i = 0; i < numVectors; i++)
{
const btVector3& dir = vectors[i];
- btVector3 dots = dir.dot3(m_vertices1[0], m_vertices1[1], m_vertices1[2]);
- supportVerticesOut[i] = m_vertices1[dots.maxAxis()];
+ btVector3 dots = dir.dot3(m_vertices1[0], m_vertices1[1], m_vertices1[2]);
+ supportVerticesOut[i] = m_vertices1[dots.maxAxis()];
}
-
}
- btTriangleShape() : btPolyhedralConvexShape ()
- {
+ btTriangleShape() : btPolyhedralConvexShape()
+ {
m_shapeType = TRIANGLE_SHAPE_PROXYTYPE;
}
- btTriangleShape(const btVector3& p0,const btVector3& p1,const btVector3& p2) : btPolyhedralConvexShape ()
- {
+ btTriangleShape(const btVector3& p0, const btVector3& p1, const btVector3& p2) : btPolyhedralConvexShape()
+ {
m_shapeType = TRIANGLE_SHAPE_PROXYTYPE;
- m_vertices1[0] = p0;
- m_vertices1[1] = p1;
- m_vertices1[2] = p2;
- }
-
+ m_vertices1[0] = p0;
+ m_vertices1[1] = p1;
+ m_vertices1[2] = p2;
+ }
- virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i) const
+ virtual void getPlane(btVector3 & planeNormal, btVector3 & planeSupport, int i) const
{
- getPlaneEquation(i,planeNormal,planeSupport);
+ getPlaneEquation(i, planeNormal, planeSupport);
}
- virtual int getNumPlanes() const
+ virtual int getNumPlanes() const
{
return 1;
}
- void calcNormal(btVector3& normal) const
+ void calcNormal(btVector3 & normal) const
{
- normal = (m_vertices1[1]-m_vertices1[0]).cross(m_vertices1[2]-m_vertices1[0]);
+ normal = (m_vertices1[1] - m_vertices1[0]).cross(m_vertices1[2] - m_vertices1[0]);
normal.normalize();
}
- virtual void getPlaneEquation(int i, btVector3& planeNormal,btVector3& planeSupport) const
+ virtual void getPlaneEquation(int i, btVector3& planeNormal, btVector3& planeSupport) const
{
(void)i;
calcNormal(planeNormal);
planeSupport = m_vertices1[0];
}
- virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const
+ virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const
{
(void)mass;
btAssert(0);
- inertia.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+ inertia.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
}
- virtual bool isInside(const btVector3& pt,btScalar tolerance) const
+ virtual bool isInside(const btVector3& pt, btScalar tolerance) const
{
btVector3 normal;
calcNormal(normal);
@@ -140,45 +134,42 @@ BT_DECLARE_ALIGNED_ALLOCATOR();
{
//inside check on edge-planes
int i;
- for (i=0;i<3;i++)
+ for (i = 0; i < 3; i++)
{
- btVector3 pa,pb;
- getEdge(i,pa,pb);
- btVector3 edge = pb-pa;
+ btVector3 pa, pb;
+ getEdge(i, pa, pb);
+ btVector3 edge = pb - pa;
btVector3 edgeNormal = edge.cross(normal);
edgeNormal.normalize();
- btScalar dist = pt.dot( edgeNormal);
+ btScalar dist = pt.dot(edgeNormal);
btScalar edgeConst = pa.dot(edgeNormal);
dist -= edgeConst;
if (dist < -tolerance)
return false;
}
-
+
return true;
}
return false;
}
- //debugging
- virtual const char* getName()const
- {
- return "Triangle";
- }
-
- virtual int getNumPreferredPenetrationDirections() const
- {
- return 2;
- }
-
- virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
- {
- calcNormal(penetrationVector);
- if (index)
- penetrationVector *= btScalar(-1.);
- }
+ //debugging
+ virtual const char* getName() const
+ {
+ return "Triangle";
+ }
+ virtual int getNumPreferredPenetrationDirections() const
+ {
+ return 2;
+ }
+ virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
+ {
+ calcNormal(penetrationVector);
+ if (index)
+ penetrationVector *= btScalar(-1.);
+ }
};
-#endif //BT_OBB_TRIANGLE_MINKOWSKI_H
-
+#endif //BT_OBB_TRIANGLE_MINKOWSKI_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btUniformScalingShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btUniformScalingShape.cpp
index b148bbd99a..ed3cd2d259 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btUniformScalingShape.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btUniformScalingShape.cpp
@@ -15,122 +15,112 @@ subject to the following restrictions:
#include "btUniformScalingShape.h"
-btUniformScalingShape::btUniformScalingShape( btConvexShape* convexChildShape,btScalar uniformScalingFactor):
-btConvexShape (), m_childConvexShape(convexChildShape),
-m_uniformScalingFactor(uniformScalingFactor)
+btUniformScalingShape::btUniformScalingShape(btConvexShape* convexChildShape, btScalar uniformScalingFactor) : btConvexShape(), m_childConvexShape(convexChildShape), m_uniformScalingFactor(uniformScalingFactor)
{
m_shapeType = UNIFORM_SCALING_SHAPE_PROXYTYPE;
}
-
+
btUniformScalingShape::~btUniformScalingShape()
{
}
-
-btVector3 btUniformScalingShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+btVector3 btUniformScalingShape::localGetSupportingVertexWithoutMargin(const btVector3& vec) const
{
btVector3 tmpVertex;
tmpVertex = m_childConvexShape->localGetSupportingVertexWithoutMargin(vec);
- return tmpVertex*m_uniformScalingFactor;
+ return tmpVertex * m_uniformScalingFactor;
}
-void btUniformScalingShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+void btUniformScalingShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
{
- m_childConvexShape->batchedUnitVectorGetSupportingVertexWithoutMargin(vectors,supportVerticesOut,numVectors);
+ m_childConvexShape->batchedUnitVectorGetSupportingVertexWithoutMargin(vectors, supportVerticesOut, numVectors);
int i;
- for (i=0;i<numVectors;i++)
+ for (i = 0; i < numVectors; i++)
{
supportVerticesOut[i] = supportVerticesOut[i] * m_uniformScalingFactor;
}
}
-
-btVector3 btUniformScalingShape::localGetSupportingVertex(const btVector3& vec)const
+btVector3 btUniformScalingShape::localGetSupportingVertex(const btVector3& vec) const
{
btVector3 tmpVertex;
tmpVertex = m_childConvexShape->localGetSupportingVertex(vec);
- return tmpVertex*m_uniformScalingFactor;
+ return tmpVertex * m_uniformScalingFactor;
}
-
-void btUniformScalingShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+void btUniformScalingShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
{
-
///this linear upscaling is not realistic, but we don't deal with large mass ratios...
btVector3 tmpInertia;
- m_childConvexShape->calculateLocalInertia(mass,tmpInertia);
+ m_childConvexShape->calculateLocalInertia(mass, tmpInertia);
inertia = tmpInertia * m_uniformScalingFactor;
}
-
- ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
-void btUniformScalingShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const
+///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+void btUniformScalingShape::getAabb(const btTransform& trans, btVector3& aabbMin, btVector3& aabbMax) const
{
- getAabbSlow(trans,aabbMin,aabbMax);
-
+ getAabbSlow(trans, aabbMin, aabbMax);
}
-void btUniformScalingShape::getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+void btUniformScalingShape::getAabbSlow(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
{
#if 1
btVector3 _directions[] =
- {
- btVector3( 1., 0., 0.),
- btVector3( 0., 1., 0.),
- btVector3( 0., 0., 1.),
- btVector3( -1., 0., 0.),
- btVector3( 0., -1., 0.),
- btVector3( 0., 0., -1.)
- };
-
+ {
+ btVector3(1., 0., 0.),
+ btVector3(0., 1., 0.),
+ btVector3(0., 0., 1.),
+ btVector3(-1., 0., 0.),
+ btVector3(0., -1., 0.),
+ btVector3(0., 0., -1.)};
+
btVector3 _supporting[] =
+ {
+ btVector3(0., 0., 0.),
+ btVector3(0., 0., 0.),
+ btVector3(0., 0., 0.),
+ btVector3(0., 0., 0.),
+ btVector3(0., 0., 0.),
+ btVector3(0., 0., 0.)};
+
+ for (int i = 0; i < 6; i++)
{
- btVector3( 0., 0., 0.),
- btVector3( 0., 0., 0.),
- btVector3( 0., 0., 0.),
- btVector3( 0., 0., 0.),
- btVector3( 0., 0., 0.),
- btVector3( 0., 0., 0.)
- };
-
- for (int i=0;i<6;i++)
- {
- _directions[i] = _directions[i]*t.getBasis();
+ _directions[i] = _directions[i] * t.getBasis();
}
-
+
batchedUnitVectorGetSupportingVertexWithoutMargin(_directions, _supporting, 6);
-
- btVector3 aabbMin1(0,0,0),aabbMax1(0,0,0);
- for ( int i = 0; i < 3; ++i )
+ btVector3 aabbMin1(0, 0, 0), aabbMax1(0, 0, 0);
+
+ for (int i = 0; i < 3; ++i)
{
aabbMax1[i] = t(_supporting[i])[i];
aabbMin1[i] = t(_supporting[i + 3])[i];
}
- btVector3 marginVec(getMargin(),getMargin(),getMargin());
- aabbMin = aabbMin1-marginVec;
- aabbMax = aabbMax1+marginVec;
-
+ btVector3 marginVec(getMargin(), getMargin(), getMargin());
+ aabbMin = aabbMin1 - marginVec;
+ aabbMax = aabbMax1 + marginVec;
+
#else
btScalar margin = getMargin();
- for (int i=0;i<3;i++)
+ for (int i = 0; i < 3; i++)
{
- btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.));
+ btVector3 vec(btScalar(0.), btScalar(0.), btScalar(0.));
vec[i] = btScalar(1.);
- btVector3 sv = localGetSupportingVertex(vec*t.getBasis());
+ btVector3 sv = localGetSupportingVertex(vec * t.getBasis());
btVector3 tmp = t(sv);
- aabbMax[i] = tmp[i]+margin;
+ aabbMax[i] = tmp[i] + margin;
vec[i] = btScalar(-1.);
- sv = localGetSupportingVertex(vec*t.getBasis());
+ sv = localGetSupportingVertex(vec * t.getBasis());
tmp = t(sv);
- aabbMin[i] = tmp[i]-margin;
+ aabbMin[i] = tmp[i] - margin;
}
#endif
}
-void btUniformScalingShape::setLocalScaling(const btVector3& scaling)
+void btUniformScalingShape::setLocalScaling(const btVector3& scaling)
{
m_childConvexShape->setLocalScaling(scaling);
}
@@ -140,21 +130,21 @@ const btVector3& btUniformScalingShape::getLocalScaling() const
return m_childConvexShape->getLocalScaling();
}
-void btUniformScalingShape::setMargin(btScalar margin)
+void btUniformScalingShape::setMargin(btScalar margin)
{
m_childConvexShape->setMargin(margin);
}
-btScalar btUniformScalingShape::getMargin() const
+btScalar btUniformScalingShape::getMargin() const
{
return m_childConvexShape->getMargin() * m_uniformScalingFactor;
}
-int btUniformScalingShape::getNumPreferredPenetrationDirections() const
+int btUniformScalingShape::getNumPreferredPenetrationDirections() const
{
return m_childConvexShape->getNumPreferredPenetrationDirections();
}
-
-void btUniformScalingShape::getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
+
+void btUniformScalingShape::getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
{
- m_childConvexShape->getPreferredPenetrationDirection(index,penetrationVector);
+ m_childConvexShape->getPreferredPenetrationDirection(index, penetrationVector);
}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btUniformScalingShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btUniformScalingShape.h
index a10f58d242..4dfe34efbd 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btUniformScalingShape.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btUniformScalingShape.h
@@ -17,73 +17,68 @@ subject to the following restrictions:
#define BT_UNIFORM_SCALING_SHAPE_H
#include "btConvexShape.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
///The btUniformScalingShape allows to re-use uniform scaled instances of btConvexShape in a memory efficient way.
///Istead of using btUniformScalingShape, it is better to use the non-uniform setLocalScaling method on convex shapes that implement it.
-ATTRIBUTE_ALIGNED16(class) btUniformScalingShape : public btConvexShape
+ATTRIBUTE_ALIGNED16(class)
+btUniformScalingShape : public btConvexShape
{
- btConvexShape* m_childConvexShape;
+ btConvexShape* m_childConvexShape;
- btScalar m_uniformScalingFactor;
-
- public:
-
+ btScalar m_uniformScalingFactor;
+
+public:
BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btUniformScalingShape( btConvexShape* convexChildShape, btScalar uniformScalingFactor);
-
+
+ btUniformScalingShape(btConvexShape * convexChildShape, btScalar uniformScalingFactor);
+
virtual ~btUniformScalingShape();
-
- virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
- virtual btVector3 localGetSupportingVertex(const btVector3& vec)const;
+ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
+
+ virtual btVector3 localGetSupportingVertex(const btVector3& vec) const;
- virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const;
- virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+ virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
- btScalar getUniformScalingFactor() const
+ btScalar getUniformScalingFactor() const
{
return m_uniformScalingFactor;
}
- btConvexShape* getChildShape()
+ btConvexShape* getChildShape()
{
return m_childConvexShape;
}
- const btConvexShape* getChildShape() const
+ const btConvexShape* getChildShape() const
{
return m_childConvexShape;
}
- virtual const char* getName()const
+ virtual const char* getName() const
{
return "UniformScalingShape";
}
-
-
///////////////////////////
-
///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
- void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
-
- virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+ void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
- virtual void setLocalScaling(const btVector3& scaling) ;
- virtual const btVector3& getLocalScaling() const ;
+ virtual void getAabbSlow(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
- virtual void setMargin(btScalar margin);
- virtual btScalar getMargin() const;
+ virtual void setLocalScaling(const btVector3& scaling);
+ virtual const btVector3& getLocalScaling() const;
- virtual int getNumPreferredPenetrationDirections() const;
-
- virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const;
+ virtual void setMargin(btScalar margin);
+ virtual btScalar getMargin() const;
+ virtual int getNumPreferredPenetrationDirections() const;
+ virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const;
};
-#endif //BT_UNIFORM_SCALING_SHAPE_H
+#endif //BT_UNIFORM_SCALING_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btBoxCollision.h b/thirdparty/bullet/BulletCollision/Gimpact/btBoxCollision.h
index 0a0357e5a8..182835c3b4 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/btBoxCollision.h
+++ b/thirdparty/bullet/BulletCollision/Gimpact/btBoxCollision.h
@@ -26,27 +26,21 @@ subject to the following restrictions:
#include "LinearMath/btTransform.h"
-
///Swap numbers
-#define BT_SWAP_NUMBERS(a,b){ \
- a = a+b; \
- b = a-b; \
- a = a-b; \
-}\
-
-
-#define BT_MAX(a,b) (a<b?b:a)
-#define BT_MIN(a,b) (a>b?b:a)
-
-#define BT_GREATER(x, y) btFabs(x) > (y)
-
-#define BT_MAX3(a,b,c) BT_MAX(a,BT_MAX(b,c))
-#define BT_MIN3(a,b,c) BT_MIN(a,BT_MIN(b,c))
-
-
+#define BT_SWAP_NUMBERS(a, b) \
+ { \
+ a = a + b; \
+ b = a - b; \
+ a = a - b; \
+ }
+#define BT_MAX(a, b) (a < b ? b : a)
+#define BT_MIN(a, b) (a > b ? b : a)
+#define BT_GREATER(x, y) btFabs(x) > (y)
+#define BT_MAX3(a, b, c) BT_MAX(a, BT_MAX(b, c))
+#define BT_MIN3(a, b, c) BT_MIN(a, BT_MIN(b, c))
enum eBT_PLANE_INTERSECTION_TYPE
{
@@ -115,152 +109,144 @@ enum eBT_PLANE_INTERSECTION_TYPE
// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,1,0,0,1);
//}
+#define TEST_CROSS_EDGE_BOX_MCR(edge, absolute_edge, pointa, pointb, _extend, i_dir_0, i_dir_1, i_comp_0, i_comp_1) \
+ { \
+ const btScalar dir0 = -edge[i_dir_0]; \
+ const btScalar dir1 = edge[i_dir_1]; \
+ btScalar pmin = pointa[i_comp_0] * dir0 + pointa[i_comp_1] * dir1; \
+ btScalar pmax = pointb[i_comp_0] * dir0 + pointb[i_comp_1] * dir1; \
+ if (pmin > pmax) \
+ { \
+ BT_SWAP_NUMBERS(pmin, pmax); \
+ } \
+ const btScalar abs_dir0 = absolute_edge[i_dir_0]; \
+ const btScalar abs_dir1 = absolute_edge[i_dir_1]; \
+ const btScalar rad = _extend[i_comp_0] * abs_dir0 + _extend[i_comp_1] * abs_dir1; \
+ if (pmin > rad || -rad > pmax) return false; \
+ }
-#define TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,i_dir_0,i_dir_1,i_comp_0,i_comp_1)\
-{\
- const btScalar dir0 = -edge[i_dir_0];\
- const btScalar dir1 = edge[i_dir_1];\
- btScalar pmin = pointa[i_comp_0]*dir0 + pointa[i_comp_1]*dir1;\
- btScalar pmax = pointb[i_comp_0]*dir0 + pointb[i_comp_1]*dir1;\
- if(pmin>pmax)\
- {\
- BT_SWAP_NUMBERS(pmin,pmax); \
- }\
- const btScalar abs_dir0 = absolute_edge[i_dir_0];\
- const btScalar abs_dir1 = absolute_edge[i_dir_1];\
- const btScalar rad = _extend[i_comp_0] * abs_dir0 + _extend[i_comp_1] * abs_dir1;\
- if(pmin>rad || -rad>pmax) return false;\
-}\
-
-
-#define TEST_CROSS_EDGE_BOX_X_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
-{\
- TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,2,1,1,2);\
-}\
-
-#define TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
-{\
- TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,0,2,2,0);\
-}\
+#define TEST_CROSS_EDGE_BOX_X_AXIS_MCR(edge, absolute_edge, pointa, pointb, _extend) \
+ { \
+ TEST_CROSS_EDGE_BOX_MCR(edge, absolute_edge, pointa, pointb, _extend, 2, 1, 1, 2); \
+ }
-#define TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
-{\
- TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,1,0,0,1);\
-}\
+#define TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(edge, absolute_edge, pointa, pointb, _extend) \
+ { \
+ TEST_CROSS_EDGE_BOX_MCR(edge, absolute_edge, pointa, pointb, _extend, 0, 2, 2, 0); \
+ }
+#define TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(edge, absolute_edge, pointa, pointb, _extend) \
+ { \
+ TEST_CROSS_EDGE_BOX_MCR(edge, absolute_edge, pointa, pointb, _extend, 1, 0, 0, 1); \
+ }
//! Returns the dot product between a vec3f and the col of a matrix
SIMD_FORCE_INLINE btScalar bt_mat3_dot_col(
-const btMatrix3x3 & mat, const btVector3 & vec3, int colindex)
+ const btMatrix3x3 &mat, const btVector3 &vec3, int colindex)
{
- return vec3[0]*mat[0][colindex] + vec3[1]*mat[1][colindex] + vec3[2]*mat[2][colindex];
+ return vec3[0] * mat[0][colindex] + vec3[1] * mat[1][colindex] + vec3[2] * mat[2][colindex];
}
-
//! Class for transforming a model1 to the space of model0
-ATTRIBUTE_ALIGNED16 (class) BT_BOX_BOX_TRANSFORM_CACHE
+ATTRIBUTE_ALIGNED16(class)
+BT_BOX_BOX_TRANSFORM_CACHE
{
public:
- btVector3 m_T1to0;//!< Transforms translation of model1 to model 0
- btMatrix3x3 m_R1to0;//!< Transforms Rotation of model1 to model 0, equal to R0' * R1
- btMatrix3x3 m_AR;//!< Absolute value of m_R1to0
+ btVector3 m_T1to0; //!< Transforms translation of model1 to model 0
+ btMatrix3x3 m_R1to0; //!< Transforms Rotation of model1 to model 0, equal to R0' * R1
+ btMatrix3x3 m_AR; //!< Absolute value of m_R1to0
SIMD_FORCE_INLINE void calc_absolute_matrix()
{
-// static const btVector3 vepsi(1e-6f,1e-6f,1e-6f);
-// m_AR[0] = vepsi + m_R1to0[0].absolute();
-// m_AR[1] = vepsi + m_R1to0[1].absolute();
-// m_AR[2] = vepsi + m_R1to0[2].absolute();
-
- int i,j;
+ // static const btVector3 vepsi(1e-6f,1e-6f,1e-6f);
+ // m_AR[0] = vepsi + m_R1to0[0].absolute();
+ // m_AR[1] = vepsi + m_R1to0[1].absolute();
+ // m_AR[2] = vepsi + m_R1to0[2].absolute();
- for(i=0;i<3;i++)
- {
- for(j=0;j<3;j++ )
- {
- m_AR[i][j] = 1e-6f + btFabs(m_R1to0[i][j]);
- }
- }
+ int i, j;
+ for (i = 0; i < 3; i++)
+ {
+ for (j = 0; j < 3; j++)
+ {
+ m_AR[i][j] = 1e-6f + btFabs(m_R1to0[i][j]);
+ }
+ }
}
BT_BOX_BOX_TRANSFORM_CACHE()
{
}
-
-
//! Calc the transformation relative 1 to 0. Inverts matrics by transposing
- SIMD_FORCE_INLINE void calc_from_homogenic(const btTransform & trans0,const btTransform & trans1)
+ SIMD_FORCE_INLINE void calc_from_homogenic(const btTransform &trans0, const btTransform &trans1)
{
-
btTransform temp_trans = trans0.inverse();
temp_trans = temp_trans * trans1;
m_T1to0 = temp_trans.getOrigin();
m_R1to0 = temp_trans.getBasis();
-
calc_absolute_matrix();
}
//! Calcs the full invertion of the matrices. Useful for scaling matrices
- SIMD_FORCE_INLINE void calc_from_full_invert(const btTransform & trans0,const btTransform & trans1)
+ SIMD_FORCE_INLINE void calc_from_full_invert(const btTransform &trans0, const btTransform &trans1)
{
m_R1to0 = trans0.getBasis().inverse();
m_T1to0 = m_R1to0 * (-trans0.getOrigin());
- m_T1to0 += m_R1to0*trans1.getOrigin();
+ m_T1to0 += m_R1to0 * trans1.getOrigin();
m_R1to0 *= trans1.getBasis();
calc_absolute_matrix();
}
- SIMD_FORCE_INLINE btVector3 transform(const btVector3 & point) const
+ SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
{
- return point.dot3( m_R1to0[0], m_R1to0[1], m_R1to0[2] ) + m_T1to0;
+ return point.dot3(m_R1to0[0], m_R1to0[1], m_R1to0[2]) + m_T1to0;
}
};
-
#define BOX_PLANE_EPSILON 0.000001f
//! Axis aligned box
-ATTRIBUTE_ALIGNED16 (class) btAABB
+ATTRIBUTE_ALIGNED16(class)
+btAABB
{
public:
btVector3 m_min;
btVector3 m_max;
btAABB()
- {}
-
+ {
+ }
- btAABB(const btVector3 & V1,
- const btVector3 & V2,
- const btVector3 & V3)
+ btAABB(const btVector3 &V1,
+ const btVector3 &V2,
+ const btVector3 &V3)
{
- m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]);
- m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]);
- m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]);
+ m_min[0] = BT_MIN3(V1[0], V2[0], V3[0]);
+ m_min[1] = BT_MIN3(V1[1], V2[1], V3[1]);
+ m_min[2] = BT_MIN3(V1[2], V2[2], V3[2]);
- m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]);
- m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]);
- m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]);
+ m_max[0] = BT_MAX3(V1[0], V2[0], V3[0]);
+ m_max[1] = BT_MAX3(V1[1], V2[1], V3[1]);
+ m_max[2] = BT_MAX3(V1[2], V2[2], V3[2]);
}
- btAABB(const btVector3 & V1,
- const btVector3 & V2,
- const btVector3 & V3,
- btScalar margin)
+ btAABB(const btVector3 &V1,
+ const btVector3 &V2,
+ const btVector3 &V3,
+ btScalar margin)
{
- m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]);
- m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]);
- m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]);
+ m_min[0] = BT_MIN3(V1[0], V2[0], V3[0]);
+ m_min[1] = BT_MIN3(V1[1], V2[1], V3[1]);
+ m_min[2] = BT_MIN3(V1[2], V2[2], V3[2]);
- m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]);
- m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]);
- m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]);
+ m_max[0] = BT_MAX3(V1[0], V2[0], V3[0]);
+ m_max[1] = BT_MAX3(V1[1], V2[1], V3[1]);
+ m_max[2] = BT_MAX3(V1[2], V2[2], V3[2]);
m_min[0] -= margin;
m_min[1] -= margin;
@@ -270,13 +256,11 @@ public:
m_max[2] += margin;
}
- btAABB(const btAABB &other):
- m_min(other.m_min),m_max(other.m_max)
+ btAABB(const btAABB &other) : m_min(other.m_min), m_max(other.m_max)
{
}
- btAABB(const btAABB &other,btScalar margin ):
- m_min(other.m_min),m_max(other.m_max)
+ btAABB(const btAABB &other, btScalar margin) : m_min(other.m_min), m_max(other.m_max)
{
m_min[0] -= margin;
m_min[1] -= margin;
@@ -317,34 +301,34 @@ public:
m_max[2] = other.m_max[2] + margin;
}
- template<typename CLASS_POINT>
+ template <typename CLASS_POINT>
SIMD_FORCE_INLINE void calc_from_triangle(
- const CLASS_POINT & V1,
- const CLASS_POINT & V2,
- const CLASS_POINT & V3)
+ const CLASS_POINT &V1,
+ const CLASS_POINT &V2,
+ const CLASS_POINT &V3)
{
- m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]);
- m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]);
- m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]);
+ m_min[0] = BT_MIN3(V1[0], V2[0], V3[0]);
+ m_min[1] = BT_MIN3(V1[1], V2[1], V3[1]);
+ m_min[2] = BT_MIN3(V1[2], V2[2], V3[2]);
- m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]);
- m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]);
- m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]);
+ m_max[0] = BT_MAX3(V1[0], V2[0], V3[0]);
+ m_max[1] = BT_MAX3(V1[1], V2[1], V3[1]);
+ m_max[2] = BT_MAX3(V1[2], V2[2], V3[2]);
}
- template<typename CLASS_POINT>
+ template <typename CLASS_POINT>
SIMD_FORCE_INLINE void calc_from_triangle_margin(
- const CLASS_POINT & V1,
- const CLASS_POINT & V2,
- const CLASS_POINT & V3, btScalar margin)
+ const CLASS_POINT &V1,
+ const CLASS_POINT &V2,
+ const CLASS_POINT &V3, btScalar margin)
{
- m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]);
- m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]);
- m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]);
+ m_min[0] = BT_MIN3(V1[0], V2[0], V3[0]);
+ m_min[1] = BT_MIN3(V1[1], V2[1], V3[1]);
+ m_min[2] = BT_MIN3(V1[2], V2[2], V3[2]);
- m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]);
- m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]);
- m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]);
+ m_max[0] = BT_MAX3(V1[0], V2[0], V3[0]);
+ m_max[1] = BT_MAX3(V1[1], V2[1], V3[1]);
+ m_max[2] = BT_MAX3(V1[2], V2[2], V3[2]);
m_min[0] -= margin;
m_min[1] -= margin;
@@ -355,91 +339,89 @@ public:
}
//! Apply a transform to an AABB
- SIMD_FORCE_INLINE void appy_transform(const btTransform & trans)
+ SIMD_FORCE_INLINE void appy_transform(const btTransform &trans)
{
- btVector3 center = (m_max+m_min)*0.5f;
+ btVector3 center = (m_max + m_min) * 0.5f;
btVector3 extends = m_max - center;
// Compute new center
center = trans(center);
- btVector3 textends = extends.dot3(trans.getBasis().getRow(0).absolute(),
- trans.getBasis().getRow(1).absolute(),
- trans.getBasis().getRow(2).absolute());
+ btVector3 textends = extends.dot3(trans.getBasis().getRow(0).absolute(),
+ trans.getBasis().getRow(1).absolute(),
+ trans.getBasis().getRow(2).absolute());
m_min = center - textends;
m_max = center + textends;
}
-
//! Apply a transform to an AABB
- SIMD_FORCE_INLINE void appy_transform_trans_cache(const BT_BOX_BOX_TRANSFORM_CACHE & trans)
+ SIMD_FORCE_INLINE void appy_transform_trans_cache(const BT_BOX_BOX_TRANSFORM_CACHE &trans)
{
- btVector3 center = (m_max+m_min)*0.5f;
+ btVector3 center = (m_max + m_min) * 0.5f;
btVector3 extends = m_max - center;
// Compute new center
center = trans.transform(center);
- btVector3 textends = extends.dot3(trans.m_R1to0.getRow(0).absolute(),
- trans.m_R1to0.getRow(1).absolute(),
- trans.m_R1to0.getRow(2).absolute());
-
+ btVector3 textends = extends.dot3(trans.m_R1to0.getRow(0).absolute(),
+ trans.m_R1to0.getRow(1).absolute(),
+ trans.m_R1to0.getRow(2).absolute());
+
m_min = center - textends;
m_max = center + textends;
}
//! Merges a Box
- SIMD_FORCE_INLINE void merge(const btAABB & box)
+ SIMD_FORCE_INLINE void merge(const btAABB &box)
{
- m_min[0] = BT_MIN(m_min[0],box.m_min[0]);
- m_min[1] = BT_MIN(m_min[1],box.m_min[1]);
- m_min[2] = BT_MIN(m_min[2],box.m_min[2]);
+ m_min[0] = BT_MIN(m_min[0], box.m_min[0]);
+ m_min[1] = BT_MIN(m_min[1], box.m_min[1]);
+ m_min[2] = BT_MIN(m_min[2], box.m_min[2]);
- m_max[0] = BT_MAX(m_max[0],box.m_max[0]);
- m_max[1] = BT_MAX(m_max[1],box.m_max[1]);
- m_max[2] = BT_MAX(m_max[2],box.m_max[2]);
+ m_max[0] = BT_MAX(m_max[0], box.m_max[0]);
+ m_max[1] = BT_MAX(m_max[1], box.m_max[1]);
+ m_max[2] = BT_MAX(m_max[2], box.m_max[2]);
}
//! Merges a point
- template<typename CLASS_POINT>
- SIMD_FORCE_INLINE void merge_point(const CLASS_POINT & point)
+ template <typename CLASS_POINT>
+ SIMD_FORCE_INLINE void merge_point(const CLASS_POINT &point)
{
- m_min[0] = BT_MIN(m_min[0],point[0]);
- m_min[1] = BT_MIN(m_min[1],point[1]);
- m_min[2] = BT_MIN(m_min[2],point[2]);
+ m_min[0] = BT_MIN(m_min[0], point[0]);
+ m_min[1] = BT_MIN(m_min[1], point[1]);
+ m_min[2] = BT_MIN(m_min[2], point[2]);
- m_max[0] = BT_MAX(m_max[0],point[0]);
- m_max[1] = BT_MAX(m_max[1],point[1]);
- m_max[2] = BT_MAX(m_max[2],point[2]);
+ m_max[0] = BT_MAX(m_max[0], point[0]);
+ m_max[1] = BT_MAX(m_max[1], point[1]);
+ m_max[2] = BT_MAX(m_max[2], point[2]);
}
//! Gets the extend and center
- SIMD_FORCE_INLINE void get_center_extend(btVector3 & center,btVector3 & extend) const
+ SIMD_FORCE_INLINE void get_center_extend(btVector3 & center, btVector3 & extend) const
{
- center = (m_max+m_min)*0.5f;
+ center = (m_max + m_min) * 0.5f;
extend = m_max - center;
}
//! Finds the intersecting box between this box and the other.
- SIMD_FORCE_INLINE void find_intersection(const btAABB & other, btAABB & intersection) const
+ SIMD_FORCE_INLINE void find_intersection(const btAABB &other, btAABB &intersection) const
{
- intersection.m_min[0] = BT_MAX(other.m_min[0],m_min[0]);
- intersection.m_min[1] = BT_MAX(other.m_min[1],m_min[1]);
- intersection.m_min[2] = BT_MAX(other.m_min[2],m_min[2]);
+ intersection.m_min[0] = BT_MAX(other.m_min[0], m_min[0]);
+ intersection.m_min[1] = BT_MAX(other.m_min[1], m_min[1]);
+ intersection.m_min[2] = BT_MAX(other.m_min[2], m_min[2]);
- intersection.m_max[0] = BT_MIN(other.m_max[0],m_max[0]);
- intersection.m_max[1] = BT_MIN(other.m_max[1],m_max[1]);
- intersection.m_max[2] = BT_MIN(other.m_max[2],m_max[2]);
+ intersection.m_max[0] = BT_MIN(other.m_max[0], m_max[0]);
+ intersection.m_max[1] = BT_MIN(other.m_max[1], m_max[1]);
+ intersection.m_max[2] = BT_MIN(other.m_max[2], m_max[2]);
}
-
- SIMD_FORCE_INLINE bool has_collision(const btAABB & other) const
+ SIMD_FORCE_INLINE bool has_collision(const btAABB &other) const
{
- if(m_min[0] > other.m_max[0] ||
- m_max[0] < other.m_min[0] ||
- m_min[1] > other.m_max[1] ||
- m_max[1] < other.m_min[1] ||
- m_min[2] > other.m_max[2] ||
- m_max[2] < other.m_min[2])
+ if (m_min[0] > other.m_max[0] ||
+ m_max[0] < other.m_min[0] ||
+ m_min[1] > other.m_max[1] ||
+ m_max[1] < other.m_min[1] ||
+ m_min[2] > other.m_max[2] ||
+ m_max[2] < other.m_min[2])
{
return false;
}
@@ -451,35 +433,34 @@ public:
\param vorigin A vec3f with the origin of the ray
\param vdir A vec3f with the direction of the ray
*/
- SIMD_FORCE_INLINE bool collide_ray(const btVector3 & vorigin,const btVector3 & vdir) const
+ SIMD_FORCE_INLINE bool collide_ray(const btVector3 &vorigin, const btVector3 &vdir) const
{
- btVector3 extents,center;
- this->get_center_extend(center,extents);;
+ btVector3 extents, center;
+ this->get_center_extend(center, extents);
+ ;
btScalar Dx = vorigin[0] - center[0];
- if(BT_GREATER(Dx, extents[0]) && Dx*vdir[0]>=0.0f) return false;
+ if (BT_GREATER(Dx, extents[0]) && Dx * vdir[0] >= 0.0f) return false;
btScalar Dy = vorigin[1] - center[1];
- if(BT_GREATER(Dy, extents[1]) && Dy*vdir[1]>=0.0f) return false;
+ if (BT_GREATER(Dy, extents[1]) && Dy * vdir[1] >= 0.0f) return false;
btScalar Dz = vorigin[2] - center[2];
- if(BT_GREATER(Dz, extents[2]) && Dz*vdir[2]>=0.0f) return false;
-
+ if (BT_GREATER(Dz, extents[2]) && Dz * vdir[2] >= 0.0f) return false;
btScalar f = vdir[1] * Dz - vdir[2] * Dy;
- if(btFabs(f) > extents[1]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[1])) return false;
+ if (btFabs(f) > extents[1] * btFabs(vdir[2]) + extents[2] * btFabs(vdir[1])) return false;
f = vdir[2] * Dx - vdir[0] * Dz;
- if(btFabs(f) > extents[0]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[0]))return false;
+ if (btFabs(f) > extents[0] * btFabs(vdir[2]) + extents[2] * btFabs(vdir[0])) return false;
f = vdir[0] * Dy - vdir[1] * Dx;
- if(btFabs(f) > extents[0]*btFabs(vdir[1]) + extents[1]*btFabs(vdir[0]))return false;
+ if (btFabs(f) > extents[0] * btFabs(vdir[1]) + extents[1] * btFabs(vdir[0])) return false;
return true;
}
-
- SIMD_FORCE_INLINE void projection_interval(const btVector3 & direction, btScalar &vmin, btScalar &vmax) const
+ SIMD_FORCE_INLINE void projection_interval(const btVector3 &direction, btScalar &vmin, btScalar &vmax) const
{
- btVector3 center = (m_max+m_min)*0.5f;
- btVector3 extend = m_max-center;
+ btVector3 center = (m_max + m_min) * 0.5f;
+ btVector3 extend = m_max - center;
- btScalar _fOrigin = direction.dot(center);
+ btScalar _fOrigin = direction.dot(center);
btScalar _fMaximumExtent = extend.dot(direction.absolute());
vmin = _fOrigin - _fMaximumExtent;
vmax = _fOrigin + _fMaximumExtent;
@@ -487,30 +468,30 @@ public:
SIMD_FORCE_INLINE eBT_PLANE_INTERSECTION_TYPE plane_classify(const btVector4 &plane) const
{
- btScalar _fmin,_fmax;
- this->projection_interval(plane,_fmin,_fmax);
+ btScalar _fmin, _fmax;
+ this->projection_interval(plane, _fmin, _fmax);
- if(plane[3] > _fmax + BOX_PLANE_EPSILON)
+ if (plane[3] > _fmax + BOX_PLANE_EPSILON)
{
- return BT_CONST_BACK_PLANE; // 0
+ return BT_CONST_BACK_PLANE; // 0
}
- if(plane[3]+BOX_PLANE_EPSILON >=_fmin)
+ if (plane[3] + BOX_PLANE_EPSILON >= _fmin)
{
- return BT_CONST_COLLIDE_PLANE; //1
+ return BT_CONST_COLLIDE_PLANE; //1
}
- return BT_CONST_FRONT_PLANE;//2
+ return BT_CONST_FRONT_PLANE; //2
}
- SIMD_FORCE_INLINE bool overlapping_trans_conservative(const btAABB & box, btTransform & trans1_to_0) const
+ SIMD_FORCE_INLINE bool overlapping_trans_conservative(const btAABB &box, btTransform &trans1_to_0) const
{
btAABB tbox = box;
tbox.appy_transform(trans1_to_0);
return has_collision(tbox);
}
- SIMD_FORCE_INLINE bool overlapping_trans_conservative2(const btAABB & box,
- const BT_BOX_BOX_TRANSFORM_CACHE & trans1_to_0) const
+ SIMD_FORCE_INLINE bool overlapping_trans_conservative2(const btAABB &box,
+ const BT_BOX_BOX_TRANSFORM_CACHE &trans1_to_0) const
{
btAABB tbox = box;
tbox.appy_transform_trans_cache(trans1_to_0);
@@ -519,52 +500,50 @@ public:
//! transcache is the transformation cache from box to this AABB
SIMD_FORCE_INLINE bool overlapping_trans_cache(
- const btAABB & box,const BT_BOX_BOX_TRANSFORM_CACHE & transcache, bool fulltest) const
+ const btAABB &box, const BT_BOX_BOX_TRANSFORM_CACHE &transcache, bool fulltest) const
{
-
//Taken from OPCODE
- btVector3 ea,eb;//extends
- btVector3 ca,cb;//extends
- get_center_extend(ca,ea);
- box.get_center_extend(cb,eb);
-
+ btVector3 ea, eb; //extends
+ btVector3 ca, cb; //extends
+ get_center_extend(ca, ea);
+ box.get_center_extend(cb, eb);
btVector3 T;
- btScalar t,t2;
+ btScalar t, t2;
int i;
// Class I : A's basis vectors
- for(i=0;i<3;i++)
+ for (i = 0; i < 3; i++)
{
- T[i] = transcache.m_R1to0[i].dot(cb) + transcache.m_T1to0[i] - ca[i];
+ T[i] = transcache.m_R1to0[i].dot(cb) + transcache.m_T1to0[i] - ca[i];
t = transcache.m_AR[i].dot(eb) + ea[i];
- if(BT_GREATER(T[i], t)) return false;
+ if (BT_GREATER(T[i], t)) return false;
}
// Class II : B's basis vectors
- for(i=0;i<3;i++)
+ for (i = 0; i < 3; i++)
{
- t = bt_mat3_dot_col(transcache.m_R1to0,T,i);
- t2 = bt_mat3_dot_col(transcache.m_AR,ea,i) + eb[i];
- if(BT_GREATER(t,t2)) return false;
+ t = bt_mat3_dot_col(transcache.m_R1to0, T, i);
+ t2 = bt_mat3_dot_col(transcache.m_AR, ea, i) + eb[i];
+ if (BT_GREATER(t, t2)) return false;
}
// Class III : 9 cross products
- if(fulltest)
+ if (fulltest)
{
- int j,m,n,o,p,q,r;
- for(i=0;i<3;i++)
+ int j, m, n, o, p, q, r;
+ for (i = 0; i < 3; i++)
{
- m = (i+1)%3;
- n = (i+2)%3;
- o = i==0?1:0;
- p = i==2?1:2;
- for(j=0;j<3;j++)
+ m = (i + 1) % 3;
+ n = (i + 2) % 3;
+ o = i == 0 ? 1 : 0;
+ p = i == 2 ? 1 : 2;
+ for (j = 0; j < 3; j++)
{
- q = j==2?1:2;
- r = j==0?1:0;
- t = T[n]*transcache.m_R1to0[m][j] - T[m]*transcache.m_R1to0[n][j];
- t2 = ea[o]*transcache.m_AR[p][j] + ea[p]*transcache.m_AR[o][j] +
- eb[r]*transcache.m_AR[i][q] + eb[q]*transcache.m_AR[i][r];
- if(BT_GREATER(t,t2)) return false;
+ q = j == 2 ? 1 : 2;
+ r = j == 0 ? 1 : 0;
+ t = T[n] * transcache.m_R1to0[m][j] - T[m] * transcache.m_R1to0[n][j];
+ t2 = ea[o] * transcache.m_AR[p][j] + ea[p] * transcache.m_AR[o][j] +
+ eb[r] * transcache.m_AR[i][q] + eb[q] * transcache.m_AR[i][r];
+ if (BT_GREATER(t, t2)) return false;
}
}
}
@@ -573,7 +552,7 @@ public:
//! Simple test for planes.
SIMD_FORCE_INLINE bool collide_plane(
- const btVector4 & plane) const
+ const btVector4 &plane) const
{
eBT_PLANE_INTERSECTION_TYPE classify = plane_classify(plane);
return (classify == BT_CONST_COLLIDE_PLANE);
@@ -581,15 +560,15 @@ public:
//! test for a triangle, with edges
SIMD_FORCE_INLINE bool collide_triangle_exact(
- const btVector3 & p1,
- const btVector3 & p2,
- const btVector3 & p3,
- const btVector4 & triangle_plane) const
+ const btVector3 &p1,
+ const btVector3 &p2,
+ const btVector3 &p3,
+ const btVector4 &triangle_plane) const
{
- if(!collide_plane(triangle_plane)) return false;
+ if (!collide_plane(triangle_plane)) return false;
- btVector3 center,extends;
- this->get_center_extend(center,extends);
+ btVector3 center, extends;
+ this->get_center_extend(center, extends);
const btVector3 v1(p1 - center);
const btVector3 v2(p2 - center);
@@ -599,47 +578,43 @@ public:
btVector3 diff(v2 - v1);
btVector3 abs_diff = diff.absolute();
//Test With X axis
- TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v1,v3,extends);
+ TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff, abs_diff, v1, v3, extends);
//Test With Y axis
- TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v1,v3,extends);
+ TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff, abs_diff, v1, v3, extends);
//Test With Z axis
- TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v1,v3,extends);
-
+ TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff, abs_diff, v1, v3, extends);
diff = v3 - v2;
abs_diff = diff.absolute();
//Test With X axis
- TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v2,v1,extends);
+ TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff, abs_diff, v2, v1, extends);
//Test With Y axis
- TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v2,v1,extends);
+ TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff, abs_diff, v2, v1, extends);
//Test With Z axis
- TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v2,v1,extends);
+ TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff, abs_diff, v2, v1, extends);
diff = v1 - v3;
abs_diff = diff.absolute();
//Test With X axis
- TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v3,v2,extends);
+ TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff, abs_diff, v3, v2, extends);
//Test With Y axis
- TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v3,v2,extends);
+ TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff, abs_diff, v3, v2, extends);
//Test With Z axis
- TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v3,v2,extends);
+ TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff, abs_diff, v3, v2, extends);
return true;
}
};
-
//! Compairison of transformation objects
-SIMD_FORCE_INLINE bool btCompareTransformsEqual(const btTransform & t1,const btTransform & t2)
+SIMD_FORCE_INLINE bool btCompareTransformsEqual(const btTransform &t1, const btTransform &t2)
{
- if(!(t1.getOrigin() == t2.getOrigin()) ) return false;
+ if (!(t1.getOrigin() == t2.getOrigin())) return false;
- if(!(t1.getBasis().getRow(0) == t2.getBasis().getRow(0)) ) return false;
- if(!(t1.getBasis().getRow(1) == t2.getBasis().getRow(1)) ) return false;
- if(!(t1.getBasis().getRow(2) == t2.getBasis().getRow(2)) ) return false;
+ if (!(t1.getBasis().getRow(0) == t2.getBasis().getRow(0))) return false;
+ if (!(t1.getBasis().getRow(1) == t2.getBasis().getRow(1))) return false;
+ if (!(t1.getBasis().getRow(2) == t2.getBasis().getRow(2))) return false;
return true;
}
-
-
-#endif // GIM_BOX_COLLISION_H_INCLUDED
+#endif // GIM_BOX_COLLISION_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btClipPolygon.h b/thirdparty/bullet/BulletCollision/Gimpact/btClipPolygon.h
index de0a5231ba..38c23e222d 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/btClipPolygon.h
+++ b/thirdparty/bullet/BulletCollision/Gimpact/btClipPolygon.h
@@ -27,77 +27,74 @@ subject to the following restrictions:
#include "LinearMath/btTransform.h"
#include "LinearMath/btGeometryUtil.h"
-
-SIMD_FORCE_INLINE btScalar bt_distance_point_plane(const btVector4 & plane,const btVector3 &point)
+SIMD_FORCE_INLINE btScalar bt_distance_point_plane(const btVector4 &plane, const btVector3 &point)
{
return point.dot(plane) - plane[3];
}
/*! Vector blending
Takes two vectors a, b, blends them together*/
-SIMD_FORCE_INLINE void bt_vec_blend(btVector3 &vr, const btVector3 &va,const btVector3 &vb, btScalar blend_factor)
+SIMD_FORCE_INLINE void bt_vec_blend(btVector3 &vr, const btVector3 &va, const btVector3 &vb, btScalar blend_factor)
{
- vr = (1-blend_factor)*va + blend_factor*vb;
+ vr = (1 - blend_factor) * va + blend_factor * vb;
}
//! This function calcs the distance from a 3D plane
SIMD_FORCE_INLINE void bt_plane_clip_polygon_collect(
- const btVector3 & point0,
- const btVector3 & point1,
- btScalar dist0,
- btScalar dist1,
- btVector3 * clipped,
- int & clipped_count)
+ const btVector3 &point0,
+ const btVector3 &point1,
+ btScalar dist0,
+ btScalar dist1,
+ btVector3 *clipped,
+ int &clipped_count)
{
- bool _prevclassif = (dist0>SIMD_EPSILON);
- bool _classif = (dist1>SIMD_EPSILON);
- if(_classif!=_prevclassif)
+ bool _prevclassif = (dist0 > SIMD_EPSILON);
+ bool _classif = (dist1 > SIMD_EPSILON);
+ if (_classif != _prevclassif)
{
- btScalar blendfactor = -dist0/(dist1-dist0);
- bt_vec_blend(clipped[clipped_count],point0,point1,blendfactor);
+ btScalar blendfactor = -dist0 / (dist1 - dist0);
+ bt_vec_blend(clipped[clipped_count], point0, point1, blendfactor);
clipped_count++;
}
- if(!_classif)
+ if (!_classif)
{
clipped[clipped_count] = point1;
clipped_count++;
}
}
-
//! Clips a polygon by a plane
/*!
*\return The count of the clipped counts
*/
SIMD_FORCE_INLINE int bt_plane_clip_polygon(
- const btVector4 & plane,
- const btVector3 * polygon_points,
- int polygon_point_count,
- btVector3 * clipped)
+ const btVector4 &plane,
+ const btVector3 *polygon_points,
+ int polygon_point_count,
+ btVector3 *clipped)
{
- int clipped_count = 0;
-
+ int clipped_count = 0;
- //clip first point
- btScalar firstdist = bt_distance_point_plane(plane,polygon_points[0]);;
- if(!(firstdist>SIMD_EPSILON))
+ //clip first point
+ btScalar firstdist = bt_distance_point_plane(plane, polygon_points[0]);
+ ;
+ if (!(firstdist > SIMD_EPSILON))
{
clipped[clipped_count] = polygon_points[0];
clipped_count++;
}
btScalar olddist = firstdist;
- for(int i=1;i<polygon_point_count;i++)
+ for (int i = 1; i < polygon_point_count; i++)
{
- btScalar dist = bt_distance_point_plane(plane,polygon_points[i]);
+ btScalar dist = bt_distance_point_plane(plane, polygon_points[i]);
bt_plane_clip_polygon_collect(
- polygon_points[i-1],polygon_points[i],
- olddist,
- dist,
- clipped,
- clipped_count);
-
+ polygon_points[i - 1], polygon_points[i],
+ olddist,
+ dist,
+ clipped,
+ clipped_count);
olddist = dist;
}
@@ -105,11 +102,11 @@ SIMD_FORCE_INLINE int bt_plane_clip_polygon(
//RETURN TO FIRST point
bt_plane_clip_polygon_collect(
- polygon_points[polygon_point_count-1],polygon_points[0],
- olddist,
- firstdist,
- clipped,
- clipped_count);
+ polygon_points[polygon_point_count - 1], polygon_points[0],
+ olddist,
+ firstdist,
+ clipped,
+ clipped_count);
return clipped_count;
}
@@ -120,18 +117,19 @@ SIMD_FORCE_INLINE int bt_plane_clip_polygon(
*\return The count of the clipped counts
*/
SIMD_FORCE_INLINE int bt_plane_clip_triangle(
- const btVector4 & plane,
- const btVector3 & point0,
- const btVector3 & point1,
- const btVector3& point2,
- btVector3 * clipped // an allocated array of 16 points at least
- )
+ const btVector4 &plane,
+ const btVector3 &point0,
+ const btVector3 &point1,
+ const btVector3 &point2,
+ btVector3 *clipped // an allocated array of 16 points at least
+)
{
- int clipped_count = 0;
+ int clipped_count = 0;
- //clip first point0
- btScalar firstdist = bt_distance_point_plane(plane,point0);;
- if(!(firstdist>SIMD_EPSILON))
+ //clip first point0
+ btScalar firstdist = bt_distance_point_plane(plane, point0);
+ ;
+ if (!(firstdist > SIMD_EPSILON))
{
clipped[clipped_count] = point0;
clipped_count++;
@@ -139,44 +137,37 @@ SIMD_FORCE_INLINE int bt_plane_clip_triangle(
// point 1
btScalar olddist = firstdist;
- btScalar dist = bt_distance_point_plane(plane,point1);
+ btScalar dist = bt_distance_point_plane(plane, point1);
bt_plane_clip_polygon_collect(
- point0,point1,
- olddist,
- dist,
- clipped,
- clipped_count);
+ point0, point1,
+ olddist,
+ dist,
+ clipped,
+ clipped_count);
olddist = dist;
-
// point 2
- dist = bt_distance_point_plane(plane,point2);
+ dist = bt_distance_point_plane(plane, point2);
bt_plane_clip_polygon_collect(
- point1,point2,
- olddist,
- dist,
- clipped,
- clipped_count);
+ point1, point2,
+ olddist,
+ dist,
+ clipped,
+ clipped_count);
olddist = dist;
-
-
//RETURN TO FIRST point0
bt_plane_clip_polygon_collect(
- point2,point0,
- olddist,
- firstdist,
- clipped,
- clipped_count);
+ point2, point0,
+ olddist,
+ firstdist,
+ clipped,
+ clipped_count);
return clipped_count;
}
-
-
-
-
-#endif // GIM_TRI_COLLISION_H_INCLUDED
+#endif // GIM_TRI_COLLISION_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btCompoundFromGimpact.h b/thirdparty/bullet/BulletCollision/Gimpact/btCompoundFromGimpact.h
index 19f7ecddd0..ede59e8a57 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/btCompoundFromGimpact.h
+++ b/thirdparty/bullet/BulletCollision/Gimpact/btCompoundFromGimpact.h
@@ -5,7 +5,8 @@
#include "btGImpactShape.h"
#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
-ATTRIBUTE_ALIGNED16(class) btCompoundFromGimpactShape : public btCompoundShape
+ATTRIBUTE_ALIGNED16(class)
+btCompoundFromGimpactShape : public btCompoundShape
{
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
@@ -18,92 +19,87 @@ public:
delete m_children[i].m_childShape;
}
}
-
};
struct MyCallback : public btTriangleRaycastCallback
+{
+ int m_ignorePart;
+ int m_ignoreTriangleIndex;
+
+ MyCallback(const btVector3& from, const btVector3& to, int ignorePart, int ignoreTriangleIndex)
+ : btTriangleRaycastCallback(from, to),
+ m_ignorePart(ignorePart),
+ m_ignoreTriangleIndex(ignoreTriangleIndex)
+ {
+ }
+ virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex)
+ {
+ if (partId != m_ignorePart || triangleIndex != m_ignoreTriangleIndex)
{
- int m_ignorePart;
- int m_ignoreTriangleIndex;
-
-
- MyCallback(const btVector3& from, const btVector3& to, int ignorePart, int ignoreTriangleIndex)
- :btTriangleRaycastCallback(from,to),
- m_ignorePart(ignorePart),
- m_ignoreTriangleIndex(ignoreTriangleIndex)
- {
-
- }
- virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex)
- {
- if (partId!=m_ignorePart || triangleIndex!=m_ignoreTriangleIndex)
- {
- if (hitFraction < m_hitFraction)
- return hitFraction;
- }
-
- return m_hitFraction;
- }
- };
- struct MyInternalTriangleIndexCallback :public btInternalTriangleIndexCallback
+ if (hitFraction < m_hitFraction)
+ return hitFraction;
+ }
+
+ return m_hitFraction;
+ }
+};
+struct MyInternalTriangleIndexCallback : public btInternalTriangleIndexCallback
+{
+ const btGImpactMeshShape* m_gimpactShape;
+ btCompoundShape* m_colShape;
+ btScalar m_depth;
+
+ MyInternalTriangleIndexCallback(btCompoundShape* colShape, const btGImpactMeshShape* meshShape, btScalar depth)
+ : m_colShape(colShape),
+ m_gimpactShape(meshShape),
+ m_depth(depth)
+ {
+ }
+
+ virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
+ {
+ btVector3 scale = m_gimpactShape->getLocalScaling();
+ btVector3 v0 = triangle[0] * scale;
+ btVector3 v1 = triangle[1] * scale;
+ btVector3 v2 = triangle[2] * scale;
+
+ btVector3 centroid = (v0 + v1 + v2) / 3;
+ btVector3 normal = (v1 - v0).cross(v2 - v0);
+ normal.normalize();
+ btVector3 rayFrom = centroid;
+ btVector3 rayTo = centroid - normal * m_depth;
+
+ MyCallback cb(rayFrom, rayTo, partId, triangleIndex);
+
+ m_gimpactShape->processAllTrianglesRay(&cb, rayFrom, rayTo);
+ if (cb.m_hitFraction < 1)
{
- const btGImpactMeshShape* m_gimpactShape;
- btCompoundShape* m_colShape;
- btScalar m_depth;
-
- MyInternalTriangleIndexCallback (btCompoundShape* colShape, const btGImpactMeshShape* meshShape, btScalar depth)
- :m_colShape(colShape),
- m_gimpactShape(meshShape),
- m_depth(depth)
- {
- }
-
- virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex)
- {
- btVector3 scale = m_gimpactShape->getLocalScaling();
- btVector3 v0=triangle[0]*scale;
- btVector3 v1=triangle[1]*scale;
- btVector3 v2=triangle[2]*scale;
-
- btVector3 centroid = (v0+v1+v2)/3;
- btVector3 normal = (v1-v0).cross(v2-v0);
- normal.normalize();
- btVector3 rayFrom = centroid;
- btVector3 rayTo = centroid-normal*m_depth;
-
- MyCallback cb(rayFrom,rayTo,partId,triangleIndex);
-
- m_gimpactShape->processAllTrianglesRay(&cb,rayFrom, rayTo);
- if (cb.m_hitFraction<1)
- {
- rayTo.setInterpolate3(cb.m_from,cb.m_to,cb.m_hitFraction);
- //rayTo = cb.m_from;
- //rayTo = rayTo.lerp(cb.m_to,cb.m_hitFraction);
- //gDebugDraw.drawLine(tr(centroid),tr(centroid+normal),btVector3(1,0,0));
- }
-
-
-
- btBU_Simplex1to4* tet = new btBU_Simplex1to4(v0,v1,v2,rayTo);
- btTransform ident;
- ident.setIdentity();
- m_colShape->addChildShape(ident,tet);
- }
- };
-
-btCompoundShape* btCreateCompoundFromGimpactShape(const btGImpactMeshShape* gimpactMesh, btScalar depth)
+ rayTo.setInterpolate3(cb.m_from, cb.m_to, cb.m_hitFraction);
+ //rayTo = cb.m_from;
+ //rayTo = rayTo.lerp(cb.m_to,cb.m_hitFraction);
+ //gDebugDraw.drawLine(tr(centroid),tr(centroid+normal),btVector3(1,0,0));
+ }
+
+ btBU_Simplex1to4* tet = new btBU_Simplex1to4(v0, v1, v2, rayTo);
+ btTransform ident;
+ ident.setIdentity();
+ m_colShape->addChildShape(ident, tet);
+ }
+};
+
+btCompoundShape* btCreateCompoundFromGimpactShape(const btGImpactMeshShape* gimpactMesh, btScalar depth)
{
btCompoundShape* colShape = new btCompoundFromGimpactShape();
-
- btTransform tr;
- tr.setIdentity();
-
- MyInternalTriangleIndexCallback cb(colShape,gimpactMesh, depth);
- btVector3 aabbMin,aabbMax;
- gimpactMesh->getAabb(tr,aabbMin,aabbMax);
- gimpactMesh->getMeshInterface()->InternalProcessAllTriangles(&cb,aabbMin,aabbMax);
-
- return colShape;
-}
-
-#endif //BT_COMPOUND_FROM_GIMPACT
+
+ btTransform tr;
+ tr.setIdentity();
+
+ MyInternalTriangleIndexCallback cb(colShape, gimpactMesh, depth);
+ btVector3 aabbMin, aabbMax;
+ gimpactMesh->getAabb(tr, aabbMin, aabbMax);
+ gimpactMesh->getMeshInterface()->InternalProcessAllTriangles(&cb, aabbMin, aabbMax);
+
+ return colShape;
+}
+
+#endif //BT_COMPOUND_FROM_GIMPACT
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btContactProcessing.cpp b/thirdparty/bullet/BulletCollision/Gimpact/btContactProcessing.cpp
index eed31d839f..f2e3e18d61 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/btContactProcessing.cpp
+++ b/thirdparty/bullet/BulletCollision/Gimpact/btContactProcessing.cpp
@@ -27,54 +27,50 @@ struct CONTACT_KEY_TOKEN
unsigned int m_key;
int m_value;
CONTACT_KEY_TOKEN()
- {
- }
-
- CONTACT_KEY_TOKEN(unsigned int key,int token)
- {
- m_key = key;
- m_value = token;
- }
-
- CONTACT_KEY_TOKEN(const CONTACT_KEY_TOKEN& rtoken)
- {
- m_key = rtoken.m_key;
- m_value = rtoken.m_value;
- }
-
- inline bool operator <(const CONTACT_KEY_TOKEN& other) const
+ {
+ }
+
+ CONTACT_KEY_TOKEN(unsigned int key, int token)
+ {
+ m_key = key;
+ m_value = token;
+ }
+
+ CONTACT_KEY_TOKEN(const CONTACT_KEY_TOKEN& rtoken)
+ {
+ m_key = rtoken.m_key;
+ m_value = rtoken.m_value;
+ }
+
+ inline bool operator<(const CONTACT_KEY_TOKEN& other) const
{
return (m_key < other.m_key);
}
- inline bool operator >(const CONTACT_KEY_TOKEN& other) const
+ inline bool operator>(const CONTACT_KEY_TOKEN& other) const
{
return (m_key > other.m_key);
}
-
};
class CONTACT_KEY_TOKEN_COMP
{
- public:
-
- bool operator() ( const CONTACT_KEY_TOKEN& a, const CONTACT_KEY_TOKEN& b ) const
- {
- return ( a < b );
- }
+public:
+ bool operator()(const CONTACT_KEY_TOKEN& a, const CONTACT_KEY_TOKEN& b) const
+ {
+ return (a < b);
+ }
};
-
void btContactArray::merge_contacts(
- const btContactArray & contacts, bool normal_contact_average)
+ const btContactArray& contacts, bool normal_contact_average)
{
clear();
int i;
- if(contacts.size()==0) return;
-
+ if (contacts.size() == 0) return;
- if(contacts.size()==1)
+ if (contacts.size() == 1)
{
push_back(contacts[0]);
return;
@@ -86,16 +82,16 @@ void btContactArray::merge_contacts(
//fill key contacts
- for ( i = 0;i<contacts.size() ;i++ )
+ for (i = 0; i < contacts.size(); i++)
{
- keycontacts.push_back(CONTACT_KEY_TOKEN(contacts[i].calc_key_contact(),i));
+ keycontacts.push_back(CONTACT_KEY_TOKEN(contacts[i].calc_key_contact(), i));
}
//sort keys
keycontacts.quickSort(CONTACT_KEY_TOKEN_COMP());
// Merge contacts
- int coincident_count=0;
+ int coincident_count = 0;
btVector3 coincident_normals[MAX_COINCIDENT];
unsigned int last_key = keycontacts[0].m_key;
@@ -103,56 +99,56 @@ void btContactArray::merge_contacts(
push_back(contacts[keycontacts[0].m_value]);
- GIM_CONTACT * pcontact = &(*this)[0];
+ GIM_CONTACT* pcontact = &(*this)[0];
- for( i=1;i<keycontacts.size();i++)
+ for (i = 1; i < keycontacts.size(); i++)
{
- key = keycontacts[i].m_key;
- const GIM_CONTACT * scontact = &contacts[keycontacts[i].m_value];
+ key = keycontacts[i].m_key;
+ const GIM_CONTACT* scontact = &contacts[keycontacts[i].m_value];
- if(last_key == key)//same points
+ if (last_key == key) //same points
{
//merge contact
- if(pcontact->m_depth - CONTACT_DIFF_EPSILON > scontact->m_depth)//)
+ if (pcontact->m_depth - CONTACT_DIFF_EPSILON > scontact->m_depth) //)
{
*pcontact = *scontact;
- coincident_count = 0;
+ coincident_count = 0;
}
- else if(normal_contact_average)
+ else if (normal_contact_average)
{
- if(btFabs(pcontact->m_depth - scontact->m_depth)<CONTACT_DIFF_EPSILON)
- {
- if(coincident_count<MAX_COINCIDENT)
- {
- coincident_normals[coincident_count] = scontact->m_normal;
- coincident_count++;
- }
- }
+ if (btFabs(pcontact->m_depth - scontact->m_depth) < CONTACT_DIFF_EPSILON)
+ {
+ if (coincident_count < MAX_COINCIDENT)
+ {
+ coincident_normals[coincident_count] = scontact->m_normal;
+ coincident_count++;
+ }
+ }
}
}
else
- {//add new contact
+ { //add new contact
- if(normal_contact_average && coincident_count>0)
- {
- pcontact->interpolate_normals(coincident_normals,coincident_count);
- coincident_count = 0;
- }
+ if (normal_contact_average && coincident_count > 0)
+ {
+ pcontact->interpolate_normals(coincident_normals, coincident_count);
+ coincident_count = 0;
+ }
- push_back(*scontact);
- pcontact = &(*this)[this->size()-1];
- }
+ push_back(*scontact);
+ pcontact = &(*this)[this->size() - 1];
+ }
last_key = key;
}
}
-void btContactArray::merge_contacts_unique(const btContactArray & contacts)
+void btContactArray::merge_contacts_unique(const btContactArray& contacts)
{
clear();
- if(contacts.size()==0) return;
+ if (contacts.size() == 0) return;
- if(contacts.size()==1)
+ if (contacts.size() == 1)
{
push_back(contacts[0]);
return;
@@ -160,14 +156,14 @@ void btContactArray::merge_contacts_unique(const btContactArray & contacts)
GIM_CONTACT average_contact = contacts[0];
- for (int i=1;i<contacts.size() ;i++ )
+ for (int i = 1; i < contacts.size(); i++)
{
average_contact.m_point += contacts[i].m_point;
average_contact.m_normal += contacts[i].m_normal * contacts[i].m_depth;
}
//divide
- btScalar divide_average = 1.0f/((btScalar)contacts.size());
+ btScalar divide_average = 1.0f / ((btScalar)contacts.size());
average_contact.m_point *= divide_average;
@@ -176,6 +172,4 @@ void btContactArray::merge_contacts_unique(const btContactArray & contacts)
average_contact.m_depth = average_contact.m_normal.length();
average_contact.m_normal /= average_contact.m_depth;
-
}
-
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btContactProcessing.h b/thirdparty/bullet/BulletCollision/Gimpact/btContactProcessing.h
index d1027dbe67..4ff09d7cdd 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/btContactProcessing.h
+++ b/thirdparty/bullet/BulletCollision/Gimpact/btContactProcessing.h
@@ -29,7 +29,7 @@ subject to the following restrictions:
#include "btTriangleShapeEx.h"
#include "btContactProcessingStructs.h"
-class btContactArray:public btAlignedObjectArray<GIM_CONTACT>
+class btContactArray : public btAlignedObjectArray<GIM_CONTACT>
{
public:
btContactArray()
@@ -38,28 +38,28 @@ public:
}
SIMD_FORCE_INLINE void push_contact(
- const btVector3 &point,const btVector3 & normal,
+ const btVector3 &point, const btVector3 &normal,
btScalar depth, int feature1, int feature2)
{
- push_back( GIM_CONTACT(point,normal,depth,feature1,feature2) );
+ push_back(GIM_CONTACT(point, normal, depth, feature1, feature2));
}
SIMD_FORCE_INLINE void push_triangle_contacts(
- const GIM_TRIANGLE_CONTACT & tricontact,
- int feature1,int feature2)
+ const GIM_TRIANGLE_CONTACT &tricontact,
+ int feature1, int feature2)
{
- for(int i = 0;i<tricontact.m_point_count ;i++ )
+ for (int i = 0; i < tricontact.m_point_count; i++)
{
push_contact(
tricontact.m_points[i],
tricontact.m_separating_normal,
- tricontact.m_penetration_depth,feature1,feature2);
+ tricontact.m_penetration_depth, feature1, feature2);
}
}
- void merge_contacts(const btContactArray & contacts, bool normal_contact_average = true);
+ void merge_contacts(const btContactArray &contacts, bool normal_contact_average = true);
- void merge_contacts_unique(const btContactArray & contacts);
+ void merge_contacts_unique(const btContactArray &contacts);
};
-#endif // GIM_CONTACT_H_INCLUDED
+#endif // GIM_CONTACT_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btContactProcessingStructs.h b/thirdparty/bullet/BulletCollision/Gimpact/btContactProcessingStructs.h
index efbc4a567a..bc8a709246 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/btContactProcessingStructs.h
+++ b/thirdparty/bullet/BulletCollision/Gimpact/btContactProcessingStructs.h
@@ -28,7 +28,6 @@ subject to the following restrictions:
#include "LinearMath/btAlignedObjectArray.h"
#include "btTriangleShapeEx.h"
-
/**
Configuration var for applying interpolation of contact normals
*/
@@ -41,69 +40,66 @@ Configuration var for applying interpolation of contact normals
class GIM_CONTACT
{
public:
- btVector3 m_point;
- btVector3 m_normal;
- btScalar m_depth;//Positive value indicates interpenetration
- btScalar m_distance;//Padding not for use
- int m_feature1;//Face number
- int m_feature2;//Face number
+ btVector3 m_point;
+ btVector3 m_normal;
+ btScalar m_depth; //Positive value indicates interpenetration
+ btScalar m_distance; //Padding not for use
+ int m_feature1; //Face number
+ int m_feature2; //Face number
public:
- GIM_CONTACT()
- {
- }
-
- GIM_CONTACT(const GIM_CONTACT & contact):
- m_point(contact.m_point),
- m_normal(contact.m_normal),
- m_depth(contact.m_depth),
- m_feature1(contact.m_feature1),
- m_feature2(contact.m_feature2)
- {
- }
-
- GIM_CONTACT(const btVector3 &point,const btVector3 & normal,
- btScalar depth, int feature1, int feature2):
- m_point(point),
- m_normal(normal),
- m_depth(depth),
- m_feature1(feature1),
- m_feature2(feature2)
- {
- }
+ GIM_CONTACT()
+ {
+ }
+
+ GIM_CONTACT(const GIM_CONTACT &contact) : m_point(contact.m_point),
+ m_normal(contact.m_normal),
+ m_depth(contact.m_depth),
+ m_feature1(contact.m_feature1),
+ m_feature2(contact.m_feature2)
+ {
+ }
+
+ GIM_CONTACT(const btVector3 &point, const btVector3 &normal,
+ btScalar depth, int feature1, int feature2) : m_point(point),
+ m_normal(normal),
+ m_depth(depth),
+ m_feature1(feature1),
+ m_feature2(feature2)
+ {
+ }
//! Calcs key for coord classification
- SIMD_FORCE_INLINE unsigned int calc_key_contact() const
- {
- int _coords[] = {
- (int)(m_point[0]*1000.0f+1.0f),
- (int)(m_point[1]*1333.0f),
- (int)(m_point[2]*2133.0f+3.0f)};
- unsigned int _hash=0;
+ SIMD_FORCE_INLINE unsigned int calc_key_contact() const
+ {
+ int _coords[] = {
+ (int)(m_point[0] * 1000.0f + 1.0f),
+ (int)(m_point[1] * 1333.0f),
+ (int)(m_point[2] * 2133.0f + 3.0f)};
+ unsigned int _hash = 0;
unsigned int *_uitmp = (unsigned int *)(&_coords[0]);
_hash = *_uitmp;
_uitmp++;
- _hash += (*_uitmp)<<4;
+ _hash += (*_uitmp) << 4;
_uitmp++;
- _hash += (*_uitmp)<<8;
+ _hash += (*_uitmp) << 8;
return _hash;
- }
+ }
- SIMD_FORCE_INLINE void interpolate_normals( btVector3 * normals,int normal_count)
- {
- btVector3 vec_sum(m_normal);
- for(int i=0;i<normal_count;i++)
+ SIMD_FORCE_INLINE void interpolate_normals(btVector3 *normals, int normal_count)
+ {
+ btVector3 vec_sum(m_normal);
+ for (int i = 0; i < normal_count; i++)
{
vec_sum += normals[i];
}
btScalar vec_sum_len = vec_sum.length2();
- if(vec_sum_len <CONTACT_DIFF_EPSILON) return;
+ if (vec_sum_len < CONTACT_DIFF_EPSILON) return;
//GIM_INV_SQRT(vec_sum_len,vec_sum_len); // 1/sqrt(vec_sum_len)
- m_normal = vec_sum/btSqrt(vec_sum_len);
- }
-
+ m_normal = vec_sum / btSqrt(vec_sum_len);
+ }
};
-#endif // BT_CONTACT_H_STRUCTS_INCLUDED
+#endif // BT_CONTACT_H_STRUCTS_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactBvh.cpp b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactBvh.cpp
index 863233163a..bb520e061d 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactBvh.cpp
+++ b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactBvh.cpp
@@ -30,7 +30,6 @@ btClock g_tree_clock;
float g_accum_tree_collision_time = 0;
int g_count_traversing = 0;
-
void bt_begin_gim02_tree_time()
{
g_tree_clock.reset();
@@ -45,7 +44,7 @@ void bt_end_gim02_tree_time()
//! Gets the average time in miliseconds of tree collisions
float btGImpactBvh::getAverageTreeCollisionTime()
{
- if(g_count_traversing == 0) return 0;
+ if (g_count_traversing == 0) return 0;
float avgtime = g_accum_tree_collision_time;
avgtime /= (float)g_count_traversing;
@@ -54,80 +53,76 @@ float btGImpactBvh::getAverageTreeCollisionTime()
g_count_traversing = 0;
return avgtime;
-// float avgtime = g_count_traversing;
-// g_count_traversing = 0;
-// return avgtime;
-
+ // float avgtime = g_count_traversing;
+ // g_count_traversing = 0;
+ // return avgtime;
}
-#endif //TRI_COLLISION_PROFILING
+#endif //TRI_COLLISION_PROFILING
/////////////////////// btBvhTree /////////////////////////////////
int btBvhTree::_calc_splitting_axis(
- GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex)
+ GIM_BVH_DATA_ARRAY& primitive_boxes, int startIndex, int endIndex)
{
-
int i;
- btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
- btVector3 variance(btScalar(0.),btScalar(0.),btScalar(0.));
- int numIndices = endIndex-startIndex;
+ btVector3 means(btScalar(0.), btScalar(0.), btScalar(0.));
+ btVector3 variance(btScalar(0.), btScalar(0.), btScalar(0.));
+ int numIndices = endIndex - startIndex;
- for (i=startIndex;i<endIndex;i++)
+ for (i = startIndex; i < endIndex; i++)
{
- btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
- primitive_boxes[i].m_bound.m_min);
- means+=center;
+ btVector3 center = btScalar(0.5) * (primitive_boxes[i].m_bound.m_max +
+ primitive_boxes[i].m_bound.m_min);
+ means += center;
}
- means *= (btScalar(1.)/(btScalar)numIndices);
+ means *= (btScalar(1.) / (btScalar)numIndices);
- for (i=startIndex;i<endIndex;i++)
+ for (i = startIndex; i < endIndex; i++)
{
- btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
- primitive_boxes[i].m_bound.m_min);
- btVector3 diff2 = center-means;
+ btVector3 center = btScalar(0.5) * (primitive_boxes[i].m_bound.m_max +
+ primitive_boxes[i].m_bound.m_min);
+ btVector3 diff2 = center - means;
diff2 = diff2 * diff2;
variance += diff2;
}
- variance *= (btScalar(1.)/ ((btScalar)numIndices-1) );
+ variance *= (btScalar(1.) / ((btScalar)numIndices - 1));
return variance.maxAxis();
}
-
int btBvhTree::_sort_and_calc_splitting_index(
- GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex,
+ GIM_BVH_DATA_ARRAY& primitive_boxes, int startIndex,
int endIndex, int splitAxis)
{
int i;
- int splitIndex =startIndex;
+ int splitIndex = startIndex;
int numIndices = endIndex - startIndex;
// average of centers
btScalar splitValue = 0.0f;
- btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
- for (i=startIndex;i<endIndex;i++)
+ btVector3 means(btScalar(0.), btScalar(0.), btScalar(0.));
+ for (i = startIndex; i < endIndex; i++)
{
- btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
- primitive_boxes[i].m_bound.m_min);
- means+=center;
+ btVector3 center = btScalar(0.5) * (primitive_boxes[i].m_bound.m_max +
+ primitive_boxes[i].m_bound.m_min);
+ means += center;
}
- means *= (btScalar(1.)/(btScalar)numIndices);
+ means *= (btScalar(1.) / (btScalar)numIndices);
splitValue = means[splitAxis];
-
//sort leafNodes so all values larger then splitValue comes first, and smaller values start from 'splitIndex'.
- for (i=startIndex;i<endIndex;i++)
+ for (i = startIndex; i < endIndex; i++)
{
- btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
- primitive_boxes[i].m_bound.m_min);
+ btVector3 center = btScalar(0.5) * (primitive_boxes[i].m_bound.m_max +
+ primitive_boxes[i].m_bound.m_min);
if (center[splitAxis] > splitValue)
{
//swap
- primitive_boxes.swap(i,splitIndex);
+ primitive_boxes.swap(i, splitIndex);
//swapLeafNodes(i,splitIndex);
splitIndex++;
}
@@ -142,32 +137,30 @@ int btBvhTree::_sort_and_calc_splitting_index(
//bool unbalanced2 = true;
//this should be safe too:
- int rangeBalancedIndices = numIndices/3;
- bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices)));
+ int rangeBalancedIndices = numIndices / 3;
+ bool unbalanced = ((splitIndex <= (startIndex + rangeBalancedIndices)) || (splitIndex >= (endIndex - 1 - rangeBalancedIndices)));
if (unbalanced)
{
- splitIndex = startIndex+ (numIndices>>1);
+ splitIndex = startIndex + (numIndices >> 1);
}
- btAssert(!((splitIndex==startIndex) || (splitIndex == (endIndex))));
+ btAssert(!((splitIndex == startIndex) || (splitIndex == (endIndex))));
return splitIndex;
-
}
-
-void btBvhTree::_build_sub_tree(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex)
+void btBvhTree::_build_sub_tree(GIM_BVH_DATA_ARRAY& primitive_boxes, int startIndex, int endIndex)
{
int curIndex = m_num_nodes;
m_num_nodes++;
- btAssert((endIndex-startIndex)>0);
+ btAssert((endIndex - startIndex) > 0);
- if ((endIndex-startIndex)==1)
+ if ((endIndex - startIndex) == 1)
{
- //We have a leaf node
- setNodeBound(curIndex,primitive_boxes[startIndex].m_bound);
+ //We have a leaf node
+ setNodeBound(curIndex, primitive_boxes[startIndex].m_bound);
m_node_array[curIndex].setDataIndex(primitive_boxes[startIndex].m_data);
return;
@@ -175,47 +168,42 @@ void btBvhTree::_build_sub_tree(GIM_BVH_DATA_ARRAY & primitive_boxes, int startI
//calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'.
//split axis
- int splitIndex = _calc_splitting_axis(primitive_boxes,startIndex,endIndex);
+ int splitIndex = _calc_splitting_axis(primitive_boxes, startIndex, endIndex);
splitIndex = _sort_and_calc_splitting_index(
- primitive_boxes,startIndex,endIndex,
- splitIndex//split axis
- );
-
+ primitive_boxes, startIndex, endIndex,
+ splitIndex //split axis
+ );
//calc this node bounding box
btAABB node_bound;
node_bound.invalidate();
- for (int i=startIndex;i<endIndex;i++)
+ for (int i = startIndex; i < endIndex; i++)
{
node_bound.merge(primitive_boxes[i].m_bound);
}
- setNodeBound(curIndex,node_bound);
-
+ setNodeBound(curIndex, node_bound);
//build left branch
- _build_sub_tree(primitive_boxes, startIndex, splitIndex );
-
+ _build_sub_tree(primitive_boxes, startIndex, splitIndex);
//build right branch
- _build_sub_tree(primitive_boxes, splitIndex ,endIndex);
+ _build_sub_tree(primitive_boxes, splitIndex, endIndex);
m_node_array[curIndex].setEscapeIndex(m_num_nodes - curIndex);
-
-
}
//! stackless build tree
void btBvhTree::build_tree(
- GIM_BVH_DATA_ARRAY & primitive_boxes)
+ GIM_BVH_DATA_ARRAY& primitive_boxes)
{
// initialize node count to 0
m_num_nodes = 0;
// allocate nodes
- m_node_array.resize(primitive_boxes.size()*2);
+ m_node_array.resize(primitive_boxes.size() * 2);
_build_sub_tree(primitive_boxes, 0, primitive_boxes.size());
}
@@ -225,13 +213,13 @@ void btBvhTree::build_tree(
void btGImpactBvh::refit()
{
int nodecount = getNodeCount();
- while(nodecount--)
+ while (nodecount--)
{
- if(isLeafNode(nodecount))
+ if (isLeafNode(nodecount))
{
btAABB leafbox;
- m_primitive_manager->get_primitive_box(getNodeData(nodecount),leafbox);
- setNodeBound(nodecount,leafbox);
+ m_primitive_manager->get_primitive_box(getNodeData(nodecount), leafbox);
+ setNodeBound(nodecount, leafbox);
}
else
{
@@ -243,20 +231,20 @@ void btGImpactBvh::refit()
btAABB temp_box;
int child_node = getLeftNode(nodecount);
- if(child_node)
+ if (child_node)
{
- getNodeBound(child_node,temp_box);
+ getNodeBound(child_node, temp_box);
bound.merge(temp_box);
}
child_node = getRightNode(nodecount);
- if(child_node)
+ if (child_node)
{
- getNodeBound(child_node,temp_box);
+ getNodeBound(child_node, temp_box);
bound.merge(temp_box);
}
- setNodeBound(nodecount,bound);
+ setNodeBound(nodecount, bound);
}
}
}
@@ -268,17 +256,17 @@ void btGImpactBvh::buildSet()
GIM_BVH_DATA_ARRAY primitive_boxes;
primitive_boxes.resize(m_primitive_manager->get_primitive_count());
- for (int i = 0;i<primitive_boxes.size() ;i++ )
+ for (int i = 0; i < primitive_boxes.size(); i++)
{
- m_primitive_manager->get_primitive_box(i,primitive_boxes[i].m_bound);
- primitive_boxes[i].m_data = i;
+ m_primitive_manager->get_primitive_box(i, primitive_boxes[i].m_bound);
+ primitive_boxes[i].m_data = i;
}
m_box_tree.build_tree(primitive_boxes);
}
//! returns the indices of the primitives in the m_primitive_manager
-bool btGImpactBvh::boxQuery(const btAABB & box, btAlignedObjectArray<int> & collided_results) const
+bool btGImpactBvh::boxQuery(const btAABB& box, btAlignedObjectArray<int>& collided_results) const
{
int curIndex = 0;
int numNodes = getNodeCount();
@@ -286,7 +274,7 @@ bool btGImpactBvh::boxQuery(const btAABB & box, btAlignedObjectArray<int> & coll
while (curIndex < numNodes)
{
btAABB bound;
- getNodeBound(curIndex,bound);
+ getNodeBound(curIndex, bound);
//catch bugs in tree data
@@ -306,19 +294,17 @@ bool btGImpactBvh::boxQuery(const btAABB & box, btAlignedObjectArray<int> & coll
else
{
//skip node
- curIndex+= getEscapeNodeIndex(curIndex);
+ curIndex += getEscapeNodeIndex(curIndex);
}
}
- if(collided_results.size()>0) return true;
+ if (collided_results.size() > 0) return true;
return false;
}
-
-
//! returns the indices of the primitives in the m_primitive_manager
bool btGImpactBvh::rayQuery(
- const btVector3 & ray_dir,const btVector3 & ray_origin ,
- btAlignedObjectArray<int> & collided_results) const
+ const btVector3& ray_dir, const btVector3& ray_origin,
+ btAlignedObjectArray<int>& collided_results) const
{
int curIndex = 0;
int numNodes = getNodeCount();
@@ -326,16 +312,16 @@ bool btGImpactBvh::rayQuery(
while (curIndex < numNodes)
{
btAABB bound;
- getNodeBound(curIndex,bound);
+ getNodeBound(curIndex, bound);
//catch bugs in tree data
- bool aabbOverlap = bound.collide_ray(ray_origin,ray_dir);
+ bool aabbOverlap = bound.collide_ray(ray_origin, ray_dir);
bool isleafnode = isLeafNode(curIndex);
if (isleafnode && aabbOverlap)
{
- collided_results.push_back(getNodeData( curIndex));
+ collided_results.push_back(getNodeData(curIndex));
}
if (aabbOverlap || isleafnode)
@@ -346,153 +332,133 @@ bool btGImpactBvh::rayQuery(
else
{
//skip node
- curIndex+= getEscapeNodeIndex(curIndex);
+ curIndex += getEscapeNodeIndex(curIndex);
}
}
- if(collided_results.size()>0) return true;
+ if (collided_results.size() > 0) return true;
return false;
}
-
SIMD_FORCE_INLINE bool _node_collision(
- btGImpactBvh * boxset0, btGImpactBvh * boxset1,
- const BT_BOX_BOX_TRANSFORM_CACHE & trans_cache_1to0,
- int node0 ,int node1, bool complete_primitive_tests)
+ btGImpactBvh* boxset0, btGImpactBvh* boxset1,
+ const BT_BOX_BOX_TRANSFORM_CACHE& trans_cache_1to0,
+ int node0, int node1, bool complete_primitive_tests)
{
btAABB box0;
- boxset0->getNodeBound(node0,box0);
+ boxset0->getNodeBound(node0, box0);
btAABB box1;
- boxset1->getNodeBound(node1,box1);
-
- return box0.overlapping_trans_cache(box1,trans_cache_1to0,complete_primitive_tests );
-// box1.appy_transform_trans_cache(trans_cache_1to0);
-// return box0.has_collision(box1);
+ boxset1->getNodeBound(node1, box1);
+ return box0.overlapping_trans_cache(box1, trans_cache_1to0, complete_primitive_tests);
+ // box1.appy_transform_trans_cache(trans_cache_1to0);
+ // return box0.has_collision(box1);
}
-
//stackless recursive collision routine
static void _find_collision_pairs_recursive(
- btGImpactBvh * boxset0, btGImpactBvh * boxset1,
- btPairSet * collision_pairs,
- const BT_BOX_BOX_TRANSFORM_CACHE & trans_cache_1to0,
+ btGImpactBvh* boxset0, btGImpactBvh* boxset1,
+ btPairSet* collision_pairs,
+ const BT_BOX_BOX_TRANSFORM_CACHE& trans_cache_1to0,
int node0, int node1, bool complete_primitive_tests)
{
+ if (_node_collision(
+ boxset0, boxset1, trans_cache_1to0,
+ node0, node1, complete_primitive_tests) == false) return; //avoid colliding internal nodes
-
-
- if( _node_collision(
- boxset0,boxset1,trans_cache_1to0,
- node0,node1,complete_primitive_tests) ==false) return;//avoid colliding internal nodes
-
- if(boxset0->isLeafNode(node0))
+ if (boxset0->isLeafNode(node0))
{
- if(boxset1->isLeafNode(node1))
+ if (boxset1->isLeafNode(node1))
{
// collision result
collision_pairs->push_pair(
- boxset0->getNodeData(node0),boxset1->getNodeData(node1));
+ boxset0->getNodeData(node0), boxset1->getNodeData(node1));
return;
}
else
{
-
//collide left recursive
_find_collision_pairs_recursive(
- boxset0,boxset1,
- collision_pairs,trans_cache_1to0,
- node0,boxset1->getLeftNode(node1),false);
+ boxset0, boxset1,
+ collision_pairs, trans_cache_1to0,
+ node0, boxset1->getLeftNode(node1), false);
//collide right recursive
_find_collision_pairs_recursive(
- boxset0,boxset1,
- collision_pairs,trans_cache_1to0,
- node0,boxset1->getRightNode(node1),false);
-
-
+ boxset0, boxset1,
+ collision_pairs, trans_cache_1to0,
+ node0, boxset1->getRightNode(node1), false);
}
}
else
{
- if(boxset1->isLeafNode(node1))
+ if (boxset1->isLeafNode(node1))
{
-
//collide left recursive
_find_collision_pairs_recursive(
- boxset0,boxset1,
- collision_pairs,trans_cache_1to0,
- boxset0->getLeftNode(node0),node1,false);
-
+ boxset0, boxset1,
+ collision_pairs, trans_cache_1to0,
+ boxset0->getLeftNode(node0), node1, false);
//collide right recursive
_find_collision_pairs_recursive(
- boxset0,boxset1,
- collision_pairs,trans_cache_1to0,
- boxset0->getRightNode(node0),node1,false);
-
-
+ boxset0, boxset1,
+ collision_pairs, trans_cache_1to0,
+ boxset0->getRightNode(node0), node1, false);
}
else
{
//collide left0 left1
-
-
_find_collision_pairs_recursive(
- boxset0,boxset1,
- collision_pairs,trans_cache_1to0,
- boxset0->getLeftNode(node0),boxset1->getLeftNode(node1),false);
+ boxset0, boxset1,
+ collision_pairs, trans_cache_1to0,
+ boxset0->getLeftNode(node0), boxset1->getLeftNode(node1), false);
//collide left0 right1
_find_collision_pairs_recursive(
- boxset0,boxset1,
- collision_pairs,trans_cache_1to0,
- boxset0->getLeftNode(node0),boxset1->getRightNode(node1),false);
-
+ boxset0, boxset1,
+ collision_pairs, trans_cache_1to0,
+ boxset0->getLeftNode(node0), boxset1->getRightNode(node1), false);
//collide right0 left1
_find_collision_pairs_recursive(
- boxset0,boxset1,
- collision_pairs,trans_cache_1to0,
- boxset0->getRightNode(node0),boxset1->getLeftNode(node1),false);
+ boxset0, boxset1,
+ collision_pairs, trans_cache_1to0,
+ boxset0->getRightNode(node0), boxset1->getLeftNode(node1), false);
//collide right0 right1
_find_collision_pairs_recursive(
- boxset0,boxset1,
- collision_pairs,trans_cache_1to0,
- boxset0->getRightNode(node0),boxset1->getRightNode(node1),false);
+ boxset0, boxset1,
+ collision_pairs, trans_cache_1to0,
+ boxset0->getRightNode(node0), boxset1->getRightNode(node1), false);
- }// else if node1 is not a leaf
- }// else if node0 is not a leaf
+ } // else if node1 is not a leaf
+ } // else if node0 is not a leaf
}
-
-void btGImpactBvh::find_collision(btGImpactBvh * boxset0, const btTransform & trans0,
- btGImpactBvh * boxset1, const btTransform & trans1,
- btPairSet & collision_pairs)
+void btGImpactBvh::find_collision(btGImpactBvh* boxset0, const btTransform& trans0,
+ btGImpactBvh* boxset1, const btTransform& trans1,
+ btPairSet& collision_pairs)
{
-
- if(boxset0->getNodeCount()==0 || boxset1->getNodeCount()==0 ) return;
+ if (boxset0->getNodeCount() == 0 || boxset1->getNodeCount() == 0) return;
BT_BOX_BOX_TRANSFORM_CACHE trans_cache_1to0;
- trans_cache_1to0.calc_from_homogenic(trans0,trans1);
+ trans_cache_1to0.calc_from_homogenic(trans0, trans1);
#ifdef TRI_COLLISION_PROFILING
bt_begin_gim02_tree_time();
-#endif //TRI_COLLISION_PROFILING
+#endif //TRI_COLLISION_PROFILING
_find_collision_pairs_recursive(
- boxset0,boxset1,
- &collision_pairs,trans_cache_1to0,0,0,true);
+ boxset0, boxset1,
+ &collision_pairs, trans_cache_1to0, 0, 0, true);
#ifdef TRI_COLLISION_PROFILING
bt_end_gim02_tree_time();
-#endif //TRI_COLLISION_PROFILING
-
+#endif //TRI_COLLISION_PROFILING
}
-
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactBvh.h b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactBvh.h
index e20e03cc1d..3cd8fa24e7 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactBvh.h
+++ b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactBvh.h
@@ -1,5 +1,5 @@
-#ifndef GIM_BOX_SET_H_INCLUDED
-#define GIM_BOX_SET_H_INCLUDED
+#ifndef BT_GIMPACT_BVH_H_INCLUDED
+#define BT_GIMPACT_BVH_H_INCLUDED
/*! \file gim_box_set.h
\author Francisco Leon Najera
@@ -24,7 +24,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#include "LinearMath/btAlignedObjectArray.h"
#include "btBoxCollision.h"
@@ -32,50 +31,48 @@ subject to the following restrictions:
#include "btGImpactBvhStructs.h"
//! A pairset array
-class btPairSet: public btAlignedObjectArray<GIM_PAIR>
+class btPairSet : public btAlignedObjectArray<GIM_PAIR>
{
public:
btPairSet()
{
reserve(32);
}
- inline void push_pair(int index1,int index2)
+ inline void push_pair(int index1, int index2)
{
- push_back(GIM_PAIR(index1,index2));
+ push_back(GIM_PAIR(index1, index2));
}
- inline void push_pair_inv(int index1,int index2)
+ inline void push_pair_inv(int index1, int index2)
{
- push_back(GIM_PAIR(index2,index1));
+ push_back(GIM_PAIR(index2, index1));
}
};
-class GIM_BVH_DATA_ARRAY:public btAlignedObjectArray<GIM_BVH_DATA>
+class GIM_BVH_DATA_ARRAY : public btAlignedObjectArray<GIM_BVH_DATA>
{
};
-
-class GIM_BVH_TREE_NODE_ARRAY:public btAlignedObjectArray<GIM_BVH_TREE_NODE>
+class GIM_BVH_TREE_NODE_ARRAY : public btAlignedObjectArray<GIM_BVH_TREE_NODE>
{
};
-
-
-
//! Basic Box tree structure
class btBvhTree
{
protected:
int m_num_nodes;
GIM_BVH_TREE_NODE_ARRAY m_node_array;
+
protected:
int _sort_and_calc_splitting_index(
- GIM_BVH_DATA_ARRAY & primitive_boxes,
- int startIndex, int endIndex, int splitAxis);
+ GIM_BVH_DATA_ARRAY& primitive_boxes,
+ int startIndex, int endIndex, int splitAxis);
- int _calc_splitting_axis(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex);
+ int _calc_splitting_axis(GIM_BVH_DATA_ARRAY& primitive_boxes, int startIndex, int endIndex);
+
+ void _build_sub_tree(GIM_BVH_DATA_ARRAY& primitive_boxes, int startIndex, int endIndex);
- void _build_sub_tree(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex);
public:
btBvhTree()
{
@@ -84,7 +81,7 @@ public:
//! prototype functions for box tree management
//!@{
- void build_tree(GIM_BVH_DATA_ARRAY & primitive_boxes);
+ void build_tree(GIM_BVH_DATA_ARRAY& primitive_boxes);
SIMD_FORCE_INLINE void clearNodes()
{
@@ -109,25 +106,25 @@ public:
return m_node_array[nodeindex].getDataIndex();
}
- SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB & bound) const
+ SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB& bound) const
{
bound = m_node_array[nodeindex].m_bound;
}
- SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB & bound)
+ SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB& bound)
{
m_node_array[nodeindex].m_bound = bound;
}
SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const
{
- return nodeindex+1;
+ return nodeindex + 1;
}
SIMD_FORCE_INLINE int getRightNode(int nodeindex) const
{
- if(m_node_array[nodeindex+1].isLeafNode()) return nodeindex+2;
- return nodeindex+1 + m_node_array[nodeindex+1].getEscapeIndex();
+ if (m_node_array[nodeindex + 1].isLeafNode()) return nodeindex + 2;
+ return nodeindex + 1 + m_node_array[nodeindex + 1].getEscapeIndex();
}
SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const
@@ -135,7 +132,7 @@ public:
return m_node_array[nodeindex].getEscapeIndex();
}
- SIMD_FORCE_INLINE const GIM_BVH_TREE_NODE * get_node_pointer(int index = 0) const
+ SIMD_FORCE_INLINE const GIM_BVH_TREE_NODE* get_node_pointer(int index = 0) const
{
return &m_node_array[index];
}
@@ -143,7 +140,6 @@ public:
//!@}
};
-
//! Prototype Base class for primitive classification
/*!
This class is a wrapper for primitive collections.
@@ -153,18 +149,16 @@ This class can manage Compound shapes and trimeshes, and if it is managing trime
class btPrimitiveManagerBase
{
public:
-
virtual ~btPrimitiveManagerBase() {}
//! determines if this manager consist on only triangles, which special case will be optimized
virtual bool is_trimesh() const = 0;
virtual int get_primitive_count() const = 0;
- virtual void get_primitive_box(int prim_index ,btAABB & primbox) const = 0;
+ virtual void get_primitive_box(int prim_index, btAABB& primbox) const = 0;
//! retrieves only the points of the triangle, and the collision margin
- virtual void get_primitive_triangle(int prim_index,btPrimitiveTriangle & triangle) const= 0;
+ virtual void get_primitive_triangle(int prim_index, btPrimitiveTriangle& triangle) const = 0;
};
-
//! Structure for containing Boxes
/*!
This class offers an structure for managing a box tree of primitives.
@@ -174,13 +168,13 @@ class btGImpactBvh
{
protected:
btBvhTree m_box_tree;
- btPrimitiveManagerBase * m_primitive_manager;
+ btPrimitiveManagerBase* m_primitive_manager;
protected:
//stackless refit
void refit();
-public:
+public:
//! this constructor doesn't build the tree. you must call buildSet
btGImpactBvh()
{
@@ -188,31 +182,30 @@ public:
}
//! this constructor doesn't build the tree. you must call buildSet
- btGImpactBvh(btPrimitiveManagerBase * primitive_manager)
+ btGImpactBvh(btPrimitiveManagerBase* primitive_manager)
{
m_primitive_manager = primitive_manager;
}
- SIMD_FORCE_INLINE btAABB getGlobalBox() const
+ SIMD_FORCE_INLINE btAABB getGlobalBox() const
{
btAABB totalbox;
getNodeBound(0, totalbox);
return totalbox;
}
- SIMD_FORCE_INLINE void setPrimitiveManager(btPrimitiveManagerBase * primitive_manager)
+ SIMD_FORCE_INLINE void setPrimitiveManager(btPrimitiveManagerBase* primitive_manager)
{
m_primitive_manager = primitive_manager;
}
- SIMD_FORCE_INLINE btPrimitiveManagerBase * getPrimitiveManager() const
+ SIMD_FORCE_INLINE btPrimitiveManagerBase* getPrimitiveManager() const
{
return m_primitive_manager;
}
-
-//! node manager prototype functions
-///@{
+ //! node manager prototype functions
+ ///@{
//! this attemps to refit the box set.
SIMD_FORCE_INLINE void update()
@@ -224,21 +217,21 @@ public:
void buildSet();
//! returns the indices of the primitives in the m_primitive_manager
- bool boxQuery(const btAABB & box, btAlignedObjectArray<int> & collided_results) const;
+ bool boxQuery(const btAABB& box, btAlignedObjectArray<int>& collided_results) const;
//! returns the indices of the primitives in the m_primitive_manager
- SIMD_FORCE_INLINE bool boxQueryTrans(const btAABB & box,
- const btTransform & transform, btAlignedObjectArray<int> & collided_results) const
+ SIMD_FORCE_INLINE bool boxQueryTrans(const btAABB& box,
+ const btTransform& transform, btAlignedObjectArray<int>& collided_results) const
{
- btAABB transbox=box;
+ btAABB transbox = box;
transbox.appy_transform(transform);
- return boxQuery(transbox,collided_results);
+ return boxQuery(transbox, collided_results);
}
//! returns the indices of the primitives in the m_primitive_manager
bool rayQuery(
- const btVector3 & ray_dir,const btVector3 & ray_origin ,
- btAlignedObjectArray<int> & collided_results) const;
+ const btVector3& ray_dir, const btVector3& ray_origin,
+ btAlignedObjectArray<int>& collided_results) const;
//! tells if this set has hierarcht
SIMD_FORCE_INLINE bool hasHierarchy() const
@@ -247,7 +240,7 @@ public:
}
//! tells if this set is a trimesh
- SIMD_FORCE_INLINE bool isTrimesh() const
+ SIMD_FORCE_INLINE bool isTrimesh() const
{
return m_primitive_manager->is_trimesh();
}
@@ -269,17 +262,16 @@ public:
return m_box_tree.getNodeData(nodeindex);
}
- SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB & bound) const
+ SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB& bound) const
{
m_box_tree.getNodeBound(nodeindex, bound);
}
- SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB & bound)
+ SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB& bound)
{
m_box_tree.setNodeBound(nodeindex, bound);
}
-
SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const
{
return m_box_tree.getLeftNode(nodeindex);
@@ -295,24 +287,23 @@ public:
return m_box_tree.getEscapeNodeIndex(nodeindex);
}
- SIMD_FORCE_INLINE void getNodeTriangle(int nodeindex,btPrimitiveTriangle & triangle) const
+ SIMD_FORCE_INLINE void getNodeTriangle(int nodeindex, btPrimitiveTriangle& triangle) const
{
- m_primitive_manager->get_primitive_triangle(getNodeData(nodeindex),triangle);
+ m_primitive_manager->get_primitive_triangle(getNodeData(nodeindex), triangle);
}
-
- SIMD_FORCE_INLINE const GIM_BVH_TREE_NODE * get_node_pointer(int index = 0) const
+ SIMD_FORCE_INLINE const GIM_BVH_TREE_NODE* get_node_pointer(int index = 0) const
{
return m_box_tree.get_node_pointer(index);
}
#ifdef TRI_COLLISION_PROFILING
static float getAverageTreeCollisionTime();
-#endif //TRI_COLLISION_PROFILING
+#endif //TRI_COLLISION_PROFILING
- static void find_collision(btGImpactBvh * boxset1, const btTransform & trans1,
- btGImpactBvh * boxset2, const btTransform & trans2,
- btPairSet & collision_pairs);
+ static void find_collision(btGImpactBvh* boxset1, const btTransform& trans1,
+ btGImpactBvh* boxset2, const btTransform& trans2,
+ btPairSet& collision_pairs);
};
-#endif // GIM_BOXPRUNING_H_INCLUDED
+#endif // BT_GIMPACT_BVH_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactBvhStructs.h b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactBvhStructs.h
index 9342a572d0..54888c6757 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactBvhStructs.h
+++ b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactBvhStructs.h
@@ -24,7 +24,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#include "LinearMath/btAlignedObjectArray.h"
#include "btBoxCollision.h"
@@ -33,21 +32,22 @@ subject to the following restrictions:
//! Overlapping pair
struct GIM_PAIR
{
- int m_index1;
- int m_index2;
- GIM_PAIR()
- {}
-
- GIM_PAIR(const GIM_PAIR & p)
- {
- m_index1 = p.m_index1;
- m_index2 = p.m_index2;
+ int m_index1;
+ int m_index2;
+ GIM_PAIR()
+ {
+ }
+
+ GIM_PAIR(const GIM_PAIR& p)
+ {
+ m_index1 = p.m_index1;
+ m_index2 = p.m_index2;
}
GIM_PAIR(int index1, int index2)
- {
- m_index1 = index1;
- m_index2 = index2;
+ {
+ m_index1 = index1;
+ m_index2 = index2;
}
};
@@ -63,8 +63,10 @@ class GIM_BVH_TREE_NODE
{
public:
btAABB m_bound;
+
protected:
- int m_escapeIndexOrDataIndex;
+ int m_escapeIndexOrDataIndex;
+
public:
GIM_BVH_TREE_NODE()
{
@@ -74,7 +76,7 @@ public:
SIMD_FORCE_INLINE bool isLeafNode() const
{
//skipindex is negative (internal node), triangleindex >=0 (leafnode)
- return (m_escapeIndexOrDataIndex>=0);
+ return (m_escapeIndexOrDataIndex >= 0);
}
SIMD_FORCE_INLINE int getEscapeIndex() const
@@ -99,7 +101,6 @@ public:
{
m_escapeIndexOrDataIndex = index;
}
-
};
-#endif // GIM_BOXPRUNING_H_INCLUDED
+#endif // GIM_BOXPRUNING_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp
index 2e87475e39..3d8ab9f520 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp
+++ b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp
@@ -31,18 +31,16 @@ Concave-Concave Collision
#include "btContactProcessing.h"
#include "LinearMath/btQuickprof.h"
-
//! Class for accessing the plane equation
class btPlaneShape : public btStaticPlaneShape
{
public:
-
btPlaneShape(const btVector3& v, float f)
- :btStaticPlaneShape(v,f)
+ : btStaticPlaneShape(v, f)
{
}
- void get_plane_equation(btVector4 &equation)
+ void get_plane_equation(btVector4& equation)
{
equation[0] = m_planeNormal[0];
equation[1] = m_planeNormal[1];
@@ -50,18 +48,16 @@ public:
equation[3] = m_planeConstant;
}
-
- void get_plane_equation_transformed(const btTransform & trans,btVector4 &equation) const
+ void get_plane_equation_transformed(const btTransform& trans, btVector4& equation) const
{
- equation[0] = trans.getBasis().getRow(0).dot(m_planeNormal);
- equation[1] = trans.getBasis().getRow(1).dot(m_planeNormal);
- equation[2] = trans.getBasis().getRow(2).dot(m_planeNormal);
- equation[3] = trans.getOrigin().dot(m_planeNormal) + m_planeConstant;
+ const btVector3 normal = trans.getBasis() * m_planeNormal;
+ equation[0] = normal[0];
+ equation[1] = normal[1];
+ equation[2] = normal[2];
+ equation[3] = normal.dot(trans * (m_planeConstant * m_planeNormal));
}
};
-
-
//////////////////////////////////////////////////////////////////////////////////////////////
#ifdef TRI_COLLISION_PROFILING
@@ -80,7 +76,7 @@ void bt_end_gim02_tri_time()
g_accum_triangle_collision_time += g_triangle_clock.getTimeMicroseconds();
g_count_triangle_collision++;
}
-#endif //TRI_COLLISION_PROFILING
+#endif //TRI_COLLISION_PROFILING
//! Retrieving shapes shapes
/*!
Declared here due of insuficent space on Pool allocators
@@ -89,7 +85,7 @@ Declared here due of insuficent space on Pool allocators
class GIM_ShapeRetriever
{
public:
- const btGImpactShapeInterface * m_gim_shape;
+ const btGImpactShapeInterface* m_gim_shape;
btTriangleShapeEx m_trishape;
btTetrahedronShapeEx m_tetrashape;
@@ -97,51 +93,50 @@ public:
class ChildShapeRetriever
{
public:
- GIM_ShapeRetriever * m_parent;
- virtual const btCollisionShape * getChildShape(int index)
+ GIM_ShapeRetriever* m_parent;
+ virtual const btCollisionShape* getChildShape(int index)
{
return m_parent->m_gim_shape->getChildShape(index);
}
virtual ~ChildShapeRetriever() {}
};
- class TriangleShapeRetriever:public ChildShapeRetriever
+ class TriangleShapeRetriever : public ChildShapeRetriever
{
public:
-
- virtual btCollisionShape * getChildShape(int index)
+ virtual btCollisionShape* getChildShape(int index)
{
- m_parent->m_gim_shape->getBulletTriangle(index,m_parent->m_trishape);
+ m_parent->m_gim_shape->getBulletTriangle(index, m_parent->m_trishape);
return &m_parent->m_trishape;
}
virtual ~TriangleShapeRetriever() {}
};
- class TetraShapeRetriever:public ChildShapeRetriever
+ class TetraShapeRetriever : public ChildShapeRetriever
{
public:
-
- virtual btCollisionShape * getChildShape(int index)
+ virtual btCollisionShape* getChildShape(int index)
{
- m_parent->m_gim_shape->getBulletTetrahedron(index,m_parent->m_tetrashape);
+ m_parent->m_gim_shape->getBulletTetrahedron(index, m_parent->m_tetrashape);
return &m_parent->m_tetrashape;
}
};
+
public:
ChildShapeRetriever m_child_retriever;
TriangleShapeRetriever m_tri_retriever;
- TetraShapeRetriever m_tetra_retriever;
- ChildShapeRetriever * m_current_retriever;
+ TetraShapeRetriever m_tetra_retriever;
+ ChildShapeRetriever* m_current_retriever;
- GIM_ShapeRetriever(const btGImpactShapeInterface * gim_shape)
+ GIM_ShapeRetriever(const btGImpactShapeInterface* gim_shape)
{
m_gim_shape = gim_shape;
//select retriever
- if(m_gim_shape->needsRetrieveTriangles())
+ if (m_gim_shape->needsRetrieveTriangles())
{
m_current_retriever = &m_tri_retriever;
}
- else if(m_gim_shape->needsRetrieveTetrahedrons())
+ else if (m_gim_shape->needsRetrieveTetrahedrons())
{
m_current_retriever = &m_tetra_retriever;
}
@@ -153,32 +148,26 @@ public:
m_current_retriever->m_parent = this;
}
- const btCollisionShape * getChildShape(int index)
+ const btCollisionShape* getChildShape(int index)
{
return m_current_retriever->getChildShape(index);
}
-
-
};
-
-
//!@}
-
#ifdef TRI_COLLISION_PROFILING
//! Gets the average time in miliseconds of tree collisions
float btGImpactCollisionAlgorithm::getAverageTreeCollisionTime()
{
return btGImpactBoxSet::getAverageTreeCollisionTime();
-
}
//! Gets the average time in miliseconds of triangle collisions
float btGImpactCollisionAlgorithm::getAverageTriangleCollisionTime()
{
- if(g_count_triangle_collision == 0) return 0;
+ if (g_count_triangle_collision == 0) return 0;
float avgtime = g_accum_triangle_collision_time;
avgtime /= (float)g_count_triangle_collision;
@@ -189,12 +178,10 @@ float btGImpactCollisionAlgorithm::getAverageTriangleCollisionTime()
return avgtime;
}
-#endif //TRI_COLLISION_PROFILING
-
+#endif //TRI_COLLISION_PROFILING
-
-btGImpactCollisionAlgorithm::btGImpactCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
-: btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap)
+btGImpactCollisionAlgorithm::btGImpactCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
+ : btActivatingCollisionAlgorithm(ci, body0Wrap, body1Wrap)
{
m_manifoldPtr = NULL;
m_convex_algorithm = NULL;
@@ -205,77 +192,62 @@ btGImpactCollisionAlgorithm::~btGImpactCollisionAlgorithm()
clearCache();
}
-
-
-
-
-void btGImpactCollisionAlgorithm::addContactPoint(const btCollisionObjectWrapper * body0Wrap,
- const btCollisionObjectWrapper * body1Wrap,
- const btVector3 & point,
- const btVector3 & normal,
- btScalar distance)
+void btGImpactCollisionAlgorithm::addContactPoint(const btCollisionObjectWrapper* body0Wrap,
+ const btCollisionObjectWrapper* body1Wrap,
+ const btVector3& point,
+ const btVector3& normal,
+ btScalar distance)
{
- m_resultOut->setShapeIdentifiersA(m_part0,m_triface0);
- m_resultOut->setShapeIdentifiersB(m_part1,m_triface1);
- checkManifold(body0Wrap,body1Wrap);
- m_resultOut->addContactPoint(normal,point,distance);
+ m_resultOut->setShapeIdentifiersA(m_part0, m_triface0);
+ m_resultOut->setShapeIdentifiersB(m_part1, m_triface1);
+ checkManifold(body0Wrap, body1Wrap);
+ m_resultOut->addContactPoint(normal, point, distance);
}
-
void btGImpactCollisionAlgorithm::shape_vs_shape_collision(
- const btCollisionObjectWrapper * body0Wrap,
- const btCollisionObjectWrapper* body1Wrap,
- const btCollisionShape * shape0,
- const btCollisionShape * shape1)
+ const btCollisionObjectWrapper* body0Wrap,
+ const btCollisionObjectWrapper* body1Wrap,
+ const btCollisionShape* shape0,
+ const btCollisionShape* shape1)
{
-
-
{
-
- btCollisionAlgorithm* algor = newAlgorithm(body0Wrap,body1Wrap);
+ btCollisionAlgorithm* algor = newAlgorithm(body0Wrap, body1Wrap);
// post : checkManifold is called
- m_resultOut->setShapeIdentifiersA(m_part0,m_triface0);
- m_resultOut->setShapeIdentifiersB(m_part1,m_triface1);
-
- algor->processCollision(body0Wrap,body1Wrap,*m_dispatchInfo,m_resultOut);
-
+ m_resultOut->setShapeIdentifiersA(m_part0, m_triface0);
+ m_resultOut->setShapeIdentifiersB(m_part1, m_triface1);
+
+ algor->processCollision(body0Wrap, body1Wrap, *m_dispatchInfo, m_resultOut);
+
algor->~btCollisionAlgorithm();
m_dispatcher->freeCollisionAlgorithm(algor);
}
-
}
void btGImpactCollisionAlgorithm::convex_vs_convex_collision(
- const btCollisionObjectWrapper* body0Wrap,
- const btCollisionObjectWrapper* body1Wrap,
- const btCollisionShape* shape0,
- const btCollisionShape* shape1)
+ const btCollisionObjectWrapper* body0Wrap,
+ const btCollisionObjectWrapper* body1Wrap,
+ const btCollisionShape* shape0,
+ const btCollisionShape* shape1)
{
+ m_resultOut->setShapeIdentifiersA(m_part0, m_triface0);
+ m_resultOut->setShapeIdentifiersB(m_part1, m_triface1);
- m_resultOut->setShapeIdentifiersA(m_part0,m_triface0);
- m_resultOut->setShapeIdentifiersB(m_part1,m_triface1);
-
- btCollisionObjectWrapper ob0(body0Wrap,shape0,body0Wrap->getCollisionObject(),body0Wrap->getWorldTransform(),m_part0,m_triface0);
- btCollisionObjectWrapper ob1(body1Wrap,shape1,body1Wrap->getCollisionObject(),body1Wrap->getWorldTransform(),m_part1,m_triface1);
- checkConvexAlgorithm(&ob0,&ob1);
- m_convex_algorithm->processCollision(&ob0,&ob1,*m_dispatchInfo,m_resultOut);
-
-
+ btCollisionObjectWrapper ob0(body0Wrap, shape0, body0Wrap->getCollisionObject(), body0Wrap->getWorldTransform(), m_part0, m_triface0);
+ btCollisionObjectWrapper ob1(body1Wrap, shape1, body1Wrap->getCollisionObject(), body1Wrap->getWorldTransform(), m_part1, m_triface1);
+ checkConvexAlgorithm(&ob0, &ob1);
+ m_convex_algorithm->processCollision(&ob0, &ob1, *m_dispatchInfo, m_resultOut);
}
-
-
-
void btGImpactCollisionAlgorithm::gimpact_vs_gimpact_find_pairs(
- const btTransform & trans0,
- const btTransform & trans1,
- const btGImpactShapeInterface * shape0,
- const btGImpactShapeInterface * shape1,btPairSet & pairset)
+ const btTransform& trans0,
+ const btTransform& trans1,
+ const btGImpactShapeInterface* shape0,
+ const btGImpactShapeInterface* shape1, btPairSet& pairset)
{
- if(shape0->hasBoxSet() && shape1->hasBoxSet())
+ if (shape0->hasBoxSet() && shape1->hasBoxSet())
{
- btGImpactBoxSet::find_collision(shape0->getBoxSet(),trans0,shape1->getBoxSet(),trans1,pairset);
+ btGImpactBoxSet::find_collision(shape0->getBoxSet(), trans0, shape1->getBoxSet(), trans1, pairset);
}
else
{
@@ -283,74 +255,66 @@ void btGImpactCollisionAlgorithm::gimpact_vs_gimpact_find_pairs(
btAABB boxshape1;
int i = shape0->getNumChildShapes();
- while(i--)
+ while (i--)
{
- shape0->getChildAabb(i,trans0,boxshape0.m_min,boxshape0.m_max);
+ shape0->getChildAabb(i, trans0, boxshape0.m_min, boxshape0.m_max);
int j = shape1->getNumChildShapes();
- while(j--)
+ while (j--)
{
- shape1->getChildAabb(i,trans1,boxshape1.m_min,boxshape1.m_max);
+ shape1->getChildAabb(i, trans1, boxshape1.m_min, boxshape1.m_max);
- if(boxshape1.has_collision(boxshape0))
+ if (boxshape1.has_collision(boxshape0))
{
- pairset.push_pair(i,j);
+ pairset.push_pair(i, j);
}
}
}
}
-
-
}
-
void btGImpactCollisionAlgorithm::gimpact_vs_shape_find_pairs(
- const btTransform & trans0,
- const btTransform & trans1,
- const btGImpactShapeInterface * shape0,
- const btCollisionShape * shape1,
- btAlignedObjectArray<int> & collided_primitives)
+ const btTransform& trans0,
+ const btTransform& trans1,
+ const btGImpactShapeInterface* shape0,
+ const btCollisionShape* shape1,
+ btAlignedObjectArray<int>& collided_primitives)
{
-
btAABB boxshape;
-
- if(shape0->hasBoxSet())
+ if (shape0->hasBoxSet())
{
btTransform trans1to0 = trans0.inverse();
trans1to0 *= trans1;
- shape1->getAabb(trans1to0,boxshape.m_min,boxshape.m_max);
+ shape1->getAabb(trans1to0, boxshape.m_min, boxshape.m_max);
shape0->getBoxSet()->boxQuery(boxshape, collided_primitives);
}
else
{
- shape1->getAabb(trans1,boxshape.m_min,boxshape.m_max);
+ shape1->getAabb(trans1, boxshape.m_min, boxshape.m_max);
btAABB boxshape0;
int i = shape0->getNumChildShapes();
- while(i--)
+ while (i--)
{
- shape0->getChildAabb(i,trans0,boxshape0.m_min,boxshape0.m_max);
+ shape0->getChildAabb(i, trans0, boxshape0.m_min, boxshape0.m_max);
- if(boxshape.has_collision(boxshape0))
+ if (boxshape.has_collision(boxshape0))
{
collided_primitives.push_back(i);
}
}
-
}
-
}
-
-void btGImpactCollisionAlgorithm::collide_gjk_triangles(const btCollisionObjectWrapper * body0Wrap,
- const btCollisionObjectWrapper * body1Wrap,
- const btGImpactMeshShapePart * shape0,
- const btGImpactMeshShapePart * shape1,
- const int * pairs, int pair_count)
+void btGImpactCollisionAlgorithm::collide_gjk_triangles(const btCollisionObjectWrapper* body0Wrap,
+ const btCollisionObjectWrapper* body1Wrap,
+ const btGImpactMeshShapePart* shape0,
+ const btGImpactMeshShapePart* shape1,
+ const int* pairs, int pair_count)
{
btTriangleShapeEx tri0;
btTriangleShapeEx tri1;
@@ -358,27 +322,22 @@ void btGImpactCollisionAlgorithm::collide_gjk_triangles(const btCollisionObjectW
shape0->lockChildShapes();
shape1->lockChildShapes();
- const int * pair_pointer = pairs;
+ const int* pair_pointer = pairs;
- while(pair_count--)
+ while (pair_count--)
{
-
m_triface0 = *(pair_pointer);
- m_triface1 = *(pair_pointer+1);
- pair_pointer+=2;
-
-
-
- shape0->getBulletTriangle(m_triface0,tri0);
- shape1->getBulletTriangle(m_triface1,tri1);
+ m_triface1 = *(pair_pointer + 1);
+ pair_pointer += 2;
+ shape0->getBulletTriangle(m_triface0, tri0);
+ shape1->getBulletTriangle(m_triface1, tri1);
//collide two convex shapes
- if(tri0.overlap_test_conservative(tri1))
+ if (tri0.overlap_test_conservative(tri1))
{
- convex_vs_convex_collision(body0Wrap,body1Wrap,&tri0,&tri1);
+ convex_vs_convex_collision(body0Wrap, body1Wrap, &tri0, &tri1);
}
-
}
shape0->unlockChildShapes();
@@ -386,10 +345,10 @@ void btGImpactCollisionAlgorithm::collide_gjk_triangles(const btCollisionObjectW
}
void btGImpactCollisionAlgorithm::collide_sat_triangles(const btCollisionObjectWrapper* body0Wrap,
- const btCollisionObjectWrapper* body1Wrap,
- const btGImpactMeshShapePart * shape0,
- const btGImpactMeshShapePart * shape1,
- const int * pairs, int pair_count)
+ const btCollisionObjectWrapper* body1Wrap,
+ const btGImpactMeshShapePart* shape0,
+ const btGImpactMeshShapePart* shape1,
+ const int* pairs, int pair_count)
{
btTransform orgtrans0 = body0Wrap->getWorldTransform();
btTransform orgtrans1 = body1Wrap->getWorldTransform();
@@ -401,119 +360,105 @@ void btGImpactCollisionAlgorithm::collide_sat_triangles(const btCollisionObjectW
shape0->lockChildShapes();
shape1->lockChildShapes();
- const int * pair_pointer = pairs;
+ const int* pair_pointer = pairs;
- while(pair_count--)
+ while (pair_count--)
{
-
m_triface0 = *(pair_pointer);
- m_triface1 = *(pair_pointer+1);
- pair_pointer+=2;
+ m_triface1 = *(pair_pointer + 1);
+ pair_pointer += 2;
+ shape0->getPrimitiveTriangle(m_triface0, ptri0);
+ shape1->getPrimitiveTriangle(m_triface1, ptri1);
- shape0->getPrimitiveTriangle(m_triface0,ptri0);
- shape1->getPrimitiveTriangle(m_triface1,ptri1);
-
- #ifdef TRI_COLLISION_PROFILING
+#ifdef TRI_COLLISION_PROFILING
bt_begin_gim02_tri_time();
- #endif
+#endif
ptri0.applyTransform(orgtrans0);
ptri1.applyTransform(orgtrans1);
-
//build planes
ptri0.buildTriPlane();
ptri1.buildTriPlane();
// test conservative
-
-
- if(ptri0.overlap_test_conservative(ptri1))
+ if (ptri0.overlap_test_conservative(ptri1))
{
- if(ptri0.find_triangle_collision_clip_method(ptri1,contact_data))
+ if (ptri0.find_triangle_collision_clip_method(ptri1, contact_data))
{
-
int j = contact_data.m_point_count;
- while(j--)
+ while (j--)
{
-
addContactPoint(body0Wrap, body1Wrap,
- contact_data.m_points[j],
- contact_data.m_separating_normal,
- -contact_data.m_penetration_depth);
+ contact_data.m_points[j],
+ contact_data.m_separating_normal,
+ -contact_data.m_penetration_depth);
}
}
}
- #ifdef TRI_COLLISION_PROFILING
+#ifdef TRI_COLLISION_PROFILING
bt_end_gim02_tri_time();
- #endif
-
+#endif
}
shape0->unlockChildShapes();
shape1->unlockChildShapes();
-
}
-
void btGImpactCollisionAlgorithm::gimpact_vs_gimpact(
- const btCollisionObjectWrapper* body0Wrap,
- const btCollisionObjectWrapper * body1Wrap,
- const btGImpactShapeInterface * shape0,
- const btGImpactShapeInterface * shape1)
+ const btCollisionObjectWrapper* body0Wrap,
+ const btCollisionObjectWrapper* body1Wrap,
+ const btGImpactShapeInterface* shape0,
+ const btGImpactShapeInterface* shape1)
{
-
- if(shape0->getGImpactShapeType()==CONST_GIMPACT_TRIMESH_SHAPE)
+ if (shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE)
{
- const btGImpactMeshShape * meshshape0 = static_cast<const btGImpactMeshShape *>(shape0);
+ const btGImpactMeshShape* meshshape0 = static_cast<const btGImpactMeshShape*>(shape0);
m_part0 = meshshape0->getMeshPartCount();
- while(m_part0--)
+ while (m_part0--)
{
- gimpact_vs_gimpact(body0Wrap,body1Wrap,meshshape0->getMeshPart(m_part0),shape1);
+ gimpact_vs_gimpact(body0Wrap, body1Wrap, meshshape0->getMeshPart(m_part0), shape1);
}
return;
}
- if(shape1->getGImpactShapeType()==CONST_GIMPACT_TRIMESH_SHAPE)
+ if (shape1->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE)
{
- const btGImpactMeshShape * meshshape1 = static_cast<const btGImpactMeshShape *>(shape1);
+ const btGImpactMeshShape* meshshape1 = static_cast<const btGImpactMeshShape*>(shape1);
m_part1 = meshshape1->getMeshPartCount();
- while(m_part1--)
+ while (m_part1--)
{
-
- gimpact_vs_gimpact(body0Wrap,body1Wrap,shape0,meshshape1->getMeshPart(m_part1));
-
+ gimpact_vs_gimpact(body0Wrap, body1Wrap, shape0, meshshape1->getMeshPart(m_part1));
}
return;
}
-
btTransform orgtrans0 = body0Wrap->getWorldTransform();
btTransform orgtrans1 = body1Wrap->getWorldTransform();
btPairSet pairset;
- gimpact_vs_gimpact_find_pairs(orgtrans0,orgtrans1,shape0,shape1,pairset);
+ gimpact_vs_gimpact_find_pairs(orgtrans0, orgtrans1, shape0, shape1, pairset);
- if(pairset.size()== 0) return;
+ if (pairset.size() == 0) return;
- if(shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART &&
+ if (shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART &&
shape1->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART)
{
- const btGImpactMeshShapePart * shapepart0 = static_cast<const btGImpactMeshShapePart * >(shape0);
- const btGImpactMeshShapePart * shapepart1 = static_cast<const btGImpactMeshShapePart * >(shape1);
- //specialized function
- #ifdef BULLET_TRIANGLE_COLLISION
- collide_gjk_triangles(body0Wrap,body1Wrap,shapepart0,shapepart1,&pairset[0].m_index1,pairset.size());
- #else
- collide_sat_triangles(body0Wrap,body1Wrap,shapepart0,shapepart1,&pairset[0].m_index1,pairset.size());
- #endif
+ const btGImpactMeshShapePart* shapepart0 = static_cast<const btGImpactMeshShapePart*>(shape0);
+ const btGImpactMeshShapePart* shapepart1 = static_cast<const btGImpactMeshShapePart*>(shape1);
+//specialized function
+#ifdef BULLET_TRIANGLE_COLLISION
+ collide_gjk_triangles(body0Wrap, body1Wrap, shapepart0, shapepart1, &pairset[0].m_index1, pairset.size());
+#else
+ collide_sat_triangles(body0Wrap, body1Wrap, shapepart0, shapepart1, &pairset[0].m_index1, pairset.size());
+#endif
return;
}
@@ -530,32 +475,32 @@ void btGImpactCollisionAlgorithm::gimpact_vs_gimpact(
bool child_has_transform1 = shape1->childrenHasTransform();
int i = pairset.size();
- while(i--)
+ while (i--)
{
- GIM_PAIR * pair = &pairset[i];
+ GIM_PAIR* pair = &pairset[i];
m_triface0 = pair->m_index1;
m_triface1 = pair->m_index2;
- const btCollisionShape * colshape0 = retriever0.getChildShape(m_triface0);
- const btCollisionShape * colshape1 = retriever1.getChildShape(m_triface1);
+ const btCollisionShape* colshape0 = retriever0.getChildShape(m_triface0);
+ const btCollisionShape* colshape1 = retriever1.getChildShape(m_triface1);
btTransform tr0 = body0Wrap->getWorldTransform();
btTransform tr1 = body1Wrap->getWorldTransform();
- if(child_has_transform0)
+ if (child_has_transform0)
{
- tr0 = orgtrans0*shape0->getChildTransform(m_triface0);
+ tr0 = orgtrans0 * shape0->getChildTransform(m_triface0);
}
- if(child_has_transform1)
+ if (child_has_transform1)
{
- tr1 = orgtrans1*shape1->getChildTransform(m_triface1);
+ tr1 = orgtrans1 * shape1->getChildTransform(m_triface1);
}
- btCollisionObjectWrapper ob0(body0Wrap,colshape0,body0Wrap->getCollisionObject(),tr0,m_part0,m_triface0);
- btCollisionObjectWrapper ob1(body1Wrap,colshape1,body1Wrap->getCollisionObject(),tr1,m_part1,m_triface1);
+ btCollisionObjectWrapper ob0(body0Wrap, colshape0, body0Wrap->getCollisionObject(), tr0, m_part0, m_triface0);
+ btCollisionObjectWrapper ob1(body1Wrap, colshape1, body1Wrap->getCollisionObject(), tr1, m_part1, m_triface1);
//collide two convex shapes
- convex_vs_convex_collision(&ob0,&ob1,colshape0,colshape1);
+ convex_vs_convex_collision(&ob0, &ob1, colshape0, colshape1);
}
shape0->unlockChildShapes();
@@ -563,159 +508,149 @@ void btGImpactCollisionAlgorithm::gimpact_vs_gimpact(
}
void btGImpactCollisionAlgorithm::gimpact_vs_shape(const btCollisionObjectWrapper* body0Wrap,
- const btCollisionObjectWrapper * body1Wrap,
- const btGImpactShapeInterface * shape0,
- const btCollisionShape * shape1,bool swapped)
+ const btCollisionObjectWrapper* body1Wrap,
+ const btGImpactShapeInterface* shape0,
+ const btCollisionShape* shape1, bool swapped)
{
- if(shape0->getGImpactShapeType()==CONST_GIMPACT_TRIMESH_SHAPE)
+ if (shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE)
{
- const btGImpactMeshShape * meshshape0 = static_cast<const btGImpactMeshShape *>(shape0);
+ const btGImpactMeshShape* meshshape0 = static_cast<const btGImpactMeshShape*>(shape0);
int& part = swapped ? m_part1 : m_part0;
part = meshshape0->getMeshPartCount();
- while(part--)
+ while (part--)
{
-
gimpact_vs_shape(body0Wrap,
- body1Wrap,
- meshshape0->getMeshPart(part),
- shape1,swapped);
-
+ body1Wrap,
+ meshshape0->getMeshPart(part),
+ shape1, swapped);
}
return;
}
- #ifdef GIMPACT_VS_PLANE_COLLISION
- if(shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART &&
+#ifdef GIMPACT_VS_PLANE_COLLISION
+ if (shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART &&
shape1->getShapeType() == STATIC_PLANE_PROXYTYPE)
{
- const btGImpactMeshShapePart * shapepart = static_cast<const btGImpactMeshShapePart *>(shape0);
- const btStaticPlaneShape * planeshape = static_cast<const btStaticPlaneShape * >(shape1);
- gimpacttrimeshpart_vs_plane_collision(body0Wrap,body1Wrap,shapepart,planeshape,swapped);
+ const btGImpactMeshShapePart* shapepart = static_cast<const btGImpactMeshShapePart*>(shape0);
+ const btStaticPlaneShape* planeshape = static_cast<const btStaticPlaneShape*>(shape1);
+ gimpacttrimeshpart_vs_plane_collision(body0Wrap, body1Wrap, shapepart, planeshape, swapped);
return;
}
- #endif
-
+#endif
-
- if(shape1->isCompound())
+ if (shape1->isCompound())
{
- const btCompoundShape * compoundshape = static_cast<const btCompoundShape *>(shape1);
- gimpact_vs_compoundshape(body0Wrap,body1Wrap,shape0,compoundshape,swapped);
+ const btCompoundShape* compoundshape = static_cast<const btCompoundShape*>(shape1);
+ gimpact_vs_compoundshape(body0Wrap, body1Wrap, shape0, compoundshape, swapped);
return;
}
- else if(shape1->isConcave())
+ else if (shape1->isConcave())
{
- const btConcaveShape * concaveshape = static_cast<const btConcaveShape *>(shape1);
- gimpact_vs_concave(body0Wrap,body1Wrap,shape0,concaveshape,swapped);
+ const btConcaveShape* concaveshape = static_cast<const btConcaveShape*>(shape1);
+ gimpact_vs_concave(body0Wrap, body1Wrap, shape0, concaveshape, swapped);
return;
}
-
btTransform orgtrans0 = body0Wrap->getWorldTransform();
btTransform orgtrans1 = body1Wrap->getWorldTransform();
btAlignedObjectArray<int> collided_results;
- gimpact_vs_shape_find_pairs(orgtrans0,orgtrans1,shape0,shape1,collided_results);
-
- if(collided_results.size() == 0) return;
+ gimpact_vs_shape_find_pairs(orgtrans0, orgtrans1, shape0, shape1, collided_results);
+ if (collided_results.size() == 0) return;
shape0->lockChildShapes();
GIM_ShapeRetriever retriever0(shape0);
-
bool child_has_transform0 = shape0->childrenHasTransform();
-
int i = collided_results.size();
- while(i--)
+ while (i--)
{
int child_index = collided_results[i];
- if(swapped)
- m_triface1 = child_index;
- else
- m_triface0 = child_index;
+ if (swapped)
+ m_triface1 = child_index;
+ else
+ m_triface0 = child_index;
- const btCollisionShape * colshape0 = retriever0.getChildShape(child_index);
+ const btCollisionShape* colshape0 = retriever0.getChildShape(child_index);
btTransform tr0 = body0Wrap->getWorldTransform();
- if(child_has_transform0)
+ if (child_has_transform0)
{
- tr0 = orgtrans0*shape0->getChildTransform(child_index);
+ tr0 = orgtrans0 * shape0->getChildTransform(child_index);
}
- btCollisionObjectWrapper ob0(body0Wrap,colshape0,body0Wrap->getCollisionObject(),body0Wrap->getWorldTransform(),m_part0,m_triface0);
+ btCollisionObjectWrapper ob0(body0Wrap, colshape0, body0Wrap->getCollisionObject(), body0Wrap->getWorldTransform(), m_part0, m_triface0);
const btCollisionObjectWrapper* prevObj0 = m_resultOut->getBody0Wrap();
-
- if (m_resultOut->getBody0Wrap()->getCollisionObject()==ob0.getCollisionObject())
+
+ if (m_resultOut->getBody0Wrap()->getCollisionObject() == ob0.getCollisionObject())
{
m_resultOut->setBody0Wrap(&ob0);
- } else
+ }
+ else
{
m_resultOut->setBody1Wrap(&ob0);
}
//collide two shapes
- if(swapped)
+ if (swapped)
{
-
- shape_vs_shape_collision(body1Wrap,&ob0,shape1,colshape0);
+ shape_vs_shape_collision(body1Wrap, &ob0, shape1, colshape0);
}
else
{
-
- shape_vs_shape_collision(&ob0,body1Wrap,colshape0,shape1);
+ shape_vs_shape_collision(&ob0, body1Wrap, colshape0, shape1);
}
m_resultOut->setBody0Wrap(prevObj0);
-
}
shape0->unlockChildShapes();
-
}
void btGImpactCollisionAlgorithm::gimpact_vs_compoundshape(const btCollisionObjectWrapper* body0Wrap,
- const btCollisionObjectWrapper* body1Wrap,
- const btGImpactShapeInterface * shape0,
- const btCompoundShape * shape1,bool swapped)
+ const btCollisionObjectWrapper* body1Wrap,
+ const btGImpactShapeInterface* shape0,
+ const btCompoundShape* shape1, bool swapped)
{
btTransform orgtrans1 = body1Wrap->getWorldTransform();
int i = shape1->getNumChildShapes();
- while(i--)
+ while (i--)
{
+ const btCollisionShape* colshape1 = shape1->getChildShape(i);
+ btTransform childtrans1 = orgtrans1 * shape1->getChildTransform(i);
- const btCollisionShape * colshape1 = shape1->getChildShape(i);
- btTransform childtrans1 = orgtrans1*shape1->getChildTransform(i);
+ btCollisionObjectWrapper ob1(body1Wrap, colshape1, body1Wrap->getCollisionObject(), childtrans1, -1, i);
- btCollisionObjectWrapper ob1(body1Wrap,colshape1,body1Wrap->getCollisionObject(),childtrans1,-1,i);
-
const btCollisionObjectWrapper* tmp = 0;
- if (m_resultOut->getBody0Wrap()->getCollisionObject()==ob1.getCollisionObject())
+ if (m_resultOut->getBody0Wrap()->getCollisionObject() == ob1.getCollisionObject())
{
tmp = m_resultOut->getBody0Wrap();
m_resultOut->setBody0Wrap(&ob1);
- } else
+ }
+ else
{
tmp = m_resultOut->getBody1Wrap();
m_resultOut->setBody1Wrap(&ob1);
}
//collide child shape
gimpact_vs_shape(body0Wrap, &ob1,
- shape0,colshape1,swapped);
+ shape0, colshape1, swapped);
- if (m_resultOut->getBody0Wrap()->getCollisionObject()==ob1.getCollisionObject())
+ if (m_resultOut->getBody0Wrap()->getCollisionObject() == ob1.getCollisionObject())
{
m_resultOut->setBody0Wrap(tmp);
- } else
+ }
+ else
{
m_resultOut->setBody1Wrap(tmp);
}
@@ -723,27 +658,25 @@ void btGImpactCollisionAlgorithm::gimpact_vs_compoundshape(const btCollisionObje
}
void btGImpactCollisionAlgorithm::gimpacttrimeshpart_vs_plane_collision(
- const btCollisionObjectWrapper * body0Wrap,
- const btCollisionObjectWrapper * body1Wrap,
- const btGImpactMeshShapePart * shape0,
- const btStaticPlaneShape * shape1,bool swapped)
+ const btCollisionObjectWrapper* body0Wrap,
+ const btCollisionObjectWrapper* body1Wrap,
+ const btGImpactMeshShapePart* shape0,
+ const btStaticPlaneShape* shape1, bool swapped)
{
-
-
btTransform orgtrans0 = body0Wrap->getWorldTransform();
btTransform orgtrans1 = body1Wrap->getWorldTransform();
- const btPlaneShape * planeshape = static_cast<const btPlaneShape *>(shape1);
+ const btPlaneShape* planeshape = static_cast<const btPlaneShape*>(shape1);
btVector4 plane;
- planeshape->get_plane_equation_transformed(orgtrans1,plane);
+ planeshape->get_plane_equation_transformed(orgtrans1, plane);
//test box against plane
btAABB tribox;
- shape0->getAabb(orgtrans0,tribox.m_min,tribox.m_max);
+ shape0->getAabb(orgtrans0, tribox.m_min, tribox.m_max);
tribox.increment_margin(planeshape->getMargin());
- if( tribox.plane_classify(plane)!= BT_CONST_COLLIDE_PLANE) return;
+ if (tribox.plane_classify(plane) != BT_CONST_COLLIDE_PLANE) return;
shape0->lockChildShapes();
@@ -751,28 +684,28 @@ void btGImpactCollisionAlgorithm::gimpacttrimeshpart_vs_plane_collision(
btVector3 vertex;
int vi = shape0->getVertexCount();
- while(vi--)
+ while (vi--)
{
- shape0->getVertex(vi,vertex);
+ shape0->getVertex(vi, vertex);
vertex = orgtrans0(vertex);
btScalar distance = vertex.dot(plane) - plane[3] - margin;
- if(distance<0.0)//add contact
+ if (distance < 0.0) //add contact
{
- if(swapped)
+ if (swapped)
{
addContactPoint(body1Wrap, body0Wrap,
- vertex,
- -plane,
- distance);
+ vertex,
+ -plane,
+ distance);
}
else
{
addContactPoint(body0Wrap, body1Wrap,
- vertex,
- plane,
- distance);
+ vertex,
+ plane,
+ distance);
}
}
}
@@ -780,69 +713,64 @@ void btGImpactCollisionAlgorithm::gimpacttrimeshpart_vs_plane_collision(
shape0->unlockChildShapes();
}
-
-
-
-class btGImpactTriangleCallback: public btTriangleCallback
+class btGImpactTriangleCallback : public btTriangleCallback
{
public:
- btGImpactCollisionAlgorithm * algorithm;
- const btCollisionObjectWrapper * body0Wrap;
- const btCollisionObjectWrapper * body1Wrap;
- const btGImpactShapeInterface * gimpactshape0;
+ btGImpactCollisionAlgorithm* algorithm;
+ const btCollisionObjectWrapper* body0Wrap;
+ const btCollisionObjectWrapper* body1Wrap;
+ const btGImpactShapeInterface* gimpactshape0;
bool swapped;
btScalar margin;
virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
{
- btTriangleShapeEx tri1(triangle[0],triangle[1],triangle[2]);
+ btTriangleShapeEx tri1(triangle[0], triangle[1], triangle[2]);
tri1.setMargin(margin);
- if(swapped)
- {
- algorithm->setPart0(partId);
- algorithm->setFace0(triangleIndex);
- }
- else
- {
- algorithm->setPart1(partId);
- algorithm->setFace1(triangleIndex);
- }
-
- btCollisionObjectWrapper ob1Wrap(body1Wrap,&tri1,body1Wrap->getCollisionObject(),body1Wrap->getWorldTransform(),partId,triangleIndex);
- const btCollisionObjectWrapper * tmp = 0;
-
- if (algorithm->internalGetResultOut()->getBody0Wrap()->getCollisionObject()==ob1Wrap.getCollisionObject())
+ if (swapped)
+ {
+ algorithm->setPart0(partId);
+ algorithm->setFace0(triangleIndex);
+ }
+ else
+ {
+ algorithm->setPart1(partId);
+ algorithm->setFace1(triangleIndex);
+ }
+
+ btCollisionObjectWrapper ob1Wrap(body1Wrap, &tri1, body1Wrap->getCollisionObject(), body1Wrap->getWorldTransform(), partId, triangleIndex);
+ const btCollisionObjectWrapper* tmp = 0;
+
+ if (algorithm->internalGetResultOut()->getBody0Wrap()->getCollisionObject() == ob1Wrap.getCollisionObject())
{
tmp = algorithm->internalGetResultOut()->getBody0Wrap();
algorithm->internalGetResultOut()->setBody0Wrap(&ob1Wrap);
- } else
+ }
+ else
{
tmp = algorithm->internalGetResultOut()->getBody1Wrap();
algorithm->internalGetResultOut()->setBody1Wrap(&ob1Wrap);
}
-
+
algorithm->gimpact_vs_shape(
- body0Wrap,&ob1Wrap,gimpactshape0,&tri1,swapped);
+ body0Wrap, &ob1Wrap, gimpactshape0, &tri1, swapped);
- if (algorithm->internalGetResultOut()->getBody0Wrap()->getCollisionObject()==ob1Wrap.getCollisionObject())
+ if (algorithm->internalGetResultOut()->getBody0Wrap()->getCollisionObject() == ob1Wrap.getCollisionObject())
{
algorithm->internalGetResultOut()->setBody0Wrap(tmp);
- } else
+ }
+ else
{
algorithm->internalGetResultOut()->setBody1Wrap(tmp);
}
-
}
};
-
-
-
void btGImpactCollisionAlgorithm::gimpact_vs_concave(
- const btCollisionObjectWrapper* body0Wrap,
- const btCollisionObjectWrapper * body1Wrap,
- const btGImpactShapeInterface * shape0,
- const btConcaveShape * shape1,bool swapped)
+ const btCollisionObjectWrapper* body0Wrap,
+ const btCollisionObjectWrapper* body1Wrap,
+ const btGImpactShapeInterface* shape0,
+ const btConcaveShape* shape1, bool swapped)
{
//create the callback
btGImpactTriangleCallback tricallback;
@@ -858,75 +786,71 @@ void btGImpactCollisionAlgorithm::gimpact_vs_concave(
gimpactInConcaveSpace = body1Wrap->getWorldTransform().inverse() * body0Wrap->getWorldTransform();
- btVector3 minAABB,maxAABB;
- shape0->getAabb(gimpactInConcaveSpace,minAABB,maxAABB);
-
- shape1->processAllTriangles(&tricallback,minAABB,maxAABB);
+ btVector3 minAABB, maxAABB;
+ shape0->getAabb(gimpactInConcaveSpace, minAABB, maxAABB);
+ shape1->processAllTriangles(&tricallback, minAABB, maxAABB);
}
-
-
-void btGImpactCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+void btGImpactCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
{
- clearCache();
+ clearCache();
- m_resultOut = resultOut;
+ m_resultOut = resultOut;
m_dispatchInfo = &dispatchInfo;
- const btGImpactShapeInterface * gimpactshape0;
- const btGImpactShapeInterface * gimpactshape1;
+ const btGImpactShapeInterface* gimpactshape0;
+ const btGImpactShapeInterface* gimpactshape1;
- if (body0Wrap->getCollisionShape()->getShapeType()==GIMPACT_SHAPE_PROXYTYPE)
+ if (body0Wrap->getCollisionShape()->getShapeType() == GIMPACT_SHAPE_PROXYTYPE)
{
- gimpactshape0 = static_cast<const btGImpactShapeInterface *>(body0Wrap->getCollisionShape());
+ gimpactshape0 = static_cast<const btGImpactShapeInterface*>(body0Wrap->getCollisionShape());
- if( body1Wrap->getCollisionShape()->getShapeType()==GIMPACT_SHAPE_PROXYTYPE )
+ if (body1Wrap->getCollisionShape()->getShapeType() == GIMPACT_SHAPE_PROXYTYPE)
{
- gimpactshape1 = static_cast<const btGImpactShapeInterface *>(body1Wrap->getCollisionShape());
+ gimpactshape1 = static_cast<const btGImpactShapeInterface*>(body1Wrap->getCollisionShape());
- gimpact_vs_gimpact(body0Wrap,body1Wrap,gimpactshape0,gimpactshape1);
+ gimpact_vs_gimpact(body0Wrap, body1Wrap, gimpactshape0, gimpactshape1);
}
else
{
- gimpact_vs_shape(body0Wrap,body1Wrap,gimpactshape0,body1Wrap->getCollisionShape(),false);
+ gimpact_vs_shape(body0Wrap, body1Wrap, gimpactshape0, body1Wrap->getCollisionShape(), false);
}
-
}
- else if (body1Wrap->getCollisionShape()->getShapeType()==GIMPACT_SHAPE_PROXYTYPE )
+ else if (body1Wrap->getCollisionShape()->getShapeType() == GIMPACT_SHAPE_PROXYTYPE)
{
- gimpactshape1 = static_cast<const btGImpactShapeInterface *>(body1Wrap->getCollisionShape());
+ gimpactshape1 = static_cast<const btGImpactShapeInterface*>(body1Wrap->getCollisionShape());
- gimpact_vs_shape(body1Wrap,body0Wrap,gimpactshape1,body0Wrap->getCollisionShape(),true);
+ gimpact_vs_shape(body1Wrap, body0Wrap, gimpactshape1, body0Wrap->getCollisionShape(), true);
}
-}
+ // Ensure that gContactProcessedCallback is called for concave shapes.
+ if (getLastManifold())
+ {
+ m_resultOut->refreshContactPoints();
+ }
+}
-btScalar btGImpactCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+btScalar btGImpactCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
{
return 1.f;
-
}
///////////////////////////////////// REGISTERING ALGORITHM //////////////////////////////////////////////
-
-
//! Use this function for register the algorithm externally
-void btGImpactCollisionAlgorithm::registerAlgorithm(btCollisionDispatcher * dispatcher)
+void btGImpactCollisionAlgorithm::registerAlgorithm(btCollisionDispatcher* dispatcher)
{
-
static btGImpactCollisionAlgorithm::CreateFunc s_gimpact_cf;
int i;
- for ( i = 0;i < MAX_BROADPHASE_COLLISION_TYPES ;i++ )
+ for (i = 0; i < MAX_BROADPHASE_COLLISION_TYPES; i++)
{
- dispatcher->registerCollisionCreateFunc(GIMPACT_SHAPE_PROXYTYPE,i ,&s_gimpact_cf);
+ dispatcher->registerCollisionCreateFunc(GIMPACT_SHAPE_PROXYTYPE, i, &s_gimpact_cf);
}
- for ( i = 0;i < MAX_BROADPHASE_COLLISION_TYPES ;i++ )
+ for (i = 0; i < MAX_BROADPHASE_COLLISION_TYPES; i++)
{
- dispatcher->registerCollisionCreateFunc(i,GIMPACT_SHAPE_PROXYTYPE ,&s_gimpact_cf);
+ dispatcher->registerCollisionCreateFunc(i, GIMPACT_SHAPE_PROXYTYPE, &s_gimpact_cf);
}
-
}
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h
index 3e5675f729..a368c8a0c0 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h
+++ b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h
@@ -42,7 +42,6 @@ class btDispatcher;
#include "LinearMath/btIDebugDraw.h"
#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
-
//! Collision Algorithm for GImpact Shapes
/*!
For register this algorithm in Bullet, proceed as following:
@@ -54,36 +53,35 @@ btGImpactCollisionAlgorithm::registerAlgorithm(dispatcher);
class btGImpactCollisionAlgorithm : public btActivatingCollisionAlgorithm
{
protected:
- btCollisionAlgorithm * m_convex_algorithm;
- btPersistentManifold * m_manifoldPtr;
+ btCollisionAlgorithm* m_convex_algorithm;
+ btPersistentManifold* m_manifoldPtr;
btManifoldResult* m_resultOut;
- const btDispatcherInfo * m_dispatchInfo;
+ const btDispatcherInfo* m_dispatchInfo;
int m_triface0;
int m_part0;
int m_triface1;
int m_part1;
-
//! Creates a new contact point
- SIMD_FORCE_INLINE btPersistentManifold* newContactManifold(const btCollisionObject* body0,const btCollisionObject* body1)
+ SIMD_FORCE_INLINE btPersistentManifold* newContactManifold(const btCollisionObject* body0, const btCollisionObject* body1)
{
- m_manifoldPtr = m_dispatcher->getNewManifold(body0,body1);
+ m_manifoldPtr = m_dispatcher->getNewManifold(body0, body1);
return m_manifoldPtr;
}
SIMD_FORCE_INLINE void destroyConvexAlgorithm()
{
- if(m_convex_algorithm)
+ if (m_convex_algorithm)
{
m_convex_algorithm->~btCollisionAlgorithm();
- m_dispatcher->freeCollisionAlgorithm( m_convex_algorithm);
+ m_dispatcher->freeCollisionAlgorithm(m_convex_algorithm);
m_convex_algorithm = NULL;
}
}
SIMD_FORCE_INLINE void destroyContactManifolds()
{
- if(m_manifoldPtr == NULL) return;
+ if (m_manifoldPtr == NULL) return;
m_dispatcher->releaseManifold(m_manifoldPtr);
m_manifoldPtr = NULL;
}
@@ -104,207 +102,187 @@ protected:
return m_manifoldPtr;
}
-
// Call before process collision
- SIMD_FORCE_INLINE void checkManifold(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ SIMD_FORCE_INLINE void checkManifold(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
{
- if(getLastManifold() == 0)
+ if (getLastManifold() == 0)
{
- newContactManifold(body0Wrap->getCollisionObject(),body1Wrap->getCollisionObject());
+ newContactManifold(body0Wrap->getCollisionObject(), body1Wrap->getCollisionObject());
}
m_resultOut->setPersistentManifold(getLastManifold());
}
// Call before process collision
- SIMD_FORCE_INLINE btCollisionAlgorithm * newAlgorithm(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ SIMD_FORCE_INLINE btCollisionAlgorithm* newAlgorithm(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
{
- checkManifold(body0Wrap,body1Wrap);
+ checkManifold(body0Wrap, body1Wrap);
- btCollisionAlgorithm * convex_algorithm = m_dispatcher->findAlgorithm(
- body0Wrap,body1Wrap,getLastManifold(), BT_CONTACT_POINT_ALGORITHMS);
- return convex_algorithm ;
+ btCollisionAlgorithm* convex_algorithm = m_dispatcher->findAlgorithm(
+ body0Wrap, body1Wrap, getLastManifold(), BT_CONTACT_POINT_ALGORITHMS);
+ return convex_algorithm;
}
// Call before process collision
- SIMD_FORCE_INLINE void checkConvexAlgorithm(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ SIMD_FORCE_INLINE void checkConvexAlgorithm(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
{
- if(m_convex_algorithm) return;
- m_convex_algorithm = newAlgorithm(body0Wrap,body1Wrap);
+ if (m_convex_algorithm) return;
+ m_convex_algorithm = newAlgorithm(body0Wrap, body1Wrap);
}
+ void addContactPoint(const btCollisionObjectWrapper* body0Wrap,
+ const btCollisionObjectWrapper* body1Wrap,
+ const btVector3& point,
+ const btVector3& normal,
+ btScalar distance);
-
-
- void addContactPoint(const btCollisionObjectWrapper * body0Wrap,
- const btCollisionObjectWrapper * body1Wrap,
- const btVector3 & point,
- const btVector3 & normal,
- btScalar distance);
-
-//! Collision routines
-//!@{
+ //! Collision routines
+ //!@{
void collide_gjk_triangles(const btCollisionObjectWrapper* body0Wrap,
- const btCollisionObjectWrapper* body1Wrap,
- const btGImpactMeshShapePart * shape0,
- const btGImpactMeshShapePart * shape1,
- const int * pairs, int pair_count);
+ const btCollisionObjectWrapper* body1Wrap,
+ const btGImpactMeshShapePart* shape0,
+ const btGImpactMeshShapePart* shape1,
+ const int* pairs, int pair_count);
void collide_sat_triangles(const btCollisionObjectWrapper* body0Wrap,
- const btCollisionObjectWrapper* body1Wrap,
- const btGImpactMeshShapePart * shape0,
- const btGImpactMeshShapePart * shape1,
- const int * pairs, int pair_count);
-
-
-
+ const btCollisionObjectWrapper* body1Wrap,
+ const btGImpactMeshShapePart* shape0,
+ const btGImpactMeshShapePart* shape1,
+ const int* pairs, int pair_count);
void shape_vs_shape_collision(
- const btCollisionObjectWrapper* body0,
- const btCollisionObjectWrapper* body1,
- const btCollisionShape * shape0,
- const btCollisionShape * shape1);
+ const btCollisionObjectWrapper* body0,
+ const btCollisionObjectWrapper* body1,
+ const btCollisionShape* shape0,
+ const btCollisionShape* shape1);
void convex_vs_convex_collision(const btCollisionObjectWrapper* body0Wrap,
- const btCollisionObjectWrapper* body1Wrap,
- const btCollisionShape* shape0,
- const btCollisionShape* shape1);
-
-
+ const btCollisionObjectWrapper* body1Wrap,
+ const btCollisionShape* shape0,
+ const btCollisionShape* shape1);
void gimpact_vs_gimpact_find_pairs(
- const btTransform & trans0,
- const btTransform & trans1,
- const btGImpactShapeInterface * shape0,
- const btGImpactShapeInterface * shape1,btPairSet & pairset);
+ const btTransform& trans0,
+ const btTransform& trans1,
+ const btGImpactShapeInterface* shape0,
+ const btGImpactShapeInterface* shape1, btPairSet& pairset);
void gimpact_vs_shape_find_pairs(
- const btTransform & trans0,
- const btTransform & trans1,
- const btGImpactShapeInterface * shape0,
- const btCollisionShape * shape1,
- btAlignedObjectArray<int> & collided_primitives);
-
+ const btTransform& trans0,
+ const btTransform& trans1,
+ const btGImpactShapeInterface* shape0,
+ const btCollisionShape* shape1,
+ btAlignedObjectArray<int>& collided_primitives);
void gimpacttrimeshpart_vs_plane_collision(
- const btCollisionObjectWrapper * body0Wrap,
- const btCollisionObjectWrapper * body1Wrap,
- const btGImpactMeshShapePart * shape0,
- const btStaticPlaneShape * shape1,bool swapped);
-
+ const btCollisionObjectWrapper* body0Wrap,
+ const btCollisionObjectWrapper* body1Wrap,
+ const btGImpactMeshShapePart* shape0,
+ const btStaticPlaneShape* shape1, bool swapped);
public:
-
- btGImpactCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
+ btGImpactCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap);
virtual ~btGImpactCollisionAlgorithm();
- virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
- btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
- virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr)
manifoldArray.push_back(m_manifoldPtr);
}
- btManifoldResult* internalGetResultOut()
+ btManifoldResult* internalGetResultOut()
{
return m_resultOut;
}
- struct CreateFunc :public btCollisionAlgorithmCreateFunc
+ struct CreateFunc : public btCollisionAlgorithmCreateFunc
{
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btGImpactCollisionAlgorithm));
- return new(mem) btGImpactCollisionAlgorithm(ci,body0Wrap,body1Wrap);
+ return new (mem) btGImpactCollisionAlgorithm(ci, body0Wrap, body1Wrap);
}
};
//! Use this function for register the algorithm externally
- static void registerAlgorithm(btCollisionDispatcher * dispatcher);
+ static void registerAlgorithm(btCollisionDispatcher* dispatcher);
#ifdef TRI_COLLISION_PROFILING
//! Gets the average time in miliseconds of tree collisions
static float getAverageTreeCollisionTime();
//! Gets the average time in miliseconds of triangle collisions
static float getAverageTriangleCollisionTime();
-#endif //TRI_COLLISION_PROFILING
+#endif //TRI_COLLISION_PROFILING
//! Collides two gimpact shapes
/*!
\pre shape0 and shape1 couldn't be btGImpactMeshShape objects
*/
-
void gimpact_vs_gimpact(const btCollisionObjectWrapper* body0Wrap,
- const btCollisionObjectWrapper * body1Wrap,
- const btGImpactShapeInterface * shape0,
- const btGImpactShapeInterface * shape1);
+ const btCollisionObjectWrapper* body1Wrap,
+ const btGImpactShapeInterface* shape0,
+ const btGImpactShapeInterface* shape1);
void gimpact_vs_shape(const btCollisionObjectWrapper* body0Wrap,
- const btCollisionObjectWrapper* body1Wrap,
- const btGImpactShapeInterface * shape0,
- const btCollisionShape * shape1,bool swapped);
+ const btCollisionObjectWrapper* body1Wrap,
+ const btGImpactShapeInterface* shape0,
+ const btCollisionShape* shape1, bool swapped);
- void gimpact_vs_compoundshape(const btCollisionObjectWrapper * body0Wrap,
- const btCollisionObjectWrapper * body1Wrap,
- const btGImpactShapeInterface * shape0,
- const btCompoundShape * shape1,bool swapped);
+ void gimpact_vs_compoundshape(const btCollisionObjectWrapper* body0Wrap,
+ const btCollisionObjectWrapper* body1Wrap,
+ const btGImpactShapeInterface* shape0,
+ const btCompoundShape* shape1, bool swapped);
void gimpact_vs_concave(
- const btCollisionObjectWrapper * body0Wrap,
- const btCollisionObjectWrapper * body1Wrap,
- const btGImpactShapeInterface * shape0,
- const btConcaveShape * shape1,bool swapped);
-
-
-
-
- /// Accessor/Mutator pairs for Part and triangleID
- void setFace0(int value)
- {
- m_triface0 = value;
- }
- int getFace0()
- {
- return m_triface0;
- }
- void setFace1(int value)
- {
- m_triface1 = value;
- }
- int getFace1()
- {
- return m_triface1;
- }
- void setPart0(int value)
- {
- m_part0 = value;
- }
- int getPart0()
- {
- return m_part0;
- }
- void setPart1(int value)
- {
- m_part1 = value;
- }
- int getPart1()
- {
- return m_part1;
- }
+ const btCollisionObjectWrapper* body0Wrap,
+ const btCollisionObjectWrapper* body1Wrap,
+ const btGImpactShapeInterface* shape0,
+ const btConcaveShape* shape1, bool swapped);
+ /// Accessor/Mutator pairs for Part and triangleID
+ void setFace0(int value)
+ {
+ m_triface0 = value;
+ }
+ int getFace0()
+ {
+ return m_triface0;
+ }
+ void setFace1(int value)
+ {
+ m_triface1 = value;
+ }
+ int getFace1()
+ {
+ return m_triface1;
+ }
+ void setPart0(int value)
+ {
+ m_part0 = value;
+ }
+ int getPart0()
+ {
+ return m_part0;
+ }
+ void setPart1(int value)
+ {
+ m_part1 = value;
+ }
+ int getPart1()
+ {
+ return m_part1;
+ }
};
-
//algorithm details
//#define BULLET_TRIANGLE_COLLISION 1
#define GIMPACT_VS_PLANE_COLLISION 1
-
-
-#endif //BT_GIMPACT_BVH_CONCAVE_COLLISION_ALGORITHM_H
+#endif //BT_GIMPACT_BVH_CONCAVE_COLLISION_ALGORITHM_H
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactMassUtil.h b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactMassUtil.h
index 2543aefcfc..1cde46ed8b 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactMassUtil.h
+++ b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactMassUtil.h
@@ -21,40 +21,36 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#ifndef GIMPACT_MASS_UTIL_H
#define GIMPACT_MASS_UTIL_H
#include "LinearMath/btTransform.h"
-
-
SIMD_FORCE_INLINE btVector3 gim_inertia_add_transformed(
- const btVector3 & source_inertia, const btVector3 & added_inertia, const btTransform & transform)
+ const btVector3& source_inertia, const btVector3& added_inertia, const btTransform& transform)
{
- btMatrix3x3 rotatedTensor = transform.getBasis().scaled(added_inertia) * transform.getBasis().transpose();
+ btMatrix3x3 rotatedTensor = transform.getBasis().scaled(added_inertia) * transform.getBasis().transpose();
btScalar x2 = transform.getOrigin()[0];
- x2*= x2;
+ x2 *= x2;
btScalar y2 = transform.getOrigin()[1];
- y2*= y2;
+ y2 *= y2;
btScalar z2 = transform.getOrigin()[2];
- z2*= z2;
+ z2 *= z2;
- btScalar ix = rotatedTensor[0][0]*(y2+z2);
- btScalar iy = rotatedTensor[1][1]*(x2+z2);
- btScalar iz = rotatedTensor[2][2]*(x2+y2);
+ btScalar ix = rotatedTensor[0][0] * (y2 + z2);
+ btScalar iy = rotatedTensor[1][1] * (x2 + z2);
+ btScalar iz = rotatedTensor[2][2] * (x2 + y2);
- return btVector3(source_inertia[0]+ix,source_inertia[1]+iy,source_inertia[2] + iz);
+ return btVector3(source_inertia[0] + ix, source_inertia[1] + iy, source_inertia[2] + iz);
}
-SIMD_FORCE_INLINE btVector3 gim_get_point_inertia(const btVector3 & point, btScalar mass)
+SIMD_FORCE_INLINE btVector3 gim_get_point_inertia(const btVector3& point, btScalar mass)
{
- btScalar x2 = point[0]*point[0];
- btScalar y2 = point[1]*point[1];
- btScalar z2 = point[2]*point[2];
- return btVector3(mass*(y2+z2),mass*(x2+z2),mass*(x2+y2));
+ btScalar x2 = point[0] * point[0];
+ btScalar y2 = point[1] * point[1];
+ btScalar z2 = point[2] * point[2];
+ return btVector3(mass * (y2 + z2), mass * (x2 + z2), mass * (x2 + y2));
}
-
-#endif //GIMPACT_MESH_SHAPE_H
+#endif //GIMPACT_MESH_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp
index 4528758c37..b81fc97044 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp
+++ b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp
@@ -27,11 +27,9 @@ subject to the following restrictions:
#ifdef TRI_COLLISION_PROFILING
btClock g_q_tree_clock;
-
float g_q_accum_tree_collision_time = 0;
int g_q_count_traversing = 0;
-
void bt_begin_gim02_q_tree_time()
{
g_q_tree_clock.reset();
@@ -43,11 +41,10 @@ void bt_end_gim02_q_tree_time()
g_q_count_traversing++;
}
-
//! Gets the average time in miliseconds of tree collisions
float btGImpactQuantizedBvh::getAverageTreeCollisionTime()
{
- if(g_q_count_traversing == 0) return 0;
+ if (g_q_count_traversing == 0) return 0;
float avgtime = g_q_accum_tree_collision_time;
avgtime /= (float)g_q_count_traversing;
@@ -56,99 +53,92 @@ float btGImpactQuantizedBvh::getAverageTreeCollisionTime()
g_q_count_traversing = 0;
return avgtime;
-// float avgtime = g_q_count_traversing;
-// g_q_count_traversing = 0;
-// return avgtime;
-
+ // float avgtime = g_q_count_traversing;
+ // g_q_count_traversing = 0;
+ // return avgtime;
}
-#endif //TRI_COLLISION_PROFILING
+#endif //TRI_COLLISION_PROFILING
/////////////////////// btQuantizedBvhTree /////////////////////////////////
void btQuantizedBvhTree::calc_quantization(
- GIM_BVH_DATA_ARRAY & primitive_boxes, btScalar boundMargin)
+ GIM_BVH_DATA_ARRAY& primitive_boxes, btScalar boundMargin)
{
//calc globa box
btAABB global_bound;
global_bound.invalidate();
- for (int i=0;i<primitive_boxes.size() ;i++ )
+ for (int i = 0; i < primitive_boxes.size(); i++)
{
global_bound.merge(primitive_boxes[i].m_bound);
}
bt_calc_quantization_parameters(
- m_global_bound.m_min,m_global_bound.m_max,m_bvhQuantization,global_bound.m_min,global_bound.m_max,boundMargin);
-
+ m_global_bound.m_min, m_global_bound.m_max, m_bvhQuantization, global_bound.m_min, global_bound.m_max, boundMargin);
}
-
-
int btQuantizedBvhTree::_calc_splitting_axis(
- GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex)
+ GIM_BVH_DATA_ARRAY& primitive_boxes, int startIndex, int endIndex)
{
-
int i;
- btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
- btVector3 variance(btScalar(0.),btScalar(0.),btScalar(0.));
- int numIndices = endIndex-startIndex;
+ btVector3 means(btScalar(0.), btScalar(0.), btScalar(0.));
+ btVector3 variance(btScalar(0.), btScalar(0.), btScalar(0.));
+ int numIndices = endIndex - startIndex;
- for (i=startIndex;i<endIndex;i++)
+ for (i = startIndex; i < endIndex; i++)
{
- btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
- primitive_boxes[i].m_bound.m_min);
- means+=center;
+ btVector3 center = btScalar(0.5) * (primitive_boxes[i].m_bound.m_max +
+ primitive_boxes[i].m_bound.m_min);
+ means += center;
}
- means *= (btScalar(1.)/(btScalar)numIndices);
+ means *= (btScalar(1.) / (btScalar)numIndices);
- for (i=startIndex;i<endIndex;i++)
+ for (i = startIndex; i < endIndex; i++)
{
- btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
- primitive_boxes[i].m_bound.m_min);
- btVector3 diff2 = center-means;
+ btVector3 center = btScalar(0.5) * (primitive_boxes[i].m_bound.m_max +
+ primitive_boxes[i].m_bound.m_min);
+ btVector3 diff2 = center - means;
diff2 = diff2 * diff2;
variance += diff2;
}
- variance *= (btScalar(1.)/ ((btScalar)numIndices-1) );
+ variance *= (btScalar(1.) / ((btScalar)numIndices - 1));
return variance.maxAxis();
}
-
int btQuantizedBvhTree::_sort_and_calc_splitting_index(
- GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex,
+ GIM_BVH_DATA_ARRAY& primitive_boxes, int startIndex,
int endIndex, int splitAxis)
{
int i;
- int splitIndex =startIndex;
+ int splitIndex = startIndex;
int numIndices = endIndex - startIndex;
// average of centers
btScalar splitValue = 0.0f;
- btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
- for (i=startIndex;i<endIndex;i++)
+ btVector3 means(btScalar(0.), btScalar(0.), btScalar(0.));
+ for (i = startIndex; i < endIndex; i++)
{
- btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
- primitive_boxes[i].m_bound.m_min);
- means+=center;
+ btVector3 center = btScalar(0.5) * (primitive_boxes[i].m_bound.m_max +
+ primitive_boxes[i].m_bound.m_min);
+ means += center;
}
- means *= (btScalar(1.)/(btScalar)numIndices);
+ means *= (btScalar(1.) / (btScalar)numIndices);
splitValue = means[splitAxis];
-
//sort leafNodes so all values larger then splitValue comes first, and smaller values start from 'splitIndex'.
- for (i=startIndex;i<endIndex;i++)
+ for (i = startIndex; i < endIndex; i++)
{
- btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
- primitive_boxes[i].m_bound.m_min);
+ btVector3 center = btScalar(0.5) * (primitive_boxes[i].m_bound.m_max +
+ primitive_boxes[i].m_bound.m_min);
if (center[splitAxis] > splitValue)
{
//swap
- primitive_boxes.swap(i,splitIndex);
+ primitive_boxes.swap(i, splitIndex);
//swapLeafNodes(i,splitIndex);
splitIndex++;
}
@@ -163,32 +153,30 @@ int btQuantizedBvhTree::_sort_and_calc_splitting_index(
//bool unbalanced2 = true;
//this should be safe too:
- int rangeBalancedIndices = numIndices/3;
- bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices)));
+ int rangeBalancedIndices = numIndices / 3;
+ bool unbalanced = ((splitIndex <= (startIndex + rangeBalancedIndices)) || (splitIndex >= (endIndex - 1 - rangeBalancedIndices)));
if (unbalanced)
{
- splitIndex = startIndex+ (numIndices>>1);
+ splitIndex = startIndex + (numIndices >> 1);
}
- btAssert(!((splitIndex==startIndex) || (splitIndex == (endIndex))));
+ btAssert(!((splitIndex == startIndex) || (splitIndex == (endIndex))));
return splitIndex;
-
}
-
-void btQuantizedBvhTree::_build_sub_tree(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex)
+void btQuantizedBvhTree::_build_sub_tree(GIM_BVH_DATA_ARRAY& primitive_boxes, int startIndex, int endIndex)
{
int curIndex = m_num_nodes;
m_num_nodes++;
- btAssert((endIndex-startIndex)>0);
+ btAssert((endIndex - startIndex) > 0);
- if ((endIndex-startIndex)==1)
+ if ((endIndex - startIndex) == 1)
{
- //We have a leaf node
- setNodeBound(curIndex,primitive_boxes[startIndex].m_bound);
+ //We have a leaf node
+ setNodeBound(curIndex, primitive_boxes[startIndex].m_bound);
m_node_array[curIndex].setDataIndex(primitive_boxes[startIndex].m_data);
return;
@@ -196,48 +184,43 @@ void btQuantizedBvhTree::_build_sub_tree(GIM_BVH_DATA_ARRAY & primitive_boxes, i
//calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'.
//split axis
- int splitIndex = _calc_splitting_axis(primitive_boxes,startIndex,endIndex);
+ int splitIndex = _calc_splitting_axis(primitive_boxes, startIndex, endIndex);
splitIndex = _sort_and_calc_splitting_index(
- primitive_boxes,startIndex,endIndex,
- splitIndex//split axis
- );
-
+ primitive_boxes, startIndex, endIndex,
+ splitIndex //split axis
+ );
//calc this node bounding box
btAABB node_bound;
node_bound.invalidate();
- for (int i=startIndex;i<endIndex;i++)
+ for (int i = startIndex; i < endIndex; i++)
{
node_bound.merge(primitive_boxes[i].m_bound);
}
- setNodeBound(curIndex,node_bound);
-
+ setNodeBound(curIndex, node_bound);
//build left branch
- _build_sub_tree(primitive_boxes, startIndex, splitIndex );
-
+ _build_sub_tree(primitive_boxes, startIndex, splitIndex);
//build right branch
- _build_sub_tree(primitive_boxes, splitIndex ,endIndex);
+ _build_sub_tree(primitive_boxes, splitIndex, endIndex);
m_node_array[curIndex].setEscapeIndex(m_num_nodes - curIndex);
-
-
}
//! stackless build tree
void btQuantizedBvhTree::build_tree(
- GIM_BVH_DATA_ARRAY & primitive_boxes)
+ GIM_BVH_DATA_ARRAY& primitive_boxes)
{
calc_quantization(primitive_boxes);
// initialize node count to 0
m_num_nodes = 0;
// allocate nodes
- m_node_array.resize(primitive_boxes.size()*2);
+ m_node_array.resize(primitive_boxes.size() * 2);
_build_sub_tree(primitive_boxes, 0, primitive_boxes.size());
}
@@ -247,13 +230,13 @@ void btQuantizedBvhTree::build_tree(
void btGImpactQuantizedBvh::refit()
{
int nodecount = getNodeCount();
- while(nodecount--)
+ while (nodecount--)
{
- if(isLeafNode(nodecount))
+ if (isLeafNode(nodecount))
{
btAABB leafbox;
- m_primitive_manager->get_primitive_box(getNodeData(nodecount),leafbox);
- setNodeBound(nodecount,leafbox);
+ m_primitive_manager->get_primitive_box(getNodeData(nodecount), leafbox);
+ setNodeBound(nodecount, leafbox);
}
else
{
@@ -265,20 +248,20 @@ void btGImpactQuantizedBvh::refit()
btAABB temp_box;
int child_node = getLeftNode(nodecount);
- if(child_node)
+ if (child_node)
{
- getNodeBound(child_node,temp_box);
+ getNodeBound(child_node, temp_box);
bound.merge(temp_box);
}
child_node = getRightNode(nodecount);
- if(child_node)
+ if (child_node)
{
- getNodeBound(child_node,temp_box);
+ getNodeBound(child_node, temp_box);
bound.merge(temp_box);
}
- setNodeBound(nodecount,bound);
+ setNodeBound(nodecount, bound);
}
}
}
@@ -290,17 +273,17 @@ void btGImpactQuantizedBvh::buildSet()
GIM_BVH_DATA_ARRAY primitive_boxes;
primitive_boxes.resize(m_primitive_manager->get_primitive_count());
- for (int i = 0;i<primitive_boxes.size() ;i++ )
+ for (int i = 0; i < primitive_boxes.size(); i++)
{
- m_primitive_manager->get_primitive_box(i,primitive_boxes[i].m_bound);
- primitive_boxes[i].m_data = i;
+ m_primitive_manager->get_primitive_box(i, primitive_boxes[i].m_bound);
+ primitive_boxes[i].m_data = i;
}
m_box_tree.build_tree(primitive_boxes);
}
//! returns the indices of the primitives in the m_primitive_manager
-bool btGImpactQuantizedBvh::boxQuery(const btAABB & box, btAlignedObjectArray<int> & collided_results) const
+bool btGImpactQuantizedBvh::boxQuery(const btAABB& box, btAlignedObjectArray<int>& collided_results) const
{
int curIndex = 0;
int numNodes = getNodeCount();
@@ -310,16 +293,14 @@ bool btGImpactQuantizedBvh::boxQuery(const btAABB & box, btAlignedObjectArray<in
unsigned short quantizedMin[3];
unsigned short quantizedMax[3];
- m_box_tree.quantizePoint(quantizedMin,box.m_min);
- m_box_tree.quantizePoint(quantizedMax,box.m_max);
-
+ m_box_tree.quantizePoint(quantizedMin, box.m_min);
+ m_box_tree.quantizePoint(quantizedMax, box.m_max);
while (curIndex < numNodes)
{
-
//catch bugs in tree data
- bool aabbOverlap = m_box_tree.testQuantizedBoxOverlapp(curIndex, quantizedMin,quantizedMax);
+ bool aabbOverlap = m_box_tree.testQuantizedBoxOverlapp(curIndex, quantizedMin, quantizedMax);
bool isleafnode = isLeafNode(curIndex);
if (isleafnode && aabbOverlap)
@@ -335,19 +316,17 @@ bool btGImpactQuantizedBvh::boxQuery(const btAABB & box, btAlignedObjectArray<in
else
{
//skip node
- curIndex+= getEscapeNodeIndex(curIndex);
+ curIndex += getEscapeNodeIndex(curIndex);
}
}
- if(collided_results.size()>0) return true;
+ if (collided_results.size() > 0) return true;
return false;
}
-
-
//! returns the indices of the primitives in the m_primitive_manager
bool btGImpactQuantizedBvh::rayQuery(
- const btVector3 & ray_dir,const btVector3 & ray_origin ,
- btAlignedObjectArray<int> & collided_results) const
+ const btVector3& ray_dir, const btVector3& ray_origin,
+ btAlignedObjectArray<int>& collided_results) const
{
int curIndex = 0;
int numNodes = getNodeCount();
@@ -355,16 +334,16 @@ bool btGImpactQuantizedBvh::rayQuery(
while (curIndex < numNodes)
{
btAABB bound;
- getNodeBound(curIndex,bound);
+ getNodeBound(curIndex, bound);
//catch bugs in tree data
- bool aabbOverlap = bound.collide_ray(ray_origin,ray_dir);
+ bool aabbOverlap = bound.collide_ray(ray_origin, ray_dir);
bool isleafnode = isLeafNode(curIndex);
if (isleafnode && aabbOverlap)
{
- collided_results.push_back(getNodeData( curIndex));
+ collided_results.push_back(getNodeData(curIndex));
}
if (aabbOverlap || isleafnode)
@@ -375,154 +354,133 @@ bool btGImpactQuantizedBvh::rayQuery(
else
{
//skip node
- curIndex+= getEscapeNodeIndex(curIndex);
+ curIndex += getEscapeNodeIndex(curIndex);
}
}
- if(collided_results.size()>0) return true;
+ if (collided_results.size() > 0) return true;
return false;
}
-
SIMD_FORCE_INLINE bool _quantized_node_collision(
- const btGImpactQuantizedBvh * boxset0, const btGImpactQuantizedBvh * boxset1,
- const BT_BOX_BOX_TRANSFORM_CACHE & trans_cache_1to0,
- int node0 ,int node1, bool complete_primitive_tests)
+ const btGImpactQuantizedBvh* boxset0, const btGImpactQuantizedBvh* boxset1,
+ const BT_BOX_BOX_TRANSFORM_CACHE& trans_cache_1to0,
+ int node0, int node1, bool complete_primitive_tests)
{
btAABB box0;
- boxset0->getNodeBound(node0,box0);
+ boxset0->getNodeBound(node0, box0);
btAABB box1;
- boxset1->getNodeBound(node1,box1);
-
- return box0.overlapping_trans_cache(box1,trans_cache_1to0,complete_primitive_tests );
-// box1.appy_transform_trans_cache(trans_cache_1to0);
-// return box0.has_collision(box1);
+ boxset1->getNodeBound(node1, box1);
+ return box0.overlapping_trans_cache(box1, trans_cache_1to0, complete_primitive_tests);
+ // box1.appy_transform_trans_cache(trans_cache_1to0);
+ // return box0.has_collision(box1);
}
-
//stackless recursive collision routine
static void _find_quantized_collision_pairs_recursive(
- const btGImpactQuantizedBvh * boxset0, const btGImpactQuantizedBvh * boxset1,
- btPairSet * collision_pairs,
- const BT_BOX_BOX_TRANSFORM_CACHE & trans_cache_1to0,
+ const btGImpactQuantizedBvh* boxset0, const btGImpactQuantizedBvh* boxset1,
+ btPairSet* collision_pairs,
+ const BT_BOX_BOX_TRANSFORM_CACHE& trans_cache_1to0,
int node0, int node1, bool complete_primitive_tests)
{
+ if (_quantized_node_collision(
+ boxset0, boxset1, trans_cache_1to0,
+ node0, node1, complete_primitive_tests) == false) return; //avoid colliding internal nodes
-
-
- if( _quantized_node_collision(
- boxset0,boxset1,trans_cache_1to0,
- node0,node1,complete_primitive_tests) ==false) return;//avoid colliding internal nodes
-
- if(boxset0->isLeafNode(node0))
+ if (boxset0->isLeafNode(node0))
{
- if(boxset1->isLeafNode(node1))
+ if (boxset1->isLeafNode(node1))
{
// collision result
collision_pairs->push_pair(
- boxset0->getNodeData(node0),boxset1->getNodeData(node1));
+ boxset0->getNodeData(node0), boxset1->getNodeData(node1));
return;
}
else
{
-
//collide left recursive
_find_quantized_collision_pairs_recursive(
- boxset0,boxset1,
- collision_pairs,trans_cache_1to0,
- node0,boxset1->getLeftNode(node1),false);
+ boxset0, boxset1,
+ collision_pairs, trans_cache_1to0,
+ node0, boxset1->getLeftNode(node1), false);
//collide right recursive
_find_quantized_collision_pairs_recursive(
- boxset0,boxset1,
- collision_pairs,trans_cache_1to0,
- node0,boxset1->getRightNode(node1),false);
-
-
+ boxset0, boxset1,
+ collision_pairs, trans_cache_1to0,
+ node0, boxset1->getRightNode(node1), false);
}
}
else
{
- if(boxset1->isLeafNode(node1))
+ if (boxset1->isLeafNode(node1))
{
-
//collide left recursive
_find_quantized_collision_pairs_recursive(
- boxset0,boxset1,
- collision_pairs,trans_cache_1to0,
- boxset0->getLeftNode(node0),node1,false);
-
+ boxset0, boxset1,
+ collision_pairs, trans_cache_1to0,
+ boxset0->getLeftNode(node0), node1, false);
//collide right recursive
_find_quantized_collision_pairs_recursive(
- boxset0,boxset1,
- collision_pairs,trans_cache_1to0,
- boxset0->getRightNode(node0),node1,false);
-
-
+ boxset0, boxset1,
+ collision_pairs, trans_cache_1to0,
+ boxset0->getRightNode(node0), node1, false);
}
else
{
//collide left0 left1
-
-
_find_quantized_collision_pairs_recursive(
- boxset0,boxset1,
- collision_pairs,trans_cache_1to0,
- boxset0->getLeftNode(node0),boxset1->getLeftNode(node1),false);
+ boxset0, boxset1,
+ collision_pairs, trans_cache_1to0,
+ boxset0->getLeftNode(node0), boxset1->getLeftNode(node1), false);
//collide left0 right1
_find_quantized_collision_pairs_recursive(
- boxset0,boxset1,
- collision_pairs,trans_cache_1to0,
- boxset0->getLeftNode(node0),boxset1->getRightNode(node1),false);
-
+ boxset0, boxset1,
+ collision_pairs, trans_cache_1to0,
+ boxset0->getLeftNode(node0), boxset1->getRightNode(node1), false);
//collide right0 left1
_find_quantized_collision_pairs_recursive(
- boxset0,boxset1,
- collision_pairs,trans_cache_1to0,
- boxset0->getRightNode(node0),boxset1->getLeftNode(node1),false);
+ boxset0, boxset1,
+ collision_pairs, trans_cache_1to0,
+ boxset0->getRightNode(node0), boxset1->getLeftNode(node1), false);
//collide right0 right1
_find_quantized_collision_pairs_recursive(
- boxset0,boxset1,
- collision_pairs,trans_cache_1to0,
- boxset0->getRightNode(node0),boxset1->getRightNode(node1),false);
+ boxset0, boxset1,
+ collision_pairs, trans_cache_1to0,
+ boxset0->getRightNode(node0), boxset1->getRightNode(node1), false);
- }// else if node1 is not a leaf
- }// else if node0 is not a leaf
+ } // else if node1 is not a leaf
+ } // else if node0 is not a leaf
}
-
-void btGImpactQuantizedBvh::find_collision(const btGImpactQuantizedBvh * boxset0, const btTransform & trans0,
- const btGImpactQuantizedBvh * boxset1, const btTransform & trans1,
- btPairSet & collision_pairs)
+void btGImpactQuantizedBvh::find_collision(const btGImpactQuantizedBvh* boxset0, const btTransform& trans0,
+ const btGImpactQuantizedBvh* boxset1, const btTransform& trans1,
+ btPairSet& collision_pairs)
{
-
- if(boxset0->getNodeCount()==0 || boxset1->getNodeCount()==0 ) return;
+ if (boxset0->getNodeCount() == 0 || boxset1->getNodeCount() == 0) return;
BT_BOX_BOX_TRANSFORM_CACHE trans_cache_1to0;
- trans_cache_1to0.calc_from_homogenic(trans0,trans1);
+ trans_cache_1to0.calc_from_homogenic(trans0, trans1);
#ifdef TRI_COLLISION_PROFILING
bt_begin_gim02_q_tree_time();
-#endif //TRI_COLLISION_PROFILING
+#endif //TRI_COLLISION_PROFILING
_find_quantized_collision_pairs_recursive(
- boxset0,boxset1,
- &collision_pairs,trans_cache_1to0,0,0,true);
+ boxset0, boxset1,
+ &collision_pairs, trans_cache_1to0, 0, 0, true);
#ifdef TRI_COLLISION_PROFILING
bt_end_gim02_q_tree_time();
-#endif //TRI_COLLISION_PROFILING
-
+#endif //TRI_COLLISION_PROFILING
}
-
-
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactQuantizedBvh.h b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactQuantizedBvh.h
index 42e5520fc0..b231c1e832 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactQuantizedBvh.h
+++ b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactQuantizedBvh.h
@@ -28,13 +28,10 @@ subject to the following restrictions:
#include "btQuantization.h"
#include "btGImpactQuantizedBvhStructs.h"
-class GIM_QUANTIZED_BVH_NODE_ARRAY:public btAlignedObjectArray<BT_QUANTIZED_BVH_NODE>
+class GIM_QUANTIZED_BVH_NODE_ARRAY : public btAlignedObjectArray<BT_QUANTIZED_BVH_NODE>
{
};
-
-
-
//! Basic Box tree structure
class btQuantizedBvhTree
{
@@ -43,16 +40,18 @@ protected:
GIM_QUANTIZED_BVH_NODE_ARRAY m_node_array;
btAABB m_global_bound;
btVector3 m_bvhQuantization;
+
protected:
- void calc_quantization(GIM_BVH_DATA_ARRAY & primitive_boxes, btScalar boundMargin = btScalar(1.0) );
+ void calc_quantization(GIM_BVH_DATA_ARRAY& primitive_boxes, btScalar boundMargin = btScalar(1.0));
int _sort_and_calc_splitting_index(
- GIM_BVH_DATA_ARRAY & primitive_boxes,
- int startIndex, int endIndex, int splitAxis);
+ GIM_BVH_DATA_ARRAY& primitive_boxes,
+ int startIndex, int endIndex, int splitAxis);
- int _calc_splitting_axis(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex);
+ int _calc_splitting_axis(GIM_BVH_DATA_ARRAY& primitive_boxes, int startIndex, int endIndex);
+
+ void _build_sub_tree(GIM_BVH_DATA_ARRAY& primitive_boxes, int startIndex, int endIndex);
- void _build_sub_tree(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex);
public:
btQuantizedBvhTree()
{
@@ -61,20 +60,19 @@ public:
//! prototype functions for box tree management
//!@{
- void build_tree(GIM_BVH_DATA_ARRAY & primitive_boxes);
+ void build_tree(GIM_BVH_DATA_ARRAY& primitive_boxes);
SIMD_FORCE_INLINE void quantizePoint(
- unsigned short * quantizedpoint, const btVector3 & point) const
+ unsigned short* quantizedpoint, const btVector3& point) const
{
- bt_quantize_clamp(quantizedpoint,point,m_global_bound.m_min,m_global_bound.m_max,m_bvhQuantization);
+ bt_quantize_clamp(quantizedpoint, point, m_global_bound.m_min, m_global_bound.m_max, m_bvhQuantization);
}
-
SIMD_FORCE_INLINE bool testQuantizedBoxOverlapp(
int node_index,
- unsigned short * quantizedMin,unsigned short * quantizedMax) const
+ unsigned short* quantizedMin, unsigned short* quantizedMax) const
{
- return m_node_array[node_index].testQuantizedBoxOverlapp(quantizedMin,quantizedMax);
+ return m_node_array[node_index].testQuantizedBoxOverlapp(quantizedMin, quantizedMax);
}
SIMD_FORCE_INLINE void clearNodes()
@@ -100,41 +98,41 @@ public:
return m_node_array[nodeindex].getDataIndex();
}
- SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB & bound) const
+ SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB& bound) const
{
bound.m_min = bt_unquantize(
m_node_array[nodeindex].m_quantizedAabbMin,
- m_global_bound.m_min,m_bvhQuantization);
+ m_global_bound.m_min, m_bvhQuantization);
bound.m_max = bt_unquantize(
m_node_array[nodeindex].m_quantizedAabbMax,
- m_global_bound.m_min,m_bvhQuantization);
+ m_global_bound.m_min, m_bvhQuantization);
}
- SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB & bound)
+ SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB& bound)
{
- bt_quantize_clamp( m_node_array[nodeindex].m_quantizedAabbMin,
- bound.m_min,
- m_global_bound.m_min,
- m_global_bound.m_max,
- m_bvhQuantization);
+ bt_quantize_clamp(m_node_array[nodeindex].m_quantizedAabbMin,
+ bound.m_min,
+ m_global_bound.m_min,
+ m_global_bound.m_max,
+ m_bvhQuantization);
- bt_quantize_clamp( m_node_array[nodeindex].m_quantizedAabbMax,
- bound.m_max,
- m_global_bound.m_min,
- m_global_bound.m_max,
- m_bvhQuantization);
+ bt_quantize_clamp(m_node_array[nodeindex].m_quantizedAabbMax,
+ bound.m_max,
+ m_global_bound.m_min,
+ m_global_bound.m_max,
+ m_bvhQuantization);
}
SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const
{
- return nodeindex+1;
+ return nodeindex + 1;
}
SIMD_FORCE_INLINE int getRightNode(int nodeindex) const
{
- if(m_node_array[nodeindex+1].isLeafNode()) return nodeindex+2;
- return nodeindex+1 + m_node_array[nodeindex+1].getEscapeIndex();
+ if (m_node_array[nodeindex + 1].isLeafNode()) return nodeindex + 2;
+ return nodeindex + 1 + m_node_array[nodeindex + 1].getEscapeIndex();
}
SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const
@@ -142,7 +140,7 @@ public:
return m_node_array[nodeindex].getEscapeIndex();
}
- SIMD_FORCE_INLINE const BT_QUANTIZED_BVH_NODE * get_node_pointer(int index = 0) const
+ SIMD_FORCE_INLINE const BT_QUANTIZED_BVH_NODE* get_node_pointer(int index = 0) const
{
return &m_node_array[index];
}
@@ -150,8 +148,6 @@ public:
//!@}
};
-
-
//! Structure for containing Boxes
/*!
This class offers an structure for managing a box tree of primitives.
@@ -161,13 +157,13 @@ class btGImpactQuantizedBvh
{
protected:
btQuantizedBvhTree m_box_tree;
- btPrimitiveManagerBase * m_primitive_manager;
+ btPrimitiveManagerBase* m_primitive_manager;
protected:
//stackless refit
void refit();
-public:
+public:
//! this constructor doesn't build the tree. you must call buildSet
btGImpactQuantizedBvh()
{
@@ -175,31 +171,30 @@ public:
}
//! this constructor doesn't build the tree. you must call buildSet
- btGImpactQuantizedBvh(btPrimitiveManagerBase * primitive_manager)
+ btGImpactQuantizedBvh(btPrimitiveManagerBase* primitive_manager)
{
m_primitive_manager = primitive_manager;
}
- SIMD_FORCE_INLINE btAABB getGlobalBox() const
+ SIMD_FORCE_INLINE btAABB getGlobalBox() const
{
btAABB totalbox;
getNodeBound(0, totalbox);
return totalbox;
}
- SIMD_FORCE_INLINE void setPrimitiveManager(btPrimitiveManagerBase * primitive_manager)
+ SIMD_FORCE_INLINE void setPrimitiveManager(btPrimitiveManagerBase* primitive_manager)
{
m_primitive_manager = primitive_manager;
}
- SIMD_FORCE_INLINE btPrimitiveManagerBase * getPrimitiveManager() const
+ SIMD_FORCE_INLINE btPrimitiveManagerBase* getPrimitiveManager() const
{
return m_primitive_manager;
}
-
-//! node manager prototype functions
-///@{
+ //! node manager prototype functions
+ ///@{
//! this attemps to refit the box set.
SIMD_FORCE_INLINE void update()
@@ -211,21 +206,21 @@ public:
void buildSet();
//! returns the indices of the primitives in the m_primitive_manager
- bool boxQuery(const btAABB & box, btAlignedObjectArray<int> & collided_results) const;
+ bool boxQuery(const btAABB& box, btAlignedObjectArray<int>& collided_results) const;
//! returns the indices of the primitives in the m_primitive_manager
- SIMD_FORCE_INLINE bool boxQueryTrans(const btAABB & box,
- const btTransform & transform, btAlignedObjectArray<int> & collided_results) const
+ SIMD_FORCE_INLINE bool boxQueryTrans(const btAABB& box,
+ const btTransform& transform, btAlignedObjectArray<int>& collided_results) const
{
- btAABB transbox=box;
+ btAABB transbox = box;
transbox.appy_transform(transform);
- return boxQuery(transbox,collided_results);
+ return boxQuery(transbox, collided_results);
}
//! returns the indices of the primitives in the m_primitive_manager
bool rayQuery(
- const btVector3 & ray_dir,const btVector3 & ray_origin ,
- btAlignedObjectArray<int> & collided_results) const;
+ const btVector3& ray_dir, const btVector3& ray_origin,
+ btAlignedObjectArray<int>& collided_results) const;
//! tells if this set has hierarcht
SIMD_FORCE_INLINE bool hasHierarchy() const
@@ -234,7 +229,7 @@ public:
}
//! tells if this set is a trimesh
- SIMD_FORCE_INLINE bool isTrimesh() const
+ SIMD_FORCE_INLINE bool isTrimesh() const
{
return m_primitive_manager->is_trimesh();
}
@@ -256,17 +251,16 @@ public:
return m_box_tree.getNodeData(nodeindex);
}
- SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB & bound) const
+ SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB& bound) const
{
m_box_tree.getNodeBound(nodeindex, bound);
}
- SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB & bound)
+ SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB& bound)
{
m_box_tree.setNodeBound(nodeindex, bound);
}
-
SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const
{
return m_box_tree.getLeftNode(nodeindex);
@@ -282,24 +276,23 @@ public:
return m_box_tree.getEscapeNodeIndex(nodeindex);
}
- SIMD_FORCE_INLINE void getNodeTriangle(int nodeindex,btPrimitiveTriangle & triangle) const
+ SIMD_FORCE_INLINE void getNodeTriangle(int nodeindex, btPrimitiveTriangle& triangle) const
{
- m_primitive_manager->get_primitive_triangle(getNodeData(nodeindex),triangle);
+ m_primitive_manager->get_primitive_triangle(getNodeData(nodeindex), triangle);
}
-
- SIMD_FORCE_INLINE const BT_QUANTIZED_BVH_NODE * get_node_pointer(int index = 0) const
+ SIMD_FORCE_INLINE const BT_QUANTIZED_BVH_NODE* get_node_pointer(int index = 0) const
{
return m_box_tree.get_node_pointer(index);
}
#ifdef TRI_COLLISION_PROFILING
static float getAverageTreeCollisionTime();
-#endif //TRI_COLLISION_PROFILING
+#endif //TRI_COLLISION_PROFILING
- static void find_collision(const btGImpactQuantizedBvh * boxset1, const btTransform & trans1,
- const btGImpactQuantizedBvh * boxset2, const btTransform & trans2,
- btPairSet & collision_pairs);
+ static void find_collision(const btGImpactQuantizedBvh* boxset1, const btTransform& trans1,
+ const btGImpactQuantizedBvh* boxset2, const btTransform& trans2,
+ btPairSet& collision_pairs);
};
-#endif // GIM_BOXPRUNING_H_INCLUDED
+#endif // GIM_BOXPRUNING_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactQuantizedBvhStructs.h b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactQuantizedBvhStructs.h
index 7dd5a1b9d0..bd50cb5b87 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactQuantizedBvhStructs.h
+++ b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactQuantizedBvhStructs.h
@@ -29,13 +29,14 @@ subject to the following restrictions:
///btQuantizedBvhNode is a compressed aabb node, 16 bytes.
///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).
-ATTRIBUTE_ALIGNED16 (struct) BT_QUANTIZED_BVH_NODE
+ATTRIBUTE_ALIGNED16(struct)
+BT_QUANTIZED_BVH_NODE
{
//12 bytes
- unsigned short int m_quantizedAabbMin[3];
- unsigned short int m_quantizedAabbMax[3];
+ unsigned short int m_quantizedAabbMin[3];
+ unsigned short int m_quantizedAabbMax[3];
//4 bytes
- int m_escapeIndexOrDataIndex;
+ int m_escapeIndexOrDataIndex;
BT_QUANTIZED_BVH_NODE()
{
@@ -45,7 +46,7 @@ ATTRIBUTE_ALIGNED16 (struct) BT_QUANTIZED_BVH_NODE
SIMD_FORCE_INLINE bool isLeafNode() const
{
//skipindex is negative (internal node), triangleindex >=0 (leafnode)
- return (m_escapeIndexOrDataIndex>=0);
+ return (m_escapeIndexOrDataIndex >= 0);
}
SIMD_FORCE_INLINE int getEscapeIndex() const
@@ -72,20 +73,19 @@ ATTRIBUTE_ALIGNED16 (struct) BT_QUANTIZED_BVH_NODE
}
SIMD_FORCE_INLINE bool testQuantizedBoxOverlapp(
- unsigned short * quantizedMin,unsigned short * quantizedMax) const
+ unsigned short* quantizedMin, unsigned short* quantizedMax) const
{
- if(m_quantizedAabbMin[0] > quantizedMax[0] ||
- m_quantizedAabbMax[0] < quantizedMin[0] ||
- m_quantizedAabbMin[1] > quantizedMax[1] ||
- m_quantizedAabbMax[1] < quantizedMin[1] ||
- m_quantizedAabbMin[2] > quantizedMax[2] ||
- m_quantizedAabbMax[2] < quantizedMin[2])
+ if (m_quantizedAabbMin[0] > quantizedMax[0] ||
+ m_quantizedAabbMax[0] < quantizedMin[0] ||
+ m_quantizedAabbMin[1] > quantizedMax[1] ||
+ m_quantizedAabbMax[1] < quantizedMin[1] ||
+ m_quantizedAabbMin[2] > quantizedMax[2] ||
+ m_quantizedAabbMax[2] < quantizedMin[2])
{
return false;
}
return true;
}
-
};
-#endif // GIM_QUANTIZED_SET_STRUCTS_H_INCLUDED
+#endif // GIM_QUANTIZED_SET_STRUCTS_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactShape.cpp b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactShape.cpp
index 30c85e3fff..34c229a3ab 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactShape.cpp
+++ b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactShape.cpp
@@ -18,178 +18,169 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#include "btGImpactShape.h"
#include "btGImpactMassUtil.h"
-
-btGImpactMeshShapePart::btGImpactMeshShapePart( btStridingMeshInterface * meshInterface, int part )
+btGImpactMeshShapePart::btGImpactMeshShapePart(btStridingMeshInterface* meshInterface, int part)
{
- // moved from .h to .cpp because of conditional compilation
- // (The setting of BT_THREADSAFE may differ between various cpp files, so it is best to
- // avoid using it in h files)
- m_primitive_manager.m_meshInterface = meshInterface;
- m_primitive_manager.m_part = part;
- m_box_set.setPrimitiveManager( &m_primitive_manager );
+ // moved from .h to .cpp because of conditional compilation
+ // (The setting of BT_THREADSAFE may differ between various cpp files, so it is best to
+ // avoid using it in h files)
+ m_primitive_manager.m_meshInterface = meshInterface;
+ m_primitive_manager.m_part = part;
+ m_box_set.setPrimitiveManager(&m_primitive_manager);
#if BT_THREADSAFE
- // If threadsafe is requested, this object uses a different lock/unlock
- // model with the btStridingMeshInterface -- lock once when the object is constructed
- // and unlock once in the destructor.
- // The other way of locking and unlocking for each collision check in the narrowphase
- // is not threadsafe. Note these are not thread-locks, they are calls to the meshInterface's
- // getLockedReadOnlyVertexIndexBase virtual function, which by default just returns a couple of
- // pointers. In theory a client could override the lock function to do all sorts of
- // things like reading data from GPU memory, or decompressing data on the fly, but such things
- // do not seem all that likely or useful, given the performance cost.
- m_primitive_manager.lock();
+ // If threadsafe is requested, this object uses a different lock/unlock
+ // model with the btStridingMeshInterface -- lock once when the object is constructed
+ // and unlock once in the destructor.
+ // The other way of locking and unlocking for each collision check in the narrowphase
+ // is not threadsafe. Note these are not thread-locks, they are calls to the meshInterface's
+ // getLockedReadOnlyVertexIndexBase virtual function, which by default just returns a couple of
+ // pointers. In theory a client could override the lock function to do all sorts of
+ // things like reading data from GPU memory, or decompressing data on the fly, but such things
+ // do not seem all that likely or useful, given the performance cost.
+ m_primitive_manager.lock();
#endif
}
btGImpactMeshShapePart::~btGImpactMeshShapePart()
{
- // moved from .h to .cpp because of conditional compilation
+ // moved from .h to .cpp because of conditional compilation
#if BT_THREADSAFE
- m_primitive_manager.unlock();
+ m_primitive_manager.unlock();
#endif
}
void btGImpactMeshShapePart::lockChildShapes() const
{
- // moved from .h to .cpp because of conditional compilation
-#if ! BT_THREADSAFE
- // called in the narrowphase -- not threadsafe!
- void * dummy = (void*) ( m_box_set.getPrimitiveManager() );
- TrimeshPrimitiveManager * dummymanager = static_cast<TrimeshPrimitiveManager *>( dummy );
- dummymanager->lock();
+ // moved from .h to .cpp because of conditional compilation
+#if !BT_THREADSAFE
+ // called in the narrowphase -- not threadsafe!
+ void* dummy = (void*)(m_box_set.getPrimitiveManager());
+ TrimeshPrimitiveManager* dummymanager = static_cast<TrimeshPrimitiveManager*>(dummy);
+ dummymanager->lock();
#endif
}
-void btGImpactMeshShapePart::unlockChildShapes() const
+void btGImpactMeshShapePart::unlockChildShapes() const
{
- // moved from .h to .cpp because of conditional compilation
-#if ! BT_THREADSAFE
- // called in the narrowphase -- not threadsafe!
- void * dummy = (void*) ( m_box_set.getPrimitiveManager() );
- TrimeshPrimitiveManager * dummymanager = static_cast<TrimeshPrimitiveManager *>( dummy );
- dummymanager->unlock();
+ // moved from .h to .cpp because of conditional compilation
+#if !BT_THREADSAFE
+ // called in the narrowphase -- not threadsafe!
+ void* dummy = (void*)(m_box_set.getPrimitiveManager());
+ TrimeshPrimitiveManager* dummymanager = static_cast<TrimeshPrimitiveManager*>(dummy);
+ dummymanager->unlock();
#endif
}
-
#define CALC_EXACT_INERTIA 1
-
-void btGImpactCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+void btGImpactCompoundShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
{
lockChildShapes();
#ifdef CALC_EXACT_INERTIA
- inertia.setValue(0.f,0.f,0.f);
+ inertia.setValue(0.f, 0.f, 0.f);
int i = this->getNumChildShapes();
- btScalar shapemass = mass/btScalar(i);
+ btScalar shapemass = mass / btScalar(i);
- while(i--)
+ while (i--)
{
btVector3 temp_inertia;
- m_childShapes[i]->calculateLocalInertia(shapemass,temp_inertia);
- if(childrenHasTransform())
+ m_childShapes[i]->calculateLocalInertia(shapemass, temp_inertia);
+ if (childrenHasTransform())
{
- inertia = gim_inertia_add_transformed( inertia,temp_inertia,m_childTransforms[i]);
+ inertia = gim_inertia_add_transformed(inertia, temp_inertia, m_childTransforms[i]);
}
else
{
- inertia = gim_inertia_add_transformed( inertia,temp_inertia,btTransform::getIdentity());
+ inertia = gim_inertia_add_transformed(inertia, temp_inertia, btTransform::getIdentity());
}
-
}
#else
// Calc box inertia
- btScalar lx= m_localAABB.m_max[0] - m_localAABB.m_min[0];
- btScalar ly= m_localAABB.m_max[1] - m_localAABB.m_min[1];
- btScalar lz= m_localAABB.m_max[2] - m_localAABB.m_min[2];
- const btScalar x2 = lx*lx;
- const btScalar y2 = ly*ly;
- const btScalar z2 = lz*lz;
+ btScalar lx = m_localAABB.m_max[0] - m_localAABB.m_min[0];
+ btScalar ly = m_localAABB.m_max[1] - m_localAABB.m_min[1];
+ btScalar lz = m_localAABB.m_max[2] - m_localAABB.m_min[2];
+ const btScalar x2 = lx * lx;
+ const btScalar y2 = ly * ly;
+ const btScalar z2 = lz * lz;
const btScalar scaledmass = mass * btScalar(0.08333333);
- inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2));
+ inertia = scaledmass * (btVector3(y2 + z2, x2 + z2, x2 + y2));
#endif
unlockChildShapes();
}
-
-
-void btGImpactMeshShapePart::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+void btGImpactMeshShapePart::calculateLocalInertia(btScalar mass, btVector3& inertia) const
{
lockChildShapes();
-
#ifdef CALC_EXACT_INERTIA
- inertia.setValue(0.f,0.f,0.f);
+ inertia.setValue(0.f, 0.f, 0.f);
int i = this->getVertexCount();
- btScalar pointmass = mass/btScalar(i);
+ btScalar pointmass = mass / btScalar(i);
- while(i--)
+ while (i--)
{
btVector3 pointintertia;
- this->getVertex(i,pointintertia);
- pointintertia = gim_get_point_inertia(pointintertia,pointmass);
- inertia+=pointintertia;
+ this->getVertex(i, pointintertia);
+ pointintertia = gim_get_point_inertia(pointintertia, pointmass);
+ inertia += pointintertia;
}
#else
// Calc box inertia
- btScalar lx= m_localAABB.m_max[0] - m_localAABB.m_min[0];
- btScalar ly= m_localAABB.m_max[1] - m_localAABB.m_min[1];
- btScalar lz= m_localAABB.m_max[2] - m_localAABB.m_min[2];
- const btScalar x2 = lx*lx;
- const btScalar y2 = ly*ly;
- const btScalar z2 = lz*lz;
+ btScalar lx = m_localAABB.m_max[0] - m_localAABB.m_min[0];
+ btScalar ly = m_localAABB.m_max[1] - m_localAABB.m_min[1];
+ btScalar lz = m_localAABB.m_max[2] - m_localAABB.m_min[2];
+ const btScalar x2 = lx * lx;
+ const btScalar y2 = ly * ly;
+ const btScalar z2 = lz * lz;
const btScalar scaledmass = mass * btScalar(0.08333333);
- inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2));
+ inertia = scaledmass * (btVector3(y2 + z2, x2 + z2, x2 + y2));
#endif
unlockChildShapes();
}
-void btGImpactMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+void btGImpactMeshShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
{
-
#ifdef CALC_EXACT_INERTIA
- inertia.setValue(0.f,0.f,0.f);
+ inertia.setValue(0.f, 0.f, 0.f);
int i = this->getMeshPartCount();
- btScalar partmass = mass/btScalar(i);
+ btScalar partmass = mass / btScalar(i);
- while(i--)
+ while (i--)
{
btVector3 partinertia;
- getMeshPart(i)->calculateLocalInertia(partmass,partinertia);
- inertia+=partinertia;
+ getMeshPart(i)->calculateLocalInertia(partmass, partinertia);
+ inertia += partinertia;
}
#else
// Calc box inertia
- btScalar lx= m_localAABB.m_max[0] - m_localAABB.m_min[0];
- btScalar ly= m_localAABB.m_max[1] - m_localAABB.m_min[1];
- btScalar lz= m_localAABB.m_max[2] - m_localAABB.m_min[2];
- const btScalar x2 = lx*lx;
- const btScalar y2 = ly*ly;
- const btScalar z2 = lz*lz;
+ btScalar lx = m_localAABB.m_max[0] - m_localAABB.m_min[0];
+ btScalar ly = m_localAABB.m_max[1] - m_localAABB.m_min[1];
+ btScalar lz = m_localAABB.m_max[2] - m_localAABB.m_min[2];
+ const btScalar x2 = lx * lx;
+ const btScalar y2 = ly * ly;
+ const btScalar z2 = lz * lz;
const btScalar scaledmass = mass * btScalar(0.08333333);
- inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2));
+ inertia = scaledmass * (btVector3(y2 + z2, x2 + z2, x2 + y2));
#endif
}
@@ -198,7 +189,7 @@ void btGImpactMeshShape::rayTest(const btVector3& rayFrom, const btVector3& rayT
{
}
-void btGImpactMeshShapePart::processAllTrianglesRay(btTriangleCallback* callback,const btVector3& rayFrom, const btVector3& rayTo) const
+void btGImpactMeshShapePart::processAllTrianglesRay(btTriangleCallback* callback, const btVector3& rayFrom, const btVector3& rayTo) const
{
lockChildShapes();
@@ -207,7 +198,7 @@ void btGImpactMeshShapePart::processAllTrianglesRay(btTriangleCallback* callback
rayDir.normalize();
m_box_set.rayQuery(rayDir, rayFrom, collided);
- if(collided.size()==0)
+ if (collided.size() == 0)
{
unlockChildShapes();
return;
@@ -216,15 +207,15 @@ void btGImpactMeshShapePart::processAllTrianglesRay(btTriangleCallback* callback
int part = (int)getPart();
btPrimitiveTriangle triangle;
int i = collided.size();
- while(i--)
+ while (i--)
{
- getPrimitiveTriangle(collided[i],triangle);
- callback->processTriangle(triangle.m_vertices,part,collided[i]);
+ getPrimitiveTriangle(collided[i], triangle);
+ callback->processTriangle(triangle.m_vertices, part, collided[i]);
}
unlockChildShapes();
}
-void btGImpactMeshShapePart::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
+void btGImpactMeshShapePart::processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
{
lockChildShapes();
btAABB box;
@@ -232,9 +223,9 @@ void btGImpactMeshShapePart::processAllTriangles(btTriangleCallback* callback,co
box.m_max = aabbMax;
btAlignedObjectArray<int> collided;
- m_box_set.boxQuery(box,collided);
+ m_box_set.boxQuery(box, collided);
- if(collided.size()==0)
+ if (collided.size() == 0)
{
unlockChildShapes();
return;
@@ -243,40 +234,38 @@ void btGImpactMeshShapePart::processAllTriangles(btTriangleCallback* callback,co
int part = (int)getPart();
btPrimitiveTriangle triangle;
int i = collided.size();
- while(i--)
+ while (i--)
{
- this->getPrimitiveTriangle(collided[i],triangle);
- callback->processTriangle(triangle.m_vertices,part,collided[i]);
+ this->getPrimitiveTriangle(collided[i], triangle);
+ callback->processTriangle(triangle.m_vertices, part, collided[i]);
}
unlockChildShapes();
-
}
-void btGImpactMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
+void btGImpactMeshShape::processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
{
int i = m_mesh_parts.size();
- while(i--)
+ while (i--)
{
- m_mesh_parts[i]->processAllTriangles(callback,aabbMin,aabbMax);
+ m_mesh_parts[i]->processAllTriangles(callback, aabbMin, aabbMax);
}
}
-void btGImpactMeshShape::processAllTrianglesRay(btTriangleCallback* callback,const btVector3& rayFrom, const btVector3& rayTo) const
+void btGImpactMeshShape::processAllTrianglesRay(btTriangleCallback* callback, const btVector3& rayFrom, const btVector3& rayTo) const
{
int i = m_mesh_parts.size();
- while(i--)
+ while (i--)
{
m_mesh_parts[i]->processAllTrianglesRay(callback, rayFrom, rayTo);
}
}
-
///fills the dataBuffer and returns the struct name (and 0 on failure)
-const char* btGImpactMeshShape::serialize(void* dataBuffer, btSerializer* serializer) const
+const char* btGImpactMeshShape::serialize(void* dataBuffer, btSerializer* serializer) const
{
- btGImpactMeshShapeData* trimeshData = (btGImpactMeshShapeData*) dataBuffer;
+ btGImpactMeshShapeData* trimeshData = (btGImpactMeshShapeData*)dataBuffer;
- btCollisionShape::serialize(&trimeshData->m_collisionShapeData,serializer);
+ btCollisionShape::serialize(&trimeshData->m_collisionShapeData, serializer);
m_meshInterface->serialize(&trimeshData->m_meshInterface, serializer);
@@ -288,4 +277,3 @@ const char* btGImpactMeshShape::serialize(void* dataBuffer, btSerializer* serial
return "btGImpactMeshShapeData";
}
-
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactShape.h b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactShape.h
index 9d7e40562c..5b85e87041 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactShape.h
+++ b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactShape.h
@@ -21,7 +21,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#ifndef GIMPACT_SHAPE_H
#define GIMPACT_SHAPE_H
@@ -37,8 +36,7 @@ subject to the following restrictions:
#include "LinearMath/btMatrix3x3.h"
#include "LinearMath/btAlignedObjectArray.h"
-#include "btGImpactQuantizedBvh.h" // box tree class
-
+#include "btGImpactQuantizedBvh.h" // box tree class
//! declare Quantized trees, (you can change to float based trees)
typedef btGImpactQuantizedBvh btGImpactBoxSet;
@@ -50,10 +48,8 @@ enum eGIMPACT_SHAPE_TYPE
CONST_GIMPACT_TRIMESH_SHAPE
};
-
-
//! Helper class for tetrahedrons
-class btTetrahedronShapeEx:public btBU_Simplex1to4
+class btTetrahedronShapeEx : public btBU_Simplex1to4
{
public:
btTetrahedronShapeEx()
@@ -61,10 +57,9 @@ public:
m_numVertices = 4;
}
-
SIMD_FORCE_INLINE void setVertices(
- const btVector3 & v0,const btVector3 & v1,
- const btVector3 & v2,const btVector3 & v3)
+ const btVector3& v0, const btVector3& v1,
+ const btVector3& v2, const btVector3& v3)
{
m_vertices[0] = v0;
m_vertices[1] = v1;
@@ -74,45 +69,42 @@ public:
}
};
-
//! Base class for gimpact shapes
class btGImpactShapeInterface : public btConcaveShape
{
protected:
- btAABB m_localAABB;
- bool m_needs_update;
- btVector3 localScaling;
- btGImpactBoxSet m_box_set;// optionally boxset
+ btAABB m_localAABB;
+ bool m_needs_update;
+ btVector3 localScaling;
+ btGImpactBoxSet m_box_set; // optionally boxset
//! use this function for perfofm refit in bounding boxes
- //! use this function for perfofm refit in bounding boxes
- virtual void calcLocalAABB()
- {
+ //! use this function for perfofm refit in bounding boxes
+ virtual void calcLocalAABB()
+ {
lockChildShapes();
- if(m_box_set.getNodeCount() == 0)
- {
- m_box_set.buildSet();
- }
- else
- {
- m_box_set.update();
- }
- unlockChildShapes();
-
- m_localAABB = m_box_set.getGlobalBox();
- }
+ if (m_box_set.getNodeCount() == 0)
+ {
+ m_box_set.buildSet();
+ }
+ else
+ {
+ m_box_set.update();
+ }
+ unlockChildShapes();
+ m_localAABB = m_box_set.getGlobalBox();
+ }
public:
btGImpactShapeInterface()
{
- m_shapeType=GIMPACT_SHAPE_PROXYTYPE;
+ m_shapeType = GIMPACT_SHAPE_PROXYTYPE;
m_localAABB.invalidate();
m_needs_update = true;
- localScaling.setValue(1.f,1.f,1.f);
+ localScaling.setValue(1.f, 1.f, 1.f);
}
-
//! performs refit operation
/*!
Updates the entire Box set of this shape.
@@ -120,47 +112,46 @@ public:
will does nothing.
\post if m_needs_update == true, then it calls calcLocalAABB();
*/
- SIMD_FORCE_INLINE void updateBound()
- {
- if(!m_needs_update) return;
- calcLocalAABB();
- m_needs_update = false;
- }
-
- //! If the Bounding box is not updated, then this class attemps to calculate it.
- /*!
+ SIMD_FORCE_INLINE void updateBound()
+ {
+ if (!m_needs_update) return;
+ calcLocalAABB();
+ m_needs_update = false;
+ }
+
+ //! If the Bounding box is not updated, then this class attemps to calculate it.
+ /*!
\post Calls updateBound() for update the box set.
*/
- void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
- {
- btAABB transformedbox = m_localAABB;
- transformedbox.appy_transform(t);
- aabbMin = transformedbox.m_min;
- aabbMax = transformedbox.m_max;
- }
-
- //! Tells to this object that is needed to refit the box set
- virtual void postUpdate()
- {
- m_needs_update = true;
- }
+ void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
+ {
+ btAABB transformedbox = m_localAABB;
+ transformedbox.appy_transform(t);
+ aabbMin = transformedbox.m_min;
+ aabbMax = transformedbox.m_max;
+ }
+
+ //! Tells to this object that is needed to refit the box set
+ virtual void postUpdate()
+ {
+ m_needs_update = true;
+ }
//! Obtains the local box, which is the global calculated box of the total of subshapes
- SIMD_FORCE_INLINE const btAABB & getLocalBox()
+ SIMD_FORCE_INLINE const btAABB& getLocalBox()
{
return m_localAABB;
}
+ virtual int getShapeType() const
+ {
+ return GIMPACT_SHAPE_PROXYTYPE;
+ }
- virtual int getShapeType() const
- {
- return GIMPACT_SHAPE_PROXYTYPE;
- }
-
- /*!
+ /*!
\post You must call updateBound() for update the box set.
*/
- virtual void setLocalScaling(const btVector3& scaling)
+ virtual void setLocalScaling(const btVector3& scaling)
{
localScaling = scaling;
postUpdate();
@@ -171,46 +162,43 @@ public:
return localScaling;
}
-
virtual void setMargin(btScalar margin)
- {
- m_collisionMargin = margin;
- int i = getNumChildShapes();
- while(i--)
- {
+ {
+ m_collisionMargin = margin;
+ int i = getNumChildShapes();
+ while (i--)
+ {
btCollisionShape* child = getChildShape(i);
child->setMargin(margin);
- }
+ }
m_needs_update = true;
- }
-
+ }
//! Subshape member functions
//!@{
//! Base method for determinig which kind of GIMPACT shape we get
- virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() const = 0 ;
+ virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() const = 0;
//! gets boxset
- SIMD_FORCE_INLINE const btGImpactBoxSet * getBoxSet() const
+ SIMD_FORCE_INLINE const btGImpactBoxSet* getBoxSet() const
{
return &m_box_set;
}
//! Determines if this class has a hierarchy structure for sorting its primitives
- SIMD_FORCE_INLINE bool hasBoxSet() const
+ SIMD_FORCE_INLINE bool hasBoxSet() const
{
- if(m_box_set.getNodeCount() == 0) return false;
+ if (m_box_set.getNodeCount() == 0) return false;
return true;
}
//! Obtains the primitive manager
- virtual const btPrimitiveManagerBase * getPrimitiveManager() const = 0;
-
+ virtual const btPrimitiveManagerBase* getPrimitiveManager() const = 0;
//! Gets the number of children
- virtual int getNumChildShapes() const = 0;
+ virtual int getNumChildShapes() const = 0;
//! if true, then its children must get transforms.
virtual bool childrenHasTransform() const = 0;
@@ -221,11 +209,9 @@ public:
//! Determines if this shape has tetrahedrons
virtual bool needsRetrieveTetrahedrons() const = 0;
- virtual void getBulletTriangle(int prim_index,btTriangleShapeEx & triangle) const = 0;
-
- virtual void getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron) const = 0;
-
+ virtual void getBulletTriangle(int prim_index, btTriangleShapeEx& triangle) const = 0;
+ virtual void getBulletTetrahedron(int prim_index, btTetrahedronShapeEx& tetrahedron) const = 0;
//! call when reading child shapes
virtual void lockChildShapes() const
@@ -237,94 +223,91 @@ public:
}
//! if this trimesh
- SIMD_FORCE_INLINE void getPrimitiveTriangle(int index,btPrimitiveTriangle & triangle) const
+ SIMD_FORCE_INLINE void getPrimitiveTriangle(int index, btPrimitiveTriangle& triangle) const
{
- getPrimitiveManager()->get_primitive_triangle(index,triangle);
+ getPrimitiveManager()->get_primitive_triangle(index, triangle);
}
-
//! Retrieves the bound from a child
- /*!
+ /*!
*/
- virtual void getChildAabb(int child_index,const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
- {
- btAABB child_aabb;
- getPrimitiveManager()->get_primitive_box(child_index,child_aabb);
- child_aabb.appy_transform(t);
- aabbMin = child_aabb.m_min;
- aabbMax = child_aabb.m_max;
- }
+ virtual void getChildAabb(int child_index, const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
+ {
+ btAABB child_aabb;
+ getPrimitiveManager()->get_primitive_box(child_index, child_aabb);
+ child_aabb.appy_transform(t);
+ aabbMin = child_aabb.m_min;
+ aabbMax = child_aabb.m_max;
+ }
//! Gets the children
virtual btCollisionShape* getChildShape(int index) = 0;
-
//! Gets the child
virtual const btCollisionShape* getChildShape(int index) const = 0;
//! Gets the children transform
- virtual btTransform getChildTransform(int index) const = 0;
+ virtual btTransform getChildTransform(int index) const = 0;
//! Sets the children transform
/*!
\post You must call updateBound() for update the box set.
*/
- virtual void setChildTransform(int index, const btTransform & transform) = 0;
+ virtual void setChildTransform(int index, const btTransform& transform) = 0;
//!@}
-
//! virtual method for ray collision
- virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const
+ virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const
{
- (void) rayFrom; (void) rayTo; (void) resultCallback;
+ (void)rayFrom;
+ (void)rayTo;
+ (void)resultCallback;
}
//! Function for retrieve triangles.
/*!
It gives the triangles in local space
*/
- virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
+ virtual void processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
{
- (void) callback; (void) aabbMin; (void) aabbMax;
+ (void)callback;
+ (void)aabbMin;
+ (void)aabbMax;
}
//! Function for retrieve triangles.
/*!
It gives the triangles in local space
*/
- virtual void processAllTrianglesRay(btTriangleCallback* /*callback*/,const btVector3& /*rayFrom*/, const btVector3& /*rayTo*/) const
+ virtual void processAllTrianglesRay(btTriangleCallback* /*callback*/, const btVector3& /*rayFrom*/, const btVector3& /*rayTo*/) const
{
-
}
//!@}
-
};
-
//! btGImpactCompoundShape allows to handle multiple btCollisionShape objects at once
/*!
This class only can manage Convex subshapes
*/
-class btGImpactCompoundShape : public btGImpactShapeInterface
+class btGImpactCompoundShape : public btGImpactShapeInterface
{
public:
//! compound primitive manager
- class CompoundPrimitiveManager:public btPrimitiveManagerBase
+ class CompoundPrimitiveManager : public btPrimitiveManagerBase
{
public:
virtual ~CompoundPrimitiveManager() {}
- btGImpactCompoundShape * m_compoundShape;
-
+ btGImpactCompoundShape* m_compoundShape;
CompoundPrimitiveManager(const CompoundPrimitiveManager& compound)
- : btPrimitiveManagerBase()
+ : btPrimitiveManagerBase()
{
m_compoundShape = compound.m_compoundShape;
}
- CompoundPrimitiveManager(btGImpactCompoundShape * compoundShape)
+ CompoundPrimitiveManager(btGImpactCompoundShape* compoundShape)
{
m_compoundShape = compoundShape;
}
@@ -341,13 +324,13 @@ public:
virtual int get_primitive_count() const
{
- return (int )m_compoundShape->getNumChildShapes();
+ return (int)m_compoundShape->getNumChildShapes();
}
- virtual void get_primitive_box(int prim_index ,btAABB & primbox) const
+ virtual void get_primitive_box(int prim_index, btAABB& primbox) const
{
btTransform prim_trans;
- if(m_compoundShape->childrenHasTransform())
+ if (m_compoundShape->childrenHasTransform())
{
prim_trans = m_compoundShape->getChildTransform(prim_index);
}
@@ -356,30 +339,26 @@ public:
prim_trans.setIdentity();
}
const btCollisionShape* shape = m_compoundShape->getChildShape(prim_index);
- shape->getAabb(prim_trans,primbox.m_min,primbox.m_max);
+ shape->getAabb(prim_trans, primbox.m_min, primbox.m_max);
}
- virtual void get_primitive_triangle(int prim_index,btPrimitiveTriangle & triangle) const
+ virtual void get_primitive_triangle(int prim_index, btPrimitiveTriangle& triangle) const
{
btAssert(0);
- (void) prim_index; (void) triangle;
+ (void)prim_index;
+ (void)triangle;
}
-
};
-
-
protected:
CompoundPrimitiveManager m_primitive_manager;
- btAlignedObjectArray<btTransform> m_childTransforms;
- btAlignedObjectArray<btCollisionShape*> m_childShapes;
-
+ btAlignedObjectArray<btTransform> m_childTransforms;
+ btAlignedObjectArray<btCollisionShape*> m_childShapes;
public:
-
btGImpactCompoundShape(bool children_has_transform = true)
{
- (void) children_has_transform;
+ (void)children_has_transform;
m_primitive_manager.m_compoundShape = this;
m_box_set.setPrimitiveManager(&m_primitive_manager);
}
@@ -388,36 +367,33 @@ public:
{
}
-
//! if true, then its children must get transforms.
virtual bool childrenHasTransform() const
{
- if(m_childTransforms.size()==0) return false;
+ if (m_childTransforms.size() == 0) return false;
return true;
}
-
//! Obtains the primitive manager
- virtual const btPrimitiveManagerBase * getPrimitiveManager() const
+ virtual const btPrimitiveManagerBase* getPrimitiveManager() const
{
return &m_primitive_manager;
}
//! Obtains the compopund primitive manager
- SIMD_FORCE_INLINE CompoundPrimitiveManager * getCompoundPrimitiveManager()
+ SIMD_FORCE_INLINE CompoundPrimitiveManager* getCompoundPrimitiveManager()
{
return &m_primitive_manager;
}
//! Gets the number of children
- virtual int getNumChildShapes() const
+ virtual int getNumChildShapes() const
{
return m_childShapes.size();
}
-
//! Use this method for adding children. Only Convex shapes are allowed.
- void addChildShape(const btTransform& localTransform,btCollisionShape* shape)
+ void addChildShape(const btTransform& localTransform, btCollisionShape* shape)
{
btAssert(shape->isConvex());
m_childTransforms.push_back(localTransform);
@@ -444,24 +420,22 @@ public:
}
//! Retrieves the bound from a child
- /*!
+ /*!
*/
- virtual void getChildAabb(int child_index,const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
- {
-
- if(childrenHasTransform())
- {
- m_childShapes[child_index]->getAabb(t*m_childTransforms[child_index],aabbMin,aabbMax);
- }
- else
- {
- m_childShapes[child_index]->getAabb(t,aabbMin,aabbMax);
- }
- }
-
+ virtual void getChildAabb(int child_index, const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
+ {
+ if (childrenHasTransform())
+ {
+ m_childShapes[child_index]->getAabb(t * m_childTransforms[child_index], aabbMin, aabbMax);
+ }
+ else
+ {
+ m_childShapes[child_index]->getAabb(t, aabbMin, aabbMax);
+ }
+ }
//! Gets the children transform
- virtual btTransform getChildTransform(int index) const
+ virtual btTransform getChildTransform(int index) const
{
btAssert(m_childTransforms.size() == m_childShapes.size());
return m_childTransforms[index];
@@ -471,7 +445,7 @@ public:
/*!
\post You must call updateBound() for update the box set.
*/
- virtual void setChildTransform(int index, const btTransform & transform)
+ virtual void setChildTransform(int index, const btTransform& transform)
{
btAssert(m_childTransforms.size() == m_childShapes.size());
m_childTransforms[index] = transform;
@@ -490,24 +464,24 @@ public:
return false;
}
-
- virtual void getBulletTriangle(int prim_index,btTriangleShapeEx & triangle) const
+ virtual void getBulletTriangle(int prim_index, btTriangleShapeEx& triangle) const
{
- (void) prim_index; (void) triangle;
+ (void)prim_index;
+ (void)triangle;
btAssert(0);
}
- virtual void getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron) const
+ virtual void getBulletTetrahedron(int prim_index, btTetrahedronShapeEx& tetrahedron) const
{
- (void) prim_index; (void) tetrahedron;
+ (void)prim_index;
+ (void)tetrahedron;
btAssert(0);
}
-
//! Calculates the exact inertia tensor for this shape
- virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+ virtual void calculateLocalInertia(btScalar mass, btVector3& inertia) const;
- virtual const char* getName()const
+ virtual const char* getName() const
{
return "GImpactCompound";
}
@@ -516,11 +490,8 @@ public:
{
return CONST_GIMPACT_COMPOUND_SHAPE;
}
-
};
-
-
//! This class manages a sub part of a mesh supplied by the btStridingMeshInterface interface.
/*!
- Simply create this shape by passing the btStridingMeshInterface to the constructor btGImpactMeshShapePart, then you must call updateBound() after creating the mesh
@@ -535,21 +506,21 @@ public:
/*!
Manages the info from btStridingMeshInterface object and controls the Lock/Unlock mechanism
*/
- class TrimeshPrimitiveManager:public btPrimitiveManagerBase
+ class TrimeshPrimitiveManager : public btPrimitiveManagerBase
{
public:
btScalar m_margin;
- btStridingMeshInterface * m_meshInterface;
+ btStridingMeshInterface* m_meshInterface;
btVector3 m_scale;
int m_part;
int m_lock_count;
- const unsigned char *vertexbase;
+ const unsigned char* vertexbase;
int numverts;
PHY_ScalarType type;
int stride;
- const unsigned char *indexbase;
+ const unsigned char* indexbase;
int indexstride;
- int numfaces;
+ int numfaces;
PHY_ScalarType indicestype;
TrimeshPrimitiveManager()
@@ -557,7 +528,7 @@ public:
m_meshInterface = NULL;
m_part = 0;
m_margin = 0.01f;
- m_scale = btVector3(1.f,1.f,1.f);
+ m_scale = btVector3(1.f, 1.f, 1.f);
m_lock_count = 0;
vertexbase = 0;
numverts = 0;
@@ -567,8 +538,8 @@ public:
numfaces = 0;
}
- TrimeshPrimitiveManager(const TrimeshPrimitiveManager & manager)
- : btPrimitiveManagerBase()
+ TrimeshPrimitiveManager(const TrimeshPrimitiveManager& manager)
+ : btPrimitiveManagerBase()
{
m_meshInterface = manager.m_meshInterface;
m_part = manager.m_part;
@@ -581,11 +552,10 @@ public:
indexbase = 0;
indexstride = 0;
numfaces = 0;
-
}
TrimeshPrimitiveManager(
- btStridingMeshInterface * meshInterface, int part)
+ btStridingMeshInterface* meshInterface, int part)
{
m_meshInterface = meshInterface;
m_part = part;
@@ -598,29 +568,28 @@ public:
indexbase = 0;
indexstride = 0;
numfaces = 0;
-
}
virtual ~TrimeshPrimitiveManager() {}
void lock()
{
- if(m_lock_count>0)
+ if (m_lock_count > 0)
{
m_lock_count++;
return;
}
m_meshInterface->getLockedReadOnlyVertexIndexBase(
- &vertexbase,numverts,
- type, stride,&indexbase, indexstride, numfaces,indicestype,m_part);
+ &vertexbase, numverts,
+ type, stride, &indexbase, indexstride, numfaces, indicestype, m_part);
m_lock_count = 1;
}
void unlock()
{
- if(m_lock_count == 0) return;
- if(m_lock_count>1)
+ if (m_lock_count == 0) return;
+ if (m_lock_count > 1)
{
--m_lock_count;
return;
@@ -637,93 +606,91 @@ public:
virtual int get_primitive_count() const
{
- return (int )numfaces;
+ return (int)numfaces;
}
SIMD_FORCE_INLINE int get_vertex_count() const
{
- return (int )numverts;
+ return (int)numverts;
}
- SIMD_FORCE_INLINE void get_indices(int face_index,unsigned int &i0,unsigned int &i1,unsigned int &i2) const
+ SIMD_FORCE_INLINE void get_indices(int face_index, unsigned int& i0, unsigned int& i1, unsigned int& i2) const
{
- if(indicestype == PHY_SHORT)
+ if (indicestype == PHY_SHORT)
{
- unsigned short* s_indices = (unsigned short *)(indexbase + face_index * indexstride);
+ unsigned short* s_indices = (unsigned short*)(indexbase + face_index * indexstride);
i0 = s_indices[0];
i1 = s_indices[1];
i2 = s_indices[2];
}
else
{
- unsigned int * i_indices = (unsigned int *)(indexbase + face_index*indexstride);
+ unsigned int* i_indices = (unsigned int*)(indexbase + face_index * indexstride);
i0 = i_indices[0];
i1 = i_indices[1];
i2 = i_indices[2];
}
}
- SIMD_FORCE_INLINE void get_vertex(unsigned int vertex_index, btVector3 & vertex) const
+ SIMD_FORCE_INLINE void get_vertex(unsigned int vertex_index, btVector3& vertex) const
{
- if(type == PHY_DOUBLE)
+ if (type == PHY_DOUBLE)
{
- double * dvertices = (double *)(vertexbase + vertex_index*stride);
- vertex[0] = btScalar(dvertices[0]*m_scale[0]);
- vertex[1] = btScalar(dvertices[1]*m_scale[1]);
- vertex[2] = btScalar(dvertices[2]*m_scale[2]);
+ double* dvertices = (double*)(vertexbase + vertex_index * stride);
+ vertex[0] = btScalar(dvertices[0] * m_scale[0]);
+ vertex[1] = btScalar(dvertices[1] * m_scale[1]);
+ vertex[2] = btScalar(dvertices[2] * m_scale[2]);
}
else
{
- float * svertices = (float *)(vertexbase + vertex_index*stride);
- vertex[0] = svertices[0]*m_scale[0];
- vertex[1] = svertices[1]*m_scale[1];
- vertex[2] = svertices[2]*m_scale[2];
+ float* svertices = (float*)(vertexbase + vertex_index * stride);
+ vertex[0] = svertices[0] * m_scale[0];
+ vertex[1] = svertices[1] * m_scale[1];
+ vertex[2] = svertices[2] * m_scale[2];
}
}
- virtual void get_primitive_box(int prim_index ,btAABB & primbox) const
+ virtual void get_primitive_box(int prim_index, btAABB& primbox) const
{
- btPrimitiveTriangle triangle;
- get_primitive_triangle(prim_index,triangle);
+ btPrimitiveTriangle triangle;
+ get_primitive_triangle(prim_index, triangle);
primbox.calc_from_triangle_margin(
triangle.m_vertices[0],
- triangle.m_vertices[1],triangle.m_vertices[2],triangle.m_margin);
+ triangle.m_vertices[1], triangle.m_vertices[2], triangle.m_margin);
}
- virtual void get_primitive_triangle(int prim_index,btPrimitiveTriangle & triangle) const
+ virtual void get_primitive_triangle(int prim_index, btPrimitiveTriangle& triangle) const
{
unsigned int indices[3];
- get_indices(prim_index,indices[0],indices[1],indices[2]);
- get_vertex(indices[0],triangle.m_vertices[0]);
- get_vertex(indices[1],triangle.m_vertices[1]);
- get_vertex(indices[2],triangle.m_vertices[2]);
+ get_indices(prim_index, indices[0], indices[1], indices[2]);
+ get_vertex(indices[0], triangle.m_vertices[0]);
+ get_vertex(indices[1], triangle.m_vertices[1]);
+ get_vertex(indices[2], triangle.m_vertices[2]);
triangle.m_margin = m_margin;
}
- SIMD_FORCE_INLINE void get_bullet_triangle(int prim_index,btTriangleShapeEx & triangle) const
+ SIMD_FORCE_INLINE void get_bullet_triangle(int prim_index, btTriangleShapeEx& triangle) const
{
unsigned int indices[3];
- get_indices(prim_index,indices[0],indices[1],indices[2]);
- get_vertex(indices[0],triangle.m_vertices1[0]);
- get_vertex(indices[1],triangle.m_vertices1[1]);
- get_vertex(indices[2],triangle.m_vertices1[2]);
+ get_indices(prim_index, indices[0], indices[1], indices[2]);
+ get_vertex(indices[0], triangle.m_vertices1[0]);
+ get_vertex(indices[1], triangle.m_vertices1[1]);
+ get_vertex(indices[2], triangle.m_vertices1[2]);
triangle.setMargin(m_margin);
}
-
};
-
protected:
TrimeshPrimitiveManager m_primitive_manager;
-public:
+public:
btGImpactMeshShapePart()
{
m_box_set.setPrimitiveManager(&m_primitive_manager);
}
- btGImpactMeshShapePart( btStridingMeshInterface * meshInterface, int part );
- virtual ~btGImpactMeshShapePart();
+ btGImpactMeshShapePart(btStridingMeshInterface* meshInterface, int part);
+ virtual ~btGImpactMeshShapePart();
//! if true, then its children must get transforms.
virtual bool childrenHasTransform() const
@@ -731,40 +698,36 @@ public:
return false;
}
-
//! call when reading child shapes
- virtual void lockChildShapes() const;
- virtual void unlockChildShapes() const;
+ virtual void lockChildShapes() const;
+ virtual void unlockChildShapes() const;
//! Gets the number of children
- virtual int getNumChildShapes() const
+ virtual int getNumChildShapes() const
{
return m_primitive_manager.get_primitive_count();
}
-
//! Gets the children
virtual btCollisionShape* getChildShape(int index)
{
- (void) index;
+ (void)index;
btAssert(0);
return NULL;
}
-
-
//! Gets the child
virtual const btCollisionShape* getChildShape(int index) const
{
- (void) index;
+ (void)index;
btAssert(0);
return NULL;
}
//! Gets the children transform
- virtual btTransform getChildTransform(int index) const
+ virtual btTransform getChildTransform(int index) const
{
- (void) index;
+ (void)index;
btAssert(0);
return btTransform();
}
@@ -773,35 +736,27 @@ public:
/*!
\post You must call updateBound() for update the box set.
*/
- virtual void setChildTransform(int index, const btTransform & transform)
+ virtual void setChildTransform(int index, const btTransform& transform)
{
- (void) index;
- (void) transform;
+ (void)index;
+ (void)transform;
btAssert(0);
}
-
//! Obtains the primitive manager
- virtual const btPrimitiveManagerBase * getPrimitiveManager() const
+ virtual const btPrimitiveManagerBase* getPrimitiveManager() const
{
return &m_primitive_manager;
}
- SIMD_FORCE_INLINE TrimeshPrimitiveManager * getTrimeshPrimitiveManager()
+ SIMD_FORCE_INLINE TrimeshPrimitiveManager* getTrimeshPrimitiveManager()
{
return &m_primitive_manager;
}
+ virtual void calculateLocalInertia(btScalar mass, btVector3& inertia) const;
-
-
-
- virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
-
-
-
-
- virtual const char* getName()const
+ virtual const char* getName() const
{
return "GImpactMeshShapePart";
}
@@ -823,61 +778,58 @@ public:
return false;
}
- virtual void getBulletTriangle(int prim_index,btTriangleShapeEx & triangle) const
+ virtual void getBulletTriangle(int prim_index, btTriangleShapeEx& triangle) const
{
- m_primitive_manager.get_bullet_triangle(prim_index,triangle);
+ m_primitive_manager.get_bullet_triangle(prim_index, triangle);
}
- virtual void getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron) const
+ virtual void getBulletTetrahedron(int prim_index, btTetrahedronShapeEx& tetrahedron) const
{
- (void) prim_index;
- (void) tetrahedron;
+ (void)prim_index;
+ (void)tetrahedron;
btAssert(0);
}
-
-
SIMD_FORCE_INLINE int getVertexCount() const
{
return m_primitive_manager.get_vertex_count();
}
- SIMD_FORCE_INLINE void getVertex(int vertex_index, btVector3 & vertex) const
+ SIMD_FORCE_INLINE void getVertex(int vertex_index, btVector3& vertex) const
{
- m_primitive_manager.get_vertex(vertex_index,vertex);
+ m_primitive_manager.get_vertex(vertex_index, vertex);
}
SIMD_FORCE_INLINE void setMargin(btScalar margin)
- {
- m_primitive_manager.m_margin = margin;
- postUpdate();
- }
-
- SIMD_FORCE_INLINE btScalar getMargin() const
- {
- return m_primitive_manager.m_margin;
- }
-
- virtual void setLocalScaling(const btVector3& scaling)
- {
- m_primitive_manager.m_scale = scaling;
- postUpdate();
- }
-
- virtual const btVector3& getLocalScaling() const
- {
- return m_primitive_manager.m_scale;
- }
-
- SIMD_FORCE_INLINE int getPart() const
- {
- return (int)m_primitive_manager.m_part;
- }
-
- virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
- virtual void processAllTrianglesRay(btTriangleCallback* callback,const btVector3& rayFrom,const btVector3& rayTo) const;
-};
+ {
+ m_primitive_manager.m_margin = margin;
+ postUpdate();
+ }
+
+ SIMD_FORCE_INLINE btScalar getMargin() const
+ {
+ return m_primitive_manager.m_margin;
+ }
+
+ virtual void setLocalScaling(const btVector3& scaling)
+ {
+ m_primitive_manager.m_scale = scaling;
+ postUpdate();
+ }
+
+ virtual const btVector3& getLocalScaling() const
+ {
+ return m_primitive_manager.m_scale;
+ }
+ SIMD_FORCE_INLINE int getPart() const
+ {
+ return (int)m_primitive_manager.m_part;
+ }
+
+ virtual void processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const;
+ virtual void processAllTrianglesRay(btTriangleCallback* callback, const btVector3& rayFrom, const btVector3& rayTo) const;
+};
//! This class manages a mesh supplied by the btStridingMeshInterface interface.
/*!
@@ -893,29 +845,29 @@ class btGImpactMeshShape : public btGImpactShapeInterface
protected:
btAlignedObjectArray<btGImpactMeshShapePart*> m_mesh_parts;
- void buildMeshParts(btStridingMeshInterface * meshInterface)
+ void buildMeshParts(btStridingMeshInterface* meshInterface)
{
- for (int i=0;i<meshInterface->getNumSubParts() ;++i )
+ for (int i = 0; i < meshInterface->getNumSubParts(); ++i)
{
- btGImpactMeshShapePart * newpart = new btGImpactMeshShapePart(meshInterface,i);
+ btGImpactMeshShapePart* newpart = new btGImpactMeshShapePart(meshInterface, i);
m_mesh_parts.push_back(newpart);
}
}
//! use this function for perfofm refit in bounding boxes
- virtual void calcLocalAABB()
- {
- m_localAABB.invalidate();
- int i = m_mesh_parts.size();
- while(i--)
- {
- m_mesh_parts[i]->updateBound();
- m_localAABB.merge(m_mesh_parts[i]->getLocalBox());
- }
- }
+ virtual void calcLocalAABB()
+ {
+ m_localAABB.invalidate();
+ int i = m_mesh_parts.size();
+ while (i--)
+ {
+ m_mesh_parts[i]->updateBound();
+ m_localAABB.merge(m_mesh_parts[i]->getLocalBox());
+ }
+ }
public:
- btGImpactMeshShape(btStridingMeshInterface * meshInterface)
+ btGImpactMeshShape(btStridingMeshInterface* meshInterface)
{
m_meshInterface = meshInterface;
buildMeshParts(meshInterface);
@@ -924,15 +876,14 @@ public:
virtual ~btGImpactMeshShape()
{
int i = m_mesh_parts.size();
- while(i--)
- {
- btGImpactMeshShapePart * part = m_mesh_parts[i];
+ while (i--)
+ {
+ btGImpactMeshShapePart* part = m_mesh_parts[i];
delete part;
- }
+ }
m_mesh_parts.clear();
}
-
btStridingMeshInterface* getMeshInterface()
{
return m_meshInterface;
@@ -948,79 +899,73 @@ public:
return m_mesh_parts.size();
}
- btGImpactMeshShapePart * getMeshPart(int index)
+ btGImpactMeshShapePart* getMeshPart(int index)
{
return m_mesh_parts[index];
}
-
-
- const btGImpactMeshShapePart * getMeshPart(int index) const
+ const btGImpactMeshShapePart* getMeshPart(int index) const
{
return m_mesh_parts[index];
}
-
- virtual void setLocalScaling(const btVector3& scaling)
+ virtual void setLocalScaling(const btVector3& scaling)
{
localScaling = scaling;
int i = m_mesh_parts.size();
- while(i--)
- {
- btGImpactMeshShapePart * part = m_mesh_parts[i];
+ while (i--)
+ {
+ btGImpactMeshShapePart* part = m_mesh_parts[i];
part->setLocalScaling(scaling);
- }
+ }
m_needs_update = true;
}
virtual void setMargin(btScalar margin)
- {
- m_collisionMargin = margin;
+ {
+ m_collisionMargin = margin;
int i = m_mesh_parts.size();
- while(i--)
- {
- btGImpactMeshShapePart * part = m_mesh_parts[i];
+ while (i--)
+ {
+ btGImpactMeshShapePart* part = m_mesh_parts[i];
part->setMargin(margin);
- }
+ }
m_needs_update = true;
- }
+ }
//! Tells to this object that is needed to refit all the meshes
- virtual void postUpdate()
- {
+ virtual void postUpdate()
+ {
int i = m_mesh_parts.size();
- while(i--)
- {
- btGImpactMeshShapePart * part = m_mesh_parts[i];
+ while (i--)
+ {
+ btGImpactMeshShapePart* part = m_mesh_parts[i];
part->postUpdate();
- }
-
- m_needs_update = true;
- }
+ }
- virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+ m_needs_update = true;
+ }
+ virtual void calculateLocalInertia(btScalar mass, btVector3& inertia) const;
//! Obtains the primitive manager
- virtual const btPrimitiveManagerBase * getPrimitiveManager() const
+ virtual const btPrimitiveManagerBase* getPrimitiveManager() const
{
btAssert(0);
return NULL;
}
-
//! Gets the number of children
- virtual int getNumChildShapes() const
+ virtual int getNumChildShapes() const
{
btAssert(0);
return 0;
}
-
//! if true, then its children must get transforms.
virtual bool childrenHasTransform() const
{
@@ -1042,15 +987,17 @@ public:
return false;
}
- virtual void getBulletTriangle(int prim_index,btTriangleShapeEx & triangle) const
+ virtual void getBulletTriangle(int prim_index, btTriangleShapeEx& triangle) const
{
- (void) prim_index; (void) triangle;
+ (void)prim_index;
+ (void)triangle;
btAssert(0);
}
- virtual void getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron) const
+ virtual void getBulletTetrahedron(int prim_index, btTetrahedronShapeEx& tetrahedron) const
{
- (void) prim_index; (void) tetrahedron;
+ (void)prim_index;
+ (void)tetrahedron;
btAssert(0);
}
@@ -1065,39 +1012,38 @@ public:
btAssert(0);
}
-
-
-
//! Retrieves the bound from a child
- /*!
+ /*!
*/
- virtual void getChildAabb(int child_index,const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
- {
- (void) child_index; (void) t; (void) aabbMin; (void) aabbMax;
- btAssert(0);
- }
+ virtual void getChildAabb(int child_index, const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
+ {
+ (void)child_index;
+ (void)t;
+ (void)aabbMin;
+ (void)aabbMax;
+ btAssert(0);
+ }
//! Gets the children
virtual btCollisionShape* getChildShape(int index)
{
- (void) index;
+ (void)index;
btAssert(0);
return NULL;
}
-
//! Gets the child
virtual const btCollisionShape* getChildShape(int index) const
{
- (void) index;
+ (void)index;
btAssert(0);
return NULL;
}
//! Gets the children transform
- virtual btTransform getChildTransform(int index) const
+ virtual btTransform getChildTransform(int index) const
{
- (void) index;
+ (void)index;
btAssert(0);
return btTransform();
}
@@ -1106,59 +1052,56 @@ public:
/*!
\post You must call updateBound() for update the box set.
*/
- virtual void setChildTransform(int index, const btTransform & transform)
+ virtual void setChildTransform(int index, const btTransform& transform)
{
- (void) index; (void) transform;
+ (void)index;
+ (void)transform;
btAssert(0);
}
-
virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() const
{
return CONST_GIMPACT_TRIMESH_SHAPE;
}
-
- virtual const char* getName()const
+ virtual const char* getName() const
{
return "GImpactMesh";
}
- virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const;
+ virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const;
//! Function for retrieve triangles.
/*!
It gives the triangles in local space
*/
- virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+ virtual void processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const;
- virtual void processAllTrianglesRay (btTriangleCallback* callback,const btVector3& rayFrom,const btVector3& rayTo) const;
+ virtual void processAllTrianglesRay(btTriangleCallback* callback, const btVector3& rayFrom, const btVector3& rayTo) const;
- virtual int calculateSerializeBufferSize() const;
+ virtual int calculateSerializeBufferSize() const;
///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
};
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btGImpactMeshShapeData
+struct btGImpactMeshShapeData
{
- btCollisionShapeData m_collisionShapeData;
+ btCollisionShapeData m_collisionShapeData;
btStridingMeshInterfaceData m_meshInterface;
- btVector3FloatData m_localScaling;
+ btVector3FloatData m_localScaling;
- float m_collisionMargin;
+ float m_collisionMargin;
- int m_gimpactSubType;
+ int m_gimpactSubType;
};
-SIMD_FORCE_INLINE int btGImpactMeshShape::calculateSerializeBufferSize() const
+SIMD_FORCE_INLINE int btGImpactMeshShape::calculateSerializeBufferSize() const
{
return sizeof(btGImpactMeshShapeData);
}
-
-#endif //GIMPACT_MESH_SHAPE_H
+#endif //GIMPACT_MESH_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btGenericPoolAllocator.cpp b/thirdparty/bullet/BulletCollision/Gimpact/btGenericPoolAllocator.cpp
index 5d07d1adb9..bfdb3db5d0 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/btGenericPoolAllocator.cpp
+++ b/thirdparty/bullet/BulletCollision/Gimpact/btGenericPoolAllocator.cpp
@@ -20,48 +20,45 @@ subject to the following restrictions:
#include "btGenericPoolAllocator.h"
-
-
/// *************** btGenericMemoryPool ******************///////////
size_t btGenericMemoryPool::allocate_from_free_nodes(size_t num_elements)
{
size_t ptr = BT_UINT_MAX;
- if(m_free_nodes_count == 0) return BT_UINT_MAX;
+ if (m_free_nodes_count == 0) return BT_UINT_MAX;
// find an avaliable free node with the correct size
size_t revindex = m_free_nodes_count;
- while(revindex-- && ptr == BT_UINT_MAX)
+ while (revindex-- && ptr == BT_UINT_MAX)
{
- if(m_allocated_sizes[m_free_nodes[revindex]]>=num_elements)
+ if (m_allocated_sizes[m_free_nodes[revindex]] >= num_elements)
{
ptr = revindex;
}
}
- if(ptr == BT_UINT_MAX) return BT_UINT_MAX; // not found
-
+ if (ptr == BT_UINT_MAX) return BT_UINT_MAX; // not found
revindex = ptr;
ptr = m_free_nodes[revindex];
// post: ptr contains the node index, and revindex the index in m_free_nodes
- size_t finalsize = m_allocated_sizes[ptr];
+ size_t finalsize = m_allocated_sizes[ptr];
finalsize -= num_elements;
m_allocated_sizes[ptr] = num_elements;
// post: finalsize>=0, m_allocated_sizes[ptr] has the requested size
- if(finalsize>0) // preserve free node, there are some free memory
+ if (finalsize > 0) // preserve free node, there are some free memory
{
m_free_nodes[revindex] = ptr + num_elements;
m_allocated_sizes[ptr + num_elements] = finalsize;
}
- else // delete free node
+ else // delete free node
{
// swap with end
- m_free_nodes[revindex] = m_free_nodes[m_free_nodes_count-1];
+ m_free_nodes[revindex] = m_free_nodes[m_free_nodes_count - 1];
m_free_nodes_count--;
}
@@ -70,17 +67,16 @@ size_t btGenericMemoryPool::allocate_from_free_nodes(size_t num_elements)
size_t btGenericMemoryPool::allocate_from_pool(size_t num_elements)
{
- if(m_allocated_count+num_elements>m_max_element_count) return BT_UINT_MAX;
+ if (m_allocated_count + num_elements > m_max_element_count) return BT_UINT_MAX;
size_t ptr = m_allocated_count;
m_allocated_sizes[m_allocated_count] = num_elements;
- m_allocated_count+=num_elements;
+ m_allocated_count += num_elements;
return ptr;
}
-
void btGenericMemoryPool::init_pool(size_t element_size, size_t element_count)
{
m_allocated_count = 0;
@@ -89,14 +85,11 @@ void btGenericMemoryPool::init_pool(size_t element_size, size_t element_count)
m_element_size = element_size;
m_max_element_count = element_count;
+ m_pool = (unsigned char *)btAlignedAlloc(m_element_size * m_max_element_count, 16);
+ m_free_nodes = (size_t *)btAlignedAlloc(sizeof(size_t) * m_max_element_count, 16);
+ m_allocated_sizes = (size_t *)btAlignedAlloc(sizeof(size_t) * m_max_element_count, 16);
-
-
- m_pool = (unsigned char *) btAlignedAlloc(m_element_size*m_max_element_count,16);
- m_free_nodes = (size_t *) btAlignedAlloc(sizeof(size_t)*m_max_element_count,16);
- m_allocated_sizes = (size_t *) btAlignedAlloc(sizeof(size_t)*m_max_element_count,16);
-
- for (size_t i = 0;i< m_max_element_count;i++ )
+ for (size_t i = 0; i < m_max_element_count; i++)
{
m_allocated_sizes[i] = 0;
}
@@ -111,150 +104,141 @@ void btGenericMemoryPool::end_pool()
m_free_nodes_count = 0;
}
-
//! Allocates memory in pool
/*!
\param size_bytes size in bytes of the buffer
*/
-void * btGenericMemoryPool::allocate(size_t size_bytes)
+void *btGenericMemoryPool::allocate(size_t size_bytes)
{
-
- size_t module = size_bytes%m_element_size;
- size_t element_count = size_bytes/m_element_size;
- if(module>0) element_count++;
+ size_t module = size_bytes % m_element_size;
+ size_t element_count = size_bytes / m_element_size;
+ if (module > 0) element_count++;
size_t alloc_pos = allocate_from_free_nodes(element_count);
// a free node is found
- if(alloc_pos != BT_UINT_MAX)
+ if (alloc_pos != BT_UINT_MAX)
{
return get_element_data(alloc_pos);
}
// allocate directly on pool
alloc_pos = allocate_from_pool(element_count);
- if(alloc_pos == BT_UINT_MAX) return NULL; // not space
+ if (alloc_pos == BT_UINT_MAX) return NULL; // not space
return get_element_data(alloc_pos);
}
-bool btGenericMemoryPool::freeMemory(void * pointer)
+bool btGenericMemoryPool::freeMemory(void *pointer)
{
- unsigned char * pointer_pos = (unsigned char *)pointer;
- unsigned char * pool_pos = (unsigned char *)m_pool;
+ unsigned char *pointer_pos = (unsigned char *)pointer;
+ unsigned char *pool_pos = (unsigned char *)m_pool;
// calc offset
- if(pointer_pos<pool_pos) return false;//other pool
+ if (pointer_pos < pool_pos) return false; //other pool
size_t offset = size_t(pointer_pos - pool_pos);
- if(offset>=get_pool_capacity()) return false;// far away
+ if (offset >= get_pool_capacity()) return false; // far away
// find free position
- m_free_nodes[m_free_nodes_count] = offset/m_element_size;
+ m_free_nodes[m_free_nodes_count] = offset / m_element_size;
m_free_nodes_count++;
return true;
}
-
/// *******************! btGenericPoolAllocator *******************!///
-
btGenericPoolAllocator::~btGenericPoolAllocator()
{
// destroy pools
size_t i;
- for (i=0;i<m_pool_count;i++)
+ for (i = 0; i < m_pool_count; i++)
{
m_pools[i]->end_pool();
btAlignedFree(m_pools[i]);
}
}
-
// creates a pool
-btGenericMemoryPool * btGenericPoolAllocator::push_new_pool()
+btGenericMemoryPool *btGenericPoolAllocator::push_new_pool()
{
- if(m_pool_count >= BT_DEFAULT_MAX_POOLS) return NULL;
+ if (m_pool_count >= BT_DEFAULT_MAX_POOLS) return NULL;
- btGenericMemoryPool * newptr = (btGenericMemoryPool *)btAlignedAlloc(sizeof(btGenericMemoryPool),16);
+ btGenericMemoryPool *newptr = (btGenericMemoryPool *)btAlignedAlloc(sizeof(btGenericMemoryPool), 16);
m_pools[m_pool_count] = newptr;
- m_pools[m_pool_count]->init_pool(m_pool_element_size,m_pool_element_count);
+ m_pools[m_pool_count]->init_pool(m_pool_element_size, m_pool_element_count);
m_pool_count++;
return newptr;
}
-void * btGenericPoolAllocator::failback_alloc(size_t size_bytes)
+void *btGenericPoolAllocator::failback_alloc(size_t size_bytes)
{
+ btGenericMemoryPool *pool = NULL;
- btGenericMemoryPool * pool = NULL;
-
-
- if(size_bytes<=get_pool_capacity())
+ if (size_bytes <= get_pool_capacity())
{
- pool = push_new_pool();
+ pool = push_new_pool();
}
- if(pool==NULL) // failback
+ if (pool == NULL) // failback
{
- return btAlignedAlloc(size_bytes,16);
+ return btAlignedAlloc(size_bytes, 16);
}
return pool->allocate(size_bytes);
}
-bool btGenericPoolAllocator::failback_free(void * pointer)
+bool btGenericPoolAllocator::failback_free(void *pointer)
{
btAlignedFree(pointer);
return true;
}
-
//! Allocates memory in pool
/*!
\param size_bytes size in bytes of the buffer
*/
-void * btGenericPoolAllocator::allocate(size_t size_bytes)
+void *btGenericPoolAllocator::allocate(size_t size_bytes)
{
- void * ptr = NULL;
+ void *ptr = NULL;
size_t i = 0;
- while(i<m_pool_count && ptr == NULL)
+ while (i < m_pool_count && ptr == NULL)
{
ptr = m_pools[i]->allocate(size_bytes);
++i;
}
- if(ptr) return ptr;
+ if (ptr) return ptr;
return failback_alloc(size_bytes);
}
-bool btGenericPoolAllocator::freeMemory(void * pointer)
+bool btGenericPoolAllocator::freeMemory(void *pointer)
{
bool result = false;
size_t i = 0;
- while(i<m_pool_count && result == false)
+ while (i < m_pool_count && result == false)
{
result = m_pools[i]->freeMemory(pointer);
++i;
}
- if(result) return true;
+ if (result) return true;
return failback_free(pointer);
}
/// ************** STANDARD ALLOCATOR ***************************///
-
#define BT_DEFAULT_POOL_SIZE 32768
#define BT_DEFAULT_POOL_ELEMENT_SIZE 8
// main allocator
-class GIM_STANDARD_ALLOCATOR: public btGenericPoolAllocator
+class GIM_STANDARD_ALLOCATOR : public btGenericPoolAllocator
{
public:
- GIM_STANDARD_ALLOCATOR():btGenericPoolAllocator(BT_DEFAULT_POOL_ELEMENT_SIZE,BT_DEFAULT_POOL_SIZE)
+ GIM_STANDARD_ALLOCATOR() : btGenericPoolAllocator(BT_DEFAULT_POOL_ELEMENT_SIZE, BT_DEFAULT_POOL_SIZE)
{
}
};
@@ -262,19 +246,18 @@ public:
// global allocator
GIM_STANDARD_ALLOCATOR g_main_allocator;
-
-void * btPoolAlloc(size_t size)
+void *btPoolAlloc(size_t size)
{
return g_main_allocator.allocate(size);
}
-void * btPoolRealloc(void *ptr, size_t oldsize, size_t newsize)
+void *btPoolRealloc(void *ptr, size_t oldsize, size_t newsize)
{
- void * newptr = btPoolAlloc(newsize);
- size_t copysize = oldsize<newsize?oldsize:newsize;
- memcpy(newptr,ptr,copysize);
- btPoolFree(ptr);
- return newptr;
+ void *newptr = btPoolAlloc(newsize);
+ size_t copysize = oldsize < newsize ? oldsize : newsize;
+ memcpy(newptr, ptr, copysize);
+ btPoolFree(ptr);
+ return newptr;
}
void btPoolFree(void *ptr)
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btGenericPoolAllocator.h b/thirdparty/bullet/BulletCollision/Gimpact/btGenericPoolAllocator.h
index b46d851634..a535088e48 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/btGenericPoolAllocator.h
+++ b/thirdparty/bullet/BulletCollision/Gimpact/btGenericPoolAllocator.h
@@ -29,16 +29,16 @@ subject to the following restrictions:
#define BT_UINT_MAX UINT_MAX
#define BT_DEFAULT_MAX_POOLS 16
-
//! Generic Pool class
class btGenericMemoryPool
{
public:
- unsigned char * m_pool; //[m_element_size*m_max_element_count];
- size_t * m_free_nodes; //[m_max_element_count];//! free nodes
- size_t * m_allocated_sizes;//[m_max_element_count];//! Number of elements allocated per node
+ unsigned char *m_pool; //[m_element_size*m_max_element_count];
+ size_t *m_free_nodes; //[m_max_element_count];//! free nodes
+ size_t *m_allocated_sizes; //[m_max_element_count];//! Number of elements allocated per node
size_t m_allocated_count;
size_t m_free_nodes_count;
+
protected:
size_t m_element_size;
size_t m_max_element_count;
@@ -47,12 +47,10 @@ protected:
size_t allocate_from_pool(size_t num_elements);
public:
-
void init_pool(size_t element_size, size_t element_count);
void end_pool();
-
btGenericMemoryPool(size_t element_size, size_t element_count)
{
init_pool(element_size, element_count);
@@ -63,10 +61,9 @@ public:
end_pool();
}
-
inline size_t get_pool_capacity()
{
- return m_element_size*m_max_element_count;
+ return m_element_size * m_max_element_count;
}
inline size_t gem_element_size()
@@ -89,23 +86,20 @@ public:
return m_free_nodes_count;
}
- inline void * get_element_data(size_t element_index)
+ inline void *get_element_data(size_t element_index)
{
- return &m_pool[element_index*m_element_size];
+ return &m_pool[element_index * m_element_size];
}
//! Allocates memory in pool
/*!
\param size_bytes size in bytes of the buffer
*/
- void * allocate(size_t size_bytes);
+ void *allocate(size_t size_bytes);
- bool freeMemory(void * pointer);
+ bool freeMemory(void *pointer);
};
-
-
-
//! Generic Allocator with pools
/*!
General purpose Allocator which can create Memory Pools dynamiacally as needed.
@@ -115,26 +109,25 @@ class btGenericPoolAllocator
protected:
size_t m_pool_element_size;
size_t m_pool_element_count;
+
public:
- btGenericMemoryPool * m_pools[BT_DEFAULT_MAX_POOLS];
+ btGenericMemoryPool *m_pools[BT_DEFAULT_MAX_POOLS];
size_t m_pool_count;
-
inline size_t get_pool_capacity()
{
- return m_pool_element_size*m_pool_element_count;
+ return m_pool_element_size * m_pool_element_count;
}
-
protected:
// creates a pool
- btGenericMemoryPool * push_new_pool();
+ btGenericMemoryPool *push_new_pool();
- void * failback_alloc(size_t size_bytes);
+ void *failback_alloc(size_t size_bytes);
- bool failback_free(void * pointer);
-public:
+ bool failback_free(void *pointer);
+public:
btGenericPoolAllocator(size_t pool_element_size, size_t pool_element_count)
{
m_pool_count = 0;
@@ -148,16 +141,13 @@ public:
/*!
\param size_bytes size in bytes of the buffer
*/
- void * allocate(size_t size_bytes);
+ void *allocate(size_t size_bytes);
- bool freeMemory(void * pointer);
+ bool freeMemory(void *pointer);
};
-
-
-void * btPoolAlloc(size_t size);
-void * btPoolRealloc(void *ptr, size_t oldsize, size_t newsize);
+void *btPoolAlloc(size_t size);
+void *btPoolRealloc(void *ptr, size_t oldsize, size_t newsize);
void btPoolFree(void *ptr);
-
#endif
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btGeometryOperations.h b/thirdparty/bullet/BulletCollision/Gimpact/btGeometryOperations.h
index 60f06510ad..6a1ee6dcf9 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/btGeometryOperations.h
+++ b/thirdparty/bullet/BulletCollision/Gimpact/btGeometryOperations.h
@@ -27,52 +27,44 @@ subject to the following restrictions:
#include "btBoxCollision.h"
-
-
-
-
#define PLANEDIREPSILON 0.0000001f
#define PARALELENORMALS 0.000001f
-
-#define BT_CLAMP(number,minval,maxval) (number<minval?minval:(number>maxval?maxval:number))
+#define BT_CLAMP(number, minval, maxval) (number < minval ? minval : (number > maxval ? maxval : number))
/// Calc a plane from a triangle edge an a normal. plane is a vec4f
-SIMD_FORCE_INLINE void bt_edge_plane(const btVector3 & e1,const btVector3 & e2, const btVector3 & normal,btVector4 & plane)
+SIMD_FORCE_INLINE void bt_edge_plane(const btVector3 &e1, const btVector3 &e2, const btVector3 &normal, btVector4 &plane)
{
- btVector3 planenormal = (e2-e1).cross(normal);
+ btVector3 planenormal = (e2 - e1).cross(normal);
planenormal.normalize();
- plane.setValue(planenormal[0],planenormal[1],planenormal[2],e2.dot(planenormal));
+ plane.setValue(planenormal[0], planenormal[1], planenormal[2], e2.dot(planenormal));
}
-
-
//***************** SEGMENT and LINE FUNCTIONS **********************************///
/*! Finds the closest point(cp) to (v) on a segment (e1,e2)
*/
SIMD_FORCE_INLINE void bt_closest_point_on_segment(
- btVector3 & cp, const btVector3 & v,
- const btVector3 &e1,const btVector3 &e2)
+ btVector3 &cp, const btVector3 &v,
+ const btVector3 &e1, const btVector3 &e2)
{
- btVector3 n = e2-e1;
- cp = v - e1;
- btScalar _scalar = cp.dot(n)/n.dot(n);
- if(_scalar <0.0f)
+ btVector3 n = e2 - e1;
+ cp = v - e1;
+ btScalar _scalar = cp.dot(n) / n.dot(n);
+ if (_scalar < 0.0f)
{
- cp = e1;
+ cp = e1;
}
- else if(_scalar >1.0f)
+ else if (_scalar > 1.0f)
{
- cp = e2;
+ cp = e2;
}
else
{
- cp = _scalar*n + e1;
+ cp = _scalar * n + e1;
}
}
-
//! line plane collision
/*!
*\return
@@ -82,131 +74,125 @@ SIMD_FORCE_INLINE void bt_closest_point_on_segment(
*/
SIMD_FORCE_INLINE int bt_line_plane_collision(
- const btVector4 & plane,
- const btVector3 & vDir,
- const btVector3 & vPoint,
- btVector3 & pout,
+ const btVector4 &plane,
+ const btVector3 &vDir,
+ const btVector3 &vPoint,
+ btVector3 &pout,
btScalar &tparam,
btScalar tmin, btScalar tmax)
{
-
btScalar _dotdir = vDir.dot(plane);
- if(btFabs(_dotdir)<PLANEDIREPSILON)
+ if (btFabs(_dotdir) < PLANEDIREPSILON)
{
tparam = tmax;
- return 0;
+ return 0;
}
- btScalar _dis = bt_distance_point_plane(plane,vPoint);
- char returnvalue = _dis<0.0f? 2:1;
- tparam = -_dis/_dotdir;
+ btScalar _dis = bt_distance_point_plane(plane, vPoint);
+ char returnvalue = _dis < 0.0f ? 2 : 1;
+ tparam = -_dis / _dotdir;
- if(tparam<tmin)
+ if (tparam < tmin)
{
returnvalue = 0;
tparam = tmin;
}
- else if(tparam>tmax)
+ else if (tparam > tmax)
{
returnvalue = 0;
tparam = tmax;
}
- pout = tparam*vDir + vPoint;
+ pout = tparam * vDir + vPoint;
return returnvalue;
}
-
//! Find closest points on segments
SIMD_FORCE_INLINE void bt_segment_collision(
- const btVector3 & vA1,
- const btVector3 & vA2,
- const btVector3 & vB1,
- const btVector3 & vB2,
- btVector3 & vPointA,
- btVector3 & vPointB)
+ const btVector3 &vA1,
+ const btVector3 &vA2,
+ const btVector3 &vB1,
+ const btVector3 &vB2,
+ btVector3 &vPointA,
+ btVector3 &vPointB)
{
- btVector3 AD = vA2 - vA1;
- btVector3 BD = vB2 - vB1;
- btVector3 N = AD.cross(BD);
- btScalar tp = N.length2();
-
- btVector4 _M;//plane
-
- if(tp<SIMD_EPSILON)//ARE PARALELE
- {
- //project B over A
- bool invert_b_order = false;
- _M[0] = vB1.dot(AD);
- _M[1] = vB2.dot(AD);
-
- if(_M[0]>_M[1])
- {
- invert_b_order = true;
- BT_SWAP_NUMBERS(_M[0],_M[1]);
- }
- _M[2] = vA1.dot(AD);
- _M[3] = vA2.dot(AD);
- //mid points
- N[0] = (_M[0]+_M[1])*0.5f;
- N[1] = (_M[2]+_M[3])*0.5f;
-
- if(N[0]<N[1])
- {
- if(_M[1]<_M[2])
- {
- vPointB = invert_b_order?vB1:vB2;
- vPointA = vA1;
- }
- else if(_M[1]<_M[3])
- {
- vPointB = invert_b_order?vB1:vB2;
- bt_closest_point_on_segment(vPointA,vPointB,vA1,vA2);
- }
- else
- {
- vPointA = vA2;
- bt_closest_point_on_segment(vPointB,vPointA,vB1,vB2);
- }
- }
- else
- {
- if(_M[3]<_M[0])
- {
- vPointB = invert_b_order?vB2:vB1;
- vPointA = vA2;
- }
- else if(_M[3]<_M[1])
- {
- vPointA = vA2;
- bt_closest_point_on_segment(vPointB,vPointA,vB1,vB2);
- }
- else
- {
- vPointB = invert_b_order?vB1:vB2;
- bt_closest_point_on_segment(vPointA,vPointB,vA1,vA2);
- }
- }
- return;
- }
-
- N = N.cross(BD);
- _M.setValue(N[0],N[1],N[2],vB1.dot(N));
+ btVector3 AD = vA2 - vA1;
+ btVector3 BD = vB2 - vB1;
+ btVector3 N = AD.cross(BD);
+ btScalar tp = N.length2();
- // get point A as the plane collision point
- bt_line_plane_collision(_M,AD,vA1,vPointA,tp,btScalar(0), btScalar(1));
-
- /*Closest point on segment*/
- vPointB = vPointA - vB1;
- tp = vPointB.dot(BD);
- tp/= BD.dot(BD);
- tp = BT_CLAMP(tp,0.0f,1.0f);
+ btVector4 _M; //plane
- vPointB = tp*BD + vB1;
-}
+ if (tp < SIMD_EPSILON) //ARE PARALELE
+ {
+ //project B over A
+ bool invert_b_order = false;
+ _M[0] = vB1.dot(AD);
+ _M[1] = vB2.dot(AD);
+
+ if (_M[0] > _M[1])
+ {
+ invert_b_order = true;
+ BT_SWAP_NUMBERS(_M[0], _M[1]);
+ }
+ _M[2] = vA1.dot(AD);
+ _M[3] = vA2.dot(AD);
+ //mid points
+ N[0] = (_M[0] + _M[1]) * 0.5f;
+ N[1] = (_M[2] + _M[3]) * 0.5f;
+
+ if (N[0] < N[1])
+ {
+ if (_M[1] < _M[2])
+ {
+ vPointB = invert_b_order ? vB1 : vB2;
+ vPointA = vA1;
+ }
+ else if (_M[1] < _M[3])
+ {
+ vPointB = invert_b_order ? vB1 : vB2;
+ bt_closest_point_on_segment(vPointA, vPointB, vA1, vA2);
+ }
+ else
+ {
+ vPointA = vA2;
+ bt_closest_point_on_segment(vPointB, vPointA, vB1, vB2);
+ }
+ }
+ else
+ {
+ if (_M[3] < _M[0])
+ {
+ vPointB = invert_b_order ? vB2 : vB1;
+ vPointA = vA2;
+ }
+ else if (_M[3] < _M[1])
+ {
+ vPointA = vA2;
+ bt_closest_point_on_segment(vPointB, vPointA, vB1, vB2);
+ }
+ else
+ {
+ vPointB = invert_b_order ? vB1 : vB2;
+ bt_closest_point_on_segment(vPointA, vPointB, vA1, vA2);
+ }
+ }
+ return;
+ }
+ N = N.cross(BD);
+ _M.setValue(N[0], N[1], N[2], vB1.dot(N));
+ // get point A as the plane collision point
+ bt_line_plane_collision(_M, AD, vA1, vPointA, tp, btScalar(0), btScalar(1));
+ /*Closest point on segment*/
+ vPointB = vPointA - vB1;
+ tp = vPointB.dot(BD);
+ tp /= BD.dot(BD);
+ tp = BT_CLAMP(tp, 0.0f, 1.0f);
+ vPointB = tp * BD + vB1;
+}
-#endif // GIM_VECTOR_H_INCLUDED
+#endif // GIM_VECTOR_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btQuantization.h b/thirdparty/bullet/BulletCollision/Gimpact/btQuantization.h
index bd2633cfc5..19a02a2177 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/btQuantization.h
+++ b/thirdparty/bullet/BulletCollision/Gimpact/btQuantization.h
@@ -27,54 +27,47 @@ subject to the following restrictions:
#include "LinearMath/btTransform.h"
-
-
-
-
-
SIMD_FORCE_INLINE void bt_calc_quantization_parameters(
- btVector3 & outMinBound,
- btVector3 & outMaxBound,
- btVector3 & bvhQuantization,
- const btVector3& srcMinBound,const btVector3& srcMaxBound,
+ btVector3& outMinBound,
+ btVector3& outMaxBound,
+ btVector3& bvhQuantization,
+ const btVector3& srcMinBound, const btVector3& srcMaxBound,
btScalar quantizationMargin)
{
//enlarge the AABB to avoid division by zero when initializing the quantization values
- btVector3 clampValue(quantizationMargin,quantizationMargin,quantizationMargin);
+ btVector3 clampValue(quantizationMargin, quantizationMargin, quantizationMargin);
outMinBound = srcMinBound - clampValue;
outMaxBound = srcMaxBound + clampValue;
btVector3 aabbSize = outMaxBound - outMinBound;
bvhQuantization = btVector3(btScalar(65535.0),
btScalar(65535.0),
- btScalar(65535.0)) / aabbSize;
+ btScalar(65535.0)) /
+ aabbSize;
}
-
SIMD_FORCE_INLINE void bt_quantize_clamp(
unsigned short* out,
const btVector3& point,
- const btVector3 & min_bound,
- const btVector3 & max_bound,
- const btVector3 & bvhQuantization)
+ const btVector3& min_bound,
+ const btVector3& max_bound,
+ const btVector3& bvhQuantization)
{
-
btVector3 clampedPoint(point);
clampedPoint.setMax(min_bound);
clampedPoint.setMin(max_bound);
btVector3 v = (clampedPoint - min_bound) * bvhQuantization;
- out[0] = (unsigned short)(v.getX()+0.5f);
- out[1] = (unsigned short)(v.getY()+0.5f);
- out[2] = (unsigned short)(v.getZ()+0.5f);
+ out[0] = (unsigned short)(v.getX() + 0.5f);
+ out[1] = (unsigned short)(v.getY() + 0.5f);
+ out[2] = (unsigned short)(v.getZ() + 0.5f);
}
-
SIMD_FORCE_INLINE btVector3 bt_unquantize(
const unsigned short* vecIn,
- const btVector3 & offset,
- const btVector3 & bvhQuantization)
+ const btVector3& offset,
+ const btVector3& bvhQuantization)
{
- btVector3 vecOut;
+ btVector3 vecOut;
vecOut.setValue(
(btScalar)(vecIn[0]) / (bvhQuantization.getX()),
(btScalar)(vecIn[1]) / (bvhQuantization.getY()),
@@ -83,6 +76,4 @@ SIMD_FORCE_INLINE btVector3 bt_unquantize(
return vecOut;
}
-
-
-#endif // BT_GIMPACT_QUANTIZATION_H_INCLUDED
+#endif // BT_GIMPACT_QUANTIZATION_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btTriangleShapeEx.cpp b/thirdparty/bullet/BulletCollision/Gimpact/btTriangleShapeEx.cpp
index ca76cc54a1..292ef8c1ff 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/btTriangleShapeEx.cpp
+++ b/thirdparty/bullet/BulletCollision/Gimpact/btTriangleShapeEx.cpp
@@ -23,196 +23,181 @@ subject to the following restrictions:
#include "btTriangleShapeEx.h"
-
-
-void GIM_TRIANGLE_CONTACT::merge_points(const btVector4 & plane,
- btScalar margin, const btVector3 * points, int point_count)
+void GIM_TRIANGLE_CONTACT::merge_points(const btVector4& plane,
+ btScalar margin, const btVector3* points, int point_count)
{
- m_point_count = 0;
- m_penetration_depth= -1000.0f;
+ m_point_count = 0;
+ m_penetration_depth = -1000.0f;
- int point_indices[MAX_TRI_CLIPPING];
+ int point_indices[MAX_TRI_CLIPPING];
int _k;
- for ( _k=0;_k<point_count;_k++)
- {
- btScalar _dist = - bt_distance_point_plane(plane,points[_k]) + margin;
-
- if (_dist>=0.0f)
- {
- if (_dist>m_penetration_depth)
- {
- m_penetration_depth = _dist;
- point_indices[0] = _k;
- m_point_count=1;
- }
- else if ((_dist+SIMD_EPSILON)>=m_penetration_depth)
- {
- point_indices[m_point_count] = _k;
- m_point_count++;
- }
- }
- }
-
- for ( _k=0;_k<m_point_count;_k++)
- {
- m_points[_k] = points[point_indices[_k]];
- }
+ for (_k = 0; _k < point_count; _k++)
+ {
+ btScalar _dist = -bt_distance_point_plane(plane, points[_k]) + margin;
+
+ if (_dist >= 0.0f)
+ {
+ if (_dist > m_penetration_depth)
+ {
+ m_penetration_depth = _dist;
+ point_indices[0] = _k;
+ m_point_count = 1;
+ }
+ else if ((_dist + SIMD_EPSILON) >= m_penetration_depth)
+ {
+ point_indices[m_point_count] = _k;
+ m_point_count++;
+ }
+ }
+ }
+
+ for (_k = 0; _k < m_point_count; _k++)
+ {
+ m_points[_k] = points[point_indices[_k]];
+ }
}
///class btPrimitiveTriangle
bool btPrimitiveTriangle::overlap_test_conservative(const btPrimitiveTriangle& other)
{
- btScalar total_margin = m_margin + other.m_margin;
- // classify points on other triangle
- btScalar dis0 = bt_distance_point_plane(m_plane,other.m_vertices[0]) - total_margin;
+ btScalar total_margin = m_margin + other.m_margin;
+ // classify points on other triangle
+ btScalar dis0 = bt_distance_point_plane(m_plane, other.m_vertices[0]) - total_margin;
- btScalar dis1 = bt_distance_point_plane(m_plane,other.m_vertices[1]) - total_margin;
+ btScalar dis1 = bt_distance_point_plane(m_plane, other.m_vertices[1]) - total_margin;
- btScalar dis2 = bt_distance_point_plane(m_plane,other.m_vertices[2]) - total_margin;
+ btScalar dis2 = bt_distance_point_plane(m_plane, other.m_vertices[2]) - total_margin;
- if (dis0>0.0f&&dis1>0.0f&&dis2>0.0f) return false;
+ if (dis0 > 0.0f && dis1 > 0.0f && dis2 > 0.0f) return false;
- // classify points on this triangle
- dis0 = bt_distance_point_plane(other.m_plane,m_vertices[0]) - total_margin;
+ // classify points on this triangle
+ dis0 = bt_distance_point_plane(other.m_plane, m_vertices[0]) - total_margin;
- dis1 = bt_distance_point_plane(other.m_plane,m_vertices[1]) - total_margin;
+ dis1 = bt_distance_point_plane(other.m_plane, m_vertices[1]) - total_margin;
- dis2 = bt_distance_point_plane(other.m_plane,m_vertices[2]) - total_margin;
+ dis2 = bt_distance_point_plane(other.m_plane, m_vertices[2]) - total_margin;
- if (dis0>0.0f&&dis1>0.0f&&dis2>0.0f) return false;
+ if (dis0 > 0.0f && dis1 > 0.0f && dis2 > 0.0f) return false;
- return true;
+ return true;
}
-int btPrimitiveTriangle::clip_triangle(btPrimitiveTriangle & other, btVector3 * clipped_points )
+int btPrimitiveTriangle::clip_triangle(btPrimitiveTriangle& other, btVector3* clipped_points)
{
- // edge 0
-
- btVector3 temp_points[MAX_TRI_CLIPPING];
-
+ // edge 0
- btVector4 edgeplane;
+ btVector3 temp_points[MAX_TRI_CLIPPING];
- get_edge_plane(0,edgeplane);
+ btVector4 edgeplane;
+ get_edge_plane(0, edgeplane);
- int clipped_count = bt_plane_clip_triangle(
- edgeplane,other.m_vertices[0],other.m_vertices[1],other.m_vertices[2],temp_points);
+ int clipped_count = bt_plane_clip_triangle(
+ edgeplane, other.m_vertices[0], other.m_vertices[1], other.m_vertices[2], temp_points);
- if (clipped_count == 0) return 0;
+ if (clipped_count == 0) return 0;
- btVector3 temp_points1[MAX_TRI_CLIPPING];
+ btVector3 temp_points1[MAX_TRI_CLIPPING];
+ // edge 1
+ get_edge_plane(1, edgeplane);
- // edge 1
- get_edge_plane(1,edgeplane);
+ clipped_count = bt_plane_clip_polygon(edgeplane, temp_points, clipped_count, temp_points1);
+ if (clipped_count == 0) return 0;
- clipped_count = bt_plane_clip_polygon(edgeplane,temp_points,clipped_count,temp_points1);
+ // edge 2
+ get_edge_plane(2, edgeplane);
- if (clipped_count == 0) return 0;
+ clipped_count = bt_plane_clip_polygon(
+ edgeplane, temp_points1, clipped_count, clipped_points);
- // edge 2
- get_edge_plane(2,edgeplane);
-
- clipped_count = bt_plane_clip_polygon(
- edgeplane,temp_points1,clipped_count,clipped_points);
-
- return clipped_count;
+ return clipped_count;
}
-bool btPrimitiveTriangle::find_triangle_collision_clip_method(btPrimitiveTriangle & other, GIM_TRIANGLE_CONTACT & contacts)
+bool btPrimitiveTriangle::find_triangle_collision_clip_method(btPrimitiveTriangle& other, GIM_TRIANGLE_CONTACT& contacts)
{
- btScalar margin = m_margin + other.m_margin;
-
- btVector3 clipped_points[MAX_TRI_CLIPPING];
- int clipped_count;
- //create planes
- // plane v vs U points
-
- GIM_TRIANGLE_CONTACT contacts1;
-
- contacts1.m_separating_normal = m_plane;
-
-
- clipped_count = clip_triangle(other,clipped_points);
-
- if (clipped_count == 0 )
- {
- return false;//Reject
- }
-
- //find most deep interval face1
- contacts1.merge_points(contacts1.m_separating_normal,margin,clipped_points,clipped_count);
- if (contacts1.m_point_count == 0) return false; // too far
- //Normal pointing to this triangle
- contacts1.m_separating_normal *= -1.f;
-
-
- //Clip tri1 by tri2 edges
- GIM_TRIANGLE_CONTACT contacts2;
- contacts2.m_separating_normal = other.m_plane;
-
- clipped_count = other.clip_triangle(*this,clipped_points);
-
- if (clipped_count == 0 )
- {
- return false;//Reject
- }
-
- //find most deep interval face1
- contacts2.merge_points(contacts2.m_separating_normal,margin,clipped_points,clipped_count);
- if (contacts2.m_point_count == 0) return false; // too far
-
-
-
-
- ////check most dir for contacts
- if (contacts2.m_penetration_depth<contacts1.m_penetration_depth)
- {
- contacts.copy_from(contacts2);
- }
- else
- {
- contacts.copy_from(contacts1);
- }
- return true;
+ btScalar margin = m_margin + other.m_margin;
+
+ btVector3 clipped_points[MAX_TRI_CLIPPING];
+ int clipped_count;
+ //create planes
+ // plane v vs U points
+
+ GIM_TRIANGLE_CONTACT contacts1;
+
+ contacts1.m_separating_normal = m_plane;
+
+ clipped_count = clip_triangle(other, clipped_points);
+
+ if (clipped_count == 0)
+ {
+ return false; //Reject
+ }
+
+ //find most deep interval face1
+ contacts1.merge_points(contacts1.m_separating_normal, margin, clipped_points, clipped_count);
+ if (contacts1.m_point_count == 0) return false; // too far
+ //Normal pointing to this triangle
+ contacts1.m_separating_normal *= -1.f;
+
+ //Clip tri1 by tri2 edges
+ GIM_TRIANGLE_CONTACT contacts2;
+ contacts2.m_separating_normal = other.m_plane;
+
+ clipped_count = other.clip_triangle(*this, clipped_points);
+
+ if (clipped_count == 0)
+ {
+ return false; //Reject
+ }
+
+ //find most deep interval face1
+ contacts2.merge_points(contacts2.m_separating_normal, margin, clipped_points, clipped_count);
+ if (contacts2.m_point_count == 0) return false; // too far
+
+ ////check most dir for contacts
+ if (contacts2.m_penetration_depth < contacts1.m_penetration_depth)
+ {
+ contacts.copy_from(contacts2);
+ }
+ else
+ {
+ contacts.copy_from(contacts1);
+ }
+ return true;
}
-
-
///class btTriangleShapeEx: public btTriangleShape
bool btTriangleShapeEx::overlap_test_conservative(const btTriangleShapeEx& other)
{
- btScalar total_margin = getMargin() + other.getMargin();
+ btScalar total_margin = getMargin() + other.getMargin();
- btVector4 plane0;
- buildTriPlane(plane0);
- btVector4 plane1;
- other.buildTriPlane(plane1);
+ btVector4 plane0;
+ buildTriPlane(plane0);
+ btVector4 plane1;
+ other.buildTriPlane(plane1);
- // classify points on other triangle
- btScalar dis0 = bt_distance_point_plane(plane0,other.m_vertices1[0]) - total_margin;
+ // classify points on other triangle
+ btScalar dis0 = bt_distance_point_plane(plane0, other.m_vertices1[0]) - total_margin;
- btScalar dis1 = bt_distance_point_plane(plane0,other.m_vertices1[1]) - total_margin;
+ btScalar dis1 = bt_distance_point_plane(plane0, other.m_vertices1[1]) - total_margin;
- btScalar dis2 = bt_distance_point_plane(plane0,other.m_vertices1[2]) - total_margin;
+ btScalar dis2 = bt_distance_point_plane(plane0, other.m_vertices1[2]) - total_margin;
- if (dis0>0.0f&&dis1>0.0f&&dis2>0.0f) return false;
+ if (dis0 > 0.0f && dis1 > 0.0f && dis2 > 0.0f) return false;
- // classify points on this triangle
- dis0 = bt_distance_point_plane(plane1,m_vertices1[0]) - total_margin;
+ // classify points on this triangle
+ dis0 = bt_distance_point_plane(plane1, m_vertices1[0]) - total_margin;
- dis1 = bt_distance_point_plane(plane1,m_vertices1[1]) - total_margin;
+ dis1 = bt_distance_point_plane(plane1, m_vertices1[1]) - total_margin;
- dis2 = bt_distance_point_plane(plane1,m_vertices1[2]) - total_margin;
+ dis2 = bt_distance_point_plane(plane1, m_vertices1[2]) - total_margin;
- if (dis0>0.0f&&dis1>0.0f&&dis2>0.0f) return false;
+ if (dis0 > 0.0f && dis1 > 0.0f && dis2 > 0.0f) return false;
- return true;
+ return true;
}
-
-
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btTriangleShapeEx.h b/thirdparty/bullet/BulletCollision/Gimpact/btTriangleShapeEx.h
index 973c2ed127..568a1ce811 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/btTriangleShapeEx.h
+++ b/thirdparty/bullet/BulletCollision/Gimpact/btTriangleShapeEx.h
@@ -21,7 +21,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#ifndef GIMPACT_TRIANGLE_SHAPE_EX_H
#define GIMPACT_TRIANGLE_SHAPE_EX_H
@@ -31,16 +30,15 @@ subject to the following restrictions:
#include "btClipPolygon.h"
#include "btGeometryOperations.h"
-
#define MAX_TRI_CLIPPING 16
//! Structure for collision
struct GIM_TRIANGLE_CONTACT
{
- btScalar m_penetration_depth;
- int m_point_count;
- btVector4 m_separating_normal;
- btVector3 m_points[MAX_TRI_CLIPPING];
+ btScalar m_penetration_depth;
+ int m_point_count;
+ btVector4 m_separating_normal;
+ btVector3 m_points[MAX_TRI_CLIPPING];
SIMD_FORCE_INLINE void copy_from(const GIM_TRIANGLE_CONTACT& other)
{
@@ -48,7 +46,7 @@ struct GIM_TRIANGLE_CONTACT
m_separating_normal = other.m_separating_normal;
m_point_count = other.m_point_count;
int i = m_point_count;
- while(i--)
+ while (i--)
{
m_points[i] = other.m_points[i];
}
@@ -63,14 +61,11 @@ struct GIM_TRIANGLE_CONTACT
copy_from(other);
}
- //! classify points that are closer
- void merge_points(const btVector4 & plane,
- btScalar margin, const btVector3 * points, int point_count);
-
+ //! classify points that are closer
+ void merge_points(const btVector4& plane,
+ btScalar margin, const btVector3* points, int point_count);
};
-
-
class btPrimitiveTriangle
{
public:
@@ -78,17 +73,15 @@ public:
btVector4 m_plane;
btScalar m_margin;
btScalar m_dummy;
- btPrimitiveTriangle():m_margin(0.01f)
+ btPrimitiveTriangle() : m_margin(0.01f)
{
-
}
-
SIMD_FORCE_INLINE void buildTriPlane()
{
- btVector3 normal = (m_vertices[1]-m_vertices[0]).cross(m_vertices[2]-m_vertices[0]);
+ btVector3 normal = (m_vertices[1] - m_vertices[0]).cross(m_vertices[2] - m_vertices[0]);
normal.normalize();
- m_plane.setValue(normal[0],normal[1],normal[2],m_vertices[0].dot(normal));
+ m_plane.setValue(normal[0], normal[1], normal[2], m_vertices[0].dot(normal));
}
//! Test if triangles could collide
@@ -98,14 +91,14 @@ public:
/*!
\pre this triangle must have its plane calculated.
*/
- SIMD_FORCE_INLINE void get_edge_plane(int edge_index, btVector4 &plane) const
- {
- const btVector3 & e0 = m_vertices[edge_index];
- const btVector3 & e1 = m_vertices[(edge_index+1)%3];
- bt_edge_plane(e0,e1,m_plane,plane);
- }
-
- void applyTransform(const btTransform& t)
+ SIMD_FORCE_INLINE void get_edge_plane(int edge_index, btVector4& plane) const
+ {
+ const btVector3& e0 = m_vertices[edge_index];
+ const btVector3& e1 = m_vertices[(edge_index + 1) % 3];
+ bt_edge_plane(e0, e1, m_plane, plane);
+ }
+
+ void applyTransform(const btTransform& t)
{
m_vertices[0] = t(m_vertices[0]);
m_vertices[1] = t(m_vertices[1]);
@@ -117,44 +110,41 @@ public:
\pre clipped_points must have MAX_TRI_CLIPPING size, and this triangle must have its plane calculated.
\return the number of clipped points
*/
- int clip_triangle(btPrimitiveTriangle & other, btVector3 * clipped_points );
+ int clip_triangle(btPrimitiveTriangle& other, btVector3* clipped_points);
//! Find collision using the clipping method
/*!
\pre this triangle and other must have their triangles calculated
*/
- bool find_triangle_collision_clip_method(btPrimitiveTriangle & other, GIM_TRIANGLE_CONTACT & contacts);
+ bool find_triangle_collision_clip_method(btPrimitiveTriangle& other, GIM_TRIANGLE_CONTACT& contacts);
};
-
-
//! Helper class for colliding Bullet Triangle Shapes
/*!
This class implements a better getAabb method than the previous btTriangleShape class
*/
-class btTriangleShapeEx: public btTriangleShape
+class btTriangleShapeEx : public btTriangleShape
{
public:
-
- btTriangleShapeEx():btTriangleShape(btVector3(0,0,0),btVector3(0,0,0),btVector3(0,0,0))
+ btTriangleShapeEx() : btTriangleShape(btVector3(0, 0, 0), btVector3(0, 0, 0), btVector3(0, 0, 0))
{
}
- btTriangleShapeEx(const btVector3& p0,const btVector3& p1,const btVector3& p2): btTriangleShape(p0,p1,p2)
+ btTriangleShapeEx(const btVector3& p0, const btVector3& p1, const btVector3& p2) : btTriangleShape(p0, p1, p2)
{
}
- btTriangleShapeEx(const btTriangleShapeEx & other): btTriangleShape(other.m_vertices1[0],other.m_vertices1[1],other.m_vertices1[2])
+ btTriangleShapeEx(const btTriangleShapeEx& other) : btTriangleShape(other.m_vertices1[0], other.m_vertices1[1], other.m_vertices1[2])
{
}
- virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax)const
+ virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
{
btVector3 tv0 = t(m_vertices1[0]);
btVector3 tv1 = t(m_vertices1[1]);
btVector3 tv2 = t(m_vertices1[2]);
- btAABB trianglebox(tv0,tv1,tv2,m_collisionMargin);
+ btAABB trianglebox(tv0, tv1, tv2, m_collisionMargin);
aabbMin = trianglebox.m_min;
aabbMax = trianglebox.m_max;
}
@@ -166,15 +156,14 @@ public:
m_vertices1[2] = t(m_vertices1[2]);
}
- SIMD_FORCE_INLINE void buildTriPlane(btVector4 & plane) const
+ SIMD_FORCE_INLINE void buildTriPlane(btVector4& plane) const
{
- btVector3 normal = (m_vertices1[1]-m_vertices1[0]).cross(m_vertices1[2]-m_vertices1[0]);
+ btVector3 normal = (m_vertices1[1] - m_vertices1[0]).cross(m_vertices1[2] - m_vertices1[0]);
normal.normalize();
- plane.setValue(normal[0],normal[1],normal[2],m_vertices1[0].dot(normal));
+ plane.setValue(normal[0], normal[1], normal[2], m_vertices1[0].dot(normal));
}
bool overlap_test_conservative(const btTriangleShapeEx& other);
};
-
-#endif //GIMPACT_TRIANGLE_MESH_SHAPE_H
+#endif //GIMPACT_TRIANGLE_MESH_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_array.h b/thirdparty/bullet/BulletCollision/Gimpact/gim_array.h
index cda51a5fce..fc2dc38a33 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_array.h
+++ b/thirdparty/bullet/BulletCollision/Gimpact/gim_array.h
@@ -34,47 +34,46 @@ email: projectileman@yahoo.com
#include "gim_memory.h"
-
#define GIM_ARRAY_GROW_INCREMENT 2
#define GIM_ARRAY_GROW_FACTOR 2
//! Very simple array container with fast access and simd memory
-template<typename T>
+template <typename T>
class gim_array
{
public:
-//! properties
-//!@{
- T *m_data;
- GUINT m_size;
- GUINT m_allocated_size;
-//!@}
-//! protected operations
-//!@{
-
- inline void destroyData()
- {
- m_allocated_size = 0;
- if(m_data==NULL) return;
+ //! properties
+ //!@{
+ T* m_data;
+ GUINT m_size;
+ GUINT m_allocated_size;
+ //!@}
+ //! protected operations
+ //!@{
+
+ inline void destroyData()
+ {
+ m_allocated_size = 0;
+ if (m_data == NULL) return;
gim_free(m_data);
m_data = NULL;
}
inline bool resizeData(GUINT newsize)
{
- if(newsize==0)
+ if (newsize == 0)
{
destroyData();
return true;
}
- if(m_size>0)
+ if (m_size > 0)
{
- m_data = (T*)gim_realloc(m_data,m_size*sizeof(T),newsize*sizeof(T));
+ m_data = (T*)gim_realloc(m_data, m_size * sizeof(T), newsize * sizeof(T));
}
else
{
- m_data = (T*)gim_alloc(newsize*sizeof(T));
+ m_data = (T*)gim_alloc(newsize * sizeof(T));
}
m_allocated_size = newsize;
return true;
@@ -82,243 +81,238 @@ public:
inline bool growingCheck()
{
- if(m_allocated_size<=m_size)
+ if (m_allocated_size <= m_size)
{
- GUINT requestsize = m_size;
- m_size = m_allocated_size;
- if(resizeData((requestsize+GIM_ARRAY_GROW_INCREMENT)*GIM_ARRAY_GROW_FACTOR)==false) return false;
+ GUINT requestsize = m_size;
+ m_size = m_allocated_size;
+ if (resizeData((requestsize + GIM_ARRAY_GROW_INCREMENT) * GIM_ARRAY_GROW_FACTOR) == false) return false;
}
return true;
}
-//!@}
-//! public operations
-//!@{
- inline bool reserve(GUINT size)
- {
- if(m_allocated_size>=size) return false;
- return resizeData(size);
- }
-
- inline void clear_range(GUINT start_range)
- {
- while(m_size>start_range)
- {
- m_data[--m_size].~T();
- }
- }
-
- inline void clear()
- {
- if(m_size==0)return;
- clear_range(0);
- }
-
- inline void clear_memory()
- {
- clear();
- destroyData();
- }
-
- gim_array()
- {
- m_data = 0;
- m_size = 0;
- m_allocated_size = 0;
- }
-
- gim_array(GUINT reservesize)
- {
- m_data = 0;
- m_size = 0;
-
- m_allocated_size = 0;
- reserve(reservesize);
- }
-
- ~gim_array()
- {
- clear_memory();
- }
-
- inline GUINT size() const
- {
- return m_size;
- }
-
- inline GUINT max_size() const
- {
- return m_allocated_size;
- }
-
- inline T & operator[](size_t i)
+ //!@}
+ //! public operations
+ //!@{
+ inline bool reserve(GUINT size)
+ {
+ if (m_allocated_size >= size) return false;
+ return resizeData(size);
+ }
+
+ inline void clear_range(GUINT start_range)
+ {
+ while (m_size > start_range)
+ {
+ m_data[--m_size].~T();
+ }
+ }
+
+ inline void clear()
+ {
+ if (m_size == 0) return;
+ clear_range(0);
+ }
+
+ inline void clear_memory()
+ {
+ clear();
+ destroyData();
+ }
+
+ gim_array()
+ {
+ m_data = 0;
+ m_size = 0;
+ m_allocated_size = 0;
+ }
+
+ gim_array(GUINT reservesize)
+ {
+ m_data = 0;
+ m_size = 0;
+
+ m_allocated_size = 0;
+ reserve(reservesize);
+ }
+
+ ~gim_array()
+ {
+ clear_memory();
+ }
+
+ inline GUINT size() const
+ {
+ return m_size;
+ }
+
+ inline GUINT max_size() const
+ {
+ return m_allocated_size;
+ }
+
+ inline T& operator[](size_t i)
{
return m_data[i];
}
- inline const T & operator[](size_t i) const
+ inline const T& operator[](size_t i) const
{
return m_data[i];
}
- inline T * pointer(){ return m_data;}
- inline const T * pointer() const
- { return m_data;}
-
+ inline T* pointer() { return m_data; }
+ inline const T* pointer() const
+ {
+ return m_data;
+ }
- inline T * get_pointer_at(GUINT i)
+ inline T* get_pointer_at(GUINT i)
{
return m_data + i;
}
- inline const T * get_pointer_at(GUINT i) const
+ inline const T* get_pointer_at(GUINT i) const
{
return m_data + i;
}
- inline T & at(GUINT i)
+ inline T& at(GUINT i)
{
return m_data[i];
}
- inline const T & at(GUINT i) const
+ inline const T& at(GUINT i) const
{
return m_data[i];
}
- inline T & front()
+ inline T& front()
{
return *m_data;
}
- inline const T & front() const
+ inline const T& front() const
{
return *m_data;
}
- inline T & back()
+ inline T& back()
{
- return m_data[m_size-1];
+ return m_data[m_size - 1];
}
- inline const T & back() const
+ inline const T& back() const
{
- return m_data[m_size-1];
+ return m_data[m_size - 1];
}
-
inline void swap(GUINT i, GUINT j)
{
- gim_swap_elements(m_data,i,j);
+ gim_swap_elements(m_data, i, j);
}
- inline void push_back(const T & obj)
+ inline void push_back(const T& obj)
{
- this->growingCheck();
- m_data[m_size] = obj;
- m_size++;
+ this->growingCheck();
+ m_data[m_size] = obj;
+ m_size++;
}
//!Simply increase the m_size, doesn't call the new element constructor
inline void push_back_mem()
{
- this->growingCheck();
- m_size++;
+ this->growingCheck();
+ m_size++;
}
- inline void push_back_memcpy(const T & obj)
+ inline void push_back_memcpy(const T& obj)
{
- this->growingCheck();
- gim_simd_memcpy(&m_data[m_size],&obj,sizeof(T));
- m_size++;
+ this->growingCheck();
+ gim_simd_memcpy(&m_data[m_size], &obj, sizeof(T));
+ m_size++;
}
inline void pop_back()
{
- m_size--;
- m_data[m_size].~T();
+ m_size--;
+ m_data[m_size].~T();
}
//!Simply decrease the m_size, doesn't call the deleted element destructor
inline void pop_back_mem()
{
- m_size--;
+ m_size--;
}
- //! fast erase
+ //! fast erase
inline void erase(GUINT index)
{
- if(index<m_size-1)
- {
- swap(index,m_size-1);
- }
- pop_back();
+ if (index < m_size - 1)
+ {
+ swap(index, m_size - 1);
+ }
+ pop_back();
}
inline void erase_sorted_mem(GUINT index)
{
- m_size--;
- for(GUINT i = index;i<m_size;i++)
- {
- gim_simd_memcpy(m_data+i,m_data+i+1,sizeof(T));
- }
+ m_size--;
+ for (GUINT i = index; i < m_size; i++)
+ {
+ gim_simd_memcpy(m_data + i, m_data + i + 1, sizeof(T));
+ }
}
inline void erase_sorted(GUINT index)
{
- m_data[index].~T();
- erase_sorted_mem(index);
+ m_data[index].~T();
+ erase_sorted_mem(index);
}
inline void insert_mem(GUINT index)
{
- this->growingCheck();
- for(GUINT i = m_size;i>index;i--)
- {
- gim_simd_memcpy(m_data+i,m_data+i-1,sizeof(T));
- }
- m_size++;
- }
-
- inline void insert(const T & obj,GUINT index)
- {
- insert_mem(index);
- m_data[index] = obj;
- }
-
- inline void resize(GUINT size, bool call_constructor = true, const T& fillData=T())
- {
- if(size>m_size)
- {
- reserve(size);
- if(call_constructor)
- {
- while(m_size<size)
- {
- m_data[m_size] = fillData;
- m_size++;
- }
- }
- else
- {
- m_size = size;
- }
- }
- else if(size<m_size)
- {
- if(call_constructor) clear_range(size);
- m_size = size;
- }
+ this->growingCheck();
+ for (GUINT i = m_size; i > index; i--)
+ {
+ gim_simd_memcpy(m_data + i, m_data + i - 1, sizeof(T));
+ }
+ m_size++;
}
- inline void refit()
+ inline void insert(const T& obj, GUINT index)
{
- resizeData(m_size);
+ insert_mem(index);
+ m_data[index] = obj;
}
-};
-
-
-
+ inline void resize(GUINT size, bool call_constructor = true, const T& fillData = T())
+ {
+ if (size > m_size)
+ {
+ reserve(size);
+ if (call_constructor)
+ {
+ while (m_size < size)
+ {
+ m_data[m_size] = fillData;
+ m_size++;
+ }
+ }
+ else
+ {
+ m_size = size;
+ }
+ }
+ else if (size < m_size)
+ {
+ if (call_constructor) clear_range(size);
+ m_size = size;
+ }
+ }
+ inline void refit()
+ {
+ resizeData(m_size);
+ }
+};
-#endif // GIM_CONTAINERS_H_INCLUDED
+#endif // GIM_CONTAINERS_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_basic_geometry_operations.h b/thirdparty/bullet/BulletCollision/Gimpact/gim_basic_geometry_operations.h
index 0c48cb60fc..7ab783672d 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_basic_geometry_operations.h
+++ b/thirdparty/bullet/BulletCollision/Gimpact/gim_basic_geometry_operations.h
@@ -35,12 +35,8 @@ email: projectileman@yahoo.com
-----------------------------------------------------------------------------
*/
-
#include "gim_linear_math.h"
-
-
-
#ifndef PLANEDIREPSILON
#define PLANEDIREPSILON 0.0000001f
#endif
@@ -49,77 +45,82 @@ email: projectileman@yahoo.com
#define PARALELENORMALS 0.000001f
#endif
-#define TRIANGLE_NORMAL(v1,v2,v3,n)\
-{\
- vec3f _dif1,_dif2;\
- VEC_DIFF(_dif1,v2,v1);\
- VEC_DIFF(_dif2,v3,v1);\
- VEC_CROSS(n,_dif1,_dif2);\
- VEC_NORMALIZE(n);\
-}\
-
-#define TRIANGLE_NORMAL_FAST(v1,v2,v3,n){\
- vec3f _dif1,_dif2; \
- VEC_DIFF(_dif1,v2,v1); \
- VEC_DIFF(_dif2,v3,v1); \
- VEC_CROSS(n,_dif1,_dif2); \
-}\
+#define TRIANGLE_NORMAL(v1, v2, v3, n) \
+ { \
+ vec3f _dif1, _dif2; \
+ VEC_DIFF(_dif1, v2, v1); \
+ VEC_DIFF(_dif2, v3, v1); \
+ VEC_CROSS(n, _dif1, _dif2); \
+ VEC_NORMALIZE(n); \
+ }
+
+#define TRIANGLE_NORMAL_FAST(v1, v2, v3, n) \
+ { \
+ vec3f _dif1, _dif2; \
+ VEC_DIFF(_dif1, v2, v1); \
+ VEC_DIFF(_dif2, v3, v1); \
+ VEC_CROSS(n, _dif1, _dif2); \
+ }
/// plane is a vec4f
-#define TRIANGLE_PLANE(v1,v2,v3,plane) {\
- TRIANGLE_NORMAL(v1,v2,v3,plane);\
- plane[3] = VEC_DOT(v1,plane);\
-}\
+#define TRIANGLE_PLANE(v1, v2, v3, plane) \
+ { \
+ TRIANGLE_NORMAL(v1, v2, v3, plane); \
+ plane[3] = VEC_DOT(v1, plane); \
+ }
/// plane is a vec4f
-#define TRIANGLE_PLANE_FAST(v1,v2,v3,plane) {\
- TRIANGLE_NORMAL_FAST(v1,v2,v3,plane);\
- plane[3] = VEC_DOT(v1,plane);\
-}\
+#define TRIANGLE_PLANE_FAST(v1, v2, v3, plane) \
+ { \
+ TRIANGLE_NORMAL_FAST(v1, v2, v3, plane); \
+ plane[3] = VEC_DOT(v1, plane); \
+ }
/// Calc a plane from an edge an a normal. plane is a vec4f
-#define EDGE_PLANE(e1,e2,n,plane) {\
- vec3f _dif; \
- VEC_DIFF(_dif,e2,e1); \
- VEC_CROSS(plane,_dif,n); \
- VEC_NORMALIZE(plane); \
- plane[3] = VEC_DOT(e1,plane);\
-}\
-
-#define DISTANCE_PLANE_POINT(plane,point) (VEC_DOT(plane,point) - plane[3])
-
-#define PROJECT_POINT_PLANE(point,plane,projected) {\
- GREAL _dis;\
- _dis = DISTANCE_PLANE_POINT(plane,point);\
- VEC_SCALE(projected,-_dis,plane);\
- VEC_SUM(projected,projected,point); \
-}\
+#define EDGE_PLANE(e1, e2, n, plane) \
+ { \
+ vec3f _dif; \
+ VEC_DIFF(_dif, e2, e1); \
+ VEC_CROSS(plane, _dif, n); \
+ VEC_NORMALIZE(plane); \
+ plane[3] = VEC_DOT(e1, plane); \
+ }
+
+#define DISTANCE_PLANE_POINT(plane, point) (VEC_DOT(plane, point) - plane[3])
+
+#define PROJECT_POINT_PLANE(point, plane, projected) \
+ { \
+ GREAL _dis; \
+ _dis = DISTANCE_PLANE_POINT(plane, point); \
+ VEC_SCALE(projected, -_dis, plane); \
+ VEC_SUM(projected, projected, point); \
+ }
//! Verifies if a point is in the plane hull
-template<typename CLASS_POINT,typename CLASS_PLANE>
+template <typename CLASS_POINT, typename CLASS_PLANE>
SIMD_FORCE_INLINE bool POINT_IN_HULL(
- const CLASS_POINT& point,const CLASS_PLANE * planes,GUINT plane_count)
+ const CLASS_POINT &point, const CLASS_PLANE *planes, GUINT plane_count)
{
GREAL _dis;
- for (GUINT _i = 0;_i< plane_count;++_i)
+ for (GUINT _i = 0; _i < plane_count; ++_i)
{
- _dis = DISTANCE_PLANE_POINT(planes[_i],point);
- if(_dis>0.0f) return false;
+ _dis = DISTANCE_PLANE_POINT(planes[_i], point);
+ if (_dis > 0.0f) return false;
}
return true;
}
-template<typename CLASS_POINT,typename CLASS_PLANE>
+template <typename CLASS_POINT, typename CLASS_PLANE>
SIMD_FORCE_INLINE void PLANE_CLIP_SEGMENT(
- const CLASS_POINT& s1,
- const CLASS_POINT &s2,const CLASS_PLANE &plane,CLASS_POINT &clipped)
+ const CLASS_POINT &s1,
+ const CLASS_POINT &s2, const CLASS_PLANE &plane, CLASS_POINT &clipped)
{
- GREAL _dis1,_dis2;
- _dis1 = DISTANCE_PLANE_POINT(plane,s1);
- VEC_DIFF(clipped,s2,s1);
- _dis2 = VEC_DOT(clipped,plane);
- VEC_SCALE(clipped,-_dis1/_dis2,clipped);
- VEC_SUM(clipped,clipped,s1);
+ GREAL _dis1, _dis2;
+ _dis1 = DISTANCE_PLANE_POINT(plane, s1);
+ VEC_DIFF(clipped, s2, s1);
+ _dis2 = VEC_DOT(clipped, plane);
+ VEC_SCALE(clipped, -_dis1 / _dis2, clipped);
+ VEC_SUM(clipped, clipped, s1);
}
enum ePLANE_INTERSECTION_TYPE
@@ -152,30 +153,30 @@ intersection type must have the following values
</ul>
*/
-template<typename CLASS_POINT,typename CLASS_PLANE>
+template <typename CLASS_POINT, typename CLASS_PLANE>
SIMD_FORCE_INLINE eLINE_PLANE_INTERSECTION_TYPE PLANE_CLIP_SEGMENT2(
- const CLASS_POINT& s1,
+ const CLASS_POINT &s1,
const CLASS_POINT &s2,
- const CLASS_PLANE &plane,CLASS_POINT &clipped)
+ const CLASS_PLANE &plane, CLASS_POINT &clipped)
{
- GREAL _dis1 = DISTANCE_PLANE_POINT(plane,s1);
- GREAL _dis2 = DISTANCE_PLANE_POINT(plane,s2);
- if(_dis1 >-G_EPSILON && _dis2 >-G_EPSILON)
+ GREAL _dis1 = DISTANCE_PLANE_POINT(plane, s1);
+ GREAL _dis2 = DISTANCE_PLANE_POINT(plane, s2);
+ if (_dis1 > -G_EPSILON && _dis2 > -G_EPSILON)
{
- if(_dis1<_dis2) return G_FRONT_PLANE_S1;
- return G_FRONT_PLANE_S2;
+ if (_dis1 < _dis2) return G_FRONT_PLANE_S1;
+ return G_FRONT_PLANE_S2;
}
- else if(_dis1 <G_EPSILON && _dis2 <G_EPSILON)
+ else if (_dis1 < G_EPSILON && _dis2 < G_EPSILON)
{
- if(_dis1>_dis2) return G_BACK_PLANE_S1;
- return G_BACK_PLANE_S2;
+ if (_dis1 > _dis2) return G_BACK_PLANE_S1;
+ return G_BACK_PLANE_S2;
}
- VEC_DIFF(clipped,s2,s1);
- _dis2 = VEC_DOT(clipped,plane);
- VEC_SCALE(clipped,-_dis1/_dis2,clipped);
- VEC_SUM(clipped,clipped,s1);
- if(_dis1<_dis2) return G_COLLIDE_PLANE_S1;
+ VEC_DIFF(clipped, s2, s1);
+ _dis2 = VEC_DOT(clipped, plane);
+ VEC_SCALE(clipped, -_dis1 / _dis2, clipped);
+ VEC_SUM(clipped, clipped, s1);
+ if (_dis1 < _dis2) return G_COLLIDE_PLANE_S1;
return G_COLLIDE_PLANE_S2;
}
@@ -194,43 +195,42 @@ intersection_type must have the following values
<li> 5 : Segment collides plane, s2 in back
</ul>
*/
-template<typename CLASS_POINT,typename CLASS_PLANE>
+template <typename CLASS_POINT, typename CLASS_PLANE>
SIMD_FORCE_INLINE eLINE_PLANE_INTERSECTION_TYPE PLANE_CLIP_SEGMENT_CLOSEST(
- const CLASS_POINT& s1,
+ const CLASS_POINT &s1,
const CLASS_POINT &s2,
const CLASS_PLANE &plane,
- CLASS_POINT &clipped1,CLASS_POINT &clipped2)
+ CLASS_POINT &clipped1, CLASS_POINT &clipped2)
{
- eLINE_PLANE_INTERSECTION_TYPE intersection_type = PLANE_CLIP_SEGMENT2(s1,s2,plane,clipped1);
- switch(intersection_type)
+ eLINE_PLANE_INTERSECTION_TYPE intersection_type = PLANE_CLIP_SEGMENT2(s1, s2, plane, clipped1);
+ switch (intersection_type)
{
- case G_FRONT_PLANE_S1:
- VEC_COPY(clipped1,s1);
- VEC_COPY(clipped2,s2);
- break;
- case G_FRONT_PLANE_S2:
- VEC_COPY(clipped1,s2);
- VEC_COPY(clipped2,s1);
- break;
- case G_BACK_PLANE_S1:
- VEC_COPY(clipped1,s1);
- VEC_COPY(clipped2,s2);
- break;
- case G_BACK_PLANE_S2:
- VEC_COPY(clipped1,s2);
- VEC_COPY(clipped2,s1);
- break;
- case G_COLLIDE_PLANE_S1:
- VEC_COPY(clipped2,s1);
- break;
- case G_COLLIDE_PLANE_S2:
- VEC_COPY(clipped2,s2);
- break;
+ case G_FRONT_PLANE_S1:
+ VEC_COPY(clipped1, s1);
+ VEC_COPY(clipped2, s2);
+ break;
+ case G_FRONT_PLANE_S2:
+ VEC_COPY(clipped1, s2);
+ VEC_COPY(clipped2, s1);
+ break;
+ case G_BACK_PLANE_S1:
+ VEC_COPY(clipped1, s1);
+ VEC_COPY(clipped2, s2);
+ break;
+ case G_BACK_PLANE_S2:
+ VEC_COPY(clipped1, s2);
+ VEC_COPY(clipped2, s1);
+ break;
+ case G_COLLIDE_PLANE_S1:
+ VEC_COPY(clipped2, s1);
+ break;
+ case G_COLLIDE_PLANE_S2:
+ VEC_COPY(clipped2, s2);
+ break;
}
return intersection_type;
}
-
//! Finds the 2 smallest cartesian coordinates of a plane normal
#define PLANE_MINOR_AXES(plane, i0, i1) VEC_MINOR_AXES(plane, i0, i1)
@@ -239,23 +239,23 @@ SIMD_FORCE_INLINE eLINE_PLANE_INTERSECTION_TYPE PLANE_CLIP_SEGMENT_CLOSEST(
Intersects plane in one way only. The ray must face the plane (normals must be in opossite directions).<br/>
It uses the PLANEDIREPSILON constant.
*/
-template<typename T,typename CLASS_POINT,typename CLASS_PLANE>
+template <typename T, typename CLASS_POINT, typename CLASS_PLANE>
SIMD_FORCE_INLINE bool RAY_PLANE_COLLISION(
- const CLASS_PLANE & plane,
- const CLASS_POINT & vDir,
- const CLASS_POINT & vPoint,
- CLASS_POINT & pout,T &tparam)
+ const CLASS_PLANE &plane,
+ const CLASS_POINT &vDir,
+ const CLASS_POINT &vPoint,
+ CLASS_POINT &pout, T &tparam)
{
- GREAL _dis,_dotdir;
- _dotdir = VEC_DOT(plane,vDir);
- if(_dotdir<PLANEDIREPSILON)
+ GREAL _dis, _dotdir;
+ _dotdir = VEC_DOT(plane, vDir);
+ if (_dotdir < PLANEDIREPSILON)
{
- return false;
+ return false;
}
- _dis = DISTANCE_PLANE_POINT(plane,vPoint);
- tparam = -_dis/_dotdir;
- VEC_SCALE(pout,tparam,vDir);
- VEC_SUM(pout,vPoint,pout);
+ _dis = DISTANCE_PLANE_POINT(plane, vPoint);
+ tparam = -_dis / _dotdir;
+ VEC_SCALE(pout, tparam, vDir);
+ VEC_SUM(pout, vPoint, pout);
return true;
}
@@ -266,39 +266,39 @@ SIMD_FORCE_INLINE bool RAY_PLANE_COLLISION(
-1 if the ray collides in front
-2 if the ray collides in back
*/
-template<typename T,typename CLASS_POINT,typename CLASS_PLANE>
+template <typename T, typename CLASS_POINT, typename CLASS_PLANE>
SIMD_FORCE_INLINE GUINT LINE_PLANE_COLLISION(
- const CLASS_PLANE & plane,
- const CLASS_POINT & vDir,
- const CLASS_POINT & vPoint,
- CLASS_POINT & pout,
+ const CLASS_PLANE &plane,
+ const CLASS_POINT &vDir,
+ const CLASS_POINT &vPoint,
+ CLASS_POINT &pout,
T &tparam,
T tmin, T tmax)
{
- GREAL _dis,_dotdir;
- _dotdir = VEC_DOT(plane,vDir);
- if(btFabs(_dotdir)<PLANEDIREPSILON)
+ GREAL _dis, _dotdir;
+ _dotdir = VEC_DOT(plane, vDir);
+ if (btFabs(_dotdir) < PLANEDIREPSILON)
{
tparam = tmax;
- return 0;
+ return 0;
}
- _dis = DISTANCE_PLANE_POINT(plane,vPoint);
- char returnvalue = _dis<0.0f?2:1;
- tparam = -_dis/_dotdir;
+ _dis = DISTANCE_PLANE_POINT(plane, vPoint);
+ char returnvalue = _dis < 0.0f ? 2 : 1;
+ tparam = -_dis / _dotdir;
- if(tparam<tmin)
+ if (tparam < tmin)
{
returnvalue = 0;
tparam = tmin;
}
- else if(tparam>tmax)
+ else if (tparam > tmax)
{
returnvalue = 0;
tparam = tmax;
}
- VEC_SCALE(pout,tparam,vDir);
- VEC_SUM(pout,vPoint,pout);
+ VEC_SCALE(pout, tparam, vDir);
+ VEC_SUM(pout, vPoint, pout);
return returnvalue;
}
@@ -312,24 +312,24 @@ SIMD_FORCE_INLINE GUINT LINE_PLANE_COLLISION(
\return true if the planes intersect, 0 if paralell.
*/
-template<typename CLASS_POINT,typename CLASS_PLANE>
+template <typename CLASS_POINT, typename CLASS_PLANE>
SIMD_FORCE_INLINE bool INTERSECT_PLANES(
- const CLASS_PLANE &p1,
- const CLASS_PLANE &p2,
- CLASS_POINT &p,
- CLASS_POINT &d)
+ const CLASS_PLANE &p1,
+ const CLASS_PLANE &p2,
+ CLASS_POINT &p,
+ CLASS_POINT &d)
{
- VEC_CROSS(d,p1,p2);
- GREAL denom = VEC_DOT(d, d);
- if(GIM_IS_ZERO(denom)) return false;
+ VEC_CROSS(d, p1, p2);
+ GREAL denom = VEC_DOT(d, d);
+ if (GIM_IS_ZERO(denom)) return false;
vec3f _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];
- VEC_CROSS(p,_n,d);
- p[0]/=denom;
- p[1]/=denom;
- p[2]/=denom;
+ _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];
+ VEC_CROSS(p, _n, d);
+ p[0] /= denom;
+ p[1] /= denom;
+ p[2] /= denom;
return true;
}
@@ -337,32 +337,31 @@ SIMD_FORCE_INLINE bool INTERSECT_PLANES(
/*! Finds the closest point(cp) to (v) on a segment (e1,e2)
*/
-template<typename CLASS_POINT>
+template <typename CLASS_POINT>
SIMD_FORCE_INLINE void CLOSEST_POINT_ON_SEGMENT(
- CLASS_POINT & cp, const CLASS_POINT & v,
- const CLASS_POINT &e1,const CLASS_POINT &e2)
+ CLASS_POINT &cp, const CLASS_POINT &v,
+ const CLASS_POINT &e1, const CLASS_POINT &e2)
{
- vec3f _n;
- VEC_DIFF(_n,e2,e1);
- VEC_DIFF(cp,v,e1);
+ vec3f _n;
+ VEC_DIFF(_n, e2, e1);
+ VEC_DIFF(cp, v, e1);
GREAL _scalar = VEC_DOT(cp, _n);
- _scalar/= VEC_DOT(_n, _n);
- if(_scalar <0.0f)
+ _scalar /= VEC_DOT(_n, _n);
+ if (_scalar < 0.0f)
{
- VEC_COPY(cp,e1);
+ VEC_COPY(cp, e1);
}
- else if(_scalar >1.0f)
+ else if (_scalar > 1.0f)
{
- VEC_COPY(cp,e2);
+ VEC_COPY(cp, e2);
}
else
{
- VEC_SCALE(cp,_scalar,_n);
- VEC_SUM(cp,cp,e1);
+ VEC_SCALE(cp, _scalar, _n);
+ VEC_SUM(cp, cp, e1);
}
}
-
/*! \brief Finds the line params where these lines intersect.
\param dir1 Direction of line 1
@@ -374,117 +373,113 @@ SIMD_FORCE_INLINE void CLOSEST_POINT_ON_SEGMENT(
\param dointersect 0 if the lines won't intersect, else 1
*/
-template<typename T,typename CLASS_POINT>
+template <typename T, typename CLASS_POINT>
SIMD_FORCE_INLINE bool LINE_INTERSECTION_PARAMS(
- const CLASS_POINT & dir1,
- CLASS_POINT & point1,
- const CLASS_POINT & dir2,
- CLASS_POINT & point2,
- T& t1,T& t2)
+ const CLASS_POINT &dir1,
+ CLASS_POINT &point1,
+ const CLASS_POINT &dir2,
+ CLASS_POINT &point2,
+ T &t1, T &t2)
{
- GREAL det;
- GREAL e1e1 = VEC_DOT(dir1,dir1);
- GREAL e1e2 = VEC_DOT(dir1,dir2);
- GREAL e2e2 = VEC_DOT(dir2,dir2);
+ GREAL det;
+ GREAL e1e1 = VEC_DOT(dir1, dir1);
+ GREAL e1e2 = VEC_DOT(dir1, dir2);
+ GREAL e2e2 = VEC_DOT(dir2, dir2);
vec3f p1p2;
- VEC_DIFF(p1p2,point1,point2);
- GREAL p1p2e1 = VEC_DOT(p1p2,dir1);
- GREAL p1p2e2 = VEC_DOT(p1p2,dir2);
- det = e1e2*e1e2 - e1e1*e2e2;
- if(GIM_IS_ZERO(det)) return false;
- t1 = (e1e2*p1p2e2 - e2e2*p1p2e1)/det;
- t2 = (e1e1*p1p2e2 - e1e2*p1p2e1)/det;
+ VEC_DIFF(p1p2, point1, point2);
+ GREAL p1p2e1 = VEC_DOT(p1p2, dir1);
+ GREAL p1p2e2 = VEC_DOT(p1p2, dir2);
+ det = e1e2 * e1e2 - e1e1 * e2e2;
+ if (GIM_IS_ZERO(det)) return false;
+ t1 = (e1e2 * p1p2e2 - e2e2 * p1p2e1) / det;
+ t2 = (e1e1 * p1p2e2 - e1e2 * p1p2e1) / det;
return true;
}
//! Find closest points on segments
-template<typename CLASS_POINT>
+template <typename CLASS_POINT>
SIMD_FORCE_INLINE void SEGMENT_COLLISION(
- const CLASS_POINT & vA1,
- const CLASS_POINT & vA2,
- const CLASS_POINT & vB1,
- const CLASS_POINT & vB2,
- CLASS_POINT & vPointA,
- CLASS_POINT & vPointB)
+ const CLASS_POINT &vA1,
+ const CLASS_POINT &vA2,
+ const CLASS_POINT &vB1,
+ const CLASS_POINT &vB2,
+ CLASS_POINT &vPointA,
+ CLASS_POINT &vPointB)
{
- CLASS_POINT _AD,_BD,n;
- vec4f _M;//plane
- VEC_DIFF(_AD,vA2,vA1);
- VEC_DIFF(_BD,vB2,vB1);
- VEC_CROSS(n,_AD,_BD);
- GREAL _tp = VEC_DOT(n,n);
- if(_tp<G_EPSILON)//ARE PARALELE
- {
- //project B over A
- bool invert_b_order = false;
- _M[0] = VEC_DOT(vB1,_AD);
- _M[1] = VEC_DOT(vB2,_AD);
- if(_M[0]>_M[1])
- {
- invert_b_order = true;
- GIM_SWAP_NUMBERS(_M[0],_M[1]);
- }
- _M[2] = VEC_DOT(vA1,_AD);
- _M[3] = VEC_DOT(vA2,_AD);
- //mid points
- n[0] = (_M[0]+_M[1])*0.5f;
- n[1] = (_M[2]+_M[3])*0.5f;
-
- if(n[0]<n[1])
- {
- if(_M[1]<_M[2])
- {
- vPointB = invert_b_order?vB1:vB2;
- vPointA = vA1;
- }
- else if(_M[1]<_M[3])
- {
- vPointB = invert_b_order?vB1:vB2;
- CLOSEST_POINT_ON_SEGMENT(vPointA,vPointB,vA1,vA2);
- }
- else
- {
- vPointA = vA2;
- CLOSEST_POINT_ON_SEGMENT(vPointB,vPointA,vB1,vB2);
- }
- }
- else
- {
- if(_M[3]<_M[0])
- {
- vPointB = invert_b_order?vB2:vB1;
- vPointA = vA2;
- }
- else if(_M[3]<_M[1])
- {
- vPointA = vA2;
- CLOSEST_POINT_ON_SEGMENT(vPointB,vPointA,vB1,vB2);
- }
- else
- {
- vPointB = invert_b_order?vB1:vB2;
- CLOSEST_POINT_ON_SEGMENT(vPointA,vPointB,vA1,vA2);
- }
- }
- return;
- }
-
-
- VEC_CROSS(_M,n,_BD);
- _M[3] = VEC_DOT(_M,vB1);
-
- LINE_PLANE_COLLISION(_M,_AD,vA1,vPointA,_tp,btScalar(0), btScalar(1));
- /*Closest point on segment*/
- VEC_DIFF(vPointB,vPointA,vB1);
- _tp = VEC_DOT(vPointB, _BD);
- _tp/= VEC_DOT(_BD, _BD);
- _tp = GIM_CLAMP(_tp,0.0f,1.0f);
- VEC_SCALE(vPointB,_tp,_BD);
- VEC_SUM(vPointB,vPointB,vB1);
-}
-
+ CLASS_POINT _AD, _BD, n;
+ vec4f _M; //plane
+ VEC_DIFF(_AD, vA2, vA1);
+ VEC_DIFF(_BD, vB2, vB1);
+ VEC_CROSS(n, _AD, _BD);
+ GREAL _tp = VEC_DOT(n, n);
+ if (_tp < G_EPSILON) //ARE PARALELE
+ {
+ //project B over A
+ bool invert_b_order = false;
+ _M[0] = VEC_DOT(vB1, _AD);
+ _M[1] = VEC_DOT(vB2, _AD);
+ if (_M[0] > _M[1])
+ {
+ invert_b_order = true;
+ GIM_SWAP_NUMBERS(_M[0], _M[1]);
+ }
+ _M[2] = VEC_DOT(vA1, _AD);
+ _M[3] = VEC_DOT(vA2, _AD);
+ //mid points
+ n[0] = (_M[0] + _M[1]) * 0.5f;
+ n[1] = (_M[2] + _M[3]) * 0.5f;
+
+ if (n[0] < n[1])
+ {
+ if (_M[1] < _M[2])
+ {
+ vPointB = invert_b_order ? vB1 : vB2;
+ vPointA = vA1;
+ }
+ else if (_M[1] < _M[3])
+ {
+ vPointB = invert_b_order ? vB1 : vB2;
+ CLOSEST_POINT_ON_SEGMENT(vPointA, vPointB, vA1, vA2);
+ }
+ else
+ {
+ vPointA = vA2;
+ CLOSEST_POINT_ON_SEGMENT(vPointB, vPointA, vB1, vB2);
+ }
+ }
+ else
+ {
+ if (_M[3] < _M[0])
+ {
+ vPointB = invert_b_order ? vB2 : vB1;
+ vPointA = vA2;
+ }
+ else if (_M[3] < _M[1])
+ {
+ vPointA = vA2;
+ CLOSEST_POINT_ON_SEGMENT(vPointB, vPointA, vB1, vB2);
+ }
+ else
+ {
+ vPointB = invert_b_order ? vB1 : vB2;
+ CLOSEST_POINT_ON_SEGMENT(vPointA, vPointB, vA1, vA2);
+ }
+ }
+ return;
+ }
+ VEC_CROSS(_M, n, _BD);
+ _M[3] = VEC_DOT(_M, vB1);
+ LINE_PLANE_COLLISION(_M, _AD, vA1, vPointA, _tp, btScalar(0), btScalar(1));
+ /*Closest point on segment*/
+ VEC_DIFF(vPointB, vPointA, vB1);
+ _tp = VEC_DOT(vPointB, _BD);
+ _tp /= VEC_DOT(_BD, _BD);
+ _tp = GIM_CLAMP(_tp, 0.0f, 1.0f);
+ VEC_SCALE(vPointB, _tp, _BD);
+ VEC_SUM(vPointB, vPointB, vB1);
+}
//! Line box intersection in one dimension
/*!
@@ -497,37 +492,36 @@ SIMD_FORCE_INLINE void SEGMENT_COLLISION(
*\param tlast the maximum projection. Assign to INFINITY at first.
*\return true if there is an intersection.
*/
-template<typename T>
-SIMD_FORCE_INLINE bool BOX_AXIS_INTERSECT(T pos, T dir,T bmin, T bmax, T & tfirst, T & tlast)
+template <typename T>
+SIMD_FORCE_INLINE bool BOX_AXIS_INTERSECT(T pos, T dir, T bmin, T bmax, T &tfirst, T &tlast)
{
- if(GIM_IS_ZERO(dir))
+ if (GIM_IS_ZERO(dir))
{
- return !(pos < bmin || pos > bmax);
+ return !(pos < bmin || pos > bmax);
}
GREAL a0 = (bmin - pos) / dir;
GREAL a1 = (bmax - pos) / dir;
- if(a0 > a1) GIM_SWAP_NUMBERS(a0, a1);
+ if (a0 > a1) GIM_SWAP_NUMBERS(a0, a1);
tfirst = GIM_MAX(a0, tfirst);
tlast = GIM_MIN(a1, tlast);
if (tlast < tfirst) return false;
return true;
}
-
//! Sorts 3 componets
-template<typename T>
+template <typename T>
SIMD_FORCE_INLINE void SORT_3_INDICES(
- const T * values,
- GUINT * order_indices)
+ const T *values,
+ GUINT *order_indices)
{
//get minimum
order_indices[0] = values[0] < values[1] ? (values[0] < values[2] ? 0 : 2) : (values[1] < values[2] ? 1 : 2);
//get second and third
- GUINT i0 = (order_indices[0] + 1)%3;
- GUINT i1 = (i0 + 1)%3;
+ GUINT i0 = (order_indices[0] + 1) % 3;
+ GUINT i1 = (i0 + 1) % 3;
- if(values[i0] < values[i1])
+ if (values[i0] < values[i1])
{
order_indices[1] = i0;
order_indices[2] = i1;
@@ -539,8 +533,4 @@ SIMD_FORCE_INLINE void SORT_3_INDICES(
}
}
-
-
-
-
-#endif // GIM_VECTOR_H_INCLUDED
+#endif // GIM_VECTOR_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_bitset.h b/thirdparty/bullet/BulletCollision/Gimpact/gim_bitset.h
index 7dee48a4c7..c1fb41a5c0 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_bitset.h
+++ b/thirdparty/bullet/BulletCollision/Gimpact/gim_bitset.h
@@ -34,34 +34,32 @@ email: projectileman@yahoo.com
#include "gim_array.h"
-
#define GUINT_BIT_COUNT 32
#define GUINT_EXPONENT 5
class gim_bitset
{
public:
- gim_array<GUINT> m_container;
-
- gim_bitset()
- {
+ gim_array<GUINT> m_container;
- }
+ gim_bitset()
+ {
+ }
- gim_bitset(GUINT bits_count)
- {
- resize(bits_count);
- }
+ gim_bitset(GUINT bits_count)
+ {
+ resize(bits_count);
+ }
- ~gim_bitset()
- {
- }
+ ~gim_bitset()
+ {
+ }
inline bool resize(GUINT newsize)
{
GUINT oldsize = m_container.size();
- m_container.resize(newsize/GUINT_BIT_COUNT + 1,false);
- while(oldsize<m_container.size())
+ m_container.resize(newsize / GUINT_BIT_COUNT + 1, false);
+ while (oldsize < m_container.size())
{
m_container[oldsize] = 0;
}
@@ -70,12 +68,12 @@ public:
inline GUINT size()
{
- return m_container.size()*GUINT_BIT_COUNT;
+ return m_container.size() * GUINT_BIT_COUNT;
}
inline void set_all()
{
- for(GUINT i = 0;i<m_container.size();++i)
+ for (GUINT i = 0; i < m_container.size(); ++i)
{
m_container[i] = 0xffffffff;
}
@@ -83,7 +81,7 @@ public:
inline void clear_all()
{
- for(GUINT i = 0;i<m_container.size();++i)
+ for (GUINT i = 0; i < m_container.size(); ++i)
{
m_container[i] = 0;
}
@@ -91,33 +89,29 @@ public:
inline void set(GUINT bit_index)
{
- if(bit_index>=size())
+ if (bit_index >= size())
{
resize(bit_index);
}
- m_container[bit_index >> GUINT_EXPONENT] |= (1 << (bit_index & (GUINT_BIT_COUNT-1)));
+ m_container[bit_index >> GUINT_EXPONENT] |= (1 << (bit_index & (GUINT_BIT_COUNT - 1)));
}
///Return 0 or 1
inline char get(GUINT bit_index)
{
- if(bit_index>=size())
+ if (bit_index >= size())
{
return 0;
}
char value = m_container[bit_index >> GUINT_EXPONENT] &
- (1 << (bit_index & (GUINT_BIT_COUNT-1)));
+ (1 << (bit_index & (GUINT_BIT_COUNT - 1)));
return value;
}
inline void clear(GUINT bit_index)
{
- m_container[bit_index >> GUINT_EXPONENT] &= ~(1 << (bit_index & (GUINT_BIT_COUNT-1)));
+ m_container[bit_index >> GUINT_EXPONENT] &= ~(1 << (bit_index & (GUINT_BIT_COUNT - 1)));
}
};
-
-
-
-
-#endif // GIM_CONTAINERS_H_INCLUDED
+#endif // GIM_CONTAINERS_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_box_collision.h b/thirdparty/bullet/BulletCollision/Gimpact/gim_box_collision.h
index a051b4fdbf..9f7cbe732f 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_box_collision.h
+++ b/thirdparty/bullet/BulletCollision/Gimpact/gim_box_collision.h
@@ -35,8 +35,6 @@ email: projectileman@yahoo.com
#include "gim_basic_geometry_operations.h"
#include "LinearMath/btTransform.h"
-
-
//SIMD_FORCE_INLINE bool test_cross_edge_box(
// const btVector3 & edge,
// const btVector3 & absolute_edge,
@@ -99,52 +97,50 @@ email: projectileman@yahoo.com
#ifndef TEST_CROSS_EDGE_BOX_MCR
-#define TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,i_dir_0,i_dir_1,i_comp_0,i_comp_1)\
-{\
- const btScalar dir0 = -edge[i_dir_0];\
- const btScalar dir1 = edge[i_dir_1];\
- btScalar pmin = pointa[i_comp_0]*dir0 + pointa[i_comp_1]*dir1;\
- btScalar pmax = pointb[i_comp_0]*dir0 + pointb[i_comp_1]*dir1;\
- if(pmin>pmax)\
- {\
- GIM_SWAP_NUMBERS(pmin,pmax); \
- }\
- const btScalar abs_dir0 = absolute_edge[i_dir_0];\
- const btScalar abs_dir1 = absolute_edge[i_dir_1];\
- const btScalar rad = _extend[i_comp_0] * abs_dir0 + _extend[i_comp_1] * abs_dir1;\
- if(pmin>rad || -rad>pmax) return false;\
-}\
+#define TEST_CROSS_EDGE_BOX_MCR(edge, absolute_edge, pointa, pointb, _extend, i_dir_0, i_dir_1, i_comp_0, i_comp_1) \
+ { \
+ const btScalar dir0 = -edge[i_dir_0]; \
+ const btScalar dir1 = edge[i_dir_1]; \
+ btScalar pmin = pointa[i_comp_0] * dir0 + pointa[i_comp_1] * dir1; \
+ btScalar pmax = pointb[i_comp_0] * dir0 + pointb[i_comp_1] * dir1; \
+ if (pmin > pmax) \
+ { \
+ GIM_SWAP_NUMBERS(pmin, pmax); \
+ } \
+ const btScalar abs_dir0 = absolute_edge[i_dir_0]; \
+ const btScalar abs_dir1 = absolute_edge[i_dir_1]; \
+ const btScalar rad = _extend[i_comp_0] * abs_dir0 + _extend[i_comp_1] * abs_dir1; \
+ if (pmin > rad || -rad > pmax) return false; \
+ }
#endif
-#define TEST_CROSS_EDGE_BOX_X_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
-{\
- TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,2,1,1,2);\
-}\
-
-#define TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
-{\
- TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,0,2,2,0);\
-}\
-
-#define TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
-{\
- TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,1,0,0,1);\
-}\
+#define TEST_CROSS_EDGE_BOX_X_AXIS_MCR(edge, absolute_edge, pointa, pointb, _extend) \
+ { \
+ TEST_CROSS_EDGE_BOX_MCR(edge, absolute_edge, pointa, pointb, _extend, 2, 1, 1, 2); \
+ }
+#define TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(edge, absolute_edge, pointa, pointb, _extend) \
+ { \
+ TEST_CROSS_EDGE_BOX_MCR(edge, absolute_edge, pointa, pointb, _extend, 0, 2, 2, 0); \
+ }
+#define TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(edge, absolute_edge, pointa, pointb, _extend) \
+ { \
+ TEST_CROSS_EDGE_BOX_MCR(edge, absolute_edge, pointa, pointb, _extend, 1, 0, 0, 1); \
+ }
//! Class for transforming a model1 to the space of model0
class GIM_BOX_BOX_TRANSFORM_CACHE
{
public:
- btVector3 m_T1to0;//!< Transforms translation of model1 to model 0
- btMatrix3x3 m_R1to0;//!< Transforms Rotation of model1 to model 0, equal to R0' * R1
- btMatrix3x3 m_AR;//!< Absolute value of m_R1to0
+ btVector3 m_T1to0; //!< Transforms translation of model1 to model 0
+ btMatrix3x3 m_R1to0; //!< Transforms Rotation of model1 to model 0, equal to R0' * R1
+ btMatrix3x3 m_AR; //!< Absolute value of m_R1to0
SIMD_FORCE_INLINE void calc_absolute_matrix()
{
- static const btVector3 vepsi(1e-6f,1e-6f,1e-6f);
+ static const btVector3 vepsi(1e-6f, 1e-6f, 1e-6f);
m_AR[0] = vepsi + m_R1to0[0].absolute();
m_AR[1] = vepsi + m_R1to0[1].absolute();
m_AR[2] = vepsi + m_R1to0[2].absolute();
@@ -154,42 +150,40 @@ public:
{
}
-
- GIM_BOX_BOX_TRANSFORM_CACHE(mat4f trans1_to_0)
+ GIM_BOX_BOX_TRANSFORM_CACHE(mat4f trans1_to_0)
{
- COPY_MATRIX_3X3(m_R1to0,trans1_to_0)
- MAT_GET_TRANSLATION(trans1_to_0,m_T1to0)
+ COPY_MATRIX_3X3(m_R1to0, trans1_to_0)
+ MAT_GET_TRANSLATION(trans1_to_0, m_T1to0)
calc_absolute_matrix();
}
//! Calc the transformation relative 1 to 0. Inverts matrics by transposing
- SIMD_FORCE_INLINE void calc_from_homogenic(const btTransform & trans0,const btTransform & trans1)
+ SIMD_FORCE_INLINE void calc_from_homogenic(const btTransform &trans0, const btTransform &trans1)
{
-
m_R1to0 = trans0.getBasis().transpose();
m_T1to0 = m_R1to0 * (-trans0.getOrigin());
- m_T1to0 += m_R1to0*trans1.getOrigin();
+ m_T1to0 += m_R1to0 * trans1.getOrigin();
m_R1to0 *= trans1.getBasis();
calc_absolute_matrix();
}
//! Calcs the full invertion of the matrices. Useful for scaling matrices
- SIMD_FORCE_INLINE void calc_from_full_invert(const btTransform & trans0,const btTransform & trans1)
+ SIMD_FORCE_INLINE void calc_from_full_invert(const btTransform &trans0, const btTransform &trans1)
{
m_R1to0 = trans0.getBasis().inverse();
m_T1to0 = m_R1to0 * (-trans0.getOrigin());
- m_T1to0 += m_R1to0*trans1.getOrigin();
+ m_T1to0 += m_R1to0 * trans1.getOrigin();
m_R1to0 *= trans1.getBasis();
calc_absolute_matrix();
}
- SIMD_FORCE_INLINE btVector3 transform(const btVector3 & point)
+ SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point)
{
- return point.dot3(m_R1to0[0], m_R1to0[1], m_R1to0[2]) + m_T1to0;
+ return point.dot3(m_R1to0[0], m_R1to0[1], m_R1to0[2]) + m_T1to0;
}
};
@@ -205,34 +199,34 @@ public:
btVector3 m_max;
GIM_AABB()
- {}
-
+ {
+ }
- GIM_AABB(const btVector3 & V1,
- const btVector3 & V2,
- const btVector3 & V3)
+ GIM_AABB(const btVector3 &V1,
+ const btVector3 &V2,
+ const btVector3 &V3)
{
- m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]);
- m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]);
- m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]);
+ m_min[0] = GIM_MIN3(V1[0], V2[0], V3[0]);
+ m_min[1] = GIM_MIN3(V1[1], V2[1], V3[1]);
+ m_min[2] = GIM_MIN3(V1[2], V2[2], V3[2]);
- m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]);
- m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]);
- m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]);
+ m_max[0] = GIM_MAX3(V1[0], V2[0], V3[0]);
+ m_max[1] = GIM_MAX3(V1[1], V2[1], V3[1]);
+ m_max[2] = GIM_MAX3(V1[2], V2[2], V3[2]);
}
- GIM_AABB(const btVector3 & V1,
- const btVector3 & V2,
- const btVector3 & V3,
+ GIM_AABB(const btVector3 &V1,
+ const btVector3 &V2,
+ const btVector3 &V3,
GREAL margin)
{
- m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]);
- m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]);
- m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]);
+ m_min[0] = GIM_MIN3(V1[0], V2[0], V3[0]);
+ m_min[1] = GIM_MIN3(V1[1], V2[1], V3[1]);
+ m_min[2] = GIM_MIN3(V1[2], V2[2], V3[2]);
- m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]);
- m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]);
- m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]);
+ m_max[0] = GIM_MAX3(V1[0], V2[0], V3[0]);
+ m_max[1] = GIM_MAX3(V1[1], V2[1], V3[1]);
+ m_max[2] = GIM_MAX3(V1[2], V2[2], V3[2]);
m_min[0] -= margin;
m_min[1] -= margin;
@@ -242,13 +236,11 @@ public:
m_max[2] += margin;
}
- GIM_AABB(const GIM_AABB &other):
- m_min(other.m_min),m_max(other.m_max)
+ GIM_AABB(const GIM_AABB &other) : m_min(other.m_min), m_max(other.m_max)
{
}
- GIM_AABB(const GIM_AABB &other,btScalar margin ):
- m_min(other.m_min),m_max(other.m_max)
+ GIM_AABB(const GIM_AABB &other, btScalar margin) : m_min(other.m_min), m_max(other.m_max)
{
m_min[0] -= margin;
m_min[1] -= margin;
@@ -289,34 +281,34 @@ public:
m_max[2] = other.m_max[2] + margin;
}
- template<typename CLASS_POINT>
+ template <typename CLASS_POINT>
SIMD_FORCE_INLINE void calc_from_triangle(
- const CLASS_POINT & V1,
- const CLASS_POINT & V2,
- const CLASS_POINT & V3)
+ const CLASS_POINT &V1,
+ const CLASS_POINT &V2,
+ const CLASS_POINT &V3)
{
- m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]);
- m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]);
- m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]);
+ m_min[0] = GIM_MIN3(V1[0], V2[0], V3[0]);
+ m_min[1] = GIM_MIN3(V1[1], V2[1], V3[1]);
+ m_min[2] = GIM_MIN3(V1[2], V2[2], V3[2]);
- m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]);
- m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]);
- m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]);
+ m_max[0] = GIM_MAX3(V1[0], V2[0], V3[0]);
+ m_max[1] = GIM_MAX3(V1[1], V2[1], V3[1]);
+ m_max[2] = GIM_MAX3(V1[2], V2[2], V3[2]);
}
- template<typename CLASS_POINT>
+ template <typename CLASS_POINT>
SIMD_FORCE_INLINE void calc_from_triangle_margin(
- const CLASS_POINT & V1,
- const CLASS_POINT & V2,
- const CLASS_POINT & V3, btScalar margin)
+ const CLASS_POINT &V1,
+ const CLASS_POINT &V2,
+ const CLASS_POINT &V3, btScalar margin)
{
- m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]);
- m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]);
- m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]);
+ m_min[0] = GIM_MIN3(V1[0], V2[0], V3[0]);
+ m_min[1] = GIM_MIN3(V1[1], V2[1], V3[1]);
+ m_min[2] = GIM_MIN3(V1[2], V2[2], V3[2]);
- m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]);
- m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]);
- m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]);
+ m_max[0] = GIM_MAX3(V1[0], V2[0], V3[0]);
+ m_max[1] = GIM_MAX3(V1[1], V2[1], V3[1]);
+ m_max[2] = GIM_MAX3(V1[2], V2[2], V3[2]);
m_min[0] -= margin;
m_min[1] -= margin;
@@ -327,74 +319,73 @@ public:
}
//! Apply a transform to an AABB
- SIMD_FORCE_INLINE void appy_transform(const btTransform & trans)
+ SIMD_FORCE_INLINE void appy_transform(const btTransform &trans)
{
- btVector3 center = (m_max+m_min)*0.5f;
+ btVector3 center = (m_max + m_min) * 0.5f;
btVector3 extends = m_max - center;
// Compute new center
center = trans(center);
- btVector3 textends = extends.dot3(trans.getBasis().getRow(0).absolute(),
- trans.getBasis().getRow(1).absolute(),
- trans.getBasis().getRow(2).absolute());
-
+ btVector3 textends = extends.dot3(trans.getBasis().getRow(0).absolute(),
+ trans.getBasis().getRow(1).absolute(),
+ trans.getBasis().getRow(2).absolute());
+
m_min = center - textends;
m_max = center + textends;
}
//! Merges a Box
- SIMD_FORCE_INLINE void merge(const GIM_AABB & box)
+ SIMD_FORCE_INLINE void merge(const GIM_AABB &box)
{
- m_min[0] = GIM_MIN(m_min[0],box.m_min[0]);
- m_min[1] = GIM_MIN(m_min[1],box.m_min[1]);
- m_min[2] = GIM_MIN(m_min[2],box.m_min[2]);
+ m_min[0] = GIM_MIN(m_min[0], box.m_min[0]);
+ m_min[1] = GIM_MIN(m_min[1], box.m_min[1]);
+ m_min[2] = GIM_MIN(m_min[2], box.m_min[2]);
- m_max[0] = GIM_MAX(m_max[0],box.m_max[0]);
- m_max[1] = GIM_MAX(m_max[1],box.m_max[1]);
- m_max[2] = GIM_MAX(m_max[2],box.m_max[2]);
+ m_max[0] = GIM_MAX(m_max[0], box.m_max[0]);
+ m_max[1] = GIM_MAX(m_max[1], box.m_max[1]);
+ m_max[2] = GIM_MAX(m_max[2], box.m_max[2]);
}
//! Merges a point
- template<typename CLASS_POINT>
- SIMD_FORCE_INLINE void merge_point(const CLASS_POINT & point)
+ template <typename CLASS_POINT>
+ SIMD_FORCE_INLINE void merge_point(const CLASS_POINT &point)
{
- m_min[0] = GIM_MIN(m_min[0],point[0]);
- m_min[1] = GIM_MIN(m_min[1],point[1]);
- m_min[2] = GIM_MIN(m_min[2],point[2]);
+ m_min[0] = GIM_MIN(m_min[0], point[0]);
+ m_min[1] = GIM_MIN(m_min[1], point[1]);
+ m_min[2] = GIM_MIN(m_min[2], point[2]);
- m_max[0] = GIM_MAX(m_max[0],point[0]);
- m_max[1] = GIM_MAX(m_max[1],point[1]);
- m_max[2] = GIM_MAX(m_max[2],point[2]);
+ m_max[0] = GIM_MAX(m_max[0], point[0]);
+ m_max[1] = GIM_MAX(m_max[1], point[1]);
+ m_max[2] = GIM_MAX(m_max[2], point[2]);
}
//! Gets the extend and center
- SIMD_FORCE_INLINE void get_center_extend(btVector3 & center,btVector3 & extend) const
+ SIMD_FORCE_INLINE void get_center_extend(btVector3 &center, btVector3 &extend) const
{
- center = (m_max+m_min)*0.5f;
+ center = (m_max + m_min) * 0.5f;
extend = m_max - center;
}
//! Finds the intersecting box between this box and the other.
- SIMD_FORCE_INLINE void find_intersection(const GIM_AABB & other, GIM_AABB & intersection) const
+ SIMD_FORCE_INLINE void find_intersection(const GIM_AABB &other, GIM_AABB &intersection) const
{
- intersection.m_min[0] = GIM_MAX(other.m_min[0],m_min[0]);
- intersection.m_min[1] = GIM_MAX(other.m_min[1],m_min[1]);
- intersection.m_min[2] = GIM_MAX(other.m_min[2],m_min[2]);
+ intersection.m_min[0] = GIM_MAX(other.m_min[0], m_min[0]);
+ intersection.m_min[1] = GIM_MAX(other.m_min[1], m_min[1]);
+ intersection.m_min[2] = GIM_MAX(other.m_min[2], m_min[2]);
- intersection.m_max[0] = GIM_MIN(other.m_max[0],m_max[0]);
- intersection.m_max[1] = GIM_MIN(other.m_max[1],m_max[1]);
- intersection.m_max[2] = GIM_MIN(other.m_max[2],m_max[2]);
+ intersection.m_max[0] = GIM_MIN(other.m_max[0], m_max[0]);
+ intersection.m_max[1] = GIM_MIN(other.m_max[1], m_max[1]);
+ intersection.m_max[2] = GIM_MIN(other.m_max[2], m_max[2]);
}
-
- SIMD_FORCE_INLINE bool has_collision(const GIM_AABB & other) const
+ SIMD_FORCE_INLINE bool has_collision(const GIM_AABB &other) const
{
- if(m_min[0] > other.m_max[0] ||
- m_max[0] < other.m_min[0] ||
- m_min[1] > other.m_max[1] ||
- m_max[1] < other.m_min[1] ||
- m_min[2] > other.m_max[2] ||
- m_max[2] < other.m_min[2])
+ if (m_min[0] > other.m_max[0] ||
+ m_max[0] < other.m_min[0] ||
+ m_min[1] > other.m_max[1] ||
+ m_max[1] < other.m_min[1] ||
+ m_min[2] > other.m_max[2] ||
+ m_max[2] < other.m_min[2])
{
return false;
}
@@ -406,35 +397,34 @@ public:
\param vorigin A vec3f with the origin of the ray
\param vdir A vec3f with the direction of the ray
*/
- SIMD_FORCE_INLINE bool collide_ray(const btVector3 & vorigin,const btVector3 & vdir)
+ SIMD_FORCE_INLINE bool collide_ray(const btVector3 &vorigin, const btVector3 &vdir)
{
- btVector3 extents,center;
- this->get_center_extend(center,extents);;
+ btVector3 extents, center;
+ this->get_center_extend(center, extents);
+ ;
btScalar Dx = vorigin[0] - center[0];
- if(GIM_GREATER(Dx, extents[0]) && Dx*vdir[0]>=0.0f) return false;
+ if (GIM_GREATER(Dx, extents[0]) && Dx * vdir[0] >= 0.0f) return false;
btScalar Dy = vorigin[1] - center[1];
- if(GIM_GREATER(Dy, extents[1]) && Dy*vdir[1]>=0.0f) return false;
+ if (GIM_GREATER(Dy, extents[1]) && Dy * vdir[1] >= 0.0f) return false;
btScalar Dz = vorigin[2] - center[2];
- if(GIM_GREATER(Dz, extents[2]) && Dz*vdir[2]>=0.0f) return false;
-
+ if (GIM_GREATER(Dz, extents[2]) && Dz * vdir[2] >= 0.0f) return false;
btScalar f = vdir[1] * Dz - vdir[2] * Dy;
- if(btFabs(f) > extents[1]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[1])) return false;
+ if (btFabs(f) > extents[1] * btFabs(vdir[2]) + extents[2] * btFabs(vdir[1])) return false;
f = vdir[2] * Dx - vdir[0] * Dz;
- if(btFabs(f) > extents[0]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[0]))return false;
+ if (btFabs(f) > extents[0] * btFabs(vdir[2]) + extents[2] * btFabs(vdir[0])) return false;
f = vdir[0] * Dy - vdir[1] * Dx;
- if(btFabs(f) > extents[0]*btFabs(vdir[1]) + extents[1]*btFabs(vdir[0]))return false;
+ if (btFabs(f) > extents[0] * btFabs(vdir[1]) + extents[1] * btFabs(vdir[0])) return false;
return true;
}
-
- SIMD_FORCE_INLINE void projection_interval(const btVector3 & direction, btScalar &vmin, btScalar &vmax) const
+ SIMD_FORCE_INLINE void projection_interval(const btVector3 &direction, btScalar &vmin, btScalar &vmax) const
{
- btVector3 center = (m_max+m_min)*0.5f;
- btVector3 extend = m_max-center;
+ btVector3 center = (m_max + m_min) * 0.5f;
+ btVector3 extend = m_max - center;
- btScalar _fOrigin = direction.dot(center);
+ btScalar _fOrigin = direction.dot(center);
btScalar _fMaximumExtent = extend.dot(direction.absolute());
vmin = _fOrigin - _fMaximumExtent;
vmax = _fOrigin + _fMaximumExtent;
@@ -442,22 +432,22 @@ public:
SIMD_FORCE_INLINE ePLANE_INTERSECTION_TYPE plane_classify(const btVector4 &plane) const
{
- btScalar _fmin,_fmax;
- this->projection_interval(plane,_fmin,_fmax);
+ btScalar _fmin, _fmax;
+ this->projection_interval(plane, _fmin, _fmax);
- if(plane[3] > _fmax + BOX_PLANE_EPSILON)
+ if (plane[3] > _fmax + BOX_PLANE_EPSILON)
{
- return G_BACK_PLANE; // 0
+ return G_BACK_PLANE; // 0
}
- if(plane[3]+BOX_PLANE_EPSILON >=_fmin)
+ if (plane[3] + BOX_PLANE_EPSILON >= _fmin)
{
- return G_COLLIDE_PLANE; //1
+ return G_COLLIDE_PLANE; //1
}
- return G_FRONT_PLANE;//2
+ return G_FRONT_PLANE; //2
}
- SIMD_FORCE_INLINE bool overlapping_trans_conservative(const GIM_AABB & box, btTransform & trans1_to_0)
+ SIMD_FORCE_INLINE bool overlapping_trans_conservative(const GIM_AABB &box, btTransform &trans1_to_0)
{
GIM_AABB tbox = box;
tbox.appy_transform(trans1_to_0);
@@ -466,52 +456,50 @@ public:
//! transcache is the transformation cache from box to this AABB
SIMD_FORCE_INLINE bool overlapping_trans_cache(
- const GIM_AABB & box,const GIM_BOX_BOX_TRANSFORM_CACHE & transcache, bool fulltest)
+ const GIM_AABB &box, const GIM_BOX_BOX_TRANSFORM_CACHE &transcache, bool fulltest)
{
-
//Taken from OPCODE
- btVector3 ea,eb;//extends
- btVector3 ca,cb;//extends
- get_center_extend(ca,ea);
- box.get_center_extend(cb,eb);
-
+ btVector3 ea, eb; //extends
+ btVector3 ca, cb; //extends
+ get_center_extend(ca, ea);
+ box.get_center_extend(cb, eb);
btVector3 T;
- btScalar t,t2;
+ btScalar t, t2;
int i;
// Class I : A's basis vectors
- for(i=0;i<3;i++)
+ for (i = 0; i < 3; i++)
{
- T[i] = transcache.m_R1to0[i].dot(cb) + transcache.m_T1to0[i] - ca[i];
+ T[i] = transcache.m_R1to0[i].dot(cb) + transcache.m_T1to0[i] - ca[i];
t = transcache.m_AR[i].dot(eb) + ea[i];
- if(GIM_GREATER(T[i], t)) return false;
+ if (GIM_GREATER(T[i], t)) return false;
}
// Class II : B's basis vectors
- for(i=0;i<3;i++)
+ for (i = 0; i < 3; i++)
{
- t = MAT_DOT_COL(transcache.m_R1to0,T,i);
- t2 = MAT_DOT_COL(transcache.m_AR,ea,i) + eb[i];
- if(GIM_GREATER(t,t2)) return false;
+ t = MAT_DOT_COL(transcache.m_R1to0, T, i);
+ t2 = MAT_DOT_COL(transcache.m_AR, ea, i) + eb[i];
+ if (GIM_GREATER(t, t2)) return false;
}
// Class III : 9 cross products
- if(fulltest)
+ if (fulltest)
{
- int j,m,n,o,p,q,r;
- for(i=0;i<3;i++)
+ int j, m, n, o, p, q, r;
+ for (i = 0; i < 3; i++)
{
- m = (i+1)%3;
- n = (i+2)%3;
- o = i==0?1:0;
- p = i==2?1:2;
- for(j=0;j<3;j++)
+ m = (i + 1) % 3;
+ n = (i + 2) % 3;
+ o = i == 0 ? 1 : 0;
+ p = i == 2 ? 1 : 2;
+ for (j = 0; j < 3; j++)
{
- q = j==2?1:2;
- r = j==0?1:0;
- t = T[n]*transcache.m_R1to0[m][j] - T[m]*transcache.m_R1to0[n][j];
- t2 = ea[o]*transcache.m_AR[p][j] + ea[p]*transcache.m_AR[o][j] +
- eb[r]*transcache.m_AR[i][q] + eb[q]*transcache.m_AR[i][r];
- if(GIM_GREATER(t,t2)) return false;
+ q = j == 2 ? 1 : 2;
+ r = j == 0 ? 1 : 0;
+ t = T[n] * transcache.m_R1to0[m][j] - T[m] * transcache.m_R1to0[n][j];
+ t2 = ea[o] * transcache.m_AR[p][j] + ea[p] * transcache.m_AR[o][j] +
+ eb[r] * transcache.m_AR[i][q] + eb[q] * transcache.m_AR[i][r];
+ if (GIM_GREATER(t, t2)) return false;
}
}
}
@@ -520,7 +508,7 @@ public:
//! Simple test for planes.
SIMD_FORCE_INLINE bool collide_plane(
- const btVector4 & plane)
+ const btVector4 &plane)
{
ePLANE_INTERSECTION_TYPE classify = plane_classify(plane);
return (classify == G_COLLIDE_PLANE);
@@ -528,15 +516,15 @@ public:
//! test for a triangle, with edges
SIMD_FORCE_INLINE bool collide_triangle_exact(
- const btVector3 & p1,
- const btVector3 & p2,
- const btVector3 & p3,
- const btVector4 & triangle_plane)
+ const btVector3 &p1,
+ const btVector3 &p2,
+ const btVector3 &p3,
+ const btVector4 &triangle_plane)
{
- if(!collide_plane(triangle_plane)) return false;
+ if (!collide_plane(triangle_plane)) return false;
- btVector3 center,extends;
- this->get_center_extend(center,extends);
+ btVector3 center, extends;
+ this->get_center_extend(center, extends);
const btVector3 v1(p1 - center);
const btVector3 v2(p2 - center);
@@ -546,30 +534,29 @@ public:
btVector3 diff(v2 - v1);
btVector3 abs_diff = diff.absolute();
//Test With X axis
- TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v1,v3,extends);
+ TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff, abs_diff, v1, v3, extends);
//Test With Y axis
- TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v1,v3,extends);
+ TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff, abs_diff, v1, v3, extends);
//Test With Z axis
- TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v1,v3,extends);
-
+ TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff, abs_diff, v1, v3, extends);
diff = v3 - v2;
abs_diff = diff.absolute();
//Test With X axis
- TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v2,v1,extends);
+ TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff, abs_diff, v2, v1, extends);
//Test With Y axis
- TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v2,v1,extends);
+ TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff, abs_diff, v2, v1, extends);
//Test With Z axis
- TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v2,v1,extends);
+ TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff, abs_diff, v2, v1, extends);
diff = v1 - v3;
abs_diff = diff.absolute();
//Test With X axis
- TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v3,v2,extends);
+ TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff, abs_diff, v3, v2, extends);
//Test With Y axis
- TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v3,v2,extends);
+ TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff, abs_diff, v3, v2, extends);
//Test With Z axis
- TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v3,v2,extends);
+ TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff, abs_diff, v3, v2, extends);
return true;
}
@@ -577,17 +564,15 @@ public:
#ifndef BT_BOX_COLLISION_H_INCLUDED
//! Compairison of transformation objects
-SIMD_FORCE_INLINE bool btCompareTransformsEqual(const btTransform & t1,const btTransform & t2)
+SIMD_FORCE_INLINE bool btCompareTransformsEqual(const btTransform &t1, const btTransform &t2)
{
- if(!(t1.getOrigin() == t2.getOrigin()) ) return false;
+ if (!(t1.getOrigin() == t2.getOrigin())) return false;
- if(!(t1.getBasis().getRow(0) == t2.getBasis().getRow(0)) ) return false;
- if(!(t1.getBasis().getRow(1) == t2.getBasis().getRow(1)) ) return false;
- if(!(t1.getBasis().getRow(2) == t2.getBasis().getRow(2)) ) return false;
+ if (!(t1.getBasis().getRow(0) == t2.getBasis().getRow(0))) return false;
+ if (!(t1.getBasis().getRow(1) == t2.getBasis().getRow(1))) return false;
+ if (!(t1.getBasis().getRow(2) == t2.getBasis().getRow(2))) return false;
return true;
}
#endif
-
-
-#endif // GIM_BOX_COLLISION_H_INCLUDED
+#endif // GIM_BOX_COLLISION_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_box_set.cpp b/thirdparty/bullet/BulletCollision/Gimpact/gim_box_set.cpp
index 0c3d7ba8db..0c7a6b7fc1 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_box_set.cpp
+++ b/thirdparty/bullet/BulletCollision/Gimpact/gim_box_set.cpp
@@ -28,67 +28,64 @@ email: projectileman@yahoo.com
-----------------------------------------------------------------------------
*/
-
#include "gim_box_set.h"
-
GUINT GIM_BOX_TREE::_calc_splitting_axis(
- gim_array<GIM_AABB_DATA> & primitive_boxes, GUINT startIndex, GUINT endIndex)
+ gim_array<GIM_AABB_DATA>& primitive_boxes, GUINT startIndex, GUINT endIndex)
{
GUINT i;
- btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
- btVector3 variance(btScalar(0.),btScalar(0.),btScalar(0.));
- GUINT numIndices = endIndex-startIndex;
+ btVector3 means(btScalar(0.), btScalar(0.), btScalar(0.));
+ btVector3 variance(btScalar(0.), btScalar(0.), btScalar(0.));
+ GUINT numIndices = endIndex - startIndex;
- for (i=startIndex;i<endIndex;i++)
+ for (i = startIndex; i < endIndex; i++)
{
- btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
- primitive_boxes[i].m_bound.m_min);
- means+=center;
+ btVector3 center = btScalar(0.5) * (primitive_boxes[i].m_bound.m_max +
+ primitive_boxes[i].m_bound.m_min);
+ means += center;
}
- means *= (btScalar(1.)/(btScalar)numIndices);
+ means *= (btScalar(1.) / (btScalar)numIndices);
- for (i=startIndex;i<endIndex;i++)
+ for (i = startIndex; i < endIndex; i++)
{
- btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
- primitive_boxes[i].m_bound.m_min);
- btVector3 diff2 = center-means;
+ btVector3 center = btScalar(0.5) * (primitive_boxes[i].m_bound.m_max +
+ primitive_boxes[i].m_bound.m_min);
+ btVector3 diff2 = center - means;
diff2 = diff2 * diff2;
variance += diff2;
}
- variance *= (btScalar(1.)/ ((btScalar)numIndices-1) );
+ variance *= (btScalar(1.) / ((btScalar)numIndices - 1));
return variance.maxAxis();
}
-
GUINT GIM_BOX_TREE::_sort_and_calc_splitting_index(
- gim_array<GIM_AABB_DATA> & primitive_boxes, GUINT startIndex,
+ gim_array<GIM_AABB_DATA>& primitive_boxes, GUINT startIndex,
GUINT endIndex, GUINT splitAxis)
{
GUINT i;
- GUINT splitIndex =startIndex;
+ GUINT splitIndex = startIndex;
GUINT numIndices = endIndex - startIndex;
// average of centers
btScalar splitValue = 0.0f;
- for (i=startIndex;i<endIndex;i++)
+ for (i = startIndex; i < endIndex; i++)
{
- splitValue+= 0.5f*(primitive_boxes[i].m_bound.m_max[splitAxis] +
- primitive_boxes[i].m_bound.m_min[splitAxis]);
+ splitValue += 0.5f * (primitive_boxes[i].m_bound.m_max[splitAxis] +
+ primitive_boxes[i].m_bound.m_min[splitAxis]);
}
splitValue /= (btScalar)numIndices;
//sort leafNodes so all values larger then splitValue comes first, and smaller values start from 'splitIndex'.
- for (i=startIndex;i<endIndex;i++)
+ for (i = startIndex; i < endIndex; i++)
{
- btScalar center = 0.5f*(primitive_boxes[i].m_bound.m_max[splitAxis] +
- primitive_boxes[i].m_bound.m_min[splitAxis]);
+ btScalar center = 0.5f * (primitive_boxes[i].m_bound.m_max[splitAxis] +
+ primitive_boxes[i].m_bound.m_min[splitAxis]);
if (center > splitValue)
{
//swap
- primitive_boxes.swap(i,splitIndex);
+ primitive_boxes.swap(i, splitIndex);
splitIndex++;
}
}
@@ -102,28 +99,27 @@ GUINT GIM_BOX_TREE::_sort_and_calc_splitting_index(
//bool unbalanced2 = true;
//this should be safe too:
- GUINT rangeBalancedIndices = numIndices/3;
- bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices)));
+ GUINT rangeBalancedIndices = numIndices / 3;
+ bool unbalanced = ((splitIndex <= (startIndex + rangeBalancedIndices)) || (splitIndex >= (endIndex - 1 - rangeBalancedIndices)));
if (unbalanced)
{
- splitIndex = startIndex+ (numIndices>>1);
+ splitIndex = startIndex + (numIndices >> 1);
}
- btAssert(!((splitIndex==startIndex) || (splitIndex == (endIndex))));
+ btAssert(!((splitIndex == startIndex) || (splitIndex == (endIndex))));
return splitIndex;
}
-
-void GIM_BOX_TREE::_build_sub_tree(gim_array<GIM_AABB_DATA> & primitive_boxes, GUINT startIndex, GUINT endIndex)
+void GIM_BOX_TREE::_build_sub_tree(gim_array<GIM_AABB_DATA>& primitive_boxes, GUINT startIndex, GUINT endIndex)
{
GUINT current_index = m_num_nodes++;
- btAssert((endIndex-startIndex)>0);
+ btAssert((endIndex - startIndex) > 0);
- if((endIndex-startIndex) == 1) //we got a leaf
- {
+ if ((endIndex - startIndex) == 1) //we got a leaf
+ {
m_node_array[current_index].m_left = 0;
m_node_array[current_index].m_right = 0;
m_node_array[current_index].m_escapeIndex = 0;
@@ -138,8 +134,8 @@ void GIM_BOX_TREE::_build_sub_tree(gim_array<GIM_AABB_DATA> & primitive_boxes, G
GUINT splitIndex;
//calc this node bounding box
- m_node_array[current_index].m_bound.invalidate();
- for (splitIndex=startIndex;splitIndex<endIndex;splitIndex++)
+ m_node_array[current_index].m_bound.invalidate();
+ for (splitIndex = startIndex; splitIndex < endIndex; splitIndex++)
{
m_node_array[current_index].m_bound.merge(primitive_boxes[splitIndex].m_bound);
}
@@ -147,36 +143,34 @@ void GIM_BOX_TREE::_build_sub_tree(gim_array<GIM_AABB_DATA> & primitive_boxes, G
//calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'.
//split axis
- splitIndex = _calc_splitting_axis(primitive_boxes,startIndex,endIndex);
+ splitIndex = _calc_splitting_axis(primitive_boxes, startIndex, endIndex);
splitIndex = _sort_and_calc_splitting_index(
- primitive_boxes,startIndex,endIndex,splitIndex);
+ primitive_boxes, startIndex, endIndex, splitIndex);
//configure this inner node : the left node index
m_node_array[current_index].m_left = m_num_nodes;
//build left child tree
- _build_sub_tree(primitive_boxes, startIndex, splitIndex );
+ _build_sub_tree(primitive_boxes, startIndex, splitIndex);
//configure this inner node : the right node index
m_node_array[current_index].m_right = m_num_nodes;
//build right child tree
- _build_sub_tree(primitive_boxes, splitIndex ,endIndex);
+ _build_sub_tree(primitive_boxes, splitIndex, endIndex);
//configure this inner node : the escape index
- m_node_array[current_index].m_escapeIndex = m_num_nodes - current_index;
+ m_node_array[current_index].m_escapeIndex = m_num_nodes - current_index;
}
//! stackless build tree
void GIM_BOX_TREE::build_tree(
- gim_array<GIM_AABB_DATA> & primitive_boxes)
+ gim_array<GIM_AABB_DATA>& primitive_boxes)
{
// initialize node count to 0
m_num_nodes = 0;
// allocate nodes
- m_node_array.resize(primitive_boxes.size()*2);
-
+ m_node_array.resize(primitive_boxes.size() * 2);
+
_build_sub_tree(primitive_boxes, 0, primitive_boxes.size());
}
-
-
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_box_set.h b/thirdparty/bullet/BulletCollision/Gimpact/gim_box_set.h
index 61d190a7df..0522007e4f 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_box_set.h
+++ b/thirdparty/bullet/BulletCollision/Gimpact/gim_box_set.h
@@ -33,54 +33,51 @@ email: projectileman@yahoo.com
-----------------------------------------------------------------------------
*/
-
#include "gim_array.h"
#include "gim_radixsort.h"
#include "gim_box_collision.h"
#include "gim_tri_collision.h"
-
-
//! Overlapping pair
struct GIM_PAIR
{
- GUINT m_index1;
- GUINT m_index2;
- GIM_PAIR()
- {}
+ GUINT m_index1;
+ GUINT m_index2;
+ GIM_PAIR()
+ {
+ }
- GIM_PAIR(const GIM_PAIR & p)
- {
- m_index1 = p.m_index1;
- m_index2 = p.m_index2;
+ GIM_PAIR(const GIM_PAIR& p)
+ {
+ m_index1 = p.m_index1;
+ m_index2 = p.m_index2;
}
GIM_PAIR(GUINT index1, GUINT index2)
- {
- m_index1 = index1;
- m_index2 = index2;
+ {
+ m_index1 = index1;
+ m_index2 = index2;
}
};
//! A pairset array
-class gim_pair_set: public gim_array<GIM_PAIR>
+class gim_pair_set : public gim_array<GIM_PAIR>
{
public:
- gim_pair_set():gim_array<GIM_PAIR>(32)
+ gim_pair_set() : gim_array<GIM_PAIR>(32)
{
}
- inline void push_pair(GUINT index1,GUINT index2)
+ inline void push_pair(GUINT index1, GUINT index2)
{
- push_back(GIM_PAIR(index1,index2));
+ push_back(GIM_PAIR(index1, index2));
}
- inline void push_pair_inv(GUINT index1,GUINT index2)
+ inline void push_pair_inv(GUINT index1, GUINT index2)
{
- push_back(GIM_PAIR(index2,index1));
+ push_back(GIM_PAIR(index2, index1));
}
};
-
//! Prototype Base class for primitive classification
/*!
This class is a wrapper for primitive collections.
@@ -90,16 +87,14 @@ This class can manage Compound shapes and trimeshes, and if it is managing trime
class GIM_PRIMITIVE_MANAGER_PROTOTYPE
{
public:
-
virtual ~GIM_PRIMITIVE_MANAGER_PROTOTYPE() {}
//! determines if this manager consist on only triangles, which special case will be optimized
virtual bool is_trimesh() = 0;
virtual GUINT get_primitive_count() = 0;
- virtual void get_primitive_box(GUINT prim_index ,GIM_AABB & primbox) = 0;
- virtual void get_primitive_triangle(GUINT prim_index,GIM_TRIANGLE & triangle) = 0;
+ virtual void get_primitive_box(GUINT prim_index, GIM_AABB& primbox) = 0;
+ virtual void get_primitive_triangle(GUINT prim_index, GIM_TRIANGLE& triangle) = 0;
};
-
struct GIM_AABB_DATA
{
GIM_AABB m_bound;
@@ -110,22 +105,22 @@ struct GIM_AABB_DATA
struct GIM_BOX_TREE_NODE
{
GIM_AABB m_bound;
- GUINT m_left;//!< Left subtree
- GUINT m_right;//!< Right subtree
- GUINT m_escapeIndex;//!< Scape index for traversing
- GUINT m_data;//!< primitive index if apply
+ GUINT m_left; //!< Left subtree
+ GUINT m_right; //!< Right subtree
+ GUINT m_escapeIndex; //!< Scape index for traversing
+ GUINT m_data; //!< primitive index if apply
GIM_BOX_TREE_NODE()
{
- m_left = 0;
- m_right = 0;
- m_escapeIndex = 0;
- m_data = 0;
+ m_left = 0;
+ m_right = 0;
+ m_escapeIndex = 0;
+ m_data = 0;
}
SIMD_FORCE_INLINE bool is_leaf_node() const
{
- return (!m_left && !m_right);
+ return (!m_left && !m_right);
}
};
@@ -135,14 +130,16 @@ class GIM_BOX_TREE
protected:
GUINT m_num_nodes;
gim_array<GIM_BOX_TREE_NODE> m_node_array;
+
protected:
GUINT _sort_and_calc_splitting_index(
- gim_array<GIM_AABB_DATA> & primitive_boxes,
- GUINT startIndex, GUINT endIndex, GUINT splitAxis);
+ gim_array<GIM_AABB_DATA>& primitive_boxes,
+ GUINT startIndex, GUINT endIndex, GUINT splitAxis);
- GUINT _calc_splitting_axis(gim_array<GIM_AABB_DATA> & primitive_boxes, GUINT startIndex, GUINT endIndex);
+ GUINT _calc_splitting_axis(gim_array<GIM_AABB_DATA>& primitive_boxes, GUINT startIndex, GUINT endIndex);
+
+ void _build_sub_tree(gim_array<GIM_AABB_DATA>& primitive_boxes, GUINT startIndex, GUINT endIndex);
- void _build_sub_tree(gim_array<GIM_AABB_DATA> & primitive_boxes, GUINT startIndex, GUINT endIndex);
public:
GIM_BOX_TREE()
{
@@ -151,7 +148,7 @@ public:
//! prototype functions for box tree management
//!@{
- void build_tree(gim_array<GIM_AABB_DATA> & primitive_boxes);
+ void build_tree(gim_array<GIM_AABB_DATA>& primitive_boxes);
SIMD_FORCE_INLINE void clearNodes()
{
@@ -176,22 +173,22 @@ public:
return m_node_array[nodeindex].m_data;
}
- SIMD_FORCE_INLINE void getNodeBound(GUINT nodeindex, GIM_AABB & bound) const
+ SIMD_FORCE_INLINE void getNodeBound(GUINT nodeindex, GIM_AABB& bound) const
{
bound = m_node_array[nodeindex].m_bound;
}
- SIMD_FORCE_INLINE void setNodeBound(GUINT nodeindex, const GIM_AABB & bound)
+ SIMD_FORCE_INLINE void setNodeBound(GUINT nodeindex, const GIM_AABB& bound)
{
m_node_array[nodeindex].m_bound = bound;
}
- SIMD_FORCE_INLINE GUINT getLeftNodeIndex(GUINT nodeindex) const
+ SIMD_FORCE_INLINE GUINT getLeftNodeIndex(GUINT nodeindex) const
{
return m_node_array[nodeindex].m_left;
}
- SIMD_FORCE_INLINE GUINT getRightNodeIndex(GUINT nodeindex) const
+ SIMD_FORCE_INLINE GUINT getRightNodeIndex(GUINT nodeindex) const
{
return m_node_array[nodeindex].m_right;
}
@@ -204,78 +201,78 @@ public:
//!@}
};
-
//! Generic Box Tree Template
/*!
This class offers an structure for managing a box tree of primitives.
Requires a Primitive prototype (like GIM_PRIMITIVE_MANAGER_PROTOTYPE ) and
a Box tree structure ( like GIM_BOX_TREE).
*/
-template<typename _GIM_PRIMITIVE_MANAGER_PROTOTYPE, typename _GIM_BOX_TREE_PROTOTYPE>
+template <typename _GIM_PRIMITIVE_MANAGER_PROTOTYPE, typename _GIM_BOX_TREE_PROTOTYPE>
class GIM_BOX_TREE_TEMPLATE_SET
{
protected:
_GIM_PRIMITIVE_MANAGER_PROTOTYPE m_primitive_manager;
_GIM_BOX_TREE_PROTOTYPE m_box_tree;
+
protected:
//stackless refit
SIMD_FORCE_INLINE void refit()
{
GUINT nodecount = getNodeCount();
- while(nodecount--)
+ while (nodecount--)
{
- if(isLeafNode(nodecount))
+ if (isLeafNode(nodecount))
{
GIM_AABB leafbox;
- m_primitive_manager.get_primitive_box(getNodeData(nodecount),leafbox);
- setNodeBound(nodecount,leafbox);
+ m_primitive_manager.get_primitive_box(getNodeData(nodecount), leafbox);
+ setNodeBound(nodecount, leafbox);
}
else
{
//get left bound
GUINT childindex = getLeftNodeIndex(nodecount);
GIM_AABB bound;
- getNodeBound(childindex,bound);
+ getNodeBound(childindex, bound);
//get right bound
childindex = getRightNodeIndex(nodecount);
GIM_AABB bound2;
- getNodeBound(childindex,bound2);
+ getNodeBound(childindex, bound2);
bound.merge(bound2);
- setNodeBound(nodecount,bound);
+ setNodeBound(nodecount, bound);
}
}
}
-public:
+public:
GIM_BOX_TREE_TEMPLATE_SET()
{
}
- SIMD_FORCE_INLINE GIM_AABB getGlobalBox() const
+ SIMD_FORCE_INLINE GIM_AABB getGlobalBox() const
{
GIM_AABB totalbox;
getNodeBound(0, totalbox);
return totalbox;
}
- SIMD_FORCE_INLINE void setPrimitiveManager(const _GIM_PRIMITIVE_MANAGER_PROTOTYPE & primitive_manager)
+ SIMD_FORCE_INLINE void setPrimitiveManager(const _GIM_PRIMITIVE_MANAGER_PROTOTYPE& primitive_manager)
{
m_primitive_manager = primitive_manager;
}
- const _GIM_PRIMITIVE_MANAGER_PROTOTYPE & getPrimitiveManager() const
+ const _GIM_PRIMITIVE_MANAGER_PROTOTYPE& getPrimitiveManager() const
{
return m_primitive_manager;
}
- _GIM_PRIMITIVE_MANAGER_PROTOTYPE & getPrimitiveManager()
+ _GIM_PRIMITIVE_MANAGER_PROTOTYPE& getPrimitiveManager()
{
return m_primitive_manager;
}
-//! node manager prototype functions
-///@{
+ //! node manager prototype functions
+ ///@{
//! this attemps to refit the box set.
SIMD_FORCE_INLINE void update()
@@ -288,19 +285,19 @@ public:
{
//obtain primitive boxes
gim_array<GIM_AABB_DATA> primitive_boxes;
- primitive_boxes.resize(m_primitive_manager.get_primitive_count(),false);
+ primitive_boxes.resize(m_primitive_manager.get_primitive_count(), false);
- for (GUINT i = 0;i<primitive_boxes.size() ;i++ )
+ for (GUINT i = 0; i < primitive_boxes.size(); i++)
{
- m_primitive_manager.get_primitive_box(i,primitive_boxes[i].m_bound);
- primitive_boxes[i].m_data = i;
+ m_primitive_manager.get_primitive_box(i, primitive_boxes[i].m_bound);
+ primitive_boxes[i].m_data = i;
}
m_box_tree.build_tree(primitive_boxes);
}
//! returns the indices of the primitives in the m_primitive_manager
- SIMD_FORCE_INLINE bool boxQuery(const GIM_AABB & box, gim_array<GUINT> & collided_results) const
+ SIMD_FORCE_INLINE bool boxQuery(const GIM_AABB& box, gim_array<GUINT>& collided_results) const
{
GUINT curIndex = 0;
GUINT numNodes = getNodeCount();
@@ -308,7 +305,7 @@ public:
while (curIndex < numNodes)
{
GIM_AABB bound;
- getNodeBound(curIndex,bound);
+ getNodeBound(curIndex, bound);
//catch bugs in tree data
@@ -328,26 +325,26 @@ public:
else
{
//skip node
- curIndex+= getScapeNodeIndex(curIndex);
+ curIndex += getScapeNodeIndex(curIndex);
}
}
- if(collided_results.size()>0) return true;
+ if (collided_results.size() > 0) return true;
return false;
}
//! returns the indices of the primitives in the m_primitive_manager
- SIMD_FORCE_INLINE bool boxQueryTrans(const GIM_AABB & box,
- const btTransform & transform, gim_array<GUINT> & collided_results) const
+ SIMD_FORCE_INLINE bool boxQueryTrans(const GIM_AABB& box,
+ const btTransform& transform, gim_array<GUINT>& collided_results) const
{
- GIM_AABB transbox=box;
+ GIM_AABB transbox = box;
transbox.appy_transform(transform);
- return boxQuery(transbox,collided_results);
+ return boxQuery(transbox, collided_results);
}
//! returns the indices of the primitives in the m_primitive_manager
SIMD_FORCE_INLINE bool rayQuery(
- const btVector3 & ray_dir,const btVector3 & ray_origin ,
- gim_array<GUINT> & collided_results) const
+ const btVector3& ray_dir, const btVector3& ray_origin,
+ gim_array<GUINT>& collided_results) const
{
GUINT curIndex = 0;
GUINT numNodes = getNodeCount();
@@ -355,16 +352,16 @@ public:
while (curIndex < numNodes)
{
GIM_AABB bound;
- getNodeBound(curIndex,bound);
+ getNodeBound(curIndex, bound);
//catch bugs in tree data
- bool aabbOverlap = bound.collide_ray(ray_origin,ray_dir);
+ bool aabbOverlap = bound.collide_ray(ray_origin, ray_dir);
bool isleafnode = isLeafNode(curIndex);
if (isleafnode && aabbOverlap)
{
- collided_results.push_back(getNodeData( curIndex));
+ collided_results.push_back(getNodeData(curIndex));
}
if (aabbOverlap || isleafnode)
@@ -375,10 +372,10 @@ public:
else
{
//skip node
- curIndex+= getScapeNodeIndex(curIndex);
+ curIndex += getScapeNodeIndex(curIndex);
}
}
- if(collided_results.size()>0) return true;
+ if (collided_results.size() > 0) return true;
return false;
}
@@ -389,7 +386,7 @@ public:
}
//! tells if this set is a trimesh
- SIMD_FORCE_INLINE bool isTrimesh() const
+ SIMD_FORCE_INLINE bool isTrimesh() const
{
return m_primitive_manager.is_trimesh();
}
@@ -411,12 +408,12 @@ public:
return m_box_tree.getNodeData(nodeindex);
}
- SIMD_FORCE_INLINE void getNodeBound(GUINT nodeindex, GIM_AABB & bound) const
+ SIMD_FORCE_INLINE void getNodeBound(GUINT nodeindex, GIM_AABB& bound) const
{
m_box_tree.getNodeBound(nodeindex, bound);
}
- SIMD_FORCE_INLINE void setNodeBound(GUINT nodeindex, const GIM_AABB & bound)
+ SIMD_FORCE_INLINE void setNodeBound(GUINT nodeindex, const GIM_AABB& bound)
{
m_box_tree.setNodeBound(nodeindex, bound);
}
@@ -436,36 +433,30 @@ public:
return m_box_tree.getScapeNodeIndex(nodeindex);
}
- SIMD_FORCE_INLINE void getNodeTriangle(GUINT nodeindex,GIM_TRIANGLE & triangle) const
+ SIMD_FORCE_INLINE void getNodeTriangle(GUINT nodeindex, GIM_TRIANGLE& triangle) const
{
- m_primitive_manager.get_primitive_triangle(getNodeData(nodeindex),triangle);
+ m_primitive_manager.get_primitive_triangle(getNodeData(nodeindex), triangle);
}
-
};
//! Class for Box Tree Sets
/*!
this has the GIM_BOX_TREE implementation for bounding boxes.
*/
-template<typename _GIM_PRIMITIVE_MANAGER_PROTOTYPE>
-class GIM_BOX_TREE_SET: public GIM_BOX_TREE_TEMPLATE_SET< _GIM_PRIMITIVE_MANAGER_PROTOTYPE, GIM_BOX_TREE>
+template <typename _GIM_PRIMITIVE_MANAGER_PROTOTYPE>
+class GIM_BOX_TREE_SET : public GIM_BOX_TREE_TEMPLATE_SET<_GIM_PRIMITIVE_MANAGER_PROTOTYPE, GIM_BOX_TREE>
{
public:
-
};
-
-
-
-
/// GIM_BOX_SET collision methods
-template<typename BOX_SET_CLASS0,typename BOX_SET_CLASS1>
+template <typename BOX_SET_CLASS0, typename BOX_SET_CLASS1>
class GIM_TREE_TREE_COLLIDER
{
public:
- gim_pair_set * m_collision_pairs;
- BOX_SET_CLASS0 * m_boxset0;
- BOX_SET_CLASS1 * m_boxset1;
+ gim_pair_set* m_collision_pairs;
+ BOX_SET_CLASS0* m_boxset0;
+ BOX_SET_CLASS1* m_boxset1;
GUINT current_node0;
GUINT current_node1;
bool node0_is_leaf;
@@ -483,18 +474,18 @@ public:
GIM_TRIANGLE m_tri1;
btVector4 m_tri1_plane;
-
public:
GIM_TREE_TREE_COLLIDER()
{
current_node0 = G_UINT_INFINITY;
current_node1 = G_UINT_INFINITY;
}
+
protected:
SIMD_FORCE_INLINE void retrieve_node0_triangle(GUINT node0)
{
- if(node0_has_triangle) return;
- m_boxset0->getNodeTriangle(node0,m_tri0);
+ if (node0_has_triangle) return;
+ m_boxset0->getNodeTriangle(node0, m_tri0);
//transform triangle
m_tri0.m_vertices[0] = trans_cache_0to1(m_tri0.m_vertices[0]);
m_tri0.m_vertices[1] = trans_cache_0to1(m_tri0.m_vertices[1]);
@@ -506,8 +497,8 @@ protected:
SIMD_FORCE_INLINE void retrieve_node1_triangle(GUINT node1)
{
- if(node1_has_triangle) return;
- m_boxset1->getNodeTriangle(node1,m_tri1);
+ if (node1_has_triangle) return;
+ m_boxset1->getNodeTriangle(node1, m_tri1);
//transform triangle
m_tri1.m_vertices[0] = trans_cache_1to0.transform(m_tri1.m_vertices[0]);
m_tri1.m_vertices[1] = trans_cache_1to0.transform(m_tri1.m_vertices[1]);
@@ -519,8 +510,8 @@ protected:
SIMD_FORCE_INLINE void retrieve_node0_info(GUINT node0)
{
- if(node0 == current_node0) return;
- m_boxset0->getNodeBound(node0,m_box0);
+ if (node0 == current_node0) return;
+ m_boxset0->getNodeBound(node0, m_box0);
node0_is_leaf = m_boxset0->isLeafNode(node0);
node0_has_triangle = false;
current_node0 = node0;
@@ -528,21 +519,21 @@ protected:
SIMD_FORCE_INLINE void retrieve_node1_info(GUINT node1)
{
- if(node1 == current_node1) return;
- m_boxset1->getNodeBound(node1,m_box1);
+ if (node1 == current_node1) return;
+ m_boxset1->getNodeBound(node1, m_box1);
node1_is_leaf = m_boxset1->isLeafNode(node1);
node1_has_triangle = false;
current_node1 = node1;
}
- SIMD_FORCE_INLINE bool node_collision(GUINT node0 ,GUINT node1)
+ SIMD_FORCE_INLINE bool node_collision(GUINT node0, GUINT node1)
{
retrieve_node0_info(node0);
retrieve_node1_info(node1);
- bool result = m_box0.overlapping_trans_cache(m_box1,trans_cache_1to0,true);
- if(!result) return false;
+ bool result = m_box0.overlapping_trans_cache(m_box1, trans_cache_1to0, true);
+ if (!result) return false;
- if(t0_is_trimesh && node0_is_leaf)
+ if (t0_is_trimesh && node0_is_leaf)
{
//perform primitive vs box collision
retrieve_node0_triangle(node0);
@@ -550,14 +541,14 @@ protected:
m_box1.increment_margin(m_tri0.m_margin);
result = m_box1.collide_triangle_exact(
- m_tri0.m_vertices[0],m_tri0.m_vertices[1],m_tri0.m_vertices[2],m_tri0_plane);
+ m_tri0.m_vertices[0], m_tri0.m_vertices[1], m_tri0.m_vertices[2], m_tri0_plane);
m_box1.increment_margin(-m_tri0.m_margin);
- if(!result) return false;
+ if (!result) return false;
return true;
}
- else if(t1_is_trimesh && node1_is_leaf)
+ else if (t1_is_trimesh && node1_is_leaf)
{
//perform primitive vs box collision
retrieve_node1_triangle(node1);
@@ -565,11 +556,11 @@ protected:
m_box0.increment_margin(m_tri1.m_margin);
result = m_box0.collide_triangle_exact(
- m_tri1.m_vertices[0],m_tri1.m_vertices[1],m_tri1.m_vertices[2],m_tri1_plane);
+ m_tri1.m_vertices[0], m_tri1.m_vertices[1], m_tri1.m_vertices[2], m_tri1_plane);
m_box0.increment_margin(-m_tri1.m_margin);
- if(!result) return false;
+ if (!result) return false;
return true;
}
return true;
@@ -582,40 +573,39 @@ protected:
stack_collisions.reserve(32);
//add the first pair
- stack_collisions.push_pair(0,0);
+ stack_collisions.push_pair(0, 0);
-
- while(stack_collisions.size())
+ while (stack_collisions.size())
{
//retrieve the last pair and pop
GUINT node0 = stack_collisions.back().m_index1;
GUINT node1 = stack_collisions.back().m_index2;
stack_collisions.pop_back();
- if(node_collision(node0,node1)) // a collision is found
+ if (node_collision(node0, node1)) // a collision is found
{
- if(node0_is_leaf)
+ if (node0_is_leaf)
{
- if(node1_is_leaf)
+ if (node1_is_leaf)
{
- m_collision_pairs->push_pair(m_boxset0->getNodeData(node0),m_boxset1->getNodeData(node1));
+ m_collision_pairs->push_pair(m_boxset0->getNodeData(node0), m_boxset1->getNodeData(node1));
}
else
{
//collide left
- stack_collisions.push_pair(node0,m_boxset1->getLeftNodeIndex(node1));
+ stack_collisions.push_pair(node0, m_boxset1->getLeftNodeIndex(node1));
//collide right
- stack_collisions.push_pair(node0,m_boxset1->getRightNodeIndex(node1));
+ stack_collisions.push_pair(node0, m_boxset1->getRightNodeIndex(node1));
}
}
else
{
- if(node1_is_leaf)
+ if (node1_is_leaf)
{
//collide left
- stack_collisions.push_pair(m_boxset0->getLeftNodeIndex(node0),node1);
+ stack_collisions.push_pair(m_boxset0->getLeftNodeIndex(node0), node1);
//collide right
- stack_collisions.push_pair(m_boxset0->getRightNodeIndex(node0),node1);
+ stack_collisions.push_pair(m_boxset0->getRightNodeIndex(node0), node1);
}
else
{
@@ -624,36 +614,36 @@ protected:
GUINT left1 = m_boxset1->getLeftNodeIndex(node1);
GUINT right1 = m_boxset1->getRightNodeIndex(node1);
//collide left
- stack_collisions.push_pair(left0,left1);
+ stack_collisions.push_pair(left0, left1);
//collide right
- stack_collisions.push_pair(left0,right1);
+ stack_collisions.push_pair(left0, right1);
//collide left
- stack_collisions.push_pair(right0,left1);
+ stack_collisions.push_pair(right0, left1);
//collide right
- stack_collisions.push_pair(right0,right1);
+ stack_collisions.push_pair(right0, right1);
- }// else if node1 is not a leaf
- }// else if node0 is not a leaf
+ } // else if node1 is not a leaf
+ } // else if node0 is not a leaf
- }// if(node_collision(node0,node1))
- }//while(stack_collisions.size())
+ } // if(node_collision(node0,node1))
+ } //while(stack_collisions.size())
}
+
public:
- void find_collision(BOX_SET_CLASS0 * boxset1, const btTransform & trans1,
- BOX_SET_CLASS1 * boxset2, const btTransform & trans2,
- gim_pair_set & collision_pairs, bool complete_primitive_tests = true)
+ void find_collision(BOX_SET_CLASS0* boxset1, const btTransform& trans1,
+ BOX_SET_CLASS1* boxset2, const btTransform& trans2,
+ gim_pair_set& collision_pairs, bool complete_primitive_tests = true)
{
m_collision_pairs = &collision_pairs;
m_boxset0 = boxset1;
m_boxset1 = boxset2;
- trans_cache_1to0.calc_from_homogenic(trans1,trans2);
+ trans_cache_1to0.calc_from_homogenic(trans1, trans2);
- trans_cache_0to1 = trans2.inverse();
+ trans_cache_0to1 = trans2.inverse();
trans_cache_0to1 *= trans1;
-
- if(complete_primitive_tests)
+ if (complete_primitive_tests)
{
t0_is_trimesh = boxset1->getPrimitiveManager().is_trimesh();
t1_is_trimesh = boxset2->getPrimitiveManager().is_trimesh();
@@ -668,7 +658,4 @@ public:
}
};
-
-#endif // GIM_BOXPRUNING_H_INCLUDED
-
-
+#endif // GIM_BOXPRUNING_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_clip_polygon.h b/thirdparty/bullet/BulletCollision/Gimpact/gim_clip_polygon.h
index e342459ce5..57b9c5c91a 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_clip_polygon.h
+++ b/thirdparty/bullet/BulletCollision/Gimpact/gim_clip_polygon.h
@@ -33,91 +33,86 @@ email: projectileman@yahoo.com
-----------------------------------------------------------------------------
*/
-
//! This function calcs the distance from a 3D plane
class DISTANCE_PLANE_3D_FUNC
{
public:
- template<typename CLASS_POINT,typename CLASS_PLANE>
- inline GREAL operator()(const CLASS_PLANE & plane, const CLASS_POINT & point)
+ template <typename CLASS_POINT, typename CLASS_PLANE>
+ inline GREAL operator()(const CLASS_PLANE& plane, const CLASS_POINT& point)
{
return DISTANCE_PLANE_POINT(plane, point);
}
};
-
-
-template<typename CLASS_POINT>
+template <typename CLASS_POINT>
SIMD_FORCE_INLINE void PLANE_CLIP_POLYGON_COLLECT(
- const CLASS_POINT & point0,
- const CLASS_POINT & point1,
- GREAL dist0,
- GREAL dist1,
- CLASS_POINT * clipped,
- GUINT & clipped_count)
+ const CLASS_POINT& point0,
+ const CLASS_POINT& point1,
+ GREAL dist0,
+ GREAL dist1,
+ CLASS_POINT* clipped,
+ GUINT& clipped_count)
{
- GUINT _prevclassif = (dist0>G_EPSILON);
- GUINT _classif = (dist1>G_EPSILON);
- if(_classif!=_prevclassif)
+ GUINT _prevclassif = (dist0 > G_EPSILON);
+ GUINT _classif = (dist1 > G_EPSILON);
+ if (_classif != _prevclassif)
{
- GREAL blendfactor = -dist0/(dist1-dist0);
- VEC_BLEND(clipped[clipped_count],point0,point1,blendfactor);
+ GREAL blendfactor = -dist0 / (dist1 - dist0);
+ VEC_BLEND(clipped[clipped_count], point0, point1, blendfactor);
clipped_count++;
}
- if(!_classif)
+ if (!_classif)
{
- VEC_COPY(clipped[clipped_count],point1);
+ VEC_COPY(clipped[clipped_count], point1);
clipped_count++;
}
}
-
//! Clips a polygon by a plane
/*!
*\return The count of the clipped counts
*/
-template<typename CLASS_POINT,typename CLASS_PLANE, typename DISTANCE_PLANE_FUNC>
+template <typename CLASS_POINT, typename CLASS_PLANE, typename DISTANCE_PLANE_FUNC>
SIMD_FORCE_INLINE GUINT PLANE_CLIP_POLYGON_GENERIC(
- const CLASS_PLANE & plane,
- const CLASS_POINT * polygon_points,
- GUINT polygon_point_count,
- CLASS_POINT * clipped,DISTANCE_PLANE_FUNC distance_func)
+ const CLASS_PLANE& plane,
+ const CLASS_POINT* polygon_points,
+ GUINT polygon_point_count,
+ CLASS_POINT* clipped, DISTANCE_PLANE_FUNC distance_func)
{
- GUINT clipped_count = 0;
+ GUINT clipped_count = 0;
-
- //clip first point
- GREAL firstdist = distance_func(plane,polygon_points[0]);;
- if(!(firstdist>G_EPSILON))
+ //clip first point
+ GREAL firstdist = distance_func(plane, polygon_points[0]);
+ ;
+ if (!(firstdist > G_EPSILON))
{
- VEC_COPY(clipped[clipped_count],polygon_points[0]);
+ VEC_COPY(clipped[clipped_count], polygon_points[0]);
clipped_count++;
}
GREAL olddist = firstdist;
- for(GUINT _i=1;_i<polygon_point_count;_i++)
- {
- GREAL dist = distance_func(plane,polygon_points[_i]);
+ for (GUINT _i = 1; _i < polygon_point_count; _i++)
+ {
+ GREAL dist = distance_func(plane, polygon_points[_i]);
PLANE_CLIP_POLYGON_COLLECT(
- polygon_points[_i-1],polygon_points[_i],
- olddist,
- dist,
- clipped,
- clipped_count);
+ polygon_points[_i - 1], polygon_points[_i],
+ olddist,
+ dist,
+ clipped,
+ clipped_count);
-
- olddist = dist;
+ olddist = dist;
}
- //RETURN TO FIRST point
+ //RETURN TO FIRST point
PLANE_CLIP_POLYGON_COLLECT(
- polygon_points[polygon_point_count-1],polygon_points[0],
- olddist,
- firstdist,
- clipped,
- clipped_count);
+ polygon_points[polygon_point_count - 1], polygon_points[0],
+ olddist,
+ firstdist,
+ clipped,
+ clipped_count);
return clipped_count;
}
@@ -126,85 +121,79 @@ SIMD_FORCE_INLINE GUINT PLANE_CLIP_POLYGON_GENERIC(
/*!
*\return The count of the clipped counts
*/
-template<typename CLASS_POINT,typename CLASS_PLANE, typename DISTANCE_PLANE_FUNC>
+template <typename CLASS_POINT, typename CLASS_PLANE, typename DISTANCE_PLANE_FUNC>
SIMD_FORCE_INLINE GUINT PLANE_CLIP_TRIANGLE_GENERIC(
- const CLASS_PLANE & plane,
- const CLASS_POINT & point0,
- const CLASS_POINT & point1,
- const CLASS_POINT & point2,
- CLASS_POINT * clipped,DISTANCE_PLANE_FUNC distance_func)
+ const CLASS_PLANE& plane,
+ const CLASS_POINT& point0,
+ const CLASS_POINT& point1,
+ const CLASS_POINT& point2,
+ CLASS_POINT* clipped, DISTANCE_PLANE_FUNC distance_func)
{
- GUINT clipped_count = 0;
+ GUINT clipped_count = 0;
- //clip first point
- GREAL firstdist = distance_func(plane,point0);;
- if(!(firstdist>G_EPSILON))
+ //clip first point
+ GREAL firstdist = distance_func(plane, point0);
+ ;
+ if (!(firstdist > G_EPSILON))
{
- VEC_COPY(clipped[clipped_count],point0);
+ VEC_COPY(clipped[clipped_count], point0);
clipped_count++;
}
// point 1
GREAL olddist = firstdist;
- GREAL dist = distance_func(plane,point1);
+ GREAL dist = distance_func(plane, point1);
PLANE_CLIP_POLYGON_COLLECT(
- point0,point1,
- olddist,
- dist,
- clipped,
- clipped_count);
+ point0, point1,
+ olddist,
+ dist,
+ clipped,
+ clipped_count);
olddist = dist;
-
// point 2
- dist = distance_func(plane,point2);
+ dist = distance_func(plane, point2);
PLANE_CLIP_POLYGON_COLLECT(
- point1,point2,
- olddist,
- dist,
- clipped,
- clipped_count);
+ point1, point2,
+ olddist,
+ dist,
+ clipped,
+ clipped_count);
olddist = dist;
-
-
//RETURN TO FIRST point
PLANE_CLIP_POLYGON_COLLECT(
- point2,point0,
- olddist,
- firstdist,
- clipped,
- clipped_count);
+ point2, point0,
+ olddist,
+ firstdist,
+ clipped,
+ clipped_count);
return clipped_count;
}
-
-template<typename CLASS_POINT,typename CLASS_PLANE>
+template <typename CLASS_POINT, typename CLASS_PLANE>
SIMD_FORCE_INLINE GUINT PLANE_CLIP_POLYGON3D(
- const CLASS_PLANE & plane,
- const CLASS_POINT * polygon_points,
- GUINT polygon_point_count,
- CLASS_POINT * clipped)
+ const CLASS_PLANE& plane,
+ const CLASS_POINT* polygon_points,
+ GUINT polygon_point_count,
+ CLASS_POINT* clipped)
{
- return PLANE_CLIP_POLYGON_GENERIC<CLASS_POINT,CLASS_PLANE>(plane,polygon_points,polygon_point_count,clipped,DISTANCE_PLANE_3D_FUNC());
+ return PLANE_CLIP_POLYGON_GENERIC<CLASS_POINT, CLASS_PLANE>(plane, polygon_points, polygon_point_count, clipped, DISTANCE_PLANE_3D_FUNC());
}
-
-template<typename CLASS_POINT,typename CLASS_PLANE>
+template <typename CLASS_POINT, typename CLASS_PLANE>
SIMD_FORCE_INLINE GUINT PLANE_CLIP_TRIANGLE3D(
- const CLASS_PLANE & plane,
- const CLASS_POINT & point0,
- const CLASS_POINT & point1,
- const CLASS_POINT & point2,
- CLASS_POINT * clipped)
+ const CLASS_PLANE& plane,
+ const CLASS_POINT& point0,
+ const CLASS_POINT& point1,
+ const CLASS_POINT& point2,
+ CLASS_POINT* clipped)
{
- return PLANE_CLIP_TRIANGLE_GENERIC<CLASS_POINT,CLASS_PLANE>(plane,point0,point1,point2,clipped,DISTANCE_PLANE_3D_FUNC());
+ return PLANE_CLIP_TRIANGLE_GENERIC<CLASS_POINT, CLASS_PLANE>(plane, point0, point1, point2, clipped, DISTANCE_PLANE_3D_FUNC());
}
-
-
-#endif // GIM_TRI_COLLISION_H_INCLUDED
+#endif // GIM_TRI_COLLISION_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_contact.cpp b/thirdparty/bullet/BulletCollision/Gimpact/gim_contact.cpp
index 20e41de089..390225709e 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_contact.cpp
+++ b/thirdparty/bullet/BulletCollision/Gimpact/gim_contact.cpp
@@ -33,91 +33,89 @@ email: projectileman@yahoo.com
#define MAX_COINCIDENT 8
void gim_contact_array::merge_contacts(
- const gim_contact_array & contacts, bool normal_contact_average)
+ const gim_contact_array& contacts, bool normal_contact_average)
{
clear();
- if(contacts.size()==1)
+ if (contacts.size() == 1)
{
push_back(contacts.back());
return;
}
gim_array<GIM_RSORT_TOKEN> keycontacts(contacts.size());
- keycontacts.resize(contacts.size(),false);
+ keycontacts.resize(contacts.size(), false);
//fill key contacts
GUINT i;
- for (i = 0;i<contacts.size() ;i++ )
+ for (i = 0; i < contacts.size(); i++)
{
keycontacts[i].m_key = contacts[i].calc_key_contact();
keycontacts[i].m_value = i;
}
//sort keys
- gim_heap_sort(keycontacts.pointer(),keycontacts.size(),GIM_RSORT_TOKEN_COMPARATOR());
+ gim_heap_sort(keycontacts.pointer(), keycontacts.size(), GIM_RSORT_TOKEN_COMPARATOR());
// Merge contacts
- GUINT coincident_count=0;
+ GUINT coincident_count = 0;
btVector3 coincident_normals[MAX_COINCIDENT];
GUINT last_key = keycontacts[0].m_key;
GUINT key = 0;
push_back(contacts[keycontacts[0].m_value]);
- GIM_CONTACT * pcontact = &back();
+ GIM_CONTACT* pcontact = &back();
-
-
- for( i=1;i<keycontacts.size();i++)
+ for (i = 1; i < keycontacts.size(); i++)
{
- key = keycontacts[i].m_key;
- const GIM_CONTACT * scontact = &contacts[keycontacts[i].m_value];
+ key = keycontacts[i].m_key;
+ const GIM_CONTACT* scontact = &contacts[keycontacts[i].m_value];
- if(last_key == key)//same points
+ if (last_key == key) //same points
{
//merge contact
- if(pcontact->m_depth - CONTACT_DIFF_EPSILON > scontact->m_depth)//)
+ if (pcontact->m_depth - CONTACT_DIFF_EPSILON > scontact->m_depth) //)
{
*pcontact = *scontact;
- coincident_count = 0;
+ coincident_count = 0;
}
- else if(normal_contact_average)
+ else if (normal_contact_average)
{
- if(btFabs(pcontact->m_depth - scontact->m_depth)<CONTACT_DIFF_EPSILON)
- {
- if(coincident_count<MAX_COINCIDENT)
- {
- coincident_normals[coincident_count] = scontact->m_normal;
- coincident_count++;
- }
- }
+ if (btFabs(pcontact->m_depth - scontact->m_depth) < CONTACT_DIFF_EPSILON)
+ {
+ if (coincident_count < MAX_COINCIDENT)
+ {
+ coincident_normals[coincident_count] = scontact->m_normal;
+ coincident_count++;
+ }
+ }
}
}
else
- {//add new contact
+ { //add new contact
- if(normal_contact_average && coincident_count>0)
- {
- pcontact->interpolate_normals(coincident_normals,coincident_count);
- coincident_count = 0;
- }
+ if (normal_contact_average && coincident_count > 0)
+ {
+ pcontact->interpolate_normals(coincident_normals, coincident_count);
+ coincident_count = 0;
+ }
- push_back(*scontact);
- pcontact = &back();
- }
+ push_back(*scontact);
+ pcontact = &back();
+ }
last_key = key;
}
}
-void gim_contact_array::merge_contacts_unique(const gim_contact_array & contacts)
+void gim_contact_array::merge_contacts_unique(const gim_contact_array& contacts)
{
clear();
- if(contacts.size()==1)
+ if (contacts.size() == 1)
{
push_back(contacts.back());
return;
@@ -125,14 +123,14 @@ void gim_contact_array::merge_contacts_unique(const gim_contact_array & contacts
GIM_CONTACT average_contact = contacts.back();
- for (GUINT i=1;i<contacts.size() ;i++ )
+ for (GUINT i = 1; i < contacts.size(); i++)
{
average_contact.m_point += contacts[i].m_point;
average_contact.m_normal += contacts[i].m_normal * contacts[i].m_depth;
}
//divide
- GREAL divide_average = 1.0f/((GREAL)contacts.size());
+ GREAL divide_average = 1.0f / ((GREAL)contacts.size());
average_contact.m_point *= divide_average;
@@ -141,6 +139,4 @@ void gim_contact_array::merge_contacts_unique(const gim_contact_array & contacts
average_contact.m_depth = average_contact.m_normal.length();
average_contact.m_normal /= average_contact.m_depth;
-
}
-
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_contact.h b/thirdparty/bullet/BulletCollision/Gimpact/gim_contact.h
index b41c714b5f..9deb28a26e 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_contact.h
+++ b/thirdparty/bullet/BulletCollision/Gimpact/gim_contact.h
@@ -36,7 +36,6 @@ email: projectileman@yahoo.com
#include "gim_radixsort.h"
#include "gim_array.h"
-
/**
Configuration var for applying interpolation of contact normals
*/
@@ -58,90 +57,87 @@ Configuration var for applying interpolation of contact normals
class GIM_CONTACT
{
public:
- btVector3 m_point;
- btVector3 m_normal;
- GREAL m_depth;//Positive value indicates interpenetration
- GREAL m_distance;//Padding not for use
- GUINT m_feature1;//Face number
- GUINT m_feature2;//Face number
+ btVector3 m_point;
+ btVector3 m_normal;
+ GREAL m_depth; //Positive value indicates interpenetration
+ GREAL m_distance; //Padding not for use
+ GUINT m_feature1; //Face number
+ GUINT m_feature2; //Face number
public:
- GIM_CONTACT()
- {
- }
-
- GIM_CONTACT(const GIM_CONTACT & contact):
- m_point(contact.m_point),
- m_normal(contact.m_normal),
- m_depth(contact.m_depth),
- m_feature1(contact.m_feature1),
- m_feature2(contact.m_feature2)
- {
- m_point = contact.m_point;
- m_normal = contact.m_normal;
- m_depth = contact.m_depth;
- m_feature1 = contact.m_feature1;
- m_feature2 = contact.m_feature2;
- }
-
- GIM_CONTACT(const btVector3 &point,const btVector3 & normal,
- GREAL depth, GUINT feature1, GUINT feature2):
- m_point(point),
- m_normal(normal),
- m_depth(depth),
- m_feature1(feature1),
- m_feature2(feature2)
- {
- }
+ GIM_CONTACT()
+ {
+ }
+
+ GIM_CONTACT(const GIM_CONTACT &contact) : m_point(contact.m_point),
+ m_normal(contact.m_normal),
+ m_depth(contact.m_depth),
+ m_feature1(contact.m_feature1),
+ m_feature2(contact.m_feature2)
+ {
+ m_point = contact.m_point;
+ m_normal = contact.m_normal;
+ m_depth = contact.m_depth;
+ m_feature1 = contact.m_feature1;
+ m_feature2 = contact.m_feature2;
+ }
+
+ GIM_CONTACT(const btVector3 &point, const btVector3 &normal,
+ GREAL depth, GUINT feature1, GUINT feature2) : m_point(point),
+ m_normal(normal),
+ m_depth(depth),
+ m_feature1(feature1),
+ m_feature2(feature2)
+ {
+ }
//! Calcs key for coord classification
- SIMD_FORCE_INLINE GUINT calc_key_contact() const
- {
- GINT _coords[] = {
- (GINT)(m_point[0]*1000.0f+1.0f),
- (GINT)(m_point[1]*1333.0f),
- (GINT)(m_point[2]*2133.0f+3.0f)};
- GUINT _hash=0;
+ SIMD_FORCE_INLINE GUINT calc_key_contact() const
+ {
+ GINT _coords[] = {
+ (GINT)(m_point[0] * 1000.0f + 1.0f),
+ (GINT)(m_point[1] * 1333.0f),
+ (GINT)(m_point[2] * 2133.0f + 3.0f)};
+ GUINT _hash = 0;
GUINT *_uitmp = (GUINT *)(&_coords[0]);
_hash = *_uitmp;
_uitmp++;
- _hash += (*_uitmp)<<4;
+ _hash += (*_uitmp) << 4;
_uitmp++;
- _hash += (*_uitmp)<<8;
+ _hash += (*_uitmp) << 8;
return _hash;
- }
+ }
- SIMD_FORCE_INLINE void interpolate_normals( btVector3 * normals,GUINT normal_count)
- {
- btVector3 vec_sum(m_normal);
- for(GUINT i=0;i<normal_count;i++)
+ SIMD_FORCE_INLINE void interpolate_normals(btVector3 *normals, GUINT normal_count)
+ {
+ btVector3 vec_sum(m_normal);
+ for (GUINT i = 0; i < normal_count; i++)
{
vec_sum += normals[i];
}
GREAL vec_sum_len = vec_sum.length2();
- if(vec_sum_len <CONTACT_DIFF_EPSILON) return;
-
- GIM_INV_SQRT(vec_sum_len,vec_sum_len); // 1/sqrt(vec_sum_len)
+ if (vec_sum_len < CONTACT_DIFF_EPSILON) return;
- m_normal = vec_sum*vec_sum_len;
- }
+ GIM_INV_SQRT(vec_sum_len, vec_sum_len); // 1/sqrt(vec_sum_len)
+ m_normal = vec_sum * vec_sum_len;
+ }
};
#endif
-class gim_contact_array:public gim_array<GIM_CONTACT>
+class gim_contact_array : public gim_array<GIM_CONTACT>
{
public:
- gim_contact_array():gim_array<GIM_CONTACT>(64)
+ gim_contact_array() : gim_array<GIM_CONTACT>(64)
{
}
- SIMD_FORCE_INLINE void push_contact(const btVector3 &point,const btVector3 & normal,
- GREAL depth, GUINT feature1, GUINT feature2)
+ SIMD_FORCE_INLINE void push_contact(const btVector3 &point, const btVector3 &normal,
+ GREAL depth, GUINT feature1, GUINT feature2)
{
push_back_mem();
- GIM_CONTACT & newele = back();
+ GIM_CONTACT &newele = back();
newele.m_point = point;
newele.m_normal = normal;
newele.m_depth = depth;
@@ -150,13 +146,13 @@ public:
}
SIMD_FORCE_INLINE void push_triangle_contacts(
- const GIM_TRIANGLE_CONTACT_DATA & tricontact,
- GUINT feature1,GUINT feature2)
+ const GIM_TRIANGLE_CONTACT_DATA &tricontact,
+ GUINT feature1, GUINT feature2)
{
- for(GUINT i = 0;i<tricontact.m_point_count ;i++ )
+ for (GUINT i = 0; i < tricontact.m_point_count; i++)
{
push_back_mem();
- GIM_CONTACT & newele = back();
+ GIM_CONTACT &newele = back();
newele.m_point = tricontact.m_points[i];
newele.m_normal = tricontact.m_separating_normal;
newele.m_depth = tricontact.m_penetration_depth;
@@ -165,8 +161,8 @@ public:
}
}
- void merge_contacts(const gim_contact_array & contacts, bool normal_contact_average = true);
- void merge_contacts_unique(const gim_contact_array & contacts);
+ void merge_contacts(const gim_contact_array &contacts, bool normal_contact_average = true);
+ void merge_contacts_unique(const gim_contact_array &contacts);
};
-#endif // GIM_CONTACT_H_INCLUDED
+#endif // GIM_CONTACT_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_geom_types.h b/thirdparty/bullet/BulletCollision/Gimpact/gim_geom_types.h
index 6b8f9ea6c2..9dc48f354b 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_geom_types.h
+++ b/thirdparty/bullet/BulletCollision/Gimpact/gim_geom_types.h
@@ -33,11 +33,8 @@ email: projectileman@yahoo.com
-----------------------------------------------------------------------------
*/
-
#include "gim_math.h"
-
-
//! Short Integer vector 2D
typedef GSHORT vec2s[2];
//! Integer vector 3D
@@ -92,6 +89,4 @@ typedef GREAL quatf[4];
//typedef struct _aabb3f aabb3f;
-
-
-#endif // GIM_GEOM_TYPES_H_INCLUDED
+#endif // GIM_GEOM_TYPES_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_geometry.h b/thirdparty/bullet/BulletCollision/Gimpact/gim_geometry.h
index c67a6991c0..4a7ac3c4d8 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_geometry.h
+++ b/thirdparty/bullet/BulletCollision/Gimpact/gim_geometry.h
@@ -39,4 +39,4 @@ email: projectileman@yahoo.com
#include "gim_box_collision.h"
#include "gim_tri_collision.h"
-#endif // GIM_VECTOR_H_INCLUDED
+#endif // GIM_VECTOR_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_hash_table.h b/thirdparty/bullet/BulletCollision/Gimpact/gim_hash_table.h
index e4237c2c57..abf88d3108 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_hash_table.h
+++ b/thirdparty/bullet/BulletCollision/Gimpact/gim_hash_table.h
@@ -34,53 +34,52 @@ email: projectileman@yahoo.com
#include "gim_radixsort.h"
-
-#define GIM_INVALID_HASH 0xffffffff //!< A very very high value
+#define GIM_INVALID_HASH 0xffffffff //!< A very very high value
#define GIM_DEFAULT_HASH_TABLE_SIZE 380
#define GIM_DEFAULT_HASH_TABLE_NODE_SIZE 4
#define GIM_HASH_TABLE_GROW_FACTOR 2
-#define GIM_MIN_RADIX_SORT_SIZE 860 //!< calibrated on a PIII
+#define GIM_MIN_RADIX_SORT_SIZE 860 //!< calibrated on a PIII
-template<typename T>
+template <typename T>
struct GIM_HASH_TABLE_NODE
{
- GUINT m_key;
- T m_data;
- GIM_HASH_TABLE_NODE()
- {
- }
-
- GIM_HASH_TABLE_NODE(const GIM_HASH_TABLE_NODE & value)
- {
- m_key = value.m_key;
- m_data = value.m_data;
- }
-
- GIM_HASH_TABLE_NODE(GUINT key, const T & data)
- {
- m_key = key;
- m_data = data;
- }
-
- bool operator <(const GIM_HASH_TABLE_NODE<T> & other) const
+ GUINT m_key;
+ T m_data;
+ GIM_HASH_TABLE_NODE()
+ {
+ }
+
+ GIM_HASH_TABLE_NODE(const GIM_HASH_TABLE_NODE& value)
+ {
+ m_key = value.m_key;
+ m_data = value.m_data;
+ }
+
+ GIM_HASH_TABLE_NODE(GUINT key, const T& data)
+ {
+ m_key = key;
+ m_data = data;
+ }
+
+ bool operator<(const GIM_HASH_TABLE_NODE<T>& other) const
{
///inverse order, further objects are first
- if(m_key < other.m_key) return true;
+ if (m_key < other.m_key) return true;
return false;
}
- bool operator >(const GIM_HASH_TABLE_NODE<T> & other) const
+ bool operator>(const GIM_HASH_TABLE_NODE<T>& other) const
{
///inverse order, further objects are first
- if(m_key > other.m_key) return true;
+ if (m_key > other.m_key) return true;
return false;
}
- bool operator ==(const GIM_HASH_TABLE_NODE<T> & other) const
+ bool operator==(const GIM_HASH_TABLE_NODE<T>& other) const
{
///inverse order, further objects are first
- if(m_key == other.m_key) return true;
+ if (m_key == other.m_key) return true;
return false;
}
};
@@ -89,21 +88,19 @@ struct GIM_HASH_TABLE_NODE
class GIM_HASH_NODE_GET_KEY
{
public:
- template<class T>
- inline GUINT operator()( const T& a)
+ template <class T>
+ inline GUINT operator()(const T& a)
{
return a.m_key;
}
};
-
-
///Macro for comparing the key and the element
class GIM_HASH_NODE_CMP_KEY_MACRO
{
public:
- template<class T>
- inline int operator() ( const T& a, GUINT key)
+ template <class T>
+ inline int operator()(const T& a, GUINT key)
{
return ((int)(a.m_key - key));
}
@@ -113,65 +110,53 @@ public:
class GIM_HASH_NODE_CMP_MACRO
{
public:
- template<class T>
- inline int operator() ( const T& a, const T& b )
+ template <class T>
+ inline int operator()(const T& a, const T& b)
{
return ((int)(a.m_key - b.m_key));
}
};
-
-
-
-
//! Sorting for hash table
/*!
switch automatically between quicksort and radixsort
*/
-template<typename T>
-void gim_sort_hash_node_array(T * array, GUINT array_count)
+template <typename T>
+void gim_sort_hash_node_array(T* array, GUINT array_count)
{
- if(array_count<GIM_MIN_RADIX_SORT_SIZE)
- {
- gim_heap_sort(array,array_count,GIM_HASH_NODE_CMP_MACRO());
- }
- else
- {
- memcopy_elements_func cmpfunc;
- gim_radix_sort(array,array_count,GIM_HASH_NODE_GET_KEY(),cmpfunc);
- }
+ if (array_count < GIM_MIN_RADIX_SORT_SIZE)
+ {
+ gim_heap_sort(array, array_count, GIM_HASH_NODE_CMP_MACRO());
+ }
+ else
+ {
+ memcopy_elements_func cmpfunc;
+ gim_radix_sort(array, array_count, GIM_HASH_NODE_GET_KEY(), cmpfunc);
+ }
}
-
-
-
-
-
// Note: assumes long is at least 32 bits.
#define GIM_NUM_PRIME 28
static const GUINT gim_prime_list[GIM_NUM_PRIME] =
-{
- 53ul, 97ul, 193ul, 389ul, 769ul,
- 1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
- 49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
- 1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
- 50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
- 1610612741ul, 3221225473ul, 4294967291ul
-};
+ {
+ 53ul, 97ul, 193ul, 389ul, 769ul,
+ 1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
+ 49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
+ 1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
+ 50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
+ 1610612741ul, 3221225473ul, 4294967291ul};
inline GUINT gim_next_prime(GUINT number)
{
- //Find nearest upper prime
- GUINT result_ind = 0;
- gim_binary_search(gim_prime_list,0,(GIM_NUM_PRIME-2),number,result_ind);
+ //Find nearest upper prime
+ GUINT result_ind = 0;
+ gim_binary_search(gim_prime_list, 0, (GIM_NUM_PRIME - 2), number, result_ind);
- // inv: result_ind < 28
- return gim_prime_list[result_ind];
+ // inv: result_ind < 28
+ return gim_prime_list[result_ind];
}
-
-
//! A compact hash table implementation
/*!
A memory aligned compact hash table that coud be treated as an array.
@@ -187,129 +172,124 @@ When the array size reaches the size equivalent to 'min_hash_table_size', then i
</ul>
*/
-template<class T>
+template <class T>
class gim_hash_table
{
protected:
- typedef GIM_HASH_TABLE_NODE<T> _node_type;
-
- //!The nodes
- //array< _node_type, SuperAllocator<_node_type> > m_nodes;
- gim_array< _node_type > m_nodes;
- //SuperBufferedArray< _node_type > m_nodes;
- bool m_sorted;
-
- ///Hash table data management. The hash table has the indices to the corresponding m_nodes array
- GUINT * m_hash_table;//!<
- GUINT m_table_size;//!<
- GUINT m_node_size;//!<
- GUINT m_min_hash_table_size;
-
-
-
- //! Returns the cell index
- inline GUINT _find_cell(GUINT hashkey)
- {
- _node_type * nodesptr = m_nodes.pointer();
- GUINT start_index = (hashkey%m_table_size)*m_node_size;
- GUINT end_index = start_index + m_node_size;
-
- while(start_index<end_index)
- {
- GUINT value = m_hash_table[start_index];
- if(value != GIM_INVALID_HASH)
- {
- if(nodesptr[value].m_key == hashkey) return start_index;
- }
- start_index++;
- }
- return GIM_INVALID_HASH;
- }
-
- //! Find the avaliable cell for the hashkey, and return an existing cell if it has the same hash key
- inline GUINT _find_avaliable_cell(GUINT hashkey)
- {
- _node_type * nodesptr = m_nodes.pointer();
- GUINT avaliable_index = GIM_INVALID_HASH;
- GUINT start_index = (hashkey%m_table_size)*m_node_size;
- GUINT end_index = start_index + m_node_size;
-
- while(start_index<end_index)
- {
- GUINT value = m_hash_table[start_index];
- if(value == GIM_INVALID_HASH)
- {
- if(avaliable_index==GIM_INVALID_HASH)
- {
- avaliable_index = start_index;
- }
- }
- else if(nodesptr[value].m_key == hashkey)
- {
- return start_index;
- }
- start_index++;
- }
- return avaliable_index;
- }
-
-
-
- //! reserves the memory for the hash table.
- /*!
+ typedef GIM_HASH_TABLE_NODE<T> _node_type;
+
+ //!The nodes
+ //array< _node_type, SuperAllocator<_node_type> > m_nodes;
+ gim_array<_node_type> m_nodes;
+ //SuperBufferedArray< _node_type > m_nodes;
+ bool m_sorted;
+
+ ///Hash table data management. The hash table has the indices to the corresponding m_nodes array
+ GUINT* m_hash_table; //!<
+ GUINT m_table_size; //!<
+ GUINT m_node_size; //!<
+ GUINT m_min_hash_table_size;
+
+ //! Returns the cell index
+ inline GUINT _find_cell(GUINT hashkey)
+ {
+ _node_type* nodesptr = m_nodes.pointer();
+ GUINT start_index = (hashkey % m_table_size) * m_node_size;
+ GUINT end_index = start_index + m_node_size;
+
+ while (start_index < end_index)
+ {
+ GUINT value = m_hash_table[start_index];
+ if (value != GIM_INVALID_HASH)
+ {
+ if (nodesptr[value].m_key == hashkey) return start_index;
+ }
+ start_index++;
+ }
+ return GIM_INVALID_HASH;
+ }
+
+ //! Find the avaliable cell for the hashkey, and return an existing cell if it has the same hash key
+ inline GUINT _find_avaliable_cell(GUINT hashkey)
+ {
+ _node_type* nodesptr = m_nodes.pointer();
+ GUINT avaliable_index = GIM_INVALID_HASH;
+ GUINT start_index = (hashkey % m_table_size) * m_node_size;
+ GUINT end_index = start_index + m_node_size;
+
+ while (start_index < end_index)
+ {
+ GUINT value = m_hash_table[start_index];
+ if (value == GIM_INVALID_HASH)
+ {
+ if (avaliable_index == GIM_INVALID_HASH)
+ {
+ avaliable_index = start_index;
+ }
+ }
+ else if (nodesptr[value].m_key == hashkey)
+ {
+ return start_index;
+ }
+ start_index++;
+ }
+ return avaliable_index;
+ }
+
+ //! reserves the memory for the hash table.
+ /*!
\pre hash table must be empty
\post reserves the memory for the hash table, an initializes all elements to GIM_INVALID_HASH.
*/
- inline void _reserve_table_memory(GUINT newtablesize)
- {
- if(newtablesize==0) return;
- if(m_node_size==0) return;
-
- //Get a Prime size
-
- m_table_size = gim_next_prime(newtablesize);
-
- GUINT datasize = m_table_size*m_node_size;
- //Alloc the data buffer
- m_hash_table = (GUINT *)gim_alloc(datasize*sizeof(GUINT));
- }
-
- inline void _invalidate_keys()
- {
- GUINT datasize = m_table_size*m_node_size;
- for(GUINT i=0;i<datasize;i++)
- {
- m_hash_table[i] = GIM_INVALID_HASH;// invalidate keys
- }
- }
-
- //! Clear all memory for the hash table
- inline void _clear_table_memory()
- {
- if(m_hash_table==NULL) return;
- gim_free(m_hash_table);
- m_hash_table = NULL;
- m_table_size = 0;
- }
-
- //! Invalidates the keys (Assigning GIM_INVALID_HASH to all) Reorders the hash keys
- inline void _rehash()
- {
- _invalidate_keys();
-
- _node_type * nodesptr = m_nodes.pointer();
- for(GUINT i=0;i<(GUINT)m_nodes.size();i++)
- {
- GUINT nodekey = nodesptr[i].m_key;
- if(nodekey != GIM_INVALID_HASH)
- {
- //Search for the avaliable cell in buffer
- GUINT index = _find_avaliable_cell(nodekey);
-
-
- if(m_hash_table[index]!=GIM_INVALID_HASH)
- {//The new index is alreade used... discard this new incomming object, repeated key
- btAssert(m_hash_table[index]==nodekey);
+ inline void _reserve_table_memory(GUINT newtablesize)
+ {
+ if (newtablesize == 0) return;
+ if (m_node_size == 0) return;
+
+ //Get a Prime size
+
+ m_table_size = gim_next_prime(newtablesize);
+
+ GUINT datasize = m_table_size * m_node_size;
+ //Alloc the data buffer
+ m_hash_table = (GUINT*)gim_alloc(datasize * sizeof(GUINT));
+ }
+
+ inline void _invalidate_keys()
+ {
+ GUINT datasize = m_table_size * m_node_size;
+ for (GUINT i = 0; i < datasize; i++)
+ {
+ m_hash_table[i] = GIM_INVALID_HASH; // invalidate keys
+ }
+ }
+
+ //! Clear all memory for the hash table
+ inline void _clear_table_memory()
+ {
+ if (m_hash_table == NULL) return;
+ gim_free(m_hash_table);
+ m_hash_table = NULL;
+ m_table_size = 0;
+ }
+
+ //! Invalidates the keys (Assigning GIM_INVALID_HASH to all) Reorders the hash keys
+ inline void _rehash()
+ {
+ _invalidate_keys();
+
+ _node_type* nodesptr = m_nodes.pointer();
+ for (GUINT i = 0; i < (GUINT)m_nodes.size(); i++)
+ {
+ GUINT nodekey = nodesptr[i].m_key;
+ if (nodekey != GIM_INVALID_HASH)
+ {
+ //Search for the avaliable cell in buffer
+ GUINT index = _find_avaliable_cell(nodekey);
+
+ if (m_hash_table[index] != GIM_INVALID_HASH)
+ { //The new index is alreade used... discard this new incomming object, repeated key
+ btAssert(m_hash_table[index] == nodekey);
nodesptr[i].m_key = GIM_INVALID_HASH;
}
else
@@ -318,585 +298,560 @@ protected:
//Assign the value for alloc
m_hash_table[index] = i;
}
- }
- }
- }
-
- //! Resize hash table indices
- inline void _resize_table(GUINT newsize)
- {
- //Clear memory
- _clear_table_memory();
- //Alloc the data
- _reserve_table_memory(newsize);
- //Invalidate keys and rehash
- _rehash();
- }
-
- //! Destroy hash table memory
- inline void _destroy()
- {
- if(m_hash_table==NULL) return;
- _clear_table_memory();
- }
-
- //! Finds an avaliable hash table cell, and resizes the table if there isn't space
- inline GUINT _assign_hash_table_cell(GUINT hashkey)
- {
- GUINT cell_index = _find_avaliable_cell(hashkey);
-
- if(cell_index==GIM_INVALID_HASH)
- {
- //rehashing
- _resize_table(m_table_size+1);
- GUINT cell_index = _find_avaliable_cell(hashkey);
- btAssert(cell_index!=GIM_INVALID_HASH);
- }
- return cell_index;
- }
-
- //! erase by index in hash table
- inline bool _erase_by_index_hash_table(GUINT index)
- {
- if(index >= m_nodes.size()) return false;
- if(m_nodes[index].m_key != GIM_INVALID_HASH)
- {
- //Search for the avaliable cell in buffer
- GUINT cell_index = _find_cell(m_nodes[index].m_key);
-
- btAssert(cell_index!=GIM_INVALID_HASH);
- btAssert(m_hash_table[cell_index]==index);
-
- m_hash_table[cell_index] = GIM_INVALID_HASH;
- }
-
- return this->_erase_unsorted(index);
- }
-
- //! erase by key in hash table
- inline bool _erase_hash_table(GUINT hashkey)
- {
- if(hashkey == GIM_INVALID_HASH) return false;
-
- //Search for the avaliable cell in buffer
- GUINT cell_index = _find_cell(hashkey);
- if(cell_index ==GIM_INVALID_HASH) return false;
-
- GUINT index = m_hash_table[cell_index];
- m_hash_table[cell_index] = GIM_INVALID_HASH;
-
- return this->_erase_unsorted(index);
- }
-
-
-
- //! insert an element in hash table
- /*!
+ }
+ }
+ }
+
+ //! Resize hash table indices
+ inline void _resize_table(GUINT newsize)
+ {
+ //Clear memory
+ _clear_table_memory();
+ //Alloc the data
+ _reserve_table_memory(newsize);
+ //Invalidate keys and rehash
+ _rehash();
+ }
+
+ //! Destroy hash table memory
+ inline void _destroy()
+ {
+ if (m_hash_table == NULL) return;
+ _clear_table_memory();
+ }
+
+ //! Finds an avaliable hash table cell, and resizes the table if there isn't space
+ inline GUINT _assign_hash_table_cell(GUINT hashkey)
+ {
+ GUINT cell_index = _find_avaliable_cell(hashkey);
+
+ if (cell_index == GIM_INVALID_HASH)
+ {
+ //rehashing
+ _resize_table(m_table_size + 1);
+ GUINT cell_index = _find_avaliable_cell(hashkey);
+ btAssert(cell_index != GIM_INVALID_HASH);
+ }
+ return cell_index;
+ }
+
+ //! erase by index in hash table
+ inline bool _erase_by_index_hash_table(GUINT index)
+ {
+ if (index >= m_nodes.size()) return false;
+ if (m_nodes[index].m_key != GIM_INVALID_HASH)
+ {
+ //Search for the avaliable cell in buffer
+ GUINT cell_index = _find_cell(m_nodes[index].m_key);
+
+ btAssert(cell_index != GIM_INVALID_HASH);
+ btAssert(m_hash_table[cell_index] == index);
+
+ m_hash_table[cell_index] = GIM_INVALID_HASH;
+ }
+
+ return this->_erase_unsorted(index);
+ }
+
+ //! erase by key in hash table
+ inline bool _erase_hash_table(GUINT hashkey)
+ {
+ if (hashkey == GIM_INVALID_HASH) return false;
+
+ //Search for the avaliable cell in buffer
+ GUINT cell_index = _find_cell(hashkey);
+ if (cell_index == GIM_INVALID_HASH) return false;
+
+ GUINT index = m_hash_table[cell_index];
+ m_hash_table[cell_index] = GIM_INVALID_HASH;
+
+ return this->_erase_unsorted(index);
+ }
+
+ //! insert an element in hash table
+ /*!
If the element exists, this won't insert the element
\return the index in the array of the existing element,or GIM_INVALID_HASH if the element has been inserted
If so, the element has been inserted at the last position of the array.
*/
- inline GUINT _insert_hash_table(GUINT hashkey, const T & value)
- {
- if(hashkey==GIM_INVALID_HASH)
- {
- //Insert anyway
- _insert_unsorted(hashkey,value);
- return GIM_INVALID_HASH;
- }
+ inline GUINT _insert_hash_table(GUINT hashkey, const T& value)
+ {
+ if (hashkey == GIM_INVALID_HASH)
+ {
+ //Insert anyway
+ _insert_unsorted(hashkey, value);
+ return GIM_INVALID_HASH;
+ }
- GUINT cell_index = _assign_hash_table_cell(hashkey);
+ GUINT cell_index = _assign_hash_table_cell(hashkey);
- GUINT value_key = m_hash_table[cell_index];
+ GUINT value_key = m_hash_table[cell_index];
- if(value_key!= GIM_INVALID_HASH) return value_key;// Not overrited
+ if (value_key != GIM_INVALID_HASH) return value_key; // Not overrited
- m_hash_table[cell_index] = m_nodes.size();
+ m_hash_table[cell_index] = m_nodes.size();
- _insert_unsorted(hashkey,value);
- return GIM_INVALID_HASH;
- }
+ _insert_unsorted(hashkey, value);
+ return GIM_INVALID_HASH;
+ }
- //! insert an element in hash table.
- /*!
+ //! insert an element in hash table.
+ /*!
If the element exists, this replaces the element.
\return the index in the array of the existing element,or GIM_INVALID_HASH if the element has been inserted
If so, the element has been inserted at the last position of the array.
*/
- inline GUINT _insert_hash_table_replace(GUINT hashkey, const T & value)
- {
- if(hashkey==GIM_INVALID_HASH)
- {
- //Insert anyway
- _insert_unsorted(hashkey,value);
- return GIM_INVALID_HASH;
- }
-
- GUINT cell_index = _assign_hash_table_cell(hashkey);
-
- GUINT value_key = m_hash_table[cell_index];
-
- if(value_key!= GIM_INVALID_HASH)
- {//replaces the existing
- m_nodes[value_key] = _node_type(hashkey,value);
- return value_key;// index of the replaced element
- }
-
- m_hash_table[cell_index] = m_nodes.size();
-
- _insert_unsorted(hashkey,value);
- return GIM_INVALID_HASH;
-
- }
-
-
- ///Sorted array data management. The hash table has the indices to the corresponding m_nodes array
- inline bool _erase_sorted(GUINT index)
- {
- if(index>=(GUINT)m_nodes.size()) return false;
- m_nodes.erase_sorted(index);
- if(m_nodes.size()<2) m_sorted = false;
- return true;
- }
-
- //! faster, but unsorted
- inline bool _erase_unsorted(GUINT index)
- {
- if(index>=m_nodes.size()) return false;
-
- GUINT lastindex = m_nodes.size()-1;
- if(index<lastindex && m_hash_table!=0)
- {
- GUINT hashkey = m_nodes[lastindex].m_key;
- if(hashkey!=GIM_INVALID_HASH)
+ inline GUINT _insert_hash_table_replace(GUINT hashkey, const T& value)
+ {
+ if (hashkey == GIM_INVALID_HASH)
+ {
+ //Insert anyway
+ _insert_unsorted(hashkey, value);
+ return GIM_INVALID_HASH;
+ }
+
+ GUINT cell_index = _assign_hash_table_cell(hashkey);
+
+ GUINT value_key = m_hash_table[cell_index];
+
+ if (value_key != GIM_INVALID_HASH)
+ { //replaces the existing
+ m_nodes[value_key] = _node_type(hashkey, value);
+ return value_key; // index of the replaced element
+ }
+
+ m_hash_table[cell_index] = m_nodes.size();
+
+ _insert_unsorted(hashkey, value);
+ return GIM_INVALID_HASH;
+ }
+
+ ///Sorted array data management. The hash table has the indices to the corresponding m_nodes array
+ inline bool _erase_sorted(GUINT index)
+ {
+ if (index >= (GUINT)m_nodes.size()) return false;
+ m_nodes.erase_sorted(index);
+ if (m_nodes.size() < 2) m_sorted = false;
+ return true;
+ }
+
+ //! faster, but unsorted
+ inline bool _erase_unsorted(GUINT index)
+ {
+ if (index >= m_nodes.size()) return false;
+
+ GUINT lastindex = m_nodes.size() - 1;
+ if (index < lastindex && m_hash_table != 0)
+ {
+ GUINT hashkey = m_nodes[lastindex].m_key;
+ if (hashkey != GIM_INVALID_HASH)
{
//update the new position of the last element
GUINT cell_index = _find_cell(hashkey);
- btAssert(cell_index!=GIM_INVALID_HASH);
+ btAssert(cell_index != GIM_INVALID_HASH);
//new position of the last element which will be swaped
m_hash_table[cell_index] = index;
}
- }
- m_nodes.erase(index);
- m_sorted = false;
- return true;
- }
-
- //! Insert in position ordered
- /*!
+ }
+ m_nodes.erase(index);
+ m_sorted = false;
+ return true;
+ }
+
+ //! Insert in position ordered
+ /*!
Also checks if it is needed to transform this container to a hash table, by calling check_for_switching_to_hashtable
*/
- inline void _insert_in_pos(GUINT hashkey, const T & value, GUINT pos)
- {
- m_nodes.insert(_node_type(hashkey,value),pos);
- this->check_for_switching_to_hashtable();
- }
-
- //! Insert an element in an ordered array
- inline GUINT _insert_sorted(GUINT hashkey, const T & value)
- {
- if(hashkey==GIM_INVALID_HASH || size()==0)
- {
- m_nodes.push_back(_node_type(hashkey,value));
- return GIM_INVALID_HASH;
- }
- //Insert at last position
- //Sort element
-
-
- GUINT result_ind=0;
- GUINT last_index = m_nodes.size()-1;
- _node_type * ptr = m_nodes.pointer();
-
- bool found = gim_binary_search_ex(
- ptr,0,last_index,result_ind,hashkey,GIM_HASH_NODE_CMP_KEY_MACRO());
-
-
- //Insert before found index
- if(found)
- {
- return result_ind;
- }
- else
- {
- _insert_in_pos(hashkey, value, result_ind);
- }
- return GIM_INVALID_HASH;
- }
-
- inline GUINT _insert_sorted_replace(GUINT hashkey, const T & value)
- {
- if(hashkey==GIM_INVALID_HASH || size()==0)
- {
- m_nodes.push_back(_node_type(hashkey,value));
- return GIM_INVALID_HASH;
- }
- //Insert at last position
- //Sort element
- GUINT result_ind;
- GUINT last_index = m_nodes.size()-1;
- _node_type * ptr = m_nodes.pointer();
-
- bool found = gim_binary_search_ex(
- ptr,0,last_index,result_ind,hashkey,GIM_HASH_NODE_CMP_KEY_MACRO());
-
- //Insert before found index
- if(found)
- {
- m_nodes[result_ind] = _node_type(hashkey,value);
- }
- else
- {
- _insert_in_pos(hashkey, value, result_ind);
- }
- return result_ind;
- }
-
- //! Fast insertion in m_nodes array
- inline GUINT _insert_unsorted(GUINT hashkey, const T & value)
- {
- m_nodes.push_back(_node_type(hashkey,value));
- m_sorted = false;
- return GIM_INVALID_HASH;
- }
-
-
+ inline void _insert_in_pos(GUINT hashkey, const T& value, GUINT pos)
+ {
+ m_nodes.insert(_node_type(hashkey, value), pos);
+ this->check_for_switching_to_hashtable();
+ }
-public:
+ //! Insert an element in an ordered array
+ inline GUINT _insert_sorted(GUINT hashkey, const T& value)
+ {
+ if (hashkey == GIM_INVALID_HASH || size() == 0)
+ {
+ m_nodes.push_back(_node_type(hashkey, value));
+ return GIM_INVALID_HASH;
+ }
+ //Insert at last position
+ //Sort element
+
+ GUINT result_ind = 0;
+ GUINT last_index = m_nodes.size() - 1;
+ _node_type* ptr = m_nodes.pointer();
+
+ bool found = gim_binary_search_ex(
+ ptr, 0, last_index, result_ind, hashkey, GIM_HASH_NODE_CMP_KEY_MACRO());
+
+ //Insert before found index
+ if (found)
+ {
+ return result_ind;
+ }
+ else
+ {
+ _insert_in_pos(hashkey, value, result_ind);
+ }
+ return GIM_INVALID_HASH;
+ }
- /*!
+ inline GUINT _insert_sorted_replace(GUINT hashkey, const T& value)
+ {
+ if (hashkey == GIM_INVALID_HASH || size() == 0)
+ {
+ m_nodes.push_back(_node_type(hashkey, value));
+ return GIM_INVALID_HASH;
+ }
+ //Insert at last position
+ //Sort element
+ GUINT result_ind;
+ GUINT last_index = m_nodes.size() - 1;
+ _node_type* ptr = m_nodes.pointer();
+
+ bool found = gim_binary_search_ex(
+ ptr, 0, last_index, result_ind, hashkey, GIM_HASH_NODE_CMP_KEY_MACRO());
+
+ //Insert before found index
+ if (found)
+ {
+ m_nodes[result_ind] = _node_type(hashkey, value);
+ }
+ else
+ {
+ _insert_in_pos(hashkey, value, result_ind);
+ }
+ return result_ind;
+ }
+
+ //! Fast insertion in m_nodes array
+ inline GUINT _insert_unsorted(GUINT hashkey, const T& value)
+ {
+ m_nodes.push_back(_node_type(hashkey, value));
+ m_sorted = false;
+ return GIM_INVALID_HASH;
+ }
+
+public:
+ /*!
<li> if node_size = 0, then this container becomes a simple sorted array allocator. reserve_size is used for reserve memory in m_nodes.
When the array size reaches the size equivalent to 'min_hash_table_size', then it becomes a hash table by calling check_for_switching_to_hashtable.
<li> If node_size != 0, then this container becomes a hash table for ever
</ul>
*/
- gim_hash_table(GUINT reserve_size = GIM_DEFAULT_HASH_TABLE_SIZE,
- GUINT node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE,
- GUINT min_hash_table_size = GIM_INVALID_HASH)
- {
- m_hash_table = NULL;
- m_table_size = 0;
- m_sorted = false;
- m_node_size = node_size;
- m_min_hash_table_size = min_hash_table_size;
-
- if(m_node_size!=0)
- {
- if(reserve_size!=0)
- {
- m_nodes.reserve(reserve_size);
- _reserve_table_memory(reserve_size);
- _invalidate_keys();
- }
- else
- {
- m_nodes.reserve(GIM_DEFAULT_HASH_TABLE_SIZE);
- _reserve_table_memory(GIM_DEFAULT_HASH_TABLE_SIZE);
- _invalidate_keys();
- }
- }
- else if(reserve_size!=0)
- {
- m_nodes.reserve(reserve_size);
- }
-
- }
-
- ~gim_hash_table()
- {
- _destroy();
- }
-
- inline bool is_hash_table()
- {
- if(m_hash_table) return true;
- return false;
- }
-
- inline bool is_sorted()
- {
- if(size()<2) return true;
- return m_sorted;
- }
-
- bool sort()
- {
- if(is_sorted()) return true;
- if(m_nodes.size()<2) return false;
-
-
- _node_type * ptr = m_nodes.pointer();
- GUINT siz = m_nodes.size();
- gim_sort_hash_node_array(ptr,siz);
- m_sorted=true;
-
-
-
- if(m_hash_table)
- {
- _rehash();
- }
- return true;
- }
-
- bool switch_to_hashtable()
- {
- if(m_hash_table) return false;
- if(m_node_size==0) m_node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE;
- if(m_nodes.size()<GIM_DEFAULT_HASH_TABLE_SIZE)
- {
- _resize_table(GIM_DEFAULT_HASH_TABLE_SIZE);
- }
- else
- {
- _resize_table(m_nodes.size()+1);
- }
-
- return true;
- }
-
- bool switch_to_sorted_array()
- {
- if(m_hash_table==NULL) return true;
- _clear_table_memory();
- return sort();
- }
-
- //!If the container reaches the
- bool check_for_switching_to_hashtable()
- {
- if(this->m_hash_table) return true;
-
- if(!(m_nodes.size()< m_min_hash_table_size))
- {
- if(m_node_size == 0)
- {
- m_node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE;
- }
-
- _resize_table(m_nodes.size()+1);
- return true;
- }
- return false;
- }
-
- inline void set_sorted(bool value)
- {
- m_sorted = value;
- }
-
- //! Retrieves the amount of keys.
- inline GUINT size() const
- {
- return m_nodes.size();
- }
-
- //! Retrieves the hash key.
- inline GUINT get_key(GUINT index) const
- {
- return m_nodes[index].m_key;
- }
-
- //! Retrieves the value by index
- /*!
+ gim_hash_table(GUINT reserve_size = GIM_DEFAULT_HASH_TABLE_SIZE,
+ GUINT node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE,
+ GUINT min_hash_table_size = GIM_INVALID_HASH)
+ {
+ m_hash_table = NULL;
+ m_table_size = 0;
+ m_sorted = false;
+ m_node_size = node_size;
+ m_min_hash_table_size = min_hash_table_size;
+
+ if (m_node_size != 0)
+ {
+ if (reserve_size != 0)
+ {
+ m_nodes.reserve(reserve_size);
+ _reserve_table_memory(reserve_size);
+ _invalidate_keys();
+ }
+ else
+ {
+ m_nodes.reserve(GIM_DEFAULT_HASH_TABLE_SIZE);
+ _reserve_table_memory(GIM_DEFAULT_HASH_TABLE_SIZE);
+ _invalidate_keys();
+ }
+ }
+ else if (reserve_size != 0)
+ {
+ m_nodes.reserve(reserve_size);
+ }
+ }
+
+ ~gim_hash_table()
+ {
+ _destroy();
+ }
+
+ inline bool is_hash_table()
+ {
+ if (m_hash_table) return true;
+ return false;
+ }
+
+ inline bool is_sorted()
+ {
+ if (size() < 2) return true;
+ return m_sorted;
+ }
+
+ bool sort()
+ {
+ if (is_sorted()) return true;
+ if (m_nodes.size() < 2) return false;
+
+ _node_type* ptr = m_nodes.pointer();
+ GUINT siz = m_nodes.size();
+ gim_sort_hash_node_array(ptr, siz);
+ m_sorted = true;
+
+ if (m_hash_table)
+ {
+ _rehash();
+ }
+ return true;
+ }
+
+ bool switch_to_hashtable()
+ {
+ if (m_hash_table) return false;
+ if (m_node_size == 0) m_node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE;
+ if (m_nodes.size() < GIM_DEFAULT_HASH_TABLE_SIZE)
+ {
+ _resize_table(GIM_DEFAULT_HASH_TABLE_SIZE);
+ }
+ else
+ {
+ _resize_table(m_nodes.size() + 1);
+ }
+
+ return true;
+ }
+
+ bool switch_to_sorted_array()
+ {
+ if (m_hash_table == NULL) return true;
+ _clear_table_memory();
+ return sort();
+ }
+
+ //!If the container reaches the
+ bool check_for_switching_to_hashtable()
+ {
+ if (this->m_hash_table) return true;
+
+ if (!(m_nodes.size() < m_min_hash_table_size))
+ {
+ if (m_node_size == 0)
+ {
+ m_node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE;
+ }
+
+ _resize_table(m_nodes.size() + 1);
+ return true;
+ }
+ return false;
+ }
+
+ inline void set_sorted(bool value)
+ {
+ m_sorted = value;
+ }
+
+ //! Retrieves the amount of keys.
+ inline GUINT size() const
+ {
+ return m_nodes.size();
+ }
+
+ //! Retrieves the hash key.
+ inline GUINT get_key(GUINT index) const
+ {
+ return m_nodes[index].m_key;
+ }
+
+ //! Retrieves the value by index
+ /*!
*/
- inline T * get_value_by_index(GUINT index)
- {
- return &m_nodes[index].m_data;
- }
-
- inline const T& operator[](GUINT index) const
- {
- return m_nodes[index].m_data;
- }
-
- inline T& operator[](GUINT index)
- {
- return m_nodes[index].m_data;
- }
-
- //! Finds the index of the element with the key
- /*!
+ inline T* get_value_by_index(GUINT index)
+ {
+ return &m_nodes[index].m_data;
+ }
+
+ inline const T& operator[](GUINT index) const
+ {
+ return m_nodes[index].m_data;
+ }
+
+ inline T& operator[](GUINT index)
+ {
+ return m_nodes[index].m_data;
+ }
+
+ //! Finds the index of the element with the key
+ /*!
\return the index in the array of the existing element,or GIM_INVALID_HASH if the element has been inserted
If so, the element has been inserted at the last position of the array.
*/
- inline GUINT find(GUINT hashkey)
- {
- if(m_hash_table)
- {
- GUINT cell_index = _find_cell(hashkey);
- if(cell_index==GIM_INVALID_HASH) return GIM_INVALID_HASH;
- return m_hash_table[cell_index];
- }
+ inline GUINT find(GUINT hashkey)
+ {
+ if (m_hash_table)
+ {
+ GUINT cell_index = _find_cell(hashkey);
+ if (cell_index == GIM_INVALID_HASH) return GIM_INVALID_HASH;
+ return m_hash_table[cell_index];
+ }
GUINT last_index = m_nodes.size();
- if(last_index<2)
- {
- if(last_index==0) return GIM_INVALID_HASH;
- if(m_nodes[0].m_key == hashkey) return 0;
- return GIM_INVALID_HASH;
- }
- else if(m_sorted)
- {
- //Binary search
- GUINT result_ind = 0;
+ if (last_index < 2)
+ {
+ if (last_index == 0) return GIM_INVALID_HASH;
+ if (m_nodes[0].m_key == hashkey) return 0;
+ return GIM_INVALID_HASH;
+ }
+ else if (m_sorted)
+ {
+ //Binary search
+ GUINT result_ind = 0;
last_index--;
- _node_type * ptr = m_nodes.pointer();
+ _node_type* ptr = m_nodes.pointer();
- bool found = gim_binary_search_ex(ptr,0,last_index,result_ind,hashkey,GIM_HASH_NODE_CMP_KEY_MACRO());
+ bool found = gim_binary_search_ex(ptr, 0, last_index, result_ind, hashkey, GIM_HASH_NODE_CMP_KEY_MACRO());
+ if (found) return result_ind;
+ }
+ return GIM_INVALID_HASH;
+ }
- if(found) return result_ind;
- }
- return GIM_INVALID_HASH;
- }
-
- //! Retrieves the value associated with the index
- /*!
+ //! Retrieves the value associated with the index
+ /*!
\return the found element, or null
*/
- inline T * get_value(GUINT hashkey)
- {
- GUINT index = find(hashkey);
- if(index == GIM_INVALID_HASH) return NULL;
- return &m_nodes[index].m_data;
- }
-
+ inline T* get_value(GUINT hashkey)
+ {
+ GUINT index = find(hashkey);
+ if (index == GIM_INVALID_HASH) return NULL;
+ return &m_nodes[index].m_data;
+ }
- /*!
+ /*!
*/
- inline bool erase_by_index(GUINT index)
- {
- if(index > m_nodes.size()) return false;
-
- if(m_hash_table == NULL)
- {
- if(is_sorted())
- {
- return this->_erase_sorted(index);
- }
- else
- {
- return this->_erase_unsorted(index);
- }
- }
- else
- {
- return this->_erase_by_index_hash_table(index);
- }
- return false;
- }
-
-
-
- inline bool erase_by_index_unsorted(GUINT index)
- {
- if(index > m_nodes.size()) return false;
-
- if(m_hash_table == NULL)
- {
- return this->_erase_unsorted(index);
- }
- else
- {
- return this->_erase_by_index_hash_table(index);
- }
- return false;
- }
-
-
-
- /*!
+ inline bool erase_by_index(GUINT index)
+ {
+ if (index > m_nodes.size()) return false;
+
+ if (m_hash_table == NULL)
+ {
+ if (is_sorted())
+ {
+ return this->_erase_sorted(index);
+ }
+ else
+ {
+ return this->_erase_unsorted(index);
+ }
+ }
+ else
+ {
+ return this->_erase_by_index_hash_table(index);
+ }
+ return false;
+ }
+
+ inline bool erase_by_index_unsorted(GUINT index)
+ {
+ if (index > m_nodes.size()) return false;
+
+ if (m_hash_table == NULL)
+ {
+ return this->_erase_unsorted(index);
+ }
+ else
+ {
+ return this->_erase_by_index_hash_table(index);
+ }
+ return false;
+ }
+
+ /*!
*/
- inline bool erase_by_key(GUINT hashkey)
- {
- if(size()==0) return false;
-
- if(m_hash_table)
- {
- return this->_erase_hash_table(hashkey);
- }
- //Binary search
-
- if(is_sorted()==false) return false;
-
- GUINT result_ind = find(hashkey);
- if(result_ind!= GIM_INVALID_HASH)
- {
- return this->_erase_sorted(result_ind);
- }
- return false;
- }
-
- void clear()
- {
- m_nodes.clear();
-
- if(m_hash_table==NULL) return;
- GUINT datasize = m_table_size*m_node_size;
- //Initialize the hashkeys.
- GUINT i;
- for(i=0;i<datasize;i++)
- {
- m_hash_table[i] = GIM_INVALID_HASH;// invalidate keys
- }
+ inline bool erase_by_key(GUINT hashkey)
+ {
+ if (size() == 0) return false;
+
+ if (m_hash_table)
+ {
+ return this->_erase_hash_table(hashkey);
+ }
+ //Binary search
+
+ if (is_sorted() == false) return false;
+
+ GUINT result_ind = find(hashkey);
+ if (result_ind != GIM_INVALID_HASH)
+ {
+ return this->_erase_sorted(result_ind);
+ }
+ return false;
+ }
+
+ void clear()
+ {
+ m_nodes.clear();
+
+ if (m_hash_table == NULL) return;
+ GUINT datasize = m_table_size * m_node_size;
+ //Initialize the hashkeys.
+ GUINT i;
+ for (i = 0; i < datasize; i++)
+ {
+ m_hash_table[i] = GIM_INVALID_HASH; // invalidate keys
+ }
m_sorted = false;
- }
+ }
- //! Insert an element into the hash
- /*!
+ //! Insert an element into the hash
+ /*!
\return If GIM_INVALID_HASH, the object has been inserted succesfully. Else it returns the position
of the existing element.
*/
- inline GUINT insert(GUINT hashkey, const T & element)
- {
- if(m_hash_table)
- {
- return this->_insert_hash_table(hashkey,element);
- }
- if(this->is_sorted())
- {
- return this->_insert_sorted(hashkey,element);
- }
- return this->_insert_unsorted(hashkey,element);
- }
-
- //! Insert an element into the hash, and could overrite an existing object with the same hash.
- /*!
+ inline GUINT insert(GUINT hashkey, const T& element)
+ {
+ if (m_hash_table)
+ {
+ return this->_insert_hash_table(hashkey, element);
+ }
+ if (this->is_sorted())
+ {
+ return this->_insert_sorted(hashkey, element);
+ }
+ return this->_insert_unsorted(hashkey, element);
+ }
+
+ //! Insert an element into the hash, and could overrite an existing object with the same hash.
+ /*!
\return If GIM_INVALID_HASH, the object has been inserted succesfully. Else it returns the position
of the replaced element.
*/
- inline GUINT insert_override(GUINT hashkey, const T & element)
- {
- if(m_hash_table)
- {
- return this->_insert_hash_table_replace(hashkey,element);
- }
- if(this->is_sorted())
- {
- return this->_insert_sorted_replace(hashkey,element);
- }
- this->_insert_unsorted(hashkey,element);
- return m_nodes.size();
- }
-
-
-
- //! Insert an element into the hash,But if this container is a sorted array, this inserts it unsorted
- /*!
- */
- inline GUINT insert_unsorted(GUINT hashkey,const T & element)
- {
- if(m_hash_table)
- {
- return this->_insert_hash_table(hashkey,element);
- }
- return this->_insert_unsorted(hashkey,element);
- }
-
+ inline GUINT insert_override(GUINT hashkey, const T& element)
+ {
+ if (m_hash_table)
+ {
+ return this->_insert_hash_table_replace(hashkey, element);
+ }
+ if (this->is_sorted())
+ {
+ return this->_insert_sorted_replace(hashkey, element);
+ }
+ this->_insert_unsorted(hashkey, element);
+ return m_nodes.size();
+ }
+ //! Insert an element into the hash,But if this container is a sorted array, this inserts it unsorted
+ /*!
+ */
+ inline GUINT insert_unsorted(GUINT hashkey, const T& element)
+ {
+ if (m_hash_table)
+ {
+ return this->_insert_hash_table(hashkey, element);
+ }
+ return this->_insert_unsorted(hashkey, element);
+ }
};
-
-
-#endif // GIM_CONTAINERS_H_INCLUDED
+#endif // GIM_CONTAINERS_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_linear_math.h b/thirdparty/bullet/BulletCollision/Gimpact/gim_linear_math.h
index 64f11b4954..98401a404a 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_linear_math.h
+++ b/thirdparty/bullet/BulletCollision/Gimpact/gim_linear_math.h
@@ -34,962 +34,900 @@ email: projectileman@yahoo.com
-----------------------------------------------------------------------------
*/
-
#include "gim_math.h"
#include "gim_geom_types.h"
-
-
-
//! Zero out a 2D vector
-#define VEC_ZERO_2(a) \
-{ \
- (a)[0] = (a)[1] = 0.0f; \
-}\
-
+#define VEC_ZERO_2(a) \
+ { \
+ (a)[0] = (a)[1] = 0.0f; \
+ }
//! Zero out a 3D vector
-#define VEC_ZERO(a) \
-{ \
- (a)[0] = (a)[1] = (a)[2] = 0.0f; \
-}\
-
+#define VEC_ZERO(a) \
+ { \
+ (a)[0] = (a)[1] = (a)[2] = 0.0f; \
+ }
/// Zero out a 4D vector
-#define VEC_ZERO_4(a) \
-{ \
- (a)[0] = (a)[1] = (a)[2] = (a)[3] = 0.0f; \
-}\
-
+#define VEC_ZERO_4(a) \
+ { \
+ (a)[0] = (a)[1] = (a)[2] = (a)[3] = 0.0f; \
+ }
/// Vector copy
-#define VEC_COPY_2(b,a) \
-{ \
- (b)[0] = (a)[0]; \
- (b)[1] = (a)[1]; \
-}\
-
+#define VEC_COPY_2(b, a) \
+ { \
+ (b)[0] = (a)[0]; \
+ (b)[1] = (a)[1]; \
+ }
/// Copy 3D vector
-#define VEC_COPY(b,a) \
-{ \
- (b)[0] = (a)[0]; \
- (b)[1] = (a)[1]; \
- (b)[2] = (a)[2]; \
-}\
-
+#define VEC_COPY(b, a) \
+ { \
+ (b)[0] = (a)[0]; \
+ (b)[1] = (a)[1]; \
+ (b)[2] = (a)[2]; \
+ }
/// Copy 4D vector
-#define VEC_COPY_4(b,a) \
-{ \
- (b)[0] = (a)[0]; \
- (b)[1] = (a)[1]; \
- (b)[2] = (a)[2]; \
- (b)[3] = (a)[3]; \
-}\
+#define VEC_COPY_4(b, a) \
+ { \
+ (b)[0] = (a)[0]; \
+ (b)[1] = (a)[1]; \
+ (b)[2] = (a)[2]; \
+ (b)[3] = (a)[3]; \
+ }
/// VECTOR SWAP
-#define VEC_SWAP(b,a) \
-{ \
- GIM_SWAP_NUMBERS((b)[0],(a)[0]);\
- GIM_SWAP_NUMBERS((b)[1],(a)[1]);\
- GIM_SWAP_NUMBERS((b)[2],(a)[2]);\
-}\
+#define VEC_SWAP(b, a) \
+ { \
+ GIM_SWAP_NUMBERS((b)[0], (a)[0]); \
+ GIM_SWAP_NUMBERS((b)[1], (a)[1]); \
+ GIM_SWAP_NUMBERS((b)[2], (a)[2]); \
+ }
/// Vector difference
-#define VEC_DIFF_2(v21,v2,v1) \
-{ \
- (v21)[0] = (v2)[0] - (v1)[0]; \
- (v21)[1] = (v2)[1] - (v1)[1]; \
-}\
-
+#define VEC_DIFF_2(v21, v2, v1) \
+ { \
+ (v21)[0] = (v2)[0] - (v1)[0]; \
+ (v21)[1] = (v2)[1] - (v1)[1]; \
+ }
/// Vector difference
-#define VEC_DIFF(v21,v2,v1) \
-{ \
- (v21)[0] = (v2)[0] - (v1)[0]; \
- (v21)[1] = (v2)[1] - (v1)[1]; \
- (v21)[2] = (v2)[2] - (v1)[2]; \
-}\
-
+#define VEC_DIFF(v21, v2, v1) \
+ { \
+ (v21)[0] = (v2)[0] - (v1)[0]; \
+ (v21)[1] = (v2)[1] - (v1)[1]; \
+ (v21)[2] = (v2)[2] - (v1)[2]; \
+ }
/// Vector difference
-#define VEC_DIFF_4(v21,v2,v1) \
-{ \
- (v21)[0] = (v2)[0] - (v1)[0]; \
- (v21)[1] = (v2)[1] - (v1)[1]; \
- (v21)[2] = (v2)[2] - (v1)[2]; \
- (v21)[3] = (v2)[3] - (v1)[3]; \
-}\
-
+#define VEC_DIFF_4(v21, v2, v1) \
+ { \
+ (v21)[0] = (v2)[0] - (v1)[0]; \
+ (v21)[1] = (v2)[1] - (v1)[1]; \
+ (v21)[2] = (v2)[2] - (v1)[2]; \
+ (v21)[3] = (v2)[3] - (v1)[3]; \
+ }
/// Vector sum
-#define VEC_SUM_2(v21,v2,v1) \
-{ \
- (v21)[0] = (v2)[0] + (v1)[0]; \
- (v21)[1] = (v2)[1] + (v1)[1]; \
-}\
-
+#define VEC_SUM_2(v21, v2, v1) \
+ { \
+ (v21)[0] = (v2)[0] + (v1)[0]; \
+ (v21)[1] = (v2)[1] + (v1)[1]; \
+ }
/// Vector sum
-#define VEC_SUM(v21,v2,v1) \
-{ \
- (v21)[0] = (v2)[0] + (v1)[0]; \
- (v21)[1] = (v2)[1] + (v1)[1]; \
- (v21)[2] = (v2)[2] + (v1)[2]; \
-}\
-
+#define VEC_SUM(v21, v2, v1) \
+ { \
+ (v21)[0] = (v2)[0] + (v1)[0]; \
+ (v21)[1] = (v2)[1] + (v1)[1]; \
+ (v21)[2] = (v2)[2] + (v1)[2]; \
+ }
/// Vector sum
-#define VEC_SUM_4(v21,v2,v1) \
-{ \
- (v21)[0] = (v2)[0] + (v1)[0]; \
- (v21)[1] = (v2)[1] + (v1)[1]; \
- (v21)[2] = (v2)[2] + (v1)[2]; \
- (v21)[3] = (v2)[3] + (v1)[3]; \
-}\
-
+#define VEC_SUM_4(v21, v2, v1) \
+ { \
+ (v21)[0] = (v2)[0] + (v1)[0]; \
+ (v21)[1] = (v2)[1] + (v1)[1]; \
+ (v21)[2] = (v2)[2] + (v1)[2]; \
+ (v21)[3] = (v2)[3] + (v1)[3]; \
+ }
/// scalar times vector
-#define VEC_SCALE_2(c,a,b) \
-{ \
- (c)[0] = (a)*(b)[0]; \
- (c)[1] = (a)*(b)[1]; \
-}\
-
+#define VEC_SCALE_2(c, a, b) \
+ { \
+ (c)[0] = (a) * (b)[0]; \
+ (c)[1] = (a) * (b)[1]; \
+ }
/// scalar times vector
-#define VEC_SCALE(c,a,b) \
-{ \
- (c)[0] = (a)*(b)[0]; \
- (c)[1] = (a)*(b)[1]; \
- (c)[2] = (a)*(b)[2]; \
-}\
-
+#define VEC_SCALE(c, a, b) \
+ { \
+ (c)[0] = (a) * (b)[0]; \
+ (c)[1] = (a) * (b)[1]; \
+ (c)[2] = (a) * (b)[2]; \
+ }
/// scalar times vector
-#define VEC_SCALE_4(c,a,b) \
-{ \
- (c)[0] = (a)*(b)[0]; \
- (c)[1] = (a)*(b)[1]; \
- (c)[2] = (a)*(b)[2]; \
- (c)[3] = (a)*(b)[3]; \
-}\
-
+#define VEC_SCALE_4(c, a, b) \
+ { \
+ (c)[0] = (a) * (b)[0]; \
+ (c)[1] = (a) * (b)[1]; \
+ (c)[2] = (a) * (b)[2]; \
+ (c)[3] = (a) * (b)[3]; \
+ }
/// accumulate scaled vector
-#define VEC_ACCUM_2(c,a,b) \
-{ \
- (c)[0] += (a)*(b)[0]; \
- (c)[1] += (a)*(b)[1]; \
-}\
-
+#define VEC_ACCUM_2(c, a, b) \
+ { \
+ (c)[0] += (a) * (b)[0]; \
+ (c)[1] += (a) * (b)[1]; \
+ }
/// accumulate scaled vector
-#define VEC_ACCUM(c,a,b) \
-{ \
- (c)[0] += (a)*(b)[0]; \
- (c)[1] += (a)*(b)[1]; \
- (c)[2] += (a)*(b)[2]; \
-}\
-
+#define VEC_ACCUM(c, a, b) \
+ { \
+ (c)[0] += (a) * (b)[0]; \
+ (c)[1] += (a) * (b)[1]; \
+ (c)[2] += (a) * (b)[2]; \
+ }
/// accumulate scaled vector
-#define VEC_ACCUM_4(c,a,b) \
-{ \
- (c)[0] += (a)*(b)[0]; \
- (c)[1] += (a)*(b)[1]; \
- (c)[2] += (a)*(b)[2]; \
- (c)[3] += (a)*(b)[3]; \
-}\
-
+#define VEC_ACCUM_4(c, a, b) \
+ { \
+ (c)[0] += (a) * (b)[0]; \
+ (c)[1] += (a) * (b)[1]; \
+ (c)[2] += (a) * (b)[2]; \
+ (c)[3] += (a) * (b)[3]; \
+ }
/// Vector dot product
-#define VEC_DOT_2(a,b) ((a)[0]*(b)[0] + (a)[1]*(b)[1])
-
+#define VEC_DOT_2(a, b) ((a)[0] * (b)[0] + (a)[1] * (b)[1])
/// Vector dot product
-#define VEC_DOT(a,b) ((a)[0]*(b)[0] + (a)[1]*(b)[1] + (a)[2]*(b)[2])
+#define VEC_DOT(a, b) ((a)[0] * (b)[0] + (a)[1] * (b)[1] + (a)[2] * (b)[2])
/// Vector dot product
-#define VEC_DOT_4(a,b) ((a)[0]*(b)[0] + (a)[1]*(b)[1] + (a)[2]*(b)[2] + (a)[3]*(b)[3])
+#define VEC_DOT_4(a, b) ((a)[0] * (b)[0] + (a)[1] * (b)[1] + (a)[2] * (b)[2] + (a)[3] * (b)[3])
/// vector impact parameter (squared)
-#define VEC_IMPACT_SQ(bsq,direction,position) {\
- GREAL _llel_ = VEC_DOT(direction, position);\
- bsq = VEC_DOT(position, position) - _llel_*_llel_;\
-}\
-
+#define VEC_IMPACT_SQ(bsq, direction, position) \
+ { \
+ GREAL _llel_ = VEC_DOT(direction, position); \
+ bsq = VEC_DOT(position, position) - _llel_ * _llel_; \
+ }
/// vector impact parameter
-#define VEC_IMPACT(bsq,direction,position) {\
- VEC_IMPACT_SQ(bsq,direction,position); \
- GIM_SQRT(bsq,bsq); \
-}\
+#define VEC_IMPACT(bsq, direction, position) \
+ { \
+ VEC_IMPACT_SQ(bsq, direction, position); \
+ GIM_SQRT(bsq, bsq); \
+ }
/// Vector length
-#define VEC_LENGTH_2(a,l)\
-{\
- GREAL _pp = VEC_DOT_2(a,a);\
- GIM_SQRT(_pp,l);\
-}\
-
+#define VEC_LENGTH_2(a, l) \
+ { \
+ GREAL _pp = VEC_DOT_2(a, a); \
+ GIM_SQRT(_pp, l); \
+ }
/// Vector length
-#define VEC_LENGTH(a,l)\
-{\
- GREAL _pp = VEC_DOT(a,a);\
- GIM_SQRT(_pp,l);\
-}\
-
+#define VEC_LENGTH(a, l) \
+ { \
+ GREAL _pp = VEC_DOT(a, a); \
+ GIM_SQRT(_pp, l); \
+ }
/// Vector length
-#define VEC_LENGTH_4(a,l)\
-{\
- GREAL _pp = VEC_DOT_4(a,a);\
- GIM_SQRT(_pp,l);\
-}\
+#define VEC_LENGTH_4(a, l) \
+ { \
+ GREAL _pp = VEC_DOT_4(a, a); \
+ GIM_SQRT(_pp, l); \
+ }
/// Vector inv length
-#define VEC_INV_LENGTH_2(a,l)\
-{\
- GREAL _pp = VEC_DOT_2(a,a);\
- GIM_INV_SQRT(_pp,l);\
-}\
-
+#define VEC_INV_LENGTH_2(a, l) \
+ { \
+ GREAL _pp = VEC_DOT_2(a, a); \
+ GIM_INV_SQRT(_pp, l); \
+ }
/// Vector inv length
-#define VEC_INV_LENGTH(a,l)\
-{\
- GREAL _pp = VEC_DOT(a,a);\
- GIM_INV_SQRT(_pp,l);\
-}\
-
+#define VEC_INV_LENGTH(a, l) \
+ { \
+ GREAL _pp = VEC_DOT(a, a); \
+ GIM_INV_SQRT(_pp, l); \
+ }
/// Vector inv length
-#define VEC_INV_LENGTH_4(a,l)\
-{\
- GREAL _pp = VEC_DOT_4(a,a);\
- GIM_INV_SQRT(_pp,l);\
-}\
-
-
+#define VEC_INV_LENGTH_4(a, l) \
+ { \
+ GREAL _pp = VEC_DOT_4(a, a); \
+ GIM_INV_SQRT(_pp, l); \
+ }
/// distance between two points
-#define VEC_DISTANCE(_len,_va,_vb) {\
- vec3f _tmp_; \
- VEC_DIFF(_tmp_, _vb, _va); \
- VEC_LENGTH(_tmp_,_len); \
-}\
-
+#define VEC_DISTANCE(_len, _va, _vb) \
+ { \
+ vec3f _tmp_; \
+ VEC_DIFF(_tmp_, _vb, _va); \
+ VEC_LENGTH(_tmp_, _len); \
+ }
/// Vector length
-#define VEC_CONJUGATE_LENGTH(a,l)\
-{\
- GREAL _pp = 1.0 - a[0]*a[0] - a[1]*a[1] - a[2]*a[2];\
- GIM_SQRT(_pp,l);\
-}\
-
+#define VEC_CONJUGATE_LENGTH(a, l) \
+ { \
+ GREAL _pp = 1.0 - a[0] * a[0] - a[1] * a[1] - a[2] * a[2]; \
+ GIM_SQRT(_pp, l); \
+ }
/// Vector length
-#define VEC_NORMALIZE(a) { \
- GREAL len;\
- VEC_INV_LENGTH(a,len); \
- if(len<G_REAL_INFINITY)\
- {\
- a[0] *= len; \
- a[1] *= len; \
- a[2] *= len; \
- } \
-}\
+#define VEC_NORMALIZE(a) \
+ { \
+ GREAL len; \
+ VEC_INV_LENGTH(a, len); \
+ if (len < G_REAL_INFINITY) \
+ { \
+ a[0] *= len; \
+ a[1] *= len; \
+ a[2] *= len; \
+ } \
+ }
/// Set Vector size
-#define VEC_RENORMALIZE(a,newlen) { \
- GREAL len;\
- VEC_INV_LENGTH(a,len); \
- if(len<G_REAL_INFINITY)\
- {\
- len *= newlen;\
- a[0] *= len; \
- a[1] *= len; \
- a[2] *= len; \
- } \
-}\
+#define VEC_RENORMALIZE(a, newlen) \
+ { \
+ GREAL len; \
+ VEC_INV_LENGTH(a, len); \
+ if (len < G_REAL_INFINITY) \
+ { \
+ len *= newlen; \
+ a[0] *= len; \
+ a[1] *= len; \
+ a[2] *= len; \
+ } \
+ }
/// Vector cross
-#define VEC_CROSS(c,a,b) \
-{ \
- c[0] = (a)[1] * (b)[2] - (a)[2] * (b)[1]; \
- c[1] = (a)[2] * (b)[0] - (a)[0] * (b)[2]; \
- c[2] = (a)[0] * (b)[1] - (a)[1] * (b)[0]; \
-}\
-
+#define VEC_CROSS(c, a, b) \
+ { \
+ c[0] = (a)[1] * (b)[2] - (a)[2] * (b)[1]; \
+ c[1] = (a)[2] * (b)[0] - (a)[0] * (b)[2]; \
+ c[2] = (a)[0] * (b)[1] - (a)[1] * (b)[0]; \
+ }
/*! Vector perp -- assumes that n is of unit length
* accepts vector v, subtracts out any component parallel to n */
-#define VEC_PERPENDICULAR(vp,v,n) \
-{ \
- GREAL dot = VEC_DOT(v, n); \
- vp[0] = (v)[0] - dot*(n)[0]; \
- vp[1] = (v)[1] - dot*(n)[1]; \
- vp[2] = (v)[2] - dot*(n)[2]; \
-}\
-
+#define VEC_PERPENDICULAR(vp, v, n) \
+ { \
+ GREAL dot = VEC_DOT(v, n); \
+ vp[0] = (v)[0] - dot * (n)[0]; \
+ vp[1] = (v)[1] - dot * (n)[1]; \
+ vp[2] = (v)[2] - dot * (n)[2]; \
+ }
/*! Vector parallel -- assumes that n is of unit length */
-#define VEC_PARALLEL(vp,v,n) \
-{ \
- GREAL dot = VEC_DOT(v, n); \
- vp[0] = (dot) * (n)[0]; \
- vp[1] = (dot) * (n)[1]; \
- vp[2] = (dot) * (n)[2]; \
-}\
+#define VEC_PARALLEL(vp, v, n) \
+ { \
+ GREAL dot = VEC_DOT(v, n); \
+ vp[0] = (dot) * (n)[0]; \
+ vp[1] = (dot) * (n)[1]; \
+ vp[2] = (dot) * (n)[2]; \
+ }
/*! Same as Vector parallel -- n can have any length
* accepts vector v, subtracts out any component perpendicular to n */
-#define VEC_PROJECT(vp,v,n) \
-{ \
- GREAL scalar = VEC_DOT(v, n); \
- scalar/= VEC_DOT(n, n); \
- vp[0] = (scalar) * (n)[0]; \
- vp[1] = (scalar) * (n)[1]; \
- vp[2] = (scalar) * (n)[2]; \
-}\
-
+#define VEC_PROJECT(vp, v, n) \
+ { \
+ GREAL scalar = VEC_DOT(v, n); \
+ scalar /= VEC_DOT(n, n); \
+ vp[0] = (scalar) * (n)[0]; \
+ vp[1] = (scalar) * (n)[1]; \
+ vp[2] = (scalar) * (n)[2]; \
+ }
/*! accepts vector v*/
-#define VEC_UNPROJECT(vp,v,n) \
-{ \
- GREAL scalar = VEC_DOT(v, n); \
- scalar = VEC_DOT(n, n)/scalar; \
- vp[0] = (scalar) * (n)[0]; \
- vp[1] = (scalar) * (n)[1]; \
- vp[2] = (scalar) * (n)[2]; \
-}\
-
+#define VEC_UNPROJECT(vp, v, n) \
+ { \
+ GREAL scalar = VEC_DOT(v, n); \
+ scalar = VEC_DOT(n, n) / scalar; \
+ vp[0] = (scalar) * (n)[0]; \
+ vp[1] = (scalar) * (n)[1]; \
+ vp[2] = (scalar) * (n)[2]; \
+ }
/*! Vector reflection -- assumes n is of unit length
Takes vector v, reflects it against reflector n, and returns vr */
-#define VEC_REFLECT(vr,v,n) \
-{ \
- GREAL dot = VEC_DOT(v, n); \
- vr[0] = (v)[0] - 2.0 * (dot) * (n)[0]; \
- vr[1] = (v)[1] - 2.0 * (dot) * (n)[1]; \
- vr[2] = (v)[2] - 2.0 * (dot) * (n)[2]; \
-}\
-
+#define VEC_REFLECT(vr, v, n) \
+ { \
+ GREAL dot = VEC_DOT(v, n); \
+ vr[0] = (v)[0] - 2.0 * (dot) * (n)[0]; \
+ vr[1] = (v)[1] - 2.0 * (dot) * (n)[1]; \
+ vr[2] = (v)[2] - 2.0 * (dot) * (n)[2]; \
+ }
/*! Vector blending
Takes two vectors a, b, blends them together with two scalars */
-#define VEC_BLEND_AB(vr,sa,a,sb,b) \
-{ \
- vr[0] = (sa) * (a)[0] + (sb) * (b)[0]; \
- vr[1] = (sa) * (a)[1] + (sb) * (b)[1]; \
- vr[2] = (sa) * (a)[2] + (sb) * (b)[2]; \
-}\
+#define VEC_BLEND_AB(vr, sa, a, sb, b) \
+ { \
+ vr[0] = (sa) * (a)[0] + (sb) * (b)[0]; \
+ vr[1] = (sa) * (a)[1] + (sb) * (b)[1]; \
+ vr[2] = (sa) * (a)[2] + (sb) * (b)[2]; \
+ }
/*! Vector blending
Takes two vectors a, b, blends them together with s <=1 */
-#define VEC_BLEND(vr,a,b,s) VEC_BLEND_AB(vr,(1-s),a,s,b)
+#define VEC_BLEND(vr, a, b, s) VEC_BLEND_AB(vr, (1 - s), a, s, b)
-#define VEC_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];
+#define VEC_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];
//! Finds the bigger cartesian coordinate from a vector
-#define VEC_MAYOR_COORD(vec, maxc)\
-{\
- GREAL A[] = {fabs(vec[0]),fabs(vec[1]),fabs(vec[2])};\
- maxc = A[0]>A[1]?(A[0]>A[2]?0:2):(A[1]>A[2]?1:2);\
-}\
+#define VEC_MAYOR_COORD(vec, maxc) \
+ { \
+ GREAL A[] = {fabs(vec[0]), fabs(vec[1]), fabs(vec[2])}; \
+ maxc = A[0] > A[1] ? (A[0] > A[2] ? 0 : 2) : (A[1] > A[2] ? 1 : 2); \
+ }
//! Finds the 2 smallest cartesian coordinates from a vector
-#define VEC_MINOR_AXES(vec, i0, i1)\
-{\
- VEC_MAYOR_COORD(vec,i0);\
- i0 = (i0+1)%3;\
- i1 = (i0+1)%3;\
-}\
-
-
-
+#define VEC_MINOR_AXES(vec, i0, i1) \
+ { \
+ VEC_MAYOR_COORD(vec, i0); \
+ i0 = (i0 + 1) % 3; \
+ i1 = (i0 + 1) % 3; \
+ }
-#define VEC_EQUAL(v1,v2) (v1[0]==v2[0]&&v1[1]==v2[1]&&v1[2]==v2[2])
-
-#define VEC_NEAR_EQUAL(v1,v2) (GIM_NEAR_EQUAL(v1[0],v2[0])&&GIM_NEAR_EQUAL(v1[1],v2[1])&&GIM_NEAR_EQUAL(v1[2],v2[2]))
+#define VEC_EQUAL(v1, v2) (v1[0] == v2[0] && v1[1] == v2[1] && v1[2] == v2[2])
+#define VEC_NEAR_EQUAL(v1, v2) (GIM_NEAR_EQUAL(v1[0], v2[0]) && GIM_NEAR_EQUAL(v1[1], v2[1]) && GIM_NEAR_EQUAL(v1[2], v2[2]))
/// Vector cross
-#define X_AXIS_CROSS_VEC(dst,src)\
-{ \
- dst[0] = 0.0f; \
- dst[1] = -src[2]; \
- dst[2] = src[1]; \
-}\
-
-#define Y_AXIS_CROSS_VEC(dst,src)\
-{ \
- dst[0] = src[2]; \
- dst[1] = 0.0f; \
- dst[2] = -src[0]; \
-}\
-
-#define Z_AXIS_CROSS_VEC(dst,src)\
-{ \
- dst[0] = -src[1]; \
- dst[1] = src[0]; \
- dst[2] = 0.0f; \
-}\
-
-
-
-
-
+#define X_AXIS_CROSS_VEC(dst, src) \
+ { \
+ dst[0] = 0.0f; \
+ dst[1] = -src[2]; \
+ dst[2] = src[1]; \
+ }
+
+#define Y_AXIS_CROSS_VEC(dst, src) \
+ { \
+ dst[0] = src[2]; \
+ dst[1] = 0.0f; \
+ dst[2] = -src[0]; \
+ }
+
+#define Z_AXIS_CROSS_VEC(dst, src) \
+ { \
+ dst[0] = -src[1]; \
+ dst[1] = src[0]; \
+ dst[2] = 0.0f; \
+ }
/// initialize matrix
-#define IDENTIFY_MATRIX_3X3(m) \
-{ \
- m[0][0] = 1.0; \
- m[0][1] = 0.0; \
- m[0][2] = 0.0; \
- \
- m[1][0] = 0.0; \
- m[1][1] = 1.0; \
- m[1][2] = 0.0; \
- \
- m[2][0] = 0.0; \
- m[2][1] = 0.0; \
- m[2][2] = 1.0; \
-}\
+#define IDENTIFY_MATRIX_3X3(m) \
+ { \
+ m[0][0] = 1.0; \
+ m[0][1] = 0.0; \
+ m[0][2] = 0.0; \
+ \
+ m[1][0] = 0.0; \
+ m[1][1] = 1.0; \
+ m[1][2] = 0.0; \
+ \
+ m[2][0] = 0.0; \
+ m[2][1] = 0.0; \
+ m[2][2] = 1.0; \
+ }
/*! initialize matrix */
-#define IDENTIFY_MATRIX_4X4(m) \
-{ \
- m[0][0] = 1.0; \
- m[0][1] = 0.0; \
- m[0][2] = 0.0; \
- m[0][3] = 0.0; \
- \
- m[1][0] = 0.0; \
- m[1][1] = 1.0; \
- m[1][2] = 0.0; \
- m[1][3] = 0.0; \
- \
- m[2][0] = 0.0; \
- m[2][1] = 0.0; \
- m[2][2] = 1.0; \
- m[2][3] = 0.0; \
- \
- m[3][0] = 0.0; \
- m[3][1] = 0.0; \
- m[3][2] = 0.0; \
- m[3][3] = 1.0; \
-}\
+#define IDENTIFY_MATRIX_4X4(m) \
+ { \
+ m[0][0] = 1.0; \
+ m[0][1] = 0.0; \
+ m[0][2] = 0.0; \
+ m[0][3] = 0.0; \
+ \
+ m[1][0] = 0.0; \
+ m[1][1] = 1.0; \
+ m[1][2] = 0.0; \
+ m[1][3] = 0.0; \
+ \
+ m[2][0] = 0.0; \
+ m[2][1] = 0.0; \
+ m[2][2] = 1.0; \
+ m[2][3] = 0.0; \
+ \
+ m[3][0] = 0.0; \
+ m[3][1] = 0.0; \
+ m[3][2] = 0.0; \
+ m[3][3] = 1.0; \
+ }
/*! initialize matrix */
-#define ZERO_MATRIX_4X4(m) \
-{ \
- m[0][0] = 0.0; \
- m[0][1] = 0.0; \
- m[0][2] = 0.0; \
- m[0][3] = 0.0; \
- \
- m[1][0] = 0.0; \
- m[1][1] = 0.0; \
- m[1][2] = 0.0; \
- m[1][3] = 0.0; \
- \
- m[2][0] = 0.0; \
- m[2][1] = 0.0; \
- m[2][2] = 0.0; \
- m[2][3] = 0.0; \
- \
- m[3][0] = 0.0; \
- m[3][1] = 0.0; \
- m[3][2] = 0.0; \
- m[3][3] = 0.0; \
-}\
+#define ZERO_MATRIX_4X4(m) \
+ { \
+ m[0][0] = 0.0; \
+ m[0][1] = 0.0; \
+ m[0][2] = 0.0; \
+ m[0][3] = 0.0; \
+ \
+ m[1][0] = 0.0; \
+ m[1][1] = 0.0; \
+ m[1][2] = 0.0; \
+ m[1][3] = 0.0; \
+ \
+ m[2][0] = 0.0; \
+ m[2][1] = 0.0; \
+ m[2][2] = 0.0; \
+ m[2][3] = 0.0; \
+ \
+ m[3][0] = 0.0; \
+ m[3][1] = 0.0; \
+ m[3][2] = 0.0; \
+ m[3][3] = 0.0; \
+ }
/*! matrix rotation X */
-#define ROTX_CS(m,cosine,sine) \
-{ \
- /* rotation about the x-axis */ \
- \
- m[0][0] = 1.0; \
- m[0][1] = 0.0; \
- m[0][2] = 0.0; \
- m[0][3] = 0.0; \
- \
- m[1][0] = 0.0; \
- m[1][1] = (cosine); \
- m[1][2] = (sine); \
- m[1][3] = 0.0; \
- \
- m[2][0] = 0.0; \
- m[2][1] = -(sine); \
- m[2][2] = (cosine); \
- m[2][3] = 0.0; \
- \
- m[3][0] = 0.0; \
- m[3][1] = 0.0; \
- m[3][2] = 0.0; \
- m[3][3] = 1.0; \
-}\
+#define ROTX_CS(m, cosine, sine) \
+ { \
+ /* rotation about the x-axis */ \
+ \
+ m[0][0] = 1.0; \
+ m[0][1] = 0.0; \
+ m[0][2] = 0.0; \
+ m[0][3] = 0.0; \
+ \
+ m[1][0] = 0.0; \
+ m[1][1] = (cosine); \
+ m[1][2] = (sine); \
+ m[1][3] = 0.0; \
+ \
+ m[2][0] = 0.0; \
+ m[2][1] = -(sine); \
+ m[2][2] = (cosine); \
+ m[2][3] = 0.0; \
+ \
+ m[3][0] = 0.0; \
+ m[3][1] = 0.0; \
+ m[3][2] = 0.0; \
+ m[3][3] = 1.0; \
+ }
/*! matrix rotation Y */
-#define ROTY_CS(m,cosine,sine) \
-{ \
- /* rotation about the y-axis */ \
- \
- m[0][0] = (cosine); \
- m[0][1] = 0.0; \
- m[0][2] = -(sine); \
- m[0][3] = 0.0; \
- \
- m[1][0] = 0.0; \
- m[1][1] = 1.0; \
- m[1][2] = 0.0; \
- m[1][3] = 0.0; \
- \
- m[2][0] = (sine); \
- m[2][1] = 0.0; \
- m[2][2] = (cosine); \
- m[2][3] = 0.0; \
- \
- m[3][0] = 0.0; \
- m[3][1] = 0.0; \
- m[3][2] = 0.0; \
- m[3][3] = 1.0; \
-}\
+#define ROTY_CS(m, cosine, sine) \
+ { \
+ /* rotation about the y-axis */ \
+ \
+ m[0][0] = (cosine); \
+ m[0][1] = 0.0; \
+ m[0][2] = -(sine); \
+ m[0][3] = 0.0; \
+ \
+ m[1][0] = 0.0; \
+ m[1][1] = 1.0; \
+ m[1][2] = 0.0; \
+ m[1][3] = 0.0; \
+ \
+ m[2][0] = (sine); \
+ m[2][1] = 0.0; \
+ m[2][2] = (cosine); \
+ m[2][3] = 0.0; \
+ \
+ m[3][0] = 0.0; \
+ m[3][1] = 0.0; \
+ m[3][2] = 0.0; \
+ m[3][3] = 1.0; \
+ }
/*! matrix rotation Z */
-#define ROTZ_CS(m,cosine,sine) \
-{ \
- /* rotation about the z-axis */ \
- \
- m[0][0] = (cosine); \
- m[0][1] = (sine); \
- m[0][2] = 0.0; \
- m[0][3] = 0.0; \
- \
- m[1][0] = -(sine); \
- m[1][1] = (cosine); \
- m[1][2] = 0.0; \
- m[1][3] = 0.0; \
- \
- m[2][0] = 0.0; \
- m[2][1] = 0.0; \
- m[2][2] = 1.0; \
- m[2][3] = 0.0; \
- \
- m[3][0] = 0.0; \
- m[3][1] = 0.0; \
- m[3][2] = 0.0; \
- m[3][3] = 1.0; \
-}\
+#define ROTZ_CS(m, cosine, sine) \
+ { \
+ /* rotation about the z-axis */ \
+ \
+ m[0][0] = (cosine); \
+ m[0][1] = (sine); \
+ m[0][2] = 0.0; \
+ m[0][3] = 0.0; \
+ \
+ m[1][0] = -(sine); \
+ m[1][1] = (cosine); \
+ m[1][2] = 0.0; \
+ m[1][3] = 0.0; \
+ \
+ m[2][0] = 0.0; \
+ m[2][1] = 0.0; \
+ m[2][2] = 1.0; \
+ m[2][3] = 0.0; \
+ \
+ m[3][0] = 0.0; \
+ m[3][1] = 0.0; \
+ m[3][2] = 0.0; \
+ m[3][3] = 1.0; \
+ }
/*! matrix copy */
-#define COPY_MATRIX_2X2(b,a) \
-{ \
- b[0][0] = a[0][0]; \
- b[0][1] = a[0][1]; \
- \
- b[1][0] = a[1][0]; \
- b[1][1] = a[1][1]; \
- \
-}\
-
+#define COPY_MATRIX_2X2(b, a) \
+ { \
+ b[0][0] = a[0][0]; \
+ b[0][1] = a[0][1]; \
+ \
+ b[1][0] = a[1][0]; \
+ b[1][1] = a[1][1]; \
+ }
/*! matrix copy */
-#define COPY_MATRIX_2X3(b,a) \
-{ \
- b[0][0] = a[0][0]; \
- b[0][1] = a[0][1]; \
- b[0][2] = a[0][2]; \
- \
- b[1][0] = a[1][0]; \
- b[1][1] = a[1][1]; \
- b[1][2] = a[1][2]; \
-}\
-
+#define COPY_MATRIX_2X3(b, a) \
+ { \
+ b[0][0] = a[0][0]; \
+ b[0][1] = a[0][1]; \
+ b[0][2] = a[0][2]; \
+ \
+ b[1][0] = a[1][0]; \
+ b[1][1] = a[1][1]; \
+ b[1][2] = a[1][2]; \
+ }
/*! matrix copy */
-#define COPY_MATRIX_3X3(b,a) \
-{ \
- b[0][0] = a[0][0]; \
- b[0][1] = a[0][1]; \
- b[0][2] = a[0][2]; \
- \
- b[1][0] = a[1][0]; \
- b[1][1] = a[1][1]; \
- b[1][2] = a[1][2]; \
- \
- b[2][0] = a[2][0]; \
- b[2][1] = a[2][1]; \
- b[2][2] = a[2][2]; \
-}\
-
+#define COPY_MATRIX_3X3(b, a) \
+ { \
+ b[0][0] = a[0][0]; \
+ b[0][1] = a[0][1]; \
+ b[0][2] = a[0][2]; \
+ \
+ b[1][0] = a[1][0]; \
+ b[1][1] = a[1][1]; \
+ b[1][2] = a[1][2]; \
+ \
+ b[2][0] = a[2][0]; \
+ b[2][1] = a[2][1]; \
+ b[2][2] = a[2][2]; \
+ }
/*! matrix copy */
-#define COPY_MATRIX_4X4(b,a) \
-{ \
- b[0][0] = a[0][0]; \
- b[0][1] = a[0][1]; \
- b[0][2] = a[0][2]; \
- b[0][3] = a[0][3]; \
- \
- b[1][0] = a[1][0]; \
- b[1][1] = a[1][1]; \
- b[1][2] = a[1][2]; \
- b[1][3] = a[1][3]; \
- \
- b[2][0] = a[2][0]; \
- b[2][1] = a[2][1]; \
- b[2][2] = a[2][2]; \
- b[2][3] = a[2][3]; \
- \
- b[3][0] = a[3][0]; \
- b[3][1] = a[3][1]; \
- b[3][2] = a[3][2]; \
- b[3][3] = a[3][3]; \
-}\
-
+#define COPY_MATRIX_4X4(b, a) \
+ { \
+ b[0][0] = a[0][0]; \
+ b[0][1] = a[0][1]; \
+ b[0][2] = a[0][2]; \
+ b[0][3] = a[0][3]; \
+ \
+ b[1][0] = a[1][0]; \
+ b[1][1] = a[1][1]; \
+ b[1][2] = a[1][2]; \
+ b[1][3] = a[1][3]; \
+ \
+ b[2][0] = a[2][0]; \
+ b[2][1] = a[2][1]; \
+ b[2][2] = a[2][2]; \
+ b[2][3] = a[2][3]; \
+ \
+ b[3][0] = a[3][0]; \
+ b[3][1] = a[3][1]; \
+ b[3][2] = a[3][2]; \
+ b[3][3] = a[3][3]; \
+ }
/*! matrix transpose */
-#define TRANSPOSE_MATRIX_2X2(b,a) \
-{ \
- b[0][0] = a[0][0]; \
- b[0][1] = a[1][0]; \
- \
- b[1][0] = a[0][1]; \
- b[1][1] = a[1][1]; \
-}\
-
+#define TRANSPOSE_MATRIX_2X2(b, a) \
+ { \
+ b[0][0] = a[0][0]; \
+ b[0][1] = a[1][0]; \
+ \
+ b[1][0] = a[0][1]; \
+ b[1][1] = a[1][1]; \
+ }
/*! matrix transpose */
-#define TRANSPOSE_MATRIX_3X3(b,a) \
-{ \
- b[0][0] = a[0][0]; \
- b[0][1] = a[1][0]; \
- b[0][2] = a[2][0]; \
- \
- b[1][0] = a[0][1]; \
- b[1][1] = a[1][1]; \
- b[1][2] = a[2][1]; \
- \
- b[2][0] = a[0][2]; \
- b[2][1] = a[1][2]; \
- b[2][2] = a[2][2]; \
-}\
-
+#define TRANSPOSE_MATRIX_3X3(b, a) \
+ { \
+ b[0][0] = a[0][0]; \
+ b[0][1] = a[1][0]; \
+ b[0][2] = a[2][0]; \
+ \
+ b[1][0] = a[0][1]; \
+ b[1][1] = a[1][1]; \
+ b[1][2] = a[2][1]; \
+ \
+ b[2][0] = a[0][2]; \
+ b[2][1] = a[1][2]; \
+ b[2][2] = a[2][2]; \
+ }
/*! matrix transpose */
-#define TRANSPOSE_MATRIX_4X4(b,a) \
-{ \
- b[0][0] = a[0][0]; \
- b[0][1] = a[1][0]; \
- b[0][2] = a[2][0]; \
- b[0][3] = a[3][0]; \
- \
- b[1][0] = a[0][1]; \
- b[1][1] = a[1][1]; \
- b[1][2] = a[2][1]; \
- b[1][3] = a[3][1]; \
- \
- b[2][0] = a[0][2]; \
- b[2][1] = a[1][2]; \
- b[2][2] = a[2][2]; \
- b[2][3] = a[3][2]; \
- \
- b[3][0] = a[0][3]; \
- b[3][1] = a[1][3]; \
- b[3][2] = a[2][3]; \
- b[3][3] = a[3][3]; \
-}\
-
+#define TRANSPOSE_MATRIX_4X4(b, a) \
+ { \
+ b[0][0] = a[0][0]; \
+ b[0][1] = a[1][0]; \
+ b[0][2] = a[2][0]; \
+ b[0][3] = a[3][0]; \
+ \
+ b[1][0] = a[0][1]; \
+ b[1][1] = a[1][1]; \
+ b[1][2] = a[2][1]; \
+ b[1][3] = a[3][1]; \
+ \
+ b[2][0] = a[0][2]; \
+ b[2][1] = a[1][2]; \
+ b[2][2] = a[2][2]; \
+ b[2][3] = a[3][2]; \
+ \
+ b[3][0] = a[0][3]; \
+ b[3][1] = a[1][3]; \
+ b[3][2] = a[2][3]; \
+ b[3][3] = a[3][3]; \
+ }
/*! multiply matrix by scalar */
-#define SCALE_MATRIX_2X2(b,s,a) \
-{ \
- b[0][0] = (s) * a[0][0]; \
- b[0][1] = (s) * a[0][1]; \
- \
- b[1][0] = (s) * a[1][0]; \
- b[1][1] = (s) * a[1][1]; \
-}\
-
+#define SCALE_MATRIX_2X2(b, s, a) \
+ { \
+ b[0][0] = (s)*a[0][0]; \
+ b[0][1] = (s)*a[0][1]; \
+ \
+ b[1][0] = (s)*a[1][0]; \
+ b[1][1] = (s)*a[1][1]; \
+ }
/*! multiply matrix by scalar */
-#define SCALE_MATRIX_3X3(b,s,a) \
-{ \
- b[0][0] = (s) * a[0][0]; \
- b[0][1] = (s) * a[0][1]; \
- b[0][2] = (s) * a[0][2]; \
- \
- b[1][0] = (s) * a[1][0]; \
- b[1][1] = (s) * a[1][1]; \
- b[1][2] = (s) * a[1][2]; \
- \
- b[2][0] = (s) * a[2][0]; \
- b[2][1] = (s) * a[2][1]; \
- b[2][2] = (s) * a[2][2]; \
-}\
-
+#define SCALE_MATRIX_3X3(b, s, a) \
+ { \
+ b[0][0] = (s)*a[0][0]; \
+ b[0][1] = (s)*a[0][1]; \
+ b[0][2] = (s)*a[0][2]; \
+ \
+ b[1][0] = (s)*a[1][0]; \
+ b[1][1] = (s)*a[1][1]; \
+ b[1][2] = (s)*a[1][2]; \
+ \
+ b[2][0] = (s)*a[2][0]; \
+ b[2][1] = (s)*a[2][1]; \
+ b[2][2] = (s)*a[2][2]; \
+ }
/*! multiply matrix by scalar */
-#define SCALE_MATRIX_4X4(b,s,a) \
-{ \
- b[0][0] = (s) * a[0][0]; \
- b[0][1] = (s) * a[0][1]; \
- b[0][2] = (s) * a[0][2]; \
- b[0][3] = (s) * a[0][3]; \
- \
- b[1][0] = (s) * a[1][0]; \
- b[1][1] = (s) * a[1][1]; \
- b[1][2] = (s) * a[1][2]; \
- b[1][3] = (s) * a[1][3]; \
- \
- b[2][0] = (s) * a[2][0]; \
- b[2][1] = (s) * a[2][1]; \
- b[2][2] = (s) * a[2][2]; \
- b[2][3] = (s) * a[2][3]; \
- \
- b[3][0] = s * a[3][0]; \
- b[3][1] = s * a[3][1]; \
- b[3][2] = s * a[3][2]; \
- b[3][3] = s * a[3][3]; \
-}\
-
+#define SCALE_MATRIX_4X4(b, s, a) \
+ { \
+ b[0][0] = (s)*a[0][0]; \
+ b[0][1] = (s)*a[0][1]; \
+ b[0][2] = (s)*a[0][2]; \
+ b[0][3] = (s)*a[0][3]; \
+ \
+ b[1][0] = (s)*a[1][0]; \
+ b[1][1] = (s)*a[1][1]; \
+ b[1][2] = (s)*a[1][2]; \
+ b[1][3] = (s)*a[1][3]; \
+ \
+ b[2][0] = (s)*a[2][0]; \
+ b[2][1] = (s)*a[2][1]; \
+ b[2][2] = (s)*a[2][2]; \
+ b[2][3] = (s)*a[2][3]; \
+ \
+ b[3][0] = s * a[3][0]; \
+ b[3][1] = s * a[3][1]; \
+ b[3][2] = s * a[3][2]; \
+ b[3][3] = s * a[3][3]; \
+ }
/*! multiply matrix by scalar */
-#define SCALE_VEC_MATRIX_2X2(b,svec,a) \
-{ \
- b[0][0] = svec[0] * a[0][0]; \
- b[1][0] = svec[0] * a[1][0]; \
- \
- b[0][1] = svec[1] * a[0][1]; \
- b[1][1] = svec[1] * a[1][1]; \
-}\
-
+#define SCALE_VEC_MATRIX_2X2(b, svec, a) \
+ { \
+ b[0][0] = svec[0] * a[0][0]; \
+ b[1][0] = svec[0] * a[1][0]; \
+ \
+ b[0][1] = svec[1] * a[0][1]; \
+ b[1][1] = svec[1] * a[1][1]; \
+ }
/*! multiply matrix by scalar. Each columns is scaled by each scalar vector component */
-#define SCALE_VEC_MATRIX_3X3(b,svec,a) \
-{ \
- b[0][0] = svec[0] * a[0][0]; \
- b[1][0] = svec[0] * a[1][0]; \
- b[2][0] = svec[0] * a[2][0]; \
- \
- b[0][1] = svec[1] * a[0][1]; \
- b[1][1] = svec[1] * a[1][1]; \
- b[2][1] = svec[1] * a[2][1]; \
- \
- b[0][2] = svec[2] * a[0][2]; \
- b[1][2] = svec[2] * a[1][2]; \
- b[2][2] = svec[2] * a[2][2]; \
-}\
-
+#define SCALE_VEC_MATRIX_3X3(b, svec, a) \
+ { \
+ b[0][0] = svec[0] * a[0][0]; \
+ b[1][0] = svec[0] * a[1][0]; \
+ b[2][0] = svec[0] * a[2][0]; \
+ \
+ b[0][1] = svec[1] * a[0][1]; \
+ b[1][1] = svec[1] * a[1][1]; \
+ b[2][1] = svec[1] * a[2][1]; \
+ \
+ b[0][2] = svec[2] * a[0][2]; \
+ b[1][2] = svec[2] * a[1][2]; \
+ b[2][2] = svec[2] * a[2][2]; \
+ }
/*! multiply matrix by scalar */
-#define SCALE_VEC_MATRIX_4X4(b,svec,a) \
-{ \
- b[0][0] = svec[0] * a[0][0]; \
- b[1][0] = svec[0] * a[1][0]; \
- b[2][0] = svec[0] * a[2][0]; \
- b[3][0] = svec[0] * a[3][0]; \
- \
- b[0][1] = svec[1] * a[0][1]; \
- b[1][1] = svec[1] * a[1][1]; \
- b[2][1] = svec[1] * a[2][1]; \
- b[3][1] = svec[1] * a[3][1]; \
- \
- b[0][2] = svec[2] * a[0][2]; \
- b[1][2] = svec[2] * a[1][2]; \
- b[2][2] = svec[2] * a[2][2]; \
- b[3][2] = svec[2] * a[3][2]; \
- \
- b[0][3] = svec[3] * a[0][3]; \
- b[1][3] = svec[3] * a[1][3]; \
- b[2][3] = svec[3] * a[2][3]; \
- b[3][3] = svec[3] * a[3][3]; \
-}\
-
+#define SCALE_VEC_MATRIX_4X4(b, svec, a) \
+ { \
+ b[0][0] = svec[0] * a[0][0]; \
+ b[1][0] = svec[0] * a[1][0]; \
+ b[2][0] = svec[0] * a[2][0]; \
+ b[3][0] = svec[0] * a[3][0]; \
+ \
+ b[0][1] = svec[1] * a[0][1]; \
+ b[1][1] = svec[1] * a[1][1]; \
+ b[2][1] = svec[1] * a[2][1]; \
+ b[3][1] = svec[1] * a[3][1]; \
+ \
+ b[0][2] = svec[2] * a[0][2]; \
+ b[1][2] = svec[2] * a[1][2]; \
+ b[2][2] = svec[2] * a[2][2]; \
+ b[3][2] = svec[2] * a[3][2]; \
+ \
+ b[0][3] = svec[3] * a[0][3]; \
+ b[1][3] = svec[3] * a[1][3]; \
+ b[2][3] = svec[3] * a[2][3]; \
+ b[3][3] = svec[3] * a[3][3]; \
+ }
/*! multiply matrix by scalar */
-#define ACCUM_SCALE_MATRIX_2X2(b,s,a) \
-{ \
- b[0][0] += (s) * a[0][0]; \
- b[0][1] += (s) * a[0][1]; \
- \
- b[1][0] += (s) * a[1][0]; \
- b[1][1] += (s) * a[1][1]; \
-}\
-
+#define ACCUM_SCALE_MATRIX_2X2(b, s, a) \
+ { \
+ b[0][0] += (s)*a[0][0]; \
+ b[0][1] += (s)*a[0][1]; \
+ \
+ b[1][0] += (s)*a[1][0]; \
+ b[1][1] += (s)*a[1][1]; \
+ }
/*! multiply matrix by scalar */
-#define ACCUM_SCALE_MATRIX_3X3(b,s,a) \
-{ \
- b[0][0] += (s) * a[0][0]; \
- b[0][1] += (s) * a[0][1]; \
- b[0][2] += (s) * a[0][2]; \
- \
- b[1][0] += (s) * a[1][0]; \
- b[1][1] += (s) * a[1][1]; \
- b[1][2] += (s) * a[1][2]; \
- \
- b[2][0] += (s) * a[2][0]; \
- b[2][1] += (s) * a[2][1]; \
- b[2][2] += (s) * a[2][2]; \
-}\
-
+#define ACCUM_SCALE_MATRIX_3X3(b, s, a) \
+ { \
+ b[0][0] += (s)*a[0][0]; \
+ b[0][1] += (s)*a[0][1]; \
+ b[0][2] += (s)*a[0][2]; \
+ \
+ b[1][0] += (s)*a[1][0]; \
+ b[1][1] += (s)*a[1][1]; \
+ b[1][2] += (s)*a[1][2]; \
+ \
+ b[2][0] += (s)*a[2][0]; \
+ b[2][1] += (s)*a[2][1]; \
+ b[2][2] += (s)*a[2][2]; \
+ }
/*! multiply matrix by scalar */
-#define ACCUM_SCALE_MATRIX_4X4(b,s,a) \
-{ \
- b[0][0] += (s) * a[0][0]; \
- b[0][1] += (s) * a[0][1]; \
- b[0][2] += (s) * a[0][2]; \
- b[0][3] += (s) * a[0][3]; \
- \
- b[1][0] += (s) * a[1][0]; \
- b[1][1] += (s) * a[1][1]; \
- b[1][2] += (s) * a[1][2]; \
- b[1][3] += (s) * a[1][3]; \
- \
- b[2][0] += (s) * a[2][0]; \
- b[2][1] += (s) * a[2][1]; \
- b[2][2] += (s) * a[2][2]; \
- b[2][3] += (s) * a[2][3]; \
- \
- b[3][0] += (s) * a[3][0]; \
- b[3][1] += (s) * a[3][1]; \
- b[3][2] += (s) * a[3][2]; \
- b[3][3] += (s) * a[3][3]; \
-}\
+#define ACCUM_SCALE_MATRIX_4X4(b, s, a) \
+ { \
+ b[0][0] += (s)*a[0][0]; \
+ b[0][1] += (s)*a[0][1]; \
+ b[0][2] += (s)*a[0][2]; \
+ b[0][3] += (s)*a[0][3]; \
+ \
+ b[1][0] += (s)*a[1][0]; \
+ b[1][1] += (s)*a[1][1]; \
+ b[1][2] += (s)*a[1][2]; \
+ b[1][3] += (s)*a[1][3]; \
+ \
+ b[2][0] += (s)*a[2][0]; \
+ b[2][1] += (s)*a[2][1]; \
+ b[2][2] += (s)*a[2][2]; \
+ b[2][3] += (s)*a[2][3]; \
+ \
+ b[3][0] += (s)*a[3][0]; \
+ b[3][1] += (s)*a[3][1]; \
+ b[3][2] += (s)*a[3][2]; \
+ b[3][3] += (s)*a[3][3]; \
+ }
/*! matrix product */
/*! c[x][y] = a[x][0]*b[0][y]+a[x][1]*b[1][y]+a[x][2]*b[2][y]+a[x][3]*b[3][y];*/
-#define MATRIX_PRODUCT_2X2(c,a,b) \
-{ \
- c[0][0] = a[0][0]*b[0][0]+a[0][1]*b[1][0]; \
- c[0][1] = a[0][0]*b[0][1]+a[0][1]*b[1][1]; \
- \
- c[1][0] = a[1][0]*b[0][0]+a[1][1]*b[1][0]; \
- c[1][1] = a[1][0]*b[0][1]+a[1][1]*b[1][1]; \
- \
-}\
+#define MATRIX_PRODUCT_2X2(c, a, b) \
+ { \
+ c[0][0] = a[0][0] * b[0][0] + a[0][1] * b[1][0]; \
+ c[0][1] = a[0][0] * b[0][1] + a[0][1] * b[1][1]; \
+ \
+ c[1][0] = a[1][0] * b[0][0] + a[1][1] * b[1][0]; \
+ c[1][1] = a[1][0] * b[0][1] + a[1][1] * b[1][1]; \
+ }
/*! matrix product */
/*! c[x][y] = a[x][0]*b[0][y]+a[x][1]*b[1][y]+a[x][2]*b[2][y]+a[x][3]*b[3][y];*/
-#define MATRIX_PRODUCT_3X3(c,a,b) \
-{ \
- c[0][0] = a[0][0]*b[0][0]+a[0][1]*b[1][0]+a[0][2]*b[2][0]; \
- c[0][1] = a[0][0]*b[0][1]+a[0][1]*b[1][1]+a[0][2]*b[2][1]; \
- c[0][2] = a[0][0]*b[0][2]+a[0][1]*b[1][2]+a[0][2]*b[2][2]; \
- \
- c[1][0] = a[1][0]*b[0][0]+a[1][1]*b[1][0]+a[1][2]*b[2][0]; \
- c[1][1] = a[1][0]*b[0][1]+a[1][1]*b[1][1]+a[1][2]*b[2][1]; \
- c[1][2] = a[1][0]*b[0][2]+a[1][1]*b[1][2]+a[1][2]*b[2][2]; \
- \
- c[2][0] = a[2][0]*b[0][0]+a[2][1]*b[1][0]+a[2][2]*b[2][0]; \
- c[2][1] = a[2][0]*b[0][1]+a[2][1]*b[1][1]+a[2][2]*b[2][1]; \
- c[2][2] = a[2][0]*b[0][2]+a[2][1]*b[1][2]+a[2][2]*b[2][2]; \
-}\
-
+#define MATRIX_PRODUCT_3X3(c, a, b) \
+ { \
+ c[0][0] = a[0][0] * b[0][0] + a[0][1] * b[1][0] + a[0][2] * b[2][0]; \
+ c[0][1] = a[0][0] * b[0][1] + a[0][1] * b[1][1] + a[0][2] * b[2][1]; \
+ c[0][2] = a[0][0] * b[0][2] + a[0][1] * b[1][2] + a[0][2] * b[2][2]; \
+ \
+ c[1][0] = a[1][0] * b[0][0] + a[1][1] * b[1][0] + a[1][2] * b[2][0]; \
+ c[1][1] = a[1][0] * b[0][1] + a[1][1] * b[1][1] + a[1][2] * b[2][1]; \
+ c[1][2] = a[1][0] * b[0][2] + a[1][1] * b[1][2] + a[1][2] * b[2][2]; \
+ \
+ c[2][0] = a[2][0] * b[0][0] + a[2][1] * b[1][0] + a[2][2] * b[2][0]; \
+ c[2][1] = a[2][0] * b[0][1] + a[2][1] * b[1][1] + a[2][2] * b[2][1]; \
+ c[2][2] = a[2][0] * b[0][2] + a[2][1] * b[1][2] + a[2][2] * b[2][2]; \
+ }
/*! matrix product */
/*! c[x][y] = a[x][0]*b[0][y]+a[x][1]*b[1][y]+a[x][2]*b[2][y]+a[x][3]*b[3][y];*/
-#define MATRIX_PRODUCT_4X4(c,a,b) \
-{ \
- c[0][0] = a[0][0]*b[0][0]+a[0][1]*b[1][0]+a[0][2]*b[2][0]+a[0][3]*b[3][0];\
- c[0][1] = a[0][0]*b[0][1]+a[0][1]*b[1][1]+a[0][2]*b[2][1]+a[0][3]*b[3][1];\
- c[0][2] = a[0][0]*b[0][2]+a[0][1]*b[1][2]+a[0][2]*b[2][2]+a[0][3]*b[3][2];\
- c[0][3] = a[0][0]*b[0][3]+a[0][1]*b[1][3]+a[0][2]*b[2][3]+a[0][3]*b[3][3];\
- \
- c[1][0] = a[1][0]*b[0][0]+a[1][1]*b[1][0]+a[1][2]*b[2][0]+a[1][3]*b[3][0];\
- c[1][1] = a[1][0]*b[0][1]+a[1][1]*b[1][1]+a[1][2]*b[2][1]+a[1][3]*b[3][1];\
- c[1][2] = a[1][0]*b[0][2]+a[1][1]*b[1][2]+a[1][2]*b[2][2]+a[1][3]*b[3][2];\
- c[1][3] = a[1][0]*b[0][3]+a[1][1]*b[1][3]+a[1][2]*b[2][3]+a[1][3]*b[3][3];\
- \
- c[2][0] = a[2][0]*b[0][0]+a[2][1]*b[1][0]+a[2][2]*b[2][0]+a[2][3]*b[3][0];\
- c[2][1] = a[2][0]*b[0][1]+a[2][1]*b[1][1]+a[2][2]*b[2][1]+a[2][3]*b[3][1];\
- c[2][2] = a[2][0]*b[0][2]+a[2][1]*b[1][2]+a[2][2]*b[2][2]+a[2][3]*b[3][2];\
- c[2][3] = a[2][0]*b[0][3]+a[2][1]*b[1][3]+a[2][2]*b[2][3]+a[2][3]*b[3][3];\
- \
- c[3][0] = a[3][0]*b[0][0]+a[3][1]*b[1][0]+a[3][2]*b[2][0]+a[3][3]*b[3][0];\
- c[3][1] = a[3][0]*b[0][1]+a[3][1]*b[1][1]+a[3][2]*b[2][1]+a[3][3]*b[3][1];\
- c[3][2] = a[3][0]*b[0][2]+a[3][1]*b[1][2]+a[3][2]*b[2][2]+a[3][3]*b[3][2];\
- c[3][3] = a[3][0]*b[0][3]+a[3][1]*b[1][3]+a[3][2]*b[2][3]+a[3][3]*b[3][3];\
-}\
-
+#define MATRIX_PRODUCT_4X4(c, a, b) \
+ { \
+ c[0][0] = a[0][0] * b[0][0] + a[0][1] * b[1][0] + a[0][2] * b[2][0] + a[0][3] * b[3][0]; \
+ c[0][1] = a[0][0] * b[0][1] + a[0][1] * b[1][1] + a[0][2] * b[2][1] + a[0][3] * b[3][1]; \
+ c[0][2] = a[0][0] * b[0][2] + a[0][1] * b[1][2] + a[0][2] * b[2][2] + a[0][3] * b[3][2]; \
+ c[0][3] = a[0][0] * b[0][3] + a[0][1] * b[1][3] + a[0][2] * b[2][3] + a[0][3] * b[3][3]; \
+ \
+ c[1][0] = a[1][0] * b[0][0] + a[1][1] * b[1][0] + a[1][2] * b[2][0] + a[1][3] * b[3][0]; \
+ c[1][1] = a[1][0] * b[0][1] + a[1][1] * b[1][1] + a[1][2] * b[2][1] + a[1][3] * b[3][1]; \
+ c[1][2] = a[1][0] * b[0][2] + a[1][1] * b[1][2] + a[1][2] * b[2][2] + a[1][3] * b[3][2]; \
+ c[1][3] = a[1][0] * b[0][3] + a[1][1] * b[1][3] + a[1][2] * b[2][3] + a[1][3] * b[3][3]; \
+ \
+ c[2][0] = a[2][0] * b[0][0] + a[2][1] * b[1][0] + a[2][2] * b[2][0] + a[2][3] * b[3][0]; \
+ c[2][1] = a[2][0] * b[0][1] + a[2][1] * b[1][1] + a[2][2] * b[2][1] + a[2][3] * b[3][1]; \
+ c[2][2] = a[2][0] * b[0][2] + a[2][1] * b[1][2] + a[2][2] * b[2][2] + a[2][3] * b[3][2]; \
+ c[2][3] = a[2][0] * b[0][3] + a[2][1] * b[1][3] + a[2][2] * b[2][3] + a[2][3] * b[3][3]; \
+ \
+ c[3][0] = a[3][0] * b[0][0] + a[3][1] * b[1][0] + a[3][2] * b[2][0] + a[3][3] * b[3][0]; \
+ c[3][1] = a[3][0] * b[0][1] + a[3][1] * b[1][1] + a[3][2] * b[2][1] + a[3][3] * b[3][1]; \
+ c[3][2] = a[3][0] * b[0][2] + a[3][1] * b[1][2] + a[3][2] * b[2][2] + a[3][3] * b[3][2]; \
+ c[3][3] = a[3][0] * b[0][3] + a[3][1] * b[1][3] + a[3][2] * b[2][3] + a[3][3] * b[3][3]; \
+ }
/*! matrix times vector */
-#define MAT_DOT_VEC_2X2(p,m,v) \
-{ \
- p[0] = m[0][0]*v[0] + m[0][1]*v[1]; \
- p[1] = m[1][0]*v[0] + m[1][1]*v[1]; \
-}\
-
+#define MAT_DOT_VEC_2X2(p, m, v) \
+ { \
+ p[0] = m[0][0] * v[0] + m[0][1] * v[1]; \
+ p[1] = m[1][0] * v[0] + m[1][1] * v[1]; \
+ }
/*! matrix times vector */
-#define MAT_DOT_VEC_3X3(p,m,v) \
-{ \
- p[0] = m[0][0]*v[0] + m[0][1]*v[1] + m[0][2]*v[2]; \
- p[1] = m[1][0]*v[0] + m[1][1]*v[1] + m[1][2]*v[2]; \
- p[2] = m[2][0]*v[0] + m[2][1]*v[1] + m[2][2]*v[2]; \
-}\
-
+#define MAT_DOT_VEC_3X3(p, m, v) \
+ { \
+ p[0] = m[0][0] * v[0] + m[0][1] * v[1] + m[0][2] * v[2]; \
+ p[1] = m[1][0] * v[0] + m[1][1] * v[1] + m[1][2] * v[2]; \
+ p[2] = m[2][0] * v[0] + m[2][1] * v[1] + m[2][2] * v[2]; \
+ }
/*! matrix times vector
v is a vec4f
*/
-#define MAT_DOT_VEC_4X4(p,m,v) \
-{ \
- p[0] = m[0][0]*v[0] + m[0][1]*v[1] + m[0][2]*v[2] + m[0][3]*v[3]; \
- p[1] = m[1][0]*v[0] + m[1][1]*v[1] + m[1][2]*v[2] + m[1][3]*v[3]; \
- p[2] = m[2][0]*v[0] + m[2][1]*v[1] + m[2][2]*v[2] + m[2][3]*v[3]; \
- p[3] = m[3][0]*v[0] + m[3][1]*v[1] + m[3][2]*v[2] + m[3][3]*v[3]; \
-}\
+#define MAT_DOT_VEC_4X4(p, m, v) \
+ { \
+ p[0] = m[0][0] * v[0] + m[0][1] * v[1] + m[0][2] * v[2] + m[0][3] * v[3]; \
+ p[1] = m[1][0] * v[0] + m[1][1] * v[1] + m[1][2] * v[2] + m[1][3] * v[3]; \
+ p[2] = m[2][0] * v[0] + m[2][1] * v[1] + m[2][2] * v[2] + m[2][3] * v[3]; \
+ p[3] = m[3][0] * v[0] + m[3][1] * v[1] + m[3][2] * v[2] + m[3][3] * v[3]; \
+ }
/*! matrix times vector
v is a vec3f
and m is a mat4f<br>
Last column is added as the position
*/
-#define MAT_DOT_VEC_3X4(p,m,v) \
-{ \
- p[0] = m[0][0]*v[0] + m[0][1]*v[1] + m[0][2]*v[2] + m[0][3]; \
- p[1] = m[1][0]*v[0] + m[1][1]*v[1] + m[1][2]*v[2] + m[1][3]; \
- p[2] = m[2][0]*v[0] + m[2][1]*v[1] + m[2][2]*v[2] + m[2][3]; \
-}\
-
+#define MAT_DOT_VEC_3X4(p, m, v) \
+ { \
+ p[0] = m[0][0] * v[0] + m[0][1] * v[1] + m[0][2] * v[2] + m[0][3]; \
+ p[1] = m[1][0] * v[0] + m[1][1] * v[1] + m[1][2] * v[2] + m[1][3]; \
+ p[2] = m[2][0] * v[0] + m[2][1] * v[1] + m[2][2] * v[2] + m[2][3]; \
+ }
/*! vector transpose times matrix */
/*! p[j] = v[0]*m[0][j] + v[1]*m[1][j] + v[2]*m[2][j]; */
-#define VEC_DOT_MAT_3X3(p,v,m) \
-{ \
- p[0] = v[0]*m[0][0] + v[1]*m[1][0] + v[2]*m[2][0]; \
- p[1] = v[0]*m[0][1] + v[1]*m[1][1] + v[2]*m[2][1]; \
- p[2] = v[0]*m[0][2] + v[1]*m[1][2] + v[2]*m[2][2]; \
-}\
-
+#define VEC_DOT_MAT_3X3(p, v, m) \
+ { \
+ p[0] = v[0] * m[0][0] + v[1] * m[1][0] + v[2] * m[2][0]; \
+ p[1] = v[0] * m[0][1] + v[1] * m[1][1] + v[2] * m[2][1]; \
+ p[2] = v[0] * m[0][2] + v[1] * m[1][2] + v[2] * m[2][2]; \
+ }
/*! affine matrix times vector */
/** The matrix is assumed to be an affine matrix, with last two
* entries representing a translation */
-#define MAT_DOT_VEC_2X3(p,m,v) \
-{ \
- p[0] = m[0][0]*v[0] + m[0][1]*v[1] + m[0][2]; \
- p[1] = m[1][0]*v[0] + m[1][1]*v[1] + m[1][2]; \
-}\
+#define MAT_DOT_VEC_2X3(p, m, v) \
+ { \
+ p[0] = m[0][0] * v[0] + m[0][1] * v[1] + m[0][2]; \
+ p[1] = m[1][0] * v[0] + m[1][1] * v[1] + m[1][2]; \
+ }
//! Transform a plane
-#define MAT_TRANSFORM_PLANE_4X4(pout,m,plane)\
-{ \
- pout[0] = m[0][0]*plane[0] + m[0][1]*plane[1] + m[0][2]*plane[2];\
- pout[1] = m[1][0]*plane[0] + m[1][1]*plane[1] + m[1][2]*plane[2];\
- pout[2] = m[2][0]*plane[0] + m[2][1]*plane[1] + m[2][2]*plane[2];\
- pout[3] = m[0][3]*pout[0] + m[1][3]*pout[1] + m[2][3]*pout[2] + plane[3];\
-}\
-
-
+#define MAT_TRANSFORM_PLANE_4X4(pout, m, plane) \
+ { \
+ pout[0] = m[0][0] * plane[0] + m[0][1] * plane[1] + m[0][2] * plane[2]; \
+ pout[1] = m[1][0] * plane[0] + m[1][1] * plane[1] + m[1][2] * plane[2]; \
+ pout[2] = m[2][0] * plane[0] + m[2][1] * plane[1] + m[2][2] * plane[2]; \
+ pout[3] = m[0][3] * pout[0] + m[1][3] * pout[1] + m[2][3] * pout[2] + plane[3]; \
+ }
/** inverse transpose of matrix times vector
*
@@ -1000,22 +938,22 @@ Last column is added as the position
* It will leave normals the wrong length !!!
* See macro below for use on normals.
*/
-#define INV_TRANSP_MAT_DOT_VEC_2X2(p,m,v) \
-{ \
- GREAL det; \
- \
- det = m[0][0]*m[1][1] - m[0][1]*m[1][0]; \
- p[0] = m[1][1]*v[0] - m[1][0]*v[1]; \
- p[1] = - m[0][1]*v[0] + m[0][0]*v[1]; \
- \
- /* if matrix not singular, and not orthonormal, then renormalize */ \
- if ((det!=1.0f) && (det != 0.0f)) { \
- det = 1.0f / det; \
- p[0] *= det; \
- p[1] *= det; \
- } \
-}\
-
+#define INV_TRANSP_MAT_DOT_VEC_2X2(p, m, v) \
+ { \
+ GREAL det; \
+ \
+ det = m[0][0] * m[1][1] - m[0][1] * m[1][0]; \
+ p[0] = m[1][1] * v[0] - m[1][0] * v[1]; \
+ p[1] = -m[0][1] * v[0] + m[0][0] * v[1]; \
+ \
+ /* if matrix not singular, and not orthonormal, then renormalize */ \
+ if ((det != 1.0f) && (det != 0.0f)) \
+ { \
+ det = 1.0f / det; \
+ p[0] *= det; \
+ p[1] *= det; \
+ } \
+ }
/** transform normal vector by inverse transpose of matrix
* and then renormalize the vector
@@ -1024,550 +962,527 @@ Last column is added as the position
* and multiplies vector v into it, to yeild vector p
* Vector p is then normalized.
*/
-#define NORM_XFORM_2X2(p,m,v) \
-{ \
- GREAL len; \
- \
- /* do nothing if off-diagonals are zero and diagonals are \
- * equal */ \
- if ((m[0][1] != 0.0) || (m[1][0] != 0.0) || (m[0][0] != m[1][1])) { \
- p[0] = m[1][1]*v[0] - m[1][0]*v[1]; \
- p[1] = - m[0][1]*v[0] + m[0][0]*v[1]; \
- \
- len = p[0]*p[0] + p[1]*p[1]; \
- GIM_INV_SQRT(len,len); \
- p[0] *= len; \
- p[1] *= len; \
- } else { \
- VEC_COPY_2 (p, v); \
- } \
-}\
-
+#define NORM_XFORM_2X2(p, m, v) \
+ { \
+ GREAL len; \
+ \
+ /* do nothing if off-diagonals are zero and diagonals are \
+ * equal */ \
+ if ((m[0][1] != 0.0) || (m[1][0] != 0.0) || (m[0][0] != m[1][1])) \
+ { \
+ p[0] = m[1][1] * v[0] - m[1][0] * v[1]; \
+ p[1] = -m[0][1] * v[0] + m[0][0] * v[1]; \
+ \
+ len = p[0] * p[0] + p[1] * p[1]; \
+ GIM_INV_SQRT(len, len); \
+ p[0] *= len; \
+ p[1] *= len; \
+ } \
+ else \
+ { \
+ VEC_COPY_2(p, v); \
+ } \
+ }
/** outer product of vector times vector transpose
*
* The outer product of vector v and vector transpose t yeilds
* dyadic matrix m.
*/
-#define OUTER_PRODUCT_2X2(m,v,t) \
-{ \
- m[0][0] = v[0] * t[0]; \
- m[0][1] = v[0] * t[1]; \
- \
- m[1][0] = v[1] * t[0]; \
- m[1][1] = v[1] * t[1]; \
-}\
-
+#define OUTER_PRODUCT_2X2(m, v, t) \
+ { \
+ m[0][0] = v[0] * t[0]; \
+ m[0][1] = v[0] * t[1]; \
+ \
+ m[1][0] = v[1] * t[0]; \
+ m[1][1] = v[1] * t[1]; \
+ }
/** outer product of vector times vector transpose
*
* The outer product of vector v and vector transpose t yeilds
* dyadic matrix m.
*/
-#define OUTER_PRODUCT_3X3(m,v,t) \
-{ \
- m[0][0] = v[0] * t[0]; \
- m[0][1] = v[0] * t[1]; \
- m[0][2] = v[0] * t[2]; \
- \
- m[1][0] = v[1] * t[0]; \
- m[1][1] = v[1] * t[1]; \
- m[1][2] = v[1] * t[2]; \
- \
- m[2][0] = v[2] * t[0]; \
- m[2][1] = v[2] * t[1]; \
- m[2][2] = v[2] * t[2]; \
-}\
-
+#define OUTER_PRODUCT_3X3(m, v, t) \
+ { \
+ m[0][0] = v[0] * t[0]; \
+ m[0][1] = v[0] * t[1]; \
+ m[0][2] = v[0] * t[2]; \
+ \
+ m[1][0] = v[1] * t[0]; \
+ m[1][1] = v[1] * t[1]; \
+ m[1][2] = v[1] * t[2]; \
+ \
+ m[2][0] = v[2] * t[0]; \
+ m[2][1] = v[2] * t[1]; \
+ m[2][2] = v[2] * t[2]; \
+ }
/** outer product of vector times vector transpose
*
* The outer product of vector v and vector transpose t yeilds
* dyadic matrix m.
*/
-#define OUTER_PRODUCT_4X4(m,v,t) \
-{ \
- m[0][0] = v[0] * t[0]; \
- m[0][1] = v[0] * t[1]; \
- m[0][2] = v[0] * t[2]; \
- m[0][3] = v[0] * t[3]; \
- \
- m[1][0] = v[1] * t[0]; \
- m[1][1] = v[1] * t[1]; \
- m[1][2] = v[1] * t[2]; \
- m[1][3] = v[1] * t[3]; \
- \
- m[2][0] = v[2] * t[0]; \
- m[2][1] = v[2] * t[1]; \
- m[2][2] = v[2] * t[2]; \
- m[2][3] = v[2] * t[3]; \
- \
- m[3][0] = v[3] * t[0]; \
- m[3][1] = v[3] * t[1]; \
- m[3][2] = v[3] * t[2]; \
- m[3][3] = v[3] * t[3]; \
-}\
-
+#define OUTER_PRODUCT_4X4(m, v, t) \
+ { \
+ m[0][0] = v[0] * t[0]; \
+ m[0][1] = v[0] * t[1]; \
+ m[0][2] = v[0] * t[2]; \
+ m[0][3] = v[0] * t[3]; \
+ \
+ m[1][0] = v[1] * t[0]; \
+ m[1][1] = v[1] * t[1]; \
+ m[1][2] = v[1] * t[2]; \
+ m[1][3] = v[1] * t[3]; \
+ \
+ m[2][0] = v[2] * t[0]; \
+ m[2][1] = v[2] * t[1]; \
+ m[2][2] = v[2] * t[2]; \
+ m[2][3] = v[2] * t[3]; \
+ \
+ m[3][0] = v[3] * t[0]; \
+ m[3][1] = v[3] * t[1]; \
+ m[3][2] = v[3] * t[2]; \
+ m[3][3] = v[3] * t[3]; \
+ }
/** outer product of vector times vector transpose
*
* The outer product of vector v and vector transpose t yeilds
* dyadic matrix m.
*/
-#define ACCUM_OUTER_PRODUCT_2X2(m,v,t) \
-{ \
- m[0][0] += v[0] * t[0]; \
- m[0][1] += v[0] * t[1]; \
- \
- m[1][0] += v[1] * t[0]; \
- m[1][1] += v[1] * t[1]; \
-}\
-
+#define ACCUM_OUTER_PRODUCT_2X2(m, v, t) \
+ { \
+ m[0][0] += v[0] * t[0]; \
+ m[0][1] += v[0] * t[1]; \
+ \
+ m[1][0] += v[1] * t[0]; \
+ m[1][1] += v[1] * t[1]; \
+ }
/** outer product of vector times vector transpose
*
* The outer product of vector v and vector transpose t yeilds
* dyadic matrix m.
*/
-#define ACCUM_OUTER_PRODUCT_3X3(m,v,t) \
-{ \
- m[0][0] += v[0] * t[0]; \
- m[0][1] += v[0] * t[1]; \
- m[0][2] += v[0] * t[2]; \
- \
- m[1][0] += v[1] * t[0]; \
- m[1][1] += v[1] * t[1]; \
- m[1][2] += v[1] * t[2]; \
- \
- m[2][0] += v[2] * t[0]; \
- m[2][1] += v[2] * t[1]; \
- m[2][2] += v[2] * t[2]; \
-}\
-
+#define ACCUM_OUTER_PRODUCT_3X3(m, v, t) \
+ { \
+ m[0][0] += v[0] * t[0]; \
+ m[0][1] += v[0] * t[1]; \
+ m[0][2] += v[0] * t[2]; \
+ \
+ m[1][0] += v[1] * t[0]; \
+ m[1][1] += v[1] * t[1]; \
+ m[1][2] += v[1] * t[2]; \
+ \
+ m[2][0] += v[2] * t[0]; \
+ m[2][1] += v[2] * t[1]; \
+ m[2][2] += v[2] * t[2]; \
+ }
/** outer product of vector times vector transpose
*
* The outer product of vector v and vector transpose t yeilds
* dyadic matrix m.
*/
-#define ACCUM_OUTER_PRODUCT_4X4(m,v,t) \
-{ \
- m[0][0] += v[0] * t[0]; \
- m[0][1] += v[0] * t[1]; \
- m[0][2] += v[0] * t[2]; \
- m[0][3] += v[0] * t[3]; \
- \
- m[1][0] += v[1] * t[0]; \
- m[1][1] += v[1] * t[1]; \
- m[1][2] += v[1] * t[2]; \
- m[1][3] += v[1] * t[3]; \
- \
- m[2][0] += v[2] * t[0]; \
- m[2][1] += v[2] * t[1]; \
- m[2][2] += v[2] * t[2]; \
- m[2][3] += v[2] * t[3]; \
- \
- m[3][0] += v[3] * t[0]; \
- m[3][1] += v[3] * t[1]; \
- m[3][2] += v[3] * t[2]; \
- m[3][3] += v[3] * t[3]; \
-}\
-
+#define ACCUM_OUTER_PRODUCT_4X4(m, v, t) \
+ { \
+ m[0][0] += v[0] * t[0]; \
+ m[0][1] += v[0] * t[1]; \
+ m[0][2] += v[0] * t[2]; \
+ m[0][3] += v[0] * t[3]; \
+ \
+ m[1][0] += v[1] * t[0]; \
+ m[1][1] += v[1] * t[1]; \
+ m[1][2] += v[1] * t[2]; \
+ m[1][3] += v[1] * t[3]; \
+ \
+ m[2][0] += v[2] * t[0]; \
+ m[2][1] += v[2] * t[1]; \
+ m[2][2] += v[2] * t[2]; \
+ m[2][3] += v[2] * t[3]; \
+ \
+ m[3][0] += v[3] * t[0]; \
+ m[3][1] += v[3] * t[1]; \
+ m[3][2] += v[3] * t[2]; \
+ m[3][3] += v[3] * t[3]; \
+ }
/** determinant of matrix
*
* Computes determinant of matrix m, returning d
*/
-#define DETERMINANT_2X2(d,m) \
-{ \
- d = m[0][0] * m[1][1] - m[0][1] * m[1][0]; \
-}\
-
+#define DETERMINANT_2X2(d, m) \
+ { \
+ d = m[0][0] * m[1][1] - m[0][1] * m[1][0]; \
+ }
/** determinant of matrix
*
* Computes determinant of matrix m, returning d
*/
-#define DETERMINANT_3X3(d,m) \
-{ \
- d = m[0][0] * (m[1][1]*m[2][2] - m[1][2] * m[2][1]); \
- d -= m[0][1] * (m[1][0]*m[2][2] - m[1][2] * m[2][0]); \
- d += m[0][2] * (m[1][0]*m[2][1] - m[1][1] * m[2][0]); \
-}\
-
+#define DETERMINANT_3X3(d, m) \
+ { \
+ d = m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]); \
+ d -= m[0][1] * (m[1][0] * m[2][2] - m[1][2] * m[2][0]); \
+ d += m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0]); \
+ }
/** i,j,th cofactor of a 4x4 matrix
*
*/
-#define COFACTOR_4X4_IJ(fac,m,i,j) \
-{ \
- GUINT __ii[4], __jj[4], __k; \
- \
- for (__k=0; __k<i; __k++) __ii[__k] = __k; \
- for (__k=i; __k<3; __k++) __ii[__k] = __k+1; \
- for (__k=0; __k<j; __k++) __jj[__k] = __k; \
- for (__k=j; __k<3; __k++) __jj[__k] = __k+1; \
- \
- (fac) = m[__ii[0]][__jj[0]] * (m[__ii[1]][__jj[1]]*m[__ii[2]][__jj[2]] \
- - m[__ii[1]][__jj[2]]*m[__ii[2]][__jj[1]]); \
- (fac) -= m[__ii[0]][__jj[1]] * (m[__ii[1]][__jj[0]]*m[__ii[2]][__jj[2]] \
- - m[__ii[1]][__jj[2]]*m[__ii[2]][__jj[0]]);\
- (fac) += m[__ii[0]][__jj[2]] * (m[__ii[1]][__jj[0]]*m[__ii[2]][__jj[1]] \
- - m[__ii[1]][__jj[1]]*m[__ii[2]][__jj[0]]);\
- \
- __k = i+j; \
- if ( __k != (__k/2)*2) { \
- (fac) = -(fac); \
- } \
-}\
-
+#define COFACTOR_4X4_IJ(fac, m, i, j) \
+ { \
+ GUINT __ii[4], __jj[4], __k; \
+ \
+ for (__k = 0; __k < i; __k++) __ii[__k] = __k; \
+ for (__k = i; __k < 3; __k++) __ii[__k] = __k + 1; \
+ for (__k = 0; __k < j; __k++) __jj[__k] = __k; \
+ for (__k = j; __k < 3; __k++) __jj[__k] = __k + 1; \
+ \
+ (fac) = m[__ii[0]][__jj[0]] * (m[__ii[1]][__jj[1]] * m[__ii[2]][__jj[2]] - m[__ii[1]][__jj[2]] * m[__ii[2]][__jj[1]]); \
+ (fac) -= m[__ii[0]][__jj[1]] * (m[__ii[1]][__jj[0]] * m[__ii[2]][__jj[2]] - m[__ii[1]][__jj[2]] * m[__ii[2]][__jj[0]]); \
+ (fac) += m[__ii[0]][__jj[2]] * (m[__ii[1]][__jj[0]] * m[__ii[2]][__jj[1]] - m[__ii[1]][__jj[1]] * m[__ii[2]][__jj[0]]); \
+ \
+ __k = i + j; \
+ if (__k != (__k / 2) * 2) \
+ { \
+ (fac) = -(fac); \
+ } \
+ }
/** determinant of matrix
*
* Computes determinant of matrix m, returning d
*/
-#define DETERMINANT_4X4(d,m) \
-{ \
- GREAL cofac; \
- COFACTOR_4X4_IJ (cofac, m, 0, 0); \
- d = m[0][0] * cofac; \
- COFACTOR_4X4_IJ (cofac, m, 0, 1); \
- d += m[0][1] * cofac; \
- COFACTOR_4X4_IJ (cofac, m, 0, 2); \
- d += m[0][2] * cofac; \
- COFACTOR_4X4_IJ (cofac, m, 0, 3); \
- d += m[0][3] * cofac; \
-}\
-
+#define DETERMINANT_4X4(d, m) \
+ { \
+ GREAL cofac; \
+ COFACTOR_4X4_IJ(cofac, m, 0, 0); \
+ d = m[0][0] * cofac; \
+ COFACTOR_4X4_IJ(cofac, m, 0, 1); \
+ d += m[0][1] * cofac; \
+ COFACTOR_4X4_IJ(cofac, m, 0, 2); \
+ d += m[0][2] * cofac; \
+ COFACTOR_4X4_IJ(cofac, m, 0, 3); \
+ d += m[0][3] * cofac; \
+ }
/** cofactor of matrix
*
* Computes cofactor of matrix m, returning a
*/
-#define COFACTOR_2X2(a,m) \
-{ \
- a[0][0] = (m)[1][1]; \
- a[0][1] = - (m)[1][0]; \
- a[1][0] = - (m)[0][1]; \
- a[1][1] = (m)[0][0]; \
-}\
-
+#define COFACTOR_2X2(a, m) \
+ { \
+ a[0][0] = (m)[1][1]; \
+ a[0][1] = -(m)[1][0]; \
+ a[1][0] = -(m)[0][1]; \
+ a[1][1] = (m)[0][0]; \
+ }
/** cofactor of matrix
*
* Computes cofactor of matrix m, returning a
*/
-#define COFACTOR_3X3(a,m) \
-{ \
- a[0][0] = m[1][1]*m[2][2] - m[1][2]*m[2][1]; \
- a[0][1] = - (m[1][0]*m[2][2] - m[2][0]*m[1][2]); \
- a[0][2] = m[1][0]*m[2][1] - m[1][1]*m[2][0]; \
- a[1][0] = - (m[0][1]*m[2][2] - m[0][2]*m[2][1]); \
- a[1][1] = m[0][0]*m[2][2] - m[0][2]*m[2][0]; \
- a[1][2] = - (m[0][0]*m[2][1] - m[0][1]*m[2][0]); \
- a[2][0] = m[0][1]*m[1][2] - m[0][2]*m[1][1]; \
- a[2][1] = - (m[0][0]*m[1][2] - m[0][2]*m[1][0]); \
- a[2][2] = m[0][0]*m[1][1] - m[0][1]*m[1][0]); \
-}\
-
+#define COFACTOR_3X3(a, m) \
+ { \
+ a[0][0] = m[1][1] * m[2][2] - m[1][2] * m[2][1]; \
+ a[0][1] = -(m[1][0] * m[2][2] - m[2][0] * m[1][2]); \
+ a[0][2] = m[1][0] * m[2][1] - m[1][1] * m[2][0]; \
+ a[1][0] = -(m[0][1] * m[2][2] - m[0][2] * m[2][1]); \
+ a[1][1] = m[0][0] * m[2][2] - m[0][2] * m[2][0]; \
+ a[1][2] = -(m[0][0] * m[2][1] - m[0][1] * m[2][0]); \
+ a[2][0] = m[0][1] * m[1][2] - m[0][2] * m[1][1]; \
+ a[2][1] = -(m[0][0] * m[1][2] - m[0][2] * m[1][0]); \
+ a[2][2] = m[0][0]*m[1][1] - m[0][1]*m[1][0]); \
+ }
/** cofactor of matrix
*
* Computes cofactor of matrix m, returning a
*/
-#define COFACTOR_4X4(a,m) \
-{ \
- int i,j; \
- \
- for (i=0; i<4; i++) { \
- for (j=0; j<4; j++) { \
- COFACTOR_4X4_IJ (a[i][j], m, i, j); \
- } \
- } \
-}\
-
+#define COFACTOR_4X4(a, m) \
+ { \
+ int i, j; \
+ \
+ for (i = 0; i < 4; i++) \
+ { \
+ for (j = 0; j < 4; j++) \
+ { \
+ COFACTOR_4X4_IJ(a[i][j], m, i, j); \
+ } \
+ } \
+ }
/** adjoint of matrix
*
* Computes adjoint of matrix m, returning a
* (Note that adjoint is just the transpose of the cofactor matrix)
*/
-#define ADJOINT_2X2(a,m) \
-{ \
- a[0][0] = (m)[1][1]; \
- a[1][0] = - (m)[1][0]; \
- a[0][1] = - (m)[0][1]; \
- a[1][1] = (m)[0][0]; \
-}\
-
+#define ADJOINT_2X2(a, m) \
+ { \
+ a[0][0] = (m)[1][1]; \
+ a[1][0] = -(m)[1][0]; \
+ a[0][1] = -(m)[0][1]; \
+ a[1][1] = (m)[0][0]; \
+ }
/** adjoint of matrix
*
* Computes adjoint of matrix m, returning a
* (Note that adjoint is just the transpose of the cofactor matrix)
*/
-#define ADJOINT_3X3(a,m) \
-{ \
- a[0][0] = m[1][1]*m[2][2] - m[1][2]*m[2][1]; \
- a[1][0] = - (m[1][0]*m[2][2] - m[2][0]*m[1][2]); \
- a[2][0] = m[1][0]*m[2][1] - m[1][1]*m[2][0]; \
- a[0][1] = - (m[0][1]*m[2][2] - m[0][2]*m[2][1]); \
- a[1][1] = m[0][0]*m[2][2] - m[0][2]*m[2][0]; \
- a[2][1] = - (m[0][0]*m[2][1] - m[0][1]*m[2][0]); \
- a[0][2] = m[0][1]*m[1][2] - m[0][2]*m[1][1]; \
- a[1][2] = - (m[0][0]*m[1][2] - m[0][2]*m[1][0]); \
- a[2][2] = m[0][0]*m[1][1] - m[0][1]*m[1][0]); \
-}\
-
+#define ADJOINT_3X3(a, m) \
+ { \
+ a[0][0] = m[1][1] * m[2][2] - m[1][2] * m[2][1]; \
+ a[1][0] = -(m[1][0] * m[2][2] - m[2][0] * m[1][2]); \
+ a[2][0] = m[1][0] * m[2][1] - m[1][1] * m[2][0]; \
+ a[0][1] = -(m[0][1] * m[2][2] - m[0][2] * m[2][1]); \
+ a[1][1] = m[0][0] * m[2][2] - m[0][2] * m[2][0]; \
+ a[2][1] = -(m[0][0] * m[2][1] - m[0][1] * m[2][0]); \
+ a[0][2] = m[0][1] * m[1][2] - m[0][2] * m[1][1]; \
+ a[1][2] = -(m[0][0] * m[1][2] - m[0][2] * m[1][0]); \
+ a[2][2] = m[0][0]*m[1][1] - m[0][1]*m[1][0]); \
+ }
/** adjoint of matrix
*
* Computes adjoint of matrix m, returning a
* (Note that adjoint is just the transpose of the cofactor matrix)
*/
-#define ADJOINT_4X4(a,m) \
-{ \
- char _i_,_j_; \
- \
- for (_i_=0; _i_<4; _i_++) { \
- for (_j_=0; _j_<4; _j_++) { \
- COFACTOR_4X4_IJ (a[_j_][_i_], m, _i_, _j_); \
- } \
- } \
-}\
-
+#define ADJOINT_4X4(a, m) \
+ { \
+ char _i_, _j_; \
+ \
+ for (_i_ = 0; _i_ < 4; _i_++) \
+ { \
+ for (_j_ = 0; _j_ < 4; _j_++) \
+ { \
+ COFACTOR_4X4_IJ(a[_j_][_i_], m, _i_, _j_); \
+ } \
+ } \
+ }
/** compute adjoint of matrix and scale
*
* Computes adjoint of matrix m, scales it by s, returning a
*/
-#define SCALE_ADJOINT_2X2(a,s,m) \
-{ \
- a[0][0] = (s) * m[1][1]; \
- a[1][0] = - (s) * m[1][0]; \
- a[0][1] = - (s) * m[0][1]; \
- a[1][1] = (s) * m[0][0]; \
-}\
-
+#define SCALE_ADJOINT_2X2(a, s, m) \
+ { \
+ a[0][0] = (s)*m[1][1]; \
+ a[1][0] = -(s)*m[1][0]; \
+ a[0][1] = -(s)*m[0][1]; \
+ a[1][1] = (s)*m[0][0]; \
+ }
/** compute adjoint of matrix and scale
*
* Computes adjoint of matrix m, scales it by s, returning a
*/
-#define SCALE_ADJOINT_3X3(a,s,m) \
-{ \
- a[0][0] = (s) * (m[1][1] * m[2][2] - m[1][2] * m[2][1]); \
- a[1][0] = (s) * (m[1][2] * m[2][0] - m[1][0] * m[2][2]); \
- a[2][0] = (s) * (m[1][0] * m[2][1] - m[1][1] * m[2][0]); \
- \
- a[0][1] = (s) * (m[0][2] * m[2][1] - m[0][1] * m[2][2]); \
- a[1][1] = (s) * (m[0][0] * m[2][2] - m[0][2] * m[2][0]); \
- a[2][1] = (s) * (m[0][1] * m[2][0] - m[0][0] * m[2][1]); \
- \
- a[0][2] = (s) * (m[0][1] * m[1][2] - m[0][2] * m[1][1]); \
- a[1][2] = (s) * (m[0][2] * m[1][0] - m[0][0] * m[1][2]); \
- a[2][2] = (s) * (m[0][0] * m[1][1] - m[0][1] * m[1][0]); \
-}\
-
+#define SCALE_ADJOINT_3X3(a, s, m) \
+ { \
+ a[0][0] = (s) * (m[1][1] * m[2][2] - m[1][2] * m[2][1]); \
+ a[1][0] = (s) * (m[1][2] * m[2][0] - m[1][0] * m[2][2]); \
+ a[2][0] = (s) * (m[1][0] * m[2][1] - m[1][1] * m[2][0]); \
+ \
+ a[0][1] = (s) * (m[0][2] * m[2][1] - m[0][1] * m[2][2]); \
+ a[1][1] = (s) * (m[0][0] * m[2][2] - m[0][2] * m[2][0]); \
+ a[2][1] = (s) * (m[0][1] * m[2][0] - m[0][0] * m[2][1]); \
+ \
+ a[0][2] = (s) * (m[0][1] * m[1][2] - m[0][2] * m[1][1]); \
+ a[1][2] = (s) * (m[0][2] * m[1][0] - m[0][0] * m[1][2]); \
+ a[2][2] = (s) * (m[0][0] * m[1][1] - m[0][1] * m[1][0]); \
+ }
/** compute adjoint of matrix and scale
*
* Computes adjoint of matrix m, scales it by s, returning a
*/
-#define SCALE_ADJOINT_4X4(a,s,m) \
-{ \
- char _i_,_j_; \
- for (_i_=0; _i_<4; _i_++) { \
- for (_j_=0; _j_<4; _j_++) { \
- COFACTOR_4X4_IJ (a[_j_][_i_], m, _i_, _j_); \
- a[_j_][_i_] *= s; \
- } \
- } \
-}\
+#define SCALE_ADJOINT_4X4(a, s, m) \
+ { \
+ char _i_, _j_; \
+ for (_i_ = 0; _i_ < 4; _i_++) \
+ { \
+ for (_j_ = 0; _j_ < 4; _j_++) \
+ { \
+ COFACTOR_4X4_IJ(a[_j_][_i_], m, _i_, _j_); \
+ a[_j_][_i_] *= s; \
+ } \
+ } \
+ }
/** inverse of matrix
*
* Compute inverse of matrix a, returning determinant m and
* inverse b
*/
-#define INVERT_2X2(b,det,a) \
-{ \
- GREAL _tmp_; \
- DETERMINANT_2X2 (det, a); \
- _tmp_ = 1.0 / (det); \
- SCALE_ADJOINT_2X2 (b, _tmp_, a); \
-}\
-
+#define INVERT_2X2(b, det, a) \
+ { \
+ GREAL _tmp_; \
+ DETERMINANT_2X2(det, a); \
+ _tmp_ = 1.0 / (det); \
+ SCALE_ADJOINT_2X2(b, _tmp_, a); \
+ }
/** inverse of matrix
*
* Compute inverse of matrix a, returning determinant m and
* inverse b
*/
-#define INVERT_3X3(b,det,a) \
-{ \
- GREAL _tmp_; \
- DETERMINANT_3X3 (det, a); \
- _tmp_ = 1.0 / (det); \
- SCALE_ADJOINT_3X3 (b, _tmp_, a); \
-}\
-
+#define INVERT_3X3(b, det, a) \
+ { \
+ GREAL _tmp_; \
+ DETERMINANT_3X3(det, a); \
+ _tmp_ = 1.0 / (det); \
+ SCALE_ADJOINT_3X3(b, _tmp_, a); \
+ }
/** inverse of matrix
*
* Compute inverse of matrix a, returning determinant m and
* inverse b
*/
-#define INVERT_4X4(b,det,a) \
-{ \
- GREAL _tmp_; \
- DETERMINANT_4X4 (det, a); \
- _tmp_ = 1.0 / (det); \
- SCALE_ADJOINT_4X4 (b, _tmp_, a); \
-}\
+#define INVERT_4X4(b, det, a) \
+ { \
+ GREAL _tmp_; \
+ DETERMINANT_4X4(det, a); \
+ _tmp_ = 1.0 / (det); \
+ SCALE_ADJOINT_4X4(b, _tmp_, a); \
+ }
//! Get the triple(3) row of a transform matrix
-#define MAT_GET_ROW(mat,vec3,rowindex)\
-{\
- vec3[0] = mat[rowindex][0];\
- vec3[1] = mat[rowindex][1];\
- vec3[2] = mat[rowindex][2]; \
-}\
+#define MAT_GET_ROW(mat, vec3, rowindex) \
+ { \
+ vec3[0] = mat[rowindex][0]; \
+ vec3[1] = mat[rowindex][1]; \
+ vec3[2] = mat[rowindex][2]; \
+ }
//! Get the tuple(2) row of a transform matrix
-#define MAT_GET_ROW2(mat,vec2,rowindex)\
-{\
- vec2[0] = mat[rowindex][0];\
- vec2[1] = mat[rowindex][1];\
-}\
-
+#define MAT_GET_ROW2(mat, vec2, rowindex) \
+ { \
+ vec2[0] = mat[rowindex][0]; \
+ vec2[1] = mat[rowindex][1]; \
+ }
//! Get the quad (4) row of a transform matrix
-#define MAT_GET_ROW4(mat,vec4,rowindex)\
-{\
- vec4[0] = mat[rowindex][0];\
- vec4[1] = mat[rowindex][1];\
- vec4[2] = mat[rowindex][2];\
- vec4[3] = mat[rowindex][3];\
-}\
+#define MAT_GET_ROW4(mat, vec4, rowindex) \
+ { \
+ vec4[0] = mat[rowindex][0]; \
+ vec4[1] = mat[rowindex][1]; \
+ vec4[2] = mat[rowindex][2]; \
+ vec4[3] = mat[rowindex][3]; \
+ }
//! Get the triple(3) col of a transform matrix
-#define MAT_GET_COL(mat,vec3,colindex)\
-{\
- vec3[0] = mat[0][colindex];\
- vec3[1] = mat[1][colindex];\
- vec3[2] = mat[2][colindex]; \
-}\
+#define MAT_GET_COL(mat, vec3, colindex) \
+ { \
+ vec3[0] = mat[0][colindex]; \
+ vec3[1] = mat[1][colindex]; \
+ vec3[2] = mat[2][colindex]; \
+ }
//! Get the tuple(2) col of a transform matrix
-#define MAT_GET_COL2(mat,vec2,colindex)\
-{\
- vec2[0] = mat[0][colindex];\
- vec2[1] = mat[1][colindex];\
-}\
-
+#define MAT_GET_COL2(mat, vec2, colindex) \
+ { \
+ vec2[0] = mat[0][colindex]; \
+ vec2[1] = mat[1][colindex]; \
+ }
//! Get the quad (4) col of a transform matrix
-#define MAT_GET_COL4(mat,vec4,colindex)\
-{\
- vec4[0] = mat[0][colindex];\
- vec4[1] = mat[1][colindex];\
- vec4[2] = mat[2][colindex];\
- vec4[3] = mat[3][colindex];\
-}\
+#define MAT_GET_COL4(mat, vec4, colindex) \
+ { \
+ vec4[0] = mat[0][colindex]; \
+ vec4[1] = mat[1][colindex]; \
+ vec4[2] = mat[2][colindex]; \
+ vec4[3] = mat[3][colindex]; \
+ }
//! Get the triple(3) col of a transform matrix
-#define MAT_GET_X(mat,vec3)\
-{\
- MAT_GET_COL(mat,vec3,0);\
-}\
+#define MAT_GET_X(mat, vec3) \
+ { \
+ MAT_GET_COL(mat, vec3, 0); \
+ }
//! Get the triple(3) col of a transform matrix
-#define MAT_GET_Y(mat,vec3)\
-{\
- MAT_GET_COL(mat,vec3,1);\
-}\
+#define MAT_GET_Y(mat, vec3) \
+ { \
+ MAT_GET_COL(mat, vec3, 1); \
+ }
//! Get the triple(3) col of a transform matrix
-#define MAT_GET_Z(mat,vec3)\
-{\
- MAT_GET_COL(mat,vec3,2);\
-}\
-
+#define MAT_GET_Z(mat, vec3) \
+ { \
+ MAT_GET_COL(mat, vec3, 2); \
+ }
//! Get the triple(3) col of a transform matrix
-#define MAT_SET_X(mat,vec3)\
-{\
- mat[0][0] = vec3[0];\
- mat[1][0] = vec3[1];\
- mat[2][0] = vec3[2];\
-}\
+#define MAT_SET_X(mat, vec3) \
+ { \
+ mat[0][0] = vec3[0]; \
+ mat[1][0] = vec3[1]; \
+ mat[2][0] = vec3[2]; \
+ }
//! Get the triple(3) col of a transform matrix
-#define MAT_SET_Y(mat,vec3)\
-{\
- mat[0][1] = vec3[0];\
- mat[1][1] = vec3[1];\
- mat[2][1] = vec3[2];\
-}\
+#define MAT_SET_Y(mat, vec3) \
+ { \
+ mat[0][1] = vec3[0]; \
+ mat[1][1] = vec3[1]; \
+ mat[2][1] = vec3[2]; \
+ }
//! Get the triple(3) col of a transform matrix
-#define MAT_SET_Z(mat,vec3)\
-{\
- mat[0][2] = vec3[0];\
- mat[1][2] = vec3[1];\
- mat[2][2] = vec3[2];\
-}\
-
+#define MAT_SET_Z(mat, vec3) \
+ { \
+ mat[0][2] = vec3[0]; \
+ mat[1][2] = vec3[1]; \
+ mat[2][2] = vec3[2]; \
+ }
//! Get the triple(3) col of a transform matrix
-#define MAT_GET_TRANSLATION(mat,vec3)\
-{\
- vec3[0] = mat[0][3];\
- vec3[1] = mat[1][3];\
- vec3[2] = mat[2][3]; \
-}\
+#define MAT_GET_TRANSLATION(mat, vec3) \
+ { \
+ vec3[0] = mat[0][3]; \
+ vec3[1] = mat[1][3]; \
+ vec3[2] = mat[2][3]; \
+ }
//! Set the triple(3) col of a transform matrix
-#define MAT_SET_TRANSLATION(mat,vec3)\
-{\
- mat[0][3] = vec3[0];\
- mat[1][3] = vec3[1];\
- mat[2][3] = vec3[2]; \
-}\
-
-
+#define MAT_SET_TRANSLATION(mat, vec3) \
+ { \
+ mat[0][3] = vec3[0]; \
+ mat[1][3] = vec3[1]; \
+ mat[2][3] = vec3[2]; \
+ }
//! Returns the dot product between a vec3f and the row of a matrix
-#define MAT_DOT_ROW(mat,vec3,rowindex) (vec3[0]*mat[rowindex][0] + vec3[1]*mat[rowindex][1] + vec3[2]*mat[rowindex][2])
+#define MAT_DOT_ROW(mat, vec3, rowindex) (vec3[0] * mat[rowindex][0] + vec3[1] * mat[rowindex][1] + vec3[2] * mat[rowindex][2])
//! Returns the dot product between a vec2f and the row of a matrix
-#define MAT_DOT_ROW2(mat,vec2,rowindex) (vec2[0]*mat[rowindex][0] + vec2[1]*mat[rowindex][1])
+#define MAT_DOT_ROW2(mat, vec2, rowindex) (vec2[0] * mat[rowindex][0] + vec2[1] * mat[rowindex][1])
//! Returns the dot product between a vec4f and the row of a matrix
-#define MAT_DOT_ROW4(mat,vec4,rowindex) (vec4[0]*mat[rowindex][0] + vec4[1]*mat[rowindex][1] + vec4[2]*mat[rowindex][2] + vec4[3]*mat[rowindex][3])
-
+#define MAT_DOT_ROW4(mat, vec4, rowindex) (vec4[0] * mat[rowindex][0] + vec4[1] * mat[rowindex][1] + vec4[2] * mat[rowindex][2] + vec4[3] * mat[rowindex][3])
//! Returns the dot product between a vec3f and the col of a matrix
-#define MAT_DOT_COL(mat,vec3,colindex) (vec3[0]*mat[0][colindex] + vec3[1]*mat[1][colindex] + vec3[2]*mat[2][colindex])
+#define MAT_DOT_COL(mat, vec3, colindex) (vec3[0] * mat[0][colindex] + vec3[1] * mat[1][colindex] + vec3[2] * mat[2][colindex])
//! Returns the dot product between a vec2f and the col of a matrix
-#define MAT_DOT_COL2(mat,vec2,colindex) (vec2[0]*mat[0][colindex] + vec2[1]*mat[1][colindex])
+#define MAT_DOT_COL2(mat, vec2, colindex) (vec2[0] * mat[0][colindex] + vec2[1] * mat[1][colindex])
//! Returns the dot product between a vec4f and the col of a matrix
-#define MAT_DOT_COL4(mat,vec4,colindex) (vec4[0]*mat[0][colindex] + vec4[1]*mat[1][colindex] + vec4[2]*mat[2][colindex] + vec4[3]*mat[3][colindex])
+#define MAT_DOT_COL4(mat, vec4, colindex) (vec4[0] * mat[0][colindex] + vec4[1] * mat[1][colindex] + vec4[2] * mat[2][colindex] + vec4[3] * mat[3][colindex])
/*!Transpose matrix times vector
v is a vec3f
and m is a mat4f<br>
*/
-#define INV_MAT_DOT_VEC_3X3(p,m,v) \
-{ \
- p[0] = MAT_DOT_COL(m,v,0); \
- p[1] = MAT_DOT_COL(m,v,1); \
- p[2] = MAT_DOT_COL(m,v,2); \
-}\
-
-
-
-#endif // GIM_VECTOR_H_INCLUDED
+#define INV_MAT_DOT_VEC_3X3(p, m, v) \
+ { \
+ p[0] = MAT_DOT_COL(m, v, 0); \
+ p[1] = MAT_DOT_COL(m, v, 1); \
+ p[2] = MAT_DOT_COL(m, v, 2); \
+ }
+
+#endif // GIM_VECTOR_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_math.h b/thirdparty/bullet/BulletCollision/Gimpact/gim_math.h
index 939079e104..3c4f821a72 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_math.h
+++ b/thirdparty/bullet/BulletCollision/Gimpact/gim_math.h
@@ -34,8 +34,6 @@ email: projectileman@yahoo.com
#include "LinearMath/btScalar.h"
-
-
#define GREAL btScalar
#define GREAL2 double
#define GINT int
@@ -45,8 +43,6 @@ email: projectileman@yahoo.com
#define GINT64 long long
#define GUINT64 unsigned long long
-
-
#define G_PI 3.14159265358979f
#define G_HALF_PI 1.5707963f
//267948966
@@ -54,16 +50,14 @@ email: projectileman@yahoo.com
//71795864
#define G_ROOT3 1.73205f
#define G_ROOT2 1.41421f
-#define G_UINT_INFINITY 0xffffffff //!< A very very high value
+#define G_UINT_INFINITY 0xffffffff //!< A very very high value
#define G_REAL_INFINITY FLT_MAX
-#define G_SIGN_BITMASK 0x80000000
+#define G_SIGN_BITMASK 0x80000000
#define G_EPSILON SIMD_EPSILON
-
-
enum GIM_SCALAR_TYPES
{
- G_STYPE_REAL =0,
+ G_STYPE_REAL = 0,
G_STYPE_REAL2,
G_STYPE_SHORT,
G_STYPE_USHORT,
@@ -73,85 +67,82 @@ enum GIM_SCALAR_TYPES
G_STYPE_UINT64
};
-
-
-#define G_DEGTORAD(X) ((X)*3.1415926f/180.0f)
-#define G_RADTODEG(X) ((X)*180.0f/3.1415926f)
+#define G_DEGTORAD(X) ((X)*3.1415926f / 180.0f)
+#define G_RADTODEG(X) ((X)*180.0f / 3.1415926f)
//! Integer representation of a floating-point value.
-#define GIM_IR(x) ((GUINT&)(x))
+#define GIM_IR(x) ((GUINT&)(x))
//! Signed integer representation of a floating-point value.
-#define GIM_SIR(x) ((GINT&)(x))
+#define GIM_SIR(x) ((GINT&)(x))
//! Absolute integer representation of a floating-point value
-#define GIM_AIR(x) (GIM_IR(x)&0x7fffffff)
+#define GIM_AIR(x) (GIM_IR(x) & 0x7fffffff)
//! Floating-point representation of an integer value.
-#define GIM_FR(x) ((GREAL&)(x))
+#define GIM_FR(x) ((GREAL&)(x))
-#define GIM_MAX(a,b) (a<b?b:a)
-#define GIM_MIN(a,b) (a>b?b:a)
+#define GIM_MAX(a, b) (a < b ? b : a)
+#define GIM_MIN(a, b) (a > b ? b : a)
-#define GIM_MAX3(a,b,c) GIM_MAX(a,GIM_MAX(b,c))
-#define GIM_MIN3(a,b,c) GIM_MIN(a,GIM_MIN(b,c))
+#define GIM_MAX3(a, b, c) GIM_MAX(a, GIM_MAX(b, c))
+#define GIM_MIN3(a, b, c) GIM_MIN(a, GIM_MIN(b, c))
-#define GIM_IS_ZERO(value) (value < G_EPSILON && value > -G_EPSILON)
+#define GIM_IS_ZERO(value) (value < G_EPSILON && value > -G_EPSILON)
#define GIM_IS_NEGATIVE(value) (value <= -G_EPSILON)
#define GIM_IS_POSISITVE(value) (value >= G_EPSILON)
-#define GIM_NEAR_EQUAL(v1,v2) GIM_IS_ZERO((v1-v2))
+#define GIM_NEAR_EQUAL(v1, v2) GIM_IS_ZERO((v1 - v2))
///returns a clamped number
-#define GIM_CLAMP(number,minval,maxval) (number<minval?minval:(number>maxval?maxval:number))
+#define GIM_CLAMP(number, minval, maxval) (number < minval ? minval : (number > maxval ? maxval : number))
-#define GIM_GREATER(x, y) btFabs(x) > (y)
+#define GIM_GREATER(x, y) btFabs(x) > (y)
///Swap numbers
-#define GIM_SWAP_NUMBERS(a,b){ \
- a = a+b; \
- b = a-b; \
- a = a-b; \
-}\
-
-#define GIM_INV_SQRT(va,isva)\
-{\
- if(va<=0.0000001f)\
- {\
- isva = G_REAL_INFINITY;\
- }\
- else\
- {\
- GREAL _x = va * 0.5f;\
- GUINT _y = 0x5f3759df - ( GIM_IR(va) >> 1);\
- isva = GIM_FR(_y);\
- isva = isva * ( 1.5f - ( _x * isva * isva ) );\
- }\
-}\
-
-#define GIM_SQRT(va,sva)\
-{\
- GIM_INV_SQRT(va,sva);\
- sva = 1.0f/sva;\
-}\
+#define GIM_SWAP_NUMBERS(a, b) \
+ { \
+ a = a + b; \
+ b = a - b; \
+ a = a - b; \
+ }
+
+#define GIM_INV_SQRT(va, isva) \
+ { \
+ if (va <= 0.0000001f) \
+ { \
+ isva = G_REAL_INFINITY; \
+ } \
+ else \
+ { \
+ GREAL _x = va * 0.5f; \
+ GUINT _y = 0x5f3759df - (GIM_IR(va) >> 1); \
+ isva = GIM_FR(_y); \
+ isva = isva * (1.5f - (_x * isva * isva)); \
+ } \
+ }
+
+#define GIM_SQRT(va, sva) \
+ { \
+ GIM_INV_SQRT(va, sva); \
+ sva = 1.0f / sva; \
+ }
//! Computes 1.0f / sqrtf(x). Comes from Quake3. See http://www.magic-software.com/3DGEDInvSqrt.html
inline GREAL gim_inv_sqrt(GREAL f)
{
- GREAL r;
- GIM_INV_SQRT(f,r);
- return r;
+ GREAL r;
+ GIM_INV_SQRT(f, r);
+ return r;
}
inline GREAL gim_sqrt(GREAL f)
{
- GREAL r;
- GIM_SQRT(f,r);
- return r;
+ GREAL r;
+ GIM_SQRT(f, r);
+ return r;
}
-
-
-#endif // GIM_MATH_H_INCLUDED
+#endif // GIM_MATH_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_memory.cpp b/thirdparty/bullet/BulletCollision/Gimpact/gim_memory.cpp
index 1636eb7867..9e29ab91d6 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_memory.cpp
+++ b/thirdparty/bullet/BulletCollision/Gimpact/gim_memory.cpp
@@ -27,7 +27,6 @@ email: projectileman@yahoo.com
-----------------------------------------------------------------------------
*/
-
#include "gim_memory.h"
#include "stdlib.h"
@@ -40,52 +39,49 @@ static gim_alloca_function *g_allocafn = 0;
static gim_realloc_function *g_reallocfn = 0;
static gim_free_function *g_freefn = 0;
-void gim_set_alloc_handler (gim_alloc_function *fn)
+void gim_set_alloc_handler(gim_alloc_function *fn)
{
- g_allocfn = fn;
+ g_allocfn = fn;
}
-void gim_set_alloca_handler (gim_alloca_function *fn)
+void gim_set_alloca_handler(gim_alloca_function *fn)
{
- g_allocafn = fn;
+ g_allocafn = fn;
}
-void gim_set_realloc_handler (gim_realloc_function *fn)
+void gim_set_realloc_handler(gim_realloc_function *fn)
{
- g_reallocfn = fn;
+ g_reallocfn = fn;
}
-void gim_set_free_handler (gim_free_function *fn)
+void gim_set_free_handler(gim_free_function *fn)
{
- g_freefn = fn;
+ g_freefn = fn;
}
gim_alloc_function *gim_get_alloc_handler()
{
- return g_allocfn;
+ return g_allocfn;
}
gim_alloca_function *gim_get_alloca_handler()
{
- return g_allocafn;
+ return g_allocafn;
}
-
-gim_realloc_function *gim_get_realloc_handler ()
+gim_realloc_function *gim_get_realloc_handler()
{
- return g_reallocfn;
+ return g_reallocfn;
}
-
-gim_free_function *gim_get_free_handler ()
+gim_free_function *gim_get_free_handler()
{
- return g_freefn;
+ return g_freefn;
}
-
-void * gim_alloc(size_t size)
+void *gim_alloc(size_t size)
{
- void * ptr;
+ void *ptr;
if (g_allocfn)
{
ptr = g_allocfn(size);
@@ -93,27 +89,29 @@ void * gim_alloc(size_t size)
else
{
#ifdef GIM_SIMD_MEMORY
- ptr = btAlignedAlloc(size,16);
+ ptr = btAlignedAlloc(size, 16);
#else
ptr = malloc(size);
#endif
}
- return ptr;
+ return ptr;
}
-void * gim_alloca(size_t size)
+void *gim_alloca(size_t size)
{
- if (g_allocafn) return g_allocafn(size); else return gim_alloc(size);
+ if (g_allocafn)
+ return g_allocafn(size);
+ else
+ return gim_alloc(size);
}
-
-void * gim_realloc(void *ptr, size_t oldsize, size_t newsize)
+void *gim_realloc(void *ptr, size_t oldsize, size_t newsize)
{
- void * newptr = gim_alloc(newsize);
- size_t copysize = oldsize<newsize?oldsize:newsize;
- gim_simd_memcpy(newptr,ptr,copysize);
- gim_free(ptr);
- return newptr;
+ void *newptr = gim_alloc(newsize);
+ size_t copysize = oldsize < newsize ? oldsize : newsize;
+ gim_simd_memcpy(newptr, ptr, copysize);
+ gim_free(ptr);
+ return newptr;
}
void gim_free(void *ptr)
@@ -121,15 +119,14 @@ void gim_free(void *ptr)
if (!ptr) return;
if (g_freefn)
{
- g_freefn(ptr);
+ g_freefn(ptr);
}
else
{
- #ifdef GIM_SIMD_MEMORY
+#ifdef GIM_SIMD_MEMORY
btAlignedFree(ptr);
- #else
+#else
free(ptr);
- #endif
+#endif
}
}
-
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_memory.h b/thirdparty/bullet/BulletCollision/Gimpact/gim_memory.h
index e203888a1e..fffbfa23d8 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_memory.h
+++ b/thirdparty/bullet/BulletCollision/Gimpact/gim_memory.h
@@ -32,93 +32,84 @@ email: projectileman@yahoo.com
-----------------------------------------------------------------------------
*/
-
#include "gim_math.h"
#include <string.h>
#ifdef PREFETCH
-#include <xmmintrin.h> // for prefetch
-#define pfval 64
-#define pfval2 128
+#include <xmmintrin.h> // for prefetch
+#define pfval 64
+#define pfval2 128
//! Prefetch 64
-#define pf(_x,_i) _mm_prefetch((void *)(_x + _i + pfval), 0)
+#define pf(_x, _i) _mm_prefetch((void *)(_x + _i + pfval), 0)
//! Prefetch 128
-#define pf2(_x,_i) _mm_prefetch((void *)(_x + _i + pfval2), 0)
+#define pf2(_x, _i) _mm_prefetch((void *)(_x + _i + pfval2), 0)
#else
//! Prefetch 64
-#define pf(_x,_i)
+#define pf(_x, _i)
//! Prefetch 128
-#define pf2(_x,_i)
+#define pf2(_x, _i)
#endif
-
///Functions for manip packed arrays of numbers
-#define GIM_COPY_ARRAYS(dest_array,source_array,element_count)\
-{\
- for (GUINT _i_=0;_i_<element_count ;++_i_)\
- {\
- dest_array[_i_] = source_array[_i_];\
- }\
-}\
-
-#define GIM_COPY_ARRAYS_1(dest_array,source_array,element_count,copy_macro)\
-{\
- for (GUINT _i_=0;_i_<element_count ;++_i_)\
- {\
- copy_macro(dest_array[_i_],source_array[_i_]);\
- }\
-}\
-
-
-#define GIM_ZERO_ARRAY(array,element_count)\
-{\
- for (GUINT _i_=0;_i_<element_count ;++_i_)\
- {\
- array[_i_] = 0;\
- }\
-}\
-
-#define GIM_CONSTANT_ARRAY(array,element_count,constant)\
-{\
- for (GUINT _i_=0;_i_<element_count ;++_i_)\
- {\
- array[_i_] = constant;\
- }\
-}\
-
+#define GIM_COPY_ARRAYS(dest_array, source_array, element_count) \
+ { \
+ for (GUINT _i_ = 0; _i_ < element_count; ++_i_) \
+ { \
+ dest_array[_i_] = source_array[_i_]; \
+ } \
+ }
+
+#define GIM_COPY_ARRAYS_1(dest_array, source_array, element_count, copy_macro) \
+ { \
+ for (GUINT _i_ = 0; _i_ < element_count; ++_i_) \
+ { \
+ copy_macro(dest_array[_i_], source_array[_i_]); \
+ } \
+ }
+
+#define GIM_ZERO_ARRAY(array, element_count) \
+ { \
+ for (GUINT _i_ = 0; _i_ < element_count; ++_i_) \
+ { \
+ array[_i_] = 0; \
+ } \
+ }
+
+#define GIM_CONSTANT_ARRAY(array, element_count, constant) \
+ { \
+ for (GUINT _i_ = 0; _i_ < element_count; ++_i_) \
+ { \
+ array[_i_] = constant; \
+ } \
+ }
///Function prototypes to allocate and free memory.
-typedef void * gim_alloc_function (size_t size);
-typedef void * gim_alloca_function (size_t size);//Allocs on the heap
-typedef void * gim_realloc_function (void *ptr, size_t oldsize, size_t newsize);
-typedef void gim_free_function (void *ptr);
-
+typedef void *gim_alloc_function(size_t size);
+typedef void *gim_alloca_function(size_t size); //Allocs on the heap
+typedef void *gim_realloc_function(void *ptr, size_t oldsize, size_t newsize);
+typedef void gim_free_function(void *ptr);
///Memory Function Handlers
///set new memory management functions. if fn is 0, the default handlers are used.
-void gim_set_alloc_handler (gim_alloc_function *fn);
-void gim_set_alloca_handler (gim_alloca_function *fn);
-void gim_set_realloc_handler (gim_realloc_function *fn);
-void gim_set_free_handler (gim_free_function *fn);
-
+void gim_set_alloc_handler(gim_alloc_function *fn);
+void gim_set_alloca_handler(gim_alloca_function *fn);
+void gim_set_realloc_handler(gim_realloc_function *fn);
+void gim_set_free_handler(gim_free_function *fn);
///get current memory management functions.
-gim_alloc_function *gim_get_alloc_handler (void);
+gim_alloc_function *gim_get_alloc_handler(void);
gim_alloca_function *gim_get_alloca_handler(void);
-gim_realloc_function *gim_get_realloc_handler (void);
-gim_free_function *gim_get_free_handler (void);
-
+gim_realloc_function *gim_get_realloc_handler(void);
+gim_free_function *gim_get_free_handler(void);
///Standar Memory functions
-void * gim_alloc(size_t size);
-void * gim_alloca(size_t size);
-void * gim_realloc(void *ptr, size_t oldsize, size_t newsize);
+void *gim_alloc(size_t size);
+void *gim_alloca(size_t size);
+void *gim_realloc(void *ptr, size_t oldsize, size_t newsize);
void gim_free(void *ptr);
-
-
-#if defined (_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
- #define GIM_SIMD_MEMORY 1
+#if defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
+#define GIM_SIMD_MEMORY 1
#endif
//! SIMD POINTER INTEGER
@@ -126,11 +117,10 @@ void gim_free(void *ptr);
//! SIMD INTEGER SIZE
#define SIMD_T_SIZE sizeof(SIMD_T)
-
-inline void gim_simd_memcpy(void * dst, const void * src, size_t copysize)
+inline void gim_simd_memcpy(void *dst, const void *src, size_t copysize)
{
#ifdef GIM_SIMD_MEMORY
-/*
+ /*
//'long long int' is incompatible with visual studio 6...
//copy words
SIMD_T * ui_src_ptr = (SIMD_T *)src;
@@ -143,48 +133,45 @@ inline void gim_simd_memcpy(void * dst, const void * src, size_t copysize)
if(copysize==0) return;
*/
- char * c_src_ptr = (char *)src;
- char * c_dst_ptr = (char *)dst;
- while(copysize>0)
- {
- *(c_dst_ptr++) = *(c_src_ptr++);
- copysize--;
- }
- return;
+ char *c_src_ptr = (char *)src;
+ char *c_dst_ptr = (char *)dst;
+ while (copysize > 0)
+ {
+ *(c_dst_ptr++) = *(c_src_ptr++);
+ copysize--;
+ }
+ return;
#else
- memcpy(dst,src,copysize);
+ memcpy(dst, src, copysize);
#endif
}
-
-
-template<class T>
-inline void gim_swap_elements(T* _array,size_t _i,size_t _j)
+template <class T>
+inline void gim_swap_elements(T *_array, size_t _i, size_t _j)
{
T _e_tmp_ = _array[_i];
_array[_i] = _array[_j];
_array[_j] = _e_tmp_;
}
-
-template<class T>
-inline void gim_swap_elements_memcpy(T* _array,size_t _i,size_t _j)
+template <class T>
+inline void gim_swap_elements_memcpy(T *_array, size_t _i, size_t _j)
{
char _e_tmp_[sizeof(T)];
- gim_simd_memcpy(_e_tmp_,&_array[_i],sizeof(T));
- gim_simd_memcpy(&_array[_i],&_array[_j],sizeof(T));
- gim_simd_memcpy(&_array[_j],_e_tmp_,sizeof(T));
+ gim_simd_memcpy(_e_tmp_, &_array[_i], sizeof(T));
+ gim_simd_memcpy(&_array[_i], &_array[_j], sizeof(T));
+ gim_simd_memcpy(&_array[_j], _e_tmp_, sizeof(T));
}
template <int SIZE>
-inline void gim_swap_elements_ptr(char * _array,size_t _i,size_t _j)
+inline void gim_swap_elements_ptr(char *_array, size_t _i, size_t _j)
{
char _e_tmp_[SIZE];
- _i*=SIZE;
- _j*=SIZE;
- gim_simd_memcpy(_e_tmp_,_array+_i,SIZE);
- gim_simd_memcpy(_array+_i,_array+_j,SIZE);
- gim_simd_memcpy(_array+_j,_e_tmp_,SIZE);
+ _i *= SIZE;
+ _j *= SIZE;
+ gim_simd_memcpy(_e_tmp_, _array + _i, SIZE);
+ gim_simd_memcpy(_array + _i, _array + _j, SIZE);
+ gim_simd_memcpy(_array + _j, _e_tmp_, SIZE);
}
-#endif // GIM_MEMORY_H_INCLUDED
+#endif // GIM_MEMORY_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_radixsort.h b/thirdparty/bullet/BulletCollision/Gimpact/gim_radixsort.h
index c246ef1254..ff7907adca 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_radixsort.h
+++ b/thirdparty/bullet/BulletCollision/Gimpact/gim_radixsort.h
@@ -40,24 +40,22 @@ email: projectileman@yahoo.com
//! Prototype for comparators
class less_comparator
{
- public:
-
- template<class T,class Z>
- inline int operator() ( const T& a, const Z& b )
+public:
+ template <class T, class Z>
+ inline int operator()(const T& a, const Z& b)
{
- return ( a<b?-1:(a>b?1:0));
+ return (a < b ? -1 : (a > b ? 1 : 0));
}
};
//! Prototype for comparators
class integer_comparator
{
- public:
-
- template<class T>
- inline int operator() ( const T& a, const T& b )
+public:
+ template <class T>
+ inline int operator()(const T& a, const T& b)
{
- return (int)(a-b);
+ return (int)(a - b);
}
};
@@ -65,20 +63,19 @@ class integer_comparator
class uint_key_func
{
public:
- template<class T>
- inline GUINT operator()( const T& a)
+ template <class T>
+ inline GUINT operator()(const T& a)
{
return (GUINT)a;
}
};
-
//!Prototype for copying elements
class copy_elements_func
{
public:
- template<class T>
- inline void operator()(T& a,T& b)
+ template <class T>
+ inline void operator()(T& a, T& b)
{
a = b;
}
@@ -88,34 +85,33 @@ public:
class memcopy_elements_func
{
public:
- template<class T>
- inline void operator()(T& a,T& b)
+ template <class T>
+ inline void operator()(T& a, T& b)
{
- gim_simd_memcpy(&a,&b,sizeof(T));
+ gim_simd_memcpy(&a, &b, sizeof(T));
}
};
-
//! @{
struct GIM_RSORT_TOKEN
{
- GUINT m_key;
- GUINT m_value;
- GIM_RSORT_TOKEN()
- {
- }
- GIM_RSORT_TOKEN(const GIM_RSORT_TOKEN& rtoken)
- {
- m_key = rtoken.m_key;
- m_value = rtoken.m_value;
- }
+ GUINT m_key;
+ GUINT m_value;
+ GIM_RSORT_TOKEN()
+ {
+ }
+ GIM_RSORT_TOKEN(const GIM_RSORT_TOKEN& rtoken)
+ {
+ m_key = rtoken.m_key;
+ m_value = rtoken.m_value;
+ }
- inline bool operator <(const GIM_RSORT_TOKEN& other) const
+ inline bool operator<(const GIM_RSORT_TOKEN& other) const
{
return (m_key < other.m_key);
}
- inline bool operator >(const GIM_RSORT_TOKEN& other) const
+ inline bool operator>(const GIM_RSORT_TOKEN& other) const
{
return (m_key > other.m_key);
}
@@ -124,33 +120,28 @@ struct GIM_RSORT_TOKEN
//! Prototype for comparators
class GIM_RSORT_TOKEN_COMPARATOR
{
- public:
-
- inline int operator()( const GIM_RSORT_TOKEN& a, const GIM_RSORT_TOKEN& b )
+public:
+ inline int operator()(const GIM_RSORT_TOKEN& a, const GIM_RSORT_TOKEN& b)
{
return (int)((a.m_key) - (b.m_key));
}
};
-
-
#define kHist 2048
// ---- utils for accessing 11-bit quantities
-#define D11_0(x) (x & 0x7FF)
-#define D11_1(x) (x >> 11 & 0x7FF)
-#define D11_2(x) (x >> 22 )
-
-
+#define D11_0(x) (x & 0x7FF)
+#define D11_1(x) (x >> 11 & 0x7FF)
+#define D11_2(x) (x >> 22)
///Radix sort for unsigned integer keys
inline void gim_radix_sort_rtokens(
- GIM_RSORT_TOKEN * array,
- GIM_RSORT_TOKEN * sorted, GUINT element_count)
+ GIM_RSORT_TOKEN* array,
+ GIM_RSORT_TOKEN* sorted, GUINT element_count)
{
GUINT i;
GUINT b0[kHist * 3];
- GUINT *b1 = b0 + kHist;
- GUINT *b2 = b1 + kHist;
+ GUINT* b1 = b0 + kHist;
+ GUINT* b2 = b1 + kHist;
for (i = 0; i < kHist * 3; ++i)
{
b0[i] = 0;
@@ -159,10 +150,10 @@ inline void gim_radix_sort_rtokens(
GUINT pos;
for (i = 0; i < element_count; ++i)
{
- fi = array[i].m_key;
- b0[D11_0(fi)] ++;
- b1[D11_1(fi)] ++;
- b2[D11_2(fi)] ++;
+ fi = array[i].m_key;
+ b0[D11_0(fi)]++;
+ b1[D11_1(fi)]++;
+ b2[D11_2(fi)]++;
}
{
GUINT sum0 = 0, sum1 = 0, sum2 = 0;
@@ -182,7 +173,7 @@ inline void gim_radix_sort_rtokens(
}
for (i = 0; i < element_count; ++i)
{
- fi = array[i].m_key;
+ fi = array[i].m_key;
pos = D11_0(fi);
pos = ++b0[pos];
sorted[pos].m_key = array[i].m_key;
@@ -190,7 +181,7 @@ inline void gim_radix_sort_rtokens(
}
for (i = 0; i < element_count; ++i)
{
- fi = sorted[i].m_key;
+ fi = sorted[i].m_key;
pos = D11_1(fi);
pos = ++b1[pos];
array[pos].m_key = sorted[i].m_key;
@@ -198,7 +189,7 @@ inline void gim_radix_sort_rtokens(
}
for (i = 0; i < element_count; ++i)
{
- fi = array[i].m_key;
+ fi = array[i].m_key;
pos = D11_2(fi);
pos = ++b2[pos];
sorted[pos].m_key = array[i].m_key;
@@ -206,9 +197,6 @@ inline void gim_radix_sort_rtokens(
}
}
-
-
-
/// Get the sorted tokens from an array. For generic use. Tokens are IRR_RSORT_TOKEN
/*!
*\param array Array of elements to sort
@@ -216,21 +204,21 @@ inline void gim_radix_sort_rtokens(
*\param element_count element count
*\param uintkey_macro Functor which retrieves the integer representation of an array element
*/
-template<typename T, class GETKEY_CLASS>
+template <typename T, class GETKEY_CLASS>
void gim_radix_sort_array_tokens(
- T* array ,
- GIM_RSORT_TOKEN * sorted_tokens,
- GUINT element_count,GETKEY_CLASS uintkey_macro)
+ T* array,
+ GIM_RSORT_TOKEN* sorted_tokens,
+ GUINT element_count, GETKEY_CLASS uintkey_macro)
{
- GIM_RSORT_TOKEN * _unsorted = (GIM_RSORT_TOKEN *) gim_alloc(sizeof(GIM_RSORT_TOKEN)*element_count);
- for (GUINT _i=0;_i<element_count;++_i)
- {
- _unsorted[_i].m_key = uintkey_macro(array[_i]);
- _unsorted[_i].m_value = _i;
- }
- gim_radix_sort_rtokens(_unsorted,sorted_tokens,element_count);
- gim_free(_unsorted);
- gim_free(_unsorted);
+ GIM_RSORT_TOKEN* _unsorted = (GIM_RSORT_TOKEN*)gim_alloc(sizeof(GIM_RSORT_TOKEN) * element_count);
+ for (GUINT _i = 0; _i < element_count; ++_i)
+ {
+ _unsorted[_i].m_key = uintkey_macro(array[_i]);
+ _unsorted[_i].m_value = _i;
+ }
+ gim_radix_sort_rtokens(_unsorted, sorted_tokens, element_count);
+ gim_free(_unsorted);
+ gim_free(_unsorted);
}
/// Sorts array in place. For generic use
@@ -241,21 +229,21 @@ void gim_radix_sort_array_tokens(
\param get_uintkey_macro Macro for extract the Integer value of the element. Similar to SIMPLE_GET_UINTKEY
\param copy_elements_macro Macro for copy elements, similar to SIMPLE_COPY_ELEMENTS
*/
-template<typename T, class GETKEY_CLASS, class COPY_CLASS>
+template <typename T, class GETKEY_CLASS, class COPY_CLASS>
void gim_radix_sort(
- T * array, GUINT element_count,
+ T* array, GUINT element_count,
GETKEY_CLASS get_uintkey_macro, COPY_CLASS copy_elements_macro)
{
- GIM_RSORT_TOKEN * _sorted = (GIM_RSORT_TOKEN *) gim_alloc(sizeof(GIM_RSORT_TOKEN)*element_count);
- gim_radix_sort_array_tokens(array,_sorted,element_count,get_uintkey_macro);
- T * _original_array = (T *) gim_alloc(sizeof(T)*element_count);
- gim_simd_memcpy(_original_array,array,sizeof(T)*element_count);
- for (GUINT _i=0;_i<element_count;++_i)
- {
- copy_elements_macro(array[_i],_original_array[_sorted[_i].m_value]);
- }
- gim_free(_original_array);
- gim_free(_sorted);
+ GIM_RSORT_TOKEN* _sorted = (GIM_RSORT_TOKEN*)gim_alloc(sizeof(GIM_RSORT_TOKEN) * element_count);
+ gim_radix_sort_array_tokens(array, _sorted, element_count, get_uintkey_macro);
+ T* _original_array = (T*)gim_alloc(sizeof(T) * element_count);
+ gim_simd_memcpy(_original_array, array, sizeof(T) * element_count);
+ for (GUINT _i = 0; _i < element_count; ++_i)
+ {
+ copy_elements_macro(array[_i], _original_array[_sorted[_i].m_value]);
+ }
+ gim_free(_original_array);
+ gim_free(_sorted);
}
//! Failsafe Iterative binary search,
@@ -269,20 +257,20 @@ If the element is not found, it returns the nearest upper element position, may
\param _found If true the value has found. Boolean
\param _result_index the index of the found element, or if not found then it will get the index of the closest bigger value
*/
-template<class T, typename KEYCLASS, typename COMP_CLASS>
-bool gim_binary_search_ex(
- const T* _array, GUINT _start_i,
- GUINT _end_i,GUINT & _result_index,
- const KEYCLASS & _search_key,
- COMP_CLASS _comp_macro)
+template <class T, typename KEYCLASS, typename COMP_CLASS>
+bool gim_binary_search_ex(
+ const T* _array, GUINT _start_i,
+ GUINT _end_i, GUINT& _result_index,
+ const KEYCLASS& _search_key,
+ COMP_CLASS _comp_macro)
{
GUINT _k;
int _comp_result;
GUINT _i = _start_i;
- GUINT _j = _end_i+1;
+ GUINT _j = _end_i + 1;
while (_i < _j)
{
- _k = (_j+_i-1)/2;
+ _k = (_j + _i - 1) / 2;
_comp_result = _comp_macro(_array[_k], _search_key);
if (_comp_result == 0)
{
@@ -291,7 +279,7 @@ bool gim_binary_search_ex(
}
else if (_comp_result < 0)
{
- _i = _k+1;
+ _i = _k + 1;
}
else
{
@@ -302,8 +290,6 @@ bool gim_binary_search_ex(
return false;
}
-
-
//! Failsafe Iterative binary search,Template version
/*!
If the element is not found, it returns the nearest upper element position, may be the further position after the last element.
@@ -314,26 +300,26 @@ If the element is not found, it returns the nearest upper element position, may
\param _result_index the index of the found element, or if not found then it will get the index of the closest bigger value
\return true if found, else false
*/
-template<class T>
+template <class T>
bool gim_binary_search(
- const T*_array,GUINT _start_i,
- GUINT _end_i,const T & _search_key,
- GUINT & _result_index)
+ const T* _array, GUINT _start_i,
+ GUINT _end_i, const T& _search_key,
+ GUINT& _result_index)
{
GUINT _i = _start_i;
- GUINT _j = _end_i+1;
+ GUINT _j = _end_i + 1;
GUINT _k;
- while(_i < _j)
+ while (_i < _j)
{
- _k = (_j+_i-1)/2;
- if(_array[_k]==_search_key)
+ _k = (_j + _i - 1) / 2;
+ if (_array[_k] == _search_key)
{
_result_index = _k;
return true;
}
- else if (_array[_k]<_search_key)
+ else if (_array[_k] < _search_key)
{
- _i = _k+1;
+ _i = _k + 1;
}
else
{
@@ -344,27 +330,25 @@ bool gim_binary_search(
return false;
}
-
-
///heap sort from http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Heap/
template <typename T, typename COMP_CLASS>
-void gim_down_heap(T *pArr, GUINT k, GUINT n,COMP_CLASS CompareFunc)
+void gim_down_heap(T* pArr, GUINT k, GUINT n, COMP_CLASS CompareFunc)
{
/* PRE: a[k+1..N] is a heap */
/* POST: a[k..N] is a heap */
T temp = pArr[k - 1];
/* k has child(s) */
- while (k <= n/2)
+ while (k <= n / 2)
{
- int child = 2*k;
+ int child = 2 * k;
- if ((child < (int)n) && CompareFunc(pArr[child - 1] , pArr[child])<0)
+ if ((child < (int)n) && CompareFunc(pArr[child - 1], pArr[child]) < 0)
{
child++;
}
/* pick larger child */
- if (CompareFunc(temp , pArr[child - 1])<0)
+ if (CompareFunc(temp, pArr[child - 1]) < 0)
{
/* move child up */
pArr[k - 1] = pArr[child - 1];
@@ -378,29 +362,25 @@ void gim_down_heap(T *pArr, GUINT k, GUINT n,COMP_CLASS CompareFunc)
pArr[k - 1] = temp;
} /*downHeap*/
-
template <typename T, typename COMP_CLASS>
-void gim_heap_sort(T *pArr, GUINT element_count, COMP_CLASS CompareFunc)
+void gim_heap_sort(T* pArr, GUINT element_count, COMP_CLASS CompareFunc)
{
/* sort a[0..N-1], N.B. 0 to N-1 */
GUINT k;
GUINT n = element_count;
- for (k = n/2; k > 0; k--)
+ for (k = n / 2; k > 0; k--)
{
gim_down_heap(pArr, k, n, CompareFunc);
}
/* a[1..N] is now a heap */
- while ( n>=2 )
+ while (n >= 2)
{
- gim_swap_elements(pArr,0,n-1); /* largest of a[0..n-1] */
+ gim_swap_elements(pArr, 0, n - 1); /* largest of a[0..n-1] */
--n;
/* restore a[1..i-1] heap */
gim_down_heap(pArr, 1, n, CompareFunc);
}
}
-
-
-
-#endif // GIM_RADIXSORT_H_INCLUDED
+#endif // GIM_RADIXSORT_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_tri_collision.cpp b/thirdparty/bullet/BulletCollision/Gimpact/gim_tri_collision.cpp
index f9727e1d53..8d83e95da4 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_tri_collision.cpp
+++ b/thirdparty/bullet/BulletCollision/Gimpact/gim_tri_collision.cpp
@@ -33,15 +33,13 @@ email: projectileman@yahoo.com
#include "gim_tri_collision.h"
-
#define TRI_LOCAL_EPSILON 0.000001f
#define MIN_EDGE_EDGE_DIS 0.00001f
-
class GIM_TRIANGLE_CALCULATION_CACHE
{
public:
- GREAL margin;
+ GREAL margin;
btVector3 tu_vertices[3];
btVector3 tv_vertices[3];
btVector4 tu_plane;
@@ -55,46 +53,47 @@ public:
GREAL du0du2;
GREAL dv[4];
GREAL dv0dv1;
- GREAL dv0dv2;
+ GREAL dv0dv2;
btVector3 temp_points[MAX_TRI_CLIPPING];
btVector3 temp_points1[MAX_TRI_CLIPPING];
btVector3 contact_points[MAX_TRI_CLIPPING];
-
-
//! if returns false, the faces are paralele
SIMD_FORCE_INLINE bool compute_intervals(
- const GREAL &D0,
- const GREAL &D1,
- const GREAL &D2,
- const GREAL &D0D1,
- const GREAL &D0D2,
- GREAL & scale_edge0,
- GREAL & scale_edge1,
- GUINT &edge_index0,
- GUINT &edge_index1)
+ const GREAL &D0,
+ const GREAL &D1,
+ const GREAL &D2,
+ const GREAL &D0D1,
+ const GREAL &D0D2,
+ GREAL &scale_edge0,
+ GREAL &scale_edge1,
+ GUINT &edge_index0,
+ GUINT &edge_index1)
{
- if(D0D1>0.0f)
+ 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 */
- scale_edge0 = -D2/(D0-D2);
- scale_edge1 = -D1/(D2-D1);
- edge_index0 = 2;edge_index1 = 1;
+ scale_edge0 = -D2 / (D0 - D2);
+ scale_edge1 = -D1 / (D2 - D1);
+ edge_index0 = 2;
+ edge_index1 = 1;
}
- else if(D0D2>0.0f)
+ else if (D0D2 > 0.0f)
{
/* here we know that d0d1<=0.0 */
- scale_edge0 = -D0/(D1-D0);
- scale_edge1 = -D1/(D2-D1);
- edge_index0 = 0;edge_index1 = 1;
+ scale_edge0 = -D0 / (D1 - D0);
+ scale_edge1 = -D1 / (D2 - D1);
+ edge_index0 = 0;
+ edge_index1 = 1;
}
- else if(D1*D2>0.0f || D0!=0.0f)
+ else if (D1 * D2 > 0.0f || D0 != 0.0f)
{
/* here we know that d0d1<=0.0 or that D0!=0.0 */
- scale_edge0 = -D0/(D1-D0);
- scale_edge1 = -D2/(D0-D2);
- edge_index0 = 0 ;edge_index1 = 2;
+ scale_edge0 = -D0 / (D1 - D0);
+ scale_edge1 = -D2 / (D0 - D2);
+ edge_index0 = 0;
+ edge_index1 = 2;
}
else
{
@@ -103,46 +102,44 @@ public:
return true;
}
-
//! clip triangle
/*!
*/
SIMD_FORCE_INLINE GUINT clip_triangle(
- const btVector4 & tri_plane,
- const btVector3 * tripoints,
- const btVector3 * srcpoints,
- btVector3 * clip_points)
+ const btVector4 &tri_plane,
+ const btVector3 *tripoints,
+ const btVector3 *srcpoints,
+ btVector3 *clip_points)
{
// edge 0
btVector4 edgeplane;
- EDGE_PLANE(tripoints[0],tripoints[1],tri_plane,edgeplane);
+ EDGE_PLANE(tripoints[0], tripoints[1], tri_plane, edgeplane);
GUINT clipped_count = PLANE_CLIP_TRIANGLE3D(
- edgeplane,srcpoints[0],srcpoints[1],srcpoints[2],temp_points);
+ edgeplane, srcpoints[0], srcpoints[1], srcpoints[2], temp_points);
- if(clipped_count == 0) return 0;
+ if (clipped_count == 0) return 0;
// edge 1
- EDGE_PLANE(tripoints[1],tripoints[2],tri_plane,edgeplane);
+ EDGE_PLANE(tripoints[1], tripoints[2], tri_plane, edgeplane);
clipped_count = PLANE_CLIP_POLYGON3D(
- edgeplane,temp_points,clipped_count,temp_points1);
+ edgeplane, temp_points, clipped_count, temp_points1);
- if(clipped_count == 0) return 0;
+ if (clipped_count == 0) return 0;
// edge 2
- EDGE_PLANE(tripoints[2],tripoints[0],tri_plane,edgeplane);
+ EDGE_PLANE(tripoints[2], tripoints[0], tri_plane, edgeplane);
clipped_count = PLANE_CLIP_POLYGON3D(
- edgeplane,temp_points1,clipped_count,clip_points);
+ edgeplane, temp_points1, clipped_count, clip_points);
return clipped_count;
-
/*GUINT i0 = (tri_plane.closestAxis()+1)%3;
GUINT i1 = (i0+1)%3;
// edge 0
@@ -172,13 +169,13 @@ public:
}
SIMD_FORCE_INLINE void sort_isect(
- GREAL & isect0,GREAL & isect1,GUINT &e0,GUINT &e1,btVector3 & vec0,btVector3 & vec1)
+ GREAL &isect0, GREAL &isect1, GUINT &e0, GUINT &e1, btVector3 &vec0, btVector3 &vec1)
{
- if(isect1<isect0)
+ if (isect1 < isect0)
{
//swap
- GIM_SWAP_NUMBERS(isect0,isect1);
- GIM_SWAP_NUMBERS(e0,e1);
+ GIM_SWAP_NUMBERS(isect0, isect1);
+ GIM_SWAP_NUMBERS(e0, e1);
btVector3 tmp = vec0;
vec0 = vec1;
vec1 = tmp;
@@ -202,53 +199,52 @@ public:
// Compute direction of intersection line
edge_edge_dir = tu_plane.cross(tv_plane);
GREAL Dlen;
- VEC_LENGTH(edge_edge_dir,Dlen);
+ VEC_LENGTH(edge_edge_dir, Dlen);
- if(Dlen<0.0001)
+ if (Dlen < 0.0001)
{
- return 0; //faces near paralele
+ return 0; //faces near paralele
}
- edge_edge_dir*= 1/Dlen;//normalize
-
+ edge_edge_dir *= 1 / Dlen; //normalize
// Compute interval for triangle 1
- GUINT tu_e0,tu_e1;//edge indices
- GREAL tu_scale_e0,tu_scale_e1;//edge scale
- if(!compute_intervals(du[0],du[1],du[2],
- du0du1,du0du2,tu_scale_e0,tu_scale_e1,tu_e0,tu_e1)) return 0;
+ GUINT tu_e0, tu_e1; //edge indices
+ GREAL tu_scale_e0, tu_scale_e1; //edge scale
+ if (!compute_intervals(du[0], du[1], du[2],
+ du0du1, du0du2, tu_scale_e0, tu_scale_e1, tu_e0, tu_e1)) return 0;
// Compute interval for triangle 2
- GUINT tv_e0,tv_e1;//edge indices
- GREAL tv_scale_e0,tv_scale_e1;//edge scale
+ GUINT tv_e0, tv_e1; //edge indices
+ GREAL tv_scale_e0, tv_scale_e1; //edge scale
- if(!compute_intervals(dv[0],dv[1],dv[2],
- dv0dv1,dv0dv2,tv_scale_e0,tv_scale_e1,tv_e0,tv_e1)) return 0;
+ if (!compute_intervals(dv[0], dv[1], dv[2],
+ dv0dv1, dv0dv2, tv_scale_e0, tv_scale_e1, tv_e0, tv_e1)) return 0;
//proyected vertices
- btVector3 up_e0 = tu_vertices[tu_e0].lerp(tu_vertices[(tu_e0+1)%3],tu_scale_e0);
- btVector3 up_e1 = tu_vertices[tu_e1].lerp(tu_vertices[(tu_e1+1)%3],tu_scale_e1);
+ btVector3 up_e0 = tu_vertices[tu_e0].lerp(tu_vertices[(tu_e0 + 1) % 3], tu_scale_e0);
+ btVector3 up_e1 = tu_vertices[tu_e1].lerp(tu_vertices[(tu_e1 + 1) % 3], tu_scale_e1);
- btVector3 vp_e0 = tv_vertices[tv_e0].lerp(tv_vertices[(tv_e0+1)%3],tv_scale_e0);
- btVector3 vp_e1 = tv_vertices[tv_e1].lerp(tv_vertices[(tv_e1+1)%3],tv_scale_e1);
+ btVector3 vp_e0 = tv_vertices[tv_e0].lerp(tv_vertices[(tv_e0 + 1) % 3], tv_scale_e0);
+ btVector3 vp_e1 = tv_vertices[tv_e1].lerp(tv_vertices[(tv_e1 + 1) % 3], tv_scale_e1);
//proyected intervals
- GREAL isect_u[] = {up_e0.dot(edge_edge_dir),up_e1.dot(edge_edge_dir)};
- GREAL isect_v[] = {vp_e0.dot(edge_edge_dir),vp_e1.dot(edge_edge_dir)};
+ GREAL isect_u[] = {up_e0.dot(edge_edge_dir), up_e1.dot(edge_edge_dir)};
+ GREAL isect_v[] = {vp_e0.dot(edge_edge_dir), vp_e1.dot(edge_edge_dir)};
- sort_isect(isect_u[0],isect_u[1],tu_e0,tu_e1,up_e0,up_e1);
- sort_isect(isect_v[0],isect_v[1],tv_e0,tv_e1,vp_e0,vp_e1);
+ sort_isect(isect_u[0], isect_u[1], tu_e0, tu_e1, up_e0, up_e1);
+ sort_isect(isect_v[0], isect_v[1], tv_e0, tv_e1, vp_e0, vp_e1);
- const GREAL midpoint_u = 0.5f*(isect_u[0]+isect_u[1]); // midpoint
- const GREAL midpoint_v = 0.5f*(isect_v[0]+isect_v[1]); // midpoint
+ const GREAL midpoint_u = 0.5f * (isect_u[0] + isect_u[1]); // midpoint
+ const GREAL midpoint_v = 0.5f * (isect_v[0] + isect_v[1]); // midpoint
- if(midpoint_u<midpoint_v)
+ if (midpoint_u < midpoint_v)
{
- if(isect_u[1]>=isect_v[1]) // face U casts face V
+ if (isect_u[1] >= isect_v[1]) // face U casts face V
{
return 1;
}
- else if(isect_v[0]<=isect_u[0]) // face V casts face U
+ else if (isect_v[0] <= isect_u[0]) // face V casts face U
{
return 2;
}
@@ -257,32 +253,31 @@ public:
closest_point_v = vp_e0;
// calc edges and separation
- if(isect_u[1]+ MIN_EDGE_EDGE_DIS<isect_v[0]) //calc distance between two lines instead
+ if (isect_u[1] + MIN_EDGE_EDGE_DIS < isect_v[0]) //calc distance between two lines instead
{
SEGMENT_COLLISION(
- tu_vertices[tu_e1],tu_vertices[(tu_e1+1)%3],
- tv_vertices[tv_e0],tv_vertices[(tv_e0+1)%3],
+ tu_vertices[tu_e1], tu_vertices[(tu_e1 + 1) % 3],
+ tv_vertices[tv_e0], tv_vertices[(tv_e0 + 1) % 3],
closest_point_u,
closest_point_v);
- edge_edge_dir = closest_point_u-closest_point_v;
- VEC_LENGTH(edge_edge_dir,distances[2]);
- edge_edge_dir *= 1.0f/distances[2];// normalize
+ edge_edge_dir = closest_point_u - closest_point_v;
+ VEC_LENGTH(edge_edge_dir, distances[2]);
+ edge_edge_dir *= 1.0f / distances[2]; // normalize
}
else
{
- distances[2] = isect_v[0]-isect_u[1];//distance negative
- //edge_edge_dir *= -1.0f; //normal pointing from V to U
+ distances[2] = isect_v[0] - isect_u[1]; //distance negative
+ //edge_edge_dir *= -1.0f; //normal pointing from V to U
}
-
}
else
{
- if(isect_v[1]>=isect_u[1]) // face V casts face U
+ if (isect_v[1] >= isect_u[1]) // face V casts face U
{
return 2;
}
- else if(isect_u[0]<=isect_v[0]) // face U casts face V
+ else if (isect_u[0] <= isect_v[0]) // face U casts face V
{
return 1;
}
@@ -291,41 +286,39 @@ public:
closest_point_v = vp_e1;
// calc edges and separation
- if(isect_v[1]+MIN_EDGE_EDGE_DIS<isect_u[0]) //calc distance between two lines instead
+ if (isect_v[1] + MIN_EDGE_EDGE_DIS < isect_u[0]) //calc distance between two lines instead
{
SEGMENT_COLLISION(
- tu_vertices[tu_e0],tu_vertices[(tu_e0+1)%3],
- tv_vertices[tv_e1],tv_vertices[(tv_e1+1)%3],
+ tu_vertices[tu_e0], tu_vertices[(tu_e0 + 1) % 3],
+ tv_vertices[tv_e1], tv_vertices[(tv_e1 + 1) % 3],
closest_point_u,
closest_point_v);
- edge_edge_dir = closest_point_u-closest_point_v;
- VEC_LENGTH(edge_edge_dir,distances[2]);
- edge_edge_dir *= 1.0f/distances[2];// normalize
+ edge_edge_dir = closest_point_u - closest_point_v;
+ VEC_LENGTH(edge_edge_dir, distances[2]);
+ edge_edge_dir *= 1.0f / distances[2]; // normalize
}
else
{
- distances[2] = isect_u[0]-isect_v[1];//distance negative
- //edge_edge_dir *= -1.0f; //normal pointing from V to U
+ distances[2] = isect_u[0] - isect_v[1]; //distance negative
+ //edge_edge_dir *= -1.0f; //normal pointing from V to U
}
}
return 3;
}
-
//! collides by two sides
SIMD_FORCE_INLINE bool triangle_collision(
- const btVector3 & u0,
- const btVector3 & u1,
- const btVector3 & u2,
- GREAL margin_u,
- const btVector3 & v0,
- const btVector3 & v1,
- const btVector3 & v2,
- GREAL margin_v,
- GIM_TRIANGLE_CONTACT_DATA & contacts)
+ const btVector3 &u0,
+ const btVector3 &u1,
+ const btVector3 &u2,
+ GREAL margin_u,
+ const btVector3 &v0,
+ const btVector3 &v1,
+ const btVector3 &v2,
+ GREAL margin_v,
+ GIM_TRIANGLE_CONTACT_DATA &contacts)
{
-
margin = margin_u + margin_v;
tu_vertices[0] = u0;
@@ -339,103 +332,99 @@ public:
//create planes
// plane v vs U points
- TRIANGLE_PLANE(tv_vertices[0],tv_vertices[1],tv_vertices[2],tv_plane);
-
- du[0] = DISTANCE_PLANE_POINT(tv_plane,tu_vertices[0]);
- du[1] = DISTANCE_PLANE_POINT(tv_plane,tu_vertices[1]);
- du[2] = DISTANCE_PLANE_POINT(tv_plane,tu_vertices[2]);
+ TRIANGLE_PLANE(tv_vertices[0], tv_vertices[1], tv_vertices[2], tv_plane);
+ du[0] = DISTANCE_PLANE_POINT(tv_plane, tu_vertices[0]);
+ du[1] = DISTANCE_PLANE_POINT(tv_plane, tu_vertices[1]);
+ du[2] = DISTANCE_PLANE_POINT(tv_plane, tu_vertices[2]);
du0du1 = du[0] * du[1];
du0du2 = du[0] * du[2];
-
- if(du0du1>0.0f && du0du2>0.0f) // same sign on all of them + not equal 0 ?
+ if (du0du1 > 0.0f && du0du2 > 0.0f) // same sign on all of them + not equal 0 ?
{
- if(du[0]<0) //we need test behind the triangle plane
+ if (du[0] < 0) //we need test behind the triangle plane
{
- distances[0] = GIM_MAX3(du[0],du[1],du[2]);
+ distances[0] = GIM_MAX3(du[0], du[1], du[2]);
distances[0] = -distances[0];
- if(distances[0]>margin) return false; //never intersect
+ if (distances[0] > margin) return false; //never intersect
//reorder triangle v
- VEC_SWAP(tv_vertices[0],tv_vertices[1]);
- VEC_SCALE_4(tv_plane,-1.0f,tv_plane);
+ VEC_SWAP(tv_vertices[0], tv_vertices[1]);
+ VEC_SCALE_4(tv_plane, -1.0f, tv_plane);
}
else
{
- distances[0] = GIM_MIN3(du[0],du[1],du[2]);
- if(distances[0]>margin) return false; //never intersect
+ distances[0] = GIM_MIN3(du[0], du[1], du[2]);
+ if (distances[0] > margin) return false; //never intersect
}
}
else
{
//Look if we need to invert the triangle
- distances[0] = (du[0]+du[1]+du[2])/3.0f; //centroid
+ distances[0] = (du[0] + du[1] + du[2]) / 3.0f; //centroid
- if(distances[0]<0.0f)
+ if (distances[0] < 0.0f)
{
//reorder triangle v
- VEC_SWAP(tv_vertices[0],tv_vertices[1]);
- VEC_SCALE_4(tv_plane,-1.0f,tv_plane);
+ VEC_SWAP(tv_vertices[0], tv_vertices[1]);
+ VEC_SCALE_4(tv_plane, -1.0f, tv_plane);
- distances[0] = GIM_MAX3(du[0],du[1],du[2]);
+ distances[0] = GIM_MAX3(du[0], du[1], du[2]);
distances[0] = -distances[0];
}
else
{
- distances[0] = GIM_MIN3(du[0],du[1],du[2]);
+ distances[0] = GIM_MIN3(du[0], du[1], du[2]);
}
}
-
// plane U vs V points
- TRIANGLE_PLANE(tu_vertices[0],tu_vertices[1],tu_vertices[2],tu_plane);
+ TRIANGLE_PLANE(tu_vertices[0], tu_vertices[1], tu_vertices[2], tu_plane);
- dv[0] = DISTANCE_PLANE_POINT(tu_plane,tv_vertices[0]);
- dv[1] = DISTANCE_PLANE_POINT(tu_plane,tv_vertices[1]);
- dv[2] = DISTANCE_PLANE_POINT(tu_plane,tv_vertices[2]);
+ dv[0] = DISTANCE_PLANE_POINT(tu_plane, tv_vertices[0]);
+ dv[1] = DISTANCE_PLANE_POINT(tu_plane, tv_vertices[1]);
+ dv[2] = DISTANCE_PLANE_POINT(tu_plane, tv_vertices[2]);
dv0dv1 = dv[0] * dv[1];
dv0dv2 = dv[0] * dv[2];
-
- if(dv0dv1>0.0f && dv0dv2>0.0f) // same sign on all of them + not equal 0 ?
+ if (dv0dv1 > 0.0f && dv0dv2 > 0.0f) // same sign on all of them + not equal 0 ?
{
- if(dv[0]<0) //we need test behind the triangle plane
+ if (dv[0] < 0) //we need test behind the triangle plane
{
- distances[1] = GIM_MAX3(dv[0],dv[1],dv[2]);
+ distances[1] = GIM_MAX3(dv[0], dv[1], dv[2]);
distances[1] = -distances[1];
- if(distances[1]>margin) return false; //never intersect
+ if (distances[1] > margin) return false; //never intersect
//reorder triangle u
- VEC_SWAP(tu_vertices[0],tu_vertices[1]);
- VEC_SCALE_4(tu_plane,-1.0f,tu_plane);
+ VEC_SWAP(tu_vertices[0], tu_vertices[1]);
+ VEC_SCALE_4(tu_plane, -1.0f, tu_plane);
}
else
{
- distances[1] = GIM_MIN3(dv[0],dv[1],dv[2]);
- if(distances[1]>margin) return false; //never intersect
+ distances[1] = GIM_MIN3(dv[0], dv[1], dv[2]);
+ if (distances[1] > margin) return false; //never intersect
}
}
else
{
//Look if we need to invert the triangle
- distances[1] = (dv[0]+dv[1]+dv[2])/3.0f; //centroid
+ distances[1] = (dv[0] + dv[1] + dv[2]) / 3.0f; //centroid
- if(distances[1]<0.0f)
+ if (distances[1] < 0.0f)
{
//reorder triangle v
- VEC_SWAP(tu_vertices[0],tu_vertices[1]);
- VEC_SCALE_4(tu_plane,-1.0f,tu_plane);
+ VEC_SWAP(tu_vertices[0], tu_vertices[1]);
+ VEC_SCALE_4(tu_plane, -1.0f, tu_plane);
- distances[1] = GIM_MAX3(dv[0],dv[1],dv[2]);
+ distances[1] = GIM_MAX3(dv[0], dv[1], dv[2]);
distances[1] = -distances[1];
}
else
{
- distances[1] = GIM_MIN3(dv[0],dv[1],dv[2]);
+ distances[1] = GIM_MIN3(dv[0], dv[1], dv[2]);
}
}
@@ -448,47 +437,44 @@ public:
}
else
{*/
- bl = 0;
- if(distances[0]<distances[1]) bl = 1;
+ bl = 0;
+ if (distances[0] < distances[1]) bl = 1;
//}
- if(bl==2) //edge edge separation
+ if (bl == 2) //edge edge separation
{
- if(distances[2]>margin) return false;
+ if (distances[2] > margin) return false;
contacts.m_penetration_depth = -distances[2] + margin;
contacts.m_points[0] = closest_point_v;
contacts.m_point_count = 1;
- VEC_COPY(contacts.m_separating_normal,edge_edge_dir);
+ VEC_COPY(contacts.m_separating_normal, edge_edge_dir);
return true;
}
//clip face against other
-
GUINT point_count;
//TODO
- if(bl == 0) //clip U points against V
+ if (bl == 0) //clip U points against V
{
- point_count = clip_triangle(tv_plane,tv_vertices,tu_vertices,contact_points);
- if(point_count == 0) return false;
- contacts.merge_points(tv_plane,margin,contact_points,point_count);
+ point_count = clip_triangle(tv_plane, tv_vertices, tu_vertices, contact_points);
+ if (point_count == 0) return false;
+ contacts.merge_points(tv_plane, margin, contact_points, point_count);
}
- else //clip V points against U
+ else //clip V points against U
{
- point_count = clip_triangle(tu_plane,tu_vertices,tv_vertices,contact_points);
- if(point_count == 0) return false;
- contacts.merge_points(tu_plane,margin,contact_points,point_count);
+ point_count = clip_triangle(tu_plane, tu_vertices, tv_vertices, contact_points);
+ if (point_count == 0) return false;
+ contacts.merge_points(tu_plane, margin, contact_points, point_count);
contacts.m_separating_normal *= -1.f;
}
- if(contacts.m_point_count == 0) return false;
+ if (contacts.m_point_count == 0) return false;
return true;
}
-
};
-
/*class GIM_TRIANGLE_CALCULATION_CACHE
{
public:
@@ -621,20 +607,13 @@ public:
};*/
-
-
bool GIM_TRIANGLE::collide_triangle_hard_test(
- const GIM_TRIANGLE & other,
- GIM_TRIANGLE_CONTACT_DATA & contact_data) const
+ const GIM_TRIANGLE &other,
+ GIM_TRIANGLE_CONTACT_DATA &contact_data) const
{
- GIM_TRIANGLE_CALCULATION_CACHE calc_cache;
+ GIM_TRIANGLE_CALCULATION_CACHE calc_cache;
return calc_cache.triangle_collision(
- m_vertices[0],m_vertices[1],m_vertices[2],m_margin,
- other.m_vertices[0],other.m_vertices[1],other.m_vertices[2],other.m_margin,
- contact_data);
-
+ m_vertices[0], m_vertices[1], m_vertices[2], m_margin,
+ other.m_vertices[0], other.m_vertices[1], other.m_vertices[2], other.m_margin,
+ contact_data);
}
-
-
-
-
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_tri_collision.h b/thirdparty/bullet/BulletCollision/Gimpact/gim_tri_collision.h
index 267f806e7e..e6d4bf5470 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_tri_collision.h
+++ b/thirdparty/bullet/BulletCollision/Gimpact/gim_tri_collision.h
@@ -36,8 +36,6 @@ email: projectileman@yahoo.com
#include "gim_box_collision.h"
#include "gim_clip_polygon.h"
-
-
#ifndef MAX_TRI_CLIPPING
#define MAX_TRI_CLIPPING 16
#endif
@@ -45,18 +43,18 @@ email: projectileman@yahoo.com
//! Structure for collision
struct GIM_TRIANGLE_CONTACT_DATA
{
- GREAL m_penetration_depth;
- GUINT m_point_count;
- btVector4 m_separating_normal;
- btVector3 m_points[MAX_TRI_CLIPPING];
+ GREAL m_penetration_depth;
+ GUINT m_point_count;
+ btVector4 m_separating_normal;
+ btVector3 m_points[MAX_TRI_CLIPPING];
- SIMD_FORCE_INLINE void copy_from(const GIM_TRIANGLE_CONTACT_DATA& other)
+ SIMD_FORCE_INLINE void copy_from(const GIM_TRIANGLE_CONTACT_DATA &other)
{
m_penetration_depth = other.m_penetration_depth;
m_separating_normal = other.m_separating_normal;
m_point_count = other.m_point_count;
GUINT i = m_point_count;
- while(i--)
+ while (i--)
{
m_points[i] = other.m_points[i];
}
@@ -66,39 +64,36 @@ struct GIM_TRIANGLE_CONTACT_DATA
{
}
- GIM_TRIANGLE_CONTACT_DATA(const GIM_TRIANGLE_CONTACT_DATA& other)
+ GIM_TRIANGLE_CONTACT_DATA(const GIM_TRIANGLE_CONTACT_DATA &other)
{
copy_from(other);
}
-
-
-
- //! classify points that are closer
- template<typename DISTANCE_FUNC,typename CLASS_PLANE>
- SIMD_FORCE_INLINE void mergepoints_generic(const CLASS_PLANE & plane,
- GREAL margin, const btVector3 * points, GUINT point_count, DISTANCE_FUNC distance_func)
- {
- m_point_count = 0;
- m_penetration_depth= -1000.0f;
+ //! classify points that are closer
+ template <typename DISTANCE_FUNC, typename CLASS_PLANE>
+ SIMD_FORCE_INLINE void mergepoints_generic(const CLASS_PLANE &plane,
+ GREAL margin, const btVector3 *points, GUINT point_count, DISTANCE_FUNC distance_func)
+ {
+ m_point_count = 0;
+ m_penetration_depth = -1000.0f;
GUINT point_indices[MAX_TRI_CLIPPING];
GUINT _k;
- for(_k=0;_k<point_count;_k++)
+ for (_k = 0; _k < point_count; _k++)
{
- GREAL _dist = -distance_func(plane,points[_k]) + margin;
+ GREAL _dist = -distance_func(plane, points[_k]) + margin;
- if(_dist>=0.0f)
+ if (_dist >= 0.0f)
{
- if(_dist>m_penetration_depth)
+ if (_dist > m_penetration_depth)
{
m_penetration_depth = _dist;
point_indices[0] = _k;
- m_point_count=1;
+ m_point_count = 1;
}
- else if((_dist+G_EPSILON)>=m_penetration_depth)
+ else if ((_dist + G_EPSILON) >= m_penetration_depth)
{
point_indices[m_point_count] = _k;
m_point_count++;
@@ -106,88 +101,87 @@ struct GIM_TRIANGLE_CONTACT_DATA
}
}
- for( _k=0;_k<m_point_count;_k++)
+ for (_k = 0; _k < m_point_count; _k++)
{
m_points[_k] = points[point_indices[_k]];
}
}
//! classify points that are closer
- SIMD_FORCE_INLINE void merge_points(const btVector4 & plane, GREAL margin,
- const btVector3 * points, GUINT point_count)
+ SIMD_FORCE_INLINE void merge_points(const btVector4 &plane, GREAL margin,
+ const btVector3 *points, GUINT point_count)
{
m_separating_normal = plane;
mergepoints_generic(plane, margin, points, point_count, DISTANCE_PLANE_3D_FUNC());
}
};
-
//! Class for colliding triangles
class GIM_TRIANGLE
{
public:
btScalar m_margin;
- btVector3 m_vertices[3];
-
- GIM_TRIANGLE():m_margin(0.1f)
- {
- }
-
- SIMD_FORCE_INLINE GIM_AABB get_box() const
- {
- return GIM_AABB(m_vertices[0],m_vertices[1],m_vertices[2],m_margin);
- }
-
- SIMD_FORCE_INLINE void get_normal(btVector3 &normal) const
- {
- TRIANGLE_NORMAL(m_vertices[0],m_vertices[1],m_vertices[2],normal);
- }
-
- SIMD_FORCE_INLINE void get_plane(btVector4 &plane) const
- {
- TRIANGLE_PLANE(m_vertices[0],m_vertices[1],m_vertices[2],plane);;
- }
-
- SIMD_FORCE_INLINE void apply_transform(const btTransform & trans)
- {
- m_vertices[0] = trans(m_vertices[0]);
- m_vertices[1] = trans(m_vertices[1]);
- m_vertices[2] = trans(m_vertices[2]);
- }
-
- SIMD_FORCE_INLINE void get_edge_plane(GUINT edge_index,const btVector3 &triangle_normal,btVector4 &plane) const
- {
- const btVector3 & e0 = m_vertices[edge_index];
- const btVector3 & e1 = m_vertices[(edge_index+1)%3];
- EDGE_PLANE(e0,e1,triangle_normal,plane);
- }
-
- //! Gets the relative transformation of this triangle
- /*!
+ btVector3 m_vertices[3];
+
+ GIM_TRIANGLE() : m_margin(0.1f)
+ {
+ }
+
+ SIMD_FORCE_INLINE GIM_AABB get_box() const
+ {
+ return GIM_AABB(m_vertices[0], m_vertices[1], m_vertices[2], m_margin);
+ }
+
+ SIMD_FORCE_INLINE void get_normal(btVector3 &normal) const
+ {
+ TRIANGLE_NORMAL(m_vertices[0], m_vertices[1], m_vertices[2], normal);
+ }
+
+ SIMD_FORCE_INLINE void get_plane(btVector4 &plane) const
+ {
+ TRIANGLE_PLANE(m_vertices[0], m_vertices[1], m_vertices[2], plane);
+ ;
+ }
+
+ SIMD_FORCE_INLINE void apply_transform(const btTransform &trans)
+ {
+ m_vertices[0] = trans(m_vertices[0]);
+ m_vertices[1] = trans(m_vertices[1]);
+ m_vertices[2] = trans(m_vertices[2]);
+ }
+
+ SIMD_FORCE_INLINE void get_edge_plane(GUINT edge_index, const btVector3 &triangle_normal, btVector4 &plane) const
+ {
+ const btVector3 &e0 = m_vertices[edge_index];
+ const btVector3 &e1 = m_vertices[(edge_index + 1) % 3];
+ EDGE_PLANE(e0, e1, triangle_normal, plane);
+ }
+
+ //! Gets the relative transformation of this triangle
+ /*!
The transformation is oriented to the triangle normal , and aligned to the 1st edge of this triangle. The position corresponds to vertice 0:
- triangle normal corresponds to Z axis.
- 1st normalized edge corresponds to X axis,
*/
- SIMD_FORCE_INLINE void get_triangle_transform(btTransform & triangle_transform) const
- {
- btMatrix3x3 & matrix = triangle_transform.getBasis();
-
- btVector3 zaxis;
- get_normal(zaxis);
- MAT_SET_Z(matrix,zaxis);
+ SIMD_FORCE_INLINE void get_triangle_transform(btTransform &triangle_transform) const
+ {
+ btMatrix3x3 &matrix = triangle_transform.getBasis();
- btVector3 xaxis = m_vertices[1] - m_vertices[0];
- VEC_NORMALIZE(xaxis);
- MAT_SET_X(matrix,xaxis);
+ btVector3 zaxis;
+ get_normal(zaxis);
+ MAT_SET_Z(matrix, zaxis);
- //y axis
- xaxis = zaxis.cross(xaxis);
- MAT_SET_Y(matrix,xaxis);
+ btVector3 xaxis = m_vertices[1] - m_vertices[0];
+ VEC_NORMALIZE(xaxis);
+ MAT_SET_X(matrix, xaxis);
- triangle_transform.setOrigin(m_vertices[0]);
- }
+ //y axis
+ xaxis = zaxis.cross(xaxis);
+ MAT_SET_Y(matrix, xaxis);
+ triangle_transform.setOrigin(m_vertices[0]);
+ }
//! Test triangles by finding separating axis
/*!
@@ -195,8 +189,8 @@ public:
\param contact_data Structure for holding contact points, normal and penetration depth; The normal is pointing toward this triangle from the other triangle
*/
bool collide_triangle_hard_test(
- const GIM_TRIANGLE & other,
- GIM_TRIANGLE_CONTACT_DATA & contact_data) const;
+ const GIM_TRIANGLE &other,
+ GIM_TRIANGLE_CONTACT_DATA &contact_data) const;
//! Test boxes before doing hard test
/*!
@@ -205,16 +199,16 @@ public:
\
*/
SIMD_FORCE_INLINE bool collide_triangle(
- const GIM_TRIANGLE & other,
- GIM_TRIANGLE_CONTACT_DATA & contact_data) const
+ const GIM_TRIANGLE &other,
+ GIM_TRIANGLE_CONTACT_DATA &contact_data) const
{
//test box collisioin
- GIM_AABB boxu(m_vertices[0],m_vertices[1],m_vertices[2],m_margin);
- GIM_AABB boxv(other.m_vertices[0],other.m_vertices[1],other.m_vertices[2],other.m_margin);
- if(!boxu.has_collision(boxv)) return false;
+ GIM_AABB boxu(m_vertices[0], m_vertices[1], m_vertices[2], m_margin);
+ GIM_AABB boxv(other.m_vertices[0], other.m_vertices[1], other.m_vertices[2], other.m_margin);
+ if (!boxu.has_collision(boxv)) return false;
//do hard test
- return collide_triangle_hard_test(other,contact_data);
+ return collide_triangle_hard_test(other, contact_data);
}
/*!
@@ -246,43 +240,43 @@ if 0.0<= u+v <=1.0 then they are inside of triangle
\return false if the point is outside of triangle.This function doesn't take the margin
*/
SIMD_FORCE_INLINE bool get_uv_parameters(
- const btVector3 & point,
- const btVector3 & tri_plane,
- GREAL & u, GREAL & v) const
+ const btVector3 &point,
+ const btVector3 &tri_plane,
+ GREAL &u, GREAL &v) const
{
- btVector3 _axe1 = m_vertices[1]-m_vertices[0];
- btVector3 _axe2 = m_vertices[2]-m_vertices[0];
+ btVector3 _axe1 = m_vertices[1] - m_vertices[0];
+ btVector3 _axe2 = m_vertices[2] - m_vertices[0];
btVector3 _vecproj = point - m_vertices[0];
- GUINT _i1 = (tri_plane.closestAxis()+1)%3;
- GUINT _i2 = (_i1+1)%3;
- if(btFabs(_axe2[_i2])<G_EPSILON)
+ GUINT _i1 = (tri_plane.closestAxis() + 1) % 3;
+ GUINT _i2 = (_i1 + 1) % 3;
+ if (btFabs(_axe2[_i2]) < G_EPSILON)
{
- u = (_vecproj[_i2]*_axe2[_i1] - _vecproj[_i1]*_axe2[_i2]) /(_axe1[_i2]*_axe2[_i1] - _axe1[_i1]*_axe2[_i2]);
- v = (_vecproj[_i1] - u*_axe1[_i1])/_axe2[_i1];
+ u = (_vecproj[_i2] * _axe2[_i1] - _vecproj[_i1] * _axe2[_i2]) / (_axe1[_i2] * _axe2[_i1] - _axe1[_i1] * _axe2[_i2]);
+ v = (_vecproj[_i1] - u * _axe1[_i1]) / _axe2[_i1];
}
else
{
- u = (_vecproj[_i1]*_axe2[_i2] - _vecproj[_i2]*_axe2[_i1]) /(_axe1[_i1]*_axe2[_i2] - _axe1[_i2]*_axe2[_i1]);
- v = (_vecproj[_i2] - u*_axe1[_i2])/_axe2[_i2];
+ u = (_vecproj[_i1] * _axe2[_i2] - _vecproj[_i2] * _axe2[_i1]) / (_axe1[_i1] * _axe2[_i2] - _axe1[_i2] * _axe2[_i1]);
+ v = (_vecproj[_i2] - u * _axe1[_i2]) / _axe2[_i2];
}
- if(u<-G_EPSILON)
+ if (u < -G_EPSILON)
{
return false;
}
- else if(v<-G_EPSILON)
+ else if (v < -G_EPSILON)
{
return false;
}
else
{
btScalar sumuv;
- sumuv = u+v;
- if(sumuv<-G_EPSILON)
+ sumuv = u + v;
+ if (sumuv < -G_EPSILON)
{
return false;
}
- else if(sumuv-1.0f>G_EPSILON)
+ else if (sumuv - 1.0f > G_EPSILON)
{
return false;
}
@@ -294,50 +288,49 @@ if 0.0<= u+v <=1.0 then they are inside of triangle
/*!
Test if point is in triangle, with m_margin tolerance
*/
- SIMD_FORCE_INLINE bool is_point_inside(const btVector3 & point, const btVector3 & tri_normal) const
+ SIMD_FORCE_INLINE bool is_point_inside(const btVector3 &point, const btVector3 &tri_normal) const
{
//Test with edge 0
btVector4 edge_plane;
- this->get_edge_plane(0,tri_normal,edge_plane);
- GREAL dist = DISTANCE_PLANE_POINT(edge_plane,point);
- if(dist-m_margin>0.0f) return false; // outside plane
+ this->get_edge_plane(0, tri_normal, edge_plane);
+ GREAL dist = DISTANCE_PLANE_POINT(edge_plane, point);
+ if (dist - m_margin > 0.0f) return false; // outside plane
- this->get_edge_plane(1,tri_normal,edge_plane);
- dist = DISTANCE_PLANE_POINT(edge_plane,point);
- if(dist-m_margin>0.0f) return false; // outside plane
+ this->get_edge_plane(1, tri_normal, edge_plane);
+ dist = DISTANCE_PLANE_POINT(edge_plane, point);
+ if (dist - m_margin > 0.0f) return false; // outside plane
- this->get_edge_plane(2,tri_normal,edge_plane);
- dist = DISTANCE_PLANE_POINT(edge_plane,point);
- if(dist-m_margin>0.0f) return false; // outside plane
+ this->get_edge_plane(2, tri_normal, edge_plane);
+ dist = DISTANCE_PLANE_POINT(edge_plane, point);
+ if (dist - m_margin > 0.0f) return false; // outside plane
return true;
}
-
//! Bidireccional ray collision
SIMD_FORCE_INLINE bool ray_collision(
- const btVector3 & vPoint,
- const btVector3 & vDir, btVector3 & pout, btVector3 & triangle_normal,
- GREAL & tparam, GREAL tmax = G_REAL_INFINITY)
+ const btVector3 &vPoint,
+ const btVector3 &vDir, btVector3 &pout, btVector3 &triangle_normal,
+ GREAL &tparam, GREAL tmax = G_REAL_INFINITY)
{
btVector4 faceplane;
{
btVector3 dif1 = m_vertices[1] - m_vertices[0];
btVector3 dif2 = m_vertices[2] - m_vertices[0];
- VEC_CROSS(faceplane,dif1,dif2);
- faceplane[3] = m_vertices[0].dot(faceplane);
+ VEC_CROSS(faceplane, dif1, dif2);
+ faceplane[3] = m_vertices[0].dot(faceplane);
}
- GUINT res = LINE_PLANE_COLLISION(faceplane,vDir,vPoint,pout,tparam, btScalar(0), tmax);
- if(res == 0) return false;
- if(! is_point_inside(pout,faceplane)) return false;
+ GUINT res = LINE_PLANE_COLLISION(faceplane, vDir, vPoint, pout, tparam, btScalar(0), tmax);
+ if (res == 0) return false;
+ if (!is_point_inside(pout, faceplane)) return false;
- if(res==2) //invert normal
+ if (res == 2) //invert normal
{
- triangle_normal.setValue(-faceplane[0],-faceplane[1],-faceplane[2]);
+ triangle_normal.setValue(-faceplane[0], -faceplane[1], -faceplane[2]);
}
else
{
- triangle_normal.setValue(faceplane[0],faceplane[1],faceplane[2]);
+ triangle_normal.setValue(faceplane[0], faceplane[1], faceplane[2]);
}
VEC_NORMALIZE(triangle_normal);
@@ -345,36 +338,31 @@ if 0.0<= u+v <=1.0 then they are inside of triangle
return true;
}
-
//! one direccion ray collision
SIMD_FORCE_INLINE bool ray_collision_front_side(
- const btVector3 & vPoint,
- const btVector3 & vDir, btVector3 & pout, btVector3 & triangle_normal,
- GREAL & tparam, GREAL tmax = G_REAL_INFINITY)
+ const btVector3 &vPoint,
+ const btVector3 &vDir, btVector3 &pout, btVector3 &triangle_normal,
+ GREAL &tparam, GREAL tmax = G_REAL_INFINITY)
{
btVector4 faceplane;
{
btVector3 dif1 = m_vertices[1] - m_vertices[0];
btVector3 dif2 = m_vertices[2] - m_vertices[0];
- VEC_CROSS(faceplane,dif1,dif2);
- faceplane[3] = m_vertices[0].dot(faceplane);
+ VEC_CROSS(faceplane, dif1, dif2);
+ faceplane[3] = m_vertices[0].dot(faceplane);
}
- GUINT res = LINE_PLANE_COLLISION(faceplane,vDir,vPoint,pout,tparam, btScalar(0), tmax);
- if(res != 1) return false;
+ GUINT res = LINE_PLANE_COLLISION(faceplane, vDir, vPoint, pout, tparam, btScalar(0), tmax);
+ if (res != 1) return false;
- if(!is_point_inside(pout,faceplane)) return false;
+ if (!is_point_inside(pout, faceplane)) return false;
- triangle_normal.setValue(faceplane[0],faceplane[1],faceplane[2]);
+ triangle_normal.setValue(faceplane[0], faceplane[1], faceplane[2]);
VEC_NORMALIZE(triangle_normal);
return true;
}
-
};
-
-
-
-#endif // GIM_TRI_COLLISION_H_INCLUDED
+#endif // GIM_TRI_COLLISION_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btComputeGjkEpaPenetration.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btComputeGjkEpaPenetration.h
index 9eb880b8df..c94391d816 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btComputeGjkEpaPenetration.h
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btComputeGjkEpaPenetration.h
@@ -16,163 +16,153 @@ subject to the following restrictions:
#ifndef BT_GJK_EPA_PENETATION_CONVEX_COLLISION_H
#define BT_GJK_EPA_PENETATION_CONVEX_COLLISION_H
-#include "LinearMath/btTransform.h" // Note that btVector3 might be double precision...
+#include "LinearMath/btTransform.h" // Note that btVector3 might be double precision...
#include "btGjkEpa3.h"
#include "btGjkCollisionDescription.h"
#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
+template <typename btConvexTemplate>
+bool btGjkEpaCalcPenDepth(const btConvexTemplate& a, const btConvexTemplate& b,
+ const btGjkCollisionDescription& colDesc,
+ btVector3& v, btVector3& wWitnessOnA, btVector3& wWitnessOnB)
+{
+ (void)v;
+ // const btScalar radialmargin(btScalar(0.));
+ btVector3 guessVector(b.getWorldTransform().getOrigin() - a.getWorldTransform().getOrigin()); //?? why not use the GJK input?
+ btGjkEpaSolver3::sResults results;
+ if (btGjkEpaSolver3_Penetration(a, b, guessVector, results))
-template <typename btConvexTemplate>
-bool btGjkEpaCalcPenDepth(const btConvexTemplate& a, const btConvexTemplate& b,
- const btGjkCollisionDescription& colDesc,
- btVector3& v, btVector3& wWitnessOnA, btVector3& wWitnessOnB)
-{
- (void)v;
-
- // const btScalar radialmargin(btScalar(0.));
-
- btVector3 guessVector(b.getWorldTransform().getOrigin()-a.getWorldTransform().getOrigin());//?? why not use the GJK input?
-
- btGjkEpaSolver3::sResults results;
-
-
- if(btGjkEpaSolver3_Penetration(a,b,guessVector,results))
-
- {
- // debugDraw->drawLine(results.witnesses[1],results.witnesses[1]+results.normal,btVector3(255,0,0));
- //resultOut->addContactPoint(results.normal,results.witnesses[1],-results.depth);
- wWitnessOnA = results.witnesses[0];
- wWitnessOnB = results.witnesses[1];
- v = results.normal;
- return true;
- } else
- {
- if(btGjkEpaSolver3_Distance(a,b,guessVector,results))
- {
- wWitnessOnA = results.witnesses[0];
- wWitnessOnB = results.witnesses[1];
- v = results.normal;
- return false;
- }
- }
- return false;
+ {
+ // debugDraw->drawLine(results.witnesses[1],results.witnesses[1]+results.normal,btVector3(255,0,0));
+ //resultOut->addContactPoint(results.normal,results.witnesses[1],-results.depth);
+ wWitnessOnA = results.witnesses[0];
+ wWitnessOnB = results.witnesses[1];
+ v = results.normal;
+ return true;
+ }
+ else
+ {
+ if (btGjkEpaSolver3_Distance(a, b, guessVector, results))
+ {
+ wWitnessOnA = results.witnesses[0];
+ wWitnessOnB = results.witnesses[1];
+ v = results.normal;
+ return false;
+ }
+ }
+ return false;
}
template <typename btConvexTemplate, typename btGjkDistanceTemplate>
-int btComputeGjkEpaPenetration(const btConvexTemplate& a, const btConvexTemplate& b, const btGjkCollisionDescription& colDesc, btVoronoiSimplexSolver& simplexSolver, btGjkDistanceTemplate* distInfo)
+int btComputeGjkEpaPenetration(const btConvexTemplate& a, const btConvexTemplate& b, const btGjkCollisionDescription& colDesc, btVoronoiSimplexSolver& simplexSolver, btGjkDistanceTemplate* distInfo)
{
-
- bool m_catchDegeneracies = true;
- btScalar m_cachedSeparatingDistance = 0.f;
-
- btScalar distance=btScalar(0.);
- btVector3 normalInB(btScalar(0.),btScalar(0.),btScalar(0.));
-
- btVector3 pointOnA,pointOnB;
- btTransform localTransA = a.getWorldTransform();
- btTransform localTransB = b.getWorldTransform();
-
- btScalar marginA = a.getMargin();
- btScalar marginB = b.getMargin();
-
- int m_curIter = 0;
- int gGjkMaxIter = colDesc.m_maxGjkIterations;//this is to catch invalid input, perhaps check for #NaN?
- btVector3 m_cachedSeparatingAxis = colDesc.m_firstDir;
-
- bool isValid = false;
- bool checkSimplex = false;
- bool checkPenetration = true;
- int m_degenerateSimplex = 0;
-
- int m_lastUsedMethod = -1;
-
- {
- btScalar squaredDistance = BT_LARGE_FLOAT;
- btScalar delta = btScalar(0.);
-
- btScalar margin = marginA + marginB;
-
-
-
- simplexSolver.reset();
-
- for ( ; ; )
- //while (true)
- {
-
- btVector3 seperatingAxisInA = (-m_cachedSeparatingAxis)* localTransA.getBasis();
- btVector3 seperatingAxisInB = m_cachedSeparatingAxis* localTransB.getBasis();
-
- btVector3 pInA = a.getLocalSupportWithoutMargin(seperatingAxisInA);
- btVector3 qInB = b.getLocalSupportWithoutMargin(seperatingAxisInB);
-
- btVector3 pWorld = localTransA(pInA);
- btVector3 qWorld = localTransB(qInB);
-
-
-
- btVector3 w = pWorld - qWorld;
- delta = m_cachedSeparatingAxis.dot(w);
-
- // potential exit, they don't overlap
- if ((delta > btScalar(0.0)) && (delta * delta > squaredDistance * colDesc.m_maximumDistanceSquared))
- {
- m_degenerateSimplex = 10;
- checkSimplex=true;
- //checkPenetration = false;
- break;
- }
-
- //exit 0: the new point is already in the simplex, or we didn't come any closer
- if (simplexSolver.inSimplex(w))
- {
- m_degenerateSimplex = 1;
- checkSimplex = true;
- break;
- }
- // are we getting any closer ?
- btScalar f0 = squaredDistance - delta;
- btScalar f1 = squaredDistance * colDesc.m_gjkRelError2;
-
- if (f0 <= f1)
- {
- if (f0 <= btScalar(0.))
- {
- m_degenerateSimplex = 2;
- } else
- {
- m_degenerateSimplex = 11;
- }
- checkSimplex = true;
- break;
- }
-
- //add current vertex to simplex
- simplexSolver.addVertex(w, pWorld, qWorld);
- btVector3 newCachedSeparatingAxis;
-
- //calculate the closest point to the origin (update vector v)
- if (!simplexSolver.closest(newCachedSeparatingAxis))
- {
- m_degenerateSimplex = 3;
- checkSimplex = true;
- break;
- }
-
- if(newCachedSeparatingAxis.length2()<colDesc.m_gjkRelError2)
- {
- m_cachedSeparatingAxis = newCachedSeparatingAxis;
- m_degenerateSimplex = 6;
- checkSimplex = true;
- break;
- }
-
- btScalar previousSquaredDistance = squaredDistance;
- squaredDistance = newCachedSeparatingAxis.length2();
+ bool m_catchDegeneracies = true;
+ btScalar m_cachedSeparatingDistance = 0.f;
+
+ btScalar distance = btScalar(0.);
+ btVector3 normalInB(btScalar(0.), btScalar(0.), btScalar(0.));
+
+ btVector3 pointOnA, pointOnB;
+ btTransform localTransA = a.getWorldTransform();
+ btTransform localTransB = b.getWorldTransform();
+
+ btScalar marginA = a.getMargin();
+ btScalar marginB = b.getMargin();
+
+ int m_curIter = 0;
+ int gGjkMaxIter = colDesc.m_maxGjkIterations; //this is to catch invalid input, perhaps check for #NaN?
+ btVector3 m_cachedSeparatingAxis = colDesc.m_firstDir;
+
+ bool isValid = false;
+ bool checkSimplex = false;
+ bool checkPenetration = true;
+ int m_degenerateSimplex = 0;
+
+ int m_lastUsedMethod = -1;
+
+ {
+ btScalar squaredDistance = BT_LARGE_FLOAT;
+ btScalar delta = btScalar(0.);
+
+ btScalar margin = marginA + marginB;
+
+ simplexSolver.reset();
+
+ for (;;)
+ //while (true)
+ {
+ btVector3 seperatingAxisInA = (-m_cachedSeparatingAxis) * localTransA.getBasis();
+ btVector3 seperatingAxisInB = m_cachedSeparatingAxis * localTransB.getBasis();
+
+ btVector3 pInA = a.getLocalSupportWithoutMargin(seperatingAxisInA);
+ btVector3 qInB = b.getLocalSupportWithoutMargin(seperatingAxisInB);
+
+ btVector3 pWorld = localTransA(pInA);
+ btVector3 qWorld = localTransB(qInB);
+
+ btVector3 w = pWorld - qWorld;
+ delta = m_cachedSeparatingAxis.dot(w);
+
+ // potential exit, they don't overlap
+ if ((delta > btScalar(0.0)) && (delta * delta > squaredDistance * colDesc.m_maximumDistanceSquared))
+ {
+ m_degenerateSimplex = 10;
+ checkSimplex = true;
+ //checkPenetration = false;
+ break;
+ }
+
+ //exit 0: the new point is already in the simplex, or we didn't come any closer
+ if (simplexSolver.inSimplex(w))
+ {
+ m_degenerateSimplex = 1;
+ checkSimplex = true;
+ break;
+ }
+ // are we getting any closer ?
+ btScalar f0 = squaredDistance - delta;
+ btScalar f1 = squaredDistance * colDesc.m_gjkRelError2;
+
+ if (f0 <= f1)
+ {
+ if (f0 <= btScalar(0.))
+ {
+ m_degenerateSimplex = 2;
+ }
+ else
+ {
+ m_degenerateSimplex = 11;
+ }
+ checkSimplex = true;
+ break;
+ }
+
+ //add current vertex to simplex
+ simplexSolver.addVertex(w, pWorld, qWorld);
+ btVector3 newCachedSeparatingAxis;
+
+ //calculate the closest point to the origin (update vector v)
+ if (!simplexSolver.closest(newCachedSeparatingAxis))
+ {
+ m_degenerateSimplex = 3;
+ checkSimplex = true;
+ break;
+ }
+
+ if (newCachedSeparatingAxis.length2() < colDesc.m_gjkRelError2)
+ {
+ m_cachedSeparatingAxis = newCachedSeparatingAxis;
+ m_degenerateSimplex = 6;
+ checkSimplex = true;
+ break;
+ }
+
+ btScalar previousSquaredDistance = squaredDistance;
+ squaredDistance = newCachedSeparatingAxis.length2();
#if 0
///warning: this termination condition leads to some problems in 2d test case see Bullet/Demos/Box2dDemo
if (squaredDistance>previousSquaredDistance)
@@ -182,188 +172,183 @@ int btComputeGjkEpaPenetration(const btConvexTemplate& a, const btConvexTemplate
checkSimplex = false;
break;
}
-#endif //
-
-
- //redundant m_simplexSolver->compute_points(pointOnA, pointOnB);
-
- //are we getting any closer ?
- if (previousSquaredDistance - squaredDistance <= SIMD_EPSILON * previousSquaredDistance)
- {
- // m_simplexSolver->backup_closest(m_cachedSeparatingAxis);
- checkSimplex = true;
- m_degenerateSimplex = 12;
-
- break;
- }
-
- m_cachedSeparatingAxis = newCachedSeparatingAxis;
-
- //degeneracy, this is typically due to invalid/uninitialized worldtransforms for a btCollisionObject
- if (m_curIter++ > gGjkMaxIter)
- {
-#if defined(DEBUG) || defined (_DEBUG)
-
- printf("btGjkPairDetector maxIter exceeded:%i\n",m_curIter);
- printf("sepAxis=(%f,%f,%f), squaredDistance = %f\n",
- m_cachedSeparatingAxis.getX(),
- m_cachedSeparatingAxis.getY(),
- m_cachedSeparatingAxis.getZ(),
- squaredDistance);
+#endif //
+
+ //redundant m_simplexSolver->compute_points(pointOnA, pointOnB);
+
+ //are we getting any closer ?
+ if (previousSquaredDistance - squaredDistance <= SIMD_EPSILON * previousSquaredDistance)
+ {
+ // m_simplexSolver->backup_closest(m_cachedSeparatingAxis);
+ checkSimplex = true;
+ m_degenerateSimplex = 12;
+
+ break;
+ }
+
+ m_cachedSeparatingAxis = newCachedSeparatingAxis;
+
+ //degeneracy, this is typically due to invalid/uninitialized worldtransforms for a btCollisionObject
+ if (m_curIter++ > gGjkMaxIter)
+ {
+#if defined(DEBUG) || defined(_DEBUG)
+
+ printf("btGjkPairDetector maxIter exceeded:%i\n", m_curIter);
+ printf("sepAxis=(%f,%f,%f), squaredDistance = %f\n",
+ m_cachedSeparatingAxis.getX(),
+ m_cachedSeparatingAxis.getY(),
+ m_cachedSeparatingAxis.getZ(),
+ squaredDistance);
#endif
-
- break;
-
- }
-
-
- bool check = (!simplexSolver.fullSimplex());
- //bool check = (!m_simplexSolver->fullSimplex() && squaredDistance > SIMD_EPSILON * m_simplexSolver->maxVertex());
-
- if (!check)
- {
- //do we need this backup_closest here ?
- // m_simplexSolver->backup_closest(m_cachedSeparatingAxis);
- m_degenerateSimplex = 13;
- break;
- }
- }
-
- if (checkSimplex)
- {
- simplexSolver.compute_points(pointOnA, pointOnB);
- normalInB = m_cachedSeparatingAxis;
-
- btScalar lenSqr =m_cachedSeparatingAxis.length2();
-
- //valid normal
- if (lenSqr < 0.0001)
- {
- m_degenerateSimplex = 5;
- }
- if (lenSqr > SIMD_EPSILON*SIMD_EPSILON)
- {
- btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
- normalInB *= rlen; //normalize
-
- btScalar s = btSqrt(squaredDistance);
-
- btAssert(s > btScalar(0.0));
- pointOnA -= m_cachedSeparatingAxis * (marginA / s);
- pointOnB += m_cachedSeparatingAxis * (marginB / s);
- distance = ((btScalar(1.)/rlen) - margin);
- isValid = true;
-
- m_lastUsedMethod = 1;
- } else
- {
- m_lastUsedMethod = 2;
- }
- }
-
- bool catchDegeneratePenetrationCase =
- (m_catchDegeneracies && m_degenerateSimplex && ((distance+margin) < 0.01));
-
- //if (checkPenetration && !isValid)
- if (checkPenetration && (!isValid || catchDegeneratePenetrationCase ))
- {
- //penetration case
-
- //if there is no way to handle penetrations, bail out
-
- // Penetration depth case.
- btVector3 tmpPointOnA,tmpPointOnB;
-
- m_cachedSeparatingAxis.setZero();
-
- bool isValid2 = btGjkEpaCalcPenDepth(a,b,
- colDesc,
- m_cachedSeparatingAxis, tmpPointOnA, tmpPointOnB);
-
- if (isValid2)
- {
- btVector3 tmpNormalInB = tmpPointOnB-tmpPointOnA;
- btScalar lenSqr = tmpNormalInB.length2();
- if (lenSqr <= (SIMD_EPSILON*SIMD_EPSILON))
- {
- tmpNormalInB = m_cachedSeparatingAxis;
- lenSqr = m_cachedSeparatingAxis.length2();
- }
-
- if (lenSqr > (SIMD_EPSILON*SIMD_EPSILON))
- {
- tmpNormalInB /= btSqrt(lenSqr);
- btScalar distance2 = -(tmpPointOnA-tmpPointOnB).length();
- //only replace valid penetrations when the result is deeper (check)
- if (!isValid || (distance2 < distance))
- {
- distance = distance2;
- pointOnA = tmpPointOnA;
- pointOnB = tmpPointOnB;
- normalInB = tmpNormalInB;
-
- isValid = true;
- m_lastUsedMethod = 3;
- } else
- {
- m_lastUsedMethod = 8;
- }
- } else
- {
- m_lastUsedMethod = 9;
- }
- } else
-
- {
- ///this is another degenerate case, where the initial GJK calculation reports a degenerate case
- ///EPA reports no penetration, and the second GJK (using the supporting vector without margin)
- ///reports a valid positive distance. Use the results of the second GJK instead of failing.
- ///thanks to Jacob.Langford for the reproduction case
- ///http://code.google.com/p/bullet/issues/detail?id=250
-
-
- if (m_cachedSeparatingAxis.length2() > btScalar(0.))
- {
- btScalar distance2 = (tmpPointOnA-tmpPointOnB).length()-margin;
- //only replace valid distances when the distance is less
- if (!isValid || (distance2 < distance))
- {
- distance = distance2;
- pointOnA = tmpPointOnA;
- pointOnB = tmpPointOnB;
- pointOnA -= m_cachedSeparatingAxis * marginA ;
- pointOnB += m_cachedSeparatingAxis * marginB ;
- normalInB = m_cachedSeparatingAxis;
- normalInB.normalize();
-
- isValid = true;
- m_lastUsedMethod = 6;
- } else
- {
- m_lastUsedMethod = 5;
- }
- }
- }
- }
- }
-
-
-
- if (isValid && ((distance < 0) || (distance*distance < colDesc.m_maximumDistanceSquared)))
- {
-
- m_cachedSeparatingAxis = normalInB;
- m_cachedSeparatingDistance = distance;
- distInfo->m_distance = distance;
- distInfo->m_normalBtoA = normalInB;
- distInfo->m_pointOnB = pointOnB;
- distInfo->m_pointOnA = pointOnB+normalInB*distance;
- return 0;
- }
- return -m_lastUsedMethod;
-}
+ break;
+ }
+
+ bool check = (!simplexSolver.fullSimplex());
+ //bool check = (!m_simplexSolver->fullSimplex() && squaredDistance > SIMD_EPSILON * m_simplexSolver->maxVertex());
+
+ if (!check)
+ {
+ //do we need this backup_closest here ?
+ // m_simplexSolver->backup_closest(m_cachedSeparatingAxis);
+ m_degenerateSimplex = 13;
+ break;
+ }
+ }
+
+ if (checkSimplex)
+ {
+ simplexSolver.compute_points(pointOnA, pointOnB);
+ normalInB = m_cachedSeparatingAxis;
+
+ btScalar lenSqr = m_cachedSeparatingAxis.length2();
+
+ //valid normal
+ if (lenSqr < 0.0001)
+ {
+ m_degenerateSimplex = 5;
+ }
+ if (lenSqr > SIMD_EPSILON * SIMD_EPSILON)
+ {
+ btScalar rlen = btScalar(1.) / btSqrt(lenSqr);
+ normalInB *= rlen; //normalize
+
+ btScalar s = btSqrt(squaredDistance);
+
+ btAssert(s > btScalar(0.0));
+ pointOnA -= m_cachedSeparatingAxis * (marginA / s);
+ pointOnB += m_cachedSeparatingAxis * (marginB / s);
+ distance = ((btScalar(1.) / rlen) - margin);
+ isValid = true;
+
+ m_lastUsedMethod = 1;
+ }
+ else
+ {
+ m_lastUsedMethod = 2;
+ }
+ }
+
+ bool catchDegeneratePenetrationCase =
+ (m_catchDegeneracies && m_degenerateSimplex && ((distance + margin) < 0.01));
+
+ //if (checkPenetration && !isValid)
+ if (checkPenetration && (!isValid || catchDegeneratePenetrationCase))
+ {
+ //penetration case
+ //if there is no way to handle penetrations, bail out
+ // Penetration depth case.
+ btVector3 tmpPointOnA, tmpPointOnB;
+
+ m_cachedSeparatingAxis.setZero();
+
+ bool isValid2 = btGjkEpaCalcPenDepth(a, b,
+ colDesc,
+ m_cachedSeparatingAxis, tmpPointOnA, tmpPointOnB);
+
+ if (isValid2)
+ {
+ btVector3 tmpNormalInB = tmpPointOnB - tmpPointOnA;
+ btScalar lenSqr = tmpNormalInB.length2();
+ if (lenSqr <= (SIMD_EPSILON * SIMD_EPSILON))
+ {
+ tmpNormalInB = m_cachedSeparatingAxis;
+ lenSqr = m_cachedSeparatingAxis.length2();
+ }
+
+ if (lenSqr > (SIMD_EPSILON * SIMD_EPSILON))
+ {
+ tmpNormalInB /= btSqrt(lenSqr);
+ btScalar distance2 = -(tmpPointOnA - tmpPointOnB).length();
+ //only replace valid penetrations when the result is deeper (check)
+ if (!isValid || (distance2 < distance))
+ {
+ distance = distance2;
+ pointOnA = tmpPointOnA;
+ pointOnB = tmpPointOnB;
+ normalInB = tmpNormalInB;
+
+ isValid = true;
+ m_lastUsedMethod = 3;
+ }
+ else
+ {
+ m_lastUsedMethod = 8;
+ }
+ }
+ else
+ {
+ m_lastUsedMethod = 9;
+ }
+ }
+ else
+
+ {
+ ///this is another degenerate case, where the initial GJK calculation reports a degenerate case
+ ///EPA reports no penetration, and the second GJK (using the supporting vector without margin)
+ ///reports a valid positive distance. Use the results of the second GJK instead of failing.
+ ///thanks to Jacob.Langford for the reproduction case
+ ///http://code.google.com/p/bullet/issues/detail?id=250
+
+ if (m_cachedSeparatingAxis.length2() > btScalar(0.))
+ {
+ btScalar distance2 = (tmpPointOnA - tmpPointOnB).length() - margin;
+ //only replace valid distances when the distance is less
+ if (!isValid || (distance2 < distance))
+ {
+ distance = distance2;
+ pointOnA = tmpPointOnA;
+ pointOnB = tmpPointOnB;
+ pointOnA -= m_cachedSeparatingAxis * marginA;
+ pointOnB += m_cachedSeparatingAxis * marginB;
+ normalInB = m_cachedSeparatingAxis;
+ normalInB.normalize();
+
+ isValid = true;
+ m_lastUsedMethod = 6;
+ }
+ else
+ {
+ m_lastUsedMethod = 5;
+ }
+ }
+ }
+ }
+ }
+
+ if (isValid && ((distance < 0) || (distance * distance < colDesc.m_maximumDistanceSquared)))
+ {
+ m_cachedSeparatingAxis = normalInB;
+ m_cachedSeparatingDistance = distance;
+ distInfo->m_distance = distance;
+ distInfo->m_normalBtoA = normalInB;
+ distInfo->m_pointOnB = pointOnB;
+ distInfo->m_pointOnA = pointOnB + normalInB * distance;
+ return 0;
+ }
+ return -m_lastUsedMethod;
+}
-#endif //BT_GJK_EPA_PENETATION_CONVEX_COLLISION_H
+#endif //BT_GJK_EPA_PENETATION_CONVEX_COLLISION_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp
index 3481fec850..38df8d4808 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp
@@ -13,7 +13,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#include "btContinuousConvexCollision.h"
#include "BulletCollision/CollisionShapes/btConvexShape.h"
#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h"
@@ -24,59 +23,60 @@ subject to the following restrictions:
#include "btPointCollector.h"
#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
-
-
-btContinuousConvexCollision::btContinuousConvexCollision ( const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* penetrationDepthSolver)
-:m_simplexSolver(simplexSolver),
-m_penetrationDepthSolver(penetrationDepthSolver),
-m_convexA(convexA),m_convexB1(convexB),m_planeShape(0)
+btContinuousConvexCollision::btContinuousConvexCollision(const btConvexShape* convexA, const btConvexShape* convexB, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* penetrationDepthSolver)
+ : m_simplexSolver(simplexSolver),
+ m_penetrationDepthSolver(penetrationDepthSolver),
+ m_convexA(convexA),
+ m_convexB1(convexB),
+ m_planeShape(0)
{
}
-
-btContinuousConvexCollision::btContinuousConvexCollision( const btConvexShape* convexA,const btStaticPlaneShape* plane)
-:m_simplexSolver(0),
-m_penetrationDepthSolver(0),
-m_convexA(convexA),m_convexB1(0),m_planeShape(plane)
+btContinuousConvexCollision::btContinuousConvexCollision(const btConvexShape* convexA, const btStaticPlaneShape* plane)
+ : m_simplexSolver(0),
+ m_penetrationDepthSolver(0),
+ m_convexA(convexA),
+ m_convexB1(0),
+ m_planeShape(plane)
{
}
-
/// This maximum should not be necessary. It allows for untested/degenerate cases in production code.
/// You don't want your game ever to lock-up.
#define MAX_ITERATIONS 64
-void btContinuousConvexCollision::computeClosestPoints( const btTransform& transA, const btTransform& transB,btPointCollector& pointCollector)
+void btContinuousConvexCollision::computeClosestPoints(const btTransform& transA, const btTransform& transB, btPointCollector& pointCollector)
{
if (m_convexB1)
{
m_simplexSolver->reset();
- btGjkPairDetector gjk(m_convexA,m_convexB1,m_convexA->getShapeType(),m_convexB1->getShapeType(),m_convexA->getMargin(),m_convexB1->getMargin(),m_simplexSolver,m_penetrationDepthSolver);
+ btGjkPairDetector gjk(m_convexA, m_convexB1, m_convexA->getShapeType(), m_convexB1->getShapeType(), m_convexA->getMargin(), m_convexB1->getMargin(), m_simplexSolver, m_penetrationDepthSolver);
btGjkPairDetector::ClosestPointInput input;
input.m_transformA = transA;
input.m_transformB = transB;
- gjk.getClosestPoints(input,pointCollector,0);
- } else
+ gjk.getClosestPoints(input, pointCollector, 0);
+ }
+ else
{
//convex versus plane
const btConvexShape* convexShape = m_convexA;
const btStaticPlaneShape* planeShape = m_planeShape;
-
+
const btVector3& planeNormal = planeShape->getPlaneNormal();
const btScalar& planeConstant = planeShape->getPlaneConstant();
-
+
btTransform convexWorldTransform = transA;
btTransform convexInPlaneTrans;
- convexInPlaneTrans= transB.inverse() * convexWorldTransform;
+ convexInPlaneTrans = transB.inverse() * convexWorldTransform;
btTransform planeInConvex;
- planeInConvex= convexWorldTransform.inverse() * transB;
-
- btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal);
+ planeInConvex = convexWorldTransform.inverse() * transB;
+
+ btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis() * -planeNormal);
btVector3 vtxInPlane = convexInPlaneTrans(vtx);
btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant);
- btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal;
+ btVector3 vtxInPlaneProjected = vtxInPlane - distance * planeNormal;
btVector3 vtxInPlaneWorld = transB * vtxInPlaneProjected;
btVector3 normalOnSurfaceB = transB.getBasis() * planeNormal;
@@ -87,36 +87,33 @@ void btContinuousConvexCollision::computeClosestPoints( const btTransform& trans
}
}
-bool btContinuousConvexCollision::calcTimeOfImpact(
- const btTransform& fromA,
- const btTransform& toA,
- const btTransform& fromB,
- const btTransform& toB,
- CastResult& result)
+bool btContinuousConvexCollision::calcTimeOfImpact(
+ const btTransform& fromA,
+ const btTransform& toA,
+ const btTransform& fromB,
+ const btTransform& toB,
+ CastResult& result)
{
-
-
/// compute linear and angular velocity for this interval, to interpolate
- btVector3 linVelA,angVelA,linVelB,angVelB;
- btTransformUtil::calculateVelocity(fromA,toA,btScalar(1.),linVelA,angVelA);
- btTransformUtil::calculateVelocity(fromB,toB,btScalar(1.),linVelB,angVelB);
-
+ btVector3 linVelA, angVelA, linVelB, angVelB;
+ btTransformUtil::calculateVelocity(fromA, toA, btScalar(1.), linVelA, angVelA);
+ btTransformUtil::calculateVelocity(fromB, toB, btScalar(1.), linVelB, angVelB);
btScalar boundingRadiusA = m_convexA->getAngularMotionDisc();
- btScalar boundingRadiusB = m_convexB1?m_convexB1->getAngularMotionDisc():0.f;
+ btScalar boundingRadiusB = m_convexB1 ? m_convexB1->getAngularMotionDisc() : 0.f;
btScalar maxAngularProjectedVelocity = angVelA.length() * boundingRadiusA + angVelB.length() * boundingRadiusB;
- btVector3 relLinVel = (linVelB-linVelA);
+ btVector3 relLinVel = (linVelB - linVelA);
+
+ btScalar relLinVelocLength = (linVelB - linVelA).length();
- btScalar relLinVelocLength = (linVelB-linVelA).length();
-
- if ((relLinVelocLength+maxAngularProjectedVelocity) == 0.f)
+ if ((relLinVelocLength + maxAngularProjectedVelocity) == 0.f)
return false;
btScalar lambda = btScalar(0.);
btVector3 n;
- n.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+ n.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
bool hasResult = false;
btVector3 c;
@@ -126,14 +123,13 @@ bool btContinuousConvexCollision::calcTimeOfImpact(
int numIter = 0;
//first solution, using GJK
-
btScalar radius = 0.001f;
-// result.drawCoordSystem(sphereTr);
+ // result.drawCoordSystem(sphereTr);
- btPointCollector pointCollector1;
+ btPointCollector pointCollector1;
- {
- computeClosestPoints(fromA,fromB,pointCollector1);
+ {
+ computeClosestPoints(fromA, fromB, pointCollector1);
hasResult = pointCollector1.m_hasResult;
c = pointCollector1.m_pointInWorld;
@@ -145,7 +141,7 @@ bool btContinuousConvexCollision::calcTimeOfImpact(
dist = pointCollector1.m_distance + result.m_allowedPenetration;
n = pointCollector1.m_normalOnBInWorld;
btScalar projectedLinearVelocity = relLinVel.dot(n);
- if ((projectedLinearVelocity+ maxAngularProjectedVelocity)<=SIMD_EPSILON)
+ if ((projectedLinearVelocity + maxAngularProjectedVelocity) <= SIMD_EPSILON)
return false;
//not close enough
@@ -153,18 +149,17 @@ bool btContinuousConvexCollision::calcTimeOfImpact(
{
if (result.m_debugDrawer)
{
- result.m_debugDrawer->drawSphere(c,0.2f,btVector3(1,1,1));
+ result.m_debugDrawer->drawSphere(c, 0.2f, btVector3(1, 1, 1));
}
btScalar dLambda = btScalar(0.);
projectedLinearVelocity = relLinVel.dot(n);
-
//don't report time of impact for motion away from the contact normal (or causes minor penetration)
- if ((projectedLinearVelocity+ maxAngularProjectedVelocity)<=SIMD_EPSILON)
+ if ((projectedLinearVelocity + maxAngularProjectedVelocity) <= SIMD_EPSILON)
return false;
-
- dLambda = dist / (projectedLinearVelocity+ maxAngularProjectedVelocity);
+
+ dLambda = dist / (projectedLinearVelocity + maxAngularProjectedVelocity);
lambda += dLambda;
@@ -181,28 +176,29 @@ bool btContinuousConvexCollision::calcTimeOfImpact(
lastLambda = lambda;
//interpolate to next lambda
- btTransform interpolatedTransA,interpolatedTransB,relativeTrans;
+ btTransform interpolatedTransA, interpolatedTransB, relativeTrans;
- btTransformUtil::integrateTransform(fromA,linVelA,angVelA,lambda,interpolatedTransA);
- btTransformUtil::integrateTransform(fromB,linVelB,angVelB,lambda,interpolatedTransB);
+ btTransformUtil::integrateTransform(fromA, linVelA, angVelA, lambda, interpolatedTransA);
+ btTransformUtil::integrateTransform(fromB, linVelB, angVelB, lambda, interpolatedTransB);
relativeTrans = interpolatedTransB.inverseTimes(interpolatedTransA);
if (result.m_debugDrawer)
{
- result.m_debugDrawer->drawSphere(interpolatedTransA.getOrigin(),0.2f,btVector3(1,0,0));
+ result.m_debugDrawer->drawSphere(interpolatedTransA.getOrigin(), 0.2f, btVector3(1, 0, 0));
}
- result.DebugDraw( lambda );
+ result.DebugDraw(lambda);
- btPointCollector pointCollector;
- computeClosestPoints(interpolatedTransA,interpolatedTransB,pointCollector);
+ btPointCollector pointCollector;
+ computeClosestPoints(interpolatedTransA, interpolatedTransB, pointCollector);
if (pointCollector.m_hasResult)
{
- dist = pointCollector.m_distance+result.m_allowedPenetration;
- c = pointCollector.m_pointInWorld;
+ dist = pointCollector.m_distance + result.m_allowedPenetration;
+ c = pointCollector.m_pointInWorld;
n = pointCollector.m_normalOnBInWorld;
- } else
+ }
+ else
{
result.reportFailure(-1, numIter);
return false;
@@ -215,7 +211,7 @@ bool btContinuousConvexCollision::calcTimeOfImpact(
return false;
}
}
-
+
result.m_fraction = lambda;
result.m_normal = n;
result.m_hitPoint = c;
@@ -224,4 +220,3 @@ bool btContinuousConvexCollision::calcTimeOfImpact(
return false;
}
-
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h
index 528b5e0101..67b2205c36 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h
@@ -13,7 +13,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#ifndef BT_CONTINUOUS_COLLISION_CONVEX_CAST_H
#define BT_CONTINUOUS_COLLISION_CONVEX_CAST_H
@@ -30,30 +29,25 @@ class btStaticPlaneShape;
class btContinuousConvexCollision : public btConvexCast
{
btSimplexSolverInterface* m_simplexSolver;
- btConvexPenetrationDepthSolver* m_penetrationDepthSolver;
- const btConvexShape* m_convexA;
+ btConvexPenetrationDepthSolver* m_penetrationDepthSolver;
+ const btConvexShape* m_convexA;
//second object is either a convex or a plane (code sharing)
- const btConvexShape* m_convexB1;
- const btStaticPlaneShape* m_planeShape;
+ const btConvexShape* m_convexB1;
+ const btStaticPlaneShape* m_planeShape;
- void computeClosestPoints( const btTransform& transA, const btTransform& transB,struct btPointCollector& pointCollector);
+ void computeClosestPoints(const btTransform& transA, const btTransform& transB, struct btPointCollector& pointCollector);
public:
+ btContinuousConvexCollision(const btConvexShape* shapeA, const btConvexShape* shapeB, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* penetrationDepthSolver);
- btContinuousConvexCollision (const btConvexShape* shapeA,const btConvexShape* shapeB ,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver);
-
- btContinuousConvexCollision(const btConvexShape* shapeA,const btStaticPlaneShape* plane );
-
- virtual bool calcTimeOfImpact(
- const btTransform& fromA,
- const btTransform& toA,
- const btTransform& fromB,
- const btTransform& toB,
- CastResult& result);
-
+ btContinuousConvexCollision(const btConvexShape* shapeA, const btStaticPlaneShape* plane);
+ virtual bool calcTimeOfImpact(
+ const btTransform& fromA,
+ const btTransform& toA,
+ const btTransform& fromB,
+ const btTransform& toB,
+ CastResult& result);
};
-
-#endif //BT_CONTINUOUS_COLLISION_CONVEX_CAST_H
-
+#endif //BT_CONTINUOUS_COLLISION_CONVEX_CAST_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btConvexCast.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btConvexCast.h
index bfd79d03be..76f54699c5 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btConvexCast.h
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btConvexCast.h
@@ -13,7 +13,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#ifndef BT_CONVEX_CAST_H
#define BT_CONVEX_CAST_H
@@ -23,51 +22,69 @@ subject to the following restrictions:
class btMinkowskiSumShape;
#include "LinearMath/btIDebugDraw.h"
+#ifdef BT_USE_DOUBLE_PRECISION
+#define MAX_ITERATIONS 64
+#define MAX_EPSILON (SIMD_EPSILON * 10)
+#else
+#define MAX_ITERATIONS 32
+#define MAX_EPSILON btScalar(0.0001)
+#endif
+///Typically the conservative advancement reaches solution in a few iterations, clip it to 32 for degenerate cases.
+///See discussion about this here http://continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=565
+//will need to digg deeper to make the algorithm more robust
+//since, a large epsilon can cause an early termination with false
+//positive results (ray intersections that shouldn't be there)
+
/// btConvexCast is an interface for Casting
class btConvexCast
{
public:
-
-
virtual ~btConvexCast();
///RayResult stores the closest result
/// alternatively, add a callback method to decide about closest/all results
- struct CastResult
+ struct CastResult
{
//virtual bool addRayResult(const btVector3& normal,btScalar fraction) = 0;
-
- virtual void DebugDraw(btScalar fraction) {(void)fraction;}
- virtual void drawCoordSystem(const btTransform& trans) {(void)trans;}
- virtual void reportFailure(int errNo, int numIterations) {(void)errNo;(void)numIterations;}
+
+ virtual void DebugDraw(btScalar fraction) { (void)fraction; }
+ virtual void drawCoordSystem(const btTransform& trans) { (void)trans; }
+ virtual void reportFailure(int errNo, int numIterations)
+ {
+ (void)errNo;
+ (void)numIterations;
+ }
CastResult()
- :m_fraction(btScalar(BT_LARGE_FLOAT)),
- m_debugDrawer(0),
- m_allowedPenetration(btScalar(0))
+ : m_fraction(btScalar(BT_LARGE_FLOAT)),
+ m_debugDrawer(0),
+ m_allowedPenetration(btScalar(0)),
+ m_subSimplexCastMaxIterations(MAX_ITERATIONS),
+ m_subSimplexCastEpsilon(MAX_EPSILON)
{
}
+ virtual ~CastResult(){};
- virtual ~CastResult() {};
-
- btTransform m_hitTransformA;
- btTransform m_hitTransformB;
- btVector3 m_normal;
- btVector3 m_hitPoint;
- btScalar m_fraction; //input and output
+ btTransform m_hitTransformA;
+ btTransform m_hitTransformB;
+ btVector3 m_normal;
+ btVector3 m_hitPoint;
+ btScalar m_fraction; //input and output
btIDebugDraw* m_debugDrawer;
- btScalar m_allowedPenetration;
+ btScalar m_allowedPenetration;
+
+ int m_subSimplexCastMaxIterations;
+ btScalar m_subSimplexCastEpsilon;
};
-
/// cast a convex against another convex object
- virtual bool calcTimeOfImpact(
- const btTransform& fromA,
- const btTransform& toA,
- const btTransform& fromB,
- const btTransform& toB,
- CastResult& result) = 0;
+ virtual bool calcTimeOfImpact(
+ const btTransform& fromA,
+ const btTransform& toA,
+ const btTransform& fromB,
+ const btTransform& toB,
+ CastResult& result) = 0;
};
-#endif //BT_CONVEX_CAST_H
+#endif //BT_CONVEX_CAST_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h
index 29620abffb..65c9df9340 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h
@@ -13,7 +13,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#ifndef BT_CONVEX_PENETRATION_DEPTH_H
#define BT_CONVEX_PENETRATION_DEPTH_H
@@ -25,16 +24,12 @@ class btTransform;
///ConvexPenetrationDepthSolver provides an interface for penetration depth calculation.
class btConvexPenetrationDepthSolver
{
-public:
-
- virtual ~btConvexPenetrationDepthSolver() {};
- virtual bool calcPenDepth( btSimplexSolverInterface& simplexSolver,
- const btConvexShape* convexA,const btConvexShape* convexB,
- const btTransform& transA,const btTransform& transB,
- btVector3& v, btVector3& pa, btVector3& pb,
- class btIDebugDraw* debugDraw) = 0;
-
-
+public:
+ virtual ~btConvexPenetrationDepthSolver(){};
+ virtual bool calcPenDepth(btSimplexSolverInterface& simplexSolver,
+ const btConvexShape* convexA, const btConvexShape* convexB,
+ const btTransform& transA, const btTransform& transB,
+ btVector3& v, btVector3& pa, btVector3& pb,
+ class btIDebugDraw* debugDraw) = 0;
};
-#endif //BT_CONVEX_PENETRATION_DEPTH_H
-
+#endif //BT_CONVEX_PENETRATION_DEPTH_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h
index 0ea7b483cf..d1bbb1a46e 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h
@@ -13,7 +13,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#ifndef BT_DISCRETE_COLLISION_DETECTOR1_INTERFACE_H
#define BT_DISCRETE_COLLISION_DETECTOR1_INTERFACE_H
@@ -27,64 +26,60 @@ subject to the following restrictions:
/// by taking closestPointInA = closestPointInB + m_distance * m_normalOnSurfaceB
struct btDiscreteCollisionDetectorInterface
{
-
struct Result
{
-
- virtual ~Result(){}
+ virtual ~Result() {}
///setShapeIdentifiersA/B provides experimental support for per-triangle material / custom material combiner
- virtual void setShapeIdentifiersA(int partId0,int index0)=0;
- virtual void setShapeIdentifiersB(int partId1,int index1)=0;
- virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)=0;
+ virtual void setShapeIdentifiersA(int partId0, int index0) = 0;
+ virtual void setShapeIdentifiersB(int partId1, int index1) = 0;
+ virtual void addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar depth) = 0;
};
struct ClosestPointInput
{
ClosestPointInput()
- :m_maximumDistanceSquared(btScalar(BT_LARGE_FLOAT))
+ : m_maximumDistanceSquared(btScalar(BT_LARGE_FLOAT))
{
}
btTransform m_transformA;
btTransform m_transformB;
- btScalar m_maximumDistanceSquared;
+ btScalar m_maximumDistanceSquared;
};
- virtual ~btDiscreteCollisionDetectorInterface() {};
+ virtual ~btDiscreteCollisionDetectorInterface(){};
//
// give either closest points (distance > 0) or penetration (distance)
// the normal always points from B towards A
//
- virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false) = 0;
-
+ virtual void getClosestPoints(const ClosestPointInput& input, Result& output, class btIDebugDraw* debugDraw, bool swapResults = false) = 0;
};
struct btStorageResult : public btDiscreteCollisionDetectorInterface::Result
{
- btVector3 m_normalOnSurfaceB;
- btVector3 m_closestPointInB;
- btScalar m_distance; //negative means penetration !
+ btVector3 m_normalOnSurfaceB;
+ btVector3 m_closestPointInB;
+ btScalar m_distance; //negative means penetration !
- protected:
- btStorageResult() : m_distance(btScalar(BT_LARGE_FLOAT))
- {
- }
-
- public:
- virtual ~btStorageResult() {};
+protected:
+ btStorageResult() : m_distance(btScalar(BT_LARGE_FLOAT))
+ {
+ }
+
+public:
+ virtual ~btStorageResult(){};
- virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)
+ virtual void addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar depth)
+ {
+ if (depth < m_distance)
{
- if (depth < m_distance)
- {
- m_normalOnSurfaceB = normalOnBInWorld;
- m_closestPointInB = pointInWorld;
- m_distance = depth;
- }
+ m_normalOnSurfaceB = normalOnBInWorld;
+ m_closestPointInB = pointInWorld;
+ m_distance = depth;
}
+ }
};
-#endif //BT_DISCRETE_COLLISION_DETECTOR1_INTERFACE_H
-
+#endif //BT_DISCRETE_COLLISION_DETECTOR1_INTERFACE_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkCollisionDescription.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkCollisionDescription.h
index 0b49b0ecc6..c9fd84bebf 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkCollisionDescription.h
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkCollisionDescription.h
@@ -13,7 +13,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#ifndef GJK_COLLISION_DESCRIPTION_H
#define GJK_COLLISION_DESCRIPTION_H
@@ -21,21 +20,20 @@ subject to the following restrictions:
struct btGjkCollisionDescription
{
- btVector3 m_firstDir;
- int m_maxGjkIterations;
- btScalar m_maximumDistanceSquared;
- btScalar m_gjkRelError2;
- btGjkCollisionDescription()
- :m_firstDir(0,1,0),
- m_maxGjkIterations(1000),
- m_maximumDistanceSquared(1e30f),
- m_gjkRelError2(1.0e-6)
- {
- }
- virtual ~btGjkCollisionDescription()
- {
- }
+ btVector3 m_firstDir;
+ int m_maxGjkIterations;
+ btScalar m_maximumDistanceSquared;
+ btScalar m_gjkRelError2;
+ btGjkCollisionDescription()
+ : m_firstDir(0, 1, 0),
+ m_maxGjkIterations(1000),
+ m_maximumDistanceSquared(1e30f),
+ m_gjkRelError2(1.0e-6)
+ {
+ }
+ virtual ~btGjkCollisionDescription()
+ {
+ }
};
-#endif //GJK_COLLISION_DESCRIPTION_H
-
+#endif //GJK_COLLISION_DESCRIPTION_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp
index bef697a0a1..9d61e75dac 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp
@@ -13,8 +13,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
-
#include "btGjkConvexCast.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h"
#include "btGjkPairDetector.h"
@@ -27,41 +25,39 @@ subject to the following restrictions:
#define MAX_ITERATIONS 32
#endif
-btGjkConvexCast::btGjkConvexCast(const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver)
-:m_simplexSolver(simplexSolver),
-m_convexA(convexA),
-m_convexB(convexB)
+btGjkConvexCast::btGjkConvexCast(const btConvexShape* convexA, const btConvexShape* convexB, btSimplexSolverInterface* simplexSolver)
+ : m_simplexSolver(simplexSolver),
+ m_convexA(convexA),
+ m_convexB(convexB)
{
}
-bool btGjkConvexCast::calcTimeOfImpact(
- const btTransform& fromA,
- const btTransform& toA,
- const btTransform& fromB,
- const btTransform& toB,
- CastResult& result)
+bool btGjkConvexCast::calcTimeOfImpact(
+ const btTransform& fromA,
+ const btTransform& toA,
+ const btTransform& fromB,
+ const btTransform& toB,
+ CastResult& result)
{
-
-
m_simplexSolver->reset();
/// compute linear velocity for this interval, to interpolate
//assume no rotation/angular velocity, assert here?
- btVector3 linVelA,linVelB;
- linVelA = toA.getOrigin()-fromA.getOrigin();
- linVelB = toB.getOrigin()-fromB.getOrigin();
+ btVector3 linVelA, linVelB;
+ linVelA = toA.getOrigin() - fromA.getOrigin();
+ linVelB = toB.getOrigin() - fromB.getOrigin();
btScalar radius = btScalar(0.001);
btScalar lambda = btScalar(0.);
- btVector3 v(1,0,0);
+ btVector3 v(1, 0, 0);
int maxIter = MAX_ITERATIONS;
btVector3 n;
- n.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+ n.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
bool hasResult = false;
btVector3 c;
- btVector3 r = (linVelA-linVelB);
+ btVector3 r = (linVelA - linVelB);
btScalar lastLambda = lambda;
//btScalar epsilon = btScalar(0.001);
@@ -69,17 +65,14 @@ bool btGjkConvexCast::calcTimeOfImpact(
int numIter = 0;
//first solution, using GJK
-
btTransform identityTrans;
identityTrans.setIdentity();
+ // result.drawCoordSystem(sphereTr);
-// result.drawCoordSystem(sphereTr);
-
- btPointCollector pointCollector;
+ btPointCollector pointCollector;
-
- btGjkPairDetector gjk(m_convexA,m_convexB,m_simplexSolver,0);//m_penetrationDepthSolver);
+ btGjkPairDetector gjk(m_convexA, m_convexB, m_simplexSolver, 0); //m_penetrationDepthSolver);
btGjkPairDetector::ClosestPointInput input;
//we don't use margins during CCD
@@ -87,7 +80,7 @@ bool btGjkConvexCast::calcTimeOfImpact(
input.m_transformA = fromA;
input.m_transformB = fromB;
- gjk.getClosestPoints(input,pointCollector,0);
+ gjk.getClosestPoints(input, pointCollector, 0);
hasResult = pointCollector.m_hasResult;
c = pointCollector.m_pointInWorld;
@@ -98,20 +91,18 @@ bool btGjkConvexCast::calcTimeOfImpact(
dist = pointCollector.m_distance;
n = pointCollector.m_normalOnBInWorld;
-
-
//not close enough
while (dist > radius)
{
numIter++;
if (numIter > maxIter)
{
- return false; //todo: report a failure
+ return false; //todo: report a failure
}
btScalar dLambda = btScalar(0.);
btScalar projectedLinearVelocity = r.dot(n);
-
+
dLambda = dist / (projectedLinearVelocity);
lambda = lambda - dLambda;
@@ -132,35 +123,35 @@ bool btGjkConvexCast::calcTimeOfImpact(
lastLambda = lambda;
//interpolate to next lambda
- result.DebugDraw( lambda );
- input.m_transformA.getOrigin().setInterpolate3(fromA.getOrigin(),toA.getOrigin(),lambda);
- input.m_transformB.getOrigin().setInterpolate3(fromB.getOrigin(),toB.getOrigin(),lambda);
-
- gjk.getClosestPoints(input,pointCollector,0);
+ result.DebugDraw(lambda);
+ input.m_transformA.getOrigin().setInterpolate3(fromA.getOrigin(), toA.getOrigin(), lambda);
+ input.m_transformB.getOrigin().setInterpolate3(fromB.getOrigin(), toB.getOrigin(), lambda);
+
+ gjk.getClosestPoints(input, pointCollector, 0);
if (pointCollector.m_hasResult)
{
if (pointCollector.m_distance < btScalar(0.))
{
result.m_fraction = lastLambda;
n = pointCollector.m_normalOnBInWorld;
- result.m_normal=n;
+ result.m_normal = n;
result.m_hitPoint = pointCollector.m_pointInWorld;
return true;
}
- c = pointCollector.m_pointInWorld;
+ c = pointCollector.m_pointInWorld;
n = pointCollector.m_normalOnBInWorld;
dist = pointCollector.m_distance;
- } else
+ }
+ else
{
//??
return false;
}
-
}
//is n normalized?
//don't report time of impact for motion away from the contact normal (or causes minor penetration)
- if (n.dot(r)>=-result.m_allowedPenetration)
+ if (n.dot(r) >= -result.m_allowedPenetration)
return false;
result.m_fraction = lambda;
@@ -170,7 +161,4 @@ bool btGjkConvexCast::calcTimeOfImpact(
}
return false;
-
-
}
-
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h
index 6a42ee63b0..ef5979173e 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h
@@ -13,8 +13,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
-
#ifndef BT_GJK_CONVEX_CAST_H
#define BT_GJK_CONVEX_CAST_H
@@ -29,22 +27,20 @@ class btMinkowskiSumShape;
///GjkConvexCast performs a raycast on a convex object using support mapping.
class btGjkConvexCast : public btConvexCast
{
- btSimplexSolverInterface* m_simplexSolver;
- const btConvexShape* m_convexA;
- const btConvexShape* m_convexB;
+ btSimplexSolverInterface* m_simplexSolver;
+ const btConvexShape* m_convexA;
+ const btConvexShape* m_convexB;
public:
-
- btGjkConvexCast(const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver);
+ btGjkConvexCast(const btConvexShape* convexA, const btConvexShape* convexB, btSimplexSolverInterface* simplexSolver);
/// cast a convex against another convex object
- virtual bool calcTimeOfImpact(
- const btTransform& fromA,
- const btTransform& toA,
- const btTransform& fromB,
- const btTransform& toB,
- CastResult& result);
-
+ virtual bool calcTimeOfImpact(
+ const btTransform& fromA,
+ const btTransform& toA,
+ const btTransform& fromB,
+ const btTransform& toB,
+ CastResult& result);
};
-#endif //BT_GJK_CONVEX_CAST_H
+#endif //BT_GJK_CONVEX_CAST_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp
index eefb974bbd..45d1817135 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp
@@ -26,1010 +26,1065 @@ GJK-EPA collision solver by Nathanael Presson, 2008
#include "BulletCollision/CollisionShapes/btSphereShape.h"
#include "btGjkEpa2.h"
-#if defined(DEBUG) || defined (_DEBUG)
-#include <stdio.h> //for debug printf
+#if defined(DEBUG) || defined(_DEBUG)
+#include <stdio.h> //for debug printf
#ifdef __SPU__
#include <spu_printf.h>
#define printf spu_printf
-#endif //__SPU__
+#endif //__SPU__
#endif
namespace gjkepa2_impl
{
+// Config
- // Config
-
- /* GJK */
-#define GJK_MAX_ITERATIONS 128
+/* GJK */
+#define GJK_MAX_ITERATIONS 128
#ifdef BT_USE_DOUBLE_PRECISION
- #define GJK_ACCURACY ((btScalar)1e-12)
- #define GJK_MIN_DISTANCE ((btScalar)1e-12)
- #define GJK_DUPLICATED_EPS ((btScalar)1e-12)
+#define GJK_ACCURACY ((btScalar)1e-12)
+#define GJK_MIN_DISTANCE ((btScalar)1e-12)
+#define GJK_DUPLICATED_EPS ((btScalar)1e-12)
#else
- #define GJK_ACCURACY ((btScalar)0.0001)
- #define GJK_MIN_DISTANCE ((btScalar)0.0001)
- #define GJK_DUPLICATED_EPS ((btScalar)0.0001)
-#endif //BT_USE_DOUBLE_PRECISION
-
+#define GJK_ACCURACY ((btScalar)0.0001)
+#define GJK_MIN_DISTANCE ((btScalar)0.0001)
+#define GJK_DUPLICATED_EPS ((btScalar)0.0001)
+#endif //BT_USE_DOUBLE_PRECISION
-#define GJK_SIMPLEX2_EPS ((btScalar)0.0)
-#define GJK_SIMPLEX3_EPS ((btScalar)0.0)
-#define GJK_SIMPLEX4_EPS ((btScalar)0.0)
+#define GJK_SIMPLEX2_EPS ((btScalar)0.0)
+#define GJK_SIMPLEX3_EPS ((btScalar)0.0)
+#define GJK_SIMPLEX4_EPS ((btScalar)0.0)
- /* EPA */
-#define EPA_MAX_VERTICES 128
-#define EPA_MAX_ITERATIONS 255
+/* EPA */
+#define EPA_MAX_VERTICES 128
+#define EPA_MAX_ITERATIONS 255
#ifdef BT_USE_DOUBLE_PRECISION
- #define EPA_ACCURACY ((btScalar)1e-12)
- #define EPA_PLANE_EPS ((btScalar)1e-14)
- #define EPA_INSIDE_EPS ((btScalar)1e-9)
+#define EPA_ACCURACY ((btScalar)1e-12)
+#define EPA_PLANE_EPS ((btScalar)1e-14)
+#define EPA_INSIDE_EPS ((btScalar)1e-9)
#else
- #define EPA_ACCURACY ((btScalar)0.0001)
- #define EPA_PLANE_EPS ((btScalar)0.00001)
- #define EPA_INSIDE_EPS ((btScalar)0.01)
+#define EPA_ACCURACY ((btScalar)0.0001)
+#define EPA_PLANE_EPS ((btScalar)0.00001)
+#define EPA_INSIDE_EPS ((btScalar)0.01)
#endif
-#define EPA_FALLBACK (10*EPA_ACCURACY)
-#define EPA_MAX_FACES (EPA_MAX_VERTICES*2)
-
+#define EPA_FALLBACK (10 * EPA_ACCURACY)
+#define EPA_MAX_FACES (EPA_MAX_VERTICES * 2)
- // Shorthands
- typedef unsigned int U;
- typedef unsigned char U1;
+// Shorthands
+typedef unsigned int U;
+typedef unsigned char U1;
- // MinkowskiDiff
- struct MinkowskiDiff
- {
- const btConvexShape* m_shapes[2];
- btMatrix3x3 m_toshape1;
- btTransform m_toshape0;
+// MinkowskiDiff
+struct MinkowskiDiff
+{
+ const btConvexShape* m_shapes[2];
+ btMatrix3x3 m_toshape1;
+ btTransform m_toshape0;
#ifdef __SPU__
- bool m_enableMargin;
+ bool m_enableMargin;
#else
- btVector3 (btConvexShape::*Ls)(const btVector3&) const;
-#endif//__SPU__
-
+ btVector3 (btConvexShape::*Ls)(const btVector3&) const;
+#endif //__SPU__
- MinkowskiDiff()
- {
-
- }
+ MinkowskiDiff()
+ {
+ }
#ifdef __SPU__
- void EnableMargin(bool enable)
- {
- m_enableMargin = enable;
- }
- inline btVector3 Support0(const btVector3& d) const
- {
- if (m_enableMargin)
- {
- return m_shapes[0]->localGetSupportVertexNonVirtual(d);
- } else
- {
- return m_shapes[0]->localGetSupportVertexWithoutMarginNonVirtual(d);
- }
- }
- inline btVector3 Support1(const btVector3& d) const
- {
- if (m_enableMargin)
- {
- return m_toshape0*(m_shapes[1]->localGetSupportVertexNonVirtual(m_toshape1*d));
- } else
- {
- return m_toshape0*(m_shapes[1]->localGetSupportVertexWithoutMarginNonVirtual(m_toshape1*d));
- }
- }
-#else
- void EnableMargin(bool enable)
- {
- if(enable)
- Ls=&btConvexShape::localGetSupportVertexNonVirtual;
- else
- Ls=&btConvexShape::localGetSupportVertexWithoutMarginNonVirtual;
- }
- inline btVector3 Support0(const btVector3& d) const
+ void EnableMargin(bool enable)
+ {
+ m_enableMargin = enable;
+ }
+ inline btVector3 Support0(const btVector3& d) const
+ {
+ if (m_enableMargin)
{
- return(((m_shapes[0])->*(Ls))(d));
+ return m_shapes[0]->localGetSupportVertexNonVirtual(d);
}
- inline btVector3 Support1(const btVector3& d) const
+ else
{
- return(m_toshape0*((m_shapes[1])->*(Ls))(m_toshape1*d));
+ return m_shapes[0]->localGetSupportVertexWithoutMarginNonVirtual(d);
}
-#endif //__SPU__
-
- inline btVector3 Support(const btVector3& d) const
+ }
+ inline btVector3 Support1(const btVector3& d) const
+ {
+ if (m_enableMargin)
{
- return(Support0(d)-Support1(-d));
+ return m_toshape0 * (m_shapes[1]->localGetSupportVertexNonVirtual(m_toshape1 * d));
}
- btVector3 Support(const btVector3& d,U index) const
+ else
{
- if(index)
- return(Support1(d));
- else
- return(Support0(d));
+ return m_toshape0 * (m_shapes[1]->localGetSupportVertexWithoutMarginNonVirtual(m_toshape1 * d));
}
- };
+ }
+#else
+ void EnableMargin(bool enable)
+ {
+ if (enable)
+ Ls = &btConvexShape::localGetSupportVertexNonVirtual;
+ else
+ Ls = &btConvexShape::localGetSupportVertexWithoutMarginNonVirtual;
+ }
+ inline btVector3 Support0(const btVector3& d) const
+ {
+ return (((m_shapes[0])->*(Ls))(d));
+ }
+ inline btVector3 Support1(const btVector3& d) const
+ {
+ return (m_toshape0 * ((m_shapes[1])->*(Ls))(m_toshape1 * d));
+ }
+#endif //__SPU__
- typedef MinkowskiDiff tShape;
+ inline btVector3 Support(const btVector3& d) const
+ {
+ return (Support0(d) - Support1(-d));
+ }
+ btVector3 Support(const btVector3& d, U index) const
+ {
+ if (index)
+ return (Support1(d));
+ else
+ return (Support0(d));
+ }
+};
+typedef MinkowskiDiff tShape;
- // GJK
- struct GJK
+// GJK
+struct GJK
+{
+ /* Types */
+ struct sSV
{
- /* Types */
- struct sSV
- {
- btVector3 d,w;
- };
- struct sSimplex
+ btVector3 d, w;
+ };
+ struct sSimplex
+ {
+ sSV* c[4];
+ btScalar p[4];
+ U rank;
+ };
+ struct eStatus
+ {
+ enum _
{
- sSV* c[4];
- btScalar p[4];
- U rank;
- };
- struct eStatus { enum _ {
Valid,
Inside,
- Failed };};
- /* Fields */
- tShape m_shape;
- btVector3 m_ray;
- btScalar m_distance;
- sSimplex m_simplices[2];
- sSV m_store[4];
- sSV* m_free[4];
- U m_nfree;
- U m_current;
- sSimplex* m_simplex;
- eStatus::_ m_status;
- /* Methods */
- GJK()
- {
- Initialize();
+ Failed
+ };
+ };
+ /* Fields */
+ tShape m_shape;
+ btVector3 m_ray;
+ btScalar m_distance;
+ sSimplex m_simplices[2];
+ sSV m_store[4];
+ sSV* m_free[4];
+ U m_nfree;
+ U m_current;
+ sSimplex* m_simplex;
+ eStatus::_ m_status;
+ /* Methods */
+ GJK()
+ {
+ Initialize();
+ }
+ void Initialize()
+ {
+ m_ray = btVector3(0, 0, 0);
+ m_nfree = 0;
+ m_status = eStatus::Failed;
+ m_current = 0;
+ m_distance = 0;
+ }
+ eStatus::_ Evaluate(const tShape& shapearg, const btVector3& guess)
+ {
+ U iterations = 0;
+ btScalar sqdist = 0;
+ btScalar alpha = 0;
+ btVector3 lastw[4];
+ U clastw = 0;
+ /* Initialize solver */
+ m_free[0] = &m_store[0];
+ m_free[1] = &m_store[1];
+ m_free[2] = &m_store[2];
+ m_free[3] = &m_store[3];
+ m_nfree = 4;
+ m_current = 0;
+ m_status = eStatus::Valid;
+ m_shape = shapearg;
+ m_distance = 0;
+ /* Initialize simplex */
+ m_simplices[0].rank = 0;
+ m_ray = guess;
+ const btScalar sqrl = m_ray.length2();
+ appendvertice(m_simplices[0], sqrl > 0 ? -m_ray : btVector3(1, 0, 0));
+ m_simplices[0].p[0] = 1;
+ m_ray = m_simplices[0].c[0]->w;
+ sqdist = sqrl;
+ lastw[0] =
+ lastw[1] =
+ lastw[2] =
+ lastw[3] = m_ray;
+ /* Loop */
+ do
+ {
+ const U next = 1 - m_current;
+ sSimplex& cs = m_simplices[m_current];
+ sSimplex& ns = m_simplices[next];
+ /* Check zero */
+ const btScalar rl = m_ray.length();
+ if (rl < GJK_MIN_DISTANCE)
+ { /* Touching or inside */
+ m_status = eStatus::Inside;
+ break;
}
- void Initialize()
+ /* Append new vertice in -'v' direction */
+ appendvertice(cs, -m_ray);
+ const btVector3& w = cs.c[cs.rank - 1]->w;
+ bool found = false;
+ for (U i = 0; i < 4; ++i)
{
- m_ray = btVector3(0,0,0);
- m_nfree = 0;
- m_status = eStatus::Failed;
- m_current = 0;
- m_distance = 0;
+ if ((w - lastw[i]).length2() < GJK_DUPLICATED_EPS)
+ {
+ found = true;
+ break;
+ }
+ }
+ if (found)
+ { /* Return old simplex */
+ removevertice(m_simplices[m_current]);
+ break;
+ }
+ else
+ { /* Update lastw */
+ lastw[clastw = (clastw + 1) & 3] = w;
+ }
+ /* Check for termination */
+ const btScalar omega = btDot(m_ray, w) / rl;
+ alpha = btMax(omega, alpha);
+ if (((rl - alpha) - (GJK_ACCURACY * rl)) <= 0)
+ { /* Return old simplex */
+ removevertice(m_simplices[m_current]);
+ break;
}
- eStatus::_ Evaluate(const tShape& shapearg,const btVector3& guess)
+ /* Reduce simplex */
+ btScalar weights[4];
+ U mask = 0;
+ switch (cs.rank)
{
- U iterations=0;
- btScalar sqdist=0;
- btScalar alpha=0;
- btVector3 lastw[4];
- U clastw=0;
- /* Initialize solver */
- m_free[0] = &m_store[0];
- m_free[1] = &m_store[1];
- m_free[2] = &m_store[2];
- m_free[3] = &m_store[3];
- m_nfree = 4;
- m_current = 0;
- m_status = eStatus::Valid;
- m_shape = shapearg;
- m_distance = 0;
- /* Initialize simplex */
- m_simplices[0].rank = 0;
- m_ray = guess;
- const btScalar sqrl= m_ray.length2();
- appendvertice(m_simplices[0],sqrl>0?-m_ray:btVector3(1,0,0));
- m_simplices[0].p[0] = 1;
- m_ray = m_simplices[0].c[0]->w;
- sqdist = sqrl;
- lastw[0] =
- lastw[1] =
- lastw[2] =
- lastw[3] = m_ray;
- /* Loop */
- do {
- const U next=1-m_current;
- sSimplex& cs=m_simplices[m_current];
- sSimplex& ns=m_simplices[next];
- /* Check zero */
- const btScalar rl=m_ray.length();
- if(rl<GJK_MIN_DISTANCE)
- {/* Touching or inside */
- m_status=eStatus::Inside;
- break;
- }
- /* Append new vertice in -'v' direction */
- appendvertice(cs,-m_ray);
- const btVector3& w=cs.c[cs.rank-1]->w;
- bool found=false;
- for(U i=0;i<4;++i)
+ case 2:
+ sqdist = projectorigin(cs.c[0]->w,
+ cs.c[1]->w,
+ weights, mask);
+ break;
+ case 3:
+ sqdist = projectorigin(cs.c[0]->w,
+ cs.c[1]->w,
+ cs.c[2]->w,
+ weights, mask);
+ break;
+ case 4:
+ sqdist = projectorigin(cs.c[0]->w,
+ cs.c[1]->w,
+ cs.c[2]->w,
+ cs.c[3]->w,
+ weights, mask);
+ break;
+ }
+ if (sqdist >= 0)
+ { /* Valid */
+ ns.rank = 0;
+ m_ray = btVector3(0, 0, 0);
+ m_current = next;
+ for (U i = 0, ni = cs.rank; i < ni; ++i)
+ {
+ if (mask & (1 << i))
{
- if((w-lastw[i]).length2()<GJK_DUPLICATED_EPS)
- { found=true;break; }
- }
- if(found)
- {/* Return old simplex */
- removevertice(m_simplices[m_current]);
- break;
+ ns.c[ns.rank] = cs.c[i];
+ ns.p[ns.rank++] = weights[i];
+ m_ray += cs.c[i]->w * weights[i];
}
else
- {/* Update lastw */
- lastw[clastw=(clastw+1)&3]=w;
- }
- /* Check for termination */
- const btScalar omega=btDot(m_ray,w)/rl;
- alpha=btMax(omega,alpha);
- if(((rl-alpha)-(GJK_ACCURACY*rl))<=0)
- {/* Return old simplex */
- removevertice(m_simplices[m_current]);
- break;
- }
- /* Reduce simplex */
- btScalar weights[4];
- U mask=0;
- switch(cs.rank)
{
- case 2: sqdist=projectorigin( cs.c[0]->w,
- cs.c[1]->w,
- weights,mask);break;
- case 3: sqdist=projectorigin( cs.c[0]->w,
- cs.c[1]->w,
- cs.c[2]->w,
- weights,mask);break;
- case 4: sqdist=projectorigin( cs.c[0]->w,
- cs.c[1]->w,
- cs.c[2]->w,
- cs.c[3]->w,
- weights,mask);break;
- }
- if(sqdist>=0)
- {/* Valid */
- ns.rank = 0;
- m_ray = btVector3(0,0,0);
- m_current = next;
- for(U i=0,ni=cs.rank;i<ni;++i)
- {
- if(mask&(1<<i))
- {
- ns.c[ns.rank] = cs.c[i];
- ns.p[ns.rank++] = weights[i];
- m_ray += cs.c[i]->w*weights[i];
- }
- else
- {
- m_free[m_nfree++] = cs.c[i];
- }
- }
- if(mask==15) m_status=eStatus::Inside;
+ m_free[m_nfree++] = cs.c[i];
}
- else
- {/* Return old simplex */
- removevertice(m_simplices[m_current]);
- break;
- }
- m_status=((++iterations)<GJK_MAX_ITERATIONS)?m_status:eStatus::Failed;
- } while(m_status==eStatus::Valid);
- m_simplex=&m_simplices[m_current];
- switch(m_status)
+ }
+ if (mask == 15) m_status = eStatus::Inside;
+ }
+ else
+ { /* Return old simplex */
+ removevertice(m_simplices[m_current]);
+ break;
+ }
+ m_status = ((++iterations) < GJK_MAX_ITERATIONS) ? m_status : eStatus::Failed;
+ } while (m_status == eStatus::Valid);
+ m_simplex = &m_simplices[m_current];
+ switch (m_status)
+ {
+ case eStatus::Valid:
+ m_distance = m_ray.length();
+ break;
+ case eStatus::Inside:
+ m_distance = 0;
+ break;
+ default:
+ {
+ }
+ }
+ return (m_status);
+ }
+ bool EncloseOrigin()
+ {
+ switch (m_simplex->rank)
+ {
+ case 1:
+ {
+ for (U i = 0; i < 3; ++i)
{
- case eStatus::Valid: m_distance=m_ray.length();break;
- case eStatus::Inside: m_distance=0;break;
- default:
- {
- }
- }
- return(m_status);
+ btVector3 axis = btVector3(0, 0, 0);
+ axis[i] = 1;
+ appendvertice(*m_simplex, axis);
+ if (EncloseOrigin()) return (true);
+ removevertice(*m_simplex);
+ appendvertice(*m_simplex, -axis);
+ if (EncloseOrigin()) return (true);
+ removevertice(*m_simplex);
+ }
}
- bool EncloseOrigin()
+ break;
+ case 2:
{
- switch(m_simplex->rank)
+ const btVector3 d = m_simplex->c[1]->w - m_simplex->c[0]->w;
+ for (U i = 0; i < 3; ++i)
{
- case 1:
- {
- for(U i=0;i<3;++i)
- {
- btVector3 axis=btVector3(0,0,0);
- axis[i]=1;
- appendvertice(*m_simplex, axis);
- if(EncloseOrigin()) return(true);
- removevertice(*m_simplex);
- appendvertice(*m_simplex,-axis);
- if(EncloseOrigin()) return(true);
- removevertice(*m_simplex);
- }
- }
- break;
- case 2:
- {
- const btVector3 d=m_simplex->c[1]->w-m_simplex->c[0]->w;
- for(U i=0;i<3;++i)
- {
- btVector3 axis=btVector3(0,0,0);
- axis[i]=1;
- const btVector3 p=btCross(d,axis);
- if(p.length2()>0)
- {
- appendvertice(*m_simplex, p);
- if(EncloseOrigin()) return(true);
- removevertice(*m_simplex);
- appendvertice(*m_simplex,-p);
- if(EncloseOrigin()) return(true);
- removevertice(*m_simplex);
- }
- }
- }
- break;
- case 3:
- {
- const btVector3 n=btCross(m_simplex->c[1]->w-m_simplex->c[0]->w,
- m_simplex->c[2]->w-m_simplex->c[0]->w);
- if(n.length2()>0)
- {
- appendvertice(*m_simplex,n);
- if(EncloseOrigin()) return(true);
- removevertice(*m_simplex);
- appendvertice(*m_simplex,-n);
- if(EncloseOrigin()) return(true);
- removevertice(*m_simplex);
- }
- }
- break;
- case 4:
+ btVector3 axis = btVector3(0, 0, 0);
+ axis[i] = 1;
+ const btVector3 p = btCross(d, axis);
+ if (p.length2() > 0)
{
- if(btFabs(det( m_simplex->c[0]->w-m_simplex->c[3]->w,
- m_simplex->c[1]->w-m_simplex->c[3]->w,
- m_simplex->c[2]->w-m_simplex->c[3]->w))>0)
- return(true);
+ appendvertice(*m_simplex, p);
+ if (EncloseOrigin()) return (true);
+ removevertice(*m_simplex);
+ appendvertice(*m_simplex, -p);
+ if (EncloseOrigin()) return (true);
+ removevertice(*m_simplex);
}
- break;
}
- return(false);
}
- /* Internals */
- void getsupport(const btVector3& d,sSV& sv) const
+ break;
+ case 3:
{
- sv.d = d/d.length();
- sv.w = m_shape.Support(sv.d);
+ const btVector3 n = btCross(m_simplex->c[1]->w - m_simplex->c[0]->w,
+ m_simplex->c[2]->w - m_simplex->c[0]->w);
+ if (n.length2() > 0)
+ {
+ appendvertice(*m_simplex, n);
+ if (EncloseOrigin()) return (true);
+ removevertice(*m_simplex);
+ appendvertice(*m_simplex, -n);
+ if (EncloseOrigin()) return (true);
+ removevertice(*m_simplex);
+ }
}
- void removevertice(sSimplex& simplex)
+ break;
+ case 4:
{
- m_free[m_nfree++]=simplex.c[--simplex.rank];
+ if (btFabs(det(m_simplex->c[0]->w - m_simplex->c[3]->w,
+ m_simplex->c[1]->w - m_simplex->c[3]->w,
+ m_simplex->c[2]->w - m_simplex->c[3]->w)) > 0)
+ return (true);
}
- void appendvertice(sSimplex& simplex,const btVector3& v)
+ break;
+ }
+ return (false);
+ }
+ /* Internals */
+ void getsupport(const btVector3& d, sSV& sv) const
+ {
+ sv.d = d / d.length();
+ sv.w = m_shape.Support(sv.d);
+ }
+ void removevertice(sSimplex& simplex)
+ {
+ m_free[m_nfree++] = simplex.c[--simplex.rank];
+ }
+ void appendvertice(sSimplex& simplex, const btVector3& v)
+ {
+ simplex.p[simplex.rank] = 0;
+ simplex.c[simplex.rank] = m_free[--m_nfree];
+ getsupport(v, *simplex.c[simplex.rank++]);
+ }
+ static btScalar det(const btVector3& a, const btVector3& b, const btVector3& c)
+ {
+ return (a.y() * b.z() * c.x() + a.z() * b.x() * c.y() -
+ a.x() * b.z() * c.y() - a.y() * b.x() * c.z() +
+ a.x() * b.y() * c.z() - a.z() * b.y() * c.x());
+ }
+ static btScalar projectorigin(const btVector3& a,
+ const btVector3& b,
+ btScalar* w, U& m)
+ {
+ const btVector3 d = b - a;
+ const btScalar l = d.length2();
+ if (l > GJK_SIMPLEX2_EPS)
+ {
+ const btScalar t(l > 0 ? -btDot(a, d) / l : 0);
+ if (t >= 1)
{
- simplex.p[simplex.rank]=0;
- simplex.c[simplex.rank]=m_free[--m_nfree];
- getsupport(v,*simplex.c[simplex.rank++]);
+ w[0] = 0;
+ w[1] = 1;
+ m = 2;
+ return (b.length2());
}
- static btScalar det(const btVector3& a,const btVector3& b,const btVector3& c)
+ else if (t <= 0)
{
- return( a.y()*b.z()*c.x()+a.z()*b.x()*c.y()-
- a.x()*b.z()*c.y()-a.y()*b.x()*c.z()+
- a.x()*b.y()*c.z()-a.z()*b.y()*c.x());
+ w[0] = 1;
+ w[1] = 0;
+ m = 1;
+ return (a.length2());
}
- static btScalar projectorigin( const btVector3& a,
- const btVector3& b,
- btScalar* w,U& m)
+ else
{
- const btVector3 d=b-a;
- const btScalar l=d.length2();
- if(l>GJK_SIMPLEX2_EPS)
- {
- const btScalar t(l>0?-btDot(a,d)/l:0);
- if(t>=1) { w[0]=0;w[1]=1;m=2;return(b.length2()); }
- else if(t<=0) { w[0]=1;w[1]=0;m=1;return(a.length2()); }
- else { w[0]=1-(w[1]=t);m=3;return((a+d*t).length2()); }
- }
- return(-1);
+ w[0] = 1 - (w[1] = t);
+ m = 3;
+ return ((a + d * t).length2());
}
- static btScalar projectorigin( const btVector3& a,
- const btVector3& b,
- const btVector3& c,
- btScalar* w,U& m)
+ }
+ return (-1);
+ }
+ static btScalar projectorigin(const btVector3& a,
+ const btVector3& b,
+ const btVector3& c,
+ btScalar* w, U& m)
+ {
+ static const U imd3[] = {1, 2, 0};
+ const btVector3* vt[] = {&a, &b, &c};
+ const btVector3 dl[] = {a - b, b - c, c - a};
+ const btVector3 n = btCross(dl[0], dl[1]);
+ const btScalar l = n.length2();
+ if (l > GJK_SIMPLEX3_EPS)
+ {
+ btScalar mindist = -1;
+ btScalar subw[2] = {0.f, 0.f};
+ U subm(0);
+ for (U i = 0; i < 3; ++i)
{
- static const U imd3[]={1,2,0};
- const btVector3* vt[]={&a,&b,&c};
- const btVector3 dl[]={a-b,b-c,c-a};
- const btVector3 n=btCross(dl[0],dl[1]);
- const btScalar l=n.length2();
- if(l>GJK_SIMPLEX3_EPS)
+ if (btDot(*vt[i], btCross(dl[i], n)) > 0)
{
- btScalar mindist=-1;
- btScalar subw[2]={0.f,0.f};
- U subm(0);
- for(U i=0;i<3;++i)
+ const U j = imd3[i];
+ const btScalar subd(projectorigin(*vt[i], *vt[j], subw, subm));
+ if ((mindist < 0) || (subd < mindist))
{
- if(btDot(*vt[i],btCross(dl[i],n))>0)
- {
- const U j=imd3[i];
- const btScalar subd(projectorigin(*vt[i],*vt[j],subw,subm));
- if((mindist<0)||(subd<mindist))
- {
- mindist = subd;
- m = static_cast<U>(((subm&1)?1<<i:0)+((subm&2)?1<<j:0));
- w[i] = subw[0];
- w[j] = subw[1];
- w[imd3[j]] = 0;
- }
- }
+ mindist = subd;
+ m = static_cast<U>(((subm & 1) ? 1 << i : 0) + ((subm & 2) ? 1 << j : 0));
+ w[i] = subw[0];
+ w[j] = subw[1];
+ w[imd3[j]] = 0;
}
- if(mindist<0)
- {
- const btScalar d=btDot(a,n);
- const btScalar s=btSqrt(l);
- const btVector3 p=n*(d/l);
- mindist = p.length2();
- m = 7;
- w[0] = (btCross(dl[1],b-p)).length()/s;
- w[1] = (btCross(dl[2],c-p)).length()/s;
- w[2] = 1-(w[0]+w[1]);
- }
- return(mindist);
}
- return(-1);
}
- static btScalar projectorigin( const btVector3& a,
- const btVector3& b,
- const btVector3& c,
- const btVector3& d,
- btScalar* w,U& m)
+ if (mindist < 0)
{
- static const U imd3[]={1,2,0};
- const btVector3* vt[]={&a,&b,&c,&d};
- const btVector3 dl[]={a-d,b-d,c-d};
- const btScalar vl=det(dl[0],dl[1],dl[2]);
- const bool ng=(vl*btDot(a,btCross(b-c,a-b)))<=0;
- if(ng&&(btFabs(vl)>GJK_SIMPLEX4_EPS))
+ const btScalar d = btDot(a, n);
+ const btScalar s = btSqrt(l);
+ const btVector3 p = n * (d / l);
+ mindist = p.length2();
+ m = 7;
+ w[0] = (btCross(dl[1], b - p)).length() / s;
+ w[1] = (btCross(dl[2], c - p)).length() / s;
+ w[2] = 1 - (w[0] + w[1]);
+ }
+ return (mindist);
+ }
+ return (-1);
+ }
+ static btScalar projectorigin(const btVector3& a,
+ const btVector3& b,
+ const btVector3& c,
+ const btVector3& d,
+ btScalar* w, U& m)
+ {
+ static const U imd3[] = {1, 2, 0};
+ const btVector3* vt[] = {&a, &b, &c, &d};
+ const btVector3 dl[] = {a - d, b - d, c - d};
+ const btScalar vl = det(dl[0], dl[1], dl[2]);
+ const bool ng = (vl * btDot(a, btCross(b - c, a - b))) <= 0;
+ if (ng && (btFabs(vl) > GJK_SIMPLEX4_EPS))
+ {
+ btScalar mindist = -1;
+ btScalar subw[3] = {0.f, 0.f, 0.f};
+ U subm(0);
+ for (U i = 0; i < 3; ++i)
+ {
+ const U j = imd3[i];
+ const btScalar s = vl * btDot(d, btCross(dl[i], dl[j]));
+ if (s > 0)
{
- btScalar mindist=-1;
- btScalar subw[3]={0.f,0.f,0.f};
- U subm(0);
- for(U i=0;i<3;++i)
- {
- const U j=imd3[i];
- const btScalar s=vl*btDot(d,btCross(dl[i],dl[j]));
- if(s>0)
- {
- const btScalar subd=projectorigin(*vt[i],*vt[j],d,subw,subm);
- if((mindist<0)||(subd<mindist))
- {
- mindist = subd;
- m = static_cast<U>((subm&1?1<<i:0)+
- (subm&2?1<<j:0)+
- (subm&4?8:0));
- w[i] = subw[0];
- w[j] = subw[1];
- w[imd3[j]] = 0;
- w[3] = subw[2];
- }
- }
- }
- if(mindist<0)
+ const btScalar subd = projectorigin(*vt[i], *vt[j], d, subw, subm);
+ if ((mindist < 0) || (subd < mindist))
{
- mindist = 0;
- m = 15;
- w[0] = det(c,b,d)/vl;
- w[1] = det(a,c,d)/vl;
- w[2] = det(b,a,d)/vl;
- w[3] = 1-(w[0]+w[1]+w[2]);
+ mindist = subd;
+ m = static_cast<U>((subm & 1 ? 1 << i : 0) +
+ (subm & 2 ? 1 << j : 0) +
+ (subm & 4 ? 8 : 0));
+ w[i] = subw[0];
+ w[j] = subw[1];
+ w[imd3[j]] = 0;
+ w[3] = subw[2];
}
- return(mindist);
}
- return(-1);
}
- };
+ if (mindist < 0)
+ {
+ mindist = 0;
+ m = 15;
+ w[0] = det(c, b, d) / vl;
+ w[1] = det(a, c, d) / vl;
+ w[2] = det(b, a, d) / vl;
+ w[3] = 1 - (w[0] + w[1] + w[2]);
+ }
+ return (mindist);
+ }
+ return (-1);
+ }
+};
- // EPA
- struct EPA
+// EPA
+struct EPA
+{
+ /* Types */
+ typedef GJK::sSV sSV;
+ struct sFace
{
- /* Types */
- typedef GJK::sSV sSV;
- struct sFace
- {
- btVector3 n;
- btScalar d;
- sSV* c[3];
- sFace* f[3];
- sFace* l[2];
- U1 e[3];
- U1 pass;
- };
- struct sList
- {
- sFace* root;
- U count;
- sList() : root(0),count(0) {}
- };
- struct sHorizon
+ btVector3 n;
+ btScalar d;
+ sSV* c[3];
+ sFace* f[3];
+ sFace* l[2];
+ U1 e[3];
+ U1 pass;
+ };
+ struct sList
+ {
+ sFace* root;
+ U count;
+ sList() : root(0), count(0) {}
+ };
+ struct sHorizon
+ {
+ sFace* cf;
+ sFace* ff;
+ U nf;
+ sHorizon() : cf(0), ff(0), nf(0) {}
+ };
+ struct eStatus
+ {
+ enum _
{
- sFace* cf;
- sFace* ff;
- U nf;
- sHorizon() : cf(0),ff(0),nf(0) {}
- };
- struct eStatus { enum _ {
Valid,
Touching,
Degenerated,
NonConvex,
- InvalidHull,
+ InvalidHull,
OutOfFaces,
OutOfVertices,
AccuraryReached,
FallBack,
- Failed };};
- /* Fields */
- eStatus::_ m_status;
- GJK::sSimplex m_result;
- btVector3 m_normal;
- btScalar m_depth;
- sSV m_sv_store[EPA_MAX_VERTICES];
- sFace m_fc_store[EPA_MAX_FACES];
- U m_nextsv;
- sList m_hull;
- sList m_stock;
- /* Methods */
- EPA()
- {
- Initialize();
- }
+ Failed
+ };
+ };
+ /* Fields */
+ eStatus::_ m_status;
+ GJK::sSimplex m_result;
+ btVector3 m_normal;
+ btScalar m_depth;
+ sSV m_sv_store[EPA_MAX_VERTICES];
+ sFace m_fc_store[EPA_MAX_FACES];
+ U m_nextsv;
+ sList m_hull;
+ sList m_stock;
+ /* Methods */
+ EPA()
+ {
+ Initialize();
+ }
+ static inline void bind(sFace* fa, U ea, sFace* fb, U eb)
+ {
+ fa->e[ea] = (U1)eb;
+ fa->f[ea] = fb;
+ fb->e[eb] = (U1)ea;
+ fb->f[eb] = fa;
+ }
+ static inline void append(sList& list, sFace* face)
+ {
+ face->l[0] = 0;
+ face->l[1] = list.root;
+ if (list.root) list.root->l[0] = face;
+ list.root = face;
+ ++list.count;
+ }
+ static inline void remove(sList& list, sFace* face)
+ {
+ if (face->l[1]) face->l[1]->l[0] = face->l[0];
+ if (face->l[0]) face->l[0]->l[1] = face->l[1];
+ if (face == list.root) list.root = face->l[1];
+ --list.count;
+ }
- static inline void bind(sFace* fa,U ea,sFace* fb,U eb)
- {
- fa->e[ea]=(U1)eb;fa->f[ea]=fb;
- fb->e[eb]=(U1)ea;fb->f[eb]=fa;
- }
- static inline void append(sList& list,sFace* face)
+ void Initialize()
+ {
+ m_status = eStatus::Failed;
+ m_normal = btVector3(0, 0, 0);
+ m_depth = 0;
+ m_nextsv = 0;
+ for (U i = 0; i < EPA_MAX_FACES; ++i)
+ {
+ append(m_stock, &m_fc_store[EPA_MAX_FACES - i - 1]);
+ }
+ }
+ eStatus::_ Evaluate(GJK& gjk, const btVector3& guess)
+ {
+ GJK::sSimplex& simplex = *gjk.m_simplex;
+ if ((simplex.rank > 1) && gjk.EncloseOrigin())
+ {
+ /* Clean up */
+ while (m_hull.root)
{
- face->l[0] = 0;
- face->l[1] = list.root;
- if(list.root) list.root->l[0]=face;
- list.root = face;
- ++list.count;
+ sFace* f = m_hull.root;
+ remove(m_hull, f);
+ append(m_stock, f);
}
- static inline void remove(sList& list,sFace* face)
+ m_status = eStatus::Valid;
+ m_nextsv = 0;
+ /* Orient simplex */
+ if (gjk.det(simplex.c[0]->w - simplex.c[3]->w,
+ simplex.c[1]->w - simplex.c[3]->w,
+ simplex.c[2]->w - simplex.c[3]->w) < 0)
{
- if(face->l[1]) face->l[1]->l[0]=face->l[0];
- if(face->l[0]) face->l[0]->l[1]=face->l[1];
- if(face==list.root) list.root=face->l[1];
- --list.count;
+ btSwap(simplex.c[0], simplex.c[1]);
+ btSwap(simplex.p[0], simplex.p[1]);
}
-
-
- void Initialize()
+ /* Build initial hull */
+ sFace* tetra[] = {newface(simplex.c[0], simplex.c[1], simplex.c[2], true),
+ newface(simplex.c[1], simplex.c[0], simplex.c[3], true),
+ newface(simplex.c[2], simplex.c[1], simplex.c[3], true),
+ newface(simplex.c[0], simplex.c[2], simplex.c[3], true)};
+ if (m_hull.count == 4)
{
- m_status = eStatus::Failed;
- m_normal = btVector3(0,0,0);
- m_depth = 0;
- m_nextsv = 0;
- for(U i=0;i<EPA_MAX_FACES;++i)
+ sFace* best = findbest();
+ sFace outer = *best;
+ U pass = 0;
+ U iterations = 0;
+ bind(tetra[0], 0, tetra[1], 0);
+ bind(tetra[0], 1, tetra[2], 0);
+ bind(tetra[0], 2, tetra[3], 0);
+ bind(tetra[1], 1, tetra[3], 2);
+ bind(tetra[1], 2, tetra[2], 1);
+ bind(tetra[2], 2, tetra[3], 1);
+ m_status = eStatus::Valid;
+ for (; iterations < EPA_MAX_ITERATIONS; ++iterations)
{
- append(m_stock,&m_fc_store[EPA_MAX_FACES-i-1]);
- }
- }
- eStatus::_ Evaluate(GJK& gjk,const btVector3& guess)
- {
- GJK::sSimplex& simplex=*gjk.m_simplex;
- if((simplex.rank>1)&&gjk.EncloseOrigin())
- {
-
- /* Clean up */
- while(m_hull.root)
- {
- sFace* f = m_hull.root;
- remove(m_hull,f);
- append(m_stock,f);
- }
- m_status = eStatus::Valid;
- m_nextsv = 0;
- /* Orient simplex */
- if(gjk.det( simplex.c[0]->w-simplex.c[3]->w,
- simplex.c[1]->w-simplex.c[3]->w,
- simplex.c[2]->w-simplex.c[3]->w)<0)
- {
- btSwap(simplex.c[0],simplex.c[1]);
- btSwap(simplex.p[0],simplex.p[1]);
- }
- /* Build initial hull */
- sFace* tetra[]={newface(simplex.c[0],simplex.c[1],simplex.c[2],true),
- newface(simplex.c[1],simplex.c[0],simplex.c[3],true),
- newface(simplex.c[2],simplex.c[1],simplex.c[3],true),
- newface(simplex.c[0],simplex.c[2],simplex.c[3],true)};
- if(m_hull.count==4)
+ if (m_nextsv < EPA_MAX_VERTICES)
{
- sFace* best=findbest();
- sFace outer=*best;
- U pass=0;
- U iterations=0;
- bind(tetra[0],0,tetra[1],0);
- bind(tetra[0],1,tetra[2],0);
- bind(tetra[0],2,tetra[3],0);
- bind(tetra[1],1,tetra[3],2);
- bind(tetra[1],2,tetra[2],1);
- bind(tetra[2],2,tetra[3],1);
- m_status=eStatus::Valid;
- for(;iterations<EPA_MAX_ITERATIONS;++iterations)
+ sHorizon horizon;
+ sSV* w = &m_sv_store[m_nextsv++];
+ bool valid = true;
+ best->pass = (U1)(++pass);
+ gjk.getsupport(best->n, *w);
+ const btScalar wdist = btDot(best->n, w->w) - best->d;
+ if (wdist > EPA_ACCURACY)
{
- if(m_nextsv<EPA_MAX_VERTICES)
- {
- sHorizon horizon;
- sSV* w=&m_sv_store[m_nextsv++];
- bool valid=true;
- best->pass = (U1)(++pass);
- gjk.getsupport(best->n,*w);
- const btScalar wdist=btDot(best->n,w->w)-best->d;
- if(wdist>EPA_ACCURACY)
- {
- for(U j=0;(j<3)&&valid;++j)
- {
- valid&=expand( pass,w,
- best->f[j],best->e[j],
- horizon);
- }
- if(valid&&(horizon.nf>=3))
- {
- bind(horizon.cf,1,horizon.ff,2);
- remove(m_hull,best);
- append(m_stock,best);
- best=findbest();
- outer=*best;
- } else { m_status=eStatus::InvalidHull;break; }
- } else { m_status=eStatus::AccuraryReached;break; }
- } else { m_status=eStatus::OutOfVertices;break; }
+ for (U j = 0; (j < 3) && valid; ++j)
+ {
+ valid &= expand(pass, w,
+ best->f[j], best->e[j],
+ horizon);
+ }
+ if (valid && (horizon.nf >= 3))
+ {
+ bind(horizon.cf, 1, horizon.ff, 2);
+ remove(m_hull, best);
+ append(m_stock, best);
+ best = findbest();
+ outer = *best;
+ }
+ else
+ {
+ m_status = eStatus::InvalidHull;
+ break;
+ }
+ }
+ else
+ {
+ m_status = eStatus::AccuraryReached;
+ break;
}
- const btVector3 projection=outer.n*outer.d;
- m_normal = outer.n;
- m_depth = outer.d;
- m_result.rank = 3;
- m_result.c[0] = outer.c[0];
- m_result.c[1] = outer.c[1];
- m_result.c[2] = outer.c[2];
- m_result.p[0] = btCross( outer.c[1]->w-projection,
- outer.c[2]->w-projection).length();
- m_result.p[1] = btCross( outer.c[2]->w-projection,
- outer.c[0]->w-projection).length();
- m_result.p[2] = btCross( outer.c[0]->w-projection,
- outer.c[1]->w-projection).length();
- const btScalar sum=m_result.p[0]+m_result.p[1]+m_result.p[2];
- m_result.p[0] /= sum;
- m_result.p[1] /= sum;
- m_result.p[2] /= sum;
- return(m_status);
- }
- }
- /* Fallback */
- m_status = eStatus::FallBack;
- m_normal = -guess;
- const btScalar nl=m_normal.length();
- if(nl>0)
- m_normal = m_normal/nl;
- else
- m_normal = btVector3(1,0,0);
- m_depth = 0;
- m_result.rank=1;
- m_result.c[0]=simplex.c[0];
- m_result.p[0]=1;
- return(m_status);
- }
- bool getedgedist(sFace* face, sSV* a, sSV* b, btScalar& dist)
- {
- const btVector3 ba = b->w - a->w;
- const btVector3 n_ab = btCross(ba, face->n); // Outward facing edge normal direction, on triangle plane
- const btScalar a_dot_nab = btDot(a->w, n_ab); // Only care about the sign to determine inside/outside, so not normalization required
-
- if(a_dot_nab < 0)
- {
- // Outside of edge a->b
-
- const btScalar ba_l2 = ba.length2();
- const btScalar a_dot_ba = btDot(a->w, ba);
- const btScalar b_dot_ba = btDot(b->w, ba);
-
- if(a_dot_ba > 0)
- {
- // Pick distance vertex a
- dist = a->w.length();
- }
- else if(b_dot_ba < 0)
- {
- // Pick distance vertex b
- dist = b->w.length();
}
else
{
- // Pick distance to edge a->b
- const btScalar a_dot_b = btDot(a->w, b->w);
- dist = btSqrt(btMax((a->w.length2() * b->w.length2() - a_dot_b * a_dot_b) / ba_l2, (btScalar)0));
+ m_status = eStatus::OutOfVertices;
+ break;
}
-
- return true;
}
+ const btVector3 projection = outer.n * outer.d;
+ m_normal = outer.n;
+ m_depth = outer.d;
+ m_result.rank = 3;
+ m_result.c[0] = outer.c[0];
+ m_result.c[1] = outer.c[1];
+ m_result.c[2] = outer.c[2];
+ m_result.p[0] = btCross(outer.c[1]->w - projection,
+ outer.c[2]->w - projection)
+ .length();
+ m_result.p[1] = btCross(outer.c[2]->w - projection,
+ outer.c[0]->w - projection)
+ .length();
+ m_result.p[2] = btCross(outer.c[0]->w - projection,
+ outer.c[1]->w - projection)
+ .length();
+ const btScalar sum = m_result.p[0] + m_result.p[1] + m_result.p[2];
+ m_result.p[0] /= sum;
+ m_result.p[1] /= sum;
+ m_result.p[2] /= sum;
+ return (m_status);
+ }
+ }
+ /* Fallback */
+ m_status = eStatus::FallBack;
+ m_normal = -guess;
+ const btScalar nl = m_normal.length();
+ if (nl > 0)
+ m_normal = m_normal / nl;
+ else
+ m_normal = btVector3(1, 0, 0);
+ m_depth = 0;
+ m_result.rank = 1;
+ m_result.c[0] = simplex.c[0];
+ m_result.p[0] = 1;
+ return (m_status);
+ }
+ bool getedgedist(sFace* face, sSV* a, sSV* b, btScalar& dist)
+ {
+ const btVector3 ba = b->w - a->w;
+ const btVector3 n_ab = btCross(ba, face->n); // Outward facing edge normal direction, on triangle plane
+ const btScalar a_dot_nab = btDot(a->w, n_ab); // Only care about the sign to determine inside/outside, so not normalization required
- return false;
+ if (a_dot_nab < 0)
+ {
+ // Outside of edge a->b
+
+ const btScalar ba_l2 = ba.length2();
+ const btScalar a_dot_ba = btDot(a->w, ba);
+ const btScalar b_dot_ba = btDot(b->w, ba);
+
+ if (a_dot_ba > 0)
+ {
+ // Pick distance vertex a
+ dist = a->w.length();
}
- sFace* newface(sSV* a,sSV* b,sSV* c,bool forced)
+ else if (b_dot_ba < 0)
{
- if(m_stock.root)
- {
- sFace* face=m_stock.root;
- remove(m_stock,face);
- append(m_hull,face);
- face->pass = 0;
- face->c[0] = a;
- face->c[1] = b;
- face->c[2] = c;
- face->n = btCross(b->w-a->w,c->w-a->w);
- const btScalar l=face->n.length();
- const bool v=l>EPA_ACCURACY;
+ // Pick distance vertex b
+ dist = b->w.length();
+ }
+ else
+ {
+ // Pick distance to edge a->b
+ const btScalar a_dot_b = btDot(a->w, b->w);
+ dist = btSqrt(btMax((a->w.length2() * b->w.length2() - a_dot_b * a_dot_b) / ba_l2, (btScalar)0));
+ }
- if(v)
- {
- if(!(getedgedist(face, a, b, face->d) ||
- getedgedist(face, b, c, face->d) ||
- getedgedist(face, c, a, face->d)))
- {
- // Origin projects to the interior of the triangle
- // Use distance to triangle plane
- face->d = btDot(a->w, face->n) / l;
- }
+ return true;
+ }
- face->n /= l;
- if(forced || (face->d >= -EPA_PLANE_EPS))
- {
- return face;
- }
- else
- m_status=eStatus::NonConvex;
- }
- else
- m_status=eStatus::Degenerated;
+ return false;
+ }
+ sFace* newface(sSV* a, sSV* b, sSV* c, bool forced)
+ {
+ if (m_stock.root)
+ {
+ sFace* face = m_stock.root;
+ remove(m_stock, face);
+ append(m_hull, face);
+ face->pass = 0;
+ face->c[0] = a;
+ face->c[1] = b;
+ face->c[2] = c;
+ face->n = btCross(b->w - a->w, c->w - a->w);
+ const btScalar l = face->n.length();
+ const bool v = l > EPA_ACCURACY;
- remove(m_hull, face);
- append(m_stock, face);
- return 0;
+ if (v)
+ {
+ if (!(getedgedist(face, a, b, face->d) ||
+ getedgedist(face, b, c, face->d) ||
+ getedgedist(face, c, a, face->d)))
+ {
+ // Origin projects to the interior of the triangle
+ // Use distance to triangle plane
+ face->d = btDot(a->w, face->n) / l;
+ }
+ face->n /= l;
+ if (forced || (face->d >= -EPA_PLANE_EPS))
+ {
+ return face;
}
- m_status = m_stock.root ? eStatus::OutOfVertices : eStatus::OutOfFaces;
- return 0;
+ else
+ m_status = eStatus::NonConvex;
+ }
+ else
+ m_status = eStatus::Degenerated;
+
+ remove(m_hull, face);
+ append(m_stock, face);
+ return 0;
+ }
+ m_status = m_stock.root ? eStatus::OutOfVertices : eStatus::OutOfFaces;
+ return 0;
+ }
+ sFace* findbest()
+ {
+ sFace* minf = m_hull.root;
+ btScalar mind = minf->d * minf->d;
+ for (sFace* f = minf->l[1]; f; f = f->l[1])
+ {
+ const btScalar sqd = f->d * f->d;
+ if (sqd < mind)
+ {
+ minf = f;
+ mind = sqd;
}
- sFace* findbest()
+ }
+ return (minf);
+ }
+ bool expand(U pass, sSV* w, sFace* f, U e, sHorizon& horizon)
+ {
+ static const U i1m3[] = {1, 2, 0};
+ static const U i2m3[] = {2, 0, 1};
+ if (f->pass != pass)
+ {
+ const U e1 = i1m3[e];
+ if ((btDot(f->n, w->w) - f->d) < -EPA_PLANE_EPS)
{
- sFace* minf=m_hull.root;
- btScalar mind=minf->d*minf->d;
- for(sFace* f=minf->l[1];f;f=f->l[1])
+ sFace* nf = newface(f->c[e1], f->c[e], w, false);
+ if (nf)
{
- const btScalar sqd=f->d*f->d;
- if(sqd<mind)
- {
- minf=f;
- mind=sqd;
- }
+ bind(nf, 0, f, e);
+ if (horizon.cf)
+ bind(horizon.cf, 1, nf, 2);
+ else
+ horizon.ff = nf;
+ horizon.cf = nf;
+ ++horizon.nf;
+ return (true);
}
- return(minf);
}
- bool expand(U pass,sSV* w,sFace* f,U e,sHorizon& horizon)
+ else
{
- static const U i1m3[]={1,2,0};
- static const U i2m3[]={2,0,1};
- if(f->pass!=pass)
+ const U e2 = i2m3[e];
+ f->pass = (U1)pass;
+ if (expand(pass, w, f->f[e1], f->e[e1], horizon) &&
+ expand(pass, w, f->f[e2], f->e[e2], horizon))
{
- const U e1=i1m3[e];
- if((btDot(f->n,w->w)-f->d)<-EPA_PLANE_EPS)
- {
- sFace* nf=newface(f->c[e1],f->c[e],w,false);
- if(nf)
- {
- bind(nf,0,f,e);
- if(horizon.cf) bind(horizon.cf,1,nf,2); else horizon.ff=nf;
- horizon.cf=nf;
- ++horizon.nf;
- return(true);
- }
- }
- else
- {
- const U e2=i2m3[e];
- f->pass = (U1)pass;
- if( expand(pass,w,f->f[e1],f->e[e1],horizon)&&
- expand(pass,w,f->f[e2],f->e[e2],horizon))
- {
- remove(m_hull,f);
- append(m_stock,f);
- return(true);
- }
- }
+ remove(m_hull, f);
+ append(m_stock, f);
+ return (true);
}
- return(false);
}
-
- };
-
- //
- static void Initialize( const btConvexShape* shape0,const btTransform& wtrs0,
- const btConvexShape* shape1,const btTransform& wtrs1,
- btGjkEpaSolver2::sResults& results,
- tShape& shape,
- bool withmargins)
- {
- /* Results */
- results.witnesses[0] =
- results.witnesses[1] = btVector3(0,0,0);
- results.status = btGjkEpaSolver2::sResults::Separated;
- /* Shape */
- shape.m_shapes[0] = shape0;
- shape.m_shapes[1] = shape1;
- shape.m_toshape1 = wtrs1.getBasis().transposeTimes(wtrs0.getBasis());
- shape.m_toshape0 = wtrs0.inverseTimes(wtrs1);
- shape.EnableMargin(withmargins);
+ }
+ return (false);
}
+};
+//
+static void Initialize(const btConvexShape* shape0, const btTransform& wtrs0,
+ const btConvexShape* shape1, const btTransform& wtrs1,
+ btGjkEpaSolver2::sResults& results,
+ tShape& shape,
+ bool withmargins)
+{
+ /* Results */
+ results.witnesses[0] =
+ results.witnesses[1] = btVector3(0, 0, 0);
+ results.status = btGjkEpaSolver2::sResults::Separated;
+ /* Shape */
+ shape.m_shapes[0] = shape0;
+ shape.m_shapes[1] = shape1;
+ shape.m_toshape1 = wtrs1.getBasis().transposeTimes(wtrs0.getBasis());
+ shape.m_toshape0 = wtrs0.inverseTimes(wtrs1);
+ shape.EnableMargin(withmargins);
}
+} // namespace gjkepa2_impl
+
//
// Api
//
-using namespace gjkepa2_impl;
+using namespace gjkepa2_impl;
//
-int btGjkEpaSolver2::StackSizeRequirement()
+int btGjkEpaSolver2::StackSizeRequirement()
{
- return(sizeof(GJK)+sizeof(EPA));
+ return (sizeof(GJK) + sizeof(EPA));
}
//
-bool btGjkEpaSolver2::Distance( const btConvexShape* shape0,
- const btTransform& wtrs0,
- const btConvexShape* shape1,
- const btTransform& wtrs1,
- const btVector3& guess,
- sResults& results)
+bool btGjkEpaSolver2::Distance(const btConvexShape* shape0,
+ const btTransform& wtrs0,
+ const btConvexShape* shape1,
+ const btTransform& wtrs1,
+ const btVector3& guess,
+ sResults& results)
{
- tShape shape;
- Initialize(shape0,wtrs0,shape1,wtrs1,results,shape,false);
- GJK gjk;
- GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,guess);
- if(gjk_status==GJK::eStatus::Valid)
+ tShape shape;
+ Initialize(shape0, wtrs0, shape1, wtrs1, results, shape, false);
+ GJK gjk;
+ GJK::eStatus::_ gjk_status = gjk.Evaluate(shape, guess);
+ if (gjk_status == GJK::eStatus::Valid)
{
- btVector3 w0=btVector3(0,0,0);
- btVector3 w1=btVector3(0,0,0);
- for(U i=0;i<gjk.m_simplex->rank;++i)
+ btVector3 w0 = btVector3(0, 0, 0);
+ btVector3 w1 = btVector3(0, 0, 0);
+ for (U i = 0; i < gjk.m_simplex->rank; ++i)
{
- const btScalar p=gjk.m_simplex->p[i];
- w0+=shape.Support( gjk.m_simplex->c[i]->d,0)*p;
- w1+=shape.Support(-gjk.m_simplex->c[i]->d,1)*p;
+ const btScalar p = gjk.m_simplex->p[i];
+ w0 += shape.Support(gjk.m_simplex->c[i]->d, 0) * p;
+ w1 += shape.Support(-gjk.m_simplex->c[i]->d, 1) * p;
}
- results.witnesses[0] = wtrs0*w0;
- results.witnesses[1] = wtrs0*w1;
- results.normal = w0-w1;
- results.distance = results.normal.length();
- results.normal /= results.distance>GJK_MIN_DISTANCE?results.distance:1;
- return(true);
+ results.witnesses[0] = wtrs0 * w0;
+ results.witnesses[1] = wtrs0 * w1;
+ results.normal = w0 - w1;
+ results.distance = results.normal.length();
+ results.normal /= results.distance > GJK_MIN_DISTANCE ? results.distance : 1;
+ return (true);
}
else
{
- results.status = gjk_status==GJK::eStatus::Inside?
- sResults::Penetrating :
- sResults::GJK_Failed ;
- return(false);
+ results.status = gjk_status == GJK::eStatus::Inside ? sResults::Penetrating : sResults::GJK_Failed;
+ return (false);
}
}
//
-bool btGjkEpaSolver2::Penetration( const btConvexShape* shape0,
- const btTransform& wtrs0,
- const btConvexShape* shape1,
- const btTransform& wtrs1,
- const btVector3& guess,
- sResults& results,
- bool usemargins)
+bool btGjkEpaSolver2::Penetration(const btConvexShape* shape0,
+ const btTransform& wtrs0,
+ const btConvexShape* shape1,
+ const btTransform& wtrs1,
+ const btVector3& guess,
+ sResults& results,
+ bool usemargins)
{
- tShape shape;
- Initialize(shape0,wtrs0,shape1,wtrs1,results,shape,usemargins);
- GJK gjk;
- GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,-guess);
- switch(gjk_status)
+ tShape shape;
+ Initialize(shape0, wtrs0, shape1, wtrs1, results, shape, usemargins);
+ GJK gjk;
+ GJK::eStatus::_ gjk_status = gjk.Evaluate(shape, -guess);
+ switch (gjk_status)
{
- case GJK::eStatus::Inside:
+ case GJK::eStatus::Inside:
{
- EPA epa;
- EPA::eStatus::_ epa_status=epa.Evaluate(gjk,-guess);
- if(epa_status!=EPA::eStatus::Failed)
+ EPA epa;
+ EPA::eStatus::_ epa_status = epa.Evaluate(gjk, -guess);
+ if (epa_status != EPA::eStatus::Failed)
{
- btVector3 w0=btVector3(0,0,0);
- for(U i=0;i<epa.m_result.rank;++i)
+ btVector3 w0 = btVector3(0, 0, 0);
+ for (U i = 0; i < epa.m_result.rank; ++i)
{
- w0+=shape.Support(epa.m_result.c[i]->d,0)*epa.m_result.p[i];
+ w0 += shape.Support(epa.m_result.c[i]->d, 0) * epa.m_result.p[i];
}
- results.status = sResults::Penetrating;
- results.witnesses[0] = wtrs0*w0;
- results.witnesses[1] = wtrs0*(w0-epa.m_normal*epa.m_depth);
- results.normal = -epa.m_normal;
- results.distance = -epa.m_depth;
- return(true);
- } else results.status=sResults::EPA_Failed;
+ results.status = sResults::Penetrating;
+ results.witnesses[0] = wtrs0 * w0;
+ results.witnesses[1] = wtrs0 * (w0 - epa.m_normal * epa.m_depth);
+ results.normal = -epa.m_normal;
+ results.distance = -epa.m_depth;
+ return (true);
+ }
+ else
+ results.status = sResults::EPA_Failed;
}
break;
- case GJK::eStatus::Failed:
- results.status=sResults::GJK_Failed;
- break;
+ case GJK::eStatus::Failed:
+ results.status = sResults::GJK_Failed;
+ break;
default:
- {
- }
+ {
+ }
}
- return(false);
+ return (false);
}
#ifndef __SPU__
//
-btScalar btGjkEpaSolver2::SignedDistance(const btVector3& position,
- btScalar margin,
- const btConvexShape* shape0,
- const btTransform& wtrs0,
- sResults& results)
+btScalar btGjkEpaSolver2::SignedDistance(const btVector3& position,
+ btScalar margin,
+ const btConvexShape* shape0,
+ const btTransform& wtrs0,
+ sResults& results)
{
- tShape shape;
- btSphereShape shape1(margin);
- btTransform wtrs1(btQuaternion(0,0,0,1),position);
- Initialize(shape0,wtrs0,&shape1,wtrs1,results,shape,false);
- GJK gjk;
- GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,btVector3(1,1,1));
- if(gjk_status==GJK::eStatus::Valid)
+ tShape shape;
+ btSphereShape shape1(margin);
+ btTransform wtrs1(btQuaternion(0, 0, 0, 1), position);
+ Initialize(shape0, wtrs0, &shape1, wtrs1, results, shape, false);
+ GJK gjk;
+ GJK::eStatus::_ gjk_status = gjk.Evaluate(shape, btVector3(1, 1, 1));
+ if (gjk_status == GJK::eStatus::Valid)
{
- btVector3 w0=btVector3(0,0,0);
- btVector3 w1=btVector3(0,0,0);
- for(U i=0;i<gjk.m_simplex->rank;++i)
+ btVector3 w0 = btVector3(0, 0, 0);
+ btVector3 w1 = btVector3(0, 0, 0);
+ for (U i = 0; i < gjk.m_simplex->rank; ++i)
{
- const btScalar p=gjk.m_simplex->p[i];
- w0+=shape.Support( gjk.m_simplex->c[i]->d,0)*p;
- w1+=shape.Support(-gjk.m_simplex->c[i]->d,1)*p;
+ const btScalar p = gjk.m_simplex->p[i];
+ w0 += shape.Support(gjk.m_simplex->c[i]->d, 0) * p;
+ w1 += shape.Support(-gjk.m_simplex->c[i]->d, 1) * p;
}
- results.witnesses[0] = wtrs0*w0;
- results.witnesses[1] = wtrs0*w1;
- const btVector3 delta= results.witnesses[1]-
- results.witnesses[0];
- const btScalar margin= shape0->getMarginNonVirtual()+
- shape1.getMarginNonVirtual();
- const btScalar length= delta.length();
- results.normal = delta/length;
- results.witnesses[0] += results.normal*margin;
- return(length-margin);
+ results.witnesses[0] = wtrs0 * w0;
+ results.witnesses[1] = wtrs0 * w1;
+ const btVector3 delta = results.witnesses[1] -
+ results.witnesses[0];
+ const btScalar margin = shape0->getMarginNonVirtual() +
+ shape1.getMarginNonVirtual();
+ const btScalar length = delta.length();
+ results.normal = delta / length;
+ results.witnesses[0] += results.normal * margin;
+ return (length - margin);
}
else
{
- if(gjk_status==GJK::eStatus::Inside)
+ if (gjk_status == GJK::eStatus::Inside)
{
- if(Penetration(shape0,wtrs0,&shape1,wtrs1,gjk.m_ray,results))
+ if (Penetration(shape0, wtrs0, &shape1, wtrs1, gjk.m_ray, results))
{
- const btVector3 delta= results.witnesses[0]-
- results.witnesses[1];
- const btScalar length= delta.length();
+ const btVector3 delta = results.witnesses[0] -
+ results.witnesses[1];
+ const btScalar length = delta.length();
if (length >= SIMD_EPSILON)
- results.normal = delta/length;
- return(-length);
+ results.normal = delta / length;
+ return (-length);
}
- }
+ }
}
- return(SIMD_INFINITY);
+ return (SIMD_INFINITY);
}
//
-bool btGjkEpaSolver2::SignedDistance(const btConvexShape* shape0,
- const btTransform& wtrs0,
- const btConvexShape* shape1,
- const btTransform& wtrs1,
- const btVector3& guess,
- sResults& results)
+bool btGjkEpaSolver2::SignedDistance(const btConvexShape* shape0,
+ const btTransform& wtrs0,
+ const btConvexShape* shape1,
+ const btTransform& wtrs1,
+ const btVector3& guess,
+ sResults& results)
{
- if(!Distance(shape0,wtrs0,shape1,wtrs1,guess,results))
- return(Penetration(shape0,wtrs0,shape1,wtrs1,guess,results,false));
+ if (!Distance(shape0, wtrs0, shape1, wtrs1, guess, results))
+ return (Penetration(shape0, wtrs0, shape1, wtrs1, guess, results, false));
else
- return(true);
+ return (true);
}
-#endif //__SPU__
+#endif //__SPU__
-/* Symbols cleanup */
+/* Symbols cleanup */
#undef GJK_MAX_ITERATIONS
#undef GJK_ACCURACY
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h
index ac501d5ecf..893daea3f5 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h
@@ -28,48 +28,46 @@ GJK-EPA collision solver by Nathanael Presson, 2008
#include "BulletCollision/CollisionShapes/btConvexShape.h"
///btGjkEpaSolver contributed under zlib by Nathanael Presson
-struct btGjkEpaSolver2
+struct btGjkEpaSolver2
{
-struct sResults
+ struct sResults
{
- enum eStatus
+ enum eStatus
{
- Separated, /* Shapes doesnt penetrate */
- Penetrating, /* Shapes are penetrating */
- GJK_Failed, /* GJK phase fail, no big issue, shapes are probably just 'touching' */
- EPA_Failed /* EPA phase fail, bigger problem, need to save parameters, and debug */
- } status;
- btVector3 witnesses[2];
- btVector3 normal;
- btScalar distance;
+ Separated, /* Shapes doesnt penetrate */
+ Penetrating, /* Shapes are penetrating */
+ GJK_Failed, /* GJK phase fail, no big issue, shapes are probably just 'touching' */
+ EPA_Failed /* EPA phase fail, bigger problem, need to save parameters, and debug */
+ } status;
+ btVector3 witnesses[2];
+ btVector3 normal;
+ btScalar distance;
};
-static int StackSizeRequirement();
+ static int StackSizeRequirement();
-static bool Distance( const btConvexShape* shape0,const btTransform& wtrs0,
- const btConvexShape* shape1,const btTransform& wtrs1,
- const btVector3& guess,
- sResults& results);
+ static bool Distance(const btConvexShape* shape0, const btTransform& wtrs0,
+ const btConvexShape* shape1, const btTransform& wtrs1,
+ const btVector3& guess,
+ sResults& results);
-static bool Penetration(const btConvexShape* shape0,const btTransform& wtrs0,
- const btConvexShape* shape1,const btTransform& wtrs1,
+ static bool Penetration(const btConvexShape* shape0, const btTransform& wtrs0,
+ const btConvexShape* shape1, const btTransform& wtrs1,
const btVector3& guess,
sResults& results,
- bool usemargins=true);
+ bool usemargins = true);
#ifndef __SPU__
-static btScalar SignedDistance( const btVector3& position,
- btScalar margin,
- const btConvexShape* shape,
- const btTransform& wtrs,
- sResults& results);
-
-static bool SignedDistance( const btConvexShape* shape0,const btTransform& wtrs0,
- const btConvexShape* shape1,const btTransform& wtrs1,
- const btVector3& guess,
- sResults& results);
-#endif //__SPU__
+ static btScalar SignedDistance(const btVector3& position,
+ btScalar margin,
+ const btConvexShape* shape,
+ const btTransform& wtrs,
+ sResults& results);
+ static bool SignedDistance(const btConvexShape* shape0, const btTransform& wtrs0,
+ const btConvexShape* shape1, const btTransform& wtrs1,
+ const btVector3& guess,
+ sResults& results);
+#endif //__SPU__
};
-#endif //BT_GJK_EPA2_H
-
+#endif //BT_GJK_EPA2_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa3.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa3.h
index ce1f24bc50..6fedbbb3e5 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa3.h
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa3.h
@@ -29,915 +29,946 @@ Improvements and refactoring by Erwin Coumans, 2008-2014
#include "LinearMath/btTransform.h"
#include "btGjkCollisionDescription.h"
-
-
-struct btGjkEpaSolver3
+struct btGjkEpaSolver3
{
-struct sResults
+ struct sResults
{
- enum eStatus
+ enum eStatus
{
- Separated, /* Shapes doesnt penetrate */
- Penetrating, /* Shapes are penetrating */
- GJK_Failed, /* GJK phase fail, no big issue, shapes are probably just 'touching' */
- EPA_Failed /* EPA phase fail, bigger problem, need to save parameters, and debug */
- } status;
- btVector3 witnesses[2];
- btVector3 normal;
- btScalar distance;
+ Separated, /* Shapes doesnt penetrate */
+ Penetrating, /* Shapes are penetrating */
+ GJK_Failed, /* GJK phase fail, no big issue, shapes are probably just 'touching' */
+ EPA_Failed /* EPA phase fail, bigger problem, need to save parameters, and debug */
+ } status;
+ btVector3 witnesses[2];
+ btVector3 normal;
+ btScalar distance;
};
-
-
};
-
-
-#if defined(DEBUG) || defined (_DEBUG)
-#include <stdio.h> //for debug printf
+#if defined(DEBUG) || defined(_DEBUG)
+#include <stdio.h> //for debug printf
#ifdef __SPU__
#include <spu_printf.h>
#define printf spu_printf
-#endif //__SPU__
+#endif //__SPU__
#endif
+// Config
-
- // Config
-
- /* GJK */
-#define GJK_MAX_ITERATIONS 128
-#define GJK_ACCURARY ((btScalar)0.0001)
-#define GJK_MIN_DISTANCE ((btScalar)0.0001)
-#define GJK_DUPLICATED_EPS ((btScalar)0.0001)
-#define GJK_SIMPLEX2_EPS ((btScalar)0.0)
-#define GJK_SIMPLEX3_EPS ((btScalar)0.0)
-#define GJK_SIMPLEX4_EPS ((btScalar)0.0)
-
- /* EPA */
-#define EPA_MAX_VERTICES 64
-#define EPA_MAX_FACES (EPA_MAX_VERTICES*2)
-#define EPA_MAX_ITERATIONS 255
-#define EPA_ACCURACY ((btScalar)0.0001)
-#define EPA_FALLBACK (10*EPA_ACCURACY)
-#define EPA_PLANE_EPS ((btScalar)0.00001)
-#define EPA_INSIDE_EPS ((btScalar)0.01)
-
-
- // Shorthands
- typedef unsigned int U;
- typedef unsigned char U1;
-
- // MinkowskiDiff
- template <typename btConvexTemplate>
- struct MinkowskiDiff
- {
- const btConvexTemplate* m_convexAPtr;
- const btConvexTemplate* m_convexBPtr;
-
- btMatrix3x3 m_toshape1;
- btTransform m_toshape0;
-
- bool m_enableMargin;
-
-
- MinkowskiDiff(const btConvexTemplate& a, const btConvexTemplate& b)
- :m_convexAPtr(&a),
- m_convexBPtr(&b)
- {
- }
-
- void EnableMargin(bool enable)
- {
- m_enableMargin = enable;
- }
- inline btVector3 Support0(const btVector3& d) const
- {
- return m_convexAPtr->getLocalSupportWithMargin(d);
- }
- inline btVector3 Support1(const btVector3& d) const
- {
- return m_toshape0*m_convexBPtr->getLocalSupportWithMargin(m_toshape1*d);
- }
-
-
- inline btVector3 Support(const btVector3& d) const
- {
- return(Support0(d)-Support1(-d));
- }
- btVector3 Support(const btVector3& d,U index) const
- {
- if(index)
- return(Support1(d));
- else
- return(Support0(d));
- }
- };
-
-enum eGjkStatus
+/* GJK */
+#define GJK_MAX_ITERATIONS 128
+#define GJK_ACCURARY ((btScalar)0.0001)
+#define GJK_MIN_DISTANCE ((btScalar)0.0001)
+#define GJK_DUPLICATED_EPS ((btScalar)0.0001)
+#define GJK_SIMPLEX2_EPS ((btScalar)0.0)
+#define GJK_SIMPLEX3_EPS ((btScalar)0.0)
+#define GJK_SIMPLEX4_EPS ((btScalar)0.0)
+
+/* EPA */
+#define EPA_MAX_VERTICES 64
+#define EPA_MAX_FACES (EPA_MAX_VERTICES * 2)
+#define EPA_MAX_ITERATIONS 255
+#define EPA_ACCURACY ((btScalar)0.0001)
+#define EPA_FALLBACK (10 * EPA_ACCURACY)
+#define EPA_PLANE_EPS ((btScalar)0.00001)
+#define EPA_INSIDE_EPS ((btScalar)0.01)
+
+// Shorthands
+typedef unsigned int U;
+typedef unsigned char U1;
+
+// MinkowskiDiff
+template <typename btConvexTemplate>
+struct MinkowskiDiff
{
- eGjkValid,
- eGjkInside,
- eGjkFailed
+ const btConvexTemplate* m_convexAPtr;
+ const btConvexTemplate* m_convexBPtr;
+
+ btMatrix3x3 m_toshape1;
+ btTransform m_toshape0;
+
+ bool m_enableMargin;
+
+ MinkowskiDiff(const btConvexTemplate& a, const btConvexTemplate& b)
+ : m_convexAPtr(&a),
+ m_convexBPtr(&b)
+ {
+ }
+
+ void EnableMargin(bool enable)
+ {
+ m_enableMargin = enable;
+ }
+ inline btVector3 Support0(const btVector3& d) const
+ {
+ return m_convexAPtr->getLocalSupportWithMargin(d);
+ }
+ inline btVector3 Support1(const btVector3& d) const
+ {
+ return m_toshape0 * m_convexBPtr->getLocalSupportWithMargin(m_toshape1 * d);
+ }
+
+ inline btVector3 Support(const btVector3& d) const
+ {
+ return (Support0(d) - Support1(-d));
+ }
+ btVector3 Support(const btVector3& d, U index) const
+ {
+ if (index)
+ return (Support1(d));
+ else
+ return (Support0(d));
+ }
};
- // GJK
- template <typename btConvexTemplate>
- struct GJK
- {
- /* Types */
- struct sSV
- {
- btVector3 d,w;
- };
- struct sSimplex
- {
- sSV* c[4];
- btScalar p[4];
- U rank;
- };
-
- /* Fields */
-
- MinkowskiDiff<btConvexTemplate> m_shape;
- btVector3 m_ray;
- btScalar m_distance;
- sSimplex m_simplices[2];
- sSV m_store[4];
- sSV* m_free[4];
- U m_nfree;
- U m_current;
- sSimplex* m_simplex;
- eGjkStatus m_status;
- /* Methods */
-
- GJK(const btConvexTemplate& a, const btConvexTemplate& b)
- :m_shape(a,b)
- {
- Initialize();
- }
- void Initialize()
- {
- m_ray = btVector3(0,0,0);
- m_nfree = 0;
- m_status = eGjkFailed;
- m_current = 0;
- m_distance = 0;
- }
- eGjkStatus Evaluate(const MinkowskiDiff<btConvexTemplate>& shapearg,const btVector3& guess)
- {
- U iterations=0;
- btScalar sqdist=0;
- btScalar alpha=0;
- btVector3 lastw[4];
- U clastw=0;
- /* Initialize solver */
- m_free[0] = &m_store[0];
- m_free[1] = &m_store[1];
- m_free[2] = &m_store[2];
- m_free[3] = &m_store[3];
- m_nfree = 4;
- m_current = 0;
- m_status = eGjkValid;
- m_shape = shapearg;
- m_distance = 0;
- /* Initialize simplex */
- m_simplices[0].rank = 0;
- m_ray = guess;
- const btScalar sqrl= m_ray.length2();
- appendvertice(m_simplices[0],sqrl>0?-m_ray:btVector3(1,0,0));
- m_simplices[0].p[0] = 1;
- m_ray = m_simplices[0].c[0]->w;
- sqdist = sqrl;
- lastw[0] =
- lastw[1] =
- lastw[2] =
- lastw[3] = m_ray;
- /* Loop */
- do {
- const U next=1-m_current;
- sSimplex& cs=m_simplices[m_current];
- sSimplex& ns=m_simplices[next];
- /* Check zero */
- const btScalar rl=m_ray.length();
- if(rl<GJK_MIN_DISTANCE)
- {/* Touching or inside */
- m_status=eGjkInside;
- break;
- }
- /* Append new vertice in -'v' direction */
- appendvertice(cs,-m_ray);
- const btVector3& w=cs.c[cs.rank-1]->w;
- bool found=false;
- for(U i=0;i<4;++i)
- {
- if((w-lastw[i]).length2()<GJK_DUPLICATED_EPS)
- { found=true;break; }
- }
- if(found)
- {/* Return old simplex */
- removevertice(m_simplices[m_current]);
- break;
- }
- else
- {/* Update lastw */
- lastw[clastw=(clastw+1)&3]=w;
- }
- /* Check for termination */
- const btScalar omega=btDot(m_ray,w)/rl;
- alpha=btMax(omega,alpha);
- if(((rl-alpha)-(GJK_ACCURARY*rl))<=0)
- {/* Return old simplex */
- removevertice(m_simplices[m_current]);
- break;
- }
- /* Reduce simplex */
- btScalar weights[4];
- U mask=0;
- switch(cs.rank)
- {
- case 2: sqdist=projectorigin( cs.c[0]->w,
- cs.c[1]->w,
- weights,mask);break;
- case 3: sqdist=projectorigin( cs.c[0]->w,
- cs.c[1]->w,
- cs.c[2]->w,
- weights,mask);break;
- case 4: sqdist=projectorigin( cs.c[0]->w,
- cs.c[1]->w,
- cs.c[2]->w,
- cs.c[3]->w,
- weights,mask);break;
- }
- if(sqdist>=0)
- {/* Valid */
- ns.rank = 0;
- m_ray = btVector3(0,0,0);
- m_current = next;
- for(U i=0,ni=cs.rank;i<ni;++i)
- {
- if(mask&(1<<i))
- {
- ns.c[ns.rank] = cs.c[i];
- ns.p[ns.rank++] = weights[i];
- m_ray += cs.c[i]->w*weights[i];
- }
- else
- {
- m_free[m_nfree++] = cs.c[i];
- }
- }
- if(mask==15) m_status=eGjkInside;
- }
- else
- {/* Return old simplex */
- removevertice(m_simplices[m_current]);
- break;
- }
- m_status=((++iterations)<GJK_MAX_ITERATIONS)?m_status:eGjkFailed;
- } while(m_status==eGjkValid);
- m_simplex=&m_simplices[m_current];
- switch(m_status)
- {
- case eGjkValid: m_distance=m_ray.length();break;
- case eGjkInside: m_distance=0;break;
- default:
- {
- }
- }
- return(m_status);
- }
- bool EncloseOrigin()
- {
- switch(m_simplex->rank)
- {
- case 1:
- {
- for(U i=0;i<3;++i)
- {
- btVector3 axis=btVector3(0,0,0);
- axis[i]=1;
- appendvertice(*m_simplex, axis);
- if(EncloseOrigin()) return(true);
- removevertice(*m_simplex);
- appendvertice(*m_simplex,-axis);
- if(EncloseOrigin()) return(true);
- removevertice(*m_simplex);
- }
- }
- break;
- case 2:
- {
- const btVector3 d=m_simplex->c[1]->w-m_simplex->c[0]->w;
- for(U i=0;i<3;++i)
- {
- btVector3 axis=btVector3(0,0,0);
- axis[i]=1;
- const btVector3 p=btCross(d,axis);
- if(p.length2()>0)
- {
- appendvertice(*m_simplex, p);
- if(EncloseOrigin()) return(true);
- removevertice(*m_simplex);
- appendvertice(*m_simplex,-p);
- if(EncloseOrigin()) return(true);
- removevertice(*m_simplex);
- }
- }
- }
- break;
- case 3:
- {
- const btVector3 n=btCross(m_simplex->c[1]->w-m_simplex->c[0]->w,
- m_simplex->c[2]->w-m_simplex->c[0]->w);
- if(n.length2()>0)
- {
- appendvertice(*m_simplex,n);
- if(EncloseOrigin()) return(true);
- removevertice(*m_simplex);
- appendvertice(*m_simplex,-n);
- if(EncloseOrigin()) return(true);
- removevertice(*m_simplex);
- }
- }
- break;
- case 4:
- {
- if(btFabs(det( m_simplex->c[0]->w-m_simplex->c[3]->w,
- m_simplex->c[1]->w-m_simplex->c[3]->w,
- m_simplex->c[2]->w-m_simplex->c[3]->w))>0)
- return(true);
- }
- break;
- }
- return(false);
- }
- /* Internals */
- void getsupport(const btVector3& d,sSV& sv) const
- {
- sv.d = d/d.length();
- sv.w = m_shape.Support(sv.d);
- }
- void removevertice(sSimplex& simplex)
- {
- m_free[m_nfree++]=simplex.c[--simplex.rank];
- }
- void appendvertice(sSimplex& simplex,const btVector3& v)
- {
- simplex.p[simplex.rank]=0;
- simplex.c[simplex.rank]=m_free[--m_nfree];
- getsupport(v,*simplex.c[simplex.rank++]);
- }
- static btScalar det(const btVector3& a,const btVector3& b,const btVector3& c)
- {
- return( a.y()*b.z()*c.x()+a.z()*b.x()*c.y()-
- a.x()*b.z()*c.y()-a.y()*b.x()*c.z()+
- a.x()*b.y()*c.z()-a.z()*b.y()*c.x());
- }
- static btScalar projectorigin( const btVector3& a,
- const btVector3& b,
- btScalar* w,U& m)
- {
- const btVector3 d=b-a;
- const btScalar l=d.length2();
- if(l>GJK_SIMPLEX2_EPS)
- {
- const btScalar t(l>0?-btDot(a,d)/l:0);
- if(t>=1) { w[0]=0;w[1]=1;m=2;return(b.length2()); }
- else if(t<=0) { w[0]=1;w[1]=0;m=1;return(a.length2()); }
- else { w[0]=1-(w[1]=t);m=3;return((a+d*t).length2()); }
- }
- return(-1);
- }
- static btScalar projectorigin( const btVector3& a,
- const btVector3& b,
- const btVector3& c,
- btScalar* w,U& m)
- {
- static const U imd3[]={1,2,0};
- const btVector3* vt[]={&a,&b,&c};
- const btVector3 dl[]={a-b,b-c,c-a};
- const btVector3 n=btCross(dl[0],dl[1]);
- const btScalar l=n.length2();
- if(l>GJK_SIMPLEX3_EPS)
- {
- btScalar mindist=-1;
- btScalar subw[2]={0.f,0.f};
- U subm(0);
- for(U i=0;i<3;++i)
- {
- if(btDot(*vt[i],btCross(dl[i],n))>0)
- {
- const U j=imd3[i];
- const btScalar subd(projectorigin(*vt[i],*vt[j],subw,subm));
- if((mindist<0)||(subd<mindist))
- {
- mindist = subd;
- m = static_cast<U>(((subm&1)?1<<i:0)+((subm&2)?1<<j:0));
- w[i] = subw[0];
- w[j] = subw[1];
- w[imd3[j]] = 0;
- }
- }
- }
- if(mindist<0)
- {
- const btScalar d=btDot(a,n);
- const btScalar s=btSqrt(l);
- const btVector3 p=n*(d/l);
- mindist = p.length2();
- m = 7;
- w[0] = (btCross(dl[1],b-p)).length()/s;
- w[1] = (btCross(dl[2],c-p)).length()/s;
- w[2] = 1-(w[0]+w[1]);
- }
- return(mindist);
- }
- return(-1);
- }
- static btScalar projectorigin( const btVector3& a,
- const btVector3& b,
- const btVector3& c,
- const btVector3& d,
- btScalar* w,U& m)
- {
- static const U imd3[]={1,2,0};
- const btVector3* vt[]={&a,&b,&c,&d};
- const btVector3 dl[]={a-d,b-d,c-d};
- const btScalar vl=det(dl[0],dl[1],dl[2]);
- const bool ng=(vl*btDot(a,btCross(b-c,a-b)))<=0;
- if(ng&&(btFabs(vl)>GJK_SIMPLEX4_EPS))
- {
- btScalar mindist=-1;
- btScalar subw[3]={0.f,0.f,0.f};
- U subm(0);
- for(U i=0;i<3;++i)
- {
- const U j=imd3[i];
- const btScalar s=vl*btDot(d,btCross(dl[i],dl[j]));
- if(s>0)
- {
- const btScalar subd=projectorigin(*vt[i],*vt[j],d,subw,subm);
- if((mindist<0)||(subd<mindist))
- {
- mindist = subd;
- m = static_cast<U>((subm&1?1<<i:0)+
- (subm&2?1<<j:0)+
- (subm&4?8:0));
- w[i] = subw[0];
- w[j] = subw[1];
- w[imd3[j]] = 0;
- w[3] = subw[2];
- }
- }
- }
- if(mindist<0)
- {
- mindist = 0;
- m = 15;
- w[0] = det(c,b,d)/vl;
- w[1] = det(a,c,d)/vl;
- w[2] = det(b,a,d)/vl;
- w[3] = 1-(w[0]+w[1]+w[2]);
- }
- return(mindist);
- }
- return(-1);
- }
- };
+enum eGjkStatus
+{
+ eGjkValid,
+ eGjkInside,
+ eGjkFailed
+};
+
+// GJK
+template <typename btConvexTemplate>
+struct GJK
+{
+ /* Types */
+ struct sSV
+ {
+ btVector3 d, w;
+ };
+ struct sSimplex
+ {
+ sSV* c[4];
+ btScalar p[4];
+ U rank;
+ };
+
+ /* Fields */
+ MinkowskiDiff<btConvexTemplate> m_shape;
+ btVector3 m_ray;
+ btScalar m_distance;
+ sSimplex m_simplices[2];
+ sSV m_store[4];
+ sSV* m_free[4];
+ U m_nfree;
+ U m_current;
+ sSimplex* m_simplex;
+ eGjkStatus m_status;
+ /* Methods */
+
+ GJK(const btConvexTemplate& a, const btConvexTemplate& b)
+ : m_shape(a, b)
+ {
+ Initialize();
+ }
+ void Initialize()
+ {
+ m_ray = btVector3(0, 0, 0);
+ m_nfree = 0;
+ m_status = eGjkFailed;
+ m_current = 0;
+ m_distance = 0;
+ }
+ eGjkStatus Evaluate(const MinkowskiDiff<btConvexTemplate>& shapearg, const btVector3& guess)
+ {
+ U iterations = 0;
+ btScalar sqdist = 0;
+ btScalar alpha = 0;
+ btVector3 lastw[4];
+ U clastw = 0;
+ /* Initialize solver */
+ m_free[0] = &m_store[0];
+ m_free[1] = &m_store[1];
+ m_free[2] = &m_store[2];
+ m_free[3] = &m_store[3];
+ m_nfree = 4;
+ m_current = 0;
+ m_status = eGjkValid;
+ m_shape = shapearg;
+ m_distance = 0;
+ /* Initialize simplex */
+ m_simplices[0].rank = 0;
+ m_ray = guess;
+ const btScalar sqrl = m_ray.length2();
+ appendvertice(m_simplices[0], sqrl > 0 ? -m_ray : btVector3(1, 0, 0));
+ m_simplices[0].p[0] = 1;
+ m_ray = m_simplices[0].c[0]->w;
+ sqdist = sqrl;
+ lastw[0] =
+ lastw[1] =
+ lastw[2] =
+ lastw[3] = m_ray;
+ /* Loop */
+ do
+ {
+ const U next = 1 - m_current;
+ sSimplex& cs = m_simplices[m_current];
+ sSimplex& ns = m_simplices[next];
+ /* Check zero */
+ const btScalar rl = m_ray.length();
+ if (rl < GJK_MIN_DISTANCE)
+ { /* Touching or inside */
+ m_status = eGjkInside;
+ break;
+ }
+ /* Append new vertice in -'v' direction */
+ appendvertice(cs, -m_ray);
+ const btVector3& w = cs.c[cs.rank - 1]->w;
+ bool found = false;
+ for (U i = 0; i < 4; ++i)
+ {
+ if ((w - lastw[i]).length2() < GJK_DUPLICATED_EPS)
+ {
+ found = true;
+ break;
+ }
+ }
+ if (found)
+ { /* Return old simplex */
+ removevertice(m_simplices[m_current]);
+ break;
+ }
+ else
+ { /* Update lastw */
+ lastw[clastw = (clastw + 1) & 3] = w;
+ }
+ /* Check for termination */
+ const btScalar omega = btDot(m_ray, w) / rl;
+ alpha = btMax(omega, alpha);
+ if (((rl - alpha) - (GJK_ACCURARY * rl)) <= 0)
+ { /* Return old simplex */
+ removevertice(m_simplices[m_current]);
+ break;
+ }
+ /* Reduce simplex */
+ btScalar weights[4];
+ U mask = 0;
+ switch (cs.rank)
+ {
+ case 2:
+ sqdist = projectorigin(cs.c[0]->w,
+ cs.c[1]->w,
+ weights, mask);
+ break;
+ case 3:
+ sqdist = projectorigin(cs.c[0]->w,
+ cs.c[1]->w,
+ cs.c[2]->w,
+ weights, mask);
+ break;
+ case 4:
+ sqdist = projectorigin(cs.c[0]->w,
+ cs.c[1]->w,
+ cs.c[2]->w,
+ cs.c[3]->w,
+ weights, mask);
+ break;
+ }
+ if (sqdist >= 0)
+ { /* Valid */
+ ns.rank = 0;
+ m_ray = btVector3(0, 0, 0);
+ m_current = next;
+ for (U i = 0, ni = cs.rank; i < ni; ++i)
+ {
+ if (mask & (1 << i))
+ {
+ ns.c[ns.rank] = cs.c[i];
+ ns.p[ns.rank++] = weights[i];
+ m_ray += cs.c[i]->w * weights[i];
+ }
+ else
+ {
+ m_free[m_nfree++] = cs.c[i];
+ }
+ }
+ if (mask == 15) m_status = eGjkInside;
+ }
+ else
+ { /* Return old simplex */
+ removevertice(m_simplices[m_current]);
+ break;
+ }
+ m_status = ((++iterations) < GJK_MAX_ITERATIONS) ? m_status : eGjkFailed;
+ } while (m_status == eGjkValid);
+ m_simplex = &m_simplices[m_current];
+ switch (m_status)
+ {
+ case eGjkValid:
+ m_distance = m_ray.length();
+ break;
+ case eGjkInside:
+ m_distance = 0;
+ break;
+ default:
+ {
+ }
+ }
+ return (m_status);
+ }
+ bool EncloseOrigin()
+ {
+ switch (m_simplex->rank)
+ {
+ case 1:
+ {
+ for (U i = 0; i < 3; ++i)
+ {
+ btVector3 axis = btVector3(0, 0, 0);
+ axis[i] = 1;
+ appendvertice(*m_simplex, axis);
+ if (EncloseOrigin()) return (true);
+ removevertice(*m_simplex);
+ appendvertice(*m_simplex, -axis);
+ if (EncloseOrigin()) return (true);
+ removevertice(*m_simplex);
+ }
+ }
+ break;
+ case 2:
+ {
+ const btVector3 d = m_simplex->c[1]->w - m_simplex->c[0]->w;
+ for (U i = 0; i < 3; ++i)
+ {
+ btVector3 axis = btVector3(0, 0, 0);
+ axis[i] = 1;
+ const btVector3 p = btCross(d, axis);
+ if (p.length2() > 0)
+ {
+ appendvertice(*m_simplex, p);
+ if (EncloseOrigin()) return (true);
+ removevertice(*m_simplex);
+ appendvertice(*m_simplex, -p);
+ if (EncloseOrigin()) return (true);
+ removevertice(*m_simplex);
+ }
+ }
+ }
+ break;
+ case 3:
+ {
+ const btVector3 n = btCross(m_simplex->c[1]->w - m_simplex->c[0]->w,
+ m_simplex->c[2]->w - m_simplex->c[0]->w);
+ if (n.length2() > 0)
+ {
+ appendvertice(*m_simplex, n);
+ if (EncloseOrigin()) return (true);
+ removevertice(*m_simplex);
+ appendvertice(*m_simplex, -n);
+ if (EncloseOrigin()) return (true);
+ removevertice(*m_simplex);
+ }
+ }
+ break;
+ case 4:
+ {
+ if (btFabs(det(m_simplex->c[0]->w - m_simplex->c[3]->w,
+ m_simplex->c[1]->w - m_simplex->c[3]->w,
+ m_simplex->c[2]->w - m_simplex->c[3]->w)) > 0)
+ return (true);
+ }
+ break;
+ }
+ return (false);
+ }
+ /* Internals */
+ void getsupport(const btVector3& d, sSV& sv) const
+ {
+ sv.d = d / d.length();
+ sv.w = m_shape.Support(sv.d);
+ }
+ void removevertice(sSimplex& simplex)
+ {
+ m_free[m_nfree++] = simplex.c[--simplex.rank];
+ }
+ void appendvertice(sSimplex& simplex, const btVector3& v)
+ {
+ simplex.p[simplex.rank] = 0;
+ simplex.c[simplex.rank] = m_free[--m_nfree];
+ getsupport(v, *simplex.c[simplex.rank++]);
+ }
+ static btScalar det(const btVector3& a, const btVector3& b, const btVector3& c)
+ {
+ return (a.y() * b.z() * c.x() + a.z() * b.x() * c.y() -
+ a.x() * b.z() * c.y() - a.y() * b.x() * c.z() +
+ a.x() * b.y() * c.z() - a.z() * b.y() * c.x());
+ }
+ static btScalar projectorigin(const btVector3& a,
+ const btVector3& b,
+ btScalar* w, U& m)
+ {
+ const btVector3 d = b - a;
+ const btScalar l = d.length2();
+ if (l > GJK_SIMPLEX2_EPS)
+ {
+ const btScalar t(l > 0 ? -btDot(a, d) / l : 0);
+ if (t >= 1)
+ {
+ w[0] = 0;
+ w[1] = 1;
+ m = 2;
+ return (b.length2());
+ }
+ else if (t <= 0)
+ {
+ w[0] = 1;
+ w[1] = 0;
+ m = 1;
+ return (a.length2());
+ }
+ else
+ {
+ w[0] = 1 - (w[1] = t);
+ m = 3;
+ return ((a + d * t).length2());
+ }
+ }
+ return (-1);
+ }
+ static btScalar projectorigin(const btVector3& a,
+ const btVector3& b,
+ const btVector3& c,
+ btScalar* w, U& m)
+ {
+ static const U imd3[] = {1, 2, 0};
+ const btVector3* vt[] = {&a, &b, &c};
+ const btVector3 dl[] = {a - b, b - c, c - a};
+ const btVector3 n = btCross(dl[0], dl[1]);
+ const btScalar l = n.length2();
+ if (l > GJK_SIMPLEX3_EPS)
+ {
+ btScalar mindist = -1;
+ btScalar subw[2] = {0.f, 0.f};
+ U subm(0);
+ for (U i = 0; i < 3; ++i)
+ {
+ if (btDot(*vt[i], btCross(dl[i], n)) > 0)
+ {
+ const U j = imd3[i];
+ const btScalar subd(projectorigin(*vt[i], *vt[j], subw, subm));
+ if ((mindist < 0) || (subd < mindist))
+ {
+ mindist = subd;
+ m = static_cast<U>(((subm & 1) ? 1 << i : 0) + ((subm & 2) ? 1 << j : 0));
+ w[i] = subw[0];
+ w[j] = subw[1];
+ w[imd3[j]] = 0;
+ }
+ }
+ }
+ if (mindist < 0)
+ {
+ const btScalar d = btDot(a, n);
+ const btScalar s = btSqrt(l);
+ const btVector3 p = n * (d / l);
+ mindist = p.length2();
+ m = 7;
+ w[0] = (btCross(dl[1], b - p)).length() / s;
+ w[1] = (btCross(dl[2], c - p)).length() / s;
+ w[2] = 1 - (w[0] + w[1]);
+ }
+ return (mindist);
+ }
+ return (-1);
+ }
+ static btScalar projectorigin(const btVector3& a,
+ const btVector3& b,
+ const btVector3& c,
+ const btVector3& d,
+ btScalar* w, U& m)
+ {
+ static const U imd3[] = {1, 2, 0};
+ const btVector3* vt[] = {&a, &b, &c, &d};
+ const btVector3 dl[] = {a - d, b - d, c - d};
+ const btScalar vl = det(dl[0], dl[1], dl[2]);
+ const bool ng = (vl * btDot(a, btCross(b - c, a - b))) <= 0;
+ if (ng && (btFabs(vl) > GJK_SIMPLEX4_EPS))
+ {
+ btScalar mindist = -1;
+ btScalar subw[3] = {0.f, 0.f, 0.f};
+ U subm(0);
+ for (U i = 0; i < 3; ++i)
+ {
+ const U j = imd3[i];
+ const btScalar s = vl * btDot(d, btCross(dl[i], dl[j]));
+ if (s > 0)
+ {
+ const btScalar subd = projectorigin(*vt[i], *vt[j], d, subw, subm);
+ if ((mindist < 0) || (subd < mindist))
+ {
+ mindist = subd;
+ m = static_cast<U>((subm & 1 ? 1 << i : 0) +
+ (subm & 2 ? 1 << j : 0) +
+ (subm & 4 ? 8 : 0));
+ w[i] = subw[0];
+ w[j] = subw[1];
+ w[imd3[j]] = 0;
+ w[3] = subw[2];
+ }
+ }
+ }
+ if (mindist < 0)
+ {
+ mindist = 0;
+ m = 15;
+ w[0] = det(c, b, d) / vl;
+ w[1] = det(a, c, d) / vl;
+ w[2] = det(b, a, d) / vl;
+ w[3] = 1 - (w[0] + w[1] + w[2]);
+ }
+ return (mindist);
+ }
+ return (-1);
+ }
+};
-enum eEpaStatus
+enum eEpaStatus
{
- eEpaValid,
- eEpaTouching,
- eEpaDegenerated,
- eEpaNonConvex,
- eEpaInvalidHull,
- eEpaOutOfFaces,
- eEpaOutOfVertices,
- eEpaAccuraryReached,
- eEpaFallBack,
- eEpaFailed
+ eEpaValid,
+ eEpaTouching,
+ eEpaDegenerated,
+ eEpaNonConvex,
+ eEpaInvalidHull,
+ eEpaOutOfFaces,
+ eEpaOutOfVertices,
+ eEpaAccuraryReached,
+ eEpaFallBack,
+ eEpaFailed
};
+// EPA
+template <typename btConvexTemplate>
+struct EPA
+{
+ /* Types */
+
+ struct sFace
+ {
+ btVector3 n;
+ btScalar d;
+ typename GJK<btConvexTemplate>::sSV* c[3];
+ sFace* f[3];
+ sFace* l[2];
+ U1 e[3];
+ U1 pass;
+ };
+ struct sList
+ {
+ sFace* root;
+ U count;
+ sList() : root(0), count(0) {}
+ };
+ struct sHorizon
+ {
+ sFace* cf;
+ sFace* ff;
+ U nf;
+ sHorizon() : cf(0), ff(0), nf(0) {}
+ };
+
+ /* Fields */
+ eEpaStatus m_status;
+ typename GJK<btConvexTemplate>::sSimplex m_result;
+ btVector3 m_normal;
+ btScalar m_depth;
+ typename GJK<btConvexTemplate>::sSV m_sv_store[EPA_MAX_VERTICES];
+ sFace m_fc_store[EPA_MAX_FACES];
+ U m_nextsv;
+ sList m_hull;
+ sList m_stock;
+ /* Methods */
+ EPA()
+ {
+ Initialize();
+ }
+
+ static inline void bind(sFace* fa, U ea, sFace* fb, U eb)
+ {
+ fa->e[ea] = (U1)eb;
+ fa->f[ea] = fb;
+ fb->e[eb] = (U1)ea;
+ fb->f[eb] = fa;
+ }
+ static inline void append(sList& list, sFace* face)
+ {
+ face->l[0] = 0;
+ face->l[1] = list.root;
+ if (list.root) list.root->l[0] = face;
+ list.root = face;
+ ++list.count;
+ }
+ static inline void remove(sList& list, sFace* face)
+ {
+ if (face->l[1]) face->l[1]->l[0] = face->l[0];
+ if (face->l[0]) face->l[0]->l[1] = face->l[1];
+ if (face == list.root) list.root = face->l[1];
+ --list.count;
+ }
+
+ void Initialize()
+ {
+ m_status = eEpaFailed;
+ m_normal = btVector3(0, 0, 0);
+ m_depth = 0;
+ m_nextsv = 0;
+ for (U i = 0; i < EPA_MAX_FACES; ++i)
+ {
+ append(m_stock, &m_fc_store[EPA_MAX_FACES - i - 1]);
+ }
+ }
+ eEpaStatus Evaluate(GJK<btConvexTemplate>& gjk, const btVector3& guess)
+ {
+ typename GJK<btConvexTemplate>::sSimplex& simplex = *gjk.m_simplex;
+ if ((simplex.rank > 1) && gjk.EncloseOrigin())
+ {
+ /* Clean up */
+ while (m_hull.root)
+ {
+ sFace* f = m_hull.root;
+ remove(m_hull, f);
+ append(m_stock, f);
+ }
+ m_status = eEpaValid;
+ m_nextsv = 0;
+ /* Orient simplex */
+ if (gjk.det(simplex.c[0]->w - simplex.c[3]->w,
+ simplex.c[1]->w - simplex.c[3]->w,
+ simplex.c[2]->w - simplex.c[3]->w) < 0)
+ {
+ btSwap(simplex.c[0], simplex.c[1]);
+ btSwap(simplex.p[0], simplex.p[1]);
+ }
+ /* Build initial hull */
+ sFace* tetra[] = {newface(simplex.c[0], simplex.c[1], simplex.c[2], true),
+ newface(simplex.c[1], simplex.c[0], simplex.c[3], true),
+ newface(simplex.c[2], simplex.c[1], simplex.c[3], true),
+ newface(simplex.c[0], simplex.c[2], simplex.c[3], true)};
+ if (m_hull.count == 4)
+ {
+ sFace* best = findbest();
+ sFace outer = *best;
+ U pass = 0;
+ U iterations = 0;
+ bind(tetra[0], 0, tetra[1], 0);
+ bind(tetra[0], 1, tetra[2], 0);
+ bind(tetra[0], 2, tetra[3], 0);
+ bind(tetra[1], 1, tetra[3], 2);
+ bind(tetra[1], 2, tetra[2], 1);
+ bind(tetra[2], 2, tetra[3], 1);
+ m_status = eEpaValid;
+ for (; iterations < EPA_MAX_ITERATIONS; ++iterations)
+ {
+ if (m_nextsv < EPA_MAX_VERTICES)
+ {
+ sHorizon horizon;
+ typename GJK<btConvexTemplate>::sSV* w = &m_sv_store[m_nextsv++];
+ bool valid = true;
+ best->pass = (U1)(++pass);
+ gjk.getsupport(best->n, *w);
+ const btScalar wdist = btDot(best->n, w->w) - best->d;
+ if (wdist > EPA_ACCURACY)
+ {
+ for (U j = 0; (j < 3) && valid; ++j)
+ {
+ valid &= expand(pass, w,
+ best->f[j], best->e[j],
+ horizon);
+ }
+ if (valid && (horizon.nf >= 3))
+ {
+ bind(horizon.cf, 1, horizon.ff, 2);
+ remove(m_hull, best);
+ append(m_stock, best);
+ best = findbest();
+ outer = *best;
+ }
+ else
+ {
+ m_status = eEpaInvalidHull;
+ break;
+ }
+ }
+ else
+ {
+ m_status = eEpaAccuraryReached;
+ break;
+ }
+ }
+ else
+ {
+ m_status = eEpaOutOfVertices;
+ break;
+ }
+ }
+ const btVector3 projection = outer.n * outer.d;
+ m_normal = outer.n;
+ m_depth = outer.d;
+ m_result.rank = 3;
+ m_result.c[0] = outer.c[0];
+ m_result.c[1] = outer.c[1];
+ m_result.c[2] = outer.c[2];
+ m_result.p[0] = btCross(outer.c[1]->w - projection,
+ outer.c[2]->w - projection)
+ .length();
+ m_result.p[1] = btCross(outer.c[2]->w - projection,
+ outer.c[0]->w - projection)
+ .length();
+ m_result.p[2] = btCross(outer.c[0]->w - projection,
+ outer.c[1]->w - projection)
+ .length();
+ const btScalar sum = m_result.p[0] + m_result.p[1] + m_result.p[2];
+ m_result.p[0] /= sum;
+ m_result.p[1] /= sum;
+ m_result.p[2] /= sum;
+ return (m_status);
+ }
+ }
+ /* Fallback */
+ m_status = eEpaFallBack;
+ m_normal = -guess;
+ const btScalar nl = m_normal.length();
+ if (nl > 0)
+ m_normal = m_normal / nl;
+ else
+ m_normal = btVector3(1, 0, 0);
+ m_depth = 0;
+ m_result.rank = 1;
+ m_result.c[0] = simplex.c[0];
+ m_result.p[0] = 1;
+ return (m_status);
+ }
+ bool getedgedist(sFace* face, typename GJK<btConvexTemplate>::sSV* a, typename GJK<btConvexTemplate>::sSV* b, btScalar& dist)
+ {
+ const btVector3 ba = b->w - a->w;
+ const btVector3 n_ab = btCross(ba, face->n); // Outward facing edge normal direction, on triangle plane
+ const btScalar a_dot_nab = btDot(a->w, n_ab); // Only care about the sign to determine inside/outside, so not normalization required
+
+ if (a_dot_nab < 0)
+ {
+ // Outside of edge a->b
+
+ const btScalar ba_l2 = ba.length2();
+ const btScalar a_dot_ba = btDot(a->w, ba);
+ const btScalar b_dot_ba = btDot(b->w, ba);
+
+ if (a_dot_ba > 0)
+ {
+ // Pick distance vertex a
+ dist = a->w.length();
+ }
+ else if (b_dot_ba < 0)
+ {
+ // Pick distance vertex b
+ dist = b->w.length();
+ }
+ else
+ {
+ // Pick distance to edge a->b
+ const btScalar a_dot_b = btDot(a->w, b->w);
+ dist = btSqrt(btMax((a->w.length2() * b->w.length2() - a_dot_b * a_dot_b) / ba_l2, (btScalar)0));
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+ sFace* newface(typename GJK<btConvexTemplate>::sSV* a, typename GJK<btConvexTemplate>::sSV* b, typename GJK<btConvexTemplate>::sSV* c, bool forced)
+ {
+ if (m_stock.root)
+ {
+ sFace* face = m_stock.root;
+ remove(m_stock, face);
+ append(m_hull, face);
+ face->pass = 0;
+ face->c[0] = a;
+ face->c[1] = b;
+ face->c[2] = c;
+ face->n = btCross(b->w - a->w, c->w - a->w);
+ const btScalar l = face->n.length();
+ const bool v = l > EPA_ACCURACY;
+
+ if (v)
+ {
+ if (!(getedgedist(face, a, b, face->d) ||
+ getedgedist(face, b, c, face->d) ||
+ getedgedist(face, c, a, face->d)))
+ {
+ // Origin projects to the interior of the triangle
+ // Use distance to triangle plane
+ face->d = btDot(a->w, face->n) / l;
+ }
+
+ face->n /= l;
+ if (forced || (face->d >= -EPA_PLANE_EPS))
+ {
+ return face;
+ }
+ else
+ m_status = eEpaNonConvex;
+ }
+ else
+ m_status = eEpaDegenerated;
+
+ remove(m_hull, face);
+ append(m_stock, face);
+ return 0;
+ }
+ m_status = m_stock.root ? eEpaOutOfVertices : eEpaOutOfFaces;
+ return 0;
+ }
+ sFace* findbest()
+ {
+ sFace* minf = m_hull.root;
+ btScalar mind = minf->d * minf->d;
+ for (sFace* f = minf->l[1]; f; f = f->l[1])
+ {
+ const btScalar sqd = f->d * f->d;
+ if (sqd < mind)
+ {
+ minf = f;
+ mind = sqd;
+ }
+ }
+ return (minf);
+ }
+ bool expand(U pass, typename GJK<btConvexTemplate>::sSV* w, sFace* f, U e, sHorizon& horizon)
+ {
+ static const U i1m3[] = {1, 2, 0};
+ static const U i2m3[] = {2, 0, 1};
+ if (f->pass != pass)
+ {
+ const U e1 = i1m3[e];
+ if ((btDot(f->n, w->w) - f->d) < -EPA_PLANE_EPS)
+ {
+ sFace* nf = newface(f->c[e1], f->c[e], w, false);
+ if (nf)
+ {
+ bind(nf, 0, f, e);
+ if (horizon.cf)
+ bind(horizon.cf, 1, nf, 2);
+ else
+ horizon.ff = nf;
+ horizon.cf = nf;
+ ++horizon.nf;
+ return (true);
+ }
+ }
+ else
+ {
+ const U e2 = i2m3[e];
+ f->pass = (U1)pass;
+ if (expand(pass, w, f->f[e1], f->e[e1], horizon) &&
+ expand(pass, w, f->f[e2], f->e[e2], horizon))
+ {
+ remove(m_hull, f);
+ append(m_stock, f);
+ return (true);
+ }
+ }
+ }
+ return (false);
+ }
+};
- // EPA
template <typename btConvexTemplate>
- struct EPA
- {
- /* Types */
-
- struct sFace
- {
- btVector3 n;
- btScalar d;
- typename GJK<btConvexTemplate>::sSV* c[3];
- sFace* f[3];
- sFace* l[2];
- U1 e[3];
- U1 pass;
- };
- struct sList
- {
- sFace* root;
- U count;
- sList() : root(0),count(0) {}
- };
- struct sHorizon
- {
- sFace* cf;
- sFace* ff;
- U nf;
- sHorizon() : cf(0),ff(0),nf(0) {}
- };
-
- /* Fields */
- eEpaStatus m_status;
- typename GJK<btConvexTemplate>::sSimplex m_result;
- btVector3 m_normal;
- btScalar m_depth;
- typename GJK<btConvexTemplate>::sSV m_sv_store[EPA_MAX_VERTICES];
- sFace m_fc_store[EPA_MAX_FACES];
- U m_nextsv;
- sList m_hull;
- sList m_stock;
- /* Methods */
- EPA()
- {
- Initialize();
- }
-
-
- static inline void bind(sFace* fa,U ea,sFace* fb,U eb)
- {
- fa->e[ea]=(U1)eb;fa->f[ea]=fb;
- fb->e[eb]=(U1)ea;fb->f[eb]=fa;
- }
- static inline void append(sList& list,sFace* face)
- {
- face->l[0] = 0;
- face->l[1] = list.root;
- if(list.root) list.root->l[0]=face;
- list.root = face;
- ++list.count;
- }
- static inline void remove(sList& list,sFace* face)
- {
- if(face->l[1]) face->l[1]->l[0]=face->l[0];
- if(face->l[0]) face->l[0]->l[1]=face->l[1];
- if(face==list.root) list.root=face->l[1];
- --list.count;
- }
-
-
- void Initialize()
- {
- m_status = eEpaFailed;
- m_normal = btVector3(0,0,0);
- m_depth = 0;
- m_nextsv = 0;
- for(U i=0;i<EPA_MAX_FACES;++i)
- {
- append(m_stock,&m_fc_store[EPA_MAX_FACES-i-1]);
- }
- }
- eEpaStatus Evaluate(GJK<btConvexTemplate>& gjk,const btVector3& guess)
- {
- typename GJK<btConvexTemplate>::sSimplex& simplex=*gjk.m_simplex;
- if((simplex.rank>1)&&gjk.EncloseOrigin())
- {
-
- /* Clean up */
- while(m_hull.root)
- {
- sFace* f = m_hull.root;
- remove(m_hull,f);
- append(m_stock,f);
- }
- m_status = eEpaValid;
- m_nextsv = 0;
- /* Orient simplex */
- if(gjk.det( simplex.c[0]->w-simplex.c[3]->w,
- simplex.c[1]->w-simplex.c[3]->w,
- simplex.c[2]->w-simplex.c[3]->w)<0)
- {
- btSwap(simplex.c[0],simplex.c[1]);
- btSwap(simplex.p[0],simplex.p[1]);
- }
- /* Build initial hull */
- sFace* tetra[]={newface(simplex.c[0],simplex.c[1],simplex.c[2],true),
- newface(simplex.c[1],simplex.c[0],simplex.c[3],true),
- newface(simplex.c[2],simplex.c[1],simplex.c[3],true),
- newface(simplex.c[0],simplex.c[2],simplex.c[3],true)};
- if(m_hull.count==4)
- {
- sFace* best=findbest();
- sFace outer=*best;
- U pass=0;
- U iterations=0;
- bind(tetra[0],0,tetra[1],0);
- bind(tetra[0],1,tetra[2],0);
- bind(tetra[0],2,tetra[3],0);
- bind(tetra[1],1,tetra[3],2);
- bind(tetra[1],2,tetra[2],1);
- bind(tetra[2],2,tetra[3],1);
- m_status=eEpaValid;
- for(;iterations<EPA_MAX_ITERATIONS;++iterations)
- {
- if(m_nextsv<EPA_MAX_VERTICES)
- {
- sHorizon horizon;
- typename GJK<btConvexTemplate>::sSV* w=&m_sv_store[m_nextsv++];
- bool valid=true;
- best->pass = (U1)(++pass);
- gjk.getsupport(best->n,*w);
- const btScalar wdist=btDot(best->n,w->w)-best->d;
- if(wdist>EPA_ACCURACY)
- {
- for(U j=0;(j<3)&&valid;++j)
- {
- valid&=expand( pass,w,
- best->f[j],best->e[j],
- horizon);
- }
- if(valid&&(horizon.nf>=3))
- {
- bind(horizon.cf,1,horizon.ff,2);
- remove(m_hull,best);
- append(m_stock,best);
- best=findbest();
- outer=*best;
- } else { m_status=eEpaInvalidHull;break; }
- } else { m_status=eEpaAccuraryReached;break; }
- } else { m_status=eEpaOutOfVertices;break; }
- }
- const btVector3 projection=outer.n*outer.d;
- m_normal = outer.n;
- m_depth = outer.d;
- m_result.rank = 3;
- m_result.c[0] = outer.c[0];
- m_result.c[1] = outer.c[1];
- m_result.c[2] = outer.c[2];
- m_result.p[0] = btCross( outer.c[1]->w-projection,
- outer.c[2]->w-projection).length();
- m_result.p[1] = btCross( outer.c[2]->w-projection,
- outer.c[0]->w-projection).length();
- m_result.p[2] = btCross( outer.c[0]->w-projection,
- outer.c[1]->w-projection).length();
- const btScalar sum=m_result.p[0]+m_result.p[1]+m_result.p[2];
- m_result.p[0] /= sum;
- m_result.p[1] /= sum;
- m_result.p[2] /= sum;
- return(m_status);
- }
- }
- /* Fallback */
- m_status = eEpaFallBack;
- m_normal = -guess;
- const btScalar nl=m_normal.length();
- if(nl>0)
- m_normal = m_normal/nl;
- else
- m_normal = btVector3(1,0,0);
- m_depth = 0;
- m_result.rank=1;
- m_result.c[0]=simplex.c[0];
- m_result.p[0]=1;
- return(m_status);
- }
- bool getedgedist(sFace* face, typename GJK<btConvexTemplate>::sSV* a, typename GJK<btConvexTemplate>::sSV* b, btScalar& dist)
- {
- const btVector3 ba = b->w - a->w;
- const btVector3 n_ab = btCross(ba, face->n); // Outward facing edge normal direction, on triangle plane
- const btScalar a_dot_nab = btDot(a->w, n_ab); // Only care about the sign to determine inside/outside, so not normalization required
-
- if(a_dot_nab < 0)
- {
- // Outside of edge a->b
-
- const btScalar ba_l2 = ba.length2();
- const btScalar a_dot_ba = btDot(a->w, ba);
- const btScalar b_dot_ba = btDot(b->w, ba);
-
- if(a_dot_ba > 0)
- {
- // Pick distance vertex a
- dist = a->w.length();
- }
- else if(b_dot_ba < 0)
- {
- // Pick distance vertex b
- dist = b->w.length();
- }
- else
- {
- // Pick distance to edge a->b
- const btScalar a_dot_b = btDot(a->w, b->w);
- dist = btSqrt(btMax((a->w.length2() * b->w.length2() - a_dot_b * a_dot_b) / ba_l2, (btScalar)0));
- }
-
- return true;
- }
-
- return false;
- }
- sFace* newface(typename GJK<btConvexTemplate>::sSV* a,typename GJK<btConvexTemplate>::sSV* b,typename GJK<btConvexTemplate>::sSV* c,bool forced)
- {
- if(m_stock.root)
- {
- sFace* face=m_stock.root;
- remove(m_stock,face);
- append(m_hull,face);
- face->pass = 0;
- face->c[0] = a;
- face->c[1] = b;
- face->c[2] = c;
- face->n = btCross(b->w-a->w,c->w-a->w);
- const btScalar l=face->n.length();
- const bool v=l>EPA_ACCURACY;
-
- if(v)
- {
- if(!(getedgedist(face, a, b, face->d) ||
- getedgedist(face, b, c, face->d) ||
- getedgedist(face, c, a, face->d)))
- {
- // Origin projects to the interior of the triangle
- // Use distance to triangle plane
- face->d = btDot(a->w, face->n) / l;
- }
-
- face->n /= l;
- if(forced || (face->d >= -EPA_PLANE_EPS))
- {
- return face;
- }
- else
- m_status=eEpaNonConvex;
- }
- else
- m_status=eEpaDegenerated;
-
- remove(m_hull, face);
- append(m_stock, face);
- return 0;
-
- }
- m_status = m_stock.root ? eEpaOutOfVertices : eEpaOutOfFaces;
- return 0;
- }
- sFace* findbest()
- {
- sFace* minf=m_hull.root;
- btScalar mind=minf->d*minf->d;
- for(sFace* f=minf->l[1];f;f=f->l[1])
- {
- const btScalar sqd=f->d*f->d;
- if(sqd<mind)
- {
- minf=f;
- mind=sqd;
- }
- }
- return(minf);
- }
- bool expand(U pass,typename GJK<btConvexTemplate>::sSV* w,sFace* f,U e,sHorizon& horizon)
- {
- static const U i1m3[]={1,2,0};
- static const U i2m3[]={2,0,1};
- if(f->pass!=pass)
- {
- const U e1=i1m3[e];
- if((btDot(f->n,w->w)-f->d)<-EPA_PLANE_EPS)
- {
- sFace* nf=newface(f->c[e1],f->c[e],w,false);
- if(nf)
- {
- bind(nf,0,f,e);
- if(horizon.cf) bind(horizon.cf,1,nf,2); else horizon.ff=nf;
- horizon.cf=nf;
- ++horizon.nf;
- return(true);
- }
- }
- else
- {
- const U e2=i2m3[e];
- f->pass = (U1)pass;
- if( expand(pass,w,f->f[e1],f->e[e1],horizon)&&
- expand(pass,w,f->f[e2],f->e[e2],horizon))
- {
- remove(m_hull,f);
- append(m_stock,f);
- return(true);
- }
- }
- }
- return(false);
- }
-
- };
-
- template <typename btConvexTemplate>
- static void Initialize( const btConvexTemplate& a, const btConvexTemplate& b,
- btGjkEpaSolver3::sResults& results,
- MinkowskiDiff<btConvexTemplate>& shape)
- {
- /* Results */
- results.witnesses[0] =
- results.witnesses[1] = btVector3(0,0,0);
- results.status = btGjkEpaSolver3::sResults::Separated;
- /* Shape */
-
- shape.m_toshape1 = b.getWorldTransform().getBasis().transposeTimes(a.getWorldTransform().getBasis());
- shape.m_toshape0 = a.getWorldTransform().inverseTimes(b.getWorldTransform());
-
- }
-
+static void Initialize(const btConvexTemplate& a, const btConvexTemplate& b,
+ btGjkEpaSolver3::sResults& results,
+ MinkowskiDiff<btConvexTemplate>& shape)
+{
+ /* Results */
+ results.witnesses[0] =
+ results.witnesses[1] = btVector3(0, 0, 0);
+ results.status = btGjkEpaSolver3::sResults::Separated;
+ /* Shape */
+
+ shape.m_toshape1 = b.getWorldTransform().getBasis().transposeTimes(a.getWorldTransform().getBasis());
+ shape.m_toshape0 = a.getWorldTransform().inverseTimes(b.getWorldTransform());
+}
//
// Api
//
-
-
//
template <typename btConvexTemplate>
-bool btGjkEpaSolver3_Distance(const btConvexTemplate& a, const btConvexTemplate& b,
- const btVector3& guess,
- btGjkEpaSolver3::sResults& results)
+bool btGjkEpaSolver3_Distance(const btConvexTemplate& a, const btConvexTemplate& b,
+ const btVector3& guess,
+ btGjkEpaSolver3::sResults& results)
{
- MinkowskiDiff<btConvexTemplate> shape(a,b);
- Initialize(a,b,results,shape);
- GJK<btConvexTemplate> gjk(a,b);
- eGjkStatus gjk_status=gjk.Evaluate(shape,guess);
- if(gjk_status==eGjkValid)
- {
- btVector3 w0=btVector3(0,0,0);
- btVector3 w1=btVector3(0,0,0);
- for(U i=0;i<gjk.m_simplex->rank;++i)
- {
- const btScalar p=gjk.m_simplex->p[i];
- w0+=shape.Support( gjk.m_simplex->c[i]->d,0)*p;
- w1+=shape.Support(-gjk.m_simplex->c[i]->d,1)*p;
- }
- results.witnesses[0] = a.getWorldTransform()*w0;
- results.witnesses[1] = a.getWorldTransform()*w1;
- results.normal = w0-w1;
- results.distance = results.normal.length();
- results.normal /= results.distance>GJK_MIN_DISTANCE?results.distance:1;
- return(true);
- }
- else
- {
- results.status = gjk_status==eGjkInside?
- btGjkEpaSolver3::sResults::Penetrating :
- btGjkEpaSolver3::sResults::GJK_Failed ;
- return(false);
- }
+ MinkowskiDiff<btConvexTemplate> shape(a, b);
+ Initialize(a, b, results, shape);
+ GJK<btConvexTemplate> gjk(a, b);
+ eGjkStatus gjk_status = gjk.Evaluate(shape, guess);
+ if (gjk_status == eGjkValid)
+ {
+ btVector3 w0 = btVector3(0, 0, 0);
+ btVector3 w1 = btVector3(0, 0, 0);
+ for (U i = 0; i < gjk.m_simplex->rank; ++i)
+ {
+ const btScalar p = gjk.m_simplex->p[i];
+ w0 += shape.Support(gjk.m_simplex->c[i]->d, 0) * p;
+ w1 += shape.Support(-gjk.m_simplex->c[i]->d, 1) * p;
+ }
+ results.witnesses[0] = a.getWorldTransform() * w0;
+ results.witnesses[1] = a.getWorldTransform() * w1;
+ results.normal = w0 - w1;
+ results.distance = results.normal.length();
+ results.normal /= results.distance > GJK_MIN_DISTANCE ? results.distance : 1;
+ return (true);
+ }
+ else
+ {
+ results.status = gjk_status == eGjkInside ? btGjkEpaSolver3::sResults::Penetrating : btGjkEpaSolver3::sResults::GJK_Failed;
+ return (false);
+ }
}
-
template <typename btConvexTemplate>
-bool btGjkEpaSolver3_Penetration(const btConvexTemplate& a,
- const btConvexTemplate& b,
- const btVector3& guess,
- btGjkEpaSolver3::sResults& results)
+bool btGjkEpaSolver3_Penetration(const btConvexTemplate& a,
+ const btConvexTemplate& b,
+ const btVector3& guess,
+ btGjkEpaSolver3::sResults& results)
{
- MinkowskiDiff<btConvexTemplate> shape(a,b);
- Initialize(a,b,results,shape);
- GJK<btConvexTemplate> gjk(a,b);
- eGjkStatus gjk_status=gjk.Evaluate(shape,-guess);
- switch(gjk_status)
- {
- case eGjkInside:
- {
- EPA<btConvexTemplate> epa;
- eEpaStatus epa_status=epa.Evaluate(gjk,-guess);
- if(epa_status!=eEpaFailed)
- {
- btVector3 w0=btVector3(0,0,0);
- for(U i=0;i<epa.m_result.rank;++i)
- {
- w0+=shape.Support(epa.m_result.c[i]->d,0)*epa.m_result.p[i];
- }
- results.status = btGjkEpaSolver3::sResults::Penetrating;
- results.witnesses[0] = a.getWorldTransform()*w0;
- results.witnesses[1] = a.getWorldTransform()*(w0-epa.m_normal*epa.m_depth);
- results.normal = -epa.m_normal;
- results.distance = -epa.m_depth;
- return(true);
- } else results.status=btGjkEpaSolver3::sResults::EPA_Failed;
- }
- break;
- case eGjkFailed:
- results.status=btGjkEpaSolver3::sResults::GJK_Failed;
- break;
- default:
- {
- }
- }
- return(false);
+ MinkowskiDiff<btConvexTemplate> shape(a, b);
+ Initialize(a, b, results, shape);
+ GJK<btConvexTemplate> gjk(a, b);
+ eGjkStatus gjk_status = gjk.Evaluate(shape, -guess);
+ switch (gjk_status)
+ {
+ case eGjkInside:
+ {
+ EPA<btConvexTemplate> epa;
+ eEpaStatus epa_status = epa.Evaluate(gjk, -guess);
+ if (epa_status != eEpaFailed)
+ {
+ btVector3 w0 = btVector3(0, 0, 0);
+ for (U i = 0; i < epa.m_result.rank; ++i)
+ {
+ w0 += shape.Support(epa.m_result.c[i]->d, 0) * epa.m_result.p[i];
+ }
+ results.status = btGjkEpaSolver3::sResults::Penetrating;
+ results.witnesses[0] = a.getWorldTransform() * w0;
+ results.witnesses[1] = a.getWorldTransform() * (w0 - epa.m_normal * epa.m_depth);
+ results.normal = -epa.m_normal;
+ results.distance = -epa.m_depth;
+ return (true);
+ }
+ else
+ results.status = btGjkEpaSolver3::sResults::EPA_Failed;
+ }
+ break;
+ case eGjkFailed:
+ results.status = btGjkEpaSolver3::sResults::GJK_Failed;
+ break;
+ default:
+ {
+ }
+ }
+ return (false);
}
#if 0
@@ -990,28 +1021,28 @@ int btComputeGjkEpaPenetration2(const btCollisionDescription& colDesc, btDistanc
#endif
template <typename btConvexTemplate, typename btDistanceInfoTemplate>
-int btComputeGjkDistance(const btConvexTemplate& a, const btConvexTemplate& b,
- const btGjkCollisionDescription& colDesc, btDistanceInfoTemplate* distInfo)
+int btComputeGjkDistance(const btConvexTemplate& a, const btConvexTemplate& b,
+ const btGjkCollisionDescription& colDesc, btDistanceInfoTemplate* distInfo)
{
- btGjkEpaSolver3::sResults results;
- btVector3 guess = colDesc.m_firstDir;
-
- bool isSeparated = btGjkEpaSolver3_Distance( a,b,
- guess,
- results);
- if (isSeparated)
- {
- distInfo->m_distance = results.distance;
- distInfo->m_pointOnA= results.witnesses[0];
- distInfo->m_pointOnB= results.witnesses[1];
- distInfo->m_normalBtoA= results.normal;
- return 0;
- }
-
- return -1;
+ btGjkEpaSolver3::sResults results;
+ btVector3 guess = colDesc.m_firstDir;
+
+ bool isSeparated = btGjkEpaSolver3_Distance(a, b,
+ guess,
+ results);
+ if (isSeparated)
+ {
+ distInfo->m_distance = results.distance;
+ distInfo->m_pointOnA = results.witnesses[0];
+ distInfo->m_pointOnB = results.witnesses[1];
+ distInfo->m_normalBtoA = results.normal;
+ return 0;
+ }
+
+ return -1;
}
-/* Symbols cleanup */
+/* Symbols cleanup */
#undef GJK_MAX_ITERATIONS
#undef GJK_ACCURARY
@@ -1029,7 +1060,4 @@ int btComputeGjkDistance(const btConvexTemplate& a, const btConvexTemplate& b,
#undef EPA_PLANE_EPS
#undef EPA_INSIDE_EPS
-
-
-#endif //BT_GJK_EPA3_H
-
+#endif //BT_GJK_EPA3_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp
index b79f49d611..07629229ab 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp
@@ -18,23 +18,21 @@ subject to the following restrictions:
#include "BulletCollision/CollisionShapes/btConvexShape.h"
#include "btGjkEpaPenetrationDepthSolver.h"
-
#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
bool btGjkEpaPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& simplexSolver,
- const btConvexShape* pConvexA, const btConvexShape* pConvexB,
- const btTransform& transformA, const btTransform& transformB,
- btVector3& v, btVector3& wWitnessOnA, btVector3& wWitnessOnB,
- class btIDebugDraw* debugDraw)
+ const btConvexShape* pConvexA, const btConvexShape* pConvexB,
+ const btTransform& transformA, const btTransform& transformB,
+ btVector3& v, btVector3& wWitnessOnA, btVector3& wWitnessOnB,
+ class btIDebugDraw* debugDraw)
{
-
(void)debugDraw;
(void)v;
(void)simplexSolver;
btVector3 guessVectors[] = {
- btVector3(transformB.getOrigin() - transformA.getOrigin()).normalized(),
- btVector3(transformA.getOrigin() - transformB.getOrigin()).normalized(),
+ btVector3(transformB.getOrigin() - transformA.getOrigin()).safeNormalize(),
+ btVector3(transformA.getOrigin() - transformB.getOrigin()).safeNormalize(),
btVector3(0, 0, 1),
btVector3(0, 1, 0),
btVector3(1, 0, 0),
@@ -49,13 +47,13 @@ bool btGjkEpaPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& simp
for (int i = 0; i < numVectors; i++)
{
simplexSolver.reset();
- btVector3 guessVector = guessVectors[i];
+ btVector3 guessVector = guessVectors[i];
- btGjkEpaSolver2::sResults results;
+ btGjkEpaSolver2::sResults results;
if (btGjkEpaSolver2::Penetration(pConvexA, transformA,
- pConvexB, transformB,
- guessVector, results))
+ pConvexB, transformB,
+ guessVector, results))
{
wWitnessOnA = results.witnesses[0];
@@ -81,4 +79,3 @@ bool btGjkEpaPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& simp
v.setValue(0, 0, 0);
return false;
}
-
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h
index 1ed6340af3..92d6df1729 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h
@@ -23,21 +23,18 @@ subject to the following restrictions:
///calculate the penetration depth between two convex shapes.
class btGjkEpaPenetrationDepthSolver : public btConvexPenetrationDepthSolver
{
- public :
-
- btGjkEpaPenetrationDepthSolver()
- {
- }
-
- bool calcPenDepth( btSimplexSolverInterface& simplexSolver,
- const btConvexShape* pConvexA, const btConvexShape* pConvexB,
- const btTransform& transformA, const btTransform& transformB,
- btVector3& v, btVector3& wWitnessOnA, btVector3& wWitnessOnB,
- class btIDebugDraw* debugDraw);
-
- private :
-
+public:
+ btGjkEpaPenetrationDepthSolver()
+ {
+ }
+
+ bool calcPenDepth(btSimplexSolverInterface& simplexSolver,
+ const btConvexShape* pConvexA, const btConvexShape* pConvexB,
+ const btTransform& transformA, const btTransform& transformB,
+ btVector3& v, btVector3& wWitnessOnA, btVector3& wWitnessOnB,
+ class btIDebugDraw* debugDraw);
+
+private:
};
-#endif // BT_GJP_EPA_PENETRATION_DEPTH_H
-
+#endif // BT_GJP_EPA_PENETRATION_DEPTH_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp
index a0b825f0e8..803f6e0671 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp
@@ -18,75 +18,69 @@ subject to the following restrictions:
#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h"
#include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h"
-
-
-#if defined(DEBUG) || defined (_DEBUG)
+#if defined(DEBUG) || defined(_DEBUG)
//#define TEST_NON_VIRTUAL 1
-#include <stdio.h> //for debug printf
+#include <stdio.h> //for debug printf
#ifdef __SPU__
#include <spu_printf.h>
#define printf spu_printf
-#endif //__SPU__
+#endif //__SPU__
#endif
//must be above the machine epsilon
-#ifdef BT_USE_DOUBLE_PRECISION
- #define REL_ERROR2 btScalar(1.0e-12)
- btScalar gGjkEpaPenetrationTolerance = 1.0e-12;
+#ifdef BT_USE_DOUBLE_PRECISION
+#define REL_ERROR2 btScalar(1.0e-12)
+btScalar gGjkEpaPenetrationTolerance = 1.0e-12;
#else
- #define REL_ERROR2 btScalar(1.0e-6)
- btScalar gGjkEpaPenetrationTolerance = 0.001;
+#define REL_ERROR2 btScalar(1.0e-6)
+btScalar gGjkEpaPenetrationTolerance = 0.001;
#endif
-//temp globals, to improve GJK/EPA/penetration calculations
-int gNumDeepPenetrationChecks = 0;
-int gNumGjkChecks = 0;
-
-
-btGjkPairDetector::btGjkPairDetector(const btConvexShape* objectA,const btConvexShape* objectB,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver)
-:m_cachedSeparatingAxis(btScalar(0.),btScalar(1.),btScalar(0.)),
-m_penetrationDepthSolver(penetrationDepthSolver),
-m_simplexSolver(simplexSolver),
-m_minkowskiA(objectA),
-m_minkowskiB(objectB),
-m_shapeTypeA(objectA->getShapeType()),
-m_shapeTypeB(objectB->getShapeType()),
-m_marginA(objectA->getMargin()),
-m_marginB(objectB->getMargin()),
-m_ignoreMargin(false),
-m_lastUsedMethod(-1),
-m_catchDegeneracies(1),
-m_fixContactNormalDirection(1)
+
+btGjkPairDetector::btGjkPairDetector(const btConvexShape *objectA, const btConvexShape *objectB, btSimplexSolverInterface *simplexSolver, btConvexPenetrationDepthSolver *penetrationDepthSolver)
+ : m_cachedSeparatingAxis(btScalar(0.), btScalar(1.), btScalar(0.)),
+ m_penetrationDepthSolver(penetrationDepthSolver),
+ m_simplexSolver(simplexSolver),
+ m_minkowskiA(objectA),
+ m_minkowskiB(objectB),
+ m_shapeTypeA(objectA->getShapeType()),
+ m_shapeTypeB(objectB->getShapeType()),
+ m_marginA(objectA->getMargin()),
+ m_marginB(objectB->getMargin()),
+ m_ignoreMargin(false),
+ m_lastUsedMethod(-1),
+ m_catchDegeneracies(1),
+ m_fixContactNormalDirection(1)
{
}
-btGjkPairDetector::btGjkPairDetector(const btConvexShape* objectA,const btConvexShape* objectB,int shapeTypeA,int shapeTypeB,btScalar marginA, btScalar marginB, btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver)
-:m_cachedSeparatingAxis(btScalar(0.),btScalar(1.),btScalar(0.)),
-m_penetrationDepthSolver(penetrationDepthSolver),
-m_simplexSolver(simplexSolver),
-m_minkowskiA(objectA),
-m_minkowskiB(objectB),
-m_shapeTypeA(shapeTypeA),
-m_shapeTypeB(shapeTypeB),
-m_marginA(marginA),
-m_marginB(marginB),
-m_ignoreMargin(false),
-m_lastUsedMethod(-1),
-m_catchDegeneracies(1),
-m_fixContactNormalDirection(1)
+btGjkPairDetector::btGjkPairDetector(const btConvexShape *objectA, const btConvexShape *objectB, int shapeTypeA, int shapeTypeB, btScalar marginA, btScalar marginB, btSimplexSolverInterface *simplexSolver, btConvexPenetrationDepthSolver *penetrationDepthSolver)
+ : m_cachedSeparatingAxis(btScalar(0.), btScalar(1.), btScalar(0.)),
+ m_penetrationDepthSolver(penetrationDepthSolver),
+ m_simplexSolver(simplexSolver),
+ m_minkowskiA(objectA),
+ m_minkowskiB(objectB),
+ m_shapeTypeA(shapeTypeA),
+ m_shapeTypeB(shapeTypeB),
+ m_marginA(marginA),
+ m_marginB(marginB),
+ m_ignoreMargin(false),
+ m_lastUsedMethod(-1),
+ m_catchDegeneracies(1),
+ m_fixContactNormalDirection(1)
{
}
-void btGjkPairDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults)
+void btGjkPairDetector::getClosestPoints(const ClosestPointInput &input, Result &output, class btIDebugDraw *debugDraw, bool swapResults)
{
(void)swapResults;
- getClosestPointsNonVirtual(input,output,debugDraw);
+ getClosestPointsNonVirtual(input, output, debugDraw);
}
-static void btComputeSupport(const btConvexShape* convexA, const btTransform& localTransA, const btConvexShape* convexB, const btTransform& localTransB, const btVector3& dir, bool check2d, btVector3& supAworld, btVector3& supBworld, btVector3& aMinb)
+static void btComputeSupport(const btConvexShape *convexA, const btTransform &localTransA, const btConvexShape *convexB, const btTransform &localTransB, const btVector3 &dir, bool check2d, btVector3 &supAworld, btVector3 &supBworld, btVector3 &aMinb)
{
- btVector3 seperatingAxisInA = (dir)* localTransA.getBasis();
- btVector3 seperatingAxisInB = (-dir)* localTransB.getBasis();
+ btVector3 seperatingAxisInA = (dir)*localTransA.getBasis();
+ btVector3 seperatingAxisInB = (-dir) * localTransB.getBasis();
btVector3 pInANoMargin = convexA->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA);
btVector3 qInBNoMargin = convexB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB);
@@ -106,22 +100,21 @@ static void btComputeSupport(const btConvexShape* convexA, const btTransform& lo
aMinb = supAworld - supBworld;
}
-struct btSupportVector
+struct btSupportVector
{
- btVector3 v; //!< Support point in minkowski sum
- btVector3 v1; //!< Support point in obj1
- btVector3 v2; //!< Support point in obj2
+ btVector3 v; //!< Support point in minkowski sum
+ btVector3 v1; //!< Support point in obj1
+ btVector3 v2; //!< Support point in obj2
};
-struct btSimplex
+struct btSimplex
{
btSupportVector ps[4];
- int last; //!< index of last added point
+ int last; //!< index of last added point
};
static btVector3 ccd_vec3_origin(0, 0, 0);
-
inline void btSimplexInit(btSimplex *s)
{
s->last = -1;
@@ -142,19 +135,18 @@ inline void btSupportCopy(btSupportVector *d, const btSupportVector *s)
*d = *s;
}
-inline void btVec3Copy(btVector3 *v, const btVector3* w)
+inline void btVec3Copy(btVector3 *v, const btVector3 *w)
{
*v = *w;
}
-inline void ccdVec3Add(btVector3*v, const btVector3*w)
+inline void ccdVec3Add(btVector3 *v, const btVector3 *w)
{
v->m_floats[0] += w->m_floats[0];
v->m_floats[1] += w->m_floats[1];
v->m_floats[2] += w->m_floats[2];
}
-
inline void ccdVec3Sub(btVector3 *v, const btVector3 *w)
{
*v -= *w;
@@ -162,24 +154,22 @@ inline void ccdVec3Sub(btVector3 *v, const btVector3 *w)
inline void btVec3Sub2(btVector3 *d, const btVector3 *v, const btVector3 *w)
{
*d = (*v) - (*w);
-
}
-inline btScalar btVec3Dot(const btVector3 *a, const btVector3 *b)
+inline btScalar btVec3Dot(const btVector3 *a, const btVector3 *b)
{
btScalar dot;
dot = a->dot(*b);
-
+
return dot;
}
-inline btScalar ccdVec3Dist2(const btVector3 *a, const btVector3*b)
+inline btScalar ccdVec3Dist2(const btVector3 *a, const btVector3 *b)
{
btVector3 ab;
btVec3Sub2(&ab, a, b);
return btVec3Dot(&ab, &ab);
}
-
inline void btVec3Scale(btVector3 *d, btScalar k)
{
d->m_floats[0] *= k;
@@ -195,7 +185,7 @@ inline void btVec3Cross(btVector3 *d, const btVector3 *a, const btVector3 *b)
}
inline void btTripleCross(const btVector3 *a, const btVector3 *b,
- const btVector3 *c, btVector3 *d)
+ const btVector3 *c, btVector3 *d)
{
btVector3 e;
btVec3Cross(&e, a, b);
@@ -213,36 +203,35 @@ inline int ccdEq(btScalar _a, btScalar _b)
a = btFabs(_a);
b = btFabs(_b);
- if (b > a) {
+ if (b > a)
+ {
return ab < SIMD_EPSILON * b;
}
- else {
+ else
+ {
return ab < SIMD_EPSILON * a;
}
}
-btScalar ccdVec3X(const btVector3* v)
+btScalar ccdVec3X(const btVector3 *v)
{
return v->x();
}
-btScalar ccdVec3Y(const btVector3* v)
+btScalar ccdVec3Y(const btVector3 *v)
{
return v->y();
}
-btScalar ccdVec3Z(const btVector3* v)
+btScalar ccdVec3Z(const btVector3 *v)
{
return v->z();
}
inline int btVec3Eq(const btVector3 *a, const btVector3 *b)
{
- return ccdEq(ccdVec3X(a), ccdVec3X(b))
- && ccdEq(ccdVec3Y(a), ccdVec3Y(b))
- && ccdEq(ccdVec3Z(a), ccdVec3Z(b));
+ return ccdEq(ccdVec3X(a), ccdVec3X(b)) && ccdEq(ccdVec3Y(a), ccdVec3Y(b)) && ccdEq(ccdVec3Z(a), ccdVec3Z(b));
}
-
inline void btSimplexAdd(btSimplex *s, const btSupportVector *v)
{
// here is no check on boundaries in sake of speed
@@ -250,7 +239,6 @@ inline void btSimplexAdd(btSimplex *s, const btSupportVector *v)
btSupportCopy(s->ps + s->last, v);
}
-
inline void btSimplexSet(btSimplex *s, size_t pos, const btSupportVector *a)
{
btSupportCopy(s->ps + pos, a);
@@ -268,27 +256,28 @@ inline const btSupportVector *ccdSimplexLast(const btSimplex *s)
inline int ccdSign(btScalar val)
{
- if (btFuzzyZero(val)) {
+ if (btFuzzyZero(val))
+ {
return 0;
}
- else if (val < btScalar(0)) {
+ else if (val < btScalar(0))
+ {
return -1;
}
return 1;
}
-
inline btScalar btVec3PointSegmentDist2(const btVector3 *P,
- const btVector3 *x0,
- const btVector3 *b,
- btVector3 *witness)
+ const btVector3 *x0,
+ const btVector3 *b,
+ btVector3 *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
@@ -310,24 +299,29 @@ inline btScalar btVec3PointSegmentDist2(const btVector3 *P,
t = -btScalar(1.) * btVec3Dot(&a, &d);
t /= btVec3Dot(&d, &d);
- if (t < btScalar(0) || btFuzzyZero(t)) {
+ if (t < btScalar(0) || btFuzzyZero(t))
+ {
dist = ccdVec3Dist2(x0, P);
if (witness)
btVec3Copy(witness, x0);
}
- else if (t > btScalar(1) || ccdEq(t, btScalar(1))) {
+ else if (t > btScalar(1) || ccdEq(t, btScalar(1)))
+ {
dist = ccdVec3Dist2(b, P);
if (witness)
btVec3Copy(witness, b);
}
- else {
- if (witness) {
+ else
+ {
+ if (witness)
+ {
btVec3Copy(witness, &d);
btVec3Scale(witness, t);
ccdVec3Add(witness, x0);
dist = ccdVec3Dist2(witness, P);
}
- else {
+ else
+ {
// recycling variables
btVec3Scale(&d, t);
ccdVec3Add(&d, &a);
@@ -338,11 +332,10 @@ inline btScalar btVec3PointSegmentDist2(const btVector3 *P,
return dist;
}
-
btScalar btVec3PointTriDist2(const btVector3 *P,
- const btVector3 *x0, const btVector3 *B,
- const btVector3 *C,
- btVector3 *witness)
+ const btVector3 *x0, const btVector3 *B,
+ const btVector3 *C,
+ btVector3 *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
@@ -372,13 +365,9 @@ btScalar btVec3PointTriDist2(const btVector3 *P,
s = (q * r - w * p) / (w * v - r * r);
t = (-s * r - q) / w;
- if ((btFuzzyZero(s) || s > btScalar(0))
- && (ccdEq(s, btScalar(1)) || s < btScalar(1))
- && (btFuzzyZero(t) || t > btScalar(0))
- && (ccdEq(t, btScalar(1)) || t < btScalar(1))
- && (ccdEq(t + s, btScalar(1)) || t + s < btScalar(1))) {
-
- if (witness)
+ if ((btFuzzyZero(s) || s > btScalar(0)) && (ccdEq(s, btScalar(1)) || s < btScalar(1)) && (btFuzzyZero(t) || t > btScalar(0)) && (ccdEq(t, btScalar(1)) || t < btScalar(1)) && (ccdEq(t + s, btScalar(1)) || t + s < btScalar(1)))
+ {
+ if (witness)
{
btVec3Scale(&d1, s);
btVec3Scale(&d2, t);
@@ -388,7 +377,7 @@ btScalar btVec3PointTriDist2(const btVector3 *P,
dist = ccdVec3Dist2(witness, P);
}
- else
+ else
{
dist = s * s * v;
dist += t * t * w;
@@ -398,18 +387,21 @@ btScalar btVec3PointTriDist2(const btVector3 *P,
dist += u;
}
}
- else {
+ else
+ {
dist = btVec3PointSegmentDist2(P, x0, B, witness);
dist2 = btVec3PointSegmentDist2(P, x0, C, &witness2);
- if (dist2 < dist) {
+ if (dist2 < dist)
+ {
dist = dist2;
if (witness)
btVec3Copy(witness, &witness2);
}
dist2 = btVec3PointSegmentDist2(P, B, C, &witness2);
- if (dist2 < dist) {
+ if (dist2 < dist)
+ {
dist = dist2;
if (witness)
btVec3Copy(witness, &witness2);
@@ -419,7 +411,6 @@ btScalar btVec3PointTriDist2(const btVector3 *P,
return dist;
}
-
static int btDoSimplex2(btSimplex *simplex, btVector3 *dir)
{
const btSupportVector *A, *B;
@@ -441,18 +432,21 @@ static int btDoSimplex2(btSimplex *simplex, btVector3 *dir)
// check if origin doesn't lie on AB segment
btVec3Cross(&tmp, &AB, &AO);
- if (btFuzzyZero(btVec3Dot(&tmp, &tmp)) && dot > btScalar(0)) {
+ if (btFuzzyZero(btVec3Dot(&tmp, &tmp)) && dot > btScalar(0))
+ {
return 1;
}
// check if origin is in area where AB segment is
- if (btFuzzyZero(dot) || dot < btScalar(0)) {
+ if (btFuzzyZero(dot) || dot < btScalar(0))
+ {
// origin is in outside are of A
btSimplexSet(simplex, 0, A);
btSimplexSetSize(simplex, 1);
btVec3Copy(dir, &AO);
}
- else {
+ else
+ {
// origin is in area where AB segment is
// keep simplex untouched and set direction to
@@ -463,8 +457,6 @@ static int btDoSimplex2(btSimplex *simplex, btVector3 *dir)
return 0;
}
-
-
static int btDoSimplex3(btSimplex *simplex, btVector3 *dir)
{
const btSupportVector *A, *B, *C;
@@ -479,13 +471,15 @@ static int btDoSimplex3(btSimplex *simplex, btVector3 *dir)
// check touching contact
dist = btVec3PointTriDist2(&ccd_vec3_origin, &A->v, &B->v, &C->v, 0);
- if (btFuzzyZero(dist)) {
+ if (btFuzzyZero(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 (btVec3Eq(&A->v, &B->v) || btVec3Eq(&A->v, &C->v)) {
+ if (btVec3Eq(&A->v, &B->v) || btVec3Eq(&A->v, &C->v))
+ {
return -1;
}
@@ -500,54 +494,64 @@ static int btDoSimplex3(btSimplex *simplex, btVector3 *dir)
btVec3Cross(&tmp, &ABC, &AC);
dot = btVec3Dot(&tmp, &AO);
- if (btFuzzyZero(dot) || dot > btScalar(0)) {
+ if (btFuzzyZero(dot) || dot > btScalar(0))
+ {
dot = btVec3Dot(&AC, &AO);
- if (btFuzzyZero(dot) || dot > btScalar(0)) {
+ if (btFuzzyZero(dot) || dot > btScalar(0))
+ {
// C is already in place
btSimplexSet(simplex, 1, A);
btSimplexSetSize(simplex, 2);
btTripleCross(&AC, &AO, &AC, dir);
}
- else {
-
+ else
+ {
dot = btVec3Dot(&AB, &AO);
- if (btFuzzyZero(dot) || dot > btScalar(0)) {
+ if (btFuzzyZero(dot) || dot > btScalar(0))
+ {
btSimplexSet(simplex, 0, B);
btSimplexSet(simplex, 1, A);
btSimplexSetSize(simplex, 2);
btTripleCross(&AB, &AO, &AB, dir);
}
- else {
+ else
+ {
btSimplexSet(simplex, 0, A);
btSimplexSetSize(simplex, 1);
btVec3Copy(dir, &AO);
}
}
}
- else {
+ else
+ {
btVec3Cross(&tmp, &AB, &ABC);
dot = btVec3Dot(&tmp, &AO);
- if (btFuzzyZero(dot) || dot > btScalar(0))
+ if (btFuzzyZero(dot) || dot > btScalar(0))
{
dot = btVec3Dot(&AB, &AO);
- if (btFuzzyZero(dot) || dot > btScalar(0)) {
+ if (btFuzzyZero(dot) || dot > btScalar(0))
+ {
btSimplexSet(simplex, 0, B);
btSimplexSet(simplex, 1, A);
btSimplexSetSize(simplex, 2);
btTripleCross(&AB, &AO, &AB, dir);
}
- else {
+ else
+ {
btSimplexSet(simplex, 0, A);
btSimplexSetSize(simplex, 1);
btVec3Copy(dir, &AO);
}
}
- else {
+ else
+ {
dot = btVec3Dot(&ABC, &AO);
- if (btFuzzyZero(dot) || dot > btScalar(0)) {
+ if (btFuzzyZero(dot) || dot > btScalar(0))
+ {
btVec3Copy(dir, &ABC);
}
- else {
+ else
+ {
btSupportVector tmp;
btSupportCopy(&tmp, C);
btSimplexSet(simplex, 0, B);
@@ -581,7 +585,8 @@ static int btDoSimplex4(btSimplex *simplex, btVector3 *dir)
// if it is not simplex can't be expanded and thus no intersection is
// found
dist = btVec3PointTriDist2(&A->v, &B->v, &C->v, &D->v, 0);
- if (btFuzzyZero(dist)) {
+ if (btFuzzyZero(dist))
+ {
return -1;
}
@@ -622,12 +627,14 @@ static int btDoSimplex4(btSimplex *simplex, btVector3 *dir)
AC_O = ccdSign(btVec3Dot(&ADB, &AO)) == C_on_ADB;
AD_O = ccdSign(btVec3Dot(&ABC, &AO)) == D_on_ABC;
- if (AB_O && AC_O && AD_O) {
+ if (AB_O && AC_O && AD_O)
+ {
// origin is in tetrahedron
return 1;
// rearrange simplex to triangle and call btDoSimplex3()
}
- else if (!AB_O) {
+ 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
@@ -636,14 +643,16 @@ static int btDoSimplex4(btSimplex *simplex, btVector3 *dir)
btSimplexSet(simplex, 2, A);
btSimplexSetSize(simplex, 3);
}
- else if (!AC_O) {
+ else if (!AC_O)
+ {
// C is farthest
btSimplexSet(simplex, 1, D);
btSimplexSet(simplex, 0, B);
btSimplexSet(simplex, 2, A);
btSimplexSetSize(simplex, 3);
}
- else { // (!AD_O)
+ else
+ { // (!AD_O)
btSimplexSet(simplex, 0, C);
btSimplexSet(simplex, 1, B);
btSimplexSet(simplex, 2, A);
@@ -655,36 +664,39 @@ static int btDoSimplex4(btSimplex *simplex, btVector3 *dir)
static int btDoSimplex(btSimplex *simplex, btVector3 *dir)
{
- if (btSimplexSize(simplex) == 2) {
+ if (btSimplexSize(simplex) == 2)
+ {
// simplex contains segment only one segment
return btDoSimplex2(simplex, dir);
}
- else if (btSimplexSize(simplex) == 3) {
+ else if (btSimplexSize(simplex) == 3)
+ {
// simplex contains triangle
return btDoSimplex3(simplex, dir);
}
- else { // btSimplexSize(simplex) == 4
- // tetrahedron - this is the only shape which can encapsule origin
- // so btDoSimplex4() also contains test on it
+ else
+ { // btSimplexSize(simplex) == 4
+ // tetrahedron - this is the only shape which can encapsule origin
+ // so btDoSimplex4() also contains test on it
return btDoSimplex4(simplex, dir);
}
}
#ifdef __SPU__
-void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw)
+void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput &input, Result &output, class btIDebugDraw *debugDraw)
#else
-void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput& input, Result& output, class btIDebugDraw* debugDraw)
+void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput &input, Result &output, class btIDebugDraw *debugDraw)
#endif
{
m_cachedSeparatingDistance = 0.f;
- btScalar distance=btScalar(0.);
- btVector3 normalInB(btScalar(0.),btScalar(0.),btScalar(0.));
+ btScalar distance = btScalar(0.);
+ btVector3 normalInB(btScalar(0.), btScalar(0.), btScalar(0.));
- btVector3 pointOnA,pointOnB;
- btTransform localTransA = input.m_transformA;
+ btVector3 pointOnA, pointOnB;
+ btTransform localTransA = input.m_transformA;
btTransform localTransB = input.m_transformB;
- btVector3 positionOffset=(localTransA.getOrigin() + localTransB.getOrigin()) * btScalar(0.5);
+ btVector3 positionOffset = (localTransA.getOrigin() + localTransB.getOrigin()) * btScalar(0.5);
localTransA.getOrigin() -= positionOffset;
localTransB.getOrigin() -= positionOffset;
@@ -693,7 +705,6 @@ void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput& inpu
btScalar marginA = m_marginA;
btScalar marginB = m_marginB;
- gNumGjkChecks++;
//for CCD we don't use margins
if (m_ignoreMargin)
@@ -703,19 +714,19 @@ void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput& inpu
}
m_curIter = 0;
- int gGjkMaxIter = 1000;//this is to catch invalid input, perhaps check for #NaN?
- m_cachedSeparatingAxis.setValue(0,1,0);
+ int gGjkMaxIter = 1000; //this is to catch invalid input, perhaps check for #NaN?
+ m_cachedSeparatingAxis.setValue(0, 1, 0);
bool isValid = false;
bool checkSimplex = false;
bool checkPenetration = true;
m_degenerateSimplex = 0;
-
+
m_lastUsedMethod = -1;
int status = -2;
btVector3 orgNormalInB(0, 0, 0);
btScalar margin = marginA + marginB;
-
+
//we add a separate implementation to check if the convex shapes intersect
//See also "Real-time Collision Detection with Implicit Objects" by Leif Olvang
//Todo: integrate the simplex penetration check directly inside the Bullet btVoronoiSimplexSolver
@@ -726,22 +737,18 @@ void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput& inpu
btScalar squaredDistance = BT_LARGE_FLOAT;
btScalar delta = btScalar(0.);
-
-
-
btSimplex simplex1;
- btSimplex* simplex = &simplex1;
+ btSimplex *simplex = &simplex1;
btSimplexInit(simplex);
btVector3 dir(1, 0, 0);
{
-
btVector3 lastSupV;
btVector3 supAworld;
btVector3 supBworld;
btComputeSupport(m_minkowskiA, localTransA, m_minkowskiB, localTransB, dir, check2d, supAworld, supBworld, lastSupV);
-
+
btSupportVector last;
last.v = lastSupV;
last.v1 = supAworld;
@@ -751,10 +758,8 @@ void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput& inpu
dir = -lastSupV;
-
-
// start iterations
- for (int iterations = 0; iterations <gGjkMaxIter; iterations++)
+ for (int iterations = 0; iterations < gGjkMaxIter; iterations++)
{
// obtain support point
btComputeSupport(m_minkowskiA, localTransA, m_minkowskiB, localTransB, dir, check2d, supAworld, supBworld, lastSupV);
@@ -769,7 +774,7 @@ void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput& inpu
status = -1;
break;
}
-
+
// add last support vector to simplex
last.v = lastSupV;
last.v1 = supAworld;
@@ -781,21 +786,21 @@ void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput& inpu
// intersect and 0 if algorithm should continue
btVector3 newDir;
- int do_simplex_res = btDoSimplex(simplex, &dir);
+ int do_simplex_res = btDoSimplex(simplex, &dir);
- if (do_simplex_res == 1)
+ if (do_simplex_res == 1)
{
- status = 0; // intersection found
+ status = 0; // intersection found
break;
}
- else if (do_simplex_res == -1)
+ else if (do_simplex_res == -1)
{
// intersection not found
status = -1;
break;
}
-
- if (btFuzzyZero(btVec3Dot(&dir, &dir)))
+
+ if (btFuzzyZero(btVec3Dot(&dir, &dir)))
{
// intersection not found
status = -1;
@@ -815,7 +820,6 @@ void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput& inpu
break;
}
}
-
}
m_simplexSolver->reset();
@@ -825,27 +829,24 @@ void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput& inpu
//printf("Intersect!\n");
}
- if (status==-1)
+ if (status == -1)
{
//printf("not intersect\n");
}
//printf("dir=%f,%f,%f\n",dir[0],dir[1],dir[2]);
if (1)
{
- for (; ; )
- //while (true)
+ for (;;)
+ //while (true)
{
-
- btVector3 seperatingAxisInA = (-m_cachedSeparatingAxis)* localTransA.getBasis();
- btVector3 seperatingAxisInB = m_cachedSeparatingAxis* localTransB.getBasis();
-
+ btVector3 seperatingAxisInA = (-m_cachedSeparatingAxis) * localTransA.getBasis();
+ btVector3 seperatingAxisInB = m_cachedSeparatingAxis * localTransB.getBasis();
btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA);
btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB);
- btVector3 pWorld = localTransA(pInA);
- btVector3 qWorld = localTransB(qInB);
-
+ btVector3 pWorld = localTransA(pInA);
+ btVector3 qWorld = localTransB(qInB);
if (check2d)
{
@@ -921,8 +922,7 @@ void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput& inpu
checkSimplex = false;
break;
}
-#endif //
-
+#endif //
//redundant m_simplexSolver->compute_points(pointOnA, pointOnB);
@@ -938,33 +938,31 @@ void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput& inpu
m_cachedSeparatingAxis = newCachedSeparatingAxis;
- //degeneracy, this is typically due to invalid/uninitialized worldtransforms for a btCollisionObject
+ //degeneracy, this is typically due to invalid/uninitialized worldtransforms for a btCollisionObject
if (m_curIter++ > gGjkMaxIter)
{
-#if defined(DEBUG) || defined (_DEBUG)
+#if defined(DEBUG) || defined(_DEBUG)
printf("btGjkPairDetector maxIter exceeded:%i\n", m_curIter);
printf("sepAxis=(%f,%f,%f), squaredDistance = %f, shapeTypeA=%i,shapeTypeB=%i\n",
- m_cachedSeparatingAxis.getX(),
- m_cachedSeparatingAxis.getY(),
- m_cachedSeparatingAxis.getZ(),
- squaredDistance,
- m_minkowskiA->getShapeType(),
- m_minkowskiB->getShapeType());
-
-#endif
- break;
+ m_cachedSeparatingAxis.getX(),
+ m_cachedSeparatingAxis.getY(),
+ m_cachedSeparatingAxis.getZ(),
+ squaredDistance,
+ m_minkowskiA->getShapeType(),
+ m_minkowskiB->getShapeType());
+#endif
+ break;
}
-
bool check = (!m_simplexSolver->fullSimplex());
//bool check = (!m_simplexSolver->fullSimplex() && squaredDistance > SIMD_EPSILON * m_simplexSolver->maxVertex());
if (!check)
{
//do we need this backup_closest here ?
- // m_simplexSolver->backup_closest(m_cachedSeparatingAxis);
+ // m_simplexSolver->backup_closest(m_cachedSeparatingAxis);
m_degenerateSimplex = 13;
break;
}
@@ -972,20 +970,20 @@ void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput& inpu
if (checkSimplex)
{
- m_simplexSolver->compute_points(pointOnA, pointOnB);
- normalInB = m_cachedSeparatingAxis;
+ m_simplexSolver->compute_points(pointOnA, pointOnB);
+ normalInB = m_cachedSeparatingAxis;
+
+ btScalar lenSqr = m_cachedSeparatingAxis.length2();
- btScalar lenSqr =m_cachedSeparatingAxis.length2();
-
//valid normal
if (lenSqr < REL_ERROR2)
{
m_degenerateSimplex = 5;
}
- if (lenSqr > SIMD_EPSILON*SIMD_EPSILON)
+ if (lenSqr > SIMD_EPSILON * SIMD_EPSILON)
{
btScalar rlen = btScalar(1.) / btSqrt(lenSqr);
- normalInB *= rlen; //normalize
+ normalInB *= rlen; //normalize
btScalar s = btSqrt(squaredDistance);
@@ -1005,13 +1003,11 @@ void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput& inpu
}
}
-
-
- bool catchDegeneratePenetrationCase =
- (m_catchDegeneracies && m_penetrationDepthSolver && m_degenerateSimplex && ((distance+margin) < gGjkEpaPenetrationTolerance));
+ bool catchDegeneratePenetrationCase =
+ (m_catchDegeneracies && m_penetrationDepthSolver && m_degenerateSimplex && ((distance + margin) < gGjkEpaPenetrationTolerance));
//if (checkPenetration && !isValid)
- if ((checkPenetration && (!isValid || catchDegeneratePenetrationCase )) || (status == 0))
+ if ((checkPenetration && (!isValid || catchDegeneratePenetrationCase)) || (status == 0))
{
//penetration case
@@ -1019,19 +1015,16 @@ void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput& inpu
if (m_penetrationDepthSolver)
{
// Penetration depth case.
- btVector3 tmpPointOnA,tmpPointOnB;
-
- gNumDeepPenetrationChecks++;
+ btVector3 tmpPointOnA, tmpPointOnB;
+
m_cachedSeparatingAxis.setZero();
- bool isValid2 = m_penetrationDepthSolver->calcPenDepth(
- *m_simplexSolver,
- m_minkowskiA,m_minkowskiB,
- localTransA,localTransB,
+ bool isValid2 = m_penetrationDepthSolver->calcPenDepth(
+ *m_simplexSolver,
+ m_minkowskiA, m_minkowskiB,
+ localTransA, localTransB,
m_cachedSeparatingAxis, tmpPointOnA, tmpPointOnB,
- debugDraw
- );
-
+ debugDraw);
if (m_cachedSeparatingAxis.length2())
{
@@ -1039,13 +1032,13 @@ void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput& inpu
{
btVector3 tmpNormalInB = tmpPointOnB - tmpPointOnA;
btScalar lenSqr = tmpNormalInB.length2();
- if (lenSqr <= (SIMD_EPSILON*SIMD_EPSILON))
+ if (lenSqr <= (SIMD_EPSILON * SIMD_EPSILON))
{
tmpNormalInB = m_cachedSeparatingAxis;
lenSqr = m_cachedSeparatingAxis.length2();
}
- if (lenSqr > (SIMD_EPSILON*SIMD_EPSILON))
+ if (lenSqr > (SIMD_EPSILON * SIMD_EPSILON))
{
tmpNormalInB /= btSqrt(lenSqr);
btScalar distance2 = -(tmpPointOnA - tmpPointOnB).length();
@@ -1058,7 +1051,6 @@ void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput& inpu
pointOnB = tmpPointOnB;
normalInB = tmpNormalInB;
isValid = true;
-
}
else
{
@@ -1079,7 +1071,6 @@ void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput& inpu
///thanks to Jacob.Langford for the reproduction case
///http://code.google.com/p/bullet/issues/detail?id=250
-
if (m_cachedSeparatingAxis.length2() > btScalar(0.))
{
btScalar distance2 = (tmpPointOnA - tmpPointOnB).length() - margin;
@@ -1103,109 +1094,90 @@ void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput& inpu
}
}
}
- } else
+ }
+ else
{
//printf("EPA didn't return a valid value\n");
}
-
}
-
}
}
-
-
- if (isValid && ((distance < 0) || (distance*distance < input.m_maximumDistanceSquared)))
+ if (isValid && ((distance < 0) || (distance * distance < input.m_maximumDistanceSquared)))
{
-
m_cachedSeparatingAxis = normalInB;
m_cachedSeparatingDistance = distance;
if (1)
{
- ///todo: need to track down this EPA penetration solver degeneracy
- ///the penetration solver reports penetration but the contact normal
- ///connecting the contact points is pointing in the opposite direction
- ///until then, detect the issue and revert the normal
+ ///todo: need to track down this EPA penetration solver degeneracy
+ ///the penetration solver reports penetration but the contact normal
+ ///connecting the contact points is pointing in the opposite direction
+ ///until then, detect the issue and revert the normal
btScalar d2 = 0.f;
{
- btVector3 seperatingAxisInA = (-orgNormalInB)* localTransA.getBasis();
- btVector3 seperatingAxisInB = orgNormalInB* localTransB.getBasis();
-
+ btVector3 seperatingAxisInA = (-orgNormalInB) * localTransA.getBasis();
+ btVector3 seperatingAxisInB = orgNormalInB * localTransB.getBasis();
btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA);
btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB);
- btVector3 pWorld = localTransA(pInA);
- btVector3 qWorld = localTransB(qInB);
+ btVector3 pWorld = localTransA(pInA);
+ btVector3 qWorld = localTransB(qInB);
btVector3 w = pWorld - qWorld;
- d2 = orgNormalInB.dot(w)- margin;
+ d2 = orgNormalInB.dot(w) - margin;
}
-
- btScalar d1=0;
+
+ btScalar d1 = 0;
{
-
- btVector3 seperatingAxisInA = (normalInB)* localTransA.getBasis();
- btVector3 seperatingAxisInB = -normalInB* localTransB.getBasis();
-
+ btVector3 seperatingAxisInA = (normalInB)*localTransA.getBasis();
+ btVector3 seperatingAxisInB = -normalInB * localTransB.getBasis();
btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA);
btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB);
- btVector3 pWorld = localTransA(pInA);
- btVector3 qWorld = localTransB(qInB);
- btVector3 w = pWorld - qWorld;
- d1 = (-normalInB).dot(w)- margin;
-
+ btVector3 pWorld = localTransA(pInA);
+ btVector3 qWorld = localTransB(qInB);
+ btVector3 w = pWorld - qWorld;
+ d1 = (-normalInB).dot(w) - margin;
}
btScalar d0 = 0.f;
{
- btVector3 seperatingAxisInA = (-normalInB)* input.m_transformA.getBasis();
- btVector3 seperatingAxisInB = normalInB* input.m_transformB.getBasis();
-
+ btVector3 seperatingAxisInA = (-normalInB) * input.m_transformA.getBasis();
+ btVector3 seperatingAxisInB = normalInB * input.m_transformB.getBasis();
btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA);
btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB);
- btVector3 pWorld = localTransA(pInA);
- btVector3 qWorld = localTransB(qInB);
- btVector3 w = pWorld - qWorld;
- d0 = normalInB.dot(w)-margin;
+ btVector3 pWorld = localTransA(pInA);
+ btVector3 qWorld = localTransB(qInB);
+ btVector3 w = pWorld - qWorld;
+ d0 = normalInB.dot(w) - margin;
}
-
- if (d1>d0)
+
+ if (d1 > d0)
{
m_lastUsedMethod = 10;
- normalInB*=-1;
- }
+ normalInB *= -1;
+ }
if (orgNormalInB.length2())
{
if (d2 > d0 && d2 > d1 && d2 > distance)
{
-
normalInB = orgNormalInB;
distance = d2;
}
}
}
-
output.addContactPoint(
normalInB,
- pointOnB+positionOffset,
+ pointOnB + positionOffset,
distance);
-
}
else
{
//printf("invalid gjk query\n");
}
-
-
}
-
-
-
-
-
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h
index feeae68621..659b63551e 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h
@@ -13,9 +13,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
-
-
#ifndef BT_GJK_PAIR_DETECTOR_H
#define BT_GJK_PAIR_DETECTOR_H
@@ -29,39 +26,34 @@ class btConvexPenetrationDepthSolver;
/// btGjkPairDetector uses GJK to implement the btDiscreteCollisionDetectorInterface
class btGjkPairDetector : public btDiscreteCollisionDetectorInterface
{
-
-
- btVector3 m_cachedSeparatingAxis;
- btConvexPenetrationDepthSolver* m_penetrationDepthSolver;
+ btVector3 m_cachedSeparatingAxis;
+ btConvexPenetrationDepthSolver* m_penetrationDepthSolver;
btSimplexSolverInterface* m_simplexSolver;
const btConvexShape* m_minkowskiA;
const btConvexShape* m_minkowskiB;
- int m_shapeTypeA;
+ int m_shapeTypeA;
int m_shapeTypeB;
- btScalar m_marginA;
- btScalar m_marginB;
+ btScalar m_marginA;
+ btScalar m_marginB;
- bool m_ignoreMargin;
- btScalar m_cachedSeparatingDistance;
-
+ bool m_ignoreMargin;
+ btScalar m_cachedSeparatingDistance;
public:
-
//some debugging to fix degeneracy problems
- int m_lastUsedMethod;
- int m_curIter;
- int m_degenerateSimplex;
- int m_catchDegeneracies;
- int m_fixContactNormalDirection;
+ int m_lastUsedMethod;
+ int m_curIter;
+ int m_degenerateSimplex;
+ int m_catchDegeneracies;
+ int m_fixContactNormalDirection;
- btGjkPairDetector(const btConvexShape* objectA,const btConvexShape* objectB,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver);
- btGjkPairDetector(const btConvexShape* objectA,const btConvexShape* objectB,int shapeTypeA,int shapeTypeB,btScalar marginA, btScalar marginB, btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver);
- virtual ~btGjkPairDetector() {};
+ btGjkPairDetector(const btConvexShape* objectA, const btConvexShape* objectB, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* penetrationDepthSolver);
+ btGjkPairDetector(const btConvexShape* objectA, const btConvexShape* objectB, int shapeTypeA, int shapeTypeB, btScalar marginA, btScalar marginB, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* penetrationDepthSolver);
+ virtual ~btGjkPairDetector(){};
- virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false);
+ virtual void getClosestPoints(const ClosestPointInput& input, Result& output, class btIDebugDraw* debugDraw, bool swapResults = false);
- void getClosestPointsNonVirtual(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw);
-
+ void getClosestPointsNonVirtual(const ClosestPointInput& input, Result& output, class btIDebugDraw* debugDraw);
void setMinkowskiA(const btConvexShape* minkA)
{
@@ -81,23 +73,21 @@ public:
{
return m_cachedSeparatingAxis;
}
- btScalar getCachedSeparatingDistance() const
+ btScalar getCachedSeparatingDistance() const
{
return m_cachedSeparatingDistance;
}
- void setPenetrationDepthSolver(btConvexPenetrationDepthSolver* penetrationDepthSolver)
+ void setPenetrationDepthSolver(btConvexPenetrationDepthSolver* penetrationDepthSolver)
{
m_penetrationDepthSolver = penetrationDepthSolver;
}
///don't use setIgnoreMargin, it's for Bullet's internal use
- void setIgnoreMargin(bool ignoreMargin)
+ void setIgnoreMargin(bool ignoreMargin)
{
m_ignoreMargin = ignoreMargin;
}
-
-
};
-#endif //BT_GJK_PAIR_DETECTOR_H
+#endif //BT_GJK_PAIR_DETECTOR_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h
index 571ad2c5f7..6d21f66202 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h
@@ -20,161 +20,152 @@ subject to the following restrictions:
#include "LinearMath/btTransformUtil.h"
#ifdef PFX_USE_FREE_VECTORMATH
- #include "physics_effects/base_level/solver/pfx_constraint_row.h"
+#include "physics_effects/base_level/solver/pfx_constraint_row.h"
typedef sce::PhysicsEffects::PfxConstraintRow btConstraintRow;
#else
- // Don't change following order of parameters
- ATTRIBUTE_ALIGNED16(struct) btConstraintRow {
- btScalar m_normal[3];
- btScalar m_rhs;
- btScalar m_jacDiagInv;
- btScalar m_lowerLimit;
- btScalar m_upperLimit;
- btScalar m_accumImpulse;
- };
- typedef btConstraintRow PfxConstraintRow;
-#endif //PFX_USE_FREE_VECTORMATH
+// Don't change following order of parameters
+ATTRIBUTE_ALIGNED16(struct)
+btConstraintRow
+{
+ btScalar m_normal[3];
+ btScalar m_rhs;
+ btScalar m_jacDiagInv;
+ btScalar m_lowerLimit;
+ btScalar m_upperLimit;
+ btScalar m_accumImpulse;
+};
+typedef btConstraintRow PfxConstraintRow;
+#endif //PFX_USE_FREE_VECTORMATH
enum btContactPointFlags
{
- BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED=1,
- BT_CONTACT_FLAG_HAS_CONTACT_CFM=2,
- BT_CONTACT_FLAG_HAS_CONTACT_ERP=4,
- BT_CONTACT_FLAG_CONTACT_STIFFNESS_DAMPING = 8,
+ BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED = 1,
+ BT_CONTACT_FLAG_HAS_CONTACT_CFM = 2,
+ BT_CONTACT_FLAG_HAS_CONTACT_ERP = 4,
+ BT_CONTACT_FLAG_CONTACT_STIFFNESS_DAMPING = 8,
BT_CONTACT_FLAG_FRICTION_ANCHOR = 16,
};
/// ManifoldContactPoint collects and maintains persistent contactpoints.
/// used to improve stability and performance of rigidbody dynamics response.
class btManifoldPoint
+{
+public:
+ btManifoldPoint()
+ : m_userPersistentData(0),
+ m_contactPointFlags(0),
+ m_appliedImpulse(0.f),
+ m_appliedImpulseLateral1(0.f),
+ m_appliedImpulseLateral2(0.f),
+ m_contactMotion1(0.f),
+ m_contactMotion2(0.f),
+ m_contactCFM(0.f),
+ m_contactERP(0.f),
+ m_frictionCFM(0.f),
+ m_lifeTime(0)
+ {
+ }
+
+ btManifoldPoint(const btVector3& pointA, const btVector3& pointB,
+ const btVector3& normal,
+ btScalar distance) : m_localPointA(pointA),
+ m_localPointB(pointB),
+ m_normalWorldOnB(normal),
+ m_distance1(distance),
+ m_combinedFriction(btScalar(0.)),
+ m_combinedRollingFriction(btScalar(0.)),
+ m_combinedSpinningFriction(btScalar(0.)),
+ m_combinedRestitution(btScalar(0.)),
+ m_userPersistentData(0),
+ m_contactPointFlags(0),
+ m_appliedImpulse(0.f),
+ m_appliedImpulseLateral1(0.f),
+ m_appliedImpulseLateral2(0.f),
+ m_contactMotion1(0.f),
+ m_contactMotion2(0.f),
+ m_contactCFM(0.f),
+ m_contactERP(0.f),
+ m_frictionCFM(0.f),
+ m_lifeTime(0)
{
- public:
- btManifoldPoint()
- :m_userPersistentData(0),
- m_contactPointFlags(0),
- m_appliedImpulse(0.f),
- m_appliedImpulseLateral1(0.f),
- m_appliedImpulseLateral2(0.f),
- m_contactMotion1(0.f),
- m_contactMotion2(0.f),
- m_contactCFM(0.f),
- m_contactERP(0.f),
- m_frictionCFM(0.f),
- m_lifeTime(0)
- {
- }
-
- btManifoldPoint( const btVector3 &pointA, const btVector3 &pointB,
- const btVector3 &normal,
- btScalar distance ) :
- m_localPointA( pointA ),
- m_localPointB( pointB ),
- m_normalWorldOnB( normal ),
- m_distance1( distance ),
- m_combinedFriction(btScalar(0.)),
- m_combinedRollingFriction(btScalar(0.)),
- m_combinedSpinningFriction(btScalar(0.)),
- m_combinedRestitution(btScalar(0.)),
- m_userPersistentData(0),
- m_contactPointFlags(0),
- m_appliedImpulse(0.f),
- m_appliedImpulseLateral1(0.f),
- m_appliedImpulseLateral2(0.f),
- m_contactMotion1(0.f),
- m_contactMotion2(0.f),
- m_contactCFM(0.f),
- m_contactERP(0.f),
- m_frictionCFM(0.f),
- m_lifeTime(0)
- {
-
- }
-
-
-
- btVector3 m_localPointA;
- btVector3 m_localPointB;
- btVector3 m_positionWorldOnB;
- ///m_positionWorldOnA is redundant information, see getPositionWorldOnA(), but for clarity
- btVector3 m_positionWorldOnA;
- btVector3 m_normalWorldOnB;
-
- btScalar m_distance1;
- btScalar m_combinedFriction;
- btScalar m_combinedRollingFriction;//torsional friction orthogonal to contact normal, useful to make spheres stop rolling forever
- btScalar m_combinedSpinningFriction;//torsional friction around contact normal, useful for grasping objects
- btScalar m_combinedRestitution;
-
- //BP mod, store contact triangles.
- int m_partId0;
- int m_partId1;
- int m_index0;
- int m_index1;
-
- mutable void* m_userPersistentData;
- //bool m_lateralFrictionInitialized;
- int m_contactPointFlags;
-
- btScalar m_appliedImpulse;
- btScalar m_appliedImpulseLateral1;
- btScalar m_appliedImpulseLateral2;
- btScalar m_contactMotion1;
- btScalar m_contactMotion2;
-
- union
- {
- btScalar m_contactCFM;
- btScalar m_combinedContactStiffness1;
- };
-
- union
- {
- btScalar m_contactERP;
- btScalar m_combinedContactDamping1;
- };
-
- btScalar m_frictionCFM;
-
- int m_lifeTime;//lifetime of the contactpoint in frames
-
- btVector3 m_lateralFrictionDir1;
- btVector3 m_lateralFrictionDir2;
-
-
-
-
- btScalar getDistance() const
- {
- return m_distance1;
- }
- int getLifeTime() const
- {
- return m_lifeTime;
- }
-
- const btVector3& getPositionWorldOnA() const {
- return m_positionWorldOnA;
-// return m_positionWorldOnB + m_normalWorldOnB * m_distance1;
- }
-
- const btVector3& getPositionWorldOnB() const
- {
- return m_positionWorldOnB;
- }
-
- void setDistance(btScalar dist)
- {
- m_distance1 = dist;
- }
-
- ///this returns the most recent applied impulse, to satisfy contact constraints by the constraint solver
- btScalar getAppliedImpulse() const
- {
- return m_appliedImpulse;
- }
-
-
+ }
+
+ btVector3 m_localPointA;
+ btVector3 m_localPointB;
+ btVector3 m_positionWorldOnB;
+ ///m_positionWorldOnA is redundant information, see getPositionWorldOnA(), but for clarity
+ btVector3 m_positionWorldOnA;
+ btVector3 m_normalWorldOnB;
+
+ btScalar m_distance1;
+ btScalar m_combinedFriction;
+ btScalar m_combinedRollingFriction; //torsional friction orthogonal to contact normal, useful to make spheres stop rolling forever
+ btScalar m_combinedSpinningFriction; //torsional friction around contact normal, useful for grasping objects
+ btScalar m_combinedRestitution;
+
+ //BP mod, store contact triangles.
+ int m_partId0;
+ int m_partId1;
+ int m_index0;
+ int m_index1;
+
+ mutable void* m_userPersistentData;
+ //bool m_lateralFrictionInitialized;
+ int m_contactPointFlags;
+
+ btScalar m_appliedImpulse;
+ btScalar m_appliedImpulseLateral1;
+ btScalar m_appliedImpulseLateral2;
+ btScalar m_contactMotion1;
+ btScalar m_contactMotion2;
+
+ union {
+ btScalar m_contactCFM;
+ btScalar m_combinedContactStiffness1;
+ };
+ union {
+ btScalar m_contactERP;
+ btScalar m_combinedContactDamping1;
};
-#endif //BT_MANIFOLD_CONTACT_POINT_H
+ btScalar m_frictionCFM;
+
+ int m_lifeTime; //lifetime of the contactpoint in frames
+
+ btVector3 m_lateralFrictionDir1;
+ btVector3 m_lateralFrictionDir2;
+
+ btScalar getDistance() const
+ {
+ return m_distance1;
+ }
+ int getLifeTime() const
+ {
+ return m_lifeTime;
+ }
+
+ const btVector3& getPositionWorldOnA() const
+ {
+ return m_positionWorldOnA;
+ // return m_positionWorldOnB + m_normalWorldOnB * m_distance1;
+ }
+
+ const btVector3& getPositionWorldOnB() const
+ {
+ return m_positionWorldOnB;
+ }
+
+ void setDistance(btScalar dist)
+ {
+ m_distance1 = dist;
+ }
+
+ ///this returns the most recent applied impulse, to satisfy contact constraints by the constraint solver
+ btScalar getAppliedImpulse() const
+ {
+ return m_appliedImpulse;
+ }
+};
+
+#endif //BT_MANIFOLD_CONTACT_POINT_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp
index fa45f49037..a77449812f 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp
@@ -21,42 +21,38 @@ subject to the following restrictions:
#define NUM_UNITSPHERE_POINTS 42
-
bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& simplexSolver,
- const btConvexShape* convexA,const btConvexShape* convexB,
- const btTransform& transA,const btTransform& transB,
- btVector3& v, btVector3& pa, btVector3& pb,
- class btIDebugDraw* debugDraw
- )
+ const btConvexShape* convexA, const btConvexShape* convexB,
+ const btTransform& transA, const btTransform& transB,
+ btVector3& v, btVector3& pa, btVector3& pb,
+ class btIDebugDraw* debugDraw)
{
-
(void)v;
-
- bool check2d= convexA->isConvex2d() && convexB->isConvex2d();
+
+ bool check2d = convexA->isConvex2d() && convexB->isConvex2d();
struct btIntermediateResult : public btDiscreteCollisionDetectorInterface::Result
{
-
- btIntermediateResult():m_hasResult(false)
+ btIntermediateResult() : m_hasResult(false)
{
}
-
+
btVector3 m_normalOnBInWorld;
btVector3 m_pointInWorld;
btScalar m_depth;
- bool m_hasResult;
+ bool m_hasResult;
- virtual void setShapeIdentifiersA(int partId0,int index0)
+ virtual void setShapeIdentifiersA(int partId0, int index0)
{
(void)partId0;
(void)index0;
}
- virtual void setShapeIdentifiersB(int partId1,int index1)
+ virtual void setShapeIdentifiersB(int partId1, int index1)
{
(void)partId1;
(void)index1;
}
- void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)
+ void addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar depth)
{
m_normalOnBInWorld = normalOnBInWorld;
m_pointInWorld = pointInWorld;
@@ -68,39 +64,39 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s
//just take fixed number of orientation, and sample the penetration depth in that direction
btScalar minProj = btScalar(BT_LARGE_FLOAT);
btVector3 minNorm(btScalar(0.), btScalar(0.), btScalar(0.));
- btVector3 minA,minB;
- btVector3 seperatingAxisInA,seperatingAxisInB;
- btVector3 pInA,qInB,pWorld,qWorld,w;
+ btVector3 minA, minB;
+ btVector3 seperatingAxisInA, seperatingAxisInB;
+ btVector3 pInA, qInB, pWorld, qWorld, w;
#ifndef __SPU__
#define USE_BATCHED_SUPPORT 1
#endif
#ifdef USE_BATCHED_SUPPORT
- btVector3 supportVerticesABatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2];
- btVector3 supportVerticesBBatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2];
- btVector3 seperatingAxisInABatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2];
- btVector3 seperatingAxisInBBatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2];
+ btVector3 supportVerticesABatch[NUM_UNITSPHERE_POINTS + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2];
+ btVector3 supportVerticesBBatch[NUM_UNITSPHERE_POINTS + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2];
+ btVector3 seperatingAxisInABatch[NUM_UNITSPHERE_POINTS + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2];
+ btVector3 seperatingAxisInBBatch[NUM_UNITSPHERE_POINTS + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2];
int i;
int numSampleDirections = NUM_UNITSPHERE_POINTS;
- for (i=0;i<numSampleDirections;i++)
+ for (i = 0; i < numSampleDirections; i++)
{
btVector3 norm = getPenetrationDirections()[i];
- seperatingAxisInABatch[i] = (-norm) * transA.getBasis() ;
- seperatingAxisInBBatch[i] = norm * transB.getBasis() ;
+ seperatingAxisInABatch[i] = (-norm) * transA.getBasis();
+ seperatingAxisInBBatch[i] = norm * transB.getBasis();
}
{
int numPDA = convexA->getNumPreferredPenetrationDirections();
if (numPDA)
{
- for (int i=0;i<numPDA;i++)
+ for (int i = 0; i < numPDA; i++)
{
btVector3 norm;
- convexA->getPreferredPenetrationDirection(i,norm);
- norm = transA.getBasis() * norm;
+ convexA->getPreferredPenetrationDirection(i, norm);
+ norm = transA.getBasis() * norm;
getPenetrationDirections()[numSampleDirections] = norm;
seperatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis();
seperatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis();
@@ -113,11 +109,11 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s
int numPDB = convexB->getNumPreferredPenetrationDirections();
if (numPDB)
{
- for (int i=0;i<numPDB;i++)
+ for (int i = 0; i < numPDB; i++)
{
btVector3 norm;
- convexB->getPreferredPenetrationDirection(i,norm);
- norm = transB.getBasis() * norm;
+ convexB->getPreferredPenetrationDirection(i, norm);
+ norm = transB.getBasis() * norm;
getPenetrationDirections()[numSampleDirections] = norm;
seperatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis();
seperatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis();
@@ -126,29 +122,25 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s
}
}
+ convexA->batchedUnitVectorGetSupportingVertexWithoutMargin(seperatingAxisInABatch, supportVerticesABatch, numSampleDirections);
+ convexB->batchedUnitVectorGetSupportingVertexWithoutMargin(seperatingAxisInBBatch, supportVerticesBBatch, numSampleDirections);
-
-
- convexA->batchedUnitVectorGetSupportingVertexWithoutMargin(seperatingAxisInABatch,supportVerticesABatch,numSampleDirections);
- convexB->batchedUnitVectorGetSupportingVertexWithoutMargin(seperatingAxisInBBatch,supportVerticesBBatch,numSampleDirections);
-
- for (i=0;i<numSampleDirections;i++)
+ for (i = 0; i < numSampleDirections; i++)
{
btVector3 norm = getPenetrationDirections()[i];
if (check2d)
{
norm[2] = 0.f;
}
- if (norm.length2()>0.01)
+ if (norm.length2() > 0.01)
{
-
seperatingAxisInA = seperatingAxisInABatch[i];
seperatingAxisInB = seperatingAxisInBBatch[i];
pInA = supportVerticesABatch[i];
qInB = supportVerticesBBatch[i];
- pWorld = transA(pInA);
+ pWorld = transA(pInA);
qWorld = transB(qInB);
if (check2d)
{
@@ -156,7 +148,7 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s
qWorld[2] = 0.f;
}
- w = qWorld - pWorld;
+ w = qWorld - pWorld;
btScalar delta = norm.dot(w);
//find smallest delta
if (delta < minProj)
@@ -167,7 +159,7 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s
minB = qWorld;
}
}
- }
+ }
#else
int numSampleDirections = NUM_UNITSPHERE_POINTS;
@@ -177,11 +169,11 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s
int numPDA = convexA->getNumPreferredPenetrationDirections();
if (numPDA)
{
- for (int i=0;i<numPDA;i++)
+ for (int i = 0; i < numPDA; i++)
{
btVector3 norm;
- convexA->getPreferredPenetrationDirection(i,norm);
- norm = transA.getBasis() * norm;
+ convexA->getPreferredPenetrationDirection(i, norm);
+ norm = transA.getBasis() * norm;
getPenetrationDirections()[numSampleDirections] = norm;
numSampleDirections++;
}
@@ -192,28 +184,28 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s
int numPDB = convexB->getNumPreferredPenetrationDirections();
if (numPDB)
{
- for (int i=0;i<numPDB;i++)
+ for (int i = 0; i < numPDB; i++)
{
btVector3 norm;
- convexB->getPreferredPenetrationDirection(i,norm);
- norm = transB.getBasis() * norm;
+ convexB->getPreferredPenetrationDirection(i, norm);
+ norm = transB.getBasis() * norm;
getPenetrationDirections()[numSampleDirections] = norm;
numSampleDirections++;
}
}
}
-#endif // __SPU__
+#endif // __SPU__
- for (int i=0;i<numSampleDirections;i++)
+ for (int i = 0; i < numSampleDirections; i++)
{
const btVector3& norm = getPenetrationDirections()[i];
- seperatingAxisInA = (-norm)* transA.getBasis();
- seperatingAxisInB = norm* transB.getBasis();
+ seperatingAxisInA = (-norm) * transA.getBasis();
+ seperatingAxisInB = norm * transB.getBasis();
pInA = convexA->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA);
qInB = convexB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB);
- pWorld = transA(pInA);
+ pWorld = transA(pInA);
qWorld = transB(qInB);
- w = qWorld - pWorld;
+ w = qWorld - pWorld;
btScalar delta = norm.dot(w);
//find smallest delta
if (delta < minProj)
@@ -224,48 +216,39 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s
minB = qWorld;
}
}
-#endif //USE_BATCHED_SUPPORT
+#endif //USE_BATCHED_SUPPORT
//add the margins
- minA += minNorm*convexA->getMarginNonVirtual();
- minB -= minNorm*convexB->getMarginNonVirtual();
+ minA += minNorm * convexA->getMarginNonVirtual();
+ minB -= minNorm * convexB->getMarginNonVirtual();
//no penetration
if (minProj < btScalar(0.))
return false;
- btScalar extraSeparation = 0.5f;///scale dependent
- minProj += extraSeparation+(convexA->getMarginNonVirtual() + convexB->getMarginNonVirtual());
-
-
-
-
+ btScalar extraSeparation = 0.5f; ///scale dependent
+ minProj += extraSeparation + (convexA->getMarginNonVirtual() + convexB->getMarginNonVirtual());
//#define DEBUG_DRAW 1
#ifdef DEBUG_DRAW
if (debugDraw)
{
- btVector3 color(0,1,0);
- debugDraw->drawLine(minA,minB,color);
- color = btVector3 (1,1,1);
- btVector3 vec = minB-minA;
+ btVector3 color(0, 1, 0);
+ debugDraw->drawLine(minA, minB, color);
+ color = btVector3(1, 1, 1);
+ btVector3 vec = minB - minA;
btScalar prj2 = minNorm.dot(vec);
- debugDraw->drawLine(minA,minA+(minNorm*minProj),color);
-
+ debugDraw->drawLine(minA, minA + (minNorm * minProj), color);
}
-#endif //DEBUG_DRAW
+#endif //DEBUG_DRAW
-
-
- btGjkPairDetector gjkdet(convexA,convexB,&simplexSolver,0);
+ btGjkPairDetector gjkdet(convexA, convexB, &simplexSolver, 0);
btScalar offsetDist = minProj;
btVector3 offset = minNorm * offsetDist;
-
-
btGjkPairDetector::ClosestPointInput input;
-
+
btVector3 newOrg = transA.getOrigin() + offset;
btTransform displacedTrans = transA;
@@ -273,89 +256,81 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s
input.m_transformA = displacedTrans;
input.m_transformB = transB;
- input.m_maximumDistanceSquared = btScalar(BT_LARGE_FLOAT);//minProj;
-
+ input.m_maximumDistanceSquared = btScalar(BT_LARGE_FLOAT); //minProj;
+
btIntermediateResult res;
gjkdet.setCachedSeperatingAxis(-minNorm);
- gjkdet.getClosestPoints(input,res,debugDraw);
+ gjkdet.getClosestPoints(input, res, debugDraw);
btScalar correctedMinNorm = minProj - res.m_depth;
-
//the penetration depth is over-estimated, relax it
- btScalar penetration_relaxation= btScalar(1.);
- minNorm*=penetration_relaxation;
-
+ btScalar penetration_relaxation = btScalar(1.);
+ minNorm *= penetration_relaxation;
if (res.m_hasResult)
{
-
pa = res.m_pointInWorld - minNorm * correctedMinNorm;
pb = res.m_pointInWorld;
v = minNorm;
-
+
#ifdef DEBUG_DRAW
if (debugDraw)
{
- btVector3 color(1,0,0);
- debugDraw->drawLine(pa,pb,color);
+ btVector3 color(1, 0, 0);
+ debugDraw->drawLine(pa, pb, color);
}
-#endif//DEBUG_DRAW
-
-
+#endif //DEBUG_DRAW
}
return res.m_hasResult;
}
-btVector3* btMinkowskiPenetrationDepthSolver::getPenetrationDirections()
+btVector3* btMinkowskiPenetrationDepthSolver::getPenetrationDirections()
{
- static btVector3 sPenetrationDirections[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2] =
- {
- btVector3(btScalar(0.000000) , btScalar(-0.000000),btScalar(-1.000000)),
- btVector3(btScalar(0.723608) , btScalar(-0.525725),btScalar(-0.447219)),
- btVector3(btScalar(-0.276388) , btScalar(-0.850649),btScalar(-0.447219)),
- btVector3(btScalar(-0.894426) , btScalar(-0.000000),btScalar(-0.447216)),
- btVector3(btScalar(-0.276388) , btScalar(0.850649),btScalar(-0.447220)),
- btVector3(btScalar(0.723608) , btScalar(0.525725),btScalar(-0.447219)),
- btVector3(btScalar(0.276388) , btScalar(-0.850649),btScalar(0.447220)),
- btVector3(btScalar(-0.723608) , btScalar(-0.525725),btScalar(0.447219)),
- btVector3(btScalar(-0.723608) , btScalar(0.525725),btScalar(0.447219)),
- btVector3(btScalar(0.276388) , btScalar(0.850649),btScalar(0.447219)),
- btVector3(btScalar(0.894426) , btScalar(0.000000),btScalar(0.447216)),
- btVector3(btScalar(-0.000000) , btScalar(0.000000),btScalar(1.000000)),
- btVector3(btScalar(0.425323) , btScalar(-0.309011),btScalar(-0.850654)),
- btVector3(btScalar(-0.162456) , btScalar(-0.499995),btScalar(-0.850654)),
- btVector3(btScalar(0.262869) , btScalar(-0.809012),btScalar(-0.525738)),
- btVector3(btScalar(0.425323) , btScalar(0.309011),btScalar(-0.850654)),
- btVector3(btScalar(0.850648) , btScalar(-0.000000),btScalar(-0.525736)),
- btVector3(btScalar(-0.525730) , btScalar(-0.000000),btScalar(-0.850652)),
- btVector3(btScalar(-0.688190) , btScalar(-0.499997),btScalar(-0.525736)),
- btVector3(btScalar(-0.162456) , btScalar(0.499995),btScalar(-0.850654)),
- btVector3(btScalar(-0.688190) , btScalar(0.499997),btScalar(-0.525736)),
- btVector3(btScalar(0.262869) , btScalar(0.809012),btScalar(-0.525738)),
- btVector3(btScalar(0.951058) , btScalar(0.309013),btScalar(0.000000)),
- btVector3(btScalar(0.951058) , btScalar(-0.309013),btScalar(0.000000)),
- btVector3(btScalar(0.587786) , btScalar(-0.809017),btScalar(0.000000)),
- btVector3(btScalar(0.000000) , btScalar(-1.000000),btScalar(0.000000)),
- btVector3(btScalar(-0.587786) , btScalar(-0.809017),btScalar(0.000000)),
- btVector3(btScalar(-0.951058) , btScalar(-0.309013),btScalar(-0.000000)),
- btVector3(btScalar(-0.951058) , btScalar(0.309013),btScalar(-0.000000)),
- btVector3(btScalar(-0.587786) , btScalar(0.809017),btScalar(-0.000000)),
- btVector3(btScalar(-0.000000) , btScalar(1.000000),btScalar(-0.000000)),
- btVector3(btScalar(0.587786) , btScalar(0.809017),btScalar(-0.000000)),
- btVector3(btScalar(0.688190) , btScalar(-0.499997),btScalar(0.525736)),
- btVector3(btScalar(-0.262869) , btScalar(-0.809012),btScalar(0.525738)),
- btVector3(btScalar(-0.850648) , btScalar(0.000000),btScalar(0.525736)),
- btVector3(btScalar(-0.262869) , btScalar(0.809012),btScalar(0.525738)),
- btVector3(btScalar(0.688190) , btScalar(0.499997),btScalar(0.525736)),
- btVector3(btScalar(0.525730) , btScalar(0.000000),btScalar(0.850652)),
- btVector3(btScalar(0.162456) , btScalar(-0.499995),btScalar(0.850654)),
- btVector3(btScalar(-0.425323) , btScalar(-0.309011),btScalar(0.850654)),
- btVector3(btScalar(-0.425323) , btScalar(0.309011),btScalar(0.850654)),
- btVector3(btScalar(0.162456) , btScalar(0.499995),btScalar(0.850654))
- };
+ static btVector3 sPenetrationDirections[NUM_UNITSPHERE_POINTS + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2] =
+ {
+ btVector3(btScalar(0.000000), btScalar(-0.000000), btScalar(-1.000000)),
+ btVector3(btScalar(0.723608), btScalar(-0.525725), btScalar(-0.447219)),
+ btVector3(btScalar(-0.276388), btScalar(-0.850649), btScalar(-0.447219)),
+ btVector3(btScalar(-0.894426), btScalar(-0.000000), btScalar(-0.447216)),
+ btVector3(btScalar(-0.276388), btScalar(0.850649), btScalar(-0.447220)),
+ btVector3(btScalar(0.723608), btScalar(0.525725), btScalar(-0.447219)),
+ btVector3(btScalar(0.276388), btScalar(-0.850649), btScalar(0.447220)),
+ btVector3(btScalar(-0.723608), btScalar(-0.525725), btScalar(0.447219)),
+ btVector3(btScalar(-0.723608), btScalar(0.525725), btScalar(0.447219)),
+ btVector3(btScalar(0.276388), btScalar(0.850649), btScalar(0.447219)),
+ btVector3(btScalar(0.894426), btScalar(0.000000), btScalar(0.447216)),
+ btVector3(btScalar(-0.000000), btScalar(0.000000), btScalar(1.000000)),
+ btVector3(btScalar(0.425323), btScalar(-0.309011), btScalar(-0.850654)),
+ btVector3(btScalar(-0.162456), btScalar(-0.499995), btScalar(-0.850654)),
+ btVector3(btScalar(0.262869), btScalar(-0.809012), btScalar(-0.525738)),
+ btVector3(btScalar(0.425323), btScalar(0.309011), btScalar(-0.850654)),
+ btVector3(btScalar(0.850648), btScalar(-0.000000), btScalar(-0.525736)),
+ btVector3(btScalar(-0.525730), btScalar(-0.000000), btScalar(-0.850652)),
+ btVector3(btScalar(-0.688190), btScalar(-0.499997), btScalar(-0.525736)),
+ btVector3(btScalar(-0.162456), btScalar(0.499995), btScalar(-0.850654)),
+ btVector3(btScalar(-0.688190), btScalar(0.499997), btScalar(-0.525736)),
+ btVector3(btScalar(0.262869), btScalar(0.809012), btScalar(-0.525738)),
+ btVector3(btScalar(0.951058), btScalar(0.309013), btScalar(0.000000)),
+ btVector3(btScalar(0.951058), btScalar(-0.309013), btScalar(0.000000)),
+ btVector3(btScalar(0.587786), btScalar(-0.809017), btScalar(0.000000)),
+ btVector3(btScalar(0.000000), btScalar(-1.000000), btScalar(0.000000)),
+ btVector3(btScalar(-0.587786), btScalar(-0.809017), btScalar(0.000000)),
+ btVector3(btScalar(-0.951058), btScalar(-0.309013), btScalar(-0.000000)),
+ btVector3(btScalar(-0.951058), btScalar(0.309013), btScalar(-0.000000)),
+ btVector3(btScalar(-0.587786), btScalar(0.809017), btScalar(-0.000000)),
+ btVector3(btScalar(-0.000000), btScalar(1.000000), btScalar(-0.000000)),
+ btVector3(btScalar(0.587786), btScalar(0.809017), btScalar(-0.000000)),
+ btVector3(btScalar(0.688190), btScalar(-0.499997), btScalar(0.525736)),
+ btVector3(btScalar(-0.262869), btScalar(-0.809012), btScalar(0.525738)),
+ btVector3(btScalar(-0.850648), btScalar(0.000000), btScalar(0.525736)),
+ btVector3(btScalar(-0.262869), btScalar(0.809012), btScalar(0.525738)),
+ btVector3(btScalar(0.688190), btScalar(0.499997), btScalar(0.525736)),
+ btVector3(btScalar(0.525730), btScalar(0.000000), btScalar(0.850652)),
+ btVector3(btScalar(0.162456), btScalar(-0.499995), btScalar(0.850654)),
+ btVector3(btScalar(-0.425323), btScalar(-0.309011), btScalar(0.850654)),
+ btVector3(btScalar(-0.425323), btScalar(0.309011), btScalar(0.850654)),
+ btVector3(btScalar(0.162456), btScalar(0.499995), btScalar(0.850654))};
return sPenetrationDirections;
}
-
-
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h
index fd533b4fc3..8e3e393259 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h
@@ -23,18 +23,14 @@ subject to the following restrictions:
class btMinkowskiPenetrationDepthSolver : public btConvexPenetrationDepthSolver
{
protected:
-
- static btVector3* getPenetrationDirections();
+ static btVector3* getPenetrationDirections();
public:
-
- virtual bool calcPenDepth( btSimplexSolverInterface& simplexSolver,
- const btConvexShape* convexA,const btConvexShape* convexB,
- const btTransform& transA,const btTransform& transB,
- btVector3& v, btVector3& pa, btVector3& pb,
- class btIDebugDraw* debugDraw
- );
+ virtual bool calcPenDepth(btSimplexSolverInterface& simplexSolver,
+ const btConvexShape* convexA, const btConvexShape* convexB,
+ const btTransform& transA, const btTransform& transB,
+ btVector3& v, btVector3& pa, btVector3& pb,
+ class btIDebugDraw* debugDraw);
};
-#endif //BT_MINKOWSKI_PENETRATION_DEPTH_SOLVER_H
-
+#endif //BT_MINKOWSKI_PENETRATION_DEPTH_SOLVER_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMprPenetration.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMprPenetration.h
index a22a0bae66..358bc95d81 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMprPenetration.h
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMprPenetration.h
@@ -28,32 +28,31 @@
//#define MPR_AVERAGE_CONTACT_POSITIONS
-
struct btMprCollisionDescription
{
- btVector3 m_firstDir;
- int m_maxGjkIterations;
- btScalar m_maximumDistanceSquared;
- btScalar m_gjkRelError2;
-
- btMprCollisionDescription()
- : m_firstDir(0,1,0),
- m_maxGjkIterations(1000),
- m_maximumDistanceSquared(1e30f),
- m_gjkRelError2(1.0e-6)
- {
- }
- virtual ~btMprCollisionDescription()
- {
- }
+ btVector3 m_firstDir;
+ int m_maxGjkIterations;
+ btScalar m_maximumDistanceSquared;
+ btScalar m_gjkRelError2;
+
+ btMprCollisionDescription()
+ : m_firstDir(0, 1, 0),
+ m_maxGjkIterations(1000),
+ m_maximumDistanceSquared(1e30f),
+ m_gjkRelError2(1.0e-6)
+ {
+ }
+ virtual ~btMprCollisionDescription()
+ {
+ }
};
struct btMprDistanceInfo
{
- btVector3 m_pointOnA;
- btVector3 m_pointOnB;
- btVector3 m_normalBtoA;
- btScalar m_distance;
+ btVector3 m_pointOnA;
+ btVector3 m_pointOnB;
+ btVector3 m_normalBtoA;
+ btScalar m_distance;
};
#ifdef __cplusplus
@@ -67,131 +66,112 @@ struct btMprDistanceInfo
#define BT_MPR_TOLERANCE 1E-6f
#define BT_MPR_MAX_ITERATIONS 1000
-struct _btMprSupport_t
+struct _btMprSupport_t
{
- btVector3 v; //!< Support point in minkowski sum
- btVector3 v1; //!< Support point in obj1
- btVector3 v2; //!< Support point in obj2
+ btVector3 v; //!< Support point in minkowski sum
+ btVector3 v1; //!< Support point in obj1
+ btVector3 v2; //!< Support point in obj2
};
typedef struct _btMprSupport_t btMprSupport_t;
-struct _btMprSimplex_t
+struct _btMprSimplex_t
{
- btMprSupport_t ps[4];
- int last; //!< index of last added point
+ btMprSupport_t ps[4];
+ int last; //!< index of last added point
};
typedef struct _btMprSimplex_t btMprSimplex_t;
-inline btMprSupport_t* btMprSimplexPointW(btMprSimplex_t *s, int idx)
+inline btMprSupport_t *btMprSimplexPointW(btMprSimplex_t *s, int idx)
{
- return &s->ps[idx];
+ return &s->ps[idx];
}
inline void btMprSimplexSetSize(btMprSimplex_t *s, int size)
{
- s->last = size - 1;
+ s->last = size - 1;
}
#ifdef DEBUG_MPR
-inline void btPrintPortalVertex(_btMprSimplex_t* portal, int index)
+inline void btPrintPortalVertex(_btMprSimplex_t *portal, int index)
{
- printf("portal[%d].v = %f,%f,%f, v1=%f,%f,%f, v2=%f,%f,%f\n", index, portal->ps[index].v.x(),portal->ps[index].v.y(),portal->ps[index].v.z(),
- portal->ps[index].v1.x(),portal->ps[index].v1.y(),portal->ps[index].v1.z(),
- portal->ps[index].v2.x(),portal->ps[index].v2.y(),portal->ps[index].v2.z());
+ printf("portal[%d].v = %f,%f,%f, v1=%f,%f,%f, v2=%f,%f,%f\n", index, portal->ps[index].v.x(), portal->ps[index].v.y(), portal->ps[index].v.z(),
+ portal->ps[index].v1.x(), portal->ps[index].v1.y(), portal->ps[index].v1.z(),
+ portal->ps[index].v2.x(), portal->ps[index].v2.y(), portal->ps[index].v2.z());
}
-#endif //DEBUG_MPR
-
-
-
+#endif //DEBUG_MPR
inline int btMprSimplexSize(const btMprSimplex_t *s)
{
- return s->last + 1;
+ return s->last + 1;
}
-
-inline const btMprSupport_t* btMprSimplexPoint(const btMprSimplex_t* s, int idx)
+inline const btMprSupport_t *btMprSimplexPoint(const btMprSimplex_t *s, int idx)
{
- // here is no check on boundaries
- return &s->ps[idx];
+ // here is no check on boundaries
+ return &s->ps[idx];
}
inline void btMprSupportCopy(btMprSupport_t *d, const btMprSupport_t *s)
{
- *d = *s;
+ *d = *s;
}
inline void btMprSimplexSet(btMprSimplex_t *s, size_t pos, const btMprSupport_t *a)
{
- btMprSupportCopy(s->ps + pos, a);
+ btMprSupportCopy(s->ps + pos, a);
}
-
inline void btMprSimplexSwap(btMprSimplex_t *s, size_t pos1, size_t pos2)
{
- btMprSupport_t supp;
+ btMprSupport_t supp;
- btMprSupportCopy(&supp, &s->ps[pos1]);
- btMprSupportCopy(&s->ps[pos1], &s->ps[pos2]);
- btMprSupportCopy(&s->ps[pos2], &supp);
+ btMprSupportCopy(&supp, &s->ps[pos1]);
+ btMprSupportCopy(&s->ps[pos1], &s->ps[pos2]);
+ btMprSupportCopy(&s->ps[pos2], &supp);
}
-
inline int btMprIsZero(float val)
{
- return BT_MPR_FABS(val) < FLT_EPSILON;
+ return BT_MPR_FABS(val) < FLT_EPSILON;
}
-
-
inline int btMprEq(float _a, float _b)
{
- float ab;
- float a, b;
+ float ab;
+ float a, b;
- ab = BT_MPR_FABS(_a - _b);
- if (BT_MPR_FABS(ab) < FLT_EPSILON)
- return 1;
+ ab = BT_MPR_FABS(_a - _b);
+ if (BT_MPR_FABS(ab) < FLT_EPSILON)
+ return 1;
- a = BT_MPR_FABS(_a);
- b = BT_MPR_FABS(_b);
- if (b > a){
- return ab < FLT_EPSILON * b;
- }else{
- return ab < FLT_EPSILON * a;
- }
+ a = BT_MPR_FABS(_a);
+ b = BT_MPR_FABS(_b);
+ if (b > a)
+ {
+ return ab < FLT_EPSILON * b;
+ }
+ else
+ {
+ return ab < FLT_EPSILON * a;
+ }
}
-
-inline int btMprVec3Eq(const btVector3* a, const btVector3 *b)
+inline int btMprVec3Eq(const btVector3 *a, const btVector3 *b)
{
- return btMprEq((*a).x(), (*b).x())
- && btMprEq((*a).y(), (*b).y())
- && btMprEq((*a).z(), (*b).z());
+ return btMprEq((*a).x(), (*b).x()) && btMprEq((*a).y(), (*b).y()) && btMprEq((*a).z(), (*b).z());
}
-
-
-
-
-
-
-
-
-
-
template <typename btConvexTemplate>
-inline void btFindOrigin(const btConvexTemplate& a, const btConvexTemplate& b, const btMprCollisionDescription& colDesc,btMprSupport_t *center)
+inline void btFindOrigin(const btConvexTemplate &a, const btConvexTemplate &b, const btMprCollisionDescription &colDesc, btMprSupport_t *center)
{
-
center->v1 = a.getObjectCenterInWorld();
- center->v2 = b.getObjectCenterInWorld();
- center->v = center->v1 - center->v2;
+ center->v2 = b.getObjectCenterInWorld();
+ center->v = center->v1 - center->v2;
}
inline void btMprVec3Set(btVector3 *v, float x, float y, float z)
{
- v->setValue(x,y,z);
+ v->setValue(x, y, z);
}
inline void btMprVec3Add(btVector3 *v, const btVector3 *w)
@@ -201,41 +181,38 @@ inline void btMprVec3Add(btVector3 *v, const btVector3 *w)
inline void btMprVec3Copy(btVector3 *v, const btVector3 *w)
{
- *v = *w;
+ *v = *w;
}
inline void btMprVec3Scale(btVector3 *d, float k)
{
- *d *= k;
+ *d *= k;
}
inline float btMprVec3Dot(const btVector3 *a, const btVector3 *b)
{
- float dot;
+ float dot;
- dot = btDot(*a,*b);
- return dot;
+ dot = btDot(*a, *b);
+ return dot;
}
-
inline float btMprVec3Len2(const btVector3 *v)
{
- return btMprVec3Dot(v, v);
+ return btMprVec3Dot(v, v);
}
inline void btMprVec3Normalize(btVector3 *d)
{
- float k = 1.f / BT_MPR_SQRT(btMprVec3Len2(d));
- btMprVec3Scale(d, k);
+ float k = 1.f / BT_MPR_SQRT(btMprVec3Len2(d));
+ btMprVec3Scale(d, k);
}
inline void btMprVec3Cross(btVector3 *d, const btVector3 *a, const btVector3 *b)
{
- *d = btCross(*a,*b);
-
+ *d = btCross(*a, *b);
}
-
inline void btMprVec3Sub2(btVector3 *d, const btVector3 *v, const btVector3 *w)
{
*d = *v - *w;
@@ -243,89 +220,97 @@ inline void btMprVec3Sub2(btVector3 *d, const btVector3 *v, const btVector3 *w)
inline void btPortalDir(const btMprSimplex_t *portal, btVector3 *dir)
{
- btVector3 v2v1, v3v1;
+ btVector3 v2v1, v3v1;
- btMprVec3Sub2(&v2v1, &btMprSimplexPoint(portal, 2)->v,
- &btMprSimplexPoint(portal, 1)->v);
- btMprVec3Sub2(&v3v1, &btMprSimplexPoint(portal, 3)->v,
- &btMprSimplexPoint(portal, 1)->v);
- btMprVec3Cross(dir, &v2v1, &v3v1);
- btMprVec3Normalize(dir);
+ btMprVec3Sub2(&v2v1, &btMprSimplexPoint(portal, 2)->v,
+ &btMprSimplexPoint(portal, 1)->v);
+ btMprVec3Sub2(&v3v1, &btMprSimplexPoint(portal, 3)->v,
+ &btMprSimplexPoint(portal, 1)->v);
+ btMprVec3Cross(dir, &v2v1, &v3v1);
+ btMprVec3Normalize(dir);
}
-
inline int portalEncapsulesOrigin(const btMprSimplex_t *portal,
- const btVector3 *dir)
+ const btVector3 *dir)
{
- float dot;
- dot = btMprVec3Dot(dir, &btMprSimplexPoint(portal, 1)->v);
- return btMprIsZero(dot) || dot > 0.f;
+ float dot;
+ dot = btMprVec3Dot(dir, &btMprSimplexPoint(portal, 1)->v);
+ return btMprIsZero(dot) || dot > 0.f;
}
inline int portalReachTolerance(const btMprSimplex_t *portal,
- const btMprSupport_t *v4,
- const btVector3 *dir)
+ const btMprSupport_t *v4,
+ const btVector3 *dir)
{
- float dv1, dv2, dv3, dv4;
- float dot1, dot2, dot3;
+ float dv1, dv2, dv3, dv4;
+ float dot1, dot2, dot3;
- // find the smallest dot product of dir and {v1-v4, v2-v4, v3-v4}
+ // find the smallest dot product of dir and {v1-v4, v2-v4, v3-v4}
- dv1 = btMprVec3Dot(&btMprSimplexPoint(portal, 1)->v, dir);
- dv2 = btMprVec3Dot(&btMprSimplexPoint(portal, 2)->v, dir);
- dv3 = btMprVec3Dot(&btMprSimplexPoint(portal, 3)->v, dir);
- dv4 = btMprVec3Dot(&v4->v, dir);
+ dv1 = btMprVec3Dot(&btMprSimplexPoint(portal, 1)->v, dir);
+ dv2 = btMprVec3Dot(&btMprSimplexPoint(portal, 2)->v, dir);
+ dv3 = btMprVec3Dot(&btMprSimplexPoint(portal, 3)->v, dir);
+ dv4 = btMprVec3Dot(&v4->v, dir);
- dot1 = dv4 - dv1;
- dot2 = dv4 - dv2;
- dot3 = dv4 - dv3;
+ dot1 = dv4 - dv1;
+ dot2 = dv4 - dv2;
+ dot3 = dv4 - dv3;
- dot1 = BT_MPR_FMIN(dot1, dot2);
- dot1 = BT_MPR_FMIN(dot1, dot3);
+ dot1 = BT_MPR_FMIN(dot1, dot2);
+ dot1 = BT_MPR_FMIN(dot1, dot3);
- return btMprEq(dot1, BT_MPR_TOLERANCE) || dot1 < BT_MPR_TOLERANCE;
+ return btMprEq(dot1, BT_MPR_TOLERANCE) || dot1 < BT_MPR_TOLERANCE;
}
inline int portalCanEncapsuleOrigin(const btMprSimplex_t *portal,
- const btMprSupport_t *v4,
- const btVector3 *dir)
+ const btMprSupport_t *v4,
+ const btVector3 *dir)
{
- float dot;
- dot = btMprVec3Dot(&v4->v, dir);
- return btMprIsZero(dot) || dot > 0.f;
+ float dot;
+ dot = btMprVec3Dot(&v4->v, dir);
+ return btMprIsZero(dot) || dot > 0.f;
}
inline void btExpandPortal(btMprSimplex_t *portal,
- const btMprSupport_t *v4)
-{
- float dot;
- btVector3 v4v0;
-
- btMprVec3Cross(&v4v0, &v4->v, &btMprSimplexPoint(portal, 0)->v);
- dot = btMprVec3Dot(&btMprSimplexPoint(portal, 1)->v, &v4v0);
- if (dot > 0.f){
- dot = btMprVec3Dot(&btMprSimplexPoint(portal, 2)->v, &v4v0);
- if (dot > 0.f){
- btMprSimplexSet(portal, 1, v4);
- }else{
- btMprSimplexSet(portal, 3, v4);
- }
- }else{
- dot = btMprVec3Dot(&btMprSimplexPoint(portal, 3)->v, &v4v0);
- if (dot > 0.f){
- btMprSimplexSet(portal, 2, v4);
- }else{
- btMprSimplexSet(portal, 1, v4);
- }
- }
+ const btMprSupport_t *v4)
+{
+ float dot;
+ btVector3 v4v0;
+
+ btMprVec3Cross(&v4v0, &v4->v, &btMprSimplexPoint(portal, 0)->v);
+ dot = btMprVec3Dot(&btMprSimplexPoint(portal, 1)->v, &v4v0);
+ if (dot > 0.f)
+ {
+ dot = btMprVec3Dot(&btMprSimplexPoint(portal, 2)->v, &v4v0);
+ if (dot > 0.f)
+ {
+ btMprSimplexSet(portal, 1, v4);
+ }
+ else
+ {
+ btMprSimplexSet(portal, 3, v4);
+ }
+ }
+ else
+ {
+ dot = btMprVec3Dot(&btMprSimplexPoint(portal, 3)->v, &v4v0);
+ if (dot > 0.f)
+ {
+ btMprSimplexSet(portal, 2, v4);
+ }
+ else
+ {
+ btMprSimplexSet(portal, 1, v4);
+ }
+ }
}
template <typename btConvexTemplate>
-inline void btMprSupport(const btConvexTemplate& a, const btConvexTemplate& b,
- const btMprCollisionDescription& colDesc,
- const btVector3& dir, btMprSupport_t *supp)
+inline void btMprSupport(const btConvexTemplate &a, const btConvexTemplate &b,
+ const btMprCollisionDescription &colDesc,
+ const btVector3 &dir, btMprSupport_t *supp)
{
- btVector3 seperatingAxisInA = dir* a.getWorldTransform().getBasis();
- btVector3 seperatingAxisInB = -dir* b.getWorldTransform().getBasis();
+ btVector3 seperatingAxisInA = dir * a.getWorldTransform().getBasis();
+ btVector3 seperatingAxisInB = -dir * b.getWorldTransform().getBasis();
btVector3 pInA = a.getLocalSupportWithMargin(seperatingAxisInA);
btVector3 qInB = b.getLocalSupportWithMargin(seperatingAxisInB);
@@ -335,574 +320,565 @@ inline void btMprSupport(const btConvexTemplate& a, const btConvexTemplate& b,
supp->v = supp->v1 - supp->v2;
}
-
template <typename btConvexTemplate>
-static int btDiscoverPortal(const btConvexTemplate& a, const btConvexTemplate& b,
- const btMprCollisionDescription& colDesc,
- btMprSimplex_t *portal)
-{
- btVector3 dir, va, vb;
- float dot;
- int cont;
-
-
-
- // vertex 0 is center of portal
- btFindOrigin(a,b,colDesc, btMprSimplexPointW(portal, 0));
-
-
- // vertex 0 is center of portal
- btMprSimplexSetSize(portal, 1);
-
-
-
- btVector3 zero = btVector3(0,0,0);
- btVector3* org = &zero;
-
- if (btMprVec3Eq(&btMprSimplexPoint(portal, 0)->v, org)){
- // 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...
- btMprVec3Set(&va, FLT_EPSILON * 10.f, 0.f, 0.f);
- btMprVec3Add(&btMprSimplexPointW(portal, 0)->v, &va);
- }
-
-
- // vertex 1 = support in direction of origin
- btMprVec3Copy(&dir, &btMprSimplexPoint(portal, 0)->v);
- btMprVec3Scale(&dir, -1.f);
- btMprVec3Normalize(&dir);
-
-
- btMprSupport(a,b,colDesc, dir, btMprSimplexPointW(portal, 1));
-
- btMprSimplexSetSize(portal, 2);
-
- // test if origin isn't outside of v1
- dot = btMprVec3Dot(&btMprSimplexPoint(portal, 1)->v, &dir);
-
-
- if (btMprIsZero(dot) || dot < 0.f)
- return -1;
-
-
- // vertex 2
- btMprVec3Cross(&dir, &btMprSimplexPoint(portal, 0)->v,
- &btMprSimplexPoint(portal, 1)->v);
- if (btMprIsZero(btMprVec3Len2(&dir))){
- if (btMprVec3Eq(&btMprSimplexPoint(portal, 1)->v, org)){
- // origin lies on v1
- return 1;
- }else{
- // origin lies on v0-v1 segment
- return 2;
- }
- }
-
- btMprVec3Normalize(&dir);
- btMprSupport(a,b,colDesc, dir, btMprSimplexPointW(portal, 2));
-
-
-
- dot = btMprVec3Dot(&btMprSimplexPoint(portal, 2)->v, &dir);
- if (btMprIsZero(dot) || dot < 0.f)
- return -1;
-
- btMprSimplexSetSize(portal, 3);
-
- // vertex 3 direction
- btMprVec3Sub2(&va, &btMprSimplexPoint(portal, 1)->v,
- &btMprSimplexPoint(portal, 0)->v);
- btMprVec3Sub2(&vb, &btMprSimplexPoint(portal, 2)->v,
- &btMprSimplexPoint(portal, 0)->v);
- btMprVec3Cross(&dir, &va, &vb);
- btMprVec3Normalize(&dir);
-
- // it is better to form portal faces to be oriented "outside" origin
- dot = btMprVec3Dot(&dir, &btMprSimplexPoint(portal, 0)->v);
- if (dot > 0.f){
- btMprSimplexSwap(portal, 1, 2);
- btMprVec3Scale(&dir, -1.f);
- }
-
- while (btMprSimplexSize(portal) < 4){
- btMprSupport(a,b,colDesc, dir, btMprSimplexPointW(portal, 3));
-
- dot = btMprVec3Dot(&btMprSimplexPoint(portal, 3)->v, &dir);
- if (btMprIsZero(dot) || dot < 0.f)
- return -1;
-
- cont = 0;
-
- // test if origin is outside (v1, v0, v3) - set v2 as v3 and
- // continue
- btMprVec3Cross(&va, &btMprSimplexPoint(portal, 1)->v,
- &btMprSimplexPoint(portal, 3)->v);
- dot = btMprVec3Dot(&va, &btMprSimplexPoint(portal, 0)->v);
- if (dot < 0.f && !btMprIsZero(dot)){
- btMprSimplexSet(portal, 2, btMprSimplexPoint(portal, 3));
- cont = 1;
- }
-
- if (!cont){
- // test if origin is outside (v3, v0, v2) - set v1 as v3 and
- // continue
- btMprVec3Cross(&va, &btMprSimplexPoint(portal, 3)->v,
- &btMprSimplexPoint(portal, 2)->v);
- dot = btMprVec3Dot(&va, &btMprSimplexPoint(portal, 0)->v);
- if (dot < 0.f && !btMprIsZero(dot)){
- btMprSimplexSet(portal, 1, btMprSimplexPoint(portal, 3));
- cont = 1;
- }
- }
-
- if (cont){
- btMprVec3Sub2(&va, &btMprSimplexPoint(portal, 1)->v,
- &btMprSimplexPoint(portal, 0)->v);
- btMprVec3Sub2(&vb, &btMprSimplexPoint(portal, 2)->v,
- &btMprSimplexPoint(portal, 0)->v);
- btMprVec3Cross(&dir, &va, &vb);
- btMprVec3Normalize(&dir);
- }else{
- btMprSimplexSetSize(portal, 4);
- }
- }
-
- return 0;
+static int btDiscoverPortal(const btConvexTemplate &a, const btConvexTemplate &b,
+ const btMprCollisionDescription &colDesc,
+ btMprSimplex_t *portal)
+{
+ btVector3 dir, va, vb;
+ float dot;
+ int cont;
+
+ // vertex 0 is center of portal
+ btFindOrigin(a, b, colDesc, btMprSimplexPointW(portal, 0));
+
+ // vertex 0 is center of portal
+ btMprSimplexSetSize(portal, 1);
+
+ btVector3 zero = btVector3(0, 0, 0);
+ btVector3 *org = &zero;
+
+ if (btMprVec3Eq(&btMprSimplexPoint(portal, 0)->v, org))
+ {
+ // 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...
+ btMprVec3Set(&va, FLT_EPSILON * 10.f, 0.f, 0.f);
+ btMprVec3Add(&btMprSimplexPointW(portal, 0)->v, &va);
+ }
+
+ // vertex 1 = support in direction of origin
+ btMprVec3Copy(&dir, &btMprSimplexPoint(portal, 0)->v);
+ btMprVec3Scale(&dir, -1.f);
+ btMprVec3Normalize(&dir);
+
+ btMprSupport(a, b, colDesc, dir, btMprSimplexPointW(portal, 1));
+
+ btMprSimplexSetSize(portal, 2);
+
+ // test if origin isn't outside of v1
+ dot = btMprVec3Dot(&btMprSimplexPoint(portal, 1)->v, &dir);
+
+ if (btMprIsZero(dot) || dot < 0.f)
+ return -1;
+
+ // vertex 2
+ btMprVec3Cross(&dir, &btMprSimplexPoint(portal, 0)->v,
+ &btMprSimplexPoint(portal, 1)->v);
+ if (btMprIsZero(btMprVec3Len2(&dir)))
+ {
+ if (btMprVec3Eq(&btMprSimplexPoint(portal, 1)->v, org))
+ {
+ // origin lies on v1
+ return 1;
+ }
+ else
+ {
+ // origin lies on v0-v1 segment
+ return 2;
+ }
+ }
+
+ btMprVec3Normalize(&dir);
+ btMprSupport(a, b, colDesc, dir, btMprSimplexPointW(portal, 2));
+
+ dot = btMprVec3Dot(&btMprSimplexPoint(portal, 2)->v, &dir);
+ if (btMprIsZero(dot) || dot < 0.f)
+ return -1;
+
+ btMprSimplexSetSize(portal, 3);
+
+ // vertex 3 direction
+ btMprVec3Sub2(&va, &btMprSimplexPoint(portal, 1)->v,
+ &btMprSimplexPoint(portal, 0)->v);
+ btMprVec3Sub2(&vb, &btMprSimplexPoint(portal, 2)->v,
+ &btMprSimplexPoint(portal, 0)->v);
+ btMprVec3Cross(&dir, &va, &vb);
+ btMprVec3Normalize(&dir);
+
+ // it is better to form portal faces to be oriented "outside" origin
+ dot = btMprVec3Dot(&dir, &btMprSimplexPoint(portal, 0)->v);
+ if (dot > 0.f)
+ {
+ btMprSimplexSwap(portal, 1, 2);
+ btMprVec3Scale(&dir, -1.f);
+ }
+
+ while (btMprSimplexSize(portal) < 4)
+ {
+ btMprSupport(a, b, colDesc, dir, btMprSimplexPointW(portal, 3));
+
+ dot = btMprVec3Dot(&btMprSimplexPoint(portal, 3)->v, &dir);
+ if (btMprIsZero(dot) || dot < 0.f)
+ return -1;
+
+ cont = 0;
+
+ // test if origin is outside (v1, v0, v3) - set v2 as v3 and
+ // continue
+ btMprVec3Cross(&va, &btMprSimplexPoint(portal, 1)->v,
+ &btMprSimplexPoint(portal, 3)->v);
+ dot = btMprVec3Dot(&va, &btMprSimplexPoint(portal, 0)->v);
+ if (dot < 0.f && !btMprIsZero(dot))
+ {
+ btMprSimplexSet(portal, 2, btMprSimplexPoint(portal, 3));
+ cont = 1;
+ }
+
+ if (!cont)
+ {
+ // test if origin is outside (v3, v0, v2) - set v1 as v3 and
+ // continue
+ btMprVec3Cross(&va, &btMprSimplexPoint(portal, 3)->v,
+ &btMprSimplexPoint(portal, 2)->v);
+ dot = btMprVec3Dot(&va, &btMprSimplexPoint(portal, 0)->v);
+ if (dot < 0.f && !btMprIsZero(dot))
+ {
+ btMprSimplexSet(portal, 1, btMprSimplexPoint(portal, 3));
+ cont = 1;
+ }
+ }
+
+ if (cont)
+ {
+ btMprVec3Sub2(&va, &btMprSimplexPoint(portal, 1)->v,
+ &btMprSimplexPoint(portal, 0)->v);
+ btMprVec3Sub2(&vb, &btMprSimplexPoint(portal, 2)->v,
+ &btMprSimplexPoint(portal, 0)->v);
+ btMprVec3Cross(&dir, &va, &vb);
+ btMprVec3Normalize(&dir);
+ }
+ else
+ {
+ btMprSimplexSetSize(portal, 4);
+ }
+ }
+
+ return 0;
}
template <typename btConvexTemplate>
-static int btRefinePortal(const btConvexTemplate& a, const btConvexTemplate& b,const btMprCollisionDescription& colDesc,
- btMprSimplex_t *portal)
+static int btRefinePortal(const btConvexTemplate &a, const btConvexTemplate &b, const btMprCollisionDescription &colDesc,
+ btMprSimplex_t *portal)
{
- btVector3 dir;
- btMprSupport_t v4;
+ btVector3 dir;
+ btMprSupport_t v4;
- for (int i=0;i<BT_MPR_MAX_ITERATIONS;i++)
- //while (1)
+ for (int i = 0; i < BT_MPR_MAX_ITERATIONS; i++)
+ //while (1)
{
- // compute direction outside the portal (from v0 throught v1,v2,v3
- // face)
- btPortalDir(portal, &dir);
+ // compute direction outside the portal (from v0 throught v1,v2,v3
+ // face)
+ btPortalDir(portal, &dir);
- // test if origin is inside the portal
- if (portalEncapsulesOrigin(portal, &dir))
- return 0;
+ // test if origin is inside the portal
+ if (portalEncapsulesOrigin(portal, &dir))
+ return 0;
- // get next support point
-
- btMprSupport(a,b,colDesc, dir, &v4);
+ // get next support point
+ btMprSupport(a, b, colDesc, dir, &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))
+ // 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))
{
- return -1;
- }
+ return -1;
+ }
- // v1-v2-v3 triangle must be rearranged to face outside Minkowski
- // difference (direction from v0).
- btExpandPortal(portal, &v4);
- }
+ // v1-v2-v3 triangle must be rearranged to face outside Minkowski
+ // difference (direction from v0).
+ btExpandPortal(portal, &v4);
+ }
- return -1;
+ return -1;
}
static void btFindPos(const btMprSimplex_t *portal, btVector3 *pos)
{
+ btVector3 zero = btVector3(0, 0, 0);
+ btVector3 *origin = &zero;
- btVector3 zero = btVector3(0,0,0);
- btVector3* origin = &zero;
-
- btVector3 dir;
- size_t i;
- float b[4], sum, inv;
- btVector3 vec, p1, p2;
+ btVector3 dir;
+ size_t i;
+ float b[4], sum, inv;
+ btVector3 vec, p1, p2;
- btPortalDir(portal, &dir);
+ btPortalDir(portal, &dir);
- // use barycentric coordinates of tetrahedron to find origin
- btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 1)->v,
- &btMprSimplexPoint(portal, 2)->v);
- b[0] = btMprVec3Dot(&vec, &btMprSimplexPoint(portal, 3)->v);
+ // use barycentric coordinates of tetrahedron to find origin
+ btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 1)->v,
+ &btMprSimplexPoint(portal, 2)->v);
+ b[0] = btMprVec3Dot(&vec, &btMprSimplexPoint(portal, 3)->v);
- btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 3)->v,
- &btMprSimplexPoint(portal, 2)->v);
- b[1] = btMprVec3Dot(&vec, &btMprSimplexPoint(portal, 0)->v);
+ btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 3)->v,
+ &btMprSimplexPoint(portal, 2)->v);
+ b[1] = btMprVec3Dot(&vec, &btMprSimplexPoint(portal, 0)->v);
- btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 0)->v,
- &btMprSimplexPoint(portal, 1)->v);
- b[2] = btMprVec3Dot(&vec, &btMprSimplexPoint(portal, 3)->v);
+ btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 0)->v,
+ &btMprSimplexPoint(portal, 1)->v);
+ b[2] = btMprVec3Dot(&vec, &btMprSimplexPoint(portal, 3)->v);
- btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 2)->v,
- &btMprSimplexPoint(portal, 1)->v);
- b[3] = btMprVec3Dot(&vec, &btMprSimplexPoint(portal, 0)->v);
+ btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 2)->v,
+ &btMprSimplexPoint(portal, 1)->v);
+ b[3] = btMprVec3Dot(&vec, &btMprSimplexPoint(portal, 0)->v);
sum = b[0] + b[1] + b[2] + b[3];
- if (btMprIsZero(sum) || sum < 0.f){
+ if (btMprIsZero(sum) || sum < 0.f)
+ {
b[0] = 0.f;
- btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 2)->v,
- &btMprSimplexPoint(portal, 3)->v);
- b[1] = btMprVec3Dot(&vec, &dir);
- btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 3)->v,
- &btMprSimplexPoint(portal, 1)->v);
- b[2] = btMprVec3Dot(&vec, &dir);
- btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 1)->v,
- &btMprSimplexPoint(portal, 2)->v);
- b[3] = btMprVec3Dot(&vec, &dir);
+ btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 2)->v,
+ &btMprSimplexPoint(portal, 3)->v);
+ b[1] = btMprVec3Dot(&vec, &dir);
+ btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 3)->v,
+ &btMprSimplexPoint(portal, 1)->v);
+ b[2] = btMprVec3Dot(&vec, &dir);
+ btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 1)->v,
+ &btMprSimplexPoint(portal, 2)->v);
+ b[3] = btMprVec3Dot(&vec, &dir);
sum = b[1] + b[2] + b[3];
}
inv = 1.f / sum;
- btMprVec3Copy(&p1, origin);
- btMprVec3Copy(&p2, origin);
- for (i = 0; i < 4; i++){
- btMprVec3Copy(&vec, &btMprSimplexPoint(portal, i)->v1);
- btMprVec3Scale(&vec, b[i]);
- btMprVec3Add(&p1, &vec);
-
- btMprVec3Copy(&vec, &btMprSimplexPoint(portal, i)->v2);
- btMprVec3Scale(&vec, b[i]);
- btMprVec3Add(&p2, &vec);
- }
- btMprVec3Scale(&p1, inv);
- btMprVec3Scale(&p2, inv);
+ btMprVec3Copy(&p1, origin);
+ btMprVec3Copy(&p2, origin);
+ for (i = 0; i < 4; i++)
+ {
+ btMprVec3Copy(&vec, &btMprSimplexPoint(portal, i)->v1);
+ btMprVec3Scale(&vec, b[i]);
+ btMprVec3Add(&p1, &vec);
+
+ btMprVec3Copy(&vec, &btMprSimplexPoint(portal, i)->v2);
+ btMprVec3Scale(&vec, b[i]);
+ btMprVec3Add(&p2, &vec);
+ }
+ btMprVec3Scale(&p1, inv);
+ btMprVec3Scale(&p2, inv);
#ifdef MPR_AVERAGE_CONTACT_POSITIONS
- btMprVec3Copy(pos, &p1);
- btMprVec3Add(pos, &p2);
- btMprVec3Scale(pos, 0.5);
+ btMprVec3Copy(pos, &p1);
+ btMprVec3Add(pos, &p2);
+ btMprVec3Scale(pos, 0.5);
#else
- btMprVec3Copy(pos, &p2);
-#endif//MPR_AVERAGE_CONTACT_POSITIONS
+ btMprVec3Copy(pos, &p2);
+#endif //MPR_AVERAGE_CONTACT_POSITIONS
}
inline float btMprVec3Dist2(const btVector3 *a, const btVector3 *b)
{
- btVector3 ab;
- btMprVec3Sub2(&ab, a, b);
- return btMprVec3Len2(&ab);
+ btVector3 ab;
+ btMprVec3Sub2(&ab, a, b);
+ return btMprVec3Len2(&ab);
}
inline float _btMprVec3PointSegmentDist2(const btVector3 *P,
- const btVector3 *x0,
- const btVector3 *b,
- btVector3 *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.
-
- float dist, t;
- btVector3 d, a;
-
- // direction of segment
- btMprVec3Sub2(&d, b, x0);
-
- // precompute vector from P to x0
- btMprVec3Sub2(&a, x0, P);
-
- t = -1.f * btMprVec3Dot(&a, &d);
- t /= btMprVec3Len2(&d);
-
- if (t < 0.f || btMprIsZero(t)){
- dist = btMprVec3Dist2(x0, P);
- if (witness)
- btMprVec3Copy(witness, x0);
- }else if (t > 1.f || btMprEq(t, 1.f)){
- dist = btMprVec3Dist2(b, P);
- if (witness)
- btMprVec3Copy(witness, b);
- }else{
- if (witness){
- btMprVec3Copy(witness, &d);
- btMprVec3Scale(witness, t);
- btMprVec3Add(witness, x0);
- dist = btMprVec3Dist2(witness, P);
- }else{
- // recycling variables
- btMprVec3Scale(&d, t);
- btMprVec3Add(&d, &a);
- dist = btMprVec3Len2(&d);
- }
- }
-
- return dist;
-}
-
+ const btVector3 *x0,
+ const btVector3 *b,
+ btVector3 *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.
+
+ float dist, t;
+ btVector3 d, a;
+
+ // direction of segment
+ btMprVec3Sub2(&d, b, x0);
+
+ // precompute vector from P to x0
+ btMprVec3Sub2(&a, x0, P);
+
+ t = -1.f * btMprVec3Dot(&a, &d);
+ t /= btMprVec3Len2(&d);
+
+ if (t < 0.f || btMprIsZero(t))
+ {
+ dist = btMprVec3Dist2(x0, P);
+ if (witness)
+ btMprVec3Copy(witness, x0);
+ }
+ else if (t > 1.f || btMprEq(t, 1.f))
+ {
+ dist = btMprVec3Dist2(b, P);
+ if (witness)
+ btMprVec3Copy(witness, b);
+ }
+ else
+ {
+ if (witness)
+ {
+ btMprVec3Copy(witness, &d);
+ btMprVec3Scale(witness, t);
+ btMprVec3Add(witness, x0);
+ dist = btMprVec3Dist2(witness, P);
+ }
+ else
+ {
+ // recycling variables
+ btMprVec3Scale(&d, t);
+ btMprVec3Add(&d, &a);
+ dist = btMprVec3Len2(&d);
+ }
+ }
+ return dist;
+}
inline float btMprVec3PointTriDist2(const btVector3 *P,
- const btVector3 *x0, const btVector3 *B,
- const btVector3 *C,
- btVector3 *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.
-
- btVector3 d1, d2, a;
- float u, v, w, p, q, r;
- float s, t, dist, dist2;
- btVector3 witness2;
-
- btMprVec3Sub2(&d1, B, x0);
- btMprVec3Sub2(&d2, C, x0);
- btMprVec3Sub2(&a, x0, P);
-
- u = btMprVec3Dot(&a, &a);
- v = btMprVec3Dot(&d1, &d1);
- w = btMprVec3Dot(&d2, &d2);
- p = btMprVec3Dot(&a, &d1);
- q = btMprVec3Dot(&a, &d2);
- r = btMprVec3Dot(&d1, &d2);
+ const btVector3 *x0, const btVector3 *B,
+ const btVector3 *C,
+ btVector3 *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.
+
+ btVector3 d1, d2, a;
+ float u, v, w, p, q, r;
+ float s, t, dist, dist2;
+ btVector3 witness2;
+
+ btMprVec3Sub2(&d1, B, x0);
+ btMprVec3Sub2(&d2, C, x0);
+ btMprVec3Sub2(&a, x0, P);
+
+ u = btMprVec3Dot(&a, &a);
+ v = btMprVec3Dot(&d1, &d1);
+ w = btMprVec3Dot(&d2, &d2);
+ p = btMprVec3Dot(&a, &d1);
+ q = btMprVec3Dot(&a, &d2);
+ r = btMprVec3Dot(&d1, &d2);
btScalar div = (w * v - r * r);
if (btMprIsZero(div))
{
- s=-1;
- } else
+ s = -1;
+ }
+ else
{
s = (q * r - w * p) / div;
t = (-s * r - q) / w;
}
- if ((btMprIsZero(s) || s > 0.f)
- && (btMprEq(s, 1.f) || s < 1.f)
- && (btMprIsZero(t) || t > 0.f)
- && (btMprEq(t, 1.f) || t < 1.f)
- && (btMprEq(t + s, 1.f) || t + s < 1.f)){
-
- if (witness){
- btMprVec3Scale(&d1, s);
- btMprVec3Scale(&d2, t);
- btMprVec3Copy(witness, x0);
- btMprVec3Add(witness, &d1);
- btMprVec3Add(witness, &d2);
-
- dist = btMprVec3Dist2(witness, P);
- }else{
- dist = s * s * v;
- dist += t * t * w;
- dist += 2.f * s * t * r;
- dist += 2.f * s * p;
- dist += 2.f * t * q;
- dist += u;
- }
- }else{
- dist = _btMprVec3PointSegmentDist2(P, x0, B, witness);
-
- dist2 = _btMprVec3PointSegmentDist2(P, x0, C, &witness2);
- if (dist2 < dist){
- dist = dist2;
- if (witness)
- btMprVec3Copy(witness, &witness2);
- }
-
- dist2 = _btMprVec3PointSegmentDist2(P, B, C, &witness2);
- if (dist2 < dist){
- dist = dist2;
- if (witness)
- btMprVec3Copy(witness, &witness2);
- }
- }
-
- return dist;
+ if ((btMprIsZero(s) || s > 0.f) && (btMprEq(s, 1.f) || s < 1.f) && (btMprIsZero(t) || t > 0.f) && (btMprEq(t, 1.f) || t < 1.f) && (btMprEq(t + s, 1.f) || t + s < 1.f))
+ {
+ if (witness)
+ {
+ btMprVec3Scale(&d1, s);
+ btMprVec3Scale(&d2, t);
+ btMprVec3Copy(witness, x0);
+ btMprVec3Add(witness, &d1);
+ btMprVec3Add(witness, &d2);
+
+ dist = btMprVec3Dist2(witness, P);
+ }
+ else
+ {
+ dist = s * s * v;
+ dist += t * t * w;
+ dist += 2.f * s * t * r;
+ dist += 2.f * s * p;
+ dist += 2.f * t * q;
+ dist += u;
+ }
+ }
+ else
+ {
+ dist = _btMprVec3PointSegmentDist2(P, x0, B, witness);
+
+ dist2 = _btMprVec3PointSegmentDist2(P, x0, C, &witness2);
+ if (dist2 < dist)
+ {
+ dist = dist2;
+ if (witness)
+ btMprVec3Copy(witness, &witness2);
+ }
+
+ dist2 = _btMprVec3PointSegmentDist2(P, B, C, &witness2);
+ if (dist2 < dist)
+ {
+ dist = dist2;
+ if (witness)
+ btMprVec3Copy(witness, &witness2);
+ }
+ }
+
+ return dist;
}
template <typename btConvexTemplate>
-static void btFindPenetr(const btConvexTemplate& a, const btConvexTemplate& b,
- const btMprCollisionDescription& colDesc,
- btMprSimplex_t *portal,
- float *depth, btVector3 *pdir, btVector3 *pos)
+static void btFindPenetr(const btConvexTemplate &a, const btConvexTemplate &b,
+ const btMprCollisionDescription &colDesc,
+ btMprSimplex_t *portal,
+ float *depth, btVector3 *pdir, btVector3 *pos)
{
- btVector3 dir;
- btMprSupport_t v4;
- unsigned long iterations;
+ btVector3 dir;
+ btMprSupport_t v4;
+ unsigned long iterations;
- btVector3 zero = btVector3(0,0,0);
- btVector3* origin = &zero;
+ btVector3 zero = btVector3(0, 0, 0);
+ btVector3 *origin = &zero;
-
- iterations = 1UL;
- for (int i=0;i<BT_MPR_MAX_ITERATIONS;i++)
- //while (1)
+ iterations = 1UL;
+ for (int i = 0; i < BT_MPR_MAX_ITERATIONS; i++)
+ //while (1)
{
- // compute portal direction and obtain next support point
- btPortalDir(portal, &dir);
-
- btMprSupport(a,b,colDesc, dir, &v4);
+ // compute portal direction and obtain next support point
+ btPortalDir(portal, &dir);
+ btMprSupport(a, b, colDesc, dir, &v4);
- // reached tolerance -> find penetration info
- if (portalReachTolerance(portal, &v4, &dir)
- || iterations ==BT_MPR_MAX_ITERATIONS)
+ // reached tolerance -> find penetration info
+ if (portalReachTolerance(portal, &v4, &dir) || iterations == BT_MPR_MAX_ITERATIONS)
{
- *depth = btMprVec3PointTriDist2(origin,&btMprSimplexPoint(portal, 1)->v,&btMprSimplexPoint(portal, 2)->v,&btMprSimplexPoint(portal, 3)->v,pdir);
- *depth = BT_MPR_SQRT(*depth);
-
+ *depth = btMprVec3PointTriDist2(origin, &btMprSimplexPoint(portal, 1)->v, &btMprSimplexPoint(portal, 2)->v, &btMprSimplexPoint(portal, 3)->v, pdir);
+ *depth = BT_MPR_SQRT(*depth);
+
if (btMprIsZero((*pdir).x()) && btMprIsZero((*pdir).y()) && btMprIsZero((*pdir).z()))
{
-
*pdir = dir;
- }
+ }
btMprVec3Normalize(pdir);
-
- // barycentric coordinates:
- btFindPos(portal, pos);
+ // barycentric coordinates:
+ btFindPos(portal, pos);
- return;
- }
+ return;
+ }
- btExpandPortal(portal, &v4);
+ btExpandPortal(portal, &v4);
- iterations++;
- }
+ iterations++;
+ }
}
-static void btFindPenetrTouch(btMprSimplex_t *portal,float *depth, btVector3 *dir, btVector3 *pos)
+static void btFindPenetrTouch(btMprSimplex_t *portal, float *depth, btVector3 *dir, btVector3 *pos)
{
- // Touching contact on portal's v1 - so depth is zero and direction
- // is unimportant and pos can be guessed
- *depth = 0.f;
- btVector3 zero = btVector3(0,0,0);
- btVector3* origin = &zero;
-
+ // Touching contact on portal's v1 - so depth is zero and direction
+ // is unimportant and pos can be guessed
+ *depth = 0.f;
+ btVector3 zero = btVector3(0, 0, 0);
+ btVector3 *origin = &zero;
btMprVec3Copy(dir, origin);
#ifdef MPR_AVERAGE_CONTACT_POSITIONS
- btMprVec3Copy(pos, &btMprSimplexPoint(portal, 1)->v1);
- btMprVec3Add(pos, &btMprSimplexPoint(portal, 1)->v2);
- btMprVec3Scale(pos, 0.5);
+ btMprVec3Copy(pos, &btMprSimplexPoint(portal, 1)->v1);
+ btMprVec3Add(pos, &btMprSimplexPoint(portal, 1)->v2);
+ btMprVec3Scale(pos, 0.5);
#else
- btMprVec3Copy(pos, &btMprSimplexPoint(portal, 1)->v2);
+ btMprVec3Copy(pos, &btMprSimplexPoint(portal, 1)->v2);
#endif
}
static void btFindPenetrSegment(btMprSimplex_t *portal,
- float *depth, btVector3 *dir, btVector3 *pos)
+ float *depth, btVector3 *dir, btVector3 *pos)
{
-
- // Origin lies on v0-v1 segment.
- // Depth is distance to v1, direction also and position must be
- // computed
+ // Origin lies on v0-v1 segment.
+ // Depth is distance to v1, direction also and position must be
+ // computed
#ifdef MPR_AVERAGE_CONTACT_POSITIONS
- btMprVec3Copy(pos, &btMprSimplexPoint(portal, 1)->v1);
- btMprVec3Add(pos, &btMprSimplexPoint(portal, 1)->v2);
- btMprVec3Scale(pos, 0.5f);
+ btMprVec3Copy(pos, &btMprSimplexPoint(portal, 1)->v1);
+ btMprVec3Add(pos, &btMprSimplexPoint(portal, 1)->v2);
+ btMprVec3Scale(pos, 0.5f);
#else
- btMprVec3Copy(pos, &btMprSimplexPoint(portal, 1)->v2);
-#endif//MPR_AVERAGE_CONTACT_POSITIONS
-
- btMprVec3Copy(dir, &btMprSimplexPoint(portal, 1)->v);
- *depth = BT_MPR_SQRT(btMprVec3Len2(dir));
- btMprVec3Normalize(dir);
+ btMprVec3Copy(pos, &btMprSimplexPoint(portal, 1)->v2);
+#endif //MPR_AVERAGE_CONTACT_POSITIONS
-
+ btMprVec3Copy(dir, &btMprSimplexPoint(portal, 1)->v);
+ *depth = BT_MPR_SQRT(btMprVec3Len2(dir));
+ btMprVec3Normalize(dir);
}
-
template <typename btConvexTemplate>
-inline int btMprPenetration( const btConvexTemplate& a, const btConvexTemplate& b,
- const btMprCollisionDescription& colDesc,
- float *depthOut, btVector3* dirOut, btVector3* posOut)
+inline int btMprPenetration(const btConvexTemplate &a, const btConvexTemplate &b,
+ const btMprCollisionDescription &colDesc,
+ float *depthOut, btVector3 *dirOut, btVector3 *posOut)
{
-
- btMprSimplex_t portal;
+ btMprSimplex_t portal;
+ // Phase 1: Portal discovery
+ int result = btDiscoverPortal(a, b, colDesc, &portal);
- // Phase 1: Portal discovery
- int result = btDiscoverPortal(a,b,colDesc, &portal);
-
-
//sepAxis[pairIndex] = *pdir;//or -dir?
switch (result)
{
- case 0:
+ case 0:
{
// Phase 2: Portal refinement
-
- result = btRefinePortal(a,b,colDesc, &portal);
+
+ result = btRefinePortal(a, b, colDesc, &portal);
if (result < 0)
return -1;
// Phase 3. Penetration info
- btFindPenetr(a,b,colDesc, &portal, depthOut, dirOut, posOut);
-
-
+ btFindPenetr(a, b, colDesc, &portal, depthOut, dirOut, posOut);
+
break;
}
- case 1:
+ case 1:
{
- // Touching contact on portal's v1.
+ // Touching contact on portal's v1.
btFindPenetrTouch(&portal, depthOut, dirOut, posOut);
- result=0;
+ result = 0;
break;
}
- case 2:
+ case 2:
{
-
- btFindPenetrSegment( &portal, depthOut, dirOut, posOut);
- result=0;
+ btFindPenetrSegment(&portal, depthOut, dirOut, posOut);
+ result = 0;
break;
}
- default:
+ default:
{
//if (res < 0)
//{
- // Origin isn't inside portal - no collision.
- result = -1;
+ // Origin isn't inside portal - no collision.
+ result = -1;
//}
}
};
-
+
return result;
};
-
-template<typename btConvexTemplate, typename btMprDistanceTemplate>
-inline int btComputeMprPenetration( const btConvexTemplate& a, const btConvexTemplate& b, const
- btMprCollisionDescription& colDesc, btMprDistanceTemplate* distInfo)
+template <typename btConvexTemplate, typename btMprDistanceTemplate>
+inline int btComputeMprPenetration(const btConvexTemplate &a, const btConvexTemplate &b, const btMprCollisionDescription &colDesc, btMprDistanceTemplate *distInfo)
{
- btVector3 dir,pos;
+ btVector3 dir, pos;
float depth;
- int res = btMprPenetration(a,b,colDesc,&depth, &dir, &pos);
- if (res==0)
+ int res = btMprPenetration(a, b, colDesc, &depth, &dir, &pos);
+ if (res == 0)
{
distInfo->m_distance = -depth;
distInfo->m_pointOnB = pos;
distInfo->m_normalBtoA = -dir;
- distInfo->m_pointOnA = pos-distInfo->m_distance*dir;
+ distInfo->m_pointOnA = pos - distInfo->m_distance * dir;
return 0;
}
return -1;
}
-
-
-#endif //BT_MPR_PENETRATION_H
+#endif //BT_MPR_PENETRATION_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp
index 9603a8bbdc..f1422cad4d 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp
@@ -13,7 +13,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#include "btPersistentManifold.h"
#include "LinearMath/btTransform.h"
#include "LinearMath/btSerializer.h"
@@ -24,83 +23,76 @@ subject to the following restrictions:
#define btCollisionObjectData btCollisionObjectFloatData
#endif
-btScalar gContactBreakingThreshold = btScalar(0.02);
-ContactDestroyedCallback gContactDestroyedCallback = 0;
-ContactProcessedCallback gContactProcessedCallback = 0;
-ContactStartedCallback gContactStartedCallback = 0;
-ContactEndedCallback gContactEndedCallback = 0;
+btScalar gContactBreakingThreshold = btScalar(0.02);
+ContactDestroyedCallback gContactDestroyedCallback = 0;
+ContactProcessedCallback gContactProcessedCallback = 0;
+ContactStartedCallback gContactStartedCallback = 0;
+ContactEndedCallback gContactEndedCallback = 0;
///gContactCalcArea3Points will approximate the convex hull area using 3 points
///when setting it to false, it will use 4 points to compute the area: it is more accurate but slower
-bool gContactCalcArea3Points = true;
-
+bool gContactCalcArea3Points = true;
btPersistentManifold::btPersistentManifold()
-:btTypedObject(BT_PERSISTENT_MANIFOLD_TYPE),
-m_body0(0),
-m_body1(0),
-m_cachedPoints (0),
-m_companionIdA(0),
-m_companionIdB(0),
-m_index1a(0)
+ : btTypedObject(BT_PERSISTENT_MANIFOLD_TYPE),
+ m_body0(0),
+ m_body1(0),
+ m_cachedPoints(0),
+ m_companionIdA(0),
+ m_companionIdB(0),
+ m_index1a(0)
{
}
-
-
-
#ifdef DEBUG_PERSISTENCY
#include <stdio.h>
-void btPersistentManifold::DebugPersistency()
+void btPersistentManifold::DebugPersistency()
{
int i;
- printf("DebugPersistency : numPoints %d\n",m_cachedPoints);
- for (i=0;i<m_cachedPoints;i++)
+ printf("DebugPersistency : numPoints %d\n", m_cachedPoints);
+ for (i = 0; i < m_cachedPoints; i++)
{
- printf("m_pointCache[%d].m_userPersistentData = %x\n",i,m_pointCache[i].m_userPersistentData);
+ printf("m_pointCache[%d].m_userPersistentData = %x\n", i, m_pointCache[i].m_userPersistentData);
}
}
-#endif //DEBUG_PERSISTENCY
+#endif //DEBUG_PERSISTENCY
void btPersistentManifold::clearUserCache(btManifoldPoint& pt)
{
-
void* oldPtr = pt.m_userPersistentData;
if (oldPtr)
{
#ifdef DEBUG_PERSISTENCY
int i;
int occurance = 0;
- for (i=0;i<m_cachedPoints;i++)
+ for (i = 0; i < m_cachedPoints; i++)
{
if (m_pointCache[i].m_userPersistentData == oldPtr)
{
occurance++;
- if (occurance>1)
+ if (occurance > 1)
printf("error in clearUserCache\n");
}
}
- btAssert(occurance<=0);
-#endif //DEBUG_PERSISTENCY
+ btAssert(occurance <= 0);
+#endif //DEBUG_PERSISTENCY
if (pt.m_userPersistentData && gContactDestroyedCallback)
{
(*gContactDestroyedCallback)(pt.m_userPersistentData);
pt.m_userPersistentData = 0;
}
-
+
#ifdef DEBUG_PERSISTENCY
DebugPersistency();
#endif
}
-
-
}
-static inline btScalar calcArea4Points(const btVector3 &p0,const btVector3 &p1,const btVector3 &p2,const btVector3 &p3)
+static inline btScalar calcArea4Points(const btVector3& p0, const btVector3& p1, const btVector3& p2, const btVector3& p3)
{
// It calculates possible 3 area constructed from random 4 points and returns the biggest one.
- btVector3 a[3],b[3];
+ btVector3 a[3], b[3];
a[0] = p0 - p1;
a[1] = p0 - p2;
a[2] = p0 - p3;
@@ -113,100 +105,102 @@ static inline btScalar calcArea4Points(const btVector3 &p0,const btVector3 &p1,c
btVector3 tmp1 = a[1].cross(b[1]);
btVector3 tmp2 = a[2].cross(b[2]);
- return btMax(btMax(tmp0.length2(),tmp1.length2()),tmp2.length2());
+ return btMax(btMax(tmp0.length2(), tmp1.length2()), tmp2.length2());
}
-int btPersistentManifold::sortCachedPoints(const btManifoldPoint& pt)
+int btPersistentManifold::sortCachedPoints(const btManifoldPoint& pt)
{
- //calculate 4 possible cases areas, and take biggest area
- //also need to keep 'deepest'
-
- int maxPenetrationIndex = -1;
+ //calculate 4 possible cases areas, and take biggest area
+ //also need to keep 'deepest'
+
+ int maxPenetrationIndex = -1;
#define KEEP_DEEPEST_POINT 1
#ifdef KEEP_DEEPEST_POINT
- btScalar maxPenetration = pt.getDistance();
- for (int i=0;i<4;i++)
+ btScalar maxPenetration = pt.getDistance();
+ for (int i = 0; i < 4; i++)
+ {
+ if (m_pointCache[i].getDistance() < maxPenetration)
{
- if (m_pointCache[i].getDistance() < maxPenetration)
- {
- maxPenetrationIndex = i;
- maxPenetration = m_pointCache[i].getDistance();
- }
+ maxPenetrationIndex = i;
+ maxPenetration = m_pointCache[i].getDistance();
}
-#endif //KEEP_DEEPEST_POINT
-
- btScalar res0(btScalar(0.)),res1(btScalar(0.)),res2(btScalar(0.)),res3(btScalar(0.));
+ }
+#endif //KEEP_DEEPEST_POINT
+
+ btScalar res0(btScalar(0.)), res1(btScalar(0.)), res2(btScalar(0.)), res3(btScalar(0.));
if (gContactCalcArea3Points)
{
if (maxPenetrationIndex != 0)
{
- btVector3 a0 = pt.m_localPointA-m_pointCache[1].m_localPointA;
- btVector3 b0 = m_pointCache[3].m_localPointA-m_pointCache[2].m_localPointA;
+ btVector3 a0 = pt.m_localPointA - m_pointCache[1].m_localPointA;
+ btVector3 b0 = m_pointCache[3].m_localPointA - m_pointCache[2].m_localPointA;
btVector3 cross = a0.cross(b0);
res0 = cross.length2();
}
if (maxPenetrationIndex != 1)
{
- btVector3 a1 = pt.m_localPointA-m_pointCache[0].m_localPointA;
- btVector3 b1 = m_pointCache[3].m_localPointA-m_pointCache[2].m_localPointA;
+ btVector3 a1 = pt.m_localPointA - m_pointCache[0].m_localPointA;
+ btVector3 b1 = m_pointCache[3].m_localPointA - m_pointCache[2].m_localPointA;
btVector3 cross = a1.cross(b1);
res1 = cross.length2();
}
if (maxPenetrationIndex != 2)
{
- btVector3 a2 = pt.m_localPointA-m_pointCache[0].m_localPointA;
- btVector3 b2 = m_pointCache[3].m_localPointA-m_pointCache[1].m_localPointA;
+ btVector3 a2 = pt.m_localPointA - m_pointCache[0].m_localPointA;
+ btVector3 b2 = m_pointCache[3].m_localPointA - m_pointCache[1].m_localPointA;
btVector3 cross = a2.cross(b2);
res2 = cross.length2();
}
if (maxPenetrationIndex != 3)
{
- btVector3 a3 = pt.m_localPointA-m_pointCache[0].m_localPointA;
- btVector3 b3 = m_pointCache[2].m_localPointA-m_pointCache[1].m_localPointA;
+ btVector3 a3 = pt.m_localPointA - m_pointCache[0].m_localPointA;
+ btVector3 b3 = m_pointCache[2].m_localPointA - m_pointCache[1].m_localPointA;
btVector3 cross = a3.cross(b3);
res3 = cross.length2();
}
- }
+ }
else
{
- if(maxPenetrationIndex != 0) {
- res0 = calcArea4Points(pt.m_localPointA,m_pointCache[1].m_localPointA,m_pointCache[2].m_localPointA,m_pointCache[3].m_localPointA);
+ if (maxPenetrationIndex != 0)
+ {
+ res0 = calcArea4Points(pt.m_localPointA, m_pointCache[1].m_localPointA, m_pointCache[2].m_localPointA, m_pointCache[3].m_localPointA);
}
- if(maxPenetrationIndex != 1) {
- res1 = calcArea4Points(pt.m_localPointA,m_pointCache[0].m_localPointA,m_pointCache[2].m_localPointA,m_pointCache[3].m_localPointA);
+ if (maxPenetrationIndex != 1)
+ {
+ res1 = calcArea4Points(pt.m_localPointA, m_pointCache[0].m_localPointA, m_pointCache[2].m_localPointA, m_pointCache[3].m_localPointA);
}
- if(maxPenetrationIndex != 2) {
- res2 = calcArea4Points(pt.m_localPointA,m_pointCache[0].m_localPointA,m_pointCache[1].m_localPointA,m_pointCache[3].m_localPointA);
+ if (maxPenetrationIndex != 2)
+ {
+ res2 = calcArea4Points(pt.m_localPointA, m_pointCache[0].m_localPointA, m_pointCache[1].m_localPointA, m_pointCache[3].m_localPointA);
}
- if(maxPenetrationIndex != 3) {
- res3 = calcArea4Points(pt.m_localPointA,m_pointCache[0].m_localPointA,m_pointCache[1].m_localPointA,m_pointCache[2].m_localPointA);
+ if (maxPenetrationIndex != 3)
+ {
+ res3 = calcArea4Points(pt.m_localPointA, m_pointCache[0].m_localPointA, m_pointCache[1].m_localPointA, m_pointCache[2].m_localPointA);
}
}
- btVector4 maxvec(res0,res1,res2,res3);
+ btVector4 maxvec(res0, res1, res2, res3);
int biggestarea = maxvec.closestAxis4();
return biggestarea;
-
}
-
int btPersistentManifold::getCacheEntry(const btManifoldPoint& newPoint) const
{
- btScalar shortestDist = getContactBreakingThreshold() * getContactBreakingThreshold();
+ btScalar shortestDist = getContactBreakingThreshold() * getContactBreakingThreshold();
int size = getNumContacts();
int nearestPoint = -1;
- for( int i = 0; i < size; i++ )
+ for (int i = 0; i < size; i++)
{
- const btManifoldPoint &mp = m_pointCache[i];
+ const btManifoldPoint& mp = m_pointCache[i];
- btVector3 diffA = mp.m_localPointA- newPoint.m_localPointA;
+ btVector3 diffA = mp.m_localPointA - newPoint.m_localPointA;
const btScalar distToManiPoint = diffA.dot(diffA);
- if( distToManiPoint < shortestDist )
+ if (distToManiPoint < shortestDist)
{
shortestDist = distToManiPoint;
nearestPoint = i;
@@ -221,7 +215,7 @@ int btPersistentManifold::addManifoldPoint(const btManifoldPoint& newPoint, bool
{
btAssert(validContactDistance(newPoint));
}
-
+
int insertIndex = getNumContacts();
if (insertIndex == MANIFOLD_CACHE_SIZE)
{
@@ -232,91 +226,87 @@ int btPersistentManifold::addManifoldPoint(const btManifoldPoint& newPoint, bool
insertIndex = 0;
#endif
clearUserCache(m_pointCache[insertIndex]);
-
- } else
+ }
+ else
{
m_cachedPoints++;
-
-
}
- if (insertIndex<0)
- insertIndex=0;
+ if (insertIndex < 0)
+ insertIndex = 0;
- btAssert(m_pointCache[insertIndex].m_userPersistentData==0);
+ btAssert(m_pointCache[insertIndex].m_userPersistentData == 0);
m_pointCache[insertIndex] = newPoint;
return insertIndex;
}
-btScalar btPersistentManifold::getContactBreakingThreshold() const
+btScalar btPersistentManifold::getContactBreakingThreshold() const
{
return m_contactBreakingThreshold;
}
-
-
-void btPersistentManifold::refreshContactPoints(const btTransform& trA,const btTransform& trB)
+void btPersistentManifold::refreshContactPoints(const btTransform& trA, const btTransform& trB)
{
int i;
#ifdef DEBUG_PERSISTENCY
printf("refreshContactPoints posA = (%f,%f,%f) posB = (%f,%f,%f)\n",
- trA.getOrigin().getX(),
- trA.getOrigin().getY(),
- trA.getOrigin().getZ(),
- trB.getOrigin().getX(),
- trB.getOrigin().getY(),
- trB.getOrigin().getZ());
-#endif //DEBUG_PERSISTENCY
+ trA.getOrigin().getX(),
+ trA.getOrigin().getY(),
+ trA.getOrigin().getZ(),
+ trB.getOrigin().getX(),
+ trB.getOrigin().getY(),
+ trB.getOrigin().getZ());
+#endif //DEBUG_PERSISTENCY
/// first refresh worldspace positions and distance
- for (i=getNumContacts()-1;i>=0;i--)
+ for (i = getNumContacts() - 1; i >= 0; i--)
{
- btManifoldPoint &manifoldPoint = m_pointCache[i];
- manifoldPoint.m_positionWorldOnA = trA( manifoldPoint.m_localPointA );
- manifoldPoint.m_positionWorldOnB = trB( manifoldPoint.m_localPointB );
- manifoldPoint.m_distance1 = (manifoldPoint.m_positionWorldOnA - manifoldPoint.m_positionWorldOnB).dot(manifoldPoint.m_normalWorldOnB);
+ btManifoldPoint& manifoldPoint = m_pointCache[i];
+ manifoldPoint.m_positionWorldOnA = trA(manifoldPoint.m_localPointA);
+ manifoldPoint.m_positionWorldOnB = trB(manifoldPoint.m_localPointB);
+ manifoldPoint.m_distance1 = (manifoldPoint.m_positionWorldOnA - manifoldPoint.m_positionWorldOnB).dot(manifoldPoint.m_normalWorldOnB);
manifoldPoint.m_lifeTime++;
}
- /// then
+ /// then
btScalar distance2d;
- btVector3 projectedDifference,projectedPoint;
- for (i=getNumContacts()-1;i>=0;i--)
+ btVector3 projectedDifference, projectedPoint;
+ for (i = getNumContacts() - 1; i >= 0; i--)
{
-
- btManifoldPoint &manifoldPoint = m_pointCache[i];
+ btManifoldPoint& manifoldPoint = m_pointCache[i];
//contact becomes invalid when signed distance exceeds margin (projected on contactnormal direction)
if (!validContactDistance(manifoldPoint))
{
removeContactPoint(i);
- } else
+ }
+ else
{
- //todo: friction anchor may require the contact to be around a bit longer
+ //todo: friction anchor may require the contact to be around a bit longer
//contact also becomes invalid when relative movement orthogonal to normal exceeds margin
projectedPoint = manifoldPoint.m_positionWorldOnA - manifoldPoint.m_normalWorldOnB * manifoldPoint.m_distance1;
projectedDifference = manifoldPoint.m_positionWorldOnB - projectedPoint;
distance2d = projectedDifference.dot(projectedDifference);
- if (distance2d > getContactBreakingThreshold()*getContactBreakingThreshold() )
+ if (distance2d > getContactBreakingThreshold() * getContactBreakingThreshold())
{
removeContactPoint(i);
- } else
+ }
+ else
{
//contact point processed callback
if (gContactProcessedCallback)
- (*gContactProcessedCallback)(manifoldPoint,(void*)m_body0,(void*)m_body1);
+ (*gContactProcessedCallback)(manifoldPoint, (void*)m_body0, (void*)m_body1);
}
}
}
#ifdef DEBUG_PERSISTENCY
DebugPersistency();
-#endif //
+#endif //
}
-
-int btPersistentManifold::calculateSerializeBufferSize() const
+int btPersistentManifold::calculateSerializeBufferSize() const
{
return sizeof(btPersistentManifoldData);
}
-const char* btPersistentManifold::serialize(const class btPersistentManifold* manifold, void* dataBuffer, class btSerializer* serializer) const
+const char* btPersistentManifold::serialize(const class btPersistentManifold* manifold, void* dataBuffer, class btSerializer* serializer) const
{
btPersistentManifoldData* dataOut = (btPersistentManifoldData*)dataBuffer;
memset(dataOut, 0, sizeof(btPersistentManifoldData));
@@ -379,7 +369,7 @@ void btPersistentManifold::deSerialize(const struct btPersistentManifoldDoubleDa
for (int i = 0; i < this->getNumContacts(); i++)
{
btManifoldPoint& pt = m_pointCache[i];
-
+
pt.m_appliedImpulse = manifoldDataPtr->m_pointCacheAppliedImpulse[i];
pt.m_appliedImpulseLateral1 = manifoldDataPtr->m_pointCacheAppliedImpulseLateral1[i];
pt.m_appliedImpulseLateral2 = manifoldDataPtr->m_pointCacheAppliedImpulseLateral2[i];
@@ -409,7 +399,6 @@ void btPersistentManifold::deSerialize(const struct btPersistentManifoldDoubleDa
pt.m_contactMotion1 = manifoldDataPtr->m_pointCacheContactMotion1[i];
pt.m_contactMotion2 = manifoldDataPtr->m_pointCacheContactMotion2[i];
}
-
}
void btPersistentManifold::deSerialize(const struct btPersistentManifoldFloatData* manifoldDataPtr)
@@ -455,5 +444,4 @@ void btPersistentManifold::deSerialize(const struct btPersistentManifoldFloatDat
pt.m_contactMotion1 = manifoldDataPtr->m_pointCacheContactMotion1[i];
pt.m_contactMotion2 = manifoldDataPtr->m_pointCacheContactMotion2[i];
}
-
} \ No newline at end of file
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h
index 67be0c48eb..8a9134c95c 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h
@@ -16,7 +16,6 @@ subject to the following restrictions:
#ifndef BT_PERSISTENT_MANIFOLD_H
#define BT_PERSISTENT_MANIFOLD_H
-
#include "LinearMath/btVector3.h"
#include "LinearMath/btTransform.h"
#include "btManifoldPoint.h"
@@ -34,14 +33,14 @@ extern btScalar gContactBreakingThreshold;
class btPersistentManifold;
typedef bool (*ContactDestroyedCallback)(void* userPersistentData);
-typedef bool (*ContactProcessedCallback)(btManifoldPoint& cp,void* body0,void* body1);
-typedef void (*ContactStartedCallback)(btPersistentManifold* const &manifold);
-typedef void (*ContactEndedCallback)(btPersistentManifold* const &manifold);
-extern ContactDestroyedCallback gContactDestroyedCallback;
+typedef bool (*ContactProcessedCallback)(btManifoldPoint& cp, void* body0, void* body1);
+typedef void (*ContactStartedCallback)(btPersistentManifold* const& manifold);
+typedef void (*ContactEndedCallback)(btPersistentManifold* const& manifold);
+extern ContactDestroyedCallback gContactDestroyedCallback;
extern ContactProcessedCallback gContactProcessedCallback;
extern ContactStartedCallback gContactStartedCallback;
extern ContactEndedCallback gContactEndedCallback;
-#endif //SWIG
+#endif //SWIG
//the enum starts at 1024 to avoid type conflicts with btTypedConstraint
enum btContactManifoldTypes
@@ -60,73 +59,74 @@ enum btContactManifoldTypes
///the contact point with deepest penetration is always kept, and it tries to maximuze the area covered by the points
///note that some pairs of objects might have more then one contact manifold.
-
//ATTRIBUTE_ALIGNED128( class) btPersistentManifold : public btTypedObject
-ATTRIBUTE_ALIGNED16( class) btPersistentManifold : public btTypedObject
+ATTRIBUTE_ALIGNED16(class)
+btPersistentManifold : public btTypedObject
{
-
btManifoldPoint m_pointCache[MANIFOLD_CACHE_SIZE];
/// this two body pointers can point to the physics rigidbody class.
const btCollisionObject* m_body0;
const btCollisionObject* m_body1;
- int m_cachedPoints;
+ int m_cachedPoints;
- btScalar m_contactBreakingThreshold;
- btScalar m_contactProcessingThreshold;
+ btScalar m_contactBreakingThreshold;
+ btScalar m_contactProcessingThreshold;
-
/// sort cached points so most isolated points come first
- int sortCachedPoints(const btManifoldPoint& pt);
+ int sortCachedPoints(const btManifoldPoint& pt);
- int findContactPoint(const btManifoldPoint* unUsed, int numUnused,const btManifoldPoint& pt);
+ int findContactPoint(const btManifoldPoint* unUsed, int numUnused, const btManifoldPoint& pt);
public:
-
BT_DECLARE_ALIGNED_ALLOCATOR();
- int m_companionIdA;
- int m_companionIdB;
+ int m_companionIdA;
+ int m_companionIdB;
int m_index1a;
btPersistentManifold();
- btPersistentManifold(const btCollisionObject* body0,const btCollisionObject* body1,int , btScalar contactBreakingThreshold,btScalar contactProcessingThreshold)
+ btPersistentManifold(const btCollisionObject* body0, const btCollisionObject* body1, int, btScalar contactBreakingThreshold, btScalar contactProcessingThreshold)
: btTypedObject(BT_PERSISTENT_MANIFOLD_TYPE),
- m_body0(body0),m_body1(body1),m_cachedPoints(0),
- m_contactBreakingThreshold(contactBreakingThreshold),
- m_contactProcessingThreshold(contactProcessingThreshold),
- m_companionIdA(0),
- m_companionIdB(0),
- m_index1a(0)
+ m_body0(body0),
+ m_body1(body1),
+ m_cachedPoints(0),
+ m_contactBreakingThreshold(contactBreakingThreshold),
+ m_contactProcessingThreshold(contactProcessingThreshold),
+ m_companionIdA(0),
+ m_companionIdB(0),
+ m_index1a(0)
{
}
- SIMD_FORCE_INLINE const btCollisionObject* getBody0() const { return m_body0;}
- SIMD_FORCE_INLINE const btCollisionObject* getBody1() const { return m_body1;}
+ SIMD_FORCE_INLINE const btCollisionObject* getBody0() const { return m_body0; }
+ SIMD_FORCE_INLINE const btCollisionObject* getBody1() const { return m_body1; }
- void setBodies(const btCollisionObject* body0,const btCollisionObject* body1)
+ void setBodies(const btCollisionObject* body0, const btCollisionObject* body1)
{
m_body0 = body0;
m_body1 = body1;
}
- void clearUserCache(btManifoldPoint& pt);
+ void clearUserCache(btManifoldPoint & pt);
#ifdef DEBUG_PERSISTENCY
- void DebugPersistency();
-#endif //
-
- SIMD_FORCE_INLINE int getNumContacts() const { return m_cachedPoints;}
+ void DebugPersistency();
+#endif //
+
+ SIMD_FORCE_INLINE int getNumContacts() const
+ {
+ return m_cachedPoints;
+ }
/// the setNumContacts API is usually not used, except when you gather/fill all contacts manually
void setNumContacts(int cachedPoints)
{
m_cachedPoints = cachedPoints;
}
-
SIMD_FORCE_INLINE const btManifoldPoint& getContactPoint(int index) const
{
btAssert(index < m_cachedPoints);
@@ -140,39 +140,36 @@ public:
}
///@todo: get this margin from the current physics / collision environment
- btScalar getContactBreakingThreshold() const;
+ btScalar getContactBreakingThreshold() const;
- btScalar getContactProcessingThreshold() const
+ btScalar getContactProcessingThreshold() const
{
return m_contactProcessingThreshold;
}
-
+
void setContactBreakingThreshold(btScalar contactBreakingThreshold)
{
m_contactBreakingThreshold = contactBreakingThreshold;
}
- void setContactProcessingThreshold(btScalar contactProcessingThreshold)
+ void setContactProcessingThreshold(btScalar contactProcessingThreshold)
{
m_contactProcessingThreshold = contactProcessingThreshold;
}
-
-
-
int getCacheEntry(const btManifoldPoint& newPoint) const;
- int addManifoldPoint( const btManifoldPoint& newPoint, bool isPredictive=false);
+ int addManifoldPoint(const btManifoldPoint& newPoint, bool isPredictive = false);
- void removeContactPoint (int index)
+ void removeContactPoint(int index)
{
clearUserCache(m_pointCache[index]);
int lastUsedIndex = getNumContacts() - 1;
-// m_pointCache[index] = m_pointCache[lastUsedIndex];
- if(index != lastUsedIndex)
+ // m_pointCache[index] = m_pointCache[lastUsedIndex];
+ if (index != lastUsedIndex)
{
- m_pointCache[index] = m_pointCache[lastUsedIndex];
+ m_pointCache[index] = m_pointCache[lastUsedIndex];
//get rid of duplicated userPersistentData pointer
m_pointCache[lastUsedIndex].m_userPersistentData = 0;
m_pointCache[lastUsedIndex].m_appliedImpulse = 0.f;
@@ -182,7 +179,7 @@ public:
m_pointCache[lastUsedIndex].m_lifeTime = 0;
}
- btAssert(m_pointCache[lastUsedIndex].m_userPersistentData==0);
+ btAssert(m_pointCache[lastUsedIndex].m_userPersistentData == 0);
m_cachedPoints--;
if (gContactEndedCallback && m_cachedPoints == 0)
@@ -243,13 +240,12 @@ public:
return pt.m_distance1 <= getContactBreakingThreshold();
}
/// calculated new worldspace coordinates and depth, and reject points that exceed the collision margin
- void refreshContactPoints( const btTransform& trA,const btTransform& trB);
+ void refreshContactPoints(const btTransform& trA, const btTransform& trB);
-
- SIMD_FORCE_INLINE void clearManifold()
+ SIMD_FORCE_INLINE void clearManifold()
{
int i;
- for (i=0;i<m_cachedPoints;i++)
+ for (i = 0; i < m_cachedPoints; i++)
{
clearUserCache(m_pointCache[i]);
}
@@ -261,15 +257,13 @@ public:
m_cachedPoints = 0;
}
- int calculateSerializeBufferSize() const;
- const char* serialize(const class btPersistentManifold* manifold, void* dataBuffer, class btSerializer* serializer) const;
+ int calculateSerializeBufferSize() const;
+ const char* serialize(const class btPersistentManifold* manifold, void* dataBuffer, class btSerializer* serializer) const;
void deSerialize(const struct btPersistentManifoldDoubleData* manifoldDataPtr);
void deSerialize(const struct btPersistentManifoldFloatData* manifoldDataPtr);
-
-
};
-
+// clang-format off
struct btPersistentManifoldDoubleData
{
@@ -362,17 +356,14 @@ struct btPersistentManifoldFloatData
btCollisionObjectFloatData *m_body1;
};
+// clang-format on
+
#ifdef BT_USE_DOUBLE_PRECISION
-#define btPersistentManifoldData btPersistentManifoldDoubleData
-#define btPersistentManifoldDataName "btPersistentManifoldDoubleData"
+#define btPersistentManifoldData btPersistentManifoldDoubleData
+#define btPersistentManifoldDataName "btPersistentManifoldDoubleData"
#else
-#define btPersistentManifoldData btPersistentManifoldFloatData
-#define btPersistentManifoldDataName "btPersistentManifoldFloatData"
-#endif //BT_USE_DOUBLE_PRECISION
-
-
-
-
-
+#define btPersistentManifoldData btPersistentManifoldFloatData
+#define btPersistentManifoldDataName "btPersistentManifoldFloatData"
+#endif //BT_USE_DOUBLE_PRECISION
-#endif //BT_PERSISTENT_MANIFOLD_H
+#endif //BT_PERSISTENT_MANIFOLD_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPointCollector.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPointCollector.h
index 18da171011..0900eb6e85 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPointCollector.h
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPointCollector.h
@@ -18,38 +18,33 @@ subject to the following restrictions:
#include "btDiscreteCollisionDetectorInterface.h"
-
-
struct btPointCollector : public btDiscreteCollisionDetectorInterface::Result
{
-
-
btVector3 m_normalOnBInWorld;
btVector3 m_pointInWorld;
- btScalar m_distance;//negative means penetration
+ btScalar m_distance; //negative means penetration
- bool m_hasResult;
+ bool m_hasResult;
- btPointCollector ()
- : m_distance(btScalar(BT_LARGE_FLOAT)),m_hasResult(false)
+ btPointCollector()
+ : m_distance(btScalar(BT_LARGE_FLOAT)), m_hasResult(false)
{
}
- virtual void setShapeIdentifiersA(int partId0,int index0)
+ virtual void setShapeIdentifiersA(int partId0, int index0)
{
(void)partId0;
(void)index0;
-
}
- virtual void setShapeIdentifiersB(int partId1,int index1)
+ virtual void setShapeIdentifiersB(int partId1, int index1)
{
(void)partId1;
(void)index1;
}
- virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)
+ virtual void addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar depth)
{
- if (depth< m_distance)
+ if (depth < m_distance)
{
m_hasResult = true;
m_normalOnBInWorld = normalOnBInWorld;
@@ -60,5 +55,4 @@ struct btPointCollector : public btDiscreteCollisionDetectorInterface::Result
}
};
-#endif //BT_POINT_COLLECTOR_H
-
+#endif //BT_POINT_COLLECTOR_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp
index ea380bc5f1..9d1836037d 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp
@@ -13,45 +13,42 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
///This file was written by Erwin Coumans
///Separating axis rest based on work from Pierre Terdiman, see
///And contact clipping based on work from Simon Hobbs
-
#include "btPolyhedralContactClipping.h"
#include "BulletCollision/CollisionShapes/btConvexPolyhedron.h"
-#include <float.h> //for FLT_MAX
+#include <float.h> //for FLT_MAX
-int gExpectedNbTests=0;
+int gExpectedNbTests = 0;
int gActualNbTests = 0;
bool gUseInternalObject = true;
// Clips a face to the back of a plane
-void btPolyhedralContactClipping::clipFace(const btVertexArray& pVtxIn, btVertexArray& ppVtxOut, const btVector3& planeNormalWS,btScalar planeEqWS)
+void btPolyhedralContactClipping::clipFace(const btVertexArray& pVtxIn, btVertexArray& ppVtxOut, const btVector3& planeNormalWS, btScalar planeEqWS)
{
-
int ve;
btScalar ds, de;
int numVerts = pVtxIn.size();
if (numVerts < 2)
return;
- btVector3 firstVertex=pVtxIn[pVtxIn.size()-1];
+ btVector3 firstVertex = pVtxIn[pVtxIn.size() - 1];
btVector3 endVertex = pVtxIn[0];
-
- ds = planeNormalWS.dot(firstVertex)+planeEqWS;
+
+ ds = planeNormalWS.dot(firstVertex) + planeEqWS;
for (ve = 0; ve < numVerts; ve++)
{
- endVertex=pVtxIn[ve];
+ endVertex = pVtxIn[ve];
- de = planeNormalWS.dot(endVertex)+planeEqWS;
+ de = planeNormalWS.dot(endVertex) + planeEqWS;
- if (ds<0)
+ if (ds < 0)
{
- if (de<0)
+ if (de < 0)
{
// Start < 0, end < 0, so output endVertex
ppVtxOut.push_back(endVertex);
@@ -59,15 +56,15 @@ void btPolyhedralContactClipping::clipFace(const btVertexArray& pVtxIn, btVertex
else
{
// Start < 0, end >= 0, so output intersection
- ppVtxOut.push_back( firstVertex.lerp(endVertex,btScalar(ds * 1.f/(ds - de))));
+ ppVtxOut.push_back(firstVertex.lerp(endVertex, btScalar(ds * 1.f / (ds - de))));
}
}
else
{
- if (de<0)
+ if (de < 0)
{
// Start >= 0, end < 0 so output intersection and end
- ppVtxOut.push_back(firstVertex.lerp(endVertex,btScalar(ds * 1.f/(ds - de))));
+ ppVtxOut.push_back(firstVertex.lerp(endVertex, btScalar(ds * 1.f / (ds - de))));
ppVtxOut.push_back(endVertex);
}
}
@@ -76,47 +73,44 @@ void btPolyhedralContactClipping::clipFace(const btVertexArray& pVtxIn, btVertex
}
}
-
-static bool TestSepAxis(const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, const btVector3& sep_axis, btScalar& depth, btVector3& witnessPointA, btVector3& witnessPointB)
+static bool TestSepAxis(const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA, const btTransform& transB, const btVector3& sep_axis, btScalar& depth, btVector3& witnessPointA, btVector3& witnessPointB)
{
- btScalar Min0,Max0;
- btScalar Min1,Max1;
- btVector3 witnesPtMinA,witnesPtMaxA;
- btVector3 witnesPtMinB,witnesPtMaxB;
+ btScalar Min0, Max0;
+ btScalar Min1, Max1;
+ btVector3 witnesPtMinA, witnesPtMaxA;
+ btVector3 witnesPtMinB, witnesPtMaxB;
- hullA.project(transA,sep_axis, Min0, Max0,witnesPtMinA,witnesPtMaxA);
- hullB.project(transB, sep_axis, Min1, Max1,witnesPtMinB,witnesPtMaxB);
+ hullA.project(transA, sep_axis, Min0, Max0, witnesPtMinA, witnesPtMaxA);
+ hullB.project(transB, sep_axis, Min1, Max1, witnesPtMinB, witnesPtMaxB);
- if(Max0<Min1 || Max1<Min0)
+ if (Max0 < Min1 || Max1 < Min0)
return false;
btScalar d0 = Max0 - Min1;
- btAssert(d0>=0.0f);
+ btAssert(d0 >= 0.0f);
btScalar d1 = Max1 - Min0;
- btAssert(d1>=0.0f);
- if (d0<d1)
+ btAssert(d1 >= 0.0f);
+ if (d0 < d1)
{
depth = d0;
witnessPointA = witnesPtMaxA;
witnessPointB = witnesPtMinB;
-
- } else
+ }
+ else
{
depth = d1;
witnessPointA = witnesPtMinA;
witnessPointB = witnesPtMaxB;
}
-
+
return true;
}
-
-
-static int gActualSATPairTests=0;
+static int gActualSATPairTests = 0;
inline bool IsAlmostZero(const btVector3& v)
{
- if(btFabs(v.x())>1e-6 || btFabs(v.y())>1e-6 || btFabs(v.z())>1e-6) return false;
+ if (btFabs(v.x()) > 1e-6 || btFabs(v.y()) > 1e-6 || btFabs(v.z()) > 1e-6) return false;
return true;
}
@@ -125,9 +119,9 @@ inline bool IsAlmostZero(const btVector3& v)
inline void BoxSupport(const btScalar extents[3], const btScalar sv[3], btScalar p[3])
{
// This version is ~11.000 cycles (4%) faster overall in one of the tests.
-// IR(p[0]) = IR(extents[0])|(IR(sv[0])&SIGN_BITMASK);
-// IR(p[1]) = IR(extents[1])|(IR(sv[1])&SIGN_BITMASK);
-// IR(p[2]) = IR(extents[2])|(IR(sv[2])&SIGN_BITMASK);
+ // IR(p[0]) = IR(extents[0])|(IR(sv[0])&SIGN_BITMASK);
+ // IR(p[1]) = IR(extents[1])|(IR(sv[1])&SIGN_BITMASK);
+ // IR(p[2]) = IR(extents[2])|(IR(sv[2])&SIGN_BITMASK);
p[0] = sv[0] < 0.0f ? -extents[0] : extents[0];
p[1] = sv[1] < 0.0f ? -extents[1] : extents[1];
p[2] = sv[2] < 0.0f ? -extents[2] : extents[2];
@@ -140,90 +134,94 @@ void InverseTransformPoint3x3(btVector3& out, const btVector3& in, const btTrans
const btVector3& r1 = rot[1];
const btVector3& r2 = rot[2];
- const btScalar x = r0.x()*in.x() + r1.x()*in.y() + r2.x()*in.z();
- const btScalar y = r0.y()*in.x() + r1.y()*in.y() + r2.y()*in.z();
- const btScalar z = r0.z()*in.x() + r1.z()*in.y() + r2.z()*in.z();
+ const btScalar x = r0.x() * in.x() + r1.x() * in.y() + r2.x() * in.z();
+ const btScalar y = r0.y() * in.x() + r1.y() * in.y() + r2.y() * in.z();
+ const btScalar z = r0.z() * in.x() + r1.z() * in.y() + r2.z() * in.z();
out.setValue(x, y, z);
}
- bool TestInternalObjects( const btTransform& trans0, const btTransform& trans1, const btVector3& delta_c, const btVector3& axis, const btConvexPolyhedron& convex0, const btConvexPolyhedron& convex1, btScalar dmin)
+bool TestInternalObjects(const btTransform& trans0, const btTransform& trans1, const btVector3& delta_c, const btVector3& axis, const btConvexPolyhedron& convex0, const btConvexPolyhedron& convex1, btScalar dmin)
{
const btScalar dp = delta_c.dot(axis);
btVector3 localAxis0;
- InverseTransformPoint3x3(localAxis0, axis,trans0);
+ InverseTransformPoint3x3(localAxis0, axis, trans0);
btVector3 localAxis1;
- InverseTransformPoint3x3(localAxis1, axis,trans1);
+ InverseTransformPoint3x3(localAxis1, axis, trans1);
btScalar p0[3];
BoxSupport(convex0.m_extents, localAxis0, p0);
btScalar p1[3];
BoxSupport(convex1.m_extents, localAxis1, p1);
- const btScalar Radius0 = p0[0]*localAxis0.x() + p0[1]*localAxis0.y() + p0[2]*localAxis0.z();
- const btScalar Radius1 = p1[0]*localAxis1.x() + p1[1]*localAxis1.y() + p1[2]*localAxis1.z();
+ const btScalar Radius0 = p0[0] * localAxis0.x() + p0[1] * localAxis0.y() + p0[2] * localAxis0.z();
+ const btScalar Radius1 = p1[0] * localAxis1.x() + p1[1] * localAxis1.y() + p1[2] * localAxis1.z();
- const btScalar MinRadius = Radius0>convex0.m_radius ? Radius0 : convex0.m_radius;
- const btScalar MaxRadius = Radius1>convex1.m_radius ? Radius1 : convex1.m_radius;
+ const btScalar MinRadius = Radius0 > convex0.m_radius ? Radius0 : convex0.m_radius;
+ const btScalar MaxRadius = Radius1 > convex1.m_radius ? Radius1 : convex1.m_radius;
const btScalar MinMaxRadius = MaxRadius + MinRadius;
const btScalar d0 = MinMaxRadius + dp;
const btScalar d1 = MinMaxRadius - dp;
- const btScalar depth = d0<d1 ? d0:d1;
- if(depth>dmin)
+ const btScalar depth = d0 < d1 ? d0 : d1;
+ if (depth > dmin)
return false;
return true;
}
-#endif //TEST_INTERNAL_OBJECTS
+#endif //TEST_INTERNAL_OBJECTS
-
-
- SIMD_FORCE_INLINE void btSegmentsClosestPoints(
+SIMD_FORCE_INLINE void btSegmentsClosestPoints(
btVector3& ptsVector,
btVector3& offsetA,
btVector3& offsetB,
btScalar& tA, btScalar& tB,
const btVector3& translation,
const btVector3& dirA, btScalar hlenA,
- const btVector3& dirB, btScalar hlenB )
+ const btVector3& dirB, btScalar hlenB)
{
// compute the parameters of the closest points on each line segment
- btScalar dirA_dot_dirB = btDot(dirA,dirB);
- btScalar dirA_dot_trans = btDot(dirA,translation);
- btScalar dirB_dot_trans = btDot(dirB,translation);
+ btScalar dirA_dot_dirB = btDot(dirA, dirB);
+ btScalar dirA_dot_trans = btDot(dirA, translation);
+ btScalar dirB_dot_trans = btDot(dirB, translation);
btScalar denom = 1.0f - dirA_dot_dirB * dirA_dot_dirB;
- if ( denom == 0.0f ) {
+ if (denom == 0.0f)
+ {
tA = 0.0f;
- } else {
- tA = ( dirA_dot_trans - dirB_dot_trans * dirA_dot_dirB ) / denom;
- if ( tA < -hlenA )
+ }
+ else
+ {
+ tA = (dirA_dot_trans - dirB_dot_trans * dirA_dot_dirB) / denom;
+ if (tA < -hlenA)
tA = -hlenA;
- else if ( tA > hlenA )
+ else if (tA > hlenA)
tA = hlenA;
}
tB = tA * dirA_dot_dirB - dirB_dot_trans;
- if ( tB < -hlenB ) {
+ if (tB < -hlenB)
+ {
tB = -hlenB;
tA = tB * dirA_dot_dirB + dirA_dot_trans;
- if ( tA < -hlenA )
+ if (tA < -hlenA)
tA = -hlenA;
- else if ( tA > hlenA )
+ else if (tA > hlenA)
tA = hlenA;
- } else if ( tB > hlenB ) {
+ }
+ else if (tB > hlenB)
+ {
tB = hlenB;
tA = tB * dirA_dot_dirB + dirA_dot_trans;
- if ( tA < -hlenA )
+ if (tA < -hlenA)
tA = -hlenA;
- else if ( tA > hlenA )
+ else if (tA > hlenA)
tA = hlenA;
}
@@ -235,44 +233,42 @@ void InverseTransformPoint3x3(btVector3& out, const btVector3& in, const btTrans
ptsVector = translation - offsetA + offsetB;
}
-
-
-bool btPolyhedralContactClipping::findSeparatingAxis( const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, btVector3& sep, btDiscreteCollisionDetectorInterface::Result& resultOut)
+bool btPolyhedralContactClipping::findSeparatingAxis(const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA, const btTransform& transB, btVector3& sep, btDiscreteCollisionDetectorInterface::Result& resultOut)
{
gActualSATPairTests++;
-//#ifdef TEST_INTERNAL_OBJECTS
+ //#ifdef TEST_INTERNAL_OBJECTS
const btVector3 c0 = transA * hullA.m_localCenter;
const btVector3 c1 = transB * hullB.m_localCenter;
const btVector3 DeltaC2 = c0 - c1;
-//#endif
+ //#endif
btScalar dmin = FLT_MAX;
- int curPlaneTests=0;
+ int curPlaneTests = 0;
int numFacesA = hullA.m_faces.size();
// Test normals from hullA
- for(int i=0;i<numFacesA;i++)
+ for (int i = 0; i < numFacesA; i++)
{
const btVector3 Normal(hullA.m_faces[i].m_plane[0], hullA.m_faces[i].m_plane[1], hullA.m_faces[i].m_plane[2]);
btVector3 faceANormalWS = transA.getBasis() * Normal;
- if (DeltaC2.dot(faceANormalWS)<0)
- faceANormalWS*=-1.f;
+ if (DeltaC2.dot(faceANormalWS) < 0)
+ faceANormalWS *= -1.f;
curPlaneTests++;
#ifdef TEST_INTERNAL_OBJECTS
gExpectedNbTests++;
- if(gUseInternalObject && !TestInternalObjects(transA,transB, DeltaC2, faceANormalWS, hullA, hullB, dmin))
+ if (gUseInternalObject && !TestInternalObjects(transA, transB, DeltaC2, faceANormalWS, hullA, hullB, dmin))
continue;
gActualNbTests++;
#endif
btScalar d;
- btVector3 wA,wB;
- if(!TestSepAxis( hullA, hullB, transA,transB, faceANormalWS, d,wA,wB))
+ btVector3 wA, wB;
+ if (!TestSepAxis(hullA, hullB, transA, transB, faceANormalWS, d, wA, wB))
return false;
- if(d<dmin)
+ if (d < dmin)
{
dmin = d;
sep = faceANormalWS;
@@ -281,92 +277,89 @@ bool btPolyhedralContactClipping::findSeparatingAxis( const btConvexPolyhedron&
int numFacesB = hullB.m_faces.size();
// Test normals from hullB
- for(int i=0;i<numFacesB;i++)
+ for (int i = 0; i < numFacesB; i++)
{
const btVector3 Normal(hullB.m_faces[i].m_plane[0], hullB.m_faces[i].m_plane[1], hullB.m_faces[i].m_plane[2]);
btVector3 WorldNormal = transB.getBasis() * Normal;
- if (DeltaC2.dot(WorldNormal)<0)
- WorldNormal *=-1.f;
+ if (DeltaC2.dot(WorldNormal) < 0)
+ WorldNormal *= -1.f;
curPlaneTests++;
#ifdef TEST_INTERNAL_OBJECTS
gExpectedNbTests++;
- if(gUseInternalObject && !TestInternalObjects(transA,transB,DeltaC2, WorldNormal, hullA, hullB, dmin))
+ if (gUseInternalObject && !TestInternalObjects(transA, transB, DeltaC2, WorldNormal, hullA, hullB, dmin))
continue;
gActualNbTests++;
#endif
btScalar d;
- btVector3 wA,wB;
- if(!TestSepAxis(hullA, hullB,transA,transB, WorldNormal,d,wA,wB))
+ btVector3 wA, wB;
+ if (!TestSepAxis(hullA, hullB, transA, transB, WorldNormal, d, wA, wB))
return false;
- if(d<dmin)
+ if (d < dmin)
{
dmin = d;
sep = WorldNormal;
}
}
- btVector3 edgeAstart,edgeAend,edgeBstart,edgeBend;
- int edgeA=-1;
- int edgeB=-1;
+ btVector3 edgeAstart, edgeAend, edgeBstart, edgeBend;
+ int edgeA = -1;
+ int edgeB = -1;
btVector3 worldEdgeA;
btVector3 worldEdgeB;
- btVector3 witnessPointA(0,0,0),witnessPointB(0,0,0);
-
+ btVector3 witnessPointA(0, 0, 0), witnessPointB(0, 0, 0);
int curEdgeEdge = 0;
// Test edges
- for(int e0=0;e0<hullA.m_uniqueEdges.size();e0++)
+ for (int e0 = 0; e0 < hullA.m_uniqueEdges.size(); e0++)
{
const btVector3 edge0 = hullA.m_uniqueEdges[e0];
const btVector3 WorldEdge0 = transA.getBasis() * edge0;
- for(int e1=0;e1<hullB.m_uniqueEdges.size();e1++)
+ for (int e1 = 0; e1 < hullB.m_uniqueEdges.size(); e1++)
{
const btVector3 edge1 = hullB.m_uniqueEdges[e1];
const btVector3 WorldEdge1 = transB.getBasis() * edge1;
btVector3 Cross = WorldEdge0.cross(WorldEdge1);
curEdgeEdge++;
- if(!IsAlmostZero(Cross))
+ if (!IsAlmostZero(Cross))
{
Cross = Cross.normalize();
- if (DeltaC2.dot(Cross)<0)
+ if (DeltaC2.dot(Cross) < 0)
Cross *= -1.f;
-
#ifdef TEST_INTERNAL_OBJECTS
gExpectedNbTests++;
- if(gUseInternalObject && !TestInternalObjects(transA,transB,DeltaC2, Cross, hullA, hullB, dmin))
+ if (gUseInternalObject && !TestInternalObjects(transA, transB, DeltaC2, Cross, hullA, hullB, dmin))
continue;
gActualNbTests++;
#endif
btScalar dist;
- btVector3 wA,wB;
- if(!TestSepAxis( hullA, hullB, transA,transB, Cross, dist,wA,wB))
+ btVector3 wA, wB;
+ if (!TestSepAxis(hullA, hullB, transA, transB, Cross, dist, wA, wB))
return false;
- if(dist<dmin)
+ if (dist < dmin)
{
dmin = dist;
sep = Cross;
- edgeA=e0;
- edgeB=e1;
+ edgeA = e0;
+ edgeB = e1;
worldEdgeA = WorldEdge0;
worldEdgeB = WorldEdge1;
- witnessPointA=wA;
- witnessPointB=wB;
+ witnessPointA = wA;
+ witnessPointB = wB;
}
}
}
-
}
- if (edgeA>=0&&edgeB>=0)
+ if (edgeA >= 0 && edgeB >= 0)
{
-// printf("edge-edge\n");
+ // printf("edge-edge\n");
//add an edge-edge contact
btVector3 ptsVector;
@@ -375,57 +368,55 @@ bool btPolyhedralContactClipping::findSeparatingAxis( const btConvexPolyhedron&
btScalar tA;
btScalar tB;
- btVector3 translation = witnessPointB-witnessPointA;
+ btVector3 translation = witnessPointB - witnessPointA;
btVector3 dirA = worldEdgeA;
btVector3 dirB = worldEdgeB;
-
+
btScalar hlenB = 1e30f;
btScalar hlenA = 1e30f;
- btSegmentsClosestPoints(ptsVector,offsetA,offsetB,tA,tB,
- translation,
- dirA, hlenA,
- dirB,hlenB);
+ btSegmentsClosestPoints(ptsVector, offsetA, offsetB, tA, tB,
+ translation,
+ dirA, hlenA,
+ dirB, hlenB);
btScalar nlSqrt = ptsVector.length2();
- if (nlSqrt>SIMD_EPSILON)
+ if (nlSqrt > SIMD_EPSILON)
{
btScalar nl = btSqrt(nlSqrt);
- ptsVector *= 1.f/nl;
- if (ptsVector.dot(DeltaC2)<0.f)
+ ptsVector *= 1.f / nl;
+ if (ptsVector.dot(DeltaC2) < 0.f)
{
- ptsVector*=-1.f;
+ ptsVector *= -1.f;
}
btVector3 ptOnB = witnessPointB + offsetB;
btScalar distance = nl;
- resultOut.addContactPoint(ptsVector, ptOnB,-distance);
+ resultOut.addContactPoint(ptsVector, ptOnB, -distance);
}
-
}
-
- if((DeltaC2.dot(sep))<0.0f)
+ if ((DeltaC2.dot(sep)) < 0.0f)
sep = -sep;
return true;
}
-void btPolyhedralContactClipping::clipFaceAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA, const btTransform& transA, btVertexArray& worldVertsB1,btVertexArray& worldVertsB2, const btScalar minDist, btScalar maxDist,btDiscreteCollisionDetectorInterface::Result& resultOut)
+void btPolyhedralContactClipping::clipFaceAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA, const btTransform& transA, btVertexArray& worldVertsB1, btVertexArray& worldVertsB2, const btScalar minDist, btScalar maxDist, btDiscreteCollisionDetectorInterface::Result& resultOut)
{
worldVertsB2.resize(0);
btVertexArray* pVtxIn = &worldVertsB1;
btVertexArray* pVtxOut = &worldVertsB2;
pVtxOut->reserve(pVtxIn->size());
- int closestFaceA=-1;
+ int closestFaceA = -1;
{
btScalar dmin = FLT_MAX;
- for(int face=0;face<hullA.m_faces.size();face++)
+ for (int face = 0; face < hullA.m_faces.size(); face++)
{
const btVector3 Normal(hullA.m_faces[face].m_plane[0], hullA.m_faces[face].m_plane[1], hullA.m_faces[face].m_plane[2]);
const btVector3 faceANormalWS = transA.getBasis() * Normal;
-
+
btScalar d = faceANormalWS.dot(separatingNormal);
if (d < dmin)
{
@@ -434,69 +425,66 @@ void btPolyhedralContactClipping::clipFaceAgainstHull(const btVector3& separatin
}
}
}
- if (closestFaceA<0)
+ if (closestFaceA < 0)
return;
const btFace& polyA = hullA.m_faces[closestFaceA];
- // clip polygon to back of planes of all faces of hull A that are adjacent to witness face
+ // clip polygon to back of planes of all faces of hull A that are adjacent to witness face
int numVerticesA = polyA.m_indices.size();
- for(int e0=0;e0<numVerticesA;e0++)
+ for (int e0 = 0; e0 < numVerticesA; e0++)
{
const btVector3& a = hullA.m_vertices[polyA.m_indices[e0]];
- const btVector3& b = hullA.m_vertices[polyA.m_indices[(e0+1)%numVerticesA]];
+ const btVector3& b = hullA.m_vertices[polyA.m_indices[(e0 + 1) % numVerticesA]];
const btVector3 edge0 = a - b;
const btVector3 WorldEdge0 = transA.getBasis() * edge0;
- btVector3 worldPlaneAnormal1 = transA.getBasis()* btVector3(polyA.m_plane[0],polyA.m_plane[1],polyA.m_plane[2]);
+ btVector3 worldPlaneAnormal1 = transA.getBasis() * btVector3(polyA.m_plane[0], polyA.m_plane[1], polyA.m_plane[2]);
- btVector3 planeNormalWS1 = -WorldEdge0.cross(worldPlaneAnormal1);//.cross(WorldEdge0);
- btVector3 worldA1 = transA*a;
+ btVector3 planeNormalWS1 = -WorldEdge0.cross(worldPlaneAnormal1); //.cross(WorldEdge0);
+ btVector3 worldA1 = transA * a;
btScalar planeEqWS1 = -worldA1.dot(planeNormalWS1);
-
+
//int otherFace=0;
#ifdef BLA1
int otherFace = polyA.m_connectedFaces[e0];
- btVector3 localPlaneNormal (hullA.m_faces[otherFace].m_plane[0],hullA.m_faces[otherFace].m_plane[1],hullA.m_faces[otherFace].m_plane[2]);
+ btVector3 localPlaneNormal(hullA.m_faces[otherFace].m_plane[0], hullA.m_faces[otherFace].m_plane[1], hullA.m_faces[otherFace].m_plane[2]);
btScalar localPlaneEq = hullA.m_faces[otherFace].m_plane[3];
- btVector3 planeNormalWS = transA.getBasis()*localPlaneNormal;
- btScalar planeEqWS=localPlaneEq-planeNormalWS.dot(transA.getOrigin());
-#else
+ btVector3 planeNormalWS = transA.getBasis() * localPlaneNormal;
+ btScalar planeEqWS = localPlaneEq - planeNormalWS.dot(transA.getOrigin());
+#else
btVector3 planeNormalWS = planeNormalWS1;
- btScalar planeEqWS=planeEqWS1;
-
+ btScalar planeEqWS = planeEqWS1;
+
#endif
//clip face
- clipFace(*pVtxIn, *pVtxOut,planeNormalWS,planeEqWS);
- btSwap(pVtxIn,pVtxOut);
+ clipFace(*pVtxIn, *pVtxOut, planeNormalWS, planeEqWS);
+ btSwap(pVtxIn, pVtxOut);
pVtxOut->resize(0);
}
-
-
-//#define ONLY_REPORT_DEEPEST_POINT
+ //#define ONLY_REPORT_DEEPEST_POINT
btVector3 point;
-
// only keep points that are behind the witness face
{
- btVector3 localPlaneNormal (polyA.m_plane[0],polyA.m_plane[1],polyA.m_plane[2]);
+ btVector3 localPlaneNormal(polyA.m_plane[0], polyA.m_plane[1], polyA.m_plane[2]);
btScalar localPlaneEq = polyA.m_plane[3];
- btVector3 planeNormalWS = transA.getBasis()*localPlaneNormal;
- btScalar planeEqWS=localPlaneEq-planeNormalWS.dot(transA.getOrigin());
- for (int i=0;i<pVtxIn->size();i++)
+ btVector3 planeNormalWS = transA.getBasis() * localPlaneNormal;
+ btScalar planeEqWS = localPlaneEq - planeNormalWS.dot(transA.getOrigin());
+ for (int i = 0; i < pVtxIn->size(); i++)
{
btVector3 vtx = pVtxIn->at(i);
- btScalar depth = planeNormalWS.dot(vtx)+planeEqWS;
- if (depth <=minDist)
+ btScalar depth = planeNormalWS.dot(vtx) + planeEqWS;
+ if (depth <= minDist)
{
-// printf("clamped: depth=%f to minDist=%f\n",depth,minDist);
+ // printf("clamped: depth=%f to minDist=%f\n",depth,minDist);
depth = minDist;
}
- if (depth <=maxDist)
+ if (depth <= maxDist)
{
btVector3 point = pVtxIn->at(i);
#ifdef ONLY_REPORT_DEEPEST_POINT
@@ -507,40 +495,32 @@ void btPolyhedralContactClipping::clipFaceAgainstHull(const btVector3& separatin
{
printf("error in btPolyhedralContactClipping depth = %f\n", depth);
printf("likely wrong separatingNormal passed in\n");
- }
-#endif
- resultOut.addContactPoint(separatingNormal,point,depth);
+ }
+#endif
+ resultOut.addContactPoint(separatingNormal, point, depth);
#endif
}
}
}
#ifdef ONLY_REPORT_DEEPEST_POINT
- if (curMaxDist<maxDist)
+ if (curMaxDist < maxDist)
{
- resultOut.addContactPoint(separatingNormal,point,curMaxDist);
+ resultOut.addContactPoint(separatingNormal, point, curMaxDist);
}
-#endif //ONLY_REPORT_DEEPEST_POINT
-
+#endif //ONLY_REPORT_DEEPEST_POINT
}
-
-
-
-
-void btPolyhedralContactClipping::clipHullAgainstHull(const btVector3& separatingNormal1, const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, const btScalar minDist, btScalar maxDist,btVertexArray& worldVertsB1,btVertexArray& worldVertsB2,btDiscreteCollisionDetectorInterface::Result& resultOut)
+void btPolyhedralContactClipping::clipHullAgainstHull(const btVector3& separatingNormal1, const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA, const btTransform& transB, const btScalar minDist, btScalar maxDist, btVertexArray& worldVertsB1, btVertexArray& worldVertsB2, btDiscreteCollisionDetectorInterface::Result& resultOut)
{
-
btVector3 separatingNormal = separatingNormal1.normalized();
-// const btVector3 c0 = transA * hullA.m_localCenter;
-// const btVector3 c1 = transB * hullB.m_localCenter;
+ // const btVector3 c0 = transA * hullA.m_localCenter;
+ // const btVector3 c1 = transB * hullB.m_localCenter;
//const btVector3 DeltaC2 = c0 - c1;
-
-
- int closestFaceB=-1;
+ int closestFaceB = -1;
btScalar dmax = -FLT_MAX;
{
- for(int face=0;face<hullB.m_faces.size();face++)
+ for (int face = 0; face < hullB.m_faces.size(); face++)
{
const btVector3 Normal(hullB.m_faces[face].m_plane[0], hullB.m_faces[face].m_plane[1], hullB.m_faces[face].m_plane[2]);
const btVector3 WorldNormal = transB.getBasis() * Normal;
@@ -553,18 +533,16 @@ void btPolyhedralContactClipping::clipHullAgainstHull(const btVector3& separatin
}
}
worldVertsB1.resize(0);
- {
- const btFace& polyB = hullB.m_faces[closestFaceB];
- const int numVertices = polyB.m_indices.size();
- for(int e0=0;e0<numVertices;e0++)
- {
- const btVector3& b = hullB.m_vertices[polyB.m_indices[e0]];
- worldVertsB1.push_back(transB*b);
- }
- }
-
-
- if (closestFaceB>=0)
- clipFaceAgainstHull(separatingNormal, hullA, transA,worldVertsB1, worldVertsB2,minDist, maxDist,resultOut);
+ {
+ const btFace& polyB = hullB.m_faces[closestFaceB];
+ const int numVertices = polyB.m_indices.size();
+ for (int e0 = 0; e0 < numVertices; e0++)
+ {
+ const btVector3& b = hullB.m_vertices[polyB.m_indices[e0]];
+ worldVertsB1.push_back(transB * b);
+ }
+ }
+ if (closestFaceB >= 0)
+ clipFaceAgainstHull(separatingNormal, hullA, transA, worldVertsB1, worldVertsB2, minDist, maxDist, resultOut);
}
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h
index 30e3db687b..328f6424bc 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h
@@ -13,14 +13,11 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
///This file was written by Erwin Coumans
-
#ifndef BT_POLYHEDRAL_CONTACT_CLIPPING_H
#define BT_POLYHEDRAL_CONTACT_CLIPPING_H
-
#include "LinearMath/btAlignedObjectArray.h"
#include "LinearMath/btTransform.h"
#include "btDiscreteCollisionDetectorInterface.h"
@@ -32,18 +29,14 @@ typedef btAlignedObjectArray<btVector3> btVertexArray;
// Clips a face to the back of a plane
struct btPolyhedralContactClipping
{
+ static void clipHullAgainstHull(const btVector3& separatingNormal1, const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA, const btTransform& transB, const btScalar minDist, btScalar maxDist, btVertexArray& worldVertsB1, btVertexArray& worldVertsB2, btDiscreteCollisionDetectorInterface::Result& resultOut);
- static void clipHullAgainstHull(const btVector3& separatingNormal1, const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, const btScalar minDist, btScalar maxDist,btVertexArray& worldVertsB1,btVertexArray& worldVertsB2,btDiscreteCollisionDetectorInterface::Result& resultOut);
-
- static void clipFaceAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA, const btTransform& transA, btVertexArray& worldVertsB1,btVertexArray& worldVertsB2, const btScalar minDist, btScalar maxDist,btDiscreteCollisionDetectorInterface::Result& resultOut);
+ static void clipFaceAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA, const btTransform& transA, btVertexArray& worldVertsB1, btVertexArray& worldVertsB2, const btScalar minDist, btScalar maxDist, btDiscreteCollisionDetectorInterface::Result& resultOut);
-
- static bool findSeparatingAxis( const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, btVector3& sep, btDiscreteCollisionDetectorInterface::Result& resultOut);
+ static bool findSeparatingAxis(const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA, const btTransform& transB, btVector3& sep, btDiscreteCollisionDetectorInterface::Result& resultOut);
///the clipFace method is used internally
- static void clipFace(const btVertexArray& pVtxIn, btVertexArray& ppVtxOut, const btVector3& planeNormalWS,btScalar planeEqWS);
-
+ static void clipFace(const btVertexArray& pVtxIn, btVertexArray& ppVtxOut, const btVector3& planeNormalWS, btScalar planeEqWS);
};
-#endif // BT_POLYHEDRAL_CONTACT_CLIPPING_H
-
+#endif // BT_POLYHEDRAL_CONTACT_CLIPPING_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp
index 786efd1820..3d11e5bce5 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp
@@ -23,39 +23,38 @@ subject to the following restrictions:
#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
#include "btRaycastCallback.h"
-btTriangleRaycastCallback::btTriangleRaycastCallback(const btVector3& from,const btVector3& to, unsigned int flags)
- :
- m_from(from),
- m_to(to),
- //@BP Mod
- m_flags(flags),
- m_hitFraction(btScalar(1.))
+btTriangleRaycastCallback::btTriangleRaycastCallback(const btVector3& from, const btVector3& to, unsigned int flags)
+ : m_from(from),
+ m_to(to),
+ //@BP Mod
+ m_flags(flags),
+ m_hitFraction(btScalar(1.))
{
-
}
-
-
-void btTriangleRaycastCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex)
+void btTriangleRaycastCallback::processTriangle(btVector3* triangle, int partId, int triangleIndex)
{
- const btVector3 &vert0=triangle[0];
- const btVector3 &vert1=triangle[1];
- const btVector3 &vert2=triangle[2];
+ const btVector3& vert0 = triangle[0];
+ const btVector3& vert1 = triangle[1];
+ const btVector3& vert2 = triangle[2];
+
+ btVector3 v10;
+ v10 = vert1 - vert0;
+ btVector3 v20;
+ v20 = vert2 - vert0;
- btVector3 v10; v10 = vert1 - vert0 ;
- btVector3 v20; v20 = vert2 - vert0 ;
+ btVector3 triangleNormal;
+ triangleNormal = v10.cross(v20);
- btVector3 triangleNormal; triangleNormal = v10.cross( v20 );
-
const btScalar dist = vert0.dot(triangleNormal);
- btScalar dist_a = triangleNormal.dot(m_from) ;
- dist_a-= dist;
+ btScalar dist_a = triangleNormal.dot(m_from);
+ dist_a -= dist;
btScalar dist_b = triangleNormal.dot(m_to);
dist_b -= dist;
- if ( dist_a * dist_b >= btScalar(0.0) )
+ if (dist_a * dist_b >= btScalar(0.0))
{
- return ; // same sign
+ return; // same sign
}
if (((m_flags & kF_FilterBackfaces) != 0) && (dist_a <= btScalar(0.0)))
@@ -64,52 +63,52 @@ void btTriangleRaycastCallback::processTriangle(btVector3* triangle,int partId,
return;
}
-
- const btScalar proj_length=dist_a-dist_b;
- const btScalar distance = (dist_a)/(proj_length);
+ const btScalar proj_length = dist_a - dist_b;
+ const btScalar distance = (dist_a) / (proj_length);
// Now we have the intersection point on the plane, we'll see if it's inside the triangle
// Add an epsilon as a tolerance for the raycast,
// in case the ray hits exacly on the edge of the triangle.
// It must be scaled for the triangle size.
-
- if(distance < m_hitFraction)
- {
-
- btScalar edge_tolerance =triangleNormal.length2();
+ if (distance < m_hitFraction)
+ {
+ btScalar edge_tolerance = triangleNormal.length2();
edge_tolerance *= btScalar(-0.0001);
- btVector3 point; point.setInterpolate3( m_from, m_to, distance);
+ btVector3 point;
+ point.setInterpolate3(m_from, m_to, distance);
{
- btVector3 v0p; v0p = vert0 - point;
- btVector3 v1p; v1p = vert1 - point;
- btVector3 cp0; cp0 = v0p.cross( v1p );
-
- if ( (btScalar)(cp0.dot(triangleNormal)) >=edge_tolerance)
+ btVector3 v0p;
+ v0p = vert0 - point;
+ btVector3 v1p;
+ v1p = vert1 - point;
+ btVector3 cp0;
+ cp0 = v0p.cross(v1p);
+
+ if ((btScalar)(cp0.dot(triangleNormal)) >= edge_tolerance)
{
-
-
- btVector3 v2p; v2p = vert2 - point;
+ btVector3 v2p;
+ v2p = vert2 - point;
btVector3 cp1;
- cp1 = v1p.cross( v2p);
- if ( (btScalar)(cp1.dot(triangleNormal)) >=edge_tolerance)
+ cp1 = v1p.cross(v2p);
+ if ((btScalar)(cp1.dot(triangleNormal)) >= edge_tolerance)
{
btVector3 cp2;
cp2 = v2p.cross(v0p);
-
- if ( (btScalar)(cp2.dot(triangleNormal)) >=edge_tolerance)
+
+ if ((btScalar)(cp2.dot(triangleNormal)) >= edge_tolerance)
{
- //@BP Mod
- // Triangle normal isn't normalized
- triangleNormal.normalize();
+ //@BP Mod
+ // Triangle normal isn't normalized
+ triangleNormal.normalize();
- //@BP Mod - Allow for unflipped normal when raycasting against backfaces
+ //@BP Mod - Allow for unflipped normal when raycasting against backfaces
if (((m_flags & kF_KeepUnflippedNormal) == 0) && (dist_a <= btScalar(0.0)))
{
- m_hitFraction = reportHit(-triangleNormal,distance,partId,triangleIndex);
+ m_hitFraction = reportHit(-triangleNormal, distance, partId, triangleIndex);
}
else
{
- m_hitFraction = reportHit(triangleNormal,distance,partId,triangleIndex);
+ m_hitFraction = reportHit(triangleNormal, distance, partId, triangleIndex);
}
}
}
@@ -118,8 +117,7 @@ void btTriangleRaycastCallback::processTriangle(btVector3* triangle,int partId,
}
}
-
-btTriangleConvexcastCallback::btTriangleConvexcastCallback (const btConvexShape* convexShape, const btTransform& convexShapeFrom, const btTransform& convexShapeTo, const btTransform& triangleToWorld, const btScalar triangleCollisionMargin)
+btTriangleConvexcastCallback::btTriangleConvexcastCallback(const btConvexShape* convexShape, const btTransform& convexShapeFrom, const btTransform& convexShapeTo, const btTransform& triangleToWorld, const btScalar triangleCollisionMargin)
{
m_convexShape = convexShape;
m_convexShapeFrom = convexShapeFrom;
@@ -130,14 +128,13 @@ btTriangleConvexcastCallback::btTriangleConvexcastCallback (const btConvexShape*
m_allowedPenetration = 0.f;
}
-void
-btTriangleConvexcastCallback::processTriangle (btVector3* triangle, int partId, int triangleIndex)
+void btTriangleConvexcastCallback::processTriangle(btVector3* triangle, int partId, int triangleIndex)
{
- btTriangleShape triangleShape (triangle[0], triangle[1], triangle[2]);
- triangleShape.setMargin(m_triangleCollisionMargin);
+ btTriangleShape triangleShape(triangle[0], triangle[1], triangle[2]);
+ triangleShape.setMargin(m_triangleCollisionMargin);
- btVoronoiSimplexSolver simplexSolver;
- btGjkEpaPenetrationDepthSolver gjkEpaPenetrationSolver;
+ btVoronoiSimplexSolver simplexSolver;
+ btGjkEpaPenetrationDepthSolver gjkEpaPenetrationSolver;
//#define USE_SUBSIMPLEX_CONVEX_CAST 1
//if you reenable USE_SUBSIMPLEX_CONVEX_CAST see commented out code below
@@ -145,21 +142,21 @@ btTriangleConvexcastCallback::processTriangle (btVector3* triangle, int partId,
btSubsimplexConvexCast convexCaster(m_convexShape, &triangleShape, &simplexSolver);
#else
//btGjkConvexCast convexCaster(m_convexShape,&triangleShape,&simplexSolver);
- btContinuousConvexCollision convexCaster(m_convexShape,&triangleShape,&simplexSolver,&gjkEpaPenetrationSolver);
-#endif //#USE_SUBSIMPLEX_CONVEX_CAST
-
+ btContinuousConvexCollision convexCaster(m_convexShape, &triangleShape, &simplexSolver, &gjkEpaPenetrationSolver);
+#endif //#USE_SUBSIMPLEX_CONVEX_CAST
+
btConvexCast::CastResult castResult;
castResult.m_fraction = btScalar(1.);
castResult.m_allowedPenetration = m_allowedPenetration;
- if (convexCaster.calcTimeOfImpact(m_convexShapeFrom,m_convexShapeTo,m_triangleToWorld, m_triangleToWorld, castResult))
+ if (convexCaster.calcTimeOfImpact(m_convexShapeFrom, m_convexShapeTo, m_triangleToWorld, m_triangleToWorld, castResult))
{
//add hit
if (castResult.m_normal.length2() > btScalar(0.0001))
- {
+ {
if (castResult.m_fraction < m_hitFraction)
{
-/* btContinuousConvexCast's normal is already in world space */
-/*
+ /* btContinuousConvexCast's normal is already in world space */
+ /*
#ifdef USE_SUBSIMPLEX_CONVEX_CAST
//rotate normal into worldspace
castResult.m_normal = m_convexShapeFrom.getBasis() * castResult.m_normal;
@@ -167,11 +164,11 @@ btTriangleConvexcastCallback::processTriangle (btVector3* triangle, int partId,
*/
castResult.m_normal.normalize();
- reportHit (castResult.m_normal,
- castResult.m_hitPoint,
- castResult.m_fraction,
- partId,
- triangleIndex);
+ reportHit(castResult.m_normal,
+ castResult.m_hitPoint,
+ castResult.m_fraction,
+ partId,
+ triangleIndex);
}
}
}
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h
index f2ed0cd39c..2b2dfabec2 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h
@@ -21,35 +21,33 @@ subject to the following restrictions:
struct btBroadphaseProxy;
class btConvexShape;
-class btTriangleRaycastCallback: public btTriangleCallback
+class btTriangleRaycastCallback : public btTriangleCallback
{
public:
-
//input
btVector3 m_from;
btVector3 m_to;
- //@BP Mod - allow backface filtering and unflipped normals
- enum EFlags
- {
- kF_None = 0,
- kF_FilterBackfaces = 1 << 0,
- kF_KeepUnflippedNormal = 1 << 1, // Prevents returned face normal getting flipped when a ray hits a back-facing triangle
- ///SubSimplexConvexCastRaytest is the default, even if kF_None is set.
- kF_UseSubSimplexConvexCastRaytest = 1 << 2, // Uses an approximate but faster ray versus convex intersection algorithm
- kF_UseGjkConvexCastRaytest = 1 << 3,
- kF_Terminator = 0xFFFFFFFF
- };
- unsigned int m_flags;
+ //@BP Mod - allow backface filtering and unflipped normals
+ enum EFlags
+ {
+ kF_None = 0,
+ kF_FilterBackfaces = 1 << 0,
+ kF_KeepUnflippedNormal = 1 << 1, // Prevents returned face normal getting flipped when a ray hits a back-facing triangle
+ ///SubSimplexConvexCastRaytest is the default, even if kF_None is set.
+ kF_UseSubSimplexConvexCastRaytest = 1 << 2, // Uses an approximate but faster ray versus convex intersection algorithm
+ kF_UseGjkConvexCastRaytest = 1 << 3,
+ kF_Terminator = 0xFFFFFFFF
+ };
+ unsigned int m_flags;
+
+ btScalar m_hitFraction;
- btScalar m_hitFraction;
+ btTriangleRaycastCallback(const btVector3& from, const btVector3& to, unsigned int flags = 0);
- btTriangleRaycastCallback(const btVector3& from,const btVector3& to, unsigned int flags=0);
-
virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex);
- virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex ) = 0;
-
+ virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex) = 0;
};
class btTriangleConvexcastCallback : public btTriangleCallback
@@ -63,12 +61,11 @@ public:
btScalar m_triangleCollisionMargin;
btScalar m_allowedPenetration;
- btTriangleConvexcastCallback (const btConvexShape* convexShape, const btTransform& convexShapeFrom, const btTransform& convexShapeTo, const btTransform& triangleToWorld, const btScalar triangleCollisionMargin);
+ btTriangleConvexcastCallback(const btConvexShape* convexShape, const btTransform& convexShapeFrom, const btTransform& convexShapeTo, const btTransform& triangleToWorld, const btScalar triangleCollisionMargin);
- virtual void processTriangle (btVector3* triangle, int partId, int triangleIndex);
+ virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex);
- virtual btScalar reportHit (const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex) = 0;
+ virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex) = 0;
};
-#endif //BT_RAYCAST_TRI_CALLBACK_H
-
+#endif //BT_RAYCAST_TRI_CALLBACK_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h
index da8a13914c..ccd227109d 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h
@@ -13,8 +13,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
-
#ifndef BT_SIMPLEX_SOLVER_INTERFACE_H
#define BT_SIMPLEX_SOLVER_INTERFACE_H
@@ -31,33 +29,30 @@ subject to the following restrictions:
/// voronoi regions or barycentric coordinates
class btSimplexSolverInterface
{
- public:
- virtual ~btSimplexSolverInterface() {};
+public:
+ virtual ~btSimplexSolverInterface(){};
virtual void reset() = 0;
virtual void addVertex(const btVector3& w, const btVector3& p, const btVector3& q) = 0;
-
+
virtual bool closest(btVector3& v) = 0;
virtual btScalar maxVertex() = 0;
virtual bool fullSimplex() const = 0;
- virtual int getSimplex(btVector3 *pBuf, btVector3 *qBuf, btVector3 *yBuf) const = 0;
+ virtual int getSimplex(btVector3* pBuf, btVector3* qBuf, btVector3* yBuf) const = 0;
virtual bool inSimplex(const btVector3& w) = 0;
-
+
virtual void backup_closest(btVector3& v) = 0;
virtual bool emptySimplex() const = 0;
virtual void compute_points(btVector3& p1, btVector3& p2) = 0;
- virtual int numVertices() const =0;
-
-
+ virtual int numVertices() const = 0;
};
#endif
-#endif //BT_SIMPLEX_SOLVER_INTERFACE_H
-
+#endif //BT_SIMPLEX_SOLVER_INTERFACE_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp
index 08d6e6de86..37458339e7 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp
@@ -13,7 +13,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#include "btSubSimplexConvexCast.h"
#include "BulletCollision/CollisionShapes/btConvexShape.h"
@@ -22,32 +21,26 @@ subject to the following restrictions:
#include "btPointCollector.h"
#include "LinearMath/btTransformUtil.h"
-btSubsimplexConvexCast::btSubsimplexConvexCast (const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver)
-:m_simplexSolver(simplexSolver),
-m_convexA(convexA),m_convexB(convexB)
+btSubsimplexConvexCast::btSubsimplexConvexCast(const btConvexShape* convexA, const btConvexShape* convexB, btSimplexSolverInterface* simplexSolver)
+ : m_simplexSolver(simplexSolver),
+ m_convexA(convexA),
+ m_convexB(convexB)
{
}
-///Typically the conservative advancement reaches solution in a few iterations, clip it to 32 for degenerate cases.
-///See discussion about this here http://continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=565
-#ifdef BT_USE_DOUBLE_PRECISION
-#define MAX_ITERATIONS 64
-#else
-#define MAX_ITERATIONS 32
-#endif
-bool btSubsimplexConvexCast::calcTimeOfImpact(
- const btTransform& fromA,
- const btTransform& toA,
- const btTransform& fromB,
- const btTransform& toB,
- CastResult& result)
-{
+bool btSubsimplexConvexCast::calcTimeOfImpact(
+ const btTransform& fromA,
+ const btTransform& toA,
+ const btTransform& fromB,
+ const btTransform& toB,
+ CastResult& result)
+{
m_simplexSolver->reset();
- btVector3 linVelA,linVelB;
- linVelA = toA.getOrigin()-fromA.getOrigin();
- linVelB = toB.getOrigin()-fromB.getOrigin();
+ btVector3 linVelA, linVelB;
+ linVelA = toA.getOrigin() - fromA.getOrigin();
+ linVelB = toB.getOrigin() - fromB.getOrigin();
btScalar lambda = btScalar(0.);
@@ -55,43 +48,31 @@ bool btSubsimplexConvexCast::calcTimeOfImpact(
btTransform interpolatedTransB = fromB;
///take relative motion
- btVector3 r = (linVelA-linVelB);
+ btVector3 r = (linVelA - linVelB);
btVector3 v;
-
- btVector3 supVertexA = fromA(m_convexA->localGetSupportingVertex(-r*fromA.getBasis()));
- btVector3 supVertexB = fromB(m_convexB->localGetSupportingVertex(r*fromB.getBasis()));
- v = supVertexA-supVertexB;
- int maxIter = MAX_ITERATIONS;
- btVector3 n;
- n.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
-
- btVector3 c;
+ btVector3 supVertexA = fromA(m_convexA->localGetSupportingVertex(-r * fromA.getBasis()));
+ btVector3 supVertexB = fromB(m_convexB->localGetSupportingVertex(r * fromB.getBasis()));
+ v = supVertexA - supVertexB;
+ int maxIter = result.m_subSimplexCastMaxIterations;
-
+ btVector3 n;
+ n.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
+ btVector3 c;
btScalar dist2 = v.length2();
-#ifdef BT_USE_DOUBLE_PRECISION
- btScalar epsilon = SIMD_EPSILON * 10;
-#else
-//todo: epsilon kept for backward compatibility of unit tests.
-//will need to digg deeper to make the algorithm more robust
-//since, a large epsilon can cause an early termination with false
-//positive results (ray intersections that shouldn't be there)
- btScalar epsilon = btScalar(0.0001);
-#endif //BT_USE_DOUBLE_PRECISION
- btVector3 w,p;
+ btVector3 w, p;
btScalar VdotR;
-
- while ( (dist2 > epsilon) && maxIter--)
+
+ while ((dist2 > result.m_subSimplexCastEpsilon) && maxIter--)
{
- supVertexA = interpolatedTransA(m_convexA->localGetSupportingVertex(-v*interpolatedTransA.getBasis()));
- supVertexB = interpolatedTransB(m_convexB->localGetSupportingVertex(v*interpolatedTransB.getBasis()));
- w = supVertexA-supVertexB;
+ supVertexA = interpolatedTransA(m_convexA->localGetSupportingVertex(-v * interpolatedTransA.getBasis()));
+ supVertexB = interpolatedTransB(m_convexB->localGetSupportingVertex(v * interpolatedTransB.getBasis()));
+ w = supVertexA - supVertexB;
btScalar VdotW = v.dot(w);
@@ -100,68 +81,63 @@ bool btSubsimplexConvexCast::calcTimeOfImpact(
return false;
}
- if ( VdotW > btScalar(0.))
+ if (VdotW > btScalar(0.))
{
VdotR = v.dot(r);
- if (VdotR >= -(SIMD_EPSILON*SIMD_EPSILON))
+ if (VdotR >= -(SIMD_EPSILON * SIMD_EPSILON))
return false;
else
{
lambda = lambda - VdotW / VdotR;
//interpolate to next lambda
// x = s + lambda * r;
- interpolatedTransA.getOrigin().setInterpolate3(fromA.getOrigin(),toA.getOrigin(),lambda);
- interpolatedTransB.getOrigin().setInterpolate3(fromB.getOrigin(),toB.getOrigin(),lambda);
+ interpolatedTransA.getOrigin().setInterpolate3(fromA.getOrigin(), toA.getOrigin(), lambda);
+ interpolatedTransB.getOrigin().setInterpolate3(fromB.getOrigin(), toB.getOrigin(), lambda);
//m_simplexSolver->reset();
//check next line
- w = supVertexA-supVertexB;
-
+ w = supVertexA - supVertexB;
+
n = v;
-
}
- }
+ }
///Just like regular GJK only add the vertex if it isn't already (close) to current vertex, it would lead to divisions by zero and NaN etc.
if (!m_simplexSolver->inSimplex(w))
- m_simplexSolver->addVertex( w, supVertexA , supVertexB);
+ m_simplexSolver->addVertex(w, supVertexA, supVertexB);
if (m_simplexSolver->closest(v))
{
dist2 = v.length2();
-
+
//todo: check this normal for validity
//n=v;
//printf("V=%f , %f, %f\n",v[0],v[1],v[2]);
//printf("DIST2=%f\n",dist2);
//printf("numverts = %i\n",m_simplexSolver->numVertices());
- } else
+ }
+ else
{
dist2 = btScalar(0.);
- }
+ }
}
//int numiter = MAX_ITERATIONS - maxIter;
-// printf("number of iterations: %d", numiter);
-
+ // printf("number of iterations: %d", numiter);
+
//don't report a time of impact when moving 'away' from the hitnormal
-
result.m_fraction = lambda;
- if (n.length2() >= (SIMD_EPSILON*SIMD_EPSILON))
+ if (n.length2() >= (SIMD_EPSILON * SIMD_EPSILON))
result.m_normal = n.normalized();
else
result.m_normal = btVector3(btScalar(0.0), btScalar(0.0), btScalar(0.0));
//don't report time of impact for motion away from the contact normal (or causes minor penetration)
- if (result.m_normal.dot(r)>=-result.m_allowedPenetration)
+ if (result.m_normal.dot(r) >= -result.m_allowedPenetration)
return false;
- btVector3 hitA,hitB;
- m_simplexSolver->compute_points(hitA,hitB);
- result.m_hitPoint=hitB;
+ btVector3 hitA, hitB;
+ m_simplexSolver->compute_points(hitA, hitB);
+ result.m_hitPoint = hitB;
return true;
}
-
-
-
-
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h
index 6c8127983e..0638a30eb1 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h
@@ -13,7 +13,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#ifndef BT_SUBSIMPLEX_CONVEX_CAST_H
#define BT_SUBSIMPLEX_CONVEX_CAST_H
@@ -28,23 +27,21 @@ class btConvexShape;
class btSubsimplexConvexCast : public btConvexCast
{
btSimplexSolverInterface* m_simplexSolver;
- const btConvexShape* m_convexA;
- const btConvexShape* m_convexB;
+ const btConvexShape* m_convexA;
+ const btConvexShape* m_convexB;
public:
-
- btSubsimplexConvexCast (const btConvexShape* shapeA,const btConvexShape* shapeB,btSimplexSolverInterface* simplexSolver);
+ btSubsimplexConvexCast(const btConvexShape* shapeA, const btConvexShape* shapeB, btSimplexSolverInterface* simplexSolver);
//virtual ~btSubsimplexConvexCast();
///SimsimplexConvexCast calculateTimeOfImpact calculates the time of impact+normal for the linear cast (sweep) between two moving objects.
///Precondition is that objects should not penetration/overlap at the start from the interval. Overlap can be tested using btGjkPairDetector.
- virtual bool calcTimeOfImpact(
- const btTransform& fromA,
- const btTransform& toA,
- const btTransform& fromB,
- const btTransform& toB,
- CastResult& result);
-
+ virtual bool calcTimeOfImpact(
+ const btTransform& fromA,
+ const btTransform& toA,
+ const btTransform& fromB,
+ const btTransform& toB,
+ CastResult& result);
};
-#endif //BT_SUBSIMPLEX_CONVEX_CAST_H
+#endif //BT_SUBSIMPLEX_CONVEX_CAST_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp
index 756373c9b5..8fda94d2ad 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp
@@ -23,26 +23,24 @@ subject to the following restrictions:
*/
-
#include "btVoronoiSimplexSolver.h"
-#define VERTA 0
-#define VERTB 1
-#define VERTC 2
-#define VERTD 3
+#define VERTA 0
+#define VERTB 1
+#define VERTC 2
+#define VERTD 3
#define CATCH_DEGENERATE_TETRAHEDRON 1
-void btVoronoiSimplexSolver::removeVertex(int index)
+void btVoronoiSimplexSolver::removeVertex(int index)
{
-
- btAssert(m_numVertices>0);
+ btAssert(m_numVertices > 0);
m_numVertices--;
m_simplexVectorW[index] = m_simplexVectorW[m_numVertices];
m_simplexPointsP[index] = m_simplexPointsP[m_numVertices];
m_simplexPointsQ[index] = m_simplexPointsQ[m_numVertices];
}
-void btVoronoiSimplexSolver::reduceVertices (const btUsageBitfield& usedVerts)
+void btVoronoiSimplexSolver::reduceVertices(const btUsageBitfield& usedVerts)
{
if ((numVertices() >= 4) && (!usedVerts.usedVertexD))
removeVertex(3);
@@ -52,29 +50,22 @@ void btVoronoiSimplexSolver::reduceVertices (const btUsageBitfield& usedVerts)
if ((numVertices() >= 2) && (!usedVerts.usedVertexB))
removeVertex(1);
-
+
if ((numVertices() >= 1) && (!usedVerts.usedVertexA))
removeVertex(0);
-
}
-
-
-
-
//clear the simplex, remove all the vertices
void btVoronoiSimplexSolver::reset()
{
m_cachedValidClosest = false;
m_numVertices = 0;
m_needsUpdate = true;
- m_lastW = btVector3(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+ m_lastW = btVector3(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
m_cachedBC.reset();
}
-
-
- //add a vertex
+//add a vertex
void btVoronoiSimplexSolver::addVertex(const btVector3& w, const btVector3& p, const btVector3& q)
{
m_lastW = w;
@@ -87,9 +78,8 @@ void btVoronoiSimplexSolver::addVertex(const btVector3& w, const btVector3& p, c
m_numVertices++;
}
-bool btVoronoiSimplexSolver::updateClosestVectorAndPoints()
+bool btVoronoiSimplexSolver::updateClosestVectorAndPoints()
{
-
if (m_needsUpdate)
{
m_cachedBC.reset();
@@ -98,127 +88,131 @@ bool btVoronoiSimplexSolver::updateClosestVectorAndPoints()
switch (numVertices())
{
- case 0:
+ case 0:
m_cachedValidClosest = false;
break;
- case 1:
+ case 1:
{
m_cachedP1 = m_simplexPointsP[0];
m_cachedP2 = m_simplexPointsQ[0];
- m_cachedV = m_cachedP1-m_cachedP2; //== m_simplexVectorW[0]
+ m_cachedV = m_cachedP1 - m_cachedP2; //== m_simplexVectorW[0]
m_cachedBC.reset();
- m_cachedBC.setBarycentricCoordinates(btScalar(1.),btScalar(0.),btScalar(0.),btScalar(0.));
+ m_cachedBC.setBarycentricCoordinates(btScalar(1.), btScalar(0.), btScalar(0.), btScalar(0.));
m_cachedValidClosest = m_cachedBC.isValid();
break;
};
- case 2:
+ case 2:
{
- //closest point origin from line segment
- const btVector3& from = m_simplexVectorW[0];
- const btVector3& to = m_simplexVectorW[1];
- btVector3 nearest;
-
- btVector3 p (btScalar(0.),btScalar(0.),btScalar(0.));
- btVector3 diff = p - from;
- btVector3 v = to - from;
- btScalar t = v.dot(diff);
-
- if (t > 0) {
- btScalar dotVV = v.dot(v);
- if (t < dotVV) {
- t /= dotVV;
- diff -= t*v;
- m_cachedBC.m_usedVertices.usedVertexA = true;
- m_cachedBC.m_usedVertices.usedVertexB = true;
- } else {
- t = 1;
- diff -= v;
- //reduce to 1 point
- m_cachedBC.m_usedVertices.usedVertexB = true;
- }
- } else
+ //closest point origin from line segment
+ const btVector3& from = m_simplexVectorW[0];
+ const btVector3& to = m_simplexVectorW[1];
+ btVector3 nearest;
+
+ btVector3 p(btScalar(0.), btScalar(0.), btScalar(0.));
+ btVector3 diff = p - from;
+ btVector3 v = to - from;
+ btScalar t = v.dot(diff);
+
+ if (t > 0)
+ {
+ btScalar dotVV = v.dot(v);
+ if (t < dotVV)
{
- t = 0;
- //reduce to 1 point
+ t /= dotVV;
+ diff -= t * v;
m_cachedBC.m_usedVertices.usedVertexA = true;
+ m_cachedBC.m_usedVertices.usedVertexB = true;
+ }
+ else
+ {
+ t = 1;
+ diff -= v;
+ //reduce to 1 point
+ m_cachedBC.m_usedVertices.usedVertexB = true;
}
- m_cachedBC.setBarycentricCoordinates(1-t,t);
- nearest = from + t*v;
+ }
+ else
+ {
+ t = 0;
+ //reduce to 1 point
+ m_cachedBC.m_usedVertices.usedVertexA = true;
+ }
+ m_cachedBC.setBarycentricCoordinates(1 - t, t);
+ nearest = from + t * v;
- m_cachedP1 = m_simplexPointsP[0] + t * (m_simplexPointsP[1] - m_simplexPointsP[0]);
- m_cachedP2 = m_simplexPointsQ[0] + t * (m_simplexPointsQ[1] - m_simplexPointsQ[0]);
- m_cachedV = m_cachedP1 - m_cachedP2;
-
- reduceVertices(m_cachedBC.m_usedVertices);
+ m_cachedP1 = m_simplexPointsP[0] + t * (m_simplexPointsP[1] - m_simplexPointsP[0]);
+ m_cachedP2 = m_simplexPointsQ[0] + t * (m_simplexPointsQ[1] - m_simplexPointsQ[0]);
+ m_cachedV = m_cachedP1 - m_cachedP2;
- m_cachedValidClosest = m_cachedBC.isValid();
- break;
+ reduceVertices(m_cachedBC.m_usedVertices);
+
+ m_cachedValidClosest = m_cachedBC.isValid();
+ break;
}
- case 3:
- {
- //closest point origin from triangle
- btVector3 p (btScalar(0.),btScalar(0.),btScalar(0.));
+ case 3:
+ {
+ //closest point origin from triangle
+ btVector3 p(btScalar(0.), btScalar(0.), btScalar(0.));
- const btVector3& a = m_simplexVectorW[0];
- const btVector3& b = m_simplexVectorW[1];
- const btVector3& c = m_simplexVectorW[2];
+ const btVector3& a = m_simplexVectorW[0];
+ const btVector3& b = m_simplexVectorW[1];
+ const btVector3& c = m_simplexVectorW[2];
- closestPtPointTriangle(p,a,b,c,m_cachedBC);
- m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] +
- m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] +
- m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2];
+ closestPtPointTriangle(p, a, b, c, m_cachedBC);
+ m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] +
+ m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] +
+ m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2];
- m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] +
- m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] +
- m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2];
+ m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] +
+ m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] +
+ m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2];
- m_cachedV = m_cachedP1-m_cachedP2;
+ m_cachedV = m_cachedP1 - m_cachedP2;
- reduceVertices (m_cachedBC.m_usedVertices);
- m_cachedValidClosest = m_cachedBC.isValid();
+ reduceVertices(m_cachedBC.m_usedVertices);
+ m_cachedValidClosest = m_cachedBC.isValid();
- break;
+ break;
}
- case 4:
+ case 4:
{
+ btVector3 p(btScalar(0.), btScalar(0.), btScalar(0.));
-
- btVector3 p (btScalar(0.),btScalar(0.),btScalar(0.));
-
const btVector3& a = m_simplexVectorW[0];
const btVector3& b = m_simplexVectorW[1];
const btVector3& c = m_simplexVectorW[2];
const btVector3& d = m_simplexVectorW[3];
- bool hasSeparation = closestPtPointTetrahedron(p,a,b,c,d,m_cachedBC);
+ bool hasSeparation = closestPtPointTetrahedron(p, a, b, c, d, m_cachedBC);
if (hasSeparation)
{
-
m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] +
- m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] +
- m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2] +
- m_simplexPointsP[3] * m_cachedBC.m_barycentricCoords[3];
+ m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] +
+ m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2] +
+ m_simplexPointsP[3] * m_cachedBC.m_barycentricCoords[3];
m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] +
- m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] +
- m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2] +
- m_simplexPointsQ[3] * m_cachedBC.m_barycentricCoords[3];
+ m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] +
+ m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2] +
+ m_simplexPointsQ[3] * m_cachedBC.m_barycentricCoords[3];
- m_cachedV = m_cachedP1-m_cachedP2;
- reduceVertices (m_cachedBC.m_usedVertices);
- } else
+ m_cachedV = m_cachedP1 - m_cachedP2;
+ reduceVertices(m_cachedBC.m_usedVertices);
+ }
+ else
{
-// printf("sub distance got penetration\n");
+ // printf("sub distance got penetration\n");
if (m_cachedBC.m_degenerate)
{
m_cachedValidClosest = false;
- } else
+ }
+ else
{
m_cachedValidClosest = true;
//degenerate case == false, penetration = true + zero
- m_cachedV.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+ m_cachedV.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
}
break;
}
@@ -228,7 +222,7 @@ bool btVoronoiSimplexSolver::updateClosestVectorAndPoints()
//closest point origin from tetrahedron
break;
}
- default:
+ default:
{
m_cachedValidClosest = false;
}
@@ -236,7 +230,6 @@ bool btVoronoiSimplexSolver::updateClosestVectorAndPoints()
}
return m_cachedValidClosest;
-
}
//return/calculate the closest vertex
@@ -247,13 +240,11 @@ bool btVoronoiSimplexSolver::closest(btVector3& v)
return succes;
}
-
-
btScalar btVoronoiSimplexSolver::maxVertex()
{
int i, numverts = numVertices();
btScalar maxV = btScalar(0.);
- for (i=0;i<numverts;i++)
+ for (i = 0; i < numverts; i++)
{
btScalar curLen2 = m_simplexVectorW[i].length2();
if (maxV < curLen2)
@@ -262,13 +253,11 @@ btScalar btVoronoiSimplexSolver::maxVertex()
return maxV;
}
-
-
- //return the current simplex
-int btVoronoiSimplexSolver::getSimplex(btVector3 *pBuf, btVector3 *qBuf, btVector3 *yBuf) const
+//return the current simplex
+int btVoronoiSimplexSolver::getSimplex(btVector3* pBuf, btVector3* qBuf, btVector3* yBuf) const
{
int i;
- for (i=0;i<numVertices();i++)
+ for (i = 0; i < numVertices(); i++)
{
yBuf[i] = m_simplexVectorW[i];
pBuf[i] = m_simplexPointsP[i];
@@ -277,20 +266,17 @@ int btVoronoiSimplexSolver::getSimplex(btVector3 *pBuf, btVector3 *qBuf, btVecto
return numVertices();
}
-
-
-
bool btVoronoiSimplexSolver::inSimplex(const btVector3& w)
{
bool found = false;
int i, numverts = numVertices();
//btScalar maxV = btScalar(0.);
-
+
//w is in the current (reduced) simplex
- for (i=0;i<numverts;i++)
+ for (i = 0; i < numverts; i++)
{
#ifdef BT_USE_EQUAL_VERTEX_THRESHOLD
- if ( m_simplexVectorW[i].distance2(w) <= m_equalVertexThreshold)
+ if (m_simplexVectorW[i].distance2(w) <= m_equalVertexThreshold)
#else
if (m_simplexVectorW[i] == w)
#endif
@@ -303,199 +289,190 @@ bool btVoronoiSimplexSolver::inSimplex(const btVector3& w)
//check in case lastW is already removed
if (w == m_lastW)
return true;
-
+
return found;
}
-void btVoronoiSimplexSolver::backup_closest(btVector3& v)
+void btVoronoiSimplexSolver::backup_closest(btVector3& v)
{
v = m_cachedV;
}
-
-bool btVoronoiSimplexSolver::emptySimplex() const
+bool btVoronoiSimplexSolver::emptySimplex() const
{
return (numVertices() == 0);
-
}
-void btVoronoiSimplexSolver::compute_points(btVector3& p1, btVector3& p2)
+void btVoronoiSimplexSolver::compute_points(btVector3& p1, btVector3& p2)
{
updateClosestVectorAndPoints();
p1 = m_cachedP1;
p2 = m_cachedP2;
-
}
-
-
-
-bool btVoronoiSimplexSolver::closestPtPointTriangle(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c,btSubSimplexClosestResult& result)
+bool btVoronoiSimplexSolver::closestPtPointTriangle(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, btSubSimplexClosestResult& result)
{
result.m_usedVertices.reset();
- // Check if P in vertex region outside A
- btVector3 ab = b - a;
- btVector3 ac = c - a;
- btVector3 ap = p - a;
- btScalar d1 = ab.dot(ap);
- btScalar d2 = ac.dot(ap);
- if (d1 <= btScalar(0.0) && d2 <= btScalar(0.0))
+ // Check if P in vertex region outside A
+ btVector3 ab = b - a;
+ btVector3 ac = c - a;
+ btVector3 ap = p - a;
+ btScalar d1 = ab.dot(ap);
+ btScalar d2 = ac.dot(ap);
+ if (d1 <= btScalar(0.0) && d2 <= btScalar(0.0))
{
result.m_closestPointOnSimplex = a;
result.m_usedVertices.usedVertexA = true;
- result.setBarycentricCoordinates(1,0,0);
- return true;// a; // barycentric coordinates (1,0,0)
+ result.setBarycentricCoordinates(1, 0, 0);
+ return true; // a; // barycentric coordinates (1,0,0)
}
- // Check if P in vertex region outside B
- btVector3 bp = p - b;
- btScalar d3 = ab.dot(bp);
- btScalar d4 = ac.dot(bp);
- if (d3 >= btScalar(0.0) && d4 <= d3)
+ // Check if P in vertex region outside B
+ btVector3 bp = p - b;
+ btScalar d3 = ab.dot(bp);
+ btScalar d4 = ac.dot(bp);
+ if (d3 >= btScalar(0.0) && d4 <= d3)
{
result.m_closestPointOnSimplex = b;
result.m_usedVertices.usedVertexB = true;
- result.setBarycentricCoordinates(0,1,0);
+ result.setBarycentricCoordinates(0, 1, 0);
- return true; // b; // barycentric coordinates (0,1,0)
+ return true; // b; // barycentric coordinates (0,1,0)
}
- // Check if P in edge region of AB, if so return projection of P onto AB
- btScalar vc = d1*d4 - d3*d2;
- if (vc <= btScalar(0.0) && d1 >= btScalar(0.0) && d3 <= btScalar(0.0)) {
- btScalar v = d1 / (d1 - d3);
+ // Check if P in edge region of AB, if so return projection of P onto AB
+ btScalar vc = d1 * d4 - d3 * d2;
+ if (vc <= btScalar(0.0) && d1 >= btScalar(0.0) && d3 <= btScalar(0.0))
+ {
+ btScalar v = d1 / (d1 - d3);
result.m_closestPointOnSimplex = a + v * ab;
result.m_usedVertices.usedVertexA = true;
result.m_usedVertices.usedVertexB = true;
- result.setBarycentricCoordinates(1-v,v,0);
+ result.setBarycentricCoordinates(1 - v, v, 0);
return true;
- //return a + v * ab; // barycentric coordinates (1-v,v,0)
- }
-
- // Check if P in vertex region outside C
- btVector3 cp = p - c;
- btScalar d5 = ab.dot(cp);
- btScalar d6 = ac.dot(cp);
- if (d6 >= btScalar(0.0) && d5 <= d6)
+ //return a + v * ab; // barycentric coordinates (1-v,v,0)
+ }
+
+ // Check if P in vertex region outside C
+ btVector3 cp = p - c;
+ btScalar d5 = ab.dot(cp);
+ btScalar d6 = ac.dot(cp);
+ if (d6 >= btScalar(0.0) && d5 <= d6)
{
result.m_closestPointOnSimplex = c;
result.m_usedVertices.usedVertexC = true;
- result.setBarycentricCoordinates(0,0,1);
- return true;//c; // barycentric coordinates (0,0,1)
+ result.setBarycentricCoordinates(0, 0, 1);
+ return true; //c; // barycentric coordinates (0,0,1)
}
- // Check if P in edge region of AC, if so return projection of P onto AC
- btScalar vb = d5*d2 - d1*d6;
- if (vb <= btScalar(0.0) && d2 >= btScalar(0.0) && d6 <= btScalar(0.0)) {
- btScalar w = d2 / (d2 - d6);
+ // Check if P in edge region of AC, if so return projection of P onto AC
+ btScalar vb = d5 * d2 - d1 * d6;
+ if (vb <= btScalar(0.0) && d2 >= btScalar(0.0) && d6 <= btScalar(0.0))
+ {
+ btScalar w = d2 / (d2 - d6);
result.m_closestPointOnSimplex = a + w * ac;
result.m_usedVertices.usedVertexA = true;
result.m_usedVertices.usedVertexC = true;
- result.setBarycentricCoordinates(1-w,0,w);
+ result.setBarycentricCoordinates(1 - w, 0, w);
return true;
- //return a + w * ac; // barycentric coordinates (1-w,0,w)
- }
+ //return a + w * ac; // barycentric coordinates (1-w,0,w)
+ }
+
+ // Check if P in edge region of BC, if so return projection of P onto BC
+ btScalar va = d3 * d6 - d5 * d4;
+ if (va <= btScalar(0.0) && (d4 - d3) >= btScalar(0.0) && (d5 - d6) >= btScalar(0.0))
+ {
+ btScalar w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
- // Check if P in edge region of BC, if so return projection of P onto BC
- btScalar va = d3*d6 - d5*d4;
- if (va <= btScalar(0.0) && (d4 - d3) >= btScalar(0.0) && (d5 - d6) >= btScalar(0.0)) {
- btScalar w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
-
result.m_closestPointOnSimplex = b + w * (c - b);
result.m_usedVertices.usedVertexB = true;
result.m_usedVertices.usedVertexC = true;
- result.setBarycentricCoordinates(0,1-w,w);
- return true;
- // return b + w * (c - b); // barycentric coordinates (0,1-w,w)
- }
-
- // P inside face region. Compute Q through its barycentric coordinates (u,v,w)
- btScalar denom = btScalar(1.0) / (va + vb + vc);
- btScalar v = vb * denom;
- btScalar w = vc * denom;
-
+ result.setBarycentricCoordinates(0, 1 - w, w);
+ return true;
+ // return b + w * (c - b); // barycentric coordinates (0,1-w,w)
+ }
+
+ // P inside face region. Compute Q through its barycentric coordinates (u,v,w)
+ btScalar denom = btScalar(1.0) / (va + vb + vc);
+ btScalar v = vb * denom;
+ btScalar w = vc * denom;
+
result.m_closestPointOnSimplex = a + ab * v + ac * w;
result.m_usedVertices.usedVertexA = true;
result.m_usedVertices.usedVertexB = true;
result.m_usedVertices.usedVertexC = true;
- result.setBarycentricCoordinates(1-v-w,v,w);
-
- return true;
-// return a + ab * v + ac * w; // = u*a + v*b + w*c, u = va * denom = btScalar(1.0) - v - w
+ result.setBarycentricCoordinates(1 - v - w, v, w);
+ return true;
+ // return a + ab * v + ac * w; // = u*a + v*b + w*c, u = va * denom = btScalar(1.0) - v - w
}
-
-
-
-
/// Test if point p and d lie on opposite sides of plane through abc
int btVoronoiSimplexSolver::pointOutsideOfPlane(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d)
{
- btVector3 normal = (b-a).cross(c-a);
+ btVector3 normal = (b - a).cross(c - a);
- btScalar signp = (p - a).dot(normal); // [AP AB AC]
- btScalar signd = (d - a).dot( normal); // [AD AB AC]
+ btScalar signp = (p - a).dot(normal); // [AP AB AC]
+ btScalar signd = (d - a).dot(normal); // [AD AB AC]
#ifdef CATCH_DEGENERATE_TETRAHEDRON
#ifdef BT_USE_DOUBLE_PRECISION
-if (signd * signd < (btScalar(1e-8) * btScalar(1e-8)))
+ if (signd * signd < (btScalar(1e-8) * btScalar(1e-8)))
{
return -1;
}
#else
if (signd * signd < (btScalar(1e-4) * btScalar(1e-4)))
{
-// printf("affine dependent/degenerate\n");//
+ // printf("affine dependent/degenerate\n");//
return -1;
}
#endif
#endif
// Points on opposite sides if expression signs are opposite
- return signp * signd < btScalar(0.);
+ return signp * signd < btScalar(0.);
}
-
-bool btVoronoiSimplexSolver::closestPtPointTetrahedron(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d, btSubSimplexClosestResult& finalResult)
+bool btVoronoiSimplexSolver::closestPtPointTetrahedron(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d, btSubSimplexClosestResult& finalResult)
{
btSubSimplexClosestResult tempResult;
- // Start out assuming point inside all halfspaces, so closest to itself
+ // Start out assuming point inside all halfspaces, so closest to itself
finalResult.m_closestPointOnSimplex = p;
finalResult.m_usedVertices.reset();
- finalResult.m_usedVertices.usedVertexA = true;
+ finalResult.m_usedVertices.usedVertexA = true;
finalResult.m_usedVertices.usedVertexB = true;
finalResult.m_usedVertices.usedVertexC = true;
finalResult.m_usedVertices.usedVertexD = true;
- int pointOutsideABC = pointOutsideOfPlane(p, a, b, c, d);
+ int pointOutsideABC = pointOutsideOfPlane(p, a, b, c, d);
int pointOutsideACD = pointOutsideOfPlane(p, a, c, d, b);
- int pointOutsideADB = pointOutsideOfPlane(p, a, d, b, c);
- int pointOutsideBDC = pointOutsideOfPlane(p, b, d, c, a);
-
- if (pointOutsideABC < 0 || pointOutsideACD < 0 || pointOutsideADB < 0 || pointOutsideBDC < 0)
- {
- finalResult.m_degenerate = true;
- return false;
- }
+ int pointOutsideADB = pointOutsideOfPlane(p, a, d, b, c);
+ int pointOutsideBDC = pointOutsideOfPlane(p, b, d, c, a);
- if (!pointOutsideABC && !pointOutsideACD && !pointOutsideADB && !pointOutsideBDC)
- {
- return false;
- }
+ if (pointOutsideABC < 0 || pointOutsideACD < 0 || pointOutsideADB < 0 || pointOutsideBDC < 0)
+ {
+ finalResult.m_degenerate = true;
+ return false;
+ }
+ if (!pointOutsideABC && !pointOutsideACD && !pointOutsideADB && !pointOutsideBDC)
+ {
+ return false;
+ }
- btScalar bestSqDist = FLT_MAX;
- // If point outside face abc then compute closest point on abc
- if (pointOutsideABC)
+ btScalar bestSqDist = FLT_MAX;
+ // If point outside face abc then compute closest point on abc
+ if (pointOutsideABC)
{
- closestPtPointTriangle(p, a, b, c,tempResult);
+ closestPtPointTriangle(p, a, b, c, tempResult);
btVector3 q = tempResult.m_closestPointOnSimplex;
-
- btScalar sqDist = (q - p).dot( q - p);
- // Update best closest point if (squared) distance is less than current best
- if (sqDist < bestSqDist) {
+
+ btScalar sqDist = (q - p).dot(q - p);
+ // Update best closest point if (squared) distance is less than current best
+ if (sqDist < bestSqDist)
+ {
bestSqDist = sqDist;
finalResult.m_closestPointOnSimplex = q;
//convert result bitmask!
@@ -504,25 +481,22 @@ bool btVoronoiSimplexSolver::closestPtPointTetrahedron(const btVector3& p, const
finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexB;
finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexC;
finalResult.setBarycentricCoordinates(
- tempResult.m_barycentricCoords[VERTA],
- tempResult.m_barycentricCoords[VERTB],
- tempResult.m_barycentricCoords[VERTC],
- 0
- );
-
+ tempResult.m_barycentricCoords[VERTA],
+ tempResult.m_barycentricCoords[VERTB],
+ tempResult.m_barycentricCoords[VERTC],
+ 0);
}
- }
-
+ }
// Repeat test for face acd
- if (pointOutsideACD)
+ if (pointOutsideACD)
{
- closestPtPointTriangle(p, a, c, d,tempResult);
+ closestPtPointTriangle(p, a, c, d, tempResult);
btVector3 q = tempResult.m_closestPointOnSimplex;
//convert result bitmask!
- btScalar sqDist = (q - p).dot( q - p);
- if (sqDist < bestSqDist)
+ btScalar sqDist = (q - p).dot(q - p);
+ if (sqDist < bestSqDist)
{
bestSqDist = sqDist;
finalResult.m_closestPointOnSimplex = q;
@@ -532,52 +506,46 @@ bool btVoronoiSimplexSolver::closestPtPointTetrahedron(const btVector3& p, const
finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexB;
finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexC;
finalResult.setBarycentricCoordinates(
- tempResult.m_barycentricCoords[VERTA],
- 0,
- tempResult.m_barycentricCoords[VERTB],
- tempResult.m_barycentricCoords[VERTC]
- );
-
+ tempResult.m_barycentricCoords[VERTA],
+ 0,
+ tempResult.m_barycentricCoords[VERTB],
+ tempResult.m_barycentricCoords[VERTC]);
}
- }
- // Repeat test for face adb
+ }
+ // Repeat test for face adb
-
if (pointOutsideADB)
{
- closestPtPointTriangle(p, a, d, b,tempResult);
+ closestPtPointTriangle(p, a, d, b, tempResult);
btVector3 q = tempResult.m_closestPointOnSimplex;
//convert result bitmask!
- btScalar sqDist = (q - p).dot( q - p);
- if (sqDist < bestSqDist)
+ btScalar sqDist = (q - p).dot(q - p);
+ if (sqDist < bestSqDist)
{
bestSqDist = sqDist;
finalResult.m_closestPointOnSimplex = q;
finalResult.m_usedVertices.reset();
finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA;
finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexC;
-
+
finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexB;
finalResult.setBarycentricCoordinates(
- tempResult.m_barycentricCoords[VERTA],
- tempResult.m_barycentricCoords[VERTC],
- 0,
- tempResult.m_barycentricCoords[VERTB]
- );
-
+ tempResult.m_barycentricCoords[VERTA],
+ tempResult.m_barycentricCoords[VERTC],
+ 0,
+ tempResult.m_barycentricCoords[VERTB]);
}
- }
- // Repeat test for face bdc
-
+ }
+ // Repeat test for face bdc
if (pointOutsideBDC)
{
- closestPtPointTriangle(p, b, d, c,tempResult);
+ closestPtPointTriangle(p, b, d, c, tempResult);
btVector3 q = tempResult.m_closestPointOnSimplex;
//convert result bitmask!
- btScalar sqDist = (q - p).dot( q - p);
- if (sqDist < bestSqDist)
+ btScalar sqDist = (q - p).dot(q - p);
+ if (sqDist < bestSqDist)
{
bestSqDist = sqDist;
finalResult.m_closestPointOnSimplex = q;
@@ -588,25 +556,22 @@ bool btVoronoiSimplexSolver::closestPtPointTetrahedron(const btVector3& p, const
finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexB;
finalResult.setBarycentricCoordinates(
- 0,
- tempResult.m_barycentricCoords[VERTA],
- tempResult.m_barycentricCoords[VERTC],
- tempResult.m_barycentricCoords[VERTB]
- );
-
+ 0,
+ tempResult.m_barycentricCoords[VERTA],
+ tempResult.m_barycentricCoords[VERTC],
+ tempResult.m_barycentricCoords[VERTB]);
}
- }
+ }
//help! we ended up full !
-
+
if (finalResult.m_usedVertices.usedVertexA &&
finalResult.m_usedVertices.usedVertexB &&
finalResult.m_usedVertices.usedVertexC &&
- finalResult.m_usedVertices.usedVertexD)
+ finalResult.m_usedVertices.usedVertexD)
{
return true;
}
- return true;
+ return true;
}
-
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h
index 80fd490f4e..24a0a8f2df 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h
@@ -13,15 +13,11 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
-
#ifndef BT_VORONOI_SIMPLEX_SOLVER_H
#define BT_VORONOI_SIMPLEX_SOLVER_H
#include "btSimplexSolverInterface.h"
-
-
#define VORONOI_SIMPLEX_MAX_VERTS 5
///disable next define, or use defaultCollisionConfiguration->getSimplexSolver()->setEqualVertexThreshold(0.f) to disable/configure
@@ -31,9 +27,10 @@ subject to the following restrictions:
#define VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD 1e-12f
#else
#define VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD 0.0001f
-#endif//BT_USE_DOUBLE_PRECISION
+#endif //BT_USE_DOUBLE_PRECISION
-struct btUsageBitfield{
+struct btUsageBitfield
+{
btUsageBitfield()
{
reset();
@@ -46,140 +43,131 @@ struct btUsageBitfield{
usedVertexC = false;
usedVertexD = false;
}
- unsigned short usedVertexA : 1;
- unsigned short usedVertexB : 1;
- unsigned short usedVertexC : 1;
- unsigned short usedVertexD : 1;
- unsigned short unused1 : 1;
- unsigned short unused2 : 1;
- unsigned short unused3 : 1;
- unsigned short unused4 : 1;
+ unsigned short usedVertexA : 1;
+ unsigned short usedVertexB : 1;
+ unsigned short usedVertexC : 1;
+ unsigned short usedVertexD : 1;
+ unsigned short unused1 : 1;
+ unsigned short unused2 : 1;
+ unsigned short unused3 : 1;
+ unsigned short unused4 : 1;
};
-
-struct btSubSimplexClosestResult
+struct btSubSimplexClosestResult
{
- btVector3 m_closestPointOnSimplex;
+ btVector3 m_closestPointOnSimplex;
//MASK for m_usedVertices
- //stores the simplex vertex-usage, using the MASK,
+ //stores the simplex vertex-usage, using the MASK,
// if m_usedVertices & MASK then the related vertex is used
- btUsageBitfield m_usedVertices;
- btScalar m_barycentricCoords[4];
+ btUsageBitfield m_usedVertices;
+ btScalar m_barycentricCoords[4];
bool m_degenerate;
- void reset()
+ void reset()
{
m_degenerate = false;
setBarycentricCoordinates();
m_usedVertices.reset();
}
- bool isValid()
+ bool isValid()
{
bool valid = (m_barycentricCoords[0] >= btScalar(0.)) &&
- (m_barycentricCoords[1] >= btScalar(0.)) &&
- (m_barycentricCoords[2] >= btScalar(0.)) &&
- (m_barycentricCoords[3] >= btScalar(0.));
-
+ (m_barycentricCoords[1] >= btScalar(0.)) &&
+ (m_barycentricCoords[2] >= btScalar(0.)) &&
+ (m_barycentricCoords[3] >= btScalar(0.));
return valid;
}
- void setBarycentricCoordinates(btScalar a=btScalar(0.),btScalar b=btScalar(0.),btScalar c=btScalar(0.),btScalar d=btScalar(0.))
+ void setBarycentricCoordinates(btScalar a = btScalar(0.), btScalar b = btScalar(0.), btScalar c = btScalar(0.), btScalar d = btScalar(0.))
{
m_barycentricCoords[0] = a;
m_barycentricCoords[1] = b;
m_barycentricCoords[2] = c;
m_barycentricCoords[3] = d;
}
-
};
/// btVoronoiSimplexSolver is an implementation of the closest point distance algorithm from a 1-4 points simplex to the origin.
/// Can be used with GJK, as an alternative to Johnson distance algorithm.
#ifdef NO_VIRTUAL_INTERFACE
-ATTRIBUTE_ALIGNED16(class) btVoronoiSimplexSolver
+ATTRIBUTE_ALIGNED16(class)
+btVoronoiSimplexSolver
#else
-ATTRIBUTE_ALIGNED16(class) btVoronoiSimplexSolver : public btSimplexSolverInterface
+ATTRIBUTE_ALIGNED16(class)
+btVoronoiSimplexSolver : public btSimplexSolverInterface
#endif
{
public:
-
BT_DECLARE_ALIGNED_ALLOCATOR();
- int m_numVertices;
-
- btVector3 m_simplexVectorW[VORONOI_SIMPLEX_MAX_VERTS];
- btVector3 m_simplexPointsP[VORONOI_SIMPLEX_MAX_VERTS];
- btVector3 m_simplexPointsQ[VORONOI_SIMPLEX_MAX_VERTS];
+ int m_numVertices;
-
+ btVector3 m_simplexVectorW[VORONOI_SIMPLEX_MAX_VERTS];
+ btVector3 m_simplexPointsP[VORONOI_SIMPLEX_MAX_VERTS];
+ btVector3 m_simplexPointsQ[VORONOI_SIMPLEX_MAX_VERTS];
- btVector3 m_cachedP1;
- btVector3 m_cachedP2;
- btVector3 m_cachedV;
- btVector3 m_lastW;
-
- btScalar m_equalVertexThreshold;
- bool m_cachedValidClosest;
+ btVector3 m_cachedP1;
+ btVector3 m_cachedP2;
+ btVector3 m_cachedV;
+ btVector3 m_lastW;
+ btScalar m_equalVertexThreshold;
+ bool m_cachedValidClosest;
btSubSimplexClosestResult m_cachedBC;
- bool m_needsUpdate;
-
- void removeVertex(int index);
- void reduceVertices (const btUsageBitfield& usedVerts);
- bool updateClosestVectorAndPoints();
+ bool m_needsUpdate;
- bool closestPtPointTetrahedron(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d, btSubSimplexClosestResult& finalResult);
- int pointOutsideOfPlane(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d);
- bool closestPtPointTriangle(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c,btSubSimplexClosestResult& result);
+ void removeVertex(int index);
+ void reduceVertices(const btUsageBitfield& usedVerts);
+ bool updateClosestVectorAndPoints();
-public:
+ bool closestPtPointTetrahedron(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d, btSubSimplexClosestResult& finalResult);
+ int pointOutsideOfPlane(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d);
+ bool closestPtPointTriangle(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, btSubSimplexClosestResult& result);
+public:
btVoronoiSimplexSolver()
- : m_equalVertexThreshold(VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD)
+ : m_equalVertexThreshold(VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD)
{
}
- void reset();
-
- void addVertex(const btVector3& w, const btVector3& p, const btVector3& q);
+ void reset();
- void setEqualVertexThreshold(btScalar threshold)
- {
- m_equalVertexThreshold = threshold;
- }
+ void addVertex(const btVector3& w, const btVector3& p, const btVector3& q);
- btScalar getEqualVertexThreshold() const
- {
- return m_equalVertexThreshold;
- }
+ void setEqualVertexThreshold(btScalar threshold)
+ {
+ m_equalVertexThreshold = threshold;
+ }
- bool closest(btVector3& v);
+ btScalar getEqualVertexThreshold() const
+ {
+ return m_equalVertexThreshold;
+ }
- btScalar maxVertex();
+ bool closest(btVector3 & v);
- bool fullSimplex() const
- {
- return (m_numVertices == 4);
- }
+ btScalar maxVertex();
- int getSimplex(btVector3 *pBuf, btVector3 *qBuf, btVector3 *yBuf) const;
+ bool fullSimplex() const
+ {
+ return (m_numVertices == 4);
+ }
- bool inSimplex(const btVector3& w);
-
- void backup_closest(btVector3& v) ;
+ int getSimplex(btVector3 * pBuf, btVector3 * qBuf, btVector3 * yBuf) const;
- bool emptySimplex() const ;
+ bool inSimplex(const btVector3& w);
- void compute_points(btVector3& p1, btVector3& p2) ;
+ void backup_closest(btVector3 & v);
- int numVertices() const
- {
- return m_numVertices;
- }
+ bool emptySimplex() const;
+ void compute_points(btVector3 & p1, btVector3 & p2);
+ int numVertices() const
+ {
+ return m_numVertices;
+ }
};
-#endif //BT_VORONOI_SIMPLEX_SOLVER_H
-
+#endif //BT_VORONOI_SIMPLEX_SOLVER_H
diff --git a/thirdparty/bullet/BulletDynamics/Character/btCharacterControllerInterface.h b/thirdparty/bullet/BulletDynamics/Character/btCharacterControllerInterface.h
index abe24b5ca6..2ccf317b92 100644
--- a/thirdparty/bullet/BulletDynamics/Character/btCharacterControllerInterface.h
+++ b/thirdparty/bullet/BulletDynamics/Character/btCharacterControllerInterface.h
@@ -26,22 +26,21 @@ class btCollisionWorld;
class btCharacterControllerInterface : public btActionInterface
{
public:
- btCharacterControllerInterface () {};
- virtual ~btCharacterControllerInterface () {};
-
- virtual void setWalkDirection(const btVector3& walkDirection) = 0;
- virtual void setVelocityForTimeInterval(const btVector3& velocity, btScalar timeInterval) = 0;
- virtual void reset ( btCollisionWorld* collisionWorld ) = 0;
- virtual void warp (const btVector3& origin) = 0;
-
- virtual void preStep ( btCollisionWorld* collisionWorld) = 0;
- virtual void playerStep (btCollisionWorld* collisionWorld, btScalar dt) = 0;
- virtual bool canJump () const = 0;
- virtual void jump(const btVector3& dir = btVector3(0, 0, 0)) = 0;
-
- virtual bool onGround () const = 0;
- virtual void setUpInterpolate (bool value) = 0;
-};
+ btCharacterControllerInterface(){};
+ virtual ~btCharacterControllerInterface(){};
+
+ virtual void setWalkDirection(const btVector3& walkDirection) = 0;
+ virtual void setVelocityForTimeInterval(const btVector3& velocity, btScalar timeInterval) = 0;
+ virtual void reset(btCollisionWorld* collisionWorld) = 0;
+ virtual void warp(const btVector3& origin) = 0;
-#endif //BT_CHARACTER_CONTROLLER_INTERFACE_H
+ virtual void preStep(btCollisionWorld* collisionWorld) = 0;
+ virtual void playerStep(btCollisionWorld* collisionWorld, btScalar dt) = 0;
+ virtual bool canJump() const = 0;
+ virtual void jump(const btVector3& dir = btVector3(0, 0, 0)) = 0;
+
+ virtual bool onGround() const = 0;
+ virtual void setUpInterpolate(bool value) = 0;
+};
+#endif //BT_CHARACTER_CONTROLLER_INTERFACE_H
diff --git a/thirdparty/bullet/BulletDynamics/Character/btKinematicCharacterController.cpp b/thirdparty/bullet/BulletDynamics/Character/btKinematicCharacterController.cpp
index cb1aa71a14..2bbccb291c 100644
--- a/thirdparty/bullet/BulletDynamics/Character/btKinematicCharacterController.cpp
+++ b/thirdparty/bullet/BulletDynamics/Character/btKinematicCharacterController.cpp
@@ -13,7 +13,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#include <stdio.h>
#include "LinearMath/btIDebugDraw.h"
#include "BulletCollision/CollisionDispatch/btGhostObject.h"
@@ -24,20 +23,19 @@ subject to the following restrictions:
#include "LinearMath/btDefaultMotionState.h"
#include "btKinematicCharacterController.h"
-
// static helper method
static btVector3
getNormalizedVector(const btVector3& v)
{
btVector3 n(0, 0, 0);
- if (v.length() > SIMD_EPSILON) {
+ if (v.length() > SIMD_EPSILON)
+ {
n = v.normalized();
}
return n;
}
-
///@todo Interact with dynamic objects,
///Ride kinematicly animated platforms properly
///More realistic (or maybe just a config option) falling
@@ -47,18 +45,19 @@ getNormalizedVector(const btVector3& v)
class btKinematicClosestNotMeRayResultCallback : public btCollisionWorld::ClosestRayResultCallback
{
public:
- btKinematicClosestNotMeRayResultCallback (btCollisionObject* me) : btCollisionWorld::ClosestRayResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0))
+ btKinematicClosestNotMeRayResultCallback(btCollisionObject* me) : btCollisionWorld::ClosestRayResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0))
{
m_me = me;
}
- virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace)
+ virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult, bool normalInWorldSpace)
{
if (rayResult.m_collisionObject == m_me)
return 1.0;
- return ClosestRayResultCallback::addSingleResult (rayResult, normalInWorldSpace);
+ return ClosestRayResultCallback::addSingleResult(rayResult, normalInWorldSpace);
}
+
protected:
btCollisionObject* m_me;
};
@@ -66,15 +65,12 @@ protected:
class btKinematicClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback
{
public:
- btKinematicClosestNotMeConvexResultCallback (btCollisionObject* me, const btVector3& up, btScalar minSlopeDot)
- : btCollisionWorld::ClosestConvexResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0))
- , m_me(me)
- , m_up(up)
- , m_minSlopeDot(minSlopeDot)
+ btKinematicClosestNotMeConvexResultCallback(btCollisionObject* me, const btVector3& up, btScalar minSlopeDot)
+ : btCollisionWorld::ClosestConvexResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0)), m_me(me), m_up(up), m_minSlopeDot(minSlopeDot)
{
}
- virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult,bool normalInWorldSpace)
+ virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult, bool normalInWorldSpace)
{
if (convexResult.m_hitCollisionObject == m_me)
return btScalar(1.0);
@@ -86,19 +82,22 @@ public:
if (normalInWorldSpace)
{
hitNormalWorld = convexResult.m_hitNormalLocal;
- } else
+ }
+ else
{
///need to transform normal into worldspace
- hitNormalWorld = convexResult.m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal;
+ hitNormalWorld = convexResult.m_hitCollisionObject->getWorldTransform().getBasis() * convexResult.m_hitNormalLocal;
}
btScalar dotUp = m_up.dot(hitNormalWorld);
- if (dotUp < m_minSlopeDot) {
+ if (dotUp < m_minSlopeDot)
+ {
return btScalar(1.0);
}
- return ClosestConvexResultCallback::addSingleResult (convexResult, normalInWorldSpace);
+ return ClosestConvexResultCallback::addSingleResult(convexResult, normalInWorldSpace);
}
+
protected:
btCollisionObject* m_me;
const btVector3 m_up;
@@ -110,7 +109,7 @@ protected:
*
* from: http://www-cs-students.stanford.edu/~adityagp/final/node3.html
*/
-btVector3 btKinematicCharacterController::computeReflectionDirection (const btVector3& direction, const btVector3& normal)
+btVector3 btKinematicCharacterController::computeReflectionDirection(const btVector3& direction, const btVector3& normal)
{
return direction - (btScalar(2.0) * direction.dot(normal)) * normal;
}
@@ -118,7 +117,7 @@ btVector3 btKinematicCharacterController::computeReflectionDirection (const btVe
/*
* Returns the portion of 'direction' that is parallel to 'normal'
*/
-btVector3 btKinematicCharacterController::parallelComponent (const btVector3& direction, const btVector3& normal)
+btVector3 btKinematicCharacterController::parallelComponent(const btVector3& direction, const btVector3& normal)
{
btScalar magnitude = direction.dot(normal);
return normal * magnitude;
@@ -127,29 +126,29 @@ btVector3 btKinematicCharacterController::parallelComponent (const btVector3& di
/*
* Returns the portion of 'direction' that is perpindicular to 'normal'
*/
-btVector3 btKinematicCharacterController::perpindicularComponent (const btVector3& direction, const btVector3& normal)
+btVector3 btKinematicCharacterController::perpindicularComponent(const btVector3& direction, const btVector3& normal)
{
return direction - parallelComponent(direction, normal);
}
-btKinematicCharacterController::btKinematicCharacterController (btPairCachingGhostObject* ghostObject,btConvexShape* convexShape,btScalar stepHeight, const btVector3& up)
+btKinematicCharacterController::btKinematicCharacterController(btPairCachingGhostObject* ghostObject, btConvexShape* convexShape, btScalar stepHeight, const btVector3& up)
{
m_ghostObject = ghostObject;
m_up.setValue(0.0f, 0.0f, 1.0f);
m_jumpAxis.setValue(0.0f, 0.0f, 1.0f);
m_addedMargin = 0.02;
- m_walkDirection.setValue(0.0,0.0,0.0);
+ m_walkDirection.setValue(0.0, 0.0, 0.0);
m_AngVel.setValue(0.0, 0.0, 0.0);
- m_useGhostObjectSweepTest = true;
+ m_useGhostObjectSweepTest = true;
m_turnAngle = btScalar(0.0);
- m_convexShape=convexShape;
- m_useWalkDirection = true; // use walk direction by default, legacy behavior
+ m_convexShape = convexShape;
+ m_useWalkDirection = true; // use walk direction by default, legacy behavior
m_velocityTimeInterval = 0.0;
m_verticalVelocity = 0.0;
m_verticalOffset = 0.0;
- m_gravity = 9.8 * 3.0 ; // 3G acceleration.
- m_fallSpeed = 55.0; // Terminal velocity of a sky diver in m/s.
- m_jumpSpeed = 10.0; // ?
+ m_gravity = 9.8 * 3.0; // 3G acceleration.
+ m_fallSpeed = 55.0; // Terminal velocity of a sky diver in m/s.
+ m_jumpSpeed = 10.0; // ?
m_SetjumpSpeed = m_jumpSpeed;
m_wasOnGround = false;
m_wasJumping = false;
@@ -166,7 +165,7 @@ btKinematicCharacterController::btKinematicCharacterController (btPairCachingGho
setMaxSlope(btRadians(45.0));
}
-btKinematicCharacterController::~btKinematicCharacterController ()
+btKinematicCharacterController::~btKinematicCharacterController()
{
}
@@ -175,7 +174,7 @@ btPairCachingGhostObject* btKinematicCharacterController::getGhostObject()
return m_ghostObject;
}
-bool btKinematicCharacterController::recoverFromPenetration ( btCollisionWorld* collisionWorld)
+bool btKinematicCharacterController::recoverFromPenetration(btCollisionWorld* collisionWorld)
{
// Here we must refresh the overlapping paircache as the penetrating movement itself or the
// previous recovery iteration might have used setWorldTransform and pushed us into an object
@@ -186,19 +185,19 @@ bool btKinematicCharacterController::recoverFromPenetration ( btCollisionWorld*
// paircache and the ghostobject's internal paircache at the same time. /BW
btVector3 minAabb, maxAabb;
- m_convexShape->getAabb(m_ghostObject->getWorldTransform(), minAabb,maxAabb);
- collisionWorld->getBroadphase()->setAabb(m_ghostObject->getBroadphaseHandle(),
- minAabb,
- maxAabb,
- collisionWorld->getDispatcher());
-
+ m_convexShape->getAabb(m_ghostObject->getWorldTransform(), minAabb, maxAabb);
+ collisionWorld->getBroadphase()->setAabb(m_ghostObject->getBroadphaseHandle(),
+ minAabb,
+ maxAabb,
+ collisionWorld->getDispatcher());
+
bool penetration = false;
collisionWorld->getDispatcher()->dispatchAllCollisionPairs(m_ghostObject->getOverlappingPairCache(), collisionWorld->getDispatchInfo(), collisionWorld->getDispatcher());
m_currentPosition = m_ghostObject->getWorldTransform().getOrigin();
-
-// btScalar maxPen = btScalar(0.0);
+
+ // btScalar maxPen = btScalar(0.0);
for (int i = 0; i < m_ghostObject->getOverlappingPairCache()->getNumOverlappingPairs(); i++)
{
m_manifoldArray.resize(0);
@@ -206,25 +205,24 @@ bool btKinematicCharacterController::recoverFromPenetration ( btCollisionWorld*
btBroadphasePair* collisionPair = &m_ghostObject->getOverlappingPairCache()->getOverlappingPairArray()[i];
btCollisionObject* obj0 = static_cast<btCollisionObject*>(collisionPair->m_pProxy0->m_clientObject);
- btCollisionObject* obj1 = static_cast<btCollisionObject*>(collisionPair->m_pProxy1->m_clientObject);
+ btCollisionObject* obj1 = static_cast<btCollisionObject*>(collisionPair->m_pProxy1->m_clientObject);
if ((obj0 && !obj0->hasContactResponse()) || (obj1 && !obj1->hasContactResponse()))
continue;
if (!needsCollision(obj0, obj1))
continue;
-
+
if (collisionPair->m_algorithm)
collisionPair->m_algorithm->getAllContactManifolds(m_manifoldArray);
-
- for (int j=0;j<m_manifoldArray.size();j++)
+ for (int j = 0; j < m_manifoldArray.size(); j++)
{
btPersistentManifold* manifold = m_manifoldArray[j];
btScalar directionSign = manifold->getBody0() == m_ghostObject ? btScalar(-1.0) : btScalar(1.0);
- for (int p=0;p<manifold->getNumContacts();p++)
+ for (int p = 0; p < manifold->getNumContacts(); p++)
{
- const btManifoldPoint&pt = manifold->getContactPoint(p);
+ const btManifoldPoint& pt = manifold->getContactPoint(p);
btScalar dist = pt.getDistance();
@@ -239,22 +237,24 @@ bool btKinematicCharacterController::recoverFromPenetration ( btCollisionWorld*
//}
m_currentPosition += pt.m_normalWorldOnB * directionSign * dist * btScalar(0.2);
penetration = true;
- } else {
+ }
+ else
+ {
//printf("touching %f\n", dist);
}
}
-
+
//manifold->clearManifold();
}
}
btTransform newTrans = m_ghostObject->getWorldTransform();
newTrans.setOrigin(m_currentPosition);
m_ghostObject->setWorldTransform(newTrans);
-// printf("m_touchingNormal = %f,%f,%f\n",m_touchingNormal[0],m_touchingNormal[1],m_touchingNormal[2]);
+ // printf("m_touchingNormal = %f,%f,%f\n",m_touchingNormal[0],m_touchingNormal[1],m_touchingNormal[2]);
return penetration;
}
-void btKinematicCharacterController::stepUp ( btCollisionWorld* world)
+void btKinematicCharacterController::stepUp(btCollisionWorld* world)
{
btScalar stepHeight = 0.0f;
if (m_verticalVelocity < 0.0)
@@ -263,8 +263,8 @@ void btKinematicCharacterController::stepUp ( btCollisionWorld* world)
// phase 1: up
btTransform start, end;
- start.setIdentity ();
- end.setIdentity ();
+ start.setIdentity();
+ end.setIdentity();
/* FIXME: Handle penetration properly */
start.setOrigin(m_currentPosition);
@@ -272,7 +272,7 @@ void btKinematicCharacterController::stepUp ( btCollisionWorld* world)
m_targetPosition = m_currentPosition + m_up * (stepHeight) + m_jumpAxis * ((m_verticalOffset > 0.f ? m_verticalOffset : 0.f));
m_currentPosition = m_targetPosition;
- end.setOrigin (m_targetPosition);
+ end.setOrigin(m_targetPosition);
start.setRotation(m_currentOrientation);
end.setRotation(m_targetOrientation);
@@ -280,10 +280,10 @@ void btKinematicCharacterController::stepUp ( btCollisionWorld* world)
btKinematicClosestNotMeConvexResultCallback callback(m_ghostObject, -m_up, m_maxSlopeCosine);
callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
-
+
if (m_useGhostObjectSweepTest)
{
- m_ghostObject->convexSweepTest (m_convexShape, start, end, callback, world->getDispatchInfo().m_allowedCcdPenetration);
+ m_ghostObject->convexSweepTest(m_convexShape, start, end, callback, world->getDispatchInfo().m_allowedCcdPenetration);
}
else
{
@@ -298,7 +298,7 @@ void btKinematicCharacterController::stepUp ( btCollisionWorld* world)
// we moved up only a fraction of the step height
m_currentStepOffset = stepHeight * callback.m_closestHitFraction;
if (m_interpolateUp == true)
- m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
+ m_currentPosition.setInterpolate3(m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
else
m_currentPosition = m_targetPosition;
}
@@ -329,7 +329,9 @@ void btKinematicCharacterController::stepUp ( btCollisionWorld* world)
m_verticalVelocity = 0.0;
m_currentStepOffset = m_stepHeight;
}
- } else {
+ }
+ else
+ {
m_currentStepOffset = stepHeight;
m_currentPosition = m_targetPosition;
}
@@ -342,43 +344,44 @@ bool btKinematicCharacterController::needsCollision(const btCollisionObject* bod
return collides;
}
-void btKinematicCharacterController::updateTargetPositionBasedOnCollision (const btVector3& hitNormal, btScalar tangentMag, btScalar normalMag)
+void btKinematicCharacterController::updateTargetPositionBasedOnCollision(const btVector3& hitNormal, btScalar tangentMag, btScalar normalMag)
{
btVector3 movementDirection = m_targetPosition - m_currentPosition;
btScalar movementLength = movementDirection.length();
- if (movementLength>SIMD_EPSILON)
+ if (movementLength > SIMD_EPSILON)
{
movementDirection.normalize();
- btVector3 reflectDir = computeReflectionDirection (movementDirection, hitNormal);
+ btVector3 reflectDir = computeReflectionDirection(movementDirection, hitNormal);
reflectDir.normalize();
btVector3 parallelDir, perpindicularDir;
- parallelDir = parallelComponent (reflectDir, hitNormal);
- perpindicularDir = perpindicularComponent (reflectDir, hitNormal);
+ parallelDir = parallelComponent(reflectDir, hitNormal);
+ perpindicularDir = perpindicularComponent(reflectDir, hitNormal);
m_targetPosition = m_currentPosition;
- if (0)//tangentMag != 0.0)
+ if (0) //tangentMag != 0.0)
{
- btVector3 parComponent = parallelDir * btScalar (tangentMag*movementLength);
-// printf("parComponent=%f,%f,%f\n",parComponent[0],parComponent[1],parComponent[2]);
- m_targetPosition += parComponent;
+ btVector3 parComponent = parallelDir * btScalar(tangentMag * movementLength);
+ // printf("parComponent=%f,%f,%f\n",parComponent[0],parComponent[1],parComponent[2]);
+ m_targetPosition += parComponent;
}
if (normalMag != 0.0)
{
- btVector3 perpComponent = perpindicularDir * btScalar (normalMag*movementLength);
-// printf("perpComponent=%f,%f,%f\n",perpComponent[0],perpComponent[1],perpComponent[2]);
+ btVector3 perpComponent = perpindicularDir * btScalar(normalMag * movementLength);
+ // printf("perpComponent=%f,%f,%f\n",perpComponent[0],perpComponent[1],perpComponent[2]);
m_targetPosition += perpComponent;
}
- } else
+ }
+ else
{
-// printf("movementLength don't normalize a zero vector\n");
+ // printf("movementLength don't normalize a zero vector\n");
}
}
-void btKinematicCharacterController::stepForwardAndStrafe ( btCollisionWorld* collisionWorld, const btVector3& walkMove)
+void btKinematicCharacterController::stepForwardAndStrafe(btCollisionWorld* collisionWorld, const btVector3& walkMove)
{
// printf("m_normalizedDirection=%f,%f,%f\n",
// m_normalizedDirection[0],m_normalizedDirection[1],m_normalizedDirection[2]);
@@ -387,29 +390,28 @@ void btKinematicCharacterController::stepForwardAndStrafe ( btCollisionWorld* co
m_targetPosition = m_currentPosition + walkMove;
- start.setIdentity ();
- end.setIdentity ();
-
+ start.setIdentity();
+ end.setIdentity();
+
btScalar fraction = 1.0;
- btScalar distance2 = (m_currentPosition-m_targetPosition).length2();
-// printf("distance2=%f\n",distance2);
+ btScalar distance2 = (m_currentPosition - m_targetPosition).length2();
+ // printf("distance2=%f\n",distance2);
int maxIter = 10;
while (fraction > btScalar(0.01) && maxIter-- > 0)
{
- start.setOrigin (m_currentPosition);
- end.setOrigin (m_targetPosition);
+ start.setOrigin(m_currentPosition);
+ end.setOrigin(m_targetPosition);
btVector3 sweepDirNegative(m_currentPosition - m_targetPosition);
start.setRotation(m_currentOrientation);
end.setRotation(m_targetOrientation);
- btKinematicClosestNotMeConvexResultCallback callback (m_ghostObject, sweepDirNegative, btScalar(0.0));
+ btKinematicClosestNotMeConvexResultCallback callback(m_ghostObject, sweepDirNegative, btScalar(0.0));
callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
-
btScalar margin = m_convexShape->getMargin();
m_convexShape->setMargin(margin + m_addedMargin);
@@ -426,18 +428,17 @@ void btKinematicCharacterController::stepForwardAndStrafe ( btCollisionWorld* co
}
m_convexShape->setMargin(margin);
-
fraction -= callback.m_closestHitFraction;
if (callback.hasHit() && m_ghostObject->hasContactResponse() && needsCollision(m_ghostObject, callback.m_hitCollisionObject))
- {
+ {
// we moved only a fraction
//btScalar hitDistance;
//hitDistance = (callback.m_hitPointWorld - m_currentPosition).length();
-// m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
+ // m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
- updateTargetPositionBasedOnCollision (callback.m_hitNormalWorld);
+ updateTargetPositionBasedOnCollision(callback.m_hitNormalWorld);
btVector3 currentDir = m_targetPosition - m_currentPosition;
distance2 = currentDir.length2();
if (distance2 > SIMD_EPSILON)
@@ -448,21 +449,21 @@ void btKinematicCharacterController::stepForwardAndStrafe ( btCollisionWorld* co
{
break;
}
- } else
+ }
+ else
{
-// printf("currentDir: don't normalize a zero vector\n");
+ // printf("currentDir: don't normalize a zero vector\n");
break;
}
-
}
- else
- {
- m_currentPosition = m_targetPosition;
+ else
+ {
+ m_currentPosition = m_targetPosition;
}
}
}
-void btKinematicCharacterController::stepDown ( btCollisionWorld* collisionWorld, btScalar dt)
+void btKinematicCharacterController::stepDown(btCollisionWorld* collisionWorld, btScalar dt)
{
btTransform start, end, end_double;
bool runonce = false;
@@ -475,64 +476,64 @@ void btKinematicCharacterController::stepDown ( btCollisionWorld* collisionWorld
m_targetPosition -= (step_drop + gravity_drop);*/
btVector3 orig_position = m_targetPosition;
-
- btScalar downVelocity = (m_verticalVelocity<0.f?-m_verticalVelocity:0.f) * dt;
+
+ btScalar downVelocity = (m_verticalVelocity < 0.f ? -m_verticalVelocity : 0.f) * dt;
if (m_verticalVelocity > 0.0)
return;
- if(downVelocity > 0.0 && downVelocity > m_fallSpeed
- && (m_wasOnGround || !m_wasJumping))
+ if (downVelocity > 0.0 && downVelocity > m_fallSpeed && (m_wasOnGround || !m_wasJumping))
downVelocity = m_fallSpeed;
btVector3 step_drop = m_up * (m_currentStepOffset + downVelocity);
m_targetPosition -= step_drop;
btKinematicClosestNotMeConvexResultCallback callback(m_ghostObject, m_up, m_maxSlopeCosine);
- callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
- callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
+ callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
+ callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
btKinematicClosestNotMeConvexResultCallback callback2(m_ghostObject, m_up, m_maxSlopeCosine);
- callback2.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
- callback2.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
+ callback2.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
+ callback2.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
while (1)
{
- start.setIdentity ();
- end.setIdentity ();
+ start.setIdentity();
+ end.setIdentity();
- end_double.setIdentity ();
+ end_double.setIdentity();
- start.setOrigin (m_currentPosition);
- end.setOrigin (m_targetPosition);
+ start.setOrigin(m_currentPosition);
+ end.setOrigin(m_targetPosition);
start.setRotation(m_currentOrientation);
end.setRotation(m_targetOrientation);
//set double test for 2x the step drop, to check for a large drop vs small drop
- end_double.setOrigin (m_targetPosition - step_drop);
+ end_double.setOrigin(m_targetPosition - step_drop);
if (m_useGhostObjectSweepTest)
{
- m_ghostObject->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
+ m_ghostObject->convexSweepTest(m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
if (!callback.hasHit() && m_ghostObject->hasContactResponse())
{
//test a double fall height, to see if the character should interpolate it's fall (full) or not (partial)
- m_ghostObject->convexSweepTest (m_convexShape, start, end_double, callback2, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
+ m_ghostObject->convexSweepTest(m_convexShape, start, end_double, callback2, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
}
- } else
+ }
+ else
{
- collisionWorld->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
+ collisionWorld->convexSweepTest(m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
if (!callback.hasHit() && m_ghostObject->hasContactResponse())
{
//test a double fall height, to see if the character should interpolate it's fall (large) or not (small)
- collisionWorld->convexSweepTest (m_convexShape, start, end_double, callback2, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
+ collisionWorld->convexSweepTest(m_convexShape, start, end_double, callback2, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
}
}
-
- btScalar downVelocity2 = (m_verticalVelocity<0.f?-m_verticalVelocity:0.f) * dt;
+
+ btScalar downVelocity2 = (m_verticalVelocity < 0.f ? -m_verticalVelocity : 0.f) * dt;
bool has_hit;
if (bounce_fix == true)
has_hit = (callback.hasHit() || callback2.hasHit()) && m_ghostObject->hasContactResponse() && needsCollision(m_ghostObject, callback.m_hitCollisionObject);
@@ -543,8 +544,7 @@ void btKinematicCharacterController::stepDown ( btCollisionWorld* collisionWorld
if (m_verticalVelocity < 0.0)
stepHeight = m_stepHeight;
- if (downVelocity2 > 0.0 && downVelocity2 < stepHeight && has_hit == true && runonce == false
- && (m_wasOnGround || !m_wasJumping))
+ if (downVelocity2 > 0.0 && downVelocity2 < stepHeight && has_hit == true && runonce == false && (m_wasOnGround || !m_wasJumping))
{
//redo the velocity calculation when falling a small amount, for fast stairs motion
//for larger falls, use the smoother/slower interpolated movement by not touching the target position
@@ -555,7 +555,7 @@ void btKinematicCharacterController::stepDown ( btCollisionWorld* collisionWorld
step_drop = m_up * (m_currentStepOffset + downVelocity);
m_targetPosition -= step_drop;
runonce = true;
- continue; //re-run previous tests
+ continue; //re-run previous tests
}
break;
}
@@ -570,30 +570,32 @@ void btKinematicCharacterController::stepDown ( btCollisionWorld* collisionWorld
if (bounce_fix == true)
{
if (full_drop == true)
- m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
- else
+ m_currentPosition.setInterpolate3(m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
+ else
//due to errors in the closestHitFraction variable when used with large polygons, calculate the hit fraction manually
- m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, fraction);
+ m_currentPosition.setInterpolate3(m_currentPosition, m_targetPosition, fraction);
}
else
- m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
+ m_currentPosition.setInterpolate3(m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
full_drop = false;
m_verticalVelocity = 0.0;
m_verticalOffset = 0.0;
m_wasJumping = false;
- } else {
+ }
+ else
+ {
// we dropped the full height
full_drop = true;
if (bounce_fix == true)
{
- downVelocity = (m_verticalVelocity<0.f?-m_verticalVelocity:0.f) * dt;
+ downVelocity = (m_verticalVelocity < 0.f ? -m_verticalVelocity : 0.f) * dt;
if (downVelocity > m_fallSpeed && (m_wasOnGround || !m_wasJumping))
{
- m_targetPosition += step_drop; //undo previous target change
+ m_targetPosition += step_drop; //undo previous target change
downVelocity = m_fallSpeed;
step_drop = m_up * (m_currentStepOffset + downVelocity);
m_targetPosition -= step_drop;
@@ -605,30 +607,22 @@ void btKinematicCharacterController::stepDown ( btCollisionWorld* collisionWorld
}
}
-
-
-void btKinematicCharacterController::setWalkDirection
-(
-const btVector3& walkDirection
-)
+void btKinematicCharacterController::setWalkDirection(
+ const btVector3& walkDirection)
{
m_useWalkDirection = true;
m_walkDirection = walkDirection;
m_normalizedDirection = getNormalizedVector(m_walkDirection);
}
-
-
-void btKinematicCharacterController::setVelocityForTimeInterval
-(
-const btVector3& velocity,
-btScalar timeInterval
-)
+void btKinematicCharacterController::setVelocityForTimeInterval(
+ const btVector3& velocity,
+ btScalar timeInterval)
{
-// printf("setVelocity!\n");
-// printf(" interval: %f\n", timeInterval);
-// printf(" velocity: (%f, %f, %f)\n",
-// velocity.x(), velocity.y(), velocity.z());
+ // printf("setVelocity!\n");
+ // printf(" interval: %f\n", timeInterval);
+ // printf(" velocity: (%f, %f, %f)\n",
+ // velocity.x(), velocity.y(), velocity.z());
m_useWalkDirection = false;
m_walkDirection = velocity;
@@ -661,7 +655,7 @@ void btKinematicCharacterController::setLinearVelocity(const btVector3& velocity
btVector3 upComponent = m_up * (btSin(SIMD_HALF_PI - btAcos(c)) * m_walkDirection.length());
m_walkDirection -= upComponent;
m_verticalVelocity = (c < 0.0f ? -1 : 1) * upComponent.length();
-
+
if (c > 0.0f)
{
m_wasJumping = true;
@@ -678,46 +672,45 @@ btVector3 btKinematicCharacterController::getLinearVelocity() const
return m_walkDirection + (m_verticalVelocity * m_up);
}
-void btKinematicCharacterController::reset ( btCollisionWorld* collisionWorld )
+void btKinematicCharacterController::reset(btCollisionWorld* collisionWorld)
{
- m_verticalVelocity = 0.0;
- m_verticalOffset = 0.0;
- m_wasOnGround = false;
- m_wasJumping = false;
- m_walkDirection.setValue(0,0,0);
- m_velocityTimeInterval = 0.0;
+ m_verticalVelocity = 0.0;
+ m_verticalOffset = 0.0;
+ m_wasOnGround = false;
+ m_wasJumping = false;
+ m_walkDirection.setValue(0, 0, 0);
+ m_velocityTimeInterval = 0.0;
- //clear pair cache
- btHashedOverlappingPairCache *cache = m_ghostObject->getOverlappingPairCache();
- while (cache->getOverlappingPairArray().size() > 0)
- {
- cache->removeOverlappingPair(cache->getOverlappingPairArray()[0].m_pProxy0, cache->getOverlappingPairArray()[0].m_pProxy1, collisionWorld->getDispatcher());
- }
+ //clear pair cache
+ btHashedOverlappingPairCache* cache = m_ghostObject->getOverlappingPairCache();
+ while (cache->getOverlappingPairArray().size() > 0)
+ {
+ cache->removeOverlappingPair(cache->getOverlappingPairArray()[0].m_pProxy0, cache->getOverlappingPairArray()[0].m_pProxy1, collisionWorld->getDispatcher());
+ }
}
-void btKinematicCharacterController::warp (const btVector3& origin)
+void btKinematicCharacterController::warp(const btVector3& origin)
{
btTransform xform;
xform.setIdentity();
- xform.setOrigin (origin);
- m_ghostObject->setWorldTransform (xform);
+ xform.setOrigin(origin);
+ m_ghostObject->setWorldTransform(xform);
}
-
-void btKinematicCharacterController::preStep ( btCollisionWorld* collisionWorld)
+void btKinematicCharacterController::preStep(btCollisionWorld* collisionWorld)
{
m_currentPosition = m_ghostObject->getWorldTransform().getOrigin();
m_targetPosition = m_currentPosition;
m_currentOrientation = m_ghostObject->getWorldTransform().getRotation();
m_targetOrientation = m_currentOrientation;
-// printf("m_targetPosition=%f,%f,%f\n",m_targetPosition[0],m_targetPosition[1],m_targetPosition[2]);
+ // printf("m_targetPosition=%f,%f,%f\n",m_targetPosition[0],m_targetPosition[1],m_targetPosition[2]);
}
-void btKinematicCharacterController::playerStep ( btCollisionWorld* collisionWorld, btScalar dt)
+void btKinematicCharacterController::playerStep(btCollisionWorld* collisionWorld, btScalar dt)
{
-// printf("playerStep(): ");
-// printf(" dt = %f", dt);
+ // printf("playerStep(): ");
+ // printf(" dt = %f", dt);
if (m_AngVel.length2() > 0.0f)
{
@@ -744,16 +737,17 @@ void btKinematicCharacterController::playerStep ( btCollisionWorld* collisionWo
}
// quick check...
- if (!m_useWalkDirection && (m_velocityTimeInterval <= 0.0)) {
-// printf("\n");
- return; // no motion
+ if (!m_useWalkDirection && (m_velocityTimeInterval <= 0.0 || m_walkDirection.fuzzyZero()))
+ {
+ // printf("\n");
+ return; // no motion
}
m_wasOnGround = onGround();
//btVector3 lvel = m_walkDirection;
//btScalar c = 0.0f;
-
+
if (m_walkDirection.length2() > 0)
{
// apply damping
@@ -761,7 +755,7 @@ void btKinematicCharacterController::playerStep ( btCollisionWorld* collisionWo
}
m_verticalVelocity *= btPow(btScalar(1) - m_linearDamping, dt);
-
+
// Update fall velocity.
m_verticalVelocity -= m_gravity * dt;
if (m_verticalVelocity > 0.0 && m_verticalVelocity > m_jumpSpeed)
@@ -777,12 +771,12 @@ void btKinematicCharacterController::playerStep ( btCollisionWorld* collisionWo
btTransform xform;
xform = m_ghostObject->getWorldTransform();
-// printf("walkDirection(%f,%f,%f)\n",walkDirection[0],walkDirection[1],walkDirection[2]);
-// printf("walkSpeed=%f\n",walkSpeed);
+ // printf("walkDirection(%f,%f,%f)\n",walkDirection[0],walkDirection[1],walkDirection[2]);
+ // printf("walkSpeed=%f\n",walkSpeed);
stepUp(collisionWorld);
//todo: Experimenting with behavior of controller when it hits a ceiling..
- //bool hitUp = stepUp (collisionWorld);
+ //bool hitUp = stepUp (collisionWorld);
//if (hitUp)
//{
// m_verticalVelocity -= m_gravity * dt;
@@ -799,9 +793,12 @@ void btKinematicCharacterController::playerStep ( btCollisionWorld* collisionWo
// xform = m_ghostObject->getWorldTransform();
//}
- if (m_useWalkDirection) {
- stepForwardAndStrafe (collisionWorld, m_walkDirection);
- } else {
+ if (m_useWalkDirection)
+ {
+ stepForwardAndStrafe(collisionWorld, m_walkDirection);
+ }
+ else
+ {
//printf(" time: %f", m_velocityTimeInterval);
// still have some time left for moving!
btScalar dtMoving =
@@ -816,7 +813,7 @@ void btKinematicCharacterController::playerStep ( btCollisionWorld* collisionWo
// okay, step
stepForwardAndStrafe(collisionWorld, move);
}
- stepDown (collisionWorld, dt);
+ stepDown(collisionWorld, dt);
//todo: Experimenting with max jump height
//if (m_wasJumping)
@@ -827,7 +824,7 @@ void btKinematicCharacterController::playerStep ( btCollisionWorld* collisionWo
// // substract the overshoot
// m_currentPosition[m_upAxis] -= ds - m_maxJumpHeight;
- // // max height was reached, so potential energy is at max
+ // // max height was reached, so potential energy is at max
// // and kinematic energy is 0, thus velocity is 0.
// if (m_verticalVelocity > 0.0)
// m_verticalVelocity = 0.0;
@@ -835,8 +832,8 @@ void btKinematicCharacterController::playerStep ( btCollisionWorld* collisionWo
//}
// printf("\n");
- xform.setOrigin (m_currentPosition);
- m_ghostObject->setWorldTransform (xform);
+ xform.setOrigin(m_currentPosition);
+ m_ghostObject->setWorldTransform(xform);
int numPenetrationLoops = 0;
m_touchingContact = false;
@@ -852,23 +849,23 @@ void btKinematicCharacterController::playerStep ( btCollisionWorld* collisionWo
}
}
-void btKinematicCharacterController::setFallSpeed (btScalar fallSpeed)
+void btKinematicCharacterController::setFallSpeed(btScalar fallSpeed)
{
m_fallSpeed = fallSpeed;
}
-void btKinematicCharacterController::setJumpSpeed (btScalar jumpSpeed)
+void btKinematicCharacterController::setJumpSpeed(btScalar jumpSpeed)
{
m_jumpSpeed = jumpSpeed;
m_SetjumpSpeed = m_jumpSpeed;
}
-void btKinematicCharacterController::setMaxJumpHeight (btScalar maxJumpHeight)
+void btKinematicCharacterController::setMaxJumpHeight(btScalar maxJumpHeight)
{
m_maxJumpHeight = maxJumpHeight;
}
-bool btKinematicCharacterController::canJump () const
+bool btKinematicCharacterController::canJump() const
{
return onGround();
}
@@ -927,20 +924,20 @@ btScalar btKinematicCharacterController::getMaxPenetrationDepth() const
return m_maxPenetrationDepth;
}
-bool btKinematicCharacterController::onGround () const
+bool btKinematicCharacterController::onGround() const
{
return (fabs(m_verticalVelocity) < SIMD_EPSILON) && (fabs(m_verticalOffset) < SIMD_EPSILON);
}
-void btKinematicCharacterController::setStepHeight(btScalar h)
+void btKinematicCharacterController::setStepHeight(btScalar h)
{
m_stepHeight = h;
}
btVector3* btKinematicCharacterController::getUpAxisDirections()
{
- static btVector3 sUpAxisDirection[3] = { btVector3(1.0f, 0.0f, 0.0f), btVector3(0.0f, 1.0f, 0.0f), btVector3(0.0f, 0.0f, 1.0f) };
-
+ static btVector3 sUpAxisDirection[3] = {btVector3(1.0f, 0.0f, 0.0f), btVector3(0.0f, 1.0f, 0.0f), btVector3(0.0f, 0.0f, 1.0f)};
+
return sUpAxisDirection;
}
@@ -997,4 +994,3 @@ btQuaternion btKinematicCharacterController::getRotation(btVector3& v0, btVector
return shortestArcQuatNormalize2(v0, v1);
}
-
diff --git a/thirdparty/bullet/BulletDynamics/Character/btKinematicCharacterController.h b/thirdparty/bullet/BulletDynamics/Character/btKinematicCharacterController.h
index 00c59c0248..ff34fc871a 100644
--- a/thirdparty/bullet/BulletDynamics/Character/btKinematicCharacterController.h
+++ b/thirdparty/bullet/BulletDynamics/Character/btKinematicCharacterController.h
@@ -13,7 +13,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#ifndef BT_KINEMATIC_CHARACTER_CONTROLLER_H
#define BT_KINEMATIC_CHARACTER_CONTROLLER_H
@@ -23,7 +22,6 @@ subject to the following restrictions:
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
-
class btCollisionShape;
class btConvexShape;
class btRigidBody;
@@ -34,15 +32,15 @@ class btPairCachingGhostObject;
///btKinematicCharacterController is an object that supports a sliding motion in a world.
///It uses a ghost object and convex sweep test to test for upcoming collisions. This is combined with discrete collision detection to recover from penetrations.
///Interaction between btKinematicCharacterController and dynamic rigid bodies needs to be explicity implemented by the user.
-ATTRIBUTE_ALIGNED16(class) btKinematicCharacterController : public btCharacterControllerInterface
+ATTRIBUTE_ALIGNED16(class)
+btKinematicCharacterController : public btCharacterControllerInterface
{
protected:
-
btScalar m_halfHeight;
-
+
btPairCachingGhostObject* m_ghostObject;
- btConvexShape* m_convexShape;//is also in m_ghostObject, but it needs to be convex, so we store it here to avoid upcast
-
+ btConvexShape* m_convexShape; //is also in m_ghostObject, but it needs to be convex, so we store it here to avoid upcast
+
btScalar m_maxPenetrationDepth;
btScalar m_verticalVelocity;
btScalar m_verticalOffset;
@@ -50,33 +48,33 @@ protected:
btScalar m_jumpSpeed;
btScalar m_SetjumpSpeed;
btScalar m_maxJumpHeight;
- btScalar m_maxSlopeRadians; // Slope angle that is set (used for returning the exact value)
- btScalar m_maxSlopeCosine; // Cosine equivalent of m_maxSlopeRadians (calculated once when set, for optimization)
+ btScalar m_maxSlopeRadians; // Slope angle that is set (used for returning the exact value)
+ btScalar m_maxSlopeCosine; // Cosine equivalent of m_maxSlopeRadians (calculated once when set, for optimization)
btScalar m_gravity;
btScalar m_turnAngle;
-
+
btScalar m_stepHeight;
- btScalar m_addedMargin;//@todo: remove this and fix the code
+ btScalar m_addedMargin; //@todo: remove this and fix the code
///this is the desired walk direction, set by the user
- btVector3 m_walkDirection;
- btVector3 m_normalizedDirection;
- btVector3 m_AngVel;
+ btVector3 m_walkDirection;
+ btVector3 m_normalizedDirection;
+ btVector3 m_AngVel;
- btVector3 m_jumpPosition;
+ btVector3 m_jumpPosition;
//some internal variables
btVector3 m_currentPosition;
- btScalar m_currentStepOffset;
+ btScalar m_currentStepOffset;
btVector3 m_targetPosition;
btQuaternion m_currentOrientation;
btQuaternion m_targetOrientation;
///keep track of the contact manifolds
- btManifoldArray m_manifoldArray;
+ btManifoldArray m_manifoldArray;
bool m_touchingContact;
btVector3 m_touchingNormal;
@@ -84,52 +82,50 @@ protected:
btScalar m_linearDamping;
btScalar m_angularDamping;
- bool m_wasOnGround;
- bool m_wasJumping;
- bool m_useGhostObjectSweepTest;
- bool m_useWalkDirection;
- btScalar m_velocityTimeInterval;
+ bool m_wasOnGround;
+ bool m_wasJumping;
+ bool m_useGhostObjectSweepTest;
+ bool m_useWalkDirection;
+ btScalar m_velocityTimeInterval;
btVector3 m_up;
btVector3 m_jumpAxis;
static btVector3* getUpAxisDirections();
- bool m_interpolateUp;
- bool full_drop;
- bool bounce_fix;
+ bool m_interpolateUp;
+ bool full_drop;
+ bool bounce_fix;
- btVector3 computeReflectionDirection (const btVector3& direction, const btVector3& normal);
- btVector3 parallelComponent (const btVector3& direction, const btVector3& normal);
- btVector3 perpindicularComponent (const btVector3& direction, const btVector3& normal);
+ btVector3 computeReflectionDirection(const btVector3& direction, const btVector3& normal);
+ btVector3 parallelComponent(const btVector3& direction, const btVector3& normal);
+ btVector3 perpindicularComponent(const btVector3& direction, const btVector3& normal);
- bool recoverFromPenetration ( btCollisionWorld* collisionWorld);
- void stepUp (btCollisionWorld* collisionWorld);
- void updateTargetPositionBasedOnCollision (const btVector3& hit_normal, btScalar tangentMag = btScalar(0.0), btScalar normalMag = btScalar(1.0));
- void stepForwardAndStrafe (btCollisionWorld* collisionWorld, const btVector3& walkMove);
- void stepDown (btCollisionWorld* collisionWorld, btScalar dt);
+ bool recoverFromPenetration(btCollisionWorld * collisionWorld);
+ void stepUp(btCollisionWorld * collisionWorld);
+ void updateTargetPositionBasedOnCollision(const btVector3& hit_normal, btScalar tangentMag = btScalar(0.0), btScalar normalMag = btScalar(1.0));
+ void stepForwardAndStrafe(btCollisionWorld * collisionWorld, const btVector3& walkMove);
+ void stepDown(btCollisionWorld * collisionWorld, btScalar dt);
virtual bool needsCollision(const btCollisionObject* body0, const btCollisionObject* body1);
void setUpVector(const btVector3& up);
- btQuaternion getRotation(btVector3& v0, btVector3& v1) const;
+ btQuaternion getRotation(btVector3 & v0, btVector3 & v1) const;
public:
-
BT_DECLARE_ALIGNED_ALLOCATOR();
- btKinematicCharacterController (btPairCachingGhostObject* ghostObject,btConvexShape* convexShape,btScalar stepHeight, const btVector3& up = btVector3(1.0,0.0,0.0));
- ~btKinematicCharacterController ();
-
+ btKinematicCharacterController(btPairCachingGhostObject * ghostObject, btConvexShape * convexShape, btScalar stepHeight, const btVector3& up = btVector3(1.0, 0.0, 0.0));
+ ~btKinematicCharacterController();
///btActionInterface interface
- virtual void updateAction( btCollisionWorld* collisionWorld,btScalar deltaTime)
+ virtual void updateAction(btCollisionWorld * collisionWorld, btScalar deltaTime)
{
- preStep ( collisionWorld);
- playerStep (collisionWorld, deltaTime);
+ preStep(collisionWorld);
+ playerStep(collisionWorld, deltaTime);
}
-
+
///btActionInterface interface
- void debugDraw(btIDebugDraw* debugDrawer);
+ void debugDraw(btIDebugDraw * debugDrawer);
void setUp(const btVector3& up);
@@ -140,7 +136,7 @@ public:
/// increment the position each simulation iteration, regardless
/// of dt.
/// This call will reset any velocity set by setVelocityForTimeInterval().
- virtual void setWalkDirection(const btVector3& walkDirection);
+ virtual void setWalkDirection(const btVector3& walkDirection);
/// Caller provides a velocity with which the character should move for
/// the given time period. After the time period, velocity is reset
@@ -148,7 +144,7 @@ public:
/// This call will reset any walk direction set by setWalkDirection().
/// Negative time intervals will result in no motion.
virtual void setVelocityForTimeInterval(const btVector3& velocity,
- btScalar timeInterval);
+ btScalar timeInterval);
virtual void setAngularVelocity(const btVector3& velocity);
virtual const btVector3& getAngularVelocity() const;
@@ -157,24 +153,24 @@ public:
virtual btVector3 getLinearVelocity() const;
void setLinearDamping(btScalar d) { m_linearDamping = btClamped(d, (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); }
- btScalar getLinearDamping() const { return m_linearDamping; }
+ btScalar getLinearDamping() const { return m_linearDamping; }
void setAngularDamping(btScalar d) { m_angularDamping = btClamped(d, (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); }
- btScalar getAngularDamping() const { return m_angularDamping; }
+ btScalar getAngularDamping() const { return m_angularDamping; }
- void reset ( btCollisionWorld* collisionWorld );
- void warp (const btVector3& origin);
+ void reset(btCollisionWorld * collisionWorld);
+ void warp(const btVector3& origin);
- void preStep ( btCollisionWorld* collisionWorld);
- void playerStep ( btCollisionWorld* collisionWorld, btScalar dt);
+ void preStep(btCollisionWorld * collisionWorld);
+ void playerStep(btCollisionWorld * collisionWorld, btScalar dt);
void setStepHeight(btScalar h);
btScalar getStepHeight() const { return m_stepHeight; }
- void setFallSpeed (btScalar fallSpeed);
+ void setFallSpeed(btScalar fallSpeed);
btScalar getFallSpeed() const { return m_fallSpeed; }
- void setJumpSpeed (btScalar jumpSpeed);
+ void setJumpSpeed(btScalar jumpSpeed);
btScalar getJumpSpeed() const { return m_jumpSpeed; }
- void setMaxJumpHeight (btScalar maxJumpHeight);
- bool canJump () const;
+ void setMaxJumpHeight(btScalar maxJumpHeight);
+ bool canJump() const;
void jump(const btVector3& v = btVector3(0, 0, 0));
@@ -192,13 +188,13 @@ public:
btScalar getMaxPenetrationDepth() const;
btPairCachingGhostObject* getGhostObject();
- void setUseGhostSweepTest(bool useGhostObjectSweepTest)
+ void setUseGhostSweepTest(bool useGhostObjectSweepTest)
{
m_useGhostObjectSweepTest = useGhostObjectSweepTest;
}
- bool onGround () const;
- void setUpInterpolate (bool value);
+ bool onGround() const;
+ void setUpInterpolate(bool value);
};
-#endif // BT_KINEMATIC_CHARACTER_CONTROLLER_H
+#endif // BT_KINEMATIC_CHARACTER_CONTROLLER_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.cpp
index c82ba87f9f..b51dfaad3c 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.cpp
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.cpp
@@ -13,7 +13,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#include "btBatchedConstraints.h"
#include "LinearMath/btIDebugDraw.h"
@@ -21,606 +20,573 @@ subject to the following restrictions:
#include "LinearMath/btStackAlloc.h"
#include "LinearMath/btQuickprof.h"
-#include <string.h> //for memset
+#include <string.h> //for memset
const int kNoMerge = -1;
bool btBatchedConstraints::s_debugDrawBatches = false;
-
struct btBatchedConstraintInfo
{
- int constraintIndex;
- int numConstraintRows;
- int bodyIds[2];
+ int constraintIndex;
+ int numConstraintRows;
+ int bodyIds[2];
};
-
struct btBatchInfo
{
- int numConstraints;
- int mergeIndex;
+ int numConstraints;
+ int mergeIndex;
- btBatchInfo() : numConstraints(0), mergeIndex(kNoMerge) {}
+ btBatchInfo() : numConstraints(0), mergeIndex(kNoMerge) {}
};
-
bool btBatchedConstraints::validate(btConstraintArray* constraints, const btAlignedObjectArray<btSolverBody>& bodies) const
{
- //
- // validate: for debugging only. Verify coloring of bodies, that no body is touched by more than one batch in any given phase
- //
- int errors = 0;
- const int kUnassignedBatch = -1;
-
- btAlignedObjectArray<int> bodyBatchId;
- for (int iPhase = 0; iPhase < m_phases.size(); ++iPhase)
- {
- bodyBatchId.resizeNoInitialize(0);
- bodyBatchId.resize( bodies.size(), kUnassignedBatch );
- const Range& phase = m_phases[iPhase];
- for (int iBatch = phase.begin; iBatch < phase.end; ++iBatch)
- {
- const Range& batch = m_batches[iBatch];
- for (int iiCons = batch.begin; iiCons < batch.end; ++iiCons)
- {
- int iCons = m_constraintIndices[iiCons];
- const btSolverConstraint& cons = constraints->at(iCons);
- const btSolverBody& bodyA = bodies[cons.m_solverBodyIdA];
- const btSolverBody& bodyB = bodies[cons.m_solverBodyIdB];
- if (! bodyA.internalGetInvMass().isZero())
- {
- int thisBodyBatchId = bodyBatchId[cons.m_solverBodyIdA];
- if (thisBodyBatchId == kUnassignedBatch)
- {
- bodyBatchId[cons.m_solverBodyIdA] = iBatch;
- }
- else if (thisBodyBatchId != iBatch)
- {
- btAssert( !"dynamic body is used in 2 different batches in the same phase" );
- errors++;
- }
- }
- if (! bodyB.internalGetInvMass().isZero())
- {
- int thisBodyBatchId = bodyBatchId[cons.m_solverBodyIdB];
- if (thisBodyBatchId == kUnassignedBatch)
- {
- bodyBatchId[cons.m_solverBodyIdB] = iBatch;
- }
- else if (thisBodyBatchId != iBatch)
- {
- btAssert( !"dynamic body is used in 2 different batches in the same phase" );
- errors++;
- }
- }
- }
- }
- }
- return errors == 0;
+ //
+ // validate: for debugging only. Verify coloring of bodies, that no body is touched by more than one batch in any given phase
+ //
+ int errors = 0;
+ const int kUnassignedBatch = -1;
+
+ btAlignedObjectArray<int> bodyBatchId;
+ for (int iPhase = 0; iPhase < m_phases.size(); ++iPhase)
+ {
+ bodyBatchId.resizeNoInitialize(0);
+ bodyBatchId.resize(bodies.size(), kUnassignedBatch);
+ const Range& phase = m_phases[iPhase];
+ for (int iBatch = phase.begin; iBatch < phase.end; ++iBatch)
+ {
+ const Range& batch = m_batches[iBatch];
+ for (int iiCons = batch.begin; iiCons < batch.end; ++iiCons)
+ {
+ int iCons = m_constraintIndices[iiCons];
+ const btSolverConstraint& cons = constraints->at(iCons);
+ const btSolverBody& bodyA = bodies[cons.m_solverBodyIdA];
+ const btSolverBody& bodyB = bodies[cons.m_solverBodyIdB];
+ if (!bodyA.internalGetInvMass().isZero())
+ {
+ int thisBodyBatchId = bodyBatchId[cons.m_solverBodyIdA];
+ if (thisBodyBatchId == kUnassignedBatch)
+ {
+ bodyBatchId[cons.m_solverBodyIdA] = iBatch;
+ }
+ else if (thisBodyBatchId != iBatch)
+ {
+ btAssert(!"dynamic body is used in 2 different batches in the same phase");
+ errors++;
+ }
+ }
+ if (!bodyB.internalGetInvMass().isZero())
+ {
+ int thisBodyBatchId = bodyBatchId[cons.m_solverBodyIdB];
+ if (thisBodyBatchId == kUnassignedBatch)
+ {
+ bodyBatchId[cons.m_solverBodyIdB] = iBatch;
+ }
+ else if (thisBodyBatchId != iBatch)
+ {
+ btAssert(!"dynamic body is used in 2 different batches in the same phase");
+ errors++;
+ }
+ }
+ }
+ }
+ }
+ return errors == 0;
}
-
-static void debugDrawSingleBatch( const btBatchedConstraints* bc,
- btConstraintArray* constraints,
- const btAlignedObjectArray<btSolverBody>& bodies,
- int iBatch,
- const btVector3& color,
- const btVector3& offset
- )
+static void debugDrawSingleBatch(const btBatchedConstraints* bc,
+ btConstraintArray* constraints,
+ const btAlignedObjectArray<btSolverBody>& bodies,
+ int iBatch,
+ const btVector3& color,
+ const btVector3& offset)
{
- if (bc && bc->m_debugDrawer && iBatch < bc->m_batches.size())
- {
- const btBatchedConstraints::Range& b = bc->m_batches[iBatch];
- for (int iiCon = b.begin; iiCon < b.end; ++iiCon)
- {
- int iCon = bc->m_constraintIndices[iiCon];
- const btSolverConstraint& con = constraints->at(iCon);
- int iBody0 = con.m_solverBodyIdA;
- int iBody1 = con.m_solverBodyIdB;
- btVector3 pos0 = bodies[iBody0].getWorldTransform().getOrigin() + offset;
- btVector3 pos1 = bodies[iBody1].getWorldTransform().getOrigin() + offset;
- bc->m_debugDrawer->drawLine(pos0, pos1, color);
- }
- }
+ if (bc && bc->m_debugDrawer && iBatch < bc->m_batches.size())
+ {
+ const btBatchedConstraints::Range& b = bc->m_batches[iBatch];
+ for (int iiCon = b.begin; iiCon < b.end; ++iiCon)
+ {
+ int iCon = bc->m_constraintIndices[iiCon];
+ const btSolverConstraint& con = constraints->at(iCon);
+ int iBody0 = con.m_solverBodyIdA;
+ int iBody1 = con.m_solverBodyIdB;
+ btVector3 pos0 = bodies[iBody0].getWorldTransform().getOrigin() + offset;
+ btVector3 pos1 = bodies[iBody1].getWorldTransform().getOrigin() + offset;
+ bc->m_debugDrawer->drawLine(pos0, pos1, color);
+ }
+ }
}
-
-static void debugDrawPhase( const btBatchedConstraints* bc,
- btConstraintArray* constraints,
- const btAlignedObjectArray<btSolverBody>& bodies,
- int iPhase,
- const btVector3& color0,
- const btVector3& color1,
- const btVector3& offset
- )
+static void debugDrawPhase(const btBatchedConstraints* bc,
+ btConstraintArray* constraints,
+ const btAlignedObjectArray<btSolverBody>& bodies,
+ int iPhase,
+ const btVector3& color0,
+ const btVector3& color1,
+ const btVector3& offset)
{
- BT_PROFILE( "debugDrawPhase" );
- if ( bc && bc->m_debugDrawer && iPhase < bc->m_phases.size() )
- {
- const btBatchedConstraints::Range& phase = bc->m_phases[iPhase];
- for (int iBatch = phase.begin; iBatch < phase.end; ++iBatch)
- {
- float tt = float(iBatch - phase.begin) / float(btMax(1, phase.end - phase.begin - 1));
- btVector3 col = lerp(color0, color1, tt);
- debugDrawSingleBatch(bc, constraints, bodies, iBatch, col, offset);
- }
- }
+ BT_PROFILE("debugDrawPhase");
+ if (bc && bc->m_debugDrawer && iPhase < bc->m_phases.size())
+ {
+ const btBatchedConstraints::Range& phase = bc->m_phases[iPhase];
+ for (int iBatch = phase.begin; iBatch < phase.end; ++iBatch)
+ {
+ float tt = float(iBatch - phase.begin) / float(btMax(1, phase.end - phase.begin - 1));
+ btVector3 col = lerp(color0, color1, tt);
+ debugDrawSingleBatch(bc, constraints, bodies, iBatch, col, offset);
+ }
+ }
}
-
-static void debugDrawAllBatches( const btBatchedConstraints* bc,
- btConstraintArray* constraints,
- const btAlignedObjectArray<btSolverBody>& bodies
- )
+static void debugDrawAllBatches(const btBatchedConstraints* bc,
+ btConstraintArray* constraints,
+ const btAlignedObjectArray<btSolverBody>& bodies)
{
- BT_PROFILE( "debugDrawAllBatches" );
- if ( bc && bc->m_debugDrawer && bc->m_phases.size() > 0 )
- {
- btVector3 bboxMin(BT_LARGE_FLOAT, BT_LARGE_FLOAT, BT_LARGE_FLOAT);
- btVector3 bboxMax = -bboxMin;
- for (int iBody = 0; iBody < bodies.size(); ++iBody)
- {
- const btVector3& pos = bodies[iBody].getWorldTransform().getOrigin();
- bboxMin.setMin(pos);
- bboxMax.setMax(pos);
- }
- btVector3 bboxExtent = bboxMax - bboxMin;
- btVector3 offsetBase = btVector3( 0, bboxExtent.y()*1.1f, 0 );
- btVector3 offsetStep = btVector3( 0, 0, bboxExtent.z()*1.1f );
- int numPhases = bc->m_phases.size();
- for (int iPhase = 0; iPhase < numPhases; ++iPhase)
- {
- float b = float(iPhase)/float(numPhases-1);
- btVector3 color0 = btVector3(1,0,b);
- btVector3 color1 = btVector3(0,1,b);
- btVector3 offset = offsetBase + offsetStep*(float(iPhase) - float(numPhases-1)*0.5);
- debugDrawPhase(bc, constraints, bodies, iPhase, color0, color1, offset);
- }
- }
+ BT_PROFILE("debugDrawAllBatches");
+ if (bc && bc->m_debugDrawer && bc->m_phases.size() > 0)
+ {
+ btVector3 bboxMin(BT_LARGE_FLOAT, BT_LARGE_FLOAT, BT_LARGE_FLOAT);
+ btVector3 bboxMax = -bboxMin;
+ for (int iBody = 0; iBody < bodies.size(); ++iBody)
+ {
+ const btVector3& pos = bodies[iBody].getWorldTransform().getOrigin();
+ bboxMin.setMin(pos);
+ bboxMax.setMax(pos);
+ }
+ btVector3 bboxExtent = bboxMax - bboxMin;
+ btVector3 offsetBase = btVector3(0, bboxExtent.y() * 1.1f, 0);
+ btVector3 offsetStep = btVector3(0, 0, bboxExtent.z() * 1.1f);
+ int numPhases = bc->m_phases.size();
+ for (int iPhase = 0; iPhase < numPhases; ++iPhase)
+ {
+ float b = float(iPhase) / float(numPhases - 1);
+ btVector3 color0 = btVector3(1, 0, b);
+ btVector3 color1 = btVector3(0, 1, b);
+ btVector3 offset = offsetBase + offsetStep * (float(iPhase) - float(numPhases - 1) * 0.5);
+ debugDrawPhase(bc, constraints, bodies, iPhase, color0, color1, offset);
+ }
+ }
}
-
static void initBatchedBodyDynamicFlags(btAlignedObjectArray<bool>* outBodyDynamicFlags, const btAlignedObjectArray<btSolverBody>& bodies)
{
- BT_PROFILE("initBatchedBodyDynamicFlags");
- btAlignedObjectArray<bool>& bodyDynamicFlags = *outBodyDynamicFlags;
- bodyDynamicFlags.resizeNoInitialize(bodies.size());
- for (int i = 0; i < bodies.size(); ++i)
- {
- const btSolverBody& body = bodies[ i ];
- bodyDynamicFlags[i] = ( body.internalGetInvMass().x() > btScalar( 0 ) );
- }
+ BT_PROFILE("initBatchedBodyDynamicFlags");
+ btAlignedObjectArray<bool>& bodyDynamicFlags = *outBodyDynamicFlags;
+ bodyDynamicFlags.resizeNoInitialize(bodies.size());
+ for (int i = 0; i < bodies.size(); ++i)
+ {
+ const btSolverBody& body = bodies[i];
+ bodyDynamicFlags[i] = (body.internalGetInvMass().x() > btScalar(0));
+ }
}
-
static int runLengthEncodeConstraintInfo(btBatchedConstraintInfo* outConInfos, int numConstraints)
{
- BT_PROFILE("runLengthEncodeConstraintInfo");
- // detect and run-length encode constraint rows that repeat the same bodies
- int iDest = 0;
- int iSrc = 0;
- while (iSrc < numConstraints)
- {
- const btBatchedConstraintInfo& srcConInfo = outConInfos[iSrc];
- btBatchedConstraintInfo& conInfo = outConInfos[iDest];
- conInfo.constraintIndex = iSrc;
- conInfo.bodyIds[0] = srcConInfo.bodyIds[0];
- conInfo.bodyIds[1] = srcConInfo.bodyIds[1];
- while (iSrc < numConstraints && outConInfos[iSrc].bodyIds[0] == srcConInfo.bodyIds[0] && outConInfos[iSrc].bodyIds[1] == srcConInfo.bodyIds[1])
- {
- ++iSrc;
- }
- conInfo.numConstraintRows = iSrc - conInfo.constraintIndex;
- ++iDest;
- }
- return iDest;
+ BT_PROFILE("runLengthEncodeConstraintInfo");
+ // detect and run-length encode constraint rows that repeat the same bodies
+ int iDest = 0;
+ int iSrc = 0;
+ while (iSrc < numConstraints)
+ {
+ const btBatchedConstraintInfo& srcConInfo = outConInfos[iSrc];
+ btBatchedConstraintInfo& conInfo = outConInfos[iDest];
+ conInfo.constraintIndex = iSrc;
+ conInfo.bodyIds[0] = srcConInfo.bodyIds[0];
+ conInfo.bodyIds[1] = srcConInfo.bodyIds[1];
+ while (iSrc < numConstraints && outConInfos[iSrc].bodyIds[0] == srcConInfo.bodyIds[0] && outConInfos[iSrc].bodyIds[1] == srcConInfo.bodyIds[1])
+ {
+ ++iSrc;
+ }
+ conInfo.numConstraintRows = iSrc - conInfo.constraintIndex;
+ ++iDest;
+ }
+ return iDest;
}
-
struct ReadSolverConstraintsLoop : public btIParallelForBody
{
- btBatchedConstraintInfo* m_outConInfos;
- btConstraintArray* m_constraints;
-
- ReadSolverConstraintsLoop( btBatchedConstraintInfo* outConInfos, btConstraintArray* constraints )
- {
- m_outConInfos = outConInfos;
- m_constraints = constraints;
- }
- void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE
- {
- for (int i = iBegin; i < iEnd; ++i)
- {
- btBatchedConstraintInfo& conInfo = m_outConInfos[i];
- const btSolverConstraint& con = m_constraints->at( i );
- conInfo.bodyIds[0] = con.m_solverBodyIdA;
- conInfo.bodyIds[1] = con.m_solverBodyIdB;
- conInfo.constraintIndex = i;
- conInfo.numConstraintRows = 1;
- }
- }
+ btBatchedConstraintInfo* m_outConInfos;
+ btConstraintArray* m_constraints;
+
+ ReadSolverConstraintsLoop(btBatchedConstraintInfo* outConInfos, btConstraintArray* constraints)
+ {
+ m_outConInfos = outConInfos;
+ m_constraints = constraints;
+ }
+ void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
+ {
+ for (int i = iBegin; i < iEnd; ++i)
+ {
+ btBatchedConstraintInfo& conInfo = m_outConInfos[i];
+ const btSolverConstraint& con = m_constraints->at(i);
+ conInfo.bodyIds[0] = con.m_solverBodyIdA;
+ conInfo.bodyIds[1] = con.m_solverBodyIdB;
+ conInfo.constraintIndex = i;
+ conInfo.numConstraintRows = 1;
+ }
+ }
};
-
static int initBatchedConstraintInfo(btBatchedConstraintInfo* outConInfos, btConstraintArray* constraints)
{
- BT_PROFILE("initBatchedConstraintInfo");
- int numConstraints = constraints->size();
- bool inParallel = true;
- if (inParallel)
- {
- ReadSolverConstraintsLoop loop(outConInfos, constraints);
- int grainSize = 1200;
- btParallelFor(0, numConstraints, grainSize, loop);
- }
- else
- {
- for (int i = 0; i < numConstraints; ++i)
- {
- btBatchedConstraintInfo& conInfo = outConInfos[i];
- const btSolverConstraint& con = constraints->at( i );
- conInfo.bodyIds[0] = con.m_solverBodyIdA;
- conInfo.bodyIds[1] = con.m_solverBodyIdB;
- conInfo.constraintIndex = i;
- conInfo.numConstraintRows = 1;
- }
- }
- bool useRunLengthEncoding = true;
- if (useRunLengthEncoding)
- {
- numConstraints = runLengthEncodeConstraintInfo(outConInfos, numConstraints);
- }
- return numConstraints;
+ BT_PROFILE("initBatchedConstraintInfo");
+ int numConstraints = constraints->size();
+ bool inParallel = true;
+ if (inParallel)
+ {
+ ReadSolverConstraintsLoop loop(outConInfos, constraints);
+ int grainSize = 1200;
+ btParallelFor(0, numConstraints, grainSize, loop);
+ }
+ else
+ {
+ for (int i = 0; i < numConstraints; ++i)
+ {
+ btBatchedConstraintInfo& conInfo = outConInfos[i];
+ const btSolverConstraint& con = constraints->at(i);
+ conInfo.bodyIds[0] = con.m_solverBodyIdA;
+ conInfo.bodyIds[1] = con.m_solverBodyIdB;
+ conInfo.constraintIndex = i;
+ conInfo.numConstraintRows = 1;
+ }
+ }
+ bool useRunLengthEncoding = true;
+ if (useRunLengthEncoding)
+ {
+ numConstraints = runLengthEncodeConstraintInfo(outConInfos, numConstraints);
+ }
+ return numConstraints;
}
-
static void expandConstraintRowsInPlace(int* constraintBatchIds, const btBatchedConstraintInfo* conInfos, int numConstraints, int numConstraintRows)
{
- BT_PROFILE("expandConstraintRowsInPlace");
- if (numConstraintRows > numConstraints)
- {
- // we walk the array in reverse to avoid overwriteing
- for (int iCon = numConstraints - 1; iCon >= 0; --iCon)
- {
- const btBatchedConstraintInfo& conInfo = conInfos[iCon];
- int iBatch = constraintBatchIds[iCon];
- for (int i = conInfo.numConstraintRows - 1; i >= 0; --i)
- {
- int iDest = conInfo.constraintIndex + i;
- btAssert(iDest >= iCon);
- btAssert(iDest >= 0 && iDest < numConstraintRows);
- constraintBatchIds[iDest] = iBatch;
- }
- }
- }
+ BT_PROFILE("expandConstraintRowsInPlace");
+ if (numConstraintRows > numConstraints)
+ {
+ // we walk the array in reverse to avoid overwriteing
+ for (int iCon = numConstraints - 1; iCon >= 0; --iCon)
+ {
+ const btBatchedConstraintInfo& conInfo = conInfos[iCon];
+ int iBatch = constraintBatchIds[iCon];
+ for (int i = conInfo.numConstraintRows - 1; i >= 0; --i)
+ {
+ int iDest = conInfo.constraintIndex + i;
+ btAssert(iDest >= iCon);
+ btAssert(iDest >= 0 && iDest < numConstraintRows);
+ constraintBatchIds[iDest] = iBatch;
+ }
+ }
+ }
}
-
static void expandConstraintRows(int* destConstraintBatchIds, const int* srcConstraintBatchIds, const btBatchedConstraintInfo* conInfos, int numConstraints, int numConstraintRows)
{
- BT_PROFILE("expandConstraintRows");
- for ( int iCon = 0; iCon < numConstraints; ++iCon )
- {
- const btBatchedConstraintInfo& conInfo = conInfos[ iCon ];
- int iBatch = srcConstraintBatchIds[ iCon ];
- for ( int i = 0; i < conInfo.numConstraintRows; ++i )
- {
- int iDest = conInfo.constraintIndex + i;
- btAssert( iDest >= iCon );
- btAssert( iDest >= 0 && iDest < numConstraintRows );
- destConstraintBatchIds[ iDest ] = iBatch;
- }
- }
+ BT_PROFILE("expandConstraintRows");
+ for (int iCon = 0; iCon < numConstraints; ++iCon)
+ {
+ const btBatchedConstraintInfo& conInfo = conInfos[iCon];
+ int iBatch = srcConstraintBatchIds[iCon];
+ for (int i = 0; i < conInfo.numConstraintRows; ++i)
+ {
+ int iDest = conInfo.constraintIndex + i;
+ btAssert(iDest >= iCon);
+ btAssert(iDest >= 0 && iDest < numConstraintRows);
+ destConstraintBatchIds[iDest] = iBatch;
+ }
+ }
}
-
struct ExpandConstraintRowsLoop : public btIParallelForBody
{
- int* m_destConstraintBatchIds;
- const int* m_srcConstraintBatchIds;
- const btBatchedConstraintInfo* m_conInfos;
- int m_numConstraintRows;
-
- ExpandConstraintRowsLoop( int* destConstraintBatchIds, const int* srcConstraintBatchIds, const btBatchedConstraintInfo* conInfos, int numConstraintRows)
- {
- m_destConstraintBatchIds = destConstraintBatchIds;
- m_srcConstraintBatchIds = srcConstraintBatchIds;
- m_conInfos = conInfos;
- m_numConstraintRows = numConstraintRows;
- }
- void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE
- {
- expandConstraintRows(m_destConstraintBatchIds, m_srcConstraintBatchIds + iBegin, m_conInfos + iBegin, iEnd - iBegin, m_numConstraintRows);
- }
+ int* m_destConstraintBatchIds;
+ const int* m_srcConstraintBatchIds;
+ const btBatchedConstraintInfo* m_conInfos;
+ int m_numConstraintRows;
+
+ ExpandConstraintRowsLoop(int* destConstraintBatchIds, const int* srcConstraintBatchIds, const btBatchedConstraintInfo* conInfos, int numConstraintRows)
+ {
+ m_destConstraintBatchIds = destConstraintBatchIds;
+ m_srcConstraintBatchIds = srcConstraintBatchIds;
+ m_conInfos = conInfos;
+ m_numConstraintRows = numConstraintRows;
+ }
+ void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
+ {
+ expandConstraintRows(m_destConstraintBatchIds, m_srcConstraintBatchIds + iBegin, m_conInfos + iBegin, iEnd - iBegin, m_numConstraintRows);
+ }
};
-
static void expandConstraintRowsMt(int* destConstraintBatchIds, const int* srcConstraintBatchIds, const btBatchedConstraintInfo* conInfos, int numConstraints, int numConstraintRows)
{
- BT_PROFILE("expandConstraintRowsMt");
- ExpandConstraintRowsLoop loop(destConstraintBatchIds, srcConstraintBatchIds, conInfos, numConstraintRows);
- int grainSize = 600;
- btParallelFor(0, numConstraints, grainSize, loop);
+ BT_PROFILE("expandConstraintRowsMt");
+ ExpandConstraintRowsLoop loop(destConstraintBatchIds, srcConstraintBatchIds, conInfos, numConstraintRows);
+ int grainSize = 600;
+ btParallelFor(0, numConstraints, grainSize, loop);
}
-
static void initBatchedConstraintInfoArray(btAlignedObjectArray<btBatchedConstraintInfo>* outConInfos, btConstraintArray* constraints)
{
- BT_PROFILE("initBatchedConstraintInfoArray");
- btAlignedObjectArray<btBatchedConstraintInfo>& conInfos = *outConInfos;
- int numConstraints = constraints->size();
- conInfos.resizeNoInitialize(numConstraints);
+ BT_PROFILE("initBatchedConstraintInfoArray");
+ btAlignedObjectArray<btBatchedConstraintInfo>& conInfos = *outConInfos;
+ int numConstraints = constraints->size();
+ conInfos.resizeNoInitialize(numConstraints);
- int newSize = initBatchedConstraintInfo(&outConInfos->at(0), constraints);
- conInfos.resizeNoInitialize(newSize);
+ int newSize = initBatchedConstraintInfo(&outConInfos->at(0), constraints);
+ conInfos.resizeNoInitialize(newSize);
}
-
static void mergeSmallBatches(btBatchInfo* batches, int iBeginBatch, int iEndBatch, int minBatchSize, int maxBatchSize)
{
- BT_PROFILE("mergeSmallBatches");
- for ( int iBatch = iEndBatch - 1; iBatch >= iBeginBatch; --iBatch )
- {
- btBatchInfo& batch = batches[ iBatch ];
- if ( batch.mergeIndex == kNoMerge && batch.numConstraints > 0 && batch.numConstraints < minBatchSize )
- {
- for ( int iDestBatch = iBatch - 1; iDestBatch >= iBeginBatch; --iDestBatch )
- {
- btBatchInfo& destBatch = batches[ iDestBatch ];
- if ( destBatch.mergeIndex == kNoMerge && ( destBatch.numConstraints + batch.numConstraints ) < maxBatchSize )
- {
- destBatch.numConstraints += batch.numConstraints;
- batch.numConstraints = 0;
- batch.mergeIndex = iDestBatch;
- break;
- }
- }
- }
- }
- // flatten mergeIndexes
- // e.g. in case where A was merged into B and then B was merged into C, we need A to point to C instead of B
- // Note: loop goes forward through batches because batches always merge from higher indexes to lower,
- // so by going from low to high it reduces the amount of trail-following
- for ( int iBatch = iBeginBatch; iBatch < iEndBatch; ++iBatch )
- {
- btBatchInfo& batch = batches[ iBatch ];
- if ( batch.mergeIndex != kNoMerge )
- {
- int iMergeDest = batches[ batch.mergeIndex ].mergeIndex;
- // follow trail of merges to the end
- while ( iMergeDest != kNoMerge )
- {
- int iNext = batches[ iMergeDest ].mergeIndex;
- if ( iNext == kNoMerge )
- {
- batch.mergeIndex = iMergeDest;
- break;
- }
- iMergeDest = iNext;
- }
- }
- }
+ BT_PROFILE("mergeSmallBatches");
+ for (int iBatch = iEndBatch - 1; iBatch >= iBeginBatch; --iBatch)
+ {
+ btBatchInfo& batch = batches[iBatch];
+ if (batch.mergeIndex == kNoMerge && batch.numConstraints > 0 && batch.numConstraints < minBatchSize)
+ {
+ for (int iDestBatch = iBatch - 1; iDestBatch >= iBeginBatch; --iDestBatch)
+ {
+ btBatchInfo& destBatch = batches[iDestBatch];
+ if (destBatch.mergeIndex == kNoMerge && (destBatch.numConstraints + batch.numConstraints) < maxBatchSize)
+ {
+ destBatch.numConstraints += batch.numConstraints;
+ batch.numConstraints = 0;
+ batch.mergeIndex = iDestBatch;
+ break;
+ }
+ }
+ }
+ }
+ // flatten mergeIndexes
+ // e.g. in case where A was merged into B and then B was merged into C, we need A to point to C instead of B
+ // Note: loop goes forward through batches because batches always merge from higher indexes to lower,
+ // so by going from low to high it reduces the amount of trail-following
+ for (int iBatch = iBeginBatch; iBatch < iEndBatch; ++iBatch)
+ {
+ btBatchInfo& batch = batches[iBatch];
+ if (batch.mergeIndex != kNoMerge)
+ {
+ int iMergeDest = batches[batch.mergeIndex].mergeIndex;
+ // follow trail of merges to the end
+ while (iMergeDest != kNoMerge)
+ {
+ int iNext = batches[iMergeDest].mergeIndex;
+ if (iNext == kNoMerge)
+ {
+ batch.mergeIndex = iMergeDest;
+ break;
+ }
+ iMergeDest = iNext;
+ }
+ }
+ }
}
-
static void updateConstraintBatchIdsForMerges(int* constraintBatchIds, int numConstraints, const btBatchInfo* batches, int numBatches)
{
- BT_PROFILE("updateConstraintBatchIdsForMerges");
- // update batchIds to account for merges
- for (int i = 0; i < numConstraints; ++i)
- {
- int iBatch = constraintBatchIds[i];
- btAssert(iBatch < numBatches);
- // if this constraint references a batch that was merged into another batch
- if (batches[iBatch].mergeIndex != kNoMerge)
- {
- // update batchId
- constraintBatchIds[i] = batches[iBatch].mergeIndex;
- }
- }
+ BT_PROFILE("updateConstraintBatchIdsForMerges");
+ // update batchIds to account for merges
+ for (int i = 0; i < numConstraints; ++i)
+ {
+ int iBatch = constraintBatchIds[i];
+ btAssert(iBatch < numBatches);
+ // if this constraint references a batch that was merged into another batch
+ if (batches[iBatch].mergeIndex != kNoMerge)
+ {
+ // update batchId
+ constraintBatchIds[i] = batches[iBatch].mergeIndex;
+ }
+ }
}
-
struct UpdateConstraintBatchIdsForMergesLoop : public btIParallelForBody
{
- int* m_constraintBatchIds;
- const btBatchInfo* m_batches;
- int m_numBatches;
-
- UpdateConstraintBatchIdsForMergesLoop( int* constraintBatchIds, const btBatchInfo* batches, int numBatches )
- {
- m_constraintBatchIds = constraintBatchIds;
- m_batches = batches;
- m_numBatches = numBatches;
- }
- void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE
- {
- BT_PROFILE( "UpdateConstraintBatchIdsForMergesLoop" );
- updateConstraintBatchIdsForMerges( m_constraintBatchIds + iBegin, iEnd - iBegin, m_batches, m_numBatches );
- }
+ int* m_constraintBatchIds;
+ const btBatchInfo* m_batches;
+ int m_numBatches;
+
+ UpdateConstraintBatchIdsForMergesLoop(int* constraintBatchIds, const btBatchInfo* batches, int numBatches)
+ {
+ m_constraintBatchIds = constraintBatchIds;
+ m_batches = batches;
+ m_numBatches = numBatches;
+ }
+ void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
+ {
+ BT_PROFILE("UpdateConstraintBatchIdsForMergesLoop");
+ updateConstraintBatchIdsForMerges(m_constraintBatchIds + iBegin, iEnd - iBegin, m_batches, m_numBatches);
+ }
};
-
static void updateConstraintBatchIdsForMergesMt(int* constraintBatchIds, int numConstraints, const btBatchInfo* batches, int numBatches)
{
- BT_PROFILE( "updateConstraintBatchIdsForMergesMt" );
- UpdateConstraintBatchIdsForMergesLoop loop(constraintBatchIds, batches, numBatches);
- int grainSize = 800;
- btParallelFor(0, numConstraints, grainSize, loop);
+ BT_PROFILE("updateConstraintBatchIdsForMergesMt");
+ UpdateConstraintBatchIdsForMergesLoop loop(constraintBatchIds, batches, numBatches);
+ int grainSize = 800;
+ btParallelFor(0, numConstraints, grainSize, loop);
}
-
inline bool BatchCompare(const btBatchedConstraints::Range& a, const btBatchedConstraints::Range& b)
{
- int lenA = a.end - a.begin;
- int lenB = b.end - b.begin;
- return lenA > lenB;
+ int lenA = a.end - a.begin;
+ int lenB = b.end - b.begin;
+ return lenA > lenB;
}
-
static void writeOutConstraintIndicesForRangeOfBatches(btBatchedConstraints* bc,
- const int* constraintBatchIds,
- int numConstraints,
- int* constraintIdPerBatch,
- int batchBegin,
- int batchEnd
- )
+ const int* constraintBatchIds,
+ int numConstraints,
+ int* constraintIdPerBatch,
+ int batchBegin,
+ int batchEnd)
{
- BT_PROFILE("writeOutConstraintIndicesForRangeOfBatches");
- for ( int iCon = 0; iCon < numConstraints; ++iCon )
- {
- int iBatch = constraintBatchIds[ iCon ];
- if (iBatch >= batchBegin && iBatch < batchEnd)
- {
- int iDestCon = constraintIdPerBatch[ iBatch ];
- constraintIdPerBatch[ iBatch ] = iDestCon + 1;
- bc->m_constraintIndices[ iDestCon ] = iCon;
- }
- }
+ BT_PROFILE("writeOutConstraintIndicesForRangeOfBatches");
+ for (int iCon = 0; iCon < numConstraints; ++iCon)
+ {
+ int iBatch = constraintBatchIds[iCon];
+ if (iBatch >= batchBegin && iBatch < batchEnd)
+ {
+ int iDestCon = constraintIdPerBatch[iBatch];
+ constraintIdPerBatch[iBatch] = iDestCon + 1;
+ bc->m_constraintIndices[iDestCon] = iCon;
+ }
+ }
}
-
struct WriteOutConstraintIndicesLoop : public btIParallelForBody
{
- btBatchedConstraints* m_batchedConstraints;
- const int* m_constraintBatchIds;
- int m_numConstraints;
- int* m_constraintIdPerBatch;
- int m_maxNumBatchesPerPhase;
-
- WriteOutConstraintIndicesLoop( btBatchedConstraints* bc, const int* constraintBatchIds, int numConstraints, int* constraintIdPerBatch, int maxNumBatchesPerPhase )
- {
- m_batchedConstraints = bc;
- m_constraintBatchIds = constraintBatchIds;
- m_numConstraints = numConstraints;
- m_constraintIdPerBatch = constraintIdPerBatch;
- m_maxNumBatchesPerPhase = maxNumBatchesPerPhase;
- }
- void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE
- {
- BT_PROFILE( "WriteOutConstraintIndicesLoop" );
- int batchBegin = iBegin * m_maxNumBatchesPerPhase;
- int batchEnd = iEnd * m_maxNumBatchesPerPhase;
- writeOutConstraintIndicesForRangeOfBatches(m_batchedConstraints,
- m_constraintBatchIds,
- m_numConstraints,
- m_constraintIdPerBatch,
- batchBegin,
- batchEnd
- );
- }
+ btBatchedConstraints* m_batchedConstraints;
+ const int* m_constraintBatchIds;
+ int m_numConstraints;
+ int* m_constraintIdPerBatch;
+ int m_maxNumBatchesPerPhase;
+
+ WriteOutConstraintIndicesLoop(btBatchedConstraints* bc, const int* constraintBatchIds, int numConstraints, int* constraintIdPerBatch, int maxNumBatchesPerPhase)
+ {
+ m_batchedConstraints = bc;
+ m_constraintBatchIds = constraintBatchIds;
+ m_numConstraints = numConstraints;
+ m_constraintIdPerBatch = constraintIdPerBatch;
+ m_maxNumBatchesPerPhase = maxNumBatchesPerPhase;
+ }
+ void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
+ {
+ BT_PROFILE("WriteOutConstraintIndicesLoop");
+ int batchBegin = iBegin * m_maxNumBatchesPerPhase;
+ int batchEnd = iEnd * m_maxNumBatchesPerPhase;
+ writeOutConstraintIndicesForRangeOfBatches(m_batchedConstraints,
+ m_constraintBatchIds,
+ m_numConstraints,
+ m_constraintIdPerBatch,
+ batchBegin,
+ batchEnd);
+ }
};
-
static void writeOutConstraintIndicesMt(btBatchedConstraints* bc,
- const int* constraintBatchIds,
- int numConstraints,
- int* constraintIdPerBatch,
- int maxNumBatchesPerPhase,
- int numPhases
- )
+ const int* constraintBatchIds,
+ int numConstraints,
+ int* constraintIdPerBatch,
+ int maxNumBatchesPerPhase,
+ int numPhases)
{
- BT_PROFILE("writeOutConstraintIndicesMt");
- bool inParallel = true;
- if (inParallel)
- {
- WriteOutConstraintIndicesLoop loop( bc, constraintBatchIds, numConstraints, constraintIdPerBatch, maxNumBatchesPerPhase );
- btParallelFor( 0, numPhases, 1, loop );
- }
- else
- {
- for ( int iCon = 0; iCon < numConstraints; ++iCon )
- {
- int iBatch = constraintBatchIds[ iCon ];
- int iDestCon = constraintIdPerBatch[ iBatch ];
- constraintIdPerBatch[ iBatch ] = iDestCon + 1;
- bc->m_constraintIndices[ iDestCon ] = iCon;
- }
- }
+ BT_PROFILE("writeOutConstraintIndicesMt");
+ bool inParallel = true;
+ if (inParallel)
+ {
+ WriteOutConstraintIndicesLoop loop(bc, constraintBatchIds, numConstraints, constraintIdPerBatch, maxNumBatchesPerPhase);
+ btParallelFor(0, numPhases, 1, loop);
+ }
+ else
+ {
+ for (int iCon = 0; iCon < numConstraints; ++iCon)
+ {
+ int iBatch = constraintBatchIds[iCon];
+ int iDestCon = constraintIdPerBatch[iBatch];
+ constraintIdPerBatch[iBatch] = iDestCon + 1;
+ bc->m_constraintIndices[iDestCon] = iCon;
+ }
+ }
}
-
static void writeGrainSizes(btBatchedConstraints* bc)
{
- typedef btBatchedConstraints::Range Range;
- int numPhases = bc->m_phases.size();
- bc->m_phaseGrainSize.resizeNoInitialize(numPhases);
- int numThreads = btGetTaskScheduler()->getNumThreads();
- for (int iPhase = 0; iPhase < numPhases; ++iPhase)
- {
- const Range& phase = bc->m_phases[ iPhase ];
- int numBatches = phase.end - phase.begin;
- float grainSize = floor((0.25f*numBatches / float(numThreads)) + 0.0f);
- bc->m_phaseGrainSize[ iPhase ] = btMax(1, int(grainSize));
- }
+ typedef btBatchedConstraints::Range Range;
+ int numPhases = bc->m_phases.size();
+ bc->m_phaseGrainSize.resizeNoInitialize(numPhases);
+ int numThreads = btGetTaskScheduler()->getNumThreads();
+ for (int iPhase = 0; iPhase < numPhases; ++iPhase)
+ {
+ const Range& phase = bc->m_phases[iPhase];
+ int numBatches = phase.end - phase.begin;
+ float grainSize = floor((0.25f * numBatches / float(numThreads)) + 0.0f);
+ bc->m_phaseGrainSize[iPhase] = btMax(1, int(grainSize));
+ }
}
-
static void writeOutBatches(btBatchedConstraints* bc,
- const int* constraintBatchIds,
- int numConstraints,
- const btBatchInfo* batches,
- int* batchWork,
- int maxNumBatchesPerPhase,
- int numPhases
-)
+ const int* constraintBatchIds,
+ int numConstraints,
+ const btBatchInfo* batches,
+ int* batchWork,
+ int maxNumBatchesPerPhase,
+ int numPhases)
{
- BT_PROFILE("writeOutBatches");
- typedef btBatchedConstraints::Range Range;
- bc->m_constraintIndices.reserve( numConstraints );
- bc->m_batches.resizeNoInitialize( 0 );
- bc->m_phases.resizeNoInitialize( 0 );
-
- //int maxNumBatches = numPhases * maxNumBatchesPerPhase;
- {
- int* constraintIdPerBatch = batchWork; // for each batch, keep an index into the next available slot in the m_constraintIndices array
- int iConstraint = 0;
- for (int iPhase = 0; iPhase < numPhases; ++iPhase)
- {
- int curPhaseBegin = bc->m_batches.size();
- int iBegin = iPhase * maxNumBatchesPerPhase;
- int iEnd = iBegin + maxNumBatchesPerPhase;
- for ( int i = iBegin; i < iEnd; ++i )
- {
- const btBatchInfo& batch = batches[ i ];
- int curBatchBegin = iConstraint;
- constraintIdPerBatch[ i ] = curBatchBegin; // record the start of each batch in m_constraintIndices array
- int numConstraints = batch.numConstraints;
- iConstraint += numConstraints;
- if ( numConstraints > 0 )
- {
- bc->m_batches.push_back( Range( curBatchBegin, iConstraint ) );
- }
- }
- // if any batches were emitted this phase,
- if ( bc->m_batches.size() > curPhaseBegin )
- {
- // output phase
- bc->m_phases.push_back( Range( curPhaseBegin, bc->m_batches.size() ) );
- }
- }
-
- btAssert(iConstraint == numConstraints);
- bc->m_constraintIndices.resizeNoInitialize( numConstraints );
- writeOutConstraintIndicesMt( bc, constraintBatchIds, numConstraints, constraintIdPerBatch, maxNumBatchesPerPhase, numPhases );
- }
- // for each phase
- for (int iPhase = 0; iPhase < bc->m_phases.size(); ++iPhase)
- {
- // sort the batches from largest to smallest (can be helpful to some task schedulers)
- const Range& curBatches = bc->m_phases[iPhase];
- bc->m_batches.quickSortInternal(BatchCompare, curBatches.begin, curBatches.end-1);
- }
- bc->m_phaseOrder.resize(bc->m_phases.size());
- for (int i = 0; i < bc->m_phases.size(); ++i)
- {
- bc->m_phaseOrder[i] = i;
- }
- writeGrainSizes(bc);
+ BT_PROFILE("writeOutBatches");
+ typedef btBatchedConstraints::Range Range;
+ bc->m_constraintIndices.reserve(numConstraints);
+ bc->m_batches.resizeNoInitialize(0);
+ bc->m_phases.resizeNoInitialize(0);
+
+ //int maxNumBatches = numPhases * maxNumBatchesPerPhase;
+ {
+ int* constraintIdPerBatch = batchWork; // for each batch, keep an index into the next available slot in the m_constraintIndices array
+ int iConstraint = 0;
+ for (int iPhase = 0; iPhase < numPhases; ++iPhase)
+ {
+ int curPhaseBegin = bc->m_batches.size();
+ int iBegin = iPhase * maxNumBatchesPerPhase;
+ int iEnd = iBegin + maxNumBatchesPerPhase;
+ for (int i = iBegin; i < iEnd; ++i)
+ {
+ const btBatchInfo& batch = batches[i];
+ int curBatchBegin = iConstraint;
+ constraintIdPerBatch[i] = curBatchBegin; // record the start of each batch in m_constraintIndices array
+ int numConstraints = batch.numConstraints;
+ iConstraint += numConstraints;
+ if (numConstraints > 0)
+ {
+ bc->m_batches.push_back(Range(curBatchBegin, iConstraint));
+ }
+ }
+ // if any batches were emitted this phase,
+ if (bc->m_batches.size() > curPhaseBegin)
+ {
+ // output phase
+ bc->m_phases.push_back(Range(curPhaseBegin, bc->m_batches.size()));
+ }
+ }
+
+ btAssert(iConstraint == numConstraints);
+ bc->m_constraintIndices.resizeNoInitialize(numConstraints);
+ writeOutConstraintIndicesMt(bc, constraintBatchIds, numConstraints, constraintIdPerBatch, maxNumBatchesPerPhase, numPhases);
+ }
+ // for each phase
+ for (int iPhase = 0; iPhase < bc->m_phases.size(); ++iPhase)
+ {
+ // sort the batches from largest to smallest (can be helpful to some task schedulers)
+ const Range& curBatches = bc->m_phases[iPhase];
+ bc->m_batches.quickSortInternal(BatchCompare, curBatches.begin, curBatches.end - 1);
+ }
+ bc->m_phaseOrder.resize(bc->m_phases.size());
+ for (int i = 0; i < bc->m_phases.size(); ++i)
+ {
+ bc->m_phaseOrder[i] = i;
+ }
+ writeGrainSizes(bc);
}
-
//
// PreallocatedMemoryHelper -- helper object for allocating a number of chunks of memory in a single contiguous block.
// It is generally more efficient to do a single larger allocation than many smaller allocations.
@@ -639,191 +605,184 @@ static void writeOutBatches(btBatchedConstraints* bc,
template <int N>
class PreallocatedMemoryHelper
{
- struct Chunk
- {
- void** ptr;
- size_t size;
- };
- Chunk m_chunks[N];
- int m_numChunks;
+ struct Chunk
+ {
+ void** ptr;
+ size_t size;
+ };
+ Chunk m_chunks[N];
+ int m_numChunks;
+
public:
- PreallocatedMemoryHelper() {m_numChunks=0;}
- void addChunk( void** ptr, size_t sz )
- {
- btAssert( m_numChunks < N );
- if ( m_numChunks < N )
- {
- Chunk& chunk = m_chunks[ m_numChunks ];
- chunk.ptr = ptr;
- chunk.size = sz;
- m_numChunks++;
- }
- }
- size_t getSizeToAllocate() const
- {
- size_t totalSize = 0;
- for (int i = 0; i < m_numChunks; ++i)
- {
- totalSize += m_chunks[i].size;
- }
- return totalSize;
- }
- void setChunkPointers(void* mem) const
- {
- size_t totalSize = 0;
- for (int i = 0; i < m_numChunks; ++i)
- {
- const Chunk& chunk = m_chunks[ i ];
- char* chunkPtr = static_cast<char*>(mem) + totalSize;
- *chunk.ptr = chunkPtr;
- totalSize += chunk.size;
- }
- }
+ PreallocatedMemoryHelper() { m_numChunks = 0; }
+ void addChunk(void** ptr, size_t sz)
+ {
+ btAssert(m_numChunks < N);
+ if (m_numChunks < N)
+ {
+ Chunk& chunk = m_chunks[m_numChunks];
+ chunk.ptr = ptr;
+ chunk.size = sz;
+ m_numChunks++;
+ }
+ }
+ size_t getSizeToAllocate() const
+ {
+ size_t totalSize = 0;
+ for (int i = 0; i < m_numChunks; ++i)
+ {
+ totalSize += m_chunks[i].size;
+ }
+ return totalSize;
+ }
+ void setChunkPointers(void* mem) const
+ {
+ size_t totalSize = 0;
+ for (int i = 0; i < m_numChunks; ++i)
+ {
+ const Chunk& chunk = m_chunks[i];
+ char* chunkPtr = static_cast<char*>(mem) + totalSize;
+ *chunk.ptr = chunkPtr;
+ totalSize += chunk.size;
+ }
+ }
};
-
-
static btVector3 findMaxDynamicConstraintExtent(
- btVector3* bodyPositions,
- bool* bodyDynamicFlags,
- btBatchedConstraintInfo* conInfos,
- int numConstraints,
- int numBodies
- )
+ btVector3* bodyPositions,
+ bool* bodyDynamicFlags,
+ btBatchedConstraintInfo* conInfos,
+ int numConstraints,
+ int numBodies)
{
- BT_PROFILE("findMaxDynamicConstraintExtent");
- btVector3 consExtent = btVector3(1,1,1) * 0.001;
- for (int iCon = 0; iCon < numConstraints; ++iCon)
- {
- const btBatchedConstraintInfo& con = conInfos[ iCon ];
- int iBody0 = con.bodyIds[0];
- int iBody1 = con.bodyIds[1];
- btAssert(iBody0 >= 0 && iBody0 < numBodies);
- btAssert(iBody1 >= 0 && iBody1 < numBodies);
- // is it a dynamic constraint?
- if (bodyDynamicFlags[iBody0] && bodyDynamicFlags[iBody1])
- {
- btVector3 delta = bodyPositions[iBody1] - bodyPositions[iBody0];
- consExtent.setMax(delta.absolute());
- }
- }
- return consExtent;
+ BT_PROFILE("findMaxDynamicConstraintExtent");
+ btVector3 consExtent = btVector3(1, 1, 1) * 0.001;
+ for (int iCon = 0; iCon < numConstraints; ++iCon)
+ {
+ const btBatchedConstraintInfo& con = conInfos[iCon];
+ int iBody0 = con.bodyIds[0];
+ int iBody1 = con.bodyIds[1];
+ btAssert(iBody0 >= 0 && iBody0 < numBodies);
+ btAssert(iBody1 >= 0 && iBody1 < numBodies);
+ // is it a dynamic constraint?
+ if (bodyDynamicFlags[iBody0] && bodyDynamicFlags[iBody1])
+ {
+ btVector3 delta = bodyPositions[iBody1] - bodyPositions[iBody0];
+ consExtent.setMax(delta.absolute());
+ }
+ }
+ return consExtent;
}
-
struct btIntVec3
{
- int m_ints[ 3 ];
+ int m_ints[3];
- SIMD_FORCE_INLINE const int& operator[](int i) const {return m_ints[i];}
- SIMD_FORCE_INLINE int& operator[](int i) {return m_ints[i];}
+ SIMD_FORCE_INLINE const int& operator[](int i) const { return m_ints[i]; }
+ SIMD_FORCE_INLINE int& operator[](int i) { return m_ints[i]; }
};
-
struct AssignConstraintsToGridBatchesParams
{
- bool* bodyDynamicFlags;
- btIntVec3* bodyGridCoords;
- int numBodies;
- btBatchedConstraintInfo* conInfos;
- int* constraintBatchIds;
- btIntVec3 gridChunkDim;
- int maxNumBatchesPerPhase;
- int numPhases;
- int phaseMask;
-
- AssignConstraintsToGridBatchesParams()
- {
- memset(this, 0, sizeof(*this));
- }
+ bool* bodyDynamicFlags;
+ btIntVec3* bodyGridCoords;
+ int numBodies;
+ btBatchedConstraintInfo* conInfos;
+ int* constraintBatchIds;
+ btIntVec3 gridChunkDim;
+ int maxNumBatchesPerPhase;
+ int numPhases;
+ int phaseMask;
+
+ AssignConstraintsToGridBatchesParams()
+ {
+ memset(this, 0, sizeof(*this));
+ }
};
-
static void assignConstraintsToGridBatches(const AssignConstraintsToGridBatchesParams& params, int iConBegin, int iConEnd)
{
- BT_PROFILE("assignConstraintsToGridBatches");
- // (can be done in parallel)
- for ( int iCon = iConBegin; iCon < iConEnd; ++iCon )
- {
- const btBatchedConstraintInfo& con = params.conInfos[ iCon ];
- int iBody0 = con.bodyIds[ 0 ];
- int iBody1 = con.bodyIds[ 1 ];
- int iPhase = iCon; //iBody0; // pseudorandom choice to distribute evenly amongst phases
- iPhase &= params.phaseMask;
- int gridCoord[ 3 ];
- // is it a dynamic constraint?
- if ( params.bodyDynamicFlags[ iBody0 ] && params.bodyDynamicFlags[ iBody1 ] )
- {
- const btIntVec3& body0Coords = params.bodyGridCoords[iBody0];
- const btIntVec3& body1Coords = params.bodyGridCoords[iBody1];
- // for each dimension x,y,z,
- for (int i = 0; i < 3; ++i)
- {
- int coordMin = btMin(body0Coords.m_ints[i], body1Coords.m_ints[i]);
- int coordMax = btMax(body0Coords.m_ints[i], body1Coords.m_ints[i]);
- if (coordMin != coordMax)
- {
- btAssert( coordMax == coordMin + 1 );
- if ((coordMin&1) == 0)
- {
- iPhase &= ~(1 << i); // force bit off
- }
- else
- {
- iPhase |= (1 << i); // force bit on
- iPhase &= params.phaseMask;
- }
- }
- gridCoord[ i ] = coordMin;
- }
- }
- else
- {
- if ( !params.bodyDynamicFlags[ iBody0 ] )
- {
- iBody0 = con.bodyIds[ 1 ];
- }
- btAssert(params.bodyDynamicFlags[ iBody0 ]);
- const btIntVec3& body0Coords = params.bodyGridCoords[iBody0];
- // for each dimension x,y,z,
- for ( int i = 0; i < 3; ++i )
- {
- gridCoord[ i ] = body0Coords.m_ints[ i ];
- }
- }
- // calculate chunk coordinates
- int chunkCoord[ 3 ];
- btIntVec3 gridChunkDim = params.gridChunkDim;
- // for each dimension x,y,z,
- for ( int i = 0; i < 3; ++i )
- {
- int coordOffset = ( iPhase >> i ) & 1;
- chunkCoord[ i ] = (gridCoord[ i ] - coordOffset)/2;
- btClamp( chunkCoord[ i ], 0, gridChunkDim[ i ] - 1);
- btAssert( chunkCoord[ i ] < gridChunkDim[ i ] );
- }
- int iBatch = iPhase * params.maxNumBatchesPerPhase + chunkCoord[ 0 ] + chunkCoord[ 1 ] * gridChunkDim[ 0 ] + chunkCoord[ 2 ] * gridChunkDim[ 0 ] * gridChunkDim[ 1 ];
- btAssert(iBatch >= 0 && iBatch < params.maxNumBatchesPerPhase*params.numPhases);
- params.constraintBatchIds[ iCon ] = iBatch;
- }
+ BT_PROFILE("assignConstraintsToGridBatches");
+ // (can be done in parallel)
+ for (int iCon = iConBegin; iCon < iConEnd; ++iCon)
+ {
+ const btBatchedConstraintInfo& con = params.conInfos[iCon];
+ int iBody0 = con.bodyIds[0];
+ int iBody1 = con.bodyIds[1];
+ int iPhase = iCon; //iBody0; // pseudorandom choice to distribute evenly amongst phases
+ iPhase &= params.phaseMask;
+ int gridCoord[3];
+ // is it a dynamic constraint?
+ if (params.bodyDynamicFlags[iBody0] && params.bodyDynamicFlags[iBody1])
+ {
+ const btIntVec3& body0Coords = params.bodyGridCoords[iBody0];
+ const btIntVec3& body1Coords = params.bodyGridCoords[iBody1];
+ // for each dimension x,y,z,
+ for (int i = 0; i < 3; ++i)
+ {
+ int coordMin = btMin(body0Coords.m_ints[i], body1Coords.m_ints[i]);
+ int coordMax = btMax(body0Coords.m_ints[i], body1Coords.m_ints[i]);
+ if (coordMin != coordMax)
+ {
+ btAssert(coordMax == coordMin + 1);
+ if ((coordMin & 1) == 0)
+ {
+ iPhase &= ~(1 << i); // force bit off
+ }
+ else
+ {
+ iPhase |= (1 << i); // force bit on
+ iPhase &= params.phaseMask;
+ }
+ }
+ gridCoord[i] = coordMin;
+ }
+ }
+ else
+ {
+ if (!params.bodyDynamicFlags[iBody0])
+ {
+ iBody0 = con.bodyIds[1];
+ }
+ btAssert(params.bodyDynamicFlags[iBody0]);
+ const btIntVec3& body0Coords = params.bodyGridCoords[iBody0];
+ // for each dimension x,y,z,
+ for (int i = 0; i < 3; ++i)
+ {
+ gridCoord[i] = body0Coords.m_ints[i];
+ }
+ }
+ // calculate chunk coordinates
+ int chunkCoord[3];
+ btIntVec3 gridChunkDim = params.gridChunkDim;
+ // for each dimension x,y,z,
+ for (int i = 0; i < 3; ++i)
+ {
+ int coordOffset = (iPhase >> i) & 1;
+ chunkCoord[i] = (gridCoord[i] - coordOffset) / 2;
+ btClamp(chunkCoord[i], 0, gridChunkDim[i] - 1);
+ btAssert(chunkCoord[i] < gridChunkDim[i]);
+ }
+ int iBatch = iPhase * params.maxNumBatchesPerPhase + chunkCoord[0] + chunkCoord[1] * gridChunkDim[0] + chunkCoord[2] * gridChunkDim[0] * gridChunkDim[1];
+ btAssert(iBatch >= 0 && iBatch < params.maxNumBatchesPerPhase * params.numPhases);
+ params.constraintBatchIds[iCon] = iBatch;
+ }
}
-
struct AssignConstraintsToGridBatchesLoop : public btIParallelForBody
{
- const AssignConstraintsToGridBatchesParams* m_params;
-
- AssignConstraintsToGridBatchesLoop( const AssignConstraintsToGridBatchesParams& params )
- {
- m_params = &params;
- }
- void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE
- {
- assignConstraintsToGridBatches(*m_params, iBegin, iEnd);
- }
+ const AssignConstraintsToGridBatchesParams* m_params;
+
+ AssignConstraintsToGridBatchesLoop(const AssignConstraintsToGridBatchesParams& params)
+ {
+ m_params = &params;
+ }
+ void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
+ {
+ assignConstraintsToGridBatches(*m_params, iBegin, iEnd);
+ }
};
-
//
// setupSpatialGridBatchesMt -- generate batches using a uniform 3D grid
//
@@ -853,276 +812,269 @@ to 4. With fewer phases, there are more constraints per phase and this makes it
*/
//
static void setupSpatialGridBatchesMt(
- btBatchedConstraints* batchedConstraints,
- btAlignedObjectArray<char>* scratchMemory,
- btConstraintArray* constraints,
- const btAlignedObjectArray<btSolverBody>& bodies,
- int minBatchSize,
- int maxBatchSize,
- bool use2DGrid
-)
+ btBatchedConstraints* batchedConstraints,
+ btAlignedObjectArray<char>* scratchMemory,
+ btConstraintArray* constraints,
+ const btAlignedObjectArray<btSolverBody>& bodies,
+ int minBatchSize,
+ int maxBatchSize,
+ bool use2DGrid)
{
- BT_PROFILE("setupSpatialGridBatchesMt");
- const int numPhases = 8;
- int numConstraints = constraints->size();
- int numConstraintRows = constraints->size();
-
- const int maxGridChunkCount = 128;
- int allocNumBatchesPerPhase = maxGridChunkCount;
- int minNumBatchesPerPhase = 16;
- int allocNumBatches = allocNumBatchesPerPhase * numPhases;
-
- btVector3* bodyPositions = NULL;
- bool* bodyDynamicFlags = NULL;
- btIntVec3* bodyGridCoords = NULL;
- btBatchInfo* batches = NULL;
- int* batchWork = NULL;
- btBatchedConstraintInfo* conInfos = NULL;
- int* constraintBatchIds = NULL;
- int* constraintRowBatchIds = NULL;
- {
- PreallocatedMemoryHelper<10> memHelper;
- memHelper.addChunk( (void**) &bodyPositions, sizeof( btVector3 ) * bodies.size() );
- memHelper.addChunk( (void**) &bodyDynamicFlags, sizeof( bool ) * bodies.size() );
- memHelper.addChunk( (void**) &bodyGridCoords, sizeof( btIntVec3 ) * bodies.size() );
- memHelper.addChunk( (void**) &batches, sizeof( btBatchInfo )* allocNumBatches );
- memHelper.addChunk( (void**) &batchWork, sizeof( int )* allocNumBatches );
- memHelper.addChunk( (void**) &conInfos, sizeof( btBatchedConstraintInfo ) * numConstraints );
- memHelper.addChunk( (void**) &constraintBatchIds, sizeof( int ) * numConstraints );
- memHelper.addChunk( (void**) &constraintRowBatchIds, sizeof( int ) * numConstraintRows );
- size_t scratchSize = memHelper.getSizeToAllocate();
- // if we need to reallocate
- if (scratchMemory->capacity() < scratchSize)
- {
- // allocate 6.25% extra to avoid repeated reallocs
- scratchMemory->reserve( scratchSize + scratchSize/16 );
- }
- scratchMemory->resizeNoInitialize( scratchSize );
- char* memPtr = &scratchMemory->at(0);
- memHelper.setChunkPointers( memPtr );
- }
-
- numConstraints = initBatchedConstraintInfo(conInfos, constraints);
-
- // compute bounding box around all dynamic bodies
- // (could be done in parallel)
- btVector3 bboxMin(BT_LARGE_FLOAT, BT_LARGE_FLOAT, BT_LARGE_FLOAT);
- btVector3 bboxMax = -bboxMin;
- //int dynamicBodyCount = 0;
- for (int i = 0; i < bodies.size(); ++i)
- {
- const btSolverBody& body = bodies[i];
- btVector3 bodyPos = body.getWorldTransform().getOrigin();
- bool isDynamic = ( body.internalGetInvMass().x() > btScalar( 0 ) );
- bodyPositions[i] = bodyPos;
- bodyDynamicFlags[i] = isDynamic;
- if (isDynamic)
- {
- //dynamicBodyCount++;
- bboxMin.setMin(bodyPos);
- bboxMax.setMax(bodyPos);
- }
- }
-
- // find max extent of all dynamic constraints
- // (could be done in parallel)
- btVector3 consExtent = findMaxDynamicConstraintExtent(bodyPositions, bodyDynamicFlags, conInfos, numConstraints, bodies.size());
-
- btVector3 gridExtent = bboxMax - bboxMin;
-
- btVector3 gridCellSize = consExtent;
- int gridDim[3];
- gridDim[ 0 ] = int( 1.0 + gridExtent.x() / gridCellSize.x() );
- gridDim[ 1 ] = int( 1.0 + gridExtent.y() / gridCellSize.y() );
- gridDim[ 2 ] = int( 1.0 + gridExtent.z() / gridCellSize.z() );
-
- // if we can collapse an axis, it will cut our number of phases in half which could be more efficient
- int phaseMask = 7;
- bool collapseAxis = use2DGrid;
- if ( collapseAxis )
- {
- // pick the smallest axis to collapse, leaving us with the greatest number of cells in our grid
- int iAxisToCollapse = 0;
- int axisDim = gridDim[iAxisToCollapse];
- //for each dimension
- for ( int i = 0; i < 3; ++i )
- {
- if (gridDim[i] < axisDim)
- {
- iAxisToCollapse = i;
- axisDim = gridDim[i];
- }
- }
- // collapse it
- gridCellSize[iAxisToCollapse] = gridExtent[iAxisToCollapse] * 2.0f;
- phaseMask &= ~(1 << iAxisToCollapse);
- }
-
- int numGridChunks = 0;
- btIntVec3 gridChunkDim; // each chunk is 2x2x2 group of cells
- while (true)
- {
- gridDim[0] = int( 1.0 + gridExtent.x() / gridCellSize.x() );
- gridDim[1] = int( 1.0 + gridExtent.y() / gridCellSize.y() );
- gridDim[2] = int( 1.0 + gridExtent.z() / gridCellSize.z() );
- gridChunkDim[ 0 ] = btMax( 1, ( gridDim[ 0 ] + 0 ) / 2 );
- gridChunkDim[ 1 ] = btMax( 1, ( gridDim[ 1 ] + 0 ) / 2 );
- gridChunkDim[ 2 ] = btMax( 1, ( gridDim[ 2 ] + 0 ) / 2 );
- numGridChunks = gridChunkDim[ 0 ] * gridChunkDim[ 1 ] * gridChunkDim[ 2 ];
- float nChunks = float(gridChunkDim[0]) * float(gridChunkDim[1]) * float(gridChunkDim[2]); // suceptible to integer overflow
- if ( numGridChunks <= maxGridChunkCount && nChunks <= maxGridChunkCount )
- {
- break;
- }
- gridCellSize *= 1.25; // should roughly cut numCells in half
- }
- btAssert(numGridChunks <= maxGridChunkCount );
- int maxNumBatchesPerPhase = numGridChunks;
-
- // for each dynamic body, compute grid coords
- btVector3 invGridCellSize = btVector3(1,1,1)/gridCellSize;
- // (can be done in parallel)
- for (int iBody = 0; iBody < bodies.size(); ++iBody)
- {
- btIntVec3& coords = bodyGridCoords[iBody];
- if (bodyDynamicFlags[iBody])
- {
- btVector3 v = ( bodyPositions[ iBody ] - bboxMin )*invGridCellSize;
- coords.m_ints[0] = int(v.x());
- coords.m_ints[1] = int(v.y());
- coords.m_ints[2] = int(v.z());
- btAssert(coords.m_ints[0] >= 0 && coords.m_ints[0] < gridDim[0]);
- btAssert(coords.m_ints[1] >= 0 && coords.m_ints[1] < gridDim[1]);
- btAssert(coords.m_ints[2] >= 0 && coords.m_ints[2] < gridDim[2]);
- }
- else
- {
- coords.m_ints[0] = -1;
- coords.m_ints[1] = -1;
- coords.m_ints[2] = -1;
- }
- }
-
- for (int iPhase = 0; iPhase < numPhases; ++iPhase)
- {
- int batchBegin = iPhase * maxNumBatchesPerPhase;
- int batchEnd = batchBegin + maxNumBatchesPerPhase;
- for ( int iBatch = batchBegin; iBatch < batchEnd; ++iBatch )
- {
- btBatchInfo& batch = batches[ iBatch ];
- batch = btBatchInfo();
- }
- }
-
- {
- AssignConstraintsToGridBatchesParams params;
- params.bodyDynamicFlags = bodyDynamicFlags;
- params.bodyGridCoords = bodyGridCoords;
- params.numBodies = bodies.size();
- params.conInfos = conInfos;
- params.constraintBatchIds = constraintBatchIds;
- params.gridChunkDim = gridChunkDim;
- params.maxNumBatchesPerPhase = maxNumBatchesPerPhase;
- params.numPhases = numPhases;
- params.phaseMask = phaseMask;
- bool inParallel = true;
- if (inParallel)
- {
- AssignConstraintsToGridBatchesLoop loop(params);
- int grainSize = 250;
- btParallelFor(0, numConstraints, grainSize, loop);
- }
- else
- {
- assignConstraintsToGridBatches( params, 0, numConstraints );
- }
- }
- for ( int iCon = 0; iCon < numConstraints; ++iCon )
- {
- const btBatchedConstraintInfo& con = conInfos[ iCon ];
- int iBatch = constraintBatchIds[ iCon ];
- btBatchInfo& batch = batches[iBatch];
- batch.numConstraints += con.numConstraintRows;
- }
-
- for (int iPhase = 0; iPhase < numPhases; ++iPhase)
- {
- // if phase is legit,
- if (iPhase == (iPhase&phaseMask))
- {
- int iBeginBatch = iPhase * maxNumBatchesPerPhase;
- int iEndBatch = iBeginBatch + maxNumBatchesPerPhase;
- mergeSmallBatches( batches, iBeginBatch, iEndBatch, minBatchSize, maxBatchSize );
- }
- }
- // all constraints have been assigned a batchId
- updateConstraintBatchIdsForMergesMt(constraintBatchIds, numConstraints, batches, maxNumBatchesPerPhase*numPhases);
-
- if (numConstraintRows > numConstraints)
- {
- expandConstraintRowsMt(&constraintRowBatchIds[0], &constraintBatchIds[0], &conInfos[0], numConstraints, numConstraintRows);
- }
- else
- {
- constraintRowBatchIds = constraintBatchIds;
- }
-
- writeOutBatches(batchedConstraints, constraintRowBatchIds, numConstraintRows, batches, batchWork, maxNumBatchesPerPhase, numPhases);
- btAssert(batchedConstraints->validate(constraints, bodies));
+ BT_PROFILE("setupSpatialGridBatchesMt");
+ const int numPhases = 8;
+ int numConstraints = constraints->size();
+ int numConstraintRows = constraints->size();
+
+ const int maxGridChunkCount = 128;
+ int allocNumBatchesPerPhase = maxGridChunkCount;
+ int minNumBatchesPerPhase = 16;
+ int allocNumBatches = allocNumBatchesPerPhase * numPhases;
+
+ btVector3* bodyPositions = NULL;
+ bool* bodyDynamicFlags = NULL;
+ btIntVec3* bodyGridCoords = NULL;
+ btBatchInfo* batches = NULL;
+ int* batchWork = NULL;
+ btBatchedConstraintInfo* conInfos = NULL;
+ int* constraintBatchIds = NULL;
+ int* constraintRowBatchIds = NULL;
+ {
+ PreallocatedMemoryHelper<10> memHelper;
+ memHelper.addChunk((void**)&bodyPositions, sizeof(btVector3) * bodies.size());
+ memHelper.addChunk((void**)&bodyDynamicFlags, sizeof(bool) * bodies.size());
+ memHelper.addChunk((void**)&bodyGridCoords, sizeof(btIntVec3) * bodies.size());
+ memHelper.addChunk((void**)&batches, sizeof(btBatchInfo) * allocNumBatches);
+ memHelper.addChunk((void**)&batchWork, sizeof(int) * allocNumBatches);
+ memHelper.addChunk((void**)&conInfos, sizeof(btBatchedConstraintInfo) * numConstraints);
+ memHelper.addChunk((void**)&constraintBatchIds, sizeof(int) * numConstraints);
+ memHelper.addChunk((void**)&constraintRowBatchIds, sizeof(int) * numConstraintRows);
+ size_t scratchSize = memHelper.getSizeToAllocate();
+ // if we need to reallocate
+ if (scratchMemory->capacity() < scratchSize)
+ {
+ // allocate 6.25% extra to avoid repeated reallocs
+ scratchMemory->reserve(scratchSize + scratchSize / 16);
+ }
+ scratchMemory->resizeNoInitialize(scratchSize);
+ char* memPtr = &scratchMemory->at(0);
+ memHelper.setChunkPointers(memPtr);
+ }
+
+ numConstraints = initBatchedConstraintInfo(conInfos, constraints);
+
+ // compute bounding box around all dynamic bodies
+ // (could be done in parallel)
+ btVector3 bboxMin(BT_LARGE_FLOAT, BT_LARGE_FLOAT, BT_LARGE_FLOAT);
+ btVector3 bboxMax = -bboxMin;
+ //int dynamicBodyCount = 0;
+ for (int i = 0; i < bodies.size(); ++i)
+ {
+ const btSolverBody& body = bodies[i];
+ btVector3 bodyPos = body.getWorldTransform().getOrigin();
+ bool isDynamic = (body.internalGetInvMass().x() > btScalar(0));
+ bodyPositions[i] = bodyPos;
+ bodyDynamicFlags[i] = isDynamic;
+ if (isDynamic)
+ {
+ //dynamicBodyCount++;
+ bboxMin.setMin(bodyPos);
+ bboxMax.setMax(bodyPos);
+ }
+ }
+
+ // find max extent of all dynamic constraints
+ // (could be done in parallel)
+ btVector3 consExtent = findMaxDynamicConstraintExtent(bodyPositions, bodyDynamicFlags, conInfos, numConstraints, bodies.size());
+
+ btVector3 gridExtent = bboxMax - bboxMin;
+
+ btVector3 gridCellSize = consExtent;
+ int gridDim[3];
+ gridDim[0] = int(1.0 + gridExtent.x() / gridCellSize.x());
+ gridDim[1] = int(1.0 + gridExtent.y() / gridCellSize.y());
+ gridDim[2] = int(1.0 + gridExtent.z() / gridCellSize.z());
+
+ // if we can collapse an axis, it will cut our number of phases in half which could be more efficient
+ int phaseMask = 7;
+ bool collapseAxis = use2DGrid;
+ if (collapseAxis)
+ {
+ // pick the smallest axis to collapse, leaving us with the greatest number of cells in our grid
+ int iAxisToCollapse = 0;
+ int axisDim = gridDim[iAxisToCollapse];
+ //for each dimension
+ for (int i = 0; i < 3; ++i)
+ {
+ if (gridDim[i] < axisDim)
+ {
+ iAxisToCollapse = i;
+ axisDim = gridDim[i];
+ }
+ }
+ // collapse it
+ gridCellSize[iAxisToCollapse] = gridExtent[iAxisToCollapse] * 2.0f;
+ phaseMask &= ~(1 << iAxisToCollapse);
+ }
+
+ int numGridChunks = 0;
+ btIntVec3 gridChunkDim; // each chunk is 2x2x2 group of cells
+ while (true)
+ {
+ gridDim[0] = int(1.0 + gridExtent.x() / gridCellSize.x());
+ gridDim[1] = int(1.0 + gridExtent.y() / gridCellSize.y());
+ gridDim[2] = int(1.0 + gridExtent.z() / gridCellSize.z());
+ gridChunkDim[0] = btMax(1, (gridDim[0] + 0) / 2);
+ gridChunkDim[1] = btMax(1, (gridDim[1] + 0) / 2);
+ gridChunkDim[2] = btMax(1, (gridDim[2] + 0) / 2);
+ numGridChunks = gridChunkDim[0] * gridChunkDim[1] * gridChunkDim[2];
+ float nChunks = float(gridChunkDim[0]) * float(gridChunkDim[1]) * float(gridChunkDim[2]); // suceptible to integer overflow
+ if (numGridChunks <= maxGridChunkCount && nChunks <= maxGridChunkCount)
+ {
+ break;
+ }
+ gridCellSize *= 1.25; // should roughly cut numCells in half
+ }
+ btAssert(numGridChunks <= maxGridChunkCount);
+ int maxNumBatchesPerPhase = numGridChunks;
+
+ // for each dynamic body, compute grid coords
+ btVector3 invGridCellSize = btVector3(1, 1, 1) / gridCellSize;
+ // (can be done in parallel)
+ for (int iBody = 0; iBody < bodies.size(); ++iBody)
+ {
+ btIntVec3& coords = bodyGridCoords[iBody];
+ if (bodyDynamicFlags[iBody])
+ {
+ btVector3 v = (bodyPositions[iBody] - bboxMin) * invGridCellSize;
+ coords.m_ints[0] = int(v.x());
+ coords.m_ints[1] = int(v.y());
+ coords.m_ints[2] = int(v.z());
+ btAssert(coords.m_ints[0] >= 0 && coords.m_ints[0] < gridDim[0]);
+ btAssert(coords.m_ints[1] >= 0 && coords.m_ints[1] < gridDim[1]);
+ btAssert(coords.m_ints[2] >= 0 && coords.m_ints[2] < gridDim[2]);
+ }
+ else
+ {
+ coords.m_ints[0] = -1;
+ coords.m_ints[1] = -1;
+ coords.m_ints[2] = -1;
+ }
+ }
+
+ for (int iPhase = 0; iPhase < numPhases; ++iPhase)
+ {
+ int batchBegin = iPhase * maxNumBatchesPerPhase;
+ int batchEnd = batchBegin + maxNumBatchesPerPhase;
+ for (int iBatch = batchBegin; iBatch < batchEnd; ++iBatch)
+ {
+ btBatchInfo& batch = batches[iBatch];
+ batch = btBatchInfo();
+ }
+ }
+
+ {
+ AssignConstraintsToGridBatchesParams params;
+ params.bodyDynamicFlags = bodyDynamicFlags;
+ params.bodyGridCoords = bodyGridCoords;
+ params.numBodies = bodies.size();
+ params.conInfos = conInfos;
+ params.constraintBatchIds = constraintBatchIds;
+ params.gridChunkDim = gridChunkDim;
+ params.maxNumBatchesPerPhase = maxNumBatchesPerPhase;
+ params.numPhases = numPhases;
+ params.phaseMask = phaseMask;
+ bool inParallel = true;
+ if (inParallel)
+ {
+ AssignConstraintsToGridBatchesLoop loop(params);
+ int grainSize = 250;
+ btParallelFor(0, numConstraints, grainSize, loop);
+ }
+ else
+ {
+ assignConstraintsToGridBatches(params, 0, numConstraints);
+ }
+ }
+ for (int iCon = 0; iCon < numConstraints; ++iCon)
+ {
+ const btBatchedConstraintInfo& con = conInfos[iCon];
+ int iBatch = constraintBatchIds[iCon];
+ btBatchInfo& batch = batches[iBatch];
+ batch.numConstraints += con.numConstraintRows;
+ }
+
+ for (int iPhase = 0; iPhase < numPhases; ++iPhase)
+ {
+ // if phase is legit,
+ if (iPhase == (iPhase & phaseMask))
+ {
+ int iBeginBatch = iPhase * maxNumBatchesPerPhase;
+ int iEndBatch = iBeginBatch + maxNumBatchesPerPhase;
+ mergeSmallBatches(batches, iBeginBatch, iEndBatch, minBatchSize, maxBatchSize);
+ }
+ }
+ // all constraints have been assigned a batchId
+ updateConstraintBatchIdsForMergesMt(constraintBatchIds, numConstraints, batches, maxNumBatchesPerPhase * numPhases);
+
+ if (numConstraintRows > numConstraints)
+ {
+ expandConstraintRowsMt(&constraintRowBatchIds[0], &constraintBatchIds[0], &conInfos[0], numConstraints, numConstraintRows);
+ }
+ else
+ {
+ constraintRowBatchIds = constraintBatchIds;
+ }
+
+ writeOutBatches(batchedConstraints, constraintRowBatchIds, numConstraintRows, batches, batchWork, maxNumBatchesPerPhase, numPhases);
+ btAssert(batchedConstraints->validate(constraints, bodies));
}
-
static void setupSingleBatch(
- btBatchedConstraints* bc,
- int numConstraints
-)
+ btBatchedConstraints* bc,
+ int numConstraints)
{
- BT_PROFILE("setupSingleBatch");
- typedef btBatchedConstraints::Range Range;
-
- bc->m_constraintIndices.resize( numConstraints );
- for ( int i = 0; i < numConstraints; ++i )
- {
- bc->m_constraintIndices[ i ] = i;
- }
-
- bc->m_batches.resizeNoInitialize( 0 );
- bc->m_phases.resizeNoInitialize( 0 );
- bc->m_phaseOrder.resizeNoInitialize( 0 );
- bc->m_phaseGrainSize.resizeNoInitialize( 0 );
-
- if (numConstraints > 0)
- {
- bc->m_batches.push_back( Range( 0, numConstraints ) );
- bc->m_phases.push_back( Range( 0, 1 ) );
- bc->m_phaseOrder.push_back(0);
- bc->m_phaseGrainSize.push_back(1);
- }
+ BT_PROFILE("setupSingleBatch");
+ typedef btBatchedConstraints::Range Range;
+
+ bc->m_constraintIndices.resize(numConstraints);
+ for (int i = 0; i < numConstraints; ++i)
+ {
+ bc->m_constraintIndices[i] = i;
+ }
+
+ bc->m_batches.resizeNoInitialize(0);
+ bc->m_phases.resizeNoInitialize(0);
+ bc->m_phaseOrder.resizeNoInitialize(0);
+ bc->m_phaseGrainSize.resizeNoInitialize(0);
+
+ if (numConstraints > 0)
+ {
+ bc->m_batches.push_back(Range(0, numConstraints));
+ bc->m_phases.push_back(Range(0, 1));
+ bc->m_phaseOrder.push_back(0);
+ bc->m_phaseGrainSize.push_back(1);
+ }
}
-
void btBatchedConstraints::setup(
- btConstraintArray* constraints,
- const btAlignedObjectArray<btSolverBody>& bodies,
- BatchingMethod batchingMethod,
- int minBatchSize,
- int maxBatchSize,
- btAlignedObjectArray<char>* scratchMemory
- )
+ btConstraintArray* constraints,
+ const btAlignedObjectArray<btSolverBody>& bodies,
+ BatchingMethod batchingMethod,
+ int minBatchSize,
+ int maxBatchSize,
+ btAlignedObjectArray<char>* scratchMemory)
{
- if (constraints->size() >= minBatchSize*4)
- {
- bool use2DGrid = batchingMethod == BATCHING_METHOD_SPATIAL_GRID_2D;
- setupSpatialGridBatchesMt( this, scratchMemory, constraints, bodies, minBatchSize, maxBatchSize, use2DGrid );
- if (s_debugDrawBatches)
- {
- debugDrawAllBatches( this, constraints, bodies );
- }
- }
- else
- {
- setupSingleBatch( this, constraints->size() );
- }
+ if (constraints->size() >= minBatchSize * 4)
+ {
+ bool use2DGrid = batchingMethod == BATCHING_METHOD_SPATIAL_GRID_2D;
+ setupSpatialGridBatchesMt(this, scratchMemory, constraints, bodies, minBatchSize, maxBatchSize, use2DGrid);
+ if (s_debugDrawBatches)
+ {
+ debugDrawAllBatches(this, constraints, bodies);
+ }
+ }
+ else
+ {
+ setupSingleBatch(this, constraints->size());
+ }
}
-
-
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.h
index 0fd8f31dd4..5d982ca370 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.h
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.h
@@ -21,46 +21,42 @@ subject to the following restrictions:
#include "BulletDynamics/ConstraintSolver/btSolverBody.h"
#include "BulletDynamics/ConstraintSolver/btSolverConstraint.h"
-
class btIDebugDraw;
struct btBatchedConstraints
{
- enum BatchingMethod
- {
- BATCHING_METHOD_SPATIAL_GRID_2D,
- BATCHING_METHOD_SPATIAL_GRID_3D,
- BATCHING_METHOD_COUNT
- };
- struct Range
- {
- int begin;
- int end;
-
- Range() : begin( 0 ), end( 0 ) {}
- Range( int _beg, int _end ) : begin( _beg ), end( _end ) {}
- };
-
- btAlignedObjectArray<int> m_constraintIndices;
- btAlignedObjectArray<Range> m_batches; // each batch is a range of indices in the m_constraintIndices array
- btAlignedObjectArray<Range> m_phases; // each phase is range of indices in the m_batches array
- btAlignedObjectArray<char> m_phaseGrainSize; // max grain size for each phase
- btAlignedObjectArray<int> m_phaseOrder; // phases can be done in any order, so we can randomize the order here
- btIDebugDraw* m_debugDrawer;
-
- static bool s_debugDrawBatches;
-
- btBatchedConstraints() {m_debugDrawer=NULL;}
- void setup( btConstraintArray* constraints,
- const btAlignedObjectArray<btSolverBody>& bodies,
- BatchingMethod batchingMethod,
- int minBatchSize,
- int maxBatchSize,
- btAlignedObjectArray<char>* scratchMemory
- );
- bool validate( btConstraintArray* constraints, const btAlignedObjectArray<btSolverBody>& bodies ) const;
+ enum BatchingMethod
+ {
+ BATCHING_METHOD_SPATIAL_GRID_2D,
+ BATCHING_METHOD_SPATIAL_GRID_3D,
+ BATCHING_METHOD_COUNT
+ };
+ struct Range
+ {
+ int begin;
+ int end;
+
+ Range() : begin(0), end(0) {}
+ Range(int _beg, int _end) : begin(_beg), end(_end) {}
+ };
+
+ btAlignedObjectArray<int> m_constraintIndices;
+ btAlignedObjectArray<Range> m_batches; // each batch is a range of indices in the m_constraintIndices array
+ btAlignedObjectArray<Range> m_phases; // each phase is range of indices in the m_batches array
+ btAlignedObjectArray<char> m_phaseGrainSize; // max grain size for each phase
+ btAlignedObjectArray<int> m_phaseOrder; // phases can be done in any order, so we can randomize the order here
+ btIDebugDraw* m_debugDrawer;
+
+ static bool s_debugDrawBatches;
+
+ btBatchedConstraints() { m_debugDrawer = NULL; }
+ void setup(btConstraintArray* constraints,
+ const btAlignedObjectArray<btSolverBody>& bodies,
+ BatchingMethod batchingMethod,
+ int minBatchSize,
+ int maxBatchSize,
+ btAlignedObjectArray<char>* scratchMemory);
+ bool validate(btConstraintArray* constraints, const btAlignedObjectArray<btSolverBody>& bodies) const;
};
-
-#endif // BT_BATCHED_CONSTRAINTS_H
-
+#endif // BT_BATCHED_CONSTRAINTS_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp
index 0572256f74..10678b2a61 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp
@@ -15,49 +15,37 @@ subject to the following restrictions:
Written by: Marcus Hennix
*/
-
#include "btConeTwistConstraint.h"
#include "BulletDynamics/Dynamics/btRigidBody.h"
#include "LinearMath/btTransformUtil.h"
#include "LinearMath/btMinMax.h"
#include <new>
-
-
//#define CONETWIST_USE_OBSOLETE_SOLVER true
#define CONETWIST_USE_OBSOLETE_SOLVER false
#define CONETWIST_DEF_FIX_THRESH btScalar(.05f)
-
SIMD_FORCE_INLINE btScalar computeAngularImpulseDenominator(const btVector3& axis, const btMatrix3x3& invInertiaWorld)
{
btVector3 vec = axis * invInertiaWorld;
return axis.dot(vec);
}
-
-
-
-btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA,btRigidBody& rbB,
- const btTransform& rbAFrame,const btTransform& rbBFrame)
- :btTypedConstraint(CONETWIST_CONSTRAINT_TYPE, rbA,rbB),m_rbAFrame(rbAFrame),m_rbBFrame(rbBFrame),
- m_angularOnly(false),
- m_useSolveConstraintObsolete(CONETWIST_USE_OBSOLETE_SOLVER)
+btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA, btRigidBody& rbB,
+ const btTransform& rbAFrame, const btTransform& rbBFrame)
+ : btTypedConstraint(CONETWIST_CONSTRAINT_TYPE, rbA, rbB), m_rbAFrame(rbAFrame), m_rbBFrame(rbBFrame), m_angularOnly(false), m_useSolveConstraintObsolete(CONETWIST_USE_OBSOLETE_SOLVER)
{
init();
}
-btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA,const btTransform& rbAFrame)
- :btTypedConstraint(CONETWIST_CONSTRAINT_TYPE,rbA),m_rbAFrame(rbAFrame),
- m_angularOnly(false),
- m_useSolveConstraintObsolete(CONETWIST_USE_OBSOLETE_SOLVER)
+btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA, const btTransform& rbAFrame)
+ : btTypedConstraint(CONETWIST_CONSTRAINT_TYPE, rbA), m_rbAFrame(rbAFrame), m_angularOnly(false), m_useSolveConstraintObsolete(CONETWIST_USE_OBSOLETE_SOLVER)
{
m_rbBFrame = m_rbAFrame;
m_rbBFrame.setOrigin(btVector3(0., 0., 0.));
- init();
+ init();
}
-
void btConeTwistConstraint::init()
{
m_angularOnly = false;
@@ -75,30 +63,29 @@ void btConeTwistConstraint::init()
m_angCFM = btScalar(0.f);
}
-
-void btConeTwistConstraint::getInfo1 (btConstraintInfo1* info)
+void btConeTwistConstraint::getInfo1(btConstraintInfo1* info)
{
if (m_useSolveConstraintObsolete)
{
info->m_numConstraintRows = 0;
info->nub = 0;
- }
+ }
else
{
info->m_numConstraintRows = 3;
info->nub = 3;
- calcAngleInfo2(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getInvInertiaTensorWorld(),m_rbB.getInvInertiaTensorWorld());
- if(m_solveSwingLimit)
+ calcAngleInfo2(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform(), m_rbA.getInvInertiaTensorWorld(), m_rbB.getInvInertiaTensorWorld());
+ if (m_solveSwingLimit)
{
info->m_numConstraintRows++;
info->nub--;
- if((m_swingSpan1 < m_fixThresh) && (m_swingSpan2 < m_fixThresh))
+ if ((m_swingSpan1 < m_fixThresh) && (m_swingSpan2 < m_fixThresh))
{
info->m_numConstraintRows++;
info->nub--;
}
}
- if(m_solveTwistLimit)
+ if (m_solveTwistLimit)
{
info->m_numConstraintRows++;
info->nub--;
@@ -106,90 +93,88 @@ void btConeTwistConstraint::getInfo1 (btConstraintInfo1* info)
}
}
-void btConeTwistConstraint::getInfo1NonVirtual (btConstraintInfo1* info)
+void btConeTwistConstraint::getInfo1NonVirtual(btConstraintInfo1* info)
{
//always reserve 6 rows: object transform is not available on SPU
info->m_numConstraintRows = 6;
info->nub = 0;
-
}
-
-void btConeTwistConstraint::getInfo2 (btConstraintInfo2* info)
+void btConeTwistConstraint::getInfo2(btConstraintInfo2* info)
{
- getInfo2NonVirtual(info,m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getInvInertiaTensorWorld(),m_rbB.getInvInertiaTensorWorld());
+ getInfo2NonVirtual(info, m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform(), m_rbA.getInvInertiaTensorWorld(), m_rbB.getInvInertiaTensorWorld());
}
-void btConeTwistConstraint::getInfo2NonVirtual (btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btMatrix3x3& invInertiaWorldA,const btMatrix3x3& invInertiaWorldB)
+void btConeTwistConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& transA, const btTransform& transB, const btMatrix3x3& invInertiaWorldA, const btMatrix3x3& invInertiaWorldB)
{
- calcAngleInfo2(transA,transB,invInertiaWorldA,invInertiaWorldB);
-
+ calcAngleInfo2(transA, transB, invInertiaWorldA, invInertiaWorldB);
+
btAssert(!m_useSolveConstraintObsolete);
- // set jacobian
- info->m_J1linearAxis[0] = 1;
- info->m_J1linearAxis[info->rowskip+1] = 1;
- info->m_J1linearAxis[2*info->rowskip+2] = 1;
+ // set jacobian
+ info->m_J1linearAxis[0] = 1;
+ info->m_J1linearAxis[info->rowskip + 1] = 1;
+ info->m_J1linearAxis[2 * info->rowskip + 2] = 1;
btVector3 a1 = transA.getBasis() * m_rbAFrame.getOrigin();
{
btVector3* angular0 = (btVector3*)(info->m_J1angularAxis);
- btVector3* angular1 = (btVector3*)(info->m_J1angularAxis+info->rowskip);
- btVector3* angular2 = (btVector3*)(info->m_J1angularAxis+2*info->rowskip);
+ btVector3* angular1 = (btVector3*)(info->m_J1angularAxis + info->rowskip);
+ btVector3* angular2 = (btVector3*)(info->m_J1angularAxis + 2 * info->rowskip);
btVector3 a1neg = -a1;
- a1neg.getSkewSymmetricMatrix(angular0,angular1,angular2);
+ a1neg.getSkewSymmetricMatrix(angular0, angular1, angular2);
}
- info->m_J2linearAxis[0] = -1;
- info->m_J2linearAxis[info->rowskip+1] = -1;
- info->m_J2linearAxis[2*info->rowskip+2] = -1;
+ info->m_J2linearAxis[0] = -1;
+ info->m_J2linearAxis[info->rowskip + 1] = -1;
+ info->m_J2linearAxis[2 * info->rowskip + 2] = -1;
btVector3 a2 = transB.getBasis() * m_rbBFrame.getOrigin();
{
btVector3* angular0 = (btVector3*)(info->m_J2angularAxis);
- btVector3* angular1 = (btVector3*)(info->m_J2angularAxis+info->rowskip);
- btVector3* angular2 = (btVector3*)(info->m_J2angularAxis+2*info->rowskip);
- a2.getSkewSymmetricMatrix(angular0,angular1,angular2);
+ btVector3* angular1 = (btVector3*)(info->m_J2angularAxis + info->rowskip);
+ btVector3* angular2 = (btVector3*)(info->m_J2angularAxis + 2 * info->rowskip);
+ a2.getSkewSymmetricMatrix(angular0, angular1, angular2);
}
- // set right hand side
+ // set right hand side
btScalar linERP = (m_flags & BT_CONETWIST_FLAGS_LIN_ERP) ? m_linERP : info->erp;
- btScalar k = info->fps * linERP;
- int j;
- for (j=0; j<3; j++)
- {
- info->m_constraintError[j*info->rowskip] = k * (a2[j] + transB.getOrigin()[j] - a1[j] - transA.getOrigin()[j]);
- info->m_lowerLimit[j*info->rowskip] = -SIMD_INFINITY;
- info->m_upperLimit[j*info->rowskip] = SIMD_INFINITY;
- if(m_flags & BT_CONETWIST_FLAGS_LIN_CFM)
+ btScalar k = info->fps * linERP;
+ int j;
+ for (j = 0; j < 3; j++)
+ {
+ info->m_constraintError[j * info->rowskip] = k * (a2[j] + transB.getOrigin()[j] - a1[j] - transA.getOrigin()[j]);
+ info->m_lowerLimit[j * info->rowskip] = -SIMD_INFINITY;
+ info->m_upperLimit[j * info->rowskip] = SIMD_INFINITY;
+ if (m_flags & BT_CONETWIST_FLAGS_LIN_CFM)
{
- info->cfm[j*info->rowskip] = m_linCFM;
+ info->cfm[j * info->rowskip] = m_linCFM;
}
- }
+ }
int row = 3;
- int srow = row * info->rowskip;
+ int srow = row * info->rowskip;
btVector3 ax1;
// angular limits
- if(m_solveSwingLimit)
+ if (m_solveSwingLimit)
{
- btScalar *J1 = info->m_J1angularAxis;
- btScalar *J2 = info->m_J2angularAxis;
- if((m_swingSpan1 < m_fixThresh) && (m_swingSpan2 < m_fixThresh))
+ btScalar* J1 = info->m_J1angularAxis;
+ btScalar* J2 = info->m_J2angularAxis;
+ if ((m_swingSpan1 < m_fixThresh) && (m_swingSpan2 < m_fixThresh))
{
- btTransform trA = transA*m_rbAFrame;
+ btTransform trA = transA * m_rbAFrame;
btVector3 p = trA.getBasis().getColumn(1);
btVector3 q = trA.getBasis().getColumn(2);
int srow1 = srow + info->rowskip;
- J1[srow+0] = p[0];
- J1[srow+1] = p[1];
- J1[srow+2] = p[2];
- J1[srow1+0] = q[0];
- J1[srow1+1] = q[1];
- J1[srow1+2] = q[2];
- J2[srow+0] = -p[0];
- J2[srow+1] = -p[1];
- J2[srow+2] = -p[2];
- J2[srow1+0] = -q[0];
- J2[srow1+1] = -q[1];
- J2[srow1+2] = -q[2];
+ J1[srow + 0] = p[0];
+ J1[srow + 1] = p[1];
+ J1[srow + 2] = p[2];
+ J1[srow1 + 0] = q[0];
+ J1[srow1 + 1] = q[1];
+ J1[srow1 + 2] = q[2];
+ J2[srow + 0] = -p[0];
+ J2[srow + 1] = -p[1];
+ J2[srow + 2] = -p[2];
+ J2[srow1 + 0] = -q[0];
+ J2[srow1 + 1] = -q[1];
+ J2[srow1 + 2] = -q[2];
btScalar fact = info->fps * m_relaxationFactor;
- info->m_constraintError[srow] = fact * m_swingAxis.dot(p);
- info->m_constraintError[srow1] = fact * m_swingAxis.dot(q);
+ info->m_constraintError[srow] = fact * m_swingAxis.dot(p);
+ info->m_constraintError[srow1] = fact * m_swingAxis.dot(q);
info->m_lowerLimit[srow] = -SIMD_INFINITY;
info->m_upperLimit[srow] = SIMD_INFINITY;
info->m_lowerLimit[srow1] = -SIMD_INFINITY;
@@ -199,16 +184,16 @@ void btConeTwistConstraint::getInfo2NonVirtual (btConstraintInfo2* info,const bt
else
{
ax1 = m_swingAxis * m_relaxationFactor * m_relaxationFactor;
- J1[srow+0] = ax1[0];
- J1[srow+1] = ax1[1];
- J1[srow+2] = ax1[2];
- J2[srow+0] = -ax1[0];
- J2[srow+1] = -ax1[1];
- J2[srow+2] = -ax1[2];
+ J1[srow + 0] = ax1[0];
+ J1[srow + 1] = ax1[1];
+ J1[srow + 2] = ax1[2];
+ J2[srow + 0] = -ax1[0];
+ J2[srow + 1] = -ax1[1];
+ J2[srow + 2] = -ax1[2];
btScalar k = info->fps * m_biasFactor;
info->m_constraintError[srow] = k * m_swingCorrection;
- if(m_flags & BT_CONETWIST_FLAGS_ANG_CFM)
+ if (m_flags & BT_CONETWIST_FLAGS_ANG_CFM)
{
info->cfm[srow] = m_angCFM;
}
@@ -218,36 +203,35 @@ void btConeTwistConstraint::getInfo2NonVirtual (btConstraintInfo2* info,const bt
srow += info->rowskip;
}
}
- if(m_solveTwistLimit)
+ if (m_solveTwistLimit)
{
ax1 = m_twistAxis * m_relaxationFactor * m_relaxationFactor;
- btScalar *J1 = info->m_J1angularAxis;
- btScalar *J2 = info->m_J2angularAxis;
- J1[srow+0] = ax1[0];
- J1[srow+1] = ax1[1];
- J1[srow+2] = ax1[2];
- J2[srow+0] = -ax1[0];
- J2[srow+1] = -ax1[1];
- J2[srow+2] = -ax1[2];
+ btScalar* J1 = info->m_J1angularAxis;
+ btScalar* J2 = info->m_J2angularAxis;
+ J1[srow + 0] = ax1[0];
+ J1[srow + 1] = ax1[1];
+ J1[srow + 2] = ax1[2];
+ J2[srow + 0] = -ax1[0];
+ J2[srow + 1] = -ax1[1];
+ J2[srow + 2] = -ax1[2];
btScalar k = info->fps * m_biasFactor;
info->m_constraintError[srow] = k * m_twistCorrection;
- if(m_flags & BT_CONETWIST_FLAGS_ANG_CFM)
+ if (m_flags & BT_CONETWIST_FLAGS_ANG_CFM)
{
info->cfm[srow] = m_angCFM;
}
- if(m_twistSpan > 0.0f)
+ if (m_twistSpan > 0.0f)
{
-
- if(m_twistCorrection > 0.0f)
+ if (m_twistCorrection > 0.0f)
{
info->m_lowerLimit[srow] = 0;
info->m_upperLimit[srow] = SIMD_INFINITY;
- }
+ }
else
{
info->m_lowerLimit[srow] = -SIMD_INFINITY;
info->m_upperLimit[srow] = 0;
- }
+ }
}
else
{
@@ -257,22 +241,20 @@ void btConeTwistConstraint::getInfo2NonVirtual (btConstraintInfo2* info,const bt
srow += info->rowskip;
}
}
-
-
-void btConeTwistConstraint::buildJacobian()
+void btConeTwistConstraint::buildJacobian()
{
if (m_useSolveConstraintObsolete)
{
m_appliedImpulse = btScalar(0.);
m_accTwistLimitImpulse = btScalar(0.);
m_accSwingLimitImpulse = btScalar(0.);
- m_accMotorImpulse = btVector3(0.,0.,0.);
+ m_accMotorImpulse = btVector3(0., 0., 0.);
if (!m_angularOnly)
{
- btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin();
- btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin();
+ btVector3 pivotAInW = m_rbA.getCenterOfMassTransform() * m_rbAFrame.getOrigin();
+ btVector3 pivotBInW = m_rbB.getCenterOfMassTransform() * m_rbBFrame.getOrigin();
btVector3 relPos = pivotBInW - pivotAInW;
btVector3 normal[3];
@@ -282,71 +264,68 @@ void btConeTwistConstraint::buildJacobian()
}
else
{
- normal[0].setValue(btScalar(1.0),0,0);
+ normal[0].setValue(btScalar(1.0), 0, 0);
}
btPlaneSpace1(normal[0], normal[1], normal[2]);
- for (int i=0;i<3;i++)
+ for (int i = 0; i < 3; i++)
{
new (&m_jac[i]) btJacobianEntry(
- m_rbA.getCenterOfMassTransform().getBasis().transpose(),
- m_rbB.getCenterOfMassTransform().getBasis().transpose(),
- pivotAInW - m_rbA.getCenterOfMassPosition(),
- pivotBInW - m_rbB.getCenterOfMassPosition(),
- normal[i],
- m_rbA.getInvInertiaDiagLocal(),
- m_rbA.getInvMass(),
- m_rbB.getInvInertiaDiagLocal(),
- m_rbB.getInvMass());
+ m_rbA.getCenterOfMassTransform().getBasis().transpose(),
+ m_rbB.getCenterOfMassTransform().getBasis().transpose(),
+ pivotAInW - m_rbA.getCenterOfMassPosition(),
+ pivotBInW - m_rbB.getCenterOfMassPosition(),
+ normal[i],
+ m_rbA.getInvInertiaDiagLocal(),
+ m_rbA.getInvMass(),
+ m_rbB.getInvInertiaDiagLocal(),
+ m_rbB.getInvMass());
}
}
- calcAngleInfo2(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getInvInertiaTensorWorld(),m_rbB.getInvInertiaTensorWorld());
+ calcAngleInfo2(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform(), m_rbA.getInvInertiaTensorWorld(), m_rbB.getInvInertiaTensorWorld());
}
}
-
-
-void btConeTwistConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep)
+void btConeTwistConstraint::solveConstraintObsolete(btSolverBody& bodyA, btSolverBody& bodyB, btScalar timeStep)
{
- #ifndef __SPU__
+#ifndef __SPU__
if (m_useSolveConstraintObsolete)
{
- btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin();
- btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin();
+ btVector3 pivotAInW = m_rbA.getCenterOfMassTransform() * m_rbAFrame.getOrigin();
+ btVector3 pivotBInW = m_rbB.getCenterOfMassTransform() * m_rbBFrame.getOrigin();
btScalar tau = btScalar(0.3);
//linear part
if (!m_angularOnly)
{
- btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition();
+ btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition();
btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition();
btVector3 vel1;
- bodyA.internalGetVelocityInLocalPointObsolete(rel_pos1,vel1);
+ bodyA.internalGetVelocityInLocalPointObsolete(rel_pos1, vel1);
btVector3 vel2;
- bodyB.internalGetVelocityInLocalPointObsolete(rel_pos2,vel2);
+ bodyB.internalGetVelocityInLocalPointObsolete(rel_pos2, vel2);
btVector3 vel = vel1 - vel2;
- for (int i=0;i<3;i++)
- {
+ for (int i = 0; i < 3; i++)
+ {
const btVector3& normal = m_jac[i].m_linearJointAxis;
btScalar jacDiagABInv = btScalar(1.) / m_jac[i].getDiagonal();
btScalar rel_vel;
rel_vel = normal.dot(vel);
//positional error (zeroth order error)
- btScalar depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal
- btScalar impulse = depth*tau/timeStep * jacDiagABInv - rel_vel * jacDiagABInv;
+ btScalar depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal
+ btScalar impulse = depth * tau / timeStep * jacDiagABInv - rel_vel * jacDiagABInv;
m_appliedImpulse += impulse;
-
+
btVector3 ftorqueAxis1 = rel_pos1.cross(normal);
btVector3 ftorqueAxis2 = rel_pos2.cross(normal);
- bodyA.internalApplyImpulse(normal*m_rbA.getInvMass(), m_rbA.getInvInertiaTensorWorld()*ftorqueAxis1,impulse);
- bodyB.internalApplyImpulse(normal*m_rbB.getInvMass(), m_rbB.getInvInertiaTensorWorld()*ftorqueAxis2,-impulse);
-
+ bodyA.internalApplyImpulse(normal * m_rbA.getInvMass(), m_rbA.getInvInertiaTensorWorld() * ftorqueAxis1, impulse);
+ bodyB.internalApplyImpulse(normal * m_rbB.getInvMass(), m_rbB.getInvInertiaTensorWorld() * ftorqueAxis2, -impulse);
}
}
@@ -356,13 +335,17 @@ void btConeTwistConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolver
// compute current and predicted transforms
btTransform trACur = m_rbA.getCenterOfMassTransform();
btTransform trBCur = m_rbB.getCenterOfMassTransform();
- btVector3 omegaA; bodyA.internalGetAngularVelocity(omegaA);
- btVector3 omegaB; bodyB.internalGetAngularVelocity(omegaB);
- btTransform trAPred; trAPred.setIdentity();
- btVector3 zerovec(0,0,0);
+ btVector3 omegaA;
+ bodyA.internalGetAngularVelocity(omegaA);
+ btVector3 omegaB;
+ bodyB.internalGetAngularVelocity(omegaB);
+ btTransform trAPred;
+ trAPred.setIdentity();
+ btVector3 zerovec(0, 0, 0);
btTransformUtil::integrateTransform(
trACur, zerovec, omegaA, timeStep, trAPred);
- btTransform trBPred; trBPred.setIdentity();
+ btTransform trBPred;
+ trBPred.setIdentity();
btTransformUtil::integrateTransform(
trBCur, zerovec, omegaB, timeStep, trBPred);
@@ -374,7 +357,7 @@ void btConeTwistConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolver
// compute desired omegas in world
btVector3 omegaADes, omegaBDes;
-
+
btTransformUtil::calculateVelocity(trACur, trADes, timeStep, zerovec, omegaADes);
btTransformUtil::calculateVelocity(trBCur, trBDes, timeStep, zerovec, omegaBDes);
@@ -415,10 +398,10 @@ void btConeTwistConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolver
{
btScalar fMaxImpulse = m_maxMotorImpulse;
if (m_bNormalizedMotorStrength)
- fMaxImpulse = fMaxImpulse/kAxisAInv;
+ fMaxImpulse = fMaxImpulse / kAxisAInv;
btVector3 newUnclampedAccImpulse = m_accMotorImpulse + impulse;
- btScalar newUnclampedMag = newUnclampedAccImpulse.length();
+ btScalar newUnclampedMag = newUnclampedAccImpulse.length();
if (newUnclampedMag > fMaxImpulse)
{
newUnclampedAccImpulse.normalize();
@@ -428,31 +411,32 @@ void btConeTwistConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolver
m_accMotorImpulse += impulse;
}
- btScalar impulseMag = impulse.length();
- btVector3 impulseAxis = impulse / impulseMag;
-
- bodyA.internalApplyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*impulseAxis, impulseMag);
- bodyB.internalApplyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*impulseAxis, -impulseMag);
+ btScalar impulseMag = impulse.length();
+ btVector3 impulseAxis = impulse / impulseMag;
+ bodyA.internalApplyImpulse(btVector3(0, 0, 0), m_rbA.getInvInertiaTensorWorld() * impulseAxis, impulseMag);
+ bodyB.internalApplyImpulse(btVector3(0, 0, 0), m_rbB.getInvInertiaTensorWorld() * impulseAxis, -impulseMag);
}
}
- else if (m_damping > SIMD_EPSILON) // no motor: do a little damping
+ else if (m_damping > SIMD_EPSILON) // no motor: do a little damping
{
- btVector3 angVelA; bodyA.internalGetAngularVelocity(angVelA);
- btVector3 angVelB; bodyB.internalGetAngularVelocity(angVelB);
+ btVector3 angVelA;
+ bodyA.internalGetAngularVelocity(angVelA);
+ btVector3 angVelB;
+ bodyB.internalGetAngularVelocity(angVelB);
btVector3 relVel = angVelB - angVelA;
if (relVel.length2() > SIMD_EPSILON)
{
btVector3 relVelAxis = relVel.normalized();
- btScalar m_kDamping = btScalar(1.) /
- (getRigidBodyA().computeAngularImpulseDenominator(relVelAxis) +
- getRigidBodyB().computeAngularImpulseDenominator(relVelAxis));
+ btScalar m_kDamping = btScalar(1.) /
+ (getRigidBodyA().computeAngularImpulseDenominator(relVelAxis) +
+ getRigidBodyB().computeAngularImpulseDenominator(relVelAxis));
btVector3 impulse = m_damping * m_kDamping * relVel;
- btScalar impulseMag = impulse.length();
+ btScalar impulseMag = impulse.length();
btVector3 impulseAxis = impulse / impulseMag;
- bodyA.internalApplyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*impulseAxis, impulseMag);
- bodyB.internalApplyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*impulseAxis, -impulseMag);
+ bodyA.internalApplyImpulse(btVector3(0, 0, 0), m_rbA.getInvInertiaTensorWorld() * impulseAxis, impulseMag);
+ bodyB.internalApplyImpulse(btVector3(0, 0, 0), m_rbB.getInvInertiaTensorWorld() * impulseAxis, -impulseMag);
}
}
@@ -467,7 +451,7 @@ void btConeTwistConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolver
// solve swing limit
if (m_solveSwingLimit)
{
- btScalar amplitude = m_swingLimitRatio * m_swingCorrection*m_biasFactor/timeStep;
+ btScalar amplitude = m_swingLimitRatio * m_swingCorrection * m_biasFactor / timeStep;
btScalar relSwingVel = (angVelB - angVelA).dot(m_swingAxis);
if (relSwingVel > 0)
amplitude += m_swingLimitRatio * relSwingVel * m_relaxationFactor;
@@ -475,7 +459,7 @@ void btConeTwistConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolver
// Clamp the accumulated impulse
btScalar temp = m_accSwingLimitImpulse;
- m_accSwingLimitImpulse = btMax(m_accSwingLimitImpulse + impulseMag, btScalar(0.0) );
+ m_accSwingLimitImpulse = btMax(m_accSwingLimitImpulse + impulseMag, btScalar(0.0));
impulseMag = m_accSwingLimitImpulse - temp;
btVector3 impulse = m_swingAxis * impulseMag;
@@ -491,47 +475,41 @@ void btConeTwistConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolver
impulseMag = impulse.length();
btVector3 noTwistSwingAxis = impulse / impulseMag;
- bodyA.internalApplyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*noTwistSwingAxis, impulseMag);
- bodyB.internalApplyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*noTwistSwingAxis, -impulseMag);
+ bodyA.internalApplyImpulse(btVector3(0, 0, 0), m_rbA.getInvInertiaTensorWorld() * noTwistSwingAxis, impulseMag);
+ bodyB.internalApplyImpulse(btVector3(0, 0, 0), m_rbB.getInvInertiaTensorWorld() * noTwistSwingAxis, -impulseMag);
}
-
// solve twist limit
if (m_solveTwistLimit)
{
- btScalar amplitude = m_twistLimitRatio * m_twistCorrection*m_biasFactor/timeStep;
- btScalar relTwistVel = (angVelB - angVelA).dot( m_twistAxis );
- if (relTwistVel > 0) // only damp when moving towards limit (m_twistAxis flipping is important)
+ btScalar amplitude = m_twistLimitRatio * m_twistCorrection * m_biasFactor / timeStep;
+ btScalar relTwistVel = (angVelB - angVelA).dot(m_twistAxis);
+ if (relTwistVel > 0) // only damp when moving towards limit (m_twistAxis flipping is important)
amplitude += m_twistLimitRatio * relTwistVel * m_relaxationFactor;
btScalar impulseMag = amplitude * m_kTwist;
// Clamp the accumulated impulse
btScalar temp = m_accTwistLimitImpulse;
- m_accTwistLimitImpulse = btMax(m_accTwistLimitImpulse + impulseMag, btScalar(0.0) );
+ m_accTwistLimitImpulse = btMax(m_accTwistLimitImpulse + impulseMag, btScalar(0.0));
impulseMag = m_accTwistLimitImpulse - temp;
- // btVector3 impulse = m_twistAxis * impulseMag;
+ // btVector3 impulse = m_twistAxis * impulseMag;
- bodyA.internalApplyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*m_twistAxis,impulseMag);
- bodyB.internalApplyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*m_twistAxis,-impulseMag);
- }
+ bodyA.internalApplyImpulse(btVector3(0, 0, 0), m_rbA.getInvInertiaTensorWorld() * m_twistAxis, impulseMag);
+ bodyB.internalApplyImpulse(btVector3(0, 0, 0), m_rbB.getInvInertiaTensorWorld() * m_twistAxis, -impulseMag);
+ }
}
}
#else
-btAssert(0);
-#endif //__SPU__
+ btAssert(0);
+#endif //__SPU__
}
-
-
-
-void btConeTwistConstraint::updateRHS(btScalar timeStep)
+void btConeTwistConstraint::updateRHS(btScalar timeStep)
{
(void)timeStep;
-
}
-
#ifndef __SPU__
void btConeTwistConstraint::calcAngleInfo()
{
@@ -540,15 +518,15 @@ void btConeTwistConstraint::calcAngleInfo()
m_solveTwistLimit = false;
m_solveSwingLimit = false;
- btVector3 b1Axis1(0,0,0),b1Axis2(0,0,0),b1Axis3(0,0,0);
- btVector3 b2Axis1(0,0,0),b2Axis2(0,0,0);
+ btVector3 b1Axis1(0, 0, 0), b1Axis2(0, 0, 0), b1Axis3(0, 0, 0);
+ btVector3 b2Axis1(0, 0, 0), b2Axis2(0, 0, 0);
b1Axis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(0);
b2Axis1 = getRigidBodyB().getCenterOfMassTransform().getBasis() * this->m_rbBFrame.getBasis().getColumn(0);
- btScalar swing1=btScalar(0.),swing2 = btScalar(0.);
+ btScalar swing1 = btScalar(0.), swing2 = btScalar(0.);
- btScalar swx=btScalar(0.),swy = btScalar(0.);
+ btScalar swx = btScalar(0.), swy = btScalar(0.);
btScalar thresh = btScalar(10.);
btScalar fact;
@@ -558,33 +536,33 @@ void btConeTwistConstraint::calcAngleInfo()
b1Axis2 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(1);
swx = b2Axis1.dot(b1Axis1);
swy = b2Axis1.dot(b1Axis2);
- swing1 = btAtan2Fast(swy, swx);
- fact = (swy*swy + swx*swx) * thresh * thresh;
+ swing1 = btAtan2Fast(swy, swx);
+ fact = (swy * swy + swx * swx) * thresh * thresh;
fact = fact / (fact + btScalar(1.0));
- swing1 *= fact;
+ swing1 *= fact;
}
if (m_swingSpan2 >= btScalar(0.05f))
{
- b1Axis3 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(2);
+ b1Axis3 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(2);
swx = b2Axis1.dot(b1Axis1);
swy = b2Axis1.dot(b1Axis3);
- swing2 = btAtan2Fast(swy, swx);
- fact = (swy*swy + swx*swx) * thresh * thresh;
+ swing2 = btAtan2Fast(swy, swx);
+ fact = (swy * swy + swx * swx) * thresh * thresh;
fact = fact / (fact + btScalar(1.0));
- swing2 *= fact;
+ swing2 *= fact;
}
- btScalar RMaxAngle1Sq = 1.0f / (m_swingSpan1*m_swingSpan1);
- btScalar RMaxAngle2Sq = 1.0f / (m_swingSpan2*m_swingSpan2);
- btScalar EllipseAngle = btFabs(swing1*swing1)* RMaxAngle1Sq + btFabs(swing2*swing2) * RMaxAngle2Sq;
+ btScalar RMaxAngle1Sq = 1.0f / (m_swingSpan1 * m_swingSpan1);
+ btScalar RMaxAngle2Sq = 1.0f / (m_swingSpan2 * m_swingSpan2);
+ btScalar EllipseAngle = btFabs(swing1 * swing1) * RMaxAngle1Sq + btFabs(swing2 * swing2) * RMaxAngle2Sq;
if (EllipseAngle > 1.0f)
{
- m_swingCorrection = EllipseAngle-1.0f;
+ m_swingCorrection = EllipseAngle - 1.0f;
m_solveSwingLimit = true;
// Calculate necessary axis & factors
- m_swingAxis = b2Axis1.cross(b1Axis2* b2Axis1.dot(b1Axis2) + b1Axis3* b2Axis1.dot(b1Axis3));
+ m_swingAxis = b2Axis1.cross(b1Axis2 * b2Axis1.dot(b1Axis2) + b1Axis3 * b2Axis1.dot(b1Axis3));
m_swingAxis.normalize();
btScalar swingAxisSign = (b2Axis1.dot(b1Axis1) >= 0.0f) ? 1.0f : -1.0f;
m_swingAxis *= swingAxisSign;
@@ -594,14 +572,14 @@ void btConeTwistConstraint::calcAngleInfo()
if (m_twistSpan >= btScalar(0.))
{
btVector3 b2Axis2 = getRigidBodyB().getCenterOfMassTransform().getBasis() * this->m_rbBFrame.getBasis().getColumn(1);
- btQuaternion rotationArc = shortestArcQuat(b2Axis1,b1Axis1);
- btVector3 TwistRef = quatRotate(rotationArc,b2Axis2);
- btScalar twist = btAtan2Fast( TwistRef.dot(b1Axis3), TwistRef.dot(b1Axis2) );
+ btQuaternion rotationArc = shortestArcQuat(b2Axis1, b1Axis1);
+ btVector3 TwistRef = quatRotate(rotationArc, b2Axis2);
+ btScalar twist = btAtan2Fast(TwistRef.dot(b1Axis3), TwistRef.dot(b1Axis2));
m_twistAngle = twist;
-// btScalar lockedFreeFactor = (m_twistSpan > btScalar(0.05f)) ? m_limitSoftness : btScalar(0.);
+ // btScalar lockedFreeFactor = (m_twistSpan > btScalar(0.05f)) ? m_limitSoftness : btScalar(0.);
btScalar lockedFreeFactor = (m_twistSpan > btScalar(0.05f)) ? btScalar(1.0f) : btScalar(0.);
- if (twist <= -m_twistSpan*lockedFreeFactor)
+ if (twist <= -m_twistSpan * lockedFreeFactor)
{
m_twistCorrection = -(twist + m_twistSpan);
m_solveTwistLimit = true;
@@ -609,7 +587,7 @@ void btConeTwistConstraint::calcAngleInfo()
m_twistAxis.normalize();
m_twistAxis *= -1.0f;
}
- else if (twist > m_twistSpan*lockedFreeFactor)
+ else if (twist > m_twistSpan * lockedFreeFactor)
{
m_twistCorrection = (twist - m_twistSpan);
m_solveTwistLimit = true;
@@ -618,13 +596,11 @@ void btConeTwistConstraint::calcAngleInfo()
}
}
}
-#endif //__SPU__
-
-static btVector3 vTwist(1,0,0); // twist axis in constraint's space
+#endif //__SPU__
+static btVector3 vTwist(1, 0, 0); // twist axis in constraint's space
-
-void btConeTwistConstraint::calcAngleInfo2(const btTransform& transA, const btTransform& transB, const btMatrix3x3& invInertiaWorldA,const btMatrix3x3& invInertiaWorldB)
+void btConeTwistConstraint::calcAngleInfo2(const btTransform& transA, const btTransform& transB, const btMatrix3x3& invInertiaWorldA, const btMatrix3x3& invInertiaWorldB)
{
m_swingCorrection = btScalar(0.);
m_twistLimitSign = btScalar(0.);
@@ -632,7 +608,7 @@ void btConeTwistConstraint::calcAngleInfo2(const btTransform& transA, const btTr
m_solveSwingLimit = false;
// compute rotation of A wrt B (in constraint space)
if (m_bMotorEnabled && (!m_useSolveConstraintObsolete))
- { // it is assumed that setMotorTarget() was alredy called
+ { // it is assumed that setMotorTarget() was alredy called
// and motor target m_qTarget is within constraint limits
// TODO : split rotation to pure swing and pure twist
// compute desired transforms in world
@@ -641,23 +617,22 @@ void btConeTwistConstraint::calcAngleInfo2(const btTransform& transA, const btTr
btTransform trB = transB * m_rbBFrame;
btTransform trDeltaAB = trB * trPose * trA.inverse();
btQuaternion qDeltaAB = trDeltaAB.getRotation();
- btVector3 swingAxis = btVector3(qDeltaAB.x(), qDeltaAB.y(), qDeltaAB.z());
+ btVector3 swingAxis = btVector3(qDeltaAB.x(), qDeltaAB.y(), qDeltaAB.z());
btScalar swingAxisLen2 = swingAxis.length2();
- if(btFuzzyZero(swingAxisLen2))
+ if (btFuzzyZero(swingAxisLen2))
{
- return;
+ return;
}
m_swingAxis = swingAxis;
m_swingAxis.normalize();
m_swingCorrection = qDeltaAB.getAngle();
- if(!btFuzzyZero(m_swingCorrection))
+ if (!btFuzzyZero(m_swingCorrection))
{
m_solveSwingLimit = true;
}
return;
}
-
{
// compute rotation of A wrt B (in constraint space)
btQuaternion qA = transA.getRotation() * m_rbAFrame.getRotation();
@@ -665,13 +640,17 @@ void btConeTwistConstraint::calcAngleInfo2(const btTransform& transA, const btTr
btQuaternion qAB = qB.inverse() * qA;
// split rotation into cone and twist
// (all this is done from B's perspective. Maybe I should be averaging axes...)
- btVector3 vConeNoTwist = quatRotate(qAB, vTwist); vConeNoTwist.normalize();
- btQuaternion qABCone = shortestArcQuat(vTwist, vConeNoTwist); qABCone.normalize();
- btQuaternion qABTwist = qABCone.inverse() * qAB; qABTwist.normalize();
+ btVector3 vConeNoTwist = quatRotate(qAB, vTwist);
+ vConeNoTwist.normalize();
+ btQuaternion qABCone = shortestArcQuat(vTwist, vConeNoTwist);
+ qABCone.normalize();
+ btQuaternion qABTwist = qABCone.inverse() * qAB;
+ qABTwist.normalize();
if (m_swingSpan1 >= m_fixThresh && m_swingSpan2 >= m_fixThresh)
{
- btScalar swingAngle, swingLimit = 0; btVector3 swingAxis;
+ btScalar swingAngle, swingLimit = 0;
+ btVector3 swingAxis;
computeConeLimitInfo(qABCone, swingAngle, swingAxis, swingLimit);
if (swingAngle > swingLimit * m_limitSoftness)
@@ -684,9 +663,9 @@ void btConeTwistConstraint::calcAngleInfo2(const btTransform& transA, const btTr
m_swingLimitRatio = 1.f;
if (swingAngle < swingLimit && m_limitSoftness < 1.f - SIMD_EPSILON)
{
- m_swingLimitRatio = (swingAngle - swingLimit * m_limitSoftness)/
+ m_swingLimitRatio = (swingAngle - swingLimit * m_limitSoftness) /
(swingLimit - swingLimit * m_limitSoftness);
- }
+ }
// swing correction tries to get back to soft limit
m_swingCorrection = swingAngle - (swingLimit * m_limitSoftness);
@@ -694,14 +673,14 @@ void btConeTwistConstraint::calcAngleInfo2(const btTransform& transA, const btTr
// adjustment of swing axis (based on ellipse normal)
adjustSwingAxisToUseEllipseNormal(swingAxis);
- // Calculate necessary axis & factors
+ // Calculate necessary axis & factors
m_swingAxis = quatRotate(qB, -swingAxis);
- m_twistAxisA.setValue(0,0,0);
+ m_twistAxisA.setValue(0, 0, 0);
- m_kSwing = btScalar(1.) /
- (computeAngularImpulseDenominator(m_swingAxis,invInertiaWorldA) +
- computeAngularImpulseDenominator(m_swingAxis,invInertiaWorldB));
+ m_kSwing = btScalar(1.) /
+ (computeAngularImpulseDenominator(m_swingAxis, invInertiaWorldA) +
+ computeAngularImpulseDenominator(m_swingAxis, invInertiaWorldB));
}
}
else
@@ -717,9 +696,9 @@ void btConeTwistConstraint::calcAngleInfo2(const btTransform& transA, const btTr
btScalar x = ivB.dot(ivA);
btScalar y = ivB.dot(jvA);
btScalar z = ivB.dot(kvA);
- if((m_swingSpan1 < m_fixThresh) && (m_swingSpan2 < m_fixThresh))
- { // fixed. We'll need to add one more row to constraint
- if((!btFuzzyZero(y)) || (!(btFuzzyZero(z))))
+ if ((m_swingSpan1 < m_fixThresh) && (m_swingSpan2 < m_fixThresh))
+ { // fixed. We'll need to add one more row to constraint
+ if ((!btFuzzyZero(y)) || (!(btFuzzyZero(z))))
{
m_solveSwingLimit = true;
m_swingAxis = -ivB.cross(ivA);
@@ -727,47 +706,47 @@ void btConeTwistConstraint::calcAngleInfo2(const btTransform& transA, const btTr
}
else
{
- if(m_swingSpan1 < m_fixThresh)
- { // hinge around Y axis
-// if(!(btFuzzyZero(y)))
- if((!(btFuzzyZero(x))) || (!(btFuzzyZero(z))))
+ if (m_swingSpan1 < m_fixThresh)
+ { // hinge around Y axis
+ // if(!(btFuzzyZero(y)))
+ if ((!(btFuzzyZero(x))) || (!(btFuzzyZero(z))))
{
m_solveSwingLimit = true;
- if(m_swingSpan2 >= m_fixThresh)
+ if (m_swingSpan2 >= m_fixThresh)
{
y = btScalar(0.f);
btScalar span2 = btAtan2(z, x);
- if(span2 > m_swingSpan2)
+ if (span2 > m_swingSpan2)
{
x = btCos(m_swingSpan2);
z = btSin(m_swingSpan2);
}
- else if(span2 < -m_swingSpan2)
+ else if (span2 < -m_swingSpan2)
{
- x = btCos(m_swingSpan2);
+ x = btCos(m_swingSpan2);
z = -btSin(m_swingSpan2);
}
}
}
}
else
- { // hinge around Z axis
-// if(!btFuzzyZero(z))
- if((!(btFuzzyZero(x))) || (!(btFuzzyZero(y))))
+ { // hinge around Z axis
+ // if(!btFuzzyZero(z))
+ if ((!(btFuzzyZero(x))) || (!(btFuzzyZero(y))))
{
m_solveSwingLimit = true;
- if(m_swingSpan1 >= m_fixThresh)
+ if (m_swingSpan1 >= m_fixThresh)
{
z = btScalar(0.f);
btScalar span1 = btAtan2(y, x);
- if(span1 > m_swingSpan1)
+ if (span1 > m_swingSpan1)
{
x = btCos(m_swingSpan1);
y = btSin(m_swingSpan1);
}
- else if(span1 < -m_swingSpan1)
+ else if (span1 < -m_swingSpan1)
{
- x = btCos(m_swingSpan1);
+ x = btCos(m_swingSpan1);
y = -btSin(m_swingSpan1);
}
}
@@ -778,10 +757,10 @@ void btConeTwistConstraint::calcAngleInfo2(const btTransform& transA, const btTr
target[2] = x * ivA[2] + y * jvA[2] + z * kvA[2];
target.normalize();
m_swingAxis = -ivB.cross(target);
- m_swingCorrection = m_swingAxis.length();
+ m_swingCorrection = m_swingAxis.length();
- if (!btFuzzyZero(m_swingCorrection))
- m_swingAxis.normalize();
+ if (!btFuzzyZero(m_swingCorrection))
+ m_swingAxis.normalize();
}
}
@@ -790,15 +769,15 @@ void btConeTwistConstraint::calcAngleInfo2(const btTransform& transA, const btTr
btVector3 twistAxis;
computeTwistLimitInfo(qABTwist, m_twistAngle, twistAxis);
- if (m_twistAngle > m_twistSpan*m_limitSoftness)
+ if (m_twistAngle > m_twistSpan * m_limitSoftness)
{
m_solveTwistLimit = true;
m_twistLimitRatio = 1.f;
if (m_twistAngle < m_twistSpan && m_limitSoftness < 1.f - SIMD_EPSILON)
{
- m_twistLimitRatio = (m_twistAngle - m_twistSpan * m_limitSoftness)/
- (m_twistSpan - m_twistSpan * m_limitSoftness);
+ m_twistLimitRatio = (m_twistAngle - m_twistSpan * m_limitSoftness) /
+ (m_twistSpan - m_twistSpan * m_limitSoftness);
}
// twist correction tries to get back to soft limit
@@ -807,8 +786,8 @@ void btConeTwistConstraint::calcAngleInfo2(const btTransform& transA, const btTr
m_twistAxis = quatRotate(qB, -twistAxis);
m_kTwist = btScalar(1.) /
- (computeAngularImpulseDenominator(m_twistAxis,invInertiaWorldA) +
- computeAngularImpulseDenominator(m_twistAxis,invInertiaWorldB));
+ (computeAngularImpulseDenominator(m_twistAxis, invInertiaWorldA) +
+ computeAngularImpulseDenominator(m_twistAxis, invInertiaWorldB));
}
if (m_solveSwingLimit)
@@ -821,15 +800,13 @@ void btConeTwistConstraint::calcAngleInfo2(const btTransform& transA, const btTr
}
}
-
-
// given a cone rotation in constraint space, (pre: twist must already be removed)
// this method computes its corresponding swing angle and axis.
// more interestingly, it computes the cone/swing limit (angle) for this cone "pose".
void btConeTwistConstraint::computeConeLimitInfo(const btQuaternion& qCone,
- btScalar& swingAngle, // out
- btVector3& vSwingAxis, // out
- btScalar& swingLimit) // out
+ btScalar& swingAngle, // out
+ btVector3& vSwingAxis, // out
+ btScalar& swingLimit) // out
{
swingAngle = qCone.getAngle();
if (swingAngle > SIMD_EPSILON)
@@ -840,7 +817,7 @@ void btConeTwistConstraint::computeConeLimitInfo(const btQuaternion& qCone,
// non-zero twist?! this should never happen.
btAssert(fabs(vSwingAxis.x()) <= SIMD_EPSILON));
#endif
-
+
// Compute limit for given swing. tricky:
// Given a swing axis, we're looking for the intersection with the bounding cone ellipse.
// (Since we're dealing with angles, this ellipse is embedded on the surface of a sphere.)
@@ -848,7 +825,7 @@ void btConeTwistConstraint::computeConeLimitInfo(const btQuaternion& qCone,
// For starters, compute the direction from center to surface of ellipse.
// This is just the perpendicular (ie. rotate 2D vector by PI/2) of the swing axis.
// (vSwingAxis is the cone rotation (in z,y); change vars and rotate to (x,y) coords.)
- btScalar xEllipse = vSwingAxis.y();
+ btScalar xEllipse = vSwingAxis.y();
btScalar yEllipse = -vSwingAxis.z();
// Now, we use the slope of the vector (using x/yEllipse) and find the length
@@ -858,10 +835,10 @@ void btConeTwistConstraint::computeConeLimitInfo(const btQuaternion& qCone,
// a^2 b^2
// Do the math and it should be clear.
- swingLimit = m_swingSpan1; // if xEllipse == 0, we have a pure vSwingAxis.z rotation: just use swingspan1
+ swingLimit = m_swingSpan1; // if xEllipse == 0, we have a pure vSwingAxis.z rotation: just use swingspan1
if (fabs(xEllipse) > SIMD_EPSILON)
{
- btScalar surfaceSlope2 = (yEllipse*yEllipse)/(xEllipse*xEllipse);
+ btScalar surfaceSlope2 = (yEllipse * yEllipse) / (xEllipse * xEllipse);
btScalar norm = 1 / (m_swingSpan2 * m_swingSpan2);
norm += surfaceSlope2 / (m_swingSpan1 * m_swingSpan1);
btScalar swingLimit2 = (1 + surfaceSlope2) / norm;
@@ -887,7 +864,7 @@ void btConeTwistConstraint::computeConeLimitInfo(const btQuaternion& qCone,
#if 0
btAssert(0);
#endif
- }
+ }
}
btVector3 btConeTwistConstraint::GetPointForAngle(btScalar fAngleInRadians, btScalar fLength) const
@@ -903,10 +880,10 @@ btVector3 btConeTwistConstraint::GetPointForAngle(btScalar fAngleInRadians, btSc
// a^2 b^2
// Do the math and it should be clear.
- btScalar swingLimit = m_swingSpan1; // if xEllipse == 0, just use axis b (1)
+ btScalar swingLimit = m_swingSpan1; // if xEllipse == 0, just use axis b (1)
if (fabs(xEllipse) > SIMD_EPSILON)
{
- btScalar surfaceSlope2 = (yEllipse*yEllipse)/(xEllipse*xEllipse);
+ btScalar surfaceSlope2 = (yEllipse * yEllipse) / (xEllipse * xEllipse);
btScalar norm = 1 / (m_swingSpan2 * m_swingSpan2);
norm += surfaceSlope2 / (m_swingSpan1 * m_swingSpan1);
btScalar swingLimit2 = (1 + surfaceSlope2) / norm;
@@ -917,20 +894,20 @@ btVector3 btConeTwistConstraint::GetPointForAngle(btScalar fAngleInRadians, btSc
// note: twist is x-axis, swing 1 and 2 are along the z and y axes respectively
btVector3 vSwingAxis(0, xEllipse, -yEllipse);
btQuaternion qSwing(vSwingAxis, swingLimit);
- btVector3 vPointInConstraintSpace(fLength,0,0);
+ btVector3 vPointInConstraintSpace(fLength, 0, 0);
return quatRotate(qSwing, vPointInConstraintSpace);
}
// given a twist rotation in constraint space, (pre: cone must already be removed)
// this method computes its corresponding angle and axis.
void btConeTwistConstraint::computeTwistLimitInfo(const btQuaternion& qTwist,
- btScalar& twistAngle, // out
- btVector3& vTwistAxis) // out
+ btScalar& twistAngle, // out
+ btVector3& vTwistAxis) // out
{
btQuaternion qMinTwist = qTwist;
twistAngle = qTwist.getAngle();
- if (twistAngle > SIMD_PI) // long way around. flip quat and recalculate.
+ if (twistAngle > SIMD_PI) // long way around. flip quat and recalculate.
{
qMinTwist = -(qTwist);
twistAngle = qMinTwist.getAngle();
@@ -948,80 +925,79 @@ void btConeTwistConstraint::computeTwistLimitInfo(const btQuaternion& qTwist,
vTwistAxis.normalize();
}
-
void btConeTwistConstraint::adjustSwingAxisToUseEllipseNormal(btVector3& vSwingAxis) const
{
// the swing axis is computed as the "twist-free" cone rotation,
// but the cone limit is not circular, but elliptical (if swingspan1 != swingspan2).
- // so, if we're outside the limits, the closest way back inside the cone isn't
+ // so, if we're outside the limits, the closest way back inside the cone isn't
// along the vector back to the center. better (and more stable) to use the ellipse normal.
// convert swing axis to direction from center to surface of ellipse
// (ie. rotate 2D vector by PI/2)
btScalar y = -vSwingAxis.z();
- btScalar z = vSwingAxis.y();
+ btScalar z = vSwingAxis.y();
// do the math...
- if (fabs(z) > SIMD_EPSILON) // avoid division by 0. and we don't need an update if z == 0.
+ if (fabs(z) > SIMD_EPSILON) // avoid division by 0. and we don't need an update if z == 0.
{
// compute gradient/normal of ellipse surface at current "point"
- btScalar grad = y/z;
+ btScalar grad = y / z;
grad *= m_swingSpan2 / m_swingSpan1;
// adjust y/z to represent normal at point (instead of vector to point)
if (y > 0)
- y = fabs(grad * z);
+ y = fabs(grad * z);
else
y = -fabs(grad * z);
// convert ellipse direction back to swing axis
vSwingAxis.setZ(-y);
- vSwingAxis.setY( z);
+ vSwingAxis.setY(z);
vSwingAxis.normalize();
}
}
-
-
-void btConeTwistConstraint::setMotorTarget(const btQuaternion &q)
+void btConeTwistConstraint::setMotorTarget(const btQuaternion& q)
{
//btTransform trACur = m_rbA.getCenterOfMassTransform();
//btTransform trBCur = m_rbB.getCenterOfMassTransform();
-// btTransform trABCur = trBCur.inverse() * trACur;
-// btQuaternion qABCur = trABCur.getRotation();
-// btTransform trConstraintCur = (trBCur * m_rbBFrame).inverse() * (trACur * m_rbAFrame);
+ // btTransform trABCur = trBCur.inverse() * trACur;
+ // btQuaternion qABCur = trABCur.getRotation();
+ // btTransform trConstraintCur = (trBCur * m_rbBFrame).inverse() * (trACur * m_rbAFrame);
//btQuaternion qConstraintCur = trConstraintCur.getRotation();
btQuaternion qConstraint = m_rbBFrame.getRotation().inverse() * q * m_rbAFrame.getRotation();
setMotorTargetInConstraintSpace(qConstraint);
}
-
-void btConeTwistConstraint::setMotorTargetInConstraintSpace(const btQuaternion &q)
+void btConeTwistConstraint::setMotorTargetInConstraintSpace(const btQuaternion& q)
{
m_qTarget = q;
// clamp motor target to within limits
{
- btScalar softness = 1.f;//m_limitSoftness;
+ btScalar softness = 1.f; //m_limitSoftness;
// split into twist and cone
btVector3 vTwisted = quatRotate(m_qTarget, vTwist);
- btQuaternion qTargetCone = shortestArcQuat(vTwist, vTwisted); qTargetCone.normalize();
- btQuaternion qTargetTwist = qTargetCone.inverse() * m_qTarget; qTargetTwist.normalize();
+ btQuaternion qTargetCone = shortestArcQuat(vTwist, vTwisted);
+ qTargetCone.normalize();
+ btQuaternion qTargetTwist = qTargetCone.inverse() * m_qTarget;
+ qTargetTwist.normalize();
// clamp cone
if (m_swingSpan1 >= btScalar(0.05f) && m_swingSpan2 >= btScalar(0.05f))
{
- btScalar swingAngle, swingLimit; btVector3 swingAxis;
+ btScalar swingAngle, swingLimit;
+ btVector3 swingAxis;
computeConeLimitInfo(qTargetCone, swingAngle, swingAxis, swingLimit);
if (fabs(swingAngle) > SIMD_EPSILON)
{
- if (swingAngle > swingLimit*softness)
- swingAngle = swingLimit*softness;
- else if (swingAngle < -swingLimit*softness)
- swingAngle = -swingLimit*softness;
+ if (swingAngle > swingLimit * softness)
+ swingAngle = swingLimit * softness;
+ else if (swingAngle < -swingLimit * softness)
+ swingAngle = -swingLimit * softness;
qTargetCone = btQuaternion(swingAxis, swingAngle);
}
}
@@ -1029,16 +1005,17 @@ void btConeTwistConstraint::setMotorTargetInConstraintSpace(const btQuaternion &
// clamp twist
if (m_twistSpan >= btScalar(0.05f))
{
- btScalar twistAngle; btVector3 twistAxis;
+ btScalar twistAngle;
+ btVector3 twistAxis;
computeTwistLimitInfo(qTargetTwist, twistAngle, twistAxis);
if (fabs(twistAngle) > SIMD_EPSILON)
{
// eddy todo: limitSoftness used here???
- if (twistAngle > m_twistSpan*softness)
- twistAngle = m_twistSpan*softness;
- else if (twistAngle < -m_twistSpan*softness)
- twistAngle = -m_twistSpan*softness;
+ if (twistAngle > m_twistSpan * softness)
+ twistAngle = m_twistSpan * softness;
+ else if (twistAngle < -m_twistSpan * softness)
+ twistAngle = -m_twistSpan * softness;
qTargetTwist = btQuaternion(twistAxis, twistAngle);
}
}
@@ -1047,15 +1024,15 @@ void btConeTwistConstraint::setMotorTargetInConstraintSpace(const btQuaternion &
}
}
-///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
///If no axis is provided, it uses the default axis for this constraint.
void btConeTwistConstraint::setParam(int num, btScalar value, int axis)
{
- switch(num)
+ switch (num)
{
- case BT_CONSTRAINT_ERP :
- case BT_CONSTRAINT_STOP_ERP :
- if((axis >= 0) && (axis < 3))
+ case BT_CONSTRAINT_ERP:
+ case BT_CONSTRAINT_STOP_ERP:
+ if ((axis >= 0) && (axis < 3))
{
m_linERP = value;
m_flags |= BT_CONETWIST_FLAGS_LIN_ERP;
@@ -1065,9 +1042,9 @@ void btConeTwistConstraint::setParam(int num, btScalar value, int axis)
m_biasFactor = value;
}
break;
- case BT_CONSTRAINT_CFM :
- case BT_CONSTRAINT_STOP_CFM :
- if((axis >= 0) && (axis < 3))
+ case BT_CONSTRAINT_CFM:
+ case BT_CONSTRAINT_STOP_CFM:
+ if ((axis >= 0) && (axis < 3))
{
m_linCFM = value;
m_flags |= BT_CONETWIST_FLAGS_LIN_CFM;
@@ -1085,19 +1062,19 @@ void btConeTwistConstraint::setParam(int num, btScalar value, int axis)
}
///return the local value of parameter
-btScalar btConeTwistConstraint::getParam(int num, int axis) const
+btScalar btConeTwistConstraint::getParam(int num, int axis) const
{
btScalar retVal = 0;
- switch(num)
+ switch (num)
{
- case BT_CONSTRAINT_ERP :
- case BT_CONSTRAINT_STOP_ERP :
- if((axis >= 0) && (axis < 3))
+ case BT_CONSTRAINT_ERP:
+ case BT_CONSTRAINT_STOP_ERP:
+ if ((axis >= 0) && (axis < 3))
{
btAssertConstrParams(m_flags & BT_CONETWIST_FLAGS_LIN_ERP);
retVal = m_linERP;
}
- else if((axis >= 3) && (axis < 6))
+ else if ((axis >= 3) && (axis < 6))
{
retVal = m_biasFactor;
}
@@ -1106,14 +1083,14 @@ btScalar btConeTwistConstraint::getParam(int num, int axis) const
btAssertConstrParams(0);
}
break;
- case BT_CONSTRAINT_CFM :
- case BT_CONSTRAINT_STOP_CFM :
- if((axis >= 0) && (axis < 3))
+ case BT_CONSTRAINT_CFM:
+ case BT_CONSTRAINT_STOP_CFM:
+ if ((axis >= 0) && (axis < 3))
{
btAssertConstrParams(m_flags & BT_CONETWIST_FLAGS_LIN_CFM);
retVal = m_linCFM;
}
- else if((axis >= 3) && (axis < 6))
+ else if ((axis >= 3) && (axis < 6))
{
btAssertConstrParams(m_flags & BT_CONETWIST_FLAGS_ANG_CFM);
retVal = m_angCFM;
@@ -1123,21 +1100,16 @@ btScalar btConeTwistConstraint::getParam(int num, int axis) const
btAssertConstrParams(0);
}
break;
- default :
+ default:
btAssertConstrParams(0);
}
return retVal;
}
-
-void btConeTwistConstraint::setFrames(const btTransform & frameA, const btTransform & frameB)
+void btConeTwistConstraint::setFrames(const btTransform& frameA, const btTransform& frameB)
{
m_rbAFrame = frameA;
m_rbBFrame = frameB;
buildJacobian();
//calculateTransforms();
}
-
-
-
-
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h
index 7a33d01d1e..64f44df1cb 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h
@@ -15,8 +15,6 @@ subject to the following restrictions:
Written by: Marcus Hennix
*/
-
-
/*
Overview:
@@ -31,8 +29,6 @@ twist is along the x-axis,
and swing 1 and 2 are along the z and y axes respectively.
*/
-
-
#ifndef BT_CONETWISTCONSTRAINT_H
#define BT_CONETWISTCONSTRAINT_H
@@ -41,13 +37,12 @@ and swing 1 and 2 are along the z and y axes respectively.
#include "btTypedConstraint.h"
#ifdef BT_USE_DOUBLE_PRECISION
-#define btConeTwistConstraintData2 btConeTwistConstraintDoubleData
-#define btConeTwistConstraintDataName "btConeTwistConstraintDoubleData"
+#define btConeTwistConstraintData2 btConeTwistConstraintDoubleData
+#define btConeTwistConstraintDataName "btConeTwistConstraintDoubleData"
#else
-#define btConeTwistConstraintData2 btConeTwistConstraintData
-#define btConeTwistConstraintDataName "btConeTwistConstraintData"
-#endif //BT_USE_DOUBLE_PRECISION
-
+#define btConeTwistConstraintData2 btConeTwistConstraintData
+#define btConeTwistConstraintDataName "btConeTwistConstraintData"
+#endif //BT_USE_DOUBLE_PRECISION
class btRigidBody;
@@ -59,103 +54,99 @@ enum btConeTwistFlags
};
///btConeTwistConstraint can be used to simulate ragdoll joints (upper arm, leg etc)
-ATTRIBUTE_ALIGNED16(class) btConeTwistConstraint : public btTypedConstraint
+ATTRIBUTE_ALIGNED16(class)
+btConeTwistConstraint : public btTypedConstraint
{
#ifdef IN_PARALLELL_SOLVER
public:
#endif
- btJacobianEntry m_jac[3]; //3 orthogonal linear constraints
+ btJacobianEntry m_jac[3]; //3 orthogonal linear constraints
- btTransform m_rbAFrame;
+ btTransform m_rbAFrame;
btTransform m_rbBFrame;
- btScalar m_limitSoftness;
- btScalar m_biasFactor;
- btScalar m_relaxationFactor;
+ btScalar m_limitSoftness;
+ btScalar m_biasFactor;
+ btScalar m_relaxationFactor;
- btScalar m_damping;
+ btScalar m_damping;
- btScalar m_swingSpan1;
- btScalar m_swingSpan2;
- btScalar m_twistSpan;
+ btScalar m_swingSpan1;
+ btScalar m_swingSpan2;
+ btScalar m_twistSpan;
- btScalar m_fixThresh;
+ btScalar m_fixThresh;
- btVector3 m_swingAxis;
- btVector3 m_twistAxis;
+ btVector3 m_swingAxis;
+ btVector3 m_twistAxis;
- btScalar m_kSwing;
- btScalar m_kTwist;
+ btScalar m_kSwing;
+ btScalar m_kTwist;
- btScalar m_twistLimitSign;
- btScalar m_swingCorrection;
- btScalar m_twistCorrection;
+ btScalar m_twistLimitSign;
+ btScalar m_swingCorrection;
+ btScalar m_twistCorrection;
- btScalar m_twistAngle;
+ btScalar m_twistAngle;
- btScalar m_accSwingLimitImpulse;
- btScalar m_accTwistLimitImpulse;
+ btScalar m_accSwingLimitImpulse;
+ btScalar m_accTwistLimitImpulse;
- bool m_angularOnly;
- bool m_solveTwistLimit;
- bool m_solveSwingLimit;
+ bool m_angularOnly;
+ bool m_solveTwistLimit;
+ bool m_solveSwingLimit;
- bool m_useSolveConstraintObsolete;
+ bool m_useSolveConstraintObsolete;
// not yet used...
- btScalar m_swingLimitRatio;
- btScalar m_twistLimitRatio;
- btVector3 m_twistAxisA;
+ btScalar m_swingLimitRatio;
+ btScalar m_twistLimitRatio;
+ btVector3 m_twistAxisA;
// motor
- bool m_bMotorEnabled;
- bool m_bNormalizedMotorStrength;
+ bool m_bMotorEnabled;
+ bool m_bNormalizedMotorStrength;
btQuaternion m_qTarget;
- btScalar m_maxMotorImpulse;
- btVector3 m_accMotorImpulse;
-
+ btScalar m_maxMotorImpulse;
+ btVector3 m_accMotorImpulse;
+
// parameters
- int m_flags;
- btScalar m_linCFM;
- btScalar m_linERP;
- btScalar m_angCFM;
-
-protected:
+ int m_flags;
+ btScalar m_linCFM;
+ btScalar m_linERP;
+ btScalar m_angCFM;
+protected:
void init();
- void computeConeLimitInfo(const btQuaternion& qCone, // in
- btScalar& swingAngle, btVector3& vSwingAxis, btScalar& swingLimit); // all outs
+ void computeConeLimitInfo(const btQuaternion& qCone, // in
+ btScalar& swingAngle, btVector3& vSwingAxis, btScalar& swingLimit); // all outs
- void computeTwistLimitInfo(const btQuaternion& qTwist, // in
- btScalar& twistAngle, btVector3& vTwistAxis); // all outs
-
- void adjustSwingAxisToUseEllipseNormal(btVector3& vSwingAxis) const;
+ void computeTwistLimitInfo(const btQuaternion& qTwist, // in
+ btScalar& twistAngle, btVector3& vTwistAxis); // all outs
+ void adjustSwingAxisToUseEllipseNormal(btVector3 & vSwingAxis) const;
public:
-
BT_DECLARE_ALIGNED_ALLOCATOR();
- btConeTwistConstraint(btRigidBody& rbA,btRigidBody& rbB,const btTransform& rbAFrame, const btTransform& rbBFrame);
-
- btConeTwistConstraint(btRigidBody& rbA,const btTransform& rbAFrame);
+ btConeTwistConstraint(btRigidBody & rbA, btRigidBody & rbB, const btTransform& rbAFrame, const btTransform& rbBFrame);
+
+ btConeTwistConstraint(btRigidBody & rbA, const btTransform& rbAFrame);
+
+ virtual void buildJacobian();
- virtual void buildJacobian();
+ virtual void getInfo1(btConstraintInfo1 * info);
- virtual void getInfo1 (btConstraintInfo1* info);
+ void getInfo1NonVirtual(btConstraintInfo1 * info);
- void getInfo1NonVirtual(btConstraintInfo1* info);
-
- virtual void getInfo2 (btConstraintInfo2* info);
-
- void getInfo2NonVirtual(btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btMatrix3x3& invInertiaWorldA,const btMatrix3x3& invInertiaWorldB);
+ virtual void getInfo2(btConstraintInfo2 * info);
- virtual void solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep);
+ void getInfo2NonVirtual(btConstraintInfo2 * info, const btTransform& transA, const btTransform& transB, const btMatrix3x3& invInertiaWorldA, const btMatrix3x3& invInertiaWorldB);
-
- void updateRHS(btScalar timeStep);
+ virtual void solveConstraintObsolete(btSolverBody & bodyA, btSolverBody & bodyB, btScalar timeStep);
+ void updateRHS(btScalar timeStep);
const btRigidBody& getRigidBodyA() const
{
@@ -166,64 +157,64 @@ public:
return m_rbB;
}
- void setAngularOnly(bool angularOnly)
+ void setAngularOnly(bool angularOnly)
{
m_angularOnly = angularOnly;
}
-
- bool getAngularOnly() const
+
+ bool getAngularOnly() const
{
- return m_angularOnly;
+ return m_angularOnly;
}
- void setLimit(int limitIndex,btScalar limitValue)
+ void setLimit(int limitIndex, btScalar limitValue)
{
switch (limitIndex)
{
- case 3:
+ case 3:
{
m_twistSpan = limitValue;
break;
}
- case 4:
+ case 4:
{
m_swingSpan2 = limitValue;
break;
}
- case 5:
+ case 5:
{
m_swingSpan1 = limitValue;
break;
}
- default:
+ default:
{
}
};
}
- btScalar getLimit(int limitIndex) const
+ btScalar getLimit(int limitIndex) const
{
switch (limitIndex)
{
- case 3:
+ case 3:
{
return m_twistSpan;
break;
}
- case 4:
+ case 4:
{
return m_swingSpan2;
break;
}
- case 5:
+ case 5:
{
return m_swingSpan1;
break;
}
- default:
+ default:
{
- btAssert(0 && "Invalid limitIndex specified for btConeTwistConstraint");
- return 0.0;
+ btAssert(0 && "Invalid limitIndex specified for btConeTwistConstraint");
+ return 0.0;
}
};
}
@@ -239,18 +230,18 @@ public:
// __relaxationFactor:
// 0->1, recommend to stay near 1.
// the lower the value, the less the constraint will fight velocities which violate the angular limits.
- void setLimit(btScalar _swingSpan1,btScalar _swingSpan2,btScalar _twistSpan, btScalar _softness = 1.f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f)
+ void setLimit(btScalar _swingSpan1, btScalar _swingSpan2, btScalar _twistSpan, btScalar _softness = 1.f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f)
{
m_swingSpan1 = _swingSpan1;
m_swingSpan2 = _swingSpan2;
- m_twistSpan = _twistSpan;
+ m_twistSpan = _twistSpan;
- m_limitSoftness = _softness;
+ m_limitSoftness = _softness;
m_biasFactor = _biasFactor;
m_relaxationFactor = _relaxationFactor;
}
- const btTransform& getAFrame() const { return m_rbAFrame; };
+ const btTransform& getAFrame() const { return m_rbAFrame; };
const btTransform& getBFrame() const { return m_rbBFrame; };
inline int getSolveTwistLimit()
@@ -269,7 +260,7 @@ public:
}
void calcAngleInfo();
- void calcAngleInfo2(const btTransform& transA, const btTransform& transB,const btMatrix3x3& invInertiaWorldA,const btMatrix3x3& invInertiaWorldB);
+ void calcAngleInfo2(const btTransform& transA, const btTransform& transB, const btMatrix3x3& invInertiaWorldA, const btMatrix3x3& invInertiaWorldB);
inline btScalar getSwingSpan1() const
{
@@ -308,8 +299,16 @@ public:
bool isMotorEnabled() const { return m_bMotorEnabled; }
btScalar getMaxMotorImpulse() const { return m_maxMotorImpulse; }
bool isMaxMotorImpulseNormalized() const { return m_bNormalizedMotorStrength; }
- void setMaxMotorImpulse(btScalar maxMotorImpulse) { m_maxMotorImpulse = maxMotorImpulse; m_bNormalizedMotorStrength = false; }
- void setMaxMotorImpulseNormalized(btScalar maxMotorImpulse) { m_maxMotorImpulse = maxMotorImpulse; m_bNormalizedMotorStrength = true; }
+ void setMaxMotorImpulse(btScalar maxMotorImpulse)
+ {
+ m_maxMotorImpulse = maxMotorImpulse;
+ m_bNormalizedMotorStrength = false;
+ }
+ void setMaxMotorImpulseNormalized(btScalar maxMotorImpulse)
+ {
+ m_maxMotorImpulse = maxMotorImpulse;
+ m_bNormalizedMotorStrength = true;
+ }
btScalar getFixThresh() { return m_fixThresh; }
void setFixThresh(btScalar fixThresh) { m_fixThresh = fixThresh; }
@@ -318,17 +317,17 @@ public:
// q: the desired rotation of bodyA wrt bodyB.
// note: if q violates the joint limits, the internal target is clamped to avoid conflicting impulses (very bad for stability)
// note: don't forget to enableMotor()
- void setMotorTarget(const btQuaternion &q);
+ void setMotorTarget(const btQuaternion& q);
const btQuaternion& getMotorTarget() const { return m_qTarget; }
// same as above, but q is the desired rotation of frameA wrt frameB in constraint space
- void setMotorTargetInConstraintSpace(const btQuaternion &q);
+ void setMotorTargetInConstraintSpace(const btQuaternion& q);
btVector3 GetPointForAngle(btScalar fAngleInRadians, btScalar fLength) const;
- ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+ ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
///If no axis is provided, it uses the default axis for this constraint.
- virtual void setParam(int num, btScalar value, int axis = -1);
+ virtual void setParam(int num, btScalar value, int axis = -1);
virtual void setFrames(const btTransform& frameA, const btTransform& frameB);
@@ -342,84 +341,74 @@ public:
return m_rbBFrame;
}
-
///return the local value of parameter
- virtual btScalar getParam(int num, int axis = -1) const;
+ virtual btScalar getParam(int num, int axis = -1) const;
int getFlags() const
{
return m_flags;
}
- virtual int calculateSerializeBufferSize() const;
+ virtual int calculateSerializeBufferSize() const;
///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
};
-
-
-struct btConeTwistConstraintDoubleData
+struct btConeTwistConstraintDoubleData
{
- btTypedConstraintDoubleData m_typeConstraintData;
+ btTypedConstraintDoubleData m_typeConstraintData;
btTransformDoubleData m_rbAFrame;
btTransformDoubleData m_rbBFrame;
//limits
- double m_swingSpan1;
- double m_swingSpan2;
- double m_twistSpan;
- double m_limitSoftness;
- double m_biasFactor;
- double m_relaxationFactor;
-
- double m_damping;
-
-
-
+ double m_swingSpan1;
+ double m_swingSpan2;
+ double m_twistSpan;
+ double m_limitSoftness;
+ double m_biasFactor;
+ double m_relaxationFactor;
+
+ double m_damping;
};
#ifdef BT_BACKWARDS_COMPATIBLE_SERIALIZATION
///this structure is not used, except for loading pre-2.82 .bullet files
-struct btConeTwistConstraintData
+struct btConeTwistConstraintData
{
- btTypedConstraintData m_typeConstraintData;
+ btTypedConstraintData m_typeConstraintData;
btTransformFloatData m_rbAFrame;
btTransformFloatData m_rbBFrame;
//limits
- float m_swingSpan1;
- float m_swingSpan2;
- float m_twistSpan;
- float m_limitSoftness;
- float m_biasFactor;
- float m_relaxationFactor;
-
- float m_damping;
-
- char m_pad[4];
+ float m_swingSpan1;
+ float m_swingSpan2;
+ float m_twistSpan;
+ float m_limitSoftness;
+ float m_biasFactor;
+ float m_relaxationFactor;
+ float m_damping;
+
+ char m_pad[4];
};
-#endif //BT_BACKWARDS_COMPATIBLE_SERIALIZATION
+#endif //BT_BACKWARDS_COMPATIBLE_SERIALIZATION
//
-SIMD_FORCE_INLINE int btConeTwistConstraint::calculateSerializeBufferSize() const
+SIMD_FORCE_INLINE int btConeTwistConstraint::calculateSerializeBufferSize() const
{
return sizeof(btConeTwistConstraintData2);
-
}
-
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
-SIMD_FORCE_INLINE const char* btConeTwistConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE const char* btConeTwistConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
{
- btConeTwistConstraintData2* cone = (btConeTwistConstraintData2*) dataBuffer;
- btTypedConstraint::serialize(&cone->m_typeConstraintData,serializer);
+ btConeTwistConstraintData2* cone = (btConeTwistConstraintData2*)dataBuffer;
+ btTypedConstraint::serialize(&cone->m_typeConstraintData, serializer);
m_rbAFrame.serialize(cone->m_rbAFrame);
m_rbBFrame.serialize(cone->m_rbBFrame);
-
+
cone->m_swingSpan1 = m_swingSpan1;
cone->m_swingSpan2 = m_swingSpan2;
cone->m_twistSpan = m_twistSpan;
@@ -431,5 +420,4 @@ SIMD_FORCE_INLINE const char* btConeTwistConstraint::serialize(void* dataBuffer,
return btConeTwistConstraintDataName;
}
-
-#endif //BT_CONETWISTCONSTRAINT_H
+#endif //BT_CONETWISTCONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConstraintSolver.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConstraintSolver.h
index 0491639f70..808433477c 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConstraintSolver.h
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConstraintSolver.h
@@ -26,41 +26,33 @@ struct btContactSolverInfo;
struct btBroadphaseProxy;
class btIDebugDraw;
class btStackAlloc;
-class btDispatcher;
+class btDispatcher;
/// btConstraintSolver provides solver interface
-
enum btConstraintSolverType
{
- BT_SEQUENTIAL_IMPULSE_SOLVER=1,
- BT_MLCP_SOLVER=2,
- BT_NNCG_SOLVER=4,
- BT_MULTIBODY_SOLVER=8,
+ BT_SEQUENTIAL_IMPULSE_SOLVER = 1,
+ BT_MLCP_SOLVER = 2,
+ BT_NNCG_SOLVER = 4,
+ BT_MULTIBODY_SOLVER = 8,
};
class btConstraintSolver
{
-
public:
-
virtual ~btConstraintSolver() {}
-
- virtual void prepareSolve (int /* numBodies */, int /* numManifolds */) {;}
+
+ virtual void prepareSolve(int /* numBodies */, int /* numManifolds */) { ; }
///solve a group of constraints
- virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints, const btContactSolverInfo& info,class btIDebugDraw* debugDrawer,btDispatcher* dispatcher) = 0;
+ virtual btScalar solveGroup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifold, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& info, class btIDebugDraw* debugDrawer, btDispatcher* dispatcher) = 0;
- virtual void allSolved (const btContactSolverInfo& /* info */,class btIDebugDraw* /* debugDrawer */) {;}
+ virtual void allSolved(const btContactSolverInfo& /* info */, class btIDebugDraw* /* debugDrawer */) { ; }
///clear internal cached data and reset random seed
- virtual void reset() = 0;
-
- virtual btConstraintSolverType getSolverType() const=0;
-
+ virtual void reset() = 0;
+ virtual btConstraintSolverType getSolverType() const = 0;
};
-
-
-
-#endif //BT_CONSTRAINT_SOLVER_H
+#endif //BT_CONSTRAINT_SOLVER_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactConstraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactConstraint.cpp
index 1098d0c96b..4b22b2fff5 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactConstraint.cpp
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactConstraint.cpp
@@ -13,7 +13,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#include "btContactConstraint.h"
#include "BulletDynamics/Dynamics/btRigidBody.h"
#include "LinearMath/btVector3.h"
@@ -22,44 +21,33 @@ subject to the following restrictions:
#include "LinearMath/btMinMax.h"
#include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h"
-
-
-btContactConstraint::btContactConstraint(btPersistentManifold* contactManifold,btRigidBody& rbA,btRigidBody& rbB)
-:btTypedConstraint(CONTACT_CONSTRAINT_TYPE,rbA,rbB),
- m_contactManifold(*contactManifold)
+btContactConstraint::btContactConstraint(btPersistentManifold* contactManifold, btRigidBody& rbA, btRigidBody& rbB)
+ : btTypedConstraint(CONTACT_CONSTRAINT_TYPE, rbA, rbB),
+ m_contactManifold(*contactManifold)
{
-
}
btContactConstraint::~btContactConstraint()
{
-
}
-void btContactConstraint::setContactManifold(btPersistentManifold* contactManifold)
+void btContactConstraint::setContactManifold(btPersistentManifold* contactManifold)
{
m_contactManifold = *contactManifold;
}
-void btContactConstraint::getInfo1 (btConstraintInfo1* info)
+void btContactConstraint::getInfo1(btConstraintInfo1* info)
{
-
}
-void btContactConstraint::getInfo2 (btConstraintInfo2* info)
+void btContactConstraint::getInfo2(btConstraintInfo2* info)
{
-
}
-void btContactConstraint::buildJacobian()
+void btContactConstraint::buildJacobian()
{
-
}
-
-
-
-
#include "btContactConstraint.h"
#include "BulletDynamics/Dynamics/btRigidBody.h"
#include "LinearMath/btVector3.h"
@@ -68,64 +56,59 @@ void btContactConstraint::buildJacobian()
#include "LinearMath/btMinMax.h"
#include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h"
-
-
//response between two dynamic objects without friction and no restitution, assuming 0 penetration depth
btScalar resolveSingleCollision(
- btRigidBody* body1,
- btCollisionObject* colObj2,
- const btVector3& contactPositionWorld,
- const btVector3& contactNormalOnB,
- const btContactSolverInfo& solverInfo,
- btScalar distance)
+ btRigidBody* body1,
+ btCollisionObject* colObj2,
+ const btVector3& contactPositionWorld,
+ const btVector3& contactNormalOnB,
+ const btContactSolverInfo& solverInfo,
+ btScalar distance)
{
btRigidBody* body2 = btRigidBody::upcast(colObj2);
-
-
- const btVector3& normal = contactNormalOnB;
-
- btVector3 rel_pos1 = contactPositionWorld - body1->getWorldTransform().getOrigin();
- btVector3 rel_pos2 = contactPositionWorld - colObj2->getWorldTransform().getOrigin();
-
- btVector3 vel1 = body1->getVelocityInLocalPoint(rel_pos1);
- btVector3 vel2 = body2? body2->getVelocityInLocalPoint(rel_pos2) : btVector3(0,0,0);
- btVector3 vel = vel1 - vel2;
- btScalar rel_vel;
- rel_vel = normal.dot(vel);
-
- btScalar combinedRestitution = 0.f;
- btScalar restitution = combinedRestitution* -rel_vel;
-
- btScalar positionalError = solverInfo.m_erp *-distance /solverInfo.m_timeStep ;
- btScalar velocityError = -(1.0f + restitution) * rel_vel;// * damping;
- btScalar denom0 = body1->computeImpulseDenominator(contactPositionWorld,normal);
- btScalar denom1 = body2? body2->computeImpulseDenominator(contactPositionWorld,normal) : 0.f;
+
+ const btVector3& normal = contactNormalOnB;
+
+ btVector3 rel_pos1 = contactPositionWorld - body1->getWorldTransform().getOrigin();
+ btVector3 rel_pos2 = contactPositionWorld - colObj2->getWorldTransform().getOrigin();
+
+ btVector3 vel1 = body1->getVelocityInLocalPoint(rel_pos1);
+ btVector3 vel2 = body2 ? body2->getVelocityInLocalPoint(rel_pos2) : btVector3(0, 0, 0);
+ btVector3 vel = vel1 - vel2;
+ btScalar rel_vel;
+ rel_vel = normal.dot(vel);
+
+ btScalar combinedRestitution = 0.f;
+ btScalar restitution = combinedRestitution * -rel_vel;
+
+ btScalar positionalError = solverInfo.m_erp * -distance / solverInfo.m_timeStep;
+ btScalar velocityError = -(1.0f + restitution) * rel_vel; // * damping;
+ btScalar denom0 = body1->computeImpulseDenominator(contactPositionWorld, normal);
+ btScalar denom1 = body2 ? body2->computeImpulseDenominator(contactPositionWorld, normal) : 0.f;
btScalar relaxation = 1.f;
- btScalar jacDiagABInv = relaxation/(denom0+denom1);
+ btScalar jacDiagABInv = relaxation / (denom0 + denom1);
- btScalar penetrationImpulse = positionalError * jacDiagABInv;
- btScalar velocityImpulse = velocityError * jacDiagABInv;
+ btScalar penetrationImpulse = positionalError * jacDiagABInv;
+ btScalar velocityImpulse = velocityError * jacDiagABInv;
- btScalar normalImpulse = penetrationImpulse+velocityImpulse;
- normalImpulse = 0.f > normalImpulse ? 0.f: normalImpulse;
+ btScalar normalImpulse = penetrationImpulse + velocityImpulse;
+ normalImpulse = 0.f > normalImpulse ? 0.f : normalImpulse;
- body1->applyImpulse(normal*(normalImpulse), rel_pos1);
- if (body2)
- body2->applyImpulse(-normal*(normalImpulse), rel_pos2);
-
- return normalImpulse;
-}
+ body1->applyImpulse(normal * (normalImpulse), rel_pos1);
+ if (body2)
+ body2->applyImpulse(-normal * (normalImpulse), rel_pos2);
+ return normalImpulse;
+}
//bilateral constraint between two dynamic objects
void resolveSingleBilateral(btRigidBody& body1, const btVector3& pos1,
- btRigidBody& body2, const btVector3& pos2,
- btScalar distance, const btVector3& normal,btScalar& impulse ,btScalar timeStep)
+ btRigidBody& body2, const btVector3& pos2,
+ btScalar distance, const btVector3& normal, btScalar& impulse, btScalar timeStep)
{
(void)timeStep;
(void)distance;
-
btScalar normalLenSqr = normal.length2();
btAssert(btFabs(normalLenSqr) < btScalar(1.1));
if (normalLenSqr > btScalar(1.1))
@@ -133,45 +116,38 @@ void resolveSingleBilateral(btRigidBody& body1, const btVector3& pos1,
impulse = btScalar(0.);
return;
}
- btVector3 rel_pos1 = pos1 - body1.getCenterOfMassPosition();
+ btVector3 rel_pos1 = pos1 - body1.getCenterOfMassPosition();
btVector3 rel_pos2 = pos2 - body2.getCenterOfMassPosition();
//this jacobian entry could be re-used for all iterations
-
+
btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1);
btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2);
btVector3 vel = vel1 - vel2;
-
- btJacobianEntry jac(body1.getCenterOfMassTransform().getBasis().transpose(),
- body2.getCenterOfMassTransform().getBasis().transpose(),
- rel_pos1,rel_pos2,normal,body1.getInvInertiaDiagLocal(),body1.getInvMass(),
- body2.getInvInertiaDiagLocal(),body2.getInvMass());
+ btJacobianEntry jac(body1.getCenterOfMassTransform().getBasis().transpose(),
+ body2.getCenterOfMassTransform().getBasis().transpose(),
+ rel_pos1, rel_pos2, normal, body1.getInvInertiaDiagLocal(), body1.getInvMass(),
+ body2.getInvInertiaDiagLocal(), body2.getInvMass());
btScalar jacDiagAB = jac.getDiagonal();
btScalar jacDiagABInv = btScalar(1.) / jacDiagAB;
-
- btScalar rel_vel = jac.getRelativeVelocity(
+
+ btScalar rel_vel = jac.getRelativeVelocity(
body1.getLinearVelocity(),
body1.getCenterOfMassTransform().getBasis().transpose() * body1.getAngularVelocity(),
body2.getLinearVelocity(),
- body2.getCenterOfMassTransform().getBasis().transpose() * body2.getAngularVelocity());
-
-
+ body2.getCenterOfMassTransform().getBasis().transpose() * body2.getAngularVelocity());
rel_vel = normal.dot(vel);
-
+
//todo: move this into proper structure
btScalar contactDamping = btScalar(0.2);
#ifdef ONLY_USE_LINEAR_MASS
btScalar massTerm = btScalar(1.) / (body1.getInvMass() + body2.getInvMass());
- impulse = - contactDamping * rel_vel * massTerm;
-#else
+ impulse = -contactDamping * rel_vel * massTerm;
+#else
btScalar velocityImpulse = -contactDamping * rel_vel * jacDiagABInv;
impulse = velocityImpulse;
#endif
}
-
-
-
-
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactConstraint.h
index adb2268353..255489be99 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactConstraint.h
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactConstraint.h
@@ -22,20 +22,17 @@ subject to the following restrictions:
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
///btContactConstraint can be automatically created to solve contact constraints using the unified btTypedConstraint interface
-ATTRIBUTE_ALIGNED16(class) btContactConstraint : public btTypedConstraint
+ATTRIBUTE_ALIGNED16(class)
+btContactConstraint : public btTypedConstraint
{
protected:
-
btPersistentManifold m_contactManifold;
protected:
-
-
- btContactConstraint(btPersistentManifold* contactManifold,btRigidBody& rbA,btRigidBody& rbB);
+ btContactConstraint(btPersistentManifold * contactManifold, btRigidBody & rbA, btRigidBody & rbB);
public:
-
- void setContactManifold(btPersistentManifold* contactManifold);
+ void setContactManifold(btPersistentManifold * contactManifold);
btPersistentManifold* getContactManifold()
{
@@ -49,25 +46,20 @@ public:
virtual ~btContactConstraint();
- virtual void getInfo1 (btConstraintInfo1* info);
+ virtual void getInfo1(btConstraintInfo1 * info);
- virtual void getInfo2 (btConstraintInfo2* info);
+ virtual void getInfo2(btConstraintInfo2 * info);
///obsolete methods
- virtual void buildJacobian();
-
-
+ virtual void buildJacobian();
};
///very basic collision resolution without friction
-btScalar resolveSingleCollision(btRigidBody* body1, class btCollisionObject* colObj2, const btVector3& contactPositionWorld,const btVector3& contactNormalOnB, const struct btContactSolverInfo& solverInfo,btScalar distance);
-
+btScalar resolveSingleCollision(btRigidBody* body1, class btCollisionObject* colObj2, const btVector3& contactPositionWorld, const btVector3& contactNormalOnB, const struct btContactSolverInfo& solverInfo, btScalar distance);
///resolveSingleBilateral is an obsolete methods used for vehicle friction between two dynamic objects
void resolveSingleBilateral(btRigidBody& body1, const btVector3& pos1,
- btRigidBody& body2, const btVector3& pos2,
- btScalar distance, const btVector3& normal,btScalar& impulse ,btScalar timeStep);
-
-
+ btRigidBody& body2, const btVector3& pos2,
+ btScalar distance, const btVector3& normal, btScalar& impulse, btScalar timeStep);
-#endif //BT_CONTACT_CONSTRAINT_H
+#endif //BT_CONTACT_CONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactSolverInfo.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactSolverInfo.h
index 93865cbc59..89f8db8b1a 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactSolverInfo.h
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactSolverInfo.h
@@ -18,7 +18,7 @@ subject to the following restrictions:
#include "LinearMath/btScalar.h"
-enum btSolverMode
+enum btSolverMode
{
SOLVER_RANDMIZE_ORDER = 1,
SOLVER_FRICTION_SEPARATE = 2,
@@ -35,134 +35,129 @@ enum btSolverMode
struct btContactSolverInfoData
{
-
-
- btScalar m_tau;
- btScalar m_damping;//global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'.
- btScalar m_friction;
- btScalar m_timeStep;
- btScalar m_restitution;
- int m_numIterations;
- btScalar m_maxErrorReduction;
- btScalar m_sor;//successive over-relaxation term
- btScalar m_erp;//error reduction for non-contact constraints
- btScalar m_erp2;//error reduction for contact constraints
- btScalar m_globalCfm;//constraint force mixing for contacts and non-contacts
- btScalar m_frictionERP;//error reduction for friction constraints
- btScalar m_frictionCFM;//constraint force mixing for friction constraints
-
- int m_splitImpulse;
- btScalar m_splitImpulsePenetrationThreshold;
- btScalar m_splitImpulseTurnErp;
- btScalar m_linearSlop;
- btScalar m_warmstartingFactor;
-
- int m_solverMode;
- int m_restingContactRestitutionThreshold;
- int m_minimumSolverBatchSize;
- btScalar m_maxGyroscopicForce;
- btScalar m_singleAxisRollingFrictionThreshold;
- btScalar m_leastSquaresResidualThreshold;
- btScalar m_restitutionVelocityThreshold;
-
+ btScalar m_tau;
+ btScalar m_damping; //global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'.
+ btScalar m_friction;
+ btScalar m_timeStep;
+ btScalar m_restitution;
+ int m_numIterations;
+ btScalar m_maxErrorReduction;
+ btScalar m_sor; //successive over-relaxation term
+ btScalar m_erp; //error reduction for non-contact constraints
+ btScalar m_erp2; //error reduction for contact constraints
+ btScalar m_globalCfm; //constraint force mixing for contacts and non-contacts
+ btScalar m_frictionERP; //error reduction for friction constraints
+ btScalar m_frictionCFM; //constraint force mixing for friction constraints
+
+ int m_splitImpulse;
+ btScalar m_splitImpulsePenetrationThreshold;
+ btScalar m_splitImpulseTurnErp;
+ btScalar m_linearSlop;
+ btScalar m_warmstartingFactor;
+
+ int m_solverMode;
+ int m_restingContactRestitutionThreshold;
+ int m_minimumSolverBatchSize;
+ btScalar m_maxGyroscopicForce;
+ btScalar m_singleAxisRollingFrictionThreshold;
+ btScalar m_leastSquaresResidualThreshold;
+ btScalar m_restitutionVelocityThreshold;
+ bool m_jointFeedbackInWorldSpace;
+ bool m_jointFeedbackInJointFrame;
};
struct btContactSolverInfo : public btContactSolverInfoData
{
-
-
-
inline btContactSolverInfo()
{
m_tau = btScalar(0.6);
m_damping = btScalar(1.0);
m_friction = btScalar(0.3);
- m_timeStep = btScalar(1.f/60.f);
+ m_timeStep = btScalar(1.f / 60.f);
m_restitution = btScalar(0.);
m_maxErrorReduction = btScalar(20.);
m_numIterations = 10;
m_erp = btScalar(0.2);
m_erp2 = btScalar(0.2);
m_globalCfm = btScalar(0.);
- m_frictionERP = btScalar(0.2);//positional friction 'anchors' are disabled by default
+ m_frictionERP = btScalar(0.2); //positional friction 'anchors' are disabled by default
m_frictionCFM = btScalar(0.);
m_sor = btScalar(1.);
m_splitImpulse = true;
m_splitImpulsePenetrationThreshold = -.04f;
m_splitImpulseTurnErp = 0.1f;
m_linearSlop = btScalar(0.0);
- m_warmstartingFactor=btScalar(0.85);
+ m_warmstartingFactor = btScalar(0.85);
//m_solverMode = SOLVER_USE_WARMSTARTING | SOLVER_SIMD | SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION|SOLVER_USE_2_FRICTION_DIRECTIONS|SOLVER_ENABLE_FRICTION_DIRECTION_CACHING;// | SOLVER_RANDMIZE_ORDER;
- m_solverMode = SOLVER_USE_WARMSTARTING | SOLVER_SIMD;// | SOLVER_RANDMIZE_ORDER;
- m_restingContactRestitutionThreshold = 2;//unused as of 2.81
- m_minimumSolverBatchSize = 128; //try to combine islands until the amount of constraints reaches this limit
- m_maxGyroscopicForce = 100.f; ///it is only used for 'explicit' version of gyroscopic force
- m_singleAxisRollingFrictionThreshold = 1e30f;///if the velocity is above this threshold, it will use a single constraint row (axis), otherwise 3 rows.
+ m_solverMode = SOLVER_USE_WARMSTARTING | SOLVER_SIMD; // | SOLVER_RANDMIZE_ORDER;
+ m_restingContactRestitutionThreshold = 2; //unused as of 2.81
+ m_minimumSolverBatchSize = 128; //try to combine islands until the amount of constraints reaches this limit
+ m_maxGyroscopicForce = 100.f; ///it is only used for 'explicit' version of gyroscopic force
+ m_singleAxisRollingFrictionThreshold = 1e30f; ///if the velocity is above this threshold, it will use a single constraint row (axis), otherwise 3 rows.
m_leastSquaresResidualThreshold = 0.f;
- m_restitutionVelocityThreshold = 0.2f;//if the relative velocity is below this threshold, there is zero restitution
+ m_restitutionVelocityThreshold = 0.2f; //if the relative velocity is below this threshold, there is zero restitution
+ m_jointFeedbackInWorldSpace = false;
+ m_jointFeedbackInJointFrame = false;
}
};
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
struct btContactSolverInfoDoubleData
{
- double m_tau;
- double m_damping;//global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'.
- double m_friction;
- double m_timeStep;
- double m_restitution;
- double m_maxErrorReduction;
- double m_sor;
- double m_erp;//used as Baumgarte factor
- double m_erp2;//used in Split Impulse
- double m_globalCfm;//constraint force mixing
- double m_splitImpulsePenetrationThreshold;
- double m_splitImpulseTurnErp;
- double m_linearSlop;
- double m_warmstartingFactor;
- double m_maxGyroscopicForce;///it is only used for 'explicit' version of gyroscopic force
- double m_singleAxisRollingFrictionThreshold;
-
- int m_numIterations;
- int m_solverMode;
- int m_restingContactRestitutionThreshold;
- int m_minimumSolverBatchSize;
- int m_splitImpulse;
- char m_padding[4];
-
+ double m_tau;
+ double m_damping; //global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'.
+ double m_friction;
+ double m_timeStep;
+ double m_restitution;
+ double m_maxErrorReduction;
+ double m_sor;
+ double m_erp; //used as Baumgarte factor
+ double m_erp2; //used in Split Impulse
+ double m_globalCfm; //constraint force mixing
+ double m_splitImpulsePenetrationThreshold;
+ double m_splitImpulseTurnErp;
+ double m_linearSlop;
+ double m_warmstartingFactor;
+ double m_maxGyroscopicForce; ///it is only used for 'explicit' version of gyroscopic force
+ double m_singleAxisRollingFrictionThreshold;
+
+ int m_numIterations;
+ int m_solverMode;
+ int m_restingContactRestitutionThreshold;
+ int m_minimumSolverBatchSize;
+ int m_splitImpulse;
+ char m_padding[4];
};
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
struct btContactSolverInfoFloatData
{
- float m_tau;
- float m_damping;//global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'.
- float m_friction;
- float m_timeStep;
-
- float m_restitution;
- float m_maxErrorReduction;
- float m_sor;
- float m_erp;//used as Baumgarte factor
-
- float m_erp2;//used in Split Impulse
- float m_globalCfm;//constraint force mixing
- float m_splitImpulsePenetrationThreshold;
- float m_splitImpulseTurnErp;
-
- float m_linearSlop;
- float m_warmstartingFactor;
- float m_maxGyroscopicForce;
- float m_singleAxisRollingFrictionThreshold;
-
- int m_numIterations;
- int m_solverMode;
- int m_restingContactRestitutionThreshold;
- int m_minimumSolverBatchSize;
-
- int m_splitImpulse;
- char m_padding[4];
+ float m_tau;
+ float m_damping; //global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'.
+ float m_friction;
+ float m_timeStep;
+
+ float m_restitution;
+ float m_maxErrorReduction;
+ float m_sor;
+ float m_erp; //used as Baumgarte factor
+
+ float m_erp2; //used in Split Impulse
+ float m_globalCfm; //constraint force mixing
+ float m_splitImpulsePenetrationThreshold;
+ float m_splitImpulseTurnErp;
+
+ float m_linearSlop;
+ float m_warmstartingFactor;
+ float m_maxGyroscopicForce;
+ float m_singleAxisRollingFrictionThreshold;
+
+ int m_numIterations;
+ int m_solverMode;
+ int m_restingContactRestitutionThreshold;
+ int m_minimumSolverBatchSize;
+
+ int m_splitImpulse;
+ char m_padding[4];
};
-
-
-#endif //BT_CONTACT_SOLVER_INFO
+#endif //BT_CONTACT_SOLVER_INFO
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btFixedConstraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btFixedConstraint.cpp
index 75d81cc08c..bba102d905 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btFixedConstraint.cpp
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btFixedConstraint.cpp
@@ -13,25 +13,20 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#include "btFixedConstraint.h"
#include "BulletDynamics/Dynamics/btRigidBody.h"
#include "LinearMath/btTransformUtil.h"
#include <new>
-
-btFixedConstraint::btFixedConstraint(btRigidBody& rbA,btRigidBody& rbB, const btTransform& frameInA,const btTransform& frameInB)
-:btGeneric6DofSpring2Constraint(rbA,rbB,frameInA,frameInB)
+btFixedConstraint::btFixedConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB)
+ : btGeneric6DofSpring2Constraint(rbA, rbB, frameInA, frameInB)
{
- setAngularLowerLimit(btVector3(0,0,0));
- setAngularUpperLimit(btVector3(0,0,0));
- setLinearLowerLimit(btVector3(0,0,0));
- setLinearUpperLimit(btVector3(0,0,0));
+ setAngularLowerLimit(btVector3(0, 0, 0));
+ setAngularUpperLimit(btVector3(0, 0, 0));
+ setLinearLowerLimit(btVector3(0, 0, 0));
+ setLinearUpperLimit(btVector3(0, 0, 0));
}
-
-
-
-btFixedConstraint::~btFixedConstraint ()
+btFixedConstraint::~btFixedConstraint()
{
}
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btFixedConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btFixedConstraint.h
index bff2008b28..6d474ea81d 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btFixedConstraint.h
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btFixedConstraint.h
@@ -18,16 +18,13 @@ subject to the following restrictions:
#include "btGeneric6DofSpring2Constraint.h"
-
-ATTRIBUTE_ALIGNED16(class) btFixedConstraint : public btGeneric6DofSpring2Constraint
+ATTRIBUTE_ALIGNED16(class)
+btFixedConstraint : public btGeneric6DofSpring2Constraint
{
-
public:
- btFixedConstraint(btRigidBody& rbA,btRigidBody& rbB, const btTransform& frameInA,const btTransform& frameInB);
+ btFixedConstraint(btRigidBody & rbA, btRigidBody & rbB, const btTransform& frameInA, const btTransform& frameInB);
-
virtual ~btFixedConstraint();
-
};
-#endif //BT_FIXED_CONSTRAINT_H
+#endif //BT_FIXED_CONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGearConstraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGearConstraint.cpp
index bcd457b673..7535c52c05 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGearConstraint.cpp
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGearConstraint.cpp
@@ -17,38 +17,36 @@ subject to the following restrictions:
#include "btGearConstraint.h"
-btGearConstraint::btGearConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& axisInA,const btVector3& axisInB, btScalar ratio)
-:btTypedConstraint(GEAR_CONSTRAINT_TYPE,rbA,rbB),
-m_axisInA(axisInA),
-m_axisInB(axisInB),
-m_ratio(ratio)
+btGearConstraint::btGearConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& axisInA, const btVector3& axisInB, btScalar ratio)
+ : btTypedConstraint(GEAR_CONSTRAINT_TYPE, rbA, rbB),
+ m_axisInA(axisInA),
+ m_axisInB(axisInB),
+ m_ratio(ratio)
{
}
-btGearConstraint::~btGearConstraint ()
+btGearConstraint::~btGearConstraint()
{
}
-void btGearConstraint::getInfo1 (btConstraintInfo1* info)
+void btGearConstraint::getInfo1(btConstraintInfo1* info)
{
info->m_numConstraintRows = 1;
info->nub = 1;
}
-void btGearConstraint::getInfo2 (btConstraintInfo2* info)
+void btGearConstraint::getInfo2(btConstraintInfo2* info)
{
btVector3 globalAxisA, globalAxisB;
- globalAxisA = m_rbA.getWorldTransform().getBasis()*this->m_axisInA;
- globalAxisB = m_rbB.getWorldTransform().getBasis()*this->m_axisInB;
+ globalAxisA = m_rbA.getWorldTransform().getBasis() * this->m_axisInA;
+ globalAxisB = m_rbB.getWorldTransform().getBasis() * this->m_axisInB;
info->m_J1angularAxis[0] = globalAxisA[0];
info->m_J1angularAxis[1] = globalAxisA[1];
info->m_J1angularAxis[2] = globalAxisA[2];
- info->m_J2angularAxis[0] = m_ratio*globalAxisB[0];
- info->m_J2angularAxis[1] = m_ratio*globalAxisB[1];
- info->m_J2angularAxis[2] = m_ratio*globalAxisB[2];
-
+ info->m_J2angularAxis[0] = m_ratio * globalAxisB[0];
+ info->m_J2angularAxis[1] = m_ratio * globalAxisB[1];
+ info->m_J2angularAxis[2] = m_ratio * globalAxisB[2];
}
-
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGearConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGearConstraint.h
index e4613455a2..64b15dfbce 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGearConstraint.h
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGearConstraint.h
@@ -13,45 +13,40 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
-
#ifndef BT_GEAR_CONSTRAINT_H
#define BT_GEAR_CONSTRAINT_H
#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
-
#ifdef BT_USE_DOUBLE_PRECISION
-#define btGearConstraintData btGearConstraintDoubleData
-#define btGearConstraintDataName "btGearConstraintDoubleData"
+#define btGearConstraintData btGearConstraintDoubleData
+#define btGearConstraintDataName "btGearConstraintDoubleData"
#else
-#define btGearConstraintData btGearConstraintFloatData
-#define btGearConstraintDataName "btGearConstraintFloatData"
-#endif //BT_USE_DOUBLE_PRECISION
-
-
+#define btGearConstraintData btGearConstraintFloatData
+#define btGearConstraintDataName "btGearConstraintFloatData"
+#endif //BT_USE_DOUBLE_PRECISION
///The btGeatConstraint will couple the angular velocity for two bodies around given local axis and ratio.
///See Bullet/Demos/ConstraintDemo for an example use.
class btGearConstraint : public btTypedConstraint
{
protected:
- btVector3 m_axisInA;
- btVector3 m_axisInB;
- bool m_useFrameA;
- btScalar m_ratio;
+ btVector3 m_axisInA;
+ btVector3 m_axisInB;
+ bool m_useFrameA;
+ btScalar m_ratio;
public:
- btGearConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& axisInA,const btVector3& axisInB, btScalar ratio=1.f);
- virtual ~btGearConstraint ();
+ btGearConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& axisInA, const btVector3& axisInB, btScalar ratio = 1.f);
+ virtual ~btGearConstraint();
///internal method used by the constraint solver, don't use them directly
- virtual void getInfo1 (btConstraintInfo1* info);
+ virtual void getInfo1(btConstraintInfo1* info);
///internal method used by the constraint solver, don't use them directly
- virtual void getInfo2 (btConstraintInfo2* info);
+ virtual void getInfo2(btConstraintInfo2* info);
- void setAxisA(btVector3& axisA)
+ void setAxisA(btVector3& axisA)
{
m_axisInA = axisA;
}
@@ -76,68 +71,64 @@ public:
return m_ratio;
}
-
- virtual void setParam(int num, btScalar value, int axis = -1)
+ virtual void setParam(int num, btScalar value, int axis = -1)
{
- (void) num;
- (void) value;
- (void) axis;
+ (void)num;
+ (void)value;
+ (void)axis;
btAssert(0);
}
///return the local value of parameter
- virtual btScalar getParam(int num, int axis = -1) const
- {
- (void) num;
- (void) axis;
+ virtual btScalar getParam(int num, int axis = -1) const
+ {
+ (void)num;
+ (void)axis;
btAssert(0);
return 0.f;
}
- virtual int calculateSerializeBufferSize() const;
+ virtual int calculateSerializeBufferSize() const;
///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
};
-
-
-
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
struct btGearConstraintFloatData
{
- btTypedConstraintFloatData m_typeConstraintData;
+ btTypedConstraintFloatData m_typeConstraintData;
- btVector3FloatData m_axisInA;
- btVector3FloatData m_axisInB;
+ btVector3FloatData m_axisInA;
+ btVector3FloatData m_axisInB;
- float m_ratio;
- char m_padding[4];
+ float m_ratio;
+ char m_padding[4];
};
struct btGearConstraintDoubleData
{
- btTypedConstraintDoubleData m_typeConstraintData;
+ btTypedConstraintDoubleData m_typeConstraintData;
- btVector3DoubleData m_axisInA;
- btVector3DoubleData m_axisInB;
+ btVector3DoubleData m_axisInA;
+ btVector3DoubleData m_axisInB;
- double m_ratio;
+ double m_ratio;
};
-SIMD_FORCE_INLINE int btGearConstraint::calculateSerializeBufferSize() const
+SIMD_FORCE_INLINE int btGearConstraint::calculateSerializeBufferSize() const
{
return sizeof(btGearConstraintData);
}
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
-SIMD_FORCE_INLINE const char* btGearConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE const char* btGearConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
{
btGearConstraintData* gear = (btGearConstraintData*)dataBuffer;
- btTypedConstraint::serialize(&gear->m_typeConstraintData,serializer);
+ btTypedConstraint::serialize(&gear->m_typeConstraintData, serializer);
- m_axisInA.serialize( gear->m_axisInA );
- m_axisInB.serialize( gear->m_axisInB );
+ m_axisInA.serialize(gear->m_axisInA);
+ m_axisInB.serialize(gear->m_axisInB);
gear->m_ratio = m_ratio;
@@ -152,9 +143,4 @@ SIMD_FORCE_INLINE const char* btGearConstraint::serialize(void* dataBuffer, btSe
return btGearConstraintDataName;
}
-
-
-
-
-
-#endif //BT_GEAR_CONSTRAINT_H
+#endif //BT_GEAR_CONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp
index c38b8353f0..1f54203532 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp
@@ -25,83 +25,61 @@ http://gimpact.sf.net
#include "LinearMath/btTransformUtil.h"
#include <new>
-
-
#define D6_USE_OBSOLETE_METHOD false
#define D6_USE_FRAME_OFFSET true
-
-
-
-
-
btGeneric6DofConstraint::btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA)
-: btTypedConstraint(D6_CONSTRAINT_TYPE, rbA, rbB)
-, m_frameInA(frameInA)
-, m_frameInB(frameInB),
-m_useLinearReferenceFrameA(useLinearReferenceFrameA),
-m_useOffsetForConstraintFrame(D6_USE_FRAME_OFFSET),
-m_flags(0),
-m_useSolveConstraintObsolete(D6_USE_OBSOLETE_METHOD)
+ : btTypedConstraint(D6_CONSTRAINT_TYPE, rbA, rbB), m_frameInA(frameInA), m_frameInB(frameInB), m_useLinearReferenceFrameA(useLinearReferenceFrameA), m_useOffsetForConstraintFrame(D6_USE_FRAME_OFFSET), m_flags(0), m_useSolveConstraintObsolete(D6_USE_OBSOLETE_METHOD)
{
calculateTransforms();
}
-
-
btGeneric6DofConstraint::btGeneric6DofConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameB)
- : btTypedConstraint(D6_CONSTRAINT_TYPE, getFixedBody(), rbB),
- m_frameInB(frameInB),
- m_useLinearReferenceFrameA(useLinearReferenceFrameB),
- m_useOffsetForConstraintFrame(D6_USE_FRAME_OFFSET),
- m_flags(0),
- m_useSolveConstraintObsolete(false)
+ : btTypedConstraint(D6_CONSTRAINT_TYPE, getFixedBody(), rbB),
+ m_frameInB(frameInB),
+ m_useLinearReferenceFrameA(useLinearReferenceFrameB),
+ m_useOffsetForConstraintFrame(D6_USE_FRAME_OFFSET),
+ m_flags(0),
+ m_useSolveConstraintObsolete(false)
{
///not providing rigidbody A means implicitly using worldspace for body A
m_frameInA = rbB.getCenterOfMassTransform() * m_frameInB;
calculateTransforms();
}
-
-
-
#define GENERIC_D6_DISABLE_WARMSTARTING 1
-
-
btScalar btGetMatrixElem(const btMatrix3x3& mat, int index);
btScalar btGetMatrixElem(const btMatrix3x3& mat, int index)
{
- int i = index%3;
- int j = index/3;
+ int i = index % 3;
+ int j = index / 3;
return mat[i][j];
}
-
-
///MatrixToEulerXYZ from http://www.geometrictools.com/LibFoundation/Mathematics/Wm4Matrix3.inl.html
-bool matrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz);
-bool matrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz)
+bool matrixToEulerXYZ(const btMatrix3x3& mat, btVector3& xyz);
+bool matrixToEulerXYZ(const btMatrix3x3& mat, btVector3& xyz)
{
// // rot = cy*cz -cy*sz sy
// // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx
// // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy
//
- btScalar fi = btGetMatrixElem(mat,2);
+ btScalar fi = btGetMatrixElem(mat, 2);
if (fi < btScalar(1.0f))
{
if (fi > btScalar(-1.0f))
{
- xyz[0] = btAtan2(-btGetMatrixElem(mat,5),btGetMatrixElem(mat,8));
- xyz[1] = btAsin(btGetMatrixElem(mat,2));
- xyz[2] = btAtan2(-btGetMatrixElem(mat,1),btGetMatrixElem(mat,0));
+ xyz[0] = btAtan2(-btGetMatrixElem(mat, 5), btGetMatrixElem(mat, 8));
+ xyz[1] = btAsin(btGetMatrixElem(mat, 2));
+ xyz[2] = btAtan2(-btGetMatrixElem(mat, 1), btGetMatrixElem(mat, 0));
return true;
}
else
{
// WARNING. Not unique. XA - ZA = -atan2(r10,r11)
- xyz[0] = -btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4));
+ xyz[0] = -btAtan2(btGetMatrixElem(mat, 3), btGetMatrixElem(mat, 4));
xyz[1] = -SIMD_HALF_PI;
xyz[2] = btScalar(0.0);
return false;
@@ -110,7 +88,7 @@ bool matrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz)
else
{
// WARNING. Not unique. XAngle + ZAngle = atan2(r10,r11)
- xyz[0] = btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4));
+ xyz[0] = btAtan2(btGetMatrixElem(mat, 3), btGetMatrixElem(mat, 4));
xyz[1] = SIMD_HALF_PI;
xyz[2] = 0.0;
}
@@ -121,52 +99,49 @@ bool matrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz)
int btRotationalLimitMotor::testLimitValue(btScalar test_value)
{
- if(m_loLimit>m_hiLimit)
+ if (m_loLimit > m_hiLimit)
{
- m_currentLimit = 0;//Free from violation
+ m_currentLimit = 0; //Free from violation
return 0;
}
if (test_value < m_loLimit)
{
- m_currentLimit = 1;//low limit violation
- m_currentLimitError = test_value - m_loLimit;
- if(m_currentLimitError>SIMD_PI)
- m_currentLimitError-=SIMD_2_PI;
- else if(m_currentLimitError<-SIMD_PI)
- m_currentLimitError+=SIMD_2_PI;
+ m_currentLimit = 1; //low limit violation
+ m_currentLimitError = test_value - m_loLimit;
+ if (m_currentLimitError > SIMD_PI)
+ m_currentLimitError -= SIMD_2_PI;
+ else if (m_currentLimitError < -SIMD_PI)
+ m_currentLimitError += SIMD_2_PI;
return 1;
}
- else if (test_value> m_hiLimit)
+ else if (test_value > m_hiLimit)
{
- m_currentLimit = 2;//High limit violation
+ m_currentLimit = 2; //High limit violation
m_currentLimitError = test_value - m_hiLimit;
- if(m_currentLimitError>SIMD_PI)
- m_currentLimitError-=SIMD_2_PI;
- else if(m_currentLimitError<-SIMD_PI)
- m_currentLimitError+=SIMD_2_PI;
+ if (m_currentLimitError > SIMD_PI)
+ m_currentLimitError -= SIMD_2_PI;
+ else if (m_currentLimitError < -SIMD_PI)
+ m_currentLimitError += SIMD_2_PI;
return 2;
};
- m_currentLimit = 0;//Free from violation
+ m_currentLimit = 0; //Free from violation
return 0;
-
}
-
-
btScalar btRotationalLimitMotor::solveAngularLimits(
- btScalar timeStep,btVector3& axis,btScalar jacDiagABInv,
- btRigidBody * body0, btRigidBody * body1 )
+ btScalar timeStep, btVector3& axis, btScalar jacDiagABInv,
+ btRigidBody* body0, btRigidBody* body1)
{
- if (needApplyTorques()==false) return 0.0f;
+ if (needApplyTorques() == false) return 0.0f;
btScalar target_velocity = m_targetVelocity;
btScalar maxMotorForce = m_maxMotorForce;
//current error correction
- if (m_currentLimit!=0)
+ if (m_currentLimit != 0)
{
- target_velocity = -m_stopERP*m_currentLimitError/(timeStep);
+ target_velocity = -m_stopERP * m_currentLimitError / (timeStep);
maxMotorForce = m_maxLimitForce;
}
@@ -178,42 +153,37 @@ btScalar btRotationalLimitMotor::solveAngularLimits(
btVector3 angVelB = body1->getAngularVelocity();
btVector3 vel_diff;
- vel_diff = angVelA-angVelB;
-
-
+ vel_diff = angVelA - angVelB;
btScalar rel_vel = axis.dot(vel_diff);
// correction velocity
- btScalar motor_relvel = m_limitSoftness*(target_velocity - m_damping*rel_vel);
+ btScalar motor_relvel = m_limitSoftness * (target_velocity - m_damping * rel_vel);
-
- if ( motor_relvel < SIMD_EPSILON && motor_relvel > -SIMD_EPSILON )
+ if (motor_relvel < SIMD_EPSILON && motor_relvel > -SIMD_EPSILON)
{
- return 0.0f;//no need for applying force
+ return 0.0f; //no need for applying force
}
-
// correction impulse
- btScalar unclippedMotorImpulse = (1+m_bounce)*motor_relvel*jacDiagABInv;
+ btScalar unclippedMotorImpulse = (1 + m_bounce) * motor_relvel * jacDiagABInv;
// clip correction impulse
btScalar clippedMotorImpulse;
///@todo: should clip against accumulated impulse
- if (unclippedMotorImpulse>0.0f)
+ if (unclippedMotorImpulse > 0.0f)
{
- clippedMotorImpulse = unclippedMotorImpulse > maxMotorForce? maxMotorForce: unclippedMotorImpulse;
+ clippedMotorImpulse = unclippedMotorImpulse > maxMotorForce ? maxMotorForce : unclippedMotorImpulse;
}
else
{
- clippedMotorImpulse = unclippedMotorImpulse < -maxMotorForce ? -maxMotorForce: unclippedMotorImpulse;
+ clippedMotorImpulse = unclippedMotorImpulse < -maxMotorForce ? -maxMotorForce : unclippedMotorImpulse;
}
-
// sort with accumulated impulses
- btScalar lo = btScalar(-BT_LARGE_FLOAT);
- btScalar hi = btScalar(BT_LARGE_FLOAT);
+ btScalar lo = btScalar(-BT_LARGE_FLOAT);
+ btScalar hi = btScalar(BT_LARGE_FLOAT);
btScalar oldaccumImpulse = m_accumulatedImpulse;
btScalar sum = oldaccumImpulse + clippedMotorImpulse;
@@ -227,59 +197,50 @@ btScalar btRotationalLimitMotor::solveAngularLimits(
body1->applyTorqueImpulse(-motorImp);
return clippedMotorImpulse;
-
-
}
//////////////////////////// End btRotationalLimitMotor ////////////////////////////////////
-
-
-
//////////////////////////// btTranslationalLimitMotor ////////////////////////////////////
-
int btTranslationalLimitMotor::testLimitValue(int limitIndex, btScalar test_value)
{
btScalar loLimit = m_lowerLimit[limitIndex];
btScalar hiLimit = m_upperLimit[limitIndex];
- if(loLimit > hiLimit)
+ if (loLimit > hiLimit)
{
- m_currentLimit[limitIndex] = 0;//Free from violation
+ m_currentLimit[limitIndex] = 0; //Free from violation
m_currentLimitError[limitIndex] = btScalar(0.f);
return 0;
}
if (test_value < loLimit)
{
- m_currentLimit[limitIndex] = 2;//low limit violation
- m_currentLimitError[limitIndex] = test_value - loLimit;
+ m_currentLimit[limitIndex] = 2; //low limit violation
+ m_currentLimitError[limitIndex] = test_value - loLimit;
return 2;
}
- else if (test_value> hiLimit)
+ else if (test_value > hiLimit)
{
- m_currentLimit[limitIndex] = 1;//High limit violation
+ m_currentLimit[limitIndex] = 1; //High limit violation
m_currentLimitError[limitIndex] = test_value - hiLimit;
return 1;
};
- m_currentLimit[limitIndex] = 0;//Free from violation
+ m_currentLimit[limitIndex] = 0; //Free from violation
m_currentLimitError[limitIndex] = btScalar(0.f);
return 0;
}
-
-
btScalar btTranslationalLimitMotor::solveLinearAxis(
btScalar timeStep,
btScalar jacDiagABInv,
- btRigidBody& body1,const btVector3 &pointInA,
- btRigidBody& body2,const btVector3 &pointInB,
+ btRigidBody& body1, const btVector3& pointInA,
+ btRigidBody& body2, const btVector3& pointInB,
int limit_index,
- const btVector3 & axis_normal_on_a,
- const btVector3 & anchorPos)
+ const btVector3& axis_normal_on_a,
+ const btVector3& anchorPos)
{
-
///find relative velocity
// btVector3 rel_pos1 = pointInA - body1.getCenterOfMassPosition();
// btVector3 rel_pos2 = pointInB - body2.getCenterOfMassPosition();
@@ -292,14 +253,12 @@ btScalar btTranslationalLimitMotor::solveLinearAxis(
btScalar rel_vel = axis_normal_on_a.dot(vel);
-
-
/// apply displacement correction
//positional error (zeroth order error)
btScalar depth = -(pointInA - pointInB).dot(axis_normal_on_a);
- btScalar lo = btScalar(-BT_LARGE_FLOAT);
- btScalar hi = btScalar(BT_LARGE_FLOAT);
+ btScalar lo = btScalar(-BT_LARGE_FLOAT);
+ btScalar hi = btScalar(BT_LARGE_FLOAT);
btScalar minLimit = m_lowerLimit[limit_index];
btScalar maxLimit = m_upperLimit[limit_index];
@@ -312,7 +271,6 @@ btScalar btTranslationalLimitMotor::solveLinearAxis(
{
depth -= maxLimit;
lo = btScalar(0.);
-
}
else
{
@@ -329,10 +287,7 @@ btScalar btTranslationalLimitMotor::solveLinearAxis(
}
}
- btScalar normalImpulse= m_limitSoftness*(m_restitution*depth/timeStep - m_damping*rel_vel) * jacDiagABInv;
-
-
-
+ btScalar normalImpulse = m_limitSoftness * (m_restitution * depth / timeStep - m_damping * rel_vel) * jacDiagABInv;
btScalar oldNormalImpulse = m_accumulatedImpulse[limit_index];
btScalar sum = oldNormalImpulse + normalImpulse;
@@ -340,11 +295,9 @@ btScalar btTranslationalLimitMotor::solveLinearAxis(
normalImpulse = m_accumulatedImpulse[limit_index] - oldNormalImpulse;
btVector3 impulse_vector = axis_normal_on_a * normalImpulse;
- body1.applyImpulse( impulse_vector, rel_pos1);
+ body1.applyImpulse(impulse_vector, rel_pos1);
body2.applyImpulse(-impulse_vector, rel_pos2);
-
-
return normalImpulse;
}
@@ -352,8 +305,8 @@ btScalar btTranslationalLimitMotor::solveLinearAxis(
void btGeneric6DofConstraint::calculateAngleInfo()
{
- btMatrix3x3 relative_frame = m_calculatedTransformA.getBasis().inverse()*m_calculatedTransformB.getBasis();
- matrixToEulerXYZ(relative_frame,m_calculatedAxisAngleDiff);
+ btMatrix3x3 relative_frame = m_calculatedTransformA.getBasis().inverse() * m_calculatedTransformB.getBasis();
+ matrixToEulerXYZ(relative_frame, m_calculatedAxisAngleDiff);
// 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]) :
//
@@ -378,31 +331,30 @@ void btGeneric6DofConstraint::calculateAngleInfo()
m_calculatedAxis[0].normalize();
m_calculatedAxis[1].normalize();
m_calculatedAxis[2].normalize();
-
}
void btGeneric6DofConstraint::calculateTransforms()
{
- calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
+ calculateTransforms(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
}
-void btGeneric6DofConstraint::calculateTransforms(const btTransform& transA,const btTransform& transB)
+void btGeneric6DofConstraint::calculateTransforms(const btTransform& transA, const btTransform& transB)
{
m_calculatedTransformA = transA * m_frameInA;
m_calculatedTransformB = transB * m_frameInB;
calculateLinearInfo();
calculateAngleInfo();
- if(m_useOffsetForConstraintFrame)
- { // get weight factors depending on masses
+ if (m_useOffsetForConstraintFrame)
+ { // get weight factors depending on masses
btScalar miA = getRigidBodyA().getInvMass();
btScalar miB = getRigidBodyB().getInvMass();
m_hasStaticBody = (miA < SIMD_EPSILON) || (miB < SIMD_EPSILON);
btScalar miS = miA + miB;
- if(miS > btScalar(0.f))
+ if (miS > btScalar(0.f))
{
m_factA = miB / miS;
}
- else
+ else
{
m_factA = btScalar(0.5f);
}
@@ -410,39 +362,32 @@ void btGeneric6DofConstraint::calculateTransforms(const btTransform& transA,cons
}
}
-
-
void btGeneric6DofConstraint::buildLinearJacobian(
- btJacobianEntry & jacLinear,const btVector3 & normalWorld,
- const btVector3 & pivotAInW,const btVector3 & pivotBInW)
+ btJacobianEntry& jacLinear, const btVector3& normalWorld,
+ const btVector3& pivotAInW, const btVector3& pivotBInW)
{
new (&jacLinear) btJacobianEntry(
- m_rbA.getCenterOfMassTransform().getBasis().transpose(),
- m_rbB.getCenterOfMassTransform().getBasis().transpose(),
- pivotAInW - m_rbA.getCenterOfMassPosition(),
- pivotBInW - m_rbB.getCenterOfMassPosition(),
- normalWorld,
- m_rbA.getInvInertiaDiagLocal(),
- m_rbA.getInvMass(),
- m_rbB.getInvInertiaDiagLocal(),
- m_rbB.getInvMass());
+ m_rbA.getCenterOfMassTransform().getBasis().transpose(),
+ m_rbB.getCenterOfMassTransform().getBasis().transpose(),
+ pivotAInW - m_rbA.getCenterOfMassPosition(),
+ pivotBInW - m_rbB.getCenterOfMassPosition(),
+ normalWorld,
+ m_rbA.getInvInertiaDiagLocal(),
+ m_rbA.getInvMass(),
+ m_rbB.getInvInertiaDiagLocal(),
+ m_rbB.getInvMass());
}
-
-
void btGeneric6DofConstraint::buildAngularJacobian(
- btJacobianEntry & jacAngular,const btVector3 & jointAxisW)
+ btJacobianEntry& jacAngular, const btVector3& jointAxisW)
{
- new (&jacAngular) btJacobianEntry(jointAxisW,
- m_rbA.getCenterOfMassTransform().getBasis().transpose(),
- m_rbB.getCenterOfMassTransform().getBasis().transpose(),
- m_rbA.getInvInertiaDiagLocal(),
- m_rbB.getInvInertiaDiagLocal());
-
+ new (&jacAngular) btJacobianEntry(jointAxisW,
+ m_rbA.getCenterOfMassTransform().getBasis().transpose(),
+ m_rbB.getCenterOfMassTransform().getBasis().transpose(),
+ m_rbA.getInvInertiaDiagLocal(),
+ m_rbB.getInvInertiaDiagLocal());
}
-
-
bool btGeneric6DofConstraint::testAngularLimitMotor(int axis_index)
{
btScalar angle = m_calculatedAxisAngleDiff[axis_index];
@@ -453,23 +398,20 @@ bool btGeneric6DofConstraint::testAngularLimitMotor(int axis_index)
return m_angularLimits[axis_index].needApplyTorques();
}
-
-
void btGeneric6DofConstraint::buildJacobian()
{
#ifndef __SPU__
if (m_useSolveConstraintObsolete)
{
-
// Clear accumulated impulses for the next simulation step
m_linearLimits.m_accumulatedImpulse.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
int i;
- for(i = 0; i < 3; i++)
+ for (i = 0; i < 3; i++)
{
m_angularLimits[i].m_accumulatedImpulse = btScalar(0.);
}
//calculates transform
- calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
+ calculateTransforms(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
// const btVector3& pivotAInW = m_calculatedTransformA.getOrigin();
// const btVector3& pivotBInW = m_calculatedTransformB.getOrigin();
@@ -483,7 +425,7 @@ void btGeneric6DofConstraint::buildJacobian()
btVector3 normalWorld;
//linear part
- for (i=0;i<3;i++)
+ for (i = 0; i < 3; i++)
{
if (m_linearLimits.isLimited(i))
{
@@ -493,56 +435,53 @@ void btGeneric6DofConstraint::buildJacobian()
normalWorld = m_calculatedTransformB.getBasis().getColumn(i);
buildLinearJacobian(
- m_jacLinear[i],normalWorld ,
- pivotAInW,pivotBInW);
-
+ m_jacLinear[i], normalWorld,
+ pivotAInW, pivotBInW);
}
}
// angular part
- for (i=0;i<3;i++)
+ for (i = 0; i < 3; i++)
{
//calculates error angle
if (testAngularLimitMotor(i))
{
normalWorld = this->getAxis(i);
// Create angular atom
- buildAngularJacobian(m_jacAng[i],normalWorld);
+ buildAngularJacobian(m_jacAng[i], normalWorld);
}
}
-
}
-#endif //__SPU__
-
+#endif //__SPU__
}
-
-void btGeneric6DofConstraint::getInfo1 (btConstraintInfo1* info)
+void btGeneric6DofConstraint::getInfo1(btConstraintInfo1* info)
{
if (m_useSolveConstraintObsolete)
{
info->m_numConstraintRows = 0;
info->nub = 0;
- } else
+ }
+ else
{
//prepare constraint
- calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
+ calculateTransforms(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
info->m_numConstraintRows = 0;
info->nub = 6;
int i;
//test linear limits
- for(i = 0; i < 3; i++)
+ for (i = 0; i < 3; i++)
{
- if(m_linearLimits.needApplyForce(i))
+ if (m_linearLimits.needApplyForce(i))
{
info->m_numConstraintRows++;
info->nub--;
}
}
//test angular limits
- for (i=0;i<3 ;i++ )
+ for (i = 0; i < 3; i++)
{
- if(testAngularLimitMotor(i))
+ if (testAngularLimitMotor(i))
{
info->m_numConstraintRows++;
info->nub--;
@@ -551,13 +490,14 @@ void btGeneric6DofConstraint::getInfo1 (btConstraintInfo1* info)
}
}
-void btGeneric6DofConstraint::getInfo1NonVirtual (btConstraintInfo1* info)
+void btGeneric6DofConstraint::getInfo1NonVirtual(btConstraintInfo1* info)
{
if (m_useSolveConstraintObsolete)
{
info->m_numConstraintRows = 0;
info->nub = 0;
- } else
+ }
+ else
{
//pre-allocate all 6
info->m_numConstraintRows = 6;
@@ -565,8 +505,7 @@ void btGeneric6DofConstraint::getInfo1NonVirtual (btConstraintInfo1* info)
}
}
-
-void btGeneric6DofConstraint::getInfo2 (btConstraintInfo2* info)
+void btGeneric6DofConstraint::getInfo2(btConstraintInfo2* info)
{
btAssert(!m_useSolveConstraintObsolete);
@@ -577,136 +516,124 @@ void btGeneric6DofConstraint::getInfo2 (btConstraintInfo2* info)
const btVector3& angVelA = m_rbA.getAngularVelocity();
const btVector3& angVelB = m_rbB.getAngularVelocity();
- if(m_useOffsetForConstraintFrame)
- { // for stability better to solve angular limits first
- int row = setAngularLimits(info, 0,transA,transB,linVelA,linVelB,angVelA,angVelB);
- setLinearLimits(info, row, transA,transB,linVelA,linVelB,angVelA,angVelB);
+ if (m_useOffsetForConstraintFrame)
+ { // for stability better to solve angular limits first
+ int row = setAngularLimits(info, 0, transA, transB, linVelA, linVelB, angVelA, angVelB);
+ setLinearLimits(info, row, transA, transB, linVelA, linVelB, angVelA, angVelB);
}
else
- { // leave old version for compatibility
- int row = setLinearLimits(info, 0, transA,transB,linVelA,linVelB,angVelA,angVelB);
- setAngularLimits(info, row,transA,transB,linVelA,linVelB,angVelA,angVelB);
+ { // leave old version for compatibility
+ int row = setLinearLimits(info, 0, transA, transB, linVelA, linVelB, angVelA, angVelB);
+ setAngularLimits(info, row, transA, transB, linVelA, linVelB, angVelA, angVelB);
}
-
}
-
-void btGeneric6DofConstraint::getInfo2NonVirtual (btConstraintInfo2* info, const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB)
+void btGeneric6DofConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB)
{
-
btAssert(!m_useSolveConstraintObsolete);
//prepare constraint
- calculateTransforms(transA,transB);
+ calculateTransforms(transA, transB);
int i;
- for (i=0;i<3 ;i++ )
+ for (i = 0; i < 3; i++)
{
testAngularLimitMotor(i);
}
- if(m_useOffsetForConstraintFrame)
- { // for stability better to solve angular limits first
- int row = setAngularLimits(info, 0,transA,transB,linVelA,linVelB,angVelA,angVelB);
- setLinearLimits(info, row, transA,transB,linVelA,linVelB,angVelA,angVelB);
+ if (m_useOffsetForConstraintFrame)
+ { // for stability better to solve angular limits first
+ int row = setAngularLimits(info, 0, transA, transB, linVelA, linVelB, angVelA, angVelB);
+ setLinearLimits(info, row, transA, transB, linVelA, linVelB, angVelA, angVelB);
}
else
- { // leave old version for compatibility
- int row = setLinearLimits(info, 0, transA,transB,linVelA,linVelB,angVelA,angVelB);
- setAngularLimits(info, row,transA,transB,linVelA,linVelB,angVelA,angVelB);
+ { // leave old version for compatibility
+ int row = setLinearLimits(info, 0, transA, transB, linVelA, linVelB, angVelA, angVelB);
+ setAngularLimits(info, row, transA, transB, linVelA, linVelB, angVelA, angVelB);
}
}
-
-
-int btGeneric6DofConstraint::setLinearLimits(btConstraintInfo2* info, int row, const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB)
+int btGeneric6DofConstraint::setLinearLimits(btConstraintInfo2* info, int row, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB)
{
-// int row = 0;
+ // int row = 0;
//solve linear limits
btRotationalLimitMotor limot;
- for (int i=0;i<3 ;i++ )
+ for (int i = 0; i < 3; i++)
{
- if(m_linearLimits.needApplyForce(i))
- { // re-use rotational motor code
+ if (m_linearLimits.needApplyForce(i))
+ { // re-use rotational motor code
limot.m_bounce = btScalar(0.f);
limot.m_currentLimit = m_linearLimits.m_currentLimit[i];
limot.m_currentPosition = m_linearLimits.m_currentLinearDiff[i];
- limot.m_currentLimitError = m_linearLimits.m_currentLimitError[i];
- limot.m_damping = m_linearLimits.m_damping;
- limot.m_enableMotor = m_linearLimits.m_enableMotor[i];
- limot.m_hiLimit = m_linearLimits.m_upperLimit[i];
- limot.m_limitSoftness = m_linearLimits.m_limitSoftness;
- limot.m_loLimit = m_linearLimits.m_lowerLimit[i];
- limot.m_maxLimitForce = btScalar(0.f);
- limot.m_maxMotorForce = m_linearLimits.m_maxMotorForce[i];
- limot.m_targetVelocity = m_linearLimits.m_targetVelocity[i];
+ limot.m_currentLimitError = m_linearLimits.m_currentLimitError[i];
+ limot.m_damping = m_linearLimits.m_damping;
+ limot.m_enableMotor = m_linearLimits.m_enableMotor[i];
+ limot.m_hiLimit = m_linearLimits.m_upperLimit[i];
+ limot.m_limitSoftness = m_linearLimits.m_limitSoftness;
+ limot.m_loLimit = m_linearLimits.m_lowerLimit[i];
+ limot.m_maxLimitForce = btScalar(0.f);
+ limot.m_maxMotorForce = m_linearLimits.m_maxMotorForce[i];
+ limot.m_targetVelocity = m_linearLimits.m_targetVelocity[i];
btVector3 axis = m_calculatedTransformA.getBasis().getColumn(i);
int flags = m_flags >> (i * BT_6DOF_FLAGS_AXIS_SHIFT);
- limot.m_normalCFM = (flags & BT_6DOF_FLAGS_CFM_NORM) ? m_linearLimits.m_normalCFM[i] : info->cfm[0];
- limot.m_stopCFM = (flags & BT_6DOF_FLAGS_CFM_STOP) ? m_linearLimits.m_stopCFM[i] : info->cfm[0];
- limot.m_stopERP = (flags & BT_6DOF_FLAGS_ERP_STOP) ? m_linearLimits.m_stopERP[i] : info->erp;
- if(m_useOffsetForConstraintFrame)
+ limot.m_normalCFM = (flags & BT_6DOF_FLAGS_CFM_NORM) ? m_linearLimits.m_normalCFM[i] : info->cfm[0];
+ limot.m_stopCFM = (flags & BT_6DOF_FLAGS_CFM_STOP) ? m_linearLimits.m_stopCFM[i] : info->cfm[0];
+ limot.m_stopERP = (flags & BT_6DOF_FLAGS_ERP_STOP) ? m_linearLimits.m_stopERP[i] : info->erp;
+ if (m_useOffsetForConstraintFrame)
{
int indx1 = (i + 1) % 3;
int indx2 = (i + 2) % 3;
- int rotAllowed = 1; // rotations around orthos to current axis
- if(m_angularLimits[indx1].m_currentLimit && m_angularLimits[indx2].m_currentLimit)
+ int rotAllowed = 1; // rotations around orthos to current axis
+ if (m_angularLimits[indx1].m_currentLimit && m_angularLimits[indx2].m_currentLimit)
{
rotAllowed = 0;
}
- row += get_limit_motor_info2(&limot, transA,transB,linVelA,linVelB,angVelA,angVelB, info, row, axis, 0, rotAllowed);
+ row += get_limit_motor_info2(&limot, transA, transB, linVelA, linVelB, angVelA, angVelB, info, row, axis, 0, rotAllowed);
}
else
{
- row += get_limit_motor_info2(&limot, transA,transB,linVelA,linVelB,angVelA,angVelB, info, row, axis, 0);
+ row += get_limit_motor_info2(&limot, transA, transB, linVelA, linVelB, angVelA, angVelB, info, row, axis, 0);
}
}
}
return row;
}
-
-
-int btGeneric6DofConstraint::setAngularLimits(btConstraintInfo2 *info, int row_offset, const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB)
+int btGeneric6DofConstraint::setAngularLimits(btConstraintInfo2* info, int row_offset, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB)
{
- btGeneric6DofConstraint * d6constraint = this;
+ btGeneric6DofConstraint* d6constraint = this;
int row = row_offset;
//solve angular limits
- for (int i=0;i<3 ;i++ )
+ for (int i = 0; i < 3; i++)
{
- if(d6constraint->getRotationalLimitMotor(i)->needApplyTorques())
+ if (d6constraint->getRotationalLimitMotor(i)->needApplyTorques())
{
btVector3 axis = d6constraint->getAxis(i);
int flags = m_flags >> ((i + 3) * BT_6DOF_FLAGS_AXIS_SHIFT);
- if(!(flags & BT_6DOF_FLAGS_CFM_NORM))
+ if (!(flags & BT_6DOF_FLAGS_CFM_NORM))
{
m_angularLimits[i].m_normalCFM = info->cfm[0];
}
- if(!(flags & BT_6DOF_FLAGS_CFM_STOP))
+ if (!(flags & BT_6DOF_FLAGS_CFM_STOP))
{
m_angularLimits[i].m_stopCFM = info->cfm[0];
}
- if(!(flags & BT_6DOF_FLAGS_ERP_STOP))
+ if (!(flags & BT_6DOF_FLAGS_ERP_STOP))
{
m_angularLimits[i].m_stopERP = info->erp;
}
row += get_limit_motor_info2(d6constraint->getRotationalLimitMotor(i),
- transA,transB,linVelA,linVelB,angVelA,angVelB, info,row,axis,1);
+ transA, transB, linVelA, linVelB, angVelA, angVelB, info, row, axis, 1);
}
}
return row;
}
-
-
-
-void btGeneric6DofConstraint::updateRHS(btScalar timeStep)
+void btGeneric6DofConstraint::updateRHS(btScalar timeStep)
{
(void)timeStep;
-
}
-
void btGeneric6DofConstraint::setFrames(const btTransform& frameA, const btTransform& frameB)
{
m_frameInA = frameA;
@@ -715,33 +642,27 @@ void btGeneric6DofConstraint::setFrames(const btTransform& frameA, const btTrans
calculateTransforms();
}
-
-
btVector3 btGeneric6DofConstraint::getAxis(int axis_index) const
{
return m_calculatedAxis[axis_index];
}
-
-btScalar btGeneric6DofConstraint::getRelativePivotPosition(int axisIndex) const
+btScalar btGeneric6DofConstraint::getRelativePivotPosition(int axisIndex) const
{
return m_calculatedLinearDiff[axisIndex];
}
-
btScalar btGeneric6DofConstraint::getAngle(int axisIndex) const
{
return m_calculatedAxisAngleDiff[axisIndex];
}
-
-
void btGeneric6DofConstraint::calcAnchorPos(void)
{
btScalar imA = m_rbA.getInvMass();
btScalar imB = m_rbB.getInvMass();
btScalar weight;
- if(imB == btScalar(0.0))
+ if (imB == btScalar(0.0))
{
weight = btScalar(1.0);
}
@@ -755,43 +676,39 @@ void btGeneric6DofConstraint::calcAnchorPos(void)
return;
}
-
-
void btGeneric6DofConstraint::calculateLinearInfo()
{
m_calculatedLinearDiff = m_calculatedTransformB.getOrigin() - m_calculatedTransformA.getOrigin();
m_calculatedLinearDiff = m_calculatedTransformA.getBasis().inverse() * m_calculatedLinearDiff;
- for(int i = 0; i < 3; i++)
+ for (int i = 0; i < 3; i++)
{
m_linearLimits.m_currentLinearDiff[i] = m_calculatedLinearDiff[i];
m_linearLimits.testLimitValue(i, m_calculatedLinearDiff[i]);
}
}
-
-
int btGeneric6DofConstraint::get_limit_motor_info2(
- btRotationalLimitMotor * limot,
- const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB,
- btConstraintInfo2 *info, int row, btVector3& ax1, int rotational,int rotAllowed)
-{
- int srow = row * info->rowskip;
- bool powered = limot->m_enableMotor;
- int limit = limot->m_currentLimit;
- if (powered || limit)
- { // if the joint is powered, or has joint limits, add in the extra row
- btScalar *J1 = rotational ? info->m_J1angularAxis : info->m_J1linearAxis;
- btScalar *J2 = rotational ? info->m_J2angularAxis : info->m_J2linearAxis;
- J1[srow+0] = ax1[0];
- J1[srow+1] = ax1[1];
- J1[srow+2] = ax1[2];
-
- J2[srow+0] = -ax1[0];
- J2[srow+1] = -ax1[1];
- J2[srow+2] = -ax1[2];
-
- if((!rotational))
- {
+ btRotationalLimitMotor* limot,
+ const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB,
+ btConstraintInfo2* info, int row, btVector3& ax1, int rotational, int rotAllowed)
+{
+ int srow = row * info->rowskip;
+ bool powered = limot->m_enableMotor;
+ int limit = limot->m_currentLimit;
+ if (powered || limit)
+ { // if the joint is powered, or has joint limits, add in the extra row
+ btScalar* J1 = rotational ? info->m_J1angularAxis : info->m_J1linearAxis;
+ btScalar* J2 = rotational ? info->m_J2angularAxis : info->m_J2linearAxis;
+ J1[srow + 0] = ax1[0];
+ J1[srow + 1] = ax1[1];
+ J1[srow + 2] = ax1[2];
+
+ J2[srow + 0] = -ax1[0];
+ J2[srow + 1] = -ax1[1];
+ J2[srow + 2] = -ax1[2];
+
+ if ((!rotational))
+ {
if (m_useOffsetForConstraintFrame)
{
btVector3 tmpA, tmpB, relA, relB;
@@ -814,55 +731,56 @@ int btGeneric6DofConstraint::get_limit_motor_info2(
relB = orthoB - totalDist * m_factB;
tmpA = relA.cross(ax1);
tmpB = relB.cross(ax1);
- if(m_hasStaticBody && (!rotAllowed))
+ if (m_hasStaticBody && (!rotAllowed))
{
tmpA *= m_factA;
tmpB *= m_factB;
}
int i;
- for (i=0; i<3; i++) info->m_J1angularAxis[srow+i] = tmpA[i];
- for (i=0; i<3; i++) info->m_J2angularAxis[srow+i] = -tmpB[i];
- } else
+ for (i = 0; i < 3; i++) info->m_J1angularAxis[srow + i] = tmpA[i];
+ for (i = 0; i < 3; i++) info->m_J2angularAxis[srow + i] = -tmpB[i];
+ }
+ else
{
- btVector3 ltd; // Linear Torque Decoupling vector
+ btVector3 ltd; // Linear Torque Decoupling vector
btVector3 c = m_calculatedTransformB.getOrigin() - transA.getOrigin();
ltd = c.cross(ax1);
- info->m_J1angularAxis[srow+0] = ltd[0];
- info->m_J1angularAxis[srow+1] = ltd[1];
- info->m_J1angularAxis[srow+2] = ltd[2];
+ info->m_J1angularAxis[srow + 0] = ltd[0];
+ info->m_J1angularAxis[srow + 1] = ltd[1];
+ info->m_J1angularAxis[srow + 2] = ltd[2];
c = m_calculatedTransformB.getOrigin() - transB.getOrigin();
ltd = -c.cross(ax1);
- info->m_J2angularAxis[srow+0] = ltd[0];
- info->m_J2angularAxis[srow+1] = ltd[1];
- info->m_J2angularAxis[srow+2] = ltd[2];
+ info->m_J2angularAxis[srow + 0] = ltd[0];
+ info->m_J2angularAxis[srow + 1] = ltd[1];
+ info->m_J2angularAxis[srow + 2] = ltd[2];
}
- }
- // if we're limited low and high simultaneously, the joint motor is
- // ineffective
- if (limit && (limot->m_loLimit == limot->m_hiLimit)) powered = false;
- info->m_constraintError[srow] = btScalar(0.f);
- if (powered)
- {
+ }
+ // if we're limited low and high simultaneously, the joint motor is
+ // ineffective
+ if (limit && (limot->m_loLimit == limot->m_hiLimit)) powered = false;
+ info->m_constraintError[srow] = btScalar(0.f);
+ if (powered)
+ {
info->cfm[srow] = limot->m_normalCFM;
- if(!limit)
- {
+ if (!limit)
+ {
btScalar tag_vel = rotational ? limot->m_targetVelocity : -limot->m_targetVelocity;
- btScalar mot_fact = getMotorFactor( limot->m_currentPosition,
- limot->m_loLimit,
- limot->m_hiLimit,
- tag_vel,
- info->fps * limot->m_stopERP);
+ btScalar mot_fact = getMotorFactor(limot->m_currentPosition,
+ limot->m_loLimit,
+ limot->m_hiLimit,
+ tag_vel,
+ info->fps * limot->m_stopERP);
info->m_constraintError[srow] += mot_fact * limot->m_targetVelocity;
- info->m_lowerLimit[srow] = -limot->m_maxMotorForce / info->fps;
- info->m_upperLimit[srow] = limot->m_maxMotorForce / info->fps;
- }
- }
- if(limit)
- {
- btScalar k = info->fps * limot->m_stopERP;
- if(!rotational)
+ info->m_lowerLimit[srow] = -limot->m_maxMotorForce / info->fps;
+ info->m_upperLimit[srow] = limot->m_maxMotorForce / info->fps;
+ }
+ }
+ if (limit)
+ {
+ btScalar k = info->fps * limot->m_stopERP;
+ if (!rotational)
{
info->m_constraintError[srow] += k * limot->m_currentLimitError;
}
@@ -871,116 +789,112 @@ int btGeneric6DofConstraint::get_limit_motor_info2(
info->m_constraintError[srow] += -k * limot->m_currentLimitError;
}
info->cfm[srow] = limot->m_stopCFM;
- if (limot->m_loLimit == limot->m_hiLimit)
- { // limited low and high simultaneously
- info->m_lowerLimit[srow] = -SIMD_INFINITY;
- info->m_upperLimit[srow] = SIMD_INFINITY;
- }
- else
- {
- if (limit == 1)
- {
- info->m_lowerLimit[srow] = 0;
- info->m_upperLimit[srow] = SIMD_INFINITY;
- }
- else
- {
- info->m_lowerLimit[srow] = -SIMD_INFINITY;
- info->m_upperLimit[srow] = 0;
- }
- // deal with bounce
- if (limot->m_bounce > 0)
- {
- // calculate joint velocity
- btScalar vel;
- if (rotational)
- {
- vel = angVelA.dot(ax1);
-//make sure that if no body -> angVelB == zero vec
-// if (body1)
- vel -= angVelB.dot(ax1);
- }
- else
- {
- vel = linVelA.dot(ax1);
-//make sure that if no body -> angVelB == zero vec
-// if (body1)
- vel -= linVelB.dot(ax1);
- }
- // only apply bounce if the velocity is incoming, and if the
- // resulting c[] exceeds what we already have.
- if (limit == 1)
- {
- if (vel < 0)
- {
- btScalar newc = -limot->m_bounce* vel;
- if (newc > info->m_constraintError[srow])
+ if (limot->m_loLimit == limot->m_hiLimit)
+ { // limited low and high simultaneously
+ info->m_lowerLimit[srow] = -SIMD_INFINITY;
+ info->m_upperLimit[srow] = SIMD_INFINITY;
+ }
+ else
+ {
+ if (limit == 1)
+ {
+ info->m_lowerLimit[srow] = 0;
+ info->m_upperLimit[srow] = SIMD_INFINITY;
+ }
+ else
+ {
+ info->m_lowerLimit[srow] = -SIMD_INFINITY;
+ info->m_upperLimit[srow] = 0;
+ }
+ // deal with bounce
+ if (limot->m_bounce > 0)
+ {
+ // calculate joint velocity
+ btScalar vel;
+ if (rotational)
+ {
+ vel = angVelA.dot(ax1);
+ //make sure that if no body -> angVelB == zero vec
+ // if (body1)
+ vel -= angVelB.dot(ax1);
+ }
+ else
+ {
+ vel = linVelA.dot(ax1);
+ //make sure that if no body -> angVelB == zero vec
+ // if (body1)
+ vel -= linVelB.dot(ax1);
+ }
+ // only apply bounce if the velocity is incoming, and if the
+ // resulting c[] exceeds what we already have.
+ if (limit == 1)
+ {
+ if (vel < 0)
+ {
+ btScalar newc = -limot->m_bounce * vel;
+ if (newc > info->m_constraintError[srow])
info->m_constraintError[srow] = newc;
- }
- }
- else
- {
- if (vel > 0)
- {
- btScalar newc = -limot->m_bounce * vel;
- if (newc < info->m_constraintError[srow])
+ }
+ }
+ else
+ {
+ if (vel > 0)
+ {
+ btScalar newc = -limot->m_bounce * vel;
+ if (newc < info->m_constraintError[srow])
info->m_constraintError[srow] = newc;
- }
- }
- }
- }
- }
- return 1;
- }
- else return 0;
+ }
+ }
+ }
+ }
+ }
+ return 1;
+ }
+ else
+ return 0;
}
-
-
-
-
-
- ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
- ///If no axis is provided, it uses the default axis for this constraint.
+///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+///If no axis is provided, it uses the default axis for this constraint.
void btGeneric6DofConstraint::setParam(int num, btScalar value, int axis)
{
- if((axis >= 0) && (axis < 3))
+ if ((axis >= 0) && (axis < 3))
{
- switch(num)
+ switch (num)
{
- case BT_CONSTRAINT_STOP_ERP :
+ case BT_CONSTRAINT_STOP_ERP:
m_linearLimits.m_stopERP[axis] = value;
m_flags |= BT_6DOF_FLAGS_ERP_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT);
break;
- case BT_CONSTRAINT_STOP_CFM :
+ case BT_CONSTRAINT_STOP_CFM:
m_linearLimits.m_stopCFM[axis] = value;
m_flags |= BT_6DOF_FLAGS_CFM_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT);
break;
- case BT_CONSTRAINT_CFM :
+ case BT_CONSTRAINT_CFM:
m_linearLimits.m_normalCFM[axis] = value;
m_flags |= BT_6DOF_FLAGS_CFM_NORM << (axis * BT_6DOF_FLAGS_AXIS_SHIFT);
break;
- default :
+ default:
btAssertConstrParams(0);
}
}
- else if((axis >=3) && (axis < 6))
+ else if ((axis >= 3) && (axis < 6))
{
- switch(num)
+ switch (num)
{
- case BT_CONSTRAINT_STOP_ERP :
+ case BT_CONSTRAINT_STOP_ERP:
m_angularLimits[axis - 3].m_stopERP = value;
m_flags |= BT_6DOF_FLAGS_ERP_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT);
break;
- case BT_CONSTRAINT_STOP_CFM :
+ case BT_CONSTRAINT_STOP_CFM:
m_angularLimits[axis - 3].m_stopCFM = value;
m_flags |= BT_6DOF_FLAGS_CFM_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT);
break;
- case BT_CONSTRAINT_CFM :
+ case BT_CONSTRAINT_CFM:
m_angularLimits[axis - 3].m_normalCFM = value;
m_flags |= BT_6DOF_FLAGS_CFM_NORM << (axis * BT_6DOF_FLAGS_AXIS_SHIFT);
break;
- default :
+ default:
btAssertConstrParams(0);
}
}
@@ -990,47 +904,47 @@ void btGeneric6DofConstraint::setParam(int num, btScalar value, int axis)
}
}
- ///return the local value of parameter
-btScalar btGeneric6DofConstraint::getParam(int num, int axis) const
+///return the local value of parameter
+btScalar btGeneric6DofConstraint::getParam(int num, int axis) const
{
btScalar retVal = 0;
- if((axis >= 0) && (axis < 3))
+ if ((axis >= 0) && (axis < 3))
{
- switch(num)
+ switch (num)
{
- case BT_CONSTRAINT_STOP_ERP :
+ case BT_CONSTRAINT_STOP_ERP:
btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_ERP_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT)));
retVal = m_linearLimits.m_stopERP[axis];
break;
- case BT_CONSTRAINT_STOP_CFM :
+ case BT_CONSTRAINT_STOP_CFM:
btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT)));
retVal = m_linearLimits.m_stopCFM[axis];
break;
- case BT_CONSTRAINT_CFM :
+ case BT_CONSTRAINT_CFM:
btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_NORM << (axis * BT_6DOF_FLAGS_AXIS_SHIFT)));
retVal = m_linearLimits.m_normalCFM[axis];
break;
- default :
+ default:
btAssertConstrParams(0);
}
}
- else if((axis >=3) && (axis < 6))
+ else if ((axis >= 3) && (axis < 6))
{
- switch(num)
+ switch (num)
{
- case BT_CONSTRAINT_STOP_ERP :
+ case BT_CONSTRAINT_STOP_ERP:
btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_ERP_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT)));
retVal = m_angularLimits[axis - 3].m_stopERP;
break;
- case BT_CONSTRAINT_STOP_CFM :
+ case BT_CONSTRAINT_STOP_CFM:
btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT)));
retVal = m_angularLimits[axis - 3].m_stopCFM;
break;
- case BT_CONSTRAINT_CFM :
+ case BT_CONSTRAINT_CFM:
btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_NORM << (axis * BT_6DOF_FLAGS_AXIS_SHIFT)));
retVal = m_angularLimits[axis - 3].m_normalCFM;
break;
- default :
+ default:
btAssertConstrParams(0);
}
}
@@ -1041,23 +955,21 @@ btScalar btGeneric6DofConstraint::getParam(int num, int axis) const
return retVal;
}
-
-
-void btGeneric6DofConstraint::setAxis(const btVector3& axis1,const btVector3& axis2)
+void btGeneric6DofConstraint::setAxis(const btVector3& axis1, const btVector3& axis2)
{
btVector3 zAxis = axis1.normalized();
btVector3 yAxis = axis2.normalized();
- btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system
-
+ btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system
+
btTransform frameInW;
frameInW.setIdentity();
- frameInW.getBasis().setValue( xAxis[0], yAxis[0], zAxis[0],
- xAxis[1], yAxis[1], zAxis[1],
- xAxis[2], yAxis[2], zAxis[2]);
-
+ frameInW.getBasis().setValue(xAxis[0], yAxis[0], zAxis[0],
+ xAxis[1], yAxis[1], zAxis[1],
+ xAxis[2], yAxis[2], zAxis[2]);
+
// now get constraint frame in local coordinate systems
m_frameInA = m_rbA.getCenterOfMassTransform().inverse() * frameInW;
m_frameInB = m_rbB.getCenterOfMassTransform().inverse() * frameInW;
-
+
calculateTransforms();
}
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h
index b2ad45f749..b9e762e175 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h
@@ -23,7 +23,6 @@ email: projectileman@yahoo.com
http://gimpact.sf.net
*/
-
#ifndef BT_GENERIC_6DOF_CONSTRAINT_H
#define BT_GENERIC_6DOF_CONSTRAINT_H
@@ -33,96 +32,91 @@ http://gimpact.sf.net
class btRigidBody;
-
-
#ifdef BT_USE_DOUBLE_PRECISION
-#define btGeneric6DofConstraintData2 btGeneric6DofConstraintDoubleData2
-#define btGeneric6DofConstraintDataName "btGeneric6DofConstraintDoubleData2"
+#define btGeneric6DofConstraintData2 btGeneric6DofConstraintDoubleData2
+#define btGeneric6DofConstraintDataName "btGeneric6DofConstraintDoubleData2"
#else
-#define btGeneric6DofConstraintData2 btGeneric6DofConstraintData
-#define btGeneric6DofConstraintDataName "btGeneric6DofConstraintData"
-#endif //BT_USE_DOUBLE_PRECISION
-
+#define btGeneric6DofConstraintData2 btGeneric6DofConstraintData
+#define btGeneric6DofConstraintDataName "btGeneric6DofConstraintData"
+#endif //BT_USE_DOUBLE_PRECISION
//! Rotation Limit structure for generic joints
class btRotationalLimitMotor
{
public:
- //! limit_parameters
- //!@{
- btScalar m_loLimit;//!< joint limit
- btScalar m_hiLimit;//!< joint limit
- btScalar m_targetVelocity;//!< target motor velocity
- btScalar m_maxMotorForce;//!< max force on motor
- btScalar m_maxLimitForce;//!< max force on limit
- btScalar m_damping;//!< Damping.
- btScalar m_limitSoftness;//! Relaxation factor
- btScalar m_normalCFM;//!< Constraint force mixing factor
- btScalar m_stopERP;//!< Error tolerance factor when joint is at limit
- btScalar m_stopCFM;//!< Constraint force mixing factor when joint is at limit
- btScalar m_bounce;//!< restitution factor
- bool m_enableMotor;
-
- //!@}
-
- //! temp_variables
- //!@{
- btScalar m_currentLimitError;//! How much is violated this limit
- btScalar m_currentPosition; //! current value of angle
- int m_currentLimit;//!< 0=free, 1=at lo limit, 2=at hi limit
- btScalar m_accumulatedImpulse;
- //!@}
-
- btRotationalLimitMotor()
- {
- m_accumulatedImpulse = 0.f;
- m_targetVelocity = 0;
- m_maxMotorForce = 6.0f;
- m_maxLimitForce = 300.0f;
- m_loLimit = 1.0f;
- m_hiLimit = -1.0f;
+ //! limit_parameters
+ //!@{
+ btScalar m_loLimit; //!< joint limit
+ btScalar m_hiLimit; //!< joint limit
+ btScalar m_targetVelocity; //!< target motor velocity
+ btScalar m_maxMotorForce; //!< max force on motor
+ btScalar m_maxLimitForce; //!< max force on limit
+ btScalar m_damping; //!< Damping.
+ btScalar m_limitSoftness; //! Relaxation factor
+ btScalar m_normalCFM; //!< Constraint force mixing factor
+ btScalar m_stopERP; //!< Error tolerance factor when joint is at limit
+ btScalar m_stopCFM; //!< Constraint force mixing factor when joint is at limit
+ btScalar m_bounce; //!< restitution factor
+ bool m_enableMotor;
+
+ //!@}
+
+ //! temp_variables
+ //!@{
+ btScalar m_currentLimitError; //! How much is violated this limit
+ btScalar m_currentPosition; //! current value of angle
+ int m_currentLimit; //!< 0=free, 1=at lo limit, 2=at hi limit
+ btScalar m_accumulatedImpulse;
+ //!@}
+
+ btRotationalLimitMotor()
+ {
+ m_accumulatedImpulse = 0.f;
+ m_targetVelocity = 0;
+ m_maxMotorForce = 6.0f;
+ m_maxLimitForce = 300.0f;
+ m_loLimit = 1.0f;
+ m_hiLimit = -1.0f;
m_normalCFM = 0.f;
m_stopERP = 0.2f;
m_stopCFM = 0.f;
- m_bounce = 0.0f;
- m_damping = 1.0f;
- m_limitSoftness = 0.5f;
- m_currentLimit = 0;
- m_currentLimitError = 0;
- m_enableMotor = false;
- }
-
- btRotationalLimitMotor(const btRotationalLimitMotor & limot)
- {
- m_targetVelocity = limot.m_targetVelocity;
- m_maxMotorForce = limot.m_maxMotorForce;
- m_limitSoftness = limot.m_limitSoftness;
- m_loLimit = limot.m_loLimit;
- m_hiLimit = limot.m_hiLimit;
+ m_bounce = 0.0f;
+ m_damping = 1.0f;
+ m_limitSoftness = 0.5f;
+ m_currentLimit = 0;
+ m_currentLimitError = 0;
+ m_enableMotor = false;
+ }
+
+ btRotationalLimitMotor(const btRotationalLimitMotor& limot)
+ {
+ m_targetVelocity = limot.m_targetVelocity;
+ m_maxMotorForce = limot.m_maxMotorForce;
+ m_limitSoftness = limot.m_limitSoftness;
+ m_loLimit = limot.m_loLimit;
+ m_hiLimit = limot.m_hiLimit;
m_normalCFM = limot.m_normalCFM;
m_stopERP = limot.m_stopERP;
- m_stopCFM = limot.m_stopCFM;
- m_bounce = limot.m_bounce;
- m_currentLimit = limot.m_currentLimit;
- m_currentLimitError = limot.m_currentLimitError;
- m_enableMotor = limot.m_enableMotor;
- }
-
-
+ m_stopCFM = limot.m_stopCFM;
+ m_bounce = limot.m_bounce;
+ m_currentLimit = limot.m_currentLimit;
+ m_currentLimitError = limot.m_currentLimitError;
+ m_enableMotor = limot.m_enableMotor;
+ }
//! Is limited
- bool isLimited() const
- {
- if(m_loLimit > m_hiLimit) return false;
- return true;
- }
+ bool isLimited() const
+ {
+ if (m_loLimit > m_hiLimit) return false;
+ return true;
+ }
//! Need apply correction
- bool needApplyTorques() const
- {
- if(m_currentLimit == 0 && m_enableMotor == false) return false;
- return true;
- }
+ bool needApplyTorques() const
+ {
+ if (m_currentLimit == 0 && m_enableMotor == false) return false;
+ return true;
+ }
//! calculates error
/*!
@@ -131,104 +125,98 @@ public:
int testLimitValue(btScalar test_value);
//! apply the correction impulses for two bodies
- btScalar solveAngularLimits(btScalar timeStep,btVector3& axis, btScalar jacDiagABInv,btRigidBody * body0, btRigidBody * body1);
-
+ btScalar solveAngularLimits(btScalar timeStep, btVector3& axis, btScalar jacDiagABInv, btRigidBody* body0, btRigidBody* body1);
};
-
-
class btTranslationalLimitMotor
{
public:
- btVector3 m_lowerLimit;//!< the constraint lower limits
- btVector3 m_upperLimit;//!< the constraint upper limits
- btVector3 m_accumulatedImpulse;
- //! Linear_Limit_parameters
- //!@{
- btScalar m_limitSoftness;//!< Softness for linear limit
- btScalar m_damping;//!< Damping for linear limit
- btScalar m_restitution;//! Bounce parameter for linear limit
- btVector3 m_normalCFM;//!< Constraint force mixing factor
- btVector3 m_stopERP;//!< Error tolerance factor when joint is at limit
- btVector3 m_stopCFM;//!< Constraint force mixing factor when joint is at limit
- //!@}
- bool m_enableMotor[3];
- btVector3 m_targetVelocity;//!< target motor velocity
- btVector3 m_maxMotorForce;//!< max force on motor
- btVector3 m_currentLimitError;//! How much is violated this limit
- btVector3 m_currentLinearDiff;//! Current relative offset of constraint frames
- int m_currentLimit[3];//!< 0=free, 1=at lower limit, 2=at upper limit
-
- btTranslationalLimitMotor()
- {
- m_lowerLimit.setValue(0.f,0.f,0.f);
- m_upperLimit.setValue(0.f,0.f,0.f);
- m_accumulatedImpulse.setValue(0.f,0.f,0.f);
+ btVector3 m_lowerLimit; //!< the constraint lower limits
+ btVector3 m_upperLimit; //!< the constraint upper limits
+ btVector3 m_accumulatedImpulse;
+ //! Linear_Limit_parameters
+ //!@{
+ btScalar m_limitSoftness; //!< Softness for linear limit
+ btScalar m_damping; //!< Damping for linear limit
+ btScalar m_restitution; //! Bounce parameter for linear limit
+ btVector3 m_normalCFM; //!< Constraint force mixing factor
+ btVector3 m_stopERP; //!< Error tolerance factor when joint is at limit
+ btVector3 m_stopCFM; //!< Constraint force mixing factor when joint is at limit
+ //!@}
+ bool m_enableMotor[3];
+ btVector3 m_targetVelocity; //!< target motor velocity
+ btVector3 m_maxMotorForce; //!< max force on motor
+ btVector3 m_currentLimitError; //! How much is violated this limit
+ btVector3 m_currentLinearDiff; //! Current relative offset of constraint frames
+ int m_currentLimit[3]; //!< 0=free, 1=at lower limit, 2=at upper limit
+
+ btTranslationalLimitMotor()
+ {
+ m_lowerLimit.setValue(0.f, 0.f, 0.f);
+ m_upperLimit.setValue(0.f, 0.f, 0.f);
+ m_accumulatedImpulse.setValue(0.f, 0.f, 0.f);
m_normalCFM.setValue(0.f, 0.f, 0.f);
m_stopERP.setValue(0.2f, 0.2f, 0.2f);
m_stopCFM.setValue(0.f, 0.f, 0.f);
- m_limitSoftness = 0.7f;
- m_damping = btScalar(1.0f);
- m_restitution = btScalar(0.5f);
- for(int i=0; i < 3; i++)
+ m_limitSoftness = 0.7f;
+ m_damping = btScalar(1.0f);
+ m_restitution = btScalar(0.5f);
+ for (int i = 0; i < 3; i++)
{
m_enableMotor[i] = false;
m_targetVelocity[i] = btScalar(0.f);
m_maxMotorForce[i] = btScalar(0.f);
}
- }
+ }
- btTranslationalLimitMotor(const btTranslationalLimitMotor & other )
- {
- m_lowerLimit = other.m_lowerLimit;
- m_upperLimit = other.m_upperLimit;
- m_accumulatedImpulse = other.m_accumulatedImpulse;
+ btTranslationalLimitMotor(const btTranslationalLimitMotor& other)
+ {
+ m_lowerLimit = other.m_lowerLimit;
+ m_upperLimit = other.m_upperLimit;
+ m_accumulatedImpulse = other.m_accumulatedImpulse;
- m_limitSoftness = other.m_limitSoftness ;
- m_damping = other.m_damping;
- m_restitution = other.m_restitution;
+ m_limitSoftness = other.m_limitSoftness;
+ m_damping = other.m_damping;
+ m_restitution = other.m_restitution;
m_normalCFM = other.m_normalCFM;
m_stopERP = other.m_stopERP;
m_stopCFM = other.m_stopCFM;
- for(int i=0; i < 3; i++)
+ for (int i = 0; i < 3; i++)
{
m_enableMotor[i] = other.m_enableMotor[i];
m_targetVelocity[i] = other.m_targetVelocity[i];
m_maxMotorForce[i] = other.m_maxMotorForce[i];
}
- }
+ }
- //! Test limit
+ //! Test limit
/*!
- free means upper < lower,
- locked means upper == lower
- limited means upper > lower
- limitIndex: first 3 are linear, next 3 are angular
*/
- inline bool isLimited(int limitIndex) const
- {
- return (m_upperLimit[limitIndex] >= m_lowerLimit[limitIndex]);
- }
- inline bool needApplyForce(int limitIndex) const
- {
- if(m_currentLimit[limitIndex] == 0 && m_enableMotor[limitIndex] == false) return false;
- return true;
- }
+ inline bool isLimited(int limitIndex) const
+ {
+ return (m_upperLimit[limitIndex] >= m_lowerLimit[limitIndex]);
+ }
+ inline bool needApplyForce(int limitIndex) const
+ {
+ if (m_currentLimit[limitIndex] == 0 && m_enableMotor[limitIndex] == false) return false;
+ return true;
+ }
int testLimitValue(int limitIndex, btScalar test_value);
-
- btScalar solveLinearAxis(
- btScalar timeStep,
- btScalar jacDiagABInv,
- btRigidBody& body1,const btVector3 &pointInA,
- btRigidBody& body2,const btVector3 &pointInB,
- int limit_index,
- const btVector3 & axis_normal_on_a,
- const btVector3 & anchorPos);
-
-
+ btScalar solveLinearAxis(
+ btScalar timeStep,
+ btScalar jacDiagABInv,
+ btRigidBody& body1, const btVector3& pointInA,
+ btRigidBody& body2, const btVector3& pointInB,
+ int limit_index,
+ const btVector3& axis_normal_on_a,
+ const btVector3& anchorPos);
};
enum bt6DofFlags
@@ -237,8 +225,7 @@ enum bt6DofFlags
BT_6DOF_FLAGS_CFM_STOP = 2,
BT_6DOF_FLAGS_ERP_STOP = 4
};
-#define BT_6DOF_FLAGS_AXIS_SHIFT 3 // bits per axis
-
+#define BT_6DOF_FLAGS_AXIS_SHIFT 3 // bits per axis
/// btGeneric6DofConstraint between two rigidbodies each with a pivotpoint that descibes the axis location in local space
/*!
@@ -276,254 +263,245 @@ This brings support for limit parameters and motors. </li>
</ul>
*/
-ATTRIBUTE_ALIGNED16(class) btGeneric6DofConstraint : public btTypedConstraint
+ATTRIBUTE_ALIGNED16(class)
+btGeneric6DofConstraint : public btTypedConstraint
{
protected:
-
//! relative_frames
- //!@{
- btTransform m_frameInA;//!< the constraint space w.r.t body A
- btTransform m_frameInB;//!< the constraint space w.r.t body B
- //!@}
+ //!@{
+ btTransform m_frameInA; //!< the constraint space w.r.t body A
+ btTransform m_frameInB; //!< the constraint space w.r.t body B
+ //!@}
- //! Jacobians
- //!@{
- btJacobianEntry m_jacLinear[3];//!< 3 orthogonal linear constraints
- btJacobianEntry m_jacAng[3];//!< 3 orthogonal angular constraints
- //!@}
+ //! Jacobians
+ //!@{
+ btJacobianEntry m_jacLinear[3]; //!< 3 orthogonal linear constraints
+ btJacobianEntry m_jacAng[3]; //!< 3 orthogonal angular constraints
+ //!@}
//! Linear_Limit_parameters
- //!@{
- btTranslationalLimitMotor m_linearLimits;
- //!@}
-
-
- //! hinge_parameters
- //!@{
- btRotationalLimitMotor m_angularLimits[3];
+ //!@{
+ btTranslationalLimitMotor m_linearLimits;
//!@}
+ //! hinge_parameters
+ //!@{
+ btRotationalLimitMotor m_angularLimits[3];
+ //!@}
protected:
- //! temporal variables
- //!@{
- btScalar m_timeStep;
- btTransform m_calculatedTransformA;
- btTransform m_calculatedTransformB;
- btVector3 m_calculatedAxisAngleDiff;
- btVector3 m_calculatedAxis[3];
- btVector3 m_calculatedLinearDiff;
- btScalar m_factA;
- btScalar m_factB;
- bool m_hasStaticBody;
-
- btVector3 m_AnchorPos; // point betwen pivots of bodies A and B to solve linear axes
+ //! temporal variables
+ //!@{
+ btScalar m_timeStep;
+ btTransform m_calculatedTransformA;
+ btTransform m_calculatedTransformB;
+ btVector3 m_calculatedAxisAngleDiff;
+ btVector3 m_calculatedAxis[3];
+ btVector3 m_calculatedLinearDiff;
+ btScalar m_factA;
+ btScalar m_factB;
+ bool m_hasStaticBody;
- bool m_useLinearReferenceFrameA;
- bool m_useOffsetForConstraintFrame;
-
- int m_flags;
+ btVector3 m_AnchorPos; // point betwen pivots of bodies A and B to solve linear axes
- //!@}
+ bool m_useLinearReferenceFrameA;
+ bool m_useOffsetForConstraintFrame;
- btGeneric6DofConstraint& operator=(btGeneric6DofConstraint& other)
- {
- btAssert(0);
- (void) other;
- return *this;
- }
+ int m_flags;
+ //!@}
- int setAngularLimits(btConstraintInfo2 *info, int row_offset,const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB);
+ btGeneric6DofConstraint& operator=(btGeneric6DofConstraint& other)
+ {
+ btAssert(0);
+ (void)other;
+ return *this;
+ }
- int setLinearLimits(btConstraintInfo2 *info, int row, const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB);
+ int setAngularLimits(btConstraintInfo2 * info, int row_offset, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB);
- void buildLinearJacobian(
- btJacobianEntry & jacLinear,const btVector3 & normalWorld,
- const btVector3 & pivotAInW,const btVector3 & pivotBInW);
+ int setLinearLimits(btConstraintInfo2 * info, int row, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB);
- void buildAngularJacobian(btJacobianEntry & jacAngular,const btVector3 & jointAxisW);
+ void buildLinearJacobian(
+ btJacobianEntry & jacLinear, const btVector3& normalWorld,
+ const btVector3& pivotAInW, const btVector3& pivotBInW);
+
+ void buildAngularJacobian(btJacobianEntry & jacAngular, const btVector3& jointAxisW);
// tests linear limits
void calculateLinearInfo();
//! calcs the euler angles between the two bodies.
- void calculateAngleInfo();
-
-
+ void calculateAngleInfo();
public:
-
BT_DECLARE_ALIGNED_ALLOCATOR();
-
+
///for backwards compatibility during the transition to 'getInfo/getInfo2'
- bool m_useSolveConstraintObsolete;
+ bool m_useSolveConstraintObsolete;
+
+ btGeneric6DofConstraint(btRigidBody & rbA, btRigidBody & rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA);
+ btGeneric6DofConstraint(btRigidBody & rbB, const btTransform& frameInB, bool useLinearReferenceFrameB);
- btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA);
- btGeneric6DofConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameB);
-
//! Calcs global transform of the offsets
/*!
Calcs the global transform for the joint offset for body A an B, and also calcs the agle differences between the bodies.
\sa btGeneric6DofConstraint.getCalculatedTransformA , btGeneric6DofConstraint.getCalculatedTransformB, btGeneric6DofConstraint.calculateAngleInfo
*/
- void calculateTransforms(const btTransform& transA,const btTransform& transB);
+ void calculateTransforms(const btTransform& transA, const btTransform& transB);
void calculateTransforms();
//! Gets the global transform of the offset for body A
- /*!
+ /*!
\sa btGeneric6DofConstraint.getFrameOffsetA, btGeneric6DofConstraint.getFrameOffsetB, btGeneric6DofConstraint.calculateAngleInfo.
*/
- const btTransform & getCalculatedTransformA() const
- {
- return m_calculatedTransformA;
- }
+ const btTransform& getCalculatedTransformA() const
+ {
+ return m_calculatedTransformA;
+ }
- //! Gets the global transform of the offset for body B
- /*!
+ //! Gets the global transform of the offset for body B
+ /*!
\sa btGeneric6DofConstraint.getFrameOffsetA, btGeneric6DofConstraint.getFrameOffsetB, btGeneric6DofConstraint.calculateAngleInfo.
*/
- const btTransform & getCalculatedTransformB() const
- {
- return m_calculatedTransformB;
- }
-
- const btTransform & getFrameOffsetA() const
- {
- return m_frameInA;
- }
-
- const btTransform & getFrameOffsetB() const
- {
- return m_frameInB;
- }
+ const btTransform& getCalculatedTransformB() const
+ {
+ return m_calculatedTransformB;
+ }
+ const btTransform& getFrameOffsetA() const
+ {
+ return m_frameInA;
+ }
- btTransform & getFrameOffsetA()
- {
- return m_frameInA;
- }
+ const btTransform& getFrameOffsetB() const
+ {
+ return m_frameInB;
+ }
- btTransform & getFrameOffsetB()
- {
- return m_frameInB;
- }
+ btTransform& getFrameOffsetA()
+ {
+ return m_frameInA;
+ }
+ btTransform& getFrameOffsetB()
+ {
+ return m_frameInB;
+ }
//! performs Jacobian calculation, and also calculates angle differences and axis
- virtual void buildJacobian();
-
- virtual void getInfo1 (btConstraintInfo1* info);
+ virtual void buildJacobian();
- void getInfo1NonVirtual (btConstraintInfo1* info);
+ virtual void getInfo1(btConstraintInfo1 * info);
- virtual void getInfo2 (btConstraintInfo2* info);
+ void getInfo1NonVirtual(btConstraintInfo1 * info);
- void getInfo2NonVirtual (btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB);
+ virtual void getInfo2(btConstraintInfo2 * info);
+ void getInfo2NonVirtual(btConstraintInfo2 * info, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB);
- void updateRHS(btScalar timeStep);
+ void updateRHS(btScalar timeStep);
//! Get the rotation axis in global coordinates
/*!
\pre btGeneric6DofConstraint.buildJacobian must be called previously.
*/
- btVector3 getAxis(int axis_index) const;
+ btVector3 getAxis(int axis_index) const;
- //! Get the relative Euler angle
- /*!
+ //! Get the relative Euler angle
+ /*!
\pre btGeneric6DofConstraint::calculateTransforms() must be called previously.
*/
- btScalar getAngle(int axis_index) const;
+ btScalar getAngle(int axis_index) const;
//! Get the relative position of the constraint pivot
- /*!
+ /*!
\pre btGeneric6DofConstraint::calculateTransforms() must be called previously.
*/
btScalar getRelativePivotPosition(int axis_index) const;
- void setFrames(const btTransform & frameA, const btTransform & frameB);
+ void setFrames(const btTransform& frameA, const btTransform& frameB);
//! Test angular limit.
/*!
Calculates angular correction and returns true if limit needs to be corrected.
\pre btGeneric6DofConstraint::calculateTransforms() must be called previously.
*/
- bool testAngularLimitMotor(int axis_index);
+ bool testAngularLimitMotor(int axis_index);
- void setLinearLowerLimit(const btVector3& linearLower)
- {
- m_linearLimits.m_lowerLimit = linearLower;
- }
+ void setLinearLowerLimit(const btVector3& linearLower)
+ {
+ m_linearLimits.m_lowerLimit = linearLower;
+ }
- void getLinearLowerLimit(btVector3& linearLower) const
+ void getLinearLowerLimit(btVector3 & linearLower) const
{
linearLower = m_linearLimits.m_lowerLimit;
}
- void setLinearUpperLimit(const btVector3& linearUpper)
+ void setLinearUpperLimit(const btVector3& linearUpper)
{
m_linearLimits.m_upperLimit = linearUpper;
}
- void getLinearUpperLimit(btVector3& linearUpper) const
+ void getLinearUpperLimit(btVector3 & linearUpper) const
{
linearUpper = m_linearLimits.m_upperLimit;
}
- void setAngularLowerLimit(const btVector3& angularLower)
- {
- for(int i = 0; i < 3; i++)
+ void setAngularLowerLimit(const btVector3& angularLower)
+ {
+ for (int i = 0; i < 3; i++)
m_angularLimits[i].m_loLimit = btNormalizeAngle(angularLower[i]);
- }
+ }
- void getAngularLowerLimit(btVector3& angularLower) const
+ void getAngularLowerLimit(btVector3 & angularLower) const
{
- for(int i = 0; i < 3; i++)
+ for (int i = 0; i < 3; i++)
angularLower[i] = m_angularLimits[i].m_loLimit;
}
- void setAngularUpperLimit(const btVector3& angularUpper)
- {
- for(int i = 0; i < 3; i++)
+ void setAngularUpperLimit(const btVector3& angularUpper)
+ {
+ for (int i = 0; i < 3; i++)
m_angularLimits[i].m_hiLimit = btNormalizeAngle(angularUpper[i]);
- }
+ }
- void getAngularUpperLimit(btVector3& angularUpper) const
+ void getAngularUpperLimit(btVector3 & angularUpper) const
{
- for(int i = 0; i < 3; i++)
+ for (int i = 0; i < 3; i++)
angularUpper[i] = m_angularLimits[i].m_hiLimit;
}
//! Retrieves the angular limit informacion
- btRotationalLimitMotor * getRotationalLimitMotor(int index)
- {
- return &m_angularLimits[index];
- }
-
- //! Retrieves the limit informacion
- btTranslationalLimitMotor * getTranslationalLimitMotor()
- {
- return &m_linearLimits;
- }
-
- //first 3 are linear, next 3 are angular
- void setLimit(int axis, btScalar lo, btScalar hi)
- {
- if(axis<3)
- {
- m_linearLimits.m_lowerLimit[axis] = lo;
- m_linearLimits.m_upperLimit[axis] = hi;
- }
- else
- {
+ btRotationalLimitMotor* getRotationalLimitMotor(int index)
+ {
+ return &m_angularLimits[index];
+ }
+
+ //! Retrieves the limit informacion
+ btTranslationalLimitMotor* getTranslationalLimitMotor()
+ {
+ return &m_linearLimits;
+ }
+
+ //first 3 are linear, next 3 are angular
+ void setLimit(int axis, btScalar lo, btScalar hi)
+ {
+ if (axis < 3)
+ {
+ m_linearLimits.m_lowerLimit[axis] = lo;
+ m_linearLimits.m_upperLimit[axis] = hi;
+ }
+ else
+ {
lo = btNormalizeAngle(lo);
hi = btNormalizeAngle(hi);
- m_angularLimits[axis-3].m_loLimit = lo;
- m_angularLimits[axis-3].m_hiLimit = hi;
- }
- }
+ m_angularLimits[axis - 3].m_loLimit = lo;
+ m_angularLimits[axis - 3].m_hiLimit = hi;
+ }
+ }
//! Test limit
/*!
@@ -532,116 +510,106 @@ public:
- limited means upper > lower
- limitIndex: first 3 are linear, next 3 are angular
*/
- bool isLimited(int limitIndex) const
- {
- if(limitIndex<3)
- {
+ bool isLimited(int limitIndex) const
+ {
+ if (limitIndex < 3)
+ {
return m_linearLimits.isLimited(limitIndex);
+ }
+ return m_angularLimits[limitIndex - 3].isLimited();
+ }
- }
- return m_angularLimits[limitIndex-3].isLimited();
- }
-
- virtual void calcAnchorPos(void); // overridable
+ virtual void calcAnchorPos(void); // overridable
- int get_limit_motor_info2( btRotationalLimitMotor * limot,
- const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB,
- btConstraintInfo2 *info, int row, btVector3& ax1, int rotational, int rotAllowed = false);
+ int get_limit_motor_info2(btRotationalLimitMotor * limot,
+ const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB,
+ btConstraintInfo2* info, int row, btVector3& ax1, int rotational, int rotAllowed = false);
// access for UseFrameOffset
bool getUseFrameOffset() const { return m_useOffsetForConstraintFrame; }
void setUseFrameOffset(bool frameOffsetOnOff) { m_useOffsetForConstraintFrame = frameOffsetOnOff; }
-
+
bool getUseLinearReferenceFrameA() const { return m_useLinearReferenceFrameA; }
void setUseLinearReferenceFrameA(bool linearReferenceFrameA) { m_useLinearReferenceFrameA = linearReferenceFrameA; }
- ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+ ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
///If no axis is provided, it uses the default axis for this constraint.
- virtual void setParam(int num, btScalar value, int axis = -1);
+ virtual void setParam(int num, btScalar value, int axis = -1);
///return the local value of parameter
- virtual btScalar getParam(int num, int axis = -1) const;
+ virtual btScalar getParam(int num, int axis = -1) const;
- void setAxis( const btVector3& axis1, const btVector3& axis2);
+ void setAxis(const btVector3& axis1, const btVector3& axis2);
- virtual int getFlags() const
- {
- return m_flags;
+ virtual int getFlags() const
+ {
+ return m_flags;
}
- virtual int calculateSerializeBufferSize() const;
+ virtual int calculateSerializeBufferSize() const;
///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-
-
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
};
-
struct btGeneric6DofConstraintData
{
- btTypedConstraintData m_typeConstraintData;
- btTransformFloatData m_rbAFrame; // constraint axii. Assumes z is hinge axis.
+ btTypedConstraintData m_typeConstraintData;
+ btTransformFloatData m_rbAFrame; // constraint axii. Assumes z is hinge axis.
btTransformFloatData m_rbBFrame;
-
- btVector3FloatData m_linearUpperLimit;
- btVector3FloatData m_linearLowerLimit;
-
- btVector3FloatData m_angularUpperLimit;
- btVector3FloatData m_angularLowerLimit;
-
- int m_useLinearReferenceFrameA;
+
+ btVector3FloatData m_linearUpperLimit;
+ btVector3FloatData m_linearLowerLimit;
+
+ btVector3FloatData m_angularUpperLimit;
+ btVector3FloatData m_angularLowerLimit;
+
+ int m_useLinearReferenceFrameA;
int m_useOffsetForConstraintFrame;
};
struct btGeneric6DofConstraintDoubleData2
{
- btTypedConstraintDoubleData m_typeConstraintData;
- btTransformDoubleData m_rbAFrame; // constraint axii. Assumes z is hinge axis.
+ btTypedConstraintDoubleData m_typeConstraintData;
+ btTransformDoubleData m_rbAFrame; // constraint axii. Assumes z is hinge axis.
btTransformDoubleData m_rbBFrame;
-
- btVector3DoubleData m_linearUpperLimit;
- btVector3DoubleData m_linearLowerLimit;
-
- btVector3DoubleData m_angularUpperLimit;
- btVector3DoubleData m_angularLowerLimit;
-
- int m_useLinearReferenceFrameA;
+
+ btVector3DoubleData m_linearUpperLimit;
+ btVector3DoubleData m_linearLowerLimit;
+
+ btVector3DoubleData m_angularUpperLimit;
+ btVector3DoubleData m_angularLowerLimit;
+
+ int m_useLinearReferenceFrameA;
int m_useOffsetForConstraintFrame;
};
-SIMD_FORCE_INLINE int btGeneric6DofConstraint::calculateSerializeBufferSize() const
+SIMD_FORCE_INLINE int btGeneric6DofConstraint::calculateSerializeBufferSize() const
{
return sizeof(btGeneric6DofConstraintData2);
}
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
-SIMD_FORCE_INLINE const char* btGeneric6DofConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE const char* btGeneric6DofConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
{
-
btGeneric6DofConstraintData2* dof = (btGeneric6DofConstraintData2*)dataBuffer;
- btTypedConstraint::serialize(&dof->m_typeConstraintData,serializer);
+ btTypedConstraint::serialize(&dof->m_typeConstraintData, serializer);
m_frameInA.serialize(dof->m_rbAFrame);
m_frameInB.serialize(dof->m_rbBFrame);
-
int i;
- for (i=0;i<3;i++)
+ for (i = 0; i < 3; i++)
{
- dof->m_angularLowerLimit.m_floats[i] = m_angularLimits[i].m_loLimit;
- dof->m_angularUpperLimit.m_floats[i] = m_angularLimits[i].m_hiLimit;
+ dof->m_angularLowerLimit.m_floats[i] = m_angularLimits[i].m_loLimit;
+ dof->m_angularUpperLimit.m_floats[i] = m_angularLimits[i].m_hiLimit;
dof->m_linearLowerLimit.m_floats[i] = m_linearLimits.m_lowerLimit[i];
dof->m_linearUpperLimit.m_floats[i] = m_linearLimits.m_upperLimit[i];
}
-
- dof->m_useLinearReferenceFrameA = m_useLinearReferenceFrameA? 1 : 0;
+
+ dof->m_useLinearReferenceFrameA = m_useLinearReferenceFrameA ? 1 : 0;
dof->m_useOffsetForConstraintFrame = m_useOffsetForConstraintFrame ? 1 : 0;
return btGeneric6DofConstraintDataName;
}
-
-
-
-
-#endif //BT_GENERIC_6DOF_CONSTRAINT_H
+#endif //BT_GENERIC_6DOF_CONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp
index 540dcd18f7..49c8d9bbf7 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp
@@ -37,67 +37,54 @@ email: projectileman@yahoo.com
http://gimpact.sf.net
*/
-
-
#include "btGeneric6DofSpring2Constraint.h"
#include "BulletDynamics/Dynamics/btRigidBody.h"
#include "LinearMath/btTransformUtil.h"
#include <new>
-
-
btGeneric6DofSpring2Constraint::btGeneric6DofSpring2Constraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, RotateOrder rotOrder)
- : btTypedConstraint(D6_SPRING_2_CONSTRAINT_TYPE, rbA, rbB)
- , m_frameInA(frameInA)
- , m_frameInB(frameInB)
- , m_rotateOrder(rotOrder)
- , m_flags(0)
+ : btTypedConstraint(D6_SPRING_2_CONSTRAINT_TYPE, rbA, rbB), m_frameInA(frameInA), m_frameInB(frameInB), m_rotateOrder(rotOrder), m_flags(0)
{
calculateTransforms();
}
-
btGeneric6DofSpring2Constraint::btGeneric6DofSpring2Constraint(btRigidBody& rbB, const btTransform& frameInB, RotateOrder rotOrder)
- : btTypedConstraint(D6_SPRING_2_CONSTRAINT_TYPE, getFixedBody(), rbB)
- , m_frameInB(frameInB)
- , m_rotateOrder(rotOrder)
- , m_flags(0)
+ : btTypedConstraint(D6_SPRING_2_CONSTRAINT_TYPE, getFixedBody(), rbB), m_frameInB(frameInB), m_rotateOrder(rotOrder), m_flags(0)
{
///not providing rigidbody A means implicitly using worldspace for body A
m_frameInA = rbB.getCenterOfMassTransform() * m_frameInB;
calculateTransforms();
}
-
btScalar btGeneric6DofSpring2Constraint::btGetMatrixElem(const btMatrix3x3& mat, int index)
{
- int i = index%3;
- int j = index/3;
+ int i = index % 3;
+ int j = index / 3;
return mat[i][j];
}
// MatrixToEulerXYZ from http://www.geometrictools.com/LibFoundation/Mathematics/Wm4Matrix3.inl.html
-bool btGeneric6DofSpring2Constraint::matrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz)
+bool btGeneric6DofSpring2Constraint::matrixToEulerXYZ(const btMatrix3x3& mat, btVector3& xyz)
{
// rot = cy*cz -cy*sz sy
// cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx
// -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy
- btScalar fi = btGetMatrixElem(mat,2);
+ btScalar fi = btGetMatrixElem(mat, 2);
if (fi < btScalar(1.0f))
{
if (fi > btScalar(-1.0f))
{
- xyz[0] = btAtan2(-btGetMatrixElem(mat,5),btGetMatrixElem(mat,8));
- xyz[1] = btAsin(btGetMatrixElem(mat,2));
- xyz[2] = btAtan2(-btGetMatrixElem(mat,1),btGetMatrixElem(mat,0));
+ xyz[0] = btAtan2(-btGetMatrixElem(mat, 5), btGetMatrixElem(mat, 8));
+ xyz[1] = btAsin(btGetMatrixElem(mat, 2));
+ xyz[2] = btAtan2(-btGetMatrixElem(mat, 1), btGetMatrixElem(mat, 0));
return true;
}
else
{
// WARNING. Not unique. XA - ZA = -atan2(r10,r11)
- xyz[0] = -btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4));
+ xyz[0] = -btAtan2(btGetMatrixElem(mat, 3), btGetMatrixElem(mat, 4));
xyz[1] = -SIMD_HALF_PI;
xyz[2] = btScalar(0.0);
return false;
@@ -106,32 +93,32 @@ bool btGeneric6DofSpring2Constraint::matrixToEulerXYZ(const btMatrix3x3& mat,btV
else
{
// WARNING. Not unique. XAngle + ZAngle = atan2(r10,r11)
- xyz[0] = btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4));
+ xyz[0] = btAtan2(btGetMatrixElem(mat, 3), btGetMatrixElem(mat, 4));
xyz[1] = SIMD_HALF_PI;
xyz[2] = 0.0;
}
return false;
}
-bool btGeneric6DofSpring2Constraint::matrixToEulerXZY(const btMatrix3x3& mat,btVector3& xyz)
+bool btGeneric6DofSpring2Constraint::matrixToEulerXZY(const btMatrix3x3& mat, btVector3& xyz)
{
// rot = cy*cz -sz sy*cz
// cy*cx*sz+sx*sy cx*cz sy*cx*sz-cy*sx
// cy*sx*sz-cx*sy sx*cz sy*sx*sz+cx*cy
- btScalar fi = btGetMatrixElem(mat,1);
+ btScalar fi = btGetMatrixElem(mat, 1);
if (fi < btScalar(1.0f))
{
if (fi > btScalar(-1.0f))
{
- xyz[0] = btAtan2(btGetMatrixElem(mat,7),btGetMatrixElem(mat,4));
- xyz[1] = btAtan2(btGetMatrixElem(mat,2),btGetMatrixElem(mat,0));
- xyz[2] = btAsin(-btGetMatrixElem(mat,1));
+ xyz[0] = btAtan2(btGetMatrixElem(mat, 7), btGetMatrixElem(mat, 4));
+ xyz[1] = btAtan2(btGetMatrixElem(mat, 2), btGetMatrixElem(mat, 0));
+ xyz[2] = btAsin(-btGetMatrixElem(mat, 1));
return true;
}
else
{
- xyz[0] = -btAtan2(-btGetMatrixElem(mat,6),btGetMatrixElem(mat,8));
+ xyz[0] = -btAtan2(-btGetMatrixElem(mat, 6), btGetMatrixElem(mat, 8));
xyz[1] = btScalar(0.0);
xyz[2] = SIMD_HALF_PI;
return false;
@@ -139,33 +126,33 @@ bool btGeneric6DofSpring2Constraint::matrixToEulerXZY(const btMatrix3x3& mat,btV
}
else
{
- xyz[0] = btAtan2(-btGetMatrixElem(mat,6),btGetMatrixElem(mat,8));
+ xyz[0] = btAtan2(-btGetMatrixElem(mat, 6), btGetMatrixElem(mat, 8));
xyz[1] = 0.0;
xyz[2] = -SIMD_HALF_PI;
}
return false;
}
-bool btGeneric6DofSpring2Constraint::matrixToEulerYXZ(const btMatrix3x3& mat,btVector3& xyz)
+bool btGeneric6DofSpring2Constraint::matrixToEulerYXZ(const btMatrix3x3& mat, btVector3& xyz)
{
// rot = cy*cz+sy*sx*sz cz*sy*sx-cy*sz cx*sy
// cx*sz cx*cz -sx
// cy*sx*sz-cz*sy sy*sz+cy*cz*sx cy*cx
- btScalar fi = btGetMatrixElem(mat,5);
+ btScalar fi = btGetMatrixElem(mat, 5);
if (fi < btScalar(1.0f))
{
if (fi > btScalar(-1.0f))
{
- xyz[0] = btAsin(-btGetMatrixElem(mat,5));
- xyz[1] = btAtan2(btGetMatrixElem(mat,2),btGetMatrixElem(mat,8));
- xyz[2] = btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4));
+ xyz[0] = btAsin(-btGetMatrixElem(mat, 5));
+ xyz[1] = btAtan2(btGetMatrixElem(mat, 2), btGetMatrixElem(mat, 8));
+ xyz[2] = btAtan2(btGetMatrixElem(mat, 3), btGetMatrixElem(mat, 4));
return true;
}
else
{
xyz[0] = SIMD_HALF_PI;
- xyz[1] = -btAtan2(-btGetMatrixElem(mat,1),btGetMatrixElem(mat,0));
+ xyz[1] = -btAtan2(-btGetMatrixElem(mat, 1), btGetMatrixElem(mat, 0));
xyz[2] = btScalar(0.0);
return false;
}
@@ -173,32 +160,32 @@ bool btGeneric6DofSpring2Constraint::matrixToEulerYXZ(const btMatrix3x3& mat,btV
else
{
xyz[0] = -SIMD_HALF_PI;
- xyz[1] = btAtan2(-btGetMatrixElem(mat,1),btGetMatrixElem(mat,0));
+ xyz[1] = btAtan2(-btGetMatrixElem(mat, 1), btGetMatrixElem(mat, 0));
xyz[2] = 0.0;
}
return false;
}
-bool btGeneric6DofSpring2Constraint::matrixToEulerYZX(const btMatrix3x3& mat,btVector3& xyz)
+bool btGeneric6DofSpring2Constraint::matrixToEulerYZX(const btMatrix3x3& mat, btVector3& xyz)
{
// rot = cy*cz sy*sx-cy*cx*sz cx*sy+cy*sz*sx
// sz cz*cx -cz*sx
// -cz*sy cy*sx+cx*sy*sz cy*cx-sy*sz*sx
- btScalar fi = btGetMatrixElem(mat,3);
+ btScalar fi = btGetMatrixElem(mat, 3);
if (fi < btScalar(1.0f))
{
if (fi > btScalar(-1.0f))
{
- xyz[0] = btAtan2(-btGetMatrixElem(mat,5),btGetMatrixElem(mat,4));
- xyz[1] = btAtan2(-btGetMatrixElem(mat,6),btGetMatrixElem(mat,0));
- xyz[2] = btAsin(btGetMatrixElem(mat,3));
+ xyz[0] = btAtan2(-btGetMatrixElem(mat, 5), btGetMatrixElem(mat, 4));
+ xyz[1] = btAtan2(-btGetMatrixElem(mat, 6), btGetMatrixElem(mat, 0));
+ xyz[2] = btAsin(btGetMatrixElem(mat, 3));
return true;
}
else
{
xyz[0] = btScalar(0.0);
- xyz[1] = -btAtan2(btGetMatrixElem(mat,7),btGetMatrixElem(mat,8));
+ xyz[1] = -btAtan2(btGetMatrixElem(mat, 7), btGetMatrixElem(mat, 8));
xyz[2] = -SIMD_HALF_PI;
return false;
}
@@ -206,33 +193,33 @@ bool btGeneric6DofSpring2Constraint::matrixToEulerYZX(const btMatrix3x3& mat,btV
else
{
xyz[0] = btScalar(0.0);
- xyz[1] = btAtan2(btGetMatrixElem(mat,7),btGetMatrixElem(mat,8));
+ xyz[1] = btAtan2(btGetMatrixElem(mat, 7), btGetMatrixElem(mat, 8));
xyz[2] = SIMD_HALF_PI;
}
return false;
}
-bool btGeneric6DofSpring2Constraint::matrixToEulerZXY(const btMatrix3x3& mat,btVector3& xyz)
+bool btGeneric6DofSpring2Constraint::matrixToEulerZXY(const btMatrix3x3& mat, btVector3& xyz)
{
// rot = cz*cy-sz*sx*sy -cx*sz cz*sy+cy*sz*sx
// cy*sz+cz*sx*sy cz*cx sz*sy-cz*xy*sx
// -cx*sy sx cx*cy
- btScalar fi = btGetMatrixElem(mat,7);
+ btScalar fi = btGetMatrixElem(mat, 7);
if (fi < btScalar(1.0f))
{
if (fi > btScalar(-1.0f))
{
- xyz[0] = btAsin(btGetMatrixElem(mat,7));
- xyz[1] = btAtan2(-btGetMatrixElem(mat,6),btGetMatrixElem(mat,8));
- xyz[2] = btAtan2(-btGetMatrixElem(mat,1),btGetMatrixElem(mat,4));
+ xyz[0] = btAsin(btGetMatrixElem(mat, 7));
+ xyz[1] = btAtan2(-btGetMatrixElem(mat, 6), btGetMatrixElem(mat, 8));
+ xyz[2] = btAtan2(-btGetMatrixElem(mat, 1), btGetMatrixElem(mat, 4));
return true;
}
else
{
xyz[0] = -SIMD_HALF_PI;
xyz[1] = btScalar(0.0);
- xyz[2] = -btAtan2(btGetMatrixElem(mat,2),btGetMatrixElem(mat,0));
+ xyz[2] = -btAtan2(btGetMatrixElem(mat, 2), btGetMatrixElem(mat, 0));
return false;
}
}
@@ -240,32 +227,32 @@ bool btGeneric6DofSpring2Constraint::matrixToEulerZXY(const btMatrix3x3& mat,btV
{
xyz[0] = SIMD_HALF_PI;
xyz[1] = btScalar(0.0);
- xyz[2] = btAtan2(btGetMatrixElem(mat,2),btGetMatrixElem(mat,0));
+ xyz[2] = btAtan2(btGetMatrixElem(mat, 2), btGetMatrixElem(mat, 0));
}
return false;
}
-bool btGeneric6DofSpring2Constraint::matrixToEulerZYX(const btMatrix3x3& mat,btVector3& xyz)
+bool btGeneric6DofSpring2Constraint::matrixToEulerZYX(const btMatrix3x3& mat, btVector3& xyz)
{
// rot = cz*cy cz*sy*sx-cx*sz sz*sx+cz*cx*sy
// cy*sz cz*cx+sz*sy*sx cx*sz*sy-cz*sx
// -sy cy*sx cy*cx
- btScalar fi = btGetMatrixElem(mat,6);
+ btScalar fi = btGetMatrixElem(mat, 6);
if (fi < btScalar(1.0f))
{
if (fi > btScalar(-1.0f))
{
- xyz[0] = btAtan2(btGetMatrixElem(mat,7), btGetMatrixElem(mat,8));
- xyz[1] = btAsin(-btGetMatrixElem(mat,6));
- xyz[2] = btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,0));
+ xyz[0] = btAtan2(btGetMatrixElem(mat, 7), btGetMatrixElem(mat, 8));
+ xyz[1] = btAsin(-btGetMatrixElem(mat, 6));
+ xyz[2] = btAtan2(btGetMatrixElem(mat, 3), btGetMatrixElem(mat, 0));
return true;
}
else
{
xyz[0] = btScalar(0.0);
xyz[1] = SIMD_HALF_PI;
- xyz[2] = -btAtan2(btGetMatrixElem(mat,1),btGetMatrixElem(mat,2));
+ xyz[2] = -btAtan2(btGetMatrixElem(mat, 1), btGetMatrixElem(mat, 2));
return false;
}
}
@@ -273,23 +260,36 @@ bool btGeneric6DofSpring2Constraint::matrixToEulerZYX(const btMatrix3x3& mat,btV
{
xyz[0] = btScalar(0.0);
xyz[1] = -SIMD_HALF_PI;
- xyz[2] = btAtan2(-btGetMatrixElem(mat,1),-btGetMatrixElem(mat,2));
+ xyz[2] = btAtan2(-btGetMatrixElem(mat, 1), -btGetMatrixElem(mat, 2));
}
return false;
}
void btGeneric6DofSpring2Constraint::calculateAngleInfo()
{
- btMatrix3x3 relative_frame = m_calculatedTransformA.getBasis().inverse()*m_calculatedTransformB.getBasis();
+ btMatrix3x3 relative_frame = m_calculatedTransformA.getBasis().inverse() * m_calculatedTransformB.getBasis();
switch (m_rotateOrder)
{
- case RO_XYZ : matrixToEulerXYZ(relative_frame,m_calculatedAxisAngleDiff); break;
- case RO_XZY : matrixToEulerXZY(relative_frame,m_calculatedAxisAngleDiff); break;
- case RO_YXZ : matrixToEulerYXZ(relative_frame,m_calculatedAxisAngleDiff); break;
- case RO_YZX : matrixToEulerYZX(relative_frame,m_calculatedAxisAngleDiff); break;
- case RO_ZXY : matrixToEulerZXY(relative_frame,m_calculatedAxisAngleDiff); break;
- case RO_ZYX : matrixToEulerZYX(relative_frame,m_calculatedAxisAngleDiff); break;
- default : btAssert(false);
+ case RO_XYZ:
+ matrixToEulerXYZ(relative_frame, m_calculatedAxisAngleDiff);
+ break;
+ case RO_XZY:
+ matrixToEulerXZY(relative_frame, m_calculatedAxisAngleDiff);
+ break;
+ case RO_YXZ:
+ matrixToEulerYXZ(relative_frame, m_calculatedAxisAngleDiff);
+ break;
+ case RO_YZX:
+ matrixToEulerYZX(relative_frame, m_calculatedAxisAngleDiff);
+ break;
+ case RO_ZXY:
+ matrixToEulerZXY(relative_frame, m_calculatedAxisAngleDiff);
+ break;
+ case RO_ZYX:
+ matrixToEulerZYX(relative_frame, m_calculatedAxisAngleDiff);
+ break;
+ default:
+ btAssert(false);
}
// 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]) :
@@ -307,14 +307,14 @@ void btGeneric6DofSpring2Constraint::calculateAngleInfo()
// to the components of w and set that to 0.
switch (m_rotateOrder)
{
- case RO_XYZ :
+ case RO_XYZ:
{
//Is this the "line of nodes" calculation choosing planes YZ (B coordinate system) and xy (A coordinate system)? (http://en.wikipedia.org/wiki/Euler_angles)
//The two planes are non-homologous, so this is a Tait–Bryan angle formalism and not a proper Euler
//Extrinsic rotations are equal to the reversed order intrinsic rotations so the above xyz extrinsic rotations (axes are fixed) are the same as the zy'x" intrinsic rotations (axes are refreshed after each rotation)
//that is why xy and YZ planes are chosen (this will describe a zy'x" intrinsic rotation) (see the figure on the left at http://en.wikipedia.org/wiki/Euler_angles under Tait–Bryan angles)
// x' = Nperp = N.cross(axis2)
- // y' = N = axis2.cross(axis0)
+ // y' = N = axis2.cross(axis0)
// z' = z
//
// x" = X
@@ -324,7 +324,7 @@ void btGeneric6DofSpring2Constraint::calculateAngleInfo()
//first rotate around z
//second rotate around y'= z.cross(X)
//third rotate around x" = X
- //Original XYZ extrinsic rotation order.
+ //Original XYZ extrinsic rotation order.
//Planes: xy and YZ normals: z, X. Plane intersection (N) is z.cross(X)
btVector3 axis0 = m_calculatedTransformB.getBasis().getColumn(0);
btVector3 axis2 = m_calculatedTransformA.getBasis().getColumn(2);
@@ -333,7 +333,7 @@ void btGeneric6DofSpring2Constraint::calculateAngleInfo()
m_calculatedAxis[2] = axis0.cross(m_calculatedAxis[1]);
break;
}
- case RO_XZY :
+ case RO_XZY:
{
//planes: xz,ZY normals: y, X
//first rotate around y
@@ -346,7 +346,7 @@ void btGeneric6DofSpring2Constraint::calculateAngleInfo()
m_calculatedAxis[1] = m_calculatedAxis[2].cross(axis0);
break;
}
- case RO_YXZ :
+ case RO_YXZ:
{
//planes: yx,XZ normals: z, Y
//first rotate around z
@@ -359,7 +359,7 @@ void btGeneric6DofSpring2Constraint::calculateAngleInfo()
m_calculatedAxis[2] = m_calculatedAxis[0].cross(axis1);
break;
}
- case RO_YZX :
+ case RO_YZX:
{
//planes: yz,ZX normals: x, Y
//first rotate around x
@@ -372,7 +372,7 @@ void btGeneric6DofSpring2Constraint::calculateAngleInfo()
m_calculatedAxis[1] = m_calculatedAxis[2].cross(axis0);
break;
}
- case RO_ZXY :
+ case RO_ZXY:
{
//planes: zx,XY normals: y, Z
//first rotate around y
@@ -385,7 +385,7 @@ void btGeneric6DofSpring2Constraint::calculateAngleInfo()
m_calculatedAxis[2] = m_calculatedAxis[0].cross(axis1);
break;
}
- case RO_ZYX :
+ case RO_ZYX:
{
//planes: zy,YX normals: x, Z
//first rotate around x
@@ -398,22 +398,21 @@ void btGeneric6DofSpring2Constraint::calculateAngleInfo()
m_calculatedAxis[2] = axis0.cross(m_calculatedAxis[1]);
break;
}
- default:
- btAssert(false);
+ default:
+ btAssert(false);
}
m_calculatedAxis[0].normalize();
m_calculatedAxis[1].normalize();
m_calculatedAxis[2].normalize();
-
}
void btGeneric6DofSpring2Constraint::calculateTransforms()
{
- calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
+ calculateTransforms(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
}
-void btGeneric6DofSpring2Constraint::calculateTransforms(const btTransform& transA,const btTransform& transB)
+void btGeneric6DofSpring2Constraint::calculateTransforms(const btTransform& transA, const btTransform& transB)
{
m_calculatedTransformA = transA * m_frameInA;
m_calculatedTransformB = transB * m_frameInB;
@@ -424,18 +423,17 @@ void btGeneric6DofSpring2Constraint::calculateTransforms(const btTransform& tran
btScalar miB = getRigidBodyB().getInvMass();
m_hasStaticBody = (miA < SIMD_EPSILON) || (miB < SIMD_EPSILON);
btScalar miS = miA + miB;
- if(miS > btScalar(0.f))
+ if (miS > btScalar(0.f))
{
m_factA = miB / miS;
}
- else
+ else
{
m_factA = btScalar(0.5f);
}
m_factB = btScalar(1.0f) - m_factA;
}
-
void btGeneric6DofSpring2Constraint::testAngularLimitMotor(int axis_index)
{
btScalar angle = m_calculatedAxisAngleDiff[axis_index];
@@ -444,35 +442,37 @@ void btGeneric6DofSpring2Constraint::testAngularLimitMotor(int axis_index)
m_angularLimits[axis_index].testLimitValue(angle);
}
-
-void btGeneric6DofSpring2Constraint::getInfo1 (btConstraintInfo1* info)
+void btGeneric6DofSpring2Constraint::getInfo1(btConstraintInfo1* info)
{
//prepare constraint
- calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
+ calculateTransforms(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
info->m_numConstraintRows = 0;
info->nub = 0;
int i;
//test linear limits
- for(i = 0; i < 3; i++)
+ for (i = 0; i < 3; i++)
{
- if (m_linearLimits.m_currentLimit[i]==4) info->m_numConstraintRows += 2;
- else if (m_linearLimits.m_currentLimit[i]!=0) info->m_numConstraintRows += 1;
- if (m_linearLimits.m_enableMotor[i] ) info->m_numConstraintRows += 1;
+ if (m_linearLimits.m_currentLimit[i] == 4)
+ info->m_numConstraintRows += 2;
+ else if (m_linearLimits.m_currentLimit[i] != 0)
+ info->m_numConstraintRows += 1;
+ if (m_linearLimits.m_enableMotor[i]) info->m_numConstraintRows += 1;
if (m_linearLimits.m_enableSpring[i]) info->m_numConstraintRows += 1;
}
//test angular limits
- for (i=0;i<3 ;i++ )
+ for (i = 0; i < 3; i++)
{
testAngularLimitMotor(i);
- if (m_angularLimits[i].m_currentLimit==4) info->m_numConstraintRows += 2;
- else if (m_angularLimits[i].m_currentLimit!=0) info->m_numConstraintRows += 1;
- if (m_angularLimits[i].m_enableMotor ) info->m_numConstraintRows += 1;
+ if (m_angularLimits[i].m_currentLimit == 4)
+ info->m_numConstraintRows += 2;
+ else if (m_angularLimits[i].m_currentLimit != 0)
+ info->m_numConstraintRows += 1;
+ if (m_angularLimits[i].m_enableMotor) info->m_numConstraintRows += 1;
if (m_angularLimits[i].m_enableSpring) info->m_numConstraintRows += 1;
}
}
-
-void btGeneric6DofSpring2Constraint::getInfo2 (btConstraintInfo2* info)
+void btGeneric6DofSpring2Constraint::getInfo2(btConstraintInfo2* info)
{
const btTransform& transA = m_rbA.getCenterOfMassTransform();
const btTransform& transB = m_rbB.getCenterOfMassTransform();
@@ -482,118 +482,138 @@ void btGeneric6DofSpring2Constraint::getInfo2 (btConstraintInfo2* info)
const btVector3& angVelB = m_rbB.getAngularVelocity();
// for stability better to solve angular limits first
- int row = setAngularLimits(info, 0,transA,transB,linVelA,linVelB,angVelA,angVelB);
- setLinearLimits(info, row, transA,transB,linVelA,linVelB,angVelA,angVelB);
+ int row = setAngularLimits(info, 0, transA, transB, linVelA, linVelB, angVelA, angVelB);
+ setLinearLimits(info, row, transA, transB, linVelA, linVelB, angVelA, angVelB);
}
-
-int btGeneric6DofSpring2Constraint::setLinearLimits(btConstraintInfo2* info, int row, const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB)
+int btGeneric6DofSpring2Constraint::setLinearLimits(btConstraintInfo2* info, int row, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB)
{
//solve linear limits
btRotationalLimitMotor2 limot;
- for (int i=0;i<3 ;i++ )
+ for (int i = 0; i < 3; i++)
{
- if(m_linearLimits.m_currentLimit[i] || m_linearLimits.m_enableMotor[i] || m_linearLimits.m_enableSpring[i])
- { // re-use rotational motor code
- limot.m_bounce = m_linearLimits.m_bounce[i];
- limot.m_currentLimit = m_linearLimits.m_currentLimit[i];
- limot.m_currentPosition = m_linearLimits.m_currentLinearDiff[i];
- limot.m_currentLimitError = m_linearLimits.m_currentLimitError[i];
- limot.m_currentLimitErrorHi = m_linearLimits.m_currentLimitErrorHi[i];
- limot.m_enableMotor = m_linearLimits.m_enableMotor[i];
- limot.m_servoMotor = m_linearLimits.m_servoMotor[i];
- limot.m_servoTarget = m_linearLimits.m_servoTarget[i];
- limot.m_enableSpring = m_linearLimits.m_enableSpring[i];
- limot.m_springStiffness = m_linearLimits.m_springStiffness[i];
+ if (m_linearLimits.m_currentLimit[i] || m_linearLimits.m_enableMotor[i] || m_linearLimits.m_enableSpring[i])
+ { // re-use rotational motor code
+ limot.m_bounce = m_linearLimits.m_bounce[i];
+ limot.m_currentLimit = m_linearLimits.m_currentLimit[i];
+ limot.m_currentPosition = m_linearLimits.m_currentLinearDiff[i];
+ limot.m_currentLimitError = m_linearLimits.m_currentLimitError[i];
+ limot.m_currentLimitErrorHi = m_linearLimits.m_currentLimitErrorHi[i];
+ limot.m_enableMotor = m_linearLimits.m_enableMotor[i];
+ limot.m_servoMotor = m_linearLimits.m_servoMotor[i];
+ limot.m_servoTarget = m_linearLimits.m_servoTarget[i];
+ limot.m_enableSpring = m_linearLimits.m_enableSpring[i];
+ limot.m_springStiffness = m_linearLimits.m_springStiffness[i];
limot.m_springStiffnessLimited = m_linearLimits.m_springStiffnessLimited[i];
- limot.m_springDamping = m_linearLimits.m_springDamping[i];
- limot.m_springDampingLimited = m_linearLimits.m_springDampingLimited[i];
- limot.m_equilibriumPoint = m_linearLimits.m_equilibriumPoint[i];
- limot.m_hiLimit = m_linearLimits.m_upperLimit[i];
- limot.m_loLimit = m_linearLimits.m_lowerLimit[i];
- limot.m_maxMotorForce = m_linearLimits.m_maxMotorForce[i];
- limot.m_targetVelocity = m_linearLimits.m_targetVelocity[i];
+ limot.m_springDamping = m_linearLimits.m_springDamping[i];
+ limot.m_springDampingLimited = m_linearLimits.m_springDampingLimited[i];
+ limot.m_equilibriumPoint = m_linearLimits.m_equilibriumPoint[i];
+ limot.m_hiLimit = m_linearLimits.m_upperLimit[i];
+ limot.m_loLimit = m_linearLimits.m_lowerLimit[i];
+ limot.m_maxMotorForce = m_linearLimits.m_maxMotorForce[i];
+ limot.m_targetVelocity = m_linearLimits.m_targetVelocity[i];
btVector3 axis = m_calculatedTransformA.getBasis().getColumn(i);
int flags = m_flags >> (i * BT_6DOF_FLAGS_AXIS_SHIFT2);
- limot.m_stopCFM = (flags & BT_6DOF_FLAGS_CFM_STOP2) ? m_linearLimits.m_stopCFM[i] : info->cfm[0];
- limot.m_stopERP = (flags & BT_6DOF_FLAGS_ERP_STOP2) ? m_linearLimits.m_stopERP[i] : info->erp;
+ limot.m_stopCFM = (flags & BT_6DOF_FLAGS_CFM_STOP2) ? m_linearLimits.m_stopCFM[i] : info->cfm[0];
+ limot.m_stopERP = (flags & BT_6DOF_FLAGS_ERP_STOP2) ? m_linearLimits.m_stopERP[i] : info->erp;
limot.m_motorCFM = (flags & BT_6DOF_FLAGS_CFM_MOTO2) ? m_linearLimits.m_motorCFM[i] : info->cfm[0];
limot.m_motorERP = (flags & BT_6DOF_FLAGS_ERP_MOTO2) ? m_linearLimits.m_motorERP[i] : info->erp;
//rotAllowed is a bit of a magic from the original 6dof. The calculation of it here is something that imitates the original behavior as much as possible.
int indx1 = (i + 1) % 3;
int indx2 = (i + 2) % 3;
- int rotAllowed = 1; // rotations around orthos to current axis (it is used only when one of the body is static)
- #define D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION 1.0e-3
+ int rotAllowed = 1; // rotations around orthos to current axis (it is used only when one of the body is static)
+#define D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION 1.0e-3
bool indx1Violated = m_angularLimits[indx1].m_currentLimit == 1 ||
- m_angularLimits[indx1].m_currentLimit == 2 ||
- ( m_angularLimits[indx1].m_currentLimit == 3 && ( m_angularLimits[indx1].m_currentLimitError < -D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION || m_angularLimits[indx1].m_currentLimitError > D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION ) ) ||
- ( m_angularLimits[indx1].m_currentLimit == 4 && ( m_angularLimits[indx1].m_currentLimitError < -D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION || m_angularLimits[indx1].m_currentLimitErrorHi > D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION ) );
+ m_angularLimits[indx1].m_currentLimit == 2 ||
+ (m_angularLimits[indx1].m_currentLimit == 3 && (m_angularLimits[indx1].m_currentLimitError < -D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION || m_angularLimits[indx1].m_currentLimitError > D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION)) ||
+ (m_angularLimits[indx1].m_currentLimit == 4 && (m_angularLimits[indx1].m_currentLimitError < -D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION || m_angularLimits[indx1].m_currentLimitErrorHi > D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION));
bool indx2Violated = m_angularLimits[indx2].m_currentLimit == 1 ||
- m_angularLimits[indx2].m_currentLimit == 2 ||
- ( m_angularLimits[indx2].m_currentLimit == 3 && ( m_angularLimits[indx2].m_currentLimitError < -D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION || m_angularLimits[indx2].m_currentLimitError > D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION ) ) ||
- ( m_angularLimits[indx2].m_currentLimit == 4 && ( m_angularLimits[indx2].m_currentLimitError < -D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION || m_angularLimits[indx2].m_currentLimitErrorHi > D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION ) );
- if( indx1Violated && indx2Violated )
+ m_angularLimits[indx2].m_currentLimit == 2 ||
+ (m_angularLimits[indx2].m_currentLimit == 3 && (m_angularLimits[indx2].m_currentLimitError < -D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION || m_angularLimits[indx2].m_currentLimitError > D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION)) ||
+ (m_angularLimits[indx2].m_currentLimit == 4 && (m_angularLimits[indx2].m_currentLimitError < -D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION || m_angularLimits[indx2].m_currentLimitErrorHi > D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION));
+ if (indx1Violated && indx2Violated)
{
rotAllowed = 0;
}
- row += get_limit_motor_info2(&limot, transA,transB,linVelA,linVelB,angVelA,angVelB, info, row, axis, 0, rotAllowed);
-
+ row += get_limit_motor_info2(&limot, transA, transB, linVelA, linVelB, angVelA, angVelB, info, row, axis, 0, rotAllowed);
}
}
return row;
}
-
-
-int btGeneric6DofSpring2Constraint::setAngularLimits(btConstraintInfo2 *info, int row_offset, const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB)
+int btGeneric6DofSpring2Constraint::setAngularLimits(btConstraintInfo2* info, int row_offset, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB)
{
int row = row_offset;
//order of rotational constraint rows
int cIdx[] = {0, 1, 2};
- switch(m_rotateOrder)
+ switch (m_rotateOrder)
{
- case RO_XYZ : cIdx[0] = 0; cIdx[1] = 1; cIdx[2] = 2; break;
- case RO_XZY : cIdx[0] = 0; cIdx[1] = 2; cIdx[2] = 1; break;
- case RO_YXZ : cIdx[0] = 1; cIdx[1] = 0; cIdx[2] = 2; break;
- case RO_YZX : cIdx[0] = 1; cIdx[1] = 2; cIdx[2] = 0; break;
- case RO_ZXY : cIdx[0] = 2; cIdx[1] = 0; cIdx[2] = 1; break;
- case RO_ZYX : cIdx[0] = 2; cIdx[1] = 1; cIdx[2] = 0; break;
- default : btAssert(false);
+ case RO_XYZ:
+ cIdx[0] = 0;
+ cIdx[1] = 1;
+ cIdx[2] = 2;
+ break;
+ case RO_XZY:
+ cIdx[0] = 0;
+ cIdx[1] = 2;
+ cIdx[2] = 1;
+ break;
+ case RO_YXZ:
+ cIdx[0] = 1;
+ cIdx[1] = 0;
+ cIdx[2] = 2;
+ break;
+ case RO_YZX:
+ cIdx[0] = 1;
+ cIdx[1] = 2;
+ cIdx[2] = 0;
+ break;
+ case RO_ZXY:
+ cIdx[0] = 2;
+ cIdx[1] = 0;
+ cIdx[2] = 1;
+ break;
+ case RO_ZYX:
+ cIdx[0] = 2;
+ cIdx[1] = 1;
+ cIdx[2] = 0;
+ break;
+ default:
+ btAssert(false);
}
- for (int ii = 0; ii < 3 ; ii++ )
+ for (int ii = 0; ii < 3; ii++)
{
int i = cIdx[ii];
- if(m_angularLimits[i].m_currentLimit || m_angularLimits[i].m_enableMotor || m_angularLimits[i].m_enableSpring)
+ if (m_angularLimits[i].m_currentLimit || m_angularLimits[i].m_enableMotor || m_angularLimits[i].m_enableSpring)
{
btVector3 axis = getAxis(i);
int flags = m_flags >> ((i + 3) * BT_6DOF_FLAGS_AXIS_SHIFT2);
- if(!(flags & BT_6DOF_FLAGS_CFM_STOP2))
+ if (!(flags & BT_6DOF_FLAGS_CFM_STOP2))
{
m_angularLimits[i].m_stopCFM = info->cfm[0];
}
- if(!(flags & BT_6DOF_FLAGS_ERP_STOP2))
+ if (!(flags & BT_6DOF_FLAGS_ERP_STOP2))
{
m_angularLimits[i].m_stopERP = info->erp;
}
- if(!(flags & BT_6DOF_FLAGS_CFM_MOTO2))
+ if (!(flags & BT_6DOF_FLAGS_CFM_MOTO2))
{
m_angularLimits[i].m_motorCFM = info->cfm[0];
}
- if(!(flags & BT_6DOF_FLAGS_ERP_MOTO2))
+ if (!(flags & BT_6DOF_FLAGS_ERP_MOTO2))
{
m_angularLimits[i].m_motorERP = info->erp;
}
- row += get_limit_motor_info2(&m_angularLimits[i],transA,transB,linVelA,linVelB,angVelA,angVelB, info,row,axis,1);
+ row += get_limit_motor_info2(&m_angularLimits[i], transA, transB, linVelA, linVelB, angVelA, angVelB, info, row, axis, 1);
}
}
return row;
}
-
void btGeneric6DofSpring2Constraint::setFrames(const btTransform& frameA, const btTransform& frameB)
{
m_frameInA = frameA;
@@ -602,32 +622,31 @@ void btGeneric6DofSpring2Constraint::setFrames(const btTransform& frameA, const
calculateTransforms();
}
-
void btGeneric6DofSpring2Constraint::calculateLinearInfo()
{
m_calculatedLinearDiff = m_calculatedTransformB.getOrigin() - m_calculatedTransformA.getOrigin();
m_calculatedLinearDiff = m_calculatedTransformA.getBasis().inverse() * m_calculatedLinearDiff;
- for(int i = 0; i < 3; i++)
+ for (int i = 0; i < 3; i++)
{
m_linearLimits.m_currentLinearDiff[i] = m_calculatedLinearDiff[i];
m_linearLimits.testLimitValue(i, m_calculatedLinearDiff[i]);
}
}
-void btGeneric6DofSpring2Constraint::calculateJacobi(btRotationalLimitMotor2 * limot, const btTransform& transA,const btTransform& transB, btConstraintInfo2 *info, int srow, btVector3& ax1, int rotational, int rotAllowed)
+void btGeneric6DofSpring2Constraint::calculateJacobi(btRotationalLimitMotor2* limot, const btTransform& transA, const btTransform& transB, btConstraintInfo2* info, int srow, btVector3& ax1, int rotational, int rotAllowed)
{
- btScalar *J1 = rotational ? info->m_J1angularAxis : info->m_J1linearAxis;
- btScalar *J2 = rotational ? info->m_J2angularAxis : info->m_J2linearAxis;
+ btScalar* J1 = rotational ? info->m_J1angularAxis : info->m_J1linearAxis;
+ btScalar* J2 = rotational ? info->m_J2angularAxis : info->m_J2linearAxis;
- J1[srow+0] = ax1[0];
- J1[srow+1] = ax1[1];
- J1[srow+2] = ax1[2];
+ J1[srow + 0] = ax1[0];
+ J1[srow + 1] = ax1[1];
+ J1[srow + 2] = ax1[2];
- J2[srow+0] = -ax1[0];
- J2[srow+1] = -ax1[1];
- J2[srow+2] = -ax1[2];
+ J2[srow + 0] = -ax1[0];
+ J2[srow + 1] = -ax1[1];
+ J2[srow + 2] = -ax1[2];
- if(!rotational)
+ if (!rotational)
{
btVector3 tmpA, tmpB, relA, relB;
// get vector from bodyB to frameB in WCS
@@ -636,40 +655,44 @@ void btGeneric6DofSpring2Constraint::calculateJacobi(btRotationalLimitMotor2 * l
relA = m_calculatedTransformA.getOrigin() - transA.getOrigin();
tmpA = relA.cross(ax1);
tmpB = relB.cross(ax1);
- if(m_hasStaticBody && (!rotAllowed))
+ if (m_hasStaticBody && (!rotAllowed))
{
tmpA *= m_factA;
tmpB *= m_factB;
}
int i;
- for (i=0; i<3; i++) info->m_J1angularAxis[srow+i] = tmpA[i];
- for (i=0; i<3; i++) info->m_J2angularAxis[srow+i] = -tmpB[i];
+ for (i = 0; i < 3; i++) info->m_J1angularAxis[srow + i] = tmpA[i];
+ for (i = 0; i < 3; i++) info->m_J2angularAxis[srow + i] = -tmpB[i];
}
}
-
int btGeneric6DofSpring2Constraint::get_limit_motor_info2(
- btRotationalLimitMotor2 * limot,
- const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB,
- btConstraintInfo2 *info, int row, btVector3& ax1, int rotational,int rotAllowed)
+ btRotationalLimitMotor2* limot,
+ const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB,
+ btConstraintInfo2* info, int row, btVector3& ax1, int rotational, int rotAllowed)
{
int count = 0;
int srow = row * info->rowskip;
- if (limot->m_currentLimit==4)
+ if (limot->m_currentLimit == 4)
{
btScalar vel = rotational ? angVelA.dot(ax1) - angVelB.dot(ax1) : linVelA.dot(ax1) - linVelB.dot(ax1);
- calculateJacobi(limot,transA,transB,info,srow,ax1,rotational,rotAllowed);
+ calculateJacobi(limot, transA, transB, info, srow, ax1, rotational, rotAllowed);
info->m_constraintError[srow] = info->fps * limot->m_stopERP * limot->m_currentLimitError * (rotational ? -1 : 1);
- if (rotational) {
- if (info->m_constraintError[srow]-vel*limot->m_stopERP > 0) {
- btScalar bounceerror = -limot->m_bounce* vel;
+ if (rotational)
+ {
+ if (info->m_constraintError[srow] - vel * limot->m_stopERP > 0)
+ {
+ btScalar bounceerror = -limot->m_bounce * vel;
if (bounceerror > info->m_constraintError[srow]) info->m_constraintError[srow] = bounceerror;
}
- } else {
- if (info->m_constraintError[srow]-vel*limot->m_stopERP < 0) {
- btScalar bounceerror = -limot->m_bounce* vel;
+ }
+ else
+ {
+ if (info->m_constraintError[srow] - vel * limot->m_stopERP < 0)
+ {
+ btScalar bounceerror = -limot->m_bounce * vel;
if (bounceerror < info->m_constraintError[srow]) info->m_constraintError[srow] = bounceerror;
}
}
@@ -679,16 +702,21 @@ int btGeneric6DofSpring2Constraint::get_limit_motor_info2(
srow += info->rowskip;
++count;
- calculateJacobi(limot,transA,transB,info,srow,ax1,rotational,rotAllowed);
+ calculateJacobi(limot, transA, transB, info, srow, ax1, rotational, rotAllowed);
info->m_constraintError[srow] = info->fps * limot->m_stopERP * limot->m_currentLimitErrorHi * (rotational ? -1 : 1);
- if (rotational) {
- if (info->m_constraintError[srow]-vel*limot->m_stopERP < 0) {
- btScalar bounceerror = -limot->m_bounce* vel;
+ if (rotational)
+ {
+ if (info->m_constraintError[srow] - vel * limot->m_stopERP < 0)
+ {
+ btScalar bounceerror = -limot->m_bounce * vel;
if (bounceerror < info->m_constraintError[srow]) info->m_constraintError[srow] = bounceerror;
}
- } else {
- if (info->m_constraintError[srow]-vel*limot->m_stopERP > 0) {
- btScalar bounceerror = -limot->m_bounce* vel;
+ }
+ else
+ {
+ if (info->m_constraintError[srow] - vel * limot->m_stopERP > 0)
+ {
+ btScalar bounceerror = -limot->m_bounce * vel;
if (bounceerror > info->m_constraintError[srow]) info->m_constraintError[srow] = bounceerror;
}
}
@@ -697,10 +725,10 @@ int btGeneric6DofSpring2Constraint::get_limit_motor_info2(
info->cfm[srow] = limot->m_stopCFM;
srow += info->rowskip;
++count;
- } else
- if (limot->m_currentLimit==3)
+ }
+ else if (limot->m_currentLimit == 3)
{
- calculateJacobi(limot,transA,transB,info,srow,ax1,rotational,rotAllowed);
+ calculateJacobi(limot, transA, transB, info, srow, ax1, rotational, rotAllowed);
info->m_constraintError[srow] = info->fps * limot->m_stopERP * limot->m_currentLimitError * (rotational ? -1 : 1);
info->m_lowerLimit[srow] = -SIMD_INFINITY;
info->m_upperLimit[srow] = SIMD_INFINITY;
@@ -711,13 +739,13 @@ int btGeneric6DofSpring2Constraint::get_limit_motor_info2(
if (limot->m_enableMotor && !limot->m_servoMotor)
{
- calculateJacobi(limot,transA,transB,info,srow,ax1,rotational,rotAllowed);
+ calculateJacobi(limot, transA, transB, info, srow, ax1, rotational, rotAllowed);
btScalar tag_vel = rotational ? limot->m_targetVelocity : -limot->m_targetVelocity;
- btScalar mot_fact = getMotorFactor(limot->m_currentPosition,
- limot->m_loLimit,
- limot->m_hiLimit,
- tag_vel,
- info->fps * limot->m_motorERP);
+ btScalar mot_fact = getMotorFactor(limot->m_currentPosition,
+ limot->m_loLimit,
+ limot->m_hiLimit,
+ tag_vel,
+ info->fps * limot->m_motorERP);
info->m_constraintError[srow] = mot_fact * limot->m_targetVelocity;
info->m_lowerLimit[srow] = -limot->m_maxMotorForce / info->fps;
info->m_upperLimit[srow] = limot->m_maxMotorForce / info->fps;
@@ -735,36 +763,36 @@ int btGeneric6DofSpring2Constraint::get_limit_motor_info2(
if (error > SIMD_PI)
{
error -= SIMD_2_PI;
- curServoTarget +=SIMD_2_PI;
+ curServoTarget += SIMD_2_PI;
}
if (error < -SIMD_PI)
{
error += SIMD_2_PI;
- curServoTarget -=SIMD_2_PI;
+ curServoTarget -= SIMD_2_PI;
}
}
- calculateJacobi(limot,transA,transB,info,srow,ax1,rotational,rotAllowed);
- btScalar targetvelocity = error<0 ? -limot->m_targetVelocity : limot->m_targetVelocity;
+ calculateJacobi(limot, transA, transB, info, srow, ax1, rotational, rotAllowed);
+ btScalar targetvelocity = error < 0 ? -limot->m_targetVelocity : limot->m_targetVelocity;
btScalar tag_vel = -targetvelocity;
btScalar mot_fact;
- if(error != 0)
+ if (error != 0)
{
btScalar lowLimit;
btScalar hiLimit;
- if(limot->m_loLimit > limot->m_hiLimit)
+ if (limot->m_loLimit > limot->m_hiLimit)
{
lowLimit = error > 0 ? curServoTarget : -SIMD_INFINITY;
- hiLimit = error < 0 ? curServoTarget : SIMD_INFINITY;
+ hiLimit = error < 0 ? curServoTarget : SIMD_INFINITY;
}
else
{
- lowLimit = error > 0 && curServoTarget>limot->m_loLimit ? curServoTarget : limot->m_loLimit;
- hiLimit = error < 0 && curServoTarget<limot->m_hiLimit ? curServoTarget : limot->m_hiLimit;
+ lowLimit = error > 0 && curServoTarget > limot->m_loLimit ? curServoTarget : limot->m_loLimit;
+ hiLimit = error < 0 && curServoTarget < limot->m_hiLimit ? curServoTarget : limot->m_hiLimit;
}
mot_fact = getMotorFactor(limot->m_currentPosition, lowLimit, hiLimit, tag_vel, info->fps * limot->m_motorERP);
- }
- else
+ }
+ else
{
mot_fact = 0;
}
@@ -779,7 +807,7 @@ int btGeneric6DofSpring2Constraint::get_limit_motor_info2(
if (limot->m_enableSpring)
{
btScalar error = limot->m_currentPosition - limot->m_equilibriumPoint;
- calculateJacobi(limot,transA,transB,info,srow,ax1,rotational,rotAllowed);
+ calculateJacobi(limot, transA, transB, info, srow, ax1, rotational, rotAllowed);
//btScalar cfm = 1.0 / ((1.0/info->fps)*limot->m_springStiffness+ limot->m_springDamping);
//if(cfm > 0.99999)
@@ -792,34 +820,46 @@ int btGeneric6DofSpring2Constraint::get_limit_motor_info2(
btScalar dt = BT_ONE / info->fps;
btScalar kd = limot->m_springDamping;
btScalar ks = limot->m_springStiffness;
- btScalar vel = rotational ? angVelA.dot(ax1) - angVelB.dot(ax1) : linVelA.dot(ax1) - linVelB.dot(ax1);
-// btScalar erp = 0.1;
+ btScalar vel;
+ if (rotational)
+ {
+ vel = angVelA.dot(ax1) - angVelB.dot(ax1);
+ }
+ else
+ {
+ btVector3 tanVelA = angVelA.cross(m_calculatedTransformA.getOrigin() - transA.getOrigin());
+ btVector3 tanVelB = angVelB.cross(m_calculatedTransformB.getOrigin() - transB.getOrigin());
+ vel = (linVelA + tanVelA).dot(ax1) - (linVelB + tanVelB).dot(ax1);
+ }
btScalar cfm = BT_ZERO;
btScalar mA = BT_ONE / m_rbA.getInvMass();
btScalar mB = BT_ONE / m_rbB.getInvMass();
- if (rotational) {
+ if (rotational)
+ {
btScalar rrA = (m_calculatedTransformA.getOrigin() - transA.getOrigin()).length2();
btScalar rrB = (m_calculatedTransformB.getOrigin() - transB.getOrigin()).length2();
if (m_rbA.getInvMass()) mA = mA * rrA + 1 / (m_rbA.getInvInertiaTensorWorld() * ax1).length();
if (m_rbB.getInvMass()) mB = mB * rrB + 1 / (m_rbB.getInvInertiaTensorWorld() * ax1).length();
}
- btScalar m = mA > mB ? mB : mA;
+ btScalar m;
+ if (m_rbA.getInvMass() == 0) m = mB; else
+ if (m_rbB.getInvMass() == 0) m = mA; else
+ m = mA*mB / (mA + mB);
btScalar angularfreq = sqrt(ks / m);
-
//limit stiffness (the spring should not be sampled faster that the quarter of its angular frequency)
- if(limot->m_springStiffnessLimited && 0.25 < angularfreq * dt)
+ if (limot->m_springStiffnessLimited && 0.25 < angularfreq * dt)
{
ks = BT_ONE / dt / dt / btScalar(16.0) * m;
}
//avoid damping that would blow up the spring
- if(limot->m_springDampingLimited && kd * dt > m)
+ if (limot->m_springDampingLimited && kd * dt > m)
{
kd = m / dt;
}
btScalar fs = ks * error * dt;
btScalar fd = -kd * (vel) * (rotational ? -1 : 1) * dt;
- btScalar f = (fs+fd);
+ btScalar f = (fs + fd);
// after the spring force affecting the body(es) the new velocity will be
// vel + f / m * (rotational ? -1 : 1)
@@ -828,15 +868,18 @@ int btGeneric6DofSpring2Constraint::get_limit_motor_info2(
// however in practice any value is fine as long as it is greater then the "proper" velocity,
// because the m_lowerLimit and the m_upperLimit will determinate the strength of the final pulling force
// so it is much simpler (and more robust) just to simply use inf (with the proper sign)
+ // (Even with our best intent the "new" velocity is only an estimation. If we underestimate
+ // the "proper" velocity that will weaken the spring, however if we overestimate it, it doesn't
+ // matter, because the solver will limit it according the force limit)
// you may also wonder what if the current velocity (vel) so high that the pulling force will not change its direction (in this iteration)
// will we not request a velocity with the wrong direction ?
- // and the answare is not, because in practice during the solving the current velocity is subtracted from the m_constraintError
+ // and the answer is not, because in practice during the solving the current velocity is subtracted from the m_constraintError
// so the sign of the force that is really matters
info->m_constraintError[srow] = (rotational ? -1 : 1) * (f < 0 ? -SIMD_INFINITY : SIMD_INFINITY);
btScalar minf = f < fd ? f : fd;
btScalar maxf = f < fd ? fd : f;
- if(!rotational)
+ if (!rotational)
{
info->m_lowerLimit[srow] = minf > 0 ? 0 : minf;
info->m_upperLimit[srow] = maxf < 0 ? 0 : maxf;
@@ -855,56 +898,55 @@ int btGeneric6DofSpring2Constraint::get_limit_motor_info2(
return count;
}
-
-//override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+//override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
//If no axis is provided, it uses the default axis for this constraint.
void btGeneric6DofSpring2Constraint::setParam(int num, btScalar value, int axis)
{
- if((axis >= 0) && (axis < 3))
+ if ((axis >= 0) && (axis < 3))
{
- switch(num)
+ switch (num)
{
- case BT_CONSTRAINT_STOP_ERP :
+ case BT_CONSTRAINT_STOP_ERP:
m_linearLimits.m_stopERP[axis] = value;
m_flags |= BT_6DOF_FLAGS_ERP_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2);
break;
- case BT_CONSTRAINT_STOP_CFM :
+ case BT_CONSTRAINT_STOP_CFM:
m_linearLimits.m_stopCFM[axis] = value;
m_flags |= BT_6DOF_FLAGS_CFM_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2);
break;
- case BT_CONSTRAINT_ERP :
+ case BT_CONSTRAINT_ERP:
m_linearLimits.m_motorERP[axis] = value;
m_flags |= BT_6DOF_FLAGS_ERP_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2);
break;
- case BT_CONSTRAINT_CFM :
+ case BT_CONSTRAINT_CFM:
m_linearLimits.m_motorCFM[axis] = value;
m_flags |= BT_6DOF_FLAGS_CFM_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2);
break;
- default :
+ default:
btAssertConstrParams(0);
}
}
- else if((axis >=3) && (axis < 6))
+ else if ((axis >= 3) && (axis < 6))
{
- switch(num)
+ switch (num)
{
- case BT_CONSTRAINT_STOP_ERP :
+ case BT_CONSTRAINT_STOP_ERP:
m_angularLimits[axis - 3].m_stopERP = value;
m_flags |= BT_6DOF_FLAGS_ERP_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2);
break;
- case BT_CONSTRAINT_STOP_CFM :
+ case BT_CONSTRAINT_STOP_CFM:
m_angularLimits[axis - 3].m_stopCFM = value;
m_flags |= BT_6DOF_FLAGS_CFM_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2);
break;
- case BT_CONSTRAINT_ERP :
+ case BT_CONSTRAINT_ERP:
m_angularLimits[axis - 3].m_motorERP = value;
m_flags |= BT_6DOF_FLAGS_ERP_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2);
break;
- case BT_CONSTRAINT_CFM :
+ case BT_CONSTRAINT_CFM:
m_angularLimits[axis - 3].m_motorCFM = value;
m_flags |= BT_6DOF_FLAGS_CFM_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2);
break;
- default :
+ default:
btAssertConstrParams(0);
}
}
@@ -915,54 +957,54 @@ void btGeneric6DofSpring2Constraint::setParam(int num, btScalar value, int axis)
}
//return the local value of parameter
-btScalar btGeneric6DofSpring2Constraint::getParam(int num, int axis) const
+btScalar btGeneric6DofSpring2Constraint::getParam(int num, int axis) const
{
btScalar retVal = 0;
- if((axis >= 0) && (axis < 3))
+ if ((axis >= 0) && (axis < 3))
{
- switch(num)
+ switch (num)
{
- case BT_CONSTRAINT_STOP_ERP :
+ case BT_CONSTRAINT_STOP_ERP:
btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_ERP_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2)));
retVal = m_linearLimits.m_stopERP[axis];
break;
- case BT_CONSTRAINT_STOP_CFM :
+ case BT_CONSTRAINT_STOP_CFM:
btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2)));
retVal = m_linearLimits.m_stopCFM[axis];
break;
- case BT_CONSTRAINT_ERP :
+ case BT_CONSTRAINT_ERP:
btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_ERP_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2)));
retVal = m_linearLimits.m_motorERP[axis];
break;
- case BT_CONSTRAINT_CFM :
+ case BT_CONSTRAINT_CFM:
btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2)));
retVal = m_linearLimits.m_motorCFM[axis];
break;
- default :
+ default:
btAssertConstrParams(0);
}
}
- else if((axis >=3) && (axis < 6))
+ else if ((axis >= 3) && (axis < 6))
{
- switch(num)
+ switch (num)
{
- case BT_CONSTRAINT_STOP_ERP :
+ case BT_CONSTRAINT_STOP_ERP:
btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_ERP_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2)));
retVal = m_angularLimits[axis - 3].m_stopERP;
break;
- case BT_CONSTRAINT_STOP_CFM :
+ case BT_CONSTRAINT_STOP_CFM:
btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2)));
retVal = m_angularLimits[axis - 3].m_stopCFM;
break;
- case BT_CONSTRAINT_ERP :
+ case BT_CONSTRAINT_ERP:
btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_ERP_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2)));
retVal = m_angularLimits[axis - 3].m_motorERP;
break;
- case BT_CONSTRAINT_CFM :
+ case BT_CONSTRAINT_CFM:
btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2)));
retVal = m_angularLimits[axis - 3].m_motorCFM;
break;
- default :
+ default:
btAssertConstrParams(0);
}
}
@@ -973,31 +1015,29 @@ btScalar btGeneric6DofSpring2Constraint::getParam(int num, int axis) const
return retVal;
}
-
-
-void btGeneric6DofSpring2Constraint::setAxis(const btVector3& axis1,const btVector3& axis2)
+void btGeneric6DofSpring2Constraint::setAxis(const btVector3& axis1, const btVector3& axis2)
{
btVector3 zAxis = axis1.normalized();
btVector3 yAxis = axis2.normalized();
- btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system
-
+ btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system
+
btTransform frameInW;
frameInW.setIdentity();
- frameInW.getBasis().setValue( xAxis[0], yAxis[0], zAxis[0],
- xAxis[1], yAxis[1], zAxis[1],
- xAxis[2], yAxis[2], zAxis[2]);
-
+ frameInW.getBasis().setValue(xAxis[0], yAxis[0], zAxis[0],
+ xAxis[1], yAxis[1], zAxis[1],
+ xAxis[2], yAxis[2], zAxis[2]);
+
// now get constraint frame in local coordinate systems
m_frameInA = m_rbA.getCenterOfMassTransform().inverse() * frameInW;
m_frameInB = m_rbB.getCenterOfMassTransform().inverse() * frameInW;
-
+
calculateTransforms();
}
void btGeneric6DofSpring2Constraint::setBounce(int index, btScalar bounce)
{
btAssert((index >= 0) && (index < 6));
- if (index<3)
+ if (index < 3)
m_linearLimits.m_bounce[index] = bounce;
else
m_angularLimits[index - 3].m_bounce = bounce;
@@ -1006,7 +1046,7 @@ void btGeneric6DofSpring2Constraint::setBounce(int index, btScalar bounce)
void btGeneric6DofSpring2Constraint::enableMotor(int index, bool onOff)
{
btAssert((index >= 0) && (index < 6));
- if (index<3)
+ if (index < 3)
m_linearLimits.m_enableMotor[index] = onOff;
else
m_angularLimits[index - 3].m_enableMotor = onOff;
@@ -1015,7 +1055,7 @@ void btGeneric6DofSpring2Constraint::enableMotor(int index, bool onOff)
void btGeneric6DofSpring2Constraint::setServo(int index, bool onOff)
{
btAssert((index >= 0) && (index < 6));
- if (index<3)
+ if (index < 3)
m_linearLimits.m_servoMotor[index] = onOff;
else
m_angularLimits[index - 3].m_servoMotor = onOff;
@@ -1024,18 +1064,16 @@ void btGeneric6DofSpring2Constraint::setServo(int index, bool onOff)
void btGeneric6DofSpring2Constraint::setTargetVelocity(int index, btScalar velocity)
{
btAssert((index >= 0) && (index < 6));
- if (index<3)
+ if (index < 3)
m_linearLimits.m_targetVelocity[index] = velocity;
else
m_angularLimits[index - 3].m_targetVelocity = velocity;
}
-
-
void btGeneric6DofSpring2Constraint::setServoTarget(int index, btScalar targetOrg)
{
btAssert((index >= 0) && (index < 6));
- if (index<3)
+ if (index < 3)
{
m_linearLimits.m_servoTarget[index] = targetOrg;
}
@@ -1044,23 +1082,24 @@ void btGeneric6DofSpring2Constraint::setServoTarget(int index, btScalar targetOr
//wrap between -PI and PI, see also
//https://stackoverflow.com/questions/4633177/c-how-to-wrap-a-float-to-the-interval-pi-pi
- btScalar target = targetOrg+SIMD_PI;
+ btScalar target = targetOrg + SIMD_PI;
if (1)
{
- btScalar m = target - SIMD_2_PI * floor(target/SIMD_2_PI);
+ btScalar m = target - SIMD_2_PI * floor(target / SIMD_2_PI);
// handle boundary cases resulted from floating-point cut off:
{
- if (m>=SIMD_2_PI)
+ if (m >= SIMD_2_PI)
{
target = 0;
- } else
+ }
+ else
{
- if (m<0 )
+ if (m < 0)
{
- if (SIMD_2_PI+m == SIMD_2_PI)
+ if (SIMD_2_PI + m == SIMD_2_PI)
target = 0;
else
- target = SIMD_2_PI+m;
+ target = SIMD_2_PI + m;
}
else
{
@@ -1070,7 +1109,7 @@ void btGeneric6DofSpring2Constraint::setServoTarget(int index, btScalar targetOr
}
target -= SIMD_PI;
}
-
+
m_angularLimits[index - 3].m_servoTarget = target;
}
}
@@ -1078,7 +1117,7 @@ void btGeneric6DofSpring2Constraint::setServoTarget(int index, btScalar targetOr
void btGeneric6DofSpring2Constraint::setMaxMotorForce(int index, btScalar force)
{
btAssert((index >= 0) && (index < 6));
- if (index<3)
+ if (index < 3)
m_linearLimits.m_maxMotorForce[index] = force;
else
m_angularLimits[index - 3].m_maxMotorForce = force;
@@ -1087,19 +1126,22 @@ void btGeneric6DofSpring2Constraint::setMaxMotorForce(int index, btScalar force)
void btGeneric6DofSpring2Constraint::enableSpring(int index, bool onOff)
{
btAssert((index >= 0) && (index < 6));
- if (index<3)
+ if (index < 3)
m_linearLimits.m_enableSpring[index] = onOff;
else
- m_angularLimits[index - 3] .m_enableSpring = onOff;
+ m_angularLimits[index - 3].m_enableSpring = onOff;
}
void btGeneric6DofSpring2Constraint::setStiffness(int index, btScalar stiffness, bool limitIfNeeded)
{
btAssert((index >= 0) && (index < 6));
- if (index<3) {
+ if (index < 3)
+ {
m_linearLimits.m_springStiffness[index] = stiffness;
m_linearLimits.m_springStiffnessLimited[index] = limitIfNeeded;
- } else {
+ }
+ else
+ {
m_angularLimits[index - 3].m_springStiffness = stiffness;
m_angularLimits[index - 3].m_springStiffnessLimited = limitIfNeeded;
}
@@ -1108,10 +1150,13 @@ void btGeneric6DofSpring2Constraint::setStiffness(int index, btScalar stiffness,
void btGeneric6DofSpring2Constraint::setDamping(int index, btScalar damping, bool limitIfNeeded)
{
btAssert((index >= 0) && (index < 6));
- if (index<3) {
+ if (index < 3)
+ {
m_linearLimits.m_springDamping[index] = damping;
m_linearLimits.m_springDampingLimited[index] = limitIfNeeded;
- } else {
+ }
+ else
+ {
m_angularLimits[index - 3].m_springDamping = damping;
m_angularLimits[index - 3].m_springDampingLimited = limitIfNeeded;
}
@@ -1121,9 +1166,9 @@ void btGeneric6DofSpring2Constraint::setEquilibriumPoint()
{
calculateTransforms();
int i;
- for( i = 0; i < 3; i++)
+ for (i = 0; i < 3; i++)
m_linearLimits.m_equilibriumPoint[i] = m_calculatedLinearDiff[i];
- for(i = 0; i < 3; i++)
+ for (i = 0; i < 3; i++)
m_angularLimits[i].m_equilibriumPoint = m_calculatedAxisAngleDiff[i];
}
@@ -1131,35 +1176,38 @@ void btGeneric6DofSpring2Constraint::setEquilibriumPoint(int index)
{
btAssert((index >= 0) && (index < 6));
calculateTransforms();
- if (index<3)
+ if (index < 3)
m_linearLimits.m_equilibriumPoint[index] = m_calculatedLinearDiff[index];
else
- m_angularLimits[index - 3] .m_equilibriumPoint = m_calculatedAxisAngleDiff[index - 3];
+ m_angularLimits[index - 3].m_equilibriumPoint = m_calculatedAxisAngleDiff[index - 3];
}
void btGeneric6DofSpring2Constraint::setEquilibriumPoint(int index, btScalar val)
{
btAssert((index >= 0) && (index < 6));
- if (index<3)
+ if (index < 3)
m_linearLimits.m_equilibriumPoint[index] = val;
else
- m_angularLimits[index - 3] .m_equilibriumPoint = val;
+ m_angularLimits[index - 3].m_equilibriumPoint = val;
}
-
//////////////////////////// btRotationalLimitMotor2 ////////////////////////////////////
void btRotationalLimitMotor2::testLimitValue(btScalar test_value)
{
//we can't normalize the angles here because we would lost the sign that we use later, but it doesn't seem to be a problem
- if(m_loLimit > m_hiLimit) {
+ if (m_loLimit > m_hiLimit)
+ {
m_currentLimit = 0;
m_currentLimitError = btScalar(0.f);
}
- else if(m_loLimit == m_hiLimit) {
+ else if (m_loLimit == m_hiLimit)
+ {
m_currentLimitError = test_value - m_loLimit;
m_currentLimit = 3;
- } else {
+ }
+ else
+ {
m_currentLimitError = test_value - m_loLimit;
m_currentLimitErrorHi = test_value - m_hiLimit;
m_currentLimit = 4;
@@ -1172,18 +1220,20 @@ void btTranslationalLimitMotor2::testLimitValue(int limitIndex, btScalar test_va
{
btScalar loLimit = m_lowerLimit[limitIndex];
btScalar hiLimit = m_upperLimit[limitIndex];
- if(loLimit > hiLimit) {
+ if (loLimit > hiLimit)
+ {
m_currentLimitError[limitIndex] = 0;
m_currentLimit[limitIndex] = 0;
}
- else if(loLimit == hiLimit) {
+ else if (loLimit == hiLimit)
+ {
m_currentLimitError[limitIndex] = test_value - loLimit;
m_currentLimit[limitIndex] = 3;
- } else {
+ }
+ else
+ {
m_currentLimitError[limitIndex] = test_value - loLimit;
m_currentLimitErrorHi[limitIndex] = test_value - hiLimit;
m_currentLimit[limitIndex] = 4;
}
}
-
-
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h
index 1b8d0eace9..bc3ee6d210 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h
@@ -37,7 +37,6 @@ email: projectileman@yahoo.com
http://gimpact.sf.net
*/
-
#ifndef BT_GENERIC_6DOF_CONSTRAINT2_H
#define BT_GENERIC_6DOF_CONSTRAINT2_H
@@ -47,18 +46,17 @@ http://gimpact.sf.net
class btRigidBody;
-
#ifdef BT_USE_DOUBLE_PRECISION
-#define btGeneric6DofSpring2ConstraintData2 btGeneric6DofSpring2ConstraintDoubleData2
-#define btGeneric6DofSpring2ConstraintDataName "btGeneric6DofSpring2ConstraintDoubleData2"
+#define btGeneric6DofSpring2ConstraintData2 btGeneric6DofSpring2ConstraintDoubleData2
+#define btGeneric6DofSpring2ConstraintDataName "btGeneric6DofSpring2ConstraintDoubleData2"
#else
-#define btGeneric6DofSpring2ConstraintData2 btGeneric6DofSpring2ConstraintData
-#define btGeneric6DofSpring2ConstraintDataName "btGeneric6DofSpring2ConstraintData"
-#endif //BT_USE_DOUBLE_PRECISION
+#define btGeneric6DofSpring2ConstraintData2 btGeneric6DofSpring2ConstraintData
+#define btGeneric6DofSpring2ConstraintDataName "btGeneric6DofSpring2ConstraintData"
+#endif //BT_USE_DOUBLE_PRECISION
enum RotateOrder
{
- RO_XYZ=0,
+ RO_XYZ = 0,
RO_XZY,
RO_YXZ,
RO_YZX,
@@ -69,9 +67,9 @@ enum RotateOrder
class btRotationalLimitMotor2
{
public:
-// upper < lower means free
-// upper == lower means locked
-// upper > lower means limited
+ // upper < lower means free
+ // upper == lower means locked
+ // upper > lower means limited
btScalar m_loLimit;
btScalar m_hiLimit;
btScalar m_bounce;
@@ -79,95 +77,92 @@ public:
btScalar m_stopCFM;
btScalar m_motorERP;
btScalar m_motorCFM;
- bool m_enableMotor;
+ bool m_enableMotor;
btScalar m_targetVelocity;
btScalar m_maxMotorForce;
- bool m_servoMotor;
+ bool m_servoMotor;
btScalar m_servoTarget;
- bool m_enableSpring;
+ bool m_enableSpring;
btScalar m_springStiffness;
- bool m_springStiffnessLimited;
+ bool m_springStiffnessLimited;
btScalar m_springDamping;
- bool m_springDampingLimited;
+ bool m_springDampingLimited;
btScalar m_equilibriumPoint;
btScalar m_currentLimitError;
btScalar m_currentLimitErrorHi;
btScalar m_currentPosition;
- int m_currentLimit;
+ int m_currentLimit;
btRotationalLimitMotor2()
{
- m_loLimit = 1.0f;
- m_hiLimit = -1.0f;
- m_bounce = 0.0f;
- m_stopERP = 0.2f;
- m_stopCFM = 0.f;
- m_motorERP = 0.9f;
- m_motorCFM = 0.f;
- m_enableMotor = false;
- m_targetVelocity = 0;
- m_maxMotorForce = 6.0f;
- m_servoMotor = false;
- m_servoTarget = 0;
- m_enableSpring = false;
- m_springStiffness = 0;
+ m_loLimit = 1.0f;
+ m_hiLimit = -1.0f;
+ m_bounce = 0.0f;
+ m_stopERP = 0.2f;
+ m_stopCFM = 0.f;
+ m_motorERP = 0.9f;
+ m_motorCFM = 0.f;
+ m_enableMotor = false;
+ m_targetVelocity = 0;
+ m_maxMotorForce = 6.0f;
+ m_servoMotor = false;
+ m_servoTarget = 0;
+ m_enableSpring = false;
+ m_springStiffness = 0;
m_springStiffnessLimited = false;
- m_springDamping = 0;
- m_springDampingLimited = false;
- m_equilibriumPoint = 0;
+ m_springDamping = 0;
+ m_springDampingLimited = false;
+ m_equilibriumPoint = 0;
- m_currentLimitError = 0;
+ m_currentLimitError = 0;
m_currentLimitErrorHi = 0;
- m_currentPosition = 0;
- m_currentLimit = 0;
+ m_currentPosition = 0;
+ m_currentLimit = 0;
}
- btRotationalLimitMotor2(const btRotationalLimitMotor2 & limot)
+ btRotationalLimitMotor2(const btRotationalLimitMotor2& limot)
{
- m_loLimit = limot.m_loLimit;
- m_hiLimit = limot.m_hiLimit;
- m_bounce = limot.m_bounce;
- m_stopERP = limot.m_stopERP;
- m_stopCFM = limot.m_stopCFM;
- m_motorERP = limot.m_motorERP;
- m_motorCFM = limot.m_motorCFM;
- m_enableMotor = limot.m_enableMotor;
- m_targetVelocity = limot.m_targetVelocity;
- m_maxMotorForce = limot.m_maxMotorForce;
- m_servoMotor = limot.m_servoMotor;
- m_servoTarget = limot.m_servoTarget;
- m_enableSpring = limot.m_enableSpring;
- m_springStiffness = limot.m_springStiffness;
+ m_loLimit = limot.m_loLimit;
+ m_hiLimit = limot.m_hiLimit;
+ m_bounce = limot.m_bounce;
+ m_stopERP = limot.m_stopERP;
+ m_stopCFM = limot.m_stopCFM;
+ m_motorERP = limot.m_motorERP;
+ m_motorCFM = limot.m_motorCFM;
+ m_enableMotor = limot.m_enableMotor;
+ m_targetVelocity = limot.m_targetVelocity;
+ m_maxMotorForce = limot.m_maxMotorForce;
+ m_servoMotor = limot.m_servoMotor;
+ m_servoTarget = limot.m_servoTarget;
+ m_enableSpring = limot.m_enableSpring;
+ m_springStiffness = limot.m_springStiffness;
m_springStiffnessLimited = limot.m_springStiffnessLimited;
- m_springDamping = limot.m_springDamping;
- m_springDampingLimited = limot.m_springDampingLimited;
- m_equilibriumPoint = limot.m_equilibriumPoint;
+ m_springDamping = limot.m_springDamping;
+ m_springDampingLimited = limot.m_springDampingLimited;
+ m_equilibriumPoint = limot.m_equilibriumPoint;
- m_currentLimitError = limot.m_currentLimitError;
+ m_currentLimitError = limot.m_currentLimitError;
m_currentLimitErrorHi = limot.m_currentLimitErrorHi;
- m_currentPosition = limot.m_currentPosition;
- m_currentLimit = limot.m_currentLimit;
+ m_currentPosition = limot.m_currentPosition;
+ m_currentLimit = limot.m_currentLimit;
}
-
bool isLimited()
{
- if(m_loLimit > m_hiLimit) return false;
+ if (m_loLimit > m_hiLimit) return false;
return true;
}
void testLimitValue(btScalar test_value);
};
-
-
class btTranslationalLimitMotor2
{
public:
-// upper < lower means free
-// upper == lower means locked
-// upper > lower means limited
+ // upper < lower means free
+ // upper == lower means locked
+ // upper > lower means limited
btVector3 m_lowerLimit;
btVector3 m_upperLimit;
btVector3 m_bounce;
@@ -175,14 +170,14 @@ public:
btVector3 m_stopCFM;
btVector3 m_motorERP;
btVector3 m_motorCFM;
- bool m_enableMotor[3];
- bool m_servoMotor[3];
- bool m_enableSpring[3];
+ bool m_enableMotor[3];
+ bool m_servoMotor[3];
+ bool m_enableSpring[3];
btVector3 m_servoTarget;
btVector3 m_springStiffness;
- bool m_springStiffnessLimited[3];
+ bool m_springStiffnessLimited[3];
btVector3 m_springDamping;
- bool m_springDampingLimited[3];
+ bool m_springDampingLimited[3];
btVector3 m_equilibriumPoint;
btVector3 m_targetVelocity;
btVector3 m_maxMotorForce;
@@ -190,69 +185,69 @@ public:
btVector3 m_currentLimitError;
btVector3 m_currentLimitErrorHi;
btVector3 m_currentLinearDiff;
- int m_currentLimit[3];
+ int m_currentLimit[3];
btTranslationalLimitMotor2()
{
- m_lowerLimit .setValue(0.f , 0.f , 0.f );
- m_upperLimit .setValue(0.f , 0.f , 0.f );
- m_bounce .setValue(0.f , 0.f , 0.f );
- m_stopERP .setValue(0.2f, 0.2f, 0.2f);
- m_stopCFM .setValue(0.f , 0.f , 0.f );
- m_motorERP .setValue(0.9f, 0.9f, 0.9f);
- m_motorCFM .setValue(0.f , 0.f , 0.f );
-
- m_currentLimitError .setValue(0.f , 0.f , 0.f );
- m_currentLimitErrorHi.setValue(0.f , 0.f , 0.f );
- m_currentLinearDiff .setValue(0.f , 0.f , 0.f );
-
- for(int i=0; i < 3; i++)
+ m_lowerLimit.setValue(0.f, 0.f, 0.f);
+ m_upperLimit.setValue(0.f, 0.f, 0.f);
+ m_bounce.setValue(0.f, 0.f, 0.f);
+ m_stopERP.setValue(0.2f, 0.2f, 0.2f);
+ m_stopCFM.setValue(0.f, 0.f, 0.f);
+ m_motorERP.setValue(0.9f, 0.9f, 0.9f);
+ m_motorCFM.setValue(0.f, 0.f, 0.f);
+
+ m_currentLimitError.setValue(0.f, 0.f, 0.f);
+ m_currentLimitErrorHi.setValue(0.f, 0.f, 0.f);
+ m_currentLinearDiff.setValue(0.f, 0.f, 0.f);
+
+ for (int i = 0; i < 3; i++)
{
- m_enableMotor[i] = false;
- m_servoMotor[i] = false;
- m_enableSpring[i] = false;
- m_servoTarget[i] = btScalar(0.f);
- m_springStiffness[i] = btScalar(0.f);
+ m_enableMotor[i] = false;
+ m_servoMotor[i] = false;
+ m_enableSpring[i] = false;
+ m_servoTarget[i] = btScalar(0.f);
+ m_springStiffness[i] = btScalar(0.f);
m_springStiffnessLimited[i] = false;
- m_springDamping[i] = btScalar(0.f);
- m_springDampingLimited[i] = false;
- m_equilibriumPoint[i] = btScalar(0.f);
- m_targetVelocity[i] = btScalar(0.f);
- m_maxMotorForce[i] = btScalar(0.f);
-
- m_currentLimit[i] = 0;
+ m_springDamping[i] = btScalar(0.f);
+ m_springDampingLimited[i] = false;
+ m_equilibriumPoint[i] = btScalar(0.f);
+ m_targetVelocity[i] = btScalar(0.f);
+ m_maxMotorForce[i] = btScalar(0.f);
+
+ m_currentLimit[i] = 0;
}
}
- btTranslationalLimitMotor2(const btTranslationalLimitMotor2 & other )
+ btTranslationalLimitMotor2(const btTranslationalLimitMotor2& other)
{
- m_lowerLimit = other.m_lowerLimit;
- m_upperLimit = other.m_upperLimit;
- m_bounce = other.m_bounce;
- m_stopERP = other.m_stopERP;
- m_stopCFM = other.m_stopCFM;
- m_motorERP = other.m_motorERP;
- m_motorCFM = other.m_motorCFM;
-
- m_currentLimitError = other.m_currentLimitError;
+ m_lowerLimit = other.m_lowerLimit;
+ m_upperLimit = other.m_upperLimit;
+ m_bounce = other.m_bounce;
+ m_stopERP = other.m_stopERP;
+ m_stopCFM = other.m_stopCFM;
+ m_motorERP = other.m_motorERP;
+ m_motorCFM = other.m_motorCFM;
+
+ m_currentLimitError = other.m_currentLimitError;
m_currentLimitErrorHi = other.m_currentLimitErrorHi;
- m_currentLinearDiff = other.m_currentLinearDiff;
+ m_currentLinearDiff = other.m_currentLinearDiff;
- for(int i=0; i < 3; i++)
+ for (int i = 0; i < 3; i++)
{
- m_enableMotor[i] = other.m_enableMotor[i];
- m_servoMotor[i] = other.m_servoMotor[i];
- m_enableSpring[i] = other.m_enableSpring[i];
- m_servoTarget[i] = other.m_servoTarget[i];
- m_springStiffness[i] = other.m_springStiffness[i];
+ m_enableMotor[i] = other.m_enableMotor[i];
+ m_servoMotor[i] = other.m_servoMotor[i];
+ m_enableSpring[i] = other.m_enableSpring[i];
+ m_servoTarget[i] = other.m_servoTarget[i];
+ m_springStiffness[i] = other.m_springStiffness[i];
m_springStiffnessLimited[i] = other.m_springStiffnessLimited[i];
- m_springDamping[i] = other.m_springDamping[i];
- m_springDampingLimited[i] = other.m_springDampingLimited[i];
- m_equilibriumPoint[i] = other.m_equilibriumPoint[i];
- m_targetVelocity[i] = other.m_targetVelocity[i];
- m_maxMotorForce[i] = other.m_maxMotorForce[i];
+ m_springDamping[i] = other.m_springDamping[i];
+ m_springDampingLimited[i] = other.m_springDampingLimited[i];
+ m_equilibriumPoint[i] = other.m_equilibriumPoint[i];
+ m_targetVelocity[i] = other.m_targetVelocity[i];
+ m_maxMotorForce[i] = other.m_maxMotorForce[i];
- m_currentLimit[i] = other.m_currentLimit[i];
+ m_currentLimit[i] = other.m_currentLimit[i];
}
}
@@ -269,15 +264,14 @@ enum bt6DofFlags2
BT_6DOF_FLAGS_CFM_STOP2 = 1,
BT_6DOF_FLAGS_ERP_STOP2 = 2,
BT_6DOF_FLAGS_CFM_MOTO2 = 4,
- BT_6DOF_FLAGS_ERP_MOTO2 = 8
+ BT_6DOF_FLAGS_ERP_MOTO2 = 8,
};
-#define BT_6DOF_FLAGS_AXIS_SHIFT2 4 // bits per axis
+#define BT_6DOF_FLAGS_AXIS_SHIFT2 4 // bits per axis
-
-ATTRIBUTE_ALIGNED16(class) btGeneric6DofSpring2Constraint : public btTypedConstraint
+ATTRIBUTE_ALIGNED16(class)
+btGeneric6DofSpring2Constraint : public btTypedConstraint
{
protected:
-
btTransform m_frameInA;
btTransform m_frameInB;
@@ -290,45 +284,43 @@ protected:
RotateOrder m_rotateOrder;
protected:
-
- btTransform m_calculatedTransformA;
- btTransform m_calculatedTransformB;
- btVector3 m_calculatedAxisAngleDiff;
- btVector3 m_calculatedAxis[3];
- btVector3 m_calculatedLinearDiff;
- btScalar m_factA;
- btScalar m_factB;
- bool m_hasStaticBody;
- int m_flags;
-
- btGeneric6DofSpring2Constraint& operator=(btGeneric6DofSpring2Constraint&)
+ btTransform m_calculatedTransformA;
+ btTransform m_calculatedTransformB;
+ btVector3 m_calculatedAxisAngleDiff;
+ btVector3 m_calculatedAxis[3];
+ btVector3 m_calculatedLinearDiff;
+ btScalar m_factA;
+ btScalar m_factB;
+ bool m_hasStaticBody;
+ int m_flags;
+
+ btGeneric6DofSpring2Constraint& operator=(btGeneric6DofSpring2Constraint&)
{
btAssert(0);
return *this;
}
- int setAngularLimits(btConstraintInfo2 *info, int row_offset,const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB);
- int setLinearLimits(btConstraintInfo2 *info, int row, const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB);
+ int setAngularLimits(btConstraintInfo2 * info, int row_offset, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB);
+ int setLinearLimits(btConstraintInfo2 * info, int row, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB);
void calculateLinearInfo();
void calculateAngleInfo();
void testAngularLimitMotor(int axis_index);
- void calculateJacobi(btRotationalLimitMotor2* limot, const btTransform& transA,const btTransform& transB, btConstraintInfo2* info, int srow, btVector3& ax1, int rotational, int rotAllowed);
- int get_limit_motor_info2(btRotationalLimitMotor2* limot,
- const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB,
- btConstraintInfo2* info, int row, btVector3& ax1, int rotational, int rotAllowed = false);
+ void calculateJacobi(btRotationalLimitMotor2 * limot, const btTransform& transA, const btTransform& transB, btConstraintInfo2* info, int srow, btVector3& ax1, int rotational, int rotAllowed);
+ int get_limit_motor_info2(btRotationalLimitMotor2 * limot,
+ const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB,
+ btConstraintInfo2* info, int row, btVector3& ax1, int rotational, int rotAllowed = false);
public:
-
BT_DECLARE_ALIGNED_ALLOCATOR();
- btGeneric6DofSpring2Constraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, RotateOrder rotOrder = RO_XYZ);
- btGeneric6DofSpring2Constraint(btRigidBody& rbB, const btTransform& frameInB, RotateOrder rotOrder = RO_XYZ);
+ btGeneric6DofSpring2Constraint(btRigidBody & rbA, btRigidBody & rbB, const btTransform& frameInA, const btTransform& frameInB, RotateOrder rotOrder = RO_XYZ);
+ btGeneric6DofSpring2Constraint(btRigidBody & rbB, const btTransform& frameInB, RotateOrder rotOrder = RO_XYZ);
virtual void buildJacobian() {}
- virtual void getInfo1 (btConstraintInfo1* info);
- virtual void getInfo2 (btConstraintInfo2* info);
+ virtual void getInfo1(btConstraintInfo1 * info);
+ virtual void getInfo2(btConstraintInfo2 * info);
virtual int calculateSerializeBufferSize() const;
virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
@@ -336,19 +328,19 @@ public:
btTranslationalLimitMotor2* getTranslationalLimitMotor() { return &m_linearLimits; }
// Calculates the global transform for the joint offset for body A an B, and also calculates the angle differences between the bodies.
- void calculateTransforms(const btTransform& transA,const btTransform& transB);
+ void calculateTransforms(const btTransform& transA, const btTransform& transB);
void calculateTransforms();
// Gets the global transform of the offset for body A
- const btTransform & getCalculatedTransformA() const { return m_calculatedTransformA; }
+ const btTransform& getCalculatedTransformA() const { return m_calculatedTransformA; }
// Gets the global transform of the offset for body B
- const btTransform & getCalculatedTransformB() const { return m_calculatedTransformB; }
+ const btTransform& getCalculatedTransformB() const { return m_calculatedTransformB; }
- const btTransform & getFrameOffsetA() const { return m_frameInA; }
- const btTransform & getFrameOffsetB() const { return m_frameInB; }
+ const btTransform& getFrameOffsetA() const { return m_frameInA; }
+ const btTransform& getFrameOffsetB() const { return m_frameInB; }
- btTransform & getFrameOffsetA() { return m_frameInA; }
- btTransform & getFrameOffsetB() { return m_frameInB; }
+ btTransform& getFrameOffsetA() { return m_frameInA; }
+ btTransform& getFrameOffsetB() { return m_frameInB; }
// Get the rotation axis in global coordinates ( btGeneric6DofSpring2Constraint::calculateTransforms() must be called previously )
btVector3 getAxis(int axis_index) const { return m_calculatedAxis[axis_index]; }
@@ -359,58 +351,58 @@ public:
// Get the relative position of the constraint pivot ( btGeneric6DofSpring2Constraint::calculateTransforms() must be called previously )
btScalar getRelativePivotPosition(int axis_index) const { return m_calculatedLinearDiff[axis_index]; }
- void setFrames(const btTransform & frameA, const btTransform & frameB);
+ void setFrames(const btTransform& frameA, const btTransform& frameB);
void setLinearLowerLimit(const btVector3& linearLower) { m_linearLimits.m_lowerLimit = linearLower; }
- void getLinearLowerLimit(btVector3& linearLower) { linearLower = m_linearLimits.m_lowerLimit; }
+ void getLinearLowerLimit(btVector3 & linearLower) { linearLower = m_linearLimits.m_lowerLimit; }
void setLinearUpperLimit(const btVector3& linearUpper) { m_linearLimits.m_upperLimit = linearUpper; }
- void getLinearUpperLimit(btVector3& linearUpper) { linearUpper = m_linearLimits.m_upperLimit; }
+ void getLinearUpperLimit(btVector3 & linearUpper) { linearUpper = m_linearLimits.m_upperLimit; }
void setAngularLowerLimit(const btVector3& angularLower)
{
- for(int i = 0; i < 3; i++)
+ for (int i = 0; i < 3; i++)
m_angularLimits[i].m_loLimit = btNormalizeAngle(angularLower[i]);
}
void setAngularLowerLimitReversed(const btVector3& angularLower)
{
- for(int i = 0; i < 3; i++)
+ for (int i = 0; i < 3; i++)
m_angularLimits[i].m_hiLimit = btNormalizeAngle(-angularLower[i]);
}
- void getAngularLowerLimit(btVector3& angularLower)
+ void getAngularLowerLimit(btVector3 & angularLower)
{
- for(int i = 0; i < 3; i++)
+ for (int i = 0; i < 3; i++)
angularLower[i] = m_angularLimits[i].m_loLimit;
}
- void getAngularLowerLimitReversed(btVector3& angularLower)
+ void getAngularLowerLimitReversed(btVector3 & angularLower)
{
- for(int i = 0; i < 3; i++)
+ for (int i = 0; i < 3; i++)
angularLower[i] = -m_angularLimits[i].m_hiLimit;
}
void setAngularUpperLimit(const btVector3& angularUpper)
{
- for(int i = 0; i < 3; i++)
+ for (int i = 0; i < 3; i++)
m_angularLimits[i].m_hiLimit = btNormalizeAngle(angularUpper[i]);
}
void setAngularUpperLimitReversed(const btVector3& angularUpper)
{
- for(int i = 0; i < 3; i++)
+ for (int i = 0; i < 3; i++)
m_angularLimits[i].m_loLimit = btNormalizeAngle(-angularUpper[i]);
}
- void getAngularUpperLimit(btVector3& angularUpper)
+ void getAngularUpperLimit(btVector3 & angularUpper)
{
- for(int i = 0; i < 3; i++)
+ for (int i = 0; i < 3; i++)
angularUpper[i] = m_angularLimits[i].m_hiLimit;
}
- void getAngularUpperLimitReversed(btVector3& angularUpper)
+ void getAngularUpperLimitReversed(btVector3 & angularUpper)
{
- for(int i = 0; i < 3; i++)
+ for (int i = 0; i < 3; i++)
angularUpper[i] = -m_angularLimits[i].m_loLimit;
}
@@ -418,7 +410,7 @@ public:
void setLimit(int axis, btScalar lo, btScalar hi)
{
- if(axis<3)
+ if (axis < 3)
{
m_linearLimits.m_lowerLimit[axis] = lo;
m_linearLimits.m_upperLimit[axis] = hi;
@@ -427,14 +419,14 @@ public:
{
lo = btNormalizeAngle(lo);
hi = btNormalizeAngle(hi);
- m_angularLimits[axis-3].m_loLimit = lo;
- m_angularLimits[axis-3].m_hiLimit = hi;
+ m_angularLimits[axis - 3].m_loLimit = lo;
+ m_angularLimits[axis - 3].m_hiLimit = hi;
}
}
void setLimitReversed(int axis, btScalar lo, btScalar hi)
{
- if(axis<3)
+ if (axis < 3)
{
m_linearLimits.m_lowerLimit[axis] = lo;
m_linearLimits.m_upperLimit[axis] = hi;
@@ -443,54 +435,53 @@ public:
{
lo = btNormalizeAngle(lo);
hi = btNormalizeAngle(hi);
- m_angularLimits[axis-3].m_hiLimit = -lo;
- m_angularLimits[axis-3].m_loLimit = -hi;
+ m_angularLimits[axis - 3].m_hiLimit = -lo;
+ m_angularLimits[axis - 3].m_loLimit = -hi;
}
}
bool isLimited(int limitIndex)
{
- if(limitIndex<3)
+ if (limitIndex < 3)
{
return m_linearLimits.isLimited(limitIndex);
}
- return m_angularLimits[limitIndex-3].isLimited();
+ return m_angularLimits[limitIndex - 3].isLimited();
}
void setRotationOrder(RotateOrder order) { m_rotateOrder = order; }
RotateOrder getRotationOrder() { return m_rotateOrder; }
- void setAxis( const btVector3& axis1, const btVector3& axis2);
+ void setAxis(const btVector3& axis1, const btVector3& axis2);
void setBounce(int index, btScalar bounce);
void enableMotor(int index, bool onOff);
- void setServo(int index, bool onOff); // set the type of the motor (servo or not) (the motor has to be turned on for servo also)
+ void setServo(int index, bool onOff); // set the type of the motor (servo or not) (the motor has to be turned on for servo also)
void setTargetVelocity(int index, btScalar velocity);
void setServoTarget(int index, btScalar target);
void setMaxMotorForce(int index, btScalar force);
void enableSpring(int index, bool onOff);
- void setStiffness(int index, btScalar stiffness, bool limitIfNeeded = true); // if limitIfNeeded is true the system will automatically limit the stiffness in necessary situations where otherwise the spring would move unrealistically too widely
- void setDamping(int index, btScalar damping, bool limitIfNeeded = true); // if limitIfNeeded is true the system will automatically limit the damping in necessary situations where otherwise the spring would blow up
- void setEquilibriumPoint(); // set the current constraint position/orientation as an equilibrium point for all DOF
- void setEquilibriumPoint(int index); // set the current constraint position/orientation as an equilibrium point for given DOF
+ void setStiffness(int index, btScalar stiffness, bool limitIfNeeded = true); // if limitIfNeeded is true the system will automatically limit the stiffness in necessary situations where otherwise the spring would move unrealistically too widely
+ void setDamping(int index, btScalar damping, bool limitIfNeeded = true); // if limitIfNeeded is true the system will automatically limit the damping in necessary situations where otherwise the spring would blow up
+ void setEquilibriumPoint(); // set the current constraint position/orientation as an equilibrium point for all DOF
+ void setEquilibriumPoint(int index); // set the current constraint position/orientation as an equilibrium point for given DOF
void setEquilibriumPoint(int index, btScalar val);
- //override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+ //override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
//If no axis is provided, it uses the default axis for this constraint.
virtual void setParam(int num, btScalar value, int axis = -1);
virtual btScalar getParam(int num, int axis = -1) const;
-
- static btScalar btGetMatrixElem(const btMatrix3x3& mat, int index);
- static bool matrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz);
- static bool matrixToEulerXZY(const btMatrix3x3& mat,btVector3& xyz);
- static bool matrixToEulerYXZ(const btMatrix3x3& mat,btVector3& xyz);
- static bool matrixToEulerYZX(const btMatrix3x3& mat,btVector3& xyz);
- static bool matrixToEulerZXY(const btMatrix3x3& mat,btVector3& xyz);
- static bool matrixToEulerZYX(const btMatrix3x3& mat,btVector3& xyz);
-};
+ static btScalar btGetMatrixElem(const btMatrix3x3& mat, int index);
+ static bool matrixToEulerXYZ(const btMatrix3x3& mat, btVector3& xyz);
+ static bool matrixToEulerXZY(const btMatrix3x3& mat, btVector3& xyz);
+ static bool matrixToEulerYXZ(const btMatrix3x3& mat, btVector3& xyz);
+ static bool matrixToEulerYZX(const btMatrix3x3& mat, btVector3& xyz);
+ static bool matrixToEulerZXY(const btMatrix3x3& mat, btVector3& xyz);
+ static bool matrixToEulerZYX(const btMatrix3x3& mat, btVector3& xyz);
+};
struct btGeneric6DofSpring2ConstraintData
{
@@ -511,12 +502,12 @@ struct btGeneric6DofSpring2ConstraintData
btVector3FloatData m_linearSpringStiffness;
btVector3FloatData m_linearSpringDamping;
btVector3FloatData m_linearEquilibriumPoint;
- char m_linearEnableMotor[4];
- char m_linearServoMotor[4];
- char m_linearEnableSpring[4];
- char m_linearSpringStiffnessLimited[4];
- char m_linearSpringDampingLimited[4];
- char m_padding1[4];
+ char m_linearEnableMotor[4];
+ char m_linearServoMotor[4];
+ char m_linearEnableSpring[4];
+ char m_linearSpringStiffnessLimited[4];
+ char m_linearSpringDampingLimited[4];
+ char m_padding1[4];
btVector3FloatData m_angularUpperLimit;
btVector3FloatData m_angularLowerLimit;
@@ -531,13 +522,13 @@ struct btGeneric6DofSpring2ConstraintData
btVector3FloatData m_angularSpringStiffness;
btVector3FloatData m_angularSpringDamping;
btVector3FloatData m_angularEquilibriumPoint;
- char m_angularEnableMotor[4];
- char m_angularServoMotor[4];
- char m_angularEnableSpring[4];
- char m_angularSpringStiffnessLimited[4];
- char m_angularSpringDampingLimited[4];
+ char m_angularEnableMotor[4];
+ char m_angularServoMotor[4];
+ char m_angularEnableSpring[4];
+ char m_angularSpringStiffnessLimited[4];
+ char m_angularSpringDampingLimited[4];
- int m_rotateOrder;
+ int m_rotateOrder;
};
struct btGeneric6DofSpring2ConstraintDoubleData2
@@ -559,12 +550,12 @@ struct btGeneric6DofSpring2ConstraintDoubleData2
btVector3DoubleData m_linearSpringStiffness;
btVector3DoubleData m_linearSpringDamping;
btVector3DoubleData m_linearEquilibriumPoint;
- char m_linearEnableMotor[4];
- char m_linearServoMotor[4];
- char m_linearEnableSpring[4];
- char m_linearSpringStiffnessLimited[4];
- char m_linearSpringDampingLimited[4];
- char m_padding1[4];
+ char m_linearEnableMotor[4];
+ char m_linearServoMotor[4];
+ char m_linearEnableSpring[4];
+ char m_linearSpringStiffnessLimited[4];
+ char m_linearSpringDampingLimited[4];
+ char m_padding1[4];
btVector3DoubleData m_angularUpperLimit;
btVector3DoubleData m_angularLowerLimit;
@@ -579,13 +570,13 @@ struct btGeneric6DofSpring2ConstraintDoubleData2
btVector3DoubleData m_angularSpringStiffness;
btVector3DoubleData m_angularSpringDamping;
btVector3DoubleData m_angularEquilibriumPoint;
- char m_angularEnableMotor[4];
- char m_angularServoMotor[4];
- char m_angularEnableSpring[4];
- char m_angularSpringStiffnessLimited[4];
- char m_angularSpringDampingLimited[4];
+ char m_angularEnableMotor[4];
+ char m_angularServoMotor[4];
+ char m_angularEnableSpring[4];
+ char m_angularSpringStiffnessLimited[4];
+ char m_angularSpringDampingLimited[4];
- int m_rotateOrder;
+ int m_rotateOrder;
};
SIMD_FORCE_INLINE int btGeneric6DofSpring2Constraint::calculateSerializeBufferSize() const
@@ -596,70 +587,70 @@ SIMD_FORCE_INLINE int btGeneric6DofSpring2Constraint::calculateSerializeBufferSi
SIMD_FORCE_INLINE const char* btGeneric6DofSpring2Constraint::serialize(void* dataBuffer, btSerializer* serializer) const
{
btGeneric6DofSpring2ConstraintData2* dof = (btGeneric6DofSpring2ConstraintData2*)dataBuffer;
- btTypedConstraint::serialize(&dof->m_typeConstraintData,serializer);
+ btTypedConstraint::serialize(&dof->m_typeConstraintData, serializer);
m_frameInA.serialize(dof->m_rbAFrame);
m_frameInB.serialize(dof->m_rbBFrame);
int i;
- for (i=0;i<3;i++)
+ for (i = 0; i < 3; i++)
{
- dof->m_angularLowerLimit.m_floats[i] = m_angularLimits[i].m_loLimit;
- dof->m_angularUpperLimit.m_floats[i] = m_angularLimits[i].m_hiLimit;
- dof->m_angularBounce.m_floats[i] = m_angularLimits[i].m_bounce;
- dof->m_angularStopERP.m_floats[i] = m_angularLimits[i].m_stopERP;
- dof->m_angularStopCFM.m_floats[i] = m_angularLimits[i].m_stopCFM;
- dof->m_angularMotorERP.m_floats[i] = m_angularLimits[i].m_motorERP;
- dof->m_angularMotorCFM.m_floats[i] = m_angularLimits[i].m_motorCFM;
- dof->m_angularTargetVelocity.m_floats[i] = m_angularLimits[i].m_targetVelocity;
- dof->m_angularMaxMotorForce.m_floats[i] = m_angularLimits[i].m_maxMotorForce;
- dof->m_angularServoTarget.m_floats[i] = m_angularLimits[i].m_servoTarget;
- dof->m_angularSpringStiffness.m_floats[i] = m_angularLimits[i].m_springStiffness;
- dof->m_angularSpringDamping.m_floats[i] = m_angularLimits[i].m_springDamping;
+ dof->m_angularLowerLimit.m_floats[i] = m_angularLimits[i].m_loLimit;
+ dof->m_angularUpperLimit.m_floats[i] = m_angularLimits[i].m_hiLimit;
+ dof->m_angularBounce.m_floats[i] = m_angularLimits[i].m_bounce;
+ dof->m_angularStopERP.m_floats[i] = m_angularLimits[i].m_stopERP;
+ dof->m_angularStopCFM.m_floats[i] = m_angularLimits[i].m_stopCFM;
+ dof->m_angularMotorERP.m_floats[i] = m_angularLimits[i].m_motorERP;
+ dof->m_angularMotorCFM.m_floats[i] = m_angularLimits[i].m_motorCFM;
+ dof->m_angularTargetVelocity.m_floats[i] = m_angularLimits[i].m_targetVelocity;
+ dof->m_angularMaxMotorForce.m_floats[i] = m_angularLimits[i].m_maxMotorForce;
+ dof->m_angularServoTarget.m_floats[i] = m_angularLimits[i].m_servoTarget;
+ dof->m_angularSpringStiffness.m_floats[i] = m_angularLimits[i].m_springStiffness;
+ dof->m_angularSpringDamping.m_floats[i] = m_angularLimits[i].m_springDamping;
dof->m_angularEquilibriumPoint.m_floats[i] = m_angularLimits[i].m_equilibriumPoint;
}
- dof->m_angularLowerLimit.m_floats[3] = 0;
- dof->m_angularUpperLimit.m_floats[3] = 0;
- dof->m_angularBounce.m_floats[3] = 0;
- dof->m_angularStopERP.m_floats[3] = 0;
- dof->m_angularStopCFM.m_floats[3] = 0;
- dof->m_angularMotorERP.m_floats[3] = 0;
- dof->m_angularMotorCFM.m_floats[3] = 0;
- dof->m_angularTargetVelocity.m_floats[3] = 0;
- dof->m_angularMaxMotorForce.m_floats[3] = 0;
- dof->m_angularServoTarget.m_floats[3] = 0;
- dof->m_angularSpringStiffness.m_floats[3] = 0;
- dof->m_angularSpringDamping.m_floats[3] = 0;
+ dof->m_angularLowerLimit.m_floats[3] = 0;
+ dof->m_angularUpperLimit.m_floats[3] = 0;
+ dof->m_angularBounce.m_floats[3] = 0;
+ dof->m_angularStopERP.m_floats[3] = 0;
+ dof->m_angularStopCFM.m_floats[3] = 0;
+ dof->m_angularMotorERP.m_floats[3] = 0;
+ dof->m_angularMotorCFM.m_floats[3] = 0;
+ dof->m_angularTargetVelocity.m_floats[3] = 0;
+ dof->m_angularMaxMotorForce.m_floats[3] = 0;
+ dof->m_angularServoTarget.m_floats[3] = 0;
+ dof->m_angularSpringStiffness.m_floats[3] = 0;
+ dof->m_angularSpringDamping.m_floats[3] = 0;
dof->m_angularEquilibriumPoint.m_floats[3] = 0;
- for (i=0;i<4;i++)
+ for (i = 0; i < 4; i++)
{
- dof->m_angularEnableMotor[i] = i < 3 ? ( m_angularLimits[i].m_enableMotor ? 1 : 0 ) : 0;
- dof->m_angularServoMotor[i] = i < 3 ? ( m_angularLimits[i].m_servoMotor ? 1 : 0 ) : 0;
- dof->m_angularEnableSpring[i] = i < 3 ? ( m_angularLimits[i].m_enableSpring ? 1 : 0 ) : 0;
- dof->m_angularSpringStiffnessLimited[i] = i < 3 ? ( m_angularLimits[i].m_springStiffnessLimited ? 1 : 0 ) : 0;
- dof->m_angularSpringDampingLimited[i] = i < 3 ? ( m_angularLimits[i].m_springDampingLimited ? 1 : 0 ) : 0;
+ dof->m_angularEnableMotor[i] = i < 3 ? (m_angularLimits[i].m_enableMotor ? 1 : 0) : 0;
+ dof->m_angularServoMotor[i] = i < 3 ? (m_angularLimits[i].m_servoMotor ? 1 : 0) : 0;
+ dof->m_angularEnableSpring[i] = i < 3 ? (m_angularLimits[i].m_enableSpring ? 1 : 0) : 0;
+ dof->m_angularSpringStiffnessLimited[i] = i < 3 ? (m_angularLimits[i].m_springStiffnessLimited ? 1 : 0) : 0;
+ dof->m_angularSpringDampingLimited[i] = i < 3 ? (m_angularLimits[i].m_springDampingLimited ? 1 : 0) : 0;
}
- m_linearLimits.m_lowerLimit.serialize( dof->m_linearLowerLimit );
- m_linearLimits.m_upperLimit.serialize( dof->m_linearUpperLimit );
- m_linearLimits.m_bounce.serialize( dof->m_linearBounce );
- m_linearLimits.m_stopERP.serialize( dof->m_linearStopERP );
- m_linearLimits.m_stopCFM.serialize( dof->m_linearStopCFM );
- m_linearLimits.m_motorERP.serialize( dof->m_linearMotorERP );
- m_linearLimits.m_motorCFM.serialize( dof->m_linearMotorCFM );
- m_linearLimits.m_targetVelocity.serialize( dof->m_linearTargetVelocity );
- m_linearLimits.m_maxMotorForce.serialize( dof->m_linearMaxMotorForce );
- m_linearLimits.m_servoTarget.serialize( dof->m_linearServoTarget );
- m_linearLimits.m_springStiffness.serialize( dof->m_linearSpringStiffness );
- m_linearLimits.m_springDamping.serialize( dof->m_linearSpringDamping );
- m_linearLimits.m_equilibriumPoint.serialize( dof->m_linearEquilibriumPoint );
- for (i=0;i<4;i++)
+ m_linearLimits.m_lowerLimit.serialize(dof->m_linearLowerLimit);
+ m_linearLimits.m_upperLimit.serialize(dof->m_linearUpperLimit);
+ m_linearLimits.m_bounce.serialize(dof->m_linearBounce);
+ m_linearLimits.m_stopERP.serialize(dof->m_linearStopERP);
+ m_linearLimits.m_stopCFM.serialize(dof->m_linearStopCFM);
+ m_linearLimits.m_motorERP.serialize(dof->m_linearMotorERP);
+ m_linearLimits.m_motorCFM.serialize(dof->m_linearMotorCFM);
+ m_linearLimits.m_targetVelocity.serialize(dof->m_linearTargetVelocity);
+ m_linearLimits.m_maxMotorForce.serialize(dof->m_linearMaxMotorForce);
+ m_linearLimits.m_servoTarget.serialize(dof->m_linearServoTarget);
+ m_linearLimits.m_springStiffness.serialize(dof->m_linearSpringStiffness);
+ m_linearLimits.m_springDamping.serialize(dof->m_linearSpringDamping);
+ m_linearLimits.m_equilibriumPoint.serialize(dof->m_linearEquilibriumPoint);
+ for (i = 0; i < 4; i++)
{
- dof->m_linearEnableMotor[i] = i < 3 ? ( m_linearLimits.m_enableMotor[i] ? 1 : 0 ) : 0;
- dof->m_linearServoMotor[i] = i < 3 ? ( m_linearLimits.m_servoMotor[i] ? 1 : 0 ) : 0;
- dof->m_linearEnableSpring[i] = i < 3 ? ( m_linearLimits.m_enableSpring[i] ? 1 : 0 ) : 0;
- dof->m_linearSpringStiffnessLimited[i] = i < 3 ? ( m_linearLimits.m_springStiffnessLimited[i] ? 1 : 0 ) : 0;
- dof->m_linearSpringDampingLimited[i] = i < 3 ? ( m_linearLimits.m_springDampingLimited[i] ? 1 : 0 ) : 0;
+ dof->m_linearEnableMotor[i] = i < 3 ? (m_linearLimits.m_enableMotor[i] ? 1 : 0) : 0;
+ dof->m_linearServoMotor[i] = i < 3 ? (m_linearLimits.m_servoMotor[i] ? 1 : 0) : 0;
+ dof->m_linearEnableSpring[i] = i < 3 ? (m_linearLimits.m_enableSpring[i] ? 1 : 0) : 0;
+ dof->m_linearSpringStiffnessLimited[i] = i < 3 ? (m_linearLimits.m_springStiffnessLimited[i] ? 1 : 0) : 0;
+ dof->m_linearSpringDampingLimited[i] = i < 3 ? (m_linearLimits.m_springDampingLimited[i] ? 1 : 0) : 0;
}
dof->m_rotateOrder = m_rotateOrder;
@@ -672,8 +663,4 @@ SIMD_FORCE_INLINE const char* btGeneric6DofSpring2Constraint::serialize(void* da
return btGeneric6DofSpring2ConstraintDataName;
}
-
-
-
-
-#endif //BT_GENERIC_6DOF_CONSTRAINT_H
+#endif //BT_GENERIC_6DOF_CONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp
index 3f875989ea..8baf52bcd1 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp
@@ -17,26 +17,23 @@ subject to the following restrictions:
#include "BulletDynamics/Dynamics/btRigidBody.h"
#include "LinearMath/btTransformUtil.h"
-
-btGeneric6DofSpringConstraint::btGeneric6DofSpringConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA)
+btGeneric6DofSpringConstraint::btGeneric6DofSpringConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA)
: btGeneric6DofConstraint(rbA, rbB, frameInA, frameInB, useLinearReferenceFrameA)
{
- init();
+ init();
}
-
btGeneric6DofSpringConstraint::btGeneric6DofSpringConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameB)
- : btGeneric6DofConstraint(rbB, frameInB, useLinearReferenceFrameB)
+ : btGeneric6DofConstraint(rbB, frameInB, useLinearReferenceFrameB)
{
- init();
+ init();
}
-
void btGeneric6DofSpringConstraint::init()
{
m_objectType = D6_SPRING_CONSTRAINT_TYPE;
- for(int i = 0; i < 6; i++)
+ for (int i = 0; i < 6; i++)
{
m_springEnabled[i] = false;
m_equilibriumPoint[i] = btScalar(0.f);
@@ -45,12 +42,11 @@ void btGeneric6DofSpringConstraint::init()
}
}
-
void btGeneric6DofSpringConstraint::enableSpring(int index, bool onOff)
{
btAssert((index >= 0) && (index < 6));
m_springEnabled[index] = onOff;
- if(index < 3)
+ if (index < 3)
{
m_linearLimits.m_enableMotor[index] = onOff;
}
@@ -60,44 +56,38 @@ void btGeneric6DofSpringConstraint::enableSpring(int index, bool onOff)
}
}
-
-
void btGeneric6DofSpringConstraint::setStiffness(int index, btScalar stiffness)
{
btAssert((index >= 0) && (index < 6));
m_springStiffness[index] = stiffness;
}
-
void btGeneric6DofSpringConstraint::setDamping(int index, btScalar damping)
{
btAssert((index >= 0) && (index < 6));
m_springDamping[index] = damping;
}
-
void btGeneric6DofSpringConstraint::setEquilibriumPoint()
{
calculateTransforms();
int i;
- for( i = 0; i < 3; i++)
+ for (i = 0; i < 3; i++)
{
m_equilibriumPoint[i] = m_calculatedLinearDiff[i];
}
- for(i = 0; i < 3; i++)
+ for (i = 0; i < 3; i++)
{
m_equilibriumPoint[i + 3] = m_calculatedAxisAngleDiff[i];
}
}
-
-
void btGeneric6DofSpringConstraint::setEquilibriumPoint(int index)
{
btAssert((index >= 0) && (index < 6));
calculateTransforms();
- if(index < 3)
+ if (index < 3)
{
m_equilibriumPoint[index] = m_calculatedLinearDiff[index];
}
@@ -113,15 +103,14 @@ void btGeneric6DofSpringConstraint::setEquilibriumPoint(int index, btScalar val)
m_equilibriumPoint[index] = val;
}
-
void btGeneric6DofSpringConstraint::internalUpdateSprings(btConstraintInfo2* info)
{
// it is assumed that calculateTransforms() have been called before this call
int i;
//btVector3 relVel = m_rbB.getLinearVelocity() - m_rbA.getLinearVelocity();
- for(i = 0; i < 3; i++)
+ for (i = 0; i < 3; i++)
{
- if(m_springEnabled[i])
+ if (m_springEnabled[i])
{
// get current position of constraint
btScalar currPos = m_calculatedLinearDiff[i];
@@ -130,28 +119,27 @@ void btGeneric6DofSpringConstraint::internalUpdateSprings(btConstraintInfo2* inf
// spring force is (delta * m_stiffness) according to Hooke's Law
btScalar force = delta * m_springStiffness[i];
btScalar velFactor = info->fps * m_springDamping[i] / btScalar(info->m_numIterations);
- m_linearLimits.m_targetVelocity[i] = velFactor * force;
- m_linearLimits.m_maxMotorForce[i] = btFabs(force);
+ m_linearLimits.m_targetVelocity[i] = velFactor * force;
+ m_linearLimits.m_maxMotorForce[i] = btFabs(force);
}
}
- for(i = 0; i < 3; i++)
+ for (i = 0; i < 3; i++)
{
- if(m_springEnabled[i + 3])
+ if (m_springEnabled[i + 3])
{
// get current position of constraint
btScalar currPos = m_calculatedAxisAngleDiff[i];
// calculate difference
- btScalar delta = currPos - m_equilibriumPoint[i+3];
+ btScalar delta = currPos - m_equilibriumPoint[i + 3];
// spring force is (-delta * m_stiffness) according to Hooke's Law
- btScalar force = -delta * m_springStiffness[i+3];
- btScalar velFactor = info->fps * m_springDamping[i+3] / btScalar(info->m_numIterations);
+ btScalar force = -delta * m_springStiffness[i + 3];
+ btScalar velFactor = info->fps * m_springDamping[i + 3] / btScalar(info->m_numIterations);
m_angularLimits[i].m_targetVelocity = velFactor * force;
m_angularLimits[i].m_maxMotorForce = btFabs(force);
}
}
}
-
void btGeneric6DofSpringConstraint::getInfo2(btConstraintInfo2* info)
{
// this will be called by constraint solver at the constraint setup stage
@@ -161,25 +149,21 @@ void btGeneric6DofSpringConstraint::getInfo2(btConstraintInfo2* info)
btGeneric6DofConstraint::getInfo2(info);
}
-
-void btGeneric6DofSpringConstraint::setAxis(const btVector3& axis1,const btVector3& axis2)
+void btGeneric6DofSpringConstraint::setAxis(const btVector3& axis1, const btVector3& axis2)
{
btVector3 zAxis = axis1.normalized();
btVector3 yAxis = axis2.normalized();
- btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system
+ btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system
btTransform frameInW;
frameInW.setIdentity();
- frameInW.getBasis().setValue( xAxis[0], yAxis[0], zAxis[0],
- xAxis[1], yAxis[1], zAxis[1],
- xAxis[2], yAxis[2], zAxis[2]);
+ frameInW.getBasis().setValue(xAxis[0], yAxis[0], zAxis[0],
+ xAxis[1], yAxis[1], zAxis[1],
+ xAxis[2], yAxis[2], zAxis[2]);
// now get constraint frame in local coordinate systems
m_frameInA = m_rbA.getCenterOfMassTransform().inverse() * frameInW;
m_frameInB = m_rbB.getCenterOfMassTransform().inverse() * frameInW;
- calculateTransforms();
+ calculateTransforms();
}
-
-
-
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h
index dac59c6889..02b9d4d05d 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h
@@ -16,20 +16,17 @@ subject to the following restrictions:
#ifndef BT_GENERIC_6DOF_SPRING_CONSTRAINT_H
#define BT_GENERIC_6DOF_SPRING_CONSTRAINT_H
-
#include "LinearMath/btVector3.h"
#include "btTypedConstraint.h"
#include "btGeneric6DofConstraint.h"
#ifdef BT_USE_DOUBLE_PRECISION
-#define btGeneric6DofSpringConstraintData2 btGeneric6DofSpringConstraintDoubleData2
-#define btGeneric6DofSpringConstraintDataName "btGeneric6DofSpringConstraintDoubleData2"
+#define btGeneric6DofSpringConstraintData2 btGeneric6DofSpringConstraintDoubleData2
+#define btGeneric6DofSpringConstraintDataName "btGeneric6DofSpringConstraintDoubleData2"
#else
-#define btGeneric6DofSpringConstraintData2 btGeneric6DofSpringConstraintData
-#define btGeneric6DofSpringConstraintDataName "btGeneric6DofSpringConstraintData"
-#endif //BT_USE_DOUBLE_PRECISION
-
-
+#define btGeneric6DofSpringConstraintData2 btGeneric6DofSpringConstraintData
+#define btGeneric6DofSpringConstraintDataName "btGeneric6DofSpringConstraintData"
+#endif //BT_USE_DOUBLE_PRECISION
/// Generic 6 DOF constraint that allows to set spring motors to any translational and rotational DOF
@@ -41,101 +38,98 @@ subject to the following restrictions:
/// 4 : rotation Y (2nd Euler rotational around new position of Y axis, range [-PI/2+epsilon, PI/2-epsilon] )
/// 5 : rotation Z (1st Euler rotational around Z axis, range [-PI+epsilon, PI-epsilon] )
-ATTRIBUTE_ALIGNED16(class) btGeneric6DofSpringConstraint : public btGeneric6DofConstraint
+ATTRIBUTE_ALIGNED16(class)
+btGeneric6DofSpringConstraint : public btGeneric6DofConstraint
{
protected:
- bool m_springEnabled[6];
- btScalar m_equilibriumPoint[6];
- btScalar m_springStiffness[6];
- btScalar m_springDamping[6]; // between 0 and 1 (1 == no damping)
+ bool m_springEnabled[6];
+ btScalar m_equilibriumPoint[6];
+ btScalar m_springStiffness[6];
+ btScalar m_springDamping[6]; // between 0 and 1 (1 == no damping)
void init();
- void internalUpdateSprings(btConstraintInfo2* info);
-public:
-
+ void internalUpdateSprings(btConstraintInfo2 * info);
+
+public:
BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btGeneric6DofSpringConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA);
- btGeneric6DofSpringConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameB);
+
+ btGeneric6DofSpringConstraint(btRigidBody & rbA, btRigidBody & rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA);
+ btGeneric6DofSpringConstraint(btRigidBody & rbB, const btTransform& frameInB, bool useLinearReferenceFrameB);
void enableSpring(int index, bool onOff);
void setStiffness(int index, btScalar stiffness);
void setDamping(int index, btScalar damping);
- void setEquilibriumPoint(); // set the current constraint position/orientation as an equilibrium point for all DOF
+ void setEquilibriumPoint(); // set the current constraint position/orientation as an equilibrium point for all DOF
void setEquilibriumPoint(int index); // set the current constraint position/orientation as an equilibrium point for given DOF
void setEquilibriumPoint(int index, btScalar val);
bool isSpringEnabled(int index) const
{
- return m_springEnabled[index];
+ return m_springEnabled[index];
}
btScalar getStiffness(int index) const
{
- return m_springStiffness[index];
+ return m_springStiffness[index];
}
btScalar getDamping(int index) const
{
- return m_springDamping[index];
+ return m_springDamping[index];
}
btScalar getEquilibriumPoint(int index) const
{
- return m_equilibriumPoint[index];
+ return m_equilibriumPoint[index];
}
- virtual void setAxis( const btVector3& axis1, const btVector3& axis2);
+ virtual void setAxis(const btVector3& axis1, const btVector3& axis2);
- virtual void getInfo2 (btConstraintInfo2* info);
+ virtual void getInfo2(btConstraintInfo2 * info);
- virtual int calculateSerializeBufferSize() const;
+ virtual int calculateSerializeBufferSize() const;
///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
};
-
struct btGeneric6DofSpringConstraintData
{
- btGeneric6DofConstraintData m_6dofData;
-
- int m_springEnabled[6];
- float m_equilibriumPoint[6];
- float m_springStiffness[6];
- float m_springDamping[6];
+ btGeneric6DofConstraintData m_6dofData;
+
+ int m_springEnabled[6];
+ float m_equilibriumPoint[6];
+ float m_springStiffness[6];
+ float m_springDamping[6];
};
struct btGeneric6DofSpringConstraintDoubleData2
{
- btGeneric6DofConstraintDoubleData2 m_6dofData;
-
- int m_springEnabled[6];
- double m_equilibriumPoint[6];
- double m_springStiffness[6];
- double m_springDamping[6];
-};
+ btGeneric6DofConstraintDoubleData2 m_6dofData;
+ int m_springEnabled[6];
+ double m_equilibriumPoint[6];
+ double m_springStiffness[6];
+ double m_springDamping[6];
+};
-SIMD_FORCE_INLINE int btGeneric6DofSpringConstraint::calculateSerializeBufferSize() const
+SIMD_FORCE_INLINE int btGeneric6DofSpringConstraint::calculateSerializeBufferSize() const
{
return sizeof(btGeneric6DofSpringConstraintData2);
}
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
-SIMD_FORCE_INLINE const char* btGeneric6DofSpringConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE const char* btGeneric6DofSpringConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
{
btGeneric6DofSpringConstraintData2* dof = (btGeneric6DofSpringConstraintData2*)dataBuffer;
- btGeneric6DofConstraint::serialize(&dof->m_6dofData,serializer);
+ btGeneric6DofConstraint::serialize(&dof->m_6dofData, serializer);
int i;
- for (i=0;i<6;i++)
+ for (i = 0; i < 6; i++)
{
dof->m_equilibriumPoint[i] = m_equilibriumPoint[i];
dof->m_springDamping[i] = m_springDamping[i];
- dof->m_springEnabled[i] = m_springEnabled[i]? 1 : 0;
+ dof->m_springEnabled[i] = m_springEnabled[i] ? 1 : 0;
dof->m_springStiffness[i] = m_springStiffness[i];
}
return btGeneric6DofSpringConstraintDataName;
}
-#endif // BT_GENERIC_6DOF_SPRING_CONSTRAINT_H
-
+#endif // BT_GENERIC_6DOF_SPRING_CONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp
index 4be2aabe4d..6507e1a0a7 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp
@@ -13,54 +13,49 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
-
#include "btHinge2Constraint.h"
#include "BulletDynamics/Dynamics/btRigidBody.h"
#include "LinearMath/btTransformUtil.h"
-
-
// constructor
// anchor, axis1 and axis2 are in world coordinate system
// axis1 must be orthogonal to axis2
btHinge2Constraint::btHinge2Constraint(btRigidBody& rbA, btRigidBody& rbB, btVector3& anchor, btVector3& axis1, btVector3& axis2)
-: btGeneric6DofSpring2Constraint(rbA, rbB, btTransform::getIdentity(), btTransform::getIdentity(),RO_XYZ),
- m_anchor(anchor),
- m_axis1(axis1),
- m_axis2(axis2)
+ : btGeneric6DofSpring2Constraint(rbA, rbB, btTransform::getIdentity(), btTransform::getIdentity(), RO_XYZ),
+ m_anchor(anchor),
+ m_axis1(axis1),
+ m_axis2(axis2)
{
// build frame basis
// 6DOF constraint uses Euler angles and to define limits
// it is assumed that rotational order is :
// Z - first, allowed limits are (-PI,PI);
- // new position of Y - second (allowed limits are (-PI/2 + epsilon, PI/2 - epsilon), where epsilon is a small positive number
+ // new position of Y - second (allowed limits are (-PI/2 + epsilon, PI/2 - epsilon), where epsilon is a small positive number
// used to prevent constraint from instability on poles;
// new position of X, allowed limits are (-PI,PI);
// So to simulate ODE Universal joint we should use parent axis as Z, child axis as Y and limit all other DOFs
// Build the frame in world coordinate system first
btVector3 zAxis = axis1.normalize();
btVector3 xAxis = axis2.normalize();
- btVector3 yAxis = zAxis.cross(xAxis); // we want right coordinate system
+ btVector3 yAxis = zAxis.cross(xAxis); // we want right coordinate system
btTransform frameInW;
frameInW.setIdentity();
- frameInW.getBasis().setValue( xAxis[0], yAxis[0], zAxis[0],
- xAxis[1], yAxis[1], zAxis[1],
- xAxis[2], yAxis[2], zAxis[2]);
+ frameInW.getBasis().setValue(xAxis[0], yAxis[0], zAxis[0],
+ xAxis[1], yAxis[1], zAxis[1],
+ xAxis[2], yAxis[2], zAxis[2]);
frameInW.setOrigin(anchor);
// now get constraint frame in local coordinate systems
m_frameInA = rbA.getCenterOfMassTransform().inverse() * frameInW;
m_frameInB = rbB.getCenterOfMassTransform().inverse() * frameInW;
// sei limits
setLinearLowerLimit(btVector3(0.f, 0.f, -1.f));
- setLinearUpperLimit(btVector3(0.f, 0.f, 1.f));
+ setLinearUpperLimit(btVector3(0.f, 0.f, 1.f));
// like front wheels of a car
- setAngularLowerLimit(btVector3(1.f, 0.f, -SIMD_HALF_PI * 0.5f));
- setAngularUpperLimit(btVector3(-1.f, 0.f, SIMD_HALF_PI * 0.5f));
+ setAngularLowerLimit(btVector3(1.f, 0.f, -SIMD_HALF_PI * 0.5f));
+ setAngularUpperLimit(btVector3(-1.f, 0.f, SIMD_HALF_PI * 0.5f));
// enable suspension
enableSpring(2, true);
setStiffness(2, SIMD_PI * SIMD_PI * 4.f);
setDamping(2, 0.01f);
setEquilibriumPoint();
}
-
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHinge2Constraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHinge2Constraint.h
index 06a8e3ecd1..95f604a890 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHinge2Constraint.h
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHinge2Constraint.h
@@ -16,32 +16,30 @@ subject to the following restrictions:
#ifndef BT_HINGE2_CONSTRAINT_H
#define BT_HINGE2_CONSTRAINT_H
-
-
#include "LinearMath/btVector3.h"
#include "btTypedConstraint.h"
#include "btGeneric6DofSpring2Constraint.h"
-
-
// Constraint similar to ODE Hinge2 Joint
// has 3 degrees of frredom:
// 2 rotational degrees of freedom, similar to Euler rotations around Z (axis 1) and X (axis 2)
// 1 translational (along axis Z) with suspension spring
-ATTRIBUTE_ALIGNED16(class) btHinge2Constraint : public btGeneric6DofSpring2Constraint
+ATTRIBUTE_ALIGNED16(class)
+btHinge2Constraint : public btGeneric6DofSpring2Constraint
{
protected:
- btVector3 m_anchor;
- btVector3 m_axis1;
- btVector3 m_axis2;
+ btVector3 m_anchor;
+ btVector3 m_axis1;
+ btVector3 m_axis2;
+
public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
// constructor
// anchor, axis1 and axis2 are in world coordinate system
// axis1 must be orthogonal to axis2
- btHinge2Constraint(btRigidBody& rbA, btRigidBody& rbB, btVector3& anchor, btVector3& axis1, btVector3& axis2);
+ btHinge2Constraint(btRigidBody & rbA, btRigidBody & rbB, btVector3 & anchor, btVector3 & axis1, btVector3 & axis2);
// access
const btVector3& getAnchor() { return m_calculatedTransformA.getOrigin(); }
const btVector3& getAnchor2() { return m_calculatedTransformB.getOrigin(); }
@@ -51,10 +49,7 @@ public:
btScalar getAngle2() { return getAngle(0); }
// limits
void setUpperLimit(btScalar ang1max) { setAngularUpperLimit(btVector3(-1.f, 0.f, ang1max)); }
- void setLowerLimit(btScalar ang1min) { setAngularLowerLimit(btVector3( 1.f, 0.f, ang1min)); }
+ void setLowerLimit(btScalar ang1min) { setAngularLowerLimit(btVector3(1.f, 0.f, ang1min)); }
};
-
-
-#endif // BT_HINGE2_CONSTRAINT_H
-
+#endif // BT_HINGE2_CONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp
index 7e5e6f9e54..aa6f69000d 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp
@@ -13,7 +13,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#include "btHingeConstraint.h"
#include "BulletDynamics/Dynamics/btRigidBody.h"
#include "LinearMath/btTransformUtil.h"
@@ -21,8 +20,6 @@ subject to the following restrictions:
#include <new>
#include "btSolverBody.h"
-
-
//#define HINGE_USE_OBSOLETE_SOLVER false
#define HINGE_USE_OBSOLETE_SOLVER false
@@ -30,59 +27,60 @@ subject to the following restrictions:
#ifndef __SPU__
-
-
-
-
-btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB,
- const btVector3& axisInA,const btVector3& axisInB, bool useReferenceFrameA)
- :btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA,rbB),
+btHingeConstraint::btHingeConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& pivotInA, const btVector3& pivotInB,
+ const btVector3& axisInA, const btVector3& axisInB, bool useReferenceFrameA)
+ : btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA, rbB),
#ifdef _BT_USE_CENTER_LIMIT_
- m_limit(),
+ m_limit(),
#endif
- m_angularOnly(false),
- m_enableAngularMotor(false),
- m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER),
- m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET),
- m_useReferenceFrameA(useReferenceFrameA),
- m_flags(0),
- m_normalCFM(0),
- m_normalERP(0),
- m_stopCFM(0),
- m_stopERP(0)
+ m_angularOnly(false),
+ m_enableAngularMotor(false),
+ m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER),
+ m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET),
+ m_useReferenceFrameA(useReferenceFrameA),
+ m_flags(0),
+ m_normalCFM(0),
+ m_normalERP(0),
+ m_stopCFM(0),
+ m_stopERP(0)
{
m_rbAFrame.getOrigin() = pivotInA;
-
+
// since no frame is given, assume this to be zero angle and just pick rb transform axis
btVector3 rbAxisA1 = rbA.getCenterOfMassTransform().getBasis().getColumn(0);
btVector3 rbAxisA2;
btScalar projection = axisInA.dot(rbAxisA1);
- if (projection >= 1.0f - SIMD_EPSILON) {
+ if (projection >= 1.0f - SIMD_EPSILON)
+ {
rbAxisA1 = -rbA.getCenterOfMassTransform().getBasis().getColumn(2);
rbAxisA2 = rbA.getCenterOfMassTransform().getBasis().getColumn(1);
- } else if (projection <= -1.0f + SIMD_EPSILON) {
+ }
+ else if (projection <= -1.0f + SIMD_EPSILON)
+ {
rbAxisA1 = rbA.getCenterOfMassTransform().getBasis().getColumn(2);
- rbAxisA2 = rbA.getCenterOfMassTransform().getBasis().getColumn(1);
- } else {
+ rbAxisA2 = rbA.getCenterOfMassTransform().getBasis().getColumn(1);
+ }
+ else
+ {
rbAxisA2 = axisInA.cross(rbAxisA1);
rbAxisA1 = rbAxisA2.cross(axisInA);
}
- m_rbAFrame.getBasis().setValue( rbAxisA1.getX(),rbAxisA2.getX(),axisInA.getX(),
- rbAxisA1.getY(),rbAxisA2.getY(),axisInA.getY(),
- rbAxisA1.getZ(),rbAxisA2.getZ(),axisInA.getZ() );
+ m_rbAFrame.getBasis().setValue(rbAxisA1.getX(), rbAxisA2.getX(), axisInA.getX(),
+ rbAxisA1.getY(), rbAxisA2.getY(), axisInA.getY(),
+ rbAxisA1.getZ(), rbAxisA2.getZ(), axisInA.getZ());
+
+ btQuaternion rotationArc = shortestArcQuat(axisInA, axisInB);
+ btVector3 rbAxisB1 = quatRotate(rotationArc, rbAxisA1);
+ btVector3 rbAxisB2 = axisInB.cross(rbAxisB1);
- btQuaternion rotationArc = shortestArcQuat(axisInA,axisInB);
- btVector3 rbAxisB1 = quatRotate(rotationArc,rbAxisA1);
- btVector3 rbAxisB2 = axisInB.cross(rbAxisB1);
-
m_rbBFrame.getOrigin() = pivotInB;
- m_rbBFrame.getBasis().setValue( rbAxisB1.getX(),rbAxisB2.getX(),axisInB.getX(),
- rbAxisB1.getY(),rbAxisB2.getY(),axisInB.getY(),
- rbAxisB1.getZ(),rbAxisB2.getZ(),axisInB.getZ() );
-
-#ifndef _BT_USE_CENTER_LIMIT_
+ m_rbBFrame.getBasis().setValue(rbAxisB1.getX(), rbAxisB2.getX(), axisInB.getX(),
+ rbAxisB1.getY(), rbAxisB2.getY(), axisInB.getY(),
+ rbAxisB1.getZ(), rbAxisB2.getZ(), axisInB.getZ());
+
+#ifndef _BT_USE_CENTER_LIMIT_
//start with free
m_lowerLimit = btScalar(1.0f);
m_upperLimit = btScalar(-1.0f);
@@ -94,47 +92,44 @@ btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const bt
m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f);
}
-
-
-btHingeConstraint::btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,const btVector3& axisInA, bool useReferenceFrameA)
-:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA),
+btHingeConstraint::btHingeConstraint(btRigidBody& rbA, const btVector3& pivotInA, const btVector3& axisInA, bool useReferenceFrameA)
+ : btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA),
#ifdef _BT_USE_CENTER_LIMIT_
-m_limit(),
+ m_limit(),
#endif
-m_angularOnly(false), m_enableAngularMotor(false),
-m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER),
-m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET),
-m_useReferenceFrameA(useReferenceFrameA),
-m_flags(0),
-m_normalCFM(0),
-m_normalERP(0),
-m_stopCFM(0),
-m_stopERP(0)
+ m_angularOnly(false),
+ m_enableAngularMotor(false),
+ m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER),
+ m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET),
+ m_useReferenceFrameA(useReferenceFrameA),
+ m_flags(0),
+ m_normalCFM(0),
+ m_normalERP(0),
+ m_stopCFM(0),
+ m_stopERP(0)
{
-
// since no frame is given, assume this to be zero angle and just pick rb transform axis
// fixed axis in worldspace
btVector3 rbAxisA1, rbAxisA2;
btPlaneSpace1(axisInA, rbAxisA1, rbAxisA2);
m_rbAFrame.getOrigin() = pivotInA;
- m_rbAFrame.getBasis().setValue( rbAxisA1.getX(),rbAxisA2.getX(),axisInA.getX(),
- rbAxisA1.getY(),rbAxisA2.getY(),axisInA.getY(),
- rbAxisA1.getZ(),rbAxisA2.getZ(),axisInA.getZ() );
+ m_rbAFrame.getBasis().setValue(rbAxisA1.getX(), rbAxisA2.getX(), axisInA.getX(),
+ rbAxisA1.getY(), rbAxisA2.getY(), axisInA.getY(),
+ rbAxisA1.getZ(), rbAxisA2.getZ(), axisInA.getZ());
btVector3 axisInB = rbA.getCenterOfMassTransform().getBasis() * axisInA;
- btQuaternion rotationArc = shortestArcQuat(axisInA,axisInB);
- btVector3 rbAxisB1 = quatRotate(rotationArc,rbAxisA1);
+ btQuaternion rotationArc = shortestArcQuat(axisInA, axisInB);
+ btVector3 rbAxisB1 = quatRotate(rotationArc, rbAxisA1);
btVector3 rbAxisB2 = axisInB.cross(rbAxisB1);
-
m_rbBFrame.getOrigin() = rbA.getCenterOfMassTransform()(pivotInA);
- m_rbBFrame.getBasis().setValue( rbAxisB1.getX(),rbAxisB2.getX(),axisInB.getX(),
- rbAxisB1.getY(),rbAxisB2.getY(),axisInB.getY(),
- rbAxisB1.getZ(),rbAxisB2.getZ(),axisInB.getZ() );
-
-#ifndef _BT_USE_CENTER_LIMIT_
+ m_rbBFrame.getBasis().setValue(rbAxisB1.getX(), rbAxisB2.getX(), axisInB.getX(),
+ rbAxisB1.getY(), rbAxisB2.getY(), axisInB.getY(),
+ rbAxisB1.getZ(), rbAxisB2.getZ(), axisInB.getZ());
+
+#ifndef _BT_USE_CENTER_LIMIT_
//start with free
m_lowerLimit = btScalar(1.0f);
m_upperLimit = btScalar(-1.0f);
@@ -146,26 +141,24 @@ m_stopERP(0)
m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f);
}
-
-
-btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB,
- const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA)
-:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA,rbB),m_rbAFrame(rbAFrame),m_rbBFrame(rbBFrame),
+btHingeConstraint::btHingeConstraint(btRigidBody& rbA, btRigidBody& rbB,
+ const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA)
+ : btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA, rbB), m_rbAFrame(rbAFrame), m_rbBFrame(rbBFrame),
#ifdef _BT_USE_CENTER_LIMIT_
-m_limit(),
+ m_limit(),
#endif
-m_angularOnly(false),
-m_enableAngularMotor(false),
-m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER),
-m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET),
-m_useReferenceFrameA(useReferenceFrameA),
-m_flags(0),
-m_normalCFM(0),
-m_normalERP(0),
-m_stopCFM(0),
-m_stopERP(0)
+ m_angularOnly(false),
+ m_enableAngularMotor(false),
+ m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER),
+ m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET),
+ m_useReferenceFrameA(useReferenceFrameA),
+ m_flags(0),
+ m_normalCFM(0),
+ m_normalERP(0),
+ m_stopCFM(0),
+ m_stopERP(0)
{
-#ifndef _BT_USE_CENTER_LIMIT_
+#ifndef _BT_USE_CENTER_LIMIT_
//start with free
m_lowerLimit = btScalar(1.0f);
m_upperLimit = btScalar(-1.0f);
@@ -175,30 +168,28 @@ m_stopERP(0)
m_solveLimit = false;
#endif
m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f);
-}
-
-
+}
btHingeConstraint::btHingeConstraint(btRigidBody& rbA, const btTransform& rbAFrame, bool useReferenceFrameA)
-:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA),m_rbAFrame(rbAFrame),m_rbBFrame(rbAFrame),
+ : btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA), m_rbAFrame(rbAFrame), m_rbBFrame(rbAFrame),
#ifdef _BT_USE_CENTER_LIMIT_
-m_limit(),
+ m_limit(),
#endif
-m_angularOnly(false),
-m_enableAngularMotor(false),
-m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER),
-m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET),
-m_useReferenceFrameA(useReferenceFrameA),
-m_flags(0),
-m_normalCFM(0),
-m_normalERP(0),
-m_stopCFM(0),
-m_stopERP(0)
+ m_angularOnly(false),
+ m_enableAngularMotor(false),
+ m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER),
+ m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET),
+ m_useReferenceFrameA(useReferenceFrameA),
+ m_flags(0),
+ m_normalCFM(0),
+ m_normalERP(0),
+ m_stopCFM(0),
+ m_stopERP(0)
{
///not providing rigidbody B means implicitly using worldspace for body B
m_rbBFrame.getOrigin() = m_rbA.getCenterOfMassTransform()(m_rbAFrame.getOrigin());
-#ifndef _BT_USE_CENTER_LIMIT_
+#ifndef _BT_USE_CENTER_LIMIT_
//start with free
m_lowerLimit = btScalar(1.0f);
m_upperLimit = btScalar(-1.0f);
@@ -210,9 +201,7 @@ m_stopERP(0)
m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f);
}
-
-
-void btHingeConstraint::buildJacobian()
+void btHingeConstraint::buildJacobian()
{
if (m_useSolveConstraintObsolete)
{
@@ -221,8 +210,8 @@ void btHingeConstraint::buildJacobian()
if (!m_angularOnly)
{
- btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin();
- btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin();
+ btVector3 pivotAInW = m_rbA.getCenterOfMassTransform() * m_rbAFrame.getOrigin();
+ btVector3 pivotBInW = m_rbB.getCenterOfMassTransform() * m_rbBFrame.getOrigin();
btVector3 relPos = pivotBInW - pivotAInW;
btVector3 normal[3];
@@ -232,23 +221,23 @@ void btHingeConstraint::buildJacobian()
}
else
{
- normal[0].setValue(btScalar(1.0),0,0);
+ normal[0].setValue(btScalar(1.0), 0, 0);
}
btPlaneSpace1(normal[0], normal[1], normal[2]);
- for (int i=0;i<3;i++)
+ for (int i = 0; i < 3; i++)
{
new (&m_jac[i]) btJacobianEntry(
- m_rbA.getCenterOfMassTransform().getBasis().transpose(),
- m_rbB.getCenterOfMassTransform().getBasis().transpose(),
- pivotAInW - m_rbA.getCenterOfMassPosition(),
- pivotBInW - m_rbB.getCenterOfMassPosition(),
- normal[i],
- m_rbA.getInvInertiaDiagLocal(),
- m_rbA.getInvMass(),
- m_rbB.getInvInertiaDiagLocal(),
- m_rbB.getInvMass());
+ m_rbA.getCenterOfMassTransform().getBasis().transpose(),
+ m_rbB.getCenterOfMassTransform().getBasis().transpose(),
+ pivotAInW - m_rbA.getCenterOfMassPosition(),
+ pivotBInW - m_rbB.getCenterOfMassPosition(),
+ normal[i],
+ m_rbA.getInvInertiaDiagLocal(),
+ m_rbA.getInvMass(),
+ m_rbB.getInvInertiaDiagLocal(),
+ m_rbB.getInvMass());
}
}
@@ -258,60 +247,55 @@ void btHingeConstraint::buildJacobian()
//this is unused for now, it's a todo
btVector3 jointAxis0local;
btVector3 jointAxis1local;
-
- btPlaneSpace1(m_rbAFrame.getBasis().getColumn(2),jointAxis0local,jointAxis1local);
+
+ btPlaneSpace1(m_rbAFrame.getBasis().getColumn(2), jointAxis0local, jointAxis1local);
btVector3 jointAxis0 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis0local;
btVector3 jointAxis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis1local;
btVector3 hingeAxisWorld = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2);
-
- new (&m_jacAng[0]) btJacobianEntry(jointAxis0,
- m_rbA.getCenterOfMassTransform().getBasis().transpose(),
- m_rbB.getCenterOfMassTransform().getBasis().transpose(),
- m_rbA.getInvInertiaDiagLocal(),
- m_rbB.getInvInertiaDiagLocal());
-
- new (&m_jacAng[1]) btJacobianEntry(jointAxis1,
- m_rbA.getCenterOfMassTransform().getBasis().transpose(),
- m_rbB.getCenterOfMassTransform().getBasis().transpose(),
- m_rbA.getInvInertiaDiagLocal(),
- m_rbB.getInvInertiaDiagLocal());
-
- new (&m_jacAng[2]) btJacobianEntry(hingeAxisWorld,
- m_rbA.getCenterOfMassTransform().getBasis().transpose(),
- m_rbB.getCenterOfMassTransform().getBasis().transpose(),
- m_rbA.getInvInertiaDiagLocal(),
- m_rbB.getInvInertiaDiagLocal());
-
- // clear accumulator
- m_accLimitImpulse = btScalar(0.);
-
- // test angular limit
- testLimit(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
- //Compute K = J*W*J' for hinge axis
- btVector3 axisA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2);
- m_kHinge = 1.0f / (getRigidBodyA().computeAngularImpulseDenominator(axisA) +
- getRigidBodyB().computeAngularImpulseDenominator(axisA));
+ new (&m_jacAng[0]) btJacobianEntry(jointAxis0,
+ m_rbA.getCenterOfMassTransform().getBasis().transpose(),
+ m_rbB.getCenterOfMassTransform().getBasis().transpose(),
+ m_rbA.getInvInertiaDiagLocal(),
+ m_rbB.getInvInertiaDiagLocal());
- }
-}
+ new (&m_jacAng[1]) btJacobianEntry(jointAxis1,
+ m_rbA.getCenterOfMassTransform().getBasis().transpose(),
+ m_rbB.getCenterOfMassTransform().getBasis().transpose(),
+ m_rbA.getInvInertiaDiagLocal(),
+ m_rbB.getInvInertiaDiagLocal());
+ new (&m_jacAng[2]) btJacobianEntry(hingeAxisWorld,
+ m_rbA.getCenterOfMassTransform().getBasis().transpose(),
+ m_rbB.getCenterOfMassTransform().getBasis().transpose(),
+ m_rbA.getInvInertiaDiagLocal(),
+ m_rbB.getInvInertiaDiagLocal());
-#endif //__SPU__
+ // clear accumulator
+ m_accLimitImpulse = btScalar(0.);
+ // test angular limit
+ testLimit(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
-static inline btScalar btNormalizeAnglePositive(btScalar angle)
-{
- return btFmod(btFmod(angle, btScalar(2.0*SIMD_PI)) + btScalar(2.0*SIMD_PI), btScalar(2.0*SIMD_PI));
+ //Compute K = J*W*J' for hinge axis
+ btVector3 axisA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2);
+ m_kHinge = 1.0f / (getRigidBodyA().computeAngularImpulseDenominator(axisA) +
+ getRigidBodyB().computeAngularImpulseDenominator(axisA));
+ }
}
+#endif //__SPU__
+static inline btScalar btNormalizeAnglePositive(btScalar angle)
+{
+ return btFmod(btFmod(angle, btScalar(2.0 * SIMD_PI)) + btScalar(2.0 * SIMD_PI), btScalar(2.0 * SIMD_PI));
+}
static btScalar btShortestAngularDistance(btScalar accAngle, btScalar curAngle)
{
btScalar result = btNormalizeAngle(btNormalizeAnglePositive(btNormalizeAnglePositive(curAngle) -
- btNormalizeAnglePositive(accAngle)));
+ btNormalizeAnglePositive(accAngle)));
return result;
}
@@ -320,41 +304,36 @@ static btScalar btShortestAngleUpdate(btScalar accAngle, btScalar curAngle)
btScalar tol(0.3);
btScalar result = btShortestAngularDistance(accAngle, curAngle);
- if (btFabs(result) > tol)
+ if (btFabs(result) > tol)
return curAngle;
- else
+ else
return accAngle + result;
return curAngle;
}
-
btScalar btHingeAccumulatedAngleConstraint::getAccumulatedHingeAngle()
{
btScalar hingeAngle = getHingeAngle();
- m_accumulatedAngle = btShortestAngleUpdate(m_accumulatedAngle,hingeAngle);
+ m_accumulatedAngle = btShortestAngleUpdate(m_accumulatedAngle, hingeAngle);
return m_accumulatedAngle;
}
-void btHingeAccumulatedAngleConstraint::setAccumulatedHingeAngle(btScalar accAngle)
+void btHingeAccumulatedAngleConstraint::setAccumulatedHingeAngle(btScalar accAngle)
{
- m_accumulatedAngle = accAngle;
+ m_accumulatedAngle = accAngle;
}
void btHingeAccumulatedAngleConstraint::getInfo1(btConstraintInfo1* info)
{
//update m_accumulatedAngle
btScalar curHingeAngle = getHingeAngle();
- m_accumulatedAngle = btShortestAngleUpdate(m_accumulatedAngle,curHingeAngle);
+ m_accumulatedAngle = btShortestAngleUpdate(m_accumulatedAngle, curHingeAngle);
btHingeConstraint::getInfo1(info);
-
}
-
void btHingeConstraint::getInfo1(btConstraintInfo1* info)
{
-
-
if (m_useSolveConstraintObsolete)
{
info->m_numConstraintRows = 0;
@@ -362,17 +341,16 @@ void btHingeConstraint::getInfo1(btConstraintInfo1* info)
}
else
{
- info->m_numConstraintRows = 5; // Fixed 3 linear + 2 angular
- info->nub = 1;
+ info->m_numConstraintRows = 5; // Fixed 3 linear + 2 angular
+ info->nub = 1;
//always add the row, to avoid computation (data is not available yet)
//prepare constraint
- testLimit(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
- if(getSolveLimit() || getEnableAngularMotor())
+ testLimit(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
+ if (getSolveLimit() || getEnableAngularMotor())
{
- info->m_numConstraintRows++; // limit 3rd anguar as well
- info->nub--;
+ info->m_numConstraintRows++; // limit 3rd anguar as well
+ info->nub--;
}
-
}
}
@@ -386,41 +364,38 @@ void btHingeConstraint::getInfo1NonVirtual(btConstraintInfo1* info)
else
{
//always add the 'limit' row, to avoid computation (data is not available yet)
- info->m_numConstraintRows = 6; // Fixed 3 linear + 2 angular
- info->nub = 0;
+ info->m_numConstraintRows = 6; // Fixed 3 linear + 2 angular
+ info->nub = 0;
}
}
-void btHingeConstraint::getInfo2 (btConstraintInfo2* info)
+void btHingeConstraint::getInfo2(btConstraintInfo2* info)
{
- if(m_useOffsetForConstraintFrame)
+ if (m_useOffsetForConstraintFrame)
{
- getInfo2InternalUsingFrameOffset(info, m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getAngularVelocity(),m_rbB.getAngularVelocity());
+ getInfo2InternalUsingFrameOffset(info, m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform(), m_rbA.getAngularVelocity(), m_rbB.getAngularVelocity());
}
else
{
- getInfo2Internal(info, m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getAngularVelocity(),m_rbB.getAngularVelocity());
+ getInfo2Internal(info, m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform(), m_rbA.getAngularVelocity(), m_rbB.getAngularVelocity());
}
}
-
-void btHingeConstraint::getInfo2NonVirtual (btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB)
+void btHingeConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& transA, const btTransform& transB, const btVector3& angVelA, const btVector3& angVelB)
{
///the regular (virtual) implementation getInfo2 already performs 'testLimit' during getInfo1, so we need to do it now
- testLimit(transA,transB);
+ testLimit(transA, transB);
- getInfo2Internal(info,transA,transB,angVelA,angVelB);
+ getInfo2Internal(info, transA, transB, angVelA, angVelB);
}
-
-void btHingeConstraint::getInfo2Internal(btConstraintInfo2* info, const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB)
+void btHingeConstraint::getInfo2Internal(btConstraintInfo2* info, const btTransform& transA, const btTransform& transB, const btVector3& angVelA, const btVector3& angVelB)
{
-
btAssert(!m_useSolveConstraintObsolete);
int i, skip = info->rowskip;
// transforms in world space
- btTransform trA = transA*m_rbAFrame;
- btTransform trB = transB*m_rbBFrame;
+ btTransform trA = transA * m_rbAFrame;
+ btTransform trB = transB * m_rbBFrame;
// pivot point
btVector3 pivotAInW = trA.getOrigin();
btVector3 pivotBInW = trB.getOrigin();
@@ -448,7 +423,7 @@ void btHingeConstraint::getInfo2Internal(btConstraintInfo2* info, const btTransf
info->m_constraintError[i*skip]=0.f;
}
}
-#endif //#if 0
+#endif //#if 0
// linear (all fixed)
if (!m_angularOnly)
@@ -460,10 +435,7 @@ void btHingeConstraint::getInfo2Internal(btConstraintInfo2* info, const btTransf
info->m_J2linearAxis[0] = -1;
info->m_J2linearAxis[skip + 1] = -1;
info->m_J2linearAxis[2 * skip + 2] = -1;
- }
-
-
-
+ }
btVector3 a1 = pivotAInW - transA.getOrigin();
{
@@ -471,22 +443,22 @@ void btHingeConstraint::getInfo2Internal(btConstraintInfo2* info, const btTransf
btVector3* angular1 = (btVector3*)(info->m_J1angularAxis + skip);
btVector3* angular2 = (btVector3*)(info->m_J1angularAxis + 2 * skip);
btVector3 a1neg = -a1;
- a1neg.getSkewSymmetricMatrix(angular0,angular1,angular2);
+ a1neg.getSkewSymmetricMatrix(angular0, angular1, angular2);
}
btVector3 a2 = pivotBInW - transB.getOrigin();
{
btVector3* angular0 = (btVector3*)(info->m_J2angularAxis);
btVector3* angular1 = (btVector3*)(info->m_J2angularAxis + skip);
btVector3* angular2 = (btVector3*)(info->m_J2angularAxis + 2 * skip);
- a2.getSkewSymmetricMatrix(angular0,angular1,angular2);
+ a2.getSkewSymmetricMatrix(angular0, angular1, angular2);
}
// linear RHS
btScalar normalErp = (m_flags & BT_HINGE_FLAGS_ERP_NORM) ? m_normalERP : info->erp;
- btScalar k = info->fps * normalErp;
+ btScalar k = info->fps * normalErp;
if (!m_angularOnly)
{
- for(i = 0; i < 3; i++)
+ for (i = 0; i < 3; i++)
{
info->m_constraintError[i * skip] = k * (pivotBInW[i] - pivotAInW[i]);
}
@@ -504,9 +476,9 @@ void btHingeConstraint::getInfo2Internal(btConstraintInfo2* info, const btTransf
// get 2 orthos to hinge axis (X, Y)
btVector3 p = trA.getBasis().getColumn(0);
btVector3 q = trA.getBasis().getColumn(1);
- // set the two hinge angular rows
- int s3 = 3 * info->rowskip;
- int s4 = 4 * info->rowskip;
+ // set the two hinge angular rows
+ int s3 = 3 * info->rowskip;
+ int s4 = 4 * info->rowskip;
info->m_J1angularAxis[s3 + 0] = p[0];
info->m_J1angularAxis[s3 + 1] = p[1];
@@ -521,181 +493,172 @@ void btHingeConstraint::getInfo2Internal(btConstraintInfo2* info, const btTransf
info->m_J2angularAxis[s4 + 0] = -q[0];
info->m_J2angularAxis[s4 + 1] = -q[1];
info->m_J2angularAxis[s4 + 2] = -q[2];
- // 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.
- btVector3 ax2 = trB.getBasis().getColumn(2);
+ // 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.
+ btVector3 ax2 = trB.getBasis().getColumn(2);
btVector3 u = ax1.cross(ax2);
info->m_constraintError[s3] = k * u.dot(p);
info->m_constraintError[s4] = k * u.dot(q);
// check angular limits
- int nrow = 4; // last filled row
+ int nrow = 4; // last filled row
int srow;
btScalar limit_err = btScalar(0.0);
int limit = 0;
- if(getSolveLimit())
+ if (getSolveLimit())
{
-#ifdef _BT_USE_CENTER_LIMIT_
- limit_err = m_limit.getCorrection() * m_referenceSign;
+#ifdef _BT_USE_CENTER_LIMIT_
+ limit_err = m_limit.getCorrection() * m_referenceSign;
#else
- limit_err = m_correction * m_referenceSign;
+ limit_err = m_correction * m_referenceSign;
#endif
- limit = (limit_err > btScalar(0.0)) ? 1 : 2;
-
+ limit = (limit_err > btScalar(0.0)) ? 1 : 2;
}
// if the hinge has joint limits or motor, add in the extra row
bool powered = getEnableAngularMotor();
- if(limit || powered)
+ if (limit || powered)
{
nrow++;
srow = nrow * info->rowskip;
- info->m_J1angularAxis[srow+0] = ax1[0];
- info->m_J1angularAxis[srow+1] = ax1[1];
- info->m_J1angularAxis[srow+2] = ax1[2];
+ info->m_J1angularAxis[srow + 0] = ax1[0];
+ info->m_J1angularAxis[srow + 1] = ax1[1];
+ info->m_J1angularAxis[srow + 2] = ax1[2];
- info->m_J2angularAxis[srow+0] = -ax1[0];
- info->m_J2angularAxis[srow+1] = -ax1[1];
- info->m_J2angularAxis[srow+2] = -ax1[2];
+ info->m_J2angularAxis[srow + 0] = -ax1[0];
+ info->m_J2angularAxis[srow + 1] = -ax1[1];
+ info->m_J2angularAxis[srow + 2] = -ax1[2];
btScalar lostop = getLowerLimit();
btScalar histop = getUpperLimit();
- if(limit && (lostop == histop))
+ if (limit && (lostop == histop))
{ // the joint motor is ineffective
powered = false;
}
info->m_constraintError[srow] = btScalar(0.0f);
btScalar currERP = (m_flags & BT_HINGE_FLAGS_ERP_STOP) ? m_stopERP : normalErp;
- if(powered)
+ if (powered)
{
- if(m_flags & BT_HINGE_FLAGS_CFM_NORM)
+ if (m_flags & BT_HINGE_FLAGS_CFM_NORM)
{
info->cfm[srow] = m_normalCFM;
}
btScalar mot_fact = getMotorFactor(m_hingeAngle, lostop, histop, m_motorTargetVelocity, info->fps * currERP);
info->m_constraintError[srow] += mot_fact * m_motorTargetVelocity * m_referenceSign;
- info->m_lowerLimit[srow] = - m_maxMotorImpulse;
- info->m_upperLimit[srow] = m_maxMotorImpulse;
+ info->m_lowerLimit[srow] = -m_maxMotorImpulse;
+ info->m_upperLimit[srow] = m_maxMotorImpulse;
}
- if(limit)
+ if (limit)
{
k = info->fps * currERP;
info->m_constraintError[srow] += k * limit_err;
- if(m_flags & BT_HINGE_FLAGS_CFM_STOP)
+ if (m_flags & BT_HINGE_FLAGS_CFM_STOP)
{
info->cfm[srow] = m_stopCFM;
}
- if(lostop == histop)
+ if (lostop == histop)
{
// limited low and high simultaneously
info->m_lowerLimit[srow] = -SIMD_INFINITY;
info->m_upperLimit[srow] = SIMD_INFINITY;
}
- else if(limit == 1)
- { // low limit
+ else if (limit == 1)
+ { // low limit
info->m_lowerLimit[srow] = 0;
info->m_upperLimit[srow] = SIMD_INFINITY;
}
- else
- { // high limit
+ else
+ { // high limit
info->m_lowerLimit[srow] = -SIMD_INFINITY;
info->m_upperLimit[srow] = 0;
}
// bounce (we'll use slider parameter abs(1.0 - m_dampingLimAng) for that)
-#ifdef _BT_USE_CENTER_LIMIT_
+#ifdef _BT_USE_CENTER_LIMIT_
btScalar bounce = m_limit.getRelaxationFactor();
#else
btScalar bounce = m_relaxationFactor;
#endif
- if(bounce > btScalar(0.0))
+ if (bounce > btScalar(0.0))
{
btScalar vel = angVelA.dot(ax1);
vel -= angVelB.dot(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)
+ if (limit == 1)
+ { // low limit
+ if (vel < 0)
{
btScalar newc = -bounce * vel;
- if(newc > info->m_constraintError[srow])
+ if (newc > info->m_constraintError[srow])
{
info->m_constraintError[srow] = newc;
}
}
}
else
- { // high limit - all those computations are reversed
- if(vel > 0)
+ { // high limit - all those computations are reversed
+ if (vel > 0)
{
btScalar newc = -bounce * vel;
- if(newc < info->m_constraintError[srow])
+ if (newc < info->m_constraintError[srow])
{
info->m_constraintError[srow] = newc;
}
}
}
}
-#ifdef _BT_USE_CENTER_LIMIT_
+#ifdef _BT_USE_CENTER_LIMIT_
info->m_constraintError[srow] *= m_limit.getBiasFactor();
#else
info->m_constraintError[srow] *= m_biasFactor;
#endif
- } // if(limit)
- } // if angular limit or powered
+ } // if(limit)
+ } // if angular limit or powered
}
-
-void btHingeConstraint::setFrames(const btTransform & frameA, const btTransform & frameB)
+void btHingeConstraint::setFrames(const btTransform& frameA, const btTransform& frameB)
{
m_rbAFrame = frameA;
m_rbBFrame = frameB;
buildJacobian();
}
-
-void btHingeConstraint::updateRHS(btScalar timeStep)
+void btHingeConstraint::updateRHS(btScalar timeStep)
{
(void)timeStep;
-
}
-
-
-
btScalar btHingeConstraint::getHingeAngle()
{
- return getHingeAngle(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
+ return getHingeAngle(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
}
-btScalar btHingeConstraint::getHingeAngle(const btTransform& transA,const btTransform& transB)
+btScalar btHingeConstraint::getHingeAngle(const btTransform& transA, const btTransform& transB)
{
- const btVector3 refAxis0 = transA.getBasis() * m_rbAFrame.getBasis().getColumn(0);
- const btVector3 refAxis1 = transA.getBasis() * m_rbAFrame.getBasis().getColumn(1);
+ const btVector3 refAxis0 = transA.getBasis() * m_rbAFrame.getBasis().getColumn(0);
+ const btVector3 refAxis1 = transA.getBasis() * m_rbAFrame.getBasis().getColumn(1);
const btVector3 swingAxis = transB.getBasis() * m_rbBFrame.getBasis().getColumn(1);
-// btScalar angle = btAtan2Fast(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1));
+ // btScalar angle = btAtan2Fast(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1));
btScalar angle = btAtan2(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1));
return m_referenceSign * angle;
}
-
-
-void btHingeConstraint::testLimit(const btTransform& transA,const btTransform& transB)
+void btHingeConstraint::testLimit(const btTransform& transA, const btTransform& transB)
{
// Compute limit information
- m_hingeAngle = getHingeAngle(transA,transB);
-#ifdef _BT_USE_CENTER_LIMIT_
+ m_hingeAngle = getHingeAngle(transA, transB);
+#ifdef _BT_USE_CENTER_LIMIT_
m_limit.test(m_hingeAngle);
#else
m_correction = btScalar(0.);
@@ -709,7 +672,7 @@ void btHingeConstraint::testLimit(const btTransform& transA,const btTransform& t
m_correction = (m_lowerLimit - m_hingeAngle);
m_limitSign = 1.0f;
m_solveLimit = true;
- }
+ }
else if (m_hingeAngle >= m_upperLimit)
{
m_correction = m_upperLimit - m_hingeAngle;
@@ -721,7 +684,6 @@ void btHingeConstraint::testLimit(const btTransform& transA,const btTransform& t
return;
}
-
static btVector3 vHinge(0, 0, btScalar(1));
void btHingeConstraint::setMotorTarget(const btQuaternion& qAinB, btScalar dt)
@@ -731,14 +693,15 @@ void btHingeConstraint::setMotorTarget(const btQuaternion& qAinB, btScalar dt)
qConstraint.normalize();
// extract "pure" hinge component
- btVector3 vNoHinge = quatRotate(qConstraint, vHinge); vNoHinge.normalize();
+ btVector3 vNoHinge = quatRotate(qConstraint, vHinge);
+ vNoHinge.normalize();
btQuaternion qNoHinge = shortestArcQuat(vHinge, vNoHinge);
btQuaternion qHinge = qNoHinge.inverse() * qConstraint;
qHinge.normalize();
// compute angular target, clamped to limits
btScalar targetAngle = qHinge.getAngle();
- if (targetAngle > SIMD_PI) // long way around. flip quat and recalculate.
+ if (targetAngle > SIMD_PI) // long way around. flip quat and recalculate.
{
qHinge = -(qHinge);
targetAngle = qHinge.getAngle();
@@ -751,7 +714,7 @@ void btHingeConstraint::setMotorTarget(const btQuaternion& qAinB, btScalar dt)
void btHingeConstraint::setMotorTarget(btScalar targetAngle, btScalar dt)
{
-#ifdef _BT_USE_CENTER_LIMIT_
+#ifdef _BT_USE_CENTER_LIMIT_
m_limit.fit(targetAngle);
#else
if (m_lowerLimit < m_upperLimit)
@@ -763,20 +726,18 @@ void btHingeConstraint::setMotorTarget(btScalar targetAngle, btScalar dt)
}
#endif
// compute angular velocity
- btScalar curAngle = getHingeAngle(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
+ btScalar curAngle = getHingeAngle(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
btScalar dAngle = targetAngle - curAngle;
m_motorTargetVelocity = dAngle / dt;
}
-
-
-void btHingeConstraint::getInfo2InternalUsingFrameOffset(btConstraintInfo2* info, const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB)
+void btHingeConstraint::getInfo2InternalUsingFrameOffset(btConstraintInfo2* info, const btTransform& transA, const btTransform& transB, const btVector3& angVelA, const btVector3& angVelB)
{
btAssert(!m_useSolveConstraintObsolete);
int i, s = info->rowskip;
// transforms in world space
- btTransform trA = transA*m_rbAFrame;
- btTransform trB = transB*m_rbBFrame;
+ btTransform trA = transA * m_rbAFrame;
+ btTransform trB = transB * m_rbBFrame;
// pivot point
// btVector3 pivotAInW = trA.getOrigin();
// btVector3 pivotBInW = trB.getOrigin();
@@ -789,11 +750,11 @@ void btHingeConstraint::getInfo2InternalUsingFrameOffset(btConstraintInfo2* info
bool hasStaticBody = (miA < SIMD_EPSILON) || (miB < SIMD_EPSILON);
btScalar miS = miA + miB;
btScalar factA, factB;
- if(miS > btScalar(0.f))
+ if (miS > btScalar(0.f))
{
factA = miB / miS;
}
- else
+ else
{
factA = btScalar(0.5f);
}
@@ -803,15 +764,21 @@ void btHingeConstraint::getInfo2InternalUsingFrameOffset(btConstraintInfo2* info
btVector3 ax1A = trA.getBasis().getColumn(2);
btVector3 ax1B = trB.getBasis().getColumn(2);
btVector3 ax1 = ax1A * factA + ax1B * factB;
+ if (ax1.length2()<SIMD_EPSILON)
+ {
+ factA=0.f;
+ factB=1.f;
+ ax1 = ax1A * factA + ax1B * factB;
+ }
ax1.normalize();
- // fill first 3 rows
+ // fill first 3 rows
// we want: velA + wA x relA == velB + wB x relB
btTransform bodyA_trans = transA;
btTransform bodyB_trans = transB;
int s0 = 0;
int s1 = s;
int s2 = s * 2;
- int nrow = 2; // last filled row
+ int nrow = 2; // last filled row
btVector3 tmpA, tmpB, relA, relB, p, q;
// get vector from bodyB to frameB in WCS
relB = trB.getOrigin() - bodyB_trans.getOrigin();
@@ -830,7 +797,7 @@ void btHingeConstraint::getInfo2InternalUsingFrameOffset(btConstraintInfo2* info
// now choose average ortho to hinge axis
p = orthoB * factA + orthoA * factB;
btScalar len2 = p.length2();
- if(len2 > SIMD_EPSILON)
+ if (len2 > SIMD_EPSILON)
{
p /= btSqrt(len2);
}
@@ -843,44 +810,44 @@ void btHingeConstraint::getInfo2InternalUsingFrameOffset(btConstraintInfo2* info
// fill three rows
tmpA = relA.cross(p);
tmpB = relB.cross(p);
- for (i=0; i<3; i++) info->m_J1angularAxis[s0+i] = tmpA[i];
- for (i=0; i<3; i++) info->m_J2angularAxis[s0+i] = -tmpB[i];
+ for (i = 0; i < 3; i++) info->m_J1angularAxis[s0 + i] = tmpA[i];
+ for (i = 0; i < 3; i++) info->m_J2angularAxis[s0 + i] = -tmpB[i];
tmpA = relA.cross(q);
tmpB = relB.cross(q);
- if(hasStaticBody && getSolveLimit())
- { // to make constraint between static and dynamic objects more rigid
+ if (hasStaticBody && getSolveLimit())
+ { // to make constraint between static and dynamic objects more rigid
// remove wA (or wB) from equation if angular limit is hit
tmpB *= factB;
tmpA *= factA;
}
- for (i=0; i<3; i++) info->m_J1angularAxis[s1+i] = tmpA[i];
- for (i=0; i<3; i++) info->m_J2angularAxis[s1+i] = -tmpB[i];
+ for (i = 0; i < 3; i++) info->m_J1angularAxis[s1 + i] = tmpA[i];
+ for (i = 0; i < 3; i++) info->m_J2angularAxis[s1 + i] = -tmpB[i];
tmpA = relA.cross(ax1);
tmpB = relB.cross(ax1);
- if(hasStaticBody)
- { // to make constraint between static and dynamic objects more rigid
+ if (hasStaticBody)
+ { // to make constraint between static and dynamic objects more rigid
// remove wA (or wB) from equation
tmpB *= factB;
tmpA *= factA;
}
- for (i=0; i<3; i++) info->m_J1angularAxis[s2+i] = tmpA[i];
- for (i=0; i<3; i++) info->m_J2angularAxis[s2+i] = -tmpB[i];
+ for (i = 0; i < 3; i++) info->m_J1angularAxis[s2 + i] = tmpA[i];
+ for (i = 0; i < 3; i++) info->m_J2angularAxis[s2 + i] = -tmpB[i];
- btScalar normalErp = (m_flags & BT_HINGE_FLAGS_ERP_NORM)? m_normalERP : info->erp;
+ btScalar normalErp = (m_flags & BT_HINGE_FLAGS_ERP_NORM) ? m_normalERP : info->erp;
btScalar k = info->fps * normalErp;
if (!m_angularOnly)
{
- for (i=0; i<3; i++) info->m_J1linearAxis[s0+i] = p[i];
- for (i=0; i<3; i++) info->m_J1linearAxis[s1+i] = q[i];
- for (i=0; i<3; i++) info->m_J1linearAxis[s2+i] = ax1[i];
+ for (i = 0; i < 3; i++) info->m_J1linearAxis[s0 + i] = p[i];
+ for (i = 0; i < 3; i++) info->m_J1linearAxis[s1 + i] = q[i];
+ for (i = 0; i < 3; i++) info->m_J1linearAxis[s2 + i] = ax1[i];
+
+ for (i = 0; i < 3; i++) info->m_J2linearAxis[s0 + i] = -p[i];
+ for (i = 0; i < 3; i++) info->m_J2linearAxis[s1 + i] = -q[i];
+ for (i = 0; i < 3; i++) info->m_J2linearAxis[s2 + i] = -ax1[i];
- for (i=0; i<3; i++) info->m_J2linearAxis[s0+i] = -p[i];
- for (i=0; i<3; i++) info->m_J2linearAxis[s1+i] = -q[i];
- for (i=0; i<3; i++) info->m_J2linearAxis[s2+i] = -ax1[i];
+ // compute three elements of right hand side
- // compute three elements of right hand side
-
btScalar rhs = k * p.dot(ofs);
info->m_constraintError[s0] = rhs;
rhs = k * q.dot(ofs);
@@ -925,146 +892,144 @@ void btHingeConstraint::getInfo2InternalUsingFrameOffset(btConstraintInfo2* info
// 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.
- k = info->fps * normalErp;//??
+ k = info->fps * normalErp; //??
btVector3 u = ax1A.cross(ax1B);
info->m_constraintError[s3] = k * u.dot(p);
info->m_constraintError[s4] = k * u.dot(q);
#endif
// check angular limits
- nrow = 4; // last filled row
+ nrow = 4; // last filled row
int srow;
btScalar limit_err = btScalar(0.0);
int limit = 0;
- if(getSolveLimit())
+ if (getSolveLimit())
{
-#ifdef _BT_USE_CENTER_LIMIT_
- limit_err = m_limit.getCorrection() * m_referenceSign;
+#ifdef _BT_USE_CENTER_LIMIT_
+ limit_err = m_limit.getCorrection() * m_referenceSign;
#else
- limit_err = m_correction * m_referenceSign;
+ limit_err = m_correction * m_referenceSign;
#endif
- limit = (limit_err > btScalar(0.0)) ? 1 : 2;
-
+ limit = (limit_err > btScalar(0.0)) ? 1 : 2;
}
// if the hinge has joint limits or motor, add in the extra row
bool powered = getEnableAngularMotor();
- if(limit || powered)
+ if (limit || powered)
{
nrow++;
srow = nrow * info->rowskip;
- info->m_J1angularAxis[srow+0] = ax1[0];
- info->m_J1angularAxis[srow+1] = ax1[1];
- info->m_J1angularAxis[srow+2] = ax1[2];
+ info->m_J1angularAxis[srow + 0] = ax1[0];
+ info->m_J1angularAxis[srow + 1] = ax1[1];
+ info->m_J1angularAxis[srow + 2] = ax1[2];
- info->m_J2angularAxis[srow+0] = -ax1[0];
- info->m_J2angularAxis[srow+1] = -ax1[1];
- info->m_J2angularAxis[srow+2] = -ax1[2];
+ info->m_J2angularAxis[srow + 0] = -ax1[0];
+ info->m_J2angularAxis[srow + 1] = -ax1[1];
+ info->m_J2angularAxis[srow + 2] = -ax1[2];
btScalar lostop = getLowerLimit();
btScalar histop = getUpperLimit();
- if(limit && (lostop == histop))
+ if (limit && (lostop == histop))
{ // the joint motor is ineffective
powered = false;
}
info->m_constraintError[srow] = btScalar(0.0f);
btScalar currERP = (m_flags & BT_HINGE_FLAGS_ERP_STOP) ? m_stopERP : normalErp;
- if(powered)
+ if (powered)
{
- if(m_flags & BT_HINGE_FLAGS_CFM_NORM)
+ if (m_flags & BT_HINGE_FLAGS_CFM_NORM)
{
info->cfm[srow] = m_normalCFM;
}
btScalar mot_fact = getMotorFactor(m_hingeAngle, lostop, histop, m_motorTargetVelocity, info->fps * currERP);
info->m_constraintError[srow] += mot_fact * m_motorTargetVelocity * m_referenceSign;
- info->m_lowerLimit[srow] = - m_maxMotorImpulse;
- info->m_upperLimit[srow] = m_maxMotorImpulse;
+ info->m_lowerLimit[srow] = -m_maxMotorImpulse;
+ info->m_upperLimit[srow] = m_maxMotorImpulse;
}
- if(limit)
+ if (limit)
{
k = info->fps * currERP;
info->m_constraintError[srow] += k * limit_err;
- if(m_flags & BT_HINGE_FLAGS_CFM_STOP)
+ if (m_flags & BT_HINGE_FLAGS_CFM_STOP)
{
info->cfm[srow] = m_stopCFM;
}
- if(lostop == histop)
+ if (lostop == histop)
{
// limited low and high simultaneously
info->m_lowerLimit[srow] = -SIMD_INFINITY;
info->m_upperLimit[srow] = SIMD_INFINITY;
}
- else if(limit == 1)
- { // low limit
+ else if (limit == 1)
+ { // low limit
info->m_lowerLimit[srow] = 0;
info->m_upperLimit[srow] = SIMD_INFINITY;
}
- else
- { // high limit
+ else
+ { // high limit
info->m_lowerLimit[srow] = -SIMD_INFINITY;
info->m_upperLimit[srow] = 0;
}
// bounce (we'll use slider parameter abs(1.0 - m_dampingLimAng) for that)
-#ifdef _BT_USE_CENTER_LIMIT_
+#ifdef _BT_USE_CENTER_LIMIT_
btScalar bounce = m_limit.getRelaxationFactor();
#else
btScalar bounce = m_relaxationFactor;
#endif
- if(bounce > btScalar(0.0))
+ if (bounce > btScalar(0.0))
{
btScalar vel = angVelA.dot(ax1);
vel -= angVelB.dot(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)
+ if (limit == 1)
+ { // low limit
+ if (vel < 0)
{
btScalar newc = -bounce * vel;
- if(newc > info->m_constraintError[srow])
+ if (newc > info->m_constraintError[srow])
{
info->m_constraintError[srow] = newc;
}
}
}
else
- { // high limit - all those computations are reversed
- if(vel > 0)
+ { // high limit - all those computations are reversed
+ if (vel > 0)
{
btScalar newc = -bounce * vel;
- if(newc < info->m_constraintError[srow])
+ if (newc < info->m_constraintError[srow])
{
info->m_constraintError[srow] = newc;
}
}
}
}
-#ifdef _BT_USE_CENTER_LIMIT_
+#ifdef _BT_USE_CENTER_LIMIT_
info->m_constraintError[srow] *= m_limit.getBiasFactor();
#else
info->m_constraintError[srow] *= m_biasFactor;
#endif
- } // if(limit)
- } // if angular limit or powered
+ } // if(limit)
+ } // if angular limit or powered
}
-
-///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
///If no axis is provided, it uses the default axis for this constraint.
void btHingeConstraint::setParam(int num, btScalar value, int axis)
{
- if((axis == -1) || (axis == 5))
+ if ((axis == -1) || (axis == 5))
{
- switch(num)
- {
- case BT_CONSTRAINT_STOP_ERP :
+ switch (num)
+ {
+ case BT_CONSTRAINT_STOP_ERP:
m_stopERP = value;
m_flags |= BT_HINGE_FLAGS_ERP_STOP;
break;
- case BT_CONSTRAINT_STOP_CFM :
+ case BT_CONSTRAINT_STOP_CFM:
m_stopCFM = value;
m_flags |= BT_HINGE_FLAGS_CFM_STOP;
break;
- case BT_CONSTRAINT_CFM :
+ case BT_CONSTRAINT_CFM:
m_normalCFM = value;
m_flags |= BT_HINGE_FLAGS_CFM_NORM;
break;
@@ -1072,7 +1037,7 @@ void btHingeConstraint::setParam(int num, btScalar value, int axis)
m_normalERP = value;
m_flags |= BT_HINGE_FLAGS_ERP_NORM;
break;
- default :
+ default:
btAssertConstrParams(0);
}
}
@@ -1083,22 +1048,22 @@ void btHingeConstraint::setParam(int num, btScalar value, int axis)
}
///return the local value of parameter
-btScalar btHingeConstraint::getParam(int num, int axis) const
+btScalar btHingeConstraint::getParam(int num, int axis) const
{
btScalar retVal = 0;
- if((axis == -1) || (axis == 5))
+ if ((axis == -1) || (axis == 5))
{
- switch(num)
- {
- case BT_CONSTRAINT_STOP_ERP :
+ switch (num)
+ {
+ case BT_CONSTRAINT_STOP_ERP:
btAssertConstrParams(m_flags & BT_HINGE_FLAGS_ERP_STOP);
retVal = m_stopERP;
break;
- case BT_CONSTRAINT_STOP_CFM :
+ case BT_CONSTRAINT_STOP_CFM:
btAssertConstrParams(m_flags & BT_HINGE_FLAGS_CFM_STOP);
retVal = m_stopCFM;
break;
- case BT_CONSTRAINT_CFM :
+ case BT_CONSTRAINT_CFM:
btAssertConstrParams(m_flags & BT_HINGE_FLAGS_CFM_NORM);
retVal = m_normalCFM;
break;
@@ -1106,7 +1071,7 @@ btScalar btHingeConstraint::getParam(int num, int axis) const
btAssertConstrParams(m_flags & BT_HINGE_FLAGS_ERP_NORM);
retVal = m_normalERP;
break;
- default :
+ default:
btAssertConstrParams(0);
}
}
@@ -1116,5 +1081,3 @@ btScalar btHingeConstraint::getParam(int num, int axis) const
}
return retVal;
}
-
-
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHingeConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHingeConstraint.h
index 3c3df24dba..c7509e30af 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHingeConstraint.h
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHingeConstraint.h
@@ -20,7 +20,6 @@ subject to the following restrictions:
#define _BT_USE_CENTER_LIMIT_ 1
-
#include "LinearMath/btVector3.h"
#include "btJacobianEntry.h"
#include "btTypedConstraint.h"
@@ -28,14 +27,12 @@ subject to the following restrictions:
class btRigidBody;
#ifdef BT_USE_DOUBLE_PRECISION
-#define btHingeConstraintData btHingeConstraintDoubleData2 //rename to 2 for backwards compatibility, so we can still load the 'btHingeConstraintDoubleData' version
-#define btHingeConstraintDataName "btHingeConstraintDoubleData2"
+#define btHingeConstraintData btHingeConstraintDoubleData2 //rename to 2 for backwards compatibility, so we can still load the 'btHingeConstraintDoubleData' version
+#define btHingeConstraintDataName "btHingeConstraintDoubleData2"
#else
-#define btHingeConstraintData btHingeConstraintFloatData
-#define btHingeConstraintDataName "btHingeConstraintFloatData"
-#endif //BT_USE_DOUBLE_PRECISION
-
-
+#define btHingeConstraintData btHingeConstraintFloatData
+#define btHingeConstraintDataName "btHingeConstraintFloatData"
+#endif //BT_USE_DOUBLE_PRECISION
enum btHingeFlags
{
@@ -45,89 +42,83 @@ enum btHingeFlags
BT_HINGE_FLAGS_ERP_NORM = 8
};
-
/// hinge constraint between two rigidbodies each with a pivotpoint that descibes the axis location in local space
/// axis defines the orientation of the hinge axis
-ATTRIBUTE_ALIGNED16(class) btHingeConstraint : public btTypedConstraint
+ATTRIBUTE_ALIGNED16(class)
+btHingeConstraint : public btTypedConstraint
{
#ifdef IN_PARALLELL_SOLVER
public:
#endif
- btJacobianEntry m_jac[3]; //3 orthogonal linear constraints
- btJacobianEntry m_jacAng[3]; //2 orthogonal angular constraints+ 1 for limit/motor
+ btJacobianEntry m_jac[3]; //3 orthogonal linear constraints
+ btJacobianEntry m_jacAng[3]; //2 orthogonal angular constraints+ 1 for limit/motor
- btTransform m_rbAFrame; // constraint axii. Assumes z is hinge axis.
+ btTransform m_rbAFrame; // constraint axii. Assumes z is hinge axis.
btTransform m_rbBFrame;
- btScalar m_motorTargetVelocity;
- btScalar m_maxMotorImpulse;
-
+ btScalar m_motorTargetVelocity;
+ btScalar m_maxMotorImpulse;
-#ifdef _BT_USE_CENTER_LIMIT_
- btAngularLimit m_limit;
+#ifdef _BT_USE_CENTER_LIMIT_
+ btAngularLimit m_limit;
#else
- btScalar m_lowerLimit;
- btScalar m_upperLimit;
- btScalar m_limitSign;
- btScalar m_correction;
+ btScalar m_lowerLimit;
+ btScalar m_upperLimit;
+ btScalar m_limitSign;
+ btScalar m_correction;
- btScalar m_limitSoftness;
- btScalar m_biasFactor;
- btScalar m_relaxationFactor;
+ btScalar m_limitSoftness;
+ btScalar m_biasFactor;
+ btScalar m_relaxationFactor;
- bool m_solveLimit;
+ bool m_solveLimit;
#endif
- btScalar m_kHinge;
-
+ btScalar m_kHinge;
- btScalar m_accLimitImpulse;
- btScalar m_hingeAngle;
- btScalar m_referenceSign;
+ btScalar m_accLimitImpulse;
+ btScalar m_hingeAngle;
+ btScalar m_referenceSign;
- bool m_angularOnly;
- bool m_enableAngularMotor;
- bool m_useSolveConstraintObsolete;
- bool m_useOffsetForConstraintFrame;
- bool m_useReferenceFrameA;
+ bool m_angularOnly;
+ bool m_enableAngularMotor;
+ bool m_useSolveConstraintObsolete;
+ bool m_useOffsetForConstraintFrame;
+ bool m_useReferenceFrameA;
- btScalar m_accMotorImpulse;
+ btScalar m_accMotorImpulse;
- int m_flags;
- btScalar m_normalCFM;
- btScalar m_normalERP;
- btScalar m_stopCFM;
- btScalar m_stopERP;
+ int m_flags;
+ btScalar m_normalCFM;
+ btScalar m_normalERP;
+ btScalar m_stopCFM;
+ btScalar m_stopERP;
-
public:
-
BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB, const btVector3& axisInA,const btVector3& axisInB, bool useReferenceFrameA = false);
- btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,const btVector3& axisInA, bool useReferenceFrameA = false);
-
- btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA = false);
+ btHingeConstraint(btRigidBody & rbA, btRigidBody & rbB, const btVector3& pivotInA, const btVector3& pivotInB, const btVector3& axisInA, const btVector3& axisInB, bool useReferenceFrameA = false);
+
+ btHingeConstraint(btRigidBody & rbA, const btVector3& pivotInA, const btVector3& axisInA, bool useReferenceFrameA = false);
- btHingeConstraint(btRigidBody& rbA,const btTransform& rbAFrame, bool useReferenceFrameA = false);
+ btHingeConstraint(btRigidBody & rbA, btRigidBody & rbB, const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA = false);
+ btHingeConstraint(btRigidBody & rbA, const btTransform& rbAFrame, bool useReferenceFrameA = false);
- virtual void buildJacobian();
+ virtual void buildJacobian();
- virtual void getInfo1 (btConstraintInfo1* info);
+ virtual void getInfo1(btConstraintInfo1 * info);
- void getInfo1NonVirtual(btConstraintInfo1* info);
+ void getInfo1NonVirtual(btConstraintInfo1 * info);
- virtual void getInfo2 (btConstraintInfo2* info);
+ virtual void getInfo2(btConstraintInfo2 * info);
- void getInfo2NonVirtual(btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB);
+ void getInfo2NonVirtual(btConstraintInfo2 * info, const btTransform& transA, const btTransform& transB, const btVector3& angVelA, const btVector3& angVelB);
- void getInfo2Internal(btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB);
- void getInfo2InternalUsingFrameOffset(btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB);
-
+ void getInfo2Internal(btConstraintInfo2 * info, const btTransform& transA, const btTransform& transB, const btVector3& angVelA, const btVector3& angVelB);
+ void getInfo2InternalUsingFrameOffset(btConstraintInfo2 * info, const btTransform& transA, const btTransform& transB, const btVector3& angVelA, const btVector3& angVelB);
- void updateRHS(btScalar timeStep);
+ void updateRHS(btScalar timeStep);
const btRigidBody& getRigidBodyA() const
{
@@ -138,19 +129,19 @@ public:
return m_rbB;
}
- btRigidBody& getRigidBodyA()
- {
- return m_rbA;
- }
+ btRigidBody& getRigidBodyA()
+ {
+ return m_rbA;
+ }
- btRigidBody& getRigidBodyB()
- {
- return m_rbB;
+ btRigidBody& getRigidBodyB()
+ {
+ return m_rbB;
}
btTransform& getFrameOffsetA()
{
- return m_rbAFrame;
+ return m_rbAFrame;
}
btTransform& getFrameOffsetB()
@@ -159,15 +150,15 @@ public:
}
void setFrames(const btTransform& frameA, const btTransform& frameB);
-
- void setAngularOnly(bool angularOnly)
+
+ void setAngularOnly(bool angularOnly)
{
m_angularOnly = angularOnly;
}
- void enableAngularMotor(bool enableMotor,btScalar targetVelocity,btScalar maxMotorImpulse)
+ void enableAngularMotor(bool enableMotor, btScalar targetVelocity, btScalar maxMotorImpulse)
{
- m_enableAngularMotor = enableMotor;
+ m_enableAngularMotor = enableMotor;
m_motorTargetVelocity = targetVelocity;
m_maxMotorImpulse = maxMotorImpulse;
}
@@ -175,29 +166,28 @@ public:
// extra motor API, including ability to set a target rotation (as opposed to angular velocity)
// note: setMotorTarget sets angular velocity under the hood, so you must call it every tick to
// maintain a given angular target.
- void enableMotor(bool enableMotor) { m_enableAngularMotor = enableMotor; }
+ void enableMotor(bool enableMotor) { m_enableAngularMotor = enableMotor; }
void setMaxMotorImpulse(btScalar maxMotorImpulse) { m_maxMotorImpulse = maxMotorImpulse; }
void setMotorTargetVelocity(btScalar motorTargetVelocity) { m_motorTargetVelocity = motorTargetVelocity; }
- void setMotorTarget(const btQuaternion& qAinB, btScalar dt); // qAinB is rotation of body A wrt body B.
+ void setMotorTarget(const btQuaternion& qAinB, btScalar dt); // qAinB is rotation of body A wrt body B.
void setMotorTarget(btScalar targetAngle, btScalar dt);
-
- void setLimit(btScalar low,btScalar high,btScalar _softness = 0.9f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f)
+ void setLimit(btScalar low, btScalar high, btScalar _softness = 0.9f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f)
{
-#ifdef _BT_USE_CENTER_LIMIT_
+#ifdef _BT_USE_CENTER_LIMIT_
m_limit.set(low, high, _softness, _biasFactor, _relaxationFactor);
#else
m_lowerLimit = btNormalizeAngle(low);
m_upperLimit = btNormalizeAngle(high);
- m_limitSoftness = _softness;
+ m_limitSoftness = _softness;
m_biasFactor = _biasFactor;
m_relaxationFactor = _relaxationFactor;
#endif
}
-
+
btScalar getLimitSoftness() const
{
-#ifdef _BT_USE_CENTER_LIMIT_
+#ifdef _BT_USE_CENTER_LIMIT_
return m_limit.getSoftness();
#else
return m_limitSoftness;
@@ -206,7 +196,7 @@ public:
btScalar getLimitBiasFactor() const
{
-#ifdef _BT_USE_CENTER_LIMIT_
+#ifdef _BT_USE_CENTER_LIMIT_
return m_limit.getBiasFactor();
#else
return m_biasFactor;
@@ -215,112 +205,110 @@ public:
btScalar getLimitRelaxationFactor() const
{
-#ifdef _BT_USE_CENTER_LIMIT_
+#ifdef _BT_USE_CENTER_LIMIT_
return m_limit.getRelaxationFactor();
#else
return m_relaxationFactor;
#endif
}
- void setAxis(btVector3& axisInA)
+ void setAxis(btVector3 & axisInA)
{
btVector3 rbAxisA1, rbAxisA2;
btPlaneSpace1(axisInA, rbAxisA1, rbAxisA2);
btVector3 pivotInA = m_rbAFrame.getOrigin();
-// m_rbAFrame.getOrigin() = pivotInA;
- m_rbAFrame.getBasis().setValue( rbAxisA1.getX(),rbAxisA2.getX(),axisInA.getX(),
- rbAxisA1.getY(),rbAxisA2.getY(),axisInA.getY(),
- rbAxisA1.getZ(),rbAxisA2.getZ(),axisInA.getZ() );
+ // m_rbAFrame.getOrigin() = pivotInA;
+ m_rbAFrame.getBasis().setValue(rbAxisA1.getX(), rbAxisA2.getX(), axisInA.getX(),
+ rbAxisA1.getY(), rbAxisA2.getY(), axisInA.getY(),
+ rbAxisA1.getZ(), rbAxisA2.getZ(), axisInA.getZ());
btVector3 axisInB = m_rbA.getCenterOfMassTransform().getBasis() * axisInA;
- btQuaternion rotationArc = shortestArcQuat(axisInA,axisInB);
- btVector3 rbAxisB1 = quatRotate(rotationArc,rbAxisA1);
+ btQuaternion rotationArc = shortestArcQuat(axisInA, axisInB);
+ btVector3 rbAxisB1 = quatRotate(rotationArc, rbAxisA1);
btVector3 rbAxisB2 = axisInB.cross(rbAxisB1);
m_rbBFrame.getOrigin() = m_rbB.getCenterOfMassTransform().inverse()(m_rbA.getCenterOfMassTransform()(pivotInA));
- m_rbBFrame.getBasis().setValue( rbAxisB1.getX(),rbAxisB2.getX(),axisInB.getX(),
- rbAxisB1.getY(),rbAxisB2.getY(),axisInB.getY(),
- rbAxisB1.getZ(),rbAxisB2.getZ(),axisInB.getZ() );
+ m_rbBFrame.getBasis().setValue(rbAxisB1.getX(), rbAxisB2.getX(), axisInB.getX(),
+ rbAxisB1.getY(), rbAxisB2.getY(), axisInB.getY(),
+ rbAxisB1.getZ(), rbAxisB2.getZ(), axisInB.getZ());
m_rbBFrame.getBasis() = m_rbB.getCenterOfMassTransform().getBasis().inverse() * m_rbBFrame.getBasis();
-
}
- bool hasLimit() const {
-#ifdef _BT_USE_CENTER_LIMIT_
- return m_limit.getHalfRange() > 0;
+ bool hasLimit() const
+ {
+#ifdef _BT_USE_CENTER_LIMIT_
+ return m_limit.getHalfRange() > 0;
#else
- return m_lowerLimit <= m_upperLimit;
+ return m_lowerLimit <= m_upperLimit;
#endif
- }
+ }
- btScalar getLowerLimit() const
+ btScalar getLowerLimit() const
{
-#ifdef _BT_USE_CENTER_LIMIT_
- return m_limit.getLow();
+#ifdef _BT_USE_CENTER_LIMIT_
+ return m_limit.getLow();
#else
- return m_lowerLimit;
+ return m_lowerLimit;
#endif
}
- btScalar getUpperLimit() const
+ btScalar getUpperLimit() const
{
-#ifdef _BT_USE_CENTER_LIMIT_
- return m_limit.getHigh();
-#else
- return m_upperLimit;
+#ifdef _BT_USE_CENTER_LIMIT_
+ return m_limit.getHigh();
+#else
+ return m_upperLimit;
#endif
}
-
///The getHingeAngle gives the hinge angle in range [-PI,PI]
btScalar getHingeAngle();
- btScalar getHingeAngle(const btTransform& transA,const btTransform& transB);
-
- void testLimit(const btTransform& transA,const btTransform& transB);
+ btScalar getHingeAngle(const btTransform& transA, const btTransform& transB);
+ void testLimit(const btTransform& transA, const btTransform& transB);
- const btTransform& getAFrame() const { return m_rbAFrame; };
+ const btTransform& getAFrame() const { return m_rbAFrame; };
const btTransform& getBFrame() const { return m_rbBFrame; };
- btTransform& getAFrame() { return m_rbAFrame; };
+ btTransform& getAFrame() { return m_rbAFrame; };
btTransform& getBFrame() { return m_rbBFrame; };
inline int getSolveLimit()
{
-#ifdef _BT_USE_CENTER_LIMIT_
- return m_limit.isLimit();
+#ifdef _BT_USE_CENTER_LIMIT_
+ return m_limit.isLimit();
#else
- return m_solveLimit;
+ return m_solveLimit;
#endif
}
inline btScalar getLimitSign()
{
-#ifdef _BT_USE_CENTER_LIMIT_
- return m_limit.getSign();
+#ifdef _BT_USE_CENTER_LIMIT_
+ return m_limit.getSign();
#else
return m_limitSign;
#endif
}
- inline bool getAngularOnly()
- {
- return m_angularOnly;
+ inline bool getAngularOnly()
+ {
+ return m_angularOnly;
}
- inline bool getEnableAngularMotor()
- {
- return m_enableAngularMotor;
+ inline bool getEnableAngularMotor()
+ {
+ return m_enableAngularMotor;
}
- inline btScalar getMotorTargetVelocity()
- {
- return m_motorTargetVelocity;
+ inline btScalar getMotorTargetVelocity()
+ {
+ return m_motorTargetVelocity;
}
- inline btScalar getMaxMotorImpulse()
- {
- return m_maxMotorImpulse;
+ inline btScalar getMaxMotorImpulse()
+ {
+ return m_maxMotorImpulse;
}
// access for UseFrameOffset
bool getUseFrameOffset() { return m_useOffsetForConstraintFrame; }
@@ -329,143 +317,132 @@ public:
bool getUseReferenceFrameA() const { return m_useReferenceFrameA; }
void setUseReferenceFrameA(bool useReferenceFrameA) { m_useReferenceFrameA = useReferenceFrameA; }
- ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+ ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
///If no axis is provided, it uses the default axis for this constraint.
- virtual void setParam(int num, btScalar value, int axis = -1);
+ virtual void setParam(int num, btScalar value, int axis = -1);
///return the local value of parameter
- virtual btScalar getParam(int num, int axis = -1) const;
-
- virtual int getFlags() const
+ virtual btScalar getParam(int num, int axis = -1) const;
+
+ virtual int getFlags() const
{
- return m_flags;
+ return m_flags;
}
- virtual int calculateSerializeBufferSize() const;
+ virtual int calculateSerializeBufferSize() const;
///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-
-
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
};
-
//only for backward compatibility
#ifdef BT_BACKWARDS_COMPATIBLE_SERIALIZATION
///this structure is not used, except for loading pre-2.82 .bullet files
-struct btHingeConstraintDoubleData
+struct btHingeConstraintDoubleData
{
- btTypedConstraintData m_typeConstraintData;
- btTransformDoubleData m_rbAFrame; // constraint axii. Assumes z is hinge axis.
+ btTypedConstraintData m_typeConstraintData;
+ btTransformDoubleData m_rbAFrame; // constraint axii. Assumes z is hinge axis.
btTransformDoubleData m_rbBFrame;
- int m_useReferenceFrameA;
- int m_angularOnly;
- int m_enableAngularMotor;
- float m_motorTargetVelocity;
- float m_maxMotorImpulse;
-
- float m_lowerLimit;
- float m_upperLimit;
- float m_limitSoftness;
- float m_biasFactor;
- float m_relaxationFactor;
-
+ int m_useReferenceFrameA;
+ int m_angularOnly;
+ int m_enableAngularMotor;
+ float m_motorTargetVelocity;
+ float m_maxMotorImpulse;
+
+ float m_lowerLimit;
+ float m_upperLimit;
+ float m_limitSoftness;
+ float m_biasFactor;
+ float m_relaxationFactor;
};
-#endif //BT_BACKWARDS_COMPATIBLE_SERIALIZATION
+#endif //BT_BACKWARDS_COMPATIBLE_SERIALIZATION
///The getAccumulatedHingeAngle returns the accumulated hinge angle, taking rotation across the -PI/PI boundary into account
-ATTRIBUTE_ALIGNED16(class) btHingeAccumulatedAngleConstraint : public btHingeConstraint
+ATTRIBUTE_ALIGNED16(class)
+btHingeAccumulatedAngleConstraint : public btHingeConstraint
{
protected:
- btScalar m_accumulatedAngle;
-public:
+ btScalar m_accumulatedAngle;
+public:
BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btHingeAccumulatedAngleConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB, const btVector3& axisInA,const btVector3& axisInB, bool useReferenceFrameA = false)
- :btHingeConstraint(rbA,rbB,pivotInA,pivotInB, axisInA,axisInB, useReferenceFrameA )
+
+ btHingeAccumulatedAngleConstraint(btRigidBody & rbA, btRigidBody & rbB, const btVector3& pivotInA, const btVector3& pivotInB, const btVector3& axisInA, const btVector3& axisInB, bool useReferenceFrameA = false)
+ : btHingeConstraint(rbA, rbB, pivotInA, pivotInB, axisInA, axisInB, useReferenceFrameA)
{
- m_accumulatedAngle=getHingeAngle();
+ m_accumulatedAngle = getHingeAngle();
}
- btHingeAccumulatedAngleConstraint(btRigidBody& rbA,const btVector3& pivotInA,const btVector3& axisInA, bool useReferenceFrameA = false)
- :btHingeConstraint(rbA,pivotInA,axisInA, useReferenceFrameA)
+ btHingeAccumulatedAngleConstraint(btRigidBody & rbA, const btVector3& pivotInA, const btVector3& axisInA, bool useReferenceFrameA = false)
+ : btHingeConstraint(rbA, pivotInA, axisInA, useReferenceFrameA)
{
- m_accumulatedAngle=getHingeAngle();
+ m_accumulatedAngle = getHingeAngle();
}
-
- btHingeAccumulatedAngleConstraint(btRigidBody& rbA,btRigidBody& rbB, const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA = false)
- :btHingeConstraint(rbA,rbB, rbAFrame, rbBFrame, useReferenceFrameA )
+
+ btHingeAccumulatedAngleConstraint(btRigidBody & rbA, btRigidBody & rbB, const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA = false)
+ : btHingeConstraint(rbA, rbB, rbAFrame, rbBFrame, useReferenceFrameA)
{
- m_accumulatedAngle=getHingeAngle();
+ m_accumulatedAngle = getHingeAngle();
}
- btHingeAccumulatedAngleConstraint(btRigidBody& rbA,const btTransform& rbAFrame, bool useReferenceFrameA = false)
- :btHingeConstraint(rbA,rbAFrame, useReferenceFrameA )
+ btHingeAccumulatedAngleConstraint(btRigidBody & rbA, const btTransform& rbAFrame, bool useReferenceFrameA = false)
+ : btHingeConstraint(rbA, rbAFrame, useReferenceFrameA)
{
- m_accumulatedAngle=getHingeAngle();
+ m_accumulatedAngle = getHingeAngle();
}
btScalar getAccumulatedHingeAngle();
- void setAccumulatedHingeAngle(btScalar accAngle);
- virtual void getInfo1 (btConstraintInfo1* info);
-
+ void setAccumulatedHingeAngle(btScalar accAngle);
+ virtual void getInfo1(btConstraintInfo1 * info);
};
-struct btHingeConstraintFloatData
+struct btHingeConstraintFloatData
{
- btTypedConstraintData m_typeConstraintData;
- btTransformFloatData m_rbAFrame; // constraint axii. Assumes z is hinge axis.
+ btTypedConstraintData m_typeConstraintData;
+ btTransformFloatData m_rbAFrame; // constraint axii. Assumes z is hinge axis.
btTransformFloatData m_rbBFrame;
- int m_useReferenceFrameA;
- int m_angularOnly;
-
- int m_enableAngularMotor;
- float m_motorTargetVelocity;
- float m_maxMotorImpulse;
-
- float m_lowerLimit;
- float m_upperLimit;
- float m_limitSoftness;
- float m_biasFactor;
- float m_relaxationFactor;
-
+ int m_useReferenceFrameA;
+ int m_angularOnly;
+
+ int m_enableAngularMotor;
+ float m_motorTargetVelocity;
+ float m_maxMotorImpulse;
+
+ float m_lowerLimit;
+ float m_upperLimit;
+ float m_limitSoftness;
+ float m_biasFactor;
+ float m_relaxationFactor;
};
-
-
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btHingeConstraintDoubleData2
+struct btHingeConstraintDoubleData2
{
- btTypedConstraintDoubleData m_typeConstraintData;
- btTransformDoubleData m_rbAFrame; // constraint axii. Assumes z is hinge axis.
+ btTypedConstraintDoubleData m_typeConstraintData;
+ btTransformDoubleData m_rbAFrame; // constraint axii. Assumes z is hinge axis.
btTransformDoubleData m_rbBFrame;
- int m_useReferenceFrameA;
- int m_angularOnly;
- int m_enableAngularMotor;
- double m_motorTargetVelocity;
- double m_maxMotorImpulse;
-
- double m_lowerLimit;
- double m_upperLimit;
- double m_limitSoftness;
- double m_biasFactor;
- double m_relaxationFactor;
- char m_padding1[4];
-
+ int m_useReferenceFrameA;
+ int m_angularOnly;
+ int m_enableAngularMotor;
+ double m_motorTargetVelocity;
+ double m_maxMotorImpulse;
+
+ double m_lowerLimit;
+ double m_upperLimit;
+ double m_limitSoftness;
+ double m_biasFactor;
+ double m_relaxationFactor;
+ char m_padding1[4];
};
-
-
-
-SIMD_FORCE_INLINE int btHingeConstraint::calculateSerializeBufferSize() const
+SIMD_FORCE_INLINE int btHingeConstraint::calculateSerializeBufferSize() const
{
return sizeof(btHingeConstraintData);
}
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
-SIMD_FORCE_INLINE const char* btHingeConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE const char* btHingeConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
{
btHingeConstraintData* hingeData = (btHingeConstraintData*)dataBuffer;
- btTypedConstraint::serialize(&hingeData->m_typeConstraintData,serializer);
+ btTypedConstraint::serialize(&hingeData->m_typeConstraintData, serializer);
m_rbAFrame.serialize(hingeData->m_rbAFrame);
m_rbBFrame.serialize(hingeData->m_rbBFrame);
@@ -475,7 +452,7 @@ SIMD_FORCE_INLINE const char* btHingeConstraint::serialize(void* dataBuffer, btS
hingeData->m_maxMotorImpulse = float(m_maxMotorImpulse);
hingeData->m_motorTargetVelocity = float(m_motorTargetVelocity);
hingeData->m_useReferenceFrameA = m_useReferenceFrameA;
-#ifdef _BT_USE_CENTER_LIMIT_
+#ifdef _BT_USE_CENTER_LIMIT_
hingeData->m_lowerLimit = float(m_limit.getLow());
hingeData->m_upperLimit = float(m_limit.getHigh());
hingeData->m_limitSoftness = float(m_limit.getSoftness());
@@ -500,4 +477,4 @@ SIMD_FORCE_INLINE const char* btHingeConstraint::serialize(void* dataBuffer, btS
return btHingeConstraintDataName;
}
-#endif //BT_HINGECONSTRAINT_H
+#endif //BT_HINGECONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btJacobianEntry.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btJacobianEntry.h
index 125580d199..438456fe51 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btJacobianEntry.h
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btJacobianEntry.h
@@ -18,7 +18,6 @@ subject to the following restrictions:
#include "LinearMath/btMatrix3x3.h"
-
//notes:
// Another memory optimization would be to store m_1MinvJt in the remaining 3 w components
// which makes the btJacobianEntry memory layout 16 bytes
@@ -27,25 +26,26 @@ subject to the following restrictions:
/// Jacobian entry is an abstraction that allows to describe constraints
/// it can be used in combination with a constraint solver
/// Can be used to relate the effect of an impulse to the constraint error
-ATTRIBUTE_ALIGNED16(class) btJacobianEntry
+ATTRIBUTE_ALIGNED16(class)
+btJacobianEntry
{
public:
- btJacobianEntry() {};
+ btJacobianEntry(){};
//constraint between two different rigidbodies
btJacobianEntry(
const btMatrix3x3& world2A,
const btMatrix3x3& world2B,
- const btVector3& rel_pos1,const btVector3& rel_pos2,
+ const btVector3& rel_pos1, const btVector3& rel_pos2,
const btVector3& jointAxis,
- const btVector3& inertiaInvA,
+ const btVector3& inertiaInvA,
const btScalar massInvA,
const btVector3& inertiaInvB,
const btScalar massInvB)
- :m_linearJointAxis(jointAxis)
+ : m_linearJointAxis(jointAxis)
{
- m_aJ = world2A*(rel_pos1.cross(m_linearJointAxis));
- m_bJ = world2B*(rel_pos2.cross(-m_linearJointAxis));
- m_0MinvJt = inertiaInvA * m_aJ;
+ m_aJ = world2A * (rel_pos1.cross(m_linearJointAxis));
+ m_bJ = world2B * (rel_pos2.cross(-m_linearJointAxis));
+ m_0MinvJt = inertiaInvA * m_aJ;
m_1MinvJt = inertiaInvB * m_bJ;
m_Adiag = massInvA + m_0MinvJt.dot(m_aJ) + massInvB + m_1MinvJt.dot(m_bJ);
@@ -54,33 +54,31 @@ public:
//angular constraint between two different rigidbodies
btJacobianEntry(const btVector3& jointAxis,
- const btMatrix3x3& world2A,
- const btMatrix3x3& world2B,
- const btVector3& inertiaInvA,
- const btVector3& inertiaInvB)
- :m_linearJointAxis(btVector3(btScalar(0.),btScalar(0.),btScalar(0.)))
+ const btMatrix3x3& world2A,
+ const btMatrix3x3& world2B,
+ const btVector3& inertiaInvA,
+ const btVector3& inertiaInvB)
+ : m_linearJointAxis(btVector3(btScalar(0.), btScalar(0.), btScalar(0.)))
{
- m_aJ= world2A*jointAxis;
- m_bJ = world2B*-jointAxis;
- m_0MinvJt = inertiaInvA * m_aJ;
+ m_aJ = world2A * jointAxis;
+ m_bJ = world2B * -jointAxis;
+ m_0MinvJt = inertiaInvA * m_aJ;
m_1MinvJt = inertiaInvB * m_bJ;
- m_Adiag = m_0MinvJt.dot(m_aJ) + m_1MinvJt.dot(m_bJ);
+ m_Adiag = m_0MinvJt.dot(m_aJ) + m_1MinvJt.dot(m_bJ);
btAssert(m_Adiag > btScalar(0.0));
}
//angular constraint between two different rigidbodies
btJacobianEntry(const btVector3& axisInA,
- const btVector3& axisInB,
- const btVector3& inertiaInvA,
- const btVector3& inertiaInvB)
- : m_linearJointAxis(btVector3(btScalar(0.),btScalar(0.),btScalar(0.)))
- , m_aJ(axisInA)
- , m_bJ(-axisInB)
+ const btVector3& axisInB,
+ const btVector3& inertiaInvA,
+ const btVector3& inertiaInvB)
+ : m_linearJointAxis(btVector3(btScalar(0.), btScalar(0.), btScalar(0.))), m_aJ(axisInA), m_bJ(-axisInB)
{
- m_0MinvJt = inertiaInvA * m_aJ;
+ m_0MinvJt = inertiaInvA * m_aJ;
m_1MinvJt = inertiaInvB * m_bJ;
- m_Adiag = m_0MinvJt.dot(m_aJ) + m_1MinvJt.dot(m_bJ);
+ m_Adiag = m_0MinvJt.dot(m_aJ) + m_1MinvJt.dot(m_bJ);
btAssert(m_Adiag > btScalar(0.0));
}
@@ -88,25 +86,25 @@ public:
//constraint on one rigidbody
btJacobianEntry(
const btMatrix3x3& world2A,
- const btVector3& rel_pos1,const btVector3& rel_pos2,
+ const btVector3& rel_pos1, const btVector3& rel_pos2,
const btVector3& jointAxis,
- const btVector3& inertiaInvA,
+ const btVector3& inertiaInvA,
const btScalar massInvA)
- :m_linearJointAxis(jointAxis)
+ : m_linearJointAxis(jointAxis)
{
- m_aJ= world2A*(rel_pos1.cross(jointAxis));
- m_bJ = world2A*(rel_pos2.cross(-jointAxis));
- m_0MinvJt = inertiaInvA * m_aJ;
- m_1MinvJt = btVector3(btScalar(0.),btScalar(0.),btScalar(0.));
+ m_aJ = world2A * (rel_pos1.cross(jointAxis));
+ m_bJ = world2A * (rel_pos2.cross(-jointAxis));
+ m_0MinvJt = inertiaInvA * m_aJ;
+ m_1MinvJt = btVector3(btScalar(0.), btScalar(0.), btScalar(0.));
m_Adiag = massInvA + m_0MinvJt.dot(m_aJ);
btAssert(m_Adiag > btScalar(0.0));
}
- btScalar getDiagonal() const { return m_Adiag; }
+ btScalar getDiagonal() const { return m_Adiag; }
// for two constraints on the same rigidbody (for example vehicle friction)
- btScalar getNonDiagonal(const btJacobianEntry& jacB, const btScalar massInvA) const
+ btScalar getNonDiagonal(const btJacobianEntry& jacB, const btScalar massInvA) const
{
const btJacobianEntry& jacA = *this;
btScalar lin = massInvA * jacA.m_linearJointAxis.dot(jacB.m_linearJointAxis);
@@ -114,42 +112,39 @@ public:
return lin + ang;
}
-
-
// for two constraints on sharing two same rigidbodies (for example two contact points between two rigidbodies)
- btScalar getNonDiagonal(const btJacobianEntry& jacB,const btScalar massInvA,const btScalar massInvB) const
+ btScalar getNonDiagonal(const btJacobianEntry& jacB, const btScalar massInvA, const btScalar massInvB) const
{
const btJacobianEntry& jacA = *this;
btVector3 lin = jacA.m_linearJointAxis * jacB.m_linearJointAxis;
btVector3 ang0 = jacA.m_0MinvJt * jacB.m_aJ;
btVector3 ang1 = jacA.m_1MinvJt * jacB.m_bJ;
- btVector3 lin0 = massInvA * lin ;
+ btVector3 lin0 = massInvA * lin;
btVector3 lin1 = massInvB * lin;
- btVector3 sum = ang0+ang1+lin0+lin1;
- return sum[0]+sum[1]+sum[2];
+ btVector3 sum = ang0 + ang1 + lin0 + lin1;
+ return sum[0] + sum[1] + sum[2];
}
- btScalar getRelativeVelocity(const btVector3& linvelA,const btVector3& angvelA,const btVector3& linvelB,const btVector3& angvelB)
+ btScalar getRelativeVelocity(const btVector3& linvelA, const btVector3& angvelA, const btVector3& linvelB, const btVector3& angvelB)
{
btVector3 linrel = linvelA - linvelB;
- btVector3 angvela = angvelA * m_aJ;
- btVector3 angvelb = angvelB * m_bJ;
+ btVector3 angvela = angvelA * m_aJ;
+ btVector3 angvelb = angvelB * m_bJ;
linrel *= m_linearJointAxis;
angvela += angvelb;
angvela += linrel;
- btScalar rel_vel2 = angvela[0]+angvela[1]+angvela[2];
+ btScalar rel_vel2 = angvela[0] + angvela[1] + angvela[2];
return rel_vel2 + SIMD_EPSILON;
}
-//private:
+ //private:
- btVector3 m_linearJointAxis;
- btVector3 m_aJ;
- btVector3 m_bJ;
- btVector3 m_0MinvJt;
- btVector3 m_1MinvJt;
+ btVector3 m_linearJointAxis;
+ btVector3 m_aJ;
+ btVector3 m_bJ;
+ btVector3 m_0MinvJt;
+ btVector3 m_1MinvJt;
//Optimization: can be stored in the w/last component of one of the vectors
- btScalar m_Adiag;
-
+ btScalar m_Adiag;
};
-#endif //BT_JACOBIAN_ENTRY_H
+#endif //BT_JACOBIAN_ENTRY_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.cpp
index f3979be358..ccf8916049 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.cpp
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.cpp
@@ -15,14 +15,9 @@ subject to the following restrictions:
#include "btNNCGConstraintSolver.h"
-
-
-
-
-
-btScalar btNNCGConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer)
+btScalar btNNCGConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
{
- btScalar val = btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup( bodies,numBodies,manifoldPtr, numManifolds, constraints,numConstraints,infoGlobal,debugDrawer);
+ btScalar val = btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
m_pNC.resizeNoInitialize(m_tmpSolverNonContactConstraintPool.size());
m_pC.resizeNoInitialize(m_tmpSolverContactConstraintPool.size());
@@ -37,38 +32,39 @@ btScalar btNNCGConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject*
return val;
}
-btScalar btNNCGConstraintSolver::solveSingleIteration(int iteration, btCollisionObject** /*bodies */,int /*numBodies*/,btPersistentManifold** /*manifoldPtr*/, int /*numManifolds*/,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* /*debugDrawer*/)
+btScalar btNNCGConstraintSolver::solveSingleIteration(int iteration, btCollisionObject** /*bodies */, int /*numBodies*/, btPersistentManifold** /*manifoldPtr*/, int /*numManifolds*/, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* /*debugDrawer*/)
{
-
int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
int numConstraintPool = m_tmpSolverContactConstraintPool.size();
int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size();
if (infoGlobal.m_solverMode & SOLVER_RANDMIZE_ORDER)
{
- if (1) // uncomment this for a bit less random ((iteration & 7) == 0)
+ if (1) // uncomment this for a bit less random ((iteration & 7) == 0)
{
-
- for (int j=0; j<numNonContactPool; ++j) {
+ for (int j = 0; j < numNonContactPool; ++j)
+ {
int tmp = m_orderNonContactConstraintPool[j];
- int swapi = btRandInt2(j+1);
+ int swapi = btRandInt2(j + 1);
m_orderNonContactConstraintPool[j] = m_orderNonContactConstraintPool[swapi];
m_orderNonContactConstraintPool[swapi] = tmp;
}
- //contact/friction constraints are not solved more than
- if (iteration< infoGlobal.m_numIterations)
+ //contact/friction constraints are not solved more than
+ if (iteration < infoGlobal.m_numIterations)
{
- for (int j=0; j<numConstraintPool; ++j) {
+ for (int j = 0; j < numConstraintPool; ++j)
+ {
int tmp = m_orderTmpConstraintPool[j];
- int swapi = btRandInt2(j+1);
+ int swapi = btRandInt2(j + 1);
m_orderTmpConstraintPool[j] = m_orderTmpConstraintPool[swapi];
m_orderTmpConstraintPool[swapi] = tmp;
}
- for (int j=0; j<numFrictionPool; ++j) {
+ for (int j = 0; j < numFrictionPool; ++j)
+ {
int tmp = m_orderFrictionConstraintPool[j];
- int swapi = btRandInt2(j+1);
+ int swapi = btRandInt2(j + 1);
m_orderFrictionConstraintPool[j] = m_orderFrictionConstraintPool[swapi];
m_orderFrictionConstraintPool[swapi] = tmp;
}
@@ -76,39 +72,40 @@ btScalar btNNCGConstraintSolver::solveSingleIteration(int iteration, btCollision
}
}
-
btScalar deltaflengthsqr = 0;
{
- for (int j=0;j<m_tmpSolverNonContactConstraintPool.size();j++)
+ for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++)
{
btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
- if (iteration < constraint.m_overrideNumSolverIterations)
+ if (iteration < constraint.m_overrideNumSolverIterations)
{
- btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[constraint.m_solverBodyIdA],m_tmpSolverBodyPool[constraint.m_solverBodyIdB],constraint);
+ btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[constraint.m_solverBodyIdA], m_tmpSolverBodyPool[constraint.m_solverBodyIdB], constraint);
m_deltafNC[j] = deltaf;
deltaflengthsqr += deltaf * deltaf;
}
}
}
-
- if (m_onlyForNoneContact)
+ if (m_onlyForNoneContact)
{
- if (iteration==0)
+ if (iteration == 0)
+ {
+ for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++) m_pNC[j] = m_deltafNC[j];
+ }
+ else
{
- for (int j=0;j<m_tmpSolverNonContactConstraintPool.size();j++) m_pNC[j] = m_deltafNC[j];
- } else {
// deltaflengthsqrprev can be 0 only if the solver solved the problem exactly in the previous iteration. In this case we should have quit, but mainly for debug reason with this 'hack' it is now allowed to continue the calculation
- btScalar beta = m_deltafLengthSqrPrev>0 ? deltaflengthsqr / m_deltafLengthSqrPrev : 2;
- if (beta>1)
+ btScalar beta = m_deltafLengthSqrPrev > 0 ? deltaflengthsqr / m_deltafLengthSqrPrev : 2;
+ if (beta > 1)
{
- for (int j=0;j<m_tmpSolverNonContactConstraintPool.size();j++) m_pNC[j] = 0;
- } else
+ for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++) m_pNC[j] = 0;
+ }
+ else
{
- for (int j=0;j<m_tmpSolverNonContactConstraintPool.size();j++)
+ for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++)
{
btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
- if (iteration < constraint.m_overrideNumSolverIterations)
+ if (iteration < constraint.m_overrideNumSolverIterations)
{
btScalar additionaldeltaimpulse = beta * m_pNC[j];
constraint.m_appliedImpulse = btScalar(constraint.m_appliedImpulse) + additionaldeltaimpulse;
@@ -116,8 +113,8 @@ btScalar btNNCGConstraintSolver::solveSingleIteration(int iteration, btCollision
btSolverBody& body1 = m_tmpSolverBodyPool[constraint.m_solverBodyIdA];
btSolverBody& body2 = m_tmpSolverBodyPool[constraint.m_solverBodyIdB];
const btSolverConstraint& c = constraint;
- body1.internalApplyImpulse(c.m_contactNormal1*body1.internalGetInvMass(),c.m_angularComponentA,additionaldeltaimpulse);
- body2.internalApplyImpulse(c.m_contactNormal2*body2.internalGetInvMass(),c.m_angularComponentB,additionaldeltaimpulse);
+ body1.internalApplyImpulse(c.m_contactNormal1 * body1.internalGetInvMass(), c.m_angularComponentA, additionaldeltaimpulse);
+ body2.internalApplyImpulse(c.m_contactNormal2 * body2.internalGetInvMass(), c.m_angularComponentB, additionaldeltaimpulse);
}
}
}
@@ -125,21 +122,18 @@ btScalar btNNCGConstraintSolver::solveSingleIteration(int iteration, btCollision
m_deltafLengthSqrPrev = deltaflengthsqr;
}
-
-
{
-
- if (iteration< infoGlobal.m_numIterations)
+ if (iteration < infoGlobal.m_numIterations)
{
- for (int j=0;j<numConstraints;j++)
+ for (int j = 0; j < numConstraints; j++)
{
if (constraints[j]->isEnabled())
{
- int bodyAid = getOrInitSolverBody(constraints[j]->getRigidBodyA(),infoGlobal.m_timeStep);
- int bodyBid = getOrInitSolverBody(constraints[j]->getRigidBodyB(),infoGlobal.m_timeStep);
+ int bodyAid = getOrInitSolverBody(constraints[j]->getRigidBodyA(), infoGlobal.m_timeStep);
+ int bodyBid = getOrInitSolverBody(constraints[j]->getRigidBodyB(), infoGlobal.m_timeStep);
btSolverBody& bodyA = m_tmpSolverBodyPool[bodyAid];
btSolverBody& bodyB = m_tmpSolverBodyPool[bodyBid];
- constraints[j]->solveConstraintObsolete(bodyA,bodyB,infoGlobal.m_timeStep);
+ constraints[j]->solveConstraintObsolete(bodyA, bodyB, infoGlobal.m_timeStep);
}
}
@@ -147,203 +141,206 @@ btScalar btNNCGConstraintSolver::solveSingleIteration(int iteration, btCollision
if (infoGlobal.m_solverMode & SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS)
{
int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
- int multiplier = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)? 2 : 1;
+ int multiplier = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) ? 2 : 1;
- for (int c=0;c<numPoolConstraints;c++)
+ for (int c = 0; c < numPoolConstraints; c++)
{
- btScalar totalImpulse =0;
+ btScalar totalImpulse = 0;
{
const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[c]];
- btScalar deltaf = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
+ btScalar deltaf = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
m_deltafC[c] = deltaf;
- deltaflengthsqr += deltaf*deltaf;
+ deltaflengthsqr += deltaf * deltaf;
totalImpulse = solveManifold.m_appliedImpulse;
}
bool applyFriction = true;
if (applyFriction)
{
{
+ btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c * multiplier]];
- btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c*multiplier]];
-
- if (totalImpulse>btScalar(0))
+ if (totalImpulse > btScalar(0))
{
- solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
- solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
- btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
- m_deltafCF[c*multiplier] = deltaf;
- deltaflengthsqr += deltaf*deltaf;
- } else {
- m_deltafCF[c*multiplier] = 0;
+ solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
+ solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
+ btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+ m_deltafCF[c * multiplier] = deltaf;
+ deltaflengthsqr += deltaf * deltaf;
+ }
+ else
+ {
+ m_deltafCF[c * multiplier] = 0;
}
}
if (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)
{
+ btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c * multiplier + 1]];
- btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c*multiplier+1]];
-
- if (totalImpulse>btScalar(0))
+ if (totalImpulse > btScalar(0))
+ {
+ solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
+ solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
+ btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+ m_deltafCF[c * multiplier + 1] = deltaf;
+ deltaflengthsqr += deltaf * deltaf;
+ }
+ else
{
- solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
- solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
- btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
- m_deltafCF[c*multiplier+1] = deltaf;
- deltaflengthsqr += deltaf*deltaf;
- } else {
- m_deltafCF[c*multiplier+1] = 0;
+ m_deltafCF[c * multiplier + 1] = 0;
}
}
}
}
-
}
- else//SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS
+ else //SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS
{
//solve the friction constraints after all contact constraints, don't interleave them
int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
int j;
- for (j=0;j<numPoolConstraints;j++)
+ for (j = 0; j < numPoolConstraints; j++)
{
const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
- btScalar deltaf = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
+ btScalar deltaf = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
m_deltafC[j] = deltaf;
- deltaflengthsqr += deltaf*deltaf;
+ deltaflengthsqr += deltaf * deltaf;
}
-
-
///solve all friction constraints
int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size();
- for (j=0;j<numFrictionPoolConstraints;j++)
+ for (j = 0; j < numFrictionPoolConstraints; j++)
{
btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]];
btScalar totalImpulse = m_tmpSolverContactConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
- if (totalImpulse>btScalar(0))
+ if (totalImpulse > btScalar(0))
{
- solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
- solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
+ solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
+ solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
- btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
+ btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
m_deltafCF[j] = deltaf;
- deltaflengthsqr += deltaf*deltaf;
- } else {
+ deltaflengthsqr += deltaf * deltaf;
+ }
+ else
+ {
m_deltafCF[j] = 0;
}
}
}
- {
+ {
int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size();
- for (int j=0;j<numRollingFrictionPoolConstraints;j++)
+ for (int j = 0; j < numRollingFrictionPoolConstraints; j++)
{
-
btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
btScalar totalImpulse = m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse;
- if (totalImpulse>btScalar(0))
+ if (totalImpulse > btScalar(0))
{
- btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction*totalImpulse;
- if (rollingFrictionMagnitude>rollingFrictionConstraint.m_friction)
+ btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse;
+ if (rollingFrictionMagnitude > rollingFrictionConstraint.m_friction)
rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
- btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA],m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB],rollingFrictionConstraint);
+ btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint);
m_deltafCRF[j] = deltaf;
- deltaflengthsqr += deltaf*deltaf;
- } else {
+ deltaflengthsqr += deltaf * deltaf;
+ }
+ else
+ {
m_deltafCRF[j] = 0;
}
}
- }
-
+ }
}
-
-
-
}
-
-
-
- if (!m_onlyForNoneContact)
+ if (!m_onlyForNoneContact)
{
- if (iteration==0)
+ if (iteration == 0)
{
- for (int j=0;j<m_tmpSolverNonContactConstraintPool.size();j++) m_pNC[j] = m_deltafNC[j];
- for (int j=0;j<m_tmpSolverContactConstraintPool.size();j++) m_pC[j] = m_deltafC[j];
- for (int j=0;j<m_tmpSolverContactFrictionConstraintPool.size();j++) m_pCF[j] = m_deltafCF[j];
- for (int j=0;j<m_tmpSolverContactRollingFrictionConstraintPool.size();j++) m_pCRF[j] = m_deltafCRF[j];
- } else
+ for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++) m_pNC[j] = m_deltafNC[j];
+ for (int j = 0; j < m_tmpSolverContactConstraintPool.size(); j++) m_pC[j] = m_deltafC[j];
+ for (int j = 0; j < m_tmpSolverContactFrictionConstraintPool.size(); j++) m_pCF[j] = m_deltafCF[j];
+ for (int j = 0; j < m_tmpSolverContactRollingFrictionConstraintPool.size(); j++) m_pCRF[j] = m_deltafCRF[j];
+ }
+ else
{
// deltaflengthsqrprev can be 0 only if the solver solved the problem exactly in the previous iteration. In this case we should have quit, but mainly for debug reason with this 'hack' it is now allowed to continue the calculation
- btScalar beta = m_deltafLengthSqrPrev>0 ? deltaflengthsqr / m_deltafLengthSqrPrev : 2;
- if (beta>1) {
- for (int j=0;j<m_tmpSolverNonContactConstraintPool.size();j++) m_pNC[j] = 0;
- for (int j=0;j<m_tmpSolverContactConstraintPool.size();j++) m_pC[j] = 0;
- for (int j=0;j<m_tmpSolverContactFrictionConstraintPool.size();j++) m_pCF[j] = 0;
- for (int j=0;j<m_tmpSolverContactRollingFrictionConstraintPool.size();j++) m_pCRF[j] = 0;
- } else {
- for (int j=0;j<m_tmpSolverNonContactConstraintPool.size();j++)
+ btScalar beta = m_deltafLengthSqrPrev > 0 ? deltaflengthsqr / m_deltafLengthSqrPrev : 2;
+ if (beta > 1)
+ {
+ for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++) m_pNC[j] = 0;
+ for (int j = 0; j < m_tmpSolverContactConstraintPool.size(); j++) m_pC[j] = 0;
+ for (int j = 0; j < m_tmpSolverContactFrictionConstraintPool.size(); j++) m_pCF[j] = 0;
+ for (int j = 0; j < m_tmpSolverContactRollingFrictionConstraintPool.size(); j++) m_pCRF[j] = 0;
+ }
+ else
+ {
+ for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++)
{
btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
- if (iteration < constraint.m_overrideNumSolverIterations) {
+ if (iteration < constraint.m_overrideNumSolverIterations)
+ {
btScalar additionaldeltaimpulse = beta * m_pNC[j];
constraint.m_appliedImpulse = btScalar(constraint.m_appliedImpulse) + additionaldeltaimpulse;
m_pNC[j] = beta * m_pNC[j] + m_deltafNC[j];
btSolverBody& body1 = m_tmpSolverBodyPool[constraint.m_solverBodyIdA];
btSolverBody& body2 = m_tmpSolverBodyPool[constraint.m_solverBodyIdB];
const btSolverConstraint& c = constraint;
- body1.internalApplyImpulse(c.m_contactNormal1*body1.internalGetInvMass(),c.m_angularComponentA,additionaldeltaimpulse);
- body2.internalApplyImpulse(c.m_contactNormal2*body2.internalGetInvMass(),c.m_angularComponentB,additionaldeltaimpulse);
+ body1.internalApplyImpulse(c.m_contactNormal1 * body1.internalGetInvMass(), c.m_angularComponentA, additionaldeltaimpulse);
+ body2.internalApplyImpulse(c.m_contactNormal2 * body2.internalGetInvMass(), c.m_angularComponentB, additionaldeltaimpulse);
}
}
- for (int j=0;j<m_tmpSolverContactConstraintPool.size();j++)
+ for (int j = 0; j < m_tmpSolverContactConstraintPool.size(); j++)
{
btSolverConstraint& constraint = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
- if (iteration< infoGlobal.m_numIterations) {
+ if (iteration < infoGlobal.m_numIterations)
+ {
btScalar additionaldeltaimpulse = beta * m_pC[j];
constraint.m_appliedImpulse = btScalar(constraint.m_appliedImpulse) + additionaldeltaimpulse;
m_pC[j] = beta * m_pC[j] + m_deltafC[j];
btSolverBody& body1 = m_tmpSolverBodyPool[constraint.m_solverBodyIdA];
btSolverBody& body2 = m_tmpSolverBodyPool[constraint.m_solverBodyIdB];
const btSolverConstraint& c = constraint;
- body1.internalApplyImpulse(c.m_contactNormal1*body1.internalGetInvMass(),c.m_angularComponentA,additionaldeltaimpulse);
- body2.internalApplyImpulse(c.m_contactNormal2*body2.internalGetInvMass(),c.m_angularComponentB,additionaldeltaimpulse);
+ body1.internalApplyImpulse(c.m_contactNormal1 * body1.internalGetInvMass(), c.m_angularComponentA, additionaldeltaimpulse);
+ body2.internalApplyImpulse(c.m_contactNormal2 * body2.internalGetInvMass(), c.m_angularComponentB, additionaldeltaimpulse);
}
}
- for (int j=0;j<m_tmpSolverContactFrictionConstraintPool.size();j++)
+ for (int j = 0; j < m_tmpSolverContactFrictionConstraintPool.size(); j++)
{
btSolverConstraint& constraint = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]];
- if (iteration< infoGlobal.m_numIterations) {
+ if (iteration < infoGlobal.m_numIterations)
+ {
btScalar additionaldeltaimpulse = beta * m_pCF[j];
constraint.m_appliedImpulse = btScalar(constraint.m_appliedImpulse) + additionaldeltaimpulse;
m_pCF[j] = beta * m_pCF[j] + m_deltafCF[j];
btSolverBody& body1 = m_tmpSolverBodyPool[constraint.m_solverBodyIdA];
btSolverBody& body2 = m_tmpSolverBodyPool[constraint.m_solverBodyIdB];
const btSolverConstraint& c = constraint;
- body1.internalApplyImpulse(c.m_contactNormal1*body1.internalGetInvMass(),c.m_angularComponentA,additionaldeltaimpulse);
- body2.internalApplyImpulse(c.m_contactNormal2*body2.internalGetInvMass(),c.m_angularComponentB,additionaldeltaimpulse);
+ body1.internalApplyImpulse(c.m_contactNormal1 * body1.internalGetInvMass(), c.m_angularComponentA, additionaldeltaimpulse);
+ body2.internalApplyImpulse(c.m_contactNormal2 * body2.internalGetInvMass(), c.m_angularComponentB, additionaldeltaimpulse);
}
}
{
- for (int j=0;j<m_tmpSolverContactRollingFrictionConstraintPool.size();j++)
+ for (int j = 0; j < m_tmpSolverContactRollingFrictionConstraintPool.size(); j++)
{
btSolverConstraint& constraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
- if (iteration< infoGlobal.m_numIterations) {
+ if (iteration < infoGlobal.m_numIterations)
+ {
btScalar additionaldeltaimpulse = beta * m_pCRF[j];
constraint.m_appliedImpulse = btScalar(constraint.m_appliedImpulse) + additionaldeltaimpulse;
m_pCRF[j] = beta * m_pCRF[j] + m_deltafCRF[j];
btSolverBody& body1 = m_tmpSolverBodyPool[constraint.m_solverBodyIdA];
btSolverBody& body2 = m_tmpSolverBodyPool[constraint.m_solverBodyIdB];
const btSolverConstraint& c = constraint;
- body1.internalApplyImpulse(c.m_contactNormal1*body1.internalGetInvMass(),c.m_angularComponentA,additionaldeltaimpulse);
- body2.internalApplyImpulse(c.m_contactNormal2*body2.internalGetInvMass(),c.m_angularComponentB,additionaldeltaimpulse);
+ body1.internalApplyImpulse(c.m_contactNormal1 * body1.internalGetInvMass(), c.m_angularComponentA, additionaldeltaimpulse);
+ body2.internalApplyImpulse(c.m_contactNormal2 * body2.internalGetInvMass(), c.m_angularComponentB, additionaldeltaimpulse);
}
}
}
@@ -355,7 +352,7 @@ btScalar btNNCGConstraintSolver::solveSingleIteration(int iteration, btCollision
return deltaflengthsqr;
}
-btScalar btNNCGConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionObject** bodies,int numBodies,const btContactSolverInfo& infoGlobal)
+btScalar btNNCGConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
{
m_pNC.resizeNoInitialize(0);
m_pC.resizeNoInitialize(0);
@@ -369,6 +366,3 @@ btScalar btNNCGConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionObject
return btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish(bodies, numBodies, infoGlobal);
}
-
-
-
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.h
index a300929cd5..c84f274a99 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.h
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.h
@@ -18,33 +18,30 @@ subject to the following restrictions:
#include "btSequentialImpulseConstraintSolver.h"
-ATTRIBUTE_ALIGNED16(class) btNNCGConstraintSolver : public btSequentialImpulseConstraintSolver
+ATTRIBUTE_ALIGNED16(class)
+btNNCGConstraintSolver : public btSequentialImpulseConstraintSolver
{
protected:
-
btScalar m_deltafLengthSqrPrev;
- btAlignedObjectArray<btScalar> m_pNC; // p for None Contact constraints
- btAlignedObjectArray<btScalar> m_pC; // p for Contact constraints
- btAlignedObjectArray<btScalar> m_pCF; // p for ContactFriction constraints
- btAlignedObjectArray<btScalar> m_pCRF; // p for ContactRollingFriction constraints
+ btAlignedObjectArray<btScalar> m_pNC; // p for None Contact constraints
+ btAlignedObjectArray<btScalar> m_pC; // p for Contact constraints
+ btAlignedObjectArray<btScalar> m_pCF; // p for ContactFriction constraints
+ btAlignedObjectArray<btScalar> m_pCRF; // p for ContactRollingFriction constraints
//These are recalculated in every iterations. We just keep these to prevent reallocation in each iteration.
- btAlignedObjectArray<btScalar> m_deltafNC; // deltaf for NoneContact constraints
- btAlignedObjectArray<btScalar> m_deltafC; // deltaf for Contact constraints
- btAlignedObjectArray<btScalar> m_deltafCF; // deltaf for ContactFriction constraints
- btAlignedObjectArray<btScalar> m_deltafCRF; // deltaf for ContactRollingFriction constraints
+ btAlignedObjectArray<btScalar> m_deltafNC; // deltaf for NoneContact constraints
+ btAlignedObjectArray<btScalar> m_deltafC; // deltaf for Contact constraints
+ btAlignedObjectArray<btScalar> m_deltafCF; // deltaf for ContactFriction constraints
+ btAlignedObjectArray<btScalar> m_deltafCRF; // deltaf for ContactRollingFriction constraints
-
protected:
+ virtual btScalar solveGroupCacheFriendlyFinish(btCollisionObject * *bodies, int numBodies, const btContactSolverInfo& infoGlobal);
+ virtual btScalar solveSingleIteration(int iteration, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
- virtual btScalar solveGroupCacheFriendlyFinish(btCollisionObject** bodies,int numBodies,const btContactSolverInfo& infoGlobal);
- virtual btScalar solveSingleIteration(int iteration, btCollisionObject** bodies ,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer);
-
- virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer);
+ virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
public:
-
BT_DECLARE_ALIGNED_ALLOCATOR();
btNNCGConstraintSolver() : btSequentialImpulseConstraintSolver(), m_onlyForNoneContact(false) {}
@@ -57,8 +54,4 @@ public:
bool m_onlyForNoneContact;
};
-
-
-
-#endif //BT_NNCG_CONSTRAINT_SOLVER_H
-
+#endif //BT_NNCG_CONSTRAINT_SOLVER_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp
index 3c0430b903..ad399dc57f 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp
@@ -13,217 +13,193 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#include "btPoint2PointConstraint.h"
#include "BulletDynamics/Dynamics/btRigidBody.h"
#include <new>
-
-
-
-
-btPoint2PointConstraint::btPoint2PointConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB)
-:btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE,rbA,rbB),m_pivotInA(pivotInA),m_pivotInB(pivotInB),
-m_flags(0),
-m_useSolveConstraintObsolete(false)
+btPoint2PointConstraint::btPoint2PointConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& pivotInA, const btVector3& pivotInB)
+ : btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE, rbA, rbB), m_pivotInA(pivotInA), m_pivotInB(pivotInB), m_flags(0), m_useSolveConstraintObsolete(false)
{
-
}
-
-btPoint2PointConstraint::btPoint2PointConstraint(btRigidBody& rbA,const btVector3& pivotInA)
-:btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE,rbA),m_pivotInA(pivotInA),m_pivotInB(rbA.getCenterOfMassTransform()(pivotInA)),
-m_flags(0),
-m_useSolveConstraintObsolete(false)
+btPoint2PointConstraint::btPoint2PointConstraint(btRigidBody& rbA, const btVector3& pivotInA)
+ : btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE, rbA), m_pivotInA(pivotInA), m_pivotInB(rbA.getCenterOfMassTransform()(pivotInA)), m_flags(0), m_useSolveConstraintObsolete(false)
{
-
}
-void btPoint2PointConstraint::buildJacobian()
+void btPoint2PointConstraint::buildJacobian()
{
-
///we need it for both methods
{
m_appliedImpulse = btScalar(0.);
- btVector3 normal(0,0,0);
+ btVector3 normal(0, 0, 0);
- for (int i=0;i<3;i++)
+ for (int i = 0; i < 3; i++)
{
normal[i] = 1;
new (&m_jac[i]) btJacobianEntry(
- m_rbA.getCenterOfMassTransform().getBasis().transpose(),
- m_rbB.getCenterOfMassTransform().getBasis().transpose(),
- m_rbA.getCenterOfMassTransform()*m_pivotInA - m_rbA.getCenterOfMassPosition(),
- m_rbB.getCenterOfMassTransform()*m_pivotInB - m_rbB.getCenterOfMassPosition(),
- normal,
- m_rbA.getInvInertiaDiagLocal(),
- m_rbA.getInvMass(),
- m_rbB.getInvInertiaDiagLocal(),
- m_rbB.getInvMass());
- normal[i] = 0;
+ m_rbA.getCenterOfMassTransform().getBasis().transpose(),
+ m_rbB.getCenterOfMassTransform().getBasis().transpose(),
+ m_rbA.getCenterOfMassTransform() * m_pivotInA - m_rbA.getCenterOfMassPosition(),
+ m_rbB.getCenterOfMassTransform() * m_pivotInB - m_rbB.getCenterOfMassPosition(),
+ normal,
+ m_rbA.getInvInertiaDiagLocal(),
+ m_rbA.getInvMass(),
+ m_rbB.getInvInertiaDiagLocal(),
+ m_rbB.getInvMass());
+ normal[i] = 0;
}
}
-
-
}
-void btPoint2PointConstraint::getInfo1 (btConstraintInfo1* info)
+void btPoint2PointConstraint::getInfo1(btConstraintInfo1* info)
{
getInfo1NonVirtual(info);
}
-void btPoint2PointConstraint::getInfo1NonVirtual (btConstraintInfo1* info)
+void btPoint2PointConstraint::getInfo1NonVirtual(btConstraintInfo1* info)
{
if (m_useSolveConstraintObsolete)
{
info->m_numConstraintRows = 0;
info->nub = 0;
- } else
+ }
+ else
{
info->m_numConstraintRows = 3;
info->nub = 3;
}
}
-
-
-
-void btPoint2PointConstraint::getInfo2 (btConstraintInfo2* info)
+void btPoint2PointConstraint::getInfo2(btConstraintInfo2* info)
{
- getInfo2NonVirtual(info, m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
+ getInfo2NonVirtual(info, m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
}
-void btPoint2PointConstraint::getInfo2NonVirtual (btConstraintInfo2* info, const btTransform& body0_trans, const btTransform& body1_trans)
+void btPoint2PointConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& body0_trans, const btTransform& body1_trans)
{
btAssert(!m_useSolveConstraintObsolete);
- //retrieve matrices
+ //retrieve matrices
// anchor points in global coordinates with respect to body PORs.
-
- // set jacobian
- info->m_J1linearAxis[0] = 1;
- info->m_J1linearAxis[info->rowskip+1] = 1;
- info->m_J1linearAxis[2*info->rowskip+2] = 1;
- btVector3 a1 = body0_trans.getBasis()*getPivotInA();
+ // set jacobian
+ info->m_J1linearAxis[0] = 1;
+ info->m_J1linearAxis[info->rowskip + 1] = 1;
+ info->m_J1linearAxis[2 * info->rowskip + 2] = 1;
+
+ btVector3 a1 = body0_trans.getBasis() * getPivotInA();
{
btVector3* angular0 = (btVector3*)(info->m_J1angularAxis);
- btVector3* angular1 = (btVector3*)(info->m_J1angularAxis+info->rowskip);
- btVector3* angular2 = (btVector3*)(info->m_J1angularAxis+2*info->rowskip);
+ btVector3* angular1 = (btVector3*)(info->m_J1angularAxis + info->rowskip);
+ btVector3* angular2 = (btVector3*)(info->m_J1angularAxis + 2 * info->rowskip);
btVector3 a1neg = -a1;
- a1neg.getSkewSymmetricMatrix(angular0,angular1,angular2);
+ a1neg.getSkewSymmetricMatrix(angular0, angular1, angular2);
}
-
+
info->m_J2linearAxis[0] = -1;
- info->m_J2linearAxis[info->rowskip+1] = -1;
- info->m_J2linearAxis[2*info->rowskip+2] = -1;
-
- btVector3 a2 = body1_trans.getBasis()*getPivotInB();
-
+ info->m_J2linearAxis[info->rowskip + 1] = -1;
+ info->m_J2linearAxis[2 * info->rowskip + 2] = -1;
+
+ btVector3 a2 = body1_trans.getBasis() * getPivotInB();
+
{
- // btVector3 a2n = -a2;
+ // btVector3 a2n = -a2;
btVector3* angular0 = (btVector3*)(info->m_J2angularAxis);
- btVector3* angular1 = (btVector3*)(info->m_J2angularAxis+info->rowskip);
- btVector3* angular2 = (btVector3*)(info->m_J2angularAxis+2*info->rowskip);
- a2.getSkewSymmetricMatrix(angular0,angular1,angular2);
+ btVector3* angular1 = (btVector3*)(info->m_J2angularAxis + info->rowskip);
+ btVector3* angular2 = (btVector3*)(info->m_J2angularAxis + 2 * info->rowskip);
+ a2.getSkewSymmetricMatrix(angular0, angular1, angular2);
}
-
-
- // set right hand side
+ // set right hand side
btScalar currERP = (m_flags & BT_P2P_FLAGS_ERP) ? m_erp : info->erp;
- btScalar k = info->fps * currERP;
- int j;
- for (j=0; j<3; j++)
- {
- info->m_constraintError[j*info->rowskip] = k * (a2[j] + body1_trans.getOrigin()[j] - a1[j] - body0_trans.getOrigin()[j]);
+ btScalar k = info->fps * currERP;
+ int j;
+ for (j = 0; j < 3; j++)
+ {
+ info->m_constraintError[j * info->rowskip] = k * (a2[j] + body1_trans.getOrigin()[j] - a1[j] - body0_trans.getOrigin()[j]);
//printf("info->m_constraintError[%d]=%f\n",j,info->m_constraintError[j]);
- }
- if(m_flags & BT_P2P_FLAGS_CFM)
+ }
+ if (m_flags & BT_P2P_FLAGS_CFM)
{
- for (j=0; j<3; j++)
+ for (j = 0; j < 3; j++)
{
- info->cfm[j*info->rowskip] = m_cfm;
+ info->cfm[j * info->rowskip] = m_cfm;
}
}
- btScalar impulseClamp = m_setting.m_impulseClamp;//
- for (j=0; j<3; j++)
- {
+ btScalar impulseClamp = m_setting.m_impulseClamp; //
+ for (j = 0; j < 3; j++)
+ {
if (m_setting.m_impulseClamp > 0)
{
- info->m_lowerLimit[j*info->rowskip] = -impulseClamp;
- info->m_upperLimit[j*info->rowskip] = impulseClamp;
+ info->m_lowerLimit[j * info->rowskip] = -impulseClamp;
+ info->m_upperLimit[j * info->rowskip] = impulseClamp;
}
}
info->m_damping = m_setting.m_damping;
-
}
-
-
-void btPoint2PointConstraint::updateRHS(btScalar timeStep)
+void btPoint2PointConstraint::updateRHS(btScalar timeStep)
{
(void)timeStep;
-
}
-///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
///If no axis is provided, it uses the default axis for this constraint.
void btPoint2PointConstraint::setParam(int num, btScalar value, int axis)
{
- if(axis != -1)
+ if (axis != -1)
{
btAssertConstrParams(0);
}
else
{
- switch(num)
+ switch (num)
{
- case BT_CONSTRAINT_ERP :
- case BT_CONSTRAINT_STOP_ERP :
- m_erp = value;
+ case BT_CONSTRAINT_ERP:
+ case BT_CONSTRAINT_STOP_ERP:
+ m_erp = value;
m_flags |= BT_P2P_FLAGS_ERP;
break;
- case BT_CONSTRAINT_CFM :
- case BT_CONSTRAINT_STOP_CFM :
- m_cfm = value;
+ case BT_CONSTRAINT_CFM:
+ case BT_CONSTRAINT_STOP_CFM:
+ m_cfm = value;
m_flags |= BT_P2P_FLAGS_CFM;
break;
- default:
+ default:
btAssertConstrParams(0);
}
}
}
///return the local value of parameter
-btScalar btPoint2PointConstraint::getParam(int num, int axis) const
+btScalar btPoint2PointConstraint::getParam(int num, int axis) const
{
btScalar retVal(SIMD_INFINITY);
- if(axis != -1)
+ if (axis != -1)
{
btAssertConstrParams(0);
}
else
{
- switch(num)
+ switch (num)
{
- case BT_CONSTRAINT_ERP :
- case BT_CONSTRAINT_STOP_ERP :
+ case BT_CONSTRAINT_ERP:
+ case BT_CONSTRAINT_STOP_ERP:
btAssertConstrParams(m_flags & BT_P2P_FLAGS_ERP);
- retVal = m_erp;
+ retVal = m_erp;
break;
- case BT_CONSTRAINT_CFM :
- case BT_CONSTRAINT_STOP_CFM :
+ case BT_CONSTRAINT_CFM:
+ case BT_CONSTRAINT_STOP_CFM:
btAssertConstrParams(m_flags & BT_P2P_FLAGS_CFM);
- retVal = m_cfm;
+ retVal = m_cfm;
break;
- default:
+ default:
btAssertConstrParams(0);
}
}
return retVal;
}
-
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h
index 8fa03d719d..4717e19800 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h
@@ -22,26 +22,24 @@ subject to the following restrictions:
class btRigidBody;
-
#ifdef BT_USE_DOUBLE_PRECISION
-#define btPoint2PointConstraintData2 btPoint2PointConstraintDoubleData2
-#define btPoint2PointConstraintDataName "btPoint2PointConstraintDoubleData2"
+#define btPoint2PointConstraintData2 btPoint2PointConstraintDoubleData2
+#define btPoint2PointConstraintDataName "btPoint2PointConstraintDoubleData2"
#else
-#define btPoint2PointConstraintData2 btPoint2PointConstraintFloatData
-#define btPoint2PointConstraintDataName "btPoint2PointConstraintFloatData"
-#endif //BT_USE_DOUBLE_PRECISION
+#define btPoint2PointConstraintData2 btPoint2PointConstraintFloatData
+#define btPoint2PointConstraintDataName "btPoint2PointConstraintFloatData"
+#endif //BT_USE_DOUBLE_PRECISION
-struct btConstraintSetting
+struct btConstraintSetting
{
- btConstraintSetting() :
- m_tau(btScalar(0.3)),
- m_damping(btScalar(1.)),
- m_impulseClamp(btScalar(0.))
+ btConstraintSetting() : m_tau(btScalar(0.3)),
+ m_damping(btScalar(1.)),
+ m_impulseClamp(btScalar(0.))
{
}
- btScalar m_tau;
- btScalar m_damping;
- btScalar m_impulseClamp;
+ btScalar m_tau;
+ btScalar m_damping;
+ btScalar m_impulseClamp;
};
enum btPoint2PointFlags
@@ -51,52 +49,51 @@ enum btPoint2PointFlags
};
/// point to point constraint between two rigidbodies each with a pivotpoint that descibes the 'ballsocket' location in local space
-ATTRIBUTE_ALIGNED16(class) btPoint2PointConstraint : public btTypedConstraint
+ATTRIBUTE_ALIGNED16(class)
+btPoint2PointConstraint : public btTypedConstraint
{
#ifdef IN_PARALLELL_SOLVER
public:
#endif
- btJacobianEntry m_jac[3]; //3 orthogonal linear constraints
-
- btVector3 m_pivotInA;
- btVector3 m_pivotInB;
-
- int m_flags;
- btScalar m_erp;
- btScalar m_cfm;
-
-public:
+ btJacobianEntry m_jac[3]; //3 orthogonal linear constraints
+
+ btVector3 m_pivotInA;
+ btVector3 m_pivotInB;
+
+ int m_flags;
+ btScalar m_erp;
+ btScalar m_cfm;
+public:
BT_DECLARE_ALIGNED_ALLOCATOR();
///for backwards compatibility during the transition to 'getInfo/getInfo2'
- bool m_useSolveConstraintObsolete;
-
- btConstraintSetting m_setting;
+ bool m_useSolveConstraintObsolete;
- btPoint2PointConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB);
+ btConstraintSetting m_setting;
- btPoint2PointConstraint(btRigidBody& rbA,const btVector3& pivotInA);
+ btPoint2PointConstraint(btRigidBody & rbA, btRigidBody & rbB, const btVector3& pivotInA, const btVector3& pivotInB);
+ btPoint2PointConstraint(btRigidBody & rbA, const btVector3& pivotInA);
- virtual void buildJacobian();
+ virtual void buildJacobian();
- virtual void getInfo1 (btConstraintInfo1* info);
+ virtual void getInfo1(btConstraintInfo1 * info);
- void getInfo1NonVirtual (btConstraintInfo1* info);
+ void getInfo1NonVirtual(btConstraintInfo1 * info);
- virtual void getInfo2 (btConstraintInfo2* info);
+ virtual void getInfo2(btConstraintInfo2 * info);
- void getInfo2NonVirtual (btConstraintInfo2* info, const btTransform& body0_trans, const btTransform& body1_trans);
+ void getInfo2NonVirtual(btConstraintInfo2 * info, const btTransform& body0_trans, const btTransform& body1_trans);
- void updateRHS(btScalar timeStep);
+ void updateRHS(btScalar timeStep);
- void setPivotA(const btVector3& pivotA)
+ void setPivotA(const btVector3& pivotA)
{
m_pivotInA = pivotA;
}
- void setPivotB(const btVector3& pivotB)
+ void setPivotB(const btVector3& pivotB)
{
m_pivotInB = pivotB;
}
@@ -111,70 +108,66 @@ public:
return m_pivotInB;
}
- ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+ ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
///If no axis is provided, it uses the default axis for this constraint.
- virtual void setParam(int num, btScalar value, int axis = -1);
+ virtual void setParam(int num, btScalar value, int axis = -1);
///return the local value of parameter
- virtual btScalar getParam(int num, int axis = -1) const;
-
- virtual int getFlags() const
+ virtual btScalar getParam(int num, int axis = -1) const;
+
+ virtual int getFlags() const
{
- return m_flags;
- }
+ return m_flags;
+ }
- virtual int calculateSerializeBufferSize() const;
+ virtual int calculateSerializeBufferSize() const;
///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-
-
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
};
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btPoint2PointConstraintFloatData
+struct btPoint2PointConstraintFloatData
{
- btTypedConstraintData m_typeConstraintData;
- btVector3FloatData m_pivotInA;
- btVector3FloatData m_pivotInB;
+ btTypedConstraintData m_typeConstraintData;
+ btVector3FloatData m_pivotInA;
+ btVector3FloatData m_pivotInB;
};
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btPoint2PointConstraintDoubleData2
+struct btPoint2PointConstraintDoubleData2
{
- btTypedConstraintDoubleData m_typeConstraintData;
- btVector3DoubleData m_pivotInA;
- btVector3DoubleData m_pivotInB;
+ btTypedConstraintDoubleData m_typeConstraintData;
+ btVector3DoubleData m_pivotInA;
+ btVector3DoubleData m_pivotInB;
};
#ifdef BT_BACKWARDS_COMPATIBLE_SERIALIZATION
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
///this structure is not used, except for loading pre-2.82 .bullet files
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btPoint2PointConstraintDoubleData
+struct btPoint2PointConstraintDoubleData
{
- btTypedConstraintData m_typeConstraintData;
- btVector3DoubleData m_pivotInA;
- btVector3DoubleData m_pivotInB;
+ btTypedConstraintData m_typeConstraintData;
+ btVector3DoubleData m_pivotInA;
+ btVector3DoubleData m_pivotInB;
};
-#endif //BT_BACKWARDS_COMPATIBLE_SERIALIZATION
+#endif //BT_BACKWARDS_COMPATIBLE_SERIALIZATION
-
-SIMD_FORCE_INLINE int btPoint2PointConstraint::calculateSerializeBufferSize() const
+SIMD_FORCE_INLINE int btPoint2PointConstraint::calculateSerializeBufferSize() const
{
return sizeof(btPoint2PointConstraintData2);
-
}
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
-SIMD_FORCE_INLINE const char* btPoint2PointConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE const char* btPoint2PointConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
{
btPoint2PointConstraintData2* p2pData = (btPoint2PointConstraintData2*)dataBuffer;
- btTypedConstraint::serialize(&p2pData->m_typeConstraintData,serializer);
+ btTypedConstraint::serialize(&p2pData->m_typeConstraintData, serializer);
m_pivotInA.serialize(p2pData->m_pivotInA);
m_pivotInB.serialize(p2pData->m_pivotInB);
return btPoint2PointConstraintDataName;
}
-#endif //BT_POINT2POINTCONSTRAINT_H
+#endif //BT_POINT2POINTCONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp
index 63174a6ec0..def3227b43 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp
@@ -21,7 +21,6 @@ subject to the following restrictions:
#include "btSequentialImpulseConstraintSolver.h"
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
-
#include "LinearMath/btIDebugDraw.h"
#include "LinearMath/btCpuFeatureUtility.h"
@@ -34,9 +33,9 @@ subject to the following restrictions:
//#include "btSolverBody.h"
//#include "btSolverConstraint.h"
#include "LinearMath/btAlignedObjectArray.h"
-#include <string.h> //for memset
+#include <string.h> //for memset
-int gNumSplitImpulseRecoveries = 0;
+int gNumSplitImpulseRecoveries = 0;
#include "BulletDynamics/Dynamics/btRigidBody.h"
@@ -45,13 +44,13 @@ int gNumSplitImpulseRecoveries = 0;
///Below are optional SSE2 and SSE4/FMA3 versions. We assume most hardware has SSE2. For SSE4/FMA3 we perform a CPU feature check.
static btScalar gResolveSingleConstraintRowGeneric_scalar_reference(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
{
- btScalar deltaImpulse = c.m_rhs - btScalar(c.m_appliedImpulse)*c.m_cfm;
+ btScalar deltaImpulse = c.m_rhs - btScalar(c.m_appliedImpulse) * c.m_cfm;
const btScalar deltaVel1Dotn = c.m_contactNormal1.dot(bodyA.internalGetDeltaLinearVelocity()) + c.m_relpos1CrossNormal.dot(bodyA.internalGetDeltaAngularVelocity());
const btScalar deltaVel2Dotn = c.m_contactNormal2.dot(bodyB.internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(bodyB.internalGetDeltaAngularVelocity());
// const btScalar delta_rel_vel = deltaVel1Dotn-deltaVel2Dotn;
- deltaImpulse -= deltaVel1Dotn*c.m_jacDiagABInv;
- deltaImpulse -= deltaVel2Dotn*c.m_jacDiagABInv;
+ deltaImpulse -= deltaVel1Dotn * c.m_jacDiagABInv;
+ deltaImpulse -= deltaVel2Dotn * c.m_jacDiagABInv;
const btScalar sum = btScalar(c.m_appliedImpulse) + deltaImpulse;
if (sum < c.m_lowerLimit)
@@ -69,21 +68,20 @@ static btScalar gResolveSingleConstraintRowGeneric_scalar_reference(btSolverBody
c.m_appliedImpulse = sum;
}
- bodyA.internalApplyImpulse(c.m_contactNormal1*bodyA.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
- bodyB.internalApplyImpulse(c.m_contactNormal2*bodyB.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
+ bodyA.internalApplyImpulse(c.m_contactNormal1 * bodyA.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
+ bodyB.internalApplyImpulse(c.m_contactNormal2 * bodyB.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
- return deltaImpulse*(1./c.m_jacDiagABInv);
+ return deltaImpulse * (1. / c.m_jacDiagABInv);
}
-
static btScalar gResolveSingleConstraintRowLowerLimit_scalar_reference(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
{
- btScalar deltaImpulse = c.m_rhs - btScalar(c.m_appliedImpulse)*c.m_cfm;
+ btScalar deltaImpulse = c.m_rhs - btScalar(c.m_appliedImpulse) * c.m_cfm;
const btScalar deltaVel1Dotn = c.m_contactNormal1.dot(bodyA.internalGetDeltaLinearVelocity()) + c.m_relpos1CrossNormal.dot(bodyA.internalGetDeltaAngularVelocity());
const btScalar deltaVel2Dotn = c.m_contactNormal2.dot(bodyB.internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(bodyB.internalGetDeltaAngularVelocity());
- deltaImpulse -= deltaVel1Dotn*c.m_jacDiagABInv;
- deltaImpulse -= deltaVel2Dotn*c.m_jacDiagABInv;
+ deltaImpulse -= deltaVel1Dotn * c.m_jacDiagABInv;
+ deltaImpulse -= deltaVel2Dotn * c.m_jacDiagABInv;
const btScalar sum = btScalar(c.m_appliedImpulse) + deltaImpulse;
if (sum < c.m_lowerLimit)
{
@@ -94,58 +92,55 @@ static btScalar gResolveSingleConstraintRowLowerLimit_scalar_reference(btSolverB
{
c.m_appliedImpulse = sum;
}
- bodyA.internalApplyImpulse(c.m_contactNormal1*bodyA.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
- bodyB.internalApplyImpulse(c.m_contactNormal2*bodyB.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
+ bodyA.internalApplyImpulse(c.m_contactNormal1 * bodyA.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
+ bodyB.internalApplyImpulse(c.m_contactNormal2 * bodyB.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
- return deltaImpulse*(1./c.m_jacDiagABInv);
+ return deltaImpulse * (1. / c.m_jacDiagABInv);
}
-
-
#ifdef USE_SIMD
#include <emmintrin.h>
-
-#define btVecSplat(x, e) _mm_shuffle_ps(x, x, _MM_SHUFFLE(e,e,e,e))
-static inline __m128 btSimdDot3( __m128 vec0, __m128 vec1 )
+#define btVecSplat(x, e) _mm_shuffle_ps(x, x, _MM_SHUFFLE(e, e, e, e))
+static inline __m128 btSimdDot3(__m128 vec0, __m128 vec1)
{
- __m128 result = _mm_mul_ps( vec0, vec1);
- return _mm_add_ps( btVecSplat( result, 0 ), _mm_add_ps( btVecSplat( result, 1 ), btVecSplat( result, 2 ) ) );
+ __m128 result = _mm_mul_ps(vec0, vec1);
+ return _mm_add_ps(btVecSplat(result, 0), _mm_add_ps(btVecSplat(result, 1), btVecSplat(result, 2)));
}
-#if defined (BT_ALLOW_SSE4)
+#if defined(BT_ALLOW_SSE4)
#include <intrin.h>
-#define USE_FMA 1
-#define USE_FMA3_INSTEAD_FMA4 1
-#define USE_SSE4_DOT 1
+#define USE_FMA 1
+#define USE_FMA3_INSTEAD_FMA4 1
+#define USE_SSE4_DOT 1
-#define SSE4_DP(a, b) _mm_dp_ps(a, b, 0x7f)
-#define SSE4_DP_FP(a, b) _mm_cvtss_f32(_mm_dp_ps(a, b, 0x7f))
+#define SSE4_DP(a, b) _mm_dp_ps(a, b, 0x7f)
+#define SSE4_DP_FP(a, b) _mm_cvtss_f32(_mm_dp_ps(a, b, 0x7f))
#if USE_SSE4_DOT
-#define DOT_PRODUCT(a, b) SSE4_DP(a, b)
+#define DOT_PRODUCT(a, b) SSE4_DP(a, b)
#else
-#define DOT_PRODUCT(a, b) btSimdDot3(a, b)
+#define DOT_PRODUCT(a, b) btSimdDot3(a, b)
#endif
#if USE_FMA
#if USE_FMA3_INSTEAD_FMA4
// a*b + c
-#define FMADD(a, b, c) _mm_fmadd_ps(a, b, c)
+#define FMADD(a, b, c) _mm_fmadd_ps(a, b, c)
// -(a*b) + c
-#define FMNADD(a, b, c) _mm_fnmadd_ps(a, b, c)
-#else // USE_FMA3
+#define FMNADD(a, b, c) _mm_fnmadd_ps(a, b, c)
+#else // USE_FMA3
// a*b + c
-#define FMADD(a, b, c) _mm_macc_ps(a, b, c)
+#define FMADD(a, b, c) _mm_macc_ps(a, b, c)
// -(a*b) + c
-#define FMNADD(a, b, c) _mm_nmacc_ps(a, b, c)
+#define FMNADD(a, b, c) _mm_nmacc_ps(a, b, c)
#endif
-#else // USE_FMA
+#else // USE_FMA
// c + a*b
-#define FMADD(a, b, c) _mm_add_ps(c, _mm_mul_ps(a, b))
+#define FMADD(a, b, c) _mm_add_ps(c, _mm_mul_ps(a, b))
// c - a*b
-#define FMNADD(a, b, c) _mm_sub_ps(c, _mm_mul_ps(a, b))
+#define FMNADD(a, b, c) _mm_sub_ps(c, _mm_mul_ps(a, b))
#endif
#endif
@@ -153,8 +148,8 @@ static inline __m128 btSimdDot3( __m128 vec0, __m128 vec1 )
static btScalar gResolveSingleConstraintRowGeneric_sse2(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
{
__m128 cpAppliedImp = _mm_set1_ps(c.m_appliedImpulse);
- __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
- __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
+ __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
+ __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
btSimdScalar deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhs), _mm_mul_ps(_mm_set1_ps(c.m_appliedImpulse), _mm_set1_ps(c.m_cfm)));
__m128 deltaVel1Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal1.mVec128, bodyA.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128, bodyA.internalGetDeltaAngularVelocity().mVec128));
__m128 deltaVel2Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal2.mVec128, bodyB.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos2CrossNormal.mVec128, bodyB.internalGetDeltaAngularVelocity().mVec128));
@@ -170,52 +165,49 @@ static btScalar gResolveSingleConstraintRowGeneric_sse2(btSolverBody& bodyA, btS
__m128 upperMinApplied = _mm_sub_ps(upperLimit1, cpAppliedImp);
deltaImpulse = _mm_or_ps(_mm_and_ps(resultUpperLess, deltaImpulse), _mm_andnot_ps(resultUpperLess, upperMinApplied));
c.m_appliedImpulse = _mm_or_ps(_mm_and_ps(resultUpperLess, c.m_appliedImpulse), _mm_andnot_ps(resultUpperLess, upperLimit1));
- __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal1.mVec128, bodyA.internalGetInvMass().mVec128);
- __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal2).mVec128, bodyB.internalGetInvMass().mVec128);
+ __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal1.mVec128, bodyA.internalGetInvMass().mVec128);
+ __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal2).mVec128, bodyB.internalGetInvMass().mVec128);
__m128 impulseMagnitude = deltaImpulse;
bodyA.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(bodyA.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentA, impulseMagnitude));
bodyA.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(bodyA.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentA.mVec128, impulseMagnitude));
bodyB.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(bodyB.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentB, impulseMagnitude));
bodyB.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(bodyB.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentB.mVec128, impulseMagnitude));
- return deltaImpulse.m_floats[0]/c.m_jacDiagABInv;
+ return deltaImpulse.m_floats[0] / c.m_jacDiagABInv;
}
-
// Enhanced version of gResolveSingleConstraintRowGeneric_sse2 with SSE4.1 and FMA3
static btScalar gResolveSingleConstraintRowGeneric_sse4_1_fma3(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
{
-#if defined (BT_ALLOW_SSE4)
- __m128 tmp = _mm_set_ps1(c.m_jacDiagABInv);
- __m128 deltaImpulse = _mm_set_ps1(c.m_rhs - btScalar(c.m_appliedImpulse)*c.m_cfm);
- const __m128 lowerLimit = _mm_set_ps1(c.m_lowerLimit);
- const __m128 upperLimit = _mm_set_ps1(c.m_upperLimit);
- const __m128 deltaVel1Dotn = _mm_add_ps(DOT_PRODUCT(c.m_contactNormal1.mVec128, bodyA.internalGetDeltaLinearVelocity().mVec128), DOT_PRODUCT(c.m_relpos1CrossNormal.mVec128, bodyA.internalGetDeltaAngularVelocity().mVec128));
- const __m128 deltaVel2Dotn = _mm_add_ps(DOT_PRODUCT(c.m_contactNormal2.mVec128, bodyB.internalGetDeltaLinearVelocity().mVec128), DOT_PRODUCT(c.m_relpos2CrossNormal.mVec128, bodyB.internalGetDeltaAngularVelocity().mVec128));
- deltaImpulse = FMNADD(deltaVel1Dotn, tmp, deltaImpulse);
- deltaImpulse = FMNADD(deltaVel2Dotn, tmp, deltaImpulse);
- tmp = _mm_add_ps(c.m_appliedImpulse, deltaImpulse); // sum
- const __m128 maskLower = _mm_cmpgt_ps(tmp, lowerLimit);
- const __m128 maskUpper = _mm_cmpgt_ps(upperLimit, tmp);
- deltaImpulse = _mm_blendv_ps(_mm_sub_ps(lowerLimit, c.m_appliedImpulse), _mm_blendv_ps(_mm_sub_ps(upperLimit, c.m_appliedImpulse), deltaImpulse, maskUpper), maskLower);
- c.m_appliedImpulse = _mm_blendv_ps(lowerLimit, _mm_blendv_ps(upperLimit, tmp, maskUpper), maskLower);
- bodyA.internalGetDeltaLinearVelocity().mVec128 = FMADD(_mm_mul_ps(c.m_contactNormal1.mVec128, bodyA.internalGetInvMass().mVec128), deltaImpulse, bodyA.internalGetDeltaLinearVelocity().mVec128);
+#if defined(BT_ALLOW_SSE4)
+ __m128 tmp = _mm_set_ps1(c.m_jacDiagABInv);
+ __m128 deltaImpulse = _mm_set_ps1(c.m_rhs - btScalar(c.m_appliedImpulse) * c.m_cfm);
+ const __m128 lowerLimit = _mm_set_ps1(c.m_lowerLimit);
+ const __m128 upperLimit = _mm_set_ps1(c.m_upperLimit);
+ const __m128 deltaVel1Dotn = _mm_add_ps(DOT_PRODUCT(c.m_contactNormal1.mVec128, bodyA.internalGetDeltaLinearVelocity().mVec128), DOT_PRODUCT(c.m_relpos1CrossNormal.mVec128, bodyA.internalGetDeltaAngularVelocity().mVec128));
+ const __m128 deltaVel2Dotn = _mm_add_ps(DOT_PRODUCT(c.m_contactNormal2.mVec128, bodyB.internalGetDeltaLinearVelocity().mVec128), DOT_PRODUCT(c.m_relpos2CrossNormal.mVec128, bodyB.internalGetDeltaAngularVelocity().mVec128));
+ deltaImpulse = FMNADD(deltaVel1Dotn, tmp, deltaImpulse);
+ deltaImpulse = FMNADD(deltaVel2Dotn, tmp, deltaImpulse);
+ tmp = _mm_add_ps(c.m_appliedImpulse, deltaImpulse); // sum
+ const __m128 maskLower = _mm_cmpgt_ps(tmp, lowerLimit);
+ const __m128 maskUpper = _mm_cmpgt_ps(upperLimit, tmp);
+ deltaImpulse = _mm_blendv_ps(_mm_sub_ps(lowerLimit, c.m_appliedImpulse), _mm_blendv_ps(_mm_sub_ps(upperLimit, c.m_appliedImpulse), deltaImpulse, maskUpper), maskLower);
+ c.m_appliedImpulse = _mm_blendv_ps(lowerLimit, _mm_blendv_ps(upperLimit, tmp, maskUpper), maskLower);
+ bodyA.internalGetDeltaLinearVelocity().mVec128 = FMADD(_mm_mul_ps(c.m_contactNormal1.mVec128, bodyA.internalGetInvMass().mVec128), deltaImpulse, bodyA.internalGetDeltaLinearVelocity().mVec128);
bodyA.internalGetDeltaAngularVelocity().mVec128 = FMADD(c.m_angularComponentA.mVec128, deltaImpulse, bodyA.internalGetDeltaAngularVelocity().mVec128);
- bodyB.internalGetDeltaLinearVelocity().mVec128 = FMADD(_mm_mul_ps(c.m_contactNormal2.mVec128, bodyB.internalGetInvMass().mVec128), deltaImpulse, bodyB.internalGetDeltaLinearVelocity().mVec128);
+ bodyB.internalGetDeltaLinearVelocity().mVec128 = FMADD(_mm_mul_ps(c.m_contactNormal2.mVec128, bodyB.internalGetInvMass().mVec128), deltaImpulse, bodyB.internalGetDeltaLinearVelocity().mVec128);
bodyB.internalGetDeltaAngularVelocity().mVec128 = FMADD(c.m_angularComponentB.mVec128, deltaImpulse, bodyB.internalGetDeltaAngularVelocity().mVec128);
btSimdScalar deltaImp = deltaImpulse;
- return deltaImp.m_floats[0]*(1./c.m_jacDiagABInv);
+ return deltaImp.m_floats[0] * (1. / c.m_jacDiagABInv);
#else
- return gResolveSingleConstraintRowGeneric_sse2(bodyA,bodyB,c);
+ return gResolveSingleConstraintRowGeneric_sse2(bodyA, bodyB, c);
#endif
}
-
-
static btScalar gResolveSingleConstraintRowLowerLimit_sse2(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
{
__m128 cpAppliedImp = _mm_set1_ps(c.m_appliedImpulse);
- __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
- __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
+ __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
+ __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
btSimdScalar deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhs), _mm_mul_ps(_mm_set1_ps(c.m_appliedImpulse), _mm_set1_ps(c.m_cfm)));
__m128 deltaVel1Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal1.mVec128, bodyA.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128, bodyA.internalGetDeltaAngularVelocity().mVec128));
__m128 deltaVel2Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal2.mVec128, bodyB.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos2CrossNormal.mVec128, bodyB.internalGetDeltaAngularVelocity().mVec128));
@@ -228,104 +220,98 @@ static btScalar gResolveSingleConstraintRowLowerLimit_sse2(btSolverBody& bodyA,
__m128 lowMinApplied = _mm_sub_ps(lowerLimit1, cpAppliedImp);
deltaImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse));
c.m_appliedImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum));
- __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal1.mVec128, bodyA.internalGetInvMass().mVec128);
- __m128 linearComponentB = _mm_mul_ps(c.m_contactNormal2.mVec128, bodyB.internalGetInvMass().mVec128);
+ __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal1.mVec128, bodyA.internalGetInvMass().mVec128);
+ __m128 linearComponentB = _mm_mul_ps(c.m_contactNormal2.mVec128, bodyB.internalGetInvMass().mVec128);
__m128 impulseMagnitude = deltaImpulse;
bodyA.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(bodyA.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentA, impulseMagnitude));
bodyA.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(bodyA.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentA.mVec128, impulseMagnitude));
bodyB.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(bodyB.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentB, impulseMagnitude));
bodyB.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(bodyB.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentB.mVec128, impulseMagnitude));
- return deltaImpulse.m_floats[0]/c.m_jacDiagABInv;
+ return deltaImpulse.m_floats[0] / c.m_jacDiagABInv;
}
-
// Enhanced version of gResolveSingleConstraintRowGeneric_sse2 with SSE4.1 and FMA3
static btScalar gResolveSingleConstraintRowLowerLimit_sse4_1_fma3(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
{
#ifdef BT_ALLOW_SSE4
- __m128 tmp = _mm_set_ps1(c.m_jacDiagABInv);
- __m128 deltaImpulse = _mm_set_ps1(c.m_rhs - btScalar(c.m_appliedImpulse)*c.m_cfm);
- const __m128 lowerLimit = _mm_set_ps1(c.m_lowerLimit);
- const __m128 deltaVel1Dotn = _mm_add_ps(DOT_PRODUCT(c.m_contactNormal1.mVec128, bodyA.internalGetDeltaLinearVelocity().mVec128), DOT_PRODUCT(c.m_relpos1CrossNormal.mVec128, bodyA.internalGetDeltaAngularVelocity().mVec128));
- const __m128 deltaVel2Dotn = _mm_add_ps(DOT_PRODUCT(c.m_contactNormal2.mVec128, bodyB.internalGetDeltaLinearVelocity().mVec128), DOT_PRODUCT(c.m_relpos2CrossNormal.mVec128, bodyB.internalGetDeltaAngularVelocity().mVec128));
- deltaImpulse = FMNADD(deltaVel1Dotn, tmp, deltaImpulse);
- deltaImpulse = FMNADD(deltaVel2Dotn, tmp, deltaImpulse);
- tmp = _mm_add_ps(c.m_appliedImpulse, deltaImpulse);
- const __m128 mask = _mm_cmpgt_ps(tmp, lowerLimit);
- deltaImpulse = _mm_blendv_ps(_mm_sub_ps(lowerLimit, c.m_appliedImpulse), deltaImpulse, mask);
- c.m_appliedImpulse = _mm_blendv_ps(lowerLimit, tmp, mask);
- bodyA.internalGetDeltaLinearVelocity().mVec128 = FMADD(_mm_mul_ps(c.m_contactNormal1.mVec128, bodyA.internalGetInvMass().mVec128), deltaImpulse, bodyA.internalGetDeltaLinearVelocity().mVec128);
+ __m128 tmp = _mm_set_ps1(c.m_jacDiagABInv);
+ __m128 deltaImpulse = _mm_set_ps1(c.m_rhs - btScalar(c.m_appliedImpulse) * c.m_cfm);
+ const __m128 lowerLimit = _mm_set_ps1(c.m_lowerLimit);
+ const __m128 deltaVel1Dotn = _mm_add_ps(DOT_PRODUCT(c.m_contactNormal1.mVec128, bodyA.internalGetDeltaLinearVelocity().mVec128), DOT_PRODUCT(c.m_relpos1CrossNormal.mVec128, bodyA.internalGetDeltaAngularVelocity().mVec128));
+ const __m128 deltaVel2Dotn = _mm_add_ps(DOT_PRODUCT(c.m_contactNormal2.mVec128, bodyB.internalGetDeltaLinearVelocity().mVec128), DOT_PRODUCT(c.m_relpos2CrossNormal.mVec128, bodyB.internalGetDeltaAngularVelocity().mVec128));
+ deltaImpulse = FMNADD(deltaVel1Dotn, tmp, deltaImpulse);
+ deltaImpulse = FMNADD(deltaVel2Dotn, tmp, deltaImpulse);
+ tmp = _mm_add_ps(c.m_appliedImpulse, deltaImpulse);
+ const __m128 mask = _mm_cmpgt_ps(tmp, lowerLimit);
+ deltaImpulse = _mm_blendv_ps(_mm_sub_ps(lowerLimit, c.m_appliedImpulse), deltaImpulse, mask);
+ c.m_appliedImpulse = _mm_blendv_ps(lowerLimit, tmp, mask);
+ bodyA.internalGetDeltaLinearVelocity().mVec128 = FMADD(_mm_mul_ps(c.m_contactNormal1.mVec128, bodyA.internalGetInvMass().mVec128), deltaImpulse, bodyA.internalGetDeltaLinearVelocity().mVec128);
bodyA.internalGetDeltaAngularVelocity().mVec128 = FMADD(c.m_angularComponentA.mVec128, deltaImpulse, bodyA.internalGetDeltaAngularVelocity().mVec128);
- bodyB.internalGetDeltaLinearVelocity().mVec128 = FMADD(_mm_mul_ps(c.m_contactNormal2.mVec128, bodyB.internalGetInvMass().mVec128), deltaImpulse, bodyB.internalGetDeltaLinearVelocity().mVec128);
+ bodyB.internalGetDeltaLinearVelocity().mVec128 = FMADD(_mm_mul_ps(c.m_contactNormal2.mVec128, bodyB.internalGetInvMass().mVec128), deltaImpulse, bodyB.internalGetDeltaLinearVelocity().mVec128);
bodyB.internalGetDeltaAngularVelocity().mVec128 = FMADD(c.m_angularComponentB.mVec128, deltaImpulse, bodyB.internalGetDeltaAngularVelocity().mVec128);
btSimdScalar deltaImp = deltaImpulse;
- return deltaImp.m_floats[0]*(1./c.m_jacDiagABInv);
+ return deltaImp.m_floats[0] * (1. / c.m_jacDiagABInv);
#else
- return gResolveSingleConstraintRowLowerLimit_sse2(bodyA,bodyB,c);
-#endif //BT_ALLOW_SSE4
+ return gResolveSingleConstraintRowLowerLimit_sse2(bodyA, bodyB, c);
+#endif //BT_ALLOW_SSE4
}
+#endif //USE_SIMD
-#endif //USE_SIMD
-
-
-
-btScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGenericSIMD(btSolverBody& bodyA,btSolverBody& bodyB,const btSolverConstraint& c)
+btScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGenericSIMD(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
{
return m_resolveSingleConstraintRowGeneric(bodyA, bodyB, c);
}
// Project Gauss Seidel or the equivalent Sequential Impulse
-btScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGeneric(btSolverBody& bodyA,btSolverBody& bodyB,const btSolverConstraint& c)
+btScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGeneric(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
{
return m_resolveSingleConstraintRowGeneric(bodyA, bodyB, c);
}
-btScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimitSIMD(btSolverBody& bodyA,btSolverBody& bodyB,const btSolverConstraint& c)
+btScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimitSIMD(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
{
return m_resolveSingleConstraintRowLowerLimit(bodyA, bodyB, c);
}
-
-btScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimit(btSolverBody& bodyA,btSolverBody& bodyB,const btSolverConstraint& c)
+btScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimit(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
{
return m_resolveSingleConstraintRowLowerLimit(bodyA, bodyB, c);
}
-
static btScalar gResolveSplitPenetrationImpulse_scalar_reference(
- btSolverBody& bodyA,
- btSolverBody& bodyB,
- const btSolverConstraint& c)
+ btSolverBody& bodyA,
+ btSolverBody& bodyB,
+ const btSolverConstraint& c)
{
btScalar deltaImpulse = 0.f;
- if (c.m_rhsPenetration)
- {
- gNumSplitImpulseRecoveries++;
- deltaImpulse = c.m_rhsPenetration-btScalar(c.m_appliedPushImpulse)*c.m_cfm;
- const btScalar deltaVel1Dotn = c.m_contactNormal1.dot(bodyA.internalGetPushVelocity()) + c.m_relpos1CrossNormal.dot(bodyA.internalGetTurnVelocity());
- const btScalar deltaVel2Dotn = c.m_contactNormal2.dot(bodyB.internalGetPushVelocity()) + c.m_relpos2CrossNormal.dot(bodyB.internalGetTurnVelocity());
-
- deltaImpulse -= deltaVel1Dotn*c.m_jacDiagABInv;
- deltaImpulse -= deltaVel2Dotn*c.m_jacDiagABInv;
- const btScalar sum = btScalar(c.m_appliedPushImpulse) + deltaImpulse;
- if (sum < c.m_lowerLimit)
- {
- deltaImpulse = c.m_lowerLimit-c.m_appliedPushImpulse;
- c.m_appliedPushImpulse = c.m_lowerLimit;
- }
- else
- {
- c.m_appliedPushImpulse = sum;
- }
- bodyA.internalApplyPushImpulse(c.m_contactNormal1*bodyA.internalGetInvMass(),c.m_angularComponentA,deltaImpulse);
- bodyB.internalApplyPushImpulse(c.m_contactNormal2*bodyB.internalGetInvMass(),c.m_angularComponentB,deltaImpulse);
- }
- return deltaImpulse*(1./c.m_jacDiagABInv);
+ if (c.m_rhsPenetration)
+ {
+ gNumSplitImpulseRecoveries++;
+ deltaImpulse = c.m_rhsPenetration - btScalar(c.m_appliedPushImpulse) * c.m_cfm;
+ const btScalar deltaVel1Dotn = c.m_contactNormal1.dot(bodyA.internalGetPushVelocity()) + c.m_relpos1CrossNormal.dot(bodyA.internalGetTurnVelocity());
+ const btScalar deltaVel2Dotn = c.m_contactNormal2.dot(bodyB.internalGetPushVelocity()) + c.m_relpos2CrossNormal.dot(bodyB.internalGetTurnVelocity());
+
+ deltaImpulse -= deltaVel1Dotn * c.m_jacDiagABInv;
+ deltaImpulse -= deltaVel2Dotn * c.m_jacDiagABInv;
+ const btScalar sum = btScalar(c.m_appliedPushImpulse) + deltaImpulse;
+ if (sum < c.m_lowerLimit)
+ {
+ deltaImpulse = c.m_lowerLimit - c.m_appliedPushImpulse;
+ c.m_appliedPushImpulse = c.m_lowerLimit;
+ }
+ else
+ {
+ c.m_appliedPushImpulse = sum;
+ }
+ bodyA.internalApplyPushImpulse(c.m_contactNormal1 * bodyA.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
+ bodyB.internalApplyPushImpulse(c.m_contactNormal2 * bodyB.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
+ }
+ return deltaImpulse * (1. / c.m_jacDiagABInv);
}
-static btScalar gResolveSplitPenetrationImpulse_sse2(btSolverBody& bodyA,btSolverBody& bodyB,const btSolverConstraint& c)
+static btScalar gResolveSplitPenetrationImpulse_sse2(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
{
#ifdef USE_SIMD
if (!c.m_rhsPenetration)
@@ -334,113 +320,109 @@ static btScalar gResolveSplitPenetrationImpulse_sse2(btSolverBody& bodyA,btSolve
gNumSplitImpulseRecoveries++;
__m128 cpAppliedImp = _mm_set1_ps(c.m_appliedPushImpulse);
- __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
- __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
- __m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhsPenetration), _mm_mul_ps(_mm_set1_ps(c.m_appliedPushImpulse),_mm_set1_ps(c.m_cfm)));
- __m128 deltaVel1Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal1.mVec128,bodyA.internalGetPushVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128,bodyA.internalGetTurnVelocity().mVec128));
- __m128 deltaVel2Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal2.mVec128,bodyB.internalGetPushVelocity().mVec128), btSimdDot3(c.m_relpos2CrossNormal.mVec128,bodyB.internalGetTurnVelocity().mVec128));
- deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel1Dotn,_mm_set1_ps(c.m_jacDiagABInv)));
- deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel2Dotn,_mm_set1_ps(c.m_jacDiagABInv)));
- btSimdScalar sum = _mm_add_ps(cpAppliedImp,deltaImpulse);
- btSimdScalar resultLowerLess,resultUpperLess;
- resultLowerLess = _mm_cmplt_ps(sum,lowerLimit1);
- resultUpperLess = _mm_cmplt_ps(sum,upperLimit1);
- __m128 lowMinApplied = _mm_sub_ps(lowerLimit1,cpAppliedImp);
- deltaImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse) );
- c.m_appliedPushImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum) );
- __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal1.mVec128,bodyA.internalGetInvMass().mVec128);
- __m128 linearComponentB = _mm_mul_ps(c.m_contactNormal2.mVec128,bodyB.internalGetInvMass().mVec128);
+ __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
+ __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
+ __m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhsPenetration), _mm_mul_ps(_mm_set1_ps(c.m_appliedPushImpulse), _mm_set1_ps(c.m_cfm)));
+ __m128 deltaVel1Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal1.mVec128, bodyA.internalGetPushVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128, bodyA.internalGetTurnVelocity().mVec128));
+ __m128 deltaVel2Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal2.mVec128, bodyB.internalGetPushVelocity().mVec128), btSimdDot3(c.m_relpos2CrossNormal.mVec128, bodyB.internalGetTurnVelocity().mVec128));
+ deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel1Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
+ deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel2Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
+ btSimdScalar sum = _mm_add_ps(cpAppliedImp, deltaImpulse);
+ btSimdScalar resultLowerLess, resultUpperLess;
+ resultLowerLess = _mm_cmplt_ps(sum, lowerLimit1);
+ resultUpperLess = _mm_cmplt_ps(sum, upperLimit1);
+ __m128 lowMinApplied = _mm_sub_ps(lowerLimit1, cpAppliedImp);
+ deltaImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse));
+ c.m_appliedPushImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum));
+ __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal1.mVec128, bodyA.internalGetInvMass().mVec128);
+ __m128 linearComponentB = _mm_mul_ps(c.m_contactNormal2.mVec128, bodyB.internalGetInvMass().mVec128);
__m128 impulseMagnitude = deltaImpulse;
- bodyA.internalGetPushVelocity().mVec128 = _mm_add_ps(bodyA.internalGetPushVelocity().mVec128,_mm_mul_ps(linearComponentA,impulseMagnitude));
- bodyA.internalGetTurnVelocity().mVec128 = _mm_add_ps(bodyA.internalGetTurnVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentA.mVec128,impulseMagnitude));
- bodyB.internalGetPushVelocity().mVec128 = _mm_add_ps(bodyB.internalGetPushVelocity().mVec128,_mm_mul_ps(linearComponentB,impulseMagnitude));
- bodyB.internalGetTurnVelocity().mVec128 = _mm_add_ps(bodyB.internalGetTurnVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentB.mVec128,impulseMagnitude));
+ bodyA.internalGetPushVelocity().mVec128 = _mm_add_ps(bodyA.internalGetPushVelocity().mVec128, _mm_mul_ps(linearComponentA, impulseMagnitude));
+ bodyA.internalGetTurnVelocity().mVec128 = _mm_add_ps(bodyA.internalGetTurnVelocity().mVec128, _mm_mul_ps(c.m_angularComponentA.mVec128, impulseMagnitude));
+ bodyB.internalGetPushVelocity().mVec128 = _mm_add_ps(bodyB.internalGetPushVelocity().mVec128, _mm_mul_ps(linearComponentB, impulseMagnitude));
+ bodyB.internalGetTurnVelocity().mVec128 = _mm_add_ps(bodyB.internalGetTurnVelocity().mVec128, _mm_mul_ps(c.m_angularComponentB.mVec128, impulseMagnitude));
btSimdScalar deltaImp = deltaImpulse;
return deltaImp.m_floats[0] * (1. / c.m_jacDiagABInv);
#else
- return gResolveSplitPenetrationImpulse_scalar_reference(bodyA,bodyB,c);
+ return gResolveSplitPenetrationImpulse_scalar_reference(bodyA, bodyB, c);
#endif
}
-
btSequentialImpulseConstraintSolver::btSequentialImpulseConstraintSolver()
{
- m_btSeed2 = 0;
- m_cachedSolverMode = 0;
- setupSolverFunctions( false );
+ m_btSeed2 = 0;
+ m_cachedSolverMode = 0;
+ setupSolverFunctions(false);
}
-void btSequentialImpulseConstraintSolver::setupSolverFunctions( bool useSimd )
+void btSequentialImpulseConstraintSolver::setupSolverFunctions(bool useSimd)
{
- m_resolveSingleConstraintRowGeneric = gResolveSingleConstraintRowGeneric_scalar_reference;
- m_resolveSingleConstraintRowLowerLimit = gResolveSingleConstraintRowLowerLimit_scalar_reference;
- m_resolveSplitPenetrationImpulse = gResolveSplitPenetrationImpulse_scalar_reference;
+ m_resolveSingleConstraintRowGeneric = gResolveSingleConstraintRowGeneric_scalar_reference;
+ m_resolveSingleConstraintRowLowerLimit = gResolveSingleConstraintRowLowerLimit_scalar_reference;
+ m_resolveSplitPenetrationImpulse = gResolveSplitPenetrationImpulse_scalar_reference;
- if ( useSimd )
- {
+ if (useSimd)
+ {
#ifdef USE_SIMD
- m_resolveSingleConstraintRowGeneric = gResolveSingleConstraintRowGeneric_sse2;
- m_resolveSingleConstraintRowLowerLimit = gResolveSingleConstraintRowLowerLimit_sse2;
- m_resolveSplitPenetrationImpulse = gResolveSplitPenetrationImpulse_sse2;
+ m_resolveSingleConstraintRowGeneric = gResolveSingleConstraintRowGeneric_sse2;
+ m_resolveSingleConstraintRowLowerLimit = gResolveSingleConstraintRowLowerLimit_sse2;
+ m_resolveSplitPenetrationImpulse = gResolveSplitPenetrationImpulse_sse2;
#ifdef BT_ALLOW_SSE4
- int cpuFeatures = btCpuFeatureUtility::getCpuFeatures();
- if ((cpuFeatures & btCpuFeatureUtility::CPU_FEATURE_FMA3) && (cpuFeatures & btCpuFeatureUtility::CPU_FEATURE_SSE4_1))
- {
- m_resolveSingleConstraintRowGeneric = gResolveSingleConstraintRowGeneric_sse4_1_fma3;
- m_resolveSingleConstraintRowLowerLimit = gResolveSingleConstraintRowLowerLimit_sse4_1_fma3;
- }
-#endif//BT_ALLOW_SSE4
-#endif //USE_SIMD
- }
+ int cpuFeatures = btCpuFeatureUtility::getCpuFeatures();
+ if ((cpuFeatures & btCpuFeatureUtility::CPU_FEATURE_FMA3) && (cpuFeatures & btCpuFeatureUtility::CPU_FEATURE_SSE4_1))
+ {
+ m_resolveSingleConstraintRowGeneric = gResolveSingleConstraintRowGeneric_sse4_1_fma3;
+ m_resolveSingleConstraintRowLowerLimit = gResolveSingleConstraintRowLowerLimit_sse4_1_fma3;
+ }
+#endif //BT_ALLOW_SSE4
+#endif //USE_SIMD
+ }
}
- btSequentialImpulseConstraintSolver::~btSequentialImpulseConstraintSolver()
- {
- }
-
- btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getScalarConstraintRowSolverGeneric()
- {
- return gResolveSingleConstraintRowGeneric_scalar_reference;
- }
+btSequentialImpulseConstraintSolver::~btSequentialImpulseConstraintSolver()
+{
+}
- btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getScalarConstraintRowSolverLowerLimit()
- {
- return gResolveSingleConstraintRowLowerLimit_scalar_reference;
- }
+btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getScalarConstraintRowSolverGeneric()
+{
+ return gResolveSingleConstraintRowGeneric_scalar_reference;
+}
+btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getScalarConstraintRowSolverLowerLimit()
+{
+ return gResolveSingleConstraintRowLowerLimit_scalar_reference;
+}
#ifdef USE_SIMD
- btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE2ConstraintRowSolverGeneric()
- {
- return gResolveSingleConstraintRowGeneric_sse2;
- }
- btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE2ConstraintRowSolverLowerLimit()
- {
- return gResolveSingleConstraintRowLowerLimit_sse2;
- }
+btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE2ConstraintRowSolverGeneric()
+{
+ return gResolveSingleConstraintRowGeneric_sse2;
+}
+btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE2ConstraintRowSolverLowerLimit()
+{
+ return gResolveSingleConstraintRowLowerLimit_sse2;
+}
#ifdef BT_ALLOW_SSE4
- btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE4_1ConstraintRowSolverGeneric()
- {
- return gResolveSingleConstraintRowGeneric_sse4_1_fma3;
- }
- btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE4_1ConstraintRowSolverLowerLimit()
- {
- return gResolveSingleConstraintRowLowerLimit_sse4_1_fma3;
- }
-#endif //BT_ALLOW_SSE4
-#endif //USE_SIMD
+btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE4_1ConstraintRowSolverGeneric()
+{
+ return gResolveSingleConstraintRowGeneric_sse4_1_fma3;
+}
+btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE4_1ConstraintRowSolverLowerLimit()
+{
+ return gResolveSingleConstraintRowLowerLimit_sse4_1_fma3;
+}
+#endif //BT_ALLOW_SSE4
+#endif //USE_SIMD
unsigned long btSequentialImpulseConstraintSolver::btRand2()
{
- m_btSeed2 = (1664525L*m_btSeed2 + 1013904223L) & 0xffffffff;
+ m_btSeed2 = (1664525L * m_btSeed2 + 1013904223L) & 0xffffffff;
return m_btSeed2;
}
-
-
//See ODE: adam's all-int straightforward(?) dRandInt (0..n-1)
-int btSequentialImpulseConstraintSolver::btRandInt2 (int n)
+int btSequentialImpulseConstraintSolver::btRandInt2(int n)
{
// seems good; xor-fold and modulus
const unsigned long un = static_cast<unsigned long>(n);
@@ -448,15 +430,20 @@ int btSequentialImpulseConstraintSolver::btRandInt2 (int n)
// 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) {
+ if (un <= 0x00010000UL)
+ {
r ^= (r >> 16);
- if (un <= 0x00000100UL) {
+ if (un <= 0x00000100UL)
+ {
r ^= (r >> 8);
- if (un <= 0x00000010UL) {
+ if (un <= 0x00000010UL)
+ {
r ^= (r >> 4);
- if (un <= 0x00000004UL) {
+ if (un <= 0x00000004UL)
+ {
r ^= (r >> 2);
- if (un <= 0x00000002UL) {
+ if (un <= 0x00000002UL)
+ {
r ^= (r >> 1);
}
}
@@ -464,70 +451,56 @@ int btSequentialImpulseConstraintSolver::btRandInt2 (int n)
}
}
- return (int) (r % un);
+ return (int)(r % un);
}
-
-
-void btSequentialImpulseConstraintSolver::initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject, btScalar timeStep)
+void btSequentialImpulseConstraintSolver::initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject, btScalar timeStep)
{
+ btRigidBody* rb = collisionObject ? btRigidBody::upcast(collisionObject) : 0;
- btRigidBody* rb = collisionObject? btRigidBody::upcast(collisionObject) : 0;
-
- solverBody->internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
- solverBody->internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f);
- solverBody->internalGetPushVelocity().setValue(0.f,0.f,0.f);
- solverBody->internalGetTurnVelocity().setValue(0.f,0.f,0.f);
+ solverBody->internalGetDeltaLinearVelocity().setValue(0.f, 0.f, 0.f);
+ solverBody->internalGetDeltaAngularVelocity().setValue(0.f, 0.f, 0.f);
+ solverBody->internalGetPushVelocity().setValue(0.f, 0.f, 0.f);
+ solverBody->internalGetTurnVelocity().setValue(0.f, 0.f, 0.f);
if (rb)
{
solverBody->m_worldTransform = rb->getWorldTransform();
- solverBody->internalSetInvMass(btVector3(rb->getInvMass(),rb->getInvMass(),rb->getInvMass())*rb->getLinearFactor());
+ solverBody->internalSetInvMass(btVector3(rb->getInvMass(), rb->getInvMass(), rb->getInvMass()) * rb->getLinearFactor());
solverBody->m_originalBody = rb;
solverBody->m_angularFactor = rb->getAngularFactor();
solverBody->m_linearFactor = rb->getLinearFactor();
solverBody->m_linearVelocity = rb->getLinearVelocity();
solverBody->m_angularVelocity = rb->getAngularVelocity();
- solverBody->m_externalForceImpulse = rb->getTotalForce()*rb->getInvMass()*timeStep;
- solverBody->m_externalTorqueImpulse = rb->getTotalTorque()*rb->getInvInertiaTensorWorld()*timeStep ;
-
- } else
+ solverBody->m_externalForceImpulse = rb->getTotalForce() * rb->getInvMass() * timeStep;
+ solverBody->m_externalTorqueImpulse = rb->getTotalTorque() * rb->getInvInertiaTensorWorld() * timeStep;
+ }
+ else
{
solverBody->m_worldTransform.setIdentity();
- solverBody->internalSetInvMass(btVector3(0,0,0));
+ solverBody->internalSetInvMass(btVector3(0, 0, 0));
solverBody->m_originalBody = 0;
- solverBody->m_angularFactor.setValue(1,1,1);
- solverBody->m_linearFactor.setValue(1,1,1);
- solverBody->m_linearVelocity.setValue(0,0,0);
- solverBody->m_angularVelocity.setValue(0,0,0);
- solverBody->m_externalForceImpulse.setValue(0,0,0);
- solverBody->m_externalTorqueImpulse.setValue(0,0,0);
+ solverBody->m_angularFactor.setValue(1, 1, 1);
+ solverBody->m_linearFactor.setValue(1, 1, 1);
+ solverBody->m_linearVelocity.setValue(0, 0, 0);
+ solverBody->m_angularVelocity.setValue(0, 0, 0);
+ solverBody->m_externalForceImpulse.setValue(0, 0, 0);
+ solverBody->m_externalTorqueImpulse.setValue(0, 0, 0);
}
-
-
}
-
-
-
-
-
btScalar btSequentialImpulseConstraintSolver::restitutionCurve(btScalar rel_vel, btScalar restitution, btScalar velocityThreshold)
{
//printf("rel_vel =%f\n", rel_vel);
- if (btFabs(rel_vel)<velocityThreshold)
+ if (btFabs(rel_vel) < velocityThreshold)
return 0.;
btScalar rest = restitution * -rel_vel;
return rest;
}
-
-
-void btSequentialImpulseConstraintSolver::applyAnisotropicFriction(btCollisionObject* colObj,btVector3& frictionDirection, int frictionMode)
+void btSequentialImpulseConstraintSolver::applyAnisotropicFriction(btCollisionObject* colObj, btVector3& frictionDirection, int frictionMode)
{
-
-
if (colObj && colObj->hasAnisotropicFriction(frictionMode))
{
// transform to local coordinates
@@ -538,16 +511,10 @@ void btSequentialImpulseConstraintSolver::applyAnisotropicFriction(btCollisionOb
// ... and transform it back to global coordinates
frictionDirection = colObj->getWorldTransform().getBasis() * loc_lateral;
}
-
}
-
-
-
-void btSequentialImpulseConstraintSolver::setupFrictionConstraint(btSolverConstraint& solverConstraint, const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
+void btSequentialImpulseConstraintSolver::setupFrictionConstraint(btSolverConstraint& solverConstraint, const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, btManifoldPoint& cp, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
{
-
-
btSolverBody& solverBodyA = m_tmpSolverBodyPool[solverBodyIdA];
btSolverBody& solverBodyB = m_tmpSolverBodyPool[solverBodyIdB];
@@ -568,12 +535,13 @@ void btSequentialImpulseConstraintSolver::setupFrictionConstraint(btSolverConstr
solverConstraint.m_contactNormal1 = normalAxis;
btVector3 ftorqueAxis1 = rel_pos1.cross(solverConstraint.m_contactNormal1);
solverConstraint.m_relpos1CrossNormal = ftorqueAxis1;
- solverConstraint.m_angularComponentA = body0->getInvInertiaTensorWorld()*ftorqueAxis1*body0->getAngularFactor();
- }else
+ solverConstraint.m_angularComponentA = body0->getInvInertiaTensorWorld() * ftorqueAxis1 * body0->getAngularFactor();
+ }
+ else
{
solverConstraint.m_contactNormal1.setZero();
solverConstraint.m_relpos1CrossNormal.setZero();
- solverConstraint.m_angularComponentA .setZero();
+ solverConstraint.m_angularComponentA.setZero();
}
if (bodyA)
@@ -581,8 +549,9 @@ void btSequentialImpulseConstraintSolver::setupFrictionConstraint(btSolverConstr
solverConstraint.m_contactNormal2 = -normalAxis;
btVector3 ftorqueAxis1 = rel_pos2.cross(solverConstraint.m_contactNormal2);
solverConstraint.m_relpos2CrossNormal = ftorqueAxis1;
- solverConstraint.m_angularComponentB = bodyA->getInvInertiaTensorWorld()*ftorqueAxis1*bodyA->getAngularFactor();
- } else
+ solverConstraint.m_angularComponentB = bodyA->getInvInertiaTensorWorld() * ftorqueAxis1 * bodyA->getAngularFactor();
+ }
+ else
{
solverConstraint.m_contactNormal2.setZero();
solverConstraint.m_relpos2CrossNormal.setZero();
@@ -595,32 +564,28 @@ void btSequentialImpulseConstraintSolver::setupFrictionConstraint(btSolverConstr
btScalar denom1 = 0.f;
if (body0)
{
- vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1);
+ vec = (solverConstraint.m_angularComponentA).cross(rel_pos1);
denom0 = body0->getInvMass() + normalAxis.dot(vec);
}
if (bodyA)
{
- vec = ( -solverConstraint.m_angularComponentB).cross(rel_pos2);
+ vec = (-solverConstraint.m_angularComponentB).cross(rel_pos2);
denom1 = bodyA->getInvMass() + normalAxis.dot(vec);
}
- btScalar denom = relaxation/(denom0+denom1);
+ btScalar denom = relaxation / (denom0 + denom1);
solverConstraint.m_jacDiagABInv = denom;
}
{
-
-
btScalar rel_vel;
- btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(body0?solverBodyA.m_linearVelocity+solverBodyA.m_externalForceImpulse:btVector3(0,0,0))
- + solverConstraint.m_relpos1CrossNormal.dot(body0?solverBodyA.m_angularVelocity:btVector3(0,0,0));
- btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(bodyA?solverBodyB.m_linearVelocity+solverBodyB.m_externalForceImpulse:btVector3(0,0,0))
- + solverConstraint.m_relpos2CrossNormal.dot(bodyA?solverBodyB.m_angularVelocity:btVector3(0,0,0));
+ btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(body0 ? solverBodyA.m_linearVelocity + solverBodyA.m_externalForceImpulse : btVector3(0, 0, 0)) + solverConstraint.m_relpos1CrossNormal.dot(body0 ? solverBodyA.m_angularVelocity : btVector3(0, 0, 0));
+ btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(bodyA ? solverBodyB.m_linearVelocity + solverBodyB.m_externalForceImpulse : btVector3(0, 0, 0)) + solverConstraint.m_relpos2CrossNormal.dot(bodyA ? solverBodyB.m_angularVelocity : btVector3(0, 0, 0));
- rel_vel = vel1Dotn+vel2Dotn;
+ rel_vel = vel1Dotn + vel2Dotn;
-// btScalar positionalError = 0.f;
+ // btScalar positionalError = 0.f;
- btScalar velocityError = desiredVelocity - rel_vel;
+ btScalar velocityError = desiredVelocity - rel_vel;
btScalar velocityImpulse = velocityError * solverConstraint.m_jacDiagABInv;
btScalar penetrationImpulse = btScalar(0);
@@ -628,8 +593,8 @@ void btSequentialImpulseConstraintSolver::setupFrictionConstraint(btSolverConstr
if (cp.m_contactPointFlags & BT_CONTACT_FLAG_FRICTION_ANCHOR)
{
btScalar distance = (cp.getPositionWorldOnA() - cp.getPositionWorldOnB()).dot(normalAxis);
- btScalar positionalError = -distance * infoGlobal.m_frictionERP/infoGlobal.m_timeStep;
- penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv;
+ btScalar positionalError = -distance * infoGlobal.m_frictionERP / infoGlobal.m_timeStep;
+ penetrationImpulse = positionalError * solverConstraint.m_jacDiagABInv;
}
solverConstraint.m_rhs = penetrationImpulse + velocityImpulse;
@@ -637,11 +602,10 @@ void btSequentialImpulseConstraintSolver::setupFrictionConstraint(btSolverConstr
solverConstraint.m_cfm = cfmSlip;
solverConstraint.m_lowerLimit = -solverConstraint.m_friction;
solverConstraint.m_upperLimit = solverConstraint.m_friction;
-
}
}
-btSolverConstraint& btSequentialImpulseConstraintSolver::addFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
+btSolverConstraint& btSequentialImpulseConstraintSolver::addFrictionConstraint(const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, btManifoldPoint& cp, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
{
btSolverConstraint& solverConstraint = m_tmpSolverContactFrictionConstraintPool.expandNonInitializing();
solverConstraint.m_frictionIndex = frictionIndex;
@@ -650,15 +614,13 @@ btSolverConstraint& btSequentialImpulseConstraintSolver::addFrictionConstraint(c
return solverConstraint;
}
-
-void btSequentialImpulseConstraintSolver::setupTorsionalFrictionConstraint( btSolverConstraint& solverConstraint, const btVector3& normalAxis1,int solverBodyIdA,int solverBodyIdB,
- btManifoldPoint& cp,btScalar combinedTorsionalFriction, const btVector3& rel_pos1,const btVector3& rel_pos2,
- btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation,
- btScalar desiredVelocity, btScalar cfmSlip)
+void btSequentialImpulseConstraintSolver::setupTorsionalFrictionConstraint(btSolverConstraint& solverConstraint, const btVector3& normalAxis1, int solverBodyIdA, int solverBodyIdB,
+ btManifoldPoint& cp, btScalar combinedTorsionalFriction, const btVector3& rel_pos1, const btVector3& rel_pos2,
+ btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation,
+ btScalar desiredVelocity, btScalar cfmSlip)
{
- btVector3 normalAxis(0,0,0);
-
+ btVector3 normalAxis(0, 0, 0);
solverConstraint.m_contactNormal1 = normalAxis;
solverConstraint.m_contactNormal2 = -normalAxis;
@@ -671,8 +633,8 @@ void btSequentialImpulseConstraintSolver::setupTorsionalFrictionConstraint( btSo
solverConstraint.m_solverBodyIdA = solverBodyIdA;
solverConstraint.m_solverBodyIdB = solverBodyIdB;
- solverConstraint.m_friction = combinedTorsionalFriction;
- solverConstraint.m_originalContactPoint = 0;
+ solverConstraint.m_friction = combinedTorsionalFriction;
+ solverConstraint.m_originalContactPoint = 0;
solverConstraint.m_appliedImpulse = 0.f;
solverConstraint.m_appliedPushImpulse = 0.f;
@@ -680,138 +642,125 @@ void btSequentialImpulseConstraintSolver::setupTorsionalFrictionConstraint( btSo
{
btVector3 ftorqueAxis1 = -normalAxis1;
solverConstraint.m_relpos1CrossNormal = ftorqueAxis1;
- solverConstraint.m_angularComponentA = body0 ? body0->getInvInertiaTensorWorld()*ftorqueAxis1*body0->getAngularFactor() : btVector3(0,0,0);
+ solverConstraint.m_angularComponentA = body0 ? body0->getInvInertiaTensorWorld() * ftorqueAxis1 * body0->getAngularFactor() : btVector3(0, 0, 0);
}
{
btVector3 ftorqueAxis1 = normalAxis1;
solverConstraint.m_relpos2CrossNormal = ftorqueAxis1;
- solverConstraint.m_angularComponentB = bodyA ? bodyA->getInvInertiaTensorWorld()*ftorqueAxis1*bodyA->getAngularFactor() : btVector3(0,0,0);
+ solverConstraint.m_angularComponentB = bodyA ? bodyA->getInvInertiaTensorWorld() * ftorqueAxis1 * bodyA->getAngularFactor() : btVector3(0, 0, 0);
}
-
{
- btVector3 iMJaA = body0?body0->getInvInertiaTensorWorld()*solverConstraint.m_relpos1CrossNormal:btVector3(0,0,0);
- btVector3 iMJaB = bodyA?bodyA->getInvInertiaTensorWorld()*solverConstraint.m_relpos2CrossNormal:btVector3(0,0,0);
+ btVector3 iMJaA = body0 ? body0->getInvInertiaTensorWorld() * solverConstraint.m_relpos1CrossNormal : btVector3(0, 0, 0);
+ btVector3 iMJaB = bodyA ? bodyA->getInvInertiaTensorWorld() * solverConstraint.m_relpos2CrossNormal : btVector3(0, 0, 0);
btScalar sum = 0;
sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
- solverConstraint.m_jacDiagABInv = btScalar(1.)/sum;
+ solverConstraint.m_jacDiagABInv = btScalar(1.) / sum;
}
{
-
-
btScalar rel_vel;
- btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(body0?solverBodyA.m_linearVelocity+solverBodyA.m_externalForceImpulse:btVector3(0,0,0))
- + solverConstraint.m_relpos1CrossNormal.dot(body0?solverBodyA.m_angularVelocity:btVector3(0,0,0));
- btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(bodyA?solverBodyB.m_linearVelocity+solverBodyB.m_externalForceImpulse:btVector3(0,0,0))
- + solverConstraint.m_relpos2CrossNormal.dot(bodyA?solverBodyB.m_angularVelocity:btVector3(0,0,0));
+ btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(body0 ? solverBodyA.m_linearVelocity + solverBodyA.m_externalForceImpulse : btVector3(0, 0, 0)) + solverConstraint.m_relpos1CrossNormal.dot(body0 ? solverBodyA.m_angularVelocity : btVector3(0, 0, 0));
+ btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(bodyA ? solverBodyB.m_linearVelocity + solverBodyB.m_externalForceImpulse : btVector3(0, 0, 0)) + solverConstraint.m_relpos2CrossNormal.dot(bodyA ? solverBodyB.m_angularVelocity : btVector3(0, 0, 0));
- rel_vel = vel1Dotn+vel2Dotn;
+ rel_vel = vel1Dotn + vel2Dotn;
-// btScalar positionalError = 0.f;
+ // btScalar positionalError = 0.f;
- btSimdScalar velocityError = desiredVelocity - rel_vel;
- btSimdScalar velocityImpulse = velocityError * btSimdScalar(solverConstraint.m_jacDiagABInv);
+ btSimdScalar velocityError = desiredVelocity - rel_vel;
+ btSimdScalar velocityImpulse = velocityError * btSimdScalar(solverConstraint.m_jacDiagABInv);
solverConstraint.m_rhs = velocityImpulse;
solverConstraint.m_cfm = cfmSlip;
solverConstraint.m_lowerLimit = -solverConstraint.m_friction;
solverConstraint.m_upperLimit = solverConstraint.m_friction;
-
}
}
-
-
-
-
-
-
-
-btSolverConstraint& btSequentialImpulseConstraintSolver::addTorsionalFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,btScalar combinedTorsionalFriction, const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity, btScalar cfmSlip)
+btSolverConstraint& btSequentialImpulseConstraintSolver::addTorsionalFrictionConstraint(const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, btManifoldPoint& cp, btScalar combinedTorsionalFriction, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity, btScalar cfmSlip)
{
btSolverConstraint& solverConstraint = m_tmpSolverContactRollingFrictionConstraintPool.expandNonInitializing();
solverConstraint.m_frictionIndex = frictionIndex;
- setupTorsionalFrictionConstraint(solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, combinedTorsionalFriction,rel_pos1, rel_pos2,
- colObj0, colObj1, relaxation, desiredVelocity, cfmSlip);
+ setupTorsionalFrictionConstraint(solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, combinedTorsionalFriction, rel_pos1, rel_pos2,
+ colObj0, colObj1, relaxation, desiredVelocity, cfmSlip);
return solverConstraint;
}
-
-int btSequentialImpulseConstraintSolver::getOrInitSolverBody(btCollisionObject& body,btScalar timeStep)
+int btSequentialImpulseConstraintSolver::getOrInitSolverBody(btCollisionObject& body, btScalar timeStep)
{
#if BT_THREADSAFE
- int solverBodyId = -1;
- bool isRigidBodyType = btRigidBody::upcast( &body ) != NULL;
- if ( isRigidBodyType && !body.isStaticOrKinematicObject() )
- {
- // dynamic body
- // Dynamic bodies can only be in one island, so it's safe to write to the companionId
- solverBodyId = body.getCompanionId();
- if ( solverBodyId < 0 )
- {
- solverBodyId = m_tmpSolverBodyPool.size();
- btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
- initSolverBody( &solverBody, &body, timeStep );
- body.setCompanionId( solverBodyId );
- }
- }
- else if (isRigidBodyType && body.isKinematicObject())
- {
- //
- // NOTE: must test for kinematic before static because some kinematic objects also
- // identify as "static"
- //
- // Kinematic bodies can be in multiple islands at once, so it is a
- // race condition to write to them, so we use an alternate method
- // to record the solverBodyId
- int uniqueId = body.getWorldArrayIndex();
- const int INVALID_SOLVER_BODY_ID = -1;
- if (uniqueId >= m_kinematicBodyUniqueIdToSolverBodyTable.size())
- {
- m_kinematicBodyUniqueIdToSolverBodyTable.resize(uniqueId + 1, INVALID_SOLVER_BODY_ID);
- }
- solverBodyId = m_kinematicBodyUniqueIdToSolverBodyTable[ uniqueId ];
- // if no table entry yet,
- if ( solverBodyId == INVALID_SOLVER_BODY_ID )
- {
- // create a table entry for this body
- solverBodyId = m_tmpSolverBodyPool.size();
- btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
- initSolverBody( &solverBody, &body, timeStep );
- m_kinematicBodyUniqueIdToSolverBodyTable[ uniqueId ] = solverBodyId;
- }
- }
- else
- {
- bool isMultiBodyType = (body.getInternalType()&btCollisionObject::CO_FEATHERSTONE_LINK);
- // Incorrectly set collision object flags can degrade performance in various ways.
+ int solverBodyId = -1;
+ bool isRigidBodyType = btRigidBody::upcast(&body) != NULL;
+ if (isRigidBodyType && !body.isStaticOrKinematicObject())
+ {
+ // dynamic body
+ // Dynamic bodies can only be in one island, so it's safe to write to the companionId
+ solverBodyId = body.getCompanionId();
+ if (solverBodyId < 0)
+ {
+ solverBodyId = m_tmpSolverBodyPool.size();
+ btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
+ initSolverBody(&solverBody, &body, timeStep);
+ body.setCompanionId(solverBodyId);
+ }
+ }
+ else if (isRigidBodyType && body.isKinematicObject())
+ {
+ //
+ // NOTE: must test for kinematic before static because some kinematic objects also
+ // identify as "static"
+ //
+ // Kinematic bodies can be in multiple islands at once, so it is a
+ // race condition to write to them, so we use an alternate method
+ // to record the solverBodyId
+ int uniqueId = body.getWorldArrayIndex();
+ const int INVALID_SOLVER_BODY_ID = -1;
+ if (uniqueId >= m_kinematicBodyUniqueIdToSolverBodyTable.size())
+ {
+ m_kinematicBodyUniqueIdToSolverBodyTable.resize(uniqueId + 1, INVALID_SOLVER_BODY_ID);
+ }
+ solverBodyId = m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId];
+ // if no table entry yet,
+ if (solverBodyId == INVALID_SOLVER_BODY_ID)
+ {
+ // create a table entry for this body
+ solverBodyId = m_tmpSolverBodyPool.size();
+ btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
+ initSolverBody(&solverBody, &body, timeStep);
+ m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId] = solverBodyId;
+ }
+ }
+ else
+ {
+ bool isMultiBodyType = (body.getInternalType() & btCollisionObject::CO_FEATHERSTONE_LINK);
+ // Incorrectly set collision object flags can degrade performance in various ways.
if (!isMultiBodyType)
{
- btAssert( body.isStaticOrKinematicObject() );
+ btAssert(body.isStaticOrKinematicObject());
}
- //it could be a multibody link collider
- // all fixed bodies (inf mass) get mapped to a single solver id
- if ( m_fixedBodyId < 0 )
- {
- m_fixedBodyId = m_tmpSolverBodyPool.size();
- btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
- initSolverBody( &fixedBody, 0, timeStep );
- }
- solverBodyId = m_fixedBodyId;
- }
- btAssert( solverBodyId >= 0 && solverBodyId < m_tmpSolverBodyPool.size() );
+ //it could be a multibody link collider
+ // all fixed bodies (inf mass) get mapped to a single solver id
+ if (m_fixedBodyId < 0)
+ {
+ m_fixedBodyId = m_tmpSolverBodyPool.size();
+ btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
+ initSolverBody(&fixedBody, 0, timeStep);
+ }
+ solverBodyId = m_fixedBodyId;
+ }
+ btAssert(solverBodyId >= 0 && solverBodyId < m_tmpSolverBodyPool.size());
return solverBodyId;
-#else // BT_THREADSAFE
+#else // BT_THREADSAFE
- int solverBodyIdA = -1;
+ int solverBodyIdA = -1;
if (body.getCompanionId() >= 0)
{
//body has already been converted
solverBodyIdA = body.getCompanionId();
- btAssert(solverBodyIdA < m_tmpSolverBodyPool.size());
- } else
+ btAssert(solverBodyIdA < m_tmpSolverBodyPool.size());
+ }
+ else
{
btRigidBody* rb = btRigidBody::upcast(&body);
//convert both active and kinematic objects (for their velocity)
@@ -819,233 +768,216 @@ int btSequentialImpulseConstraintSolver::getOrInitSolverBody(btCollisionObject&
{
solverBodyIdA = m_tmpSolverBodyPool.size();
btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
- initSolverBody(&solverBody,&body,timeStep);
+ initSolverBody(&solverBody, &body, timeStep);
body.setCompanionId(solverBodyIdA);
- } else
+ }
+ else
{
-
- if (m_fixedBodyId<0)
+ if (m_fixedBodyId < 0)
{
m_fixedBodyId = m_tmpSolverBodyPool.size();
btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
- initSolverBody(&fixedBody,0,timeStep);
+ initSolverBody(&fixedBody, 0, timeStep);
}
return m_fixedBodyId;
-// return 0;//assume first one is a fixed solver body
+ // return 0;//assume first one is a fixed solver body
}
}
return solverBodyIdA;
-#endif // BT_THREADSAFE
-
+#endif // BT_THREADSAFE
}
#include <stdio.h>
-
void btSequentialImpulseConstraintSolver::setupContactConstraint(btSolverConstraint& solverConstraint,
int solverBodyIdA, int solverBodyIdB,
btManifoldPoint& cp, const btContactSolverInfo& infoGlobal,
btScalar& relaxation,
const btVector3& rel_pos1, const btVector3& rel_pos2)
{
+ // const btVector3& pos1 = cp.getPositionWorldOnA();
+ // const btVector3& pos2 = cp.getPositionWorldOnB();
- // const btVector3& pos1 = cp.getPositionWorldOnA();
- // const btVector3& pos2 = cp.getPositionWorldOnB();
-
- btSolverBody* bodyA = &m_tmpSolverBodyPool[solverBodyIdA];
- btSolverBody* bodyB = &m_tmpSolverBodyPool[solverBodyIdB];
-
- btRigidBody* rb0 = bodyA->m_originalBody;
- btRigidBody* rb1 = bodyB->m_originalBody;
-
-// btVector3 rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin();
-// btVector3 rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin();
- //rel_pos1 = pos1 - bodyA->getWorldTransform().getOrigin();
- //rel_pos2 = pos2 - bodyB->getWorldTransform().getOrigin();
-
- relaxation = infoGlobal.m_sor;
- btScalar invTimeStep = btScalar(1)/infoGlobal.m_timeStep;
-
- //cfm = 1 / ( dt * kp + kd )
- //erp = dt * kp / ( dt * kp + kd )
-
- btScalar cfm = infoGlobal.m_globalCfm;
- btScalar erp = infoGlobal.m_erp2;
-
- if ((cp.m_contactPointFlags&BT_CONTACT_FLAG_HAS_CONTACT_CFM) || (cp.m_contactPointFlags&BT_CONTACT_FLAG_HAS_CONTACT_ERP))
- {
- if (cp.m_contactPointFlags&BT_CONTACT_FLAG_HAS_CONTACT_CFM)
- cfm = cp.m_contactCFM;
- if (cp.m_contactPointFlags&BT_CONTACT_FLAG_HAS_CONTACT_ERP)
- erp = cp.m_contactERP;
- } else
- {
- if (cp.m_contactPointFlags & BT_CONTACT_FLAG_CONTACT_STIFFNESS_DAMPING)
- {
- btScalar denom = ( infoGlobal.m_timeStep * cp.m_combinedContactStiffness1 + cp.m_combinedContactDamping1 );
- if (denom < SIMD_EPSILON)
- {
- denom = SIMD_EPSILON;
- }
- cfm = btScalar(1) / denom;
- erp = (infoGlobal.m_timeStep * cp.m_combinedContactStiffness1) / denom;
- }
- }
-
- cfm *= invTimeStep;
-
-
- btVector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB);
- solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld()*torqueAxis0*rb0->getAngularFactor() : btVector3(0,0,0);
- btVector3 torqueAxis1 = rel_pos2.cross(cp.m_normalWorldOnB);
- solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld()*-torqueAxis1*rb1->getAngularFactor() : btVector3(0,0,0);
-
- {
-#ifdef COMPUTE_IMPULSE_DENOM
- btScalar denom0 = rb0->computeImpulseDenominator(pos1,cp.m_normalWorldOnB);
- btScalar denom1 = rb1->computeImpulseDenominator(pos2,cp.m_normalWorldOnB);
-#else
- btVector3 vec;
- btScalar denom0 = 0.f;
- btScalar denom1 = 0.f;
- if (rb0)
- {
- vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1);
- denom0 = rb0->getInvMass() + cp.m_normalWorldOnB.dot(vec);
- }
- if (rb1)
- {
- vec = ( -solverConstraint.m_angularComponentB).cross(rel_pos2);
- denom1 = rb1->getInvMass() + cp.m_normalWorldOnB.dot(vec);
- }
-#endif //COMPUTE_IMPULSE_DENOM
-
- btScalar denom = relaxation/(denom0+denom1+cfm);
- solverConstraint.m_jacDiagABInv = denom;
- }
-
- if (rb0)
- {
- solverConstraint.m_contactNormal1 = cp.m_normalWorldOnB;
- solverConstraint.m_relpos1CrossNormal = torqueAxis0;
- } else
- {
- solverConstraint.m_contactNormal1.setZero();
- solverConstraint.m_relpos1CrossNormal.setZero();
- }
- if (rb1)
- {
- solverConstraint.m_contactNormal2 = -cp.m_normalWorldOnB;
- solverConstraint.m_relpos2CrossNormal = -torqueAxis1;
- }else
- {
- solverConstraint.m_contactNormal2.setZero();
- solverConstraint.m_relpos2CrossNormal.setZero();
- }
-
- btScalar restitution = 0.f;
- btScalar penetration = cp.getDistance()+infoGlobal.m_linearSlop;
-
- {
- btVector3 vel1,vel2;
+ btSolverBody* bodyA = &m_tmpSolverBodyPool[solverBodyIdA];
+ btSolverBody* bodyB = &m_tmpSolverBodyPool[solverBodyIdB];
- vel1 = rb0? rb0->getVelocityInLocalPoint(rel_pos1) : btVector3(0,0,0);
- vel2 = rb1? rb1->getVelocityInLocalPoint(rel_pos2) : btVector3(0,0,0);
+ btRigidBody* rb0 = bodyA->m_originalBody;
+ btRigidBody* rb1 = bodyB->m_originalBody;
- // btVector3 vel2 = rb1 ? rb1->getVelocityInLocalPoint(rel_pos2) : btVector3(0,0,0);
- btVector3 vel = vel1 - vel2;
- btScalar rel_vel = cp.m_normalWorldOnB.dot(vel);
+ // btVector3 rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin();
+ // btVector3 rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin();
+ //rel_pos1 = pos1 - bodyA->getWorldTransform().getOrigin();
+ //rel_pos2 = pos2 - bodyB->getWorldTransform().getOrigin();
+ relaxation = infoGlobal.m_sor;
+ btScalar invTimeStep = btScalar(1) / infoGlobal.m_timeStep;
+ //cfm = 1 / ( dt * kp + kd )
+ //erp = dt * kp / ( dt * kp + kd )
- solverConstraint.m_friction = cp.m_combinedFriction;
+ btScalar cfm = infoGlobal.m_globalCfm;
+ btScalar erp = infoGlobal.m_erp2;
+ if ((cp.m_contactPointFlags & BT_CONTACT_FLAG_HAS_CONTACT_CFM) || (cp.m_contactPointFlags & BT_CONTACT_FLAG_HAS_CONTACT_ERP))
+ {
+ if (cp.m_contactPointFlags & BT_CONTACT_FLAG_HAS_CONTACT_CFM)
+ cfm = cp.m_contactCFM;
+ if (cp.m_contactPointFlags & BT_CONTACT_FLAG_HAS_CONTACT_ERP)
+ erp = cp.m_contactERP;
+ }
+ else
+ {
+ if (cp.m_contactPointFlags & BT_CONTACT_FLAG_CONTACT_STIFFNESS_DAMPING)
+ {
+ btScalar denom = (infoGlobal.m_timeStep * cp.m_combinedContactStiffness1 + cp.m_combinedContactDamping1);
+ if (denom < SIMD_EPSILON)
+ {
+ denom = SIMD_EPSILON;
+ }
+ cfm = btScalar(1) / denom;
+ erp = (infoGlobal.m_timeStep * cp.m_combinedContactStiffness1) / denom;
+ }
+ }
- restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution, infoGlobal.m_restitutionVelocityThreshold);
- if (restitution <= btScalar(0.))
- {
- restitution = 0.f;
- };
- }
+ cfm *= invTimeStep;
+ btVector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB);
+ solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld() * torqueAxis0 * rb0->getAngularFactor() : btVector3(0, 0, 0);
+ btVector3 torqueAxis1 = rel_pos2.cross(cp.m_normalWorldOnB);
+ solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld() * -torqueAxis1 * rb1->getAngularFactor() : btVector3(0, 0, 0);
- ///warm starting (or zero if disabled)
- if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
- {
- solverConstraint.m_appliedImpulse = cp.m_appliedImpulse * infoGlobal.m_warmstartingFactor;
- if (rb0)
- bodyA->internalApplyImpulse(solverConstraint.m_contactNormal1*bodyA->internalGetInvMass()*rb0->getLinearFactor(),solverConstraint.m_angularComponentA,solverConstraint.m_appliedImpulse);
- if (rb1)
- bodyB->internalApplyImpulse(-solverConstraint.m_contactNormal2*bodyB->internalGetInvMass()*rb1->getLinearFactor(),-solverConstraint.m_angularComponentB,-(btScalar)solverConstraint.m_appliedImpulse);
- } else
- {
- solverConstraint.m_appliedImpulse = 0.f;
- }
+ {
+#ifdef COMPUTE_IMPULSE_DENOM
+ btScalar denom0 = rb0->computeImpulseDenominator(pos1, cp.m_normalWorldOnB);
+ btScalar denom1 = rb1->computeImpulseDenominator(pos2, cp.m_normalWorldOnB);
+#else
+ btVector3 vec;
+ btScalar denom0 = 0.f;
+ btScalar denom1 = 0.f;
+ if (rb0)
+ {
+ vec = (solverConstraint.m_angularComponentA).cross(rel_pos1);
+ denom0 = rb0->getInvMass() + cp.m_normalWorldOnB.dot(vec);
+ }
+ if (rb1)
+ {
+ vec = (-solverConstraint.m_angularComponentB).cross(rel_pos2);
+ denom1 = rb1->getInvMass() + cp.m_normalWorldOnB.dot(vec);
+ }
+#endif //COMPUTE_IMPULSE_DENOM
- solverConstraint.m_appliedPushImpulse = 0.f;
+ btScalar denom = relaxation / (denom0 + denom1 + cfm);
+ solverConstraint.m_jacDiagABInv = denom;
+ }
- {
+ if (rb0)
+ {
+ solverConstraint.m_contactNormal1 = cp.m_normalWorldOnB;
+ solverConstraint.m_relpos1CrossNormal = torqueAxis0;
+ }
+ else
+ {
+ solverConstraint.m_contactNormal1.setZero();
+ solverConstraint.m_relpos1CrossNormal.setZero();
+ }
+ if (rb1)
+ {
+ solverConstraint.m_contactNormal2 = -cp.m_normalWorldOnB;
+ solverConstraint.m_relpos2CrossNormal = -torqueAxis1;
+ }
+ else
+ {
+ solverConstraint.m_contactNormal2.setZero();
+ solverConstraint.m_relpos2CrossNormal.setZero();
+ }
- btVector3 externalForceImpulseA = bodyA->m_originalBody ? bodyA->m_externalForceImpulse: btVector3(0,0,0);
- btVector3 externalTorqueImpulseA = bodyA->m_originalBody ? bodyA->m_externalTorqueImpulse: btVector3(0,0,0);
- btVector3 externalForceImpulseB = bodyB->m_originalBody ? bodyB->m_externalForceImpulse: btVector3(0,0,0);
- btVector3 externalTorqueImpulseB = bodyB->m_originalBody ?bodyB->m_externalTorqueImpulse : btVector3(0,0,0);
+ btScalar restitution = 0.f;
+ btScalar penetration = cp.getDistance() + infoGlobal.m_linearSlop;
+ {
+ btVector3 vel1, vel2;
- btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(bodyA->m_linearVelocity+externalForceImpulseA)
- + solverConstraint.m_relpos1CrossNormal.dot(bodyA->m_angularVelocity+externalTorqueImpulseA);
- btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(bodyB->m_linearVelocity+externalForceImpulseB)
- + solverConstraint.m_relpos2CrossNormal.dot(bodyB->m_angularVelocity+externalTorqueImpulseB);
- btScalar rel_vel = vel1Dotn+vel2Dotn;
+ vel1 = rb0 ? rb0->getVelocityInLocalPoint(rel_pos1) : btVector3(0, 0, 0);
+ vel2 = rb1 ? rb1->getVelocityInLocalPoint(rel_pos2) : btVector3(0, 0, 0);
- btScalar positionalError = 0.f;
- btScalar velocityError = restitution - rel_vel;// * damping;
+ // btVector3 vel2 = rb1 ? rb1->getVelocityInLocalPoint(rel_pos2) : btVector3(0,0,0);
+ btVector3 vel = vel1 - vel2;
+ btScalar rel_vel = cp.m_normalWorldOnB.dot(vel);
+ solverConstraint.m_friction = cp.m_combinedFriction;
-
- if (penetration>0)
- {
- positionalError = 0;
+ restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution, infoGlobal.m_restitutionVelocityThreshold);
+ if (restitution <= btScalar(0.))
+ {
+ restitution = 0.f;
+ };
+ }
- velocityError -= penetration *invTimeStep;
- } else
- {
- positionalError = -penetration * erp*invTimeStep;
+ ///warm starting (or zero if disabled)
+ if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
+ {
+ solverConstraint.m_appliedImpulse = cp.m_appliedImpulse * infoGlobal.m_warmstartingFactor;
+ if (rb0)
+ bodyA->internalApplyImpulse(solverConstraint.m_contactNormal1 * bodyA->internalGetInvMass(), solverConstraint.m_angularComponentA, solverConstraint.m_appliedImpulse);
+ if (rb1)
+ bodyB->internalApplyImpulse(-solverConstraint.m_contactNormal2 * bodyB->internalGetInvMass() , -solverConstraint.m_angularComponentB, -(btScalar)solverConstraint.m_appliedImpulse);
+ }
+ else
+ {
+ solverConstraint.m_appliedImpulse = 0.f;
+ }
- }
+ solverConstraint.m_appliedPushImpulse = 0.f;
- btScalar penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv;
- btScalar velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv;
+ {
+ btVector3 externalForceImpulseA = bodyA->m_originalBody ? bodyA->m_externalForceImpulse : btVector3(0, 0, 0);
+ btVector3 externalTorqueImpulseA = bodyA->m_originalBody ? bodyA->m_externalTorqueImpulse : btVector3(0, 0, 0);
+ btVector3 externalForceImpulseB = bodyB->m_originalBody ? bodyB->m_externalForceImpulse : btVector3(0, 0, 0);
+ btVector3 externalTorqueImpulseB = bodyB->m_originalBody ? bodyB->m_externalTorqueImpulse : btVector3(0, 0, 0);
- if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
- {
- //combine position and velocity into rhs
- solverConstraint.m_rhs = penetrationImpulse+velocityImpulse;//-solverConstraint.m_contactNormal1.dot(bodyA->m_externalForce*bodyA->m_invMass-bodyB->m_externalForce/bodyB->m_invMass)*solverConstraint.m_jacDiagABInv;
- solverConstraint.m_rhsPenetration = 0.f;
+ btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(bodyA->m_linearVelocity + externalForceImpulseA) + solverConstraint.m_relpos1CrossNormal.dot(bodyA->m_angularVelocity + externalTorqueImpulseA);
+ btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(bodyB->m_linearVelocity + externalForceImpulseB) + solverConstraint.m_relpos2CrossNormal.dot(bodyB->m_angularVelocity + externalTorqueImpulseB);
+ btScalar rel_vel = vel1Dotn + vel2Dotn;
- } else
- {
- //split position and velocity into rhs and m_rhsPenetration
- solverConstraint.m_rhs = velocityImpulse;
- solverConstraint.m_rhsPenetration = penetrationImpulse;
- }
- solverConstraint.m_cfm = cfm*solverConstraint.m_jacDiagABInv;
- solverConstraint.m_lowerLimit = 0;
- solverConstraint.m_upperLimit = 1e10f;
- }
+ btScalar positionalError = 0.f;
+ btScalar velocityError = restitution - rel_vel; // * damping;
+ if (penetration > 0)
+ {
+ positionalError = 0;
+ velocityError -= penetration * invTimeStep;
+ }
+ else
+ {
+ positionalError = -penetration * erp * invTimeStep;
+ }
+ btScalar penetrationImpulse = positionalError * solverConstraint.m_jacDiagABInv;
+ btScalar velocityImpulse = velocityError * solverConstraint.m_jacDiagABInv;
+ if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
+ {
+ //combine position and velocity into rhs
+ solverConstraint.m_rhs = penetrationImpulse + velocityImpulse; //-solverConstraint.m_contactNormal1.dot(bodyA->m_externalForce*bodyA->m_invMass-bodyB->m_externalForce/bodyB->m_invMass)*solverConstraint.m_jacDiagABInv;
+ solverConstraint.m_rhsPenetration = 0.f;
+ }
+ else
+ {
+ //split position and velocity into rhs and m_rhsPenetration
+ solverConstraint.m_rhs = velocityImpulse;
+ solverConstraint.m_rhsPenetration = penetrationImpulse;
+ }
+ solverConstraint.m_cfm = cfm * solverConstraint.m_jacDiagABInv;
+ solverConstraint.m_lowerLimit = 0;
+ solverConstraint.m_upperLimit = 1e10f;
+ }
}
-
-
-void btSequentialImpulseConstraintSolver::setFrictionConstraintImpulse( btSolverConstraint& solverConstraint,
- int solverBodyIdA, int solverBodyIdB,
- btManifoldPoint& cp, const btContactSolverInfo& infoGlobal)
+void btSequentialImpulseConstraintSolver::setFrictionConstraintImpulse(btSolverConstraint& solverConstraint,
+ int solverBodyIdA, int solverBodyIdB,
+ btManifoldPoint& cp, const btContactSolverInfo& infoGlobal)
{
-
btSolverBody* bodyA = &m_tmpSolverBodyPool[solverBodyIdA];
btSolverBody* bodyB = &m_tmpSolverBodyPool[solverBodyIdB];
@@ -1058,10 +990,11 @@ void btSequentialImpulseConstraintSolver::setFrictionConstraintImpulse( btSolver
{
frictionConstraint1.m_appliedImpulse = cp.m_appliedImpulseLateral1 * infoGlobal.m_warmstartingFactor;
if (rb0)
- bodyA->internalApplyImpulse(frictionConstraint1.m_contactNormal1*rb0->getInvMass()*rb0->getLinearFactor(),frictionConstraint1.m_angularComponentA,frictionConstraint1.m_appliedImpulse);
+ bodyA->internalApplyImpulse(frictionConstraint1.m_contactNormal1 * rb0->getInvMass() , frictionConstraint1.m_angularComponentA, frictionConstraint1.m_appliedImpulse);
if (rb1)
- bodyB->internalApplyImpulse(-frictionConstraint1.m_contactNormal2*rb1->getInvMass()*rb1->getLinearFactor(),-frictionConstraint1.m_angularComponentB,-(btScalar)frictionConstraint1.m_appliedImpulse);
- } else
+ bodyB->internalApplyImpulse(-frictionConstraint1.m_contactNormal2 * rb1->getInvMass() , -frictionConstraint1.m_angularComponentB, -(btScalar)frictionConstraint1.m_appliedImpulse);
+ }
+ else
{
frictionConstraint1.m_appliedImpulse = 0.f;
}
@@ -1069,50 +1002,45 @@ void btSequentialImpulseConstraintSolver::setFrictionConstraintImpulse( btSolver
if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
{
- btSolverConstraint& frictionConstraint2 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex+1];
+ btSolverConstraint& frictionConstraint2 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex + 1];
if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
{
- frictionConstraint2.m_appliedImpulse = cp.m_appliedImpulseLateral2 * infoGlobal.m_warmstartingFactor;
+ frictionConstraint2.m_appliedImpulse = cp.m_appliedImpulseLateral2 * infoGlobal.m_warmstartingFactor;
if (rb0)
- bodyA->internalApplyImpulse(frictionConstraint2.m_contactNormal1*rb0->getInvMass(),frictionConstraint2.m_angularComponentA,frictionConstraint2.m_appliedImpulse);
+ bodyA->internalApplyImpulse(frictionConstraint2.m_contactNormal1 * rb0->getInvMass(), frictionConstraint2.m_angularComponentA, frictionConstraint2.m_appliedImpulse);
if (rb1)
- bodyB->internalApplyImpulse(-frictionConstraint2.m_contactNormal2*rb1->getInvMass(),-frictionConstraint2.m_angularComponentB,-(btScalar)frictionConstraint2.m_appliedImpulse);
- } else
+ bodyB->internalApplyImpulse(-frictionConstraint2.m_contactNormal2 * rb1->getInvMass(), -frictionConstraint2.m_angularComponentB, -(btScalar)frictionConstraint2.m_appliedImpulse);
+ }
+ else
{
frictionConstraint2.m_appliedImpulse = 0.f;
}
}
}
-
-
-
-void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* manifold,const btContactSolverInfo& infoGlobal)
+void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* manifold, const btContactSolverInfo& infoGlobal)
{
- btCollisionObject* colObj0=0,*colObj1=0;
+ btCollisionObject *colObj0 = 0, *colObj1 = 0;
colObj0 = (btCollisionObject*)manifold->getBody0();
colObj1 = (btCollisionObject*)manifold->getBody1();
- int solverBodyIdA = getOrInitSolverBody(*colObj0,infoGlobal.m_timeStep);
- int solverBodyIdB = getOrInitSolverBody(*colObj1,infoGlobal.m_timeStep);
+ int solverBodyIdA = getOrInitSolverBody(*colObj0, infoGlobal.m_timeStep);
+ int solverBodyIdB = getOrInitSolverBody(*colObj1, infoGlobal.m_timeStep);
-// btRigidBody* bodyA = btRigidBody::upcast(colObj0);
-// btRigidBody* bodyB = btRigidBody::upcast(colObj1);
+ // btRigidBody* bodyA = btRigidBody::upcast(colObj0);
+ // btRigidBody* bodyB = btRigidBody::upcast(colObj1);
btSolverBody* solverBodyA = &m_tmpSolverBodyPool[solverBodyIdA];
btSolverBody* solverBodyB = &m_tmpSolverBodyPool[solverBodyIdB];
-
-
///avoid collision response between two static objects
if (!solverBodyA || (solverBodyA->m_invMass.fuzzyZero() && (!solverBodyB || solverBodyB->m_invMass.fuzzyZero())))
return;
- int rollingFriction=1;
- for (int j=0;j<manifold->getNumContacts();j++)
+ int rollingFriction = 1;
+ for (int j = 0; j < manifold->getNumContacts(); j++)
{
-
btManifoldPoint& cp = manifold->getContactPoint(j);
if (cp.getDistance() <= manifold->getContactProcessingThreshold())
@@ -1121,7 +1049,6 @@ void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* m
btVector3 rel_pos2;
btScalar relaxation;
-
int frictionIndex = m_tmpSolverContactConstraintPool.size();
btSolverConstraint& solverConstraint = m_tmpSolverContactConstraintPool.expandNonInitializing();
solverConstraint.m_solverBodyIdA = solverBodyIdA;
@@ -1137,43 +1064,38 @@ void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* m
btVector3 vel1;
btVector3 vel2;
-
- solverBodyA->getVelocityInLocalPointNoDelta(rel_pos1,vel1);
- solverBodyB->getVelocityInLocalPointNoDelta(rel_pos2,vel2 );
- btVector3 vel = vel1 - vel2;
+ solverBodyA->getVelocityInLocalPointNoDelta(rel_pos1, vel1);
+ solverBodyB->getVelocityInLocalPointNoDelta(rel_pos2, vel2);
+
+ btVector3 vel = vel1 - vel2;
btScalar rel_vel = cp.m_normalWorldOnB.dot(vel);
setupContactConstraint(solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal, relaxation, rel_pos1, rel_pos2);
-
-
-
/////setup the friction constraints
solverConstraint.m_frictionIndex = m_tmpSolverContactFrictionConstraintPool.size();
- if ((cp.m_combinedRollingFriction>0.f) && (rollingFriction>0))
+ if ((cp.m_combinedRollingFriction > 0.f) && (rollingFriction > 0))
{
-
{
- addTorsionalFrictionConstraint(cp.m_normalWorldOnB,solverBodyIdA,solverBodyIdB,frictionIndex,cp,cp.m_combinedSpinningFriction, rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
- btVector3 axis0,axis1;
- btPlaneSpace1(cp.m_normalWorldOnB,axis0,axis1);
+ addTorsionalFrictionConstraint(cp.m_normalWorldOnB, solverBodyIdA, solverBodyIdB, frictionIndex, cp, cp.m_combinedSpinningFriction, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
+ btVector3 axis0, axis1;
+ btPlaneSpace1(cp.m_normalWorldOnB, axis0, axis1);
axis0.normalize();
axis1.normalize();
-
- applyAnisotropicFriction(colObj0,axis0,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
- applyAnisotropicFriction(colObj1,axis0,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
- applyAnisotropicFriction(colObj0,axis1,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
- applyAnisotropicFriction(colObj1,axis1,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
- if (axis0.length()>0.001)
- addTorsionalFrictionConstraint(axis0,solverBodyIdA,solverBodyIdB,frictionIndex,cp,
- cp.m_combinedRollingFriction, rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
- if (axis1.length()>0.001)
- addTorsionalFrictionConstraint(axis1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,
- cp.m_combinedRollingFriction, rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
+ applyAnisotropicFriction(colObj0, axis0, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
+ applyAnisotropicFriction(colObj1, axis0, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
+ applyAnisotropicFriction(colObj0, axis1, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
+ applyAnisotropicFriction(colObj1, axis1, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
+ if (axis0.length() > 0.001)
+ addTorsionalFrictionConstraint(axis0, solverBodyIdA, solverBodyIdB, frictionIndex, cp,
+ cp.m_combinedRollingFriction, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
+ if (axis1.length() > 0.001)
+ addTorsionalFrictionConstraint(axis1, solverBodyIdA, solverBodyIdB, frictionIndex, cp,
+ cp.m_combinedRollingFriction, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
}
}
@@ -1188,106 +1110,97 @@ void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* m
///If you choose SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION, then the friction will be independent from the relative projected velocity.
///
///The user can manually override the friction directions for certain contacts using a contact callback,
- ///and set the cp.m_lateralFrictionInitialized to true
+ ///and use contactPoint.m_contactPointFlags |= BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED
///In that case, you can set the target relative motion in each friction direction (cp.m_contactMotion1 and cp.m_contactMotion2)
///this will give a conveyor belt effect
///
-
- if (!(infoGlobal.m_solverMode & SOLVER_ENABLE_FRICTION_DIRECTION_CACHING) || !(cp.m_contactPointFlags&BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED))
+
+ if (!(infoGlobal.m_solverMode & SOLVER_ENABLE_FRICTION_DIRECTION_CACHING) || !(cp.m_contactPointFlags & BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED))
{
cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel;
btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2();
if (!(infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION) && lat_rel_vel > SIMD_EPSILON)
{
- cp.m_lateralFrictionDir1 *= 1.f/btSqrt(lat_rel_vel);
- applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION);
- applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION);
- addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation,infoGlobal);
+ cp.m_lateralFrictionDir1 *= 1.f / btSqrt(lat_rel_vel);
+ applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+ applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+ addFrictionConstraint(cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
- if((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
+ if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
{
cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross(cp.m_normalWorldOnB);
- cp.m_lateralFrictionDir2.normalize();//??
- applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION);
- applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION);
- addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation, infoGlobal);
+ cp.m_lateralFrictionDir2.normalize(); //??
+ applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+ applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+ addFrictionConstraint(cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
}
-
- } else
+ }
+ else
{
- btPlaneSpace1(cp.m_normalWorldOnB,cp.m_lateralFrictionDir1,cp.m_lateralFrictionDir2);
+ btPlaneSpace1(cp.m_normalWorldOnB, cp.m_lateralFrictionDir1, cp.m_lateralFrictionDir2);
- applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION);
- applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION);
- addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation, infoGlobal);
+ applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+ applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+ addFrictionConstraint(cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
{
- applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION);
- applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION);
- addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation, infoGlobal);
+ applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+ applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+ addFrictionConstraint(cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
}
-
if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION))
{
- cp.m_contactPointFlags|=BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED;
+ cp.m_contactPointFlags |= BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED;
}
}
-
- } else
+ }
+ else
{
- addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation, infoGlobal, cp.m_contactMotion1, cp.m_frictionCFM);
+ addFrictionConstraint(cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion1, cp.m_frictionCFM);
if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
- addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation, infoGlobal, cp.m_contactMotion2, cp.m_frictionCFM);
-
+ addFrictionConstraint(cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion2, cp.m_frictionCFM);
}
- setFrictionConstraintImpulse( solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal);
-
-
-
-
+ setFrictionConstraintImpulse(solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal);
}
}
}
-void btSequentialImpulseConstraintSolver::convertContacts(btPersistentManifold** manifoldPtr,int numManifolds, const btContactSolverInfo& infoGlobal)
+void btSequentialImpulseConstraintSolver::convertContacts(btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal)
{
int i;
btPersistentManifold* manifold = 0;
-// btCollisionObject* colObj0=0,*colObj1=0;
-
+ // btCollisionObject* colObj0=0,*colObj1=0;
- for (i=0;i<numManifolds;i++)
+ for (i = 0; i < numManifolds; i++)
{
manifold = manifoldPtr[i];
- convertContact(manifold,infoGlobal);
+ convertContact(manifold, infoGlobal);
}
}
-
void btSequentialImpulseConstraintSolver::convertJoint(btSolverConstraint* currentConstraintRow,
- btTypedConstraint* constraint,
- const btTypedConstraint::btConstraintInfo1& info1,
- int solverBodyIdA,
- int solverBodyIdB,
- const btContactSolverInfo& infoGlobal
- )
+ btTypedConstraint* constraint,
+ const btTypedConstraint::btConstraintInfo1& info1,
+ int solverBodyIdA,
+ int solverBodyIdB,
+ const btContactSolverInfo& infoGlobal)
{
const btRigidBody& rbA = constraint->getRigidBodyA();
const btRigidBody& rbB = constraint->getRigidBodyB();
- const btSolverBody* bodyAPtr = &m_tmpSolverBodyPool[solverBodyIdA];
- const btSolverBody* bodyBPtr = &m_tmpSolverBodyPool[solverBodyIdB];
+ const btSolverBody* bodyAPtr = &m_tmpSolverBodyPool[solverBodyIdA];
+ const btSolverBody* bodyBPtr = &m_tmpSolverBodyPool[solverBodyIdB];
int overrideNumSolverIterations = constraint->getOverrideNumSolverIterations() > 0 ? constraint->getOverrideNumSolverIterations() : infoGlobal.m_numIterations;
- if (overrideNumSolverIterations>m_maxOverrideNumSolverIterations)
+ if (overrideNumSolverIterations > m_maxOverrideNumSolverIterations)
m_maxOverrideNumSolverIterations = overrideNumSolverIterations;
- for (int j=0;j<info1.m_numConstraintRows;j++)
+ for (int j = 0; j < info1.m_numConstraintRows; j++)
{
- memset(&currentConstraintRow[j],0,sizeof(btSolverConstraint));
+ memset(&currentConstraintRow[j], 0, sizeof(btSolverConstraint));
currentConstraintRow[j].m_lowerLimit = -SIMD_INFINITY;
currentConstraintRow[j].m_upperLimit = SIMD_INFINITY;
currentConstraintRow[j].m_appliedImpulse = 0.f;
@@ -1297,15 +1210,15 @@ void btSequentialImpulseConstraintSolver::convertJoint(btSolverConstraint* curre
currentConstraintRow[j].m_overrideNumSolverIterations = overrideNumSolverIterations;
}
- // these vectors are already cleared in initSolverBody, no need to redundantly clear again
- btAssert(bodyAPtr->getDeltaLinearVelocity().isZero());
- btAssert(bodyAPtr->getDeltaAngularVelocity().isZero());
- btAssert(bodyAPtr->getPushVelocity().isZero());
- btAssert(bodyAPtr->getTurnVelocity().isZero());
- btAssert(bodyBPtr->getDeltaLinearVelocity().isZero());
- btAssert(bodyBPtr->getDeltaAngularVelocity().isZero());
- btAssert(bodyBPtr->getPushVelocity().isZero());
- btAssert(bodyBPtr->getTurnVelocity().isZero());
+ // these vectors are already cleared in initSolverBody, no need to redundantly clear again
+ btAssert(bodyAPtr->getDeltaLinearVelocity().isZero());
+ btAssert(bodyAPtr->getDeltaAngularVelocity().isZero());
+ btAssert(bodyAPtr->getPushVelocity().isZero());
+ btAssert(bodyAPtr->getTurnVelocity().isZero());
+ btAssert(bodyBPtr->getDeltaLinearVelocity().isZero());
+ btAssert(bodyBPtr->getDeltaAngularVelocity().isZero());
+ btAssert(bodyBPtr->getPushVelocity().isZero());
+ btAssert(bodyBPtr->getTurnVelocity().isZero());
//bodyAPtr->internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
//bodyAPtr->internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f);
//bodyAPtr->internalGetPushVelocity().setValue(0.f,0.f,0.f);
@@ -1315,17 +1228,16 @@ void btSequentialImpulseConstraintSolver::convertJoint(btSolverConstraint* curre
//bodyBPtr->internalGetPushVelocity().setValue(0.f,0.f,0.f);
//bodyBPtr->internalGetTurnVelocity().setValue(0.f,0.f,0.f);
-
btTypedConstraint::btConstraintInfo2 info2;
- info2.fps = 1.f/infoGlobal.m_timeStep;
+ info2.fps = 1.f / infoGlobal.m_timeStep;
info2.erp = infoGlobal.m_erp;
info2.m_J1linearAxis = currentConstraintRow->m_contactNormal1;
info2.m_J1angularAxis = currentConstraintRow->m_relpos1CrossNormal;
info2.m_J2linearAxis = currentConstraintRow->m_contactNormal2;
info2.m_J2angularAxis = currentConstraintRow->m_relpos2CrossNormal;
- info2.rowskip = sizeof(btSolverConstraint)/sizeof(btScalar);//check this
+ info2.rowskip = sizeof(btSolverConstraint) / sizeof(btScalar); //check this
///the size of btSolverConstraint needs be a multiple of btScalar
- btAssert(info2.rowskip*sizeof(btScalar)== sizeof(btSolverConstraint));
+ btAssert(info2.rowskip * sizeof(btScalar) == sizeof(btSolverConstraint));
info2.m_constraintError = &currentConstraintRow->m_rhs;
currentConstraintRow->m_cfm = infoGlobal.m_globalCfm;
info2.m_damping = infoGlobal.m_damping;
@@ -1336,16 +1248,16 @@ void btSequentialImpulseConstraintSolver::convertJoint(btSolverConstraint* curre
constraint->getInfo2(&info2);
///finalize the constraint setup
- for (int j=0;j<info1.m_numConstraintRows;j++)
+ for (int j = 0; j < info1.m_numConstraintRows; j++)
{
btSolverConstraint& solverConstraint = currentConstraintRow[j];
- if (solverConstraint.m_upperLimit>=constraint->getBreakingImpulseThreshold())
+ if (solverConstraint.m_upperLimit >= constraint->getBreakingImpulseThreshold())
{
solverConstraint.m_upperLimit = constraint->getBreakingImpulseThreshold();
}
- if (solverConstraint.m_lowerLimit<=-constraint->getBreakingImpulseThreshold())
+ if (solverConstraint.m_lowerLimit <= -constraint->getBreakingImpulseThreshold())
{
solverConstraint.m_lowerLimit = -constraint->getBreakingImpulseThreshold();
}
@@ -1354,18 +1266,18 @@ void btSequentialImpulseConstraintSolver::convertJoint(btSolverConstraint* curre
{
const btVector3& ftorqueAxis1 = solverConstraint.m_relpos1CrossNormal;
- solverConstraint.m_angularComponentA = constraint->getRigidBodyA().getInvInertiaTensorWorld()*ftorqueAxis1*constraint->getRigidBodyA().getAngularFactor();
+ solverConstraint.m_angularComponentA = constraint->getRigidBodyA().getInvInertiaTensorWorld() * ftorqueAxis1 * constraint->getRigidBodyA().getAngularFactor();
}
{
const btVector3& ftorqueAxis2 = solverConstraint.m_relpos2CrossNormal;
- solverConstraint.m_angularComponentB = constraint->getRigidBodyB().getInvInertiaTensorWorld()*ftorqueAxis2*constraint->getRigidBodyB().getAngularFactor();
+ solverConstraint.m_angularComponentB = constraint->getRigidBodyB().getInvInertiaTensorWorld() * ftorqueAxis2 * constraint->getRigidBodyB().getAngularFactor();
}
{
- btVector3 iMJlA = solverConstraint.m_contactNormal1*rbA.getInvMass();
- btVector3 iMJaA = rbA.getInvInertiaTensorWorld()*solverConstraint.m_relpos1CrossNormal;
- btVector3 iMJlB = solverConstraint.m_contactNormal2*rbB.getInvMass();//sign of normal?
- btVector3 iMJaB = rbB.getInvInertiaTensorWorld()*solverConstraint.m_relpos2CrossNormal;
+ btVector3 iMJlA = solverConstraint.m_contactNormal1 * rbA.getInvMass();
+ btVector3 iMJaA = rbA.getInvInertiaTensorWorld() * solverConstraint.m_relpos1CrossNormal;
+ btVector3 iMJlB = solverConstraint.m_contactNormal2 * rbB.getInvMass(); //sign of normal?
+ btVector3 iMJaB = rbB.getInvInertiaTensorWorld() * solverConstraint.m_relpos2CrossNormal;
btScalar sum = iMJlA.dot(solverConstraint.m_contactNormal1);
sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
@@ -1373,41 +1285,38 @@ void btSequentialImpulseConstraintSolver::convertJoint(btSolverConstraint* curre
sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
btScalar fsum = btFabs(sum);
btAssert(fsum > SIMD_EPSILON);
- btScalar sorRelaxation = 1.f;//todo: get from globalInfo?
- solverConstraint.m_jacDiagABInv = fsum>SIMD_EPSILON?sorRelaxation/sum : 0.f;
+ btScalar sorRelaxation = 1.f; //todo: get from globalInfo?
+ solverConstraint.m_jacDiagABInv = fsum > SIMD_EPSILON ? sorRelaxation / sum : 0.f;
}
{
btScalar rel_vel;
- btVector3 externalForceImpulseA = bodyAPtr->m_originalBody ? bodyAPtr->m_externalForceImpulse : btVector3(0,0,0);
- btVector3 externalTorqueImpulseA = bodyAPtr->m_originalBody ? bodyAPtr->m_externalTorqueImpulse : btVector3(0,0,0);
+ btVector3 externalForceImpulseA = bodyAPtr->m_originalBody ? bodyAPtr->m_externalForceImpulse : btVector3(0, 0, 0);
+ btVector3 externalTorqueImpulseA = bodyAPtr->m_originalBody ? bodyAPtr->m_externalTorqueImpulse : btVector3(0, 0, 0);
- btVector3 externalForceImpulseB = bodyBPtr->m_originalBody ? bodyBPtr->m_externalForceImpulse : btVector3(0,0,0);
- btVector3 externalTorqueImpulseB = bodyBPtr->m_originalBody ?bodyBPtr->m_externalTorqueImpulse : btVector3(0,0,0);
+ btVector3 externalForceImpulseB = bodyBPtr->m_originalBody ? bodyBPtr->m_externalForceImpulse : btVector3(0, 0, 0);
+ btVector3 externalTorqueImpulseB = bodyBPtr->m_originalBody ? bodyBPtr->m_externalTorqueImpulse : btVector3(0, 0, 0);
- btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(rbA.getLinearVelocity()+externalForceImpulseA)
- + solverConstraint.m_relpos1CrossNormal.dot(rbA.getAngularVelocity()+externalTorqueImpulseA);
+ btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(rbA.getLinearVelocity() + externalForceImpulseA) + solverConstraint.m_relpos1CrossNormal.dot(rbA.getAngularVelocity() + externalTorqueImpulseA);
- btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(rbB.getLinearVelocity()+externalForceImpulseB)
- + solverConstraint.m_relpos2CrossNormal.dot(rbB.getAngularVelocity()+externalTorqueImpulseB);
+ btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(rbB.getLinearVelocity() + externalForceImpulseB) + solverConstraint.m_relpos2CrossNormal.dot(rbB.getAngularVelocity() + externalTorqueImpulseB);
- rel_vel = vel1Dotn+vel2Dotn;
+ rel_vel = vel1Dotn + vel2Dotn;
btScalar restitution = 0.f;
- btScalar positionalError = solverConstraint.m_rhs;//already filled in by getConstraintInfo2
- btScalar velocityError = restitution - rel_vel * info2.m_damping;
- btScalar penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv;
- btScalar velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv;
- solverConstraint.m_rhs = penetrationImpulse+velocityImpulse;
+ btScalar positionalError = solverConstraint.m_rhs; //already filled in by getConstraintInfo2
+ btScalar velocityError = restitution - rel_vel * info2.m_damping;
+ btScalar penetrationImpulse = positionalError * solverConstraint.m_jacDiagABInv;
+ btScalar velocityImpulse = velocityError * solverConstraint.m_jacDiagABInv;
+ solverConstraint.m_rhs = penetrationImpulse + velocityImpulse;
solverConstraint.m_appliedImpulse = 0.f;
}
}
}
-
-void btSequentialImpulseConstraintSolver::convertJoints(btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal)
+void btSequentialImpulseConstraintSolver::convertJoints(btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal)
{
- BT_PROFILE("convertJoints");
- for (int j=0;j<numConstraints;j++)
+ BT_PROFILE("convertJoints");
+ for (int j = 0; j < numConstraints; j++)
{
btTypedConstraint* constraint = constraints[j];
constraint->buildJacobian();
@@ -1418,7 +1327,7 @@ void btSequentialImpulseConstraintSolver::convertJoints(btTypedConstraint** cons
m_tmpConstraintSizesPool.resizeNoInitialize(numConstraints);
//calculate the total number of contraint rows
- for (int i=0;i<numConstraints;i++)
+ for (int i = 0; i < numConstraints; i++)
{
btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
btJointFeedback* fb = constraints[i]->getJointFeedback();
@@ -1433,7 +1342,8 @@ void btSequentialImpulseConstraintSolver::convertJoints(btTypedConstraint** cons
if (constraints[i]->isEnabled())
{
constraints[i]->getInfo1(&info1);
- } else
+ }
+ else
{
info1.m_numConstraintRows = 0;
info1.nub = 0;
@@ -1442,110 +1352,105 @@ void btSequentialImpulseConstraintSolver::convertJoints(btTypedConstraint** cons
}
m_tmpSolverNonContactConstraintPool.resizeNoInitialize(totalNumRows);
-
///setup the btSolverConstraints
int currentRow = 0;
- for (int i=0;i<numConstraints;i++)
+ for (int i = 0; i < numConstraints; i++)
{
const btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
if (info1.m_numConstraintRows)
{
- btAssert(currentRow<totalNumRows);
+ btAssert(currentRow < totalNumRows);
btSolverConstraint* currentConstraintRow = &m_tmpSolverNonContactConstraintPool[currentRow];
btTypedConstraint* constraint = constraints[i];
btRigidBody& rbA = constraint->getRigidBodyA();
btRigidBody& rbB = constraint->getRigidBodyB();
- int solverBodyIdA = getOrInitSolverBody(rbA,infoGlobal.m_timeStep);
- int solverBodyIdB = getOrInitSolverBody(rbB,infoGlobal.m_timeStep);
+ int solverBodyIdA = getOrInitSolverBody(rbA, infoGlobal.m_timeStep);
+ int solverBodyIdB = getOrInitSolverBody(rbB, infoGlobal.m_timeStep);
- convertJoint(currentConstraintRow, constraint, info1, solverBodyIdA, solverBodyIdB, infoGlobal);
- }
- currentRow+=info1.m_numConstraintRows;
+ convertJoint(currentConstraintRow, constraint, info1, solverBodyIdA, solverBodyIdB, infoGlobal);
+ }
+ currentRow += info1.m_numConstraintRows;
}
}
-
void btSequentialImpulseConstraintSolver::convertBodies(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
{
- BT_PROFILE("convertBodies");
+ BT_PROFILE("convertBodies");
for (int i = 0; i < numBodies; i++)
{
bodies[i]->setCompanionId(-1);
}
#if BT_THREADSAFE
- m_kinematicBodyUniqueIdToSolverBodyTable.resize( 0 );
-#endif // BT_THREADSAFE
+ m_kinematicBodyUniqueIdToSolverBodyTable.resize(0);
+#endif // BT_THREADSAFE
- m_tmpSolverBodyPool.reserve(numBodies+1);
+ m_tmpSolverBodyPool.reserve(numBodies + 1);
m_tmpSolverBodyPool.resize(0);
//btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
- //initSolverBody(&fixedBody,0);
+ //initSolverBody(&fixedBody,0);
- for (int i=0;i<numBodies;i++)
+ for (int i = 0; i < numBodies; i++)
{
- int bodyId = getOrInitSolverBody(*bodies[i],infoGlobal.m_timeStep);
+ int bodyId = getOrInitSolverBody(*bodies[i], infoGlobal.m_timeStep);
btRigidBody* body = btRigidBody::upcast(bodies[i]);
if (body && body->getInvMass())
{
btSolverBody& solverBody = m_tmpSolverBodyPool[bodyId];
- btVector3 gyroForce (0,0,0);
- if (body->getFlags()&BT_ENABLE_GYROSCOPIC_FORCE_EXPLICIT)
+ btVector3 gyroForce(0, 0, 0);
+ if (body->getFlags() & BT_ENABLE_GYROSCOPIC_FORCE_EXPLICIT)
{
gyroForce = body->computeGyroscopicForceExplicit(infoGlobal.m_maxGyroscopicForce);
- solverBody.m_externalTorqueImpulse -= gyroForce*body->getInvInertiaTensorWorld()*infoGlobal.m_timeStep;
+ solverBody.m_externalTorqueImpulse -= gyroForce * body->getInvInertiaTensorWorld() * infoGlobal.m_timeStep;
}
- if (body->getFlags()&BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_WORLD)
+ if (body->getFlags() & BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_WORLD)
{
gyroForce = body->computeGyroscopicImpulseImplicit_World(infoGlobal.m_timeStep);
solverBody.m_externalTorqueImpulse += gyroForce;
}
- if (body->getFlags()&BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY)
+ if (body->getFlags() & BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY)
{
gyroForce = body->computeGyroscopicImpulseImplicit_Body(infoGlobal.m_timeStep);
solverBody.m_externalTorqueImpulse += gyroForce;
-
}
}
}
}
-
-btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer)
+btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
{
m_fixedBodyId = -1;
BT_PROFILE("solveGroupCacheFriendlySetup");
(void)debugDrawer;
- // if solver mode has changed,
- if ( infoGlobal.m_solverMode != m_cachedSolverMode )
- {
- // update solver functions to use SIMD or non-SIMD
- bool useSimd = !!( infoGlobal.m_solverMode & SOLVER_SIMD );
- setupSolverFunctions( useSimd );
- m_cachedSolverMode = infoGlobal.m_solverMode;
- }
+ // if solver mode has changed,
+ if (infoGlobal.m_solverMode != m_cachedSolverMode)
+ {
+ // update solver functions to use SIMD or non-SIMD
+ bool useSimd = !!(infoGlobal.m_solverMode & SOLVER_SIMD);
+ setupSolverFunctions(useSimd);
+ m_cachedSolverMode = infoGlobal.m_solverMode;
+ }
m_maxOverrideNumSolverIterations = 0;
#ifdef BT_ADDITIONAL_DEBUG
- //make sure that dynamic bodies exist for all (enabled) constraints
- for (int i=0;i<numConstraints;i++)
+ //make sure that dynamic bodies exist for all (enabled) constraints
+ for (int i = 0; i < numConstraints; i++)
{
btTypedConstraint* constraint = constraints[i];
if (constraint->isEnabled())
{
if (!constraint->getRigidBodyA().isStaticOrKinematicObject())
{
- bool found=false;
- for (int b=0;b<numBodies;b++)
+ bool found = false;
+ for (int b = 0; b < numBodies; b++)
{
-
- if (&constraint->getRigidBodyA()==bodies[b])
+ if (&constraint->getRigidBodyA() == bodies[b])
{
found = true;
break;
@@ -1555,10 +1460,10 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol
}
if (!constraint->getRigidBodyB().isStaticOrKinematicObject())
{
- bool found=false;
- for (int b=0;b<numBodies;b++)
+ bool found = false;
+ for (int b = 0; b < numBodies; b++)
{
- if (&constraint->getRigidBodyB()==bodies[b])
+ if (&constraint->getRigidBodyB() == bodies[b])
{
found = true;
break;
@@ -1568,50 +1473,46 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol
}
}
}
- //make sure that dynamic bodies exist for all contact manifolds
- for (int i=0;i<numManifolds;i++)
- {
- if (!manifoldPtr[i]->getBody0()->isStaticOrKinematicObject())
- {
- bool found=false;
- for (int b=0;b<numBodies;b++)
- {
-
- if (manifoldPtr[i]->getBody0()==bodies[b])
- {
- found = true;
- break;
- }
- }
- btAssert(found);
- }
- if (!manifoldPtr[i]->getBody1()->isStaticOrKinematicObject())
- {
- bool found=false;
- for (int b=0;b<numBodies;b++)
- {
- if (manifoldPtr[i]->getBody1()==bodies[b])
- {
- found = true;
- break;
- }
- }
- btAssert(found);
- }
- }
-#endif //BT_ADDITIONAL_DEBUG
-
+ //make sure that dynamic bodies exist for all contact manifolds
+ for (int i = 0; i < numManifolds; i++)
+ {
+ if (!manifoldPtr[i]->getBody0()->isStaticOrKinematicObject())
+ {
+ bool found = false;
+ for (int b = 0; b < numBodies; b++)
+ {
+ if (manifoldPtr[i]->getBody0() == bodies[b])
+ {
+ found = true;
+ break;
+ }
+ }
+ btAssert(found);
+ }
+ if (!manifoldPtr[i]->getBody1()->isStaticOrKinematicObject())
+ {
+ bool found = false;
+ for (int b = 0; b < numBodies; b++)
+ {
+ if (manifoldPtr[i]->getBody1() == bodies[b])
+ {
+ found = true;
+ break;
+ }
+ }
+ btAssert(found);
+ }
+ }
+#endif //BT_ADDITIONAL_DEBUG
//convert all bodies
- convertBodies(bodies, numBodies, infoGlobal);
-
- convertJoints(constraints, numConstraints, infoGlobal);
+ convertBodies(bodies, numBodies, infoGlobal);
- convertContacts(manifoldPtr,numManifolds,infoGlobal);
+ convertJoints(constraints, numConstraints, infoGlobal);
+ convertContacts(manifoldPtr, numManifolds, infoGlobal);
-// btContactSolverInfo info = infoGlobal;
-
+ // btContactSolverInfo info = infoGlobal;
int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
int numConstraintPool = m_tmpSolverContactConstraintPool.size();
@@ -1620,35 +1521,33 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol
///@todo: use stack allocator for such temporarily memory, same for solver bodies/constraints
m_orderNonContactConstraintPool.resizeNoInitialize(numNonContactPool);
if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
- m_orderTmpConstraintPool.resizeNoInitialize(numConstraintPool*2);
+ m_orderTmpConstraintPool.resizeNoInitialize(numConstraintPool * 2);
else
m_orderTmpConstraintPool.resizeNoInitialize(numConstraintPool);
m_orderFrictionConstraintPool.resizeNoInitialize(numFrictionPool);
{
int i;
- for (i=0;i<numNonContactPool;i++)
+ for (i = 0; i < numNonContactPool; i++)
{
m_orderNonContactConstraintPool[i] = i;
}
- for (i=0;i<numConstraintPool;i++)
+ for (i = 0; i < numConstraintPool; i++)
{
m_orderTmpConstraintPool[i] = i;
}
- for (i=0;i<numFrictionPool;i++)
+ for (i = 0; i < numFrictionPool; i++)
{
m_orderFrictionConstraintPool[i] = i;
}
}
return 0.f;
-
}
-
-btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration, btCollisionObject** /*bodies */,int /*numBodies*/,btPersistentManifold** /*manifoldPtr*/, int /*numManifolds*/,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* /*debugDrawer*/)
+btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration, btCollisionObject** /*bodies */, int /*numBodies*/, btPersistentManifold** /*manifoldPtr*/, int /*numManifolds*/, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* /*debugDrawer*/)
{
- BT_PROFILE("solveSingleIteration");
+ BT_PROFILE("solveSingleIteration");
btScalar leastSquaresResidual = 0.f;
int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
@@ -1657,29 +1556,31 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration
if (infoGlobal.m_solverMode & SOLVER_RANDMIZE_ORDER)
{
- if (1) // uncomment this for a bit less random ((iteration & 7) == 0)
+ if (1) // uncomment this for a bit less random ((iteration & 7) == 0)
{
-
- for (int j=0; j<numNonContactPool; ++j) {
+ for (int j = 0; j < numNonContactPool; ++j)
+ {
int tmp = m_orderNonContactConstraintPool[j];
- int swapi = btRandInt2(j+1);
+ int swapi = btRandInt2(j + 1);
m_orderNonContactConstraintPool[j] = m_orderNonContactConstraintPool[swapi];
m_orderNonContactConstraintPool[swapi] = tmp;
}
//contact/friction constraints are not solved more than
- if (iteration< infoGlobal.m_numIterations)
+ if (iteration < infoGlobal.m_numIterations)
{
- for (int j=0; j<numConstraintPool; ++j) {
+ for (int j = 0; j < numConstraintPool; ++j)
+ {
int tmp = m_orderTmpConstraintPool[j];
- int swapi = btRandInt2(j+1);
+ int swapi = btRandInt2(j + 1);
m_orderTmpConstraintPool[j] = m_orderTmpConstraintPool[swapi];
m_orderTmpConstraintPool[swapi] = tmp;
}
- for (int j=0; j<numFrictionPool; ++j) {
+ for (int j = 0; j < numFrictionPool; ++j)
+ {
int tmp = m_orderFrictionConstraintPool[j];
- int swapi = btRandInt2(j+1);
+ int swapi = btRandInt2(j + 1);
m_orderFrictionConstraintPool[j] = m_orderFrictionConstraintPool[swapi];
m_orderFrictionConstraintPool[swapi] = tmp;
}
@@ -1687,253 +1588,240 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration
}
}
- ///solve all joint constraints
- for (int j=0;j<m_tmpSolverNonContactConstraintPool.size();j++)
+ ///solve all joint constraints
+ for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++)
+ {
+ btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
+ if (iteration < constraint.m_overrideNumSolverIterations)
{
- btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
- if (iteration < constraint.m_overrideNumSolverIterations)
- {
- btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[constraint.m_solverBodyIdA],m_tmpSolverBodyPool[constraint.m_solverBodyIdB],constraint);
- leastSquaresResidual = btMax(leastSquaresResidual, residual*residual);
- }
+ btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[constraint.m_solverBodyIdA], m_tmpSolverBodyPool[constraint.m_solverBodyIdB], constraint);
+ leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
}
+ }
- if (iteration< infoGlobal.m_numIterations)
+ if (iteration < infoGlobal.m_numIterations)
+ {
+ for (int j = 0; j < numConstraints; j++)
{
- for (int j=0;j<numConstraints;j++)
+ if (constraints[j]->isEnabled())
{
- if (constraints[j]->isEnabled())
- {
- int bodyAid = getOrInitSolverBody(constraints[j]->getRigidBodyA(),infoGlobal.m_timeStep);
- int bodyBid = getOrInitSolverBody(constraints[j]->getRigidBodyB(),infoGlobal.m_timeStep);
- btSolverBody& bodyA = m_tmpSolverBodyPool[bodyAid];
- btSolverBody& bodyB = m_tmpSolverBodyPool[bodyBid];
- constraints[j]->solveConstraintObsolete(bodyA,bodyB,infoGlobal.m_timeStep);
- }
+ int bodyAid = getOrInitSolverBody(constraints[j]->getRigidBodyA(), infoGlobal.m_timeStep);
+ int bodyBid = getOrInitSolverBody(constraints[j]->getRigidBodyB(), infoGlobal.m_timeStep);
+ btSolverBody& bodyA = m_tmpSolverBodyPool[bodyAid];
+ btSolverBody& bodyB = m_tmpSolverBodyPool[bodyBid];
+ constraints[j]->solveConstraintObsolete(bodyA, bodyB, infoGlobal.m_timeStep);
}
+ }
+
+ ///solve all contact constraints
+ if (infoGlobal.m_solverMode & SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS)
+ {
+ int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+ int multiplier = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) ? 2 : 1;
- ///solve all contact constraints
- if (infoGlobal.m_solverMode & SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS)
+ for (int c = 0; c < numPoolConstraints; c++)
{
- int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
- int multiplier = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)? 2 : 1;
+ btScalar totalImpulse = 0;
- for (int c=0;c<numPoolConstraints;c++)
{
- btScalar totalImpulse =0;
+ const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[c]];
+ btScalar residual = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+ leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
+ totalImpulse = solveManifold.m_appliedImpulse;
+ }
+ bool applyFriction = true;
+ if (applyFriction)
+ {
{
- const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[c]];
- btScalar residual = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
- leastSquaresResidual = btMax(leastSquaresResidual, residual*residual);
+ btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c * multiplier]];
- totalImpulse = solveManifold.m_appliedImpulse;
- }
- bool applyFriction = true;
- if (applyFriction)
- {
+ if (totalImpulse > btScalar(0))
{
+ solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
+ solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
- btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c*multiplier]];
-
- if (totalImpulse>btScalar(0))
- {
- solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
- solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
-
- btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
- leastSquaresResidual = btMax(leastSquaresResidual, residual*residual);
- }
+ btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+ leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
}
+ }
- if (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)
- {
-
- btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c*multiplier+1]];
+ if (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)
+ {
+ btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c * multiplier + 1]];
- if (totalImpulse>btScalar(0))
- {
- solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
- solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
+ if (totalImpulse > btScalar(0))
+ {
+ solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
+ solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
- btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
- leastSquaresResidual = btMax(leastSquaresResidual, residual*residual);
- }
+ btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+ leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
}
}
}
-
}
- else//SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS
- {
- //solve the friction constraints after all contact constraints, don't interleave them
- int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
- int j;
-
- for (j=0;j<numPoolConstraints;j++)
- {
- const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
- btScalar residual = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
- leastSquaresResidual = btMax(leastSquaresResidual, residual*residual);
- }
+ }
+ else //SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS
+ {
+ //solve the friction constraints after all contact constraints, don't interleave them
+ int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+ int j;
+ for (j = 0; j < numPoolConstraints; j++)
+ {
+ const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
+ btScalar residual = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+ leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
+ }
+ ///solve all friction constraints
- ///solve all friction constraints
+ int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size();
+ for (j = 0; j < numFrictionPoolConstraints; j++)
+ {
+ btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]];
+ btScalar totalImpulse = m_tmpSolverContactConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
- int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size();
- for (j=0;j<numFrictionPoolConstraints;j++)
+ if (totalImpulse > btScalar(0))
{
- btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]];
- btScalar totalImpulse = m_tmpSolverContactConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
+ solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
+ solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
- if (totalImpulse>btScalar(0))
- {
- solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
- solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
-
- btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
- leastSquaresResidual = btMax(leastSquaresResidual, residual*residual);
- }
+ btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+ leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
}
}
+ }
+ int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size();
+ for (int j = 0; j < numRollingFrictionPoolConstraints; j++)
+ {
+ btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
+ btScalar totalImpulse = m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse;
+ if (totalImpulse > btScalar(0))
+ {
+ btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse;
+ if (rollingFrictionMagnitude > rollingFrictionConstraint.m_friction)
+ rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
- int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size();
- for (int j=0;j<numRollingFrictionPoolConstraints;j++)
- {
-
- btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
- btScalar totalImpulse = m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse;
- if (totalImpulse>btScalar(0))
- {
- btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction*totalImpulse;
- if (rollingFrictionMagnitude>rollingFrictionConstraint.m_friction)
- rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
-
- rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
- rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
-
- btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA],m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB],rollingFrictionConstraint);
- leastSquaresResidual = btMax(leastSquaresResidual, residual*residual);
- }
- }
-
+ rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
+ rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
+ btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint);
+ leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
+ }
}
+ }
return leastSquaresResidual;
}
-
-void btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer)
+void btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
{
BT_PROFILE("solveGroupCacheFriendlySplitImpulseIterations");
int iteration;
if (infoGlobal.m_splitImpulse)
{
{
- for ( iteration = 0;iteration<infoGlobal.m_numIterations;iteration++)
+ for (iteration = 0; iteration < infoGlobal.m_numIterations; iteration++)
{
- btScalar leastSquaresResidual =0.f;
+ btScalar leastSquaresResidual = 0.f;
{
int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
int j;
- for (j=0;j<numPoolConstraints;j++)
+ for (j = 0; j < numPoolConstraints; j++)
{
const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
- btScalar residual = resolveSplitPenetrationImpulse(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
- leastSquaresResidual = btMax(leastSquaresResidual, residual*residual);
+ btScalar residual = resolveSplitPenetrationImpulse(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+ leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
}
}
- if (leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || iteration>=(infoGlobal.m_numIterations-1))
+ if (leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || iteration >= (infoGlobal.m_numIterations - 1))
{
#ifdef VERBOSE_RESIDUAL_PRINTF
- printf("residual = %f at iteration #%d\n",leastSquaresResidual,iteration);
+ printf("residual = %f at iteration #%d\n", leastSquaresResidual, iteration);
#endif
break;
}
}
- }
+ }
}
}
-btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations(btCollisionObject** bodies ,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer)
+btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
{
BT_PROFILE("solveGroupCacheFriendlyIterations");
{
///this is a special step to resolve penetrations (just for contacts)
- solveGroupCacheFriendlySplitImpulseIterations(bodies ,numBodies,manifoldPtr, numManifolds,constraints,numConstraints,infoGlobal,debugDrawer);
+ solveGroupCacheFriendlySplitImpulseIterations(bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
- int maxIterations = m_maxOverrideNumSolverIterations > infoGlobal.m_numIterations? m_maxOverrideNumSolverIterations : infoGlobal.m_numIterations;
+ int maxIterations = m_maxOverrideNumSolverIterations > infoGlobal.m_numIterations ? m_maxOverrideNumSolverIterations : infoGlobal.m_numIterations;
- for ( int iteration = 0 ; iteration< maxIterations ; iteration++)
+ for (int iteration = 0; iteration < maxIterations; iteration++)
//for ( int iteration = maxIterations-1 ; iteration >= 0;iteration--)
{
- m_leastSquaresResidual = solveSingleIteration(iteration, bodies ,numBodies,manifoldPtr, numManifolds,constraints,numConstraints,infoGlobal,debugDrawer);
+ m_leastSquaresResidual = solveSingleIteration(iteration, bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
- if (m_leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || (iteration>= (maxIterations-1)))
+ if (m_leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || (iteration >= (maxIterations - 1)))
{
#ifdef VERBOSE_RESIDUAL_PRINTF
- printf("residual = %f at iteration #%d\n",m_leastSquaresResidual,iteration);
+ printf("residual = %f at iteration #%d\n", m_leastSquaresResidual, iteration);
#endif
break;
}
}
-
}
return 0.f;
}
void btSequentialImpulseConstraintSolver::writeBackContacts(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
{
- for (int j=iBegin; j<iEnd; j++)
- {
- const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[j];
- btManifoldPoint* pt = (btManifoldPoint*) solveManifold.m_originalContactPoint;
- btAssert(pt);
- pt->m_appliedImpulse = solveManifold.m_appliedImpulse;
+ for (int j = iBegin; j < iEnd; j++)
+ {
+ const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[j];
+ btManifoldPoint* pt = (btManifoldPoint*)solveManifold.m_originalContactPoint;
+ btAssert(pt);
+ pt->m_appliedImpulse = solveManifold.m_appliedImpulse;
// float f = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
- // printf("pt->m_appliedImpulseLateral1 = %f\n", f);
- pt->m_appliedImpulseLateral1 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
- //printf("pt->m_appliedImpulseLateral1 = %f\n", pt->m_appliedImpulseLateral1);
- if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
- {
- pt->m_appliedImpulseLateral2 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex+1].m_appliedImpulse;
- }
- //do a callback here?
+ // printf("pt->m_appliedImpulseLateral1 = %f\n", f);
+ pt->m_appliedImpulseLateral1 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
+ //printf("pt->m_appliedImpulseLateral1 = %f\n", pt->m_appliedImpulseLateral1);
+ if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
+ {
+ pt->m_appliedImpulseLateral2 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex + 1].m_appliedImpulse;
}
+ //do a callback here?
+ }
}
void btSequentialImpulseConstraintSolver::writeBackJoints(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
{
- for (int j=iBegin; j<iEnd; j++)
+ for (int j = iBegin; j < iEnd; j++)
{
const btSolverConstraint& solverConstr = m_tmpSolverNonContactConstraintPool[j];
btTypedConstraint* constr = (btTypedConstraint*)solverConstr.m_originalContactPoint;
btJointFeedback* fb = constr->getJointFeedback();
if (fb)
{
- fb->m_appliedForceBodyA += solverConstr.m_contactNormal1*solverConstr.m_appliedImpulse*constr->getRigidBodyA().getLinearFactor()/infoGlobal.m_timeStep;
- fb->m_appliedForceBodyB += solverConstr.m_contactNormal2*solverConstr.m_appliedImpulse*constr->getRigidBodyB().getLinearFactor()/infoGlobal.m_timeStep;
- fb->m_appliedTorqueBodyA += solverConstr.m_relpos1CrossNormal* constr->getRigidBodyA().getAngularFactor()*solverConstr.m_appliedImpulse/infoGlobal.m_timeStep;
- fb->m_appliedTorqueBodyB += solverConstr.m_relpos2CrossNormal* constr->getRigidBodyB().getAngularFactor()*solverConstr.m_appliedImpulse/infoGlobal.m_timeStep; /*RGM ???? */
-
+ fb->m_appliedForceBodyA += solverConstr.m_contactNormal1 * solverConstr.m_appliedImpulse * constr->getRigidBodyA().getLinearFactor() / infoGlobal.m_timeStep;
+ fb->m_appliedForceBodyB += solverConstr.m_contactNormal2 * solverConstr.m_appliedImpulse * constr->getRigidBodyB().getLinearFactor() / infoGlobal.m_timeStep;
+ fb->m_appliedTorqueBodyA += solverConstr.m_relpos1CrossNormal * constr->getRigidBodyA().getAngularFactor() * solverConstr.m_appliedImpulse / infoGlobal.m_timeStep;
+ fb->m_appliedTorqueBodyB += solverConstr.m_relpos2CrossNormal * constr->getRigidBodyB().getAngularFactor() * solverConstr.m_appliedImpulse / infoGlobal.m_timeStep; /*RGM ???? */
}
constr->internalSetAppliedImpulse(solverConstr.m_appliedImpulse);
- if (btFabs(solverConstr.m_appliedImpulse)>=constr->getBreakingImpulseThreshold())
+ if (btFabs(solverConstr.m_appliedImpulse) >= constr->getBreakingImpulseThreshold())
{
constr->setEnabled(false);
}
}
}
-
void btSequentialImpulseConstraintSolver::writeBackBodies(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
{
- for (int i=iBegin; i<iEnd; i++)
+ for (int i = iBegin; i < iEnd; i++)
{
btRigidBody* body = m_tmpSolverBodyPool[i].m_originalBody;
if (body)
@@ -1944,11 +1832,11 @@ void btSequentialImpulseConstraintSolver::writeBackBodies(int iBegin, int iEnd,
m_tmpSolverBodyPool[i].writebackVelocity();
m_tmpSolverBodyPool[i].m_originalBody->setLinearVelocity(
- m_tmpSolverBodyPool[i].m_linearVelocity+
+ m_tmpSolverBodyPool[i].m_linearVelocity +
m_tmpSolverBodyPool[i].m_externalForceImpulse);
m_tmpSolverBodyPool[i].m_originalBody->setAngularVelocity(
- m_tmpSolverBodyPool[i].m_angularVelocity+
+ m_tmpSolverBodyPool[i].m_angularVelocity +
m_tmpSolverBodyPool[i].m_externalTorqueImpulse);
if (infoGlobal.m_splitImpulse)
@@ -1959,17 +1847,17 @@ void btSequentialImpulseConstraintSolver::writeBackBodies(int iBegin, int iEnd,
}
}
-btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionObject** bodies,int numBodies,const btContactSolverInfo& infoGlobal)
+btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
{
BT_PROFILE("solveGroupCacheFriendlyFinish");
if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
{
- writeBackContacts(0, m_tmpSolverContactConstraintPool.size(), infoGlobal);
+ writeBackContacts(0, m_tmpSolverContactConstraintPool.size(), infoGlobal);
}
- writeBackJoints(0, m_tmpSolverNonContactConstraintPool.size(), infoGlobal);
- writeBackBodies(0, m_tmpSolverBodyPool.size(), infoGlobal);
+ writeBackJoints(0, m_tmpSolverNonContactConstraintPool.size(), infoGlobal);
+ writeBackBodies(0, m_tmpSolverBodyPool.size(), infoGlobal);
m_tmpSolverContactConstraintPool.resizeNoInitialize(0);
m_tmpSolverNonContactConstraintPool.resizeNoInitialize(0);
@@ -1980,25 +1868,22 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish(btCo
return 0.f;
}
-
-
/// btSequentialImpulseConstraintSolver Sequentially applies impulses
-btScalar btSequentialImpulseConstraintSolver::solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btDispatcher* /*dispatcher*/)
+btScalar btSequentialImpulseConstraintSolver::solveGroup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer, btDispatcher* /*dispatcher*/)
{
-
BT_PROFILE("solveGroup");
//you need to provide at least some bodies
- solveGroupCacheFriendlySetup( bodies, numBodies, manifoldPtr, numManifolds,constraints, numConstraints,infoGlobal,debugDrawer);
+ solveGroupCacheFriendlySetup(bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
- solveGroupCacheFriendlyIterations(bodies, numBodies, manifoldPtr, numManifolds,constraints, numConstraints,infoGlobal,debugDrawer);
+ solveGroupCacheFriendlyIterations(bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
solveGroupCacheFriendlyFinish(bodies, numBodies, infoGlobal);
return 0.f;
}
-void btSequentialImpulseConstraintSolver::reset()
+void btSequentialImpulseConstraintSolver::reset()
{
m_btSeed2 = 0;
}
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h
index b834c3dac3..70db83b063 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h
@@ -27,147 +27,142 @@ class btCollisionObject;
#include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h"
#include "BulletDynamics/ConstraintSolver/btConstraintSolver.h"
-typedef btScalar(*btSingleConstraintRowSolver)(btSolverBody&, btSolverBody&, const btSolverConstraint&);
+typedef btScalar (*btSingleConstraintRowSolver)(btSolverBody&, btSolverBody&, const btSolverConstraint&);
///The btSequentialImpulseConstraintSolver is a fast SIMD implementation of the Projected Gauss Seidel (iterative LCP) method.
-ATTRIBUTE_ALIGNED16(class) btSequentialImpulseConstraintSolver : public btConstraintSolver
+ATTRIBUTE_ALIGNED16(class)
+btSequentialImpulseConstraintSolver : public btConstraintSolver
{
protected:
- btAlignedObjectArray<btSolverBody> m_tmpSolverBodyPool;
- btConstraintArray m_tmpSolverContactConstraintPool;
- btConstraintArray m_tmpSolverNonContactConstraintPool;
- btConstraintArray m_tmpSolverContactFrictionConstraintPool;
- btConstraintArray m_tmpSolverContactRollingFrictionConstraintPool;
-
- btAlignedObjectArray<int> m_orderTmpConstraintPool;
- btAlignedObjectArray<int> m_orderNonContactConstraintPool;
- btAlignedObjectArray<int> m_orderFrictionConstraintPool;
+ btAlignedObjectArray<btSolverBody> m_tmpSolverBodyPool;
+ btConstraintArray m_tmpSolverContactConstraintPool;
+ btConstraintArray m_tmpSolverNonContactConstraintPool;
+ btConstraintArray m_tmpSolverContactFrictionConstraintPool;
+ btConstraintArray m_tmpSolverContactRollingFrictionConstraintPool;
+
+ btAlignedObjectArray<int> m_orderTmpConstraintPool;
+ btAlignedObjectArray<int> m_orderNonContactConstraintPool;
+ btAlignedObjectArray<int> m_orderFrictionConstraintPool;
btAlignedObjectArray<btTypedConstraint::btConstraintInfo1> m_tmpConstraintSizesPool;
- int m_maxOverrideNumSolverIterations;
+ int m_maxOverrideNumSolverIterations;
int m_fixedBodyId;
- // When running solvers on multiple threads, a race condition exists for Kinematic objects that
- // participate in more than one solver.
- // The getOrInitSolverBody() function writes the companionId of each body (storing the index of the solver body
- // for the current solver). For normal dynamic bodies it isn't an issue because they can only be in one island
- // (and therefore one thread) at a time. But kinematic bodies can be in multiple islands at once.
- // To avoid this race condition, this solver does not write the companionId, instead it stores the solver body
- // index in this solver-local table, indexed by the uniqueId of the body.
- btAlignedObjectArray<int> m_kinematicBodyUniqueIdToSolverBodyTable; // only used for multithreading
+ // When running solvers on multiple threads, a race condition exists for Kinematic objects that
+ // participate in more than one solver.
+ // The getOrInitSolverBody() function writes the companionId of each body (storing the index of the solver body
+ // for the current solver). For normal dynamic bodies it isn't an issue because they can only be in one island
+ // (and therefore one thread) at a time. But kinematic bodies can be in multiple islands at once.
+ // To avoid this race condition, this solver does not write the companionId, instead it stores the solver body
+ // index in this solver-local table, indexed by the uniqueId of the body.
+ btAlignedObjectArray<int> m_kinematicBodyUniqueIdToSolverBodyTable; // only used for multithreading
btSingleConstraintRowSolver m_resolveSingleConstraintRowGeneric;
btSingleConstraintRowSolver m_resolveSingleConstraintRowLowerLimit;
- btSingleConstraintRowSolver m_resolveSplitPenetrationImpulse;
- int m_cachedSolverMode; // used to check if SOLVER_SIMD flag has been changed
- void setupSolverFunctions( bool useSimd );
+ btSingleConstraintRowSolver m_resolveSplitPenetrationImpulse;
+ int m_cachedSolverMode; // used to check if SOLVER_SIMD flag has been changed
+ void setupSolverFunctions(bool useSimd);
- btScalar m_leastSquaresResidual;
+ btScalar m_leastSquaresResidual;
- void setupFrictionConstraint( btSolverConstraint& solverConstraint, const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,
- btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,
- btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation,
- const btContactSolverInfo& infoGlobal,
- btScalar desiredVelocity=0., btScalar cfmSlip=0.);
+ void setupFrictionConstraint(btSolverConstraint & solverConstraint, const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB,
+ btManifoldPoint& cp, const btVector3& rel_pos1, const btVector3& rel_pos2,
+ btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation,
+ const btContactSolverInfo& infoGlobal,
+ btScalar desiredVelocity = 0., btScalar cfmSlip = 0.);
- void setupTorsionalFrictionConstraint( btSolverConstraint& solverConstraint, const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,
- btManifoldPoint& cp,btScalar combinedTorsionalFriction, const btVector3& rel_pos1,const btVector3& rel_pos2,
- btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation,
- btScalar desiredVelocity=0., btScalar cfmSlip=0.);
+ void setupTorsionalFrictionConstraint(btSolverConstraint & solverConstraint, const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB,
+ btManifoldPoint& cp, btScalar combinedTorsionalFriction, const btVector3& rel_pos1, const btVector3& rel_pos2,
+ btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation,
+ btScalar desiredVelocity = 0., btScalar cfmSlip = 0.);
- btSolverConstraint& addFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity=0., btScalar cfmSlip=0.);
- btSolverConstraint& addTorsionalFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,btScalar torsionalFriction, const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity=0, btScalar cfmSlip=0.f);
+ btSolverConstraint& addFrictionConstraint(const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, btManifoldPoint& cp, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity = 0., btScalar cfmSlip = 0.);
+ btSolverConstraint& addTorsionalFrictionConstraint(const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, btManifoldPoint& cp, btScalar torsionalFriction, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity = 0, btScalar cfmSlip = 0.f);
+ void setupContactConstraint(btSolverConstraint & solverConstraint, int solverBodyIdA, int solverBodyIdB, btManifoldPoint& cp,
+ const btContactSolverInfo& infoGlobal, btScalar& relaxation, const btVector3& rel_pos1, const btVector3& rel_pos2);
- void setupContactConstraint(btSolverConstraint& solverConstraint, int solverBodyIdA, int solverBodyIdB, btManifoldPoint& cp,
- const btContactSolverInfo& infoGlobal,btScalar& relaxation, const btVector3& rel_pos1, const btVector3& rel_pos2);
+ static void applyAnisotropicFriction(btCollisionObject * colObj, btVector3 & frictionDirection, int frictionMode);
- static void applyAnisotropicFriction(btCollisionObject* colObj,btVector3& frictionDirection, int frictionMode);
-
- void setFrictionConstraintImpulse( btSolverConstraint& solverConstraint, int solverBodyIdA,int solverBodyIdB,
- btManifoldPoint& cp, const btContactSolverInfo& infoGlobal);
+ void setFrictionConstraintImpulse(btSolverConstraint & solverConstraint, int solverBodyIdA, int solverBodyIdB,
+ btManifoldPoint& cp, const btContactSolverInfo& infoGlobal);
///m_btSeed2 is used for re-arranging the constraint rows. improves convergence/quality of friction
- unsigned long m_btSeed2;
-
+ unsigned long m_btSeed2;
btScalar restitutionCurve(btScalar rel_vel, btScalar restitution, btScalar velocityThreshold);
- virtual void convertContacts(btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal);
+ virtual void convertContacts(btPersistentManifold * *manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal);
- void convertContact(btPersistentManifold* manifold,const btContactSolverInfo& infoGlobal);
+ void convertContact(btPersistentManifold * manifold, const btContactSolverInfo& infoGlobal);
- virtual void convertJoints(btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal);
- void convertJoint(btSolverConstraint* currentConstraintRow, btTypedConstraint* constraint, const btTypedConstraint::btConstraintInfo1& info1, int solverBodyIdA, int solverBodyIdB, const btContactSolverInfo& infoGlobal);
+ virtual void convertJoints(btTypedConstraint * *constraints, int numConstraints, const btContactSolverInfo& infoGlobal);
+ void convertJoint(btSolverConstraint * currentConstraintRow, btTypedConstraint * constraint, const btTypedConstraint::btConstraintInfo1& info1, int solverBodyIdA, int solverBodyIdB, const btContactSolverInfo& infoGlobal);
- virtual void convertBodies(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal);
+ virtual void convertBodies(btCollisionObject * *bodies, int numBodies, const btContactSolverInfo& infoGlobal);
- btScalar resolveSplitPenetrationSIMD(btSolverBody& bodyA,btSolverBody& bodyB, const btSolverConstraint& contactConstraint)
- {
- return m_resolveSplitPenetrationImpulse( bodyA, bodyB, contactConstraint );
- }
+ btScalar resolveSplitPenetrationSIMD(btSolverBody & bodyA, btSolverBody & bodyB, const btSolverConstraint& contactConstraint)
+ {
+ return m_resolveSplitPenetrationImpulse(bodyA, bodyB, contactConstraint);
+ }
- btScalar resolveSplitPenetrationImpulseCacheFriendly(btSolverBody& bodyA,btSolverBody& bodyB, const btSolverConstraint& contactConstraint)
- {
- return m_resolveSplitPenetrationImpulse( bodyA, bodyB, contactConstraint );
- }
+ btScalar resolveSplitPenetrationImpulseCacheFriendly(btSolverBody & bodyA, btSolverBody & bodyB, const btSolverConstraint& contactConstraint)
+ {
+ return m_resolveSplitPenetrationImpulse(bodyA, bodyB, contactConstraint);
+ }
//internal method
- int getOrInitSolverBody(btCollisionObject& body,btScalar timeStep);
- void initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject, btScalar timeStep);
-
- btScalar resolveSingleConstraintRowGeneric(btSolverBody& bodyA,btSolverBody& bodyB,const btSolverConstraint& contactConstraint);
- btScalar resolveSingleConstraintRowGenericSIMD(btSolverBody& bodyA,btSolverBody& bodyB,const btSolverConstraint& contactConstraint);
- btScalar resolveSingleConstraintRowLowerLimit(btSolverBody& bodyA,btSolverBody& bodyB,const btSolverConstraint& contactConstraint);
- btScalar resolveSingleConstraintRowLowerLimitSIMD(btSolverBody& bodyA,btSolverBody& bodyB,const btSolverConstraint& contactConstraint);
- btScalar resolveSplitPenetrationImpulse(btSolverBody& bodyA,btSolverBody& bodyB, const btSolverConstraint& contactConstraint)
- {
- return m_resolveSplitPenetrationImpulse( bodyA, bodyB, contactConstraint );
- }
+ int getOrInitSolverBody(btCollisionObject & body, btScalar timeStep);
+ void initSolverBody(btSolverBody * solverBody, btCollisionObject * collisionObject, btScalar timeStep);
+
+ btScalar resolveSingleConstraintRowGeneric(btSolverBody & bodyA, btSolverBody & bodyB, const btSolverConstraint& contactConstraint);
+ btScalar resolveSingleConstraintRowGenericSIMD(btSolverBody & bodyA, btSolverBody & bodyB, const btSolverConstraint& contactConstraint);
+ btScalar resolveSingleConstraintRowLowerLimit(btSolverBody & bodyA, btSolverBody & bodyB, const btSolverConstraint& contactConstraint);
+ btScalar resolveSingleConstraintRowLowerLimitSIMD(btSolverBody & bodyA, btSolverBody & bodyB, const btSolverConstraint& contactConstraint);
+ btScalar resolveSplitPenetrationImpulse(btSolverBody & bodyA, btSolverBody & bodyB, const btSolverConstraint& contactConstraint)
+ {
+ return m_resolveSplitPenetrationImpulse(bodyA, bodyB, contactConstraint);
+ }
protected:
+ void writeBackContacts(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
+ void writeBackJoints(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
+ void writeBackBodies(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
+ virtual void solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
+ virtual btScalar solveGroupCacheFriendlyFinish(btCollisionObject * *bodies, int numBodies, const btContactSolverInfo& infoGlobal);
+ virtual btScalar solveSingleIteration(int iteration, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
- void writeBackContacts(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
- void writeBackJoints(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
- void writeBackBodies(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
- virtual void solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer);
- virtual btScalar solveGroupCacheFriendlyFinish(btCollisionObject** bodies,int numBodies,const btContactSolverInfo& infoGlobal);
- virtual btScalar solveSingleIteration(int iteration, btCollisionObject** bodies ,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer);
-
- virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer);
- virtual btScalar solveGroupCacheFriendlyIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer);
-
+ virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
+ virtual btScalar solveGroupCacheFriendlyIterations(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
public:
-
BT_DECLARE_ALIGNED_ALLOCATOR();
btSequentialImpulseConstraintSolver();
virtual ~btSequentialImpulseConstraintSolver();
- virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& info, btIDebugDraw* debugDrawer,btDispatcher* dispatcher);
+ virtual btScalar solveGroup(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifold, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btDispatcher* dispatcher);
///clear internal cached data and reset random seed
- virtual void reset();
+ virtual void reset();
unsigned long btRand2();
- int btRandInt2 (int n);
+ int btRandInt2(int n);
- void setRandSeed(unsigned long seed)
+ void setRandSeed(unsigned long seed)
{
m_btSeed2 = seed;
}
- unsigned long getRandSeed() const
+ unsigned long getRandSeed() const
{
return m_btSeed2;
}
-
- virtual btConstraintSolverType getSolverType() const
+ virtual btConstraintSolverType getSolverType() const
{
return BT_SEQUENTIAL_IMPULSE_SOLVER;
}
- btSingleConstraintRowSolver getActiveConstraintRowSolverGeneric()
+ btSingleConstraintRowSolver getActiveConstraintRowSolverGeneric()
{
return m_resolveSingleConstraintRowGeneric;
}
@@ -175,7 +170,7 @@ public:
{
m_resolveSingleConstraintRowGeneric = rowSolver;
}
- btSingleConstraintRowSolver getActiveConstraintRowSolverLowerLimit()
+ btSingleConstraintRowSolver getActiveConstraintRowSolverLowerLimit()
{
return m_resolveSingleConstraintRowLowerLimit;
}
@@ -185,18 +180,14 @@ public:
}
///Various implementations of solving a single constraint row using a generic equality constraint, using scalar reference, SSE2 or SSE4
- btSingleConstraintRowSolver getScalarConstraintRowSolverGeneric();
- btSingleConstraintRowSolver getSSE2ConstraintRowSolverGeneric();
- btSingleConstraintRowSolver getSSE4_1ConstraintRowSolverGeneric();
+ btSingleConstraintRowSolver getScalarConstraintRowSolverGeneric();
+ btSingleConstraintRowSolver getSSE2ConstraintRowSolverGeneric();
+ btSingleConstraintRowSolver getSSE4_1ConstraintRowSolverGeneric();
///Various implementations of solving a single constraint row using an inequality (lower limit) constraint, using scalar reference, SSE2 or SSE4
- btSingleConstraintRowSolver getScalarConstraintRowSolverLowerLimit();
- btSingleConstraintRowSolver getSSE2ConstraintRowSolverLowerLimit();
- btSingleConstraintRowSolver getSSE4_1ConstraintRowSolverLowerLimit();
+ btSingleConstraintRowSolver getScalarConstraintRowSolverLowerLimit();
+ btSingleConstraintRowSolver getSSE2ConstraintRowSolverLowerLimit();
+ btSingleConstraintRowSolver getSSE4_1ConstraintRowSolverLowerLimit();
};
-
-
-
-#endif //BT_SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H
-
+#endif //BT_SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.cpp
index 4306c37e49..2718da4a50 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.cpp
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.cpp
@@ -13,7 +13,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#include "btSequentialImpulseConstraintSolverMt.h"
#include "LinearMath/btQuickprof.h"
@@ -23,8 +22,6 @@ subject to the following restrictions:
#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
#include "BulletDynamics/Dynamics/btRigidBody.h"
-
-
bool btSequentialImpulseConstraintSolverMt::s_allowNestedParallelForLoops = false; // some task schedulers don't like nested loops
int btSequentialImpulseConstraintSolverMt::s_minimumContactManifoldsForBatching = 250;
int btSequentialImpulseConstraintSolverMt::s_minBatchSize = 50;
@@ -32,613 +29,594 @@ int btSequentialImpulseConstraintSolverMt::s_maxBatchSize = 100;
btBatchedConstraints::BatchingMethod btSequentialImpulseConstraintSolverMt::s_contactBatchingMethod = btBatchedConstraints::BATCHING_METHOD_SPATIAL_GRID_2D;
btBatchedConstraints::BatchingMethod btSequentialImpulseConstraintSolverMt::s_jointBatchingMethod = btBatchedConstraints::BATCHING_METHOD_SPATIAL_GRID_2D;
-
btSequentialImpulseConstraintSolverMt::btSequentialImpulseConstraintSolverMt()
{
- m_numFrictionDirections = 1;
- m_useBatching = false;
- m_useObsoleteJointConstraints = false;
+ m_numFrictionDirections = 1;
+ m_useBatching = false;
+ m_useObsoleteJointConstraints = false;
}
-
btSequentialImpulseConstraintSolverMt::~btSequentialImpulseConstraintSolverMt()
{
}
-
void btSequentialImpulseConstraintSolverMt::setupBatchedContactConstraints()
{
- BT_PROFILE("setupBatchedContactConstraints");
- m_batchedContactConstraints.setup( &m_tmpSolverContactConstraintPool,
- m_tmpSolverBodyPool,
- s_contactBatchingMethod,
- s_minBatchSize,
- s_maxBatchSize,
- &m_scratchMemory
- );
+ BT_PROFILE("setupBatchedContactConstraints");
+ m_batchedContactConstraints.setup(&m_tmpSolverContactConstraintPool,
+ m_tmpSolverBodyPool,
+ s_contactBatchingMethod,
+ s_minBatchSize,
+ s_maxBatchSize,
+ &m_scratchMemory);
}
-
void btSequentialImpulseConstraintSolverMt::setupBatchedJointConstraints()
{
- BT_PROFILE("setupBatchedJointConstraints");
- m_batchedJointConstraints.setup( &m_tmpSolverNonContactConstraintPool,
- m_tmpSolverBodyPool,
- s_jointBatchingMethod,
- s_minBatchSize,
- s_maxBatchSize,
- &m_scratchMemory
- );
+ BT_PROFILE("setupBatchedJointConstraints");
+ m_batchedJointConstraints.setup(&m_tmpSolverNonContactConstraintPool,
+ m_tmpSolverBodyPool,
+ s_jointBatchingMethod,
+ s_minBatchSize,
+ s_maxBatchSize,
+ &m_scratchMemory);
}
-
void btSequentialImpulseConstraintSolverMt::internalSetupContactConstraints(int iContactConstraint, const btContactSolverInfo& infoGlobal)
{
- btSolverConstraint& contactConstraint = m_tmpSolverContactConstraintPool[iContactConstraint];
-
- btVector3 rel_pos1;
- btVector3 rel_pos2;
- btScalar relaxation;
-
- int solverBodyIdA = contactConstraint.m_solverBodyIdA;
- int solverBodyIdB = contactConstraint.m_solverBodyIdB;
-
- btSolverBody* solverBodyA = &m_tmpSolverBodyPool[ solverBodyIdA ];
- btSolverBody* solverBodyB = &m_tmpSolverBodyPool[ solverBodyIdB ];
-
- btRigidBody* colObj0 = solverBodyA->m_originalBody;
- btRigidBody* colObj1 = solverBodyB->m_originalBody;
-
- btManifoldPoint& cp = *static_cast<btManifoldPoint*>( contactConstraint.m_originalContactPoint );
-
- const btVector3& pos1 = cp.getPositionWorldOnA();
- const btVector3& pos2 = cp.getPositionWorldOnB();
-
- rel_pos1 = pos1 - solverBodyA->getWorldTransform().getOrigin();
- rel_pos2 = pos2 - solverBodyB->getWorldTransform().getOrigin();
-
- btVector3 vel1;
- btVector3 vel2;
-
- solverBodyA->getVelocityInLocalPointNoDelta( rel_pos1, vel1 );
- solverBodyB->getVelocityInLocalPointNoDelta( rel_pos2, vel2 );
-
- btVector3 vel = vel1 - vel2;
- btScalar rel_vel = cp.m_normalWorldOnB.dot( vel );
-
- setupContactConstraint( contactConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal, relaxation, rel_pos1, rel_pos2 );
-
- // setup rolling friction constraints
- int rollingFrictionIndex = m_rollingFrictionIndexTable[iContactConstraint];
- if (rollingFrictionIndex >= 0)
- {
- btSolverConstraint& spinningFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[ rollingFrictionIndex ];
- btAssert( spinningFrictionConstraint.m_frictionIndex == iContactConstraint );
- setupTorsionalFrictionConstraint( spinningFrictionConstraint,
- cp.m_normalWorldOnB,
- solverBodyIdA,
- solverBodyIdB,
- cp,
- cp.m_combinedSpinningFriction,
- rel_pos1,
- rel_pos2,
- colObj0,
- colObj1,
- relaxation,
- 0.0f,
- 0.0f
- );
- btVector3 axis[2];
- btPlaneSpace1( cp.m_normalWorldOnB, axis[0], axis[1] );
- axis[0].normalize();
- axis[1].normalize();
-
- applyAnisotropicFriction( colObj0, axis[0], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION );
- applyAnisotropicFriction( colObj1, axis[0], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION );
- applyAnisotropicFriction( colObj0, axis[1], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION );
- applyAnisotropicFriction( colObj1, axis[1], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION );
- // put the largest axis first
- if (axis[1].length2() > axis[0].length2())
- {
- btSwap(axis[0], axis[1]);
- }
- const btScalar kRollingFrictionThreshold = 0.001f;
- for (int i = 0; i < 2; ++i)
- {
- int iRollingFric = rollingFrictionIndex + 1 + i;
- btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[ iRollingFric ];
- btAssert(rollingFrictionConstraint.m_frictionIndex == iContactConstraint);
- btVector3 dir = axis[i];
- if ( dir.length() > kRollingFrictionThreshold )
- {
- setupTorsionalFrictionConstraint( rollingFrictionConstraint,
- dir,
- solverBodyIdA,
- solverBodyIdB,
- cp,
- cp.m_combinedRollingFriction,
- rel_pos1,
- rel_pos2,
- colObj0,
- colObj1,
- relaxation,
- 0.0f,
- 0.0f
- );
- }
- else
- {
- rollingFrictionConstraint.m_frictionIndex = -1; // disable constraint
- }
- }
- }
-
- // setup friction constraints
- // setupFrictionConstraint(solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, desiredVelocity, cfmSlip);
- {
- ///Bullet has several options to set the friction directions
- ///By default, each contact has only a single friction direction that is recomputed automatically very frame
- ///based on the relative linear velocity.
- ///If the relative velocity it zero, it will automatically compute a friction direction.
-
- ///You can also enable two friction directions, using the SOLVER_USE_2_FRICTION_DIRECTIONS.
- ///In that case, the second friction direction will be orthogonal to both contact normal and first friction direction.
- ///
- ///If you choose SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION, then the friction will be independent from the relative projected velocity.
- ///
- ///The user can manually override the friction directions for certain contacts using a contact callback,
- ///and set the cp.m_lateralFrictionInitialized to true
- ///In that case, you can set the target relative motion in each friction direction (cp.m_contactMotion1 and cp.m_contactMotion2)
- ///this will give a conveyor belt effect
- ///
- btSolverConstraint* frictionConstraint1 = &m_tmpSolverContactFrictionConstraintPool[contactConstraint.m_frictionIndex];
- btAssert(frictionConstraint1->m_frictionIndex == iContactConstraint);
-
- btSolverConstraint* frictionConstraint2 = NULL;
- if ( infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS )
- {
- frictionConstraint2 = &m_tmpSolverContactFrictionConstraintPool[contactConstraint.m_frictionIndex + 1];
- btAssert( frictionConstraint2->m_frictionIndex == iContactConstraint );
- }
-
- if ( !( infoGlobal.m_solverMode & SOLVER_ENABLE_FRICTION_DIRECTION_CACHING ) || !( cp.m_contactPointFlags&BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED ) )
- {
- cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel;
- btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2();
- if ( !( infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION ) && lat_rel_vel > SIMD_EPSILON )
- {
- cp.m_lateralFrictionDir1 *= 1.f / btSqrt( lat_rel_vel );
- applyAnisotropicFriction( colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION );
- applyAnisotropicFriction( colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION );
- setupFrictionConstraint( *frictionConstraint1, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal );
-
- if ( frictionConstraint2 )
- {
- cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross( cp.m_normalWorldOnB );
- cp.m_lateralFrictionDir2.normalize();//??
- applyAnisotropicFriction( colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION );
- applyAnisotropicFriction( colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION );
- setupFrictionConstraint( *frictionConstraint2, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal );
- }
- }
- else
- {
- btPlaneSpace1( cp.m_normalWorldOnB, cp.m_lateralFrictionDir1, cp.m_lateralFrictionDir2 );
-
- applyAnisotropicFriction( colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION );
- applyAnisotropicFriction( colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION );
- setupFrictionConstraint( *frictionConstraint1, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal );
-
- if ( frictionConstraint2 )
- {
- applyAnisotropicFriction( colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION );
- applyAnisotropicFriction( colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION );
- setupFrictionConstraint( *frictionConstraint2, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal );
- }
-
- if ( ( infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS ) && ( infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION ) )
- {
- cp.m_contactPointFlags |= BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED;
- }
- }
- }
- else
- {
- setupFrictionConstraint( *frictionConstraint1, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion1, cp.m_frictionCFM );
- if ( frictionConstraint2 )
- {
- setupFrictionConstraint( *frictionConstraint2, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion2, cp.m_frictionCFM );
- }
- }
- }
-
- setFrictionConstraintImpulse( contactConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal );
-}
+ btSolverConstraint& contactConstraint = m_tmpSolverContactConstraintPool[iContactConstraint];
+
+ btVector3 rel_pos1;
+ btVector3 rel_pos2;
+ btScalar relaxation;
+
+ int solverBodyIdA = contactConstraint.m_solverBodyIdA;
+ int solverBodyIdB = contactConstraint.m_solverBodyIdB;
+
+ btSolverBody* solverBodyA = &m_tmpSolverBodyPool[solverBodyIdA];
+ btSolverBody* solverBodyB = &m_tmpSolverBodyPool[solverBodyIdB];
+
+ btRigidBody* colObj0 = solverBodyA->m_originalBody;
+ btRigidBody* colObj1 = solverBodyB->m_originalBody;
+
+ btManifoldPoint& cp = *static_cast<btManifoldPoint*>(contactConstraint.m_originalContactPoint);
+
+ const btVector3& pos1 = cp.getPositionWorldOnA();
+ const btVector3& pos2 = cp.getPositionWorldOnB();
+
+ rel_pos1 = pos1 - solverBodyA->getWorldTransform().getOrigin();
+ rel_pos2 = pos2 - solverBodyB->getWorldTransform().getOrigin();
+
+ btVector3 vel1;
+ btVector3 vel2;
+
+ solverBodyA->getVelocityInLocalPointNoDelta(rel_pos1, vel1);
+ solverBodyB->getVelocityInLocalPointNoDelta(rel_pos2, vel2);
+
+ btVector3 vel = vel1 - vel2;
+ btScalar rel_vel = cp.m_normalWorldOnB.dot(vel);
+
+ setupContactConstraint(contactConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal, relaxation, rel_pos1, rel_pos2);
+
+ // setup rolling friction constraints
+ int rollingFrictionIndex = m_rollingFrictionIndexTable[iContactConstraint];
+ if (rollingFrictionIndex >= 0)
+ {
+ btSolverConstraint& spinningFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[rollingFrictionIndex];
+ btAssert(spinningFrictionConstraint.m_frictionIndex == iContactConstraint);
+ setupTorsionalFrictionConstraint(spinningFrictionConstraint,
+ cp.m_normalWorldOnB,
+ solverBodyIdA,
+ solverBodyIdB,
+ cp,
+ cp.m_combinedSpinningFriction,
+ rel_pos1,
+ rel_pos2,
+ colObj0,
+ colObj1,
+ relaxation,
+ 0.0f,
+ 0.0f);
+ btVector3 axis[2];
+ btPlaneSpace1(cp.m_normalWorldOnB, axis[0], axis[1]);
+ axis[0].normalize();
+ axis[1].normalize();
+
+ applyAnisotropicFriction(colObj0, axis[0], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
+ applyAnisotropicFriction(colObj1, axis[0], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
+ applyAnisotropicFriction(colObj0, axis[1], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
+ applyAnisotropicFriction(colObj1, axis[1], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
+ // put the largest axis first
+ if (axis[1].length2() > axis[0].length2())
+ {
+ btSwap(axis[0], axis[1]);
+ }
+ const btScalar kRollingFrictionThreshold = 0.001f;
+ for (int i = 0; i < 2; ++i)
+ {
+ int iRollingFric = rollingFrictionIndex + 1 + i;
+ btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[iRollingFric];
+ btAssert(rollingFrictionConstraint.m_frictionIndex == iContactConstraint);
+ btVector3 dir = axis[i];
+ if (dir.length() > kRollingFrictionThreshold)
+ {
+ setupTorsionalFrictionConstraint(rollingFrictionConstraint,
+ dir,
+ solverBodyIdA,
+ solverBodyIdB,
+ cp,
+ cp.m_combinedRollingFriction,
+ rel_pos1,
+ rel_pos2,
+ colObj0,
+ colObj1,
+ relaxation,
+ 0.0f,
+ 0.0f);
+ }
+ else
+ {
+ rollingFrictionConstraint.m_frictionIndex = -1; // disable constraint
+ }
+ }
+ }
+
+ // setup friction constraints
+ // setupFrictionConstraint(solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, desiredVelocity, cfmSlip);
+ {
+ ///Bullet has several options to set the friction directions
+ ///By default, each contact has only a single friction direction that is recomputed automatically very frame
+ ///based on the relative linear velocity.
+ ///If the relative velocity it zero, it will automatically compute a friction direction.
+
+ ///You can also enable two friction directions, using the SOLVER_USE_2_FRICTION_DIRECTIONS.
+ ///In that case, the second friction direction will be orthogonal to both contact normal and first friction direction.
+ ///
+ ///If you choose SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION, then the friction will be independent from the relative projected velocity.
+ ///
+ ///The user can manually override the friction directions for certain contacts using a contact callback,
+ ///and set the cp.m_lateralFrictionInitialized to true
+ ///In that case, you can set the target relative motion in each friction direction (cp.m_contactMotion1 and cp.m_contactMotion2)
+ ///this will give a conveyor belt effect
+ ///
+ btSolverConstraint* frictionConstraint1 = &m_tmpSolverContactFrictionConstraintPool[contactConstraint.m_frictionIndex];
+ btAssert(frictionConstraint1->m_frictionIndex == iContactConstraint);
+
+ btSolverConstraint* frictionConstraint2 = NULL;
+ if (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)
+ {
+ frictionConstraint2 = &m_tmpSolverContactFrictionConstraintPool[contactConstraint.m_frictionIndex + 1];
+ btAssert(frictionConstraint2->m_frictionIndex == iContactConstraint);
+ }
+
+ if (!(infoGlobal.m_solverMode & SOLVER_ENABLE_FRICTION_DIRECTION_CACHING) || !(cp.m_contactPointFlags & BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED))
+ {
+ cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel;
+ btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2();
+ if (!(infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION) && lat_rel_vel > SIMD_EPSILON)
+ {
+ cp.m_lateralFrictionDir1 *= 1.f / btSqrt(lat_rel_vel);
+ applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+ applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+ setupFrictionConstraint(*frictionConstraint1, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
+
+ if (frictionConstraint2)
+ {
+ cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross(cp.m_normalWorldOnB);
+ cp.m_lateralFrictionDir2.normalize(); //??
+ applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+ applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+ setupFrictionConstraint(*frictionConstraint2, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
+ }
+ }
+ else
+ {
+ btPlaneSpace1(cp.m_normalWorldOnB, cp.m_lateralFrictionDir1, cp.m_lateralFrictionDir2);
+
+ applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+ applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+ setupFrictionConstraint(*frictionConstraint1, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
+
+ if (frictionConstraint2)
+ {
+ applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+ applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+ setupFrictionConstraint(*frictionConstraint2, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
+ }
+
+ if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION))
+ {
+ cp.m_contactPointFlags |= BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED;
+ }
+ }
+ }
+ else
+ {
+ setupFrictionConstraint(*frictionConstraint1, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion1, cp.m_frictionCFM);
+ if (frictionConstraint2)
+ {
+ setupFrictionConstraint(*frictionConstraint2, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion2, cp.m_frictionCFM);
+ }
+ }
+ }
+ setFrictionConstraintImpulse(contactConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal);
+}
struct SetupContactConstraintsLoop : public btIParallelForBody
{
- btSequentialImpulseConstraintSolverMt* m_solver;
- const btBatchedConstraints* m_bc;
- const btContactSolverInfo* m_infoGlobal;
-
- SetupContactConstraintsLoop( btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc, const btContactSolverInfo& infoGlobal )
- {
- m_solver = solver;
- m_bc = bc;
- m_infoGlobal = &infoGlobal;
- }
- void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE
- {
- BT_PROFILE( "SetupContactConstraintsLoop" );
- for ( int iBatch = iBegin; iBatch < iEnd; ++iBatch )
- {
- const btBatchedConstraints::Range& batch = m_bc->m_batches[ iBatch ];
- for (int i = batch.begin; i < batch.end; ++i)
- {
- int iContact = m_bc->m_constraintIndices[i];
- m_solver->internalSetupContactConstraints( iContact, *m_infoGlobal );
- }
- }
- }
-};
+ btSequentialImpulseConstraintSolverMt* m_solver;
+ const btBatchedConstraints* m_bc;
+ const btContactSolverInfo* m_infoGlobal;
+ SetupContactConstraintsLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc, const btContactSolverInfo& infoGlobal)
+ {
+ m_solver = solver;
+ m_bc = bc;
+ m_infoGlobal = &infoGlobal;
+ }
+ void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
+ {
+ BT_PROFILE("SetupContactConstraintsLoop");
+ for (int iBatch = iBegin; iBatch < iEnd; ++iBatch)
+ {
+ const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch];
+ for (int i = batch.begin; i < batch.end; ++i)
+ {
+ int iContact = m_bc->m_constraintIndices[i];
+ m_solver->internalSetupContactConstraints(iContact, *m_infoGlobal);
+ }
+ }
+ }
+};
void btSequentialImpulseConstraintSolverMt::setupAllContactConstraints(const btContactSolverInfo& infoGlobal)
{
- BT_PROFILE( "setupAllContactConstraints" );
- if ( m_useBatching )
- {
- const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
- SetupContactConstraintsLoop loop( this, &batchedCons, infoGlobal );
- for ( int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase )
- {
- int iPhase = batchedCons.m_phaseOrder[ iiPhase ];
- const btBatchedConstraints::Range& phase = batchedCons.m_phases[ iPhase ];
- int grainSize = 1;
- btParallelFor( phase.begin, phase.end, grainSize, loop );
- }
- }
- else
- {
- for ( int i = 0; i < m_tmpSolverContactConstraintPool.size(); ++i )
- {
- internalSetupContactConstraints( i, infoGlobal );
- }
- }
+ BT_PROFILE("setupAllContactConstraints");
+ if (m_useBatching)
+ {
+ const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
+ SetupContactConstraintsLoop loop(this, &batchedCons, infoGlobal);
+ for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase)
+ {
+ int iPhase = batchedCons.m_phaseOrder[iiPhase];
+ const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase];
+ int grainSize = 1;
+ btParallelFor(phase.begin, phase.end, grainSize, loop);
+ }
+ }
+ else
+ {
+ for (int i = 0; i < m_tmpSolverContactConstraintPool.size(); ++i)
+ {
+ internalSetupContactConstraints(i, infoGlobal);
+ }
+ }
}
-
-int btSequentialImpulseConstraintSolverMt::getOrInitSolverBodyThreadsafe(btCollisionObject& body,btScalar timeStep)
+int btSequentialImpulseConstraintSolverMt::getOrInitSolverBodyThreadsafe(btCollisionObject& body, btScalar timeStep)
{
- //
- // getOrInitSolverBody is threadsafe only for a single thread per solver (with potentially multiple solvers)
- //
- // getOrInitSolverBodyThreadsafe -- attempts to be fully threadsafe (however may affect determinism)
- //
- int solverBodyId = -1;
- bool isRigidBodyType = btRigidBody::upcast( &body ) != NULL;
- if ( isRigidBodyType && !body.isStaticOrKinematicObject() )
- {
- // dynamic body
- // Dynamic bodies can only be in one island, so it's safe to write to the companionId
- solverBodyId = body.getCompanionId();
- if ( solverBodyId < 0 )
- {
- m_bodySolverArrayMutex.lock();
- // now that we have the lock, check again
- solverBodyId = body.getCompanionId();
- if ( solverBodyId < 0 )
- {
- solverBodyId = m_tmpSolverBodyPool.size();
- btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
- initSolverBody( &solverBody, &body, timeStep );
- body.setCompanionId( solverBodyId );
- }
- m_bodySolverArrayMutex.unlock();
- }
- }
- else if (isRigidBodyType && body.isKinematicObject())
- {
- //
- // NOTE: must test for kinematic before static because some kinematic objects also
- // identify as "static"
- //
- // Kinematic bodies can be in multiple islands at once, so it is a
- // race condition to write to them, so we use an alternate method
- // to record the solverBodyId
- int uniqueId = body.getWorldArrayIndex();
- const int INVALID_SOLVER_BODY_ID = -1;
- if (m_kinematicBodyUniqueIdToSolverBodyTable.size() <= uniqueId )
- {
- m_kinematicBodyUniqueIdToSolverBodyTableMutex.lock();
- // now that we have the lock, check again
- if ( m_kinematicBodyUniqueIdToSolverBodyTable.size() <= uniqueId )
- {
- m_kinematicBodyUniqueIdToSolverBodyTable.resize( uniqueId + 1, INVALID_SOLVER_BODY_ID );
- }
- m_kinematicBodyUniqueIdToSolverBodyTableMutex.unlock();
- }
- solverBodyId = m_kinematicBodyUniqueIdToSolverBodyTable[ uniqueId ];
- // if no table entry yet,
- if ( INVALID_SOLVER_BODY_ID == solverBodyId )
- {
- // need to acquire both locks
- m_kinematicBodyUniqueIdToSolverBodyTableMutex.lock();
- m_bodySolverArrayMutex.lock();
- // now that we have the lock, check again
- solverBodyId = m_kinematicBodyUniqueIdToSolverBodyTable[ uniqueId ];
- if ( INVALID_SOLVER_BODY_ID == solverBodyId )
- {
- // create a table entry for this body
- solverBodyId = m_tmpSolverBodyPool.size();
- btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
- initSolverBody( &solverBody, &body, timeStep );
- m_kinematicBodyUniqueIdToSolverBodyTable[ uniqueId ] = solverBodyId;
- }
- m_bodySolverArrayMutex.unlock();
- m_kinematicBodyUniqueIdToSolverBodyTableMutex.unlock();
- }
- }
- else
- {
- // all fixed bodies (inf mass) get mapped to a single solver id
- if ( m_fixedBodyId < 0 )
- {
- m_bodySolverArrayMutex.lock();
- // now that we have the lock, check again
- if ( m_fixedBodyId < 0 )
- {
- m_fixedBodyId = m_tmpSolverBodyPool.size();
- btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
- initSolverBody( &fixedBody, 0, timeStep );
- }
- m_bodySolverArrayMutex.unlock();
- }
- solverBodyId = m_fixedBodyId;
- }
- btAssert( solverBodyId >= 0 && solverBodyId < m_tmpSolverBodyPool.size() );
+ //
+ // getOrInitSolverBody is threadsafe only for a single thread per solver (with potentially multiple solvers)
+ //
+ // getOrInitSolverBodyThreadsafe -- attempts to be fully threadsafe (however may affect determinism)
+ //
+ int solverBodyId = -1;
+ bool isRigidBodyType = btRigidBody::upcast(&body) != NULL;
+ if (isRigidBodyType && !body.isStaticOrKinematicObject())
+ {
+ // dynamic body
+ // Dynamic bodies can only be in one island, so it's safe to write to the companionId
+ solverBodyId = body.getCompanionId();
+ if (solverBodyId < 0)
+ {
+ m_bodySolverArrayMutex.lock();
+ // now that we have the lock, check again
+ solverBodyId = body.getCompanionId();
+ if (solverBodyId < 0)
+ {
+ solverBodyId = m_tmpSolverBodyPool.size();
+ btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
+ initSolverBody(&solverBody, &body, timeStep);
+ body.setCompanionId(solverBodyId);
+ }
+ m_bodySolverArrayMutex.unlock();
+ }
+ }
+ else if (isRigidBodyType && body.isKinematicObject())
+ {
+ //
+ // NOTE: must test for kinematic before static because some kinematic objects also
+ // identify as "static"
+ //
+ // Kinematic bodies can be in multiple islands at once, so it is a
+ // race condition to write to them, so we use an alternate method
+ // to record the solverBodyId
+ int uniqueId = body.getWorldArrayIndex();
+ const int INVALID_SOLVER_BODY_ID = -1;
+ if (m_kinematicBodyUniqueIdToSolverBodyTable.size() <= uniqueId)
+ {
+ m_kinematicBodyUniqueIdToSolverBodyTableMutex.lock();
+ // now that we have the lock, check again
+ if (m_kinematicBodyUniqueIdToSolverBodyTable.size() <= uniqueId)
+ {
+ m_kinematicBodyUniqueIdToSolverBodyTable.resize(uniqueId + 1, INVALID_SOLVER_BODY_ID);
+ }
+ m_kinematicBodyUniqueIdToSolverBodyTableMutex.unlock();
+ }
+ solverBodyId = m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId];
+ // if no table entry yet,
+ if (INVALID_SOLVER_BODY_ID == solverBodyId)
+ {
+ // need to acquire both locks
+ m_kinematicBodyUniqueIdToSolverBodyTableMutex.lock();
+ m_bodySolverArrayMutex.lock();
+ // now that we have the lock, check again
+ solverBodyId = m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId];
+ if (INVALID_SOLVER_BODY_ID == solverBodyId)
+ {
+ // create a table entry for this body
+ solverBodyId = m_tmpSolverBodyPool.size();
+ btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
+ initSolverBody(&solverBody, &body, timeStep);
+ m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId] = solverBodyId;
+ }
+ m_bodySolverArrayMutex.unlock();
+ m_kinematicBodyUniqueIdToSolverBodyTableMutex.unlock();
+ }
+ }
+ else
+ {
+ // all fixed bodies (inf mass) get mapped to a single solver id
+ if (m_fixedBodyId < 0)
+ {
+ m_bodySolverArrayMutex.lock();
+ // now that we have the lock, check again
+ if (m_fixedBodyId < 0)
+ {
+ m_fixedBodyId = m_tmpSolverBodyPool.size();
+ btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
+ initSolverBody(&fixedBody, 0, timeStep);
+ }
+ m_bodySolverArrayMutex.unlock();
+ }
+ solverBodyId = m_fixedBodyId;
+ }
+ btAssert(solverBodyId >= 0 && solverBodyId < m_tmpSolverBodyPool.size());
return solverBodyId;
}
-
void btSequentialImpulseConstraintSolverMt::internalCollectContactManifoldCachedInfo(btContactManifoldCachedInfo* cachedInfoArray, btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal)
{
- BT_PROFILE("internalCollectContactManifoldCachedInfo");
- for (int i = 0; i < numManifolds; ++i)
- {
- btContactManifoldCachedInfo* cachedInfo = &cachedInfoArray[i];
- btPersistentManifold* manifold = manifoldPtr[i];
- btCollisionObject* colObj0 = (btCollisionObject*) manifold->getBody0();
- btCollisionObject* colObj1 = (btCollisionObject*) manifold->getBody1();
-
- int solverBodyIdA = getOrInitSolverBodyThreadsafe( *colObj0, infoGlobal.m_timeStep );
- int solverBodyIdB = getOrInitSolverBodyThreadsafe( *colObj1, infoGlobal.m_timeStep );
-
- cachedInfo->solverBodyIds[ 0 ] = solverBodyIdA;
- cachedInfo->solverBodyIds[ 1 ] = solverBodyIdB;
- cachedInfo->numTouchingContacts = 0;
-
- btSolverBody* solverBodyA = &m_tmpSolverBodyPool[ solverBodyIdA ];
- btSolverBody* solverBodyB = &m_tmpSolverBodyPool[ solverBodyIdB ];
-
- // A contact manifold between 2 static object should not exist!
- // check the collision flags of your objects if this assert fires.
- // Incorrectly set collision object flags can degrade performance in various ways.
- btAssert( !m_tmpSolverBodyPool[ solverBodyIdA ].m_invMass.isZero() || !m_tmpSolverBodyPool[ solverBodyIdB ].m_invMass.isZero() );
-
- int iContact = 0;
- for ( int j = 0; j < manifold->getNumContacts(); j++ )
- {
- btManifoldPoint& cp = manifold->getContactPoint( j );
-
- if ( cp.getDistance() <= manifold->getContactProcessingThreshold() )
- {
- cachedInfo->contactPoints[ iContact ] = &cp;
- cachedInfo->contactHasRollingFriction[ iContact ] = ( cp.m_combinedRollingFriction > 0.f );
- iContact++;
- }
- }
- cachedInfo->numTouchingContacts = iContact;
- }
-}
+ BT_PROFILE("internalCollectContactManifoldCachedInfo");
+ for (int i = 0; i < numManifolds; ++i)
+ {
+ btContactManifoldCachedInfo* cachedInfo = &cachedInfoArray[i];
+ btPersistentManifold* manifold = manifoldPtr[i];
+ btCollisionObject* colObj0 = (btCollisionObject*)manifold->getBody0();
+ btCollisionObject* colObj1 = (btCollisionObject*)manifold->getBody1();
+
+ int solverBodyIdA = getOrInitSolverBodyThreadsafe(*colObj0, infoGlobal.m_timeStep);
+ int solverBodyIdB = getOrInitSolverBodyThreadsafe(*colObj1, infoGlobal.m_timeStep);
+
+ cachedInfo->solverBodyIds[0] = solverBodyIdA;
+ cachedInfo->solverBodyIds[1] = solverBodyIdB;
+ cachedInfo->numTouchingContacts = 0;
+
+ btSolverBody* solverBodyA = &m_tmpSolverBodyPool[solverBodyIdA];
+ btSolverBody* solverBodyB = &m_tmpSolverBodyPool[solverBodyIdB];
+ // A contact manifold between 2 static object should not exist!
+ // check the collision flags of your objects if this assert fires.
+ // Incorrectly set collision object flags can degrade performance in various ways.
+ btAssert(!m_tmpSolverBodyPool[solverBodyIdA].m_invMass.isZero() || !m_tmpSolverBodyPool[solverBodyIdB].m_invMass.isZero());
+
+ int iContact = 0;
+ for (int j = 0; j < manifold->getNumContacts(); j++)
+ {
+ btManifoldPoint& cp = manifold->getContactPoint(j);
+
+ if (cp.getDistance() <= manifold->getContactProcessingThreshold())
+ {
+ cachedInfo->contactPoints[iContact] = &cp;
+ cachedInfo->contactHasRollingFriction[iContact] = (cp.m_combinedRollingFriction > 0.f);
+ iContact++;
+ }
+ }
+ cachedInfo->numTouchingContacts = iContact;
+ }
+}
struct CollectContactManifoldCachedInfoLoop : public btIParallelForBody
{
- btSequentialImpulseConstraintSolverMt* m_solver;
- btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* m_cachedInfoArray;
- btPersistentManifold** m_manifoldPtr;
- const btContactSolverInfo* m_infoGlobal;
-
- CollectContactManifoldCachedInfoLoop( btSequentialImpulseConstraintSolverMt* solver, btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* cachedInfoArray, btPersistentManifold** manifoldPtr, const btContactSolverInfo& infoGlobal )
- {
- m_solver = solver;
- m_cachedInfoArray = cachedInfoArray;
- m_manifoldPtr = manifoldPtr;
- m_infoGlobal = &infoGlobal;
- }
- void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE
- {
- m_solver->internalCollectContactManifoldCachedInfo( m_cachedInfoArray + iBegin, m_manifoldPtr + iBegin, iEnd - iBegin, *m_infoGlobal );
- }
-};
+ btSequentialImpulseConstraintSolverMt* m_solver;
+ btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* m_cachedInfoArray;
+ btPersistentManifold** m_manifoldPtr;
+ const btContactSolverInfo* m_infoGlobal;
+ CollectContactManifoldCachedInfoLoop(btSequentialImpulseConstraintSolverMt* solver, btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* cachedInfoArray, btPersistentManifold** manifoldPtr, const btContactSolverInfo& infoGlobal)
+ {
+ m_solver = solver;
+ m_cachedInfoArray = cachedInfoArray;
+ m_manifoldPtr = manifoldPtr;
+ m_infoGlobal = &infoGlobal;
+ }
+ void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
+ {
+ m_solver->internalCollectContactManifoldCachedInfo(m_cachedInfoArray + iBegin, m_manifoldPtr + iBegin, iEnd - iBegin, *m_infoGlobal);
+ }
+};
void btSequentialImpulseConstraintSolverMt::internalAllocContactConstraints(const btContactManifoldCachedInfo* cachedInfoArray, int numManifolds)
{
- BT_PROFILE("internalAllocContactConstraints");
- // possibly parallel part
- for ( int iManifold = 0; iManifold < numManifolds; ++iManifold )
- {
- const btContactManifoldCachedInfo& cachedInfo = cachedInfoArray[ iManifold ];
- int contactIndex = cachedInfo.contactIndex;
- int frictionIndex = contactIndex * m_numFrictionDirections;
- int rollingFrictionIndex = cachedInfo.rollingFrictionIndex;
- for ( int i = 0; i < cachedInfo.numTouchingContacts; i++ )
- {
- btSolverConstraint& contactConstraint = m_tmpSolverContactConstraintPool[contactIndex];
- contactConstraint.m_solverBodyIdA = cachedInfo.solverBodyIds[ 0 ];
- contactConstraint.m_solverBodyIdB = cachedInfo.solverBodyIds[ 1 ];
- contactConstraint.m_originalContactPoint = cachedInfo.contactPoints[ i ];
-
- // allocate the friction constraints
- contactConstraint.m_frictionIndex = frictionIndex;
- for ( int iDir = 0; iDir < m_numFrictionDirections; ++iDir )
- {
- btSolverConstraint& frictionConstraint = m_tmpSolverContactFrictionConstraintPool[frictionIndex];
- frictionConstraint.m_frictionIndex = contactIndex;
- frictionIndex++;
- }
-
- // allocate rolling friction constraints
- if ( cachedInfo.contactHasRollingFriction[ i ] )
- {
- m_rollingFrictionIndexTable[ contactIndex ] = rollingFrictionIndex;
- // allocate 3 (although we may use only 2 sometimes)
- for ( int i = 0; i < 3; i++ )
- {
- m_tmpSolverContactRollingFrictionConstraintPool[ rollingFrictionIndex ].m_frictionIndex = contactIndex;
- rollingFrictionIndex++;
- }
- }
- else
- {
- // indicate there is no rolling friction for this contact point
- m_rollingFrictionIndexTable[ contactIndex ] = -1;
- }
- contactIndex++;
- }
- }
-}
+ BT_PROFILE("internalAllocContactConstraints");
+ // possibly parallel part
+ for (int iManifold = 0; iManifold < numManifolds; ++iManifold)
+ {
+ const btContactManifoldCachedInfo& cachedInfo = cachedInfoArray[iManifold];
+ int contactIndex = cachedInfo.contactIndex;
+ int frictionIndex = contactIndex * m_numFrictionDirections;
+ int rollingFrictionIndex = cachedInfo.rollingFrictionIndex;
+ for (int i = 0; i < cachedInfo.numTouchingContacts; i++)
+ {
+ btSolverConstraint& contactConstraint = m_tmpSolverContactConstraintPool[contactIndex];
+ contactConstraint.m_solverBodyIdA = cachedInfo.solverBodyIds[0];
+ contactConstraint.m_solverBodyIdB = cachedInfo.solverBodyIds[1];
+ contactConstraint.m_originalContactPoint = cachedInfo.contactPoints[i];
+
+ // allocate the friction constraints
+ contactConstraint.m_frictionIndex = frictionIndex;
+ for (int iDir = 0; iDir < m_numFrictionDirections; ++iDir)
+ {
+ btSolverConstraint& frictionConstraint = m_tmpSolverContactFrictionConstraintPool[frictionIndex];
+ frictionConstraint.m_frictionIndex = contactIndex;
+ frictionIndex++;
+ }
+ // allocate rolling friction constraints
+ if (cachedInfo.contactHasRollingFriction[i])
+ {
+ m_rollingFrictionIndexTable[contactIndex] = rollingFrictionIndex;
+ // allocate 3 (although we may use only 2 sometimes)
+ for (int i = 0; i < 3; i++)
+ {
+ m_tmpSolverContactRollingFrictionConstraintPool[rollingFrictionIndex].m_frictionIndex = contactIndex;
+ rollingFrictionIndex++;
+ }
+ }
+ else
+ {
+ // indicate there is no rolling friction for this contact point
+ m_rollingFrictionIndexTable[contactIndex] = -1;
+ }
+ contactIndex++;
+ }
+ }
+}
struct AllocContactConstraintsLoop : public btIParallelForBody
{
- btSequentialImpulseConstraintSolverMt* m_solver;
- const btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* m_cachedInfoArray;
-
- AllocContactConstraintsLoop( btSequentialImpulseConstraintSolverMt* solver, btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* cachedInfoArray )
- {
- m_solver = solver;
- m_cachedInfoArray = cachedInfoArray;
- }
- void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE
- {
- m_solver->internalAllocContactConstraints( m_cachedInfoArray + iBegin, iEnd - iBegin );
- }
-};
+ btSequentialImpulseConstraintSolverMt* m_solver;
+ const btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* m_cachedInfoArray;
+ AllocContactConstraintsLoop(btSequentialImpulseConstraintSolverMt* solver, btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* cachedInfoArray)
+ {
+ m_solver = solver;
+ m_cachedInfoArray = cachedInfoArray;
+ }
+ void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
+ {
+ m_solver->internalAllocContactConstraints(m_cachedInfoArray + iBegin, iEnd - iBegin);
+ }
+};
void btSequentialImpulseConstraintSolverMt::allocAllContactConstraints(btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal)
{
- BT_PROFILE( "allocAllContactConstraints" );
- btAlignedObjectArray<btContactManifoldCachedInfo> cachedInfoArray; // = m_manifoldCachedInfoArray;
- cachedInfoArray.resizeNoInitialize( numManifolds );
- if (/* DISABLES CODE */ (false))
- {
- // sequential
- internalCollectContactManifoldCachedInfo(&cachedInfoArray[ 0 ], manifoldPtr, numManifolds, infoGlobal);
- }
- else
- {
- // may alter ordering of bodies which affects determinism
- CollectContactManifoldCachedInfoLoop loop( this, &cachedInfoArray[ 0 ], manifoldPtr, infoGlobal );
- int grainSize = 200;
- btParallelFor( 0, numManifolds, grainSize, loop );
- }
-
- {
- // serial part
- int numContacts = 0;
- int numRollingFrictionConstraints = 0;
- for ( int iManifold = 0; iManifold < numManifolds; ++iManifold )
- {
- btContactManifoldCachedInfo& cachedInfo = cachedInfoArray[ iManifold ];
- cachedInfo.contactIndex = numContacts;
- cachedInfo.rollingFrictionIndex = numRollingFrictionConstraints;
- numContacts += cachedInfo.numTouchingContacts;
- for (int i = 0; i < cachedInfo.numTouchingContacts; ++i)
- {
- if (cachedInfo.contactHasRollingFriction[i])
- {
- numRollingFrictionConstraints += 3;
- }
- }
- }
- {
- BT_PROFILE( "allocPools" );
- if ( m_tmpSolverContactConstraintPool.capacity() < numContacts )
- {
- // if we need to reallocate, reserve some extra so we don't have to reallocate again next frame
- int extraReserve = numContacts / 16;
- m_tmpSolverContactConstraintPool.reserve( numContacts + extraReserve );
- m_rollingFrictionIndexTable.reserve( numContacts + extraReserve );
- m_tmpSolverContactFrictionConstraintPool.reserve( ( numContacts + extraReserve )*m_numFrictionDirections );
- m_tmpSolverContactRollingFrictionConstraintPool.reserve( numRollingFrictionConstraints + extraReserve );
- }
- m_tmpSolverContactConstraintPool.resizeNoInitialize( numContacts );
- m_rollingFrictionIndexTable.resizeNoInitialize( numContacts );
- m_tmpSolverContactFrictionConstraintPool.resizeNoInitialize( numContacts*m_numFrictionDirections );
- m_tmpSolverContactRollingFrictionConstraintPool.resizeNoInitialize( numRollingFrictionConstraints );
- }
- }
- {
- AllocContactConstraintsLoop loop(this, &cachedInfoArray[0]);
- int grainSize = 200;
- btParallelFor( 0, numManifolds, grainSize, loop );
- }
-}
+ BT_PROFILE("allocAllContactConstraints");
+ btAlignedObjectArray<btContactManifoldCachedInfo> cachedInfoArray; // = m_manifoldCachedInfoArray;
+ cachedInfoArray.resizeNoInitialize(numManifolds);
+ if (/* DISABLES CODE */ (false))
+ {
+ // sequential
+ internalCollectContactManifoldCachedInfo(&cachedInfoArray[0], manifoldPtr, numManifolds, infoGlobal);
+ }
+ else
+ {
+ // may alter ordering of bodies which affects determinism
+ CollectContactManifoldCachedInfoLoop loop(this, &cachedInfoArray[0], manifoldPtr, infoGlobal);
+ int grainSize = 200;
+ btParallelFor(0, numManifolds, grainSize, loop);
+ }
+ {
+ // serial part
+ int numContacts = 0;
+ int numRollingFrictionConstraints = 0;
+ for (int iManifold = 0; iManifold < numManifolds; ++iManifold)
+ {
+ btContactManifoldCachedInfo& cachedInfo = cachedInfoArray[iManifold];
+ cachedInfo.contactIndex = numContacts;
+ cachedInfo.rollingFrictionIndex = numRollingFrictionConstraints;
+ numContacts += cachedInfo.numTouchingContacts;
+ for (int i = 0; i < cachedInfo.numTouchingContacts; ++i)
+ {
+ if (cachedInfo.contactHasRollingFriction[i])
+ {
+ numRollingFrictionConstraints += 3;
+ }
+ }
+ }
+ {
+ BT_PROFILE("allocPools");
+ if (m_tmpSolverContactConstraintPool.capacity() < numContacts)
+ {
+ // if we need to reallocate, reserve some extra so we don't have to reallocate again next frame
+ int extraReserve = numContacts / 16;
+ m_tmpSolverContactConstraintPool.reserve(numContacts + extraReserve);
+ m_rollingFrictionIndexTable.reserve(numContacts + extraReserve);
+ m_tmpSolverContactFrictionConstraintPool.reserve((numContacts + extraReserve) * m_numFrictionDirections);
+ m_tmpSolverContactRollingFrictionConstraintPool.reserve(numRollingFrictionConstraints + extraReserve);
+ }
+ m_tmpSolverContactConstraintPool.resizeNoInitialize(numContacts);
+ m_rollingFrictionIndexTable.resizeNoInitialize(numContacts);
+ m_tmpSolverContactFrictionConstraintPool.resizeNoInitialize(numContacts * m_numFrictionDirections);
+ m_tmpSolverContactRollingFrictionConstraintPool.resizeNoInitialize(numRollingFrictionConstraints);
+ }
+ }
+ {
+ AllocContactConstraintsLoop loop(this, &cachedInfoArray[0]);
+ int grainSize = 200;
+ btParallelFor(0, numManifolds, grainSize, loop);
+ }
+}
void btSequentialImpulseConstraintSolverMt::convertContacts(btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal)
{
- if (!m_useBatching)
- {
- btSequentialImpulseConstraintSolver::convertContacts(manifoldPtr, numManifolds, infoGlobal);
- return;
- }
- BT_PROFILE( "convertContacts" );
- if (numManifolds > 0)
- {
- if ( m_fixedBodyId < 0 )
- {
- m_fixedBodyId = m_tmpSolverBodyPool.size();
- btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
- initSolverBody( &fixedBody, 0, infoGlobal.m_timeStep );
- }
- allocAllContactConstraints( manifoldPtr, numManifolds, infoGlobal );
- if ( m_useBatching )
- {
- setupBatchedContactConstraints();
- }
- setupAllContactConstraints( infoGlobal );
- }
+ if (!m_useBatching)
+ {
+ btSequentialImpulseConstraintSolver::convertContacts(manifoldPtr, numManifolds, infoGlobal);
+ return;
+ }
+ BT_PROFILE("convertContacts");
+ if (numManifolds > 0)
+ {
+ if (m_fixedBodyId < 0)
+ {
+ m_fixedBodyId = m_tmpSolverBodyPool.size();
+ btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
+ initSolverBody(&fixedBody, 0, infoGlobal.m_timeStep);
+ }
+ allocAllContactConstraints(manifoldPtr, numManifolds, infoGlobal);
+ if (m_useBatching)
+ {
+ setupBatchedContactConstraints();
+ }
+ setupAllContactConstraints(infoGlobal);
+ }
}
-
-void btSequentialImpulseConstraintSolverMt::internalInitMultipleJoints( btTypedConstraint** constraints, int iBegin, int iEnd )
+void btSequentialImpulseConstraintSolverMt::internalInitMultipleJoints(btTypedConstraint** constraints, int iBegin, int iEnd)
{
- BT_PROFILE("internalInitMultipleJoints");
- for ( int i = iBegin; i < iEnd; i++ )
+ BT_PROFILE("internalInitMultipleJoints");
+ for (int i = iBegin; i < iEnd; i++)
{
btTypedConstraint* constraint = constraints[i];
btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
if (constraint->isEnabled())
- {
- constraint->buildJacobian();
- constraint->internalSetAppliedImpulse( 0.0f );
- btJointFeedback* fb = constraint->getJointFeedback();
- if ( fb )
- {
- fb->m_appliedForceBodyA.setZero();
- fb->m_appliedTorqueBodyA.setZero();
- fb->m_appliedForceBodyB.setZero();
- fb->m_appliedTorqueBodyB.setZero();
- }
- constraint->getInfo1( &info1 );
- }
- else
+ {
+ constraint->buildJacobian();
+ constraint->internalSetAppliedImpulse(0.0f);
+ btJointFeedback* fb = constraint->getJointFeedback();
+ if (fb)
+ {
+ fb->m_appliedForceBodyA.setZero();
+ fb->m_appliedTorqueBodyA.setZero();
+ fb->m_appliedForceBodyB.setZero();
+ fb->m_appliedTorqueBodyB.setZero();
+ }
+ constraint->getInfo1(&info1);
+ }
+ else
{
info1.m_numConstraintRows = 0;
info1.nub = 0;
@@ -646,158 +624,151 @@ void btSequentialImpulseConstraintSolverMt::internalInitMultipleJoints( btTypedC
}
}
-
struct InitJointsLoop : public btIParallelForBody
{
- btSequentialImpulseConstraintSolverMt* m_solver;
- btTypedConstraint** m_constraints;
-
- InitJointsLoop( btSequentialImpulseConstraintSolverMt* solver, btTypedConstraint** constraints )
- {
- m_solver = solver;
- m_constraints = constraints;
- }
- void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE
- {
- m_solver->internalInitMultipleJoints( m_constraints, iBegin, iEnd );
- }
-};
+ btSequentialImpulseConstraintSolverMt* m_solver;
+ btTypedConstraint** m_constraints;
+ InitJointsLoop(btSequentialImpulseConstraintSolverMt* solver, btTypedConstraint** constraints)
+ {
+ m_solver = solver;
+ m_constraints = constraints;
+ }
+ void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
+ {
+ m_solver->internalInitMultipleJoints(m_constraints, iBegin, iEnd);
+ }
+};
-void btSequentialImpulseConstraintSolverMt::internalConvertMultipleJoints( const btAlignedObjectArray<JointParams>& jointParamsArray, btTypedConstraint** constraints, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal )
+void btSequentialImpulseConstraintSolverMt::internalConvertMultipleJoints(const btAlignedObjectArray<JointParams>& jointParamsArray, btTypedConstraint** constraints, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
{
- BT_PROFILE("internalConvertMultipleJoints");
- for ( int i = iBegin; i < iEnd; ++i )
- {
- const JointParams& jointParams = jointParamsArray[ i ];
- int currentRow = jointParams.m_solverConstraint;
- if ( currentRow != -1 )
- {
- const btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[ i ];
- btAssert( currentRow < m_tmpSolverNonContactConstraintPool.size() );
- btAssert( info1.m_numConstraintRows > 0 );
-
- btSolverConstraint* currentConstraintRow = &m_tmpSolverNonContactConstraintPool[ currentRow ];
- btTypedConstraint* constraint = constraints[ i ];
-
- convertJoint( currentConstraintRow, constraint, info1, jointParams.m_solverBodyA, jointParams.m_solverBodyB, infoGlobal );
- }
- }
-}
+ BT_PROFILE("internalConvertMultipleJoints");
+ for (int i = iBegin; i < iEnd; ++i)
+ {
+ const JointParams& jointParams = jointParamsArray[i];
+ int currentRow = jointParams.m_solverConstraint;
+ if (currentRow != -1)
+ {
+ const btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
+ btAssert(currentRow < m_tmpSolverNonContactConstraintPool.size());
+ btAssert(info1.m_numConstraintRows > 0);
+
+ btSolverConstraint* currentConstraintRow = &m_tmpSolverNonContactConstraintPool[currentRow];
+ btTypedConstraint* constraint = constraints[i];
+ convertJoint(currentConstraintRow, constraint, info1, jointParams.m_solverBodyA, jointParams.m_solverBodyB, infoGlobal);
+ }
+ }
+}
struct ConvertJointsLoop : public btIParallelForBody
{
- btSequentialImpulseConstraintSolverMt* m_solver;
- const btAlignedObjectArray<btSequentialImpulseConstraintSolverMt::JointParams>& m_jointParamsArray;
- btTypedConstraint** m_srcConstraints;
- const btContactSolverInfo& m_infoGlobal;
-
- ConvertJointsLoop( btSequentialImpulseConstraintSolverMt* solver,
- const btAlignedObjectArray<btSequentialImpulseConstraintSolverMt::JointParams>& jointParamsArray,
- btTypedConstraint** srcConstraints,
- const btContactSolverInfo& infoGlobal
- ) :
- m_jointParamsArray(jointParamsArray),
- m_infoGlobal(infoGlobal)
- {
- m_solver = solver;
- m_srcConstraints = srcConstraints;
- }
- void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE
- {
- m_solver->internalConvertMultipleJoints( m_jointParamsArray, m_srcConstraints, iBegin, iEnd, m_infoGlobal );
- }
+ btSequentialImpulseConstraintSolverMt* m_solver;
+ const btAlignedObjectArray<btSequentialImpulseConstraintSolverMt::JointParams>& m_jointParamsArray;
+ btTypedConstraint** m_srcConstraints;
+ const btContactSolverInfo& m_infoGlobal;
+
+ ConvertJointsLoop(btSequentialImpulseConstraintSolverMt* solver,
+ const btAlignedObjectArray<btSequentialImpulseConstraintSolverMt::JointParams>& jointParamsArray,
+ btTypedConstraint** srcConstraints,
+ const btContactSolverInfo& infoGlobal) : m_jointParamsArray(jointParamsArray),
+ m_infoGlobal(infoGlobal)
+ {
+ m_solver = solver;
+ m_srcConstraints = srcConstraints;
+ }
+ void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
+ {
+ m_solver->internalConvertMultipleJoints(m_jointParamsArray, m_srcConstraints, iBegin, iEnd, m_infoGlobal);
+ }
};
-
void btSequentialImpulseConstraintSolverMt::convertJoints(btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal)
{
- if ( !m_useBatching )
- {
- btSequentialImpulseConstraintSolver::convertJoints(constraints, numConstraints, infoGlobal);
- return;
- }
- BT_PROFILE("convertJoints");
- bool parallelJointSetup = true;
+ if (!m_useBatching)
+ {
+ btSequentialImpulseConstraintSolver::convertJoints(constraints, numConstraints, infoGlobal);
+ return;
+ }
+ BT_PROFILE("convertJoints");
+ bool parallelJointSetup = true;
m_tmpConstraintSizesPool.resizeNoInitialize(numConstraints);
- if (parallelJointSetup)
- {
- InitJointsLoop loop(this, constraints);
- int grainSize = 40;
- btParallelFor(0, numConstraints, grainSize, loop);
- }
- else
- {
- internalInitMultipleJoints( constraints, 0, numConstraints );
- }
+ if (parallelJointSetup)
+ {
+ InitJointsLoop loop(this, constraints);
+ int grainSize = 40;
+ btParallelFor(0, numConstraints, grainSize, loop);
+ }
+ else
+ {
+ internalInitMultipleJoints(constraints, 0, numConstraints);
+ }
int totalNumRows = 0;
- btAlignedObjectArray<JointParams> jointParamsArray;
- jointParamsArray.resizeNoInitialize(numConstraints);
+ btAlignedObjectArray<JointParams> jointParamsArray;
+ jointParamsArray.resizeNoInitialize(numConstraints);
//calculate the total number of contraint rows
- for (int i=0;i<numConstraints;i++)
+ for (int i = 0; i < numConstraints; i++)
{
- btTypedConstraint* constraint = constraints[ i ];
+ btTypedConstraint* constraint = constraints[i];
- JointParams& params = jointParamsArray[ i ];
+ JointParams& params = jointParamsArray[i];
const btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
if (info1.m_numConstraintRows)
{
- params.m_solverConstraint = totalNumRows;
- params.m_solverBodyA = getOrInitSolverBody( constraint->getRigidBodyA(), infoGlobal.m_timeStep );
- params.m_solverBodyB = getOrInitSolverBody( constraint->getRigidBodyB(), infoGlobal.m_timeStep );
+ params.m_solverConstraint = totalNumRows;
+ params.m_solverBodyA = getOrInitSolverBody(constraint->getRigidBodyA(), infoGlobal.m_timeStep);
+ params.m_solverBodyB = getOrInitSolverBody(constraint->getRigidBodyB(), infoGlobal.m_timeStep);
}
- else
+ else
{
- params.m_solverConstraint = -1;
+ params.m_solverConstraint = -1;
}
totalNumRows += info1.m_numConstraintRows;
}
m_tmpSolverNonContactConstraintPool.resizeNoInitialize(totalNumRows);
///setup the btSolverConstraints
- if ( parallelJointSetup )
- {
- ConvertJointsLoop loop(this, jointParamsArray, constraints, infoGlobal);
- int grainSize = 20;
- btParallelFor(0, numConstraints, grainSize, loop);
- }
- else
- {
- internalConvertMultipleJoints( jointParamsArray, constraints, 0, numConstraints, infoGlobal );
- }
- setupBatchedJointConstraints();
+ if (parallelJointSetup)
+ {
+ ConvertJointsLoop loop(this, jointParamsArray, constraints, infoGlobal);
+ int grainSize = 20;
+ btParallelFor(0, numConstraints, grainSize, loop);
+ }
+ else
+ {
+ internalConvertMultipleJoints(jointParamsArray, constraints, 0, numConstraints, infoGlobal);
+ }
+ setupBatchedJointConstraints();
}
-
void btSequentialImpulseConstraintSolverMt::internalConvertBodies(btCollisionObject** bodies, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
{
- BT_PROFILE("internalConvertBodies");
- for (int i=iBegin; i < iEnd; i++)
+ BT_PROFILE("internalConvertBodies");
+ for (int i = iBegin; i < iEnd; i++)
{
- btCollisionObject* obj = bodies[i];
+ btCollisionObject* obj = bodies[i];
obj->setCompanionId(i);
btSolverBody& solverBody = m_tmpSolverBodyPool[i];
- initSolverBody(&solverBody, obj, infoGlobal.m_timeStep);
+ initSolverBody(&solverBody, obj, infoGlobal.m_timeStep);
btRigidBody* body = btRigidBody::upcast(obj);
if (body && body->getInvMass())
{
- btVector3 gyroForce (0,0,0);
- if (body->getFlags()&BT_ENABLE_GYROSCOPIC_FORCE_EXPLICIT)
+ btVector3 gyroForce(0, 0, 0);
+ if (body->getFlags() & BT_ENABLE_GYROSCOPIC_FORCE_EXPLICIT)
{
gyroForce = body->computeGyroscopicForceExplicit(infoGlobal.m_maxGyroscopicForce);
- solverBody.m_externalTorqueImpulse -= gyroForce*body->getInvInertiaTensorWorld()*infoGlobal.m_timeStep;
+ solverBody.m_externalTorqueImpulse -= gyroForce * body->getInvInertiaTensorWorld() * infoGlobal.m_timeStep;
}
- if (body->getFlags()&BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_WORLD)
+ if (body->getFlags() & BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_WORLD)
{
gyroForce = body->computeGyroscopicImpulseImplicit_World(infoGlobal.m_timeStep);
solverBody.m_externalTorqueImpulse += gyroForce;
}
- if (body->getFlags()&BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY)
+ if (body->getFlags() & BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY)
{
gyroForce = body->computeGyroscopicImpulseImplicit_Body(infoGlobal.m_timeStep);
solverBody.m_externalTorqueImpulse += gyroForce;
@@ -806,809 +777,772 @@ void btSequentialImpulseConstraintSolverMt::internalConvertBodies(btCollisionObj
}
}
-
struct ConvertBodiesLoop : public btIParallelForBody
{
- btSequentialImpulseConstraintSolverMt* m_solver;
- btCollisionObject** m_bodies;
- int m_numBodies;
- const btContactSolverInfo& m_infoGlobal;
-
- ConvertBodiesLoop( btSequentialImpulseConstraintSolverMt* solver,
- btCollisionObject** bodies,
- int numBodies,
- const btContactSolverInfo& infoGlobal
- ) :
- m_infoGlobal(infoGlobal)
- {
- m_solver = solver;
- m_bodies = bodies;
- m_numBodies = numBodies;
- }
- void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE
- {
- m_solver->internalConvertBodies( m_bodies, iBegin, iEnd, m_infoGlobal );
- }
+ btSequentialImpulseConstraintSolverMt* m_solver;
+ btCollisionObject** m_bodies;
+ int m_numBodies;
+ const btContactSolverInfo& m_infoGlobal;
+
+ ConvertBodiesLoop(btSequentialImpulseConstraintSolverMt* solver,
+ btCollisionObject** bodies,
+ int numBodies,
+ const btContactSolverInfo& infoGlobal) : m_infoGlobal(infoGlobal)
+ {
+ m_solver = solver;
+ m_bodies = bodies;
+ m_numBodies = numBodies;
+ }
+ void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
+ {
+ m_solver->internalConvertBodies(m_bodies, iBegin, iEnd, m_infoGlobal);
+ }
};
-
void btSequentialImpulseConstraintSolverMt::convertBodies(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
{
- BT_PROFILE("convertBodies");
- m_kinematicBodyUniqueIdToSolverBodyTable.resize( 0 );
-
- m_tmpSolverBodyPool.resizeNoInitialize(numBodies+1);
-
- m_fixedBodyId = numBodies;
- {
- btSolverBody& fixedBody = m_tmpSolverBodyPool[ m_fixedBodyId ];
- initSolverBody( &fixedBody, NULL, infoGlobal.m_timeStep );
- }
-
- bool parallelBodySetup = true;
- if (parallelBodySetup)
- {
- ConvertBodiesLoop loop(this, bodies, numBodies, infoGlobal);
- int grainSize = 40;
- btParallelFor(0, numBodies, grainSize, loop);
- }
- else
- {
- internalConvertBodies( bodies, 0, numBodies, infoGlobal );
- }
-}
+ BT_PROFILE("convertBodies");
+ m_kinematicBodyUniqueIdToSolverBodyTable.resize(0);
+ m_tmpSolverBodyPool.resizeNoInitialize(numBodies + 1);
+
+ m_fixedBodyId = numBodies;
+ {
+ btSolverBody& fixedBody = m_tmpSolverBodyPool[m_fixedBodyId];
+ initSolverBody(&fixedBody, NULL, infoGlobal.m_timeStep);
+ }
+
+ bool parallelBodySetup = true;
+ if (parallelBodySetup)
+ {
+ ConvertBodiesLoop loop(this, bodies, numBodies, infoGlobal);
+ int grainSize = 40;
+ btParallelFor(0, numBodies, grainSize, loop);
+ }
+ else
+ {
+ internalConvertBodies(bodies, 0, numBodies, infoGlobal);
+ }
+}
btScalar btSequentialImpulseConstraintSolverMt::solveGroupCacheFriendlySetup(
- btCollisionObject** bodies,
- int numBodies,
- btPersistentManifold** manifoldPtr,
- int numManifolds,
- btTypedConstraint** constraints,
- int numConstraints,
- const btContactSolverInfo& infoGlobal,
- btIDebugDraw* debugDrawer
- )
+ btCollisionObject** bodies,
+ int numBodies,
+ btPersistentManifold** manifoldPtr,
+ int numManifolds,
+ btTypedConstraint** constraints,
+ int numConstraints,
+ const btContactSolverInfo& infoGlobal,
+ btIDebugDraw* debugDrawer)
{
- m_numFrictionDirections = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) ? 2 : 1;
- m_useBatching = false;
- if ( numManifolds >= s_minimumContactManifoldsForBatching &&
- (s_allowNestedParallelForLoops || !btThreadsAreRunning())
- )
- {
- m_useBatching = true;
- m_batchedContactConstraints.m_debugDrawer = debugDrawer;
- m_batchedJointConstraints.m_debugDrawer = debugDrawer;
- }
- btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup( bodies,
- numBodies,
- manifoldPtr,
- numManifolds,
- constraints,
- numConstraints,
- infoGlobal,
- debugDrawer
- );
- return 0.0f;
+ m_numFrictionDirections = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) ? 2 : 1;
+ m_useBatching = false;
+ if (numManifolds >= s_minimumContactManifoldsForBatching &&
+ (s_allowNestedParallelForLoops || !btThreadsAreRunning()))
+ {
+ m_useBatching = true;
+ m_batchedContactConstraints.m_debugDrawer = debugDrawer;
+ m_batchedJointConstraints.m_debugDrawer = debugDrawer;
+ }
+ btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(bodies,
+ numBodies,
+ manifoldPtr,
+ numManifolds,
+ constraints,
+ numConstraints,
+ infoGlobal,
+ debugDrawer);
+ return 0.0f;
}
-
-btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactSplitPenetrationImpulseConstraints( const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd )
+btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactSplitPenetrationImpulseConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd)
{
- btScalar leastSquaresResidual = 0.f;
- for ( int iiCons = batchBegin; iiCons < batchEnd; ++iiCons )
- {
- int iCons = consIndices[ iiCons ];
- const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[ iCons ];
- btSolverBody& bodyA = m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdA ];
- btSolverBody& bodyB = m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdB ];
- btScalar residual = resolveSplitPenetrationImpulse( bodyA, bodyB, solveManifold );
- leastSquaresResidual += residual*residual;
- }
- return leastSquaresResidual;
+ btScalar leastSquaresResidual = 0.f;
+ for (int iiCons = batchBegin; iiCons < batchEnd; ++iiCons)
+ {
+ int iCons = consIndices[iiCons];
+ const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[iCons];
+ btSolverBody& bodyA = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA];
+ btSolverBody& bodyB = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB];
+ btScalar residual = resolveSplitPenetrationImpulse(bodyA, bodyB, solveManifold);
+ leastSquaresResidual += residual * residual;
+ }
+ return leastSquaresResidual;
}
-
struct ContactSplitPenetrationImpulseSolverLoop : public btIParallelSumBody
{
- btSequentialImpulseConstraintSolverMt* m_solver;
- const btBatchedConstraints* m_bc;
-
- ContactSplitPenetrationImpulseSolverLoop( btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc )
- {
- m_solver = solver;
- m_bc = bc;
- }
- btScalar sumLoop( int iBegin, int iEnd ) const BT_OVERRIDE
- {
- BT_PROFILE( "ContactSplitPenetrationImpulseSolverLoop" );
- btScalar sum = 0;
- for ( int iBatch = iBegin; iBatch < iEnd; ++iBatch )
- {
- const btBatchedConstraints::Range& batch = m_bc->m_batches[ iBatch ];
- sum += m_solver->resolveMultipleContactSplitPenetrationImpulseConstraints( m_bc->m_constraintIndices, batch.begin, batch.end );
- }
- return sum;
- }
-};
+ btSequentialImpulseConstraintSolverMt* m_solver;
+ const btBatchedConstraints* m_bc;
+ ContactSplitPenetrationImpulseSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc)
+ {
+ m_solver = solver;
+ m_bc = bc;
+ }
+ btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE
+ {
+ BT_PROFILE("ContactSplitPenetrationImpulseSolverLoop");
+ btScalar sum = 0;
+ for (int iBatch = iBegin; iBatch < iEnd; ++iBatch)
+ {
+ const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch];
+ sum += m_solver->resolveMultipleContactSplitPenetrationImpulseConstraints(m_bc->m_constraintIndices, batch.begin, batch.end);
+ }
+ return sum;
+ }
+};
-void btSequentialImpulseConstraintSolverMt::solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer)
+void btSequentialImpulseConstraintSolverMt::solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
{
BT_PROFILE("solveGroupCacheFriendlySplitImpulseIterations");
if (infoGlobal.m_splitImpulse)
{
- for ( int iteration = 0; iteration < infoGlobal.m_numIterations; iteration++ )
- {
- btScalar leastSquaresResidual = 0.f;
- if (m_useBatching)
- {
- const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
- ContactSplitPenetrationImpulseSolverLoop loop( this, &batchedCons );
- btScalar leastSquaresResidual = 0.f;
- for ( int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase )
- {
- int iPhase = batchedCons.m_phaseOrder[ iiPhase ];
- const btBatchedConstraints::Range& phase = batchedCons.m_phases[ iPhase ];
- int grainSize = batchedCons.m_phaseGrainSize[iPhase];
- leastSquaresResidual += btParallelSum( phase.begin, phase.end, grainSize, loop );
- }
- }
- else
- {
- // non-batched
- leastSquaresResidual = resolveMultipleContactSplitPenetrationImpulseConstraints(m_orderTmpConstraintPool, 0, m_tmpSolverContactConstraintPool.size());
- }
- if ( leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || iteration >= ( infoGlobal.m_numIterations - 1 ) )
- {
+ for (int iteration = 0; iteration < infoGlobal.m_numIterations; iteration++)
+ {
+ btScalar leastSquaresResidual = 0.f;
+ if (m_useBatching)
+ {
+ const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
+ ContactSplitPenetrationImpulseSolverLoop loop(this, &batchedCons);
+ btScalar leastSquaresResidual = 0.f;
+ for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase)
+ {
+ int iPhase = batchedCons.m_phaseOrder[iiPhase];
+ const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase];
+ int grainSize = batchedCons.m_phaseGrainSize[iPhase];
+ leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop);
+ }
+ }
+ else
+ {
+ // non-batched
+ leastSquaresResidual = resolveMultipleContactSplitPenetrationImpulseConstraints(m_orderTmpConstraintPool, 0, m_tmpSolverContactConstraintPool.size());
+ }
+ if (leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || iteration >= (infoGlobal.m_numIterations - 1))
+ {
#ifdef VERBOSE_RESIDUAL_PRINTF
- printf( "residual = %f at iteration #%d\n", leastSquaresResidual, iteration );
+ printf("residual = %f at iteration #%d\n", leastSquaresResidual, iteration);
#endif
- break;
- }
- }
+ break;
+ }
+ }
}
}
-
-btScalar btSequentialImpulseConstraintSolverMt::solveSingleIteration(int iteration, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer)
+btScalar btSequentialImpulseConstraintSolverMt::solveSingleIteration(int iteration, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
{
- if ( !m_useBatching )
- {
- return btSequentialImpulseConstraintSolver::solveSingleIteration( iteration, bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer );
- }
- BT_PROFILE( "solveSingleIterationMt" );
- btScalar leastSquaresResidual = 0.f;
+ if (!m_useBatching)
+ {
+ return btSequentialImpulseConstraintSolver::solveSingleIteration(iteration, bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
+ }
+ BT_PROFILE("solveSingleIterationMt");
+ btScalar leastSquaresResidual = 0.f;
if (infoGlobal.m_solverMode & SOLVER_RANDMIZE_ORDER)
{
- if (1) // uncomment this for a bit less random ((iteration & 7) == 0)
+ if (1) // uncomment this for a bit less random ((iteration & 7) == 0)
{
- randomizeConstraintOrdering(iteration, infoGlobal.m_numIterations);
+ randomizeConstraintOrdering(iteration, infoGlobal.m_numIterations);
}
}
{
///solve all joint constraints
- leastSquaresResidual += resolveAllJointConstraints(iteration);
+ leastSquaresResidual += resolveAllJointConstraints(iteration);
- if (iteration< infoGlobal.m_numIterations)
+ if (iteration < infoGlobal.m_numIterations)
{
- // this loop is only used for cone-twist constraints,
- // it would be nice to skip this loop if none of the constraints need it
- if ( m_useObsoleteJointConstraints )
- {
- for ( int j = 0; j<numConstraints; j++ )
- {
- if ( constraints[ j ]->isEnabled() )
- {
- int bodyAid = getOrInitSolverBody( constraints[ j ]->getRigidBodyA(), infoGlobal.m_timeStep );
- int bodyBid = getOrInitSolverBody( constraints[ j ]->getRigidBodyB(), infoGlobal.m_timeStep );
- btSolverBody& bodyA = m_tmpSolverBodyPool[ bodyAid ];
- btSolverBody& bodyB = m_tmpSolverBodyPool[ bodyBid ];
- constraints[ j ]->solveConstraintObsolete( bodyA, bodyB, infoGlobal.m_timeStep );
- }
- }
- }
+ // this loop is only used for cone-twist constraints,
+ // it would be nice to skip this loop if none of the constraints need it
+ if (m_useObsoleteJointConstraints)
+ {
+ for (int j = 0; j < numConstraints; j++)
+ {
+ if (constraints[j]->isEnabled())
+ {
+ int bodyAid = getOrInitSolverBody(constraints[j]->getRigidBodyA(), infoGlobal.m_timeStep);
+ int bodyBid = getOrInitSolverBody(constraints[j]->getRigidBodyB(), infoGlobal.m_timeStep);
+ btSolverBody& bodyA = m_tmpSolverBodyPool[bodyAid];
+ btSolverBody& bodyB = m_tmpSolverBodyPool[bodyBid];
+ constraints[j]->solveConstraintObsolete(bodyA, bodyB, infoGlobal.m_timeStep);
+ }
+ }
+ }
if (infoGlobal.m_solverMode & SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS)
{
- // solve all contact, contact-friction, and rolling friction constraints interleaved
- leastSquaresResidual += resolveAllContactConstraintsInterleaved();
+ // solve all contact, contact-friction, and rolling friction constraints interleaved
+ leastSquaresResidual += resolveAllContactConstraintsInterleaved();
}
- else//SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS
+ else //SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS
{
- // don't interleave them
+ // don't interleave them
// solve all contact constraints
- leastSquaresResidual += resolveAllContactConstraints();
+ leastSquaresResidual += resolveAllContactConstraints();
// solve all contact friction constraints
- leastSquaresResidual += resolveAllContactFrictionConstraints();
+ leastSquaresResidual += resolveAllContactFrictionConstraints();
- // solve all rolling friction constraints
- leastSquaresResidual += resolveAllRollingFrictionConstraints();
+ // solve all rolling friction constraints
+ leastSquaresResidual += resolveAllRollingFrictionConstraints();
}
}
}
- return leastSquaresResidual;
+ return leastSquaresResidual;
}
-
-btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleJointConstraints( const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd, int iteration )
+btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleJointConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd, int iteration)
{
- btScalar leastSquaresResidual = 0.f;
- for ( int iiCons = batchBegin; iiCons < batchEnd; ++iiCons )
- {
- int iCons = consIndices[ iiCons ];
- const btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[ iCons ];
- if ( iteration < constraint.m_overrideNumSolverIterations )
- {
- btSolverBody& bodyA = m_tmpSolverBodyPool[ constraint.m_solverBodyIdA ];
- btSolverBody& bodyB = m_tmpSolverBodyPool[ constraint.m_solverBodyIdB ];
- btScalar residual = resolveSingleConstraintRowGeneric( bodyA, bodyB, constraint );
- leastSquaresResidual += residual*residual;
- }
- }
- return leastSquaresResidual;
+ btScalar leastSquaresResidual = 0.f;
+ for (int iiCons = batchBegin; iiCons < batchEnd; ++iiCons)
+ {
+ int iCons = consIndices[iiCons];
+ const btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[iCons];
+ if (iteration < constraint.m_overrideNumSolverIterations)
+ {
+ btSolverBody& bodyA = m_tmpSolverBodyPool[constraint.m_solverBodyIdA];
+ btSolverBody& bodyB = m_tmpSolverBodyPool[constraint.m_solverBodyIdB];
+ btScalar residual = resolveSingleConstraintRowGeneric(bodyA, bodyB, constraint);
+ leastSquaresResidual += residual * residual;
+ }
+ }
+ return leastSquaresResidual;
}
-
-btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactConstraints( const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd )
+btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd)
{
- btScalar leastSquaresResidual = 0.f;
- for ( int iiCons = batchBegin; iiCons < batchEnd; ++iiCons )
- {
- int iCons = consIndices[ iiCons ];
- const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[ iCons ];
- btSolverBody& bodyA = m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdA ];
- btSolverBody& bodyB = m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdB ];
- btScalar residual = resolveSingleConstraintRowLowerLimit( bodyA, bodyB, solveManifold );
- leastSquaresResidual += residual*residual;
- }
- return leastSquaresResidual;
+ btScalar leastSquaresResidual = 0.f;
+ for (int iiCons = batchBegin; iiCons < batchEnd; ++iiCons)
+ {
+ int iCons = consIndices[iiCons];
+ const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[iCons];
+ btSolverBody& bodyA = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA];
+ btSolverBody& bodyB = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB];
+ btScalar residual = resolveSingleConstraintRowLowerLimit(bodyA, bodyB, solveManifold);
+ leastSquaresResidual += residual * residual;
+ }
+ return leastSquaresResidual;
}
-
-btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactFrictionConstraints( const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd )
+btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactFrictionConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd)
{
- btScalar leastSquaresResidual = 0.f;
- for ( int iiCons = batchBegin; iiCons < batchEnd; ++iiCons )
- {
- int iContact = consIndices[ iiCons ];
- btScalar totalImpulse = m_tmpSolverContactConstraintPool[ iContact ].m_appliedImpulse;
-
- // apply sliding friction
- if ( totalImpulse > 0.0f )
- {
- int iBegin = iContact * m_numFrictionDirections;
- int iEnd = iBegin + m_numFrictionDirections;
- for ( int iFriction = iBegin; iFriction < iEnd; ++iFriction )
- {
- btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[ iFriction++ ];
- btAssert( solveManifold.m_frictionIndex == iContact );
-
- solveManifold.m_lowerLimit = -( solveManifold.m_friction*totalImpulse );
- solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
-
- btSolverBody& bodyA = m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdA ];
- btSolverBody& bodyB = m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdB ];
- btScalar residual = resolveSingleConstraintRowGeneric( bodyA, bodyB, solveManifold );
- leastSquaresResidual += residual*residual;
- }
- }
- }
- return leastSquaresResidual;
-}
+ btScalar leastSquaresResidual = 0.f;
+ for (int iiCons = batchBegin; iiCons < batchEnd; ++iiCons)
+ {
+ int iContact = consIndices[iiCons];
+ btScalar totalImpulse = m_tmpSolverContactConstraintPool[iContact].m_appliedImpulse;
+ // apply sliding friction
+ if (totalImpulse > 0.0f)
+ {
+ int iBegin = iContact * m_numFrictionDirections;
+ int iEnd = iBegin + m_numFrictionDirections;
+ for (int iFriction = iBegin; iFriction < iEnd; ++iFriction)
+ {
+ btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[iFriction++];
+ btAssert(solveManifold.m_frictionIndex == iContact);
-btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactRollingFrictionConstraints( const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd )
-{
- btScalar leastSquaresResidual = 0.f;
- for ( int iiCons = batchBegin; iiCons < batchEnd; ++iiCons )
- {
- int iContact = consIndices[ iiCons ];
- int iFirstRollingFriction = m_rollingFrictionIndexTable[ iContact ];
- if ( iFirstRollingFriction >= 0 )
- {
- btScalar totalImpulse = m_tmpSolverContactConstraintPool[ iContact ].m_appliedImpulse;
- // apply rolling friction
- if ( totalImpulse > 0.0f )
- {
- int iBegin = iFirstRollingFriction;
- int iEnd = iBegin + 3;
- for ( int iRollingFric = iBegin; iRollingFric < iEnd; ++iRollingFric )
- {
- btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[ iRollingFric ];
- if ( rollingFrictionConstraint.m_frictionIndex != iContact )
- {
- break;
- }
- btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction*totalImpulse;
- if ( rollingFrictionMagnitude > rollingFrictionConstraint.m_friction )
- {
- rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
- }
-
- rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
- rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
-
- btScalar residual = resolveSingleConstraintRowGeneric( m_tmpSolverBodyPool[ rollingFrictionConstraint.m_solverBodyIdA ], m_tmpSolverBodyPool[ rollingFrictionConstraint.m_solverBodyIdB ], rollingFrictionConstraint );
- leastSquaresResidual += residual*residual;
- }
- }
- }
- }
- return leastSquaresResidual;
-}
+ solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
+ solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
+ btSolverBody& bodyA = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA];
+ btSolverBody& bodyB = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB];
+ btScalar residual = resolveSingleConstraintRowGeneric(bodyA, bodyB, solveManifold);
+ leastSquaresResidual += residual * residual;
+ }
+ }
+ }
+ return leastSquaresResidual;
+}
-btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactConstraintsInterleaved( const btAlignedObjectArray<int>& contactIndices,
- int batchBegin,
- int batchEnd
- )
+btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactRollingFrictionConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd)
{
- btScalar leastSquaresResidual = 0.f;
- int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
-
- for ( int iiCons = batchBegin; iiCons < batchEnd; iiCons++ )
- {
- btScalar totalImpulse = 0;
- int iContact = contactIndices[ iiCons ];
- // apply penetration constraint
- {
- const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[ iContact ];
- btScalar residual = resolveSingleConstraintRowLowerLimit( m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdA ], m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdB ], solveManifold );
- leastSquaresResidual += residual*residual;
- totalImpulse = solveManifold.m_appliedImpulse;
- }
-
- // apply sliding friction
- if ( totalImpulse > 0.0f )
- {
- int iBegin = iContact * m_numFrictionDirections;
- int iEnd = iBegin + m_numFrictionDirections;
- for ( int iFriction = iBegin; iFriction < iEnd; ++iFriction )
- {
- btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[ iFriction ];
- btAssert( solveManifold.m_frictionIndex == iContact );
-
- solveManifold.m_lowerLimit = -( solveManifold.m_friction*totalImpulse );
- solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
-
- btSolverBody& bodyA = m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdA ];
- btSolverBody& bodyB = m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdB ];
- btScalar residual = resolveSingleConstraintRowGeneric( bodyA, bodyB, solveManifold );
- leastSquaresResidual += residual*residual;
- }
- }
-
- // apply rolling friction
- int iFirstRollingFriction = m_rollingFrictionIndexTable[ iContact ];
- if ( totalImpulse > 0.0f && iFirstRollingFriction >= 0)
- {
- int iBegin = iFirstRollingFriction;
- int iEnd = iBegin + 3;
- for ( int iRollingFric = iBegin; iRollingFric < iEnd; ++iRollingFric )
- {
- btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[ iRollingFric ];
- if ( rollingFrictionConstraint.m_frictionIndex != iContact )
- {
- break;
- }
- btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction*totalImpulse;
- if ( rollingFrictionMagnitude > rollingFrictionConstraint.m_friction )
- {
- rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
- }
-
- rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
- rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
-
- btScalar residual = resolveSingleConstraintRowGeneric( m_tmpSolverBodyPool[ rollingFrictionConstraint.m_solverBodyIdA ], m_tmpSolverBodyPool[ rollingFrictionConstraint.m_solverBodyIdB ], rollingFrictionConstraint );
- leastSquaresResidual += residual*residual;
- }
- }
- }
- return leastSquaresResidual;
+ btScalar leastSquaresResidual = 0.f;
+ for (int iiCons = batchBegin; iiCons < batchEnd; ++iiCons)
+ {
+ int iContact = consIndices[iiCons];
+ int iFirstRollingFriction = m_rollingFrictionIndexTable[iContact];
+ if (iFirstRollingFriction >= 0)
+ {
+ btScalar totalImpulse = m_tmpSolverContactConstraintPool[iContact].m_appliedImpulse;
+ // apply rolling friction
+ if (totalImpulse > 0.0f)
+ {
+ int iBegin = iFirstRollingFriction;
+ int iEnd = iBegin + 3;
+ for (int iRollingFric = iBegin; iRollingFric < iEnd; ++iRollingFric)
+ {
+ btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[iRollingFric];
+ if (rollingFrictionConstraint.m_frictionIndex != iContact)
+ {
+ break;
+ }
+ btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse;
+ if (rollingFrictionMagnitude > rollingFrictionConstraint.m_friction)
+ {
+ rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
+ }
+
+ rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
+ rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
+
+ btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint);
+ leastSquaresResidual += residual * residual;
+ }
+ }
+ }
+ }
+ return leastSquaresResidual;
}
-
-void btSequentialImpulseConstraintSolverMt::randomizeBatchedConstraintOrdering( btBatchedConstraints* batchedConstraints )
+btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactConstraintsInterleaved(const btAlignedObjectArray<int>& contactIndices,
+ int batchBegin,
+ int batchEnd)
{
- btBatchedConstraints& bc = *batchedConstraints;
- // randomize ordering of phases
- for ( int ii = 1; ii < bc.m_phaseOrder.size(); ++ii )
- {
- int iSwap = btRandInt2( ii + 1 );
- bc.m_phaseOrder.swap( ii, iSwap );
- }
-
- // for each batch,
- for ( int iBatch = 0; iBatch < bc.m_batches.size(); ++iBatch )
- {
- // randomize ordering of constraints within the batch
- const btBatchedConstraints::Range& batch = bc.m_batches[ iBatch ];
- for ( int iiCons = batch.begin; iiCons < batch.end; ++iiCons )
- {
- int iSwap = batch.begin + btRandInt2( iiCons - batch.begin + 1 );
- btAssert(iSwap >= batch.begin && iSwap < batch.end);
- bc.m_constraintIndices.swap( iiCons, iSwap );
- }
- }
+ btScalar leastSquaresResidual = 0.f;
+ int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+
+ for (int iiCons = batchBegin; iiCons < batchEnd; iiCons++)
+ {
+ btScalar totalImpulse = 0;
+ int iContact = contactIndices[iiCons];
+ // apply penetration constraint
+ {
+ const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[iContact];
+ btScalar residual = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+ leastSquaresResidual += residual * residual;
+ totalImpulse = solveManifold.m_appliedImpulse;
+ }
+
+ // apply sliding friction
+ if (totalImpulse > 0.0f)
+ {
+ int iBegin = iContact * m_numFrictionDirections;
+ int iEnd = iBegin + m_numFrictionDirections;
+ for (int iFriction = iBegin; iFriction < iEnd; ++iFriction)
+ {
+ btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[iFriction];
+ btAssert(solveManifold.m_frictionIndex == iContact);
+
+ solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
+ solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
+
+ btSolverBody& bodyA = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA];
+ btSolverBody& bodyB = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB];
+ btScalar residual = resolveSingleConstraintRowGeneric(bodyA, bodyB, solveManifold);
+ leastSquaresResidual += residual * residual;
+ }
+ }
+
+ // apply rolling friction
+ int iFirstRollingFriction = m_rollingFrictionIndexTable[iContact];
+ if (totalImpulse > 0.0f && iFirstRollingFriction >= 0)
+ {
+ int iBegin = iFirstRollingFriction;
+ int iEnd = iBegin + 3;
+ for (int iRollingFric = iBegin; iRollingFric < iEnd; ++iRollingFric)
+ {
+ btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[iRollingFric];
+ if (rollingFrictionConstraint.m_frictionIndex != iContact)
+ {
+ break;
+ }
+ btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse;
+ if (rollingFrictionMagnitude > rollingFrictionConstraint.m_friction)
+ {
+ rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
+ }
+
+ rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
+ rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
+
+ btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint);
+ leastSquaresResidual += residual * residual;
+ }
+ }
+ }
+ return leastSquaresResidual;
}
+void btSequentialImpulseConstraintSolverMt::randomizeBatchedConstraintOrdering(btBatchedConstraints* batchedConstraints)
+{
+ btBatchedConstraints& bc = *batchedConstraints;
+ // randomize ordering of phases
+ for (int ii = 1; ii < bc.m_phaseOrder.size(); ++ii)
+ {
+ int iSwap = btRandInt2(ii + 1);
+ bc.m_phaseOrder.swap(ii, iSwap);
+ }
+
+ // for each batch,
+ for (int iBatch = 0; iBatch < bc.m_batches.size(); ++iBatch)
+ {
+ // randomize ordering of constraints within the batch
+ const btBatchedConstraints::Range& batch = bc.m_batches[iBatch];
+ for (int iiCons = batch.begin; iiCons < batch.end; ++iiCons)
+ {
+ int iSwap = batch.begin + btRandInt2(iiCons - batch.begin + 1);
+ btAssert(iSwap >= batch.begin && iSwap < batch.end);
+ bc.m_constraintIndices.swap(iiCons, iSwap);
+ }
+ }
+}
void btSequentialImpulseConstraintSolverMt::randomizeConstraintOrdering(int iteration, int numIterations)
{
- // randomize ordering of joint constraints
- randomizeBatchedConstraintOrdering( &m_batchedJointConstraints );
-
- //contact/friction constraints are not solved more than numIterations
- if ( iteration < numIterations )
- {
- randomizeBatchedConstraintOrdering( &m_batchedContactConstraints );
- }
-}
+ // randomize ordering of joint constraints
+ randomizeBatchedConstraintOrdering(&m_batchedJointConstraints);
+ //contact/friction constraints are not solved more than numIterations
+ if (iteration < numIterations)
+ {
+ randomizeBatchedConstraintOrdering(&m_batchedContactConstraints);
+ }
+}
struct JointSolverLoop : public btIParallelSumBody
{
- btSequentialImpulseConstraintSolverMt* m_solver;
- const btBatchedConstraints* m_bc;
- int m_iteration;
-
- JointSolverLoop( btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc, int iteration )
- {
- m_solver = solver;
- m_bc = bc;
- m_iteration = iteration;
- }
- btScalar sumLoop( int iBegin, int iEnd ) const BT_OVERRIDE
- {
- BT_PROFILE( "JointSolverLoop" );
- btScalar sum = 0;
- for ( int iBatch = iBegin; iBatch < iEnd; ++iBatch )
- {
- const btBatchedConstraints::Range& batch = m_bc->m_batches[ iBatch ];
- sum += m_solver->resolveMultipleJointConstraints( m_bc->m_constraintIndices, batch.begin, batch.end, m_iteration );
- }
- return sum;
- }
-};
+ btSequentialImpulseConstraintSolverMt* m_solver;
+ const btBatchedConstraints* m_bc;
+ int m_iteration;
+ JointSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc, int iteration)
+ {
+ m_solver = solver;
+ m_bc = bc;
+ m_iteration = iteration;
+ }
+ btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE
+ {
+ BT_PROFILE("JointSolverLoop");
+ btScalar sum = 0;
+ for (int iBatch = iBegin; iBatch < iEnd; ++iBatch)
+ {
+ const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch];
+ sum += m_solver->resolveMultipleJointConstraints(m_bc->m_constraintIndices, batch.begin, batch.end, m_iteration);
+ }
+ return sum;
+ }
+};
btScalar btSequentialImpulseConstraintSolverMt::resolveAllJointConstraints(int iteration)
{
- BT_PROFILE( "resolveAllJointConstraints" );
- const btBatchedConstraints& batchedCons = m_batchedJointConstraints;
- JointSolverLoop loop( this, &batchedCons, iteration );
- btScalar leastSquaresResidual = 0.f;
- for ( int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase )
- {
- int iPhase = batchedCons.m_phaseOrder[ iiPhase ];
- const btBatchedConstraints::Range& phase = batchedCons.m_phases[ iPhase ];
- int grainSize = 1;
- leastSquaresResidual += btParallelSum( phase.begin, phase.end, grainSize, loop );
- }
- return leastSquaresResidual;
+ BT_PROFILE("resolveAllJointConstraints");
+ const btBatchedConstraints& batchedCons = m_batchedJointConstraints;
+ JointSolverLoop loop(this, &batchedCons, iteration);
+ btScalar leastSquaresResidual = 0.f;
+ for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase)
+ {
+ int iPhase = batchedCons.m_phaseOrder[iiPhase];
+ const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase];
+ int grainSize = 1;
+ leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop);
+ }
+ return leastSquaresResidual;
}
-
struct ContactSolverLoop : public btIParallelSumBody
{
- btSequentialImpulseConstraintSolverMt* m_solver;
- const btBatchedConstraints* m_bc;
-
- ContactSolverLoop( btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc )
- {
- m_solver = solver;
- m_bc = bc;
- }
- btScalar sumLoop( int iBegin, int iEnd ) const BT_OVERRIDE
- {
- BT_PROFILE( "ContactSolverLoop" );
- btScalar sum = 0;
- for ( int iBatch = iBegin; iBatch < iEnd; ++iBatch )
- {
- const btBatchedConstraints::Range& batch = m_bc->m_batches[ iBatch ];
- sum += m_solver->resolveMultipleContactConstraints( m_bc->m_constraintIndices, batch.begin, batch.end );
- }
- return sum;
- }
-};
+ btSequentialImpulseConstraintSolverMt* m_solver;
+ const btBatchedConstraints* m_bc;
+ ContactSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc)
+ {
+ m_solver = solver;
+ m_bc = bc;
+ }
+ btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE
+ {
+ BT_PROFILE("ContactSolverLoop");
+ btScalar sum = 0;
+ for (int iBatch = iBegin; iBatch < iEnd; ++iBatch)
+ {
+ const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch];
+ sum += m_solver->resolveMultipleContactConstraints(m_bc->m_constraintIndices, batch.begin, batch.end);
+ }
+ return sum;
+ }
+};
btScalar btSequentialImpulseConstraintSolverMt::resolveAllContactConstraints()
{
- BT_PROFILE( "resolveAllContactConstraints" );
- const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
- ContactSolverLoop loop( this, &batchedCons );
- btScalar leastSquaresResidual = 0.f;
- for ( int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase )
- {
- int iPhase = batchedCons.m_phaseOrder[ iiPhase ];
- const btBatchedConstraints::Range& phase = batchedCons.m_phases[ iPhase ];
- int grainSize = batchedCons.m_phaseGrainSize[iPhase];
- leastSquaresResidual += btParallelSum( phase.begin, phase.end, grainSize, loop );
- }
- return leastSquaresResidual;
+ BT_PROFILE("resolveAllContactConstraints");
+ const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
+ ContactSolverLoop loop(this, &batchedCons);
+ btScalar leastSquaresResidual = 0.f;
+ for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase)
+ {
+ int iPhase = batchedCons.m_phaseOrder[iiPhase];
+ const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase];
+ int grainSize = batchedCons.m_phaseGrainSize[iPhase];
+ leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop);
+ }
+ return leastSquaresResidual;
}
-
struct ContactFrictionSolverLoop : public btIParallelSumBody
{
- btSequentialImpulseConstraintSolverMt* m_solver;
- const btBatchedConstraints* m_bc;
-
- ContactFrictionSolverLoop( btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc )
- {
- m_solver = solver;
- m_bc = bc;
- }
- btScalar sumLoop( int iBegin, int iEnd ) const BT_OVERRIDE
- {
- BT_PROFILE( "ContactFrictionSolverLoop" );
- btScalar sum = 0;
- for ( int iBatch = iBegin; iBatch < iEnd; ++iBatch )
- {
- const btBatchedConstraints::Range& batch = m_bc->m_batches[ iBatch ];
- sum += m_solver->resolveMultipleContactFrictionConstraints( m_bc->m_constraintIndices, batch.begin, batch.end );
- }
- return sum;
- }
-};
+ btSequentialImpulseConstraintSolverMt* m_solver;
+ const btBatchedConstraints* m_bc;
+ ContactFrictionSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc)
+ {
+ m_solver = solver;
+ m_bc = bc;
+ }
+ btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE
+ {
+ BT_PROFILE("ContactFrictionSolverLoop");
+ btScalar sum = 0;
+ for (int iBatch = iBegin; iBatch < iEnd; ++iBatch)
+ {
+ const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch];
+ sum += m_solver->resolveMultipleContactFrictionConstraints(m_bc->m_constraintIndices, batch.begin, batch.end);
+ }
+ return sum;
+ }
+};
btScalar btSequentialImpulseConstraintSolverMt::resolveAllContactFrictionConstraints()
{
- BT_PROFILE( "resolveAllContactFrictionConstraints" );
- const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
- ContactFrictionSolverLoop loop( this, &batchedCons );
- btScalar leastSquaresResidual = 0.f;
- for ( int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase )
- {
- int iPhase = batchedCons.m_phaseOrder[ iiPhase ];
- const btBatchedConstraints::Range& phase = batchedCons.m_phases[ iPhase ];
- int grainSize = batchedCons.m_phaseGrainSize[iPhase];
- leastSquaresResidual += btParallelSum( phase.begin, phase.end, grainSize, loop );
- }
- return leastSquaresResidual;
+ BT_PROFILE("resolveAllContactFrictionConstraints");
+ const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
+ ContactFrictionSolverLoop loop(this, &batchedCons);
+ btScalar leastSquaresResidual = 0.f;
+ for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase)
+ {
+ int iPhase = batchedCons.m_phaseOrder[iiPhase];
+ const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase];
+ int grainSize = batchedCons.m_phaseGrainSize[iPhase];
+ leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop);
+ }
+ return leastSquaresResidual;
}
-
struct InterleavedContactSolverLoop : public btIParallelSumBody
{
- btSequentialImpulseConstraintSolverMt* m_solver;
- const btBatchedConstraints* m_bc;
-
- InterleavedContactSolverLoop( btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc )
- {
- m_solver = solver;
- m_bc = bc;
- }
- btScalar sumLoop( int iBegin, int iEnd ) const BT_OVERRIDE
- {
- BT_PROFILE( "InterleavedContactSolverLoop" );
- btScalar sum = 0;
- for ( int iBatch = iBegin; iBatch < iEnd; ++iBatch )
- {
- const btBatchedConstraints::Range& batch = m_bc->m_batches[ iBatch ];
- sum += m_solver->resolveMultipleContactConstraintsInterleaved( m_bc->m_constraintIndices, batch.begin, batch.end );
- }
- return sum;
- }
-};
+ btSequentialImpulseConstraintSolverMt* m_solver;
+ const btBatchedConstraints* m_bc;
+ InterleavedContactSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc)
+ {
+ m_solver = solver;
+ m_bc = bc;
+ }
+ btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE
+ {
+ BT_PROFILE("InterleavedContactSolverLoop");
+ btScalar sum = 0;
+ for (int iBatch = iBegin; iBatch < iEnd; ++iBatch)
+ {
+ const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch];
+ sum += m_solver->resolveMultipleContactConstraintsInterleaved(m_bc->m_constraintIndices, batch.begin, batch.end);
+ }
+ return sum;
+ }
+};
btScalar btSequentialImpulseConstraintSolverMt::resolveAllContactConstraintsInterleaved()
{
- BT_PROFILE( "resolveAllContactConstraintsInterleaved" );
- const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
- InterleavedContactSolverLoop loop( this, &batchedCons );
- btScalar leastSquaresResidual = 0.f;
- for ( int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase )
- {
- int iPhase = batchedCons.m_phaseOrder[ iiPhase ];
- const btBatchedConstraints::Range& phase = batchedCons.m_phases[ iPhase ];
- int grainSize = 1;
- leastSquaresResidual += btParallelSum( phase.begin, phase.end, grainSize, loop );
- }
- return leastSquaresResidual;
+ BT_PROFILE("resolveAllContactConstraintsInterleaved");
+ const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
+ InterleavedContactSolverLoop loop(this, &batchedCons);
+ btScalar leastSquaresResidual = 0.f;
+ for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase)
+ {
+ int iPhase = batchedCons.m_phaseOrder[iiPhase];
+ const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase];
+ int grainSize = 1;
+ leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop);
+ }
+ return leastSquaresResidual;
}
-
struct ContactRollingFrictionSolverLoop : public btIParallelSumBody
{
- btSequentialImpulseConstraintSolverMt* m_solver;
- const btBatchedConstraints* m_bc;
-
- ContactRollingFrictionSolverLoop( btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc )
- {
- m_solver = solver;
- m_bc = bc;
- }
- btScalar sumLoop( int iBegin, int iEnd ) const BT_OVERRIDE
- {
- BT_PROFILE( "ContactFrictionSolverLoop" );
- btScalar sum = 0;
- for ( int iBatch = iBegin; iBatch < iEnd; ++iBatch )
- {
- const btBatchedConstraints::Range& batch = m_bc->m_batches[ iBatch ];
- sum += m_solver->resolveMultipleContactRollingFrictionConstraints( m_bc->m_constraintIndices, batch.begin, batch.end );
- }
- return sum;
- }
-};
+ btSequentialImpulseConstraintSolverMt* m_solver;
+ const btBatchedConstraints* m_bc;
+ ContactRollingFrictionSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc)
+ {
+ m_solver = solver;
+ m_bc = bc;
+ }
+ btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE
+ {
+ BT_PROFILE("ContactFrictionSolverLoop");
+ btScalar sum = 0;
+ for (int iBatch = iBegin; iBatch < iEnd; ++iBatch)
+ {
+ const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch];
+ sum += m_solver->resolveMultipleContactRollingFrictionConstraints(m_bc->m_constraintIndices, batch.begin, batch.end);
+ }
+ return sum;
+ }
+};
btScalar btSequentialImpulseConstraintSolverMt::resolveAllRollingFrictionConstraints()
{
- BT_PROFILE( "resolveAllRollingFrictionConstraints" );
- btScalar leastSquaresResidual = 0.f;
- //
- // We do not generate batches for rolling friction constraints. We assume that
- // one of two cases is true:
- //
- // 1. either most bodies in the simulation have rolling friction, in which case we can use the
- // batches for contacts and use a lookup table to translate contact indices to rolling friction
- // (ignoring any contact indices that don't map to a rolling friction constraint). As long as
- // most contacts have a corresponding rolling friction constraint, this should parallelize well.
- //
- // -OR-
- //
- // 2. few bodies in the simulation have rolling friction, so it is not worth trying to use the
- // batches from contacts as most of the contacts won't have corresponding rolling friction
- // constraints and most threads would end up doing very little work. Most of the time would
- // go to threading overhead, so we don't bother with threading.
- //
- int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size();
- if (numRollingFrictionPoolConstraints >= m_tmpSolverContactConstraintPool.size())
- {
- // use batching if there are many rolling friction constraints
- const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
- ContactRollingFrictionSolverLoop loop( this, &batchedCons );
- btScalar leastSquaresResidual = 0.f;
- for ( int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase )
- {
- int iPhase = batchedCons.m_phaseOrder[ iiPhase ];
- const btBatchedConstraints::Range& phase = batchedCons.m_phases[ iPhase ];
- int grainSize = 1;
- leastSquaresResidual += btParallelSum( phase.begin, phase.end, grainSize, loop );
- }
- }
- else
- {
- // no batching, also ignores SOLVER_RANDMIZE_ORDER
- for ( int j = 0; j < numRollingFrictionPoolConstraints; j++ )
- {
- btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[ j ];
- if ( rollingFrictionConstraint.m_frictionIndex >= 0 )
- {
- btScalar totalImpulse = m_tmpSolverContactConstraintPool[ rollingFrictionConstraint.m_frictionIndex ].m_appliedImpulse;
- if ( totalImpulse > 0.0f )
- {
- btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction*totalImpulse;
- if ( rollingFrictionMagnitude > rollingFrictionConstraint.m_friction )
- rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
-
- rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
- rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
-
- btScalar residual = resolveSingleConstraintRowGeneric( m_tmpSolverBodyPool[ rollingFrictionConstraint.m_solverBodyIdA ], m_tmpSolverBodyPool[ rollingFrictionConstraint.m_solverBodyIdB ], rollingFrictionConstraint );
- leastSquaresResidual += residual*residual;
- }
- }
- }
- }
- return leastSquaresResidual;
+ BT_PROFILE("resolveAllRollingFrictionConstraints");
+ btScalar leastSquaresResidual = 0.f;
+ //
+ // We do not generate batches for rolling friction constraints. We assume that
+ // one of two cases is true:
+ //
+ // 1. either most bodies in the simulation have rolling friction, in which case we can use the
+ // batches for contacts and use a lookup table to translate contact indices to rolling friction
+ // (ignoring any contact indices that don't map to a rolling friction constraint). As long as
+ // most contacts have a corresponding rolling friction constraint, this should parallelize well.
+ //
+ // -OR-
+ //
+ // 2. few bodies in the simulation have rolling friction, so it is not worth trying to use the
+ // batches from contacts as most of the contacts won't have corresponding rolling friction
+ // constraints and most threads would end up doing very little work. Most of the time would
+ // go to threading overhead, so we don't bother with threading.
+ //
+ int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size();
+ if (numRollingFrictionPoolConstraints >= m_tmpSolverContactConstraintPool.size())
+ {
+ // use batching if there are many rolling friction constraints
+ const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
+ ContactRollingFrictionSolverLoop loop(this, &batchedCons);
+ btScalar leastSquaresResidual = 0.f;
+ for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase)
+ {
+ int iPhase = batchedCons.m_phaseOrder[iiPhase];
+ const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase];
+ int grainSize = 1;
+ leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop);
+ }
+ }
+ else
+ {
+ // no batching, also ignores SOLVER_RANDMIZE_ORDER
+ for (int j = 0; j < numRollingFrictionPoolConstraints; j++)
+ {
+ btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
+ if (rollingFrictionConstraint.m_frictionIndex >= 0)
+ {
+ btScalar totalImpulse = m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse;
+ if (totalImpulse > 0.0f)
+ {
+ btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse;
+ if (rollingFrictionMagnitude > rollingFrictionConstraint.m_friction)
+ rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
+
+ rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
+ rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
+
+ btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint);
+ leastSquaresResidual += residual * residual;
+ }
+ }
+ }
+ }
+ return leastSquaresResidual;
}
-
-void btSequentialImpulseConstraintSolverMt::internalWriteBackContacts( int iBegin, int iEnd, const btContactSolverInfo& infoGlobal )
+void btSequentialImpulseConstraintSolverMt::internalWriteBackContacts(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
{
- BT_PROFILE("internalWriteBackContacts");
- writeBackContacts(iBegin, iEnd, infoGlobal);
- //for ( int iContact = iBegin; iContact < iEnd; ++iContact)
- //{
- // const btSolverConstraint& contactConstraint = m_tmpSolverContactConstraintPool[ iContact ];
- // btManifoldPoint* pt = (btManifoldPoint*) contactConstraint.m_originalContactPoint;
- // btAssert( pt );
- // pt->m_appliedImpulse = contactConstraint.m_appliedImpulse;
- // pt->m_appliedImpulseLateral1 = m_tmpSolverContactFrictionConstraintPool[ contactConstraint.m_frictionIndex ].m_appliedImpulse;
- // if ( m_numFrictionDirections == 2 )
- // {
- // pt->m_appliedImpulseLateral2 = m_tmpSolverContactFrictionConstraintPool[ contactConstraint.m_frictionIndex + 1 ].m_appliedImpulse;
- // }
- //}
+ BT_PROFILE("internalWriteBackContacts");
+ writeBackContacts(iBegin, iEnd, infoGlobal);
+ //for ( int iContact = iBegin; iContact < iEnd; ++iContact)
+ //{
+ // const btSolverConstraint& contactConstraint = m_tmpSolverContactConstraintPool[ iContact ];
+ // btManifoldPoint* pt = (btManifoldPoint*) contactConstraint.m_originalContactPoint;
+ // btAssert( pt );
+ // pt->m_appliedImpulse = contactConstraint.m_appliedImpulse;
+ // pt->m_appliedImpulseLateral1 = m_tmpSolverContactFrictionConstraintPool[ contactConstraint.m_frictionIndex ].m_appliedImpulse;
+ // if ( m_numFrictionDirections == 2 )
+ // {
+ // pt->m_appliedImpulseLateral2 = m_tmpSolverContactFrictionConstraintPool[ contactConstraint.m_frictionIndex + 1 ].m_appliedImpulse;
+ // }
+ //}
}
-
-void btSequentialImpulseConstraintSolverMt::internalWriteBackJoints( int iBegin, int iEnd, const btContactSolverInfo& infoGlobal )
+void btSequentialImpulseConstraintSolverMt::internalWriteBackJoints(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
{
BT_PROFILE("internalWriteBackJoints");
- writeBackJoints(iBegin, iEnd, infoGlobal);
+ writeBackJoints(iBegin, iEnd, infoGlobal);
}
-
-void btSequentialImpulseConstraintSolverMt::internalWriteBackBodies( int iBegin, int iEnd, const btContactSolverInfo& infoGlobal )
+void btSequentialImpulseConstraintSolverMt::internalWriteBackBodies(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
{
BT_PROFILE("internalWriteBackBodies");
- writeBackBodies( iBegin, iEnd, infoGlobal );
+ writeBackBodies(iBegin, iEnd, infoGlobal);
}
-
struct WriteContactPointsLoop : public btIParallelForBody
{
- btSequentialImpulseConstraintSolverMt* m_solver;
- const btContactSolverInfo* m_infoGlobal;
-
- WriteContactPointsLoop( btSequentialImpulseConstraintSolverMt* solver, const btContactSolverInfo& infoGlobal )
- {
- m_solver = solver;
- m_infoGlobal = &infoGlobal;
- }
- void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE
- {
- m_solver->internalWriteBackContacts( iBegin, iEnd, *m_infoGlobal );
- }
-};
+ btSequentialImpulseConstraintSolverMt* m_solver;
+ const btContactSolverInfo* m_infoGlobal;
+ WriteContactPointsLoop(btSequentialImpulseConstraintSolverMt* solver, const btContactSolverInfo& infoGlobal)
+ {
+ m_solver = solver;
+ m_infoGlobal = &infoGlobal;
+ }
+ void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
+ {
+ m_solver->internalWriteBackContacts(iBegin, iEnd, *m_infoGlobal);
+ }
+};
struct WriteJointsLoop : public btIParallelForBody
{
- btSequentialImpulseConstraintSolverMt* m_solver;
- const btContactSolverInfo* m_infoGlobal;
-
- WriteJointsLoop( btSequentialImpulseConstraintSolverMt* solver, const btContactSolverInfo& infoGlobal )
- {
- m_solver = solver;
- m_infoGlobal = &infoGlobal;
- }
- void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE
- {
- m_solver->internalWriteBackJoints( iBegin, iEnd, *m_infoGlobal );
- }
-};
+ btSequentialImpulseConstraintSolverMt* m_solver;
+ const btContactSolverInfo* m_infoGlobal;
+ WriteJointsLoop(btSequentialImpulseConstraintSolverMt* solver, const btContactSolverInfo& infoGlobal)
+ {
+ m_solver = solver;
+ m_infoGlobal = &infoGlobal;
+ }
+ void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
+ {
+ m_solver->internalWriteBackJoints(iBegin, iEnd, *m_infoGlobal);
+ }
+};
struct WriteBodiesLoop : public btIParallelForBody
{
- btSequentialImpulseConstraintSolverMt* m_solver;
- const btContactSolverInfo* m_infoGlobal;
-
- WriteBodiesLoop( btSequentialImpulseConstraintSolverMt* solver, const btContactSolverInfo& infoGlobal )
- {
- m_solver = solver;
- m_infoGlobal = &infoGlobal;
- }
- void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE
- {
- m_solver->internalWriteBackBodies( iBegin, iEnd, *m_infoGlobal );
- }
-};
+ btSequentialImpulseConstraintSolverMt* m_solver;
+ const btContactSolverInfo* m_infoGlobal;
+ WriteBodiesLoop(btSequentialImpulseConstraintSolverMt* solver, const btContactSolverInfo& infoGlobal)
+ {
+ m_solver = solver;
+ m_infoGlobal = &infoGlobal;
+ }
+ void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
+ {
+ m_solver->internalWriteBackBodies(iBegin, iEnd, *m_infoGlobal);
+ }
+};
btScalar btSequentialImpulseConstraintSolverMt::solveGroupCacheFriendlyFinish(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
{
BT_PROFILE("solveGroupCacheFriendlyFinish");
if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
- {
- WriteContactPointsLoop loop( this, infoGlobal );
- int grainSize = 500;
- btParallelFor( 0, m_tmpSolverContactConstraintPool.size(), grainSize, loop );
- }
-
- {
- WriteJointsLoop loop( this, infoGlobal );
- int grainSize = 400;
- btParallelFor( 0, m_tmpSolverNonContactConstraintPool.size(), grainSize, loop );
- }
- {
- WriteBodiesLoop loop( this, infoGlobal );
- int grainSize = 100;
- btParallelFor( 0, m_tmpSolverBodyPool.size(), grainSize, loop );
- }
+ {
+ WriteContactPointsLoop loop(this, infoGlobal);
+ int grainSize = 500;
+ btParallelFor(0, m_tmpSolverContactConstraintPool.size(), grainSize, loop);
+ }
+
+ {
+ WriteJointsLoop loop(this, infoGlobal);
+ int grainSize = 400;
+ btParallelFor(0, m_tmpSolverNonContactConstraintPool.size(), grainSize, loop);
+ }
+ {
+ WriteBodiesLoop loop(this, infoGlobal);
+ int grainSize = 100;
+ btParallelFor(0, m_tmpSolverBodyPool.size(), grainSize, loop);
+ }
m_tmpSolverContactConstraintPool.resizeNoInitialize(0);
m_tmpSolverNonContactConstraintPool.resizeNoInitialize(0);
@@ -1618,4 +1552,3 @@ btScalar btSequentialImpulseConstraintSolverMt::solveGroupCacheFriendlyFinish(bt
m_tmpSolverBodyPool.resizeNoInitialize(0);
return 0.f;
}
-
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.h
index 55d53474c4..1861ddd7d7 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.h
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.h
@@ -53,102 +53,98 @@ subject to the following restrictions:
/// because floating point addition is not associative due to rounding errors.
/// The task scheduler can and should ensure that the result of any parallelSum operation is deterministic.
///
-ATTRIBUTE_ALIGNED16(class) btSequentialImpulseConstraintSolverMt : public btSequentialImpulseConstraintSolver
+ATTRIBUTE_ALIGNED16(class)
+btSequentialImpulseConstraintSolverMt : public btSequentialImpulseConstraintSolver
{
public:
- virtual void solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer) BT_OVERRIDE;
- virtual btScalar solveSingleIteration(int iteration, btCollisionObject** bodies ,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer) BT_OVERRIDE;
- virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer) BT_OVERRIDE;
- virtual btScalar solveGroupCacheFriendlyFinish(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal) BT_OVERRIDE;
-
- // temp struct used to collect info from persistent manifolds into a cache-friendly struct using multiple threads
- struct btContactManifoldCachedInfo
- {
- static const int MAX_NUM_CONTACT_POINTS = 4;
-
- int numTouchingContacts;
- int solverBodyIds[ 2 ];
- int contactIndex;
- int rollingFrictionIndex;
- bool contactHasRollingFriction[ MAX_NUM_CONTACT_POINTS ];
- btManifoldPoint* contactPoints[ MAX_NUM_CONTACT_POINTS ];
- };
- // temp struct used for setting up joint constraints in parallel
- struct JointParams
- {
- int m_solverConstraint;
- int m_solverBodyA;
- int m_solverBodyB;
- };
- void internalInitMultipleJoints(btTypedConstraint** constraints, int iBegin, int iEnd);
- void internalConvertMultipleJoints( const btAlignedObjectArray<JointParams>& jointParamsArray, btTypedConstraint** constraints, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal );
-
- // parameters to control batching
- static bool s_allowNestedParallelForLoops; // whether to allow nested parallel operations
- static int s_minimumContactManifoldsForBatching; // don't even try to batch if fewer manifolds than this
- static btBatchedConstraints::BatchingMethod s_contactBatchingMethod;
- static btBatchedConstraints::BatchingMethod s_jointBatchingMethod;
- static int s_minBatchSize; // desired number of constraints per batch
- static int s_maxBatchSize;
+ virtual void solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer) BT_OVERRIDE;
+ virtual btScalar solveSingleIteration(int iteration, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer) BT_OVERRIDE;
+ virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer) BT_OVERRIDE;
+ virtual btScalar solveGroupCacheFriendlyFinish(btCollisionObject * *bodies, int numBodies, const btContactSolverInfo& infoGlobal) BT_OVERRIDE;
+
+ // temp struct used to collect info from persistent manifolds into a cache-friendly struct using multiple threads
+ struct btContactManifoldCachedInfo
+ {
+ static const int MAX_NUM_CONTACT_POINTS = 4;
+
+ int numTouchingContacts;
+ int solverBodyIds[2];
+ int contactIndex;
+ int rollingFrictionIndex;
+ bool contactHasRollingFriction[MAX_NUM_CONTACT_POINTS];
+ btManifoldPoint* contactPoints[MAX_NUM_CONTACT_POINTS];
+ };
+ // temp struct used for setting up joint constraints in parallel
+ struct JointParams
+ {
+ int m_solverConstraint;
+ int m_solverBodyA;
+ int m_solverBodyB;
+ };
+ void internalInitMultipleJoints(btTypedConstraint * *constraints, int iBegin, int iEnd);
+ void internalConvertMultipleJoints(const btAlignedObjectArray<JointParams>& jointParamsArray, btTypedConstraint** constraints, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
+
+ // parameters to control batching
+ static bool s_allowNestedParallelForLoops; // whether to allow nested parallel operations
+ static int s_minimumContactManifoldsForBatching; // don't even try to batch if fewer manifolds than this
+ static btBatchedConstraints::BatchingMethod s_contactBatchingMethod;
+ static btBatchedConstraints::BatchingMethod s_jointBatchingMethod;
+ static int s_minBatchSize; // desired number of constraints per batch
+ static int s_maxBatchSize;
protected:
- static const int CACHE_LINE_SIZE = 64;
-
- btBatchedConstraints m_batchedContactConstraints;
- btBatchedConstraints m_batchedJointConstraints;
- int m_numFrictionDirections;
- bool m_useBatching;
- bool m_useObsoleteJointConstraints;
- btAlignedObjectArray<btContactManifoldCachedInfo> m_manifoldCachedInfoArray;
- btAlignedObjectArray<int> m_rollingFrictionIndexTable; // lookup table mapping contact index to rolling friction index
- btSpinMutex m_bodySolverArrayMutex;
- char m_antiFalseSharingPadding[CACHE_LINE_SIZE]; // padding to keep mutexes in separate cachelines
- btSpinMutex m_kinematicBodyUniqueIdToSolverBodyTableMutex;
- btAlignedObjectArray<char> m_scratchMemory;
-
- virtual void randomizeConstraintOrdering( int iteration, int numIterations );
- virtual btScalar resolveAllJointConstraints( int iteration );
- virtual btScalar resolveAllContactConstraints();
- virtual btScalar resolveAllContactFrictionConstraints();
- virtual btScalar resolveAllContactConstraintsInterleaved();
- virtual btScalar resolveAllRollingFrictionConstraints();
-
- virtual void setupBatchedContactConstraints();
- virtual void setupBatchedJointConstraints();
- virtual void convertJoints(btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal) BT_OVERRIDE;
- virtual void convertContacts(btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal) BT_OVERRIDE;
- virtual void convertBodies(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal) BT_OVERRIDE;
-
- int getOrInitSolverBodyThreadsafe(btCollisionObject& body, btScalar timeStep);
- void allocAllContactConstraints(btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal);
- void setupAllContactConstraints(const btContactSolverInfo& infoGlobal);
- void randomizeBatchedConstraintOrdering( btBatchedConstraints* batchedConstraints );
+ static const int CACHE_LINE_SIZE = 64;
+
+ btBatchedConstraints m_batchedContactConstraints;
+ btBatchedConstraints m_batchedJointConstraints;
+ int m_numFrictionDirections;
+ bool m_useBatching;
+ bool m_useObsoleteJointConstraints;
+ btAlignedObjectArray<btContactManifoldCachedInfo> m_manifoldCachedInfoArray;
+ btAlignedObjectArray<int> m_rollingFrictionIndexTable; // lookup table mapping contact index to rolling friction index
+ btSpinMutex m_bodySolverArrayMutex;
+ char m_antiFalseSharingPadding[CACHE_LINE_SIZE]; // padding to keep mutexes in separate cachelines
+ btSpinMutex m_kinematicBodyUniqueIdToSolverBodyTableMutex;
+ btAlignedObjectArray<char> m_scratchMemory;
+
+ virtual void randomizeConstraintOrdering(int iteration, int numIterations);
+ virtual btScalar resolveAllJointConstraints(int iteration);
+ virtual btScalar resolveAllContactConstraints();
+ virtual btScalar resolveAllContactFrictionConstraints();
+ virtual btScalar resolveAllContactConstraintsInterleaved();
+ virtual btScalar resolveAllRollingFrictionConstraints();
+
+ virtual void setupBatchedContactConstraints();
+ virtual void setupBatchedJointConstraints();
+ virtual void convertJoints(btTypedConstraint * *constraints, int numConstraints, const btContactSolverInfo& infoGlobal) BT_OVERRIDE;
+ virtual void convertContacts(btPersistentManifold * *manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal) BT_OVERRIDE;
+ virtual void convertBodies(btCollisionObject * *bodies, int numBodies, const btContactSolverInfo& infoGlobal) BT_OVERRIDE;
+
+ int getOrInitSolverBodyThreadsafe(btCollisionObject & body, btScalar timeStep);
+ void allocAllContactConstraints(btPersistentManifold * *manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal);
+ void setupAllContactConstraints(const btContactSolverInfo& infoGlobal);
+ void randomizeBatchedConstraintOrdering(btBatchedConstraints * batchedConstraints);
public:
-
BT_DECLARE_ALIGNED_ALLOCATOR();
btSequentialImpulseConstraintSolverMt();
virtual ~btSequentialImpulseConstraintSolverMt();
- btScalar resolveMultipleJointConstraints( const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd, int iteration );
- btScalar resolveMultipleContactConstraints( const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd );
- btScalar resolveMultipleContactSplitPenetrationImpulseConstraints( const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd );
- btScalar resolveMultipleContactFrictionConstraints( const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd );
- btScalar resolveMultipleContactRollingFrictionConstraints( const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd );
- btScalar resolveMultipleContactConstraintsInterleaved( const btAlignedObjectArray<int>& contactIndices, int batchBegin, int batchEnd );
-
- void internalCollectContactManifoldCachedInfo(btContactManifoldCachedInfo* cachedInfoArray, btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal);
- void internalAllocContactConstraints(const btContactManifoldCachedInfo* cachedInfoArray, int numManifolds);
- void internalSetupContactConstraints(int iContactConstraint, const btContactSolverInfo& infoGlobal);
- void internalConvertBodies(btCollisionObject** bodies, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
- void internalWriteBackContacts(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
- void internalWriteBackJoints(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
- void internalWriteBackBodies(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
+ btScalar resolveMultipleJointConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd, int iteration);
+ btScalar resolveMultipleContactConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd);
+ btScalar resolveMultipleContactSplitPenetrationImpulseConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd);
+ btScalar resolveMultipleContactFrictionConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd);
+ btScalar resolveMultipleContactRollingFrictionConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd);
+ btScalar resolveMultipleContactConstraintsInterleaved(const btAlignedObjectArray<int>& contactIndices, int batchBegin, int batchEnd);
+
+ void internalCollectContactManifoldCachedInfo(btContactManifoldCachedInfo * cachedInfoArray, btPersistentManifold * *manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal);
+ void internalAllocContactConstraints(const btContactManifoldCachedInfo* cachedInfoArray, int numManifolds);
+ void internalSetupContactConstraints(int iContactConstraint, const btContactSolverInfo& infoGlobal);
+ void internalConvertBodies(btCollisionObject * *bodies, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
+ void internalWriteBackContacts(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
+ void internalWriteBackJoints(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
+ void internalWriteBackBodies(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
};
-
-
-
-#endif //BT_SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_MT_H
-
+#endif //BT_SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_MT_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp
index d63cef0316..cac5302a73 100755
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp
@@ -18,8 +18,6 @@ Added by Roman Ponomarev (rponom@gmail.com)
April 04, 2008
*/
-
-
#include "btSliderConstraint.h"
#include "BulletDynamics/Dynamics/btRigidBody.h"
#include "LinearMath/btTransformUtil.h"
@@ -29,10 +27,10 @@ April 04, 2008
void btSliderConstraint::initParams()
{
- m_lowerLinLimit = btScalar(1.0);
- m_upperLinLimit = btScalar(-1.0);
- m_lowerAngLimit = btScalar(0.);
- m_upperAngLimit = btScalar(0.);
+ m_lowerLinLimit = btScalar(1.0);
+ m_upperLinLimit = btScalar(-1.0);
+ m_lowerAngLimit = btScalar(0.);
+ m_upperAngLimit = btScalar(0.);
m_softnessDirLin = SLIDER_CONSTRAINT_DEF_SOFTNESS;
m_restitutionDirLin = SLIDER_CONSTRAINT_DEF_RESTITUTION;
m_dampingDirLin = btScalar(0.);
@@ -59,13 +57,13 @@ void btSliderConstraint::initParams()
m_cfmLimAng = SLIDER_CONSTRAINT_DEF_CFM;
m_poweredLinMotor = false;
- m_targetLinMotorVelocity = btScalar(0.);
- m_maxLinMotorForce = btScalar(0.);
+ m_targetLinMotorVelocity = btScalar(0.);
+ m_maxLinMotorForce = btScalar(0.);
m_accumulatedLinMotorImpulse = btScalar(0.0);
m_poweredAngMotor = false;
- m_targetAngMotorVelocity = btScalar(0.);
- m_maxAngMotorForce = btScalar(0.);
+ m_targetAngMotorVelocity = btScalar(0.);
+ m_maxAngMotorForce = btScalar(0.);
m_accumulatedAngMotorImpulse = btScalar(0.0);
m_flags = 0;
@@ -73,43 +71,32 @@ void btSliderConstraint::initParams()
m_useOffsetForConstraintFrame = USE_OFFSET_FOR_CONSTANT_FRAME;
- calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
+ calculateTransforms(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
}
-
-
-
-
btSliderConstraint::btSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA)
- : btTypedConstraint(SLIDER_CONSTRAINT_TYPE, rbA, rbB),
- m_useSolveConstraintObsolete(false),
- m_frameInA(frameInA),
- m_frameInB(frameInB),
- m_useLinearReferenceFrameA(useLinearReferenceFrameA)
+ : btTypedConstraint(SLIDER_CONSTRAINT_TYPE, rbA, rbB),
+ m_useSolveConstraintObsolete(false),
+ m_frameInA(frameInA),
+ m_frameInB(frameInB),
+ m_useLinearReferenceFrameA(useLinearReferenceFrameA)
{
initParams();
}
-
-
btSliderConstraint::btSliderConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameA)
- : btTypedConstraint(SLIDER_CONSTRAINT_TYPE, getFixedBody(), rbB),
- m_useSolveConstraintObsolete(false),
- m_frameInB(frameInB),
- m_useLinearReferenceFrameA(useLinearReferenceFrameA)
+ : btTypedConstraint(SLIDER_CONSTRAINT_TYPE, getFixedBody(), rbB),
+ m_useSolveConstraintObsolete(false),
+ m_frameInB(frameInB),
+ m_useLinearReferenceFrameA(useLinearReferenceFrameA)
{
///not providing rigidbody A means implicitly using worldspace for body A
m_frameInA = rbB.getCenterOfMassTransform() * m_frameInB;
-// m_frameInA.getOrigin() = m_rbA.getCenterOfMassTransform()(m_frameInA.getOrigin());
+ // m_frameInA.getOrigin() = m_rbA.getCenterOfMassTransform()(m_frameInA.getOrigin());
initParams();
}
-
-
-
-
-
void btSliderConstraint::getInfo1(btConstraintInfo1* info)
{
if (m_useSolveConstraintObsolete)
@@ -119,46 +106,39 @@ void btSliderConstraint::getInfo1(btConstraintInfo1* info)
}
else
{
- info->m_numConstraintRows = 4; // Fixed 2 linear + 2 angular
- info->nub = 2;
+ info->m_numConstraintRows = 4; // Fixed 2 linear + 2 angular
+ info->nub = 2;
//prepare constraint
- calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
+ calculateTransforms(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
testAngLimits();
testLinLimits();
- if(getSolveLinLimit() || getPoweredLinMotor())
+ if (getSolveLinLimit() || getPoweredLinMotor())
{
- info->m_numConstraintRows++; // limit 3rd linear as well
- info->nub--;
+ info->m_numConstraintRows++; // limit 3rd linear as well
+ info->nub--;
}
- if(getSolveAngLimit() || getPoweredAngMotor())
+ if (getSolveAngLimit() || getPoweredAngMotor())
{
- info->m_numConstraintRows++; // limit 3rd angular as well
- info->nub--;
+ info->m_numConstraintRows++; // limit 3rd angular as well
+ info->nub--;
}
}
}
void btSliderConstraint::getInfo1NonVirtual(btConstraintInfo1* info)
{
-
- info->m_numConstraintRows = 6; // Fixed 2 linear + 2 angular + 1 limit (even if not used)
- info->nub = 0;
+ info->m_numConstraintRows = 6; // Fixed 2 linear + 2 angular + 1 limit (even if not used)
+ info->nub = 0;
}
void btSliderConstraint::getInfo2(btConstraintInfo2* info)
{
- getInfo2NonVirtual(info,m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(), m_rbA.getLinearVelocity(),m_rbB.getLinearVelocity(), m_rbA.getInvMass(),m_rbB.getInvMass());
+ getInfo2NonVirtual(info, m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform(), m_rbA.getLinearVelocity(), m_rbB.getLinearVelocity(), m_rbA.getInvMass(), m_rbB.getInvMass());
}
-
-
-
-
-
-
-void btSliderConstraint::calculateTransforms(const btTransform& transA,const btTransform& transB)
+void btSliderConstraint::calculateTransforms(const btTransform& transA, const btTransform& transB)
{
- if(m_useLinearReferenceFrameA || (!m_useSolveConstraintObsolete))
+ if (m_useLinearReferenceFrameA || (!m_useSolveConstraintObsolete))
{
m_calculatedTransformA = transA * m_frameInA;
m_calculatedTransformB = transB * m_frameInB;
@@ -170,8 +150,8 @@ void btSliderConstraint::calculateTransforms(const btTransform& transA,const btT
}
m_realPivotAInW = m_calculatedTransformA.getOrigin();
m_realPivotBInW = m_calculatedTransformB.getOrigin();
- m_sliderAxis = m_calculatedTransformA.getBasis().getColumn(0); // along X
- if(m_useLinearReferenceFrameA || m_useSolveConstraintObsolete)
+ m_sliderAxis = m_calculatedTransformA.getBasis().getColumn(0); // along X
+ if (m_useLinearReferenceFrameA || m_useSolveConstraintObsolete)
{
m_delta = m_realPivotBInW - m_realPivotAInW;
}
@@ -180,30 +160,28 @@ void btSliderConstraint::calculateTransforms(const btTransform& transA,const btT
m_delta = m_realPivotAInW - m_realPivotBInW;
}
m_projPivotInW = m_realPivotAInW + m_sliderAxis.dot(m_delta) * m_sliderAxis;
- btVector3 normalWorld;
- int i;
- //linear part
- for(i = 0; i < 3; i++)
- {
+ btVector3 normalWorld;
+ int i;
+ //linear part
+ for (i = 0; i < 3; i++)
+ {
normalWorld = m_calculatedTransformA.getBasis().getColumn(i);
m_depth[i] = m_delta.dot(normalWorld);
- }
+ }
}
-
-
void btSliderConstraint::testLinLimits(void)
{
m_solveLinLim = false;
m_linPos = m_depth[0];
- if(m_lowerLinLimit <= m_upperLinLimit)
+ if (m_lowerLinLimit <= m_upperLinLimit)
{
- if(m_depth[0] > m_upperLinLimit)
+ if (m_depth[0] > m_upperLinLimit)
{
m_depth[0] -= m_upperLinLimit;
m_solveLinLim = true;
}
- else if(m_depth[0] < m_lowerLinLimit)
+ else if (m_depth[0] < m_lowerLinLimit)
{
m_depth[0] -= m_lowerLinLimit;
m_solveLinLim = true;
@@ -219,27 +197,25 @@ void btSliderConstraint::testLinLimits(void)
}
}
-
-
void btSliderConstraint::testAngLimits(void)
{
m_angDepth = btScalar(0.);
m_solveAngLim = false;
- if(m_lowerAngLimit <= m_upperAngLimit)
+ if (m_lowerAngLimit <= m_upperAngLimit)
{
const btVector3 axisA0 = m_calculatedTransformA.getBasis().getColumn(1);
const btVector3 axisA1 = m_calculatedTransformA.getBasis().getColumn(2);
const btVector3 axisB0 = m_calculatedTransformB.getBasis().getColumn(1);
-// btScalar rot = btAtan2Fast(axisB0.dot(axisA1), axisB0.dot(axisA0));
- btScalar rot = btAtan2(axisB0.dot(axisA1), axisB0.dot(axisA0));
+ // btScalar rot = btAtan2Fast(axisB0.dot(axisA1), axisB0.dot(axisA0));
+ btScalar rot = btAtan2(axisB0.dot(axisA1), axisB0.dot(axisA0));
rot = btAdjustAngleToLimits(rot, m_lowerAngLimit, m_upperAngLimit);
m_angPos = rot;
- if(rot < m_lowerAngLimit)
+ if (rot < m_lowerAngLimit)
{
m_angDepth = rot - m_lowerAngLimit;
m_solveAngLim = true;
- }
- else if(rot > m_upperAngLimit)
+ }
+ else if (rot > m_upperAngLimit)
{
m_angDepth = rot - m_upperAngLimit;
m_solveAngLim = true;
@@ -255,8 +231,6 @@ btVector3 btSliderConstraint::getAncorInA(void)
return ancorInA;
}
-
-
btVector3 btSliderConstraint::getAncorInB(void)
{
btVector3 ancorInB;
@@ -264,17 +238,16 @@ btVector3 btSliderConstraint::getAncorInB(void)
return ancorInB;
}
-
-void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& transA,const btTransform& transB, const btVector3& linVelA,const btVector3& linVelB, btScalar rbAinvMass,btScalar rbBinvMass )
+void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, btScalar rbAinvMass, btScalar rbBinvMass)
{
const btTransform& trA = getCalculatedTransformA();
const btTransform& trB = getCalculatedTransformB();
-
+
btAssert(!m_useSolveConstraintObsolete);
int i, s = info->rowskip;
-
+
btScalar signFact = m_useLinearReferenceFrameA ? btScalar(1.0f) : btScalar(-1.0f);
-
+
// difference between frames in WCS
btVector3 ofs = trB.getOrigin() - trA.getOrigin();
// now get weight factors depending on masses
@@ -283,11 +256,11 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra
bool hasStaticBody = (miA < SIMD_EPSILON) || (miB < SIMD_EPSILON);
btScalar miS = miA + miB;
btScalar factA, factB;
- if(miS > btScalar(0.f))
+ if (miS > btScalar(0.f))
{
factA = miB / miS;
}
- else
+ else
{
factA = btScalar(0.5f);
}
@@ -295,17 +268,17 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra
btVector3 ax1, p, q;
btVector3 ax1A = trA.getBasis().getColumn(0);
btVector3 ax1B = trB.getBasis().getColumn(0);
- if(m_useOffsetForConstraintFrame)
+ if (m_useOffsetForConstraintFrame)
{
// get the desired direction of slider axis
// as weighted sum of X-orthos of frameA and frameB in WCS
ax1 = ax1A * factA + ax1B * factB;
ax1.normalize();
// construct two orthos to slider axis
- btPlaneSpace1 (ax1, p, q);
+ btPlaneSpace1(ax1, p, q);
}
else
- { // old way - use frameA
+ { // old way - use frameA
ax1 = trA.getBasis().getColumn(0);
// get 2 orthos to slider axis (Y, Z)
p = trA.getBasis().getColumn(1);
@@ -322,16 +295,16 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra
info->m_J1angularAxis[0] = p[0];
info->m_J1angularAxis[1] = p[1];
info->m_J1angularAxis[2] = p[2];
- info->m_J1angularAxis[s+0] = q[0];
- info->m_J1angularAxis[s+1] = q[1];
- info->m_J1angularAxis[s+2] = q[2];
+ info->m_J1angularAxis[s + 0] = q[0];
+ info->m_J1angularAxis[s + 1] = q[1];
+ info->m_J1angularAxis[s + 2] = q[2];
info->m_J2angularAxis[0] = -p[0];
info->m_J2angularAxis[1] = -p[1];
info->m_J2angularAxis[2] = -p[2];
- info->m_J2angularAxis[s+0] = -q[0];
- info->m_J2angularAxis[s+1] = -q[1];
- info->m_J2angularAxis[s+2] = -q[2];
+ info->m_J2angularAxis[s + 0] = -q[0];
+ info->m_J2angularAxis[s + 1] = -q[1];
+ info->m_J2angularAxis[s + 2] = -q[2];
// compute the right hand side of the constraint equation. set relative
// body velocities along p and q to bring the slider back into alignment.
// if ax1A,ax1B are the unit length slider axes as computed from bodyA and
@@ -347,25 +320,25 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra
// 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.
-// btScalar k = info->fps * info->erp * getSoftnessOrthoAng();
+ // btScalar k = info->fps * info->erp * getSoftnessOrthoAng();
btScalar currERP = (m_flags & BT_SLIDER_FLAGS_ERP_ORTANG) ? m_softnessOrthoAng : m_softnessOrthoAng * info->erp;
btScalar k = info->fps * currERP;
btVector3 u = ax1A.cross(ax1B);
info->m_constraintError[0] = k * u.dot(p);
info->m_constraintError[s] = k * u.dot(q);
- if(m_flags & BT_SLIDER_FLAGS_CFM_ORTANG)
+ if (m_flags & BT_SLIDER_FLAGS_CFM_ORTANG)
{
info->cfm[0] = m_cfmOrthoAng;
info->cfm[s] = m_cfmOrthoAng;
}
- int nrow = 1; // last filled row
+ int nrow = 1; // last filled row
int srow;
btScalar limit_err;
int limit;
- // next two rows.
+ // next two rows.
// we want: velA + wA x relA == velB + wB x relB ... but this would
// result in three equations, so we project along two orthos to the slider axis
@@ -375,8 +348,8 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra
int s2 = nrow * s;
nrow++;
int s3 = nrow * s;
- btVector3 tmpA(0,0,0), tmpB(0,0,0), relA(0,0,0), relB(0,0,0), c(0,0,0);
- if(m_useOffsetForConstraintFrame)
+ btVector3 tmpA(0, 0, 0), tmpB(0, 0, 0), relA(0, 0, 0), relB(0, 0, 0), c(0, 0, 0);
+ if (m_useOffsetForConstraintFrame)
{
// get vector from bodyB to frameB in WCS
relB = trB.getOrigin() - bodyB_trans.getOrigin();
@@ -398,7 +371,7 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra
// now choose average ortho to slider axis
p = orthoB * factA + orthoA * factB;
btScalar len2 = p.length2();
- if(len2 > SIMD_EPSILON)
+ if (len2 > SIMD_EPSILON)
{
p /= btSqrt(len2);
}
@@ -411,38 +384,38 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra
// fill two rows
tmpA = relA.cross(p);
tmpB = relB.cross(p);
- for (i=0; i<3; i++) info->m_J1angularAxis[s2+i] = tmpA[i];
- for (i=0; i<3; i++) info->m_J2angularAxis[s2+i] = -tmpB[i];
+ for (i = 0; i < 3; i++) info->m_J1angularAxis[s2 + i] = tmpA[i];
+ for (i = 0; i < 3; i++) info->m_J2angularAxis[s2 + i] = -tmpB[i];
tmpA = relA.cross(q);
tmpB = relB.cross(q);
- if(hasStaticBody && getSolveAngLimit())
- { // to make constraint between static and dynamic objects more rigid
+ if (hasStaticBody && getSolveAngLimit())
+ { // to make constraint between static and dynamic objects more rigid
// remove wA (or wB) from equation if angular limit is hit
tmpB *= factB;
tmpA *= factA;
}
- for (i=0; i<3; i++) info->m_J1angularAxis[s3+i] = tmpA[i];
- for (i=0; i<3; i++) info->m_J2angularAxis[s3+i] = -tmpB[i];
- for (i=0; i<3; i++) info->m_J1linearAxis[s2+i] = p[i];
- for (i=0; i<3; i++) info->m_J1linearAxis[s3+i] = q[i];
- for (i=0; i<3; i++) info->m_J2linearAxis[s2+i] = -p[i];
- for (i=0; i<3; i++) info->m_J2linearAxis[s3+i] = -q[i];
+ for (i = 0; i < 3; i++) info->m_J1angularAxis[s3 + i] = tmpA[i];
+ for (i = 0; i < 3; i++) info->m_J2angularAxis[s3 + i] = -tmpB[i];
+ for (i = 0; i < 3; i++) info->m_J1linearAxis[s2 + i] = p[i];
+ for (i = 0; i < 3; i++) info->m_J1linearAxis[s3 + i] = q[i];
+ for (i = 0; i < 3; i++) info->m_J2linearAxis[s2 + i] = -p[i];
+ for (i = 0; i < 3; i++) info->m_J2linearAxis[s3 + i] = -q[i];
}
else
- { // old way - maybe incorrect if bodies are not on the slider axis
+ { // old way - maybe incorrect if bodies are not on the slider axis
// see discussion "Bug in slider constraint" http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?f=9&t=4024&start=0
c = bodyB_trans.getOrigin() - bodyA_trans.getOrigin();
btVector3 tmp = c.cross(p);
- for (i=0; i<3; i++) info->m_J1angularAxis[s2+i] = factA*tmp[i];
- for (i=0; i<3; i++) info->m_J2angularAxis[s2+i] = factB*tmp[i];
+ for (i = 0; i < 3; i++) info->m_J1angularAxis[s2 + i] = factA * tmp[i];
+ for (i = 0; i < 3; i++) info->m_J2angularAxis[s2 + i] = factB * tmp[i];
tmp = c.cross(q);
- for (i=0; i<3; i++) info->m_J1angularAxis[s3+i] = factA*tmp[i];
- for (i=0; i<3; i++) info->m_J2angularAxis[s3+i] = factB*tmp[i];
+ for (i = 0; i < 3; i++) info->m_J1angularAxis[s3 + i] = factA * tmp[i];
+ for (i = 0; i < 3; i++) info->m_J2angularAxis[s3 + i] = factB * tmp[i];
- for (i=0; i<3; i++) info->m_J1linearAxis[s2+i] = p[i];
- for (i=0; i<3; i++) info->m_J1linearAxis[s3+i] = q[i];
- for (i=0; i<3; i++) info->m_J2linearAxis[s2+i] = -p[i];
- for (i=0; i<3; i++) info->m_J2linearAxis[s3+i] = -q[i];
+ for (i = 0; i < 3; i++) info->m_J1linearAxis[s2 + i] = p[i];
+ for (i = 0; i < 3; i++) info->m_J1linearAxis[s3 + i] = q[i];
+ for (i = 0; i < 3; i++) info->m_J2linearAxis[s2 + i] = -p[i];
+ for (i = 0; i < 3; i++) info->m_J2linearAxis[s3 + i] = -q[i];
}
// compute two elements of right hand side
@@ -454,19 +427,18 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra
info->m_constraintError[s2] = rhs;
rhs = k * q.dot(ofs);
info->m_constraintError[s3] = rhs;
- if(m_flags & BT_SLIDER_FLAGS_CFM_ORTLIN)
+ if (m_flags & BT_SLIDER_FLAGS_CFM_ORTLIN)
{
info->cfm[s2] = m_cfmOrthoLin;
info->cfm[s3] = m_cfmOrthoLin;
}
-
// check linear limits
limit_err = btScalar(0.0);
limit = 0;
- if(getSolveLinLimit())
+ if (getSolveLinLimit())
{
- limit_err = getLinDepth() * signFact;
+ limit_err = getLinDepth() * signFact;
limit = (limit_err > btScalar(0.0)) ? 2 : 1;
}
bool powered = getPoweredLinMotor();
@@ -475,12 +447,12 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra
{
nrow++;
srow = nrow * info->rowskip;
- info->m_J1linearAxis[srow+0] = ax1[0];
- info->m_J1linearAxis[srow+1] = ax1[1];
- info->m_J1linearAxis[srow+2] = ax1[2];
- info->m_J2linearAxis[srow+0] = -ax1[0];
- info->m_J2linearAxis[srow+1] = -ax1[1];
- info->m_J2linearAxis[srow+2] = -ax1[2];
+ info->m_J1linearAxis[srow + 0] = ax1[0];
+ info->m_J1linearAxis[srow + 1] = ax1[1];
+ info->m_J1linearAxis[srow + 2] = ax1[2];
+ info->m_J2linearAxis[srow + 0] = -ax1[0];
+ info->m_J2linearAxis[srow + 1] = -ax1[1];
+ info->m_J2linearAxis[srow + 2] = -ax1[2];
// linear torque decoupling step:
//
// we have to be careful that the linear constraint forces (+/- ax1) applied to the two bodies
@@ -488,36 +460,36 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra
// constraint force is applied at must lie along the same ax1 axis.
// a torque couple will result in limited slider-jointed free
// bodies from gaining angular momentum.
- if(m_useOffsetForConstraintFrame)
+ if (m_useOffsetForConstraintFrame)
{
// this is needed only when bodyA and bodyB are both dynamic.
- if(!hasStaticBody)
+ if (!hasStaticBody)
{
tmpA = relA.cross(ax1);
tmpB = relB.cross(ax1);
- info->m_J1angularAxis[srow+0] = tmpA[0];
- info->m_J1angularAxis[srow+1] = tmpA[1];
- info->m_J1angularAxis[srow+2] = tmpA[2];
- info->m_J2angularAxis[srow+0] = -tmpB[0];
- info->m_J2angularAxis[srow+1] = -tmpB[1];
- info->m_J2angularAxis[srow+2] = -tmpB[2];
+ info->m_J1angularAxis[srow + 0] = tmpA[0];
+ info->m_J1angularAxis[srow + 1] = tmpA[1];
+ info->m_J1angularAxis[srow + 2] = tmpA[2];
+ info->m_J2angularAxis[srow + 0] = -tmpB[0];
+ info->m_J2angularAxis[srow + 1] = -tmpB[1];
+ info->m_J2angularAxis[srow + 2] = -tmpB[2];
}
}
else
- { // The old way. May be incorrect if bodies are not on the slider axis
- btVector3 ltd; // Linear Torque Decoupling vector (a torque)
+ { // The old way. May be incorrect if bodies are not on the slider axis
+ btVector3 ltd; // Linear Torque Decoupling vector (a torque)
ltd = c.cross(ax1);
- info->m_J1angularAxis[srow+0] = factA*ltd[0];
- info->m_J1angularAxis[srow+1] = factA*ltd[1];
- info->m_J1angularAxis[srow+2] = factA*ltd[2];
- info->m_J2angularAxis[srow+0] = factB*ltd[0];
- info->m_J2angularAxis[srow+1] = factB*ltd[1];
- info->m_J2angularAxis[srow+2] = factB*ltd[2];
+ info->m_J1angularAxis[srow + 0] = factA * ltd[0];
+ info->m_J1angularAxis[srow + 1] = factA * ltd[1];
+ info->m_J1angularAxis[srow + 2] = factA * ltd[2];
+ info->m_J2angularAxis[srow + 0] = factB * ltd[0];
+ info->m_J2angularAxis[srow + 1] = factB * ltd[1];
+ info->m_J2angularAxis[srow + 2] = factB * ltd[2];
}
// right-hand part
btScalar lostop = getLowerLinLimit();
btScalar histop = getUpperLinLimit();
- if(limit && (lostop == histop))
+ if (limit && (lostop == histop))
{ // the joint motor is ineffective
powered = false;
}
@@ -525,9 +497,9 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra
info->m_lowerLimit[srow] = 0.;
info->m_upperLimit[srow] = 0.;
currERP = (m_flags & BT_SLIDER_FLAGS_ERP_LIMLIN) ? m_softnessLimLin : info->erp;
- if(powered)
+ if (powered)
{
- if(m_flags & BT_SLIDER_FLAGS_CFM_DIRLIN)
+ if (m_flags & BT_SLIDER_FLAGS_CFM_DIRLIN)
{
info->cfm[srow] = m_cfmDirLin;
}
@@ -537,41 +509,41 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra
info->m_lowerLimit[srow] += -getMaxLinMotorForce() / info->fps;
info->m_upperLimit[srow] += getMaxLinMotorForce() / info->fps;
}
- if(limit)
+ if (limit)
{
k = info->fps * currERP;
info->m_constraintError[srow] += k * limit_err;
- if(m_flags & BT_SLIDER_FLAGS_CFM_LIMLIN)
+ if (m_flags & BT_SLIDER_FLAGS_CFM_LIMLIN)
{
info->cfm[srow] = m_cfmLimLin;
}
- if(lostop == histop)
- { // limited low and high simultaneously
+ if (lostop == histop)
+ { // limited low and high simultaneously
info->m_lowerLimit[srow] = -SIMD_INFINITY;
info->m_upperLimit[srow] = SIMD_INFINITY;
}
- else if(limit == 1)
- { // low limit
+ else if (limit == 1)
+ { // low limit
info->m_lowerLimit[srow] = -SIMD_INFINITY;
info->m_upperLimit[srow] = 0;
}
- else
- { // high limit
+ else
+ { // high limit
info->m_lowerLimit[srow] = 0;
info->m_upperLimit[srow] = SIMD_INFINITY;
}
// bounce (we'll use slider parameter abs(1.0 - m_dampingLimLin) for that)
btScalar bounce = btFabs(btScalar(1.0) - getDampingLimLin());
- if(bounce > btScalar(0.0))
+ if (bounce > btScalar(0.0))
{
btScalar vel = linVelA.dot(ax1);
vel -= linVelB.dot(ax1);
vel *= signFact;
// 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)
+ if (limit == 1)
+ { // low limit
+ if (vel < 0)
{
btScalar newc = -bounce * vel;
if (newc > info->m_constraintError[srow])
@@ -581,11 +553,11 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra
}
}
else
- { // high limit - all those computations are reversed
- if(vel > 0)
+ { // high limit - all those computations are reversed
+ if (vel > 0)
{
btScalar newc = -bounce * vel;
- if(newc < info->m_constraintError[srow])
+ if (newc < info->m_constraintError[srow])
{
info->m_constraintError[srow] = newc;
}
@@ -593,40 +565,40 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra
}
}
info->m_constraintError[srow] *= getSoftnessLimLin();
- } // if(limit)
- } // if linear limit
+ } // if(limit)
+ } // if linear limit
// check angular limits
limit_err = btScalar(0.0);
limit = 0;
- if(getSolveAngLimit())
+ if (getSolveAngLimit())
{
limit_err = getAngDepth();
limit = (limit_err > btScalar(0.0)) ? 1 : 2;
}
// if the slider has joint limits, add in the extra row
powered = getPoweredAngMotor();
- if(limit || powered)
+ if (limit || powered)
{
nrow++;
srow = nrow * info->rowskip;
- info->m_J1angularAxis[srow+0] = ax1[0];
- info->m_J1angularAxis[srow+1] = ax1[1];
- info->m_J1angularAxis[srow+2] = ax1[2];
+ info->m_J1angularAxis[srow + 0] = ax1[0];
+ info->m_J1angularAxis[srow + 1] = ax1[1];
+ info->m_J1angularAxis[srow + 2] = ax1[2];
- info->m_J2angularAxis[srow+0] = -ax1[0];
- info->m_J2angularAxis[srow+1] = -ax1[1];
- info->m_J2angularAxis[srow+2] = -ax1[2];
+ info->m_J2angularAxis[srow + 0] = -ax1[0];
+ info->m_J2angularAxis[srow + 1] = -ax1[1];
+ info->m_J2angularAxis[srow + 2] = -ax1[2];
btScalar lostop = getLowerAngLimit();
btScalar histop = getUpperAngLimit();
- if(limit && (lostop == histop))
+ if (limit && (lostop == histop))
{ // the joint motor is ineffective
powered = false;
}
currERP = (m_flags & BT_SLIDER_FLAGS_ERP_LIMANG) ? m_softnessLimAng : info->erp;
- if(powered)
+ if (powered)
{
- if(m_flags & BT_SLIDER_FLAGS_CFM_DIRANG)
+ if (m_flags & BT_SLIDER_FLAGS_CFM_DIRANG)
{
info->cfm[srow] = m_cfmDirAng;
}
@@ -635,55 +607,55 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra
info->m_lowerLimit[srow] = -getMaxAngMotorForce() / info->fps;
info->m_upperLimit[srow] = getMaxAngMotorForce() / info->fps;
}
- if(limit)
+ if (limit)
{
k = info->fps * currERP;
info->m_constraintError[srow] += k * limit_err;
- if(m_flags & BT_SLIDER_FLAGS_CFM_LIMANG)
+ if (m_flags & BT_SLIDER_FLAGS_CFM_LIMANG)
{
info->cfm[srow] = m_cfmLimAng;
}
- if(lostop == histop)
+ if (lostop == histop)
{
// limited low and high simultaneously
info->m_lowerLimit[srow] = -SIMD_INFINITY;
info->m_upperLimit[srow] = SIMD_INFINITY;
}
- else if(limit == 1)
- { // low limit
+ else if (limit == 1)
+ { // low limit
info->m_lowerLimit[srow] = 0;
info->m_upperLimit[srow] = SIMD_INFINITY;
}
- else
- { // high limit
+ else
+ { // high limit
info->m_lowerLimit[srow] = -SIMD_INFINITY;
info->m_upperLimit[srow] = 0;
}
// bounce (we'll use slider parameter abs(1.0 - m_dampingLimAng) for that)
btScalar bounce = btFabs(btScalar(1.0) - getDampingLimAng());
- if(bounce > btScalar(0.0))
+ if (bounce > btScalar(0.0))
{
btScalar vel = m_rbA.getAngularVelocity().dot(ax1);
vel -= m_rbB.getAngularVelocity().dot(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)
+ if (limit == 1)
+ { // low limit
+ if (vel < 0)
{
btScalar newc = -bounce * vel;
- if(newc > info->m_constraintError[srow])
+ if (newc > info->m_constraintError[srow])
{
info->m_constraintError[srow] = newc;
}
}
}
else
- { // high limit - all those computations are reversed
- if(vel > 0)
+ { // high limit - all those computations are reversed
+ if (vel > 0)
{
btScalar newc = -bounce * vel;
- if(newc < info->m_constraintError[srow])
+ if (newc < info->m_constraintError[srow])
{
info->m_constraintError[srow] = newc;
}
@@ -691,165 +663,161 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra
}
}
info->m_constraintError[srow] *= getSoftnessLimAng();
- } // if(limit)
- } // if angular limit or powered
+ } // if(limit)
+ } // if angular limit or powered
}
-
-///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
///If no axis is provided, it uses the default axis for this constraint.
void btSliderConstraint::setParam(int num, btScalar value, int axis)
{
- switch(num)
+ switch (num)
{
- case BT_CONSTRAINT_STOP_ERP :
- if(axis < 1)
- {
- m_softnessLimLin = value;
- m_flags |= BT_SLIDER_FLAGS_ERP_LIMLIN;
- }
- else if(axis < 3)
- {
- m_softnessOrthoLin = value;
- m_flags |= BT_SLIDER_FLAGS_ERP_ORTLIN;
- }
- else if(axis == 3)
- {
- m_softnessLimAng = value;
- m_flags |= BT_SLIDER_FLAGS_ERP_LIMANG;
- }
- else if(axis < 6)
- {
- m_softnessOrthoAng = value;
- m_flags |= BT_SLIDER_FLAGS_ERP_ORTANG;
- }
- else
- {
- btAssertConstrParams(0);
- }
- break;
- case BT_CONSTRAINT_CFM :
- if(axis < 1)
- {
- m_cfmDirLin = value;
- m_flags |= BT_SLIDER_FLAGS_CFM_DIRLIN;
- }
- else if(axis == 3)
- {
- m_cfmDirAng = value;
- m_flags |= BT_SLIDER_FLAGS_CFM_DIRANG;
- }
- else
- {
- btAssertConstrParams(0);
- }
- break;
- case BT_CONSTRAINT_STOP_CFM :
- if(axis < 1)
- {
- m_cfmLimLin = value;
- m_flags |= BT_SLIDER_FLAGS_CFM_LIMLIN;
- }
- else if(axis < 3)
- {
- m_cfmOrthoLin = value;
- m_flags |= BT_SLIDER_FLAGS_CFM_ORTLIN;
- }
- else if(axis == 3)
- {
- m_cfmLimAng = value;
- m_flags |= BT_SLIDER_FLAGS_CFM_LIMANG;
- }
- else if(axis < 6)
- {
- m_cfmOrthoAng = value;
- m_flags |= BT_SLIDER_FLAGS_CFM_ORTANG;
- }
- else
- {
- btAssertConstrParams(0);
- }
- break;
+ case BT_CONSTRAINT_STOP_ERP:
+ if (axis < 1)
+ {
+ m_softnessLimLin = value;
+ m_flags |= BT_SLIDER_FLAGS_ERP_LIMLIN;
+ }
+ else if (axis < 3)
+ {
+ m_softnessOrthoLin = value;
+ m_flags |= BT_SLIDER_FLAGS_ERP_ORTLIN;
+ }
+ else if (axis == 3)
+ {
+ m_softnessLimAng = value;
+ m_flags |= BT_SLIDER_FLAGS_ERP_LIMANG;
+ }
+ else if (axis < 6)
+ {
+ m_softnessOrthoAng = value;
+ m_flags |= BT_SLIDER_FLAGS_ERP_ORTANG;
+ }
+ else
+ {
+ btAssertConstrParams(0);
+ }
+ break;
+ case BT_CONSTRAINT_CFM:
+ if (axis < 1)
+ {
+ m_cfmDirLin = value;
+ m_flags |= BT_SLIDER_FLAGS_CFM_DIRLIN;
+ }
+ else if (axis == 3)
+ {
+ m_cfmDirAng = value;
+ m_flags |= BT_SLIDER_FLAGS_CFM_DIRANG;
+ }
+ else
+ {
+ btAssertConstrParams(0);
+ }
+ break;
+ case BT_CONSTRAINT_STOP_CFM:
+ if (axis < 1)
+ {
+ m_cfmLimLin = value;
+ m_flags |= BT_SLIDER_FLAGS_CFM_LIMLIN;
+ }
+ else if (axis < 3)
+ {
+ m_cfmOrthoLin = value;
+ m_flags |= BT_SLIDER_FLAGS_CFM_ORTLIN;
+ }
+ else if (axis == 3)
+ {
+ m_cfmLimAng = value;
+ m_flags |= BT_SLIDER_FLAGS_CFM_LIMANG;
+ }
+ else if (axis < 6)
+ {
+ m_cfmOrthoAng = value;
+ m_flags |= BT_SLIDER_FLAGS_CFM_ORTANG;
+ }
+ else
+ {
+ btAssertConstrParams(0);
+ }
+ break;
}
}
///return the local value of parameter
-btScalar btSliderConstraint::getParam(int num, int axis) const
+btScalar btSliderConstraint::getParam(int num, int axis) const
{
btScalar retVal(SIMD_INFINITY);
- switch(num)
+ switch (num)
{
- case BT_CONSTRAINT_STOP_ERP :
- if(axis < 1)
- {
- btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_LIMLIN);
- retVal = m_softnessLimLin;
- }
- else if(axis < 3)
- {
- btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_ORTLIN);
- retVal = m_softnessOrthoLin;
- }
- else if(axis == 3)
- {
- btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_LIMANG);
- retVal = m_softnessLimAng;
- }
- else if(axis < 6)
- {
- btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_ORTANG);
- retVal = m_softnessOrthoAng;
- }
- else
- {
- btAssertConstrParams(0);
- }
- break;
- case BT_CONSTRAINT_CFM :
- if(axis < 1)
- {
- btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_DIRLIN);
- retVal = m_cfmDirLin;
- }
- else if(axis == 3)
- {
- btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_DIRANG);
- retVal = m_cfmDirAng;
- }
- else
- {
- btAssertConstrParams(0);
- }
- break;
- case BT_CONSTRAINT_STOP_CFM :
- if(axis < 1)
- {
- btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_LIMLIN);
- retVal = m_cfmLimLin;
- }
- else if(axis < 3)
- {
- btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_ORTLIN);
- retVal = m_cfmOrthoLin;
- }
- else if(axis == 3)
- {
- btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_LIMANG);
- retVal = m_cfmLimAng;
- }
- else if(axis < 6)
- {
- btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_ORTANG);
- retVal = m_cfmOrthoAng;
- }
- else
- {
- btAssertConstrParams(0);
- }
- break;
+ case BT_CONSTRAINT_STOP_ERP:
+ if (axis < 1)
+ {
+ btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_LIMLIN);
+ retVal = m_softnessLimLin;
+ }
+ else if (axis < 3)
+ {
+ btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_ORTLIN);
+ retVal = m_softnessOrthoLin;
+ }
+ else if (axis == 3)
+ {
+ btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_LIMANG);
+ retVal = m_softnessLimAng;
+ }
+ else if (axis < 6)
+ {
+ btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_ORTANG);
+ retVal = m_softnessOrthoAng;
+ }
+ else
+ {
+ btAssertConstrParams(0);
+ }
+ break;
+ case BT_CONSTRAINT_CFM:
+ if (axis < 1)
+ {
+ btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_DIRLIN);
+ retVal = m_cfmDirLin;
+ }
+ else if (axis == 3)
+ {
+ btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_DIRANG);
+ retVal = m_cfmDirAng;
+ }
+ else
+ {
+ btAssertConstrParams(0);
+ }
+ break;
+ case BT_CONSTRAINT_STOP_CFM:
+ if (axis < 1)
+ {
+ btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_LIMLIN);
+ retVal = m_cfmLimLin;
+ }
+ else if (axis < 3)
+ {
+ btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_ORTLIN);
+ retVal = m_cfmOrthoLin;
+ }
+ else if (axis == 3)
+ {
+ btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_LIMANG);
+ retVal = m_cfmLimAng;
+ }
+ else if (axis < 6)
+ {
+ btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_ORTANG);
+ retVal = m_cfmOrthoAng;
+ }
+ else
+ {
+ btAssertConstrParams(0);
+ }
+ break;
}
return retVal;
}
-
-
-
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.h
index 1957f08a96..75ca34e978 100755
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.h
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.h
@@ -25,31 +25,26 @@ TODO:
#ifndef BT_SLIDER_CONSTRAINT_H
#define BT_SLIDER_CONSTRAINT_H
-#include "LinearMath/btScalar.h"//for BT_USE_DOUBLE_PRECISION
+#include "LinearMath/btScalar.h" //for BT_USE_DOUBLE_PRECISION
#ifdef BT_USE_DOUBLE_PRECISION
-#define btSliderConstraintData2 btSliderConstraintDoubleData
-#define btSliderConstraintDataName "btSliderConstraintDoubleData"
+#define btSliderConstraintData2 btSliderConstraintDoubleData
+#define btSliderConstraintDataName "btSliderConstraintDoubleData"
#else
-#define btSliderConstraintData2 btSliderConstraintData
-#define btSliderConstraintDataName "btSliderConstraintData"
-#endif //BT_USE_DOUBLE_PRECISION
+#define btSliderConstraintData2 btSliderConstraintData
+#define btSliderConstraintDataName "btSliderConstraintData"
+#endif //BT_USE_DOUBLE_PRECISION
#include "LinearMath/btVector3.h"
#include "btJacobianEntry.h"
#include "btTypedConstraint.h"
-
-
class btRigidBody;
-
-
-#define SLIDER_CONSTRAINT_DEF_SOFTNESS (btScalar(1.0))
-#define SLIDER_CONSTRAINT_DEF_DAMPING (btScalar(1.0))
-#define SLIDER_CONSTRAINT_DEF_RESTITUTION (btScalar(0.7))
-#define SLIDER_CONSTRAINT_DEF_CFM (btScalar(0.f))
-
+#define SLIDER_CONSTRAINT_DEF_SOFTNESS (btScalar(1.0))
+#define SLIDER_CONSTRAINT_DEF_DAMPING (btScalar(1.0))
+#define SLIDER_CONSTRAINT_DEF_RESTITUTION (btScalar(0.7))
+#define SLIDER_CONSTRAINT_DEF_CFM (btScalar(0.f))
enum btSliderFlags
{
@@ -67,15 +62,15 @@ enum btSliderFlags
BT_SLIDER_FLAGS_ERP_LIMANG = (1 << 11)
};
-
-ATTRIBUTE_ALIGNED16(class) btSliderConstraint : public btTypedConstraint
+ATTRIBUTE_ALIGNED16(class)
+btSliderConstraint : public btTypedConstraint
{
protected:
///for backwards compatibility during the transition to 'getInfo/getInfo2'
- bool m_useSolveConstraintObsolete;
- bool m_useOffsetForConstraintFrame;
- btTransform m_frameInA;
- btTransform m_frameInB;
+ bool m_useSolveConstraintObsolete;
+ bool m_useOffsetForConstraintFrame;
+ btTransform m_frameInA;
+ btTransform m_frameInB;
// use frameA fo define limits, if true
bool m_useLinearReferenceFrameA;
// linear limits
@@ -119,21 +114,21 @@ protected:
btScalar m_restitutionOrthoAng;
btScalar m_dampingOrthoAng;
btScalar m_cfmOrthoAng;
-
+
// for interlal use
bool m_solveLinLim;
bool m_solveAngLim;
int m_flags;
- btJacobianEntry m_jacLin[3];
- btScalar m_jacLinDiagABInv[3];
+ btJacobianEntry m_jacLin[3];
+ btScalar m_jacLinDiagABInv[3];
- btJacobianEntry m_jacAng[3];
+ btJacobianEntry m_jacAng[3];
btScalar m_timeStep;
- btTransform m_calculatedTransformA;
- btTransform m_calculatedTransformB;
+ btTransform m_calculatedTransformA;
+ btTransform m_calculatedTransformB;
btVector3 m_sliderAxis;
btVector3 m_realPivotAInW;
@@ -150,57 +145,57 @@ protected:
btScalar m_angDepth;
btScalar m_kAngle;
- bool m_poweredLinMotor;
- btScalar m_targetLinMotorVelocity;
- btScalar m_maxLinMotorForce;
- btScalar m_accumulatedLinMotorImpulse;
-
- bool m_poweredAngMotor;
- btScalar m_targetAngMotorVelocity;
- btScalar m_maxAngMotorForce;
- btScalar m_accumulatedAngMotorImpulse;
-
- //------------------------
+ bool m_poweredLinMotor;
+ btScalar m_targetLinMotorVelocity;
+ btScalar m_maxLinMotorForce;
+ btScalar m_accumulatedLinMotorImpulse;
+
+ bool m_poweredAngMotor;
+ btScalar m_targetAngMotorVelocity;
+ btScalar m_maxAngMotorForce;
+ btScalar m_accumulatedAngMotorImpulse;
+
+ //------------------------
void initParams();
+
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
-
+
// constructors
- btSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA);
- btSliderConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameA);
+ btSliderConstraint(btRigidBody & rbA, btRigidBody & rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA);
+ btSliderConstraint(btRigidBody & rbB, const btTransform& frameInB, bool useLinearReferenceFrameA);
// overrides
- virtual void getInfo1 (btConstraintInfo1* info);
+ virtual void getInfo1(btConstraintInfo1 * info);
- void getInfo1NonVirtual(btConstraintInfo1* info);
-
- virtual void getInfo2 (btConstraintInfo2* info);
+ void getInfo1NonVirtual(btConstraintInfo1 * info);
- void getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& transA, const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB, btScalar rbAinvMass,btScalar rbBinvMass);
+ virtual void getInfo2(btConstraintInfo2 * info);
+ void getInfo2NonVirtual(btConstraintInfo2 * info, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, btScalar rbAinvMass, btScalar rbBinvMass);
// access
- const btRigidBody& getRigidBodyA() const { return m_rbA; }
- const btRigidBody& getRigidBodyB() const { return m_rbB; }
- const btTransform & getCalculatedTransformA() const { return m_calculatedTransformA; }
- const btTransform & getCalculatedTransformB() const { return m_calculatedTransformB; }
- const btTransform & getFrameOffsetA() const { return m_frameInA; }
- const btTransform & getFrameOffsetB() const { return m_frameInB; }
- btTransform & getFrameOffsetA() { return m_frameInA; }
- btTransform & getFrameOffsetB() { return m_frameInB; }
- btScalar getLowerLinLimit() { return m_lowerLinLimit; }
- void setLowerLinLimit(btScalar lowerLimit) { m_lowerLinLimit = lowerLimit; }
- btScalar getUpperLinLimit() { return m_upperLinLimit; }
- void setUpperLinLimit(btScalar upperLimit) { m_upperLinLimit = upperLimit; }
- btScalar getLowerAngLimit() { return m_lowerAngLimit; }
- void setLowerAngLimit(btScalar lowerLimit) { m_lowerAngLimit = btNormalizeAngle(lowerLimit); }
- btScalar getUpperAngLimit() { return m_upperAngLimit; }
- void setUpperAngLimit(btScalar upperLimit) { m_upperAngLimit = btNormalizeAngle(upperLimit); }
+ const btRigidBody& getRigidBodyA() const { return m_rbA; }
+ const btRigidBody& getRigidBodyB() const { return m_rbB; }
+ const btTransform& getCalculatedTransformA() const { return m_calculatedTransformA; }
+ const btTransform& getCalculatedTransformB() const { return m_calculatedTransformB; }
+ const btTransform& getFrameOffsetA() const { return m_frameInA; }
+ const btTransform& getFrameOffsetB() const { return m_frameInB; }
+ btTransform& getFrameOffsetA() { return m_frameInA; }
+ btTransform& getFrameOffsetB() { return m_frameInB; }
+ btScalar getLowerLinLimit() { return m_lowerLinLimit; }
+ void setLowerLinLimit(btScalar lowerLimit) { m_lowerLinLimit = lowerLimit; }
+ btScalar getUpperLinLimit() { return m_upperLinLimit; }
+ void setUpperLinLimit(btScalar upperLimit) { m_upperLinLimit = upperLimit; }
+ btScalar getLowerAngLimit() { return m_lowerAngLimit; }
+ void setLowerAngLimit(btScalar lowerLimit) { m_lowerAngLimit = btNormalizeAngle(lowerLimit); }
+ btScalar getUpperAngLimit() { return m_upperAngLimit; }
+ void setUpperAngLimit(btScalar upperLimit) { m_upperAngLimit = btNormalizeAngle(upperLimit); }
bool getUseLinearReferenceFrameA() { return m_useLinearReferenceFrameA; }
btScalar getSoftnessDirLin() { return m_softnessDirLin; }
btScalar getRestitutionDirLin() { return m_restitutionDirLin; }
- btScalar getDampingDirLin() { return m_dampingDirLin ; }
+ btScalar getDampingDirLin() { return m_dampingDirLin; }
btScalar getSoftnessDirAng() { return m_softnessDirAng; }
btScalar getRestitutionDirAng() { return m_restitutionDirAng; }
btScalar getDampingDirAng() { return m_dampingDirAng; }
@@ -249,8 +244,6 @@ public:
btScalar getLinearPos() const { return m_linPos; }
btScalar getAngularPos() const { return m_angPos; }
-
-
// access for ODE solver
bool getSolveLinLimit() { return m_solveLinLim; }
@@ -258,9 +251,9 @@ public:
bool getSolveAngLimit() { return m_solveAngLim; }
btScalar getAngDepth() { return m_angDepth; }
// shared code used by ODE solver
- void calculateTransforms(const btTransform& transA,const btTransform& transB);
- void testLinLimits();
- void testAngLimits();
+ void calculateTransforms(const btTransform& transA, const btTransform& transB);
+ void testLinLimits();
+ void testAngLimits();
// access for PE Solver
btVector3 getAncorInA();
btVector3 getAncorInB();
@@ -268,84 +261,75 @@ public:
bool getUseFrameOffset() { return m_useOffsetForConstraintFrame; }
void setUseFrameOffset(bool frameOffsetOnOff) { m_useOffsetForConstraintFrame = frameOffsetOnOff; }
- void setFrames(const btTransform& frameA, const btTransform& frameB)
- {
- m_frameInA=frameA;
- m_frameInB=frameB;
- calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
+ void setFrames(const btTransform& frameA, const btTransform& frameB)
+ {
+ m_frameInA = frameA;
+ m_frameInB = frameB;
+ calculateTransforms(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
buildJacobian();
- }
-
+ }
- ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+ ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
///If no axis is provided, it uses the default axis for this constraint.
- virtual void setParam(int num, btScalar value, int axis = -1);
+ virtual void setParam(int num, btScalar value, int axis = -1);
///return the local value of parameter
- virtual btScalar getParam(int num, int axis = -1) const;
-
- virtual int getFlags() const
- {
+ virtual btScalar getParam(int num, int axis = -1) const;
+
+ virtual int getFlags() const
+ {
return m_flags;
}
- virtual int calculateSerializeBufferSize() const;
+ virtual int calculateSerializeBufferSize() const;
///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-
-
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
};
-
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-
struct btSliderConstraintData
{
- btTypedConstraintData m_typeConstraintData;
- btTransformFloatData m_rbAFrame; // constraint axii. Assumes z is hinge axis.
+ btTypedConstraintData m_typeConstraintData;
+ btTransformFloatData m_rbAFrame; // constraint axii. Assumes z is hinge axis.
btTransformFloatData m_rbBFrame;
-
- float m_linearUpperLimit;
- float m_linearLowerLimit;
- float m_angularUpperLimit;
- float m_angularLowerLimit;
+ float m_linearUpperLimit;
+ float m_linearLowerLimit;
- int m_useLinearReferenceFrameA;
- int m_useOffsetForConstraintFrame;
+ float m_angularUpperLimit;
+ float m_angularLowerLimit;
+ int m_useLinearReferenceFrameA;
+ int m_useOffsetForConstraintFrame;
};
-
struct btSliderConstraintDoubleData
{
- btTypedConstraintDoubleData m_typeConstraintData;
- btTransformDoubleData m_rbAFrame; // constraint axii. Assumes z is hinge axis.
+ btTypedConstraintDoubleData m_typeConstraintData;
+ btTransformDoubleData m_rbAFrame; // constraint axii. Assumes z is hinge axis.
btTransformDoubleData m_rbBFrame;
-
- double m_linearUpperLimit;
- double m_linearLowerLimit;
- double m_angularUpperLimit;
- double m_angularLowerLimit;
+ double m_linearUpperLimit;
+ double m_linearLowerLimit;
- int m_useLinearReferenceFrameA;
- int m_useOffsetForConstraintFrame;
+ double m_angularUpperLimit;
+ double m_angularLowerLimit;
+ int m_useLinearReferenceFrameA;
+ int m_useOffsetForConstraintFrame;
};
-SIMD_FORCE_INLINE int btSliderConstraint::calculateSerializeBufferSize() const
+SIMD_FORCE_INLINE int btSliderConstraint::calculateSerializeBufferSize() const
{
return sizeof(btSliderConstraintData2);
}
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
-SIMD_FORCE_INLINE const char* btSliderConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE const char* btSliderConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
{
-
- btSliderConstraintData2* sliderData = (btSliderConstraintData2*) dataBuffer;
- btTypedConstraint::serialize(&sliderData->m_typeConstraintData,serializer);
+ btSliderConstraintData2* sliderData = (btSliderConstraintData2*)dataBuffer;
+ btTypedConstraint::serialize(&sliderData->m_typeConstraintData, serializer);
m_frameInA.serialize(sliderData->m_rbAFrame);
m_frameInB.serialize(sliderData->m_rbBFrame);
@@ -362,7 +346,4 @@ SIMD_FORCE_INLINE const char* btSliderConstraint::serialize(void* dataBuffer, bt
return btSliderConstraintDataName;
}
-
-
-#endif //BT_SLIDER_CONSTRAINT_H
-
+#endif //BT_SLIDER_CONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp
index 0c7dbd668b..1ea20edcb2 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp
@@ -13,43 +13,38 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
-
#include "btSolve2LinearConstraint.h"
#include "BulletDynamics/Dynamics/btRigidBody.h"
#include "LinearMath/btVector3.h"
#include "btJacobianEntry.h"
-
void btSolve2LinearConstraint::resolveUnilateralPairConstraint(
- btRigidBody* body1,
- btRigidBody* body2,
-
- const btMatrix3x3& world2A,
- const btMatrix3x3& world2B,
-
- const btVector3& invInertiaADiag,
- const btScalar invMassA,
- const btVector3& linvelA,const btVector3& angvelA,
- const btVector3& rel_posA1,
- const btVector3& invInertiaBDiag,
- const btScalar invMassB,
- const btVector3& linvelB,const btVector3& angvelB,
- const btVector3& rel_posA2,
-
- btScalar depthA, const btVector3& normalA,
- const btVector3& rel_posB1,const btVector3& rel_posB2,
- btScalar depthB, const btVector3& normalB,
- btScalar& imp0,btScalar& imp1)
+ btRigidBody* body1,
+ btRigidBody* body2,
+
+ const btMatrix3x3& world2A,
+ const btMatrix3x3& world2B,
+
+ const btVector3& invInertiaADiag,
+ const btScalar invMassA,
+ const btVector3& linvelA, const btVector3& angvelA,
+ const btVector3& rel_posA1,
+ const btVector3& invInertiaBDiag,
+ const btScalar invMassB,
+ const btVector3& linvelB, const btVector3& angvelB,
+ const btVector3& rel_posA2,
+
+ btScalar depthA, const btVector3& normalA,
+ const btVector3& rel_posB1, const btVector3& rel_posB2,
+ btScalar depthB, const btVector3& normalB,
+ btScalar& imp0, btScalar& imp1)
{
(void)linvelA;
(void)linvelB;
(void)angvelB;
(void)angvelA;
-
-
imp0 = btScalar(0.);
imp1 = btScalar(0.);
@@ -59,86 +54,76 @@ void btSolve2LinearConstraint::resolveUnilateralPairConstraint(
btAssert(len < SIMD_EPSILON);
-
//this jacobian entry could be re-used for all iterations
- btJacobianEntry jacA(world2A,world2B,rel_posA1,rel_posA2,normalA,invInertiaADiag,invMassA,
- invInertiaBDiag,invMassB);
- btJacobianEntry jacB(world2A,world2B,rel_posB1,rel_posB2,normalB,invInertiaADiag,invMassA,
- invInertiaBDiag,invMassB);
-
+ btJacobianEntry jacA(world2A, world2B, rel_posA1, rel_posA2, normalA, invInertiaADiag, invMassA,
+ invInertiaBDiag, invMassB);
+ btJacobianEntry jacB(world2A, world2B, rel_posB1, rel_posB2, normalB, invInertiaADiag, invMassA,
+ invInertiaBDiag, invMassB);
+
//const btScalar vel0 = jacA.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB);
//const btScalar vel1 = jacB.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB);
- const btScalar vel0 = normalA.dot(body1->getVelocityInLocalPoint(rel_posA1)-body2->getVelocityInLocalPoint(rel_posA1));
- const btScalar vel1 = normalB.dot(body1->getVelocityInLocalPoint(rel_posB1)-body2->getVelocityInLocalPoint(rel_posB1));
+ const btScalar vel0 = normalA.dot(body1->getVelocityInLocalPoint(rel_posA1) - body2->getVelocityInLocalPoint(rel_posA1));
+ const btScalar vel1 = normalB.dot(body1->getVelocityInLocalPoint(rel_posB1) - body2->getVelocityInLocalPoint(rel_posB1));
-// btScalar penetrationImpulse = (depth*contactTau*timeCorrection) * massTerm;//jacDiagABInv
+ // btScalar penetrationImpulse = (depth*contactTau*timeCorrection) * massTerm;//jacDiagABInv
btScalar massTerm = btScalar(1.) / (invMassA + invMassB);
-
// calculate rhs (or error) terms
- const btScalar dv0 = depthA * m_tau * massTerm - vel0 * m_damping;
- const btScalar dv1 = depthB * m_tau * massTerm - vel1 * m_damping;
-
+ const btScalar dv0 = depthA * m_tau * massTerm - vel0 * m_damping;
+ const btScalar dv1 = depthB * m_tau * massTerm - vel1 * m_damping;
// dC/dv * dv = -C
-
+
// jacobian * impulse = -error
//
//impulse = jacobianInverse * -error
// inverting 2x2 symmetric system (offdiagonal are equal!)
- //
+ //
+ btScalar nonDiag = jacA.getNonDiagonal(jacB, invMassA, invMassB);
+ btScalar invDet = btScalar(1.0) / (jacA.getDiagonal() * jacB.getDiagonal() - nonDiag * nonDiag);
- btScalar nonDiag = jacA.getNonDiagonal(jacB,invMassA,invMassB);
- btScalar invDet = btScalar(1.0) / (jacA.getDiagonal() * jacB.getDiagonal() - nonDiag * nonDiag );
-
//imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet;
//imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet;
imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet;
- imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet;
+ imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * -nonDiag * invDet;
//[a b] [d -c]
//[c d] inverse = (1 / determinant) * [-b a] where determinant is (ad - bc)
//[jA nD] * [imp0] = [dv0]
//[nD jB] [imp1] [dv1]
-
}
-
-
void btSolve2LinearConstraint::resolveBilateralPairConstraint(
- btRigidBody* body1,
- btRigidBody* body2,
- const btMatrix3x3& world2A,
- const btMatrix3x3& world2B,
-
- const btVector3& invInertiaADiag,
- const btScalar invMassA,
- const btVector3& linvelA,const btVector3& angvelA,
- const btVector3& rel_posA1,
- const btVector3& invInertiaBDiag,
- const btScalar invMassB,
- const btVector3& linvelB,const btVector3& angvelB,
- const btVector3& rel_posA2,
-
- btScalar depthA, const btVector3& normalA,
- const btVector3& rel_posB1,const btVector3& rel_posB2,
- btScalar depthB, const btVector3& normalB,
- btScalar& imp0,btScalar& imp1)
+ btRigidBody* body1,
+ btRigidBody* body2,
+ const btMatrix3x3& world2A,
+ const btMatrix3x3& world2B,
+
+ const btVector3& invInertiaADiag,
+ const btScalar invMassA,
+ const btVector3& linvelA, const btVector3& angvelA,
+ const btVector3& rel_posA1,
+ const btVector3& invInertiaBDiag,
+ const btScalar invMassB,
+ const btVector3& linvelB, const btVector3& angvelB,
+ const btVector3& rel_posA2,
+
+ btScalar depthA, const btVector3& normalA,
+ const btVector3& rel_posB1, const btVector3& rel_posB2,
+ btScalar depthB, const btVector3& normalB,
+ btScalar& imp0, btScalar& imp1)
{
-
(void)linvelA;
(void)linvelB;
(void)angvelA;
(void)angvelB;
-
-
imp0 = btScalar(0.);
imp1 = btScalar(0.);
@@ -148,42 +133,40 @@ void btSolve2LinearConstraint::resolveBilateralPairConstraint(
btAssert(len < SIMD_EPSILON);
-
//this jacobian entry could be re-used for all iterations
- btJacobianEntry jacA(world2A,world2B,rel_posA1,rel_posA2,normalA,invInertiaADiag,invMassA,
- invInertiaBDiag,invMassB);
- btJacobianEntry jacB(world2A,world2B,rel_posB1,rel_posB2,normalB,invInertiaADiag,invMassA,
- invInertiaBDiag,invMassB);
-
+ btJacobianEntry jacA(world2A, world2B, rel_posA1, rel_posA2, normalA, invInertiaADiag, invMassA,
+ invInertiaBDiag, invMassB);
+ btJacobianEntry jacB(world2A, world2B, rel_posB1, rel_posB2, normalB, invInertiaADiag, invMassA,
+ invInertiaBDiag, invMassB);
+
//const btScalar vel0 = jacA.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB);
//const btScalar vel1 = jacB.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB);
- const btScalar vel0 = normalA.dot(body1->getVelocityInLocalPoint(rel_posA1)-body2->getVelocityInLocalPoint(rel_posA1));
- const btScalar vel1 = normalB.dot(body1->getVelocityInLocalPoint(rel_posB1)-body2->getVelocityInLocalPoint(rel_posB1));
+ const btScalar vel0 = normalA.dot(body1->getVelocityInLocalPoint(rel_posA1) - body2->getVelocityInLocalPoint(rel_posA1));
+ const btScalar vel1 = normalB.dot(body1->getVelocityInLocalPoint(rel_posB1) - body2->getVelocityInLocalPoint(rel_posB1));
// calculate rhs (or error) terms
- const btScalar dv0 = depthA * m_tau - vel0 * m_damping;
- const btScalar dv1 = depthB * m_tau - vel1 * m_damping;
+ const btScalar dv0 = depthA * m_tau - vel0 * m_damping;
+ const btScalar dv1 = depthB * m_tau - vel1 * m_damping;
// dC/dv * dv = -C
-
+
// jacobian * impulse = -error
//
//impulse = jacobianInverse * -error
// inverting 2x2 symmetric system (offdiagonal are equal!)
- //
+ //
+ btScalar nonDiag = jacA.getNonDiagonal(jacB, invMassA, invMassB);
+ btScalar invDet = btScalar(1.0) / (jacA.getDiagonal() * jacB.getDiagonal() - nonDiag * nonDiag);
- btScalar nonDiag = jacA.getNonDiagonal(jacB,invMassA,invMassB);
- btScalar invDet = btScalar(1.0) / (jacA.getDiagonal() * jacB.getDiagonal() - nonDiag * nonDiag );
-
//imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet;
//imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet;
imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet;
- imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet;
+ imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * -nonDiag * invDet;
//[a b] [d -c]
//[c d] inverse = (1 / determinant) * [-b a] where determinant is (ad - bc)
@@ -191,9 +174,9 @@ void btSolve2LinearConstraint::resolveBilateralPairConstraint(
//[jA nD] * [imp0] = [dv0]
//[nD jB] [imp1] [dv1]
- if ( imp0 > btScalar(0.0))
+ if (imp0 > btScalar(0.0))
{
- if ( imp1 > btScalar(0.0) )
+ if (imp1 > btScalar(0.0))
{
//both positive
}
@@ -203,9 +186,10 @@ void btSolve2LinearConstraint::resolveBilateralPairConstraint(
// now imp0>0 imp1<0
imp0 = dv0 / jacA.getDiagonal();
- if ( imp0 > btScalar(0.0) )
+ if (imp0 > btScalar(0.0))
{
- } else
+ }
+ else
{
imp0 = btScalar(0.);
}
@@ -216,24 +200,25 @@ void btSolve2LinearConstraint::resolveBilateralPairConstraint(
imp0 = btScalar(0.);
imp1 = dv1 / jacB.getDiagonal();
- if ( imp1 <= btScalar(0.0) )
+ if (imp1 <= btScalar(0.0))
{
imp1 = btScalar(0.);
// now imp0>0 imp1<0
imp0 = dv0 / jacA.getDiagonal();
- if ( imp0 > btScalar(0.0) )
+ if (imp0 > btScalar(0.0))
{
- } else
+ }
+ else
{
imp0 = btScalar(0.);
}
- } else
+ }
+ else
{
}
}
}
-
/*
void btSolve2LinearConstraint::resolveAngularConstraint( const btMatrix3x3& invInertiaAWS,
const btScalar invMassA,
@@ -252,4 +237,3 @@ void btSolve2LinearConstraint::resolveAngularConstraint( const btMatrix3x3& invI
}
*/
-
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h
index e8bfabf864..fca8ecec81 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h
@@ -19,20 +19,16 @@ subject to the following restrictions:
#include "LinearMath/btMatrix3x3.h"
#include "LinearMath/btVector3.h"
-
class btRigidBody;
-
-
/// constraint class used for lateral tyre friction.
-class btSolve2LinearConstraint
+class btSolve2LinearConstraint
{
- btScalar m_tau;
- btScalar m_damping;
+ btScalar m_tau;
+ btScalar m_damping;
public:
-
- btSolve2LinearConstraint(btScalar tau,btScalar damping)
+ btSolve2LinearConstraint(btScalar tau, btScalar damping)
{
m_tau = tau;
m_damping = damping;
@@ -40,52 +36,51 @@ public:
//
// solve unilateral constraint (equality, direct method)
//
- void resolveUnilateralPairConstraint(
- btRigidBody* body0,
+ void resolveUnilateralPairConstraint(
+ btRigidBody* body0,
btRigidBody* body1,
const btMatrix3x3& world2A,
- const btMatrix3x3& world2B,
-
- const btVector3& invInertiaADiag,
- const btScalar invMassA,
- const btVector3& linvelA,const btVector3& angvelA,
- const btVector3& rel_posA1,
- const btVector3& invInertiaBDiag,
- const btScalar invMassB,
- const btVector3& linvelB,const btVector3& angvelB,
- const btVector3& rel_posA2,
-
- btScalar depthA, const btVector3& normalA,
- const btVector3& rel_posB1,const btVector3& rel_posB2,
- btScalar depthB, const btVector3& normalB,
- btScalar& imp0,btScalar& imp1);
-
+ const btMatrix3x3& world2B,
+
+ const btVector3& invInertiaADiag,
+ const btScalar invMassA,
+ const btVector3& linvelA, const btVector3& angvelA,
+ const btVector3& rel_posA1,
+ const btVector3& invInertiaBDiag,
+ const btScalar invMassB,
+ const btVector3& linvelB, const btVector3& angvelB,
+ const btVector3& rel_posA2,
+
+ btScalar depthA, const btVector3& normalA,
+ const btVector3& rel_posB1, const btVector3& rel_posB2,
+ btScalar depthB, const btVector3& normalB,
+ btScalar& imp0, btScalar& imp1);
//
// solving 2x2 lcp problem (inequality, direct solution )
//
void resolveBilateralPairConstraint(
- btRigidBody* body0,
- btRigidBody* body1,
+ btRigidBody* body0,
+ btRigidBody* body1,
const btMatrix3x3& world2A,
- const btMatrix3x3& world2B,
-
- const btVector3& invInertiaADiag,
- const btScalar invMassA,
- const btVector3& linvelA,const btVector3& angvelA,
- const btVector3& rel_posA1,
- const btVector3& invInertiaBDiag,
- const btScalar invMassB,
- const btVector3& linvelB,const btVector3& angvelB,
- const btVector3& rel_posA2,
-
- btScalar depthA, const btVector3& normalA,
- const btVector3& rel_posB1,const btVector3& rel_posB2,
- btScalar depthB, const btVector3& normalB,
- btScalar& imp0,btScalar& imp1);
-
-/*
+ const btMatrix3x3& world2B,
+
+ const btVector3& invInertiaADiag,
+ const btScalar invMassA,
+ const btVector3& linvelA, const btVector3& angvelA,
+ const btVector3& rel_posA1,
+ const btVector3& invInertiaBDiag,
+ const btScalar invMassB,
+ const btVector3& linvelB, const btVector3& angvelB,
+ const btVector3& rel_posA2,
+
+ btScalar depthA, const btVector3& normalA,
+ const btVector3& rel_posB1, const btVector3& rel_posB2,
+ btScalar depthB, const btVector3& normalB,
+ btScalar& imp0, btScalar& imp1);
+
+ /*
void resolveAngularConstraint( const btMatrix3x3& invInertiaAWS,
const btScalar invMassA,
const btVector3& linvelA,const btVector3& angvelA,
@@ -101,7 +96,6 @@ public:
btScalar& imp0,btScalar& imp1);
*/
-
};
-#endif //BT_SOLVE_2LINEAR_CONSTRAINT_H
+#endif //BT_SOLVE_2LINEAR_CONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolverBody.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolverBody.h
index 27ccefe416..409aa8a08c 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolverBody.h
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolverBody.h
@@ -16,7 +16,7 @@ subject to the following restrictions:
#ifndef BT_SOLVER_BODY_H
#define BT_SOLVER_BODY_H
-class btRigidBody;
+class btRigidBody;
#include "LinearMath/btVector3.h"
#include "LinearMath/btMatrix3x3.h"
@@ -26,103 +26,99 @@ class btRigidBody;
///Until we get other contributions, only use SIMD on Windows, when using Visual Studio 2008 or later, and not double precision
#ifdef BT_USE_SSE
#define USE_SIMD 1
-#endif //
-
+#endif //
#ifdef USE_SIMD
-struct btSimdScalar
+struct btSimdScalar
{
- SIMD_FORCE_INLINE btSimdScalar()
+ SIMD_FORCE_INLINE btSimdScalar()
{
-
}
- SIMD_FORCE_INLINE btSimdScalar(float fl)
- :m_vec128 (_mm_set1_ps(fl))
+ SIMD_FORCE_INLINE btSimdScalar(float fl)
+ : m_vec128(_mm_set1_ps(fl))
{
}
- SIMD_FORCE_INLINE btSimdScalar(__m128 v128)
- :m_vec128(v128)
+ SIMD_FORCE_INLINE btSimdScalar(__m128 v128)
+ : m_vec128(v128)
{
}
- union
- {
- __m128 m_vec128;
- float m_floats[4];
- int m_ints[4];
- btScalar m_unusedPadding;
+ union {
+ __m128 m_vec128;
+ float m_floats[4];
+ int m_ints[4];
+ btScalar m_unusedPadding;
};
- SIMD_FORCE_INLINE __m128 get128()
+ SIMD_FORCE_INLINE __m128 get128()
{
return m_vec128;
}
- SIMD_FORCE_INLINE const __m128 get128() const
+ SIMD_FORCE_INLINE const __m128 get128() const
{
return m_vec128;
}
- SIMD_FORCE_INLINE void set128(__m128 v128)
+ SIMD_FORCE_INLINE void set128(__m128 v128)
{
m_vec128 = v128;
}
- SIMD_FORCE_INLINE operator __m128()
- {
- return m_vec128;
- }
- SIMD_FORCE_INLINE operator const __m128() const
- {
- return m_vec128;
+ SIMD_FORCE_INLINE operator __m128()
+ {
+ return m_vec128;
}
-
- SIMD_FORCE_INLINE operator float() const
- {
- return m_floats[0];
+ SIMD_FORCE_INLINE operator const __m128() const
+ {
+ return m_vec128;
}
+ SIMD_FORCE_INLINE operator float() const
+ {
+ return m_floats[0];
+ }
};
///@brief Return the elementwise product of two btSimdScalar
-SIMD_FORCE_INLINE btSimdScalar
-operator*(const btSimdScalar& v1, const btSimdScalar& v2)
+SIMD_FORCE_INLINE btSimdScalar
+operator*(const btSimdScalar& v1, const btSimdScalar& v2)
{
- return btSimdScalar(_mm_mul_ps(v1.get128(),v2.get128()));
+ return btSimdScalar(_mm_mul_ps(v1.get128(), v2.get128()));
}
///@brief Return the elementwise product of two btSimdScalar
-SIMD_FORCE_INLINE btSimdScalar
-operator+(const btSimdScalar& v1, const btSimdScalar& v2)
+SIMD_FORCE_INLINE btSimdScalar
+operator+(const btSimdScalar& v1, const btSimdScalar& v2)
{
- return btSimdScalar(_mm_add_ps(v1.get128(),v2.get128()));
+ return btSimdScalar(_mm_add_ps(v1.get128(), v2.get128()));
}
-
#else
#define btSimdScalar btScalar
#endif
///The btSolverBody is an internal datastructure for the constraint solver. Only necessary data is packed to increase cache coherence/performance.
-ATTRIBUTE_ALIGNED16 (struct) btSolverBody
+ATTRIBUTE_ALIGNED16(struct)
+btSolverBody
{
BT_DECLARE_ALIGNED_ALLOCATOR();
- btTransform m_worldTransform;
- btVector3 m_deltaLinearVelocity;
- btVector3 m_deltaAngularVelocity;
- btVector3 m_angularFactor;
- btVector3 m_linearFactor;
- btVector3 m_invMass;
- btVector3 m_pushVelocity;
- btVector3 m_turnVelocity;
- btVector3 m_linearVelocity;
- btVector3 m_angularVelocity;
- btVector3 m_externalForceImpulse;
- btVector3 m_externalTorqueImpulse;
-
- btRigidBody* m_originalBody;
- void setWorldTransform(const btTransform& worldTransform)
+ btTransform m_worldTransform;
+ btVector3 m_deltaLinearVelocity;
+ btVector3 m_deltaAngularVelocity;
+ btVector3 m_angularFactor;
+ btVector3 m_linearFactor;
+ btVector3 m_invMass;
+ btVector3 m_pushVelocity;
+ btVector3 m_turnVelocity;
+ btVector3 m_linearVelocity;
+ btVector3 m_angularVelocity;
+ btVector3 m_externalForceImpulse;
+ btVector3 m_externalTorqueImpulse;
+
+ btRigidBody* m_originalBody;
+ void setWorldTransform(const btTransform& worldTransform)
{
m_worldTransform = worldTransform;
}
@@ -131,56 +127,50 @@ ATTRIBUTE_ALIGNED16 (struct) btSolverBody
{
return m_worldTransform;
}
-
-
- SIMD_FORCE_INLINE void getVelocityInLocalPointNoDelta(const btVector3& rel_pos, btVector3& velocity ) const
+ SIMD_FORCE_INLINE void getVelocityInLocalPointNoDelta(const btVector3& rel_pos, btVector3& velocity) const
{
if (m_originalBody)
- velocity = m_linearVelocity + m_externalForceImpulse + (m_angularVelocity+m_externalTorqueImpulse).cross(rel_pos);
+ velocity = m_linearVelocity + m_externalForceImpulse + (m_angularVelocity + m_externalTorqueImpulse).cross(rel_pos);
else
- velocity.setValue(0,0,0);
+ velocity.setValue(0, 0, 0);
}
-
- SIMD_FORCE_INLINE void getVelocityInLocalPointObsolete(const btVector3& rel_pos, btVector3& velocity ) const
+ SIMD_FORCE_INLINE void getVelocityInLocalPointObsolete(const btVector3& rel_pos, btVector3& velocity) const
{
if (m_originalBody)
- velocity = m_linearVelocity+m_deltaLinearVelocity + (m_angularVelocity+m_deltaAngularVelocity).cross(rel_pos);
+ velocity = m_linearVelocity + m_deltaLinearVelocity + (m_angularVelocity + m_deltaAngularVelocity).cross(rel_pos);
else
- velocity.setValue(0,0,0);
+ velocity.setValue(0, 0, 0);
}
- SIMD_FORCE_INLINE void getAngularVelocity(btVector3& angVel) const
+ SIMD_FORCE_INLINE void getAngularVelocity(btVector3 & angVel) const
{
if (m_originalBody)
- angVel =m_angularVelocity+m_deltaAngularVelocity;
+ angVel = m_angularVelocity + m_deltaAngularVelocity;
else
- angVel.setValue(0,0,0);
+ angVel.setValue(0, 0, 0);
}
-
//Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position
- SIMD_FORCE_INLINE void applyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,const btScalar impulseMagnitude)
+ SIMD_FORCE_INLINE void applyImpulse(const btVector3& linearComponent, const btVector3& angularComponent, const btScalar impulseMagnitude)
{
if (m_originalBody)
{
- m_deltaLinearVelocity += linearComponent*impulseMagnitude*m_linearFactor;
- m_deltaAngularVelocity += angularComponent*(impulseMagnitude*m_angularFactor);
+ m_deltaLinearVelocity += linearComponent * impulseMagnitude * m_linearFactor;
+ m_deltaAngularVelocity += angularComponent * (impulseMagnitude * m_angularFactor);
}
}
- SIMD_FORCE_INLINE void internalApplyPushImpulse(const btVector3& linearComponent, const btVector3& angularComponent,btScalar impulseMagnitude)
+ SIMD_FORCE_INLINE void internalApplyPushImpulse(const btVector3& linearComponent, const btVector3& angularComponent, btScalar impulseMagnitude)
{
if (m_originalBody)
{
- m_pushVelocity += linearComponent*impulseMagnitude*m_linearFactor;
- m_turnVelocity += angularComponent*(impulseMagnitude*m_angularFactor);
+ m_pushVelocity += linearComponent * impulseMagnitude * m_linearFactor;
+ m_turnVelocity += angularComponent * (impulseMagnitude * m_angularFactor);
}
}
-
-
const btVector3& getDeltaLinearVelocity() const
{
return m_deltaLinearVelocity;
@@ -191,20 +181,19 @@ ATTRIBUTE_ALIGNED16 (struct) btSolverBody
return m_deltaAngularVelocity;
}
- const btVector3& getPushVelocity() const
+ const btVector3& getPushVelocity() const
{
return m_pushVelocity;
}
- const btVector3& getTurnVelocity() const
+ const btVector3& getTurnVelocity() const
{
return m_turnVelocity;
}
-
////////////////////////////////////////////////
///some internal methods, don't use them
-
+
btVector3& internalGetDeltaLinearVelocity()
{
return m_deltaLinearVelocity;
@@ -229,7 +218,7 @@ ATTRIBUTE_ALIGNED16 (struct) btSolverBody
{
m_invMass = invMass;
}
-
+
btVector3& internalGetPushVelocity()
{
return m_pushVelocity;
@@ -240,67 +229,57 @@ ATTRIBUTE_ALIGNED16 (struct) btSolverBody
return m_turnVelocity;
}
- SIMD_FORCE_INLINE void internalGetVelocityInLocalPointObsolete(const btVector3& rel_pos, btVector3& velocity ) const
+ SIMD_FORCE_INLINE void internalGetVelocityInLocalPointObsolete(const btVector3& rel_pos, btVector3& velocity) const
{
- velocity = m_linearVelocity+m_deltaLinearVelocity + (m_angularVelocity+m_deltaAngularVelocity).cross(rel_pos);
+ velocity = m_linearVelocity + m_deltaLinearVelocity + (m_angularVelocity + m_deltaAngularVelocity).cross(rel_pos);
}
- SIMD_FORCE_INLINE void internalGetAngularVelocity(btVector3& angVel) const
+ SIMD_FORCE_INLINE void internalGetAngularVelocity(btVector3 & angVel) const
{
- angVel = m_angularVelocity+m_deltaAngularVelocity;
+ angVel = m_angularVelocity + m_deltaAngularVelocity;
}
-
//Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position
- SIMD_FORCE_INLINE void internalApplyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,const btScalar impulseMagnitude)
+ SIMD_FORCE_INLINE void internalApplyImpulse(const btVector3& linearComponent, const btVector3& angularComponent, const btScalar impulseMagnitude)
{
if (m_originalBody)
{
- m_deltaLinearVelocity += linearComponent*impulseMagnitude*m_linearFactor;
- m_deltaAngularVelocity += angularComponent*(impulseMagnitude*m_angularFactor);
+ m_deltaLinearVelocity += linearComponent * impulseMagnitude * m_linearFactor;
+ m_deltaAngularVelocity += angularComponent * (impulseMagnitude * m_angularFactor);
}
}
-
-
-
- void writebackVelocity()
+ void writebackVelocity()
{
if (m_originalBody)
{
- m_linearVelocity +=m_deltaLinearVelocity;
+ m_linearVelocity += m_deltaLinearVelocity;
m_angularVelocity += m_deltaAngularVelocity;
-
+
//m_originalBody->setCompanionId(-1);
}
}
-
- void writebackVelocityAndTransform(btScalar timeStep, btScalar splitImpulseTurnErp)
+ void writebackVelocityAndTransform(btScalar timeStep, btScalar splitImpulseTurnErp)
{
- (void) timeStep;
+ (void)timeStep;
if (m_originalBody)
{
m_linearVelocity += m_deltaLinearVelocity;
m_angularVelocity += m_deltaAngularVelocity;
-
+
//correct the position/orientation based on push/turn recovery
btTransform newTransform;
- if (m_pushVelocity[0]!=0.f || m_pushVelocity[1]!=0 || m_pushVelocity[2]!=0 || m_turnVelocity[0]!=0.f || m_turnVelocity[1]!=0 || m_turnVelocity[2]!=0)
+ if (m_pushVelocity[0] != 0.f || m_pushVelocity[1] != 0 || m_pushVelocity[2] != 0 || m_turnVelocity[0] != 0.f || m_turnVelocity[1] != 0 || m_turnVelocity[2] != 0)
{
- // btQuaternion orn = m_worldTransform.getRotation();
- btTransformUtil::integrateTransform(m_worldTransform,m_pushVelocity,m_turnVelocity*splitImpulseTurnErp,timeStep,newTransform);
+ // btQuaternion orn = m_worldTransform.getRotation();
+ btTransformUtil::integrateTransform(m_worldTransform, m_pushVelocity, m_turnVelocity * splitImpulseTurnErp, timeStep, newTransform);
m_worldTransform = newTransform;
}
//m_worldTransform.setRotation(orn);
//m_originalBody->setCompanionId(-1);
}
}
-
-
-
};
-#endif //BT_SOLVER_BODY_H
-
-
+#endif //BT_SOLVER_BODY_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolverConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolverConstraint.h
index 5515e6b311..c7938df867 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolverConstraint.h
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolverConstraint.h
@@ -16,7 +16,7 @@ subject to the following restrictions:
#ifndef BT_SOLVER_CONSTRAINT_H
#define BT_SOLVER_CONSTRAINT_H
-class btRigidBody;
+class btRigidBody;
#include "LinearMath/btVector3.h"
#include "LinearMath/btMatrix3x3.h"
#include "btJacobianEntry.h"
@@ -25,56 +25,50 @@ class btRigidBody;
//#define NO_FRICTION_TANGENTIALS 1
#include "btSolverBody.h"
-
///1D constraint along a normal axis between bodyA and bodyB. It can be combined to solve contact and friction constraints.
-ATTRIBUTE_ALIGNED16 (struct) btSolverConstraint
+ATTRIBUTE_ALIGNED16(struct)
+btSolverConstraint
{
BT_DECLARE_ALIGNED_ALLOCATOR();
- btVector3 m_relpos1CrossNormal;
- btVector3 m_contactNormal1;
-
- btVector3 m_relpos2CrossNormal;
- btVector3 m_contactNormal2; //usually m_contactNormal2 == -m_contactNormal1, but not always
-
- btVector3 m_angularComponentA;
- btVector3 m_angularComponentB;
-
- mutable btSimdScalar m_appliedPushImpulse;
- mutable btSimdScalar m_appliedImpulse;
-
- btScalar m_friction;
- btScalar m_jacDiagABInv;
- btScalar m_rhs;
- btScalar m_cfm;
-
- btScalar m_lowerLimit;
- btScalar m_upperLimit;
- btScalar m_rhsPenetration;
- union
- {
- void* m_originalContactPoint;
- btScalar m_unusedPadding4;
- int m_numRowsForNonContactConstraint;
+ btVector3 m_relpos1CrossNormal;
+ btVector3 m_contactNormal1;
+
+ btVector3 m_relpos2CrossNormal;
+ btVector3 m_contactNormal2; //usually m_contactNormal2 == -m_contactNormal1, but not always
+
+ btVector3 m_angularComponentA;
+ btVector3 m_angularComponentB;
+
+ mutable btSimdScalar m_appliedPushImpulse;
+ mutable btSimdScalar m_appliedImpulse;
+
+ btScalar m_friction;
+ btScalar m_jacDiagABInv;
+ btScalar m_rhs;
+ btScalar m_cfm;
+
+ btScalar m_lowerLimit;
+ btScalar m_upperLimit;
+ btScalar m_rhsPenetration;
+ union {
+ void* m_originalContactPoint;
+ btScalar m_unusedPadding4;
+ int m_numRowsForNonContactConstraint;
};
- int m_overrideNumSolverIterations;
- int m_frictionIndex;
+ int m_overrideNumSolverIterations;
+ int m_frictionIndex;
int m_solverBodyIdA;
int m_solverBodyIdB;
-
- enum btSolverConstraintType
+ enum btSolverConstraintType
{
BT_SOLVER_CONTACT_1D = 0,
BT_SOLVER_FRICTION_1D
};
};
-typedef btAlignedObjectArray<btSolverConstraint> btConstraintArray;
-
-
-#endif //BT_SOLVER_CONSTRAINT_H
-
-
+typedef btAlignedObjectArray<btSolverConstraint> btConstraintArray;
+#endif //BT_SOLVER_CONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp
index 9f04f28053..ebe679c449 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp
@@ -13,69 +13,63 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#include "btTypedConstraint.h"
#include "BulletDynamics/Dynamics/btRigidBody.h"
#include "LinearMath/btSerializer.h"
-
#define DEFAULT_DEBUGDRAW_SIZE btScalar(0.05f)
btTypedConstraint::btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA)
-:btTypedObject(type),
-m_userConstraintType(-1),
-m_userConstraintPtr((void*)-1),
-m_breakingImpulseThreshold(SIMD_INFINITY),
-m_isEnabled(true),
-m_needsFeedback(false),
-m_overrideNumSolverIterations(-1),
-m_rbA(rbA),
-m_rbB(getFixedBody()),
-m_appliedImpulse(btScalar(0.)),
-m_dbgDrawSize(DEFAULT_DEBUGDRAW_SIZE),
-m_jointFeedback(0)
+ : btTypedObject(type),
+ m_userConstraintType(-1),
+ m_userConstraintPtr((void*)-1),
+ m_breakingImpulseThreshold(SIMD_INFINITY),
+ m_isEnabled(true),
+ m_needsFeedback(false),
+ m_overrideNumSolverIterations(-1),
+ m_rbA(rbA),
+ m_rbB(getFixedBody()),
+ m_appliedImpulse(btScalar(0.)),
+ m_dbgDrawSize(DEFAULT_DEBUGDRAW_SIZE),
+ m_jointFeedback(0)
{
}
-
-btTypedConstraint::btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA,btRigidBody& rbB)
-:btTypedObject(type),
-m_userConstraintType(-1),
-m_userConstraintPtr((void*)-1),
-m_breakingImpulseThreshold(SIMD_INFINITY),
-m_isEnabled(true),
-m_needsFeedback(false),
-m_overrideNumSolverIterations(-1),
-m_rbA(rbA),
-m_rbB(rbB),
-m_appliedImpulse(btScalar(0.)),
-m_dbgDrawSize(DEFAULT_DEBUGDRAW_SIZE),
-m_jointFeedback(0)
+btTypedConstraint::btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA, btRigidBody& rbB)
+ : btTypedObject(type),
+ m_userConstraintType(-1),
+ m_userConstraintPtr((void*)-1),
+ m_breakingImpulseThreshold(SIMD_INFINITY),
+ m_isEnabled(true),
+ m_needsFeedback(false),
+ m_overrideNumSolverIterations(-1),
+ m_rbA(rbA),
+ m_rbB(rbB),
+ m_appliedImpulse(btScalar(0.)),
+ m_dbgDrawSize(DEFAULT_DEBUGDRAW_SIZE),
+ m_jointFeedback(0)
{
}
-
-
-
btScalar btTypedConstraint::getMotorFactor(btScalar pos, btScalar lowLim, btScalar uppLim, btScalar vel, btScalar timeFact)
{
- if(lowLim > uppLim)
+ if (lowLim > uppLim)
{
return btScalar(1.0f);
}
- else if(lowLim == uppLim)
+ else if (lowLim == uppLim)
{
return btScalar(0.0f);
}
btScalar lim_fact = btScalar(1.0f);
btScalar delta_max = vel / timeFact;
- if(delta_max < btScalar(0.0f))
+ if (delta_max < btScalar(0.0f))
{
- if((pos >= lowLim) && (pos < (lowLim - delta_max)))
+ if ((pos >= lowLim) && (pos < (lowLim - delta_max)))
{
lim_fact = (lowLim - pos) / delta_max;
}
- else if(pos < lowLim)
+ else if (pos < lowLim)
{
lim_fact = btScalar(0.0f);
}
@@ -84,13 +78,13 @@ btScalar btTypedConstraint::getMotorFactor(btScalar pos, btScalar lowLim, btScal
lim_fact = btScalar(1.0f);
}
}
- else if(delta_max > btScalar(0.0f))
+ else if (delta_max > btScalar(0.0f))
{
- if((pos <= uppLim) && (pos > (uppLim - delta_max)))
+ if ((pos <= uppLim) && (pos > (uppLim - delta_max)))
{
lim_fact = (uppLim - pos) / delta_max;
}
- else if(pos > uppLim)
+ else if (pos > uppLim)
{
lim_fact = btScalar(0.0f);
}
@@ -101,19 +95,19 @@ btScalar btTypedConstraint::getMotorFactor(btScalar pos, btScalar lowLim, btScal
}
else
{
- lim_fact = btScalar(0.0f);
+ lim_fact = btScalar(0.0f);
}
return lim_fact;
}
///fills the dataBuffer and returns the struct name (and 0 on failure)
-const char* btTypedConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
+const char* btTypedConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
{
- btTypedConstraintData2* tcd = (btTypedConstraintData2*) dataBuffer;
+ btTypedConstraintData2* tcd = (btTypedConstraintData2*)dataBuffer;
tcd->m_rbA = (btRigidBodyData*)serializer->getUniquePointer(&m_rbA);
tcd->m_rbB = (btRigidBodyData*)serializer->getUniquePointer(&m_rbB);
- char* name = (char*) serializer->findNameForPointer(this);
+ char* name = (char*)serializer->findNameForPointer(this);
tcd->m_name = (char*)serializer->getUniquePointer(name);
if (tcd->m_name)
{
@@ -124,10 +118,10 @@ const char* btTypedConstraint::serialize(void* dataBuffer, btSerializer* seriali
tcd->m_needsFeedback = m_needsFeedback;
tcd->m_overrideNumSolverIterations = m_overrideNumSolverIterations;
tcd->m_breakingImpulseThreshold = m_breakingImpulseThreshold;
- tcd->m_isEnabled = m_isEnabled? 1: 0;
-
- tcd->m_userConstraintId =m_userConstraintId;
- tcd->m_userConstraintType =m_userConstraintType;
+ tcd->m_isEnabled = m_isEnabled ? 1 : 0;
+
+ tcd->m_userConstraintId = m_userConstraintId;
+ tcd->m_userConstraintType = m_userConstraintType;
tcd->m_appliedImpulse = m_appliedImpulse;
tcd->m_dbgDrawSize = m_dbgDrawSize;
@@ -135,10 +129,10 @@ const char* btTypedConstraint::serialize(void* dataBuffer, btSerializer* seriali
tcd->m_disableCollisionsBetweenLinkedBodies = false;
int i;
- for (i=0;i<m_rbA.getNumConstraintRefs();i++)
+ for (i = 0; i < m_rbA.getNumConstraintRefs(); i++)
if (m_rbA.getConstraintRef(i) == this)
tcd->m_disableCollisionsBetweenLinkedBodies = true;
- for (i=0;i<m_rbB.getNumConstraintRefs();i++)
+ for (i = 0; i < m_rbB.getNumConstraintRefs(); i++)
if (m_rbB.getConstraintRef(i) == this)
tcd->m_disableCollisionsBetweenLinkedBodies = true;
@@ -147,17 +141,16 @@ const char* btTypedConstraint::serialize(void* dataBuffer, btSerializer* seriali
btRigidBody& btTypedConstraint::getFixedBody()
{
- static btRigidBody s_fixed(0, 0,0);
- s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),btScalar(0.),btScalar(0.)));
+ static btRigidBody s_fixed(0, 0, 0);
+ s_fixed.setMassProps(btScalar(0.), btVector3(btScalar(0.), btScalar(0.), btScalar(0.)));
return s_fixed;
}
-
void btAngularLimit::set(btScalar low, btScalar high, btScalar _softness, btScalar _biasFactor, btScalar _relaxationFactor)
{
m_halfRange = (high - low) / 2.0f;
m_center = btNormalizeAngle(low + m_halfRange);
- m_softness = _softness;
+ m_softness = _softness;
m_biasFactor = _biasFactor;
m_relaxationFactor = _relaxationFactor;
}
@@ -174,7 +167,7 @@ void btAngularLimit::test(const btScalar angle)
if (deviation < -m_halfRange)
{
m_solveLimit = true;
- m_correction = - (deviation + m_halfRange);
+ m_correction = -(deviation + m_halfRange);
m_sign = +1.0f;
}
else if (deviation > m_halfRange)
@@ -186,7 +179,6 @@ void btAngularLimit::test(const btScalar angle)
}
}
-
btScalar btAngularLimit::getError() const
{
return m_correction * m_sign;
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btTypedConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btTypedConstraint.h
index 8a2a2d1ae7..d30f3dee5c 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btTypedConstraint.h
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btTypedConstraint.h
@@ -16,26 +16,24 @@ subject to the following restrictions:
#ifndef BT_TYPED_CONSTRAINT_H
#define BT_TYPED_CONSTRAINT_H
-
#include "LinearMath/btScalar.h"
#include "btSolverConstraint.h"
#include "BulletDynamics/Dynamics/btRigidBody.h"
#ifdef BT_USE_DOUBLE_PRECISION
-#define btTypedConstraintData2 btTypedConstraintDoubleData
-#define btTypedConstraintDataName "btTypedConstraintDoubleData"
+#define btTypedConstraintData2 btTypedConstraintDoubleData
+#define btTypedConstraintDataName "btTypedConstraintDoubleData"
#else
-#define btTypedConstraintData2 btTypedConstraintFloatData
-#define btTypedConstraintDataName "btTypedConstraintFloatData"
-#endif //BT_USE_DOUBLE_PRECISION
-
+#define btTypedConstraintData2 btTypedConstraintFloatData
+#define btTypedConstraintDataName "btTypedConstraintFloatData"
+#endif //BT_USE_DOUBLE_PRECISION
class btSerializer;
//Don't change any of the existing enum values, so add enum types at the end for serialization compatibility
enum btTypedConstraintType
{
- POINT2POINT_CONSTRAINT_TYPE=3,
+ POINT2POINT_CONSTRAINT_TYPE = 3,
HINGE_CONSTRAINT_TYPE,
CONETWIST_CONSTRAINT_TYPE,
D6_CONSTRAINT_TYPE,
@@ -48,91 +46,88 @@ enum btTypedConstraintType
MAX_CONSTRAINT_TYPE
};
-
enum btConstraintParams
{
- BT_CONSTRAINT_ERP=1,
+ BT_CONSTRAINT_ERP = 1,
BT_CONSTRAINT_STOP_ERP,
BT_CONSTRAINT_CFM,
BT_CONSTRAINT_STOP_CFM
};
#if 1
- #define btAssertConstrParams(_par) btAssert(_par)
+#define btAssertConstrParams(_par) btAssert(_par)
#else
- #define btAssertConstrParams(_par)
+#define btAssertConstrParams(_par)
#endif
-
-ATTRIBUTE_ALIGNED16(struct) btJointFeedback
+ATTRIBUTE_ALIGNED16(struct)
+btJointFeedback
{
BT_DECLARE_ALIGNED_ALLOCATOR();
- btVector3 m_appliedForceBodyA;
- btVector3 m_appliedTorqueBodyA;
- btVector3 m_appliedForceBodyB;
- btVector3 m_appliedTorqueBodyB;
+ btVector3 m_appliedForceBodyA;
+ btVector3 m_appliedTorqueBodyA;
+ btVector3 m_appliedForceBodyB;
+ btVector3 m_appliedTorqueBodyB;
};
-
///TypedConstraint is the baseclass for Bullet constraints and vehicles
-ATTRIBUTE_ALIGNED16(class) btTypedConstraint : public btTypedObject
+ATTRIBUTE_ALIGNED16(class)
+btTypedConstraint : public btTypedObject
{
- int m_userConstraintType;
+ int m_userConstraintType;
- union
- {
- int m_userConstraintId;
+ union {
+ int m_userConstraintId;
void* m_userConstraintPtr;
};
- btScalar m_breakingImpulseThreshold;
- bool m_isEnabled;
- bool m_needsFeedback;
- int m_overrideNumSolverIterations;
+ btScalar m_breakingImpulseThreshold;
+ bool m_isEnabled;
+ bool m_needsFeedback;
+ int m_overrideNumSolverIterations;
-
- btTypedConstraint& operator=(btTypedConstraint& other)
+ btTypedConstraint& operator=(btTypedConstraint& other)
{
btAssert(0);
- (void) other;
+ (void)other;
return *this;
}
protected:
- btRigidBody& m_rbA;
- btRigidBody& m_rbB;
- btScalar m_appliedImpulse;
- btScalar m_dbgDrawSize;
- btJointFeedback* m_jointFeedback;
+ btRigidBody& m_rbA;
+ btRigidBody& m_rbB;
+ btScalar m_appliedImpulse;
+ btScalar m_dbgDrawSize;
+ btJointFeedback* m_jointFeedback;
///internal method used by the constraint solver, don't use them directly
btScalar getMotorFactor(btScalar pos, btScalar lowLim, btScalar uppLim, btScalar vel, btScalar timeFact);
-
public:
-
BT_DECLARE_ALIGNED_ALLOCATOR();
- virtual ~btTypedConstraint() {};
- btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA);
- btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA,btRigidBody& rbB);
+ virtual ~btTypedConstraint(){};
+ btTypedConstraint(btTypedConstraintType type, btRigidBody & rbA);
+ btTypedConstraint(btTypedConstraintType type, btRigidBody & rbA, btRigidBody & rbB);
- struct btConstraintInfo1 {
- int m_numConstraintRows,nub;
+ struct btConstraintInfo1
+ {
+ int m_numConstraintRows, nub;
};
static btRigidBody& getFixedBody();
- struct btConstraintInfo2 {
+ struct btConstraintInfo2
+ {
// integrator parameters: frames per second (1/stepsize), default error
// reduction parameter (0..1).
- btScalar fps,erp;
+ btScalar fps, erp;
// 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.
- btScalar *m_J1linearAxis,*m_J1angularAxis,*m_J2linearAxis,*m_J2angularAxis;
+ btScalar *m_J1linearAxis, *m_J1angularAxis, *m_J2linearAxis, *m_J2angularAxis;
// elements to jump from one row to the next in J's
int rowskip;
@@ -140,19 +135,19 @@ public:
// 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.
- btScalar *m_constraintError,*cfm;
+ btScalar *m_constraintError, *cfm;
// lo and hi limits for variables (set to -/+ infinity on entry).
- btScalar *m_lowerLimit,*m_upperLimit;
+ btScalar *m_lowerLimit, *m_upperLimit;
// number of solver iterations
int m_numIterations;
//damping of the velocity
- btScalar m_damping;
+ btScalar m_damping;
};
- int getOverrideNumSolverIterations() const
+ int getOverrideNumSolverIterations() const
{
return m_overrideNumSolverIterations;
}
@@ -165,60 +160,57 @@ public:
}
///internal method used by the constraint solver, don't use them directly
- virtual void buildJacobian() {};
+ virtual void buildJacobian(){};
///internal method used by the constraint solver, don't use them directly
- virtual void setupSolverConstraint(btConstraintArray& ca, int solverBodyA,int solverBodyB, btScalar timeStep)
+ virtual void setupSolverConstraint(btConstraintArray & ca, int solverBodyA, int solverBodyB, btScalar timeStep)
{
- (void)ca;
- (void)solverBodyA;
- (void)solverBodyB;
- (void)timeStep;
+ (void)ca;
+ (void)solverBodyA;
+ (void)solverBodyB;
+ (void)timeStep;
}
-
+
///internal method used by the constraint solver, don't use them directly
- virtual void getInfo1 (btConstraintInfo1* info)=0;
+ virtual void getInfo1(btConstraintInfo1 * info) = 0;
///internal method used by the constraint solver, don't use them directly
- virtual void getInfo2 (btConstraintInfo2* info)=0;
+ virtual void getInfo2(btConstraintInfo2 * info) = 0;
///internal method used by the constraint solver, don't use them directly
- void internalSetAppliedImpulse(btScalar appliedImpulse)
+ void internalSetAppliedImpulse(btScalar appliedImpulse)
{
m_appliedImpulse = appliedImpulse;
}
///internal method used by the constraint solver, don't use them directly
- btScalar internalGetAppliedImpulse()
+ btScalar internalGetAppliedImpulse()
{
return m_appliedImpulse;
}
-
- btScalar getBreakingImpulseThreshold() const
+ btScalar getBreakingImpulseThreshold() const
{
- return m_breakingImpulseThreshold;
+ return m_breakingImpulseThreshold;
}
- void setBreakingImpulseThreshold(btScalar threshold)
+ void setBreakingImpulseThreshold(btScalar threshold)
{
m_breakingImpulseThreshold = threshold;
}
- bool isEnabled() const
+ bool isEnabled() const
{
return m_isEnabled;
}
- void setEnabled(bool enabled)
+ void setEnabled(bool enabled)
{
- m_isEnabled=enabled;
+ m_isEnabled = enabled;
}
-
///internal method used by the constraint solver, don't use them directly
- virtual void solveConstraintObsolete(btSolverBody& /*bodyA*/,btSolverBody& /*bodyB*/,btScalar /*timeStep*/) {};
+ virtual void solveConstraintObsolete(btSolverBody& /*bodyA*/, btSolverBody& /*bodyB*/, btScalar /*timeStep*/){};
-
const btRigidBody& getRigidBodyA() const
{
return m_rbA;
@@ -228,7 +220,7 @@ public:
return m_rbB;
}
- btRigidBody& getRigidBodyA()
+ btRigidBody& getRigidBodyA()
{
return m_rbA;
}
@@ -239,15 +231,15 @@ public:
int getUserConstraintType() const
{
- return m_userConstraintType ;
+ return m_userConstraintType;
}
- void setUserConstraintType(int userConstraintType)
+ void setUserConstraintType(int userConstraintType)
{
m_userConstraintType = userConstraintType;
};
- void setUserConstraintId(int uid)
+ void setUserConstraintId(int uid)
{
m_userConstraintId = uid;
}
@@ -257,17 +249,17 @@ public:
return m_userConstraintId;
}
- void setUserConstraintPtr(void* ptr)
+ void setUserConstraintPtr(void* ptr)
{
m_userConstraintPtr = ptr;
}
- void* getUserConstraintPtr()
+ void* getUserConstraintPtr()
{
return m_userConstraintPtr;
}
- void setJointFeedback(btJointFeedback* jointFeedback)
+ void setJointFeedback(btJointFeedback * jointFeedback)
{
m_jointFeedback = jointFeedback;
}
@@ -282,37 +274,36 @@ public:
return m_jointFeedback;
}
-
int getUid() const
{
- return m_userConstraintId;
- }
+ return m_userConstraintId;
+ }
- bool needsFeedback() const
+ bool needsFeedback() const
{
return m_needsFeedback;
}
///enableFeedback will allow to read the applied linear and angular impulse
///use getAppliedImpulse, getAppliedLinearImpulse and getAppliedAngularImpulse to read feedback information
- void enableFeedback(bool needsFeedback)
+ void enableFeedback(bool needsFeedback)
{
m_needsFeedback = needsFeedback;
}
- ///getAppliedImpulse is an estimated total applied impulse.
+ ///getAppliedImpulse is an estimated total applied impulse.
///This feedback could be used to determine breaking constraints or playing sounds.
- btScalar getAppliedImpulse() const
+ btScalar getAppliedImpulse() const
{
btAssert(m_needsFeedback);
return m_appliedImpulse;
}
- btTypedConstraintType getConstraintType () const
+ btTypedConstraintType getConstraintType() const
{
return btTypedConstraintType(m_objectType);
}
-
+
void setDbgDrawSize(btScalar dbgDrawSize)
{
m_dbgDrawSize = dbgDrawSize;
@@ -322,35 +313,34 @@ public:
return m_dbgDrawSize;
}
- ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+ ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
///If no axis is provided, it uses the default axis for this constraint.
- virtual void setParam(int num, btScalar value, int axis = -1) = 0;
+ virtual void setParam(int num, btScalar value, int axis = -1) = 0;
///return the local value of parameter
- virtual btScalar getParam(int num, int axis = -1) const = 0;
-
- virtual int calculateSerializeBufferSize() const;
+ virtual btScalar getParam(int num, int axis = -1) const = 0;
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+ virtual int calculateSerializeBufferSize() const;
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
};
-// returns angle in range [-SIMD_2_PI, SIMD_2_PI], closest to one of the limits
+// returns angle in range [-SIMD_2_PI, SIMD_2_PI], closest to one of the limits
// all arguments should be normalized angles (i.e. in range [-SIMD_PI, SIMD_PI])
SIMD_FORCE_INLINE btScalar btAdjustAngleToLimits(btScalar angleInRadians, btScalar angleLowerLimitInRadians, btScalar angleUpperLimitInRadians)
{
- if(angleLowerLimitInRadians >= angleUpperLimitInRadians)
+ if (angleLowerLimitInRadians >= angleUpperLimitInRadians)
{
return angleInRadians;
}
- else if(angleInRadians < angleLowerLimitInRadians)
+ else if (angleInRadians < angleLowerLimitInRadians)
{
btScalar diffLo = btFabs(btNormalizeAngle(angleLowerLimitInRadians - angleInRadians));
btScalar diffHi = btFabs(btNormalizeAngle(angleUpperLimitInRadians - angleInRadians));
return (diffLo < diffHi) ? angleInRadians : (angleInRadians + SIMD_2_PI);
}
- else if(angleInRadians > angleUpperLimitInRadians)
+ else if (angleInRadians > angleUpperLimitInRadians)
{
btScalar diffHi = btFabs(btNormalizeAngle(angleInRadians - angleUpperLimitInRadians));
btScalar diffLo = btFabs(btNormalizeAngle(angleInRadians - angleLowerLimitInRadians));
@@ -362,6 +352,8 @@ SIMD_FORCE_INLINE btScalar btAdjustAngleToLimits(btScalar angleInRadians, btScal
}
}
+// clang-format off
+
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
struct btTypedConstraintFloatData
{
@@ -385,6 +377,8 @@ struct btTypedConstraintFloatData
};
+
+
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
#define BT_BACKWARDS_COMPATIBLE_SERIALIZATION
@@ -436,18 +430,17 @@ struct btTypedConstraintDoubleData
};
+// clang-format on
-SIMD_FORCE_INLINE int btTypedConstraint::calculateSerializeBufferSize() const
+SIMD_FORCE_INLINE int btTypedConstraint::calculateSerializeBufferSize() const
{
return sizeof(btTypedConstraintData2);
}
-
-
class btAngularLimit
{
private:
- btScalar
+ btScalar
m_center,
m_halfRange,
m_softness,
@@ -462,15 +455,16 @@ private:
public:
/// Default constructor initializes limit as inactive, allowing free constraint movement
btAngularLimit()
- :m_center(0.0f),
- m_halfRange(-1.0f),
- m_softness(0.9f),
- m_biasFactor(0.3f),
- m_relaxationFactor(1.0f),
- m_correction(0.0f),
- m_sign(0.0f),
- m_solveLimit(false)
- {}
+ : m_center(0.0f),
+ m_halfRange(-1.0f),
+ m_softness(0.9f),
+ m_biasFactor(0.3f),
+ m_relaxationFactor(1.0f),
+ m_correction(0.0f),
+ m_sign(0.0f),
+ m_solveLimit(false)
+ {
+ }
/// Sets all limit's parameters.
/// When low > high limit becomes inactive.
@@ -499,13 +493,13 @@ public:
return m_relaxationFactor;
}
- /// Returns correction value evaluated when test() was invoked
+ /// Returns correction value evaluated when test() was invoked
inline btScalar getCorrection() const
{
return m_correction;
}
- /// Returns sign value evaluated when test() was invoked
+ /// Returns sign value evaluated when test() was invoked
inline btScalar getSign() const
{
return m_sign;
@@ -533,9 +527,6 @@ public:
btScalar getLow() const;
btScalar getHigh() const;
-
};
-
-
-#endif //BT_TYPED_CONSTRAINT_H
+#endif //BT_TYPED_CONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp
index b009f41aec..42ed1fbb87 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp
@@ -13,43 +13,38 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
-
#include "btUniversalConstraint.h"
#include "BulletDynamics/Dynamics/btRigidBody.h"
#include "LinearMath/btTransformUtil.h"
-
-
#define UNIV_EPS btScalar(0.01f)
-
// constructor
// anchor, axis1 and axis2 are in world coordinate system
// axis1 must be orthogonal to axis2
btUniversalConstraint::btUniversalConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& anchor, const btVector3& axis1, const btVector3& axis2)
-: btGeneric6DofConstraint(rbA, rbB, btTransform::getIdentity(), btTransform::getIdentity(), true),
- m_anchor(anchor),
- m_axis1(axis1),
- m_axis2(axis2)
+ : btGeneric6DofConstraint(rbA, rbB, btTransform::getIdentity(), btTransform::getIdentity(), true),
+ m_anchor(anchor),
+ m_axis1(axis1),
+ m_axis2(axis2)
{
// build frame basis
// 6DOF constraint uses Euler angles and to define limits
// it is assumed that rotational order is :
// Z - first, allowed limits are (-PI,PI);
- // new position of Y - second (allowed limits are (-PI/2 + epsilon, PI/2 - epsilon), where epsilon is a small positive number
+ // new position of Y - second (allowed limits are (-PI/2 + epsilon, PI/2 - epsilon), where epsilon is a small positive number
// used to prevent constraint from instability on poles;
// new position of X, allowed limits are (-PI,PI);
// So to simulate ODE Universal joint we should use parent axis as Z, child axis as Y and limit all other DOFs
// Build the frame in world coordinate system first
btVector3 zAxis = m_axis1.normalize();
btVector3 yAxis = m_axis2.normalize();
- btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system
+ btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system
btTransform frameInW;
frameInW.setIdentity();
- frameInW.getBasis().setValue( xAxis[0], yAxis[0], zAxis[0],
- xAxis[1], yAxis[1], zAxis[1],
- xAxis[2], yAxis[2], zAxis[2]);
+ frameInW.getBasis().setValue(xAxis[0], yAxis[0], zAxis[0],
+ xAxis[1], yAxis[1], zAxis[1],
+ xAxis[2], yAxis[2], zAxis[2]);
frameInW.setOrigin(anchor);
// now get constraint frame in local coordinate systems
m_frameInA = rbA.getCenterOfMassTransform().inverse() * frameInW;
@@ -58,30 +53,28 @@ btUniversalConstraint::btUniversalConstraint(btRigidBody& rbA, btRigidBody& rbB,
setLinearLowerLimit(btVector3(0., 0., 0.));
setLinearUpperLimit(btVector3(0., 0., 0.));
setAngularLowerLimit(btVector3(0.f, -SIMD_HALF_PI + UNIV_EPS, -SIMD_PI + UNIV_EPS));
- setAngularUpperLimit(btVector3(0.f, SIMD_HALF_PI - UNIV_EPS, SIMD_PI - UNIV_EPS));
+ setAngularUpperLimit(btVector3(0.f, SIMD_HALF_PI - UNIV_EPS, SIMD_PI - UNIV_EPS));
}
-void btUniversalConstraint::setAxis(const btVector3& axis1,const btVector3& axis2)
+void btUniversalConstraint::setAxis(const btVector3& axis1, const btVector3& axis2)
{
- m_axis1 = axis1;
- m_axis2 = axis2;
+ m_axis1 = axis1;
+ m_axis2 = axis2;
btVector3 zAxis = axis1.normalized();
btVector3 yAxis = axis2.normalized();
- btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system
+ btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system
btTransform frameInW;
frameInW.setIdentity();
- frameInW.getBasis().setValue( xAxis[0], yAxis[0], zAxis[0],
- xAxis[1], yAxis[1], zAxis[1],
- xAxis[2], yAxis[2], zAxis[2]);
+ frameInW.getBasis().setValue(xAxis[0], yAxis[0], zAxis[0],
+ xAxis[1], yAxis[1], zAxis[1],
+ xAxis[2], yAxis[2], zAxis[2]);
frameInW.setOrigin(m_anchor);
// now get constraint frame in local coordinate systems
m_frameInA = m_rbA.getCenterOfMassTransform().inverse() * frameInW;
m_frameInB = m_rbB.getCenterOfMassTransform().inverse() * frameInW;
- calculateTransforms();
+ calculateTransforms();
}
-
-
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btUniversalConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btUniversalConstraint.h
index 9e70841043..8c24d93a64 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btUniversalConstraint.h
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btUniversalConstraint.h
@@ -16,35 +16,32 @@ subject to the following restrictions:
#ifndef BT_UNIVERSAL_CONSTRAINT_H
#define BT_UNIVERSAL_CONSTRAINT_H
-
-
#include "LinearMath/btVector3.h"
#include "btTypedConstraint.h"
#include "btGeneric6DofConstraint.h"
-
-
/// Constraint similar to ODE Universal Joint
/// has 2 rotatioonal degrees of freedom, similar to Euler rotations around Z (axis 1)
/// and Y (axis 2)
-/// Description from ODE manual :
-/// "Given axis 1 on body 1, and axis 2 on body 2 that is perpendicular to axis 1, it keeps them perpendicular.
+/// Description from ODE manual :
+/// "Given axis 1 on body 1, and axis 2 on body 2 that is perpendicular to axis 1, it keeps them perpendicular.
/// In other words, rotation of the two bodies about the direction perpendicular to the two axes will be equal."
-ATTRIBUTE_ALIGNED16(class) btUniversalConstraint : public btGeneric6DofConstraint
+ATTRIBUTE_ALIGNED16(class)
+btUniversalConstraint : public btGeneric6DofConstraint
{
protected:
- btVector3 m_anchor;
- btVector3 m_axis1;
- btVector3 m_axis2;
+ btVector3 m_anchor;
+ btVector3 m_axis1;
+ btVector3 m_axis2;
+
public:
-
BT_DECLARE_ALIGNED_ALLOCATOR();
-
+
// constructor
// anchor, axis1 and axis2 are in world coordinate system
// axis1 must be orthogonal to axis2
- btUniversalConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& anchor, const btVector3& axis1, const btVector3& axis2);
+ btUniversalConstraint(btRigidBody & rbA, btRigidBody & rbB, const btVector3& anchor, const btVector3& axis1, const btVector3& axis2);
// access
const btVector3& getAnchor() { return m_calculatedTransformA.getOrigin(); }
const btVector3& getAnchor2() { return m_calculatedTransformB.getOrigin(); }
@@ -56,10 +53,7 @@ public:
void setUpperLimit(btScalar ang1max, btScalar ang2max) { setAngularUpperLimit(btVector3(0.f, ang1max, ang2max)); }
void setLowerLimit(btScalar ang1min, btScalar ang2min) { setAngularLowerLimit(btVector3(0.f, ang1min, ang2min)); }
- void setAxis( const btVector3& axis1, const btVector3& axis2);
+ void setAxis(const btVector3& axis1, const btVector3& axis2);
};
-
-
-#endif // BT_UNIVERSAL_CONSTRAINT_H
-
+#endif // BT_UNIVERSAL_CONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/Dynamics/btActionInterface.h b/thirdparty/bullet/BulletDynamics/Dynamics/btActionInterface.h
index e1fea3a49c..b5cac56cdc 100644
--- a/thirdparty/bullet/BulletDynamics/Dynamics/btActionInterface.h
+++ b/thirdparty/bullet/BulletDynamics/Dynamics/btActionInterface.h
@@ -26,21 +26,16 @@ class btCollisionWorld;
class btActionInterface
{
protected:
-
static btRigidBody& getFixedBody();
-
-
-public:
+public:
virtual ~btActionInterface()
{
}
- virtual void updateAction( btCollisionWorld* collisionWorld, btScalar deltaTimeStep)=0;
+ virtual void updateAction(btCollisionWorld* collisionWorld, btScalar deltaTimeStep) = 0;
virtual void debugDraw(btIDebugDraw* debugDrawer) = 0;
-
};
-#endif //_BT_ACTION_INTERFACE_H
-
+#endif //_BT_ACTION_INTERFACE_H
diff --git a/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp b/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp
index b9944c138b..dfbbdb154f 100644
--- a/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp
+++ b/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp
@@ -13,7 +13,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#include "btDiscreteDynamicsWorld.h"
//collision detection
@@ -38,11 +37,9 @@ subject to the following restrictions:
#include "BulletDynamics/ConstraintSolver/btSliderConstraint.h"
#include "BulletDynamics/ConstraintSolver/btContactConstraint.h"
-
#include "LinearMath/btIDebugDraw.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h"
-
#include "BulletDynamics/Dynamics/btActionInterface.h"
#include "LinearMath/btQuickprof.h"
#include "LinearMath/btMotionState.h"
@@ -56,57 +53,52 @@ int startHit=2;
int firstHit=startHit;
#endif
-SIMD_FORCE_INLINE int btGetConstraintIslandId(const btTypedConstraint* lhs)
+SIMD_FORCE_INLINE int btGetConstraintIslandId(const btTypedConstraint* lhs)
{
int islandId;
const btCollisionObject& rcolObj0 = lhs->getRigidBodyA();
const btCollisionObject& rcolObj1 = lhs->getRigidBodyB();
- islandId= rcolObj0.getIslandTag()>=0?rcolObj0.getIslandTag():rcolObj1.getIslandTag();
+ islandId = rcolObj0.getIslandTag() >= 0 ? rcolObj0.getIslandTag() : rcolObj1.getIslandTag();
return islandId;
-
}
-
class btSortConstraintOnIslandPredicate
{
- public:
-
- bool operator() ( const btTypedConstraint* lhs, const btTypedConstraint* rhs ) const
- {
- int rIslandId0,lIslandId0;
- rIslandId0 = btGetConstraintIslandId(rhs);
- lIslandId0 = btGetConstraintIslandId(lhs);
- return lIslandId0 < rIslandId0;
- }
+public:
+ bool operator()(const btTypedConstraint* lhs, const btTypedConstraint* rhs) const
+ {
+ int rIslandId0, lIslandId0;
+ rIslandId0 = btGetConstraintIslandId(rhs);
+ lIslandId0 = btGetConstraintIslandId(lhs);
+ return lIslandId0 < rIslandId0;
+ }
};
struct InplaceSolverIslandCallback : public btSimulationIslandManager::IslandCallback
{
- btContactSolverInfo* m_solverInfo;
- btConstraintSolver* m_solver;
- btTypedConstraint** m_sortedConstraints;
- int m_numConstraints;
- btIDebugDraw* m_debugDrawer;
- btDispatcher* m_dispatcher;
+ btContactSolverInfo* m_solverInfo;
+ btConstraintSolver* m_solver;
+ btTypedConstraint** m_sortedConstraints;
+ int m_numConstraints;
+ btIDebugDraw* m_debugDrawer;
+ btDispatcher* m_dispatcher;
btAlignedObjectArray<btCollisionObject*> m_bodies;
btAlignedObjectArray<btPersistentManifold*> m_manifolds;
btAlignedObjectArray<btTypedConstraint*> m_constraints;
-
InplaceSolverIslandCallback(
- btConstraintSolver* solver,
+ btConstraintSolver* solver,
btStackAlloc* stackAlloc,
btDispatcher* dispatcher)
- :m_solverInfo(NULL),
- m_solver(solver),
- m_sortedConstraints(NULL),
- m_numConstraints(0),
- m_debugDrawer(NULL),
- m_dispatcher(dispatcher)
+ : m_solverInfo(NULL),
+ m_solver(solver),
+ m_sortedConstraints(NULL),
+ m_numConstraints(0),
+ m_debugDrawer(NULL),
+ m_dispatcher(dispatcher)
{
-
}
InplaceSolverIslandCallback& operator=(InplaceSolverIslandCallback& other)
@@ -116,34 +108,34 @@ struct InplaceSolverIslandCallback : public btSimulationIslandManager::IslandCal
return *this;
}
- SIMD_FORCE_INLINE void setup ( btContactSolverInfo* solverInfo, btTypedConstraint** sortedConstraints, int numConstraints, btIDebugDraw* debugDrawer)
+ SIMD_FORCE_INLINE void setup(btContactSolverInfo* solverInfo, btTypedConstraint** sortedConstraints, int numConstraints, btIDebugDraw* debugDrawer)
{
btAssert(solverInfo);
m_solverInfo = solverInfo;
m_sortedConstraints = sortedConstraints;
m_numConstraints = numConstraints;
m_debugDrawer = debugDrawer;
- m_bodies.resize (0);
- m_manifolds.resize (0);
- m_constraints.resize (0);
+ m_bodies.resize(0);
+ m_manifolds.resize(0);
+ m_constraints.resize(0);
}
-
- virtual void processIsland(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifolds,int numManifolds, int islandId)
+ virtual void processIsland(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifolds, int numManifolds, int islandId)
{
- if (islandId<0)
+ if (islandId < 0)
{
///we don't split islands, so all constraints/contact manifolds/bodies are passed into the solver regardless the island id
- m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,&m_sortedConstraints[0],m_numConstraints,*m_solverInfo,m_debugDrawer,m_dispatcher);
- } else
+ m_solver->solveGroup(bodies, numBodies, manifolds, numManifolds, &m_sortedConstraints[0], m_numConstraints, *m_solverInfo, m_debugDrawer, m_dispatcher);
+ }
+ else
{
- //also add all non-contact constraints/joints for this island
+ //also add all non-contact constraints/joints for this island
btTypedConstraint** startConstraint = 0;
int numCurConstraints = 0;
int i;
//find the first constraint for this island
- for (i=0;i<m_numConstraints;i++)
+ for (i = 0; i < m_numConstraints; i++)
{
if (btGetConstraintIslandId(m_sortedConstraints[i]) == islandId)
{
@@ -152,7 +144,7 @@ struct InplaceSolverIslandCallback : public btSimulationIslandManager::IslandCal
}
}
//count the number of constraints in this island
- for (;i<m_numConstraints;i++)
+ for (; i < m_numConstraints; i++)
{
if (btGetConstraintIslandId(m_sortedConstraints[i]) == islandId)
{
@@ -160,91 +152,87 @@ struct InplaceSolverIslandCallback : public btSimulationIslandManager::IslandCal
}
}
- if (m_solverInfo->m_minimumSolverBatchSize<=1)
+ if (m_solverInfo->m_minimumSolverBatchSize <= 1)
{
- m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,startConstraint,numCurConstraints,*m_solverInfo,m_debugDrawer,m_dispatcher);
- } else
+ m_solver->solveGroup(bodies, numBodies, manifolds, numManifolds, startConstraint, numCurConstraints, *m_solverInfo, m_debugDrawer, m_dispatcher);
+ }
+ else
{
-
- for (i=0;i<numBodies;i++)
+ for (i = 0; i < numBodies; i++)
m_bodies.push_back(bodies[i]);
- for (i=0;i<numManifolds;i++)
+ for (i = 0; i < numManifolds; i++)
m_manifolds.push_back(manifolds[i]);
- for (i=0;i<numCurConstraints;i++)
+ for (i = 0; i < numCurConstraints; i++)
m_constraints.push_back(startConstraint[i]);
- if ((m_constraints.size()+m_manifolds.size())>m_solverInfo->m_minimumSolverBatchSize)
+ if ((m_constraints.size() + m_manifolds.size()) > m_solverInfo->m_minimumSolverBatchSize)
{
processConstraints();
- } else
+ }
+ else
{
//printf("deferred\n");
}
}
}
}
- void processConstraints()
+ void processConstraints()
{
+ btCollisionObject** bodies = m_bodies.size() ? &m_bodies[0] : 0;
+ btPersistentManifold** manifold = m_manifolds.size() ? &m_manifolds[0] : 0;
+ btTypedConstraint** constraints = m_constraints.size() ? &m_constraints[0] : 0;
- btCollisionObject** bodies = m_bodies.size()? &m_bodies[0]:0;
- btPersistentManifold** manifold = m_manifolds.size()?&m_manifolds[0]:0;
- btTypedConstraint** constraints = m_constraints.size()?&m_constraints[0]:0;
-
- m_solver->solveGroup( bodies,m_bodies.size(),manifold, m_manifolds.size(),constraints, m_constraints.size() ,*m_solverInfo,m_debugDrawer,m_dispatcher);
+ m_solver->solveGroup(bodies, m_bodies.size(), manifold, m_manifolds.size(), constraints, m_constraints.size(), *m_solverInfo, m_debugDrawer, m_dispatcher);
m_bodies.resize(0);
m_manifolds.resize(0);
m_constraints.resize(0);
-
}
-
};
-
-
-btDiscreteDynamicsWorld::btDiscreteDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration)
-:btDynamicsWorld(dispatcher,pairCache,collisionConfiguration),
-m_sortedConstraints (),
-m_solverIslandCallback ( NULL ),
-m_constraintSolver(constraintSolver),
-m_gravity(0,-10,0),
-m_localTime(0),
-m_fixedTimeStep(0),
-m_synchronizeAllMotionStates(false),
-m_applySpeculativeContactRestitution(false),
-m_profileTimings(0),
-m_latencyMotionStateInterpolation(true)
+btDiscreteDynamicsWorld::btDiscreteDynamicsWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration)
+ : btDynamicsWorld(dispatcher, pairCache, collisionConfiguration),
+ m_sortedConstraints(),
+ m_solverIslandCallback(NULL),
+ m_constraintSolver(constraintSolver),
+ m_gravity(0, -10, 0),
+ m_localTime(0),
+ m_fixedTimeStep(0),
+ m_synchronizeAllMotionStates(false),
+ m_applySpeculativeContactRestitution(false),
+ m_profileTimings(0),
+ m_latencyMotionStateInterpolation(true)
{
if (!m_constraintSolver)
{
- void* mem = btAlignedAlloc(sizeof(btSequentialImpulseConstraintSolver),16);
+ void* mem = btAlignedAlloc(sizeof(btSequentialImpulseConstraintSolver), 16);
m_constraintSolver = new (mem) btSequentialImpulseConstraintSolver;
m_ownsConstraintSolver = true;
- } else
+ }
+ else
{
m_ownsConstraintSolver = false;
}
{
- void* mem = btAlignedAlloc(sizeof(btSimulationIslandManager),16);
+ void* mem = btAlignedAlloc(sizeof(btSimulationIslandManager), 16);
m_islandManager = new (mem) btSimulationIslandManager();
}
m_ownsIslandManager = true;
{
- void* mem = btAlignedAlloc(sizeof(InplaceSolverIslandCallback),16);
- m_solverIslandCallback = new (mem) InplaceSolverIslandCallback (m_constraintSolver, 0, dispatcher);
+ void* mem = btAlignedAlloc(sizeof(InplaceSolverIslandCallback), 16);
+ m_solverIslandCallback = new (mem) InplaceSolverIslandCallback(m_constraintSolver, 0, dispatcher);
}
}
-
btDiscreteDynamicsWorld::~btDiscreteDynamicsWorld()
{
//only delete it when we created it
if (m_ownsIslandManager)
{
m_islandManager->~btSimulationIslandManager();
- btAlignedFree( m_islandManager);
+ btAlignedFree(m_islandManager);
}
if (m_solverIslandCallback)
{
@@ -253,18 +241,17 @@ btDiscreteDynamicsWorld::~btDiscreteDynamicsWorld()
}
if (m_ownsConstraintSolver)
{
-
m_constraintSolver->~btConstraintSolver();
btAlignedFree(m_constraintSolver);
}
}
-void btDiscreteDynamicsWorld::saveKinematicState(btScalar timeStep)
+void btDiscreteDynamicsWorld::saveKinematicState(btScalar timeStep)
{
-///would like to iterate over m_nonStaticRigidBodies, but unfortunately old API allows
-///to switch status _after_ adding kinematic objects to the world
-///fix it for Bullet 3.x release
- for (int i=0;i<m_collisionObjects.size();i++)
+ ///would like to iterate over m_nonStaticRigidBodies, but unfortunately old API allows
+ ///to switch status _after_ adding kinematic objects to the world
+ ///fix it for Bullet 3.x release
+ for (int i = 0; i < m_collisionObjects.size(); i++)
{
btCollisionObject* colObj = m_collisionObjects[i];
btRigidBody* body = btRigidBody::upcast(colObj);
@@ -277,10 +264,9 @@ void btDiscreteDynamicsWorld::saveKinematicState(btScalar timeStep)
}
}
}
-
}
-void btDiscreteDynamicsWorld::debugDrawWorld()
+void btDiscreteDynamicsWorld::debugDrawWorld()
{
BT_PROFILE("debugDrawWorld");
@@ -290,43 +276,40 @@ void btDiscreteDynamicsWorld::debugDrawWorld()
if (getDebugDrawer())
{
int mode = getDebugDrawer()->getDebugMode();
- if(mode & (btIDebugDraw::DBG_DrawConstraints | btIDebugDraw::DBG_DrawConstraintLimits))
+ if (mode & (btIDebugDraw::DBG_DrawConstraints | btIDebugDraw::DBG_DrawConstraintLimits))
{
drawConstraints = true;
}
}
- if(drawConstraints)
+ if (drawConstraints)
{
- for(int i = getNumConstraints()-1; i>=0 ;i--)
+ for (int i = getNumConstraints() - 1; i >= 0; i--)
{
btTypedConstraint* constraint = getConstraint(i);
debugDrawConstraint(constraint);
}
}
-
-
- if (getDebugDrawer() && (getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawAabb | btIDebugDraw::DBG_DrawNormals)))
+ if (getDebugDrawer() && (getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawAabb | btIDebugDraw::DBG_DrawNormals)))
{
int i;
if (getDebugDrawer() && getDebugDrawer()->getDebugMode())
{
- for (i=0;i<m_actions.size();i++)
+ for (i = 0; i < m_actions.size(); i++)
{
m_actions[i]->debugDraw(m_debugDrawer);
}
}
}
- if (getDebugDrawer())
- getDebugDrawer()->flushLines();
-
+ if (getDebugDrawer())
+ getDebugDrawer()->flushLines();
}
-void btDiscreteDynamicsWorld::clearForces()
+void btDiscreteDynamicsWorld::clearForces()
{
///@todo: iterate over awake simulation islands!
- for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
+ for (int i = 0; i < m_nonStaticRigidBodies.size(); i++)
{
btRigidBody* body = m_nonStaticRigidBodies[i];
//need to check if next line is ok
@@ -336,10 +319,10 @@ void btDiscreteDynamicsWorld::clearForces()
}
///apply gravity, call this once per timestep
-void btDiscreteDynamicsWorld::applyGravity()
+void btDiscreteDynamicsWorld::applyGravity()
{
///@todo: iterate over awake simulation islands!
- for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
+ for (int i = 0; i < m_nonStaticRigidBodies.size(); i++)
{
btRigidBody* body = m_nonStaticRigidBodies[i];
if (body->isActive())
@@ -349,8 +332,7 @@ void btDiscreteDynamicsWorld::applyGravity()
}
}
-
-void btDiscreteDynamicsWorld::synchronizeSingleMotionState(btRigidBody* body)
+void btDiscreteDynamicsWorld::synchronizeSingleMotionState(btRigidBody* body)
{
btAssert(body);
@@ -363,32 +345,32 @@ void btDiscreteDynamicsWorld::synchronizeSingleMotionState(btRigidBody* body)
{
btTransform interpolatedTransform;
btTransformUtil::integrateTransform(body->getInterpolationWorldTransform(),
- body->getInterpolationLinearVelocity(),body->getInterpolationAngularVelocity(),
- (m_latencyMotionStateInterpolation && m_fixedTimeStep) ? m_localTime - m_fixedTimeStep : m_localTime*body->getHitFraction(),
- interpolatedTransform);
+ body->getInterpolationLinearVelocity(), body->getInterpolationAngularVelocity(),
+ (m_latencyMotionStateInterpolation && m_fixedTimeStep) ? m_localTime - m_fixedTimeStep : m_localTime * body->getHitFraction(),
+ interpolatedTransform);
body->getMotionState()->setWorldTransform(interpolatedTransform);
}
}
}
-
-void btDiscreteDynamicsWorld::synchronizeMotionStates()
+void btDiscreteDynamicsWorld::synchronizeMotionStates()
{
-// BT_PROFILE("synchronizeMotionStates");
+ // BT_PROFILE("synchronizeMotionStates");
if (m_synchronizeAllMotionStates)
{
//iterate over all collision objects
- for ( int i=0;i<m_collisionObjects.size();i++)
+ for (int i = 0; i < m_collisionObjects.size(); i++)
{
btCollisionObject* colObj = m_collisionObjects[i];
btRigidBody* body = btRigidBody::upcast(colObj);
if (body)
synchronizeSingleMotionState(body);
}
- } else
+ }
+ else
{
//iterate over all active rigid bodies
- for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
+ for (int i = 0; i < m_nonStaticRigidBodies.size(); i++)
{
btRigidBody* body = m_nonStaticRigidBodies[i];
if (body->isActive())
@@ -397,12 +379,10 @@ void btDiscreteDynamicsWorld::synchronizeMotionStates()
}
}
-
-int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, btScalar fixedTimeStep)
+int btDiscreteDynamicsWorld::stepSimulation(btScalar timeStep, int maxSubSteps, btScalar fixedTimeStep)
{
startProfiling(timeStep);
-
int numSimulationSubSteps = 0;
if (maxSubSteps)
@@ -412,10 +392,11 @@ int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps,
m_localTime += timeStep;
if (m_localTime >= fixedTimeStep)
{
- numSimulationSubSteps = int( m_localTime / fixedTimeStep);
+ numSimulationSubSteps = int(m_localTime / fixedTimeStep);
m_localTime -= numSimulationSubSteps * fixedTimeStep;
}
- } else
+ }
+ else
{
//variable timestep
fixedTimeStep = timeStep;
@@ -425,7 +406,8 @@ int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps,
{
numSimulationSubSteps = 0;
maxSubSteps = 0;
- } else
+ }
+ else
{
numSimulationSubSteps = 1;
maxSubSteps = 1;
@@ -435,28 +417,25 @@ int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps,
//process some debugging flags
if (getDebugDrawer())
{
- btIDebugDraw* debugDrawer = getDebugDrawer ();
+ btIDebugDraw* debugDrawer = getDebugDrawer();
gDisableDeactivation = (debugDrawer->getDebugMode() & btIDebugDraw::DBG_NoDeactivation) != 0;
}
if (numSimulationSubSteps)
{
-
//clamp the number of substeps, to prevent simulation grinding spiralling down to a halt
- int clampedSimulationSteps = (numSimulationSubSteps > maxSubSteps)? maxSubSteps : numSimulationSubSteps;
+ int clampedSimulationSteps = (numSimulationSubSteps > maxSubSteps) ? maxSubSteps : numSimulationSubSteps;
- saveKinematicState(fixedTimeStep*clampedSimulationSteps);
+ saveKinematicState(fixedTimeStep * clampedSimulationSteps);
applyGravity();
-
-
- for (int i=0;i<clampedSimulationSteps;i++)
+ for (int i = 0; i < clampedSimulationSteps; i++)
{
internalSingleStepSimulation(fixedTimeStep);
synchronizeMotionStates();
}
-
- } else
+ }
+ else
{
synchronizeMotionStates();
}
@@ -465,17 +444,17 @@ int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps,
#ifndef BT_NO_PROFILE
CProfileManager::Increment_Frame_Counter();
-#endif //BT_NO_PROFILE
+#endif //BT_NO_PROFILE
return numSimulationSubSteps;
}
-void btDiscreteDynamicsWorld::internalSingleStepSimulation(btScalar timeStep)
+void btDiscreteDynamicsWorld::internalSingleStepSimulation(btScalar timeStep)
{
-
BT_PROFILE("internalSingleStepSimulation");
- if(0 != m_internalPreTickCallback) {
+ if (0 != m_internalPreTickCallback)
+ {
(*m_internalPreTickCallback)(this, timeStep);
}
@@ -488,19 +467,15 @@ void btDiscreteDynamicsWorld::internalSingleStepSimulation(btScalar timeStep)
dispatchInfo.m_stepCount = 0;
dispatchInfo.m_debugDraw = getDebugDrawer();
-
- createPredictiveContacts(timeStep);
+ createPredictiveContacts(timeStep);
///perform collision detection
performDiscreteCollisionDetection();
calculateSimulationIslands();
-
getSolverInfo().m_timeStep = timeStep;
-
-
///solve contact and other joint constraints
solveConstraints(getSolverInfo());
@@ -513,37 +488,38 @@ void btDiscreteDynamicsWorld::internalSingleStepSimulation(btScalar timeStep)
///update vehicle simulation
updateActions(timeStep);
- updateActivationState( timeStep );
+ updateActivationState(timeStep);
- if(0 != m_internalTickCallback) {
+ if (0 != m_internalTickCallback)
+ {
(*m_internalTickCallback)(this, timeStep);
}
}
-void btDiscreteDynamicsWorld::setGravity(const btVector3& gravity)
+void btDiscreteDynamicsWorld::setGravity(const btVector3& gravity)
{
m_gravity = gravity;
- for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
+ for (int i = 0; i < m_nonStaticRigidBodies.size(); i++)
{
btRigidBody* body = m_nonStaticRigidBodies[i];
- if (body->isActive() && !(body->getFlags() &BT_DISABLE_WORLD_GRAVITY))
+ if (body->isActive() && !(body->getFlags() & BT_DISABLE_WORLD_GRAVITY))
{
body->setGravity(gravity);
}
}
}
-btVector3 btDiscreteDynamicsWorld::getGravity () const
+btVector3 btDiscreteDynamicsWorld::getGravity() const
{
return m_gravity;
}
-void btDiscreteDynamicsWorld::addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup, int collisionFilterMask)
+void btDiscreteDynamicsWorld::addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup, int collisionFilterMask)
{
- btCollisionWorld::addCollisionObject(collisionObject,collisionFilterGroup,collisionFilterMask);
+ btCollisionWorld::addCollisionObject(collisionObject, collisionFilterGroup, collisionFilterMask);
}
-void btDiscreteDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject)
+void btDiscreteDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject)
{
btRigidBody* body = btRigidBody::upcast(collisionObject);
if (body)
@@ -552,16 +528,15 @@ void btDiscreteDynamicsWorld::removeCollisionObject(btCollisionObject* collision
btCollisionWorld::removeCollisionObject(collisionObject);
}
-void btDiscreteDynamicsWorld::removeRigidBody(btRigidBody* body)
+void btDiscreteDynamicsWorld::removeRigidBody(btRigidBody* body)
{
m_nonStaticRigidBodies.remove(body);
btCollisionWorld::removeCollisionObject(body);
}
-
-void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body)
+void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body)
{
- if (!body->isStaticOrKinematicObject() && !(body->getFlags() &BT_DISABLE_WORLD_GRAVITY))
+ if (!body->isStaticOrKinematicObject() && !(body->getFlags() & BT_DISABLE_WORLD_GRAVITY))
{
body->setGravity(m_gravity);
}
@@ -571,22 +546,23 @@ void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body)
if (!body->isStaticObject())
{
m_nonStaticRigidBodies.push_back(body);
- } else
+ }
+ else
{
body->setActivationState(ISLAND_SLEEPING);
}
bool isDynamic = !(body->isStaticObject() || body->isKinematicObject());
- int collisionFilterGroup = isDynamic? int(btBroadphaseProxy::DefaultFilter) : int(btBroadphaseProxy::StaticFilter);
- int collisionFilterMask = isDynamic? int(btBroadphaseProxy::AllFilter) : int(btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter);
+ int collisionFilterGroup = isDynamic ? int(btBroadphaseProxy::DefaultFilter) : int(btBroadphaseProxy::StaticFilter);
+ int collisionFilterMask = isDynamic ? int(btBroadphaseProxy::AllFilter) : int(btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter);
- addCollisionObject(body,collisionFilterGroup,collisionFilterMask);
+ addCollisionObject(body, collisionFilterGroup, collisionFilterMask);
}
}
-void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body, int group, int mask)
+void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body, int group, int mask)
{
- if (!body->isStaticOrKinematicObject() && !(body->getFlags() &BT_DISABLE_WORLD_GRAVITY))
+ if (!body->isStaticOrKinematicObject() && !(body->getFlags() & BT_DISABLE_WORLD_GRAVITY))
{
body->setGravity(m_gravity);
}
@@ -597,31 +573,29 @@ void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body, int group, int mas
{
m_nonStaticRigidBodies.push_back(body);
}
- else
+ else
{
body->setActivationState(ISLAND_SLEEPING);
}
- addCollisionObject(body,group,mask);
+ addCollisionObject(body, group, mask);
}
}
-
-void btDiscreteDynamicsWorld::updateActions(btScalar timeStep)
+void btDiscreteDynamicsWorld::updateActions(btScalar timeStep)
{
BT_PROFILE("updateActions");
- for ( int i=0;i<m_actions.size();i++)
+ for (int i = 0; i < m_actions.size(); i++)
{
- m_actions[i]->updateAction( this, timeStep);
+ m_actions[i]->updateAction(this, timeStep);
}
}
-
-void btDiscreteDynamicsWorld::updateActivationState(btScalar timeStep)
+void btDiscreteDynamicsWorld::updateActivationState(btScalar timeStep)
{
BT_PROFILE("updateActivationState");
- for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
+ for (int i = 0; i < m_nonStaticRigidBodies.size(); i++)
{
btRigidBody* body = m_nonStaticRigidBodies[i];
if (body)
@@ -633,32 +607,33 @@ void btDiscreteDynamicsWorld::updateActivationState(btScalar timeStep)
if (body->isStaticOrKinematicObject())
{
body->setActivationState(ISLAND_SLEEPING);
- } else
+ }
+ else
{
if (body->getActivationState() == ACTIVE_TAG)
- body->setActivationState( WANTS_DEACTIVATION );
+ body->setActivationState(WANTS_DEACTIVATION);
if (body->getActivationState() == ISLAND_SLEEPING)
{
- body->setAngularVelocity(btVector3(0,0,0));
- body->setLinearVelocity(btVector3(0,0,0));
+ body->setAngularVelocity(btVector3(0, 0, 0));
+ body->setLinearVelocity(btVector3(0, 0, 0));
}
-
}
- } else
+ }
+ else
{
if (body->getActivationState() != DISABLE_DEACTIVATION)
- body->setActivationState( ACTIVE_TAG );
+ body->setActivationState(ACTIVE_TAG);
}
}
}
}
-void btDiscreteDynamicsWorld::addConstraint(btTypedConstraint* constraint,bool disableCollisionsBetweenLinkedBodies)
+void btDiscreteDynamicsWorld::addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies)
{
m_constraints.push_back(constraint);
- //Make sure the two bodies of a type constraint are different (possibly add this to the btTypedConstraint constructor?)
- btAssert(&constraint->getRigidBodyA()!=&constraint->getRigidBodyB());
-
+ //Make sure the two bodies of a type constraint are different (possibly add this to the btTypedConstraint constructor?)
+ btAssert(&constraint->getRigidBodyA() != &constraint->getRigidBodyB());
+
if (disableCollisionsBetweenLinkedBodies)
{
constraint->getRigidBodyA().addConstraintRef(constraint);
@@ -666,105 +641,98 @@ void btDiscreteDynamicsWorld::addConstraint(btTypedConstraint* constraint,bool d
}
}
-void btDiscreteDynamicsWorld::removeConstraint(btTypedConstraint* constraint)
+void btDiscreteDynamicsWorld::removeConstraint(btTypedConstraint* constraint)
{
m_constraints.remove(constraint);
constraint->getRigidBodyA().removeConstraintRef(constraint);
constraint->getRigidBodyB().removeConstraintRef(constraint);
}
-void btDiscreteDynamicsWorld::addAction(btActionInterface* action)
+void btDiscreteDynamicsWorld::addAction(btActionInterface* action)
{
m_actions.push_back(action);
}
-void btDiscreteDynamicsWorld::removeAction(btActionInterface* action)
+void btDiscreteDynamicsWorld::removeAction(btActionInterface* action)
{
m_actions.remove(action);
}
-
-void btDiscreteDynamicsWorld::addVehicle(btActionInterface* vehicle)
+void btDiscreteDynamicsWorld::addVehicle(btActionInterface* vehicle)
{
addAction(vehicle);
}
-void btDiscreteDynamicsWorld::removeVehicle(btActionInterface* vehicle)
+void btDiscreteDynamicsWorld::removeVehicle(btActionInterface* vehicle)
{
removeAction(vehicle);
}
-void btDiscreteDynamicsWorld::addCharacter(btActionInterface* character)
+void btDiscreteDynamicsWorld::addCharacter(btActionInterface* character)
{
addAction(character);
}
-void btDiscreteDynamicsWorld::removeCharacter(btActionInterface* character)
+void btDiscreteDynamicsWorld::removeCharacter(btActionInterface* character)
{
removeAction(character);
}
-
-
-
-void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
+void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
{
BT_PROFILE("solveConstraints");
- m_sortedConstraints.resize( m_constraints.size());
+ m_sortedConstraints.resize(m_constraints.size());
int i;
- for (i=0;i<getNumConstraints();i++)
+ for (i = 0; i < getNumConstraints(); i++)
{
m_sortedConstraints[i] = m_constraints[i];
}
-// btAssert(0);
-
-
+ // btAssert(0);
m_sortedConstraints.quickSort(btSortConstraintOnIslandPredicate());
btTypedConstraint** constraintsPtr = getNumConstraints() ? &m_sortedConstraints[0] : 0;
- m_solverIslandCallback->setup(&solverInfo,constraintsPtr,m_sortedConstraints.size(),getDebugDrawer());
+ m_solverIslandCallback->setup(&solverInfo, constraintsPtr, m_sortedConstraints.size(), getDebugDrawer());
m_constraintSolver->prepareSolve(getCollisionWorld()->getNumCollisionObjects(), getCollisionWorld()->getDispatcher()->getNumManifolds());
/// solve all the constraints for this island
- m_islandManager->buildAndProcessIslands(getCollisionWorld()->getDispatcher(),getCollisionWorld(),m_solverIslandCallback);
+ m_islandManager->buildAndProcessIslands(getCollisionWorld()->getDispatcher(), getCollisionWorld(), m_solverIslandCallback);
m_solverIslandCallback->processConstraints();
m_constraintSolver->allSolved(solverInfo, m_debugDrawer);
}
-
-void btDiscreteDynamicsWorld::calculateSimulationIslands()
+void btDiscreteDynamicsWorld::calculateSimulationIslands()
{
BT_PROFILE("calculateSimulationIslands");
- getSimulationIslandManager()->updateActivationState(getCollisionWorld(),getCollisionWorld()->getDispatcher());
+ getSimulationIslandManager()->updateActivationState(getCollisionWorld(), getCollisionWorld()->getDispatcher());
- {
- //merge islands based on speculative contact manifolds too
- for (int i=0;i<this->m_predictiveManifolds.size();i++)
- {
- btPersistentManifold* manifold = m_predictiveManifolds[i];
+ {
+ //merge islands based on speculative contact manifolds too
+ for (int i = 0; i < this->m_predictiveManifolds.size(); i++)
+ {
+ btPersistentManifold* manifold = m_predictiveManifolds[i];
- const btCollisionObject* colObj0 = manifold->getBody0();
- const btCollisionObject* colObj1 = manifold->getBody1();
+ const btCollisionObject* colObj0 = manifold->getBody0();
+ const btCollisionObject* colObj1 = manifold->getBody1();
- if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) &&
- ((colObj1) && (!(colObj1)->isStaticOrKinematicObject())))
- {
- getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(),(colObj1)->getIslandTag());
- }
- }
- }
+ if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) &&
+ ((colObj1) && (!(colObj1)->isStaticOrKinematicObject())))
+ {
+ getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(), (colObj1)->getIslandTag());
+ }
+ }
+ }
{
int i;
int numConstraints = int(m_constraints.size());
- for (i=0;i< numConstraints ; i++ )
+ for (i = 0; i < numConstraints; i++)
{
btTypedConstraint* constraint = m_constraints[i];
if (constraint->isEnabled())
@@ -775,7 +743,7 @@ void btDiscreteDynamicsWorld::calculateSimulationIslands()
if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) &&
((colObj1) && (!(colObj1)->isStaticOrKinematicObject())))
{
- getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(),(colObj1)->getIslandTag());
+ getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(), (colObj1)->getIslandTag());
}
}
}
@@ -783,51 +751,44 @@ void btDiscreteDynamicsWorld::calculateSimulationIslands()
//Store the island id in each body
getSimulationIslandManager()->storeIslandActivationState(getCollisionWorld());
-
-
}
-
-
-
class btClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback
{
public:
-
btCollisionObject* m_me;
btScalar m_allowedPenetration;
btOverlappingPairCache* m_pairCache;
btDispatcher* m_dispatcher;
public:
- btClosestNotMeConvexResultCallback (btCollisionObject* me,const btVector3& fromA,const btVector3& toA,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) :
- btCollisionWorld::ClosestConvexResultCallback(fromA,toA),
- m_me(me),
- m_allowedPenetration(0.0f),
- m_pairCache(pairCache),
- m_dispatcher(dispatcher)
+ btClosestNotMeConvexResultCallback(btCollisionObject* me, const btVector3& fromA, const btVector3& toA, btOverlappingPairCache* pairCache, btDispatcher* dispatcher) : btCollisionWorld::ClosestConvexResultCallback(fromA, toA),
+ m_me(me),
+ m_allowedPenetration(0.0f),
+ m_pairCache(pairCache),
+ m_dispatcher(dispatcher)
{
}
- virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult,bool normalInWorldSpace)
+ virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult, bool normalInWorldSpace)
{
if (convexResult.m_hitCollisionObject == m_me)
return 1.0f;
//ignore result if there is no contact response
- if(!convexResult.m_hitCollisionObject->hasContactResponse())
+ if (!convexResult.m_hitCollisionObject->hasContactResponse())
return 1.0f;
- btVector3 linVelA,linVelB;
- linVelA = m_convexToWorld-m_convexFromWorld;
- linVelB = btVector3(0,0,0);//toB.getOrigin()-fromB.getOrigin();
+ btVector3 linVelA, linVelB;
+ linVelA = m_convexToWorld - m_convexFromWorld;
+ linVelB = btVector3(0, 0, 0); //toB.getOrigin()-fromB.getOrigin();
- btVector3 relativeVelocity = (linVelA-linVelB);
+ btVector3 relativeVelocity = (linVelA - linVelB);
//don't report time of impact for motion away from the contact normal (or causes minor penetration)
- if (convexResult.m_hitNormalLocal.dot(relativeVelocity)>=-m_allowedPenetration)
+ if (convexResult.m_hitNormalLocal.dot(relativeVelocity) >= -m_allowedPenetration)
return 1.f;
- return ClosestConvexResultCallback::addSingleResult (convexResult, normalInWorldSpace);
+ return ClosestConvexResultCallback::addSingleResult(convexResult, normalInWorldSpace);
}
virtual bool needsCollision(btBroadphaseProxy* proxy0) const
@@ -840,13 +801,13 @@ public:
if (!ClosestConvexResultCallback::needsCollision(proxy0))
return false;
- btCollisionObject* otherObj = (btCollisionObject*) proxy0->m_clientObject;
+ btCollisionObject* otherObj = (btCollisionObject*)proxy0->m_clientObject;
- if(!m_dispatcher->needsCollision(m_me, otherObj))
+ if (!m_dispatcher->needsCollision(m_me, otherObj))
return false;
//call needsResponse, see http://code.google.com/p/bullet/issues/detail?id=179
- if (m_dispatcher->needsResponse(m_me,otherObj))
+ if (m_dispatcher->needsResponse(m_me, otherObj))
{
#if 0
///don't do CCD when there are already contact points (touching contact/penetration)
@@ -872,28 +833,24 @@ public:
return false;
}
-
-
};
///internal debugging variable. this value shouldn't be too high
-int gNumClampedCcdMotions=0;
-
+int gNumClampedCcdMotions = 0;
-void btDiscreteDynamicsWorld::createPredictiveContactsInternal( btRigidBody** bodies, int numBodies, btScalar timeStep)
+void btDiscreteDynamicsWorld::createPredictiveContactsInternal(btRigidBody** bodies, int numBodies, btScalar timeStep)
{
btTransform predictedTrans;
- for ( int i=0;i<numBodies;i++)
+ for (int i = 0; i < numBodies; i++)
{
btRigidBody* body = bodies[i];
body->setHitFraction(1.f);
if (body->isActive() && (!body->isStaticOrKinematicObject()))
{
-
body->predictIntegratedTransform(timeStep, predictedTrans);
- btScalar squareMotion = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin()).length2();
+ btScalar squareMotion = (predictedTrans.getOrigin() - body->getWorldTransform().getOrigin()).length2();
if (getDispatchInfo().m_useContinuous && body->getCcdSquareMotionThreshold() && body->getCcdSquareMotionThreshold() < squareMotion)
{
@@ -905,60 +862,55 @@ void btDiscreteDynamicsWorld::createPredictiveContactsInternal( btRigidBody** bo
class StaticOnlyCallback : public btClosestNotMeConvexResultCallback
{
public:
-
- StaticOnlyCallback (btCollisionObject* me,const btVector3& fromA,const btVector3& toA,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) :
- btClosestNotMeConvexResultCallback(me,fromA,toA,pairCache,dispatcher)
+ StaticOnlyCallback(btCollisionObject* me, const btVector3& fromA, const btVector3& toA, btOverlappingPairCache* pairCache, btDispatcher* dispatcher) : btClosestNotMeConvexResultCallback(me, fromA, toA, pairCache, dispatcher)
{
}
- virtual bool needsCollision(btBroadphaseProxy* proxy0) const
+ virtual bool needsCollision(btBroadphaseProxy* proxy0) const
{
- btCollisionObject* otherObj = (btCollisionObject*) proxy0->m_clientObject;
+ btCollisionObject* otherObj = (btCollisionObject*)proxy0->m_clientObject;
if (!otherObj->isStaticOrKinematicObject())
return false;
return btClosestNotMeConvexResultCallback::needsCollision(proxy0);
}
};
- StaticOnlyCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher());
+ StaticOnlyCallback sweepResults(body, body->getWorldTransform().getOrigin(), predictedTrans.getOrigin(), getBroadphase()->getOverlappingPairCache(), getDispatcher());
#else
- btClosestNotMeConvexResultCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher());
+ btClosestNotMeConvexResultCallback sweepResults(body, body->getWorldTransform().getOrigin(), predictedTrans.getOrigin(), getBroadphase()->getOverlappingPairCache(), getDispatcher());
#endif
//btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
- btSphereShape tmpSphere(body->getCcdSweptSphereRadius());//btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
- sweepResults.m_allowedPenetration=getDispatchInfo().m_allowedCcdPenetration;
+ btSphereShape tmpSphere(body->getCcdSweptSphereRadius()); //btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
+ sweepResults.m_allowedPenetration = getDispatchInfo().m_allowedCcdPenetration;
sweepResults.m_collisionFilterGroup = body->getBroadphaseProxy()->m_collisionFilterGroup;
- sweepResults.m_collisionFilterMask = body->getBroadphaseProxy()->m_collisionFilterMask;
+ sweepResults.m_collisionFilterMask = body->getBroadphaseProxy()->m_collisionFilterMask;
btTransform modifiedPredictedTrans = predictedTrans;
modifiedPredictedTrans.setBasis(body->getWorldTransform().getBasis());
- convexSweepTest(&tmpSphere,body->getWorldTransform(),modifiedPredictedTrans,sweepResults);
+ convexSweepTest(&tmpSphere, body->getWorldTransform(), modifiedPredictedTrans, sweepResults);
if (sweepResults.hasHit() && (sweepResults.m_closestHitFraction < 1.f))
{
-
- btVector3 distVec = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin())*sweepResults.m_closestHitFraction;
+ btVector3 distVec = (predictedTrans.getOrigin() - body->getWorldTransform().getOrigin()) * sweepResults.m_closestHitFraction;
btScalar distance = distVec.dot(-sweepResults.m_hitNormalWorld);
-
- btPersistentManifold* manifold = m_dispatcher1->getNewManifold(body,sweepResults.m_hitCollisionObject);
- btMutexLock( &m_predictiveManifoldsMutex );
+ btPersistentManifold* manifold = m_dispatcher1->getNewManifold(body, sweepResults.m_hitCollisionObject);
+ btMutexLock(&m_predictiveManifoldsMutex);
m_predictiveManifolds.push_back(manifold);
- btMutexUnlock( &m_predictiveManifoldsMutex );
+ btMutexUnlock(&m_predictiveManifoldsMutex);
- btVector3 worldPointB = body->getWorldTransform().getOrigin()+distVec;
- btVector3 localPointB = sweepResults.m_hitCollisionObject->getWorldTransform().inverse()*worldPointB;
+ btVector3 worldPointB = body->getWorldTransform().getOrigin() + distVec;
+ btVector3 localPointB = sweepResults.m_hitCollisionObject->getWorldTransform().inverse() * worldPointB;
- btManifoldPoint newPoint(btVector3(0,0,0), localPointB,sweepResults.m_hitNormalWorld,distance);
+ btManifoldPoint newPoint(btVector3(0, 0, 0), localPointB, sweepResults.m_hitNormalWorld, distance);
bool isPredictive = true;
int index = manifold->addManifoldPoint(newPoint, isPredictive);
btManifoldPoint& pt = manifold->getContactPoint(index);
pt.m_combinedRestitution = 0;
- pt.m_combinedFriction = gCalculateCombinedFrictionCallback(body,sweepResults.m_hitCollisionObject);
+ pt.m_combinedFriction = gCalculateCombinedFrictionCallback(body, sweepResults.m_hitCollisionObject);
pt.m_positionWorldOnA = body->getWorldTransform().getOrigin();
pt.m_positionWorldOnB = worldPointB;
-
}
}
}
@@ -968,42 +920,39 @@ void btDiscreteDynamicsWorld::createPredictiveContactsInternal( btRigidBody** bo
void btDiscreteDynamicsWorld::releasePredictiveContacts()
{
- BT_PROFILE( "release predictive contact manifolds" );
-
- for ( int i = 0; i < m_predictiveManifolds.size(); i++ )
- {
- btPersistentManifold* manifold = m_predictiveManifolds[ i ];
- this->m_dispatcher1->releaseManifold( manifold );
- }
- m_predictiveManifolds.clear();
+ BT_PROFILE("release predictive contact manifolds");
+
+ for (int i = 0; i < m_predictiveManifolds.size(); i++)
+ {
+ btPersistentManifold* manifold = m_predictiveManifolds[i];
+ this->m_dispatcher1->releaseManifold(manifold);
+ }
+ m_predictiveManifolds.clear();
}
void btDiscreteDynamicsWorld::createPredictiveContacts(btScalar timeStep)
{
BT_PROFILE("createPredictiveContacts");
- releasePredictiveContacts();
- if (m_nonStaticRigidBodies.size() > 0)
- {
- createPredictiveContactsInternal( &m_nonStaticRigidBodies[ 0 ], m_nonStaticRigidBodies.size(), timeStep );
- }
+ releasePredictiveContacts();
+ if (m_nonStaticRigidBodies.size() > 0)
+ {
+ createPredictiveContactsInternal(&m_nonStaticRigidBodies[0], m_nonStaticRigidBodies.size(), timeStep);
+ }
}
-void btDiscreteDynamicsWorld::integrateTransformsInternal( btRigidBody** bodies, int numBodies, btScalar timeStep )
+void btDiscreteDynamicsWorld::integrateTransformsInternal(btRigidBody** bodies, int numBodies, btScalar timeStep)
{
btTransform predictedTrans;
- for (int i=0;i<numBodies;i++)
+ for (int i = 0; i < numBodies; i++)
{
btRigidBody* body = bodies[i];
body->setHitFraction(1.f);
if (body->isActive() && (!body->isStaticOrKinematicObject()))
{
-
body->predictIntegratedTransform(timeStep, predictedTrans);
- btScalar squareMotion = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin()).length2();
-
-
+ btScalar squareMotion = (predictedTrans.getOrigin() - body->getWorldTransform().getOrigin()).length2();
if (getDispatchInfo().m_useContinuous && body->getCcdSquareMotionThreshold() && body->getCcdSquareMotionThreshold() < squareMotion)
{
@@ -1015,43 +964,40 @@ void btDiscreteDynamicsWorld::integrateTransformsInternal( btRigidBody** bodies,
class StaticOnlyCallback : public btClosestNotMeConvexResultCallback
{
public:
-
- StaticOnlyCallback (btCollisionObject* me,const btVector3& fromA,const btVector3& toA,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) :
- btClosestNotMeConvexResultCallback(me,fromA,toA,pairCache,dispatcher)
+ StaticOnlyCallback(btCollisionObject* me, const btVector3& fromA, const btVector3& toA, btOverlappingPairCache* pairCache, btDispatcher* dispatcher) : btClosestNotMeConvexResultCallback(me, fromA, toA, pairCache, dispatcher)
{
}
- virtual bool needsCollision(btBroadphaseProxy* proxy0) const
+ virtual bool needsCollision(btBroadphaseProxy* proxy0) const
{
- btCollisionObject* otherObj = (btCollisionObject*) proxy0->m_clientObject;
+ btCollisionObject* otherObj = (btCollisionObject*)proxy0->m_clientObject;
if (!otherObj->isStaticOrKinematicObject())
return false;
return btClosestNotMeConvexResultCallback::needsCollision(proxy0);
}
};
- StaticOnlyCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher());
+ StaticOnlyCallback sweepResults(body, body->getWorldTransform().getOrigin(), predictedTrans.getOrigin(), getBroadphase()->getOverlappingPairCache(), getDispatcher());
#else
- btClosestNotMeConvexResultCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher());
+ btClosestNotMeConvexResultCallback sweepResults(body, body->getWorldTransform().getOrigin(), predictedTrans.getOrigin(), getBroadphase()->getOverlappingPairCache(), getDispatcher());
#endif
//btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
- btSphereShape tmpSphere(body->getCcdSweptSphereRadius());//btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
- sweepResults.m_allowedPenetration=getDispatchInfo().m_allowedCcdPenetration;
+ btSphereShape tmpSphere(body->getCcdSweptSphereRadius()); //btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
+ sweepResults.m_allowedPenetration = getDispatchInfo().m_allowedCcdPenetration;
sweepResults.m_collisionFilterGroup = body->getBroadphaseProxy()->m_collisionFilterGroup;
- sweepResults.m_collisionFilterMask = body->getBroadphaseProxy()->m_collisionFilterMask;
+ sweepResults.m_collisionFilterMask = body->getBroadphaseProxy()->m_collisionFilterMask;
btTransform modifiedPredictedTrans = predictedTrans;
modifiedPredictedTrans.setBasis(body->getWorldTransform().getBasis());
- convexSweepTest(&tmpSphere,body->getWorldTransform(),modifiedPredictedTrans,sweepResults);
+ convexSweepTest(&tmpSphere, body->getWorldTransform(), modifiedPredictedTrans, sweepResults);
if (sweepResults.hasHit() && (sweepResults.m_closestHitFraction < 1.f))
{
-
//printf("clamped integration to hit fraction = %f\n",fraction);
body->setHitFraction(sweepResults.m_closestHitFraction);
- body->predictIntegratedTransform(timeStep*body->getHitFraction(), predictedTrans);
+ body->predictIntegratedTransform(timeStep * body->getHitFraction(), predictedTrans);
body->setHitFraction(0.f);
- body->proceedToTransform( predictedTrans);
+ body->proceedToTransform(predictedTrans);
#if 0
btVector3 linVel = body->getLinearVelocity();
@@ -1078,50 +1024,45 @@ void btDiscreteDynamicsWorld::integrateTransformsInternal( btRigidBody** bodies,
//btScalar depth = 0.f;
//appliedImpulse = resolveSingleCollision(body,(btCollisionObject*)sweepResults.m_hitCollisionObject,sweepResults.m_hitPointWorld,sweepResults.m_hitNormalWorld,getSolverInfo(), depth);
-
#endif
- continue;
+ continue;
}
}
}
-
- body->proceedToTransform( predictedTrans);
-
+ body->proceedToTransform(predictedTrans);
}
-
}
-
}
void btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep)
{
BT_PROFILE("integrateTransforms");
- if (m_nonStaticRigidBodies.size() > 0)
- {
- integrateTransformsInternal(&m_nonStaticRigidBodies[0], m_nonStaticRigidBodies.size(), timeStep);
- }
+ if (m_nonStaticRigidBodies.size() > 0)
+ {
+ integrateTransformsInternal(&m_nonStaticRigidBodies[0], m_nonStaticRigidBodies.size(), timeStep);
+ }
- ///this should probably be switched on by default, but it is not well tested yet
+ ///this should probably be switched on by default, but it is not well tested yet
if (m_applySpeculativeContactRestitution)
{
BT_PROFILE("apply speculative contact restitution");
- for (int i=0;i<m_predictiveManifolds.size();i++)
+ for (int i = 0; i < m_predictiveManifolds.size(); i++)
{
btPersistentManifold* manifold = m_predictiveManifolds[i];
btRigidBody* body0 = btRigidBody::upcast((btCollisionObject*)manifold->getBody0());
btRigidBody* body1 = btRigidBody::upcast((btCollisionObject*)manifold->getBody1());
- for (int p=0;p<manifold->getNumContacts();p++)
+ for (int p = 0; p < manifold->getNumContacts(); p++)
{
const btManifoldPoint& pt = manifold->getContactPoint(p);
btScalar combinedRestitution = gCalculateCombinedRestitutionCallback(body0, body1);
- if (combinedRestitution>0 && pt.m_appliedImpulse != 0.f)
+ if (combinedRestitution > 0 && pt.m_appliedImpulse != 0.f)
//if (pt.getDistance()>0 && combinedRestitution>0 && pt.m_appliedImpulse != 0.f)
{
- btVector3 imp = -pt.m_normalWorldOnB * pt.m_appliedImpulse* combinedRestitution;
+ btVector3 imp = -pt.m_normalWorldOnB * pt.m_appliedImpulse * combinedRestitution;
const btVector3& pos1 = pt.getPositionWorldOnA();
const btVector3& pos2 = pt.getPositionWorldOnB();
@@ -1130,23 +1071,19 @@ void btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep)
btVector3 rel_pos1 = pos2 - body1->getWorldTransform().getOrigin();
if (body0)
- body0->applyImpulse(imp,rel_pos0);
+ body0->applyImpulse(imp, rel_pos0);
if (body1)
- body1->applyImpulse(-imp,rel_pos1);
+ body1->applyImpulse(-imp, rel_pos1);
}
}
}
}
}
-
-
-
-
-void btDiscreteDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
+void btDiscreteDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
{
BT_PROFILE("predictUnconstraintMotion");
- for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
+ for (int i = 0; i < m_nonStaticRigidBodies.size(); i++)
{
btRigidBody* body = m_nonStaticRigidBodies[i];
if (!body->isStaticOrKinematicObject())
@@ -1155,179 +1092,171 @@ void btDiscreteDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
body->applyDamping(timeStep);
- body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform());
+ body->predictIntegratedTransform(timeStep, body->getInterpolationWorldTransform());
}
}
}
-
-void btDiscreteDynamicsWorld::startProfiling(btScalar timeStep)
+void btDiscreteDynamicsWorld::startProfiling(btScalar timeStep)
{
(void)timeStep;
#ifndef BT_NO_PROFILE
CProfileManager::Reset();
-#endif //BT_NO_PROFILE
-
+#endif //BT_NO_PROFILE
}
-
-
-
-
-
void btDiscreteDynamicsWorld::debugDrawConstraint(btTypedConstraint* constraint)
{
bool drawFrames = (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawConstraints) != 0;
bool drawLimits = (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawConstraintLimits) != 0;
btScalar dbgDrawSize = constraint->getDbgDrawSize();
- if(dbgDrawSize <= btScalar(0.f))
+ if (dbgDrawSize <= btScalar(0.f))
{
return;
}
- switch(constraint->getConstraintType())
+ switch (constraint->getConstraintType())
{
case POINT2POINT_CONSTRAINT_TYPE:
+ {
+ btPoint2PointConstraint* p2pC = (btPoint2PointConstraint*)constraint;
+ btTransform tr;
+ tr.setIdentity();
+ btVector3 pivot = p2pC->getPivotInA();
+ pivot = p2pC->getRigidBodyA().getCenterOfMassTransform() * pivot;
+ tr.setOrigin(pivot);
+ getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+ // that ideally should draw the same frame
+ pivot = p2pC->getPivotInB();
+ pivot = p2pC->getRigidBodyB().getCenterOfMassTransform() * pivot;
+ tr.setOrigin(pivot);
+ if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+ }
+ break;
+ case HINGE_CONSTRAINT_TYPE:
+ {
+ btHingeConstraint* pHinge = (btHingeConstraint*)constraint;
+ btTransform tr = pHinge->getRigidBodyA().getCenterOfMassTransform() * pHinge->getAFrame();
+ if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+ tr = pHinge->getRigidBodyB().getCenterOfMassTransform() * pHinge->getBFrame();
+ if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+ btScalar minAng = pHinge->getLowerLimit();
+ btScalar maxAng = pHinge->getUpperLimit();
+ if (minAng == maxAng)
{
- btPoint2PointConstraint* p2pC = (btPoint2PointConstraint*)constraint;
- btTransform tr;
- tr.setIdentity();
- btVector3 pivot = p2pC->getPivotInA();
- pivot = p2pC->getRigidBodyA().getCenterOfMassTransform() * pivot;
- tr.setOrigin(pivot);
- getDebugDrawer()->drawTransform(tr, dbgDrawSize);
- // that ideally should draw the same frame
- pivot = p2pC->getPivotInB();
- pivot = p2pC->getRigidBodyB().getCenterOfMassTransform() * pivot;
- tr.setOrigin(pivot);
- if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+ break;
}
- break;
- case HINGE_CONSTRAINT_TYPE:
+ bool drawSect = true;
+ if (!pHinge->hasLimit())
{
- btHingeConstraint* pHinge = (btHingeConstraint*)constraint;
- btTransform tr = pHinge->getRigidBodyA().getCenterOfMassTransform() * pHinge->getAFrame();
- if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
- tr = pHinge->getRigidBodyB().getCenterOfMassTransform() * pHinge->getBFrame();
- if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
- btScalar minAng = pHinge->getLowerLimit();
- btScalar maxAng = pHinge->getUpperLimit();
- if(minAng == maxAng)
- {
- break;
- }
- bool drawSect = true;
- if(!pHinge->hasLimit())
- {
- minAng = btScalar(0.f);
- maxAng = SIMD_2_PI;
- drawSect = false;
- }
- if(drawLimits)
- {
- btVector3& center = tr.getOrigin();
- btVector3 normal = tr.getBasis().getColumn(2);
- btVector3 axis = tr.getBasis().getColumn(0);
- getDebugDrawer()->drawArc(center, normal, axis, dbgDrawSize, dbgDrawSize, minAng, maxAng, btVector3(0,0,0), drawSect);
- }
+ minAng = btScalar(0.f);
+ maxAng = SIMD_2_PI;
+ drawSect = false;
}
- break;
+ if (drawLimits)
+ {
+ btVector3& center = tr.getOrigin();
+ btVector3 normal = tr.getBasis().getColumn(2);
+ btVector3 axis = tr.getBasis().getColumn(0);
+ getDebugDrawer()->drawArc(center, normal, axis, dbgDrawSize, dbgDrawSize, minAng, maxAng, btVector3(0, 0, 0), drawSect);
+ }
+ }
+ break;
case CONETWIST_CONSTRAINT_TYPE:
+ {
+ btConeTwistConstraint* pCT = (btConeTwistConstraint*)constraint;
+ btTransform tr = pCT->getRigidBodyA().getCenterOfMassTransform() * pCT->getAFrame();
+ if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+ tr = pCT->getRigidBodyB().getCenterOfMassTransform() * pCT->getBFrame();
+ if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+ if (drawLimits)
{
- btConeTwistConstraint* pCT = (btConeTwistConstraint*)constraint;
- btTransform tr = pCT->getRigidBodyA().getCenterOfMassTransform() * pCT->getAFrame();
- if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
- tr = pCT->getRigidBodyB().getCenterOfMassTransform() * pCT->getBFrame();
- if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
- if(drawLimits)
+ //const btScalar length = btScalar(5);
+ const btScalar length = dbgDrawSize;
+ static int nSegments = 8 * 4;
+ btScalar fAngleInRadians = btScalar(2. * 3.1415926) * (btScalar)(nSegments - 1) / btScalar(nSegments);
+ btVector3 pPrev = pCT->GetPointForAngle(fAngleInRadians, length);
+ pPrev = tr * pPrev;
+ for (int i = 0; i < nSegments; i++)
{
- //const btScalar length = btScalar(5);
- const btScalar length = dbgDrawSize;
- static int nSegments = 8*4;
- btScalar fAngleInRadians = btScalar(2.*3.1415926) * (btScalar)(nSegments-1)/btScalar(nSegments);
- btVector3 pPrev = pCT->GetPointForAngle(fAngleInRadians, length);
- pPrev = tr * pPrev;
- for (int i=0; i<nSegments; i++)
- {
- fAngleInRadians = btScalar(2.*3.1415926) * (btScalar)i/btScalar(nSegments);
- btVector3 pCur = pCT->GetPointForAngle(fAngleInRadians, length);
- pCur = tr * pCur;
- getDebugDrawer()->drawLine(pPrev, pCur, btVector3(0,0,0));
-
- if (i%(nSegments/8) == 0)
- getDebugDrawer()->drawLine(tr.getOrigin(), pCur, btVector3(0,0,0));
+ fAngleInRadians = btScalar(2. * 3.1415926) * (btScalar)i / btScalar(nSegments);
+ btVector3 pCur = pCT->GetPointForAngle(fAngleInRadians, length);
+ pCur = tr * pCur;
+ getDebugDrawer()->drawLine(pPrev, pCur, btVector3(0, 0, 0));
- pPrev = pCur;
- }
- btScalar tws = pCT->getTwistSpan();
- btScalar twa = pCT->getTwistAngle();
- bool useFrameB = (pCT->getRigidBodyB().getInvMass() > btScalar(0.f));
- if(useFrameB)
- {
- tr = pCT->getRigidBodyB().getCenterOfMassTransform() * pCT->getBFrame();
- }
- else
- {
- tr = pCT->getRigidBodyA().getCenterOfMassTransform() * pCT->getAFrame();
- }
- btVector3 pivot = tr.getOrigin();
- btVector3 normal = tr.getBasis().getColumn(0);
- btVector3 axis1 = tr.getBasis().getColumn(1);
- getDebugDrawer()->drawArc(pivot, normal, axis1, dbgDrawSize, dbgDrawSize, -twa-tws, -twa+tws, btVector3(0,0,0), true);
+ if (i % (nSegments / 8) == 0)
+ getDebugDrawer()->drawLine(tr.getOrigin(), pCur, btVector3(0, 0, 0));
+ pPrev = pCur;
+ }
+ btScalar tws = pCT->getTwistSpan();
+ btScalar twa = pCT->getTwistAngle();
+ bool useFrameB = (pCT->getRigidBodyB().getInvMass() > btScalar(0.f));
+ if (useFrameB)
+ {
+ tr = pCT->getRigidBodyB().getCenterOfMassTransform() * pCT->getBFrame();
}
+ else
+ {
+ tr = pCT->getRigidBodyA().getCenterOfMassTransform() * pCT->getAFrame();
+ }
+ btVector3 pivot = tr.getOrigin();
+ btVector3 normal = tr.getBasis().getColumn(0);
+ btVector3 axis1 = tr.getBasis().getColumn(1);
+ getDebugDrawer()->drawArc(pivot, normal, axis1, dbgDrawSize, dbgDrawSize, -twa - tws, -twa + tws, btVector3(0, 0, 0), true);
}
- break;
+ }
+ break;
case D6_SPRING_CONSTRAINT_TYPE:
case D6_CONSTRAINT_TYPE:
+ {
+ btGeneric6DofConstraint* p6DOF = (btGeneric6DofConstraint*)constraint;
+ btTransform tr = p6DOF->getCalculatedTransformA();
+ if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+ tr = p6DOF->getCalculatedTransformB();
+ if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+ if (drawLimits)
{
- btGeneric6DofConstraint* p6DOF = (btGeneric6DofConstraint*)constraint;
- btTransform tr = p6DOF->getCalculatedTransformA();
- if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+ tr = p6DOF->getCalculatedTransformA();
+ const btVector3& center = p6DOF->getCalculatedTransformB().getOrigin();
+ btVector3 up = tr.getBasis().getColumn(2);
+ btVector3 axis = tr.getBasis().getColumn(0);
+ btScalar minTh = p6DOF->getRotationalLimitMotor(1)->m_loLimit;
+ btScalar maxTh = p6DOF->getRotationalLimitMotor(1)->m_hiLimit;
+ btScalar minPs = p6DOF->getRotationalLimitMotor(2)->m_loLimit;
+ btScalar maxPs = p6DOF->getRotationalLimitMotor(2)->m_hiLimit;
+ getDebugDrawer()->drawSpherePatch(center, up, axis, dbgDrawSize * btScalar(.9f), minTh, maxTh, minPs, maxPs, btVector3(0, 0, 0));
+ axis = tr.getBasis().getColumn(1);
+ btScalar ay = p6DOF->getAngle(1);
+ btScalar az = p6DOF->getAngle(2);
+ btScalar cy = btCos(ay);
+ btScalar sy = btSin(ay);
+ btScalar cz = btCos(az);
+ btScalar sz = btSin(az);
+ btVector3 ref;
+ ref[0] = cy * cz * axis[0] + cy * sz * axis[1] - sy * axis[2];
+ ref[1] = -sz * axis[0] + cz * axis[1];
+ ref[2] = cz * sy * axis[0] + sz * sy * axis[1] + cy * axis[2];
tr = p6DOF->getCalculatedTransformB();
- if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
- if(drawLimits)
+ btVector3 normal = -tr.getBasis().getColumn(0);
+ btScalar minFi = p6DOF->getRotationalLimitMotor(0)->m_loLimit;
+ btScalar maxFi = p6DOF->getRotationalLimitMotor(0)->m_hiLimit;
+ if (minFi > maxFi)
{
- tr = p6DOF->getCalculatedTransformA();
- const btVector3& center = p6DOF->getCalculatedTransformB().getOrigin();
- btVector3 up = tr.getBasis().getColumn(2);
- btVector3 axis = tr.getBasis().getColumn(0);
- btScalar minTh = p6DOF->getRotationalLimitMotor(1)->m_loLimit;
- btScalar maxTh = p6DOF->getRotationalLimitMotor(1)->m_hiLimit;
- btScalar minPs = p6DOF->getRotationalLimitMotor(2)->m_loLimit;
- btScalar maxPs = p6DOF->getRotationalLimitMotor(2)->m_hiLimit;
- getDebugDrawer()->drawSpherePatch(center, up, axis, dbgDrawSize * btScalar(.9f), minTh, maxTh, minPs, maxPs, btVector3(0,0,0));
- axis = tr.getBasis().getColumn(1);
- btScalar ay = p6DOF->getAngle(1);
- btScalar az = p6DOF->getAngle(2);
- btScalar cy = btCos(ay);
- btScalar sy = btSin(ay);
- btScalar cz = btCos(az);
- btScalar sz = btSin(az);
- btVector3 ref;
- ref[0] = cy*cz*axis[0] + cy*sz*axis[1] - sy*axis[2];
- ref[1] = -sz*axis[0] + cz*axis[1];
- ref[2] = cz*sy*axis[0] + sz*sy*axis[1] + cy*axis[2];
- tr = p6DOF->getCalculatedTransformB();
- btVector3 normal = -tr.getBasis().getColumn(0);
- btScalar minFi = p6DOF->getRotationalLimitMotor(0)->m_loLimit;
- btScalar maxFi = p6DOF->getRotationalLimitMotor(0)->m_hiLimit;
- if(minFi > maxFi)
- {
- getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, -SIMD_PI, SIMD_PI, btVector3(0,0,0), false);
- }
- else if(minFi < maxFi)
- {
- getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, minFi, maxFi, btVector3(0,0,0), true);
- }
- tr = p6DOF->getCalculatedTransformA();
- btVector3 bbMin = p6DOF->getTranslationalLimitMotor()->m_lowerLimit;
- btVector3 bbMax = p6DOF->getTranslationalLimitMotor()->m_upperLimit;
- getDebugDrawer()->drawBox(bbMin, bbMax, tr, btVector3(0,0,0));
+ getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, -SIMD_PI, SIMD_PI, btVector3(0, 0, 0), false);
}
+ else if (minFi < maxFi)
+ {
+ getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, minFi, maxFi, btVector3(0, 0, 0), true);
+ }
+ tr = p6DOF->getCalculatedTransformA();
+ btVector3 bbMin = p6DOF->getTranslationalLimitMotor()->m_lowerLimit;
+ btVector3 bbMax = p6DOF->getTranslationalLimitMotor()->m_upperLimit;
+ getDebugDrawer()->drawBox(bbMin, bbMax, tr, btVector3(0, 0, 0));
}
- break;
+ }
+ break;
///note: the code for D6_SPRING_2_CONSTRAINT_TYPE is identical to D6_CONSTRAINT_TYPE, the D6_CONSTRAINT_TYPE+D6_SPRING_CONSTRAINT_TYPE will likely become obsolete/deprecated at some stage
case D6_SPRING_2_CONSTRAINT_TYPE:
{
@@ -1359,9 +1288,9 @@ void btDiscreteDynamicsWorld::debugDrawConstraint(btTypedConstraint* constraint)
btScalar cz = btCos(az);
btScalar sz = btSin(az);
btVector3 ref;
- ref[0] = cy*cz*axis[0] + cy*sz*axis[1] - sy*axis[2];
- ref[1] = -sz*axis[0] + cz*axis[1];
- ref[2] = cz*sy*axis[0] + sz*sy*axis[1] + cy*axis[2];
+ ref[0] = cy * cz * axis[0] + cy * sz * axis[1] - sy * axis[2];
+ ref[1] = -sz * axis[0] + cz * axis[1];
+ ref[2] = cz * sy * axis[0] + sz * sy * axis[1] + cy * axis[2];
tr = p6DOF->getCalculatedTransformB();
btVector3 normal = -tr.getBasis().getColumn(0);
btScalar minFi = p6DOF->getRotationalLimitMotor(0)->m_loLimit;
@@ -1383,42 +1312,38 @@ void btDiscreteDynamicsWorld::debugDrawConstraint(btTypedConstraint* constraint)
break;
}
case SLIDER_CONSTRAINT_TYPE:
+ {
+ btSliderConstraint* pSlider = (btSliderConstraint*)constraint;
+ btTransform tr = pSlider->getCalculatedTransformA();
+ if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+ tr = pSlider->getCalculatedTransformB();
+ if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+ if (drawLimits)
{
- btSliderConstraint* pSlider = (btSliderConstraint*)constraint;
- btTransform tr = pSlider->getCalculatedTransformA();
- if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
- tr = pSlider->getCalculatedTransformB();
- if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
- if(drawLimits)
- {
- btTransform tr = pSlider->getUseLinearReferenceFrameA() ? pSlider->getCalculatedTransformA() : pSlider->getCalculatedTransformB();
- btVector3 li_min = tr * btVector3(pSlider->getLowerLinLimit(), 0.f, 0.f);
- btVector3 li_max = tr * btVector3(pSlider->getUpperLinLimit(), 0.f, 0.f);
- getDebugDrawer()->drawLine(li_min, li_max, btVector3(0, 0, 0));
- btVector3 normal = tr.getBasis().getColumn(0);
- btVector3 axis = tr.getBasis().getColumn(1);
- btScalar a_min = pSlider->getLowerAngLimit();
- btScalar a_max = pSlider->getUpperAngLimit();
- const btVector3& center = pSlider->getCalculatedTransformB().getOrigin();
- getDebugDrawer()->drawArc(center, normal, axis, dbgDrawSize, dbgDrawSize, a_min, a_max, btVector3(0,0,0), true);
- }
+ btTransform tr = pSlider->getUseLinearReferenceFrameA() ? pSlider->getCalculatedTransformA() : pSlider->getCalculatedTransformB();
+ btVector3 li_min = tr * btVector3(pSlider->getLowerLinLimit(), 0.f, 0.f);
+ btVector3 li_max = tr * btVector3(pSlider->getUpperLinLimit(), 0.f, 0.f);
+ getDebugDrawer()->drawLine(li_min, li_max, btVector3(0, 0, 0));
+ btVector3 normal = tr.getBasis().getColumn(0);
+ btVector3 axis = tr.getBasis().getColumn(1);
+ btScalar a_min = pSlider->getLowerAngLimit();
+ btScalar a_max = pSlider->getUpperAngLimit();
+ const btVector3& center = pSlider->getCalculatedTransformB().getOrigin();
+ getDebugDrawer()->drawArc(center, normal, axis, dbgDrawSize, dbgDrawSize, a_min, a_max, btVector3(0, 0, 0), true);
}
- break;
- default :
+ }
+ break;
+ default:
break;
}
return;
}
-
-
-
-
-void btDiscreteDynamicsWorld::setConstraintSolver(btConstraintSolver* solver)
+void btDiscreteDynamicsWorld::setConstraintSolver(btConstraintSolver* solver)
{
if (m_ownsConstraintSolver)
{
- btAlignedFree( m_constraintSolver);
+ btAlignedFree(m_constraintSolver);
}
m_ownsConstraintSolver = false;
m_constraintSolver = solver;
@@ -1430,8 +1355,7 @@ btConstraintSolver* btDiscreteDynamicsWorld::getConstraintSolver()
return m_constraintSolver;
}
-
-int btDiscreteDynamicsWorld::getNumConstraints() const
+int btDiscreteDynamicsWorld::getNumConstraints() const
{
return int(m_constraints.size());
}
@@ -1444,93 +1368,87 @@ const btTypedConstraint* btDiscreteDynamicsWorld::getConstraint(int index) const
return m_constraints[index];
}
-
-
-void btDiscreteDynamicsWorld::serializeRigidBodies(btSerializer* serializer)
+void btDiscreteDynamicsWorld::serializeRigidBodies(btSerializer* serializer)
{
int i;
//serialize all collision objects
- for (i=0;i<m_collisionObjects.size();i++)
+ for (i = 0; i < m_collisionObjects.size(); i++)
{
btCollisionObject* colObj = m_collisionObjects[i];
if (colObj->getInternalType() & btCollisionObject::CO_RIGID_BODY)
{
int len = colObj->calculateSerializeBufferSize();
- btChunk* chunk = serializer->allocate(len,1);
+ btChunk* chunk = serializer->allocate(len, 1);
const char* structType = colObj->serialize(chunk->m_oldPtr, serializer);
- serializer->finalizeChunk(chunk,structType,BT_RIGIDBODY_CODE,colObj);
+ serializer->finalizeChunk(chunk, structType, BT_RIGIDBODY_CODE, colObj);
}
}
- for (i=0;i<m_constraints.size();i++)
+ for (i = 0; i < m_constraints.size(); i++)
{
btTypedConstraint* constraint = m_constraints[i];
int size = constraint->calculateSerializeBufferSize();
- btChunk* chunk = serializer->allocate(size,1);
- const char* structType = constraint->serialize(chunk->m_oldPtr,serializer);
- serializer->finalizeChunk(chunk,structType,BT_CONSTRAINT_CODE,constraint);
+ btChunk* chunk = serializer->allocate(size, 1);
+ const char* structType = constraint->serialize(chunk->m_oldPtr, serializer);
+ serializer->finalizeChunk(chunk, structType, BT_CONSTRAINT_CODE, constraint);
}
}
-
-
-
-void btDiscreteDynamicsWorld::serializeDynamicsWorldInfo(btSerializer* serializer)
+void btDiscreteDynamicsWorld::serializeDynamicsWorldInfo(btSerializer* serializer)
{
#ifdef BT_USE_DOUBLE_PRECISION
- int len = sizeof(btDynamicsWorldDoubleData);
- btChunk* chunk = serializer->allocate(len,1);
- btDynamicsWorldDoubleData* worldInfo = (btDynamicsWorldDoubleData*)chunk->m_oldPtr;
-#else//BT_USE_DOUBLE_PRECISION
- int len = sizeof(btDynamicsWorldFloatData);
- btChunk* chunk = serializer->allocate(len,1);
- btDynamicsWorldFloatData* worldInfo = (btDynamicsWorldFloatData*)chunk->m_oldPtr;
-#endif//BT_USE_DOUBLE_PRECISION
-
- memset(worldInfo ,0x00,len);
-
- m_gravity.serialize(worldInfo->m_gravity);
- worldInfo->m_solverInfo.m_tau = getSolverInfo().m_tau;
- worldInfo->m_solverInfo.m_damping = getSolverInfo().m_damping;
- worldInfo->m_solverInfo.m_friction = getSolverInfo().m_friction;
- worldInfo->m_solverInfo.m_timeStep = getSolverInfo().m_timeStep;
-
- worldInfo->m_solverInfo.m_restitution = getSolverInfo().m_restitution;
- worldInfo->m_solverInfo.m_maxErrorReduction = getSolverInfo().m_maxErrorReduction;
- worldInfo->m_solverInfo.m_sor = getSolverInfo().m_sor;
- worldInfo->m_solverInfo.m_erp = getSolverInfo().m_erp;
-
- worldInfo->m_solverInfo.m_erp2 = getSolverInfo().m_erp2;
- worldInfo->m_solverInfo.m_globalCfm = getSolverInfo().m_globalCfm;
- worldInfo->m_solverInfo.m_splitImpulsePenetrationThreshold = getSolverInfo().m_splitImpulsePenetrationThreshold;
- worldInfo->m_solverInfo.m_splitImpulseTurnErp = getSolverInfo().m_splitImpulseTurnErp;
-
- worldInfo->m_solverInfo.m_linearSlop = getSolverInfo().m_linearSlop;
- worldInfo->m_solverInfo.m_warmstartingFactor = getSolverInfo().m_warmstartingFactor;
- worldInfo->m_solverInfo.m_maxGyroscopicForce = getSolverInfo().m_maxGyroscopicForce;
- worldInfo->m_solverInfo.m_singleAxisRollingFrictionThreshold = getSolverInfo().m_singleAxisRollingFrictionThreshold;
-
- worldInfo->m_solverInfo.m_numIterations = getSolverInfo().m_numIterations;
- worldInfo->m_solverInfo.m_solverMode = getSolverInfo().m_solverMode;
- worldInfo->m_solverInfo.m_restingContactRestitutionThreshold = getSolverInfo().m_restingContactRestitutionThreshold;
- worldInfo->m_solverInfo.m_minimumSolverBatchSize = getSolverInfo().m_minimumSolverBatchSize;
-
- worldInfo->m_solverInfo.m_splitImpulse = getSolverInfo().m_splitImpulse;
-
- // Fill padding with zeros to appease msan.
- memset(worldInfo->m_solverInfo.m_padding, 0, sizeof(worldInfo->m_solverInfo.m_padding));
+ int len = sizeof(btDynamicsWorldDoubleData);
+ btChunk* chunk = serializer->allocate(len, 1);
+ btDynamicsWorldDoubleData* worldInfo = (btDynamicsWorldDoubleData*)chunk->m_oldPtr;
+#else //BT_USE_DOUBLE_PRECISION
+ int len = sizeof(btDynamicsWorldFloatData);
+ btChunk* chunk = serializer->allocate(len, 1);
+ btDynamicsWorldFloatData* worldInfo = (btDynamicsWorldFloatData*)chunk->m_oldPtr;
+#endif //BT_USE_DOUBLE_PRECISION
+
+ memset(worldInfo, 0x00, len);
+
+ m_gravity.serialize(worldInfo->m_gravity);
+ worldInfo->m_solverInfo.m_tau = getSolverInfo().m_tau;
+ worldInfo->m_solverInfo.m_damping = getSolverInfo().m_damping;
+ worldInfo->m_solverInfo.m_friction = getSolverInfo().m_friction;
+ worldInfo->m_solverInfo.m_timeStep = getSolverInfo().m_timeStep;
+
+ worldInfo->m_solverInfo.m_restitution = getSolverInfo().m_restitution;
+ worldInfo->m_solverInfo.m_maxErrorReduction = getSolverInfo().m_maxErrorReduction;
+ worldInfo->m_solverInfo.m_sor = getSolverInfo().m_sor;
+ worldInfo->m_solverInfo.m_erp = getSolverInfo().m_erp;
+
+ worldInfo->m_solverInfo.m_erp2 = getSolverInfo().m_erp2;
+ worldInfo->m_solverInfo.m_globalCfm = getSolverInfo().m_globalCfm;
+ worldInfo->m_solverInfo.m_splitImpulsePenetrationThreshold = getSolverInfo().m_splitImpulsePenetrationThreshold;
+ worldInfo->m_solverInfo.m_splitImpulseTurnErp = getSolverInfo().m_splitImpulseTurnErp;
+
+ worldInfo->m_solverInfo.m_linearSlop = getSolverInfo().m_linearSlop;
+ worldInfo->m_solverInfo.m_warmstartingFactor = getSolverInfo().m_warmstartingFactor;
+ worldInfo->m_solverInfo.m_maxGyroscopicForce = getSolverInfo().m_maxGyroscopicForce;
+ worldInfo->m_solverInfo.m_singleAxisRollingFrictionThreshold = getSolverInfo().m_singleAxisRollingFrictionThreshold;
+
+ worldInfo->m_solverInfo.m_numIterations = getSolverInfo().m_numIterations;
+ worldInfo->m_solverInfo.m_solverMode = getSolverInfo().m_solverMode;
+ worldInfo->m_solverInfo.m_restingContactRestitutionThreshold = getSolverInfo().m_restingContactRestitutionThreshold;
+ worldInfo->m_solverInfo.m_minimumSolverBatchSize = getSolverInfo().m_minimumSolverBatchSize;
+
+ worldInfo->m_solverInfo.m_splitImpulse = getSolverInfo().m_splitImpulse;
+
+ // Fill padding with zeros to appease msan.
+ memset(worldInfo->m_solverInfo.m_padding, 0, sizeof(worldInfo->m_solverInfo.m_padding));
#ifdef BT_USE_DOUBLE_PRECISION
- const char* structType = "btDynamicsWorldDoubleData";
-#else//BT_USE_DOUBLE_PRECISION
- const char* structType = "btDynamicsWorldFloatData";
-#endif//BT_USE_DOUBLE_PRECISION
- serializer->finalizeChunk(chunk,structType,BT_DYNAMICSWORLD_CODE,worldInfo);
+ const char* structType = "btDynamicsWorldDoubleData";
+#else //BT_USE_DOUBLE_PRECISION
+ const char* structType = "btDynamicsWorldFloatData";
+#endif //BT_USE_DOUBLE_PRECISION
+ serializer->finalizeChunk(chunk, structType, BT_DYNAMICSWORLD_CODE, worldInfo);
}
-void btDiscreteDynamicsWorld::serialize(btSerializer* serializer)
+void btDiscreteDynamicsWorld::serialize(btSerializer* serializer)
{
-
serializer->startSerialization();
serializeDynamicsWorldInfo(serializer);
@@ -1543,4 +1461,3 @@ void btDiscreteDynamicsWorld::serialize(btSerializer* serializer)
serializer->finishSerialization();
}
-
diff --git a/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h b/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h
index b0d19f48a3..7fe9619213 100644
--- a/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h
+++ b/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h
@@ -13,7 +13,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#ifndef BT_DISCRETE_DYNAMICS_WORLD_H
#define BT_DISCRETE_DYNAMICS_WORLD_H
@@ -32,159 +31,153 @@ struct InplaceSolverIslandCallback;
#include "LinearMath/btAlignedObjectArray.h"
#include "LinearMath/btThreads.h"
-
///btDiscreteDynamicsWorld provides discrete rigid body simulation
///those classes replace the obsolete CcdPhysicsEnvironment/CcdPhysicsController
-ATTRIBUTE_ALIGNED16(class) btDiscreteDynamicsWorld : public btDynamicsWorld
+ATTRIBUTE_ALIGNED16(class)
+btDiscreteDynamicsWorld : public btDynamicsWorld
{
protected:
-
- btAlignedObjectArray<btTypedConstraint*> m_sortedConstraints;
- InplaceSolverIslandCallback* m_solverIslandCallback;
+ btAlignedObjectArray<btTypedConstraint*> m_sortedConstraints;
+ InplaceSolverIslandCallback* m_solverIslandCallback;
- btConstraintSolver* m_constraintSolver;
+ btConstraintSolver* m_constraintSolver;
- btSimulationIslandManager* m_islandManager;
+ btSimulationIslandManager* m_islandManager;
btAlignedObjectArray<btTypedConstraint*> m_constraints;
btAlignedObjectArray<btRigidBody*> m_nonStaticRigidBodies;
- btVector3 m_gravity;
+ btVector3 m_gravity;
//for variable timesteps
- btScalar m_localTime;
- btScalar m_fixedTimeStep;
+ btScalar m_localTime;
+ btScalar m_fixedTimeStep;
//for variable timesteps
- bool m_ownsIslandManager;
- bool m_ownsConstraintSolver;
- bool m_synchronizeAllMotionStates;
- bool m_applySpeculativeContactRestitution;
+ bool m_ownsIslandManager;
+ bool m_ownsConstraintSolver;
+ bool m_synchronizeAllMotionStates;
+ bool m_applySpeculativeContactRestitution;
- btAlignedObjectArray<btActionInterface*> m_actions;
-
- int m_profileTimings;
+ btAlignedObjectArray<btActionInterface*> m_actions;
- bool m_latencyMotionStateInterpolation;
+ int m_profileTimings;
- btAlignedObjectArray<btPersistentManifold*> m_predictiveManifolds;
- btSpinMutex m_predictiveManifoldsMutex; // used to synchronize threads creating predictive contacts
+ bool m_latencyMotionStateInterpolation;
- virtual void predictUnconstraintMotion(btScalar timeStep);
-
- void integrateTransformsInternal( btRigidBody** bodies, int numBodies, btScalar timeStep ); // can be called in parallel
- virtual void integrateTransforms(btScalar timeStep);
-
- virtual void calculateSimulationIslands();
+ btAlignedObjectArray<btPersistentManifold*> m_predictiveManifolds;
+ btSpinMutex m_predictiveManifoldsMutex; // used to synchronize threads creating predictive contacts
- virtual void solveConstraints(btContactSolverInfo& solverInfo);
-
- virtual void updateActivationState(btScalar timeStep);
+ virtual void predictUnconstraintMotion(btScalar timeStep);
- void updateActions(btScalar timeStep);
+ void integrateTransformsInternal(btRigidBody * *bodies, int numBodies, btScalar timeStep); // can be called in parallel
+ virtual void integrateTransforms(btScalar timeStep);
- void startProfiling(btScalar timeStep);
+ virtual void calculateSimulationIslands();
- virtual void internalSingleStepSimulation( btScalar timeStep);
+ virtual void solveConstraints(btContactSolverInfo & solverInfo);
- void releasePredictiveContacts();
- void createPredictiveContactsInternal( btRigidBody** bodies, int numBodies, btScalar timeStep ); // can be called in parallel
- virtual void createPredictiveContacts(btScalar timeStep);
+ virtual void updateActivationState(btScalar timeStep);
- virtual void saveKinematicState(btScalar timeStep);
+ void updateActions(btScalar timeStep);
- void serializeRigidBodies(btSerializer* serializer);
+ void startProfiling(btScalar timeStep);
- void serializeDynamicsWorldInfo(btSerializer* serializer);
+ virtual void internalSingleStepSimulation(btScalar timeStep);
-public:
+ void releasePredictiveContacts();
+ void createPredictiveContactsInternal(btRigidBody * *bodies, int numBodies, btScalar timeStep); // can be called in parallel
+ virtual void createPredictiveContacts(btScalar timeStep);
+ virtual void saveKinematicState(btScalar timeStep);
+ void serializeRigidBodies(btSerializer * serializer);
+
+ void serializeDynamicsWorldInfo(btSerializer * serializer);
+
+public:
BT_DECLARE_ALIGNED_ALLOCATOR();
///this btDiscreteDynamicsWorld constructor gets created objects from the user, and will not delete those
- btDiscreteDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration);
+ btDiscreteDynamicsWorld(btDispatcher * dispatcher, btBroadphaseInterface * pairCache, btConstraintSolver * constraintSolver, btCollisionConfiguration * collisionConfiguration);
virtual ~btDiscreteDynamicsWorld();
///if maxSubSteps > 0, it will interpolate motion between fixedTimeStep's
- virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.));
+ virtual int stepSimulation(btScalar timeStep, int maxSubSteps = 1, btScalar fixedTimeStep = btScalar(1.) / btScalar(60.));
-
- virtual void synchronizeMotionStates();
+ virtual void synchronizeMotionStates();
///this can be useful to synchronize a single rigid body -> graphics object
- void synchronizeSingleMotionState(btRigidBody* body);
+ void synchronizeSingleMotionState(btRigidBody * body);
+
+ virtual void addConstraint(btTypedConstraint * constraint, bool disableCollisionsBetweenLinkedBodies = false);
- virtual void addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies=false);
+ virtual void removeConstraint(btTypedConstraint * constraint);
- virtual void removeConstraint(btTypedConstraint* constraint);
+ virtual void addAction(btActionInterface*);
- virtual void addAction(btActionInterface*);
+ virtual void removeAction(btActionInterface*);
- virtual void removeAction(btActionInterface*);
-
- btSimulationIslandManager* getSimulationIslandManager()
+ btSimulationIslandManager* getSimulationIslandManager()
{
return m_islandManager;
}
- const btSimulationIslandManager* getSimulationIslandManager() const
+ const btSimulationIslandManager* getSimulationIslandManager() const
{
return m_islandManager;
}
- btCollisionWorld* getCollisionWorld()
+ btCollisionWorld* getCollisionWorld()
{
return this;
}
- virtual void setGravity(const btVector3& gravity);
+ virtual void setGravity(const btVector3& gravity);
- virtual btVector3 getGravity () const;
+ virtual btVector3 getGravity() const;
- virtual void addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup=btBroadphaseProxy::StaticFilter, int collisionFilterMask=btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter);
+ virtual void addCollisionObject(btCollisionObject * collisionObject, int collisionFilterGroup = btBroadphaseProxy::StaticFilter, int collisionFilterMask = btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter);
- virtual void addRigidBody(btRigidBody* body);
+ virtual void addRigidBody(btRigidBody * body);
- virtual void addRigidBody(btRigidBody* body, int group, int mask);
+ virtual void addRigidBody(btRigidBody * body, int group, int mask);
- virtual void removeRigidBody(btRigidBody* body);
+ virtual void removeRigidBody(btRigidBody * body);
///removeCollisionObject will first check if it is a rigid body, if so call removeRigidBody otherwise call btCollisionWorld::removeCollisionObject
- virtual void removeCollisionObject(btCollisionObject* collisionObject);
-
+ virtual void removeCollisionObject(btCollisionObject * collisionObject);
- virtual void debugDrawConstraint(btTypedConstraint* constraint);
+ virtual void debugDrawConstraint(btTypedConstraint * constraint);
- virtual void debugDrawWorld();
+ virtual void debugDrawWorld();
- virtual void setConstraintSolver(btConstraintSolver* solver);
+ virtual void setConstraintSolver(btConstraintSolver * solver);
virtual btConstraintSolver* getConstraintSolver();
-
- virtual int getNumConstraints() const;
- virtual btTypedConstraint* getConstraint(int index) ;
+ virtual int getNumConstraints() const;
+
+ virtual btTypedConstraint* getConstraint(int index);
virtual const btTypedConstraint* getConstraint(int index) const;
-
- virtual btDynamicsWorldType getWorldType() const
+ virtual btDynamicsWorldType getWorldType() const
{
return BT_DISCRETE_DYNAMICS_WORLD;
}
-
+
///the forces on each rigidbody is accumulating together with gravity. clear this after each timestep.
- virtual void clearForces();
+ virtual void clearForces();
///apply gravity, call this once per timestep
- virtual void applyGravity();
+ virtual void applyGravity();
- virtual void setNumTasks(int numTasks)
+ virtual void setNumTasks(int numTasks)
{
- (void) numTasks;
+ (void)numTasks;
}
///obsolete, use updateActions instead
@@ -194,15 +187,15 @@ public:
}
///obsolete, use addAction instead
- virtual void addVehicle(btActionInterface* vehicle);
+ virtual void addVehicle(btActionInterface * vehicle);
///obsolete, use removeAction instead
- virtual void removeVehicle(btActionInterface* vehicle);
+ virtual void removeVehicle(btActionInterface * vehicle);
///obsolete, use addAction instead
- virtual void addCharacter(btActionInterface* character);
+ virtual void addCharacter(btActionInterface * character);
///obsolete, use removeAction instead
- virtual void removeCharacter(btActionInterface* character);
+ virtual void removeCharacter(btActionInterface * character);
- void setSynchronizeAllMotionStates(bool synchronizeAll)
+ void setSynchronizeAllMotionStates(bool synchronizeAll)
{
m_synchronizeAllMotionStates = synchronizeAll;
}
@@ -215,18 +208,18 @@ public:
{
m_applySpeculativeContactRestitution = enable;
}
-
+
bool getApplySpeculativeContactRestitution() const
{
return m_applySpeculativeContactRestitution;
}
///Preliminary serialization test for Bullet 2.76. Loading those files requires a separate parser (see Bullet/Demos/SerializeDemo)
- virtual void serialize(btSerializer* serializer);
+ virtual void serialize(btSerializer * serializer);
///Interpolate motion state between previous and current transform, instead of current and next transform.
///This can relieve discontinuities in the rendering, due to penetrations
- void setLatencyMotionStateInterpolation(bool latencyInterpolation )
+ void setLatencyMotionStateInterpolation(bool latencyInterpolation)
{
m_latencyMotionStateInterpolation = latencyInterpolation;
}
@@ -236,4 +229,4 @@ public:
}
};
-#endif //BT_DISCRETE_DYNAMICS_WORLD_H
+#endif //BT_DISCRETE_DYNAMICS_WORLD_H
diff --git a/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.cpp b/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.cpp
index d705bf2381..8207b47135 100644
--- a/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.cpp
+++ b/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.cpp
@@ -13,7 +13,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#include "btDiscreteDynamicsWorldMt.h"
//collision detection
@@ -38,148 +37,139 @@ subject to the following restrictions:
#include "BulletDynamics/ConstraintSolver/btSliderConstraint.h"
#include "BulletDynamics/ConstraintSolver/btContactConstraint.h"
-
#include "LinearMath/btIDebugDraw.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h"
-
#include "BulletDynamics/Dynamics/btActionInterface.h"
#include "LinearMath/btQuickprof.h"
#include "LinearMath/btMotionState.h"
#include "LinearMath/btSerializer.h"
-
-
///
/// btConstraintSolverPoolMt
///
btConstraintSolverPoolMt::ThreadSolver* btConstraintSolverPoolMt::getAndLockThreadSolver()
{
- int i = 0;
+ int i = 0;
#if BT_THREADSAFE
- i = btGetCurrentThreadIndex() % m_solvers.size();
-#endif // #if BT_THREADSAFE
- while ( true )
- {
- ThreadSolver& solver = m_solvers[ i ];
- if ( solver.mutex.tryLock() )
- {
- return &solver;
- }
- // failed, try the next one
- i = ( i + 1 ) % m_solvers.size();
- }
- return NULL;
+ i = btGetCurrentThreadIndex() % m_solvers.size();
+#endif // #if BT_THREADSAFE
+ while (true)
+ {
+ ThreadSolver& solver = m_solvers[i];
+ if (solver.mutex.tryLock())
+ {
+ return &solver;
+ }
+ // failed, try the next one
+ i = (i + 1) % m_solvers.size();
+ }
+ return NULL;
}
-void btConstraintSolverPoolMt::init( btConstraintSolver** solvers, int numSolvers )
+void btConstraintSolverPoolMt::init(btConstraintSolver** solvers, int numSolvers)
{
- m_solverType = BT_SEQUENTIAL_IMPULSE_SOLVER;
- m_solvers.resize( numSolvers );
- for ( int i = 0; i < numSolvers; ++i )
- {
- m_solvers[ i ].solver = solvers[ i ];
- }
- if ( numSolvers > 0 )
- {
- m_solverType = solvers[ 0 ]->getSolverType();
- }
+ m_solverType = BT_SEQUENTIAL_IMPULSE_SOLVER;
+ m_solvers.resize(numSolvers);
+ for (int i = 0; i < numSolvers; ++i)
+ {
+ m_solvers[i].solver = solvers[i];
+ }
+ if (numSolvers > 0)
+ {
+ m_solverType = solvers[0]->getSolverType();
+ }
}
// create the solvers for me
-btConstraintSolverPoolMt::btConstraintSolverPoolMt( int numSolvers )
+btConstraintSolverPoolMt::btConstraintSolverPoolMt(int numSolvers)
{
- btAlignedObjectArray<btConstraintSolver*> solvers;
- solvers.reserve( numSolvers );
- for ( int i = 0; i < numSolvers; ++i )
- {
- btConstraintSolver* solver = new btSequentialImpulseConstraintSolver();
- solvers.push_back( solver );
- }
- init( &solvers[ 0 ], numSolvers );
+ btAlignedObjectArray<btConstraintSolver*> solvers;
+ solvers.reserve(numSolvers);
+ for (int i = 0; i < numSolvers; ++i)
+ {
+ btConstraintSolver* solver = new btSequentialImpulseConstraintSolver();
+ solvers.push_back(solver);
+ }
+ init(&solvers[0], numSolvers);
}
// pass in fully constructed solvers (destructor will delete them)
-btConstraintSolverPoolMt::btConstraintSolverPoolMt( btConstraintSolver** solvers, int numSolvers )
+btConstraintSolverPoolMt::btConstraintSolverPoolMt(btConstraintSolver** solvers, int numSolvers)
{
- init( solvers, numSolvers );
+ init(solvers, numSolvers);
}
btConstraintSolverPoolMt::~btConstraintSolverPoolMt()
{
- // delete all solvers
- for ( int i = 0; i < m_solvers.size(); ++i )
- {
- ThreadSolver& solver = m_solvers[ i ];
- delete solver.solver;
- solver.solver = NULL;
- }
+ // delete all solvers
+ for (int i = 0; i < m_solvers.size(); ++i)
+ {
+ ThreadSolver& solver = m_solvers[i];
+ delete solver.solver;
+ solver.solver = NULL;
+ }
}
///solve a group of constraints
-btScalar btConstraintSolverPoolMt::solveGroup( btCollisionObject** bodies,
- int numBodies,
- btPersistentManifold** manifolds,
- int numManifolds,
- btTypedConstraint** constraints,
- int numConstraints,
- const btContactSolverInfo& info,
- btIDebugDraw* debugDrawer,
- btDispatcher* dispatcher
-)
+btScalar btConstraintSolverPoolMt::solveGroup(btCollisionObject** bodies,
+ int numBodies,
+ btPersistentManifold** manifolds,
+ int numManifolds,
+ btTypedConstraint** constraints,
+ int numConstraints,
+ const btContactSolverInfo& info,
+ btIDebugDraw* debugDrawer,
+ btDispatcher* dispatcher)
{
- ThreadSolver* ts = getAndLockThreadSolver();
- ts->solver->solveGroup( bodies, numBodies, manifolds, numManifolds, constraints, numConstraints, info, debugDrawer, dispatcher );
- ts->mutex.unlock();
- return 0.0f;
+ ThreadSolver* ts = getAndLockThreadSolver();
+ ts->solver->solveGroup(bodies, numBodies, manifolds, numManifolds, constraints, numConstraints, info, debugDrawer, dispatcher);
+ ts->mutex.unlock();
+ return 0.0f;
}
void btConstraintSolverPoolMt::reset()
{
- for ( int i = 0; i < m_solvers.size(); ++i )
- {
- ThreadSolver& solver = m_solvers[ i ];
- solver.mutex.lock();
- solver.solver->reset();
- solver.mutex.unlock();
- }
+ for (int i = 0; i < m_solvers.size(); ++i)
+ {
+ ThreadSolver& solver = m_solvers[i];
+ solver.mutex.lock();
+ solver.solver->reset();
+ solver.mutex.unlock();
+ }
}
-
///
/// btDiscreteDynamicsWorldMt
///
btDiscreteDynamicsWorldMt::btDiscreteDynamicsWorldMt(btDispatcher* dispatcher,
- btBroadphaseInterface* pairCache,
- btConstraintSolverPoolMt* constraintSolver,
- btConstraintSolver* constraintSolverMt,
- btCollisionConfiguration* collisionConfiguration
-)
-: btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration)
+ btBroadphaseInterface* pairCache,
+ btConstraintSolverPoolMt* solverPool,
+ btConstraintSolver* constraintSolverMt,
+ btCollisionConfiguration* collisionConfiguration)
+ : btDiscreteDynamicsWorld(dispatcher, pairCache, solverPool, collisionConfiguration)
{
if (m_ownsIslandManager)
{
m_islandManager->~btSimulationIslandManager();
- btAlignedFree( m_islandManager);
+ btAlignedFree(m_islandManager);
}
{
- void* mem = btAlignedAlloc(sizeof(btSimulationIslandManagerMt),16);
+ void* mem = btAlignedAlloc(sizeof(btSimulationIslandManagerMt), 16);
btSimulationIslandManagerMt* im = new (mem) btSimulationIslandManagerMt();
- im->setMinimumSolverBatchSize( m_solverInfo.m_minimumSolverBatchSize );
- m_islandManager = im;
+ im->setMinimumSolverBatchSize(m_solverInfo.m_minimumSolverBatchSize);
+ m_islandManager = im;
}
- m_constraintSolverMt = constraintSolverMt;
+ m_constraintSolverMt = constraintSolverMt;
}
-
btDiscreteDynamicsWorldMt::~btDiscreteDynamicsWorldMt()
{
}
-
void btDiscreteDynamicsWorldMt::solveConstraints(btContactSolverInfo& solverInfo)
{
BT_PROFILE("solveConstraints");
@@ -187,92 +177,87 @@ void btDiscreteDynamicsWorldMt::solveConstraints(btContactSolverInfo& solverInfo
m_constraintSolver->prepareSolve(getCollisionWorld()->getNumCollisionObjects(), getCollisionWorld()->getDispatcher()->getNumManifolds());
/// solve all the constraints for this island
- btSimulationIslandManagerMt* im = static_cast<btSimulationIslandManagerMt*>(m_islandManager);
- btSimulationIslandManagerMt::SolverParams solverParams;
- solverParams.m_solverPool = m_constraintSolver;
- solverParams.m_solverMt = m_constraintSolverMt;
- solverParams.m_solverInfo = &solverInfo;
- solverParams.m_debugDrawer = m_debugDrawer;
- solverParams.m_dispatcher = getCollisionWorld()->getDispatcher();
- im->buildAndProcessIslands( getCollisionWorld()->getDispatcher(), getCollisionWorld(), m_constraints, solverParams );
+ btSimulationIslandManagerMt* im = static_cast<btSimulationIslandManagerMt*>(m_islandManager);
+ btSimulationIslandManagerMt::SolverParams solverParams;
+ solverParams.m_solverPool = m_constraintSolver;
+ solverParams.m_solverMt = m_constraintSolverMt;
+ solverParams.m_solverInfo = &solverInfo;
+ solverParams.m_debugDrawer = m_debugDrawer;
+ solverParams.m_dispatcher = getCollisionWorld()->getDispatcher();
+ im->buildAndProcessIslands(getCollisionWorld()->getDispatcher(), getCollisionWorld(), m_constraints, solverParams);
m_constraintSolver->allSolved(solverInfo, m_debugDrawer);
}
-
struct UpdaterUnconstrainedMotion : public btIParallelForBody
{
- btScalar timeStep;
- btRigidBody** rigidBodies;
+ btScalar timeStep;
+ btRigidBody** rigidBodies;
- void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE
- {
- for ( int i = iBegin; i < iEnd; ++i )
- {
- btRigidBody* body = rigidBodies[ i ];
- if ( !body->isStaticOrKinematicObject() )
- {
- //don't integrate/update velocities here, it happens in the constraint solver
- body->applyDamping( timeStep );
- body->predictIntegratedTransform( timeStep, body->getInterpolationWorldTransform() );
- }
- }
- }
+ void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
+ {
+ for (int i = iBegin; i < iEnd; ++i)
+ {
+ btRigidBody* body = rigidBodies[i];
+ if (!body->isStaticOrKinematicObject())
+ {
+ //don't integrate/update velocities here, it happens in the constraint solver
+ body->applyDamping(timeStep);
+ body->predictIntegratedTransform(timeStep, body->getInterpolationWorldTransform());
+ }
+ }
+ }
};
-
-void btDiscreteDynamicsWorldMt::predictUnconstraintMotion( btScalar timeStep )
+void btDiscreteDynamicsWorldMt::predictUnconstraintMotion(btScalar timeStep)
{
- BT_PROFILE( "predictUnconstraintMotion" );
- if ( m_nonStaticRigidBodies.size() > 0 )
- {
- UpdaterUnconstrainedMotion update;
- update.timeStep = timeStep;
- update.rigidBodies = &m_nonStaticRigidBodies[ 0 ];
- int grainSize = 50; // num of iterations per task for task scheduler
- btParallelFor( 0, m_nonStaticRigidBodies.size(), grainSize, update );
- }
+ BT_PROFILE("predictUnconstraintMotion");
+ if (m_nonStaticRigidBodies.size() > 0)
+ {
+ UpdaterUnconstrainedMotion update;
+ update.timeStep = timeStep;
+ update.rigidBodies = &m_nonStaticRigidBodies[0];
+ int grainSize = 50; // num of iterations per task for task scheduler
+ btParallelFor(0, m_nonStaticRigidBodies.size(), grainSize, update);
+ }
}
-
-void btDiscreteDynamicsWorldMt::createPredictiveContacts( btScalar timeStep )
+void btDiscreteDynamicsWorldMt::createPredictiveContacts(btScalar timeStep)
{
- BT_PROFILE( "createPredictiveContacts" );
- releasePredictiveContacts();
- if ( m_nonStaticRigidBodies.size() > 0 )
- {
- UpdaterCreatePredictiveContacts update;
- update.world = this;
- update.timeStep = timeStep;
- update.rigidBodies = &m_nonStaticRigidBodies[ 0 ];
- int grainSize = 50; // num of iterations per task for task scheduler
- btParallelFor( 0, m_nonStaticRigidBodies.size(), grainSize, update );
- }
+ BT_PROFILE("createPredictiveContacts");
+ releasePredictiveContacts();
+ if (m_nonStaticRigidBodies.size() > 0)
+ {
+ UpdaterCreatePredictiveContacts update;
+ update.world = this;
+ update.timeStep = timeStep;
+ update.rigidBodies = &m_nonStaticRigidBodies[0];
+ int grainSize = 50; // num of iterations per task for task scheduler
+ btParallelFor(0, m_nonStaticRigidBodies.size(), grainSize, update);
+ }
}
-
-void btDiscreteDynamicsWorldMt::integrateTransforms( btScalar timeStep )
+void btDiscreteDynamicsWorldMt::integrateTransforms(btScalar timeStep)
{
- BT_PROFILE( "integrateTransforms" );
- if ( m_nonStaticRigidBodies.size() > 0 )
- {
- UpdaterIntegrateTransforms update;
- update.world = this;
- update.timeStep = timeStep;
- update.rigidBodies = &m_nonStaticRigidBodies[ 0 ];
- int grainSize = 50; // num of iterations per task for task scheduler
- btParallelFor( 0, m_nonStaticRigidBodies.size(), grainSize, update );
- }
+ BT_PROFILE("integrateTransforms");
+ if (m_nonStaticRigidBodies.size() > 0)
+ {
+ UpdaterIntegrateTransforms update;
+ update.world = this;
+ update.timeStep = timeStep;
+ update.rigidBodies = &m_nonStaticRigidBodies[0];
+ int grainSize = 50; // num of iterations per task for task scheduler
+ btParallelFor(0, m_nonStaticRigidBodies.size(), grainSize, update);
+ }
}
-
-int btDiscreteDynamicsWorldMt::stepSimulation( btScalar timeStep, int maxSubSteps, btScalar fixedTimeStep )
+int btDiscreteDynamicsWorldMt::stepSimulation(btScalar timeStep, int maxSubSteps, btScalar fixedTimeStep)
{
- int numSubSteps = btDiscreteDynamicsWorld::stepSimulation(timeStep, maxSubSteps, fixedTimeStep);
- if (btITaskScheduler* scheduler = btGetTaskScheduler())
- {
- // tell Bullet's threads to sleep, so other threads can run
- scheduler->sleepWorkerThreadsHint();
- }
- return numSubSteps;
+ int numSubSteps = btDiscreteDynamicsWorld::stepSimulation(timeStep, maxSubSteps, fixedTimeStep);
+ if (btITaskScheduler* scheduler = btGetTaskScheduler())
+ {
+ // tell Bullet's threads to sleep, so other threads can run
+ scheduler->sleepWorkerThreadsHint();
+ }
+ return numSubSteps;
}
diff --git a/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.h b/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.h
index 667fe5800e..dccf35d7a7 100644
--- a/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.h
+++ b/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.h
@@ -13,7 +13,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#ifndef BT_DISCRETE_DYNAMICS_WORLD_MT_H
#define BT_DISCRETE_DYNAMICS_WORLD_MT_H
@@ -21,7 +20,6 @@ subject to the following restrictions:
#include "btSimulationIslandManagerMt.h"
#include "BulletDynamics/ConstraintSolver/btConstraintSolver.h"
-
///
/// btConstraintSolverPoolMt - masquerades as a constraint solver, but really it is a threadsafe pool of them.
///
@@ -34,46 +32,43 @@ subject to the following restrictions:
class btConstraintSolverPoolMt : public btConstraintSolver
{
public:
- // create the solvers for me
- explicit btConstraintSolverPoolMt( int numSolvers );
+ // create the solvers for me
+ explicit btConstraintSolverPoolMt(int numSolvers);
- // pass in fully constructed solvers (destructor will delete them)
- btConstraintSolverPoolMt( btConstraintSolver** solvers, int numSolvers );
+ // pass in fully constructed solvers (destructor will delete them)
+ btConstraintSolverPoolMt(btConstraintSolver** solvers, int numSolvers);
- virtual ~btConstraintSolverPoolMt();
+ virtual ~btConstraintSolverPoolMt();
- ///solve a group of constraints
- virtual btScalar solveGroup( btCollisionObject** bodies,
- int numBodies,
- btPersistentManifold** manifolds,
- int numManifolds,
- btTypedConstraint** constraints,
- int numConstraints,
- const btContactSolverInfo& info,
- btIDebugDraw* debugDrawer,
- btDispatcher* dispatcher
- ) BT_OVERRIDE;
+ ///solve a group of constraints
+ virtual btScalar solveGroup(btCollisionObject** bodies,
+ int numBodies,
+ btPersistentManifold** manifolds,
+ int numManifolds,
+ btTypedConstraint** constraints,
+ int numConstraints,
+ const btContactSolverInfo& info,
+ btIDebugDraw* debugDrawer,
+ btDispatcher* dispatcher) BT_OVERRIDE;
- virtual void reset() BT_OVERRIDE;
- virtual btConstraintSolverType getSolverType() const BT_OVERRIDE { return m_solverType; }
+ virtual void reset() BT_OVERRIDE;
+ virtual btConstraintSolverType getSolverType() const BT_OVERRIDE { return m_solverType; }
private:
- const static size_t kCacheLineSize = 128;
- struct ThreadSolver
- {
- btConstraintSolver* solver;
- btSpinMutex mutex;
- char _cachelinePadding[ kCacheLineSize - sizeof( btSpinMutex ) - sizeof( void* ) ]; // keep mutexes from sharing a cache line
- };
- btAlignedObjectArray<ThreadSolver> m_solvers;
- btConstraintSolverType m_solverType;
-
- ThreadSolver* getAndLockThreadSolver();
- void init( btConstraintSolver** solvers, int numSolvers );
+ const static size_t kCacheLineSize = 128;
+ struct ThreadSolver
+ {
+ btConstraintSolver* solver;
+ btSpinMutex mutex;
+ char _cachelinePadding[kCacheLineSize - sizeof(btSpinMutex) - sizeof(void*)]; // keep mutexes from sharing a cache line
+ };
+ btAlignedObjectArray<ThreadSolver> m_solvers;
+ btConstraintSolverType m_solverType;
+
+ ThreadSolver* getAndLockThreadSolver();
+ void init(btConstraintSolver** solvers, int numSolvers);
};
-
-
///
/// btDiscreteDynamicsWorldMt -- a version of DiscreteDynamicsWorld with some minor changes to support
/// solving simulation islands on multiple threads.
@@ -84,53 +79,53 @@ private:
/// - integrateTransforms
/// - createPredictiveContacts
///
-ATTRIBUTE_ALIGNED16(class) btDiscreteDynamicsWorldMt : public btDiscreteDynamicsWorld
+ATTRIBUTE_ALIGNED16(class)
+btDiscreteDynamicsWorldMt : public btDiscreteDynamicsWorld
{
protected:
- btConstraintSolver* m_constraintSolverMt;
-
- virtual void solveConstraints(btContactSolverInfo& solverInfo) BT_OVERRIDE;
-
- virtual void predictUnconstraintMotion( btScalar timeStep ) BT_OVERRIDE;
-
- struct UpdaterCreatePredictiveContacts : public btIParallelForBody
- {
- btScalar timeStep;
- btRigidBody** rigidBodies;
- btDiscreteDynamicsWorldMt* world;
-
- void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE
- {
- world->createPredictiveContactsInternal( &rigidBodies[ iBegin ], iEnd - iBegin, timeStep );
- }
- };
- virtual void createPredictiveContacts( btScalar timeStep ) BT_OVERRIDE;
-
- struct UpdaterIntegrateTransforms : public btIParallelForBody
- {
- btScalar timeStep;
- btRigidBody** rigidBodies;
- btDiscreteDynamicsWorldMt* world;
-
- void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE
- {
- world->integrateTransformsInternal( &rigidBodies[ iBegin ], iEnd - iBegin, timeStep );
- }
- };
- virtual void integrateTransforms( btScalar timeStep ) BT_OVERRIDE;
+ btConstraintSolver* m_constraintSolverMt;
+
+ virtual void solveConstraints(btContactSolverInfo & solverInfo) BT_OVERRIDE;
+
+ virtual void predictUnconstraintMotion(btScalar timeStep) BT_OVERRIDE;
+
+ struct UpdaterCreatePredictiveContacts : public btIParallelForBody
+ {
+ btScalar timeStep;
+ btRigidBody** rigidBodies;
+ btDiscreteDynamicsWorldMt* world;
+
+ void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
+ {
+ world->createPredictiveContactsInternal(&rigidBodies[iBegin], iEnd - iBegin, timeStep);
+ }
+ };
+ virtual void createPredictiveContacts(btScalar timeStep) BT_OVERRIDE;
+
+ struct UpdaterIntegrateTransforms : public btIParallelForBody
+ {
+ btScalar timeStep;
+ btRigidBody** rigidBodies;
+ btDiscreteDynamicsWorldMt* world;
+
+ void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
+ {
+ world->integrateTransformsInternal(&rigidBodies[iBegin], iEnd - iBegin, timeStep);
+ }
+ };
+ virtual void integrateTransforms(btScalar timeStep) BT_OVERRIDE;
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
- btDiscreteDynamicsWorldMt(btDispatcher* dispatcher,
- btBroadphaseInterface* pairCache,
- btConstraintSolverPoolMt* constraintSolver, // Note this should be a solver-pool for multi-threading
- btConstraintSolver* constraintSolverMt, // single multi-threaded solver for large islands (or NULL)
- btCollisionConfiguration* collisionConfiguration
- );
+ btDiscreteDynamicsWorldMt(btDispatcher * dispatcher,
+ btBroadphaseInterface * pairCache,
+ btConstraintSolverPoolMt * solverPool, // Note this should be a solver-pool for multi-threading
+ btConstraintSolver * constraintSolverMt, // single multi-threaded solver for large islands (or NULL)
+ btCollisionConfiguration * collisionConfiguration);
virtual ~btDiscreteDynamicsWorldMt();
- virtual int stepSimulation( btScalar timeStep, int maxSubSteps, btScalar fixedTimeStep ) BT_OVERRIDE;
+ virtual int stepSimulation(btScalar timeStep, int maxSubSteps, btScalar fixedTimeStep) BT_OVERRIDE;
};
-#endif //BT_DISCRETE_DYNAMICS_WORLD_H
+#endif //BT_DISCRETE_DYNAMICS_WORLD_H
diff --git a/thirdparty/bullet/BulletDynamics/Dynamics/btDynamicsWorld.h b/thirdparty/bullet/BulletDynamics/Dynamics/btDynamicsWorld.h
index 42d8fc0de3..eadd8c12e7 100644
--- a/thirdparty/bullet/BulletDynamics/Dynamics/btDynamicsWorld.h
+++ b/thirdparty/bullet/BulletDynamics/Dynamics/btDynamicsWorld.h
@@ -24,150 +24,150 @@ class btActionInterface;
class btConstraintSolver;
class btDynamicsWorld;
-
/// Type for the callback for each tick
-typedef void (*btInternalTickCallback)(btDynamicsWorld *world, btScalar timeStep);
+typedef void (*btInternalTickCallback)(btDynamicsWorld* world, btScalar timeStep);
enum btDynamicsWorldType
{
- BT_SIMPLE_DYNAMICS_WORLD=1,
- BT_DISCRETE_DYNAMICS_WORLD=2,
- BT_CONTINUOUS_DYNAMICS_WORLD=3,
- BT_SOFT_RIGID_DYNAMICS_WORLD=4,
- BT_GPU_DYNAMICS_WORLD=5,
- BT_SOFT_MULTIBODY_DYNAMICS_WORLD=6
+ BT_SIMPLE_DYNAMICS_WORLD = 1,
+ BT_DISCRETE_DYNAMICS_WORLD = 2,
+ BT_CONTINUOUS_DYNAMICS_WORLD = 3,
+ BT_SOFT_RIGID_DYNAMICS_WORLD = 4,
+ BT_GPU_DYNAMICS_WORLD = 5,
+ BT_SOFT_MULTIBODY_DYNAMICS_WORLD = 6
};
///The btDynamicsWorld is the interface class for several dynamics implementation, basic, discrete, parallel, and continuous etc.
class btDynamicsWorld : public btCollisionWorld
{
-
protected:
- btInternalTickCallback m_internalTickCallback;
- btInternalTickCallback m_internalPreTickCallback;
- void* m_worldUserInfo;
+ btInternalTickCallback m_internalTickCallback;
+ btInternalTickCallback m_internalPreTickCallback;
+ void* m_worldUserInfo;
- btContactSolverInfo m_solverInfo;
+ btContactSolverInfo m_solverInfo;
public:
-
+ btDynamicsWorld(btDispatcher* dispatcher, btBroadphaseInterface* broadphase, btCollisionConfiguration* collisionConfiguration)
+ : btCollisionWorld(dispatcher, broadphase, collisionConfiguration), m_internalTickCallback(0), m_internalPreTickCallback(0), m_worldUserInfo(0)
+ {
+ }
- btDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphase,btCollisionConfiguration* collisionConfiguration)
- :btCollisionWorld(dispatcher,broadphase,collisionConfiguration), m_internalTickCallback(0),m_internalPreTickCallback(0), m_worldUserInfo(0)
- {
- }
+ virtual ~btDynamicsWorld()
+ {
+ }
- virtual ~btDynamicsWorld()
- {
- }
-
- ///stepSimulation proceeds the simulation over 'timeStep', units in preferably in seconds.
- ///By default, Bullet will subdivide the timestep in constant substeps of each 'fixedTimeStep'.
- ///in order to keep the simulation real-time, the maximum number of substeps can be clamped to 'maxSubSteps'.
- ///You can disable subdividing the timestep/substepping by passing maxSubSteps=0 as second argument to stepSimulation, but in that case you have to keep the timeStep constant.
- virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.))=0;
-
- virtual void debugDrawWorld() = 0;
-
- virtual void addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies=false)
- {
- (void)constraint; (void)disableCollisionsBetweenLinkedBodies;
- }
+ ///stepSimulation proceeds the simulation over 'timeStep', units in preferably in seconds.
+ ///By default, Bullet will subdivide the timestep in constant substeps of each 'fixedTimeStep'.
+ ///in order to keep the simulation real-time, the maximum number of substeps can be clamped to 'maxSubSteps'.
+ ///You can disable subdividing the timestep/substepping by passing maxSubSteps=0 as second argument to stepSimulation, but in that case you have to keep the timeStep constant.
+ virtual int stepSimulation(btScalar timeStep, int maxSubSteps = 1, btScalar fixedTimeStep = btScalar(1.) / btScalar(60.)) = 0;
- virtual void removeConstraint(btTypedConstraint* constraint) {(void)constraint;}
+ virtual void debugDrawWorld() = 0;
- virtual void addAction(btActionInterface* action) = 0;
+ virtual void addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies = false)
+ {
+ (void)constraint;
+ (void)disableCollisionsBetweenLinkedBodies;
+ }
- virtual void removeAction(btActionInterface* action) = 0;
+ virtual void removeConstraint(btTypedConstraint* constraint) { (void)constraint; }
- //once a rigidbody is added to the dynamics world, it will get this gravity assigned
- //existing rigidbodies in the world get gravity assigned too, during this method
- virtual void setGravity(const btVector3& gravity) = 0;
- virtual btVector3 getGravity () const = 0;
+ virtual void addAction(btActionInterface* action) = 0;
- virtual void synchronizeMotionStates() = 0;
+ virtual void removeAction(btActionInterface* action) = 0;
- virtual void addRigidBody(btRigidBody* body) = 0;
+ //once a rigidbody is added to the dynamics world, it will get this gravity assigned
+ //existing rigidbodies in the world get gravity assigned too, during this method
+ virtual void setGravity(const btVector3& gravity) = 0;
+ virtual btVector3 getGravity() const = 0;
- virtual void addRigidBody(btRigidBody* body, int group, int mask) = 0;
+ virtual void synchronizeMotionStates() = 0;
- virtual void removeRigidBody(btRigidBody* body) = 0;
+ virtual void addRigidBody(btRigidBody* body) = 0;
- virtual void setConstraintSolver(btConstraintSolver* solver) = 0;
+ virtual void addRigidBody(btRigidBody* body, int group, int mask) = 0;
- virtual btConstraintSolver* getConstraintSolver() = 0;
-
- virtual int getNumConstraints() const { return 0; }
-
- virtual btTypedConstraint* getConstraint(int index) { (void)index; return 0; }
-
- virtual const btTypedConstraint* getConstraint(int index) const { (void)index; return 0; }
+ virtual void removeRigidBody(btRigidBody* body) = 0;
- virtual btDynamicsWorldType getWorldType() const=0;
+ virtual void setConstraintSolver(btConstraintSolver* solver) = 0;
- virtual void clearForces() = 0;
+ virtual btConstraintSolver* getConstraintSolver() = 0;
- /// Set the callback for when an internal tick (simulation substep) happens, optional user info
- void setInternalTickCallback(btInternalTickCallback cb, void* worldUserInfo=0,bool isPreTick=false)
- {
- if (isPreTick)
- {
- m_internalPreTickCallback = cb;
- } else
- {
- m_internalTickCallback = cb;
- }
- m_worldUserInfo = worldUserInfo;
- }
+ virtual int getNumConstraints() const { return 0; }
- void setWorldUserInfo(void* worldUserInfo)
- {
- m_worldUserInfo = worldUserInfo;
- }
+ virtual btTypedConstraint* getConstraint(int index)
+ {
+ (void)index;
+ return 0;
+ }
- void* getWorldUserInfo() const
- {
- return m_worldUserInfo;
- }
+ virtual const btTypedConstraint* getConstraint(int index) const
+ {
+ (void)index;
+ return 0;
+ }
+
+ virtual btDynamicsWorldType getWorldType() const = 0;
+
+ virtual void clearForces() = 0;
- btContactSolverInfo& getSolverInfo()
+ /// Set the callback for when an internal tick (simulation substep) happens, optional user info
+ void setInternalTickCallback(btInternalTickCallback cb, void* worldUserInfo = 0, bool isPreTick = false)
+ {
+ if (isPreTick)
{
- return m_solverInfo;
+ m_internalPreTickCallback = cb;
}
-
- const btContactSolverInfo& getSolverInfo() const
+ else
{
- return m_solverInfo;
+ m_internalTickCallback = cb;
}
-
-
- ///obsolete, use addAction instead.
- virtual void addVehicle(btActionInterface* vehicle) {(void)vehicle;}
- ///obsolete, use removeAction instead
- virtual void removeVehicle(btActionInterface* vehicle) {(void)vehicle;}
- ///obsolete, use addAction instead.
- virtual void addCharacter(btActionInterface* character) {(void)character;}
- ///obsolete, use removeAction instead
- virtual void removeCharacter(btActionInterface* character) {(void)character;}
-
-
+ m_worldUserInfo = worldUserInfo;
+ }
+
+ void setWorldUserInfo(void* worldUserInfo)
+ {
+ m_worldUserInfo = worldUserInfo;
+ }
+
+ void* getWorldUserInfo() const
+ {
+ return m_worldUserInfo;
+ }
+
+ btContactSolverInfo& getSolverInfo()
+ {
+ return m_solverInfo;
+ }
+
+ const btContactSolverInfo& getSolverInfo() const
+ {
+ return m_solverInfo;
+ }
+
+ ///obsolete, use addAction instead.
+ virtual void addVehicle(btActionInterface* vehicle) { (void)vehicle; }
+ ///obsolete, use removeAction instead
+ virtual void removeVehicle(btActionInterface* vehicle) { (void)vehicle; }
+ ///obsolete, use addAction instead.
+ virtual void addCharacter(btActionInterface* character) { (void)character; }
+ ///obsolete, use removeAction instead
+ virtual void removeCharacter(btActionInterface* character) { (void)character; }
};
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
struct btDynamicsWorldDoubleData
{
- btContactSolverInfoDoubleData m_solverInfo;
- btVector3DoubleData m_gravity;
+ btContactSolverInfoDoubleData m_solverInfo;
+ btVector3DoubleData m_gravity;
};
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
struct btDynamicsWorldFloatData
{
- btContactSolverInfoFloatData m_solverInfo;
- btVector3FloatData m_gravity;
+ btContactSolverInfoFloatData m_solverInfo;
+ btVector3FloatData m_gravity;
};
-
-#endif //BT_DYNAMICS_WORLD_H
-
-
+#endif //BT_DYNAMICS_WORLD_H
diff --git a/thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.cpp b/thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.cpp
index ca0714fcfa..f4bcabada2 100644
--- a/thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.cpp
+++ b/thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.cpp
@@ -22,36 +22,34 @@ subject to the following restrictions:
#include "LinearMath/btSerializer.h"
//'temporarily' global variables
-btScalar gDeactivationTime = btScalar(2.);
-bool gDisableDeactivation = false;
+btScalar gDeactivationTime = btScalar(2.);
+bool gDisableDeactivation = false;
static int uniqueId = 0;
-
btRigidBody::btRigidBody(const btRigidBody::btRigidBodyConstructionInfo& constructionInfo)
{
setupRigidBody(constructionInfo);
}
-btRigidBody::btRigidBody(btScalar mass, btMotionState *motionState, btCollisionShape *collisionShape, const btVector3 &localInertia)
+btRigidBody::btRigidBody(btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia)
{
- btRigidBodyConstructionInfo cinfo(mass,motionState,collisionShape,localInertia);
+ btRigidBodyConstructionInfo cinfo(mass, motionState, collisionShape, localInertia);
setupRigidBody(cinfo);
}
-void btRigidBody::setupRigidBody(const btRigidBody::btRigidBodyConstructionInfo& constructionInfo)
+void btRigidBody::setupRigidBody(const btRigidBody::btRigidBodyConstructionInfo& constructionInfo)
{
-
- m_internalType=CO_RIGID_BODY;
+ m_internalType = CO_RIGID_BODY;
m_linearVelocity.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
- m_angularVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
- m_angularFactor.setValue(1,1,1);
- m_linearFactor.setValue(1,1,1);
+ m_angularVelocity.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
+ m_angularFactor.setValue(1, 1, 1);
+ m_linearFactor.setValue(1, 1, 1);
m_gravity.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
m_gravity_acceleration.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
m_totalForce.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
m_totalTorque.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)),
- setDamping(constructionInfo.m_linearDamping, constructionInfo.m_angularDamping);
+ setDamping(constructionInfo.m_linearDamping, constructionInfo.m_angularDamping);
m_linearSleepingThreshold = constructionInfo.m_linearSleepingThreshold;
m_angularSleepingThreshold = constructionInfo.m_angularSleepingThreshold;
@@ -67,48 +65,44 @@ void btRigidBody::setupRigidBody(const btRigidBody::btRigidBodyConstructionInfo&
if (m_optionalMotionState)
{
m_optionalMotionState->getWorldTransform(m_worldTransform);
- } else
+ }
+ else
{
m_worldTransform = constructionInfo.m_startWorldTransform;
}
m_interpolationWorldTransform = m_worldTransform;
- m_interpolationLinearVelocity.setValue(0,0,0);
- m_interpolationAngularVelocity.setValue(0,0,0);
-
+ m_interpolationLinearVelocity.setValue(0, 0, 0);
+ m_interpolationAngularVelocity.setValue(0, 0, 0);
+
//moved to btCollisionObject
m_friction = constructionInfo.m_friction;
m_rollingFriction = constructionInfo.m_rollingFriction;
- m_spinningFriction = constructionInfo.m_spinningFriction;
-
+ m_spinningFriction = constructionInfo.m_spinningFriction;
+
m_restitution = constructionInfo.m_restitution;
- setCollisionShape( constructionInfo.m_collisionShape );
+ setCollisionShape(constructionInfo.m_collisionShape);
m_debugBodyId = uniqueId++;
-
+
setMassProps(constructionInfo.m_mass, constructionInfo.m_localInertia);
updateInertiaTensor();
m_rigidbodyFlags = BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY;
-
m_deltaLinearVelocity.setZero();
m_deltaAngularVelocity.setZero();
- m_invMass = m_inverseMass*m_linearFactor;
+ m_invMass = m_inverseMass * m_linearFactor;
m_pushVelocity.setZero();
m_turnVelocity.setZero();
-
-
-
}
-
-void btRigidBody::predictIntegratedTransform(btScalar timeStep,btTransform& predictedTransform)
+void btRigidBody::predictIntegratedTransform(btScalar timeStep, btTransform& predictedTransform)
{
- btTransformUtil::integrateTransform(m_worldTransform,m_linearVelocity,m_angularVelocity,timeStep,predictedTransform);
+ btTransformUtil::integrateTransform(m_worldTransform, m_linearVelocity, m_angularVelocity, timeStep, predictedTransform);
}
-void btRigidBody::saveKinematicState(btScalar timeStep)
+void btRigidBody::saveKinematicState(btScalar timeStep)
{
//todo: clamp to some (user definable) safe minimum timestep, to limit maximum angular/linear velocities
if (timeStep != btScalar(0.))
@@ -116,25 +110,22 @@ void btRigidBody::saveKinematicState(btScalar timeStep)
//if we use motionstate to synchronize world transforms, get the new kinematic/animated world transform
if (getMotionState())
getMotionState()->getWorldTransform(m_worldTransform);
- btVector3 linVel,angVel;
-
- btTransformUtil::calculateVelocity(m_interpolationWorldTransform,m_worldTransform,timeStep,m_linearVelocity,m_angularVelocity);
+ btVector3 linVel, angVel;
+
+ btTransformUtil::calculateVelocity(m_interpolationWorldTransform, m_worldTransform, timeStep, m_linearVelocity, m_angularVelocity);
m_interpolationLinearVelocity = m_linearVelocity;
m_interpolationAngularVelocity = m_angularVelocity;
m_interpolationWorldTransform = m_worldTransform;
//printf("angular = %f %f %f\n",m_angularVelocity.getX(),m_angularVelocity.getY(),m_angularVelocity.getZ());
}
}
-
-void btRigidBody::getAabb(btVector3& aabbMin,btVector3& aabbMax) const
+
+void btRigidBody::getAabb(btVector3& aabbMin, btVector3& aabbMax) const
{
- getCollisionShape()->getAabb(m_worldTransform,aabbMin,aabbMax);
+ getCollisionShape()->getAabb(m_worldTransform, aabbMin, aabbMax);
}
-
-
-
-void btRigidBody::setGravity(const btVector3& acceleration)
+void btRigidBody::setGravity(const btVector3& acceleration)
{
if (m_inverseMass != btScalar(0.0))
{
@@ -143,22 +134,14 @@ void btRigidBody::setGravity(const btVector3& acceleration)
m_gravity_acceleration = acceleration;
}
-
-
-
-
-
void btRigidBody::setDamping(btScalar lin_damping, btScalar ang_damping)
{
m_linearDamping = btClamped(lin_damping, (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
m_angularDamping = btClamped(ang_damping, (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
}
-
-
-
///applyDamping damps the velocity, using the given m_linearDamping and m_angularDamping
-void btRigidBody::applyDamping(btScalar timeStep)
+void btRigidBody::applyDamping(btScalar timeStep)
{
//On new damping: see discussion/issue report here: http://code.google.com/p/bullet/issues/detail?id=74
//todo: do some performance comparisons (but other parts of the engine are probably bottleneck anyway
@@ -168,8 +151,8 @@ void btRigidBody::applyDamping(btScalar timeStep)
m_linearVelocity *= GEN_clamped((btScalar(1.) - timeStep * m_linearDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
m_angularVelocity *= GEN_clamped((btScalar(1.) - timeStep * m_angularDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
#else
- m_linearVelocity *= btPow(btScalar(1)-m_linearDamping, timeStep);
- m_angularVelocity *= btPow(btScalar(1)-m_angularDamping, timeStep);
+ m_linearVelocity *= btPow(btScalar(1) - m_linearDamping, timeStep);
+ m_angularVelocity *= btPow(btScalar(1) - m_angularDamping, timeStep);
#endif
if (m_additionalDamping)
@@ -182,7 +165,6 @@ void btRigidBody::applyDamping(btScalar timeStep)
m_angularVelocity *= m_additionalDampingFactor;
m_linearVelocity *= m_additionalDampingFactor;
}
-
btScalar speed = m_linearVelocity.length();
if (speed < m_linearDamping)
@@ -191,10 +173,11 @@ void btRigidBody::applyDamping(btScalar timeStep)
if (speed > dampVel)
{
btVector3 dir = m_linearVelocity.normalized();
- m_linearVelocity -= dir * dampVel;
- } else
+ m_linearVelocity -= dir * dampVel;
+ }
+ else
{
- m_linearVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+ m_linearVelocity.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
}
}
@@ -205,30 +188,28 @@ void btRigidBody::applyDamping(btScalar timeStep)
if (angSpeed > angDampVel)
{
btVector3 dir = m_angularVelocity.normalized();
- m_angularVelocity -= dir * angDampVel;
- } else
+ m_angularVelocity -= dir * angDampVel;
+ }
+ else
{
- m_angularVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+ m_angularVelocity.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
}
}
}
}
-
void btRigidBody::applyGravity()
{
if (isStaticOrKinematicObject())
return;
-
- applyCentralForce(m_gravity);
+ applyCentralForce(m_gravity);
}
void btRigidBody::proceedToTransform(const btTransform& newTrans)
{
- setCenterOfMassTransform( newTrans );
+ setCenterOfMassTransform(newTrans);
}
-
void btRigidBody::setMassProps(btScalar mass, const btVector3& inertia)
{
@@ -236,7 +217,8 @@ void btRigidBody::setMassProps(btScalar mass, const btVector3& inertia)
{
m_collisionFlags |= btCollisionObject::CF_STATIC_OBJECT;
m_inverseMass = btScalar(0.);
- } else
+ }
+ else
{
m_collisionFlags &= (~btCollisionObject::CF_STATIC_OBJECT);
m_inverseMass = btScalar(1.0) / mass;
@@ -244,50 +226,45 @@ void btRigidBody::setMassProps(btScalar mass, const btVector3& inertia)
//Fg = m * a
m_gravity = mass * m_gravity_acceleration;
-
- m_invInertiaLocal.setValue(inertia.x() != btScalar(0.0) ? btScalar(1.0) / inertia.x(): btScalar(0.0),
- inertia.y() != btScalar(0.0) ? btScalar(1.0) / inertia.y(): btScalar(0.0),
- inertia.z() != btScalar(0.0) ? btScalar(1.0) / inertia.z(): btScalar(0.0));
- m_invMass = m_linearFactor*m_inverseMass;
+ m_invInertiaLocal.setValue(inertia.x() != btScalar(0.0) ? btScalar(1.0) / inertia.x() : btScalar(0.0),
+ inertia.y() != btScalar(0.0) ? btScalar(1.0) / inertia.y() : btScalar(0.0),
+ inertia.z() != btScalar(0.0) ? btScalar(1.0) / inertia.z() : btScalar(0.0));
+
+ m_invMass = m_linearFactor * m_inverseMass;
}
-
-void btRigidBody::updateInertiaTensor()
+void btRigidBody::updateInertiaTensor()
{
m_invInertiaTensorWorld = m_worldTransform.getBasis().scaled(m_invInertiaLocal) * m_worldTransform.getBasis().transpose();
}
-
-
btVector3 btRigidBody::getLocalInertia() const
{
-
btVector3 inertiaLocal;
const btVector3 inertia = m_invInertiaLocal;
inertiaLocal.setValue(inertia.x() != btScalar(0.0) ? btScalar(1.0) / inertia.x() : btScalar(0.0),
- inertia.y() != btScalar(0.0) ? btScalar(1.0) / inertia.y() : btScalar(0.0),
- inertia.z() != btScalar(0.0) ? btScalar(1.0) / inertia.z() : btScalar(0.0));
+ inertia.y() != btScalar(0.0) ? btScalar(1.0) / inertia.y() : btScalar(0.0),
+ inertia.z() != btScalar(0.0) ? btScalar(1.0) / inertia.z() : btScalar(0.0));
return inertiaLocal;
}
inline btVector3 evalEulerEqn(const btVector3& w1, const btVector3& w0, const btVector3& T, const btScalar dt,
- const btMatrix3x3 &I)
+ const btMatrix3x3& I)
{
- const btVector3 w2 = I*w1 + w1.cross(I*w1)*dt - (T*dt + I*w0);
+ const btVector3 w2 = I * w1 + w1.cross(I * w1) * dt - (T * dt + I * w0);
return w2;
}
inline btMatrix3x3 evalEulerEqnDeriv(const btVector3& w1, const btVector3& w0, const btScalar dt,
- const btMatrix3x3 &I)
+ const btMatrix3x3& I)
{
-
btMatrix3x3 w1x, Iw1x;
- const btVector3 Iwi = (I*w1);
+ const btVector3 Iwi = (I * w1);
w1.getSkewSymmetricMatrix(&w1x[0], &w1x[1], &w1x[2]);
Iwi.getSkewSymmetricMatrix(&Iw1x[0], &Iw1x[1], &Iw1x[2]);
- const btMatrix3x3 dfw1 = I + (w1x*I - Iw1x)*dt;
+ const btMatrix3x3 dfw1 = I + (w1x * I - Iw1x) * dt;
return dfw1;
}
@@ -295,58 +272,55 @@ btVector3 btRigidBody::computeGyroscopicForceExplicit(btScalar maxGyroscopicForc
{
btVector3 inertiaLocal = getLocalInertia();
btMatrix3x3 inertiaTensorWorld = getWorldTransform().getBasis().scaled(inertiaLocal) * getWorldTransform().getBasis().transpose();
- btVector3 tmp = inertiaTensorWorld*getAngularVelocity();
+ btVector3 tmp = inertiaTensorWorld * getAngularVelocity();
btVector3 gf = getAngularVelocity().cross(tmp);
btScalar l2 = gf.length2();
- if (l2>maxGyroscopicForce*maxGyroscopicForce)
+ if (l2 > maxGyroscopicForce * maxGyroscopicForce)
{
- gf *= btScalar(1.)/btSqrt(l2)*maxGyroscopicForce;
+ gf *= btScalar(1.) / btSqrt(l2) * maxGyroscopicForce;
}
return gf;
}
-
btVector3 btRigidBody::computeGyroscopicImpulseImplicit_Body(btScalar step) const
-{
+{
btVector3 idl = getLocalInertia();
btVector3 omega1 = getAngularVelocity();
btQuaternion q = getWorldTransform().getRotation();
-
+
// Convert to body coordinates
btVector3 omegab = quatRotate(q.inverse(), omega1);
btMatrix3x3 Ib;
- Ib.setValue(idl.x(),0,0,
- 0,idl.y(),0,
- 0,0,idl.z());
-
- btVector3 ibo = Ib*omegab;
+ Ib.setValue(idl.x(), 0, 0,
+ 0, idl.y(), 0,
+ 0, 0, idl.z());
+
+ btVector3 ibo = Ib * omegab;
// Residual vector
btVector3 f = step * omegab.cross(ibo);
-
+
btMatrix3x3 skew0;
omegab.getSkewSymmetricMatrix(&skew0[0], &skew0[1], &skew0[2]);
- btVector3 om = Ib*omegab;
+ btVector3 om = Ib * omegab;
btMatrix3x3 skew1;
- om.getSkewSymmetricMatrix(&skew1[0],&skew1[1],&skew1[2]);
-
+ om.getSkewSymmetricMatrix(&skew1[0], &skew1[1], &skew1[2]);
+
// Jacobian
- btMatrix3x3 J = Ib + (skew0*Ib - skew1)*step;
-
-// btMatrix3x3 Jinv = J.inverse();
-// btVector3 omega_div = Jinv*f;
+ btMatrix3x3 J = Ib + (skew0 * Ib - skew1) * step;
+
+ // btMatrix3x3 Jinv = J.inverse();
+ // btVector3 omega_div = Jinv*f;
btVector3 omega_div = J.solve33(f);
-
+
// Single Newton-Raphson update
- omegab = omegab - omega_div;//Solve33(J, f);
+ omegab = omegab - omega_div; //Solve33(J, f);
// Back to world coordinates
- btVector3 omega2 = quatRotate(q,omegab);
- btVector3 gf = omega2-omega1;
+ btVector3 omega2 = quatRotate(q, omegab);
+ btVector3 gf = omega2 - omega1;
return gf;
}
-
-
btVector3 btRigidBody::computeGyroscopicImpulseImplicit_World(btScalar step) const
{
// use full newton-euler equations. common practice to drop the wxIw term. want it for better tumbling behavior.
@@ -361,7 +335,7 @@ btVector3 btRigidBody::computeGyroscopicImpulseImplicit_World(btScalar step) con
m_worldTransform.getBasis().transpose();
// use newtons method to find implicit solution for new angular velocity (w')
- // f(w') = -(T*step + Iw) + Iw' + w' + w'xIw'*step = 0
+ // f(w') = -(T*step + Iw) + Iw' + w' + w'xIw'*step = 0
// df/dw' = I + 1xIw'*step + w'xI*step
btVector3 w1 = w0;
@@ -383,8 +357,7 @@ btVector3 btRigidBody::computeGyroscopicImpulseImplicit_World(btScalar step) con
return gf;
}
-
-void btRigidBody::integrateVelocities(btScalar step)
+void btRigidBody::integrateVelocities(btScalar step)
{
if (isStaticOrKinematicObject())
return;
@@ -393,30 +366,28 @@ void btRigidBody::integrateVelocities(btScalar step)
m_angularVelocity += m_invInertiaTensorWorld * m_totalTorque * step;
#define MAX_ANGVEL SIMD_HALF_PI
- /// clamp angular velocity. collision calculations will fail on higher angular velocities
+ /// clamp angular velocity. collision calculations will fail on higher angular velocities
btScalar angvel = m_angularVelocity.length();
- if (angvel*step > MAX_ANGVEL)
+ if (angvel * step > MAX_ANGVEL)
{
- m_angularVelocity *= (MAX_ANGVEL/step) /angvel;
+ m_angularVelocity *= (MAX_ANGVEL / step) / angvel;
}
-
}
btQuaternion btRigidBody::getOrientation() const
{
- btQuaternion orn;
- m_worldTransform.getBasis().getRotation(orn);
- return orn;
+ btQuaternion orn;
+ m_worldTransform.getBasis().getRotation(orn);
+ return orn;
}
-
-
+
void btRigidBody::setCenterOfMassTransform(const btTransform& xform)
{
-
if (isKinematicObject())
{
m_interpolationWorldTransform = m_worldTransform;
- } else
+ }
+ else
{
m_interpolationWorldTransform = xform;
}
@@ -426,10 +397,6 @@ void btRigidBody::setCenterOfMassTransform(const btTransform& xform)
updateInertiaTensor();
}
-
-
-
-
void btRigidBody::addConstraintRef(btTypedConstraint* c)
{
///disable collision with the 'other' body
@@ -450,39 +417,39 @@ void btRigidBody::addConstraintRef(btTypedConstraint* c)
{
colObjB->setIgnoreCollisionCheck(colObjA, true);
}
- }
+ }
}
void btRigidBody::removeConstraintRef(btTypedConstraint* c)
{
int index = m_constraintRefs.findLinearSearch(c);
//don't remove constraints that are not referenced
- if(index < m_constraintRefs.size())
- {
- m_constraintRefs.remove(c);
- btCollisionObject* colObjA = &c->getRigidBodyA();
- btCollisionObject* colObjB = &c->getRigidBodyB();
- if (colObjA == this)
- {
- colObjA->setIgnoreCollisionCheck(colObjB, false);
- }
- else
- {
- colObjB->setIgnoreCollisionCheck(colObjA, false);
- }
- }
+ if (index < m_constraintRefs.size())
+ {
+ m_constraintRefs.remove(c);
+ btCollisionObject* colObjA = &c->getRigidBodyA();
+ btCollisionObject* colObjB = &c->getRigidBodyB();
+ if (colObjA == this)
+ {
+ colObjA->setIgnoreCollisionCheck(colObjB, false);
+ }
+ else
+ {
+ colObjB->setIgnoreCollisionCheck(colObjA, false);
+ }
+ }
}
-int btRigidBody::calculateSerializeBufferSize() const
+int btRigidBody::calculateSerializeBufferSize() const
{
int sz = sizeof(btRigidBodyData);
return sz;
}
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
-const char* btRigidBody::serialize(void* dataBuffer, class btSerializer* serializer) const
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char* btRigidBody::serialize(void* dataBuffer, class btSerializer* serializer) const
{
- btRigidBodyData* rbd = (btRigidBodyData*) dataBuffer;
+ btRigidBodyData* rbd = (btRigidBodyData*)dataBuffer;
btCollisionObject::serialize(&rbd->m_collisionObjectData, serializer);
@@ -504,7 +471,7 @@ const char* btRigidBody::serialize(void* dataBuffer, class btSerializer* seriali
rbd->m_additionalLinearDampingThresholdSqr = m_additionalLinearDampingThresholdSqr;
rbd->m_additionalAngularDampingThresholdSqr = m_additionalAngularDampingThresholdSqr;
rbd->m_additionalAngularDampingFactor = m_additionalAngularDampingFactor;
- rbd->m_linearSleepingThreshold=m_linearSleepingThreshold;
+ rbd->m_linearSleepingThreshold = m_linearSleepingThreshold;
rbd->m_angularSleepingThreshold = m_angularSleepingThreshold;
// Fill padding with zeros to appease msan.
@@ -515,13 +482,9 @@ const char* btRigidBody::serialize(void* dataBuffer, class btSerializer* seriali
return btRigidBodyDataName;
}
-
-
void btRigidBody::serializeSingleObject(class btSerializer* serializer) const
{
- btChunk* chunk = serializer->allocate(calculateSerializeBufferSize(),1);
+ btChunk* chunk = serializer->allocate(calculateSerializeBufferSize(), 1);
const char* structType = serialize(chunk->m_oldPtr, serializer);
- serializer->finalizeChunk(chunk,structType,BT_RIGIDBODY_CODE,(void*)this);
+ serializer->finalizeChunk(chunk, structType, BT_RIGIDBODY_CODE, (void*)this);
}
-
-
diff --git a/thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.h b/thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.h
index 372245031b..05f270a4b8 100644
--- a/thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.h
+++ b/thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.h
@@ -25,209 +25,195 @@ class btCollisionShape;
class btMotionState;
class btTypedConstraint;
-
extern btScalar gDeactivationTime;
extern bool gDisableDeactivation;
#ifdef BT_USE_DOUBLE_PRECISION
-#define btRigidBodyData btRigidBodyDoubleData
-#define btRigidBodyDataName "btRigidBodyDoubleData"
+#define btRigidBodyData btRigidBodyDoubleData
+#define btRigidBodyDataName "btRigidBodyDoubleData"
#else
-#define btRigidBodyData btRigidBodyFloatData
-#define btRigidBodyDataName "btRigidBodyFloatData"
-#endif //BT_USE_DOUBLE_PRECISION
-
+#define btRigidBodyData btRigidBodyFloatData
+#define btRigidBodyDataName "btRigidBodyFloatData"
+#endif //BT_USE_DOUBLE_PRECISION
-enum btRigidBodyFlags
+enum btRigidBodyFlags
{
BT_DISABLE_WORLD_GRAVITY = 1,
///BT_ENABLE_GYROPSCOPIC_FORCE flags is enabled by default in Bullet 2.83 and onwards.
///and it BT_ENABLE_GYROPSCOPIC_FORCE becomes equivalent to BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY
///See Demos/GyroscopicDemo and computeGyroscopicImpulseImplicit
BT_ENABLE_GYROSCOPIC_FORCE_EXPLICIT = 2,
- BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_WORLD=4,
- BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY=8,
+ BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_WORLD = 4,
+ BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY = 8,
BT_ENABLE_GYROPSCOPIC_FORCE = BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY,
};
-
///The btRigidBody is the main class for rigid body objects. It is derived from btCollisionObject, so it keeps a pointer to a btCollisionShape.
///It is recommended for performance and memory use to share btCollisionShape objects whenever possible.
-///There are 3 types of rigid bodies:
+///There are 3 types of rigid bodies:
///- A) Dynamic rigid bodies, with positive mass. Motion is controlled by rigid body dynamics.
///- B) Fixed objects with zero mass. They are not moving (basically collision objects)
-///- C) Kinematic objects, which are objects without mass, but the user can move them. There is on-way interaction, and Bullet calculates a velocity based on the timestep and previous and current world transform.
+///- C) Kinematic objects, which are objects without mass, but the user can move them. There is one-way interaction, and Bullet calculates a velocity based on the timestep and previous and current world transform.
///Bullet automatically deactivates dynamic rigid bodies, when the velocity is below a threshold for a given time.
///Deactivated (sleeping) rigid bodies don't take any processing time, except a minor broadphase collision detection impact (to allow active objects to activate/wake up sleeping objects)
-class btRigidBody : public btCollisionObject
+class btRigidBody : public btCollisionObject
{
-
- btMatrix3x3 m_invInertiaTensorWorld;
- btVector3 m_linearVelocity;
- btVector3 m_angularVelocity;
- btScalar m_inverseMass;
- btVector3 m_linearFactor;
-
- btVector3 m_gravity;
- btVector3 m_gravity_acceleration;
- btVector3 m_invInertiaLocal;
- btVector3 m_totalForce;
- btVector3 m_totalTorque;
-
- btScalar m_linearDamping;
- btScalar m_angularDamping;
-
- bool m_additionalDamping;
- btScalar m_additionalDampingFactor;
- btScalar m_additionalLinearDampingThresholdSqr;
- btScalar m_additionalAngularDampingThresholdSqr;
- btScalar m_additionalAngularDampingFactor;
-
-
- btScalar m_linearSleepingThreshold;
- btScalar m_angularSleepingThreshold;
+ btMatrix3x3 m_invInertiaTensorWorld;
+ btVector3 m_linearVelocity;
+ btVector3 m_angularVelocity;
+ btScalar m_inverseMass;
+ btVector3 m_linearFactor;
+
+ btVector3 m_gravity;
+ btVector3 m_gravity_acceleration;
+ btVector3 m_invInertiaLocal;
+ btVector3 m_totalForce;
+ btVector3 m_totalTorque;
+
+ btScalar m_linearDamping;
+ btScalar m_angularDamping;
+
+ bool m_additionalDamping;
+ btScalar m_additionalDampingFactor;
+ btScalar m_additionalLinearDampingThresholdSqr;
+ btScalar m_additionalAngularDampingThresholdSqr;
+ btScalar m_additionalAngularDampingFactor;
+
+ btScalar m_linearSleepingThreshold;
+ btScalar m_angularSleepingThreshold;
//m_optionalMotionState allows to automatic synchronize the world transform for active objects
- btMotionState* m_optionalMotionState;
+ btMotionState* m_optionalMotionState;
//keep track of typed constraints referencing this rigid body, to disable collision between linked bodies
btAlignedObjectArray<btTypedConstraint*> m_constraintRefs;
- int m_rigidbodyFlags;
-
- int m_debugBodyId;
-
+ int m_rigidbodyFlags;
-protected:
-
- ATTRIBUTE_ALIGNED16(btVector3 m_deltaLinearVelocity);
- btVector3 m_deltaAngularVelocity;
- btVector3 m_angularFactor;
- btVector3 m_invMass;
- btVector3 m_pushVelocity;
- btVector3 m_turnVelocity;
+ int m_debugBodyId;
+protected:
+ ATTRIBUTE_ALIGNED16(btVector3 m_deltaLinearVelocity);
+ btVector3 m_deltaAngularVelocity;
+ btVector3 m_angularFactor;
+ btVector3 m_invMass;
+ btVector3 m_pushVelocity;
+ btVector3 m_turnVelocity;
public:
-
-
///The btRigidBodyConstructionInfo structure provides information to create a rigid body. Setting mass to zero creates a fixed (non-dynamic) rigid body.
///For dynamic objects, you can use the collision shape to approximate the local inertia tensor, otherwise use the zero vector (default argument)
- ///You can use the motion state to synchronize the world transform between physics and graphics objects.
+ ///You can use the motion state to synchronize the world transform between physics and graphics objects.
///And if the motion state is provided, the rigid body will initialize its initial world transform from the motion state,
///m_startWorldTransform is only used when you don't provide a motion state.
- struct btRigidBodyConstructionInfo
+ struct btRigidBodyConstructionInfo
{
- btScalar m_mass;
+ btScalar m_mass;
///When a motionState is provided, the rigid body will initialize its world transform from the motion state
///In this case, m_startWorldTransform is ignored.
- btMotionState* m_motionState;
- btTransform m_startWorldTransform;
+ btMotionState* m_motionState;
+ btTransform m_startWorldTransform;
- btCollisionShape* m_collisionShape;
- btVector3 m_localInertia;
- btScalar m_linearDamping;
- btScalar m_angularDamping;
+ btCollisionShape* m_collisionShape;
+ btVector3 m_localInertia;
+ btScalar m_linearDamping;
+ btScalar m_angularDamping;
///best simulation results when friction is non-zero
- btScalar m_friction;
+ btScalar m_friction;
///the m_rollingFriction prevents rounded shapes, such as spheres, cylinders and capsules from rolling forever.
///See Bullet/Demos/RollingFrictionDemo for usage
- btScalar m_rollingFriction;
- btScalar m_spinningFriction;//torsional friction around contact normal
-
+ btScalar m_rollingFriction;
+ btScalar m_spinningFriction; //torsional friction around contact normal
+
///best simulation results using zero restitution.
- btScalar m_restitution;
+ btScalar m_restitution;
- btScalar m_linearSleepingThreshold;
- btScalar m_angularSleepingThreshold;
+ btScalar m_linearSleepingThreshold;
+ btScalar m_angularSleepingThreshold;
//Additional damping can help avoiding lowpass jitter motion, help stability for ragdolls etc.
//Such damping is undesirable, so once the overall simulation quality of the rigid body dynamics system has improved, this should become obsolete
- bool m_additionalDamping;
- btScalar m_additionalDampingFactor;
- btScalar m_additionalLinearDampingThresholdSqr;
- btScalar m_additionalAngularDampingThresholdSqr;
- btScalar m_additionalAngularDampingFactor;
-
- btRigidBodyConstructionInfo( btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0)):
- m_mass(mass),
- m_motionState(motionState),
- m_collisionShape(collisionShape),
- m_localInertia(localInertia),
- m_linearDamping(btScalar(0.)),
- m_angularDamping(btScalar(0.)),
- m_friction(btScalar(0.5)),
- m_rollingFriction(btScalar(0)),
- m_spinningFriction(btScalar(0)),
- m_restitution(btScalar(0.)),
- m_linearSleepingThreshold(btScalar(0.8)),
- m_angularSleepingThreshold(btScalar(1.f)),
- m_additionalDamping(false),
- m_additionalDampingFactor(btScalar(0.005)),
- m_additionalLinearDampingThresholdSqr(btScalar(0.01)),
- m_additionalAngularDampingThresholdSqr(btScalar(0.01)),
- m_additionalAngularDampingFactor(btScalar(0.01))
+ bool m_additionalDamping;
+ btScalar m_additionalDampingFactor;
+ btScalar m_additionalLinearDampingThresholdSqr;
+ btScalar m_additionalAngularDampingThresholdSqr;
+ btScalar m_additionalAngularDampingFactor;
+
+ btRigidBodyConstructionInfo(btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia = btVector3(0, 0, 0)) : m_mass(mass),
+ m_motionState(motionState),
+ m_collisionShape(collisionShape),
+ m_localInertia(localInertia),
+ m_linearDamping(btScalar(0.)),
+ m_angularDamping(btScalar(0.)),
+ m_friction(btScalar(0.5)),
+ m_rollingFriction(btScalar(0)),
+ m_spinningFriction(btScalar(0)),
+ m_restitution(btScalar(0.)),
+ m_linearSleepingThreshold(btScalar(0.8)),
+ m_angularSleepingThreshold(btScalar(1.f)),
+ m_additionalDamping(false),
+ m_additionalDampingFactor(btScalar(0.005)),
+ m_additionalLinearDampingThresholdSqr(btScalar(0.01)),
+ m_additionalAngularDampingThresholdSqr(btScalar(0.01)),
+ m_additionalAngularDampingFactor(btScalar(0.01))
{
m_startWorldTransform.setIdentity();
}
};
///btRigidBody constructor using construction info
- btRigidBody( const btRigidBodyConstructionInfo& constructionInfo);
+ btRigidBody(const btRigidBodyConstructionInfo& constructionInfo);
- ///btRigidBody constructor for backwards compatibility.
+ ///btRigidBody constructor for backwards compatibility.
///To specify friction (etc) during rigid body construction, please use the other constructor (using btRigidBodyConstructionInfo)
- btRigidBody( btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0));
-
+ btRigidBody(btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia = btVector3(0, 0, 0));
virtual ~btRigidBody()
- {
- //No constraints should point to this rigidbody
- //Remove constraints from the dynamics world before you delete the related rigidbodies.
- btAssert(m_constraintRefs.size()==0);
- }
+ {
+ //No constraints should point to this rigidbody
+ //Remove constraints from the dynamics world before you delete the related rigidbodies.
+ btAssert(m_constraintRefs.size() == 0);
+ }
protected:
-
///setupRigidBody is only used internally by the constructor
- void setupRigidBody(const btRigidBodyConstructionInfo& constructionInfo);
+ void setupRigidBody(const btRigidBodyConstructionInfo& constructionInfo);
public:
+ void proceedToTransform(const btTransform& newTrans);
- void proceedToTransform(const btTransform& newTrans);
-
///to keep collision detection and dynamics separate we don't store a rigidbody pointer
///but a rigidbody is derived from btCollisionObject, so we can safely perform an upcast
- static const btRigidBody* upcast(const btCollisionObject* colObj)
+ static const btRigidBody* upcast(const btCollisionObject* colObj)
{
- if (colObj->getInternalType()&btCollisionObject::CO_RIGID_BODY)
+ if (colObj->getInternalType() & btCollisionObject::CO_RIGID_BODY)
return (const btRigidBody*)colObj;
return 0;
}
- static btRigidBody* upcast(btCollisionObject* colObj)
+ static btRigidBody* upcast(btCollisionObject* colObj)
{
- if (colObj->getInternalType()&btCollisionObject::CO_RIGID_BODY)
+ if (colObj->getInternalType() & btCollisionObject::CO_RIGID_BODY)
return (btRigidBody*)colObj;
return 0;
}
-
+
/// continuous collision detection needs prediction
- void predictIntegratedTransform(btScalar step, btTransform& predictedTransform) ;
-
- void saveKinematicState(btScalar step);
-
- void applyGravity();
-
- void setGravity(const btVector3& acceleration);
+ void predictIntegratedTransform(btScalar step, btTransform& predictedTransform);
+
+ void saveKinematicState(btScalar step);
+
+ void applyGravity();
+
+ void setGravity(const btVector3& acceleration);
- const btVector3& getGravity() const
+ const btVector3& getGravity() const
{
return m_gravity_acceleration;
}
- void setDamping(btScalar lin_damping, btScalar ang_damping);
+ void setDamping(btScalar lin_damping, btScalar ang_damping);
btScalar getLinearDamping() const
{
@@ -249,18 +235,20 @@ public:
return m_angularSleepingThreshold;
}
- void applyDamping(btScalar timeStep);
+ void applyDamping(btScalar timeStep);
- SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const {
+ SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const
+ {
return m_collisionShape;
}
- SIMD_FORCE_INLINE btCollisionShape* getCollisionShape() {
- return m_collisionShape;
+ SIMD_FORCE_INLINE btCollisionShape* getCollisionShape()
+ {
+ return m_collisionShape;
}
-
- void setMassProps(btScalar mass, const btVector3& inertia);
-
+
+ void setMassProps(btScalar mass, const btVector3& inertia);
+
const btVector3& getLinearFactor() const
{
return m_linearFactor;
@@ -268,20 +256,21 @@ public:
void setLinearFactor(const btVector3& linearFactor)
{
m_linearFactor = linearFactor;
- m_invMass = m_linearFactor*m_inverseMass;
+ m_invMass = m_linearFactor * m_inverseMass;
}
- btScalar getInvMass() const { return m_inverseMass; }
- const btMatrix3x3& getInvInertiaTensorWorld() const {
- return m_invInertiaTensorWorld;
+ btScalar getInvMass() const { return m_inverseMass; }
+ const btMatrix3x3& getInvInertiaTensorWorld() const
+ {
+ return m_invInertiaTensorWorld;
}
-
- void integrateVelocities(btScalar step);
- void setCenterOfMassTransform(const btTransform& xform);
+ void integrateVelocities(btScalar step);
+
+ void setCenterOfMassTransform(const btTransform& xform);
- void applyCentralForce(const btVector3& force)
+ void applyCentralForce(const btVector3& force)
{
- m_totalForce += force*m_linearFactor;
+ m_totalForce += force * m_linearFactor;
}
const btVector3& getTotalForce() const
@@ -293,90 +282,93 @@ public:
{
return m_totalTorque;
};
-
+
const btVector3& getInvInertiaDiagLocal() const
{
return m_invInertiaLocal;
};
- void setInvInertiaDiagLocal(const btVector3& diagInvInertia)
+ void setInvInertiaDiagLocal(const btVector3& diagInvInertia)
{
m_invInertiaLocal = diagInvInertia;
}
- void setSleepingThresholds(btScalar linear,btScalar angular)
+ void setSleepingThresholds(btScalar linear, btScalar angular)
{
m_linearSleepingThreshold = linear;
m_angularSleepingThreshold = angular;
}
- void applyTorque(const btVector3& torque)
+ void applyTorque(const btVector3& torque)
{
- m_totalTorque += torque*m_angularFactor;
+ m_totalTorque += torque * m_angularFactor;
}
-
- void applyForce(const btVector3& force, const btVector3& rel_pos)
+
+ void applyForce(const btVector3& force, const btVector3& rel_pos)
{
applyCentralForce(force);
- applyTorque(rel_pos.cross(force*m_linearFactor));
+ applyTorque(rel_pos.cross(force * m_linearFactor));
}
-
+
void applyCentralImpulse(const btVector3& impulse)
{
- m_linearVelocity += impulse *m_linearFactor * m_inverseMass;
+ m_linearVelocity += impulse * m_linearFactor * m_inverseMass;
}
-
- void applyTorqueImpulse(const btVector3& torque)
+
+ void applyTorqueImpulse(const btVector3& torque)
{
- m_angularVelocity += m_invInertiaTensorWorld * torque * m_angularFactor;
+ m_angularVelocity += m_invInertiaTensorWorld * torque * m_angularFactor;
}
-
- void applyImpulse(const btVector3& impulse, const btVector3& rel_pos)
+
+ void applyImpulse(const btVector3& impulse, const btVector3& rel_pos)
{
if (m_inverseMass != btScalar(0.))
{
applyCentralImpulse(impulse);
if (m_angularFactor)
{
- applyTorqueImpulse(rel_pos.cross(impulse*m_linearFactor));
+ applyTorqueImpulse(rel_pos.cross(impulse * m_linearFactor));
}
}
}
- void clearForces()
+ void clearForces()
{
m_totalForce.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
m_totalTorque.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
}
-
- void updateInertiaTensor();
-
- const btVector3& getCenterOfMassPosition() const {
- return m_worldTransform.getOrigin();
+
+ void updateInertiaTensor();
+
+ const btVector3& getCenterOfMassPosition() const
+ {
+ return m_worldTransform.getOrigin();
}
btQuaternion getOrientation() const;
-
- const btTransform& getCenterOfMassTransform() const {
- return m_worldTransform;
+
+ const btTransform& getCenterOfMassTransform() const
+ {
+ return m_worldTransform;
}
- const btVector3& getLinearVelocity() const {
- return m_linearVelocity;
+ const btVector3& getLinearVelocity() const
+ {
+ return m_linearVelocity;
}
- const btVector3& getAngularVelocity() const {
- return m_angularVelocity;
+ const btVector3& getAngularVelocity() const
+ {
+ return m_angularVelocity;
}
-
inline void setLinearVelocity(const btVector3& lin_vel)
- {
+ {
m_updateRevision++;
- m_linearVelocity = lin_vel;
+ m_linearVelocity = lin_vel;
}
- inline void setAngularVelocity(const btVector3& ang_vel)
- {
+ inline void setAngularVelocity(const btVector3& ang_vel)
+ {
m_updateRevision++;
- m_angularVelocity = ang_vel;
+ m_angularVelocity = ang_vel;
}
btVector3 getVelocityInLocalPoint(const btVector3& rel_pos) const
@@ -388,18 +380,13 @@ public:
// return (m_worldTransform(rel_pos) - m_interpolationWorldTransform(rel_pos)) / m_kinematicTimeStep;
}
- void translate(const btVector3& v)
+ void translate(const btVector3& v)
{
- m_worldTransform.getOrigin() += v;
+ m_worldTransform.getOrigin() += v;
}
-
- void getAabb(btVector3& aabbMin,btVector3& aabbMax) const;
-
+ void getAabb(btVector3& aabbMin, btVector3& aabbMax) const;
-
-
-
SIMD_FORCE_INLINE btScalar computeImpulseDenominator(const btVector3& pos, const btVector3& normal) const
{
btVector3 r0 = pos - getCenterOfMassPosition();
@@ -409,7 +396,6 @@ public:
btVector3 vec = (c0 * getInvInertiaTensorWorld()).cross(r0);
return m_inverseMass + normal.dot(vec);
-
}
SIMD_FORCE_INLINE btScalar computeAngularImpulseDenominator(const btVector3& axis) const
@@ -418,26 +404,25 @@ public:
return axis.dot(vec);
}
- SIMD_FORCE_INLINE void updateDeactivation(btScalar timeStep)
+ SIMD_FORCE_INLINE void updateDeactivation(btScalar timeStep)
{
- if ( (getActivationState() == ISLAND_SLEEPING) || (getActivationState() == DISABLE_DEACTIVATION))
+ if ((getActivationState() == ISLAND_SLEEPING) || (getActivationState() == DISABLE_DEACTIVATION))
return;
- if ((getLinearVelocity().length2() < m_linearSleepingThreshold*m_linearSleepingThreshold) &&
- (getAngularVelocity().length2() < m_angularSleepingThreshold*m_angularSleepingThreshold))
+ if ((getLinearVelocity().length2() < m_linearSleepingThreshold * m_linearSleepingThreshold) &&
+ (getAngularVelocity().length2() < m_angularSleepingThreshold * m_angularSleepingThreshold))
{
m_deactivationTime += timeStep;
- } else
+ }
+ else
{
- m_deactivationTime=btScalar(0.);
+ m_deactivationTime = btScalar(0.);
setActivationState(0);
}
-
}
- SIMD_FORCE_INLINE bool wantsSleeping()
+ SIMD_FORCE_INLINE bool wantsSleeping()
{
-
if (getActivationState() == DISABLE_DEACTIVATION)
return false;
@@ -445,41 +430,39 @@ public:
if (gDisableDeactivation || (gDeactivationTime == btScalar(0.)))
return false;
- if ( (getActivationState() == ISLAND_SLEEPING) || (getActivationState() == WANTS_DEACTIVATION))
+ if ((getActivationState() == ISLAND_SLEEPING) || (getActivationState() == WANTS_DEACTIVATION))
return true;
- if (m_deactivationTime> gDeactivationTime)
+ if (m_deactivationTime > gDeactivationTime)
{
return true;
}
return false;
}
-
-
- const btBroadphaseProxy* getBroadphaseProxy() const
+ const btBroadphaseProxy* getBroadphaseProxy() const
{
return m_broadphaseHandle;
}
- btBroadphaseProxy* getBroadphaseProxy()
+ btBroadphaseProxy* getBroadphaseProxy()
{
return m_broadphaseHandle;
}
- void setNewBroadphaseProxy(btBroadphaseProxy* broadphaseProxy)
+ void setNewBroadphaseProxy(btBroadphaseProxy* broadphaseProxy)
{
m_broadphaseHandle = broadphaseProxy;
}
//btMotionState allows to automatic synchronize the world transform for active objects
- btMotionState* getMotionState()
+ btMotionState* getMotionState()
{
return m_optionalMotionState;
}
- const btMotionState* getMotionState() const
+ const btMotionState* getMotionState() const
{
return m_optionalMotionState;
}
- void setMotionState(btMotionState* motionState)
+ void setMotionState(btMotionState* motionState)
{
m_optionalMotionState = motionState;
if (m_optionalMotionState)
@@ -487,27 +470,27 @@ public:
}
//for experimental overriding of friction/contact solver func
- int m_contactSolverType;
- int m_frictionSolverType;
+ int m_contactSolverType;
+ int m_frictionSolverType;
- void setAngularFactor(const btVector3& angFac)
+ void setAngularFactor(const btVector3& angFac)
{
m_updateRevision++;
m_angularFactor = angFac;
}
- void setAngularFactor(btScalar angFac)
+ void setAngularFactor(btScalar angFac)
{
m_updateRevision++;
- m_angularFactor.setValue(angFac,angFac,angFac);
+ m_angularFactor.setValue(angFac, angFac, angFac);
}
- const btVector3& getAngularFactor() const
+ const btVector3& getAngularFactor() const
{
return m_angularFactor;
}
//is this rigidbody added to a btCollisionWorld/btDynamicsWorld/btBroadphase?
- bool isInWorld() const
+ bool isInWorld() const
{
return (getBroadphaseProxy() != 0);
}
@@ -525,7 +508,7 @@ public:
return m_constraintRefs.size();
}
- void setFlags(int flags)
+ void setFlags(int flags)
{
m_rigidbodyFlags = flags;
}
@@ -535,12 +518,9 @@ public:
return m_rigidbodyFlags;
}
-
-
-
///perform implicit force computation in world space
btVector3 computeGyroscopicImpulseImplicit_World(btScalar dt) const;
-
+
///perform implicit force computation in body space (inertial frame)
btVector3 computeGyroscopicImpulseImplicit_Body(btScalar step) const;
@@ -550,70 +530,66 @@ public:
///////////////////////////////////////////////
- virtual int calculateSerializeBufferSize() const;
+ virtual int calculateSerializeBufferSize() const;
///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const;
+ virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const;
virtual void serializeSingleObject(class btSerializer* serializer) const;
-
};
//@todo add m_optionalMotionState and m_constraintRefs to btRigidBodyData
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btRigidBodyFloatData
+struct btRigidBodyFloatData
{
- btCollisionObjectFloatData m_collisionObjectData;
- btMatrix3x3FloatData m_invInertiaTensorWorld;
- btVector3FloatData m_linearVelocity;
- btVector3FloatData m_angularVelocity;
- btVector3FloatData m_angularFactor;
- btVector3FloatData m_linearFactor;
- btVector3FloatData m_gravity;
- btVector3FloatData m_gravity_acceleration;
- btVector3FloatData m_invInertiaLocal;
- btVector3FloatData m_totalForce;
- btVector3FloatData m_totalTorque;
- float m_inverseMass;
- float m_linearDamping;
- float m_angularDamping;
- float m_additionalDampingFactor;
- float m_additionalLinearDampingThresholdSqr;
- float m_additionalAngularDampingThresholdSqr;
- float m_additionalAngularDampingFactor;
- float m_linearSleepingThreshold;
- float m_angularSleepingThreshold;
- int m_additionalDamping;
+ btCollisionObjectFloatData m_collisionObjectData;
+ btMatrix3x3FloatData m_invInertiaTensorWorld;
+ btVector3FloatData m_linearVelocity;
+ btVector3FloatData m_angularVelocity;
+ btVector3FloatData m_angularFactor;
+ btVector3FloatData m_linearFactor;
+ btVector3FloatData m_gravity;
+ btVector3FloatData m_gravity_acceleration;
+ btVector3FloatData m_invInertiaLocal;
+ btVector3FloatData m_totalForce;
+ btVector3FloatData m_totalTorque;
+ float m_inverseMass;
+ float m_linearDamping;
+ float m_angularDamping;
+ float m_additionalDampingFactor;
+ float m_additionalLinearDampingThresholdSqr;
+ float m_additionalAngularDampingThresholdSqr;
+ float m_additionalAngularDampingFactor;
+ float m_linearSleepingThreshold;
+ float m_angularSleepingThreshold;
+ int m_additionalDamping;
};
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btRigidBodyDoubleData
+struct btRigidBodyDoubleData
{
- btCollisionObjectDoubleData m_collisionObjectData;
- btMatrix3x3DoubleData m_invInertiaTensorWorld;
- btVector3DoubleData m_linearVelocity;
- btVector3DoubleData m_angularVelocity;
- btVector3DoubleData m_angularFactor;
- btVector3DoubleData m_linearFactor;
- btVector3DoubleData m_gravity;
- btVector3DoubleData m_gravity_acceleration;
- btVector3DoubleData m_invInertiaLocal;
- btVector3DoubleData m_totalForce;
- btVector3DoubleData m_totalTorque;
- double m_inverseMass;
- double m_linearDamping;
- double m_angularDamping;
- double m_additionalDampingFactor;
- double m_additionalLinearDampingThresholdSqr;
- double m_additionalAngularDampingThresholdSqr;
- double m_additionalAngularDampingFactor;
- double m_linearSleepingThreshold;
- double m_angularSleepingThreshold;
- int m_additionalDamping;
- char m_padding[4];
+ btCollisionObjectDoubleData m_collisionObjectData;
+ btMatrix3x3DoubleData m_invInertiaTensorWorld;
+ btVector3DoubleData m_linearVelocity;
+ btVector3DoubleData m_angularVelocity;
+ btVector3DoubleData m_angularFactor;
+ btVector3DoubleData m_linearFactor;
+ btVector3DoubleData m_gravity;
+ btVector3DoubleData m_gravity_acceleration;
+ btVector3DoubleData m_invInertiaLocal;
+ btVector3DoubleData m_totalForce;
+ btVector3DoubleData m_totalTorque;
+ double m_inverseMass;
+ double m_linearDamping;
+ double m_angularDamping;
+ double m_additionalDampingFactor;
+ double m_additionalLinearDampingThresholdSqr;
+ double m_additionalAngularDampingThresholdSqr;
+ double m_additionalAngularDampingFactor;
+ double m_linearSleepingThreshold;
+ double m_angularSleepingThreshold;
+ int m_additionalDamping;
+ char m_padding[4];
};
-
-
-#endif //BT_RIGIDBODY_H
-
+#endif //BT_RIGIDBODY_H
diff --git a/thirdparty/bullet/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp b/thirdparty/bullet/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp
index 6f63b87c80..8103390fb1 100644
--- a/thirdparty/bullet/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp
+++ b/thirdparty/bullet/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp
@@ -21,47 +21,40 @@ subject to the following restrictions:
#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
-
/*
Make sure this dummy function never changes so that it
can be used by probes that are checking whether the
library is actually installed.
*/
-extern "C"
+extern "C"
{
- void btBulletDynamicsProbe ();
- void btBulletDynamicsProbe () {}
+ void btBulletDynamicsProbe();
+ void btBulletDynamicsProbe() {}
}
-
-
-
-btSimpleDynamicsWorld::btSimpleDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration)
-:btDynamicsWorld(dispatcher,pairCache,collisionConfiguration),
-m_constraintSolver(constraintSolver),
-m_ownsConstraintSolver(false),
-m_gravity(0,0,-10)
+btSimpleDynamicsWorld::btSimpleDynamicsWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration)
+ : btDynamicsWorld(dispatcher, pairCache, collisionConfiguration),
+ m_constraintSolver(constraintSolver),
+ m_ownsConstraintSolver(false),
+ m_gravity(0, 0, -10)
{
-
}
-
btSimpleDynamicsWorld::~btSimpleDynamicsWorld()
{
if (m_ownsConstraintSolver)
- btAlignedFree( m_constraintSolver);
+ btAlignedFree(m_constraintSolver);
}
-int btSimpleDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, btScalar fixedTimeStep)
+int btSimpleDynamicsWorld::stepSimulation(btScalar timeStep, int maxSubSteps, btScalar fixedTimeStep)
{
(void)fixedTimeStep;
(void)maxSubSteps;
-
///apply gravity, predict motion
predictUnconstraintMotion(timeStep);
- btDispatcherInfo& dispatchInfo = getDispatchInfo();
+ btDispatcherInfo& dispatchInfo = getDispatchInfo();
dispatchInfo.m_timeStep = timeStep;
dispatchInfo.m_stepCount = 0;
dispatchInfo.m_debugDraw = getDebugDrawer();
@@ -74,17 +67,17 @@ int btSimpleDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, b
if (numManifolds)
{
btPersistentManifold** manifoldPtr = ((btCollisionDispatcher*)m_dispatcher1)->getInternalManifoldPointer();
-
+
btContactSolverInfo infoGlobal;
infoGlobal.m_timeStep = timeStep;
- m_constraintSolver->prepareSolve(0,numManifolds);
- m_constraintSolver->solveGroup(&getCollisionObjectArray()[0],getNumCollisionObjects(),manifoldPtr, numManifolds,0,0,infoGlobal,m_debugDrawer, m_dispatcher1);
- m_constraintSolver->allSolved(infoGlobal,m_debugDrawer);
+ m_constraintSolver->prepareSolve(0, numManifolds);
+ m_constraintSolver->solveGroup(&getCollisionObjectArray()[0], getNumCollisionObjects(), manifoldPtr, numManifolds, 0, 0, infoGlobal, m_debugDrawer, m_dispatcher1);
+ m_constraintSolver->allSolved(infoGlobal, m_debugDrawer);
}
///integrate transforms
integrateTransforms(timeStep);
-
+
updateAabbs();
synchronizeMotionStates();
@@ -92,29 +85,27 @@ int btSimpleDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, b
clearForces();
return 1;
-
}
-void btSimpleDynamicsWorld::clearForces()
+void btSimpleDynamicsWorld::clearForces()
{
///@todo: iterate over awake simulation islands!
- for ( int i=0;i<m_collisionObjects.size();i++)
+ for (int i = 0; i < m_collisionObjects.size(); i++)
{
btCollisionObject* colObj = m_collisionObjects[i];
-
+
btRigidBody* body = btRigidBody::upcast(colObj);
if (body)
{
body->clearForces();
}
}
-}
-
+}
-void btSimpleDynamicsWorld::setGravity(const btVector3& gravity)
+void btSimpleDynamicsWorld::setGravity(const btVector3& gravity)
{
m_gravity = gravity;
- for ( int i=0;i<m_collisionObjects.size();i++)
+ for (int i = 0; i < m_collisionObjects.size(); i++)
{
btCollisionObject* colObj = m_collisionObjects[i];
btRigidBody* body = btRigidBody::upcast(colObj);
@@ -125,17 +116,17 @@ void btSimpleDynamicsWorld::setGravity(const btVector3& gravity)
}
}
-btVector3 btSimpleDynamicsWorld::getGravity () const
+btVector3 btSimpleDynamicsWorld::getGravity() const
{
return m_gravity;
}
-void btSimpleDynamicsWorld::removeRigidBody(btRigidBody* body)
+void btSimpleDynamicsWorld::removeRigidBody(btRigidBody* body)
{
btCollisionWorld::removeCollisionObject(body);
}
-void btSimpleDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject)
+void btSimpleDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject)
{
btRigidBody* body = btRigidBody::upcast(collisionObject);
if (body)
@@ -144,8 +135,7 @@ void btSimpleDynamicsWorld::removeCollisionObject(btCollisionObject* collisionOb
btCollisionWorld::removeCollisionObject(collisionObject);
}
-
-void btSimpleDynamicsWorld::addRigidBody(btRigidBody* body)
+void btSimpleDynamicsWorld::addRigidBody(btRigidBody* body)
{
body->setGravity(m_gravity);
@@ -155,37 +145,32 @@ void btSimpleDynamicsWorld::addRigidBody(btRigidBody* body)
}
}
-void btSimpleDynamicsWorld::addRigidBody(btRigidBody* body, int group, int mask)
+void btSimpleDynamicsWorld::addRigidBody(btRigidBody* body, int group, int mask)
{
body->setGravity(m_gravity);
if (body->getCollisionShape())
{
- addCollisionObject(body,group,mask);
+ addCollisionObject(body, group, mask);
}
}
-
-void btSimpleDynamicsWorld::debugDrawWorld()
+void btSimpleDynamicsWorld::debugDrawWorld()
{
-
}
-
-void btSimpleDynamicsWorld::addAction(btActionInterface* action)
-{
+void btSimpleDynamicsWorld::addAction(btActionInterface* action)
+{
}
-void btSimpleDynamicsWorld::removeAction(btActionInterface* action)
+void btSimpleDynamicsWorld::removeAction(btActionInterface* action)
{
-
}
-
-void btSimpleDynamicsWorld::updateAabbs()
+void btSimpleDynamicsWorld::updateAabbs()
{
btTransform predictedTrans;
- for ( int i=0;i<m_collisionObjects.size();i++)
+ for (int i = 0; i < m_collisionObjects.size(); i++)
{
btCollisionObject* colObj = m_collisionObjects[i];
btRigidBody* body = btRigidBody::upcast(colObj);
@@ -193,19 +178,19 @@ void btSimpleDynamicsWorld::updateAabbs()
{
if (body->isActive() && (!body->isStaticObject()))
{
- btVector3 minAabb,maxAabb;
- colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb);
+ btVector3 minAabb, maxAabb;
+ colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb, maxAabb);
btBroadphaseInterface* bp = getBroadphase();
- bp->setAabb(body->getBroadphaseHandle(),minAabb,maxAabb, m_dispatcher1);
+ bp->setAabb(body->getBroadphaseHandle(), minAabb, maxAabb, m_dispatcher1);
}
}
}
}
-void btSimpleDynamicsWorld::integrateTransforms(btScalar timeStep)
+void btSimpleDynamicsWorld::integrateTransforms(btScalar timeStep)
{
btTransform predictedTrans;
- for ( int i=0;i<m_collisionObjects.size();i++)
+ for (int i = 0; i < m_collisionObjects.size(); i++)
{
btCollisionObject* colObj = m_collisionObjects[i];
btRigidBody* body = btRigidBody::upcast(colObj);
@@ -214,17 +199,15 @@ void btSimpleDynamicsWorld::integrateTransforms(btScalar timeStep)
if (body->isActive() && (!body->isStaticObject()))
{
body->predictIntegratedTransform(timeStep, predictedTrans);
- body->proceedToTransform( predictedTrans);
+ body->proceedToTransform(predictedTrans);
}
}
}
}
-
-
-void btSimpleDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
+void btSimpleDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
{
- for ( int i=0;i<m_collisionObjects.size();i++)
+ for (int i = 0; i < m_collisionObjects.size(); i++)
{
btCollisionObject* colObj = m_collisionObjects[i];
btRigidBody* body = btRigidBody::upcast(colObj);
@@ -235,20 +218,19 @@ void btSimpleDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
if (body->isActive())
{
body->applyGravity();
- body->integrateVelocities( timeStep);
+ body->integrateVelocities(timeStep);
body->applyDamping(timeStep);
- body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform());
+ body->predictIntegratedTransform(timeStep, body->getInterpolationWorldTransform());
}
}
}
}
}
-
-void btSimpleDynamicsWorld::synchronizeMotionStates()
+void btSimpleDynamicsWorld::synchronizeMotionStates()
{
///@todo: iterate over awake simulation islands!
- for ( int i=0;i<m_collisionObjects.size();i++)
+ for (int i = 0; i < m_collisionObjects.size(); i++)
{
btCollisionObject* colObj = m_collisionObjects[i];
btRigidBody* body = btRigidBody::upcast(colObj);
@@ -260,11 +242,9 @@ void btSimpleDynamicsWorld::synchronizeMotionStates()
}
}
}
-
}
-
-void btSimpleDynamicsWorld::setConstraintSolver(btConstraintSolver* solver)
+void btSimpleDynamicsWorld::setConstraintSolver(btConstraintSolver* solver)
{
if (m_ownsConstraintSolver)
{
diff --git a/thirdparty/bullet/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h b/thirdparty/bullet/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h
index 44b7e7fb34..12be231c7f 100644
--- a/thirdparty/bullet/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h
+++ b/thirdparty/bullet/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h
@@ -27,63 +27,58 @@ class btConstraintSolver;
class btSimpleDynamicsWorld : public btDynamicsWorld
{
protected:
+ btConstraintSolver* m_constraintSolver;
- btConstraintSolver* m_constraintSolver;
+ bool m_ownsConstraintSolver;
- bool m_ownsConstraintSolver;
-
- void predictUnconstraintMotion(btScalar timeStep);
-
- void integrateTransforms(btScalar timeStep);
-
- btVector3 m_gravity;
-
-public:
+ void predictUnconstraintMotion(btScalar timeStep);
+ void integrateTransforms(btScalar timeStep);
+ btVector3 m_gravity;
+public:
///this btSimpleDynamicsWorld constructor creates dispatcher, broadphase pairCache and constraintSolver
- btSimpleDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration);
+ btSimpleDynamicsWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration);
virtual ~btSimpleDynamicsWorld();
-
+
///maxSubSteps/fixedTimeStep for interpolation is currently ignored for btSimpleDynamicsWorld, use btDiscreteDynamicsWorld instead
- virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.));
+ virtual int stepSimulation(btScalar timeStep, int maxSubSteps = 1, btScalar fixedTimeStep = btScalar(1.) / btScalar(60.));
- virtual void setGravity(const btVector3& gravity);
+ virtual void setGravity(const btVector3& gravity);
- virtual btVector3 getGravity () const;
+ virtual btVector3 getGravity() const;
- virtual void addRigidBody(btRigidBody* body);
+ virtual void addRigidBody(btRigidBody* body);
- virtual void addRigidBody(btRigidBody* body, int group, int mask);
+ virtual void addRigidBody(btRigidBody* body, int group, int mask);
- virtual void removeRigidBody(btRigidBody* body);
+ virtual void removeRigidBody(btRigidBody* body);
- virtual void debugDrawWorld();
-
- virtual void addAction(btActionInterface* action);
+ virtual void debugDrawWorld();
- virtual void removeAction(btActionInterface* action);
+ virtual void addAction(btActionInterface* action);
+
+ virtual void removeAction(btActionInterface* action);
///removeCollisionObject will first check if it is a rigid body, if so call removeRigidBody otherwise call btCollisionWorld::removeCollisionObject
- virtual void removeCollisionObject(btCollisionObject* collisionObject);
-
- virtual void updateAabbs();
+ virtual void removeCollisionObject(btCollisionObject* collisionObject);
+
+ virtual void updateAabbs();
- virtual void synchronizeMotionStates();
+ virtual void synchronizeMotionStates();
- virtual void setConstraintSolver(btConstraintSolver* solver);
+ virtual void setConstraintSolver(btConstraintSolver* solver);
virtual btConstraintSolver* getConstraintSolver();
- virtual btDynamicsWorldType getWorldType() const
+ virtual btDynamicsWorldType getWorldType() const
{
return BT_SIMPLE_DYNAMICS_WORLD;
}
- virtual void clearForces();
-
+ virtual void clearForces();
};
-#endif //BT_SIMPLE_DYNAMICS_WORLD_H
+#endif //BT_SIMPLE_DYNAMICS_WORLD_H
diff --git a/thirdparty/bullet/BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp b/thirdparty/bullet/BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp
index fc54f0ba6e..17287aa82a 100644
--- a/thirdparty/bullet/BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp
+++ b/thirdparty/bullet/BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp
@@ -13,7 +13,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#include "LinearMath/btScalar.h"
#include "LinearMath/btThreads.h"
#include "btSimulationIslandManagerMt.h"
@@ -27,273 +26,259 @@ subject to the following restrictions:
//#include <stdio.h>
#include "LinearMath/btQuickprof.h"
-
-SIMD_FORCE_INLINE int calcBatchCost( int bodies, int manifolds, int constraints )
+SIMD_FORCE_INLINE int calcBatchCost(int bodies, int manifolds, int constraints)
{
- // rough estimate of the cost of a batch, used for merging
- int batchCost = bodies + 8 * manifolds + 4 * constraints;
- return batchCost;
+ // rough estimate of the cost of a batch, used for merging
+ int batchCost = bodies + 8 * manifolds + 4 * constraints;
+ return batchCost;
}
-
-SIMD_FORCE_INLINE int calcBatchCost( const btSimulationIslandManagerMt::Island* island )
+SIMD_FORCE_INLINE int calcBatchCost(const btSimulationIslandManagerMt::Island* island)
{
- return calcBatchCost( island->bodyArray.size(), island->manifoldArray.size(), island->constraintArray.size() );
+ return calcBatchCost(island->bodyArray.size(), island->manifoldArray.size(), island->constraintArray.size());
}
-
btSimulationIslandManagerMt::btSimulationIslandManagerMt()
{
- m_minimumSolverBatchSize = calcBatchCost(0, 128, 0);
- m_batchIslandMinBodyCount = 32;
- m_islandDispatch = parallelIslandDispatch;
- m_batchIsland = NULL;
+ m_minimumSolverBatchSize = calcBatchCost(0, 128, 0);
+ m_batchIslandMinBodyCount = 32;
+ m_islandDispatch = parallelIslandDispatch;
+ m_batchIsland = NULL;
}
-
btSimulationIslandManagerMt::~btSimulationIslandManagerMt()
{
- for ( int i = 0; i < m_allocatedIslands.size(); ++i )
- {
- delete m_allocatedIslands[ i ];
- }
- m_allocatedIslands.resize( 0 );
- m_activeIslands.resize( 0 );
- m_freeIslands.resize( 0 );
+ for (int i = 0; i < m_allocatedIslands.size(); ++i)
+ {
+ delete m_allocatedIslands[i];
+ }
+ m_allocatedIslands.resize(0);
+ m_activeIslands.resize(0);
+ m_freeIslands.resize(0);
}
-
-inline int getIslandId(const btPersistentManifold* lhs)
+inline int getIslandId(const btPersistentManifold* lhs)
{
const btCollisionObject* rcolObj0 = static_cast<const btCollisionObject*>(lhs->getBody0());
const btCollisionObject* rcolObj1 = static_cast<const btCollisionObject*>(lhs->getBody1());
- int islandId = rcolObj0->getIslandTag() >= 0 ? rcolObj0->getIslandTag() : rcolObj1->getIslandTag();
+ int islandId = rcolObj0->getIslandTag() >= 0 ? rcolObj0->getIslandTag() : rcolObj1->getIslandTag();
return islandId;
}
-
-SIMD_FORCE_INLINE int btGetConstraintIslandId( const btTypedConstraint* lhs )
+SIMD_FORCE_INLINE int btGetConstraintIslandId(const btTypedConstraint* lhs)
{
- const btCollisionObject& rcolObj0 = lhs->getRigidBodyA();
- const btCollisionObject& rcolObj1 = lhs->getRigidBodyB();
- int islandId = rcolObj0.getIslandTag() >= 0 ? rcolObj0.getIslandTag() : rcolObj1.getIslandTag();
- return islandId;
+ const btCollisionObject& rcolObj0 = lhs->getRigidBodyA();
+ const btCollisionObject& rcolObj1 = lhs->getRigidBodyB();
+ int islandId = rcolObj0.getIslandTag() >= 0 ? rcolObj0.getIslandTag() : rcolObj1.getIslandTag();
+ return islandId;
}
/// function object that routes calls to operator<
class IslandBatchSizeSortPredicate
{
public:
- bool operator() ( const btSimulationIslandManagerMt::Island* lhs, const btSimulationIslandManagerMt::Island* rhs ) const
- {
- int lCost = calcBatchCost( lhs );
- int rCost = calcBatchCost( rhs );
- return lCost > rCost;
- }
+ bool operator()(const btSimulationIslandManagerMt::Island* lhs, const btSimulationIslandManagerMt::Island* rhs) const
+ {
+ int lCost = calcBatchCost(lhs);
+ int rCost = calcBatchCost(rhs);
+ return lCost > rCost;
+ }
};
-
class IslandBodyCapacitySortPredicate
{
public:
- bool operator() ( const btSimulationIslandManagerMt::Island* lhs, const btSimulationIslandManagerMt::Island* rhs ) const
- {
- return lhs->bodyArray.capacity() > rhs->bodyArray.capacity();
- }
+ bool operator()(const btSimulationIslandManagerMt::Island* lhs, const btSimulationIslandManagerMt::Island* rhs) const
+ {
+ return lhs->bodyArray.capacity() > rhs->bodyArray.capacity();
+ }
};
-
-void btSimulationIslandManagerMt::Island::append( const Island& other )
+void btSimulationIslandManagerMt::Island::append(const Island& other)
{
- // append bodies
- for ( int i = 0; i < other.bodyArray.size(); ++i )
- {
- bodyArray.push_back( other.bodyArray[ i ] );
- }
- // append manifolds
- for ( int i = 0; i < other.manifoldArray.size(); ++i )
- {
- manifoldArray.push_back( other.manifoldArray[ i ] );
- }
- // append constraints
- for ( int i = 0; i < other.constraintArray.size(); ++i )
- {
- constraintArray.push_back( other.constraintArray[ i ] );
- }
+ // append bodies
+ for (int i = 0; i < other.bodyArray.size(); ++i)
+ {
+ bodyArray.push_back(other.bodyArray[i]);
+ }
+ // append manifolds
+ for (int i = 0; i < other.manifoldArray.size(); ++i)
+ {
+ manifoldArray.push_back(other.manifoldArray[i]);
+ }
+ // append constraints
+ for (int i = 0; i < other.constraintArray.size(); ++i)
+ {
+ constraintArray.push_back(other.constraintArray[i]);
+ }
}
-
-bool btIsBodyInIsland( const btSimulationIslandManagerMt::Island& island, const btCollisionObject* obj )
+bool btIsBodyInIsland(const btSimulationIslandManagerMt::Island& island, const btCollisionObject* obj)
{
- for ( int i = 0; i < island.bodyArray.size(); ++i )
- {
- if ( island.bodyArray[ i ] == obj )
- {
- return true;
- }
- }
- return false;
+ for (int i = 0; i < island.bodyArray.size(); ++i)
+ {
+ if (island.bodyArray[i] == obj)
+ {
+ return true;
+ }
+ }
+ return false;
}
-
void btSimulationIslandManagerMt::initIslandPools()
{
- // reset island pools
- int numElem = getUnionFind().getNumElements();
- m_lookupIslandFromId.resize( numElem );
- for ( int i = 0; i < m_lookupIslandFromId.size(); ++i )
- {
- m_lookupIslandFromId[ i ] = NULL;
- }
- m_activeIslands.resize( 0 );
- m_freeIslands.resize( 0 );
- // check whether allocated islands are sorted by body capacity (largest to smallest)
- int lastCapacity = 0;
- bool isSorted = true;
- for ( int i = 0; i < m_allocatedIslands.size(); ++i )
- {
- Island* island = m_allocatedIslands[ i ];
- int cap = island->bodyArray.capacity();
- if ( cap > lastCapacity )
- {
- isSorted = false;
- break;
- }
- lastCapacity = cap;
- }
- if ( !isSorted )
- {
- m_allocatedIslands.quickSort( IslandBodyCapacitySortPredicate() );
- }
-
- m_batchIsland = NULL;
- // mark all islands free (but avoid deallocation)
- for ( int i = 0; i < m_allocatedIslands.size(); ++i )
- {
- Island* island = m_allocatedIslands[ i ];
- island->bodyArray.resize( 0 );
- island->manifoldArray.resize( 0 );
- island->constraintArray.resize( 0 );
- island->id = -1;
- island->isSleeping = true;
- m_freeIslands.push_back( island );
- }
-}
+ // reset island pools
+ int numElem = getUnionFind().getNumElements();
+ m_lookupIslandFromId.resize(numElem);
+ for (int i = 0; i < m_lookupIslandFromId.size(); ++i)
+ {
+ m_lookupIslandFromId[i] = NULL;
+ }
+ m_activeIslands.resize(0);
+ m_freeIslands.resize(0);
+ // check whether allocated islands are sorted by body capacity (largest to smallest)
+ int lastCapacity = 0;
+ bool isSorted = true;
+ for (int i = 0; i < m_allocatedIslands.size(); ++i)
+ {
+ Island* island = m_allocatedIslands[i];
+ int cap = island->bodyArray.capacity();
+ if (cap > lastCapacity)
+ {
+ isSorted = false;
+ break;
+ }
+ lastCapacity = cap;
+ }
+ if (!isSorted)
+ {
+ m_allocatedIslands.quickSort(IslandBodyCapacitySortPredicate());
+ }
+ m_batchIsland = NULL;
+ // mark all islands free (but avoid deallocation)
+ for (int i = 0; i < m_allocatedIslands.size(); ++i)
+ {
+ Island* island = m_allocatedIslands[i];
+ island->bodyArray.resize(0);
+ island->manifoldArray.resize(0);
+ island->constraintArray.resize(0);
+ island->id = -1;
+ island->isSleeping = true;
+ m_freeIslands.push_back(island);
+ }
+}
-btSimulationIslandManagerMt::Island* btSimulationIslandManagerMt::getIsland( int id )
+btSimulationIslandManagerMt::Island* btSimulationIslandManagerMt::getIsland(int id)
{
- Island* island = m_lookupIslandFromId[ id ];
- if ( island == NULL )
- {
- // search for existing island
- for ( int i = 0; i < m_activeIslands.size(); ++i )
- {
- if ( m_activeIslands[ i ]->id == id )
- {
- island = m_activeIslands[ i ];
- break;
- }
- }
- m_lookupIslandFromId[ id ] = island;
- }
- return island;
+ Island* island = m_lookupIslandFromId[id];
+ if (island == NULL)
+ {
+ // search for existing island
+ for (int i = 0; i < m_activeIslands.size(); ++i)
+ {
+ if (m_activeIslands[i]->id == id)
+ {
+ island = m_activeIslands[i];
+ break;
+ }
+ }
+ m_lookupIslandFromId[id] = island;
+ }
+ return island;
}
-
-btSimulationIslandManagerMt::Island* btSimulationIslandManagerMt::allocateIsland( int id, int numBodies )
+btSimulationIslandManagerMt::Island* btSimulationIslandManagerMt::allocateIsland(int id, int numBodies)
{
- Island* island = NULL;
- int allocSize = numBodies;
- if ( numBodies < m_batchIslandMinBodyCount )
- {
- if ( m_batchIsland )
- {
- island = m_batchIsland;
- m_lookupIslandFromId[ id ] = island;
- // if we've made a large enough batch,
- if ( island->bodyArray.size() + numBodies >= m_batchIslandMinBodyCount )
- {
- // next time start a new batch
- m_batchIsland = NULL;
- }
- return island;
- }
- else
- {
- // need to allocate a batch island
- allocSize = m_batchIslandMinBodyCount * 2;
- }
- }
- btAlignedObjectArray<Island*>& freeIslands = m_freeIslands;
-
- // search for free island
- if ( freeIslands.size() > 0 )
- {
- // try to reuse a previously allocated island
- int iFound = freeIslands.size();
- // linear search for smallest island that can hold our bodies
- for ( int i = freeIslands.size() - 1; i >= 0; --i )
- {
- if ( freeIslands[ i ]->bodyArray.capacity() >= allocSize )
- {
- iFound = i;
- island = freeIslands[ i ];
- island->id = id;
- break;
- }
- }
- // if found, shrink array while maintaining ordering
- if ( island )
- {
- int iDest = iFound;
- int iSrc = iDest + 1;
- while ( iSrc < freeIslands.size() )
- {
- freeIslands[ iDest++ ] = freeIslands[ iSrc++ ];
- }
- freeIslands.pop_back();
- }
- }
- if ( island == NULL )
- {
- // no free island found, allocate
- island = new Island(); // TODO: change this to use the pool allocator
- island->id = id;
- island->bodyArray.reserve( allocSize );
- m_allocatedIslands.push_back( island );
- }
- m_lookupIslandFromId[ id ] = island;
- if ( numBodies < m_batchIslandMinBodyCount )
- {
- m_batchIsland = island;
- }
- m_activeIslands.push_back( island );
- return island;
-}
+ Island* island = NULL;
+ int allocSize = numBodies;
+ if (numBodies < m_batchIslandMinBodyCount)
+ {
+ if (m_batchIsland)
+ {
+ island = m_batchIsland;
+ m_lookupIslandFromId[id] = island;
+ // if we've made a large enough batch,
+ if (island->bodyArray.size() + numBodies >= m_batchIslandMinBodyCount)
+ {
+ // next time start a new batch
+ m_batchIsland = NULL;
+ }
+ return island;
+ }
+ else
+ {
+ // need to allocate a batch island
+ allocSize = m_batchIslandMinBodyCount * 2;
+ }
+ }
+ btAlignedObjectArray<Island*>& freeIslands = m_freeIslands;
+ // search for free island
+ if (freeIslands.size() > 0)
+ {
+ // try to reuse a previously allocated island
+ int iFound = freeIslands.size();
+ // linear search for smallest island that can hold our bodies
+ for (int i = freeIslands.size() - 1; i >= 0; --i)
+ {
+ if (freeIslands[i]->bodyArray.capacity() >= allocSize)
+ {
+ iFound = i;
+ island = freeIslands[i];
+ island->id = id;
+ break;
+ }
+ }
+ // if found, shrink array while maintaining ordering
+ if (island)
+ {
+ int iDest = iFound;
+ int iSrc = iDest + 1;
+ while (iSrc < freeIslands.size())
+ {
+ freeIslands[iDest++] = freeIslands[iSrc++];
+ }
+ freeIslands.pop_back();
+ }
+ }
+ if (island == NULL)
+ {
+ // no free island found, allocate
+ island = new Island(); // TODO: change this to use the pool allocator
+ island->id = id;
+ island->bodyArray.reserve(allocSize);
+ m_allocatedIslands.push_back(island);
+ }
+ m_lookupIslandFromId[id] = island;
+ if (numBodies < m_batchIslandMinBodyCount)
+ {
+ m_batchIsland = island;
+ }
+ m_activeIslands.push_back(island);
+ return island;
+}
-void btSimulationIslandManagerMt::buildIslands( btDispatcher* dispatcher, btCollisionWorld* collisionWorld )
+void btSimulationIslandManagerMt::buildIslands(btDispatcher* dispatcher, btCollisionWorld* collisionWorld)
{
-
BT_PROFILE("buildIslands");
-
+
btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
//we are going to sort the unionfind array, and store the element id in the size
//afterwards, we clean unionfind, to make sure no-one uses it anymore
-
+
getUnionFind().sortIslands();
int numElem = getUnionFind().getNumElements();
- int endIslandIndex=1;
+ int endIslandIndex = 1;
int startIslandIndex;
//update the sleeping state for bodies, if all are sleeping
- for ( startIslandIndex=0;startIslandIndex<numElem;startIslandIndex = endIslandIndex)
+ for (startIslandIndex = 0; startIslandIndex < numElem; startIslandIndex = endIslandIndex)
{
int islandId = getUnionFind().getElement(startIslandIndex).m_id;
- for (endIslandIndex = startIslandIndex+1;(endIslandIndex<numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId);endIslandIndex++)
+ for (endIslandIndex = startIslandIndex + 1; (endIslandIndex < numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId); endIslandIndex++)
{
}
@@ -302,21 +287,21 @@ void btSimulationIslandManagerMt::buildIslands( btDispatcher* dispatcher, btColl
bool allSleeping = true;
int idx;
- for (idx=startIslandIndex;idx<endIslandIndex;idx++)
+ for (idx = startIslandIndex; idx < endIslandIndex; idx++)
{
int i = getUnionFind().getElement(idx).m_sz;
btCollisionObject* colObj0 = collisionObjects[i];
if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
{
-// printf("error in island management\n");
+ // printf("error in island management\n");
}
btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
if (colObj0->getIslandTag() == islandId)
{
- if (colObj0->getActivationState()== ACTIVE_TAG ||
- colObj0->getActivationState()== DISABLE_DEACTIVATION)
+ if (colObj0->getActivationState() == ACTIVE_TAG ||
+ colObj0->getActivationState() == DISABLE_DEACTIVATION)
{
allSleeping = false;
break;
@@ -327,43 +312,43 @@ void btSimulationIslandManagerMt::buildIslands( btDispatcher* dispatcher, btColl
if (allSleeping)
{
int idx;
- for (idx=startIslandIndex;idx<endIslandIndex;idx++)
+ for (idx = startIslandIndex; idx < endIslandIndex; idx++)
{
int i = getUnionFind().getElement(idx).m_sz;
btCollisionObject* colObj0 = collisionObjects[i];
if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
{
-// printf("error in island management\n");
+ // printf("error in island management\n");
}
btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
if (colObj0->getIslandTag() == islandId)
{
- colObj0->setActivationState( ISLAND_SLEEPING );
+ colObj0->setActivationState(ISLAND_SLEEPING);
}
}
- } else
+ }
+ else
{
-
int idx;
- for (idx=startIslandIndex;idx<endIslandIndex;idx++)
+ for (idx = startIslandIndex; idx < endIslandIndex; idx++)
{
int i = getUnionFind().getElement(idx).m_sz;
btCollisionObject* colObj0 = collisionObjects[i];
if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
{
-// printf("error in island management\n");
+ // printf("error in island management\n");
}
btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
if (colObj0->getIslandTag() == islandId)
{
- if ( colObj0->getActivationState() == ISLAND_SLEEPING)
+ if (colObj0->getActivationState() == ISLAND_SLEEPING)
{
- colObj0->setActivationState( WANTS_DEACTIVATION);
+ colObj0->setActivationState(WANTS_DEACTIVATION);
colObj0->setDeactivationTime(0.f);
}
}
@@ -372,352 +357,338 @@ void btSimulationIslandManagerMt::buildIslands( btDispatcher* dispatcher, btColl
}
}
-
-void btSimulationIslandManagerMt::addBodiesToIslands( btCollisionWorld* collisionWorld )
+void btSimulationIslandManagerMt::addBodiesToIslands(btCollisionWorld* collisionWorld)
{
- btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
- int endIslandIndex = 1;
- int startIslandIndex;
- int numElem = getUnionFind().getNumElements();
-
- // create explicit islands and add bodies to each
- for ( startIslandIndex = 0; startIslandIndex < numElem; startIslandIndex = endIslandIndex )
- {
- int islandId = getUnionFind().getElement( startIslandIndex ).m_id;
-
- // find end index
- for ( endIslandIndex = startIslandIndex; ( endIslandIndex < numElem ) && ( getUnionFind().getElement( endIslandIndex ).m_id == islandId ); endIslandIndex++ )
- {
- }
- // check if island is sleeping
- bool islandSleeping = true;
- for ( int iElem = startIslandIndex; iElem < endIslandIndex; iElem++ )
- {
- int i = getUnionFind().getElement( iElem ).m_sz;
- btCollisionObject* colObj = collisionObjects[ i ];
- if ( colObj->isActive() )
- {
- islandSleeping = false;
- }
- }
- if ( !islandSleeping )
- {
- // want to count the number of bodies before allocating the island to optimize memory usage of the Island structures
- int numBodies = endIslandIndex - startIslandIndex;
- Island* island = allocateIsland( islandId, numBodies );
- island->isSleeping = false;
-
- // add bodies to island
- for ( int iElem = startIslandIndex; iElem < endIslandIndex; iElem++ )
- {
- int i = getUnionFind().getElement( iElem ).m_sz;
- btCollisionObject* colObj = collisionObjects[ i ];
- island->bodyArray.push_back( colObj );
- }
- }
- }
+ btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
+ int endIslandIndex = 1;
+ int startIslandIndex;
+ int numElem = getUnionFind().getNumElements();
-}
+ // create explicit islands and add bodies to each
+ for (startIslandIndex = 0; startIslandIndex < numElem; startIslandIndex = endIslandIndex)
+ {
+ int islandId = getUnionFind().getElement(startIslandIndex).m_id;
+ // find end index
+ for (endIslandIndex = startIslandIndex; (endIslandIndex < numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId); endIslandIndex++)
+ {
+ }
+ // check if island is sleeping
+ bool islandSleeping = true;
+ for (int iElem = startIslandIndex; iElem < endIslandIndex; iElem++)
+ {
+ int i = getUnionFind().getElement(iElem).m_sz;
+ btCollisionObject* colObj = collisionObjects[i];
+ if (colObj->isActive())
+ {
+ islandSleeping = false;
+ }
+ }
+ if (!islandSleeping)
+ {
+ // want to count the number of bodies before allocating the island to optimize memory usage of the Island structures
+ int numBodies = endIslandIndex - startIslandIndex;
+ Island* island = allocateIsland(islandId, numBodies);
+ island->isSleeping = false;
-void btSimulationIslandManagerMt::addManifoldsToIslands( btDispatcher* dispatcher )
-{
- // walk all the manifolds, activating bodies touched by kinematic objects, and add each manifold to its Island
- int maxNumManifolds = dispatcher->getNumManifolds();
- for ( int i = 0; i < maxNumManifolds; i++ )
- {
- btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal( i );
-
- const btCollisionObject* colObj0 = static_cast<const btCollisionObject*>( manifold->getBody0() );
- const btCollisionObject* colObj1 = static_cast<const btCollisionObject*>( manifold->getBody1() );
-
- ///@todo: check sleeping conditions!
- if ( ( ( colObj0 ) && colObj0->getActivationState() != ISLAND_SLEEPING ) ||
- ( ( colObj1 ) && colObj1->getActivationState() != ISLAND_SLEEPING ) )
- {
-
- //kinematic objects don't merge islands, but wake up all connected objects
- if ( colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING )
- {
- if ( colObj0->hasContactResponse() )
- colObj1->activate();
- }
- if ( colObj1->isKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING )
- {
- if ( colObj1->hasContactResponse() )
- colObj0->activate();
- }
- //filtering for response
- if ( dispatcher->needsResponse( colObj0, colObj1 ) )
- {
- // scatter manifolds into various islands
- int islandId = getIslandId( manifold );
- // if island not sleeping,
- if ( Island* island = getIsland( islandId ) )
- {
- island->manifoldArray.push_back( manifold );
- }
- }
- }
- }
+ // add bodies to island
+ for (int iElem = startIslandIndex; iElem < endIslandIndex; iElem++)
+ {
+ int i = getUnionFind().getElement(iElem).m_sz;
+ btCollisionObject* colObj = collisionObjects[i];
+ island->bodyArray.push_back(colObj);
+ }
+ }
+ }
}
-
-void btSimulationIslandManagerMt::addConstraintsToIslands( btAlignedObjectArray<btTypedConstraint*>& constraints )
+void btSimulationIslandManagerMt::addManifoldsToIslands(btDispatcher* dispatcher)
{
- // walk constraints
- for ( int i = 0; i < constraints.size(); i++ )
- {
- // scatter constraints into various islands
- btTypedConstraint* constraint = constraints[ i ];
- if ( constraint->isEnabled() )
- {
- int islandId = btGetConstraintIslandId( constraint );
- // if island is not sleeping,
- if ( Island* island = getIsland( islandId ) )
- {
- island->constraintArray.push_back( constraint );
- }
- }
- }
+ // walk all the manifolds, activating bodies touched by kinematic objects, and add each manifold to its Island
+ int maxNumManifolds = dispatcher->getNumManifolds();
+ for (int i = 0; i < maxNumManifolds; i++)
+ {
+ btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i);
+
+ const btCollisionObject* colObj0 = static_cast<const btCollisionObject*>(manifold->getBody0());
+ const btCollisionObject* colObj1 = static_cast<const btCollisionObject*>(manifold->getBody1());
+
+ ///@todo: check sleeping conditions!
+ if (((colObj0) && colObj0->getActivationState() != ISLAND_SLEEPING) ||
+ ((colObj1) && colObj1->getActivationState() != ISLAND_SLEEPING))
+ {
+ //kinematic objects don't merge islands, but wake up all connected objects
+ if (colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING)
+ {
+ if (colObj0->hasContactResponse())
+ colObj1->activate();
+ }
+ if (colObj1->isKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING)
+ {
+ if (colObj1->hasContactResponse())
+ colObj0->activate();
+ }
+ //filtering for response
+ if (dispatcher->needsResponse(colObj0, colObj1))
+ {
+ // scatter manifolds into various islands
+ int islandId = getIslandId(manifold);
+ // if island not sleeping,
+ if (Island* island = getIsland(islandId))
+ {
+ island->manifoldArray.push_back(manifold);
+ }
+ }
+ }
+ }
}
+void btSimulationIslandManagerMt::addConstraintsToIslands(btAlignedObjectArray<btTypedConstraint*>& constraints)
+{
+ // walk constraints
+ for (int i = 0; i < constraints.size(); i++)
+ {
+ // scatter constraints into various islands
+ btTypedConstraint* constraint = constraints[i];
+ if (constraint->isEnabled())
+ {
+ int islandId = btGetConstraintIslandId(constraint);
+ // if island is not sleeping,
+ if (Island* island = getIsland(islandId))
+ {
+ island->constraintArray.push_back(constraint);
+ }
+ }
+ }
+}
void btSimulationIslandManagerMt::mergeIslands()
{
- // sort islands in order of decreasing batch size
- m_activeIslands.quickSort( IslandBatchSizeSortPredicate() );
-
- // merge small islands to satisfy minimum batch size
- // find first small batch island
- int destIslandIndex = m_activeIslands.size();
- for ( int i = 0; i < m_activeIslands.size(); ++i )
- {
- Island* island = m_activeIslands[ i ];
- int batchSize = calcBatchCost( island );
- if ( batchSize < m_minimumSolverBatchSize )
- {
- destIslandIndex = i;
- break;
- }
- }
- int lastIndex = m_activeIslands.size() - 1;
- while ( destIslandIndex < lastIndex )
- {
- // merge islands from the back of the list
- Island* island = m_activeIslands[ destIslandIndex ];
- int numBodies = island->bodyArray.size();
- int numManifolds = island->manifoldArray.size();
- int numConstraints = island->constraintArray.size();
- int firstIndex = lastIndex;
- // figure out how many islands we want to merge and find out how many bodies, manifolds and constraints we will have
- while ( true )
- {
- Island* src = m_activeIslands[ firstIndex ];
- numBodies += src->bodyArray.size();
- numManifolds += src->manifoldArray.size();
- numConstraints += src->constraintArray.size();
- int batchCost = calcBatchCost( numBodies, numManifolds, numConstraints );
- if ( batchCost >= m_minimumSolverBatchSize )
- {
- break;
- }
- if ( firstIndex - 1 == destIslandIndex )
- {
- break;
- }
- firstIndex--;
- }
- // reserve space for these pointers to minimize reallocation
- island->bodyArray.reserve( numBodies );
- island->manifoldArray.reserve( numManifolds );
- island->constraintArray.reserve( numConstraints );
- // merge islands
- for ( int i = firstIndex; i <= lastIndex; ++i )
- {
- island->append( *m_activeIslands[ i ] );
- }
- // shrink array to exclude the islands that were merged from
- m_activeIslands.resize( firstIndex );
- lastIndex = firstIndex - 1;
- destIslandIndex++;
- }
-}
+ // sort islands in order of decreasing batch size
+ m_activeIslands.quickSort(IslandBatchSizeSortPredicate());
+ // merge small islands to satisfy minimum batch size
+ // find first small batch island
+ int destIslandIndex = m_activeIslands.size();
+ for (int i = 0; i < m_activeIslands.size(); ++i)
+ {
+ Island* island = m_activeIslands[i];
+ int batchSize = calcBatchCost(island);
+ if (batchSize < m_minimumSolverBatchSize)
+ {
+ destIslandIndex = i;
+ break;
+ }
+ }
+ int lastIndex = m_activeIslands.size() - 1;
+ while (destIslandIndex < lastIndex)
+ {
+ // merge islands from the back of the list
+ Island* island = m_activeIslands[destIslandIndex];
+ int numBodies = island->bodyArray.size();
+ int numManifolds = island->manifoldArray.size();
+ int numConstraints = island->constraintArray.size();
+ int firstIndex = lastIndex;
+ // figure out how many islands we want to merge and find out how many bodies, manifolds and constraints we will have
+ while (true)
+ {
+ Island* src = m_activeIslands[firstIndex];
+ numBodies += src->bodyArray.size();
+ numManifolds += src->manifoldArray.size();
+ numConstraints += src->constraintArray.size();
+ int batchCost = calcBatchCost(numBodies, numManifolds, numConstraints);
+ if (batchCost >= m_minimumSolverBatchSize)
+ {
+ break;
+ }
+ if (firstIndex - 1 == destIslandIndex)
+ {
+ break;
+ }
+ firstIndex--;
+ }
+ // reserve space for these pointers to minimize reallocation
+ island->bodyArray.reserve(numBodies);
+ island->manifoldArray.reserve(numManifolds);
+ island->constraintArray.reserve(numConstraints);
+ // merge islands
+ for (int i = firstIndex; i <= lastIndex; ++i)
+ {
+ island->append(*m_activeIslands[i]);
+ }
+ // shrink array to exclude the islands that were merged from
+ m_activeIslands.resize(firstIndex);
+ lastIndex = firstIndex - 1;
+ destIslandIndex++;
+ }
+}
void btSimulationIslandManagerMt::solveIsland(btConstraintSolver* solver, Island& island, const SolverParams& solverParams)
{
- btPersistentManifold** manifolds = island.manifoldArray.size() ? &island.manifoldArray[ 0 ] : NULL;
- btTypedConstraint** constraintsPtr = island.constraintArray.size() ? &island.constraintArray[ 0 ] : NULL;
- solver->solveGroup( &island.bodyArray[ 0 ],
- island.bodyArray.size(),
- manifolds,
- island.manifoldArray.size(),
- constraintsPtr,
- island.constraintArray.size(),
- *solverParams.m_solverInfo,
- solverParams.m_debugDrawer,
- solverParams.m_dispatcher
- );
+ btPersistentManifold** manifolds = island.manifoldArray.size() ? &island.manifoldArray[0] : NULL;
+ btTypedConstraint** constraintsPtr = island.constraintArray.size() ? &island.constraintArray[0] : NULL;
+ solver->solveGroup(&island.bodyArray[0],
+ island.bodyArray.size(),
+ manifolds,
+ island.manifoldArray.size(),
+ constraintsPtr,
+ island.constraintArray.size(),
+ *solverParams.m_solverInfo,
+ solverParams.m_debugDrawer,
+ solverParams.m_dispatcher);
}
-
-void btSimulationIslandManagerMt::serialIslandDispatch( btAlignedObjectArray<Island*>* islandsPtr, const SolverParams& solverParams )
+void btSimulationIslandManagerMt::serialIslandDispatch(btAlignedObjectArray<Island*>* islandsPtr, const SolverParams& solverParams)
{
- BT_PROFILE( "serialIslandDispatch" );
- // serial dispatch
- btAlignedObjectArray<Island*>& islands = *islandsPtr;
- btConstraintSolver* solver = solverParams.m_solverMt ? solverParams.m_solverMt : solverParams.m_solverPool;
- for ( int i = 0; i < islands.size(); ++i )
- {
- solveIsland(solver, *islands[ i ], solverParams);
- }
+ BT_PROFILE("serialIslandDispatch");
+ // serial dispatch
+ btAlignedObjectArray<Island*>& islands = *islandsPtr;
+ btConstraintSolver* solver = solverParams.m_solverMt ? solverParams.m_solverMt : solverParams.m_solverPool;
+ for (int i = 0; i < islands.size(); ++i)
+ {
+ solveIsland(solver, *islands[i], solverParams);
+ }
}
-
struct UpdateIslandDispatcher : public btIParallelForBody
{
- btAlignedObjectArray<btSimulationIslandManagerMt::Island*>& m_islandsPtr;
- const btSimulationIslandManagerMt::SolverParams& m_solverParams;
-
- UpdateIslandDispatcher(btAlignedObjectArray<btSimulationIslandManagerMt::Island*>& islandsPtr, const btSimulationIslandManagerMt::SolverParams& solverParams)
- : m_islandsPtr(islandsPtr), m_solverParams(solverParams)
- {}
-
- void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE
- {
- btConstraintSolver* solver = m_solverParams.m_solverPool;
- for ( int i = iBegin; i < iEnd; ++i )
- {
- btSimulationIslandManagerMt::Island* island = m_islandsPtr[ i ];
- btSimulationIslandManagerMt::solveIsland( solver, *island, m_solverParams );
- }
- }
-};
+ btAlignedObjectArray<btSimulationIslandManagerMt::Island*>& m_islandsPtr;
+ const btSimulationIslandManagerMt::SolverParams& m_solverParams;
+ UpdateIslandDispatcher(btAlignedObjectArray<btSimulationIslandManagerMt::Island*>& islandsPtr, const btSimulationIslandManagerMt::SolverParams& solverParams)
+ : m_islandsPtr(islandsPtr), m_solverParams(solverParams)
+ {
+ }
+
+ void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
+ {
+ btConstraintSolver* solver = m_solverParams.m_solverPool;
+ for (int i = iBegin; i < iEnd; ++i)
+ {
+ btSimulationIslandManagerMt::Island* island = m_islandsPtr[i];
+ btSimulationIslandManagerMt::solveIsland(solver, *island, m_solverParams);
+ }
+ }
+};
-void btSimulationIslandManagerMt::parallelIslandDispatch( btAlignedObjectArray<Island*>* islandsPtr, const SolverParams& solverParams )
+void btSimulationIslandManagerMt::parallelIslandDispatch(btAlignedObjectArray<Island*>* islandsPtr, const SolverParams& solverParams)
{
- BT_PROFILE( "parallelIslandDispatch" );
- //
- // if there are islands with many contacts, it may be faster to submit these
- // large islands *serially* to a single parallel constraint solver, and then later
- // submit the remaining smaller islands in parallel to multiple sequential solvers.
- //
- // Some task schedulers do not deal well with nested parallelFor loops. One implementation
- // of OpenMP was actually slower than doing everything single-threaded. Intel TBB
- // on the other hand, seems to do a pretty respectable job with it.
- //
- // When solving islands in parallel, the worst case performance happens when there
- // is one very large island and then perhaps a smattering of very small
- // islands -- one worker thread takes the large island and the remaining workers
- // tear through the smaller islands and then sit idle waiting for the first worker
- // to finish. Solving islands in parallel works best when there are numerous small
- // islands, roughly equal in size.
- //
- // By contrast, the other approach -- the parallel constraint solver -- is only
- // able to deliver a worthwhile speedup when the island is large. For smaller islands,
- // it is difficult to extract a useful amount of parallelism -- the overhead of grouping
- // the constraints into batches and sending the batches to worker threads can nullify
- // any gains from parallelism.
- //
-
- UpdateIslandDispatcher dispatcher(*islandsPtr, solverParams);
- // We take advantage of the fact the islands are sorted in order of decreasing size
- int iBegin = 0;
- if (solverParams.m_solverMt)
- {
- while ( iBegin < islandsPtr->size() )
- {
- btSimulationIslandManagerMt::Island* island = ( *islandsPtr )[ iBegin ];
- if ( island->manifoldArray.size() < btSequentialImpulseConstraintSolverMt::s_minimumContactManifoldsForBatching )
- {
- // OK to submit the rest of the array in parallel
- break;
- }
- // serial dispatch to parallel solver for large islands (if any)
- solveIsland(solverParams.m_solverMt, *island, solverParams);
- ++iBegin;
- }
- }
- // parallel dispatch to sequential solvers for rest
- btParallelFor( iBegin, islandsPtr->size(), 1, dispatcher );
+ BT_PROFILE("parallelIslandDispatch");
+ //
+ // if there are islands with many contacts, it may be faster to submit these
+ // large islands *serially* to a single parallel constraint solver, and then later
+ // submit the remaining smaller islands in parallel to multiple sequential solvers.
+ //
+ // Some task schedulers do not deal well with nested parallelFor loops. One implementation
+ // of OpenMP was actually slower than doing everything single-threaded. Intel TBB
+ // on the other hand, seems to do a pretty respectable job with it.
+ //
+ // When solving islands in parallel, the worst case performance happens when there
+ // is one very large island and then perhaps a smattering of very small
+ // islands -- one worker thread takes the large island and the remaining workers
+ // tear through the smaller islands and then sit idle waiting for the first worker
+ // to finish. Solving islands in parallel works best when there are numerous small
+ // islands, roughly equal in size.
+ //
+ // By contrast, the other approach -- the parallel constraint solver -- is only
+ // able to deliver a worthwhile speedup when the island is large. For smaller islands,
+ // it is difficult to extract a useful amount of parallelism -- the overhead of grouping
+ // the constraints into batches and sending the batches to worker threads can nullify
+ // any gains from parallelism.
+ //
+
+ UpdateIslandDispatcher dispatcher(*islandsPtr, solverParams);
+ // We take advantage of the fact the islands are sorted in order of decreasing size
+ int iBegin = 0;
+ if (solverParams.m_solverMt)
+ {
+ while (iBegin < islandsPtr->size())
+ {
+ btSimulationIslandManagerMt::Island* island = (*islandsPtr)[iBegin];
+ if (island->manifoldArray.size() < btSequentialImpulseConstraintSolverMt::s_minimumContactManifoldsForBatching)
+ {
+ // OK to submit the rest of the array in parallel
+ break;
+ }
+ // serial dispatch to parallel solver for large islands (if any)
+ solveIsland(solverParams.m_solverMt, *island, solverParams);
+ ++iBegin;
+ }
+ }
+ // parallel dispatch to sequential solvers for rest
+ btParallelFor(iBegin, islandsPtr->size(), 1, dispatcher);
}
-
///@todo: this is random access, it can be walked 'cache friendly'!
-void btSimulationIslandManagerMt::buildAndProcessIslands( btDispatcher* dispatcher,
- btCollisionWorld* collisionWorld,
- btAlignedObjectArray<btTypedConstraint*>& constraints,
- const SolverParams& solverParams
- )
+void btSimulationIslandManagerMt::buildAndProcessIslands(btDispatcher* dispatcher,
+ btCollisionWorld* collisionWorld,
+ btAlignedObjectArray<btTypedConstraint*>& constraints,
+ const SolverParams& solverParams)
{
BT_PROFILE("buildAndProcessIslands");
btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
- buildIslands(dispatcher,collisionWorld);
+ buildIslands(dispatcher, collisionWorld);
- if(!getSplitIslands())
+ if (!getSplitIslands())
{
- btPersistentManifold** manifolds = dispatcher->getInternalManifoldPointer();
- int maxNumManifolds = dispatcher->getNumManifolds();
-
- for ( int i = 0; i < maxNumManifolds; i++ )
- {
- btPersistentManifold* manifold = manifolds[ i ];
-
- const btCollisionObject* colObj0 = static_cast<const btCollisionObject*>( manifold->getBody0() );
- const btCollisionObject* colObj1 = static_cast<const btCollisionObject*>( manifold->getBody1() );
-
- ///@todo: check sleeping conditions!
- if ( ( ( colObj0 ) && colObj0->getActivationState() != ISLAND_SLEEPING ) ||
- ( ( colObj1 ) && colObj1->getActivationState() != ISLAND_SLEEPING ) )
- {
-
- //kinematic objects don't merge islands, but wake up all connected objects
- if ( colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING )
- {
- if ( colObj0->hasContactResponse() )
- colObj1->activate();
- }
- if ( colObj1->isKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING )
- {
- if ( colObj1->hasContactResponse() )
- colObj0->activate();
- }
- }
- }
- btTypedConstraint** constraintsPtr = constraints.size() ? &constraints[ 0 ] : NULL;
- btConstraintSolver* solver = solverParams.m_solverMt ? solverParams.m_solverMt : solverParams.m_solverPool;
- solver->solveGroup(&collisionObjects[0],
- collisionObjects.size(),
- manifolds,
- maxNumManifolds,
- constraintsPtr,
- constraints.size(),
- *solverParams.m_solverInfo,
- solverParams.m_debugDrawer,
- solverParams.m_dispatcher
- );
+ btPersistentManifold** manifolds = dispatcher->getInternalManifoldPointer();
+ int maxNumManifolds = dispatcher->getNumManifolds();
+
+ for (int i = 0; i < maxNumManifolds; i++)
+ {
+ btPersistentManifold* manifold = manifolds[i];
+
+ const btCollisionObject* colObj0 = static_cast<const btCollisionObject*>(manifold->getBody0());
+ const btCollisionObject* colObj1 = static_cast<const btCollisionObject*>(manifold->getBody1());
+
+ ///@todo: check sleeping conditions!
+ if (((colObj0) && colObj0->getActivationState() != ISLAND_SLEEPING) ||
+ ((colObj1) && colObj1->getActivationState() != ISLAND_SLEEPING))
+ {
+ //kinematic objects don't merge islands, but wake up all connected objects
+ if (colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING)
+ {
+ if (colObj0->hasContactResponse())
+ colObj1->activate();
+ }
+ if (colObj1->isKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING)
+ {
+ if (colObj1->hasContactResponse())
+ colObj0->activate();
+ }
+ }
+ }
+ btTypedConstraint** constraintsPtr = constraints.size() ? &constraints[0] : NULL;
+ btConstraintSolver* solver = solverParams.m_solverMt ? solverParams.m_solverMt : solverParams.m_solverPool;
+ solver->solveGroup(&collisionObjects[0],
+ collisionObjects.size(),
+ manifolds,
+ maxNumManifolds,
+ constraintsPtr,
+ constraints.size(),
+ *solverParams.m_solverInfo,
+ solverParams.m_debugDrawer,
+ solverParams.m_dispatcher);
}
else
{
- initIslandPools();
-
- //traverse the simulation islands, and call the solver, unless all objects are sleeping/deactivated
- addBodiesToIslands( collisionWorld );
- addManifoldsToIslands( dispatcher );
- addConstraintsToIslands( constraints );
-
- // m_activeIslands array should now contain all non-sleeping Islands, and each Island should
- // have all the necessary bodies, manifolds and constraints.
-
- // if we want to merge islands with small batch counts,
- if ( m_minimumSolverBatchSize > 1 )
- {
- mergeIslands();
- }
- // dispatch islands to solver
- m_islandDispatch( &m_activeIslands, solverParams );
+ initIslandPools();
+
+ //traverse the simulation islands, and call the solver, unless all objects are sleeping/deactivated
+ addBodiesToIslands(collisionWorld);
+ addManifoldsToIslands(dispatcher);
+ addConstraintsToIslands(constraints);
+
+ // m_activeIslands array should now contain all non-sleeping Islands, and each Island should
+ // have all the necessary bodies, manifolds and constraints.
+
+ // if we want to merge islands with small batch counts,
+ if (m_minimumSolverBatchSize > 1)
+ {
+ mergeIslands();
+ }
+ // dispatch islands to solver
+ m_islandDispatch(&m_activeIslands, solverParams);
}
}
diff --git a/thirdparty/bullet/BulletDynamics/Dynamics/btSimulationIslandManagerMt.h b/thirdparty/bullet/BulletDynamics/Dynamics/btSimulationIslandManagerMt.h
index 563577a6f4..ab73a899f1 100644
--- a/thirdparty/bullet/BulletDynamics/Dynamics/btSimulationIslandManagerMt.h
+++ b/thirdparty/bullet/BulletDynamics/Dynamics/btSimulationIslandManagerMt.h
@@ -35,80 +35,78 @@ class btIDebugDraw;
class btSimulationIslandManagerMt : public btSimulationIslandManager
{
public:
- struct Island
- {
- // a simulation island consisting of bodies, manifolds and constraints,
- // to be passed into a constraint solver.
- btAlignedObjectArray<btCollisionObject*> bodyArray;
- btAlignedObjectArray<btPersistentManifold*> manifoldArray;
- btAlignedObjectArray<btTypedConstraint*> constraintArray;
- int id; // island id
- bool isSleeping;
+ struct Island
+ {
+ // a simulation island consisting of bodies, manifolds and constraints,
+ // to be passed into a constraint solver.
+ btAlignedObjectArray<btCollisionObject*> bodyArray;
+ btAlignedObjectArray<btPersistentManifold*> manifoldArray;
+ btAlignedObjectArray<btTypedConstraint*> constraintArray;
+ int id; // island id
+ bool isSleeping;
- void append( const Island& other ); // add bodies, manifolds, constraints to my own
- };
- struct SolverParams
- {
- btConstraintSolver* m_solverPool;
- btConstraintSolver* m_solverMt;
- btContactSolverInfo* m_solverInfo;
- btIDebugDraw* m_debugDrawer;
- btDispatcher* m_dispatcher;
- };
- static void solveIsland(btConstraintSolver* solver, Island& island, const SolverParams& solverParams);
+ void append(const Island& other); // add bodies, manifolds, constraints to my own
+ };
+ struct SolverParams
+ {
+ btConstraintSolver* m_solverPool;
+ btConstraintSolver* m_solverMt;
+ btContactSolverInfo* m_solverInfo;
+ btIDebugDraw* m_debugDrawer;
+ btDispatcher* m_dispatcher;
+ };
+ static void solveIsland(btConstraintSolver* solver, Island& island, const SolverParams& solverParams);
+
+ typedef void (*IslandDispatchFunc)(btAlignedObjectArray<Island*>* islands, const SolverParams& solverParams);
+ static void serialIslandDispatch(btAlignedObjectArray<Island*>* islandsPtr, const SolverParams& solverParams);
+ static void parallelIslandDispatch(btAlignedObjectArray<Island*>* islandsPtr, const SolverParams& solverParams);
- typedef void( *IslandDispatchFunc ) ( btAlignedObjectArray<Island*>* islands, const SolverParams& solverParams );
- static void serialIslandDispatch( btAlignedObjectArray<Island*>* islandsPtr, const SolverParams& solverParams );
- static void parallelIslandDispatch( btAlignedObjectArray<Island*>* islandsPtr, const SolverParams& solverParams );
protected:
- btAlignedObjectArray<Island*> m_allocatedIslands; // owner of all Islands
- btAlignedObjectArray<Island*> m_activeIslands; // islands actively in use
- btAlignedObjectArray<Island*> m_freeIslands; // islands ready to be reused
- btAlignedObjectArray<Island*> m_lookupIslandFromId; // big lookup table to map islandId to Island pointer
- Island* m_batchIsland;
- int m_minimumSolverBatchSize;
- int m_batchIslandMinBodyCount;
- IslandDispatchFunc m_islandDispatch;
+ btAlignedObjectArray<Island*> m_allocatedIslands; // owner of all Islands
+ btAlignedObjectArray<Island*> m_activeIslands; // islands actively in use
+ btAlignedObjectArray<Island*> m_freeIslands; // islands ready to be reused
+ btAlignedObjectArray<Island*> m_lookupIslandFromId; // big lookup table to map islandId to Island pointer
+ Island* m_batchIsland;
+ int m_minimumSolverBatchSize;
+ int m_batchIslandMinBodyCount;
+ IslandDispatchFunc m_islandDispatch;
+
+ Island* getIsland(int id);
+ virtual Island* allocateIsland(int id, int numBodies);
+ virtual void initIslandPools();
+ virtual void addBodiesToIslands(btCollisionWorld* collisionWorld);
+ virtual void addManifoldsToIslands(btDispatcher* dispatcher);
+ virtual void addConstraintsToIslands(btAlignedObjectArray<btTypedConstraint*>& constraints);
+ virtual void mergeIslands();
- Island* getIsland( int id );
- virtual Island* allocateIsland( int id, int numBodies );
- virtual void initIslandPools();
- virtual void addBodiesToIslands( btCollisionWorld* collisionWorld );
- virtual void addManifoldsToIslands( btDispatcher* dispatcher );
- virtual void addConstraintsToIslands( btAlignedObjectArray<btTypedConstraint*>& constraints );
- virtual void mergeIslands();
-
public:
btSimulationIslandManagerMt();
virtual ~btSimulationIslandManagerMt();
- virtual void buildAndProcessIslands( btDispatcher* dispatcher,
- btCollisionWorld* collisionWorld,
- btAlignedObjectArray<btTypedConstraint*>& constraints,
- const SolverParams& solverParams
- );
+ virtual void buildAndProcessIslands(btDispatcher* dispatcher,
+ btCollisionWorld* collisionWorld,
+ btAlignedObjectArray<btTypedConstraint*>& constraints,
+ const SolverParams& solverParams);
- virtual void buildIslands(btDispatcher* dispatcher,btCollisionWorld* colWorld);
+ virtual void buildIslands(btDispatcher* dispatcher, btCollisionWorld* colWorld);
- int getMinimumSolverBatchSize() const
- {
- return m_minimumSolverBatchSize;
- }
- void setMinimumSolverBatchSize( int sz )
- {
- m_minimumSolverBatchSize = sz;
- }
- IslandDispatchFunc getIslandDispatchFunction() const
- {
- return m_islandDispatch;
- }
- // allow users to set their own dispatch function for multithreaded dispatch
- void setIslandDispatchFunction( IslandDispatchFunc func )
- {
- m_islandDispatch = func;
- }
+ int getMinimumSolverBatchSize() const
+ {
+ return m_minimumSolverBatchSize;
+ }
+ void setMinimumSolverBatchSize(int sz)
+ {
+ m_minimumSolverBatchSize = sz;
+ }
+ IslandDispatchFunc getIslandDispatchFunction() const
+ {
+ return m_islandDispatch;
+ }
+ // allow users to set their own dispatch function for multithreaded dispatch
+ void setIslandDispatchFunction(IslandDispatchFunc func)
+ {
+ m_islandDispatch = func;
+ }
};
-
-#endif //BT_SIMULATION_ISLAND_MANAGER_H
-
+#endif //BT_SIMULATION_ISLAND_MANAGER_H
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.cpp b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.cpp
index 0e85b55728..53fc48d4b9 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.cpp
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.cpp
@@ -21,7 +21,6 @@
*/
-
#include "btMultiBody.h"
#include "btMultiBodyLink.h"
#include "btMultiBodyLinkCollider.h"
@@ -29,28 +28,29 @@
#include "LinearMath/btTransformUtil.h"
#include "LinearMath/btSerializer.h"
//#include "Bullet3Common/b3Logging.h"
-// #define INCLUDE_GYRO_TERM
+// #define INCLUDE_GYRO_TERM
-///todo: determine if we need these options. If so, make a proper API, otherwise delete those globals
-bool gJointFeedbackInWorldSpace = false;
-bool gJointFeedbackInJointFrame = false;
-namespace {
- const btScalar SLEEP_EPSILON = btScalar(0.05); // this is a squared velocity (m^2 s^-2)
- const btScalar SLEEP_TIMEOUT = btScalar(2); // in seconds
+namespace
+{
+const btScalar SLEEP_EPSILON = btScalar(0.05); // this is a squared velocity (m^2 s^-2)
+const btScalar SLEEP_TIMEOUT = btScalar(2); // in seconds
+} // namespace
+
+void btMultiBody::spatialTransform(const btMatrix3x3 &rotation_matrix, // rotates vectors in 'from' frame to vectors in 'to' frame
+ const btVector3 &displacement, // vector from origin of 'from' frame to origin of 'to' frame, in 'to' coordinates
+ const btVector3 &top_in, // top part of input vector
+ const btVector3 &bottom_in, // bottom part of input vector
+ btVector3 &top_out, // top part of output vector
+ btVector3 &bottom_out) // bottom part of output vector
+{
+ top_out = rotation_matrix * top_in;
+ bottom_out = -displacement.cross(top_out) + rotation_matrix * bottom_in;
}
-namespace {
- void SpatialTransform(const btMatrix3x3 &rotation_matrix, // rotates vectors in 'from' frame to vectors in 'to' frame
- const btVector3 &displacement, // vector from origin of 'from' frame to origin of 'to' frame, in 'to' coordinates
- const btVector3 &top_in, // top part of input vector
- const btVector3 &bottom_in, // bottom part of input vector
- btVector3 &top_out, // top part of output vector
- btVector3 &bottom_out) // bottom part of output vector
- {
- top_out = rotation_matrix * top_in;
- bottom_out = -displacement.cross(top_out) + rotation_matrix * bottom_in;
- }
+namespace
+{
+
#if 0
void InverseSpatialTransform(const btMatrix3x3 &rotation_matrix,
@@ -83,60 +83,58 @@ namespace {
bottom_out = a_bottom.cross(b_top) + a_top.cross(b_bottom);
}
#endif
-
-}
+} // namespace
//
// Implementation of class btMultiBody
//
btMultiBody::btMultiBody(int n_links,
- btScalar mass,
- const btVector3 &inertia,
- bool fixedBase,
- bool canSleep,
- bool /*deprecatedUseMultiDof*/)
- :
- m_baseCollider(0),
- m_baseName(0),
- m_basePos(0,0,0),
- m_baseQuat(0, 0, 0, 1),
- m_baseMass(mass),
- m_baseInertia(inertia),
-
- m_fixedBase(fixedBase),
- m_awake(true),
- m_canSleep(canSleep),
- m_sleepTimer(0),
- m_userObjectPointer(0),
- m_userIndex2(-1),
- m_userIndex(-1),
- m_companionId(-1),
- m_linearDamping(0.04f),
- m_angularDamping(0.04f),
- m_useGyroTerm(true),
- m_maxAppliedImpulse(1000.f),
- m_maxCoordinateVelocity(100.f),
- m_hasSelfCollision(true),
- __posUpdated(false),
- m_dofCount(0),
- m_posVarCnt(0),
- m_useRK4(false),
- m_useGlobalVelocities(false),
- m_internalNeedsJointFeedback(false)
-{
- m_cachedInertiaTopLeft.setValue(0,0,0,0,0,0,0,0,0);
- m_cachedInertiaTopRight.setValue(0,0,0,0,0,0,0,0,0);
- m_cachedInertiaLowerLeft.setValue(0,0,0,0,0,0,0,0,0);
- m_cachedInertiaLowerRight.setValue(0,0,0,0,0,0,0,0,0);
- m_cachedInertiaValid=false;
+ btScalar mass,
+ const btVector3 &inertia,
+ bool fixedBase,
+ bool canSleep,
+ bool /*deprecatedUseMultiDof*/)
+ : m_baseCollider(0),
+ m_baseName(0),
+ m_basePos(0, 0, 0),
+ m_baseQuat(0, 0, 0, 1),
+ m_baseMass(mass),
+ m_baseInertia(inertia),
+
+ m_fixedBase(fixedBase),
+ m_awake(true),
+ m_canSleep(canSleep),
+ m_sleepTimer(0),
+ m_userObjectPointer(0),
+ m_userIndex2(-1),
+ m_userIndex(-1),
+ m_companionId(-1),
+ m_linearDamping(0.04f),
+ m_angularDamping(0.04f),
+ m_useGyroTerm(true),
+ m_maxAppliedImpulse(1000.f),
+ m_maxCoordinateVelocity(100.f),
+ m_hasSelfCollision(true),
+ __posUpdated(false),
+ m_dofCount(0),
+ m_posVarCnt(0),
+ m_useRK4(false),
+ m_useGlobalVelocities(false),
+ m_internalNeedsJointFeedback(false)
+{
+ m_cachedInertiaTopLeft.setValue(0, 0, 0, 0, 0, 0, 0, 0, 0);
+ m_cachedInertiaTopRight.setValue(0, 0, 0, 0, 0, 0, 0, 0, 0);
+ m_cachedInertiaLowerLeft.setValue(0, 0, 0, 0, 0, 0, 0, 0, 0);
+ m_cachedInertiaLowerRight.setValue(0, 0, 0, 0, 0, 0, 0, 0, 0);
+ m_cachedInertiaValid = false;
m_links.resize(n_links);
m_matrixBuf.resize(n_links + 1);
- m_baseForce.setValue(0, 0, 0);
- m_baseTorque.setValue(0, 0, 0);
+ m_baseForce.setValue(0, 0, 0);
+ m_baseTorque.setValue(0, 0, 0);
clearConstraintForces();
clearForcesAndTorques();
@@ -147,131 +145,125 @@ btMultiBody::~btMultiBody()
}
void btMultiBody::setupFixed(int i,
- btScalar mass,
- const btVector3 &inertia,
- int parent,
- const btQuaternion &rotParentToThis,
- const btVector3 &parentComToThisPivotOffset,
- const btVector3 &thisPivotToThisComOffset, bool /*deprecatedDisableParentCollision*/)
-{
-
+ btScalar mass,
+ const btVector3 &inertia,
+ int parent,
+ const btQuaternion &rotParentToThis,
+ const btVector3 &parentComToThisPivotOffset,
+ const btVector3 &thisPivotToThisComOffset, bool /*deprecatedDisableParentCollision*/)
+{
m_links[i].m_mass = mass;
- m_links[i].m_inertiaLocal = inertia;
- m_links[i].m_parent = parent;
- m_links[i].setAxisTop(0, 0., 0., 0.);
- m_links[i].setAxisBottom(0, btVector3(0,0,0));
- m_links[i].m_zeroRotParentToThis = rotParentToThis;
+ m_links[i].m_inertiaLocal = inertia;
+ m_links[i].m_parent = parent;
+ m_links[i].setAxisTop(0, 0., 0., 0.);
+ m_links[i].setAxisBottom(0, btVector3(0, 0, 0));
+ m_links[i].m_zeroRotParentToThis = rotParentToThis;
m_links[i].m_dVector = thisPivotToThisComOffset;
- m_links[i].m_eVector = parentComToThisPivotOffset;
+ m_links[i].m_eVector = parentComToThisPivotOffset;
m_links[i].m_jointType = btMultibodyLink::eFixed;
m_links[i].m_dofCount = 0;
m_links[i].m_posVarCount = 0;
- m_links[i].m_flags |=BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION;
-
+ m_links[i].m_flags |= BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION;
+
m_links[i].updateCacheMultiDof();
updateLinksDofOffsets();
-
}
-
void btMultiBody::setupPrismatic(int i,
- btScalar mass,
- const btVector3 &inertia,
- int parent,
- const btQuaternion &rotParentToThis,
- const btVector3 &jointAxis,
- const btVector3 &parentComToThisPivotOffset,
- const btVector3 &thisPivotToThisComOffset,
- bool disableParentCollision)
+ btScalar mass,
+ const btVector3 &inertia,
+ int parent,
+ const btQuaternion &rotParentToThis,
+ const btVector3 &jointAxis,
+ const btVector3 &parentComToThisPivotOffset,
+ const btVector3 &thisPivotToThisComOffset,
+ bool disableParentCollision)
{
m_dofCount += 1;
m_posVarCnt += 1;
-
- m_links[i].m_mass = mass;
- m_links[i].m_inertiaLocal = inertia;
- m_links[i].m_parent = parent;
- m_links[i].m_zeroRotParentToThis = rotParentToThis;
- m_links[i].setAxisTop(0, 0., 0., 0.);
- m_links[i].setAxisBottom(0, jointAxis);
- m_links[i].m_eVector = parentComToThisPivotOffset;
+
+ m_links[i].m_mass = mass;
+ m_links[i].m_inertiaLocal = inertia;
+ m_links[i].m_parent = parent;
+ m_links[i].m_zeroRotParentToThis = rotParentToThis;
+ m_links[i].setAxisTop(0, 0., 0., 0.);
+ m_links[i].setAxisBottom(0, jointAxis);
+ m_links[i].m_eVector = parentComToThisPivotOffset;
m_links[i].m_dVector = thisPivotToThisComOffset;
- m_links[i].m_cachedRotParentToThis = rotParentToThis;
+ m_links[i].m_cachedRotParentToThis = rotParentToThis;
m_links[i].m_jointType = btMultibodyLink::ePrismatic;
m_links[i].m_dofCount = 1;
- m_links[i].m_posVarCount = 1;
+ m_links[i].m_posVarCount = 1;
m_links[i].m_jointPos[0] = 0.f;
m_links[i].m_jointTorque[0] = 0.f;
if (disableParentCollision)
- m_links[i].m_flags |=BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION;
+ m_links[i].m_flags |= BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION;
//
-
+
m_links[i].updateCacheMultiDof();
-
+
updateLinksDofOffsets();
}
void btMultiBody::setupRevolute(int i,
- btScalar mass,
- const btVector3 &inertia,
- int parent,
- const btQuaternion &rotParentToThis,
- const btVector3 &jointAxis,
- const btVector3 &parentComToThisPivotOffset,
- const btVector3 &thisPivotToThisComOffset,
- bool disableParentCollision)
+ btScalar mass,
+ const btVector3 &inertia,
+ int parent,
+ const btQuaternion &rotParentToThis,
+ const btVector3 &jointAxis,
+ const btVector3 &parentComToThisPivotOffset,
+ const btVector3 &thisPivotToThisComOffset,
+ bool disableParentCollision)
{
m_dofCount += 1;
m_posVarCnt += 1;
-
- m_links[i].m_mass = mass;
- m_links[i].m_inertiaLocal = inertia;
- m_links[i].m_parent = parent;
- m_links[i].m_zeroRotParentToThis = rotParentToThis;
- m_links[i].setAxisTop(0, jointAxis);
- m_links[i].setAxisBottom(0, jointAxis.cross(thisPivotToThisComOffset));
- m_links[i].m_dVector = thisPivotToThisComOffset;
- m_links[i].m_eVector = parentComToThisPivotOffset;
+
+ m_links[i].m_mass = mass;
+ m_links[i].m_inertiaLocal = inertia;
+ m_links[i].m_parent = parent;
+ m_links[i].m_zeroRotParentToThis = rotParentToThis;
+ m_links[i].setAxisTop(0, jointAxis);
+ m_links[i].setAxisBottom(0, jointAxis.cross(thisPivotToThisComOffset));
+ m_links[i].m_dVector = thisPivotToThisComOffset;
+ m_links[i].m_eVector = parentComToThisPivotOffset;
m_links[i].m_jointType = btMultibodyLink::eRevolute;
m_links[i].m_dofCount = 1;
- m_links[i].m_posVarCount = 1;
+ m_links[i].m_posVarCount = 1;
m_links[i].m_jointPos[0] = 0.f;
m_links[i].m_jointTorque[0] = 0.f;
if (disableParentCollision)
- m_links[i].m_flags |=BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION;
- //
+ m_links[i].m_flags |= BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION;
+ //
m_links[i].updateCacheMultiDof();
//
updateLinksDofOffsets();
}
-
-
void btMultiBody::setupSpherical(int i,
- btScalar mass,
- const btVector3 &inertia,
- int parent,
- const btQuaternion &rotParentToThis,
- const btVector3 &parentComToThisPivotOffset,
- const btVector3 &thisPivotToThisComOffset,
- bool disableParentCollision)
-{
-
+ btScalar mass,
+ const btVector3 &inertia,
+ int parent,
+ const btQuaternion &rotParentToThis,
+ const btVector3 &parentComToThisPivotOffset,
+ const btVector3 &thisPivotToThisComOffset,
+ bool disableParentCollision)
+{
m_dofCount += 3;
m_posVarCnt += 4;
m_links[i].m_mass = mass;
- m_links[i].m_inertiaLocal = inertia;
- m_links[i].m_parent = parent;
- m_links[i].m_zeroRotParentToThis = rotParentToThis;
- m_links[i].m_dVector = thisPivotToThisComOffset;
- m_links[i].m_eVector = parentComToThisPivotOffset;
+ m_links[i].m_inertiaLocal = inertia;
+ m_links[i].m_parent = parent;
+ m_links[i].m_zeroRotParentToThis = rotParentToThis;
+ m_links[i].m_dVector = thisPivotToThisComOffset;
+ m_links[i].m_eVector = parentComToThisPivotOffset;
m_links[i].m_jointType = btMultibodyLink::eSpherical;
m_links[i].m_dofCount = 3;
@@ -282,281 +274,297 @@ void btMultiBody::setupSpherical(int i,
m_links[i].setAxisBottom(0, m_links[i].getAxisTop(0).cross(thisPivotToThisComOffset));
m_links[i].setAxisBottom(1, m_links[i].getAxisTop(1).cross(thisPivotToThisComOffset));
m_links[i].setAxisBottom(2, m_links[i].getAxisTop(2).cross(thisPivotToThisComOffset));
- m_links[i].m_jointPos[0] = m_links[i].m_jointPos[1] = m_links[i].m_jointPos[2] = 0.f; m_links[i].m_jointPos[3] = 1.f;
+ m_links[i].m_jointPos[0] = m_links[i].m_jointPos[1] = m_links[i].m_jointPos[2] = 0.f;
+ m_links[i].m_jointPos[3] = 1.f;
m_links[i].m_jointTorque[0] = m_links[i].m_jointTorque[1] = m_links[i].m_jointTorque[2] = 0.f;
-
if (disableParentCollision)
- m_links[i].m_flags |=BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION;
+ m_links[i].m_flags |= BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION;
//
- m_links[i].updateCacheMultiDof();
+ m_links[i].updateCacheMultiDof();
//
updateLinksDofOffsets();
}
void btMultiBody::setupPlanar(int i,
- btScalar mass,
- const btVector3 &inertia,
- int parent,
- const btQuaternion &rotParentToThis,
- const btVector3 &rotationAxis,
- const btVector3 &parentComToThisComOffset,
- bool disableParentCollision)
-{
-
+ btScalar mass,
+ const btVector3 &inertia,
+ int parent,
+ const btQuaternion &rotParentToThis,
+ const btVector3 &rotationAxis,
+ const btVector3 &parentComToThisComOffset,
+ bool disableParentCollision)
+{
m_dofCount += 3;
m_posVarCnt += 3;
m_links[i].m_mass = mass;
- m_links[i].m_inertiaLocal = inertia;
- m_links[i].m_parent = parent;
- m_links[i].m_zeroRotParentToThis = rotParentToThis;
+ m_links[i].m_inertiaLocal = inertia;
+ m_links[i].m_parent = parent;
+ m_links[i].m_zeroRotParentToThis = rotParentToThis;
m_links[i].m_dVector.setZero();
- m_links[i].m_eVector = parentComToThisComOffset;
+ m_links[i].m_eVector = parentComToThisComOffset;
//
btVector3 vecNonParallelToRotAxis(1, 0, 0);
- if(rotationAxis.normalized().dot(vecNonParallelToRotAxis) > 0.999)
+ if (rotationAxis.normalized().dot(vecNonParallelToRotAxis) > 0.999)
vecNonParallelToRotAxis.setValue(0, 1, 0);
//
m_links[i].m_jointType = btMultibodyLink::ePlanar;
m_links[i].m_dofCount = 3;
m_links[i].m_posVarCount = 3;
- btVector3 n=rotationAxis.normalized();
- m_links[i].setAxisTop(0, n[0],n[1],n[2]);
- m_links[i].setAxisTop(1,0,0,0);
- m_links[i].setAxisTop(2,0,0,0);
- m_links[i].setAxisBottom(0,0,0,0);
+ btVector3 n = rotationAxis.normalized();
+ m_links[i].setAxisTop(0, n[0], n[1], n[2]);
+ m_links[i].setAxisTop(1, 0, 0, 0);
+ m_links[i].setAxisTop(2, 0, 0, 0);
+ m_links[i].setAxisBottom(0, 0, 0, 0);
btVector3 cr = m_links[i].getAxisTop(0).cross(vecNonParallelToRotAxis);
- m_links[i].setAxisBottom(1,cr[0],cr[1],cr[2]);
+ m_links[i].setAxisBottom(1, cr[0], cr[1], cr[2]);
cr = m_links[i].getAxisBottom(1).cross(m_links[i].getAxisTop(0));
- m_links[i].setAxisBottom(2,cr[0],cr[1],cr[2]);
+ m_links[i].setAxisBottom(2, cr[0], cr[1], cr[2]);
m_links[i].m_jointPos[0] = m_links[i].m_jointPos[1] = m_links[i].m_jointPos[2] = 0.f;
m_links[i].m_jointTorque[0] = m_links[i].m_jointTorque[1] = m_links[i].m_jointTorque[2] = 0.f;
if (disableParentCollision)
- m_links[i].m_flags |=BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION;
- //
+ m_links[i].m_flags |= BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION;
+ //
m_links[i].updateCacheMultiDof();
//
updateLinksDofOffsets();
+
+ m_links[i].setAxisBottom(1, m_links[i].getAxisBottom(1).normalized());
+ m_links[i].setAxisBottom(2, m_links[i].getAxisBottom(2).normalized());
}
void btMultiBody::finalizeMultiDof()
{
m_deltaV.resize(0);
m_deltaV.resize(6 + m_dofCount);
- m_realBuf.resize(6 + m_dofCount + m_dofCount*m_dofCount + 6 + m_dofCount); //m_dofCount for joint-space vels + m_dofCount^2 for "D" matrices + delta-pos vector (6 base "vels" + joint "vels")
- m_vectorBuf.resize(2 * m_dofCount); //two 3-vectors (i.e. one six-vector) for each system dof ("h" matrices)
- for (int i=0;i<m_vectorBuf.size();i++)
+ m_realBuf.resize(6 + m_dofCount + m_dofCount * m_dofCount + 6 + m_dofCount); //m_dofCount for joint-space vels + m_dofCount^2 for "D" matrices + delta-pos vector (6 base "vels" + joint "vels")
+ m_vectorBuf.resize(2 * m_dofCount); //two 3-vectors (i.e. one six-vector) for each system dof ("h" matrices)
+ for (int i = 0; i < m_vectorBuf.size(); i++)
{
- m_vectorBuf[i].setValue(0,0,0);
+ m_vectorBuf[i].setValue(0, 0, 0);
}
updateLinksDofOffsets();
}
-
+
int btMultiBody::getParent(int i) const
{
- return m_links[i].m_parent;
+ return m_links[i].m_parent;
}
btScalar btMultiBody::getLinkMass(int i) const
{
- return m_links[i].m_mass;
+ return m_links[i].m_mass;
}
-const btVector3 & btMultiBody::getLinkInertia(int i) const
+const btVector3 &btMultiBody::getLinkInertia(int i) const
{
- return m_links[i].m_inertiaLocal;
+ return m_links[i].m_inertiaLocal;
}
btScalar btMultiBody::getJointPos(int i) const
{
- return m_links[i].m_jointPos[0];
+ return m_links[i].m_jointPos[0];
}
btScalar btMultiBody::getJointVel(int i) const
{
- return m_realBuf[6 + m_links[i].m_dofOffset];
+ return m_realBuf[6 + m_links[i].m_dofOffset];
}
-btScalar * btMultiBody::getJointPosMultiDof(int i)
+btScalar *btMultiBody::getJointPosMultiDof(int i)
{
return &m_links[i].m_jointPos[0];
}
-btScalar * btMultiBody::getJointVelMultiDof(int i)
+btScalar *btMultiBody::getJointVelMultiDof(int i)
{
return &m_realBuf[6 + m_links[i].m_dofOffset];
}
-const btScalar * btMultiBody::getJointPosMultiDof(int i) const
+const btScalar *btMultiBody::getJointPosMultiDof(int i) const
{
return &m_links[i].m_jointPos[0];
}
-const btScalar * btMultiBody::getJointVelMultiDof(int i) const
+const btScalar *btMultiBody::getJointVelMultiDof(int i) const
{
return &m_realBuf[6 + m_links[i].m_dofOffset];
}
-
void btMultiBody::setJointPos(int i, btScalar q)
{
- m_links[i].m_jointPos[0] = q;
- m_links[i].updateCacheMultiDof();
+ m_links[i].m_jointPos[0] = q;
+ m_links[i].updateCacheMultiDof();
+}
+
+
+void btMultiBody::setJointPosMultiDof(int i, const double *q)
+{
+ for (int pos = 0; pos < m_links[i].m_posVarCount; ++pos)
+ m_links[i].m_jointPos[pos] = (btScalar)q[pos];
+
+ m_links[i].updateCacheMultiDof();
}
-void btMultiBody::setJointPosMultiDof(int i, btScalar *q)
+void btMultiBody::setJointPosMultiDof(int i, const float *q)
{
- for(int pos = 0; pos < m_links[i].m_posVarCount; ++pos)
- m_links[i].m_jointPos[pos] = q[pos];
+ for (int pos = 0; pos < m_links[i].m_posVarCount; ++pos)
+ m_links[i].m_jointPos[pos] = (btScalar)q[pos];
- m_links[i].updateCacheMultiDof();
+ m_links[i].updateCacheMultiDof();
}
+
+
void btMultiBody::setJointVel(int i, btScalar qdot)
{
- m_realBuf[6 + m_links[i].m_dofOffset] = qdot;
+ m_realBuf[6 + m_links[i].m_dofOffset] = qdot;
}
-void btMultiBody::setJointVelMultiDof(int i, btScalar *qdot)
+void btMultiBody::setJointVelMultiDof(int i, const double *qdot)
{
- for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
- m_realBuf[6 + m_links[i].m_dofOffset + dof] = qdot[dof];
+ for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+ m_realBuf[6 + m_links[i].m_dofOffset + dof] = (btScalar)qdot[dof];
}
-const btVector3 & btMultiBody::getRVector(int i) const
+void btMultiBody::setJointVelMultiDof(int i, const float* qdot)
{
- return m_links[i].m_cachedRVector;
+ for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+ m_realBuf[6 + m_links[i].m_dofOffset + dof] = (btScalar)qdot[dof];
}
-const btQuaternion & btMultiBody::getParentToLocalRot(int i) const
+const btVector3 &btMultiBody::getRVector(int i) const
{
- return m_links[i].m_cachedRotParentToThis;
+ return m_links[i].m_cachedRVector;
+}
+
+const btQuaternion &btMultiBody::getParentToLocalRot(int i) const
+{
+ return m_links[i].m_cachedRotParentToThis;
}
btVector3 btMultiBody::localPosToWorld(int i, const btVector3 &local_pos) const
{
- btAssert(i>=-1);
- btAssert(i<m_links.size());
- if ((i<-1) || (i>=m_links.size()))
+ btAssert(i >= -1);
+ btAssert(i < m_links.size());
+ if ((i < -1) || (i >= m_links.size()))
{
- return btVector3(SIMD_INFINITY,SIMD_INFINITY,SIMD_INFINITY);
+ return btVector3(SIMD_INFINITY, SIMD_INFINITY, SIMD_INFINITY);
}
- btVector3 result = local_pos;
- while (i != -1) {
- // 'result' is in frame i. transform it to frame parent(i)
- result += getRVector(i);
- result = quatRotate(getParentToLocalRot(i).inverse(),result);
- i = getParent(i);
- }
+ btVector3 result = local_pos;
+ while (i != -1)
+ {
+ // 'result' is in frame i. transform it to frame parent(i)
+ result += getRVector(i);
+ result = quatRotate(getParentToLocalRot(i).inverse(), result);
+ i = getParent(i);
+ }
- // 'result' is now in the base frame. transform it to world frame
- result = quatRotate(getWorldToBaseRot().inverse() ,result);
- result += getBasePos();
+ // 'result' is now in the base frame. transform it to world frame
+ result = quatRotate(getWorldToBaseRot().inverse(), result);
+ result += getBasePos();
- return result;
+ return result;
}
btVector3 btMultiBody::worldPosToLocal(int i, const btVector3 &world_pos) const
{
- btAssert(i>=-1);
- btAssert(i<m_links.size());
- if ((i<-1) || (i>=m_links.size()))
+ btAssert(i >= -1);
+ btAssert(i < m_links.size());
+ if ((i < -1) || (i >= m_links.size()))
{
- return btVector3(SIMD_INFINITY,SIMD_INFINITY,SIMD_INFINITY);
+ return btVector3(SIMD_INFINITY, SIMD_INFINITY, SIMD_INFINITY);
}
- if (i == -1) {
- // world to base
- return quatRotate(getWorldToBaseRot(),(world_pos - getBasePos()));
- } else {
- // find position in parent frame, then transform to current frame
- return quatRotate(getParentToLocalRot(i),worldPosToLocal(getParent(i), world_pos)) - getRVector(i);
- }
+ if (i == -1)
+ {
+ // world to base
+ return quatRotate(getWorldToBaseRot(), (world_pos - getBasePos()));
+ }
+ else
+ {
+ // find position in parent frame, then transform to current frame
+ return quatRotate(getParentToLocalRot(i), worldPosToLocal(getParent(i), world_pos)) - getRVector(i);
+ }
}
btVector3 btMultiBody::localDirToWorld(int i, const btVector3 &local_dir) const
{
- btAssert(i>=-1);
- btAssert(i<m_links.size());
- if ((i<-1) || (i>=m_links.size()))
+ btAssert(i >= -1);
+ btAssert(i < m_links.size());
+ if ((i < -1) || (i >= m_links.size()))
{
- return btVector3(SIMD_INFINITY,SIMD_INFINITY,SIMD_INFINITY);
+ return btVector3(SIMD_INFINITY, SIMD_INFINITY, SIMD_INFINITY);
}
-
- btVector3 result = local_dir;
- while (i != -1) {
- result = quatRotate(getParentToLocalRot(i).inverse() , result);
- i = getParent(i);
- }
- result = quatRotate(getWorldToBaseRot().inverse() , result);
- return result;
+ btVector3 result = local_dir;
+ while (i != -1)
+ {
+ result = quatRotate(getParentToLocalRot(i).inverse(), result);
+ i = getParent(i);
+ }
+ result = quatRotate(getWorldToBaseRot().inverse(), result);
+ return result;
}
btVector3 btMultiBody::worldDirToLocal(int i, const btVector3 &world_dir) const
{
- btAssert(i>=-1);
- btAssert(i<m_links.size());
- if ((i<-1) || (i>=m_links.size()))
+ btAssert(i >= -1);
+ btAssert(i < m_links.size());
+ if ((i < -1) || (i >= m_links.size()))
{
- return btVector3(SIMD_INFINITY,SIMD_INFINITY,SIMD_INFINITY);
+ return btVector3(SIMD_INFINITY, SIMD_INFINITY, SIMD_INFINITY);
}
- if (i == -1) {
- return quatRotate(getWorldToBaseRot(), world_dir);
- } else {
- return quatRotate(getParentToLocalRot(i) ,worldDirToLocal(getParent(i), world_dir));
- }
+ if (i == -1)
+ {
+ return quatRotate(getWorldToBaseRot(), world_dir);
+ }
+ else
+ {
+ return quatRotate(getParentToLocalRot(i), worldDirToLocal(getParent(i), world_dir));
+ }
}
btMatrix3x3 btMultiBody::localFrameToWorld(int i, const btMatrix3x3 &local_frame) const
{
- btMatrix3x3 result = local_frame;
- btVector3 frameInWorld0 = localDirToWorld(i, local_frame.getColumn(0));
- btVector3 frameInWorld1 = localDirToWorld(i, local_frame.getColumn(1));
- btVector3 frameInWorld2 = localDirToWorld(i, local_frame.getColumn(2));
- result.setValue(frameInWorld0[0], frameInWorld1[0], frameInWorld2[0], frameInWorld0[1], frameInWorld1[1], frameInWorld2[1], frameInWorld0[2], frameInWorld1[2], frameInWorld2[2]);
- return result;
+ btMatrix3x3 result = local_frame;
+ btVector3 frameInWorld0 = localDirToWorld(i, local_frame.getColumn(0));
+ btVector3 frameInWorld1 = localDirToWorld(i, local_frame.getColumn(1));
+ btVector3 frameInWorld2 = localDirToWorld(i, local_frame.getColumn(2));
+ result.setValue(frameInWorld0[0], frameInWorld1[0], frameInWorld2[0], frameInWorld0[1], frameInWorld1[1], frameInWorld2[1], frameInWorld0[2], frameInWorld1[2], frameInWorld2[2]);
+ return result;
}
void btMultiBody::compTreeLinkVelocities(btVector3 *omega, btVector3 *vel) const
{
int num_links = getNumLinks();
- // Calculates the velocities of each link (and the base) in its local frame
- omega[0] = quatRotate(m_baseQuat ,getBaseOmega());
- vel[0] = quatRotate(m_baseQuat ,getBaseVel());
-
- for (int i = 0; i < num_links; ++i)
+ // Calculates the velocities of each link (and the base) in its local frame
+ const btQuaternion& base_rot = getWorldToBaseRot();
+ omega[0] = quatRotate(base_rot, getBaseOmega());
+ vel[0] = quatRotate(base_rot, getBaseVel());
+
+ for (int i = 0; i < num_links; ++i)
{
- const int parent = m_links[i].m_parent;
+ const btMultibodyLink& link = getLink(i);
+ const int parent = link.m_parent;
- // transform parent vel into this frame, store in omega[i+1], vel[i+1]
- SpatialTransform(btMatrix3x3(m_links[i].m_cachedRotParentToThis), m_links[i].m_cachedRVector,
- omega[parent+1], vel[parent+1],
- omega[i+1], vel[i+1]);
+ // transform parent vel into this frame, store in omega[i+1], vel[i+1]
+ spatialTransform(btMatrix3x3(link.m_cachedRotParentToThis), link.m_cachedRVector,
+ omega[parent + 1], vel[parent + 1],
+ omega[i + 1], vel[i + 1]);
- // now add qidot * shat_i
- //only supported for revolute/prismatic joints, todo: spherical and planar joints
- switch(m_links[i].m_jointType)
+ // now add qidot * shat_i
+ const btScalar* jointVel = getJointVelMultiDof(i);
+ for (int dof = 0; dof < link.m_dofCount; ++dof)
{
- case btMultibodyLink::ePrismatic:
- case btMultibodyLink::eRevolute:
- {
- btVector3 axisTop = m_links[i].getAxisTop(0);
- btVector3 axisBottom = m_links[i].getAxisBottom(0);
- btScalar jointVel = getJointVel(i);
- omega[i+1] += jointVel * axisTop;
- vel[i+1] += jointVel * axisBottom;
- break;
- }
- default:
- {
- }
+ omega[i + 1] += jointVel[dof] * link.getAxisTop(dof);
+ vel[i + 1] += jointVel[dof] * link.getAxisBottom(dof);
}
}
}
@@ -564,41 +572,48 @@ void btMultiBody::compTreeLinkVelocities(btVector3 *omega, btVector3 *vel) const
btScalar btMultiBody::getKineticEnergy() const
{
int num_links = getNumLinks();
- // TODO: would be better not to allocate memory here
- btAlignedObjectArray<btVector3> omega;omega.resize(num_links+1);
- btAlignedObjectArray<btVector3> vel;vel.resize(num_links+1);
- compTreeLinkVelocities(&omega[0], &vel[0]);
-
- // we will do the factor of 0.5 at the end
- btScalar result = m_baseMass * vel[0].dot(vel[0]);
- result += omega[0].dot(m_baseInertia * omega[0]);
-
- for (int i = 0; i < num_links; ++i) {
- result += m_links[i].m_mass * vel[i+1].dot(vel[i+1]);
- result += omega[i+1].dot(m_links[i].m_inertiaLocal * omega[i+1]);
- }
+ // TODO: would be better not to allocate memory here
+ btAlignedObjectArray<btVector3> omega;
+ omega.resize(num_links + 1);
+ btAlignedObjectArray<btVector3> vel;
+ vel.resize(num_links + 1);
+ compTreeLinkVelocities(&omega[0], &vel[0]);
+
+ // we will do the factor of 0.5 at the end
+ btScalar result = m_baseMass * vel[0].dot(vel[0]);
+ result += omega[0].dot(m_baseInertia * omega[0]);
+
+ for (int i = 0; i < num_links; ++i)
+ {
+ result += m_links[i].m_mass * vel[i + 1].dot(vel[i + 1]);
+ result += omega[i + 1].dot(m_links[i].m_inertiaLocal * omega[i + 1]);
+ }
- return 0.5f * result;
+ return 0.5f * result;
}
btVector3 btMultiBody::getAngularMomentum() const
{
int num_links = getNumLinks();
- // TODO: would be better not to allocate memory here
- btAlignedObjectArray<btVector3> omega;omega.resize(num_links+1);
- btAlignedObjectArray<btVector3> vel;vel.resize(num_links+1);
- btAlignedObjectArray<btQuaternion> rot_from_world;rot_from_world.resize(num_links+1);
- compTreeLinkVelocities(&omega[0], &vel[0]);
-
- rot_from_world[0] = m_baseQuat;
- btVector3 result = quatRotate(rot_from_world[0].inverse() , (m_baseInertia * omega[0]));
-
- for (int i = 0; i < num_links; ++i) {
- rot_from_world[i+1] = m_links[i].m_cachedRotParentToThis * rot_from_world[m_links[i].m_parent+1];
- result += (quatRotate(rot_from_world[i+1].inverse() , (m_links[i].m_inertiaLocal * omega[i+1])));
- }
+ // TODO: would be better not to allocate memory here
+ btAlignedObjectArray<btVector3> omega;
+ omega.resize(num_links + 1);
+ btAlignedObjectArray<btVector3> vel;
+ vel.resize(num_links + 1);
+ btAlignedObjectArray<btQuaternion> rot_from_world;
+ rot_from_world.resize(num_links + 1);
+ compTreeLinkVelocities(&omega[0], &vel[0]);
+
+ rot_from_world[0] = m_baseQuat;
+ btVector3 result = quatRotate(rot_from_world[0].inverse(), (m_baseInertia * omega[0]));
+
+ for (int i = 0; i < num_links; ++i)
+ {
+ rot_from_world[i + 1] = m_links[i].m_cachedRotParentToThis * rot_from_world[m_links[i].m_parent + 1];
+ result += (quatRotate(rot_from_world[i + 1].inverse(), (m_links[i].m_inertiaLocal * omega[i + 1])));
+ }
- return result;
+ return result;
}
void btMultiBody::clearConstraintForces()
@@ -606,57 +621,55 @@ void btMultiBody::clearConstraintForces()
m_baseConstraintForce.setValue(0, 0, 0);
m_baseConstraintTorque.setValue(0, 0, 0);
-
- for (int i = 0; i < getNumLinks(); ++i) {
- m_links[i].m_appliedConstraintForce.setValue(0, 0, 0);
- m_links[i].m_appliedConstraintTorque.setValue(0, 0, 0);
- }
+ for (int i = 0; i < getNumLinks(); ++i)
+ {
+ m_links[i].m_appliedConstraintForce.setValue(0, 0, 0);
+ m_links[i].m_appliedConstraintTorque.setValue(0, 0, 0);
+ }
}
void btMultiBody::clearForcesAndTorques()
{
- m_baseForce.setValue(0, 0, 0);
- m_baseTorque.setValue(0, 0, 0);
+ m_baseForce.setValue(0, 0, 0);
+ m_baseTorque.setValue(0, 0, 0);
-
- for (int i = 0; i < getNumLinks(); ++i) {
- m_links[i].m_appliedForce.setValue(0, 0, 0);
- m_links[i].m_appliedTorque.setValue(0, 0, 0);
+ for (int i = 0; i < getNumLinks(); ++i)
+ {
+ m_links[i].m_appliedForce.setValue(0, 0, 0);
+ m_links[i].m_appliedTorque.setValue(0, 0, 0);
m_links[i].m_jointTorque[0] = m_links[i].m_jointTorque[1] = m_links[i].m_jointTorque[2] = m_links[i].m_jointTorque[3] = m_links[i].m_jointTorque[4] = m_links[i].m_jointTorque[5] = 0.f;
- }
+ }
}
void btMultiBody::clearVelocities()
{
- for (int i = 0; i < 6 + getNumDofs(); ++i)
+ for (int i = 0; i < 6 + getNumDofs(); ++i)
{
m_realBuf[i] = 0.f;
}
}
void btMultiBody::addLinkForce(int i, const btVector3 &f)
{
- m_links[i].m_appliedForce += f;
+ m_links[i].m_appliedForce += f;
}
void btMultiBody::addLinkTorque(int i, const btVector3 &t)
{
- m_links[i].m_appliedTorque += t;
+ m_links[i].m_appliedTorque += t;
}
void btMultiBody::addLinkConstraintForce(int i, const btVector3 &f)
{
- m_links[i].m_appliedConstraintForce += f;
+ m_links[i].m_appliedConstraintForce += f;
}
void btMultiBody::addLinkConstraintTorque(int i, const btVector3 &t)
{
- m_links[i].m_appliedConstraintTorque += t;
+ m_links[i].m_appliedConstraintTorque += t;
}
-
-
void btMultiBody::addJointTorque(int i, btScalar Q)
{
- m_links[i].m_jointTorque[0] += Q;
+ m_links[i].m_jointTorque[0] += Q;
}
void btMultiBody::addJointTorqueMultiDof(int i, int dof, btScalar Q)
@@ -666,70 +679,72 @@ void btMultiBody::addJointTorqueMultiDof(int i, int dof, btScalar Q)
void btMultiBody::addJointTorqueMultiDof(int i, const btScalar *Q)
{
- for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+ for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
m_links[i].m_jointTorque[dof] = Q[dof];
}
-const btVector3 & btMultiBody::getLinkForce(int i) const
+const btVector3 &btMultiBody::getLinkForce(int i) const
{
- return m_links[i].m_appliedForce;
+ return m_links[i].m_appliedForce;
}
-const btVector3 & btMultiBody::getLinkTorque(int i) const
+const btVector3 &btMultiBody::getLinkTorque(int i) const
{
- return m_links[i].m_appliedTorque;
+ return m_links[i].m_appliedTorque;
}
btScalar btMultiBody::getJointTorque(int i) const
{
- return m_links[i].m_jointTorque[0];
+ return m_links[i].m_jointTorque[0];
}
-btScalar * btMultiBody::getJointTorqueMultiDof(int i)
+btScalar *btMultiBody::getJointTorqueMultiDof(int i)
{
- return &m_links[i].m_jointTorque[0];
+ return &m_links[i].m_jointTorque[0];
}
-inline btMatrix3x3 outerProduct(const btVector3& v0, const btVector3& v1) //renamed it from vecMulVecTranspose (http://en.wikipedia.org/wiki/Outer_product); maybe it should be moved to btVector3 like dot and cross?
-{
- btVector3 row0 = btVector3(
- v0.x() * v1.x(),
- v0.x() * v1.y(),
- v0.x() * v1.z());
- btVector3 row1 = btVector3(
- v0.y() * v1.x(),
- v0.y() * v1.y(),
- v0.y() * v1.z());
- btVector3 row2 = btVector3(
- v0.z() * v1.x(),
- v0.z() * v1.y(),
- v0.z() * v1.z());
-
- btMatrix3x3 m(row0[0],row0[1],row0[2],
- row1[0],row1[1],row1[2],
- row2[0],row2[1],row2[2]);
- return m;
+inline btMatrix3x3 outerProduct(const btVector3 &v0, const btVector3 &v1) //renamed it from vecMulVecTranspose (http://en.wikipedia.org/wiki/Outer_product); maybe it should be moved to btVector3 like dot and cross?
+{
+ btVector3 row0 = btVector3(
+ v0.x() * v1.x(),
+ v0.x() * v1.y(),
+ v0.x() * v1.z());
+ btVector3 row1 = btVector3(
+ v0.y() * v1.x(),
+ v0.y() * v1.y(),
+ v0.y() * v1.z());
+ btVector3 row2 = btVector3(
+ v0.z() * v1.x(),
+ v0.z() * v1.y(),
+ v0.z() * v1.z());
+
+ btMatrix3x3 m(row0[0], row0[1], row0[2],
+ row1[0], row1[1], row1[2],
+ row2[0], row2[1], row2[2]);
+ return m;
}
#define vecMulVecTranspose(v0, v1Transposed) outerProduct(v0, v1Transposed)
//
void btMultiBody::computeAccelerationsArticulatedBodyAlgorithmMultiDof(btScalar dt,
- btAlignedObjectArray<btScalar> &scratch_r,
- btAlignedObjectArray<btVector3> &scratch_v,
- btAlignedObjectArray<btMatrix3x3> &scratch_m,
- bool isConstraintPass)
+ btAlignedObjectArray<btScalar> &scratch_r,
+ btAlignedObjectArray<btVector3> &scratch_v,
+ btAlignedObjectArray<btMatrix3x3> &scratch_m,
+ bool isConstraintPass,
+ bool jointFeedbackInWorldSpace,
+ bool jointFeedbackInJointFrame)
{
- // Implement Featherstone's algorithm to calculate joint accelerations (q_double_dot)
- // and the base linear & angular accelerations.
+ // Implement Featherstone's algorithm to calculate joint accelerations (q_double_dot)
+ // and the base linear & angular accelerations.
- // We apply damping forces in this routine as well as any external forces specified by the
- // caller (via addBaseForce etc).
+ // We apply damping forces in this routine as well as any external forces specified by the
+ // caller (via addBaseForce etc).
+
+ // output should point to an array of 6 + num_links reals.
+ // Format is: 3 angular accelerations (in world frame), 3 linear accelerations (in world frame),
+ // num_links joint acceleration values.
- // output should point to an array of 6 + num_links reals.
- // Format is: 3 angular accelerations (in world frame), 3 linear accelerations (in world frame),
- // num_links joint acceleration values.
-
// We added support for multi degree of freedom (multi dof) joints.
// In addition we also can compute the joint reaction forces. This is performed in a second pass,
// so that we can include the effect of the constraint solver forces (computed in the PGS LCP solver)
@@ -738,96 +753,96 @@ void btMultiBody::computeAccelerationsArticulatedBodyAlgorithmMultiDof(btScalar
int num_links = getNumLinks();
- const btScalar DAMPING_K1_LINEAR = m_linearDamping;
+ const btScalar DAMPING_K1_LINEAR = m_linearDamping;
const btScalar DAMPING_K2_LINEAR = m_linearDamping;
const btScalar DAMPING_K1_ANGULAR = m_angularDamping;
- const btScalar DAMPING_K2_ANGULAR= m_angularDamping;
+ const btScalar DAMPING_K2_ANGULAR = m_angularDamping;
const btVector3 base_vel = getBaseVel();
const btVector3 base_omega = getBaseOmega();
- // Temporary matrices/vectors -- use scratch space from caller
- // so that we don't have to keep reallocating every frame
+ // Temporary matrices/vectors -- use scratch space from caller
+ // so that we don't have to keep reallocating every frame
- scratch_r.resize(2*m_dofCount + 7); //multidof? ("Y"s use it and it is used to store qdd) => 2 x m_dofCount
- scratch_v.resize(8*num_links + 6);
- scratch_m.resize(4*num_links + 4);
+ scratch_r.resize(2 * m_dofCount + 7); //multidof? ("Y"s use it and it is used to store qdd) => 2 x m_dofCount
+ scratch_v.resize(8 * num_links + 6);
+ scratch_m.resize(4 * num_links + 4);
//btScalar * r_ptr = &scratch_r[0];
- btScalar * output = &scratch_r[m_dofCount]; // "output" holds the q_double_dot results
- btVector3 * v_ptr = &scratch_v[0];
-
- // vhat_i (top = angular, bottom = linear part)
+ btScalar *output = &scratch_r[m_dofCount]; // "output" holds the q_double_dot results
+ btVector3 *v_ptr = &scratch_v[0];
+
+ // vhat_i (top = angular, bottom = linear part)
btSpatialMotionVector *spatVel = (btSpatialMotionVector *)v_ptr;
v_ptr += num_links * 2 + 2;
//
- // zhat_i^A
- btSpatialForceVector * zeroAccSpatFrc = (btSpatialForceVector *)v_ptr;
+ // zhat_i^A
+ btSpatialForceVector *zeroAccSpatFrc = (btSpatialForceVector *)v_ptr;
v_ptr += num_links * 2 + 2;
//
- // chat_i (note NOT defined for the base)
- btSpatialMotionVector * spatCoriolisAcc = (btSpatialMotionVector *)v_ptr;
+ // chat_i (note NOT defined for the base)
+ btSpatialMotionVector *spatCoriolisAcc = (btSpatialMotionVector *)v_ptr;
v_ptr += num_links * 2;
//
- // Ihat_i^A.
- btSymmetricSpatialDyad * spatInertia = (btSymmetricSpatialDyad *)&scratch_m[num_links + 1];
-
- // Cached 3x3 rotation matrices from parent frame to this frame.
- btMatrix3x3 * rot_from_parent = &m_matrixBuf[0];
- btMatrix3x3 * rot_from_world = &scratch_m[0];
-
- // hhat_i, ahat_i
- // hhat is NOT stored for the base (but ahat is)
- btSpatialForceVector * h = (btSpatialForceVector *)(m_dofCount > 0 ? &m_vectorBuf[0] : 0);
- btSpatialMotionVector * spatAcc = (btSpatialMotionVector *)v_ptr;
- v_ptr += num_links * 2 + 2;
+ // Ihat_i^A.
+ btSymmetricSpatialDyad *spatInertia = (btSymmetricSpatialDyad *)&scratch_m[num_links + 1];
+
+ // Cached 3x3 rotation matrices from parent frame to this frame.
+ btMatrix3x3 *rot_from_parent = &m_matrixBuf[0];
+ btMatrix3x3 *rot_from_world = &scratch_m[0];
+
+ // hhat_i, ahat_i
+ // hhat is NOT stored for the base (but ahat is)
+ btSpatialForceVector *h = (btSpatialForceVector *)(m_dofCount > 0 ? &m_vectorBuf[0] : 0);
+ btSpatialMotionVector *spatAcc = (btSpatialMotionVector *)v_ptr;
+ v_ptr += num_links * 2 + 2;
//
- // Y_i, invD_i
- btScalar * invD = m_dofCount > 0 ? &m_realBuf[6 + m_dofCount] : 0;
- btScalar * Y = &scratch_r[0];
+ // Y_i, invD_i
+ btScalar *invD = m_dofCount > 0 ? &m_realBuf[6 + m_dofCount] : 0;
+ btScalar *Y = &scratch_r[0];
//
- //aux variables
- btSpatialMotionVector spatJointVel; //spatial velocity due to the joint motion (i.e. without predecessors' influence)
- btScalar D[36]; //"D" matrix; it's dofxdof for each body so asingle 6x6 D matrix will do
- btScalar invD_times_Y[6]; //D^{-1} * Y [dofxdof x dofx1 = dofx1] <=> D^{-1} * u; better moved to buffers since it is recalced in calcAccelerationDeltasMultiDof; num_dof of btScalar would cover all bodies
- btSpatialMotionVector result; //holds results of the SolveImatrix op; it is a spatial motion vector (accel)
- btScalar Y_minus_hT_a[6]; //Y - h^{T} * a; it's dofx1 for each body so a single 6x1 temp is enough
- btSpatialForceVector spatForceVecTemps[6]; //6 temporary spatial force vectors
- btSpatialTransformationMatrix fromParent; //spatial transform from parent to child
- btSymmetricSpatialDyad dyadTemp; //inertia matrix temp
+ //aux variables
+ btSpatialMotionVector spatJointVel; //spatial velocity due to the joint motion (i.e. without predecessors' influence)
+ btScalar D[36]; //"D" matrix; it's dofxdof for each body so asingle 6x6 D matrix will do
+ btScalar invD_times_Y[6]; //D^{-1} * Y [dofxdof x dofx1 = dofx1] <=> D^{-1} * u; better moved to buffers since it is recalced in calcAccelerationDeltasMultiDof; num_dof of btScalar would cover all bodies
+ btSpatialMotionVector result; //holds results of the SolveImatrix op; it is a spatial motion vector (accel)
+ btScalar Y_minus_hT_a[6]; //Y - h^{T} * a; it's dofx1 for each body so a single 6x1 temp is enough
+ btSpatialForceVector spatForceVecTemps[6]; //6 temporary spatial force vectors
+ btSpatialTransformationMatrix fromParent; //spatial transform from parent to child
+ btSymmetricSpatialDyad dyadTemp; //inertia matrix temp
btSpatialTransformationMatrix fromWorld;
fromWorld.m_trnVec.setZero();
/////////////////
- // ptr to the joint accel part of the output
- btScalar * joint_accel = output + 6;
+ // ptr to the joint accel part of the output
+ btScalar *joint_accel = output + 6;
- // Start of the algorithm proper.
-
- // First 'upward' loop.
- // Combines CompTreeLinkVelocities and InitTreeLinks from Mirtich.
+ // Start of the algorithm proper.
+
+ // First 'upward' loop.
+ // Combines CompTreeLinkVelocities and InitTreeLinks from Mirtich.
- rot_from_parent[0] = btMatrix3x3(m_baseQuat); //m_baseQuat assumed to be alias!?
+ rot_from_parent[0] = btMatrix3x3(m_baseQuat); //m_baseQuat assumed to be alias!?
//create the vector of spatial velocity of the base by transforming global-coor linear and angular velocities into base-local coordinates
spatVel[0].setVector(rot_from_parent[0] * base_omega, rot_from_parent[0] * base_vel);
- if (m_fixedBase)
- {
+ if (m_fixedBase)
+ {
zeroAccSpatFrc[0].setZero();
- }
- else
+ }
+ else
{
- const btVector3& baseForce = isConstraintPass? m_baseConstraintForce : m_baseForce;
- const btVector3& baseTorque = isConstraintPass? m_baseConstraintTorque : m_baseTorque;
- //external forces
- zeroAccSpatFrc[0].setVector(-(rot_from_parent[0] * baseTorque), -(rot_from_parent[0] * baseForce));
+ const btVector3 &baseForce = isConstraintPass ? m_baseConstraintForce : m_baseForce;
+ const btVector3 &baseTorque = isConstraintPass ? m_baseConstraintTorque : m_baseTorque;
+ //external forces
+ zeroAccSpatFrc[0].setVector(-(rot_from_parent[0] * baseTorque), -(rot_from_parent[0] * baseForce));
//adding damping terms (only)
const btScalar linDampMult = 1., angDampMult = 1.;
zeroAccSpatFrc[0].addVector(angDampMult * m_baseInertia * spatVel[0].getAngular() * (DAMPING_K1_ANGULAR + DAMPING_K2_ANGULAR * spatVel[0].getAngular().safeNorm()),
- linDampMult * m_baseMass * spatVel[0].getLinear() * (DAMPING_K1_LINEAR + DAMPING_K2_LINEAR * spatVel[0].getLinear().safeNorm()));
+ linDampMult * m_baseMass * spatVel[0].getLinear() * (DAMPING_K1_LINEAR + DAMPING_K2_LINEAR * spatVel[0].getLinear().safeNorm()));
//
//p += vhat x Ihat vhat - done in a simpler way
@@ -835,67 +850,66 @@ void btMultiBody::computeAccelerationsArticulatedBodyAlgorithmMultiDof(btScalar
zeroAccSpatFrc[0].addAngular(spatVel[0].getAngular().cross(m_baseInertia * spatVel[0].getAngular()));
//
zeroAccSpatFrc[0].addLinear(m_baseMass * spatVel[0].getAngular().cross(spatVel[0].getLinear()));
- }
-
+ }
//init the spatial AB inertia (it has the simple form thanks to choosing local body frames origins at their COMs)
- spatInertia[0].setMatrix( btMatrix3x3(0,0,0,0,0,0,0,0,0),
- //
- btMatrix3x3(m_baseMass, 0, 0,
- 0, m_baseMass, 0,
- 0, 0, m_baseMass),
- //
- btMatrix3x3(m_baseInertia[0], 0, 0,
- 0, m_baseInertia[1], 0,
- 0, 0, m_baseInertia[2])
- );
-
- rot_from_world[0] = rot_from_parent[0];
+ spatInertia[0].setMatrix(btMatrix3x3(0, 0, 0, 0, 0, 0, 0, 0, 0),
+ //
+ btMatrix3x3(m_baseMass, 0, 0,
+ 0, m_baseMass, 0,
+ 0, 0, m_baseMass),
+ //
+ btMatrix3x3(m_baseInertia[0], 0, 0,
+ 0, m_baseInertia[1], 0,
+ 0, 0, m_baseInertia[2]));
+
+ rot_from_world[0] = rot_from_parent[0];
//
- for (int i = 0; i < num_links; ++i) {
- const int parent = m_links[i].m_parent;
- rot_from_parent[i+1] = btMatrix3x3(m_links[i].m_cachedRotParentToThis);
- rot_from_world[i+1] = rot_from_parent[i+1] * rot_from_world[parent+1];
+ for (int i = 0; i < num_links; ++i)
+ {
+ const int parent = m_links[i].m_parent;
+ rot_from_parent[i + 1] = btMatrix3x3(m_links[i].m_cachedRotParentToThis);
+ rot_from_world[i + 1] = rot_from_parent[i + 1] * rot_from_world[parent + 1];
- fromParent.m_rotMat = rot_from_parent[i+1]; fromParent.m_trnVec = m_links[i].m_cachedRVector;
- fromWorld.m_rotMat = rot_from_world[i+1];
- fromParent.transform(spatVel[parent+1], spatVel[i+1]);
+ fromParent.m_rotMat = rot_from_parent[i + 1];
+ fromParent.m_trnVec = m_links[i].m_cachedRVector;
+ fromWorld.m_rotMat = rot_from_world[i + 1];
+ fromParent.transform(spatVel[parent + 1], spatVel[i + 1]);
// now set vhat_i to its true value by doing
- // vhat_i += qidot * shat_i
- if(!m_useGlobalVelocities)
+ // vhat_i += qidot * shat_i
+ if (!m_useGlobalVelocities)
{
spatJointVel.setZero();
- for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+ for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
spatJointVel += m_links[i].m_axes[dof] * getJointVelMultiDof(i)[dof];
// remember vhat_i is really vhat_p(i) (but in current frame) at this point => we need to add velocity across the inboard joint
- spatVel[i+1] += spatJointVel;
+ spatVel[i + 1] += spatJointVel;
//
// vhat_i is vhat_p(i) transformed to local coors + the velocity across the i-th inboard joint
//spatVel[i+1] = fromParent * spatVel[parent+1] + spatJointVel;
-
}
else
{
- fromWorld.transformRotationOnly(m_links[i].m_absFrameTotVelocity, spatVel[i+1]);
+ fromWorld.transformRotationOnly(m_links[i].m_absFrameTotVelocity, spatVel[i + 1]);
fromWorld.transformRotationOnly(m_links[i].m_absFrameLocVelocity, spatJointVel);
}
- // we can now calculate chat_i
- spatVel[i+1].cross(spatJointVel, spatCoriolisAcc[i]);
+ // we can now calculate chat_i
+ spatVel[i + 1].cross(spatJointVel, spatCoriolisAcc[i]);
- // calculate zhat_i^A
+ // calculate zhat_i^A
//
- //external forces
- btVector3 linkAppliedForce = isConstraintPass? m_links[i].m_appliedConstraintForce : m_links[i].m_appliedForce;
- btVector3 linkAppliedTorque =isConstraintPass ? m_links[i].m_appliedConstraintTorque : m_links[i].m_appliedTorque;
-
- zeroAccSpatFrc[i+1].setVector(-(rot_from_world[i+1] * linkAppliedTorque), -(rot_from_world[i+1] * linkAppliedForce ));
-
+ //external forces
+ btVector3 linkAppliedForce = isConstraintPass ? m_links[i].m_appliedConstraintForce : m_links[i].m_appliedForce;
+ btVector3 linkAppliedTorque = isConstraintPass ? m_links[i].m_appliedConstraintTorque : m_links[i].m_appliedTorque;
+
+ zeroAccSpatFrc[i + 1].setVector(-(rot_from_world[i + 1] * linkAppliedTorque), -(rot_from_world[i + 1] * linkAppliedForce));
+
#if 0
{
@@ -913,27 +927,26 @@ void btMultiBody::computeAccelerationsArticulatedBodyAlgorithmMultiDof(btScalar
//
//adding damping terms (only)
btScalar linDampMult = 1., angDampMult = 1.;
- zeroAccSpatFrc[i+1].addVector(angDampMult * m_links[i].m_inertiaLocal * spatVel[i+1].getAngular() * (DAMPING_K1_ANGULAR + DAMPING_K2_ANGULAR * spatVel[i+1].getAngular().safeNorm()),
- linDampMult * m_links[i].m_mass * spatVel[i+1].getLinear() * (DAMPING_K1_LINEAR + DAMPING_K2_LINEAR * spatVel[i+1].getLinear().safeNorm()));
-
- // calculate Ihat_i^A
+ zeroAccSpatFrc[i + 1].addVector(angDampMult * m_links[i].m_inertiaLocal * spatVel[i + 1].getAngular() * (DAMPING_K1_ANGULAR + DAMPING_K2_ANGULAR * spatVel[i + 1].getAngular().safeNorm()),
+ linDampMult * m_links[i].m_mass * spatVel[i + 1].getLinear() * (DAMPING_K1_LINEAR + DAMPING_K2_LINEAR * spatVel[i + 1].getLinear().safeNorm()));
+
+ // calculate Ihat_i^A
//init the spatial AB inertia (it has the simple form thanks to choosing local body frames origins at their COMs)
- spatInertia[i+1].setMatrix( btMatrix3x3(0,0,0,0,0,0,0,0,0),
- //
- btMatrix3x3(m_links[i].m_mass, 0, 0,
- 0, m_links[i].m_mass, 0,
- 0, 0, m_links[i].m_mass),
- //
- btMatrix3x3(m_links[i].m_inertiaLocal[0], 0, 0,
- 0, m_links[i].m_inertiaLocal[1], 0,
- 0, 0, m_links[i].m_inertiaLocal[2])
- );
+ spatInertia[i + 1].setMatrix(btMatrix3x3(0, 0, 0, 0, 0, 0, 0, 0, 0),
+ //
+ btMatrix3x3(m_links[i].m_mass, 0, 0,
+ 0, m_links[i].m_mass, 0,
+ 0, 0, m_links[i].m_mass),
+ //
+ btMatrix3x3(m_links[i].m_inertiaLocal[0], 0, 0,
+ 0, m_links[i].m_inertiaLocal[1], 0,
+ 0, 0, m_links[i].m_inertiaLocal[2]));
//
//p += vhat x Ihat vhat - done in a simpler way
- if(m_useGyroTerm)
- zeroAccSpatFrc[i+1].addAngular(spatVel[i+1].getAngular().cross(m_links[i].m_inertiaLocal * spatVel[i+1].getAngular()));
- //
- zeroAccSpatFrc[i+1].addLinear(m_links[i].m_mass * spatVel[i+1].getAngular().cross(spatVel[i+1].getLinear()));
+ if (m_useGyroTerm)
+ zeroAccSpatFrc[i + 1].addAngular(spatVel[i + 1].getAngular().cross(m_links[i].m_inertiaLocal * spatVel[i + 1].getAngular()));
+ //
+ zeroAccSpatFrc[i + 1].addLinear(m_links[i].m_mass * spatVel[i + 1].getAngular().cross(spatVel[i + 1].getLinear()));
//btVector3 temp = m_links[i].m_mass * spatVel[i+1].getAngular().cross(spatVel[i+1].getLinear());
////clamp parent's omega
//btScalar parOmegaMod = temp.length();
@@ -944,52 +957,49 @@ void btMultiBody::computeAccelerationsArticulatedBodyAlgorithmMultiDof(btScalar
//printf("|zeroAccSpatFrc[%d]| = %.4f\n", i+1, temp.length());
//temp = spatCoriolisAcc[i].getLinear();
//printf("|spatCoriolisAcc[%d]| = %.4f\n", i+1, temp.length());
-
-
//printf("w[%d] = [%.4f %.4f %.4f]\n", i, vel_top_angular[i+1].x(), vel_top_angular[i+1].y(), vel_top_angular[i+1].z());
- //printf("v[%d] = [%.4f %.4f %.4f]\n", i, vel_bottom_linear[i+1].x(), vel_bottom_linear[i+1].y(), vel_bottom_linear[i+1].z());
+ //printf("v[%d] = [%.4f %.4f %.4f]\n", i, vel_bottom_linear[i+1].x(), vel_bottom_linear[i+1].y(), vel_bottom_linear[i+1].z());
//printf("c[%d] = [%.4f %.4f %.4f]\n", i, coriolis_bottom_linear[i].x(), coriolis_bottom_linear[i].y(), coriolis_bottom_linear[i].z());
- }
-
- // 'Downward' loop.
- // (part of TreeForwardDynamics in Mirtich.)
- for (int i = num_links - 1; i >= 0; --i)
+ }
+
+ // 'Downward' loop.
+ // (part of TreeForwardDynamics in Mirtich.)
+ for (int i = num_links - 1; i >= 0; --i)
{
const int parent = m_links[i].m_parent;
- fromParent.m_rotMat = rot_from_parent[i+1]; fromParent.m_trnVec = m_links[i].m_cachedRVector;
+ fromParent.m_rotMat = rot_from_parent[i + 1];
+ fromParent.m_trnVec = m_links[i].m_cachedRVector;
- for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+ for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
{
btSpatialForceVector &hDof = h[m_links[i].m_dofOffset + dof];
//
- hDof = spatInertia[i+1] * m_links[i].m_axes[dof];
+ hDof = spatInertia[i + 1] * m_links[i].m_axes[dof];
//
- Y[m_links[i].m_dofOffset + dof] = m_links[i].m_jointTorque[dof]
- - m_links[i].m_axes[dof].dot(zeroAccSpatFrc[i+1])
- - spatCoriolisAcc[i].dot(hDof);
-
+ Y[m_links[i].m_dofOffset + dof] = m_links[i].m_jointTorque[dof] - m_links[i].m_axes[dof].dot(zeroAccSpatFrc[i + 1]) - spatCoriolisAcc[i].dot(hDof);
}
- for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
- {
+ for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+ {
btScalar *D_row = &D[dof * m_links[i].m_dofCount];
- for(int dof2 = 0; dof2 < m_links[i].m_dofCount; ++dof2)
+ for (int dof2 = 0; dof2 < m_links[i].m_dofCount; ++dof2)
{
const btSpatialForceVector &hDof2 = h[m_links[i].m_dofOffset + dof2];
D_row[dof2] = m_links[i].m_axes[dof].dot(hDof2);
}
}
- btScalar *invDi = &invD[m_links[i].m_dofOffset*m_links[i].m_dofOffset];
- switch(m_links[i].m_jointType)
+ btScalar *invDi = &invD[m_links[i].m_dofOffset * m_links[i].m_dofOffset];
+ switch (m_links[i].m_jointType)
{
case btMultibodyLink::ePrismatic:
case btMultibodyLink::eRevolute:
{
- if (D[0]>=SIMD_EPSILON)
+ if (D[0] >= SIMD_EPSILON)
{
invDi[0] = 1.0f / D[0];
- } else
+ }
+ else
{
invDi[0] = 0;
}
@@ -1002,10 +1012,10 @@ void btMultiBody::computeAccelerationsArticulatedBodyAlgorithmMultiDof(btScalar
const btMatrix3x3 invD3x3(D3x3.inverse());
//unroll the loop?
- for(int row = 0; row < 3; ++row)
+ for (int row = 0; row < 3; ++row)
{
- for(int col = 0; col < 3; ++col)
- {
+ for (int col = 0; col < 3; ++col)
+ {
invDi[row * 3 + col] = invD3x3[row][col];
}
}
@@ -1014,86 +1024,82 @@ void btMultiBody::computeAccelerationsArticulatedBodyAlgorithmMultiDof(btScalar
}
default:
{
-
}
}
//determine h*D^{-1}
- for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+ for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
{
spatForceVecTemps[dof].setZero();
- for(int dof2 = 0; dof2 < m_links[i].m_dofCount; ++dof2)
- {
+ for (int dof2 = 0; dof2 < m_links[i].m_dofCount; ++dof2)
+ {
const btSpatialForceVector &hDof2 = h[m_links[i].m_dofOffset + dof2];
- //
+ //
spatForceVecTemps[dof] += hDof2 * invDi[dof2 * m_links[i].m_dofCount + dof];
}
}
- dyadTemp = spatInertia[i+1];
+ dyadTemp = spatInertia[i + 1];
//determine (h*D^{-1}) * h^{T}
- for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
- {
+ for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+ {
const btSpatialForceVector &hDof = h[m_links[i].m_dofOffset + dof];
//
dyadTemp -= symmetricSpatialOuterProduct(hDof, spatForceVecTemps[dof]);
}
- fromParent.transformInverse(dyadTemp, spatInertia[parent+1], btSpatialTransformationMatrix::Add);
-
- for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+ fromParent.transformInverse(dyadTemp, spatInertia[parent + 1], btSpatialTransformationMatrix::Add);
+
+ for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
{
invD_times_Y[dof] = 0.f;
- for(int dof2 = 0; dof2 < m_links[i].m_dofCount; ++dof2)
+ for (int dof2 = 0; dof2 < m_links[i].m_dofCount; ++dof2)
{
- invD_times_Y[dof] += invDi[dof * m_links[i].m_dofCount + dof2] * Y[m_links[i].m_dofOffset + dof2];
- }
+ invD_times_Y[dof] += invDi[dof * m_links[i].m_dofCount + dof2] * Y[m_links[i].m_dofOffset + dof2];
+ }
}
-
- spatForceVecTemps[0] = zeroAccSpatFrc[i+1] + spatInertia[i+1] * spatCoriolisAcc[i];
- for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
- {
+ spatForceVecTemps[0] = zeroAccSpatFrc[i + 1] + spatInertia[i + 1] * spatCoriolisAcc[i];
+
+ for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+ {
const btSpatialForceVector &hDof = h[m_links[i].m_dofOffset + dof];
//
- spatForceVecTemps[0] += hDof * invD_times_Y[dof];
+ spatForceVecTemps[0] += hDof * invD_times_Y[dof];
}
-
+
fromParent.transformInverse(spatForceVecTemps[0], spatForceVecTemps[1]);
-
- zeroAccSpatFrc[parent+1] += spatForceVecTemps[1];
- }
+ zeroAccSpatFrc[parent + 1] += spatForceVecTemps[1];
+ }
- // Second 'upward' loop
- // (part of TreeForwardDynamics in Mirtich)
+ // Second 'upward' loop
+ // (part of TreeForwardDynamics in Mirtich)
- if (m_fixedBase)
+ if (m_fixedBase)
{
- spatAcc[0].setZero();
- }
- else
+ spatAcc[0].setZero();
+ }
+ else
{
- if (num_links > 0)
+ if (num_links > 0)
{
m_cachedInertiaValid = true;
m_cachedInertiaTopLeft = spatInertia[0].m_topLeftMat;
m_cachedInertiaTopRight = spatInertia[0].m_topRightMat;
m_cachedInertiaLowerLeft = spatInertia[0].m_bottomLeftMat;
- m_cachedInertiaLowerRight= spatInertia[0].m_topLeftMat.transpose();
+ m_cachedInertiaLowerRight = spatInertia[0].m_topLeftMat.transpose();
+ }
- }
-
solveImatrix(zeroAccSpatFrc[0], result);
spatAcc[0] = -result;
- }
-
-
- // now do the loop over the m_links
- for (int i = 0; i < num_links; ++i)
+ }
+
+ // now do the loop over the m_links
+ for (int i = 0; i < num_links; ++i)
{
// qdd = D^{-1} * (Y - h^{T}*apar) = (S^{T}*I*S)^{-1} * (tau - S^{T}*I*cor - S^{T}*zeroAccFrc - S^{T}*I*apar)
// a = apar + cor + Sqdd
@@ -1101,73 +1107,73 @@ void btMultiBody::computeAccelerationsArticulatedBodyAlgorithmMultiDof(btScalar
// qdd = D^{-1} * (Y - h^{T}*(apar+cor))
// a = apar + Sqdd
- const int parent = m_links[i].m_parent;
- fromParent.m_rotMat = rot_from_parent[i+1]; fromParent.m_trnVec = m_links[i].m_cachedRVector;
+ const int parent = m_links[i].m_parent;
+ fromParent.m_rotMat = rot_from_parent[i + 1];
+ fromParent.m_trnVec = m_links[i].m_cachedRVector;
+
+ fromParent.transform(spatAcc[parent + 1], spatAcc[i + 1]);
- fromParent.transform(spatAcc[parent+1], spatAcc[i+1]);
-
- for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+ for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
{
const btSpatialForceVector &hDof = h[m_links[i].m_dofOffset + dof];
- //
- Y_minus_hT_a[dof] = Y[m_links[i].m_dofOffset + dof] - spatAcc[i+1].dot(hDof);
+ //
+ Y_minus_hT_a[dof] = Y[m_links[i].m_dofOffset + dof] - spatAcc[i + 1].dot(hDof);
}
- btScalar *invDi = &invD[m_links[i].m_dofOffset*m_links[i].m_dofOffset];
+ btScalar *invDi = &invD[m_links[i].m_dofOffset * m_links[i].m_dofOffset];
//D^{-1} * (Y - h^{T}*apar)
mulMatrix(invDi, Y_minus_hT_a, m_links[i].m_dofCount, m_links[i].m_dofCount, m_links[i].m_dofCount, 1, &joint_accel[m_links[i].m_dofOffset]);
- spatAcc[i+1] += spatCoriolisAcc[i];
+ spatAcc[i + 1] += spatCoriolisAcc[i];
- for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
- spatAcc[i+1] += m_links[i].m_axes[dof] * joint_accel[m_links[i].m_dofOffset + dof];
+ for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+ spatAcc[i + 1] += m_links[i].m_axes[dof] * joint_accel[m_links[i].m_dofOffset + dof];
if (m_links[i].m_jointFeedback)
{
m_internalNeedsJointFeedback = true;
- btVector3 angularBotVec = (spatInertia[i+1]*spatAcc[i+1]+zeroAccSpatFrc[i+1]).m_bottomVec;
- btVector3 linearTopVec = (spatInertia[i+1]*spatAcc[i+1]+zeroAccSpatFrc[i+1]).m_topVec;
+ btVector3 angularBotVec = (spatInertia[i + 1] * spatAcc[i + 1] + zeroAccSpatFrc[i + 1]).m_bottomVec;
+ btVector3 linearTopVec = (spatInertia[i + 1] * spatAcc[i + 1] + zeroAccSpatFrc[i + 1]).m_topVec;
- if (gJointFeedbackInJointFrame)
+ if (jointFeedbackInJointFrame)
{
//shift the reaction forces to the joint frame
//linear (force) component is the same
//shift the angular (torque, moment) component using the relative position, m_links[i].m_dVector
- angularBotVec = angularBotVec - linearTopVec.cross(m_links[i].m_dVector);
+ angularBotVec = angularBotVec - linearTopVec.cross(m_links[i].m_dVector);
}
-
- if (gJointFeedbackInWorldSpace)
+ if (jointFeedbackInWorldSpace)
{
if (isConstraintPass)
{
- m_links[i].m_jointFeedback->m_reactionForces.m_bottomVec += m_links[i].m_cachedWorldTransform.getBasis()*angularBotVec;
- m_links[i].m_jointFeedback->m_reactionForces.m_topVec += m_links[i].m_cachedWorldTransform.getBasis()*linearTopVec;
- } else
+ m_links[i].m_jointFeedback->m_reactionForces.m_bottomVec += m_links[i].m_cachedWorldTransform.getBasis() * angularBotVec;
+ m_links[i].m_jointFeedback->m_reactionForces.m_topVec += m_links[i].m_cachedWorldTransform.getBasis() * linearTopVec;
+ }
+ else
{
- m_links[i].m_jointFeedback->m_reactionForces.m_bottomVec = m_links[i].m_cachedWorldTransform.getBasis()*angularBotVec;
- m_links[i].m_jointFeedback->m_reactionForces.m_topVec = m_links[i].m_cachedWorldTransform.getBasis()*linearTopVec;
+ m_links[i].m_jointFeedback->m_reactionForces.m_bottomVec = m_links[i].m_cachedWorldTransform.getBasis() * angularBotVec;
+ m_links[i].m_jointFeedback->m_reactionForces.m_topVec = m_links[i].m_cachedWorldTransform.getBasis() * linearTopVec;
}
- } else
+ }
+ else
{
if (isConstraintPass)
{
- m_links[i].m_jointFeedback->m_reactionForces.m_bottomVec += angularBotVec;
- m_links[i].m_jointFeedback->m_reactionForces.m_topVec += linearTopVec;
-
+ m_links[i].m_jointFeedback->m_reactionForces.m_bottomVec += angularBotVec;
+ m_links[i].m_jointFeedback->m_reactionForces.m_topVec += linearTopVec;
}
else
{
- m_links[i].m_jointFeedback->m_reactionForces.m_bottomVec = angularBotVec;
- m_links[i].m_jointFeedback->m_reactionForces.m_topVec = linearTopVec;
- }
- }
+ m_links[i].m_jointFeedback->m_reactionForces.m_bottomVec = angularBotVec;
+ m_links[i].m_jointFeedback->m_reactionForces.m_topVec = linearTopVec;
+ }
+ }
+ }
}
- }
-
- // transform base accelerations back to the world frame.
+ // transform base accelerations back to the world frame.
const btVector3 omegadot_out = rot_from_parent[0].transpose() * spatAcc[0].getAngular();
output[0] = omegadot_out[0];
output[1] = omegadot_out[1];
@@ -1196,26 +1202,25 @@ void btMultiBody::computeAccelerationsArticulatedBodyAlgorithmMultiDof(btScalar
//printf("]\n");
/////////////////
- // Final step: add the accelerations (times dt) to the velocities.
+ // Final step: add the accelerations (times dt) to the velocities.
if (!isConstraintPass)
{
- if(dt > 0.)
- applyDeltaVeeMultiDof(output, dt);
-
+ if (dt > 0.)
+ applyDeltaVeeMultiDof(output, dt);
}
/////
//btScalar angularThres = 1;
- //btScalar maxAngVel = 0.;
+ //btScalar maxAngVel = 0.;
//bool scaleDown = 1.;
//for(int link = 0; link < m_links.size(); ++link)
- //{
+ //{
// if(spatVel[link+1].getAngular().length() > maxAngVel)
// {
// maxAngVel = spatVel[link+1].getAngular().length();
// scaleDown = angularThres / spatVel[link+1].getAngular().length();
// break;
- // }
+ // }
//}
//if(scaleDown != 1.)
@@ -1232,77 +1237,77 @@ void btMultiBody::computeAccelerationsArticulatedBodyAlgorithmMultiDof(btScalar
/////
/////////////////////
- if(m_useGlobalVelocities)
+ if (m_useGlobalVelocities)
{
- for (int i = 0; i < num_links; ++i)
+ for (int i = 0; i < num_links; ++i)
{
const int parent = m_links[i].m_parent;
//rot_from_parent[i+1] = btMatrix3x3(m_links[i].m_cachedRotParentToThis); /// <- done
//rot_from_world[i+1] = rot_from_parent[i+1] * rot_from_world[parent+1]; /// <- done
-
- fromParent.m_rotMat = rot_from_parent[i+1]; fromParent.m_trnVec = m_links[i].m_cachedRVector;
- fromWorld.m_rotMat = rot_from_world[i+1];
-
- // vhat_i = i_xhat_p(i) * vhat_p(i)
- fromParent.transform(spatVel[parent+1], spatVel[i+1]);
+
+ fromParent.m_rotMat = rot_from_parent[i + 1];
+ fromParent.m_trnVec = m_links[i].m_cachedRVector;
+ fromWorld.m_rotMat = rot_from_world[i + 1];
+
+ // vhat_i = i_xhat_p(i) * vhat_p(i)
+ fromParent.transform(spatVel[parent + 1], spatVel[i + 1]);
//nice alternative below (using operator *) but it generates temps
/////////////////////////////////////////////////////////////
// now set vhat_i to its true value by doing
- // vhat_i += qidot * shat_i
+ // vhat_i += qidot * shat_i
spatJointVel.setZero();
- for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+ for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
spatJointVel += m_links[i].m_axes[dof] * getJointVelMultiDof(i)[dof];
-
- // remember vhat_i is really vhat_p(i) (but in current frame) at this point => we need to add velocity across the inboard joint
- spatVel[i+1] += spatJointVel;
+ // remember vhat_i is really vhat_p(i) (but in current frame) at this point => we need to add velocity across the inboard joint
+ spatVel[i + 1] += spatJointVel;
- fromWorld.transformInverseRotationOnly(spatVel[i+1], m_links[i].m_absFrameTotVelocity);
+ fromWorld.transformInverseRotationOnly(spatVel[i + 1], m_links[i].m_absFrameTotVelocity);
fromWorld.transformInverseRotationOnly(spatJointVel, m_links[i].m_absFrameLocVelocity);
}
}
-
}
-
-
-void btMultiBody::solveImatrix(const btVector3& rhs_top, const btVector3& rhs_bot, btScalar result[6]) const
+void btMultiBody::solveImatrix(const btVector3 &rhs_top, const btVector3 &rhs_bot, btScalar result[6]) const
{
int num_links = getNumLinks();
///solve I * x = rhs, so the result = invI * rhs
- if (num_links == 0)
+ if (num_links == 0)
{
// in the case of 0 m_links (i.e. a plain rigid body, not a multibody) rhs * invI is easier
-
- if ((m_baseInertia[0] >= SIMD_EPSILON) && (m_baseInertia[1] >= SIMD_EPSILON) && (m_baseInertia[2] >= SIMD_EPSILON))
- {
- result[0] = rhs_bot[0] / m_baseInertia[0];
- result[1] = rhs_bot[1] / m_baseInertia[1];
- result[2] = rhs_bot[2] / m_baseInertia[2];
- } else
- {
- result[0] = 0;
- result[1] = 0;
- result[2] = 0;
- }
- if (m_baseMass>=SIMD_EPSILON)
- {
- result[3] = rhs_top[0] / m_baseMass;
- result[4] = rhs_top[1] / m_baseMass;
- result[5] = rhs_top[2] / m_baseMass;
- } else
- {
- result[3] = 0;
- result[4] = 0;
- result[5] = 0;
+
+ if ((m_baseInertia[0] >= SIMD_EPSILON) && (m_baseInertia[1] >= SIMD_EPSILON) && (m_baseInertia[2] >= SIMD_EPSILON))
+ {
+ result[0] = rhs_bot[0] / m_baseInertia[0];
+ result[1] = rhs_bot[1] / m_baseInertia[1];
+ result[2] = rhs_bot[2] / m_baseInertia[2];
+ }
+ else
+ {
+ result[0] = 0;
+ result[1] = 0;
+ result[2] = 0;
+ }
+ if (m_baseMass >= SIMD_EPSILON)
+ {
+ result[3] = rhs_top[0] / m_baseMass;
+ result[4] = rhs_top[1] / m_baseMass;
+ result[5] = rhs_top[2] / m_baseMass;
+ }
+ else
+ {
+ result[3] = 0;
+ result[4] = 0;
+ result[5] = 0;
+ }
}
- } else
+ else
{
if (!m_cachedInertiaValid)
{
- for (int i=0;i<6;i++)
+ for (int i = 0; i < 6; i++)
{
result[i] = 0.f;
}
@@ -1310,94 +1315,95 @@ void btMultiBody::solveImatrix(const btVector3& rhs_top, const btVector3& rhs_bo
}
/// Special routine for calculating the inverse of a spatial inertia matrix
///the 6x6 matrix is stored as 4 blocks of 3x3 matrices
- btMatrix3x3 Binv = m_cachedInertiaTopRight.inverse()*-1.f;
+ btMatrix3x3 Binv = m_cachedInertiaTopRight.inverse() * -1.f;
btMatrix3x3 tmp = m_cachedInertiaLowerRight * Binv;
btMatrix3x3 invIupper_right = (tmp * m_cachedInertiaTopLeft + m_cachedInertiaLowerLeft).inverse();
tmp = invIupper_right * m_cachedInertiaLowerRight;
btMatrix3x3 invI_upper_left = (tmp * Binv);
btMatrix3x3 invI_lower_right = (invI_upper_left).transpose();
- tmp = m_cachedInertiaTopLeft * invI_upper_left;
- tmp[0][0]-= 1.0;
- tmp[1][1]-= 1.0;
- tmp[2][2]-= 1.0;
+ tmp = m_cachedInertiaTopLeft * invI_upper_left;
+ tmp[0][0] -= 1.0;
+ tmp[1][1] -= 1.0;
+ tmp[2][2] -= 1.0;
btMatrix3x3 invI_lower_left = (Binv * tmp);
//multiply result = invI * rhs
{
- btVector3 vtop = invI_upper_left*rhs_top;
- btVector3 tmp;
- tmp = invIupper_right * rhs_bot;
- vtop += tmp;
- btVector3 vbot = invI_lower_left*rhs_top;
- tmp = invI_lower_right * rhs_bot;
- vbot += tmp;
- result[0] = vtop[0];
- result[1] = vtop[1];
- result[2] = vtop[2];
- result[3] = vbot[0];
- result[4] = vbot[1];
- result[5] = vbot[2];
+ btVector3 vtop = invI_upper_left * rhs_top;
+ btVector3 tmp;
+ tmp = invIupper_right * rhs_bot;
+ vtop += tmp;
+ btVector3 vbot = invI_lower_left * rhs_top;
+ tmp = invI_lower_right * rhs_bot;
+ vbot += tmp;
+ result[0] = vtop[0];
+ result[1] = vtop[1];
+ result[2] = vtop[2];
+ result[3] = vbot[0];
+ result[4] = vbot[1];
+ result[5] = vbot[2];
}
-
- }
+ }
}
void btMultiBody::solveImatrix(const btSpatialForceVector &rhs, btSpatialMotionVector &result) const
{
int num_links = getNumLinks();
///solve I * x = rhs, so the result = invI * rhs
- if (num_links == 0)
+ if (num_links == 0)
{
// in the case of 0 m_links (i.e. a plain rigid body, not a multibody) rhs * invI is easier
if ((m_baseInertia[0] >= SIMD_EPSILON) && (m_baseInertia[1] >= SIMD_EPSILON) && (m_baseInertia[2] >= SIMD_EPSILON))
- {
- result.setAngular(rhs.getAngular() / m_baseInertia);
- } else
- {
- result.setAngular(btVector3(0,0,0));
- }
- if (m_baseMass>=SIMD_EPSILON)
- {
- result.setLinear(rhs.getLinear() / m_baseMass);
- } else
- {
- result.setLinear(btVector3(0,0,0));
- }
- } else
+ {
+ result.setAngular(rhs.getAngular() / m_baseInertia);
+ }
+ else
+ {
+ result.setAngular(btVector3(0, 0, 0));
+ }
+ if (m_baseMass >= SIMD_EPSILON)
+ {
+ result.setLinear(rhs.getLinear() / m_baseMass);
+ }
+ else
+ {
+ result.setLinear(btVector3(0, 0, 0));
+ }
+ }
+ else
{
/// Special routine for calculating the inverse of a spatial inertia matrix
///the 6x6 matrix is stored as 4 blocks of 3x3 matrices
if (!m_cachedInertiaValid)
{
- result.setLinear(btVector3(0,0,0));
- result.setAngular(btVector3(0,0,0));
- result.setVector(btVector3(0,0,0),btVector3(0,0,0));
+ result.setLinear(btVector3(0, 0, 0));
+ result.setAngular(btVector3(0, 0, 0));
+ result.setVector(btVector3(0, 0, 0), btVector3(0, 0, 0));
return;
}
- btMatrix3x3 Binv = m_cachedInertiaTopRight.inverse()*-1.f;
+ btMatrix3x3 Binv = m_cachedInertiaTopRight.inverse() * -1.f;
btMatrix3x3 tmp = m_cachedInertiaLowerRight * Binv;
btMatrix3x3 invIupper_right = (tmp * m_cachedInertiaTopLeft + m_cachedInertiaLowerLeft).inverse();
tmp = invIupper_right * m_cachedInertiaLowerRight;
btMatrix3x3 invI_upper_left = (tmp * Binv);
btMatrix3x3 invI_lower_right = (invI_upper_left).transpose();
- tmp = m_cachedInertiaTopLeft * invI_upper_left;
- tmp[0][0]-= 1.0;
- tmp[1][1]-= 1.0;
- tmp[2][2]-= 1.0;
+ tmp = m_cachedInertiaTopLeft * invI_upper_left;
+ tmp[0][0] -= 1.0;
+ tmp[1][1] -= 1.0;
+ tmp[2][2] -= 1.0;
btMatrix3x3 invI_lower_left = (Binv * tmp);
//multiply result = invI * rhs
{
- btVector3 vtop = invI_upper_left*rhs.getLinear();
- btVector3 tmp;
- tmp = invIupper_right * rhs.getAngular();
- vtop += tmp;
- btVector3 vbot = invI_lower_left*rhs.getLinear();
- tmp = invI_lower_right * rhs.getAngular();
- vbot += tmp;
- result.setVector(vtop, vbot);
+ btVector3 vtop = invI_upper_left * rhs.getLinear();
+ btVector3 tmp;
+ tmp = invIupper_right * rhs.getAngular();
+ vtop += tmp;
+ btVector3 vbot = invI_lower_left * rhs.getLinear();
+ tmp = invI_lower_right * rhs.getAngular();
+ vbot += tmp;
+ result.setVector(vtop, vbot);
}
-
- }
+ }
}
void btMultiBody::mulMatrix(btScalar *pA, btScalar *pB, int rowsA, int colsA, int rowsB, int colsB, btScalar *pC) const
@@ -1416,155 +1422,152 @@ void btMultiBody::mulMatrix(btScalar *pA, btScalar *pB, int rowsA, int colsA, in
}
void btMultiBody::calcAccelerationDeltasMultiDof(const btScalar *force, btScalar *output,
- btAlignedObjectArray<btScalar> &scratch_r, btAlignedObjectArray<btVector3> &scratch_v) const
+ btAlignedObjectArray<btScalar> &scratch_r, btAlignedObjectArray<btVector3> &scratch_v) const
{
- // Temporary matrices/vectors -- use scratch space from caller
- // so that we don't have to keep reallocating every frame
+ // Temporary matrices/vectors -- use scratch space from caller
+ // so that we don't have to keep reallocating every frame
-
- int num_links = getNumLinks();
- scratch_r.resize(m_dofCount);
- scratch_v.resize(4*num_links + 4);
+ int num_links = getNumLinks();
+ scratch_r.resize(m_dofCount);
+ scratch_v.resize(4 * num_links + 4);
- btScalar * r_ptr = m_dofCount ? &scratch_r[0] : 0;
- btVector3 * v_ptr = &scratch_v[0];
+ btScalar *r_ptr = m_dofCount ? &scratch_r[0] : 0;
+ btVector3 *v_ptr = &scratch_v[0];
- // zhat_i^A (scratch space)
- btSpatialForceVector * zeroAccSpatFrc = (btSpatialForceVector *)v_ptr;
+ // zhat_i^A (scratch space)
+ btSpatialForceVector *zeroAccSpatFrc = (btSpatialForceVector *)v_ptr;
v_ptr += num_links * 2 + 2;
- // rot_from_parent (cached from calcAccelerations)
- const btMatrix3x3 * rot_from_parent = &m_matrixBuf[0];
+ // rot_from_parent (cached from calcAccelerations)
+ const btMatrix3x3 *rot_from_parent = &m_matrixBuf[0];
- // hhat (cached), accel (scratch)
- // hhat is NOT stored for the base (but ahat is)
- const btSpatialForceVector * h = (btSpatialForceVector *)(m_dofCount > 0 ? &m_vectorBuf[0] : 0);
- btSpatialMotionVector * spatAcc = (btSpatialMotionVector *)v_ptr;
+ // hhat (cached), accel (scratch)
+ // hhat is NOT stored for the base (but ahat is)
+ const btSpatialForceVector *h = (btSpatialForceVector *)(m_dofCount > 0 ? &m_vectorBuf[0] : 0);
+ btSpatialMotionVector *spatAcc = (btSpatialMotionVector *)v_ptr;
v_ptr += num_links * 2 + 2;
- // Y_i (scratch), invD_i (cached)
- const btScalar * invD = m_dofCount > 0 ? &m_realBuf[6 + m_dofCount] : 0;
- btScalar * Y = r_ptr;
+ // Y_i (scratch), invD_i (cached)
+ const btScalar *invD = m_dofCount > 0 ? &m_realBuf[6 + m_dofCount] : 0;
+ btScalar *Y = r_ptr;
////////////////
//aux variables
- btScalar invD_times_Y[6]; //D^{-1} * Y [dofxdof x dofx1 = dofx1] <=> D^{-1} * u; better moved to buffers since it is recalced in calcAccelerationDeltasMultiDof; num_dof of btScalar would cover all bodies
- btSpatialMotionVector result; //holds results of the SolveImatrix op; it is a spatial motion vector (accel)
- btScalar Y_minus_hT_a[6]; //Y - h^{T} * a; it's dofx1 for each body so a single 6x1 temp is enough
- btSpatialForceVector spatForceVecTemps[6]; //6 temporary spatial force vectors
- btSpatialTransformationMatrix fromParent;
+ btScalar invD_times_Y[6]; //D^{-1} * Y [dofxdof x dofx1 = dofx1] <=> D^{-1} * u; better moved to buffers since it is recalced in calcAccelerationDeltasMultiDof; num_dof of btScalar would cover all bodies
+ btSpatialMotionVector result; //holds results of the SolveImatrix op; it is a spatial motion vector (accel)
+ btScalar Y_minus_hT_a[6]; //Y - h^{T} * a; it's dofx1 for each body so a single 6x1 temp is enough
+ btSpatialForceVector spatForceVecTemps[6]; //6 temporary spatial force vectors
+ btSpatialTransformationMatrix fromParent;
/////////////////
- // First 'upward' loop.
- // Combines CompTreeLinkVelocities and InitTreeLinks from Mirtich.
-
+ // First 'upward' loop.
+ // Combines CompTreeLinkVelocities and InitTreeLinks from Mirtich.
+
// Fill in zero_acc
- // -- set to force/torque on the base, zero otherwise
- if (m_fixedBase)
+ // -- set to force/torque on the base, zero otherwise
+ if (m_fixedBase)
+ {
+ zeroAccSpatFrc[0].setZero();
+ }
+ else
{
- zeroAccSpatFrc[0].setZero();
- } else
- {
//test forces
fromParent.m_rotMat = rot_from_parent[0];
- fromParent.transformRotationOnly(btSpatialForceVector(-force[0],-force[1],-force[2], -force[3],-force[4],-force[5]), zeroAccSpatFrc[0]);
- }
- for (int i = 0; i < num_links; ++i)
+ fromParent.transformRotationOnly(btSpatialForceVector(-force[0], -force[1], -force[2], -force[3], -force[4], -force[5]), zeroAccSpatFrc[0]);
+ }
+ for (int i = 0; i < num_links; ++i)
{
- zeroAccSpatFrc[i+1].setZero();
- }
+ zeroAccSpatFrc[i + 1].setZero();
+ }
// 'Downward' loop.
- // (part of TreeForwardDynamics in Mirtich.)
- for (int i = num_links - 1; i >= 0; --i)
+ // (part of TreeForwardDynamics in Mirtich.)
+ for (int i = num_links - 1; i >= 0; --i)
{
const int parent = m_links[i].m_parent;
- fromParent.m_rotMat = rot_from_parent[i+1]; fromParent.m_trnVec = m_links[i].m_cachedRVector;
+ fromParent.m_rotMat = rot_from_parent[i + 1];
+ fromParent.m_trnVec = m_links[i].m_cachedRVector;
- for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+ for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
{
- Y[m_links[i].m_dofOffset + dof] = force[6 + m_links[i].m_dofOffset + dof]
- - m_links[i].m_axes[dof].dot(zeroAccSpatFrc[i+1])
- ;
+ Y[m_links[i].m_dofOffset + dof] = force[6 + m_links[i].m_dofOffset + dof] - m_links[i].m_axes[dof].dot(zeroAccSpatFrc[i + 1]);
}
btVector3 in_top, in_bottom, out_top, out_bottom;
- const btScalar *invDi = &invD[m_links[i].m_dofOffset*m_links[i].m_dofOffset];
-
- for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+ const btScalar *invDi = &invD[m_links[i].m_dofOffset * m_links[i].m_dofOffset];
+
+ for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
{
invD_times_Y[dof] = 0.f;
- for(int dof2 = 0; dof2 < m_links[i].m_dofCount; ++dof2)
+ for (int dof2 = 0; dof2 < m_links[i].m_dofCount; ++dof2)
{
- invD_times_Y[dof] += invDi[dof * m_links[i].m_dofCount + dof2] * Y[m_links[i].m_dofOffset + dof2];
- }
+ invD_times_Y[dof] += invDi[dof * m_links[i].m_dofCount + dof2] * Y[m_links[i].m_dofOffset + dof2];
+ }
}
-
- // Zp += pXi * (Zi + hi*Yi/Di)
- spatForceVecTemps[0] = zeroAccSpatFrc[i+1];
- for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+ // Zp += pXi * (Zi + hi*Yi/Di)
+ spatForceVecTemps[0] = zeroAccSpatFrc[i + 1];
+
+ for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
{
const btSpatialForceVector &hDof = h[m_links[i].m_dofOffset + dof];
//
- spatForceVecTemps[0] += hDof * invD_times_Y[dof];
+ spatForceVecTemps[0] += hDof * invD_times_Y[dof];
}
-
fromParent.transformInverse(spatForceVecTemps[0], spatForceVecTemps[1]);
-
- zeroAccSpatFrc[parent+1] += spatForceVecTemps[1];
- }
-
- // ptr to the joint accel part of the output
- btScalar * joint_accel = output + 6;
+ zeroAccSpatFrc[parent + 1] += spatForceVecTemps[1];
+ }
- // Second 'upward' loop
- // (part of TreeForwardDynamics in Mirtich)
+ // ptr to the joint accel part of the output
+ btScalar *joint_accel = output + 6;
- if (m_fixedBase)
+ // Second 'upward' loop
+ // (part of TreeForwardDynamics in Mirtich)
+
+ if (m_fixedBase)
{
- spatAcc[0].setZero();
- }
- else
+ spatAcc[0].setZero();
+ }
+ else
{
solveImatrix(zeroAccSpatFrc[0], result);
spatAcc[0] = -result;
+ }
- }
-
- // now do the loop over the m_links
- for (int i = 0; i < num_links; ++i)
+ // now do the loop over the m_links
+ for (int i = 0; i < num_links; ++i)
{
- const int parent = m_links[i].m_parent;
- fromParent.m_rotMat = rot_from_parent[i+1]; fromParent.m_trnVec = m_links[i].m_cachedRVector;
+ const int parent = m_links[i].m_parent;
+ fromParent.m_rotMat = rot_from_parent[i + 1];
+ fromParent.m_trnVec = m_links[i].m_cachedRVector;
- fromParent.transform(spatAcc[parent+1], spatAcc[i+1]);
-
- for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+ fromParent.transform(spatAcc[parent + 1], spatAcc[i + 1]);
+
+ for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
{
const btSpatialForceVector &hDof = h[m_links[i].m_dofOffset + dof];
- //
- Y_minus_hT_a[dof] = Y[m_links[i].m_dofOffset + dof] - spatAcc[i+1].dot(hDof);
+ //
+ Y_minus_hT_a[dof] = Y[m_links[i].m_dofOffset + dof] - spatAcc[i + 1].dot(hDof);
}
- const btScalar *invDi = &invD[m_links[i].m_dofOffset*m_links[i].m_dofOffset];
- mulMatrix(const_cast<btScalar*>(invDi), Y_minus_hT_a, m_links[i].m_dofCount, m_links[i].m_dofCount, m_links[i].m_dofCount, 1, &joint_accel[m_links[i].m_dofOffset]);
+ const btScalar *invDi = &invD[m_links[i].m_dofOffset * m_links[i].m_dofOffset];
+ mulMatrix(const_cast<btScalar *>(invDi), Y_minus_hT_a, m_links[i].m_dofCount, m_links[i].m_dofCount, m_links[i].m_dofCount, 1, &joint_accel[m_links[i].m_dofOffset]);
- for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
- spatAcc[i+1] += m_links[i].m_axes[dof] * joint_accel[m_links[i].m_dofOffset + dof];
- }
+ for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+ spatAcc[i + 1] += m_links[i].m_axes[dof] * joint_accel[m_links[i].m_dofOffset + dof];
+ }
- // transform base accelerations back to the world frame.
- btVector3 omegadot_out;
- omegadot_out = rot_from_parent[0].transpose() * spatAcc[0].getAngular();
+ // transform base accelerations back to the world frame.
+ btVector3 omegadot_out;
+ omegadot_out = rot_from_parent[0].transpose() * spatAcc[0].getAngular();
output[0] = omegadot_out[0];
output[1] = omegadot_out[1];
output[2] = omegadot_out[2];
- btVector3 vdot_out;
- vdot_out = rot_from_parent[0].transpose() * spatAcc[0].getLinear();
+ btVector3 vdot_out;
+ vdot_out = rot_from_parent[0].transpose() * spatAcc[0].getLinear();
output[3] = vdot_out[0];
output[4] = vdot_out[1];
output[5] = vdot_out[2];
@@ -1577,19 +1580,16 @@ void btMultiBody::calcAccelerationDeltasMultiDof(const btScalar *force, btScalar
/////////////////
}
-
-
-
void btMultiBody::stepPositionsMultiDof(btScalar dt, btScalar *pq, btScalar *pqd)
-{
+{
int num_links = getNumLinks();
- // step position by adding dt * velocity
- //btVector3 v = getBaseVel();
- //m_basePos += dt * v;
+ // step position by adding dt * velocity
+ //btVector3 v = getBaseVel();
+ //m_basePos += dt * v;
//
btScalar *pBasePos = (pq ? &pq[4] : m_basePos);
- btScalar *pBaseVel = (pqd ? &pqd[3] : &m_realBuf[3]); //note: the !pqd case assumes m_realBuf holds with base velocity at 3,4,5 (should be wrapped for safety)
- //
+ btScalar *pBaseVel = (pqd ? &pqd[3] : &m_realBuf[3]); //note: the !pqd case assumes m_realBuf holds with base velocity at 3,4,5 (should be wrapped for safety)
+ //
pBasePos[0] += dt * pBaseVel[0];
pBasePos[1] += dt * pBaseVel[1];
pBasePos[2] += dt * pBaseVel[2];
@@ -1599,92 +1599,98 @@ void btMultiBody::stepPositionsMultiDof(btScalar dt, btScalar *pq, btScalar *pqd
struct
{
//"exponential map" based on btTransformUtil::integrateTransform(..)
- void operator() (const btVector3 &omega, btQuaternion &quat, bool baseBody, btScalar dt)
+ void operator()(const btVector3 &omega, btQuaternion &quat, bool baseBody, btScalar dt)
{
//baseBody => quat is alias and omega is global coor
- //!baseBody => quat is alibi and omega is local coor
-
+ //!baseBody => quat is alibi and omega is local coor
+
btVector3 axis;
btVector3 angvel;
- if(!baseBody)
- angvel = quatRotate(quat, omega); //if quat is not m_baseQuat, it is alibi => ok
+ if (!baseBody)
+ angvel = quatRotate(quat, omega); //if quat is not m_baseQuat, it is alibi => ok
else
angvel = omega;
-
- btScalar fAngle = angvel.length();
+
+ btScalar fAngle = angvel.length();
//limit the angular motion
if (fAngle * dt > ANGULAR_MOTION_THRESHOLD)
{
- fAngle = btScalar(0.5)*SIMD_HALF_PI / dt;
+ fAngle = btScalar(0.5) * SIMD_HALF_PI / dt;
}
- if ( fAngle < btScalar(0.001) )
+ if (fAngle < btScalar(0.001))
{
// use Taylor's expansions of sync function
- axis = angvel*( btScalar(0.5)*dt-(dt*dt*dt)*(btScalar(0.020833333333))*fAngle*fAngle );
+ axis = angvel * (btScalar(0.5) * dt - (dt * dt * dt) * (btScalar(0.020833333333)) * fAngle * fAngle);
}
else
{
// sync(fAngle) = sin(c*fAngle)/t
- axis = angvel*( btSin(btScalar(0.5)*fAngle*dt)/fAngle );
+ axis = angvel * (btSin(btScalar(0.5) * fAngle * dt) / fAngle);
}
-
- if(!baseBody)
- quat = btQuaternion(axis.x(),axis.y(),axis.z(),btCos( fAngle*dt*btScalar(0.5) )) * quat;
- else
- quat = quat * btQuaternion(-axis.x(),-axis.y(),-axis.z(),btCos( fAngle*dt*btScalar(0.5) ));
- //equivalent to: quat = (btQuaternion(axis.x(),axis.y(),axis.z(),btCos( fAngle*dt*btScalar(0.5) )) * quat.inverse()).inverse();
-
+
+ if (!baseBody)
+ quat = btQuaternion(axis.x(), axis.y(), axis.z(), btCos(fAngle * dt * btScalar(0.5))) * quat;
+ else
+ quat = quat * btQuaternion(-axis.x(), -axis.y(), -axis.z(), btCos(fAngle * dt * btScalar(0.5)));
+ //equivalent to: quat = (btQuaternion(axis.x(),axis.y(),axis.z(),btCos( fAngle*dt*btScalar(0.5) )) * quat.inverse()).inverse();
+
quat.normalize();
}
} pQuatUpdateFun;
///////////////////////////////
//pQuatUpdateFun(getBaseOmega(), m_baseQuat, true, dt);
- //
- btScalar *pBaseQuat = pq ? pq : m_baseQuat;
- btScalar *pBaseOmega = pqd ? pqd : &m_realBuf[0]; //note: the !pqd case assumes m_realBuf starts with base omega (should be wrapped for safety)
//
- btQuaternion baseQuat; baseQuat.setValue(pBaseQuat[0], pBaseQuat[1], pBaseQuat[2], pBaseQuat[3]);
- btVector3 baseOmega; baseOmega.setValue(pBaseOmega[0], pBaseOmega[1], pBaseOmega[2]);
+ btScalar *pBaseQuat = pq ? pq : m_baseQuat;
+ btScalar *pBaseOmega = pqd ? pqd : &m_realBuf[0]; //note: the !pqd case assumes m_realBuf starts with base omega (should be wrapped for safety)
+ //
+ btQuaternion baseQuat;
+ baseQuat.setValue(pBaseQuat[0], pBaseQuat[1], pBaseQuat[2], pBaseQuat[3]);
+ btVector3 baseOmega;
+ baseOmega.setValue(pBaseOmega[0], pBaseOmega[1], pBaseOmega[2]);
pQuatUpdateFun(baseOmega, baseQuat, true, dt);
pBaseQuat[0] = baseQuat.x();
pBaseQuat[1] = baseQuat.y();
pBaseQuat[2] = baseQuat.z();
pBaseQuat[3] = baseQuat.w();
-
//printf("pBaseOmega = %.4f %.4f %.4f\n", pBaseOmega->x(), pBaseOmega->y(), pBaseOmega->z());
//printf("pBaseVel = %.4f %.4f %.4f\n", pBaseVel->x(), pBaseVel->y(), pBaseVel->z());
//printf("baseQuat = %.4f %.4f %.4f %.4f\n", pBaseQuat->x(), pBaseQuat->y(), pBaseQuat->z(), pBaseQuat->w());
- if(pq)
+ if (pq)
pq += 7;
- if(pqd)
+ if (pqd)
pqd += 6;
// Finally we can update m_jointPos for each of the m_links
- for (int i = 0; i < num_links; ++i)
+ for (int i = 0; i < num_links; ++i)
{
- btScalar *pJointPos = (pq ? pq : &m_links[i].m_jointPos[0]);
+ btScalar *pJointPos = (pq ? pq : &m_links[i].m_jointPos[0]);
btScalar *pJointVel = (pqd ? pqd : getJointVelMultiDof(i));
- switch(m_links[i].m_jointType)
+ switch (m_links[i].m_jointType)
{
case btMultibodyLink::ePrismatic:
case btMultibodyLink::eRevolute:
{
- btScalar jointVel = pJointVel[0];
+ btScalar jointVel = pJointVel[0];
pJointPos[0] += dt * jointVel;
break;
}
case btMultibodyLink::eSpherical:
{
- btVector3 jointVel; jointVel.setValue(pJointVel[0], pJointVel[1], pJointVel[2]);
- btQuaternion jointOri; jointOri.setValue(pJointPos[0], pJointPos[1], pJointPos[2], pJointPos[3]);
+ btVector3 jointVel;
+ jointVel.setValue(pJointVel[0], pJointVel[1], pJointVel[2]);
+ btQuaternion jointOri;
+ jointOri.setValue(pJointPos[0], pJointPos[1], pJointPos[2], pJointPos[3]);
pQuatUpdateFun(jointVel, jointOri, false, dt);
- pJointPos[0] = jointOri.x(); pJointPos[1] = jointOri.y(); pJointPos[2] = jointOri.z(); pJointPos[3] = jointOri.w();
+ pJointPos[0] = jointOri.x();
+ pJointPos[1] = jointOri.y();
+ pJointPos[2] = jointOri.z();
+ pJointPos[3] = jointOri.w();
break;
}
case btMultibodyLink::ePlanar:
@@ -1701,122 +1707,135 @@ void btMultiBody::stepPositionsMultiDof(btScalar dt, btScalar *pq, btScalar *pqd
default:
{
}
-
}
m_links[i].updateCacheMultiDof(pq);
- if(pq)
+ if (pq)
pq += m_links[i].m_posVarCount;
- if(pqd)
+ if (pqd)
pqd += m_links[i].m_dofCount;
- }
+ }
}
void btMultiBody::fillConstraintJacobianMultiDof(int link,
- const btVector3 &contact_point,
- const btVector3 &normal_ang,
- const btVector3 &normal_lin,
- btScalar *jac,
- btAlignedObjectArray<btScalar> &scratch_r,
- btAlignedObjectArray<btVector3> &scratch_v,
- btAlignedObjectArray<btMatrix3x3> &scratch_m) const
-{
- // temporary space
+ const btVector3 &contact_point,
+ const btVector3 &normal_ang,
+ const btVector3 &normal_lin,
+ btScalar *jac,
+ btAlignedObjectArray<btScalar> &scratch_r1,
+ btAlignedObjectArray<btVector3> &scratch_v,
+ btAlignedObjectArray<btMatrix3x3> &scratch_m) const
+{
+ // temporary space
int num_links = getNumLinks();
int m_dofCount = getNumDofs();
- scratch_v.resize(3*num_links + 3); //(num_links + base) offsets + (num_links + base) normals_lin + (num_links + base) normals_ang
- scratch_m.resize(num_links + 1);
-
- btVector3 * v_ptr = &scratch_v[0];
- btVector3 * p_minus_com_local = v_ptr; v_ptr += num_links + 1;
- btVector3 * n_local_lin = v_ptr; v_ptr += num_links + 1;
- btVector3 * n_local_ang = v_ptr; v_ptr += num_links + 1;
- btAssert(v_ptr - &scratch_v[0] == scratch_v.size());
-
- scratch_r.resize(m_dofCount);
- btScalar * results = m_dofCount > 0 ? &scratch_r[0] : 0;
-
- btMatrix3x3 * rot_from_world = &scratch_m[0];
+ scratch_v.resize(3 * num_links + 3); //(num_links + base) offsets + (num_links + base) normals_lin + (num_links + base) normals_ang
+ scratch_m.resize(num_links + 1);
+
+ btVector3 *v_ptr = &scratch_v[0];
+ btVector3 *p_minus_com_local = v_ptr;
+ v_ptr += num_links + 1;
+ btVector3 *n_local_lin = v_ptr;
+ v_ptr += num_links + 1;
+ btVector3 *n_local_ang = v_ptr;
+ v_ptr += num_links + 1;
+ btAssert(v_ptr - &scratch_v[0] == scratch_v.size());
+
+ //scratch_r.resize(m_dofCount);
+ //btScalar *results = m_dofCount > 0 ? &scratch_r[0] : 0;
+
+ scratch_r1.resize(m_dofCount+num_links);
+ btScalar * results = m_dofCount > 0 ? &scratch_r1[0] : 0;
+ btScalar* links = num_links? &scratch_r1[m_dofCount] : 0;
+ int numLinksChildToRoot=0;
+ int l = link;
+ while (l != -1)
+ {
+ links[numLinksChildToRoot++]=l;
+ l = m_links[l].m_parent;
+ }
+
+ btMatrix3x3 *rot_from_world = &scratch_m[0];
- const btVector3 p_minus_com_world = contact_point - m_basePos;
- const btVector3 &normal_lin_world = normal_lin; //convenience
+ const btVector3 p_minus_com_world = contact_point - m_basePos;
+ const btVector3 &normal_lin_world = normal_lin; //convenience
const btVector3 &normal_ang_world = normal_ang;
- rot_from_world[0] = btMatrix3x3(m_baseQuat);
-
- // omega coeffients first.
- btVector3 omega_coeffs_world;
- omega_coeffs_world = p_minus_com_world.cross(normal_lin_world);
+ rot_from_world[0] = btMatrix3x3(m_baseQuat);
+
+ // omega coeffients first.
+ btVector3 omega_coeffs_world;
+ omega_coeffs_world = p_minus_com_world.cross(normal_lin_world);
jac[0] = omega_coeffs_world[0] + normal_ang_world[0];
jac[1] = omega_coeffs_world[1] + normal_ang_world[1];
jac[2] = omega_coeffs_world[2] + normal_ang_world[2];
- // then v coefficients
- jac[3] = normal_lin_world[0];
- jac[4] = normal_lin_world[1];
- jac[5] = normal_lin_world[2];
+ // then v coefficients
+ jac[3] = normal_lin_world[0];
+ jac[4] = normal_lin_world[1];
+ jac[5] = normal_lin_world[2];
//create link-local versions of p_minus_com and normal
p_minus_com_local[0] = rot_from_world[0] * p_minus_com_world;
- n_local_lin[0] = rot_from_world[0] * normal_lin_world;
+ n_local_lin[0] = rot_from_world[0] * normal_lin_world;
n_local_ang[0] = rot_from_world[0] * normal_ang_world;
- // Set remaining jac values to zero for now.
- for (int i = 6; i < 6 + m_dofCount; ++i)
+ // Set remaining jac values to zero for now.
+ for (int i = 6; i < 6 + m_dofCount; ++i)
{
- jac[i] = 0;
- }
-
- // Qdot coefficients, if necessary.
- if (num_links > 0 && link > -1) {
-
- // TODO: speed this up -- don't calculate for m_links we don't need.
- // (Also, we are making 3 separate calls to this function, for the normal & the 2 friction directions,
- // which is resulting in repeated work being done...)
-
- // calculate required normals & positions in the local frames.
- for (int i = 0; i < num_links; ++i) {
+ jac[i] = 0;
+ }
- // transform to local frame
- const int parent = m_links[i].m_parent;
- const btMatrix3x3 mtx(m_links[i].m_cachedRotParentToThis);
- rot_from_world[i+1] = mtx * rot_from_world[parent+1];
+ // Qdot coefficients, if necessary.
+ if (num_links > 0 && link > -1)
+ {
+ // TODO: (Also, we are making 3 separate calls to this function, for the normal & the 2 friction directions,
+ // which is resulting in repeated work being done...)
+
+ // calculate required normals & positions in the local frames.
+ for (int a = 0; a < numLinksChildToRoot; a++)
+ {
+ int i = links[numLinksChildToRoot-1-a];
+ // transform to local frame
+ const int parent = m_links[i].m_parent;
+ const btMatrix3x3 mtx(m_links[i].m_cachedRotParentToThis);
+ rot_from_world[i + 1] = mtx * rot_from_world[parent + 1];
- n_local_lin[i+1] = mtx * n_local_lin[parent+1];
- n_local_ang[i+1] = mtx * n_local_ang[parent+1];
- p_minus_com_local[i+1] = mtx * p_minus_com_local[parent+1] - m_links[i].m_cachedRVector;
+ n_local_lin[i + 1] = mtx * n_local_lin[parent + 1];
+ n_local_ang[i + 1] = mtx * n_local_ang[parent + 1];
+ p_minus_com_local[i + 1] = mtx * p_minus_com_local[parent + 1] - m_links[i].m_cachedRVector;
// calculate the jacobian entry
- switch(m_links[i].m_jointType)
+ switch (m_links[i].m_jointType)
{
case btMultibodyLink::eRevolute:
{
- results[m_links[i].m_dofOffset] = n_local_lin[i+1].dot(m_links[i].getAxisTop(0).cross(p_minus_com_local[i+1]) + m_links[i].getAxisBottom(0));
- results[m_links[i].m_dofOffset] += n_local_ang[i+1].dot(m_links[i].getAxisTop(0));
+ results[m_links[i].m_dofOffset] = n_local_lin[i + 1].dot(m_links[i].getAxisTop(0).cross(p_minus_com_local[i + 1]) + m_links[i].getAxisBottom(0));
+ results[m_links[i].m_dofOffset] += n_local_ang[i + 1].dot(m_links[i].getAxisTop(0));
break;
}
case btMultibodyLink::ePrismatic:
{
- results[m_links[i].m_dofOffset] = n_local_lin[i+1].dot(m_links[i].getAxisBottom(0));
+ results[m_links[i].m_dofOffset] = n_local_lin[i + 1].dot(m_links[i].getAxisBottom(0));
break;
}
case btMultibodyLink::eSpherical:
{
- results[m_links[i].m_dofOffset + 0] = n_local_lin[i+1].dot(m_links[i].getAxisTop(0).cross(p_minus_com_local[i+1]) + m_links[i].getAxisBottom(0));
- results[m_links[i].m_dofOffset + 1] = n_local_lin[i+1].dot(m_links[i].getAxisTop(1).cross(p_minus_com_local[i+1]) + m_links[i].getAxisBottom(1));
- results[m_links[i].m_dofOffset + 2] = n_local_lin[i+1].dot(m_links[i].getAxisTop(2).cross(p_minus_com_local[i+1]) + m_links[i].getAxisBottom(2));
-
- results[m_links[i].m_dofOffset + 0] += n_local_ang[i+1].dot(m_links[i].getAxisTop(0));
- results[m_links[i].m_dofOffset + 1] += n_local_ang[i+1].dot(m_links[i].getAxisTop(1));
- results[m_links[i].m_dofOffset + 2] += n_local_ang[i+1].dot(m_links[i].getAxisTop(2));
+ results[m_links[i].m_dofOffset + 0] = n_local_lin[i + 1].dot(m_links[i].getAxisTop(0).cross(p_minus_com_local[i + 1]) + m_links[i].getAxisBottom(0));
+ results[m_links[i].m_dofOffset + 1] = n_local_lin[i + 1].dot(m_links[i].getAxisTop(1).cross(p_minus_com_local[i + 1]) + m_links[i].getAxisBottom(1));
+ results[m_links[i].m_dofOffset + 2] = n_local_lin[i + 1].dot(m_links[i].getAxisTop(2).cross(p_minus_com_local[i + 1]) + m_links[i].getAxisBottom(2));
+
+ results[m_links[i].m_dofOffset + 0] += n_local_ang[i + 1].dot(m_links[i].getAxisTop(0));
+ results[m_links[i].m_dofOffset + 1] += n_local_ang[i + 1].dot(m_links[i].getAxisTop(1));
+ results[m_links[i].m_dofOffset + 2] += n_local_ang[i + 1].dot(m_links[i].getAxisTop(2));
break;
}
case btMultibodyLink::ePlanar:
{
- results[m_links[i].m_dofOffset + 0] = n_local_lin[i+1].dot(m_links[i].getAxisTop(0).cross(p_minus_com_local[i+1]));// + m_links[i].getAxisBottom(0));
- results[m_links[i].m_dofOffset + 1] = n_local_lin[i+1].dot(m_links[i].getAxisBottom(1));
- results[m_links[i].m_dofOffset + 2] = n_local_lin[i+1].dot(m_links[i].getAxisBottom(2));
+ results[m_links[i].m_dofOffset + 0] = n_local_lin[i + 1].dot(m_links[i].getAxisTop(0).cross(p_minus_com_local[i + 1])); // + m_links[i].getAxisBottom(0));
+ results[m_links[i].m_dofOffset + 1] = n_local_lin[i + 1].dot(m_links[i].getAxisBottom(1));
+ results[m_links[i].m_dofOffset + 2] = n_local_lin[i + 1].dot(m_links[i].getAxisBottom(2));
break;
}
@@ -1824,269 +1843,260 @@ void btMultiBody::fillConstraintJacobianMultiDof(int link,
{
}
}
-
- }
+ }
- // Now copy through to output.
+ // Now copy through to output.
//printf("jac[%d] = ", link);
- while (link != -1)
+ while (link != -1)
{
- for(int dof = 0; dof < m_links[link].m_dofCount; ++dof)
+ for (int dof = 0; dof < m_links[link].m_dofCount; ++dof)
{
jac[6 + m_links[link].m_dofOffset + dof] = results[m_links[link].m_dofOffset + dof];
//printf("%.2f\t", jac[6 + m_links[link].m_dofOffset + dof]);
}
-
+
link = m_links[link].m_parent;
- }
+ }
//printf("]\n");
- }
+ }
}
-
void btMultiBody::wakeUp()
{
m_sleepTimer = 0;
- m_awake = true;
+ m_awake = true;
}
void btMultiBody::goToSleep()
{
- m_awake = false;
+ m_awake = false;
}
void btMultiBody::checkMotionAndSleepIfRequired(btScalar timestep)
{
extern bool gDisableDeactivation;
- if (!m_canSleep || gDisableDeactivation)
+ if (!m_canSleep || gDisableDeactivation)
{
m_awake = true;
m_sleepTimer = 0;
return;
}
- // motion is computed as omega^2 + v^2 + (sum of squares of joint velocities)
- btScalar motion = 0;
+ // motion is computed as omega^2 + v^2 + (sum of squares of joint velocities)
+ btScalar motion = 0;
{
- for (int i = 0; i < 6 + m_dofCount; ++i)
+ for (int i = 0; i < 6 + m_dofCount; ++i)
motion += m_realBuf[i] * m_realBuf[i];
}
-
-
- if (motion < SLEEP_EPSILON) {
- m_sleepTimer += timestep;
- if (m_sleepTimer > SLEEP_TIMEOUT) {
- goToSleep();
- }
- } else {
- m_sleepTimer = 0;
+
+ if (motion < SLEEP_EPSILON)
+ {
+ m_sleepTimer += timestep;
+ if (m_sleepTimer > SLEEP_TIMEOUT)
+ {
+ goToSleep();
+ }
+ }
+ else
+ {
+ m_sleepTimer = 0;
if (!m_awake)
wakeUp();
- }
+ }
}
-
-void btMultiBody::forwardKinematics(btAlignedObjectArray<btQuaternion>& world_to_local,btAlignedObjectArray<btVector3>& local_origin)
+void btMultiBody::forwardKinematics(btAlignedObjectArray<btQuaternion> &world_to_local, btAlignedObjectArray<btVector3> &local_origin)
{
-
int num_links = getNumLinks();
// Cached 3x3 rotation matrices from parent frame to this frame.
- btMatrix3x3* rot_from_parent =(btMatrix3x3 *) &m_matrixBuf[0];
+ btMatrix3x3 *rot_from_parent = (btMatrix3x3 *)&m_matrixBuf[0];
- rot_from_parent[0] = btMatrix3x3(m_baseQuat); //m_baseQuat assumed to be alias!?
-
- for (int i = 0; i < num_links; ++i)
+ rot_from_parent[0] = btMatrix3x3(m_baseQuat); //m_baseQuat assumed to be alias!?
+
+ for (int i = 0; i < num_links; ++i)
{
- rot_from_parent[i+1] = btMatrix3x3(m_links[i].m_cachedRotParentToThis);
+ rot_from_parent[i + 1] = btMatrix3x3(m_links[i].m_cachedRotParentToThis);
}
-
+
int nLinks = getNumLinks();
///base + num m_links
- world_to_local.resize(nLinks+1);
- local_origin.resize(nLinks+1);
+ world_to_local.resize(nLinks + 1);
+ local_origin.resize(nLinks + 1);
world_to_local[0] = getWorldToBaseRot();
local_origin[0] = getBasePos();
-
- for (int k=0;k<getNumLinks();k++)
+
+ for (int k = 0; k < getNumLinks(); k++)
{
const int parent = getParent(k);
- world_to_local[k+1] = getParentToLocalRot(k) * world_to_local[parent+1];
- local_origin[k+1] = local_origin[parent+1] + (quatRotate(world_to_local[k+1].inverse() , getRVector(k)));
+ world_to_local[k + 1] = getParentToLocalRot(k) * world_to_local[parent + 1];
+ local_origin[k + 1] = local_origin[parent + 1] + (quatRotate(world_to_local[k + 1].inverse(), getRVector(k)));
}
- for (int link=0;link<getNumLinks();link++)
+ for (int link = 0; link < getNumLinks(); link++)
{
- int index = link+1;
+ int index = link + 1;
btVector3 posr = local_origin[index];
- btScalar quat[4]={-world_to_local[index].x(),-world_to_local[index].y(),-world_to_local[index].z(),world_to_local[index].w()};
+ btScalar quat[4] = {-world_to_local[index].x(), -world_to_local[index].y(), -world_to_local[index].z(), world_to_local[index].w()};
btTransform tr;
tr.setIdentity();
tr.setOrigin(posr);
- tr.setRotation(btQuaternion(quat[0],quat[1],quat[2],quat[3]));
+ tr.setRotation(btQuaternion(quat[0], quat[1], quat[2], quat[3]));
getLink(link).m_cachedWorldTransform = tr;
-
}
-
}
-void btMultiBody::updateCollisionObjectWorldTransforms(btAlignedObjectArray<btQuaternion>& world_to_local,btAlignedObjectArray<btVector3>& local_origin)
+void btMultiBody::updateCollisionObjectWorldTransforms(btAlignedObjectArray<btQuaternion> &world_to_local, btAlignedObjectArray<btVector3> &local_origin)
{
- world_to_local.resize(getNumLinks()+1);
- local_origin.resize(getNumLinks()+1);
-
+ world_to_local.resize(getNumLinks() + 1);
+ local_origin.resize(getNumLinks() + 1);
+
world_to_local[0] = getWorldToBaseRot();
local_origin[0] = getBasePos();
-
+
if (getBaseCollider())
{
btVector3 posr = local_origin[0];
// float pos[4]={posr.x(),posr.y(),posr.z(),1};
- btScalar quat[4]={-world_to_local[0].x(),-world_to_local[0].y(),-world_to_local[0].z(),world_to_local[0].w()};
+ btScalar quat[4] = {-world_to_local[0].x(), -world_to_local[0].y(), -world_to_local[0].z(), world_to_local[0].w()};
btTransform tr;
tr.setIdentity();
tr.setOrigin(posr);
- tr.setRotation(btQuaternion(quat[0],quat[1],quat[2],quat[3]));
-
+ tr.setRotation(btQuaternion(quat[0], quat[1], quat[2], quat[3]));
+
getBaseCollider()->setWorldTransform(tr);
-
}
-
- for (int k=0;k<getNumLinks();k++)
+
+ for (int k = 0; k < getNumLinks(); k++)
{
const int parent = getParent(k);
- world_to_local[k+1] = getParentToLocalRot(k) * world_to_local[parent+1];
- local_origin[k+1] = local_origin[parent+1] + (quatRotate(world_to_local[k+1].inverse() , getRVector(k)));
+ world_to_local[k + 1] = getParentToLocalRot(k) * world_to_local[parent + 1];
+ local_origin[k + 1] = local_origin[parent + 1] + (quatRotate(world_to_local[k + 1].inverse(), getRVector(k)));
}
-
-
- for (int m=0;m<getNumLinks();m++)
+
+ for (int m = 0; m < getNumLinks(); m++)
{
- btMultiBodyLinkCollider* col = getLink(m).m_collider;
+ btMultiBodyLinkCollider *col = getLink(m).m_collider;
if (col)
{
int link = col->m_link;
btAssert(link == m);
-
- int index = link+1;
-
+
+ int index = link + 1;
+
btVector3 posr = local_origin[index];
// float pos[4]={posr.x(),posr.y(),posr.z(),1};
- btScalar quat[4]={-world_to_local[index].x(),-world_to_local[index].y(),-world_to_local[index].z(),world_to_local[index].w()};
+ btScalar quat[4] = {-world_to_local[index].x(), -world_to_local[index].y(), -world_to_local[index].z(), world_to_local[index].w()};
btTransform tr;
tr.setIdentity();
tr.setOrigin(posr);
- tr.setRotation(btQuaternion(quat[0],quat[1],quat[2],quat[3]));
-
+ tr.setRotation(btQuaternion(quat[0], quat[1], quat[2], quat[3]));
+
col->setWorldTransform(tr);
}
}
}
-int btMultiBody::calculateSerializeBufferSize() const
+int btMultiBody::calculateSerializeBufferSize() const
{
int sz = sizeof(btMultiBodyData);
return sz;
}
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
-const char* btMultiBody::serialize(void* dataBuffer, class btSerializer* serializer) const
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char *btMultiBody::serialize(void *dataBuffer, class btSerializer *serializer) const
{
- btMultiBodyData* mbd = (btMultiBodyData*) dataBuffer;
- getBasePos().serialize(mbd->m_baseWorldPosition);
- getWorldToBaseRot().inverse().serialize(mbd->m_baseWorldOrientation);
- getBaseVel().serialize(mbd->m_baseLinearVelocity);
- getBaseOmega().serialize(mbd->m_baseAngularVelocity);
-
- mbd->m_baseMass = this->getBaseMass();
- getBaseInertia().serialize(mbd->m_baseInertia);
+ btMultiBodyData *mbd = (btMultiBodyData *)dataBuffer;
+ getBasePos().serialize(mbd->m_baseWorldPosition);
+ getWorldToBaseRot().inverse().serialize(mbd->m_baseWorldOrientation);
+ getBaseVel().serialize(mbd->m_baseLinearVelocity);
+ getBaseOmega().serialize(mbd->m_baseAngularVelocity);
+
+ mbd->m_baseMass = this->getBaseMass();
+ getBaseInertia().serialize(mbd->m_baseInertia);
+ {
+ char *name = (char *)serializer->findNameForPointer(m_baseName);
+ mbd->m_baseName = (char *)serializer->getUniquePointer(name);
+ if (mbd->m_baseName)
{
- char* name = (char*) serializer->findNameForPointer(m_baseName);
- mbd->m_baseName = (char*)serializer->getUniquePointer(name);
- if (mbd->m_baseName)
- {
- serializer->serializeName(name);
- }
+ serializer->serializeName(name);
}
- mbd->m_numLinks = this->getNumLinks();
- if (mbd->m_numLinks)
+ }
+ mbd->m_numLinks = this->getNumLinks();
+ if (mbd->m_numLinks)
+ {
+ int sz = sizeof(btMultiBodyLinkData);
+ int numElem = mbd->m_numLinks;
+ btChunk *chunk = serializer->allocate(sz, numElem);
+ btMultiBodyLinkData *memPtr = (btMultiBodyLinkData *)chunk->m_oldPtr;
+ for (int i = 0; i < numElem; i++, memPtr++)
{
- int sz = sizeof(btMultiBodyLinkData);
- int numElem = mbd->m_numLinks;
- btChunk* chunk = serializer->allocate(sz,numElem);
- btMultiBodyLinkData* memPtr = (btMultiBodyLinkData*)chunk->m_oldPtr;
- for (int i=0;i<numElem;i++,memPtr++)
+ memPtr->m_jointType = getLink(i).m_jointType;
+ memPtr->m_dofCount = getLink(i).m_dofCount;
+ memPtr->m_posVarCount = getLink(i).m_posVarCount;
+
+ getLink(i).m_inertiaLocal.serialize(memPtr->m_linkInertia);
+
+ getLink(i).m_absFrameTotVelocity.m_topVec.serialize(memPtr->m_absFrameTotVelocityTop);
+ getLink(i).m_absFrameTotVelocity.m_bottomVec.serialize(memPtr->m_absFrameTotVelocityBottom);
+ getLink(i).m_absFrameLocVelocity.m_topVec.serialize(memPtr->m_absFrameLocVelocityTop);
+ getLink(i).m_absFrameLocVelocity.m_bottomVec.serialize(memPtr->m_absFrameLocVelocityBottom);
+
+ memPtr->m_linkMass = getLink(i).m_mass;
+ memPtr->m_parentIndex = getLink(i).m_parent;
+ memPtr->m_jointDamping = getLink(i).m_jointDamping;
+ memPtr->m_jointFriction = getLink(i).m_jointFriction;
+ memPtr->m_jointLowerLimit = getLink(i).m_jointLowerLimit;
+ memPtr->m_jointUpperLimit = getLink(i).m_jointUpperLimit;
+ memPtr->m_jointMaxForce = getLink(i).m_jointMaxForce;
+ memPtr->m_jointMaxVelocity = getLink(i).m_jointMaxVelocity;
+
+ getLink(i).m_eVector.serialize(memPtr->m_parentComToThisPivotOffset);
+ getLink(i).m_dVector.serialize(memPtr->m_thisPivotToThisComOffset);
+ getLink(i).m_zeroRotParentToThis.serialize(memPtr->m_zeroRotParentToThis);
+ btAssert(memPtr->m_dofCount <= 3);
+ for (int dof = 0; dof < getLink(i).m_dofCount; dof++)
{
+ getLink(i).getAxisBottom(dof).serialize(memPtr->m_jointAxisBottom[dof]);
+ getLink(i).getAxisTop(dof).serialize(memPtr->m_jointAxisTop[dof]);
- memPtr->m_jointType = getLink(i).m_jointType;
- memPtr->m_dofCount = getLink(i).m_dofCount;
- memPtr->m_posVarCount = getLink(i).m_posVarCount;
-
- getLink(i).m_inertiaLocal.serialize(memPtr->m_linkInertia);
-
- getLink(i).m_absFrameTotVelocity.m_topVec.serialize(memPtr->m_absFrameTotVelocityTop);
- getLink(i).m_absFrameTotVelocity.m_bottomVec.serialize(memPtr->m_absFrameTotVelocityBottom);
- getLink(i).m_absFrameLocVelocity.m_topVec.serialize(memPtr->m_absFrameLocVelocityTop);
- getLink(i).m_absFrameLocVelocity.m_bottomVec.serialize(memPtr->m_absFrameLocVelocityBottom);
-
- memPtr->m_linkMass = getLink(i).m_mass;
- memPtr->m_parentIndex = getLink(i).m_parent;
- memPtr->m_jointDamping = getLink(i).m_jointDamping;
- memPtr->m_jointFriction = getLink(i).m_jointFriction;
- memPtr->m_jointLowerLimit = getLink(i).m_jointLowerLimit;
- memPtr->m_jointUpperLimit = getLink(i).m_jointUpperLimit;
- memPtr->m_jointMaxForce = getLink(i).m_jointMaxForce;
- memPtr->m_jointMaxVelocity = getLink(i).m_jointMaxVelocity;
-
- getLink(i).m_eVector.serialize(memPtr->m_parentComToThisPivotOffset);
- getLink(i).m_dVector.serialize(memPtr->m_thisPivotToThisComOffset);
- getLink(i).m_zeroRotParentToThis.serialize(memPtr->m_zeroRotParentToThis);
- btAssert(memPtr->m_dofCount<=3);
- for (int dof = 0;dof<getLink(i).m_dofCount;dof++)
- {
- getLink(i).getAxisBottom(dof).serialize(memPtr->m_jointAxisBottom[dof]);
- getLink(i).getAxisTop(dof).serialize(memPtr->m_jointAxisTop[dof]);
-
- memPtr->m_jointTorque[dof] = getLink(i).m_jointTorque[dof];
- memPtr->m_jointVel[dof] = getJointVelMultiDof(i)[dof];
+ memPtr->m_jointTorque[dof] = getLink(i).m_jointTorque[dof];
+ memPtr->m_jointVel[dof] = getJointVelMultiDof(i)[dof];
+ }
+ int numPosVar = getLink(i).m_posVarCount;
+ for (int posvar = 0; posvar < numPosVar; posvar++)
+ {
+ memPtr->m_jointPos[posvar] = getLink(i).m_jointPos[posvar];
+ }
- }
- int numPosVar = getLink(i).m_posVarCount;
- for (int posvar = 0; posvar < numPosVar;posvar++)
- {
- memPtr->m_jointPos[posvar] = getLink(i).m_jointPos[posvar];
- }
-
-
+ {
+ char *name = (char *)serializer->findNameForPointer(m_links[i].m_linkName);
+ memPtr->m_linkName = (char *)serializer->getUniquePointer(name);
+ if (memPtr->m_linkName)
{
- char* name = (char*) serializer->findNameForPointer(m_links[i].m_linkName);
- memPtr->m_linkName = (char*)serializer->getUniquePointer(name);
- if (memPtr->m_linkName)
- {
- serializer->serializeName(name);
- }
+ serializer->serializeName(name);
}
+ }
+ {
+ char *name = (char *)serializer->findNameForPointer(m_links[i].m_jointName);
+ memPtr->m_jointName = (char *)serializer->getUniquePointer(name);
+ if (memPtr->m_jointName)
{
- char* name = (char*) serializer->findNameForPointer(m_links[i].m_jointName);
- memPtr->m_jointName = (char*)serializer->getUniquePointer(name);
- if (memPtr->m_jointName)
- {
- serializer->serializeName(name);
- }
+ serializer->serializeName(name);
}
- memPtr->m_linkCollider = (btCollisionObjectData*)serializer->getUniquePointer(getLink(i).m_collider);
-
}
- serializer->finalizeChunk(chunk,btMultiBodyLinkDataName,BT_ARRAY_CODE,(void*) &m_links[0]);
+ memPtr->m_linkCollider = (btCollisionObjectData *)serializer->getUniquePointer(getLink(i).m_collider);
}
- mbd->m_links = mbd->m_numLinks? (btMultiBodyLinkData*) serializer->getUniquePointer((void*)&m_links[0]):0;
+ serializer->finalizeChunk(chunk, btMultiBodyLinkDataName, BT_ARRAY_CODE, (void *)&m_links[0]);
+ }
+ mbd->m_links = mbd->m_numLinks ? (btMultiBodyLinkData *)serializer->getUniquePointer((void *)&m_links[0]) : 0;
- // Fill padding with zeros to appease msan.
+ // Fill padding with zeros to appease msan.
#ifdef BT_USE_DOUBLE_PRECISION
- memset(mbd->m_padding, 0, sizeof(mbd->m_padding));
+ memset(mbd->m_padding, 0, sizeof(mbd->m_padding));
#endif
- return btMultiBodyDataName;
+ return btMultiBodyDataName;
}
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.h
index 5cd00e5173..e5c0f1806b 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.h
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.h
@@ -21,7 +21,6 @@
*/
-
#ifndef BT_MULTIBODY_H
#define BT_MULTIBODY_H
@@ -31,116 +30,111 @@
#include "LinearMath/btMatrix3x3.h"
#include "LinearMath/btAlignedObjectArray.h"
-
///serialization data, don't change them if you are not familiar with the details of the serialization mechanisms
#ifdef BT_USE_DOUBLE_PRECISION
- #define btMultiBodyData btMultiBodyDoubleData
- #define btMultiBodyDataName "btMultiBodyDoubleData"
- #define btMultiBodyLinkData btMultiBodyLinkDoubleData
- #define btMultiBodyLinkDataName "btMultiBodyLinkDoubleData"
+#define btMultiBodyData btMultiBodyDoubleData
+#define btMultiBodyDataName "btMultiBodyDoubleData"
+#define btMultiBodyLinkData btMultiBodyLinkDoubleData
+#define btMultiBodyLinkDataName "btMultiBodyLinkDoubleData"
#else
- #define btMultiBodyData btMultiBodyFloatData
- #define btMultiBodyDataName "btMultiBodyFloatData"
- #define btMultiBodyLinkData btMultiBodyLinkFloatData
- #define btMultiBodyLinkDataName "btMultiBodyLinkFloatData"
-#endif //BT_USE_DOUBLE_PRECISION
+#define btMultiBodyData btMultiBodyFloatData
+#define btMultiBodyDataName "btMultiBodyFloatData"
+#define btMultiBodyLinkData btMultiBodyLinkFloatData
+#define btMultiBodyLinkDataName "btMultiBodyLinkFloatData"
+#endif //BT_USE_DOUBLE_PRECISION
#include "btMultiBodyLink.h"
class btMultiBodyLinkCollider;
-ATTRIBUTE_ALIGNED16(class) btMultiBody
+ATTRIBUTE_ALIGNED16(class)
+btMultiBody
{
public:
-
-
BT_DECLARE_ALIGNED_ALLOCATOR();
- //
- // initialization
- //
-
- btMultiBody(int n_links, // NOT including the base
- btScalar mass, // mass of base
- const btVector3 &inertia, // inertia of base, in base frame; assumed diagonal
- bool fixedBase, // whether the base is fixed (true) or can move (false)
- bool canSleep, bool deprecatedMultiDof=true);
+ //
+ // initialization
+ //
+ btMultiBody(int n_links, // NOT including the base
+ btScalar mass, // mass of base
+ const btVector3 &inertia, // inertia of base, in base frame; assumed diagonal
+ bool fixedBase, // whether the base is fixed (true) or can move (false)
+ bool canSleep, bool deprecatedMultiDof = true);
virtual ~btMultiBody();
-
+
//note: fixed link collision with parent is always disabled
void setupFixed(int linkIndex,
- btScalar mass,
- const btVector3 &inertia,
- int parent,
- const btQuaternion &rotParentToThis,
- const btVector3 &parentComToThisPivotOffset,
- const btVector3 &thisPivotToThisComOffset, bool deprecatedDisableParentCollision=true);
-
-
+ btScalar mass,
+ const btVector3 &inertia,
+ int parent,
+ const btQuaternion &rotParentToThis,
+ const btVector3 &parentComToThisPivotOffset,
+ const btVector3 &thisPivotToThisComOffset, bool deprecatedDisableParentCollision = true);
+
void setupPrismatic(int i,
- btScalar mass,
- const btVector3 &inertia,
- int parent,
- const btQuaternion &rotParentToThis,
- const btVector3 &jointAxis,
- const btVector3 &parentComToThisPivotOffset,
- const btVector3 &thisPivotToThisComOffset,
- bool disableParentCollision);
-
- void setupRevolute(int linkIndex, // 0 to num_links-1
- btScalar mass,
- const btVector3 &inertia,
- int parentIndex,
- const btQuaternion &rotParentToThis, // rotate points in parent frame to this frame, when q = 0
- const btVector3 &jointAxis, // in my frame
- const btVector3 &parentComToThisPivotOffset, // vector from parent COM to joint axis, in PARENT frame
- const btVector3 &thisPivotToThisComOffset, // vector from joint axis to my COM, in MY frame
- bool disableParentCollision=false);
-
- void setupSpherical(int linkIndex, // 0 to num_links-1
- btScalar mass,
- const btVector3 &inertia,
- int parent,
- const btQuaternion &rotParentToThis, // rotate points in parent frame to this frame, when q = 0
- const btVector3 &parentComToThisPivotOffset, // vector from parent COM to joint axis, in PARENT frame
- const btVector3 &thisPivotToThisComOffset, // vector from joint axis to my COM, in MY frame
- bool disableParentCollision=false);
-
- void setupPlanar(int i, // 0 to num_links-1
- btScalar mass,
- const btVector3 &inertia,
- int parent,
- const btQuaternion &rotParentToThis, // rotate points in parent frame to this frame, when q = 0
- const btVector3 &rotationAxis,
- const btVector3 &parentComToThisComOffset, // vector from parent COM to this COM, in PARENT frame
- bool disableParentCollision=false);
-
- const btMultibodyLink& getLink(int index) const
+ btScalar mass,
+ const btVector3 &inertia,
+ int parent,
+ const btQuaternion &rotParentToThis,
+ const btVector3 &jointAxis,
+ const btVector3 &parentComToThisPivotOffset,
+ const btVector3 &thisPivotToThisComOffset,
+ bool disableParentCollision);
+
+ void setupRevolute(int linkIndex, // 0 to num_links-1
+ btScalar mass,
+ const btVector3 &inertia,
+ int parentIndex,
+ const btQuaternion &rotParentToThis, // rotate points in parent frame to this frame, when q = 0
+ const btVector3 &jointAxis, // in my frame
+ const btVector3 &parentComToThisPivotOffset, // vector from parent COM to joint axis, in PARENT frame
+ const btVector3 &thisPivotToThisComOffset, // vector from joint axis to my COM, in MY frame
+ bool disableParentCollision = false);
+
+ void setupSpherical(int linkIndex, // 0 to num_links-1
+ btScalar mass,
+ const btVector3 &inertia,
+ int parent,
+ const btQuaternion &rotParentToThis, // rotate points in parent frame to this frame, when q = 0
+ const btVector3 &parentComToThisPivotOffset, // vector from parent COM to joint axis, in PARENT frame
+ const btVector3 &thisPivotToThisComOffset, // vector from joint axis to my COM, in MY frame
+ bool disableParentCollision = false);
+
+ void setupPlanar(int i, // 0 to num_links-1
+ btScalar mass,
+ const btVector3 &inertia,
+ int parent,
+ const btQuaternion &rotParentToThis, // rotate points in parent frame to this frame, when q = 0
+ const btVector3 &rotationAxis,
+ const btVector3 &parentComToThisComOffset, // vector from parent COM to this COM, in PARENT frame
+ bool disableParentCollision = false);
+
+ const btMultibodyLink &getLink(int index) const
{
return m_links[index];
}
- btMultibodyLink& getLink(int index)
+ btMultibodyLink &getLink(int index)
{
return m_links[index];
}
-
- void setBaseCollider(btMultiBodyLinkCollider* collider)//collider can be NULL to disable collision for the base
+ void setBaseCollider(btMultiBodyLinkCollider * collider) //collider can be NULL to disable collision for the base
{
m_baseCollider = collider;
}
- const btMultiBodyLinkCollider* getBaseCollider() const
+ const btMultiBodyLinkCollider *getBaseCollider() const
{
return m_baseCollider;
}
- btMultiBodyLinkCollider* getBaseCollider()
+ btMultiBodyLinkCollider *getBaseCollider()
{
return m_baseCollider;
}
- btMultiBodyLinkCollider* getLinkCollider(int index)
+ const btMultiBodyLinkCollider *getLinkCollider(int index) const
{
if (index >= 0 && index < getNumLinks())
{
@@ -149,61 +143,65 @@ public:
return 0;
}
- //
- // get parent
- // input: link num from 0 to num_links-1
- // output: link num from 0 to num_links-1, OR -1 to mean the base.
- //
- int getParent(int link_num) const;
-
-
- //
- // get number of m_links, masses, moments of inertia
- //
+ btMultiBodyLinkCollider *getLinkCollider(int index)
+ {
+ if (index >= 0 && index < getNumLinks())
+ {
+ return getLink(index).m_collider;
+ }
+ return 0;
+ }
+
+ //
+ // get parent
+ // input: link num from 0 to num_links-1
+ // output: link num from 0 to num_links-1, OR -1 to mean the base.
+ //
+ int getParent(int link_num) const;
+
+ //
+ // get number of m_links, masses, moments of inertia
+ //
- int getNumLinks() const { return m_links.size(); }
+ int getNumLinks() const { return m_links.size(); }
int getNumDofs() const { return m_dofCount; }
int getNumPosVars() const { return m_posVarCnt; }
- btScalar getBaseMass() const { return m_baseMass; }
- const btVector3 & getBaseInertia() const { return m_baseInertia; }
- btScalar getLinkMass(int i) const;
- const btVector3 & getLinkInertia(int i) const;
-
-
+ btScalar getBaseMass() const { return m_baseMass; }
+ const btVector3 &getBaseInertia() const { return m_baseInertia; }
+ btScalar getLinkMass(int i) const;
+ const btVector3 &getLinkInertia(int i) const;
- //
- // change mass (incomplete: can only change base mass and inertia at present)
- //
+ //
+ // change mass (incomplete: can only change base mass and inertia at present)
+ //
- void setBaseMass(btScalar mass) { m_baseMass = mass; }
- void setBaseInertia(const btVector3 &inertia) { m_baseInertia = inertia; }
+ void setBaseMass(btScalar mass) { m_baseMass = mass; }
+ void setBaseInertia(const btVector3 &inertia) { m_baseInertia = inertia; }
+ //
+ // get/set pos/vel/rot/omega for the base link
+ //
- //
- // get/set pos/vel/rot/omega for the base link
- //
-
- const btVector3 & getBasePos() const { return m_basePos; } // in world frame
- const btVector3 getBaseVel() const
- {
- return btVector3(m_realBuf[3],m_realBuf[4],m_realBuf[5]);
- } // in world frame
- const btQuaternion & getWorldToBaseRot() const
- {
- return m_baseQuat;
- } // rotates world vectors into base frame
- btVector3 getBaseOmega() const { return btVector3(m_realBuf[0],m_realBuf[1],m_realBuf[2]); } // in world frame
+ const btVector3 &getBasePos() const { return m_basePos; } // in world frame
+ const btVector3 getBaseVel() const
+ {
+ return btVector3(m_realBuf[3], m_realBuf[4], m_realBuf[5]);
+ } // in world frame
+ const btQuaternion &getWorldToBaseRot() const
+ {
+ return m_baseQuat;
+ } // rotates world vectors into base frame
+ btVector3 getBaseOmega() const { return btVector3(m_realBuf[0], m_realBuf[1], m_realBuf[2]); } // in world frame
- void setBasePos(const btVector3 &pos)
- {
- m_basePos = pos;
+ void setBasePos(const btVector3 &pos)
+ {
+ m_basePos = pos;
}
- void setBaseWorldTransform(const btTransform& tr)
+ void setBaseWorldTransform(const btTransform &tr)
{
setBasePos(tr.getOrigin());
setWorldToBaseRot(tr.getRotation().inverse());
-
}
btTransform getBaseWorldTransform() const
@@ -214,190 +212,186 @@ public:
return tr;
}
- void setBaseVel(const btVector3 &vel)
- {
-
- m_realBuf[3]=vel[0]; m_realBuf[4]=vel[1]; m_realBuf[5]=vel[2];
+ void setBaseVel(const btVector3 &vel)
+ {
+ m_realBuf[3] = vel[0];
+ m_realBuf[4] = vel[1];
+ m_realBuf[5] = vel[2];
}
- void setWorldToBaseRot(const btQuaternion &rot)
- {
- m_baseQuat = rot; //m_baseQuat asumed to ba alias!?
+ void setWorldToBaseRot(const btQuaternion &rot)
+ {
+ m_baseQuat = rot; //m_baseQuat asumed to ba alias!?
}
- void setBaseOmega(const btVector3 &omega)
- {
- m_realBuf[0]=omega[0];
- m_realBuf[1]=omega[1];
- m_realBuf[2]=omega[2];
+ void setBaseOmega(const btVector3 &omega)
+ {
+ m_realBuf[0] = omega[0];
+ m_realBuf[1] = omega[1];
+ m_realBuf[2] = omega[2];
}
+ //
+ // get/set pos/vel for child m_links (i = 0 to num_links-1)
+ //
- //
- // get/set pos/vel for child m_links (i = 0 to num_links-1)
- //
-
- btScalar getJointPos(int i) const;
- btScalar getJointVel(int i) const;
-
- btScalar * getJointVelMultiDof(int i);
- btScalar * getJointPosMultiDof(int i);
-
- const btScalar * getJointVelMultiDof(int i) const ;
- const btScalar * getJointPosMultiDof(int i) const ;
+ btScalar getJointPos(int i) const;
+ btScalar getJointVel(int i) const;
- void setJointPos(int i, btScalar q);
- void setJointVel(int i, btScalar qdot);
- void setJointPosMultiDof(int i, btScalar *q);
- void setJointVelMultiDof(int i, btScalar *qdot);
+ btScalar *getJointVelMultiDof(int i);
+ btScalar *getJointPosMultiDof(int i);
+ const btScalar *getJointVelMultiDof(int i) const;
+ const btScalar *getJointPosMultiDof(int i) const;
+ void setJointPos(int i, btScalar q);
+ void setJointVel(int i, btScalar qdot);
+ void setJointPosMultiDof(int i, const double *q);
+ void setJointVelMultiDof(int i, const double *qdot);
+ void setJointPosMultiDof(int i, const float *q);
+ void setJointVelMultiDof(int i, const float *qdot);
- //
- // direct access to velocities as a vector of 6 + num_links elements.
- // (omega first, then v, then joint velocities.)
- //
- const btScalar * getVelocityVector() const
- {
- return &m_realBuf[0];
+ //
+ // direct access to velocities as a vector of 6 + num_links elements.
+ // (omega first, then v, then joint velocities.)
+ //
+ const btScalar *getVelocityVector() const
+ {
+ return &m_realBuf[0];
}
-/* btScalar * getVelocityVector()
+ /* btScalar * getVelocityVector()
{
return &real_buf[0];
}
- */
+ */
- //
- // get the frames of reference (positions and orientations) of the child m_links
- // (i = 0 to num_links-1)
- //
+ //
+ // get the frames of reference (positions and orientations) of the child m_links
+ // (i = 0 to num_links-1)
+ //
- const btVector3 & getRVector(int i) const; // vector from COM(parent(i)) to COM(i), in frame i's coords
- const btQuaternion & getParentToLocalRot(int i) const; // rotates vectors in frame parent(i) to vectors in frame i.
+ const btVector3 &getRVector(int i) const; // vector from COM(parent(i)) to COM(i), in frame i's coords
+ const btQuaternion &getParentToLocalRot(int i) const; // rotates vectors in frame parent(i) to vectors in frame i.
+ //
+ // transform vectors in local frame of link i to world frame (or vice versa)
+ //
+ btVector3 localPosToWorld(int i, const btVector3 &vec) const;
+ btVector3 localDirToWorld(int i, const btVector3 &vec) const;
+ btVector3 worldPosToLocal(int i, const btVector3 &vec) const;
+ btVector3 worldDirToLocal(int i, const btVector3 &vec) const;
- //
- // transform vectors in local frame of link i to world frame (or vice versa)
- //
- btVector3 localPosToWorld(int i, const btVector3 &vec) const;
- btVector3 localDirToWorld(int i, const btVector3 &vec) const;
- btVector3 worldPosToLocal(int i, const btVector3 &vec) const;
- btVector3 worldDirToLocal(int i, const btVector3 &vec) const;
+ //
+ // transform a frame in local coordinate to a frame in world coordinate
+ //
+ btMatrix3x3 localFrameToWorld(int i, const btMatrix3x3 &mat) const;
- //
- // transform a frame in local coordinate to a frame in world coordinate
- //
- btMatrix3x3 localFrameToWorld(int i, const btMatrix3x3 &mat) const;
+ //
+ // calculate kinetic energy and angular momentum
+ // useful for debugging.
+ //
- //
- // calculate kinetic energy and angular momentum
- // useful for debugging.
- //
+ btScalar getKineticEnergy() const;
+ btVector3 getAngularMomentum() const;
- btScalar getKineticEnergy() const;
- btVector3 getAngularMomentum() const;
-
+ //
+ // set external forces and torques. Note all external forces/torques are given in the WORLD frame.
+ //
- //
- // set external forces and torques. Note all external forces/torques are given in the WORLD frame.
- //
-
- void clearForcesAndTorques();
- void clearConstraintForces();
+ void clearForcesAndTorques();
+ void clearConstraintForces();
void clearVelocities();
- void addBaseForce(const btVector3 &f)
- {
- m_baseForce += f;
- }
- void addBaseTorque(const btVector3 &t) { m_baseTorque += t; }
- void addLinkForce(int i, const btVector3 &f);
- void addLinkTorque(int i, const btVector3 &t);
-
- void addBaseConstraintForce(const btVector3 &f)
- {
- m_baseConstraintForce += f;
- }
- void addBaseConstraintTorque(const btVector3 &t) { m_baseConstraintTorque += t; }
- void addLinkConstraintForce(int i, const btVector3 &f);
- void addLinkConstraintTorque(int i, const btVector3 &t);
-
-
-void addJointTorque(int i, btScalar Q);
+ void addBaseForce(const btVector3 &f)
+ {
+ m_baseForce += f;
+ }
+ void addBaseTorque(const btVector3 &t) { m_baseTorque += t; }
+ void addLinkForce(int i, const btVector3 &f);
+ void addLinkTorque(int i, const btVector3 &t);
+
+ void addBaseConstraintForce(const btVector3 &f)
+ {
+ m_baseConstraintForce += f;
+ }
+ void addBaseConstraintTorque(const btVector3 &t) { m_baseConstraintTorque += t; }
+ void addLinkConstraintForce(int i, const btVector3 &f);
+ void addLinkConstraintTorque(int i, const btVector3 &t);
+
+ void addJointTorque(int i, btScalar Q);
void addJointTorqueMultiDof(int i, int dof, btScalar Q);
void addJointTorqueMultiDof(int i, const btScalar *Q);
- const btVector3 & getBaseForce() const { return m_baseForce; }
- const btVector3 & getBaseTorque() const { return m_baseTorque; }
- const btVector3 & getLinkForce(int i) const;
- const btVector3 & getLinkTorque(int i) const;
- btScalar getJointTorque(int i) const;
- btScalar * getJointTorqueMultiDof(int i);
-
-
- //
- // dynamics routines.
- //
-
- // timestep the velocities (given the external forces/torques set using addBaseForce etc).
- // also sets up caches for calcAccelerationDeltas.
- //
- // Note: the caller must provide three vectors which are used as
- // temporary scratch space. The idea here is to reduce dynamic
- // memory allocation: the same scratch vectors can be re-used
- // again and again for different Multibodies, instead of each
- // btMultiBody allocating (and then deallocating) their own
- // individual scratch buffers. This gives a considerable speed
- // improvement, at least on Windows (where dynamic memory
- // allocation appears to be fairly slow).
- //
-
-
+ const btVector3 &getBaseForce() const { return m_baseForce; }
+ const btVector3 &getBaseTorque() const { return m_baseTorque; }
+ const btVector3 &getLinkForce(int i) const;
+ const btVector3 &getLinkTorque(int i) const;
+ btScalar getJointTorque(int i) const;
+ btScalar *getJointTorqueMultiDof(int i);
+
+ //
+ // dynamics routines.
+ //
+
+ // timestep the velocities (given the external forces/torques set using addBaseForce etc).
+ // also sets up caches for calcAccelerationDeltas.
+ //
+ // Note: the caller must provide three vectors which are used as
+ // temporary scratch space. The idea here is to reduce dynamic
+ // memory allocation: the same scratch vectors can be re-used
+ // again and again for different Multibodies, instead of each
+ // btMultiBody allocating (and then deallocating) their own
+ // individual scratch buffers. This gives a considerable speed
+ // improvement, at least on Windows (where dynamic memory
+ // allocation appears to be fairly slow).
+ //
+
void computeAccelerationsArticulatedBodyAlgorithmMultiDof(btScalar dt,
- btAlignedObjectArray<btScalar> &scratch_r,
- btAlignedObjectArray<btVector3> &scratch_v,
- btAlignedObjectArray<btMatrix3x3> &scratch_m,
- bool isConstraintPass=false
- );
-
-///stepVelocitiesMultiDof is deprecated, use computeAccelerationsArticulatedBodyAlgorithmMultiDof instead
- void stepVelocitiesMultiDof(btScalar dt,
- btAlignedObjectArray<btScalar> &scratch_r,
- btAlignedObjectArray<btVector3> &scratch_v,
- btAlignedObjectArray<btMatrix3x3> &scratch_m,
- bool isConstraintPass=false)
- {
- computeAccelerationsArticulatedBodyAlgorithmMultiDof(dt,scratch_r,scratch_v,scratch_m,isConstraintPass);
- }
-
- // calcAccelerationDeltasMultiDof
- // input: force vector (in same format as jacobian, i.e.:
- // 3 torque values, 3 force values, num_links joint torque values)
- // output: 3 omegadot values, 3 vdot values, num_links q_double_dot values
- // (existing contents of output array are replaced)
- // calcAccelerationDeltasMultiDof must have been called first.
+ btAlignedObjectArray<btScalar> & scratch_r,
+ btAlignedObjectArray<btVector3> & scratch_v,
+ btAlignedObjectArray<btMatrix3x3> & scratch_m,
+ bool isConstraintPass,
+ bool jointFeedbackInWorldSpace,
+ bool jointFeedbackInJointFrame
+ );
+
+ ///stepVelocitiesMultiDof is deprecated, use computeAccelerationsArticulatedBodyAlgorithmMultiDof instead
+ //void stepVelocitiesMultiDof(btScalar dt,
+ // btAlignedObjectArray<btScalar> & scratch_r,
+ // btAlignedObjectArray<btVector3> & scratch_v,
+ // btAlignedObjectArray<btMatrix3x3> & scratch_m,
+ // bool isConstraintPass = false)
+ //{
+ // computeAccelerationsArticulatedBodyAlgorithmMultiDof(dt, scratch_r, scratch_v, scratch_m, isConstraintPass, false, false);
+ //}
+
+ // calcAccelerationDeltasMultiDof
+ // input: force vector (in same format as jacobian, i.e.:
+ // 3 torque values, 3 force values, num_links joint torque values)
+ // output: 3 omegadot values, 3 vdot values, num_links q_double_dot values
+ // (existing contents of output array are replaced)
+ // calcAccelerationDeltasMultiDof must have been called first.
void calcAccelerationDeltasMultiDof(const btScalar *force, btScalar *output,
- btAlignedObjectArray<btScalar> &scratch_r,
- btAlignedObjectArray<btVector3> &scratch_v) const;
-
-
- void applyDeltaVeeMultiDof2(const btScalar * delta_vee, btScalar multiplier)
+ btAlignedObjectArray<btScalar> &scratch_r,
+ btAlignedObjectArray<btVector3> &scratch_v) const;
+
+ void applyDeltaVeeMultiDof2(const btScalar *delta_vee, btScalar multiplier)
{
for (int dof = 0; dof < 6 + getNumDofs(); ++dof)
- {
- m_deltaV[dof] += delta_vee[dof] * multiplier;
- }
+ {
+ m_deltaV[dof] += delta_vee[dof] * multiplier;
+ }
}
void processDeltaVeeMultiDof2()
{
- applyDeltaVeeMultiDof(&m_deltaV[0],1);
+ applyDeltaVeeMultiDof(&m_deltaV[0], 1);
for (int dof = 0; dof < 6 + getNumDofs(); ++dof)
- {
+ {
m_deltaV[dof] = 0.f;
}
}
- void applyDeltaVeeMultiDof(const btScalar * delta_vee, btScalar multiplier)
+ void applyDeltaVeeMultiDof(const btScalar *delta_vee, btScalar multiplier)
{
//for (int dof = 0; dof < 6 + getNumDofs(); ++dof)
// printf("%.4f ", delta_vee[dof]*multiplier);
@@ -418,65 +412,61 @@ void addJointTorque(int i, btScalar Q);
for (int dof = 0; dof < 6 + getNumDofs(); ++dof)
{
m_realBuf[dof] += delta_vee[dof] * multiplier;
- btClamp(m_realBuf[dof],-m_maxCoordinateVelocity,m_maxCoordinateVelocity);
+ btClamp(m_realBuf[dof], -m_maxCoordinateVelocity, m_maxCoordinateVelocity);
}
- }
+ }
-
-
- // timestep the positions (given current velocities).
+ // timestep the positions (given current velocities).
void stepPositionsMultiDof(btScalar dt, btScalar *pq = 0, btScalar *pqd = 0);
+ //
+ // contacts
+ //
- //
- // contacts
- //
+ // This routine fills out a contact constraint jacobian for this body.
+ // the 'normal' supplied must be -n for body1 or +n for body2 of the contact.
+ // 'normal' & 'contact_point' are both given in world coordinates.
- // This routine fills out a contact constraint jacobian for this body.
- // the 'normal' supplied must be -n for body1 or +n for body2 of the contact.
- // 'normal' & 'contact_point' are both given in world coordinates.
-
void fillContactJacobianMultiDof(int link,
- const btVector3 &contact_point,
- const btVector3 &normal,
- btScalar *jac,
- btAlignedObjectArray<btScalar> &scratch_r,
- btAlignedObjectArray<btVector3> &scratch_v,
- btAlignedObjectArray<btMatrix3x3> &scratch_m) const { fillConstraintJacobianMultiDof(link, contact_point, btVector3(0, 0, 0), normal, jac, scratch_r, scratch_v, scratch_m); }
+ const btVector3 &contact_point,
+ const btVector3 &normal,
+ btScalar *jac,
+ btAlignedObjectArray<btScalar> &scratch_r,
+ btAlignedObjectArray<btVector3> &scratch_v,
+ btAlignedObjectArray<btMatrix3x3> &scratch_m) const { fillConstraintJacobianMultiDof(link, contact_point, btVector3(0, 0, 0), normal, jac, scratch_r, scratch_v, scratch_m); }
//a more general version of fillContactJacobianMultiDof which does not assume..
//.. that the constraint in question is contact or, to be more precise, constrains linear velocity only
void fillConstraintJacobianMultiDof(int link,
- const btVector3 &contact_point,
- const btVector3 &normal_ang,
- const btVector3 &normal_lin,
- btScalar *jac,
- btAlignedObjectArray<btScalar> &scratch_r,
- btAlignedObjectArray<btVector3> &scratch_v,
- btAlignedObjectArray<btMatrix3x3> &scratch_m) const;
-
-
- //
- // sleeping
- //
- void setCanSleep(bool canSleep)
+ const btVector3 &contact_point,
+ const btVector3 &normal_ang,
+ const btVector3 &normal_lin,
+ btScalar *jac,
+ btAlignedObjectArray<btScalar> &scratch_r,
+ btAlignedObjectArray<btVector3> &scratch_v,
+ btAlignedObjectArray<btMatrix3x3> &scratch_m) const;
+
+ //
+ // sleeping
+ //
+ void setCanSleep(bool canSleep)
{
m_canSleep = canSleep;
}
- bool getCanSleep()const
+ bool getCanSleep() const
{
return m_canSleep;
}
- bool isAwake() const { return m_awake; }
- void wakeUp();
- void goToSleep();
- void checkMotionAndSleepIfRequired(btScalar timestep);
-
+ bool isAwake() const { return m_awake; }
+ void wakeUp();
+ void goToSleep();
+ void checkMotionAndSleepIfRequired(btScalar timestep);
+
bool hasFixedBase() const
{
- return m_fixedBase;
+ return m_fixedBase;
}
int getCompanionId() const
@@ -489,16 +479,16 @@ void addJointTorque(int i, btScalar Q);
m_companionId = id;
}
- void setNumLinks(int numLinks)//careful: when changing the number of m_links, make sure to re-initialize or update existing m_links
+ void setNumLinks(int numLinks) //careful: when changing the number of m_links, make sure to re-initialize or update existing m_links
{
m_links.resize(numLinks);
}
btScalar getLinearDamping() const
{
- return m_linearDamping;
+ return m_linearDamping;
}
- void setLinearDamping( btScalar damp)
+ void setLinearDamping(btScalar damp)
{
m_linearDamping = damp;
}
@@ -506,11 +496,11 @@ void addJointTorque(int i, btScalar Q);
{
return m_angularDamping;
}
- void setAngularDamping( btScalar damp)
+ void setAngularDamping(btScalar damp)
{
m_angularDamping = damp;
}
-
+
bool getUseGyroTerm() const
{
return m_useGyroTerm;
@@ -519,24 +509,24 @@ void addJointTorque(int i, btScalar Q);
{
m_useGyroTerm = useGyro;
}
- btScalar getMaxCoordinateVelocity() const
+ btScalar getMaxCoordinateVelocity() const
{
- return m_maxCoordinateVelocity ;
+ return m_maxCoordinateVelocity;
}
- void setMaxCoordinateVelocity(btScalar maxVel)
+ void setMaxCoordinateVelocity(btScalar maxVel)
{
m_maxCoordinateVelocity = maxVel;
}
- btScalar getMaxAppliedImpulse() const
+ btScalar getMaxAppliedImpulse() const
{
return m_maxAppliedImpulse;
}
- void setMaxAppliedImpulse(btScalar maxImp)
+ void setMaxAppliedImpulse(btScalar maxImp)
{
m_maxAppliedImpulse = maxImp;
}
- void setHasSelfCollision(bool hasSelfCollision)
+ void setHasSelfCollision(bool hasSelfCollision)
{
m_hasSelfCollision = hasSelfCollision;
}
@@ -545,7 +535,6 @@ void addJointTorque(int i, btScalar Q);
return m_hasSelfCollision;
}
-
void finalizeMultiDof();
void useRK4Integration(bool use) { m_useRK4 = use; }
@@ -561,126 +550,132 @@ void addJointTorque(int i, btScalar Q);
{
__posUpdated = updated;
}
-
+
//internalNeedsJointFeedback is for internal use only
bool internalNeedsJointFeedback() const
{
return m_internalNeedsJointFeedback;
}
- void forwardKinematics(btAlignedObjectArray<btQuaternion>& scratch_q,btAlignedObjectArray<btVector3>& scratch_m);
+ void forwardKinematics(btAlignedObjectArray<btQuaternion> & scratch_q, btAlignedObjectArray<btVector3> & scratch_m);
+
+ void compTreeLinkVelocities(btVector3 * omega, btVector3 * vel) const;
- void compTreeLinkVelocities(btVector3 *omega, btVector3 *vel) const;
+ void updateCollisionObjectWorldTransforms(btAlignedObjectArray<btQuaternion> & scratch_q, btAlignedObjectArray<btVector3> & scratch_m);
- void updateCollisionObjectWorldTransforms(btAlignedObjectArray<btQuaternion>& scratch_q,btAlignedObjectArray<btVector3>& scratch_m);
-
- virtual int calculateSerializeBufferSize() const;
+ virtual int calculateSerializeBufferSize() const;
///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const;
+ virtual const char *serialize(void *dataBuffer, class btSerializer *serializer) const;
- const char* getBaseName() const
+ const char *getBaseName() const
{
return m_baseName;
}
///memory of setBaseName needs to be manager by user
- void setBaseName(const char* name)
+ void setBaseName(const char *name)
{
m_baseName = name;
}
///users can point to their objects, userPointer is not used by Bullet
- void* getUserPointer() const
+ void *getUserPointer() const
{
return m_userObjectPointer;
}
- int getUserIndex() const
+ int getUserIndex() const
{
return m_userIndex;
}
- int getUserIndex2() const
+ int getUserIndex2() const
{
return m_userIndex2;
}
///users can point to their objects, userPointer is not used by Bullet
- void setUserPointer(void* userPointer)
+ void setUserPointer(void *userPointer)
{
m_userObjectPointer = userPointer;
}
///users can point to their objects, userPointer is not used by Bullet
- void setUserIndex(int index)
+ void setUserIndex(int index)
{
m_userIndex = index;
}
- void setUserIndex2(int index)
+ void setUserIndex2(int index)
{
m_userIndex2 = index;
}
-private:
- btMultiBody(const btMultiBody &); // not implemented
- void operator=(const btMultiBody &); // not implemented
+ static void spatialTransform(const btMatrix3x3 &rotation_matrix, // rotates vectors in 'from' frame to vectors in 'to' frame
+ const btVector3 &displacement, // vector from origin of 'from' frame to origin of 'to' frame, in 'to' coordinates
+ const btVector3 &top_in, // top part of input vector
+ const btVector3 &bottom_in, // bottom part of input vector
+ btVector3 &top_out, // top part of output vector
+ btVector3 &bottom_out); // bottom part of output vector
+
- void solveImatrix(const btVector3& rhs_top, const btVector3& rhs_bot, btScalar result[6]) const;
+private:
+ btMultiBody(const btMultiBody &); // not implemented
+ void operator=(const btMultiBody &); // not implemented
+
+ void solveImatrix(const btVector3 &rhs_top, const btVector3 &rhs_bot, btScalar result[6]) const;
void solveImatrix(const btSpatialForceVector &rhs, btSpatialMotionVector &result) const;
-
+
void updateLinksDofOffsets()
{
int dofOffset = 0, cfgOffset = 0;
- for(int bidx = 0; bidx < m_links.size(); ++bidx)
+ for (int bidx = 0; bidx < m_links.size(); ++bidx)
{
- m_links[bidx].m_dofOffset = dofOffset; m_links[bidx].m_cfgOffset = cfgOffset;
- dofOffset += m_links[bidx].m_dofCount; cfgOffset += m_links[bidx].m_posVarCount;
+ m_links[bidx].m_dofOffset = dofOffset;
+ m_links[bidx].m_cfgOffset = cfgOffset;
+ dofOffset += m_links[bidx].m_dofCount;
+ cfgOffset += m_links[bidx].m_posVarCount;
}
}
- void mulMatrix(btScalar *pA, btScalar *pB, int rowsA, int colsA, int rowsB, int colsB, btScalar *pC) const;
-
-
-private:
-
- btMultiBodyLinkCollider* m_baseCollider;//can be NULL
- const char* m_baseName;//memory needs to be manager by user!
-
- btVector3 m_basePos; // position of COM of base (world frame)
- btQuaternion m_baseQuat; // rotates world points into base frame
-
- btScalar m_baseMass; // mass of the base
- btVector3 m_baseInertia; // inertia of the base (in local frame; diagonal)
-
- btVector3 m_baseForce; // external force applied to base. World frame.
- btVector3 m_baseTorque; // external torque applied to base. World frame.
-
- btVector3 m_baseConstraintForce; // external force applied to base. World frame.
- btVector3 m_baseConstraintTorque; // external torque applied to base. World frame.
-
- btAlignedObjectArray<btMultibodyLink> m_links; // array of m_links, excluding the base. index from 0 to num_links-1.
-
-
- //
- // realBuf:
- // offset size array
- // 0 6 + num_links v (base_omega; base_vel; joint_vels) MULTIDOF [sysdof x sysdof for D matrices (TOO MUCH!) + pos_delta which is sys-cfg sized]
- // 6+num_links num_links D
- //
- // vectorBuf:
- // offset size array
- // 0 num_links h_top
- // num_links num_links h_bottom
- //
- // matrixBuf:
- // offset size array
- // 0 num_links+1 rot_from_parent
- //
- btAlignedObjectArray<btScalar> m_deltaV;
- btAlignedObjectArray<btScalar> m_realBuf;
- btAlignedObjectArray<btVector3> m_vectorBuf;
- btAlignedObjectArray<btMatrix3x3> m_matrixBuf;
+ void mulMatrix(btScalar * pA, btScalar * pB, int rowsA, int colsA, int rowsB, int colsB, btScalar *pC) const;
+private:
+ btMultiBodyLinkCollider *m_baseCollider; //can be NULL
+ const char *m_baseName; //memory needs to be manager by user!
+
+ btVector3 m_basePos; // position of COM of base (world frame)
+ btQuaternion m_baseQuat; // rotates world points into base frame
+
+ btScalar m_baseMass; // mass of the base
+ btVector3 m_baseInertia; // inertia of the base (in local frame; diagonal)
+
+ btVector3 m_baseForce; // external force applied to base. World frame.
+ btVector3 m_baseTorque; // external torque applied to base. World frame.
+
+ btVector3 m_baseConstraintForce; // external force applied to base. World frame.
+ btVector3 m_baseConstraintTorque; // external torque applied to base. World frame.
+
+ btAlignedObjectArray<btMultibodyLink> m_links; // array of m_links, excluding the base. index from 0 to num_links-1.
+
+ //
+ // realBuf:
+ // offset size array
+ // 0 6 + num_links v (base_omega; base_vel; joint_vels) MULTIDOF [sysdof x sysdof for D matrices (TOO MUCH!) + pos_delta which is sys-cfg sized]
+ // 6+num_links num_links D
+ //
+ // vectorBuf:
+ // offset size array
+ // 0 num_links h_top
+ // num_links num_links h_bottom
+ //
+ // matrixBuf:
+ // offset size array
+ // 0 num_links+1 rot_from_parent
+ //
+ btAlignedObjectArray<btScalar> m_deltaV;
+ btAlignedObjectArray<btScalar> m_realBuf;
+ btAlignedObjectArray<btVector3> m_vectorBuf;
+ btAlignedObjectArray<btMatrix3x3> m_matrixBuf;
btMatrix3x3 m_cachedInertiaTopLeft;
btMatrix3x3 m_cachedInertiaTopRight;
@@ -688,25 +683,25 @@ private:
btMatrix3x3 m_cachedInertiaLowerRight;
bool m_cachedInertiaValid;
- bool m_fixedBase;
+ bool m_fixedBase;
- // Sleep parameters.
- bool m_awake;
- bool m_canSleep;
- btScalar m_sleepTimer;
+ // Sleep parameters.
+ bool m_awake;
+ bool m_canSleep;
+ btScalar m_sleepTimer;
- void* m_userObjectPointer;
+ void *m_userObjectPointer;
int m_userIndex2;
int m_userIndex;
- int m_companionId;
- btScalar m_linearDamping;
- btScalar m_angularDamping;
- bool m_useGyroTerm;
- btScalar m_maxAppliedImpulse;
- btScalar m_maxCoordinateVelocity;
- bool m_hasSelfCollision;
-
+ int m_companionId;
+ btScalar m_linearDamping;
+ btScalar m_angularDamping;
+ bool m_useGyroTerm;
+ btScalar m_maxAppliedImpulse;
+ btScalar m_maxCoordinateVelocity;
+ bool m_hasSelfCollision;
+
bool __posUpdated;
int m_dofCount, m_posVarCnt;
@@ -720,117 +715,108 @@ private:
struct btMultiBodyLinkDoubleData
{
- btQuaternionDoubleData m_zeroRotParentToThis;
- btVector3DoubleData m_parentComToThisPivotOffset;
- btVector3DoubleData m_thisPivotToThisComOffset;
- btVector3DoubleData m_jointAxisTop[6];
- btVector3DoubleData m_jointAxisBottom[6];
-
- btVector3DoubleData m_linkInertia; // inertia of the base (in local frame; diagonal)
- btVector3DoubleData m_absFrameTotVelocityTop;
- btVector3DoubleData m_absFrameTotVelocityBottom;
- btVector3DoubleData m_absFrameLocVelocityTop;
- btVector3DoubleData m_absFrameLocVelocityBottom;
-
- double m_linkMass;
- int m_parentIndex;
- int m_jointType;
-
- int m_dofCount;
- int m_posVarCount;
- double m_jointPos[7];
- double m_jointVel[6];
- double m_jointTorque[6];
-
- double m_jointDamping;
- double m_jointFriction;
- double m_jointLowerLimit;
- double m_jointUpperLimit;
- double m_jointMaxForce;
- double m_jointMaxVelocity;
-
- char *m_linkName;
- char *m_jointName;
- btCollisionObjectDoubleData *m_linkCollider;
- char *m_paddingPtr;
-
+ btQuaternionDoubleData m_zeroRotParentToThis;
+ btVector3DoubleData m_parentComToThisPivotOffset;
+ btVector3DoubleData m_thisPivotToThisComOffset;
+ btVector3DoubleData m_jointAxisTop[6];
+ btVector3DoubleData m_jointAxisBottom[6];
+
+ btVector3DoubleData m_linkInertia; // inertia of the base (in local frame; diagonal)
+ btVector3DoubleData m_absFrameTotVelocityTop;
+ btVector3DoubleData m_absFrameTotVelocityBottom;
+ btVector3DoubleData m_absFrameLocVelocityTop;
+ btVector3DoubleData m_absFrameLocVelocityBottom;
+
+ double m_linkMass;
+ int m_parentIndex;
+ int m_jointType;
+
+ int m_dofCount;
+ int m_posVarCount;
+ double m_jointPos[7];
+ double m_jointVel[6];
+ double m_jointTorque[6];
+
+ double m_jointDamping;
+ double m_jointFriction;
+ double m_jointLowerLimit;
+ double m_jointUpperLimit;
+ double m_jointMaxForce;
+ double m_jointMaxVelocity;
+
+ char *m_linkName;
+ char *m_jointName;
+ btCollisionObjectDoubleData *m_linkCollider;
+ char *m_paddingPtr;
};
struct btMultiBodyLinkFloatData
{
- btQuaternionFloatData m_zeroRotParentToThis;
- btVector3FloatData m_parentComToThisPivotOffset;
- btVector3FloatData m_thisPivotToThisComOffset;
- btVector3FloatData m_jointAxisTop[6];
- btVector3FloatData m_jointAxisBottom[6];
- btVector3FloatData m_linkInertia; // inertia of the base (in local frame; diagonal)
- btVector3FloatData m_absFrameTotVelocityTop;
- btVector3FloatData m_absFrameTotVelocityBottom;
- btVector3FloatData m_absFrameLocVelocityTop;
- btVector3FloatData m_absFrameLocVelocityBottom;
-
- int m_dofCount;
- float m_linkMass;
- int m_parentIndex;
- int m_jointType;
-
-
-
- float m_jointPos[7];
- float m_jointVel[6];
- float m_jointTorque[6];
- int m_posVarCount;
- float m_jointDamping;
- float m_jointFriction;
- float m_jointLowerLimit;
- float m_jointUpperLimit;
- float m_jointMaxForce;
- float m_jointMaxVelocity;
-
- char *m_linkName;
- char *m_jointName;
- btCollisionObjectFloatData *m_linkCollider;
- char *m_paddingPtr;
-
+ btQuaternionFloatData m_zeroRotParentToThis;
+ btVector3FloatData m_parentComToThisPivotOffset;
+ btVector3FloatData m_thisPivotToThisComOffset;
+ btVector3FloatData m_jointAxisTop[6];
+ btVector3FloatData m_jointAxisBottom[6];
+ btVector3FloatData m_linkInertia; // inertia of the base (in local frame; diagonal)
+ btVector3FloatData m_absFrameTotVelocityTop;
+ btVector3FloatData m_absFrameTotVelocityBottom;
+ btVector3FloatData m_absFrameLocVelocityTop;
+ btVector3FloatData m_absFrameLocVelocityBottom;
+
+ int m_dofCount;
+ float m_linkMass;
+ int m_parentIndex;
+ int m_jointType;
+
+ float m_jointPos[7];
+ float m_jointVel[6];
+ float m_jointTorque[6];
+ int m_posVarCount;
+ float m_jointDamping;
+ float m_jointFriction;
+ float m_jointLowerLimit;
+ float m_jointUpperLimit;
+ float m_jointMaxForce;
+ float m_jointMaxVelocity;
+
+ char *m_linkName;
+ char *m_jointName;
+ btCollisionObjectFloatData *m_linkCollider;
+ char *m_paddingPtr;
};
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btMultiBodyDoubleData
+struct btMultiBodyDoubleData
{
btVector3DoubleData m_baseWorldPosition;
btQuaternionDoubleData m_baseWorldOrientation;
btVector3DoubleData m_baseLinearVelocity;
btVector3DoubleData m_baseAngularVelocity;
- btVector3DoubleData m_baseInertia; // inertia of the base (in local frame; diagonal)
- double m_baseMass;
- int m_numLinks;
- char m_padding[4];
-
- char *m_baseName;
- btMultiBodyLinkDoubleData *m_links;
- btCollisionObjectDoubleData *m_baseCollider;
-
-
+ btVector3DoubleData m_baseInertia; // inertia of the base (in local frame; diagonal)
+ double m_baseMass;
+ int m_numLinks;
+ char m_padding[4];
+
+ char *m_baseName;
+ btMultiBodyLinkDoubleData *m_links;
+ btCollisionObjectDoubleData *m_baseCollider;
};
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btMultiBodyFloatData
+struct btMultiBodyFloatData
{
btVector3FloatData m_baseWorldPosition;
btQuaternionFloatData m_baseWorldOrientation;
btVector3FloatData m_baseLinearVelocity;
btVector3FloatData m_baseAngularVelocity;
- btVector3FloatData m_baseInertia; // inertia of the base (in local frame; diagonal)
- float m_baseMass;
- int m_numLinks;
-
- char *m_baseName;
- btMultiBodyLinkFloatData *m_links;
- btCollisionObjectFloatData *m_baseCollider;
+ btVector3FloatData m_baseInertia; // inertia of the base (in local frame; diagonal)
+ float m_baseMass;
+ int m_numLinks;
+ char *m_baseName;
+ btMultiBodyLinkFloatData *m_links;
+ btCollisionObjectFloatData *m_baseCollider;
};
-
-
#endif
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp
index 9f61874b83..e17ab94d98 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp
@@ -1,32 +1,29 @@
#include "btMultiBodyConstraint.h"
#include "BulletDynamics/Dynamics/btRigidBody.h"
-#include "btMultiBodyPoint2Point.h" //for testing (BTMBP2PCONSTRAINT_BLOCK_ANGULAR_MOTION_TEST macro)
+#include "btMultiBodyPoint2Point.h" //for testing (BTMBP2PCONSTRAINT_BLOCK_ANGULAR_MOTION_TEST macro)
-
-
-btMultiBodyConstraint::btMultiBodyConstraint(btMultiBody* bodyA,btMultiBody* bodyB,int linkA, int linkB, int numRows, bool isUnilateral)
- :m_bodyA(bodyA),
- m_bodyB(bodyB),
- m_linkA(linkA),
- m_linkB(linkB),
- m_numRows(numRows),
- m_jacSizeA(0),
- m_jacSizeBoth(0),
- m_isUnilateral(isUnilateral),
- m_numDofsFinalized(-1),
- m_maxAppliedImpulse(100)
+btMultiBodyConstraint::btMultiBodyConstraint(btMultiBody* bodyA, btMultiBody* bodyB, int linkA, int linkB, int numRows, bool isUnilateral)
+ : m_bodyA(bodyA),
+ m_bodyB(bodyB),
+ m_linkA(linkA),
+ m_linkB(linkB),
+ m_numRows(numRows),
+ m_jacSizeA(0),
+ m_jacSizeBoth(0),
+ m_isUnilateral(isUnilateral),
+ m_numDofsFinalized(-1),
+ m_maxAppliedImpulse(100)
{
-
}
void btMultiBodyConstraint::updateJacobianSizes()
{
- if(m_bodyA)
+ if (m_bodyA)
{
m_jacSizeA = (6 + m_bodyA->getNumDofs());
}
- if(m_bodyB)
+ if (m_bodyB)
{
m_jacSizeBoth = m_jacSizeA + 6 + m_bodyB->getNumDofs();
}
@@ -38,7 +35,7 @@ void btMultiBodyConstraint::allocateJacobiansMultiDof()
{
updateJacobianSizes();
- m_posOffset = ((1 + m_jacSizeBoth)*m_numRows);
+ m_posOffset = ((1 + m_jacSizeBoth) * m_numRows);
m_data.resize((2 + m_jacSizeBoth) * m_numRows);
}
@@ -46,298 +43,307 @@ btMultiBodyConstraint::~btMultiBodyConstraint()
{
}
-void btMultiBodyConstraint::applyDeltaVee(btMultiBodyJacobianData& data, btScalar* delta_vee, btScalar impulse, int velocityIndex, int ndof)
+void btMultiBodyConstraint::applyDeltaVee(btMultiBodyJacobianData& data, btScalar* delta_vee, btScalar impulse, int velocityIndex, int ndof)
{
for (int i = 0; i < ndof; ++i)
- data.m_deltaVelocities[velocityIndex+i] += delta_vee[i] * impulse;
+ data.m_deltaVelocities[velocityIndex + i] += delta_vee[i] * impulse;
}
-btScalar btMultiBodyConstraint::fillMultiBodyConstraint( btMultiBodySolverConstraint& solverConstraint,
- btMultiBodyJacobianData& data,
- btScalar* jacOrgA, btScalar* jacOrgB,
- const btVector3& constraintNormalAng,
- const btVector3& constraintNormalLin,
- const btVector3& posAworld, const btVector3& posBworld,
- btScalar posError,
- const btContactSolverInfo& infoGlobal,
- btScalar lowerLimit, btScalar upperLimit,
- bool angConstraint,
- btScalar relaxation,
- bool isFriction, btScalar desiredVelocity, btScalar cfmSlip)
+btScalar btMultiBodyConstraint::fillMultiBodyConstraint(btMultiBodySolverConstraint& solverConstraint,
+ btMultiBodyJacobianData& data,
+ btScalar* jacOrgA, btScalar* jacOrgB,
+ const btVector3& constraintNormalAng,
+ const btVector3& constraintNormalLin,
+ const btVector3& posAworld, const btVector3& posBworld,
+ btScalar posError,
+ const btContactSolverInfo& infoGlobal,
+ btScalar lowerLimit, btScalar upperLimit,
+ bool angConstraint,
+ btScalar relaxation,
+ bool isFriction, btScalar desiredVelocity, btScalar cfmSlip)
{
- solverConstraint.m_multiBodyA = m_bodyA;
- solverConstraint.m_multiBodyB = m_bodyB;
- solverConstraint.m_linkA = m_linkA;
- solverConstraint.m_linkB = m_linkB;
-
- btMultiBody* multiBodyA = solverConstraint.m_multiBodyA;
- btMultiBody* multiBodyB = solverConstraint.m_multiBodyB;
-
- btSolverBody* bodyA = multiBodyA ? 0 : &data.m_solverBodyPool->at(solverConstraint.m_solverBodyIdA);
- btSolverBody* bodyB = multiBodyB ? 0 : &data.m_solverBodyPool->at(solverConstraint.m_solverBodyIdB);
-
- btRigidBody* rb0 = multiBodyA ? 0 : bodyA->m_originalBody;
- btRigidBody* rb1 = multiBodyB ? 0 : bodyB->m_originalBody;
-
- btVector3 rel_pos1, rel_pos2; //these two used to be inited to posAworld and posBworld (respectively) but it does not seem necessary
- if (bodyA)
- rel_pos1 = posAworld - bodyA->getWorldTransform().getOrigin();
- if (bodyB)
- rel_pos2 = posBworld - bodyB->getWorldTransform().getOrigin();
-
- if (multiBodyA)
- {
- if (solverConstraint.m_linkA<0)
- {
- rel_pos1 = posAworld - multiBodyA->getBasePos();
- } else
- {
- rel_pos1 = posAworld - multiBodyA->getLink(solverConstraint.m_linkA).m_cachedWorldTransform.getOrigin();
- }
-
- const int ndofA = multiBodyA->getNumDofs() + 6;
-
- solverConstraint.m_deltaVelAindex = multiBodyA->getCompanionId();
-
- if (solverConstraint.m_deltaVelAindex <0)
- {
- solverConstraint.m_deltaVelAindex = data.m_deltaVelocities.size();
- multiBodyA->setCompanionId(solverConstraint.m_deltaVelAindex);
- data.m_deltaVelocities.resize(data.m_deltaVelocities.size()+ndofA);
- } else
- {
- btAssert(data.m_deltaVelocities.size() >= solverConstraint.m_deltaVelAindex+ndofA);
- }
-
- //determine jacobian of this 1D constraint in terms of multibodyA's degrees of freedom
- //resize..
- solverConstraint.m_jacAindex = data.m_jacobians.size();
- data.m_jacobians.resize(data.m_jacobians.size()+ndofA);
- //copy/determine
- if(jacOrgA)
- {
- for (int i=0;i<ndofA;i++)
- data.m_jacobians[solverConstraint.m_jacAindex+i] = jacOrgA[i];
- }
- else
- {
- btScalar* jac1=&data.m_jacobians[solverConstraint.m_jacAindex];
- //multiBodyA->fillContactJacobianMultiDof(solverConstraint.m_linkA, posAworld, constraintNormalLin, jac1, data.scratch_r, data.scratch_v, data.scratch_m);
- multiBodyA->fillConstraintJacobianMultiDof(solverConstraint.m_linkA, posAworld, constraintNormalAng, constraintNormalLin, jac1, data.scratch_r, data.scratch_v, data.scratch_m);
- }
-
- //determine the velocity response of multibodyA to reaction impulses of this constraint (i.e. A[i,i] for i=1,...n_con: multibody's inverse inertia with respect to this 1D constraint)
- //resize..
- data.m_deltaVelocitiesUnitImpulse.resize(data.m_deltaVelocitiesUnitImpulse.size()+ndofA); //=> each constraint row has the constrained tree dofs allocated in m_deltaVelocitiesUnitImpulse
- btAssert(data.m_jacobians.size() == data.m_deltaVelocitiesUnitImpulse.size());
- btScalar* delta = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
- //determine..
- multiBodyA->calcAccelerationDeltasMultiDof(&data.m_jacobians[solverConstraint.m_jacAindex],delta,data.scratch_r, data.scratch_v);
-
- btVector3 torqueAxis0;
- if (angConstraint) {
- torqueAxis0 = constraintNormalAng;
- }
- else {
- torqueAxis0 = rel_pos1.cross(constraintNormalLin);
-
- }
- solverConstraint.m_relpos1CrossNormal = torqueAxis0;
- solverConstraint.m_contactNormal1 = constraintNormalLin;
- }
- else //if(rb0)
- {
- btVector3 torqueAxis0;
- if (angConstraint) {
- torqueAxis0 = constraintNormalAng;
- }
- else {
- torqueAxis0 = rel_pos1.cross(constraintNormalLin);
- }
- solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld()*torqueAxis0*rb0->getAngularFactor() : btVector3(0,0,0);
- solverConstraint.m_relpos1CrossNormal = torqueAxis0;
- solverConstraint.m_contactNormal1 = constraintNormalLin;
- }
-
- if (multiBodyB)
- {
- if (solverConstraint.m_linkB<0)
- {
- rel_pos2 = posBworld - multiBodyB->getBasePos();
- } else
- {
- rel_pos2 = posBworld - multiBodyB->getLink(solverConstraint.m_linkB).m_cachedWorldTransform.getOrigin();
- }
-
- const int ndofB = multiBodyB->getNumDofs() + 6;
-
- solverConstraint.m_deltaVelBindex = multiBodyB->getCompanionId();
- if (solverConstraint.m_deltaVelBindex <0)
- {
- solverConstraint.m_deltaVelBindex = data.m_deltaVelocities.size();
- multiBodyB->setCompanionId(solverConstraint.m_deltaVelBindex);
- data.m_deltaVelocities.resize(data.m_deltaVelocities.size()+ndofB);
- }
-
- //determine jacobian of this 1D constraint in terms of multibodyB's degrees of freedom
- //resize..
- solverConstraint.m_jacBindex = data.m_jacobians.size();
- data.m_jacobians.resize(data.m_jacobians.size()+ndofB);
- //copy/determine..
- if(jacOrgB)
- {
- for (int i=0;i<ndofB;i++)
- data.m_jacobians[solverConstraint.m_jacBindex+i] = jacOrgB[i];
- }
- else
- {
- //multiBodyB->fillContactJacobianMultiDof(solverConstraint.m_linkB, posBworld, -constraintNormalLin, &data.m_jacobians[solverConstraint.m_jacBindex], data.scratch_r, data.scratch_v, data.scratch_m);
- multiBodyB->fillConstraintJacobianMultiDof(solverConstraint.m_linkB, posBworld, -constraintNormalAng, -constraintNormalLin, &data.m_jacobians[solverConstraint.m_jacBindex], data.scratch_r, data.scratch_v, data.scratch_m);
- }
-
- //determine velocity response of multibodyB to reaction impulses of this constraint (i.e. A[i,i] for i=1,...n_con: multibody's inverse inertia with respect to this 1D constraint)
- //resize..
- data.m_deltaVelocitiesUnitImpulse.resize(data.m_deltaVelocitiesUnitImpulse.size()+ndofB);
- btAssert(data.m_jacobians.size() == data.m_deltaVelocitiesUnitImpulse.size());
- btScalar* delta = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
- //determine..
- multiBodyB->calcAccelerationDeltasMultiDof(&data.m_jacobians[solverConstraint.m_jacBindex],delta,data.scratch_r, data.scratch_v);
-
- btVector3 torqueAxis1;
- if (angConstraint) {
- torqueAxis1 = constraintNormalAng;
- }
- else {
- torqueAxis1 = rel_pos2.cross(constraintNormalLin);
- }
- solverConstraint.m_relpos2CrossNormal = -torqueAxis1;
- solverConstraint.m_contactNormal2 = -constraintNormalLin;
- }
- else //if(rb1)
- {
- btVector3 torqueAxis1;
- if (angConstraint) {
- torqueAxis1 = constraintNormalAng;
- }
- else {
- torqueAxis1 = rel_pos2.cross(constraintNormalLin);
- }
- solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld()*-torqueAxis1*rb1->getAngularFactor() : btVector3(0,0,0);
- solverConstraint.m_relpos2CrossNormal = -torqueAxis1;
- solverConstraint.m_contactNormal2 = -constraintNormalLin;
- }
- {
-
- btVector3 vec;
- btScalar denom0 = 0.f;
- btScalar denom1 = 0.f;
- btScalar* jacB = 0;
- btScalar* jacA = 0;
- btScalar* deltaVelA = 0;
- btScalar* deltaVelB = 0;
- int ndofA = 0;
- //determine the "effective mass" of the constrained multibodyA with respect to this 1D constraint (i.e. 1/A[i,i])
- if (multiBodyA)
- {
- ndofA = multiBodyA->getNumDofs() + 6;
- jacA = &data.m_jacobians[solverConstraint.m_jacAindex];
- deltaVelA = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
- for (int i = 0; i < ndofA; ++i)
- {
- btScalar j = jacA[i] ;
- btScalar l = deltaVelA[i];
- denom0 += j*l;
- }
- }
- else if(rb0)
- {
- vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1);
- if (angConstraint) {
+ solverConstraint.m_multiBodyA = m_bodyA;
+ solverConstraint.m_multiBodyB = m_bodyB;
+ solverConstraint.m_linkA = m_linkA;
+ solverConstraint.m_linkB = m_linkB;
+
+ btMultiBody* multiBodyA = solverConstraint.m_multiBodyA;
+ btMultiBody* multiBodyB = solverConstraint.m_multiBodyB;
+
+ btSolverBody* bodyA = multiBodyA ? 0 : &data.m_solverBodyPool->at(solverConstraint.m_solverBodyIdA);
+ btSolverBody* bodyB = multiBodyB ? 0 : &data.m_solverBodyPool->at(solverConstraint.m_solverBodyIdB);
+
+ btRigidBody* rb0 = multiBodyA ? 0 : bodyA->m_originalBody;
+ btRigidBody* rb1 = multiBodyB ? 0 : bodyB->m_originalBody;
+
+ btVector3 rel_pos1, rel_pos2; //these two used to be inited to posAworld and posBworld (respectively) but it does not seem necessary
+ if (bodyA)
+ rel_pos1 = posAworld - bodyA->getWorldTransform().getOrigin();
+ if (bodyB)
+ rel_pos2 = posBworld - bodyB->getWorldTransform().getOrigin();
+
+ if (multiBodyA)
+ {
+ if (solverConstraint.m_linkA < 0)
+ {
+ rel_pos1 = posAworld - multiBodyA->getBasePos();
+ }
+ else
+ {
+ rel_pos1 = posAworld - multiBodyA->getLink(solverConstraint.m_linkA).m_cachedWorldTransform.getOrigin();
+ }
+
+ const int ndofA = multiBodyA->getNumDofs() + 6;
+
+ solverConstraint.m_deltaVelAindex = multiBodyA->getCompanionId();
+
+ if (solverConstraint.m_deltaVelAindex < 0)
+ {
+ solverConstraint.m_deltaVelAindex = data.m_deltaVelocities.size();
+ multiBodyA->setCompanionId(solverConstraint.m_deltaVelAindex);
+ data.m_deltaVelocities.resize(data.m_deltaVelocities.size() + ndofA);
+ }
+ else
+ {
+ btAssert(data.m_deltaVelocities.size() >= solverConstraint.m_deltaVelAindex + ndofA);
+ }
+
+ //determine jacobian of this 1D constraint in terms of multibodyA's degrees of freedom
+ //resize..
+ solverConstraint.m_jacAindex = data.m_jacobians.size();
+ data.m_jacobians.resize(data.m_jacobians.size() + ndofA);
+ //copy/determine
+ if (jacOrgA)
+ {
+ for (int i = 0; i < ndofA; i++)
+ data.m_jacobians[solverConstraint.m_jacAindex + i] = jacOrgA[i];
+ }
+ else
+ {
+ btScalar* jac1 = &data.m_jacobians[solverConstraint.m_jacAindex];
+ //multiBodyA->fillContactJacobianMultiDof(solverConstraint.m_linkA, posAworld, constraintNormalLin, jac1, data.scratch_r, data.scratch_v, data.scratch_m);
+ multiBodyA->fillConstraintJacobianMultiDof(solverConstraint.m_linkA, posAworld, constraintNormalAng, constraintNormalLin, jac1, data.scratch_r, data.scratch_v, data.scratch_m);
+ }
+
+ //determine the velocity response of multibodyA to reaction impulses of this constraint (i.e. A[i,i] for i=1,...n_con: multibody's inverse inertia with respect to this 1D constraint)
+ //resize..
+ data.m_deltaVelocitiesUnitImpulse.resize(data.m_deltaVelocitiesUnitImpulse.size() + ndofA); //=> each constraint row has the constrained tree dofs allocated in m_deltaVelocitiesUnitImpulse
+ btAssert(data.m_jacobians.size() == data.m_deltaVelocitiesUnitImpulse.size());
+ btScalar* delta = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
+ //determine..
+ multiBodyA->calcAccelerationDeltasMultiDof(&data.m_jacobians[solverConstraint.m_jacAindex], delta, data.scratch_r, data.scratch_v);
+
+ btVector3 torqueAxis0;
+ if (angConstraint)
+ {
+ torqueAxis0 = constraintNormalAng;
+ }
+ else
+ {
+ torqueAxis0 = rel_pos1.cross(constraintNormalLin);
+ }
+ solverConstraint.m_relpos1CrossNormal = torqueAxis0;
+ solverConstraint.m_contactNormal1 = constraintNormalLin;
+ }
+ else //if(rb0)
+ {
+ btVector3 torqueAxis0;
+ if (angConstraint)
+ {
+ torqueAxis0 = constraintNormalAng;
+ }
+ else
+ {
+ torqueAxis0 = rel_pos1.cross(constraintNormalLin);
+ }
+ solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld() * torqueAxis0 * rb0->getAngularFactor() : btVector3(0, 0, 0);
+ solverConstraint.m_relpos1CrossNormal = torqueAxis0;
+ solverConstraint.m_contactNormal1 = constraintNormalLin;
+ }
+
+ if (multiBodyB)
+ {
+ if (solverConstraint.m_linkB < 0)
+ {
+ rel_pos2 = posBworld - multiBodyB->getBasePos();
+ }
+ else
+ {
+ rel_pos2 = posBworld - multiBodyB->getLink(solverConstraint.m_linkB).m_cachedWorldTransform.getOrigin();
+ }
+
+ const int ndofB = multiBodyB->getNumDofs() + 6;
+
+ solverConstraint.m_deltaVelBindex = multiBodyB->getCompanionId();
+ if (solverConstraint.m_deltaVelBindex < 0)
+ {
+ solverConstraint.m_deltaVelBindex = data.m_deltaVelocities.size();
+ multiBodyB->setCompanionId(solverConstraint.m_deltaVelBindex);
+ data.m_deltaVelocities.resize(data.m_deltaVelocities.size() + ndofB);
+ }
+
+ //determine jacobian of this 1D constraint in terms of multibodyB's degrees of freedom
+ //resize..
+ solverConstraint.m_jacBindex = data.m_jacobians.size();
+ data.m_jacobians.resize(data.m_jacobians.size() + ndofB);
+ //copy/determine..
+ if (jacOrgB)
+ {
+ for (int i = 0; i < ndofB; i++)
+ data.m_jacobians[solverConstraint.m_jacBindex + i] = jacOrgB[i];
+ }
+ else
+ {
+ //multiBodyB->fillContactJacobianMultiDof(solverConstraint.m_linkB, posBworld, -constraintNormalLin, &data.m_jacobians[solverConstraint.m_jacBindex], data.scratch_r, data.scratch_v, data.scratch_m);
+ multiBodyB->fillConstraintJacobianMultiDof(solverConstraint.m_linkB, posBworld, -constraintNormalAng, -constraintNormalLin, &data.m_jacobians[solverConstraint.m_jacBindex], data.scratch_r, data.scratch_v, data.scratch_m);
+ }
+
+ //determine velocity response of multibodyB to reaction impulses of this constraint (i.e. A[i,i] for i=1,...n_con: multibody's inverse inertia with respect to this 1D constraint)
+ //resize..
+ data.m_deltaVelocitiesUnitImpulse.resize(data.m_deltaVelocitiesUnitImpulse.size() + ndofB);
+ btAssert(data.m_jacobians.size() == data.m_deltaVelocitiesUnitImpulse.size());
+ btScalar* delta = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
+ //determine..
+ multiBodyB->calcAccelerationDeltasMultiDof(&data.m_jacobians[solverConstraint.m_jacBindex], delta, data.scratch_r, data.scratch_v);
+
+ btVector3 torqueAxis1;
+ if (angConstraint)
+ {
+ torqueAxis1 = constraintNormalAng;
+ }
+ else
+ {
+ torqueAxis1 = rel_pos2.cross(constraintNormalLin);
+ }
+ solverConstraint.m_relpos2CrossNormal = -torqueAxis1;
+ solverConstraint.m_contactNormal2 = -constraintNormalLin;
+ }
+ else //if(rb1)
+ {
+ btVector3 torqueAxis1;
+ if (angConstraint)
+ {
+ torqueAxis1 = constraintNormalAng;
+ }
+ else
+ {
+ torqueAxis1 = rel_pos2.cross(constraintNormalLin);
+ }
+ solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld() * -torqueAxis1 * rb1->getAngularFactor() : btVector3(0, 0, 0);
+ solverConstraint.m_relpos2CrossNormal = -torqueAxis1;
+ solverConstraint.m_contactNormal2 = -constraintNormalLin;
+ }
+ {
+ btVector3 vec;
+ btScalar denom0 = 0.f;
+ btScalar denom1 = 0.f;
+ btScalar* jacB = 0;
+ btScalar* jacA = 0;
+ btScalar* deltaVelA = 0;
+ btScalar* deltaVelB = 0;
+ int ndofA = 0;
+ //determine the "effective mass" of the constrained multibodyA with respect to this 1D constraint (i.e. 1/A[i,i])
+ if (multiBodyA)
+ {
+ ndofA = multiBodyA->getNumDofs() + 6;
+ jacA = &data.m_jacobians[solverConstraint.m_jacAindex];
+ deltaVelA = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
+ for (int i = 0; i < ndofA; ++i)
+ {
+ btScalar j = jacA[i];
+ btScalar l = deltaVelA[i];
+ denom0 += j * l;
+ }
+ }
+ else if (rb0)
+ {
+ vec = (solverConstraint.m_angularComponentA).cross(rel_pos1);
+ if (angConstraint)
+ {
denom0 = constraintNormalAng.dot(solverConstraint.m_angularComponentA);
- }
- else {
- denom0 = rb0->getInvMass() + constraintNormalLin.dot(vec);
- }
- }
- //
- if (multiBodyB)
- {
- const int ndofB = multiBodyB->getNumDofs() + 6;
- jacB = &data.m_jacobians[solverConstraint.m_jacBindex];
- deltaVelB = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
- for (int i = 0; i < ndofB; ++i)
- {
- btScalar j = jacB[i] ;
- btScalar l = deltaVelB[i];
- denom1 += j*l;
- }
-
- }
- else if(rb1)
- {
- vec = ( -solverConstraint.m_angularComponentB).cross(rel_pos2);
- if (angConstraint) {
+ }
+ else
+ {
+ denom0 = rb0->getInvMass() + constraintNormalLin.dot(vec);
+ }
+ }
+ //
+ if (multiBodyB)
+ {
+ const int ndofB = multiBodyB->getNumDofs() + 6;
+ jacB = &data.m_jacobians[solverConstraint.m_jacBindex];
+ deltaVelB = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
+ for (int i = 0; i < ndofB; ++i)
+ {
+ btScalar j = jacB[i];
+ btScalar l = deltaVelB[i];
+ denom1 += j * l;
+ }
+ }
+ else if (rb1)
+ {
+ vec = (-solverConstraint.m_angularComponentB).cross(rel_pos2);
+ if (angConstraint)
+ {
denom1 = constraintNormalAng.dot(-solverConstraint.m_angularComponentB);
- }
- else {
- denom1 = rb1->getInvMass() + constraintNormalLin.dot(vec);
- }
- }
-
- //
- btScalar d = denom0+denom1;
- if (d>SIMD_EPSILON)
- {
- solverConstraint.m_jacDiagABInv = relaxation/(d);
- }
- else
- {
- //disable the constraint row to handle singularity/redundant constraint
- solverConstraint.m_jacDiagABInv = 0.f;
- }
- }
-
-
- //compute rhs and remaining solverConstraint fields
- btScalar penetration = isFriction? 0 : posError;
-
- btScalar rel_vel = 0.f;
- int ndofA = 0;
- int ndofB = 0;
- {
- btVector3 vel1,vel2;
- if (multiBodyA)
- {
- ndofA = multiBodyA->getNumDofs() + 6;
- btScalar* jacA = &data.m_jacobians[solverConstraint.m_jacAindex];
- for (int i = 0; i < ndofA ; ++i)
- rel_vel += multiBodyA->getVelocityVector()[i] * jacA[i];
- }
- else if(rb0)
- {
+ }
+ else
+ {
+ denom1 = rb1->getInvMass() + constraintNormalLin.dot(vec);
+ }
+ }
+
+ //
+ btScalar d = denom0 + denom1;
+ if (d > SIMD_EPSILON)
+ {
+ solverConstraint.m_jacDiagABInv = relaxation / (d);
+ }
+ else
+ {
+ //disable the constraint row to handle singularity/redundant constraint
+ solverConstraint.m_jacDiagABInv = 0.f;
+ }
+ }
+
+ //compute rhs and remaining solverConstraint fields
+ btScalar penetration = isFriction ? 0 : posError;
+
+ btScalar rel_vel = 0.f;
+ int ndofA = 0;
+ int ndofB = 0;
+ {
+ btVector3 vel1, vel2;
+ if (multiBodyA)
+ {
+ ndofA = multiBodyA->getNumDofs() + 6;
+ btScalar* jacA = &data.m_jacobians[solverConstraint.m_jacAindex];
+ for (int i = 0; i < ndofA; ++i)
+ rel_vel += multiBodyA->getVelocityVector()[i] * jacA[i];
+ }
+ else if (rb0)
+ {
rel_vel += rb0->getLinearVelocity().dot(solverConstraint.m_contactNormal1);
rel_vel += rb0->getAngularVelocity().dot(solverConstraint.m_relpos1CrossNormal);
- }
- if (multiBodyB)
- {
- ndofB = multiBodyB->getNumDofs() + 6;
- btScalar* jacB = &data.m_jacobians[solverConstraint.m_jacBindex];
- for (int i = 0; i < ndofB ; ++i)
- rel_vel += multiBodyB->getVelocityVector()[i] * jacB[i];
-
- }
- else if(rb1)
- {
+ }
+ if (multiBodyB)
+ {
+ ndofB = multiBodyB->getNumDofs() + 6;
+ btScalar* jacB = &data.m_jacobians[solverConstraint.m_jacBindex];
+ for (int i = 0; i < ndofB; ++i)
+ rel_vel += multiBodyB->getVelocityVector()[i] * jacB[i];
+ }
+ else if (rb1)
+ {
rel_vel += rb1->getLinearVelocity().dot(solverConstraint.m_contactNormal2);
rel_vel += rb1->getAngularVelocity().dot(solverConstraint.m_relpos2CrossNormal);
- }
-
- solverConstraint.m_friction = 0.f;//cp.m_combinedFriction;
- }
-
-
- ///warm starting (or zero if disabled)
- /*
+ }
+
+ solverConstraint.m_friction = 0.f; //cp.m_combinedFriction;
+ }
+
+ ///warm starting (or zero if disabled)
+ /*
if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
{
solverConstraint.m_appliedImpulse = isFriction ? 0 : cp.m_appliedImpulse * infoGlobal.m_warmstartingFactor;
@@ -369,38 +375,35 @@ btScalar btMultiBodyConstraint::fillMultiBodyConstraint( btMultiBodySolverConstr
}
} else
*/
-
- solverConstraint.m_appliedImpulse = 0.f;
- solverConstraint.m_appliedPushImpulse = 0.f;
-
- {
-
- btScalar positionalError = 0.f;
- btScalar velocityError = desiredVelocity - rel_vel;// * damping;
-
-
- btScalar erp = infoGlobal.m_erp2;
-
+
+ solverConstraint.m_appliedImpulse = 0.f;
+ solverConstraint.m_appliedPushImpulse = 0.f;
+
+ {
+ btScalar positionalError = 0.f;
+ btScalar velocityError = desiredVelocity - rel_vel; // * damping;
+
+ btScalar erp = infoGlobal.m_erp2;
+
//split impulse is not implemented yet for btMultiBody*
//if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
- {
- erp = infoGlobal.m_erp;
- }
-
- positionalError = -penetration * erp/infoGlobal.m_timeStep;
-
- btScalar penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv;
- btScalar velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv;
-
+ {
+ erp = infoGlobal.m_erp;
+ }
+
+ positionalError = -penetration * erp / infoGlobal.m_timeStep;
+
+ btScalar penetrationImpulse = positionalError * solverConstraint.m_jacDiagABInv;
+ btScalar velocityImpulse = velocityError * solverConstraint.m_jacDiagABInv;
+
//split impulse is not implemented yet for btMultiBody*
- // if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
- {
- //combine position and velocity into rhs
- solverConstraint.m_rhs = penetrationImpulse+velocityImpulse;
- solverConstraint.m_rhsPenetration = 0.f;
-
- }
+ // if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
+ {
+ //combine position and velocity into rhs
+ solverConstraint.m_rhs = penetrationImpulse + velocityImpulse;
+ solverConstraint.m_rhsPenetration = 0.f;
+ }
/*else
{
//split position and velocity into rhs and m_rhsPenetration
@@ -409,11 +412,10 @@ btScalar btMultiBodyConstraint::fillMultiBodyConstraint( btMultiBodySolverConstr
}
*/
- solverConstraint.m_cfm = 0.f;
- solverConstraint.m_lowerLimit = lowerLimit;
- solverConstraint.m_upperLimit = upperLimit;
- }
-
- return rel_vel;
-
+ solverConstraint.m_cfm = 0.f;
+ solverConstraint.m_lowerLimit = lowerLimit;
+ solverConstraint.m_upperLimit = upperLimit;
+ }
+
+ return rel_vel;
}
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraint.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraint.h
index a2ae571273..5c15f3e851 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraint.h
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraint.h
@@ -27,66 +27,62 @@ struct btSolverInfo;
struct btMultiBodyJacobianData
{
- btAlignedObjectArray<btScalar> m_jacobians;
- btAlignedObjectArray<btScalar> m_deltaVelocitiesUnitImpulse; //holds the joint-space response of the corresp. tree to the test impulse in each constraint space dimension
- btAlignedObjectArray<btScalar> m_deltaVelocities; //holds joint-space vectors of all the constrained trees accumulating the effect of corrective impulses applied in SI
- btAlignedObjectArray<btScalar> scratch_r;
- btAlignedObjectArray<btVector3> scratch_v;
- btAlignedObjectArray<btMatrix3x3> scratch_m;
- btAlignedObjectArray<btSolverBody>* m_solverBodyPool;
- int m_fixedBodyId;
-
+ btAlignedObjectArray<btScalar> m_jacobians;
+ btAlignedObjectArray<btScalar> m_deltaVelocitiesUnitImpulse; //holds the joint-space response of the corresp. tree to the test impulse in each constraint space dimension
+ btAlignedObjectArray<btScalar> m_deltaVelocities; //holds joint-space vectors of all the constrained trees accumulating the effect of corrective impulses applied in SI
+ btAlignedObjectArray<btScalar> scratch_r;
+ btAlignedObjectArray<btVector3> scratch_v;
+ btAlignedObjectArray<btMatrix3x3> scratch_m;
+ btAlignedObjectArray<btSolverBody>* m_solverBodyPool;
+ int m_fixedBodyId;
};
-
-ATTRIBUTE_ALIGNED16(class) btMultiBodyConstraint
+ATTRIBUTE_ALIGNED16(class)
+btMultiBodyConstraint
{
protected:
-
- btMultiBody* m_bodyA;
- btMultiBody* m_bodyB;
- int m_linkA;
- int m_linkB;
-
- int m_numRows;
- int m_jacSizeA;
- int m_jacSizeBoth;
- int m_posOffset;
-
- bool m_isUnilateral;
- int m_numDofsFinalized;
- btScalar m_maxAppliedImpulse;
-
-
- // warning: the data block lay out is not consistent for all constraints
- // data block laid out as follows:
- // cached impulses. (one per row.)
- // jacobians. (interleaved, row1 body1 then row1 body2 then row2 body 1 etc)
- // positions. (one per row.)
- btAlignedObjectArray<btScalar> m_data;
-
- void applyDeltaVee(btMultiBodyJacobianData& data, btScalar* delta_vee, btScalar impulse, int velocityIndex, int ndof);
-
- btScalar fillMultiBodyConstraint(btMultiBodySolverConstraint& solverConstraint,
- btMultiBodyJacobianData& data,
- btScalar* jacOrgA, btScalar* jacOrgB,
- const btVector3& constraintNormalAng,
-
- const btVector3& constraintNormalLin,
- const btVector3& posAworld, const btVector3& posBworld,
- btScalar posError,
- const btContactSolverInfo& infoGlobal,
- btScalar lowerLimit, btScalar upperLimit,
- bool angConstraint = false,
-
- btScalar relaxation = 1.f,
- bool isFriction = false, btScalar desiredVelocity=0, btScalar cfmSlip=0);
+ btMultiBody* m_bodyA;
+ btMultiBody* m_bodyB;
+ int m_linkA;
+ int m_linkB;
+
+ int m_numRows;
+ int m_jacSizeA;
+ int m_jacSizeBoth;
+ int m_posOffset;
+
+ bool m_isUnilateral;
+ int m_numDofsFinalized;
+ btScalar m_maxAppliedImpulse;
+
+ // warning: the data block lay out is not consistent for all constraints
+ // data block laid out as follows:
+ // cached impulses. (one per row.)
+ // jacobians. (interleaved, row1 body1 then row1 body2 then row2 body 1 etc)
+ // positions. (one per row.)
+ btAlignedObjectArray<btScalar> m_data;
+
+ void applyDeltaVee(btMultiBodyJacobianData & data, btScalar * delta_vee, btScalar impulse, int velocityIndex, int ndof);
+
+ btScalar fillMultiBodyConstraint(btMultiBodySolverConstraint & solverConstraint,
+ btMultiBodyJacobianData & data,
+ btScalar * jacOrgA, btScalar * jacOrgB,
+ const btVector3& constraintNormalAng,
+
+ const btVector3& constraintNormalLin,
+ const btVector3& posAworld, const btVector3& posBworld,
+ btScalar posError,
+ const btContactSolverInfo& infoGlobal,
+ btScalar lowerLimit, btScalar upperLimit,
+ bool angConstraint = false,
+
+ btScalar relaxation = 1.f,
+ bool isFriction = false, btScalar desiredVelocity = 0, btScalar cfmSlip = 0);
public:
-
BT_DECLARE_ALIGNED_ALLOCATOR();
- btMultiBodyConstraint(btMultiBody* bodyA,btMultiBody* bodyB,int linkA, int linkB, int numRows, bool isUnilateral);
+ btMultiBodyConstraint(btMultiBody * bodyA, btMultiBody * bodyB, int linkA, int linkB, int numRows, bool isUnilateral);
virtual ~btMultiBodyConstraint();
void updateJacobianSizes();
@@ -94,27 +90,27 @@ public:
//many constraints have setFrameInB/setPivotInB. Will use 'getConstraintType' later.
virtual void setFrameInB(const btMatrix3x3& frameInB) {}
- virtual void setPivotInB(const btVector3& pivotInB){}
+ virtual void setPivotInB(const btVector3& pivotInB) {}
- virtual void finalizeMultiDof()=0;
+ virtual void finalizeMultiDof() = 0;
- virtual int getIslandIdA() const =0;
- virtual int getIslandIdB() const =0;
+ virtual int getIslandIdA() const = 0;
+ virtual int getIslandIdB() const = 0;
- virtual void createConstraintRows(btMultiBodyConstraintArray& constraintRows,
- btMultiBodyJacobianData& data,
- const btContactSolverInfo& infoGlobal)=0;
+ virtual void createConstraintRows(btMultiBodyConstraintArray & constraintRows,
+ btMultiBodyJacobianData & data,
+ const btContactSolverInfo& infoGlobal) = 0;
- int getNumRows() const
+ int getNumRows() const
{
return m_numRows;
}
- btMultiBody* getMultiBodyA()
+ btMultiBody* getMultiBodyA()
{
return m_bodyA;
}
- btMultiBody* getMultiBodyB()
+ btMultiBody* getMultiBodyB()
{
return m_bodyB;
}
@@ -127,77 +123,72 @@ public:
{
return m_linkB;
}
- void internalSetAppliedImpulse(int dof, btScalar appliedImpulse)
+ void internalSetAppliedImpulse(int dof, btScalar appliedImpulse)
{
- btAssert(dof>=0);
+ btAssert(dof >= 0);
btAssert(dof < getNumRows());
m_data[dof] = appliedImpulse;
-
}
-
- btScalar getAppliedImpulse(int dof)
+
+ btScalar getAppliedImpulse(int dof)
{
- btAssert(dof>=0);
+ btAssert(dof >= 0);
btAssert(dof < getNumRows());
return m_data[dof];
}
// current constraint position
- // constraint is pos >= 0 for unilateral, or pos = 0 for bilateral
- // NOTE: ignored position for friction rows.
- btScalar getPosition(int row) const
+ // constraint is pos >= 0 for unilateral, or pos = 0 for bilateral
+ // NOTE: ignored position for friction rows.
+ btScalar getPosition(int row) const
{
return m_data[m_posOffset + row];
}
- void setPosition(int row, btScalar pos)
+ void setPosition(int row, btScalar pos)
{
m_data[m_posOffset + row] = pos;
}
-
bool isUnilateral() const
{
return m_isUnilateral;
}
// jacobian blocks.
- // each of size 6 + num_links. (jacobian2 is null if no body2.)
- // format: 3 'omega' coefficients, 3 'v' coefficients, then the 'qdot' coefficients.
- btScalar* jacobianA(int row)
+ // each of size 6 + num_links. (jacobian2 is null if no body2.)
+ // format: 3 'omega' coefficients, 3 'v' coefficients, then the 'qdot' coefficients.
+ btScalar* jacobianA(int row)
{
return &m_data[m_numRows + row * m_jacSizeBoth];
}
- const btScalar* jacobianA(int row) const
+ const btScalar* jacobianA(int row) const
{
return &m_data[m_numRows + (row * m_jacSizeBoth)];
}
- btScalar* jacobianB(int row)
+ btScalar* jacobianB(int row)
{
return &m_data[m_numRows + (row * m_jacSizeBoth) + m_jacSizeA];
}
- const btScalar* jacobianB(int row) const
+ const btScalar* jacobianB(int row) const
{
return &m_data[m_numRows + (row * m_jacSizeBoth) + m_jacSizeA];
}
- btScalar getMaxAppliedImpulse() const
+ btScalar getMaxAppliedImpulse() const
{
return m_maxAppliedImpulse;
}
- void setMaxAppliedImpulse(btScalar maxImp)
+ void setMaxAppliedImpulse(btScalar maxImp)
{
m_maxAppliedImpulse = maxImp;
}
- virtual void debugDraw(class btIDebugDraw* drawer)=0;
+ virtual void debugDraw(class btIDebugDraw * drawer) = 0;
virtual void setGearRatio(btScalar ratio) {}
virtual void setGearAuxLink(int gearAuxLink) {}
- virtual void setRelativePositionTarget(btScalar relPosTarget){}
- virtual void setErp(btScalar erp){}
-
-
+ virtual void setRelativePositionTarget(btScalar relPosTarget) {}
+ virtual void setErp(btScalar erp) {}
};
-#endif //BT_MULTIBODY_CONSTRAINT_H
-
+#endif //BT_MULTIBODY_CONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp
index cd84826e1a..e97bd71cc4 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp
@@ -13,7 +13,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#include "btMultiBodyConstraintSolver.h"
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
#include "btMultiBodyLinkCollider.h"
@@ -24,33 +23,33 @@ subject to the following restrictions:
#include "LinearMath/btQuickprof.h"
-btScalar btMultiBodyConstraintSolver::solveSingleIteration(int iteration, btCollisionObject** bodies ,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer)
+btScalar btMultiBodyConstraintSolver::solveSingleIteration(int iteration, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
{
- btScalar leastSquaredResidual = btSequentialImpulseConstraintSolver::solveSingleIteration(iteration, bodies ,numBodies,manifoldPtr, numManifolds,constraints,numConstraints,infoGlobal,debugDrawer);
-
+ btScalar leastSquaredResidual = btSequentialImpulseConstraintSolver::solveSingleIteration(iteration, bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
+
//solve featherstone non-contact constraints
//printf("m_multiBodyNonContactConstraints = %d\n",m_multiBodyNonContactConstraints.size());
- for (int j=0;j<m_multiBodyNonContactConstraints.size();j++)
+ for (int j = 0; j < m_multiBodyNonContactConstraints.size(); j++)
{
- int index = iteration&1? j : m_multiBodyNonContactConstraints.size()-1-j;
+ int index = iteration & 1 ? j : m_multiBodyNonContactConstraints.size() - 1 - j;
btMultiBodySolverConstraint& constraint = m_multiBodyNonContactConstraints[index];
-
+
btScalar residual = resolveSingleConstraintRowGeneric(constraint);
- leastSquaredResidual = btMax(leastSquaredResidual,residual*residual);
+ leastSquaredResidual = btMax(leastSquaredResidual, residual * residual);
- if(constraint.m_multiBodyA)
+ if (constraint.m_multiBodyA)
constraint.m_multiBodyA->setPosUpdated(false);
- if(constraint.m_multiBodyB)
+ if (constraint.m_multiBodyB)
constraint.m_multiBodyB->setPosUpdated(false);
}
//solve featherstone normal contact
- for (int j0=0;j0<m_multiBodyNormalContactConstraints.size();j0++)
+ for (int j0 = 0; j0 < m_multiBodyNormalContactConstraints.size(); j0++)
{
- int index = j0;//iteration&1? j0 : m_multiBodyNormalContactConstraints.size()-1-j0;
+ int index = j0; //iteration&1? j0 : m_multiBodyNormalContactConstraints.size()-1-j0;
btMultiBodySolverConstraint& constraint = m_multiBodyNormalContactConstraints[index];
btScalar residual = 0.f;
@@ -60,32 +59,32 @@ btScalar btMultiBodyConstraintSolver::solveSingleIteration(int iteration, btColl
residual = resolveSingleConstraintRowGeneric(constraint);
}
- leastSquaredResidual = btMax(leastSquaredResidual,residual*residual);
-
- if(constraint.m_multiBodyA)
+ leastSquaredResidual = btMax(leastSquaredResidual, residual * residual);
+
+ if (constraint.m_multiBodyA)
constraint.m_multiBodyA->setPosUpdated(false);
- if(constraint.m_multiBodyB)
+ if (constraint.m_multiBodyB)
constraint.m_multiBodyB->setPosUpdated(false);
}
//solve featherstone frictional contact
- if (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS && ((infoGlobal.m_solverMode&SOLVER_DISABLE_IMPLICIT_CONE_FRICTION) == 0))
+ if (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS && ((infoGlobal.m_solverMode & SOLVER_DISABLE_IMPLICIT_CONE_FRICTION) == 0))
{
- for (int j1 = 0; j1<this->m_multiBodyTorsionalFrictionContactConstraints.size(); j1++)
+ for (int j1 = 0; j1 < this->m_multiBodyTorsionalFrictionContactConstraints.size(); j1++)
{
if (iteration < infoGlobal.m_numIterations)
{
- int index = j1;//iteration&1? j1 : m_multiBodyTorsionalFrictionContactConstraints.size()-1-j1;
+ int index = j1; //iteration&1? j1 : m_multiBodyTorsionalFrictionContactConstraints.size()-1-j1;
btMultiBodySolverConstraint& frictionConstraint = m_multiBodyTorsionalFrictionContactConstraints[index];
btScalar totalImpulse = m_multiBodyNormalContactConstraints[frictionConstraint.m_frictionIndex].m_appliedImpulse;
//adjust friction limits here
- if (totalImpulse>btScalar(0))
+ if (totalImpulse > btScalar(0))
{
- frictionConstraint.m_lowerLimit = -(frictionConstraint.m_friction*totalImpulse);
- frictionConstraint.m_upperLimit = frictionConstraint.m_friction*totalImpulse;
+ frictionConstraint.m_lowerLimit = -(frictionConstraint.m_friction * totalImpulse);
+ frictionConstraint.m_upperLimit = frictionConstraint.m_friction * totalImpulse;
btScalar residual = resolveSingleConstraintRowGeneric(frictionConstraint);
- leastSquaredResidual = btMax(leastSquaredResidual , residual*residual);
+ leastSquaredResidual = btMax(leastSquaredResidual, residual * residual);
if (frictionConstraint.m_multiBodyA)
frictionConstraint.m_multiBodyA->setPosUpdated(false);
@@ -99,29 +98,29 @@ btScalar btMultiBodyConstraintSolver::solveSingleIteration(int iteration, btColl
{
if (iteration < infoGlobal.m_numIterations)
{
- int index = j1;//iteration&1? j1 : m_multiBodyFrictionContactConstraints.size()-1-j1;
+ int index = j1; //iteration&1? j1 : m_multiBodyFrictionContactConstraints.size()-1-j1;
btMultiBodySolverConstraint& frictionConstraint = m_multiBodyFrictionContactConstraints[index];
btScalar totalImpulse = m_multiBodyNormalContactConstraints[frictionConstraint.m_frictionIndex].m_appliedImpulse;
j1++;
- int index2 = j1;//iteration&1? j1 : m_multiBodyFrictionContactConstraints.size()-1-j1;
+ int index2 = j1; //iteration&1? j1 : m_multiBodyFrictionContactConstraints.size()-1-j1;
btMultiBodySolverConstraint& frictionConstraintB = m_multiBodyFrictionContactConstraints[index2];
btAssert(frictionConstraint.m_frictionIndex == frictionConstraintB.m_frictionIndex);
if (frictionConstraint.m_frictionIndex == frictionConstraintB.m_frictionIndex)
{
- frictionConstraint.m_lowerLimit = -(frictionConstraint.m_friction*totalImpulse);
- frictionConstraint.m_upperLimit = frictionConstraint.m_friction*totalImpulse;
- frictionConstraintB.m_lowerLimit = -(frictionConstraintB.m_friction*totalImpulse);
- frictionConstraintB.m_upperLimit = frictionConstraintB.m_friction*totalImpulse;
+ frictionConstraint.m_lowerLimit = -(frictionConstraint.m_friction * totalImpulse);
+ frictionConstraint.m_upperLimit = frictionConstraint.m_friction * totalImpulse;
+ frictionConstraintB.m_lowerLimit = -(frictionConstraintB.m_friction * totalImpulse);
+ frictionConstraintB.m_upperLimit = frictionConstraintB.m_friction * totalImpulse;
btScalar residual = resolveConeFrictionConstraintRows(frictionConstraint, frictionConstraintB);
- leastSquaredResidual = btMax(leastSquaredResidual, residual*residual);
-
+ leastSquaredResidual = btMax(leastSquaredResidual, residual * residual);
+
if (frictionConstraintB.m_multiBodyA)
frictionConstraintB.m_multiBodyA->setPosUpdated(false);
if (frictionConstraintB.m_multiBodyB)
frictionConstraintB.m_multiBodyB->setPosUpdated(false);
-
+
if (frictionConstraint.m_multiBodyA)
frictionConstraint.m_multiBodyA->setPosUpdated(false);
if (frictionConstraint.m_multiBodyB)
@@ -129,26 +128,24 @@ btScalar btMultiBodyConstraintSolver::solveSingleIteration(int iteration, btColl
}
}
}
-
-
}
else
{
- for (int j1 = 0; j1<this->m_multiBodyFrictionContactConstraints.size(); j1++)
+ for (int j1 = 0; j1 < this->m_multiBodyFrictionContactConstraints.size(); j1++)
{
if (iteration < infoGlobal.m_numIterations)
{
- int index = j1;//iteration&1? j1 : m_multiBodyFrictionContactConstraints.size()-1-j1;
+ int index = j1; //iteration&1? j1 : m_multiBodyFrictionContactConstraints.size()-1-j1;
btMultiBodySolverConstraint& frictionConstraint = m_multiBodyFrictionContactConstraints[index];
btScalar totalImpulse = m_multiBodyNormalContactConstraints[frictionConstraint.m_frictionIndex].m_appliedImpulse;
//adjust friction limits here
- if (totalImpulse>btScalar(0))
+ if (totalImpulse > btScalar(0))
{
- frictionConstraint.m_lowerLimit = -(frictionConstraint.m_friction*totalImpulse);
- frictionConstraint.m_upperLimit = frictionConstraint.m_friction*totalImpulse;
+ frictionConstraint.m_lowerLimit = -(frictionConstraint.m_friction * totalImpulse);
+ frictionConstraint.m_upperLimit = frictionConstraint.m_friction * totalImpulse;
btScalar residual = resolveSingleConstraintRowGeneric(frictionConstraint);
- leastSquaredResidual = btMax(leastSquaredResidual, residual*residual);
+ leastSquaredResidual = btMax(leastSquaredResidual, residual * residual);
if (frictionConstraint.m_multiBodyA)
frictionConstraint.m_multiBodyA->setPosUpdated(false);
@@ -161,18 +158,18 @@ btScalar btMultiBodyConstraintSolver::solveSingleIteration(int iteration, btColl
return leastSquaredResidual;
}
-btScalar btMultiBodyConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer)
+btScalar btMultiBodyConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
{
m_multiBodyNonContactConstraints.resize(0);
m_multiBodyNormalContactConstraints.resize(0);
m_multiBodyFrictionContactConstraints.resize(0);
m_multiBodyTorsionalFrictionContactConstraints.resize(0);
-
+
m_data.m_jacobians.resize(0);
m_data.m_deltaVelocitiesUnitImpulse.resize(0);
m_data.m_deltaVelocities.resize(0);
- for (int i=0;i<numBodies;i++)
+ for (int i = 0; i < numBodies; i++)
{
const btMultiBodyLinkCollider* fcA = btMultiBodyLinkCollider::upcast(bodies[i]);
if (fcA)
@@ -181,21 +178,20 @@ btScalar btMultiBodyConstraintSolver::solveGroupCacheFriendlySetup(btCollisionOb
}
}
- btScalar val = btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup( bodies,numBodies,manifoldPtr, numManifolds, constraints,numConstraints,infoGlobal,debugDrawer);
+ btScalar val = btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
return val;
}
-void btMultiBodyConstraintSolver::applyDeltaVee(btScalar* delta_vee, btScalar impulse, int velocityIndex, int ndof)
+void btMultiBodyConstraintSolver::applyDeltaVee(btScalar* delta_vee, btScalar impulse, int velocityIndex, int ndof)
{
- for (int i = 0; i < ndof; ++i)
- m_data.m_deltaVelocities[velocityIndex+i] += delta_vee[i] * impulse;
+ for (int i = 0; i < ndof; ++i)
+ m_data.m_deltaVelocities[velocityIndex + i] += delta_vee[i] * impulse;
}
btScalar btMultiBodyConstraintSolver::resolveSingleConstraintRowGeneric(const btMultiBodySolverConstraint& c)
{
-
- btScalar deltaImpulse = c.m_rhs - btScalar(c.m_appliedImpulse)*c.m_cfm;
+ btScalar deltaImpulse = c.m_rhs - btScalar(c.m_appliedImpulse) * c.m_cfm;
btScalar deltaVelADotn = 0;
btScalar deltaVelBDotn = 0;
btSolverBody* bodyA = 0;
@@ -227,9 +223,8 @@ btScalar btMultiBodyConstraintSolver::resolveSingleConstraintRowGeneric(const bt
deltaVelBDotn += c.m_contactNormal2.dot(bodyB->internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(bodyB->internalGetDeltaAngularVelocity());
}
-
- deltaImpulse -= deltaVelADotn*c.m_jacDiagABInv;//m_jacDiagABInv = 1./denom
- deltaImpulse -= deltaVelBDotn*c.m_jacDiagABInv;
+ deltaImpulse -= deltaVelADotn * c.m_jacDiagABInv; //m_jacDiagABInv = 1./denom
+ deltaImpulse -= deltaVelBDotn * c.m_jacDiagABInv;
const btScalar sum = btScalar(c.m_appliedImpulse) + deltaImpulse;
if (sum < c.m_lowerLimit)
@@ -246,7 +241,7 @@ btScalar btMultiBodyConstraintSolver::resolveSingleConstraintRowGeneric(const bt
{
c.m_appliedImpulse = sum;
}
-
+
if (c.m_multiBodyA)
{
applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacAindex], deltaImpulse, c.m_deltaVelAindex, ndofA);
@@ -254,12 +249,11 @@ btScalar btMultiBodyConstraintSolver::resolveSingleConstraintRowGeneric(const bt
//note: update of the actual velocities (below) in the multibody does not have to happen now since m_deltaVelocities can be applied after all iterations
//it would make the multibody solver more like the regular one with m_deltaVelocities being equivalent to btSolverBody::m_deltaLinearVelocity/m_deltaAngularVelocity
c.m_multiBodyA->applyDeltaVeeMultiDof2(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacAindex], deltaImpulse);
-#endif //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
+#endif //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
}
else if (c.m_solverBodyIdA >= 0)
{
- bodyA->internalApplyImpulse(c.m_contactNormal1*bodyA->internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
-
+ bodyA->internalApplyImpulse(c.m_contactNormal1 * bodyA->internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
}
if (c.m_multiBodyB)
{
@@ -268,54 +262,54 @@ btScalar btMultiBodyConstraintSolver::resolveSingleConstraintRowGeneric(const bt
//note: update of the actual velocities (below) in the multibody does not have to happen now since m_deltaVelocities can be applied after all iterations
//it would make the multibody solver more like the regular one with m_deltaVelocities being equivalent to btSolverBody::m_deltaLinearVelocity/m_deltaAngularVelocity
c.m_multiBodyB->applyDeltaVeeMultiDof2(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacBindex], deltaImpulse);
-#endif //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
+#endif //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
}
else if (c.m_solverBodyIdB >= 0)
{
- bodyB->internalApplyImpulse(c.m_contactNormal2*bodyB->internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
+ bodyB->internalApplyImpulse(c.m_contactNormal2 * bodyB->internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
}
- btScalar deltaVel =deltaImpulse/c.m_jacDiagABInv;
+ btScalar deltaVel = deltaImpulse / c.m_jacDiagABInv;
return deltaVel;
}
-
-btScalar btMultiBodyConstraintSolver::resolveConeFrictionConstraintRows(const btMultiBodySolverConstraint& cA1,const btMultiBodySolverConstraint& cB)
+btScalar btMultiBodyConstraintSolver::resolveConeFrictionConstraintRows(const btMultiBodySolverConstraint& cA1, const btMultiBodySolverConstraint& cB)
{
- int ndofA=0;
- int ndofB=0;
+ int ndofA = 0;
+ int ndofB = 0;
btSolverBody* bodyA = 0;
btSolverBody* bodyB = 0;
btScalar deltaImpulseB = 0.f;
btScalar sumB = 0.f;
{
- deltaImpulseB = cB.m_rhs-btScalar(cB.m_appliedImpulse)*cB.m_cfm;
- btScalar deltaVelADotn=0;
- btScalar deltaVelBDotn=0;
+ deltaImpulseB = cB.m_rhs - btScalar(cB.m_appliedImpulse) * cB.m_cfm;
+ btScalar deltaVelADotn = 0;
+ btScalar deltaVelBDotn = 0;
if (cB.m_multiBodyA)
{
- ndofA = cB.m_multiBodyA->getNumDofs() + 6;
- for (int i = 0; i < ndofA; ++i)
- deltaVelADotn += m_data.m_jacobians[cB.m_jacAindex+i] * m_data.m_deltaVelocities[cB.m_deltaVelAindex+i];
- } else if(cB.m_solverBodyIdA >= 0)
+ ndofA = cB.m_multiBodyA->getNumDofs() + 6;
+ for (int i = 0; i < ndofA; ++i)
+ deltaVelADotn += m_data.m_jacobians[cB.m_jacAindex + i] * m_data.m_deltaVelocities[cB.m_deltaVelAindex + i];
+ }
+ else if (cB.m_solverBodyIdA >= 0)
{
bodyA = &m_tmpSolverBodyPool[cB.m_solverBodyIdA];
- deltaVelADotn += cB.m_contactNormal1.dot(bodyA->internalGetDeltaLinearVelocity()) + cB.m_relpos1CrossNormal.dot(bodyA->internalGetDeltaAngularVelocity());
+ deltaVelADotn += cB.m_contactNormal1.dot(bodyA->internalGetDeltaLinearVelocity()) + cB.m_relpos1CrossNormal.dot(bodyA->internalGetDeltaAngularVelocity());
}
if (cB.m_multiBodyB)
{
- ndofB = cB.m_multiBodyB->getNumDofs() + 6;
- for (int i = 0; i < ndofB; ++i)
- deltaVelBDotn += m_data.m_jacobians[cB.m_jacBindex+i] * m_data.m_deltaVelocities[cB.m_deltaVelBindex+i];
- } else if(cB.m_solverBodyIdB >= 0)
+ ndofB = cB.m_multiBodyB->getNumDofs() + 6;
+ for (int i = 0; i < ndofB; ++i)
+ deltaVelBDotn += m_data.m_jacobians[cB.m_jacBindex + i] * m_data.m_deltaVelocities[cB.m_deltaVelBindex + i];
+ }
+ else if (cB.m_solverBodyIdB >= 0)
{
bodyB = &m_tmpSolverBodyPool[cB.m_solverBodyIdB];
- deltaVelBDotn += cB.m_contactNormal2.dot(bodyB->internalGetDeltaLinearVelocity()) + cB.m_relpos2CrossNormal.dot(bodyB->internalGetDeltaAngularVelocity());
+ deltaVelBDotn += cB.m_contactNormal2.dot(bodyB->internalGetDeltaLinearVelocity()) + cB.m_relpos2CrossNormal.dot(bodyB->internalGetDeltaAngularVelocity());
}
-
- deltaImpulseB -= deltaVelADotn*cB.m_jacDiagABInv;//m_jacDiagABInv = 1./denom
- deltaImpulseB -= deltaVelBDotn*cB.m_jacDiagABInv;
+ deltaImpulseB -= deltaVelADotn * cB.m_jacDiagABInv; //m_jacDiagABInv = 1./denom
+ deltaImpulseB -= deltaVelBDotn * cB.m_jacDiagABInv;
sumB = btScalar(cB.m_appliedImpulse) + deltaImpulseB;
}
@@ -324,45 +318,45 @@ btScalar btMultiBodyConstraintSolver::resolveConeFrictionConstraintRows(const bt
const btMultiBodySolverConstraint& cA = cA1;
{
{
- deltaImpulseA = cA.m_rhs-btScalar(cA.m_appliedImpulse)*cA.m_cfm;
- btScalar deltaVelADotn=0;
- btScalar deltaVelBDotn=0;
+ deltaImpulseA = cA.m_rhs - btScalar(cA.m_appliedImpulse) * cA.m_cfm;
+ btScalar deltaVelADotn = 0;
+ btScalar deltaVelBDotn = 0;
if (cA.m_multiBodyA)
{
- ndofA = cA.m_multiBodyA->getNumDofs() + 6;
- for (int i = 0; i < ndofA; ++i)
- deltaVelADotn += m_data.m_jacobians[cA.m_jacAindex+i] * m_data.m_deltaVelocities[cA.m_deltaVelAindex+i];
- } else if(cA.m_solverBodyIdA >= 0)
+ ndofA = cA.m_multiBodyA->getNumDofs() + 6;
+ for (int i = 0; i < ndofA; ++i)
+ deltaVelADotn += m_data.m_jacobians[cA.m_jacAindex + i] * m_data.m_deltaVelocities[cA.m_deltaVelAindex + i];
+ }
+ else if (cA.m_solverBodyIdA >= 0)
{
bodyA = &m_tmpSolverBodyPool[cA.m_solverBodyIdA];
- deltaVelADotn += cA.m_contactNormal1.dot(bodyA->internalGetDeltaLinearVelocity()) + cA.m_relpos1CrossNormal.dot(bodyA->internalGetDeltaAngularVelocity());
+ deltaVelADotn += cA.m_contactNormal1.dot(bodyA->internalGetDeltaLinearVelocity()) + cA.m_relpos1CrossNormal.dot(bodyA->internalGetDeltaAngularVelocity());
}
if (cA.m_multiBodyB)
{
- ndofB = cA.m_multiBodyB->getNumDofs() + 6;
- for (int i = 0; i < ndofB; ++i)
- deltaVelBDotn += m_data.m_jacobians[cA.m_jacBindex+i] * m_data.m_deltaVelocities[cA.m_deltaVelBindex+i];
- } else if(cA.m_solverBodyIdB >= 0)
+ ndofB = cA.m_multiBodyB->getNumDofs() + 6;
+ for (int i = 0; i < ndofB; ++i)
+ deltaVelBDotn += m_data.m_jacobians[cA.m_jacBindex + i] * m_data.m_deltaVelocities[cA.m_deltaVelBindex + i];
+ }
+ else if (cA.m_solverBodyIdB >= 0)
{
bodyB = &m_tmpSolverBodyPool[cA.m_solverBodyIdB];
- deltaVelBDotn += cA.m_contactNormal2.dot(bodyB->internalGetDeltaLinearVelocity()) + cA.m_relpos2CrossNormal.dot(bodyB->internalGetDeltaAngularVelocity());
+ deltaVelBDotn += cA.m_contactNormal2.dot(bodyB->internalGetDeltaLinearVelocity()) + cA.m_relpos2CrossNormal.dot(bodyB->internalGetDeltaAngularVelocity());
}
-
- deltaImpulseA -= deltaVelADotn*cA.m_jacDiagABInv;//m_jacDiagABInv = 1./denom
- deltaImpulseA -= deltaVelBDotn*cA.m_jacDiagABInv;
+ deltaImpulseA -= deltaVelADotn * cA.m_jacDiagABInv; //m_jacDiagABInv = 1./denom
+ deltaImpulseA -= deltaVelBDotn * cA.m_jacDiagABInv;
sumA = btScalar(cA.m_appliedImpulse) + deltaImpulseA;
}
}
- if (sumA*sumA+sumB*sumB>=cA.m_lowerLimit*cB.m_lowerLimit)
+ if (sumA * sumA + sumB * sumB >= cA.m_lowerLimit * cB.m_lowerLimit)
{
- btScalar angle = btAtan2(sumA,sumB);
- btScalar sumAclipped = btFabs(cA.m_lowerLimit*btSin(angle));
- btScalar sumBclipped = btFabs(cB.m_lowerLimit*btCos(angle));
+ btScalar angle = btAtan2(sumA, sumB);
+ btScalar sumAclipped = btFabs(cA.m_lowerLimit * btSin(angle));
+ btScalar sumBclipped = btFabs(cB.m_lowerLimit * btCos(angle));
-
if (sumA < -sumAclipped)
{
deltaImpulseA = -sumAclipped - cA.m_appliedImpulse;
@@ -396,78 +390,77 @@ btScalar btMultiBodyConstraintSolver::resolveConeFrictionConstraintRows(const bt
//cA.m_appliedImpulse = sumAclipped;
//deltaImpulseB = sumBclipped-cB.m_appliedImpulse;
//cB.m_appliedImpulse = sumBclipped;
- }
+ }
else
{
cA.m_appliedImpulse = sumA;
cB.m_appliedImpulse = sumB;
}
-
+
if (cA.m_multiBodyA)
{
- applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[cA.m_jacAindex],deltaImpulseA,cA.m_deltaVelAindex,ndofA);
+ applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[cA.m_jacAindex], deltaImpulseA, cA.m_deltaVelAindex, ndofA);
#ifdef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
//note: update of the actual velocities (below) in the multibody does not have to happen now since m_deltaVelocities can be applied after all iterations
//it would make the multibody solver more like the regular one with m_deltaVelocities being equivalent to btSolverBody::m_deltaLinearVelocity/m_deltaAngularVelocity
- cA.m_multiBodyA->applyDeltaVeeMultiDof2(&m_data.m_deltaVelocitiesUnitImpulse[cA.m_jacAindex],deltaImpulseA);
-#endif //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
- } else if(cA.m_solverBodyIdA >= 0)
+ cA.m_multiBodyA->applyDeltaVeeMultiDof2(&m_data.m_deltaVelocitiesUnitImpulse[cA.m_jacAindex], deltaImpulseA);
+#endif //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
+ }
+ else if (cA.m_solverBodyIdA >= 0)
{
- bodyA->internalApplyImpulse(cA.m_contactNormal1*bodyA->internalGetInvMass(),cA.m_angularComponentA,deltaImpulseA);
-
+ bodyA->internalApplyImpulse(cA.m_contactNormal1 * bodyA->internalGetInvMass(), cA.m_angularComponentA, deltaImpulseA);
}
if (cA.m_multiBodyB)
{
- applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[cA.m_jacBindex],deltaImpulseA,cA.m_deltaVelBindex,ndofB);
+ applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[cA.m_jacBindex], deltaImpulseA, cA.m_deltaVelBindex, ndofB);
#ifdef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
//note: update of the actual velocities (below) in the multibody does not have to happen now since m_deltaVelocities can be applied after all iterations
//it would make the multibody solver more like the regular one with m_deltaVelocities being equivalent to btSolverBody::m_deltaLinearVelocity/m_deltaAngularVelocity
- cA.m_multiBodyB->applyDeltaVeeMultiDof2(&m_data.m_deltaVelocitiesUnitImpulse[cA.m_jacBindex],deltaImpulseA);
-#endif //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
- } else if(cA.m_solverBodyIdB >= 0)
+ cA.m_multiBodyB->applyDeltaVeeMultiDof2(&m_data.m_deltaVelocitiesUnitImpulse[cA.m_jacBindex], deltaImpulseA);
+#endif //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
+ }
+ else if (cA.m_solverBodyIdB >= 0)
{
- bodyB->internalApplyImpulse(cA.m_contactNormal2*bodyB->internalGetInvMass(),cA.m_angularComponentB,deltaImpulseA);
+ bodyB->internalApplyImpulse(cA.m_contactNormal2 * bodyB->internalGetInvMass(), cA.m_angularComponentB, deltaImpulseA);
}
if (cB.m_multiBodyA)
{
- applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[cB.m_jacAindex],deltaImpulseB,cB.m_deltaVelAindex,ndofA);
+ applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[cB.m_jacAindex], deltaImpulseB, cB.m_deltaVelAindex, ndofA);
#ifdef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
//note: update of the actual velocities (below) in the multibody does not have to happen now since m_deltaVelocities can be applied after all iterations
//it would make the multibody solver more like the regular one with m_deltaVelocities being equivalent to btSolverBody::m_deltaLinearVelocity/m_deltaAngularVelocity
- cB.m_multiBodyA->applyDeltaVeeMultiDof2(&m_data.m_deltaVelocitiesUnitImpulse[cB.m_jacAindex],deltaImpulseB);
-#endif //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
- } else if(cB.m_solverBodyIdA >= 0)
+ cB.m_multiBodyA->applyDeltaVeeMultiDof2(&m_data.m_deltaVelocitiesUnitImpulse[cB.m_jacAindex], deltaImpulseB);
+#endif //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
+ }
+ else if (cB.m_solverBodyIdA >= 0)
{
- bodyA->internalApplyImpulse(cB.m_contactNormal1*bodyA->internalGetInvMass(),cB.m_angularComponentA,deltaImpulseB);
+ bodyA->internalApplyImpulse(cB.m_contactNormal1 * bodyA->internalGetInvMass(), cB.m_angularComponentA, deltaImpulseB);
}
if (cB.m_multiBodyB)
{
- applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[cB.m_jacBindex],deltaImpulseB,cB.m_deltaVelBindex,ndofB);
+ applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[cB.m_jacBindex], deltaImpulseB, cB.m_deltaVelBindex, ndofB);
#ifdef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
//note: update of the actual velocities (below) in the multibody does not have to happen now since m_deltaVelocities can be applied after all iterations
//it would make the multibody solver more like the regular one with m_deltaVelocities being equivalent to btSolverBody::m_deltaLinearVelocity/m_deltaAngularVelocity
- cB.m_multiBodyB->applyDeltaVeeMultiDof2(&m_data.m_deltaVelocitiesUnitImpulse[cB.m_jacBindex],deltaImpulseB);
-#endif //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
- } else if(cB.m_solverBodyIdB >= 0)
+ cB.m_multiBodyB->applyDeltaVeeMultiDof2(&m_data.m_deltaVelocitiesUnitImpulse[cB.m_jacBindex], deltaImpulseB);
+#endif //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
+ }
+ else if (cB.m_solverBodyIdB >= 0)
{
- bodyB->internalApplyImpulse(cB.m_contactNormal2*bodyB->internalGetInvMass(),cB.m_angularComponentB,deltaImpulseB);
+ bodyB->internalApplyImpulse(cB.m_contactNormal2 * bodyB->internalGetInvMass(), cB.m_angularComponentB, deltaImpulseB);
}
- btScalar deltaVel =deltaImpulseA/cA.m_jacDiagABInv+deltaImpulseB/cB.m_jacDiagABInv;
- return deltaVel;
+ btScalar deltaVel = deltaImpulseA / cA.m_jacDiagABInv + deltaImpulseB / cB.m_jacDiagABInv;
+ return deltaVel;
}
-
-
-
-void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySolverConstraint& solverConstraint,
- const btVector3& contactNormal,
- btManifoldPoint& cp, const btContactSolverInfo& infoGlobal,
- btScalar& relaxation,
- bool isFriction, btScalar desiredVelocity, btScalar cfmSlip)
+void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySolverConstraint& solverConstraint,
+ const btVector3& contactNormal,
+ btManifoldPoint& cp, const btContactSolverInfo& infoGlobal,
+ btScalar& relaxation,
+ bool isFriction, btScalar desiredVelocity, btScalar cfmSlip)
{
-
BT_PROFILE("setupMultiBodyContactConstraint");
btVector3 rel_pos1;
btVector3 rel_pos2;
@@ -485,44 +478,46 @@ void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySol
btRigidBody* rb1 = multiBodyB ? 0 : bodyB->m_originalBody;
if (bodyA)
- rel_pos1 = pos1 - bodyA->getWorldTransform().getOrigin();
+ rel_pos1 = pos1 - bodyA->getWorldTransform().getOrigin();
if (bodyB)
rel_pos2 = pos2 - bodyB->getWorldTransform().getOrigin();
relaxation = infoGlobal.m_sor;
-
- btScalar invTimeStep = btScalar(1)/infoGlobal.m_timeStep;
-
- //cfm = 1 / ( dt * kp + kd )
- //erp = dt * kp / ( dt * kp + kd )
-
- btScalar cfm;
+
+ btScalar invTimeStep = btScalar(1) / infoGlobal.m_timeStep;
+
+ //cfm = 1 / ( dt * kp + kd )
+ //erp = dt * kp / ( dt * kp + kd )
+
+ btScalar cfm;
btScalar erp;
if (isFriction)
{
cfm = infoGlobal.m_frictionCFM;
erp = infoGlobal.m_frictionERP;
- } else
+ }
+ else
{
cfm = infoGlobal.m_globalCfm;
erp = infoGlobal.m_erp2;
- if ((cp.m_contactPointFlags&BT_CONTACT_FLAG_HAS_CONTACT_CFM) || (cp.m_contactPointFlags&BT_CONTACT_FLAG_HAS_CONTACT_ERP))
+ if ((cp.m_contactPointFlags & BT_CONTACT_FLAG_HAS_CONTACT_CFM) || (cp.m_contactPointFlags & BT_CONTACT_FLAG_HAS_CONTACT_ERP))
{
- if (cp.m_contactPointFlags&BT_CONTACT_FLAG_HAS_CONTACT_CFM)
- cfm = cp.m_contactCFM;
- if (cp.m_contactPointFlags&BT_CONTACT_FLAG_HAS_CONTACT_ERP)
- erp = cp.m_contactERP;
- } else
+ if (cp.m_contactPointFlags & BT_CONTACT_FLAG_HAS_CONTACT_CFM)
+ cfm = cp.m_contactCFM;
+ if (cp.m_contactPointFlags & BT_CONTACT_FLAG_HAS_CONTACT_ERP)
+ erp = cp.m_contactERP;
+ }
+ else
{
if (cp.m_contactPointFlags & BT_CONTACT_FLAG_CONTACT_STIFFNESS_DAMPING)
{
- btScalar denom = ( infoGlobal.m_timeStep * cp.m_combinedContactStiffness1 + cp.m_combinedContactDamping1 );
+ btScalar denom = (infoGlobal.m_timeStep * cp.m_combinedContactStiffness1 + cp.m_combinedContactDamping1);
if (denom < SIMD_EPSILON)
{
denom = SIMD_EPSILON;
}
- cfm = btScalar(1) / denom;
+ cfm = btScalar(1) / denom;
erp = (infoGlobal.m_timeStep * cp.m_combinedContactStiffness1) / denom;
}
}
@@ -532,218 +527,217 @@ void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySol
if (multiBodyA)
{
- if (solverConstraint.m_linkA<0)
+ if (solverConstraint.m_linkA < 0)
{
rel_pos1 = pos1 - multiBodyA->getBasePos();
- } else
+ }
+ else
{
rel_pos1 = pos1 - multiBodyA->getLink(solverConstraint.m_linkA).m_cachedWorldTransform.getOrigin();
}
- const int ndofA = multiBodyA->getNumDofs() + 6;
+ const int ndofA = multiBodyA->getNumDofs() + 6;
solverConstraint.m_deltaVelAindex = multiBodyA->getCompanionId();
- if (solverConstraint.m_deltaVelAindex <0)
+ if (solverConstraint.m_deltaVelAindex < 0)
{
solverConstraint.m_deltaVelAindex = m_data.m_deltaVelocities.size();
multiBodyA->setCompanionId(solverConstraint.m_deltaVelAindex);
- m_data.m_deltaVelocities.resize(m_data.m_deltaVelocities.size()+ndofA);
- } else
+ m_data.m_deltaVelocities.resize(m_data.m_deltaVelocities.size() + ndofA);
+ }
+ else
{
- btAssert(m_data.m_deltaVelocities.size() >= solverConstraint.m_deltaVelAindex+ndofA);
+ btAssert(m_data.m_deltaVelocities.size() >= solverConstraint.m_deltaVelAindex + ndofA);
}
solverConstraint.m_jacAindex = m_data.m_jacobians.size();
- m_data.m_jacobians.resize(m_data.m_jacobians.size()+ndofA);
- m_data.m_deltaVelocitiesUnitImpulse.resize(m_data.m_deltaVelocitiesUnitImpulse.size()+ndofA);
+ m_data.m_jacobians.resize(m_data.m_jacobians.size() + ndofA);
+ m_data.m_deltaVelocitiesUnitImpulse.resize(m_data.m_deltaVelocitiesUnitImpulse.size() + ndofA);
btAssert(m_data.m_jacobians.size() == m_data.m_deltaVelocitiesUnitImpulse.size());
- btScalar* jac1=&m_data.m_jacobians[solverConstraint.m_jacAindex];
+ btScalar* jac1 = &m_data.m_jacobians[solverConstraint.m_jacAindex];
multiBodyA->fillContactJacobianMultiDof(solverConstraint.m_linkA, cp.getPositionWorldOnA(), contactNormal, jac1, m_data.scratch_r, m_data.scratch_v, m_data.scratch_m);
btScalar* delta = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
- multiBodyA->calcAccelerationDeltasMultiDof(&m_data.m_jacobians[solverConstraint.m_jacAindex],delta,m_data.scratch_r, m_data.scratch_v);
+ multiBodyA->calcAccelerationDeltasMultiDof(&m_data.m_jacobians[solverConstraint.m_jacAindex], delta, m_data.scratch_r, m_data.scratch_v);
btVector3 torqueAxis0 = rel_pos1.cross(contactNormal);
solverConstraint.m_relpos1CrossNormal = torqueAxis0;
solverConstraint.m_contactNormal1 = contactNormal;
- } else
+ }
+ else
{
btVector3 torqueAxis0 = rel_pos1.cross(contactNormal);
solverConstraint.m_relpos1CrossNormal = torqueAxis0;
solverConstraint.m_contactNormal1 = contactNormal;
- solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld()*torqueAxis0*rb0->getAngularFactor() : btVector3(0,0,0);
+ solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld() * torqueAxis0 * rb0->getAngularFactor() : btVector3(0, 0, 0);
}
-
-
if (multiBodyB)
{
- if (solverConstraint.m_linkB<0)
+ if (solverConstraint.m_linkB < 0)
{
rel_pos2 = pos2 - multiBodyB->getBasePos();
- } else
+ }
+ else
{
rel_pos2 = pos2 - multiBodyB->getLink(solverConstraint.m_linkB).m_cachedWorldTransform.getOrigin();
}
- const int ndofB = multiBodyB->getNumDofs() + 6;
+ const int ndofB = multiBodyB->getNumDofs() + 6;
solverConstraint.m_deltaVelBindex = multiBodyB->getCompanionId();
- if (solverConstraint.m_deltaVelBindex <0)
+ if (solverConstraint.m_deltaVelBindex < 0)
{
solverConstraint.m_deltaVelBindex = m_data.m_deltaVelocities.size();
multiBodyB->setCompanionId(solverConstraint.m_deltaVelBindex);
- m_data.m_deltaVelocities.resize(m_data.m_deltaVelocities.size()+ndofB);
+ m_data.m_deltaVelocities.resize(m_data.m_deltaVelocities.size() + ndofB);
}
solverConstraint.m_jacBindex = m_data.m_jacobians.size();
- m_data.m_jacobians.resize(m_data.m_jacobians.size()+ndofB);
- m_data.m_deltaVelocitiesUnitImpulse.resize(m_data.m_deltaVelocitiesUnitImpulse.size()+ndofB);
+ m_data.m_jacobians.resize(m_data.m_jacobians.size() + ndofB);
+ m_data.m_deltaVelocitiesUnitImpulse.resize(m_data.m_deltaVelocitiesUnitImpulse.size() + ndofB);
btAssert(m_data.m_jacobians.size() == m_data.m_deltaVelocitiesUnitImpulse.size());
multiBodyB->fillContactJacobianMultiDof(solverConstraint.m_linkB, cp.getPositionWorldOnB(), -contactNormal, &m_data.m_jacobians[solverConstraint.m_jacBindex], m_data.scratch_r, m_data.scratch_v, m_data.scratch_m);
- multiBodyB->calcAccelerationDeltasMultiDof(&m_data.m_jacobians[solverConstraint.m_jacBindex],&m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex],m_data.scratch_r, m_data.scratch_v);
-
- btVector3 torqueAxis1 = rel_pos2.cross(contactNormal);
+ multiBodyB->calcAccelerationDeltasMultiDof(&m_data.m_jacobians[solverConstraint.m_jacBindex], &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex], m_data.scratch_r, m_data.scratch_v);
+
+ btVector3 torqueAxis1 = rel_pos2.cross(contactNormal);
solverConstraint.m_relpos2CrossNormal = -torqueAxis1;
solverConstraint.m_contactNormal2 = -contactNormal;
-
- } else
+ }
+ else
{
- btVector3 torqueAxis1 = rel_pos2.cross(contactNormal);
+ btVector3 torqueAxis1 = rel_pos2.cross(contactNormal);
solverConstraint.m_relpos2CrossNormal = -torqueAxis1;
solverConstraint.m_contactNormal2 = -contactNormal;
-
- solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld()*-torqueAxis1*rb1->getAngularFactor() : btVector3(0,0,0);
+
+ solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld() * -torqueAxis1 * rb1->getAngularFactor() : btVector3(0, 0, 0);
}
{
-
btVector3 vec;
btScalar denom0 = 0.f;
btScalar denom1 = 0.f;
btScalar* jacB = 0;
btScalar* jacA = 0;
- btScalar* lambdaA =0;
- btScalar* lambdaB =0;
- int ndofA = 0;
+ btScalar* lambdaA = 0;
+ btScalar* lambdaB = 0;
+ int ndofA = 0;
if (multiBodyA)
{
- ndofA = multiBodyA->getNumDofs() + 6;
+ ndofA = multiBodyA->getNumDofs() + 6;
jacA = &m_data.m_jacobians[solverConstraint.m_jacAindex];
lambdaA = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
for (int i = 0; i < ndofA; ++i)
{
- btScalar j = jacA[i] ;
- btScalar l =lambdaA[i];
- denom0 += j*l;
+ btScalar j = jacA[i];
+ btScalar l = lambdaA[i];
+ denom0 += j * l;
}
- } else
+ }
+ else
{
if (rb0)
{
- vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1);
+ vec = (solverConstraint.m_angularComponentA).cross(rel_pos1);
denom0 = rb0->getInvMass() + contactNormal.dot(vec);
}
}
if (multiBodyB)
{
- const int ndofB = multiBodyB->getNumDofs() + 6;
+ const int ndofB = multiBodyB->getNumDofs() + 6;
jacB = &m_data.m_jacobians[solverConstraint.m_jacBindex];
lambdaB = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
for (int i = 0; i < ndofB; ++i)
{
- btScalar j = jacB[i] ;
- btScalar l =lambdaB[i];
- denom1 += j*l;
+ btScalar j = jacB[i];
+ btScalar l = lambdaB[i];
+ denom1 += j * l;
}
-
- } else
+ }
+ else
{
if (rb1)
{
- vec = ( -solverConstraint.m_angularComponentB).cross(rel_pos2);
+ vec = (-solverConstraint.m_angularComponentB).cross(rel_pos2);
denom1 = rb1->getInvMass() + contactNormal.dot(vec);
}
}
-
-
- btScalar d = denom0+denom1+cfm;
- if (d>SIMD_EPSILON)
- {
- solverConstraint.m_jacDiagABInv = relaxation/(d);
- } else
- {
+ btScalar d = denom0 + denom1 + cfm;
+ if (d > SIMD_EPSILON)
+ {
+ solverConstraint.m_jacDiagABInv = relaxation / (d);
+ }
+ else
+ {
//disable the constraint row to handle singularity/redundant constraint
- solverConstraint.m_jacDiagABInv = 0.f;
- }
-
+ solverConstraint.m_jacDiagABInv = 0.f;
+ }
}
-
//compute rhs and remaining solverConstraint fields
-
-
btScalar restitution = 0.f;
- btScalar distance = 0;
- if (!isFriction)
- {
- distance = cp.getDistance()+infoGlobal.m_linearSlop;
- } else
- {
- if (cp.m_contactPointFlags & BT_CONTACT_FLAG_FRICTION_ANCHOR)
- {
- distance = (cp.getPositionWorldOnA() - cp.getPositionWorldOnB()).dot(contactNormal);
- }
- }
-
-
- btScalar rel_vel = 0.f;
- int ndofA = 0;
- int ndofB = 0;
+ btScalar distance = 0;
+ if (!isFriction)
+ {
+ distance = cp.getDistance() + infoGlobal.m_linearSlop;
+ }
+ else
{
+ if (cp.m_contactPointFlags & BT_CONTACT_FLAG_FRICTION_ANCHOR)
+ {
+ distance = (cp.getPositionWorldOnA() - cp.getPositionWorldOnB()).dot(contactNormal);
+ }
+ }
- btVector3 vel1,vel2;
+ btScalar rel_vel = 0.f;
+ int ndofA = 0;
+ int ndofB = 0;
+ {
+ btVector3 vel1, vel2;
if (multiBodyA)
{
- ndofA = multiBodyA->getNumDofs() + 6;
+ ndofA = multiBodyA->getNumDofs() + 6;
btScalar* jacA = &m_data.m_jacobians[solverConstraint.m_jacAindex];
- for (int i = 0; i < ndofA ; ++i)
+ for (int i = 0; i < ndofA; ++i)
rel_vel += multiBodyA->getVelocityVector()[i] * jacA[i];
- } else
+ }
+ else
{
if (rb0)
{
- rel_vel += (rb0->getVelocityInLocalPoint(rel_pos1) +
- (rb0->getTotalTorque()*rb0->getInvInertiaTensorWorld()*infoGlobal.m_timeStep).cross(rel_pos1)+
- rb0->getTotalForce()*rb0->getInvMass()*infoGlobal.m_timeStep).dot(solverConstraint.m_contactNormal1);
+ rel_vel += (rb0->getVelocityInLocalPoint(rel_pos1) +
+ (rb0->getTotalTorque() * rb0->getInvInertiaTensorWorld() * infoGlobal.m_timeStep).cross(rel_pos1) +
+ rb0->getTotalForce() * rb0->getInvMass() * infoGlobal.m_timeStep)
+ .dot(solverConstraint.m_contactNormal1);
}
}
if (multiBodyB)
{
- ndofB = multiBodyB->getNumDofs() + 6;
+ ndofB = multiBodyB->getNumDofs() + 6;
btScalar* jacB = &m_data.m_jacobians[solverConstraint.m_jacBindex];
- for (int i = 0; i < ndofB ; ++i)
+ for (int i = 0; i < ndofB; ++i)
rel_vel += multiBodyB->getVelocityVector()[i] * jacB[i];
-
- } else
+ }
+ else
{
if (rb1)
{
- rel_vel += (rb1->getVelocityInLocalPoint(rel_pos2)+
- (rb1->getTotalTorque()*rb1->getInvInertiaTensorWorld()*infoGlobal.m_timeStep).cross(rel_pos2) +
- rb1->getTotalForce()*rb1->getInvMass()*infoGlobal.m_timeStep).dot(solverConstraint.m_contactNormal2);
+ rel_vel += (rb1->getVelocityInLocalPoint(rel_pos2) +
+ (rb1->getTotalTorque() * rb1->getInvInertiaTensorWorld() * infoGlobal.m_timeStep).cross(rel_pos2) +
+ rb1->getTotalForce() * rb1->getInvMass() * infoGlobal.m_timeStep)
+ .dot(solverConstraint.m_contactNormal2);
}
}
solverConstraint.m_friction = cp.m_combinedFriction;
- if(!isFriction)
+ if (!isFriction)
{
- restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution, infoGlobal.m_restitutionVelocityThreshold);
+ restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution, infoGlobal.m_restitutionVelocityThreshold);
if (restitution <= btScalar(0.))
{
restitution = 0.f;
@@ -751,10 +745,9 @@ void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySol
}
}
-
///warm starting (or zero if disabled)
//disable warmstarting for btMultiBody, it has issues gaining energy (==explosion)
- if (0)//infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
+ if (0) //infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
{
solverConstraint.m_appliedImpulse = isFriction ? 0 : cp.m_appliedImpulse * infoGlobal.m_warmstartingFactor;
@@ -764,27 +757,30 @@ void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySol
{
btScalar impulse = solverConstraint.m_appliedImpulse;
btScalar* deltaV = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
- multiBodyA->applyDeltaVeeMultiDof(deltaV,impulse);
-
- applyDeltaVee(deltaV,impulse,solverConstraint.m_deltaVelAindex,ndofA);
- } else
+ multiBodyA->applyDeltaVeeMultiDof(deltaV, impulse);
+
+ applyDeltaVee(deltaV, impulse, solverConstraint.m_deltaVelAindex, ndofA);
+ }
+ else
{
if (rb0)
- bodyA->internalApplyImpulse(solverConstraint.m_contactNormal1*bodyA->internalGetInvMass()*rb0->getLinearFactor(),solverConstraint.m_angularComponentA,solverConstraint.m_appliedImpulse);
+ bodyA->internalApplyImpulse(solverConstraint.m_contactNormal1 * bodyA->internalGetInvMass() * rb0->getLinearFactor(), solverConstraint.m_angularComponentA, solverConstraint.m_appliedImpulse);
}
if (multiBodyB)
{
btScalar impulse = solverConstraint.m_appliedImpulse;
btScalar* deltaV = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
- multiBodyB->applyDeltaVeeMultiDof(deltaV,impulse);
- applyDeltaVee(deltaV,impulse,solverConstraint.m_deltaVelBindex,ndofB);
- } else
+ multiBodyB->applyDeltaVeeMultiDof(deltaV, impulse);
+ applyDeltaVee(deltaV, impulse, solverConstraint.m_deltaVelBindex, ndofB);
+ }
+ else
{
if (rb1)
- bodyB->internalApplyImpulse(-solverConstraint.m_contactNormal2*bodyB->internalGetInvMass()*rb1->getLinearFactor(),-solverConstraint.m_angularComponentB,-(btScalar)solverConstraint.m_appliedImpulse);
+ bodyB->internalApplyImpulse(-solverConstraint.m_contactNormal2 * bodyB->internalGetInvMass() * rb1->getLinearFactor(), -solverConstraint.m_angularComponentB, -(btScalar)solverConstraint.m_appliedImpulse);
}
}
- } else
+ }
+ else
{
solverConstraint.m_appliedImpulse = 0.f;
}
@@ -792,38 +788,37 @@ void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySol
solverConstraint.m_appliedPushImpulse = 0.f;
{
-
btScalar positionalError = 0.f;
- btScalar velocityError = restitution - rel_vel;// * damping; //note for friction restitution is always set to 0 (check above) so it is acutally velocityError = -rel_vel for friction
+ btScalar velocityError = restitution - rel_vel; // * damping; //note for friction restitution is always set to 0 (check above) so it is acutally velocityError = -rel_vel for friction
if (isFriction)
{
- positionalError = -distance * erp/infoGlobal.m_timeStep;
- } else
+ positionalError = -distance * erp / infoGlobal.m_timeStep;
+ }
+ else
{
- if (distance>0)
+ if (distance > 0)
{
positionalError = 0;
velocityError -= distance / infoGlobal.m_timeStep;
-
- } else
+ }
+ else
{
- positionalError = -distance * erp/infoGlobal.m_timeStep;
+ positionalError = -distance * erp / infoGlobal.m_timeStep;
}
}
- btScalar penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv;
- btScalar velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv;
+ btScalar penetrationImpulse = positionalError * solverConstraint.m_jacDiagABInv;
+ btScalar velocityImpulse = velocityError * solverConstraint.m_jacDiagABInv;
- if(!isFriction)
+ if (!isFriction)
{
- // if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
+ // if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
{
//combine position and velocity into rhs
- solverConstraint.m_rhs = penetrationImpulse+velocityImpulse;
+ solverConstraint.m_rhs = penetrationImpulse + velocityImpulse;
solverConstraint.m_rhsPenetration = 0.f;
-
}
- /*else
+ /*else
{
//split position and velocity into rhs and m_rhsPenetration
solverConstraint.m_rhs = velocityImpulse;
@@ -835,309 +830,288 @@ void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySol
}
else
{
- solverConstraint.m_rhs = penetrationImpulse+velocityImpulse;
+ solverConstraint.m_rhs = penetrationImpulse + velocityImpulse;
solverConstraint.m_rhsPenetration = 0.f;
solverConstraint.m_lowerLimit = -solverConstraint.m_friction;
solverConstraint.m_upperLimit = solverConstraint.m_friction;
}
- solverConstraint.m_cfm = cfm*solverConstraint.m_jacDiagABInv;
-
-
-
+ solverConstraint.m_cfm = cfm * solverConstraint.m_jacDiagABInv;
}
-
}
void btMultiBodyConstraintSolver::setupMultiBodyTorsionalFrictionConstraint(btMultiBodySolverConstraint& solverConstraint,
- const btVector3& constraintNormal,
- btManifoldPoint& cp,
- btScalar combinedTorsionalFriction,
- const btContactSolverInfo& infoGlobal,
- btScalar& relaxation,
- bool isFriction, btScalar desiredVelocity, btScalar cfmSlip)
+ const btVector3& constraintNormal,
+ btManifoldPoint& cp,
+ btScalar combinedTorsionalFriction,
+ const btContactSolverInfo& infoGlobal,
+ btScalar& relaxation,
+ bool isFriction, btScalar desiredVelocity, btScalar cfmSlip)
{
-
- BT_PROFILE("setupMultiBodyRollingFrictionConstraint");
- btVector3 rel_pos1;
- btVector3 rel_pos2;
-
- btMultiBody* multiBodyA = solverConstraint.m_multiBodyA;
- btMultiBody* multiBodyB = solverConstraint.m_multiBodyB;
-
- const btVector3& pos1 = cp.getPositionWorldOnA();
- const btVector3& pos2 = cp.getPositionWorldOnB();
-
- btSolverBody* bodyA = multiBodyA ? 0 : &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA];
- btSolverBody* bodyB = multiBodyB ? 0 : &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB];
-
- btRigidBody* rb0 = multiBodyA ? 0 : bodyA->m_originalBody;
- btRigidBody* rb1 = multiBodyB ? 0 : bodyB->m_originalBody;
-
- if (bodyA)
- rel_pos1 = pos1 - bodyA->getWorldTransform().getOrigin();
- if (bodyB)
- rel_pos2 = pos2 - bodyB->getWorldTransform().getOrigin();
-
- relaxation = infoGlobal.m_sor;
-
- // btScalar invTimeStep = btScalar(1)/infoGlobal.m_timeStep;
-
-
- if (multiBodyA)
- {
- if (solverConstraint.m_linkA<0)
- {
- rel_pos1 = pos1 - multiBodyA->getBasePos();
- } else
- {
- rel_pos1 = pos1 - multiBodyA->getLink(solverConstraint.m_linkA).m_cachedWorldTransform.getOrigin();
- }
- const int ndofA = multiBodyA->getNumDofs() + 6;
-
- solverConstraint.m_deltaVelAindex = multiBodyA->getCompanionId();
-
- if (solverConstraint.m_deltaVelAindex <0)
- {
- solverConstraint.m_deltaVelAindex = m_data.m_deltaVelocities.size();
- multiBodyA->setCompanionId(solverConstraint.m_deltaVelAindex);
- m_data.m_deltaVelocities.resize(m_data.m_deltaVelocities.size()+ndofA);
- } else
- {
- btAssert(m_data.m_deltaVelocities.size() >= solverConstraint.m_deltaVelAindex+ndofA);
- }
-
- solverConstraint.m_jacAindex = m_data.m_jacobians.size();
- m_data.m_jacobians.resize(m_data.m_jacobians.size()+ndofA);
- m_data.m_deltaVelocitiesUnitImpulse.resize(m_data.m_deltaVelocitiesUnitImpulse.size()+ndofA);
- btAssert(m_data.m_jacobians.size() == m_data.m_deltaVelocitiesUnitImpulse.size());
-
- btScalar* jac1=&m_data.m_jacobians[solverConstraint.m_jacAindex];
- multiBodyA->fillConstraintJacobianMultiDof(solverConstraint.m_linkA, cp.getPositionWorldOnA(), constraintNormal, btVector3(0,0,0), jac1, m_data.scratch_r, m_data.scratch_v, m_data.scratch_m);
- btScalar* delta = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
- multiBodyA->calcAccelerationDeltasMultiDof(&m_data.m_jacobians[solverConstraint.m_jacAindex],delta,m_data.scratch_r, m_data.scratch_v);
-
- btVector3 torqueAxis0 = -constraintNormal;
- solverConstraint.m_relpos1CrossNormal = torqueAxis0;
- solverConstraint.m_contactNormal1 = btVector3(0,0,0);
- } else
- {
- btVector3 torqueAxis0 = -constraintNormal;
- solverConstraint.m_relpos1CrossNormal = torqueAxis0;
- solverConstraint.m_contactNormal1 = btVector3(0,0,0);
- solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld()*torqueAxis0*rb0->getAngularFactor() : btVector3(0,0,0);
- }
-
-
-
- if (multiBodyB)
- {
- if (solverConstraint.m_linkB<0)
- {
- rel_pos2 = pos2 - multiBodyB->getBasePos();
- } else
- {
- rel_pos2 = pos2 - multiBodyB->getLink(solverConstraint.m_linkB).m_cachedWorldTransform.getOrigin();
- }
-
- const int ndofB = multiBodyB->getNumDofs() + 6;
-
- solverConstraint.m_deltaVelBindex = multiBodyB->getCompanionId();
- if (solverConstraint.m_deltaVelBindex <0)
- {
- solverConstraint.m_deltaVelBindex = m_data.m_deltaVelocities.size();
- multiBodyB->setCompanionId(solverConstraint.m_deltaVelBindex);
- m_data.m_deltaVelocities.resize(m_data.m_deltaVelocities.size()+ndofB);
- }
-
- solverConstraint.m_jacBindex = m_data.m_jacobians.size();
-
- m_data.m_jacobians.resize(m_data.m_jacobians.size()+ndofB);
- m_data.m_deltaVelocitiesUnitImpulse.resize(m_data.m_deltaVelocitiesUnitImpulse.size()+ndofB);
- btAssert(m_data.m_jacobians.size() == m_data.m_deltaVelocitiesUnitImpulse.size());
-
- multiBodyB->fillConstraintJacobianMultiDof(solverConstraint.m_linkB, cp.getPositionWorldOnB(), -constraintNormal, btVector3(0,0,0), &m_data.m_jacobians[solverConstraint.m_jacBindex], m_data.scratch_r, m_data.scratch_v, m_data.scratch_m);
- multiBodyB->calcAccelerationDeltasMultiDof(&m_data.m_jacobians[solverConstraint.m_jacBindex],&m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex],m_data.scratch_r, m_data.scratch_v);
-
- btVector3 torqueAxis1 = constraintNormal;
- solverConstraint.m_relpos2CrossNormal = torqueAxis1;
- solverConstraint.m_contactNormal2 = -btVector3(0,0,0);
-
- } else
- {
- btVector3 torqueAxis1 = constraintNormal;
- solverConstraint.m_relpos2CrossNormal = torqueAxis1;
- solverConstraint.m_contactNormal2 = -btVector3(0,0,0);
-
- solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld()*torqueAxis1*rb1->getAngularFactor() : btVector3(0,0,0);
- }
-
- {
-
- btScalar denom0 = 0.f;
- btScalar denom1 = 0.f;
- btScalar* jacB = 0;
- btScalar* jacA = 0;
- btScalar* lambdaA =0;
- btScalar* lambdaB =0;
- int ndofA = 0;
- if (multiBodyA)
- {
- ndofA = multiBodyA->getNumDofs() + 6;
- jacA = &m_data.m_jacobians[solverConstraint.m_jacAindex];
- lambdaA = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
- for (int i = 0; i < ndofA; ++i)
- {
- btScalar j = jacA[i] ;
- btScalar l =lambdaA[i];
- denom0 += j*l;
- }
- } else
- {
- if (rb0)
- {
- btVector3 iMJaA = rb0?rb0->getInvInertiaTensorWorld()*solverConstraint.m_relpos1CrossNormal:btVector3(0,0,0);
+ BT_PROFILE("setupMultiBodyRollingFrictionConstraint");
+ btVector3 rel_pos1;
+ btVector3 rel_pos2;
+
+ btMultiBody* multiBodyA = solverConstraint.m_multiBodyA;
+ btMultiBody* multiBodyB = solverConstraint.m_multiBodyB;
+
+ const btVector3& pos1 = cp.getPositionWorldOnA();
+ const btVector3& pos2 = cp.getPositionWorldOnB();
+
+ btSolverBody* bodyA = multiBodyA ? 0 : &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA];
+ btSolverBody* bodyB = multiBodyB ? 0 : &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB];
+
+ btRigidBody* rb0 = multiBodyA ? 0 : bodyA->m_originalBody;
+ btRigidBody* rb1 = multiBodyB ? 0 : bodyB->m_originalBody;
+
+ if (bodyA)
+ rel_pos1 = pos1 - bodyA->getWorldTransform().getOrigin();
+ if (bodyB)
+ rel_pos2 = pos2 - bodyB->getWorldTransform().getOrigin();
+
+ relaxation = infoGlobal.m_sor;
+
+ // btScalar invTimeStep = btScalar(1)/infoGlobal.m_timeStep;
+
+ if (multiBodyA)
+ {
+ if (solverConstraint.m_linkA < 0)
+ {
+ rel_pos1 = pos1 - multiBodyA->getBasePos();
+ }
+ else
+ {
+ rel_pos1 = pos1 - multiBodyA->getLink(solverConstraint.m_linkA).m_cachedWorldTransform.getOrigin();
+ }
+ const int ndofA = multiBodyA->getNumDofs() + 6;
+
+ solverConstraint.m_deltaVelAindex = multiBodyA->getCompanionId();
+
+ if (solverConstraint.m_deltaVelAindex < 0)
+ {
+ solverConstraint.m_deltaVelAindex = m_data.m_deltaVelocities.size();
+ multiBodyA->setCompanionId(solverConstraint.m_deltaVelAindex);
+ m_data.m_deltaVelocities.resize(m_data.m_deltaVelocities.size() + ndofA);
+ }
+ else
+ {
+ btAssert(m_data.m_deltaVelocities.size() >= solverConstraint.m_deltaVelAindex + ndofA);
+ }
+
+ solverConstraint.m_jacAindex = m_data.m_jacobians.size();
+ m_data.m_jacobians.resize(m_data.m_jacobians.size() + ndofA);
+ m_data.m_deltaVelocitiesUnitImpulse.resize(m_data.m_deltaVelocitiesUnitImpulse.size() + ndofA);
+ btAssert(m_data.m_jacobians.size() == m_data.m_deltaVelocitiesUnitImpulse.size());
+
+ btScalar* jac1 = &m_data.m_jacobians[solverConstraint.m_jacAindex];
+ multiBodyA->fillConstraintJacobianMultiDof(solverConstraint.m_linkA, cp.getPositionWorldOnA(), constraintNormal, btVector3(0, 0, 0), jac1, m_data.scratch_r, m_data.scratch_v, m_data.scratch_m);
+ btScalar* delta = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
+ multiBodyA->calcAccelerationDeltasMultiDof(&m_data.m_jacobians[solverConstraint.m_jacAindex], delta, m_data.scratch_r, m_data.scratch_v);
+
+ btVector3 torqueAxis0 = -constraintNormal;
+ solverConstraint.m_relpos1CrossNormal = torqueAxis0;
+ solverConstraint.m_contactNormal1 = btVector3(0, 0, 0);
+ }
+ else
+ {
+ btVector3 torqueAxis0 = -constraintNormal;
+ solverConstraint.m_relpos1CrossNormal = torqueAxis0;
+ solverConstraint.m_contactNormal1 = btVector3(0, 0, 0);
+ solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld() * torqueAxis0 * rb0->getAngularFactor() : btVector3(0, 0, 0);
+ }
+
+ if (multiBodyB)
+ {
+ if (solverConstraint.m_linkB < 0)
+ {
+ rel_pos2 = pos2 - multiBodyB->getBasePos();
+ }
+ else
+ {
+ rel_pos2 = pos2 - multiBodyB->getLink(solverConstraint.m_linkB).m_cachedWorldTransform.getOrigin();
+ }
+
+ const int ndofB = multiBodyB->getNumDofs() + 6;
+
+ solverConstraint.m_deltaVelBindex = multiBodyB->getCompanionId();
+ if (solverConstraint.m_deltaVelBindex < 0)
+ {
+ solverConstraint.m_deltaVelBindex = m_data.m_deltaVelocities.size();
+ multiBodyB->setCompanionId(solverConstraint.m_deltaVelBindex);
+ m_data.m_deltaVelocities.resize(m_data.m_deltaVelocities.size() + ndofB);
+ }
+
+ solverConstraint.m_jacBindex = m_data.m_jacobians.size();
+
+ m_data.m_jacobians.resize(m_data.m_jacobians.size() + ndofB);
+ m_data.m_deltaVelocitiesUnitImpulse.resize(m_data.m_deltaVelocitiesUnitImpulse.size() + ndofB);
+ btAssert(m_data.m_jacobians.size() == m_data.m_deltaVelocitiesUnitImpulse.size());
+
+ multiBodyB->fillConstraintJacobianMultiDof(solverConstraint.m_linkB, cp.getPositionWorldOnB(), -constraintNormal, btVector3(0, 0, 0), &m_data.m_jacobians[solverConstraint.m_jacBindex], m_data.scratch_r, m_data.scratch_v, m_data.scratch_m);
+ multiBodyB->calcAccelerationDeltasMultiDof(&m_data.m_jacobians[solverConstraint.m_jacBindex], &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex], m_data.scratch_r, m_data.scratch_v);
+
+ btVector3 torqueAxis1 = constraintNormal;
+ solverConstraint.m_relpos2CrossNormal = torqueAxis1;
+ solverConstraint.m_contactNormal2 = -btVector3(0, 0, 0);
+ }
+ else
+ {
+ btVector3 torqueAxis1 = constraintNormal;
+ solverConstraint.m_relpos2CrossNormal = torqueAxis1;
+ solverConstraint.m_contactNormal2 = -btVector3(0, 0, 0);
+
+ solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld() * torqueAxis1 * rb1->getAngularFactor() : btVector3(0, 0, 0);
+ }
+
+ {
+ btScalar denom0 = 0.f;
+ btScalar denom1 = 0.f;
+ btScalar* jacB = 0;
+ btScalar* jacA = 0;
+ btScalar* lambdaA = 0;
+ btScalar* lambdaB = 0;
+ int ndofA = 0;
+ if (multiBodyA)
+ {
+ ndofA = multiBodyA->getNumDofs() + 6;
+ jacA = &m_data.m_jacobians[solverConstraint.m_jacAindex];
+ lambdaA = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
+ for (int i = 0; i < ndofA; ++i)
+ {
+ btScalar j = jacA[i];
+ btScalar l = lambdaA[i];
+ denom0 += j * l;
+ }
+ }
+ else
+ {
+ if (rb0)
+ {
+ btVector3 iMJaA = rb0 ? rb0->getInvInertiaTensorWorld() * solverConstraint.m_relpos1CrossNormal : btVector3(0, 0, 0);
denom0 = iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
- }
- }
- if (multiBodyB)
- {
- const int ndofB = multiBodyB->getNumDofs() + 6;
- jacB = &m_data.m_jacobians[solverConstraint.m_jacBindex];
- lambdaB = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
- for (int i = 0; i < ndofB; ++i)
- {
- btScalar j = jacB[i] ;
- btScalar l =lambdaB[i];
- denom1 += j*l;
- }
-
- } else
- {
- if (rb1)
- {
- btVector3 iMJaB = rb1?rb1->getInvInertiaTensorWorld()*solverConstraint.m_relpos2CrossNormal:btVector3(0,0,0);
+ }
+ }
+ if (multiBodyB)
+ {
+ const int ndofB = multiBodyB->getNumDofs() + 6;
+ jacB = &m_data.m_jacobians[solverConstraint.m_jacBindex];
+ lambdaB = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
+ for (int i = 0; i < ndofB; ++i)
+ {
+ btScalar j = jacB[i];
+ btScalar l = lambdaB[i];
+ denom1 += j * l;
+ }
+ }
+ else
+ {
+ if (rb1)
+ {
+ btVector3 iMJaB = rb1 ? rb1->getInvInertiaTensorWorld() * solverConstraint.m_relpos2CrossNormal : btVector3(0, 0, 0);
denom1 = iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
- }
- }
-
-
-
- btScalar d = denom0+denom1+infoGlobal.m_globalCfm;
- if (d>SIMD_EPSILON)
- {
- solverConstraint.m_jacDiagABInv = relaxation/(d);
- } else
- {
- //disable the constraint row to handle singularity/redundant constraint
- solverConstraint.m_jacDiagABInv = 0.f;
- }
-
- }
-
-
- //compute rhs and remaining solverConstraint fields
-
-
-
- btScalar restitution = 0.f;
- btScalar penetration = isFriction? 0 : cp.getDistance();
-
- btScalar rel_vel = 0.f;
- int ndofA = 0;
- int ndofB = 0;
- {
-
- btVector3 vel1,vel2;
- if (multiBodyA)
- {
- ndofA = multiBodyA->getNumDofs() + 6;
- btScalar* jacA = &m_data.m_jacobians[solverConstraint.m_jacAindex];
- for (int i = 0; i < ndofA ; ++i)
- rel_vel += multiBodyA->getVelocityVector()[i] * jacA[i];
- } else
- {
- if (rb0)
- {
+ }
+ }
+
+ btScalar d = denom0 + denom1 + infoGlobal.m_globalCfm;
+ if (d > SIMD_EPSILON)
+ {
+ solverConstraint.m_jacDiagABInv = relaxation / (d);
+ }
+ else
+ {
+ //disable the constraint row to handle singularity/redundant constraint
+ solverConstraint.m_jacDiagABInv = 0.f;
+ }
+ }
+
+ //compute rhs and remaining solverConstraint fields
+
+ btScalar restitution = 0.f;
+ btScalar penetration = isFriction ? 0 : cp.getDistance();
+
+ btScalar rel_vel = 0.f;
+ int ndofA = 0;
+ int ndofB = 0;
+ {
+ btVector3 vel1, vel2;
+ if (multiBodyA)
+ {
+ ndofA = multiBodyA->getNumDofs() + 6;
+ btScalar* jacA = &m_data.m_jacobians[solverConstraint.m_jacAindex];
+ for (int i = 0; i < ndofA; ++i)
+ rel_vel += multiBodyA->getVelocityVector()[i] * jacA[i];
+ }
+ else
+ {
+ if (rb0)
+ {
btSolverBody* solverBodyA = &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA];
- rel_vel += solverConstraint.m_contactNormal1.dot(rb0?solverBodyA->m_linearVelocity+solverBodyA->m_externalForceImpulse:btVector3(0,0,0))
- + solverConstraint.m_relpos1CrossNormal.dot(rb0?solverBodyA->m_angularVelocity:btVector3(0,0,0));
-
- }
- }
- if (multiBodyB)
- {
- ndofB = multiBodyB->getNumDofs() + 6;
- btScalar* jacB = &m_data.m_jacobians[solverConstraint.m_jacBindex];
- for (int i = 0; i < ndofB ; ++i)
- rel_vel += multiBodyB->getVelocityVector()[i] * jacB[i];
-
- } else
- {
- if (rb1)
- {
+ rel_vel += solverConstraint.m_contactNormal1.dot(rb0 ? solverBodyA->m_linearVelocity + solverBodyA->m_externalForceImpulse : btVector3(0, 0, 0)) + solverConstraint.m_relpos1CrossNormal.dot(rb0 ? solverBodyA->m_angularVelocity : btVector3(0, 0, 0));
+ }
+ }
+ if (multiBodyB)
+ {
+ ndofB = multiBodyB->getNumDofs() + 6;
+ btScalar* jacB = &m_data.m_jacobians[solverConstraint.m_jacBindex];
+ for (int i = 0; i < ndofB; ++i)
+ rel_vel += multiBodyB->getVelocityVector()[i] * jacB[i];
+ }
+ else
+ {
+ if (rb1)
+ {
btSolverBody* solverBodyB = &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB];
- rel_vel += solverConstraint.m_contactNormal2.dot(rb1?solverBodyB->m_linearVelocity+solverBodyB->m_externalForceImpulse:btVector3(0,0,0))
- + solverConstraint.m_relpos2CrossNormal.dot(rb1?solverBodyB->m_angularVelocity:btVector3(0,0,0));
-
- }
- }
-
- solverConstraint.m_friction =combinedTorsionalFriction;
-
- if(!isFriction)
- {
- restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution, infoGlobal.m_restitutionVelocityThreshold);
- if (restitution <= btScalar(0.))
- {
- restitution = 0.f;
- }
- }
- }
-
-
- solverConstraint.m_appliedImpulse = 0.f;
- solverConstraint.m_appliedPushImpulse = 0.f;
-
- {
-
- btScalar velocityError = 0 - rel_vel;// * damping; //note for friction restitution is always set to 0 (check above) so it is acutally velocityError = -rel_vel for friction
-
-
-
- btScalar velocityImpulse = velocityError*solverConstraint.m_jacDiagABInv;
-
- solverConstraint.m_rhs = velocityImpulse;
- solverConstraint.m_rhsPenetration = 0.f;
- solverConstraint.m_lowerLimit = -solverConstraint.m_friction;
- solverConstraint.m_upperLimit = solverConstraint.m_friction;
-
- solverConstraint.m_cfm = infoGlobal.m_globalCfm*solverConstraint.m_jacDiagABInv;
-
-
-
- }
-
+ rel_vel += solverConstraint.m_contactNormal2.dot(rb1 ? solverBodyB->m_linearVelocity + solverBodyB->m_externalForceImpulse : btVector3(0, 0, 0)) + solverConstraint.m_relpos2CrossNormal.dot(rb1 ? solverBodyB->m_angularVelocity : btVector3(0, 0, 0));
+ }
+ }
+
+ solverConstraint.m_friction = combinedTorsionalFriction;
+
+ if (!isFriction)
+ {
+ restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution, infoGlobal.m_restitutionVelocityThreshold);
+ if (restitution <= btScalar(0.))
+ {
+ restitution = 0.f;
+ }
+ }
+ }
+
+ solverConstraint.m_appliedImpulse = 0.f;
+ solverConstraint.m_appliedPushImpulse = 0.f;
+
+ {
+ btScalar velocityError = 0 - rel_vel; // * damping; //note for friction restitution is always set to 0 (check above) so it is acutally velocityError = -rel_vel for friction
+
+ btScalar velocityImpulse = velocityError * solverConstraint.m_jacDiagABInv;
+
+ solverConstraint.m_rhs = velocityImpulse;
+ solverConstraint.m_rhsPenetration = 0.f;
+ solverConstraint.m_lowerLimit = -solverConstraint.m_friction;
+ solverConstraint.m_upperLimit = solverConstraint.m_friction;
+
+ solverConstraint.m_cfm = infoGlobal.m_globalCfm * solverConstraint.m_jacDiagABInv;
+ }
}
-btMultiBodySolverConstraint& btMultiBodyConstraintSolver::addMultiBodyFrictionConstraint(const btVector3& normalAxis,btPersistentManifold* manifold,int frictionIndex,btManifoldPoint& cp,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
+btMultiBodySolverConstraint& btMultiBodyConstraintSolver::addMultiBodyFrictionConstraint(const btVector3& normalAxis, btPersistentManifold* manifold, int frictionIndex, btManifoldPoint& cp, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
{
BT_PROFILE("addMultiBodyFrictionConstraint");
btMultiBodySolverConstraint& solverConstraint = m_multiBodyFrictionContactConstraints.expandNonInitializing();
- solverConstraint.m_orgConstraint = 0;
- solverConstraint.m_orgDofIndex = -1;
-
+ solverConstraint.m_orgConstraint = 0;
+ solverConstraint.m_orgDofIndex = -1;
+
solverConstraint.m_frictionIndex = frictionIndex;
bool isFriction = true;
const btMultiBodyLinkCollider* fcA = btMultiBodyLinkCollider::upcast(manifold->getBody0());
const btMultiBodyLinkCollider* fcB = btMultiBodyLinkCollider::upcast(manifold->getBody1());
-
- btMultiBody* mbA = fcA? fcA->m_multiBody : 0;
- btMultiBody* mbB = fcB? fcB->m_multiBody : 0;
- int solverBodyIdA = mbA? -1 : getOrInitSolverBody(*colObj0,infoGlobal.m_timeStep);
- int solverBodyIdB = mbB ? -1 : getOrInitSolverBody(*colObj1,infoGlobal.m_timeStep);
+ btMultiBody* mbA = fcA ? fcA->m_multiBody : 0;
+ btMultiBody* mbB = fcB ? fcB->m_multiBody : 0;
+
+ int solverBodyIdA = mbA ? -1 : getOrInitSolverBody(*colObj0, infoGlobal.m_timeStep);
+ int solverBodyIdB = mbB ? -1 : getOrInitSolverBody(*colObj1, infoGlobal.m_timeStep);
solverConstraint.m_solverBodyIdA = solverBodyIdA;
solverConstraint.m_solverBodyIdB = solverBodyIdB;
@@ -1151,95 +1125,92 @@ btMultiBodySolverConstraint& btMultiBodyConstraintSolver::addMultiBodyFrictionCo
solverConstraint.m_originalContactPoint = &cp;
- setupMultiBodyContactConstraint(solverConstraint, normalAxis, cp, infoGlobal,relaxation,isFriction, desiredVelocity, cfmSlip);
+ setupMultiBodyContactConstraint(solverConstraint, normalAxis, cp, infoGlobal, relaxation, isFriction, desiredVelocity, cfmSlip);
return solverConstraint;
}
-btMultiBodySolverConstraint& btMultiBodyConstraintSolver::addMultiBodyTorsionalFrictionConstraint(const btVector3& normalAxis,btPersistentManifold* manifold,int frictionIndex,btManifoldPoint& cp,
- btScalar combinedTorsionalFriction,
- btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
+btMultiBodySolverConstraint& btMultiBodyConstraintSolver::addMultiBodyTorsionalFrictionConstraint(const btVector3& normalAxis, btPersistentManifold* manifold, int frictionIndex, btManifoldPoint& cp,
+ btScalar combinedTorsionalFriction,
+ btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
{
- BT_PROFILE("addMultiBodyRollingFrictionConstraint");
-
- bool useTorsionalAndConeFriction = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS && ((infoGlobal.m_solverMode&SOLVER_DISABLE_IMPLICIT_CONE_FRICTION) == 0));
-
- btMultiBodySolverConstraint& solverConstraint = useTorsionalAndConeFriction? m_multiBodyTorsionalFrictionContactConstraints.expandNonInitializing() : m_multiBodyFrictionContactConstraints.expandNonInitializing();
- solverConstraint.m_orgConstraint = 0;
- solverConstraint.m_orgDofIndex = -1;
-
- solverConstraint.m_frictionIndex = frictionIndex;
- bool isFriction = true;
-
- const btMultiBodyLinkCollider* fcA = btMultiBodyLinkCollider::upcast(manifold->getBody0());
- const btMultiBodyLinkCollider* fcB = btMultiBodyLinkCollider::upcast(manifold->getBody1());
-
- btMultiBody* mbA = fcA? fcA->m_multiBody : 0;
- btMultiBody* mbB = fcB? fcB->m_multiBody : 0;
-
- int solverBodyIdA = mbA? -1 : getOrInitSolverBody(*colObj0,infoGlobal.m_timeStep);
- int solverBodyIdB = mbB ? -1 : getOrInitSolverBody(*colObj1,infoGlobal.m_timeStep);
-
- solverConstraint.m_solverBodyIdA = solverBodyIdA;
- solverConstraint.m_solverBodyIdB = solverBodyIdB;
- solverConstraint.m_multiBodyA = mbA;
- if (mbA)
- solverConstraint.m_linkA = fcA->m_link;
-
- solverConstraint.m_multiBodyB = mbB;
- if (mbB)
- solverConstraint.m_linkB = fcB->m_link;
-
- solverConstraint.m_originalContactPoint = &cp;
-
- setupMultiBodyTorsionalFrictionConstraint(solverConstraint, normalAxis, cp, combinedTorsionalFriction,infoGlobal,relaxation,isFriction, desiredVelocity, cfmSlip);
- return solverConstraint;
+ BT_PROFILE("addMultiBodyRollingFrictionConstraint");
+
+ bool useTorsionalAndConeFriction = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS && ((infoGlobal.m_solverMode & SOLVER_DISABLE_IMPLICIT_CONE_FRICTION) == 0));
+
+ btMultiBodySolverConstraint& solverConstraint = useTorsionalAndConeFriction ? m_multiBodyTorsionalFrictionContactConstraints.expandNonInitializing() : m_multiBodyFrictionContactConstraints.expandNonInitializing();
+ solverConstraint.m_orgConstraint = 0;
+ solverConstraint.m_orgDofIndex = -1;
+
+ solverConstraint.m_frictionIndex = frictionIndex;
+ bool isFriction = true;
+
+ const btMultiBodyLinkCollider* fcA = btMultiBodyLinkCollider::upcast(manifold->getBody0());
+ const btMultiBodyLinkCollider* fcB = btMultiBodyLinkCollider::upcast(manifold->getBody1());
+
+ btMultiBody* mbA = fcA ? fcA->m_multiBody : 0;
+ btMultiBody* mbB = fcB ? fcB->m_multiBody : 0;
+
+ int solverBodyIdA = mbA ? -1 : getOrInitSolverBody(*colObj0, infoGlobal.m_timeStep);
+ int solverBodyIdB = mbB ? -1 : getOrInitSolverBody(*colObj1, infoGlobal.m_timeStep);
+
+ solverConstraint.m_solverBodyIdA = solverBodyIdA;
+ solverConstraint.m_solverBodyIdB = solverBodyIdB;
+ solverConstraint.m_multiBodyA = mbA;
+ if (mbA)
+ solverConstraint.m_linkA = fcA->m_link;
+
+ solverConstraint.m_multiBodyB = mbB;
+ if (mbB)
+ solverConstraint.m_linkB = fcB->m_link;
+
+ solverConstraint.m_originalContactPoint = &cp;
+
+ setupMultiBodyTorsionalFrictionConstraint(solverConstraint, normalAxis, cp, combinedTorsionalFriction, infoGlobal, relaxation, isFriction, desiredVelocity, cfmSlip);
+ return solverConstraint;
}
-void btMultiBodyConstraintSolver::convertMultiBodyContact(btPersistentManifold* manifold,const btContactSolverInfo& infoGlobal)
+void btMultiBodyConstraintSolver::convertMultiBodyContact(btPersistentManifold* manifold, const btContactSolverInfo& infoGlobal)
{
const btMultiBodyLinkCollider* fcA = btMultiBodyLinkCollider::upcast(manifold->getBody0());
const btMultiBodyLinkCollider* fcB = btMultiBodyLinkCollider::upcast(manifold->getBody1());
-
- btMultiBody* mbA = fcA? fcA->m_multiBody : 0;
- btMultiBody* mbB = fcB? fcB->m_multiBody : 0;
- btCollisionObject* colObj0=0,*colObj1=0;
+ btMultiBody* mbA = fcA ? fcA->m_multiBody : 0;
+ btMultiBody* mbB = fcB ? fcB->m_multiBody : 0;
+
+ btCollisionObject *colObj0 = 0, *colObj1 = 0;
colObj0 = (btCollisionObject*)manifold->getBody0();
colObj1 = (btCollisionObject*)manifold->getBody1();
- int solverBodyIdA = mbA? -1 : getOrInitSolverBody(*colObj0,infoGlobal.m_timeStep);
- int solverBodyIdB = mbB ? -1 : getOrInitSolverBody(*colObj1,infoGlobal.m_timeStep);
-
-// btSolverBody* solverBodyA = mbA ? 0 : &m_tmpSolverBodyPool[solverBodyIdA];
-// btSolverBody* solverBodyB = mbB ? 0 : &m_tmpSolverBodyPool[solverBodyIdB];
+ int solverBodyIdA = mbA ? -1 : getOrInitSolverBody(*colObj0, infoGlobal.m_timeStep);
+ int solverBodyIdB = mbB ? -1 : getOrInitSolverBody(*colObj1, infoGlobal.m_timeStep);
+ // btSolverBody* solverBodyA = mbA ? 0 : &m_tmpSolverBodyPool[solverBodyIdA];
+ // btSolverBody* solverBodyB = mbB ? 0 : &m_tmpSolverBodyPool[solverBodyIdB];
///avoid collision response between two static objects
-// if (!solverBodyA || (solverBodyA->m_invMass.isZero() && (!solverBodyB || solverBodyB->m_invMass.isZero())))
+ // if (!solverBodyA || (solverBodyA->m_invMass.isZero() && (!solverBodyB || solverBodyB->m_invMass.isZero())))
// return;
- //only a single rollingFriction per manifold
- int rollingFriction=1;
-
- for (int j=0;j<manifold->getNumContacts();j++)
- {
+ //only a single rollingFriction per manifold
+ int rollingFriction = 1;
+ for (int j = 0; j < manifold->getNumContacts(); j++)
+ {
btManifoldPoint& cp = manifold->getContactPoint(j);
if (cp.getDistance() <= manifold->getContactProcessingThreshold())
{
-
btScalar relaxation;
int frictionIndex = m_multiBodyNormalContactConstraints.size();
btMultiBodySolverConstraint& solverConstraint = m_multiBodyNormalContactConstraints.expandNonInitializing();
- // btRigidBody* rb0 = btRigidBody::upcast(colObj0);
- // btRigidBody* rb1 = btRigidBody::upcast(colObj1);
- solverConstraint.m_orgConstraint = 0;
- solverConstraint.m_orgDofIndex = -1;
+ // btRigidBody* rb0 = btRigidBody::upcast(colObj0);
+ // btRigidBody* rb1 = btRigidBody::upcast(colObj1);
+ solverConstraint.m_orgConstraint = 0;
+ solverConstraint.m_orgDofIndex = -1;
solverConstraint.m_solverBodyIdA = solverBodyIdA;
solverConstraint.m_solverBodyIdB = solverBodyIdB;
solverConstraint.m_multiBodyA = mbA;
@@ -1253,60 +1224,59 @@ void btMultiBodyConstraintSolver::convertMultiBodyContact(btPersistentManifold*
solverConstraint.m_originalContactPoint = &cp;
bool isFriction = false;
- setupMultiBodyContactConstraint(solverConstraint, cp.m_normalWorldOnB,cp, infoGlobal, relaxation, isFriction);
+ setupMultiBodyContactConstraint(solverConstraint, cp.m_normalWorldOnB, cp, infoGlobal, relaxation, isFriction);
-// const btVector3& pos1 = cp.getPositionWorldOnA();
-// const btVector3& pos2 = cp.getPositionWorldOnB();
+ // const btVector3& pos1 = cp.getPositionWorldOnA();
+ // const btVector3& pos2 = cp.getPositionWorldOnB();
/////setup the friction constraints
#define ENABLE_FRICTION
#ifdef ENABLE_FRICTION
- solverConstraint.m_frictionIndex = frictionIndex;
+ solverConstraint.m_frictionIndex = m_multiBodyFrictionContactConstraints.size();
///Bullet has several options to set the friction directions
///By default, each contact has only a single friction direction that is recomputed automatically every frame
///based on the relative linear velocity.
///If the relative velocity is zero, it will automatically compute a friction direction.
-
+
///You can also enable two friction directions, using the SOLVER_USE_2_FRICTION_DIRECTIONS.
///In that case, the second friction direction will be orthogonal to both contact normal and first friction direction.
///
///If you choose SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION, then the friction will be independent from the relative projected velocity.
///
- ///The user can manually override the friction directions for certain contacts using a contact callback,
+ ///The user can manually override the friction directions for certain contacts using a contact callback,
///and set the cp.m_lateralFrictionInitialized to true
///In that case, you can set the target relative motion in each friction direction (cp.m_contactMotion1 and cp.m_contactMotion2)
///this will give a conveyor belt effect
///
- btPlaneSpace1(cp.m_normalWorldOnB,cp.m_lateralFrictionDir1,cp.m_lateralFrictionDir2);
+ btPlaneSpace1(cp.m_normalWorldOnB, cp.m_lateralFrictionDir1, cp.m_lateralFrictionDir2);
cp.m_lateralFrictionDir1.normalize();
cp.m_lateralFrictionDir2.normalize();
- if (rollingFriction > 0 )
- {
- if (cp.m_combinedSpinningFriction>0)
- {
- addMultiBodyTorsionalFrictionConstraint(cp.m_normalWorldOnB,manifold,frictionIndex,cp,cp.m_combinedSpinningFriction, colObj0,colObj1, relaxation,infoGlobal);
- }
- if (cp.m_combinedRollingFriction>0)
- {
-
- applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
- applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
- applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
- applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
-
- if (cp.m_lateralFrictionDir1.length()>0.001)
- addMultiBodyTorsionalFrictionConstraint(cp.m_lateralFrictionDir1,manifold,frictionIndex,cp,cp.m_combinedRollingFriction, colObj0,colObj1, relaxation,infoGlobal);
-
- if (cp.m_lateralFrictionDir2.length()>0.001)
- addMultiBodyTorsionalFrictionConstraint(cp.m_lateralFrictionDir2,manifold,frictionIndex,cp,cp.m_combinedRollingFriction, colObj0,colObj1, relaxation,infoGlobal);
- }
- rollingFriction--;
- }
- if (!(infoGlobal.m_solverMode & SOLVER_ENABLE_FRICTION_DIRECTION_CACHING) || !(cp.m_contactPointFlags&BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED))
- {/*
+ if (rollingFriction > 0)
+ {
+ if (cp.m_combinedSpinningFriction > 0)
+ {
+ addMultiBodyTorsionalFrictionConstraint(cp.m_normalWorldOnB, manifold, frictionIndex, cp, cp.m_combinedSpinningFriction, colObj0, colObj1, relaxation, infoGlobal);
+ }
+ if (cp.m_combinedRollingFriction > 0)
+ {
+ applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
+ applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
+ applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
+ applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
+
+ if (cp.m_lateralFrictionDir1.length() > 0.001)
+ addMultiBodyTorsionalFrictionConstraint(cp.m_lateralFrictionDir1, manifold, frictionIndex, cp, cp.m_combinedRollingFriction, colObj0, colObj1, relaxation, infoGlobal);
+
+ if (cp.m_lateralFrictionDir2.length() > 0.001)
+ addMultiBodyTorsionalFrictionConstraint(cp.m_lateralFrictionDir2, manifold, frictionIndex, cp, cp.m_combinedRollingFriction, colObj0, colObj1, relaxation, infoGlobal);
+ }
+ rollingFriction--;
+ }
+ if (!(infoGlobal.m_solverMode & SOLVER_ENABLE_FRICTION_DIRECTION_CACHING) || !(cp.m_contactPointFlags & BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED))
+ { /*
cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel;
btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2();
if (!(infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION) && lat_rel_vel > SIMD_EPSILON)
@@ -1329,85 +1299,77 @@ void btMultiBodyConstraintSolver::convertMultiBodyContact(btPersistentManifold*
} else
*/
{
-
-
- applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION);
- applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION);
- addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir1,manifold,frictionIndex,cp,colObj0,colObj1, relaxation,infoGlobal);
-
+ applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+ applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+ addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir1, manifold, frictionIndex, cp, colObj0, colObj1, relaxation, infoGlobal);
if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
{
- applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION);
- applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION);
- addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir2,manifold,frictionIndex,cp,colObj0,colObj1, relaxation,infoGlobal);
+ applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+ applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+ addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir2, manifold, frictionIndex, cp, colObj0, colObj1, relaxation, infoGlobal);
}
if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION))
{
- cp.m_contactPointFlags|=BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED;
+ cp.m_contactPointFlags |= BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED;
}
}
-
- } else
+ }
+ else
{
- addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir1,manifold,frictionIndex,cp,colObj0,colObj1, relaxation,infoGlobal,cp.m_contactMotion1, cp.m_frictionCFM);
+ addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir1, manifold, frictionIndex, cp, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion1, cp.m_frictionCFM);
if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
- addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir2,manifold,frictionIndex,cp,colObj0,colObj1, relaxation, infoGlobal,cp.m_contactMotion2, cp.m_frictionCFM);
+ addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir2, manifold, frictionIndex, cp, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion2, cp.m_frictionCFM);
//setMultiBodyFrictionConstraintImpulse( solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal);
//todo:
solverConstraint.m_appliedImpulse = 0.f;
solverConstraint.m_appliedPushImpulse = 0.f;
}
-
-
-#endif //ENABLE_FRICTION
+#endif //ENABLE_FRICTION
}
}
}
-void btMultiBodyConstraintSolver::convertContacts(btPersistentManifold** manifoldPtr,int numManifolds, const btContactSolverInfo& infoGlobal)
+void btMultiBodyConstraintSolver::convertContacts(btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal)
{
//btPersistentManifold* manifold = 0;
- for (int i=0;i<numManifolds;i++)
+ for (int i = 0; i < numManifolds; i++)
{
- btPersistentManifold* manifold= manifoldPtr[i];
+ btPersistentManifold* manifold = manifoldPtr[i];
const btMultiBodyLinkCollider* fcA = btMultiBodyLinkCollider::upcast(manifold->getBody0());
const btMultiBodyLinkCollider* fcB = btMultiBodyLinkCollider::upcast(manifold->getBody1());
if (!fcA && !fcB)
{
//the contact doesn't involve any Featherstone btMultiBody, so deal with the regular btRigidBody/btCollisionObject case
- convertContact(manifold,infoGlobal);
- } else
+ convertContact(manifold, infoGlobal);
+ }
+ else
{
- convertMultiBodyContact(manifold,infoGlobal);
+ convertMultiBodyContact(manifold, infoGlobal);
}
}
//also convert the multibody constraints, if any
-
- for (int i=0;i<m_tmpNumMultiBodyConstraints;i++)
+ for (int i = 0; i < m_tmpNumMultiBodyConstraints; i++)
{
btMultiBodyConstraint* c = m_tmpMultiBodyConstraints[i];
m_data.m_solverBodyPool = &m_tmpSolverBodyPool;
m_data.m_fixedBodyId = m_fixedBodyId;
-
- c->createConstraintRows(m_multiBodyNonContactConstraints,m_data, infoGlobal);
- }
+ c->createConstraintRows(m_multiBodyNonContactConstraints, m_data, infoGlobal);
+ }
}
-
-
-btScalar btMultiBodyConstraintSolver::solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& info, btIDebugDraw* debugDrawer,btDispatcher* dispatcher)
+btScalar btMultiBodyConstraintSolver::solveGroup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifold, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btDispatcher* dispatcher)
{
//printf("btMultiBodyConstraintSolver::solveGroup: numBodies=%d, numConstraints=%d\n", numBodies, numConstraints);
- return btSequentialImpulseConstraintSolver::solveGroup(bodies,numBodies,manifold,numManifolds,constraints,numConstraints,info,debugDrawer,dispatcher);
+ return btSequentialImpulseConstraintSolver::solveGroup(bodies, numBodies, manifold, numManifolds, constraints, numConstraints, info, debugDrawer, dispatcher);
}
#if 0
@@ -1431,56 +1393,54 @@ static void applyJointFeedback(btMultiBodyJacobianData& data, const btMultiBodyS
}
#endif
-
void btMultiBodyConstraintSolver::writeBackSolverBodyToMultiBody(btMultiBodySolverConstraint& c, btScalar deltaTime)
{
-#if 1
-
+#if 1
+
//bod->addBaseForce(m_gravity * bod->getBaseMass());
//bod->addLinkForce(j, m_gravity * bod->getLinkMass(j));
if (c.m_orgConstraint)
{
- c.m_orgConstraint->internalSetAppliedImpulse(c.m_orgDofIndex,c.m_appliedImpulse);
+ c.m_orgConstraint->internalSetAppliedImpulse(c.m_orgDofIndex, c.m_appliedImpulse);
}
-
if (c.m_multiBodyA)
{
-
c.m_multiBodyA->setCompanionId(-1);
- btVector3 force = c.m_contactNormal1*(c.m_appliedImpulse/deltaTime);
- btVector3 torque = c.m_relpos1CrossNormal*(c.m_appliedImpulse/deltaTime);
- if (c.m_linkA<0)
+ btVector3 force = c.m_contactNormal1 * (c.m_appliedImpulse / deltaTime);
+ btVector3 torque = c.m_relpos1CrossNormal * (c.m_appliedImpulse / deltaTime);
+ if (c.m_linkA < 0)
{
c.m_multiBodyA->addBaseConstraintForce(force);
c.m_multiBodyA->addBaseConstraintTorque(torque);
- } else
+ }
+ else
{
- c.m_multiBodyA->addLinkConstraintForce(c.m_linkA,force);
- //b3Printf("force = %f,%f,%f\n",force[0],force[1],force[2]);//[0],torque[1],torque[2]);
- c.m_multiBodyA->addLinkConstraintTorque(c.m_linkA,torque);
+ c.m_multiBodyA->addLinkConstraintForce(c.m_linkA, force);
+ //b3Printf("force = %f,%f,%f\n",force[0],force[1],force[2]);//[0],torque[1],torque[2]);
+ c.m_multiBodyA->addLinkConstraintTorque(c.m_linkA, torque);
}
}
-
+
if (c.m_multiBodyB)
{
{
c.m_multiBodyB->setCompanionId(-1);
- btVector3 force = c.m_contactNormal2*(c.m_appliedImpulse/deltaTime);
- btVector3 torque = c.m_relpos2CrossNormal*(c.m_appliedImpulse/deltaTime);
- if (c.m_linkB<0)
+ btVector3 force = c.m_contactNormal2 * (c.m_appliedImpulse / deltaTime);
+ btVector3 torque = c.m_relpos2CrossNormal * (c.m_appliedImpulse / deltaTime);
+ if (c.m_linkB < 0)
{
c.m_multiBodyB->addBaseConstraintForce(force);
c.m_multiBodyB->addBaseConstraintTorque(torque);
- } else
+ }
+ else
{
{
- c.m_multiBodyB->addLinkConstraintForce(c.m_linkB,force);
+ c.m_multiBodyB->addLinkConstraintForce(c.m_linkB, force);
//b3Printf("t = %f,%f,%f\n",force[0],force[1],force[2]);//[0],torque[1],torque[2]);
- c.m_multiBodyB->addLinkConstraintTorque(c.m_linkB,torque);
+ c.m_multiBodyB->addLinkConstraintTorque(c.m_linkB, torque);
}
-
}
}
}
@@ -1490,66 +1450,64 @@ void btMultiBodyConstraintSolver::writeBackSolverBodyToMultiBody(btMultiBodySolv
if (c.m_multiBodyA)
{
- c.m_multiBodyA->applyDeltaVeeMultiDof(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacAindex],c.m_appliedImpulse);
+ c.m_multiBodyA->applyDeltaVeeMultiDof(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacAindex], c.m_appliedImpulse);
}
-
+
if (c.m_multiBodyB)
{
- c.m_multiBodyB->applyDeltaVeeMultiDof(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacBindex],c.m_appliedImpulse);
+ c.m_multiBodyB->applyDeltaVeeMultiDof(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacBindex], c.m_appliedImpulse);
}
#endif
-
-
-
}
-btScalar btMultiBodyConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionObject** bodies,int numBodies,const btContactSolverInfo& infoGlobal)
+btScalar btMultiBodyConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
{
BT_PROFILE("btMultiBodyConstraintSolver::solveGroupCacheFriendlyFinish");
int numPoolConstraints = m_multiBodyNormalContactConstraints.size();
-
- //write back the delta v to the multi bodies, either as applied impulse (direct velocity change)
+ //write back the delta v to the multi bodies, either as applied impulse (direct velocity change)
//or as applied force, so we can measure the joint reaction forces easier
- for (int i=0;i<numPoolConstraints;i++)
+ for (int i = 0; i < numPoolConstraints; i++)
{
btMultiBodySolverConstraint& solverConstraint = m_multiBodyNormalContactConstraints[i];
- writeBackSolverBodyToMultiBody(solverConstraint,infoGlobal.m_timeStep);
+ writeBackSolverBodyToMultiBody(solverConstraint, infoGlobal.m_timeStep);
- writeBackSolverBodyToMultiBody(m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex],infoGlobal.m_timeStep);
+ writeBackSolverBodyToMultiBody(m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex], infoGlobal.m_timeStep);
if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
{
- writeBackSolverBodyToMultiBody(m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1],infoGlobal.m_timeStep);
+ writeBackSolverBodyToMultiBody(m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex + 1], infoGlobal.m_timeStep);
}
}
-
- for (int i=0;i<m_multiBodyNonContactConstraints.size();i++)
+ for (int i = 0; i < m_multiBodyNonContactConstraints.size(); i++)
{
btMultiBodySolverConstraint& solverConstraint = m_multiBodyNonContactConstraints[i];
- writeBackSolverBodyToMultiBody(solverConstraint,infoGlobal.m_timeStep);
+ writeBackSolverBodyToMultiBody(solverConstraint, infoGlobal.m_timeStep);
}
-
if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
{
BT_PROFILE("warm starting write back");
- for (int j=0;j<numPoolConstraints;j++)
+ for (int j = 0; j < numPoolConstraints; j++)
{
const btMultiBodySolverConstraint& solverConstraint = m_multiBodyNormalContactConstraints[j];
- btManifoldPoint* pt = (btManifoldPoint*) solverConstraint.m_originalContactPoint;
+ btManifoldPoint* pt = (btManifoldPoint*)solverConstraint.m_originalContactPoint;
btAssert(pt);
pt->m_appliedImpulse = solverConstraint.m_appliedImpulse;
pt->m_appliedImpulseLateral1 = m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_appliedImpulse;
-
+
//printf("pt->m_appliedImpulseLateral1 = %f\n", pt->m_appliedImpulseLateral1);
if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
{
- pt->m_appliedImpulseLateral2 = m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_appliedImpulse;
+ pt->m_appliedImpulseLateral2 = m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex + 1].m_appliedImpulse;
+ } else
+ {
+ pt->m_appliedImpulseLateral2 = 0;
}
- //do a callback here?
}
+
+ //do a callback here?
}
#if 0
//multibody joint feedback
@@ -1648,25 +1606,22 @@ btScalar btMultiBodyConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionO
}
}
-#endif
+#endif
#endif
- return btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish(bodies,numBodies,infoGlobal);
+ return btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish(bodies, numBodies, infoGlobal);
}
-
-void btMultiBodyConstraintSolver::solveMultiBodyGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,btMultiBodyConstraint** multiBodyConstraints, int numMultiBodyConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer,btDispatcher* dispatcher)
+void btMultiBodyConstraintSolver::solveMultiBodyGroup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifold, int numManifolds, btTypedConstraint** constraints, int numConstraints, btMultiBodyConstraint** multiBodyConstraints, int numMultiBodyConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btDispatcher* dispatcher)
{
//printf("solveMultiBodyGroup: numBodies=%d, numConstraints=%d, numManifolds=%d, numMultiBodyConstraints=%d\n", numBodies, numConstraints, numManifolds, numMultiBodyConstraints);
//printf("solveMultiBodyGroup start\n");
m_tmpMultiBodyConstraints = multiBodyConstraints;
m_tmpNumMultiBodyConstraints = numMultiBodyConstraints;
-
- btSequentialImpulseConstraintSolver::solveGroup(bodies,numBodies,manifold,numManifolds,constraints,numConstraints,info,debugDrawer,dispatcher);
+
+ btSequentialImpulseConstraintSolver::solveGroup(bodies, numBodies, manifold, numManifolds, constraints, numConstraints, info, debugDrawer, dispatcher);
m_tmpMultiBodyConstraints = 0;
m_tmpNumMultiBodyConstraints = 0;
-
-
}
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h
index 29f484e1d8..f39f2879fc 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h
@@ -25,80 +25,71 @@ class btMultiBody;
#include "btMultiBodyConstraint.h"
-
-
-ATTRIBUTE_ALIGNED16(class) btMultiBodyConstraintSolver : public btSequentialImpulseConstraintSolver
+ATTRIBUTE_ALIGNED16(class)
+btMultiBodyConstraintSolver : public btSequentialImpulseConstraintSolver
{
-
protected:
+ btMultiBodyConstraintArray m_multiBodyNonContactConstraints;
- btMultiBodyConstraintArray m_multiBodyNonContactConstraints;
+ btMultiBodyConstraintArray m_multiBodyNormalContactConstraints;
+ btMultiBodyConstraintArray m_multiBodyFrictionContactConstraints;
+ btMultiBodyConstraintArray m_multiBodyTorsionalFrictionContactConstraints;
- btMultiBodyConstraintArray m_multiBodyNormalContactConstraints;
- btMultiBodyConstraintArray m_multiBodyFrictionContactConstraints;
- btMultiBodyConstraintArray m_multiBodyTorsionalFrictionContactConstraints;
+ btMultiBodyJacobianData m_data;
- btMultiBodyJacobianData m_data;
-
//temp storage for multi body constraints for a specific island/group called by 'solveGroup'
- btMultiBodyConstraint** m_tmpMultiBodyConstraints;
- int m_tmpNumMultiBodyConstraints;
+ btMultiBodyConstraint** m_tmpMultiBodyConstraints;
+ int m_tmpNumMultiBodyConstraints;
btScalar resolveSingleConstraintRowGeneric(const btMultiBodySolverConstraint& c);
-
+
//solve 2 friction directions and clamp against the implicit friction cone
btScalar resolveConeFrictionConstraintRows(const btMultiBodySolverConstraint& cA1, const btMultiBodySolverConstraint& cB);
-
-
- void convertContacts(btPersistentManifold** manifoldPtr,int numManifolds, const btContactSolverInfo& infoGlobal);
-
- btMultiBodySolverConstraint& addMultiBodyFrictionConstraint(const btVector3& normalAxis,btPersistentManifold* manifold,int frictionIndex,btManifoldPoint& cp,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity=0, btScalar cfmSlip=0);
-
- btMultiBodySolverConstraint& addMultiBodyTorsionalFrictionConstraint(const btVector3& normalAxis,btPersistentManifold* manifold,int frictionIndex,btManifoldPoint& cp,
- btScalar combinedTorsionalFriction,
- btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity=0, btScalar cfmSlip=0);
-
- void setupMultiBodyJointLimitConstraint(btMultiBodySolverConstraint& constraintRow,
- btScalar* jacA,btScalar* jacB,
- btScalar penetration,btScalar combinedFrictionCoeff, btScalar combinedRestitutionCoeff,
- const btContactSolverInfo& infoGlobal);
-
- void setupMultiBodyContactConstraint(btMultiBodySolverConstraint& solverConstraint,
- const btVector3& contactNormal,
- btManifoldPoint& cp, const btContactSolverInfo& infoGlobal,
- btScalar& relaxation,
- bool isFriction, btScalar desiredVelocity=0, btScalar cfmSlip=0);
-
- //either rolling or spinning friction
- void setupMultiBodyTorsionalFrictionConstraint(btMultiBodySolverConstraint& solverConstraint,
- const btVector3& contactNormal,
- btManifoldPoint& cp,
- btScalar combinedTorsionalFriction,
- const btContactSolverInfo& infoGlobal,
- btScalar& relaxation,
- bool isFriction, btScalar desiredVelocity=0, btScalar cfmSlip=0);
-
- void convertMultiBodyContact(btPersistentManifold* manifold,const btContactSolverInfo& infoGlobal);
- virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer);
-// virtual btScalar solveGroupCacheFriendlyIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer);
-
- virtual btScalar solveSingleIteration(int iteration, btCollisionObject** bodies ,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer);
- void applyDeltaVee(btScalar* deltaV, btScalar impulse, int velocityIndex, int ndof);
- void writeBackSolverBodyToMultiBody(btMultiBodySolverConstraint& constraint, btScalar deltaTime);
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
+ void convertContacts(btPersistentManifold * *manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal);
- ///this method should not be called, it was just used during porting/integration of Featherstone btMultiBody, providing backwards compatibility but no support for btMultiBodyConstraint (only contact constraints)
- virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& info, btIDebugDraw* debugDrawer,btDispatcher* dispatcher);
- virtual btScalar solveGroupCacheFriendlyFinish(btCollisionObject** bodies,int numBodies,const btContactSolverInfo& infoGlobal);
-
- virtual void solveMultiBodyGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,btMultiBodyConstraint** multiBodyConstraints, int numMultiBodyConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer,btDispatcher* dispatcher);
-};
+ btMultiBodySolverConstraint& addMultiBodyFrictionConstraint(const btVector3& normalAxis, btPersistentManifold* manifold, int frictionIndex, btManifoldPoint& cp, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity = 0, btScalar cfmSlip = 0);
+
+ btMultiBodySolverConstraint& addMultiBodyTorsionalFrictionConstraint(const btVector3& normalAxis, btPersistentManifold* manifold, int frictionIndex, btManifoldPoint& cp,
+ btScalar combinedTorsionalFriction,
+ btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity = 0, btScalar cfmSlip = 0);
-
-
+ void setupMultiBodyJointLimitConstraint(btMultiBodySolverConstraint & constraintRow,
+ btScalar * jacA, btScalar * jacB,
+ btScalar penetration, btScalar combinedFrictionCoeff, btScalar combinedRestitutionCoeff,
+ const btContactSolverInfo& infoGlobal);
+ void setupMultiBodyContactConstraint(btMultiBodySolverConstraint & solverConstraint,
+ const btVector3& contactNormal,
+ btManifoldPoint& cp, const btContactSolverInfo& infoGlobal,
+ btScalar& relaxation,
+ bool isFriction, btScalar desiredVelocity = 0, btScalar cfmSlip = 0);
-#endif //BT_MULTIBODY_CONSTRAINT_SOLVER_H
+ //either rolling or spinning friction
+ void setupMultiBodyTorsionalFrictionConstraint(btMultiBodySolverConstraint & solverConstraint,
+ const btVector3& contactNormal,
+ btManifoldPoint& cp,
+ btScalar combinedTorsionalFriction,
+ const btContactSolverInfo& infoGlobal,
+ btScalar& relaxation,
+ bool isFriction, btScalar desiredVelocity = 0, btScalar cfmSlip = 0);
+
+ void convertMultiBodyContact(btPersistentManifold * manifold, const btContactSolverInfo& infoGlobal);
+ virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
+ // virtual btScalar solveGroupCacheFriendlyIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer);
+
+ virtual btScalar solveSingleIteration(int iteration, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
+ void applyDeltaVee(btScalar * deltaV, btScalar impulse, int velocityIndex, int ndof);
+ void writeBackSolverBodyToMultiBody(btMultiBodySolverConstraint & constraint, btScalar deltaTime);
+
+public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ ///this method should not be called, it was just used during porting/integration of Featherstone btMultiBody, providing backwards compatibility but no support for btMultiBodyConstraint (only contact constraints)
+ virtual btScalar solveGroup(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifold, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btDispatcher* dispatcher);
+ virtual btScalar solveGroupCacheFriendlyFinish(btCollisionObject * *bodies, int numBodies, const btContactSolverInfo& infoGlobal);
+
+ virtual void solveMultiBodyGroup(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifold, int numManifolds, btTypedConstraint** constraints, int numConstraints, btMultiBodyConstraint** multiBodyConstraints, int numMultiBodyConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btDispatcher* dispatcher);
+};
+#endif //BT_MULTIBODY_CONSTRAINT_SOLVER_H
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp
index 9c5f3ad8a9..1557987bc3 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp
@@ -23,45 +23,43 @@ subject to the following restrictions:
#include "LinearMath/btIDebugDraw.h"
#include "LinearMath/btSerializer.h"
-
-void btMultiBodyDynamicsWorld::addMultiBody(btMultiBody* body, int group, int mask)
+void btMultiBodyDynamicsWorld::addMultiBody(btMultiBody* body, int group, int mask)
{
m_multiBodies.push_back(body);
-
}
-void btMultiBodyDynamicsWorld::removeMultiBody(btMultiBody* body)
+void btMultiBodyDynamicsWorld::removeMultiBody(btMultiBody* body)
{
m_multiBodies.remove(body);
}
-void btMultiBodyDynamicsWorld::calculateSimulationIslands()
+void btMultiBodyDynamicsWorld::calculateSimulationIslands()
{
BT_PROFILE("calculateSimulationIslands");
- getSimulationIslandManager()->updateActivationState(getCollisionWorld(),getCollisionWorld()->getDispatcher());
-
- {
- //merge islands based on speculative contact manifolds too
- for (int i=0;i<this->m_predictiveManifolds.size();i++)
- {
- btPersistentManifold* manifold = m_predictiveManifolds[i];
-
- const btCollisionObject* colObj0 = manifold->getBody0();
- const btCollisionObject* colObj1 = manifold->getBody1();
-
- if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) &&
- ((colObj1) && (!(colObj1)->isStaticOrKinematicObject())))
- {
- getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(),(colObj1)->getIslandTag());
- }
- }
- }
-
+ getSimulationIslandManager()->updateActivationState(getCollisionWorld(), getCollisionWorld()->getDispatcher());
+
+ {
+ //merge islands based on speculative contact manifolds too
+ for (int i = 0; i < this->m_predictiveManifolds.size(); i++)
+ {
+ btPersistentManifold* manifold = m_predictiveManifolds[i];
+
+ const btCollisionObject* colObj0 = manifold->getBody0();
+ const btCollisionObject* colObj1 = manifold->getBody1();
+
+ if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) &&
+ ((colObj1) && (!(colObj1)->isStaticOrKinematicObject())))
+ {
+ getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(), (colObj1)->getIslandTag());
+ }
+ }
+ }
+
{
int i;
int numConstraints = int(m_constraints.size());
- for (i=0;i< numConstraints ; i++ )
+ for (i = 0; i < numConstraints; i++)
{
btTypedConstraint* constraint = m_constraints[i];
if (constraint->isEnabled())
@@ -72,23 +70,23 @@ void btMultiBodyDynamicsWorld::calculateSimulationIslands()
if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) &&
((colObj1) && (!(colObj1)->isStaticOrKinematicObject())))
{
- getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(),(colObj1)->getIslandTag());
+ getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(), (colObj1)->getIslandTag());
}
}
}
}
//merge islands linked by Featherstone link colliders
- for (int i=0;i<m_multiBodies.size();i++)
+ for (int i = 0; i < m_multiBodies.size(); i++)
{
btMultiBody* body = m_multiBodies[i];
{
btMultiBodyLinkCollider* prev = body->getBaseCollider();
- for (int b=0;b<body->getNumLinks();b++)
+ for (int b = 0; b < body->getNumLinks(); b++)
{
btMultiBodyLinkCollider* cur = body->getLink(b).m_collider;
-
+
if (((cur) && (!(cur)->isStaticOrKinematicObject())) &&
((prev) && (!(prev)->isStaticOrKinematicObject())))
{
@@ -98,36 +96,31 @@ void btMultiBodyDynamicsWorld::calculateSimulationIslands()
}
if (cur && !cur->isStaticOrKinematicObject())
prev = cur;
-
}
}
}
//merge islands linked by multibody constraints
{
- for (int i=0;i<this->m_multiBodyConstraints.size();i++)
+ for (int i = 0; i < this->m_multiBodyConstraints.size(); i++)
{
btMultiBodyConstraint* c = m_multiBodyConstraints[i];
int tagA = c->getIslandIdA();
int tagB = c->getIslandIdB();
- if (tagA>=0 && tagB>=0)
+ if (tagA >= 0 && tagB >= 0)
getSimulationIslandManager()->getUnionFind().unite(tagA, tagB);
}
}
//Store the island id in each body
getSimulationIslandManager()->storeIslandActivationState(getCollisionWorld());
-
}
-
-void btMultiBodyDynamicsWorld::updateActivationState(btScalar timeStep)
+void btMultiBodyDynamicsWorld::updateActivationState(btScalar timeStep)
{
BT_PROFILE("btMultiBodyDynamicsWorld::updateActivationState");
-
-
- for ( int i=0;i<m_multiBodies.size();i++)
+ for (int i = 0; i < m_multiBodies.size(); i++)
{
btMultiBody* body = m_multiBodies[i];
if (body)
@@ -138,119 +131,108 @@ void btMultiBodyDynamicsWorld::updateActivationState(btScalar timeStep)
btMultiBodyLinkCollider* col = body->getBaseCollider();
if (col && col->getActivationState() == ACTIVE_TAG)
{
- col->setActivationState( WANTS_DEACTIVATION);
+ col->setActivationState(WANTS_DEACTIVATION);
col->setDeactivationTime(0.f);
}
- for (int b=0;b<body->getNumLinks();b++)
+ for (int b = 0; b < body->getNumLinks(); b++)
{
btMultiBodyLinkCollider* col = body->getLink(b).m_collider;
if (col && col->getActivationState() == ACTIVE_TAG)
{
- col->setActivationState( WANTS_DEACTIVATION);
+ col->setActivationState(WANTS_DEACTIVATION);
col->setDeactivationTime(0.f);
}
}
- } else
+ }
+ else
{
btMultiBodyLinkCollider* col = body->getBaseCollider();
if (col && col->getActivationState() != DISABLE_DEACTIVATION)
- col->setActivationState( ACTIVE_TAG );
+ col->setActivationState(ACTIVE_TAG);
- for (int b=0;b<body->getNumLinks();b++)
+ for (int b = 0; b < body->getNumLinks(); b++)
{
btMultiBodyLinkCollider* col = body->getLink(b).m_collider;
if (col && col->getActivationState() != DISABLE_DEACTIVATION)
- col->setActivationState( ACTIVE_TAG );
+ col->setActivationState(ACTIVE_TAG);
}
}
-
}
}
btDiscreteDynamicsWorld::updateActivationState(timeStep);
}
-
-SIMD_FORCE_INLINE int btGetConstraintIslandId2(const btTypedConstraint* lhs)
+SIMD_FORCE_INLINE int btGetConstraintIslandId2(const btTypedConstraint* lhs)
{
int islandId;
-
+
const btCollisionObject& rcolObj0 = lhs->getRigidBodyA();
const btCollisionObject& rcolObj1 = lhs->getRigidBodyB();
- islandId= rcolObj0.getIslandTag()>=0?rcolObj0.getIslandTag():rcolObj1.getIslandTag();
+ islandId = rcolObj0.getIslandTag() >= 0 ? rcolObj0.getIslandTag() : rcolObj1.getIslandTag();
return islandId;
-
}
-
class btSortConstraintOnIslandPredicate2
{
- public:
-
- bool operator() ( const btTypedConstraint* lhs, const btTypedConstraint* rhs ) const
- {
- int rIslandId0,lIslandId0;
- rIslandId0 = btGetConstraintIslandId2(rhs);
- lIslandId0 = btGetConstraintIslandId2(lhs);
- return lIslandId0 < rIslandId0;
- }
+public:
+ bool operator()(const btTypedConstraint* lhs, const btTypedConstraint* rhs) const
+ {
+ int rIslandId0, lIslandId0;
+ rIslandId0 = btGetConstraintIslandId2(rhs);
+ lIslandId0 = btGetConstraintIslandId2(lhs);
+ return lIslandId0 < rIslandId0;
+ }
};
-
-
-SIMD_FORCE_INLINE int btGetMultiBodyConstraintIslandId(const btMultiBodyConstraint* lhs)
+SIMD_FORCE_INLINE int btGetMultiBodyConstraintIslandId(const btMultiBodyConstraint* lhs)
{
int islandId;
-
+
int islandTagA = lhs->getIslandIdA();
int islandTagB = lhs->getIslandIdB();
- islandId= islandTagA>=0?islandTagA:islandTagB;
+ islandId = islandTagA >= 0 ? islandTagA : islandTagB;
return islandId;
-
}
-
class btSortMultiBodyConstraintOnIslandPredicate
{
- public:
-
- bool operator() ( const btMultiBodyConstraint* lhs, const btMultiBodyConstraint* rhs ) const
- {
- int rIslandId0,lIslandId0;
- rIslandId0 = btGetMultiBodyConstraintIslandId(rhs);
- lIslandId0 = btGetMultiBodyConstraintIslandId(lhs);
- return lIslandId0 < rIslandId0;
- }
+public:
+ bool operator()(const btMultiBodyConstraint* lhs, const btMultiBodyConstraint* rhs) const
+ {
+ int rIslandId0, lIslandId0;
+ rIslandId0 = btGetMultiBodyConstraintIslandId(rhs);
+ lIslandId0 = btGetMultiBodyConstraintIslandId(lhs);
+ return lIslandId0 < rIslandId0;
+ }
};
struct MultiBodyInplaceSolverIslandCallback : public btSimulationIslandManager::IslandCallback
{
- btContactSolverInfo* m_solverInfo;
- btMultiBodyConstraintSolver* m_solver;
- btMultiBodyConstraint** m_multiBodySortedConstraints;
- int m_numMultiBodyConstraints;
-
- btTypedConstraint** m_sortedConstraints;
- int m_numConstraints;
- btIDebugDraw* m_debugDrawer;
- btDispatcher* m_dispatcher;
-
+ btContactSolverInfo* m_solverInfo;
+ btMultiBodyConstraintSolver* m_solver;
+ btMultiBodyConstraint** m_multiBodySortedConstraints;
+ int m_numMultiBodyConstraints;
+
+ btTypedConstraint** m_sortedConstraints;
+ int m_numConstraints;
+ btIDebugDraw* m_debugDrawer;
+ btDispatcher* m_dispatcher;
+
btAlignedObjectArray<btCollisionObject*> m_bodies;
btAlignedObjectArray<btPersistentManifold*> m_manifolds;
btAlignedObjectArray<btTypedConstraint*> m_constraints;
btAlignedObjectArray<btMultiBodyConstraint*> m_multiBodyConstraints;
-
- MultiBodyInplaceSolverIslandCallback( btMultiBodyConstraintSolver* solver,
- btDispatcher* dispatcher)
- :m_solverInfo(NULL),
- m_solver(solver),
- m_multiBodySortedConstraints(NULL),
- m_numConstraints(0),
- m_debugDrawer(NULL),
- m_dispatcher(dispatcher)
+ MultiBodyInplaceSolverIslandCallback(btMultiBodyConstraintSolver* solver,
+ btDispatcher* dispatcher)
+ : m_solverInfo(NULL),
+ m_solver(solver),
+ m_multiBodySortedConstraints(NULL),
+ m_numConstraints(0),
+ m_debugDrawer(NULL),
+ m_dispatcher(dispatcher)
{
-
}
MultiBodyInplaceSolverIslandCallback& operator=(MultiBodyInplaceSolverIslandCallback& other)
@@ -260,7 +242,7 @@ struct MultiBodyInplaceSolverIslandCallback : public btSimulationIslandManager::
return *this;
}
- SIMD_FORCE_INLINE void setup ( btContactSolverInfo* solverInfo, btTypedConstraint** sortedConstraints, int numConstraints, btMultiBodyConstraint** sortedMultiBodyConstraints, int numMultiBodyConstraints, btIDebugDraw* debugDrawer)
+ SIMD_FORCE_INLINE void setup(btContactSolverInfo* solverInfo, btTypedConstraint** sortedConstraints, int numConstraints, btMultiBodyConstraint** sortedMultiBodyConstraints, int numMultiBodyConstraints, btIDebugDraw* debugDrawer)
{
btAssert(solverInfo);
m_solverInfo = solverInfo;
@@ -271,26 +253,27 @@ struct MultiBodyInplaceSolverIslandCallback : public btSimulationIslandManager::
m_numConstraints = numConstraints;
m_debugDrawer = debugDrawer;
- m_bodies.resize (0);
- m_manifolds.resize (0);
- m_constraints.resize (0);
+ m_bodies.resize(0);
+ m_manifolds.resize(0);
+ m_constraints.resize(0);
m_multiBodyConstraints.resize(0);
}
- void setMultiBodyConstraintSolver(btMultiBodyConstraintSolver* solver)
- {
- m_solver = solver;
- }
-
- virtual void processIsland(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifolds,int numManifolds, int islandId)
+ void setMultiBodyConstraintSolver(btMultiBodyConstraintSolver* solver)
+ {
+ m_solver = solver;
+ }
+
+ virtual void processIsland(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifolds, int numManifolds, int islandId)
{
- if (islandId<0)
+ if (islandId < 0)
{
///we don't split islands, so all constraints/contact manifolds/bodies are passed into the solver regardless the island id
- m_solver->solveMultiBodyGroup( bodies,numBodies,manifolds, numManifolds,m_sortedConstraints, m_numConstraints, &m_multiBodySortedConstraints[0],m_numConstraints,*m_solverInfo,m_debugDrawer,m_dispatcher);
- } else
+ m_solver->solveMultiBodyGroup(bodies, numBodies, manifolds, numManifolds, m_sortedConstraints, m_numConstraints, &m_multiBodySortedConstraints[0], m_numConstraints, *m_solverInfo, m_debugDrawer, m_dispatcher);
+ }
+ else
{
- //also add all non-contact constraints/joints for this island
+ //also add all non-contact constraints/joints for this island
btTypedConstraint** startConstraint = 0;
btMultiBodyConstraint** startMultiBodyConstraint = 0;
@@ -298,10 +281,10 @@ struct MultiBodyInplaceSolverIslandCallback : public btSimulationIslandManager::
int numCurMultiBodyConstraints = 0;
int i;
-
+
//find the first constraint for this island
- for (i=0;i<m_numConstraints;i++)
+ for (i = 0; i < m_numConstraints; i++)
{
if (btGetConstraintIslandId2(m_sortedConstraints[i]) == islandId)
{
@@ -310,7 +293,7 @@ struct MultiBodyInplaceSolverIslandCallback : public btSimulationIslandManager::
}
}
//count the number of constraints in this island
- for (;i<m_numConstraints;i++)
+ for (; i < m_numConstraints; i++)
{
if (btGetConstraintIslandId2(m_sortedConstraints[i]) == islandId)
{
@@ -318,17 +301,16 @@ struct MultiBodyInplaceSolverIslandCallback : public btSimulationIslandManager::
}
}
- for (i=0;i<m_numMultiBodyConstraints;i++)
+ for (i = 0; i < m_numMultiBodyConstraints; i++)
{
if (btGetMultiBodyConstraintIslandId(m_multiBodySortedConstraints[i]) == islandId)
{
-
startMultiBodyConstraint = &m_multiBodySortedConstraints[i];
break;
}
}
//count the number of multi body constraints in this island
- for (;i<m_numMultiBodyConstraints;i++)
+ for (; i < m_numMultiBodyConstraints; i++)
{
if (btGetMultiBodyConstraintIslandId(m_multiBodySortedConstraints[i]) == islandId)
{
@@ -341,101 +323,94 @@ struct MultiBodyInplaceSolverIslandCallback : public btSimulationIslandManager::
// m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,startConstraint,numCurConstraints,*m_solverInfo,m_debugDrawer,m_dispatcher);
//} else
{
-
- for (i=0;i<numBodies;i++)
+ for (i = 0; i < numBodies; i++)
m_bodies.push_back(bodies[i]);
- for (i=0;i<numManifolds;i++)
+ for (i = 0; i < numManifolds; i++)
m_manifolds.push_back(manifolds[i]);
- for (i=0;i<numCurConstraints;i++)
+ for (i = 0; i < numCurConstraints; i++)
m_constraints.push_back(startConstraint[i]);
-
- for (i=0;i<numCurMultiBodyConstraints;i++)
+
+ for (i = 0; i < numCurMultiBodyConstraints; i++)
m_multiBodyConstraints.push_back(startMultiBodyConstraint[i]);
-
- if ((m_multiBodyConstraints.size()+m_constraints.size()+m_manifolds.size())>m_solverInfo->m_minimumSolverBatchSize)
+
+ if ((m_multiBodyConstraints.size() + m_constraints.size() + m_manifolds.size()) > m_solverInfo->m_minimumSolverBatchSize)
{
processConstraints();
- } else
+ }
+ else
{
//printf("deferred\n");
}
}
}
}
- void processConstraints()
+ void processConstraints()
{
-
- btCollisionObject** bodies = m_bodies.size()? &m_bodies[0]:0;
- btPersistentManifold** manifold = m_manifolds.size()?&m_manifolds[0]:0;
- btTypedConstraint** constraints = m_constraints.size()?&m_constraints[0]:0;
- btMultiBodyConstraint** multiBodyConstraints = m_multiBodyConstraints.size() ? &m_multiBodyConstraints[0] : 0;
+ btCollisionObject** bodies = m_bodies.size() ? &m_bodies[0] : 0;
+ btPersistentManifold** manifold = m_manifolds.size() ? &m_manifolds[0] : 0;
+ btTypedConstraint** constraints = m_constraints.size() ? &m_constraints[0] : 0;
+ btMultiBodyConstraint** multiBodyConstraints = m_multiBodyConstraints.size() ? &m_multiBodyConstraints[0] : 0;
//printf("mb contacts = %d, mb constraints = %d\n", mbContacts, m_multiBodyConstraints.size());
-
- m_solver->solveMultiBodyGroup( bodies,m_bodies.size(),manifold, m_manifolds.size(),constraints, m_constraints.size() ,multiBodyConstraints, m_multiBodyConstraints.size(), *m_solverInfo,m_debugDrawer,m_dispatcher);
+
+ m_solver->solveMultiBodyGroup(bodies, m_bodies.size(), manifold, m_manifolds.size(), constraints, m_constraints.size(), multiBodyConstraints, m_multiBodyConstraints.size(), *m_solverInfo, m_debugDrawer, m_dispatcher);
m_bodies.resize(0);
m_manifolds.resize(0);
m_constraints.resize(0);
m_multiBodyConstraints.resize(0);
}
-
};
-
-
-btMultiBodyDynamicsWorld::btMultiBodyDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btMultiBodyConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration)
- :btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration),
- m_multiBodyConstraintSolver(constraintSolver)
+btMultiBodyDynamicsWorld::btMultiBodyDynamicsWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btMultiBodyConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration)
+ : btDiscreteDynamicsWorld(dispatcher, pairCache, constraintSolver, collisionConfiguration),
+ m_multiBodyConstraintSolver(constraintSolver)
{
//split impulse is not yet supported for Featherstone hierarchies
-// getSolverInfo().m_splitImpulse = false;
- getSolverInfo().m_solverMode |=SOLVER_USE_2_FRICTION_DIRECTIONS;
- m_solverMultiBodyIslandCallback = new MultiBodyInplaceSolverIslandCallback(constraintSolver,dispatcher);
+ // getSolverInfo().m_splitImpulse = false;
+ getSolverInfo().m_solverMode |= SOLVER_USE_2_FRICTION_DIRECTIONS;
+ m_solverMultiBodyIslandCallback = new MultiBodyInplaceSolverIslandCallback(constraintSolver, dispatcher);
}
-btMultiBodyDynamicsWorld::~btMultiBodyDynamicsWorld ()
+btMultiBodyDynamicsWorld::~btMultiBodyDynamicsWorld()
{
delete m_solverMultiBodyIslandCallback;
}
-void btMultiBodyDynamicsWorld::setMultiBodyConstraintSolver(btMultiBodyConstraintSolver* solver)
+void btMultiBodyDynamicsWorld::setMultiBodyConstraintSolver(btMultiBodyConstraintSolver* solver)
{
- m_multiBodyConstraintSolver = solver;
- m_solverMultiBodyIslandCallback->setMultiBodyConstraintSolver(solver);
- btDiscreteDynamicsWorld::setConstraintSolver(solver);
+ m_multiBodyConstraintSolver = solver;
+ m_solverMultiBodyIslandCallback->setMultiBodyConstraintSolver(solver);
+ btDiscreteDynamicsWorld::setConstraintSolver(solver);
}
-void btMultiBodyDynamicsWorld::setConstraintSolver(btConstraintSolver* solver)
+void btMultiBodyDynamicsWorld::setConstraintSolver(btConstraintSolver* solver)
{
- if (solver->getSolverType()==BT_MULTIBODY_SOLVER)
- {
- m_multiBodyConstraintSolver = (btMultiBodyConstraintSolver*)solver;
- }
- btDiscreteDynamicsWorld::setConstraintSolver(solver);
+ if (solver->getSolverType() == BT_MULTIBODY_SOLVER)
+ {
+ m_multiBodyConstraintSolver = (btMultiBodyConstraintSolver*)solver;
+ }
+ btDiscreteDynamicsWorld::setConstraintSolver(solver);
}
-void btMultiBodyDynamicsWorld::forwardKinematics()
+void btMultiBodyDynamicsWorld::forwardKinematics()
{
-
- for (int b=0;b<m_multiBodies.size();b++)
+ for (int b = 0; b < m_multiBodies.size(); b++)
{
btMultiBody* bod = m_multiBodies[b];
- bod->forwardKinematics(m_scratch_world_to_local,m_scratch_local_origin);
+ bod->forwardKinematics(m_scratch_world_to_local, m_scratch_local_origin);
}
}
-void btMultiBodyDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
+void btMultiBodyDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
{
forwardKinematics();
-
-
BT_PROFILE("solveConstraints");
-
+
clearMultiBodyConstraintForces();
- m_sortedConstraints.resize( m_constraints.size());
- int i;
- for (i=0;i<getNumConstraints();i++)
+ m_sortedConstraints.resize(m_constraints.size());
+ int i;
+ for (i = 0; i < getNumConstraints(); i++)
{
m_sortedConstraints[i] = m_constraints[i];
}
@@ -443,109 +418,120 @@ void btMultiBodyDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
btTypedConstraint** constraintsPtr = getNumConstraints() ? &m_sortedConstraints[0] : 0;
m_sortedMultiBodyConstraints.resize(m_multiBodyConstraints.size());
- for (i=0;i<m_multiBodyConstraints.size();i++)
+ for (i = 0; i < m_multiBodyConstraints.size(); i++)
{
m_sortedMultiBodyConstraints[i] = m_multiBodyConstraints[i];
}
m_sortedMultiBodyConstraints.quickSort(btSortMultiBodyConstraintOnIslandPredicate());
- btMultiBodyConstraint** sortedMultiBodyConstraints = m_sortedMultiBodyConstraints.size() ? &m_sortedMultiBodyConstraints[0] : 0;
-
+ btMultiBodyConstraint** sortedMultiBodyConstraints = m_sortedMultiBodyConstraints.size() ? &m_sortedMultiBodyConstraints[0] : 0;
- m_solverMultiBodyIslandCallback->setup(&solverInfo,constraintsPtr,m_sortedConstraints.size(),sortedMultiBodyConstraints,m_sortedMultiBodyConstraints.size(), getDebugDrawer());
+ m_solverMultiBodyIslandCallback->setup(&solverInfo, constraintsPtr, m_sortedConstraints.size(), sortedMultiBodyConstraints, m_sortedMultiBodyConstraints.size(), getDebugDrawer());
m_constraintSolver->prepareSolve(getCollisionWorld()->getNumCollisionObjects(), getCollisionWorld()->getDispatcher()->getNumManifolds());
-
#ifndef BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
{
BT_PROFILE("btMultiBody addForce");
- for (int i=0;i<this->m_multiBodies.size();i++)
+ for (int i = 0; i < this->m_multiBodies.size(); i++)
{
btMultiBody* bod = m_multiBodies[i];
bool isSleeping = false;
-
+
if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
{
isSleeping = true;
- }
- for (int b=0;b<bod->getNumLinks();b++)
+ }
+ for (int b = 0; b < bod->getNumLinks(); b++)
{
- if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState()==ISLAND_SLEEPING)
+ if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
isSleeping = true;
- }
+ }
if (!isSleeping)
{
//useless? they get resized in stepVelocities once again (AND DIFFERENTLY)
- m_scratch_r.resize(bod->getNumLinks()+1); //multidof? ("Y"s use it and it is used to store qdd)
- m_scratch_v.resize(bod->getNumLinks()+1);
- m_scratch_m.resize(bod->getNumLinks()+1);
+ m_scratch_r.resize(bod->getNumLinks() + 1); //multidof? ("Y"s use it and it is used to store qdd)
+ m_scratch_v.resize(bod->getNumLinks() + 1);
+ m_scratch_m.resize(bod->getNumLinks() + 1);
bod->addBaseForce(m_gravity * bod->getBaseMass());
- for (int j = 0; j < bod->getNumLinks(); ++j)
+ for (int j = 0; j < bod->getNumLinks(); ++j)
{
bod->addLinkForce(j, m_gravity * bod->getLinkMass(j));
}
- }//if (!isSleeping)
+ } //if (!isSleeping)
}
}
-#endif //BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
-
+#endif //BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
{
BT_PROFILE("btMultiBody stepVelocities");
- for (int i=0;i<this->m_multiBodies.size();i++)
+ for (int i = 0; i < this->m_multiBodies.size(); i++)
{
btMultiBody* bod = m_multiBodies[i];
bool isSleeping = false;
-
+
if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
{
isSleeping = true;
- }
- for (int b=0;b<bod->getNumLinks();b++)
+ }
+ for (int b = 0; b < bod->getNumLinks(); b++)
{
- if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState()==ISLAND_SLEEPING)
+ if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
isSleeping = true;
- }
+ }
if (!isSleeping)
{
//useless? they get resized in stepVelocities once again (AND DIFFERENTLY)
- m_scratch_r.resize(bod->getNumLinks()+1); //multidof? ("Y"s use it and it is used to store qdd)
- m_scratch_v.resize(bod->getNumLinks()+1);
- m_scratch_m.resize(bod->getNumLinks()+1);
+ m_scratch_r.resize(bod->getNumLinks() + 1); //multidof? ("Y"s use it and it is used to store qdd)
+ m_scratch_v.resize(bod->getNumLinks() + 1);
+ m_scratch_m.resize(bod->getNumLinks() + 1);
bool doNotUpdatePos = false;
-
+ bool isConstraintPass = false;
{
- if(!bod->isUsingRK4Integration())
+ if (!bod->isUsingRK4Integration())
{
- bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(solverInfo.m_timeStep, m_scratch_r, m_scratch_v, m_scratch_m);
+ bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(solverInfo.m_timeStep,
+ m_scratch_r, m_scratch_v, m_scratch_m,isConstraintPass,
+ getSolverInfo().m_jointFeedbackInWorldSpace,
+ getSolverInfo().m_jointFeedbackInJointFrame);
}
else
- {
+ {
//
int numDofs = bod->getNumDofs() + 6;
int numPosVars = bod->getNumPosVars() + 7;
- btAlignedObjectArray<btScalar> scratch_r2; scratch_r2.resize(2*numPosVars + 8*numDofs);
+ btAlignedObjectArray<btScalar> scratch_r2;
+ scratch_r2.resize(2 * numPosVars + 8 * numDofs);
//convenience
- btScalar *pMem = &scratch_r2[0];
- btScalar *scratch_q0 = pMem; pMem += numPosVars;
- btScalar *scratch_qx = pMem; pMem += numPosVars;
- btScalar *scratch_qd0 = pMem; pMem += numDofs;
- btScalar *scratch_qd1 = pMem; pMem += numDofs;
- btScalar *scratch_qd2 = pMem; pMem += numDofs;
- btScalar *scratch_qd3 = pMem; pMem += numDofs;
- btScalar *scratch_qdd0 = pMem; pMem += numDofs;
- btScalar *scratch_qdd1 = pMem; pMem += numDofs;
- btScalar *scratch_qdd2 = pMem; pMem += numDofs;
- btScalar *scratch_qdd3 = pMem; pMem += numDofs;
- btAssert((pMem - (2*numPosVars + 8*numDofs)) == &scratch_r2[0]);
-
- /////
+ btScalar* pMem = &scratch_r2[0];
+ btScalar* scratch_q0 = pMem;
+ pMem += numPosVars;
+ btScalar* scratch_qx = pMem;
+ pMem += numPosVars;
+ btScalar* scratch_qd0 = pMem;
+ pMem += numDofs;
+ btScalar* scratch_qd1 = pMem;
+ pMem += numDofs;
+ btScalar* scratch_qd2 = pMem;
+ pMem += numDofs;
+ btScalar* scratch_qd3 = pMem;
+ pMem += numDofs;
+ btScalar* scratch_qdd0 = pMem;
+ pMem += numDofs;
+ btScalar* scratch_qdd1 = pMem;
+ pMem += numDofs;
+ btScalar* scratch_qdd2 = pMem;
+ pMem += numDofs;
+ btScalar* scratch_qdd3 = pMem;
+ pMem += numDofs;
+ btAssert((pMem - (2 * numPosVars + 8 * numDofs)) == &scratch_r2[0]);
+
+ /////
//copy q0 to scratch_q0 and qd0 to scratch_qd0
scratch_q0[0] = bod->getWorldToBaseRot().x();
scratch_q0[1] = bod->getWorldToBaseRot().y();
@@ -555,83 +541,88 @@ void btMultiBodyDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
scratch_q0[5] = bod->getBasePos().y();
scratch_q0[6] = bod->getBasePos().z();
//
- for(int link = 0; link < bod->getNumLinks(); ++link)
+ for (int link = 0; link < bod->getNumLinks(); ++link)
{
- for(int dof = 0; dof < bod->getLink(link).m_posVarCount; ++dof)
- scratch_q0[7 + bod->getLink(link).m_cfgOffset + dof] = bod->getLink(link).m_jointPos[dof];
+ for (int dof = 0; dof < bod->getLink(link).m_posVarCount; ++dof)
+ scratch_q0[7 + bod->getLink(link).m_cfgOffset + dof] = bod->getLink(link).m_jointPos[dof];
}
//
- for(int dof = 0; dof < numDofs; ++dof)
+ for (int dof = 0; dof < numDofs; ++dof)
scratch_qd0[dof] = bod->getVelocityVector()[dof];
////
struct
{
- btMultiBody *bod;
- btScalar *scratch_qx, *scratch_q0;
-
- void operator()()
- {
- for(int dof = 0; dof < bod->getNumPosVars() + 7; ++dof)
- scratch_qx[dof] = scratch_q0[dof];
- }
+ btMultiBody* bod;
+ btScalar *scratch_qx, *scratch_q0;
+
+ void operator()()
+ {
+ for (int dof = 0; dof < bod->getNumPosVars() + 7; ++dof)
+ scratch_qx[dof] = scratch_q0[dof];
+ }
} pResetQx = {bod, scratch_qx, scratch_q0};
//
struct
{
- void operator()(btScalar dt, const btScalar *pDer, const btScalar *pCurVal, btScalar *pVal, int size)
- {
- for(int i = 0; i < size; ++i)
- pVal[i] = pCurVal[i] + dt * pDer[i];
- }
+ void operator()(btScalar dt, const btScalar* pDer, const btScalar* pCurVal, btScalar* pVal, int size)
+ {
+ for (int i = 0; i < size; ++i)
+ pVal[i] = pCurVal[i] + dt * pDer[i];
+ }
} pEulerIntegrate;
//
struct
- {
- void operator()(btMultiBody *pBody, const btScalar *pData)
- {
- btScalar *pVel = const_cast<btScalar*>(pBody->getVelocityVector());
-
- for(int i = 0; i < pBody->getNumDofs() + 6; ++i)
- pVel[i] = pData[i];
-
- }
- } pCopyToVelocityVector;
+ {
+ void operator()(btMultiBody* pBody, const btScalar* pData)
+ {
+ btScalar* pVel = const_cast<btScalar*>(pBody->getVelocityVector());
+
+ for (int i = 0; i < pBody->getNumDofs() + 6; ++i)
+ pVel[i] = pData[i];
+ }
+ } pCopyToVelocityVector;
//
- struct
+ struct
{
- void operator()(const btScalar *pSrc, btScalar *pDst, int start, int size)
- {
- for(int i = 0; i < size; ++i)
- pDst[i] = pSrc[start + i];
- }
+ void operator()(const btScalar* pSrc, btScalar* pDst, int start, int size)
+ {
+ for (int i = 0; i < size; ++i)
+ pDst[i] = pSrc[start + i];
+ }
} pCopy;
//
btScalar h = solverInfo.m_timeStep;
- #define output &m_scratch_r[bod->getNumDofs()]
- //calc qdd0 from: q0 & qd0
- bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m);
+#define output &m_scratch_r[bod->getNumDofs()]
+ //calc qdd0 from: q0 & qd0
+ bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m,
+ isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
+ getSolverInfo().m_jointFeedbackInJointFrame);
pCopy(output, scratch_qdd0, 0, numDofs);
//calc q1 = q0 + h/2 * qd0
pResetQx();
- bod->stepPositionsMultiDof(btScalar(.5)*h, scratch_qx, scratch_qd0);
+ bod->stepPositionsMultiDof(btScalar(.5) * h, scratch_qx, scratch_qd0);
//calc qd1 = qd0 + h/2 * qdd0
- pEulerIntegrate(btScalar(.5)*h, scratch_qdd0, scratch_qd0, scratch_qd1, numDofs);
+ pEulerIntegrate(btScalar(.5) * h, scratch_qdd0, scratch_qd0, scratch_qd1, numDofs);
//
//calc qdd1 from: q1 & qd1
pCopyToVelocityVector(bod, scratch_qd1);
- bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m);
+ bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m,
+ isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
+ getSolverInfo().m_jointFeedbackInJointFrame);
pCopy(output, scratch_qdd1, 0, numDofs);
//calc q2 = q0 + h/2 * qd1
pResetQx();
- bod->stepPositionsMultiDof(btScalar(.5)*h, scratch_qx, scratch_qd1);
+ bod->stepPositionsMultiDof(btScalar(.5) * h, scratch_qx, scratch_qd1);
//calc qd2 = qd0 + h/2 * qdd1
- pEulerIntegrate(btScalar(.5)*h, scratch_qdd1, scratch_qd0, scratch_qd2, numDofs);
+ pEulerIntegrate(btScalar(.5) * h, scratch_qdd1, scratch_qd0, scratch_qd2, numDofs);
//
//calc qdd2 from: q2 & qd2
pCopyToVelocityVector(bod, scratch_qd2);
- bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m);
+ bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m,
+ isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
+ getSolverInfo().m_jointFeedbackInJointFrame);
pCopy(output, scratch_qdd2, 0, numDofs);
//calc q3 = q0 + h * qd2
pResetQx();
@@ -641,156 +632,158 @@ void btMultiBodyDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
//
//calc qdd3 from: q3 & qd3
pCopyToVelocityVector(bod, scratch_qd3);
- bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m);
+ bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m,
+ isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
+ getSolverInfo().m_jointFeedbackInJointFrame);
pCopy(output, scratch_qdd3, 0, numDofs);
//
//calc q = q0 + h/6(qd0 + 2*(qd1 + qd2) + qd3)
- //calc qd = qd0 + h/6(qdd0 + 2*(qdd1 + qdd2) + qdd3)
- btAlignedObjectArray<btScalar> delta_q; delta_q.resize(numDofs);
- btAlignedObjectArray<btScalar> delta_qd; delta_qd.resize(numDofs);
- for(int i = 0; i < numDofs; ++i)
+ //calc qd = qd0 + h/6(qdd0 + 2*(qdd1 + qdd2) + qdd3)
+ btAlignedObjectArray<btScalar> delta_q;
+ delta_q.resize(numDofs);
+ btAlignedObjectArray<btScalar> delta_qd;
+ delta_qd.resize(numDofs);
+ for (int i = 0; i < numDofs; ++i)
{
- delta_q[i] = h/btScalar(6.)*(scratch_qd0[i] + 2*scratch_qd1[i] + 2*scratch_qd2[i] + scratch_qd3[i]);
- delta_qd[i] = h/btScalar(6.)*(scratch_qdd0[i] + 2*scratch_qdd1[i] + 2*scratch_qdd2[i] + scratch_qdd3[i]);
+ delta_q[i] = h / btScalar(6.) * (scratch_qd0[i] + 2 * scratch_qd1[i] + 2 * scratch_qd2[i] + scratch_qd3[i]);
+ delta_qd[i] = h / btScalar(6.) * (scratch_qdd0[i] + 2 * scratch_qdd1[i] + 2 * scratch_qdd2[i] + scratch_qdd3[i]);
//delta_q[i] = h*scratch_qd0[i];
//delta_qd[i] = h*scratch_qdd0[i];
}
//
pCopyToVelocityVector(bod, scratch_qd0);
- bod->applyDeltaVeeMultiDof(&delta_qd[0], 1);
+ bod->applyDeltaVeeMultiDof(&delta_qd[0], 1);
//
- if(!doNotUpdatePos)
+ if (!doNotUpdatePos)
{
- btScalar *pRealBuf = const_cast<btScalar *>(bod->getVelocityVector());
- pRealBuf += 6 + bod->getNumDofs() + bod->getNumDofs()*bod->getNumDofs();
+ btScalar* pRealBuf = const_cast<btScalar*>(bod->getVelocityVector());
+ pRealBuf += 6 + bod->getNumDofs() + bod->getNumDofs() * bod->getNumDofs();
- for(int i = 0; i < numDofs; ++i)
+ for (int i = 0; i < numDofs; ++i)
pRealBuf[i] = delta_q[i];
//bod->stepPositionsMultiDof(1, 0, &delta_q[0]);
- bod->setPosUpdated(true);
+ bod->setPosUpdated(true);
}
//ugly hack which resets the cached data to t0 (needed for constraint solver)
{
- for(int link = 0; link < bod->getNumLinks(); ++link)
+ for (int link = 0; link < bod->getNumLinks(); ++link)
bod->getLink(link).updateCacheMultiDof();
- bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0, m_scratch_r, m_scratch_v, m_scratch_m);
+ bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0, m_scratch_r, m_scratch_v, m_scratch_m,
+ isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
+ getSolverInfo().m_jointFeedbackInJointFrame);
}
-
}
}
-
+
#ifndef BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
bod->clearForcesAndTorques();
-#endif //BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
- }//if (!isSleeping)
+#endif //BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
+ } //if (!isSleeping)
}
}
/// solve all the constraints for this island
m_islandManager->buildAndProcessIslands(getCollisionWorld()->getDispatcher(), getCollisionWorld(), m_solverMultiBodyIslandCallback);
-
m_solverMultiBodyIslandCallback->processConstraints();
-
+
m_constraintSolver->allSolved(solverInfo, m_debugDrawer);
{
- BT_PROFILE("btMultiBody stepVelocities");
- for (int i=0;i<this->m_multiBodies.size();i++)
- {
- btMultiBody* bod = m_multiBodies[i];
-
- bool isSleeping = false;
-
- if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
- {
- isSleeping = true;
- }
- for (int b=0;b<bod->getNumLinks();b++)
- {
- if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState()==ISLAND_SLEEPING)
- isSleeping = true;
- }
-
- if (!isSleeping)
- {
- //useless? they get resized in stepVelocities once again (AND DIFFERENTLY)
- m_scratch_r.resize(bod->getNumLinks()+1); //multidof? ("Y"s use it and it is used to store qdd)
- m_scratch_v.resize(bod->getNumLinks()+1);
- m_scratch_m.resize(bod->getNumLinks()+1);
-
-
- {
- if(!bod->isUsingRK4Integration())
- {
- bool isConstraintPass = true;
- bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(solverInfo.m_timeStep, m_scratch_r, m_scratch_v, m_scratch_m, isConstraintPass);
- }
+ BT_PROFILE("btMultiBody stepVelocities");
+ for (int i = 0; i < this->m_multiBodies.size(); i++)
+ {
+ btMultiBody* bod = m_multiBodies[i];
+
+ bool isSleeping = false;
+
+ if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
+ {
+ isSleeping = true;
+ }
+ for (int b = 0; b < bod->getNumLinks(); b++)
+ {
+ if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
+ isSleeping = true;
+ }
+
+ if (!isSleeping)
+ {
+ //useless? they get resized in stepVelocities once again (AND DIFFERENTLY)
+ m_scratch_r.resize(bod->getNumLinks() + 1); //multidof? ("Y"s use it and it is used to store qdd)
+ m_scratch_v.resize(bod->getNumLinks() + 1);
+ m_scratch_m.resize(bod->getNumLinks() + 1);
+
+ {
+ if (!bod->isUsingRK4Integration())
+ {
+ bool isConstraintPass = true;
+ bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(solverInfo.m_timeStep, m_scratch_r, m_scratch_v, m_scratch_m, isConstraintPass,
+ getSolverInfo().m_jointFeedbackInWorldSpace,
+ getSolverInfo().m_jointFeedbackInJointFrame);
+ }
}
}
}
}
- for (int i=0;i<this->m_multiBodies.size();i++)
+ for (int i = 0; i < this->m_multiBodies.size(); i++)
{
btMultiBody* bod = m_multiBodies[i];
bod->processDeltaVeeMultiDof2();
}
-
}
-void btMultiBodyDynamicsWorld::integrateTransforms(btScalar timeStep)
+void btMultiBodyDynamicsWorld::integrateTransforms(btScalar timeStep)
{
btDiscreteDynamicsWorld::integrateTransforms(timeStep);
{
BT_PROFILE("btMultiBody stepPositions");
//integrate and update the Featherstone hierarchies
-
- for (int b=0;b<m_multiBodies.size();b++)
+
+ for (int b = 0; b < m_multiBodies.size(); b++)
{
btMultiBody* bod = m_multiBodies[b];
bool isSleeping = false;
if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
{
isSleeping = true;
- }
- for (int b=0;b<bod->getNumLinks();b++)
+ }
+ for (int b = 0; b < bod->getNumLinks(); b++)
{
- if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState()==ISLAND_SLEEPING)
+ if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
isSleeping = true;
}
-
if (!isSleeping)
{
int nLinks = bod->getNumLinks();
///base + num m_links
-
-
+
{
- if(!bod->isPosUpdated())
+ if (!bod->isPosUpdated())
bod->stepPositionsMultiDof(timeStep);
else
{
- btScalar *pRealBuf = const_cast<btScalar *>(bod->getVelocityVector());
- pRealBuf += 6 + bod->getNumDofs() + bod->getNumDofs()*bod->getNumDofs();
+ btScalar* pRealBuf = const_cast<btScalar*>(bod->getVelocityVector());
+ pRealBuf += 6 + bod->getNumDofs() + bod->getNumDofs() * bod->getNumDofs();
bod->stepPositionsMultiDof(1, 0, pRealBuf);
bod->setPosUpdated(false);
}
}
-
- m_scratch_world_to_local.resize(nLinks+1);
- m_scratch_local_origin.resize(nLinks+1);
- bod->updateCollisionObjectWorldTransforms(m_scratch_world_to_local,m_scratch_local_origin);
-
- } else
+ m_scratch_world_to_local.resize(nLinks + 1);
+ m_scratch_local_origin.resize(nLinks + 1);
+
+ bod->updateCollisionObjectWorldTransforms(m_scratch_world_to_local, m_scratch_local_origin);
+ }
+ else
{
bod->clearVelocities();
}
@@ -798,14 +791,12 @@ void btMultiBodyDynamicsWorld::integrateTransforms(btScalar timeStep)
}
}
-
-
-void btMultiBodyDynamicsWorld::addMultiBodyConstraint( btMultiBodyConstraint* constraint)
+void btMultiBodyDynamicsWorld::addMultiBodyConstraint(btMultiBodyConstraint* constraint)
{
m_multiBodyConstraints.push_back(constraint);
}
-void btMultiBodyDynamicsWorld::removeMultiBodyConstraint( btMultiBodyConstraint* constraint)
+void btMultiBodyDynamicsWorld::removeMultiBodyConstraint(btMultiBodyConstraint* constraint)
{
m_multiBodyConstraints.remove(constraint);
}
@@ -815,8 +806,7 @@ void btMultiBodyDynamicsWorld::debugDrawMultiBodyConstraint(btMultiBodyConstrain
constraint->debugDraw(getDebugDrawer());
}
-
-void btMultiBodyDynamicsWorld::debugDrawWorld()
+void btMultiBodyDynamicsWorld::debugDrawWorld()
{
BT_PROFILE("btMultiBodyDynamicsWorld debugDrawWorld");
@@ -826,7 +816,7 @@ void btMultiBodyDynamicsWorld::debugDrawWorld()
if (getDebugDrawer())
{
int mode = getDebugDrawer()->getDebugMode();
- if (mode & (btIDebugDraw::DBG_DrawConstraints | btIDebugDraw::DBG_DrawConstraintLimits))
+ if (mode & (btIDebugDraw::DBG_DrawConstraints | btIDebugDraw::DBG_DrawConstraintLimits))
{
drawConstraints = true;
}
@@ -834,160 +824,148 @@ void btMultiBodyDynamicsWorld::debugDrawWorld()
if (drawConstraints)
{
BT_PROFILE("btMultiBody debugDrawWorld");
-
- for (int c=0;c<m_multiBodyConstraints.size();c++)
+ for (int c = 0; c < m_multiBodyConstraints.size(); c++)
{
btMultiBodyConstraint* constraint = m_multiBodyConstraints[c];
debugDrawMultiBodyConstraint(constraint);
}
- for (int b = 0; b<m_multiBodies.size(); b++)
+ for (int b = 0; b < m_multiBodies.size(); b++)
{
btMultiBody* bod = m_multiBodies[b];
- bod->forwardKinematics(m_scratch_world_to_local1,m_scratch_local_origin1);
-
- if (mode & btIDebugDraw::DBG_DrawFrames)
+ bod->forwardKinematics(m_scratch_world_to_local1, m_scratch_local_origin1);
+
+ if (mode & btIDebugDraw::DBG_DrawFrames)
{
getDebugDrawer()->drawTransform(bod->getBaseWorldTransform(), 0.1);
}
- for (int m = 0; m<bod->getNumLinks(); m++)
+ for (int m = 0; m < bod->getNumLinks(); m++)
{
-
const btTransform& tr = bod->getLink(m).m_cachedWorldTransform;
- if (mode & btIDebugDraw::DBG_DrawFrames)
+ if (mode & btIDebugDraw::DBG_DrawFrames)
{
getDebugDrawer()->drawTransform(tr, 0.1);
}
- //draw the joint axis
- if (bod->getLink(m).m_jointType==btMultibodyLink::eRevolute)
+ //draw the joint axis
+ if (bod->getLink(m).m_jointType == btMultibodyLink::eRevolute)
{
- btVector3 vec = quatRotate(tr.getRotation(),bod->getLink(m).m_axes[0].m_topVec)*0.1;
-
- btVector4 color(0,0,0,1);//1,1,1);
- btVector3 from = vec+tr.getOrigin()-quatRotate(tr.getRotation(),bod->getLink(m).m_dVector);
- btVector3 to = tr.getOrigin()-quatRotate(tr.getRotation(),bod->getLink(m).m_dVector);
- getDebugDrawer()->drawLine(from,to,color);
+ btVector3 vec = quatRotate(tr.getRotation(), bod->getLink(m).m_axes[0].m_topVec) * 0.1;
+
+ btVector4 color(0, 0, 0, 1); //1,1,1);
+ btVector3 from = vec + tr.getOrigin() - quatRotate(tr.getRotation(), bod->getLink(m).m_dVector);
+ btVector3 to = tr.getOrigin() - quatRotate(tr.getRotation(), bod->getLink(m).m_dVector);
+ getDebugDrawer()->drawLine(from, to, color);
}
- if (bod->getLink(m).m_jointType==btMultibodyLink::eFixed)
+ if (bod->getLink(m).m_jointType == btMultibodyLink::eFixed)
{
- btVector3 vec = quatRotate(tr.getRotation(),bod->getLink(m).m_axes[0].m_bottomVec)*0.1;
-
- btVector4 color(0,0,0,1);//1,1,1);
- btVector3 from = vec+tr.getOrigin()-quatRotate(tr.getRotation(),bod->getLink(m).m_dVector);
- btVector3 to = tr.getOrigin()-quatRotate(tr.getRotation(),bod->getLink(m).m_dVector);
- getDebugDrawer()->drawLine(from,to,color);
+ btVector3 vec = quatRotate(tr.getRotation(), bod->getLink(m).m_axes[0].m_bottomVec) * 0.1;
+
+ btVector4 color(0, 0, 0, 1); //1,1,1);
+ btVector3 from = vec + tr.getOrigin() - quatRotate(tr.getRotation(), bod->getLink(m).m_dVector);
+ btVector3 to = tr.getOrigin() - quatRotate(tr.getRotation(), bod->getLink(m).m_dVector);
+ getDebugDrawer()->drawLine(from, to, color);
}
- if (bod->getLink(m).m_jointType==btMultibodyLink::ePrismatic)
+ if (bod->getLink(m).m_jointType == btMultibodyLink::ePrismatic)
{
- btVector3 vec = quatRotate(tr.getRotation(),bod->getLink(m).m_axes[0].m_bottomVec)*0.1;
-
- btVector4 color(0,0,0,1);//1,1,1);
- btVector3 from = vec+tr.getOrigin()-quatRotate(tr.getRotation(),bod->getLink(m).m_dVector);
- btVector3 to = tr.getOrigin()-quatRotate(tr.getRotation(),bod->getLink(m).m_dVector);
- getDebugDrawer()->drawLine(from,to,color);
+ btVector3 vec = quatRotate(tr.getRotation(), bod->getLink(m).m_axes[0].m_bottomVec) * 0.1;
+
+ btVector4 color(0, 0, 0, 1); //1,1,1);
+ btVector3 from = vec + tr.getOrigin() - quatRotate(tr.getRotation(), bod->getLink(m).m_dVector);
+ btVector3 to = tr.getOrigin() - quatRotate(tr.getRotation(), bod->getLink(m).m_dVector);
+ getDebugDrawer()->drawLine(from, to, color);
}
-
}
}
}
}
-
-
}
-
-
void btMultiBodyDynamicsWorld::applyGravity()
{
- btDiscreteDynamicsWorld::applyGravity();
+ btDiscreteDynamicsWorld::applyGravity();
#ifdef BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
- BT_PROFILE("btMultiBody addGravity");
- for (int i=0;i<this->m_multiBodies.size();i++)
- {
- btMultiBody* bod = m_multiBodies[i];
-
- bool isSleeping = false;
-
- if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
- {
- isSleeping = true;
- }
- for (int b=0;b<bod->getNumLinks();b++)
- {
- if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState()==ISLAND_SLEEPING)
- isSleeping = true;
- }
-
- if (!isSleeping)
- {
- bod->addBaseForce(m_gravity * bod->getBaseMass());
-
- for (int j = 0; j < bod->getNumLinks(); ++j)
- {
- bod->addLinkForce(j, m_gravity * bod->getLinkMass(j));
- }
- }//if (!isSleeping)
- }
-#endif //BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
+ BT_PROFILE("btMultiBody addGravity");
+ for (int i = 0; i < this->m_multiBodies.size(); i++)
+ {
+ btMultiBody* bod = m_multiBodies[i];
+
+ bool isSleeping = false;
+
+ if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
+ {
+ isSleeping = true;
+ }
+ for (int b = 0; b < bod->getNumLinks(); b++)
+ {
+ if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
+ isSleeping = true;
+ }
+
+ if (!isSleeping)
+ {
+ bod->addBaseForce(m_gravity * bod->getBaseMass());
+
+ for (int j = 0; j < bod->getNumLinks(); ++j)
+ {
+ bod->addLinkForce(j, m_gravity * bod->getLinkMass(j));
+ }
+ } //if (!isSleeping)
+ }
+#endif //BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
}
void btMultiBodyDynamicsWorld::clearMultiBodyConstraintForces()
-{
- for (int i=0;i<this->m_multiBodies.size();i++)
- {
- btMultiBody* bod = m_multiBodies[i];
- bod->clearConstraintForces();
- }
+{
+ for (int i = 0; i < this->m_multiBodies.size(); i++)
+ {
+ btMultiBody* bod = m_multiBodies[i];
+ bod->clearConstraintForces();
+ }
}
void btMultiBodyDynamicsWorld::clearMultiBodyForces()
{
- {
- // BT_PROFILE("clearMultiBodyForces");
- for (int i=0;i<this->m_multiBodies.size();i++)
- {
- btMultiBody* bod = m_multiBodies[i];
-
- bool isSleeping = false;
-
- if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
- {
- isSleeping = true;
- }
- for (int b=0;b<bod->getNumLinks();b++)
- {
- if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState()==ISLAND_SLEEPING)
- isSleeping = true;
- }
-
- if (!isSleeping)
- {
- btMultiBody* bod = m_multiBodies[i];
- bod->clearForcesAndTorques();
- }
+ {
+ // BT_PROFILE("clearMultiBodyForces");
+ for (int i = 0; i < this->m_multiBodies.size(); i++)
+ {
+ btMultiBody* bod = m_multiBodies[i];
+
+ bool isSleeping = false;
+
+ if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
+ {
+ isSleeping = true;
+ }
+ for (int b = 0; b < bod->getNumLinks(); b++)
+ {
+ if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
+ isSleeping = true;
+ }
+
+ if (!isSleeping)
+ {
+ btMultiBody* bod = m_multiBodies[i];
+ bod->clearForcesAndTorques();
+ }
}
}
-
}
void btMultiBodyDynamicsWorld::clearForces()
{
- btDiscreteDynamicsWorld::clearForces();
+ btDiscreteDynamicsWorld::clearForces();
#ifdef BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
clearMultiBodyForces();
#endif
}
-
-
-
-void btMultiBodyDynamicsWorld::serialize(btSerializer* serializer)
+void btMultiBodyDynamicsWorld::serialize(btSerializer* serializer)
{
-
serializer->startSerialization();
- serializeDynamicsWorldInfo( serializer);
+ serializeDynamicsWorldInfo(serializer);
serializeMultiBodies(serializer);
@@ -1000,32 +978,31 @@ void btMultiBodyDynamicsWorld::serialize(btSerializer* serializer)
serializer->finishSerialization();
}
-void btMultiBodyDynamicsWorld::serializeMultiBodies(btSerializer* serializer)
+void btMultiBodyDynamicsWorld::serializeMultiBodies(btSerializer* serializer)
{
int i;
//serialize all collision objects
- for (i=0;i<m_multiBodies.size();i++)
+ for (i = 0; i < m_multiBodies.size(); i++)
{
btMultiBody* mb = m_multiBodies[i];
{
int len = mb->calculateSerializeBufferSize();
- btChunk* chunk = serializer->allocate(len,1);
+ btChunk* chunk = serializer->allocate(len, 1);
const char* structType = mb->serialize(chunk->m_oldPtr, serializer);
- serializer->finalizeChunk(chunk,structType,BT_MULTIBODY_CODE,mb);
+ serializer->finalizeChunk(chunk, structType, BT_MULTIBODY_CODE, mb);
}
}
//serialize all multibody links (collision objects)
- for (i=0;i<m_collisionObjects.size();i++)
+ for (i = 0; i < m_collisionObjects.size(); i++)
{
btCollisionObject* colObj = m_collisionObjects[i];
if (colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
{
int len = colObj->calculateSerializeBufferSize();
- btChunk* chunk = serializer->allocate(len,1);
+ btChunk* chunk = serializer->allocate(len, 1);
const char* structType = colObj->serialize(chunk->m_oldPtr, serializer);
- serializer->finalizeChunk(chunk,structType,BT_MB_LINKCOLLIDER_CODE,colObj);
+ serializer->finalizeChunk(chunk, structType, BT_MB_LINKCOLLIDER_CODE, colObj);
}
}
-
}
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h
index 2fbf089d81..641238f3bb 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h
@@ -33,8 +33,8 @@ protected:
btAlignedObjectArray<btMultiBody*> m_multiBodies;
btAlignedObjectArray<btMultiBodyConstraint*> m_multiBodyConstraints;
btAlignedObjectArray<btMultiBodyConstraint*> m_sortedMultiBodyConstraints;
- btMultiBodyConstraintSolver* m_multiBodyConstraintSolver;
- MultiBodyInplaceSolverIslandCallback* m_solverMultiBodyIslandCallback;
+ btMultiBodyConstraintSolver* m_multiBodyConstraintSolver;
+ MultiBodyInplaceSolverIslandCallback* m_solverMultiBodyIslandCallback;
//cached data to avoid memory allocations
btAlignedObjectArray<btQuaternion> m_scratch_world_to_local;
@@ -45,72 +45,69 @@ protected:
btAlignedObjectArray<btVector3> m_scratch_v;
btAlignedObjectArray<btMatrix3x3> m_scratch_m;
-
- virtual void calculateSimulationIslands();
- virtual void updateActivationState(btScalar timeStep);
- virtual void solveConstraints(btContactSolverInfo& solverInfo);
-
- virtual void serializeMultiBodies(btSerializer* serializer);
+ virtual void calculateSimulationIslands();
+ virtual void updateActivationState(btScalar timeStep);
+ virtual void solveConstraints(btContactSolverInfo& solverInfo);
-public:
+ virtual void serializeMultiBodies(btSerializer* serializer);
- btMultiBodyDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btMultiBodyConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration);
+public:
+ btMultiBodyDynamicsWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btMultiBodyConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration);
- virtual ~btMultiBodyDynamicsWorld ();
+ virtual ~btMultiBodyDynamicsWorld();
- virtual void addMultiBody(btMultiBody* body, int group= btBroadphaseProxy::DefaultFilter, int mask=btBroadphaseProxy::AllFilter);
+ virtual void addMultiBody(btMultiBody* body, int group = btBroadphaseProxy::DefaultFilter, int mask = btBroadphaseProxy::AllFilter);
- virtual void removeMultiBody(btMultiBody* body);
+ virtual void removeMultiBody(btMultiBody* body);
- virtual int getNumMultibodies() const
+ virtual int getNumMultibodies() const
{
return m_multiBodies.size();
}
- btMultiBody* getMultiBody(int mbIndex)
+ btMultiBody* getMultiBody(int mbIndex)
{
return m_multiBodies[mbIndex];
}
- const btMultiBody* getMultiBody(int mbIndex) const
+ const btMultiBody* getMultiBody(int mbIndex) const
{
return m_multiBodies[mbIndex];
}
- virtual void addMultiBodyConstraint( btMultiBodyConstraint* constraint);
+ virtual void addMultiBodyConstraint(btMultiBodyConstraint* constraint);
- virtual int getNumMultiBodyConstraints() const
+ virtual int getNumMultiBodyConstraints() const
{
- return m_multiBodyConstraints.size();
+ return m_multiBodyConstraints.size();
}
- virtual btMultiBodyConstraint* getMultiBodyConstraint( int constraintIndex)
+ virtual btMultiBodyConstraint* getMultiBodyConstraint(int constraintIndex)
{
- return m_multiBodyConstraints[constraintIndex];
+ return m_multiBodyConstraints[constraintIndex];
}
- virtual const btMultiBodyConstraint* getMultiBodyConstraint( int constraintIndex) const
+ virtual const btMultiBodyConstraint* getMultiBodyConstraint(int constraintIndex) const
{
- return m_multiBodyConstraints[constraintIndex];
+ return m_multiBodyConstraints[constraintIndex];
}
- virtual void removeMultiBodyConstraint( btMultiBodyConstraint* constraint);
+ virtual void removeMultiBodyConstraint(btMultiBodyConstraint* constraint);
+
+ virtual void integrateTransforms(btScalar timeStep);
- virtual void integrateTransforms(btScalar timeStep);
+ virtual void debugDrawWorld();
- virtual void debugDrawWorld();
+ virtual void debugDrawMultiBodyConstraint(btMultiBodyConstraint* constraint);
- virtual void debugDrawMultiBodyConstraint(btMultiBodyConstraint* constraint);
-
- void forwardKinematics();
+ void forwardKinematics();
virtual void clearForces();
virtual void clearMultiBodyConstraintForces();
virtual void clearMultiBodyForces();
virtual void applyGravity();
-
- virtual void serialize(btSerializer* serializer);
- virtual void setMultiBodyConstraintSolver(btMultiBodyConstraintSolver* solver);
- virtual void setConstraintSolver(btConstraintSolver* solver);
+ virtual void serialize(btSerializer* serializer);
+ virtual void setMultiBodyConstraintSolver(btMultiBodyConstraintSolver* solver);
+ virtual void setConstraintSolver(btConstraintSolver* solver);
};
-#endif //BT_MULTIBODY_DYNAMICS_WORLD_H
+#endif //BT_MULTIBODY_DYNAMICS_WORLD_H
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.cpp b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.cpp
index af48e94a83..5ef9444c2f 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.cpp
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.cpp
@@ -24,27 +24,27 @@ subject to the following restrictions:
#define BTMBFIXEDCONSTRAINT_DIM 6
btMultiBodyFixedConstraint::btMultiBodyFixedConstraint(btMultiBody* body, int link, btRigidBody* bodyB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB)
- :btMultiBodyConstraint(body,0,link,-1,BTMBFIXEDCONSTRAINT_DIM,false),
- m_rigidBodyA(0),
- m_rigidBodyB(bodyB),
- m_pivotInA(pivotInA),
- m_pivotInB(pivotInB),
- m_frameInA(frameInA),
- m_frameInB(frameInB)
+ : btMultiBodyConstraint(body, 0, link, -1, BTMBFIXEDCONSTRAINT_DIM, false),
+ m_rigidBodyA(0),
+ m_rigidBodyB(bodyB),
+ m_pivotInA(pivotInA),
+ m_pivotInB(pivotInB),
+ m_frameInA(frameInA),
+ m_frameInB(frameInB)
{
- m_data.resize(BTMBFIXEDCONSTRAINT_DIM);//at least store the applied impulses
+ m_data.resize(BTMBFIXEDCONSTRAINT_DIM); //at least store the applied impulses
}
btMultiBodyFixedConstraint::btMultiBodyFixedConstraint(btMultiBody* bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB)
- :btMultiBodyConstraint(bodyA,bodyB,linkA,linkB,BTMBFIXEDCONSTRAINT_DIM,false),
- m_rigidBodyA(0),
- m_rigidBodyB(0),
- m_pivotInA(pivotInA),
- m_pivotInB(pivotInB),
- m_frameInA(frameInA),
- m_frameInB(frameInB)
+ : btMultiBodyConstraint(bodyA, bodyB, linkA, linkB, BTMBFIXEDCONSTRAINT_DIM, false),
+ m_rigidBodyA(0),
+ m_rigidBodyB(0),
+ m_pivotInA(pivotInA),
+ m_pivotInB(pivotInB),
+ m_frameInA(frameInA),
+ m_frameInB(frameInB)
{
- m_data.resize(BTMBFIXEDCONSTRAINT_DIM);//at least store the applied impulses
+ m_data.resize(BTMBFIXEDCONSTRAINT_DIM); //at least store the applied impulses
}
void btMultiBodyFixedConstraint::finalizeMultiDof()
@@ -57,7 +57,6 @@ btMultiBodyFixedConstraint::~btMultiBodyFixedConstraint()
{
}
-
int btMultiBodyFixedConstraint::getIslandIdA() const
{
if (m_rigidBodyA)
@@ -103,82 +102,83 @@ int btMultiBodyFixedConstraint::getIslandIdB() const
void btMultiBodyFixedConstraint::createConstraintRows(btMultiBodyConstraintArray& constraintRows, btMultiBodyJacobianData& data, const btContactSolverInfo& infoGlobal)
{
- int numDim = BTMBFIXEDCONSTRAINT_DIM;
- for (int i=0;i<numDim;i++)
+ int numDim = BTMBFIXEDCONSTRAINT_DIM;
+ for (int i = 0; i < numDim; i++)
{
- btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();
- constraintRow.m_orgConstraint = this;
- constraintRow.m_orgDofIndex = i;
- constraintRow.m_relpos1CrossNormal.setValue(0,0,0);
- constraintRow.m_contactNormal1.setValue(0,0,0);
- constraintRow.m_relpos2CrossNormal.setValue(0,0,0);
- constraintRow.m_contactNormal2.setValue(0,0,0);
- constraintRow.m_angularComponentA.setValue(0,0,0);
- constraintRow.m_angularComponentB.setValue(0,0,0);
-
- constraintRow.m_solverBodyIdA = data.m_fixedBodyId;
- constraintRow.m_solverBodyIdB = data.m_fixedBodyId;
-
- // Convert local points back to world
- btVector3 pivotAworld = m_pivotInA;
- btMatrix3x3 frameAworld = m_frameInA;
- if (m_rigidBodyA)
- {
-
- constraintRow.m_solverBodyIdA = m_rigidBodyA->getCompanionId();
- pivotAworld = m_rigidBodyA->getCenterOfMassTransform()*m_pivotInA;
- frameAworld = frameAworld.transpose()*btMatrix3x3(m_rigidBodyA->getOrientation());
-
- } else
- {
- if (m_bodyA) {
- pivotAworld = m_bodyA->localPosToWorld(m_linkA, m_pivotInA);
- frameAworld = m_bodyA->localFrameToWorld(m_linkA, frameAworld);
- }
- }
- btVector3 pivotBworld = m_pivotInB;
- btMatrix3x3 frameBworld = m_frameInB;
- if (m_rigidBodyB)
- {
- constraintRow.m_solverBodyIdB = m_rigidBodyB->getCompanionId();
- pivotBworld = m_rigidBodyB->getCenterOfMassTransform()*m_pivotInB;
- frameBworld = frameBworld.transpose()*btMatrix3x3(m_rigidBodyB->getOrientation());
-
- } else
- {
- if (m_bodyB) {
- pivotBworld = m_bodyB->localPosToWorld(m_linkB, m_pivotInB);
- frameBworld = m_bodyB->localFrameToWorld(m_linkB, frameBworld);
- }
- }
-
- btMatrix3x3 relRot = frameAworld.inverse()*frameBworld;
- btVector3 angleDiff;
- btGeneric6DofSpring2Constraint::matrixToEulerXYZ(relRot,angleDiff);
-
- btVector3 constraintNormalLin(0,0,0);
- btVector3 constraintNormalAng(0,0,0);
- btScalar posError = 0.0;
- if (i < 3) {
- constraintNormalLin[i] = 1;
- posError = (pivotAworld-pivotBworld).dot(constraintNormalLin);
- fillMultiBodyConstraint(constraintRow, data, 0, 0, constraintNormalAng,
- constraintNormalLin, pivotAworld, pivotBworld,
- posError,
- infoGlobal,
- -m_maxAppliedImpulse, m_maxAppliedImpulse
- );
- }
- else { //i>=3
- constraintNormalAng = frameAworld.getColumn(i%3);
- posError = angleDiff[i%3];
- fillMultiBodyConstraint(constraintRow, data, 0, 0, constraintNormalAng,
- constraintNormalLin, pivotAworld, pivotBworld,
- posError,
- infoGlobal,
- -m_maxAppliedImpulse, m_maxAppliedImpulse, true
- );
- }
+ btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();
+ constraintRow.m_orgConstraint = this;
+ constraintRow.m_orgDofIndex = i;
+ constraintRow.m_relpos1CrossNormal.setValue(0, 0, 0);
+ constraintRow.m_contactNormal1.setValue(0, 0, 0);
+ constraintRow.m_relpos2CrossNormal.setValue(0, 0, 0);
+ constraintRow.m_contactNormal2.setValue(0, 0, 0);
+ constraintRow.m_angularComponentA.setValue(0, 0, 0);
+ constraintRow.m_angularComponentB.setValue(0, 0, 0);
+
+ constraintRow.m_solverBodyIdA = data.m_fixedBodyId;
+ constraintRow.m_solverBodyIdB = data.m_fixedBodyId;
+
+ // Convert local points back to world
+ btVector3 pivotAworld = m_pivotInA;
+ btMatrix3x3 frameAworld = m_frameInA;
+ if (m_rigidBodyA)
+ {
+ constraintRow.m_solverBodyIdA = m_rigidBodyA->getCompanionId();
+ pivotAworld = m_rigidBodyA->getCenterOfMassTransform() * m_pivotInA;
+ frameAworld = frameAworld.transpose() * btMatrix3x3(m_rigidBodyA->getOrientation());
+ }
+ else
+ {
+ if (m_bodyA)
+ {
+ pivotAworld = m_bodyA->localPosToWorld(m_linkA, m_pivotInA);
+ frameAworld = m_bodyA->localFrameToWorld(m_linkA, frameAworld);
+ }
+ }
+ btVector3 pivotBworld = m_pivotInB;
+ btMatrix3x3 frameBworld = m_frameInB;
+ if (m_rigidBodyB)
+ {
+ constraintRow.m_solverBodyIdB = m_rigidBodyB->getCompanionId();
+ pivotBworld = m_rigidBodyB->getCenterOfMassTransform() * m_pivotInB;
+ frameBworld = frameBworld.transpose() * btMatrix3x3(m_rigidBodyB->getOrientation());
+ }
+ else
+ {
+ if (m_bodyB)
+ {
+ pivotBworld = m_bodyB->localPosToWorld(m_linkB, m_pivotInB);
+ frameBworld = m_bodyB->localFrameToWorld(m_linkB, frameBworld);
+ }
+ }
+
+ btMatrix3x3 relRot = frameAworld.inverse() * frameBworld;
+ btVector3 angleDiff;
+ btGeneric6DofSpring2Constraint::matrixToEulerXYZ(relRot, angleDiff);
+
+ btVector3 constraintNormalLin(0, 0, 0);
+ btVector3 constraintNormalAng(0, 0, 0);
+ btScalar posError = 0.0;
+ if (i < 3)
+ {
+ constraintNormalLin[i] = 1;
+ posError = (pivotAworld - pivotBworld).dot(constraintNormalLin);
+ fillMultiBodyConstraint(constraintRow, data, 0, 0, constraintNormalAng,
+ constraintNormalLin, pivotAworld, pivotBworld,
+ posError,
+ infoGlobal,
+ -m_maxAppliedImpulse, m_maxAppliedImpulse);
+ }
+ else
+ { //i>=3
+ constraintNormalAng = frameAworld.getColumn(i % 3);
+ posError = angleDiff[i % 3];
+ fillMultiBodyConstraint(constraintRow, data, 0, 0, constraintNormalAng,
+ constraintNormalLin, pivotAworld, pivotBworld,
+ posError,
+ infoGlobal,
+ -m_maxAppliedImpulse, m_maxAppliedImpulse, true);
+ }
}
}
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.h
index 036025136e..adb1cb47da 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.h
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.h
@@ -23,16 +23,14 @@ subject to the following restrictions:
class btMultiBodyFixedConstraint : public btMultiBodyConstraint
{
protected:
-
- btRigidBody* m_rigidBodyA;
- btRigidBody* m_rigidBodyB;
- btVector3 m_pivotInA;
- btVector3 m_pivotInB;
- btMatrix3x3 m_frameInA;
- btMatrix3x3 m_frameInB;
+ btRigidBody* m_rigidBodyA;
+ btRigidBody* m_rigidBodyB;
+ btVector3 m_pivotInA;
+ btVector3 m_pivotInB;
+ btMatrix3x3 m_frameInA;
+ btMatrix3x3 m_frameInB;
public:
-
btMultiBodyFixedConstraint(btMultiBody* body, int link, btRigidBody* bodyB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB);
btMultiBodyFixedConstraint(btMultiBody* bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB);
@@ -44,18 +42,18 @@ public:
virtual int getIslandIdB() const;
virtual void createConstraintRows(btMultiBodyConstraintArray& constraintRows,
- btMultiBodyJacobianData& data,
- const btContactSolverInfo& infoGlobal);
-
- const btVector3& getPivotInA() const
- {
- return m_pivotInA;
- }
-
- void setPivotInA(const btVector3& pivotInA)
- {
- m_pivotInA = pivotInA;
- }
+ btMultiBodyJacobianData& data,
+ const btContactSolverInfo& infoGlobal);
+
+ const btVector3& getPivotInA() const
+ {
+ return m_pivotInA;
+ }
+
+ void setPivotInA(const btVector3& pivotInA)
+ {
+ m_pivotInA = pivotInA;
+ }
const btVector3& getPivotInB() const
{
@@ -66,29 +64,28 @@ public:
{
m_pivotInB = pivotInB;
}
-
- const btMatrix3x3& getFrameInA() const
- {
- return m_frameInA;
- }
-
- void setFrameInA(const btMatrix3x3& frameInA)
- {
- m_frameInA = frameInA;
- }
-
- const btMatrix3x3& getFrameInB() const
- {
- return m_frameInB;
- }
-
- virtual void setFrameInB(const btMatrix3x3& frameInB)
- {
- m_frameInB = frameInB;
- }
- virtual void debugDraw(class btIDebugDraw* drawer);
+ const btMatrix3x3& getFrameInA() const
+ {
+ return m_frameInA;
+ }
+ void setFrameInA(const btMatrix3x3& frameInA)
+ {
+ m_frameInA = frameInA;
+ }
+
+ const btMatrix3x3& getFrameInB() const
+ {
+ return m_frameInB;
+ }
+
+ virtual void setFrameInB(const btMatrix3x3& frameInB)
+ {
+ m_frameInB = frameInB;
+ }
+
+ virtual void debugDraw(class btIDebugDraw* drawer);
};
-#endif //BT_MULTIBODY_FIXED_CONSTRAINT_H
+#endif //BT_MULTIBODY_FIXED_CONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyGearConstraint.cpp b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyGearConstraint.cpp
index 09ddd65cd8..bf6b811d26 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyGearConstraint.cpp
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyGearConstraint.cpp
@@ -21,20 +21,18 @@ subject to the following restrictions:
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
btMultiBodyGearConstraint::btMultiBodyGearConstraint(btMultiBody* bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB)
- :btMultiBodyConstraint(bodyA,bodyB,linkA,linkB,1,false),
- m_gearRatio(1),
- m_gearAuxLink(-1),
- m_erp(0),
- m_relativePositionTarget(0)
+ : btMultiBodyConstraint(bodyA, bodyB, linkA, linkB, 1, false),
+ m_gearRatio(1),
+ m_gearAuxLink(-1),
+ m_erp(0),
+ m_relativePositionTarget(0)
{
-
}
void btMultiBodyGearConstraint::finalizeMultiDof()
{
-
allocateJacobiansMultiDof();
-
+
m_numDofsFinalized = m_jacSizeBoth;
}
@@ -42,7 +40,6 @@ btMultiBodyGearConstraint::~btMultiBodyGearConstraint()
{
}
-
int btMultiBodyGearConstraint::getIslandIdA() const
{
if (m_bodyA)
@@ -81,27 +78,25 @@ int btMultiBodyGearConstraint::getIslandIdB() const
return -1;
}
-
void btMultiBodyGearConstraint::createConstraintRows(btMultiBodyConstraintArray& constraintRows,
- btMultiBodyJacobianData& data,
- const btContactSolverInfo& infoGlobal)
+ btMultiBodyJacobianData& data,
+ const btContactSolverInfo& infoGlobal)
{
- // only positions need to be updated -- data.m_jacobians and force
- // directions were set in the ctor and never change.
-
+ // only positions need to be updated -- data.m_jacobians and force
+ // directions were set in the ctor and never change.
+
if (m_numDofsFinalized != m_jacSizeBoth)
{
- finalizeMultiDof();
+ finalizeMultiDof();
}
//don't crash
if (m_numDofsFinalized != m_jacSizeBoth)
return;
-
- if (m_maxAppliedImpulse==0.f)
+ if (m_maxAppliedImpulse == 0.f)
return;
-
+
// note: we rely on the fact that data.m_jacobians are
// always initialized to zero by the Constraint ctor
int linkDoF = 0;
@@ -114,67 +109,66 @@ void btMultiBodyGearConstraint::createConstraintRows(btMultiBodyConstraintArray&
btScalar posError = 0;
const btVector3 dummy(0, 0, 0);
-
+
btScalar kp = 1;
btScalar kd = 1;
int numRows = getNumRows();
- for (int row=0;row<numRows;row++)
+ for (int row = 0; row < numRows; row++)
{
btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();
-
- int dof = 0;
- btScalar currentPosition = m_bodyA->getJointPosMultiDof(m_linkA)[dof];
- btScalar currentVelocity = m_bodyA->getJointVelMultiDof(m_linkA)[dof];
+ int dof = 0;
+ btScalar currentPosition = m_bodyA->getJointPosMultiDof(m_linkA)[dof];
+ btScalar currentVelocity = m_bodyA->getJointVelMultiDof(m_linkA)[dof];
btScalar auxVel = 0;
-
- if (m_gearAuxLink>=0)
+
+ if (m_gearAuxLink >= 0)
{
auxVel = m_bodyA->getJointVelMultiDof(m_gearAuxLink)[dof];
}
currentVelocity += auxVel;
- if (m_erp!=0)
+ if (m_erp != 0)
{
btScalar currentPositionA = m_bodyA->getJointPosMultiDof(m_linkA)[dof];
if (m_gearAuxLink >= 0)
{
currentPositionA -= m_bodyA->getJointPosMultiDof(m_gearAuxLink)[dof];
}
- btScalar currentPositionB = m_gearRatio*m_bodyA->getJointPosMultiDof(m_linkB)[dof];
- btScalar diff = currentPositionB+currentPositionA;
+ btScalar currentPositionB = m_gearRatio * m_bodyA->getJointPosMultiDof(m_linkB)[dof];
+ btScalar diff = currentPositionB + currentPositionA;
btScalar desiredPositionDiff = this->m_relativePositionTarget;
- posError = -m_erp*(desiredPositionDiff - diff);
+ posError = -m_erp * (desiredPositionDiff - diff);
}
-
- btScalar desiredRelativeVelocity = auxVel;
-
- fillMultiBodyConstraint(constraintRow,data,jacobianA(row),jacobianB(row),dummy,dummy,dummy,dummy,posError,infoGlobal,-m_maxAppliedImpulse,m_maxAppliedImpulse,false,1,false,desiredRelativeVelocity);
+
+ btScalar desiredRelativeVelocity = auxVel;
+
+ fillMultiBodyConstraint(constraintRow, data, jacobianA(row), jacobianB(row), dummy, dummy, dummy, dummy, posError, infoGlobal, -m_maxAppliedImpulse, m_maxAppliedImpulse, false, 1, false, desiredRelativeVelocity);
constraintRow.m_orgConstraint = this;
constraintRow.m_orgDofIndex = row;
{
//expect either prismatic or revolute joint type for now
- btAssert((m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::eRevolute)||(m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::ePrismatic));
+ btAssert((m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::eRevolute) || (m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::ePrismatic));
switch (m_bodyA->getLink(m_linkA).m_jointType)
{
case btMultibodyLink::eRevolute:
{
constraintRow.m_contactNormal1.setZero();
constraintRow.m_contactNormal2.setZero();
- btVector3 revoluteAxisInWorld = quatRotate(m_bodyA->getLink(m_linkA).m_cachedWorldTransform.getRotation(),m_bodyA->getLink(m_linkA).m_axes[0].m_topVec);
- constraintRow.m_relpos1CrossNormal=revoluteAxisInWorld;
- constraintRow.m_relpos2CrossNormal=-revoluteAxisInWorld;
-
+ btVector3 revoluteAxisInWorld = quatRotate(m_bodyA->getLink(m_linkA).m_cachedWorldTransform.getRotation(), m_bodyA->getLink(m_linkA).m_axes[0].m_topVec);
+ constraintRow.m_relpos1CrossNormal = revoluteAxisInWorld;
+ constraintRow.m_relpos2CrossNormal = -revoluteAxisInWorld;
+
break;
}
case btMultibodyLink::ePrismatic:
{
- btVector3 prismaticAxisInWorld = quatRotate(m_bodyA->getLink(m_linkA).m_cachedWorldTransform.getRotation(),m_bodyA->getLink(m_linkA).m_axes[0].m_bottomVec);
- constraintRow.m_contactNormal1=prismaticAxisInWorld;
- constraintRow.m_contactNormal2=-prismaticAxisInWorld;
+ btVector3 prismaticAxisInWorld = quatRotate(m_bodyA->getLink(m_linkA).m_cachedWorldTransform.getRotation(), m_bodyA->getLink(m_linkA).m_axes[0].m_bottomVec);
+ constraintRow.m_contactNormal1 = prismaticAxisInWorld;
+ constraintRow.m_contactNormal2 = -prismaticAxisInWorld;
constraintRow.m_relpos1CrossNormal.setZero();
- constraintRow.m_relpos2CrossNormal.setZero();
+ constraintRow.m_relpos2CrossNormal.setZero();
break;
}
default:
@@ -182,10 +176,6 @@ void btMultiBodyGearConstraint::createConstraintRows(btMultiBodyConstraintArray&
btAssert(0);
}
};
-
}
-
}
-
}
-
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyGearConstraint.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyGearConstraint.h
index 0115de6241..31888fbc68 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyGearConstraint.h
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyGearConstraint.h
@@ -23,20 +23,18 @@ subject to the following restrictions:
class btMultiBodyGearConstraint : public btMultiBodyConstraint
{
protected:
+ btRigidBody* m_rigidBodyA;
+ btRigidBody* m_rigidBodyB;
+ btVector3 m_pivotInA;
+ btVector3 m_pivotInB;
+ btMatrix3x3 m_frameInA;
+ btMatrix3x3 m_frameInB;
+ btScalar m_gearRatio;
+ int m_gearAuxLink;
+ btScalar m_erp;
+ btScalar m_relativePositionTarget;
- btRigidBody* m_rigidBodyA;
- btRigidBody* m_rigidBodyB;
- btVector3 m_pivotInA;
- btVector3 m_pivotInB;
- btMatrix3x3 m_frameInA;
- btMatrix3x3 m_frameInB;
- btScalar m_gearRatio;
- int m_gearAuxLink;
- btScalar m_erp;
- btScalar m_relativePositionTarget;
-
public:
-
//btMultiBodyGearConstraint(btMultiBody* body, int link, btRigidBody* bodyB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB);
btMultiBodyGearConstraint(btMultiBody* bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB);
@@ -48,18 +46,18 @@ public:
virtual int getIslandIdB() const;
virtual void createConstraintRows(btMultiBodyConstraintArray& constraintRows,
- btMultiBodyJacobianData& data,
- const btContactSolverInfo& infoGlobal);
-
- const btVector3& getPivotInA() const
- {
- return m_pivotInA;
- }
-
- void setPivotInA(const btVector3& pivotInA)
- {
- m_pivotInA = pivotInA;
- }
+ btMultiBodyJacobianData& data,
+ const btContactSolverInfo& infoGlobal);
+
+ const btVector3& getPivotInA() const
+ {
+ return m_pivotInA;
+ }
+
+ void setPivotInA(const btVector3& pivotInA)
+ {
+ m_pivotInA = pivotInA;
+ }
const btVector3& getPivotInB() const
{
@@ -70,32 +68,32 @@ public:
{
m_pivotInB = pivotInB;
}
-
- const btMatrix3x3& getFrameInA() const
- {
- return m_frameInA;
- }
-
- void setFrameInA(const btMatrix3x3& frameInA)
- {
- m_frameInA = frameInA;
- }
-
- const btMatrix3x3& getFrameInB() const
- {
- return m_frameInB;
- }
-
- virtual void setFrameInB(const btMatrix3x3& frameInB)
- {
- m_frameInB = frameInB;
- }
+
+ const btMatrix3x3& getFrameInA() const
+ {
+ return m_frameInA;
+ }
+
+ void setFrameInA(const btMatrix3x3& frameInA)
+ {
+ m_frameInA = frameInA;
+ }
+
+ const btMatrix3x3& getFrameInB() const
+ {
+ return m_frameInB;
+ }
+
+ virtual void setFrameInB(const btMatrix3x3& frameInB)
+ {
+ m_frameInB = frameInB;
+ }
virtual void debugDraw(class btIDebugDraw* drawer)
{
//todo(erwincoumans)
}
-
+
virtual void setGearRatio(btScalar gearRatio)
{
m_gearRatio = gearRatio;
@@ -114,4 +112,4 @@ public:
}
};
-#endif //BT_MULTIBODY_GEAR_CONSTRAINT_H
+#endif //BT_MULTIBODY_GEAR_CONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointFeedback.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointFeedback.h
index 5c2fa8ed5b..d943019e71 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointFeedback.h
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointFeedback.h
@@ -12,8 +12,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
-
#ifndef BT_MULTIBODY_JOINT_FEEDBACK_H
#define BT_MULTIBODY_JOINT_FEEDBACK_H
@@ -21,7 +19,7 @@ subject to the following restrictions:
struct btMultiBodyJointFeedback
{
- btSpatialForceVector m_reactionForces;
+ btSpatialForceVector m_reactionForces;
};
-#endif //BT_MULTIBODY_JOINT_FEEDBACK_H
+#endif //BT_MULTIBODY_JOINT_FEEDBACK_H
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp
index 35c929f7ce..8791ad2868 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp
@@ -20,21 +20,18 @@ subject to the following restrictions:
#include "btMultiBodyLinkCollider.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-
-
btMultiBodyJointLimitConstraint::btMultiBodyJointLimitConstraint(btMultiBody* body, int link, btScalar lower, btScalar upper)
//:btMultiBodyConstraint(body,0,link,-1,2,true),
- :btMultiBodyConstraint(body,body,link,body->getLink(link).m_parent,2,true),
- m_lowerBound(lower),
- m_upperBound(upper)
+ : btMultiBodyConstraint(body, body, link, body->getLink(link).m_parent, 2, true),
+ m_lowerBound(lower),
+ m_upperBound(upper)
{
-
}
void btMultiBodyJointLimitConstraint::finalizeMultiDof()
{
// the data.m_jacobians never change, so may as well
- // initialize them here
+ // initialize them here
allocateJacobiansMultiDof();
@@ -53,10 +50,8 @@ btMultiBodyJointLimitConstraint::~btMultiBodyJointLimitConstraint()
{
}
-
int btMultiBodyJointLimitConstraint::getIslandIdA() const
{
-
if (m_bodyA)
{
if (m_linkA < 0)
@@ -93,72 +88,69 @@ int btMultiBodyJointLimitConstraint::getIslandIdB() const
return -1;
}
-
void btMultiBodyJointLimitConstraint::createConstraintRows(btMultiBodyConstraintArray& constraintRows,
- btMultiBodyJacobianData& data,
- const btContactSolverInfo& infoGlobal)
+ btMultiBodyJacobianData& data,
+ const btContactSolverInfo& infoGlobal)
{
-
- // only positions need to be updated -- data.m_jacobians and force
- // directions were set in the ctor and never change.
+ // only positions need to be updated -- data.m_jacobians and force
+ // directions were set in the ctor and never change.
if (m_numDofsFinalized != m_jacSizeBoth)
{
- finalizeMultiDof();
+ finalizeMultiDof();
}
+ // row 0: the lower bound
+ setPosition(0, m_bodyA->getJointPos(m_linkA) - m_lowerBound); //multidof: this is joint-type dependent
- // row 0: the lower bound
- setPosition(0, m_bodyA->getJointPos(m_linkA) - m_lowerBound); //multidof: this is joint-type dependent
+ // row 1: the upper bound
+ setPosition(1, m_upperBound - m_bodyA->getJointPos(m_linkA));
- // row 1: the upper bound
- setPosition(1, m_upperBound - m_bodyA->getJointPos(m_linkA));
-
- for (int row=0;row<getNumRows();row++)
+ for (int row = 0; row < getNumRows(); row++)
{
btScalar penetration = getPosition(row);
//todo: consider adding some safety threshold here
- if (penetration>0)
+ if (penetration > 0)
{
continue;
}
- btScalar direction = row? -1 : 1;
+ btScalar direction = row ? -1 : 1;
btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();
- constraintRow.m_orgConstraint = this;
- constraintRow.m_orgDofIndex = row;
-
+ constraintRow.m_orgConstraint = this;
+ constraintRow.m_orgDofIndex = row;
+
constraintRow.m_multiBodyA = m_bodyA;
constraintRow.m_multiBodyB = m_bodyB;
- const btScalar posError = 0; //why assume it's zero?
+ const btScalar posError = 0; //why assume it's zero?
const btVector3 dummy(0, 0, 0);
- btScalar rel_vel = fillMultiBodyConstraint(constraintRow,data,jacobianA(row),jacobianB(row),dummy,dummy,dummy,dummy,posError,infoGlobal,0,m_maxAppliedImpulse);
+ btScalar rel_vel = fillMultiBodyConstraint(constraintRow, data, jacobianA(row), jacobianB(row), dummy, dummy, dummy, dummy, posError, infoGlobal, 0, m_maxAppliedImpulse);
{
//expect either prismatic or revolute joint type for now
- btAssert((m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::eRevolute)||(m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::ePrismatic));
+ btAssert((m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::eRevolute) || (m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::ePrismatic));
switch (m_bodyA->getLink(m_linkA).m_jointType)
{
case btMultibodyLink::eRevolute:
{
constraintRow.m_contactNormal1.setZero();
constraintRow.m_contactNormal2.setZero();
- btVector3 revoluteAxisInWorld = direction*quatRotate(m_bodyA->getLink(m_linkA).m_cachedWorldTransform.getRotation(),m_bodyA->getLink(m_linkA).m_axes[0].m_topVec);
- constraintRow.m_relpos1CrossNormal=revoluteAxisInWorld;
- constraintRow.m_relpos2CrossNormal=-revoluteAxisInWorld;
-
+ btVector3 revoluteAxisInWorld = direction * quatRotate(m_bodyA->getLink(m_linkA).m_cachedWorldTransform.getRotation(), m_bodyA->getLink(m_linkA).m_axes[0].m_topVec);
+ constraintRow.m_relpos1CrossNormal = revoluteAxisInWorld;
+ constraintRow.m_relpos2CrossNormal = -revoluteAxisInWorld;
+
break;
}
case btMultibodyLink::ePrismatic:
{
- btVector3 prismaticAxisInWorld = direction* quatRotate(m_bodyA->getLink(m_linkA).m_cachedWorldTransform.getRotation(),m_bodyA->getLink(m_linkA).m_axes[0].m_bottomVec);
- constraintRow.m_contactNormal1=prismaticAxisInWorld;
- constraintRow.m_contactNormal2=-prismaticAxisInWorld;
+ btVector3 prismaticAxisInWorld = direction * quatRotate(m_bodyA->getLink(m_linkA).m_cachedWorldTransform.getRotation(), m_bodyA->getLink(m_linkA).m_axes[0].m_bottomVec);
+ constraintRow.m_contactNormal1 = prismaticAxisInWorld;
+ constraintRow.m_contactNormal2 = -prismaticAxisInWorld;
constraintRow.m_relpos1CrossNormal.setZero();
constraintRow.m_relpos2CrossNormal.setZero();
-
+
break;
}
default:
@@ -166,36 +158,35 @@ void btMultiBodyJointLimitConstraint::createConstraintRows(btMultiBodyConstraint
btAssert(0);
}
};
-
}
{
-
btScalar positionalError = 0.f;
- btScalar velocityError = - rel_vel;// * damping;
+ btScalar velocityError = -rel_vel; // * damping;
btScalar erp = infoGlobal.m_erp2;
if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
{
erp = infoGlobal.m_erp;
}
- if (penetration>0)
+ if (penetration > 0)
{
positionalError = 0;
velocityError = -penetration / infoGlobal.m_timeStep;
- } else
+ }
+ else
{
- positionalError = -penetration * erp/infoGlobal.m_timeStep;
+ positionalError = -penetration * erp / infoGlobal.m_timeStep;
}
- btScalar penetrationImpulse = positionalError*constraintRow.m_jacDiagABInv;
- btScalar velocityImpulse = velocityError *constraintRow.m_jacDiagABInv;
+ btScalar penetrationImpulse = positionalError * constraintRow.m_jacDiagABInv;
+ btScalar velocityImpulse = velocityError * constraintRow.m_jacDiagABInv;
if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
{
//combine position and velocity into rhs
- constraintRow.m_rhs = penetrationImpulse+velocityImpulse;
+ constraintRow.m_rhs = penetrationImpulse + velocityImpulse;
constraintRow.m_rhsPenetration = 0.f;
-
- } else
+ }
+ else
{
//split position and velocity into rhs and m_rhsPenetration
constraintRow.m_rhs = velocityImpulse;
@@ -203,9 +194,4 @@ void btMultiBodyJointLimitConstraint::createConstraintRows(btMultiBodyConstraint
}
}
}
-
}
-
-
-
-
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.h
index 55b8d122b9..6716ba490f 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.h
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.h
@@ -22,11 +22,10 @@ struct btSolverInfo;
class btMultiBodyJointLimitConstraint : public btMultiBodyConstraint
{
protected:
+ btScalar m_lowerBound;
+ btScalar m_upperBound;
- btScalar m_lowerBound;
- btScalar m_upperBound;
public:
-
btMultiBodyJointLimitConstraint(btMultiBody* body, int link, btScalar lower, btScalar upper);
virtual ~btMultiBodyJointLimitConstraint();
@@ -36,15 +35,13 @@ public:
virtual int getIslandIdB() const;
virtual void createConstraintRows(btMultiBodyConstraintArray& constraintRows,
- btMultiBodyJacobianData& data,
- const btContactSolverInfo& infoGlobal);
+ btMultiBodyJacobianData& data,
+ const btContactSolverInfo& infoGlobal);
virtual void debugDraw(class btIDebugDraw* drawer)
{
//todo(erwincoumans)
}
-
};
-#endif //BT_MULTIBODY_JOINT_LIMIT_CONSTRAINT_H
-
+#endif //BT_MULTIBODY_JOINT_LIMIT_CONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp
index 2a70ea97e5..5c816c4987 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp
@@ -20,22 +20,18 @@ subject to the following restrictions:
#include "btMultiBodyLinkCollider.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-
btMultiBodyJointMotor::btMultiBodyJointMotor(btMultiBody* body, int link, btScalar desiredVelocity, btScalar maxMotorImpulse)
- :btMultiBodyConstraint(body,body,link,body->getLink(link).m_parent,1,true),
- m_desiredVelocity(desiredVelocity),
- m_desiredPosition(0),
- m_kd(1.),
- m_kp(0),
- m_erp(1),
- m_rhsClamp(SIMD_INFINITY)
+ : btMultiBodyConstraint(body, body, link, body->getLink(link).m_parent, 1, true),
+ m_desiredVelocity(desiredVelocity),
+ m_desiredPosition(0),
+ m_kd(1.),
+ m_kp(0),
+ m_erp(1),
+ m_rhsClamp(SIMD_INFINITY)
{
-
m_maxAppliedImpulse = maxMotorImpulse;
// the data.m_jacobians never change, so may as well
- // initialize them here
-
-
+ // initialize them here
}
void btMultiBodyJointMotor::finalizeMultiDof()
@@ -55,18 +51,17 @@ void btMultiBodyJointMotor::finalizeMultiDof()
btMultiBodyJointMotor::btMultiBodyJointMotor(btMultiBody* body, int link, int linkDoF, btScalar desiredVelocity, btScalar maxMotorImpulse)
//:btMultiBodyConstraint(body,0,link,-1,1,true),
- :btMultiBodyConstraint(body,body,link,body->getLink(link).m_parent,1,true),
- m_desiredVelocity(desiredVelocity),
- m_desiredPosition(0),
- m_kd(1.),
- m_kp(0),
- m_erp(1),
- m_rhsClamp(SIMD_INFINITY)
+ : btMultiBodyConstraint(body, body, link, body->getLink(link).m_parent, 1, true),
+ m_desiredVelocity(desiredVelocity),
+ m_desiredPosition(0),
+ m_kd(1.),
+ m_kp(0),
+ m_erp(1),
+ m_rhsClamp(SIMD_INFINITY)
{
btAssert(linkDoF < body->getLink(link).m_dofCount);
m_maxAppliedImpulse = maxMotorImpulse;
-
}
btMultiBodyJointMotor::~btMultiBodyJointMotor()
{
@@ -108,76 +103,74 @@ int btMultiBodyJointMotor::getIslandIdB() const
return -1;
}
-
void btMultiBodyJointMotor::createConstraintRows(btMultiBodyConstraintArray& constraintRows,
- btMultiBodyJacobianData& data,
- const btContactSolverInfo& infoGlobal)
+ btMultiBodyJacobianData& data,
+ const btContactSolverInfo& infoGlobal)
{
- // only positions need to be updated -- data.m_jacobians and force
- // directions were set in the ctor and never change.
-
+ // only positions need to be updated -- data.m_jacobians and force
+ // directions were set in the ctor and never change.
+
if (m_numDofsFinalized != m_jacSizeBoth)
{
- finalizeMultiDof();
+ finalizeMultiDof();
}
//don't crash
if (m_numDofsFinalized != m_jacSizeBoth)
return;
- if (m_maxAppliedImpulse==0.f)
+ if (m_maxAppliedImpulse == 0.f)
return;
const btScalar posError = 0;
const btVector3 dummy(0, 0, 0);
- for (int row=0;row<getNumRows();row++)
+ for (int row = 0; row < getNumRows(); row++)
{
btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();
- int dof = 0;
- btScalar currentPosition = m_bodyA->getJointPosMultiDof(m_linkA)[dof];
- btScalar currentVelocity = m_bodyA->getJointVelMultiDof(m_linkA)[dof];
- btScalar positionStabiliationTerm = m_erp*(m_desiredPosition-currentPosition)/infoGlobal.m_timeStep;
-
- btScalar velocityError = (m_desiredVelocity - currentVelocity);
- btScalar rhs = m_kp * positionStabiliationTerm + currentVelocity+m_kd * velocityError;
- if (rhs>m_rhsClamp)
+ int dof = 0;
+ btScalar currentPosition = m_bodyA->getJointPosMultiDof(m_linkA)[dof];
+ btScalar currentVelocity = m_bodyA->getJointVelMultiDof(m_linkA)[dof];
+ btScalar positionStabiliationTerm = m_erp * (m_desiredPosition - currentPosition) / infoGlobal.m_timeStep;
+
+ btScalar velocityError = (m_desiredVelocity - currentVelocity);
+ btScalar rhs = m_kp * positionStabiliationTerm + currentVelocity + m_kd * velocityError;
+ if (rhs > m_rhsClamp)
{
- rhs=m_rhsClamp;
+ rhs = m_rhsClamp;
}
- if (rhs<-m_rhsClamp)
+ if (rhs < -m_rhsClamp)
{
- rhs=-m_rhsClamp;
+ rhs = -m_rhsClamp;
}
-
-
- fillMultiBodyConstraint(constraintRow,data,jacobianA(row),jacobianB(row),dummy,dummy,dummy,dummy,posError,infoGlobal,-m_maxAppliedImpulse,m_maxAppliedImpulse,false,1,false,rhs);
+
+ fillMultiBodyConstraint(constraintRow, data, jacobianA(row), jacobianB(row), dummy, dummy, dummy, dummy, posError, infoGlobal, -m_maxAppliedImpulse, m_maxAppliedImpulse, false, 1, false, rhs);
constraintRow.m_orgConstraint = this;
constraintRow.m_orgDofIndex = row;
{
//expect either prismatic or revolute joint type for now
- btAssert((m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::eRevolute)||(m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::ePrismatic));
+ btAssert((m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::eRevolute) || (m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::ePrismatic));
switch (m_bodyA->getLink(m_linkA).m_jointType)
{
case btMultibodyLink::eRevolute:
{
constraintRow.m_contactNormal1.setZero();
constraintRow.m_contactNormal2.setZero();
- btVector3 revoluteAxisInWorld = quatRotate(m_bodyA->getLink(m_linkA).m_cachedWorldTransform.getRotation(),m_bodyA->getLink(m_linkA).m_axes[0].m_topVec);
- constraintRow.m_relpos1CrossNormal=revoluteAxisInWorld;
- constraintRow.m_relpos2CrossNormal=-revoluteAxisInWorld;
-
+ btVector3 revoluteAxisInWorld = quatRotate(m_bodyA->getLink(m_linkA).m_cachedWorldTransform.getRotation(), m_bodyA->getLink(m_linkA).m_axes[0].m_topVec);
+ constraintRow.m_relpos1CrossNormal = revoluteAxisInWorld;
+ constraintRow.m_relpos2CrossNormal = -revoluteAxisInWorld;
+
break;
}
case btMultibodyLink::ePrismatic:
{
- btVector3 prismaticAxisInWorld = quatRotate(m_bodyA->getLink(m_linkA).m_cachedWorldTransform.getRotation(),m_bodyA->getLink(m_linkA).m_axes[0].m_bottomVec);
- constraintRow.m_contactNormal1=prismaticAxisInWorld;
- constraintRow.m_contactNormal2=-prismaticAxisInWorld;
+ btVector3 prismaticAxisInWorld = quatRotate(m_bodyA->getLink(m_linkA).m_cachedWorldTransform.getRotation(), m_bodyA->getLink(m_linkA).m_axes[0].m_bottomVec);
+ constraintRow.m_contactNormal1 = prismaticAxisInWorld;
+ constraintRow.m_contactNormal2 = -prismaticAxisInWorld;
constraintRow.m_relpos1CrossNormal.setZero();
constraintRow.m_relpos2CrossNormal.setZero();
-
+
break;
}
default:
@@ -185,10 +178,6 @@ void btMultiBodyJointMotor::createConstraintRows(btMultiBodyConstraintArray& con
btAssert(0);
}
};
-
}
-
}
-
}
-
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointMotor.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointMotor.h
index 4063bed79a..1aca36352e 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointMotor.h
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointMotor.h
@@ -24,41 +24,38 @@ struct btSolverInfo;
class btMultiBodyJointMotor : public btMultiBodyConstraint
{
protected:
-
- btScalar m_desiredVelocity;
- btScalar m_desiredPosition;
- btScalar m_kd;
- btScalar m_kp;
- btScalar m_erp;
- btScalar m_rhsClamp;//maximum error
-
+ btScalar m_desiredVelocity;
+ btScalar m_desiredPosition;
+ btScalar m_kd;
+ btScalar m_kp;
+ btScalar m_erp;
+ btScalar m_rhsClamp; //maximum error
public:
-
btMultiBodyJointMotor(btMultiBody* body, int link, btScalar desiredVelocity, btScalar maxMotorImpulse);
btMultiBodyJointMotor(btMultiBody* body, int link, int linkDoF, btScalar desiredVelocity, btScalar maxMotorImpulse);
virtual ~btMultiBodyJointMotor();
- virtual void finalizeMultiDof();
+ virtual void finalizeMultiDof();
virtual int getIslandIdA() const;
virtual int getIslandIdB() const;
virtual void createConstraintRows(btMultiBodyConstraintArray& constraintRows,
- btMultiBodyJacobianData& data,
- const btContactSolverInfo& infoGlobal);
+ btMultiBodyJacobianData& data,
+ const btContactSolverInfo& infoGlobal);
+
+ virtual void setVelocityTarget(btScalar velTarget, btScalar kd = 1.f)
+ {
+ m_desiredVelocity = velTarget;
+ m_kd = kd;
+ }
- virtual void setVelocityTarget(btScalar velTarget, btScalar kd = 1.f)
- {
- m_desiredVelocity = velTarget;
- m_kd = kd;
- }
+ virtual void setPositionTarget(btScalar posTarget, btScalar kp = 1.f)
+ {
+ m_desiredPosition = posTarget;
+ m_kp = kp;
+ }
- virtual void setPositionTarget(btScalar posTarget, btScalar kp = 1.f)
- {
- m_desiredPosition = posTarget;
- m_kp = kp;
- }
-
virtual void setErp(btScalar erp)
{
m_erp = erp;
@@ -77,5 +74,4 @@ public:
}
};
-#endif //BT_MULTIBODY_JOINT_MOTOR_H
-
+#endif //BT_MULTIBODY_JOINT_MOTOR_H
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyLink.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyLink.h
index 21c9e7a557..92d41dfac2 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyLink.h
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyLink.h
@@ -20,7 +20,7 @@ subject to the following restrictions:
#include "LinearMath/btVector3.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-enum btMultiBodyLinkFlags
+enum btMultiBodyLinkFlags
{
BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION = 1,
BT_MULTIBODYLINKFLAGS_DISABLE_ALL_PARENT_COLLISION = 2,
@@ -36,7 +36,6 @@ enum btMultiBodyLinkFlags
//namespace {
-
#include "LinearMath/btSpatialAlgebra.h"
//}
@@ -45,27 +44,26 @@ enum btMultiBodyLinkFlags
// Link struct
//
-struct btMultibodyLink
+struct btMultibodyLink
{
-
BT_DECLARE_ALIGNED_ALLOCATOR();
- btScalar m_mass; // mass of link
- btVector3 m_inertiaLocal; // inertia of link (local frame; diagonal)
+ btScalar m_mass; // mass of link
+ btVector3 m_inertiaLocal; // inertia of link (local frame; diagonal)
+
+ int m_parent; // index of the parent link (assumed to be < index of this link), or -1 if parent is the base link.
- int m_parent; // index of the parent link (assumed to be < index of this link), or -1 if parent is the base link.
+ btQuaternion m_zeroRotParentToThis; // rotates vectors in parent-frame to vectors in local-frame (when q=0). constant.
- btQuaternion m_zeroRotParentToThis; // rotates vectors in parent-frame to vectors in local-frame (when q=0). constant.
+ btVector3 m_dVector; // vector from the inboard joint pos to this link's COM. (local frame.) constant.
+ //this is set to zero for planar joint (see also m_eVector comment)
- btVector3 m_dVector; // vector from the inboard joint pos to this link's COM. (local frame.) constant.
- //this is set to zero for planar joint (see also m_eVector comment)
-
- // m_eVector is constant, but depends on the joint type:
- // revolute, fixed, prismatic, spherical: vector from parent's COM to the pivot point, in PARENT's frame.
+ // m_eVector is constant, but depends on the joint type:
+ // revolute, fixed, prismatic, spherical: vector from parent's COM to the pivot point, in PARENT's frame.
// planar: vector from COM of parent to COM of this link, WHEN Q = 0. (local frame.)
// todo: fix the planar so it is consistent with the other joints
-
- btVector3 m_eVector;
+
+ btVector3 m_eVector;
btSpatialMotionVector m_absFrameTotVelocity, m_absFrameLocVelocity;
@@ -79,13 +77,11 @@ struct btMultibodyLink
eInvalid
};
-
-
// "axis" = spatial joint axis (Mirtich Defn 9 p104). (expressed in local frame.) constant.
- // for prismatic: m_axesTop[0] = zero;
- // m_axesBottom[0] = unit vector along the joint axis.
- // for revolute: m_axesTop[0] = unit vector along the rotation axis (u);
- // m_axesBottom[0] = u cross m_dVector (i.e. COM linear motion due to the rotation at the joint)
+ // for prismatic: m_axesTop[0] = zero;
+ // m_axesBottom[0] = unit vector along the joint axis.
+ // for revolute: m_axesTop[0] = unit vector along the rotation axis (u);
+ // m_axesBottom[0] = u cross m_dVector (i.e. COM linear motion due to the rotation at the joint)
//
// for spherical: m_axesTop[0][1][2] (u1,u2,u3) form a 3x3 identity matrix (3 rotation axes)
// m_axesBottom[0][1][2] cross u1,u2,u3 (i.e. COM linear motion due to the rotation at the joint)
@@ -93,143 +89,141 @@ struct btMultibodyLink
// for planar: m_axesTop[0] = unit vector along the rotation axis (u); defines the plane of motion
// m_axesTop[1][2] = zero
// m_axesBottom[0] = zero
- // m_axesBottom[1][2] = unit vectors along the translational axes on that plane
+ // m_axesBottom[1][2] = unit vectors along the translational axes on that plane
btSpatialMotionVector m_axes[6];
void setAxisTop(int dof, const btVector3 &axis) { m_axes[dof].m_topVec = axis; }
- void setAxisBottom(int dof, const btVector3 &axis)
- {
- m_axes[dof].m_bottomVec = axis;
+ void setAxisBottom(int dof, const btVector3 &axis)
+ {
+ m_axes[dof].m_bottomVec = axis;
}
- void setAxisTop(int dof, const btScalar &x, const btScalar &y, const btScalar &z)
+ void setAxisTop(int dof, const btScalar &x, const btScalar &y, const btScalar &z)
{
- m_axes[dof].m_topVec.setValue(x, y, z);
+ m_axes[dof].m_topVec.setValue(x, y, z);
}
- void setAxisBottom(int dof, const btScalar &x, const btScalar &y, const btScalar &z)
- {
- m_axes[dof].m_bottomVec.setValue(x, y, z);
+ void setAxisBottom(int dof, const btScalar &x, const btScalar &y, const btScalar &z)
+ {
+ m_axes[dof].m_bottomVec.setValue(x, y, z);
}
- const btVector3 & getAxisTop(int dof) const { return m_axes[dof].m_topVec; }
- const btVector3 & getAxisBottom(int dof) const { return m_axes[dof].m_bottomVec; }
+ const btVector3 &getAxisTop(int dof) const { return m_axes[dof].m_topVec; }
+ const btVector3 &getAxisBottom(int dof) const { return m_axes[dof].m_bottomVec; }
int m_dofOffset, m_cfgOffset;
- btQuaternion m_cachedRotParentToThis; // rotates vectors in parent frame to vectors in local frame
- btVector3 m_cachedRVector; // vector from COM of parent to COM of this link, in local frame.
+ btQuaternion m_cachedRotParentToThis; // rotates vectors in parent frame to vectors in local frame
+ btVector3 m_cachedRVector; // vector from COM of parent to COM of this link, in local frame.
- btVector3 m_appliedForce; // In WORLD frame
- btVector3 m_appliedTorque; // In WORLD frame
+ btVector3 m_appliedForce; // In WORLD frame
+ btVector3 m_appliedTorque; // In WORLD frame
-btVector3 m_appliedConstraintForce; // In WORLD frame
- btVector3 m_appliedConstraintTorque; // In WORLD frame
+ btVector3 m_appliedConstraintForce; // In WORLD frame
+ btVector3 m_appliedConstraintTorque; // In WORLD frame
btScalar m_jointPos[7];
-
- //m_jointTorque is the joint torque applied by the user using 'addJointTorque'.
- //It gets set to zero after each internal stepSimulation call
+
+ //m_jointTorque is the joint torque applied by the user using 'addJointTorque'.
+ //It gets set to zero after each internal stepSimulation call
btScalar m_jointTorque[6];
-
- class btMultiBodyLinkCollider* m_collider;
+
+ class btMultiBodyLinkCollider *m_collider;
int m_flags;
-
-
- int m_dofCount, m_posVarCount; //redundant but handy
-
+
+ int m_dofCount, m_posVarCount; //redundant but handy
+
eFeatherstoneJointType m_jointType;
-
- struct btMultiBodyJointFeedback* m_jointFeedback;
-
- btTransform m_cachedWorldTransform;//this cache is updated when calling btMultiBody::forwardKinematics
-
- const char* m_linkName;//m_linkName memory needs to be managed by the developer/user!
- const char* m_jointName;//m_jointName memory needs to be managed by the developer/user!
- const void* m_userPtr;//m_userPtr ptr needs to be managed by the developer/user!
-
- btScalar m_jointDamping; //todo: implement this internally. It is unused for now, it is set by a URDF loader. User can apply manual damping.
- btScalar m_jointFriction; //todo: implement this internally. It is unused for now, it is set by a URDF loader. User can apply manual friction using a velocity motor.
- btScalar m_jointLowerLimit; //todo: implement this internally. It is unused for now, it is set by a URDF loader.
- btScalar m_jointUpperLimit; //todo: implement this internally. It is unused for now, it is set by a URDF loader.
- btScalar m_jointMaxForce; //todo: implement this internally. It is unused for now, it is set by a URDF loader.
- btScalar m_jointMaxVelocity;//todo: implement this internally. It is unused for now, it is set by a URDF loader.
-
+
+ struct btMultiBodyJointFeedback *m_jointFeedback;
+
+ btTransform m_cachedWorldTransform; //this cache is updated when calling btMultiBody::forwardKinematics
+
+ const char *m_linkName; //m_linkName memory needs to be managed by the developer/user!
+ const char *m_jointName; //m_jointName memory needs to be managed by the developer/user!
+ const void *m_userPtr; //m_userPtr ptr needs to be managed by the developer/user!
+
+ btScalar m_jointDamping; //todo: implement this internally. It is unused for now, it is set by a URDF loader. User can apply manual damping.
+ btScalar m_jointFriction; //todo: implement this internally. It is unused for now, it is set by a URDF loader. User can apply manual friction using a velocity motor.
+ btScalar m_jointLowerLimit; //todo: implement this internally. It is unused for now, it is set by a URDF loader.
+ btScalar m_jointUpperLimit; //todo: implement this internally. It is unused for now, it is set by a URDF loader.
+ btScalar m_jointMaxForce; //todo: implement this internally. It is unused for now, it is set by a URDF loader.
+ btScalar m_jointMaxVelocity; //todo: implement this internally. It is unused for now, it is set by a URDF loader.
+
// ctor: set some sensible defaults
btMultibodyLink()
- : m_mass(1),
- m_parent(-1),
- m_zeroRotParentToThis(0, 0, 0, 1),
- m_cachedRotParentToThis(0, 0, 0, 1),
- m_collider(0),
- m_flags(0),
- m_dofCount(0),
- m_posVarCount(0),
- m_jointType(btMultibodyLink::eInvalid),
- m_jointFeedback(0),
- m_linkName(0),
- m_jointName(0),
- m_userPtr(0),
- m_jointDamping(0),
- m_jointFriction(0),
- m_jointLowerLimit(0),
- m_jointUpperLimit(0),
- m_jointMaxForce(0),
- m_jointMaxVelocity(0)
+ : m_mass(1),
+ m_parent(-1),
+ m_zeroRotParentToThis(0, 0, 0, 1),
+ m_cachedRotParentToThis(0, 0, 0, 1),
+ m_collider(0),
+ m_flags(0),
+ m_dofCount(0),
+ m_posVarCount(0),
+ m_jointType(btMultibodyLink::eInvalid),
+ m_jointFeedback(0),
+ m_linkName(0),
+ m_jointName(0),
+ m_userPtr(0),
+ m_jointDamping(0),
+ m_jointFriction(0),
+ m_jointLowerLimit(0),
+ m_jointUpperLimit(0),
+ m_jointMaxForce(0),
+ m_jointMaxVelocity(0)
{
-
m_inertiaLocal.setValue(1, 1, 1);
setAxisTop(0, 0., 0., 0.);
setAxisBottom(0, 1., 0., 0.);
m_dVector.setValue(0, 0, 0);
m_eVector.setValue(0, 0, 0);
m_cachedRVector.setValue(0, 0, 0);
- m_appliedForce.setValue( 0, 0, 0);
+ m_appliedForce.setValue(0, 0, 0);
m_appliedTorque.setValue(0, 0, 0);
- m_appliedConstraintForce.setValue(0,0,0);
- m_appliedConstraintTorque.setValue(0,0,0);
- //
+ m_appliedConstraintForce.setValue(0, 0, 0);
+ m_appliedConstraintTorque.setValue(0, 0, 0);
+ //
m_jointPos[0] = m_jointPos[1] = m_jointPos[2] = m_jointPos[4] = m_jointPos[5] = m_jointPos[6] = 0.f;
- m_jointPos[3] = 1.f; //"quat.w"
+ m_jointPos[3] = 1.f; //"quat.w"
m_jointTorque[0] = m_jointTorque[1] = m_jointTorque[2] = m_jointTorque[3] = m_jointTorque[4] = m_jointTorque[5] = 0.f;
m_cachedWorldTransform.setIdentity();
}
- // routine to update m_cachedRotParentToThis and m_cachedRVector
+ // routine to update m_cachedRotParentToThis and m_cachedRVector
void updateCacheMultiDof(btScalar *pq = 0)
{
btScalar *pJointPos = (pq ? pq : &m_jointPos[0]);
- switch(m_jointType)
+ switch (m_jointType)
{
case eRevolute:
{
- m_cachedRotParentToThis = btQuaternion(getAxisTop(0),-pJointPos[0]) * m_zeroRotParentToThis;
- m_cachedRVector = m_dVector + quatRotate(m_cachedRotParentToThis,m_eVector);
+ m_cachedRotParentToThis = btQuaternion(getAxisTop(0), -pJointPos[0]) * m_zeroRotParentToThis;
+ m_cachedRVector = m_dVector + quatRotate(m_cachedRotParentToThis, m_eVector);
break;
}
case ePrismatic:
{
// m_cachedRotParentToThis never changes, so no need to update
- m_cachedRVector = m_dVector + quatRotate(m_cachedRotParentToThis,m_eVector) + pJointPos[0] * getAxisBottom(0);
+ m_cachedRVector = m_dVector + quatRotate(m_cachedRotParentToThis, m_eVector) + pJointPos[0] * getAxisBottom(0);
break;
}
case eSpherical:
{
m_cachedRotParentToThis = btQuaternion(pJointPos[0], pJointPos[1], pJointPos[2], -pJointPos[3]) * m_zeroRotParentToThis;
- m_cachedRVector = m_dVector + quatRotate(m_cachedRotParentToThis,m_eVector);
+ m_cachedRVector = m_dVector + quatRotate(m_cachedRotParentToThis, m_eVector);
break;
}
case ePlanar:
{
- m_cachedRotParentToThis = btQuaternion(getAxisTop(0),-pJointPos[0]) * m_zeroRotParentToThis;
- m_cachedRVector = quatRotate(btQuaternion(getAxisTop(0),-pJointPos[0]), pJointPos[1] * getAxisBottom(1) + pJointPos[2] * getAxisBottom(2)) + quatRotate(m_cachedRotParentToThis,m_eVector);
+ m_cachedRotParentToThis = btQuaternion(getAxisTop(0), -pJointPos[0]) * m_zeroRotParentToThis;
+ m_cachedRVector = quatRotate(btQuaternion(getAxisTop(0), -pJointPos[0]), pJointPos[1] * getAxisBottom(1) + pJointPos[2] * getAxisBottom(2)) + quatRotate(m_cachedRotParentToThis, m_eVector);
break;
}
case eFixed:
{
m_cachedRotParentToThis = m_zeroRotParentToThis;
- m_cachedRVector = m_dVector + quatRotate(m_cachedRotParentToThis,m_eVector);
+ m_cachedRVector = m_dVector + quatRotate(m_cachedRotParentToThis, m_eVector);
break;
}
@@ -242,5 +236,4 @@ btVector3 m_appliedConstraintForce; // In WORLD frame
}
};
-
-#endif //BT_MULTIBODY_LINK_H
+#endif //BT_MULTIBODY_LINK_H
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyLinkCollider.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyLinkCollider.h
index 7092e62b5a..f91c001f12 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyLinkCollider.h
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyLinkCollider.h
@@ -29,21 +29,18 @@ subject to the following restrictions:
#define btMultiBodyLinkColliderDataName "btMultiBodyLinkColliderFloatData"
#endif
-
class btMultiBodyLinkCollider : public btCollisionObject
{
-//protected:
+ //protected:
public:
-
btMultiBody* m_multiBody;
int m_link;
-
- btMultiBodyLinkCollider (btMultiBody* multiBody,int link)
- :m_multiBody(multiBody),
- m_link(link)
+ btMultiBodyLinkCollider(btMultiBody* multiBody, int link)
+ : m_multiBody(multiBody),
+ m_link(link)
{
- m_checkCollideWith = true;
+ m_checkCollideWith = true;
//we need to remove the 'CF_STATIC_OBJECT' flag, otherwise links/base doesn't merge islands
//this means that some constraints might point to bodies that are not in the islands, causing crashes
//if (link>=0 || (multiBody && !multiBody->hasFixedBase()))
@@ -59,18 +56,18 @@ public:
}
static btMultiBodyLinkCollider* upcast(btCollisionObject* colObj)
{
- if (colObj->getInternalType()&btCollisionObject::CO_FEATHERSTONE_LINK)
+ if (colObj->getInternalType() & btCollisionObject::CO_FEATHERSTONE_LINK)
return (btMultiBodyLinkCollider*)colObj;
return 0;
}
static const btMultiBodyLinkCollider* upcast(const btCollisionObject* colObj)
{
- if (colObj->getInternalType()&btCollisionObject::CO_FEATHERSTONE_LINK)
+ if (colObj->getInternalType() & btCollisionObject::CO_FEATHERSTONE_LINK)
return (btMultiBodyLinkCollider*)colObj;
return 0;
}
- virtual bool checkCollideWithOverride(const btCollisionObject* co) const
+ virtual bool checkCollideWithOverride(const btCollisionObject* co) const
{
const btMultiBodyLinkCollider* other = btMultiBodyLinkCollider::upcast(co);
if (!other)
@@ -81,47 +78,46 @@ public:
return false;
//check if 'link' has collision disabled
- if (m_link>=0)
+ if (m_link >= 0)
{
const btMultibodyLink& link = m_multiBody->getLink(this->m_link);
- if (link.m_flags&BT_MULTIBODYLINKFLAGS_DISABLE_ALL_PARENT_COLLISION)
+ if (link.m_flags & BT_MULTIBODYLINKFLAGS_DISABLE_ALL_PARENT_COLLISION)
{
int parent_of_this = m_link;
while (1)
{
- if (parent_of_this==-1)
+ if (parent_of_this == -1)
break;
parent_of_this = m_multiBody->getLink(parent_of_this).m_parent;
- if (parent_of_this==other->m_link)
+ if (parent_of_this == other->m_link)
{
return false;
}
}
}
- else if (link.m_flags&BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION)
+ else if (link.m_flags & BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION)
{
- if ( link.m_parent == other->m_link)
+ if (link.m_parent == other->m_link)
return false;
}
-
}
- if (other->m_link>=0)
+ if (other->m_link >= 0)
{
const btMultibodyLink& otherLink = other->m_multiBody->getLink(other->m_link);
- if (otherLink.m_flags& BT_MULTIBODYLINKFLAGS_DISABLE_ALL_PARENT_COLLISION)
+ if (otherLink.m_flags & BT_MULTIBODYLINKFLAGS_DISABLE_ALL_PARENT_COLLISION)
{
int parent_of_other = other->m_link;
while (1)
{
- if (parent_of_other==-1)
+ if (parent_of_other == -1)
break;
parent_of_other = m_multiBody->getLink(parent_of_other).m_parent;
- if (parent_of_other==this->m_link)
+ if (parent_of_other == this->m_link)
return false;
}
}
- else if (otherLink.m_flags& BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION)
+ else if (otherLink.m_flags & BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION)
{
if (otherLink.m_parent == this->m_link)
return false;
@@ -130,13 +126,13 @@ public:
return true;
}
- virtual int calculateSerializeBufferSize() const;
+ virtual int calculateSerializeBufferSize() const;
///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const;
-
+ virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const;
};
+// clang-format off
struct btMultiBodyLinkColliderFloatData
{
@@ -154,16 +150,18 @@ struct btMultiBodyLinkColliderDoubleData
char m_padding[4];
};
-SIMD_FORCE_INLINE int btMultiBodyLinkCollider::calculateSerializeBufferSize() const
+// clang-format on
+
+SIMD_FORCE_INLINE int btMultiBodyLinkCollider::calculateSerializeBufferSize() const
{
return sizeof(btMultiBodyLinkColliderData);
}
-SIMD_FORCE_INLINE const char* btMultiBodyLinkCollider::serialize(void* dataBuffer, class btSerializer* serializer) const
+SIMD_FORCE_INLINE const char* btMultiBodyLinkCollider::serialize(void* dataBuffer, class btSerializer* serializer) const
{
btMultiBodyLinkColliderData* dataOut = (btMultiBodyLinkColliderData*)dataBuffer;
- btCollisionObject::serialize(&dataOut->m_colObjData,serializer);
-
+ btCollisionObject::serialize(&dataOut->m_colObjData, serializer);
+
dataOut->m_link = this->m_link;
dataOut->m_multiBody = (btMultiBodyData*)serializer->getUniquePointer(m_multiBody);
@@ -173,5 +171,4 @@ SIMD_FORCE_INLINE const char* btMultiBodyLinkCollider::serialize(void* dataBuffe
return btMultiBodyLinkColliderDataName;
}
-#endif //BT_FEATHERSTONE_LINK_COLLIDER_H
-
+#endif //BT_FEATHERSTONE_LINK_COLLIDER_H
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp
index 2b59f0b7a6..37d3aede37 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp
@@ -21,29 +21,29 @@ subject to the following restrictions:
#include "LinearMath/btIDebugDraw.h"
#ifndef BTMBP2PCONSTRAINT_BLOCK_ANGULAR_MOTION_TEST
- #define BTMBP2PCONSTRAINT_DIM 3
+#define BTMBP2PCONSTRAINT_DIM 3
#else
- #define BTMBP2PCONSTRAINT_DIM 6
+#define BTMBP2PCONSTRAINT_DIM 6
#endif
btMultiBodyPoint2Point::btMultiBodyPoint2Point(btMultiBody* body, int link, btRigidBody* bodyB, const btVector3& pivotInA, const btVector3& pivotInB)
- :btMultiBodyConstraint(body,0,link,-1,BTMBP2PCONSTRAINT_DIM,false),
- m_rigidBodyA(0),
- m_rigidBodyB(bodyB),
- m_pivotInA(pivotInA),
- m_pivotInB(pivotInB)
+ : btMultiBodyConstraint(body, 0, link, -1, BTMBP2PCONSTRAINT_DIM, false),
+ m_rigidBodyA(0),
+ m_rigidBodyB(bodyB),
+ m_pivotInA(pivotInA),
+ m_pivotInB(pivotInB)
{
- m_data.resize(BTMBP2PCONSTRAINT_DIM);//at least store the applied impulses
+ m_data.resize(BTMBP2PCONSTRAINT_DIM); //at least store the applied impulses
}
btMultiBodyPoint2Point::btMultiBodyPoint2Point(btMultiBody* bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB)
- :btMultiBodyConstraint(bodyA,bodyB,linkA,linkB,BTMBP2PCONSTRAINT_DIM,false),
- m_rigidBodyA(0),
- m_rigidBodyB(0),
- m_pivotInA(pivotInA),
- m_pivotInB(pivotInB)
+ : btMultiBodyConstraint(bodyA, bodyB, linkA, linkB, BTMBP2PCONSTRAINT_DIM, false),
+ m_rigidBodyA(0),
+ m_rigidBodyB(0),
+ m_pivotInA(pivotInA),
+ m_pivotInB(pivotInB)
{
- m_data.resize(BTMBP2PCONSTRAINT_DIM);//at least store the applied impulses
+ m_data.resize(BTMBP2PCONSTRAINT_DIM); //at least store the applied impulses
}
void btMultiBodyPoint2Point::finalizeMultiDof()
@@ -56,7 +56,6 @@ btMultiBodyPoint2Point::~btMultiBodyPoint2Point()
{
}
-
int btMultiBodyPoint2Point::getIslandIdA() const
{
if (m_rigidBodyA)
@@ -73,7 +72,7 @@ int btMultiBodyPoint2Point::getIslandIdA() const
else
{
if (m_bodyA->getLink(m_linkA).m_collider)
- return m_bodyA->getLink(m_linkA).m_collider->getIslandTag();
+ return m_bodyA->getLink(m_linkA).m_collider->getIslandTag();
}
}
return -1;
@@ -100,48 +99,43 @@ int btMultiBodyPoint2Point::getIslandIdB() const
return -1;
}
-
-
void btMultiBodyPoint2Point::createConstraintRows(btMultiBodyConstraintArray& constraintRows,
- btMultiBodyJacobianData& data,
- const btContactSolverInfo& infoGlobal)
+ btMultiBodyJacobianData& data,
+ const btContactSolverInfo& infoGlobal)
{
-
-// int i=1;
-int numDim = BTMBP2PCONSTRAINT_DIM;
- for (int i=0;i<numDim;i++)
+ // int i=1;
+ int numDim = BTMBP2PCONSTRAINT_DIM;
+ for (int i = 0; i < numDim; i++)
{
-
btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();
- //memset(&constraintRow,0xffffffff,sizeof(btMultiBodySolverConstraint));
- constraintRow.m_orgConstraint = this;
- constraintRow.m_orgDofIndex = i;
- constraintRow.m_relpos1CrossNormal.setValue(0,0,0);
- constraintRow.m_contactNormal1.setValue(0,0,0);
- constraintRow.m_relpos2CrossNormal.setValue(0,0,0);
- constraintRow.m_contactNormal2.setValue(0,0,0);
- constraintRow.m_angularComponentA.setValue(0,0,0);
- constraintRow.m_angularComponentB.setValue(0,0,0);
+ //memset(&constraintRow,0xffffffff,sizeof(btMultiBodySolverConstraint));
+ constraintRow.m_orgConstraint = this;
+ constraintRow.m_orgDofIndex = i;
+ constraintRow.m_relpos1CrossNormal.setValue(0, 0, 0);
+ constraintRow.m_contactNormal1.setValue(0, 0, 0);
+ constraintRow.m_relpos2CrossNormal.setValue(0, 0, 0);
+ constraintRow.m_contactNormal2.setValue(0, 0, 0);
+ constraintRow.m_angularComponentA.setValue(0, 0, 0);
+ constraintRow.m_angularComponentB.setValue(0, 0, 0);
constraintRow.m_solverBodyIdA = data.m_fixedBodyId;
constraintRow.m_solverBodyIdB = data.m_fixedBodyId;
- btVector3 contactNormalOnB(0,0,0);
+ btVector3 contactNormalOnB(0, 0, 0);
#ifndef BTMBP2PCONSTRAINT_BLOCK_ANGULAR_MOTION_TEST
contactNormalOnB[i] = -1;
#else
- contactNormalOnB[i%3] = -1;
+ contactNormalOnB[i % 3] = -1;
#endif
-
- // Convert local points back to world
+ // Convert local points back to world
btVector3 pivotAworld = m_pivotInA;
if (m_rigidBodyA)
{
-
constraintRow.m_solverBodyIdA = m_rigidBodyA->getCompanionId();
- pivotAworld = m_rigidBodyA->getCenterOfMassTransform()*m_pivotInA;
- } else
+ pivotAworld = m_rigidBodyA->getCenterOfMassTransform() * m_pivotInA;
+ }
+ else
{
if (m_bodyA)
pivotAworld = m_bodyA->localPosToWorld(m_linkA, m_pivotInA);
@@ -150,44 +144,41 @@ int numDim = BTMBP2PCONSTRAINT_DIM;
if (m_rigidBodyB)
{
constraintRow.m_solverBodyIdB = m_rigidBodyB->getCompanionId();
- pivotBworld = m_rigidBodyB->getCenterOfMassTransform()*m_pivotInB;
- } else
+ pivotBworld = m_rigidBodyB->getCenterOfMassTransform() * m_pivotInB;
+ }
+ else
{
if (m_bodyB)
pivotBworld = m_bodyB->localPosToWorld(m_linkB, m_pivotInB);
-
}
- btScalar posError = i < 3 ? (pivotAworld-pivotBworld).dot(contactNormalOnB) : 0;
+ btScalar posError = i < 3 ? (pivotAworld - pivotBworld).dot(contactNormalOnB) : 0;
#ifndef BTMBP2PCONSTRAINT_BLOCK_ANGULAR_MOTION_TEST
-
- fillMultiBodyConstraint(constraintRow, data, 0, 0, btVector3(0,0,0),
- contactNormalOnB, pivotAworld, pivotBworld, //sucks but let it be this way "for the time being"
- posError,
- infoGlobal,
- -m_maxAppliedImpulse, m_maxAppliedImpulse
- );
- //@todo: support the case of btMultiBody versus btRigidBody,
- //see btPoint2PointConstraint::getInfo2NonVirtual
+ fillMultiBodyConstraint(constraintRow, data, 0, 0, btVector3(0, 0, 0),
+ contactNormalOnB, pivotAworld, pivotBworld, //sucks but let it be this way "for the time being"
+ posError,
+ infoGlobal,
+ -m_maxAppliedImpulse, m_maxAppliedImpulse);
+ //@todo: support the case of btMultiBody versus btRigidBody,
+ //see btPoint2PointConstraint::getInfo2NonVirtual
#else
const btVector3 dummy(0, 0, 0);
btAssert(m_bodyA->isMultiDof());
btScalar* jac1 = jacobianA(i);
- const btVector3 &normalAng = i >= 3 ? contactNormalOnB : dummy;
- const btVector3 &normalLin = i < 3 ? contactNormalOnB : dummy;
+ const btVector3& normalAng = i >= 3 ? contactNormalOnB : dummy;
+ const btVector3& normalLin = i < 3 ? contactNormalOnB : dummy;
m_bodyA->filConstraintJacobianMultiDof(m_linkA, pivotAworld, normalAng, normalLin, jac1, data.scratch_r, data.scratch_v, data.scratch_m);
fillMultiBodyConstraint(constraintRow, data, jac1, 0,
- dummy, dummy, dummy, //sucks but let it be this way "for the time being"
- posError,
- infoGlobal,
- -m_maxAppliedImpulse, m_maxAppliedImpulse
- );
+ dummy, dummy, dummy, //sucks but let it be this way "for the time being"
+ posError,
+ infoGlobal,
+ -m_maxAppliedImpulse, m_maxAppliedImpulse);
#endif
}
}
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyPoint2Point.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyPoint2Point.h
index bf39acc5b9..ef03a557ec 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyPoint2Point.h
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyPoint2Point.h
@@ -22,22 +22,20 @@ subject to the following restrictions:
//#define BTMBP2PCONSTRAINT_BLOCK_ANGULAR_MOTION_TEST
-ATTRIBUTE_ALIGNED16(class) btMultiBodyPoint2Point : public btMultiBodyConstraint
+ATTRIBUTE_ALIGNED16(class)
+btMultiBodyPoint2Point : public btMultiBodyConstraint
{
protected:
-
- btRigidBody* m_rigidBodyA;
- btRigidBody* m_rigidBodyB;
- btVector3 m_pivotInA;
- btVector3 m_pivotInB;
-
+ btRigidBody* m_rigidBodyA;
+ btRigidBody* m_rigidBodyB;
+ btVector3 m_pivotInA;
+ btVector3 m_pivotInB;
public:
-
BT_DECLARE_ALIGNED_ALLOCATOR();
- btMultiBodyPoint2Point(btMultiBody* body, int link, btRigidBody* bodyB, const btVector3& pivotInA, const btVector3& pivotInB);
- btMultiBodyPoint2Point(btMultiBody* bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB);
+ btMultiBodyPoint2Point(btMultiBody * body, int link, btRigidBody* bodyB, const btVector3& pivotInA, const btVector3& pivotInB);
+ btMultiBodyPoint2Point(btMultiBody * bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB);
virtual ~btMultiBodyPoint2Point();
@@ -46,9 +44,9 @@ public:
virtual int getIslandIdA() const;
virtual int getIslandIdB() const;
- virtual void createConstraintRows(btMultiBodyConstraintArray& constraintRows,
- btMultiBodyJacobianData& data,
- const btContactSolverInfo& infoGlobal);
+ virtual void createConstraintRows(btMultiBodyConstraintArray & constraintRows,
+ btMultiBodyJacobianData & data,
+ const btContactSolverInfo& infoGlobal);
const btVector3& getPivotInB() const
{
@@ -60,9 +58,7 @@ public:
m_pivotInB = pivotInB;
}
-
- virtual void debugDraw(class btIDebugDraw* drawer);
-
+ virtual void debugDraw(class btIDebugDraw * drawer);
};
-#endif //BT_MULTIBODY_POINT2POINT_H
+#endif //BT_MULTIBODY_POINT2POINT_H
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySliderConstraint.cpp b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySliderConstraint.cpp
index 43f26f9833..e025302ce6 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySliderConstraint.cpp
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySliderConstraint.cpp
@@ -25,29 +25,29 @@ subject to the following restrictions:
#define EPSILON 0.000001
btMultiBodySliderConstraint::btMultiBodySliderConstraint(btMultiBody* body, int link, btRigidBody* bodyB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB, const btVector3& jointAxis)
- :btMultiBodyConstraint(body,0,link,-1,BTMBSLIDERCONSTRAINT_DIM,false),
- m_rigidBodyA(0),
- m_rigidBodyB(bodyB),
- m_pivotInA(pivotInA),
- m_pivotInB(pivotInB),
- m_frameInA(frameInA),
- m_frameInB(frameInB),
- m_jointAxis(jointAxis)
+ : btMultiBodyConstraint(body, 0, link, -1, BTMBSLIDERCONSTRAINT_DIM, false),
+ m_rigidBodyA(0),
+ m_rigidBodyB(bodyB),
+ m_pivotInA(pivotInA),
+ m_pivotInB(pivotInB),
+ m_frameInA(frameInA),
+ m_frameInB(frameInB),
+ m_jointAxis(jointAxis)
{
- m_data.resize(BTMBSLIDERCONSTRAINT_DIM);//at least store the applied impulses
+ m_data.resize(BTMBSLIDERCONSTRAINT_DIM); //at least store the applied impulses
}
btMultiBodySliderConstraint::btMultiBodySliderConstraint(btMultiBody* bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB, const btVector3& jointAxis)
- :btMultiBodyConstraint(bodyA,bodyB,linkA,linkB,BTMBSLIDERCONSTRAINT_DIM,false),
- m_rigidBodyA(0),
- m_rigidBodyB(0),
- m_pivotInA(pivotInA),
- m_pivotInB(pivotInB),
- m_frameInA(frameInA),
- m_frameInB(frameInB),
- m_jointAxis(jointAxis)
+ : btMultiBodyConstraint(bodyA, bodyB, linkA, linkB, BTMBSLIDERCONSTRAINT_DIM, false),
+ m_rigidBodyA(0),
+ m_rigidBodyB(0),
+ m_pivotInA(pivotInA),
+ m_pivotInB(pivotInB),
+ m_frameInA(frameInA),
+ m_frameInB(frameInB),
+ m_jointAxis(jointAxis)
{
- m_data.resize(BTMBSLIDERCONSTRAINT_DIM);//at least store the applied impulses
+ m_data.resize(BTMBSLIDERCONSTRAINT_DIM); //at least store the applied impulses
}
void btMultiBodySliderConstraint::finalizeMultiDof()
@@ -60,7 +60,6 @@ btMultiBodySliderConstraint::~btMultiBodySliderConstraint()
{
}
-
int btMultiBodySliderConstraint::getIslandIdA() const
{
if (m_rigidBodyA)
@@ -105,98 +104,100 @@ int btMultiBodySliderConstraint::getIslandIdB() const
}
void btMultiBodySliderConstraint::createConstraintRows(btMultiBodyConstraintArray& constraintRows, btMultiBodyJacobianData& data, const btContactSolverInfo& infoGlobal)
{
- // Convert local points back to world
- btVector3 pivotAworld = m_pivotInA;
- btMatrix3x3 frameAworld = m_frameInA;
- btVector3 jointAxis = m_jointAxis;
- if (m_rigidBodyA)
- {
- pivotAworld = m_rigidBodyA->getCenterOfMassTransform()*m_pivotInA;
- frameAworld = m_frameInA.transpose()*btMatrix3x3(m_rigidBodyA->getOrientation());
- jointAxis = quatRotate(m_rigidBodyA->getOrientation(),m_jointAxis);
-
- } else if (m_bodyA) {
- pivotAworld = m_bodyA->localPosToWorld(m_linkA, m_pivotInA);
- frameAworld = m_bodyA->localFrameToWorld(m_linkA, m_frameInA);
- jointAxis = m_bodyA->localDirToWorld(m_linkA, m_jointAxis);
- }
- btVector3 pivotBworld = m_pivotInB;
- btMatrix3x3 frameBworld = m_frameInB;
- if (m_rigidBodyB)
- {
- pivotBworld = m_rigidBodyB->getCenterOfMassTransform()*m_pivotInB;
- frameBworld = m_frameInB.transpose()*btMatrix3x3(m_rigidBodyB->getOrientation());
-
- } else if (m_bodyB) {
- pivotBworld = m_bodyB->localPosToWorld(m_linkB, m_pivotInB);
- frameBworld = m_bodyB->localFrameToWorld(m_linkB, m_frameInB);
- }
-
- btVector3 constraintAxis[2];
- for (int i = 0; i < 3; ++i)
- {
- constraintAxis[0] = frameAworld.getColumn(i).cross(jointAxis);
- if (constraintAxis[0].safeNorm() > EPSILON)
- {
- constraintAxis[0] = constraintAxis[0].normalized();
- constraintAxis[1] = jointAxis.cross(constraintAxis[0]);
- constraintAxis[1] = constraintAxis[1].normalized();
- break;
- }
- }
-
- btMatrix3x3 relRot = frameAworld.inverse()*frameBworld;
- btVector3 angleDiff;
- btGeneric6DofSpring2Constraint::matrixToEulerXYZ(relRot,angleDiff);
-
- int numDim = BTMBSLIDERCONSTRAINT_DIM;
- for (int i=0;i<numDim;i++)
+ // Convert local points back to world
+ btVector3 pivotAworld = m_pivotInA;
+ btMatrix3x3 frameAworld = m_frameInA;
+ btVector3 jointAxis = m_jointAxis;
+ if (m_rigidBodyA)
+ {
+ pivotAworld = m_rigidBodyA->getCenterOfMassTransform() * m_pivotInA;
+ frameAworld = m_frameInA.transpose() * btMatrix3x3(m_rigidBodyA->getOrientation());
+ jointAxis = quatRotate(m_rigidBodyA->getOrientation(), m_jointAxis);
+ }
+ else if (m_bodyA)
{
- btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();
- constraintRow.m_orgConstraint = this;
- constraintRow.m_orgDofIndex = i;
- constraintRow.m_relpos1CrossNormal.setValue(0,0,0);
- constraintRow.m_contactNormal1.setValue(0,0,0);
- constraintRow.m_relpos2CrossNormal.setValue(0,0,0);
- constraintRow.m_contactNormal2.setValue(0,0,0);
- constraintRow.m_angularComponentA.setValue(0,0,0);
- constraintRow.m_angularComponentB.setValue(0,0,0);
-
- constraintRow.m_solverBodyIdA = data.m_fixedBodyId;
- constraintRow.m_solverBodyIdB = data.m_fixedBodyId;
-
- if (m_rigidBodyA)
- {
- constraintRow.m_solverBodyIdA = m_rigidBodyA->getCompanionId();
- }
- if (m_rigidBodyB)
- {
- constraintRow.m_solverBodyIdB = m_rigidBodyB->getCompanionId();
- }
-
- btVector3 constraintNormalLin(0,0,0);
- btVector3 constraintNormalAng(0,0,0);
- btScalar posError = 0.0;
- if (i < 2) {
- constraintNormalLin = constraintAxis[i];
- posError = (pivotAworld-pivotBworld).dot(constraintNormalLin);
- fillMultiBodyConstraint(constraintRow, data, 0, 0, constraintNormalAng,
- constraintNormalLin, pivotAworld, pivotBworld,
- posError,
- infoGlobal,
- -m_maxAppliedImpulse, m_maxAppliedImpulse
- );
- }
- else { //i>=2
- constraintNormalAng = frameAworld.getColumn(i%3);
- posError = angleDiff[i%3];
- fillMultiBodyConstraint(constraintRow, data, 0, 0, constraintNormalAng,
- constraintNormalLin, pivotAworld, pivotBworld,
- posError,
- infoGlobal,
- -m_maxAppliedImpulse, m_maxAppliedImpulse, true
- );
- }
+ pivotAworld = m_bodyA->localPosToWorld(m_linkA, m_pivotInA);
+ frameAworld = m_bodyA->localFrameToWorld(m_linkA, m_frameInA);
+ jointAxis = m_bodyA->localDirToWorld(m_linkA, m_jointAxis);
+ }
+ btVector3 pivotBworld = m_pivotInB;
+ btMatrix3x3 frameBworld = m_frameInB;
+ if (m_rigidBodyB)
+ {
+ pivotBworld = m_rigidBodyB->getCenterOfMassTransform() * m_pivotInB;
+ frameBworld = m_frameInB.transpose() * btMatrix3x3(m_rigidBodyB->getOrientation());
+ }
+ else if (m_bodyB)
+ {
+ pivotBworld = m_bodyB->localPosToWorld(m_linkB, m_pivotInB);
+ frameBworld = m_bodyB->localFrameToWorld(m_linkB, m_frameInB);
+ }
+
+ btVector3 constraintAxis[2];
+ for (int i = 0; i < 3; ++i)
+ {
+ constraintAxis[0] = frameAworld.getColumn(i).cross(jointAxis);
+ if (constraintAxis[0].safeNorm() > EPSILON)
+ {
+ constraintAxis[0] = constraintAxis[0].normalized();
+ constraintAxis[1] = jointAxis.cross(constraintAxis[0]);
+ constraintAxis[1] = constraintAxis[1].normalized();
+ break;
+ }
+ }
+
+ btMatrix3x3 relRot = frameAworld.inverse() * frameBworld;
+ btVector3 angleDiff;
+ btGeneric6DofSpring2Constraint::matrixToEulerXYZ(relRot, angleDiff);
+
+ int numDim = BTMBSLIDERCONSTRAINT_DIM;
+ for (int i = 0; i < numDim; i++)
+ {
+ btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();
+ constraintRow.m_orgConstraint = this;
+ constraintRow.m_orgDofIndex = i;
+ constraintRow.m_relpos1CrossNormal.setValue(0, 0, 0);
+ constraintRow.m_contactNormal1.setValue(0, 0, 0);
+ constraintRow.m_relpos2CrossNormal.setValue(0, 0, 0);
+ constraintRow.m_contactNormal2.setValue(0, 0, 0);
+ constraintRow.m_angularComponentA.setValue(0, 0, 0);
+ constraintRow.m_angularComponentB.setValue(0, 0, 0);
+
+ constraintRow.m_solverBodyIdA = data.m_fixedBodyId;
+ constraintRow.m_solverBodyIdB = data.m_fixedBodyId;
+
+ if (m_rigidBodyA)
+ {
+ constraintRow.m_solverBodyIdA = m_rigidBodyA->getCompanionId();
+ }
+ if (m_rigidBodyB)
+ {
+ constraintRow.m_solverBodyIdB = m_rigidBodyB->getCompanionId();
+ }
+
+ btVector3 constraintNormalLin(0, 0, 0);
+ btVector3 constraintNormalAng(0, 0, 0);
+ btScalar posError = 0.0;
+ if (i < 2)
+ {
+ constraintNormalLin = constraintAxis[i];
+ posError = (pivotAworld - pivotBworld).dot(constraintNormalLin);
+ fillMultiBodyConstraint(constraintRow, data, 0, 0, constraintNormalAng,
+ constraintNormalLin, pivotAworld, pivotBworld,
+ posError,
+ infoGlobal,
+ -m_maxAppliedImpulse, m_maxAppliedImpulse);
+ }
+ else
+ { //i>=2
+ constraintNormalAng = frameAworld.getColumn(i % 3);
+ posError = angleDiff[i % 3];
+ fillMultiBodyConstraint(constraintRow, data, 0, 0, constraintNormalAng,
+ constraintNormalLin, pivotAworld, pivotBworld,
+ posError,
+ infoGlobal,
+ -m_maxAppliedImpulse, m_maxAppliedImpulse, true);
+ }
}
}
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySliderConstraint.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySliderConstraint.h
index 0a6cf3df12..b192b6f8f3 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySliderConstraint.h
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySliderConstraint.h
@@ -23,17 +23,15 @@ subject to the following restrictions:
class btMultiBodySliderConstraint : public btMultiBodyConstraint
{
protected:
-
- btRigidBody* m_rigidBodyA;
- btRigidBody* m_rigidBodyB;
- btVector3 m_pivotInA;
- btVector3 m_pivotInB;
- btMatrix3x3 m_frameInA;
- btMatrix3x3 m_frameInB;
- btVector3 m_jointAxis;
+ btRigidBody* m_rigidBodyA;
+ btRigidBody* m_rigidBodyB;
+ btVector3 m_pivotInA;
+ btVector3 m_pivotInB;
+ btMatrix3x3 m_frameInA;
+ btMatrix3x3 m_frameInB;
+ btVector3 m_jointAxis;
public:
-
btMultiBodySliderConstraint(btMultiBody* body, int link, btRigidBody* bodyB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB, const btVector3& jointAxis);
btMultiBodySliderConstraint(btMultiBody* bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB, const btVector3& jointAxis);
@@ -45,18 +43,18 @@ public:
virtual int getIslandIdB() const;
virtual void createConstraintRows(btMultiBodyConstraintArray& constraintRows,
- btMultiBodyJacobianData& data,
- const btContactSolverInfo& infoGlobal);
-
- const btVector3& getPivotInA() const
- {
- return m_pivotInA;
- }
-
- void setPivotInA(const btVector3& pivotInA)
- {
- m_pivotInA = pivotInA;
- }
+ btMultiBodyJacobianData& data,
+ const btContactSolverInfo& infoGlobal);
+
+ const btVector3& getPivotInA() const
+ {
+ return m_pivotInA;
+ }
+
+ void setPivotInA(const btVector3& pivotInA)
+ {
+ m_pivotInA = pivotInA;
+ }
const btVector3& getPivotInB() const
{
@@ -67,39 +65,38 @@ public:
{
m_pivotInB = pivotInB;
}
-
- const btMatrix3x3& getFrameInA() const
- {
- return m_frameInA;
- }
-
- void setFrameInA(const btMatrix3x3& frameInA)
- {
- m_frameInA = frameInA;
- }
-
- const btMatrix3x3& getFrameInB() const
- {
- return m_frameInB;
- }
-
- virtual void setFrameInB(const btMatrix3x3& frameInB)
- {
- m_frameInB = frameInB;
- }
-
- const btVector3& getJointAxis() const
- {
- return m_jointAxis;
- }
-
- void setJointAxis(const btVector3& jointAxis)
- {
- m_jointAxis = jointAxis;
- }
- virtual void debugDraw(class btIDebugDraw* drawer);
+ const btMatrix3x3& getFrameInA() const
+ {
+ return m_frameInA;
+ }
+
+ void setFrameInA(const btMatrix3x3& frameInA)
+ {
+ m_frameInA = frameInA;
+ }
+ const btMatrix3x3& getFrameInB() const
+ {
+ return m_frameInB;
+ }
+
+ virtual void setFrameInB(const btMatrix3x3& frameInB)
+ {
+ m_frameInB = frameInB;
+ }
+
+ const btVector3& getJointAxis() const
+ {
+ return m_jointAxis;
+ }
+
+ void setJointAxis(const btVector3& jointAxis)
+ {
+ m_jointAxis = jointAxis;
+ }
+
+ virtual void debugDraw(class btIDebugDraw* drawer);
};
-#endif //BT_MULTIBODY_SLIDER_CONSTRAINT_H
+#endif //BT_MULTIBODY_SLIDER_CONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySolverConstraint.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySolverConstraint.h
index 6fa1550e9e..deed3e2a12 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySolverConstraint.h
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySolverConstraint.h
@@ -25,66 +25,66 @@ class btMultiBodyConstraint;
#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
///1D constraint along a normal axis between bodyA and bodyB. It can be combined to solve contact and friction constraints.
-ATTRIBUTE_ALIGNED16 (struct) btMultiBodySolverConstraint
+ATTRIBUTE_ALIGNED16(struct)
+btMultiBodySolverConstraint
{
BT_DECLARE_ALIGNED_ALLOCATOR();
- btMultiBodySolverConstraint() : m_solverBodyIdA(-1), m_multiBodyA(0), m_linkA(-1), m_solverBodyIdB(-1), m_multiBodyB(0), m_linkB(-1),m_orgConstraint(0), m_orgDofIndex(-1)
- {}
-
- int m_deltaVelAindex;//more generic version of m_relpos1CrossNormal/m_contactNormal1
- int m_jacAindex;
- int m_deltaVelBindex;
- int m_jacBindex;
-
- btVector3 m_relpos1CrossNormal;
- btVector3 m_contactNormal1;
- btVector3 m_relpos2CrossNormal;
- btVector3 m_contactNormal2; //usually m_contactNormal2 == -m_contactNormal1, but not always
-
-
- btVector3 m_angularComponentA;
- btVector3 m_angularComponentB;
-
- mutable btSimdScalar m_appliedPushImpulse;
- mutable btSimdScalar m_appliedImpulse;
-
- btScalar m_friction;
- btScalar m_jacDiagABInv;
- btScalar m_rhs;
- btScalar m_cfm;
-
- btScalar m_lowerLimit;
- btScalar m_upperLimit;
- btScalar m_rhsPenetration;
- union
+ btMultiBodySolverConstraint() : m_solverBodyIdA(-1), m_multiBodyA(0), m_linkA(-1), m_solverBodyIdB(-1), m_multiBodyB(0), m_linkB(-1), m_orgConstraint(0), m_orgDofIndex(-1)
{
- void* m_originalContactPoint;
- btScalar m_unusedPadding4;
+ }
+
+ int m_deltaVelAindex; //more generic version of m_relpos1CrossNormal/m_contactNormal1
+ int m_jacAindex;
+ int m_deltaVelBindex;
+ int m_jacBindex;
+
+ btVector3 m_relpos1CrossNormal;
+ btVector3 m_contactNormal1;
+ btVector3 m_relpos2CrossNormal;
+ btVector3 m_contactNormal2; //usually m_contactNormal2 == -m_contactNormal1, but not always
+
+ btVector3 m_angularComponentA;
+ btVector3 m_angularComponentB;
+
+ mutable btSimdScalar m_appliedPushImpulse;
+ mutable btSimdScalar m_appliedImpulse;
+
+ btScalar m_friction;
+ btScalar m_jacDiagABInv;
+ btScalar m_rhs;
+ btScalar m_cfm;
+
+ btScalar m_lowerLimit;
+ btScalar m_upperLimit;
+ btScalar m_rhsPenetration;
+ union {
+ void* m_originalContactPoint;
+ btScalar m_unusedPadding4;
};
- int m_overrideNumSolverIterations;
- int m_frictionIndex;
+ int m_overrideNumSolverIterations;
+ int m_frictionIndex;
int m_solverBodyIdA;
btMultiBody* m_multiBodyA;
- int m_linkA;
-
+ int m_linkA;
+
int m_solverBodyIdB;
btMultiBody* m_multiBodyB;
- int m_linkB;
+ int m_linkB;
//for writing back applied impulses
- btMultiBodyConstraint* m_orgConstraint;
+ btMultiBodyConstraint* m_orgConstraint;
int m_orgDofIndex;
- enum btSolverConstraintType
+ enum btSolverConstraintType
{
BT_SOLVER_CONTACT_1D = 0,
BT_SOLVER_FRICTION_1D
};
};
-typedef btAlignedObjectArray<btMultiBodySolverConstraint> btMultiBodyConstraintArray;
+typedef btAlignedObjectArray<btMultiBodySolverConstraint> btMultiBodyConstraintArray;
-#endif //BT_MULTIBODY_SOLVER_CONSTRAINT_H
+#endif //BT_MULTIBODY_SOLVER_CONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySphericalJointMotor.cpp b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySphericalJointMotor.cpp
new file mode 100644
index 0000000000..3e5aa30f28
--- /dev/null
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySphericalJointMotor.cpp
@@ -0,0 +1,172 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2018 Erwin Coumans http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+///This file was written by Erwin Coumans
+
+#include "btMultiBodySphericalJointMotor.h"
+#include "btMultiBody.h"
+#include "btMultiBodyLinkCollider.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "LinearMath/btTransformUtil.h"
+#include "BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h"
+
+btMultiBodySphericalJointMotor::btMultiBodySphericalJointMotor(btMultiBody* body, int link, btScalar maxMotorImpulse)
+ : btMultiBodyConstraint(body, body, link, body->getLink(link).m_parent, 3, true),
+ m_desiredVelocity(0, 0, 0),
+ m_desiredPosition(0,0,0,1),
+ m_kd(1.),
+ m_kp(0.2),
+ m_erp(1),
+ m_rhsClamp(SIMD_INFINITY)
+{
+
+ m_maxAppliedImpulse = maxMotorImpulse;
+}
+
+
+void btMultiBodySphericalJointMotor::finalizeMultiDof()
+{
+ allocateJacobiansMultiDof();
+ // note: we rely on the fact that data.m_jacobians are
+ // always initialized to zero by the Constraint ctor
+ int linkDoF = 0;
+ unsigned int offset = 6 + (m_bodyA->getLink(m_linkA).m_dofOffset + linkDoF);
+
+ // row 0: the lower bound
+ // row 0: the lower bound
+ jacobianA(0)[offset] = 1;
+
+ m_numDofsFinalized = m_jacSizeBoth;
+}
+
+
+btMultiBodySphericalJointMotor::~btMultiBodySphericalJointMotor()
+{
+}
+
+int btMultiBodySphericalJointMotor::getIslandIdA() const
+{
+ if (this->m_linkA < 0)
+ {
+ btMultiBodyLinkCollider* col = m_bodyA->getBaseCollider();
+ if (col)
+ return col->getIslandTag();
+ }
+ else
+ {
+ if (m_bodyA->getLink(m_linkA).m_collider)
+ {
+ return m_bodyA->getLink(m_linkA).m_collider->getIslandTag();
+ }
+ }
+ return -1;
+}
+
+int btMultiBodySphericalJointMotor::getIslandIdB() const
+{
+ if (m_linkB < 0)
+ {
+ btMultiBodyLinkCollider* col = m_bodyB->getBaseCollider();
+ if (col)
+ return col->getIslandTag();
+ }
+ else
+ {
+ if (m_bodyB->getLink(m_linkB).m_collider)
+ {
+ return m_bodyB->getLink(m_linkB).m_collider->getIslandTag();
+ }
+ }
+ return -1;
+}
+
+void btMultiBodySphericalJointMotor::createConstraintRows(btMultiBodyConstraintArray& constraintRows,
+ btMultiBodyJacobianData& data,
+ const btContactSolverInfo& infoGlobal)
+{
+ // only positions need to be updated -- data.m_jacobians and force
+ // directions were set in the ctor and never change.
+
+ if (m_numDofsFinalized != m_jacSizeBoth)
+ {
+ finalizeMultiDof();
+ }
+
+ //don't crash
+ if (m_numDofsFinalized != m_jacSizeBoth)
+ return;
+
+
+ if (m_maxAppliedImpulse == 0.f)
+ return;
+
+ const btScalar posError = 0;
+ const btVector3 dummy(0, 0, 0);
+
+
+ btVector3 axis[3] = { btVector3(1, 0, 0), btVector3(0, 1, 0), btVector3(0, 0, 1) };
+
+ btQuaternion desiredQuat = m_desiredPosition;
+ btQuaternion currentQuat(m_bodyA->getJointPosMultiDof(m_linkA)[0],
+ m_bodyA->getJointPosMultiDof(m_linkA)[1],
+ m_bodyA->getJointPosMultiDof(m_linkA)[2],
+ m_bodyA->getJointPosMultiDof(m_linkA)[3]);
+
+btQuaternion relRot = currentQuat.inverse() * desiredQuat;
+ btVector3 angleDiff;
+ btGeneric6DofSpring2Constraint::matrixToEulerXYZ(btMatrix3x3(relRot), angleDiff);
+
+
+
+ for (int row = 0; row < getNumRows(); row++)
+ {
+ btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();
+
+ int dof = row;
+
+ btScalar currentVelocity = m_bodyA->getJointVelMultiDof(m_linkA)[dof];
+ btScalar desiredVelocity = this->m_desiredVelocity[row];
+
+ btScalar velocityError = desiredVelocity - currentVelocity;
+
+ btMatrix3x3 frameAworld;
+ frameAworld.setIdentity();
+ frameAworld = m_bodyA->localFrameToWorld(m_linkA, frameAworld);
+ btScalar posError = 0;
+ {
+ btAssert(m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::eSpherical);
+ switch (m_bodyA->getLink(m_linkA).m_jointType)
+ {
+ case btMultibodyLink::eSpherical:
+ {
+ btVector3 constraintNormalAng = frameAworld.getColumn(row % 3);
+ posError = m_kp*angleDiff[row % 3];
+ fillMultiBodyConstraint(constraintRow, data, 0, 0, constraintNormalAng,
+ btVector3(0,0,0), dummy, dummy,
+ posError,
+ infoGlobal,
+ -m_maxAppliedImpulse, m_maxAppliedImpulse, true);
+ constraintRow.m_orgConstraint = this;
+ constraintRow.m_orgDofIndex = row;
+ break;
+ }
+ default:
+ {
+ btAssert(0);
+ }
+ };
+ }
+ }
+}
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySphericalJointMotor.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySphericalJointMotor.h
new file mode 100644
index 0000000000..621beab5a4
--- /dev/null
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySphericalJointMotor.h
@@ -0,0 +1,77 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2018 Erwin Coumans http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+///This file was written by Erwin Coumans
+
+#ifndef BT_MULTIBODY_SPHERICAL_JOINT_MOTOR_H
+#define BT_MULTIBODY_SPHERICAL_JOINT_MOTOR_H
+
+#include "btMultiBodyConstraint.h"
+struct btSolverInfo;
+
+class btMultiBodySphericalJointMotor : public btMultiBodyConstraint
+{
+protected:
+ btVector3 m_desiredVelocity;
+ btQuaternion m_desiredPosition;
+ btScalar m_kd;
+ btScalar m_kp;
+ btScalar m_erp;
+ btScalar m_rhsClamp; //maximum error
+
+public:
+ btMultiBodySphericalJointMotor(btMultiBody* body, int link, btScalar maxMotorImpulse);
+
+ virtual ~btMultiBodySphericalJointMotor();
+ virtual void finalizeMultiDof();
+
+ virtual int getIslandIdA() const;
+ virtual int getIslandIdB() const;
+
+ virtual void createConstraintRows(btMultiBodyConstraintArray& constraintRows,
+ btMultiBodyJacobianData& data,
+ const btContactSolverInfo& infoGlobal);
+
+ virtual void setVelocityTarget(const btVector3& velTarget, btScalar kd = 1.f)
+ {
+ m_desiredVelocity = velTarget;
+ m_kd = kd;
+ }
+
+ virtual void setPositionTarget(const btQuaternion& posTarget, btScalar kp = 1.f)
+ {
+ m_desiredPosition = posTarget;
+ m_kp = kp;
+ }
+
+ virtual void setErp(btScalar erp)
+ {
+ m_erp = erp;
+ }
+ virtual btScalar getErp() const
+ {
+ return m_erp;
+ }
+ virtual void setRhsClamp(btScalar rhsClamp)
+ {
+ m_rhsClamp = rhsClamp;
+ }
+ virtual void debugDraw(class btIDebugDraw* drawer)
+ {
+ //todo(erwincoumans)
+ }
+};
+
+#endif //BT_MULTIBODY_SPHERICAL_JOINT_MOTOR_H
diff --git a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btDantzigLCP.cpp b/thirdparty/bullet/BulletDynamics/MLCPSolvers/btDantzigLCP.cpp
index 986f214870..98ecdc0794 100644
--- a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btDantzigLCP.cpp
+++ b/thirdparty/bullet/BulletDynamics/MLCPSolvers/btDantzigLCP.cpp
@@ -108,18 +108,16 @@ rows/columns and manipulate C.
*/
-
#include "btDantzigLCP.h"
-#include <string.h>//memcpy
+#include <string.h> //memcpy
bool s_error = false;
//***************************************************************************
// code generation parameters
-
-#define btLCP_FAST // use fast btLCP object
+#define btLCP_FAST // use fast btLCP object
// option 1 : matrix row pointers (less data copying)
#define BTROWPTRS
@@ -133,8 +131,6 @@ bool s_error = false;
#define BTNUB_OPTIMIZATIONS
-
-
/* 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.
@@ -145,66 +141,69 @@ bool s_error = false;
* if this is in the factorizer source file, n must be a multiple of 2.
*/
-static void btSolveL1_1 (const btScalar *L, btScalar *B, int n, int lskip1)
-{
- /* declare variables - Z matrix, p and q vectors, etc */
- btScalar Z11,m11,Z21,m21,p1,q1,p2,*ex;
- const btScalar *ell;
- int i,j;
- /* compute all 2 x 1 blocks of X */
- for (i=0; i < n; i+=2) {
- /* compute all 2 x 1 block of X, from rows i..i+2-1 */
- /* set the Z matrix to 0 */
- Z11=0;
- Z21=0;
- ell = L + i*lskip1;
- ex = B;
- /* the inner loop that computes outer products and adds them to Z */
- for (j=i-2; j >= 0; j -= 2) {
- /* compute outer product and add it to the Z matrix */
- p1=ell[0];
- q1=ex[0];
- m11 = p1 * q1;
- p2=ell[lskip1];
- m21 = p2 * q1;
- Z11 += m11;
- Z21 += m21;
- /* compute outer product and add it to the Z matrix */
- p1=ell[1];
- q1=ex[1];
- m11 = p1 * q1;
- p2=ell[1+lskip1];
- m21 = p2 * q1;
- /* advance pointers */
- ell += 2;
- ex += 2;
- Z11 += m11;
- Z21 += m21;
- /* end of inner loop */
- }
- /* compute left-over iterations */
- j += 2;
- for (; j > 0; j--) {
- /* compute outer product and add it to the Z matrix */
- p1=ell[0];
- q1=ex[0];
- m11 = p1 * q1;
- p2=ell[lskip1];
- m21 = p2 * q1;
- /* advance pointers */
- ell += 1;
- ex += 1;
- Z11 += m11;
- Z21 += m21;
- }
- /* finish computing the X(i) block */
- Z11 = ex[0] - Z11;
- ex[0] = Z11;
- p1 = ell[lskip1];
- Z21 = ex[1] - Z21 - p1*Z11;
- ex[1] = Z21;
- /* end of outer loop */
- }
+static void btSolveL1_1(const btScalar *L, btScalar *B, int n, int lskip1)
+{
+ /* declare variables - Z matrix, p and q vectors, etc */
+ btScalar Z11, m11, Z21, m21, p1, q1, p2, *ex;
+ const btScalar *ell;
+ int i, j;
+ /* compute all 2 x 1 blocks of X */
+ for (i = 0; i < n; i += 2)
+ {
+ /* compute all 2 x 1 block of X, from rows i..i+2-1 */
+ /* set the Z matrix to 0 */
+ Z11 = 0;
+ Z21 = 0;
+ ell = L + i * lskip1;
+ ex = B;
+ /* the inner loop that computes outer products and adds them to Z */
+ for (j = i - 2; j >= 0; j -= 2)
+ {
+ /* compute outer product and add it to the Z matrix */
+ p1 = ell[0];
+ q1 = ex[0];
+ m11 = p1 * q1;
+ p2 = ell[lskip1];
+ m21 = p2 * q1;
+ Z11 += m11;
+ Z21 += m21;
+ /* compute outer product and add it to the Z matrix */
+ p1 = ell[1];
+ q1 = ex[1];
+ m11 = p1 * q1;
+ p2 = ell[1 + lskip1];
+ m21 = p2 * q1;
+ /* advance pointers */
+ ell += 2;
+ ex += 2;
+ Z11 += m11;
+ Z21 += m21;
+ /* end of inner loop */
+ }
+ /* compute left-over iterations */
+ j += 2;
+ for (; j > 0; j--)
+ {
+ /* compute outer product and add it to the Z matrix */
+ p1 = ell[0];
+ q1 = ex[0];
+ m11 = p1 * q1;
+ p2 = ell[lskip1];
+ m21 = p2 * q1;
+ /* advance pointers */
+ ell += 1;
+ ex += 1;
+ Z11 += m11;
+ Z21 += m21;
+ }
+ /* finish computing the X(i) block */
+ Z11 = ex[0] - Z11;
+ ex[0] = Z11;
+ p1 = ell[lskip1];
+ Z21 = ex[1] - Z21 - p1 * Z11;
+ ex[1] = Z21;
+ /* end of outer loop */
+ }
}
/* solve L*X=B, with B containing 2 right hand sides.
@@ -217,300 +216,308 @@ static void btSolveL1_1 (const btScalar *L, btScalar *B, int n, int lskip1)
* if this is in the factorizer source file, n must be a multiple of 2.
*/
-static void btSolveL1_2 (const btScalar *L, btScalar *B, int n, int lskip1)
-{
- /* declare variables - Z matrix, p and q vectors, etc */
- btScalar Z11,m11,Z12,m12,Z21,m21,Z22,m22,p1,q1,p2,q2,*ex;
- const btScalar *ell;
- int i,j;
- /* compute all 2 x 2 blocks of X */
- for (i=0; i < n; i+=2) {
- /* compute all 2 x 2 block of X, from rows i..i+2-1 */
- /* set the Z matrix to 0 */
- Z11=0;
- Z12=0;
- Z21=0;
- Z22=0;
- ell = L + i*lskip1;
- ex = B;
- /* the inner loop that computes outer products and adds them to Z */
- for (j=i-2; j >= 0; j -= 2) {
- /* compute outer product and add it to the Z matrix */
- p1=ell[0];
- q1=ex[0];
- m11 = p1 * q1;
- q2=ex[lskip1];
- m12 = p1 * q2;
- p2=ell[lskip1];
- m21 = p2 * q1;
- m22 = p2 * q2;
- Z11 += m11;
- Z12 += m12;
- Z21 += m21;
- Z22 += m22;
- /* compute outer product and add it to the Z matrix */
- p1=ell[1];
- q1=ex[1];
- m11 = p1 * q1;
- q2=ex[1+lskip1];
- m12 = p1 * q2;
- p2=ell[1+lskip1];
- m21 = p2 * q1;
- m22 = p2 * q2;
- /* advance pointers */
- ell += 2;
- ex += 2;
- Z11 += m11;
- Z12 += m12;
- Z21 += m21;
- Z22 += m22;
- /* end of inner loop */
- }
- /* compute left-over iterations */
- j += 2;
- for (; j > 0; j--) {
- /* compute outer product and add it to the Z matrix */
- p1=ell[0];
- q1=ex[0];
- m11 = p1 * q1;
- q2=ex[lskip1];
- m12 = p1 * q2;
- p2=ell[lskip1];
- m21 = p2 * q1;
- m22 = p2 * q2;
- /* advance pointers */
- ell += 1;
- ex += 1;
- Z11 += m11;
- Z12 += m12;
- Z21 += m21;
- Z22 += m22;
- }
- /* finish computing the X(i) block */
- Z11 = ex[0] - Z11;
- ex[0] = Z11;
- Z12 = ex[lskip1] - Z12;
- ex[lskip1] = Z12;
- p1 = ell[lskip1];
- Z21 = ex[1] - Z21 - p1*Z11;
- ex[1] = Z21;
- Z22 = ex[1+lskip1] - Z22 - p1*Z12;
- ex[1+lskip1] = Z22;
- /* end of outer loop */
- }
+static void btSolveL1_2(const btScalar *L, btScalar *B, int n, int lskip1)
+{
+ /* declare variables - Z matrix, p and q vectors, etc */
+ btScalar Z11, m11, Z12, m12, Z21, m21, Z22, m22, p1, q1, p2, q2, *ex;
+ const btScalar *ell;
+ int i, j;
+ /* compute all 2 x 2 blocks of X */
+ for (i = 0; i < n; i += 2)
+ {
+ /* compute all 2 x 2 block of X, from rows i..i+2-1 */
+ /* set the Z matrix to 0 */
+ Z11 = 0;
+ Z12 = 0;
+ Z21 = 0;
+ Z22 = 0;
+ ell = L + i * lskip1;
+ ex = B;
+ /* the inner loop that computes outer products and adds them to Z */
+ for (j = i - 2; j >= 0; j -= 2)
+ {
+ /* compute outer product and add it to the Z matrix */
+ p1 = ell[0];
+ q1 = ex[0];
+ m11 = p1 * q1;
+ q2 = ex[lskip1];
+ m12 = p1 * q2;
+ p2 = ell[lskip1];
+ m21 = p2 * q1;
+ m22 = p2 * q2;
+ Z11 += m11;
+ Z12 += m12;
+ Z21 += m21;
+ Z22 += m22;
+ /* compute outer product and add it to the Z matrix */
+ p1 = ell[1];
+ q1 = ex[1];
+ m11 = p1 * q1;
+ q2 = ex[1 + lskip1];
+ m12 = p1 * q2;
+ p2 = ell[1 + lskip1];
+ m21 = p2 * q1;
+ m22 = p2 * q2;
+ /* advance pointers */
+ ell += 2;
+ ex += 2;
+ Z11 += m11;
+ Z12 += m12;
+ Z21 += m21;
+ Z22 += m22;
+ /* end of inner loop */
+ }
+ /* compute left-over iterations */
+ j += 2;
+ for (; j > 0; j--)
+ {
+ /* compute outer product and add it to the Z matrix */
+ p1 = ell[0];
+ q1 = ex[0];
+ m11 = p1 * q1;
+ q2 = ex[lskip1];
+ m12 = p1 * q2;
+ p2 = ell[lskip1];
+ m21 = p2 * q1;
+ m22 = p2 * q2;
+ /* advance pointers */
+ ell += 1;
+ ex += 1;
+ Z11 += m11;
+ Z12 += m12;
+ Z21 += m21;
+ Z22 += m22;
+ }
+ /* finish computing the X(i) block */
+ Z11 = ex[0] - Z11;
+ ex[0] = Z11;
+ Z12 = ex[lskip1] - Z12;
+ ex[lskip1] = Z12;
+ p1 = ell[lskip1];
+ Z21 = ex[1] - Z21 - p1 * Z11;
+ ex[1] = Z21;
+ Z22 = ex[1 + lskip1] - Z22 - p1 * Z12;
+ ex[1 + lskip1] = Z22;
+ /* end of outer loop */
+ }
}
+void btFactorLDLT(btScalar *A, btScalar *d, int n, int nskip1)
+{
+ int i, j;
+ btScalar sum, *ell, *dee, dd, p1, p2, q1, q2, Z11, m11, Z21, m21, Z22, m22;
+ if (n < 1) return;
-void btFactorLDLT (btScalar *A, btScalar *d, int n, int nskip1)
-{
- int i,j;
- btScalar sum,*ell,*dee,dd,p1,p2,q1,q2,Z11,m11,Z21,m21,Z22,m22;
- if (n < 1) return;
-
- for (i=0; i<=n-2; i += 2) {
- /* solve L*(D*l)=a, l is scaled elements in 2 x i block at A(i,0) */
- btSolveL1_2 (A,A+i*nskip1,i,nskip1);
- /* 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. */
- Z11 = 0;
- Z21 = 0;
- Z22 = 0;
- ell = A+i*nskip1;
- dee = d;
- for (j=i-6; j >= 0; j -= 6) {
- p1 = ell[0];
- p2 = ell[nskip1];
- dd = dee[0];
- q1 = p1*dd;
- q2 = p2*dd;
- ell[0] = q1;
- ell[nskip1] = q2;
- m11 = p1*q1;
- m21 = p2*q1;
- m22 = p2*q2;
- Z11 += m11;
- Z21 += m21;
- Z22 += m22;
- p1 = ell[1];
- p2 = ell[1+nskip1];
- dd = dee[1];
- q1 = p1*dd;
- q2 = p2*dd;
- ell[1] = q1;
- ell[1+nskip1] = q2;
- m11 = p1*q1;
- m21 = p2*q1;
- m22 = p2*q2;
- Z11 += m11;
- Z21 += m21;
- Z22 += m22;
- p1 = ell[2];
- p2 = ell[2+nskip1];
- dd = dee[2];
- q1 = p1*dd;
- q2 = p2*dd;
- ell[2] = q1;
- ell[2+nskip1] = q2;
- m11 = p1*q1;
- m21 = p2*q1;
- m22 = p2*q2;
- Z11 += m11;
- Z21 += m21;
- Z22 += m22;
- p1 = ell[3];
- p2 = ell[3+nskip1];
- dd = dee[3];
- q1 = p1*dd;
- q2 = p2*dd;
- ell[3] = q1;
- ell[3+nskip1] = q2;
- m11 = p1*q1;
- m21 = p2*q1;
- m22 = p2*q2;
- Z11 += m11;
- Z21 += m21;
- Z22 += m22;
- p1 = ell[4];
- p2 = ell[4+nskip1];
- dd = dee[4];
- q1 = p1*dd;
- q2 = p2*dd;
- ell[4] = q1;
- ell[4+nskip1] = q2;
- m11 = p1*q1;
- m21 = p2*q1;
- m22 = p2*q2;
- Z11 += m11;
- Z21 += m21;
- Z22 += m22;
- p1 = ell[5];
- p2 = ell[5+nskip1];
- dd = dee[5];
- q1 = p1*dd;
- q2 = p2*dd;
- ell[5] = q1;
- ell[5+nskip1] = q2;
- m11 = p1*q1;
- m21 = p2*q1;
- m22 = p2*q2;
- Z11 += m11;
- Z21 += m21;
- Z22 += m22;
- ell += 6;
- dee += 6;
- }
- /* compute left-over iterations */
- j += 6;
- for (; j > 0; j--) {
- p1 = ell[0];
- p2 = ell[nskip1];
- dd = dee[0];
- q1 = p1*dd;
- q2 = p2*dd;
- ell[0] = q1;
- ell[nskip1] = q2;
- m11 = p1*q1;
- m21 = p2*q1;
- m22 = p2*q2;
- Z11 += m11;
- Z21 += m21;
- Z22 += m22;
- ell++;
- dee++;
- }
- /* solve for diagonal 2 x 2 block at A(i,i) */
- Z11 = ell[0] - Z11;
- Z21 = ell[nskip1] - Z21;
- Z22 = ell[1+nskip1] - Z22;
- dee = d + i;
- /* factorize 2 x 2 block Z,dee */
- /* factorize row 1 */
- dee[0] = btRecip(Z11);
- /* factorize row 2 */
- sum = 0;
- q1 = Z21;
- q2 = q1 * dee[0];
- Z21 = q2;
- sum += q1*q2;
- dee[1] = btRecip(Z22 - sum);
- /* done factorizing 2 x 2 block */
- ell[nskip1] = Z21;
- }
- /* compute the (less than 2) rows at the bottom */
- switch (n-i) {
- case 0:
- break;
-
- case 1:
- btSolveL1_1 (A,A+i*nskip1,i,nskip1);
- /* 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. */
- Z11 = 0;
- ell = A+i*nskip1;
- dee = d;
- for (j=i-6; j >= 0; j -= 6) {
- p1 = ell[0];
- dd = dee[0];
- q1 = p1*dd;
- ell[0] = q1;
- m11 = p1*q1;
- Z11 += m11;
- p1 = ell[1];
- dd = dee[1];
- q1 = p1*dd;
- ell[1] = q1;
- m11 = p1*q1;
- Z11 += m11;
- p1 = ell[2];
- dd = dee[2];
- q1 = p1*dd;
- ell[2] = q1;
- m11 = p1*q1;
- Z11 += m11;
- p1 = ell[3];
- dd = dee[3];
- q1 = p1*dd;
- ell[3] = q1;
- m11 = p1*q1;
- Z11 += m11;
- p1 = ell[4];
- dd = dee[4];
- q1 = p1*dd;
- ell[4] = q1;
- m11 = p1*q1;
- Z11 += m11;
- p1 = ell[5];
- dd = dee[5];
- q1 = p1*dd;
- ell[5] = q1;
- m11 = p1*q1;
- Z11 += m11;
- ell += 6;
- dee += 6;
- }
- /* compute left-over iterations */
- j += 6;
- for (; j > 0; j--) {
- p1 = ell[0];
- dd = dee[0];
- q1 = p1*dd;
- ell[0] = q1;
- m11 = p1*q1;
- Z11 += m11;
- ell++;
- dee++;
- }
- /* solve for diagonal 1 x 1 block at A(i,i) */
- Z11 = ell[0] - Z11;
- dee = d + i;
- /* factorize 1 x 1 block Z,dee */
- /* factorize row 1 */
- dee[0] = btRecip(Z11);
- /* done factorizing 1 x 1 block */
- break;
-
- //default: *((char*)0)=0; /* this should never happen! */
- }
+ for (i = 0; i <= n - 2; i += 2)
+ {
+ /* solve L*(D*l)=a, l is scaled elements in 2 x i block at A(i,0) */
+ btSolveL1_2(A, A + i * nskip1, i, nskip1);
+ /* 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. */
+ Z11 = 0;
+ Z21 = 0;
+ Z22 = 0;
+ ell = A + i * nskip1;
+ dee = d;
+ for (j = i - 6; j >= 0; j -= 6)
+ {
+ p1 = ell[0];
+ p2 = ell[nskip1];
+ dd = dee[0];
+ q1 = p1 * dd;
+ q2 = p2 * dd;
+ ell[0] = q1;
+ ell[nskip1] = q2;
+ m11 = p1 * q1;
+ m21 = p2 * q1;
+ m22 = p2 * q2;
+ Z11 += m11;
+ Z21 += m21;
+ Z22 += m22;
+ p1 = ell[1];
+ p2 = ell[1 + nskip1];
+ dd = dee[1];
+ q1 = p1 * dd;
+ q2 = p2 * dd;
+ ell[1] = q1;
+ ell[1 + nskip1] = q2;
+ m11 = p1 * q1;
+ m21 = p2 * q1;
+ m22 = p2 * q2;
+ Z11 += m11;
+ Z21 += m21;
+ Z22 += m22;
+ p1 = ell[2];
+ p2 = ell[2 + nskip1];
+ dd = dee[2];
+ q1 = p1 * dd;
+ q2 = p2 * dd;
+ ell[2] = q1;
+ ell[2 + nskip1] = q2;
+ m11 = p1 * q1;
+ m21 = p2 * q1;
+ m22 = p2 * q2;
+ Z11 += m11;
+ Z21 += m21;
+ Z22 += m22;
+ p1 = ell[3];
+ p2 = ell[3 + nskip1];
+ dd = dee[3];
+ q1 = p1 * dd;
+ q2 = p2 * dd;
+ ell[3] = q1;
+ ell[3 + nskip1] = q2;
+ m11 = p1 * q1;
+ m21 = p2 * q1;
+ m22 = p2 * q2;
+ Z11 += m11;
+ Z21 += m21;
+ Z22 += m22;
+ p1 = ell[4];
+ p2 = ell[4 + nskip1];
+ dd = dee[4];
+ q1 = p1 * dd;
+ q2 = p2 * dd;
+ ell[4] = q1;
+ ell[4 + nskip1] = q2;
+ m11 = p1 * q1;
+ m21 = p2 * q1;
+ m22 = p2 * q2;
+ Z11 += m11;
+ Z21 += m21;
+ Z22 += m22;
+ p1 = ell[5];
+ p2 = ell[5 + nskip1];
+ dd = dee[5];
+ q1 = p1 * dd;
+ q2 = p2 * dd;
+ ell[5] = q1;
+ ell[5 + nskip1] = q2;
+ m11 = p1 * q1;
+ m21 = p2 * q1;
+ m22 = p2 * q2;
+ Z11 += m11;
+ Z21 += m21;
+ Z22 += m22;
+ ell += 6;
+ dee += 6;
+ }
+ /* compute left-over iterations */
+ j += 6;
+ for (; j > 0; j--)
+ {
+ p1 = ell[0];
+ p2 = ell[nskip1];
+ dd = dee[0];
+ q1 = p1 * dd;
+ q2 = p2 * dd;
+ ell[0] = q1;
+ ell[nskip1] = q2;
+ m11 = p1 * q1;
+ m21 = p2 * q1;
+ m22 = p2 * q2;
+ Z11 += m11;
+ Z21 += m21;
+ Z22 += m22;
+ ell++;
+ dee++;
+ }
+ /* solve for diagonal 2 x 2 block at A(i,i) */
+ Z11 = ell[0] - Z11;
+ Z21 = ell[nskip1] - Z21;
+ Z22 = ell[1 + nskip1] - Z22;
+ dee = d + i;
+ /* factorize 2 x 2 block Z,dee */
+ /* factorize row 1 */
+ dee[0] = btRecip(Z11);
+ /* factorize row 2 */
+ sum = 0;
+ q1 = Z21;
+ q2 = q1 * dee[0];
+ Z21 = q2;
+ sum += q1 * q2;
+ dee[1] = btRecip(Z22 - sum);
+ /* done factorizing 2 x 2 block */
+ ell[nskip1] = Z21;
+ }
+ /* compute the (less than 2) rows at the bottom */
+ switch (n - i)
+ {
+ case 0:
+ break;
+
+ case 1:
+ btSolveL1_1(A, A + i * nskip1, i, nskip1);
+ /* 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. */
+ Z11 = 0;
+ ell = A + i * nskip1;
+ dee = d;
+ for (j = i - 6; j >= 0; j -= 6)
+ {
+ p1 = ell[0];
+ dd = dee[0];
+ q1 = p1 * dd;
+ ell[0] = q1;
+ m11 = p1 * q1;
+ Z11 += m11;
+ p1 = ell[1];
+ dd = dee[1];
+ q1 = p1 * dd;
+ ell[1] = q1;
+ m11 = p1 * q1;
+ Z11 += m11;
+ p1 = ell[2];
+ dd = dee[2];
+ q1 = p1 * dd;
+ ell[2] = q1;
+ m11 = p1 * q1;
+ Z11 += m11;
+ p1 = ell[3];
+ dd = dee[3];
+ q1 = p1 * dd;
+ ell[3] = q1;
+ m11 = p1 * q1;
+ Z11 += m11;
+ p1 = ell[4];
+ dd = dee[4];
+ q1 = p1 * dd;
+ ell[4] = q1;
+ m11 = p1 * q1;
+ Z11 += m11;
+ p1 = ell[5];
+ dd = dee[5];
+ q1 = p1 * dd;
+ ell[5] = q1;
+ m11 = p1 * q1;
+ Z11 += m11;
+ ell += 6;
+ dee += 6;
+ }
+ /* compute left-over iterations */
+ j += 6;
+ for (; j > 0; j--)
+ {
+ p1 = ell[0];
+ dd = dee[0];
+ q1 = p1 * dd;
+ ell[0] = q1;
+ m11 = p1 * q1;
+ Z11 += m11;
+ ell++;
+ dee++;
+ }
+ /* solve for diagonal 1 x 1 block at A(i,i) */
+ Z11 = ell[0] - Z11;
+ dee = d + i;
+ /* factorize 1 x 1 block Z,dee */
+ /* factorize row 1 */
+ dee[0] = btRecip(Z11);
+ /* done factorizing 1 x 1 block */
+ break;
+
+ //default: *((char*)0)=0; /* this should never happen! */
+ }
}
/* solve L*X=B, with B containing 1 right hand sides.
@@ -523,289 +530,295 @@ void btFactorLDLT (btScalar *A, btScalar *d, int n, int nskip1)
* if this is in the factorizer source file, n must be a multiple of 4.
*/
-void btSolveL1 (const btScalar *L, btScalar *B, int n, int lskip1)
-{
- /* declare variables - Z matrix, p and q vectors, etc */
- btScalar Z11,Z21,Z31,Z41,p1,q1,p2,p3,p4,*ex;
- const btScalar *ell;
- int lskip2,lskip3,i,j;
- /* compute lskip values */
- lskip2 = 2*lskip1;
- lskip3 = 3*lskip1;
- /* compute all 4 x 1 blocks of X */
- for (i=0; i <= n-4; i+=4) {
- /* compute all 4 x 1 block of X, from rows i..i+4-1 */
- /* set the Z matrix to 0 */
- Z11=0;
- Z21=0;
- Z31=0;
- Z41=0;
- ell = L + i*lskip1;
- ex = B;
- /* the inner loop that computes outer products and adds them to Z */
- for (j=i-12; j >= 0; j -= 12) {
- /* load p and q values */
- p1=ell[0];
- q1=ex[0];
- p2=ell[lskip1];
- p3=ell[lskip2];
- p4=ell[lskip3];
- /* 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 */
- p1=ell[1];
- q1=ex[1];
- p2=ell[1+lskip1];
- p3=ell[1+lskip2];
- p4=ell[1+lskip3];
- /* 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 */
- p1=ell[2];
- q1=ex[2];
- p2=ell[2+lskip1];
- p3=ell[2+lskip2];
- p4=ell[2+lskip3];
- /* 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 */
- p1=ell[3];
- q1=ex[3];
- p2=ell[3+lskip1];
- p3=ell[3+lskip2];
- p4=ell[3+lskip3];
- /* 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 */
- p1=ell[4];
- q1=ex[4];
- p2=ell[4+lskip1];
- p3=ell[4+lskip2];
- p4=ell[4+lskip3];
- /* 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 */
- p1=ell[5];
- q1=ex[5];
- p2=ell[5+lskip1];
- p3=ell[5+lskip2];
- p4=ell[5+lskip3];
- /* 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 */
- p1=ell[6];
- q1=ex[6];
- p2=ell[6+lskip1];
- p3=ell[6+lskip2];
- p4=ell[6+lskip3];
- /* 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 */
- p1=ell[7];
- q1=ex[7];
- p2=ell[7+lskip1];
- p3=ell[7+lskip2];
- p4=ell[7+lskip3];
- /* 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 */
- p1=ell[8];
- q1=ex[8];
- p2=ell[8+lskip1];
- p3=ell[8+lskip2];
- p4=ell[8+lskip3];
- /* 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 */
- p1=ell[9];
- q1=ex[9];
- p2=ell[9+lskip1];
- p3=ell[9+lskip2];
- p4=ell[9+lskip3];
- /* 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 */
- p1=ell[10];
- q1=ex[10];
- p2=ell[10+lskip1];
- p3=ell[10+lskip2];
- p4=ell[10+lskip3];
- /* 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 */
- p1=ell[11];
- q1=ex[11];
- p2=ell[11+lskip1];
- p3=ell[11+lskip2];
- p4=ell[11+lskip3];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- Z21 += p2 * q1;
- Z31 += p3 * q1;
- Z41 += p4 * q1;
- /* advance pointers */
- ell += 12;
- ex += 12;
- /* end of inner loop */
- }
- /* compute left-over iterations */
- j += 12;
- for (; j > 0; j--) {
- /* load p and q values */
- p1=ell[0];
- q1=ex[0];
- p2=ell[lskip1];
- p3=ell[lskip2];
- p4=ell[lskip3];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- Z21 += p2 * q1;
- Z31 += p3 * q1;
- Z41 += p4 * q1;
- /* advance pointers */
- ell += 1;
- ex += 1;
- }
- /* finish computing the X(i) block */
- Z11 = ex[0] - Z11;
- ex[0] = Z11;
- p1 = ell[lskip1];
- Z21 = ex[1] - Z21 - p1*Z11;
- ex[1] = Z21;
- p1 = ell[lskip2];
- p2 = ell[1+lskip2];
- Z31 = ex[2] - Z31 - p1*Z11 - p2*Z21;
- ex[2] = Z31;
- p1 = ell[lskip3];
- p2 = ell[1+lskip3];
- p3 = ell[2+lskip3];
- Z41 = ex[3] - Z41 - p1*Z11 - p2*Z21 - p3*Z31;
- ex[3] = Z41;
- /* end of outer loop */
- }
- /* compute rows at end that are not a multiple of block size */
- for (; i < n; i++) {
- /* compute all 1 x 1 block of X, from rows i..i+1-1 */
- /* set the Z matrix to 0 */
- Z11=0;
- ell = L + i*lskip1;
- ex = B;
- /* the inner loop that computes outer products and adds them to Z */
- for (j=i-12; j >= 0; j -= 12) {
- /* load p and q values */
- p1=ell[0];
- q1=ex[0];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- /* load p and q values */
- p1=ell[1];
- q1=ex[1];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- /* load p and q values */
- p1=ell[2];
- q1=ex[2];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- /* load p and q values */
- p1=ell[3];
- q1=ex[3];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- /* load p and q values */
- p1=ell[4];
- q1=ex[4];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- /* load p and q values */
- p1=ell[5];
- q1=ex[5];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- /* load p and q values */
- p1=ell[6];
- q1=ex[6];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- /* load p and q values */
- p1=ell[7];
- q1=ex[7];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- /* load p and q values */
- p1=ell[8];
- q1=ex[8];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- /* load p and q values */
- p1=ell[9];
- q1=ex[9];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- /* load p and q values */
- p1=ell[10];
- q1=ex[10];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- /* load p and q values */
- p1=ell[11];
- q1=ex[11];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- /* advance pointers */
- ell += 12;
- ex += 12;
- /* end of inner loop */
- }
- /* compute left-over iterations */
- j += 12;
- for (; j > 0; j--) {
- /* load p and q values */
- p1=ell[0];
- q1=ex[0];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- /* advance pointers */
- ell += 1;
- ex += 1;
- }
- /* finish computing the X(i) block */
- Z11 = ex[0] - Z11;
- ex[0] = Z11;
- }
+void btSolveL1(const btScalar *L, btScalar *B, int n, int lskip1)
+{
+ /* declare variables - Z matrix, p and q vectors, etc */
+ btScalar Z11, Z21, Z31, Z41, p1, q1, p2, p3, p4, *ex;
+ const btScalar *ell;
+ int lskip2, lskip3, i, j;
+ /* compute lskip values */
+ lskip2 = 2 * lskip1;
+ lskip3 = 3 * lskip1;
+ /* compute all 4 x 1 blocks of X */
+ for (i = 0; i <= n - 4; i += 4)
+ {
+ /* compute all 4 x 1 block of X, from rows i..i+4-1 */
+ /* set the Z matrix to 0 */
+ Z11 = 0;
+ Z21 = 0;
+ Z31 = 0;
+ Z41 = 0;
+ ell = L + i * lskip1;
+ ex = B;
+ /* the inner loop that computes outer products and adds them to Z */
+ for (j = i - 12; j >= 0; j -= 12)
+ {
+ /* load p and q values */
+ p1 = ell[0];
+ q1 = ex[0];
+ p2 = ell[lskip1];
+ p3 = ell[lskip2];
+ p4 = ell[lskip3];
+ /* 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 */
+ p1 = ell[1];
+ q1 = ex[1];
+ p2 = ell[1 + lskip1];
+ p3 = ell[1 + lskip2];
+ p4 = ell[1 + lskip3];
+ /* 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 */
+ p1 = ell[2];
+ q1 = ex[2];
+ p2 = ell[2 + lskip1];
+ p3 = ell[2 + lskip2];
+ p4 = ell[2 + lskip3];
+ /* 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 */
+ p1 = ell[3];
+ q1 = ex[3];
+ p2 = ell[3 + lskip1];
+ p3 = ell[3 + lskip2];
+ p4 = ell[3 + lskip3];
+ /* 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 */
+ p1 = ell[4];
+ q1 = ex[4];
+ p2 = ell[4 + lskip1];
+ p3 = ell[4 + lskip2];
+ p4 = ell[4 + lskip3];
+ /* 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 */
+ p1 = ell[5];
+ q1 = ex[5];
+ p2 = ell[5 + lskip1];
+ p3 = ell[5 + lskip2];
+ p4 = ell[5 + lskip3];
+ /* 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 */
+ p1 = ell[6];
+ q1 = ex[6];
+ p2 = ell[6 + lskip1];
+ p3 = ell[6 + lskip2];
+ p4 = ell[6 + lskip3];
+ /* 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 */
+ p1 = ell[7];
+ q1 = ex[7];
+ p2 = ell[7 + lskip1];
+ p3 = ell[7 + lskip2];
+ p4 = ell[7 + lskip3];
+ /* 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 */
+ p1 = ell[8];
+ q1 = ex[8];
+ p2 = ell[8 + lskip1];
+ p3 = ell[8 + lskip2];
+ p4 = ell[8 + lskip3];
+ /* 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 */
+ p1 = ell[9];
+ q1 = ex[9];
+ p2 = ell[9 + lskip1];
+ p3 = ell[9 + lskip2];
+ p4 = ell[9 + lskip3];
+ /* 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 */
+ p1 = ell[10];
+ q1 = ex[10];
+ p2 = ell[10 + lskip1];
+ p3 = ell[10 + lskip2];
+ p4 = ell[10 + lskip3];
+ /* 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 */
+ p1 = ell[11];
+ q1 = ex[11];
+ p2 = ell[11 + lskip1];
+ p3 = ell[11 + lskip2];
+ p4 = ell[11 + lskip3];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ Z21 += p2 * q1;
+ Z31 += p3 * q1;
+ Z41 += p4 * q1;
+ /* advance pointers */
+ ell += 12;
+ ex += 12;
+ /* end of inner loop */
+ }
+ /* compute left-over iterations */
+ j += 12;
+ for (; j > 0; j--)
+ {
+ /* load p and q values */
+ p1 = ell[0];
+ q1 = ex[0];
+ p2 = ell[lskip1];
+ p3 = ell[lskip2];
+ p4 = ell[lskip3];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ Z21 += p2 * q1;
+ Z31 += p3 * q1;
+ Z41 += p4 * q1;
+ /* advance pointers */
+ ell += 1;
+ ex += 1;
+ }
+ /* finish computing the X(i) block */
+ Z11 = ex[0] - Z11;
+ ex[0] = Z11;
+ p1 = ell[lskip1];
+ Z21 = ex[1] - Z21 - p1 * Z11;
+ ex[1] = Z21;
+ p1 = ell[lskip2];
+ p2 = ell[1 + lskip2];
+ Z31 = ex[2] - Z31 - p1 * Z11 - p2 * Z21;
+ ex[2] = Z31;
+ p1 = ell[lskip3];
+ p2 = ell[1 + lskip3];
+ p3 = ell[2 + lskip3];
+ Z41 = ex[3] - Z41 - p1 * Z11 - p2 * Z21 - p3 * Z31;
+ ex[3] = Z41;
+ /* end of outer loop */
+ }
+ /* compute rows at end that are not a multiple of block size */
+ for (; i < n; i++)
+ {
+ /* compute all 1 x 1 block of X, from rows i..i+1-1 */
+ /* set the Z matrix to 0 */
+ Z11 = 0;
+ ell = L + i * lskip1;
+ ex = B;
+ /* the inner loop that computes outer products and adds them to Z */
+ for (j = i - 12; j >= 0; j -= 12)
+ {
+ /* load p and q values */
+ p1 = ell[0];
+ q1 = ex[0];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ /* load p and q values */
+ p1 = ell[1];
+ q1 = ex[1];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ /* load p and q values */
+ p1 = ell[2];
+ q1 = ex[2];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ /* load p and q values */
+ p1 = ell[3];
+ q1 = ex[3];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ /* load p and q values */
+ p1 = ell[4];
+ q1 = ex[4];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ /* load p and q values */
+ p1 = ell[5];
+ q1 = ex[5];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ /* load p and q values */
+ p1 = ell[6];
+ q1 = ex[6];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ /* load p and q values */
+ p1 = ell[7];
+ q1 = ex[7];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ /* load p and q values */
+ p1 = ell[8];
+ q1 = ex[8];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ /* load p and q values */
+ p1 = ell[9];
+ q1 = ex[9];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ /* load p and q values */
+ p1 = ell[10];
+ q1 = ex[10];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ /* load p and q values */
+ p1 = ell[11];
+ q1 = ex[11];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ /* advance pointers */
+ ell += 12;
+ ex += 12;
+ /* end of inner loop */
+ }
+ /* compute left-over iterations */
+ j += 12;
+ for (; j > 0; j--)
+ {
+ /* load p and q values */
+ p1 = ell[0];
+ q1 = ex[0];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ /* advance pointers */
+ ell += 1;
+ ex += 1;
+ }
+ /* finish computing the X(i) block */
+ Z11 = ex[0] - Z11;
+ ex[0] = Z11;
+ }
}
/* solve L^T * x=b, with b containing 1 right hand side.
@@ -816,215 +829,218 @@ void btSolveL1 (const btScalar *L, btScalar *B, int n, int lskip1)
* this processes blocks of 4.
*/
-void btSolveL1T (const btScalar *L, btScalar *B, int n, int lskip1)
-{
- /* declare variables - Z matrix, p and q vectors, etc */
- btScalar Z11,m11,Z21,m21,Z31,m31,Z41,m41,p1,q1,p2,p3,p4,*ex;
- const btScalar *ell;
- int lskip2,i,j;
-// int lskip3;
- /* special handling for L and B because we're solving L1 *transpose* */
- L = L + (n-1)*(lskip1+1);
- B = B + n-1;
- lskip1 = -lskip1;
- /* compute lskip values */
- lskip2 = 2*lskip1;
- //lskip3 = 3*lskip1;
- /* compute all 4 x 1 blocks of X */
- for (i=0; i <= n-4; i+=4) {
- /* compute all 4 x 1 block of X, from rows i..i+4-1 */
- /* set the Z matrix to 0 */
- Z11=0;
- Z21=0;
- Z31=0;
- Z41=0;
- ell = L - i;
- ex = B;
- /* the inner loop that computes outer products and adds them to Z */
- for (j=i-4; j >= 0; j -= 4) {
- /* load p and q values */
- p1=ell[0];
- q1=ex[0];
- p2=ell[-1];
- p3=ell[-2];
- p4=ell[-3];
- /* compute outer product and add it to the Z matrix */
- m11 = p1 * q1;
- m21 = p2 * q1;
- m31 = p3 * q1;
- m41 = p4 * q1;
- ell += lskip1;
- Z11 += m11;
- Z21 += m21;
- Z31 += m31;
- Z41 += m41;
- /* load p and q values */
- p1=ell[0];
- q1=ex[-1];
- p2=ell[-1];
- p3=ell[-2];
- p4=ell[-3];
- /* compute outer product and add it to the Z matrix */
- m11 = p1 * q1;
- m21 = p2 * q1;
- m31 = p3 * q1;
- m41 = p4 * q1;
- ell += lskip1;
- Z11 += m11;
- Z21 += m21;
- Z31 += m31;
- Z41 += m41;
- /* load p and q values */
- p1=ell[0];
- q1=ex[-2];
- p2=ell[-1];
- p3=ell[-2];
- p4=ell[-3];
- /* compute outer product and add it to the Z matrix */
- m11 = p1 * q1;
- m21 = p2 * q1;
- m31 = p3 * q1;
- m41 = p4 * q1;
- ell += lskip1;
- Z11 += m11;
- Z21 += m21;
- Z31 += m31;
- Z41 += m41;
- /* load p and q values */
- p1=ell[0];
- q1=ex[-3];
- p2=ell[-1];
- p3=ell[-2];
- p4=ell[-3];
- /* compute outer product and add it to the Z matrix */
- m11 = p1 * q1;
- m21 = p2 * q1;
- m31 = p3 * q1;
- m41 = p4 * q1;
- ell += lskip1;
- ex -= 4;
- Z11 += m11;
- Z21 += m21;
- Z31 += m31;
- Z41 += m41;
- /* end of inner loop */
- }
- /* compute left-over iterations */
- j += 4;
- for (; j > 0; j--) {
- /* load p and q values */
- p1=ell[0];
- q1=ex[0];
- p2=ell[-1];
- p3=ell[-2];
- p4=ell[-3];
- /* compute outer product and add it to the Z matrix */
- m11 = p1 * q1;
- m21 = p2 * q1;
- m31 = p3 * q1;
- m41 = p4 * q1;
- ell += lskip1;
- ex -= 1;
- Z11 += m11;
- Z21 += m21;
- Z31 += m31;
- Z41 += m41;
- }
- /* finish computing the X(i) block */
- Z11 = ex[0] - Z11;
- ex[0] = Z11;
- p1 = ell[-1];
- Z21 = ex[-1] - Z21 - p1*Z11;
- ex[-1] = Z21;
- p1 = ell[-2];
- p2 = ell[-2+lskip1];
- Z31 = ex[-2] - Z31 - p1*Z11 - p2*Z21;
- ex[-2] = Z31;
- p1 = ell[-3];
- p2 = ell[-3+lskip1];
- p3 = ell[-3+lskip2];
- Z41 = ex[-3] - Z41 - p1*Z11 - p2*Z21 - p3*Z31;
- ex[-3] = Z41;
- /* end of outer loop */
- }
- /* compute rows at end that are not a multiple of block size */
- for (; i < n; i++) {
- /* compute all 1 x 1 block of X, from rows i..i+1-1 */
- /* set the Z matrix to 0 */
- Z11=0;
- ell = L - i;
- ex = B;
- /* the inner loop that computes outer products and adds them to Z */
- for (j=i-4; j >= 0; j -= 4) {
- /* load p and q values */
- p1=ell[0];
- q1=ex[0];
- /* compute outer product and add it to the Z matrix */
- m11 = p1 * q1;
- ell += lskip1;
- Z11 += m11;
- /* load p and q values */
- p1=ell[0];
- q1=ex[-1];
- /* compute outer product and add it to the Z matrix */
- m11 = p1 * q1;
- ell += lskip1;
- Z11 += m11;
- /* load p and q values */
- p1=ell[0];
- q1=ex[-2];
- /* compute outer product and add it to the Z matrix */
- m11 = p1 * q1;
- ell += lskip1;
- Z11 += m11;
- /* load p and q values */
- p1=ell[0];
- q1=ex[-3];
- /* compute outer product and add it to the Z matrix */
- m11 = p1 * q1;
- ell += lskip1;
- ex -= 4;
- Z11 += m11;
- /* end of inner loop */
- }
- /* compute left-over iterations */
- j += 4;
- for (; j > 0; j--) {
- /* load p and q values */
- p1=ell[0];
- q1=ex[0];
- /* compute outer product and add it to the Z matrix */
- m11 = p1 * q1;
- ell += lskip1;
- ex -= 1;
- Z11 += m11;
- }
- /* finish computing the X(i) block */
- Z11 = ex[0] - Z11;
- ex[0] = Z11;
- }
+void btSolveL1T(const btScalar *L, btScalar *B, int n, int lskip1)
+{
+ /* declare variables - Z matrix, p and q vectors, etc */
+ btScalar Z11, m11, Z21, m21, Z31, m31, Z41, m41, p1, q1, p2, p3, p4, *ex;
+ const btScalar *ell;
+ int lskip2, i, j;
+ // int lskip3;
+ /* special handling for L and B because we're solving L1 *transpose* */
+ L = L + (n - 1) * (lskip1 + 1);
+ B = B + n - 1;
+ lskip1 = -lskip1;
+ /* compute lskip values */
+ lskip2 = 2 * lskip1;
+ //lskip3 = 3*lskip1;
+ /* compute all 4 x 1 blocks of X */
+ for (i = 0; i <= n - 4; i += 4)
+ {
+ /* compute all 4 x 1 block of X, from rows i..i+4-1 */
+ /* set the Z matrix to 0 */
+ Z11 = 0;
+ Z21 = 0;
+ Z31 = 0;
+ Z41 = 0;
+ ell = L - i;
+ ex = B;
+ /* the inner loop that computes outer products and adds them to Z */
+ for (j = i - 4; j >= 0; j -= 4)
+ {
+ /* load p and q values */
+ p1 = ell[0];
+ q1 = ex[0];
+ p2 = ell[-1];
+ p3 = ell[-2];
+ p4 = ell[-3];
+ /* compute outer product and add it to the Z matrix */
+ m11 = p1 * q1;
+ m21 = p2 * q1;
+ m31 = p3 * q1;
+ m41 = p4 * q1;
+ ell += lskip1;
+ Z11 += m11;
+ Z21 += m21;
+ Z31 += m31;
+ Z41 += m41;
+ /* load p and q values */
+ p1 = ell[0];
+ q1 = ex[-1];
+ p2 = ell[-1];
+ p3 = ell[-2];
+ p4 = ell[-3];
+ /* compute outer product and add it to the Z matrix */
+ m11 = p1 * q1;
+ m21 = p2 * q1;
+ m31 = p3 * q1;
+ m41 = p4 * q1;
+ ell += lskip1;
+ Z11 += m11;
+ Z21 += m21;
+ Z31 += m31;
+ Z41 += m41;
+ /* load p and q values */
+ p1 = ell[0];
+ q1 = ex[-2];
+ p2 = ell[-1];
+ p3 = ell[-2];
+ p4 = ell[-3];
+ /* compute outer product and add it to the Z matrix */
+ m11 = p1 * q1;
+ m21 = p2 * q1;
+ m31 = p3 * q1;
+ m41 = p4 * q1;
+ ell += lskip1;
+ Z11 += m11;
+ Z21 += m21;
+ Z31 += m31;
+ Z41 += m41;
+ /* load p and q values */
+ p1 = ell[0];
+ q1 = ex[-3];
+ p2 = ell[-1];
+ p3 = ell[-2];
+ p4 = ell[-3];
+ /* compute outer product and add it to the Z matrix */
+ m11 = p1 * q1;
+ m21 = p2 * q1;
+ m31 = p3 * q1;
+ m41 = p4 * q1;
+ ell += lskip1;
+ ex -= 4;
+ Z11 += m11;
+ Z21 += m21;
+ Z31 += m31;
+ Z41 += m41;
+ /* end of inner loop */
+ }
+ /* compute left-over iterations */
+ j += 4;
+ for (; j > 0; j--)
+ {
+ /* load p and q values */
+ p1 = ell[0];
+ q1 = ex[0];
+ p2 = ell[-1];
+ p3 = ell[-2];
+ p4 = ell[-3];
+ /* compute outer product and add it to the Z matrix */
+ m11 = p1 * q1;
+ m21 = p2 * q1;
+ m31 = p3 * q1;
+ m41 = p4 * q1;
+ ell += lskip1;
+ ex -= 1;
+ Z11 += m11;
+ Z21 += m21;
+ Z31 += m31;
+ Z41 += m41;
+ }
+ /* finish computing the X(i) block */
+ Z11 = ex[0] - Z11;
+ ex[0] = Z11;
+ p1 = ell[-1];
+ Z21 = ex[-1] - Z21 - p1 * Z11;
+ ex[-1] = Z21;
+ p1 = ell[-2];
+ p2 = ell[-2 + lskip1];
+ Z31 = ex[-2] - Z31 - p1 * Z11 - p2 * Z21;
+ ex[-2] = Z31;
+ p1 = ell[-3];
+ p2 = ell[-3 + lskip1];
+ p3 = ell[-3 + lskip2];
+ Z41 = ex[-3] - Z41 - p1 * Z11 - p2 * Z21 - p3 * Z31;
+ ex[-3] = Z41;
+ /* end of outer loop */
+ }
+ /* compute rows at end that are not a multiple of block size */
+ for (; i < n; i++)
+ {
+ /* compute all 1 x 1 block of X, from rows i..i+1-1 */
+ /* set the Z matrix to 0 */
+ Z11 = 0;
+ ell = L - i;
+ ex = B;
+ /* the inner loop that computes outer products and adds them to Z */
+ for (j = i - 4; j >= 0; j -= 4)
+ {
+ /* load p and q values */
+ p1 = ell[0];
+ q1 = ex[0];
+ /* compute outer product and add it to the Z matrix */
+ m11 = p1 * q1;
+ ell += lskip1;
+ Z11 += m11;
+ /* load p and q values */
+ p1 = ell[0];
+ q1 = ex[-1];
+ /* compute outer product and add it to the Z matrix */
+ m11 = p1 * q1;
+ ell += lskip1;
+ Z11 += m11;
+ /* load p and q values */
+ p1 = ell[0];
+ q1 = ex[-2];
+ /* compute outer product and add it to the Z matrix */
+ m11 = p1 * q1;
+ ell += lskip1;
+ Z11 += m11;
+ /* load p and q values */
+ p1 = ell[0];
+ q1 = ex[-3];
+ /* compute outer product and add it to the Z matrix */
+ m11 = p1 * q1;
+ ell += lskip1;
+ ex -= 4;
+ Z11 += m11;
+ /* end of inner loop */
+ }
+ /* compute left-over iterations */
+ j += 4;
+ for (; j > 0; j--)
+ {
+ /* load p and q values */
+ p1 = ell[0];
+ q1 = ex[0];
+ /* compute outer product and add it to the Z matrix */
+ m11 = p1 * q1;
+ ell += lskip1;
+ ex -= 1;
+ Z11 += m11;
+ }
+ /* finish computing the X(i) block */
+ Z11 = ex[0] - Z11;
+ ex[0] = Z11;
+ }
}
-
-
-void btVectorScale (btScalar *a, const btScalar *d, int n)
+void btVectorScale(btScalar *a, const btScalar *d, int n)
{
- btAssert (a && d && n >= 0);
- for (int i=0; i<n; i++) {
- a[i] *= d[i];
- }
+ btAssert(a && d && n >= 0);
+ for (int i = 0; i < n; i++)
+ {
+ a[i] *= d[i];
+ }
}
-void btSolveLDLT (const btScalar *L, const btScalar *d, btScalar *b, int n, int nskip)
+void btSolveLDLT(const btScalar *L, const btScalar *d, btScalar *b, int n, int nskip)
{
- btAssert (L && d && b && n > 0 && nskip >= n);
- btSolveL1 (L,b,n,nskip);
- btVectorScale (b,d,n);
- btSolveL1T (L,b,n,nskip);
+ btAssert(L && d && b && n > 0 && nskip >= n);
+ btSolveL1(L, b, n, nskip);
+ btVectorScale(b, d, n);
+ btSolveL1T(L, b, n, nskip);
}
-
-
//***************************************************************************
// swap row/column i1 with i2 in the n*n matrix A. the leading dimension of
@@ -1033,124 +1049,129 @@ void btSolveLDLT (const btScalar *L, const btScalar *d, btScalar *b, int n, int
// rows will be swapped by exchanging row pointers. otherwise the data will
// be copied.
-static void btSwapRowsAndCols (BTATYPE A, int n, int i1, int i2, int nskip,
- int do_fast_row_swaps)
+static void btSwapRowsAndCols(BTATYPE A, int n, int i1, int i2, int nskip,
+ int do_fast_row_swaps)
{
- btAssert (A && n > 0 && i1 >= 0 && i2 >= 0 && i1 < n && i2 < n &&
- nskip >= n && i1 < i2);
-
-# ifdef BTROWPTRS
- btScalar *A_i1 = A[i1];
- btScalar *A_i2 = A[i2];
- for (int i=i1+1; i<i2; ++i) {
- btScalar *A_i_i1 = A[i] + i1;
- A_i1[i] = *A_i_i1;
- *A_i_i1 = A_i2[i];
- }
- A_i1[i2] = A_i1[i1];
- A_i1[i1] = A_i2[i1];
- A_i2[i1] = A_i2[i2];
- // swap rows, by swapping row pointers
- if (do_fast_row_swaps) {
- A[i1] = A_i2;
- A[i2] = A_i1;
- }
- else {
- // Only swap till i2 column to match A plain storage variant.
- for (int k = 0; k <= i2; ++k) {
- btScalar tmp = A_i1[k];
- A_i1[k] = A_i2[k];
- A_i2[k] = tmp;
- }
- }
- // swap columns the hard way
- for (int j=i2+1; j<n; ++j) {
- btScalar *A_j = A[j];
- btScalar tmp = A_j[i1];
- A_j[i1] = A_j[i2];
- A_j[i2] = tmp;
- }
-# else
- btScalar *A_i1 = A+i1*nskip;
- btScalar *A_i2 = A+i2*nskip;
- for (int k = 0; k < i1; ++k) {
- btScalar tmp = A_i1[k];
- A_i1[k] = A_i2[k];
- A_i2[k] = tmp;
- }
- btScalar *A_i = A_i1 + nskip;
- for (int i=i1+1; i<i2; A_i+=nskip, ++i) {
- btScalar tmp = A_i2[i];
- A_i2[i] = A_i[i1];
- A_i[i1] = tmp;
- }
- {
- btScalar tmp = A_i1[i1];
- A_i1[i1] = A_i2[i2];
- A_i2[i2] = tmp;
- }
- btScalar *A_j = A_i2 + nskip;
- for (int j=i2+1; j<n; A_j+=nskip, ++j) {
- btScalar tmp = A_j[i1];
- A_j[i1] = A_j[i2];
- A_j[i2] = tmp;
- }
-# endif
-}
+ btAssert(A && n > 0 && i1 >= 0 && i2 >= 0 && i1 < n && i2 < n &&
+ nskip >= n && i1 < i2);
+#ifdef BTROWPTRS
+ btScalar *A_i1 = A[i1];
+ btScalar *A_i2 = A[i2];
+ for (int i = i1 + 1; i < i2; ++i)
+ {
+ btScalar *A_i_i1 = A[i] + i1;
+ A_i1[i] = *A_i_i1;
+ *A_i_i1 = A_i2[i];
+ }
+ A_i1[i2] = A_i1[i1];
+ A_i1[i1] = A_i2[i1];
+ A_i2[i1] = A_i2[i2];
+ // swap rows, by swapping row pointers
+ if (do_fast_row_swaps)
+ {
+ A[i1] = A_i2;
+ A[i2] = A_i1;
+ }
+ else
+ {
+ // Only swap till i2 column to match A plain storage variant.
+ for (int k = 0; k <= i2; ++k)
+ {
+ btScalar tmp = A_i1[k];
+ A_i1[k] = A_i2[k];
+ A_i2[k] = tmp;
+ }
+ }
+ // swap columns the hard way
+ for (int j = i2 + 1; j < n; ++j)
+ {
+ btScalar *A_j = A[j];
+ btScalar tmp = A_j[i1];
+ A_j[i1] = A_j[i2];
+ A_j[i2] = tmp;
+ }
+#else
+ btScalar *A_i1 = A + i1 * nskip;
+ btScalar *A_i2 = A + i2 * nskip;
+ for (int k = 0; k < i1; ++k)
+ {
+ btScalar tmp = A_i1[k];
+ A_i1[k] = A_i2[k];
+ A_i2[k] = tmp;
+ }
+ btScalar *A_i = A_i1 + nskip;
+ for (int i = i1 + 1; i < i2; A_i += nskip, ++i)
+ {
+ btScalar tmp = A_i2[i];
+ A_i2[i] = A_i[i1];
+ A_i[i1] = tmp;
+ }
+ {
+ btScalar tmp = A_i1[i1];
+ A_i1[i1] = A_i2[i2];
+ A_i2[i2] = tmp;
+ }
+ btScalar *A_j = A_i2 + nskip;
+ for (int j = i2 + 1; j < n; A_j += nskip, ++j)
+ {
+ btScalar tmp = A_j[i1];
+ A_j[i1] = A_j[i2];
+ A_j[i2] = tmp;
+ }
+#endif
+}
// swap two indexes in the n*n LCP problem. i1 must be <= i2.
-static void btSwapProblem (BTATYPE A, btScalar *x, btScalar *b, btScalar *w, btScalar *lo,
- btScalar *hi, int *p, bool *state, int *findex,
- int n, int i1, int i2, int nskip,
- int do_fast_row_swaps)
+static void btSwapProblem(BTATYPE A, btScalar *x, btScalar *b, btScalar *w, btScalar *lo,
+ btScalar *hi, int *p, bool *state, int *findex,
+ int n, int i1, int i2, int nskip,
+ int do_fast_row_swaps)
{
- btScalar tmpr;
- int tmpi;
- bool tmpb;
- btAssert (n>0 && i1 >=0 && i2 >= 0 && i1 < n && i2 < n && nskip >= n && i1 <= i2);
- if (i1==i2) return;
-
- btSwapRowsAndCols (A,n,i1,i2,nskip,do_fast_row_swaps);
-
- tmpr = x[i1];
- x[i1] = x[i2];
- x[i2] = tmpr;
-
- tmpr = b[i1];
- b[i1] = b[i2];
- b[i2] = tmpr;
-
- tmpr = w[i1];
- w[i1] = w[i2];
- w[i2] = tmpr;
-
- tmpr = lo[i1];
- lo[i1] = lo[i2];
- lo[i2] = tmpr;
-
- tmpr = hi[i1];
- hi[i1] = hi[i2];
- hi[i2] = tmpr;
-
- tmpi = p[i1];
- p[i1] = p[i2];
- p[i2] = tmpi;
-
- tmpb = state[i1];
- state[i1] = state[i2];
- state[i2] = tmpb;
-
- if (findex) {
- tmpi = findex[i1];
- findex[i1] = findex[i2];
- findex[i2] = tmpi;
- }
-}
+ btScalar tmpr;
+ int tmpi;
+ bool tmpb;
+ btAssert(n > 0 && i1 >= 0 && i2 >= 0 && i1 < n && i2 < n && nskip >= n && i1 <= i2);
+ if (i1 == i2) return;
+
+ btSwapRowsAndCols(A, n, i1, i2, nskip, do_fast_row_swaps);
+
+ tmpr = x[i1];
+ x[i1] = x[i2];
+ x[i2] = tmpr;
+ tmpr = b[i1];
+ b[i1] = b[i2];
+ b[i2] = tmpr;
+ tmpr = w[i1];
+ w[i1] = w[i2];
+ w[i2] = tmpr;
+ tmpr = lo[i1];
+ lo[i1] = lo[i2];
+ lo[i2] = tmpr;
+
+ tmpr = hi[i1];
+ hi[i1] = hi[i2];
+ hi[i2] = tmpr;
+
+ tmpi = p[i1];
+ p[i1] = p[i2];
+ p[i2] = tmpi;
+
+ tmpb = state[i1];
+ state[i1] = state[i2];
+ state[i2] = tmpb;
+
+ if (findex)
+ {
+ tmpi = findex[i1];
+ findex[i1] = findex[i2];
+ findex[i2] = tmpi;
+ }
+}
//***************************************************************************
// btLCP manipulator object. this represents an n*n LCP problem.
@@ -1186,79 +1207,88 @@ static void btSwapProblem (BTATYPE A, btScalar *x, btScalar *b, btScalar *w, btS
#ifdef btLCP_FAST
-struct btLCP
+struct btLCP
{
const int m_n;
const int m_nskip;
int m_nub;
- int m_nC, m_nN; // size of each index set
- BTATYPE const m_A; // A rows
- btScalar *const m_x, * const m_b, *const m_w, *const m_lo,* const m_hi; // permuted LCP problem data
- btScalar *const m_L, *const m_d; // L*D*L' factorization of set C
+ int m_nC, m_nN; // size of each index set
+ BTATYPE const m_A; // A rows
+ btScalar *const m_x, *const m_b, *const m_w, *const m_lo, *const m_hi; // permuted LCP problem data
+ btScalar *const m_L, *const m_d; // L*D*L' factorization of set C
btScalar *const m_Dell, *const m_ell, *const m_tmp;
bool *const m_state;
int *const m_findex, *const m_p, *const m_C;
- btLCP (int _n, int _nskip, int _nub, btScalar *_Adata, btScalar *_x, btScalar *_b, btScalar *_w,
- btScalar *_lo, btScalar *_hi, btScalar *l, btScalar *_d,
- btScalar *_Dell, btScalar *_ell, btScalar *_tmp,
- bool *_state, int *_findex, int *p, int *c, btScalar **Arows);
+ btLCP(int _n, int _nskip, int _nub, btScalar *_Adata, btScalar *_x, btScalar *_b, btScalar *_w,
+ btScalar *_lo, btScalar *_hi, btScalar *l, btScalar *_d,
+ btScalar *_Dell, btScalar *_ell, btScalar *_tmp,
+ bool *_state, int *_findex, int *p, int *c, btScalar **Arows);
int getNub() const { return m_nub; }
- void transfer_i_to_C (int i);
- void transfer_i_to_N (int i) { m_nN++; } // because we can assume C and N span 1:i-1
- void transfer_i_from_N_to_C (int i);
- void transfer_i_from_C_to_N (int i, btAlignedObjectArray<btScalar>& scratch);
+ void transfer_i_to_C(int i);
+ void transfer_i_to_N(int i) { m_nN++; } // because we can assume C and N span 1:i-1
+ void transfer_i_from_N_to_C(int i);
+ void transfer_i_from_C_to_N(int i, btAlignedObjectArray<btScalar> &scratch);
int numC() const { return m_nC; }
int numN() const { return m_nN; }
- int indexC (int i) const { return i; }
- int indexN (int i) const { return i+m_nC; }
- btScalar Aii (int i) const { return BTAROW(i)[i]; }
- btScalar AiC_times_qC (int i, btScalar *q) const { return btLargeDot (BTAROW(i), q, m_nC); }
- btScalar AiN_times_qN (int i, btScalar *q) const { return btLargeDot (BTAROW(i)+m_nC, q+m_nC, m_nN); }
- void pN_equals_ANC_times_qC (btScalar *p, btScalar *q);
- void pN_plusequals_ANi (btScalar *p, int i, int sign=1);
- void pC_plusequals_s_times_qC (btScalar *p, btScalar s, btScalar *q);
- void pN_plusequals_s_times_qN (btScalar *p, btScalar s, btScalar *q);
- void solve1 (btScalar *a, int i, int dir=1, int only_transfer=0);
+ int indexC(int i) const { return i; }
+ int indexN(int i) const { return i + m_nC; }
+ btScalar Aii(int i) const { return BTAROW(i)[i]; }
+ btScalar AiC_times_qC(int i, btScalar *q) const { return btLargeDot(BTAROW(i), q, m_nC); }
+ btScalar AiN_times_qN(int i, btScalar *q) const { return btLargeDot(BTAROW(i) + m_nC, q + m_nC, m_nN); }
+ void pN_equals_ANC_times_qC(btScalar *p, btScalar *q);
+ void pN_plusequals_ANi(btScalar *p, int i, int sign = 1);
+ void pC_plusequals_s_times_qC(btScalar *p, btScalar s, btScalar *q);
+ void pN_plusequals_s_times_qN(btScalar *p, btScalar s, btScalar *q);
+ void solve1(btScalar *a, int i, int dir = 1, int only_transfer = 0);
void unpermute();
};
-
-btLCP::btLCP (int _n, int _nskip, int _nub, btScalar *_Adata, btScalar *_x, btScalar *_b, btScalar *_w,
- btScalar *_lo, btScalar *_hi, btScalar *l, btScalar *_d,
- btScalar *_Dell, btScalar *_ell, btScalar *_tmp,
- bool *_state, int *_findex, int *p, int *c, btScalar **Arows):
- m_n(_n), m_nskip(_nskip), m_nub(_nub), m_nC(0), m_nN(0),
-# ifdef BTROWPTRS
- m_A(Arows),
+btLCP::btLCP(int _n, int _nskip, int _nub, btScalar *_Adata, btScalar *_x, btScalar *_b, btScalar *_w,
+ btScalar *_lo, btScalar *_hi, btScalar *l, btScalar *_d,
+ btScalar *_Dell, btScalar *_ell, btScalar *_tmp,
+ bool *_state, int *_findex, int *p, int *c, btScalar **Arows) : m_n(_n), m_nskip(_nskip), m_nub(_nub), m_nC(0), m_nN(0),
+#ifdef BTROWPTRS
+ m_A(Arows),
#else
- m_A(_Adata),
+ m_A(_Adata),
#endif
- m_x(_x), m_b(_b), m_w(_w), m_lo(_lo), m_hi(_hi),
- 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)
+ m_x(_x),
+ m_b(_b),
+ m_w(_w),
+ m_lo(_lo),
+ m_hi(_hi),
+ 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)
{
- {
- btSetZero (m_x,m_n);
- }
+ {
+ btSetZero(m_x, m_n);
+ }
- {
-# ifdef BTROWPTRS
- // make matrix row pointers
- btScalar *aptr = _Adata;
- BTATYPE A = m_A;
- const int n = m_n, nskip = m_nskip;
- for (int k=0; k<n; aptr+=nskip, ++k) A[k] = aptr;
-# endif
- }
+ {
+#ifdef BTROWPTRS
+ // make matrix row pointers
+ btScalar *aptr = _Adata;
+ BTATYPE A = m_A;
+ const int n = m_n, nskip = m_nskip;
+ for (int k = 0; k < n; aptr += nskip, ++k) A[k] = aptr;
+#endif
+ }
- {
- int *p = m_p;
- const int n = m_n;
- for (int k=0; k<n; ++k) p[k]=k; // initially unpermuted
- }
+ {
+ int *p = m_p;
+ const int n = m_n;
+ for (int k = 0; k < n; ++k) p[k] = k; // initially unpermuted
+ }
- /*
+ /*
// for testing, we can do some random swaps in the area i > nub
{
const int n = m_n;
@@ -1277,63 +1307,69 @@ btLCP::btLCP (int _n, int _nskip, int _nub, btScalar *_Adata, btScalar *_x, btSc
}
*/
- // 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;
- btScalar *lo = m_lo, *hi = m_hi;
- const int n = m_n;
- for (int k = m_nub; k<n; ++k) {
- if (findex && findex[k] >= 0) continue;
- if (lo[k]==-BT_INFINITY && hi[k]==BT_INFINITY) {
- btSwapProblem (m_A,m_x,m_b,m_w,lo,hi,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 int nub = m_nub;
- {
- btScalar *Lrow = m_L;
- const int nskip = m_nskip;
- for (int j=0; j<nub; Lrow+=nskip, ++j) memcpy(Lrow,BTAROW(j),(j+1)*sizeof(btScalar));
- }
- btFactorLDLT (m_L,m_d,nub,m_nskip);
- memcpy (m_x,m_b,nub*sizeof(btScalar));
- btSolveLDLT (m_L,m_d,m_x,nub,m_nskip);
- btSetZero (m_w,nub);
- {
- int *C = m_C;
- for (int 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 int nub = m_nub;
- int *findex = m_findex;
- int num_at_end = 0;
- for (int k=m_n-1; k >= nub; k--) {
- if (findex[k] >= 0) {
- btSwapProblem (m_A,m_x,m_b,m_w,m_lo,m_hi,m_p,m_state,findex,m_n,k,m_n-1-num_at_end,m_nskip,1);
- num_at_end++;
- }
- }
- }
+ // 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.
- // print info about indexes
- /*
+ {
+ int *findex = m_findex;
+ btScalar *lo = m_lo, *hi = m_hi;
+ const int n = m_n;
+ for (int k = m_nub; k < n; ++k)
+ {
+ if (findex && findex[k] >= 0) continue;
+ if (lo[k] == -BT_INFINITY && hi[k] == BT_INFINITY)
+ {
+ btSwapProblem(m_A, m_x, m_b, m_w, lo, hi, 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 int nub = m_nub;
+ {
+ btScalar *Lrow = m_L;
+ const int nskip = m_nskip;
+ for (int j = 0; j < nub; Lrow += nskip, ++j) memcpy(Lrow, BTAROW(j), (j + 1) * sizeof(btScalar));
+ }
+ btFactorLDLT(m_L, m_d, nub, m_nskip);
+ memcpy(m_x, m_b, nub * sizeof(btScalar));
+ btSolveLDLT(m_L, m_d, m_x, nub, m_nskip);
+ btSetZero(m_w, nub);
+ {
+ int *C = m_C;
+ for (int 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 int nub = m_nub;
+ int *findex = m_findex;
+ int num_at_end = 0;
+ for (int k = m_n - 1; k >= nub; k--)
+ {
+ if (findex[k] >= 0)
+ {
+ btSwapProblem(m_A, m_x, m_b, m_w, m_lo, m_hi, 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 int n = m_n;
const int nub = m_nub;
@@ -1347,734 +1383,776 @@ btLCP::btLCP (int _n, int _nskip, int _nub, btScalar *_Adata, btScalar *_x, btSc
*/
}
-
-void btLCP::transfer_i_to_C (int i)
+void btLCP::transfer_i_to_C(int i)
{
- {
- if (m_nC > 0) {
- // ell,Dell were computed by solve1(). note, ell = D \ L1solve (L,A(i,C))
- {
- const int nC = m_nC;
- btScalar *const Ltgt = m_L + nC*m_nskip, *ell = m_ell;
- for (int j=0; j<nC; ++j) Ltgt[j] = ell[j];
- }
- const int nC = m_nC;
- m_d[nC] = btRecip (BTAROW(i)[i] - btLargeDot(m_ell,m_Dell,nC));
- }
- else {
- m_d[0] = btRecip (BTAROW(i)[i]);
- }
-
- btSwapProblem (m_A,m_x,m_b,m_w,m_lo,m_hi,m_p,m_state,m_findex,m_n,m_nC,i,m_nskip,1);
+ {
+ if (m_nC > 0)
+ {
+ // ell,Dell were computed by solve1(). note, ell = D \ L1solve (L,A(i,C))
+ {
+ const int nC = m_nC;
+ btScalar *const Ltgt = m_L + nC * m_nskip, *ell = m_ell;
+ for (int j = 0; j < nC; ++j) Ltgt[j] = ell[j];
+ }
+ const int nC = m_nC;
+ m_d[nC] = btRecip(BTAROW(i)[i] - btLargeDot(m_ell, m_Dell, nC));
+ }
+ else
+ {
+ m_d[0] = btRecip(BTAROW(i)[i]);
+ }
- const int nC = m_nC;
- m_C[nC] = nC;
- m_nC = nC + 1; // nC value is outdated after this line
- }
+ btSwapProblem(m_A, m_x, m_b, m_w, m_lo, m_hi, m_p, m_state, m_findex, m_n, m_nC, i, m_nskip, 1);
+ const int nC = m_nC;
+ m_C[nC] = nC;
+ m_nC = nC + 1; // nC value is outdated after this line
+ }
}
-
-void btLCP::transfer_i_from_N_to_C (int i)
+void btLCP::transfer_i_from_N_to_C(int i)
{
- {
- if (m_nC > 0) {
- {
- btScalar *const aptr = BTAROW(i);
- btScalar *Dell = m_Dell;
- const int *C = m_C;
-# ifdef BTNUB_OPTIMIZATIONS
- // if nub>0, initial part of aptr unpermuted
- const int nub = m_nub;
- int j=0;
- for ( ; j<nub; ++j) Dell[j] = aptr[j];
- const int nC = m_nC;
- for ( ; j<nC; ++j) Dell[j] = aptr[C[j]];
-# else
- const int nC = m_nC;
- for (int j=0; j<nC; ++j) Dell[j] = aptr[C[j]];
-# endif
- }
- btSolveL1 (m_L,m_Dell,m_nC,m_nskip);
- {
- const int nC = m_nC;
- btScalar *const Ltgt = m_L + nC*m_nskip;
- btScalar *ell = m_ell, *Dell = m_Dell, *d = m_d;
- for (int j=0; j<nC; ++j) Ltgt[j] = ell[j] = Dell[j] * d[j];
- }
- const int nC = m_nC;
- m_d[nC] = btRecip (BTAROW(i)[i] - btLargeDot(m_ell,m_Dell,nC));
- }
- else {
- m_d[0] = btRecip (BTAROW(i)[i]);
- }
-
- btSwapProblem (m_A,m_x,m_b,m_w,m_lo,m_hi,m_p,m_state,m_findex,m_n,m_nC,i,m_nskip,1);
-
- const int nC = m_nC;
- 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.
-
+ {
+ if (m_nC > 0)
+ {
+ {
+ btScalar *const aptr = BTAROW(i);
+ btScalar *Dell = m_Dell;
+ const int *C = m_C;
+#ifdef BTNUB_OPTIMIZATIONS
+ // if nub>0, initial part of aptr unpermuted
+ const int nub = m_nub;
+ int j = 0;
+ for (; j < nub; ++j) Dell[j] = aptr[j];
+ const int nC = m_nC;
+ for (; j < nC; ++j) Dell[j] = aptr[C[j]];
+#else
+ const int nC = m_nC;
+ for (int j = 0; j < nC; ++j) Dell[j] = aptr[C[j]];
+#endif
+ }
+ btSolveL1(m_L, m_Dell, m_nC, m_nskip);
+ {
+ const int nC = m_nC;
+ btScalar *const Ltgt = m_L + nC * m_nskip;
+ btScalar *ell = m_ell, *Dell = m_Dell, *d = m_d;
+ for (int j = 0; j < nC; ++j) Ltgt[j] = ell[j] = Dell[j] * d[j];
+ }
+ const int nC = m_nC;
+ m_d[nC] = btRecip(BTAROW(i)[i] - btLargeDot(m_ell, m_Dell, nC));
+ }
+ else
+ {
+ m_d[0] = btRecip(BTAROW(i)[i]);
+ }
+
+ btSwapProblem(m_A, m_x, m_b, m_w, m_lo, m_hi, m_p, m_state, m_findex, m_n, m_nC, i, m_nskip, 1);
+
+ const int nC = m_nC;
+ 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.
}
-void btRemoveRowCol (btScalar *A, int n, int nskip, int r)
+void btRemoveRowCol(btScalar *A, int n, int nskip, int r)
{
- btAssert(A && n > 0 && nskip >= n && r >= 0 && r < n);
- if (r >= n-1) return;
- if (r > 0) {
- {
- const size_t move_size = (n-r-1)*sizeof(btScalar);
- btScalar *Adst = A + r;
- for (int i=0; i<r; Adst+=nskip,++i) {
- btScalar *Asrc = Adst + 1;
- memmove (Adst,Asrc,move_size);
- }
- }
- {
- const size_t cpy_size = r*sizeof(btScalar);
- btScalar *Adst = A + r * nskip;
- for (int i=r; i<(n-1); ++i) {
- btScalar *Asrc = Adst + nskip;
- memcpy (Adst,Asrc,cpy_size);
- Adst = Asrc;
- }
- }
- }
- {
- const size_t cpy_size = (n-r-1)*sizeof(btScalar);
- btScalar *Adst = A + r * (nskip + 1);
- for (int i=r; i<(n-1); ++i) {
- btScalar *Asrc = Adst + (nskip + 1);
- memcpy (Adst,Asrc,cpy_size);
- Adst = Asrc - 1;
- }
- }
+ btAssert(A && n > 0 && nskip >= n && r >= 0 && r < n);
+ if (r >= n - 1) return;
+ if (r > 0)
+ {
+ {
+ const size_t move_size = (n - r - 1) * sizeof(btScalar);
+ btScalar *Adst = A + r;
+ for (int i = 0; i < r; Adst += nskip, ++i)
+ {
+ btScalar *Asrc = Adst + 1;
+ memmove(Adst, Asrc, move_size);
+ }
+ }
+ {
+ const size_t cpy_size = r * sizeof(btScalar);
+ btScalar *Adst = A + r * nskip;
+ for (int i = r; i < (n - 1); ++i)
+ {
+ btScalar *Asrc = Adst + nskip;
+ memcpy(Adst, Asrc, cpy_size);
+ Adst = Asrc;
+ }
+ }
+ }
+ {
+ const size_t cpy_size = (n - r - 1) * sizeof(btScalar);
+ btScalar *Adst = A + r * (nskip + 1);
+ for (int i = r; i < (n - 1); ++i)
+ {
+ btScalar *Asrc = Adst + (nskip + 1);
+ memcpy(Adst, Asrc, cpy_size);
+ Adst = Asrc - 1;
+ }
+ }
}
+void btLDLTAddTL(btScalar *L, btScalar *d, const btScalar *a, int n, int nskip, btAlignedObjectArray<btScalar> &scratch)
+{
+ btAssert(L && d && a && n > 0 && nskip >= n);
+ if (n < 2) return;
+ scratch.resize(2 * nskip);
+ btScalar *W1 = &scratch[0];
+ btScalar *W2 = W1 + nskip;
-void btLDLTAddTL (btScalar *L, btScalar *d, const btScalar *a, int n, int nskip, btAlignedObjectArray<btScalar>& scratch)
-{
- btAssert (L && d && a && n > 0 && nskip >= n);
-
- if (n < 2) return;
- scratch.resize(2*nskip);
- btScalar *W1 = &scratch[0];
-
- btScalar *W2 = W1 + nskip;
-
- W1[0] = btScalar(0.0);
- W2[0] = btScalar(0.0);
- for (int j=1; j<n; ++j) {
- W1[j] = W2[j] = (btScalar) (a[j] * SIMDSQRT12);
- }
- btScalar W11 = (btScalar) ((btScalar(0.5)*a[0]+1)*SIMDSQRT12);
- btScalar W21 = (btScalar) ((btScalar(0.5)*a[0]-1)*SIMDSQRT12);
-
- btScalar alpha1 = btScalar(1.0);
- btScalar alpha2 = btScalar(1.0);
+ W1[0] = btScalar(0.0);
+ W2[0] = btScalar(0.0);
+ for (int j = 1; j < n; ++j)
+ {
+ W1[j] = W2[j] = (btScalar)(a[j] * SIMDSQRT12);
+ }
+ btScalar W11 = (btScalar)((btScalar(0.5) * a[0] + 1) * SIMDSQRT12);
+ btScalar W21 = (btScalar)((btScalar(0.5) * a[0] - 1) * SIMDSQRT12);
- {
- btScalar dee = d[0];
- btScalar alphanew = alpha1 + (W11*W11)*dee;
- btAssert(alphanew != btScalar(0.0));
- dee /= alphanew;
- btScalar gamma1 = W11 * dee;
- dee *= alpha1;
- alpha1 = alphanew;
- alphanew = alpha2 - (W21*W21)*dee;
- dee /= alphanew;
- //btScalar gamma2 = W21 * dee;
- alpha2 = alphanew;
- btScalar k1 = btScalar(1.0) - W21*gamma1;
- btScalar k2 = W21*gamma1*W11 - W21;
- btScalar *ll = L + nskip;
- for (int p=1; p<n; ll+=nskip, ++p) {
- btScalar Wp = W1[p];
- btScalar ell = *ll;
- W1[p] = Wp - W11*ell;
- W2[p] = k1*Wp + k2*ell;
- }
- }
+ btScalar alpha1 = btScalar(1.0);
+ btScalar alpha2 = btScalar(1.0);
- btScalar *ll = L + (nskip + 1);
- for (int j=1; j<n; ll+=nskip+1, ++j) {
- btScalar k1 = W1[j];
- btScalar k2 = W2[j];
-
- btScalar dee = d[j];
- btScalar alphanew = alpha1 + (k1*k1)*dee;
- btAssert(alphanew != btScalar(0.0));
- dee /= alphanew;
- btScalar gamma1 = k1 * dee;
- dee *= alpha1;
- alpha1 = alphanew;
- alphanew = alpha2 - (k2*k2)*dee;
- dee /= alphanew;
- btScalar gamma2 = k2 * dee;
- dee *= alpha2;
- d[j] = dee;
- alpha2 = alphanew;
-
- btScalar *l = ll + nskip;
- for (int p=j+1; p<n; l+=nskip, ++p) {
- btScalar ell = *l;
- btScalar Wp = W1[p] - k1 * ell;
- ell += gamma1 * Wp;
- W1[p] = Wp;
- Wp = W2[p] - k2 * ell;
- ell -= gamma2 * Wp;
- W2[p] = Wp;
- *l = ell;
- }
- }
+ {
+ btScalar dee = d[0];
+ btScalar alphanew = alpha1 + (W11 * W11) * dee;
+ btAssert(alphanew != btScalar(0.0));
+ dee /= alphanew;
+ btScalar gamma1 = W11 * dee;
+ dee *= alpha1;
+ alpha1 = alphanew;
+ alphanew = alpha2 - (W21 * W21) * dee;
+ dee /= alphanew;
+ //btScalar gamma2 = W21 * dee;
+ alpha2 = alphanew;
+ btScalar k1 = btScalar(1.0) - W21 * gamma1;
+ btScalar k2 = W21 * gamma1 * W11 - W21;
+ btScalar *ll = L + nskip;
+ for (int p = 1; p < n; ll += nskip, ++p)
+ {
+ btScalar Wp = W1[p];
+ btScalar ell = *ll;
+ W1[p] = Wp - W11 * ell;
+ W2[p] = k1 * Wp + k2 * ell;
+ }
+ }
+
+ btScalar *ll = L + (nskip + 1);
+ for (int j = 1; j < n; ll += nskip + 1, ++j)
+ {
+ btScalar k1 = W1[j];
+ btScalar k2 = W2[j];
+
+ btScalar dee = d[j];
+ btScalar alphanew = alpha1 + (k1 * k1) * dee;
+ btAssert(alphanew != btScalar(0.0));
+ dee /= alphanew;
+ btScalar gamma1 = k1 * dee;
+ dee *= alpha1;
+ alpha1 = alphanew;
+ alphanew = alpha2 - (k2 * k2) * dee;
+ dee /= alphanew;
+ btScalar gamma2 = k2 * dee;
+ dee *= alpha2;
+ d[j] = dee;
+ alpha2 = alphanew;
+
+ btScalar *l = ll + nskip;
+ for (int p = j + 1; p < n; l += nskip, ++p)
+ {
+ btScalar ell = *l;
+ btScalar Wp = W1[p] - k1 * ell;
+ ell += gamma1 * Wp;
+ W1[p] = Wp;
+ Wp = W2[p] - k2 * ell;
+ ell -= gamma2 * Wp;
+ W2[p] = Wp;
+ *l = ell;
+ }
+ }
}
-
-#define _BTGETA(i,j) (A[i][j])
+#define _BTGETA(i, j) (A[i][j])
//#define _GETA(i,j) (A[(i)*nskip+(j)])
-#define BTGETA(i,j) ((i > j) ? _BTGETA(i,j) : _BTGETA(j,i))
+#define BTGETA(i, j) ((i > j) ? _BTGETA(i, j) : _BTGETA(j, i))
inline size_t btEstimateLDLTAddTLTmpbufSize(int nskip)
{
- return nskip * 2 * sizeof(btScalar);
+ return nskip * 2 * sizeof(btScalar);
}
-
-void btLDLTRemove (btScalar **A, const int *p, btScalar *L, btScalar *d,
- int n1, int n2, int r, int nskip, btAlignedObjectArray<btScalar>& scratch)
+void btLDLTRemove(btScalar **A, const int *p, btScalar *L, btScalar *d,
+ int n1, int n2, int r, int nskip, btAlignedObjectArray<btScalar> &scratch)
{
- btAssert(A && p && L && d && n1 > 0 && n2 > 0 && r >= 0 && r < n2 &&
- n1 >= n2 && nskip >= n1);
- #ifdef BT_DEBUG
- for (int i=0; i<n2; ++i)
+ btAssert(A && p && L && d && n1 > 0 && n2 > 0 && r >= 0 && r < n2 &&
+ n1 >= n2 && nskip >= n1);
+#ifdef BT_DEBUG
+ for (int i = 0; i < n2; ++i)
btAssert(p[i] >= 0 && p[i] < n1);
- #endif
-
- if (r==n2-1) {
- return; // deleting last row/col is easy
- }
- else {
- size_t LDLTAddTL_size = btEstimateLDLTAddTLTmpbufSize(nskip);
- btAssert(LDLTAddTL_size % sizeof(btScalar) == 0);
- scratch.resize(nskip * 2+n2);
- btScalar *tmp = &scratch[0];
- if (r==0) {
- btScalar *a = (btScalar *)((char *)tmp + LDLTAddTL_size);
- const int p_0 = p[0];
- for (int i=0; i<n2; ++i) {
- a[i] = -BTGETA(p[i],p_0);
- }
- a[0] += btScalar(1.0);
- btLDLTAddTL (L,d,a,n2,nskip,scratch);
- }
- else {
- btScalar *t = (btScalar *)((char *)tmp + LDLTAddTL_size);
- {
- btScalar *Lcurr = L + r*nskip;
- for (int i=0; i<r; ++Lcurr, ++i) {
- btAssert(d[i] != btScalar(0.0));
- t[i] = *Lcurr / d[i];
- }
- }
- btScalar *a = t + r;
- {
- btScalar *Lcurr = L + r*nskip;
- const int *pp_r = p + r, p_r = *pp_r;
- const int n2_minus_r = n2-r;
- for (int i=0; i<n2_minus_r; Lcurr+=nskip,++i) {
- a[i] = btLargeDot(Lcurr,t,r) - BTGETA(pp_r[i],p_r);
- }
- }
- a[0] += btScalar(1.0);
- btLDLTAddTL (L + r*nskip+r, d+r, a, n2-r, nskip, scratch);
- }
- }
+#endif
- // snip out row/column r from L and d
- btRemoveRowCol (L,n2,nskip,r);
- if (r < (n2-1)) memmove (d+r,d+r+1,(n2-r-1)*sizeof(btScalar));
+ if (r == n2 - 1)
+ {
+ return; // deleting last row/col is easy
+ }
+ else
+ {
+ size_t LDLTAddTL_size = btEstimateLDLTAddTLTmpbufSize(nskip);
+ btAssert(LDLTAddTL_size % sizeof(btScalar) == 0);
+ scratch.resize(nskip * 2 + n2);
+ btScalar *tmp = &scratch[0];
+ if (r == 0)
+ {
+ btScalar *a = (btScalar *)((char *)tmp + LDLTAddTL_size);
+ const int p_0 = p[0];
+ for (int i = 0; i < n2; ++i)
+ {
+ a[i] = -BTGETA(p[i], p_0);
+ }
+ a[0] += btScalar(1.0);
+ btLDLTAddTL(L, d, a, n2, nskip, scratch);
+ }
+ else
+ {
+ btScalar *t = (btScalar *)((char *)tmp + LDLTAddTL_size);
+ {
+ btScalar *Lcurr = L + r * nskip;
+ for (int i = 0; i < r; ++Lcurr, ++i)
+ {
+ btAssert(d[i] != btScalar(0.0));
+ t[i] = *Lcurr / d[i];
+ }
+ }
+ btScalar *a = t + r;
+ {
+ btScalar *Lcurr = L + r * nskip;
+ const int *pp_r = p + r, p_r = *pp_r;
+ const int n2_minus_r = n2 - r;
+ for (int i = 0; i < n2_minus_r; Lcurr += nskip, ++i)
+ {
+ a[i] = btLargeDot(Lcurr, t, r) - BTGETA(pp_r[i], p_r);
+ }
+ }
+ a[0] += btScalar(1.0);
+ btLDLTAddTL(L + r * nskip + r, d + r, a, n2 - r, nskip, scratch);
+ }
+ }
+
+ // snip out row/column r from L and d
+ btRemoveRowCol(L, n2, nskip, r);
+ if (r < (n2 - 1)) memmove(d + r, d + r + 1, (n2 - r - 1) * sizeof(btScalar));
}
-
-void btLCP::transfer_i_from_C_to_N (int i, btAlignedObjectArray<btScalar>& scratch)
+void btLCP::transfer_i_from_C_to_N(int i, btAlignedObjectArray<btScalar> &scratch)
{
- {
- int *C = m_C;
- // remove a row/column from the factorization, and adjust the
- // indexes (black magic!)
- int last_idx = -1;
- const int nC = m_nC;
- int j = 0;
- for ( ; j<nC; ++j) {
- if (C[j]==nC-1) {
- last_idx = j;
- }
- if (C[j]==i) {
- btLDLTRemove (m_A,C,m_L,m_d,m_n,nC,j,m_nskip,scratch);
- int k;
- if (last_idx == -1) {
- for (k=j+1 ; k<nC; ++k) {
- if (C[k]==nC-1) {
- break;
- }
- }
- btAssert (k < nC);
- }
- else {
- k = last_idx;
- }
- C[k] = C[j];
- if (j < (nC-1)) memmove (C+j,C+j+1,(nC-j-1)*sizeof(int));
- break;
- }
- }
- btAssert (j < nC);
-
- btSwapProblem (m_A,m_x,m_b,m_w,m_lo,m_hi,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
- }
-
+ {
+ int *C = m_C;
+ // remove a row/column from the factorization, and adjust the
+ // indexes (black magic!)
+ int last_idx = -1;
+ const int nC = m_nC;
+ int j = 0;
+ for (; j < nC; ++j)
+ {
+ if (C[j] == nC - 1)
+ {
+ last_idx = j;
+ }
+ if (C[j] == i)
+ {
+ btLDLTRemove(m_A, C, m_L, m_d, m_n, nC, j, m_nskip, scratch);
+ int k;
+ if (last_idx == -1)
+ {
+ for (k = j + 1; k < nC; ++k)
+ {
+ if (C[k] == nC - 1)
+ {
+ break;
+ }
+ }
+ btAssert(k < nC);
+ }
+ else
+ {
+ k = last_idx;
+ }
+ C[k] = C[j];
+ if (j < (nC - 1)) memmove(C + j, C + j + 1, (nC - j - 1) * sizeof(int));
+ break;
+ }
+ }
+ btAssert(j < nC);
+
+ btSwapProblem(m_A, m_x, m_b, m_w, m_lo, m_hi, 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
+ }
}
-
-void btLCP::pN_equals_ANC_times_qC (btScalar *p, btScalar *q)
+void btLCP::pN_equals_ANC_times_qC(btScalar *p, btScalar *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 int nC = m_nC;
- btScalar *ptgt = p + nC;
- const int nN = m_nN;
- for (int i=0; i<nN; ++i) {
- ptgt[i] = btLargeDot (BTAROW(i+nC),q,nC);
- }
+ // 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 int nC = m_nC;
+ btScalar *ptgt = p + nC;
+ const int nN = m_nN;
+ for (int i = 0; i < nN; ++i)
+ {
+ ptgt[i] = btLargeDot(BTAROW(i + nC), q, nC);
+ }
}
-
-void btLCP::pN_plusequals_ANi (btScalar *p, int i, int sign)
+void btLCP::pN_plusequals_ANi(btScalar *p, int i, int sign)
{
- const int nC = m_nC;
- btScalar *aptr = BTAROW(i) + nC;
- btScalar *ptgt = p + nC;
- if (sign > 0) {
- const int nN = m_nN;
- for (int j=0; j<nN; ++j) ptgt[j] += aptr[j];
- }
- else {
- const int nN = m_nN;
- for (int j=0; j<nN; ++j) ptgt[j] -= aptr[j];
- }
+ const int nC = m_nC;
+ btScalar *aptr = BTAROW(i) + nC;
+ btScalar *ptgt = p + nC;
+ if (sign > 0)
+ {
+ const int nN = m_nN;
+ for (int j = 0; j < nN; ++j) ptgt[j] += aptr[j];
+ }
+ else
+ {
+ const int nN = m_nN;
+ for (int j = 0; j < nN; ++j) ptgt[j] -= aptr[j];
+ }
}
-void btLCP::pC_plusequals_s_times_qC (btScalar *p, btScalar s, btScalar *q)
+void btLCP::pC_plusequals_s_times_qC(btScalar *p, btScalar s, btScalar *q)
{
- const int nC = m_nC;
- for (int i=0; i<nC; ++i) {
- p[i] += s*q[i];
- }
+ const int nC = m_nC;
+ for (int i = 0; i < nC; ++i)
+ {
+ p[i] += s * q[i];
+ }
}
-void btLCP::pN_plusequals_s_times_qN (btScalar *p, btScalar s, btScalar *q)
+void btLCP::pN_plusequals_s_times_qN(btScalar *p, btScalar s, btScalar *q)
{
- const int nC = m_nC;
- btScalar *ptgt = p + nC, *qsrc = q + nC;
- const int nN = m_nN;
- for (int i=0; i<nN; ++i) {
- ptgt[i] += s*qsrc[i];
- }
+ const int nC = m_nC;
+ btScalar *ptgt = p + nC, *qsrc = q + nC;
+ const int nN = m_nN;
+ for (int i = 0; i < nN; ++i)
+ {
+ ptgt[i] += s * qsrc[i];
+ }
}
-void btLCP::solve1 (btScalar *a, int i, int dir, int only_transfer)
+void btLCP::solve1(btScalar *a, int i, int dir, 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.
-
- if (m_nC > 0) {
- {
- btScalar *Dell = m_Dell;
- int *C = m_C;
- btScalar *aptr = BTAROW(i);
-# ifdef BTNUB_OPTIMIZATIONS
- // if nub>0, initial part of aptr[] is guaranteed unpermuted
- const int nub = m_nub;
- int j=0;
- for ( ; j<nub; ++j) Dell[j] = aptr[j];
- const int nC = m_nC;
- for ( ; j<nC; ++j) Dell[j] = aptr[C[j]];
-# else
- const int nC = m_nC;
- for (int j=0; j<nC; ++j) Dell[j] = aptr[C[j]];
-# endif
- }
- btSolveL1 (m_L,m_Dell,m_nC,m_nskip);
- {
- btScalar *ell = m_ell, *Dell = m_Dell, *d = m_d;
- const int nC = m_nC;
- for (int j=0; j<nC; ++j) ell[j] = Dell[j] * d[j];
- }
+ // 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.
- if (!only_transfer) {
- btScalar *tmp = m_tmp, *ell = m_ell;
- {
- const int nC = m_nC;
- for (int j=0; j<nC; ++j) tmp[j] = ell[j];
- }
- btSolveL1T (m_L,tmp,m_nC,m_nskip);
- if (dir > 0) {
- int *C = m_C;
- btScalar *tmp = m_tmp;
- const int nC = m_nC;
- for (int j=0; j<nC; ++j) a[C[j]] = -tmp[j];
- } else {
- int *C = m_C;
- btScalar *tmp = m_tmp;
- const int nC = m_nC;
- for (int j=0; j<nC; ++j) a[C[j]] = tmp[j];
- }
- }
- }
-}
+ if (m_nC > 0)
+ {
+ {
+ btScalar *Dell = m_Dell;
+ int *C = m_C;
+ btScalar *aptr = BTAROW(i);
+#ifdef BTNUB_OPTIMIZATIONS
+ // if nub>0, initial part of aptr[] is guaranteed unpermuted
+ const int nub = m_nub;
+ int j = 0;
+ for (; j < nub; ++j) Dell[j] = aptr[j];
+ const int nC = m_nC;
+ for (; j < nC; ++j) Dell[j] = aptr[C[j]];
+#else
+ const int nC = m_nC;
+ for (int j = 0; j < nC; ++j) Dell[j] = aptr[C[j]];
+#endif
+ }
+ btSolveL1(m_L, m_Dell, m_nC, m_nskip);
+ {
+ btScalar *ell = m_ell, *Dell = m_Dell, *d = m_d;
+ const int nC = m_nC;
+ for (int j = 0; j < nC; ++j) ell[j] = Dell[j] * d[j];
+ }
+ if (!only_transfer)
+ {
+ btScalar *tmp = m_tmp, *ell = m_ell;
+ {
+ const int nC = m_nC;
+ for (int j = 0; j < nC; ++j) tmp[j] = ell[j];
+ }
+ btSolveL1T(m_L, tmp, m_nC, m_nskip);
+ if (dir > 0)
+ {
+ int *C = m_C;
+ btScalar *tmp = m_tmp;
+ const int nC = m_nC;
+ for (int j = 0; j < nC; ++j) a[C[j]] = -tmp[j];
+ }
+ else
+ {
+ int *C = m_C;
+ btScalar *tmp = m_tmp;
+ const int nC = m_nC;
+ for (int j = 0; j < nC; ++j) a[C[j]] = tmp[j];
+ }
+ }
+ }
+}
void btLCP::unpermute()
{
- // now we have to un-permute x and w
- {
- memcpy (m_tmp,m_x,m_n*sizeof(btScalar));
- btScalar *x = m_x, *tmp = m_tmp;
- const int *p = m_p;
- const int n = m_n;
- for (int j=0; j<n; ++j) x[p[j]] = tmp[j];
- }
- {
- memcpy (m_tmp,m_w,m_n*sizeof(btScalar));
- btScalar *w = m_w, *tmp = m_tmp;
- const int *p = m_p;
- const int n = m_n;
- for (int j=0; j<n; ++j) w[p[j]] = tmp[j];
- }
+ // now we have to un-permute x and w
+ {
+ memcpy(m_tmp, m_x, m_n * sizeof(btScalar));
+ btScalar *x = m_x, *tmp = m_tmp;
+ const int *p = m_p;
+ const int n = m_n;
+ for (int j = 0; j < n; ++j) x[p[j]] = tmp[j];
+ }
+ {
+ memcpy(m_tmp, m_w, m_n * sizeof(btScalar));
+ btScalar *w = m_w, *tmp = m_tmp;
+ const int *p = m_p;
+ const int n = m_n;
+ for (int j = 0; j < n; ++j) w[p[j]] = tmp[j];
+ }
}
-#endif // btLCP_FAST
-
+#endif // btLCP_FAST
//***************************************************************************
// an optimized Dantzig LCP driver routine for the lo-hi LCP problem.
-bool btSolveDantzigLCP (int n, btScalar *A, btScalar *x, btScalar *b,
- btScalar* outer_w, int nub, btScalar *lo, btScalar *hi, int *findex, btDantzigScratchMemory& scratchMem)
+bool btSolveDantzigLCP(int n, btScalar *A, btScalar *x, btScalar *b,
+ btScalar *outer_w, int nub, btScalar *lo, btScalar *hi, int *findex, btDantzigScratchMemory &scratchMem)
{
s_error = false;
-// printf("btSolveDantzigLCP n=%d\n",n);
- btAssert (n>0 && A && x && b && lo && hi && nub >= 0 && nub <= n);
- btAssert(outer_w);
+ // printf("btSolveDantzigLCP n=%d\n",n);
+ btAssert(n > 0 && A && x && b && lo && hi && nub >= 0 && nub <= n);
+ btAssert(outer_w);
#ifdef BT_DEBUG
- {
- // check restrictions on lo and hi
- for (int k=0; k<n; ++k)
- btAssert (lo[k] <= 0 && hi[k] >= 0);
- }
-# endif
-
-
- // if all the variables are unbounded then we can just factor, solve,
- // and return
- if (nub >= n)
- {
-
-
- int nskip = (n);
- btFactorLDLT (A, outer_w, n, nskip);
- btSolveLDLT (A, outer_w, b, n, nskip);
- memcpy (x, b, n*sizeof(btScalar));
-
- return !s_error;
- }
-
- const int nskip = (n);
- scratchMem.L.resize(n*nskip);
-
- scratchMem.d.resize(n);
-
- btScalar *w = outer_w;
- scratchMem.delta_w.resize(n);
- scratchMem.delta_x.resize(n);
- scratchMem.Dell.resize(n);
- scratchMem.ell.resize(n);
- scratchMem.Arows.resize(n);
- scratchMem.p.resize(n);
- scratchMem.C.resize(n);
-
- // for i in N, state[i] is 0 if x(i)==lo(i) or 1 if x(i)==hi(i)
- scratchMem.state.resize(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!
- btLCP lcp(n,nskip,nub,A,x,b,w,lo,hi,&scratchMem.L[0],&scratchMem.d[0],&scratchMem.Dell[0],&scratchMem.ell[0],&scratchMem.delta_w[0],&scratchMem.state[0],findex,&scratchMem.p[0],&scratchMem.C[0],&scratchMem.Arows[0]);
- int 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 (int i=adj_nub; i<n; ++i)
- {
- 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 (int j=0; j<n; ++j) scratchMem.delta_w[scratchMem.p[j]] = x[j];
-
- // set lo and hi values
- for (int k=i; k<n; ++k) {
- btScalar wfk = scratchMem.delta_w[findex[k]];
- if (wfk == 0) {
- hi[k] = 0;
- lo[k] = 0;
- }
- else {
- hi[k] = btFabs (hi[k] * wfk);
- lo[k] = -hi[k];
- }
- }
- 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.
- w[i] = lcp.AiC_times_qC (i,x) + lcp.AiN_times_qN (i,x) - b[i];
-
- // 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.
-
- // see if x(i),w(i) is in a valid region
- if (lo[i]==0 && w[i] >= 0) {
- lcp.transfer_i_to_N (i);
- scratchMem.state[i] = false;
- }
- else if (hi[i]==0 && w[i] <= 0) {
- lcp.transfer_i_to_N (i);
- scratchMem.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 (&scratchMem.delta_x[0],i,0,1);
-
- lcp.transfer_i_to_C (i);
- }
- else {
- // we must push x(i) and w(i)
- for (;;) {
- int dir;
- btScalar dirf;
- // find direction to push on x(i)
- if (w[i] <= 0) {
- dir = 1;
- dirf = btScalar(1.0);
- }
- else {
- dir = -1;
- dirf = btScalar(-1.0);
- }
-
- // compute: delta_x(C) = -dir*A(C,C)\A(C,i)
- lcp.solve1 (&scratchMem.delta_x[0],i,dir);
-
- // note that delta_x[i] = dirf, 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 (&scratchMem.delta_w[0],&scratchMem.delta_x[0]);
- lcp.pN_plusequals_ANi (&scratchMem.delta_w[0],i,dir);
- scratchMem.delta_w[i] = lcp.AiC_times_qC (i,&scratchMem.delta_x[0]) + lcp.Aii(i)*dirf;
-
- // 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
- int si = 0; // si = index to switch if cmd>3
- btScalar s = -w[i]/scratchMem.delta_w[i];
- if (dir > 0) {
- if (hi[i] < BT_INFINITY) {
- btScalar s2 = (hi[i]-x[i])*dirf; // was (hi[i]-x[i])/dirf // step to x(i)=hi(i)
- if (s2 < s) {
- s = s2;
- cmd = 3;
- }
- }
- }
- else {
- if (lo[i] > -BT_INFINITY) {
- btScalar s2 = (lo[i]-x[i])*dirf; // was (lo[i]-x[i])/dirf // step to x(i)=lo(i)
- if (s2 < s) {
- s = s2;
- cmd = 2;
- }
- }
- }
-
- {
- const int numN = lcp.numN();
- for (int k=0; k < numN; ++k) {
- const int indexN_k = lcp.indexN(k);
- if (!scratchMem.state[indexN_k] ? scratchMem.delta_w[indexN_k] < 0 : scratchMem.delta_w[indexN_k] > 0) {
- // don't bother checking if lo=hi=0
- if (lo[indexN_k] == 0 && hi[indexN_k] == 0) continue;
- btScalar s2 = -w[indexN_k] / scratchMem.delta_w[indexN_k];
- if (s2 < s) {
- s = s2;
- cmd = 4;
- si = indexN_k;
- }
- }
- }
- }
-
- {
- const int numC = lcp.numC();
- for (int k=adj_nub; k < numC; ++k) {
- const int indexC_k = lcp.indexC(k);
- if (scratchMem.delta_x[indexC_k] < 0 && lo[indexC_k] > -BT_INFINITY) {
- btScalar s2 = (lo[indexC_k]-x[indexC_k]) / scratchMem.delta_x[indexC_k];
- if (s2 < s) {
- s = s2;
- cmd = 5;
- si = indexC_k;
- }
- }
- if (scratchMem.delta_x[indexC_k] > 0 && hi[indexC_k] < BT_INFINITY) {
- btScalar s2 = (hi[indexC_k]-x[indexC_k]) / scratchMem.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 <= btScalar(0.0))
- {
-// printf("LCP internal error, s <= 0 (s=%.4e)",(double)s);
- if (i < n) {
- btSetZero (x+i,n-i);
- btSetZero (w+i,n-i);
- }
- s_error = true;
- break;
- }
-
- // apply x = x + s * delta_x
- lcp.pC_plusequals_s_times_qC (x, s, &scratchMem.delta_x[0]);
- x[i] += s * dirf;
-
- // apply w = w + s * delta_w
- lcp.pN_plusequals_s_times_qN (w, s, &scratchMem.delta_w[0]);
- w[i] += s * scratchMem.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
- x[i] = lo[i];
- scratchMem.state[i] = false;
- lcp.transfer_i_to_N (i);
- break;
- case 3: // done
- x[i] = hi[i];
- scratchMem.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
- x[si] = lo[si];
- scratchMem.state[si] = false;
- lcp.transfer_i_from_C_to_N (si, scratchMem.m_scratch);
- break;
- case 6: // keep going
- x[si] = hi[si];
- scratchMem.state[si] = true;
- lcp.transfer_i_from_C_to_N (si, scratchMem.m_scratch);
- break;
- }
-
- if (cmd <= 3) break;
- } // for (;;)
- } // else
-
- if (s_error)
{
- break;
- }
- } // for (int i=adj_nub; i<n; ++i)
+ // check restrictions on lo and hi
+ for (int k = 0; k < n; ++k)
+ btAssert(lo[k] <= 0 && hi[k] >= 0);
+ }
+#endif
- lcp.unpermute();
+ // if all the variables are unbounded then we can just factor, solve,
+ // and return
+ if (nub >= n)
+ {
+ int nskip = (n);
+ btFactorLDLT(A, outer_w, n, nskip);
+ btSolveLDLT(A, outer_w, b, n, nskip);
+ memcpy(x, b, n * sizeof(btScalar));
+
+ return !s_error;
+ }
+
+ const int nskip = (n);
+ scratchMem.L.resize(n * nskip);
+
+ scratchMem.d.resize(n);
+
+ btScalar *w = outer_w;
+ scratchMem.delta_w.resize(n);
+ scratchMem.delta_x.resize(n);
+ scratchMem.Dell.resize(n);
+ scratchMem.ell.resize(n);
+ scratchMem.Arows.resize(n);
+ scratchMem.p.resize(n);
+ scratchMem.C.resize(n);
+
+ // for i in N, state[i] is 0 if x(i)==lo(i) or 1 if x(i)==hi(i)
+ scratchMem.state.resize(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!
+ btLCP lcp(n, nskip, nub, A, x, b, w, lo, hi, &scratchMem.L[0], &scratchMem.d[0], &scratchMem.Dell[0], &scratchMem.ell[0], &scratchMem.delta_w[0], &scratchMem.state[0], findex, &scratchMem.p[0], &scratchMem.C[0], &scratchMem.Arows[0]);
+ int 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 (int i = adj_nub; i < n; ++i)
+ {
+ 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 (int j = 0; j < n; ++j) scratchMem.delta_w[scratchMem.p[j]] = x[j];
+
+ // set lo and hi values
+ for (int k = i; k < n; ++k)
+ {
+ btScalar wfk = scratchMem.delta_w[findex[k]];
+ if (wfk == 0)
+ {
+ hi[k] = 0;
+ lo[k] = 0;
+ }
+ else
+ {
+ hi[k] = btFabs(hi[k] * wfk);
+ lo[k] = -hi[k];
+ }
+ }
+ 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.
+ w[i] = lcp.AiC_times_qC(i, x) + lcp.AiN_times_qN(i, x) - b[i];
+
+ // 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.
+
+ // see if x(i),w(i) is in a valid region
+ if (lo[i] == 0 && w[i] >= 0)
+ {
+ lcp.transfer_i_to_N(i);
+ scratchMem.state[i] = false;
+ }
+ else if (hi[i] == 0 && w[i] <= 0)
+ {
+ lcp.transfer_i_to_N(i);
+ scratchMem.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(&scratchMem.delta_x[0], i, 0, 1);
+
+ lcp.transfer_i_to_C(i);
+ }
+ else
+ {
+ // we must push x(i) and w(i)
+ for (;;)
+ {
+ int dir;
+ btScalar dirf;
+ // find direction to push on x(i)
+ if (w[i] <= 0)
+ {
+ dir = 1;
+ dirf = btScalar(1.0);
+ }
+ else
+ {
+ dir = -1;
+ dirf = btScalar(-1.0);
+ }
+
+ // compute: delta_x(C) = -dir*A(C,C)\A(C,i)
+ lcp.solve1(&scratchMem.delta_x[0], i, dir);
+
+ // note that delta_x[i] = dirf, 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(&scratchMem.delta_w[0], &scratchMem.delta_x[0]);
+ lcp.pN_plusequals_ANi(&scratchMem.delta_w[0], i, dir);
+ scratchMem.delta_w[i] = lcp.AiC_times_qC(i, &scratchMem.delta_x[0]) + lcp.Aii(i) * dirf;
+
+ // 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
+ int si = 0; // si = index to switch if cmd>3
+ btScalar s = -w[i] / scratchMem.delta_w[i];
+ if (dir > 0)
+ {
+ if (hi[i] < BT_INFINITY)
+ {
+ btScalar s2 = (hi[i] - x[i]) * dirf; // was (hi[i]-x[i])/dirf // step to x(i)=hi(i)
+ if (s2 < s)
+ {
+ s = s2;
+ cmd = 3;
+ }
+ }
+ }
+ else
+ {
+ if (lo[i] > -BT_INFINITY)
+ {
+ btScalar s2 = (lo[i] - x[i]) * dirf; // was (lo[i]-x[i])/dirf // step to x(i)=lo(i)
+ if (s2 < s)
+ {
+ s = s2;
+ cmd = 2;
+ }
+ }
+ }
+
+ {
+ const int numN = lcp.numN();
+ for (int k = 0; k < numN; ++k)
+ {
+ const int indexN_k = lcp.indexN(k);
+ if (!scratchMem.state[indexN_k] ? scratchMem.delta_w[indexN_k] < 0 : scratchMem.delta_w[indexN_k] > 0)
+ {
+ // don't bother checking if lo=hi=0
+ if (lo[indexN_k] == 0 && hi[indexN_k] == 0) continue;
+ btScalar s2 = -w[indexN_k] / scratchMem.delta_w[indexN_k];
+ if (s2 < s)
+ {
+ s = s2;
+ cmd = 4;
+ si = indexN_k;
+ }
+ }
+ }
+ }
+
+ {
+ const int numC = lcp.numC();
+ for (int k = adj_nub; k < numC; ++k)
+ {
+ const int indexC_k = lcp.indexC(k);
+ if (scratchMem.delta_x[indexC_k] < 0 && lo[indexC_k] > -BT_INFINITY)
+ {
+ btScalar s2 = (lo[indexC_k] - x[indexC_k]) / scratchMem.delta_x[indexC_k];
+ if (s2 < s)
+ {
+ s = s2;
+ cmd = 5;
+ si = indexC_k;
+ }
+ }
+ if (scratchMem.delta_x[indexC_k] > 0 && hi[indexC_k] < BT_INFINITY)
+ {
+ btScalar s2 = (hi[indexC_k] - x[indexC_k]) / scratchMem.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 <= btScalar(0.0))
+ {
+ // printf("LCP internal error, s <= 0 (s=%.4e)",(double)s);
+ if (i < n)
+ {
+ btSetZero(x + i, n - i);
+ btSetZero(w + i, n - i);
+ }
+ s_error = true;
+ break;
+ }
+
+ // apply x = x + s * delta_x
+ lcp.pC_plusequals_s_times_qC(x, s, &scratchMem.delta_x[0]);
+ x[i] += s * dirf;
+
+ // apply w = w + s * delta_w
+ lcp.pN_plusequals_s_times_qN(w, s, &scratchMem.delta_w[0]);
+ w[i] += s * scratchMem.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
+ x[i] = lo[i];
+ scratchMem.state[i] = false;
+ lcp.transfer_i_to_N(i);
+ break;
+ case 3: // done
+ x[i] = hi[i];
+ scratchMem.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
+ x[si] = lo[si];
+ scratchMem.state[si] = false;
+ lcp.transfer_i_from_C_to_N(si, scratchMem.m_scratch);
+ break;
+ case 6: // keep going
+ x[si] = hi[si];
+ scratchMem.state[si] = true;
+ lcp.transfer_i_from_C_to_N(si, scratchMem.m_scratch);
+ break;
+ }
+
+ if (cmd <= 3) break;
+ } // for (;;)
+ } // else
+
+ if (s_error)
+ {
+ break;
+ }
+ } // for (int i=adj_nub; i<n; ++i)
+ lcp.unpermute();
- return !s_error;
+ return !s_error;
}
-
diff --git a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btDantzigLCP.h b/thirdparty/bullet/BulletDynamics/MLCPSolvers/btDantzigLCP.h
index 903832770a..8d9b2a13e9 100644
--- a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btDantzigLCP.h
+++ b/thirdparty/bullet/BulletDynamics/MLCPSolvers/btDantzigLCP.h
@@ -41,7 +41,6 @@ to be implemented. the first `nub' variables are assumed to have findex < 0.
*/
-
#ifndef _BT_LCP_H_
#define _BT_LCP_H_
@@ -49,7 +48,6 @@ to be implemented. the first `nub' variables are assumed to have findex < 0.
#include <stdio.h>
#include <assert.h>
-
#include "LinearMath/btScalar.h"
#include "LinearMath/btAlignedObjectArray.h"
@@ -62,16 +60,14 @@ struct btDantzigScratchMemory
btAlignedObjectArray<btScalar> delta_x;
btAlignedObjectArray<btScalar> Dell;
btAlignedObjectArray<btScalar> ell;
- btAlignedObjectArray<btScalar*> Arows;
+ btAlignedObjectArray<btScalar *> Arows;
btAlignedObjectArray<int> p;
btAlignedObjectArray<int> C;
btAlignedObjectArray<bool> state;
};
//return false if solving failed
-bool btSolveDantzigLCP (int n, btScalar *A, btScalar *x, btScalar *b, btScalar *w,
- int nub, btScalar *lo, btScalar *hi, int *findex,btDantzigScratchMemory& scratch);
-
-
+bool btSolveDantzigLCP(int n, btScalar *A, btScalar *x, btScalar *b, btScalar *w,
+ int nub, btScalar *lo, btScalar *hi, int *findex, btDantzigScratchMemory &scratch);
-#endif //_BT_LCP_H_
+#endif //_BT_LCP_H_
diff --git a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btDantzigSolver.h b/thirdparty/bullet/BulletDynamics/MLCPSolvers/btDantzigSolver.h
index 2a2f2d3d32..1f669751ce 100644
--- a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btDantzigSolver.h
+++ b/thirdparty/bullet/BulletDynamics/MLCPSolvers/btDantzigSolver.h
@@ -20,30 +20,28 @@ subject to the following restrictions:
#include "btMLCPSolverInterface.h"
#include "btDantzigLCP.h"
-
class btDantzigSolver : public btMLCPSolverInterface
{
protected:
-
btScalar m_acceptableUpperLimitSolution;
- btAlignedObjectArray<char> m_tempBuffer;
+ btAlignedObjectArray<char> m_tempBuffer;
btAlignedObjectArray<btScalar> m_A;
btAlignedObjectArray<btScalar> m_b;
btAlignedObjectArray<btScalar> m_x;
btAlignedObjectArray<btScalar> m_lo;
btAlignedObjectArray<btScalar> m_hi;
- btAlignedObjectArray<int> m_dependencies;
+ btAlignedObjectArray<int> m_dependencies;
btDantzigScratchMemory m_scratchMemory;
-public:
+public:
btDantzigSolver()
- :m_acceptableUpperLimitSolution(btScalar(1000))
+ : m_acceptableUpperLimitSolution(btScalar(1000))
{
}
- virtual bool solveMLCP(const btMatrixXu & A, const btVectorXu & b, btVectorXu& x, const btVectorXu & lo,const btVectorXu & hi,const btAlignedObjectArray<int>& limitDependency, int numIterations, bool useSparsity = true)
+ virtual bool solveMLCP(const btMatrixXu& A, const btVectorXu& b, btVectorXu& x, const btVectorXu& lo, const btVectorXu& hi, const btAlignedObjectArray<int>& limitDependency, int numIterations, bool useSparsity = true)
{
bool result = true;
int n = b.rows();
@@ -52,14 +50,12 @@ public:
int nub = 0;
btAlignedObjectArray<btScalar> ww;
ww.resize(n);
-
const btScalar* Aptr = A.getBufferPointer();
- m_A.resize(n*n);
- for (int i=0;i<n*n;i++)
+ m_A.resize(n * n);
+ for (int i = 0; i < n * n; i++)
{
m_A[i] = Aptr[i];
-
}
m_b.resize(n);
@@ -67,7 +63,7 @@ public:
m_lo.resize(n);
m_hi.resize(n);
m_dependencies.resize(n);
- for (int i=0;i<n;i++)
+ for (int i = 0; i < n; i++)
{
m_lo[i] = lo[i];
m_hi[i] = hi[i];
@@ -76,13 +72,12 @@ public:
m_dependencies[i] = limitDependency[i];
}
-
- result = btSolveDantzigLCP (n,&m_A[0],&m_x[0],&m_b[0],&ww[0],nub,&m_lo[0],&m_hi[0],&m_dependencies[0],m_scratchMemory);
+ result = btSolveDantzigLCP(n, &m_A[0], &m_x[0], &m_b[0], &ww[0], nub, &m_lo[0], &m_hi[0], &m_dependencies[0], m_scratchMemory);
if (!result)
return result;
-// printf("numAllocas = %d\n",numAllocas);
- for (int i=0;i<n;i++)
+ // printf("numAllocas = %d\n",numAllocas);
+ for (int i = 0; i < n; i++)
{
volatile btScalar xx = m_x[i];
if (xx != m_x[i])
@@ -98,15 +93,14 @@ public:
}
}
- for (int i=0;i<n;i++)
+ for (int i = 0; i < n; i++)
{
x[i] = m_x[i];
}
-
}
return result;
}
};
-#endif //BT_DANTZIG_SOLVER_H
+#endif //BT_DANTZIG_SOLVER_H
diff --git a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeAlgorithm.cpp b/thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeAlgorithm.cpp
index 1f4015c7c7..954ffaed75 100644
--- a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeAlgorithm.cpp
+++ b/thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeAlgorithm.cpp
@@ -19,64 +19,60 @@ subject to the following restrictions:
//Math library was replaced from fmatvec to a the file src/LinearMath/btMatrixX.h
//STL/std::vector replaced by btAlignedObjectArray
-
-
#include "btLemkeAlgorithm.h"
#undef BT_DEBUG_OSTREAM
#ifdef BT_DEBUG_OSTREAM
using namespace std;
-#endif //BT_DEBUG_OSTREAM
+#endif //BT_DEBUG_OSTREAM
btScalar btMachEps()
{
- static bool calculated=false;
+ static bool calculated = false;
static btScalar machEps = btScalar(1.);
if (!calculated)
{
- do {
+ do
+ {
machEps /= btScalar(2.0);
// If next epsilon yields 1, then break, because current
// epsilon is the machine epsilon.
- }
- while ((btScalar)(1.0 + (machEps/btScalar(2.0))) != btScalar(1.0));
-// printf( "\nCalculated Machine epsilon: %G\n", machEps );
- calculated=true;
+ } while ((btScalar)(1.0 + (machEps / btScalar(2.0))) != btScalar(1.0));
+ // printf( "\nCalculated Machine epsilon: %G\n", machEps );
+ calculated = true;
}
return machEps;
}
-btScalar btEpsRoot() {
-
+btScalar btEpsRoot()
+{
static btScalar epsroot = 0.;
static bool alreadyCalculated = false;
-
- if (!alreadyCalculated) {
+
+ if (!alreadyCalculated)
+ {
epsroot = btSqrt(btMachEps());
alreadyCalculated = true;
}
return epsroot;
}
-
-
- btVectorXu btLemkeAlgorithm::solve(unsigned int maxloops /* = 0*/)
+btVectorXu btLemkeAlgorithm::solve(unsigned int maxloops /* = 0*/)
{
-
-
- steps = 0;
+ steps = 0;
- int dim = m_q.size();
+ int dim = m_q.size();
#ifdef BT_DEBUG_OSTREAM
- if(DEBUGLEVEL >= 1) {
- cout << "Dimension = " << dim << endl;
- }
-#endif //BT_DEBUG_OSTREAM
+ if (DEBUGLEVEL >= 1)
+ {
+ cout << "Dimension = " << dim << endl;
+ }
+#endif //BT_DEBUG_OSTREAM
btVectorXu solutionVector(2 * dim);
solutionVector.setZero();
-
- //, INIT, 0.);
+
+ //, INIT, 0.);
btMatrixXu ident(dim, dim);
ident.setIdentity();
@@ -85,287 +81,289 @@ btScalar btEpsRoot() {
#endif
btMatrixXu mNeg = m_M.negative();
-
- btMatrixXu A(dim, 2 * dim + 2);
+
+ btMatrixXu A(dim, 2 * dim + 2);
//
- A.setSubMatrix(0, 0, dim - 1, dim - 1,ident);
- A.setSubMatrix(0, dim, dim - 1, 2 * dim - 1,mNeg);
+ A.setSubMatrix(0, 0, dim - 1, dim - 1, ident);
+ A.setSubMatrix(0, dim, dim - 1, 2 * dim - 1, mNeg);
A.setSubMatrix(0, 2 * dim, dim - 1, 2 * dim, -1.f);
- A.setSubMatrix(0, 2 * dim + 1, dim - 1, 2 * dim + 1,m_q);
+ A.setSubMatrix(0, 2 * dim + 1, dim - 1, 2 * dim + 1, m_q);
#ifdef BT_DEBUG_OSTREAM
cout << A << std::endl;
-#endif //BT_DEBUG_OSTREAM
+#endif //BT_DEBUG_OSTREAM
+ // btVectorXu q_;
+ // q_ >> A(0, 2 * dim + 1, dim - 1, 2 * dim + 1);
- // btVectorXu q_;
- // q_ >> A(0, 2 * dim + 1, dim - 1, 2 * dim + 1);
-
- btAlignedObjectArray<int> basis;
- //At first, all w-values are in the basis
- for (int i = 0; i < dim; i++)
- basis.push_back(i);
+ btAlignedObjectArray<int> basis;
+ //At first, all w-values are in the basis
+ for (int i = 0; i < dim; i++)
+ basis.push_back(i);
int pivotRowIndex = -1;
btScalar minValue = 1e30f;
bool greaterZero = true;
- for (int i=0;i<dim;i++)
+ for (int i = 0; i < dim; i++)
{
- btScalar v =A(i,2*dim+1);
- if (v<minValue)
+ btScalar v = A(i, 2 * dim + 1);
+ if (v < minValue)
{
- minValue=v;
+ minValue = v;
pivotRowIndex = i;
}
- if (v<0)
+ if (v < 0)
greaterZero = false;
}
-
-
- // int pivotRowIndex = q_.minIndex();//minIndex(q_); // first row is that with lowest q-value
- int z0Row = pivotRowIndex; // remember the col of z0 for ending algorithm afterwards
- int pivotColIndex = 2 * dim; // first col is that of z0
+ // int pivotRowIndex = q_.minIndex();//minIndex(q_); // first row is that with lowest q-value
+ int z0Row = pivotRowIndex; // remember the col of z0 for ending algorithm afterwards
+ int pivotColIndex = 2 * dim; // first col is that of z0
#ifdef BT_DEBUG_OSTREAM
- if (DEBUGLEVEL >= 3)
+ if (DEBUGLEVEL >= 3)
{
- // cout << "A: " << A << endl;
- cout << "pivotRowIndex " << pivotRowIndex << endl;
- cout << "pivotColIndex " << pivotColIndex << endl;
- cout << "Basis: ";
- for (int i = 0; i < basis.size(); i++)
- cout << basis[i] << " ";
- cout << endl;
- }
-#endif //BT_DEBUG_OSTREAM
+ // cout << "A: " << A << endl;
+ cout << "pivotRowIndex " << pivotRowIndex << endl;
+ cout << "pivotColIndex " << pivotColIndex << endl;
+ cout << "Basis: ";
+ for (int i = 0; i < basis.size(); i++)
+ cout << basis[i] << " ";
+ cout << endl;
+ }
+#endif //BT_DEBUG_OSTREAM
if (!greaterZero)
{
+ if (maxloops == 0)
+ {
+ maxloops = 100;
+ // maxloops = UINT_MAX; //TODO: not a really nice way, problem is: maxloops should be 2^dim (=1<<dim), but this could exceed UINT_MAX and thus the result would be 0 and therefore the lemke algorithm wouldn't start but probably would find a solution within less then UINT_MAX steps. Therefore this constant is used as a upper border right now...
+ }
- if (maxloops == 0) {
- maxloops = 100;
-// maxloops = UINT_MAX; //TODO: not a really nice way, problem is: maxloops should be 2^dim (=1<<dim), but this could exceed UINT_MAX and thus the result would be 0 and therefore the lemke algorithm wouldn't start but probably would find a solution within less then UINT_MAX steps. Therefore this constant is used as a upper border right now...
- }
-
- /*start looping*/
- for(steps = 0; steps < maxloops; steps++) {
-
- GaussJordanEliminationStep(A, pivotRowIndex, pivotColIndex, basis);
-#ifdef BT_DEBUG_OSTREAM
- if (DEBUGLEVEL >= 3) {
- // cout << "A: " << A << endl;
- cout << "pivotRowIndex " << pivotRowIndex << endl;
- cout << "pivotColIndex " << pivotColIndex << endl;
- cout << "Basis: ";
- for (int i = 0; i < basis.size(); i++)
- cout << basis[i] << " ";
- cout << endl;
- }
-#endif //BT_DEBUG_OSTREAM
-
- int pivotColIndexOld = pivotColIndex;
-
- /*find new column index */
- if (basis[pivotRowIndex] < dim) //if a w-value left the basis get in the correspondent z-value
- pivotColIndex = basis[pivotRowIndex] + dim;
- else
- //else do it the other way round and get in the corresponding w-value
- pivotColIndex = basis[pivotRowIndex] - dim;
-
- /*the column becomes part of the basis*/
- basis[pivotRowIndex] = pivotColIndexOld;
-
- pivotRowIndex = findLexicographicMinimum(A, pivotColIndex);
-
- if(z0Row == pivotRowIndex) { //if z0 leaves the basis the solution is found --> one last elimination step is necessary
- GaussJordanEliminationStep(A, pivotRowIndex, pivotColIndex, basis);
- basis[pivotRowIndex] = pivotColIndex; //update basis
- break;
- }
-
- }
+ /*start looping*/
+ for (steps = 0; steps < maxloops; steps++)
+ {
+ GaussJordanEliminationStep(A, pivotRowIndex, pivotColIndex, basis);
#ifdef BT_DEBUG_OSTREAM
- if(DEBUGLEVEL >= 1) {
- cout << "Number of loops: " << steps << endl;
- cout << "Number of maximal loops: " << maxloops << endl;
- }
-#endif //BT_DEBUG_OSTREAM
-
- if(!validBasis(basis)) {
- info = -1;
+ if (DEBUGLEVEL >= 3)
+ {
+ // cout << "A: " << A << endl;
+ cout << "pivotRowIndex " << pivotRowIndex << endl;
+ cout << "pivotColIndex " << pivotColIndex << endl;
+ cout << "Basis: ";
+ for (int i = 0; i < basis.size(); i++)
+ cout << basis[i] << " ";
+ cout << endl;
+ }
+#endif //BT_DEBUG_OSTREAM
+
+ int pivotColIndexOld = pivotColIndex;
+
+ /*find new column index */
+ if (basis[pivotRowIndex] < dim) //if a w-value left the basis get in the correspondent z-value
+ pivotColIndex = basis[pivotRowIndex] + dim;
+ else
+ //else do it the other way round and get in the corresponding w-value
+ pivotColIndex = basis[pivotRowIndex] - dim;
+
+ /*the column becomes part of the basis*/
+ basis[pivotRowIndex] = pivotColIndexOld;
+
+ pivotRowIndex = findLexicographicMinimum(A, pivotColIndex);
+
+ if (z0Row == pivotRowIndex)
+ { //if z0 leaves the basis the solution is found --> one last elimination step is necessary
+ GaussJordanEliminationStep(A, pivotRowIndex, pivotColIndex, basis);
+ basis[pivotRowIndex] = pivotColIndex; //update basis
+ break;
+ }
+ }
#ifdef BT_DEBUG_OSTREAM
- if(DEBUGLEVEL >= 1)
- cerr << "Lemke-Algorithm ended with Ray-Termination (no valid solution)." << endl;
-#endif //BT_DEBUG_OSTREAM
+ if (DEBUGLEVEL >= 1)
+ {
+ cout << "Number of loops: " << steps << endl;
+ cout << "Number of maximal loops: " << maxloops << endl;
+ }
+#endif //BT_DEBUG_OSTREAM
- return solutionVector;
- }
+ if (!validBasis(basis))
+ {
+ info = -1;
+#ifdef BT_DEBUG_OSTREAM
+ if (DEBUGLEVEL >= 1)
+ cerr << "Lemke-Algorithm ended with Ray-Termination (no valid solution)." << endl;
+#endif //BT_DEBUG_OSTREAM
- }
+ return solutionVector;
+ }
+ }
#ifdef BT_DEBUG_OSTREAM
- if (DEBUGLEVEL >= 2) {
- // cout << "A: " << A << endl;
- cout << "pivotRowIndex " << pivotRowIndex << endl;
- cout << "pivotColIndex " << pivotColIndex << endl;
- }
-#endif //BT_DEBUG_OSTREAM
-
- for (int i = 0; i < basis.size(); i++)
+ if (DEBUGLEVEL >= 2)
{
- solutionVector[basis[i]] = A(i,2*dim+1);//q_[i];
+ // cout << "A: " << A << endl;
+ cout << "pivotRowIndex " << pivotRowIndex << endl;
+ cout << "pivotColIndex " << pivotColIndex << endl;
}
+#endif //BT_DEBUG_OSTREAM
- info = 0;
+ for (int i = 0; i < basis.size(); i++)
+ {
+ solutionVector[basis[i]] = A(i, 2 * dim + 1); //q_[i];
+ }
- return solutionVector;
- }
+ info = 0;
- int btLemkeAlgorithm::findLexicographicMinimum(const btMatrixXu& A, const int & pivotColIndex) {
- int RowIndex = 0;
- int dim = A.rows();
- btAlignedObjectArray<btVectorXu> Rows;
- for (int row = 0; row < dim; row++)
- {
+ return solutionVector;
+}
- btVectorXu vec(dim + 1);
- vec.setZero();//, INIT, 0.)
- Rows.push_back(vec);
- btScalar a = A(row, pivotColIndex);
- if (a > 0) {
- Rows[row][0] = A(row, 2 * dim + 1) / a;
- Rows[row][1] = A(row, 2 * dim) / a;
- for (int j = 2; j < dim + 1; j++)
- Rows[row][j] = A(row, j - 1) / a;
+int btLemkeAlgorithm::findLexicographicMinimum(const btMatrixXu& A, const int& pivotColIndex)
+{
+ int RowIndex = 0;
+ int dim = A.rows();
+ btAlignedObjectArray<btVectorXu> Rows;
+ for (int row = 0; row < dim; row++)
+ {
+ btVectorXu vec(dim + 1);
+ vec.setZero(); //, INIT, 0.)
+ Rows.push_back(vec);
+ btScalar a = A(row, pivotColIndex);
+ if (a > 0)
+ {
+ Rows[row][0] = A(row, 2 * dim + 1) / a;
+ Rows[row][1] = A(row, 2 * dim) / a;
+ for (int j = 2; j < dim + 1; j++)
+ Rows[row][j] = A(row, j - 1) / a;
#ifdef BT_DEBUG_OSTREAM
- // if (DEBUGLEVEL) {
- // cout << "Rows(" << row << ") = " << Rows[row] << endl;
+ // if (DEBUGLEVEL) {
+ // cout << "Rows(" << row << ") = " << Rows[row] << endl;
// }
-#endif
- }
- }
-
- for (int i = 0; i < Rows.size(); i++)
- {
- if (Rows[i].nrm2() > 0.) {
-
- int j = 0;
- for (; j < Rows.size(); j++)
- {
- if(i != j)
- {
- if(Rows[j].nrm2() > 0.)
- {
- btVectorXu test(dim + 1);
- for (int ii=0;ii<dim+1;ii++)
- {
- test[ii] = Rows[j][ii] - Rows[i][ii];
- }
-
- //=Rows[j] - Rows[i]
- if (! LexicographicPositive(test))
- break;
- }
- }
- }
-
- if (j == Rows.size())
- {
- RowIndex += i;
- break;
- }
- }
- }
-
- return RowIndex;
- }
-
- bool btLemkeAlgorithm::LexicographicPositive(const btVectorXu & v)
-{
- int i = 0;
- // if (DEBUGLEVEL)
- // cout << "v " << v << endl;
+#endif
+ }
+ }
- while(i < v.size()-1 && fabs(v[i]) < btMachEps())
- i++;
- if (v[i] > 0)
- return true;
+ for (int i = 0; i < Rows.size(); i++)
+ {
+ if (Rows[i].nrm2() > 0.)
+ {
+ int j = 0;
+ for (; j < Rows.size(); j++)
+ {
+ if (i != j)
+ {
+ if (Rows[j].nrm2() > 0.)
+ {
+ btVectorXu test(dim + 1);
+ for (int ii = 0; ii < dim + 1; ii++)
+ {
+ test[ii] = Rows[j][ii] - Rows[i][ii];
+ }
+
+ //=Rows[j] - Rows[i]
+ if (!LexicographicPositive(test))
+ break;
+ }
+ }
+ }
+
+ if (j == Rows.size())
+ {
+ RowIndex += i;
+ break;
+ }
+ }
+ }
- return false;
- }
+ return RowIndex;
+}
-void btLemkeAlgorithm::GaussJordanEliminationStep(btMatrixXu& A, int pivotRowIndex, int pivotColumnIndex, const btAlignedObjectArray<int>& basis)
+bool btLemkeAlgorithm::LexicographicPositive(const btVectorXu& v)
{
+ int i = 0;
+ // if (DEBUGLEVEL)
+ // cout << "v " << v << endl;
+
+ while (i < v.size() - 1 && fabs(v[i]) < btMachEps())
+ i++;
+ if (v[i] > 0)
+ return true;
+ return false;
+}
+
+void btLemkeAlgorithm::GaussJordanEliminationStep(btMatrixXu& A, int pivotRowIndex, int pivotColumnIndex, const btAlignedObjectArray<int>& basis)
+{
btScalar a = -1 / A(pivotRowIndex, pivotColumnIndex);
#ifdef BT_DEBUG_OSTREAM
cout << A << std::endl;
#endif
- for (int i = 0; i < A.rows(); i++)
+ for (int i = 0; i < A.rows(); i++)
{
- if (i != pivotRowIndex)
- {
- for (int j = 0; j < A.cols(); j++)
+ if (i != pivotRowIndex)
{
- if (j != pivotColumnIndex)
- {
- btScalar v = A(i, j);
- v += A(pivotRowIndex, j) * A(i, pivotColumnIndex) * a;
- A.setElem(i, j, v);
- }
+ for (int j = 0; j < A.cols(); j++)
+ {
+ if (j != pivotColumnIndex)
+ {
+ btScalar v = A(i, j);
+ v += A(pivotRowIndex, j) * A(i, pivotColumnIndex) * a;
+ A.setElem(i, j, v);
+ }
+ }
}
- }
}
#ifdef BT_DEBUG_OSTREAM
cout << A << std::endl;
-#endif //BT_DEBUG_OSTREAM
- for (int i = 0; i < A.cols(); i++)
+#endif //BT_DEBUG_OSTREAM
+ for (int i = 0; i < A.cols(); i++)
{
- A.mulElem(pivotRowIndex, i,-a);
- }
+ A.mulElem(pivotRowIndex, i, -a);
+ }
#ifdef BT_DEBUG_OSTREAM
cout << A << std::endl;
-#endif //#ifdef BT_DEBUG_OSTREAM
+#endif //#ifdef BT_DEBUG_OSTREAM
- for (int i = 0; i < A.rows(); i++)
+ for (int i = 0; i < A.rows(); i++)
{
- if (i != pivotRowIndex)
- {
- A.setElem(i, pivotColumnIndex,0);
- }
+ if (i != pivotRowIndex)
+ {
+ A.setElem(i, pivotColumnIndex, 0);
+ }
}
#ifdef BT_DEBUG_OSTREAM
cout << A << std::endl;
-#endif //#ifdef BT_DEBUG_OSTREAM
- }
+#endif //#ifdef BT_DEBUG_OSTREAM
+}
- bool btLemkeAlgorithm::greaterZero(const btVectorXu & vector)
+bool btLemkeAlgorithm::greaterZero(const btVectorXu& vector)
{
- bool isGreater = true;
- for (int i = 0; i < vector.size(); i++) {
- if (vector[i] < 0) {
- isGreater = false;
- break;
- }
- }
-
- return isGreater;
- }
-
- bool btLemkeAlgorithm::validBasis(const btAlignedObjectArray<int>& basis)
- {
- bool isValid = true;
- for (int i = 0; i < basis.size(); i++) {
- if (basis[i] >= basis.size() * 2) { //then z0 is in the base
- isValid = false;
- break;
- }
- }
-
- return isValid;
- }
+ bool isGreater = true;
+ for (int i = 0; i < vector.size(); i++)
+ {
+ if (vector[i] < 0)
+ {
+ isGreater = false;
+ break;
+ }
+ }
+ return isGreater;
+}
+bool btLemkeAlgorithm::validBasis(const btAlignedObjectArray<int>& basis)
+{
+ bool isValid = true;
+ for (int i = 0; i < basis.size(); i++)
+ {
+ if (basis[i] >= basis.size() * 2)
+ { //then z0 is in the base
+ isValid = false;
+ break;
+ }
+ }
+
+ return isValid;
+}
diff --git a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeAlgorithm.h b/thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeAlgorithm.h
index 7555cd9d20..3c6bf72a23 100644
--- a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeAlgorithm.h
+++ b/thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeAlgorithm.h
@@ -19,90 +19,84 @@ subject to the following restrictions:
//Math library was replaced from fmatvec to a the file src/LinearMath/btMatrixX.h
//STL/std::vector replaced by btAlignedObjectArray
-
-
#ifndef BT_NUMERICS_LEMKE_ALGORITHM_H_
#define BT_NUMERICS_LEMKE_ALGORITHM_H_
#include "LinearMath/btMatrixX.h"
-
-#include <vector> //todo: replace by btAlignedObjectArray
+#include <vector> //todo: replace by btAlignedObjectArray
class btLemkeAlgorithm
{
public:
-
-
- btLemkeAlgorithm(const btMatrixXu& M_, const btVectorXu& q_, const int & DEBUGLEVEL_ = 0) :
- DEBUGLEVEL(DEBUGLEVEL_)
- {
- setSystem(M_, q_);
- }
+ btLemkeAlgorithm(const btMatrixXu& M_, const btVectorXu& q_, const int& DEBUGLEVEL_ = 0) : DEBUGLEVEL(DEBUGLEVEL_)
+ {
+ setSystem(M_, q_);
+ }
- /* GETTER / SETTER */
- /**
+ /* GETTER / SETTER */
+ /**
* \brief return info of solution process
*/
- int getInfo() {
- return info;
- }
+ int getInfo()
+ {
+ return info;
+ }
- /**
+ /**
* \brief get the number of steps until the solution was found
*/
- int getSteps(void) {
- return steps;
- }
-
-
+ int getSteps(void)
+ {
+ return steps;
+ }
- /**
+ /**
* \brief set system with Matrix M and vector q
*/
- void setSystem(const btMatrixXu & M_, const btVectorXu & q_)
+ void setSystem(const btMatrixXu& M_, const btVectorXu& q_)
{
m_M = M_;
m_q = q_;
- }
- /***************************************************/
+ }
+ /***************************************************/
- /**
+ /**
* \brief solve algorithm adapted from : Fast Implementation of Lemke’s Algorithm for Rigid Body Contact Simulation (John E. Lloyd)
*/
- btVectorXu solve(unsigned int maxloops = 0);
+ btVectorXu solve(unsigned int maxloops = 0);
- virtual ~btLemkeAlgorithm() {
- }
+ virtual ~btLemkeAlgorithm()
+ {
+ }
protected:
- int findLexicographicMinimum(const btMatrixXu &A, const int & pivotColIndex);
- bool LexicographicPositive(const btVectorXu & v);
- void GaussJordanEliminationStep(btMatrixXu &A, int pivotRowIndex, int pivotColumnIndex, const btAlignedObjectArray<int>& basis);
- bool greaterZero(const btVectorXu & vector);
- bool validBasis(const btAlignedObjectArray<int>& basis);
+ int findLexicographicMinimum(const btMatrixXu& A, const int& pivotColIndex);
+ bool LexicographicPositive(const btVectorXu& v);
+ void GaussJordanEliminationStep(btMatrixXu& A, int pivotRowIndex, int pivotColumnIndex, const btAlignedObjectArray<int>& basis);
+ bool greaterZero(const btVectorXu& vector);
+ bool validBasis(const btAlignedObjectArray<int>& basis);
- btMatrixXu m_M;
- btVectorXu m_q;
+ btMatrixXu m_M;
+ btVectorXu m_q;
- /**
+ /**
* \brief number of steps until the Lemke algorithm found a solution
*/
- unsigned int steps;
+ unsigned int steps;
- /**
+ /**
* \brief define level of debug output
*/
- int DEBUGLEVEL;
+ int DEBUGLEVEL;
- /**
+ /**
* \brief did the algorithm find a solution
*
* -1 : not successful
* 0 : successful
*/
- int info;
+ int info;
};
-
#endif /* BT_NUMERICS_LEMKE_ALGORITHM_H_ */
diff --git a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeSolver.h b/thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeSolver.h
index 98484c3796..3f215e56bb 100644
--- a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeSolver.h
+++ b/thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeSolver.h
@@ -17,334 +17,322 @@ subject to the following restrictions:
#ifndef BT_LEMKE_SOLVER_H
#define BT_LEMKE_SOLVER_H
-
#include "btMLCPSolverInterface.h"
#include "btLemkeAlgorithm.h"
-
-
-
///The btLemkeSolver is based on "Fast Implementation of Lemke’s Algorithm for Rigid Body Contact Simulation (John E. Lloyd) "
///It is a slower but more accurate solver. Increase the m_maxLoops for better convergence, at the cost of more CPU time.
///The original implementation of the btLemkeAlgorithm was done by Kilian Grundl from the MBSim team
class btLemkeSolver : public btMLCPSolverInterface
{
protected:
-
public:
-
- btScalar m_maxValue;
- int m_debugLevel;
- int m_maxLoops;
- bool m_useLoHighBounds;
-
-
+ btScalar m_maxValue;
+ int m_debugLevel;
+ int m_maxLoops;
+ bool m_useLoHighBounds;
btLemkeSolver()
- :m_maxValue(100000),
- m_debugLevel(0),
- m_maxLoops(1000),
- m_useLoHighBounds(true)
+ : m_maxValue(100000),
+ m_debugLevel(0),
+ m_maxLoops(1000),
+ m_useLoHighBounds(true)
{
}
- virtual bool solveMLCP(const btMatrixXu & A, const btVectorXu & b, btVectorXu& x, const btVectorXu & lo,const btVectorXu & hi,const btAlignedObjectArray<int>& limitDependency, int numIterations, bool useSparsity = true)
+ virtual bool solveMLCP(const btMatrixXu& A, const btVectorXu& b, btVectorXu& x, const btVectorXu& lo, const btVectorXu& hi, const btAlignedObjectArray<int>& limitDependency, int numIterations, bool useSparsity = true)
{
-
if (m_useLoHighBounds)
{
+ BT_PROFILE("btLemkeSolver::solveMLCP");
+ int n = A.rows();
+ if (0 == n)
+ return true;
- BT_PROFILE("btLemkeSolver::solveMLCP");
- int n = A.rows();
- if (0==n)
- return true;
-
- bool fail = false;
-
- btVectorXu solution(n);
- btVectorXu q1;
- q1.resize(n);
- for (int row=0;row<n;row++)
- {
- q1[row] = -b[row];
- }
+ bool fail = false;
+
+ btVectorXu solution(n);
+ btVectorXu q1;
+ q1.resize(n);
+ for (int row = 0; row < n; row++)
+ {
+ q1[row] = -b[row];
+ }
- // cout << "A" << endl;
- // cout << A << endl;
+ // cout << "A" << endl;
+ // cout << A << endl;
/////////////////////////////////////
//slow matrix inversion, replace with LU decomposition
btMatrixXu A1;
- btMatrixXu B(n,n);
+ btMatrixXu B(n, n);
{
BT_PROFILE("inverse(slow)");
- A1.resize(A.rows(),A.cols());
- for (int row=0;row<A.rows();row++)
+ A1.resize(A.rows(), A.cols());
+ for (int row = 0; row < A.rows(); row++)
{
- for (int col=0;col<A.cols();col++)
+ for (int col = 0; col < A.cols(); col++)
{
- A1.setElem(row,col,A(row,col));
+ A1.setElem(row, col, A(row, col));
}
}
btMatrixXu matrix;
- matrix.resize(n,2*n);
- for (int row=0;row<n;row++)
+ matrix.resize(n, 2 * n);
+ for (int row = 0; row < n; row++)
{
- for (int col=0;col<n;col++)
+ for (int col = 0; col < n; col++)
{
- matrix.setElem(row,col,A1(row,col));
+ matrix.setElem(row, col, A1(row, col));
}
}
-
- btScalar ratio,a;
- int i,j,k;
- for(i = 0; i < n; i++){
- for(j = n; j < 2*n; j++){
- if(i==(j-n))
- matrix.setElem(i,j,1.0);
- else
- matrix.setElem(i,j,0.0);
+ btScalar ratio, a;
+ int i, j, k;
+ for (i = 0; i < n; i++)
+ {
+ for (j = n; j < 2 * n; j++)
+ {
+ if (i == (j - n))
+ matrix.setElem(i, j, 1.0);
+ else
+ matrix.setElem(i, j, 0.0);
+ }
}
- }
- for(i = 0; i < n; i++){
- for(j = 0; j < n; j++){
- if(i!=j)
+ for (i = 0; i < n; i++)
+ {
+ for (j = 0; j < n; j++)
{
- btScalar v = matrix(i,i);
- if (btFuzzyZero(v))
+ if (i != j)
{
- a = 0.000001f;
- }
- ratio = matrix(j,i)/matrix(i,i);
- for(k = 0; k < 2*n; k++){
- matrix.addElem(j,k,- ratio * matrix(i,k));
+ btScalar v = matrix(i, i);
+ if (btFuzzyZero(v))
+ {
+ a = 0.000001f;
+ }
+ ratio = matrix(j, i) / matrix(i, i);
+ for (k = 0; k < 2 * n; k++)
+ {
+ matrix.addElem(j, k, -ratio * matrix(i, k));
+ }
}
}
}
- }
- for(i = 0; i < n; i++){
- a = matrix(i,i);
- if (btFuzzyZero(a))
+ for (i = 0; i < n; i++)
{
- a = 0.000001f;
- }
- btScalar invA = 1.f/a;
- for(j = 0; j < 2*n; j++){
- matrix.mulElem(i,j,invA);
+ a = matrix(i, i);
+ if (btFuzzyZero(a))
+ {
+ a = 0.000001f;
+ }
+ btScalar invA = 1.f / a;
+ for (j = 0; j < 2 * n; j++)
+ {
+ matrix.mulElem(i, j, invA);
+ }
}
- }
-
-
-
-
- for (int row=0;row<n;row++)
+ for (int row = 0; row < n; row++)
{
- for (int col=0;col<n;col++)
+ for (int col = 0; col < n; col++)
{
- B.setElem(row,col,matrix(row,n+col));
+ B.setElem(row, col, matrix(row, n + col));
}
}
}
- btMatrixXu b1(n,1);
+ btMatrixXu b1(n, 1);
- btMatrixXu M(n*2,n*2);
- for (int row=0;row<n;row++)
- {
- b1.setElem(row,0,-b[row]);
- for (int col=0;col<n;col++)
+ btMatrixXu M(n * 2, n * 2);
+ for (int row = 0; row < n; row++)
{
- btScalar v =B(row,col);
- M.setElem(row,col,v);
- M.setElem(n+row,n+col,v);
- M.setElem(n+row,col,-v);
- M.setElem(row,n+col,-v);
-
+ b1.setElem(row, 0, -b[row]);
+ for (int col = 0; col < n; col++)
+ {
+ btScalar v = B(row, col);
+ M.setElem(row, col, v);
+ M.setElem(n + row, n + col, v);
+ M.setElem(n + row, col, -v);
+ M.setElem(row, n + col, -v);
+ }
}
- }
- btMatrixXu Bb1 = B*b1;
-// q = [ (-B*b1 - lo)' (hi + B*b1)' ]'
+ btMatrixXu Bb1 = B * b1;
+ // q = [ (-B*b1 - lo)' (hi + B*b1)' ]'
- btVectorXu qq;
- qq.resize(n*2);
- for (int row=0;row<n;row++)
- {
- qq[row] = -Bb1(row,0)-lo[row];
- qq[n+row] = Bb1(row,0)+hi[row];
- }
+ btVectorXu qq;
+ qq.resize(n * 2);
+ for (int row = 0; row < n; row++)
+ {
+ qq[row] = -Bb1(row, 0) - lo[row];
+ qq[n + row] = Bb1(row, 0) + hi[row];
+ }
- btVectorXu z1;
+ btVectorXu z1;
- btMatrixXu y1;
- y1.resize(n,1);
- btLemkeAlgorithm lemke(M,qq,m_debugLevel);
- {
- BT_PROFILE("lemke.solve");
- lemke.setSystem(M,qq);
- z1 = lemke.solve(m_maxLoops);
- }
- for (int row=0;row<n;row++)
- {
- y1.setElem(row,0,z1[2*n+row]-z1[3*n+row]);
- }
- btMatrixXu y1_b1(n,1);
- for (int i=0;i<n;i++)
- {
- y1_b1.setElem(i,0,y1(i,0)-b1(i,0));
- }
+ btMatrixXu y1;
+ y1.resize(n, 1);
+ btLemkeAlgorithm lemke(M, qq, m_debugLevel);
+ {
+ BT_PROFILE("lemke.solve");
+ lemke.setSystem(M, qq);
+ z1 = lemke.solve(m_maxLoops);
+ }
+ for (int row = 0; row < n; row++)
+ {
+ y1.setElem(row, 0, z1[2 * n + row] - z1[3 * n + row]);
+ }
+ btMatrixXu y1_b1(n, 1);
+ for (int i = 0; i < n; i++)
+ {
+ y1_b1.setElem(i, 0, y1(i, 0) - b1(i, 0));
+ }
- btMatrixXu x1;
+ btMatrixXu x1;
- x1 = B*(y1_b1);
-
- for (int row=0;row<n;row++)
- {
- solution[row] = x1(row,0);//n];
- }
+ x1 = B * (y1_b1);
- int errorIndexMax = -1;
- int errorIndexMin = -1;
- float errorValueMax = -1e30;
- float errorValueMin = 1e30;
-
- for (int i=0;i<n;i++)
- {
- x[i] = solution[i];
- volatile btScalar check = x[i];
- if (x[i] != check)
+ for (int row = 0; row < n; row++)
{
- //printf("Lemke result is #NAN\n");
- x.setZero();
- return false;
+ solution[row] = x1(row, 0); //n];
}
-
- //this is some hack/safety mechanism, to discard invalid solutions from the Lemke solver
- //we need to figure out why it happens, and fix it, or detect it properly)
- if (x[i]>m_maxValue)
+
+ int errorIndexMax = -1;
+ int errorIndexMin = -1;
+ float errorValueMax = -1e30;
+ float errorValueMin = 1e30;
+
+ for (int i = 0; i < n; i++)
{
- if (x[i]> errorValueMax)
+ x[i] = solution[i];
+ volatile btScalar check = x[i];
+ if (x[i] != check)
+ {
+ //printf("Lemke result is #NAN\n");
+ x.setZero();
+ return false;
+ }
+
+ //this is some hack/safety mechanism, to discard invalid solutions from the Lemke solver
+ //we need to figure out why it happens, and fix it, or detect it properly)
+ if (x[i] > m_maxValue)
+ {
+ if (x[i] > errorValueMax)
+ {
+ fail = true;
+ errorIndexMax = i;
+ errorValueMax = x[i];
+ }
+ ////printf("x[i] = %f,",x[i]);
+ }
+ if (x[i] < -m_maxValue)
{
- fail = true;
- errorIndexMax = i;
- errorValueMax = x[i];
+ if (x[i] < errorValueMin)
+ {
+ errorIndexMin = i;
+ errorValueMin = x[i];
+ fail = true;
+ //printf("x[i] = %f,",x[i]);
+ }
}
- ////printf("x[i] = %f,",x[i]);
}
- if (x[i]<-m_maxValue)
+ if (fail)
{
- if (x[i]<errorValueMin)
+ int m_errorCountTimes = 0;
+ if (errorIndexMin < 0)
+ errorValueMin = 0.f;
+ if (errorIndexMax < 0)
+ errorValueMax = 0.f;
+ m_errorCountTimes++;
+ // printf("Error (x[%d] = %f, x[%d] = %f), resetting %d times\n", errorIndexMin,errorValueMin, errorIndexMax, errorValueMax, errorCountTimes++);
+ for (int i = 0; i < n; i++)
{
- errorIndexMin = i;
- errorValueMin = x[i];
- fail = true;
- //printf("x[i] = %f,",x[i]);
+ x[i] = 0.f;
}
}
+ return !fail;
}
- if (fail)
+ else
+
{
- int m_errorCountTimes = 0;
- if (errorIndexMin<0)
- errorValueMin = 0.f;
- if (errorIndexMax<0)
- errorValueMax = 0.f;
- m_errorCountTimes++;
- // printf("Error (x[%d] = %f, x[%d] = %f), resetting %d times\n", errorIndexMin,errorValueMin, errorIndexMax, errorValueMax, errorCountTimes++);
- for (int i=0;i<n;i++)
- {
- x[i]=0.f;
- }
- }
- return !fail;
- } else
-
- {
int dimension = A.rows();
- if (0==dimension)
- return true;
-
-// printf("================ solving using Lemke/Newton/Fixpoint\n");
-
- btVectorXu q;
- q.resize(dimension);
- for (int row=0;row<dimension;row++)
- {
- q[row] = -b[row];
- }
-
- btLemkeAlgorithm lemke(A,q,m_debugLevel);
-
-
- lemke.setSystem(A,q);
-
- btVectorXu solution = lemke.solve(m_maxLoops);
-
- //check solution
-
- bool fail = false;
- int errorIndexMax = -1;
- int errorIndexMin = -1;
- float errorValueMax = -1e30;
- float errorValueMin = 1e30;
-
- for (int i=0;i<dimension;i++)
- {
- x[i] = solution[i+dimension];
- volatile btScalar check = x[i];
- if (x[i] != check)
+ if (0 == dimension)
+ return true;
+
+ // printf("================ solving using Lemke/Newton/Fixpoint\n");
+
+ btVectorXu q;
+ q.resize(dimension);
+ for (int row = 0; row < dimension; row++)
{
- x.setZero();
- return false;
+ q[row] = -b[row];
}
-
- //this is some hack/safety mechanism, to discard invalid solutions from the Lemke solver
- //we need to figure out why it happens, and fix it, or detect it properly)
- if (x[i]>m_maxValue)
+
+ btLemkeAlgorithm lemke(A, q, m_debugLevel);
+
+ lemke.setSystem(A, q);
+
+ btVectorXu solution = lemke.solve(m_maxLoops);
+
+ //check solution
+
+ bool fail = false;
+ int errorIndexMax = -1;
+ int errorIndexMin = -1;
+ float errorValueMax = -1e30;
+ float errorValueMin = 1e30;
+
+ for (int i = 0; i < dimension; i++)
{
- if (x[i]> errorValueMax)
+ x[i] = solution[i + dimension];
+ volatile btScalar check = x[i];
+ if (x[i] != check)
{
- fail = true;
- errorIndexMax = i;
- errorValueMax = x[i];
+ x.setZero();
+ return false;
}
- ////printf("x[i] = %f,",x[i]);
- }
- if (x[i]<-m_maxValue)
- {
- if (x[i]<errorValueMin)
+
+ //this is some hack/safety mechanism, to discard invalid solutions from the Lemke solver
+ //we need to figure out why it happens, and fix it, or detect it properly)
+ if (x[i] > m_maxValue)
+ {
+ if (x[i] > errorValueMax)
+ {
+ fail = true;
+ errorIndexMax = i;
+ errorValueMax = x[i];
+ }
+ ////printf("x[i] = %f,",x[i]);
+ }
+ if (x[i] < -m_maxValue)
{
- errorIndexMin = i;
- errorValueMin = x[i];
- fail = true;
- //printf("x[i] = %f,",x[i]);
+ if (x[i] < errorValueMin)
+ {
+ errorIndexMin = i;
+ errorValueMin = x[i];
+ fail = true;
+ //printf("x[i] = %f,",x[i]);
+ }
}
}
- }
- if (fail)
- {
- static int errorCountTimes = 0;
- if (errorIndexMin<0)
- errorValueMin = 0.f;
- if (errorIndexMax<0)
- errorValueMax = 0.f;
- printf("Error (x[%d] = %f, x[%d] = %f), resetting %d times\n", errorIndexMin,errorValueMin, errorIndexMax, errorValueMax, errorCountTimes++);
- for (int i=0;i<dimension;i++)
+ if (fail)
{
- x[i]=0.f;
+ static int errorCountTimes = 0;
+ if (errorIndexMin < 0)
+ errorValueMin = 0.f;
+ if (errorIndexMax < 0)
+ errorValueMax = 0.f;
+ printf("Error (x[%d] = %f, x[%d] = %f), resetting %d times\n", errorIndexMin, errorValueMin, errorIndexMax, errorValueMax, errorCountTimes++);
+ for (int i = 0; i < dimension; i++)
+ {
+ x[i] = 0.f;
+ }
}
- }
-
-
- return !fail;
- }
- return true;
+ return !fail;
+ }
+ return true;
}
-
};
-#endif //BT_LEMKE_SOLVER_H
+#endif //BT_LEMKE_SOLVER_H
diff --git a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btMLCPSolver.cpp b/thirdparty/bullet/BulletDynamics/MLCPSolvers/btMLCPSolver.cpp
index 8f54c52626..5d864f2757 100644
--- a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btMLCPSolver.cpp
+++ b/thirdparty/bullet/BulletDynamics/MLCPSolvers/btMLCPSolver.cpp
@@ -19,10 +19,9 @@ subject to the following restrictions:
#include "LinearMath/btQuickprof.h"
#include "btSolveProjectedGaussSeidel.h"
-
-btMLCPSolver::btMLCPSolver( btMLCPSolverInterface* solver)
-:m_solver(solver),
-m_fallback(0)
+btMLCPSolver::btMLCPSolver(btMLCPSolverInterface* solver)
+ : m_solver(solver),
+ m_fallback(0)
{
}
@@ -33,67 +32,65 @@ btMLCPSolver::~btMLCPSolver()
bool gUseMatrixMultiply = false;
bool interleaveContactAndFriction = false;
-btScalar btMLCPSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies, int numBodiesUnUsed, btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer)
+btScalar btMLCPSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies, int numBodiesUnUsed, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
{
- btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup( bodies, numBodiesUnUsed, manifoldPtr, numManifolds,constraints,numConstraints,infoGlobal,debugDrawer);
+ btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(bodies, numBodiesUnUsed, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
{
BT_PROFILE("gather constraint data");
- int numFrictionPerContact = m_tmpSolverContactConstraintPool.size()==m_tmpSolverContactFrictionConstraintPool.size()? 1 : 2;
-
+ int numFrictionPerContact = m_tmpSolverContactConstraintPool.size() == m_tmpSolverContactFrictionConstraintPool.size() ? 1 : 2;
- // int numBodies = m_tmpSolverBodyPool.size();
+ // int numBodies = m_tmpSolverBodyPool.size();
m_allConstraintPtrArray.resize(0);
- m_limitDependencies.resize(m_tmpSolverNonContactConstraintPool.size()+m_tmpSolverContactConstraintPool.size()+m_tmpSolverContactFrictionConstraintPool.size());
- btAssert(m_limitDependencies.size() == m_tmpSolverNonContactConstraintPool.size()+m_tmpSolverContactConstraintPool.size()+m_tmpSolverContactFrictionConstraintPool.size());
- // printf("m_limitDependencies.size() = %d\n",m_limitDependencies.size());
+ m_limitDependencies.resize(m_tmpSolverNonContactConstraintPool.size() + m_tmpSolverContactConstraintPool.size() + m_tmpSolverContactFrictionConstraintPool.size());
+ btAssert(m_limitDependencies.size() == m_tmpSolverNonContactConstraintPool.size() + m_tmpSolverContactConstraintPool.size() + m_tmpSolverContactFrictionConstraintPool.size());
+ // printf("m_limitDependencies.size() = %d\n",m_limitDependencies.size());
int dindex = 0;
- for (int i=0;i<m_tmpSolverNonContactConstraintPool.size();i++)
+ for (int i = 0; i < m_tmpSolverNonContactConstraintPool.size(); i++)
{
m_allConstraintPtrArray.push_back(&m_tmpSolverNonContactConstraintPool[i]);
m_limitDependencies[dindex++] = -1;
}
-
+
///The btSequentialImpulseConstraintSolver moves all friction constraints at the very end, we can also interleave them instead
-
- int firstContactConstraintOffset=dindex;
+
+ int firstContactConstraintOffset = dindex;
if (interleaveContactAndFriction)
{
- for (int i=0;i<m_tmpSolverContactConstraintPool.size();i++)
+ for (int i = 0; i < m_tmpSolverContactConstraintPool.size(); i++)
{
m_allConstraintPtrArray.push_back(&m_tmpSolverContactConstraintPool[i]);
m_limitDependencies[dindex++] = -1;
- m_allConstraintPtrArray.push_back(&m_tmpSolverContactFrictionConstraintPool[i*numFrictionPerContact]);
- int findex = (m_tmpSolverContactFrictionConstraintPool[i*numFrictionPerContact].m_frictionIndex*(1+numFrictionPerContact));
- m_limitDependencies[dindex++] = findex +firstContactConstraintOffset;
- if (numFrictionPerContact==2)
+ m_allConstraintPtrArray.push_back(&m_tmpSolverContactFrictionConstraintPool[i * numFrictionPerContact]);
+ int findex = (m_tmpSolverContactFrictionConstraintPool[i * numFrictionPerContact].m_frictionIndex * (1 + numFrictionPerContact));
+ m_limitDependencies[dindex++] = findex + firstContactConstraintOffset;
+ if (numFrictionPerContact == 2)
{
- m_allConstraintPtrArray.push_back(&m_tmpSolverContactFrictionConstraintPool[i*numFrictionPerContact+1]);
- m_limitDependencies[dindex++] = findex+firstContactConstraintOffset;
+ m_allConstraintPtrArray.push_back(&m_tmpSolverContactFrictionConstraintPool[i * numFrictionPerContact + 1]);
+ m_limitDependencies[dindex++] = findex + firstContactConstraintOffset;
}
}
- } else
+ }
+ else
{
- for (int i=0;i<m_tmpSolverContactConstraintPool.size();i++)
+ for (int i = 0; i < m_tmpSolverContactConstraintPool.size(); i++)
{
m_allConstraintPtrArray.push_back(&m_tmpSolverContactConstraintPool[i]);
m_limitDependencies[dindex++] = -1;
}
- for (int i=0;i<m_tmpSolverContactFrictionConstraintPool.size();i++)
+ for (int i = 0; i < m_tmpSolverContactFrictionConstraintPool.size(); i++)
{
m_allConstraintPtrArray.push_back(&m_tmpSolverContactFrictionConstraintPool[i]);
- m_limitDependencies[dindex++] = m_tmpSolverContactFrictionConstraintPool[i].m_frictionIndex+firstContactConstraintOffset;
+ m_limitDependencies[dindex++] = m_tmpSolverContactFrictionConstraintPool[i].m_frictionIndex + firstContactConstraintOffset;
}
-
}
-
if (!m_allConstraintPtrArray.size())
{
- m_A.resize(0,0);
+ m_A.resize(0, 0);
m_b.resize(0);
m_x.resize(0);
m_lo.resize(0);
@@ -102,7 +99,6 @@ btScalar btMLCPSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies,
}
}
-
if (gUseMatrixMultiply)
{
BT_PROFILE("createMLCP");
@@ -121,7 +117,7 @@ bool btMLCPSolver::solveMLCP(const btContactSolverInfo& infoGlobal)
{
bool result = true;
- if (m_A.rows()==0)
+ if (m_A.rows() == 0)
return true;
//if using split impulse, we solve 2 separate (M)LCPs
@@ -129,28 +125,26 @@ bool btMLCPSolver::solveMLCP(const btContactSolverInfo& infoGlobal)
{
btMatrixXu Acopy = m_A;
btAlignedObjectArray<int> limitDependenciesCopy = m_limitDependencies;
-// printf("solve first LCP\n");
- result = m_solver->solveMLCP(m_A, m_b, m_x, m_lo,m_hi, m_limitDependencies,infoGlobal.m_numIterations );
+ // printf("solve first LCP\n");
+ result = m_solver->solveMLCP(m_A, m_b, m_x, m_lo, m_hi, m_limitDependencies, infoGlobal.m_numIterations);
if (result)
- result = m_solver->solveMLCP(Acopy, m_bSplit, m_xSplit, m_lo,m_hi, limitDependenciesCopy,infoGlobal.m_numIterations );
-
- } else
+ result = m_solver->solveMLCP(Acopy, m_bSplit, m_xSplit, m_lo, m_hi, limitDependenciesCopy, infoGlobal.m_numIterations);
+ }
+ else
{
- result = m_solver->solveMLCP(m_A, m_b, m_x, m_lo,m_hi, m_limitDependencies,infoGlobal.m_numIterations );
+ result = m_solver->solveMLCP(m_A, m_b, m_x, m_lo, m_hi, m_limitDependencies, infoGlobal.m_numIterations);
}
return result;
}
struct btJointNode
{
- int jointIndex; // pointer to enclosing dxJoint object
- int otherBodyIndex; // *other* body this joint is connected to
- int nextJointNodeIndex;//-1 for null
+ int jointIndex; // pointer to enclosing dxJoint object
+ int otherBodyIndex; // *other* body this joint is connected to
+ int nextJointNodeIndex; //-1 for null
int constraintRowIndex;
};
-
-
void btMLCPSolver::createMLCPFast(const btContactSolverInfo& infoGlobal)
{
int numContactRows = interleaveContactAndFriction ? 3 : 1;
@@ -163,36 +157,36 @@ void btMLCPSolver::createMLCPFast(const btContactSolverInfo& infoGlobal)
m_bSplit.resize(numConstraintRows);
m_b.setZero();
m_bSplit.setZero();
- for (int i=0;i<numConstraintRows ;i++)
+ for (int i = 0; i < numConstraintRows; i++)
{
btScalar jacDiag = m_allConstraintPtrArray[i]->m_jacDiagABInv;
if (!btFuzzyZero(jacDiag))
{
btScalar rhs = m_allConstraintPtrArray[i]->m_rhs;
btScalar rhsPenetration = m_allConstraintPtrArray[i]->m_rhsPenetration;
- m_b[i]=rhs/jacDiag;
- m_bSplit[i] = rhsPenetration/jacDiag;
+ m_b[i] = rhs / jacDiag;
+ m_bSplit[i] = rhsPenetration / jacDiag;
}
-
}
}
-// btScalar* w = 0;
-// int nub = 0;
+ // btScalar* w = 0;
+ // int nub = 0;
m_lo.resize(numConstraintRows);
m_hi.resize(numConstraintRows);
-
+
{
BT_PROFILE("init lo/ho");
- for (int i=0;i<numConstraintRows;i++)
+ for (int i = 0; i < numConstraintRows; i++)
{
- if (0)//m_limitDependencies[i]>=0)
+ if (0) //m_limitDependencies[i]>=0)
{
m_lo[i] = -BT_INFINITY;
m_hi[i] = BT_INFINITY;
- } else
+ }
+ else
{
m_lo[i] = m_allConstraintPtrArray[i]->m_lowerLimit;
m_hi[i] = m_allConstraintPtrArray[i]->m_upperLimit;
@@ -201,48 +195,48 @@ void btMLCPSolver::createMLCPFast(const btContactSolverInfo& infoGlobal)
}
//
- int m=m_allConstraintPtrArray.size();
+ int m = m_allConstraintPtrArray.size();
int numBodies = m_tmpSolverBodyPool.size();
btAlignedObjectArray<int> bodyJointNodeArray;
{
BT_PROFILE("bodyJointNodeArray.resize");
- bodyJointNodeArray.resize(numBodies,-1);
+ bodyJointNodeArray.resize(numBodies, -1);
}
btAlignedObjectArray<btJointNode> jointNodeArray;
{
BT_PROFILE("jointNodeArray.reserve");
- jointNodeArray.reserve(2*m_allConstraintPtrArray.size());
+ jointNodeArray.reserve(2 * m_allConstraintPtrArray.size());
}
- btMatrixXu& J3 = m_scratchJ3;
+ btMatrixXu& J3 = m_scratchJ3;
{
BT_PROFILE("J3.resize");
- J3.resize(2*m,8);
+ J3.resize(2 * m, 8);
}
- btMatrixXu& JinvM3 = m_scratchJInvM3;
+ btMatrixXu& JinvM3 = m_scratchJInvM3;
{
BT_PROFILE("JinvM3.resize/setZero");
- JinvM3.resize(2*m,8);
+ JinvM3.resize(2 * m, 8);
JinvM3.setZero();
J3.setZero();
}
- int cur=0;
+ int cur = 0;
int rowOffset = 0;
- btAlignedObjectArray<int>& ofs = m_scratchOfs;
+ btAlignedObjectArray<int>& ofs = m_scratchOfs;
{
BT_PROFILE("ofs resize");
ofs.resize(0);
ofs.resizeNoInitialize(m_allConstraintPtrArray.size());
- }
+ }
{
BT_PROFILE("Compute J and JinvM");
- int c=0;
+ int c = 0;
int numRows = 0;
- for (int i=0;i<m_allConstraintPtrArray.size();i+=numRows,c++)
+ for (int i = 0; i < m_allConstraintPtrArray.size(); i += numRows, c++)
{
ofs[c] = rowOffset;
int sbA = m_allConstraintPtrArray[i]->m_solverBodyIdA;
@@ -250,14 +244,14 @@ void btMLCPSolver::createMLCPFast(const btContactSolverInfo& infoGlobal)
btRigidBody* orgBodyA = m_tmpSolverBodyPool[sbA].m_originalBody;
btRigidBody* orgBodyB = m_tmpSolverBodyPool[sbB].m_originalBody;
- numRows = i<m_tmpSolverNonContactConstraintPool.size() ? m_tmpConstraintSizesPool[c].m_numConstraintRows : numContactRows ;
+ numRows = i < m_tmpSolverNonContactConstraintPool.size() ? m_tmpConstraintSizesPool[c].m_numConstraintRows : numContactRows;
if (orgBodyA)
{
{
- int slotA=-1;
+ int slotA = -1;
//find free jointNode slot for sbA
- slotA =jointNodeArray.size();
- jointNodeArray.expand();//NonInitializing();
+ slotA = jointNodeArray.size();
+ jointNodeArray.expand(); //NonInitializing();
int prevSlot = bodyJointNodeArray[sbA];
bodyJointNodeArray[sbA] = slotA;
jointNodeArray[slotA].nextJointNodeIndex = prevSlot;
@@ -265,35 +259,35 @@ void btMLCPSolver::createMLCPFast(const btContactSolverInfo& infoGlobal)
jointNodeArray[slotA].constraintRowIndex = i;
jointNodeArray[slotA].otherBodyIndex = orgBodyB ? sbB : -1;
}
- for (int row=0;row<numRows;row++,cur++)
+ for (int row = 0; row < numRows; row++, cur++)
{
- btVector3 normalInvMass = m_allConstraintPtrArray[i+row]->m_contactNormal1 * orgBodyA->getInvMass();
- btVector3 relPosCrossNormalInvInertia = m_allConstraintPtrArray[i+row]->m_relpos1CrossNormal * orgBodyA->getInvInertiaTensorWorld();
+ btVector3 normalInvMass = m_allConstraintPtrArray[i + row]->m_contactNormal1 * orgBodyA->getInvMass();
+ btVector3 relPosCrossNormalInvInertia = m_allConstraintPtrArray[i + row]->m_relpos1CrossNormal * orgBodyA->getInvInertiaTensorWorld();
- for (int r=0;r<3;r++)
+ for (int r = 0; r < 3; r++)
{
- J3.setElem(cur,r,m_allConstraintPtrArray[i+row]->m_contactNormal1[r]);
- J3.setElem(cur,r+4,m_allConstraintPtrArray[i+row]->m_relpos1CrossNormal[r]);
- JinvM3.setElem(cur,r,normalInvMass[r]);
- JinvM3.setElem(cur,r+4,relPosCrossNormalInvInertia[r]);
+ J3.setElem(cur, r, m_allConstraintPtrArray[i + row]->m_contactNormal1[r]);
+ J3.setElem(cur, r + 4, m_allConstraintPtrArray[i + row]->m_relpos1CrossNormal[r]);
+ JinvM3.setElem(cur, r, normalInvMass[r]);
+ JinvM3.setElem(cur, r + 4, relPosCrossNormalInvInertia[r]);
}
- J3.setElem(cur,3,0);
- JinvM3.setElem(cur,3,0);
- J3.setElem(cur,7,0);
- JinvM3.setElem(cur,7,0);
+ J3.setElem(cur, 3, 0);
+ JinvM3.setElem(cur, 3, 0);
+ J3.setElem(cur, 7, 0);
+ JinvM3.setElem(cur, 7, 0);
}
- } else
+ }
+ else
{
cur += numRows;
}
if (orgBodyB)
{
-
{
- int slotB=-1;
+ int slotB = -1;
//find free jointNode slot for sbA
- slotB =jointNodeArray.size();
- jointNodeArray.expand();//NonInitializing();
+ slotB = jointNodeArray.size();
+ jointNodeArray.expand(); //NonInitializing();
int prevSlot = bodyJointNodeArray[sbB];
bodyJointNodeArray[sbB] = slotB;
jointNodeArray[slotB].nextJointNodeIndex = prevSlot;
@@ -302,78 +296,74 @@ void btMLCPSolver::createMLCPFast(const btContactSolverInfo& infoGlobal)
jointNodeArray[slotB].constraintRowIndex = i;
}
- for (int row=0;row<numRows;row++,cur++)
+ for (int row = 0; row < numRows; row++, cur++)
{
- btVector3 normalInvMassB = m_allConstraintPtrArray[i+row]->m_contactNormal2*orgBodyB->getInvMass();
- btVector3 relPosInvInertiaB = m_allConstraintPtrArray[i+row]->m_relpos2CrossNormal * orgBodyB->getInvInertiaTensorWorld();
+ btVector3 normalInvMassB = m_allConstraintPtrArray[i + row]->m_contactNormal2 * orgBodyB->getInvMass();
+ btVector3 relPosInvInertiaB = m_allConstraintPtrArray[i + row]->m_relpos2CrossNormal * orgBodyB->getInvInertiaTensorWorld();
- for (int r=0;r<3;r++)
+ for (int r = 0; r < 3; r++)
{
- J3.setElem(cur,r,m_allConstraintPtrArray[i+row]->m_contactNormal2[r]);
- J3.setElem(cur,r+4,m_allConstraintPtrArray[i+row]->m_relpos2CrossNormal[r]);
- JinvM3.setElem(cur,r,normalInvMassB[r]);
- JinvM3.setElem(cur,r+4,relPosInvInertiaB[r]);
+ J3.setElem(cur, r, m_allConstraintPtrArray[i + row]->m_contactNormal2[r]);
+ J3.setElem(cur, r + 4, m_allConstraintPtrArray[i + row]->m_relpos2CrossNormal[r]);
+ JinvM3.setElem(cur, r, normalInvMassB[r]);
+ JinvM3.setElem(cur, r + 4, relPosInvInertiaB[r]);
}
- J3.setElem(cur,3,0);
- JinvM3.setElem(cur,3,0);
- J3.setElem(cur,7,0);
- JinvM3.setElem(cur,7,0);
+ J3.setElem(cur, 3, 0);
+ JinvM3.setElem(cur, 3, 0);
+ J3.setElem(cur, 7, 0);
+ JinvM3.setElem(cur, 7, 0);
}
}
else
{
cur += numRows;
}
- rowOffset+=numRows;
-
+ rowOffset += numRows;
}
-
}
-
//compute JinvM = J*invM.
const btScalar* JinvM = JinvM3.getBufferPointer();
const btScalar* Jptr = J3.getBufferPointer();
{
BT_PROFILE("m_A.resize");
- m_A.resize(n,n);
+ m_A.resize(n, n);
}
-
+
{
BT_PROFILE("m_A.setZero");
m_A.setZero();
}
- int c=0;
+ int c = 0;
{
int numRows = 0;
BT_PROFILE("Compute A");
- for (int i=0;i<m_allConstraintPtrArray.size();i+= numRows,c++)
+ for (int i = 0; i < m_allConstraintPtrArray.size(); i += numRows, c++)
{
int row__ = ofs[c];
int sbA = m_allConstraintPtrArray[i]->m_solverBodyIdA;
int sbB = m_allConstraintPtrArray[i]->m_solverBodyIdB;
- // btRigidBody* orgBodyA = m_tmpSolverBodyPool[sbA].m_originalBody;
- // btRigidBody* orgBodyB = m_tmpSolverBodyPool[sbB].m_originalBody;
+ // btRigidBody* orgBodyA = m_tmpSolverBodyPool[sbA].m_originalBody;
+ // btRigidBody* orgBodyB = m_tmpSolverBodyPool[sbB].m_originalBody;
+
+ numRows = i < m_tmpSolverNonContactConstraintPool.size() ? m_tmpConstraintSizesPool[c].m_numConstraintRows : numContactRows;
- numRows = i<m_tmpSolverNonContactConstraintPool.size() ? m_tmpConstraintSizesPool[c].m_numConstraintRows : numContactRows ;
-
- const btScalar *JinvMrow = JinvM + 2*8*(size_t)row__;
+ const btScalar* JinvMrow = JinvM + 2 * 8 * (size_t)row__;
{
int startJointNodeA = bodyJointNodeArray[sbA];
- while (startJointNodeA>=0)
+ while (startJointNodeA >= 0)
{
int j0 = jointNodeArray[startJointNodeA].jointIndex;
int cr0 = jointNodeArray[startJointNodeA].constraintRowIndex;
- if (j0<c)
+ if (j0 < c)
{
-
int numRowsOther = cr0 < m_tmpSolverNonContactConstraintPool.size() ? m_tmpConstraintSizesPool[j0].m_numConstraintRows : numContactRows;
- size_t ofsother = (m_allConstraintPtrArray[cr0]->m_solverBodyIdB == sbA) ? 8*numRowsOther : 0;
+ size_t ofsother = (m_allConstraintPtrArray[cr0]->m_solverBodyIdB == sbA) ? 8 * numRowsOther : 0;
//printf("%d joint i %d and j0: %d: ",count++,i,j0);
- m_A.multiplyAdd2_p8r ( JinvMrow,
- Jptr + 2*8*(size_t)ofs[j0] + ofsother, numRows, numRowsOther, row__,ofs[j0]);
+ m_A.multiplyAdd2_p8r(JinvMrow,
+ Jptr + 2 * 8 * (size_t)ofs[j0] + ofsother, numRows, numRowsOther, row__, ofs[j0]);
}
startJointNodeA = jointNodeArray[startJointNodeA].nextJointNodeIndex;
}
@@ -381,17 +371,17 @@ void btMLCPSolver::createMLCPFast(const btContactSolverInfo& infoGlobal)
{
int startJointNodeB = bodyJointNodeArray[sbB];
- while (startJointNodeB>=0)
+ while (startJointNodeB >= 0)
{
int j1 = jointNodeArray[startJointNodeB].jointIndex;
int cj1 = jointNodeArray[startJointNodeB].constraintRowIndex;
- if (j1<c)
+ if (j1 < c)
{
- int numRowsOther = cj1 < m_tmpSolverNonContactConstraintPool.size() ? m_tmpConstraintSizesPool[j1].m_numConstraintRows : numContactRows;
- size_t ofsother = (m_allConstraintPtrArray[cj1]->m_solverBodyIdB == sbB) ? 8*numRowsOther : 0;
- m_A.multiplyAdd2_p8r ( JinvMrow + 8*(size_t)numRows,
- Jptr + 2*8*(size_t)ofs[j1] + ofsother, numRows, numRowsOther, row__,ofs[j1]);
+ int numRowsOther = cj1 < m_tmpSolverNonContactConstraintPool.size() ? m_tmpConstraintSizesPool[j1].m_numConstraintRows : numContactRows;
+ size_t ofsother = (m_allConstraintPtrArray[cj1]->m_solverBodyIdB == sbB) ? 8 * numRowsOther : 0;
+ m_A.multiplyAdd2_p8r(JinvMrow + 8 * (size_t)numRows,
+ Jptr + 2 * 8 * (size_t)ofs[j1] + ofsother, numRows, numRowsOther, row__, ofs[j1]);
}
startJointNodeB = jointNodeArray[startJointNodeB].nextJointNodeIndex;
}
@@ -402,27 +392,25 @@ void btMLCPSolver::createMLCPFast(const btContactSolverInfo& infoGlobal)
BT_PROFILE("compute diagonal");
// compute diagonal blocks of m_A
- int row__ = 0;
+ int row__ = 0;
int numJointRows = m_allConstraintPtrArray.size();
- int jj=0;
- for (;row__<numJointRows;)
+ int jj = 0;
+ for (; row__ < numJointRows;)
{
-
//int sbA = m_allConstraintPtrArray[row__]->m_solverBodyIdA;
int sbB = m_allConstraintPtrArray[row__]->m_solverBodyIdB;
- // btRigidBody* orgBodyA = m_tmpSolverBodyPool[sbA].m_originalBody;
+ // btRigidBody* orgBodyA = m_tmpSolverBodyPool[sbA].m_originalBody;
btRigidBody* orgBodyB = m_tmpSolverBodyPool[sbB].m_originalBody;
+ const unsigned int infom = row__ < m_tmpSolverNonContactConstraintPool.size() ? m_tmpConstraintSizesPool[jj].m_numConstraintRows : numContactRows;
- const unsigned int infom = row__ < m_tmpSolverNonContactConstraintPool.size() ? m_tmpConstraintSizesPool[jj].m_numConstraintRows : numContactRows;
-
- const btScalar *JinvMrow = JinvM + 2*8*(size_t)row__;
- const btScalar *Jrow = Jptr + 2*8*(size_t)row__;
- m_A.multiply2_p8r (JinvMrow, Jrow, infom, infom, row__,row__);
- if (orgBodyB)
+ const btScalar* JinvMrow = JinvM + 2 * 8 * (size_t)row__;
+ const btScalar* Jrow = Jptr + 2 * 8 * (size_t)row__;
+ m_A.multiply2_p8r(JinvMrow, Jrow, infom, infom, row__, row__);
+ if (orgBodyB)
{
- m_A.multiplyAdd2_p8r (JinvMrow + 8*(size_t)infom, Jrow + 8*(size_t)infom, infom, infom, row__,row__);
+ m_A.multiplyAdd2_p8r(JinvMrow + 8 * (size_t)infom, Jrow + 8 * (size_t)infom, infom, infom, row__, row__);
}
row__ += infom;
jj++;
@@ -433,12 +421,12 @@ void btMLCPSolver::createMLCPFast(const btContactSolverInfo& infoGlobal)
if (1)
{
// add cfm to the diagonal of m_A
- for ( int i=0; i<m_A.rows(); ++i)
+ for (int i = 0; i < m_A.rows(); ++i)
{
- m_A.setElem(i,i,m_A(i,i)+ infoGlobal.m_globalCfm/ infoGlobal.m_timeStep);
+ m_A.setElem(i, i, m_A(i, i) + infoGlobal.m_globalCfm / infoGlobal.m_timeStep);
}
}
-
+
///fill the upper triangle of the matrix, to make it symmetric
{
BT_PROFILE("fill the upper triangle ");
@@ -450,21 +438,21 @@ void btMLCPSolver::createMLCPFast(const btContactSolverInfo& infoGlobal)
m_x.resize(numConstraintRows);
m_xSplit.resize(numConstraintRows);
- if (infoGlobal.m_solverMode&SOLVER_USE_WARMSTARTING)
+ if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
{
- for (int i=0;i<m_allConstraintPtrArray.size();i++)
+ for (int i = 0; i < m_allConstraintPtrArray.size(); i++)
{
const btSolverConstraint& c = *m_allConstraintPtrArray[i];
- m_x[i]=c.m_appliedImpulse;
+ m_x[i] = c.m_appliedImpulse;
m_xSplit[i] = c.m_appliedPushImpulse;
}
- } else
+ }
+ else
{
m_x.setZero();
m_xSplit.setZero();
}
}
-
}
void btMLCPSolver::createMLCP(const btContactSolverInfo& infoGlobal)
@@ -475,120 +463,116 @@ void btMLCPSolver::createMLCP(const btContactSolverInfo& infoGlobal)
m_b.resize(numConstraintRows);
if (infoGlobal.m_splitImpulse)
m_bSplit.resize(numConstraintRows);
-
+
m_bSplit.setZero();
m_b.setZero();
- for (int i=0;i<numConstraintRows ;i++)
+ for (int i = 0; i < numConstraintRows; i++)
{
if (m_allConstraintPtrArray[i]->m_jacDiagABInv)
{
- m_b[i]=m_allConstraintPtrArray[i]->m_rhs/m_allConstraintPtrArray[i]->m_jacDiagABInv;
+ m_b[i] = m_allConstraintPtrArray[i]->m_rhs / m_allConstraintPtrArray[i]->m_jacDiagABInv;
if (infoGlobal.m_splitImpulse)
- m_bSplit[i] = m_allConstraintPtrArray[i]->m_rhsPenetration/m_allConstraintPtrArray[i]->m_jacDiagABInv;
+ m_bSplit[i] = m_allConstraintPtrArray[i]->m_rhsPenetration / m_allConstraintPtrArray[i]->m_jacDiagABInv;
}
}
-
- btMatrixXu& Minv = m_scratchMInv;
- Minv.resize(6*numBodies,6*numBodies);
+
+ btMatrixXu& Minv = m_scratchMInv;
+ Minv.resize(6 * numBodies, 6 * numBodies);
Minv.setZero();
- for (int i=0;i<numBodies;i++)
+ for (int i = 0; i < numBodies; i++)
{
const btSolverBody& rb = m_tmpSolverBodyPool[i];
const btVector3& invMass = rb.m_invMass;
- setElem(Minv,i*6+0,i*6+0,invMass[0]);
- setElem(Minv,i*6+1,i*6+1,invMass[1]);
- setElem(Minv,i*6+2,i*6+2,invMass[2]);
+ setElem(Minv, i * 6 + 0, i * 6 + 0, invMass[0]);
+ setElem(Minv, i * 6 + 1, i * 6 + 1, invMass[1]);
+ setElem(Minv, i * 6 + 2, i * 6 + 2, invMass[2]);
btRigidBody* orgBody = m_tmpSolverBodyPool[i].m_originalBody;
-
- for (int r=0;r<3;r++)
- for (int c=0;c<3;c++)
- setElem(Minv,i*6+3+r,i*6+3+c,orgBody? orgBody->getInvInertiaTensorWorld()[r][c] : 0);
+
+ for (int r = 0; r < 3; r++)
+ for (int c = 0; c < 3; c++)
+ setElem(Minv, i * 6 + 3 + r, i * 6 + 3 + c, orgBody ? orgBody->getInvInertiaTensorWorld()[r][c] : 0);
}
-
- btMatrixXu& J = m_scratchJ;
- J.resize(numConstraintRows,6*numBodies);
+
+ btMatrixXu& J = m_scratchJ;
+ J.resize(numConstraintRows, 6 * numBodies);
J.setZero();
-
+
m_lo.resize(numConstraintRows);
m_hi.resize(numConstraintRows);
-
- for (int i=0;i<numConstraintRows;i++)
- {
+ for (int i = 0; i < numConstraintRows; i++)
+ {
m_lo[i] = m_allConstraintPtrArray[i]->m_lowerLimit;
m_hi[i] = m_allConstraintPtrArray[i]->m_upperLimit;
-
+
int bodyIndex0 = m_allConstraintPtrArray[i]->m_solverBodyIdA;
int bodyIndex1 = m_allConstraintPtrArray[i]->m_solverBodyIdB;
if (m_tmpSolverBodyPool[bodyIndex0].m_originalBody)
{
- setElem(J,i,6*bodyIndex0+0,m_allConstraintPtrArray[i]->m_contactNormal1[0]);
- setElem(J,i,6*bodyIndex0+1,m_allConstraintPtrArray[i]->m_contactNormal1[1]);
- setElem(J,i,6*bodyIndex0+2,m_allConstraintPtrArray[i]->m_contactNormal1[2]);
- setElem(J,i,6*bodyIndex0+3,m_allConstraintPtrArray[i]->m_relpos1CrossNormal[0]);
- setElem(J,i,6*bodyIndex0+4,m_allConstraintPtrArray[i]->m_relpos1CrossNormal[1]);
- setElem(J,i,6*bodyIndex0+5,m_allConstraintPtrArray[i]->m_relpos1CrossNormal[2]);
+ setElem(J, i, 6 * bodyIndex0 + 0, m_allConstraintPtrArray[i]->m_contactNormal1[0]);
+ setElem(J, i, 6 * bodyIndex0 + 1, m_allConstraintPtrArray[i]->m_contactNormal1[1]);
+ setElem(J, i, 6 * bodyIndex0 + 2, m_allConstraintPtrArray[i]->m_contactNormal1[2]);
+ setElem(J, i, 6 * bodyIndex0 + 3, m_allConstraintPtrArray[i]->m_relpos1CrossNormal[0]);
+ setElem(J, i, 6 * bodyIndex0 + 4, m_allConstraintPtrArray[i]->m_relpos1CrossNormal[1]);
+ setElem(J, i, 6 * bodyIndex0 + 5, m_allConstraintPtrArray[i]->m_relpos1CrossNormal[2]);
}
if (m_tmpSolverBodyPool[bodyIndex1].m_originalBody)
{
- setElem(J,i,6*bodyIndex1+0,m_allConstraintPtrArray[i]->m_contactNormal2[0]);
- setElem(J,i,6*bodyIndex1+1,m_allConstraintPtrArray[i]->m_contactNormal2[1]);
- setElem(J,i,6*bodyIndex1+2,m_allConstraintPtrArray[i]->m_contactNormal2[2]);
- setElem(J,i,6*bodyIndex1+3,m_allConstraintPtrArray[i]->m_relpos2CrossNormal[0]);
- setElem(J,i,6*bodyIndex1+4,m_allConstraintPtrArray[i]->m_relpos2CrossNormal[1]);
- setElem(J,i,6*bodyIndex1+5,m_allConstraintPtrArray[i]->m_relpos2CrossNormal[2]);
+ setElem(J, i, 6 * bodyIndex1 + 0, m_allConstraintPtrArray[i]->m_contactNormal2[0]);
+ setElem(J, i, 6 * bodyIndex1 + 1, m_allConstraintPtrArray[i]->m_contactNormal2[1]);
+ setElem(J, i, 6 * bodyIndex1 + 2, m_allConstraintPtrArray[i]->m_contactNormal2[2]);
+ setElem(J, i, 6 * bodyIndex1 + 3, m_allConstraintPtrArray[i]->m_relpos2CrossNormal[0]);
+ setElem(J, i, 6 * bodyIndex1 + 4, m_allConstraintPtrArray[i]->m_relpos2CrossNormal[1]);
+ setElem(J, i, 6 * bodyIndex1 + 5, m_allConstraintPtrArray[i]->m_relpos2CrossNormal[2]);
}
}
-
- btMatrixXu& J_transpose = m_scratchJTranspose;
- J_transpose= J.transpose();
- btMatrixXu& tmp = m_scratchTmp;
+ btMatrixXu& J_transpose = m_scratchJTranspose;
+ J_transpose = J.transpose();
+
+ btMatrixXu& tmp = m_scratchTmp;
{
{
BT_PROFILE("J*Minv");
- tmp = J*Minv;
-
+ tmp = J * Minv;
}
{
BT_PROFILE("J*tmp");
- m_A = tmp*J_transpose;
+ m_A = tmp * J_transpose;
}
}
if (1)
{
// add cfm to the diagonal of m_A
- for ( int i=0; i<m_A.rows(); ++i)
+ for (int i = 0; i < m_A.rows(); ++i)
{
- m_A.setElem(i,i,m_A(i,i)+ infoGlobal.m_globalCfm / infoGlobal.m_timeStep);
+ m_A.setElem(i, i, m_A(i, i) + infoGlobal.m_globalCfm / infoGlobal.m_timeStep);
}
}
m_x.resize(numConstraintRows);
if (infoGlobal.m_splitImpulse)
m_xSplit.resize(numConstraintRows);
-// m_x.setZero();
+ // m_x.setZero();
- for (int i=0;i<m_allConstraintPtrArray.size();i++)
+ for (int i = 0; i < m_allConstraintPtrArray.size(); i++)
{
const btSolverConstraint& c = *m_allConstraintPtrArray[i];
- m_x[i]=c.m_appliedImpulse;
+ m_x[i] = c.m_appliedImpulse;
if (infoGlobal.m_splitImpulse)
m_xSplit[i] = c.m_appliedPushImpulse;
}
-
}
-
-btScalar btMLCPSolver::solveGroupCacheFriendlyIterations(btCollisionObject** bodies ,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer)
+btScalar btMLCPSolver::solveGroupCacheFriendlyIterations(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
{
bool result = true;
{
BT_PROFILE("solveMLCP");
-// printf("m_A(%d,%d)\n", m_A.rows(),m_A.cols());
+ // printf("m_A(%d,%d)\n", m_A.rows(),m_A.cols());
result = solveMLCP(infoGlobal);
}
@@ -596,44 +580,41 @@ btScalar btMLCPSolver::solveGroupCacheFriendlyIterations(btCollisionObject** bod
if (result)
{
BT_PROFILE("process MLCP results");
- for (int i=0;i<m_allConstraintPtrArray.size();i++)
+ for (int i = 0; i < m_allConstraintPtrArray.size(); i++)
{
{
btSolverConstraint& c = *m_allConstraintPtrArray[i];
int sbA = c.m_solverBodyIdA;
int sbB = c.m_solverBodyIdB;
//btRigidBody* orgBodyA = m_tmpSolverBodyPool[sbA].m_originalBody;
- // btRigidBody* orgBodyB = m_tmpSolverBodyPool[sbB].m_originalBody;
+ // btRigidBody* orgBodyB = m_tmpSolverBodyPool[sbB].m_originalBody;
btSolverBody& solverBodyA = m_tmpSolverBodyPool[sbA];
btSolverBody& solverBodyB = m_tmpSolverBodyPool[sbB];
-
+
{
- btScalar deltaImpulse = m_x[i]-c.m_appliedImpulse;
+ btScalar deltaImpulse = m_x[i] - c.m_appliedImpulse;
c.m_appliedImpulse = m_x[i];
- solverBodyA.internalApplyImpulse(c.m_contactNormal1*solverBodyA.internalGetInvMass(),c.m_angularComponentA,deltaImpulse);
- solverBodyB.internalApplyImpulse(c.m_contactNormal2*solverBodyB.internalGetInvMass(),c.m_angularComponentB,deltaImpulse);
+ solverBodyA.internalApplyImpulse(c.m_contactNormal1 * solverBodyA.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
+ solverBodyB.internalApplyImpulse(c.m_contactNormal2 * solverBodyB.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
}
if (infoGlobal.m_splitImpulse)
{
btScalar deltaImpulse = m_xSplit[i] - c.m_appliedPushImpulse;
- solverBodyA.internalApplyPushImpulse(c.m_contactNormal1*solverBodyA.internalGetInvMass(),c.m_angularComponentA,deltaImpulse);
- solverBodyB.internalApplyPushImpulse(c.m_contactNormal2*solverBodyB.internalGetInvMass(),c.m_angularComponentB,deltaImpulse);
+ solverBodyA.internalApplyPushImpulse(c.m_contactNormal1 * solverBodyA.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
+ solverBodyB.internalApplyPushImpulse(c.m_contactNormal2 * solverBodyB.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
c.m_appliedPushImpulse = m_xSplit[i];
}
-
}
}
}
else
{
- // printf("m_fallback = %d\n",m_fallback);
+ // printf("m_fallback = %d\n",m_fallback);
m_fallback++;
- btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations(bodies ,numBodies,manifoldPtr, numManifolds,constraints,numConstraints,infoGlobal,debugDrawer);
+ btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations(bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
}
return 0.f;
}
-
-
diff --git a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btMLCPSolver.h b/thirdparty/bullet/BulletDynamics/MLCPSolvers/btMLCPSolver.h
index 26b482ddc1..510ae59e58 100644
--- a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btMLCPSolver.h
+++ b/thirdparty/bullet/BulletDynamics/MLCPSolvers/btMLCPSolver.h
@@ -23,15 +23,13 @@ subject to the following restrictions:
class btMLCPSolver : public btSequentialImpulseConstraintSolver
{
-
protected:
-
btMatrixXu m_A;
btVectorXu m_b;
btVectorXu m_x;
btVectorXu m_lo;
btVectorXu m_hi;
-
+
///when using 'split impulse' we solve two separate (M)LCPs
btVectorXu m_bSplit;
btVectorXu m_xSplit;
@@ -39,24 +37,23 @@ protected:
btVectorXu m_xSplit2;
btAlignedObjectArray<int> m_limitDependencies;
- btAlignedObjectArray<btSolverConstraint*> m_allConstraintPtrArray;
+ btAlignedObjectArray<btSolverConstraint*> m_allConstraintPtrArray;
btMLCPSolverInterface* m_solver;
int m_fallback;
- /// The following scratch variables are not stateful -- contents are cleared prior to each use.
- /// They are only cached here to avoid extra memory allocations and deallocations and to ensure
- /// that multiple instances of the solver can be run in parallel.
- btMatrixXu m_scratchJ3;
- btMatrixXu m_scratchJInvM3;
- btAlignedObjectArray<int> m_scratchOfs;
- btMatrixXu m_scratchMInv;
- btMatrixXu m_scratchJ;
- btMatrixXu m_scratchJTranspose;
- btMatrixXu m_scratchTmp;
-
- virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer);
- virtual btScalar solveGroupCacheFriendlyIterations(btCollisionObject** bodies ,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer);
+ /// The following scratch variables are not stateful -- contents are cleared prior to each use.
+ /// They are only cached here to avoid extra memory allocations and deallocations and to ensure
+ /// that multiple instances of the solver can be run in parallel.
+ btMatrixXu m_scratchJ3;
+ btMatrixXu m_scratchJInvM3;
+ btAlignedObjectArray<int> m_scratchOfs;
+ btMatrixXu m_scratchMInv;
+ btMatrixXu m_scratchJ;
+ btMatrixXu m_scratchJTranspose;
+ btMatrixXu m_scratchTmp;
+ virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
+ virtual btScalar solveGroupCacheFriendlyIterations(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
virtual void createMLCP(const btContactSolverInfo& infoGlobal);
virtual void createMLCPFast(const btContactSolverInfo& infoGlobal);
@@ -65,8 +62,7 @@ protected:
virtual bool solveMLCP(const btContactSolverInfo& infoGlobal);
public:
-
- btMLCPSolver( btMLCPSolverInterface* solver);
+ btMLCPSolver(btMLCPSolverInterface* solver);
virtual ~btMLCPSolver();
void setMLCPSolver(btMLCPSolverInterface* solver)
@@ -83,12 +79,10 @@ public:
m_fallback = num;
}
- virtual btConstraintSolverType getSolverType() const
+ virtual btConstraintSolverType getSolverType() const
{
return BT_MLCP_SOLVER;
}
-
};
-
-#endif //BT_MLCP_SOLVER_H
+#endif //BT_MLCP_SOLVER_H
diff --git a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btMLCPSolverInterface.h b/thirdparty/bullet/BulletDynamics/MLCPSolvers/btMLCPSolverInterface.h
index 25bb3f6d32..6b0465b88d 100644
--- a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btMLCPSolverInterface.h
+++ b/thirdparty/bullet/BulletDynamics/MLCPSolvers/btMLCPSolverInterface.h
@@ -27,7 +27,7 @@ public:
}
//return true is it solves the problem successfully
- virtual bool solveMLCP(const btMatrixXu & A, const btVectorXu & b, btVectorXu& x, const btVectorXu & lo,const btVectorXu & hi,const btAlignedObjectArray<int>& limitDependency, int numIterations, bool useSparsity = true)=0;
+ virtual bool solveMLCP(const btMatrixXu& A, const btVectorXu& b, btVectorXu& x, const btVectorXu& lo, const btVectorXu& hi, const btAlignedObjectArray<int>& limitDependency, int numIterations, bool useSparsity = true) = 0;
};
-#endif //BT_MLCP_SOLVER_INTERFACE_H
+#endif //BT_MLCP_SOLVER_INTERFACE_H
diff --git a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btPATHSolver.h b/thirdparty/bullet/BulletDynamics/MLCPSolvers/btPATHSolver.h
index 9ec31a6d4e..7f8eec3f6e 100644
--- a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btPATHSolver.h
+++ b/thirdparty/bullet/BulletDynamics/MLCPSolvers/btPATHSolver.h
@@ -14,38 +14,35 @@ subject to the following restrictions:
*/
///original version written by Erwin Coumans, October 2013
-
#ifndef BT_PATH_SOLVER_H
#define BT_PATH_SOLVER_H
//#define BT_USE_PATH
#ifdef BT_USE_PATH
-extern "C" {
+extern "C"
+{
#include "PATH/SimpleLCP.h"
#include "PATH/License.h"
#include "PATH/Error_Interface.h"
};
- void __stdcall MyError(Void *data, Char *msg)
+void __stdcall MyError(Void *data, Char *msg)
{
- printf("Path Error: %s\n",msg);
+ printf("Path Error: %s\n", msg);
}
- void __stdcall MyWarning(Void *data, Char *msg)
+void __stdcall MyWarning(Void *data, Char *msg)
{
- printf("Path Warning: %s\n",msg);
+ printf("Path Warning: %s\n", msg);
}
Error_Interface e;
-
-
#include "btMLCPSolverInterface.h"
#include "Dantzig/lcp.h"
class btPathSolver : public btMLCPSolverInterface
{
public:
-
btPathSolver()
{
License_SetString("2069810742&Courtesy_License&&&USR&2013&14_12_2011&1000&PATH&GEN&31_12_2013&0_0_0&0&0_0");
@@ -55,17 +52,15 @@ public:
Error_SetInterface(&e);
}
-
- virtual bool solveMLCP(const btMatrixXu & A, const btVectorXu & b, btVectorXu& x, const btVectorXu & lo,const btVectorXu & hi,const btAlignedObjectArray<int>& limitDependency, int numIterations, bool useSparsity = true)
+ virtual bool solveMLCP(const btMatrixXu &A, const btVectorXu &b, btVectorXu &x, const btVectorXu &lo, const btVectorXu &hi, const btAlignedObjectArray<int> &limitDependency, int numIterations, bool useSparsity = true)
{
MCP_Termination status;
-
int numVariables = b.rows();
- if (0==numVariables)
+ if (0 == numVariables)
return true;
- /* - variables - the number of variables in the problem
+ /* - variables - the number of variables in the problem
- m_nnz - the number of nonzeros in the M matrix
- m_i - a vector of size m_nnz containing the row indices for M
- m_j - a vector of size m_nnz containing the column indices for M
@@ -78,16 +73,16 @@ public:
btAlignedObjectArray<int> rowIndices;
btAlignedObjectArray<int> colIndices;
- for (int i=0;i<A.rows();i++)
+ for (int i = 0; i < A.rows(); i++)
{
- for (int j=0;j<A.cols();j++)
+ for (int j = 0; j < A.cols(); j++)
{
- if (A(i,j)!=0.f)
+ if (A(i, j) != 0.f)
{
//add 1, because Path starts at 1, instead of 0
- rowIndices.push_back(i+1);
- colIndices.push_back(j+1);
- values.push_back(A(i,j));
+ rowIndices.push_back(i + 1);
+ colIndices.push_back(j + 1);
+ values.push_back(A(i, j));
}
}
}
@@ -97,19 +92,18 @@ public:
btAlignedObjectArray<double> rhs;
btAlignedObjectArray<double> upperBounds;
btAlignedObjectArray<double> lowerBounds;
- for (int i=0;i<numVariables;i++)
+ for (int i = 0; i < numVariables; i++)
{
upperBounds.push_back(hi[i]);
lowerBounds.push_back(lo[i]);
rhs.push_back(-b[i]);
}
-
- SimpleLCP(numVariables,numNonZero,&rowIndices[0],&colIndices[0],&values[0],&rhs[0],&lowerBounds[0],&upperBounds[0], &status, &zResult[0]);
+ SimpleLCP(numVariables, numNonZero, &rowIndices[0], &colIndices[0], &values[0], &rhs[0], &lowerBounds[0], &upperBounds[0], &status, &zResult[0]);
if (status != MCP_Solved)
{
- static const char* gReturnMsgs[] = {
+ static const char *gReturnMsgs[] = {
"Invalid return",
"MCP_Solved: The problem was solved",
"MCP_NoProgress: A stationary point was found",
@@ -122,16 +116,16 @@ public:
"MCP_Infeasible: Problem has no solution",
"MCP_Error: An error occurred within the code",
"MCP_LicenseError: License could not be found",
- "MCP_OK"
- };
+ "MCP_OK"};
- printf("ERROR: The PATH MCP solver failed: %s\n", gReturnMsgs[(unsigned int)status]);// << std::endl;
+ printf("ERROR: The PATH MCP solver failed: %s\n", gReturnMsgs[(unsigned int)status]); // << std::endl;
printf("using Projected Gauss Seidel fallback\n");
-
+
return false;
- } else
+ }
+ else
{
- for (int i=0;i<numVariables;i++)
+ for (int i = 0; i < numVariables; i++)
{
x[i] = zResult[i];
//check for #NAN
@@ -139,13 +133,10 @@ public:
return false;
}
return true;
-
}
-
}
};
-#endif //BT_USE_PATH
-
+#endif //BT_USE_PATH
-#endif //BT_PATH_SOLVER_H
+#endif //BT_PATH_SOLVER_H
diff --git a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h b/thirdparty/bullet/BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h
index c0b40ffd9f..c3f4ec3997 100644
--- a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h
+++ b/thirdparty/bullet/BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h
@@ -17,25 +17,22 @@ subject to the following restrictions:
#ifndef BT_SOLVE_PROJECTED_GAUSS_SEIDEL_H
#define BT_SOLVE_PROJECTED_GAUSS_SEIDEL_H
-
#include "btMLCPSolverInterface.h"
///This solver is mainly for debug/learning purposes: it is functionally equivalent to the btSequentialImpulseConstraintSolver solver, but much slower (it builds the full LCP matrix)
class btSolveProjectedGaussSeidel : public btMLCPSolverInterface
{
-
public:
-
btScalar m_leastSquaresResidualThreshold;
btScalar m_leastSquaresResidual;
btSolveProjectedGaussSeidel()
- :m_leastSquaresResidualThreshold(0),
- m_leastSquaresResidual(0)
+ : m_leastSquaresResidualThreshold(0),
+ m_leastSquaresResidual(0)
{
}
- virtual bool solveMLCP(const btMatrixXu & A, const btVectorXu & b, btVectorXu& x, const btVectorXu & lo,const btVectorXu & hi,const btAlignedObjectArray<int>& limitDependency, int numIterations, bool useSparsity = true)
+ virtual bool solveMLCP(const btMatrixXu& A, const btVectorXu& b, btVectorXu& x, const btVectorXu& lo, const btVectorXu& hi, const btAlignedObjectArray<int>& limitDependency, int numIterations, bool useSparsity = true)
{
if (!A.rows())
return true;
@@ -46,65 +43,65 @@ public:
btAssert(A.rows() == b.rows());
int i, j, numRows = A.rows();
-
+
btScalar delta;
- for (int k = 0; k <numIterations; k++)
+ for (int k = 0; k < numIterations; k++)
{
m_leastSquaresResidual = 0.f;
- for (i = 0; i <numRows; i++)
+ for (i = 0; i < numRows; i++)
{
delta = 0.0f;
if (useSparsity)
{
- for (int h=0;h<A.m_rowNonZeroElements1[i].size();h++)
+ for (int h = 0; h < A.m_rowNonZeroElements1[i].size(); h++)
{
- int j = A.m_rowNonZeroElements1[i][h];
- if (j != i)//skip main diagonal
+ j = A.m_rowNonZeroElements1[i][h];
+ if (j != i) //skip main diagonal
{
- delta += A(i,j) * x[j];
+ delta += A(i, j) * x[j];
}
}
- } else
+ }
+ else
{
- for (j = 0; j <i; j++)
- delta += A(i,j) * x[j];
- for (j = i+1; j<numRows; j++)
- delta += A(i,j) * x[j];
+ for (j = 0; j < i; j++)
+ delta += A(i, j) * x[j];
+ for (j = i + 1; j < numRows; j++)
+ delta += A(i, j) * x[j];
}
- btScalar aDiag = A(i,i);
+ btScalar aDiag = A(i, i);
btScalar xOld = x[i];
- x [i] = (b [i] - delta) / aDiag;
+ x[i] = (b[i] - delta) / aDiag;
btScalar s = 1.f;
- if (limitDependency[i]>=0)
+ if (limitDependency[i] >= 0)
{
s = x[limitDependency[i]];
- if (s<0)
- s=1;
+ if (s < 0)
+ s = 1;
}
-
- if (x[i]<lo[i]*s)
- x[i]=lo[i]*s;
- if (x[i]>hi[i]*s)
- x[i]=hi[i]*s;
+
+ if (x[i] < lo[i] * s)
+ x[i] = lo[i] * s;
+ if (x[i] > hi[i] * s)
+ x[i] = hi[i] * s;
btScalar diff = x[i] - xOld;
- m_leastSquaresResidual += diff*diff;
+ m_leastSquaresResidual += diff * diff;
}
- btScalar eps = m_leastSquaresResidualThreshold;
- if ((m_leastSquaresResidual < eps) || (k >=(numIterations-1)))
+ btScalar eps = m_leastSquaresResidualThreshold;
+ if ((m_leastSquaresResidual < eps) || (k >= (numIterations - 1)))
{
#ifdef VERBOSE_PRINTF_RESIDUAL
- printf("totalLenSqr = %f at iteration #%d\n", m_leastSquaresResidual,k);
+ printf("totalLenSqr = %f at iteration #%d\n", m_leastSquaresResidual, k);
#endif
break;
}
}
return true;
}
-
};
-#endif //BT_SOLVE_PROJECTED_GAUSS_SEIDEL_H
+#endif //BT_SOLVE_PROJECTED_GAUSS_SEIDEL_H
diff --git a/thirdparty/bullet/BulletDynamics/Vehicle/btRaycastVehicle.cpp b/thirdparty/bullet/BulletDynamics/Vehicle/btRaycastVehicle.cpp
index f299aa34e8..fc70d8e637 100644
--- a/thirdparty/bullet/BulletDynamics/Vehicle/btRaycastVehicle.cpp
+++ b/thirdparty/bullet/BulletDynamics/Vehicle/btRaycastVehicle.cpp
@@ -24,17 +24,16 @@
#define ROLLING_INFLUENCE_FIX
-
btRigidBody& btActionInterface::getFixedBody()
{
- static btRigidBody s_fixed(0, 0,0);
- s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),btScalar(0.),btScalar(0.)));
+ static btRigidBody s_fixed(0, 0, 0);
+ s_fixed.setMassProps(btScalar(0.), btVector3(btScalar(0.), btScalar(0.), btScalar(0.)));
return s_fixed;
}
-btRaycastVehicle::btRaycastVehicle(const btVehicleTuning& tuning,btRigidBody* chassis, btVehicleRaycaster* raycaster )
-:m_vehicleRaycaster(raycaster),
-m_pitchControl(btScalar(0.))
+btRaycastVehicle::btRaycastVehicle(const btVehicleTuning& tuning, btRigidBody* chassis, btVehicleRaycaster* raycaster)
+ : m_vehicleRaycaster(raycaster),
+ m_pitchControl(btScalar(0.))
{
m_chassisBody = chassis;
m_indexRightAxis = 0;
@@ -43,28 +42,22 @@ m_pitchControl(btScalar(0.))
defaultInit(tuning);
}
-
void btRaycastVehicle::defaultInit(const btVehicleTuning& tuning)
{
(void)tuning;
m_currentVehicleSpeedKmHour = btScalar(0.);
m_steeringValue = btScalar(0.);
-
}
-
-
btRaycastVehicle::~btRaycastVehicle()
{
}
-
//
// basically most of the code is general for 2 or 4 wheel vehicles, but some of it needs to be reviewed
//
-btWheelInfo& btRaycastVehicle::addWheel( const btVector3& connectionPointCS, const btVector3& wheelDirectionCS0,const btVector3& wheelAxleCS, btScalar suspensionRestLength, btScalar wheelRadius,const btVehicleTuning& tuning, bool isFrontWheel)
+btWheelInfo& btRaycastVehicle::addWheel(const btVector3& connectionPointCS, const btVector3& wheelDirectionCS0, const btVector3& wheelAxleCS, btScalar suspensionRestLength, btScalar wheelRadius, const btVehicleTuning& tuning, bool isFrontWheel)
{
-
btWheelInfoConstructionInfo ci;
ci.m_chassisConnectionCS = connectionPointCS;
@@ -80,83 +73,76 @@ btWheelInfo& btRaycastVehicle::addWheel( const btVector3& connectionPointCS, con
ci.m_maxSuspensionTravelCm = tuning.m_maxSuspensionTravelCm;
ci.m_maxSuspensionForce = tuning.m_maxSuspensionForce;
- m_wheelInfo.push_back( btWheelInfo(ci));
-
- btWheelInfo& wheel = m_wheelInfo[getNumWheels()-1];
-
- updateWheelTransformsWS( wheel , false );
- updateWheelTransform(getNumWheels()-1,false);
- return wheel;
-}
-
+ m_wheelInfo.push_back(btWheelInfo(ci));
+ btWheelInfo& wheel = m_wheelInfo[getNumWheels() - 1];
+ updateWheelTransformsWS(wheel, false);
+ updateWheelTransform(getNumWheels() - 1, false);
+ return wheel;
+}
-const btTransform& btRaycastVehicle::getWheelTransformWS( int wheelIndex ) const
+const btTransform& btRaycastVehicle::getWheelTransformWS(int wheelIndex) const
{
btAssert(wheelIndex < getNumWheels());
const btWheelInfo& wheel = m_wheelInfo[wheelIndex];
return wheel.m_worldTransform;
-
}
-void btRaycastVehicle::updateWheelTransform( int wheelIndex , bool interpolatedTransform)
+void btRaycastVehicle::updateWheelTransform(int wheelIndex, bool interpolatedTransform)
{
-
- btWheelInfo& wheel = m_wheelInfo[ wheelIndex ];
- updateWheelTransformsWS(wheel,interpolatedTransform);
+ btWheelInfo& wheel = m_wheelInfo[wheelIndex];
+ updateWheelTransformsWS(wheel, interpolatedTransform);
btVector3 up = -wheel.m_raycastInfo.m_wheelDirectionWS;
const btVector3& right = wheel.m_raycastInfo.m_wheelAxleWS;
btVector3 fwd = up.cross(right);
fwd = fwd.normalize();
-// up = right.cross(fwd);
-// up.normalize();
+ // up = right.cross(fwd);
+ // up.normalize();
//rotate around steering over de wheelAxleWS
btScalar steering = wheel.m_steering;
-
- btQuaternion steeringOrn(up,steering);//wheel.m_steering);
+
+ btQuaternion steeringOrn(up, steering); //wheel.m_steering);
btMatrix3x3 steeringMat(steeringOrn);
- btQuaternion rotatingOrn(right,-wheel.m_rotation);
+ btQuaternion rotatingOrn(right, -wheel.m_rotation);
btMatrix3x3 rotatingMat(rotatingOrn);
- btMatrix3x3 basis2;
- basis2[0][m_indexRightAxis] = -right[0];
- basis2[1][m_indexRightAxis] = -right[1];
- basis2[2][m_indexRightAxis] = -right[2];
+ btMatrix3x3 basis2;
+ basis2[0][m_indexRightAxis] = -right[0];
+ basis2[1][m_indexRightAxis] = -right[1];
+ basis2[2][m_indexRightAxis] = -right[2];
- basis2[0][m_indexUpAxis] = up[0];
- basis2[1][m_indexUpAxis] = up[1];
- basis2[2][m_indexUpAxis] = up[2];
+ basis2[0][m_indexUpAxis] = up[0];
+ basis2[1][m_indexUpAxis] = up[1];
+ basis2[2][m_indexUpAxis] = up[2];
- basis2[0][m_indexForwardAxis] = fwd[0];
- basis2[1][m_indexForwardAxis] = fwd[1];
- basis2[2][m_indexForwardAxis] = fwd[2];
+ basis2[0][m_indexForwardAxis] = fwd[0];
+ basis2[1][m_indexForwardAxis] = fwd[1];
+ basis2[2][m_indexForwardAxis] = fwd[2];
wheel.m_worldTransform.setBasis(steeringMat * rotatingMat * basis2);
wheel.m_worldTransform.setOrigin(
- wheel.m_raycastInfo.m_hardPointWS + wheel.m_raycastInfo.m_wheelDirectionWS * wheel.m_raycastInfo.m_suspensionLength
- );
+ wheel.m_raycastInfo.m_hardPointWS + wheel.m_raycastInfo.m_wheelDirectionWS * wheel.m_raycastInfo.m_suspensionLength);
}
void btRaycastVehicle::resetSuspension()
{
-
int i;
- for (i=0;i<m_wheelInfo.size(); i++)
+ for (i = 0; i < m_wheelInfo.size(); i++)
{
- btWheelInfo& wheel = m_wheelInfo[i];
- wheel.m_raycastInfo.m_suspensionLength = wheel.getSuspensionRestLength();
- wheel.m_suspensionRelativeVelocity = btScalar(0.0);
-
- wheel.m_raycastInfo.m_contactNormalWS = - wheel.m_raycastInfo.m_wheelDirectionWS;
- //wheel_info.setContactFriction(btScalar(0.0));
- wheel.m_clippedInvContactDotSuspension = btScalar(1.0);
+ btWheelInfo& wheel = m_wheelInfo[i];
+ wheel.m_raycastInfo.m_suspensionLength = wheel.getSuspensionRestLength();
+ wheel.m_suspensionRelativeVelocity = btScalar(0.0);
+
+ wheel.m_raycastInfo.m_contactNormalWS = -wheel.m_raycastInfo.m_wheelDirectionWS;
+ //wheel_info.setContactFriction(btScalar(0.0));
+ wheel.m_clippedInvContactDotSuspension = btScalar(1.0);
}
}
-void btRaycastVehicle::updateWheelTransformsWS(btWheelInfo& wheel , bool interpolatedTransform)
+void btRaycastVehicle::updateWheelTransformsWS(btWheelInfo& wheel, bool interpolatedTransform)
{
wheel.m_raycastInfo.m_isInContact = false;
@@ -166,19 +152,18 @@ void btRaycastVehicle::updateWheelTransformsWS(btWheelInfo& wheel , bool interpo
getRigidBody()->getMotionState()->getWorldTransform(chassisTrans);
}
- wheel.m_raycastInfo.m_hardPointWS = chassisTrans( wheel.m_chassisConnectionPointCS );
- wheel.m_raycastInfo.m_wheelDirectionWS = chassisTrans.getBasis() * wheel.m_wheelDirectionCS ;
+ wheel.m_raycastInfo.m_hardPointWS = chassisTrans(wheel.m_chassisConnectionPointCS);
+ wheel.m_raycastInfo.m_wheelDirectionWS = chassisTrans.getBasis() * wheel.m_wheelDirectionCS;
wheel.m_raycastInfo.m_wheelAxleWS = chassisTrans.getBasis() * wheel.m_wheelAxleCS;
}
btScalar btRaycastVehicle::rayCast(btWheelInfo& wheel)
{
- updateWheelTransformsWS( wheel,false);
+ updateWheelTransformsWS(wheel, false);
-
btScalar depth = -1;
-
- btScalar raylen = wheel.getSuspensionRestLength()+wheel.m_wheelsRadius;
+
+ btScalar raylen = wheel.getSuspensionRestLength() + wheel.m_wheelsRadius;
btVector3 rayvector = wheel.m_raycastInfo.m_wheelDirectionWS * (raylen);
const btVector3& source = wheel.m_raycastInfo.m_hardPointWS;
@@ -186,12 +171,12 @@ btScalar btRaycastVehicle::rayCast(btWheelInfo& wheel)
const btVector3& target = wheel.m_raycastInfo.m_contactPointWS;
btScalar param = btScalar(0.);
-
- btVehicleRaycaster::btVehicleRaycasterResult rayResults;
+
+ btVehicleRaycaster::btVehicleRaycasterResult rayResults;
btAssert(m_vehicleRaycaster);
- void* object = m_vehicleRaycaster->castRay(source,target,rayResults);
+ void* object = m_vehicleRaycaster->castRay(source, target, rayResults);
wheel.m_raycastInfo.m_groundObject = 0;
@@ -199,19 +184,18 @@ btScalar btRaycastVehicle::rayCast(btWheelInfo& wheel)
{
param = rayResults.m_distFraction;
depth = raylen * rayResults.m_distFraction;
- wheel.m_raycastInfo.m_contactNormalWS = rayResults.m_hitNormalInWorld;
+ wheel.m_raycastInfo.m_contactNormalWS = rayResults.m_hitNormalInWorld;
wheel.m_raycastInfo.m_isInContact = true;
-
- wheel.m_raycastInfo.m_groundObject = &getFixedBody();///@todo for driving on dynamic/movable objects!;
- //wheel.m_raycastInfo.m_groundObject = object;
+ wheel.m_raycastInfo.m_groundObject = &getFixedBody(); ///@todo for driving on dynamic/movable objects!;
+ //wheel.m_raycastInfo.m_groundObject = object;
- btScalar hitDistance = param*raylen;
+ btScalar hitDistance = param * raylen;
wheel.m_raycastInfo.m_suspensionLength = hitDistance - wheel.m_wheelsRadius;
//clamp on max suspension travel
- btScalar minSuspensionLength = wheel.getSuspensionRestLength() - wheel.m_maxSuspensionTravelCm*btScalar(0.01);
- btScalar maxSuspensionLength = wheel.getSuspensionRestLength()+ wheel.m_maxSuspensionTravelCm*btScalar(0.01);
+ btScalar minSuspensionLength = wheel.getSuspensionRestLength() - wheel.m_maxSuspensionTravelCm * btScalar(0.01);
+ btScalar maxSuspensionLength = wheel.getSuspensionRestLength() + wheel.m_maxSuspensionTravelCm * btScalar(0.01);
if (wheel.m_raycastInfo.m_suspensionLength < minSuspensionLength)
{
wheel.m_raycastInfo.m_suspensionLength = minSuspensionLength;
@@ -223,16 +207,16 @@ btScalar btRaycastVehicle::rayCast(btWheelInfo& wheel)
wheel.m_raycastInfo.m_contactPointWS = rayResults.m_hitPointInWorld;
- btScalar denominator= wheel.m_raycastInfo.m_contactNormalWS.dot( wheel.m_raycastInfo.m_wheelDirectionWS );
+ btScalar denominator = wheel.m_raycastInfo.m_contactNormalWS.dot(wheel.m_raycastInfo.m_wheelDirectionWS);
btVector3 chassis_velocity_at_contactPoint;
- btVector3 relpos = wheel.m_raycastInfo.m_contactPointWS-getRigidBody()->getCenterOfMassPosition();
+ btVector3 relpos = wheel.m_raycastInfo.m_contactPointWS - getRigidBody()->getCenterOfMassPosition();
chassis_velocity_at_contactPoint = getRigidBody()->getVelocityInLocalPoint(relpos);
- btScalar projVel = wheel.m_raycastInfo.m_contactNormalWS.dot( chassis_velocity_at_contactPoint );
+ btScalar projVel = wheel.m_raycastInfo.m_contactNormalWS.dot(chassis_velocity_at_contactPoint);
- if ( denominator >= btScalar(-0.1))
+ if (denominator >= btScalar(-0.1))
{
wheel.m_suspensionRelativeVelocity = btScalar(0.0);
wheel.m_clippedInvContactDotSuspension = btScalar(1.0) / btScalar(0.1);
@@ -243,20 +227,19 @@ btScalar btRaycastVehicle::rayCast(btWheelInfo& wheel)
wheel.m_suspensionRelativeVelocity = projVel * inv;
wheel.m_clippedInvContactDotSuspension = inv;
}
-
- } else
+ }
+ else
{
//put wheel info as in rest position
wheel.m_raycastInfo.m_suspensionLength = wheel.getSuspensionRestLength();
wheel.m_suspensionRelativeVelocity = btScalar(0.0);
- wheel.m_raycastInfo.m_contactNormalWS = - wheel.m_raycastInfo.m_wheelDirectionWS;
+ wheel.m_raycastInfo.m_contactNormalWS = -wheel.m_raycastInfo.m_wheelDirectionWS;
wheel.m_clippedInvContactDotSuspension = btScalar(1.0);
}
return depth;
}
-
const btTransform& btRaycastVehicle::getChassisWorldTransform() const
{
/*if (getRigidBody()->getMotionState())
@@ -267,26 +250,23 @@ const btTransform& btRaycastVehicle::getChassisWorldTransform() const
}
*/
-
return getRigidBody()->getCenterOfMassTransform();
}
-
-void btRaycastVehicle::updateVehicle( btScalar step )
+void btRaycastVehicle::updateVehicle(btScalar step)
{
{
- for (int i=0;i<getNumWheels();i++)
+ for (int i = 0; i < getNumWheels(); i++)
{
- updateWheelTransform(i,false);
+ updateWheelTransform(i, false);
}
}
-
m_currentVehicleSpeedKmHour = btScalar(3.6) * getRigidBody()->getLinearVelocity().length();
-
+
const btTransform& chassisTrans = getChassisWorldTransform();
- btVector3 forwardW (
+ btVector3 forwardW(
chassisTrans.getBasis()[0][m_indexForwardAxis],
chassisTrans.getBasis()[1][m_indexForwardAxis],
chassisTrans.getBasis()[2][m_indexForwardAxis]);
@@ -299,52 +279,47 @@ void btRaycastVehicle::updateVehicle( btScalar step )
//
// simulate suspension
//
-
- int i=0;
- for (i=0;i<m_wheelInfo.size();i++)
+
+ int i = 0;
+ for (i = 0; i < m_wheelInfo.size(); i++)
{
- //btScalar depth;
- //depth =
- rayCast( m_wheelInfo[i]);
+ //btScalar depth;
+ //depth =
+ rayCast(m_wheelInfo[i]);
}
updateSuspension(step);
-
- for (i=0;i<m_wheelInfo.size();i++)
+ for (i = 0; i < m_wheelInfo.size(); i++)
{
//apply suspension force
btWheelInfo& wheel = m_wheelInfo[i];
-
+
btScalar suspensionForce = wheel.m_wheelsSuspensionForce;
-
+
if (suspensionForce > wheel.m_maxSuspensionForce)
{
suspensionForce = wheel.m_maxSuspensionForce;
}
btVector3 impulse = wheel.m_raycastInfo.m_contactNormalWS * suspensionForce * step;
btVector3 relpos = wheel.m_raycastInfo.m_contactPointWS - getRigidBody()->getCenterOfMassPosition();
-
+
getRigidBody()->applyImpulse(impulse, relpos);
-
}
-
-
- updateFriction( step);
+ updateFriction(step);
-
- for (i=0;i<m_wheelInfo.size();i++)
+ for (i = 0; i < m_wheelInfo.size(); i++)
{
btWheelInfo& wheel = m_wheelInfo[i];
btVector3 relpos = wheel.m_raycastInfo.m_hardPointWS - getRigidBody()->getCenterOfMassPosition();
- btVector3 vel = getRigidBody()->getVelocityInLocalPoint( relpos );
+ btVector3 vel = getRigidBody()->getVelocityInLocalPoint(relpos);
if (wheel.m_raycastInfo.m_isInContact)
{
- const btTransform& chassisWorldTransform = getChassisWorldTransform();
+ const btTransform& chassisWorldTransform = getChassisWorldTransform();
- btVector3 fwd (
+ btVector3 fwd(
chassisWorldTransform.getBasis()[0][m_indexForwardAxis],
chassisWorldTransform.getBasis()[1][m_indexForwardAxis],
chassisWorldTransform.getBasis()[2][m_indexForwardAxis]);
@@ -353,99 +328,88 @@ void btRaycastVehicle::updateVehicle( btScalar step )
fwd -= wheel.m_raycastInfo.m_contactNormalWS * proj;
btScalar proj2 = fwd.dot(vel);
-
+
wheel.m_deltaRotation = (proj2 * step) / (wheel.m_wheelsRadius);
wheel.m_rotation += wheel.m_deltaRotation;
-
- } else
+ }
+ else
{
wheel.m_rotation += wheel.m_deltaRotation;
}
-
- wheel.m_deltaRotation *= btScalar(0.99);//damping of rotation when not in contact
+ wheel.m_deltaRotation *= btScalar(0.99); //damping of rotation when not in contact
}
-
-
-
}
-
-void btRaycastVehicle::setSteeringValue(btScalar steering,int wheel)
+void btRaycastVehicle::setSteeringValue(btScalar steering, int wheel)
{
- btAssert(wheel>=0 && wheel < getNumWheels());
+ btAssert(wheel >= 0 && wheel < getNumWheels());
btWheelInfo& wheelInfo = getWheelInfo(wheel);
wheelInfo.m_steering = steering;
}
-
-
-btScalar btRaycastVehicle::getSteeringValue(int wheel) const
+btScalar btRaycastVehicle::getSteeringValue(int wheel) const
{
return getWheelInfo(wheel).m_steering;
}
-
-void btRaycastVehicle::applyEngineForce(btScalar force, int wheel)
+void btRaycastVehicle::applyEngineForce(btScalar force, int wheel)
{
- btAssert(wheel>=0 && wheel < getNumWheels());
+ btAssert(wheel >= 0 && wheel < getNumWheels());
btWheelInfo& wheelInfo = getWheelInfo(wheel);
wheelInfo.m_engineForce = force;
}
-
-const btWheelInfo& btRaycastVehicle::getWheelInfo(int index) const
+const btWheelInfo& btRaycastVehicle::getWheelInfo(int index) const
{
- btAssert((index >= 0) && (index < getNumWheels()));
-
+ btAssert((index >= 0) && (index < getNumWheels()));
+
return m_wheelInfo[index];
}
-btWheelInfo& btRaycastVehicle::getWheelInfo(int index)
+btWheelInfo& btRaycastVehicle::getWheelInfo(int index)
{
- btAssert((index >= 0) && (index < getNumWheels()));
-
+ btAssert((index >= 0) && (index < getNumWheels()));
+
return m_wheelInfo[index];
}
-void btRaycastVehicle::setBrake(btScalar brake,int wheelIndex)
+void btRaycastVehicle::setBrake(btScalar brake, int wheelIndex)
{
- btAssert((wheelIndex >= 0) && (wheelIndex < getNumWheels()));
+ btAssert((wheelIndex >= 0) && (wheelIndex < getNumWheels()));
getWheelInfo(wheelIndex).m_brake = brake;
}
-
-void btRaycastVehicle::updateSuspension(btScalar deltaTime)
+void btRaycastVehicle::updateSuspension(btScalar deltaTime)
{
(void)deltaTime;
btScalar chassisMass = btScalar(1.) / m_chassisBody->getInvMass();
-
- for (int w_it=0; w_it<getNumWheels(); w_it++)
+
+ for (int w_it = 0; w_it < getNumWheels(); w_it++)
{
- btWheelInfo &wheel_info = m_wheelInfo[w_it];
-
- if ( wheel_info.m_raycastInfo.m_isInContact )
+ btWheelInfo& wheel_info = m_wheelInfo[w_it];
+
+ if (wheel_info.m_raycastInfo.m_isInContact)
{
btScalar force;
// Spring
{
- btScalar susp_length = wheel_info.getSuspensionRestLength();
- btScalar current_length = wheel_info.m_raycastInfo.m_suspensionLength;
+ btScalar susp_length = wheel_info.getSuspensionRestLength();
+ btScalar current_length = wheel_info.m_raycastInfo.m_suspensionLength;
btScalar length_diff = (susp_length - current_length);
- force = wheel_info.m_suspensionStiffness
- * length_diff * wheel_info.m_clippedInvContactDotSuspension;
+ force = wheel_info.m_suspensionStiffness * length_diff * wheel_info.m_clippedInvContactDotSuspension;
}
-
+
// Damper
{
btScalar projected_rel_vel = wheel_info.m_suspensionRelativeVelocity;
{
- btScalar susp_damping;
- if ( projected_rel_vel < btScalar(0.0) )
+ btScalar susp_damping;
+ if (projected_rel_vel < btScalar(0.0))
{
susp_damping = wheel_info.m_wheelsDampingCompression;
}
@@ -469,50 +433,43 @@ void btRaycastVehicle::updateSuspension(btScalar deltaTime)
wheel_info.m_wheelsSuspensionForce = btScalar(0.0);
}
}
-
}
-
struct btWheelContactPoint
{
btRigidBody* m_body0;
btRigidBody* m_body1;
- btVector3 m_frictionPositionWorld;
- btVector3 m_frictionDirectionWorld;
- btScalar m_jacDiagABInv;
- btScalar m_maxImpulse;
-
-
- btWheelContactPoint(btRigidBody* body0,btRigidBody* body1,const btVector3& frictionPosWorld,const btVector3& frictionDirectionWorld, btScalar maxImpulse)
- :m_body0(body0),
- m_body1(body1),
- m_frictionPositionWorld(frictionPosWorld),
- m_frictionDirectionWorld(frictionDirectionWorld),
- m_maxImpulse(maxImpulse)
+ btVector3 m_frictionPositionWorld;
+ btVector3 m_frictionDirectionWorld;
+ btScalar m_jacDiagABInv;
+ btScalar m_maxImpulse;
+
+ btWheelContactPoint(btRigidBody* body0, btRigidBody* body1, const btVector3& frictionPosWorld, const btVector3& frictionDirectionWorld, btScalar maxImpulse)
+ : m_body0(body0),
+ m_body1(body1),
+ m_frictionPositionWorld(frictionPosWorld),
+ m_frictionDirectionWorld(frictionDirectionWorld),
+ m_maxImpulse(maxImpulse)
{
- btScalar denom0 = body0->computeImpulseDenominator(frictionPosWorld,frictionDirectionWorld);
- btScalar denom1 = body1->computeImpulseDenominator(frictionPosWorld,frictionDirectionWorld);
- btScalar relaxation = 1.f;
- m_jacDiagABInv = relaxation/(denom0+denom1);
+ btScalar denom0 = body0->computeImpulseDenominator(frictionPosWorld, frictionDirectionWorld);
+ btScalar denom1 = body1->computeImpulseDenominator(frictionPosWorld, frictionDirectionWorld);
+ btScalar relaxation = 1.f;
+ m_jacDiagABInv = relaxation / (denom0 + denom1);
}
-
-
-
};
btScalar calcRollingFriction(btWheelContactPoint& contactPoint, int numWheelsOnGround);
btScalar calcRollingFriction(btWheelContactPoint& contactPoint, int numWheelsOnGround)
{
-
- btScalar j1=0.f;
+ btScalar j1 = 0.f;
const btVector3& contactPosWorld = contactPoint.m_frictionPositionWorld;
- btVector3 rel_pos1 = contactPosWorld - contactPoint.m_body0->getCenterOfMassPosition();
+ btVector3 rel_pos1 = contactPosWorld - contactPoint.m_body0->getCenterOfMassPosition();
btVector3 rel_pos2 = contactPosWorld - contactPoint.m_body1->getCenterOfMassPosition();
-
- btScalar maxImpulse = contactPoint.m_maxImpulse;
-
+
+ btScalar maxImpulse = contactPoint.m_maxImpulse;
+
btVector3 vel1 = contactPoint.m_body0->getVelocityInLocalPoint(rel_pos1);
btVector3 vel2 = contactPoint.m_body1->getVelocityInLocalPoint(rel_pos2);
btVector3 vel = vel1 - vel2;
@@ -520,253 +477,225 @@ btScalar calcRollingFriction(btWheelContactPoint& contactPoint, int numWheelsOnG
btScalar vrel = contactPoint.m_frictionDirectionWorld.dot(vel);
// calculate j that moves us to zero relative velocity
- j1 = -vrel * contactPoint.m_jacDiagABInv/btScalar(numWheelsOnGround);
+ j1 = -vrel * contactPoint.m_jacDiagABInv / btScalar(numWheelsOnGround);
btSetMin(j1, maxImpulse);
btSetMax(j1, -maxImpulse);
return j1;
}
+btScalar sideFrictionStiffness2 = btScalar(1.0);
+void btRaycastVehicle::updateFriction(btScalar timeStep)
+{
+ //calculate the impulse, so that the wheels don't move sidewards
+ int numWheel = getNumWheels();
+ if (!numWheel)
+ return;
+ m_forwardWS.resize(numWheel);
+ m_axle.resize(numWheel);
+ m_forwardImpulse.resize(numWheel);
+ m_sideImpulse.resize(numWheel);
+ int numWheelsOnGround = 0;
-btScalar sideFrictionStiffness2 = btScalar(1.0);
-void btRaycastVehicle::updateFriction(btScalar timeStep)
-{
+ //collapse all those loops into one!
+ for (int i = 0; i < getNumWheels(); i++)
+ {
+ btWheelInfo& wheelInfo = m_wheelInfo[i];
+ class btRigidBody* groundObject = (class btRigidBody*)wheelInfo.m_raycastInfo.m_groundObject;
+ if (groundObject)
+ numWheelsOnGround++;
+ m_sideImpulse[i] = btScalar(0.);
+ m_forwardImpulse[i] = btScalar(0.);
+ }
- //calculate the impulse, so that the wheels don't move sidewards
- int numWheel = getNumWheels();
- if (!numWheel)
- return;
-
- m_forwardWS.resize(numWheel);
- m_axle.resize(numWheel);
- m_forwardImpulse.resize(numWheel);
- m_sideImpulse.resize(numWheel);
-
- int numWheelsOnGround = 0;
-
-
- //collapse all those loops into one!
- for (int i=0;i<getNumWheels();i++)
+ {
+ for (int i = 0; i < getNumWheels(); i++)
{
btWheelInfo& wheelInfo = m_wheelInfo[i];
- class btRigidBody* groundObject = (class btRigidBody*) wheelInfo.m_raycastInfo.m_groundObject;
- if (groundObject)
- numWheelsOnGround++;
- m_sideImpulse[i] = btScalar(0.);
- m_forwardImpulse[i] = btScalar(0.);
- }
-
- {
-
- for (int i=0;i<getNumWheels();i++)
+ class btRigidBody* groundObject = (class btRigidBody*)wheelInfo.m_raycastInfo.m_groundObject;
+
+ if (groundObject)
{
+ const btTransform& wheelTrans = getWheelTransformWS(i);
- btWheelInfo& wheelInfo = m_wheelInfo[i];
-
- class btRigidBody* groundObject = (class btRigidBody*) wheelInfo.m_raycastInfo.m_groundObject;
+ btMatrix3x3 wheelBasis0 = wheelTrans.getBasis();
+ m_axle[i] = -btVector3(
+ wheelBasis0[0][m_indexRightAxis],
+ wheelBasis0[1][m_indexRightAxis],
+ wheelBasis0[2][m_indexRightAxis]);
- if (groundObject)
- {
+ const btVector3& surfNormalWS = wheelInfo.m_raycastInfo.m_contactNormalWS;
+ btScalar proj = m_axle[i].dot(surfNormalWS);
+ m_axle[i] -= surfNormalWS * proj;
+ m_axle[i] = m_axle[i].normalize();
- const btTransform& wheelTrans = getWheelTransformWS( i );
-
- btMatrix3x3 wheelBasis0 = wheelTrans.getBasis();
- m_axle[i] = -btVector3(
- wheelBasis0[0][m_indexRightAxis],
- wheelBasis0[1][m_indexRightAxis],
- wheelBasis0[2][m_indexRightAxis]);
-
- const btVector3& surfNormalWS = wheelInfo.m_raycastInfo.m_contactNormalWS;
- btScalar proj = m_axle[i].dot(surfNormalWS);
- m_axle[i] -= surfNormalWS * proj;
- m_axle[i] = m_axle[i].normalize();
-
- m_forwardWS[i] = surfNormalWS.cross(m_axle[i]);
- m_forwardWS[i].normalize();
-
-
- resolveSingleBilateral(*m_chassisBody, wheelInfo.m_raycastInfo.m_contactPointWS,
- *groundObject, wheelInfo.m_raycastInfo.m_contactPointWS,
- btScalar(0.), m_axle[i],m_sideImpulse[i],timeStep);
-
- m_sideImpulse[i] *= sideFrictionStiffness2;
-
- }
-
+ m_forwardWS[i] = surfNormalWS.cross(m_axle[i]);
+ m_forwardWS[i].normalize();
+ resolveSingleBilateral(*m_chassisBody, wheelInfo.m_raycastInfo.m_contactPointWS,
+ *groundObject, wheelInfo.m_raycastInfo.m_contactPointWS,
+ btScalar(0.), m_axle[i], m_sideImpulse[i], timeStep);
+
+ m_sideImpulse[i] *= sideFrictionStiffness2;
}
}
+ }
btScalar sideFactor = btScalar(1.);
btScalar fwdFactor = 0.5;
bool sliding = false;
{
- for (int wheel =0;wheel <getNumWheels();wheel++)
+ for (int wheel = 0; wheel < getNumWheels(); wheel++)
{
btWheelInfo& wheelInfo = m_wheelInfo[wheel];
- class btRigidBody* groundObject = (class btRigidBody*) wheelInfo.m_raycastInfo.m_groundObject;
+ class btRigidBody* groundObject = (class btRigidBody*)wheelInfo.m_raycastInfo.m_groundObject;
- btScalar rollingFriction = 0.f;
+ btScalar rollingFriction = 0.f;
if (groundObject)
{
if (wheelInfo.m_engineForce != 0.f)
{
- rollingFriction = wheelInfo.m_engineForce* timeStep;
- } else
+ rollingFriction = wheelInfo.m_engineForce * timeStep;
+ }
+ else
{
btScalar defaultRollingFrictionImpulse = 0.f;
btScalar maxImpulse = wheelInfo.m_brake ? wheelInfo.m_brake : defaultRollingFrictionImpulse;
- btWheelContactPoint contactPt(m_chassisBody,groundObject,wheelInfo.m_raycastInfo.m_contactPointWS,m_forwardWS[wheel],maxImpulse);
+ btWheelContactPoint contactPt(m_chassisBody, groundObject, wheelInfo.m_raycastInfo.m_contactPointWS, m_forwardWS[wheel], maxImpulse);
btAssert(numWheelsOnGround > 0);
rollingFriction = calcRollingFriction(contactPt, numWheelsOnGround);
}
}
//switch between active rolling (throttle), braking and non-active rolling friction (no throttle/break)
-
-
-
m_forwardImpulse[wheel] = btScalar(0.);
- m_wheelInfo[wheel].m_skidInfo= btScalar(1.);
+ m_wheelInfo[wheel].m_skidInfo = btScalar(1.);
if (groundObject)
{
- m_wheelInfo[wheel].m_skidInfo= btScalar(1.);
-
+ m_wheelInfo[wheel].m_skidInfo = btScalar(1.);
+
btScalar maximp = wheelInfo.m_wheelsSuspensionForce * timeStep * wheelInfo.m_frictionSlip;
btScalar maximpSide = maximp;
btScalar maximpSquared = maximp * maximpSide;
-
- m_forwardImpulse[wheel] = rollingFriction;//wheelInfo.m_engineForce* timeStep;
+ m_forwardImpulse[wheel] = rollingFriction; //wheelInfo.m_engineForce* timeStep;
+
+ btScalar x = (m_forwardImpulse[wheel]) * fwdFactor;
+ btScalar y = (m_sideImpulse[wheel]) * sideFactor;
- btScalar x = (m_forwardImpulse[wheel] ) * fwdFactor;
- btScalar y = (m_sideImpulse[wheel] ) * sideFactor;
-
- btScalar impulseSquared = (x*x + y*y);
+ btScalar impulseSquared = (x * x + y * y);
if (impulseSquared > maximpSquared)
{
sliding = true;
-
+
btScalar factor = maximp / btSqrt(impulseSquared);
-
+
m_wheelInfo[wheel].m_skidInfo *= factor;
}
- }
-
+ }
}
}
-
-
-
- if (sliding)
+ if (sliding)
+ {
+ for (int wheel = 0; wheel < getNumWheels(); wheel++)
{
- for (int wheel = 0;wheel < getNumWheels(); wheel++)
+ if (m_sideImpulse[wheel] != btScalar(0.))
{
- if (m_sideImpulse[wheel] != btScalar(0.))
+ if (m_wheelInfo[wheel].m_skidInfo < btScalar(1.))
{
- if (m_wheelInfo[wheel].m_skidInfo< btScalar(1.))
- {
- m_forwardImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo;
- m_sideImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo;
- }
+ m_forwardImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo;
+ m_sideImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo;
}
}
}
+ }
- // apply the impulses
+ // apply the impulses
+ {
+ for (int wheel = 0; wheel < getNumWheels(); wheel++)
{
- for (int wheel = 0;wheel<getNumWheels() ; wheel++)
- {
- btWheelInfo& wheelInfo = m_wheelInfo[wheel];
+ btWheelInfo& wheelInfo = m_wheelInfo[wheel];
- btVector3 rel_pos = wheelInfo.m_raycastInfo.m_contactPointWS -
- m_chassisBody->getCenterOfMassPosition();
+ btVector3 rel_pos = wheelInfo.m_raycastInfo.m_contactPointWS -
+ m_chassisBody->getCenterOfMassPosition();
- if (m_forwardImpulse[wheel] != btScalar(0.))
- {
- m_chassisBody->applyImpulse(m_forwardWS[wheel]*(m_forwardImpulse[wheel]),rel_pos);
- }
- if (m_sideImpulse[wheel] != btScalar(0.))
- {
- class btRigidBody* groundObject = (class btRigidBody*) m_wheelInfo[wheel].m_raycastInfo.m_groundObject;
+ if (m_forwardImpulse[wheel] != btScalar(0.))
+ {
+ m_chassisBody->applyImpulse(m_forwardWS[wheel] * (m_forwardImpulse[wheel]), rel_pos);
+ }
+ if (m_sideImpulse[wheel] != btScalar(0.))
+ {
+ class btRigidBody* groundObject = (class btRigidBody*)m_wheelInfo[wheel].m_raycastInfo.m_groundObject;
- btVector3 rel_pos2 = wheelInfo.m_raycastInfo.m_contactPointWS -
- groundObject->getCenterOfMassPosition();
+ btVector3 rel_pos2 = wheelInfo.m_raycastInfo.m_contactPointWS -
+ groundObject->getCenterOfMassPosition();
-
- btVector3 sideImp = m_axle[wheel] * m_sideImpulse[wheel];
+ btVector3 sideImp = m_axle[wheel] * m_sideImpulse[wheel];
-#if defined ROLLING_INFLUENCE_FIX // fix. It only worked if car's up was along Y - VT.
- btVector3 vChassisWorldUp = getRigidBody()->getCenterOfMassTransform().getBasis().getColumn(m_indexUpAxis);
- rel_pos -= vChassisWorldUp * (vChassisWorldUp.dot(rel_pos) * (1.f-wheelInfo.m_rollInfluence));
+#if defined ROLLING_INFLUENCE_FIX // fix. It only worked if car's up was along Y - VT.
+ btVector3 vChassisWorldUp = getRigidBody()->getCenterOfMassTransform().getBasis().getColumn(m_indexUpAxis);
+ rel_pos -= vChassisWorldUp * (vChassisWorldUp.dot(rel_pos) * (1.f - wheelInfo.m_rollInfluence));
#else
- rel_pos[m_indexUpAxis] *= wheelInfo.m_rollInfluence;
+ rel_pos[m_indexUpAxis] *= wheelInfo.m_rollInfluence;
#endif
- m_chassisBody->applyImpulse(sideImp,rel_pos);
+ m_chassisBody->applyImpulse(sideImp, rel_pos);
- //apply friction impulse on the ground
- groundObject->applyImpulse(-sideImp,rel_pos2);
- }
+ //apply friction impulse on the ground
+ groundObject->applyImpulse(-sideImp, rel_pos2);
}
}
-
-
+ }
}
-
-
-void btRaycastVehicle::debugDraw(btIDebugDraw* debugDrawer)
+void btRaycastVehicle::debugDraw(btIDebugDraw* debugDrawer)
{
-
- for (int v=0;v<this->getNumWheels();v++)
+ for (int v = 0; v < this->getNumWheels(); v++)
{
- btVector3 wheelColor(0,1,1);
+ btVector3 wheelColor(0, 1, 1);
if (getWheelInfo(v).m_raycastInfo.m_isInContact)
{
- wheelColor.setValue(0,0,1);
- } else
+ wheelColor.setValue(0, 0, 1);
+ }
+ else
{
- wheelColor.setValue(1,0,1);
+ wheelColor.setValue(1, 0, 1);
}
btVector3 wheelPosWS = getWheelInfo(v).m_worldTransform.getOrigin();
- btVector3 axle = btVector3(
+ btVector3 axle = btVector3(
getWheelInfo(v).m_worldTransform.getBasis()[0][getRightAxis()],
getWheelInfo(v).m_worldTransform.getBasis()[1][getRightAxis()],
getWheelInfo(v).m_worldTransform.getBasis()[2][getRightAxis()]);
//debug wheels (cylinders)
- debugDrawer->drawLine(wheelPosWS,wheelPosWS+axle,wheelColor);
- debugDrawer->drawLine(wheelPosWS,getWheelInfo(v).m_raycastInfo.m_contactPointWS,wheelColor);
-
+ debugDrawer->drawLine(wheelPosWS, wheelPosWS + axle, wheelColor);
+ debugDrawer->drawLine(wheelPosWS, getWheelInfo(v).m_raycastInfo.m_contactPointWS, wheelColor);
}
}
-
-void* btDefaultVehicleRaycaster::castRay(const btVector3& from,const btVector3& to, btVehicleRaycasterResult& result)
+void* btDefaultVehicleRaycaster::castRay(const btVector3& from, const btVector3& to, btVehicleRaycasterResult& result)
{
-// RayResultCallback& resultCallback;
+ // RayResultCallback& resultCallback;
- btCollisionWorld::ClosestRayResultCallback rayCallback(from,to);
+ btCollisionWorld::ClosestRayResultCallback rayCallback(from, to);
m_dynamicsWorld->rayTest(from, to, rayCallback);
if (rayCallback.hasHit())
{
-
const btRigidBody* body = btRigidBody::upcast(rayCallback.m_collisionObject);
- if (body && body->hasContactResponse())
+ if (body && body->hasContactResponse())
{
result.m_hitPointInWorld = rayCallback.m_hitPointWorld;
result.m_hitNormalInWorld = rayCallback.m_hitNormalWorld;
@@ -777,4 +706,3 @@ void* btDefaultVehicleRaycaster::castRay(const btVector3& from,const btVector3&
}
return 0;
}
-
diff --git a/thirdparty/bullet/BulletDynamics/Vehicle/btRaycastVehicle.h b/thirdparty/bullet/BulletDynamics/Vehicle/btRaycastVehicle.h
index 04656b912c..99d6894e56 100644
--- a/thirdparty/bullet/BulletDynamics/Vehicle/btRaycastVehicle.h
+++ b/thirdparty/bullet/BulletDynamics/Vehicle/btRaycastVehicle.h
@@ -24,122 +24,111 @@ class btDynamicsWorld;
///rayCast vehicle, very special constraint that turn a rigidbody into a vehicle.
class btRaycastVehicle : public btActionInterface
{
+ btAlignedObjectArray<btVector3> m_forwardWS;
+ btAlignedObjectArray<btVector3> m_axle;
+ btAlignedObjectArray<btScalar> m_forwardImpulse;
+ btAlignedObjectArray<btScalar> m_sideImpulse;
- btAlignedObjectArray<btVector3> m_forwardWS;
- btAlignedObjectArray<btVector3> m_axle;
- btAlignedObjectArray<btScalar> m_forwardImpulse;
- btAlignedObjectArray<btScalar> m_sideImpulse;
-
- ///backwards compatibility
- int m_userConstraintType;
- int m_userConstraintId;
+ ///backwards compatibility
+ int m_userConstraintType;
+ int m_userConstraintId;
public:
class btVehicleTuning
+ {
+ public:
+ btVehicleTuning()
+ : m_suspensionStiffness(btScalar(5.88)),
+ m_suspensionCompression(btScalar(0.83)),
+ m_suspensionDamping(btScalar(0.88)),
+ m_maxSuspensionTravelCm(btScalar(500.)),
+ m_frictionSlip(btScalar(10.5)),
+ m_maxSuspensionForce(btScalar(6000.))
{
- public:
-
- btVehicleTuning()
- :m_suspensionStiffness(btScalar(5.88)),
- m_suspensionCompression(btScalar(0.83)),
- m_suspensionDamping(btScalar(0.88)),
- m_maxSuspensionTravelCm(btScalar(500.)),
- m_frictionSlip(btScalar(10.5)),
- m_maxSuspensionForce(btScalar(6000.))
- {
- }
- btScalar m_suspensionStiffness;
- btScalar m_suspensionCompression;
- btScalar m_suspensionDamping;
- btScalar m_maxSuspensionTravelCm;
- btScalar m_frictionSlip;
- btScalar m_maxSuspensionForce;
-
- };
-private:
+ }
+ btScalar m_suspensionStiffness;
+ btScalar m_suspensionCompression;
+ btScalar m_suspensionDamping;
+ btScalar m_maxSuspensionTravelCm;
+ btScalar m_frictionSlip;
+ btScalar m_maxSuspensionForce;
+ };
- btVehicleRaycaster* m_vehicleRaycaster;
- btScalar m_pitchControl;
- btScalar m_steeringValue;
+private:
+ btVehicleRaycaster* m_vehicleRaycaster;
+ btScalar m_pitchControl;
+ btScalar m_steeringValue;
btScalar m_currentVehicleSpeedKmHour;
btRigidBody* m_chassisBody;
int m_indexRightAxis;
int m_indexUpAxis;
- int m_indexForwardAxis;
+ int m_indexForwardAxis;
void defaultInit(const btVehicleTuning& tuning);
public:
-
//constructor to create a car from an existing rigidbody
- btRaycastVehicle(const btVehicleTuning& tuning,btRigidBody* chassis, btVehicleRaycaster* raycaster );
-
- virtual ~btRaycastVehicle() ;
+ btRaycastVehicle(const btVehicleTuning& tuning, btRigidBody* chassis, btVehicleRaycaster* raycaster);
+ virtual ~btRaycastVehicle();
///btActionInterface interface
- virtual void updateAction( btCollisionWorld* collisionWorld, btScalar step)
+ virtual void updateAction(btCollisionWorld* collisionWorld, btScalar step)
{
- (void) collisionWorld;
+ (void)collisionWorld;
updateVehicle(step);
}
-
///btActionInterface interface
- void debugDraw(btIDebugDraw* debugDrawer);
-
+ void debugDraw(btIDebugDraw* debugDrawer);
+
const btTransform& getChassisWorldTransform() const;
-
+
btScalar rayCast(btWheelInfo& wheel);
virtual void updateVehicle(btScalar step);
-
-
+
void resetSuspension();
- btScalar getSteeringValue(int wheel) const;
+ btScalar getSteeringValue(int wheel) const;
- void setSteeringValue(btScalar steering,int wheel);
+ void setSteeringValue(btScalar steering, int wheel);
+ void applyEngineForce(btScalar force, int wheel);
- void applyEngineForce(btScalar force, int wheel);
+ const btTransform& getWheelTransformWS(int wheelIndex) const;
- const btTransform& getWheelTransformWS( int wheelIndex ) const;
+ void updateWheelTransform(int wheelIndex, bool interpolatedTransform = true);
- void updateWheelTransform( int wheelIndex, bool interpolatedTransform = true );
-
-// void setRaycastWheelInfo( int wheelIndex , bool isInContact, const btVector3& hitPoint, const btVector3& hitNormal,btScalar depth);
+ // void setRaycastWheelInfo( int wheelIndex , bool isInContact, const btVector3& hitPoint, const btVector3& hitNormal,btScalar depth);
- btWheelInfo& addWheel( const btVector3& connectionPointCS0, const btVector3& wheelDirectionCS0,const btVector3& wheelAxleCS,btScalar suspensionRestLength,btScalar wheelRadius,const btVehicleTuning& tuning, bool isFrontWheel);
+ btWheelInfo& addWheel(const btVector3& connectionPointCS0, const btVector3& wheelDirectionCS0, const btVector3& wheelAxleCS, btScalar suspensionRestLength, btScalar wheelRadius, const btVehicleTuning& tuning, bool isFrontWheel);
- inline int getNumWheels() const {
- return int (m_wheelInfo.size());
+ inline int getNumWheels() const
+ {
+ return int(m_wheelInfo.size());
}
-
- btAlignedObjectArray<btWheelInfo> m_wheelInfo;
+ btAlignedObjectArray<btWheelInfo> m_wheelInfo;
- const btWheelInfo& getWheelInfo(int index) const;
+ const btWheelInfo& getWheelInfo(int index) const;
- btWheelInfo& getWheelInfo(int index);
+ btWheelInfo& getWheelInfo(int index);
- void updateWheelTransformsWS(btWheelInfo& wheel , bool interpolatedTransform = true);
+ void updateWheelTransformsWS(btWheelInfo& wheel, bool interpolatedTransform = true);
-
- void setBrake(btScalar brake,int wheelIndex);
+ void setBrake(btScalar brake, int wheelIndex);
- void setPitchControl(btScalar pitch)
+ void setPitchControl(btScalar pitch)
{
m_pitchControl = pitch;
}
-
- void updateSuspension(btScalar deltaTime);
-
- virtual void updateFriction(btScalar timeStep);
+ void updateSuspension(btScalar deltaTime);
+ virtual void updateFriction(btScalar timeStep);
inline btRigidBody* getRigidBody()
{
@@ -151,7 +140,7 @@ public:
return m_chassisBody;
}
- inline int getRightAxis() const
+ inline int getRightAxis() const
{
return m_indexRightAxis;
}
@@ -165,46 +154,44 @@ public:
return m_indexForwardAxis;
}
-
///Worldspace forward vector
btVector3 getForwardVector() const
{
- const btTransform& chassisTrans = getChassisWorldTransform();
+ const btTransform& chassisTrans = getChassisWorldTransform();
- btVector3 forwardW (
- chassisTrans.getBasis()[0][m_indexForwardAxis],
- chassisTrans.getBasis()[1][m_indexForwardAxis],
- chassisTrans.getBasis()[2][m_indexForwardAxis]);
+ btVector3 forwardW(
+ chassisTrans.getBasis()[0][m_indexForwardAxis],
+ chassisTrans.getBasis()[1][m_indexForwardAxis],
+ chassisTrans.getBasis()[2][m_indexForwardAxis]);
return forwardW;
}
///Velocity of vehicle (positive if velocity vector has same direction as foward vector)
- btScalar getCurrentSpeedKmHour() const
+ btScalar getCurrentSpeedKmHour() const
{
return m_currentVehicleSpeedKmHour;
}
- virtual void setCoordinateSystem(int rightIndex,int upIndex,int forwardIndex)
+ virtual void setCoordinateSystem(int rightIndex, int upIndex, int forwardIndex)
{
m_indexRightAxis = rightIndex;
m_indexUpAxis = upIndex;
m_indexForwardAxis = forwardIndex;
}
-
///backwards compatibility
int getUserConstraintType() const
{
- return m_userConstraintType ;
+ return m_userConstraintType;
}
- void setUserConstraintType(int userConstraintType)
+ void setUserConstraintType(int userConstraintType)
{
m_userConstraintType = userConstraintType;
};
- void setUserConstraintId(int uid)
+ void setUserConstraintId(int uid)
{
m_userConstraintId = uid;
}
@@ -213,22 +200,19 @@ public:
{
return m_userConstraintId;
}
-
};
class btDefaultVehicleRaycaster : public btVehicleRaycaster
{
- btDynamicsWorld* m_dynamicsWorld;
+ btDynamicsWorld* m_dynamicsWorld;
+
public:
btDefaultVehicleRaycaster(btDynamicsWorld* world)
- :m_dynamicsWorld(world)
+ : m_dynamicsWorld(world)
{
}
- virtual void* castRay(const btVector3& from,const btVector3& to, btVehicleRaycasterResult& result);
-
+ virtual void* castRay(const btVector3& from, const btVector3& to, btVehicleRaycasterResult& result);
};
-
-#endif //BT_RAYCASTVEHICLE_H
-
+#endif //BT_RAYCASTVEHICLE_H
diff --git a/thirdparty/bullet/BulletDynamics/Vehicle/btVehicleRaycaster.h b/thirdparty/bullet/BulletDynamics/Vehicle/btVehicleRaycaster.h
index 3cc909c653..2c44ce546c 100644
--- a/thirdparty/bullet/BulletDynamics/Vehicle/btVehicleRaycaster.h
+++ b/thirdparty/bullet/BulletDynamics/Vehicle/btVehicleRaycaster.h
@@ -16,20 +16,18 @@
/// btVehicleRaycaster is provides interface for between vehicle simulation and raycasting
struct btVehicleRaycaster
{
-virtual ~btVehicleRaycaster()
-{
-}
+ virtual ~btVehicleRaycaster()
+ {
+ }
struct btVehicleRaycasterResult
{
- btVehicleRaycasterResult() :m_distFraction(btScalar(-1.)){};
- btVector3 m_hitPointInWorld;
- btVector3 m_hitNormalInWorld;
- btScalar m_distFraction;
+ btVehicleRaycasterResult() : m_distFraction(btScalar(-1.)){};
+ btVector3 m_hitPointInWorld;
+ btVector3 m_hitNormalInWorld;
+ btScalar m_distFraction;
};
- virtual void* castRay(const btVector3& from,const btVector3& to, btVehicleRaycasterResult& result) = 0;
-
+ virtual void* castRay(const btVector3& from, const btVector3& to, btVehicleRaycasterResult& result) = 0;
};
-#endif //BT_VEHICLE_RAYCASTER_H
-
+#endif //BT_VEHICLE_RAYCASTER_H
diff --git a/thirdparty/bullet/BulletDynamics/Vehicle/btWheelInfo.cpp b/thirdparty/bullet/BulletDynamics/Vehicle/btWheelInfo.cpp
index ef93c16fff..d5c12f223b 100644
--- a/thirdparty/bullet/BulletDynamics/Vehicle/btWheelInfo.cpp
+++ b/thirdparty/bullet/BulletDynamics/Vehicle/btWheelInfo.cpp
@@ -9,30 +9,26 @@
* It is provided "as is" without express or implied warranty.
*/
#include "btWheelInfo.h"
-#include "BulletDynamics/Dynamics/btRigidBody.h" // for pointvelocity
-
+#include "BulletDynamics/Dynamics/btRigidBody.h" // for pointvelocity
btScalar btWheelInfo::getSuspensionRestLength() const
{
-
return m_suspensionRestLength1;
-
}
-void btWheelInfo::updateWheel(const btRigidBody& chassis,RaycastInfo& raycastInfo)
+void btWheelInfo::updateWheel(const btRigidBody& chassis, RaycastInfo& raycastInfo)
{
(void)raycastInfo;
-
if (m_raycastInfo.m_isInContact)
{
- btScalar project= m_raycastInfo.m_contactNormalWS.dot( m_raycastInfo.m_wheelDirectionWS );
- btVector3 chassis_velocity_at_contactPoint;
+ btScalar project = m_raycastInfo.m_contactNormalWS.dot(m_raycastInfo.m_wheelDirectionWS);
+ btVector3 chassis_velocity_at_contactPoint;
btVector3 relpos = m_raycastInfo.m_contactPointWS - chassis.getCenterOfMassPosition();
- chassis_velocity_at_contactPoint = chassis.getVelocityInLocalPoint( relpos );
- btScalar projVel = m_raycastInfo.m_contactNormalWS.dot( chassis_velocity_at_contactPoint );
- if ( project >= btScalar(-0.1))
+ chassis_velocity_at_contactPoint = chassis.getVelocityInLocalPoint(relpos);
+ btScalar projVel = m_raycastInfo.m_contactNormalWS.dot(chassis_velocity_at_contactPoint);
+ if (project >= btScalar(-0.1))
{
m_suspensionRelativeVelocity = btScalar(0.0);
m_clippedInvContactDotSuspension = btScalar(1.0) / btScalar(0.1);
@@ -43,10 +39,9 @@ void btWheelInfo::updateWheel(const btRigidBody& chassis,RaycastInfo& raycastInf
m_suspensionRelativeVelocity = projVel * inv;
m_clippedInvContactDotSuspension = inv;
}
-
}
- else // Not in contact : position wheel in a nice (rest length) position
+ else // Not in contact : position wheel in a nice (rest length) position
{
m_raycastInfo.m_suspensionLength = this->getSuspensionRestLength();
m_suspensionRelativeVelocity = btScalar(0.0);
diff --git a/thirdparty/bullet/BulletDynamics/Vehicle/btWheelInfo.h b/thirdparty/bullet/BulletDynamics/Vehicle/btWheelInfo.h
index f991a57b69..af88b8ff83 100644
--- a/thirdparty/bullet/BulletDynamics/Vehicle/btWheelInfo.h
+++ b/thirdparty/bullet/BulletDynamics/Vehicle/btWheelInfo.h
@@ -18,20 +18,19 @@ class btRigidBody;
struct btWheelInfoConstructionInfo
{
- btVector3 m_chassisConnectionCS;
- btVector3 m_wheelDirectionCS;
- btVector3 m_wheelAxleCS;
- btScalar m_suspensionRestLength;
- btScalar m_maxSuspensionTravelCm;
- btScalar m_wheelRadius;
-
- btScalar m_suspensionStiffness;
- btScalar m_wheelsDampingCompression;
- btScalar m_wheelsDampingRelaxation;
- btScalar m_frictionSlip;
- btScalar m_maxSuspensionForce;
+ btVector3 m_chassisConnectionCS;
+ btVector3 m_wheelDirectionCS;
+ btVector3 m_wheelAxleCS;
+ btScalar m_suspensionRestLength;
+ btScalar m_maxSuspensionTravelCm;
+ btScalar m_wheelRadius;
+
+ btScalar m_suspensionStiffness;
+ btScalar m_wheelsDampingCompression;
+ btScalar m_wheelsDampingRelaxation;
+ btScalar m_frictionSlip;
+ btScalar m_maxSuspensionForce;
bool m_bIsFrontWheel;
-
};
/// btWheelInfo contains information per wheel about friction and suspension.
@@ -40,51 +39,50 @@ struct btWheelInfo
struct RaycastInfo
{
//set by raycaster
- btVector3 m_contactNormalWS;//contactnormal
- btVector3 m_contactPointWS;//raycast hitpoint
- btScalar m_suspensionLength;
- btVector3 m_hardPointWS;//raycast starting point
- btVector3 m_wheelDirectionWS; //direction in worldspace
- btVector3 m_wheelAxleWS; // axle in worldspace
- bool m_isInContact;
- void* m_groundObject; //could be general void* ptr
+ btVector3 m_contactNormalWS; //contactnormal
+ btVector3 m_contactPointWS; //raycast hitpoint
+ btScalar m_suspensionLength;
+ btVector3 m_hardPointWS; //raycast starting point
+ btVector3 m_wheelDirectionWS; //direction in worldspace
+ btVector3 m_wheelAxleWS; // axle in worldspace
+ bool m_isInContact;
+ void* m_groundObject; //could be general void* ptr
};
- RaycastInfo m_raycastInfo;
+ RaycastInfo m_raycastInfo;
- btTransform m_worldTransform;
-
- btVector3 m_chassisConnectionPointCS; //const
- btVector3 m_wheelDirectionCS;//const
- btVector3 m_wheelAxleCS; // const or modified by steering
- btScalar m_suspensionRestLength1;//const
- btScalar m_maxSuspensionTravelCm;
+ btTransform m_worldTransform;
+
+ btVector3 m_chassisConnectionPointCS; //const
+ btVector3 m_wheelDirectionCS; //const
+ btVector3 m_wheelAxleCS; // const or modified by steering
+ btScalar m_suspensionRestLength1; //const
+ btScalar m_maxSuspensionTravelCm;
btScalar getSuspensionRestLength() const;
- btScalar m_wheelsRadius;//const
- btScalar m_suspensionStiffness;//const
- btScalar m_wheelsDampingCompression;//const
- btScalar m_wheelsDampingRelaxation;//const
- btScalar m_frictionSlip;
- btScalar m_steering;
- btScalar m_rotation;
- btScalar m_deltaRotation;
- btScalar m_rollInfluence;
- btScalar m_maxSuspensionForce;
-
- btScalar m_engineForce;
-
- btScalar m_brake;
-
+ btScalar m_wheelsRadius; //const
+ btScalar m_suspensionStiffness; //const
+ btScalar m_wheelsDampingCompression; //const
+ btScalar m_wheelsDampingRelaxation; //const
+ btScalar m_frictionSlip;
+ btScalar m_steering;
+ btScalar m_rotation;
+ btScalar m_deltaRotation;
+ btScalar m_rollInfluence;
+ btScalar m_maxSuspensionForce;
+
+ btScalar m_engineForce;
+
+ btScalar m_brake;
+
bool m_bIsFrontWheel;
-
- void* m_clientInfo;//can be used to store pointer to sync transforms...
+
+ void* m_clientInfo; //can be used to store pointer to sync transforms...
btWheelInfo() {}
btWheelInfo(btWheelInfoConstructionInfo& ci)
{
-
m_suspensionRestLength1 = ci.m_suspensionRestLength;
m_maxSuspensionTravelCm = ci.m_maxSuspensionTravelCm;
@@ -104,18 +102,15 @@ struct btWheelInfo
m_rollInfluence = btScalar(0.1);
m_bIsFrontWheel = ci.m_bIsFrontWheel;
m_maxSuspensionForce = ci.m_maxSuspensionForce;
-
}
- void updateWheel(const btRigidBody& chassis,RaycastInfo& raycastInfo);
+ void updateWheel(const btRigidBody& chassis, RaycastInfo& raycastInfo);
- btScalar m_clippedInvContactDotSuspension;
- btScalar m_suspensionRelativeVelocity;
+ btScalar m_clippedInvContactDotSuspension;
+ btScalar m_suspensionRelativeVelocity;
//calculated by suspension
- btScalar m_wheelsSuspensionForce;
- btScalar m_skidInfo;
-
+ btScalar m_wheelsSuspensionForce;
+ btScalar m_skidInfo;
};
-#endif //BT_WHEEL_INFO_H
-
+#endif //BT_WHEEL_INFO_H
diff --git a/thirdparty/bullet/BulletInverseDynamics/IDConfig.hpp b/thirdparty/bullet/BulletInverseDynamics/IDConfig.hpp
index ebb10e7a16..b662b80152 100644
--- a/thirdparty/bullet/BulletInverseDynamics/IDConfig.hpp
+++ b/thirdparty/bullet/BulletInverseDynamics/IDConfig.hpp
@@ -32,10 +32,10 @@
#define BT_ID_POW(x, y) btPow(x, y)
#define BT_ID_PI SIMD_PI
#ifdef _WIN32
- #define BT_ID_SNPRINTF _snprintf
+#define BT_ID_SNPRINTF _snprintf
#else
- #define BT_ID_SNPRINTF snprintf
-#endif //
+#define BT_ID_SNPRINTF snprintf
+#endif //
#endif
// error messages
#include "IDErrorMessages.hpp"
@@ -52,8 +52,8 @@
#error "custom inverse dynamics config, but no custom namespace defined"
#endif
-#define BT_ID_MAX(a,b) std::max(a,b)
-#define BT_ID_MIN(a,b) std::min(a,b)
+#define BT_ID_MAX(a, b) std::max(a, b)
+#define BT_ID_MIN(a, b) std::min(a, b)
#else
#define btInverseDynamics btInverseDynamicsBullet3
@@ -62,8 +62,8 @@
#include "LinearMath/btScalar.h"
typedef btScalar idScalar;
#include "LinearMath/btMinMax.h"
-#define BT_ID_MAX(a,b) btMax(a,b)
-#define BT_ID_MIN(a,b) btMin(a,b)
+#define BT_ID_MAX(a, b) btMax(a, b)
+#define BT_ID_MIN(a, b) btMin(a, b)
#ifdef BT_USE_DOUBLE_PRECISION
#define BT_ID_USE_DOUBLE_PRECISION
@@ -71,31 +71,31 @@ typedef btScalar idScalar;
#ifndef BT_USE_INVERSE_DYNAMICS_WITH_BULLET2
-
// use bullet types for arrays and array indices
#include "Bullet3Common/b3AlignedObjectArray.h"
// this is to make it work with C++2003, otherwise we could do this:
// template <typename T>
// using idArray = b3AlignedObjectArray<T>;
template <typename T>
-struct idArray {
+struct idArray
+{
typedef b3AlignedObjectArray<T> type;
};
typedef int idArrayIdx;
#define ID_DECLARE_ALIGNED_ALLOCATOR() B3_DECLARE_ALIGNED_ALLOCATOR()
-#else // BT_USE_INVERSE_DYNAMICS_WITH_BULLET2
+#else // BT_USE_INVERSE_DYNAMICS_WITH_BULLET2
#include "LinearMath/btAlignedObjectArray.h"
template <typename T>
-struct idArray {
+struct idArray
+{
typedef btAlignedObjectArray<T> type;
};
typedef int idArrayIdx;
#define ID_DECLARE_ALIGNED_ALLOCATOR() BT_DECLARE_ALIGNED_ALLOCATOR()
-#endif // BT_USE_INVERSE_DYNAMICS_WITH_BULLET2
-
+#endif // BT_USE_INVERSE_DYNAMICS_WITH_BULLET2
// use bullet's allocator functions
#define idMalloc btAllocFunc
diff --git a/thirdparty/bullet/BulletInverseDynamics/IDConfigBuiltin.hpp b/thirdparty/bullet/BulletInverseDynamics/IDConfigBuiltin.hpp
index 130c19c6d6..6392367924 100644
--- a/thirdparty/bullet/BulletInverseDynamics/IDConfigBuiltin.hpp
+++ b/thirdparty/bullet/BulletInverseDynamics/IDConfigBuiltin.hpp
@@ -14,7 +14,8 @@ typedef float idScalar;
// template <typename T>
// using idArray = std::vector<T>;
template <typename T>
-struct idArray {
+struct idArray
+{
typedef std::vector<T> type;
};
typedef std::vector<int>::size_type idArrayIdx;
@@ -23,14 +24,14 @@ typedef std::vector<int>::size_type idArrayIdx;
#define idMalloc ::malloc
#define idFree ::free
// currently not aligned at all...
-#define ID_DECLARE_ALIGNED_ALLOCATOR() \
- inline void* operator new(std::size_t sizeInBytes) { return idMalloc(sizeInBytes); } \
- inline void operator delete(void* ptr) { idFree(ptr); } \
- inline void* operator new(std::size_t, void* ptr) { return ptr; } \
- inline void operator delete(void*, void*) {} \
- inline void* operator new[](std::size_t sizeInBytes) { return idMalloc(sizeInBytes); } \
- inline void operator delete[](void* ptr) { idFree(ptr); } \
- inline void* operator new[](std::size_t, void* ptr) { return ptr; } \
+#define ID_DECLARE_ALIGNED_ALLOCATOR() \
+ inline void* operator new(std::size_t sizeInBytes) { return idMalloc(sizeInBytes); } \
+ inline void operator delete(void* ptr) { idFree(ptr); } \
+ inline void* operator new(std::size_t, void* ptr) { return ptr; } \
+ inline void operator delete(void*, void*) {} \
+ inline void* operator new[](std::size_t sizeInBytes) { return idMalloc(sizeInBytes); } \
+ inline void operator delete[](void* ptr) { idFree(ptr); } \
+ inline void* operator new[](std::size_t, void* ptr) { return ptr; } \
inline void operator delete[](void*, void*) {}
#include "details/IDMatVec.hpp"
diff --git a/thirdparty/bullet/BulletInverseDynamics/IDConfigEigen.hpp b/thirdparty/bullet/BulletInverseDynamics/IDConfigEigen.hpp
index cbd7e8a9c4..cfb308ee55 100644
--- a/thirdparty/bullet/BulletInverseDynamics/IDConfigEigen.hpp
+++ b/thirdparty/bullet/BulletInverseDynamics/IDConfigEigen.hpp
@@ -15,7 +15,8 @@ typedef float idScalar;
// template <typename T>
// using idArray = std::vector<T>;
template <typename T>
-struct idArray {
+struct idArray
+{
typedef std::vector<T> type;
};
typedef std::vector<int>::size_type idArrayIdx;
diff --git a/thirdparty/bullet/BulletInverseDynamics/IDErrorMessages.hpp b/thirdparty/bullet/BulletInverseDynamics/IDErrorMessages.hpp
index 1b3fd268a0..5a98f01498 100644
--- a/thirdparty/bullet/BulletInverseDynamics/IDErrorMessages.hpp
+++ b/thirdparty/bullet/BulletInverseDynamics/IDErrorMessages.hpp
@@ -13,16 +13,18 @@
#else // BT_ID_WO_BULLET
#include <cstdio>
/// print error message with file/line information
-#define bt_id_error_message(...) \
- do { \
- fprintf(stderr, "[Error:%s:%d] ", __INVDYN_FILE_WO_DIR__, __LINE__); \
- fprintf(stderr, __VA_ARGS__); \
+#define bt_id_error_message(...) \
+ do \
+ { \
+ fprintf(stderr, "[Error:%s:%d] ", __INVDYN_FILE_WO_DIR__, __LINE__); \
+ fprintf(stderr, __VA_ARGS__); \
} while (0)
/// print warning message with file/line information
-#define bt_id_warning_message(...) \
- do { \
- fprintf(stderr, "[Warning:%s:%d] ", __INVDYN_FILE_WO_DIR__, __LINE__); \
- fprintf(stderr, __VA_ARGS__); \
+#define bt_id_warning_message(...) \
+ do \
+ { \
+ fprintf(stderr, "[Warning:%s:%d] ", __INVDYN_FILE_WO_DIR__, __LINE__); \
+ fprintf(stderr, __VA_ARGS__); \
} while (0)
#define id_printf(...) printf(__VA_ARGS__)
#endif // BT_ID_WO_BULLET
diff --git a/thirdparty/bullet/BulletInverseDynamics/IDMath.cpp b/thirdparty/bullet/BulletInverseDynamics/IDMath.cpp
index d279d3435c..2f120ed489 100644
--- a/thirdparty/bullet/BulletInverseDynamics/IDMath.cpp
+++ b/thirdparty/bullet/BulletInverseDynamics/IDMath.cpp
@@ -3,25 +3,30 @@
#include <cmath>
#include <limits>
-namespace btInverseDynamics {
+namespace btInverseDynamics
+{
static const idScalar kIsZero = 5 * std::numeric_limits<idScalar>::epsilon();
// requirements for axis length deviation from 1.0
// experimentally set from random euler angle rotation matrices
static const idScalar kAxisLengthEpsilon = 10 * kIsZero;
-void setZero(vec3 &v) {
+void setZero(vec3 &v)
+{
v(0) = 0;
v(1) = 0;
v(2) = 0;
}
-void setZero(vecx &v) {
- for (int i = 0; i < v.size(); i++) {
+void setZero(vecx &v)
+{
+ for (int i = 0; i < v.size(); i++)
+ {
v(i) = 0;
}
}
-void setZero(mat33 &m) {
+void setZero(mat33 &m)
+{
m(0, 0) = 0;
m(0, 1) = 0;
m(0, 2) = 0;
@@ -33,7 +38,8 @@ void setZero(mat33 &m) {
m(2, 2) = 0;
}
-void skew(vec3& v, mat33* result) {
+void skew(vec3 &v, mat33 *result)
+{
(*result)(0, 0) = 0.0;
(*result)(0, 1) = -v(2);
(*result)(0, 2) = v(1);
@@ -45,22 +51,28 @@ void skew(vec3& v, mat33* result) {
(*result)(2, 2) = 0.0;
}
-idScalar maxAbs(const vecx &v) {
+idScalar maxAbs(const vecx &v)
+{
idScalar result = 0.0;
- for (int i = 0; i < v.size(); i++) {
+ for (int i = 0; i < v.size(); i++)
+ {
const idScalar tmp = BT_ID_FABS(v(i));
- if (tmp > result) {
+ if (tmp > result)
+ {
result = tmp;
}
}
return result;
}
-idScalar maxAbs(const vec3 &v) {
+idScalar maxAbs(const vec3 &v)
+{
idScalar result = 0.0;
- for (int i = 0; i < 3; i++) {
+ for (int i = 0; i < 3; i++)
+ {
const idScalar tmp = BT_ID_FABS(v(i));
- if (tmp > result) {
+ if (tmp > result)
+ {
result = tmp;
}
}
@@ -68,60 +80,75 @@ idScalar maxAbs(const vec3 &v) {
}
#if (defined BT_ID_HAVE_MAT3X)
-idScalar maxAbsMat3x(const mat3x &m) {
- // only used for tests -- so just loop here for portability
- idScalar result = 0.0;
- for (idArrayIdx col = 0; col < m.cols(); col++) {
- for (idArrayIdx row = 0; row < 3; row++) {
- result = BT_ID_MAX(result, std::fabs(m(row, col)));
- }
- }
- return result;
+idScalar maxAbsMat3x(const mat3x &m)
+{
+ // only used for tests -- so just loop here for portability
+ idScalar result = 0.0;
+ for (idArrayIdx col = 0; col < m.cols(); col++)
+ {
+ for (idArrayIdx row = 0; row < 3; row++)
+ {
+ result = BT_ID_MAX(result, std::fabs(m(row, col)));
+ }
+ }
+ return result;
}
-void mul(const mat33 &a, const mat3x &b, mat3x *result) {
- if (b.cols() != result->cols()) {
- bt_id_error_message("size missmatch. b.cols()= %d, result->cols()= %d\n",
- static_cast<int>(b.cols()), static_cast<int>(result->cols()));
- abort();
- }
-
- for (idArrayIdx col = 0; col < b.cols(); col++) {
- const idScalar x = a(0,0)*b(0,col)+a(0,1)*b(1,col)+a(0,2)*b(2,col);
- const idScalar y = a(1,0)*b(0,col)+a(1,1)*b(1,col)+a(1,2)*b(2,col);
- const idScalar z = a(2,0)*b(0,col)+a(2,1)*b(1,col)+a(2,2)*b(2,col);
- setMat3xElem(0, col, x, result);
- setMat3xElem(1, col, y, result);
- setMat3xElem(2, col, z, result);
- }
+void mul(const mat33 &a, const mat3x &b, mat3x *result)
+{
+ if (b.cols() != result->cols())
+ {
+ bt_id_error_message("size missmatch. b.cols()= %d, result->cols()= %d\n",
+ static_cast<int>(b.cols()), static_cast<int>(result->cols()));
+ abort();
+ }
+
+ for (idArrayIdx col = 0; col < b.cols(); col++)
+ {
+ const idScalar x = a(0, 0) * b(0, col) + a(0, 1) * b(1, col) + a(0, 2) * b(2, col);
+ const idScalar y = a(1, 0) * b(0, col) + a(1, 1) * b(1, col) + a(1, 2) * b(2, col);
+ const idScalar z = a(2, 0) * b(0, col) + a(2, 1) * b(1, col) + a(2, 2) * b(2, col);
+ setMat3xElem(0, col, x, result);
+ setMat3xElem(1, col, y, result);
+ setMat3xElem(2, col, z, result);
+ }
}
-void add(const mat3x &a, const mat3x &b, mat3x *result) {
- if (a.cols() != b.cols()) {
- bt_id_error_message("size missmatch. a.cols()= %d, b.cols()= %d\n",
- static_cast<int>(a.cols()), static_cast<int>(b.cols()));
- abort();
- }
- for (idArrayIdx col = 0; col < b.cols(); col++) {
- for (idArrayIdx row = 0; row < 3; row++) {
- setMat3xElem(row, col, a(row, col) + b(row, col), result);
- }
- }
+void add(const mat3x &a, const mat3x &b, mat3x *result)
+{
+ if (a.cols() != b.cols())
+ {
+ bt_id_error_message("size missmatch. a.cols()= %d, b.cols()= %d\n",
+ static_cast<int>(a.cols()), static_cast<int>(b.cols()));
+ abort();
+ }
+ for (idArrayIdx col = 0; col < b.cols(); col++)
+ {
+ for (idArrayIdx row = 0; row < 3; row++)
+ {
+ setMat3xElem(row, col, a(row, col) + b(row, col), result);
+ }
+ }
}
-void sub(const mat3x &a, const mat3x &b, mat3x *result) {
- if (a.cols() != b.cols()) {
- bt_id_error_message("size missmatch. a.cols()= %d, b.cols()= %d\n",
- static_cast<int>(a.cols()), static_cast<int>(b.cols()));
- abort();
- }
- for (idArrayIdx col = 0; col < b.cols(); col++) {
- for (idArrayIdx row = 0; row < 3; row++) {
- setMat3xElem(row, col, a(row, col) - b(row, col), result);
- }
- }
+void sub(const mat3x &a, const mat3x &b, mat3x *result)
+{
+ if (a.cols() != b.cols())
+ {
+ bt_id_error_message("size missmatch. a.cols()= %d, b.cols()= %d\n",
+ static_cast<int>(a.cols()), static_cast<int>(b.cols()));
+ abort();
+ }
+ for (idArrayIdx col = 0; col < b.cols(); col++)
+ {
+ for (idArrayIdx row = 0; row < 3; row++)
+ {
+ setMat3xElem(row, col, a(row, col) - b(row, col), result);
+ }
+ }
}
#endif
-mat33 transformX(const idScalar &alpha) {
+mat33 transformX(const idScalar &alpha)
+{
mat33 T;
const idScalar cos_alpha = BT_ID_COS(alpha);
const idScalar sin_alpha = BT_ID_SIN(alpha);
@@ -143,7 +170,8 @@ mat33 transformX(const idScalar &alpha) {
return T;
}
-mat33 transformY(const idScalar &beta) {
+mat33 transformY(const idScalar &beta)
+{
mat33 T;
const idScalar cos_beta = BT_ID_COS(beta);
const idScalar sin_beta = BT_ID_SIN(beta);
@@ -165,7 +193,8 @@ mat33 transformY(const idScalar &beta) {
return T;
}
-mat33 transformZ(const idScalar &gamma) {
+mat33 transformZ(const idScalar &gamma)
+{
mat33 T;
const idScalar cos_gamma = BT_ID_COS(gamma);
const idScalar sin_gamma = BT_ID_SIN(gamma);
@@ -187,7 +216,8 @@ mat33 transformZ(const idScalar &gamma) {
return T;
}
-mat33 tildeOperator(const vec3 &v) {
+mat33 tildeOperator(const vec3 &v)
+{
mat33 m;
m(0, 0) = 0.0;
m(0, 1) = -v(2);
@@ -201,7 +231,8 @@ mat33 tildeOperator(const vec3 &v) {
return m;
}
-void getVecMatFromDH(idScalar theta, idScalar d, idScalar a, idScalar alpha, vec3 *r, mat33 *T) {
+void getVecMatFromDH(idScalar theta, idScalar d, idScalar a, idScalar alpha, vec3 *r, mat33 *T)
+{
const idScalar sa = BT_ID_SIN(alpha);
const idScalar ca = BT_ID_COS(alpha);
const idScalar st = BT_ID_SIN(theta);
@@ -224,7 +255,8 @@ void getVecMatFromDH(idScalar theta, idScalar d, idScalar a, idScalar alpha, vec
(*T)(2, 2) = ca;
}
-void bodyTParentFromAxisAngle(const vec3 &axis, const idScalar &angle, mat33 *T) {
+void bodyTParentFromAxisAngle(const vec3 &axis, const idScalar &angle, mat33 *T)
+{
const idScalar c = BT_ID_COS(angle);
const idScalar s = -BT_ID_SIN(angle);
const idScalar one_m_c = 1.0 - c;
@@ -246,175 +278,214 @@ void bodyTParentFromAxisAngle(const vec3 &axis, const idScalar &angle, mat33 *T)
(*T)(2, 2) = z * z * one_m_c + c;
}
-bool isPositiveDefinite(const mat33 &m) {
+bool isPositiveDefinite(const mat33 &m)
+{
// test if all upper left determinants are positive
- if (m(0, 0) <= 0) { // upper 1x1
+ if (m(0, 0) <= 0)
+ { // upper 1x1
return false;
}
- if (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0) <= 0) { // upper 2x2
+ if (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0) <= 0)
+ { // upper 2x2
return false;
}
if ((m(0, 0) * (m(1, 1) * m(2, 2) - m(1, 2) * m(2, 1)) -
m(0, 1) * (m(1, 0) * m(2, 2) - m(1, 2) * m(2, 0)) +
- m(0, 2) * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0))) < 0) {
+ m(0, 2) * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0))) < 0)
+ {
return false;
}
return true;
}
-bool isPositiveSemiDefinite(const mat33 &m) {
+bool isPositiveSemiDefinite(const mat33 &m)
+{
// test if all upper left determinants are positive
- if (m(0, 0) < 0) { // upper 1x1
+ if (m(0, 0) < 0)
+ { // upper 1x1
return false;
}
- if (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0) < 0) { // upper 2x2
+ if (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0) < 0)
+ { // upper 2x2
return false;
}
if ((m(0, 0) * (m(1, 1) * m(2, 2) - m(1, 2) * m(2, 1)) -
m(0, 1) * (m(1, 0) * m(2, 2) - m(1, 2) * m(2, 0)) +
- m(0, 2) * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0))) < 0) {
+ m(0, 2) * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0))) < 0)
+ {
return false;
}
return true;
}
-bool isPositiveSemiDefiniteFuzzy(const mat33 &m) {
+bool isPositiveSemiDefiniteFuzzy(const mat33 &m)
+{
// test if all upper left determinants are positive
- if (m(0, 0) < -kIsZero) { // upper 1x1
+ if (m(0, 0) < -kIsZero)
+ { // upper 1x1
return false;
}
- if (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0) < -kIsZero) { // upper 2x2
+ if (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0) < -kIsZero)
+ { // upper 2x2
return false;
}
if ((m(0, 0) * (m(1, 1) * m(2, 2) - m(1, 2) * m(2, 1)) -
m(0, 1) * (m(1, 0) * m(2, 2) - m(1, 2) * m(2, 0)) +
- m(0, 2) * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0))) < -kIsZero) {
+ m(0, 2) * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0))) < -kIsZero)
+ {
return false;
}
return true;
}
-idScalar determinant(const mat33 &m) {
+idScalar determinant(const mat33 &m)
+{
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(0, 2) * m(1, 1) * m(2, 0) - m(0, 0) * m(1, 2) * m(2, 1) - m(0, 1) * m(1, 0) * m(2, 2);
}
-bool isValidInertiaMatrix(const mat33 &I, const int index, bool has_fixed_joint) {
+bool isValidInertiaMatrix(const mat33 &I, const int index, bool has_fixed_joint)
+{
// TODO(Thomas) do we really want this?
// in cases where the inertia tensor about the center of mass is zero,
// the determinant of the inertia tensor about the joint axis is almost
// zero and can have a very small negative value.
- if (!isPositiveSemiDefiniteFuzzy(I)) {
- bt_id_error_message("invalid inertia matrix for body %d, not positive definite "
- "(fixed joint)\n",
- index);
- bt_id_error_message("matrix is:\n"
- "[%.20e %.20e %.20e;\n"
- "%.20e %.20e %.20e;\n"
- "%.20e %.20e %.20e]\n",
- I(0, 0), I(0, 1), I(0, 2), I(1, 0), I(1, 1), I(1, 2), I(2, 0), I(2, 1),
- I(2, 2));
+ if (!isPositiveSemiDefiniteFuzzy(I))
+ {
+ bt_id_error_message(
+ "invalid inertia matrix for body %d, not positive definite "
+ "(fixed joint)\n",
+ index);
+ bt_id_error_message(
+ "matrix is:\n"
+ "[%.20e %.20e %.20e;\n"
+ "%.20e %.20e %.20e;\n"
+ "%.20e %.20e %.20e]\n",
+ I(0, 0), I(0, 1), I(0, 2), I(1, 0), I(1, 1), I(1, 2), I(2, 0), I(2, 1),
+ I(2, 2));
return false;
}
// check triangle inequality, must have I(i,i)+I(j,j)>=I(k,k)
- if (!has_fixed_joint) {
- if (I(0, 0) + I(1, 1) < I(2, 2)) {
+ if (!has_fixed_joint)
+ {
+ if (I(0, 0) + I(1, 1) < I(2, 2))
+ {
bt_id_error_message("invalid inertia tensor for body %d, I(0,0) + I(1,1) < I(2,2)\n", index);
- bt_id_error_message("matrix is:\n"
- "[%.20e %.20e %.20e;\n"
- "%.20e %.20e %.20e;\n"
- "%.20e %.20e %.20e]\n",
- I(0, 0), I(0, 1), I(0, 2), I(1, 0), I(1, 1), I(1, 2), I(2, 0), I(2, 1),
- I(2, 2));
+ bt_id_error_message(
+ "matrix is:\n"
+ "[%.20e %.20e %.20e;\n"
+ "%.20e %.20e %.20e;\n"
+ "%.20e %.20e %.20e]\n",
+ I(0, 0), I(0, 1), I(0, 2), I(1, 0), I(1, 1), I(1, 2), I(2, 0), I(2, 1),
+ I(2, 2));
return false;
}
- if (I(0, 0) + I(1, 1) < I(2, 2)) {
+ if (I(0, 0) + I(1, 1) < I(2, 2))
+ {
bt_id_error_message("invalid inertia tensor for body %d, I(0,0) + I(1,1) < I(2,2)\n", index);
- bt_id_error_message("matrix is:\n"
- "[%.20e %.20e %.20e;\n"
- "%.20e %.20e %.20e;\n"
- "%.20e %.20e %.20e]\n",
- I(0, 0), I(0, 1), I(0, 2), I(1, 0), I(1, 1), I(1, 2), I(2, 0), I(2, 1),
- I(2, 2));
+ bt_id_error_message(
+ "matrix is:\n"
+ "[%.20e %.20e %.20e;\n"
+ "%.20e %.20e %.20e;\n"
+ "%.20e %.20e %.20e]\n",
+ I(0, 0), I(0, 1), I(0, 2), I(1, 0), I(1, 1), I(1, 2), I(2, 0), I(2, 1),
+ I(2, 2));
return false;
}
- if (I(1, 1) + I(2, 2) < I(0, 0)) {
+ if (I(1, 1) + I(2, 2) < I(0, 0))
+ {
bt_id_error_message("invalid inertia tensor for body %d, I(1,1) + I(2,2) < I(0,0)\n", index);
- bt_id_error_message("matrix is:\n"
- "[%.20e %.20e %.20e;\n"
- "%.20e %.20e %.20e;\n"
- "%.20e %.20e %.20e]\n",
- I(0, 0), I(0, 1), I(0, 2), I(1, 0), I(1, 1), I(1, 2), I(2, 0), I(2, 1),
- I(2, 2));
+ bt_id_error_message(
+ "matrix is:\n"
+ "[%.20e %.20e %.20e;\n"
+ "%.20e %.20e %.20e;\n"
+ "%.20e %.20e %.20e]\n",
+ I(0, 0), I(0, 1), I(0, 2), I(1, 0), I(1, 1), I(1, 2), I(2, 0), I(2, 1),
+ I(2, 2));
return false;
}
}
// check positive/zero diagonal elements
- for (int i = 0; i < 3; i++) {
- if (I(i, i) < 0) { // accept zero
+ for (int i = 0; i < 3; i++)
+ {
+ if (I(i, i) < 0)
+ { // accept zero
bt_id_error_message("invalid inertia tensor, I(%d,%d)= %e <0\n", i, i, I(i, i));
return false;
}
}
// check symmetry
- if (BT_ID_FABS(I(1, 0) - I(0, 1)) > kIsZero) {
- bt_id_error_message("invalid inertia tensor for body %d I(1,0)!=I(0,1). I(1,0)-I(0,1)= "
- "%e\n",
- index, I(1, 0) - I(0, 1));
+ if (BT_ID_FABS(I(1, 0) - I(0, 1)) > kIsZero)
+ {
+ bt_id_error_message(
+ "invalid inertia tensor for body %d I(1,0)!=I(0,1). I(1,0)-I(0,1)= "
+ "%e\n",
+ index, I(1, 0) - I(0, 1));
return false;
}
- if (BT_ID_FABS(I(2, 0) - I(0, 2)) > kIsZero) {
- bt_id_error_message("invalid inertia tensor for body %d I(2,0)!=I(0,2). I(2,0)-I(0,2)= "
- "%e\n",
- index, I(2, 0) - I(0, 2));
+ if (BT_ID_FABS(I(2, 0) - I(0, 2)) > kIsZero)
+ {
+ bt_id_error_message(
+ "invalid inertia tensor for body %d I(2,0)!=I(0,2). I(2,0)-I(0,2)= "
+ "%e\n",
+ index, I(2, 0) - I(0, 2));
return false;
}
- if (BT_ID_FABS(I(1, 2) - I(2, 1)) > kIsZero) {
+ if (BT_ID_FABS(I(1, 2) - I(2, 1)) > kIsZero)
+ {
bt_id_error_message("invalid inertia tensor body %d I(1,2)!=I(2,1). I(1,2)-I(2,1)= %e\n", index,
- I(1, 2) - I(2, 1));
+ I(1, 2) - I(2, 1));
return false;
}
return true;
}
-bool isValidTransformMatrix(const mat33 &m) {
-#define print_mat(x) \
- bt_id_error_message("matrix is [%e, %e, %e; %e, %e, %e; %e, %e, %e]\n", x(0, 0), x(0, 1), x(0, 2), \
- x(1, 0), x(1, 1), x(1, 2), x(2, 0), x(2, 1), x(2, 2))
+bool isValidTransformMatrix(const mat33 &m)
+{
+#define print_mat(x) \
+ bt_id_error_message("matrix is [%e, %e, %e; %e, %e, %e; %e, %e, %e]\n", x(0, 0), x(0, 1), x(0, 2), \
+ x(1, 0), x(1, 1), x(1, 2), x(2, 0), x(2, 1), x(2, 2))
// check for unit length column vectors
- for (int i = 0; i < 3; i++) {
+ for (int i = 0; i < 3; i++)
+ {
const idScalar length_minus_1 =
BT_ID_FABS(m(0, i) * m(0, i) + m(1, i) * m(1, i) + m(2, i) * m(2, i) - 1.0);
- if (length_minus_1 > kAxisLengthEpsilon) {
- bt_id_error_message("Not a valid rotation matrix (column %d not unit length)\n"
- "column = [%.18e %.18e %.18e]\n"
- "length-1.0= %.18e\n",
- i, m(0, i), m(1, i), m(2, i), length_minus_1);
+ if (length_minus_1 > kAxisLengthEpsilon)
+ {
+ bt_id_error_message(
+ "Not a valid rotation matrix (column %d not unit length)\n"
+ "column = [%.18e %.18e %.18e]\n"
+ "length-1.0= %.18e\n",
+ i, m(0, i), m(1, i), m(2, i), length_minus_1);
print_mat(m);
return false;
}
}
// check for orthogonal column vectors
- if (BT_ID_FABS(m(0, 0) * m(0, 1) + m(1, 0) * m(1, 1) + m(2, 0) * m(2, 1)) > kAxisLengthEpsilon) {
+ if (BT_ID_FABS(m(0, 0) * m(0, 1) + m(1, 0) * m(1, 1) + m(2, 0) * m(2, 1)) > kAxisLengthEpsilon)
+ {
bt_id_error_message("Not a valid rotation matrix (columns 0 and 1 not orthogonal)\n");
print_mat(m);
return false;
}
- if (BT_ID_FABS(m(0, 0) * m(0, 2) + m(1, 0) * m(1, 2) + m(2, 0) * m(2, 2)) > kAxisLengthEpsilon) {
+ if (BT_ID_FABS(m(0, 0) * m(0, 2) + m(1, 0) * m(1, 2) + m(2, 0) * m(2, 2)) > kAxisLengthEpsilon)
+ {
bt_id_error_message("Not a valid rotation matrix (columns 0 and 2 not orthogonal)\n");
print_mat(m);
return false;
}
- if (BT_ID_FABS(m(0, 1) * m(0, 2) + m(1, 1) * m(1, 2) + m(2, 1) * m(2, 2)) > kAxisLengthEpsilon) {
+ if (BT_ID_FABS(m(0, 1) * m(0, 2) + m(1, 1) * m(1, 2) + m(2, 1) * m(2, 2)) > kAxisLengthEpsilon)
+ {
bt_id_error_message("Not a valid rotation matrix (columns 0 and 2 not orthogonal)\n");
print_mat(m);
return false;
}
// check determinant (rotation not reflection)
- if (determinant(m) <= 0) {
+ if (determinant(m) <= 0)
+ {
bt_id_error_message("Not a valid rotation matrix (determinant <=0)\n");
print_mat(m);
return false;
@@ -422,16 +493,18 @@ bool isValidTransformMatrix(const mat33 &m) {
return true;
}
-bool isUnitVector(const vec3 &vector) {
+bool isUnitVector(const vec3 &vector)
+{
return BT_ID_FABS(vector(0) * vector(0) + vector(1) * vector(1) + vector(2) * vector(2) - 1.0) <
kIsZero;
}
-vec3 rpyFromMatrix(const mat33 &rot) {
+vec3 rpyFromMatrix(const mat33 &rot)
+{
vec3 rpy;
rpy(2) = BT_ID_ATAN2(-rot(1, 0), rot(0, 0));
rpy(1) = BT_ID_ATAN2(rot(2, 0), BT_ID_COS(rpy(2)) * rot(0, 0) - BT_ID_SIN(rpy(0)) * rot(1, 0));
rpy(0) = BT_ID_ATAN2(-rot(2, 0), rot(2, 2));
return rpy;
}
-}
+} // namespace btInverseDynamics
diff --git a/thirdparty/bullet/BulletInverseDynamics/IDMath.hpp b/thirdparty/bullet/BulletInverseDynamics/IDMath.hpp
index b355474d44..40bee5302b 100644
--- a/thirdparty/bullet/BulletInverseDynamics/IDMath.hpp
+++ b/thirdparty/bullet/BulletInverseDynamics/IDMath.hpp
@@ -5,7 +5,8 @@
#define IDMATH_HPP_
#include "IDConfig.hpp"
-namespace btInverseDynamics {
+namespace btInverseDynamics
+{
/// set all elements to zero
void setZero(vec3& v);
/// set all elements to zero
@@ -23,11 +24,11 @@ idScalar maxAbs(const vec3& v);
#if (defined BT_ID_HAVE_MAT3X)
idScalar maxAbsMat3x(const mat3x& m);
-void setZero(mat3x&m);
+void setZero(mat3x& m);
// define math functions on mat3x here to avoid allocations in operators.
-void mul(const mat33&a, const mat3x&b, mat3x* result);
-void add(const mat3x&a, const mat3x&b, mat3x* result);
-void sub(const mat3x&a, const mat3x&b, mat3x* result);
+void mul(const mat33& a, const mat3x& b, mat3x* result);
+void add(const mat3x& a, const mat3x& b, mat3x* result);
+void sub(const mat3x& a, const mat3x& b, mat3x* result);
#endif
/// get offset vector & transform matrix from DH parameters
@@ -94,6 +95,6 @@ mat33 transformZ(const idScalar& gamma);
///calculate rpy angles (x-y-z Euler angles) from a given rotation matrix
/// @param rot rotation matrix
/// @returns x-y-z Euler angles
-vec3 rpyFromMatrix(const mat33&rot);
-}
+vec3 rpyFromMatrix(const mat33& rot);
+} // namespace btInverseDynamics
#endif // IDMATH_HPP_
diff --git a/thirdparty/bullet/BulletInverseDynamics/MultiBodyTree.cpp b/thirdparty/bullet/BulletInverseDynamics/MultiBodyTree.cpp
index becfe0f4a2..f150b5ae4c 100644
--- a/thirdparty/bullet/BulletInverseDynamics/MultiBodyTree.cpp
+++ b/thirdparty/bullet/BulletInverseDynamics/MultiBodyTree.cpp
@@ -8,69 +8,84 @@
#include "details/MultiBodyTreeImpl.hpp"
#include "details/MultiBodyTreeInitCache.hpp"
-namespace btInverseDynamics {
-
+namespace btInverseDynamics
+{
MultiBodyTree::MultiBodyTree()
: m_is_finalized(false),
m_mass_parameters_are_valid(true),
m_accept_invalid_mass_parameters(false),
m_impl(0x0),
- m_init_cache(0x0) {
+ m_init_cache(0x0)
+{
m_init_cache = new InitCache();
}
-MultiBodyTree::~MultiBodyTree() {
+MultiBodyTree::~MultiBodyTree()
+{
delete m_impl;
delete m_init_cache;
}
-void MultiBodyTree::setAcceptInvalidMassParameters(bool flag) {
+void MultiBodyTree::setAcceptInvalidMassParameters(bool flag)
+{
m_accept_invalid_mass_parameters = flag;
}
-bool MultiBodyTree::getAcceptInvalidMassProperties() const {
+bool MultiBodyTree::getAcceptInvalidMassProperties() const
+{
return m_accept_invalid_mass_parameters;
}
-int MultiBodyTree::getBodyOrigin(const int body_index, vec3 *world_origin) const {
+int MultiBodyTree::getBodyOrigin(const int body_index, vec3 *world_origin) const
+{
return m_impl->getBodyOrigin(body_index, world_origin);
}
-int MultiBodyTree::getBodyCoM(const int body_index, vec3 *world_com) const {
+int MultiBodyTree::getBodyCoM(const int body_index, vec3 *world_com) const
+{
return m_impl->getBodyCoM(body_index, world_com);
}
-int MultiBodyTree::getBodyTransform(const int body_index, mat33 *world_T_body) const {
+int MultiBodyTree::getBodyTransform(const int body_index, mat33 *world_T_body) const
+{
return m_impl->getBodyTransform(body_index, world_T_body);
}
-int MultiBodyTree::getBodyAngularVelocity(const int body_index, vec3 *world_omega) const {
+int MultiBodyTree::getBodyAngularVelocity(const int body_index, vec3 *world_omega) const
+{
return m_impl->getBodyAngularVelocity(body_index, world_omega);
}
-int MultiBodyTree::getBodyLinearVelocity(const int body_index, vec3 *world_velocity) const {
+int MultiBodyTree::getBodyLinearVelocity(const int body_index, vec3 *world_velocity) const
+{
return m_impl->getBodyLinearVelocity(body_index, world_velocity);
}
-int MultiBodyTree::getBodyLinearVelocityCoM(const int body_index, vec3 *world_velocity) const {
+int MultiBodyTree::getBodyLinearVelocityCoM(const int body_index, vec3 *world_velocity) const
+{
return m_impl->getBodyLinearVelocityCoM(body_index, world_velocity);
}
-int MultiBodyTree::getBodyAngularAcceleration(const int body_index, vec3 *world_dot_omega) const {
+int MultiBodyTree::getBodyAngularAcceleration(const int body_index, vec3 *world_dot_omega) const
+{
return m_impl->getBodyAngularAcceleration(body_index, world_dot_omega);
}
-int MultiBodyTree::getBodyLinearAcceleration(const int body_index, vec3 *world_acceleration) const {
+int MultiBodyTree::getBodyLinearAcceleration(const int body_index, vec3 *world_acceleration) const
+{
return m_impl->getBodyLinearAcceleration(body_index, world_acceleration);
}
-int MultiBodyTree::getParentRParentBodyRef(const int body_index, vec3* r) const {
- return m_impl->getParentRParentBodyRef(body_index, r);
+int MultiBodyTree::getParentRParentBodyRef(const int body_index, vec3 *r) const
+{
+ return m_impl->getParentRParentBodyRef(body_index, r);
}
-int MultiBodyTree::getBodyTParentRef(const int body_index, mat33* T) const {
- return m_impl->getBodyTParentRef(body_index, T);
+int MultiBodyTree::getBodyTParentRef(const int body_index, mat33 *T) const
+{
+ return m_impl->getBodyTParentRef(body_index, T);
}
-int MultiBodyTree::getBodyAxisOfMotion(const int body_index, vec3* axis) const {
- return m_impl->getBodyAxisOfMotion(body_index, axis);
+int MultiBodyTree::getBodyAxisOfMotion(const int body_index, vec3 *axis) const
+{
+ return m_impl->getBodyAxisOfMotion(body_index, axis);
}
void MultiBodyTree::printTree() { m_impl->printTree(); }
@@ -81,12 +96,15 @@ int MultiBodyTree::numBodies() const { return m_impl->m_num_bodies; }
int MultiBodyTree::numDoFs() const { return m_impl->m_num_dofs; }
int MultiBodyTree::calculateInverseDynamics(const vecx &q, const vecx &u, const vecx &dot_u,
- vecx *joint_forces) {
- if (false == m_is_finalized) {
+ vecx *joint_forces)
+{
+ if (false == m_is_finalized)
+ {
bt_id_error_message("system has not been initialized\n");
return -1;
}
- if (-1 == m_impl->calculateInverseDynamics(q, u, dot_u, joint_forces)) {
+ if (-1 == m_impl->calculateInverseDynamics(q, u, dot_u, joint_forces))
+ {
bt_id_error_message("error in inverse dynamics calculation\n");
return -1;
}
@@ -95,141 +113,164 @@ int MultiBodyTree::calculateInverseDynamics(const vecx &q, const vecx &u, const
int MultiBodyTree::calculateMassMatrix(const vecx &q, const bool update_kinematics,
const bool initialize_matrix,
- const bool set_lower_triangular_matrix, matxx *mass_matrix) {
- if (false == m_is_finalized) {
+ const bool set_lower_triangular_matrix, matxx *mass_matrix)
+{
+ if (false == m_is_finalized)
+ {
bt_id_error_message("system has not been initialized\n");
return -1;
}
if (-1 ==
m_impl->calculateMassMatrix(q, update_kinematics, initialize_matrix,
- set_lower_triangular_matrix, mass_matrix)) {
+ set_lower_triangular_matrix, mass_matrix))
+ {
bt_id_error_message("error in mass matrix calculation\n");
return -1;
}
return 0;
}
-int MultiBodyTree::calculateMassMatrix(const vecx &q, matxx *mass_matrix) {
+int MultiBodyTree::calculateMassMatrix(const vecx &q, matxx *mass_matrix)
+{
return calculateMassMatrix(q, true, true, true, mass_matrix);
}
+int MultiBodyTree::calculateKinematics(const vecx &q, const vecx &u, const vecx &dot_u)
+{
+ vec3 world_gravity(m_impl->m_world_gravity);
+ // temporarily set gravity to zero, to ensure we get the actual accelerations
+ setZero(m_impl->m_world_gravity);
+ if (false == m_is_finalized)
+ {
+ bt_id_error_message("system has not been initialized\n");
+ return -1;
+ }
+ if (-1 == m_impl->calculateKinematics(q, u, dot_u,
+ MultiBodyTree::MultiBodyImpl::POSITION_VELOCITY_ACCELERATION))
+ {
+ bt_id_error_message("error in kinematics calculation\n");
+ return -1;
+ }
-int MultiBodyTree::calculateKinematics(const vecx& q, const vecx& u, const vecx& dot_u) {
- vec3 world_gravity(m_impl->m_world_gravity);
- // temporarily set gravity to zero, to ensure we get the actual accelerations
- setZero(m_impl->m_world_gravity);
-
- if (false == m_is_finalized) {
- bt_id_error_message("system has not been initialized\n");
- return -1;
- }
- if (-1 == m_impl->calculateKinematics(q, u, dot_u,
- MultiBodyTree::MultiBodyImpl::POSITION_VELOCITY_ACCELERATION)) {
- bt_id_error_message("error in kinematics calculation\n");
- return -1;
- }
-
- m_impl->m_world_gravity=world_gravity;
- return 0;
+ m_impl->m_world_gravity = world_gravity;
+ return 0;
}
-
-int MultiBodyTree::calculatePositionKinematics(const vecx& q) {
- if (false == m_is_finalized) {
+int MultiBodyTree::calculatePositionKinematics(const vecx &q)
+{
+ if (false == m_is_finalized)
+ {
bt_id_error_message("system has not been initialized\n");
return -1;
}
if (-1 == m_impl->calculateKinematics(q, q, q,
- MultiBodyTree::MultiBodyImpl::POSITION_VELOCITY)) {
+ MultiBodyTree::MultiBodyImpl::POSITION_VELOCITY))
+ {
bt_id_error_message("error in kinematics calculation\n");
return -1;
}
return 0;
}
-int MultiBodyTree::calculatePositionAndVelocityKinematics(const vecx& q, const vecx& u) {
- if (false == m_is_finalized) {
+int MultiBodyTree::calculatePositionAndVelocityKinematics(const vecx &q, const vecx &u)
+{
+ if (false == m_is_finalized)
+ {
bt_id_error_message("system has not been initialized\n");
return -1;
}
if (-1 == m_impl->calculateKinematics(q, u, u,
- MultiBodyTree::MultiBodyImpl::POSITION_VELOCITY)) {
+ MultiBodyTree::MultiBodyImpl::POSITION_VELOCITY))
+ {
bt_id_error_message("error in kinematics calculation\n");
return -1;
}
return 0;
}
-
#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
-int MultiBodyTree::calculateJacobians(const vecx& q, const vecx& u) {
- if (false == m_is_finalized) {
- bt_id_error_message("system has not been initialized\n");
- return -1;
- }
- if (-1 == m_impl->calculateJacobians(q, u,
- MultiBodyTree::MultiBodyImpl::POSITION_VELOCITY)) {
- bt_id_error_message("error in jacobian calculation\n");
- return -1;
- }
- return 0;
+int MultiBodyTree::calculateJacobians(const vecx &q, const vecx &u)
+{
+ if (false == m_is_finalized)
+ {
+ bt_id_error_message("system has not been initialized\n");
+ return -1;
+ }
+ if (-1 == m_impl->calculateJacobians(q, u,
+ MultiBodyTree::MultiBodyImpl::POSITION_VELOCITY))
+ {
+ bt_id_error_message("error in jacobian calculation\n");
+ return -1;
+ }
+ return 0;
}
-int MultiBodyTree::calculateJacobians(const vecx& q){
- if (false == m_is_finalized) {
- bt_id_error_message("system has not been initialized\n");
- return -1;
- }
- if (-1 == m_impl->calculateJacobians(q, q,
- MultiBodyTree::MultiBodyImpl::POSITION_ONLY)) {
- bt_id_error_message("error in jacobian calculation\n");
- return -1;
- }
- return 0;
+int MultiBodyTree::calculateJacobians(const vecx &q)
+{
+ if (false == m_is_finalized)
+ {
+ bt_id_error_message("system has not been initialized\n");
+ return -1;
+ }
+ if (-1 == m_impl->calculateJacobians(q, q,
+ MultiBodyTree::MultiBodyImpl::POSITION_ONLY))
+ {
+ bt_id_error_message("error in jacobian calculation\n");
+ return -1;
+ }
+ return 0;
}
-int MultiBodyTree::getBodyDotJacobianTransU(const int body_index, vec3* world_dot_jac_trans_u) const {
- return m_impl->getBodyDotJacobianTransU(body_index,world_dot_jac_trans_u);
+int MultiBodyTree::getBodyDotJacobianTransU(const int body_index, vec3 *world_dot_jac_trans_u) const
+{
+ return m_impl->getBodyDotJacobianTransU(body_index, world_dot_jac_trans_u);
}
-int MultiBodyTree::getBodyDotJacobianRotU(const int body_index, vec3* world_dot_jac_rot_u) const {
- return m_impl->getBodyDotJacobianRotU(body_index,world_dot_jac_rot_u);
+int MultiBodyTree::getBodyDotJacobianRotU(const int body_index, vec3 *world_dot_jac_rot_u) const
+{
+ return m_impl->getBodyDotJacobianRotU(body_index, world_dot_jac_rot_u);
}
-int MultiBodyTree::getBodyJacobianTrans(const int body_index, mat3x* world_jac_trans) const {
- return m_impl->getBodyJacobianTrans(body_index,world_jac_trans);
+int MultiBodyTree::getBodyJacobianTrans(const int body_index, mat3x *world_jac_trans) const
+{
+ return m_impl->getBodyJacobianTrans(body_index, world_jac_trans);
}
-int MultiBodyTree::getBodyJacobianRot(const int body_index, mat3x* world_jac_rot) const {
- return m_impl->getBodyJacobianRot(body_index,world_jac_rot);
+int MultiBodyTree::getBodyJacobianRot(const int body_index, mat3x *world_jac_rot) const
+{
+ return m_impl->getBodyJacobianRot(body_index, world_jac_rot);
}
-
#endif
int MultiBodyTree::addBody(int body_index, int parent_index, JointType joint_type,
const vec3 &parent_r_parent_body_ref, const mat33 &body_T_parent_ref,
const vec3 &body_axis_of_motion_, idScalar mass,
const vec3 &body_r_body_com, const mat33 &body_I_body,
- const int user_int, void *user_ptr) {
- if (body_index < 0) {
+ const int user_int, void *user_ptr)
+{
+ if (body_index < 0)
+ {
bt_id_error_message("body index must be positive (got %d)\n", body_index);
return -1;
}
vec3 body_axis_of_motion(body_axis_of_motion_);
- switch (joint_type) {
+ switch (joint_type)
+ {
case REVOLUTE:
case PRISMATIC:
// check if axis is unit vector
- if (!isUnitVector(body_axis_of_motion)) {
+ if (!isUnitVector(body_axis_of_motion))
+ {
bt_id_warning_message(
"axis of motion not a unit axis ([%f %f %f]), will use normalized vector\n",
body_axis_of_motion(0), body_axis_of_motion(1), body_axis_of_motion(2));
idScalar length = BT_ID_SQRT(BT_ID_POW(body_axis_of_motion(0), 2) +
- BT_ID_POW(body_axis_of_motion(1), 2) +
- BT_ID_POW(body_axis_of_motion(2), 2));
- if (length < BT_ID_SQRT(std::numeric_limits<idScalar>::min())) {
+ BT_ID_POW(body_axis_of_motion(1), 2) +
+ BT_ID_POW(body_axis_of_motion(2), 2));
+ if (length < BT_ID_SQRT(std::numeric_limits<idScalar>::min()))
+ {
bt_id_error_message("axis of motion vector too short (%e)\n", length);
return -1;
}
@@ -240,29 +281,36 @@ int MultiBodyTree::addBody(int body_index, int parent_index, JointType joint_typ
break;
case FLOATING:
break;
+ case SPHERICAL:
+ break;
default:
bt_id_error_message("unknown joint type %d\n", joint_type);
return -1;
}
// sanity check for mass properties. Zero mass is OK.
- if (mass < 0) {
+ if (mass < 0)
+ {
m_mass_parameters_are_valid = false;
bt_id_error_message("Body %d has invalid mass %e\n", body_index, mass);
- if (!m_accept_invalid_mass_parameters) {
+ if (!m_accept_invalid_mass_parameters)
+ {
return -1;
}
}
- if (!isValidInertiaMatrix(body_I_body, body_index, FIXED == joint_type)) {
+ if (!isValidInertiaMatrix(body_I_body, body_index, FIXED == joint_type))
+ {
m_mass_parameters_are_valid = false;
// error message printed in function call
- if (!m_accept_invalid_mass_parameters) {
+ if (!m_accept_invalid_mass_parameters)
+ {
return -1;
}
}
- if (!isValidTransformMatrix(body_T_parent_ref)) {
+ if (!isValidTransformMatrix(body_T_parent_ref))
+ {
return -1;
}
@@ -271,52 +319,63 @@ int MultiBodyTree::addBody(int body_index, int parent_index, JointType joint_typ
body_I_body, user_int, user_ptr);
}
-int MultiBodyTree::getParentIndex(const int body_index, int *parent_index) const {
+int MultiBodyTree::getParentIndex(const int body_index, int *parent_index) const
+{
return m_impl->getParentIndex(body_index, parent_index);
}
-int MultiBodyTree::getUserInt(const int body_index, int *user_int) const {
+int MultiBodyTree::getUserInt(const int body_index, int *user_int) const
+{
return m_impl->getUserInt(body_index, user_int);
}
-int MultiBodyTree::getUserPtr(const int body_index, void **user_ptr) const {
+int MultiBodyTree::getUserPtr(const int body_index, void **user_ptr) const
+{
return m_impl->getUserPtr(body_index, user_ptr);
}
-int MultiBodyTree::setUserInt(const int body_index, const int user_int) {
+int MultiBodyTree::setUserInt(const int body_index, const int user_int)
+{
return m_impl->setUserInt(body_index, user_int);
}
-int MultiBodyTree::setUserPtr(const int body_index, void *const user_ptr) {
+int MultiBodyTree::setUserPtr(const int body_index, void *const user_ptr)
+{
return m_impl->setUserPtr(body_index, user_ptr);
}
-int MultiBodyTree::finalize() {
+int MultiBodyTree::finalize()
+{
const int &num_bodies = m_init_cache->numBodies();
const int &num_dofs = m_init_cache->numDoFs();
- if(num_dofs<=0) {
- bt_id_error_message("Need num_dofs>=1, but num_dofs= %d\n", num_dofs);
- //return -1;
- }
+ if (num_dofs <= 0)
+ {
+ bt_id_error_message("Need num_dofs>=1, but num_dofs= %d\n", num_dofs);
+ //return -1;
+ }
// 1 allocate internal MultiBody structure
m_impl = new MultiBodyImpl(num_bodies, num_dofs);
// 2 build new index set assuring index(parent) < index(child)
- if (-1 == m_init_cache->buildIndexSets()) {
+ if (-1 == m_init_cache->buildIndexSets())
+ {
return -1;
}
m_init_cache->getParentIndexArray(&m_impl->m_parent_index);
// 3 setup internal kinematic and dynamic data
- for (int index = 0; index < num_bodies; index++) {
+ for (int index = 0; index < num_bodies; index++)
+ {
InertiaData inertia;
JointData joint;
- if (-1 == m_init_cache->getInertiaData(index, &inertia)) {
+ if (-1 == m_init_cache->getInertiaData(index, &inertia))
+ {
return -1;
}
- if (-1 == m_init_cache->getJointData(index, &joint)) {
+ if (-1 == m_init_cache->getJointData(index, &joint))
+ {
return -1;
}
@@ -332,24 +391,29 @@ int MultiBodyTree::finalize() {
rigid_body.m_joint_type = joint.m_type;
int user_int;
- if (-1 == m_init_cache->getUserInt(index, &user_int)) {
+ if (-1 == m_init_cache->getUserInt(index, &user_int))
+ {
return -1;
}
- if (-1 == m_impl->setUserInt(index, user_int)) {
+ if (-1 == m_impl->setUserInt(index, user_int))
+ {
return -1;
}
- void* user_ptr;
- if (-1 == m_init_cache->getUserPtr(index, &user_ptr)) {
+ void *user_ptr;
+ if (-1 == m_init_cache->getUserPtr(index, &user_ptr))
+ {
return -1;
}
- if (-1 == m_impl->setUserPtr(index, user_ptr)) {
+ if (-1 == m_impl->setUserPtr(index, user_ptr))
+ {
return -1;
}
// Set joint Jacobians. Note that the dimension is always 3x1 here to avoid variable sized
// matrices.
- switch (rigid_body.m_joint_type) {
+ switch (rigid_body.m_joint_type)
+ {
case REVOLUTE:
rigid_body.m_Jac_JR(0) = joint.m_child_axis_of_motion(0);
rigid_body.m_Jac_JR(1) = joint.m_child_axis_of_motion(1);
@@ -375,6 +439,16 @@ int MultiBodyTree::finalize() {
rigid_body.m_Jac_JT(1) = 0.0;
rigid_body.m_Jac_JT(2) = 0.0;
break;
+ case SPHERICAL:
+ // NOTE/TODO: this is not really correct.
+ // the Jacobians should be 3x3 matrices here !
+ rigid_body.m_Jac_JR(0) = 0.0;
+ rigid_body.m_Jac_JR(1) = 0.0;
+ rigid_body.m_Jac_JR(2) = 0.0;
+ rigid_body.m_Jac_JT(0) = 0.0;
+ rigid_body.m_Jac_JT(1) = 0.0;
+ rigid_body.m_Jac_JT(2) = 0.0;
+ break;
case FLOATING:
// NOTE/TODO: this is not really correct.
// the Jacobians should be 3x3 matrices here !
@@ -392,7 +466,8 @@ int MultiBodyTree::finalize() {
}
// 4 assign degree of freedom indices & build per-joint-type index arrays
- if (-1 == m_impl->generateIndexSets()) {
+ if (-1 == m_impl->generateIndexSets())
+ {
bt_id_error_message("generating index sets\n");
return -1;
}
@@ -408,54 +483,66 @@ int MultiBodyTree::finalize() {
return 0;
}
-int MultiBodyTree::setGravityInWorldFrame(const vec3 &gravity) {
+int MultiBodyTree::setGravityInWorldFrame(const vec3 &gravity)
+{
return m_impl->setGravityInWorldFrame(gravity);
}
-int MultiBodyTree::getJointType(const int body_index, JointType *joint_type) const {
+int MultiBodyTree::getJointType(const int body_index, JointType *joint_type) const
+{
return m_impl->getJointType(body_index, joint_type);
}
-int MultiBodyTree::getJointTypeStr(const int body_index, const char **joint_type) const {
+int MultiBodyTree::getJointTypeStr(const int body_index, const char **joint_type) const
+{
return m_impl->getJointTypeStr(body_index, joint_type);
}
-int MultiBodyTree::getDoFOffset(const int body_index, int *q_offset) const {
+int MultiBodyTree::getDoFOffset(const int body_index, int *q_offset) const
+{
return m_impl->getDoFOffset(body_index, q_offset);
}
-int MultiBodyTree::setBodyMass(const int body_index, idScalar mass) {
+int MultiBodyTree::setBodyMass(const int body_index, idScalar mass)
+{
return m_impl->setBodyMass(body_index, mass);
}
-int MultiBodyTree::setBodyFirstMassMoment(const int body_index, const vec3& first_mass_moment) {
+int MultiBodyTree::setBodyFirstMassMoment(const int body_index, const vec3 &first_mass_moment)
+{
return m_impl->setBodyFirstMassMoment(body_index, first_mass_moment);
}
-int MultiBodyTree::setBodySecondMassMoment(const int body_index, const mat33& second_mass_moment) {
+int MultiBodyTree::setBodySecondMassMoment(const int body_index, const mat33 &second_mass_moment)
+{
return m_impl->setBodySecondMassMoment(body_index, second_mass_moment);
}
-int MultiBodyTree::getBodyMass(const int body_index, idScalar *mass) const {
+int MultiBodyTree::getBodyMass(const int body_index, idScalar *mass) const
+{
return m_impl->getBodyMass(body_index, mass);
}
-int MultiBodyTree::getBodyFirstMassMoment(const int body_index, vec3 *first_mass_moment) const {
+int MultiBodyTree::getBodyFirstMassMoment(const int body_index, vec3 *first_mass_moment) const
+{
return m_impl->getBodyFirstMassMoment(body_index, first_mass_moment);
}
-int MultiBodyTree::getBodySecondMassMoment(const int body_index, mat33 *second_mass_moment) const {
+int MultiBodyTree::getBodySecondMassMoment(const int body_index, mat33 *second_mass_moment) const
+{
return m_impl->getBodySecondMassMoment(body_index, second_mass_moment);
}
void MultiBodyTree::clearAllUserForcesAndMoments() { m_impl->clearAllUserForcesAndMoments(); }
-int MultiBodyTree::addUserForce(const int body_index, const vec3 &body_force) {
+int MultiBodyTree::addUserForce(const int body_index, const vec3 &body_force)
+{
return m_impl->addUserForce(body_index, body_force);
}
-int MultiBodyTree::addUserMoment(const int body_index, const vec3 &body_moment) {
+int MultiBodyTree::addUserMoment(const int body_index, const vec3 &body_moment)
+{
return m_impl->addUserMoment(body_index, body_moment);
}
-}
+} // namespace btInverseDynamics
diff --git a/thirdparty/bullet/BulletInverseDynamics/MultiBodyTree.hpp b/thirdparty/bullet/BulletInverseDynamics/MultiBodyTree.hpp
index d235aa6e76..7b852f976c 100644
--- a/thirdparty/bullet/BulletInverseDynamics/MultiBodyTree.hpp
+++ b/thirdparty/bullet/BulletInverseDynamics/MultiBodyTree.hpp
@@ -4,10 +4,11 @@
#include "IDConfig.hpp"
#include "IDMath.hpp"
-namespace btInverseDynamics {
-
+namespace btInverseDynamics
+{
/// Enumeration of supported joint types
-enum JointType {
+enum JointType
+{
/// no degree of freedom, moves with parent
FIXED = 0,
/// one rotational degree of freedom relative to parent
@@ -15,7 +16,9 @@ enum JointType {
/// one translational degree of freedom relative to parent
PRISMATIC,
/// six degrees of freedom relative to parent
- FLOATING
+ FLOATING,
+ /// three degrees of freedom, relative to parent
+ SPHERICAL
};
/// Interface class for calculating inverse dynamics for tree structured
@@ -30,12 +33,14 @@ enum JointType {
/// - PRISMATIC: displacement [m]
/// - FLOATING: Euler x-y-z angles [rad] and displacement in body-fixed frame of parent [m]
/// (in that order)
+/// - SPHERICAL: Euler x-y-z angles [rad]
/// The u vector contains the generalized speeds, which are
/// - FIXED: none
/// - REVOLUTE: time derivative of angle of rotation [rad/s]
/// - PRISMATIC: time derivative of displacement [m/s]
/// - FLOATING: angular velocity [rad/s] (*not* time derivative of rpy angles)
/// and time derivative of displacement in parent frame [m/s]
+// - SPHERICAL: angular velocity [rad/s]
///
/// The q and u vectors are obtained by stacking contributions of all bodies in one
/// vector in the order of body indices.
@@ -46,12 +51,13 @@ enum JointType {
/// - PRISMATIC: force [N], along joint axis
/// - FLOATING: moment vector [Nm] and force vector [N], both in body-fixed frame
/// (in that order)
-///
+/// - SPHERICAL: moment vector [Nm]
/// TODO - force element interface (friction, springs, dampers, etc)
/// - gears and motor inertia
-class MultiBodyTree {
+class MultiBodyTree
+{
public:
- ID_DECLARE_ALIGNED_ALLOCATOR();
+ ID_DECLARE_ALIGNED_ALLOCATOR();
/// The contructor.
/// Initialization & allocation is via addBody and buildSystem calls.
MultiBodyTree();
@@ -119,9 +125,9 @@ public:
/// print tree data to stdout
void printTreeData();
/// Calculate joint forces for given generalized state & derivatives.
- /// This also updates kinematic terms computed in calculateKinematics.
- /// If gravity is not set to zero, acceleration terms will contain
- /// gravitational acceleration.
+ /// This also updates kinematic terms computed in calculateKinematics.
+ /// If gravity is not set to zero, acceleration terms will contain
+ /// gravitational acceleration.
/// @param q generalized coordinates
/// @param u generalized velocities. In the general case, u=T(q)*dot(q) and dim(q)>=dim(u)
/// @param dot_u time derivative of u
@@ -152,30 +158,28 @@ public:
/// @return -1 on error, 0 on success
int calculateMassMatrix(const vecx& q, matxx* mass_matrix);
-
- /// Calculates kinematics also calculated in calculateInverseDynamics,
- /// but not dynamics.
- /// This function ensures that correct accelerations are computed that do not
- /// contain gravitational acceleration terms.
- /// Does not calculate Jacobians, but only vector quantities (positions, velocities & accelerations)
- int calculateKinematics(const vecx& q, const vecx& u, const vecx& dot_u);
- /// Calculate position kinematics
- int calculatePositionKinematics(const vecx& q);
- /// Calculate position and velocity kinematics
- int calculatePositionAndVelocityKinematics(const vecx& q, const vecx& u);
+ /// Calculates kinematics also calculated in calculateInverseDynamics,
+ /// but not dynamics.
+ /// This function ensures that correct accelerations are computed that do not
+ /// contain gravitational acceleration terms.
+ /// Does not calculate Jacobians, but only vector quantities (positions, velocities & accelerations)
+ int calculateKinematics(const vecx& q, const vecx& u, const vecx& dot_u);
+ /// Calculate position kinematics
+ int calculatePositionKinematics(const vecx& q);
+ /// Calculate position and velocity kinematics
+ int calculatePositionAndVelocityKinematics(const vecx& q, const vecx& u);
#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
- /// Calculate Jacobians (dvel/du), as well as velocity-dependent accelearation components
- /// d(Jacobian)/dt*u
- /// This function assumes that calculateInverseDynamics was called, or calculateKinematics,
- /// or calculatePositionAndVelocityKinematics
- int calculateJacobians(const vecx& q, const vecx& u);
- /// Calculate Jacobians (dvel/du)
- /// This function assumes that calculateInverseDynamics was called, or
- /// one of the calculateKineamtics functions
- int calculateJacobians(const vecx& q);
-#endif // BT_ID_HAVE_MAT3X
-
+ /// Calculate Jacobians (dvel/du), as well as velocity-dependent accelearation components
+ /// d(Jacobian)/dt*u
+ /// This function assumes that calculateInverseDynamics was called, or calculateKinematics,
+ /// or calculatePositionAndVelocityKinematics
+ int calculateJacobians(const vecx& q, const vecx& u);
+ /// Calculate Jacobians (dvel/du)
+ /// This function assumes that calculateInverseDynamics was called, or
+ /// one of the calculateKineamtics functions
+ int calculateJacobians(const vecx& q);
+#endif // BT_ID_HAVE_MAT3X
/// set gravitational acceleration
/// the default is [0;0;-9.8] in the world frame
@@ -231,15 +235,15 @@ public:
int getBodyLinearAcceleration(const int body_index, vec3* world_acceleration) const;
#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
- // get translational jacobian, in world frame (dworld_velocity/du)
- int getBodyJacobianTrans(const int body_index, mat3x* world_jac_trans) const;
- // get rotational jacobian, in world frame (dworld_omega/du)
- int getBodyJacobianRot(const int body_index, mat3x* world_jac_rot) const;
- // get product of translational jacobian derivative * generatlized velocities
- int getBodyDotJacobianTransU(const int body_index, vec3* world_dot_jac_trans_u) const;
- // get product of rotational jacobian derivative * generatlized velocities
- int getBodyDotJacobianRotU(const int body_index, vec3* world_dot_jac_rot_u) const;
-#endif // BT_ID_HAVE_MAT3X
+ // get translational jacobian, in world frame (dworld_velocity/du)
+ int getBodyJacobianTrans(const int body_index, mat3x* world_jac_trans) const;
+ // get rotational jacobian, in world frame (dworld_omega/du)
+ int getBodyJacobianRot(const int body_index, mat3x* world_jac_rot) const;
+ // get product of translational jacobian derivative * generatlized velocities
+ int getBodyDotJacobianTransU(const int body_index, vec3* world_dot_jac_trans_u) const;
+ // get product of rotational jacobian derivative * generatlized velocities
+ int getBodyDotJacobianRotU(const int body_index, vec3* world_dot_jac_rot_u) const;
+#endif // BT_ID_HAVE_MAT3X
/// returns the (internal) index of body
/// @param body_index is the index of a body
@@ -256,21 +260,21 @@ public:
/// @param joint_type string naming the corresponding joint type
/// @return 0 on success, -1 on failure
int getJointTypeStr(const int body_index, const char** joint_type) const;
- /// get offset translation to parent body (see addBody)
+ /// get offset translation to parent body (see addBody)
/// @param body_index index of the body
/// @param r the offset translation (see above)
/// @return 0 on success, -1 on failure
- int getParentRParentBodyRef(const int body_index, vec3* r) const;
+ int getParentRParentBodyRef(const int body_index, vec3* r) const;
/// get offset rotation to parent body (see addBody)
/// @param body_index index of the body
/// @param T the transform (see above)
/// @return 0 on success, -1 on failure
- int getBodyTParentRef(const int body_index, mat33* T) const;
+ int getBodyTParentRef(const int body_index, mat33* T) const;
/// get axis of motion (see addBody)
/// @param body_index index of the body
/// @param axis the axis (see above)
/// @return 0 on success, -1 on failure
- int getBodyAxisOfMotion(const int body_index, vec3* axis) const;
+ int getBodyAxisOfMotion(const int body_index, vec3* axis) const;
/// get offset for degrees of freedom of this body into the q-vector
/// @param body_index index of the body
/// @param q_offset offset the q vector
diff --git a/thirdparty/bullet/BulletInverseDynamics/details/IDEigenInterface.hpp b/thirdparty/bullet/BulletInverseDynamics/details/IDEigenInterface.hpp
index 836395cea2..fe4f102513 100644
--- a/thirdparty/bullet/BulletInverseDynamics/details/IDEigenInterface.hpp
+++ b/thirdparty/bullet/BulletInverseDynamics/details/IDEigenInterface.hpp
@@ -1,8 +1,8 @@
#ifndef INVDYNEIGENINTERFACE_HPP_
#define INVDYNEIGENINTERFACE_HPP_
#include "../IDConfig.hpp"
-namespace btInverseDynamics {
-
+namespace btInverseDynamics
+{
#define BT_ID_HAVE_MAT3X
#ifdef BT_USE_DOUBLE_PRECISION
@@ -19,18 +19,21 @@ typedef Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::DontAlign> m
typedef Eigen::Matrix<float, 3, Eigen::Dynamic, Eigen::DontAlign> mat3x;
#endif
-inline void resize(mat3x &m, Eigen::Index size) {
- m.resize(3, size);
- m.setZero();
+inline void resize(mat3x &m, Eigen::Index size)
+{
+ m.resize(3, size);
+ m.setZero();
}
-inline void setMatxxElem(const idArrayIdx row, const idArrayIdx col, const idScalar val, matxx*m){
- (*m)(row, col) = val;
+inline void setMatxxElem(const idArrayIdx row, const idArrayIdx col, const idScalar val, matxx *m)
+{
+ (*m)(row, col) = val;
}
-inline void setMat3xElem(const idArrayIdx row, const idArrayIdx col, const idScalar val, mat3x*m){
- (*m)(row, col) = val;
+inline void setMat3xElem(const idArrayIdx row, const idArrayIdx col, const idScalar val, mat3x *m)
+{
+ (*m)(row, col) = val;
}
-}
+} // namespace btInverseDynamics
#endif // INVDYNEIGENINTERFACE_HPP_
diff --git a/thirdparty/bullet/BulletInverseDynamics/details/IDLinearMathInterface.hpp b/thirdparty/bullet/BulletInverseDynamics/details/IDLinearMathInterface.hpp
index c179daeec6..0c398a3727 100644
--- a/thirdparty/bullet/BulletInverseDynamics/details/IDLinearMathInterface.hpp
+++ b/thirdparty/bullet/BulletInverseDynamics/details/IDLinearMathInterface.hpp
@@ -10,32 +10,37 @@
#include "../../LinearMath/btMatrixX.h"
#define BT_ID_HAVE_MAT3X
-namespace btInverseDynamics {
+namespace btInverseDynamics
+{
class vec3;
class vecx;
class mat33;
typedef btMatrixX<idScalar> matxx;
-class vec3 : public btVector3 {
+class vec3 : public btVector3
+{
public:
vec3() : btVector3() {}
vec3(const btVector3& btv) { *this = btv; }
idScalar& operator()(int i) { return (*this)[i]; }
const idScalar& operator()(int i) const { return (*this)[i]; }
int size() const { return 3; }
- const vec3& operator=(const btVector3& rhs) {
+ const vec3& operator=(const btVector3& rhs)
+ {
*static_cast<btVector3*>(this) = rhs;
return *this;
}
};
-class mat33 : public btMatrix3x3 {
+class mat33 : public btMatrix3x3
+{
public:
mat33() : btMatrix3x3() {}
mat33(const btMatrix3x3& btm) { *this = btm; }
idScalar& operator()(int i, int j) { return (*this)[i][j]; }
const idScalar& operator()(int i, int j) const { return (*this)[i][j]; }
- const mat33& operator=(const btMatrix3x3& rhs) {
+ const mat33& operator=(const btMatrix3x3& rhs)
+ {
*static_cast<btMatrix3x3*>(this) = rhs;
return *this;
}
@@ -47,10 +52,12 @@ inline mat33 operator/(const mat33& a, const idScalar& s) { return a * (1.0 / s)
inline mat33 operator*(const idScalar& s, const mat33& a) { return a * s; }
-class vecx : public btVectorX<idScalar> {
+class vecx : public btVectorX<idScalar>
+{
public:
vecx(int size) : btVectorX<idScalar>(size) {}
- const vecx& operator=(const btVectorX<idScalar>& rhs) {
+ const vecx& operator=(const btVectorX<idScalar>& rhs)
+ {
*static_cast<btVectorX<idScalar>*>(this) = rhs;
return *this;
}
@@ -66,43 +73,53 @@ public:
friend vecx operator/(const vecx& a, const idScalar& s);
};
-inline vecx operator*(const vecx& a, const idScalar& s) {
+inline vecx operator*(const vecx& a, const idScalar& s)
+{
vecx result(a.size());
- for (int i = 0; i < result.size(); i++) {
+ for (int i = 0; i < result.size(); i++)
+ {
result(i) = a(i) * s;
}
return result;
}
inline vecx operator*(const idScalar& s, const vecx& a) { return a * s; }
-inline vecx operator+(const vecx& a, const vecx& b) {
+inline vecx operator+(const vecx& a, const vecx& b)
+{
vecx result(a.size());
// TODO: error handling for a.size() != b.size()??
- if (a.size() != b.size()) {
+ if (a.size() != b.size())
+ {
bt_id_error_message("size missmatch. a.size()= %d, b.size()= %d\n", a.size(), b.size());
abort();
}
- for (int i = 0; i < a.size(); i++) {
+ for (int i = 0; i < a.size(); i++)
+ {
result(i) = a(i) + b(i);
}
return result;
}
-inline vecx operator-(const vecx& a, const vecx& b) {
+inline vecx operator-(const vecx& a, const vecx& b)
+{
vecx result(a.size());
// TODO: error handling for a.size() != b.size()??
- if (a.size() != b.size()) {
+ if (a.size() != b.size())
+ {
bt_id_error_message("size missmatch. a.size()= %d, b.size()= %d\n", a.size(), b.size());
abort();
}
- for (int i = 0; i < a.size(); i++) {
+ for (int i = 0; i < a.size(); i++)
+ {
result(i) = a(i) - b(i);
}
return result;
}
-inline vecx operator/(const vecx& a, const idScalar& s) {
+inline vecx operator/(const vecx& a, const idScalar& s)
+{
vecx result(a.size());
- for (int i = 0; i < result.size(); i++) {
+ for (int i = 0; i < result.size(); i++)
+ {
result(i) = a(i) / s;
}
@@ -110,63 +127,76 @@ inline vecx operator/(const vecx& a, const idScalar& s) {
}
// use btMatrixX to implement 3xX matrix
-class mat3x : public matxx {
+class mat3x : public matxx
+{
public:
- mat3x(){}
- mat3x(const mat3x&rhs) {
- matxx::resize(rhs.rows(), rhs.cols());
- *this = rhs;
- }
- mat3x(int rows, int cols): matxx(3,cols) {
- }
- void operator=(const mat3x& rhs) {
- if (m_cols != rhs.m_cols) {
- bt_id_error_message("size missmatch, cols= %d but rhs.cols= %d\n", cols(), rhs.cols());
- abort();
+ mat3x() {}
+ mat3x(const mat3x& rhs)
+ {
+ matxx::resize(rhs.rows(), rhs.cols());
+ *this = rhs;
+ }
+ mat3x(int rows, int cols) : matxx(3, cols)
+ {
+ }
+ void operator=(const mat3x& rhs)
+ {
+ if (m_cols != rhs.m_cols)
+ {
+ bt_id_error_message("size missmatch, cols= %d but rhs.cols= %d\n", cols(), rhs.cols());
+ abort();
+ }
+ for (int i = 0; i < rows(); i++)
+ {
+ for (int k = 0; k < cols(); k++)
+ {
+ setElem(i, k, rhs(i, k));
+ }
+ }
+ }
+ void setZero()
+ {
+ matxx::setZero();
}
- for(int i=0;i<rows();i++) {
- for(int k=0;k<cols();k++) {
- setElem(i,k,rhs(i,k));
- }
- }
- }
- void setZero() {
- matxx::setZero();
- }
};
-
-inline vec3 operator*(const mat3x& a, const vecx& b) {
- vec3 result;
- if (a.cols() != b.size()) {
- bt_id_error_message("size missmatch. a.cols()= %d, b.size()= %d\n", a.cols(), b.size());
- abort();
- }
- result(0)=0.0;
- result(1)=0.0;
- result(2)=0.0;
- for(int i=0;i<b.size();i++) {
- for(int k=0;k<3;k++) {
- result(k)+=a(k,i)*b(i);
- }
- }
- return result;
+inline vec3 operator*(const mat3x& a, const vecx& b)
+{
+ vec3 result;
+ if (a.cols() != b.size())
+ {
+ bt_id_error_message("size missmatch. a.cols()= %d, b.size()= %d\n", a.cols(), b.size());
+ abort();
+ }
+ result(0) = 0.0;
+ result(1) = 0.0;
+ result(2) = 0.0;
+ for (int i = 0; i < b.size(); i++)
+ {
+ for (int k = 0; k < 3; k++)
+ {
+ result(k) += a(k, i) * b(i);
+ }
+ }
+ return result;
}
-
-inline void resize(mat3x &m, idArrayIdx size) {
- m.resize(3, size);
- m.setZero();
+inline void resize(mat3x& m, idArrayIdx size)
+{
+ m.resize(3, size);
+ m.setZero();
}
-inline void setMatxxElem(const idArrayIdx row, const idArrayIdx col, const idScalar val, matxx*m){
- m->setElem(row, col, val);
+inline void setMatxxElem(const idArrayIdx row, const idArrayIdx col, const idScalar val, matxx* m)
+{
+ m->setElem(row, col, val);
}
-inline void setMat3xElem(const idArrayIdx row, const idArrayIdx col, const idScalar val, mat3x*m){
- m->setElem(row, col, val);
+inline void setMat3xElem(const idArrayIdx row, const idArrayIdx col, const idScalar val, mat3x* m)
+{
+ m->setElem(row, col, val);
}
-}
+} // namespace btInverseDynamics
#endif // IDLINEARMATHINTERFACE_HPP_
diff --git a/thirdparty/bullet/BulletInverseDynamics/details/IDMatVec.hpp b/thirdparty/bullet/BulletInverseDynamics/details/IDMatVec.hpp
index c89db5e123..1c786095e7 100644
--- a/thirdparty/bullet/BulletInverseDynamics/details/IDMatVec.hpp
+++ b/thirdparty/bullet/BulletInverseDynamics/details/IDMatVec.hpp
@@ -7,7 +7,8 @@
#include "../IDConfig.hpp"
#define BT_ID_HAVE_MAT3X
-namespace btInverseDynamics {
+namespace btInverseDynamics
+{
class vec3;
class vecx;
class mat33;
@@ -17,7 +18,8 @@ class mat3x;
/// This is a very basic implementation to enable stand-alone use of the library.
/// The implementation is not really optimized and misses many features that you would
/// want from a "fully featured" linear math library.
-class vec3 {
+class vec3
+{
public:
idScalar& operator()(int i) { return m_data[i]; }
const idScalar& operator()(int i) const { return m_data[i]; }
@@ -40,7 +42,8 @@ private:
idScalar m_data[3];
};
-class mat33 {
+class mat33
+{
public:
idScalar& operator()(int i, int j) { return m_data[3 * i + j]; }
const idScalar& operator()(int i, int j) const { return m_data[3 * i + j]; }
@@ -62,9 +65,11 @@ private:
idScalar m_data[9];
};
-class vecx {
+class vecx
+{
public:
- vecx(int size) : m_size(size) {
+ vecx(int size) : m_size(size)
+ {
m_data = static_cast<idScalar*>(idMalloc(sizeof(idScalar) * size));
}
~vecx() { idFree(m_data); }
@@ -85,14 +90,17 @@ private:
idScalar* m_data;
};
-class matxx {
+class matxx
+{
public:
- matxx() {
- m_data = 0x0;
- m_cols=0;
- m_rows=0;
- }
- matxx(int rows, int cols) : m_rows(rows), m_cols(cols) {
+ matxx()
+ {
+ m_data = 0x0;
+ m_cols = 0;
+ m_rows = 0;
+ }
+ matxx(int rows, int cols) : m_rows(rows), m_cols(cols)
+ {
m_data = static_cast<idScalar*>(idMalloc(sizeof(idScalar) * rows * cols));
}
~matxx() { idFree(m_data); }
@@ -107,69 +115,86 @@ private:
idScalar* m_data;
};
-class mat3x {
+class mat3x
+{
public:
- mat3x() {
- m_data = 0x0;
- m_cols=0;
- }
- mat3x(const mat3x&rhs) {
- m_cols=rhs.m_cols;
- allocate();
- *this = rhs;
- }
- mat3x(int rows, int cols): m_cols(cols) {
- allocate();
- };
- void operator=(const mat3x& rhs) {
- if (m_cols != rhs.m_cols) {
- bt_id_error_message("size missmatch, cols= %d but rhs.cols= %d\n", cols(), rhs.cols());
- abort();
- }
- for(int i=0;i<3*m_cols;i++) {
- m_data[i] = rhs.m_data[i];
- }
- }
-
- ~mat3x() {
- free();
- }
- idScalar& operator()(int row, int col) { return m_data[row * m_cols + col]; }
- const idScalar& operator()(int row, int col) const { return m_data[row * m_cols + col]; }
- int rows() const { return m_rows; }
- const int& cols() const { return m_cols; }
- void resize(int rows, int cols) {
- m_cols=cols;
- free();
- allocate();
- }
- void setZero() {
- memset(m_data,0x0,sizeof(idScalar)*m_rows*m_cols);
- }
- // avoid operators that would allocate -- use functions sub/add/mul in IDMath.hpp instead
+ mat3x()
+ {
+ m_data = 0x0;
+ m_cols = 0;
+ }
+ mat3x(const mat3x& rhs)
+ {
+ m_cols = rhs.m_cols;
+ allocate();
+ *this = rhs;
+ }
+ mat3x(int rows, int cols) : m_cols(cols)
+ {
+ allocate();
+ };
+ void operator=(const mat3x& rhs)
+ {
+ if (m_cols != rhs.m_cols)
+ {
+ bt_id_error_message("size missmatch, cols= %d but rhs.cols= %d\n", cols(), rhs.cols());
+ abort();
+ }
+ for (int i = 0; i < 3 * m_cols; i++)
+ {
+ m_data[i] = rhs.m_data[i];
+ }
+ }
+
+ ~mat3x()
+ {
+ free();
+ }
+ idScalar& operator()(int row, int col) { return m_data[row * m_cols + col]; }
+ const idScalar& operator()(int row, int col) const { return m_data[row * m_cols + col]; }
+ int rows() const { return m_rows; }
+ const int& cols() const { return m_cols; }
+ void resize(int rows, int cols)
+ {
+ m_cols = cols;
+ free();
+ allocate();
+ }
+ void setZero()
+ {
+ memset(m_data, 0x0, sizeof(idScalar) * m_rows * m_cols);
+ }
+ // avoid operators that would allocate -- use functions sub/add/mul in IDMath.hpp instead
private:
- void allocate(){m_data = static_cast<idScalar*>(idMalloc(sizeof(idScalar) * m_rows * m_cols));}
- void free() { idFree(m_data);}
- enum {m_rows=3};
- int m_cols;
- idScalar* m_data;
+ void allocate() { m_data = static_cast<idScalar*>(idMalloc(sizeof(idScalar) * m_rows * m_cols)); }
+ void free() { idFree(m_data); }
+ enum
+ {
+ m_rows = 3
+ };
+ int m_cols;
+ idScalar* m_data;
};
-inline void resize(mat3x &m, idArrayIdx size) {
- m.resize(3, size);
- m.setZero();
+inline void resize(mat3x& m, idArrayIdx size)
+{
+ m.resize(3, size);
+ m.setZero();
}
//////////////////////////////////////////////////
// Implementations
-inline const vec3& vec3::operator=(const vec3& rhs) {
- if (&rhs != this) {
+inline const vec3& vec3::operator=(const vec3& rhs)
+{
+ if (&rhs != this)
+ {
memcpy(m_data, rhs.m_data, 3 * sizeof(idScalar));
}
return *this;
}
-inline vec3 vec3::cross(const vec3& b) const {
+inline vec3 vec3::cross(const vec3& b) const
+{
vec3 result;
result.m_data[0] = m_data[1] * b.m_data[2] - m_data[2] * b.m_data[1];
result.m_data[1] = m_data[2] * b.m_data[0] - m_data[0] * b.m_data[2];
@@ -178,17 +203,21 @@ inline vec3 vec3::cross(const vec3& b) const {
return result;
}
-inline idScalar vec3::dot(const vec3& b) const {
+inline idScalar vec3::dot(const vec3& b) const
+{
return m_data[0] * b.m_data[0] + m_data[1] * b.m_data[1] + m_data[2] * b.m_data[2];
}
-inline const mat33& mat33::operator=(const mat33& rhs) {
- if (&rhs != this) {
+inline const mat33& mat33::operator=(const mat33& rhs)
+{
+ if (&rhs != this)
+ {
memcpy(m_data, rhs.m_data, 9 * sizeof(idScalar));
}
return *this;
}
-inline mat33 mat33::transpose() const {
+inline mat33 mat33::transpose() const
+{
mat33 result;
result.m_data[0] = m_data[0];
result.m_data[1] = m_data[3];
@@ -203,7 +232,8 @@ inline mat33 mat33::transpose() const {
return result;
}
-inline mat33 operator*(const mat33& a, const mat33& b) {
+inline mat33 operator*(const mat33& a, const mat33& b)
+{
mat33 result;
result.m_data[0] =
a.m_data[0] * b.m_data[0] + a.m_data[1] * b.m_data[3] + a.m_data[2] * b.m_data[6];
@@ -227,22 +257,27 @@ inline mat33 operator*(const mat33& a, const mat33& b) {
return result;
}
-inline const mat33& mat33::operator+=(const mat33& b) {
- for (int i = 0; i < 9; i++) {
+inline const mat33& mat33::operator+=(const mat33& b)
+{
+ for (int i = 0; i < 9; i++)
+ {
m_data[i] += b.m_data[i];
}
return *this;
}
-inline const mat33& mat33::operator-=(const mat33& b) {
- for (int i = 0; i < 9; i++) {
+inline const mat33& mat33::operator-=(const mat33& b)
+{
+ for (int i = 0; i < 9; i++)
+ {
m_data[i] -= b.m_data[i];
}
return *this;
}
-inline vec3 operator*(const mat33& a, const vec3& b) {
+inline vec3 operator*(const mat33& a, const vec3& b)
+{
vec3 result;
result.m_data[0] =
@@ -255,23 +290,29 @@ inline vec3 operator*(const mat33& a, const vec3& b) {
return result;
}
-inline const vec3& vec3::operator+=(const vec3& b) {
- for (int i = 0; i < 3; i++) {
+inline const vec3& vec3::operator+=(const vec3& b)
+{
+ for (int i = 0; i < 3; i++)
+ {
m_data[i] += b.m_data[i];
}
return *this;
}
-inline const vec3& vec3::operator-=(const vec3& b) {
- for (int i = 0; i < 3; i++) {
+inline const vec3& vec3::operator-=(const vec3& b)
+{
+ for (int i = 0; i < 3; i++)
+ {
m_data[i] -= b.m_data[i];
}
return *this;
}
-inline mat33 operator*(const mat33& a, const idScalar& s) {
+inline mat33 operator*(const mat33& a, const idScalar& s)
+{
mat33 result;
- for (int i = 0; i < 9; i++) {
+ for (int i = 0; i < 9; i++)
+ {
result.m_data[i] = a.m_data[i] * s;
}
return result;
@@ -279,137 +320,170 @@ inline mat33 operator*(const mat33& a, const idScalar& s) {
inline mat33 operator*(const idScalar& s, const mat33& a) { return a * s; }
-inline vec3 operator*(const vec3& a, const idScalar& s) {
+inline vec3 operator*(const vec3& a, const idScalar& s)
+{
vec3 result;
- for (int i = 0; i < 3; i++) {
+ for (int i = 0; i < 3; i++)
+ {
result.m_data[i] = a.m_data[i] * s;
}
return result;
}
inline vec3 operator*(const idScalar& s, const vec3& a) { return a * s; }
-inline mat33 operator+(const mat33& a, const mat33& b) {
+inline mat33 operator+(const mat33& a, const mat33& b)
+{
mat33 result;
- for (int i = 0; i < 9; i++) {
+ for (int i = 0; i < 9; i++)
+ {
result.m_data[i] = a.m_data[i] + b.m_data[i];
}
return result;
}
-inline vec3 operator+(const vec3& a, const vec3& b) {
+inline vec3 operator+(const vec3& a, const vec3& b)
+{
vec3 result;
- for (int i = 0; i < 3; i++) {
+ for (int i = 0; i < 3; i++)
+ {
result.m_data[i] = a.m_data[i] + b.m_data[i];
}
return result;
}
-inline mat33 operator-(const mat33& a, const mat33& b) {
+inline mat33 operator-(const mat33& a, const mat33& b)
+{
mat33 result;
- for (int i = 0; i < 9; i++) {
+ for (int i = 0; i < 9; i++)
+ {
result.m_data[i] = a.m_data[i] - b.m_data[i];
}
return result;
}
-inline vec3 operator-(const vec3& a, const vec3& b) {
+inline vec3 operator-(const vec3& a, const vec3& b)
+{
vec3 result;
- for (int i = 0; i < 3; i++) {
+ for (int i = 0; i < 3; i++)
+ {
result.m_data[i] = a.m_data[i] - b.m_data[i];
}
return result;
}
-inline mat33 operator/(const mat33& a, const idScalar& s) {
+inline mat33 operator/(const mat33& a, const idScalar& s)
+{
mat33 result;
- for (int i = 0; i < 9; i++) {
+ for (int i = 0; i < 9; i++)
+ {
result.m_data[i] = a.m_data[i] / s;
}
return result;
}
-inline vec3 operator/(const vec3& a, const idScalar& s) {
+inline vec3 operator/(const vec3& a, const idScalar& s)
+{
vec3 result;
- for (int i = 0; i < 3; i++) {
+ for (int i = 0; i < 3; i++)
+ {
result.m_data[i] = a.m_data[i] / s;
}
return result;
}
-inline const vecx& vecx::operator=(const vecx& rhs) {
- if (size() != rhs.size()) {
+inline const vecx& vecx::operator=(const vecx& rhs)
+{
+ if (size() != rhs.size())
+ {
bt_id_error_message("size missmatch, size()= %d but rhs.size()= %d\n", size(), rhs.size());
abort();
}
- if (&rhs != this) {
+ if (&rhs != this)
+ {
memcpy(m_data, rhs.m_data, rhs.size() * sizeof(idScalar));
}
return *this;
}
-inline vecx operator*(const vecx& a, const idScalar& s) {
+inline vecx operator*(const vecx& a, const idScalar& s)
+{
vecx result(a.size());
- for (int i = 0; i < result.size(); i++) {
+ for (int i = 0; i < result.size(); i++)
+ {
result.m_data[i] = a.m_data[i] * s;
}
return result;
}
inline vecx operator*(const idScalar& s, const vecx& a) { return a * s; }
-inline vecx operator+(const vecx& a, const vecx& b) {
+inline vecx operator+(const vecx& a, const vecx& b)
+{
vecx result(a.size());
// TODO: error handling for a.size() != b.size()??
- if (a.size() != b.size()) {
+ if (a.size() != b.size())
+ {
bt_id_error_message("size missmatch. a.size()= %d, b.size()= %d\n", a.size(), b.size());
abort();
}
- for (int i = 0; i < a.size(); i++) {
+ for (int i = 0; i < a.size(); i++)
+ {
result.m_data[i] = a.m_data[i] + b.m_data[i];
}
return result;
}
-inline vecx operator-(const vecx& a, const vecx& b) {
+inline vecx operator-(const vecx& a, const vecx& b)
+{
vecx result(a.size());
// TODO: error handling for a.size() != b.size()??
- if (a.size() != b.size()) {
+ if (a.size() != b.size())
+ {
bt_id_error_message("size missmatch. a.size()= %d, b.size()= %d\n", a.size(), b.size());
abort();
}
- for (int i = 0; i < a.size(); i++) {
+ for (int i = 0; i < a.size(); i++)
+ {
result.m_data[i] = a.m_data[i] - b.m_data[i];
}
return result;
}
-inline vecx operator/(const vecx& a, const idScalar& s) {
+inline vecx operator/(const vecx& a, const idScalar& s)
+{
vecx result(a.size());
- for (int i = 0; i < result.size(); i++) {
+ for (int i = 0; i < result.size(); i++)
+ {
result.m_data[i] = a.m_data[i] / s;
}
return result;
}
-inline vec3 operator*(const mat3x& a, const vecx& b) {
- vec3 result;
- if (a.cols() != b.size()) {
- bt_id_error_message("size missmatch. a.cols()= %d, b.size()= %d\n", a.cols(), b.size());
- abort();
- }
- result(0)=0.0;
- result(1)=0.0;
- result(2)=0.0;
- for(int i=0;i<b.size();i++) {
- for(int k=0;k<3;k++) {
- result(k)+=a(k,i)*b(i);
- }
- }
- return result;
+inline vec3 operator*(const mat3x& a, const vecx& b)
+{
+ vec3 result;
+ if (a.cols() != b.size())
+ {
+ bt_id_error_message("size missmatch. a.cols()= %d, b.size()= %d\n", a.cols(), b.size());
+ abort();
+ }
+ result(0) = 0.0;
+ result(1) = 0.0;
+ result(2) = 0.0;
+ for (int i = 0; i < b.size(); i++)
+ {
+ for (int k = 0; k < 3; k++)
+ {
+ result(k) += a(k, i) * b(i);
+ }
+ }
+ return result;
}
-inline void setMatxxElem(const idArrayIdx row, const idArrayIdx col, const idScalar val, matxx*m){
- (*m)(row, col) = val;
+inline void setMatxxElem(const idArrayIdx row, const idArrayIdx col, const idScalar val, matxx* m)
+{
+ (*m)(row, col) = val;
}
-inline void setMat3xElem(const idArrayIdx row, const idArrayIdx col, const idScalar val, mat3x*m){
- (*m)(row, col) = val;
+inline void setMat3xElem(const idArrayIdx row, const idArrayIdx col, const idScalar val, mat3x* m)
+{
+ (*m)(row, col) = val;
}
-} // namespace btInverseDynamcis
+} // namespace btInverseDynamics
#endif
diff --git a/thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeImpl.cpp b/thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeImpl.cpp
index e8563238c3..befbc2e2a4 100644
--- a/thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeImpl.cpp
+++ b/thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeImpl.cpp
@@ -1,16 +1,16 @@
#include "MultiBodyTreeImpl.hpp"
-namespace btInverseDynamics {
-
+namespace btInverseDynamics
+{
MultiBodyTree::MultiBodyImpl::MultiBodyImpl(int num_bodies_, int num_dofs_)
: m_num_bodies(num_bodies_), m_num_dofs(num_dofs_)
#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
- ,m_m3x(3,m_num_dofs)
+ ,
+ m_m3x(3, m_num_dofs)
#endif
{
-
#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
- resize(m_m3x,m_num_dofs);
+ resize(m_m3x, m_num_dofs);
#endif
m_body_list.resize(num_bodies_);
m_parent_index.resize(num_bodies_);
@@ -23,8 +23,10 @@ MultiBodyTree::MultiBodyImpl::MultiBodyImpl(int num_bodies_, int num_dofs_)
m_world_gravity(2) = -9.8;
}
-const char *MultiBodyTree::MultiBodyImpl::jointTypeToString(const JointType &type) const {
- switch (type) {
+const char *MultiBodyTree::MultiBodyImpl::jointTypeToString(const JointType &type) const
+{
+ switch (type)
+ {
case FIXED:
return "fixed";
case REVOLUTE:
@@ -33,22 +35,28 @@ const char *MultiBodyTree::MultiBodyImpl::jointTypeToString(const JointType &typ
return "prismatic";
case FLOATING:
return "floating";
+ case SPHERICAL:
+ return "spherical";
}
return "error: invalid";
}
-inline void indent(const int &level) {
+inline void indent(const int &level)
+{
for (int j = 0; j < level; j++)
id_printf(" "); // indent
}
-void MultiBodyTree::MultiBodyImpl::printTree() {
+void MultiBodyTree::MultiBodyImpl::printTree()
+{
id_printf("body %.2d[%s]: root\n", 0, jointTypeToString(m_body_list[0].m_joint_type));
printTree(0, 0);
}
-void MultiBodyTree::MultiBodyImpl::printTreeData() {
- for (idArrayIdx i = 0; i < m_body_list.size(); i++) {
+void MultiBodyTree::MultiBodyImpl::printTreeData()
+{
+ for (idArrayIdx i = 0; i < m_body_list.size(); i++)
+ {
RigidBody &body = m_body_list[i];
id_printf("body: %d\n", static_cast<int>(i));
id_printf("type: %s\n", jointTypeToString(body.m_joint_type));
@@ -59,19 +67,22 @@ void MultiBodyTree::MultiBodyImpl::printTreeData() {
id_printf("mass = %f\n", body.m_mass);
id_printf("mass * com = [%f %f %f]\n", body.m_body_mass_com(0), body.m_body_mass_com(1),
body.m_body_mass_com(2));
- id_printf("I_o= [%f %f %f;\n"
- " %f %f %f;\n"
- " %f %f %f]\n",
- body.m_body_I_body(0, 0), body.m_body_I_body(0, 1), body.m_body_I_body(0, 2),
- body.m_body_I_body(1, 0), body.m_body_I_body(1, 1), body.m_body_I_body(1, 2),
- body.m_body_I_body(2, 0), body.m_body_I_body(2, 1), body.m_body_I_body(2, 2));
+ id_printf(
+ "I_o= [%f %f %f;\n"
+ " %f %f %f;\n"
+ " %f %f %f]\n",
+ body.m_body_I_body(0, 0), body.m_body_I_body(0, 1), body.m_body_I_body(0, 2),
+ body.m_body_I_body(1, 0), body.m_body_I_body(1, 1), body.m_body_I_body(1, 2),
+ body.m_body_I_body(2, 0), body.m_body_I_body(2, 1), body.m_body_I_body(2, 2));
id_printf("parent_pos_parent_body_ref= [%f %f %f]\n", body.m_parent_pos_parent_body_ref(0),
body.m_parent_pos_parent_body_ref(1), body.m_parent_pos_parent_body_ref(2));
}
}
-int MultiBodyTree::MultiBodyImpl::bodyNumDoFs(const JointType &type) const {
- switch (type) {
+int MultiBodyTree::MultiBodyImpl::bodyNumDoFs(const JointType &type) const
+{
+ switch (type)
+ {
case FIXED:
return 0;
case REVOLUTE:
@@ -79,12 +90,15 @@ int MultiBodyTree::MultiBodyImpl::bodyNumDoFs(const JointType &type) const {
return 1;
case FLOATING:
return 6;
+ case SPHERICAL:
+ return 3;
}
bt_id_error_message("unknown joint type %d\n", type);
return 0;
}
-void MultiBodyTree::MultiBodyImpl::printTree(int index, int indentation) {
+void MultiBodyTree::MultiBodyImpl::printTree(int index, int indentation)
+{
// this is adapted from URDF2Bullet.
// TODO: fix this and print proper graph (similar to git --log --graph)
int num_children = m_child_indices[index].size();
@@ -92,7 +106,8 @@ void MultiBodyTree::MultiBodyImpl::printTree(int index, int indentation) {
indentation += 2;
int count = 0;
- for (int i = 0; i < num_children; i++) {
+ for (int i = 0; i < num_children; i++)
+ {
int child_index = m_child_indices[index][i];
indent(indentation);
id_printf("body %.2d[%s]: %.2d is child no. %d (qi= %d .. %d) \n", index,
@@ -104,19 +119,23 @@ void MultiBodyTree::MultiBodyImpl::printTree(int index, int indentation) {
}
}
-int MultiBodyTree::MultiBodyImpl::setGravityInWorldFrame(const vec3 &gravity) {
+int MultiBodyTree::MultiBodyImpl::setGravityInWorldFrame(const vec3 &gravity)
+{
m_world_gravity = gravity;
return 0;
}
-int MultiBodyTree::MultiBodyImpl::generateIndexSets() {
+int MultiBodyTree::MultiBodyImpl::generateIndexSets()
+{
m_body_revolute_list.resize(0);
m_body_prismatic_list.resize(0);
int q_index = 0;
- for (idArrayIdx i = 0; i < m_body_list.size(); i++) {
+ for (idArrayIdx i = 0; i < m_body_list.size(); i++)
+ {
RigidBody &body = m_body_list[i];
body.m_q_index = -1;
- switch (body.m_joint_type) {
+ switch (body.m_joint_type)
+ {
case REVOLUTE:
m_body_revolute_list.push_back(i);
body.m_q_index = q_index;
@@ -135,28 +154,41 @@ int MultiBodyTree::MultiBodyImpl::generateIndexSets() {
body.m_q_index = q_index;
q_index += 6;
break;
+ case SPHERICAL:
+ m_body_spherical_list.push_back(i);
+ body.m_q_index = q_index;
+ q_index += 3;
+ break;
default:
bt_id_error_message("unsupported joint type %d\n", body.m_joint_type);
return -1;
}
}
// sanity check
- if (q_index != m_num_dofs) {
+ if (q_index != m_num_dofs)
+ {
bt_id_error_message("internal error, q_index= %d but num_dofs %d\n", q_index, m_num_dofs);
return -1;
}
m_child_indices.resize(m_body_list.size());
- for (idArrayIdx child = 1; child < m_parent_index.size(); child++) {
+ for (idArrayIdx child = 1; child < m_parent_index.size(); child++)
+ {
const int &parent = m_parent_index[child];
- if (parent >= 0 && parent < (static_cast<int>(m_parent_index.size()) - 1)) {
+ if (parent >= 0 && parent < (static_cast<int>(m_parent_index.size()) - 1))
+ {
m_child_indices[parent].push_back(child);
- } else {
- if (-1 == parent) {
+ }
+ else
+ {
+ if (-1 == parent)
+ {
// multiple bodies are directly linked to the environment, ie, not a single root
bt_id_error_message("building index sets parent(%zu)= -1 (multiple roots)\n", child);
- } else {
+ }
+ else
+ {
// should never happen
bt_id_error_message(
"building index sets. parent_index[%zu]= %d, but m_parent_index.size()= %d\n",
@@ -169,11 +201,14 @@ int MultiBodyTree::MultiBodyImpl::generateIndexSets() {
return 0;
}
-void MultiBodyTree::MultiBodyImpl::calculateStaticData() {
+void MultiBodyTree::MultiBodyImpl::calculateStaticData()
+{
// relative kinematics that are not a function of q, u, dot_u
- for (idArrayIdx i = 0; i < m_body_list.size(); i++) {
+ for (idArrayIdx i = 0; i < m_body_list.size(); i++)
+ {
RigidBody &body = m_body_list[i];
- switch (body.m_joint_type) {
+ switch (body.m_joint_type)
+ {
case REVOLUTE:
body.m_parent_vel_rel(0) = 0;
body.m_parent_vel_rel(1) = 0;
@@ -212,41 +247,56 @@ void MultiBodyTree::MultiBodyImpl::calculateStaticData() {
case FLOATING:
// no static data
break;
+ case SPHERICAL:
+ //todo: review
+ body.m_parent_pos_parent_body = body.m_parent_pos_parent_body_ref;
+ body.m_parent_vel_rel(0) = 0;
+ body.m_parent_vel_rel(1) = 0;
+ body.m_parent_vel_rel(2) = 0;
+ body.m_parent_acc_rel(0) = 0;
+ body.m_parent_acc_rel(1) = 0;
+ body.m_parent_acc_rel(2) = 0;
+ break;
}
- // resize & initialize jacobians to zero.
+ // resize & initialize jacobians to zero.
#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
- body.m_body_dot_Jac_T_u(0) = 0.0;
- body.m_body_dot_Jac_T_u(1) = 0.0;
- body.m_body_dot_Jac_T_u(2) = 0.0;
- body.m_body_dot_Jac_R_u(0) = 0.0;
- body.m_body_dot_Jac_R_u(1) = 0.0;
- body.m_body_dot_Jac_R_u(2) = 0.0;
- resize(body.m_body_Jac_T,m_num_dofs);
- resize(body.m_body_Jac_R,m_num_dofs);
- body.m_body_Jac_T.setZero();
- body.m_body_Jac_R.setZero();
-#endif //
+ body.m_body_dot_Jac_T_u(0) = 0.0;
+ body.m_body_dot_Jac_T_u(1) = 0.0;
+ body.m_body_dot_Jac_T_u(2) = 0.0;
+ body.m_body_dot_Jac_R_u(0) = 0.0;
+ body.m_body_dot_Jac_R_u(1) = 0.0;
+ body.m_body_dot_Jac_R_u(2) = 0.0;
+ resize(body.m_body_Jac_T, m_num_dofs);
+ resize(body.m_body_Jac_R, m_num_dofs);
+ body.m_body_Jac_T.setZero();
+ body.m_body_Jac_R.setZero();
+#endif //
}
}
int MultiBodyTree::MultiBodyImpl::calculateInverseDynamics(const vecx &q, const vecx &u,
- const vecx &dot_u, vecx *joint_forces) {
+ const vecx &dot_u, vecx *joint_forces)
+{
if (q.size() != m_num_dofs || u.size() != m_num_dofs || dot_u.size() != m_num_dofs ||
- joint_forces->size() != m_num_dofs) {
- bt_id_error_message("wrong vector dimension. system has %d DOFs,\n"
- "but dim(q)= %d, dim(u)= %d, dim(dot_u)= %d, dim(joint_forces)= %d\n",
- m_num_dofs, static_cast<int>(q.size()), static_cast<int>(u.size()),
- static_cast<int>(dot_u.size()), static_cast<int>(joint_forces->size()));
+ joint_forces->size() != m_num_dofs)
+ {
+ bt_id_error_message(
+ "wrong vector dimension. system has %d DOFs,\n"
+ "but dim(q)= %d, dim(u)= %d, dim(dot_u)= %d, dim(joint_forces)= %d\n",
+ m_num_dofs, static_cast<int>(q.size()), static_cast<int>(u.size()),
+ static_cast<int>(dot_u.size()), static_cast<int>(joint_forces->size()));
return -1;
}
// 1. relative kinematics
- if(-1 == calculateKinematics(q,u,dot_u, POSITION_VELOCITY_ACCELERATION)) {
- bt_id_error_message("error in calculateKinematics\n");
- return -1;
- }
- // 2. update contributions to equations of motion for every body.
- for (idArrayIdx i = 0; i < m_body_list.size(); i++) {
+ if (-1 == calculateKinematics(q, u, dot_u, POSITION_VELOCITY_ACCELERATION))
+ {
+ bt_id_error_message("error in calculateKinematics\n");
+ return -1;
+ }
+ // 2. update contributions to equations of motion for every body.
+ for (idArrayIdx i = 0; i < m_body_list.size(); i++)
+ {
RigidBody &body = m_body_list[i];
// 3.4 update dynamic terms (rate of change of angular & linear momentum)
body.m_eom_lhs_rotational =
@@ -268,14 +318,16 @@ int MultiBodyTree::MultiBodyImpl::calculateInverseDynamics(const vecx &q, const
// Also, this enables adding zero weight bodies as a way to calculate frame poses
// for force elements, etc.
- for (int body_idx = m_body_list.size() - 1; body_idx >= 0; body_idx--) {
+ for (int body_idx = m_body_list.size() - 1; body_idx >= 0; body_idx--)
+ {
// sum of forces and moments acting on this body from its children
vec3 sum_f_children;
vec3 sum_m_children;
setZero(sum_f_children);
setZero(sum_m_children);
for (idArrayIdx child_list_idx = 0; child_list_idx < m_child_indices[body_idx].size();
- child_list_idx++) {
+ child_list_idx++)
+ {
const RigidBody &child = m_body_list[m_child_indices[body_idx][child_list_idx]];
vec3 child_joint_force_in_this_frame =
child.m_body_T_parent.transpose() * child.m_force_at_joint;
@@ -293,19 +345,22 @@ int MultiBodyTree::MultiBodyImpl::calculateInverseDynamics(const vecx &q, const
// These are the components of force_at_joint/moment_at_joint
// in the free directions given by Jac_JT/Jac_JR
// 4.1 revolute joints
- for (idArrayIdx i = 0; i < m_body_revolute_list.size(); i++) {
+ for (idArrayIdx i = 0; i < m_body_revolute_list.size(); i++)
+ {
RigidBody &body = m_body_list[m_body_revolute_list[i]];
// (*joint_forces)(body.m_q_index) = body.m_Jac_JR.transpose() * body.m_moment_at_joint;
(*joint_forces)(body.m_q_index) = body.m_Jac_JR.dot(body.m_moment_at_joint);
}
// 4.2 for prismatic joints
- for (idArrayIdx i = 0; i < m_body_prismatic_list.size(); i++) {
+ for (idArrayIdx i = 0; i < m_body_prismatic_list.size(); i++)
+ {
RigidBody &body = m_body_list[m_body_prismatic_list[i]];
// (*joint_forces)(body.m_q_index) = body.m_Jac_JT.transpose() * body.m_force_at_joint;
(*joint_forces)(body.m_q_index) = body.m_Jac_JT.dot(body.m_force_at_joint);
}
// 4.3 floating bodies (6-DoF joints)
- for (idArrayIdx i = 0; i < m_body_floating_list.size(); i++) {
+ for (idArrayIdx i = 0; i < m_body_floating_list.size(); i++)
+ {
RigidBody &body = m_body_list[m_body_floating_list[i]];
(*joint_forces)(body.m_q_index + 0) = body.m_moment_at_joint(0);
(*joint_forces)(body.m_q_index + 1) = body.m_moment_at_joint(1);
@@ -316,84 +371,133 @@ int MultiBodyTree::MultiBodyImpl::calculateInverseDynamics(const vecx &q, const
(*joint_forces)(body.m_q_index + 5) = body.m_force_at_joint(2);
}
+ // 4.4 spherical bodies (3-DoF joints)
+ for (idArrayIdx i = 0; i < m_body_spherical_list.size(); i++)
+ {
+ //todo: review
+ RigidBody &body = m_body_list[m_body_spherical_list[i]];
+ (*joint_forces)(body.m_q_index + 0) = body.m_moment_at_joint(0);
+ (*joint_forces)(body.m_q_index + 1) = body.m_moment_at_joint(1);
+ (*joint_forces)(body.m_q_index + 2) = body.m_moment_at_joint(2);
+ }
return 0;
}
-int MultiBodyTree::MultiBodyImpl::calculateKinematics(const vecx &q, const vecx &u, const vecx& dot_u,
- const KinUpdateType type) {
- if (q.size() != m_num_dofs || u.size() != m_num_dofs || dot_u.size() != m_num_dofs ) {
- bt_id_error_message("wrong vector dimension. system has %d DOFs,\n"
- "but dim(q)= %d, dim(u)= %d, dim(dot_u)= %d\n",
- m_num_dofs, static_cast<int>(q.size()), static_cast<int>(u.size()),
- static_cast<int>(dot_u.size()));
+int MultiBodyTree::MultiBodyImpl::calculateKinematics(const vecx &q, const vecx &u, const vecx &dot_u,
+ const KinUpdateType type)
+{
+ if (q.size() != m_num_dofs || u.size() != m_num_dofs || dot_u.size() != m_num_dofs)
+ {
+ bt_id_error_message(
+ "wrong vector dimension. system has %d DOFs,\n"
+ "but dim(q)= %d, dim(u)= %d, dim(dot_u)= %d\n",
+ m_num_dofs, static_cast<int>(q.size()), static_cast<int>(u.size()),
+ static_cast<int>(dot_u.size()));
+ return -1;
+ }
+ if (type != POSITION_ONLY && type != POSITION_VELOCITY && type != POSITION_VELOCITY_ACCELERATION)
+ {
+ bt_id_error_message("invalid type %d\n", type);
return -1;
}
- if(type != POSITION_ONLY && type != POSITION_VELOCITY && type != POSITION_VELOCITY_ACCELERATION) {
- bt_id_error_message("invalid type %d\n", type);
- return -1;
- }
// 1. update relative kinematics
// 1.1 for revolute
- for (idArrayIdx i = 0; i < m_body_revolute_list.size(); i++) {
+ for (idArrayIdx i = 0; i < m_body_revolute_list.size(); i++)
+ {
RigidBody &body = m_body_list[m_body_revolute_list[i]];
mat33 T;
bodyTParentFromAxisAngle(body.m_Jac_JR, q(body.m_q_index), &T);
body.m_body_T_parent = T * body.m_body_T_parent_ref;
- if(type >= POSITION_VELOCITY) {
- body.m_body_ang_vel_rel = body.m_Jac_JR * u(body.m_q_index);
- }
- if(type >= POSITION_VELOCITY_ACCELERATION) {
- body.m_body_ang_acc_rel = body.m_Jac_JR * dot_u(body.m_q_index);
- }
+ if (type >= POSITION_VELOCITY)
+ {
+ body.m_body_ang_vel_rel = body.m_Jac_JR * u(body.m_q_index);
+ }
+ if (type >= POSITION_VELOCITY_ACCELERATION)
+ {
+ body.m_body_ang_acc_rel = body.m_Jac_JR * dot_u(body.m_q_index);
+ }
}
// 1.2 for prismatic
- for (idArrayIdx i = 0; i < m_body_prismatic_list.size(); i++) {
+ for (idArrayIdx i = 0; i < m_body_prismatic_list.size(); i++)
+ {
RigidBody &body = m_body_list[m_body_prismatic_list[i]];
body.m_parent_pos_parent_body =
body.m_parent_pos_parent_body_ref + body.m_parent_Jac_JT * q(body.m_q_index);
- if(type >= POSITION_VELOCITY) {
- body.m_parent_vel_rel =
- body.m_body_T_parent_ref.transpose() * body.m_Jac_JT * u(body.m_q_index);
- }
- if(type >= POSITION_VELOCITY_ACCELERATION) {
- body.m_parent_acc_rel = body.m_parent_Jac_JT * dot_u(body.m_q_index);
- }
+ if (type >= POSITION_VELOCITY)
+ {
+ body.m_parent_vel_rel =
+ body.m_body_T_parent_ref.transpose() * body.m_Jac_JT * u(body.m_q_index);
+ }
+ if (type >= POSITION_VELOCITY_ACCELERATION)
+ {
+ body.m_parent_acc_rel = body.m_parent_Jac_JT * dot_u(body.m_q_index);
+ }
}
// 1.3 fixed joints: nothing to do
// 1.4 6dof joints:
- for (idArrayIdx i = 0; i < m_body_floating_list.size(); i++) {
+ for (idArrayIdx i = 0; i < m_body_floating_list.size(); i++)
+ {
RigidBody &body = m_body_list[m_body_floating_list[i]];
body.m_body_T_parent = transformZ(q(body.m_q_index + 2)) *
- transformY(q(body.m_q_index + 1)) * transformX(q(body.m_q_index));
+ transformY(q(body.m_q_index + 1)) *
+ transformX(q(body.m_q_index));
body.m_parent_pos_parent_body(0) = q(body.m_q_index + 3);
body.m_parent_pos_parent_body(1) = q(body.m_q_index + 4);
body.m_parent_pos_parent_body(2) = q(body.m_q_index + 5);
body.m_parent_pos_parent_body = body.m_body_T_parent * body.m_parent_pos_parent_body;
- if(type >= POSITION_VELOCITY) {
- body.m_body_ang_vel_rel(0) = u(body.m_q_index + 0);
- body.m_body_ang_vel_rel(1) = u(body.m_q_index + 1);
- body.m_body_ang_vel_rel(2) = u(body.m_q_index + 2);
+ if (type >= POSITION_VELOCITY)
+ {
+ body.m_body_ang_vel_rel(0) = u(body.m_q_index + 0);
+ body.m_body_ang_vel_rel(1) = u(body.m_q_index + 1);
+ body.m_body_ang_vel_rel(2) = u(body.m_q_index + 2);
- body.m_parent_vel_rel(0) = u(body.m_q_index + 3);
- body.m_parent_vel_rel(1) = u(body.m_q_index + 4);
- body.m_parent_vel_rel(2) = u(body.m_q_index + 5);
+ body.m_parent_vel_rel(0) = u(body.m_q_index + 3);
+ body.m_parent_vel_rel(1) = u(body.m_q_index + 4);
+ body.m_parent_vel_rel(2) = u(body.m_q_index + 5);
- body.m_parent_vel_rel = body.m_body_T_parent.transpose() * body.m_parent_vel_rel;
- }
- if(type >= POSITION_VELOCITY_ACCELERATION) {
- body.m_body_ang_acc_rel(0) = dot_u(body.m_q_index + 0);
- body.m_body_ang_acc_rel(1) = dot_u(body.m_q_index + 1);
- body.m_body_ang_acc_rel(2) = dot_u(body.m_q_index + 2);
+ body.m_parent_vel_rel = body.m_body_T_parent.transpose() * body.m_parent_vel_rel;
+ }
+ if (type >= POSITION_VELOCITY_ACCELERATION)
+ {
+ body.m_body_ang_acc_rel(0) = dot_u(body.m_q_index + 0);
+ body.m_body_ang_acc_rel(1) = dot_u(body.m_q_index + 1);
+ body.m_body_ang_acc_rel(2) = dot_u(body.m_q_index + 2);
- body.m_parent_acc_rel(0) = dot_u(body.m_q_index + 3);
- body.m_parent_acc_rel(1) = dot_u(body.m_q_index + 4);
- body.m_parent_acc_rel(2) = dot_u(body.m_q_index + 5);
+ body.m_parent_acc_rel(0) = dot_u(body.m_q_index + 3);
+ body.m_parent_acc_rel(1) = dot_u(body.m_q_index + 4);
+ body.m_parent_acc_rel(2) = dot_u(body.m_q_index + 5);
- body.m_parent_acc_rel = body.m_body_T_parent.transpose() * body.m_parent_acc_rel;
- }
+ body.m_parent_acc_rel = body.m_body_T_parent.transpose() * body.m_parent_acc_rel;
+ }
+ }
+
+ for (idArrayIdx i = 0; i < m_body_spherical_list.size(); i++)
+ {
+ //todo: review
+ RigidBody &body = m_body_list[m_body_spherical_list[i]];
+
+ body.m_body_T_parent = transformZ(q(body.m_q_index + 2)) *
+ transformY(q(body.m_q_index + 1)) *
+ transformX(q(body.m_q_index));
+ body.m_parent_pos_parent_body = body.m_body_T_parent * body.m_parent_pos_parent_body;
+
+ if (type >= POSITION_VELOCITY)
+ {
+ body.m_body_ang_vel_rel(0) = u(body.m_q_index + 0);
+ body.m_body_ang_vel_rel(1) = u(body.m_q_index + 1);
+ body.m_body_ang_vel_rel(2) = u(body.m_q_index + 2);
+ body.m_parent_vel_rel = body.m_body_T_parent.transpose() * body.m_parent_vel_rel;
+ }
+ if (type >= POSITION_VELOCITY_ACCELERATION)
+ {
+ body.m_body_ang_acc_rel(0) = dot_u(body.m_q_index + 0);
+ body.m_body_ang_acc_rel(1) = dot_u(body.m_q_index + 1);
+ body.m_body_ang_acc_rel(2) = dot_u(body.m_q_index + 2);
+ body.m_parent_acc_rel = body.m_body_T_parent.transpose() * body.m_parent_acc_rel;
+ }
}
// 2. absolute kinematic quantities (vector valued)
@@ -410,26 +514,29 @@ int MultiBodyTree::MultiBodyImpl::calculateKinematics(const vecx &q, const vecx
body.m_body_pos = body.m_body_T_parent * body.m_parent_pos_parent_body;
body.m_body_T_world = body.m_body_T_parent;
- if(type >= POSITION_VELOCITY) {
- // 3.2 update absolute velocities
- body.m_body_ang_vel = body.m_body_ang_vel_rel;
- body.m_body_vel = body.m_parent_vel_rel;
- }
- if(type >= POSITION_VELOCITY_ACCELERATION) {
- // 3.3 update absolute accelerations
- // NOTE: assumption: dot(J_JR) = 0; true here, but not for general joints
- body.m_body_ang_acc = body.m_body_ang_acc_rel;
- body.m_body_acc = body.m_body_T_parent * body.m_parent_acc_rel;
- // add gravitational acceleration to root body
- // this is an efficient way to add gravitational terms,
- // but it does mean that the kinematics are no longer
- // correct at the acceleration level
- // NOTE: To get correct acceleration kinematics, just set world_gravity to zero
- body.m_body_acc = body.m_body_acc - body.m_body_T_parent * m_world_gravity;
- }
+ if (type >= POSITION_VELOCITY)
+ {
+ // 3.2 update absolute velocities
+ body.m_body_ang_vel = body.m_body_ang_vel_rel;
+ body.m_body_vel = body.m_parent_vel_rel;
+ }
+ if (type >= POSITION_VELOCITY_ACCELERATION)
+ {
+ // 3.3 update absolute accelerations
+ // NOTE: assumption: dot(J_JR) = 0; true here, but not for general joints
+ body.m_body_ang_acc = body.m_body_ang_acc_rel;
+ body.m_body_acc = body.m_body_T_parent * body.m_parent_acc_rel;
+ // add gravitational acceleration to root body
+ // this is an efficient way to add gravitational terms,
+ // but it does mean that the kinematics are no longer
+ // correct at the acceleration level
+ // NOTE: To get correct acceleration kinematics, just set world_gravity to zero
+ body.m_body_acc = body.m_body_acc - body.m_body_T_parent * m_world_gravity;
+ }
}
- for (idArrayIdx i = 1; i < m_body_list.size(); i++) {
+ for (idArrayIdx i = 1; i < m_body_list.size(); i++)
+ {
RigidBody &body = m_body_list[i];
RigidBody &parent = m_body_list[m_parent_index[i]];
// 2.1 update absolute positions and orientations:
@@ -439,121 +546,159 @@ int MultiBodyTree::MultiBodyImpl::calculateKinematics(const vecx &q, const vecx
body.m_body_T_parent * (parent.m_body_pos + body.m_parent_pos_parent_body);
body.m_body_T_world = body.m_body_T_parent * parent.m_body_T_world;
- if(type >= POSITION_VELOCITY) {
- // 2.2 update absolute velocities
- body.m_body_ang_vel =
- body.m_body_T_parent * parent.m_body_ang_vel + body.m_body_ang_vel_rel;
-
- body.m_body_vel =
- body.m_body_T_parent *
- (parent.m_body_vel + parent.m_body_ang_vel.cross(body.m_parent_pos_parent_body) +
- body.m_parent_vel_rel);
- }
- if(type >= POSITION_VELOCITY_ACCELERATION) {
- // 2.3 update absolute accelerations
- // NOTE: assumption: dot(J_JR) = 0; true here, but not for general joints
- body.m_body_ang_acc =
- body.m_body_T_parent * parent.m_body_ang_acc -
- body.m_body_ang_vel_rel.cross(body.m_body_T_parent * parent.m_body_ang_vel) +
- body.m_body_ang_acc_rel;
- body.m_body_acc =
- body.m_body_T_parent *
- (parent.m_body_acc + parent.m_body_ang_acc.cross(body.m_parent_pos_parent_body) +
- parent.m_body_ang_vel.cross(parent.m_body_ang_vel.cross(body.m_parent_pos_parent_body)) +
- 2.0 * parent.m_body_ang_vel.cross(body.m_parent_vel_rel) + body.m_parent_acc_rel);
- }
+ if (type >= POSITION_VELOCITY)
+ {
+ // 2.2 update absolute velocities
+ body.m_body_ang_vel =
+ body.m_body_T_parent * parent.m_body_ang_vel + body.m_body_ang_vel_rel;
+
+ body.m_body_vel =
+ body.m_body_T_parent *
+ (parent.m_body_vel + parent.m_body_ang_vel.cross(body.m_parent_pos_parent_body) +
+ body.m_parent_vel_rel);
+ }
+ if (type >= POSITION_VELOCITY_ACCELERATION)
+ {
+ // 2.3 update absolute accelerations
+ // NOTE: assumption: dot(J_JR) = 0; true here, but not for general joints
+ body.m_body_ang_acc =
+ body.m_body_T_parent * parent.m_body_ang_acc -
+ body.m_body_ang_vel_rel.cross(body.m_body_T_parent * parent.m_body_ang_vel) +
+ body.m_body_ang_acc_rel;
+ body.m_body_acc =
+ body.m_body_T_parent *
+ (parent.m_body_acc + parent.m_body_ang_acc.cross(body.m_parent_pos_parent_body) +
+ parent.m_body_ang_vel.cross(parent.m_body_ang_vel.cross(body.m_parent_pos_parent_body)) +
+ 2.0 * parent.m_body_ang_vel.cross(body.m_parent_vel_rel) + body.m_parent_acc_rel);
+ }
}
- return 0;
+ return 0;
}
#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
-void MultiBodyTree::MultiBodyImpl::addRelativeJacobianComponent(RigidBody&body) {
- const int& idx=body.m_q_index;
- switch(body.m_joint_type) {
- case FIXED:
- break;
- case REVOLUTE:
- setMat3xElem(0,idx, body.m_Jac_JR(0), &body.m_body_Jac_R);
- setMat3xElem(1,idx, body.m_Jac_JR(1), &body.m_body_Jac_R);
- setMat3xElem(2,idx, body.m_Jac_JR(2), &body.m_body_Jac_R);
- break;
- case PRISMATIC:
- setMat3xElem(0,idx, body.m_body_T_parent_ref(0,0)*body.m_Jac_JT(0)
- +body.m_body_T_parent_ref(1,0)*body.m_Jac_JT(1)
- +body.m_body_T_parent_ref(2,0)*body.m_Jac_JT(2),
- &body.m_body_Jac_T);
- setMat3xElem(1,idx,body.m_body_T_parent_ref(0,1)*body.m_Jac_JT(0)
- +body.m_body_T_parent_ref(1,1)*body.m_Jac_JT(1)
- +body.m_body_T_parent_ref(2,1)*body.m_Jac_JT(2),
- &body.m_body_Jac_T);
- setMat3xElem(2,idx, body.m_body_T_parent_ref(0,2)*body.m_Jac_JT(0)
- +body.m_body_T_parent_ref(1,2)*body.m_Jac_JT(1)
- +body.m_body_T_parent_ref(2,2)*body.m_Jac_JT(2),
- &body.m_body_Jac_T);
- break;
- case FLOATING:
- setMat3xElem(0,idx+0, 1.0, &body.m_body_Jac_R);
- setMat3xElem(1,idx+1, 1.0, &body.m_body_Jac_R);
- setMat3xElem(2,idx+2, 1.0, &body.m_body_Jac_R);
- // body_Jac_T = body_T_parent.transpose();
- setMat3xElem(0,idx+3, body.m_body_T_parent(0,0), &body.m_body_Jac_T);
- setMat3xElem(0,idx+4, body.m_body_T_parent(1,0), &body.m_body_Jac_T);
- setMat3xElem(0,idx+5, body.m_body_T_parent(2,0), &body.m_body_Jac_T);
-
- setMat3xElem(1,idx+3, body.m_body_T_parent(0,1), &body.m_body_Jac_T);
- setMat3xElem(1,idx+4, body.m_body_T_parent(1,1), &body.m_body_Jac_T);
- setMat3xElem(1,idx+5, body.m_body_T_parent(2,1), &body.m_body_Jac_T);
-
- setMat3xElem(2,idx+3, body.m_body_T_parent(0,2), &body.m_body_Jac_T);
- setMat3xElem(2,idx+4, body.m_body_T_parent(1,2), &body.m_body_Jac_T);
- setMat3xElem(2,idx+5, body.m_body_T_parent(2,2), &body.m_body_Jac_T);
-
- break;
- }
+void MultiBodyTree::MultiBodyImpl::addRelativeJacobianComponent(RigidBody &body)
+{
+ const int &idx = body.m_q_index;
+ switch (body.m_joint_type)
+ {
+ case FIXED:
+ break;
+ case REVOLUTE:
+ setMat3xElem(0, idx, body.m_Jac_JR(0), &body.m_body_Jac_R);
+ setMat3xElem(1, idx, body.m_Jac_JR(1), &body.m_body_Jac_R);
+ setMat3xElem(2, idx, body.m_Jac_JR(2), &body.m_body_Jac_R);
+ break;
+ case PRISMATIC:
+ setMat3xElem(0, idx, body.m_body_T_parent_ref(0, 0) * body.m_Jac_JT(0) + body.m_body_T_parent_ref(1, 0) * body.m_Jac_JT(1) + body.m_body_T_parent_ref(2, 0) * body.m_Jac_JT(2),
+ &body.m_body_Jac_T);
+ setMat3xElem(1, idx, body.m_body_T_parent_ref(0, 1) * body.m_Jac_JT(0) + body.m_body_T_parent_ref(1, 1) * body.m_Jac_JT(1) + body.m_body_T_parent_ref(2, 1) * body.m_Jac_JT(2),
+ &body.m_body_Jac_T);
+ setMat3xElem(2, idx, body.m_body_T_parent_ref(0, 2) * body.m_Jac_JT(0) + body.m_body_T_parent_ref(1, 2) * body.m_Jac_JT(1) + body.m_body_T_parent_ref(2, 2) * body.m_Jac_JT(2),
+ &body.m_body_Jac_T);
+ break;
+ case FLOATING:
+ setMat3xElem(0, idx + 0, 1.0, &body.m_body_Jac_R);
+ setMat3xElem(1, idx + 1, 1.0, &body.m_body_Jac_R);
+ setMat3xElem(2, idx + 2, 1.0, &body.m_body_Jac_R);
+ // body_Jac_T = body_T_parent.transpose();
+ setMat3xElem(0, idx + 3, body.m_body_T_parent(0, 0), &body.m_body_Jac_T);
+ setMat3xElem(0, idx + 4, body.m_body_T_parent(1, 0), &body.m_body_Jac_T);
+ setMat3xElem(0, idx + 5, body.m_body_T_parent(2, 0), &body.m_body_Jac_T);
+
+ setMat3xElem(1, idx + 3, body.m_body_T_parent(0, 1), &body.m_body_Jac_T);
+ setMat3xElem(1, idx + 4, body.m_body_T_parent(1, 1), &body.m_body_Jac_T);
+ setMat3xElem(1, idx + 5, body.m_body_T_parent(2, 1), &body.m_body_Jac_T);
+
+ setMat3xElem(2, idx + 3, body.m_body_T_parent(0, 2), &body.m_body_Jac_T);
+ setMat3xElem(2, idx + 4, body.m_body_T_parent(1, 2), &body.m_body_Jac_T);
+ setMat3xElem(2, idx + 5, body.m_body_T_parent(2, 2), &body.m_body_Jac_T);
+
+ break;
+ case SPHERICAL:
+ //todo: review
+ setMat3xElem(0, idx + 0, 1.0, &body.m_body_Jac_R);
+ setMat3xElem(1, idx + 1, 1.0, &body.m_body_Jac_R);
+ setMat3xElem(2, idx + 2, 1.0, &body.m_body_Jac_R);
+ break;
+ }
}
-int MultiBodyTree::MultiBodyImpl::calculateJacobians(const vecx& q, const vecx& u, const KinUpdateType type) {
- if (q.size() != m_num_dofs || u.size() != m_num_dofs) {
- bt_id_error_message("wrong vector dimension. system has %d DOFs,\n"
- "but dim(q)= %d, dim(u)= %d\n",
- m_num_dofs, static_cast<int>(q.size()), static_cast<int>(u.size()));
- return -1;
- }
- if(type != POSITION_ONLY && type != POSITION_VELOCITY) {
- bt_id_error_message("invalid type %d\n", type);
- return -1;
- }
-
- addRelativeJacobianComponent(m_body_list[0]);
- for (idArrayIdx i = 1; i < m_body_list.size(); i++) {
- RigidBody &body = m_body_list[i];
- RigidBody &parent = m_body_list[m_parent_index[i]];
-
- mul(body.m_body_T_parent, parent.m_body_Jac_R,& body.m_body_Jac_R);
- body.m_body_Jac_T = parent.m_body_Jac_T;
- mul(tildeOperator(body.m_parent_pos_parent_body),parent.m_body_Jac_R,&m_m3x);
- sub(body.m_body_Jac_T,m_m3x, &body.m_body_Jac_T);
-
- addRelativeJacobianComponent(body);
- mul(body.m_body_T_parent, body.m_body_Jac_T,&body.m_body_Jac_T);
-
- if(type >= POSITION_VELOCITY) {
- body.m_body_dot_Jac_R_u = body.m_body_T_parent * parent.m_body_dot_Jac_R_u -
- body.m_body_ang_vel_rel.cross(body.m_body_T_parent * parent.m_body_ang_vel);
- body.m_body_dot_Jac_T_u = body.m_body_T_parent *
- (parent.m_body_dot_Jac_T_u + parent.m_body_dot_Jac_R_u.cross(body.m_parent_pos_parent_body) +
- parent.m_body_ang_vel.cross(parent.m_body_ang_vel.cross(body.m_parent_pos_parent_body)) +
- 2.0 * parent.m_body_ang_vel.cross(body.m_parent_vel_rel));
- }
- }
- return 0;
+int MultiBodyTree::MultiBodyImpl::calculateJacobians(const vecx &q, const vecx &u, const KinUpdateType type)
+{
+ if (q.size() != m_num_dofs || u.size() != m_num_dofs)
+ {
+ bt_id_error_message(
+ "wrong vector dimension. system has %d DOFs,\n"
+ "but dim(q)= %d, dim(u)= %d\n",
+ m_num_dofs, static_cast<int>(q.size()), static_cast<int>(u.size()));
+ return -1;
+ }
+ if (type != POSITION_ONLY && type != POSITION_VELOCITY)
+ {
+ bt_id_error_message("invalid type %d\n", type);
+ return -1;
+ }
+
+ addRelativeJacobianComponent(m_body_list[0]);
+ for (idArrayIdx i = 1; i < m_body_list.size(); i++)
+ {
+ RigidBody &body = m_body_list[i];
+ RigidBody &parent = m_body_list[m_parent_index[i]];
+
+ mul(body.m_body_T_parent, parent.m_body_Jac_R, &body.m_body_Jac_R);
+ body.m_body_Jac_T = parent.m_body_Jac_T;
+ mul(tildeOperator(body.m_parent_pos_parent_body), parent.m_body_Jac_R, &m_m3x);
+ sub(body.m_body_Jac_T, m_m3x, &body.m_body_Jac_T);
+
+ addRelativeJacobianComponent(body);
+ mul(body.m_body_T_parent, body.m_body_Jac_T, &body.m_body_Jac_T);
+
+ if (type >= POSITION_VELOCITY)
+ {
+ body.m_body_dot_Jac_R_u = body.m_body_T_parent * parent.m_body_dot_Jac_R_u -
+ body.m_body_ang_vel_rel.cross(body.m_body_T_parent * parent.m_body_ang_vel);
+ body.m_body_dot_Jac_T_u = body.m_body_T_parent *
+ (parent.m_body_dot_Jac_T_u + parent.m_body_dot_Jac_R_u.cross(body.m_parent_pos_parent_body) +
+ parent.m_body_ang_vel.cross(parent.m_body_ang_vel.cross(body.m_parent_pos_parent_body)) +
+ 2.0 * parent.m_body_ang_vel.cross(body.m_parent_vel_rel));
+ }
+ }
+ return 0;
}
#endif
-static inline void setSixDoFJacobians(const int dof, vec3 &Jac_JR, vec3 &Jac_JT) {
- switch (dof) {
+static inline void setThreeDoFJacobians(const int dof, vec3 &Jac_JR, vec3 &Jac_JT)
+{
+ switch (dof)
+ {
+ // rotational part
+ case 0:
+ Jac_JR(0) = 1;
+ Jac_JR(1) = 0;
+ Jac_JR(2) = 0;
+ setZero(Jac_JT);
+ break;
+ case 1:
+ Jac_JR(0) = 0;
+ Jac_JR(1) = 1;
+ Jac_JR(2) = 0;
+ setZero(Jac_JT);
+ break;
+ case 2:
+ Jac_JR(0) = 0;
+ Jac_JR(1) = 0;
+ Jac_JR(2) = 1;
+ setZero(Jac_JT);
+ break;
+ }
+}
+
+static inline void setSixDoFJacobians(const int dof, vec3 &Jac_JR, vec3 &Jac_JT)
+{
+ switch (dof)
+ {
// rotational part
case 0:
Jac_JR(0) = 1;
@@ -595,8 +740,10 @@ static inline void setSixDoFJacobians(const int dof, vec3 &Jac_JR, vec3 &Jac_JT)
}
}
-static inline int jointNumDoFs(const JointType &type) {
- switch (type) {
+static inline int jointNumDoFs(const JointType &type)
+{
+ switch (type)
+ {
case FIXED:
return 0;
case REVOLUTE:
@@ -604,6 +751,8 @@ static inline int jointNumDoFs(const JointType &type) {
return 1;
case FLOATING:
return 6;
+ case SPHERICAL:
+ return 3;
}
// this should never happen
bt_id_error_message("invalid joint type\n");
@@ -615,37 +764,45 @@ static inline int jointNumDoFs(const JointType &type) {
int MultiBodyTree::MultiBodyImpl::calculateMassMatrix(const vecx &q, const bool update_kinematics,
const bool initialize_matrix,
const bool set_lower_triangular_matrix,
- matxx *mass_matrix) {
-// This calculates the joint space mass matrix for the multibody system.
-// The algorithm is essentially an implementation of "method 3"
-// in "Efficient Dynamic Simulation of Robotic Mechanisms" (Walker and Orin, 1982)
-// (Later named "Composite Rigid Body Algorithm" by Featherstone).
-//
-// This implementation, however, handles branched systems and uses a formulation centered
-// on the origin of the body-fixed frame to avoid re-computing various quantities at the com.
+ matxx *mass_matrix)
+{
+ // This calculates the joint space mass matrix for the multibody system.
+ // The algorithm is essentially an implementation of "method 3"
+ // in "Efficient Dynamic Simulation of Robotic Mechanisms" (Walker and Orin, 1982)
+ // (Later named "Composite Rigid Body Algorithm" by Featherstone).
+ //
+ // This implementation, however, handles branched systems and uses a formulation centered
+ // on the origin of the body-fixed frame to avoid re-computing various quantities at the com.
if (q.size() != m_num_dofs || mass_matrix->rows() != m_num_dofs ||
- mass_matrix->cols() != m_num_dofs) {
- bt_id_error_message("Dimension error. System has %d DOFs,\n"
- "but dim(q)= %d, dim(mass_matrix)= %d x %d\n",
- m_num_dofs, static_cast<int>(q.size()), static_cast<int>(mass_matrix->rows()),
- static_cast<int>(mass_matrix->cols()));
+ mass_matrix->cols() != m_num_dofs)
+ {
+ bt_id_error_message(
+ "Dimension error. System has %d DOFs,\n"
+ "but dim(q)= %d, dim(mass_matrix)= %d x %d\n",
+ m_num_dofs, static_cast<int>(q.size()), static_cast<int>(mass_matrix->rows()),
+ static_cast<int>(mass_matrix->cols()));
return -1;
}
// TODO add optimized zeroing function?
- if (initialize_matrix) {
- for (int i = 0; i < m_num_dofs; i++) {
- for (int j = 0; j < m_num_dofs; j++) {
- setMatxxElem(i, j, 0.0, mass_matrix);
+ if (initialize_matrix)
+ {
+ for (int i = 0; i < m_num_dofs; i++)
+ {
+ for (int j = 0; j < m_num_dofs; j++)
+ {
+ setMatxxElem(i, j, 0.0, mass_matrix);
}
}
}
- if (update_kinematics) {
+ if (update_kinematics)
+ {
// 1. update relative kinematics
// 1.1 for revolute joints
- for (idArrayIdx i = 0; i < m_body_revolute_list.size(); i++) {
+ for (idArrayIdx i = 0; i < m_body_revolute_list.size(); i++)
+ {
RigidBody &body = m_body_list[m_body_revolute_list[i]];
// from reference orientation (q=0) of body-fixed frame to current orientation
mat33 body_T_body_ref;
@@ -653,7 +810,8 @@ int MultiBodyTree::MultiBodyImpl::calculateMassMatrix(const vecx &q, const bool
body.m_body_T_parent = body_T_body_ref * body.m_body_T_parent_ref;
}
// 1.2 for prismatic joints
- for (idArrayIdx i = 0; i < m_body_prismatic_list.size(); i++) {
+ for (idArrayIdx i = 0; i < m_body_prismatic_list.size(); i++)
+ {
RigidBody &body = m_body_list[m_body_prismatic_list[i]];
// body.m_body_T_parent= fixed
body.m_parent_pos_parent_body =
@@ -661,7 +819,8 @@ int MultiBodyTree::MultiBodyImpl::calculateMassMatrix(const vecx &q, const bool
}
// 1.3 fixed joints: nothing to do
// 1.4 6dof joints:
- for (idArrayIdx i = 0; i < m_body_floating_list.size(); i++) {
+ for (idArrayIdx i = 0; i < m_body_floating_list.size(); i++)
+ {
RigidBody &body = m_body_list[m_body_floating_list[i]];
body.m_body_T_parent = transformZ(q(body.m_q_index + 2)) *
@@ -674,7 +833,8 @@ int MultiBodyTree::MultiBodyImpl::calculateMassMatrix(const vecx &q, const bool
body.m_parent_pos_parent_body = body.m_body_T_parent * body.m_parent_pos_parent_body;
}
}
- for (int i = m_body_list.size() - 1; i >= 0; i--) {
+ for (int i = m_body_list.size() - 1; i >= 0; i--)
+ {
RigidBody &body = m_body_list[i];
// calculate mass, center of mass and inertia of "composite rigid body",
// ie, sub-tree starting at current body
@@ -682,7 +842,8 @@ int MultiBodyTree::MultiBodyImpl::calculateMassMatrix(const vecx &q, const bool
body.m_body_subtree_mass_com = body.m_body_mass_com;
body.m_body_subtree_I_body = body.m_body_I_body;
- for (idArrayIdx c = 0; c < m_child_indices[i].size(); c++) {
+ for (idArrayIdx c = 0; c < m_child_indices[i].size(); c++)
+ {
RigidBody &child = m_body_list[m_child_indices[i][c]];
mat33 body_T_child = child.m_body_T_parent.transpose();
@@ -692,7 +853,8 @@ int MultiBodyTree::MultiBodyImpl::calculateMassMatrix(const vecx &q, const bool
body.m_body_subtree_I_body +=
body_T_child * child.m_body_subtree_I_body * child.m_body_T_parent;
- if (child.m_subtree_mass > 0) {
+ if (child.m_subtree_mass > 0)
+ {
// Shift the reference point for the child subtree inertia using the
// Huygens-Steiner ("parallel axis") theorem.
// (First shift from child origin to child com, then from there to this body's
@@ -707,7 +869,8 @@ int MultiBodyTree::MultiBodyImpl::calculateMassMatrix(const vecx &q, const bool
}
}
- for (int i = m_body_list.size() - 1; i >= 0; i--) {
+ for (int i = m_body_list.size() - 1; i >= 0; i--)
+ {
const RigidBody &body = m_body_list[i];
// determine DoF-range for body
@@ -717,11 +880,18 @@ int MultiBodyTree::MultiBodyImpl::calculateMassMatrix(const vecx &q, const bool
// local joint jacobians (ok as is for 1-DoF joints)
vec3 Jac_JR = body.m_Jac_JR;
vec3 Jac_JT = body.m_Jac_JT;
- for (int col = q_index_max; col >= q_index_min; col--) {
+ for (int col = q_index_max; col >= q_index_min; col--)
+ {
// set jacobians for 6-DoF joints
- if (FLOATING == body.m_joint_type) {
+ if (FLOATING == body.m_joint_type)
+ {
setSixDoFJacobians(col - q_index_min, Jac_JR, Jac_JT);
}
+ if (SPHERICAL == body.m_joint_type)
+ {
+ //todo: review
+ setThreeDoFJacobians(col - q_index_min, Jac_JR, Jac_JT);
+ }
vec3 body_eom_rot =
body.m_body_subtree_I_body * Jac_JR + body.m_body_subtree_mass_com.cross(Jac_JT);
@@ -732,19 +902,27 @@ int MultiBodyTree::MultiBodyImpl::calculateMassMatrix(const vecx &q, const bool
// rest of the mass matrix column upwards
{
// 1. for multi-dof joints, rest of the dofs of this body
- for (int row = col - 1; row >= q_index_min; row--) {
- if (FLOATING != body.m_joint_type) {
- bt_id_error_message("??\n");
- return -1;
+ for (int row = col - 1; row >= q_index_min; row--)
+ {
+ if (SPHERICAL == body.m_joint_type)
+ {
+ //todo: review
+ setThreeDoFJacobians(row - q_index_min, Jac_JR, Jac_JT);
+ const double Mrc = Jac_JR.dot(body_eom_rot) + Jac_JT.dot(body_eom_trans);
+ setMatxxElem(col, row, Mrc, mass_matrix);
+ }
+ if (FLOATING == body.m_joint_type)
+ {
+ setSixDoFJacobians(row - q_index_min, Jac_JR, Jac_JT);
+ const double Mrc = Jac_JR.dot(body_eom_rot) + Jac_JT.dot(body_eom_trans);
+ setMatxxElem(col, row, Mrc, mass_matrix);
}
- setSixDoFJacobians(row - q_index_min, Jac_JR, Jac_JT);
- const double Mrc = Jac_JR.dot(body_eom_rot) + Jac_JT.dot(body_eom_trans);
- setMatxxElem(col, row, Mrc, mass_matrix);
}
// 2. ancestor dofs
int child_idx = i;
int parent_idx = m_parent_index[i];
- while (parent_idx >= 0) {
+ while (parent_idx >= 0)
+ {
const RigidBody &child_body = m_body_list[child_idx];
const RigidBody &parent_body = m_body_list[parent_idx];
@@ -758,9 +936,16 @@ int MultiBodyTree::MultiBodyImpl::calculateMassMatrix(const vecx &q, const bool
parent_body_q_index_min + jointNumDoFs(parent_body.m_joint_type) - 1;
vec3 Jac_JR = parent_body.m_Jac_JR;
vec3 Jac_JT = parent_body.m_Jac_JT;
- for (int row = parent_body_q_index_max; row >= parent_body_q_index_min; row--) {
+ for (int row = parent_body_q_index_max; row >= parent_body_q_index_min; row--)
+ {
+ if (SPHERICAL == parent_body.m_joint_type)
+ {
+ //todo: review
+ setThreeDoFJacobians(row - parent_body_q_index_min, Jac_JR, Jac_JT);
+ }
// set jacobians for 6-DoF joints
- if (FLOATING == parent_body.m_joint_type) {
+ if (FLOATING == parent_body.m_joint_type)
+ {
setSixDoFJacobians(row - parent_body_q_index_min, Jac_JR, Jac_JT);
}
const double Mrc = Jac_JR.dot(body_eom_rot) + Jac_JT.dot(body_eom_trans);
@@ -774,10 +959,13 @@ int MultiBodyTree::MultiBodyImpl::calculateMassMatrix(const vecx &q, const bool
}
}
- if (set_lower_triangular_matrix) {
- for (int col = 0; col < m_num_dofs; col++) {
- for (int row = 0; row < col; row++) {
- setMatxxElem(row, col, (*mass_matrix)(col, row), mass_matrix);
+ if (set_lower_triangular_matrix)
+ {
+ for (int col = 0; col < m_num_dofs; col++)
+ {
+ for (int row = 0; row < col; row++)
+ {
+ setMatxxElem(row, col, (*mass_matrix)(col, row), mass_matrix);
}
}
}
@@ -785,76 +973,91 @@ int MultiBodyTree::MultiBodyImpl::calculateMassMatrix(const vecx &q, const bool
}
// utility macro
-#define CHECK_IF_BODY_INDEX_IS_VALID(index) \
- do { \
- if (index < 0 || index >= m_num_bodies) { \
- bt_id_error_message("invalid index %d (num_bodies= %d)\n", index, m_num_bodies); \
- return -1; \
- } \
+#define CHECK_IF_BODY_INDEX_IS_VALID(index) \
+ do \
+ { \
+ if (index < 0 || index >= m_num_bodies) \
+ { \
+ bt_id_error_message("invalid index %d (num_bodies= %d)\n", index, m_num_bodies); \
+ return -1; \
+ } \
} while (0)
-int MultiBodyTree::MultiBodyImpl::getParentIndex(const int body_index, int *p) {
+int MultiBodyTree::MultiBodyImpl::getParentIndex(const int body_index, int *p)
+{
CHECK_IF_BODY_INDEX_IS_VALID(body_index);
*p = m_parent_index[body_index];
return 0;
}
-int MultiBodyTree::MultiBodyImpl::getUserInt(const int body_index, int *user_int) const {
+int MultiBodyTree::MultiBodyImpl::getUserInt(const int body_index, int *user_int) const
+{
CHECK_IF_BODY_INDEX_IS_VALID(body_index);
*user_int = m_user_int[body_index];
return 0;
}
-int MultiBodyTree::MultiBodyImpl::getUserPtr(const int body_index, void **user_ptr) const {
+int MultiBodyTree::MultiBodyImpl::getUserPtr(const int body_index, void **user_ptr) const
+{
CHECK_IF_BODY_INDEX_IS_VALID(body_index);
*user_ptr = m_user_ptr[body_index];
return 0;
}
-int MultiBodyTree::MultiBodyImpl::setUserInt(const int body_index, const int user_int) {
+int MultiBodyTree::MultiBodyImpl::setUserInt(const int body_index, const int user_int)
+{
CHECK_IF_BODY_INDEX_IS_VALID(body_index);
m_user_int[body_index] = user_int;
return 0;
}
-int MultiBodyTree::MultiBodyImpl::setUserPtr(const int body_index, void *const user_ptr) {
+int MultiBodyTree::MultiBodyImpl::setUserPtr(const int body_index, void *const user_ptr)
+{
CHECK_IF_BODY_INDEX_IS_VALID(body_index);
m_user_ptr[body_index] = user_ptr;
return 0;
}
-int MultiBodyTree::MultiBodyImpl::getBodyOrigin(int body_index, vec3 *world_origin) const {
+int MultiBodyTree::MultiBodyImpl::getBodyOrigin(int body_index, vec3 *world_origin) const
+{
CHECK_IF_BODY_INDEX_IS_VALID(body_index);
const RigidBody &body = m_body_list[body_index];
*world_origin = body.m_body_T_world.transpose() * body.m_body_pos;
return 0;
}
-int MultiBodyTree::MultiBodyImpl::getBodyCoM(int body_index, vec3 *world_com) const {
+int MultiBodyTree::MultiBodyImpl::getBodyCoM(int body_index, vec3 *world_com) const
+{
CHECK_IF_BODY_INDEX_IS_VALID(body_index);
const RigidBody &body = m_body_list[body_index];
- if (body.m_mass > 0) {
+ if (body.m_mass > 0)
+ {
*world_com = body.m_body_T_world.transpose() *
(body.m_body_pos + body.m_body_mass_com / body.m_mass);
- } else {
+ }
+ else
+ {
*world_com = body.m_body_T_world.transpose() * (body.m_body_pos);
}
return 0;
}
-int MultiBodyTree::MultiBodyImpl::getBodyTransform(int body_index, mat33 *world_T_body) const {
+int MultiBodyTree::MultiBodyImpl::getBodyTransform(int body_index, mat33 *world_T_body) const
+{
CHECK_IF_BODY_INDEX_IS_VALID(body_index);
const RigidBody &body = m_body_list[body_index];
*world_T_body = body.m_body_T_world.transpose();
return 0;
}
-int MultiBodyTree::MultiBodyImpl::getBodyAngularVelocity(int body_index, vec3 *world_omega) const {
+int MultiBodyTree::MultiBodyImpl::getBodyAngularVelocity(int body_index, vec3 *world_omega) const
+{
CHECK_IF_BODY_INDEX_IS_VALID(body_index);
const RigidBody &body = m_body_list[body_index];
*world_omega = body.m_body_T_world.transpose() * body.m_body_ang_vel;
return 0;
}
int MultiBodyTree::MultiBodyImpl::getBodyLinearVelocity(int body_index,
- vec3 *world_velocity) const {
+ vec3 *world_velocity) const
+{
CHECK_IF_BODY_INDEX_IS_VALID(body_index);
const RigidBody &body = m_body_list[body_index];
*world_velocity = body.m_body_T_world.transpose() * body.m_body_vel;
@@ -862,13 +1065,17 @@ int MultiBodyTree::MultiBodyImpl::getBodyLinearVelocity(int body_index,
}
int MultiBodyTree::MultiBodyImpl::getBodyLinearVelocityCoM(int body_index,
- vec3 *world_velocity) const {
+ vec3 *world_velocity) const
+{
CHECK_IF_BODY_INDEX_IS_VALID(body_index);
const RigidBody &body = m_body_list[body_index];
vec3 com;
- if (body.m_mass > 0) {
+ if (body.m_mass > 0)
+ {
com = body.m_body_mass_com / body.m_mass;
- } else {
+ }
+ else
+ {
com(0) = 0;
com(1) = 0;
com(2) = 0;
@@ -880,149 +1087,173 @@ int MultiBodyTree::MultiBodyImpl::getBodyLinearVelocityCoM(int body_index,
}
int MultiBodyTree::MultiBodyImpl::getBodyAngularAcceleration(int body_index,
- vec3 *world_dot_omega) const {
+ vec3 *world_dot_omega) const
+{
CHECK_IF_BODY_INDEX_IS_VALID(body_index);
const RigidBody &body = m_body_list[body_index];
*world_dot_omega = body.m_body_T_world.transpose() * body.m_body_ang_acc;
return 0;
}
int MultiBodyTree::MultiBodyImpl::getBodyLinearAcceleration(int body_index,
- vec3 *world_acceleration) const {
+ vec3 *world_acceleration) const
+{
CHECK_IF_BODY_INDEX_IS_VALID(body_index);
const RigidBody &body = m_body_list[body_index];
*world_acceleration = body.m_body_T_world.transpose() * body.m_body_acc;
return 0;
}
-int MultiBodyTree::MultiBodyImpl::getJointType(const int body_index, JointType *joint_type) const {
+int MultiBodyTree::MultiBodyImpl::getJointType(const int body_index, JointType *joint_type) const
+{
CHECK_IF_BODY_INDEX_IS_VALID(body_index);
*joint_type = m_body_list[body_index].m_joint_type;
return 0;
}
int MultiBodyTree::MultiBodyImpl::getJointTypeStr(const int body_index,
- const char **joint_type) const {
+ const char **joint_type) const
+{
CHECK_IF_BODY_INDEX_IS_VALID(body_index);
*joint_type = jointTypeToString(m_body_list[body_index].m_joint_type);
return 0;
}
-int MultiBodyTree::MultiBodyImpl::getParentRParentBodyRef(const int body_index, vec3* r) const{
- CHECK_IF_BODY_INDEX_IS_VALID(body_index);
- *r=m_body_list[body_index].m_parent_pos_parent_body_ref;
- return 0;
+int MultiBodyTree::MultiBodyImpl::getParentRParentBodyRef(const int body_index, vec3 *r) const
+{
+ CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+ *r = m_body_list[body_index].m_parent_pos_parent_body_ref;
+ return 0;
}
-int MultiBodyTree::MultiBodyImpl::getBodyTParentRef(const int body_index, mat33* T) const{
- CHECK_IF_BODY_INDEX_IS_VALID(body_index);
- *T=m_body_list[body_index].m_body_T_parent_ref;
- return 0;
+int MultiBodyTree::MultiBodyImpl::getBodyTParentRef(const int body_index, mat33 *T) const
+{
+ CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+ *T = m_body_list[body_index].m_body_T_parent_ref;
+ return 0;
}
-int MultiBodyTree::MultiBodyImpl::getBodyAxisOfMotion(const int body_index, vec3* axis) const{
- CHECK_IF_BODY_INDEX_IS_VALID(body_index);
- if(m_body_list[body_index].m_joint_type == REVOLUTE) {
- *axis = m_body_list[body_index].m_Jac_JR;
- return 0;
- }
- if(m_body_list[body_index].m_joint_type == PRISMATIC) {
- *axis = m_body_list[body_index].m_Jac_JT;
- return 0;
- }
- setZero(*axis);
- return 0;
+int MultiBodyTree::MultiBodyImpl::getBodyAxisOfMotion(const int body_index, vec3 *axis) const
+{
+ CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+ if (m_body_list[body_index].m_joint_type == REVOLUTE)
+ {
+ *axis = m_body_list[body_index].m_Jac_JR;
+ return 0;
+ }
+ if (m_body_list[body_index].m_joint_type == PRISMATIC)
+ {
+ *axis = m_body_list[body_index].m_Jac_JT;
+ return 0;
+ }
+ setZero(*axis);
+ return 0;
}
-int MultiBodyTree::MultiBodyImpl::getDoFOffset(const int body_index, int *q_index) const {
+int MultiBodyTree::MultiBodyImpl::getDoFOffset(const int body_index, int *q_index) const
+{
CHECK_IF_BODY_INDEX_IS_VALID(body_index);
*q_index = m_body_list[body_index].m_q_index;
return 0;
}
-int MultiBodyTree::MultiBodyImpl::setBodyMass(const int body_index, const idScalar mass) {
+int MultiBodyTree::MultiBodyImpl::setBodyMass(const int body_index, const idScalar mass)
+{
CHECK_IF_BODY_INDEX_IS_VALID(body_index);
m_body_list[body_index].m_mass = mass;
return 0;
}
int MultiBodyTree::MultiBodyImpl::setBodyFirstMassMoment(const int body_index,
- const vec3& first_mass_moment) {
+ const vec3 &first_mass_moment)
+{
CHECK_IF_BODY_INDEX_IS_VALID(body_index);
m_body_list[body_index].m_body_mass_com = first_mass_moment;
return 0;
}
int MultiBodyTree::MultiBodyImpl::setBodySecondMassMoment(const int body_index,
- const mat33& second_mass_moment) {
+ const mat33 &second_mass_moment)
+{
CHECK_IF_BODY_INDEX_IS_VALID(body_index);
m_body_list[body_index].m_body_I_body = second_mass_moment;
return 0;
}
-int MultiBodyTree::MultiBodyImpl::getBodyMass(const int body_index, idScalar *mass) const {
+int MultiBodyTree::MultiBodyImpl::getBodyMass(const int body_index, idScalar *mass) const
+{
CHECK_IF_BODY_INDEX_IS_VALID(body_index);
*mass = m_body_list[body_index].m_mass;
return 0;
}
int MultiBodyTree::MultiBodyImpl::getBodyFirstMassMoment(const int body_index,
- vec3 *first_mass_moment) const {
+ vec3 *first_mass_moment) const
+{
CHECK_IF_BODY_INDEX_IS_VALID(body_index);
*first_mass_moment = m_body_list[body_index].m_body_mass_com;
return 0;
}
int MultiBodyTree::MultiBodyImpl::getBodySecondMassMoment(const int body_index,
- mat33 *second_mass_moment) const {
+ mat33 *second_mass_moment) const
+{
CHECK_IF_BODY_INDEX_IS_VALID(body_index);
*second_mass_moment = m_body_list[body_index].m_body_I_body;
return 0;
}
-void MultiBodyTree::MultiBodyImpl::clearAllUserForcesAndMoments() {
- for (int index = 0; index < m_num_bodies; index++) {
+void MultiBodyTree::MultiBodyImpl::clearAllUserForcesAndMoments()
+{
+ for (int index = 0; index < m_num_bodies; index++)
+ {
RigidBody &body = m_body_list[index];
setZero(body.m_body_force_user);
setZero(body.m_body_moment_user);
}
}
-int MultiBodyTree::MultiBodyImpl::addUserForce(const int body_index, const vec3 &body_force) {
+int MultiBodyTree::MultiBodyImpl::addUserForce(const int body_index, const vec3 &body_force)
+{
CHECK_IF_BODY_INDEX_IS_VALID(body_index);
m_body_list[body_index].m_body_force_user += body_force;
return 0;
}
-int MultiBodyTree::MultiBodyImpl::addUserMoment(const int body_index, const vec3 &body_moment) {
+int MultiBodyTree::MultiBodyImpl::addUserMoment(const int body_index, const vec3 &body_moment)
+{
CHECK_IF_BODY_INDEX_IS_VALID(body_index);
m_body_list[body_index].m_body_moment_user += body_moment;
return 0;
}
#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
-int MultiBodyTree::MultiBodyImpl::getBodyDotJacobianTransU(const int body_index, vec3* world_dot_jac_trans_u) const {
- CHECK_IF_BODY_INDEX_IS_VALID(body_index);
- const RigidBody &body = m_body_list[body_index];
- *world_dot_jac_trans_u = body.m_body_T_world.transpose() * body.m_body_dot_Jac_T_u;
- return 0;
+int MultiBodyTree::MultiBodyImpl::getBodyDotJacobianTransU(const int body_index, vec3 *world_dot_jac_trans_u) const
+{
+ CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+ const RigidBody &body = m_body_list[body_index];
+ *world_dot_jac_trans_u = body.m_body_T_world.transpose() * body.m_body_dot_Jac_T_u;
+ return 0;
}
-int MultiBodyTree::MultiBodyImpl::getBodyDotJacobianRotU(const int body_index, vec3* world_dot_jac_rot_u) const{
- CHECK_IF_BODY_INDEX_IS_VALID(body_index);
- const RigidBody &body = m_body_list[body_index];
- *world_dot_jac_rot_u = body.m_body_T_world.transpose() * body.m_body_dot_Jac_R_u;
- return 0;
+int MultiBodyTree::MultiBodyImpl::getBodyDotJacobianRotU(const int body_index, vec3 *world_dot_jac_rot_u) const
+{
+ CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+ const RigidBody &body = m_body_list[body_index];
+ *world_dot_jac_rot_u = body.m_body_T_world.transpose() * body.m_body_dot_Jac_R_u;
+ return 0;
}
-int MultiBodyTree::MultiBodyImpl::getBodyJacobianTrans(const int body_index, mat3x* world_jac_trans) const{
- CHECK_IF_BODY_INDEX_IS_VALID(body_index);
- const RigidBody &body = m_body_list[body_index];
- mul(body.m_body_T_world.transpose(), body.m_body_Jac_T, world_jac_trans);
- return 0;
+int MultiBodyTree::MultiBodyImpl::getBodyJacobianTrans(const int body_index, mat3x *world_jac_trans) const
+{
+ CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+ const RigidBody &body = m_body_list[body_index];
+ mul(body.m_body_T_world.transpose(), body.m_body_Jac_T, world_jac_trans);
+ return 0;
}
-int MultiBodyTree::MultiBodyImpl::getBodyJacobianRot(const int body_index, mat3x* world_jac_rot) const{
- CHECK_IF_BODY_INDEX_IS_VALID(body_index);
- const RigidBody &body = m_body_list[body_index];
- mul(body.m_body_T_world.transpose(), body.m_body_Jac_R,world_jac_rot);
- return 0;
+int MultiBodyTree::MultiBodyImpl::getBodyJacobianRot(const int body_index, mat3x *world_jac_rot) const
+{
+ CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+ const RigidBody &body = m_body_list[body_index];
+ mul(body.m_body_T_world.transpose(), body.m_body_Jac_R, world_jac_rot);
+ return 0;
}
#endif
-}
+} // namespace btInverseDynamics
diff --git a/thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeImpl.hpp b/thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeImpl.hpp
index 3efe9d0492..eabdbe161b 100644
--- a/thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeImpl.hpp
+++ b/thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeImpl.hpp
@@ -8,12 +8,13 @@
#include "../IDConfig.hpp"
#include "../MultiBodyTree.hpp"
-namespace btInverseDynamics {
-
+namespace btInverseDynamics
+{
/// Structure for for rigid body mass properties, connectivity and kinematic state
/// all vectors and matrices are in body-fixed frame, if not indicated otherwise.
/// The body-fixed frame is located in the joint connecting the body to its parent.
-struct RigidBody {
+struct RigidBody
+{
ID_DECLARE_ALIGNED_ALLOCATOR();
// 1 Inertial properties
/// Mass
@@ -112,31 +113,33 @@ struct RigidBody {
mat33 m_body_subtree_I_body;
#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
- /// translational jacobian in body-fixed frame d(m_body_vel)/du
- mat3x m_body_Jac_T;
- /// rotationsl jacobian in body-fixed frame d(m_body_ang_vel)/du
- mat3x m_body_Jac_R;
- /// components of linear acceleration depending on u
- /// (same as is d(m_Jac_T)/dt*u)
- vec3 m_body_dot_Jac_T_u;
- /// components of angular acceleration depending on u
- /// (same as is d(m_Jac_T)/dt*u)
- vec3 m_body_dot_Jac_R_u;
+ /// translational jacobian in body-fixed frame d(m_body_vel)/du
+ mat3x m_body_Jac_T;
+ /// rotationsl jacobian in body-fixed frame d(m_body_ang_vel)/du
+ mat3x m_body_Jac_R;
+ /// components of linear acceleration depending on u
+ /// (same as is d(m_Jac_T)/dt*u)
+ vec3 m_body_dot_Jac_T_u;
+ /// components of angular acceleration depending on u
+ /// (same as is d(m_Jac_T)/dt*u)
+ vec3 m_body_dot_Jac_R_u;
#endif
};
/// The MBS implements a tree structured multibody system
-class MultiBodyTree::MultiBodyImpl {
+class MultiBodyTree::MultiBodyImpl
+{
friend class MultiBodyTree;
public:
ID_DECLARE_ALIGNED_ALLOCATOR();
- enum KinUpdateType {
- POSITION_ONLY,
- POSITION_VELOCITY,
- POSITION_VELOCITY_ACCELERATION
- };
+ enum KinUpdateType
+ {
+ POSITION_ONLY,
+ POSITION_VELOCITY,
+ POSITION_VELOCITY_ACCELERATION
+ };
/// constructor
/// @param num_bodies the number of bodies in the system
@@ -150,24 +153,24 @@ public:
int calculateMassMatrix(const vecx& q, const bool update_kinematics,
const bool initialize_matrix, const bool set_lower_triangular_matrix,
matxx* mass_matrix);
- /// calculate kinematics (vector quantities)
- /// Depending on type, update positions only, positions & velocities, or positions, velocities
- /// and accelerations.
- int calculateKinematics(const vecx& q, const vecx& u, const vecx& dot_u, const KinUpdateType type);
+ /// calculate kinematics (vector quantities)
+ /// Depending on type, update positions only, positions & velocities, or positions, velocities
+ /// and accelerations.
+ int calculateKinematics(const vecx& q, const vecx& u, const vecx& dot_u, const KinUpdateType type);
#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
- /// calculate jacobians and (if type == POSITION_VELOCITY), also velocity-dependent accelration terms.
- int calculateJacobians(const vecx& q, const vecx& u, const KinUpdateType type);
- /// \copydoc MultiBodyTree::getBodyDotJacobianTransU
- int getBodyDotJacobianTransU(const int body_index, vec3* world_dot_jac_trans_u) const ;
- /// \copydoc MultiBodyTree::getBodyDotJacobianRotU
- int getBodyDotJacobianRotU(const int body_index, vec3* world_dot_jac_rot_u) const;
- /// \copydoc MultiBodyTree::getBodyJacobianTrans
- int getBodyJacobianTrans(const int body_index, mat3x* world_jac_trans) const ;
- /// \copydoc MultiBodyTree::getBodyJacobianRot
- int getBodyJacobianRot(const int body_index, mat3x* world_jac_rot) const;
- /// Add relative Jacobian component from motion relative to parent body
- /// @param body the body to add the Jacobian component for
- void addRelativeJacobianComponent(RigidBody&body);
+ /// calculate jacobians and (if type == POSITION_VELOCITY), also velocity-dependent accelration terms.
+ int calculateJacobians(const vecx& q, const vecx& u, const KinUpdateType type);
+ /// \copydoc MultiBodyTree::getBodyDotJacobianTransU
+ int getBodyDotJacobianTransU(const int body_index, vec3* world_dot_jac_trans_u) const;
+ /// \copydoc MultiBodyTree::getBodyDotJacobianRotU
+ int getBodyDotJacobianRotU(const int body_index, vec3* world_dot_jac_rot_u) const;
+ /// \copydoc MultiBodyTree::getBodyJacobianTrans
+ int getBodyJacobianTrans(const int body_index, mat3x* world_jac_trans) const;
+ /// \copydoc MultiBodyTree::getBodyJacobianRot
+ int getBodyJacobianRot(const int body_index, mat3x* world_jac_rot) const;
+ /// Add relative Jacobian component from motion relative to parent body
+ /// @param body the body to add the Jacobian component for
+ void addRelativeJacobianComponent(RigidBody& body);
#endif
/// generate additional index sets from the parent_index array
/// @return -1 on error, 0 on success
@@ -190,12 +193,12 @@ public:
int getJointType(const int body_index, JointType* joint_type) const;
/// \copydoc MultiBodyTree::getJointTypeStr
int getJointTypeStr(const int body_index, const char** joint_type) const;
- /// \copydoc MultiBodyTree::getParentRParentBodyRef
- int getParentRParentBodyRef(const int body_index, vec3* r) const;
- /// \copydoc MultiBodyTree::getBodyTParentRef
- int getBodyTParentRef(const int body_index, mat33* T) const;
- /// \copydoc MultiBodyTree::getBodyAxisOfMotion
- int getBodyAxisOfMotion(const int body_index, vec3* axis) const;
+ /// \copydoc MultiBodyTree::getParentRParentBodyRef
+ int getParentRParentBodyRef(const int body_index, vec3* r) const;
+ /// \copydoc MultiBodyTree::getBodyTParentRef
+ int getBodyTParentRef(const int body_index, mat33* T) const;
+ /// \copydoc MultiBodyTree::getBodyAxisOfMotion
+ int getBodyAxisOfMotion(const int body_index, vec3* axis) const;
/// \copydoc MultiBodyTree:getDoFOffset
int getDoFOffset(const int body_index, int* q_index) const;
/// \copydoc MultiBodyTree::getBodyOrigin
@@ -271,13 +274,15 @@ private:
idArray<int>::type m_body_prismatic_list;
// Indices of floating joints
idArray<int>::type m_body_floating_list;
+ // Indices of spherical joints
+ idArray<int>::type m_body_spherical_list;
// a user-provided integer
idArray<int>::type m_user_int;
// a user-provided pointer
idArray<void*>::type m_user_ptr;
#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
- mat3x m_m3x;
+ mat3x m_m3x;
#endif
};
-}
+} // namespace btInverseDynamics
#endif
diff --git a/thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeInitCache.cpp b/thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeInitCache.cpp
index e9511b7076..a718db051e 100644
--- a/thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeInitCache.cpp
+++ b/thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeInitCache.cpp
@@ -1,12 +1,13 @@
#include "MultiBodyTreeInitCache.hpp"
-namespace btInverseDynamics {
-
-MultiBodyTree::InitCache::InitCache() {
+namespace btInverseDynamics
+{
+MultiBodyTree::InitCache::InitCache()
+{
m_inertias.resize(0);
m_joints.resize(0);
m_num_dofs = 0;
- m_root_index=-1;
+ m_root_index = -1;
}
int MultiBodyTree::InitCache::addBody(const int body_index, const int parent_index,
@@ -15,8 +16,10 @@ int MultiBodyTree::InitCache::addBody(const int body_index, const int parent_ind
const mat33& body_T_parent_ref,
const vec3& body_axis_of_motion, const idScalar mass,
const vec3& body_r_body_com, const mat33& body_I_body,
- const int user_int, void* user_ptr) {
- switch (joint_type) {
+ const int user_int, void* user_ptr)
+{
+ switch (joint_type)
+ {
case REVOLUTE:
case PRISMATIC:
m_num_dofs += 1;
@@ -25,6 +28,9 @@ int MultiBodyTree::InitCache::addBody(const int body_index, const int parent_ind
// does not add a degree of freedom
// m_num_dofs+=0;
break;
+ case SPHERICAL:
+ m_num_dofs += 3;
+ break;
case FLOATING:
m_num_dofs += 6;
break;
@@ -33,13 +39,15 @@ int MultiBodyTree::InitCache::addBody(const int body_index, const int parent_ind
return -1;
}
- if(-1 == parent_index) {
- if(m_root_index>=0) {
+ if (-1 == parent_index)
+ {
+ if (m_root_index >= 0)
+ {
bt_id_error_message("trying to add body %d as root, but already added %d as root body\n",
- body_index, m_root_index);
+ body_index, m_root_index);
return -1;
}
- m_root_index=body_index;
+ m_root_index = body_index;
}
JointData joint;
@@ -61,8 +69,10 @@ int MultiBodyTree::InitCache::addBody(const int body_index, const int parent_ind
m_user_ptr.push_back(user_ptr);
return 0;
}
-int MultiBodyTree::InitCache::getInertiaData(const int index, InertiaData* inertia) const {
- if (index < 0 || index > static_cast<int>(m_inertias.size())) {
+int MultiBodyTree::InitCache::getInertiaData(const int index, InertiaData* inertia) const
+{
+ if (index < 0 || index > static_cast<int>(m_inertias.size()))
+ {
bt_id_error_message("index out of range\n");
return -1;
}
@@ -71,8 +81,10 @@ int MultiBodyTree::InitCache::getInertiaData(const int index, InertiaData* inert
return 0;
}
-int MultiBodyTree::InitCache::getUserInt(const int index, int* user_int) const {
- if (index < 0 || index > static_cast<int>(m_user_int.size())) {
+int MultiBodyTree::InitCache::getUserInt(const int index, int* user_int) const
+{
+ if (index < 0 || index > static_cast<int>(m_user_int.size()))
+ {
bt_id_error_message("index out of range\n");
return -1;
}
@@ -80,8 +92,10 @@ int MultiBodyTree::InitCache::getUserInt(const int index, int* user_int) const {
return 0;
}
-int MultiBodyTree::InitCache::getUserPtr(const int index, void** user_ptr) const {
- if (index < 0 || index > static_cast<int>(m_user_ptr.size())) {
+int MultiBodyTree::InitCache::getUserPtr(const int index, void** user_ptr) const
+{
+ if (index < 0 || index > static_cast<int>(m_user_ptr.size()))
+ {
bt_id_error_message("index out of range\n");
return -1;
}
@@ -89,8 +103,10 @@ int MultiBodyTree::InitCache::getUserPtr(const int index, void** user_ptr) const
return 0;
}
-int MultiBodyTree::InitCache::getJointData(const int index, JointData* joint) const {
- if (index < 0 || index > static_cast<int>(m_joints.size())) {
+int MultiBodyTree::InitCache::getJointData(const int index, JointData* joint) const
+{
+ if (index < 0 || index > static_cast<int>(m_joints.size()))
+ {
bt_id_error_message("index out of range\n");
return -1;
}
@@ -98,16 +114,18 @@ int MultiBodyTree::InitCache::getJointData(const int index, JointData* joint) co
return 0;
}
-int MultiBodyTree::InitCache::buildIndexSets() {
+int MultiBodyTree::InitCache::buildIndexSets()
+{
// NOTE: This function assumes that proper indices were provided
// User2InternalIndex from utils can be used to facilitate this.
m_parent_index.resize(numBodies());
- for (idArrayIdx j = 0; j < m_joints.size(); j++) {
+ for (idArrayIdx j = 0; j < m_joints.size(); j++)
+ {
const JointData& joint = m_joints[j];
m_parent_index[joint.m_child] = joint.m_parent;
}
return 0;
}
-}
+} // namespace btInverseDynamics
diff --git a/thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeInitCache.hpp b/thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeInitCache.hpp
index 0d2aa4a071..dbdb3ff604 100644
--- a/thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeInitCache.hpp
+++ b/thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeInitCache.hpp
@@ -5,9 +5,11 @@
#include "../IDMath.hpp"
#include "../MultiBodyTree.hpp"
-namespace btInverseDynamics {
+namespace btInverseDynamics
+{
/// Mass properties of a rigid body
-struct InertiaData {
+struct InertiaData
+{
ID_DECLARE_ALIGNED_ALLOCATOR();
/// mass
@@ -21,7 +23,8 @@ struct InertiaData {
};
/// Joint properties
-struct JointData {
+struct JointData
+{
ID_DECLARE_ALIGNED_ALLOCATOR();
/// type of joint
@@ -48,7 +51,8 @@ struct JointData {
/// Data structure to store data passed by the user.
/// This is used in MultiBodyTree::finalize to build internal data structures.
-class MultiBodyTree::InitCache {
+class MultiBodyTree::InitCache
+{
public:
ID_DECLARE_ALIGNED_ALLOCATOR();
/// constructor
@@ -105,5 +109,5 @@ private:
// index of root body (or -1 if not set)
int m_root_index;
};
-}
+} // namespace btInverseDynamics
#endif // MULTIBODYTREEINITCACHE_HPP_
diff --git a/thirdparty/bullet/BulletSoftBody/btDefaultSoftBodySolver.cpp b/thirdparty/bullet/BulletSoftBody/btDefaultSoftBodySolver.cpp
index 9c20403074..8b7ff9abcd 100644
--- a/thirdparty/bullet/BulletSoftBody/btDefaultSoftBodySolver.cpp
+++ b/thirdparty/bullet/BulletSoftBody/btDefaultSoftBodySolver.cpp
@@ -21,11 +21,10 @@ subject to the following restrictions:
#include "BulletCollision/CollisionShapes/btCapsuleShape.h"
#include "BulletSoftBody/btSoftBody.h"
-
btDefaultSoftBodySolver::btDefaultSoftBodySolver()
{
// Initial we will clearly need to update solver constants
- // For now this is global for the cloths linked with this solver - we should probably make this body specific
+ // For now this is global for the cloths linked with this solver - we should probably make this body specific
// for performance in future once we understand more clearly when constants need to be updated
m_updateSolverConstants = true;
}
@@ -37,67 +36,65 @@ btDefaultSoftBodySolver::~btDefaultSoftBodySolver()
// In this case the data is already in the soft bodies so there is no need for us to do anything
void btDefaultSoftBodySolver::copyBackToSoftBodies(bool bMove)
{
-
}
-void btDefaultSoftBodySolver::optimize( btAlignedObjectArray< btSoftBody * > &softBodies , bool forceUpdate)
+void btDefaultSoftBodySolver::optimize(btAlignedObjectArray<btSoftBody *> &softBodies, bool forceUpdate)
{
- m_softBodySet.copyFromArray( softBodies );
+ m_softBodySet.copyFromArray(softBodies);
}
-void btDefaultSoftBodySolver::updateSoftBodies( )
+void btDefaultSoftBodySolver::updateSoftBodies()
{
- for ( int i=0; i < m_softBodySet.size(); i++)
+ for (int i = 0; i < m_softBodySet.size(); i++)
{
- btSoftBody* psb=(btSoftBody*)m_softBodySet[i];
+ btSoftBody *psb = (btSoftBody *)m_softBodySet[i];
if (psb->isActive())
{
- psb->integrateMotion();
+ psb->integrateMotion();
}
}
-} // updateSoftBodies
+} // updateSoftBodies
bool btDefaultSoftBodySolver::checkInitialized()
{
return true;
}
-void btDefaultSoftBodySolver::solveConstraints( float solverdt )
+void btDefaultSoftBodySolver::solveConstraints(float solverdt)
{
// Solve constraints for non-solver softbodies
- for(int i=0; i < m_softBodySet.size(); ++i)
+ for (int i = 0; i < m_softBodySet.size(); ++i)
{
- btSoftBody* psb = static_cast<btSoftBody*>(m_softBodySet[i]);
+ btSoftBody *psb = static_cast<btSoftBody *>(m_softBodySet[i]);
if (psb->isActive())
{
psb->solveConstraints();
}
- }
-} // btDefaultSoftBodySolver::solveConstraints
-
+ }
+} // btDefaultSoftBodySolver::solveConstraints
-void btDefaultSoftBodySolver::copySoftBodyToVertexBuffer( const btSoftBody *const softBody, btVertexBufferDescriptor *vertexBuffer )
+void btDefaultSoftBodySolver::copySoftBodyToVertexBuffer(const btSoftBody *const softBody, btVertexBufferDescriptor *vertexBuffer)
{
// Currently only support CPU output buffers
// TODO: check for DX11 buffers. Take all offsets into the same DX11 buffer
// and use them together on a single kernel call if possible by setting up a
// per-cloth target buffer array for the copy kernel.
- if( vertexBuffer->getBufferType() == btVertexBufferDescriptor::CPU_BUFFER )
+ if (vertexBuffer->getBufferType() == btVertexBufferDescriptor::CPU_BUFFER)
{
- const btAlignedObjectArray<btSoftBody::Node> &clothVertices( softBody->m_nodes );
+ const btAlignedObjectArray<btSoftBody::Node> &clothVertices(softBody->m_nodes);
int numVertices = clothVertices.size();
- const btCPUVertexBufferDescriptor *cpuVertexBuffer = static_cast< btCPUVertexBufferDescriptor* >(vertexBuffer);
- float *basePointer = cpuVertexBuffer->getBasePointer();
+ const btCPUVertexBufferDescriptor *cpuVertexBuffer = static_cast<btCPUVertexBufferDescriptor *>(vertexBuffer);
+ float *basePointer = cpuVertexBuffer->getBasePointer();
- if( vertexBuffer->hasVertexPositions() )
+ if (vertexBuffer->hasVertexPositions())
{
const int vertexOffset = cpuVertexBuffer->getVertexOffset();
const int vertexStride = cpuVertexBuffer->getVertexStride();
float *vertexPointer = basePointer + vertexOffset;
- for( int vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex )
+ for (int vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex)
{
btVector3 position = clothVertices[vertexIndex].m_x;
*(vertexPointer + 0) = (float)position.getX();
@@ -106,13 +103,13 @@ void btDefaultSoftBodySolver::copySoftBodyToVertexBuffer( const btSoftBody *cons
vertexPointer += vertexStride;
}
}
- if( vertexBuffer->hasNormals() )
+ if (vertexBuffer->hasNormals())
{
const int normalOffset = cpuVertexBuffer->getNormalOffset();
const int normalStride = cpuVertexBuffer->getNormalStride();
float *normalPointer = basePointer + normalOffset;
- for( int vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex )
+ for (int vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex)
{
btVector3 normal = clothVertices[vertexIndex].m_n;
*(normalPointer + 0) = (float)normal.getX();
@@ -122,30 +119,28 @@ void btDefaultSoftBodySolver::copySoftBodyToVertexBuffer( const btSoftBody *cons
}
}
}
-} // btDefaultSoftBodySolver::copySoftBodyToVertexBuffer
+} // btDefaultSoftBodySolver::copySoftBodyToVertexBuffer
-void btDefaultSoftBodySolver::processCollision( btSoftBody* softBody, btSoftBody* otherSoftBody)
+void btDefaultSoftBodySolver::processCollision(btSoftBody *softBody, btSoftBody *otherSoftBody)
{
- softBody->defaultCollisionHandler( otherSoftBody);
+ softBody->defaultCollisionHandler(otherSoftBody);
}
// For the default solver just leave the soft body to do its collision processing
-void btDefaultSoftBodySolver::processCollision( btSoftBody *softBody, const btCollisionObjectWrapper* collisionObjectWrap )
+void btDefaultSoftBodySolver::processCollision(btSoftBody *softBody, const btCollisionObjectWrapper *collisionObjectWrap)
{
- softBody->defaultCollisionHandler( collisionObjectWrap );
-} // btDefaultSoftBodySolver::processCollision
-
+ softBody->defaultCollisionHandler(collisionObjectWrap);
+} // btDefaultSoftBodySolver::processCollision
-void btDefaultSoftBodySolver::predictMotion( float timeStep )
+void btDefaultSoftBodySolver::predictMotion(float timeStep)
{
- for ( int i=0; i < m_softBodySet.size(); ++i)
+ for (int i = 0; i < m_softBodySet.size(); ++i)
{
- btSoftBody* psb = m_softBodySet[i];
+ btSoftBody *psb = m_softBodySet[i];
if (psb->isActive())
{
- psb->predictMotion(timeStep);
+ psb->predictMotion(timeStep);
}
}
}
-
diff --git a/thirdparty/bullet/BulletSoftBody/btDefaultSoftBodySolver.h b/thirdparty/bullet/BulletSoftBody/btDefaultSoftBodySolver.h
index 1c17ffcbb2..50bd735165 100644
--- a/thirdparty/bullet/BulletSoftBody/btDefaultSoftBodySolver.h
+++ b/thirdparty/bullet/BulletSoftBody/btDefaultSoftBodySolver.h
@@ -16,25 +16,23 @@ subject to the following restrictions:
#ifndef BT_SOFT_BODY_DEFAULT_SOLVER_H
#define BT_SOFT_BODY_DEFAULT_SOLVER_H
-
#include "BulletSoftBody/btSoftBodySolvers.h"
#include "btSoftBodySolverVertexBuffer.h"
struct btCollisionObjectWrapper;
class btDefaultSoftBodySolver : public btSoftBodySolver
{
-protected:
+protected:
/** Variable to define whether we need to update solver constants on the next iteration */
bool m_updateSolverConstants;
- btAlignedObjectArray< btSoftBody * > m_softBodySet;
-
+ btAlignedObjectArray<btSoftBody *> m_softBodySet;
public:
btDefaultSoftBodySolver();
-
+
virtual ~btDefaultSoftBodySolver();
-
+
virtual SolverTypes getSolverType() const
{
return DEFAULT_SOLVER;
@@ -42,22 +40,21 @@ public:
virtual bool checkInitialized();
- virtual void updateSoftBodies( );
+ virtual void updateSoftBodies();
- virtual void optimize( btAlignedObjectArray< btSoftBody * > &softBodies,bool forceUpdate=false );
+ virtual void optimize(btAlignedObjectArray<btSoftBody *> &softBodies, bool forceUpdate = false);
virtual void copyBackToSoftBodies(bool bMove = true);
- virtual void solveConstraints( float solverdt );
-
- virtual void predictMotion( float solverdt );
+ virtual void solveConstraints(float solverdt);
- virtual void copySoftBodyToVertexBuffer( const btSoftBody *const softBody, btVertexBufferDescriptor *vertexBuffer );
+ virtual void predictMotion(float solverdt);
- virtual void processCollision( btSoftBody *, const btCollisionObjectWrapper* );
+ virtual void copySoftBodyToVertexBuffer(const btSoftBody *const softBody, btVertexBufferDescriptor *vertexBuffer);
- virtual void processCollision( btSoftBody*, btSoftBody* );
+ virtual void processCollision(btSoftBody *, const btCollisionObjectWrapper *);
+ virtual void processCollision(btSoftBody *, btSoftBody *);
};
-#endif // #ifndef BT_ACCELERATED_SOFT_BODY_CPU_SOLVER_H
+#endif // #ifndef BT_ACCELERATED_SOFT_BODY_CPU_SOLVER_H
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftBody.cpp b/thirdparty/bullet/BulletSoftBody/btSoftBody.cpp
index 48efb0d8d4..58796a88d0 100644
--- a/thirdparty/bullet/BulletSoftBody/btSoftBody.cpp
+++ b/thirdparty/bullet/BulletSoftBody/btSoftBody.cpp
@@ -21,97 +21,94 @@ subject to the following restrictions:
#include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
#include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
-
//
-btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo,int node_count, const btVector3* x, const btScalar* m)
-:m_softBodySolver(0),m_worldInfo(worldInfo)
-{
- /* Init */
+btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo, int node_count, const btVector3* x, const btScalar* m)
+ : m_softBodySolver(0), m_worldInfo(worldInfo)
+{
+ /* Init */
initDefaults();
- /* Default material */
- Material* pm=appendMaterial();
- pm->m_kLST = 1;
- pm->m_kAST = 1;
- pm->m_kVST = 1;
- pm->m_flags = fMaterial::Default;
+ /* Default material */
+ Material* pm = appendMaterial();
+ pm->m_kLST = 1;
+ pm->m_kAST = 1;
+ pm->m_kVST = 1;
+ pm->m_flags = fMaterial::Default;
- /* Nodes */
- const btScalar margin=getCollisionShape()->getMargin();
+ /* Nodes */
+ const btScalar margin = getCollisionShape()->getMargin();
m_nodes.resize(node_count);
- for(int i=0,ni=node_count;i<ni;++i)
- {
- Node& n=m_nodes[i];
+ for (int i = 0, ni = node_count; i < ni; ++i)
+ {
+ Node& n = m_nodes[i];
ZeroInitialize(n);
- n.m_x = x?*x++:btVector3(0,0,0);
- n.m_q = n.m_x;
- n.m_im = m?*m++:1;
- n.m_im = n.m_im>0?1/n.m_im:0;
- n.m_leaf = m_ndbvt.insert(btDbvtVolume::FromCR(n.m_x,margin),&n);
- n.m_material= pm;
+ n.m_x = x ? *x++ : btVector3(0, 0, 0);
+ n.m_q = n.m_x;
+ n.m_im = m ? *m++ : 1;
+ n.m_im = n.m_im > 0 ? 1 / n.m_im : 0;
+ n.m_leaf = m_ndbvt.insert(btDbvtVolume::FromCR(n.m_x, margin), &n);
+ n.m_material = pm;
}
- updateBounds();
-
+ updateBounds();
}
-btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo)
-:m_worldInfo(worldInfo)
+btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo)
+ : m_worldInfo(worldInfo)
{
initDefaults();
}
-
-void btSoftBody::initDefaults()
-{
- m_internalType = CO_SOFT_BODY;
- m_cfg.aeromodel = eAeroModel::V_Point;
- m_cfg.kVCF = 1;
- m_cfg.kDG = 0;
- m_cfg.kLF = 0;
- m_cfg.kDP = 0;
- m_cfg.kPR = 0;
- m_cfg.kVC = 0;
- m_cfg.kDF = (btScalar)0.2;
- m_cfg.kMT = 0;
- m_cfg.kCHR = (btScalar)1.0;
- m_cfg.kKHR = (btScalar)0.1;
- m_cfg.kSHR = (btScalar)1.0;
- m_cfg.kAHR = (btScalar)0.7;
- m_cfg.kSRHR_CL = (btScalar)0.1;
- m_cfg.kSKHR_CL = (btScalar)1;
- m_cfg.kSSHR_CL = (btScalar)0.5;
- m_cfg.kSR_SPLT_CL = (btScalar)0.5;
- m_cfg.kSK_SPLT_CL = (btScalar)0.5;
- m_cfg.kSS_SPLT_CL = (btScalar)0.5;
- m_cfg.maxvolume = (btScalar)1;
- m_cfg.timescale = 1;
- m_cfg.viterations = 0;
- m_cfg.piterations = 1;
- m_cfg.diterations = 0;
- m_cfg.citerations = 4;
- m_cfg.collisions = fCollision::Default;
- m_pose.m_bvolume = false;
- m_pose.m_bframe = false;
- m_pose.m_volume = 0;
- m_pose.m_com = btVector3(0,0,0);
+void btSoftBody::initDefaults()
+{
+ m_internalType = CO_SOFT_BODY;
+ m_cfg.aeromodel = eAeroModel::V_Point;
+ m_cfg.kVCF = 1;
+ m_cfg.kDG = 0;
+ m_cfg.kLF = 0;
+ m_cfg.kDP = 0;
+ m_cfg.kPR = 0;
+ m_cfg.kVC = 0;
+ m_cfg.kDF = (btScalar)0.2;
+ m_cfg.kMT = 0;
+ m_cfg.kCHR = (btScalar)1.0;
+ m_cfg.kKHR = (btScalar)0.1;
+ m_cfg.kSHR = (btScalar)1.0;
+ m_cfg.kAHR = (btScalar)0.7;
+ m_cfg.kSRHR_CL = (btScalar)0.1;
+ m_cfg.kSKHR_CL = (btScalar)1;
+ m_cfg.kSSHR_CL = (btScalar)0.5;
+ m_cfg.kSR_SPLT_CL = (btScalar)0.5;
+ m_cfg.kSK_SPLT_CL = (btScalar)0.5;
+ m_cfg.kSS_SPLT_CL = (btScalar)0.5;
+ m_cfg.maxvolume = (btScalar)1;
+ m_cfg.timescale = 1;
+ m_cfg.viterations = 0;
+ m_cfg.piterations = 1;
+ m_cfg.diterations = 0;
+ m_cfg.citerations = 4;
+ m_cfg.collisions = fCollision::Default;
+ m_pose.m_bvolume = false;
+ m_pose.m_bframe = false;
+ m_pose.m_volume = 0;
+ m_pose.m_com = btVector3(0, 0, 0);
m_pose.m_rot.setIdentity();
m_pose.m_scl.setIdentity();
- m_tag = 0;
- m_timeacc = 0;
- m_bUpdateRtCst = true;
- m_bounds[0] = btVector3(0,0,0);
- m_bounds[1] = btVector3(0,0,0);
+ m_tag = 0;
+ m_timeacc = 0;
+ m_bUpdateRtCst = true;
+ m_bounds[0] = btVector3(0, 0, 0);
+ m_bounds[1] = btVector3(0, 0, 0);
m_worldTransform.setIdentity();
setSolver(eSolverPresets::Positions);
-
- /* Collision shape */
+
+ /* Collision shape */
///for now, create a collision shape internally
m_collisionShape = new btSoftBodyCollisionShape(this);
m_collisionShape->setMargin(0.25f);
-
+
m_initialWorldTransform.setIdentity();
- m_windVelocity = btVector3(0,0,0);
+ m_windVelocity = btVector3(0, 0, 0);
m_restLengthScale = btScalar(1.0);
}
@@ -119,343 +116,361 @@ void btSoftBody::initDefaults()
btSoftBody::~btSoftBody()
{
//for now, delete the internal shape
- delete m_collisionShape;
+ delete m_collisionShape;
int i;
releaseClusters();
- for(i=0;i<m_materials.size();++i)
+ for (i = 0; i < m_materials.size(); ++i)
btAlignedFree(m_materials[i]);
- for(i=0;i<m_joints.size();++i)
+ for (i = 0; i < m_joints.size(); ++i)
btAlignedFree(m_joints[i]);
}
//
-bool btSoftBody::checkLink(int node0,int node1) const
+bool btSoftBody::checkLink(int node0, int node1) const
{
- return(checkLink(&m_nodes[node0],&m_nodes[node1]));
+ return (checkLink(&m_nodes[node0], &m_nodes[node1]));
}
//
-bool btSoftBody::checkLink(const Node* node0,const Node* node1) const
+bool btSoftBody::checkLink(const Node* node0, const Node* node1) const
{
- const Node* n[]={node0,node1};
- for(int i=0,ni=m_links.size();i<ni;++i)
+ const Node* n[] = {node0, node1};
+ for (int i = 0, ni = m_links.size(); i < ni; ++i)
{
- const Link& l=m_links[i];
- if( (l.m_n[0]==n[0]&&l.m_n[1]==n[1])||
- (l.m_n[0]==n[1]&&l.m_n[1]==n[0]))
+ const Link& l = m_links[i];
+ if ((l.m_n[0] == n[0] && l.m_n[1] == n[1]) ||
+ (l.m_n[0] == n[1] && l.m_n[1] == n[0]))
{
- return(true);
+ return (true);
}
}
- return(false);
+ return (false);
}
//
-bool btSoftBody::checkFace(int node0,int node1,int node2) const
+bool btSoftBody::checkFace(int node0, int node1, int node2) const
{
- const Node* n[]={ &m_nodes[node0],
- &m_nodes[node1],
- &m_nodes[node2]};
- for(int i=0,ni=m_faces.size();i<ni;++i)
+ const Node* n[] = {&m_nodes[node0],
+ &m_nodes[node1],
+ &m_nodes[node2]};
+ for (int i = 0, ni = m_faces.size(); i < ni; ++i)
{
- const Face& f=m_faces[i];
- int c=0;
- for(int j=0;j<3;++j)
+ const Face& f = m_faces[i];
+ int c = 0;
+ for (int j = 0; j < 3; ++j)
{
- if( (f.m_n[j]==n[0])||
- (f.m_n[j]==n[1])||
- (f.m_n[j]==n[2])) c|=1<<j; else break;
+ if ((f.m_n[j] == n[0]) ||
+ (f.m_n[j] == n[1]) ||
+ (f.m_n[j] == n[2]))
+ c |= 1 << j;
+ else
+ break;
}
- if(c==7) return(true);
+ if (c == 7) return (true);
}
- return(false);
+ return (false);
}
//
-btSoftBody::Material* btSoftBody::appendMaterial()
+btSoftBody::Material* btSoftBody::appendMaterial()
{
- Material* pm=new(btAlignedAlloc(sizeof(Material),16)) Material();
- if(m_materials.size()>0)
- *pm=*m_materials[0];
+ Material* pm = new (btAlignedAlloc(sizeof(Material), 16)) Material();
+ if (m_materials.size() > 0)
+ *pm = *m_materials[0];
else
ZeroInitialize(*pm);
m_materials.push_back(pm);
- return(pm);
+ return (pm);
}
//
-void btSoftBody::appendNote( const char* text,
- const btVector3& o,
- const btVector4& c,
- Node* n0,
- Node* n1,
- Node* n2,
- Node* n3)
+void btSoftBody::appendNote(const char* text,
+ const btVector3& o,
+ const btVector4& c,
+ Node* n0,
+ Node* n1,
+ Node* n2,
+ Node* n3)
{
- Note n;
+ Note n;
ZeroInitialize(n);
- n.m_rank = 0;
- n.m_text = text;
- n.m_offset = o;
- n.m_coords[0] = c.x();
- n.m_coords[1] = c.y();
- n.m_coords[2] = c.z();
- n.m_coords[3] = c.w();
- n.m_nodes[0] = n0;n.m_rank+=n0?1:0;
- n.m_nodes[1] = n1;n.m_rank+=n1?1:0;
- n.m_nodes[2] = n2;n.m_rank+=n2?1:0;
- n.m_nodes[3] = n3;n.m_rank+=n3?1:0;
+ n.m_rank = 0;
+ n.m_text = text;
+ n.m_offset = o;
+ n.m_coords[0] = c.x();
+ n.m_coords[1] = c.y();
+ n.m_coords[2] = c.z();
+ n.m_coords[3] = c.w();
+ n.m_nodes[0] = n0;
+ n.m_rank += n0 ? 1 : 0;
+ n.m_nodes[1] = n1;
+ n.m_rank += n1 ? 1 : 0;
+ n.m_nodes[2] = n2;
+ n.m_rank += n2 ? 1 : 0;
+ n.m_nodes[3] = n3;
+ n.m_rank += n3 ? 1 : 0;
m_notes.push_back(n);
}
//
-void btSoftBody::appendNote( const char* text,
- const btVector3& o,
- Node* feature)
+void btSoftBody::appendNote(const char* text,
+ const btVector3& o,
+ Node* feature)
{
- appendNote(text,o,btVector4(1,0,0,0),feature);
+ appendNote(text, o, btVector4(1, 0, 0, 0), feature);
}
//
-void btSoftBody::appendNote( const char* text,
- const btVector3& o,
- Link* feature)
+void btSoftBody::appendNote(const char* text,
+ const btVector3& o,
+ Link* feature)
{
- static const btScalar w=1/(btScalar)2;
- appendNote(text,o,btVector4(w,w,0,0), feature->m_n[0],
- feature->m_n[1]);
+ static const btScalar w = 1 / (btScalar)2;
+ appendNote(text, o, btVector4(w, w, 0, 0), feature->m_n[0],
+ feature->m_n[1]);
}
//
-void btSoftBody::appendNote( const char* text,
- const btVector3& o,
- Face* feature)
+void btSoftBody::appendNote(const char* text,
+ const btVector3& o,
+ Face* feature)
{
- static const btScalar w=1/(btScalar)3;
- appendNote(text,o,btVector4(w,w,w,0), feature->m_n[0],
- feature->m_n[1],
- feature->m_n[2]);
+ static const btScalar w = 1 / (btScalar)3;
+ appendNote(text, o, btVector4(w, w, w, 0), feature->m_n[0],
+ feature->m_n[1],
+ feature->m_n[2]);
}
//
-void btSoftBody::appendNode( const btVector3& x,btScalar m)
+void btSoftBody::appendNode(const btVector3& x, btScalar m)
{
- if(m_nodes.capacity()==m_nodes.size())
+ if (m_nodes.capacity() == m_nodes.size())
{
pointersToIndices();
- m_nodes.reserve(m_nodes.size()*2+1);
+ m_nodes.reserve(m_nodes.size() * 2 + 1);
indicesToPointers();
}
- const btScalar margin=getCollisionShape()->getMargin();
+ const btScalar margin = getCollisionShape()->getMargin();
m_nodes.push_back(Node());
- Node& n=m_nodes[m_nodes.size()-1];
+ Node& n = m_nodes[m_nodes.size() - 1];
ZeroInitialize(n);
- n.m_x = x;
- n.m_q = n.m_x;
- n.m_im = m>0?1/m:0;
- n.m_material = m_materials[0];
- n.m_leaf = m_ndbvt.insert(btDbvtVolume::FromCR(n.m_x,margin),&n);
+ n.m_x = x;
+ n.m_q = n.m_x;
+ n.m_im = m > 0 ? 1 / m : 0;
+ n.m_material = m_materials[0];
+ n.m_leaf = m_ndbvt.insert(btDbvtVolume::FromCR(n.m_x, margin), &n);
}
//
-void btSoftBody::appendLink(int model,Material* mat)
+void btSoftBody::appendLink(int model, Material* mat)
{
- Link l;
- if(model>=0)
- l=m_links[model];
+ Link l;
+ if (model >= 0)
+ l = m_links[model];
else
- { ZeroInitialize(l);l.m_material=mat?mat:m_materials[0]; }
+ {
+ ZeroInitialize(l);
+ l.m_material = mat ? mat : m_materials[0];
+ }
m_links.push_back(l);
}
//
-void btSoftBody::appendLink( int node0,
- int node1,
- Material* mat,
- bool bcheckexist)
+void btSoftBody::appendLink(int node0,
+ int node1,
+ Material* mat,
+ bool bcheckexist)
{
- appendLink(&m_nodes[node0],&m_nodes[node1],mat,bcheckexist);
+ appendLink(&m_nodes[node0], &m_nodes[node1], mat, bcheckexist);
}
//
-void btSoftBody::appendLink( Node* node0,
- Node* node1,
- Material* mat,
- bool bcheckexist)
+void btSoftBody::appendLink(Node* node0,
+ Node* node1,
+ Material* mat,
+ bool bcheckexist)
{
- if((!bcheckexist)||(!checkLink(node0,node1)))
+ if ((!bcheckexist) || (!checkLink(node0, node1)))
{
- appendLink(-1,mat);
- Link& l=m_links[m_links.size()-1];
- l.m_n[0] = node0;
- l.m_n[1] = node1;
- l.m_rl = (l.m_n[0]->m_x-l.m_n[1]->m_x).length();
- m_bUpdateRtCst=true;
+ appendLink(-1, mat);
+ Link& l = m_links[m_links.size() - 1];
+ l.m_n[0] = node0;
+ l.m_n[1] = node1;
+ l.m_rl = (l.m_n[0]->m_x - l.m_n[1]->m_x).length();
+ m_bUpdateRtCst = true;
}
}
//
-void btSoftBody::appendFace(int model,Material* mat)
+void btSoftBody::appendFace(int model, Material* mat)
{
- Face f;
- if(model>=0)
- { f=m_faces[model]; }
+ Face f;
+ if (model >= 0)
+ {
+ f = m_faces[model];
+ }
else
- { ZeroInitialize(f);f.m_material=mat?mat:m_materials[0]; }
+ {
+ ZeroInitialize(f);
+ f.m_material = mat ? mat : m_materials[0];
+ }
m_faces.push_back(f);
}
//
-void btSoftBody::appendFace(int node0,int node1,int node2,Material* mat)
+void btSoftBody::appendFace(int node0, int node1, int node2, Material* mat)
{
- if (node0==node1)
+ if (node0 == node1)
return;
- if (node1==node2)
+ if (node1 == node2)
return;
- if (node2==node0)
+ if (node2 == node0)
return;
- appendFace(-1,mat);
- Face& f=m_faces[m_faces.size()-1];
- btAssert(node0!=node1);
- btAssert(node1!=node2);
- btAssert(node2!=node0);
- f.m_n[0] = &m_nodes[node0];
- f.m_n[1] = &m_nodes[node1];
- f.m_n[2] = &m_nodes[node2];
- f.m_ra = AreaOf( f.m_n[0]->m_x,
- f.m_n[1]->m_x,
- f.m_n[2]->m_x);
- m_bUpdateRtCst=true;
+ appendFace(-1, mat);
+ Face& f = m_faces[m_faces.size() - 1];
+ btAssert(node0 != node1);
+ btAssert(node1 != node2);
+ btAssert(node2 != node0);
+ f.m_n[0] = &m_nodes[node0];
+ f.m_n[1] = &m_nodes[node1];
+ f.m_n[2] = &m_nodes[node2];
+ f.m_ra = AreaOf(f.m_n[0]->m_x,
+ f.m_n[1]->m_x,
+ f.m_n[2]->m_x);
+ m_bUpdateRtCst = true;
}
//
-void btSoftBody::appendTetra(int model,Material* mat)
+void btSoftBody::appendTetra(int model, Material* mat)
{
-Tetra t;
-if(model>=0)
- t=m_tetras[model];
+ Tetra t;
+ if (model >= 0)
+ t = m_tetras[model];
else
- { ZeroInitialize(t);t.m_material=mat?mat:m_materials[0]; }
-m_tetras.push_back(t);
+ {
+ ZeroInitialize(t);
+ t.m_material = mat ? mat : m_materials[0];
+ }
+ m_tetras.push_back(t);
}
//
-void btSoftBody::appendTetra(int node0,
- int node1,
- int node2,
- int node3,
- Material* mat)
+void btSoftBody::appendTetra(int node0,
+ int node1,
+ int node2,
+ int node3,
+ Material* mat)
{
- appendTetra(-1,mat);
- Tetra& t=m_tetras[m_tetras.size()-1];
- t.m_n[0] = &m_nodes[node0];
- t.m_n[1] = &m_nodes[node1];
- t.m_n[2] = &m_nodes[node2];
- t.m_n[3] = &m_nodes[node3];
- t.m_rv = VolumeOf(t.m_n[0]->m_x,t.m_n[1]->m_x,t.m_n[2]->m_x,t.m_n[3]->m_x);
- m_bUpdateRtCst=true;
+ appendTetra(-1, mat);
+ Tetra& t = m_tetras[m_tetras.size() - 1];
+ t.m_n[0] = &m_nodes[node0];
+ t.m_n[1] = &m_nodes[node1];
+ t.m_n[2] = &m_nodes[node2];
+ t.m_n[3] = &m_nodes[node3];
+ t.m_rv = VolumeOf(t.m_n[0]->m_x, t.m_n[1]->m_x, t.m_n[2]->m_x, t.m_n[3]->m_x);
+ m_bUpdateRtCst = true;
}
//
-void btSoftBody::appendAnchor(int node,btRigidBody* body, bool disableCollisionBetweenLinkedBodies,btScalar influence)
+void btSoftBody::appendAnchor(int node, btRigidBody* body, bool disableCollisionBetweenLinkedBodies, btScalar influence)
{
- btVector3 local = body->getWorldTransform().inverse()*m_nodes[node].m_x;
- appendAnchor(node,body,local,disableCollisionBetweenLinkedBodies,influence);
+ btVector3 local = body->getWorldTransform().inverse() * m_nodes[node].m_x;
+ appendAnchor(node, body, local, disableCollisionBetweenLinkedBodies, influence);
}
//
-void btSoftBody::appendAnchor(int node,btRigidBody* body, const btVector3& localPivot,bool disableCollisionBetweenLinkedBodies,btScalar influence)
+void btSoftBody::appendAnchor(int node, btRigidBody* body, const btVector3& localPivot, bool disableCollisionBetweenLinkedBodies, btScalar influence)
{
if (disableCollisionBetweenLinkedBodies)
{
- if (m_collisionDisabledObjects.findLinearSearch(body)==m_collisionDisabledObjects.size())
+ if (m_collisionDisabledObjects.findLinearSearch(body) == m_collisionDisabledObjects.size())
{
m_collisionDisabledObjects.push_back(body);
}
}
- Anchor a;
- a.m_node = &m_nodes[node];
- a.m_body = body;
- a.m_local = localPivot;
- a.m_node->m_battach = 1;
+ Anchor a;
+ a.m_node = &m_nodes[node];
+ a.m_body = body;
+ a.m_local = localPivot;
+ a.m_node->m_battach = 1;
a.m_influence = influence;
m_anchors.push_back(a);
}
//
-void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,Cluster* body0,Body body1)
+void btSoftBody::appendLinearJoint(const LJoint::Specs& specs, Cluster* body0, Body body1)
{
- LJoint* pj = new(btAlignedAlloc(sizeof(LJoint),16)) LJoint();
- pj->m_bodies[0] = body0;
- pj->m_bodies[1] = body1;
- pj->m_refs[0] = pj->m_bodies[0].xform().inverse()*specs.position;
- pj->m_refs[1] = pj->m_bodies[1].xform().inverse()*specs.position;
- pj->m_cfm = specs.cfm;
- pj->m_erp = specs.erp;
- pj->m_split = specs.split;
+ LJoint* pj = new (btAlignedAlloc(sizeof(LJoint), 16)) LJoint();
+ pj->m_bodies[0] = body0;
+ pj->m_bodies[1] = body1;
+ pj->m_refs[0] = pj->m_bodies[0].xform().inverse() * specs.position;
+ pj->m_refs[1] = pj->m_bodies[1].xform().inverse() * specs.position;
+ pj->m_cfm = specs.cfm;
+ pj->m_erp = specs.erp;
+ pj->m_split = specs.split;
m_joints.push_back(pj);
}
//
-void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,Body body)
+void btSoftBody::appendLinearJoint(const LJoint::Specs& specs, Body body)
{
- appendLinearJoint(specs,m_clusters[0],body);
+ appendLinearJoint(specs, m_clusters[0], body);
}
//
-void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,btSoftBody* body)
+void btSoftBody::appendLinearJoint(const LJoint::Specs& specs, btSoftBody* body)
{
- appendLinearJoint(specs,m_clusters[0],body->m_clusters[0]);
+ appendLinearJoint(specs, m_clusters[0], body->m_clusters[0]);
}
//
-void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,Cluster* body0,Body body1)
+void btSoftBody::appendAngularJoint(const AJoint::Specs& specs, Cluster* body0, Body body1)
{
- AJoint* pj = new(btAlignedAlloc(sizeof(AJoint),16)) AJoint();
- pj->m_bodies[0] = body0;
- pj->m_bodies[1] = body1;
- pj->m_refs[0] = pj->m_bodies[0].xform().inverse().getBasis()*specs.axis;
- pj->m_refs[1] = pj->m_bodies[1].xform().inverse().getBasis()*specs.axis;
- pj->m_cfm = specs.cfm;
- pj->m_erp = specs.erp;
- pj->m_split = specs.split;
- pj->m_icontrol = specs.icontrol;
+ AJoint* pj = new (btAlignedAlloc(sizeof(AJoint), 16)) AJoint();
+ pj->m_bodies[0] = body0;
+ pj->m_bodies[1] = body1;
+ pj->m_refs[0] = pj->m_bodies[0].xform().inverse().getBasis() * specs.axis;
+ pj->m_refs[1] = pj->m_bodies[1].xform().inverse().getBasis() * specs.axis;
+ pj->m_cfm = specs.cfm;
+ pj->m_erp = specs.erp;
+ pj->m_split = specs.split;
+ pj->m_icontrol = specs.icontrol;
m_joints.push_back(pj);
}
//
-void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,Body body)
+void btSoftBody::appendAngularJoint(const AJoint::Specs& specs, Body body)
{
- appendAngularJoint(specs,m_clusters[0],body);
+ appendAngularJoint(specs, m_clusters[0], body);
}
//
-void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,btSoftBody* body)
+void btSoftBody::appendAngularJoint(const AJoint::Specs& specs, btSoftBody* body)
{
- appendAngularJoint(specs,m_clusters[0],body->m_clusters[0]);
+ appendAngularJoint(specs, m_clusters[0], body->m_clusters[0]);
}
//
-void btSoftBody::addForce(const btVector3& force)
+void btSoftBody::addForce(const btVector3& force)
{
- for(int i=0,ni=m_nodes.size();i<ni;++i) addForce(force,i);
+ for (int i = 0, ni = m_nodes.size(); i < ni; ++i) addForce(force, i);
}
//
-void btSoftBody::addForce(const btVector3& force,int node)
+void btSoftBody::addForce(const btVector3& force, int node)
{
- Node& n=m_nodes[node];
- if(n.m_im>0)
+ Node& n = m_nodes[node];
+ if (n.m_im > 0)
{
- n.m_f += force;
+ n.m_f += force;
}
}
-void btSoftBody::addAeroForceToNode(const btVector3& windVelocity,int nodeIndex)
+void btSoftBody::addAeroForceToNode(const btVector3& windVelocity, int nodeIndex)
{
btAssert(nodeIndex >= 0 && nodeIndex < m_nodes.size());
@@ -464,51 +479,51 @@ void btSoftBody::addAeroForceToNode(const btVector3& windVelocity,int nodeInde
const btScalar kDG = m_cfg.kDG;
//const btScalar kPR = m_cfg.kPR;
//const btScalar kVC = m_cfg.kVC;
- const bool as_lift = kLF>0;
- const bool as_drag = kDG>0;
+ const bool as_lift = kLF > 0;
+ const bool as_drag = kDG > 0;
const bool as_aero = as_lift || as_drag;
const bool as_vaero = as_aero && (m_cfg.aeromodel < btSoftBody::eAeroModel::F_TwoSided);
Node& n = m_nodes[nodeIndex];
- if( n.m_im>0 )
+ if (n.m_im > 0)
{
- btSoftBody::sMedium medium;
+ btSoftBody::sMedium medium;
EvaluateMedium(m_worldInfo, n.m_x, medium);
medium.m_velocity = windVelocity;
medium.m_density = m_worldInfo->air_density;
- /* Aerodynamics */
- if(as_vaero)
- {
- const btVector3 rel_v = n.m_v - medium.m_velocity;
+ /* Aerodynamics */
+ if (as_vaero)
+ {
+ const btVector3 rel_v = n.m_v - medium.m_velocity;
const btScalar rel_v_len = rel_v.length();
- const btScalar rel_v2 = rel_v.length2();
+ const btScalar rel_v2 = rel_v.length2();
- if(rel_v2>SIMD_EPSILON)
+ if (rel_v2 > SIMD_EPSILON)
{
const btVector3 rel_v_nrm = rel_v.normalized();
- btVector3 nrm = n.m_n;
+ btVector3 nrm = n.m_n;
if (m_cfg.aeromodel == btSoftBody::eAeroModel::V_TwoSidedLiftDrag)
{
- nrm *= (btScalar)( (btDot(nrm,rel_v) < 0) ? -1 : +1);
+ nrm *= (btScalar)((btDot(nrm, rel_v) < 0) ? -1 : +1);
btVector3 fDrag(0, 0, 0);
btVector3 fLift(0, 0, 0);
btScalar n_dot_v = nrm.dot(rel_v_nrm);
btScalar tri_area = 0.5f * n.m_area;
-
+
fDrag = 0.5f * kDG * medium.m_density * rel_v2 * tri_area * n_dot_v * (-rel_v_nrm);
-
+
// Check angle of attack
// cos(10º) = 0.98480
- if ( 0 < n_dot_v && n_dot_v < 0.98480f)
- fLift = 0.5f * kLF * medium.m_density * rel_v_len * tri_area * btSqrt(1.0f-n_dot_v*n_dot_v) * (nrm.cross(rel_v_nrm).cross(rel_v_nrm));
+ if (0 < n_dot_v && n_dot_v < 0.98480f)
+ fLift = 0.5f * kLF * medium.m_density * rel_v_len * tri_area * btSqrt(1.0f - n_dot_v * n_dot_v) * (nrm.cross(rel_v_nrm).cross(rel_v_nrm));
// Check if the velocity change resulted by aero drag force exceeds the current velocity of the node.
- btVector3 del_v_by_fDrag = fDrag*n.m_im*m_sst.sdt;
+ btVector3 del_v_by_fDrag = fDrag * n.m_im * m_sst.sdt;
btScalar del_v_by_fDrag_len2 = del_v_by_fDrag.length2();
btScalar v_len2 = n.m_v.length2();
@@ -516,7 +531,7 @@ void btSoftBody::addAeroForceToNode(const btVector3& windVelocity,int nodeInde
{
btScalar del_v_by_fDrag_len = del_v_by_fDrag.length();
btScalar v_len = n.m_v.length();
- fDrag *= btScalar(0.8)*(v_len / del_v_by_fDrag_len);
+ fDrag *= btScalar(0.8) * (v_len / del_v_by_fDrag_len);
}
n.m_f += fDrag;
@@ -525,83 +540,83 @@ void btSoftBody::addAeroForceToNode(const btVector3& windVelocity,int nodeInde
else if (m_cfg.aeromodel == btSoftBody::eAeroModel::V_Point || m_cfg.aeromodel == btSoftBody::eAeroModel::V_OneSided || m_cfg.aeromodel == btSoftBody::eAeroModel::V_TwoSided)
{
if (m_cfg.aeromodel == btSoftBody::eAeroModel::V_TwoSided)
- nrm *= (btScalar)( (btDot(nrm,rel_v) < 0) ? -1 : +1);
+ nrm *= (btScalar)((btDot(nrm, rel_v) < 0) ? -1 : +1);
- const btScalar dvn = btDot(rel_v,nrm);
- /* Compute forces */
- if(dvn>0)
+ const btScalar dvn = btDot(rel_v, nrm);
+ /* Compute forces */
+ if (dvn > 0)
{
- btVector3 force(0,0,0);
- const btScalar c0 = n.m_area * dvn * rel_v2/2;
- const btScalar c1 = c0 * medium.m_density;
- force += nrm*(-c1*kLF);
- force += rel_v.normalized() * (-c1 * kDG);
+ btVector3 force(0, 0, 0);
+ const btScalar c0 = n.m_area * dvn * rel_v2 / 2;
+ const btScalar c1 = c0 * medium.m_density;
+ force += nrm * (-c1 * kLF);
+ force += rel_v.normalized() * (-c1 * kDG);
ApplyClampedForce(n, force, dt);
}
- }
+ }
}
}
}
}
-void btSoftBody::addAeroForceToFace(const btVector3& windVelocity,int faceIndex)
+void btSoftBody::addAeroForceToFace(const btVector3& windVelocity, int faceIndex)
{
const btScalar dt = m_sst.sdt;
const btScalar kLF = m_cfg.kLF;
const btScalar kDG = m_cfg.kDG;
-// const btScalar kPR = m_cfg.kPR;
-// const btScalar kVC = m_cfg.kVC;
- const bool as_lift = kLF>0;
- const bool as_drag = kDG>0;
+ // const btScalar kPR = m_cfg.kPR;
+ // const btScalar kVC = m_cfg.kVC;
+ const bool as_lift = kLF > 0;
+ const bool as_drag = kDG > 0;
const bool as_aero = as_lift || as_drag;
const bool as_faero = as_aero && (m_cfg.aeromodel >= btSoftBody::eAeroModel::F_TwoSided);
- if(as_faero)
+ if (as_faero)
{
- btSoftBody::Face& f=m_faces[faceIndex];
+ btSoftBody::Face& f = m_faces[faceIndex];
- btSoftBody::sMedium medium;
-
- const btVector3 v=(f.m_n[0]->m_v+f.m_n[1]->m_v+f.m_n[2]->m_v)/3;
- const btVector3 x=(f.m_n[0]->m_x+f.m_n[1]->m_x+f.m_n[2]->m_x)/3;
- EvaluateMedium(m_worldInfo,x,medium);
+ btSoftBody::sMedium medium;
+
+ const btVector3 v = (f.m_n[0]->m_v + f.m_n[1]->m_v + f.m_n[2]->m_v) / 3;
+ const btVector3 x = (f.m_n[0]->m_x + f.m_n[1]->m_x + f.m_n[2]->m_x) / 3;
+ EvaluateMedium(m_worldInfo, x, medium);
medium.m_velocity = windVelocity;
medium.m_density = m_worldInfo->air_density;
- const btVector3 rel_v=v-medium.m_velocity;
+ const btVector3 rel_v = v - medium.m_velocity;
const btScalar rel_v_len = rel_v.length();
- const btScalar rel_v2=rel_v.length2();
+ const btScalar rel_v2 = rel_v.length2();
- if(rel_v2>SIMD_EPSILON)
+ if (rel_v2 > SIMD_EPSILON)
{
const btVector3 rel_v_nrm = rel_v.normalized();
- btVector3 nrm = f.m_normal;
+ btVector3 nrm = f.m_normal;
if (m_cfg.aeromodel == btSoftBody::eAeroModel::F_TwoSidedLiftDrag)
{
- nrm *= (btScalar)( (btDot(nrm,rel_v) < 0) ? -1 : +1);
+ nrm *= (btScalar)((btDot(nrm, rel_v) < 0) ? -1 : +1);
btVector3 fDrag(0, 0, 0);
btVector3 fLift(0, 0, 0);
btScalar n_dot_v = nrm.dot(rel_v_nrm);
btScalar tri_area = 0.5f * f.m_ra;
-
+
fDrag = 0.5f * kDG * medium.m_density * rel_v2 * tri_area * n_dot_v * (-rel_v_nrm);
// Check angle of attack
// cos(10º) = 0.98480
- if ( 0 < n_dot_v && n_dot_v < 0.98480f)
- fLift = 0.5f * kLF * medium.m_density * rel_v_len * tri_area * btSqrt(1.0f-n_dot_v*n_dot_v) * (nrm.cross(rel_v_nrm).cross(rel_v_nrm));
+ if (0 < n_dot_v && n_dot_v < 0.98480f)
+ fLift = 0.5f * kLF * medium.m_density * rel_v_len * tri_area * btSqrt(1.0f - n_dot_v * n_dot_v) * (nrm.cross(rel_v_nrm).cross(rel_v_nrm));
fDrag /= 3;
fLift /= 3;
- for(int j=0;j<3;++j)
+ for (int j = 0; j < 3; ++j)
{
- if (f.m_n[j]->m_im>0)
+ if (f.m_n[j]->m_im > 0)
{
// Check if the velocity change resulted by aero drag force exceeds the current velocity of the node.
- btVector3 del_v_by_fDrag = fDrag*f.m_n[j]->m_im*m_sst.sdt;
+ btVector3 del_v_by_fDrag = fDrag * f.m_n[j]->m_im * m_sst.sdt;
btScalar del_v_by_fDrag_len2 = del_v_by_fDrag.length2();
btScalar v_len2 = f.m_n[j]->m_v.length2();
@@ -609,10 +624,10 @@ void btSoftBody::addAeroForceToFace(const btVector3& windVelocity,int faceInde
{
btScalar del_v_by_fDrag_len = del_v_by_fDrag.length();
btScalar v_len = f.m_n[j]->m_v.length();
- fDrag *= btScalar(0.8)*(v_len / del_v_by_fDrag_len);
+ fDrag *= btScalar(0.8) * (v_len / del_v_by_fDrag_len);
}
- f.m_n[j]->m_f += fDrag;
+ f.m_n[j]->m_f += fDrag;
f.m_n[j]->m_f += fLift;
}
}
@@ -620,183 +635,181 @@ void btSoftBody::addAeroForceToFace(const btVector3& windVelocity,int faceInde
else if (m_cfg.aeromodel == btSoftBody::eAeroModel::F_OneSided || m_cfg.aeromodel == btSoftBody::eAeroModel::F_TwoSided)
{
if (m_cfg.aeromodel == btSoftBody::eAeroModel::F_TwoSided)
- nrm *= (btScalar)( (btDot(nrm,rel_v) < 0) ? -1 : +1);
+ nrm *= (btScalar)((btDot(nrm, rel_v) < 0) ? -1 : +1);
- const btScalar dvn=btDot(rel_v,nrm);
- /* Compute forces */
- if(dvn>0)
+ const btScalar dvn = btDot(rel_v, nrm);
+ /* Compute forces */
+ if (dvn > 0)
{
- btVector3 force(0,0,0);
- const btScalar c0 = f.m_ra*dvn*rel_v2;
- const btScalar c1 = c0*medium.m_density;
- force += nrm*(-c1*kLF);
- force += rel_v.normalized()*(-c1*kDG);
- force /= 3;
- for(int j=0;j<3;++j) ApplyClampedForce(*f.m_n[j],force,dt);
+ btVector3 force(0, 0, 0);
+ const btScalar c0 = f.m_ra * dvn * rel_v2;
+ const btScalar c1 = c0 * medium.m_density;
+ force += nrm * (-c1 * kLF);
+ force += rel_v.normalized() * (-c1 * kDG);
+ force /= 3;
+ for (int j = 0; j < 3; ++j) ApplyClampedForce(*f.m_n[j], force, dt);
}
}
}
}
-
}
//
-void btSoftBody::addVelocity(const btVector3& velocity)
+void btSoftBody::addVelocity(const btVector3& velocity)
{
- for(int i=0,ni=m_nodes.size();i<ni;++i) addVelocity(velocity,i);
+ for (int i = 0, ni = m_nodes.size(); i < ni; ++i) addVelocity(velocity, i);
}
-/* Set velocity for the entire body */
-void btSoftBody::setVelocity( const btVector3& velocity)
+/* Set velocity for the entire body */
+void btSoftBody::setVelocity(const btVector3& velocity)
{
- for(int i=0,ni=m_nodes.size();i<ni;++i)
+ for (int i = 0, ni = m_nodes.size(); i < ni; ++i)
{
- Node& n=m_nodes[i];
- if(n.m_im>0)
+ Node& n = m_nodes[i];
+ if (n.m_im > 0)
{
- n.m_v = velocity;
+ n.m_v = velocity;
}
}
}
-
//
-void btSoftBody::addVelocity(const btVector3& velocity,int node)
+void btSoftBody::addVelocity(const btVector3& velocity, int node)
{
- Node& n=m_nodes[node];
- if(n.m_im>0)
+ Node& n = m_nodes[node];
+ if (n.m_im > 0)
{
- n.m_v += velocity;
+ n.m_v += velocity;
}
}
//
-void btSoftBody::setMass(int node,btScalar mass)
+void btSoftBody::setMass(int node, btScalar mass)
{
- m_nodes[node].m_im=mass>0?1/mass:0;
- m_bUpdateRtCst=true;
+ m_nodes[node].m_im = mass > 0 ? 1 / mass : 0;
+ m_bUpdateRtCst = true;
}
//
-btScalar btSoftBody::getMass(int node) const
+btScalar btSoftBody::getMass(int node) const
{
- return(m_nodes[node].m_im>0?1/m_nodes[node].m_im:0);
+ return (m_nodes[node].m_im > 0 ? 1 / m_nodes[node].m_im : 0);
}
//
-btScalar btSoftBody::getTotalMass() const
+btScalar btSoftBody::getTotalMass() const
{
- btScalar mass=0;
- for(int i=0;i<m_nodes.size();++i)
+ btScalar mass = 0;
+ for (int i = 0; i < m_nodes.size(); ++i)
{
- mass+=getMass(i);
+ mass += getMass(i);
}
- return(mass);
+ return (mass);
}
//
-void btSoftBody::setTotalMass(btScalar mass,bool fromfaces)
+void btSoftBody::setTotalMass(btScalar mass, bool fromfaces)
{
int i;
- if(fromfaces)
+ if (fromfaces)
{
-
- for(i=0;i<m_nodes.size();++i)
+ for (i = 0; i < m_nodes.size(); ++i)
{
- m_nodes[i].m_im=0;
+ m_nodes[i].m_im = 0;
}
- for(i=0;i<m_faces.size();++i)
+ for (i = 0; i < m_faces.size(); ++i)
{
- const Face& f=m_faces[i];
- const btScalar twicearea=AreaOf( f.m_n[0]->m_x,
- f.m_n[1]->m_x,
- f.m_n[2]->m_x);
- for(int j=0;j<3;++j)
+ const Face& f = m_faces[i];
+ const btScalar twicearea = AreaOf(f.m_n[0]->m_x,
+ f.m_n[1]->m_x,
+ f.m_n[2]->m_x);
+ for (int j = 0; j < 3; ++j)
{
- f.m_n[j]->m_im+=twicearea;
+ f.m_n[j]->m_im += twicearea;
}
}
- for( i=0;i<m_nodes.size();++i)
+ for (i = 0; i < m_nodes.size(); ++i)
{
- m_nodes[i].m_im=1/m_nodes[i].m_im;
+ m_nodes[i].m_im = 1 / m_nodes[i].m_im;
}
}
- const btScalar tm=getTotalMass();
- const btScalar itm=1/tm;
- for( i=0;i<m_nodes.size();++i)
+ const btScalar tm = getTotalMass();
+ const btScalar itm = 1 / tm;
+ for (i = 0; i < m_nodes.size(); ++i)
{
- m_nodes[i].m_im/=itm*mass;
+ m_nodes[i].m_im /= itm * mass;
}
- m_bUpdateRtCst=true;
+ m_bUpdateRtCst = true;
}
//
-void btSoftBody::setTotalDensity(btScalar density)
+void btSoftBody::setTotalDensity(btScalar density)
{
- setTotalMass(getVolume()*density,true);
+ setTotalMass(getVolume() * density, true);
}
//
-void btSoftBody::setVolumeMass(btScalar mass)
+void btSoftBody::setVolumeMass(btScalar mass)
{
-btAlignedObjectArray<btScalar> ranks;
-ranks.resize(m_nodes.size(),0);
-int i;
+ btAlignedObjectArray<btScalar> ranks;
+ ranks.resize(m_nodes.size(), 0);
+ int i;
-for(i=0;i<m_nodes.size();++i)
+ for (i = 0; i < m_nodes.size(); ++i)
{
- m_nodes[i].m_im=0;
+ m_nodes[i].m_im = 0;
}
-for(i=0;i<m_tetras.size();++i)
+ for (i = 0; i < m_tetras.size(); ++i)
{
- const Tetra& t=m_tetras[i];
- for(int j=0;j<4;++j)
+ const Tetra& t = m_tetras[i];
+ for (int j = 0; j < 4; ++j)
{
- t.m_n[j]->m_im+=btFabs(t.m_rv);
- ranks[int(t.m_n[j]-&m_nodes[0])]+=1;
+ t.m_n[j]->m_im += btFabs(t.m_rv);
+ ranks[int(t.m_n[j] - &m_nodes[0])] += 1;
}
}
-for( i=0;i<m_nodes.size();++i)
+ for (i = 0; i < m_nodes.size(); ++i)
{
- if(m_nodes[i].m_im>0)
+ if (m_nodes[i].m_im > 0)
{
- m_nodes[i].m_im=ranks[i]/m_nodes[i].m_im;
+ m_nodes[i].m_im = ranks[i] / m_nodes[i].m_im;
}
}
-setTotalMass(mass,false);
+ setTotalMass(mass, false);
}
//
-void btSoftBody::setVolumeDensity(btScalar density)
+void btSoftBody::setVolumeDensity(btScalar density)
{
-btScalar volume=0;
-for(int i=0;i<m_tetras.size();++i)
+ btScalar volume = 0;
+ for (int i = 0; i < m_tetras.size(); ++i)
{
- const Tetra& t=m_tetras[i];
- for(int j=0;j<4;++j)
+ const Tetra& t = m_tetras[i];
+ for (int j = 0; j < 4; ++j)
{
- volume+=btFabs(t.m_rv);
+ volume += btFabs(t.m_rv);
}
}
-setVolumeMass(volume*density/6);
+ setVolumeMass(volume * density / 6);
}
//
-void btSoftBody::transform(const btTransform& trs)
+void btSoftBody::transform(const btTransform& trs)
{
- const btScalar margin=getCollisionShape()->getMargin();
- ATTRIBUTE_ALIGNED16(btDbvtVolume) vol;
-
- for(int i=0,ni=m_nodes.size();i<ni;++i)
+ const btScalar margin = getCollisionShape()->getMargin();
+ ATTRIBUTE_ALIGNED16(btDbvtVolume)
+ vol;
+
+ for (int i = 0, ni = m_nodes.size(); i < ni; ++i)
{
- Node& n=m_nodes[i];
- n.m_x=trs*n.m_x;
- n.m_q=trs*n.m_q;
- n.m_n=trs.getBasis()*n.m_n;
- vol = btDbvtVolume::FromCR(n.m_x,margin);
-
- m_ndbvt.update(n.m_leaf,vol);
+ Node& n = m_nodes[i];
+ n.m_x = trs * n.m_x;
+ n.m_q = trs * n.m_q;
+ n.m_n = trs.getBasis() * n.m_n;
+ vol = btDbvtVolume::FromCR(n.m_x, margin);
+
+ m_ndbvt.update(n.m_leaf, vol);
}
updateNormals();
updateBounds();
@@ -805,37 +818,37 @@ void btSoftBody::transform(const btTransform& trs)
}
//
-void btSoftBody::translate(const btVector3& trs)
+void btSoftBody::translate(const btVector3& trs)
{
- btTransform t;
+ btTransform t;
t.setIdentity();
t.setOrigin(trs);
transform(t);
}
//
-void btSoftBody::rotate( const btQuaternion& rot)
+void btSoftBody::rotate(const btQuaternion& rot)
{
- btTransform t;
+ btTransform t;
t.setIdentity();
t.setRotation(rot);
transform(t);
}
//
-void btSoftBody::scale(const btVector3& scl)
+void btSoftBody::scale(const btVector3& scl)
{
+ const btScalar margin = getCollisionShape()->getMargin();
+ ATTRIBUTE_ALIGNED16(btDbvtVolume)
+ vol;
- const btScalar margin=getCollisionShape()->getMargin();
- ATTRIBUTE_ALIGNED16(btDbvtVolume) vol;
-
- for(int i=0,ni=m_nodes.size();i<ni;++i)
+ for (int i = 0, ni = m_nodes.size(); i < ni; ++i)
{
- Node& n=m_nodes[i];
- n.m_x*=scl;
- n.m_q*=scl;
- vol = btDbvtVolume::FromCR(n.m_x,margin);
- m_ndbvt.update(n.m_leaf,vol);
+ Node& n = m_nodes[i];
+ n.m_x *= scl;
+ n.m_q *= scl;
+ vol = btDbvtVolume::FromCR(n.m_x, margin);
+ m_ndbvt.update(n.m_leaf, vol);
}
updateNormals();
updateBounds();
@@ -851,437 +864,432 @@ btScalar btSoftBody::getRestLengthScale()
//
void btSoftBody::setRestLengthScale(btScalar restLengthScale)
{
- for(int i=0, ni=m_links.size(); i<ni; ++i)
+ for (int i = 0, ni = m_links.size(); i < ni; ++i)
{
- Link& l=m_links[i];
- l.m_rl = l.m_rl / m_restLengthScale * restLengthScale;
- l.m_c1 = l.m_rl*l.m_rl;
+ Link& l = m_links[i];
+ l.m_rl = l.m_rl / m_restLengthScale * restLengthScale;
+ l.m_c1 = l.m_rl * l.m_rl;
}
m_restLengthScale = restLengthScale;
-
+
if (getActivationState() == ISLAND_SLEEPING)
activate();
}
//
-void btSoftBody::setPose(bool bvolume,bool bframe)
+void btSoftBody::setPose(bool bvolume, bool bframe)
{
- m_pose.m_bvolume = bvolume;
- m_pose.m_bframe = bframe;
- int i,ni;
+ m_pose.m_bvolume = bvolume;
+ m_pose.m_bframe = bframe;
+ int i, ni;
- /* Weights */
- const btScalar omass=getTotalMass();
- const btScalar kmass=omass*m_nodes.size()*1000;
- btScalar tmass=omass;
+ /* Weights */
+ const btScalar omass = getTotalMass();
+ const btScalar kmass = omass * m_nodes.size() * 1000;
+ btScalar tmass = omass;
m_pose.m_wgh.resize(m_nodes.size());
- for(i=0,ni=m_nodes.size();i<ni;++i)
+ for (i = 0, ni = m_nodes.size(); i < ni; ++i)
{
- if(m_nodes[i].m_im<=0) tmass+=kmass;
+ if (m_nodes[i].m_im <= 0) tmass += kmass;
}
- for( i=0,ni=m_nodes.size();i<ni;++i)
+ for (i = 0, ni = m_nodes.size(); i < ni; ++i)
{
- Node& n=m_nodes[i];
- m_pose.m_wgh[i]= n.m_im>0 ?
- 1/(m_nodes[i].m_im*tmass) :
- kmass/tmass;
+ Node& n = m_nodes[i];
+ m_pose.m_wgh[i] = n.m_im > 0 ? 1 / (m_nodes[i].m_im * tmass) : kmass / tmass;
}
- /* Pos */
- const btVector3 com=evaluateCom();
+ /* Pos */
+ const btVector3 com = evaluateCom();
m_pose.m_pos.resize(m_nodes.size());
- for( i=0,ni=m_nodes.size();i<ni;++i)
+ for (i = 0, ni = m_nodes.size(); i < ni; ++i)
{
- m_pose.m_pos[i]=m_nodes[i].m_x-com;
+ m_pose.m_pos[i] = m_nodes[i].m_x - com;
}
- m_pose.m_volume = bvolume?getVolume():0;
- m_pose.m_com = com;
+ m_pose.m_volume = bvolume ? getVolume() : 0;
+ m_pose.m_com = com;
m_pose.m_rot.setIdentity();
m_pose.m_scl.setIdentity();
- /* Aqq */
- m_pose.m_aqq[0] =
- m_pose.m_aqq[1] =
- m_pose.m_aqq[2] = btVector3(0,0,0);
- for( i=0,ni=m_nodes.size();i<ni;++i)
- {
- const btVector3& q=m_pose.m_pos[i];
- const btVector3 mq=m_pose.m_wgh[i]*q;
- m_pose.m_aqq[0]+=mq.x()*q;
- m_pose.m_aqq[1]+=mq.y()*q;
- m_pose.m_aqq[2]+=mq.z()*q;
- }
- m_pose.m_aqq=m_pose.m_aqq.inverse();
-
+ /* Aqq */
+ m_pose.m_aqq[0] =
+ m_pose.m_aqq[1] =
+ m_pose.m_aqq[2] = btVector3(0, 0, 0);
+ for (i = 0, ni = m_nodes.size(); i < ni; ++i)
+ {
+ const btVector3& q = m_pose.m_pos[i];
+ const btVector3 mq = m_pose.m_wgh[i] * q;
+ m_pose.m_aqq[0] += mq.x() * q;
+ m_pose.m_aqq[1] += mq.y() * q;
+ m_pose.m_aqq[2] += mq.z() * q;
+ }
+ m_pose.m_aqq = m_pose.m_aqq.inverse();
+
updateConstants();
}
-void btSoftBody::resetLinkRestLengths()
+void btSoftBody::resetLinkRestLengths()
{
- for(int i=0, ni=m_links.size();i<ni;++i)
+ for (int i = 0, ni = m_links.size(); i < ni; ++i)
{
- Link& l = m_links[i];
- l.m_rl = (l.m_n[0]->m_x-l.m_n[1]->m_x).length();
- l.m_c1 = l.m_rl*l.m_rl;
+ Link& l = m_links[i];
+ l.m_rl = (l.m_n[0]->m_x - l.m_n[1]->m_x).length();
+ l.m_c1 = l.m_rl * l.m_rl;
}
}
//
-btScalar btSoftBody::getVolume() const
+btScalar btSoftBody::getVolume() const
{
- btScalar vol=0;
- if(m_nodes.size()>0)
+ btScalar vol = 0;
+ if (m_nodes.size() > 0)
{
- int i,ni;
+ int i, ni;
- const btVector3 org=m_nodes[0].m_x;
- for(i=0,ni=m_faces.size();i<ni;++i)
+ const btVector3 org = m_nodes[0].m_x;
+ for (i = 0, ni = m_faces.size(); i < ni; ++i)
{
- const Face& f=m_faces[i];
- vol+=btDot(f.m_n[0]->m_x-org,btCross(f.m_n[1]->m_x-org,f.m_n[2]->m_x-org));
+ const Face& f = m_faces[i];
+ vol += btDot(f.m_n[0]->m_x - org, btCross(f.m_n[1]->m_x - org, f.m_n[2]->m_x - org));
}
- vol/=(btScalar)6;
+ vol /= (btScalar)6;
}
- return(vol);
+ return (vol);
}
//
-int btSoftBody::clusterCount() const
+int btSoftBody::clusterCount() const
{
- return(m_clusters.size());
+ return (m_clusters.size());
}
//
-btVector3 btSoftBody::clusterCom(const Cluster* cluster)
+btVector3 btSoftBody::clusterCom(const Cluster* cluster)
{
- btVector3 com(0,0,0);
- for(int i=0,ni=cluster->m_nodes.size();i<ni;++i)
+ btVector3 com(0, 0, 0);
+ for (int i = 0, ni = cluster->m_nodes.size(); i < ni; ++i)
{
- com+=cluster->m_nodes[i]->m_x*cluster->m_masses[i];
+ com += cluster->m_nodes[i]->m_x * cluster->m_masses[i];
}
- return(com*cluster->m_imass);
+ return (com * cluster->m_imass);
}
//
-btVector3 btSoftBody::clusterCom(int cluster) const
+btVector3 btSoftBody::clusterCom(int cluster) const
{
- return(clusterCom(m_clusters[cluster]));
+ return (clusterCom(m_clusters[cluster]));
}
//
-btVector3 btSoftBody::clusterVelocity(const Cluster* cluster,const btVector3& rpos)
+btVector3 btSoftBody::clusterVelocity(const Cluster* cluster, const btVector3& rpos)
{
- return(cluster->m_lv+btCross(cluster->m_av,rpos));
+ return (cluster->m_lv + btCross(cluster->m_av, rpos));
}
//
-void btSoftBody::clusterVImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse)
+void btSoftBody::clusterVImpulse(Cluster* cluster, const btVector3& rpos, const btVector3& impulse)
{
- const btVector3 li=cluster->m_imass*impulse;
- const btVector3 ai=cluster->m_invwi*btCross(rpos,impulse);
- cluster->m_vimpulses[0]+=li;cluster->m_lv+=li;
- cluster->m_vimpulses[1]+=ai;cluster->m_av+=ai;
+ const btVector3 li = cluster->m_imass * impulse;
+ const btVector3 ai = cluster->m_invwi * btCross(rpos, impulse);
+ cluster->m_vimpulses[0] += li;
+ cluster->m_lv += li;
+ cluster->m_vimpulses[1] += ai;
+ cluster->m_av += ai;
cluster->m_nvimpulses++;
}
//
-void btSoftBody::clusterDImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse)
+void btSoftBody::clusterDImpulse(Cluster* cluster, const btVector3& rpos, const btVector3& impulse)
{
- const btVector3 li=cluster->m_imass*impulse;
- const btVector3 ai=cluster->m_invwi*btCross(rpos,impulse);
- cluster->m_dimpulses[0]+=li;
- cluster->m_dimpulses[1]+=ai;
+ const btVector3 li = cluster->m_imass * impulse;
+ const btVector3 ai = cluster->m_invwi * btCross(rpos, impulse);
+ cluster->m_dimpulses[0] += li;
+ cluster->m_dimpulses[1] += ai;
cluster->m_ndimpulses++;
}
//
-void btSoftBody::clusterImpulse(Cluster* cluster,const btVector3& rpos,const Impulse& impulse)
+void btSoftBody::clusterImpulse(Cluster* cluster, const btVector3& rpos, const Impulse& impulse)
{
- if(impulse.m_asVelocity) clusterVImpulse(cluster,rpos,impulse.m_velocity);
- if(impulse.m_asDrift) clusterDImpulse(cluster,rpos,impulse.m_drift);
+ if (impulse.m_asVelocity) clusterVImpulse(cluster, rpos, impulse.m_velocity);
+ if (impulse.m_asDrift) clusterDImpulse(cluster, rpos, impulse.m_drift);
}
//
-void btSoftBody::clusterVAImpulse(Cluster* cluster,const btVector3& impulse)
+void btSoftBody::clusterVAImpulse(Cluster* cluster, const btVector3& impulse)
{
- const btVector3 ai=cluster->m_invwi*impulse;
- cluster->m_vimpulses[1]+=ai;cluster->m_av+=ai;
+ const btVector3 ai = cluster->m_invwi * impulse;
+ cluster->m_vimpulses[1] += ai;
+ cluster->m_av += ai;
cluster->m_nvimpulses++;
}
//
-void btSoftBody::clusterDAImpulse(Cluster* cluster,const btVector3& impulse)
+void btSoftBody::clusterDAImpulse(Cluster* cluster, const btVector3& impulse)
{
- const btVector3 ai=cluster->m_invwi*impulse;
- cluster->m_dimpulses[1]+=ai;
+ const btVector3 ai = cluster->m_invwi * impulse;
+ cluster->m_dimpulses[1] += ai;
cluster->m_ndimpulses++;
}
//
-void btSoftBody::clusterAImpulse(Cluster* cluster,const Impulse& impulse)
+void btSoftBody::clusterAImpulse(Cluster* cluster, const Impulse& impulse)
{
- if(impulse.m_asVelocity) clusterVAImpulse(cluster,impulse.m_velocity);
- if(impulse.m_asDrift) clusterDAImpulse(cluster,impulse.m_drift);
+ if (impulse.m_asVelocity) clusterVAImpulse(cluster, impulse.m_velocity);
+ if (impulse.m_asDrift) clusterDAImpulse(cluster, impulse.m_drift);
}
//
-void btSoftBody::clusterDCImpulse(Cluster* cluster,const btVector3& impulse)
+void btSoftBody::clusterDCImpulse(Cluster* cluster, const btVector3& impulse)
{
- cluster->m_dimpulses[0]+=impulse*cluster->m_imass;
+ cluster->m_dimpulses[0] += impulse * cluster->m_imass;
cluster->m_ndimpulses++;
}
struct NodeLinks
{
- btAlignedObjectArray<int> m_links;
+ btAlignedObjectArray<int> m_links;
};
-
-
//
-int btSoftBody::generateBendingConstraints(int distance,Material* mat)
+int btSoftBody::generateBendingConstraints(int distance, Material* mat)
{
- int i,j;
+ int i, j;
- if(distance>1)
+ if (distance > 1)
{
- /* Build graph */
- const int n=m_nodes.size();
- const unsigned inf=(~(unsigned)0)>>1;
- unsigned* adj=new unsigned[n*n];
-
+ /* Build graph */
+ const int n = m_nodes.size();
+ const unsigned inf = (~(unsigned)0) >> 1;
+ unsigned* adj = new unsigned[n * n];
-#define IDX(_x_,_y_) ((_y_)*n+(_x_))
- for(j=0;j<n;++j)
+#define IDX(_x_, _y_) ((_y_)*n + (_x_))
+ for (j = 0; j < n; ++j)
{
- for(i=0;i<n;++i)
+ for (i = 0; i < n; ++i)
{
- if(i!=j)
+ if (i != j)
{
- adj[IDX(i,j)]=adj[IDX(j,i)]=inf;
+ adj[IDX(i, j)] = adj[IDX(j, i)] = inf;
}
else
{
- adj[IDX(i,j)]=adj[IDX(j,i)]=0;
+ adj[IDX(i, j)] = adj[IDX(j, i)] = 0;
}
}
}
- for( i=0;i<m_links.size();++i)
+ for (i = 0; i < m_links.size(); ++i)
{
- const int ia=(int)(m_links[i].m_n[0]-&m_nodes[0]);
- const int ib=(int)(m_links[i].m_n[1]-&m_nodes[0]);
- adj[IDX(ia,ib)]=1;
- adj[IDX(ib,ia)]=1;
+ const int ia = (int)(m_links[i].m_n[0] - &m_nodes[0]);
+ const int ib = (int)(m_links[i].m_n[1] - &m_nodes[0]);
+ adj[IDX(ia, ib)] = 1;
+ adj[IDX(ib, ia)] = 1;
}
-
//special optimized case for distance == 2
if (distance == 2)
{
-
btAlignedObjectArray<NodeLinks> nodeLinks;
-
/* Build node links */
nodeLinks.resize(m_nodes.size());
- for( i=0;i<m_links.size();++i)
+ for (i = 0; i < m_links.size(); ++i)
{
- const int ia=(int)(m_links[i].m_n[0]-&m_nodes[0]);
- const int ib=(int)(m_links[i].m_n[1]-&m_nodes[0]);
- if (nodeLinks[ia].m_links.findLinearSearch(ib)==nodeLinks[ia].m_links.size())
+ const int ia = (int)(m_links[i].m_n[0] - &m_nodes[0]);
+ const int ib = (int)(m_links[i].m_n[1] - &m_nodes[0]);
+ if (nodeLinks[ia].m_links.findLinearSearch(ib) == nodeLinks[ia].m_links.size())
nodeLinks[ia].m_links.push_back(ib);
- if (nodeLinks[ib].m_links.findLinearSearch(ia)==nodeLinks[ib].m_links.size())
+ if (nodeLinks[ib].m_links.findLinearSearch(ia) == nodeLinks[ib].m_links.size())
nodeLinks[ib].m_links.push_back(ia);
}
- for (int ii=0;ii<nodeLinks.size();ii++)
+ for (int ii = 0; ii < nodeLinks.size(); ii++)
{
- int i=ii;
+ int i = ii;
- for (int jj=0;jj<nodeLinks[ii].m_links.size();jj++)
+ for (int jj = 0; jj < nodeLinks[ii].m_links.size(); jj++)
{
int k = nodeLinks[ii].m_links[jj];
- for (int kk=0;kk<nodeLinks[k].m_links.size();kk++)
+ for (int kk = 0; kk < nodeLinks[k].m_links.size(); kk++)
{
int j = nodeLinks[k].m_links[kk];
- if (i!=j)
+ if (i != j)
{
- const unsigned sum=adj[IDX(i,k)]+adj[IDX(k,j)];
- btAssert(sum==2);
- if(adj[IDX(i,j)]>sum)
+ const unsigned sum = adj[IDX(i, k)] + adj[IDX(k, j)];
+ btAssert(sum == 2);
+ if (adj[IDX(i, j)] > sum)
{
- adj[IDX(i,j)]=adj[IDX(j,i)]=sum;
+ adj[IDX(i, j)] = adj[IDX(j, i)] = sum;
}
}
-
}
}
}
- } else
+ }
+ else
{
///generic Floyd's algorithm
- for(int k=0;k<n;++k)
+ for (int k = 0; k < n; ++k)
{
- for(j=0;j<n;++j)
+ for (j = 0; j < n; ++j)
{
- for(i=j+1;i<n;++i)
+ for (i = j + 1; i < n; ++i)
{
- const unsigned sum=adj[IDX(i,k)]+adj[IDX(k,j)];
- if(adj[IDX(i,j)]>sum)
+ const unsigned sum = adj[IDX(i, k)] + adj[IDX(k, j)];
+ if (adj[IDX(i, j)] > sum)
{
- adj[IDX(i,j)]=adj[IDX(j,i)]=sum;
+ adj[IDX(i, j)] = adj[IDX(j, i)] = sum;
}
}
}
}
}
-
- /* Build links */
- int nlinks=0;
- for(j=0;j<n;++j)
+ /* Build links */
+ int nlinks = 0;
+ for (j = 0; j < n; ++j)
{
- for(i=j+1;i<n;++i)
+ for (i = j + 1; i < n; ++i)
{
- if(adj[IDX(i,j)]==(unsigned)distance)
+ if (adj[IDX(i, j)] == (unsigned)distance)
{
- appendLink(i,j,mat);
- m_links[m_links.size()-1].m_bbending=1;
+ appendLink(i, j, mat);
+ m_links[m_links.size() - 1].m_bbending = 1;
++nlinks;
}
}
}
- delete[] adj;
- return(nlinks);
+ delete[] adj;
+ return (nlinks);
}
- return(0);
+ return (0);
}
//
-void btSoftBody::randomizeConstraints()
+void btSoftBody::randomizeConstraints()
{
- unsigned long seed=243703;
-#define NEXTRAND (seed=(1664525L*seed+1013904223L)&0xffffffff)
- int i,ni;
+ unsigned long seed = 243703;
+#define NEXTRAND (seed = (1664525L * seed + 1013904223L) & 0xffffffff)
+ int i, ni;
- for(i=0,ni=m_links.size();i<ni;++i)
+ for (i = 0, ni = m_links.size(); i < ni; ++i)
{
- btSwap(m_links[i],m_links[NEXTRAND%ni]);
+ btSwap(m_links[i], m_links[NEXTRAND % ni]);
}
- for(i=0,ni=m_faces.size();i<ni;++i)
+ for (i = 0, ni = m_faces.size(); i < ni; ++i)
{
- btSwap(m_faces[i],m_faces[NEXTRAND%ni]);
+ btSwap(m_faces[i], m_faces[NEXTRAND % ni]);
}
#undef NEXTRAND
}
//
-void btSoftBody::releaseCluster(int index)
+void btSoftBody::releaseCluster(int index)
{
- Cluster* c=m_clusters[index];
- if(c->m_leaf) m_cdbvt.remove(c->m_leaf);
+ Cluster* c = m_clusters[index];
+ if (c->m_leaf) m_cdbvt.remove(c->m_leaf);
c->~Cluster();
btAlignedFree(c);
m_clusters.remove(c);
}
//
-void btSoftBody::releaseClusters()
+void btSoftBody::releaseClusters()
{
- while(m_clusters.size()>0) releaseCluster(0);
+ while (m_clusters.size() > 0) releaseCluster(0);
}
//
-int btSoftBody::generateClusters(int k,int maxiterations)
+int btSoftBody::generateClusters(int k, int maxiterations)
{
int i;
releaseClusters();
- m_clusters.resize(btMin(k,m_nodes.size()));
- for(i=0;i<m_clusters.size();++i)
- {
- m_clusters[i] = new(btAlignedAlloc(sizeof(Cluster),16)) Cluster();
- m_clusters[i]->m_collide= true;
- }
- k=m_clusters.size();
- if(k>0)
- {
- /* Initialize */
- btAlignedObjectArray<btVector3> centers;
- btVector3 cog(0,0,0);
- int i;
- for(i=0;i<m_nodes.size();++i)
- {
- cog+=m_nodes[i].m_x;
- m_clusters[(i*29873)%m_clusters.size()]->m_nodes.push_back(&m_nodes[i]);
- }
- cog/=(btScalar)m_nodes.size();
- centers.resize(k,cog);
- /* Iterate */
- const btScalar slope=16;
- bool changed;
- int iterations=0;
- do {
- const btScalar w=2-btMin<btScalar>(1,iterations/slope);
- changed=false;
- iterations++;
+ m_clusters.resize(btMin(k, m_nodes.size()));
+ for (i = 0; i < m_clusters.size(); ++i)
+ {
+ m_clusters[i] = new (btAlignedAlloc(sizeof(Cluster), 16)) Cluster();
+ m_clusters[i]->m_collide = true;
+ }
+ k = m_clusters.size();
+ if (k > 0)
+ {
+ /* Initialize */
+ btAlignedObjectArray<btVector3> centers;
+ btVector3 cog(0, 0, 0);
+ int i;
+ for (i = 0; i < m_nodes.size(); ++i)
+ {
+ cog += m_nodes[i].m_x;
+ m_clusters[(i * 29873) % m_clusters.size()]->m_nodes.push_back(&m_nodes[i]);
+ }
+ cog /= (btScalar)m_nodes.size();
+ centers.resize(k, cog);
+ /* Iterate */
+ const btScalar slope = 16;
+ bool changed;
+ int iterations = 0;
+ do
+ {
+ const btScalar w = 2 - btMin<btScalar>(1, iterations / slope);
+ changed = false;
+ iterations++;
int i;
- for(i=0;i<k;++i)
+ for (i = 0; i < k; ++i)
{
- btVector3 c(0,0,0);
- for(int j=0;j<m_clusters[i]->m_nodes.size();++j)
+ btVector3 c(0, 0, 0);
+ for (int j = 0; j < m_clusters[i]->m_nodes.size(); ++j)
{
- c+=m_clusters[i]->m_nodes[j]->m_x;
+ c += m_clusters[i]->m_nodes[j]->m_x;
}
- if(m_clusters[i]->m_nodes.size())
+ if (m_clusters[i]->m_nodes.size())
{
- c /= (btScalar)m_clusters[i]->m_nodes.size();
- c = centers[i]+(c-centers[i])*w;
- changed |= ((c-centers[i]).length2()>SIMD_EPSILON);
- centers[i] = c;
+ c /= (btScalar)m_clusters[i]->m_nodes.size();
+ c = centers[i] + (c - centers[i]) * w;
+ changed |= ((c - centers[i]).length2() > SIMD_EPSILON);
+ centers[i] = c;
m_clusters[i]->m_nodes.resize(0);
- }
+ }
}
- for(i=0;i<m_nodes.size();++i)
+ for (i = 0; i < m_nodes.size(); ++i)
{
- const btVector3 nx=m_nodes[i].m_x;
- int kbest=0;
- btScalar kdist=ClusterMetric(centers[0],nx);
- for(int j=1;j<k;++j)
+ const btVector3 nx = m_nodes[i].m_x;
+ int kbest = 0;
+ btScalar kdist = ClusterMetric(centers[0], nx);
+ for (int j = 1; j < k; ++j)
{
- const btScalar d=ClusterMetric(centers[j],nx);
- if(d<kdist)
+ const btScalar d = ClusterMetric(centers[j], nx);
+ if (d < kdist)
{
- kbest=j;
- kdist=d;
+ kbest = j;
+ kdist = d;
}
}
m_clusters[kbest]->m_nodes.push_back(&m_nodes[i]);
- }
- } while(changed&&(iterations<maxiterations));
- /* Merge */
- btAlignedObjectArray<int> cids;
- cids.resize(m_nodes.size(),-1);
- for(i=0;i<m_clusters.size();++i)
+ }
+ } while (changed && (iterations < maxiterations));
+ /* Merge */
+ btAlignedObjectArray<int> cids;
+ cids.resize(m_nodes.size(), -1);
+ for (i = 0; i < m_clusters.size(); ++i)
{
- for(int j=0;j<m_clusters[i]->m_nodes.size();++j)
+ for (int j = 0; j < m_clusters[i]->m_nodes.size(); ++j)
{
- cids[int(m_clusters[i]->m_nodes[j]-&m_nodes[0])]=i;
+ cids[int(m_clusters[i]->m_nodes[j] - &m_nodes[0])] = i;
}
}
- for(i=0;i<m_faces.size();++i)
+ for (i = 0; i < m_faces.size(); ++i)
{
- const int idx[]={ int(m_faces[i].m_n[0]-&m_nodes[0]),
- int(m_faces[i].m_n[1]-&m_nodes[0]),
- int(m_faces[i].m_n[2]-&m_nodes[0])};
- for(int j=0;j<3;++j)
+ const int idx[] = {int(m_faces[i].m_n[0] - &m_nodes[0]),
+ int(m_faces[i].m_n[1] - &m_nodes[0]),
+ int(m_faces[i].m_n[2] - &m_nodes[0])};
+ for (int j = 0; j < 3; ++j)
{
- const int cid=cids[idx[j]];
- for(int q=1;q<3;++q)
+ const int cid = cids[idx[j]];
+ for (int q = 1; q < 3; ++q)
{
- const int kid=idx[(j+q)%3];
- if(cids[kid]!=cid)
+ const int kid = idx[(j + q) % 3];
+ if (cids[kid] != cid)
{
- if(m_clusters[cid]->m_nodes.findLinearSearch(&m_nodes[kid])==m_clusters[cid]->m_nodes.size())
+ if (m_clusters[cid]->m_nodes.findLinearSearch(&m_nodes[kid]) == m_clusters[cid]->m_nodes.size())
{
m_clusters[cid]->m_nodes.push_back(&m_nodes[kid]);
}
@@ -1289,55 +1297,56 @@ int btSoftBody::generateClusters(int k,int maxiterations)
}
}
}
- /* Master */
- if(m_clusters.size()>1)
+ /* Master */
+ if (m_clusters.size() > 1)
{
- Cluster* pmaster=new(btAlignedAlloc(sizeof(Cluster),16)) Cluster();
- pmaster->m_collide = false;
+ Cluster* pmaster = new (btAlignedAlloc(sizeof(Cluster), 16)) Cluster();
+ pmaster->m_collide = false;
pmaster->m_nodes.reserve(m_nodes.size());
- for(int i=0;i<m_nodes.size();++i) pmaster->m_nodes.push_back(&m_nodes[i]);
+ for (int i = 0; i < m_nodes.size(); ++i) pmaster->m_nodes.push_back(&m_nodes[i]);
m_clusters.push_back(pmaster);
- btSwap(m_clusters[0],m_clusters[m_clusters.size()-1]);
+ btSwap(m_clusters[0], m_clusters[m_clusters.size() - 1]);
}
- /* Terminate */
- for(i=0;i<m_clusters.size();++i)
+ /* Terminate */
+ for (i = 0; i < m_clusters.size(); ++i)
{
- if(m_clusters[i]->m_nodes.size()==0)
+ if (m_clusters[i]->m_nodes.size() == 0)
{
releaseCluster(i--);
}
}
- } else
+ }
+ else
{
//create a cluster for each tetrahedron (if tetrahedra exist) or each face
if (m_tetras.size())
{
m_clusters.resize(m_tetras.size());
- for(i=0;i<m_clusters.size();++i)
+ for (i = 0; i < m_clusters.size(); ++i)
{
- m_clusters[i] = new(btAlignedAlloc(sizeof(Cluster),16)) Cluster();
- m_clusters[i]->m_collide= true;
+ m_clusters[i] = new (btAlignedAlloc(sizeof(Cluster), 16)) Cluster();
+ m_clusters[i]->m_collide = true;
}
- for (i=0;i<m_tetras.size();i++)
+ for (i = 0; i < m_tetras.size(); i++)
{
- for (int j=0;j<4;j++)
+ for (int j = 0; j < 4; j++)
{
m_clusters[i]->m_nodes.push_back(m_tetras[i].m_n[j]);
}
}
-
- } else
+ }
+ else
{
m_clusters.resize(m_faces.size());
- for(i=0;i<m_clusters.size();++i)
+ for (i = 0; i < m_clusters.size(); ++i)
{
- m_clusters[i] = new(btAlignedAlloc(sizeof(Cluster),16)) Cluster();
- m_clusters[i]->m_collide= true;
+ m_clusters[i] = new (btAlignedAlloc(sizeof(Cluster), 16)) Cluster();
+ m_clusters[i]->m_collide = true;
}
- for(i=0;i<m_faces.size();++i)
+ for (i = 0; i < m_faces.size(); ++i)
{
- for(int j=0;j<3;++j)
+ for (int j = 0; j < 3; ++j)
{
m_clusters[i]->m_nodes.push_back(m_faces[i].m_n[j]);
}
@@ -1350,261 +1359,272 @@ int btSoftBody::generateClusters(int k,int maxiterations)
initializeClusters();
updateClusters();
-
//for self-collision
- m_clusterConnectivity.resize(m_clusters.size()*m_clusters.size());
+ m_clusterConnectivity.resize(m_clusters.size() * m_clusters.size());
{
- for (int c0=0;c0<m_clusters.size();c0++)
+ for (int c0 = 0; c0 < m_clusters.size(); c0++)
{
- m_clusters[c0]->m_clusterIndex=c0;
- for (int c1=0;c1<m_clusters.size();c1++)
+ m_clusters[c0]->m_clusterIndex = c0;
+ for (int c1 = 0; c1 < m_clusters.size(); c1++)
{
-
- bool connected=false;
+ bool connected = false;
Cluster* cla = m_clusters[c0];
Cluster* clb = m_clusters[c1];
- for (int i=0;!connected&&i<cla->m_nodes.size();i++)
+ for (int i = 0; !connected && i < cla->m_nodes.size(); i++)
{
- for (int j=0;j<clb->m_nodes.size();j++)
+ for (int j = 0; j < clb->m_nodes.size(); j++)
{
if (cla->m_nodes[i] == clb->m_nodes[j])
{
- connected=true;
+ connected = true;
break;
}
}
}
- m_clusterConnectivity[c0+c1*m_clusters.size()]=connected;
+ m_clusterConnectivity[c0 + c1 * m_clusters.size()] = connected;
}
}
}
}
- return(m_clusters.size());
+ return (m_clusters.size());
}
//
-void btSoftBody::refine(ImplicitFn* ifn,btScalar accurary,bool cut)
+void btSoftBody::refine(ImplicitFn* ifn, btScalar accurary, bool cut)
{
- const Node* nbase = &m_nodes[0];
- int ncount = m_nodes.size();
- btSymMatrix<int> edges(ncount,-2);
- int newnodes=0;
- int i,j,k,ni;
+ const Node* nbase = &m_nodes[0];
+ int ncount = m_nodes.size();
+ btSymMatrix<int> edges(ncount, -2);
+ int newnodes = 0;
+ int i, j, k, ni;
- /* Filter out */
- for(i=0;i<m_links.size();++i)
+ /* Filter out */
+ for (i = 0; i < m_links.size(); ++i)
{
- Link& l=m_links[i];
- if(l.m_bbending)
+ Link& l = m_links[i];
+ if (l.m_bbending)
{
- if(!SameSign(ifn->Eval(l.m_n[0]->m_x),ifn->Eval(l.m_n[1]->m_x)))
+ if (!SameSign(ifn->Eval(l.m_n[0]->m_x), ifn->Eval(l.m_n[1]->m_x)))
{
- btSwap(m_links[i],m_links[m_links.size()-1]);
- m_links.pop_back();--i;
+ btSwap(m_links[i], m_links[m_links.size() - 1]);
+ m_links.pop_back();
+ --i;
}
- }
+ }
}
- /* Fill edges */
- for(i=0;i<m_links.size();++i)
+ /* Fill edges */
+ for (i = 0; i < m_links.size(); ++i)
{
- Link& l=m_links[i];
- edges(int(l.m_n[0]-nbase),int(l.m_n[1]-nbase))=-1;
+ Link& l = m_links[i];
+ edges(int(l.m_n[0] - nbase), int(l.m_n[1] - nbase)) = -1;
}
- for(i=0;i<m_faces.size();++i)
- {
- Face& f=m_faces[i];
- edges(int(f.m_n[0]-nbase),int(f.m_n[1]-nbase))=-1;
- edges(int(f.m_n[1]-nbase),int(f.m_n[2]-nbase))=-1;
- edges(int(f.m_n[2]-nbase),int(f.m_n[0]-nbase))=-1;
+ for (i = 0; i < m_faces.size(); ++i)
+ {
+ Face& f = m_faces[i];
+ edges(int(f.m_n[0] - nbase), int(f.m_n[1] - nbase)) = -1;
+ edges(int(f.m_n[1] - nbase), int(f.m_n[2] - nbase)) = -1;
+ edges(int(f.m_n[2] - nbase), int(f.m_n[0] - nbase)) = -1;
}
- /* Intersect */
- for(i=0;i<ncount;++i)
+ /* Intersect */
+ for (i = 0; i < ncount; ++i)
{
- for(j=i+1;j<ncount;++j)
+ for (j = i + 1; j < ncount; ++j)
{
- if(edges(i,j)==-1)
+ if (edges(i, j) == -1)
{
- Node& a=m_nodes[i];
- Node& b=m_nodes[j];
- const btScalar t=ImplicitSolve(ifn,a.m_x,b.m_x,accurary);
- if(t>0)
+ Node& a = m_nodes[i];
+ Node& b = m_nodes[j];
+ const btScalar t = ImplicitSolve(ifn, a.m_x, b.m_x, accurary);
+ if (t > 0)
{
- const btVector3 x=Lerp(a.m_x,b.m_x,t);
- const btVector3 v=Lerp(a.m_v,b.m_v,t);
- btScalar m=0;
- if(a.m_im>0)
+ const btVector3 x = Lerp(a.m_x, b.m_x, t);
+ const btVector3 v = Lerp(a.m_v, b.m_v, t);
+ btScalar m = 0;
+ if (a.m_im > 0)
{
- if(b.m_im>0)
+ if (b.m_im > 0)
{
- const btScalar ma=1/a.m_im;
- const btScalar mb=1/b.m_im;
- const btScalar mc=Lerp(ma,mb,t);
- const btScalar f=(ma+mb)/(ma+mb+mc);
- a.m_im=1/(ma*f);
- b.m_im=1/(mb*f);
- m=mc*f;
+ const btScalar ma = 1 / a.m_im;
+ const btScalar mb = 1 / b.m_im;
+ const btScalar mc = Lerp(ma, mb, t);
+ const btScalar f = (ma + mb) / (ma + mb + mc);
+ a.m_im = 1 / (ma * f);
+ b.m_im = 1 / (mb * f);
+ m = mc * f;
}
else
- { a.m_im/=0.5f;m=1/a.m_im; }
+ {
+ a.m_im /= 0.5f;
+ m = 1 / a.m_im;
+ }
}
else
{
- if(b.m_im>0)
- { b.m_im/=0.5f;m=1/b.m_im; }
+ if (b.m_im > 0)
+ {
+ b.m_im /= 0.5f;
+ m = 1 / b.m_im;
+ }
else
- m=0;
+ m = 0;
}
- appendNode(x,m);
- edges(i,j)=m_nodes.size()-1;
- m_nodes[edges(i,j)].m_v=v;
+ appendNode(x, m);
+ edges(i, j) = m_nodes.size() - 1;
+ m_nodes[edges(i, j)].m_v = v;
++newnodes;
}
}
}
}
- nbase=&m_nodes[0];
- /* Refine links */
- for(i=0,ni=m_links.size();i<ni;++i)
+ nbase = &m_nodes[0];
+ /* Refine links */
+ for (i = 0, ni = m_links.size(); i < ni; ++i)
{
- Link& feat=m_links[i];
- const int idx[]={ int(feat.m_n[0]-nbase),
- int(feat.m_n[1]-nbase)};
- if((idx[0]<ncount)&&(idx[1]<ncount))
+ Link& feat = m_links[i];
+ const int idx[] = {int(feat.m_n[0] - nbase),
+ int(feat.m_n[1] - nbase)};
+ if ((idx[0] < ncount) && (idx[1] < ncount))
{
- const int ni=edges(idx[0],idx[1]);
- if(ni>0)
+ const int ni = edges(idx[0], idx[1]);
+ if (ni > 0)
{
appendLink(i);
- Link* pft[]={ &m_links[i],
- &m_links[m_links.size()-1]};
- pft[0]->m_n[0]=&m_nodes[idx[0]];
- pft[0]->m_n[1]=&m_nodes[ni];
- pft[1]->m_n[0]=&m_nodes[ni];
- pft[1]->m_n[1]=&m_nodes[idx[1]];
+ Link* pft[] = {&m_links[i],
+ &m_links[m_links.size() - 1]};
+ pft[0]->m_n[0] = &m_nodes[idx[0]];
+ pft[0]->m_n[1] = &m_nodes[ni];
+ pft[1]->m_n[0] = &m_nodes[ni];
+ pft[1]->m_n[1] = &m_nodes[idx[1]];
}
}
}
- /* Refine faces */
- for(i=0;i<m_faces.size();++i)
+ /* Refine faces */
+ for (i = 0; i < m_faces.size(); ++i)
{
- const Face& feat=m_faces[i];
- const int idx[]={ int(feat.m_n[0]-nbase),
- int(feat.m_n[1]-nbase),
- int(feat.m_n[2]-nbase)};
- for(j=2,k=0;k<3;j=k++)
+ const Face& feat = m_faces[i];
+ const int idx[] = {int(feat.m_n[0] - nbase),
+ int(feat.m_n[1] - nbase),
+ int(feat.m_n[2] - nbase)};
+ for (j = 2, k = 0; k < 3; j = k++)
{
- if((idx[j]<ncount)&&(idx[k]<ncount))
+ if ((idx[j] < ncount) && (idx[k] < ncount))
{
- const int ni=edges(idx[j],idx[k]);
- if(ni>0)
+ const int ni = edges(idx[j], idx[k]);
+ if (ni > 0)
{
appendFace(i);
- const int l=(k+1)%3;
- Face* pft[]={ &m_faces[i],
- &m_faces[m_faces.size()-1]};
- pft[0]->m_n[0]=&m_nodes[idx[l]];
- pft[0]->m_n[1]=&m_nodes[idx[j]];
- pft[0]->m_n[2]=&m_nodes[ni];
- pft[1]->m_n[0]=&m_nodes[ni];
- pft[1]->m_n[1]=&m_nodes[idx[k]];
- pft[1]->m_n[2]=&m_nodes[idx[l]];
- appendLink(ni,idx[l],pft[0]->m_material);
- --i;break;
+ const int l = (k + 1) % 3;
+ Face* pft[] = {&m_faces[i],
+ &m_faces[m_faces.size() - 1]};
+ pft[0]->m_n[0] = &m_nodes[idx[l]];
+ pft[0]->m_n[1] = &m_nodes[idx[j]];
+ pft[0]->m_n[2] = &m_nodes[ni];
+ pft[1]->m_n[0] = &m_nodes[ni];
+ pft[1]->m_n[1] = &m_nodes[idx[k]];
+ pft[1]->m_n[2] = &m_nodes[idx[l]];
+ appendLink(ni, idx[l], pft[0]->m_material);
+ --i;
+ break;
}
}
}
}
- /* Cut */
- if(cut)
- {
- btAlignedObjectArray<int> cnodes;
- const int pcount=ncount;
- int i;
- ncount=m_nodes.size();
- cnodes.resize(ncount,0);
- /* Nodes */
- for(i=0;i<ncount;++i)
+ /* Cut */
+ if (cut)
+ {
+ btAlignedObjectArray<int> cnodes;
+ const int pcount = ncount;
+ int i;
+ ncount = m_nodes.size();
+ cnodes.resize(ncount, 0);
+ /* Nodes */
+ for (i = 0; i < ncount; ++i)
{
- const btVector3 x=m_nodes[i].m_x;
- if((i>=pcount)||(btFabs(ifn->Eval(x))<accurary))
+ const btVector3 x = m_nodes[i].m_x;
+ if ((i >= pcount) || (btFabs(ifn->Eval(x)) < accurary))
{
- const btVector3 v=m_nodes[i].m_v;
- btScalar m=getMass(i);
- if(m>0) { m*=0.5f;m_nodes[i].m_im/=0.5f; }
- appendNode(x,m);
- cnodes[i]=m_nodes.size()-1;
- m_nodes[cnodes[i]].m_v=v;
+ const btVector3 v = m_nodes[i].m_v;
+ btScalar m = getMass(i);
+ if (m > 0)
+ {
+ m *= 0.5f;
+ m_nodes[i].m_im /= 0.5f;
+ }
+ appendNode(x, m);
+ cnodes[i] = m_nodes.size() - 1;
+ m_nodes[cnodes[i]].m_v = v;
}
}
- nbase=&m_nodes[0];
- /* Links */
- for(i=0,ni=m_links.size();i<ni;++i)
+ nbase = &m_nodes[0];
+ /* Links */
+ for (i = 0, ni = m_links.size(); i < ni; ++i)
{
- const int id[]={ int(m_links[i].m_n[0]-nbase),
- int(m_links[i].m_n[1]-nbase)};
- int todetach=0;
- if(cnodes[id[0]]&&cnodes[id[1]])
+ const int id[] = {int(m_links[i].m_n[0] - nbase),
+ int(m_links[i].m_n[1] - nbase)};
+ int todetach = 0;
+ if (cnodes[id[0]] && cnodes[id[1]])
{
appendLink(i);
- todetach=m_links.size()-1;
+ todetach = m_links.size() - 1;
}
else
{
- if(( (ifn->Eval(m_nodes[id[0]].m_x)<accurary)&&
- (ifn->Eval(m_nodes[id[1]].m_x)<accurary)))
- todetach=i;
+ if (((ifn->Eval(m_nodes[id[0]].m_x) < accurary) &&
+ (ifn->Eval(m_nodes[id[1]].m_x) < accurary)))
+ todetach = i;
}
- if(todetach)
+ if (todetach)
{
- Link& l=m_links[todetach];
- for(int j=0;j<2;++j)
+ Link& l = m_links[todetach];
+ for (int j = 0; j < 2; ++j)
{
- int cn=cnodes[int(l.m_n[j]-nbase)];
- if(cn) l.m_n[j]=&m_nodes[cn];
- }
+ int cn = cnodes[int(l.m_n[j] - nbase)];
+ if (cn) l.m_n[j] = &m_nodes[cn];
+ }
}
}
- /* Faces */
- for(i=0,ni=m_faces.size();i<ni;++i)
+ /* Faces */
+ for (i = 0, ni = m_faces.size(); i < ni; ++i)
{
- Node** n= m_faces[i].m_n;
- if( (ifn->Eval(n[0]->m_x)<accurary)&&
- (ifn->Eval(n[1]->m_x)<accurary)&&
- (ifn->Eval(n[2]->m_x)<accurary))
+ Node** n = m_faces[i].m_n;
+ if ((ifn->Eval(n[0]->m_x) < accurary) &&
+ (ifn->Eval(n[1]->m_x) < accurary) &&
+ (ifn->Eval(n[2]->m_x) < accurary))
{
- for(int j=0;j<3;++j)
+ for (int j = 0; j < 3; ++j)
{
- int cn=cnodes[int(n[j]-nbase)];
- if(cn) n[j]=&m_nodes[cn];
+ int cn = cnodes[int(n[j] - nbase)];
+ if (cn) n[j] = &m_nodes[cn];
}
}
}
- /* Clean orphans */
- int nnodes=m_nodes.size();
- btAlignedObjectArray<int> ranks;
- btAlignedObjectArray<int> todelete;
- ranks.resize(nnodes,0);
- for(i=0,ni=m_links.size();i<ni;++i)
+ /* Clean orphans */
+ int nnodes = m_nodes.size();
+ btAlignedObjectArray<int> ranks;
+ btAlignedObjectArray<int> todelete;
+ ranks.resize(nnodes, 0);
+ for (i = 0, ni = m_links.size(); i < ni; ++i)
{
- for(int j=0;j<2;++j) ranks[int(m_links[i].m_n[j]-nbase)]++;
+ for (int j = 0; j < 2; ++j) ranks[int(m_links[i].m_n[j] - nbase)]++;
}
- for(i=0,ni=m_faces.size();i<ni;++i)
+ for (i = 0, ni = m_faces.size(); i < ni; ++i)
{
- for(int j=0;j<3;++j) ranks[int(m_faces[i].m_n[j]-nbase)]++;
+ for (int j = 0; j < 3; ++j) ranks[int(m_faces[i].m_n[j] - nbase)]++;
}
- for(i=0;i<m_links.size();++i)
+ for (i = 0; i < m_links.size(); ++i)
{
- const int id[]={ int(m_links[i].m_n[0]-nbase),
- int(m_links[i].m_n[1]-nbase)};
- const bool sg[]={ ranks[id[0]]==1,
- ranks[id[1]]==1};
- if(sg[0]||sg[1])
+ const int id[] = {int(m_links[i].m_n[0] - nbase),
+ int(m_links[i].m_n[1] - nbase)};
+ const bool sg[] = {ranks[id[0]] == 1,
+ ranks[id[1]] == 1};
+ if (sg[0] || sg[1])
{
--ranks[id[0]];
--ranks[id[1]];
- btSwap(m_links[i],m_links[m_links.size()-1]);
- m_links.pop_back();--i;
+ btSwap(m_links[i], m_links[m_links.size() - 1]);
+ m_links.pop_back();
+ --i;
}
}
#if 0
@@ -1631,679 +1651,675 @@ void btSoftBody::refine(ImplicitFn* ifn,btScalar accurary,bool cut)
}
#endif
}
- m_bUpdateRtCst=true;
+ m_bUpdateRtCst = true;
}
//
-bool btSoftBody::cutLink(const Node* node0,const Node* node1,btScalar position)
+bool btSoftBody::cutLink(const Node* node0, const Node* node1, btScalar position)
{
- return(cutLink(int(node0-&m_nodes[0]),int(node1-&m_nodes[0]),position));
+ return (cutLink(int(node0 - &m_nodes[0]), int(node1 - &m_nodes[0]), position));
}
//
-bool btSoftBody::cutLink(int node0,int node1,btScalar position)
+bool btSoftBody::cutLink(int node0, int node1, btScalar position)
{
- bool done=false;
- int i,ni;
-// const btVector3 d=m_nodes[node0].m_x-m_nodes[node1].m_x;
- const btVector3 x=Lerp(m_nodes[node0].m_x,m_nodes[node1].m_x,position);
- const btVector3 v=Lerp(m_nodes[node0].m_v,m_nodes[node1].m_v,position);
- const btScalar m=1;
- appendNode(x,m);
- appendNode(x,m);
- Node* pa=&m_nodes[node0];
- Node* pb=&m_nodes[node1];
- Node* pn[2]={ &m_nodes[m_nodes.size()-2],
- &m_nodes[m_nodes.size()-1]};
- pn[0]->m_v=v;
- pn[1]->m_v=v;
- for(i=0,ni=m_links.size();i<ni;++i)
+ bool done = false;
+ int i, ni;
+ // const btVector3 d=m_nodes[node0].m_x-m_nodes[node1].m_x;
+ const btVector3 x = Lerp(m_nodes[node0].m_x, m_nodes[node1].m_x, position);
+ const btVector3 v = Lerp(m_nodes[node0].m_v, m_nodes[node1].m_v, position);
+ const btScalar m = 1;
+ appendNode(x, m);
+ appendNode(x, m);
+ Node* pa = &m_nodes[node0];
+ Node* pb = &m_nodes[node1];
+ Node* pn[2] = {&m_nodes[m_nodes.size() - 2],
+ &m_nodes[m_nodes.size() - 1]};
+ pn[0]->m_v = v;
+ pn[1]->m_v = v;
+ for (i = 0, ni = m_links.size(); i < ni; ++i)
{
- const int mtch=MatchEdge(m_links[i].m_n[0],m_links[i].m_n[1],pa,pb);
- if(mtch!=-1)
+ const int mtch = MatchEdge(m_links[i].m_n[0], m_links[i].m_n[1], pa, pb);
+ if (mtch != -1)
{
appendLink(i);
- Link* pft[]={&m_links[i],&m_links[m_links.size()-1]};
- pft[0]->m_n[1]=pn[mtch];
- pft[1]->m_n[0]=pn[1-mtch];
- done=true;
+ Link* pft[] = {&m_links[i], &m_links[m_links.size() - 1]};
+ pft[0]->m_n[1] = pn[mtch];
+ pft[1]->m_n[0] = pn[1 - mtch];
+ done = true;
}
}
- for(i=0,ni=m_faces.size();i<ni;++i)
+ for (i = 0, ni = m_faces.size(); i < ni; ++i)
{
- for(int k=2,l=0;l<3;k=l++)
+ for (int k = 2, l = 0; l < 3; k = l++)
{
- const int mtch=MatchEdge(m_faces[i].m_n[k],m_faces[i].m_n[l],pa,pb);
- if(mtch!=-1)
+ const int mtch = MatchEdge(m_faces[i].m_n[k], m_faces[i].m_n[l], pa, pb);
+ if (mtch != -1)
{
appendFace(i);
- Face* pft[]={&m_faces[i],&m_faces[m_faces.size()-1]};
- pft[0]->m_n[l]=pn[mtch];
- pft[1]->m_n[k]=pn[1-mtch];
- appendLink(pn[0],pft[0]->m_n[(l+1)%3],pft[0]->m_material,true);
- appendLink(pn[1],pft[0]->m_n[(l+1)%3],pft[0]->m_material,true);
+ Face* pft[] = {&m_faces[i], &m_faces[m_faces.size() - 1]};
+ pft[0]->m_n[l] = pn[mtch];
+ pft[1]->m_n[k] = pn[1 - mtch];
+ appendLink(pn[0], pft[0]->m_n[(l + 1) % 3], pft[0]->m_material, true);
+ appendLink(pn[1], pft[0]->m_n[(l + 1) % 3], pft[0]->m_material, true);
}
}
}
- if(!done)
+ if (!done)
{
m_ndbvt.remove(pn[0]->m_leaf);
m_ndbvt.remove(pn[1]->m_leaf);
m_nodes.pop_back();
m_nodes.pop_back();
}
- return(done);
+ return (done);
}
//
-bool btSoftBody::rayTest(const btVector3& rayFrom,
- const btVector3& rayTo,
- sRayCast& results)
+bool btSoftBody::rayTest(const btVector3& rayFrom,
+ const btVector3& rayTo,
+ sRayCast& results)
{
- if(m_faces.size()&&m_fdbvt.empty())
+ if (m_faces.size() && m_fdbvt.empty())
initializeFaceTree();
- results.body = this;
+ results.body = this;
results.fraction = 1.f;
- results.feature = eFeature::None;
- results.index = -1;
+ results.feature = eFeature::None;
+ results.index = -1;
- return(rayTest(rayFrom,rayTo,results.fraction,results.feature,results.index,false)!=0);
+ return (rayTest(rayFrom, rayTo, results.fraction, results.feature, results.index, false) != 0);
}
//
-void btSoftBody::setSolver(eSolverPresets::_ preset)
+void btSoftBody::setSolver(eSolverPresets::_ preset)
{
m_cfg.m_vsequence.clear();
m_cfg.m_psequence.clear();
m_cfg.m_dsequence.clear();
- switch(preset)
- {
- case eSolverPresets::Positions:
- m_cfg.m_psequence.push_back(ePSolver::Anchors);
- m_cfg.m_psequence.push_back(ePSolver::RContacts);
- m_cfg.m_psequence.push_back(ePSolver::SContacts);
- m_cfg.m_psequence.push_back(ePSolver::Linear);
- break;
- case eSolverPresets::Velocities:
- m_cfg.m_vsequence.push_back(eVSolver::Linear);
-
- m_cfg.m_psequence.push_back(ePSolver::Anchors);
- m_cfg.m_psequence.push_back(ePSolver::RContacts);
- m_cfg.m_psequence.push_back(ePSolver::SContacts);
-
- m_cfg.m_dsequence.push_back(ePSolver::Linear);
- break;
+ switch (preset)
+ {
+ case eSolverPresets::Positions:
+ m_cfg.m_psequence.push_back(ePSolver::Anchors);
+ m_cfg.m_psequence.push_back(ePSolver::RContacts);
+ m_cfg.m_psequence.push_back(ePSolver::SContacts);
+ m_cfg.m_psequence.push_back(ePSolver::Linear);
+ break;
+ case eSolverPresets::Velocities:
+ m_cfg.m_vsequence.push_back(eVSolver::Linear);
+
+ m_cfg.m_psequence.push_back(ePSolver::Anchors);
+ m_cfg.m_psequence.push_back(ePSolver::RContacts);
+ m_cfg.m_psequence.push_back(ePSolver::SContacts);
+
+ m_cfg.m_dsequence.push_back(ePSolver::Linear);
+ break;
}
}
//
-void btSoftBody::predictMotion(btScalar dt)
+void btSoftBody::predictMotion(btScalar dt)
{
+ int i, ni;
- int i,ni;
-
- /* Update */
- if(m_bUpdateRtCst)
+ /* Update */
+ if (m_bUpdateRtCst)
{
- m_bUpdateRtCst=false;
+ m_bUpdateRtCst = false;
updateConstants();
m_fdbvt.clear();
- if(m_cfg.collisions&fCollision::VF_SS)
+ if (m_cfg.collisions & fCollision::VF_SS)
{
- initializeFaceTree();
+ initializeFaceTree();
}
}
- /* Prepare */
- m_sst.sdt = dt*m_cfg.timescale;
- m_sst.isdt = 1/m_sst.sdt;
- m_sst.velmrg = m_sst.sdt*3;
- m_sst.radmrg = getCollisionShape()->getMargin();
- m_sst.updmrg = m_sst.radmrg*(btScalar)0.25;
- /* Forces */
- addVelocity(m_worldInfo->m_gravity*m_sst.sdt);
+ /* Prepare */
+ m_sst.sdt = dt * m_cfg.timescale;
+ m_sst.isdt = 1 / m_sst.sdt;
+ m_sst.velmrg = m_sst.sdt * 3;
+ m_sst.radmrg = getCollisionShape()->getMargin();
+ m_sst.updmrg = m_sst.radmrg * (btScalar)0.25;
+ /* Forces */
+ addVelocity(m_worldInfo->m_gravity * m_sst.sdt);
applyForces();
- /* Integrate */
- for(i=0,ni=m_nodes.size();i<ni;++i)
+ /* Integrate */
+ for (i = 0, ni = m_nodes.size(); i < ni; ++i)
{
- Node& n=m_nodes[i];
- n.m_q = n.m_x;
- btVector3 deltaV = n.m_f*n.m_im*m_sst.sdt;
+ Node& n = m_nodes[i];
+ n.m_q = n.m_x;
+ btVector3 deltaV = n.m_f * n.m_im * m_sst.sdt;
{
btScalar maxDisplacement = m_worldInfo->m_maxDisplacement;
- btScalar clampDeltaV = maxDisplacement/m_sst.sdt;
- for (int c=0;c<3;c++)
+ btScalar clampDeltaV = maxDisplacement / m_sst.sdt;
+ for (int c = 0; c < 3; c++)
{
- if (deltaV[c]>clampDeltaV)
+ if (deltaV[c] > clampDeltaV)
{
deltaV[c] = clampDeltaV;
}
- if (deltaV[c]<-clampDeltaV)
+ if (deltaV[c] < -clampDeltaV)
{
- deltaV[c]=-clampDeltaV;
+ deltaV[c] = -clampDeltaV;
}
}
}
- n.m_v += deltaV;
- n.m_x += n.m_v*m_sst.sdt;
- n.m_f = btVector3(0,0,0);
+ n.m_v += deltaV;
+ n.m_x += n.m_v * m_sst.sdt;
+ n.m_f = btVector3(0, 0, 0);
}
- /* Clusters */
+ /* Clusters */
updateClusters();
- /* Bounds */
- updateBounds();
- /* Nodes */
- ATTRIBUTE_ALIGNED16(btDbvtVolume) vol;
- for(i=0,ni=m_nodes.size();i<ni;++i)
- {
- Node& n=m_nodes[i];
- vol = btDbvtVolume::FromCR(n.m_x,m_sst.radmrg);
- m_ndbvt.update( n.m_leaf,
- vol,
- n.m_v*m_sst.velmrg,
- m_sst.updmrg);
- }
- /* Faces */
- if(!m_fdbvt.empty())
- {
- for(int i=0;i<m_faces.size();++i)
- {
- Face& f=m_faces[i];
- const btVector3 v=( f.m_n[0]->m_v+
- f.m_n[1]->m_v+
- f.m_n[2]->m_v)/3;
- vol = VolumeOf(f,m_sst.radmrg);
- m_fdbvt.update( f.m_leaf,
- vol,
- v*m_sst.velmrg,
- m_sst.updmrg);
- }
- }
- /* Pose */
+ /* Bounds */
+ updateBounds();
+ /* Nodes */
+ ATTRIBUTE_ALIGNED16(btDbvtVolume)
+ vol;
+ for (i = 0, ni = m_nodes.size(); i < ni; ++i)
+ {
+ Node& n = m_nodes[i];
+ vol = btDbvtVolume::FromCR(n.m_x, m_sst.radmrg);
+ m_ndbvt.update(n.m_leaf,
+ vol,
+ n.m_v * m_sst.velmrg,
+ m_sst.updmrg);
+ }
+ /* Faces */
+ if (!m_fdbvt.empty())
+ {
+ for (int i = 0; i < m_faces.size(); ++i)
+ {
+ Face& f = m_faces[i];
+ const btVector3 v = (f.m_n[0]->m_v +
+ f.m_n[1]->m_v +
+ f.m_n[2]->m_v) /
+ 3;
+ vol = VolumeOf(f, m_sst.radmrg);
+ m_fdbvt.update(f.m_leaf,
+ vol,
+ v * m_sst.velmrg,
+ m_sst.updmrg);
+ }
+ }
+ /* Pose */
updatePose();
- /* Match */
- if(m_pose.m_bframe&&(m_cfg.kMT>0))
+ /* Match */
+ if (m_pose.m_bframe && (m_cfg.kMT > 0))
{
- const btMatrix3x3 posetrs=m_pose.m_rot;
- for(int i=0,ni=m_nodes.size();i<ni;++i)
+ const btMatrix3x3 posetrs = m_pose.m_rot;
+ for (int i = 0, ni = m_nodes.size(); i < ni; ++i)
{
- Node& n=m_nodes[i];
- if(n.m_im>0)
+ Node& n = m_nodes[i];
+ if (n.m_im > 0)
{
- const btVector3 x=posetrs*m_pose.m_pos[i]+m_pose.m_com;
- n.m_x=Lerp(n.m_x,x,m_cfg.kMT);
+ const btVector3 x = posetrs * m_pose.m_pos[i] + m_pose.m_com;
+ n.m_x = Lerp(n.m_x, x, m_cfg.kMT);
}
}
}
- /* Clear contacts */
+ /* Clear contacts */
m_rcontacts.resize(0);
m_scontacts.resize(0);
- /* Optimize dbvt's */
+ /* Optimize dbvt's */
m_ndbvt.optimizeIncremental(1);
m_fdbvt.optimizeIncremental(1);
m_cdbvt.optimizeIncremental(1);
}
//
-void btSoftBody::solveConstraints()
+void btSoftBody::solveConstraints()
{
-
- /* Apply clusters */
+ /* Apply clusters */
applyClusters(false);
- /* Prepare links */
+ /* Prepare links */
- int i,ni;
+ int i, ni;
- for(i=0,ni=m_links.size();i<ni;++i)
+ for (i = 0, ni = m_links.size(); i < ni; ++i)
{
- Link& l=m_links[i];
- l.m_c3 = l.m_n[1]->m_q-l.m_n[0]->m_q;
- l.m_c2 = 1/(l.m_c3.length2()*l.m_c0);
+ Link& l = m_links[i];
+ l.m_c3 = l.m_n[1]->m_q - l.m_n[0]->m_q;
+ l.m_c2 = 1 / (l.m_c3.length2() * l.m_c0);
}
- /* Prepare anchors */
- for(i=0,ni=m_anchors.size();i<ni;++i)
+ /* Prepare anchors */
+ for (i = 0, ni = m_anchors.size(); i < ni; ++i)
{
- Anchor& a=m_anchors[i];
- const btVector3 ra=a.m_body->getWorldTransform().getBasis()*a.m_local;
- a.m_c0 = ImpulseMatrix( m_sst.sdt,
- a.m_node->m_im,
- a.m_body->getInvMass(),
- a.m_body->getInvInertiaTensorWorld(),
- ra);
- a.m_c1 = ra;
- a.m_c2 = m_sst.sdt*a.m_node->m_im;
+ Anchor& a = m_anchors[i];
+ const btVector3 ra = a.m_body->getWorldTransform().getBasis() * a.m_local;
+ a.m_c0 = ImpulseMatrix(m_sst.sdt,
+ a.m_node->m_im,
+ a.m_body->getInvMass(),
+ a.m_body->getInvInertiaTensorWorld(),
+ ra);
+ a.m_c1 = ra;
+ a.m_c2 = m_sst.sdt * a.m_node->m_im;
a.m_body->activate();
}
- /* Solve velocities */
- if(m_cfg.viterations>0)
+ /* Solve velocities */
+ if (m_cfg.viterations > 0)
{
- /* Solve */
- for(int isolve=0;isolve<m_cfg.viterations;++isolve)
+ /* Solve */
+ for (int isolve = 0; isolve < m_cfg.viterations; ++isolve)
{
- for(int iseq=0;iseq<m_cfg.m_vsequence.size();++iseq)
+ for (int iseq = 0; iseq < m_cfg.m_vsequence.size(); ++iseq)
{
- getSolver(m_cfg.m_vsequence[iseq])(this,1);
+ getSolver(m_cfg.m_vsequence[iseq])(this, 1);
}
}
- /* Update */
- for(i=0,ni=m_nodes.size();i<ni;++i)
+ /* Update */
+ for (i = 0, ni = m_nodes.size(); i < ni; ++i)
{
- Node& n=m_nodes[i];
- n.m_x = n.m_q+n.m_v*m_sst.sdt;
+ Node& n = m_nodes[i];
+ n.m_x = n.m_q + n.m_v * m_sst.sdt;
}
}
- /* Solve positions */
- if(m_cfg.piterations>0)
+ /* Solve positions */
+ if (m_cfg.piterations > 0)
{
- for(int isolve=0;isolve<m_cfg.piterations;++isolve)
+ for (int isolve = 0; isolve < m_cfg.piterations; ++isolve)
{
- const btScalar ti=isolve/(btScalar)m_cfg.piterations;
- for(int iseq=0;iseq<m_cfg.m_psequence.size();++iseq)
+ const btScalar ti = isolve / (btScalar)m_cfg.piterations;
+ for (int iseq = 0; iseq < m_cfg.m_psequence.size(); ++iseq)
{
- getSolver(m_cfg.m_psequence[iseq])(this,1,ti);
+ getSolver(m_cfg.m_psequence[iseq])(this, 1, ti);
}
}
- const btScalar vc=m_sst.isdt*(1-m_cfg.kDP);
- for(i=0,ni=m_nodes.size();i<ni;++i)
+ const btScalar vc = m_sst.isdt * (1 - m_cfg.kDP);
+ for (i = 0, ni = m_nodes.size(); i < ni; ++i)
{
- Node& n=m_nodes[i];
- n.m_v = (n.m_x-n.m_q)*vc;
- n.m_f = btVector3(0,0,0);
+ Node& n = m_nodes[i];
+ n.m_v = (n.m_x - n.m_q) * vc;
+ n.m_f = btVector3(0, 0, 0);
}
}
- /* Solve drift */
- if(m_cfg.diterations>0)
+ /* Solve drift */
+ if (m_cfg.diterations > 0)
{
- const btScalar vcf=m_cfg.kVCF*m_sst.isdt;
- for(i=0,ni=m_nodes.size();i<ni;++i)
+ const btScalar vcf = m_cfg.kVCF * m_sst.isdt;
+ for (i = 0, ni = m_nodes.size(); i < ni; ++i)
{
- Node& n=m_nodes[i];
- n.m_q = n.m_x;
+ Node& n = m_nodes[i];
+ n.m_q = n.m_x;
}
- for(int idrift=0;idrift<m_cfg.diterations;++idrift)
+ for (int idrift = 0; idrift < m_cfg.diterations; ++idrift)
{
- for(int iseq=0;iseq<m_cfg.m_dsequence.size();++iseq)
+ for (int iseq = 0; iseq < m_cfg.m_dsequence.size(); ++iseq)
{
- getSolver(m_cfg.m_dsequence[iseq])(this,1,0);
+ getSolver(m_cfg.m_dsequence[iseq])(this, 1, 0);
}
}
- for(int i=0,ni=m_nodes.size();i<ni;++i)
+ for (int i = 0, ni = m_nodes.size(); i < ni; ++i)
{
- Node& n=m_nodes[i];
- n.m_v += (n.m_x-n.m_q)*vcf;
+ Node& n = m_nodes[i];
+ n.m_v += (n.m_x - n.m_q) * vcf;
}
}
- /* Apply clusters */
+ /* Apply clusters */
dampClusters();
applyClusters(true);
}
//
-void btSoftBody::staticSolve(int iterations)
+void btSoftBody::staticSolve(int iterations)
{
- for(int isolve=0;isolve<iterations;++isolve)
+ for (int isolve = 0; isolve < iterations; ++isolve)
{
- for(int iseq=0;iseq<m_cfg.m_psequence.size();++iseq)
+ for (int iseq = 0; iseq < m_cfg.m_psequence.size(); ++iseq)
{
- getSolver(m_cfg.m_psequence[iseq])(this,1,0);
+ getSolver(m_cfg.m_psequence[iseq])(this, 1, 0);
}
}
}
//
-void btSoftBody::solveCommonConstraints(btSoftBody** /*bodies*/,int /*count*/,int /*iterations*/)
+void btSoftBody::solveCommonConstraints(btSoftBody** /*bodies*/, int /*count*/, int /*iterations*/)
{
/// placeholder
}
//
-void btSoftBody::solveClusters(const btAlignedObjectArray<btSoftBody*>& bodies)
+void btSoftBody::solveClusters(const btAlignedObjectArray<btSoftBody*>& bodies)
{
- const int nb=bodies.size();
- int iterations=0;
+ const int nb = bodies.size();
+ int iterations = 0;
int i;
- for(i=0;i<nb;++i)
+ for (i = 0; i < nb; ++i)
{
- iterations=btMax(iterations,bodies[i]->m_cfg.citerations);
+ iterations = btMax(iterations, bodies[i]->m_cfg.citerations);
}
- for(i=0;i<nb;++i)
+ for (i = 0; i < nb; ++i)
{
bodies[i]->prepareClusters(iterations);
}
- for(i=0;i<iterations;++i)
+ for (i = 0; i < iterations; ++i)
{
- const btScalar sor=1;
- for(int j=0;j<nb;++j)
+ const btScalar sor = 1;
+ for (int j = 0; j < nb; ++j)
{
bodies[j]->solveClusters(sor);
}
}
- for(i=0;i<nb;++i)
+ for (i = 0; i < nb; ++i)
{
bodies[i]->cleanupClusters();
}
}
//
-void btSoftBody::integrateMotion()
+void btSoftBody::integrateMotion()
{
- /* Update */
+ /* Update */
updateNormals();
}
//
-btSoftBody::RayFromToCaster::RayFromToCaster(const btVector3& rayFrom,const btVector3& rayTo,btScalar mxt)
+btSoftBody::RayFromToCaster::RayFromToCaster(const btVector3& rayFrom, const btVector3& rayTo, btScalar mxt)
{
m_rayFrom = rayFrom;
- m_rayNormalizedDirection = (rayTo-rayFrom);
+ m_rayNormalizedDirection = (rayTo - rayFrom);
m_rayTo = rayTo;
- m_mint = mxt;
- m_face = 0;
- m_tests = 0;
+ m_mint = mxt;
+ m_face = 0;
+ m_tests = 0;
}
//
-void btSoftBody::RayFromToCaster::Process(const btDbvtNode* leaf)
+void btSoftBody::RayFromToCaster::Process(const btDbvtNode* leaf)
{
- btSoftBody::Face& f=*(btSoftBody::Face*)leaf->data;
- const btScalar t=rayFromToTriangle( m_rayFrom,m_rayTo,m_rayNormalizedDirection,
- f.m_n[0]->m_x,
- f.m_n[1]->m_x,
- f.m_n[2]->m_x,
- m_mint);
- if((t>0)&&(t<m_mint))
- {
- m_mint=t;m_face=&f;
+ btSoftBody::Face& f = *(btSoftBody::Face*)leaf->data;
+ const btScalar t = rayFromToTriangle(m_rayFrom, m_rayTo, m_rayNormalizedDirection,
+ f.m_n[0]->m_x,
+ f.m_n[1]->m_x,
+ f.m_n[2]->m_x,
+ m_mint);
+ if ((t > 0) && (t < m_mint))
+ {
+ m_mint = t;
+ m_face = &f;
}
++m_tests;
}
//
-btScalar btSoftBody::RayFromToCaster::rayFromToTriangle( const btVector3& rayFrom,
- const btVector3& rayTo,
- const btVector3& rayNormalizedDirection,
- const btVector3& a,
- const btVector3& b,
- const btVector3& c,
- btScalar maxt)
+btScalar btSoftBody::RayFromToCaster::rayFromToTriangle(const btVector3& rayFrom,
+ const btVector3& rayTo,
+ const btVector3& rayNormalizedDirection,
+ const btVector3& a,
+ const btVector3& b,
+ const btVector3& c,
+ btScalar maxt)
{
- static const btScalar ceps=-SIMD_EPSILON*10;
- static const btScalar teps=SIMD_EPSILON*10;
+ static const btScalar ceps = -SIMD_EPSILON * 10;
+ static const btScalar teps = SIMD_EPSILON * 10;
- const btVector3 n=btCross(b-a,c-a);
- const btScalar d=btDot(a,n);
- const btScalar den=btDot(rayNormalizedDirection,n);
- if(!btFuzzyZero(den))
+ const btVector3 n = btCross(b - a, c - a);
+ const btScalar d = btDot(a, n);
+ const btScalar den = btDot(rayNormalizedDirection, n);
+ if (!btFuzzyZero(den))
{
- const btScalar num=btDot(rayFrom,n)-d;
- const btScalar t=-num/den;
- if((t>teps)&&(t<maxt))
+ const btScalar num = btDot(rayFrom, n) - d;
+ const btScalar t = -num / den;
+ if ((t > teps) && (t < maxt))
{
- const btVector3 hit=rayFrom+rayNormalizedDirection*t;
- if( (btDot(n,btCross(a-hit,b-hit))>ceps) &&
- (btDot(n,btCross(b-hit,c-hit))>ceps) &&
- (btDot(n,btCross(c-hit,a-hit))>ceps))
+ const btVector3 hit = rayFrom + rayNormalizedDirection * t;
+ if ((btDot(n, btCross(a - hit, b - hit)) > ceps) &&
+ (btDot(n, btCross(b - hit, c - hit)) > ceps) &&
+ (btDot(n, btCross(c - hit, a - hit)) > ceps))
{
- return(t);
+ return (t);
}
}
}
- return(-1);
+ return (-1);
}
//
-void btSoftBody::pointersToIndices()
+void btSoftBody::pointersToIndices()
{
-#define PTR2IDX(_p_,_b_) reinterpret_cast<btSoftBody::Node*>((_p_)-(_b_))
- btSoftBody::Node* base=m_nodes.size() ? &m_nodes[0] : 0;
- int i,ni;
+#define PTR2IDX(_p_, _b_) reinterpret_cast<btSoftBody::Node*>((_p_) - (_b_))
+ btSoftBody::Node* base = m_nodes.size() ? &m_nodes[0] : 0;
+ int i, ni;
- for(i=0,ni=m_nodes.size();i<ni;++i)
+ for (i = 0, ni = m_nodes.size(); i < ni; ++i)
{
- if(m_nodes[i].m_leaf)
+ if (m_nodes[i].m_leaf)
{
- m_nodes[i].m_leaf->data=*(void**)&i;
+ m_nodes[i].m_leaf->data = *(void**)&i;
}
}
- for(i=0,ni=m_links.size();i<ni;++i)
+ for (i = 0, ni = m_links.size(); i < ni; ++i)
{
- m_links[i].m_n[0]=PTR2IDX(m_links[i].m_n[0],base);
- m_links[i].m_n[1]=PTR2IDX(m_links[i].m_n[1],base);
+ m_links[i].m_n[0] = PTR2IDX(m_links[i].m_n[0], base);
+ m_links[i].m_n[1] = PTR2IDX(m_links[i].m_n[1], base);
}
- for(i=0,ni=m_faces.size();i<ni;++i)
+ for (i = 0, ni = m_faces.size(); i < ni; ++i)
{
- m_faces[i].m_n[0]=PTR2IDX(m_faces[i].m_n[0],base);
- m_faces[i].m_n[1]=PTR2IDX(m_faces[i].m_n[1],base);
- m_faces[i].m_n[2]=PTR2IDX(m_faces[i].m_n[2],base);
- if(m_faces[i].m_leaf)
+ m_faces[i].m_n[0] = PTR2IDX(m_faces[i].m_n[0], base);
+ m_faces[i].m_n[1] = PTR2IDX(m_faces[i].m_n[1], base);
+ m_faces[i].m_n[2] = PTR2IDX(m_faces[i].m_n[2], base);
+ if (m_faces[i].m_leaf)
{
- m_faces[i].m_leaf->data=*(void**)&i;
+ m_faces[i].m_leaf->data = *(void**)&i;
}
}
- for(i=0,ni=m_anchors.size();i<ni;++i)
+ for (i = 0, ni = m_anchors.size(); i < ni; ++i)
{
- m_anchors[i].m_node=PTR2IDX(m_anchors[i].m_node,base);
+ m_anchors[i].m_node = PTR2IDX(m_anchors[i].m_node, base);
}
- for(i=0,ni=m_notes.size();i<ni;++i)
+ for (i = 0, ni = m_notes.size(); i < ni; ++i)
{
- for(int j=0;j<m_notes[i].m_rank;++j)
+ for (int j = 0; j < m_notes[i].m_rank; ++j)
{
- m_notes[i].m_nodes[j]=PTR2IDX(m_notes[i].m_nodes[j],base);
+ m_notes[i].m_nodes[j] = PTR2IDX(m_notes[i].m_nodes[j], base);
}
}
-#undef PTR2IDX
+#undef PTR2IDX
}
//
-void btSoftBody::indicesToPointers(const int* map)
+void btSoftBody::indicesToPointers(const int* map)
{
-#define IDX2PTR(_p_,_b_) map?(&(_b_)[map[(((char*)_p_)-(char*)0)]]): \
- (&(_b_)[(((char*)_p_)-(char*)0)])
- btSoftBody::Node* base=m_nodes.size() ? &m_nodes[0]:0;
- int i,ni;
+#define IDX2PTR(_p_, _b_) map ? (&(_b_)[map[(((char*)_p_) - (char*)0)]]) : (&(_b_)[(((char*)_p_) - (char*)0)])
+ btSoftBody::Node* base = m_nodes.size() ? &m_nodes[0] : 0;
+ int i, ni;
- for(i=0,ni=m_nodes.size();i<ni;++i)
+ for (i = 0, ni = m_nodes.size(); i < ni; ++i)
{
- if(m_nodes[i].m_leaf)
+ if (m_nodes[i].m_leaf)
{
- m_nodes[i].m_leaf->data=&m_nodes[i];
+ m_nodes[i].m_leaf->data = &m_nodes[i];
}
}
- for(i=0,ni=m_links.size();i<ni;++i)
+ for (i = 0, ni = m_links.size(); i < ni; ++i)
{
- m_links[i].m_n[0]=IDX2PTR(m_links[i].m_n[0],base);
- m_links[i].m_n[1]=IDX2PTR(m_links[i].m_n[1],base);
+ m_links[i].m_n[0] = IDX2PTR(m_links[i].m_n[0], base);
+ m_links[i].m_n[1] = IDX2PTR(m_links[i].m_n[1], base);
}
- for(i=0,ni=m_faces.size();i<ni;++i)
+ for (i = 0, ni = m_faces.size(); i < ni; ++i)
{
- m_faces[i].m_n[0]=IDX2PTR(m_faces[i].m_n[0],base);
- m_faces[i].m_n[1]=IDX2PTR(m_faces[i].m_n[1],base);
- m_faces[i].m_n[2]=IDX2PTR(m_faces[i].m_n[2],base);
- if(m_faces[i].m_leaf)
+ m_faces[i].m_n[0] = IDX2PTR(m_faces[i].m_n[0], base);
+ m_faces[i].m_n[1] = IDX2PTR(m_faces[i].m_n[1], base);
+ m_faces[i].m_n[2] = IDX2PTR(m_faces[i].m_n[2], base);
+ if (m_faces[i].m_leaf)
{
- m_faces[i].m_leaf->data=&m_faces[i];
+ m_faces[i].m_leaf->data = &m_faces[i];
}
}
- for(i=0,ni=m_anchors.size();i<ni;++i)
+ for (i = 0, ni = m_anchors.size(); i < ni; ++i)
{
- m_anchors[i].m_node=IDX2PTR(m_anchors[i].m_node,base);
+ m_anchors[i].m_node = IDX2PTR(m_anchors[i].m_node, base);
}
- for(i=0,ni=m_notes.size();i<ni;++i)
+ for (i = 0, ni = m_notes.size(); i < ni; ++i)
{
- for(int j=0;j<m_notes[i].m_rank;++j)
+ for (int j = 0; j < m_notes[i].m_rank; ++j)
{
- m_notes[i].m_nodes[j]=IDX2PTR(m_notes[i].m_nodes[j],base);
+ m_notes[i].m_nodes[j] = IDX2PTR(m_notes[i].m_nodes[j], base);
}
}
-#undef IDX2PTR
+#undef IDX2PTR
}
//
-int btSoftBody::rayTest(const btVector3& rayFrom,const btVector3& rayTo,
- btScalar& mint,eFeature::_& feature,int& index,bool bcountonly) const
+int btSoftBody::rayTest(const btVector3& rayFrom, const btVector3& rayTo,
+ btScalar& mint, eFeature::_& feature, int& index, bool bcountonly) const
{
- int cnt=0;
- btVector3 dir = rayTo-rayFrom;
-
+ int cnt = 0;
+ btVector3 dir = rayTo - rayFrom;
+
+ if (bcountonly || m_fdbvt.empty())
+ { /* Full search */
- if(bcountonly||m_fdbvt.empty())
- {/* Full search */
-
- for(int i=0,ni=m_faces.size();i<ni;++i)
+ for (int i = 0, ni = m_faces.size(); i < ni; ++i)
{
- const btSoftBody::Face& f=m_faces[i];
+ const btSoftBody::Face& f = m_faces[i];
- const btScalar t=RayFromToCaster::rayFromToTriangle( rayFrom,rayTo,dir,
- f.m_n[0]->m_x,
- f.m_n[1]->m_x,
- f.m_n[2]->m_x,
- mint);
- if(t>0)
+ const btScalar t = RayFromToCaster::rayFromToTriangle(rayFrom, rayTo, dir,
+ f.m_n[0]->m_x,
+ f.m_n[1]->m_x,
+ f.m_n[2]->m_x,
+ mint);
+ if (t > 0)
{
++cnt;
- if(!bcountonly)
+ if (!bcountonly)
{
- feature=btSoftBody::eFeature::Face;
- index=i;
- mint=t;
+ feature = btSoftBody::eFeature::Face;
+ index = i;
+ mint = t;
}
}
}
}
else
- {/* Use dbvt */
- RayFromToCaster collider(rayFrom,rayTo,mint);
+ { /* Use dbvt */
+ RayFromToCaster collider(rayFrom, rayTo, mint);
- btDbvt::rayTest(m_fdbvt.m_root,rayFrom,rayTo,collider);
- if(collider.m_face)
+ btDbvt::rayTest(m_fdbvt.m_root, rayFrom, rayTo, collider);
+ if (collider.m_face)
{
- mint=collider.m_mint;
- feature=btSoftBody::eFeature::Face;
- index=(int)(collider.m_face-&m_faces[0]);
- cnt=1;
+ mint = collider.m_mint;
+ feature = btSoftBody::eFeature::Face;
+ index = (int)(collider.m_face - &m_faces[0]);
+ cnt = 1;
}
}
- for (int i=0;i<m_tetras.size();i++)
+ for (int i = 0; i < m_tetras.size(); i++)
{
const btSoftBody::Tetra& tet = m_tetras[i];
- int tetfaces[4][3] = {{0,1,2},{0,1,3},{1,2,3},{0,2,3}};
- for (int f=0;f<4;f++)
+ int tetfaces[4][3] = {{0, 1, 2}, {0, 1, 3}, {1, 2, 3}, {0, 2, 3}};
+ for (int f = 0; f < 4; f++)
{
+ int index0 = tetfaces[f][0];
+ int index1 = tetfaces[f][1];
+ int index2 = tetfaces[f][2];
+ btVector3 v0 = tet.m_n[index0]->m_x;
+ btVector3 v1 = tet.m_n[index1]->m_x;
+ btVector3 v2 = tet.m_n[index2]->m_x;
- int index0=tetfaces[f][0];
- int index1=tetfaces[f][1];
- int index2=tetfaces[f][2];
- btVector3 v0=tet.m_n[index0]->m_x;
- btVector3 v1=tet.m_n[index1]->m_x;
- btVector3 v2=tet.m_n[index2]->m_x;
-
-
- const btScalar t=RayFromToCaster::rayFromToTriangle( rayFrom,rayTo,dir,
- v0,v1,v2,
- mint);
- if(t>0)
+ const btScalar t = RayFromToCaster::rayFromToTriangle(rayFrom, rayTo, dir,
+ v0, v1, v2,
+ mint);
+ if (t > 0)
{
++cnt;
- if(!bcountonly)
+ if (!bcountonly)
{
- feature=btSoftBody::eFeature::Tetra;
- index=i;
- mint=t;
+ feature = btSoftBody::eFeature::Tetra;
+ index = i;
+ mint = t;
}
}
}
}
- return(cnt);
+ return (cnt);
}
//
-void btSoftBody::initializeFaceTree()
+void btSoftBody::initializeFaceTree()
{
m_fdbvt.clear();
- for(int i=0;i<m_faces.size();++i)
+ for (int i = 0; i < m_faces.size(); ++i)
{
- Face& f=m_faces[i];
- f.m_leaf=m_fdbvt.insert(VolumeOf(f,0),&f);
+ Face& f = m_faces[i];
+ f.m_leaf = m_fdbvt.insert(VolumeOf(f, 0), &f);
}
}
//
-btVector3 btSoftBody::evaluateCom() const
+btVector3 btSoftBody::evaluateCom() const
{
- btVector3 com(0,0,0);
- if(m_pose.m_bframe)
+ btVector3 com(0, 0, 0);
+ if (m_pose.m_bframe)
{
- for(int i=0,ni=m_nodes.size();i<ni;++i)
+ for (int i = 0, ni = m_nodes.size(); i < ni; ++i)
{
- com+=m_nodes[i].m_x*m_pose.m_wgh[i];
+ com += m_nodes[i].m_x * m_pose.m_wgh[i];
}
}
- return(com);
+ return (com);
}
//
-bool btSoftBody::checkContact( const btCollisionObjectWrapper* colObjWrap,
- const btVector3& x,
- btScalar margin,
- btSoftBody::sCti& cti) const
+bool btSoftBody::checkContact(const btCollisionObjectWrapper* colObjWrap,
+ const btVector3& x,
+ btScalar margin,
+ btSoftBody::sCti& cti) const
{
btVector3 nrm;
- const btCollisionShape *shp = colObjWrap->getCollisionShape();
-// const btRigidBody *tmpRigid = btRigidBody::upcast(colObjWrap->getCollisionObject());
+ const btCollisionShape* shp = colObjWrap->getCollisionShape();
+ // const btRigidBody *tmpRigid = btRigidBody::upcast(colObjWrap->getCollisionObject());
//const btTransform &wtr = tmpRigid ? tmpRigid->getWorldTransform() : colObjWrap->getWorldTransform();
- const btTransform &wtr = colObjWrap->getWorldTransform();
+ const btTransform& wtr = colObjWrap->getWorldTransform();
//todo: check which transform is needed here
- btScalar dst =
- m_worldInfo->m_sparsesdf.Evaluate(
+ btScalar dst =
+ m_worldInfo->m_sparsesdf.Evaluate(
wtr.invXform(x),
shp,
nrm,
margin);
- if(dst<0)
+ if (dst < 0)
{
cti.m_colObj = colObjWrap->getCollisionObject();
- cti.m_normal = wtr.getBasis()*nrm;
- cti.m_offset = -btDot( cti.m_normal, x - cti.m_normal * dst );
- return(true);
+ cti.m_normal = wtr.getBasis() * nrm;
+ cti.m_offset = -btDot(cti.m_normal, x - cti.m_normal * dst);
+ return (true);
}
- return(false);
+ return (false);
}
//
-void btSoftBody::updateNormals()
+void btSoftBody::updateNormals()
{
+ const btVector3 zv(0, 0, 0);
+ int i, ni;
- const btVector3 zv(0,0,0);
- int i,ni;
-
- for(i=0,ni=m_nodes.size();i<ni;++i)
+ for (i = 0, ni = m_nodes.size(); i < ni; ++i)
{
- m_nodes[i].m_n=zv;
+ m_nodes[i].m_n = zv;
}
- for(i=0,ni=m_faces.size();i<ni;++i)
+ for (i = 0, ni = m_faces.size(); i < ni; ++i)
{
- btSoftBody::Face& f=m_faces[i];
- const btVector3 n=btCross(f.m_n[1]->m_x-f.m_n[0]->m_x,
- f.m_n[2]->m_x-f.m_n[0]->m_x);
- f.m_normal=n.normalized();
- f.m_n[0]->m_n+=n;
- f.m_n[1]->m_n+=n;
- f.m_n[2]->m_n+=n;
+ btSoftBody::Face& f = m_faces[i];
+ const btVector3 n = btCross(f.m_n[1]->m_x - f.m_n[0]->m_x,
+ f.m_n[2]->m_x - f.m_n[0]->m_x);
+ f.m_normal = n.normalized();
+ f.m_n[0]->m_n += n;
+ f.m_n[1]->m_n += n;
+ f.m_n[2]->m_n += n;
}
- for(i=0,ni=m_nodes.size();i<ni;++i)
+ for (i = 0, ni = m_nodes.size(); i < ni; ++i)
{
btScalar len = m_nodes[i].m_n.length();
- if (len>SIMD_EPSILON)
+ if (len > SIMD_EPSILON)
m_nodes[i].m_n /= len;
}
}
//
-void btSoftBody::updateBounds()
+void btSoftBody::updateBounds()
{
/*if( m_acceleratedSoftBody )
{
@@ -2317,258 +2333,259 @@ void btSoftBody::updateBounds()
m_bounds[1] = btVector3(1000, 1000, 1000);
} else {*/
- if(m_ndbvt.m_root)
- {
- const btVector3& mins=m_ndbvt.m_root->volume.Mins();
- const btVector3& maxs=m_ndbvt.m_root->volume.Maxs();
- const btScalar csm=getCollisionShape()->getMargin();
- const btVector3 mrg=btVector3( csm,
- csm,
- csm)*1; // ??? to investigate...
- m_bounds[0]=mins-mrg;
- m_bounds[1]=maxs+mrg;
- if(0!=getBroadphaseHandle())
- {
- m_worldInfo->m_broadphase->setAabb( getBroadphaseHandle(),
- m_bounds[0],
- m_bounds[1],
- m_worldInfo->m_dispatcher);
- }
- }
- else
+ if (m_ndbvt.m_root)
+ {
+ const btVector3& mins = m_ndbvt.m_root->volume.Mins();
+ const btVector3& maxs = m_ndbvt.m_root->volume.Maxs();
+ const btScalar csm = getCollisionShape()->getMargin();
+ const btVector3 mrg = btVector3(csm,
+ csm,
+ csm) *
+ 1; // ??? to investigate...
+ m_bounds[0] = mins - mrg;
+ m_bounds[1] = maxs + mrg;
+ if (0 != getBroadphaseHandle())
{
- m_bounds[0]=
- m_bounds[1]=btVector3(0,0,0);
- }
+ m_worldInfo->m_broadphase->setAabb(getBroadphaseHandle(),
+ m_bounds[0],
+ m_bounds[1],
+ m_worldInfo->m_dispatcher);
+ }
+ }
+ else
+ {
+ m_bounds[0] =
+ m_bounds[1] = btVector3(0, 0, 0);
+ }
//}
}
-
//
-void btSoftBody::updatePose()
+void btSoftBody::updatePose()
{
- if(m_pose.m_bframe)
+ if (m_pose.m_bframe)
{
- btSoftBody::Pose& pose=m_pose;
- const btVector3 com=evaluateCom();
- /* Com */
- pose.m_com = com;
- /* Rotation */
- btMatrix3x3 Apq;
- const btScalar eps=SIMD_EPSILON;
- Apq[0]=Apq[1]=Apq[2]=btVector3(0,0,0);
- Apq[0].setX(eps);Apq[1].setY(eps*2);Apq[2].setZ(eps*3);
- for(int i=0,ni=m_nodes.size();i<ni;++i)
+ btSoftBody::Pose& pose = m_pose;
+ const btVector3 com = evaluateCom();
+ /* Com */
+ pose.m_com = com;
+ /* Rotation */
+ btMatrix3x3 Apq;
+ const btScalar eps = SIMD_EPSILON;
+ Apq[0] = Apq[1] = Apq[2] = btVector3(0, 0, 0);
+ Apq[0].setX(eps);
+ Apq[1].setY(eps * 2);
+ Apq[2].setZ(eps * 3);
+ for (int i = 0, ni = m_nodes.size(); i < ni; ++i)
{
- const btVector3 a=pose.m_wgh[i]*(m_nodes[i].m_x-com);
- const btVector3& b=pose.m_pos[i];
- Apq[0]+=a.x()*b;
- Apq[1]+=a.y()*b;
- Apq[2]+=a.z()*b;
+ const btVector3 a = pose.m_wgh[i] * (m_nodes[i].m_x - com);
+ const btVector3& b = pose.m_pos[i];
+ Apq[0] += a.x() * b;
+ Apq[1] += a.y() * b;
+ Apq[2] += a.z() * b;
}
- btMatrix3x3 r,s;
- PolarDecompose(Apq,r,s);
- pose.m_rot=r;
- pose.m_scl=pose.m_aqq*r.transpose()*Apq;
- if(m_cfg.maxvolume>1)
+ btMatrix3x3 r, s;
+ PolarDecompose(Apq, r, s);
+ pose.m_rot = r;
+ pose.m_scl = pose.m_aqq * r.transpose() * Apq;
+ if (m_cfg.maxvolume > 1)
{
- const btScalar idet=Clamp<btScalar>( 1/pose.m_scl.determinant(),
- 1,m_cfg.maxvolume);
- pose.m_scl=Mul(pose.m_scl,idet);
+ const btScalar idet = Clamp<btScalar>(1 / pose.m_scl.determinant(),
+ 1, m_cfg.maxvolume);
+ pose.m_scl = Mul(pose.m_scl, idet);
}
-
}
}
//
-void btSoftBody::updateArea(bool averageArea)
+void btSoftBody::updateArea(bool averageArea)
{
- int i,ni;
+ int i, ni;
- /* Face area */
- for(i=0,ni=m_faces.size();i<ni;++i)
+ /* Face area */
+ for (i = 0, ni = m_faces.size(); i < ni; ++i)
{
- Face& f=m_faces[i];
- f.m_ra = AreaOf(f.m_n[0]->m_x,f.m_n[1]->m_x,f.m_n[2]->m_x);
+ Face& f = m_faces[i];
+ f.m_ra = AreaOf(f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x);
}
-
- /* Node area */
+
+ /* Node area */
if (averageArea)
{
- btAlignedObjectArray<int> counts;
- counts.resize(m_nodes.size(),0);
- for(i=0,ni=m_nodes.size();i<ni;++i)
+ btAlignedObjectArray<int> counts;
+ counts.resize(m_nodes.size(), 0);
+ for (i = 0, ni = m_nodes.size(); i < ni; ++i)
{
- m_nodes[i].m_area = 0;
+ m_nodes[i].m_area = 0;
}
- for(i=0,ni=m_faces.size();i<ni;++i)
+ for (i = 0, ni = m_faces.size(); i < ni; ++i)
{
- btSoftBody::Face& f=m_faces[i];
- for(int j=0;j<3;++j)
+ btSoftBody::Face& f = m_faces[i];
+ for (int j = 0; j < 3; ++j)
{
- const int index=(int)(f.m_n[j]-&m_nodes[0]);
+ const int index = (int)(f.m_n[j] - &m_nodes[0]);
counts[index]++;
- f.m_n[j]->m_area+=btFabs(f.m_ra);
+ f.m_n[j]->m_area += btFabs(f.m_ra);
}
}
- for(i=0,ni=m_nodes.size();i<ni;++i)
+ for (i = 0, ni = m_nodes.size(); i < ni; ++i)
{
- if(counts[i]>0)
- m_nodes[i].m_area/=(btScalar)counts[i];
+ if (counts[i] > 0)
+ m_nodes[i].m_area /= (btScalar)counts[i];
else
- m_nodes[i].m_area=0;
+ m_nodes[i].m_area = 0;
}
}
else
{
// initialize node area as zero
- for(i=0,ni=m_nodes.size();i<ni;++i)
+ for (i = 0, ni = m_nodes.size(); i < ni; ++i)
{
- m_nodes[i].m_area=0;
+ m_nodes[i].m_area = 0;
}
- for(i=0,ni=m_faces.size();i<ni;++i)
+ for (i = 0, ni = m_faces.size(); i < ni; ++i)
{
- btSoftBody::Face& f=m_faces[i];
+ btSoftBody::Face& f = m_faces[i];
- for(int j=0;j<3;++j)
+ for (int j = 0; j < 3; ++j)
{
f.m_n[j]->m_area += f.m_ra;
}
}
- for(i=0,ni=m_nodes.size();i<ni;++i)
+ for (i = 0, ni = m_nodes.size(); i < ni; ++i)
{
m_nodes[i].m_area *= 0.3333333f;
}
}
}
+void btSoftBody::updateLinkConstants()
+{
+ int i, ni;
-void btSoftBody::updateLinkConstants()
-{
- int i,ni;
-
- /* Links */
- for(i=0,ni=m_links.size();i<ni;++i)
+ /* Links */
+ for (i = 0, ni = m_links.size(); i < ni; ++i)
{
- Link& l=m_links[i];
- Material& m=*l.m_material;
- l.m_c0 = (l.m_n[0]->m_im+l.m_n[1]->m_im)/m.m_kLST;
+ Link& l = m_links[i];
+ Material& m = *l.m_material;
+ l.m_c0 = (l.m_n[0]->m_im + l.m_n[1]->m_im) / m.m_kLST;
}
}
-void btSoftBody::updateConstants()
+void btSoftBody::updateConstants()
{
resetLinkRestLengths();
updateLinkConstants();
updateArea();
}
-
-
//
-void btSoftBody::initializeClusters()
+void btSoftBody::initializeClusters()
{
int i;
- for( i=0;i<m_clusters.size();++i)
+ for (i = 0; i < m_clusters.size(); ++i)
{
- Cluster& c=*m_clusters[i];
- c.m_imass=0;
+ Cluster& c = *m_clusters[i];
+ c.m_imass = 0;
c.m_masses.resize(c.m_nodes.size());
- for(int j=0;j<c.m_nodes.size();++j)
+ for (int j = 0; j < c.m_nodes.size(); ++j)
{
- if (c.m_nodes[j]->m_im==0)
+ if (c.m_nodes[j]->m_im == 0)
{
c.m_containsAnchor = true;
- c.m_masses[j] = BT_LARGE_FLOAT;
- } else
+ c.m_masses[j] = BT_LARGE_FLOAT;
+ }
+ else
{
- c.m_masses[j] = btScalar(1.)/c.m_nodes[j]->m_im;
+ c.m_masses[j] = btScalar(1.) / c.m_nodes[j]->m_im;
}
- c.m_imass += c.m_masses[j];
+ c.m_imass += c.m_masses[j];
}
- c.m_imass = btScalar(1.)/c.m_imass;
- c.m_com = btSoftBody::clusterCom(&c);
- c.m_lv = btVector3(0,0,0);
- c.m_av = btVector3(0,0,0);
- c.m_leaf = 0;
- /* Inertia */
- btMatrix3x3& ii=c.m_locii;
- ii[0]=ii[1]=ii[2]=btVector3(0,0,0);
+ c.m_imass = btScalar(1.) / c.m_imass;
+ c.m_com = btSoftBody::clusterCom(&c);
+ c.m_lv = btVector3(0, 0, 0);
+ c.m_av = btVector3(0, 0, 0);
+ c.m_leaf = 0;
+ /* Inertia */
+ btMatrix3x3& ii = c.m_locii;
+ ii[0] = ii[1] = ii[2] = btVector3(0, 0, 0);
{
- int i,ni;
+ int i, ni;
- for(i=0,ni=c.m_nodes.size();i<ni;++i)
+ for (i = 0, ni = c.m_nodes.size(); i < ni; ++i)
{
- const btVector3 k=c.m_nodes[i]->m_x-c.m_com;
- const btVector3 q=k*k;
- const btScalar m=c.m_masses[i];
- ii[0][0] += m*(q[1]+q[2]);
- ii[1][1] += m*(q[0]+q[2]);
- ii[2][2] += m*(q[0]+q[1]);
- ii[0][1] -= m*k[0]*k[1];
- ii[0][2] -= m*k[0]*k[2];
- ii[1][2] -= m*k[1]*k[2];
+ const btVector3 k = c.m_nodes[i]->m_x - c.m_com;
+ const btVector3 q = k * k;
+ const btScalar m = c.m_masses[i];
+ ii[0][0] += m * (q[1] + q[2]);
+ ii[1][1] += m * (q[0] + q[2]);
+ ii[2][2] += m * (q[0] + q[1]);
+ ii[0][1] -= m * k[0] * k[1];
+ ii[0][2] -= m * k[0] * k[2];
+ ii[1][2] -= m * k[1] * k[2];
}
}
- ii[1][0]=ii[0][1];
- ii[2][0]=ii[0][2];
- ii[2][1]=ii[1][2];
-
+ ii[1][0] = ii[0][1];
+ ii[2][0] = ii[0][2];
+ ii[2][1] = ii[1][2];
+
ii = ii.inverse();
- /* Frame */
+ /* Frame */
c.m_framexform.setIdentity();
c.m_framexform.setOrigin(c.m_com);
c.m_framerefs.resize(c.m_nodes.size());
{
int i;
- for(i=0;i<c.m_framerefs.size();++i)
+ for (i = 0; i < c.m_framerefs.size(); ++i)
{
- c.m_framerefs[i]=c.m_nodes[i]->m_x-c.m_com;
+ c.m_framerefs[i] = c.m_nodes[i]->m_x - c.m_com;
}
}
}
}
//
-void btSoftBody::updateClusters()
+void btSoftBody::updateClusters()
{
BT_PROFILE("UpdateClusters");
int i;
- for(i=0;i<m_clusters.size();++i)
+ for (i = 0; i < m_clusters.size(); ++i)
{
- btSoftBody::Cluster& c=*m_clusters[i];
- const int n=c.m_nodes.size();
+ btSoftBody::Cluster& c = *m_clusters[i];
+ const int n = c.m_nodes.size();
//const btScalar invn=1/(btScalar)n;
- if(n)
- {
- /* Frame */
- const btScalar eps=btScalar(0.0001);
- btMatrix3x3 m,r,s;
- m[0]=m[1]=m[2]=btVector3(0,0,0);
- m[0][0]=eps*1;
- m[1][1]=eps*2;
- m[2][2]=eps*3;
- c.m_com=clusterCom(&c);
- for(int i=0;i<c.m_nodes.size();++i)
- {
- const btVector3 a=c.m_nodes[i]->m_x-c.m_com;
- const btVector3& b=c.m_framerefs[i];
- m[0]+=a[0]*b;m[1]+=a[1]*b;m[2]+=a[2]*b;
- }
- PolarDecompose(m,r,s);
+ if (n)
+ {
+ /* Frame */
+ const btScalar eps = btScalar(0.0001);
+ btMatrix3x3 m, r, s;
+ m[0] = m[1] = m[2] = btVector3(0, 0, 0);
+ m[0][0] = eps * 1;
+ m[1][1] = eps * 2;
+ m[2][2] = eps * 3;
+ c.m_com = clusterCom(&c);
+ for (int i = 0; i < c.m_nodes.size(); ++i)
+ {
+ const btVector3 a = c.m_nodes[i]->m_x - c.m_com;
+ const btVector3& b = c.m_framerefs[i];
+ m[0] += a[0] * b;
+ m[1] += a[1] * b;
+ m[2] += a[2] * b;
+ }
+ PolarDecompose(m, r, s);
c.m_framexform.setOrigin(c.m_com);
- c.m_framexform.setBasis(r);
- /* Inertia */
-#if 1/* Constant */
- c.m_invwi=c.m_framexform.getBasis()*c.m_locii*c.m_framexform.getBasis().transpose();
+ c.m_framexform.setBasis(r);
+ /* Inertia */
+#if 1 /* Constant */
+ c.m_invwi = c.m_framexform.getBasis() * c.m_locii * c.m_framexform.getBasis().transpose();
#else
-#if 0/* Sphere */
+#if 0 /* Sphere */
const btScalar rk=(2*c.m_extents.length2())/(5*c.m_imass);
const btVector3 inertia(rk,rk,rk);
const btVector3 iin(btFabs(inertia[0])>SIMD_EPSILON?1/inertia[0]:0,
@@ -2576,186 +2593,181 @@ void btSoftBody::updateClusters()
btFabs(inertia[2])>SIMD_EPSILON?1/inertia[2]:0);
c.m_invwi=c.m_xform.getBasis().scaled(iin)*c.m_xform.getBasis().transpose();
-#else/* Actual */
- c.m_invwi[0]=c.m_invwi[1]=c.m_invwi[2]=btVector3(0,0,0);
- for(int i=0;i<n;++i)
- {
- const btVector3 k=c.m_nodes[i]->m_x-c.m_com;
- const btVector3 q=k*k;
- const btScalar m=1/c.m_nodes[i]->m_im;
- c.m_invwi[0][0] += m*(q[1]+q[2]);
- c.m_invwi[1][1] += m*(q[0]+q[2]);
- c.m_invwi[2][2] += m*(q[0]+q[1]);
- c.m_invwi[0][1] -= m*k[0]*k[1];
- c.m_invwi[0][2] -= m*k[0]*k[2];
- c.m_invwi[1][2] -= m*k[1]*k[2];
- }
- c.m_invwi[1][0]=c.m_invwi[0][1];
- c.m_invwi[2][0]=c.m_invwi[0][2];
- c.m_invwi[2][1]=c.m_invwi[1][2];
- c.m_invwi=c.m_invwi.inverse();
+#else /* Actual */
+ c.m_invwi[0] = c.m_invwi[1] = c.m_invwi[2] = btVector3(0, 0, 0);
+ for (int i = 0; i < n; ++i)
+ {
+ const btVector3 k = c.m_nodes[i]->m_x - c.m_com;
+ const btVector3 q = k * k;
+ const btScalar m = 1 / c.m_nodes[i]->m_im;
+ c.m_invwi[0][0] += m * (q[1] + q[2]);
+ c.m_invwi[1][1] += m * (q[0] + q[2]);
+ c.m_invwi[2][2] += m * (q[0] + q[1]);
+ c.m_invwi[0][1] -= m * k[0] * k[1];
+ c.m_invwi[0][2] -= m * k[0] * k[2];
+ c.m_invwi[1][2] -= m * k[1] * k[2];
+ }
+ c.m_invwi[1][0] = c.m_invwi[0][1];
+ c.m_invwi[2][0] = c.m_invwi[0][2];
+ c.m_invwi[2][1] = c.m_invwi[1][2];
+ c.m_invwi = c.m_invwi.inverse();
#endif
#endif
- /* Velocities */
- c.m_lv=btVector3(0,0,0);
- c.m_av=btVector3(0,0,0);
+ /* Velocities */
+ c.m_lv = btVector3(0, 0, 0);
+ c.m_av = btVector3(0, 0, 0);
{
int i;
- for(i=0;i<n;++i)
+ for (i = 0; i < n; ++i)
{
- const btVector3 v=c.m_nodes[i]->m_v*c.m_masses[i];
- c.m_lv += v;
- c.m_av += btCross(c.m_nodes[i]->m_x-c.m_com,v);
+ const btVector3 v = c.m_nodes[i]->m_v * c.m_masses[i];
+ c.m_lv += v;
+ c.m_av += btCross(c.m_nodes[i]->m_x - c.m_com, v);
}
}
- c.m_lv=c.m_imass*c.m_lv*(1-c.m_ldamping);
- c.m_av=c.m_invwi*c.m_av*(1-c.m_adamping);
- c.m_vimpulses[0] =
- c.m_vimpulses[1] = btVector3(0,0,0);
- c.m_dimpulses[0] =
- c.m_dimpulses[1] = btVector3(0,0,0);
- c.m_nvimpulses = 0;
- c.m_ndimpulses = 0;
- /* Matching */
- if(c.m_matching>0)
- {
- for(int j=0;j<c.m_nodes.size();++j)
+ c.m_lv = c.m_imass * c.m_lv * (1 - c.m_ldamping);
+ c.m_av = c.m_invwi * c.m_av * (1 - c.m_adamping);
+ c.m_vimpulses[0] =
+ c.m_vimpulses[1] = btVector3(0, 0, 0);
+ c.m_dimpulses[0] =
+ c.m_dimpulses[1] = btVector3(0, 0, 0);
+ c.m_nvimpulses = 0;
+ c.m_ndimpulses = 0;
+ /* Matching */
+ if (c.m_matching > 0)
+ {
+ for (int j = 0; j < c.m_nodes.size(); ++j)
{
- Node& n=*c.m_nodes[j];
- const btVector3 x=c.m_framexform*c.m_framerefs[j];
- n.m_x=Lerp(n.m_x,x,c.m_matching);
+ Node& n = *c.m_nodes[j];
+ const btVector3 x = c.m_framexform * c.m_framerefs[j];
+ n.m_x = Lerp(n.m_x, x, c.m_matching);
}
- }
- /* Dbvt */
- if(c.m_collide)
+ }
+ /* Dbvt */
+ if (c.m_collide)
{
- btVector3 mi=c.m_nodes[0]->m_x;
- btVector3 mx=mi;
- for(int j=1;j<n;++j)
+ btVector3 mi = c.m_nodes[0]->m_x;
+ btVector3 mx = mi;
+ for (int j = 1; j < n; ++j)
{
mi.setMin(c.m_nodes[j]->m_x);
mx.setMax(c.m_nodes[j]->m_x);
- }
- ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(mi,mx);
- if(c.m_leaf)
- m_cdbvt.update(c.m_leaf,bounds,c.m_lv*m_sst.sdt*3,m_sst.radmrg);
+ }
+ ATTRIBUTE_ALIGNED16(btDbvtVolume)
+ bounds = btDbvtVolume::FromMM(mi, mx);
+ if (c.m_leaf)
+ m_cdbvt.update(c.m_leaf, bounds, c.m_lv * m_sst.sdt * 3, m_sst.radmrg);
else
- c.m_leaf=m_cdbvt.insert(bounds,&c);
+ c.m_leaf = m_cdbvt.insert(bounds, &c);
}
}
}
-
-
}
-
-
-
//
-void btSoftBody::cleanupClusters()
+void btSoftBody::cleanupClusters()
{
- for(int i=0;i<m_joints.size();++i)
+ for (int i = 0; i < m_joints.size(); ++i)
{
m_joints[i]->Terminate(m_sst.sdt);
- if(m_joints[i]->m_delete)
+ if (m_joints[i]->m_delete)
{
btAlignedFree(m_joints[i]);
m_joints.remove(m_joints[i--]);
- }
+ }
}
}
//
-void btSoftBody::prepareClusters(int iterations)
+void btSoftBody::prepareClusters(int iterations)
{
- for(int i=0;i<m_joints.size();++i)
+ for (int i = 0; i < m_joints.size(); ++i)
{
- m_joints[i]->Prepare(m_sst.sdt,iterations);
+ m_joints[i]->Prepare(m_sst.sdt, iterations);
}
}
-
//
-void btSoftBody::solveClusters(btScalar sor)
+void btSoftBody::solveClusters(btScalar sor)
{
- for(int i=0,ni=m_joints.size();i<ni;++i)
+ for (int i = 0, ni = m_joints.size(); i < ni; ++i)
{
- m_joints[i]->Solve(m_sst.sdt,sor);
+ m_joints[i]->Solve(m_sst.sdt, sor);
}
}
//
-void btSoftBody::applyClusters(bool drift)
+void btSoftBody::applyClusters(bool drift)
{
BT_PROFILE("ApplyClusters");
-// const btScalar f0=m_sst.sdt;
+ // const btScalar f0=m_sst.sdt;
//const btScalar f1=f0/2;
btAlignedObjectArray<btVector3> deltas;
btAlignedObjectArray<btScalar> weights;
- deltas.resize(m_nodes.size(),btVector3(0,0,0));
- weights.resize(m_nodes.size(),0);
+ deltas.resize(m_nodes.size(), btVector3(0, 0, 0));
+ weights.resize(m_nodes.size(), 0);
int i;
- if(drift)
+ if (drift)
{
- for(i=0;i<m_clusters.size();++i)
+ for (i = 0; i < m_clusters.size(); ++i)
{
- Cluster& c=*m_clusters[i];
- if(c.m_ndimpulses)
+ Cluster& c = *m_clusters[i];
+ if (c.m_ndimpulses)
{
- c.m_dimpulses[0]/=(btScalar)c.m_ndimpulses;
- c.m_dimpulses[1]/=(btScalar)c.m_ndimpulses;
+ c.m_dimpulses[0] /= (btScalar)c.m_ndimpulses;
+ c.m_dimpulses[1] /= (btScalar)c.m_ndimpulses;
}
}
}
-
- for(i=0;i<m_clusters.size();++i)
+
+ for (i = 0; i < m_clusters.size(); ++i)
{
- Cluster& c=*m_clusters[i];
- if(0<(drift?c.m_ndimpulses:c.m_nvimpulses))
+ Cluster& c = *m_clusters[i];
+ if (0 < (drift ? c.m_ndimpulses : c.m_nvimpulses))
{
- const btVector3 v=(drift?c.m_dimpulses[0]:c.m_vimpulses[0])*m_sst.sdt;
- const btVector3 w=(drift?c.m_dimpulses[1]:c.m_vimpulses[1])*m_sst.sdt;
- for(int j=0;j<c.m_nodes.size();++j)
+ const btVector3 v = (drift ? c.m_dimpulses[0] : c.m_vimpulses[0]) * m_sst.sdt;
+ const btVector3 w = (drift ? c.m_dimpulses[1] : c.m_vimpulses[1]) * m_sst.sdt;
+ for (int j = 0; j < c.m_nodes.size(); ++j)
{
- const int idx=int(c.m_nodes[j]-&m_nodes[0]);
- const btVector3& x=c.m_nodes[j]->m_x;
- const btScalar q=c.m_masses[j];
- deltas[idx] += (v+btCross(w,x-c.m_com))*q;
- weights[idx] += q;
+ const int idx = int(c.m_nodes[j] - &m_nodes[0]);
+ const btVector3& x = c.m_nodes[j]->m_x;
+ const btScalar q = c.m_masses[j];
+ deltas[idx] += (v + btCross(w, x - c.m_com)) * q;
+ weights[idx] += q;
}
}
}
- for(i=0;i<deltas.size();++i)
+ for (i = 0; i < deltas.size(); ++i)
{
- if(weights[i]>0)
+ if (weights[i] > 0)
{
- m_nodes[i].m_x+=deltas[i]/weights[i];
+ m_nodes[i].m_x += deltas[i] / weights[i];
}
}
}
//
-void btSoftBody::dampClusters()
+void btSoftBody::dampClusters()
{
int i;
- for(i=0;i<m_clusters.size();++i)
+ for (i = 0; i < m_clusters.size(); ++i)
{
- Cluster& c=*m_clusters[i];
- if(c.m_ndamping>0)
+ Cluster& c = *m_clusters[i];
+ if (c.m_ndamping > 0)
{
- for(int j=0;j<c.m_nodes.size();++j)
+ for (int j = 0; j < c.m_nodes.size(); ++j)
{
- Node& n=*c.m_nodes[j];
- if(n.m_im>0)
+ Node& n = *c.m_nodes[j];
+ if (n.m_im > 0)
{
- const btVector3 vx=c.m_lv+btCross(c.m_av,c.m_nodes[j]->m_q-c.m_com);
- if(vx.length2()<=n.m_v.length2())
- {
- n.m_v += c.m_ndamping*(vx-n.m_v);
- }
+ const btVector3 vx = c.m_lv + btCross(c.m_av, c.m_nodes[j]->m_q - c.m_com);
+ if (vx.length2() <= n.m_v.length2())
+ {
+ n.m_v += c.m_ndamping * (vx - n.m_v);
+ }
}
}
}
@@ -2763,710 +2775,696 @@ void btSoftBody::dampClusters()
}
//
-void btSoftBody::Joint::Prepare(btScalar dt,int)
+void btSoftBody::Joint::Prepare(btScalar dt, int)
{
m_bodies[0].activate();
m_bodies[1].activate();
}
//
-void btSoftBody::LJoint::Prepare(btScalar dt,int iterations)
+void btSoftBody::LJoint::Prepare(btScalar dt, int iterations)
{
- static const btScalar maxdrift=4;
- Joint::Prepare(dt,iterations);
- m_rpos[0] = m_bodies[0].xform()*m_refs[0];
- m_rpos[1] = m_bodies[1].xform()*m_refs[1];
- m_drift = Clamp(m_rpos[0]-m_rpos[1],maxdrift)*m_erp/dt;
- m_rpos[0] -= m_bodies[0].xform().getOrigin();
- m_rpos[1] -= m_bodies[1].xform().getOrigin();
- m_massmatrix = ImpulseMatrix( m_bodies[0].invMass(),m_bodies[0].invWorldInertia(),m_rpos[0],
- m_bodies[1].invMass(),m_bodies[1].invWorldInertia(),m_rpos[1]);
- if(m_split>0)
+ static const btScalar maxdrift = 4;
+ Joint::Prepare(dt, iterations);
+ m_rpos[0] = m_bodies[0].xform() * m_refs[0];
+ m_rpos[1] = m_bodies[1].xform() * m_refs[1];
+ m_drift = Clamp(m_rpos[0] - m_rpos[1], maxdrift) * m_erp / dt;
+ m_rpos[0] -= m_bodies[0].xform().getOrigin();
+ m_rpos[1] -= m_bodies[1].xform().getOrigin();
+ m_massmatrix = ImpulseMatrix(m_bodies[0].invMass(), m_bodies[0].invWorldInertia(), m_rpos[0],
+ m_bodies[1].invMass(), m_bodies[1].invWorldInertia(), m_rpos[1]);
+ if (m_split > 0)
{
- m_sdrift = m_massmatrix*(m_drift*m_split);
- m_drift *= 1-m_split;
+ m_sdrift = m_massmatrix * (m_drift * m_split);
+ m_drift *= 1 - m_split;
}
- m_drift /=(btScalar)iterations;
+ m_drift /= (btScalar)iterations;
}
//
-void btSoftBody::LJoint::Solve(btScalar dt,btScalar sor)
+void btSoftBody::LJoint::Solve(btScalar dt, btScalar sor)
{
- const btVector3 va=m_bodies[0].velocity(m_rpos[0]);
- const btVector3 vb=m_bodies[1].velocity(m_rpos[1]);
- const btVector3 vr=va-vb;
- btSoftBody::Impulse impulse;
- impulse.m_asVelocity = 1;
- impulse.m_velocity = m_massmatrix*(m_drift+vr*m_cfm)*sor;
- m_bodies[0].applyImpulse(-impulse,m_rpos[0]);
- m_bodies[1].applyImpulse( impulse,m_rpos[1]);
+ const btVector3 va = m_bodies[0].velocity(m_rpos[0]);
+ const btVector3 vb = m_bodies[1].velocity(m_rpos[1]);
+ const btVector3 vr = va - vb;
+ btSoftBody::Impulse impulse;
+ impulse.m_asVelocity = 1;
+ impulse.m_velocity = m_massmatrix * (m_drift + vr * m_cfm) * sor;
+ m_bodies[0].applyImpulse(-impulse, m_rpos[0]);
+ m_bodies[1].applyImpulse(impulse, m_rpos[1]);
}
//
-void btSoftBody::LJoint::Terminate(btScalar dt)
+void btSoftBody::LJoint::Terminate(btScalar dt)
{
- if(m_split>0)
+ if (m_split > 0)
{
- m_bodies[0].applyDImpulse(-m_sdrift,m_rpos[0]);
- m_bodies[1].applyDImpulse( m_sdrift,m_rpos[1]);
+ m_bodies[0].applyDImpulse(-m_sdrift, m_rpos[0]);
+ m_bodies[1].applyDImpulse(m_sdrift, m_rpos[1]);
}
}
//
-void btSoftBody::AJoint::Prepare(btScalar dt,int iterations)
+void btSoftBody::AJoint::Prepare(btScalar dt, int iterations)
{
- static const btScalar maxdrift=SIMD_PI/16;
+ static const btScalar maxdrift = SIMD_PI / 16;
m_icontrol->Prepare(this);
- Joint::Prepare(dt,iterations);
- m_axis[0] = m_bodies[0].xform().getBasis()*m_refs[0];
- m_axis[1] = m_bodies[1].xform().getBasis()*m_refs[1];
- m_drift = NormalizeAny(btCross(m_axis[1],m_axis[0]));
- m_drift *= btMin(maxdrift,btAcos(Clamp<btScalar>(btDot(m_axis[0],m_axis[1]),-1,+1)));
- m_drift *= m_erp/dt;
- m_massmatrix= AngularImpulseMatrix(m_bodies[0].invWorldInertia(),m_bodies[1].invWorldInertia());
- if(m_split>0)
+ Joint::Prepare(dt, iterations);
+ m_axis[0] = m_bodies[0].xform().getBasis() * m_refs[0];
+ m_axis[1] = m_bodies[1].xform().getBasis() * m_refs[1];
+ m_drift = NormalizeAny(btCross(m_axis[1], m_axis[0]));
+ m_drift *= btMin(maxdrift, btAcos(Clamp<btScalar>(btDot(m_axis[0], m_axis[1]), -1, +1)));
+ m_drift *= m_erp / dt;
+ m_massmatrix = AngularImpulseMatrix(m_bodies[0].invWorldInertia(), m_bodies[1].invWorldInertia());
+ if (m_split > 0)
{
- m_sdrift = m_massmatrix*(m_drift*m_split);
- m_drift *= 1-m_split;
+ m_sdrift = m_massmatrix * (m_drift * m_split);
+ m_drift *= 1 - m_split;
}
- m_drift /=(btScalar)iterations;
+ m_drift /= (btScalar)iterations;
}
//
-void btSoftBody::AJoint::Solve(btScalar dt,btScalar sor)
+void btSoftBody::AJoint::Solve(btScalar dt, btScalar sor)
{
- const btVector3 va=m_bodies[0].angularVelocity();
- const btVector3 vb=m_bodies[1].angularVelocity();
- const btVector3 vr=va-vb;
- const btScalar sp=btDot(vr,m_axis[0]);
- const btVector3 vc=vr-m_axis[0]*m_icontrol->Speed(this,sp);
- btSoftBody::Impulse impulse;
- impulse.m_asVelocity = 1;
- impulse.m_velocity = m_massmatrix*(m_drift+vc*m_cfm)*sor;
+ const btVector3 va = m_bodies[0].angularVelocity();
+ const btVector3 vb = m_bodies[1].angularVelocity();
+ const btVector3 vr = va - vb;
+ const btScalar sp = btDot(vr, m_axis[0]);
+ const btVector3 vc = vr - m_axis[0] * m_icontrol->Speed(this, sp);
+ btSoftBody::Impulse impulse;
+ impulse.m_asVelocity = 1;
+ impulse.m_velocity = m_massmatrix * (m_drift + vc * m_cfm) * sor;
m_bodies[0].applyAImpulse(-impulse);
- m_bodies[1].applyAImpulse( impulse);
+ m_bodies[1].applyAImpulse(impulse);
}
//
-void btSoftBody::AJoint::Terminate(btScalar dt)
+void btSoftBody::AJoint::Terminate(btScalar dt)
{
- if(m_split>0)
+ if (m_split > 0)
{
m_bodies[0].applyDAImpulse(-m_sdrift);
- m_bodies[1].applyDAImpulse( m_sdrift);
+ m_bodies[1].applyDAImpulse(m_sdrift);
}
}
//
-void btSoftBody::CJoint::Prepare(btScalar dt,int iterations)
+void btSoftBody::CJoint::Prepare(btScalar dt, int iterations)
{
- Joint::Prepare(dt,iterations);
- const bool dodrift=(m_life==0);
- m_delete=(++m_life)>m_maxlife;
- if(dodrift)
+ Joint::Prepare(dt, iterations);
+ const bool dodrift = (m_life == 0);
+ m_delete = (++m_life) > m_maxlife;
+ if (dodrift)
{
- m_drift=m_drift*m_erp/dt;
- if(m_split>0)
+ m_drift = m_drift * m_erp / dt;
+ if (m_split > 0)
{
- m_sdrift = m_massmatrix*(m_drift*m_split);
- m_drift *= 1-m_split;
+ m_sdrift = m_massmatrix * (m_drift * m_split);
+ m_drift *= 1 - m_split;
}
- m_drift/=(btScalar)iterations;
+ m_drift /= (btScalar)iterations;
}
else
{
- m_drift=m_sdrift=btVector3(0,0,0);
+ m_drift = m_sdrift = btVector3(0, 0, 0);
}
}
//
-void btSoftBody::CJoint::Solve(btScalar dt,btScalar sor)
+void btSoftBody::CJoint::Solve(btScalar dt, btScalar sor)
{
- const btVector3 va=m_bodies[0].velocity(m_rpos[0]);
- const btVector3 vb=m_bodies[1].velocity(m_rpos[1]);
- const btVector3 vrel=va-vb;
- const btScalar rvac=btDot(vrel,m_normal);
- btSoftBody::Impulse impulse;
- impulse.m_asVelocity = 1;
- impulse.m_velocity = m_drift;
- if(rvac<0)
+ const btVector3 va = m_bodies[0].velocity(m_rpos[0]);
+ const btVector3 vb = m_bodies[1].velocity(m_rpos[1]);
+ const btVector3 vrel = va - vb;
+ const btScalar rvac = btDot(vrel, m_normal);
+ btSoftBody::Impulse impulse;
+ impulse.m_asVelocity = 1;
+ impulse.m_velocity = m_drift;
+ if (rvac < 0)
{
- const btVector3 iv=m_normal*rvac;
- const btVector3 fv=vrel-iv;
- impulse.m_velocity += iv+fv*m_friction;
+ const btVector3 iv = m_normal * rvac;
+ const btVector3 fv = vrel - iv;
+ impulse.m_velocity += iv + fv * m_friction;
}
- impulse.m_velocity=m_massmatrix*impulse.m_velocity*sor;
-
- if (m_bodies[0].m_soft==m_bodies[1].m_soft)
+ impulse.m_velocity = m_massmatrix * impulse.m_velocity * sor;
+
+ if (m_bodies[0].m_soft == m_bodies[1].m_soft)
{
- if ((impulse.m_velocity.getX() ==impulse.m_velocity.getX())&&(impulse.m_velocity.getY() ==impulse.m_velocity.getY())&&
- (impulse.m_velocity.getZ() ==impulse.m_velocity.getZ()))
+ if ((impulse.m_velocity.getX() == impulse.m_velocity.getX()) && (impulse.m_velocity.getY() == impulse.m_velocity.getY()) &&
+ (impulse.m_velocity.getZ() == impulse.m_velocity.getZ()))
{
if (impulse.m_asVelocity)
{
- if (impulse.m_velocity.length() <m_bodies[0].m_soft->m_maxSelfCollisionImpulse)
+ if (impulse.m_velocity.length() < m_bodies[0].m_soft->m_maxSelfCollisionImpulse)
{
-
- } else
+ }
+ else
{
- m_bodies[0].applyImpulse(-impulse*m_bodies[0].m_soft->m_selfCollisionImpulseFactor,m_rpos[0]);
- m_bodies[1].applyImpulse( impulse*m_bodies[0].m_soft->m_selfCollisionImpulseFactor,m_rpos[1]);
+ m_bodies[0].applyImpulse(-impulse * m_bodies[0].m_soft->m_selfCollisionImpulseFactor, m_rpos[0]);
+ m_bodies[1].applyImpulse(impulse * m_bodies[0].m_soft->m_selfCollisionImpulseFactor, m_rpos[1]);
}
}
}
- } else
+ }
+ else
{
- m_bodies[0].applyImpulse(-impulse,m_rpos[0]);
- m_bodies[1].applyImpulse( impulse,m_rpos[1]);
+ m_bodies[0].applyImpulse(-impulse, m_rpos[0]);
+ m_bodies[1].applyImpulse(impulse, m_rpos[1]);
}
}
//
-void btSoftBody::CJoint::Terminate(btScalar dt)
+void btSoftBody::CJoint::Terminate(btScalar dt)
{
- if(m_split>0)
+ if (m_split > 0)
{
- m_bodies[0].applyDImpulse(-m_sdrift,m_rpos[0]);
- m_bodies[1].applyDImpulse( m_sdrift,m_rpos[1]);
+ m_bodies[0].applyDImpulse(-m_sdrift, m_rpos[0]);
+ m_bodies[1].applyDImpulse(m_sdrift, m_rpos[1]);
}
}
//
-void btSoftBody::applyForces()
+void btSoftBody::applyForces()
{
-
BT_PROFILE("SoftBody applyForces");
-// const btScalar dt = m_sst.sdt;
- const btScalar kLF = m_cfg.kLF;
- const btScalar kDG = m_cfg.kDG;
- const btScalar kPR = m_cfg.kPR;
- const btScalar kVC = m_cfg.kVC;
- const bool as_lift = kLF>0;
- const bool as_drag = kDG>0;
- const bool as_pressure = kPR!=0;
- const bool as_volume = kVC>0;
- const bool as_aero = as_lift ||
- as_drag ;
+ // const btScalar dt = m_sst.sdt;
+ const btScalar kLF = m_cfg.kLF;
+ const btScalar kDG = m_cfg.kDG;
+ const btScalar kPR = m_cfg.kPR;
+ const btScalar kVC = m_cfg.kVC;
+ const bool as_lift = kLF > 0;
+ const bool as_drag = kDG > 0;
+ const bool as_pressure = kPR != 0;
+ const bool as_volume = kVC > 0;
+ const bool as_aero = as_lift ||
+ as_drag;
//const bool as_vaero = as_aero &&
// (m_cfg.aeromodel < btSoftBody::eAeroModel::F_TwoSided);
//const bool as_faero = as_aero &&
// (m_cfg.aeromodel >= btSoftBody::eAeroModel::F_TwoSided);
- const bool use_medium = as_aero;
- const bool use_volume = as_pressure ||
- as_volume ;
- btScalar volume = 0;
- btScalar ivolumetp = 0;
- btScalar dvolumetv = 0;
- btSoftBody::sMedium medium;
- if(use_volume)
+ const bool use_medium = as_aero;
+ const bool use_volume = as_pressure ||
+ as_volume;
+ btScalar volume = 0;
+ btScalar ivolumetp = 0;
+ btScalar dvolumetv = 0;
+ btSoftBody::sMedium medium;
+ if (use_volume)
{
- volume = getVolume();
- ivolumetp = 1/btFabs(volume)*kPR;
- dvolumetv = (m_pose.m_volume-volume)*kVC;
+ volume = getVolume();
+ ivolumetp = 1 / btFabs(volume) * kPR;
+ dvolumetv = (m_pose.m_volume - volume) * kVC;
}
- /* Per vertex forces */
- int i,ni;
+ /* Per vertex forces */
+ int i, ni;
- for(i=0,ni=m_nodes.size();i<ni;++i)
+ for (i = 0, ni = m_nodes.size(); i < ni; ++i)
{
- btSoftBody::Node& n=m_nodes[i];
- if(n.m_im>0)
+ btSoftBody::Node& n = m_nodes[i];
+ if (n.m_im > 0)
{
- if(use_medium)
+ if (use_medium)
{
- /* Aerodynamics */
+ /* Aerodynamics */
addAeroForceToNode(m_windVelocity, i);
}
- /* Pressure */
- if(as_pressure)
+ /* Pressure */
+ if (as_pressure)
{
- n.m_f += n.m_n*(n.m_area*ivolumetp);
+ n.m_f += n.m_n * (n.m_area * ivolumetp);
}
- /* Volume */
- if(as_volume)
+ /* Volume */
+ if (as_volume)
{
- n.m_f += n.m_n*(n.m_area*dvolumetv);
+ n.m_f += n.m_n * (n.m_area * dvolumetv);
}
}
}
- /* Per face forces */
- for(i=0,ni=m_faces.size();i<ni;++i)
+ /* Per face forces */
+ for (i = 0, ni = m_faces.size(); i < ni; ++i)
{
- // btSoftBody::Face& f=m_faces[i];
+ // btSoftBody::Face& f=m_faces[i];
- /* Aerodynamics */
- addAeroForceToFace(m_windVelocity, i);
+ /* Aerodynamics */
+ addAeroForceToFace(m_windVelocity, i);
}
}
//
-void btSoftBody::PSolve_Anchors(btSoftBody* psb,btScalar kst,btScalar ti)
+void btSoftBody::PSolve_Anchors(btSoftBody* psb, btScalar kst, btScalar ti)
{
BT_PROFILE("PSolve_Anchors");
- const btScalar kAHR=psb->m_cfg.kAHR*kst;
- const btScalar dt=psb->m_sst.sdt;
- for(int i=0,ni=psb->m_anchors.size();i<ni;++i)
+ const btScalar kAHR = psb->m_cfg.kAHR * kst;
+ const btScalar dt = psb->m_sst.sdt;
+ for (int i = 0, ni = psb->m_anchors.size(); i < ni; ++i)
{
- const Anchor& a=psb->m_anchors[i];
- const btTransform& t=a.m_body->getWorldTransform();
- Node& n=*a.m_node;
- const btVector3 wa=t*a.m_local;
- const btVector3 va=a.m_body->getVelocityInLocalPoint(a.m_c1)*dt;
- const btVector3 vb=n.m_x-n.m_q;
- const btVector3 vr=(va-vb)+(wa-n.m_x)*kAHR;
- const btVector3 impulse=a.m_c0*vr*a.m_influence;
- n.m_x+=impulse*a.m_c2;
- a.m_body->applyImpulse(-impulse,a.m_c1);
+ const Anchor& a = psb->m_anchors[i];
+ const btTransform& t = a.m_body->getWorldTransform();
+ Node& n = *a.m_node;
+ const btVector3 wa = t * a.m_local;
+ const btVector3 va = a.m_body->getVelocityInLocalPoint(a.m_c1) * dt;
+ const btVector3 vb = n.m_x - n.m_q;
+ const btVector3 vr = (va - vb) + (wa - n.m_x) * kAHR;
+ const btVector3 impulse = a.m_c0 * vr * a.m_influence;
+ n.m_x += impulse * a.m_c2;
+ a.m_body->applyImpulse(-impulse, a.m_c1);
}
}
-
//
void btSoftBody::PSolve_RContacts(btSoftBody* psb, btScalar kst, btScalar ti)
{
BT_PROFILE("PSolve_RContacts");
- const btScalar dt = psb->m_sst.sdt;
- const btScalar mrg = psb->getCollisionShape()->getMargin();
+ const btScalar dt = psb->m_sst.sdt;
+ const btScalar mrg = psb->getCollisionShape()->getMargin();
btMultiBodyJacobianData jacobianData;
- for(int i=0,ni=psb->m_rcontacts.size();i<ni;++i)
- {
- const RContact& c = psb->m_rcontacts[i];
- const sCti& cti = c.m_cti;
- if (cti.m_colObj->hasContactResponse())
- {
- btVector3 va(0,0,0);
- btRigidBody* rigidCol=0;
- btMultiBodyLinkCollider* multibodyLinkCol=0;
- btScalar* deltaV;
-
- if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
- {
- rigidCol = (btRigidBody*)btRigidBody::upcast(cti.m_colObj);
- va = rigidCol ? rigidCol->getVelocityInLocalPoint(c.m_c1)*dt : btVector3(0,0,0);
- }
+ for (int i = 0, ni = psb->m_rcontacts.size(); i < ni; ++i)
+ {
+ const RContact& c = psb->m_rcontacts[i];
+ const sCti& cti = c.m_cti;
+ if (cti.m_colObj->hasContactResponse())
+ {
+ btVector3 va(0, 0, 0);
+ btRigidBody* rigidCol = 0;
+ btMultiBodyLinkCollider* multibodyLinkCol = 0;
+ btScalar* deltaV;
+
+ if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
+ {
+ rigidCol = (btRigidBody*)btRigidBody::upcast(cti.m_colObj);
+ va = rigidCol ? rigidCol->getVelocityInLocalPoint(c.m_c1) * dt : btVector3(0, 0, 0);
+ }
else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
- {
- multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
- if (multibodyLinkCol)
- {
- const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
- jacobianData.m_jacobians.resize(ndof);
- jacobianData.m_deltaVelocitiesUnitImpulse.resize(ndof);
- btScalar* jac=&jacobianData.m_jacobians[0];
-
- multibodyLinkCol->m_multiBody->fillContactJacobianMultiDof(multibodyLinkCol->m_link, c.m_node->m_x, cti.m_normal, jac, jacobianData.scratch_r, jacobianData.scratch_v, jacobianData.scratch_m);
- deltaV = &jacobianData.m_deltaVelocitiesUnitImpulse[0];
- multibodyLinkCol->m_multiBody->calcAccelerationDeltasMultiDof(&jacobianData.m_jacobians[0],deltaV,jacobianData.scratch_r, jacobianData.scratch_v);
-
- btScalar vel = 0.0;
- for (int j = 0; j < ndof ; ++j) {
- vel += multibodyLinkCol->m_multiBody->getVelocityVector()[j] * jac[j];
- }
- va = cti.m_normal*vel*dt;
- }
- }
-
- const btVector3 vb = c.m_node->m_x-c.m_node->m_q;
- const btVector3 vr = vb-va;
- const btScalar dn = btDot(vr, cti.m_normal);
- if(dn<=SIMD_EPSILON)
- {
- const btScalar dp = btMin( (btDot(c.m_node->m_x, cti.m_normal) + cti.m_offset), mrg );
- const btVector3 fv = vr - (cti.m_normal * dn);
+ {
+ multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
+ if (multibodyLinkCol)
+ {
+ const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
+ jacobianData.m_jacobians.resize(ndof);
+ jacobianData.m_deltaVelocitiesUnitImpulse.resize(ndof);
+ btScalar* jac = &jacobianData.m_jacobians[0];
+
+ multibodyLinkCol->m_multiBody->fillContactJacobianMultiDof(multibodyLinkCol->m_link, c.m_node->m_x, cti.m_normal, jac, jacobianData.scratch_r, jacobianData.scratch_v, jacobianData.scratch_m);
+ deltaV = &jacobianData.m_deltaVelocitiesUnitImpulse[0];
+ multibodyLinkCol->m_multiBody->calcAccelerationDeltasMultiDof(&jacobianData.m_jacobians[0], deltaV, jacobianData.scratch_r, jacobianData.scratch_v);
+
+ btScalar vel = 0.0;
+ for (int j = 0; j < ndof; ++j)
+ {
+ vel += multibodyLinkCol->m_multiBody->getVelocityVector()[j] * jac[j];
+ }
+ va = cti.m_normal * vel * dt;
+ }
+ }
+
+ const btVector3 vb = c.m_node->m_x - c.m_node->m_q;
+ const btVector3 vr = vb - va;
+ const btScalar dn = btDot(vr, cti.m_normal);
+ if (dn <= SIMD_EPSILON)
+ {
+ const btScalar dp = btMin((btDot(c.m_node->m_x, cti.m_normal) + cti.m_offset), mrg);
+ const btVector3 fv = vr - (cti.m_normal * dn);
// c0 is the impulse matrix, c3 is 1 - the friction coefficient or 0, c4 is the contact hardness coefficient
- const btVector3 impulse = c.m_c0 * ( (vr - (fv * c.m_c3) + (cti.m_normal * (dp * c.m_c4))) * kst );
+ const btVector3 impulse = c.m_c0 * ((vr - (fv * c.m_c3) + (cti.m_normal * (dp * c.m_c4))) * kst);
c.m_node->m_x -= impulse * c.m_c2;
-
- if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
- {
- if (rigidCol)
- rigidCol->applyImpulse(impulse,c.m_c1);
- }
- else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
- {
- if (multibodyLinkCol)
- {
- double multiplier = 0.5;
- multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof(deltaV,-impulse.length()*multiplier);
- }
- }
+
+ if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
+ {
+ if (rigidCol)
+ rigidCol->applyImpulse(impulse, c.m_c1);
+ }
+ else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
+ {
+ if (multibodyLinkCol)
+ {
+ double multiplier = 0.5;
+ multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof(deltaV, -impulse.length() * multiplier);
+ }
+ }
}
}
}
}
//
-void btSoftBody::PSolve_SContacts(btSoftBody* psb,btScalar,btScalar ti)
+void btSoftBody::PSolve_SContacts(btSoftBody* psb, btScalar, btScalar ti)
{
BT_PROFILE("PSolve_SContacts");
-
- for(int i=0,ni=psb->m_scontacts.size();i<ni;++i)
+
+ for (int i = 0, ni = psb->m_scontacts.size(); i < ni; ++i)
{
- const SContact& c=psb->m_scontacts[i];
- const btVector3& nr=c.m_normal;
- Node& n=*c.m_node;
- Face& f=*c.m_face;
- const btVector3 p=BaryEval( f.m_n[0]->m_x,
- f.m_n[1]->m_x,
- f.m_n[2]->m_x,
- c.m_weights);
- const btVector3 q=BaryEval( f.m_n[0]->m_q,
- f.m_n[1]->m_q,
- f.m_n[2]->m_q,
- c.m_weights);
- const btVector3 vr=(n.m_x-n.m_q)-(p-q);
- btVector3 corr(0,0,0);
- btScalar dot = btDot(vr,nr);
- if(dot<0)
+ const SContact& c = psb->m_scontacts[i];
+ const btVector3& nr = c.m_normal;
+ Node& n = *c.m_node;
+ Face& f = *c.m_face;
+ const btVector3 p = BaryEval(f.m_n[0]->m_x,
+ f.m_n[1]->m_x,
+ f.m_n[2]->m_x,
+ c.m_weights);
+ const btVector3 q = BaryEval(f.m_n[0]->m_q,
+ f.m_n[1]->m_q,
+ f.m_n[2]->m_q,
+ c.m_weights);
+ const btVector3 vr = (n.m_x - n.m_q) - (p - q);
+ btVector3 corr(0, 0, 0);
+ btScalar dot = btDot(vr, nr);
+ if (dot < 0)
{
- const btScalar j=c.m_margin-(btDot(nr,n.m_x)-btDot(nr,p));
- corr+=c.m_normal*j;
+ const btScalar j = c.m_margin - (btDot(nr, n.m_x) - btDot(nr, p));
+ corr += c.m_normal * j;
}
- corr -= ProjectOnPlane(vr,nr)*c.m_friction;
- n.m_x += corr*c.m_cfm[0];
- f.m_n[0]->m_x -= corr*(c.m_cfm[1]*c.m_weights.x());
- f.m_n[1]->m_x -= corr*(c.m_cfm[1]*c.m_weights.y());
- f.m_n[2]->m_x -= corr*(c.m_cfm[1]*c.m_weights.z());
+ corr -= ProjectOnPlane(vr, nr) * c.m_friction;
+ n.m_x += corr * c.m_cfm[0];
+ f.m_n[0]->m_x -= corr * (c.m_cfm[1] * c.m_weights.x());
+ f.m_n[1]->m_x -= corr * (c.m_cfm[1] * c.m_weights.y());
+ f.m_n[2]->m_x -= corr * (c.m_cfm[1] * c.m_weights.z());
}
}
//
-void btSoftBody::PSolve_Links(btSoftBody* psb,btScalar kst,btScalar ti)
+void btSoftBody::PSolve_Links(btSoftBody* psb, btScalar kst, btScalar ti)
{
-BT_PROFILE("PSolve_Links");
- for(int i=0,ni=psb->m_links.size();i<ni;++i)
- {
- Link& l=psb->m_links[i];
- if(l.m_c0>0)
+ BT_PROFILE("PSolve_Links");
+ for (int i = 0, ni = psb->m_links.size(); i < ni; ++i)
+ {
+ Link& l = psb->m_links[i];
+ if (l.m_c0 > 0)
{
- Node& a=*l.m_n[0];
- Node& b=*l.m_n[1];
- const btVector3 del=b.m_x-a.m_x;
- const btScalar len=del.length2();
- if (l.m_c1+len > SIMD_EPSILON)
+ Node& a = *l.m_n[0];
+ Node& b = *l.m_n[1];
+ const btVector3 del = b.m_x - a.m_x;
+ const btScalar len = del.length2();
+ if (l.m_c1 + len > SIMD_EPSILON)
{
- const btScalar k=((l.m_c1-len)/(l.m_c0*(l.m_c1+len)))*kst;
- a.m_x-=del*(k*a.m_im);
- b.m_x+=del*(k*b.m_im);
+ const btScalar k = ((l.m_c1 - len) / (l.m_c0 * (l.m_c1 + len))) * kst;
+ a.m_x -= del * (k * a.m_im);
+ b.m_x += del * (k * b.m_im);
}
}
}
}
//
-void btSoftBody::VSolve_Links(btSoftBody* psb,btScalar kst)
+void btSoftBody::VSolve_Links(btSoftBody* psb, btScalar kst)
{
BT_PROFILE("VSolve_Links");
- for(int i=0,ni=psb->m_links.size();i<ni;++i)
- {
- Link& l=psb->m_links[i];
- Node** n=l.m_n;
- const btScalar j=-btDot(l.m_c3,n[0]->m_v-n[1]->m_v)*l.m_c2*kst;
- n[0]->m_v+= l.m_c3*(j*n[0]->m_im);
- n[1]->m_v-= l.m_c3*(j*n[1]->m_im);
+ for (int i = 0, ni = psb->m_links.size(); i < ni; ++i)
+ {
+ Link& l = psb->m_links[i];
+ Node** n = l.m_n;
+ const btScalar j = -btDot(l.m_c3, n[0]->m_v - n[1]->m_v) * l.m_c2 * kst;
+ n[0]->m_v += l.m_c3 * (j * n[0]->m_im);
+ n[1]->m_v -= l.m_c3 * (j * n[1]->m_im);
}
}
//
-btSoftBody::psolver_t btSoftBody::getSolver(ePSolver::_ solver)
+btSoftBody::psolver_t btSoftBody::getSolver(ePSolver::_ solver)
{
- switch(solver)
+ switch (solver)
{
- case ePSolver::Anchors:
- return(&btSoftBody::PSolve_Anchors);
- case ePSolver::Linear:
- return(&btSoftBody::PSolve_Links);
- case ePSolver::RContacts:
- return(&btSoftBody::PSolve_RContacts);
- case ePSolver::SContacts:
- return(&btSoftBody::PSolve_SContacts);
+ case ePSolver::Anchors:
+ return (&btSoftBody::PSolve_Anchors);
+ case ePSolver::Linear:
+ return (&btSoftBody::PSolve_Links);
+ case ePSolver::RContacts:
+ return (&btSoftBody::PSolve_RContacts);
+ case ePSolver::SContacts:
+ return (&btSoftBody::PSolve_SContacts);
default:
{
}
}
- return(0);
+ return (0);
}
//
-btSoftBody::vsolver_t btSoftBody::getSolver(eVSolver::_ solver)
+btSoftBody::vsolver_t btSoftBody::getSolver(eVSolver::_ solver)
{
- switch(solver)
+ switch (solver)
{
- case eVSolver::Linear: return(&btSoftBody::VSolve_Links);
+ case eVSolver::Linear:
+ return (&btSoftBody::VSolve_Links);
default:
{
}
}
- return(0);
+ return (0);
}
//
-void btSoftBody::defaultCollisionHandler(const btCollisionObjectWrapper* pcoWrap)
+void btSoftBody::defaultCollisionHandler(const btCollisionObjectWrapper* pcoWrap)
{
-
- switch(m_cfg.collisions&fCollision::RVSmask)
+ switch (m_cfg.collisions & fCollision::RVSmask)
{
- case fCollision::SDF_RS:
+ case fCollision::SDF_RS:
{
- btSoftColliders::CollideSDF_RS docollide;
- btRigidBody* prb1=(btRigidBody*) btRigidBody::upcast(pcoWrap->getCollisionObject());
- btTransform wtr=pcoWrap->getWorldTransform();
+ btSoftColliders::CollideSDF_RS docollide;
+ btRigidBody* prb1 = (btRigidBody*)btRigidBody::upcast(pcoWrap->getCollisionObject());
+ btTransform wtr = pcoWrap->getWorldTransform();
- const btTransform ctr=pcoWrap->getWorldTransform();
- const btScalar timemargin=(wtr.getOrigin()-ctr.getOrigin()).length();
- const btScalar basemargin=getCollisionShape()->getMargin();
- btVector3 mins;
- btVector3 maxs;
- ATTRIBUTE_ALIGNED16(btDbvtVolume) volume;
- pcoWrap->getCollisionShape()->getAabb( pcoWrap->getWorldTransform(),
- mins,
- maxs);
- volume=btDbvtVolume::FromMM(mins,maxs);
- volume.Expand(btVector3(basemargin,basemargin,basemargin));
- docollide.psb = this;
+ const btTransform ctr = pcoWrap->getWorldTransform();
+ const btScalar timemargin = (wtr.getOrigin() - ctr.getOrigin()).length();
+ const btScalar basemargin = getCollisionShape()->getMargin();
+ btVector3 mins;
+ btVector3 maxs;
+ ATTRIBUTE_ALIGNED16(btDbvtVolume)
+ volume;
+ pcoWrap->getCollisionShape()->getAabb(pcoWrap->getWorldTransform(),
+ mins,
+ maxs);
+ volume = btDbvtVolume::FromMM(mins, maxs);
+ volume.Expand(btVector3(basemargin, basemargin, basemargin));
+ docollide.psb = this;
docollide.m_colObj1Wrap = pcoWrap;
docollide.m_rigidBody = prb1;
- docollide.dynmargin = basemargin+timemargin;
- docollide.stamargin = basemargin;
- m_ndbvt.collideTV(m_ndbvt.m_root,volume,docollide);
+ docollide.dynmargin = basemargin + timemargin;
+ docollide.stamargin = basemargin;
+ m_ndbvt.collideTV(m_ndbvt.m_root, volume, docollide);
}
break;
- case fCollision::CL_RS:
+ case fCollision::CL_RS:
{
- btSoftColliders::CollideCL_RS collider;
- collider.ProcessColObj(this,pcoWrap);
+ btSoftColliders::CollideCL_RS collider;
+ collider.ProcessColObj(this, pcoWrap);
}
break;
}
}
//
-void btSoftBody::defaultCollisionHandler(btSoftBody* psb)
+void btSoftBody::defaultCollisionHandler(btSoftBody* psb)
{
- const int cf=m_cfg.collisions&psb->m_cfg.collisions;
- switch(cf&fCollision::SVSmask)
+ const int cf = m_cfg.collisions & psb->m_cfg.collisions;
+ switch (cf & fCollision::SVSmask)
{
- case fCollision::CL_SS:
+ case fCollision::CL_SS:
{
-
//support self-collision if CL_SELF flag set
- if (this!=psb || psb->m_cfg.collisions&fCollision::CL_SELF)
+ if (this != psb || psb->m_cfg.collisions & fCollision::CL_SELF)
{
- btSoftColliders::CollideCL_SS docollide;
- docollide.ProcessSoftSoft(this,psb);
+ btSoftColliders::CollideCL_SS docollide;
+ docollide.ProcessSoftSoft(this, psb);
}
-
}
break;
- case fCollision::VF_SS:
+ case fCollision::VF_SS:
{
//only self-collision for Cluster, not Vertex-Face yet
- if (this!=psb)
- {
- btSoftColliders::CollideVF_SS docollide;
- /* common */
- docollide.mrg= getCollisionShape()->getMargin()+
- psb->getCollisionShape()->getMargin();
- /* psb0 nodes vs psb1 faces */
- docollide.psb[0]=this;
- docollide.psb[1]=psb;
- docollide.psb[0]->m_ndbvt.collideTT( docollide.psb[0]->m_ndbvt.m_root,
- docollide.psb[1]->m_fdbvt.m_root,
- docollide);
- /* psb1 nodes vs psb0 faces */
- docollide.psb[0]=psb;
- docollide.psb[1]=this;
- docollide.psb[0]->m_ndbvt.collideTT( docollide.psb[0]->m_ndbvt.m_root,
- docollide.psb[1]->m_fdbvt.m_root,
- docollide);
+ if (this != psb)
+ {
+ btSoftColliders::CollideVF_SS docollide;
+ /* common */
+ docollide.mrg = getCollisionShape()->getMargin() +
+ psb->getCollisionShape()->getMargin();
+ /* psb0 nodes vs psb1 faces */
+ docollide.psb[0] = this;
+ docollide.psb[1] = psb;
+ docollide.psb[0]->m_ndbvt.collideTT(docollide.psb[0]->m_ndbvt.m_root,
+ docollide.psb[1]->m_fdbvt.m_root,
+ docollide);
+ /* psb1 nodes vs psb0 faces */
+ docollide.psb[0] = psb;
+ docollide.psb[1] = this;
+ docollide.psb[0]->m_ndbvt.collideTT(docollide.psb[0]->m_ndbvt.m_root,
+ docollide.psb[1]->m_fdbvt.m_root,
+ docollide);
}
}
break;
- default:
+ default:
{
-
}
}
}
-
-
-void btSoftBody::setWindVelocity( const btVector3 &velocity )
+void btSoftBody::setWindVelocity(const btVector3& velocity)
{
m_windVelocity = velocity;
}
-
const btVector3& btSoftBody::getWindVelocity()
{
return m_windVelocity;
}
-
-
-int btSoftBody::calculateSerializeBufferSize() const
+int btSoftBody::calculateSerializeBufferSize() const
{
int sz = sizeof(btSoftBodyData);
return sz;
}
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
-const char* btSoftBody::serialize(void* dataBuffer, class btSerializer* serializer) const
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char* btSoftBody::serialize(void* dataBuffer, class btSerializer* serializer) const
{
- btSoftBodyData* sbd = (btSoftBodyData*) dataBuffer;
+ btSoftBodyData* sbd = (btSoftBodyData*)dataBuffer;
btCollisionObject::serialize(&sbd->m_collisionObjectData, serializer);
- btHashMap<btHashPtr,int> m_nodeIndexMap;
+ btHashMap<btHashPtr, int> m_nodeIndexMap;
sbd->m_numMaterials = m_materials.size();
- sbd->m_materials = sbd->m_numMaterials? (SoftBodyMaterialData**) serializer->getUniquePointer((void*)&m_materials): 0;
+ sbd->m_materials = sbd->m_numMaterials ? (SoftBodyMaterialData**)serializer->getUniquePointer((void*)&m_materials) : 0;
if (sbd->m_materials)
{
int sz = sizeof(SoftBodyMaterialData*);
int numElem = sbd->m_numMaterials;
- btChunk* chunk = serializer->allocate(sz,numElem);
+ btChunk* chunk = serializer->allocate(sz, numElem);
//SoftBodyMaterialData** memPtr = chunk->m_oldPtr;
SoftBodyMaterialData** memPtr = (SoftBodyMaterialData**)chunk->m_oldPtr;
- for (int i=0;i<numElem;i++,memPtr++)
+ for (int i = 0; i < numElem; i++, memPtr++)
{
btSoftBody::Material* mat = m_materials[i];
*memPtr = mat ? (SoftBodyMaterialData*)serializer->getUniquePointer((void*)mat) : 0;
if (!serializer->findPointer(mat))
{
//serialize it here
- btChunk* chunk = serializer->allocate(sizeof(SoftBodyMaterialData),1);
+ btChunk* chunk = serializer->allocate(sizeof(SoftBodyMaterialData), 1);
SoftBodyMaterialData* memPtr = (SoftBodyMaterialData*)chunk->m_oldPtr;
memPtr->m_flags = mat->m_flags;
memPtr->m_angularStiffness = mat->m_kAST;
memPtr->m_linearStiffness = mat->m_kLST;
memPtr->m_volumeStiffness = mat->m_kVST;
- serializer->finalizeChunk(chunk,"SoftBodyMaterialData",BT_SBMATERIAL_CODE,mat);
+ serializer->finalizeChunk(chunk, "SoftBodyMaterialData", BT_SBMATERIAL_CODE, mat);
}
}
- serializer->finalizeChunk(chunk,"SoftBodyMaterialData",BT_ARRAY_CODE,(void*) &m_materials);
+ serializer->finalizeChunk(chunk, "SoftBodyMaterialData", BT_ARRAY_CODE, (void*)&m_materials);
}
-
-
-
sbd->m_numNodes = m_nodes.size();
- sbd->m_nodes = sbd->m_numNodes ? (SoftBodyNodeData*)serializer->getUniquePointer((void*)&m_nodes): 0;
+ sbd->m_nodes = sbd->m_numNodes ? (SoftBodyNodeData*)serializer->getUniquePointer((void*)&m_nodes) : 0;
if (sbd->m_nodes)
{
int sz = sizeof(SoftBodyNodeData);
int numElem = sbd->m_numNodes;
- btChunk* chunk = serializer->allocate(sz,numElem);
+ btChunk* chunk = serializer->allocate(sz, numElem);
SoftBodyNodeData* memPtr = (SoftBodyNodeData*)chunk->m_oldPtr;
- for (int i=0;i<numElem;i++,memPtr++)
+ for (int i = 0; i < numElem; i++, memPtr++)
{
- m_nodes[i].m_f.serializeFloat( memPtr->m_accumulatedForce);
+ m_nodes[i].m_f.serializeFloat(memPtr->m_accumulatedForce);
memPtr->m_area = m_nodes[i].m_area;
memPtr->m_attach = m_nodes[i].m_battach;
memPtr->m_inverseMass = m_nodes[i].m_im;
- memPtr->m_material = m_nodes[i].m_material? (SoftBodyMaterialData*)serializer->getUniquePointer((void*) m_nodes[i].m_material):0;
+ memPtr->m_material = m_nodes[i].m_material ? (SoftBodyMaterialData*)serializer->getUniquePointer((void*)m_nodes[i].m_material) : 0;
m_nodes[i].m_n.serializeFloat(memPtr->m_normal);
m_nodes[i].m_x.serializeFloat(memPtr->m_position);
m_nodes[i].m_q.serializeFloat(memPtr->m_previousPosition);
m_nodes[i].m_v.serializeFloat(memPtr->m_velocity);
- m_nodeIndexMap.insert(&m_nodes[i],i);
+ m_nodeIndexMap.insert(&m_nodes[i], i);
}
- serializer->finalizeChunk(chunk,"SoftBodyNodeData",BT_SBNODE_CODE,(void*) &m_nodes);
+ serializer->finalizeChunk(chunk, "SoftBodyNodeData", BT_SBNODE_CODE, (void*)&m_nodes);
}
sbd->m_numLinks = m_links.size();
- sbd->m_links = sbd->m_numLinks? (SoftBodyLinkData*) serializer->getUniquePointer((void*)&m_links[0]):0;
+ sbd->m_links = sbd->m_numLinks ? (SoftBodyLinkData*)serializer->getUniquePointer((void*)&m_links[0]) : 0;
if (sbd->m_links)
{
int sz = sizeof(SoftBodyLinkData);
int numElem = sbd->m_numLinks;
- btChunk* chunk = serializer->allocate(sz,numElem);
+ btChunk* chunk = serializer->allocate(sz, numElem);
SoftBodyLinkData* memPtr = (SoftBodyLinkData*)chunk->m_oldPtr;
- for (int i=0;i<numElem;i++,memPtr++)
+ for (int i = 0; i < numElem; i++, memPtr++)
{
memPtr->m_bbending = m_links[i].m_bbending;
- memPtr->m_material = m_links[i].m_material? (SoftBodyMaterialData*)serializer->getUniquePointer((void*) m_links[i].m_material):0;
- memPtr->m_nodeIndices[0] = m_links[i].m_n[0] ? m_links[i].m_n[0] - &m_nodes[0]: -1;
- memPtr->m_nodeIndices[1] = m_links[i].m_n[1] ? m_links[i].m_n[1] - &m_nodes[0]: -1;
- btAssert(memPtr->m_nodeIndices[0]<m_nodes.size());
- btAssert(memPtr->m_nodeIndices[1]<m_nodes.size());
+ memPtr->m_material = m_links[i].m_material ? (SoftBodyMaterialData*)serializer->getUniquePointer((void*)m_links[i].m_material) : 0;
+ memPtr->m_nodeIndices[0] = m_links[i].m_n[0] ? m_links[i].m_n[0] - &m_nodes[0] : -1;
+ memPtr->m_nodeIndices[1] = m_links[i].m_n[1] ? m_links[i].m_n[1] - &m_nodes[0] : -1;
+ btAssert(memPtr->m_nodeIndices[0] < m_nodes.size());
+ btAssert(memPtr->m_nodeIndices[1] < m_nodes.size());
memPtr->m_restLength = m_links[i].m_rl;
}
- serializer->finalizeChunk(chunk,"SoftBodyLinkData",BT_ARRAY_CODE,(void*) &m_links[0]);
-
+ serializer->finalizeChunk(chunk, "SoftBodyLinkData", BT_ARRAY_CODE, (void*)&m_links[0]);
}
-
sbd->m_numFaces = m_faces.size();
- sbd->m_faces = sbd->m_numFaces? (SoftBodyFaceData*) serializer->getUniquePointer((void*)&m_faces[0]):0;
+ sbd->m_faces = sbd->m_numFaces ? (SoftBodyFaceData*)serializer->getUniquePointer((void*)&m_faces[0]) : 0;
if (sbd->m_faces)
{
int sz = sizeof(SoftBodyFaceData);
int numElem = sbd->m_numFaces;
- btChunk* chunk = serializer->allocate(sz,numElem);
+ btChunk* chunk = serializer->allocate(sz, numElem);
SoftBodyFaceData* memPtr = (SoftBodyFaceData*)chunk->m_oldPtr;
- for (int i=0;i<numElem;i++,memPtr++)
+ for (int i = 0; i < numElem; i++, memPtr++)
{
- memPtr->m_material = m_faces[i].m_material ? (SoftBodyMaterialData*) serializer->getUniquePointer((void*)m_faces[i].m_material): 0;
- m_faces[i].m_normal.serializeFloat( memPtr->m_normal);
- for (int j=0;j<3;j++)
+ memPtr->m_material = m_faces[i].m_material ? (SoftBodyMaterialData*)serializer->getUniquePointer((void*)m_faces[i].m_material) : 0;
+ m_faces[i].m_normal.serializeFloat(memPtr->m_normal);
+ for (int j = 0; j < 3; j++)
{
- memPtr->m_nodeIndices[j] = m_faces[i].m_n[j]? m_faces[i].m_n[j] - &m_nodes[0]: -1;
+ memPtr->m_nodeIndices[j] = m_faces[i].m_n[j] ? m_faces[i].m_n[j] - &m_nodes[0] : -1;
}
memPtr->m_restArea = m_faces[i].m_ra;
}
- serializer->finalizeChunk(chunk,"SoftBodyFaceData",BT_ARRAY_CODE,(void*) &m_faces[0]);
+ serializer->finalizeChunk(chunk, "SoftBodyFaceData", BT_ARRAY_CODE, (void*)&m_faces[0]);
}
-
sbd->m_numTetrahedra = m_tetras.size();
- sbd->m_tetrahedra = sbd->m_numTetrahedra ? (SoftBodyTetraData*) serializer->getUniquePointer((void*)&m_tetras[0]):0;
+ sbd->m_tetrahedra = sbd->m_numTetrahedra ? (SoftBodyTetraData*)serializer->getUniquePointer((void*)&m_tetras[0]) : 0;
if (sbd->m_tetrahedra)
{
int sz = sizeof(SoftBodyTetraData);
int numElem = sbd->m_numTetrahedra;
- btChunk* chunk = serializer->allocate(sz,numElem);
+ btChunk* chunk = serializer->allocate(sz, numElem);
SoftBodyTetraData* memPtr = (SoftBodyTetraData*)chunk->m_oldPtr;
- for (int i=0;i<numElem;i++,memPtr++)
+ for (int i = 0; i < numElem; i++, memPtr++)
{
- for (int j=0;j<4;j++)
+ for (int j = 0; j < 4; j++)
{
- m_tetras[i].m_c0[j].serializeFloat( memPtr->m_c0[j] );
- memPtr->m_nodeIndices[j] = m_tetras[j].m_n[j]? m_tetras[j].m_n[j]-&m_nodes[0] : -1;
+ m_tetras[i].m_c0[j].serializeFloat(memPtr->m_c0[j]);
+ memPtr->m_nodeIndices[j] = m_tetras[j].m_n[j] ? m_tetras[j].m_n[j] - &m_nodes[0] : -1;
}
memPtr->m_c1 = m_tetras[i].m_c1;
memPtr->m_c2 = m_tetras[i].m_c2;
- memPtr->m_material = m_tetras[i].m_material ? (SoftBodyMaterialData*)serializer->getUniquePointer((void*) m_tetras[i].m_material): 0;
+ memPtr->m_material = m_tetras[i].m_material ? (SoftBodyMaterialData*)serializer->getUniquePointer((void*)m_tetras[i].m_material) : 0;
memPtr->m_restVolume = m_tetras[i].m_rv;
}
- serializer->finalizeChunk(chunk,"SoftBodyTetraData",BT_ARRAY_CODE,(void*) &m_tetras[0]);
+ serializer->finalizeChunk(chunk, "SoftBodyTetraData", BT_ARRAY_CODE, (void*)&m_tetras[0]);
}
sbd->m_numAnchors = m_anchors.size();
- sbd->m_anchors = sbd->m_numAnchors ? (SoftRigidAnchorData*) serializer->getUniquePointer((void*)&m_anchors[0]):0;
+ sbd->m_anchors = sbd->m_numAnchors ? (SoftRigidAnchorData*)serializer->getUniquePointer((void*)&m_anchors[0]) : 0;
if (sbd->m_anchors)
{
int sz = sizeof(SoftRigidAnchorData);
int numElem = sbd->m_numAnchors;
- btChunk* chunk = serializer->allocate(sz,numElem);
+ btChunk* chunk = serializer->allocate(sz, numElem);
SoftRigidAnchorData* memPtr = (SoftRigidAnchorData*)chunk->m_oldPtr;
- for (int i=0;i<numElem;i++,memPtr++)
+ for (int i = 0; i < numElem; i++, memPtr++)
{
m_anchors[i].m_c0.serializeFloat(memPtr->m_c0);
m_anchors[i].m_c1.serializeFloat(memPtr->m_c1);
memPtr->m_c2 = m_anchors[i].m_c2;
m_anchors[i].m_local.serializeFloat(memPtr->m_localFrame);
- memPtr->m_nodeIndex = m_anchors[i].m_node? m_anchors[i].m_node-&m_nodes[0]: -1;
-
- memPtr->m_rigidBody = m_anchors[i].m_body? (btRigidBodyData*) serializer->getUniquePointer((void*)m_anchors[i].m_body): 0;
+ memPtr->m_nodeIndex = m_anchors[i].m_node ? m_anchors[i].m_node - &m_nodes[0] : -1;
+
+ memPtr->m_rigidBody = m_anchors[i].m_body ? (btRigidBodyData*)serializer->getUniquePointer((void*)m_anchors[i].m_body) : 0;
btAssert(memPtr->m_nodeIndex < m_nodes.size());
}
- serializer->finalizeChunk(chunk,"SoftRigidAnchorData",BT_ARRAY_CODE,(void*) &m_anchors[0]);
+ serializer->finalizeChunk(chunk, "SoftRigidAnchorData", BT_ARRAY_CODE, (void*)&m_anchors[0]);
}
-
sbd->m_config.m_dynamicFriction = m_cfg.kDF;
sbd->m_config.m_baumgarte = m_cfg.kVCF;
@@ -3501,64 +3499,63 @@ const char* btSoftBody::serialize(void* dataBuffer, class btSerializer* serializ
sbd->m_pose = (SoftBodyPoseData*)serializer->getUniquePointer((void*)&m_pose);
int sz = sizeof(SoftBodyPoseData);
- btChunk* chunk = serializer->allocate(sz,1);
+ btChunk* chunk = serializer->allocate(sz, 1);
SoftBodyPoseData* memPtr = (SoftBodyPoseData*)chunk->m_oldPtr;
-
+
m_pose.m_aqq.serializeFloat(memPtr->m_aqq);
memPtr->m_bframe = m_pose.m_bframe;
memPtr->m_bvolume = m_pose.m_bvolume;
m_pose.m_com.serializeFloat(memPtr->m_com);
-
+
memPtr->m_numPositions = m_pose.m_pos.size();
- memPtr->m_positions = memPtr->m_numPositions ? (btVector3FloatData*)serializer->getUniquePointer((void*)&m_pose.m_pos[0]): 0;
+ memPtr->m_positions = memPtr->m_numPositions ? (btVector3FloatData*)serializer->getUniquePointer((void*)&m_pose.m_pos[0]) : 0;
if (memPtr->m_numPositions)
{
int numElem = memPtr->m_numPositions;
int sz = sizeof(btVector3Data);
- btChunk* chunk = serializer->allocate(sz,numElem);
+ btChunk* chunk = serializer->allocate(sz, numElem);
btVector3FloatData* memPtr = (btVector3FloatData*)chunk->m_oldPtr;
- for (int i=0;i<numElem;i++,memPtr++)
+ for (int i = 0; i < numElem; i++, memPtr++)
{
m_pose.m_pos[i].serializeFloat(*memPtr);
}
- serializer->finalizeChunk(chunk,"btVector3FloatData",BT_ARRAY_CODE,(void*)&m_pose.m_pos[0]);
+ serializer->finalizeChunk(chunk, "btVector3FloatData", BT_ARRAY_CODE, (void*)&m_pose.m_pos[0]);
}
memPtr->m_restVolume = m_pose.m_volume;
m_pose.m_rot.serializeFloat(memPtr->m_rot);
m_pose.m_scl.serializeFloat(memPtr->m_scale);
memPtr->m_numWeigts = m_pose.m_wgh.size();
- memPtr->m_weights = memPtr->m_numWeigts? (float*) serializer->getUniquePointer((void*) &m_pose.m_wgh[0]) : 0;
+ memPtr->m_weights = memPtr->m_numWeigts ? (float*)serializer->getUniquePointer((void*)&m_pose.m_wgh[0]) : 0;
if (memPtr->m_numWeigts)
{
-
int numElem = memPtr->m_numWeigts;
int sz = sizeof(float);
- btChunk* chunk = serializer->allocate(sz,numElem);
- float* memPtr = (float*) chunk->m_oldPtr;
- for (int i=0;i<numElem;i++,memPtr++)
+ btChunk* chunk = serializer->allocate(sz, numElem);
+ float* memPtr = (float*)chunk->m_oldPtr;
+ for (int i = 0; i < numElem; i++, memPtr++)
{
*memPtr = m_pose.m_wgh[i];
}
- serializer->finalizeChunk(chunk,"float",BT_ARRAY_CODE,(void*)&m_pose.m_wgh[0]);
+ serializer->finalizeChunk(chunk, "float", BT_ARRAY_CODE, (void*)&m_pose.m_wgh[0]);
}
- serializer->finalizeChunk(chunk,"SoftBodyPoseData",BT_ARRAY_CODE,(void*)&m_pose);
+ serializer->finalizeChunk(chunk, "SoftBodyPoseData", BT_ARRAY_CODE, (void*)&m_pose);
}
//clusters for convex-cluster collision detection
sbd->m_numClusters = m_clusters.size();
- sbd->m_clusters = sbd->m_numClusters? (SoftBodyClusterData*) serializer->getUniquePointer((void*)m_clusters[0]) : 0;
+ sbd->m_clusters = sbd->m_numClusters ? (SoftBodyClusterData*)serializer->getUniquePointer((void*)m_clusters[0]) : 0;
if (sbd->m_numClusters)
{
int numElem = sbd->m_numClusters;
int sz = sizeof(SoftBodyClusterData);
- btChunk* chunk = serializer->allocate(sz,numElem);
- SoftBodyClusterData* memPtr = (SoftBodyClusterData*) chunk->m_oldPtr;
- for (int i=0;i<numElem;i++,memPtr++)
+ btChunk* chunk = serializer->allocate(sz, numElem);
+ SoftBodyClusterData* memPtr = (SoftBodyClusterData*)chunk->m_oldPtr;
+ for (int i = 0; i < numElem; i++, memPtr++)
{
- memPtr->m_adamping= m_clusters[i]->m_adamping;
+ memPtr->m_adamping = m_clusters[i]->m_adamping;
m_clusters[i]->m_av.serializeFloat(memPtr->m_av);
memPtr->m_clusterIndex = m_clusters[i]->m_clusterIndex;
memPtr->m_collide = m_clusters[i]->m_collide;
@@ -3589,69 +3586,64 @@ const char* btSoftBody::serialize(void* dataBuffer, class btSerializer* serializ
m_clusters[i]->m_vimpulses[1].serializeFloat(memPtr->m_vimpulses[1]);
memPtr->m_ndimpulses = m_clusters[i]->m_ndimpulses;
-
-
- memPtr->m_framerefs = memPtr->m_numFrameRefs? (btVector3FloatData*)serializer->getUniquePointer((void*)&m_clusters[i]->m_framerefs[0]) : 0;
+ memPtr->m_framerefs = memPtr->m_numFrameRefs ? (btVector3FloatData*)serializer->getUniquePointer((void*)&m_clusters[i]->m_framerefs[0]) : 0;
if (memPtr->m_framerefs)
{
int numElem = memPtr->m_numFrameRefs;
int sz = sizeof(btVector3FloatData);
- btChunk* chunk = serializer->allocate(sz,numElem);
- btVector3FloatData* memPtr = (btVector3FloatData*) chunk->m_oldPtr;
- for (int j=0;j<numElem;j++,memPtr++)
+ btChunk* chunk = serializer->allocate(sz, numElem);
+ btVector3FloatData* memPtr = (btVector3FloatData*)chunk->m_oldPtr;
+ for (int j = 0; j < numElem; j++, memPtr++)
{
m_clusters[i]->m_framerefs[j].serializeFloat(*memPtr);
}
- serializer->finalizeChunk(chunk,"btVector3FloatData",BT_ARRAY_CODE,(void*)&m_clusters[i]->m_framerefs[0]);
+ serializer->finalizeChunk(chunk, "btVector3FloatData", BT_ARRAY_CODE, (void*)&m_clusters[i]->m_framerefs[0]);
}
-
- memPtr->m_masses = memPtr->m_numMasses ? (float*) serializer->getUniquePointer((void*)&m_clusters[i]->m_masses[0]): 0;
+
+ memPtr->m_masses = memPtr->m_numMasses ? (float*)serializer->getUniquePointer((void*)&m_clusters[i]->m_masses[0]) : 0;
if (memPtr->m_masses)
{
int numElem = memPtr->m_numMasses;
int sz = sizeof(float);
- btChunk* chunk = serializer->allocate(sz,numElem);
- float* memPtr = (float*) chunk->m_oldPtr;
- for (int j=0;j<numElem;j++,memPtr++)
+ btChunk* chunk = serializer->allocate(sz, numElem);
+ float* memPtr = (float*)chunk->m_oldPtr;
+ for (int j = 0; j < numElem; j++, memPtr++)
{
*memPtr = m_clusters[i]->m_masses[j];
}
- serializer->finalizeChunk(chunk,"float",BT_ARRAY_CODE,(void*)&m_clusters[i]->m_masses[0]);
+ serializer->finalizeChunk(chunk, "float", BT_ARRAY_CODE, (void*)&m_clusters[i]->m_masses[0]);
}
- memPtr->m_nodeIndices = memPtr->m_numNodes ? (int*) serializer->getUniquePointer((void*) &m_clusters[i]->m_nodes) : 0;
- if (memPtr->m_nodeIndices )
+ memPtr->m_nodeIndices = memPtr->m_numNodes ? (int*)serializer->getUniquePointer((void*)&m_clusters[i]->m_nodes) : 0;
+ if (memPtr->m_nodeIndices)
{
int numElem = memPtr->m_numMasses;
int sz = sizeof(int);
- btChunk* chunk = serializer->allocate(sz,numElem);
- int* memPtr = (int*) chunk->m_oldPtr;
- for (int j=0;j<numElem;j++,memPtr++)
+ btChunk* chunk = serializer->allocate(sz, numElem);
+ int* memPtr = (int*)chunk->m_oldPtr;
+ for (int j = 0; j < numElem; j++, memPtr++)
{
int* indexPtr = m_nodeIndexMap.find(m_clusters[i]->m_nodes[j]);
btAssert(indexPtr);
*memPtr = *indexPtr;
}
- serializer->finalizeChunk(chunk,"int",BT_ARRAY_CODE,(void*)&m_clusters[i]->m_nodes);
+ serializer->finalizeChunk(chunk, "int", BT_ARRAY_CODE, (void*)&m_clusters[i]->m_nodes);
}
}
- serializer->finalizeChunk(chunk,"SoftBodyClusterData",BT_ARRAY_CODE,(void*)m_clusters[0]);
-
+ serializer->finalizeChunk(chunk, "SoftBodyClusterData", BT_ARRAY_CODE, (void*)m_clusters[0]);
}
-
-
sbd->m_numJoints = m_joints.size();
- sbd->m_joints = m_joints.size()? (btSoftBodyJointData*) serializer->getUniquePointer((void*)&m_joints[0]) : 0;
+ sbd->m_joints = m_joints.size() ? (btSoftBodyJointData*)serializer->getUniquePointer((void*)&m_joints[0]) : 0;
if (sbd->m_joints)
{
int sz = sizeof(btSoftBodyJointData);
int numElem = m_joints.size();
- btChunk* chunk = serializer->allocate(sz,numElem);
+ btChunk* chunk = serializer->allocate(sz, numElem);
btSoftBodyJointData* memPtr = (btSoftBodyJointData*)chunk->m_oldPtr;
- for (int i=0;i<numElem;i++,memPtr++)
+ for (int i = 0; i < numElem; i++, memPtr++)
{
memPtr->m_jointType = (int)m_joints[i]->Type();
m_joints[i]->m_refs[0].serializeFloat(memPtr->m_refs[0]);
@@ -3660,8 +3652,8 @@ const char* btSoftBody::serialize(void* dataBuffer, class btSerializer* serializ
memPtr->m_erp = float(m_joints[i]->m_erp);
memPtr->m_split = float(m_joints[i]->m_split);
memPtr->m_delete = m_joints[i]->m_delete;
-
- for (int j=0;j<4;j++)
+
+ for (int j = 0; j < 4; j++)
{
memPtr->m_relPosition[0].m_floats[j] = 0.f;
memPtr->m_relPosition[1].m_floats[j] = 0.f;
@@ -3700,10 +3692,8 @@ const char* btSoftBody::serialize(void* dataBuffer, class btSerializer* serializ
memPtr->m_bodyB = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[1].m_rigid);
}
}
- serializer->finalizeChunk(chunk,"btSoftBodyJointData",BT_ARRAY_CODE,(void*) &m_joints[0]);
+ serializer->finalizeChunk(chunk, "btSoftBodyJointData", BT_ARRAY_CODE, (void*)&m_joints[0]);
}
-
return btSoftBodyDataName;
}
-
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftBody.h b/thirdparty/bullet/BulletSoftBody/btSoftBody.h
index ada0dfd1a5..9b35b799d8 100644
--- a/thirdparty/bullet/BulletSoftBody/btSoftBody.h
+++ b/thirdparty/bullet/BulletSoftBody/btSoftBody.h
@@ -31,862 +31,890 @@ subject to the following restrictions:
//#define btRigidBodyData btRigidBodyDoubleData
//#define btRigidBodyDataName "btRigidBodyDoubleData"
//#else
-#define btSoftBodyData btSoftBodyFloatData
-#define btSoftBodyDataName "btSoftBodyFloatData"
+#define btSoftBodyData btSoftBodyFloatData
+#define btSoftBodyDataName "btSoftBodyFloatData"
//#endif //BT_USE_DOUBLE_PRECISION
class btBroadphaseInterface;
class btDispatcher;
class btSoftBodySolver;
-/* btSoftBodyWorldInfo */
-struct btSoftBodyWorldInfo
+/* btSoftBodyWorldInfo */
+struct btSoftBodyWorldInfo
{
- btScalar air_density;
- btScalar water_density;
- btScalar water_offset;
- btScalar m_maxDisplacement;
- btVector3 water_normal;
- btBroadphaseInterface* m_broadphase;
- btDispatcher* m_dispatcher;
- btVector3 m_gravity;
- btSparseSdf<3> m_sparsesdf;
+ btScalar air_density;
+ btScalar water_density;
+ btScalar water_offset;
+ btScalar m_maxDisplacement;
+ btVector3 water_normal;
+ btBroadphaseInterface* m_broadphase;
+ btDispatcher* m_dispatcher;
+ btVector3 m_gravity;
+ btSparseSdf<3> m_sparsesdf;
btSoftBodyWorldInfo()
- :air_density((btScalar)1.2),
- water_density(0),
- water_offset(0),
- m_maxDisplacement(1000.f),//avoid soft body from 'exploding' so use some upper threshold of maximum motion that a node can travel per frame
- water_normal(0,0,0),
- m_broadphase(0),
- m_dispatcher(0),
- m_gravity(0,-10,0)
+ : air_density((btScalar)1.2),
+ water_density(0),
+ water_offset(0),
+ m_maxDisplacement(1000.f), //avoid soft body from 'exploding' so use some upper threshold of maximum motion that a node can travel per frame
+ water_normal(0, 0, 0),
+ m_broadphase(0),
+ m_dispatcher(0),
+ m_gravity(0, -10, 0)
{
}
-};
-
+};
-///The btSoftBody is an class to simulate cloth and volumetric soft bodies.
+///The btSoftBody is an class to simulate cloth and volumetric soft bodies.
///There is two-way interaction between btSoftBody and btRigidBody/btCollisionObject.
-class btSoftBody : public btCollisionObject
+class btSoftBody : public btCollisionObject
{
public:
btAlignedObjectArray<const class btCollisionObject*> m_collisionDisabledObjects;
// The solver object that handles this soft body
- btSoftBodySolver *m_softBodySolver;
+ btSoftBodySolver* m_softBodySolver;
//
// Enumerations
//
- ///eAeroModel
- struct eAeroModel { enum _ {
- V_Point, ///Vertex normals are oriented toward velocity
- V_TwoSided, ///Vertex normals are flipped to match velocity
- V_TwoSidedLiftDrag, ///Vertex normals are flipped to match velocity and lift and drag forces are applied
- V_OneSided, ///Vertex normals are taken as it is
- F_TwoSided, ///Face normals are flipped to match velocity
- F_TwoSidedLiftDrag, ///Face normals are flipped to match velocity and lift and drag forces are applied
- F_OneSided, ///Face normals are taken as it is
- END
- };};
+ ///eAeroModel
+ struct eAeroModel
+ {
+ enum _
+ {
+ V_Point, ///Vertex normals are oriented toward velocity
+ V_TwoSided, ///Vertex normals are flipped to match velocity
+ V_TwoSidedLiftDrag, ///Vertex normals are flipped to match velocity and lift and drag forces are applied
+ V_OneSided, ///Vertex normals are taken as it is
+ F_TwoSided, ///Face normals are flipped to match velocity
+ F_TwoSidedLiftDrag, ///Face normals are flipped to match velocity and lift and drag forces are applied
+ F_OneSided, ///Face normals are taken as it is
+ END
+ };
+ };
///eVSolver : velocities solvers
- struct eVSolver { enum _ {
- Linear, ///Linear solver
- END
- };};
+ struct eVSolver
+ {
+ enum _
+ {
+ Linear, ///Linear solver
+ END
+ };
+ };
///ePSolver : positions solvers
- struct ePSolver { enum _ {
- Linear, ///Linear solver
- Anchors, ///Anchor solver
- RContacts, ///Rigid contacts solver
- SContacts, ///Soft contacts solver
- END
- };};
+ struct ePSolver
+ {
+ enum _
+ {
+ Linear, ///Linear solver
+ Anchors, ///Anchor solver
+ RContacts, ///Rigid contacts solver
+ SContacts, ///Soft contacts solver
+ END
+ };
+ };
///eSolverPresets
- struct eSolverPresets { enum _ {
- Positions,
- Velocities,
- Default = Positions,
- END
- };};
+ struct eSolverPresets
+ {
+ enum _
+ {
+ Positions,
+ Velocities,
+ Default = Positions,
+ END
+ };
+ };
///eFeature
- struct eFeature { enum _ {
- None,
- Node,
- Link,
- Face,
- Tetra,
- END
- };};
-
- typedef btAlignedObjectArray<eVSolver::_> tVSolverArray;
- typedef btAlignedObjectArray<ePSolver::_> tPSolverArray;
+ struct eFeature
+ {
+ enum _
+ {
+ None,
+ Node,
+ Link,
+ Face,
+ Tetra,
+ END
+ };
+ };
+
+ typedef btAlignedObjectArray<eVSolver::_> tVSolverArray;
+ typedef btAlignedObjectArray<ePSolver::_> tPSolverArray;
//
// Flags
//
///fCollision
- struct fCollision { enum _ {
- RVSmask = 0x000f, ///Rigid versus soft mask
- SDF_RS = 0x0001, ///SDF based rigid vs soft
- CL_RS = 0x0002, ///Cluster vs convex rigid vs soft
-
- SVSmask = 0x0030, ///Rigid versus soft mask
- VF_SS = 0x0010, ///Vertex vs face soft vs soft handling
- CL_SS = 0x0020, ///Cluster vs cluster soft vs soft handling
- CL_SELF = 0x0040, ///Cluster soft body self collision
- /* presets */
- Default = SDF_RS,
- END
- };};
+ struct fCollision
+ {
+ enum _
+ {
+ RVSmask = 0x000f, ///Rigid versus soft mask
+ SDF_RS = 0x0001, ///SDF based rigid vs soft
+ CL_RS = 0x0002, ///Cluster vs convex rigid vs soft
+
+ SVSmask = 0x0030, ///Rigid versus soft mask
+ VF_SS = 0x0010, ///Vertex vs face soft vs soft handling
+ CL_SS = 0x0020, ///Cluster vs cluster soft vs soft handling
+ CL_SELF = 0x0040, ///Cluster soft body self collision
+ /* presets */
+ Default = SDF_RS,
+ END
+ };
+ };
///fMaterial
- struct fMaterial { enum _ {
- DebugDraw = 0x0001, /// Enable debug draw
- /* presets */
- Default = DebugDraw,
- END
- };};
+ struct fMaterial
+ {
+ enum _
+ {
+ DebugDraw = 0x0001, /// Enable debug draw
+ /* presets */
+ Default = DebugDraw,
+ END
+ };
+ };
//
// API Types
//
- /* sRayCast */
+ /* sRayCast */
struct sRayCast
{
- btSoftBody* body; /// soft body
- eFeature::_ feature; /// feature type
- int index; /// feature index
- btScalar fraction; /// time of impact fraction (rayorg+(rayto-rayfrom)*fraction)
+ btSoftBody* body; /// soft body
+ eFeature::_ feature; /// feature type
+ int index; /// feature index
+ btScalar fraction; /// time of impact fraction (rayorg+(rayto-rayfrom)*fraction)
};
- /* ImplicitFn */
- struct ImplicitFn
+ /* ImplicitFn */
+ struct ImplicitFn
{
virtual ~ImplicitFn() {}
- virtual btScalar Eval(const btVector3& x)=0;
+ virtual btScalar Eval(const btVector3& x) = 0;
};
//
// Internal types
//
- typedef btAlignedObjectArray<btScalar> tScalarArray;
- typedef btAlignedObjectArray<btVector3> tVector3Array;
+ typedef btAlignedObjectArray<btScalar> tScalarArray;
+ typedef btAlignedObjectArray<btVector3> tVector3Array;
- /* sCti is Softbody contact info */
- struct sCti
+ /* sCti is Softbody contact info */
+ struct sCti
{
- const btCollisionObject* m_colObj; /* Rigid body */
- btVector3 m_normal; /* Outward normal */
- btScalar m_offset; /* Offset from origin */
- };
+ const btCollisionObject* m_colObj; /* Rigid body */
+ btVector3 m_normal; /* Outward normal */
+ btScalar m_offset; /* Offset from origin */
+ };
- /* sMedium */
- struct sMedium
+ /* sMedium */
+ struct sMedium
{
- btVector3 m_velocity; /* Velocity */
- btScalar m_pressure; /* Pressure */
- btScalar m_density; /* Density */
+ btVector3 m_velocity; /* Velocity */
+ btScalar m_pressure; /* Pressure */
+ btScalar m_density; /* Density */
};
- /* Base type */
- struct Element
+ /* Base type */
+ struct Element
{
- void* m_tag; // User data
+ void* m_tag; // User data
Element() : m_tag(0) {}
};
- /* Material */
- struct Material : Element
+ /* Material */
+ struct Material : Element
{
- btScalar m_kLST; // Linear stiffness coefficient [0,1]
- btScalar m_kAST; // Area/Angular stiffness coefficient [0,1]
- btScalar m_kVST; // Volume stiffness coefficient [0,1]
- int m_flags; // Flags
+ btScalar m_kLST; // Linear stiffness coefficient [0,1]
+ btScalar m_kAST; // Area/Angular stiffness coefficient [0,1]
+ btScalar m_kVST; // Volume stiffness coefficient [0,1]
+ int m_flags; // Flags
};
- /* Feature */
- struct Feature : Element
+ /* Feature */
+ struct Feature : Element
{
- Material* m_material; // Material
+ Material* m_material; // Material
};
- /* Node */
- struct Node : Feature
+ /* Node */
+ struct Node : Feature
{
- btVector3 m_x; // Position
- btVector3 m_q; // Previous step position
- btVector3 m_v; // Velocity
- btVector3 m_f; // Force accumulator
- btVector3 m_n; // Normal
- btScalar m_im; // 1/mass
- btScalar m_area; // Area
- btDbvtNode* m_leaf; // Leaf data
- int m_battach:1; // Attached
+ btVector3 m_x; // Position
+ btVector3 m_q; // Previous step position
+ btVector3 m_v; // Velocity
+ btVector3 m_f; // Force accumulator
+ btVector3 m_n; // Normal
+ btScalar m_im; // 1/mass
+ btScalar m_area; // Area
+ btDbvtNode* m_leaf; // Leaf data
+ int m_battach : 1; // Attached
};
- /* Link */
- ATTRIBUTE_ALIGNED16(struct) Link : Feature
+ /* Link */
+ ATTRIBUTE_ALIGNED16(struct)
+ Link : Feature
{
- btVector3 m_c3; // gradient
- Node* m_n[2]; // Node pointers
- btScalar m_rl; // Rest length
- int m_bbending:1; // Bending link
- btScalar m_c0; // (ima+imb)*kLST
- btScalar m_c1; // rl^2
- btScalar m_c2; // |gradient|^2/c0
-
- BT_DECLARE_ALIGNED_ALLOCATOR();
+ btVector3 m_c3; // gradient
+ Node* m_n[2]; // Node pointers
+ btScalar m_rl; // Rest length
+ int m_bbending : 1; // Bending link
+ btScalar m_c0; // (ima+imb)*kLST
+ btScalar m_c1; // rl^2
+ btScalar m_c2; // |gradient|^2/c0
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+ };
+ /* Face */
+ struct Face : Feature
+ {
+ Node* m_n[3]; // Node pointers
+ btVector3 m_normal; // Normal
+ btScalar m_ra; // Rest area
+ btDbvtNode* m_leaf; // Leaf data
+ };
+ /* Tetra */
+ struct Tetra : Feature
+ {
+ Node* m_n[4]; // Node pointers
+ btScalar m_rv; // Rest volume
+ btDbvtNode* m_leaf; // Leaf data
+ btVector3 m_c0[4]; // gradients
+ btScalar m_c1; // (4*kVST)/(im0+im1+im2+im3)
+ btScalar m_c2; // m_c1/sum(|g0..3|^2)
+ };
+ /* RContact */
+ struct RContact
+ {
+ sCti m_cti; // Contact infos
+ Node* m_node; // Owner node
+ btMatrix3x3 m_c0; // Impulse matrix
+ btVector3 m_c1; // Relative anchor
+ btScalar m_c2; // ima*dt
+ btScalar m_c3; // Friction
+ btScalar m_c4; // Hardness
+ };
+ /* SContact */
+ struct SContact
+ {
+ Node* m_node; // Node
+ Face* m_face; // Face
+ btVector3 m_weights; // Weigths
+ btVector3 m_normal; // Normal
+ btScalar m_margin; // Margin
+ btScalar m_friction; // Friction
+ btScalar m_cfm[2]; // Constraint force mixing
};
- /* Face */
- struct Face : Feature
- {
- Node* m_n[3]; // Node pointers
- btVector3 m_normal; // Normal
- btScalar m_ra; // Rest area
- btDbvtNode* m_leaf; // Leaf data
- };
- /* Tetra */
- struct Tetra : Feature
- {
- Node* m_n[4]; // Node pointers
- btScalar m_rv; // Rest volume
- btDbvtNode* m_leaf; // Leaf data
- btVector3 m_c0[4]; // gradients
- btScalar m_c1; // (4*kVST)/(im0+im1+im2+im3)
- btScalar m_c2; // m_c1/sum(|g0..3|^2)
- };
- /* RContact */
- struct RContact
- {
- sCti m_cti; // Contact infos
- Node* m_node; // Owner node
- btMatrix3x3 m_c0; // Impulse matrix
- btVector3 m_c1; // Relative anchor
- btScalar m_c2; // ima*dt
- btScalar m_c3; // Friction
- btScalar m_c4; // Hardness
- };
- /* SContact */
- struct SContact
- {
- Node* m_node; // Node
- Face* m_face; // Face
- btVector3 m_weights; // Weigths
- btVector3 m_normal; // Normal
- btScalar m_margin; // Margin
- btScalar m_friction; // Friction
- btScalar m_cfm[2]; // Constraint force mixing
- };
- /* Anchor */
- struct Anchor
- {
- Node* m_node; // Node pointer
- btVector3 m_local; // Anchor position in body space
- btRigidBody* m_body; // Body
- btScalar m_influence;
- btMatrix3x3 m_c0; // Impulse matrix
- btVector3 m_c1; // Relative anchor
- btScalar m_c2; // ima*dt
- };
- /* Note */
- struct Note : Element
- {
- const char* m_text; // Text
- btVector3 m_offset; // Offset
- int m_rank; // Rank
- Node* m_nodes[4]; // Nodes
- btScalar m_coords[4]; // Coordinates
- };
- /* Pose */
- struct Pose
- {
- bool m_bvolume; // Is valid
- bool m_bframe; // Is frame
- btScalar m_volume; // Rest volume
- tVector3Array m_pos; // Reference positions
- tScalarArray m_wgh; // Weights
- btVector3 m_com; // COM
- btMatrix3x3 m_rot; // Rotation
- btMatrix3x3 m_scl; // Scale
- btMatrix3x3 m_aqq; // Base scaling
- };
- /* Cluster */
- struct Cluster
- {
- tScalarArray m_masses;
- btAlignedObjectArray<Node*> m_nodes;
- tVector3Array m_framerefs;
- btTransform m_framexform;
- btScalar m_idmass;
- btScalar m_imass;
- btMatrix3x3 m_locii;
- btMatrix3x3 m_invwi;
- btVector3 m_com;
- btVector3 m_vimpulses[2];
- btVector3 m_dimpulses[2];
- int m_nvimpulses;
- int m_ndimpulses;
- btVector3 m_lv;
- btVector3 m_av;
- btDbvtNode* m_leaf;
- btScalar m_ndamping; /* Node damping */
- btScalar m_ldamping; /* Linear damping */
- btScalar m_adamping; /* Angular damping */
- btScalar m_matching;
- btScalar m_maxSelfCollisionImpulse;
- btScalar m_selfCollisionImpulseFactor;
- bool m_containsAnchor;
- bool m_collide;
- int m_clusterIndex;
- Cluster() : m_leaf(0),m_ndamping(0),m_ldamping(0),m_adamping(0),m_matching(0)
- ,m_maxSelfCollisionImpulse(100.f),
- m_selfCollisionImpulseFactor(0.01f),
- m_containsAnchor(false)
- {}
- };
- /* Impulse */
- struct Impulse
- {
- btVector3 m_velocity;
- btVector3 m_drift;
- int m_asVelocity:1;
- int m_asDrift:1;
- Impulse() : m_velocity(0,0,0),m_drift(0,0,0),m_asVelocity(0),m_asDrift(0) {}
- Impulse operator -() const
+ /* Anchor */
+ struct Anchor
+ {
+ Node* m_node; // Node pointer
+ btVector3 m_local; // Anchor position in body space
+ btRigidBody* m_body; // Body
+ btScalar m_influence;
+ btMatrix3x3 m_c0; // Impulse matrix
+ btVector3 m_c1; // Relative anchor
+ btScalar m_c2; // ima*dt
+ };
+ /* Note */
+ struct Note : Element
+ {
+ const char* m_text; // Text
+ btVector3 m_offset; // Offset
+ int m_rank; // Rank
+ Node* m_nodes[4]; // Nodes
+ btScalar m_coords[4]; // Coordinates
+ };
+ /* Pose */
+ struct Pose
+ {
+ bool m_bvolume; // Is valid
+ bool m_bframe; // Is frame
+ btScalar m_volume; // Rest volume
+ tVector3Array m_pos; // Reference positions
+ tScalarArray m_wgh; // Weights
+ btVector3 m_com; // COM
+ btMatrix3x3 m_rot; // Rotation
+ btMatrix3x3 m_scl; // Scale
+ btMatrix3x3 m_aqq; // Base scaling
+ };
+ /* Cluster */
+ struct Cluster
+ {
+ tScalarArray m_masses;
+ btAlignedObjectArray<Node*> m_nodes;
+ tVector3Array m_framerefs;
+ btTransform m_framexform;
+ btScalar m_idmass;
+ btScalar m_imass;
+ btMatrix3x3 m_locii;
+ btMatrix3x3 m_invwi;
+ btVector3 m_com;
+ btVector3 m_vimpulses[2];
+ btVector3 m_dimpulses[2];
+ int m_nvimpulses;
+ int m_ndimpulses;
+ btVector3 m_lv;
+ btVector3 m_av;
+ btDbvtNode* m_leaf;
+ btScalar m_ndamping; /* Node damping */
+ btScalar m_ldamping; /* Linear damping */
+ btScalar m_adamping; /* Angular damping */
+ btScalar m_matching;
+ btScalar m_maxSelfCollisionImpulse;
+ btScalar m_selfCollisionImpulseFactor;
+ bool m_containsAnchor;
+ bool m_collide;
+ int m_clusterIndex;
+ Cluster() : m_leaf(0), m_ndamping(0), m_ldamping(0), m_adamping(0), m_matching(0), m_maxSelfCollisionImpulse(100.f), m_selfCollisionImpulseFactor(0.01f), m_containsAnchor(false)
+ {
+ }
+ };
+ /* Impulse */
+ struct Impulse
+ {
+ btVector3 m_velocity;
+ btVector3 m_drift;
+ int m_asVelocity : 1;
+ int m_asDrift : 1;
+ Impulse() : m_velocity(0, 0, 0), m_drift(0, 0, 0), m_asVelocity(0), m_asDrift(0) {}
+ Impulse operator-() const
{
- Impulse i=*this;
- i.m_velocity=-i.m_velocity;
- i.m_drift=-i.m_drift;
- return(i);
+ Impulse i = *this;
+ i.m_velocity = -i.m_velocity;
+ i.m_drift = -i.m_drift;
+ return (i);
}
- Impulse operator*(btScalar x) const
+ Impulse operator*(btScalar x) const
{
- Impulse i=*this;
- i.m_velocity*=x;
- i.m_drift*=x;
- return(i);
+ Impulse i = *this;
+ i.m_velocity *= x;
+ i.m_drift *= x;
+ return (i);
}
};
- /* Body */
- struct Body
+ /* Body */
+ struct Body
{
- Cluster* m_soft;
- btRigidBody* m_rigid;
- const btCollisionObject* m_collisionObject;
+ Cluster* m_soft;
+ btRigidBody* m_rigid;
+ const btCollisionObject* m_collisionObject;
- Body() : m_soft(0),m_rigid(0),m_collisionObject(0) {}
- Body(Cluster* p) : m_soft(p),m_rigid(0),m_collisionObject(0) {}
- Body(const btCollisionObject* colObj) : m_soft(0),m_collisionObject(colObj)
+ Body() : m_soft(0), m_rigid(0), m_collisionObject(0) {}
+ Body(Cluster* p) : m_soft(p), m_rigid(0), m_collisionObject(0) {}
+ Body(const btCollisionObject* colObj) : m_soft(0), m_collisionObject(colObj)
{
m_rigid = (btRigidBody*)btRigidBody::upcast(m_collisionObject);
}
- void activate() const
+ void activate() const
{
- if(m_rigid)
+ if (m_rigid)
m_rigid->activate();
if (m_collisionObject)
m_collisionObject->activate();
-
}
- const btMatrix3x3& invWorldInertia() const
+ const btMatrix3x3& invWorldInertia() const
{
- static const btMatrix3x3 iwi(0,0,0,0,0,0,0,0,0);
- if(m_rigid) return(m_rigid->getInvInertiaTensorWorld());
- if(m_soft) return(m_soft->m_invwi);
- return(iwi);
+ static const btMatrix3x3 iwi(0, 0, 0, 0, 0, 0, 0, 0, 0);
+ if (m_rigid) return (m_rigid->getInvInertiaTensorWorld());
+ if (m_soft) return (m_soft->m_invwi);
+ return (iwi);
}
- btScalar invMass() const
+ btScalar invMass() const
{
- if(m_rigid) return(m_rigid->getInvMass());
- if(m_soft) return(m_soft->m_imass);
- return(0);
+ if (m_rigid) return (m_rigid->getInvMass());
+ if (m_soft) return (m_soft->m_imass);
+ return (0);
}
- const btTransform& xform() const
+ const btTransform& xform() const
{
- static const btTransform identity=btTransform::getIdentity();
- if(m_collisionObject) return(m_collisionObject->getWorldTransform());
- if(m_soft) return(m_soft->m_framexform);
- return(identity);
+ static const btTransform identity = btTransform::getIdentity();
+ if (m_collisionObject) return (m_collisionObject->getWorldTransform());
+ if (m_soft) return (m_soft->m_framexform);
+ return (identity);
}
- btVector3 linearVelocity() const
+ btVector3 linearVelocity() const
{
- if(m_rigid) return(m_rigid->getLinearVelocity());
- if(m_soft) return(m_soft->m_lv);
- return(btVector3(0,0,0));
+ if (m_rigid) return (m_rigid->getLinearVelocity());
+ if (m_soft) return (m_soft->m_lv);
+ return (btVector3(0, 0, 0));
}
- btVector3 angularVelocity(const btVector3& rpos) const
- {
- if(m_rigid) return(btCross(m_rigid->getAngularVelocity(),rpos));
- if(m_soft) return(btCross(m_soft->m_av,rpos));
- return(btVector3(0,0,0));
+ btVector3 angularVelocity(const btVector3& rpos) const
+ {
+ if (m_rigid) return (btCross(m_rigid->getAngularVelocity(), rpos));
+ if (m_soft) return (btCross(m_soft->m_av, rpos));
+ return (btVector3(0, 0, 0));
}
- btVector3 angularVelocity() const
- {
- if(m_rigid) return(m_rigid->getAngularVelocity());
- if(m_soft) return(m_soft->m_av);
- return(btVector3(0,0,0));
+ btVector3 angularVelocity() const
+ {
+ if (m_rigid) return (m_rigid->getAngularVelocity());
+ if (m_soft) return (m_soft->m_av);
+ return (btVector3(0, 0, 0));
}
- btVector3 velocity(const btVector3& rpos) const
+ btVector3 velocity(const btVector3& rpos) const
{
- return(linearVelocity()+angularVelocity(rpos));
+ return (linearVelocity() + angularVelocity(rpos));
}
- void applyVImpulse(const btVector3& impulse,const btVector3& rpos) const
+ void applyVImpulse(const btVector3& impulse, const btVector3& rpos) const
{
- if(m_rigid) m_rigid->applyImpulse(impulse,rpos);
- if(m_soft) btSoftBody::clusterVImpulse(m_soft,rpos,impulse);
+ if (m_rigid) m_rigid->applyImpulse(impulse, rpos);
+ if (m_soft) btSoftBody::clusterVImpulse(m_soft, rpos, impulse);
}
- void applyDImpulse(const btVector3& impulse,const btVector3& rpos) const
+ void applyDImpulse(const btVector3& impulse, const btVector3& rpos) const
{
- if(m_rigid) m_rigid->applyImpulse(impulse,rpos);
- if(m_soft) btSoftBody::clusterDImpulse(m_soft,rpos,impulse);
- }
- void applyImpulse(const Impulse& impulse,const btVector3& rpos) const
+ if (m_rigid) m_rigid->applyImpulse(impulse, rpos);
+ if (m_soft) btSoftBody::clusterDImpulse(m_soft, rpos, impulse);
+ }
+ void applyImpulse(const Impulse& impulse, const btVector3& rpos) const
{
- if(impulse.m_asVelocity)
+ if (impulse.m_asVelocity)
{
-// printf("impulse.m_velocity = %f,%f,%f\n",impulse.m_velocity.getX(),impulse.m_velocity.getY(),impulse.m_velocity.getZ());
- applyVImpulse(impulse.m_velocity,rpos);
+ // printf("impulse.m_velocity = %f,%f,%f\n",impulse.m_velocity.getX(),impulse.m_velocity.getY(),impulse.m_velocity.getZ());
+ applyVImpulse(impulse.m_velocity, rpos);
}
- if(impulse.m_asDrift)
+ if (impulse.m_asDrift)
{
-// printf("impulse.m_drift = %f,%f,%f\n",impulse.m_drift.getX(),impulse.m_drift.getY(),impulse.m_drift.getZ());
- applyDImpulse(impulse.m_drift,rpos);
+ // printf("impulse.m_drift = %f,%f,%f\n",impulse.m_drift.getX(),impulse.m_drift.getY(),impulse.m_drift.getZ());
+ applyDImpulse(impulse.m_drift, rpos);
}
}
- void applyVAImpulse(const btVector3& impulse) const
+ void applyVAImpulse(const btVector3& impulse) const
{
- if(m_rigid) m_rigid->applyTorqueImpulse(impulse);
- if(m_soft) btSoftBody::clusterVAImpulse(m_soft,impulse);
+ if (m_rigid) m_rigid->applyTorqueImpulse(impulse);
+ if (m_soft) btSoftBody::clusterVAImpulse(m_soft, impulse);
}
- void applyDAImpulse(const btVector3& impulse) const
+ void applyDAImpulse(const btVector3& impulse) const
{
- if(m_rigid) m_rigid->applyTorqueImpulse(impulse);
- if(m_soft) btSoftBody::clusterDAImpulse(m_soft,impulse);
+ if (m_rigid) m_rigid->applyTorqueImpulse(impulse);
+ if (m_soft) btSoftBody::clusterDAImpulse(m_soft, impulse);
}
- void applyAImpulse(const Impulse& impulse) const
+ void applyAImpulse(const Impulse& impulse) const
{
- if(impulse.m_asVelocity) applyVAImpulse(impulse.m_velocity);
- if(impulse.m_asDrift) applyDAImpulse(impulse.m_drift);
+ if (impulse.m_asVelocity) applyVAImpulse(impulse.m_velocity);
+ if (impulse.m_asDrift) applyDAImpulse(impulse.m_drift);
}
- void applyDCImpulse(const btVector3& impulse) const
+ void applyDCImpulse(const btVector3& impulse) const
{
- if(m_rigid) m_rigid->applyCentralImpulse(impulse);
- if(m_soft) btSoftBody::clusterDCImpulse(m_soft,impulse);
+ if (m_rigid) m_rigid->applyCentralImpulse(impulse);
+ if (m_soft) btSoftBody::clusterDCImpulse(m_soft, impulse);
}
};
- /* Joint */
- struct Joint
+ /* Joint */
+ struct Joint
{
- struct eType { enum _ {
- Linear=0,
- Angular,
- Contact
- };};
+ struct eType
+ {
+ enum _
+ {
+ Linear = 0,
+ Angular,
+ Contact
+ };
+ };
struct Specs
{
- Specs() : erp(1),cfm(1),split(1) {}
- btScalar erp;
- btScalar cfm;
- btScalar split;
+ Specs() : erp(1), cfm(1), split(1) {}
+ btScalar erp;
+ btScalar cfm;
+ btScalar split;
};
- Body m_bodies[2];
- btVector3 m_refs[2];
- btScalar m_cfm;
- btScalar m_erp;
- btScalar m_split;
- btVector3 m_drift;
- btVector3 m_sdrift;
- btMatrix3x3 m_massmatrix;
- bool m_delete;
- virtual ~Joint() {}
+ Body m_bodies[2];
+ btVector3 m_refs[2];
+ btScalar m_cfm;
+ btScalar m_erp;
+ btScalar m_split;
+ btVector3 m_drift;
+ btVector3 m_sdrift;
+ btMatrix3x3 m_massmatrix;
+ bool m_delete;
+ virtual ~Joint() {}
Joint() : m_delete(false) {}
- virtual void Prepare(btScalar dt,int iterations);
- virtual void Solve(btScalar dt,btScalar sor)=0;
- virtual void Terminate(btScalar dt)=0;
- virtual eType::_ Type() const=0;
+ virtual void Prepare(btScalar dt, int iterations);
+ virtual void Solve(btScalar dt, btScalar sor) = 0;
+ virtual void Terminate(btScalar dt) = 0;
+ virtual eType::_ Type() const = 0;
};
- /* LJoint */
- struct LJoint : Joint
+ /* LJoint */
+ struct LJoint : Joint
{
struct Specs : Joint::Specs
{
- btVector3 position;
- };
- btVector3 m_rpos[2];
- void Prepare(btScalar dt,int iterations);
- void Solve(btScalar dt,btScalar sor);
- void Terminate(btScalar dt);
- eType::_ Type() const { return(eType::Linear); }
+ btVector3 position;
+ };
+ btVector3 m_rpos[2];
+ void Prepare(btScalar dt, int iterations);
+ void Solve(btScalar dt, btScalar sor);
+ void Terminate(btScalar dt);
+ eType::_ Type() const { return (eType::Linear); }
};
- /* AJoint */
- struct AJoint : Joint
+ /* AJoint */
+ struct AJoint : Joint
{
struct IControl
{
virtual ~IControl() {}
- virtual void Prepare(AJoint*) {}
- virtual btScalar Speed(AJoint*,btScalar current) { return(current); }
- static IControl* Default() { static IControl def;return(&def); }
+ virtual void Prepare(AJoint*) {}
+ virtual btScalar Speed(AJoint*, btScalar current) { return (current); }
+ static IControl* Default()
+ {
+ static IControl def;
+ return (&def);
+ }
};
struct Specs : Joint::Specs
{
Specs() : icontrol(IControl::Default()) {}
- btVector3 axis;
- IControl* icontrol;
- };
- btVector3 m_axis[2];
- IControl* m_icontrol;
- void Prepare(btScalar dt,int iterations);
- void Solve(btScalar dt,btScalar sor);
- void Terminate(btScalar dt);
- eType::_ Type() const { return(eType::Angular); }
- };
- /* CJoint */
- struct CJoint : Joint
- {
- int m_life;
- int m_maxlife;
- btVector3 m_rpos[2];
- btVector3 m_normal;
- btScalar m_friction;
- void Prepare(btScalar dt,int iterations);
- void Solve(btScalar dt,btScalar sor);
- void Terminate(btScalar dt);
- eType::_ Type() const { return(eType::Contact); }
- };
- /* Config */
- struct Config
- {
- eAeroModel::_ aeromodel; // Aerodynamic model (default: V_Point)
- btScalar kVCF; // Velocities correction factor (Baumgarte)
- btScalar kDP; // Damping coefficient [0,1]
- btScalar kDG; // Drag coefficient [0,+inf]
- btScalar kLF; // Lift coefficient [0,+inf]
- btScalar kPR; // Pressure coefficient [-inf,+inf]
- btScalar kVC; // Volume conversation coefficient [0,+inf]
- btScalar kDF; // Dynamic friction coefficient [0,1]
- btScalar kMT; // Pose matching coefficient [0,1]
- btScalar kCHR; // Rigid contacts hardness [0,1]
- btScalar kKHR; // Kinetic contacts hardness [0,1]
- btScalar kSHR; // Soft contacts hardness [0,1]
- btScalar kAHR; // Anchors hardness [0,1]
- btScalar kSRHR_CL; // Soft vs rigid hardness [0,1] (cluster only)
- btScalar kSKHR_CL; // Soft vs kinetic hardness [0,1] (cluster only)
- btScalar kSSHR_CL; // Soft vs soft hardness [0,1] (cluster only)
- btScalar kSR_SPLT_CL; // Soft vs rigid impulse split [0,1] (cluster only)
- btScalar kSK_SPLT_CL; // Soft vs rigid impulse split [0,1] (cluster only)
- btScalar kSS_SPLT_CL; // Soft vs rigid impulse split [0,1] (cluster only)
- btScalar maxvolume; // Maximum volume ratio for pose
- btScalar timescale; // Time scale
- int viterations; // Velocities solver iterations
- int piterations; // Positions solver iterations
- int diterations; // Drift solver iterations
- int citerations; // Cluster solver iterations
- int collisions; // Collisions flags
- tVSolverArray m_vsequence; // Velocity solvers sequence
- tPSolverArray m_psequence; // Position solvers sequence
- tPSolverArray m_dsequence; // Drift solvers sequence
- };
- /* SolverState */
- struct SolverState
- {
- btScalar sdt; // dt*timescale
- btScalar isdt; // 1/sdt
- btScalar velmrg; // velocity margin
- btScalar radmrg; // radial margin
- btScalar updmrg; // Update margin
- };
+ btVector3 axis;
+ IControl* icontrol;
+ };
+ btVector3 m_axis[2];
+ IControl* m_icontrol;
+ void Prepare(btScalar dt, int iterations);
+ void Solve(btScalar dt, btScalar sor);
+ void Terminate(btScalar dt);
+ eType::_ Type() const { return (eType::Angular); }
+ };
+ /* CJoint */
+ struct CJoint : Joint
+ {
+ int m_life;
+ int m_maxlife;
+ btVector3 m_rpos[2];
+ btVector3 m_normal;
+ btScalar m_friction;
+ void Prepare(btScalar dt, int iterations);
+ void Solve(btScalar dt, btScalar sor);
+ void Terminate(btScalar dt);
+ eType::_ Type() const { return (eType::Contact); }
+ };
+ /* Config */
+ struct Config
+ {
+ eAeroModel::_ aeromodel; // Aerodynamic model (default: V_Point)
+ btScalar kVCF; // Velocities correction factor (Baumgarte)
+ btScalar kDP; // Damping coefficient [0,1]
+ btScalar kDG; // Drag coefficient [0,+inf]
+ btScalar kLF; // Lift coefficient [0,+inf]
+ btScalar kPR; // Pressure coefficient [-inf,+inf]
+ btScalar kVC; // Volume conversation coefficient [0,+inf]
+ btScalar kDF; // Dynamic friction coefficient [0,1]
+ btScalar kMT; // Pose matching coefficient [0,1]
+ btScalar kCHR; // Rigid contacts hardness [0,1]
+ btScalar kKHR; // Kinetic contacts hardness [0,1]
+ btScalar kSHR; // Soft contacts hardness [0,1]
+ btScalar kAHR; // Anchors hardness [0,1]
+ btScalar kSRHR_CL; // Soft vs rigid hardness [0,1] (cluster only)
+ btScalar kSKHR_CL; // Soft vs kinetic hardness [0,1] (cluster only)
+ btScalar kSSHR_CL; // Soft vs soft hardness [0,1] (cluster only)
+ btScalar kSR_SPLT_CL; // Soft vs rigid impulse split [0,1] (cluster only)
+ btScalar kSK_SPLT_CL; // Soft vs rigid impulse split [0,1] (cluster only)
+ btScalar kSS_SPLT_CL; // Soft vs rigid impulse split [0,1] (cluster only)
+ btScalar maxvolume; // Maximum volume ratio for pose
+ btScalar timescale; // Time scale
+ int viterations; // Velocities solver iterations
+ int piterations; // Positions solver iterations
+ int diterations; // Drift solver iterations
+ int citerations; // Cluster solver iterations
+ int collisions; // Collisions flags
+ tVSolverArray m_vsequence; // Velocity solvers sequence
+ tPSolverArray m_psequence; // Position solvers sequence
+ tPSolverArray m_dsequence; // Drift solvers sequence
+ };
+ /* SolverState */
+ struct SolverState
+ {
+ btScalar sdt; // dt*timescale
+ btScalar isdt; // 1/sdt
+ btScalar velmrg; // velocity margin
+ btScalar radmrg; // radial margin
+ btScalar updmrg; // Update margin
+ };
/// RayFromToCaster takes a ray from, ray to (instead of direction!)
- struct RayFromToCaster : btDbvt::ICollide
- {
- btVector3 m_rayFrom;
- btVector3 m_rayTo;
- btVector3 m_rayNormalizedDirection;
- btScalar m_mint;
- Face* m_face;
- int m_tests;
- RayFromToCaster(const btVector3& rayFrom,const btVector3& rayTo,btScalar mxt);
- void Process(const btDbvtNode* leaf);
-
- static /*inline*/ btScalar rayFromToTriangle(const btVector3& rayFrom,
- const btVector3& rayTo,
- const btVector3& rayNormalizedDirection,
- const btVector3& a,
- const btVector3& b,
- const btVector3& c,
- btScalar maxt=SIMD_INFINITY);
+ struct RayFromToCaster : btDbvt::ICollide
+ {
+ btVector3 m_rayFrom;
+ btVector3 m_rayTo;
+ btVector3 m_rayNormalizedDirection;
+ btScalar m_mint;
+ Face* m_face;
+ int m_tests;
+ RayFromToCaster(const btVector3& rayFrom, const btVector3& rayTo, btScalar mxt);
+ void Process(const btDbvtNode* leaf);
+
+ static /*inline*/ btScalar rayFromToTriangle(const btVector3& rayFrom,
+ const btVector3& rayTo,
+ const btVector3& rayNormalizedDirection,
+ const btVector3& a,
+ const btVector3& b,
+ const btVector3& c,
+ btScalar maxt = SIMD_INFINITY);
};
//
// Typedefs
//
- typedef void (*psolver_t)(btSoftBody*,btScalar,btScalar);
- typedef void (*vsolver_t)(btSoftBody*,btScalar);
- typedef btAlignedObjectArray<Cluster*> tClusterArray;
- typedef btAlignedObjectArray<Note> tNoteArray;
- typedef btAlignedObjectArray<Node> tNodeArray;
- typedef btAlignedObjectArray<btDbvtNode*> tLeafArray;
- typedef btAlignedObjectArray<Link> tLinkArray;
- typedef btAlignedObjectArray<Face> tFaceArray;
- typedef btAlignedObjectArray<Tetra> tTetraArray;
- typedef btAlignedObjectArray<Anchor> tAnchorArray;
- typedef btAlignedObjectArray<RContact> tRContactArray;
- typedef btAlignedObjectArray<SContact> tSContactArray;
- typedef btAlignedObjectArray<Material*> tMaterialArray;
- typedef btAlignedObjectArray<Joint*> tJointArray;
- typedef btAlignedObjectArray<btSoftBody*> tSoftBodyArray;
+ typedef void (*psolver_t)(btSoftBody*, btScalar, btScalar);
+ typedef void (*vsolver_t)(btSoftBody*, btScalar);
+ typedef btAlignedObjectArray<Cluster*> tClusterArray;
+ typedef btAlignedObjectArray<Note> tNoteArray;
+ typedef btAlignedObjectArray<Node> tNodeArray;
+ typedef btAlignedObjectArray<btDbvtNode*> tLeafArray;
+ typedef btAlignedObjectArray<Link> tLinkArray;
+ typedef btAlignedObjectArray<Face> tFaceArray;
+ typedef btAlignedObjectArray<Tetra> tTetraArray;
+ typedef btAlignedObjectArray<Anchor> tAnchorArray;
+ typedef btAlignedObjectArray<RContact> tRContactArray;
+ typedef btAlignedObjectArray<SContact> tSContactArray;
+ typedef btAlignedObjectArray<Material*> tMaterialArray;
+ typedef btAlignedObjectArray<Joint*> tJointArray;
+ typedef btAlignedObjectArray<btSoftBody*> tSoftBodyArray;
//
// Fields
//
- Config m_cfg; // Configuration
- SolverState m_sst; // Solver state
- Pose m_pose; // Pose
- void* m_tag; // User data
- btSoftBodyWorldInfo* m_worldInfo; // World info
- tNoteArray m_notes; // Notes
- tNodeArray m_nodes; // Nodes
- tLinkArray m_links; // Links
- tFaceArray m_faces; // Faces
- tTetraArray m_tetras; // Tetras
- tAnchorArray m_anchors; // Anchors
- tRContactArray m_rcontacts; // Rigid contacts
- tSContactArray m_scontacts; // Soft contacts
- tJointArray m_joints; // Joints
- tMaterialArray m_materials; // Materials
- btScalar m_timeacc; // Time accumulator
- btVector3 m_bounds[2]; // Spatial bounds
- bool m_bUpdateRtCst; // Update runtime constants
- btDbvt m_ndbvt; // Nodes tree
- btDbvt m_fdbvt; // Faces tree
- btDbvt m_cdbvt; // Clusters tree
- tClusterArray m_clusters; // Clusters
-
- btAlignedObjectArray<bool>m_clusterConnectivity;//cluster connectivity, for self-collision
-
- btTransform m_initialWorldTransform;
-
- btVector3 m_windVelocity;
-
- btScalar m_restLengthScale;
-
+ Config m_cfg; // Configuration
+ SolverState m_sst; // Solver state
+ Pose m_pose; // Pose
+ void* m_tag; // User data
+ btSoftBodyWorldInfo* m_worldInfo; // World info
+ tNoteArray m_notes; // Notes
+ tNodeArray m_nodes; // Nodes
+ tLinkArray m_links; // Links
+ tFaceArray m_faces; // Faces
+ tTetraArray m_tetras; // Tetras
+ tAnchorArray m_anchors; // Anchors
+ tRContactArray m_rcontacts; // Rigid contacts
+ tSContactArray m_scontacts; // Soft contacts
+ tJointArray m_joints; // Joints
+ tMaterialArray m_materials; // Materials
+ btScalar m_timeacc; // Time accumulator
+ btVector3 m_bounds[2]; // Spatial bounds
+ bool m_bUpdateRtCst; // Update runtime constants
+ btDbvt m_ndbvt; // Nodes tree
+ btDbvt m_fdbvt; // Faces tree
+ btDbvt m_cdbvt; // Clusters tree
+ tClusterArray m_clusters; // Clusters
+
+ btAlignedObjectArray<bool> m_clusterConnectivity; //cluster connectivity, for self-collision
+
+ btTransform m_initialWorldTransform;
+
+ btVector3 m_windVelocity;
+
+ btScalar m_restLengthScale;
+
//
// Api
//
- /* ctor */
- btSoftBody( btSoftBodyWorldInfo* worldInfo,int node_count, const btVector3* x, const btScalar* m);
+ /* ctor */
+ btSoftBody(btSoftBodyWorldInfo* worldInfo, int node_count, const btVector3* x, const btScalar* m);
- /* ctor */
- btSoftBody( btSoftBodyWorldInfo* worldInfo);
+ /* ctor */
+ btSoftBody(btSoftBodyWorldInfo* worldInfo);
- void initDefaults();
+ void initDefaults();
- /* dtor */
+ /* dtor */
virtual ~btSoftBody();
- /* Check for existing link */
+ /* Check for existing link */
- btAlignedObjectArray<int> m_userIndexMapping;
+ btAlignedObjectArray<int> m_userIndexMapping;
- btSoftBodyWorldInfo* getWorldInfo()
+ btSoftBodyWorldInfo* getWorldInfo()
{
return m_worldInfo;
}
///@todo: avoid internal softbody shape hack and move collision code to collision library
- virtual void setCollisionShape(btCollisionShape* collisionShape)
+ virtual void setCollisionShape(btCollisionShape* collisionShape)
{
-
}
- bool checkLink( int node0,
- int node1) const;
- bool checkLink( const Node* node0,
- const Node* node1) const;
- /* Check for existring face */
- bool checkFace( int node0,
- int node1,
- int node2) const;
- /* Append material */
- Material* appendMaterial();
- /* Append note */
- void appendNote( const char* text,
- const btVector3& o,
- const btVector4& c=btVector4(1,0,0,0),
- Node* n0=0,
- Node* n1=0,
- Node* n2=0,
- Node* n3=0);
- void appendNote( const char* text,
- const btVector3& o,
- Node* feature);
- void appendNote( const char* text,
- const btVector3& o,
- Link* feature);
- void appendNote( const char* text,
- const btVector3& o,
- Face* feature);
- /* Append node */
- void appendNode( const btVector3& x,btScalar m);
- /* Append link */
- void appendLink(int model=-1,Material* mat=0);
- void appendLink( int node0,
- int node1,
- Material* mat=0,
- bool bcheckexist=false);
- void appendLink( Node* node0,
- Node* node1,
- Material* mat=0,
- bool bcheckexist=false);
- /* Append face */
- void appendFace(int model=-1,Material* mat=0);
- void appendFace( int node0,
- int node1,
- int node2,
- Material* mat=0);
- void appendTetra(int model,Material* mat);
+ bool checkLink(int node0,
+ int node1) const;
+ bool checkLink(const Node* node0,
+ const Node* node1) const;
+ /* Check for existring face */
+ bool checkFace(int node0,
+ int node1,
+ int node2) const;
+ /* Append material */
+ Material* appendMaterial();
+ /* Append note */
+ void appendNote(const char* text,
+ const btVector3& o,
+ const btVector4& c = btVector4(1, 0, 0, 0),
+ Node* n0 = 0,
+ Node* n1 = 0,
+ Node* n2 = 0,
+ Node* n3 = 0);
+ void appendNote(const char* text,
+ const btVector3& o,
+ Node* feature);
+ void appendNote(const char* text,
+ const btVector3& o,
+ Link* feature);
+ void appendNote(const char* text,
+ const btVector3& o,
+ Face* feature);
+ /* Append node */
+ void appendNode(const btVector3& x, btScalar m);
+ /* Append link */
+ void appendLink(int model = -1, Material* mat = 0);
+ void appendLink(int node0,
+ int node1,
+ Material* mat = 0,
+ bool bcheckexist = false);
+ void appendLink(Node* node0,
+ Node* node1,
+ Material* mat = 0,
+ bool bcheckexist = false);
+ /* Append face */
+ void appendFace(int model = -1, Material* mat = 0);
+ void appendFace(int node0,
+ int node1,
+ int node2,
+ Material* mat = 0);
+ void appendTetra(int model, Material* mat);
//
- void appendTetra(int node0,
- int node1,
- int node2,
- int node3,
- Material* mat=0);
-
-
- /* Append anchor */
- void appendAnchor( int node,
- btRigidBody* body, bool disableCollisionBetweenLinkedBodies=false,btScalar influence = 1);
- void appendAnchor(int node,btRigidBody* body, const btVector3& localPivot,bool disableCollisionBetweenLinkedBodies=false,btScalar influence = 1);
- /* Append linear joint */
- void appendLinearJoint(const LJoint::Specs& specs,Cluster* body0,Body body1);
- void appendLinearJoint(const LJoint::Specs& specs,Body body=Body());
- void appendLinearJoint(const LJoint::Specs& specs,btSoftBody* body);
- /* Append linear joint */
- void appendAngularJoint(const AJoint::Specs& specs,Cluster* body0,Body body1);
- void appendAngularJoint(const AJoint::Specs& specs,Body body=Body());
- void appendAngularJoint(const AJoint::Specs& specs,btSoftBody* body);
- /* Add force (or gravity) to the entire body */
- void addForce( const btVector3& force);
- /* Add force (or gravity) to a node of the body */
- void addForce( const btVector3& force,
- int node);
+ void appendTetra(int node0,
+ int node1,
+ int node2,
+ int node3,
+ Material* mat = 0);
+
+ /* Append anchor */
+ void appendAnchor(int node,
+ btRigidBody* body, bool disableCollisionBetweenLinkedBodies = false, btScalar influence = 1);
+ void appendAnchor(int node, btRigidBody* body, const btVector3& localPivot, bool disableCollisionBetweenLinkedBodies = false, btScalar influence = 1);
+ /* Append linear joint */
+ void appendLinearJoint(const LJoint::Specs& specs, Cluster* body0, Body body1);
+ void appendLinearJoint(const LJoint::Specs& specs, Body body = Body());
+ void appendLinearJoint(const LJoint::Specs& specs, btSoftBody* body);
+ /* Append linear joint */
+ void appendAngularJoint(const AJoint::Specs& specs, Cluster* body0, Body body1);
+ void appendAngularJoint(const AJoint::Specs& specs, Body body = Body());
+ void appendAngularJoint(const AJoint::Specs& specs, btSoftBody* body);
+ /* Add force (or gravity) to the entire body */
+ void addForce(const btVector3& force);
+ /* Add force (or gravity) to a node of the body */
+ void addForce(const btVector3& force,
+ int node);
/* Add aero force to a node of the body */
- void addAeroForceToNode(const btVector3& windVelocity,int nodeIndex);
+ void addAeroForceToNode(const btVector3& windVelocity, int nodeIndex);
/* Add aero force to a face of the body */
- void addAeroForceToFace(const btVector3& windVelocity,int faceIndex);
-
- /* Add velocity to the entire body */
- void addVelocity( const btVector3& velocity);
-
- /* Set velocity for the entire body */
- void setVelocity( const btVector3& velocity);
-
- /* Add velocity to a node of the body */
- void addVelocity( const btVector3& velocity,
- int node);
- /* Set mass */
- void setMass( int node,
- btScalar mass);
- /* Get mass */
- btScalar getMass( int node) const;
- /* Get total mass */
- btScalar getTotalMass() const;
- /* Set total mass (weighted by previous masses) */
- void setTotalMass( btScalar mass,
- bool fromfaces=false);
- /* Set total density */
- void setTotalDensity(btScalar density);
+ void addAeroForceToFace(const btVector3& windVelocity, int faceIndex);
+
+ /* Add velocity to the entire body */
+ void addVelocity(const btVector3& velocity);
+
+ /* Set velocity for the entire body */
+ void setVelocity(const btVector3& velocity);
+
+ /* Add velocity to a node of the body */
+ void addVelocity(const btVector3& velocity,
+ int node);
+ /* Set mass */
+ void setMass(int node,
+ btScalar mass);
+ /* Get mass */
+ btScalar getMass(int node) const;
+ /* Get total mass */
+ btScalar getTotalMass() const;
+ /* Set total mass (weighted by previous masses) */
+ void setTotalMass(btScalar mass,
+ bool fromfaces = false);
+ /* Set total density */
+ void setTotalDensity(btScalar density);
/* Set volume mass (using tetrahedrons) */
- void setVolumeMass( btScalar mass);
+ void setVolumeMass(btScalar mass);
/* Set volume density (using tetrahedrons) */
- void setVolumeDensity( btScalar density);
- /* Transform */
- void transform( const btTransform& trs);
- /* Translate */
- void translate( const btVector3& trs);
- /* Rotate */
- void rotate( const btQuaternion& rot);
- /* Scale */
- void scale( const btVector3& scl);
+ void setVolumeDensity(btScalar density);
+ /* Transform */
+ void transform(const btTransform& trs);
+ /* Translate */
+ void translate(const btVector3& trs);
+ /* Rotate */
+ void rotate(const btQuaternion& rot);
+ /* Scale */
+ void scale(const btVector3& scl);
/* Get link resting lengths scale */
- btScalar getRestLengthScale();
+ btScalar getRestLengthScale();
/* Scale resting length of all springs */
- void setRestLengthScale(btScalar restLength);
- /* Set current state as pose */
- void setPose( bool bvolume,
- bool bframe);
- /* Set current link lengths as resting lengths */
- void resetLinkRestLengths();
- /* Return the volume */
- btScalar getVolume() const;
- /* Cluster count */
- int clusterCount() const;
- /* Cluster center of mass */
- static btVector3 clusterCom(const Cluster* cluster);
- btVector3 clusterCom(int cluster) const;
- /* Cluster velocity at rpos */
- static btVector3 clusterVelocity(const Cluster* cluster,const btVector3& rpos);
- /* Cluster impulse */
- static void clusterVImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse);
- static void clusterDImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse);
- static void clusterImpulse(Cluster* cluster,const btVector3& rpos,const Impulse& impulse);
- static void clusterVAImpulse(Cluster* cluster,const btVector3& impulse);
- static void clusterDAImpulse(Cluster* cluster,const btVector3& impulse);
- static void clusterAImpulse(Cluster* cluster,const Impulse& impulse);
- static void clusterDCImpulse(Cluster* cluster,const btVector3& impulse);
- /* Generate bending constraints based on distance in the adjency graph */
- int generateBendingConstraints( int distance,
- Material* mat=0);
- /* Randomize constraints to reduce solver bias */
- void randomizeConstraints();
- /* Release clusters */
- void releaseCluster(int index);
- void releaseClusters();
- /* Generate clusters (K-mean) */
+ void setRestLengthScale(btScalar restLength);
+ /* Set current state as pose */
+ void setPose(bool bvolume,
+ bool bframe);
+ /* Set current link lengths as resting lengths */
+ void resetLinkRestLengths();
+ /* Return the volume */
+ btScalar getVolume() const;
+ /* Cluster count */
+ int clusterCount() const;
+ /* Cluster center of mass */
+ static btVector3 clusterCom(const Cluster* cluster);
+ btVector3 clusterCom(int cluster) const;
+ /* Cluster velocity at rpos */
+ static btVector3 clusterVelocity(const Cluster* cluster, const btVector3& rpos);
+ /* Cluster impulse */
+ static void clusterVImpulse(Cluster* cluster, const btVector3& rpos, const btVector3& impulse);
+ static void clusterDImpulse(Cluster* cluster, const btVector3& rpos, const btVector3& impulse);
+ static void clusterImpulse(Cluster* cluster, const btVector3& rpos, const Impulse& impulse);
+ static void clusterVAImpulse(Cluster* cluster, const btVector3& impulse);
+ static void clusterDAImpulse(Cluster* cluster, const btVector3& impulse);
+ static void clusterAImpulse(Cluster* cluster, const Impulse& impulse);
+ static void clusterDCImpulse(Cluster* cluster, const btVector3& impulse);
+ /* Generate bending constraints based on distance in the adjency graph */
+ int generateBendingConstraints(int distance,
+ Material* mat = 0);
+ /* Randomize constraints to reduce solver bias */
+ void randomizeConstraints();
+ /* Release clusters */
+ void releaseCluster(int index);
+ void releaseClusters();
+ /* Generate clusters (K-mean) */
///generateClusters with k=0 will create a convex cluster for each tetrahedron or triangle
///otherwise an approximation will be used (better performance)
- int generateClusters(int k,int maxiterations=8192);
- /* Refine */
- void refine(ImplicitFn* ifn,btScalar accurary,bool cut);
- /* CutLink */
- bool cutLink(int node0,int node1,btScalar position);
- bool cutLink(const Node* node0,const Node* node1,btScalar position);
+ int generateClusters(int k, int maxiterations = 8192);
+ /* Refine */
+ void refine(ImplicitFn* ifn, btScalar accurary, bool cut);
+ /* CutLink */
+ bool cutLink(int node0, int node1, btScalar position);
+ bool cutLink(const Node* node0, const Node* node1, btScalar position);
///Ray casting using rayFrom and rayTo in worldspace, (not direction!)
- bool rayTest(const btVector3& rayFrom,
- const btVector3& rayTo,
- sRayCast& results);
- /* Solver presets */
- void setSolver(eSolverPresets::_ preset);
- /* predictMotion */
- void predictMotion(btScalar dt);
- /* solveConstraints */
- void solveConstraints();
- /* staticSolve */
- void staticSolve(int iterations);
- /* solveCommonConstraints */
- static void solveCommonConstraints(btSoftBody** bodies,int count,int iterations);
- /* solveClusters */
- static void solveClusters(const btAlignedObjectArray<btSoftBody*>& bodies);
- /* integrateMotion */
- void integrateMotion();
- /* defaultCollisionHandlers */
- void defaultCollisionHandler(const btCollisionObjectWrapper* pcoWrap);
- void defaultCollisionHandler(btSoftBody* psb);
-
-
+ bool rayTest(const btVector3& rayFrom,
+ const btVector3& rayTo,
+ sRayCast& results);
+ /* Solver presets */
+ void setSolver(eSolverPresets::_ preset);
+ /* predictMotion */
+ void predictMotion(btScalar dt);
+ /* solveConstraints */
+ void solveConstraints();
+ /* staticSolve */
+ void staticSolve(int iterations);
+ /* solveCommonConstraints */
+ static void solveCommonConstraints(btSoftBody** bodies, int count, int iterations);
+ /* solveClusters */
+ static void solveClusters(const btAlignedObjectArray<btSoftBody*>& bodies);
+ /* integrateMotion */
+ void integrateMotion();
+ /* defaultCollisionHandlers */
+ void defaultCollisionHandler(const btCollisionObjectWrapper* pcoWrap);
+ void defaultCollisionHandler(btSoftBody* psb);
//
// Functionality to deal with new accelerated solvers.
@@ -895,8 +923,7 @@ public:
/**
* Set a wind velocity for interaction with the air.
*/
- void setWindVelocity( const btVector3 &velocity );
-
+ void setWindVelocity(const btVector3& velocity);
/**
* Return the wind velocity for interaction with the air.
@@ -907,41 +934,40 @@ public:
// Set the solver that handles this soft body
// Should not be allowed to get out of sync with reality
// Currently called internally on addition to the world
- void setSoftBodySolver( btSoftBodySolver *softBodySolver )
+ void setSoftBodySolver(btSoftBodySolver* softBodySolver)
{
m_softBodySolver = softBodySolver;
}
//
// Return the solver that handles this soft body
- //
- btSoftBodySolver *getSoftBodySolver()
+ //
+ btSoftBodySolver* getSoftBodySolver()
{
return m_softBodySolver;
}
//
// Return the solver that handles this soft body
- //
- btSoftBodySolver *getSoftBodySolver() const
+ //
+ btSoftBodySolver* getSoftBodySolver() const
{
return m_softBodySolver;
}
-
//
// Cast
//
- static const btSoftBody* upcast(const btCollisionObject* colObj)
+ static const btSoftBody* upcast(const btCollisionObject* colObj)
{
- if (colObj->getInternalType()==CO_SOFT_BODY)
+ if (colObj->getInternalType() == CO_SOFT_BODY)
return (const btSoftBody*)colObj;
return 0;
}
- static btSoftBody* upcast(btCollisionObject* colObj)
+ static btSoftBody* upcast(btCollisionObject* colObj)
{
- if (colObj->getInternalType()==CO_SOFT_BODY)
+ if (colObj->getInternalType() == CO_SOFT_BODY)
return (btSoftBody*)colObj;
return 0;
}
@@ -950,7 +976,7 @@ public:
// ::btCollisionObject
//
- virtual void getAabb(btVector3& aabbMin,btVector3& aabbMax) const
+ virtual void getAabb(btVector3& aabbMin, btVector3& aabbMax) const
{
aabbMin = m_bounds[0];
aabbMax = m_bounds[1];
@@ -958,48 +984,42 @@ public:
//
// Private
//
- void pointersToIndices();
- void indicesToPointers(const int* map=0);
-
- int rayTest(const btVector3& rayFrom,const btVector3& rayTo,
- btScalar& mint,eFeature::_& feature,int& index,bool bcountonly) const;
- void initializeFaceTree();
- btVector3 evaluateCom() const;
- bool checkContact(const btCollisionObjectWrapper* colObjWrap,const btVector3& x,btScalar margin,btSoftBody::sCti& cti) const;
- void updateNormals();
- void updateBounds();
- void updatePose();
- void updateConstants();
- void updateLinkConstants();
- void updateArea(bool averageArea = true);
- void initializeClusters();
- void updateClusters();
- void cleanupClusters();
- void prepareClusters(int iterations);
- void solveClusters(btScalar sor);
- void applyClusters(bool drift);
- void dampClusters();
- void applyForces();
- static void PSolve_Anchors(btSoftBody* psb,btScalar kst,btScalar ti);
- static void PSolve_RContacts(btSoftBody* psb,btScalar kst,btScalar ti);
- static void PSolve_SContacts(btSoftBody* psb,btScalar,btScalar ti);
- static void PSolve_Links(btSoftBody* psb,btScalar kst,btScalar ti);
- static void VSolve_Links(btSoftBody* psb,btScalar kst);
- static psolver_t getSolver(ePSolver::_ solver);
- static vsolver_t getSolver(eVSolver::_ solver);
-
-
- virtual int calculateSerializeBufferSize() const;
+ void pointersToIndices();
+ void indicesToPointers(const int* map = 0);
+
+ int rayTest(const btVector3& rayFrom, const btVector3& rayTo,
+ btScalar& mint, eFeature::_& feature, int& index, bool bcountonly) const;
+ void initializeFaceTree();
+ btVector3 evaluateCom() const;
+ bool checkContact(const btCollisionObjectWrapper* colObjWrap, const btVector3& x, btScalar margin, btSoftBody::sCti& cti) const;
+ void updateNormals();
+ void updateBounds();
+ void updatePose();
+ void updateConstants();
+ void updateLinkConstants();
+ void updateArea(bool averageArea = true);
+ void initializeClusters();
+ void updateClusters();
+ void cleanupClusters();
+ void prepareClusters(int iterations);
+ void solveClusters(btScalar sor);
+ void applyClusters(bool drift);
+ void dampClusters();
+ void applyForces();
+ static void PSolve_Anchors(btSoftBody* psb, btScalar kst, btScalar ti);
+ static void PSolve_RContacts(btSoftBody* psb, btScalar kst, btScalar ti);
+ static void PSolve_SContacts(btSoftBody* psb, btScalar, btScalar ti);
+ static void PSolve_Links(btSoftBody* psb, btScalar kst, btScalar ti);
+ static void VSolve_Links(btSoftBody* psb, btScalar kst);
+ static psolver_t getSolver(ePSolver::_ solver);
+ static vsolver_t getSolver(eVSolver::_ solver);
+
+ virtual int calculateSerializeBufferSize() const;
///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const;
+ virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const;
//virtual void serializeSingleObject(class btSerializer* serializer) const;
-
-
};
-
-
-
-#endif //_BT_SOFT_BODY_H
+#endif //_BT_SOFT_BODY_H
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp b/thirdparty/bullet/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp
index ab84bddf2a..750718f57f 100644
--- a/thirdparty/bullet/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp
+++ b/thirdparty/bullet/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp
@@ -13,7 +13,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#include "btSoftBodyConcaveCollisionAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
@@ -27,34 +26,28 @@ subject to the following restrictions:
#include "BulletCollision/CollisionShapes/btConvexHullShape.h"
#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
-
#include "LinearMath/btIDebugDraw.h"
#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
#include "BulletSoftBody/btSoftBody.h"
-#define BT_SOFTBODY_TRIANGLE_EXTRUSION btScalar(0.06)//make this configurable
+#define BT_SOFTBODY_TRIANGLE_EXTRUSION btScalar(0.06) //make this configurable
-btSoftBodyConcaveCollisionAlgorithm::btSoftBodyConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped)
-: btCollisionAlgorithm(ci),
-m_isSwapped(isSwapped),
-m_btSoftBodyTriangleCallback(ci.m_dispatcher1,body0Wrap,body1Wrap,isSwapped)
+btSoftBodyConcaveCollisionAlgorithm::btSoftBodyConcaveCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped)
+ : btCollisionAlgorithm(ci),
+ m_isSwapped(isSwapped),
+ m_btSoftBodyTriangleCallback(ci.m_dispatcher1, body0Wrap, body1Wrap, isSwapped)
{
}
-
-
btSoftBodyConcaveCollisionAlgorithm::~btSoftBodyConcaveCollisionAlgorithm()
{
}
-
-
-btSoftBodyTriangleCallback::btSoftBodyTriangleCallback(btDispatcher* dispatcher,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped):
-m_dispatcher(dispatcher),
-m_dispatchInfoPtr(0)
+btSoftBodyTriangleCallback::btSoftBodyTriangleCallback(btDispatcher* dispatcher, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped) : m_dispatcher(dispatcher),
+ m_dispatchInfoPtr(0)
{
- m_softBody = (isSwapped? (btSoftBody*)body1Wrap->getCollisionObject():(btSoftBody*)body0Wrap->getCollisionObject());
- m_triBody = isSwapped? body0Wrap->getCollisionObject():body1Wrap->getCollisionObject();
+ m_softBody = (isSwapped ? (btSoftBody*)body1Wrap->getCollisionObject() : (btSoftBody*)body0Wrap->getCollisionObject());
+ m_triBody = isSwapped ? body0Wrap->getCollisionObject() : body1Wrap->getCollisionObject();
//
// create the manifold from the dispatcher 'manifold pool'
@@ -68,46 +61,42 @@ btSoftBodyTriangleCallback::~btSoftBodyTriangleCallback()
{
clearCache();
// m_dispatcher->releaseManifold( m_manifoldPtr );
-
}
-
-void btSoftBodyTriangleCallback::clearCache()
+void btSoftBodyTriangleCallback::clearCache()
{
- for (int i=0;i<m_shapeCache.size();i++)
+ for (int i = 0; i < m_shapeCache.size(); i++)
{
btTriIndex* tmp = m_shapeCache.getAtIndex(i);
btAssert(tmp);
btAssert(tmp->m_childShape);
- m_softBody->getWorldInfo()->m_sparsesdf.RemoveReferences(tmp->m_childShape);//necessary?
+ m_softBody->getWorldInfo()->m_sparsesdf.RemoveReferences(tmp->m_childShape); //necessary?
delete tmp->m_childShape;
}
m_shapeCache.clear();
}
-
-void btSoftBodyTriangleCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex)
+void btSoftBodyTriangleCallback::processTriangle(btVector3* triangle, int partId, int triangleIndex)
{
//just for debugging purposes
//printf("triangle %d",m_triangleCount++);
-
+
btCollisionAlgorithmConstructionInfo ci;
ci.m_dispatcher1 = m_dispatcher;
///debug drawing of the overlapping triangles
- if (m_dispatchInfoPtr && m_dispatchInfoPtr->m_debugDraw && (m_dispatchInfoPtr->m_debugDraw->getDebugMode() &btIDebugDraw::DBG_DrawWireframe))
+ if (m_dispatchInfoPtr && m_dispatchInfoPtr->m_debugDraw && (m_dispatchInfoPtr->m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawWireframe))
{
- btVector3 color(1,1,0);
+ btVector3 color(1, 1, 0);
const btTransform& tr = m_triBody->getWorldTransform();
- m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(triangle[1]),color);
- m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(triangle[2]),color);
- m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(triangle[0]),color);
+ m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]), tr(triangle[1]), color);
+ m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]), tr(triangle[2]), color);
+ m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]), tr(triangle[0]), color);
}
- btTriIndex triIndex(partId,triangleIndex,0);
+ btTriIndex triIndex(partId, triangleIndex, 0);
btHashKey<btTriIndex> triKey(triIndex.getUid());
-
btTriIndex* shapeIndex = m_shapeCache[triKey];
if (shapeIndex)
{
@@ -117,82 +106,73 @@ void btSoftBodyTriangleCallback::processTriangle(btVector3* triangle,int partId,
//copy over user pointers to temporary shape
tm->setUserPointer(m_triBody->getCollisionShape()->getUserPointer());
- btCollisionObjectWrapper softBody(0,m_softBody->getCollisionShape(),m_softBody,m_softBody->getWorldTransform(),-1,-1);
+ btCollisionObjectWrapper softBody(0, m_softBody->getCollisionShape(), m_softBody, m_softBody->getWorldTransform(), -1, -1);
//btCollisionObjectWrapper triBody(0,tm, ob, btTransform::getIdentity());//ob->getWorldTransform());//??
- btCollisionObjectWrapper triBody(0,tm, m_triBody, m_triBody->getWorldTransform(),partId, triangleIndex);
+ btCollisionObjectWrapper triBody(0, tm, m_triBody, m_triBody->getWorldTransform(), partId, triangleIndex);
ebtDispatcherQueryType algoType = m_resultOut->m_closestPointDistanceThreshold > 0 ? BT_CLOSEST_POINT_ALGORITHMS : BT_CONTACT_POINT_ALGORITHMS;
- btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(&softBody,&triBody,0, algoType);//m_manifoldPtr);
+ btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(&softBody, &triBody, 0, algoType); //m_manifoldPtr);
- colAlgo->processCollision(&softBody,&triBody,*m_dispatchInfoPtr,m_resultOut);
+ colAlgo->processCollision(&softBody, &triBody, *m_dispatchInfoPtr, m_resultOut);
colAlgo->~btCollisionAlgorithm();
ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo);
-
+
return;
}
- //aabb filter is already applied!
+ //aabb filter is already applied!
//btCollisionObject* colObj = static_cast<btCollisionObject*>(m_convexProxy->m_clientObject);
// if (m_softBody->getCollisionShape()->getShapeType()==
{
// btVector3 other;
- btVector3 normal = (triangle[1]-triangle[0]).cross(triangle[2]-triangle[0]);
+ btVector3 normal = (triangle[1] - triangle[0]).cross(triangle[2] - triangle[0]);
normal.normalize();
- normal*= BT_SOFTBODY_TRIANGLE_EXTRUSION;
+ normal *= BT_SOFTBODY_TRIANGLE_EXTRUSION;
// other=(triangle[0]+triangle[1]+triangle[2])*0.333333f;
// other+=normal*22.f;
- btVector3 pts[6] = {triangle[0]+normal,
- triangle[1]+normal,
- triangle[2]+normal,
- triangle[0]-normal,
- triangle[1]-normal,
- triangle[2]-normal};
-
- btConvexHullShape* tm = new btConvexHullShape(&pts[0].getX(),6);
+ btVector3 pts[6] = {triangle[0] + normal,
+ triangle[1] + normal,
+ triangle[2] + normal,
+ triangle[0] - normal,
+ triangle[1] - normal,
+ triangle[2] - normal};
+ btConvexHullShape* tm = new btConvexHullShape(&pts[0].getX(), 6);
// btBU_Simplex1to4 tm(triangle[0],triangle[1],triangle[2],other);
- //btTriangleShape tm(triangle[0],triangle[1],triangle[2]);
+ //btTriangleShape tm(triangle[0],triangle[1],triangle[2]);
// tm.setMargin(m_collisionMarginTriangle);
//copy over user pointers to temporary shape
tm->setUserPointer(m_triBody->getCollisionShape()->getUserPointer());
-
- btCollisionObjectWrapper softBody(0,m_softBody->getCollisionShape(),m_softBody,m_softBody->getWorldTransform(),-1,-1);
- btCollisionObjectWrapper triBody(0,tm, m_triBody, m_triBody->getWorldTransform(),partId, triangleIndex);//btTransform::getIdentity());//??
+ btCollisionObjectWrapper softBody(0, m_softBody->getCollisionShape(), m_softBody, m_softBody->getWorldTransform(), -1, -1);
+ btCollisionObjectWrapper triBody(0, tm, m_triBody, m_triBody->getWorldTransform(), partId, triangleIndex); //btTransform::getIdentity());//??
ebtDispatcherQueryType algoType = m_resultOut->m_closestPointDistanceThreshold > 0 ? BT_CLOSEST_POINT_ALGORITHMS : BT_CONTACT_POINT_ALGORITHMS;
- btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(&softBody,&triBody,0, algoType);//m_manifoldPtr);
+ btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(&softBody, &triBody, 0, algoType); //m_manifoldPtr);
- colAlgo->processCollision(&softBody,&triBody,*m_dispatchInfoPtr,m_resultOut);
+ colAlgo->processCollision(&softBody, &triBody, *m_dispatchInfoPtr, m_resultOut);
colAlgo->~btCollisionAlgorithm();
ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo);
triIndex.m_childShape = tm;
- m_shapeCache.insert(triKey,triIndex);
-
+ m_shapeCache.insert(triKey, triIndex);
}
-
-
-
}
-
-
-void btSoftBodyTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle,const btCollisionObjectWrapper* triBodyWrap, const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+void btSoftBodyTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle, const btCollisionObjectWrapper* triBodyWrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
{
m_dispatchInfoPtr = &dispatchInfo;
- m_collisionMarginTriangle = collisionMarginTriangle+btScalar(BT_SOFTBODY_TRIANGLE_EXTRUSION);
+ m_collisionMarginTriangle = collisionMarginTriangle + btScalar(BT_SOFTBODY_TRIANGLE_EXTRUSION);
m_resultOut = resultOut;
-
- btVector3 aabbWorldSpaceMin,aabbWorldSpaceMax;
- m_softBody->getAabb(aabbWorldSpaceMin,aabbWorldSpaceMax);
- btVector3 halfExtents = (aabbWorldSpaceMax-aabbWorldSpaceMin)*btScalar(0.5);
- btVector3 softBodyCenter = (aabbWorldSpaceMax+aabbWorldSpaceMin)*btScalar(0.5);
+ btVector3 aabbWorldSpaceMin, aabbWorldSpaceMax;
+ m_softBody->getAabb(aabbWorldSpaceMin, aabbWorldSpaceMax);
+ btVector3 halfExtents = (aabbWorldSpaceMax - aabbWorldSpaceMin) * btScalar(0.5);
+ btVector3 softBodyCenter = (aabbWorldSpaceMax + aabbWorldSpaceMin) * btScalar(0.5);
btTransform softTransform;
softTransform.setIdentity();
@@ -200,56 +180,45 @@ void btSoftBodyTriangleCallback::setTimeStepAndCounters(btScalar collisionMargin
btTransform convexInTriangleSpace;
convexInTriangleSpace = triBodyWrap->getWorldTransform().inverse() * softTransform;
- btTransformAabb(halfExtents,m_collisionMarginTriangle,convexInTriangleSpace,m_aabbMin,m_aabbMax);
+ btTransformAabb(halfExtents, m_collisionMarginTriangle, convexInTriangleSpace, m_aabbMin, m_aabbMax);
}
void btSoftBodyConcaveCollisionAlgorithm::clearCache()
{
m_btSoftBodyTriangleCallback.clearCache();
-
}
-void btSoftBodyConcaveCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+void btSoftBodyConcaveCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
{
-
-
//btCollisionObject* convexBody = m_isSwapped ? body1 : body0;
const btCollisionObjectWrapper* triBody = m_isSwapped ? body0Wrap : body1Wrap;
if (triBody->getCollisionShape()->isConcave())
{
-
-
- const btCollisionObject* triOb = triBody->getCollisionObject();
- const btConcaveShape* concaveShape = static_cast<const btConcaveShape*>( triOb->getCollisionShape());
+ const btCollisionObject* triOb = triBody->getCollisionObject();
+ const btConcaveShape* concaveShape = static_cast<const btConcaveShape*>(triOb->getCollisionShape());
// if (convexBody->getCollisionShape()->isConvex())
{
btScalar collisionMarginTriangle = concaveShape->getMargin();
// resultOut->setPersistentManifold(m_btSoftBodyTriangleCallback.m_manifoldPtr);
- m_btSoftBodyTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle,triBody,dispatchInfo,resultOut);
+ m_btSoftBodyTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle, triBody, dispatchInfo, resultOut);
-
- concaveShape->processAllTriangles( &m_btSoftBodyTriangleCallback,m_btSoftBodyTriangleCallback.getAabbMin(),m_btSoftBodyTriangleCallback.getAabbMax());
+ concaveShape->processAllTriangles(&m_btSoftBodyTriangleCallback, m_btSoftBodyTriangleCallback.getAabbMin(), m_btSoftBodyTriangleCallback.getAabbMax());
// resultOut->refreshContactPoints();
-
}
-
}
-
}
-
-btScalar btSoftBodyConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+btScalar btSoftBodyConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
{
(void)resultOut;
(void)dispatchInfo;
btCollisionObject* convexbody = m_isSwapped ? body1 : body0;
btCollisionObject* triBody = m_isSwapped ? body0 : body1;
-
//quick approximation using raycast, todo: hook up to the continuous collision detection (one of the btConvexCast)
//only perform CCD above a certain threshold, this prevents blocking on the long run
@@ -268,25 +237,23 @@ btScalar btSoftBodyConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionO
btTransform convexFromLocal = triInv * convexbody->getWorldTransform();
btTransform convexToLocal = triInv * convexbody->getInterpolationWorldTransform();
- struct LocalTriangleSphereCastCallback : public btTriangleCallback
+ struct LocalTriangleSphereCastCallback : public btTriangleCallback
{
btTransform m_ccdSphereFromTrans;
btTransform m_ccdSphereToTrans;
- btTransform m_meshTransform;
+ btTransform m_meshTransform;
- btScalar m_ccdSphereRadius;
- btScalar m_hitFraction;
+ btScalar m_ccdSphereRadius;
+ btScalar m_hitFraction;
-
- LocalTriangleSphereCastCallback(const btTransform& from,const btTransform& to,btScalar ccdSphereRadius,btScalar hitFraction)
- :m_ccdSphereFromTrans(from),
- m_ccdSphereToTrans(to),
- m_ccdSphereRadius(ccdSphereRadius),
- m_hitFraction(hitFraction)
- {
+ LocalTriangleSphereCastCallback(const btTransform& from, const btTransform& to, btScalar ccdSphereRadius, btScalar hitFraction)
+ : m_ccdSphereFromTrans(from),
+ m_ccdSphereToTrans(to),
+ m_ccdSphereRadius(ccdSphereRadius),
+ m_hitFraction(hitFraction)
+ {
}
-
virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
{
(void)partId;
@@ -296,29 +263,23 @@ btScalar btSoftBodyConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionO
ident.setIdentity();
btConvexCast::CastResult castResult;
castResult.m_fraction = m_hitFraction;
- btSphereShape pointShape(m_ccdSphereRadius);
- btTriangleShape triShape(triangle[0],triangle[1],triangle[2]);
- btVoronoiSimplexSolver simplexSolver;
- btSubsimplexConvexCast convexCaster(&pointShape,&triShape,&simplexSolver);
+ btSphereShape pointShape(m_ccdSphereRadius);
+ btTriangleShape triShape(triangle[0], triangle[1], triangle[2]);
+ btVoronoiSimplexSolver simplexSolver;
+ btSubsimplexConvexCast convexCaster(&pointShape, &triShape, &simplexSolver);
//GjkConvexCast convexCaster(&pointShape,convexShape,&simplexSolver);
//ContinuousConvexCollision convexCaster(&pointShape,convexShape,&simplexSolver,0);
//local space?
- if (convexCaster.calcTimeOfImpact(m_ccdSphereFromTrans,m_ccdSphereToTrans,
- ident,ident,castResult))
+ if (convexCaster.calcTimeOfImpact(m_ccdSphereFromTrans, m_ccdSphereToTrans,
+ ident, ident, castResult))
{
if (m_hitFraction > castResult.m_fraction)
m_hitFraction = castResult.m_fraction;
}
-
}
-
};
-
-
-
-
if (triBody->getCollisionShape()->isConcave())
{
btVector3 rayAabbMin = convexFromLocal.getOrigin();
@@ -326,33 +287,30 @@ btScalar btSoftBodyConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionO
btVector3 rayAabbMax = convexFromLocal.getOrigin();
rayAabbMax.setMax(convexToLocal.getOrigin());
btScalar ccdRadius0 = convexbody->getCcdSweptSphereRadius();
- rayAabbMin -= btVector3(ccdRadius0,ccdRadius0,ccdRadius0);
- rayAabbMax += btVector3(ccdRadius0,ccdRadius0,ccdRadius0);
+ rayAabbMin -= btVector3(ccdRadius0, ccdRadius0, ccdRadius0);
+ rayAabbMax += btVector3(ccdRadius0, ccdRadius0, ccdRadius0);
- btScalar curHitFraction = btScalar(1.); //is this available?
- LocalTriangleSphereCastCallback raycastCallback(convexFromLocal,convexToLocal,
- convexbody->getCcdSweptSphereRadius(),curHitFraction);
+ btScalar curHitFraction = btScalar(1.); //is this available?
+ LocalTriangleSphereCastCallback raycastCallback(convexFromLocal, convexToLocal,
+ convexbody->getCcdSweptSphereRadius(), curHitFraction);
raycastCallback.m_hitFraction = convexbody->getHitFraction();
btCollisionObject* concavebody = triBody;
- btConcaveShape* triangleMesh = (btConcaveShape*) concavebody->getCollisionShape();
+ btConcaveShape* triangleMesh = (btConcaveShape*)concavebody->getCollisionShape();
if (triangleMesh)
{
- triangleMesh->processAllTriangles(&raycastCallback,rayAabbMin,rayAabbMax);
+ triangleMesh->processAllTriangles(&raycastCallback, rayAabbMin, rayAabbMax);
}
-
-
if (raycastCallback.m_hitFraction < convexbody->getHitFraction())
{
- convexbody->setHitFraction( raycastCallback.m_hitFraction);
+ convexbody->setHitFraction(raycastCallback.m_hitFraction);
return raycastCallback.m_hitFraction;
}
}
return btScalar(1.);
-
}
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h b/thirdparty/bullet/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h
index 11c7b88f98..3adedbd805 100644
--- a/thirdparty/bullet/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h
+++ b/thirdparty/bullet/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h
@@ -29,63 +29,62 @@ class btCollisionShape;
#include "LinearMath/btHashMap.h"
-#include "BulletCollision/BroadphaseCollision/btQuantizedBvh.h" //for definition of MAX_NUM_PARTS_IN_BITS
+#include "BulletCollision/BroadphaseCollision/btQuantizedBvh.h" //for definition of MAX_NUM_PARTS_IN_BITS
struct btTriIndex
{
int m_PartIdTriangleIndex;
- class btCollisionShape* m_childShape;
+ class btCollisionShape* m_childShape;
- btTriIndex(int partId,int triangleIndex,btCollisionShape* shape)
+ btTriIndex(int partId, int triangleIndex, btCollisionShape* shape)
{
- m_PartIdTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | triangleIndex;
+ m_PartIdTriangleIndex = (partId << (31 - MAX_NUM_PARTS_IN_BITS)) | triangleIndex;
m_childShape = shape;
}
- int getTriangleIndex() const
+ int getTriangleIndex() const
{
// Get only the lower bits where the triangle index is stored
unsigned int x = 0;
- unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);
- return (m_PartIdTriangleIndex&~(y));
+ unsigned int y = (~(x & 0)) << (31 - MAX_NUM_PARTS_IN_BITS);
+ return (m_PartIdTriangleIndex & ~(y));
}
- int getPartId() const
+ int getPartId() const
{
// Get only the highest bits where the part index is stored
- return (m_PartIdTriangleIndex>>(31-MAX_NUM_PARTS_IN_BITS));
+ return (m_PartIdTriangleIndex >> (31 - MAX_NUM_PARTS_IN_BITS));
}
- int getUid() const
+ int getUid() const
{
return m_PartIdTriangleIndex;
}
};
-
///For each triangle in the concave mesh that overlaps with the AABB of a soft body (m_softBody), processTriangle is called.
class btSoftBodyTriangleCallback : public btTriangleCallback
{
btSoftBody* m_softBody;
const btCollisionObject* m_triBody;
- btVector3 m_aabbMin;
- btVector3 m_aabbMax ;
+ btVector3 m_aabbMin;
+ btVector3 m_aabbMax;
btManifoldResult* m_resultOut;
- btDispatcher* m_dispatcher;
+ btDispatcher* m_dispatcher;
const btDispatcherInfo* m_dispatchInfoPtr;
btScalar m_collisionMarginTriangle;
- btHashMap<btHashKey<btTriIndex>,btTriIndex> m_shapeCache;
+ btHashMap<btHashKey<btTriIndex>, btTriIndex> m_shapeCache;
public:
- int m_triangleCount;
+ int m_triangleCount;
// btPersistentManifold* m_manifoldPtr;
- btSoftBodyTriangleCallback(btDispatcher* dispatcher,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped);
+ btSoftBodyTriangleCallback(btDispatcher* dispatcher, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped);
- void setTimeStepAndCounters(btScalar collisionMarginTriangle,const btCollisionObjectWrapper* triObjWrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ void setTimeStepAndCounters(btScalar collisionMarginTriangle, const btCollisionObjectWrapper* triObjWrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual ~btSoftBodyTriangleCallback();
@@ -101,55 +100,48 @@ public:
{
return m_aabbMax;
}
-
};
-
-
-
/// btSoftBodyConcaveCollisionAlgorithm supports collision between soft body shapes and (concave) trianges meshes.
-class btSoftBodyConcaveCollisionAlgorithm : public btCollisionAlgorithm
+class btSoftBodyConcaveCollisionAlgorithm : public btCollisionAlgorithm
{
-
- bool m_isSwapped;
+ bool m_isSwapped;
btSoftBodyTriangleCallback m_btSoftBodyTriangleCallback;
public:
-
- btSoftBodyConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped);
+ btSoftBodyConcaveCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped);
virtual ~btSoftBodyConcaveCollisionAlgorithm();
- virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
- btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
- virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
//we don't add any manifolds
}
- void clearCache();
+ void clearCache();
- struct CreateFunc :public btCollisionAlgorithmCreateFunc
+ struct CreateFunc : public btCollisionAlgorithmCreateFunc
{
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftBodyConcaveCollisionAlgorithm));
- return new(mem) btSoftBodyConcaveCollisionAlgorithm(ci,body0Wrap,body1Wrap,false);
+ return new (mem) btSoftBodyConcaveCollisionAlgorithm(ci, body0Wrap, body1Wrap, false);
}
};
- struct SwappedCreateFunc :public btCollisionAlgorithmCreateFunc
+ struct SwappedCreateFunc : public btCollisionAlgorithmCreateFunc
{
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftBodyConcaveCollisionAlgorithm));
- return new(mem) btSoftBodyConcaveCollisionAlgorithm(ci,body0Wrap,body1Wrap,true);
+ return new (mem) btSoftBodyConcaveCollisionAlgorithm(ci, body0Wrap, body1Wrap, true);
}
};
-
};
-#endif //BT_SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_H
+#endif //BT_SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_H
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftBodyData.h b/thirdparty/bullet/BulletSoftBody/btSoftBodyData.h
index 87d8841cfa..cec6f401ec 100644
--- a/thirdparty/bullet/BulletSoftBody/btSoftBodyData.h
+++ b/thirdparty/bullet/BulletSoftBody/btSoftBodyData.h
@@ -19,199 +19,194 @@ subject to the following restrictions:
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletDynamics/Dynamics/btRigidBody.h"
-
-struct SoftBodyMaterialData
+struct SoftBodyMaterialData
{
- float m_linearStiffness;
- float m_angularStiffness;
- float m_volumeStiffness;
- int m_flags;
+ float m_linearStiffness;
+ float m_angularStiffness;
+ float m_volumeStiffness;
+ int m_flags;
};
-struct SoftBodyNodeData
+struct SoftBodyNodeData
{
- SoftBodyMaterialData *m_material;
- btVector3FloatData m_position;
- btVector3FloatData m_previousPosition;
- btVector3FloatData m_velocity;
- btVector3FloatData m_accumulatedForce;
- btVector3FloatData m_normal;
- float m_inverseMass;
- float m_area;
- int m_attach;
- int m_pad;
+ SoftBodyMaterialData *m_material;
+ btVector3FloatData m_position;
+ btVector3FloatData m_previousPosition;
+ btVector3FloatData m_velocity;
+ btVector3FloatData m_accumulatedForce;
+ btVector3FloatData m_normal;
+ float m_inverseMass;
+ float m_area;
+ int m_attach;
+ int m_pad;
};
-struct SoftBodyLinkData
+struct SoftBodyLinkData
{
- SoftBodyMaterialData *m_material;
- int m_nodeIndices[2]; // Node pointers
- float m_restLength; // Rest length
- int m_bbending; // Bending link
+ SoftBodyMaterialData *m_material;
+ int m_nodeIndices[2]; // Node pointers
+ float m_restLength; // Rest length
+ int m_bbending; // Bending link
};
-struct SoftBodyFaceData
+struct SoftBodyFaceData
{
- btVector3FloatData m_normal; // Normal
- SoftBodyMaterialData *m_material;
- int m_nodeIndices[3]; // Node pointers
- float m_restArea; // Rest area
-};
+ btVector3FloatData m_normal; // Normal
+ SoftBodyMaterialData *m_material;
+ int m_nodeIndices[3]; // Node pointers
+ float m_restArea; // Rest area
+};
-struct SoftBodyTetraData
+struct SoftBodyTetraData
{
- btVector3FloatData m_c0[4]; // gradients
- SoftBodyMaterialData *m_material;
- int m_nodeIndices[4]; // Node pointers
- float m_restVolume; // Rest volume
- float m_c1; // (4*kVST)/(im0+im1+im2+im3)
- float m_c2; // m_c1/sum(|g0..3|^2)
- int m_pad;
+ btVector3FloatData m_c0[4]; // gradients
+ SoftBodyMaterialData *m_material;
+ int m_nodeIndices[4]; // Node pointers
+ float m_restVolume; // Rest volume
+ float m_c1; // (4*kVST)/(im0+im1+im2+im3)
+ float m_c2; // m_c1/sum(|g0..3|^2)
+ int m_pad;
};
-struct SoftRigidAnchorData
+struct SoftRigidAnchorData
{
- btMatrix3x3FloatData m_c0; // Impulse matrix
- btVector3FloatData m_c1; // Relative anchor
- btVector3FloatData m_localFrame; // Anchor position in body space
- btRigidBodyData *m_rigidBody;
- int m_nodeIndex; // Node pointer
- float m_c2; // ima*dt
+ btMatrix3x3FloatData m_c0; // Impulse matrix
+ btVector3FloatData m_c1; // Relative anchor
+ btVector3FloatData m_localFrame; // Anchor position in body space
+ btRigidBodyData *m_rigidBody;
+ int m_nodeIndex; // Node pointer
+ float m_c2; // ima*dt
};
-
-
-struct SoftBodyConfigData
+struct SoftBodyConfigData
{
- int m_aeroModel; // Aerodynamic model (default: V_Point)
- float m_baumgarte; // Velocities correction factor (Baumgarte)
- float m_damping; // Damping coefficient [0,1]
- float m_drag; // Drag coefficient [0,+inf]
- float m_lift; // Lift coefficient [0,+inf]
- float m_pressure; // Pressure coefficient [-inf,+inf]
- float m_volume; // Volume conversation coefficient [0,+inf]
- float m_dynamicFriction; // Dynamic friction coefficient [0,1]
- float m_poseMatch; // Pose matching coefficient [0,1]
- float m_rigidContactHardness; // Rigid contacts hardness [0,1]
- float m_kineticContactHardness; // Kinetic contacts hardness [0,1]
- float m_softContactHardness; // Soft contacts hardness [0,1]
- float m_anchorHardness; // Anchors hardness [0,1]
- float m_softRigidClusterHardness; // Soft vs rigid hardness [0,1] (cluster only)
- float m_softKineticClusterHardness; // Soft vs kinetic hardness [0,1] (cluster only)
- float m_softSoftClusterHardness; // Soft vs soft hardness [0,1] (cluster only)
- float m_softRigidClusterImpulseSplit; // Soft vs rigid impulse split [0,1] (cluster only)
- float m_softKineticClusterImpulseSplit; // Soft vs rigid impulse split [0,1] (cluster only)
- float m_softSoftClusterImpulseSplit; // Soft vs rigid impulse split [0,1] (cluster only)
- float m_maxVolume; // Maximum volume ratio for pose
- float m_timeScale; // Time scale
- int m_velocityIterations; // Velocities solver iterations
- int m_positionIterations; // Positions solver iterations
- int m_driftIterations; // Drift solver iterations
- int m_clusterIterations; // Cluster solver iterations
- int m_collisionFlags; // Collisions flags
+ int m_aeroModel; // Aerodynamic model (default: V_Point)
+ float m_baumgarte; // Velocities correction factor (Baumgarte)
+ float m_damping; // Damping coefficient [0,1]
+ float m_drag; // Drag coefficient [0,+inf]
+ float m_lift; // Lift coefficient [0,+inf]
+ float m_pressure; // Pressure coefficient [-inf,+inf]
+ float m_volume; // Volume conversation coefficient [0,+inf]
+ float m_dynamicFriction; // Dynamic friction coefficient [0,1]
+ float m_poseMatch; // Pose matching coefficient [0,1]
+ float m_rigidContactHardness; // Rigid contacts hardness [0,1]
+ float m_kineticContactHardness; // Kinetic contacts hardness [0,1]
+ float m_softContactHardness; // Soft contacts hardness [0,1]
+ float m_anchorHardness; // Anchors hardness [0,1]
+ float m_softRigidClusterHardness; // Soft vs rigid hardness [0,1] (cluster only)
+ float m_softKineticClusterHardness; // Soft vs kinetic hardness [0,1] (cluster only)
+ float m_softSoftClusterHardness; // Soft vs soft hardness [0,1] (cluster only)
+ float m_softRigidClusterImpulseSplit; // Soft vs rigid impulse split [0,1] (cluster only)
+ float m_softKineticClusterImpulseSplit; // Soft vs rigid impulse split [0,1] (cluster only)
+ float m_softSoftClusterImpulseSplit; // Soft vs rigid impulse split [0,1] (cluster only)
+ float m_maxVolume; // Maximum volume ratio for pose
+ float m_timeScale; // Time scale
+ int m_velocityIterations; // Velocities solver iterations
+ int m_positionIterations; // Positions solver iterations
+ int m_driftIterations; // Drift solver iterations
+ int m_clusterIterations; // Cluster solver iterations
+ int m_collisionFlags; // Collisions flags
};
-struct SoftBodyPoseData
+struct SoftBodyPoseData
{
- btMatrix3x3FloatData m_rot; // Rotation
- btMatrix3x3FloatData m_scale; // Scale
- btMatrix3x3FloatData m_aqq; // Base scaling
- btVector3FloatData m_com; // COM
-
- btVector3FloatData *m_positions; // Reference positions
- float *m_weights; // Weights
- int m_numPositions;
- int m_numWeigts;
-
- int m_bvolume; // Is valid
- int m_bframe; // Is frame
- float m_restVolume; // Rest volume
- int m_pad;
+ btMatrix3x3FloatData m_rot; // Rotation
+ btMatrix3x3FloatData m_scale; // Scale
+ btMatrix3x3FloatData m_aqq; // Base scaling
+ btVector3FloatData m_com; // COM
+
+ btVector3FloatData *m_positions; // Reference positions
+ float *m_weights; // Weights
+ int m_numPositions;
+ int m_numWeigts;
+
+ int m_bvolume; // Is valid
+ int m_bframe; // Is frame
+ float m_restVolume; // Rest volume
+ int m_pad;
};
-struct SoftBodyClusterData
+struct SoftBodyClusterData
{
- btTransformFloatData m_framexform;
- btMatrix3x3FloatData m_locii;
- btMatrix3x3FloatData m_invwi;
- btVector3FloatData m_com;
- btVector3FloatData m_vimpulses[2];
- btVector3FloatData m_dimpulses[2];
- btVector3FloatData m_lv;
- btVector3FloatData m_av;
-
- btVector3FloatData *m_framerefs;
- int *m_nodeIndices;
- float *m_masses;
-
- int m_numFrameRefs;
- int m_numNodes;
- int m_numMasses;
-
- float m_idmass;
- float m_imass;
- int m_nvimpulses;
- int m_ndimpulses;
- float m_ndamping;
- float m_ldamping;
- float m_adamping;
- float m_matching;
- float m_maxSelfCollisionImpulse;
- float m_selfCollisionImpulseFactor;
- int m_containsAnchor;
- int m_collide;
- int m_clusterIndex;
+ btTransformFloatData m_framexform;
+ btMatrix3x3FloatData m_locii;
+ btMatrix3x3FloatData m_invwi;
+ btVector3FloatData m_com;
+ btVector3FloatData m_vimpulses[2];
+ btVector3FloatData m_dimpulses[2];
+ btVector3FloatData m_lv;
+ btVector3FloatData m_av;
+
+ btVector3FloatData *m_framerefs;
+ int *m_nodeIndices;
+ float *m_masses;
+
+ int m_numFrameRefs;
+ int m_numNodes;
+ int m_numMasses;
+
+ float m_idmass;
+ float m_imass;
+ int m_nvimpulses;
+ int m_ndimpulses;
+ float m_ndamping;
+ float m_ldamping;
+ float m_adamping;
+ float m_matching;
+ float m_maxSelfCollisionImpulse;
+ float m_selfCollisionImpulseFactor;
+ int m_containsAnchor;
+ int m_collide;
+ int m_clusterIndex;
};
-
-enum btSoftJointBodyType
+enum btSoftJointBodyType
{
- BT_JOINT_SOFT_BODY_CLUSTER=1,
+ BT_JOINT_SOFT_BODY_CLUSTER = 1,
BT_JOINT_RIGID_BODY,
BT_JOINT_COLLISION_OBJECT
};
-struct btSoftBodyJointData
+struct btSoftBodyJointData
{
- void *m_bodyA;
- void *m_bodyB;
- btVector3FloatData m_refs[2];
- float m_cfm;
- float m_erp;
- float m_split;
- int m_delete;
- btVector3FloatData m_relPosition[2];//linear
- int m_bodyAtype;
- int m_bodyBtype;
- int m_jointType;
- int m_pad;
+ void *m_bodyA;
+ void *m_bodyB;
+ btVector3FloatData m_refs[2];
+ float m_cfm;
+ float m_erp;
+ float m_split;
+ int m_delete;
+ btVector3FloatData m_relPosition[2]; //linear
+ int m_bodyAtype;
+ int m_bodyBtype;
+ int m_jointType;
+ int m_pad;
};
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btSoftBodyFloatData
+struct btSoftBodyFloatData
{
- btCollisionObjectFloatData m_collisionObjectData;
-
- SoftBodyPoseData *m_pose;
- SoftBodyMaterialData **m_materials;
- SoftBodyNodeData *m_nodes;
- SoftBodyLinkData *m_links;
- SoftBodyFaceData *m_faces;
- SoftBodyTetraData *m_tetrahedra;
- SoftRigidAnchorData *m_anchors;
- SoftBodyClusterData *m_clusters;
- btSoftBodyJointData *m_joints;
-
- int m_numMaterials;
- int m_numNodes;
- int m_numLinks;
- int m_numFaces;
- int m_numTetrahedra;
- int m_numAnchors;
- int m_numClusters;
- int m_numJoints;
- SoftBodyConfigData m_config;
+ btCollisionObjectFloatData m_collisionObjectData;
+
+ SoftBodyPoseData *m_pose;
+ SoftBodyMaterialData **m_materials;
+ SoftBodyNodeData *m_nodes;
+ SoftBodyLinkData *m_links;
+ SoftBodyFaceData *m_faces;
+ SoftBodyTetraData *m_tetrahedra;
+ SoftRigidAnchorData *m_anchors;
+ SoftBodyClusterData *m_clusters;
+ btSoftBodyJointData *m_joints;
+
+ int m_numMaterials;
+ int m_numNodes;
+ int m_numLinks;
+ int m_numFaces;
+ int m_numTetrahedra;
+ int m_numAnchors;
+ int m_numClusters;
+ int m_numJoints;
+ SoftBodyConfigData m_config;
};
-#endif //BT_SOFTBODY_FLOAT_DATA
-
+#endif //BT_SOFTBODY_FLOAT_DATA
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.cpp b/thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.cpp
index 51fcd16da4..d0a9921d89 100644
--- a/thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.cpp
+++ b/thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.cpp
@@ -21,106 +21,111 @@ subject to the following restrictions:
#include "LinearMath/btConvexHull.h"
#include "LinearMath/btConvexHullComputer.h"
-
//
-static void drawVertex( btIDebugDraw* idraw,
- const btVector3& x,btScalar s,const btVector3& c)
+static void drawVertex(btIDebugDraw* idraw,
+ const btVector3& x, btScalar s, const btVector3& c)
{
- idraw->drawLine(x-btVector3(s,0,0),x+btVector3(s,0,0),c);
- idraw->drawLine(x-btVector3(0,s,0),x+btVector3(0,s,0),c);
- idraw->drawLine(x-btVector3(0,0,s),x+btVector3(0,0,s),c);
+ idraw->drawLine(x - btVector3(s, 0, 0), x + btVector3(s, 0, 0), c);
+ idraw->drawLine(x - btVector3(0, s, 0), x + btVector3(0, s, 0), c);
+ idraw->drawLine(x - btVector3(0, 0, s), x + btVector3(0, 0, s), c);
}
//
-static void drawBox( btIDebugDraw* idraw,
- const btVector3& mins,
- const btVector3& maxs,
- const btVector3& color)
+static void drawBox(btIDebugDraw* idraw,
+ const btVector3& mins,
+ const btVector3& maxs,
+ const btVector3& color)
{
- const btVector3 c[]={ btVector3(mins.x(),mins.y(),mins.z()),
- btVector3(maxs.x(),mins.y(),mins.z()),
- btVector3(maxs.x(),maxs.y(),mins.z()),
- btVector3(mins.x(),maxs.y(),mins.z()),
- btVector3(mins.x(),mins.y(),maxs.z()),
- btVector3(maxs.x(),mins.y(),maxs.z()),
- btVector3(maxs.x(),maxs.y(),maxs.z()),
- btVector3(mins.x(),maxs.y(),maxs.z())};
- idraw->drawLine(c[0],c[1],color);idraw->drawLine(c[1],c[2],color);
- idraw->drawLine(c[2],c[3],color);idraw->drawLine(c[3],c[0],color);
- idraw->drawLine(c[4],c[5],color);idraw->drawLine(c[5],c[6],color);
- idraw->drawLine(c[6],c[7],color);idraw->drawLine(c[7],c[4],color);
- idraw->drawLine(c[0],c[4],color);idraw->drawLine(c[1],c[5],color);
- idraw->drawLine(c[2],c[6],color);idraw->drawLine(c[3],c[7],color);
+ const btVector3 c[] = {btVector3(mins.x(), mins.y(), mins.z()),
+ btVector3(maxs.x(), mins.y(), mins.z()),
+ btVector3(maxs.x(), maxs.y(), mins.z()),
+ btVector3(mins.x(), maxs.y(), mins.z()),
+ btVector3(mins.x(), mins.y(), maxs.z()),
+ btVector3(maxs.x(), mins.y(), maxs.z()),
+ btVector3(maxs.x(), maxs.y(), maxs.z()),
+ btVector3(mins.x(), maxs.y(), maxs.z())};
+ idraw->drawLine(c[0], c[1], color);
+ idraw->drawLine(c[1], c[2], color);
+ idraw->drawLine(c[2], c[3], color);
+ idraw->drawLine(c[3], c[0], color);
+ idraw->drawLine(c[4], c[5], color);
+ idraw->drawLine(c[5], c[6], color);
+ idraw->drawLine(c[6], c[7], color);
+ idraw->drawLine(c[7], c[4], color);
+ idraw->drawLine(c[0], c[4], color);
+ idraw->drawLine(c[1], c[5], color);
+ idraw->drawLine(c[2], c[6], color);
+ idraw->drawLine(c[3], c[7], color);
}
//
-static void drawTree( btIDebugDraw* idraw,
- const btDbvtNode* node,
- int depth,
- const btVector3& ncolor,
- const btVector3& lcolor,
- int mindepth,
- int maxdepth)
+static void drawTree(btIDebugDraw* idraw,
+ const btDbvtNode* node,
+ int depth,
+ const btVector3& ncolor,
+ const btVector3& lcolor,
+ int mindepth,
+ int maxdepth)
{
- if(node)
+ if (node)
{
- if(node->isinternal()&&((depth<maxdepth)||(maxdepth<0)))
+ if (node->isinternal() && ((depth < maxdepth) || (maxdepth < 0)))
{
- drawTree(idraw,node->childs[0],depth+1,ncolor,lcolor,mindepth,maxdepth);
- drawTree(idraw,node->childs[1],depth+1,ncolor,lcolor,mindepth,maxdepth);
+ drawTree(idraw, node->childs[0], depth + 1, ncolor, lcolor, mindepth, maxdepth);
+ drawTree(idraw, node->childs[1], depth + 1, ncolor, lcolor, mindepth, maxdepth);
}
- if(depth>=mindepth)
+ if (depth >= mindepth)
{
- const btScalar scl=(btScalar)(node->isinternal()?1:1);
- const btVector3 mi=node->volume.Center()-node->volume.Extents()*scl;
- const btVector3 mx=node->volume.Center()+node->volume.Extents()*scl;
- drawBox(idraw,mi,mx,node->isleaf()?lcolor:ncolor);
+ const btScalar scl = (btScalar)(node->isinternal() ? 1 : 1);
+ const btVector3 mi = node->volume.Center() - node->volume.Extents() * scl;
+ const btVector3 mx = node->volume.Center() + node->volume.Extents() * scl;
+ drawBox(idraw, mi, mx, node->isleaf() ? lcolor : ncolor);
}
}
}
//
template <typename T>
-static inline T sum(const btAlignedObjectArray<T>& items)
+static inline T sum(const btAlignedObjectArray<T>& items)
{
- T v;
- if(items.size())
+ T v;
+ if (items.size())
{
- v=items[0];
- for(int i=1,ni=items.size();i<ni;++i)
+ v = items[0];
+ for (int i = 1, ni = items.size(); i < ni; ++i)
{
- v+=items[i];
+ v += items[i];
}
}
- return(v);
+ return (v);
}
//
-template <typename T,typename Q>
-static inline void add(btAlignedObjectArray<T>& items,const Q& value)
+template <typename T, typename Q>
+static inline void add(btAlignedObjectArray<T>& items, const Q& value)
{
- for(int i=0,ni=items.size();i<ni;++i)
+ for (int i = 0, ni = items.size(); i < ni; ++i)
{
- items[i]+=value;
+ items[i] += value;
}
}
//
-template <typename T,typename Q>
-static inline void mul(btAlignedObjectArray<T>& items,const Q& value)
+template <typename T, typename Q>
+static inline void mul(btAlignedObjectArray<T>& items, const Q& value)
{
- for(int i=0,ni=items.size();i<ni;++i)
+ for (int i = 0, ni = items.size(); i < ni; ++i)
{
- items[i]*=value;
+ items[i] *= value;
}
}
//
template <typename T>
-static inline T average(const btAlignedObjectArray<T>& items)
+static inline T average(const btAlignedObjectArray<T>& items)
{
- const btScalar n=(btScalar)(items.size()>0?items.size():1);
- return(sum(items)/n);
+ const btScalar n = (btScalar)(items.size() > 0 ? items.size() : 1);
+ return (sum(items) / n);
}
#if 0
@@ -158,86 +163,84 @@ static btVector3 stresscolor(btScalar stress)
#endif
//
-void btSoftBodyHelpers::Draw( btSoftBody* psb,
- btIDebugDraw* idraw,
- int drawflags)
+void btSoftBodyHelpers::Draw(btSoftBody* psb,
+ btIDebugDraw* idraw,
+ int drawflags)
{
- const btScalar scl=(btScalar)0.1;
- const btScalar nscl=scl*5;
- const btVector3 lcolor=btVector3(0,0,0);
- const btVector3 ncolor=btVector3(1,1,1);
- const btVector3 ccolor=btVector3(1,0,0);
- int i,j,nj;
-
- /* Clusters */
- if(0!=(drawflags&fDrawFlags::Clusters))
+ const btScalar scl = (btScalar)0.1;
+ const btScalar nscl = scl * 5;
+ const btVector3 lcolor = btVector3(0, 0, 0);
+ const btVector3 ncolor = btVector3(1, 1, 1);
+ const btVector3 ccolor = btVector3(1, 0, 0);
+ int i, j, nj;
+
+ /* Clusters */
+ if (0 != (drawflags & fDrawFlags::Clusters))
{
srand(1806);
- for(i=0;i<psb->m_clusters.size();++i)
+ for (i = 0; i < psb->m_clusters.size(); ++i)
{
- if(psb->m_clusters[i]->m_collide)
+ if (psb->m_clusters[i]->m_collide)
{
- btVector3 color( rand()/(btScalar)RAND_MAX,
- rand()/(btScalar)RAND_MAX,
- rand()/(btScalar)RAND_MAX);
- color=color.normalized()*0.75;
- btAlignedObjectArray<btVector3> vertices;
+ btVector3 color(rand() / (btScalar)RAND_MAX,
+ rand() / (btScalar)RAND_MAX,
+ rand() / (btScalar)RAND_MAX);
+ color = color.normalized() * 0.75;
+ btAlignedObjectArray<btVector3> vertices;
vertices.resize(psb->m_clusters[i]->m_nodes.size());
- for(j=0,nj=vertices.size();j<nj;++j)
- {
- vertices[j]=psb->m_clusters[i]->m_nodes[j]->m_x;
+ for (j = 0, nj = vertices.size(); j < nj; ++j)
+ {
+ vertices[j] = psb->m_clusters[i]->m_nodes[j]->m_x;
}
#define USE_NEW_CONVEX_HULL_COMPUTER
#ifdef USE_NEW_CONVEX_HULL_COMPUTER
- btConvexHullComputer computer;
+ btConvexHullComputer computer;
int stride = sizeof(btVector3);
int count = vertices.size();
- btScalar shrink=0.f;
- btScalar shrinkClamp=0.f;
- computer.compute(&vertices[0].getX(),stride,count,shrink,shrinkClamp);
- for (int i=0;i<computer.faces.size();i++)
+ btScalar shrink = 0.f;
+ btScalar shrinkClamp = 0.f;
+ computer.compute(&vertices[0].getX(), stride, count, shrink, shrinkClamp);
+ for (int i = 0; i < computer.faces.size(); i++)
{
-
int face = computer.faces[i];
//printf("face=%d\n",face);
- const btConvexHullComputer::Edge* firstEdge = &computer.edges[face];
- const btConvexHullComputer::Edge* edge = firstEdge->getNextEdgeOfFace();
+ const btConvexHullComputer::Edge* firstEdge = &computer.edges[face];
+ const btConvexHullComputer::Edge* edge = firstEdge->getNextEdgeOfFace();
int v0 = firstEdge->getSourceVertex();
int v1 = firstEdge->getTargetVertex();
- while (edge!=firstEdge)
+ while (edge != firstEdge)
{
int v2 = edge->getTargetVertex();
- idraw->drawTriangle(computer.vertices[v0],computer.vertices[v1],computer.vertices[v2],color,1);
+ idraw->drawTriangle(computer.vertices[v0], computer.vertices[v1], computer.vertices[v2], color, 1);
edge = edge->getNextEdgeOfFace();
- v0=v1;
- v1=v2;
+ v0 = v1;
+ v1 = v2;
};
}
#else
- HullDesc hdsc(QF_TRIANGLES,vertices.size(),&vertices[0]);
- HullResult hres;
- HullLibrary hlib;
- hdsc.mMaxVertices=vertices.size();
- hlib.CreateConvexHull(hdsc,hres);
- const btVector3 center=average(hres.m_OutputVertices);
- add(hres.m_OutputVertices,-center);
- mul(hres.m_OutputVertices,(btScalar)1);
- add(hres.m_OutputVertices,center);
- for(j=0;j<(int)hres.mNumFaces;++j)
+ HullDesc hdsc(QF_TRIANGLES, vertices.size(), &vertices[0]);
+ HullResult hres;
+ HullLibrary hlib;
+ hdsc.mMaxVertices = vertices.size();
+ hlib.CreateConvexHull(hdsc, hres);
+ const btVector3 center = average(hres.m_OutputVertices);
+ add(hres.m_OutputVertices, -center);
+ mul(hres.m_OutputVertices, (btScalar)1);
+ add(hres.m_OutputVertices, center);
+ for (j = 0; j < (int)hres.mNumFaces; ++j)
{
- const int idx[]={hres.m_Indices[j*3+0],hres.m_Indices[j*3+1],hres.m_Indices[j*3+2]};
+ const int idx[] = {hres.m_Indices[j * 3 + 0], hres.m_Indices[j * 3 + 1], hres.m_Indices[j * 3 + 2]};
idraw->drawTriangle(hres.m_OutputVertices[idx[0]],
- hres.m_OutputVertices[idx[1]],
- hres.m_OutputVertices[idx[2]],
- color,1);
+ hres.m_OutputVertices[idx[1]],
+ hres.m_OutputVertices[idx[2]],
+ color, 1);
}
hlib.ReleaseResult(hres);
#endif
-
}
- /* Velocities */
+ /* Velocities */
#if 0
for(int j=0;j<psb->m_clusters[i].m_nodes.size();++j)
{
@@ -247,273 +250,269 @@ void btSoftBodyHelpers::Draw( btSoftBody* psb,
idraw->drawLine(c.m_nodes[j]->m_x,c.m_nodes[j]->m_x+v,btVector3(1,0,0));
}
#endif
- /* Frame */
- // btSoftBody::Cluster& c=*psb->m_clusters[i];
- // idraw->drawLine(c.m_com,c.m_framexform*btVector3(10,0,0),btVector3(1,0,0));
- // idraw->drawLine(c.m_com,c.m_framexform*btVector3(0,10,0),btVector3(0,1,0));
- // idraw->drawLine(c.m_com,c.m_framexform*btVector3(0,0,10),btVector3(0,0,1));
+ /* Frame */
+ // btSoftBody::Cluster& c=*psb->m_clusters[i];
+ // idraw->drawLine(c.m_com,c.m_framexform*btVector3(10,0,0),btVector3(1,0,0));
+ // idraw->drawLine(c.m_com,c.m_framexform*btVector3(0,10,0),btVector3(0,1,0));
+ // idraw->drawLine(c.m_com,c.m_framexform*btVector3(0,0,10),btVector3(0,0,1));
}
}
else
{
- /* Nodes */
- if(0!=(drawflags&fDrawFlags::Nodes))
+ /* Nodes */
+ if (0 != (drawflags & fDrawFlags::Nodes))
{
- for(i=0;i<psb->m_nodes.size();++i)
+ for (i = 0; i < psb->m_nodes.size(); ++i)
{
- const btSoftBody::Node& n=psb->m_nodes[i];
- if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
- idraw->drawLine(n.m_x-btVector3(scl,0,0),n.m_x+btVector3(scl,0,0),btVector3(1,0,0));
- idraw->drawLine(n.m_x-btVector3(0,scl,0),n.m_x+btVector3(0,scl,0),btVector3(0,1,0));
- idraw->drawLine(n.m_x-btVector3(0,0,scl),n.m_x+btVector3(0,0,scl),btVector3(0,0,1));
+ const btSoftBody::Node& n = psb->m_nodes[i];
+ if (0 == (n.m_material->m_flags & btSoftBody::fMaterial::DebugDraw)) continue;
+ idraw->drawLine(n.m_x - btVector3(scl, 0, 0), n.m_x + btVector3(scl, 0, 0), btVector3(1, 0, 0));
+ idraw->drawLine(n.m_x - btVector3(0, scl, 0), n.m_x + btVector3(0, scl, 0), btVector3(0, 1, 0));
+ idraw->drawLine(n.m_x - btVector3(0, 0, scl), n.m_x + btVector3(0, 0, scl), btVector3(0, 0, 1));
}
}
- /* Links */
- if(0!=(drawflags&fDrawFlags::Links))
+ /* Links */
+ if (0 != (drawflags & fDrawFlags::Links))
{
- for(i=0;i<psb->m_links.size();++i)
+ for (i = 0; i < psb->m_links.size(); ++i)
{
- const btSoftBody::Link& l=psb->m_links[i];
- if(0==(l.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
- idraw->drawLine(l.m_n[0]->m_x,l.m_n[1]->m_x,lcolor);
+ const btSoftBody::Link& l = psb->m_links[i];
+ if (0 == (l.m_material->m_flags & btSoftBody::fMaterial::DebugDraw)) continue;
+ idraw->drawLine(l.m_n[0]->m_x, l.m_n[1]->m_x, lcolor);
}
}
- /* Normals */
- if(0!=(drawflags&fDrawFlags::Normals))
+ /* Normals */
+ if (0 != (drawflags & fDrawFlags::Normals))
{
- for(i=0;i<psb->m_nodes.size();++i)
+ for (i = 0; i < psb->m_nodes.size(); ++i)
{
- const btSoftBody::Node& n=psb->m_nodes[i];
- if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
- const btVector3 d=n.m_n*nscl;
- idraw->drawLine(n.m_x,n.m_x+d,ncolor);
- idraw->drawLine(n.m_x,n.m_x-d,ncolor*0.5);
+ const btSoftBody::Node& n = psb->m_nodes[i];
+ if (0 == (n.m_material->m_flags & btSoftBody::fMaterial::DebugDraw)) continue;
+ const btVector3 d = n.m_n * nscl;
+ idraw->drawLine(n.m_x, n.m_x + d, ncolor);
+ idraw->drawLine(n.m_x, n.m_x - d, ncolor * 0.5);
}
}
- /* Contacts */
- if(0!=(drawflags&fDrawFlags::Contacts))
+ /* Contacts */
+ if (0 != (drawflags & fDrawFlags::Contacts))
{
- static const btVector3 axis[]={btVector3(1,0,0),
- btVector3(0,1,0),
- btVector3(0,0,1)};
- for(i=0;i<psb->m_rcontacts.size();++i)
- {
- const btSoftBody::RContact& c=psb->m_rcontacts[i];
- const btVector3 o= c.m_node->m_x-c.m_cti.m_normal*
- (btDot(c.m_node->m_x,c.m_cti.m_normal)+c.m_cti.m_offset);
- const btVector3 x=btCross(c.m_cti.m_normal,axis[c.m_cti.m_normal.minAxis()]).normalized();
- const btVector3 y=btCross(x,c.m_cti.m_normal).normalized();
- idraw->drawLine(o-x*nscl,o+x*nscl,ccolor);
- idraw->drawLine(o-y*nscl,o+y*nscl,ccolor);
- idraw->drawLine(o,o+c.m_cti.m_normal*nscl*3,btVector3(1,1,0));
+ static const btVector3 axis[] = {btVector3(1, 0, 0),
+ btVector3(0, 1, 0),
+ btVector3(0, 0, 1)};
+ for (i = 0; i < psb->m_rcontacts.size(); ++i)
+ {
+ const btSoftBody::RContact& c = psb->m_rcontacts[i];
+ const btVector3 o = c.m_node->m_x - c.m_cti.m_normal *
+ (btDot(c.m_node->m_x, c.m_cti.m_normal) + c.m_cti.m_offset);
+ const btVector3 x = btCross(c.m_cti.m_normal, axis[c.m_cti.m_normal.minAxis()]).normalized();
+ const btVector3 y = btCross(x, c.m_cti.m_normal).normalized();
+ idraw->drawLine(o - x * nscl, o + x * nscl, ccolor);
+ idraw->drawLine(o - y * nscl, o + y * nscl, ccolor);
+ idraw->drawLine(o, o + c.m_cti.m_normal * nscl * 3, btVector3(1, 1, 0));
}
}
- /* Faces */
- if(0!=(drawflags&fDrawFlags::Faces))
- {
- const btScalar scl=(btScalar)0.8;
- const btScalar alp=(btScalar)1;
- const btVector3 col(0,(btScalar)0.7,0);
- for(i=0;i<psb->m_faces.size();++i)
+ /* Faces */
+ if (0 != (drawflags & fDrawFlags::Faces))
{
- const btSoftBody::Face& f=psb->m_faces[i];
- if(0==(f.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
- const btVector3 x[]={f.m_n[0]->m_x,f.m_n[1]->m_x,f.m_n[2]->m_x};
- const btVector3 c=(x[0]+x[1]+x[2])/3;
- idraw->drawTriangle((x[0]-c)*scl+c,
- (x[1]-c)*scl+c,
- (x[2]-c)*scl+c,
- col,alp);
- }
- }
- /* Tetras */
- if(0!=(drawflags&fDrawFlags::Tetras))
- {
- const btScalar scl=(btScalar)0.8;
- const btScalar alp=(btScalar)1;
- const btVector3 col((btScalar)0.3,(btScalar)0.3,(btScalar)0.7);
- for(int i=0;i<psb->m_tetras.size();++i)
+ const btScalar scl = (btScalar)0.8;
+ const btScalar alp = (btScalar)1;
+ const btVector3 col(0, (btScalar)0.7, 0);
+ for (i = 0; i < psb->m_faces.size(); ++i)
+ {
+ const btSoftBody::Face& f = psb->m_faces[i];
+ if (0 == (f.m_material->m_flags & btSoftBody::fMaterial::DebugDraw)) continue;
+ const btVector3 x[] = {f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x};
+ const btVector3 c = (x[0] + x[1] + x[2]) / 3;
+ idraw->drawTriangle((x[0] - c) * scl + c,
+ (x[1] - c) * scl + c,
+ (x[2] - c) * scl + c,
+ col, alp);
+ }
+ }
+ /* Tetras */
+ if (0 != (drawflags & fDrawFlags::Tetras))
{
- const btSoftBody::Tetra& t=psb->m_tetras[i];
- if(0==(t.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
- const btVector3 x[]={t.m_n[0]->m_x,t.m_n[1]->m_x,t.m_n[2]->m_x,t.m_n[3]->m_x};
- const btVector3 c=(x[0]+x[1]+x[2]+x[3])/4;
- idraw->drawTriangle((x[0]-c)*scl+c,(x[1]-c)*scl+c,(x[2]-c)*scl+c,col,alp);
- idraw->drawTriangle((x[0]-c)*scl+c,(x[1]-c)*scl+c,(x[3]-c)*scl+c,col,alp);
- idraw->drawTriangle((x[1]-c)*scl+c,(x[2]-c)*scl+c,(x[3]-c)*scl+c,col,alp);
- idraw->drawTriangle((x[2]-c)*scl+c,(x[0]-c)*scl+c,(x[3]-c)*scl+c,col,alp);
- }
- }
+ const btScalar scl = (btScalar)0.8;
+ const btScalar alp = (btScalar)1;
+ const btVector3 col((btScalar)0.3, (btScalar)0.3, (btScalar)0.7);
+ for (int i = 0; i < psb->m_tetras.size(); ++i)
+ {
+ const btSoftBody::Tetra& t = psb->m_tetras[i];
+ if (0 == (t.m_material->m_flags & btSoftBody::fMaterial::DebugDraw)) continue;
+ const btVector3 x[] = {t.m_n[0]->m_x, t.m_n[1]->m_x, t.m_n[2]->m_x, t.m_n[3]->m_x};
+ const btVector3 c = (x[0] + x[1] + x[2] + x[3]) / 4;
+ idraw->drawTriangle((x[0] - c) * scl + c, (x[1] - c) * scl + c, (x[2] - c) * scl + c, col, alp);
+ idraw->drawTriangle((x[0] - c) * scl + c, (x[1] - c) * scl + c, (x[3] - c) * scl + c, col, alp);
+ idraw->drawTriangle((x[1] - c) * scl + c, (x[2] - c) * scl + c, (x[3] - c) * scl + c, col, alp);
+ idraw->drawTriangle((x[2] - c) * scl + c, (x[0] - c) * scl + c, (x[3] - c) * scl + c, col, alp);
+ }
+ }
}
- /* Anchors */
- if(0!=(drawflags&fDrawFlags::Anchors))
+ /* Anchors */
+ if (0 != (drawflags & fDrawFlags::Anchors))
{
- for(i=0;i<psb->m_anchors.size();++i)
+ for (i = 0; i < psb->m_anchors.size(); ++i)
{
- const btSoftBody::Anchor& a=psb->m_anchors[i];
- const btVector3 q=a.m_body->getWorldTransform()*a.m_local;
- drawVertex(idraw,a.m_node->m_x,0.25,btVector3(1,0,0));
- drawVertex(idraw,q,0.25,btVector3(0,1,0));
- idraw->drawLine(a.m_node->m_x,q,btVector3(1,1,1));
+ const btSoftBody::Anchor& a = psb->m_anchors[i];
+ const btVector3 q = a.m_body->getWorldTransform() * a.m_local;
+ drawVertex(idraw, a.m_node->m_x, 0.25, btVector3(1, 0, 0));
+ drawVertex(idraw, q, 0.25, btVector3(0, 1, 0));
+ idraw->drawLine(a.m_node->m_x, q, btVector3(1, 1, 1));
}
- for(i=0;i<psb->m_nodes.size();++i)
+ for (i = 0; i < psb->m_nodes.size(); ++i)
{
- const btSoftBody::Node& n=psb->m_nodes[i];
- if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
- if(n.m_im<=0)
+ const btSoftBody::Node& n = psb->m_nodes[i];
+ if (0 == (n.m_material->m_flags & btSoftBody::fMaterial::DebugDraw)) continue;
+ if (n.m_im <= 0)
{
- drawVertex(idraw,n.m_x,0.25,btVector3(1,0,0));
+ drawVertex(idraw, n.m_x, 0.25, btVector3(1, 0, 0));
}
}
}
-
- /* Notes */
- if(0!=(drawflags&fDrawFlags::Notes))
+ /* Notes */
+ if (0 != (drawflags & fDrawFlags::Notes))
{
- for(i=0;i<psb->m_notes.size();++i)
+ for (i = 0; i < psb->m_notes.size(); ++i)
{
- const btSoftBody::Note& n=psb->m_notes[i];
- btVector3 p=n.m_offset;
- for(int j=0;j<n.m_rank;++j)
+ const btSoftBody::Note& n = psb->m_notes[i];
+ btVector3 p = n.m_offset;
+ for (int j = 0; j < n.m_rank; ++j)
{
- p+=n.m_nodes[j]->m_x*n.m_coords[j];
+ p += n.m_nodes[j]->m_x * n.m_coords[j];
}
- idraw->draw3dText(p,n.m_text);
+ idraw->draw3dText(p, n.m_text);
}
}
- /* Node tree */
- if(0!=(drawflags&fDrawFlags::NodeTree)) DrawNodeTree(psb,idraw);
- /* Face tree */
- if(0!=(drawflags&fDrawFlags::FaceTree)) DrawFaceTree(psb,idraw);
- /* Cluster tree */
- if(0!=(drawflags&fDrawFlags::ClusterTree)) DrawClusterTree(psb,idraw);
- /* Joints */
- if(0!=(drawflags&fDrawFlags::Joints))
+ /* Node tree */
+ if (0 != (drawflags & fDrawFlags::NodeTree)) DrawNodeTree(psb, idraw);
+ /* Face tree */
+ if (0 != (drawflags & fDrawFlags::FaceTree)) DrawFaceTree(psb, idraw);
+ /* Cluster tree */
+ if (0 != (drawflags & fDrawFlags::ClusterTree)) DrawClusterTree(psb, idraw);
+ /* Joints */
+ if (0 != (drawflags & fDrawFlags::Joints))
{
- for(i=0;i<psb->m_joints.size();++i)
+ for (i = 0; i < psb->m_joints.size(); ++i)
{
- const btSoftBody::Joint* pj=psb->m_joints[i];
- switch(pj->Type())
+ const btSoftBody::Joint* pj = psb->m_joints[i];
+ switch (pj->Type())
{
- case btSoftBody::Joint::eType::Linear:
+ case btSoftBody::Joint::eType::Linear:
{
- const btSoftBody::LJoint* pjl=(const btSoftBody::LJoint*)pj;
- const btVector3 a0=pj->m_bodies[0].xform()*pjl->m_refs[0];
- const btVector3 a1=pj->m_bodies[1].xform()*pjl->m_refs[1];
- idraw->drawLine(pj->m_bodies[0].xform().getOrigin(),a0,btVector3(1,1,0));
- idraw->drawLine(pj->m_bodies[1].xform().getOrigin(),a1,btVector3(0,1,1));
- drawVertex(idraw,a0,0.25,btVector3(1,1,0));
- drawVertex(idraw,a1,0.25,btVector3(0,1,1));
+ const btSoftBody::LJoint* pjl = (const btSoftBody::LJoint*)pj;
+ const btVector3 a0 = pj->m_bodies[0].xform() * pjl->m_refs[0];
+ const btVector3 a1 = pj->m_bodies[1].xform() * pjl->m_refs[1];
+ idraw->drawLine(pj->m_bodies[0].xform().getOrigin(), a0, btVector3(1, 1, 0));
+ idraw->drawLine(pj->m_bodies[1].xform().getOrigin(), a1, btVector3(0, 1, 1));
+ drawVertex(idraw, a0, 0.25, btVector3(1, 1, 0));
+ drawVertex(idraw, a1, 0.25, btVector3(0, 1, 1));
}
break;
- case btSoftBody::Joint::eType::Angular:
+ case btSoftBody::Joint::eType::Angular:
{
//const btSoftBody::AJoint* pja=(const btSoftBody::AJoint*)pj;
- const btVector3 o0=pj->m_bodies[0].xform().getOrigin();
- const btVector3 o1=pj->m_bodies[1].xform().getOrigin();
- const btVector3 a0=pj->m_bodies[0].xform().getBasis()*pj->m_refs[0];
- const btVector3 a1=pj->m_bodies[1].xform().getBasis()*pj->m_refs[1];
- idraw->drawLine(o0,o0+a0*10,btVector3(1,1,0));
- idraw->drawLine(o0,o0+a1*10,btVector3(1,1,0));
- idraw->drawLine(o1,o1+a0*10,btVector3(0,1,1));
- idraw->drawLine(o1,o1+a1*10,btVector3(0,1,1));
+ const btVector3 o0 = pj->m_bodies[0].xform().getOrigin();
+ const btVector3 o1 = pj->m_bodies[1].xform().getOrigin();
+ const btVector3 a0 = pj->m_bodies[0].xform().getBasis() * pj->m_refs[0];
+ const btVector3 a1 = pj->m_bodies[1].xform().getBasis() * pj->m_refs[1];
+ idraw->drawLine(o0, o0 + a0 * 10, btVector3(1, 1, 0));
+ idraw->drawLine(o0, o0 + a1 * 10, btVector3(1, 1, 0));
+ idraw->drawLine(o1, o1 + a0 * 10, btVector3(0, 1, 1));
+ idraw->drawLine(o1, o1 + a1 * 10, btVector3(0, 1, 1));
break;
}
default:
{
}
-
- }
+ }
}
}
}
//
-void btSoftBodyHelpers::DrawInfos( btSoftBody* psb,
- btIDebugDraw* idraw,
- bool masses,
- bool areas,
- bool /*stress*/)
+void btSoftBodyHelpers::DrawInfos(btSoftBody* psb,
+ btIDebugDraw* idraw,
+ bool masses,
+ bool areas,
+ bool /*stress*/)
{
- for(int i=0;i<psb->m_nodes.size();++i)
+ for (int i = 0; i < psb->m_nodes.size(); ++i)
{
- const btSoftBody::Node& n=psb->m_nodes[i];
- char text[2048]={0};
- char buff[1024];
- if(masses)
+ const btSoftBody::Node& n = psb->m_nodes[i];
+ char text[2048] = {0};
+ char buff[1024];
+ if (masses)
{
- sprintf(buff," M(%.2f)",1/n.m_im);
- strcat(text,buff);
+ sprintf(buff, " M(%.2f)", 1 / n.m_im);
+ strcat(text, buff);
}
- if(areas)
+ if (areas)
{
- sprintf(buff," A(%.2f)",n.m_area);
- strcat(text,buff);
+ sprintf(buff, " A(%.2f)", n.m_area);
+ strcat(text, buff);
}
- if(text[0]) idraw->draw3dText(n.m_x,text);
+ if (text[0]) idraw->draw3dText(n.m_x, text);
}
}
//
-void btSoftBodyHelpers::DrawNodeTree( btSoftBody* psb,
- btIDebugDraw* idraw,
- int mindepth,
- int maxdepth)
+void btSoftBodyHelpers::DrawNodeTree(btSoftBody* psb,
+ btIDebugDraw* idraw,
+ int mindepth,
+ int maxdepth)
{
- drawTree(idraw,psb->m_ndbvt.m_root,0,btVector3(1,0,1),btVector3(1,1,1),mindepth,maxdepth);
+ drawTree(idraw, psb->m_ndbvt.m_root, 0, btVector3(1, 0, 1), btVector3(1, 1, 1), mindepth, maxdepth);
}
//
-void btSoftBodyHelpers::DrawFaceTree( btSoftBody* psb,
- btIDebugDraw* idraw,
- int mindepth,
- int maxdepth)
+void btSoftBodyHelpers::DrawFaceTree(btSoftBody* psb,
+ btIDebugDraw* idraw,
+ int mindepth,
+ int maxdepth)
{
- drawTree(idraw,psb->m_fdbvt.m_root,0,btVector3(0,1,0),btVector3(1,0,0),mindepth,maxdepth);
+ drawTree(idraw, psb->m_fdbvt.m_root, 0, btVector3(0, 1, 0), btVector3(1, 0, 0), mindepth, maxdepth);
}
//
-void btSoftBodyHelpers::DrawClusterTree( btSoftBody* psb,
- btIDebugDraw* idraw,
- int mindepth,
- int maxdepth)
+void btSoftBodyHelpers::DrawClusterTree(btSoftBody* psb,
+ btIDebugDraw* idraw,
+ int mindepth,
+ int maxdepth)
{
- drawTree(idraw,psb->m_cdbvt.m_root,0,btVector3(0,1,1),btVector3(1,0,0),mindepth,maxdepth);
+ drawTree(idraw, psb->m_cdbvt.m_root, 0, btVector3(0, 1, 1), btVector3(1, 0, 0), mindepth, maxdepth);
}
-
//The btSoftBody object from the BulletSDK includes an array of Nodes and Links. These links appear
-// to be first set up to connect a node to between 5 and 6 of its neighbors [480 links],
-//and then to the rest of the nodes after the execution of the Floyd-Warshall graph algorithm
-//[another 930 links].
+// to be first set up to connect a node to between 5 and 6 of its neighbors [480 links],
+//and then to the rest of the nodes after the execution of the Floyd-Warshall graph algorithm
+//[another 930 links].
//The way the links are stored by default, we have a number of cases where adjacent links share a node in common
-// - this leads to the creation of a data dependency through memory.
-//The PSolve_Links() function reads and writes nodes as it iterates over each link.
-//So, we now have the possibility of a data dependency between iteration X
-//that processes link L with iteration X+1 that processes link L+1
-//because L and L+1 have one node in common, and iteration X updates the positions of that node,
+// - this leads to the creation of a data dependency through memory.
+//The PSolve_Links() function reads and writes nodes as it iterates over each link.
+//So, we now have the possibility of a data dependency between iteration X
+//that processes link L with iteration X+1 that processes link L+1
+//because L and L+1 have one node in common, and iteration X updates the positions of that node,
//and iteration X+1 reads in the position of that shared node.
//
-//Such a memory dependency limits the ability of a modern CPU to speculate beyond
-//a certain point because it has to respect a possible dependency
-//- this prevents the CPU from making full use of its out-of-order resources.
-//If we re-order the links such that we minimize the cases where a link L and L+1 share a common node,
-//we create a temporal gap between when the node position is written,
-//and when it is subsequently read. This in turn allows the CPU to continue execution without
-//risking a dependency violation. Such a reordering would result in significant speedups on
-//modern CPUs with lots of execution resources.
-//In our testing, we see it have a tremendous impact not only on the A7,
-//but also on all x86 cores that ship with modern Macs.
-//The attached source file includes a single function (ReoptimizeLinkOrder) which can be called on a
-//btSoftBody object in the solveConstraints() function before the actual solver is invoked,
+//Such a memory dependency limits the ability of a modern CPU to speculate beyond
+//a certain point because it has to respect a possible dependency
+//- this prevents the CPU from making full use of its out-of-order resources.
+//If we re-order the links such that we minimize the cases where a link L and L+1 share a common node,
+//we create a temporal gap between when the node position is written,
+//and when it is subsequently read. This in turn allows the CPU to continue execution without
+//risking a dependency violation. Such a reordering would result in significant speedups on
+//modern CPUs with lots of execution resources.
+//In our testing, we see it have a tremendous impact not only on the A7,
+//but also on all x86 cores that ship with modern Macs.
+//The attached source file includes a single function (ReoptimizeLinkOrder) which can be called on a
+//btSoftBody object in the solveConstraints() function before the actual solver is invoked,
//or right after generateBendingConstraints() once we have all 1410 links.
-
//===================================================================
//
//
-// This function takes in a list of interdependent Links and tries
+// This function takes in a list of interdependent Links and tries
// to maximize the distance between calculation
// of dependent links. This increases the amount of parallelism that can
// be exploited by out-of-order instruction processors with large but
@@ -522,93 +521,103 @@ void btSoftBodyHelpers::DrawClusterTree( btSoftBody* psb,
//===================================================================
// A small structure to track lists of dependent link calculations
-class LinkDeps_t {
- public:
- int value; // A link calculation that is dependent on this one
- // Positive values = "input A" while negative values = "input B"
- LinkDeps_t *next; // Next dependence in the list
+class LinkDeps_t
+{
+public:
+ int value; // A link calculation that is dependent on this one
+ // Positive values = "input A" while negative values = "input B"
+ LinkDeps_t* next; // Next dependence in the list
};
-typedef LinkDeps_t *LinkDepsPtr_t;
+typedef LinkDeps_t* LinkDepsPtr_t;
// Dependency list constants
-#define REOP_NOT_DEPENDENT -1
-#define REOP_NODE_COMPLETE -2 // Must be less than REOP_NOT_DEPENDENT
-
+#define REOP_NOT_DEPENDENT -1
+#define REOP_NODE_COMPLETE -2 // Must be less than REOP_NOT_DEPENDENT
-void btSoftBodyHelpers::ReoptimizeLinkOrder(btSoftBody *psb /* This can be replaced by a btSoftBody pointer */)
+void btSoftBodyHelpers::ReoptimizeLinkOrder(btSoftBody* psb /* This can be replaced by a btSoftBody pointer */)
{
- int i, nLinks=psb->m_links.size(), nNodes=psb->m_nodes.size();
- btSoftBody::Link *lr;
+ int i, nLinks = psb->m_links.size(), nNodes = psb->m_nodes.size();
+ btSoftBody::Link* lr;
int ar, br;
- btSoftBody::Node *node0 = &(psb->m_nodes[0]);
- btSoftBody::Node *node1 = &(psb->m_nodes[1]);
+ btSoftBody::Node* node0 = &(psb->m_nodes[0]);
+ btSoftBody::Node* node1 = &(psb->m_nodes[1]);
LinkDepsPtr_t linkDep;
int readyListHead, readyListTail, linkNum, linkDepFrees, depLink;
-
+
// Allocate temporary buffers
- int *nodeWrittenAt = new int[nNodes+1]; // What link calculation produced this node's current values?
- int *linkDepA = new int[nLinks]; // Link calculation input is dependent upon prior calculation #N
- int *linkDepB = new int[nLinks];
- int *readyList = new int[nLinks]; // List of ready-to-process link calculations (# of links, maximum)
- LinkDeps_t *linkDepFreeList = new LinkDeps_t[2*nLinks]; // Dependent-on-me list elements (2x# of links, maximum)
- LinkDepsPtr_t *linkDepListStarts = new LinkDepsPtr_t[nLinks]; // Start nodes of dependent-on-me lists, one for each link
-
+ int* nodeWrittenAt = new int[nNodes + 1]; // What link calculation produced this node's current values?
+ int* linkDepA = new int[nLinks]; // Link calculation input is dependent upon prior calculation #N
+ int* linkDepB = new int[nLinks];
+ int* readyList = new int[nLinks]; // List of ready-to-process link calculations (# of links, maximum)
+ LinkDeps_t* linkDepFreeList = new LinkDeps_t[2 * nLinks]; // Dependent-on-me list elements (2x# of links, maximum)
+ LinkDepsPtr_t* linkDepListStarts = new LinkDepsPtr_t[nLinks]; // Start nodes of dependent-on-me lists, one for each link
+
// Copy the original, unsorted links to a side buffer
- btSoftBody::Link *linkBuffer = new btSoftBody::Link[nLinks];
- memcpy(linkBuffer, &(psb->m_links[0]), sizeof(btSoftBody::Link)*nLinks);
+ btSoftBody::Link* linkBuffer = new btSoftBody::Link[nLinks];
+ memcpy(linkBuffer, &(psb->m_links[0]), sizeof(btSoftBody::Link) * nLinks);
// Clear out the node setup and ready list
- for (i=0; i < nNodes+1; i++) {
+ for (i = 0; i < nNodes + 1; i++)
+ {
nodeWrittenAt[i] = REOP_NOT_DEPENDENT;
}
- for (i=0; i < nLinks; i++) {
+ for (i = 0; i < nLinks; i++)
+ {
linkDepListStarts[i] = NULL;
}
readyListHead = readyListTail = linkDepFrees = 0;
// Initial link analysis to set up data structures
- for (i=0; i < nLinks; i++) {
-
+ for (i = 0; i < nLinks; i++)
+ {
// Note which prior link calculations we are dependent upon & build up dependence lists
lr = &(psb->m_links[i]);
- ar = (lr->m_n[0] - node0)/(node1 - node0);
- br = (lr->m_n[1] - node0)/(node1 - node0);
- if (nodeWrittenAt[ar] > REOP_NOT_DEPENDENT) {
+ ar = (lr->m_n[0] - node0) / (node1 - node0);
+ br = (lr->m_n[1] - node0) / (node1 - node0);
+ if (nodeWrittenAt[ar] > REOP_NOT_DEPENDENT)
+ {
linkDepA[i] = nodeWrittenAt[ar];
linkDep = &linkDepFreeList[linkDepFrees++];
linkDep->value = i;
linkDep->next = linkDepListStarts[nodeWrittenAt[ar]];
linkDepListStarts[nodeWrittenAt[ar]] = linkDep;
- } else {
+ }
+ else
+ {
linkDepA[i] = REOP_NOT_DEPENDENT;
}
- if (nodeWrittenAt[br] > REOP_NOT_DEPENDENT) {
+ if (nodeWrittenAt[br] > REOP_NOT_DEPENDENT)
+ {
linkDepB[i] = nodeWrittenAt[br];
linkDep = &linkDepFreeList[linkDepFrees++];
- linkDep->value = -(i+1);
+ linkDep->value = -(i + 1);
linkDep->next = linkDepListStarts[nodeWrittenAt[br]];
linkDepListStarts[nodeWrittenAt[br]] = linkDep;
- } else {
+ }
+ else
+ {
linkDepB[i] = REOP_NOT_DEPENDENT;
}
-
+
// Add this link to the initial ready list, if it is not dependent on any other links
- if ((linkDepA[i] == REOP_NOT_DEPENDENT) && (linkDepB[i] == REOP_NOT_DEPENDENT)) {
+ if ((linkDepA[i] == REOP_NOT_DEPENDENT) && (linkDepB[i] == REOP_NOT_DEPENDENT))
+ {
readyList[readyListTail++] = i;
- linkDepA[i] = linkDepB[i] = REOP_NODE_COMPLETE; // Probably not needed now
+ linkDepA[i] = linkDepB[i] = REOP_NODE_COMPLETE; // Probably not needed now
}
-
+
// Update the nodes to mark which ones are calculated by this link
nodeWrittenAt[ar] = nodeWrittenAt[br] = i;
}
-
+
// Process the ready list and create the sorted list of links
// -- By treating the ready list as a queue, we maximize the distance between any
// inter-dependent node calculations
// -- All other (non-related) nodes in the ready list will automatically be inserted
// in between each set of inter-dependent link calculations by this loop
i = 0;
- while (readyListHead != readyListTail) {
+ while (readyListHead != readyListTail)
+ {
// Use ready list to select the next link to process
linkNum = readyList[readyListHead++];
// Copy the next-to-calculate link back into the original link array
@@ -616,180 +625,183 @@ void btSoftBodyHelpers::ReoptimizeLinkOrder(btSoftBody *psb /* This can be repla
// Free up any link inputs that are dependent on this one
linkDep = linkDepListStarts[linkNum];
- while (linkDep) {
+ while (linkDep)
+ {
depLink = linkDep->value;
- if (depLink >= 0) {
+ if (depLink >= 0)
+ {
linkDepA[depLink] = REOP_NOT_DEPENDENT;
- } else {
+ }
+ else
+ {
depLink = -depLink - 1;
linkDepB[depLink] = REOP_NOT_DEPENDENT;
}
// Add this dependent link calculation to the ready list if *both* inputs are clear
- if ((linkDepA[depLink] == REOP_NOT_DEPENDENT) && (linkDepB[depLink] == REOP_NOT_DEPENDENT)) {
+ if ((linkDepA[depLink] == REOP_NOT_DEPENDENT) && (linkDepB[depLink] == REOP_NOT_DEPENDENT))
+ {
readyList[readyListTail++] = depLink;
- linkDepA[depLink] = linkDepB[depLink] = REOP_NODE_COMPLETE; // Probably not needed now
+ linkDepA[depLink] = linkDepB[depLink] = REOP_NODE_COMPLETE; // Probably not needed now
}
linkDep = linkDep->next;
}
}
// Delete the temporary buffers
- delete [] nodeWrittenAt;
- delete [] linkDepA;
- delete [] linkDepB;
- delete [] readyList;
- delete [] linkDepFreeList;
- delete [] linkDepListStarts;
- delete [] linkBuffer;
+ delete[] nodeWrittenAt;
+ delete[] linkDepA;
+ delete[] linkDepB;
+ delete[] readyList;
+ delete[] linkDepFreeList;
+ delete[] linkDepListStarts;
+ delete[] linkBuffer;
}
-
//
-void btSoftBodyHelpers::DrawFrame( btSoftBody* psb,
- btIDebugDraw* idraw)
+void btSoftBodyHelpers::DrawFrame(btSoftBody* psb,
+ btIDebugDraw* idraw)
{
- if(psb->m_pose.m_bframe)
+ if (psb->m_pose.m_bframe)
{
- static const btScalar ascl=10;
- static const btScalar nscl=(btScalar)0.1;
- const btVector3 com=psb->m_pose.m_com;
- const btMatrix3x3 trs=psb->m_pose.m_rot*psb->m_pose.m_scl;
- const btVector3 Xaxis=(trs*btVector3(1,0,0)).normalized();
- const btVector3 Yaxis=(trs*btVector3(0,1,0)).normalized();
- const btVector3 Zaxis=(trs*btVector3(0,0,1)).normalized();
- idraw->drawLine(com,com+Xaxis*ascl,btVector3(1,0,0));
- idraw->drawLine(com,com+Yaxis*ascl,btVector3(0,1,0));
- idraw->drawLine(com,com+Zaxis*ascl,btVector3(0,0,1));
- for(int i=0;i<psb->m_pose.m_pos.size();++i)
+ static const btScalar ascl = 10;
+ static const btScalar nscl = (btScalar)0.1;
+ const btVector3 com = psb->m_pose.m_com;
+ const btMatrix3x3 trs = psb->m_pose.m_rot * psb->m_pose.m_scl;
+ const btVector3 Xaxis = (trs * btVector3(1, 0, 0)).normalized();
+ const btVector3 Yaxis = (trs * btVector3(0, 1, 0)).normalized();
+ const btVector3 Zaxis = (trs * btVector3(0, 0, 1)).normalized();
+ idraw->drawLine(com, com + Xaxis * ascl, btVector3(1, 0, 0));
+ idraw->drawLine(com, com + Yaxis * ascl, btVector3(0, 1, 0));
+ idraw->drawLine(com, com + Zaxis * ascl, btVector3(0, 0, 1));
+ for (int i = 0; i < psb->m_pose.m_pos.size(); ++i)
{
- const btVector3 x=com+trs*psb->m_pose.m_pos[i];
- drawVertex(idraw,x,nscl,btVector3(1,0,1));
+ const btVector3 x = com + trs * psb->m_pose.m_pos[i];
+ drawVertex(idraw, x, nscl, btVector3(1, 0, 1));
}
}
}
//
-btSoftBody* btSoftBodyHelpers::CreateRope( btSoftBodyWorldInfo& worldInfo, const btVector3& from,
- const btVector3& to,
- int res,
- int fixeds)
+btSoftBody* btSoftBodyHelpers::CreateRope(btSoftBodyWorldInfo& worldInfo, const btVector3& from,
+ const btVector3& to,
+ int res,
+ int fixeds)
{
- /* Create nodes */
- const int r=res+2;
- btVector3* x=new btVector3[r];
- btScalar* m=new btScalar[r];
+ /* Create nodes */
+ const int r = res + 2;
+ btVector3* x = new btVector3[r];
+ btScalar* m = new btScalar[r];
int i;
- for(i=0;i<r;++i)
+ for (i = 0; i < r; ++i)
{
- const btScalar t=i/(btScalar)(r-1);
- x[i]=lerp(from,to,t);
- m[i]=1;
+ const btScalar t = i / (btScalar)(r - 1);
+ x[i] = lerp(from, to, t);
+ m[i] = 1;
}
- btSoftBody* psb= new btSoftBody(&worldInfo,r,x,m);
- if(fixeds&1) psb->setMass(0,0);
- if(fixeds&2) psb->setMass(r-1,0);
+ btSoftBody* psb = new btSoftBody(&worldInfo, r, x, m);
+ if (fixeds & 1) psb->setMass(0, 0);
+ if (fixeds & 2) psb->setMass(r - 1, 0);
delete[] x;
delete[] m;
- /* Create links */
- for(i=1;i<r;++i)
+ /* Create links */
+ for (i = 1; i < r; ++i)
{
- psb->appendLink(i-1,i);
+ psb->appendLink(i - 1, i);
}
- /* Finished */
- return(psb);
+ /* Finished */
+ return (psb);
}
//
-btSoftBody* btSoftBodyHelpers::CreatePatch(btSoftBodyWorldInfo& worldInfo,const btVector3& corner00,
- const btVector3& corner10,
- const btVector3& corner01,
- const btVector3& corner11,
- int resx,
- int resy,
- int fixeds,
- bool gendiags)
+btSoftBody* btSoftBodyHelpers::CreatePatch(btSoftBodyWorldInfo& worldInfo, const btVector3& corner00,
+ const btVector3& corner10,
+ const btVector3& corner01,
+ const btVector3& corner11,
+ int resx,
+ int resy,
+ int fixeds,
+ bool gendiags)
{
-#define IDX(_x_,_y_) ((_y_)*rx+(_x_))
- /* Create nodes */
- if((resx<2)||(resy<2)) return(0);
- const int rx=resx;
- const int ry=resy;
- const int tot=rx*ry;
- btVector3* x=new btVector3[tot];
- btScalar* m=new btScalar[tot];
+#define IDX(_x_, _y_) ((_y_)*rx + (_x_))
+ /* Create nodes */
+ if ((resx < 2) || (resy < 2)) return (0);
+ const int rx = resx;
+ const int ry = resy;
+ const int tot = rx * ry;
+ btVector3* x = new btVector3[tot];
+ btScalar* m = new btScalar[tot];
int iy;
- for(iy=0;iy<ry;++iy)
+ for (iy = 0; iy < ry; ++iy)
{
- const btScalar ty=iy/(btScalar)(ry-1);
- const btVector3 py0=lerp(corner00,corner01,ty);
- const btVector3 py1=lerp(corner10,corner11,ty);
- for(int ix=0;ix<rx;++ix)
+ const btScalar ty = iy / (btScalar)(ry - 1);
+ const btVector3 py0 = lerp(corner00, corner01, ty);
+ const btVector3 py1 = lerp(corner10, corner11, ty);
+ for (int ix = 0; ix < rx; ++ix)
{
- const btScalar tx=ix/(btScalar)(rx-1);
- x[IDX(ix,iy)]=lerp(py0,py1,tx);
- m[IDX(ix,iy)]=1;
+ const btScalar tx = ix / (btScalar)(rx - 1);
+ x[IDX(ix, iy)] = lerp(py0, py1, tx);
+ m[IDX(ix, iy)] = 1;
}
}
- btSoftBody* psb=new btSoftBody(&worldInfo,tot,x,m);
- if(fixeds&1) psb->setMass(IDX(0,0),0);
- if(fixeds&2) psb->setMass(IDX(rx-1,0),0);
- if(fixeds&4) psb->setMass(IDX(0,ry-1),0);
- if(fixeds&8) psb->setMass(IDX(rx-1,ry-1),0);
+ btSoftBody* psb = new btSoftBody(&worldInfo, tot, x, m);
+ if (fixeds & 1) psb->setMass(IDX(0, 0), 0);
+ if (fixeds & 2) psb->setMass(IDX(rx - 1, 0), 0);
+ if (fixeds & 4) psb->setMass(IDX(0, ry - 1), 0);
+ if (fixeds & 8) psb->setMass(IDX(rx - 1, ry - 1), 0);
delete[] x;
delete[] m;
- /* Create links and faces */
- for(iy=0;iy<ry;++iy)
+ /* Create links and faces */
+ for (iy = 0; iy < ry; ++iy)
{
- for(int ix=0;ix<rx;++ix)
+ for (int ix = 0; ix < rx; ++ix)
{
- const int idx=IDX(ix,iy);
- const bool mdx=(ix+1)<rx;
- const bool mdy=(iy+1)<ry;
- if(mdx) psb->appendLink(idx,IDX(ix+1,iy));
- if(mdy) psb->appendLink(idx,IDX(ix,iy+1));
- if(mdx&&mdy)
+ const int idx = IDX(ix, iy);
+ const bool mdx = (ix + 1) < rx;
+ const bool mdy = (iy + 1) < ry;
+ if (mdx) psb->appendLink(idx, IDX(ix + 1, iy));
+ if (mdy) psb->appendLink(idx, IDX(ix, iy + 1));
+ if (mdx && mdy)
{
- if((ix+iy)&1)
+ if ((ix + iy) & 1)
{
- psb->appendFace(IDX(ix,iy),IDX(ix+1,iy),IDX(ix+1,iy+1));
- psb->appendFace(IDX(ix,iy),IDX(ix+1,iy+1),IDX(ix,iy+1));
- if(gendiags)
+ psb->appendFace(IDX(ix, iy), IDX(ix + 1, iy), IDX(ix + 1, iy + 1));
+ psb->appendFace(IDX(ix, iy), IDX(ix + 1, iy + 1), IDX(ix, iy + 1));
+ if (gendiags)
{
- psb->appendLink(IDX(ix,iy),IDX(ix+1,iy+1));
+ psb->appendLink(IDX(ix, iy), IDX(ix + 1, iy + 1));
}
}
else
{
- psb->appendFace(IDX(ix,iy+1),IDX(ix,iy),IDX(ix+1,iy));
- psb->appendFace(IDX(ix,iy+1),IDX(ix+1,iy),IDX(ix+1,iy+1));
- if(gendiags)
+ psb->appendFace(IDX(ix, iy + 1), IDX(ix, iy), IDX(ix + 1, iy));
+ psb->appendFace(IDX(ix, iy + 1), IDX(ix + 1, iy), IDX(ix + 1, iy + 1));
+ if (gendiags)
{
- psb->appendLink(IDX(ix+1,iy),IDX(ix,iy+1));
+ psb->appendLink(IDX(ix + 1, iy), IDX(ix, iy + 1));
}
}
}
}
}
- /* Finished */
+ /* Finished */
#undef IDX
- return(psb);
+ return (psb);
}
//
-btSoftBody* btSoftBodyHelpers::CreatePatchUV(btSoftBodyWorldInfo& worldInfo,
- const btVector3& corner00,
- const btVector3& corner10,
- const btVector3& corner01,
- const btVector3& corner11,
- int resx,
- int resy,
- int fixeds,
- bool gendiags,
- float* tex_coords)
+btSoftBody* btSoftBodyHelpers::CreatePatchUV(btSoftBodyWorldInfo& worldInfo,
+ const btVector3& corner00,
+ const btVector3& corner10,
+ const btVector3& corner01,
+ const btVector3& corner11,
+ int resx,
+ int resy,
+ int fixeds,
+ bool gendiags,
+ float* tex_coords)
{
-
/*
*
* corners:
@@ -857,92 +869,92 @@ btSoftBody* btSoftBodyHelpers::CreatePatchUV(btSoftBodyWorldInfo& worldInfo,
*
*/
-#define IDX(_x_,_y_) ((_y_)*rx+(_x_))
- /* Create nodes */
- if((resx<2)||(resy<2)) return(0);
- const int rx=resx;
- const int ry=resy;
- const int tot=rx*ry;
- btVector3* x=new btVector3[tot];
- btScalar* m=new btScalar[tot];
+#define IDX(_x_, _y_) ((_y_)*rx + (_x_))
+ /* Create nodes */
+ if ((resx < 2) || (resy < 2)) return (0);
+ const int rx = resx;
+ const int ry = resy;
+ const int tot = rx * ry;
+ btVector3* x = new btVector3[tot];
+ btScalar* m = new btScalar[tot];
int iy;
- for(iy=0;iy<ry;++iy)
+ for (iy = 0; iy < ry; ++iy)
{
- const btScalar ty=iy/(btScalar)(ry-1);
- const btVector3 py0=lerp(corner00,corner01,ty);
- const btVector3 py1=lerp(corner10,corner11,ty);
- for(int ix=0;ix<rx;++ix)
+ const btScalar ty = iy / (btScalar)(ry - 1);
+ const btVector3 py0 = lerp(corner00, corner01, ty);
+ const btVector3 py1 = lerp(corner10, corner11, ty);
+ for (int ix = 0; ix < rx; ++ix)
{
- const btScalar tx=ix/(btScalar)(rx-1);
- x[IDX(ix,iy)]=lerp(py0,py1,tx);
- m[IDX(ix,iy)]=1;
+ const btScalar tx = ix / (btScalar)(rx - 1);
+ x[IDX(ix, iy)] = lerp(py0, py1, tx);
+ m[IDX(ix, iy)] = 1;
}
}
- btSoftBody* psb=new btSoftBody(&worldInfo,tot,x,m);
- if(fixeds&1) psb->setMass(IDX(0,0),0);
- if(fixeds&2) psb->setMass(IDX(rx-1,0),0);
- if(fixeds&4) psb->setMass(IDX(0,ry-1),0);
- if(fixeds&8) psb->setMass(IDX(rx-1,ry-1),0);
- if(fixeds&16) psb->setMass(IDX((rx-1)/2,0),0);
- if(fixeds&32) psb->setMass(IDX(0,(ry-1)/2),0);
- if(fixeds&64) psb->setMass(IDX(rx-1,(ry-1)/2),0);
- if(fixeds&128) psb->setMass(IDX((rx-1)/2,ry-1),0);
- if(fixeds&256) psb->setMass(IDX((rx-1)/2,(ry-1)/2),0);
+ btSoftBody* psb = new btSoftBody(&worldInfo, tot, x, m);
+ if (fixeds & 1) psb->setMass(IDX(0, 0), 0);
+ if (fixeds & 2) psb->setMass(IDX(rx - 1, 0), 0);
+ if (fixeds & 4) psb->setMass(IDX(0, ry - 1), 0);
+ if (fixeds & 8) psb->setMass(IDX(rx - 1, ry - 1), 0);
+ if (fixeds & 16) psb->setMass(IDX((rx - 1) / 2, 0), 0);
+ if (fixeds & 32) psb->setMass(IDX(0, (ry - 1) / 2), 0);
+ if (fixeds & 64) psb->setMass(IDX(rx - 1, (ry - 1) / 2), 0);
+ if (fixeds & 128) psb->setMass(IDX((rx - 1) / 2, ry - 1), 0);
+ if (fixeds & 256) psb->setMass(IDX((rx - 1) / 2, (ry - 1) / 2), 0);
delete[] x;
delete[] m;
-
int z = 0;
- /* Create links and faces */
- for(iy=0;iy<ry;++iy)
+ /* Create links and faces */
+ for (iy = 0; iy < ry; ++iy)
{
- for(int ix=0;ix<rx;++ix)
+ for (int ix = 0; ix < rx; ++ix)
{
- const bool mdx=(ix+1)<rx;
- const bool mdy=(iy+1)<ry;
+ const bool mdx = (ix + 1) < rx;
+ const bool mdy = (iy + 1) < ry;
- int node00=IDX(ix,iy);
- int node01=IDX(ix+1,iy);
- int node10=IDX(ix,iy+1);
- int node11=IDX(ix+1,iy+1);
+ int node00 = IDX(ix, iy);
+ int node01 = IDX(ix + 1, iy);
+ int node10 = IDX(ix, iy + 1);
+ int node11 = IDX(ix + 1, iy + 1);
- if(mdx) psb->appendLink(node00,node01);
- if(mdy) psb->appendLink(node00,node10);
- if(mdx&&mdy)
+ if (mdx) psb->appendLink(node00, node01);
+ if (mdy) psb->appendLink(node00, node10);
+ if (mdx && mdy)
{
- psb->appendFace(node00,node10,node11);
- if (tex_coords) {
- tex_coords[z+0]=CalculateUV(resx,resy,ix,iy,0);
- tex_coords[z+1]=CalculateUV(resx,resy,ix,iy,1);
- tex_coords[z+2]=CalculateUV(resx,resy,ix,iy,0);
- tex_coords[z+3]=CalculateUV(resx,resy,ix,iy,2);
- tex_coords[z+4]=CalculateUV(resx,resy,ix,iy,3);
- tex_coords[z+5]=CalculateUV(resx,resy,ix,iy,2);
+ psb->appendFace(node00, node10, node11);
+ if (tex_coords)
+ {
+ tex_coords[z + 0] = CalculateUV(resx, resy, ix, iy, 0);
+ tex_coords[z + 1] = CalculateUV(resx, resy, ix, iy, 1);
+ tex_coords[z + 2] = CalculateUV(resx, resy, ix, iy, 0);
+ tex_coords[z + 3] = CalculateUV(resx, resy, ix, iy, 2);
+ tex_coords[z + 4] = CalculateUV(resx, resy, ix, iy, 3);
+ tex_coords[z + 5] = CalculateUV(resx, resy, ix, iy, 2);
}
- psb->appendFace(node11,node01,node00);
- if (tex_coords) {
- tex_coords[z+6 ]=CalculateUV(resx,resy,ix,iy,3);
- tex_coords[z+7 ]=CalculateUV(resx,resy,ix,iy,2);
- tex_coords[z+8 ]=CalculateUV(resx,resy,ix,iy,3);
- tex_coords[z+9 ]=CalculateUV(resx,resy,ix,iy,1);
- tex_coords[z+10]=CalculateUV(resx,resy,ix,iy,0);
- tex_coords[z+11]=CalculateUV(resx,resy,ix,iy,1);
+ psb->appendFace(node11, node01, node00);
+ if (tex_coords)
+ {
+ tex_coords[z + 6] = CalculateUV(resx, resy, ix, iy, 3);
+ tex_coords[z + 7] = CalculateUV(resx, resy, ix, iy, 2);
+ tex_coords[z + 8] = CalculateUV(resx, resy, ix, iy, 3);
+ tex_coords[z + 9] = CalculateUV(resx, resy, ix, iy, 1);
+ tex_coords[z + 10] = CalculateUV(resx, resy, ix, iy, 0);
+ tex_coords[z + 11] = CalculateUV(resx, resy, ix, iy, 1);
}
- if (gendiags) psb->appendLink(node00,node11);
+ if (gendiags) psb->appendLink(node00, node11);
z += 12;
}
}
}
- /* Finished */
+ /* Finished */
#undef IDX
- return(psb);
+ return (psb);
}
-float btSoftBodyHelpers::CalculateUV(int resx,int resy,int ix,int iy,int id)
+float btSoftBodyHelpers::CalculateUV(int resx, int resy, int ix, int iy, int id)
{
-
/*
*
*
@@ -968,90 +980,93 @@ float btSoftBodyHelpers::CalculateUV(int resx,int resy,int ix,int iy,int id)
*
*/
- float tc=0.0f;
- if (id == 0) {
- tc = (1.0f/((resx-1))*ix);
+ float tc = 0.0f;
+ if (id == 0)
+ {
+ tc = (1.0f / ((resx - 1)) * ix);
}
- else if (id==1) {
- tc = (1.0f/((resy-1))*(resy-1-iy));
+ else if (id == 1)
+ {
+ tc = (1.0f / ((resy - 1)) * (resy - 1 - iy));
}
- else if (id==2) {
- tc = (1.0f/((resy-1))*(resy-1-iy-1));
+ else if (id == 2)
+ {
+ tc = (1.0f / ((resy - 1)) * (resy - 1 - iy - 1));
}
- else if (id==3) {
- tc = (1.0f/((resx-1))*(ix+1));
+ else if (id == 3)
+ {
+ tc = (1.0f / ((resx - 1)) * (ix + 1));
}
return tc;
}
//
-btSoftBody* btSoftBodyHelpers::CreateEllipsoid(btSoftBodyWorldInfo& worldInfo,const btVector3& center,
- const btVector3& radius,
- int res)
+btSoftBody* btSoftBodyHelpers::CreateEllipsoid(btSoftBodyWorldInfo& worldInfo, const btVector3& center,
+ const btVector3& radius,
+ int res)
{
- struct Hammersley
+ struct Hammersley
{
- static void Generate(btVector3* x,int n)
+ static void Generate(btVector3* x, int n)
{
- for(int i=0;i<n;i++)
+ for (int i = 0; i < n; i++)
{
- btScalar p=0.5,t=0;
- for(int j=i;j;p*=0.5,j>>=1) if(j&1) t+=p;
- btScalar w=2*t-1;
- btScalar a=(SIMD_PI+2*i*SIMD_PI)/n;
- btScalar s=btSqrt(1-w*w);
- *x++=btVector3(s*btCos(a),s*btSin(a),w);
+ btScalar p = 0.5, t = 0;
+ for (int j = i; j; p *= 0.5, j >>= 1)
+ if (j & 1) t += p;
+ btScalar w = 2 * t - 1;
+ btScalar a = (SIMD_PI + 2 * i * SIMD_PI) / n;
+ btScalar s = btSqrt(1 - w * w);
+ *x++ = btVector3(s * btCos(a), s * btSin(a), w);
}
}
};
- btAlignedObjectArray<btVector3> vtx;
- vtx.resize(3+res);
- Hammersley::Generate(&vtx[0],vtx.size());
- for(int i=0;i<vtx.size();++i)
+ btAlignedObjectArray<btVector3> vtx;
+ vtx.resize(3 + res);
+ Hammersley::Generate(&vtx[0], vtx.size());
+ for (int i = 0; i < vtx.size(); ++i)
{
- vtx[i]=vtx[i]*radius+center;
+ vtx[i] = vtx[i] * radius + center;
}
- return(CreateFromConvexHull(worldInfo,&vtx[0],vtx.size()));
+ return (CreateFromConvexHull(worldInfo, &vtx[0], vtx.size()));
}
-
-
//
-btSoftBody* btSoftBodyHelpers::CreateFromTriMesh(btSoftBodyWorldInfo& worldInfo,const btScalar* vertices,
- const int* triangles,
- int ntriangles, bool randomizeConstraints)
+btSoftBody* btSoftBodyHelpers::CreateFromTriMesh(btSoftBodyWorldInfo& worldInfo, const btScalar* vertices,
+ const int* triangles,
+ int ntriangles, bool randomizeConstraints)
{
- int maxidx=0;
- int i,j,ni;
+ int maxidx = 0;
+ int i, j, ni;
- for(i=0,ni=ntriangles*3;i<ni;++i)
+ for (i = 0, ni = ntriangles * 3; i < ni; ++i)
{
- maxidx=btMax(triangles[i],maxidx);
+ maxidx = btMax(triangles[i], maxidx);
}
++maxidx;
- btAlignedObjectArray<bool> chks;
- btAlignedObjectArray<btVector3> vtx;
- chks.resize(maxidx*maxidx,false);
+ btAlignedObjectArray<bool> chks;
+ btAlignedObjectArray<btVector3> vtx;
+ chks.resize(maxidx * maxidx, false);
vtx.resize(maxidx);
- for(i=0,j=0,ni=maxidx*3;i<ni;++j,i+=3)
+ for (i = 0, j = 0, ni = maxidx * 3; i < ni; ++j, i += 3)
{
- vtx[j]=btVector3(vertices[i],vertices[i+1],vertices[i+2]);
+ vtx[j] = btVector3(vertices[i], vertices[i + 1], vertices[i + 2]);
}
- btSoftBody* psb=new btSoftBody(&worldInfo,vtx.size(),&vtx[0],0);
- for( i=0,ni=ntriangles*3;i<ni;i+=3)
+ btSoftBody* psb = new btSoftBody(&worldInfo, vtx.size(), &vtx[0], 0);
+ for (i = 0, ni = ntriangles * 3; i < ni; i += 3)
{
- const int idx[]={triangles[i],triangles[i+1],triangles[i+2]};
-#define IDX(_x_,_y_) ((_y_)*maxidx+(_x_))
- for(int j=2,k=0;k<3;j=k++)
+ const int idx[] = {triangles[i], triangles[i + 1], triangles[i + 2]};
+#define IDX(_x_, _y_) ((_y_)*maxidx + (_x_))
+ for (int j = 2, k = 0; k < 3; j = k++)
{
- if(!chks[IDX(idx[j],idx[k])])
+ if (!chks[IDX(idx[j], idx[k])])
{
- chks[IDX(idx[j],idx[k])]=true;
- chks[IDX(idx[k],idx[j])]=true;
- psb->appendLink(idx[j],idx[k]);
+ chks[IDX(idx[j], idx[k])] = true;
+ chks[IDX(idx[k], idx[j])] = true;
+ psb->appendLink(idx[j], idx[k]);
}
}
#undef IDX
- psb->appendFace(idx[0],idx[1],idx[2]);
+ psb->appendFace(idx[0], idx[1], idx[2]);
}
if (randomizeConstraints)
@@ -1059,44 +1074,41 @@ btSoftBody* btSoftBodyHelpers::CreateFromTriMesh(btSoftBodyWorldInfo& worldInfo
psb->randomizeConstraints();
}
- return(psb);
+ return (psb);
}
//
-btSoftBody* btSoftBodyHelpers::CreateFromConvexHull(btSoftBodyWorldInfo& worldInfo, const btVector3* vertices,
- int nvertices, bool randomizeConstraints)
+btSoftBody* btSoftBodyHelpers::CreateFromConvexHull(btSoftBodyWorldInfo& worldInfo, const btVector3* vertices,
+ int nvertices, bool randomizeConstraints)
{
- HullDesc hdsc(QF_TRIANGLES,nvertices,vertices);
- HullResult hres;
- HullLibrary hlib;/*??*/
- hdsc.mMaxVertices=nvertices;
- hlib.CreateConvexHull(hdsc,hres);
- btSoftBody* psb=new btSoftBody(&worldInfo,(int)hres.mNumOutputVertices,
- &hres.m_OutputVertices[0],0);
- for(int i=0;i<(int)hres.mNumFaces;++i)
+ HullDesc hdsc(QF_TRIANGLES, nvertices, vertices);
+ HullResult hres;
+ HullLibrary hlib; /*??*/
+ hdsc.mMaxVertices = nvertices;
+ hlib.CreateConvexHull(hdsc, hres);
+ btSoftBody* psb = new btSoftBody(&worldInfo, (int)hres.mNumOutputVertices,
+ &hres.m_OutputVertices[0], 0);
+ for (int i = 0; i < (int)hres.mNumFaces; ++i)
{
- const int idx[]={ static_cast<int>(hres.m_Indices[i*3+0]),
- static_cast<int>(hres.m_Indices[i*3+1]),
- static_cast<int>(hres.m_Indices[i*3+2])};
- if(idx[0]<idx[1]) psb->appendLink( idx[0],idx[1]);
- if(idx[1]<idx[2]) psb->appendLink( idx[1],idx[2]);
- if(idx[2]<idx[0]) psb->appendLink( idx[2],idx[0]);
- psb->appendFace(idx[0],idx[1],idx[2]);
+ const int idx[] = {static_cast<int>(hres.m_Indices[i * 3 + 0]),
+ static_cast<int>(hres.m_Indices[i * 3 + 1]),
+ static_cast<int>(hres.m_Indices[i * 3 + 2])};
+ if (idx[0] < idx[1]) psb->appendLink(idx[0], idx[1]);
+ if (idx[1] < idx[2]) psb->appendLink(idx[1], idx[2]);
+ if (idx[2] < idx[0]) psb->appendLink(idx[2], idx[0]);
+ psb->appendFace(idx[0], idx[1], idx[2]);
}
hlib.ReleaseResult(hres);
if (randomizeConstraints)
{
psb->randomizeConstraints();
}
- return(psb);
+ return (psb);
}
-
-
-
static int nextLine(const char* buffer)
{
- int numBytesRead=0;
+ int numBytesRead = 0;
while (*buffer != '\n')
{
@@ -1104,8 +1116,7 @@ static int nextLine(const char* buffer)
numBytesRead++;
}
-
- if (buffer[0]==0x0a)
+ if (buffer[0] == 0x0a)
{
buffer++;
numBytesRead++;
@@ -1113,8 +1124,8 @@ static int nextLine(const char* buffer)
return numBytesRead;
}
-/* Create from TetGen .ele, .face, .node data */
-btSoftBody* btSoftBodyHelpers::CreateFromTetGenData(btSoftBodyWorldInfo& worldInfo,
+/* Create from TetGen .ele, .face, .node data */
+btSoftBody* btSoftBodyHelpers::CreateFromTetGenData(btSoftBodyWorldInfo& worldInfo,
const char* ele,
const char* face,
const char* node,
@@ -1122,38 +1133,38 @@ btSoftBody* btSoftBodyHelpers::CreateFromTetGenData(btSoftBodyWorldInfo& worldIn
bool btetralinks,
bool bfacesfromtetras)
{
-btAlignedObjectArray<btVector3> pos;
-int nnode=0;
-int ndims=0;
-int nattrb=0;
-int hasbounds=0;
-int result = sscanf(node,"%d %d %d %d",&nnode,&ndims,&nattrb,&hasbounds);
-result = sscanf(node,"%d %d %d %d",&nnode,&ndims,&nattrb,&hasbounds);
-node += nextLine(node);
-
-pos.resize(nnode);
-for(int i=0;i<pos.size();++i)
+ btAlignedObjectArray<btVector3> pos;
+ int nnode = 0;
+ int ndims = 0;
+ int nattrb = 0;
+ int hasbounds = 0;
+ int result = sscanf(node, "%d %d %d %d", &nnode, &ndims, &nattrb, &hasbounds);
+ result = sscanf(node, "%d %d %d %d", &nnode, &ndims, &nattrb, &hasbounds);
+ node += nextLine(node);
+
+ pos.resize(nnode);
+ for (int i = 0; i < pos.size(); ++i)
{
- int index=0;
- //int bound=0;
- float x,y,z;
- sscanf(node,"%d %f %f %f",&index,&x,&y,&z);
+ int index = 0;
+ //int bound=0;
+ float x, y, z;
+ sscanf(node, "%d %f %f %f", &index, &x, &y, &z);
-// sn>>index;
-// sn>>x;sn>>y;sn>>z;
- node += nextLine(node);
+ // sn>>index;
+ // sn>>x;sn>>y;sn>>z;
+ node += nextLine(node);
- //for(int j=0;j<nattrb;++j)
- // sn>>a;
+ //for(int j=0;j<nattrb;++j)
+ // sn>>a;
- //if(hasbounds)
- // sn>>bound;
+ //if(hasbounds)
+ // sn>>bound;
- pos[index].setX(btScalar(x));
- pos[index].setY(btScalar(y));
- pos[index].setZ(btScalar(z));
+ pos[index].setX(btScalar(x));
+ pos[index].setY(btScalar(y));
+ pos[index].setZ(btScalar(z));
}
-btSoftBody* psb=new btSoftBody(&worldInfo,nnode,&pos[0],0);
+ btSoftBody* psb = new btSoftBody(&worldInfo, nnode, &pos[0], 0);
#if 0
if(face&&face[0])
{
@@ -1178,42 +1189,41 @@ if(face&&face[0])
}
#endif
-if(ele&&ele[0])
+ if (ele && ele[0])
{
- int ntetra=0;
- int ncorner=0;
- int neattrb=0;
- sscanf(ele,"%d %d %d",&ntetra,&ncorner,&neattrb);
- ele += nextLine(ele);
-
- //se>>ntetra;se>>ncorner;se>>neattrb;
- for(int i=0;i<ntetra;++i)
+ int ntetra = 0;
+ int ncorner = 0;
+ int neattrb = 0;
+ sscanf(ele, "%d %d %d", &ntetra, &ncorner, &neattrb);
+ ele += nextLine(ele);
+
+ //se>>ntetra;se>>ncorner;se>>neattrb;
+ for (int i = 0; i < ntetra; ++i)
{
- int index=0;
- int ni[4];
-
- //se>>index;
- //se>>ni[0];se>>ni[1];se>>ni[2];se>>ni[3];
- sscanf(ele,"%d %d %d %d %d",&index,&ni[0],&ni[1],&ni[2],&ni[3]);
- ele+=nextLine(ele);
- //for(int j=0;j<neattrb;++j)
- // se>>a;
- psb->appendTetra(ni[0],ni[1],ni[2],ni[3]);
- if(btetralinks)
+ int index = 0;
+ int ni[4];
+
+ //se>>index;
+ //se>>ni[0];se>>ni[1];se>>ni[2];se>>ni[3];
+ sscanf(ele, "%d %d %d %d %d", &index, &ni[0], &ni[1], &ni[2], &ni[3]);
+ ele += nextLine(ele);
+ //for(int j=0;j<neattrb;++j)
+ // se>>a;
+ psb->appendTetra(ni[0], ni[1], ni[2], ni[3]);
+ if (btetralinks)
{
- psb->appendLink(ni[0],ni[1],0,true);
- psb->appendLink(ni[1],ni[2],0,true);
- psb->appendLink(ni[2],ni[0],0,true);
- psb->appendLink(ni[0],ni[3],0,true);
- psb->appendLink(ni[1],ni[3],0,true);
- psb->appendLink(ni[2],ni[3],0,true);
+ psb->appendLink(ni[0], ni[1], 0, true);
+ psb->appendLink(ni[1], ni[2], 0, true);
+ psb->appendLink(ni[2], ni[0], 0, true);
+ psb->appendLink(ni[0], ni[3], 0, true);
+ psb->appendLink(ni[1], ni[3], 0, true);
+ psb->appendLink(ni[2], ni[3], 0, true);
}
}
}
-printf("Nodes: %u\r\n",psb->m_nodes.size());
-printf("Links: %u\r\n",psb->m_links.size());
-printf("Faces: %u\r\n",psb->m_faces.size());
-printf("Tetras: %u\r\n",psb->m_tetras.size());
-return(psb);
+ printf("Nodes: %u\r\n", psb->m_nodes.size());
+ printf("Links: %u\r\n", psb->m_links.size());
+ printf("Faces: %u\r\n", psb->m_faces.size());
+ printf("Tetras: %u\r\n", psb->m_tetras.size());
+ return (psb);
}
-
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.h b/thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.h
index 7271530109..e433558c18 100644
--- a/thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.h
+++ b/thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.h
@@ -22,127 +22,130 @@ subject to the following restrictions:
// Helpers
//
-/* fDrawFlags */
-struct fDrawFlags { enum _ {
- Nodes = 0x0001,
- Links = 0x0002,
- Faces = 0x0004,
- Tetras = 0x0008,
- Normals = 0x0010,
- Contacts = 0x0020,
- Anchors = 0x0040,
- Notes = 0x0080,
- Clusters = 0x0100,
- NodeTree = 0x0200,
- FaceTree = 0x0400,
- ClusterTree = 0x0800,
- Joints = 0x1000,
- /* presets */
- Std = Links+Faces+Tetras+Anchors+Notes+Joints,
- StdTetra = Std-Faces+Tetras
-};};
-
-struct btSoftBodyHelpers
+/* fDrawFlags */
+struct fDrawFlags
{
- /* Draw body */
- static void Draw( btSoftBody* psb,
- btIDebugDraw* idraw,
- int drawflags=fDrawFlags::Std);
- /* Draw body infos */
- static void DrawInfos( btSoftBody* psb,
- btIDebugDraw* idraw,
- bool masses,
- bool areas,
- bool stress);
- /* Draw node tree */
- static void DrawNodeTree( btSoftBody* psb,
- btIDebugDraw* idraw,
- int mindepth=0,
- int maxdepth=-1);
- /* Draw face tree */
- static void DrawFaceTree( btSoftBody* psb,
- btIDebugDraw* idraw,
- int mindepth=0,
- int maxdepth=-1);
- /* Draw cluster tree */
- static void DrawClusterTree(btSoftBody* psb,
- btIDebugDraw* idraw,
- int mindepth=0,
- int maxdepth=-1);
- /* Draw rigid frame */
- static void DrawFrame( btSoftBody* psb,
- btIDebugDraw* idraw);
- /* Create a rope */
- static btSoftBody* CreateRope( btSoftBodyWorldInfo& worldInfo,
- const btVector3& from,
- const btVector3& to,
- int res,
- int fixeds);
- /* Create a patch */
- static btSoftBody* CreatePatch(btSoftBodyWorldInfo& worldInfo,
- const btVector3& corner00,
- const btVector3& corner10,
- const btVector3& corner01,
- const btVector3& corner11,
- int resx,
- int resy,
- int fixeds,
- bool gendiags);
- /* Create a patch with UV Texture Coordinates */
- static btSoftBody* CreatePatchUV(btSoftBodyWorldInfo& worldInfo,
- const btVector3& corner00,
- const btVector3& corner10,
- const btVector3& corner01,
- const btVector3& corner11,
- int resx,
- int resy,
- int fixeds,
- bool gendiags,
- float* tex_coords=0);
- static float CalculateUV(int resx,int resy,int ix,int iy,int id);
- /* Create an ellipsoid */
- static btSoftBody* CreateEllipsoid(btSoftBodyWorldInfo& worldInfo,
- const btVector3& center,
- const btVector3& radius,
- int res);
- /* Create from trimesh */
- static btSoftBody* CreateFromTriMesh( btSoftBodyWorldInfo& worldInfo,
- const btScalar* vertices,
- const int* triangles,
- int ntriangles,
- bool randomizeConstraints = true);
- /* Create from convex-hull */
- static btSoftBody* CreateFromConvexHull( btSoftBodyWorldInfo& worldInfo,
- const btVector3* vertices,
- int nvertices,
- bool randomizeConstraints = true);
+ enum _
+ {
+ Nodes = 0x0001,
+ Links = 0x0002,
+ Faces = 0x0004,
+ Tetras = 0x0008,
+ Normals = 0x0010,
+ Contacts = 0x0020,
+ Anchors = 0x0040,
+ Notes = 0x0080,
+ Clusters = 0x0100,
+ NodeTree = 0x0200,
+ FaceTree = 0x0400,
+ ClusterTree = 0x0800,
+ Joints = 0x1000,
+ /* presets */
+ Std = Links + Faces + Tetras + Anchors + Notes + Joints,
+ StdTetra = Std - Faces + Tetras
+ };
+};
+struct btSoftBodyHelpers
+{
+ /* Draw body */
+ static void Draw(btSoftBody* psb,
+ btIDebugDraw* idraw,
+ int drawflags = fDrawFlags::Std);
+ /* Draw body infos */
+ static void DrawInfos(btSoftBody* psb,
+ btIDebugDraw* idraw,
+ bool masses,
+ bool areas,
+ bool stress);
+ /* Draw node tree */
+ static void DrawNodeTree(btSoftBody* psb,
+ btIDebugDraw* idraw,
+ int mindepth = 0,
+ int maxdepth = -1);
+ /* Draw face tree */
+ static void DrawFaceTree(btSoftBody* psb,
+ btIDebugDraw* idraw,
+ int mindepth = 0,
+ int maxdepth = -1);
+ /* Draw cluster tree */
+ static void DrawClusterTree(btSoftBody* psb,
+ btIDebugDraw* idraw,
+ int mindepth = 0,
+ int maxdepth = -1);
+ /* Draw rigid frame */
+ static void DrawFrame(btSoftBody* psb,
+ btIDebugDraw* idraw);
+ /* Create a rope */
+ static btSoftBody* CreateRope(btSoftBodyWorldInfo& worldInfo,
+ const btVector3& from,
+ const btVector3& to,
+ int res,
+ int fixeds);
+ /* Create a patch */
+ static btSoftBody* CreatePatch(btSoftBodyWorldInfo& worldInfo,
+ const btVector3& corner00,
+ const btVector3& corner10,
+ const btVector3& corner01,
+ const btVector3& corner11,
+ int resx,
+ int resy,
+ int fixeds,
+ bool gendiags);
+ /* Create a patch with UV Texture Coordinates */
+ static btSoftBody* CreatePatchUV(btSoftBodyWorldInfo& worldInfo,
+ const btVector3& corner00,
+ const btVector3& corner10,
+ const btVector3& corner01,
+ const btVector3& corner11,
+ int resx,
+ int resy,
+ int fixeds,
+ bool gendiags,
+ float* tex_coords = 0);
+ static float CalculateUV(int resx, int resy, int ix, int iy, int id);
+ /* Create an ellipsoid */
+ static btSoftBody* CreateEllipsoid(btSoftBodyWorldInfo& worldInfo,
+ const btVector3& center,
+ const btVector3& radius,
+ int res);
+ /* Create from trimesh */
+ static btSoftBody* CreateFromTriMesh(btSoftBodyWorldInfo& worldInfo,
+ const btScalar* vertices,
+ const int* triangles,
+ int ntriangles,
+ bool randomizeConstraints = true);
+ /* Create from convex-hull */
+ static btSoftBody* CreateFromConvexHull(btSoftBodyWorldInfo& worldInfo,
+ const btVector3* vertices,
+ int nvertices,
+ bool randomizeConstraints = true);
- /* Export TetGen compatible .smesh file */
-// static void ExportAsSMeshFile( btSoftBody* psb,
-// const char* filename);
- /* Create from TetGen .ele, .face, .node files */
-// static btSoftBody* CreateFromTetGenFile( btSoftBodyWorldInfo& worldInfo,
-// const char* ele,
-// const char* face,
-// const char* node,
-// bool bfacelinks,
-// bool btetralinks,
-// bool bfacesfromtetras);
- /* Create from TetGen .ele, .face, .node data */
- static btSoftBody* CreateFromTetGenData( btSoftBodyWorldInfo& worldInfo,
- const char* ele,
- const char* face,
- const char* node,
- bool bfacelinks,
- bool btetralinks,
- bool bfacesfromtetras);
+ /* Export TetGen compatible .smesh file */
+ // static void ExportAsSMeshFile( btSoftBody* psb,
+ // const char* filename);
+ /* Create from TetGen .ele, .face, .node files */
+ // static btSoftBody* CreateFromTetGenFile( btSoftBodyWorldInfo& worldInfo,
+ // const char* ele,
+ // const char* face,
+ // const char* node,
+ // bool bfacelinks,
+ // bool btetralinks,
+ // bool bfacesfromtetras);
+ /* Create from TetGen .ele, .face, .node data */
+ static btSoftBody* CreateFromTetGenData(btSoftBodyWorldInfo& worldInfo,
+ const char* ele,
+ const char* face,
+ const char* node,
+ bool bfacelinks,
+ bool btetralinks,
+ bool bfacesfromtetras);
/// Sort the list of links to move link calculations that are dependent upon earlier
/// ones as far as possible away from the calculation of those values
/// This tends to make adjacent loop iterations not dependent upon one another,
/// so out-of-order processors can execute instructions from multiple iterations at once
- static void ReoptimizeLinkOrder(btSoftBody *psb );
+ static void ReoptimizeLinkOrder(btSoftBody* psb);
};
-#endif //BT_SOFT_BODY_HELPERS_H
+#endif //BT_SOFT_BODY_HELPERS_H
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftBodyInternals.h b/thirdparty/bullet/BulletSoftBody/btSoftBodyInternals.h
index 1ad82616ea..7efe514f38 100644
--- a/thirdparty/bullet/BulletSoftBody/btSoftBodyInternals.h
+++ b/thirdparty/bullet/BulletSoftBody/btSoftBodyInternals.h
@@ -19,29 +19,37 @@ subject to the following restrictions:
#include "btSoftBody.h"
-
#include "LinearMath/btQuickprof.h"
#include "LinearMath/btPolarDecomposition.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "BulletCollision/CollisionShapes/btConvexInternalShape.h"
#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
-#include <string.h> //for memset
+#include <string.h> //for memset
//
// btSymMatrix
//
template <typename T>
struct btSymMatrix
{
- btSymMatrix() : dim(0) {}
- btSymMatrix(int n,const T& init=T()) { resize(n,init); }
- void resize(int n,const T& init=T()) { dim=n;store.resize((n*(n+1))/2,init); }
- int index(int c,int r) const { if(c>r) btSwap(c,r);btAssert(r<dim);return((r*(r+1))/2+c); }
- T& operator()(int c,int r) { return(store[index(c,r)]); }
- const T& operator()(int c,int r) const { return(store[index(c,r)]); }
- btAlignedObjectArray<T> store;
- int dim;
-};
+ btSymMatrix() : dim(0) {}
+ btSymMatrix(int n, const T& init = T()) { resize(n, init); }
+ void resize(int n, const T& init = T())
+ {
+ dim = n;
+ store.resize((n * (n + 1)) / 2, init);
+ }
+ int index(int c, int r) const
+ {
+ if (c > r) btSwap(c, r);
+ btAssert(r < dim);
+ return ((r * (r + 1)) / 2 + c);
+ }
+ T& operator()(int c, int r) { return (store[index(c, r)]); }
+ const T& operator()(int c, int r) const { return (store[index(c, r)]); }
+ btAlignedObjectArray<T> store;
+ int dim;
+};
//
// btSoftBodyCollisionShape
@@ -49,67 +57,64 @@ struct btSymMatrix
class btSoftBodyCollisionShape : public btConcaveShape
{
public:
- btSoftBody* m_body;
+ btSoftBody* m_body;
btSoftBodyCollisionShape(btSoftBody* backptr)
{
m_shapeType = SOFTBODY_SHAPE_PROXYTYPE;
- m_body=backptr;
+ m_body = backptr;
}
virtual ~btSoftBodyCollisionShape()
{
-
}
- void processAllTriangles(btTriangleCallback* /*callback*/,const btVector3& /*aabbMin*/,const btVector3& /*aabbMax*/) const
+ void processAllTriangles(btTriangleCallback* /*callback*/, const btVector3& /*aabbMin*/, const btVector3& /*aabbMax*/) const
{
//not yet
btAssert(0);
}
///getAabb returns the axis aligned bounding box in the coordinate frame of the given transform t.
- virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+ virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
{
/* t is usually identity, except when colliding against btCompoundShape. See Issue 512 */
- const btVector3 mins=m_body->m_bounds[0];
- const btVector3 maxs=m_body->m_bounds[1];
- const btVector3 crns[]={t*btVector3(mins.x(),mins.y(),mins.z()),
- t*btVector3(maxs.x(),mins.y(),mins.z()),
- t*btVector3(maxs.x(),maxs.y(),mins.z()),
- t*btVector3(mins.x(),maxs.y(),mins.z()),
- t*btVector3(mins.x(),mins.y(),maxs.z()),
- t*btVector3(maxs.x(),mins.y(),maxs.z()),
- t*btVector3(maxs.x(),maxs.y(),maxs.z()),
- t*btVector3(mins.x(),maxs.y(),maxs.z())};
- aabbMin=aabbMax=crns[0];
- for(int i=1;i<8;++i)
+ const btVector3 mins = m_body->m_bounds[0];
+ const btVector3 maxs = m_body->m_bounds[1];
+ const btVector3 crns[] = {t * btVector3(mins.x(), mins.y(), mins.z()),
+ t * btVector3(maxs.x(), mins.y(), mins.z()),
+ t * btVector3(maxs.x(), maxs.y(), mins.z()),
+ t * btVector3(mins.x(), maxs.y(), mins.z()),
+ t * btVector3(mins.x(), mins.y(), maxs.z()),
+ t * btVector3(maxs.x(), mins.y(), maxs.z()),
+ t * btVector3(maxs.x(), maxs.y(), maxs.z()),
+ t * btVector3(mins.x(), maxs.y(), maxs.z())};
+ aabbMin = aabbMax = crns[0];
+ for (int i = 1; i < 8; ++i)
{
aabbMin.setMin(crns[i]);
aabbMax.setMax(crns[i]);
}
}
-
- virtual void setLocalScaling(const btVector3& /*scaling*/)
- {
+ virtual void setLocalScaling(const btVector3& /*scaling*/)
+ {
///na
}
virtual const btVector3& getLocalScaling() const
{
- static const btVector3 dummy(1,1,1);
+ static const btVector3 dummy(1, 1, 1);
return dummy;
}
- virtual void calculateLocalInertia(btScalar /*mass*/,btVector3& /*inertia*/) const
+ virtual void calculateLocalInertia(btScalar /*mass*/, btVector3& /*inertia*/) const
{
///not yet
btAssert(0);
}
- virtual const char* getName()const
+ virtual const char* getName() const
{
return "SoftBody";
}
-
};
//
@@ -118,48 +123,53 @@ public:
class btSoftClusterCollisionShape : public btConvexInternalShape
{
public:
- const btSoftBody::Cluster* m_cluster;
+ const btSoftBody::Cluster* m_cluster;
- btSoftClusterCollisionShape (const btSoftBody::Cluster* cluster) : m_cluster(cluster) { setMargin(0); }
+ btSoftClusterCollisionShape(const btSoftBody::Cluster* cluster) : m_cluster(cluster) { setMargin(0); }
-
- virtual btVector3 localGetSupportingVertex(const btVector3& vec) const
+ virtual btVector3 localGetSupportingVertex(const btVector3& vec) const
{
- btSoftBody::Node* const * n=&m_cluster->m_nodes[0];
- btScalar d=btDot(vec,n[0]->m_x);
- int j=0;
- for(int i=1,ni=m_cluster->m_nodes.size();i<ni;++i)
+ btSoftBody::Node* const* n = &m_cluster->m_nodes[0];
+ btScalar d = btDot(vec, n[0]->m_x);
+ int j = 0;
+ for (int i = 1, ni = m_cluster->m_nodes.size(); i < ni; ++i)
{
- const btScalar k=btDot(vec,n[i]->m_x);
- if(k>d) { d=k;j=i; }
+ const btScalar k = btDot(vec, n[i]->m_x);
+ if (k > d)
+ {
+ d = k;
+ j = i;
+ }
}
- return(n[j]->m_x);
+ return (n[j]->m_x);
}
- virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const
{
- return(localGetSupportingVertex(vec));
+ return (localGetSupportingVertex(vec));
}
//notice that the vectors should be unit length
- virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
- {}
-
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
+ {
+ }
- virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const
- {}
+ virtual void calculateLocalInertia(btScalar mass, btVector3& inertia) const
+ {
+ }
- virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
- {}
+ virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
+ {
+ }
- virtual int getShapeType() const { return SOFTBODY_SHAPE_PROXYTYPE; }
+ virtual int getShapeType() const { return SOFTBODY_SHAPE_PROXYTYPE; }
//debugging
- virtual const char* getName()const {return "SOFTCLUSTER";}
+ virtual const char* getName() const { return "SOFTCLUSTER"; }
- virtual void setMargin(btScalar margin)
+ virtual void setMargin(btScalar margin)
{
btConvexInternalShape::setMargin(margin);
}
- virtual btScalar getMargin() const
+ virtual btScalar getMargin() const
{
return btConvexInternalShape::getMargin();
}
@@ -171,229 +181,247 @@ public:
//
template <typename T>
-static inline void ZeroInitialize(T& value)
+static inline void ZeroInitialize(T& value)
{
- memset(&value,0,sizeof(T));
+ memset(&value, 0, sizeof(T));
}
//
template <typename T>
-static inline bool CompLess(const T& a,const T& b)
-{ return(a<b); }
+static inline bool CompLess(const T& a, const T& b)
+{
+ return (a < b);
+}
//
template <typename T>
-static inline bool CompGreater(const T& a,const T& b)
-{ return(a>b); }
+static inline bool CompGreater(const T& a, const T& b)
+{
+ return (a > b);
+}
//
template <typename T>
-static inline T Lerp(const T& a,const T& b,btScalar t)
-{ return(a+(b-a)*t); }
+static inline T Lerp(const T& a, const T& b, btScalar t)
+{
+ return (a + (b - a) * t);
+}
//
template <typename T>
-static inline T InvLerp(const T& a,const T& b,btScalar t)
-{ return((b+a*t-b*t)/(a*b)); }
+static inline T InvLerp(const T& a, const T& b, btScalar t)
+{
+ return ((b + a * t - b * t) / (a * b));
+}
//
-static inline btMatrix3x3 Lerp( const btMatrix3x3& a,
- const btMatrix3x3& b,
- btScalar t)
+static inline btMatrix3x3 Lerp(const btMatrix3x3& a,
+ const btMatrix3x3& b,
+ btScalar t)
{
- btMatrix3x3 r;
- r[0]=Lerp(a[0],b[0],t);
- r[1]=Lerp(a[1],b[1],t);
- r[2]=Lerp(a[2],b[2],t);
- return(r);
+ btMatrix3x3 r;
+ r[0] = Lerp(a[0], b[0], t);
+ r[1] = Lerp(a[1], b[1], t);
+ r[2] = Lerp(a[2], b[2], t);
+ return (r);
}
//
-static inline btVector3 Clamp(const btVector3& v,btScalar maxlength)
+static inline btVector3 Clamp(const btVector3& v, btScalar maxlength)
{
- const btScalar sql=v.length2();
- if(sql>(maxlength*maxlength))
- return((v*maxlength)/btSqrt(sql));
+ const btScalar sql = v.length2();
+ if (sql > (maxlength * maxlength))
+ return ((v * maxlength) / btSqrt(sql));
else
- return(v);
+ return (v);
}
//
template <typename T>
-static inline T Clamp(const T& x,const T& l,const T& h)
-{ return(x<l?l:x>h?h:x); }
+static inline T Clamp(const T& x, const T& l, const T& h)
+{
+ return (x < l ? l : x > h ? h : x);
+}
//
template <typename T>
-static inline T Sq(const T& x)
-{ return(x*x); }
+static inline T Sq(const T& x)
+{
+ return (x * x);
+}
//
template <typename T>
-static inline T Cube(const T& x)
-{ return(x*x*x); }
+static inline T Cube(const T& x)
+{
+ return (x * x * x);
+}
//
template <typename T>
-static inline T Sign(const T& x)
-{ return((T)(x<0?-1:+1)); }
+static inline T Sign(const T& x)
+{
+ return ((T)(x < 0 ? -1 : +1));
+}
//
template <typename T>
-static inline bool SameSign(const T& x,const T& y)
-{ return((x*y)>0); }
-//
-static inline btScalar ClusterMetric(const btVector3& x,const btVector3& y)
+static inline bool SameSign(const T& x, const T& y)
{
- const btVector3 d=x-y;
- return(btFabs(d[0])+btFabs(d[1])+btFabs(d[2]));
+ return ((x * y) > 0);
}
//
-static inline btMatrix3x3 ScaleAlongAxis(const btVector3& a,btScalar s)
+static inline btScalar ClusterMetric(const btVector3& x, const btVector3& y)
{
- const btScalar xx=a.x()*a.x();
- const btScalar yy=a.y()*a.y();
- const btScalar zz=a.z()*a.z();
- const btScalar xy=a.x()*a.y();
- const btScalar yz=a.y()*a.z();
- const btScalar zx=a.z()*a.x();
- btMatrix3x3 m;
- m[0]=btVector3(1-xx+xx*s,xy*s-xy,zx*s-zx);
- m[1]=btVector3(xy*s-xy,1-yy+yy*s,yz*s-yz);
- m[2]=btVector3(zx*s-zx,yz*s-yz,1-zz+zz*s);
- return(m);
+ const btVector3 d = x - y;
+ return (btFabs(d[0]) + btFabs(d[1]) + btFabs(d[2]));
+}
+//
+static inline btMatrix3x3 ScaleAlongAxis(const btVector3& a, btScalar s)
+{
+ const btScalar xx = a.x() * a.x();
+ const btScalar yy = a.y() * a.y();
+ const btScalar zz = a.z() * a.z();
+ const btScalar xy = a.x() * a.y();
+ const btScalar yz = a.y() * a.z();
+ const btScalar zx = a.z() * a.x();
+ btMatrix3x3 m;
+ m[0] = btVector3(1 - xx + xx * s, xy * s - xy, zx * s - zx);
+ m[1] = btVector3(xy * s - xy, 1 - yy + yy * s, yz * s - yz);
+ m[2] = btVector3(zx * s - zx, yz * s - yz, 1 - zz + zz * s);
+ return (m);
}
//
-static inline btMatrix3x3 Cross(const btVector3& v)
+static inline btMatrix3x3 Cross(const btVector3& v)
{
- btMatrix3x3 m;
- m[0]=btVector3(0,-v.z(),+v.y());
- m[1]=btVector3(+v.z(),0,-v.x());
- m[2]=btVector3(-v.y(),+v.x(),0);
- return(m);
+ btMatrix3x3 m;
+ m[0] = btVector3(0, -v.z(), +v.y());
+ m[1] = btVector3(+v.z(), 0, -v.x());
+ m[2] = btVector3(-v.y(), +v.x(), 0);
+ return (m);
}
//
-static inline btMatrix3x3 Diagonal(btScalar x)
+static inline btMatrix3x3 Diagonal(btScalar x)
{
- btMatrix3x3 m;
- m[0]=btVector3(x,0,0);
- m[1]=btVector3(0,x,0);
- m[2]=btVector3(0,0,x);
- return(m);
+ btMatrix3x3 m;
+ m[0] = btVector3(x, 0, 0);
+ m[1] = btVector3(0, x, 0);
+ m[2] = btVector3(0, 0, x);
+ return (m);
}
//
-static inline btMatrix3x3 Add(const btMatrix3x3& a,
- const btMatrix3x3& b)
+static inline btMatrix3x3 Add(const btMatrix3x3& a,
+ const btMatrix3x3& b)
{
- btMatrix3x3 r;
- for(int i=0;i<3;++i) r[i]=a[i]+b[i];
- return(r);
+ btMatrix3x3 r;
+ for (int i = 0; i < 3; ++i) r[i] = a[i] + b[i];
+ return (r);
}
//
-static inline btMatrix3x3 Sub(const btMatrix3x3& a,
- const btMatrix3x3& b)
+static inline btMatrix3x3 Sub(const btMatrix3x3& a,
+ const btMatrix3x3& b)
{
- btMatrix3x3 r;
- for(int i=0;i<3;++i) r[i]=a[i]-b[i];
- return(r);
+ btMatrix3x3 r;
+ for (int i = 0; i < 3; ++i) r[i] = a[i] - b[i];
+ return (r);
}
//
-static inline btMatrix3x3 Mul(const btMatrix3x3& a,
- btScalar b)
+static inline btMatrix3x3 Mul(const btMatrix3x3& a,
+ btScalar b)
{
- btMatrix3x3 r;
- for(int i=0;i<3;++i) r[i]=a[i]*b;
- return(r);
+ btMatrix3x3 r;
+ for (int i = 0; i < 3; ++i) r[i] = a[i] * b;
+ return (r);
}
//
-static inline void Orthogonalize(btMatrix3x3& m)
+static inline void Orthogonalize(btMatrix3x3& m)
{
- m[2]=btCross(m[0],m[1]).normalized();
- m[1]=btCross(m[2],m[0]).normalized();
- m[0]=btCross(m[1],m[2]).normalized();
+ m[2] = btCross(m[0], m[1]).normalized();
+ m[1] = btCross(m[2], m[0]).normalized();
+ m[0] = btCross(m[1], m[2]).normalized();
}
//
-static inline btMatrix3x3 MassMatrix(btScalar im,const btMatrix3x3& iwi,const btVector3& r)
+static inline btMatrix3x3 MassMatrix(btScalar im, const btMatrix3x3& iwi, const btVector3& r)
{
- const btMatrix3x3 cr=Cross(r);
- return(Sub(Diagonal(im),cr*iwi*cr));
+ const btMatrix3x3 cr = Cross(r);
+ return (Sub(Diagonal(im), cr * iwi * cr));
}
//
-static inline btMatrix3x3 ImpulseMatrix( btScalar dt,
- btScalar ima,
- btScalar imb,
- const btMatrix3x3& iwi,
- const btVector3& r)
+static inline btMatrix3x3 ImpulseMatrix(btScalar dt,
+ btScalar ima,
+ btScalar imb,
+ const btMatrix3x3& iwi,
+ const btVector3& r)
{
- return(Diagonal(1/dt)*Add(Diagonal(ima),MassMatrix(imb,iwi,r)).inverse());
+ return (Diagonal(1 / dt) * Add(Diagonal(ima), MassMatrix(imb, iwi, r)).inverse());
}
//
-static inline btMatrix3x3 ImpulseMatrix( btScalar ima,const btMatrix3x3& iia,const btVector3& ra,
- btScalar imb,const btMatrix3x3& iib,const btVector3& rb)
+static inline btMatrix3x3 ImpulseMatrix(btScalar ima, const btMatrix3x3& iia, const btVector3& ra,
+ btScalar imb, const btMatrix3x3& iib, const btVector3& rb)
{
- return(Add(MassMatrix(ima,iia,ra),MassMatrix(imb,iib,rb)).inverse());
+ return (Add(MassMatrix(ima, iia, ra), MassMatrix(imb, iib, rb)).inverse());
}
//
-static inline btMatrix3x3 AngularImpulseMatrix( const btMatrix3x3& iia,
- const btMatrix3x3& iib)
+static inline btMatrix3x3 AngularImpulseMatrix(const btMatrix3x3& iia,
+ const btMatrix3x3& iib)
{
- return(Add(iia,iib).inverse());
+ return (Add(iia, iib).inverse());
}
//
-static inline btVector3 ProjectOnAxis( const btVector3& v,
- const btVector3& a)
+static inline btVector3 ProjectOnAxis(const btVector3& v,
+ const btVector3& a)
{
- return(a*btDot(v,a));
+ return (a * btDot(v, a));
}
//
-static inline btVector3 ProjectOnPlane( const btVector3& v,
- const btVector3& a)
+static inline btVector3 ProjectOnPlane(const btVector3& v,
+ const btVector3& a)
{
- return(v-ProjectOnAxis(v,a));
+ return (v - ProjectOnAxis(v, a));
}
//
-static inline void ProjectOrigin( const btVector3& a,
- const btVector3& b,
- btVector3& prj,
- btScalar& sqd)
+static inline void ProjectOrigin(const btVector3& a,
+ const btVector3& b,
+ btVector3& prj,
+ btScalar& sqd)
{
- const btVector3 d=b-a;
- const btScalar m2=d.length2();
- if(m2>SIMD_EPSILON)
- {
- const btScalar t=Clamp<btScalar>(-btDot(a,d)/m2,0,1);
- const btVector3 p=a+d*t;
- const btScalar l2=p.length2();
- if(l2<sqd)
+ const btVector3 d = b - a;
+ const btScalar m2 = d.length2();
+ if (m2 > SIMD_EPSILON)
+ {
+ const btScalar t = Clamp<btScalar>(-btDot(a, d) / m2, 0, 1);
+ const btVector3 p = a + d * t;
+ const btScalar l2 = p.length2();
+ if (l2 < sqd)
{
- prj=p;
- sqd=l2;
+ prj = p;
+ sqd = l2;
}
}
}
//
-static inline void ProjectOrigin( const btVector3& a,
- const btVector3& b,
- const btVector3& c,
- btVector3& prj,
- btScalar& sqd)
+static inline void ProjectOrigin(const btVector3& a,
+ const btVector3& b,
+ const btVector3& c,
+ btVector3& prj,
+ btScalar& sqd)
{
- const btVector3& q=btCross(b-a,c-a);
- const btScalar m2=q.length2();
- if(m2>SIMD_EPSILON)
+ const btVector3& q = btCross(b - a, c - a);
+ const btScalar m2 = q.length2();
+ if (m2 > SIMD_EPSILON)
{
- const btVector3 n=q/btSqrt(m2);
- const btScalar k=btDot(a,n);
- const btScalar k2=k*k;
- if(k2<sqd)
+ const btVector3 n = q / btSqrt(m2);
+ const btScalar k = btDot(a, n);
+ const btScalar k2 = k * k;
+ if (k2 < sqd)
{
- const btVector3 p=n*k;
- if( (btDot(btCross(a-p,b-p),q)>0)&&
- (btDot(btCross(b-p,c-p),q)>0)&&
- (btDot(btCross(c-p,a-p),q)>0))
- {
- prj=p;
- sqd=k2;
+ const btVector3 p = n * k;
+ if ((btDot(btCross(a - p, b - p), q) > 0) &&
+ (btDot(btCross(b - p, c - p), q) > 0) &&
+ (btDot(btCross(c - p, a - p), q) > 0))
+ {
+ prj = p;
+ sqd = k2;
}
else
{
- ProjectOrigin(a,b,prj,sqd);
- ProjectOrigin(b,c,prj,sqd);
- ProjectOrigin(c,a,prj,sqd);
+ ProjectOrigin(a, b, prj, sqd);
+ ProjectOrigin(b, c, prj, sqd);
+ ProjectOrigin(c, a, prj, sqd);
}
}
}
@@ -401,155 +429,159 @@ static inline void ProjectOrigin( const btVector3& a,
//
template <typename T>
-static inline T BaryEval( const T& a,
- const T& b,
- const T& c,
- const btVector3& coord)
+static inline T BaryEval(const T& a,
+ const T& b,
+ const T& c,
+ const btVector3& coord)
{
- return(a*coord.x()+b*coord.y()+c*coord.z());
+ return (a * coord.x() + b * coord.y() + c * coord.z());
}
//
-static inline btVector3 BaryCoord( const btVector3& a,
- const btVector3& b,
- const btVector3& c,
- const btVector3& p)
+static inline btVector3 BaryCoord(const btVector3& a,
+ const btVector3& b,
+ const btVector3& c,
+ const btVector3& p)
{
- const btScalar w[]={ btCross(a-p,b-p).length(),
- btCross(b-p,c-p).length(),
- btCross(c-p,a-p).length()};
- const btScalar isum=1/(w[0]+w[1]+w[2]);
- return(btVector3(w[1]*isum,w[2]*isum,w[0]*isum));
+ const btScalar w[] = {btCross(a - p, b - p).length(),
+ btCross(b - p, c - p).length(),
+ btCross(c - p, a - p).length()};
+ const btScalar isum = 1 / (w[0] + w[1] + w[2]);
+ return (btVector3(w[1] * isum, w[2] * isum, w[0] * isum));
}
//
-inline static btScalar ImplicitSolve( btSoftBody::ImplicitFn* fn,
- const btVector3& a,
- const btVector3& b,
- const btScalar accuracy,
- const int maxiterations=256)
+inline static btScalar ImplicitSolve(btSoftBody::ImplicitFn* fn,
+ const btVector3& a,
+ const btVector3& b,
+ const btScalar accuracy,
+ const int maxiterations = 256)
{
- btScalar span[2]={0,1};
- btScalar values[2]={fn->Eval(a),fn->Eval(b)};
- if(values[0]>values[1])
+ btScalar span[2] = {0, 1};
+ btScalar values[2] = {fn->Eval(a), fn->Eval(b)};
+ if (values[0] > values[1])
{
- btSwap(span[0],span[1]);
- btSwap(values[0],values[1]);
+ btSwap(span[0], span[1]);
+ btSwap(values[0], values[1]);
}
- if(values[0]>-accuracy) return(-1);
- if(values[1]<+accuracy) return(-1);
- for(int i=0;i<maxiterations;++i)
+ if (values[0] > -accuracy) return (-1);
+ if (values[1] < +accuracy) return (-1);
+ for (int i = 0; i < maxiterations; ++i)
{
- const btScalar t=Lerp(span[0],span[1],values[0]/(values[0]-values[1]));
- const btScalar v=fn->Eval(Lerp(a,b,t));
- if((t<=0)||(t>=1)) break;
- if(btFabs(v)<accuracy) return(t);
- if(v<0)
- { span[0]=t;values[0]=v; }
+ const btScalar t = Lerp(span[0], span[1], values[0] / (values[0] - values[1]));
+ const btScalar v = fn->Eval(Lerp(a, b, t));
+ if ((t <= 0) || (t >= 1)) break;
+ if (btFabs(v) < accuracy) return (t);
+ if (v < 0)
+ {
+ span[0] = t;
+ values[0] = v;
+ }
else
- { span[1]=t;values[1]=v; }
+ {
+ span[1] = t;
+ values[1] = v;
+ }
}
- return(-1);
+ return (-1);
}
-inline static void EvaluateMedium( const btSoftBodyWorldInfo* wfi,
- const btVector3& x,
- btSoftBody::sMedium& medium)
+inline static void EvaluateMedium(const btSoftBodyWorldInfo* wfi,
+ const btVector3& x,
+ btSoftBody::sMedium& medium)
{
- medium.m_velocity = btVector3(0,0,0);
- medium.m_pressure = 0;
- medium.m_density = wfi->air_density;
- if(wfi->water_density>0)
+ medium.m_velocity = btVector3(0, 0, 0);
+ medium.m_pressure = 0;
+ medium.m_density = wfi->air_density;
+ if (wfi->water_density > 0)
{
- const btScalar depth=-(btDot(x,wfi->water_normal)+wfi->water_offset);
- if(depth>0)
+ const btScalar depth = -(btDot(x, wfi->water_normal) + wfi->water_offset);
+ if (depth > 0)
{
- medium.m_density = wfi->water_density;
- medium.m_pressure = depth*wfi->water_density*wfi->m_gravity.length();
+ medium.m_density = wfi->water_density;
+ medium.m_pressure = depth * wfi->water_density * wfi->m_gravity.length();
}
}
}
-
//
-static inline btVector3 NormalizeAny(const btVector3& v)
+static inline btVector3 NormalizeAny(const btVector3& v)
{
- const btScalar l=v.length();
- if(l>SIMD_EPSILON)
- return(v/l);
+ const btScalar l = v.length();
+ if (l > SIMD_EPSILON)
+ return (v / l);
else
- return(btVector3(0,0,0));
+ return (btVector3(0, 0, 0));
}
//
-static inline btDbvtVolume VolumeOf( const btSoftBody::Face& f,
- btScalar margin)
+static inline btDbvtVolume VolumeOf(const btSoftBody::Face& f,
+ btScalar margin)
{
- const btVector3* pts[]={ &f.m_n[0]->m_x,
- &f.m_n[1]->m_x,
- &f.m_n[2]->m_x};
- btDbvtVolume vol=btDbvtVolume::FromPoints(pts,3);
- vol.Expand(btVector3(margin,margin,margin));
- return(vol);
+ const btVector3* pts[] = {&f.m_n[0]->m_x,
+ &f.m_n[1]->m_x,
+ &f.m_n[2]->m_x};
+ btDbvtVolume vol = btDbvtVolume::FromPoints(pts, 3);
+ vol.Expand(btVector3(margin, margin, margin));
+ return (vol);
}
//
-static inline btVector3 CenterOf( const btSoftBody::Face& f)
+static inline btVector3 CenterOf(const btSoftBody::Face& f)
{
- return((f.m_n[0]->m_x+f.m_n[1]->m_x+f.m_n[2]->m_x)/3);
+ return ((f.m_n[0]->m_x + f.m_n[1]->m_x + f.m_n[2]->m_x) / 3);
}
//
-static inline btScalar AreaOf( const btVector3& x0,
- const btVector3& x1,
- const btVector3& x2)
+static inline btScalar AreaOf(const btVector3& x0,
+ const btVector3& x1,
+ const btVector3& x2)
{
- const btVector3 a=x1-x0;
- const btVector3 b=x2-x0;
- const btVector3 cr=btCross(a,b);
- const btScalar area=cr.length();
- return(area);
+ const btVector3 a = x1 - x0;
+ const btVector3 b = x2 - x0;
+ const btVector3 cr = btCross(a, b);
+ const btScalar area = cr.length();
+ return (area);
}
//
-static inline btScalar VolumeOf( const btVector3& x0,
- const btVector3& x1,
- const btVector3& x2,
- const btVector3& x3)
+static inline btScalar VolumeOf(const btVector3& x0,
+ const btVector3& x1,
+ const btVector3& x2,
+ const btVector3& x3)
{
- const btVector3 a=x1-x0;
- const btVector3 b=x2-x0;
- const btVector3 c=x3-x0;
- return(btDot(a,btCross(b,c)));
+ const btVector3 a = x1 - x0;
+ const btVector3 b = x2 - x0;
+ const btVector3 c = x3 - x0;
+ return (btDot(a, btCross(b, c)));
}
//
-
//
-static inline void ApplyClampedForce( btSoftBody::Node& n,
- const btVector3& f,
- btScalar dt)
+static inline void ApplyClampedForce(btSoftBody::Node& n,
+ const btVector3& f,
+ btScalar dt)
{
- const btScalar dtim=dt*n.m_im;
- if((f*dtim).length2()>n.m_v.length2())
- {/* Clamp */
- n.m_f-=ProjectOnAxis(n.m_v,f.normalized())/dtim;
+ const btScalar dtim = dt * n.m_im;
+ if ((f * dtim).length2() > n.m_v.length2())
+ { /* Clamp */
+ n.m_f -= ProjectOnAxis(n.m_v, f.normalized()) / dtim;
}
else
- {/* Apply */
- n.m_f+=f;
+ { /* Apply */
+ n.m_f += f;
}
}
//
-static inline int MatchEdge( const btSoftBody::Node* a,
- const btSoftBody::Node* b,
- const btSoftBody::Node* ma,
- const btSoftBody::Node* mb)
+static inline int MatchEdge(const btSoftBody::Node* a,
+ const btSoftBody::Node* b,
+ const btSoftBody::Node* ma,
+ const btSoftBody::Node* mb)
{
- if((a==ma)&&(b==mb)) return(0);
- if((a==mb)&&(b==ma)) return(1);
- return(-1);
+ if ((a == ma) && (b == mb)) return (0);
+ if ((a == mb) && (b == ma)) return (1);
+ return (-1);
}
//
@@ -557,58 +589,72 @@ static inline int MatchEdge( const btSoftBody::Node* a,
// straitforward implementation of http://math.fullerton.edu/mathews/n2003/JacobiMethodMod.html
// outputs are NOT sorted.
//
-struct btEigen
+struct btEigen
{
- static int system(btMatrix3x3& a,btMatrix3x3* vectors,btVector3* values=0)
+ static int system(btMatrix3x3& a, btMatrix3x3* vectors, btVector3* values = 0)
{
- static const int maxiterations=16;
- static const btScalar accuracy=(btScalar)0.0001;
- btMatrix3x3& v=*vectors;
- int iterations=0;
+ static const int maxiterations = 16;
+ static const btScalar accuracy = (btScalar)0.0001;
+ btMatrix3x3& v = *vectors;
+ int iterations = 0;
vectors->setIdentity();
- do {
- int p=0,q=1;
- if(btFabs(a[p][q])<btFabs(a[0][2])) { p=0;q=2; }
- if(btFabs(a[p][q])<btFabs(a[1][2])) { p=1;q=2; }
- if(btFabs(a[p][q])>accuracy)
+ do
+ {
+ int p = 0, q = 1;
+ if (btFabs(a[p][q]) < btFabs(a[0][2]))
{
- const btScalar w=(a[q][q]-a[p][p])/(2*a[p][q]);
- const btScalar z=btFabs(w);
- const btScalar t=w/(z*(btSqrt(1+w*w)+z));
- if(t==t)/* [WARNING] let hope that one does not get thrown aways by some compilers... */
+ p = 0;
+ q = 2;
+ }
+ if (btFabs(a[p][q]) < btFabs(a[1][2]))
+ {
+ p = 1;
+ q = 2;
+ }
+ if (btFabs(a[p][q]) > accuracy)
+ {
+ const btScalar w = (a[q][q] - a[p][p]) / (2 * a[p][q]);
+ const btScalar z = btFabs(w);
+ const btScalar t = w / (z * (btSqrt(1 + w * w) + z));
+ if (t == t) /* [WARNING] let hope that one does not get thrown aways by some compilers... */
{
- const btScalar c=1/btSqrt(t*t+1);
- const btScalar s=c*t;
- mulPQ(a,c,s,p,q);
- mulTPQ(a,c,s,p,q);
- mulPQ(v,c,s,p,q);
- } else break;
- } else break;
- } while((++iterations)<maxiterations);
- if(values)
+ const btScalar c = 1 / btSqrt(t * t + 1);
+ const btScalar s = c * t;
+ mulPQ(a, c, s, p, q);
+ mulTPQ(a, c, s, p, q);
+ mulPQ(v, c, s, p, q);
+ }
+ else
+ break;
+ }
+ else
+ break;
+ } while ((++iterations) < maxiterations);
+ if (values)
{
- *values=btVector3(a[0][0],a[1][1],a[2][2]);
+ *values = btVector3(a[0][0], a[1][1], a[2][2]);
}
- return(iterations);
+ return (iterations);
}
+
private:
- static inline void mulTPQ(btMatrix3x3& a,btScalar c,btScalar s,int p,int q)
+ static inline void mulTPQ(btMatrix3x3& a, btScalar c, btScalar s, int p, int q)
{
- const btScalar m[2][3]={ {a[p][0],a[p][1],a[p][2]},
- {a[q][0],a[q][1],a[q][2]}};
+ const btScalar m[2][3] = {{a[p][0], a[p][1], a[p][2]},
+ {a[q][0], a[q][1], a[q][2]}};
int i;
- for(i=0;i<3;++i) a[p][i]=c*m[0][i]-s*m[1][i];
- for(i=0;i<3;++i) a[q][i]=c*m[1][i]+s*m[0][i];
+ for (i = 0; i < 3; ++i) a[p][i] = c * m[0][i] - s * m[1][i];
+ for (i = 0; i < 3; ++i) a[q][i] = c * m[1][i] + s * m[0][i];
}
- static inline void mulPQ(btMatrix3x3& a,btScalar c,btScalar s,int p,int q)
+ static inline void mulPQ(btMatrix3x3& a, btScalar c, btScalar s, int p, int q)
{
- const btScalar m[2][3]={ {a[0][p],a[1][p],a[2][p]},
- {a[0][q],a[1][q],a[2][q]}};
+ const btScalar m[2][3] = {{a[0][p], a[1][p], a[2][p]},
+ {a[0][q], a[1][q], a[2][q]}};
int i;
- for(i=0;i<3;++i) a[i][p]=c*m[0][i]-s*m[1][i];
- for(i=0;i<3;++i) a[i][q]=c*m[1][i]+s*m[0][i];
+ for (i = 0; i < 3; ++i) a[i][p] = c * m[0][i] - s * m[1][i];
+ for (i = 0; i < 3; ++i) a[i][q] = c * m[1][i] + s * m[0][i];
}
};
@@ -616,9 +662,9 @@ private:
// Polar decomposition,
// "Computing the Polar Decomposition with Applications", Nicholas J. Higham, 1986.
//
-static inline int PolarDecompose( const btMatrix3x3& m,btMatrix3x3& q,btMatrix3x3& s)
+static inline int PolarDecompose(const btMatrix3x3& m, btMatrix3x3& q, btMatrix3x3& s)
{
- static const btPolarDecomposition polar;
+ static const btPolarDecomposition polar;
return polar.decompose(m, q, s);
}
@@ -630,282 +676,284 @@ struct btSoftColliders
//
// ClusterBase
//
- struct ClusterBase : btDbvt::ICollide
+ struct ClusterBase : btDbvt::ICollide
{
- btScalar erp;
- btScalar idt;
- btScalar m_margin;
- btScalar friction;
- btScalar threshold;
+ btScalar erp;
+ btScalar idt;
+ btScalar m_margin;
+ btScalar friction;
+ btScalar threshold;
ClusterBase()
{
- erp =(btScalar)1;
- idt =0;
- m_margin =0;
- friction =0;
- threshold =(btScalar)0;
+ erp = (btScalar)1;
+ idt = 0;
+ m_margin = 0;
+ friction = 0;
+ threshold = (btScalar)0;
}
- bool SolveContact( const btGjkEpaSolver2::sResults& res,
- btSoftBody::Body ba,const btSoftBody::Body bb,
- btSoftBody::CJoint& joint)
+ bool SolveContact(const btGjkEpaSolver2::sResults& res,
+ btSoftBody::Body ba, const btSoftBody::Body bb,
+ btSoftBody::CJoint& joint)
{
- if(res.distance<m_margin)
+ if (res.distance < m_margin)
{
btVector3 norm = res.normal;
- norm.normalize();//is it necessary?
-
- const btVector3 ra=res.witnesses[0]-ba.xform().getOrigin();
- const btVector3 rb=res.witnesses[1]-bb.xform().getOrigin();
- const btVector3 va=ba.velocity(ra);
- const btVector3 vb=bb.velocity(rb);
- const btVector3 vrel=va-vb;
- const btScalar rvac=btDot(vrel,norm);
- btScalar depth=res.distance-m_margin;
-
-// printf("depth=%f\n",depth);
- const btVector3 iv=norm*rvac;
- const btVector3 fv=vrel-iv;
- joint.m_bodies[0] = ba;
- joint.m_bodies[1] = bb;
- joint.m_refs[0] = ra*ba.xform().getBasis();
- joint.m_refs[1] = rb*bb.xform().getBasis();
- joint.m_rpos[0] = ra;
- joint.m_rpos[1] = rb;
- joint.m_cfm = 1;
- joint.m_erp = 1;
- joint.m_life = 0;
- joint.m_maxlife = 0;
- joint.m_split = 1;
-
- joint.m_drift = depth*norm;
-
- joint.m_normal = norm;
-// printf("normal=%f,%f,%f\n",res.normal.getX(),res.normal.getY(),res.normal.getZ());
- joint.m_delete = false;
- joint.m_friction = fv.length2()<(rvac*friction*rvac*friction)?1:friction;
- joint.m_massmatrix = ImpulseMatrix( ba.invMass(),ba.invWorldInertia(),joint.m_rpos[0],
- bb.invMass(),bb.invWorldInertia(),joint.m_rpos[1]);
-
- return(true);
+ norm.normalize(); //is it necessary?
+
+ const btVector3 ra = res.witnesses[0] - ba.xform().getOrigin();
+ const btVector3 rb = res.witnesses[1] - bb.xform().getOrigin();
+ const btVector3 va = ba.velocity(ra);
+ const btVector3 vb = bb.velocity(rb);
+ const btVector3 vrel = va - vb;
+ const btScalar rvac = btDot(vrel, norm);
+ btScalar depth = res.distance - m_margin;
+
+ // printf("depth=%f\n",depth);
+ const btVector3 iv = norm * rvac;
+ const btVector3 fv = vrel - iv;
+ joint.m_bodies[0] = ba;
+ joint.m_bodies[1] = bb;
+ joint.m_refs[0] = ra * ba.xform().getBasis();
+ joint.m_refs[1] = rb * bb.xform().getBasis();
+ joint.m_rpos[0] = ra;
+ joint.m_rpos[1] = rb;
+ joint.m_cfm = 1;
+ joint.m_erp = 1;
+ joint.m_life = 0;
+ joint.m_maxlife = 0;
+ joint.m_split = 1;
+
+ joint.m_drift = depth * norm;
+
+ joint.m_normal = norm;
+ // printf("normal=%f,%f,%f\n",res.normal.getX(),res.normal.getY(),res.normal.getZ());
+ joint.m_delete = false;
+ joint.m_friction = fv.length2() < (rvac * friction * rvac * friction) ? 1 : friction;
+ joint.m_massmatrix = ImpulseMatrix(ba.invMass(), ba.invWorldInertia(), joint.m_rpos[0],
+ bb.invMass(), bb.invWorldInertia(), joint.m_rpos[1]);
+
+ return (true);
}
- return(false);
+ return (false);
}
};
//
// CollideCL_RS
//
- struct CollideCL_RS : ClusterBase
+ struct CollideCL_RS : ClusterBase
{
- btSoftBody* psb;
- const btCollisionObjectWrapper* m_colObjWrap;
+ btSoftBody* psb;
+ const btCollisionObjectWrapper* m_colObjWrap;
- void Process(const btDbvtNode* leaf)
+ void Process(const btDbvtNode* leaf)
{
- btSoftBody::Cluster* cluster=(btSoftBody::Cluster*)leaf->data;
- btSoftClusterCollisionShape cshape(cluster);
-
- const btConvexShape* rshape=(const btConvexShape*)m_colObjWrap->getCollisionShape();
+ btSoftBody::Cluster* cluster = (btSoftBody::Cluster*)leaf->data;
+ btSoftClusterCollisionShape cshape(cluster);
+
+ const btConvexShape* rshape = (const btConvexShape*)m_colObjWrap->getCollisionShape();
///don't collide an anchored cluster with a static/kinematic object
- if(m_colObjWrap->getCollisionObject()->isStaticOrKinematicObject() && cluster->m_containsAnchor)
+ if (m_colObjWrap->getCollisionObject()->isStaticOrKinematicObject() && cluster->m_containsAnchor)
return;
- btGjkEpaSolver2::sResults res;
- if(btGjkEpaSolver2::SignedDistance( &cshape,btTransform::getIdentity(),
- rshape,m_colObjWrap->getWorldTransform(),
- btVector3(1,0,0),res))
+ btGjkEpaSolver2::sResults res;
+ if (btGjkEpaSolver2::SignedDistance(&cshape, btTransform::getIdentity(),
+ rshape, m_colObjWrap->getWorldTransform(),
+ btVector3(1, 0, 0), res))
{
- btSoftBody::CJoint joint;
- if(SolveContact(res,cluster,m_colObjWrap->getCollisionObject(),joint))//prb,joint))
+ btSoftBody::CJoint joint;
+ if (SolveContact(res, cluster, m_colObjWrap->getCollisionObject(), joint)) //prb,joint))
{
- btSoftBody::CJoint* pj=new(btAlignedAlloc(sizeof(btSoftBody::CJoint),16)) btSoftBody::CJoint();
- *pj=joint;psb->m_joints.push_back(pj);
- if(m_colObjWrap->getCollisionObject()->isStaticOrKinematicObject())
+ btSoftBody::CJoint* pj = new (btAlignedAlloc(sizeof(btSoftBody::CJoint), 16)) btSoftBody::CJoint();
+ *pj = joint;
+ psb->m_joints.push_back(pj);
+ if (m_colObjWrap->getCollisionObject()->isStaticOrKinematicObject())
{
- pj->m_erp *= psb->m_cfg.kSKHR_CL;
- pj->m_split *= psb->m_cfg.kSK_SPLT_CL;
+ pj->m_erp *= psb->m_cfg.kSKHR_CL;
+ pj->m_split *= psb->m_cfg.kSK_SPLT_CL;
}
else
{
- pj->m_erp *= psb->m_cfg.kSRHR_CL;
- pj->m_split *= psb->m_cfg.kSR_SPLT_CL;
+ pj->m_erp *= psb->m_cfg.kSRHR_CL;
+ pj->m_split *= psb->m_cfg.kSR_SPLT_CL;
}
}
}
}
- void ProcessColObj(btSoftBody* ps,const btCollisionObjectWrapper* colObWrap)
+ void ProcessColObj(btSoftBody* ps, const btCollisionObjectWrapper* colObWrap)
{
- psb = ps;
- m_colObjWrap = colObWrap;
- idt = ps->m_sst.isdt;
- m_margin = m_colObjWrap->getCollisionShape()->getMargin()+psb->getCollisionShape()->getMargin();
+ psb = ps;
+ m_colObjWrap = colObWrap;
+ idt = ps->m_sst.isdt;
+ m_margin = m_colObjWrap->getCollisionShape()->getMargin() + psb->getCollisionShape()->getMargin();
///Bullet rigid body uses multiply instead of minimum to determine combined friction. Some customization would be useful.
- friction = btMin(psb->m_cfg.kDF,m_colObjWrap->getCollisionObject()->getFriction());
- btVector3 mins;
- btVector3 maxs;
-
- ATTRIBUTE_ALIGNED16(btDbvtVolume) volume;
- colObWrap->getCollisionShape()->getAabb(colObWrap->getWorldTransform(),mins,maxs);
- volume=btDbvtVolume::FromMM(mins,maxs);
- volume.Expand(btVector3(1,1,1)*m_margin);
- ps->m_cdbvt.collideTV(ps->m_cdbvt.m_root,volume,*this);
- }
+ friction = btMin(psb->m_cfg.kDF, m_colObjWrap->getCollisionObject()->getFriction());
+ btVector3 mins;
+ btVector3 maxs;
+
+ ATTRIBUTE_ALIGNED16(btDbvtVolume)
+ volume;
+ colObWrap->getCollisionShape()->getAabb(colObWrap->getWorldTransform(), mins, maxs);
+ volume = btDbvtVolume::FromMM(mins, maxs);
+ volume.Expand(btVector3(1, 1, 1) * m_margin);
+ ps->m_cdbvt.collideTV(ps->m_cdbvt.m_root, volume, *this);
+ }
};
//
// CollideCL_SS
//
- struct CollideCL_SS : ClusterBase
+ struct CollideCL_SS : ClusterBase
{
- btSoftBody* bodies[2];
- void Process(const btDbvtNode* la,const btDbvtNode* lb)
+ btSoftBody* bodies[2];
+ void Process(const btDbvtNode* la, const btDbvtNode* lb)
{
- btSoftBody::Cluster* cla=(btSoftBody::Cluster*)la->data;
- btSoftBody::Cluster* clb=(btSoftBody::Cluster*)lb->data;
+ btSoftBody::Cluster* cla = (btSoftBody::Cluster*)la->data;
+ btSoftBody::Cluster* clb = (btSoftBody::Cluster*)lb->data;
-
- bool connected=false;
- if ((bodies[0]==bodies[1])&&(bodies[0]->m_clusterConnectivity.size()))
+ bool connected = false;
+ if ((bodies[0] == bodies[1]) && (bodies[0]->m_clusterConnectivity.size()))
{
- connected = bodies[0]->m_clusterConnectivity[cla->m_clusterIndex+bodies[0]->m_clusters.size()*clb->m_clusterIndex];
+ connected = bodies[0]->m_clusterConnectivity[cla->m_clusterIndex + bodies[0]->m_clusters.size() * clb->m_clusterIndex];
}
if (!connected)
{
- btSoftClusterCollisionShape csa(cla);
- btSoftClusterCollisionShape csb(clb);
- btGjkEpaSolver2::sResults res;
- if(btGjkEpaSolver2::SignedDistance( &csa,btTransform::getIdentity(),
- &csb,btTransform::getIdentity(),
- cla->m_com-clb->m_com,res))
+ btSoftClusterCollisionShape csa(cla);
+ btSoftClusterCollisionShape csb(clb);
+ btGjkEpaSolver2::sResults res;
+ if (btGjkEpaSolver2::SignedDistance(&csa, btTransform::getIdentity(),
+ &csb, btTransform::getIdentity(),
+ cla->m_com - clb->m_com, res))
{
- btSoftBody::CJoint joint;
- if(SolveContact(res,cla,clb,joint))
+ btSoftBody::CJoint joint;
+ if (SolveContact(res, cla, clb, joint))
{
- btSoftBody::CJoint* pj=new(btAlignedAlloc(sizeof(btSoftBody::CJoint),16)) btSoftBody::CJoint();
- *pj=joint;bodies[0]->m_joints.push_back(pj);
- pj->m_erp *= btMax(bodies[0]->m_cfg.kSSHR_CL,bodies[1]->m_cfg.kSSHR_CL);
- pj->m_split *= (bodies[0]->m_cfg.kSS_SPLT_CL+bodies[1]->m_cfg.kSS_SPLT_CL)/2;
+ btSoftBody::CJoint* pj = new (btAlignedAlloc(sizeof(btSoftBody::CJoint), 16)) btSoftBody::CJoint();
+ *pj = joint;
+ bodies[0]->m_joints.push_back(pj);
+ pj->m_erp *= btMax(bodies[0]->m_cfg.kSSHR_CL, bodies[1]->m_cfg.kSSHR_CL);
+ pj->m_split *= (bodies[0]->m_cfg.kSS_SPLT_CL + bodies[1]->m_cfg.kSS_SPLT_CL) / 2;
}
}
- } else
+ }
+ else
{
- static int count=0;
+ static int count = 0;
count++;
//printf("count=%d\n",count);
-
}
}
- void ProcessSoftSoft(btSoftBody* psa,btSoftBody* psb)
+ void ProcessSoftSoft(btSoftBody* psa, btSoftBody* psb)
{
- idt = psa->m_sst.isdt;
+ idt = psa->m_sst.isdt;
//m_margin = (psa->getCollisionShape()->getMargin()+psb->getCollisionShape()->getMargin())/2;
- m_margin = (psa->getCollisionShape()->getMargin()+psb->getCollisionShape()->getMargin());
- friction = btMin(psa->m_cfg.kDF,psb->m_cfg.kDF);
- bodies[0] = psa;
- bodies[1] = psb;
- psa->m_cdbvt.collideTT(psa->m_cdbvt.m_root,psb->m_cdbvt.m_root,*this);
- }
+ m_margin = (psa->getCollisionShape()->getMargin() + psb->getCollisionShape()->getMargin());
+ friction = btMin(psa->m_cfg.kDF, psb->m_cfg.kDF);
+ bodies[0] = psa;
+ bodies[1] = psb;
+ psa->m_cdbvt.collideTT(psa->m_cdbvt.m_root, psb->m_cdbvt.m_root, *this);
+ }
};
//
// CollideSDF_RS
//
- struct CollideSDF_RS : btDbvt::ICollide
+ struct CollideSDF_RS : btDbvt::ICollide
{
- void Process(const btDbvtNode* leaf)
+ void Process(const btDbvtNode* leaf)
{
- btSoftBody::Node* node=(btSoftBody::Node*)leaf->data;
+ btSoftBody::Node* node = (btSoftBody::Node*)leaf->data;
DoNode(*node);
}
- void DoNode(btSoftBody::Node& n) const
+ void DoNode(btSoftBody::Node& n) const
{
- const btScalar m=n.m_im>0?dynmargin:stamargin;
- btSoftBody::RContact c;
+ const btScalar m = n.m_im > 0 ? dynmargin : stamargin;
+ btSoftBody::RContact c;
- if( (!n.m_battach)&&
- psb->checkContact(m_colObj1Wrap,n.m_x,m,c.m_cti))
+ if ((!n.m_battach) &&
+ psb->checkContact(m_colObj1Wrap, n.m_x, m, c.m_cti))
{
- const btScalar ima=n.m_im;
- const btScalar imb= m_rigidBody? m_rigidBody->getInvMass() : 0.f;
- const btScalar ms=ima+imb;
- if(ms>0)
+ const btScalar ima = n.m_im;
+ const btScalar imb = m_rigidBody ? m_rigidBody->getInvMass() : 0.f;
+ const btScalar ms = ima + imb;
+ if (ms > 0)
{
- const btTransform& wtr=m_rigidBody?m_rigidBody->getWorldTransform() : m_colObj1Wrap->getCollisionObject()->getWorldTransform();
- static const btMatrix3x3 iwiStatic(0,0,0,0,0,0,0,0,0);
- const btMatrix3x3& iwi=m_rigidBody?m_rigidBody->getInvInertiaTensorWorld() : iwiStatic;
- const btVector3 ra=n.m_x-wtr.getOrigin();
- const btVector3 va=m_rigidBody ? m_rigidBody->getVelocityInLocalPoint(ra)*psb->m_sst.sdt : btVector3(0,0,0);
- const btVector3 vb=n.m_x-n.m_q;
- const btVector3 vr=vb-va;
- const btScalar dn=btDot(vr,c.m_cti.m_normal);
- const btVector3 fv=vr-c.m_cti.m_normal*dn;
- const btScalar fc=psb->m_cfg.kDF*m_colObj1Wrap->getCollisionObject()->getFriction();
- c.m_node = &n;
- c.m_c0 = ImpulseMatrix(psb->m_sst.sdt,ima,imb,iwi,ra);
- c.m_c1 = ra;
- c.m_c2 = ima*psb->m_sst.sdt;
- c.m_c3 = fv.length2()<(dn*fc*dn*fc)?0:1-fc;
- c.m_c4 = m_colObj1Wrap->getCollisionObject()->isStaticOrKinematicObject()?psb->m_cfg.kKHR:psb->m_cfg.kCHR;
+ const btTransform& wtr = m_rigidBody ? m_rigidBody->getWorldTransform() : m_colObj1Wrap->getCollisionObject()->getWorldTransform();
+ static const btMatrix3x3 iwiStatic(0, 0, 0, 0, 0, 0, 0, 0, 0);
+ const btMatrix3x3& iwi = m_rigidBody ? m_rigidBody->getInvInertiaTensorWorld() : iwiStatic;
+ const btVector3 ra = n.m_x - wtr.getOrigin();
+ const btVector3 va = m_rigidBody ? m_rigidBody->getVelocityInLocalPoint(ra) * psb->m_sst.sdt : btVector3(0, 0, 0);
+ const btVector3 vb = n.m_x - n.m_q;
+ const btVector3 vr = vb - va;
+ const btScalar dn = btDot(vr, c.m_cti.m_normal);
+ const btVector3 fv = vr - c.m_cti.m_normal * dn;
+ const btScalar fc = psb->m_cfg.kDF * m_colObj1Wrap->getCollisionObject()->getFriction();
+ c.m_node = &n;
+ c.m_c0 = ImpulseMatrix(psb->m_sst.sdt, ima, imb, iwi, ra);
+ c.m_c1 = ra;
+ c.m_c2 = ima * psb->m_sst.sdt;
+ c.m_c3 = fv.length2() < (dn * fc * dn * fc) ? 0 : 1 - fc;
+ c.m_c4 = m_colObj1Wrap->getCollisionObject()->isStaticOrKinematicObject() ? psb->m_cfg.kKHR : psb->m_cfg.kCHR;
psb->m_rcontacts.push_back(c);
if (m_rigidBody)
m_rigidBody->activate();
}
}
}
- btSoftBody* psb;
- const btCollisionObjectWrapper* m_colObj1Wrap;
- btRigidBody* m_rigidBody;
- btScalar dynmargin;
- btScalar stamargin;
+ btSoftBody* psb;
+ const btCollisionObjectWrapper* m_colObj1Wrap;
+ btRigidBody* m_rigidBody;
+ btScalar dynmargin;
+ btScalar stamargin;
};
//
// CollideVF_SS
//
- struct CollideVF_SS : btDbvt::ICollide
+ struct CollideVF_SS : btDbvt::ICollide
{
- void Process(const btDbvtNode* lnode,
- const btDbvtNode* lface)
+ void Process(const btDbvtNode* lnode,
+ const btDbvtNode* lface)
{
- btSoftBody::Node* node=(btSoftBody::Node*)lnode->data;
- btSoftBody::Face* face=(btSoftBody::Face*)lface->data;
- btVector3 o=node->m_x;
- btVector3 p;
- btScalar d=SIMD_INFINITY;
- ProjectOrigin( face->m_n[0]->m_x-o,
- face->m_n[1]->m_x-o,
- face->m_n[2]->m_x-o,
- p,d);
- const btScalar m=mrg+(o-node->m_q).length()*2;
- if(d<(m*m))
+ btSoftBody::Node* node = (btSoftBody::Node*)lnode->data;
+ btSoftBody::Face* face = (btSoftBody::Face*)lface->data;
+ btVector3 o = node->m_x;
+ btVector3 p;
+ btScalar d = SIMD_INFINITY;
+ ProjectOrigin(face->m_n[0]->m_x - o,
+ face->m_n[1]->m_x - o,
+ face->m_n[2]->m_x - o,
+ p, d);
+ const btScalar m = mrg + (o - node->m_q).length() * 2;
+ if (d < (m * m))
{
- const btSoftBody::Node* n[]={face->m_n[0],face->m_n[1],face->m_n[2]};
- const btVector3 w=BaryCoord(n[0]->m_x,n[1]->m_x,n[2]->m_x,p+o);
- const btScalar ma=node->m_im;
- btScalar mb=BaryEval(n[0]->m_im,n[1]->m_im,n[2]->m_im,w);
- if( (n[0]->m_im<=0)||
- (n[1]->m_im<=0)||
- (n[2]->m_im<=0))
+ const btSoftBody::Node* n[] = {face->m_n[0], face->m_n[1], face->m_n[2]};
+ const btVector3 w = BaryCoord(n[0]->m_x, n[1]->m_x, n[2]->m_x, p + o);
+ const btScalar ma = node->m_im;
+ btScalar mb = BaryEval(n[0]->m_im, n[1]->m_im, n[2]->m_im, w);
+ if ((n[0]->m_im <= 0) ||
+ (n[1]->m_im <= 0) ||
+ (n[2]->m_im <= 0))
{
- mb=0;
+ mb = 0;
}
- const btScalar ms=ma+mb;
- if(ms>0)
+ const btScalar ms = ma + mb;
+ if (ms > 0)
{
- btSoftBody::SContact c;
- c.m_normal = p/-btSqrt(d);
- c.m_margin = m;
- c.m_node = node;
- c.m_face = face;
- c.m_weights = w;
- c.m_friction = btMax(psb[0]->m_cfg.kDF,psb[1]->m_cfg.kDF);
- c.m_cfm[0] = ma/ms*psb[0]->m_cfg.kSHR;
- c.m_cfm[1] = mb/ms*psb[1]->m_cfg.kSHR;
+ btSoftBody::SContact c;
+ c.m_normal = p / -btSqrt(d);
+ c.m_margin = m;
+ c.m_node = node;
+ c.m_face = face;
+ c.m_weights = w;
+ c.m_friction = btMax(psb[0]->m_cfg.kDF, psb[1]->m_cfg.kDF);
+ c.m_cfm[0] = ma / ms * psb[0]->m_cfg.kSHR;
+ c.m_cfm[1] = mb / ms * psb[1]->m_cfg.kSHR;
psb[0]->m_scontacts.push_back(c);
}
- }
+ }
}
- btSoftBody* psb[2];
- btScalar mrg;
+ btSoftBody* psb[2];
+ btScalar mrg;
};
};
-#endif //_BT_SOFT_BODY_INTERNALS_H
+#endif //_BT_SOFT_BODY_INTERNALS_H
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp b/thirdparty/bullet/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp
index f5a67f6d89..3127369ccd 100644
--- a/thirdparty/bullet/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp
+++ b/thirdparty/bullet/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp
@@ -23,27 +23,27 @@ subject to the following restrictions:
#define ENABLE_SOFTBODY_CONCAVE_COLLISIONS 1
btSoftBodyRigidBodyCollisionConfiguration::btSoftBodyRigidBodyCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo)
-:btDefaultCollisionConfiguration(constructionInfo)
+ : btDefaultCollisionConfiguration(constructionInfo)
{
void* mem;
- mem = btAlignedAlloc(sizeof(btSoftSoftCollisionAlgorithm::CreateFunc),16);
- m_softSoftCreateFunc = new(mem) btSoftSoftCollisionAlgorithm::CreateFunc;
+ mem = btAlignedAlloc(sizeof(btSoftSoftCollisionAlgorithm::CreateFunc), 16);
+ m_softSoftCreateFunc = new (mem) btSoftSoftCollisionAlgorithm::CreateFunc;
- mem = btAlignedAlloc(sizeof(btSoftRigidCollisionAlgorithm::CreateFunc),16);
- m_softRigidConvexCreateFunc = new(mem) btSoftRigidCollisionAlgorithm::CreateFunc;
+ mem = btAlignedAlloc(sizeof(btSoftRigidCollisionAlgorithm::CreateFunc), 16);
+ m_softRigidConvexCreateFunc = new (mem) btSoftRigidCollisionAlgorithm::CreateFunc;
- mem = btAlignedAlloc(sizeof(btSoftRigidCollisionAlgorithm::CreateFunc),16);
- m_swappedSoftRigidConvexCreateFunc = new(mem) btSoftRigidCollisionAlgorithm::CreateFunc;
- m_swappedSoftRigidConvexCreateFunc->m_swapped=true;
+ mem = btAlignedAlloc(sizeof(btSoftRigidCollisionAlgorithm::CreateFunc), 16);
+ m_swappedSoftRigidConvexCreateFunc = new (mem) btSoftRigidCollisionAlgorithm::CreateFunc;
+ m_swappedSoftRigidConvexCreateFunc->m_swapped = true;
#ifdef ENABLE_SOFTBODY_CONCAVE_COLLISIONS
- mem = btAlignedAlloc(sizeof(btSoftBodyConcaveCollisionAlgorithm::CreateFunc),16);
- m_softRigidConcaveCreateFunc = new(mem) btSoftBodyConcaveCollisionAlgorithm::CreateFunc;
+ mem = btAlignedAlloc(sizeof(btSoftBodyConcaveCollisionAlgorithm::CreateFunc), 16);
+ m_softRigidConcaveCreateFunc = new (mem) btSoftBodyConcaveCollisionAlgorithm::CreateFunc;
- mem = btAlignedAlloc(sizeof(btSoftBodyConcaveCollisionAlgorithm::CreateFunc),16);
- m_swappedSoftRigidConcaveCreateFunc = new(mem) btSoftBodyConcaveCollisionAlgorithm::SwappedCreateFunc;
- m_swappedSoftRigidConcaveCreateFunc->m_swapped=true;
+ mem = btAlignedAlloc(sizeof(btSoftBodyConcaveCollisionAlgorithm::CreateFunc), 16);
+ m_swappedSoftRigidConcaveCreateFunc = new (mem) btSoftBodyConcaveCollisionAlgorithm::SwappedCreateFunc;
+ m_swappedSoftRigidConcaveCreateFunc->m_swapped = true;
#endif
//replace pool by a new one, with potential larger size
@@ -53,82 +53,79 @@ btSoftBodyRigidBodyCollisionConfiguration::btSoftBodyRigidBodyCollisionConfigura
int curElemSize = m_collisionAlgorithmPool->getElementSize();
///calculate maximum element size, big enough to fit any collision algorithm in the memory pool
-
int maxSize0 = sizeof(btSoftSoftCollisionAlgorithm);
int maxSize1 = sizeof(btSoftRigidCollisionAlgorithm);
int maxSize2 = sizeof(btSoftBodyConcaveCollisionAlgorithm);
- int collisionAlgorithmMaxElementSize = btMax(maxSize0,maxSize1);
- collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize2);
-
+ int collisionAlgorithmMaxElementSize = btMax(maxSize0, maxSize1);
+ collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize, maxSize2);
+
if (collisionAlgorithmMaxElementSize > curElemSize)
{
m_collisionAlgorithmPool->~btPoolAllocator();
btAlignedFree(m_collisionAlgorithmPool);
- void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16);
- m_collisionAlgorithmPool = new(mem) btPoolAllocator(collisionAlgorithmMaxElementSize,constructionInfo.m_defaultMaxCollisionAlgorithmPoolSize);
+ void* mem = btAlignedAlloc(sizeof(btPoolAllocator), 16);
+ m_collisionAlgorithmPool = new (mem) btPoolAllocator(collisionAlgorithmMaxElementSize, constructionInfo.m_defaultMaxCollisionAlgorithmPoolSize);
}
}
-
}
btSoftBodyRigidBodyCollisionConfiguration::~btSoftBodyRigidBodyCollisionConfiguration()
{
m_softSoftCreateFunc->~btCollisionAlgorithmCreateFunc();
- btAlignedFree( m_softSoftCreateFunc);
+ btAlignedFree(m_softSoftCreateFunc);
m_softRigidConvexCreateFunc->~btCollisionAlgorithmCreateFunc();
- btAlignedFree( m_softRigidConvexCreateFunc);
+ btAlignedFree(m_softRigidConvexCreateFunc);
m_swappedSoftRigidConvexCreateFunc->~btCollisionAlgorithmCreateFunc();
- btAlignedFree( m_swappedSoftRigidConvexCreateFunc);
+ btAlignedFree(m_swappedSoftRigidConvexCreateFunc);
#ifdef ENABLE_SOFTBODY_CONCAVE_COLLISIONS
m_softRigidConcaveCreateFunc->~btCollisionAlgorithmCreateFunc();
- btAlignedFree( m_softRigidConcaveCreateFunc);
+ btAlignedFree(m_softRigidConcaveCreateFunc);
m_swappedSoftRigidConcaveCreateFunc->~btCollisionAlgorithmCreateFunc();
- btAlignedFree( m_swappedSoftRigidConcaveCreateFunc);
+ btAlignedFree(m_swappedSoftRigidConcaveCreateFunc);
#endif
}
///creation of soft-soft and soft-rigid, and otherwise fallback to base class implementation
-btCollisionAlgorithmCreateFunc* btSoftBodyRigidBodyCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1)
+btCollisionAlgorithmCreateFunc* btSoftBodyRigidBodyCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0, int proxyType1)
{
-
///try to handle the softbody interactions first
- if ((proxyType0 == SOFTBODY_SHAPE_PROXYTYPE ) && (proxyType1==SOFTBODY_SHAPE_PROXYTYPE))
+ if ((proxyType0 == SOFTBODY_SHAPE_PROXYTYPE) && (proxyType1 == SOFTBODY_SHAPE_PROXYTYPE))
{
- return m_softSoftCreateFunc;
+ return m_softSoftCreateFunc;
}
///softbody versus convex
- if (proxyType0 == SOFTBODY_SHAPE_PROXYTYPE && btBroadphaseProxy::isConvex(proxyType1))
+ if (proxyType0 == SOFTBODY_SHAPE_PROXYTYPE && btBroadphaseProxy::isConvex(proxyType1))
{
- return m_softRigidConvexCreateFunc;
+ return m_softRigidConvexCreateFunc;
}
///convex versus soft body
- if (btBroadphaseProxy::isConvex(proxyType0) && proxyType1 == SOFTBODY_SHAPE_PROXYTYPE )
+ if (btBroadphaseProxy::isConvex(proxyType0) && proxyType1 == SOFTBODY_SHAPE_PROXYTYPE)
{
- return m_swappedSoftRigidConvexCreateFunc;
+ return m_swappedSoftRigidConvexCreateFunc;
}
#ifdef ENABLE_SOFTBODY_CONCAVE_COLLISIONS
///softbody versus convex
- if (proxyType0 == SOFTBODY_SHAPE_PROXYTYPE && btBroadphaseProxy::isConcave(proxyType1))
+ if (proxyType0 == SOFTBODY_SHAPE_PROXYTYPE && btBroadphaseProxy::isConcave(proxyType1))
{
- return m_softRigidConcaveCreateFunc;
+ return m_softRigidConcaveCreateFunc;
}
///convex versus soft body
- if (btBroadphaseProxy::isConcave(proxyType0) && proxyType1 == SOFTBODY_SHAPE_PROXYTYPE )
+ if (btBroadphaseProxy::isConcave(proxyType0) && proxyType1 == SOFTBODY_SHAPE_PROXYTYPE)
{
- return m_swappedSoftRigidConcaveCreateFunc;
+ return m_swappedSoftRigidConcaveCreateFunc;
}
#endif
///fallback to the regular rigid collision shape
- return btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(proxyType0,proxyType1);
+ return btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(proxyType0, proxyType1);
}
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h b/thirdparty/bullet/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h
index 21addcfe2e..0396a52dac 100644
--- a/thirdparty/bullet/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h
+++ b/thirdparty/bullet/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h
@@ -21,28 +21,23 @@ subject to the following restrictions:
class btVoronoiSimplexSolver;
class btGjkEpaPenetrationDepthSolver;
-
///btSoftBodyRigidBodyCollisionConfiguration add softbody interaction on top of btDefaultCollisionConfiguration
-class btSoftBodyRigidBodyCollisionConfiguration : public btDefaultCollisionConfiguration
+class btSoftBodyRigidBodyCollisionConfiguration : public btDefaultCollisionConfiguration
{
-
//default CreationFunctions, filling the m_doubleDispatch table
- btCollisionAlgorithmCreateFunc* m_softSoftCreateFunc;
- btCollisionAlgorithmCreateFunc* m_softRigidConvexCreateFunc;
- btCollisionAlgorithmCreateFunc* m_swappedSoftRigidConvexCreateFunc;
- btCollisionAlgorithmCreateFunc* m_softRigidConcaveCreateFunc;
- btCollisionAlgorithmCreateFunc* m_swappedSoftRigidConcaveCreateFunc;
+ btCollisionAlgorithmCreateFunc* m_softSoftCreateFunc;
+ btCollisionAlgorithmCreateFunc* m_softRigidConvexCreateFunc;
+ btCollisionAlgorithmCreateFunc* m_swappedSoftRigidConvexCreateFunc;
+ btCollisionAlgorithmCreateFunc* m_softRigidConcaveCreateFunc;
+ btCollisionAlgorithmCreateFunc* m_swappedSoftRigidConcaveCreateFunc;
public:
-
btSoftBodyRigidBodyCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo = btDefaultCollisionConstructionInfo());
virtual ~btSoftBodyRigidBodyCollisionConfiguration();
///creation of soft-soft and soft-rigid, and otherwise fallback to base class implementation
- virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1);
-
+ virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0, int proxyType1);
};
-#endif //BT_SOFTBODY_RIGIDBODY_COLLISION_CONFIGURATION
-
+#endif //BT_SOFTBODY_RIGIDBODY_COLLISION_CONFIGURATION
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftBodySolverVertexBuffer.h b/thirdparty/bullet/BulletSoftBody/btSoftBodySolverVertexBuffer.h
index c4733d6400..bc538db4a2 100644
--- a/thirdparty/bullet/BulletSoftBody/btSoftBodySolverVertexBuffer.h
+++ b/thirdparty/bullet/BulletSoftBody/btSoftBodySolverVertexBuffer.h
@@ -16,7 +16,6 @@ subject to the following restrictions:
#ifndef BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_H
#define BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_H
-
class btVertexBufferDescriptor
{
public:
@@ -27,8 +26,7 @@ public:
OPENGL_BUFFER
};
-protected:
-
+protected:
bool m_hasVertexPositions;
bool m_hasNormals;
@@ -51,7 +49,6 @@ public:
virtual ~btVertexBufferDescriptor()
{
-
}
virtual bool hasVertexPositions() const
@@ -102,7 +99,6 @@ public:
}
};
-
class btCPUVertexBufferDescriptor : public btVertexBufferDescriptor
{
protected:
@@ -114,7 +110,7 @@ public:
* vertexOffset is the offset in floats to the first vertex.
* vertexStride is the stride in floats between vertices.
*/
- btCPUVertexBufferDescriptor( float *basePointer, int vertexOffset, int vertexStride )
+ btCPUVertexBufferDescriptor(float *basePointer, int vertexOffset, int vertexStride)
{
m_basePointer = basePointer;
m_vertexOffset = vertexOffset;
@@ -127,7 +123,7 @@ public:
* vertexOffset is the offset in floats to the first vertex.
* vertexStride is the stride in floats between vertices.
*/
- btCPUVertexBufferDescriptor( float *basePointer, int vertexOffset, int vertexStride, int normalOffset, int normalStride )
+ btCPUVertexBufferDescriptor(float *basePointer, int vertexOffset, int vertexStride, int normalOffset, int normalStride)
{
m_basePointer = basePointer;
@@ -142,7 +138,6 @@ public:
virtual ~btCPUVertexBufferDescriptor()
{
-
}
/**
@@ -162,4 +157,4 @@ public:
}
};
-#endif // #ifndef BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_H
+#endif // #ifndef BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_H
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftBodySolvers.h b/thirdparty/bullet/BulletSoftBody/btSoftBodySolvers.h
index 6947bc27d2..dcf5082650 100644
--- a/thirdparty/bullet/BulletSoftBody/btSoftBodySolvers.h
+++ b/thirdparty/bullet/BulletSoftBody/btSoftBodySolvers.h
@@ -18,7 +18,6 @@ subject to the following restrictions:
#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h"
-
class btSoftBodyTriangleData;
class btSoftBodyLinkData;
class btSoftBodyVertexData;
@@ -26,7 +25,6 @@ class btVertexBufferDescriptor;
class btCollisionObject;
class btSoftBody;
-
class btSoftBodySolver
{
public:
@@ -40,17 +38,15 @@ public:
DX_SIMD_SOLVER
};
-
protected:
int m_numberOfPositionIterations;
int m_numberOfVelocityIterations;
// Simulation timescale
float m_timeScale;
-
+
public:
- btSoftBodySolver() :
- m_numberOfPositionIterations( 10 ),
- m_timeScale( 1 )
+ btSoftBodySolver() : m_numberOfPositionIterations(10),
+ m_timeScale(1)
{
m_numberOfVelocityIterations = 0;
m_numberOfPositionIterations = 5;
@@ -59,39 +55,38 @@ public:
virtual ~btSoftBodySolver()
{
}
-
+
/**
* Return the type of the solver.
*/
virtual SolverTypes getSolverType() const = 0;
-
/** Ensure that this solver is initialized. */
virtual bool checkInitialized() = 0;
/** Optimize soft bodies in this solver. */
- virtual void optimize( btAlignedObjectArray< btSoftBody * > &softBodies , bool forceUpdate=false) = 0;
+ virtual void optimize(btAlignedObjectArray<btSoftBody *> &softBodies, bool forceUpdate = false) = 0;
/** Copy necessary data back to the original soft body source objects. */
virtual void copyBackToSoftBodies(bool bMove = true) = 0;
/** Predict motion of soft bodies into next timestep */
- virtual void predictMotion( float solverdt ) = 0;
+ virtual void predictMotion(float solverdt) = 0;
/** Solve constraints for a set of soft bodies */
- virtual void solveConstraints( float solverdt ) = 0;
+ virtual void solveConstraints(float solverdt) = 0;
/** Perform necessary per-step updates of soft bodies such as recomputing normals and bounding boxes */
virtual void updateSoftBodies() = 0;
/** Process a collision between one of the world's soft bodies and another collision object */
- virtual void processCollision( btSoftBody *, const struct btCollisionObjectWrapper* ) = 0;
+ virtual void processCollision(btSoftBody *, const struct btCollisionObjectWrapper *) = 0;
/** Process a collision between two soft bodies */
- virtual void processCollision( btSoftBody*, btSoftBody* ) = 0;
+ virtual void processCollision(btSoftBody *, btSoftBody *) = 0;
/** Set the number of velocity constraint solver iterations this solver uses. */
- virtual void setNumberOfPositionIterations( int iterations )
+ virtual void setNumberOfPositionIterations(int iterations)
{
m_numberOfPositionIterations = iterations;
}
@@ -103,7 +98,7 @@ public:
}
/** Set the number of velocity constraint solver iterations this solver uses. */
- virtual void setNumberOfVelocityIterations( int iterations )
+ virtual void setNumberOfVelocityIterations(int iterations)
{
m_numberOfVelocityIterations = iterations;
}
@@ -135,7 +130,6 @@ public:
class btSoftBodySolverOutput
{
protected:
-
public:
btSoftBodySolverOutput()
{
@@ -145,10 +139,8 @@ public:
{
}
-
/** Output current computed vertex data to the vertex buffers for all cloths in the solver. */
- virtual void copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer ) = 0;
+ virtual void copySoftBodyToVertexBuffer(const btSoftBody *const softBody, btVertexBufferDescriptor *vertexBuffer) = 0;
};
-
-#endif // #ifndef BT_SOFT_BODY_SOLVERS_H
+#endif // #ifndef BT_SOFT_BODY_SOLVERS_H
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftMultiBodyDynamicsWorld.cpp b/thirdparty/bullet/BulletSoftBody/btSoftMultiBodyDynamicsWorld.cpp
index 6facce4e86..282dbf75f0 100644
--- a/thirdparty/bullet/BulletSoftBody/btSoftMultiBodyDynamicsWorld.cpp
+++ b/thirdparty/bullet/BulletSoftBody/btSoftMultiBodyDynamicsWorld.cpp
@@ -13,7 +13,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#include "btSoftMultiBodyDynamicsWorld.h"
#include "LinearMath/btQuickprof.h"
@@ -24,42 +23,38 @@ subject to the following restrictions:
#include "BulletSoftBody/btDefaultSoftBodySolver.h"
#include "LinearMath/btSerializer.h"
-
btSoftMultiBodyDynamicsWorld::btSoftMultiBodyDynamicsWorld(
btDispatcher* dispatcher,
btBroadphaseInterface* pairCache,
btMultiBodyConstraintSolver* constraintSolver,
btCollisionConfiguration* collisionConfiguration,
- btSoftBodySolver *softBodySolver ) :
- btMultiBodyDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration),
- m_softBodySolver( softBodySolver ),
- m_ownsSolver(false)
+ btSoftBodySolver* softBodySolver) : btMultiBodyDynamicsWorld(dispatcher, pairCache, constraintSolver, collisionConfiguration),
+ m_softBodySolver(softBodySolver),
+ m_ownsSolver(false)
{
- if( !m_softBodySolver )
+ if (!m_softBodySolver)
{
- void* ptr = btAlignedAlloc(sizeof(btDefaultSoftBodySolver),16);
- m_softBodySolver = new(ptr) btDefaultSoftBodySolver();
+ void* ptr = btAlignedAlloc(sizeof(btDefaultSoftBodySolver), 16);
+ m_softBodySolver = new (ptr) btDefaultSoftBodySolver();
m_ownsSolver = true;
}
- m_drawFlags = fDrawFlags::Std;
- m_drawNodeTree = true;
- m_drawFaceTree = false;
- m_drawClusterTree = false;
+ m_drawFlags = fDrawFlags::Std;
+ m_drawNodeTree = true;
+ m_drawFaceTree = false;
+ m_drawClusterTree = false;
m_sbi.m_broadphase = pairCache;
m_sbi.m_dispatcher = dispatcher;
m_sbi.m_sparsesdf.Initialize();
m_sbi.m_sparsesdf.Reset();
- m_sbi.air_density = (btScalar)1.2;
- m_sbi.water_density = 0;
- m_sbi.water_offset = 0;
- m_sbi.water_normal = btVector3(0,0,0);
- m_sbi.m_gravity.setValue(0,-10,0);
+ m_sbi.air_density = (btScalar)1.2;
+ m_sbi.water_density = 0;
+ m_sbi.water_offset = 0;
+ m_sbi.water_normal = btVector3(0, 0, 0);
+ m_sbi.m_gravity.setValue(0, -10, 0);
m_sbi.m_sparsesdf.Initialize();
-
-
}
btSoftMultiBodyDynamicsWorld::~btSoftMultiBodyDynamicsWorld()
@@ -71,82 +66,78 @@ btSoftMultiBodyDynamicsWorld::~btSoftMultiBodyDynamicsWorld()
}
}
-void btSoftMultiBodyDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
+void btSoftMultiBodyDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
{
- btDiscreteDynamicsWorld::predictUnconstraintMotion( timeStep );
+ btDiscreteDynamicsWorld::predictUnconstraintMotion(timeStep);
{
BT_PROFILE("predictUnconstraintMotionSoftBody");
- m_softBodySolver->predictMotion( float(timeStep) );
+ m_softBodySolver->predictMotion(float(timeStep));
}
}
-void btSoftMultiBodyDynamicsWorld::internalSingleStepSimulation( btScalar timeStep )
+void btSoftMultiBodyDynamicsWorld::internalSingleStepSimulation(btScalar timeStep)
{
-
// Let the solver grab the soft bodies and if necessary optimize for it
- m_softBodySolver->optimize( getSoftBodyArray() );
+ m_softBodySolver->optimize(getSoftBodyArray());
- if( !m_softBodySolver->checkInitialized() )
+ if (!m_softBodySolver->checkInitialized())
{
- btAssert( "Solver initialization failed\n" );
+ btAssert("Solver initialization failed\n");
}
- btDiscreteDynamicsWorld::internalSingleStepSimulation( timeStep );
+ btDiscreteDynamicsWorld::internalSingleStepSimulation(timeStep);
///solve soft bodies constraints
- solveSoftBodiesConstraints( timeStep );
+ solveSoftBodiesConstraints(timeStep);
//self collisions
- for ( int i=0;i<m_softBodies.size();i++)
+ for (int i = 0; i < m_softBodies.size(); i++)
{
- btSoftBody* psb=(btSoftBody*)m_softBodies[i];
+ btSoftBody* psb = (btSoftBody*)m_softBodies[i];
psb->defaultCollisionHandler(psb);
}
///update soft bodies
- m_softBodySolver->updateSoftBodies( );
-
+ m_softBodySolver->updateSoftBodies();
+
// End solver-wise simulation step
// ///////////////////////////////
-
}
-void btSoftMultiBodyDynamicsWorld::solveSoftBodiesConstraints( btScalar timeStep )
+void btSoftMultiBodyDynamicsWorld::solveSoftBodiesConstraints(btScalar timeStep)
{
BT_PROFILE("solveSoftConstraints");
- if(m_softBodies.size())
+ if (m_softBodies.size())
{
btSoftBody::solveClusters(m_softBodies);
}
// Solve constraints solver-wise
- m_softBodySolver->solveConstraints( timeStep * m_softBodySolver->getTimeScale() );
-
+ m_softBodySolver->solveConstraints(timeStep * m_softBodySolver->getTimeScale());
}
-void btSoftMultiBodyDynamicsWorld::addSoftBody(btSoftBody* body, int collisionFilterGroup, int collisionFilterMask)
+void btSoftMultiBodyDynamicsWorld::addSoftBody(btSoftBody* body, int collisionFilterGroup, int collisionFilterMask)
{
m_softBodies.push_back(body);
// Set the soft body solver that will deal with this body
// to be the world's solver
- body->setSoftBodySolver( m_softBodySolver );
+ body->setSoftBodySolver(m_softBodySolver);
btCollisionWorld::addCollisionObject(body,
- collisionFilterGroup,
- collisionFilterMask);
-
+ collisionFilterGroup,
+ collisionFilterMask);
}
-void btSoftMultiBodyDynamicsWorld::removeSoftBody(btSoftBody* body)
+void btSoftMultiBodyDynamicsWorld::removeSoftBody(btSoftBody* body)
{
m_softBodies.remove(body);
btCollisionWorld::removeCollisionObject(body);
}
-void btSoftMultiBodyDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject)
+void btSoftMultiBodyDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject)
{
btSoftBody* body = btSoftBody::upcast(collisionObject);
if (body)
@@ -155,60 +146,57 @@ void btSoftMultiBodyDynamicsWorld::removeCollisionObject(btCollisionObject* coll
btDiscreteDynamicsWorld::removeCollisionObject(collisionObject);
}
-void btSoftMultiBodyDynamicsWorld::debugDrawWorld()
+void btSoftMultiBodyDynamicsWorld::debugDrawWorld()
{
btMultiBodyDynamicsWorld::debugDrawWorld();
if (getDebugDrawer())
{
int i;
- for ( i=0;i<this->m_softBodies.size();i++)
+ for (i = 0; i < this->m_softBodies.size(); i++)
{
- btSoftBody* psb=(btSoftBody*)this->m_softBodies[i];
+ btSoftBody* psb = (btSoftBody*)this->m_softBodies[i];
if (getDebugDrawer() && (getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe)))
{
- btSoftBodyHelpers::DrawFrame(psb,m_debugDrawer);
- btSoftBodyHelpers::Draw(psb,m_debugDrawer,m_drawFlags);
+ btSoftBodyHelpers::DrawFrame(psb, m_debugDrawer);
+ btSoftBodyHelpers::Draw(psb, m_debugDrawer, m_drawFlags);
}
-
+
if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
{
- if(m_drawNodeTree) btSoftBodyHelpers::DrawNodeTree(psb,m_debugDrawer);
- if(m_drawFaceTree) btSoftBodyHelpers::DrawFaceTree(psb,m_debugDrawer);
- if(m_drawClusterTree) btSoftBodyHelpers::DrawClusterTree(psb,m_debugDrawer);
+ if (m_drawNodeTree) btSoftBodyHelpers::DrawNodeTree(psb, m_debugDrawer);
+ if (m_drawFaceTree) btSoftBodyHelpers::DrawFaceTree(psb, m_debugDrawer);
+ if (m_drawClusterTree) btSoftBodyHelpers::DrawClusterTree(psb, m_debugDrawer);
}
- }
- }
+ }
+ }
}
-
-
-
struct btSoftSingleRayCallback : public btBroadphaseRayCallback
{
- btVector3 m_rayFromWorld;
- btVector3 m_rayToWorld;
- btTransform m_rayFromTrans;
- btTransform m_rayToTrans;
- btVector3 m_hitNormal;
-
- const btSoftMultiBodyDynamicsWorld* m_world;
- btCollisionWorld::RayResultCallback& m_resultCallback;
-
- btSoftSingleRayCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld,const btSoftMultiBodyDynamicsWorld* world,btCollisionWorld::RayResultCallback& resultCallback)
- :m_rayFromWorld(rayFromWorld),
- m_rayToWorld(rayToWorld),
- m_world(world),
- m_resultCallback(resultCallback)
+ btVector3 m_rayFromWorld;
+ btVector3 m_rayToWorld;
+ btTransform m_rayFromTrans;
+ btTransform m_rayToTrans;
+ btVector3 m_hitNormal;
+
+ const btSoftMultiBodyDynamicsWorld* m_world;
+ btCollisionWorld::RayResultCallback& m_resultCallback;
+
+ btSoftSingleRayCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld, const btSoftMultiBodyDynamicsWorld* world, btCollisionWorld::RayResultCallback& resultCallback)
+ : m_rayFromWorld(rayFromWorld),
+ m_rayToWorld(rayToWorld),
+ m_world(world),
+ m_resultCallback(resultCallback)
{
m_rayFromTrans.setIdentity();
m_rayFromTrans.setOrigin(m_rayFromWorld);
m_rayToTrans.setIdentity();
m_rayToTrans.setOrigin(m_rayToWorld);
- btVector3 rayDir = (rayToWorld-rayFromWorld);
+ btVector3 rayDir = (rayToWorld - rayFromWorld);
- rayDir.normalize ();
+ rayDir.normalize();
///what about division by zero? --> just set rayDirection[i] to INF/1e30
m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[0];
m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[1];
@@ -217,22 +205,19 @@ struct btSoftSingleRayCallback : public btBroadphaseRayCallback
m_signs[1] = m_rayDirectionInverse[1] < 0.0;
m_signs[2] = m_rayDirectionInverse[2] < 0.0;
- m_lambda_max = rayDir.dot(m_rayToWorld-m_rayFromWorld);
-
+ m_lambda_max = rayDir.dot(m_rayToWorld - m_rayFromWorld);
}
-
-
- virtual bool process(const btBroadphaseProxy* proxy)
+ virtual bool process(const btBroadphaseProxy* proxy)
{
///terminate further ray tests, once the closestHitFraction reached zero
if (m_resultCallback.m_closestHitFraction == btScalar(0.f))
return false;
- btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
+ btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
//only perform raycast if filterMask matches
- if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
+ if (m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
{
//RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
//btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
@@ -250,110 +235,106 @@ struct btSoftSingleRayCallback : public btBroadphaseRayCallback
//culling already done by broadphase
//if (btRayAabb(m_rayFromWorld,m_rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,m_hitNormal))
{
- m_world->rayTestSingle(m_rayFromTrans,m_rayToTrans,
- collisionObject,
- collisionObject->getCollisionShape(),
- collisionObject->getWorldTransform(),
- m_resultCallback);
+ m_world->rayTestSingle(m_rayFromTrans, m_rayToTrans,
+ collisionObject,
+ collisionObject->getCollisionShape(),
+ collisionObject->getWorldTransform(),
+ m_resultCallback);
}
}
return true;
}
};
-void btSoftMultiBodyDynamicsWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const
+void btSoftMultiBodyDynamicsWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const
{
BT_PROFILE("rayTest");
/// use the broadphase to accelerate the search for objects, based on their aabb
/// and for each object with ray-aabb overlap, perform an exact ray test
- btSoftSingleRayCallback rayCB(rayFromWorld,rayToWorld,this,resultCallback);
+ btSoftSingleRayCallback rayCB(rayFromWorld, rayToWorld, this, resultCallback);
#ifndef USE_BRUTEFORCE_RAYBROADPHASE
- m_broadphasePairCache->rayTest(rayFromWorld,rayToWorld,rayCB);
+ m_broadphasePairCache->rayTest(rayFromWorld, rayToWorld, rayCB);
#else
- for (int i=0;i<this->getNumCollisionObjects();i++)
+ for (int i = 0; i < this->getNumCollisionObjects(); i++)
{
rayCB.process(m_collisionObjects[i]->getBroadphaseHandle());
- }
-#endif //USE_BRUTEFORCE_RAYBROADPHASE
-
+ }
+#endif //USE_BRUTEFORCE_RAYBROADPHASE
}
-
-void btSoftMultiBodyDynamicsWorld::rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans,
- btCollisionObject* collisionObject,
- const btCollisionShape* collisionShape,
- const btTransform& colObjWorldTransform,
- RayResultCallback& resultCallback)
+void btSoftMultiBodyDynamicsWorld::rayTestSingle(const btTransform& rayFromTrans, const btTransform& rayToTrans,
+ btCollisionObject* collisionObject,
+ const btCollisionShape* collisionShape,
+ const btTransform& colObjWorldTransform,
+ RayResultCallback& resultCallback)
{
- if (collisionShape->isSoftBody()) {
+ if (collisionShape->isSoftBody())
+ {
btSoftBody* softBody = btSoftBody::upcast(collisionObject);
- if (softBody) {
+ if (softBody)
+ {
btSoftBody::sRayCast softResult;
- if (softBody->rayTest(rayFromTrans.getOrigin(), rayToTrans.getOrigin(), softResult))
+ if (softBody->rayTest(rayFromTrans.getOrigin(), rayToTrans.getOrigin(), softResult))
{
-
- if (softResult.fraction<= resultCallback.m_closestHitFraction)
+ if (softResult.fraction <= resultCallback.m_closestHitFraction)
{
-
btCollisionWorld::LocalShapeInfo shapeInfo;
shapeInfo.m_shapePart = 0;
shapeInfo.m_triangleIndex = softResult.index;
// get the normal
btVector3 rayDir = rayToTrans.getOrigin() - rayFromTrans.getOrigin();
- btVector3 normal=-rayDir;
+ btVector3 normal = -rayDir;
normal.normalize();
if (softResult.feature == btSoftBody::eFeature::Face)
{
normal = softBody->m_faces[softResult.index].m_normal;
- if (normal.dot(rayDir) > 0) {
+ if (normal.dot(rayDir) > 0)
+ {
// normal always point toward origin of the ray
normal = -normal;
}
}
-
- btCollisionWorld::LocalRayResult rayResult
- (collisionObject,
- &shapeInfo,
- normal,
- softResult.fraction);
- bool normalInWorldSpace = true;
- resultCallback.addSingleResult(rayResult,normalInWorldSpace);
+
+ btCollisionWorld::LocalRayResult rayResult(collisionObject,
+ &shapeInfo,
+ normal,
+ softResult.fraction);
+ bool normalInWorldSpace = true;
+ resultCallback.addSingleResult(rayResult, normalInWorldSpace);
}
}
}
- }
- else {
- btCollisionWorld::rayTestSingle(rayFromTrans,rayToTrans,collisionObject,collisionShape,colObjWorldTransform,resultCallback);
+ }
+ else
+ {
+ btCollisionWorld::rayTestSingle(rayFromTrans, rayToTrans, collisionObject, collisionShape, colObjWorldTransform, resultCallback);
}
}
-
-void btSoftMultiBodyDynamicsWorld::serializeSoftBodies(btSerializer* serializer)
+void btSoftMultiBodyDynamicsWorld::serializeSoftBodies(btSerializer* serializer)
{
int i;
//serialize all collision objects
- for (i=0;i<m_collisionObjects.size();i++)
+ for (i = 0; i < m_collisionObjects.size(); i++)
{
btCollisionObject* colObj = m_collisionObjects[i];
if (colObj->getInternalType() & btCollisionObject::CO_SOFT_BODY)
{
int len = colObj->calculateSerializeBufferSize();
- btChunk* chunk = serializer->allocate(len,1);
+ btChunk* chunk = serializer->allocate(len, 1);
const char* structType = colObj->serialize(chunk->m_oldPtr, serializer);
- serializer->finalizeChunk(chunk,structType,BT_SOFTBODY_CODE,colObj);
+ serializer->finalizeChunk(chunk, structType, BT_SOFTBODY_CODE, colObj);
}
}
-
}
-void btSoftMultiBodyDynamicsWorld::serialize(btSerializer* serializer)
+void btSoftMultiBodyDynamicsWorld::serialize(btSerializer* serializer)
{
-
serializer->startSerialization();
- serializeDynamicsWorldInfo( serializer);
+ serializeDynamicsWorldInfo(serializer);
serializeSoftBodies(serializer);
@@ -367,5 +348,3 @@ void btSoftMultiBodyDynamicsWorld::serialize(btSerializer* serializer)
serializer->finishSerialization();
}
-
-
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftMultiBodyDynamicsWorld.h b/thirdparty/bullet/BulletSoftBody/btSoftMultiBodyDynamicsWorld.h
index 6d46a21db5..f295945a6d 100644
--- a/thirdparty/bullet/BulletSoftBody/btSoftMultiBodyDynamicsWorld.h
+++ b/thirdparty/bullet/BulletSoftBody/btSoftMultiBodyDynamicsWorld.h
@@ -21,64 +21,61 @@ subject to the following restrictions:
#include "BulletSoftBody/btSoftBody.h"
#ifndef BT_SOFT_RIGID_DYNAMICS_WORLD_H
-typedef btAlignedObjectArray<btSoftBody*> btSoftBodyArray;
+typedef btAlignedObjectArray<btSoftBody*> btSoftBodyArray;
#endif
class btSoftBodySolver;
class btSoftMultiBodyDynamicsWorld : public btMultiBodyDynamicsWorld
{
-
- btSoftBodyArray m_softBodies;
- int m_drawFlags;
- bool m_drawNodeTree;
- bool m_drawFaceTree;
- bool m_drawClusterTree;
+ btSoftBodyArray m_softBodies;
+ int m_drawFlags;
+ bool m_drawNodeTree;
+ bool m_drawFaceTree;
+ bool m_drawClusterTree;
btSoftBodyWorldInfo m_sbi;
///Solver classes that encapsulate multiple soft bodies for solving
- btSoftBodySolver *m_softBodySolver;
- bool m_ownsSolver;
+ btSoftBodySolver* m_softBodySolver;
+ bool m_ownsSolver;
protected:
+ virtual void predictUnconstraintMotion(btScalar timeStep);
- virtual void predictUnconstraintMotion(btScalar timeStep);
-
- virtual void internalSingleStepSimulation( btScalar timeStep);
+ virtual void internalSingleStepSimulation(btScalar timeStep);
- void solveSoftBodiesConstraints( btScalar timeStep );
+ void solveSoftBodiesConstraints(btScalar timeStep);
- void serializeSoftBodies(btSerializer* serializer);
+ void serializeSoftBodies(btSerializer* serializer);
public:
-
- btSoftMultiBodyDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btMultiBodyConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration, btSoftBodySolver *softBodySolver = 0 );
+ btSoftMultiBodyDynamicsWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btMultiBodyConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration, btSoftBodySolver* softBodySolver = 0);
virtual ~btSoftMultiBodyDynamicsWorld();
- virtual void debugDrawWorld();
+ virtual void debugDrawWorld();
- void addSoftBody(btSoftBody* body, int collisionFilterGroup=btBroadphaseProxy::DefaultFilter, int collisionFilterMask=btBroadphaseProxy::AllFilter);
+ void addSoftBody(btSoftBody* body, int collisionFilterGroup = btBroadphaseProxy::DefaultFilter, int collisionFilterMask = btBroadphaseProxy::AllFilter);
- void removeSoftBody(btSoftBody* body);
+ void removeSoftBody(btSoftBody* body);
///removeCollisionObject will first check if it is a rigid body, if so call removeRigidBody otherwise call btDiscreteDynamicsWorld::removeCollisionObject
- virtual void removeCollisionObject(btCollisionObject* collisionObject);
+ virtual void removeCollisionObject(btCollisionObject* collisionObject);
- int getDrawFlags() const { return(m_drawFlags); }
- void setDrawFlags(int f) { m_drawFlags=f; }
+ int getDrawFlags() const { return (m_drawFlags); }
+ void setDrawFlags(int f) { m_drawFlags = f; }
- btSoftBodyWorldInfo& getWorldInfo()
+ btSoftBodyWorldInfo& getWorldInfo()
{
return m_sbi;
}
- const btSoftBodyWorldInfo& getWorldInfo() const
+ const btSoftBodyWorldInfo& getWorldInfo() const
{
return m_sbi;
}
- virtual btDynamicsWorldType getWorldType() const
+ virtual btDynamicsWorldType getWorldType() const
{
- return BT_SOFT_MULTIBODY_DYNAMICS_WORLD;
+ return BT_SOFT_MULTIBODY_DYNAMICS_WORLD;
}
btSoftBodyArray& getSoftBodyArray()
@@ -91,20 +88,18 @@ public:
return m_softBodies;
}
-
- virtual void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const;
+ virtual void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const;
/// rayTestSingle performs a raycast call and calls the resultCallback. It is used internally by rayTest.
/// In a future implementation, we consider moving the ray test as a virtual method in btCollisionShape.
/// This allows more customization.
- static void rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans,
- btCollisionObject* collisionObject,
- const btCollisionShape* collisionShape,
- const btTransform& colObjWorldTransform,
- RayResultCallback& resultCallback);
-
- virtual void serialize(btSerializer* serializer);
+ static void rayTestSingle(const btTransform& rayFromTrans, const btTransform& rayToTrans,
+ btCollisionObject* collisionObject,
+ const btCollisionShape* collisionShape,
+ const btTransform& colObjWorldTransform,
+ RayResultCallback& resultCallback);
+ virtual void serialize(btSerializer* serializer);
};
-#endif //BT_SOFT_MULTIBODY_DYNAMICS_WORLD_H
+#endif //BT_SOFT_MULTIBODY_DYNAMICS_WORLD_H
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp b/thirdparty/bullet/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp
index 01c148a2ca..56d8083f22 100644
--- a/thirdparty/bullet/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp
+++ b/thirdparty/bullet/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp
@@ -27,18 +27,16 @@ subject to the following restrictions:
//#include <stdio.h>
-btSoftRigidCollisionAlgorithm::btSoftRigidCollisionAlgorithm(btPersistentManifold* /*mf*/,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* ,const btCollisionObjectWrapper* , bool isSwapped)
-: btCollisionAlgorithm(ci),
-//m_ownManifold(false),
-//m_manifoldPtr(mf),
-m_isSwapped(isSwapped)
+btSoftRigidCollisionAlgorithm::btSoftRigidCollisionAlgorithm(btPersistentManifold* /*mf*/, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper*, const btCollisionObjectWrapper*, bool isSwapped)
+ : btCollisionAlgorithm(ci),
+ //m_ownManifold(false),
+ //m_manifoldPtr(mf),
+ m_isSwapped(isSwapped)
{
}
-
btSoftRigidCollisionAlgorithm::~btSoftRigidCollisionAlgorithm()
{
-
//m_softBody->m_overlappingRigidBodies.remove(m_rigidCollisionObject);
/*if (m_ownManifold)
@@ -47,31 +45,27 @@ btSoftRigidCollisionAlgorithm::~btSoftRigidCollisionAlgorithm()
m_dispatcher->releaseManifold(m_manifoldPtr);
}
*/
-
}
-
#include <stdio.h>
-void btSoftRigidCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+void btSoftRigidCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
{
(void)dispatchInfo;
(void)resultOut;
//printf("btSoftRigidCollisionAlgorithm\n");
-// const btCollisionObjectWrapper* softWrap = m_isSwapped?body1Wrap:body0Wrap;
-// const btCollisionObjectWrapper* rigidWrap = m_isSwapped?body0Wrap:body1Wrap;
- btSoftBody* softBody = m_isSwapped? (btSoftBody*)body1Wrap->getCollisionObject() : (btSoftBody*)body0Wrap->getCollisionObject();
- const btCollisionObjectWrapper* rigidCollisionObjectWrap = m_isSwapped? body0Wrap : body1Wrap;
-
- if (softBody->m_collisionDisabledObjects.findLinearSearch(rigidCollisionObjectWrap->getCollisionObject())==softBody->m_collisionDisabledObjects.size())
+ // const btCollisionObjectWrapper* softWrap = m_isSwapped?body1Wrap:body0Wrap;
+ // const btCollisionObjectWrapper* rigidWrap = m_isSwapped?body0Wrap:body1Wrap;
+ btSoftBody* softBody = m_isSwapped ? (btSoftBody*)body1Wrap->getCollisionObject() : (btSoftBody*)body0Wrap->getCollisionObject();
+ const btCollisionObjectWrapper* rigidCollisionObjectWrap = m_isSwapped ? body0Wrap : body1Wrap;
+
+ if (softBody->m_collisionDisabledObjects.findLinearSearch(rigidCollisionObjectWrap->getCollisionObject()) == softBody->m_collisionDisabledObjects.size())
{
softBody->getSoftBodySolver()->processCollision(softBody, rigidCollisionObjectWrap);
}
-
-
}
-btScalar btSoftRigidCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+btScalar btSoftRigidCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0, btCollisionObject* col1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
{
(void)resultOut;
(void)dispatchInfo;
@@ -81,6 +75,3 @@ btScalar btSoftRigidCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject*
//not yet
return btScalar(1.);
}
-
-
-
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftRigidCollisionAlgorithm.h b/thirdparty/bullet/BulletSoftBody/btSoftRigidCollisionAlgorithm.h
index 93fcc6065b..9773af19a0 100644
--- a/thirdparty/bullet/BulletSoftBody/btSoftRigidCollisionAlgorithm.h
+++ b/thirdparty/bullet/BulletSoftBody/btSoftRigidCollisionAlgorithm.h
@@ -35,41 +35,37 @@ class btSoftRigidCollisionAlgorithm : public btCollisionAlgorithm
//btCollisionObject* m_rigidCollisionObject;
///for rigid versus soft (instead of soft versus rigid), we use this swapped boolean
- bool m_isSwapped;
+ bool m_isSwapped;
public:
-
- btSoftRigidCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* col0,const btCollisionObjectWrapper* col1Wrap, bool isSwapped);
+ btSoftRigidCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* col0, const btCollisionObjectWrapper* col1Wrap, bool isSwapped);
virtual ~btSoftRigidCollisionAlgorithm();
- virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
- virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
- virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
//we don't add any manifolds
}
-
- struct CreateFunc :public btCollisionAlgorithmCreateFunc
+ struct CreateFunc : public btCollisionAlgorithmCreateFunc
{
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftRigidCollisionAlgorithm));
if (!m_swapped)
{
- return new(mem) btSoftRigidCollisionAlgorithm(0,ci,body0Wrap,body1Wrap,false);
- } else
+ return new (mem) btSoftRigidCollisionAlgorithm(0, ci, body0Wrap, body1Wrap, false);
+ }
+ else
{
- return new(mem) btSoftRigidCollisionAlgorithm(0,ci,body0Wrap,body1Wrap,true);
+ return new (mem) btSoftRigidCollisionAlgorithm(0, ci, body0Wrap, body1Wrap, true);
}
}
};
-
};
-#endif //BT_SOFT_RIGID_COLLISION_ALGORITHM_H
-
-
+#endif //BT_SOFT_RIGID_COLLISION_ALGORITHM_H
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftRigidDynamicsWorld.cpp b/thirdparty/bullet/BulletSoftBody/btSoftRigidDynamicsWorld.cpp
index 204b4f576d..510b731fc1 100644
--- a/thirdparty/bullet/BulletSoftBody/btSoftRigidDynamicsWorld.cpp
+++ b/thirdparty/bullet/BulletSoftBody/btSoftRigidDynamicsWorld.cpp
@@ -13,7 +13,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#include "btSoftRigidDynamicsWorld.h"
#include "LinearMath/btQuickprof.h"
@@ -24,42 +23,38 @@ subject to the following restrictions:
#include "btDefaultSoftBodySolver.h"
#include "LinearMath/btSerializer.h"
-
btSoftRigidDynamicsWorld::btSoftRigidDynamicsWorld(
btDispatcher* dispatcher,
btBroadphaseInterface* pairCache,
btConstraintSolver* constraintSolver,
btCollisionConfiguration* collisionConfiguration,
- btSoftBodySolver *softBodySolver ) :
- btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration),
- m_softBodySolver( softBodySolver ),
- m_ownsSolver(false)
+ btSoftBodySolver* softBodySolver) : btDiscreteDynamicsWorld(dispatcher, pairCache, constraintSolver, collisionConfiguration),
+ m_softBodySolver(softBodySolver),
+ m_ownsSolver(false)
{
- if( !m_softBodySolver )
+ if (!m_softBodySolver)
{
- void* ptr = btAlignedAlloc(sizeof(btDefaultSoftBodySolver),16);
- m_softBodySolver = new(ptr) btDefaultSoftBodySolver();
+ void* ptr = btAlignedAlloc(sizeof(btDefaultSoftBodySolver), 16);
+ m_softBodySolver = new (ptr) btDefaultSoftBodySolver();
m_ownsSolver = true;
}
- m_drawFlags = fDrawFlags::Std;
- m_drawNodeTree = true;
- m_drawFaceTree = false;
- m_drawClusterTree = false;
+ m_drawFlags = fDrawFlags::Std;
+ m_drawNodeTree = true;
+ m_drawFaceTree = false;
+ m_drawClusterTree = false;
m_sbi.m_broadphase = pairCache;
m_sbi.m_dispatcher = dispatcher;
m_sbi.m_sparsesdf.Initialize();
m_sbi.m_sparsesdf.Reset();
- m_sbi.air_density = (btScalar)1.2;
- m_sbi.water_density = 0;
- m_sbi.water_offset = 0;
- m_sbi.water_normal = btVector3(0,0,0);
- m_sbi.m_gravity.setValue(0,-10,0);
+ m_sbi.air_density = (btScalar)1.2;
+ m_sbi.water_density = 0;
+ m_sbi.water_offset = 0;
+ m_sbi.water_normal = btVector3(0, 0, 0);
+ m_sbi.m_gravity.setValue(0, -10, 0);
m_sbi.m_sparsesdf.Initialize();
-
-
}
btSoftRigidDynamicsWorld::~btSoftRigidDynamicsWorld()
@@ -71,82 +66,78 @@ btSoftRigidDynamicsWorld::~btSoftRigidDynamicsWorld()
}
}
-void btSoftRigidDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
+void btSoftRigidDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
{
- btDiscreteDynamicsWorld::predictUnconstraintMotion( timeStep );
+ btDiscreteDynamicsWorld::predictUnconstraintMotion(timeStep);
{
BT_PROFILE("predictUnconstraintMotionSoftBody");
- m_softBodySolver->predictMotion( float(timeStep) );
+ m_softBodySolver->predictMotion(float(timeStep));
}
}
-void btSoftRigidDynamicsWorld::internalSingleStepSimulation( btScalar timeStep )
+void btSoftRigidDynamicsWorld::internalSingleStepSimulation(btScalar timeStep)
{
-
// Let the solver grab the soft bodies and if necessary optimize for it
- m_softBodySolver->optimize( getSoftBodyArray() );
+ m_softBodySolver->optimize(getSoftBodyArray());
- if( !m_softBodySolver->checkInitialized() )
+ if (!m_softBodySolver->checkInitialized())
{
- btAssert( "Solver initialization failed\n" );
+ btAssert("Solver initialization failed\n");
}
- btDiscreteDynamicsWorld::internalSingleStepSimulation( timeStep );
+ btDiscreteDynamicsWorld::internalSingleStepSimulation(timeStep);
///solve soft bodies constraints
- solveSoftBodiesConstraints( timeStep );
+ solveSoftBodiesConstraints(timeStep);
//self collisions
- for ( int i=0;i<m_softBodies.size();i++)
+ for (int i = 0; i < m_softBodies.size(); i++)
{
- btSoftBody* psb=(btSoftBody*)m_softBodies[i];
+ btSoftBody* psb = (btSoftBody*)m_softBodies[i];
psb->defaultCollisionHandler(psb);
}
///update soft bodies
- m_softBodySolver->updateSoftBodies( );
-
+ m_softBodySolver->updateSoftBodies();
+
// End solver-wise simulation step
// ///////////////////////////////
-
}
-void btSoftRigidDynamicsWorld::solveSoftBodiesConstraints( btScalar timeStep )
+void btSoftRigidDynamicsWorld::solveSoftBodiesConstraints(btScalar timeStep)
{
BT_PROFILE("solveSoftConstraints");
- if(m_softBodies.size())
+ if (m_softBodies.size())
{
btSoftBody::solveClusters(m_softBodies);
}
// Solve constraints solver-wise
- m_softBodySolver->solveConstraints( timeStep * m_softBodySolver->getTimeScale() );
-
+ m_softBodySolver->solveConstraints(timeStep * m_softBodySolver->getTimeScale());
}
-void btSoftRigidDynamicsWorld::addSoftBody(btSoftBody* body, int collisionFilterGroup, int collisionFilterMask)
+void btSoftRigidDynamicsWorld::addSoftBody(btSoftBody* body, int collisionFilterGroup, int collisionFilterMask)
{
m_softBodies.push_back(body);
// Set the soft body solver that will deal with this body
// to be the world's solver
- body->setSoftBodySolver( m_softBodySolver );
+ body->setSoftBodySolver(m_softBodySolver);
btCollisionWorld::addCollisionObject(body,
- collisionFilterGroup,
- collisionFilterMask);
-
+ collisionFilterGroup,
+ collisionFilterMask);
}
-void btSoftRigidDynamicsWorld::removeSoftBody(btSoftBody* body)
+void btSoftRigidDynamicsWorld::removeSoftBody(btSoftBody* body)
{
m_softBodies.remove(body);
btCollisionWorld::removeCollisionObject(body);
}
-void btSoftRigidDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject)
+void btSoftRigidDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject)
{
btSoftBody* body = btSoftBody::upcast(collisionObject);
if (body)
@@ -155,60 +146,57 @@ void btSoftRigidDynamicsWorld::removeCollisionObject(btCollisionObject* collisio
btDiscreteDynamicsWorld::removeCollisionObject(collisionObject);
}
-void btSoftRigidDynamicsWorld::debugDrawWorld()
+void btSoftRigidDynamicsWorld::debugDrawWorld()
{
btDiscreteDynamicsWorld::debugDrawWorld();
if (getDebugDrawer())
{
int i;
- for ( i=0;i<this->m_softBodies.size();i++)
+ for (i = 0; i < this->m_softBodies.size(); i++)
{
- btSoftBody* psb=(btSoftBody*)this->m_softBodies[i];
+ btSoftBody* psb = (btSoftBody*)this->m_softBodies[i];
if (getDebugDrawer() && (getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe)))
{
- btSoftBodyHelpers::DrawFrame(psb,m_debugDrawer);
- btSoftBodyHelpers::Draw(psb,m_debugDrawer,m_drawFlags);
+ btSoftBodyHelpers::DrawFrame(psb, m_debugDrawer);
+ btSoftBodyHelpers::Draw(psb, m_debugDrawer, m_drawFlags);
}
-
+
if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
{
- if(m_drawNodeTree) btSoftBodyHelpers::DrawNodeTree(psb,m_debugDrawer);
- if(m_drawFaceTree) btSoftBodyHelpers::DrawFaceTree(psb,m_debugDrawer);
- if(m_drawClusterTree) btSoftBodyHelpers::DrawClusterTree(psb,m_debugDrawer);
+ if (m_drawNodeTree) btSoftBodyHelpers::DrawNodeTree(psb, m_debugDrawer);
+ if (m_drawFaceTree) btSoftBodyHelpers::DrawFaceTree(psb, m_debugDrawer);
+ if (m_drawClusterTree) btSoftBodyHelpers::DrawClusterTree(psb, m_debugDrawer);
}
- }
- }
+ }
+ }
}
-
-
-
struct btSoftSingleRayCallback : public btBroadphaseRayCallback
{
- btVector3 m_rayFromWorld;
- btVector3 m_rayToWorld;
- btTransform m_rayFromTrans;
- btTransform m_rayToTrans;
- btVector3 m_hitNormal;
-
- const btSoftRigidDynamicsWorld* m_world;
- btCollisionWorld::RayResultCallback& m_resultCallback;
-
- btSoftSingleRayCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld,const btSoftRigidDynamicsWorld* world,btCollisionWorld::RayResultCallback& resultCallback)
- :m_rayFromWorld(rayFromWorld),
- m_rayToWorld(rayToWorld),
- m_world(world),
- m_resultCallback(resultCallback)
+ btVector3 m_rayFromWorld;
+ btVector3 m_rayToWorld;
+ btTransform m_rayFromTrans;
+ btTransform m_rayToTrans;
+ btVector3 m_hitNormal;
+
+ const btSoftRigidDynamicsWorld* m_world;
+ btCollisionWorld::RayResultCallback& m_resultCallback;
+
+ btSoftSingleRayCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld, const btSoftRigidDynamicsWorld* world, btCollisionWorld::RayResultCallback& resultCallback)
+ : m_rayFromWorld(rayFromWorld),
+ m_rayToWorld(rayToWorld),
+ m_world(world),
+ m_resultCallback(resultCallback)
{
m_rayFromTrans.setIdentity();
m_rayFromTrans.setOrigin(m_rayFromWorld);
m_rayToTrans.setIdentity();
m_rayToTrans.setOrigin(m_rayToWorld);
- btVector3 rayDir = (rayToWorld-rayFromWorld);
+ btVector3 rayDir = (rayToWorld - rayFromWorld);
- rayDir.normalize ();
+ rayDir.normalize();
///what about division by zero? --> just set rayDirection[i] to INF/1e30
m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[0];
m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[1];
@@ -217,22 +205,19 @@ struct btSoftSingleRayCallback : public btBroadphaseRayCallback
m_signs[1] = m_rayDirectionInverse[1] < 0.0;
m_signs[2] = m_rayDirectionInverse[2] < 0.0;
- m_lambda_max = rayDir.dot(m_rayToWorld-m_rayFromWorld);
-
+ m_lambda_max = rayDir.dot(m_rayToWorld - m_rayFromWorld);
}
-
-
- virtual bool process(const btBroadphaseProxy* proxy)
+ virtual bool process(const btBroadphaseProxy* proxy)
{
///terminate further ray tests, once the closestHitFraction reached zero
if (m_resultCallback.m_closestHitFraction == btScalar(0.f))
return false;
- btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
+ btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
//only perform raycast if filterMask matches
- if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
+ if (m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
{
//RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
//btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
@@ -250,110 +235,106 @@ struct btSoftSingleRayCallback : public btBroadphaseRayCallback
//culling already done by broadphase
//if (btRayAabb(m_rayFromWorld,m_rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,m_hitNormal))
{
- m_world->rayTestSingle(m_rayFromTrans,m_rayToTrans,
- collisionObject,
- collisionObject->getCollisionShape(),
- collisionObject->getWorldTransform(),
- m_resultCallback);
+ m_world->rayTestSingle(m_rayFromTrans, m_rayToTrans,
+ collisionObject,
+ collisionObject->getCollisionShape(),
+ collisionObject->getWorldTransform(),
+ m_resultCallback);
}
}
return true;
}
};
-void btSoftRigidDynamicsWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const
+void btSoftRigidDynamicsWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const
{
BT_PROFILE("rayTest");
/// use the broadphase to accelerate the search for objects, based on their aabb
/// and for each object with ray-aabb overlap, perform an exact ray test
- btSoftSingleRayCallback rayCB(rayFromWorld,rayToWorld,this,resultCallback);
+ btSoftSingleRayCallback rayCB(rayFromWorld, rayToWorld, this, resultCallback);
#ifndef USE_BRUTEFORCE_RAYBROADPHASE
- m_broadphasePairCache->rayTest(rayFromWorld,rayToWorld,rayCB);
+ m_broadphasePairCache->rayTest(rayFromWorld, rayToWorld, rayCB);
#else
- for (int i=0;i<this->getNumCollisionObjects();i++)
+ for (int i = 0; i < this->getNumCollisionObjects(); i++)
{
rayCB.process(m_collisionObjects[i]->getBroadphaseHandle());
- }
-#endif //USE_BRUTEFORCE_RAYBROADPHASE
-
+ }
+#endif //USE_BRUTEFORCE_RAYBROADPHASE
}
-
-void btSoftRigidDynamicsWorld::rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans,
- btCollisionObject* collisionObject,
- const btCollisionShape* collisionShape,
- const btTransform& colObjWorldTransform,
- RayResultCallback& resultCallback)
+void btSoftRigidDynamicsWorld::rayTestSingle(const btTransform& rayFromTrans, const btTransform& rayToTrans,
+ btCollisionObject* collisionObject,
+ const btCollisionShape* collisionShape,
+ const btTransform& colObjWorldTransform,
+ RayResultCallback& resultCallback)
{
- if (collisionShape->isSoftBody()) {
+ if (collisionShape->isSoftBody())
+ {
btSoftBody* softBody = btSoftBody::upcast(collisionObject);
- if (softBody) {
+ if (softBody)
+ {
btSoftBody::sRayCast softResult;
- if (softBody->rayTest(rayFromTrans.getOrigin(), rayToTrans.getOrigin(), softResult))
+ if (softBody->rayTest(rayFromTrans.getOrigin(), rayToTrans.getOrigin(), softResult))
{
-
- if (softResult.fraction<= resultCallback.m_closestHitFraction)
+ if (softResult.fraction <= resultCallback.m_closestHitFraction)
{
-
btCollisionWorld::LocalShapeInfo shapeInfo;
shapeInfo.m_shapePart = 0;
shapeInfo.m_triangleIndex = softResult.index;
// get the normal
btVector3 rayDir = rayToTrans.getOrigin() - rayFromTrans.getOrigin();
- btVector3 normal=-rayDir;
+ btVector3 normal = -rayDir;
normal.normalize();
if (softResult.feature == btSoftBody::eFeature::Face)
{
normal = softBody->m_faces[softResult.index].m_normal;
- if (normal.dot(rayDir) > 0) {
+ if (normal.dot(rayDir) > 0)
+ {
// normal always point toward origin of the ray
normal = -normal;
}
}
-
- btCollisionWorld::LocalRayResult rayResult
- (collisionObject,
- &shapeInfo,
- normal,
- softResult.fraction);
- bool normalInWorldSpace = true;
- resultCallback.addSingleResult(rayResult,normalInWorldSpace);
+
+ btCollisionWorld::LocalRayResult rayResult(collisionObject,
+ &shapeInfo,
+ normal,
+ softResult.fraction);
+ bool normalInWorldSpace = true;
+ resultCallback.addSingleResult(rayResult, normalInWorldSpace);
}
}
}
- }
- else {
- btCollisionWorld::rayTestSingle(rayFromTrans,rayToTrans,collisionObject,collisionShape,colObjWorldTransform,resultCallback);
+ }
+ else
+ {
+ btCollisionWorld::rayTestSingle(rayFromTrans, rayToTrans, collisionObject, collisionShape, colObjWorldTransform, resultCallback);
}
}
-
-void btSoftRigidDynamicsWorld::serializeSoftBodies(btSerializer* serializer)
+void btSoftRigidDynamicsWorld::serializeSoftBodies(btSerializer* serializer)
{
int i;
//serialize all collision objects
- for (i=0;i<m_collisionObjects.size();i++)
+ for (i = 0; i < m_collisionObjects.size(); i++)
{
btCollisionObject* colObj = m_collisionObjects[i];
if (colObj->getInternalType() & btCollisionObject::CO_SOFT_BODY)
{
int len = colObj->calculateSerializeBufferSize();
- btChunk* chunk = serializer->allocate(len,1);
+ btChunk* chunk = serializer->allocate(len, 1);
const char* structType = colObj->serialize(chunk->m_oldPtr, serializer);
- serializer->finalizeChunk(chunk,structType,BT_SOFTBODY_CODE,colObj);
+ serializer->finalizeChunk(chunk, structType, BT_SOFTBODY_CODE, colObj);
}
}
-
}
-void btSoftRigidDynamicsWorld::serialize(btSerializer* serializer)
+void btSoftRigidDynamicsWorld::serialize(btSerializer* serializer)
{
-
serializer->startSerialization();
- serializeDynamicsWorldInfo( serializer);
+ serializeDynamicsWorldInfo(serializer);
serializeSoftBodies(serializer);
@@ -363,5 +344,3 @@ void btSoftRigidDynamicsWorld::serialize(btSerializer* serializer)
serializer->finishSerialization();
}
-
-
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftRigidDynamicsWorld.h b/thirdparty/bullet/BulletSoftBody/btSoftRigidDynamicsWorld.h
index d921a6488d..be49c444d7 100644
--- a/thirdparty/bullet/BulletSoftBody/btSoftRigidDynamicsWorld.h
+++ b/thirdparty/bullet/BulletSoftBody/btSoftRigidDynamicsWorld.h
@@ -19,63 +19,60 @@ subject to the following restrictions:
#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h"
#include "btSoftBody.h"
-typedef btAlignedObjectArray<btSoftBody*> btSoftBodyArray;
+typedef btAlignedObjectArray<btSoftBody*> btSoftBodyArray;
class btSoftBodySolver;
class btSoftRigidDynamicsWorld : public btDiscreteDynamicsWorld
{
-
- btSoftBodyArray m_softBodies;
- int m_drawFlags;
- bool m_drawNodeTree;
- bool m_drawFaceTree;
- bool m_drawClusterTree;
+ btSoftBodyArray m_softBodies;
+ int m_drawFlags;
+ bool m_drawNodeTree;
+ bool m_drawFaceTree;
+ bool m_drawClusterTree;
btSoftBodyWorldInfo m_sbi;
///Solver classes that encapsulate multiple soft bodies for solving
- btSoftBodySolver *m_softBodySolver;
- bool m_ownsSolver;
+ btSoftBodySolver* m_softBodySolver;
+ bool m_ownsSolver;
protected:
+ virtual void predictUnconstraintMotion(btScalar timeStep);
- virtual void predictUnconstraintMotion(btScalar timeStep);
-
- virtual void internalSingleStepSimulation( btScalar timeStep);
+ virtual void internalSingleStepSimulation(btScalar timeStep);
- void solveSoftBodiesConstraints( btScalar timeStep );
+ void solveSoftBodiesConstraints(btScalar timeStep);
- void serializeSoftBodies(btSerializer* serializer);
+ void serializeSoftBodies(btSerializer* serializer);
public:
-
- btSoftRigidDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration, btSoftBodySolver *softBodySolver = 0 );
+ btSoftRigidDynamicsWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration, btSoftBodySolver* softBodySolver = 0);
virtual ~btSoftRigidDynamicsWorld();
- virtual void debugDrawWorld();
+ virtual void debugDrawWorld();
- void addSoftBody(btSoftBody* body, int collisionFilterGroup=btBroadphaseProxy::DefaultFilter, int collisionFilterMask=btBroadphaseProxy::AllFilter);
+ void addSoftBody(btSoftBody* body, int collisionFilterGroup = btBroadphaseProxy::DefaultFilter, int collisionFilterMask = btBroadphaseProxy::AllFilter);
- void removeSoftBody(btSoftBody* body);
+ void removeSoftBody(btSoftBody* body);
///removeCollisionObject will first check if it is a rigid body, if so call removeRigidBody otherwise call btDiscreteDynamicsWorld::removeCollisionObject
- virtual void removeCollisionObject(btCollisionObject* collisionObject);
+ virtual void removeCollisionObject(btCollisionObject* collisionObject);
- int getDrawFlags() const { return(m_drawFlags); }
- void setDrawFlags(int f) { m_drawFlags=f; }
+ int getDrawFlags() const { return (m_drawFlags); }
+ void setDrawFlags(int f) { m_drawFlags = f; }
- btSoftBodyWorldInfo& getWorldInfo()
+ btSoftBodyWorldInfo& getWorldInfo()
{
return m_sbi;
}
- const btSoftBodyWorldInfo& getWorldInfo() const
+ const btSoftBodyWorldInfo& getWorldInfo() const
{
return m_sbi;
}
- virtual btDynamicsWorldType getWorldType() const
+ virtual btDynamicsWorldType getWorldType() const
{
- return BT_SOFT_RIGID_DYNAMICS_WORLD;
+ return BT_SOFT_RIGID_DYNAMICS_WORLD;
}
btSoftBodyArray& getSoftBodyArray()
@@ -88,20 +85,18 @@ public:
return m_softBodies;
}
-
- virtual void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const;
+ virtual void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const;
/// rayTestSingle performs a raycast call and calls the resultCallback. It is used internally by rayTest.
/// In a future implementation, we consider moving the ray test as a virtual method in btCollisionShape.
/// This allows more customization.
- static void rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans,
- btCollisionObject* collisionObject,
- const btCollisionShape* collisionShape,
- const btTransform& colObjWorldTransform,
- RayResultCallback& resultCallback);
-
- virtual void serialize(btSerializer* serializer);
+ static void rayTestSingle(const btTransform& rayFromTrans, const btTransform& rayToTrans,
+ btCollisionObject* collisionObject,
+ const btCollisionShape* collisionShape,
+ const btTransform& colObjWorldTransform,
+ RayResultCallback& resultCallback);
+ virtual void serialize(btSerializer* serializer);
};
-#endif //BT_SOFT_RIGID_DYNAMICS_WORLD_H
+#endif //BT_SOFT_RIGID_DYNAMICS_WORLD_H
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp b/thirdparty/bullet/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp
index 72043e69e2..9c3e904f64 100644
--- a/thirdparty/bullet/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp
+++ b/thirdparty/bullet/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp
@@ -23,8 +23,8 @@ subject to the following restrictions:
#define USE_PERSISTENT_CONTACTS 1
-btSoftSoftCollisionAlgorithm::btSoftSoftCollisionAlgorithm(btPersistentManifold* /*mf*/,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* /*obj0*/,const btCollisionObjectWrapper* /*obj1*/)
-: btCollisionAlgorithm(ci)
+btSoftSoftCollisionAlgorithm::btSoftSoftCollisionAlgorithm(btPersistentManifold* /*mf*/, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* /*obj0*/, const btCollisionObjectWrapper* /*obj1*/)
+ : btCollisionAlgorithm(ci)
//m_ownManifold(false),
//m_manifoldPtr(mf)
{
@@ -34,14 +34,14 @@ btSoftSoftCollisionAlgorithm::~btSoftSoftCollisionAlgorithm()
{
}
-void btSoftSoftCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/)
+void btSoftSoftCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& /*dispatchInfo*/, btManifoldResult* /*resultOut*/)
{
- btSoftBody* soft0 = (btSoftBody*)body0Wrap->getCollisionObject();
- btSoftBody* soft1 = (btSoftBody*)body1Wrap->getCollisionObject();
+ btSoftBody* soft0 = (btSoftBody*)body0Wrap->getCollisionObject();
+ btSoftBody* soft1 = (btSoftBody*)body1Wrap->getCollisionObject();
soft0->getSoftBodySolver()->processCollision(soft0, soft1);
}
-btScalar btSoftSoftCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/,btCollisionObject* /*body1*/,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/)
+btScalar btSoftSoftCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/, btCollisionObject* /*body1*/, const btDispatcherInfo& /*dispatchInfo*/, btManifoldResult* /*resultOut*/)
{
//not yet
return 1.f;
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftSoftCollisionAlgorithm.h b/thirdparty/bullet/BulletSoftBody/btSoftSoftCollisionAlgorithm.h
index 4eab7aea2f..6f871f5b85 100644
--- a/thirdparty/bullet/BulletSoftBody/btSoftSoftCollisionAlgorithm.h
+++ b/thirdparty/bullet/BulletSoftBody/btSoftSoftCollisionAlgorithm.h
@@ -27,43 +27,39 @@ class btSoftBody;
///collision detection between two btSoftBody shapes
class btSoftSoftCollisionAlgorithm : public btCollisionAlgorithm
{
- bool m_ownManifold;
- btPersistentManifold* m_manifoldPtr;
-
-// btSoftBody* m_softBody0;
-// btSoftBody* m_softBody1;
+ bool m_ownManifold;
+ btPersistentManifold* m_manifoldPtr;
+ // btSoftBody* m_softBody0;
+ // btSoftBody* m_softBody1;
public:
btSoftSoftCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
: btCollisionAlgorithm(ci) {}
- virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
- virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
- virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr && m_ownManifold)
manifoldArray.push_back(m_manifoldPtr);
}
- btSoftSoftCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
+ btSoftSoftCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap);
virtual ~btSoftSoftCollisionAlgorithm();
- struct CreateFunc :public btCollisionAlgorithmCreateFunc
+ struct CreateFunc : public btCollisionAlgorithmCreateFunc
{
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
{
int bbsize = sizeof(btSoftSoftCollisionAlgorithm);
void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize);
- return new(ptr) btSoftSoftCollisionAlgorithm(0,ci,body0Wrap,body1Wrap);
+ return new (ptr) btSoftSoftCollisionAlgorithm(0, ci, body0Wrap, body1Wrap);
}
};
-
};
-#endif //BT_SOFT_SOFT_COLLISION_ALGORITHM_H
-
-
+#endif //BT_SOFT_SOFT_COLLISION_ALGORITHM_H
diff --git a/thirdparty/bullet/BulletSoftBody/btSparseSDF.h b/thirdparty/bullet/BulletSoftBody/btSparseSDF.h
index ba437c28ef..a52b2cb1cc 100644
--- a/thirdparty/bullet/BulletSoftBody/btSparseSDF.h
+++ b/thirdparty/bullet/BulletSoftBody/btSparseSDF.h
@@ -24,296 +24,320 @@ subject to the following restrictions:
template <const int DWORDLEN>
unsigned int HsiehHash(const void* pdata)
{
- const unsigned short* data=(const unsigned short*)pdata;
- unsigned hash=DWORDLEN<<2,tmp;
- for(int i=0;i<DWORDLEN;++i)
+ const unsigned short* data = (const unsigned short*)pdata;
+ unsigned hash = DWORDLEN << 2, tmp;
+ for (int i = 0; i < DWORDLEN; ++i)
{
- hash += data[0];
- tmp = (data[1]<<11)^hash;
- hash = (hash<<16)^tmp;
- data += 2;
- hash += hash>>11;
+ hash += data[0];
+ tmp = (data[1] << 11) ^ hash;
+ hash = (hash << 16) ^ tmp;
+ data += 2;
+ hash += hash >> 11;
}
- hash^=hash<<3;hash+=hash>>5;
- hash^=hash<<4;hash+=hash>>17;
- hash^=hash<<25;hash+=hash>>6;
- return(hash);
+ hash ^= hash << 3;
+ hash += hash >> 5;
+ hash ^= hash << 4;
+ hash += hash >> 17;
+ hash ^= hash << 25;
+ hash += hash >> 6;
+ return (hash);
}
template <const int CELLSIZE>
-struct btSparseSdf
+struct btSparseSdf
{
//
// Inner types
//
struct IntFrac
{
- int b;
- int i;
- btScalar f;
+ int b;
+ int i;
+ btScalar f;
};
- struct Cell
+ struct Cell
{
- btScalar d[CELLSIZE+1][CELLSIZE+1][CELLSIZE+1];
- int c[3];
- int puid;
- unsigned hash;
- const btCollisionShape* pclient;
- Cell* next;
+ btScalar d[CELLSIZE + 1][CELLSIZE + 1][CELLSIZE + 1];
+ int c[3];
+ int puid;
+ unsigned hash;
+ const btCollisionShape* pclient;
+ Cell* next;
};
//
// Fields
//
- btAlignedObjectArray<Cell*> cells;
- btScalar voxelsz;
- int puid;
- int ncells;
- int m_clampCells;
- int nprobes;
- int nqueries;
+ btAlignedObjectArray<Cell*> cells;
+ btScalar voxelsz;
+ int puid;
+ int ncells;
+ int m_clampCells;
+ int nprobes;
+ int nqueries;
//
// Methods
//
//
- void Initialize(int hashsize=2383, int clampCells = 256*1024)
+ void Initialize(int hashsize = 2383, int clampCells = 256 * 1024)
{
//avoid a crash due to running out of memory, so clamp the maximum number of cells allocated
//if this limit is reached, the SDF is reset (at the cost of some performance during the reset)
m_clampCells = clampCells;
- cells.resize(hashsize,0);
+ cells.resize(hashsize, 0);
Reset();
}
//
- void Reset()
+ void Reset()
{
- for(int i=0,ni=cells.size();i<ni;++i)
+ for (int i = 0, ni = cells.size(); i < ni; ++i)
{
- Cell* pc=cells[i];
- cells[i]=0;
- while(pc)
+ Cell* pc = cells[i];
+ cells[i] = 0;
+ while (pc)
{
- Cell* pn=pc->next;
+ Cell* pn = pc->next;
delete pc;
- pc=pn;
+ pc = pn;
}
}
- voxelsz =0.25;
- puid =0;
- ncells =0;
- nprobes =1;
- nqueries =1;
+ voxelsz = 0.25;
+ puid = 0;
+ ncells = 0;
+ nprobes = 1;
+ nqueries = 1;
}
//
- void GarbageCollect(int lifetime=256)
+ void GarbageCollect(int lifetime = 256)
{
- const int life=puid-lifetime;
- for(int i=0;i<cells.size();++i)
+ const int life = puid - lifetime;
+ for (int i = 0; i < cells.size(); ++i)
{
- Cell*& root=cells[i];
- Cell* pp=0;
- Cell* pc=root;
- while(pc)
+ Cell*& root = cells[i];
+ Cell* pp = 0;
+ Cell* pc = root;
+ while (pc)
{
- Cell* pn=pc->next;
- if(pc->puid<life)
+ Cell* pn = pc->next;
+ if (pc->puid < life)
{
- if(pp) pp->next=pn; else root=pn;
- delete pc;pc=pp;--ncells;
+ if (pp)
+ pp->next = pn;
+ else
+ root = pn;
+ delete pc;
+ pc = pp;
+ --ncells;
}
- pp=pc;pc=pn;
+ pp = pc;
+ pc = pn;
}
}
//printf("GC[%d]: %d cells, PpQ: %f\r\n",puid,ncells,nprobes/(btScalar)nqueries);
- nqueries=1;
- nprobes=1;
- ++puid; ///@todo: Reset puid's when int range limit is reached */
- /* else setup a priority list... */
+ nqueries = 1;
+ nprobes = 1;
+ ++puid; ///@todo: Reset puid's when int range limit is reached */
+ /* else setup a priority list... */
}
//
- int RemoveReferences(btCollisionShape* pcs)
+ int RemoveReferences(btCollisionShape* pcs)
{
- int refcount=0;
- for(int i=0;i<cells.size();++i)
+ int refcount = 0;
+ for (int i = 0; i < cells.size(); ++i)
{
- Cell*& root=cells[i];
- Cell* pp=0;
- Cell* pc=root;
- while(pc)
+ Cell*& root = cells[i];
+ Cell* pp = 0;
+ Cell* pc = root;
+ while (pc)
{
- Cell* pn=pc->next;
- if(pc->pclient==pcs)
+ Cell* pn = pc->next;
+ if (pc->pclient == pcs)
{
- if(pp) pp->next=pn; else root=pn;
- delete pc;pc=pp;++refcount;
+ if (pp)
+ pp->next = pn;
+ else
+ root = pn;
+ delete pc;
+ pc = pp;
+ ++refcount;
}
- pp=pc;pc=pn;
+ pp = pc;
+ pc = pn;
}
}
- return(refcount);
+ return (refcount);
}
//
- btScalar Evaluate( const btVector3& x,
- const btCollisionShape* shape,
- btVector3& normal,
- btScalar margin)
+ btScalar Evaluate(const btVector3& x,
+ const btCollisionShape* shape,
+ btVector3& normal,
+ btScalar margin)
{
- /* Lookup cell */
- const btVector3 scx=x/voxelsz;
- const IntFrac ix=Decompose(scx.x());
- const IntFrac iy=Decompose(scx.y());
- const IntFrac iz=Decompose(scx.z());
- const unsigned h=Hash(ix.b,iy.b,iz.b,shape);
- Cell*& root=cells[static_cast<int>(h%cells.size())];
- Cell* c=root;
+ /* Lookup cell */
+ const btVector3 scx = x / voxelsz;
+ const IntFrac ix = Decompose(scx.x());
+ const IntFrac iy = Decompose(scx.y());
+ const IntFrac iz = Decompose(scx.z());
+ const unsigned h = Hash(ix.b, iy.b, iz.b, shape);
+ Cell*& root = cells[static_cast<int>(h % cells.size())];
+ Cell* c = root;
++nqueries;
- while(c)
+ while (c)
{
++nprobes;
- if( (c->hash==h) &&
- (c->c[0]==ix.b) &&
- (c->c[1]==iy.b) &&
- (c->c[2]==iz.b) &&
- (c->pclient==shape))
- { break; }
+ if ((c->hash == h) &&
+ (c->c[0] == ix.b) &&
+ (c->c[1] == iy.b) &&
+ (c->c[2] == iz.b) &&
+ (c->pclient == shape))
+ {
+ break;
+ }
else
- { c=c->next; }
+ {
+ c = c->next;
+ }
}
- if(!c)
+ if (!c)
{
- ++nprobes;
+ ++nprobes;
++ncells;
//int sz = sizeof(Cell);
- if (ncells>m_clampCells)
+ if (ncells > m_clampCells)
{
- static int numResets=0;
+ static int numResets = 0;
numResets++;
-// printf("numResets=%d\n",numResets);
+ // printf("numResets=%d\n",numResets);
Reset();
}
- c=new Cell();
- c->next=root;root=c;
- c->pclient=shape;
- c->hash=h;
- c->c[0]=ix.b;c->c[1]=iy.b;c->c[2]=iz.b;
+ c = new Cell();
+ c->next = root;
+ root = c;
+ c->pclient = shape;
+ c->hash = h;
+ c->c[0] = ix.b;
+ c->c[1] = iy.b;
+ c->c[2] = iz.b;
BuildCell(*c);
}
- c->puid=puid;
- /* Extract infos */
- const int o[]={ ix.i,iy.i,iz.i};
- const btScalar d[]={ c->d[o[0]+0][o[1]+0][o[2]+0],
- c->d[o[0]+1][o[1]+0][o[2]+0],
- c->d[o[0]+1][o[1]+1][o[2]+0],
- c->d[o[0]+0][o[1]+1][o[2]+0],
- c->d[o[0]+0][o[1]+0][o[2]+1],
- c->d[o[0]+1][o[1]+0][o[2]+1],
- c->d[o[0]+1][o[1]+1][o[2]+1],
- c->d[o[0]+0][o[1]+1][o[2]+1]};
- /* Normal */
+ c->puid = puid;
+ /* Extract infos */
+ const int o[] = {ix.i, iy.i, iz.i};
+ const btScalar d[] = {c->d[o[0] + 0][o[1] + 0][o[2] + 0],
+ c->d[o[0] + 1][o[1] + 0][o[2] + 0],
+ c->d[o[0] + 1][o[1] + 1][o[2] + 0],
+ c->d[o[0] + 0][o[1] + 1][o[2] + 0],
+ c->d[o[0] + 0][o[1] + 0][o[2] + 1],
+ c->d[o[0] + 1][o[1] + 0][o[2] + 1],
+ c->d[o[0] + 1][o[1] + 1][o[2] + 1],
+ c->d[o[0] + 0][o[1] + 1][o[2] + 1]};
+ /* Normal */
#if 1
- const btScalar gx[]={ d[1]-d[0],d[2]-d[3],
- d[5]-d[4],d[6]-d[7]};
- const btScalar gy[]={ d[3]-d[0],d[2]-d[1],
- d[7]-d[4],d[6]-d[5]};
- const btScalar gz[]={ d[4]-d[0],d[5]-d[1],
- d[7]-d[3],d[6]-d[2]};
- normal.setX(Lerp( Lerp(gx[0],gx[1],iy.f),
- Lerp(gx[2],gx[3],iy.f),iz.f));
- normal.setY(Lerp( Lerp(gy[0],gy[1],ix.f),
- Lerp(gy[2],gy[3],ix.f),iz.f));
- normal.setZ(Lerp( Lerp(gz[0],gz[1],ix.f),
- Lerp(gz[2],gz[3],ix.f),iy.f));
- normal = normal.normalized();
+ const btScalar gx[] = {d[1] - d[0], d[2] - d[3],
+ d[5] - d[4], d[6] - d[7]};
+ const btScalar gy[] = {d[3] - d[0], d[2] - d[1],
+ d[7] - d[4], d[6] - d[5]};
+ const btScalar gz[] = {d[4] - d[0], d[5] - d[1],
+ d[7] - d[3], d[6] - d[2]};
+ normal.setX(Lerp(Lerp(gx[0], gx[1], iy.f),
+ Lerp(gx[2], gx[3], iy.f), iz.f));
+ normal.setY(Lerp(Lerp(gy[0], gy[1], ix.f),
+ Lerp(gy[2], gy[3], ix.f), iz.f));
+ normal.setZ(Lerp(Lerp(gz[0], gz[1], ix.f),
+ Lerp(gz[2], gz[3], ix.f), iy.f));
+ normal = normal.normalized();
#else
- normal = btVector3(d[1]-d[0],d[3]-d[0],d[4]-d[0]).normalized();
+ normal = btVector3(d[1] - d[0], d[3] - d[0], d[4] - d[0]).normalized();
#endif
- /* Distance */
- const btScalar d0=Lerp(Lerp(d[0],d[1],ix.f),
- Lerp(d[3],d[2],ix.f),iy.f);
- const btScalar d1=Lerp(Lerp(d[4],d[5],ix.f),
- Lerp(d[7],d[6],ix.f),iy.f);
- return(Lerp(d0,d1,iz.f)-margin);
+ /* Distance */
+ const btScalar d0 = Lerp(Lerp(d[0], d[1], ix.f),
+ Lerp(d[3], d[2], ix.f), iy.f);
+ const btScalar d1 = Lerp(Lerp(d[4], d[5], ix.f),
+ Lerp(d[7], d[6], ix.f), iy.f);
+ return (Lerp(d0, d1, iz.f) - margin);
}
//
- void BuildCell(Cell& c)
+ void BuildCell(Cell& c)
{
- const btVector3 org=btVector3( (btScalar)c.c[0],
- (btScalar)c.c[1],
- (btScalar)c.c[2]) *
- CELLSIZE*voxelsz;
- for(int k=0;k<=CELLSIZE;++k)
+ const btVector3 org = btVector3((btScalar)c.c[0],
+ (btScalar)c.c[1],
+ (btScalar)c.c[2]) *
+ CELLSIZE * voxelsz;
+ for (int k = 0; k <= CELLSIZE; ++k)
{
- const btScalar z=voxelsz*k+org.z();
- for(int j=0;j<=CELLSIZE;++j)
+ const btScalar z = voxelsz * k + org.z();
+ for (int j = 0; j <= CELLSIZE; ++j)
{
- const btScalar y=voxelsz*j+org.y();
- for(int i=0;i<=CELLSIZE;++i)
+ const btScalar y = voxelsz * j + org.y();
+ for (int i = 0; i <= CELLSIZE; ++i)
{
- const btScalar x=voxelsz*i+org.x();
- c.d[i][j][k]=DistanceToShape( btVector3(x,y,z),
- c.pclient);
+ const btScalar x = voxelsz * i + org.x();
+ c.d[i][j][k] = DistanceToShape(btVector3(x, y, z),
+ c.pclient);
}
}
}
}
//
- static inline btScalar DistanceToShape(const btVector3& x,
- const btCollisionShape* shape)
+ static inline btScalar DistanceToShape(const btVector3& x,
+ const btCollisionShape* shape)
{
- btTransform unit;
+ btTransform unit;
unit.setIdentity();
- if(shape->isConvex())
+ if (shape->isConvex())
{
- btGjkEpaSolver2::sResults res;
- const btConvexShape* csh=static_cast<const btConvexShape*>(shape);
- return(btGjkEpaSolver2::SignedDistance(x,0,csh,unit,res));
+ btGjkEpaSolver2::sResults res;
+ const btConvexShape* csh = static_cast<const btConvexShape*>(shape);
+ return (btGjkEpaSolver2::SignedDistance(x, 0, csh, unit, res));
}
- return(0);
+ return (0);
}
//
- static inline IntFrac Decompose(btScalar x)
+ static inline IntFrac Decompose(btScalar x)
{
/* That one need a lot of improvements... */
- /* Remove test, faster floor... */
- IntFrac r;
- x/=CELLSIZE;
- const int o=x<0?(int)(-x+1):0;
- x+=o;r.b=(int)x;
- const btScalar k=(x-r.b)*CELLSIZE;
- r.i=(int)k;r.f=k-r.i;r.b-=o;
- return(r);
+ /* Remove test, faster floor... */
+ IntFrac r;
+ x /= CELLSIZE;
+ const int o = x < 0 ? (int)(-x + 1) : 0;
+ x += o;
+ r.b = (int)x;
+ const btScalar k = (x - r.b) * CELLSIZE;
+ r.i = (int)k;
+ r.f = k - r.i;
+ r.b -= o;
+ return (r);
}
//
- static inline btScalar Lerp(btScalar a,btScalar b,btScalar t)
+ static inline btScalar Lerp(btScalar a, btScalar b, btScalar t)
{
- return(a+(b-a)*t);
+ return (a + (b - a) * t);
}
-
-
//
- static inline unsigned int Hash(int x,int y,int z,const btCollisionShape* shape)
+ static inline unsigned int Hash(int x, int y, int z, const btCollisionShape* shape)
{
struct btS
- {
- int x,y,z;
+ {
+ int x, y, z;
void* p;
};
btS myset;
- myset.x=x;myset.y=y;myset.z=z;myset.p=(void*)shape;
+ myset.x = x;
+ myset.y = y;
+ myset.z = z;
+ myset.p = (void*)shape;
const void* ptr = &myset;
- unsigned int result = HsiehHash<sizeof(btS)/4> (ptr);
-
+ unsigned int result = HsiehHash<sizeof(btS) / 4>(ptr);
return result;
}
};
-
-#endif //BT_SPARSE_SDF_H
+#endif //BT_SPARSE_SDF_H
diff --git a/thirdparty/bullet/LinearMath/TaskScheduler/btTaskScheduler.cpp b/thirdparty/bullet/LinearMath/TaskScheduler/btTaskScheduler.cpp
index 49510d1660..5f1115c402 100644
--- a/thirdparty/bullet/LinearMath/TaskScheduler/btTaskScheduler.cpp
+++ b/thirdparty/bullet/LinearMath/TaskScheduler/btTaskScheduler.cpp
@@ -6,13 +6,11 @@
#include <stdio.h>
#include <algorithm>
-
-
#if BT_THREADSAFE
#include "btThreadSupportInterface.h"
-#if defined( _WIN32 )
+#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
@@ -20,404 +18,399 @@
#endif
-
typedef unsigned long long btU64;
static const int kCacheLineSize = 64;
void btSpinPause()
{
-#if defined( _WIN32 )
- YieldProcessor();
+#if defined(_WIN32)
+ YieldProcessor();
#endif
}
-
struct WorkerThreadStatus
{
- enum Type
- {
- kInvalid,
- kWaitingForWork,
- kWorking,
- kSleeping,
- };
+ enum Type
+ {
+ kInvalid,
+ kWaitingForWork,
+ kWorking,
+ kSleeping,
+ };
};
-
-ATTRIBUTE_ALIGNED64(class) WorkerThreadDirectives
+ATTRIBUTE_ALIGNED64(class)
+WorkerThreadDirectives
{
- static const int kMaxThreadCount = BT_MAX_THREAD_COUNT;
- // directives for all worker threads packed into a single cacheline
- char m_threadDirs[kMaxThreadCount];
+ static const int kMaxThreadCount = BT_MAX_THREAD_COUNT;
+ // directives for all worker threads packed into a single cacheline
+ char m_threadDirs[kMaxThreadCount];
public:
- enum Type
- {
- kInvalid,
- kGoToSleep, // go to sleep
- kStayAwakeButIdle, // wait for not checking job queue
- kScanForJobs, // actively scan job queue for jobs
- };
- WorkerThreadDirectives()
- {
- for ( int i = 0; i < kMaxThreadCount; ++i )
- {
- m_threadDirs[ i ] = 0;
- }
- }
-
- Type getDirective(int threadId)
- {
- btAssert(threadId < kMaxThreadCount);
- return static_cast<Type>(m_threadDirs[threadId]);
- }
-
- void setDirectiveByRange(int threadBegin, int threadEnd, Type dir)
- {
- btAssert( threadBegin < threadEnd );
- btAssert( threadEnd <= kMaxThreadCount );
- char dirChar = static_cast<char>(dir);
- for ( int i = threadBegin; i < threadEnd; ++i )
- {
- m_threadDirs[ i ] = dirChar;
- }
- }
+ enum Type
+ {
+ kInvalid,
+ kGoToSleep, // go to sleep
+ kStayAwakeButIdle, // wait for not checking job queue
+ kScanForJobs, // actively scan job queue for jobs
+ };
+ WorkerThreadDirectives()
+ {
+ for (int i = 0; i < kMaxThreadCount; ++i)
+ {
+ m_threadDirs[i] = 0;
+ }
+ }
+
+ Type getDirective(int threadId)
+ {
+ btAssert(threadId < kMaxThreadCount);
+ return static_cast<Type>(m_threadDirs[threadId]);
+ }
+
+ void setDirectiveByRange(int threadBegin, int threadEnd, Type dir)
+ {
+ btAssert(threadBegin < threadEnd);
+ btAssert(threadEnd <= kMaxThreadCount);
+ char dirChar = static_cast<char>(dir);
+ for (int i = threadBegin; i < threadEnd; ++i)
+ {
+ m_threadDirs[i] = dirChar;
+ }
+ }
};
class JobQueue;
-ATTRIBUTE_ALIGNED64(struct) ThreadLocalStorage
+ATTRIBUTE_ALIGNED64(struct)
+ThreadLocalStorage
{
- int m_threadId;
- WorkerThreadStatus::Type m_status;
- int m_numJobsFinished;
- btSpinMutex m_mutex;
- btScalar m_sumResult;
- WorkerThreadDirectives * m_directive;
- JobQueue* m_queue;
- btClock* m_clock;
- unsigned int m_cooldownTime;
+ int m_threadId;
+ WorkerThreadStatus::Type m_status;
+ int m_numJobsFinished;
+ btSpinMutex m_mutex;
+ btScalar m_sumResult;
+ WorkerThreadDirectives* m_directive;
+ JobQueue* m_queue;
+ btClock* m_clock;
+ unsigned int m_cooldownTime;
};
-
struct IJob
{
- virtual void executeJob(int threadId) = 0;
+ virtual void executeJob(int threadId) = 0;
};
class ParallelForJob : public IJob
{
- const btIParallelForBody* m_body;
- int m_begin;
- int m_end;
+ const btIParallelForBody* m_body;
+ int m_begin;
+ int m_end;
public:
- ParallelForJob( int iBegin, int iEnd, const btIParallelForBody& body )
- {
- m_body = &body;
- m_begin = iBegin;
- m_end = iEnd;
- }
- virtual void executeJob(int threadId) BT_OVERRIDE
- {
- BT_PROFILE( "executeJob" );
-
- // call the functor body to do the work
- m_body->forLoop( m_begin, m_end );
- }
-};
+ ParallelForJob(int iBegin, int iEnd, const btIParallelForBody& body)
+ {
+ m_body = &body;
+ m_begin = iBegin;
+ m_end = iEnd;
+ }
+ virtual void executeJob(int threadId) BT_OVERRIDE
+ {
+ BT_PROFILE("executeJob");
+ // call the functor body to do the work
+ m_body->forLoop(m_begin, m_end);
+ }
+};
class ParallelSumJob : public IJob
{
- const btIParallelSumBody* m_body;
- ThreadLocalStorage* m_threadLocalStoreArray;
- int m_begin;
- int m_end;
+ const btIParallelSumBody* m_body;
+ ThreadLocalStorage* m_threadLocalStoreArray;
+ int m_begin;
+ int m_end;
public:
- ParallelSumJob( int iBegin, int iEnd, const btIParallelSumBody& body, ThreadLocalStorage* tls )
- {
- m_body = &body;
- m_threadLocalStoreArray = tls;
- m_begin = iBegin;
- m_end = iEnd;
- }
- virtual void executeJob( int threadId ) BT_OVERRIDE
- {
- BT_PROFILE( "executeJob" );
-
- // call the functor body to do the work
- btScalar val = m_body->sumLoop( m_begin, m_end );
+ ParallelSumJob(int iBegin, int iEnd, const btIParallelSumBody& body, ThreadLocalStorage* tls)
+ {
+ m_body = &body;
+ m_threadLocalStoreArray = tls;
+ m_begin = iBegin;
+ m_end = iEnd;
+ }
+ virtual void executeJob(int threadId) BT_OVERRIDE
+ {
+ BT_PROFILE("executeJob");
+
+ // call the functor body to do the work
+ btScalar val = m_body->sumLoop(m_begin, m_end);
#if BT_PARALLEL_SUM_DETERMINISTISM
- // by truncating bits of the result, we can make the parallelSum deterministic (at the expense of precision)
- const float TRUNC_SCALE = float(1<<19);
- val = floor(val*TRUNC_SCALE+0.5f)/TRUNC_SCALE; // truncate some bits
+ // by truncating bits of the result, we can make the parallelSum deterministic (at the expense of precision)
+ const float TRUNC_SCALE = float(1 << 19);
+ val = floor(val * TRUNC_SCALE + 0.5f) / TRUNC_SCALE; // truncate some bits
#endif
- m_threadLocalStoreArray[threadId].m_sumResult += val;
- }
+ m_threadLocalStoreArray[threadId].m_sumResult += val;
+ }
};
-
-ATTRIBUTE_ALIGNED64(class) JobQueue
+ATTRIBUTE_ALIGNED64(class)
+JobQueue
{
- btThreadSupportInterface* m_threadSupport;
- btCriticalSection* m_queueLock;
- btSpinMutex m_mutex;
-
- btAlignedObjectArray<IJob*> m_jobQueue;
- char* m_jobMem;
- int m_jobMemSize;
- bool m_queueIsEmpty;
- int m_tailIndex;
- int m_headIndex;
- int m_allocSize;
- bool m_useSpinMutex;
- btAlignedObjectArray<JobQueue*> m_neighborContexts;
- char m_cachePadding[kCacheLineSize]; // prevent false sharing
-
- void freeJobMem()
- {
- if ( m_jobMem )
- {
- // free old
- btAlignedFree(m_jobMem);
- m_jobMem = NULL;
- }
- }
- void resizeJobMem(int newSize)
- {
- if (newSize > m_jobMemSize)
- {
- freeJobMem();
- m_jobMem = static_cast<char*>(btAlignedAlloc(newSize, kCacheLineSize));
- m_jobMemSize = newSize;
- }
- }
+ btThreadSupportInterface* m_threadSupport;
+ btCriticalSection* m_queueLock;
+ btSpinMutex m_mutex;
+
+ btAlignedObjectArray<IJob*> m_jobQueue;
+ char* m_jobMem;
+ int m_jobMemSize;
+ bool m_queueIsEmpty;
+ int m_tailIndex;
+ int m_headIndex;
+ int m_allocSize;
+ bool m_useSpinMutex;
+ btAlignedObjectArray<JobQueue*> m_neighborContexts;
+ char m_cachePadding[kCacheLineSize]; // prevent false sharing
+
+ void freeJobMem()
+ {
+ if (m_jobMem)
+ {
+ // free old
+ btAlignedFree(m_jobMem);
+ m_jobMem = NULL;
+ }
+ }
+ void resizeJobMem(int newSize)
+ {
+ if (newSize > m_jobMemSize)
+ {
+ freeJobMem();
+ m_jobMem = static_cast<char*>(btAlignedAlloc(newSize, kCacheLineSize));
+ m_jobMemSize = newSize;
+ }
+ }
public:
-
- JobQueue()
- {
- m_jobMem = NULL;
- m_jobMemSize = 0;
- m_threadSupport = NULL;
- m_queueLock = NULL;
- m_headIndex = 0;
- m_tailIndex = 0;
- m_useSpinMutex = false;
- }
- ~JobQueue()
- {
+ JobQueue()
+ {
+ m_jobMem = NULL;
+ m_jobMemSize = 0;
+ m_threadSupport = NULL;
+ m_queueLock = NULL;
+ m_headIndex = 0;
+ m_tailIndex = 0;
+ m_useSpinMutex = false;
+ }
+ ~JobQueue()
+ {
exit();
- }
+ }
void exit()
- {
+ {
freeJobMem();
- if (m_queueLock && m_threadSupport)
- {
- m_threadSupport->deleteCriticalSection(m_queueLock);
- m_queueLock = NULL;
+ if (m_queueLock && m_threadSupport)
+ {
+ m_threadSupport->deleteCriticalSection(m_queueLock);
+ m_queueLock = NULL;
m_threadSupport = 0;
- }
- }
-
- void init(btThreadSupportInterface* threadSup, btAlignedObjectArray<JobQueue>* contextArray)
- {
- m_threadSupport = threadSup;
- if (threadSup)
- {
- m_queueLock = m_threadSupport->createCriticalSection();
- }
- setupJobStealing(contextArray, contextArray->size());
- }
- void setupJobStealing(btAlignedObjectArray<JobQueue>* contextArray, int numActiveContexts)
- {
- btAlignedObjectArray<JobQueue>& contexts = *contextArray;
- int selfIndex = 0;
- for (int i = 0; i < contexts.size(); ++i)
- {
- if ( this == &contexts[ i ] )
- {
- selfIndex = i;
- break;
- }
- }
- int numNeighbors = btMin(2, contexts.size() - 1);
- int neighborOffsets[ ] = {-1, 1, -2, 2, -3, 3};
- int numOffsets = sizeof(neighborOffsets)/sizeof(neighborOffsets[0]);
- m_neighborContexts.reserve( numNeighbors );
- m_neighborContexts.resizeNoInitialize(0);
- for (int i = 0; i < numOffsets && m_neighborContexts.size() < numNeighbors; i++)
- {
- int neighborIndex = selfIndex + neighborOffsets[i];
- if ( neighborIndex >= 0 && neighborIndex < numActiveContexts)
- {
- m_neighborContexts.push_back( &contexts[ neighborIndex ] );
- }
- }
- }
-
- bool isQueueEmpty() const {return m_queueIsEmpty;}
- void lockQueue()
- {
- if ( m_useSpinMutex )
- {
- m_mutex.lock();
- }
- else
- {
- m_queueLock->lock();
- }
- }
- void unlockQueue()
- {
- if ( m_useSpinMutex )
- {
- m_mutex.unlock();
- }
- else
- {
- m_queueLock->unlock();
- }
- }
- void clearQueue(int jobCount, int jobSize)
- {
- lockQueue();
- m_headIndex = 0;
- m_tailIndex = 0;
- m_allocSize = 0;
- m_queueIsEmpty = true;
- int jobBufSize = jobSize * jobCount;
- // make sure we have enough memory allocated to store jobs
- if ( jobBufSize > m_jobMemSize )
- {
- resizeJobMem( jobBufSize );
- }
- // make sure job queue is big enough
- if ( jobCount > m_jobQueue.capacity() )
- {
- m_jobQueue.reserve( jobCount );
- }
- unlockQueue();
- m_jobQueue.resizeNoInitialize( 0 );
- }
- void* allocJobMem(int jobSize)
- {
- btAssert(m_jobMemSize >= (m_allocSize + jobSize));
- void* jobMem = &m_jobMem[m_allocSize];
- m_allocSize += jobSize;
- return jobMem;
- }
- void submitJob( IJob* job )
- {
- btAssert( reinterpret_cast<char*>( job ) >= &m_jobMem[ 0 ] && reinterpret_cast<char*>( job ) < &m_jobMem[ 0 ] + m_allocSize );
- m_jobQueue.push_back( job );
- lockQueue();
- m_tailIndex++;
- m_queueIsEmpty = false;
- unlockQueue();
- }
- IJob* consumeJobFromOwnQueue()
- {
- if ( m_queueIsEmpty )
- {
- // lock free path. even if this is taken erroneously it isn't harmful
- return NULL;
- }
- IJob* job = NULL;
- lockQueue();
- if ( !m_queueIsEmpty )
- {
- job = m_jobQueue[ m_headIndex++ ];
- btAssert( reinterpret_cast<char*>( job ) >= &m_jobMem[ 0 ] && reinterpret_cast<char*>( job ) < &m_jobMem[ 0 ] + m_allocSize );
- if ( m_headIndex == m_tailIndex )
- {
- m_queueIsEmpty = true;
- }
- }
- unlockQueue();
- return job;
- }
- IJob* consumeJob()
- {
- if (IJob* job = consumeJobFromOwnQueue())
- {
- return job;
- }
- // own queue is empty, try to steal from neighbor
- for (int i = 0; i < m_neighborContexts.size(); ++i)
- {
- JobQueue* otherContext = m_neighborContexts[ i ];
- if ( IJob* job = otherContext->consumeJobFromOwnQueue() )
- {
- return job;
- }
- }
- return NULL;
- }
-};
+ }
+ }
+ void init(btThreadSupportInterface * threadSup, btAlignedObjectArray<JobQueue> * contextArray)
+ {
+ m_threadSupport = threadSup;
+ if (threadSup)
+ {
+ m_queueLock = m_threadSupport->createCriticalSection();
+ }
+ setupJobStealing(contextArray, contextArray->size());
+ }
+ void setupJobStealing(btAlignedObjectArray<JobQueue> * contextArray, int numActiveContexts)
+ {
+ btAlignedObjectArray<JobQueue>& contexts = *contextArray;
+ int selfIndex = 0;
+ for (int i = 0; i < contexts.size(); ++i)
+ {
+ if (this == &contexts[i])
+ {
+ selfIndex = i;
+ break;
+ }
+ }
+ int numNeighbors = btMin(2, contexts.size() - 1);
+ int neighborOffsets[] = {-1, 1, -2, 2, -3, 3};
+ int numOffsets = sizeof(neighborOffsets) / sizeof(neighborOffsets[0]);
+ m_neighborContexts.reserve(numNeighbors);
+ m_neighborContexts.resizeNoInitialize(0);
+ for (int i = 0; i < numOffsets && m_neighborContexts.size() < numNeighbors; i++)
+ {
+ int neighborIndex = selfIndex + neighborOffsets[i];
+ if (neighborIndex >= 0 && neighborIndex < numActiveContexts)
+ {
+ m_neighborContexts.push_back(&contexts[neighborIndex]);
+ }
+ }
+ }
+
+ bool isQueueEmpty() const { return m_queueIsEmpty; }
+ void lockQueue()
+ {
+ if (m_useSpinMutex)
+ {
+ m_mutex.lock();
+ }
+ else
+ {
+ m_queueLock->lock();
+ }
+ }
+ void unlockQueue()
+ {
+ if (m_useSpinMutex)
+ {
+ m_mutex.unlock();
+ }
+ else
+ {
+ m_queueLock->unlock();
+ }
+ }
+ void clearQueue(int jobCount, int jobSize)
+ {
+ lockQueue();
+ m_headIndex = 0;
+ m_tailIndex = 0;
+ m_allocSize = 0;
+ m_queueIsEmpty = true;
+ int jobBufSize = jobSize * jobCount;
+ // make sure we have enough memory allocated to store jobs
+ if (jobBufSize > m_jobMemSize)
+ {
+ resizeJobMem(jobBufSize);
+ }
+ // make sure job queue is big enough
+ if (jobCount > m_jobQueue.capacity())
+ {
+ m_jobQueue.reserve(jobCount);
+ }
+ unlockQueue();
+ m_jobQueue.resizeNoInitialize(0);
+ }
+ void* allocJobMem(int jobSize)
+ {
+ btAssert(m_jobMemSize >= (m_allocSize + jobSize));
+ void* jobMem = &m_jobMem[m_allocSize];
+ m_allocSize += jobSize;
+ return jobMem;
+ }
+ void submitJob(IJob * job)
+ {
+ btAssert(reinterpret_cast<char*>(job) >= &m_jobMem[0] && reinterpret_cast<char*>(job) < &m_jobMem[0] + m_allocSize);
+ m_jobQueue.push_back(job);
+ lockQueue();
+ m_tailIndex++;
+ m_queueIsEmpty = false;
+ unlockQueue();
+ }
+ IJob* consumeJobFromOwnQueue()
+ {
+ if (m_queueIsEmpty)
+ {
+ // lock free path. even if this is taken erroneously it isn't harmful
+ return NULL;
+ }
+ IJob* job = NULL;
+ lockQueue();
+ if (!m_queueIsEmpty)
+ {
+ job = m_jobQueue[m_headIndex++];
+ btAssert(reinterpret_cast<char*>(job) >= &m_jobMem[0] && reinterpret_cast<char*>(job) < &m_jobMem[0] + m_allocSize);
+ if (m_headIndex == m_tailIndex)
+ {
+ m_queueIsEmpty = true;
+ }
+ }
+ unlockQueue();
+ return job;
+ }
+ IJob* consumeJob()
+ {
+ if (IJob* job = consumeJobFromOwnQueue())
+ {
+ return job;
+ }
+ // own queue is empty, try to steal from neighbor
+ for (int i = 0; i < m_neighborContexts.size(); ++i)
+ {
+ JobQueue* otherContext = m_neighborContexts[i];
+ if (IJob* job = otherContext->consumeJobFromOwnQueue())
+ {
+ return job;
+ }
+ }
+ return NULL;
+ }
+};
-static void WorkerThreadFunc( void* userPtr )
+static void WorkerThreadFunc(void* userPtr)
{
- BT_PROFILE( "WorkerThreadFunc" );
- ThreadLocalStorage* localStorage = (ThreadLocalStorage*) userPtr;
- JobQueue* jobQueue = localStorage->m_queue;
-
- bool shouldSleep = false;
- int threadId = localStorage->m_threadId;
- while (! shouldSleep)
- {
- // do work
- localStorage->m_mutex.lock();
- while ( IJob* job = jobQueue->consumeJob() )
- {
- localStorage->m_status = WorkerThreadStatus::kWorking;
- job->executeJob( threadId );
- localStorage->m_numJobsFinished++;
- }
- localStorage->m_status = WorkerThreadStatus::kWaitingForWork;
- localStorage->m_mutex.unlock();
- btU64 clockStart = localStorage->m_clock->getTimeMicroseconds();
- // while queue is empty,
- while (jobQueue->isQueueEmpty())
- {
- // todo: spin wait a bit to avoid hammering the empty queue
- btSpinPause();
- if ( localStorage->m_directive->getDirective(threadId) == WorkerThreadDirectives::kGoToSleep )
- {
- shouldSleep = true;
- break;
- }
- // if jobs are incoming,
- if ( localStorage->m_directive->getDirective( threadId ) == WorkerThreadDirectives::kScanForJobs )
- {
- clockStart = localStorage->m_clock->getTimeMicroseconds(); // reset clock
- }
- else
- {
- for ( int i = 0; i < 50; ++i )
- {
- btSpinPause();
- btSpinPause();
- btSpinPause();
- btSpinPause();
- if (localStorage->m_directive->getDirective( threadId ) == WorkerThreadDirectives::kScanForJobs || !jobQueue->isQueueEmpty())
- {
- break;
- }
- }
- // if no jobs incoming and queue has been empty for the cooldown time, sleep
- btU64 timeElapsed = localStorage->m_clock->getTimeMicroseconds() - clockStart;
- if (timeElapsed > localStorage->m_cooldownTime)
- {
- shouldSleep = true;
- break;
- }
- }
- }
- }
+ BT_PROFILE("WorkerThreadFunc");
+ ThreadLocalStorage* localStorage = (ThreadLocalStorage*)userPtr;
+ JobQueue* jobQueue = localStorage->m_queue;
+
+ bool shouldSleep = false;
+ int threadId = localStorage->m_threadId;
+ while (!shouldSleep)
+ {
+ // do work
+ localStorage->m_mutex.lock();
+ while (IJob* job = jobQueue->consumeJob())
+ {
+ localStorage->m_status = WorkerThreadStatus::kWorking;
+ job->executeJob(threadId);
+ localStorage->m_numJobsFinished++;
+ }
+ localStorage->m_status = WorkerThreadStatus::kWaitingForWork;
+ localStorage->m_mutex.unlock();
+ btU64 clockStart = localStorage->m_clock->getTimeMicroseconds();
+ // while queue is empty,
+ while (jobQueue->isQueueEmpty())
+ {
+ // todo: spin wait a bit to avoid hammering the empty queue
+ btSpinPause();
+ if (localStorage->m_directive->getDirective(threadId) == WorkerThreadDirectives::kGoToSleep)
+ {
+ shouldSleep = true;
+ break;
+ }
+ // if jobs are incoming,
+ if (localStorage->m_directive->getDirective(threadId) == WorkerThreadDirectives::kScanForJobs)
+ {
+ clockStart = localStorage->m_clock->getTimeMicroseconds(); // reset clock
+ }
+ else
+ {
+ for (int i = 0; i < 50; ++i)
+ {
+ btSpinPause();
+ btSpinPause();
+ btSpinPause();
+ btSpinPause();
+ if (localStorage->m_directive->getDirective(threadId) == WorkerThreadDirectives::kScanForJobs || !jobQueue->isQueueEmpty())
+ {
+ break;
+ }
+ }
+ // if no jobs incoming and queue has been empty for the cooldown time, sleep
+ btU64 timeElapsed = localStorage->m_clock->getTimeMicroseconds() - clockStart;
+ if (timeElapsed > localStorage->m_cooldownTime)
+ {
+ shouldSleep = true;
+ break;
+ }
+ }
+ }
+ }
{
BT_PROFILE("sleep");
// go sleep
@@ -427,376 +420,373 @@ static void WorkerThreadFunc( void* userPtr )
}
}
-
class btTaskSchedulerDefault : public btITaskScheduler
{
- btThreadSupportInterface* m_threadSupport;
- WorkerThreadDirectives* m_workerDirective;
- btAlignedObjectArray<JobQueue> m_jobQueues;
- btAlignedObjectArray<JobQueue*> m_perThreadJobQueues;
- btAlignedObjectArray<ThreadLocalStorage> m_threadLocalStorage;
- btSpinMutex m_antiNestingLock; // prevent nested parallel-for
- btClock m_clock;
- int m_numThreads;
- int m_numWorkerThreads;
- int m_numActiveJobQueues;
- int m_maxNumThreads;
- int m_numJobs;
- static const int kFirstWorkerThreadId = 1;
+ btThreadSupportInterface* m_threadSupport;
+ WorkerThreadDirectives* m_workerDirective;
+ btAlignedObjectArray<JobQueue> m_jobQueues;
+ btAlignedObjectArray<JobQueue*> m_perThreadJobQueues;
+ btAlignedObjectArray<ThreadLocalStorage> m_threadLocalStorage;
+ btSpinMutex m_antiNestingLock; // prevent nested parallel-for
+ btClock m_clock;
+ int m_numThreads;
+ int m_numWorkerThreads;
+ int m_numActiveJobQueues;
+ int m_maxNumThreads;
+ int m_numJobs;
+ static const int kFirstWorkerThreadId = 1;
+
public:
+ btTaskSchedulerDefault() : btITaskScheduler("ThreadSupport")
+ {
+ m_threadSupport = NULL;
+ m_workerDirective = NULL;
+ }
- btTaskSchedulerDefault() : btITaskScheduler("ThreadSupport")
- {
- m_threadSupport = NULL;
- m_workerDirective = NULL;
- }
-
- virtual ~btTaskSchedulerDefault()
- {
- waitForWorkersToSleep();
-
- for ( int i = 0; i < m_jobQueues.size(); ++i )
- {
- m_jobQueues[i].exit();
- }
-
- if (m_threadSupport)
- {
- delete m_threadSupport;
- m_threadSupport = NULL;
- }
- if (m_workerDirective)
- {
- btAlignedFree(m_workerDirective);
- m_workerDirective = NULL;
- }
- }
-
- void init()
- {
- btThreadSupportInterface::ConstructionInfo constructionInfo( "TaskScheduler", WorkerThreadFunc );
- m_threadSupport = btThreadSupportInterface::create( constructionInfo );
- m_workerDirective = static_cast<WorkerThreadDirectives*>(btAlignedAlloc(sizeof(*m_workerDirective), 64));
-
- m_numWorkerThreads = m_threadSupport->getNumWorkerThreads();
- m_maxNumThreads = m_threadSupport->getNumWorkerThreads() + 1;
- m_numThreads = m_maxNumThreads;
- // ideal to have one job queue for each physical processor (except for the main thread which needs no queue)
- int numThreadsPerQueue = m_threadSupport->getLogicalToPhysicalCoreRatio();
- int numJobQueues = (numThreadsPerQueue == 1) ? (m_maxNumThreads-1) : (m_maxNumThreads / numThreadsPerQueue);
- m_jobQueues.resize(numJobQueues);
- m_numActiveJobQueues = numJobQueues;
- for ( int i = 0; i < m_jobQueues.size(); ++i )
- {
- m_jobQueues[i].init( m_threadSupport, &m_jobQueues );
- }
- m_perThreadJobQueues.resize(m_numThreads);
- for ( int i = 0; i < m_numThreads; i++ )
- {
- JobQueue* jq = NULL;
- // only worker threads get a job queue
- if (i > 0)
- {
- if (numThreadsPerQueue == 1)
- {
- // one queue per worker thread
- jq = &m_jobQueues[ i - kFirstWorkerThreadId ];
- }
- else
- {
- // 2 threads share each queue
- jq = &m_jobQueues[ i / numThreadsPerQueue ];
- }
- }
- m_perThreadJobQueues[i] = jq;
- }
- m_threadLocalStorage.resize(m_numThreads);
- for ( int i = 0; i < m_numThreads; i++ )
- {
- ThreadLocalStorage& storage = m_threadLocalStorage[i];
- storage.m_threadId = i;
- storage.m_directive = m_workerDirective;
- storage.m_status = WorkerThreadStatus::kSleeping;
- storage.m_cooldownTime = 100; // 100 microseconds, threads go to sleep after this long if they have nothing to do
- storage.m_clock = &m_clock;
- storage.m_queue = m_perThreadJobQueues[i];
- }
- setWorkerDirectives( WorkerThreadDirectives::kGoToSleep ); // no work for them yet
- setNumThreads( m_threadSupport->getCacheFriendlyNumThreads() );
- }
-
- void setWorkerDirectives(WorkerThreadDirectives::Type dir)
- {
- m_workerDirective->setDirectiveByRange(kFirstWorkerThreadId, m_numThreads, dir);
- }
-
- virtual int getMaxNumThreads() const BT_OVERRIDE
- {
- return m_maxNumThreads;
- }
-
- virtual int getNumThreads() const BT_OVERRIDE
- {
- return m_numThreads;
- }
-
- virtual void setNumThreads( int numThreads ) BT_OVERRIDE
- {
- m_numThreads = btMax( btMin(numThreads, int(m_maxNumThreads)), 1 );
- m_numWorkerThreads = m_numThreads - 1;
- m_numActiveJobQueues = 0;
- // if there is at least 1 worker,
- if ( m_numWorkerThreads > 0 )
- {
- // re-setup job stealing between queues to avoid attempting to steal from an inactive job queue
- JobQueue* lastActiveContext = m_perThreadJobQueues[ m_numThreads - 1 ];
- int iLastActiveContext = lastActiveContext - &m_jobQueues[0];
- m_numActiveJobQueues = iLastActiveContext + 1;
- for ( int i = 0; i < m_jobQueues.size(); ++i )
- {
- m_jobQueues[ i ].setupJobStealing( &m_jobQueues, m_numActiveJobQueues );
- }
- }
- m_workerDirective->setDirectiveByRange(m_numThreads, BT_MAX_THREAD_COUNT, WorkerThreadDirectives::kGoToSleep);
- }
-
- void waitJobs()
- {
- BT_PROFILE( "waitJobs" );
- // have the main thread work until the job queues are empty
- int numMainThreadJobsFinished = 0;
- for ( int i = 0; i < m_numActiveJobQueues; ++i )
- {
- while ( IJob* job = m_jobQueues[i].consumeJob() )
- {
- job->executeJob( 0 );
- numMainThreadJobsFinished++;
- }
- }
-
- // done with jobs for now, tell workers to rest (but not sleep)
- setWorkerDirectives( WorkerThreadDirectives::kStayAwakeButIdle );
-
- btU64 clockStart = m_clock.getTimeMicroseconds();
- // wait for workers to finish any jobs in progress
- while ( true )
- {
- int numWorkerJobsFinished = 0;
- for ( int iThread = kFirstWorkerThreadId; iThread < m_numThreads; ++iThread )
- {
- ThreadLocalStorage* storage = &m_threadLocalStorage[iThread];
- storage->m_mutex.lock();
- numWorkerJobsFinished += storage->m_numJobsFinished;
- storage->m_mutex.unlock();
- }
- if (numWorkerJobsFinished + numMainThreadJobsFinished == m_numJobs)
- {
- break;
- }
- btU64 timeElapsed = m_clock.getTimeMicroseconds() - clockStart;
- btAssert(timeElapsed < 1000);
- if (timeElapsed > 100000)
- {
- break;
- }
- btSpinPause();
- }
- }
-
- void wakeWorkers(int numWorkersToWake)
- {
- BT_PROFILE( "wakeWorkers" );
- btAssert( m_workerDirective->getDirective(1) == WorkerThreadDirectives::kScanForJobs );
- int numDesiredWorkers = btMin(numWorkersToWake, m_numWorkerThreads);
- int numActiveWorkers = 0;
- for ( int iWorker = 0; iWorker < m_numWorkerThreads; ++iWorker )
- {
- // note this count of active workers is not necessarily totally reliable, because a worker thread could be
- // just about to put itself to sleep. So we may on occasion fail to wake up all the workers. It should be rare.
- ThreadLocalStorage& storage = m_threadLocalStorage[ kFirstWorkerThreadId + iWorker ];
- if (storage.m_status != WorkerThreadStatus::kSleeping)
- {
- numActiveWorkers++;
- }
- }
- for ( int iWorker = 0; iWorker < m_numWorkerThreads && numActiveWorkers < numDesiredWorkers; ++iWorker )
- {
- ThreadLocalStorage& storage = m_threadLocalStorage[ kFirstWorkerThreadId + iWorker ];
- if (storage.m_status == WorkerThreadStatus::kSleeping)
- {
- m_threadSupport->runTask( iWorker, &storage );
- numActiveWorkers++;
- }
- }
- }
-
- void waitForWorkersToSleep()
- {
- BT_PROFILE( "waitForWorkersToSleep" );
- setWorkerDirectives( WorkerThreadDirectives::kGoToSleep );
- m_threadSupport->waitForAllTasks();
- for ( int i = kFirstWorkerThreadId; i < m_numThreads; i++ )
- {
- ThreadLocalStorage& storage = m_threadLocalStorage[i];
- btAssert( storage.m_status == WorkerThreadStatus::kSleeping );
- }
- }
-
- virtual void sleepWorkerThreadsHint() BT_OVERRIDE
- {
- BT_PROFILE( "sleepWorkerThreadsHint" );
- // hint the task scheduler that we may not be using these threads for a little while
- setWorkerDirectives( WorkerThreadDirectives::kGoToSleep );
- }
-
- void prepareWorkerThreads()
- {
- for ( int i = kFirstWorkerThreadId; i < m_numThreads; ++i )
- {
- ThreadLocalStorage& storage = m_threadLocalStorage[i];
- storage.m_mutex.lock();
- storage.m_numJobsFinished = 0;
- storage.m_mutex.unlock();
- }
- setWorkerDirectives( WorkerThreadDirectives::kScanForJobs );
- }
-
- virtual void parallelFor( int iBegin, int iEnd, int grainSize, const btIParallelForBody& body ) BT_OVERRIDE
- {
- BT_PROFILE( "parallelFor_ThreadSupport" );
- btAssert( iEnd >= iBegin );
- btAssert( grainSize >= 1 );
- int iterationCount = iEnd - iBegin;
- if ( iterationCount > grainSize && m_numWorkerThreads > 0 && m_antiNestingLock.tryLock() )
- {
- typedef ParallelForJob JobType;
- int jobCount = ( iterationCount + grainSize - 1 ) / grainSize;
- m_numJobs = jobCount;
- btAssert( jobCount >= 2 ); // need more than one job for multithreading
- int jobSize = sizeof( JobType );
-
- for (int i = 0; i < m_numActiveJobQueues; ++i)
- {
- m_jobQueues[i].clearQueue( jobCount, jobSize );
- }
- // prepare worker threads for incoming work
- prepareWorkerThreads();
- // submit all of the jobs
- int iJob = 0;
- int iThread = kFirstWorkerThreadId; // first worker thread
- for ( int i = iBegin; i < iEnd; i += grainSize )
- {
- btAssert( iJob < jobCount );
- int iE = btMin( i + grainSize, iEnd );
- JobQueue* jq = m_perThreadJobQueues[ iThread ];
- btAssert(jq);
- btAssert((jq - &m_jobQueues[0]) < m_numActiveJobQueues);
- void* jobMem = jq->allocJobMem(jobSize);
- JobType* job = new ( jobMem ) ParallelForJob( i, iE, body ); // placement new
- jq->submitJob( job );
- iJob++;
- iThread++;
- if ( iThread >= m_numThreads )
- {
- iThread = kFirstWorkerThreadId; // first worker thread
- }
- }
- wakeWorkers( jobCount - 1 );
-
- // put the main thread to work on emptying the job queue and then wait for all workers to finish
- waitJobs();
- m_antiNestingLock.unlock();
- }
- else
- {
- BT_PROFILE( "parallelFor_mainThread" );
- // just run on main thread
- body.forLoop( iBegin, iEnd );
- }
- }
- virtual btScalar parallelSum( int iBegin, int iEnd, int grainSize, const btIParallelSumBody& body ) BT_OVERRIDE
- {
- BT_PROFILE( "parallelSum_ThreadSupport" );
- btAssert( iEnd >= iBegin );
- btAssert( grainSize >= 1 );
- int iterationCount = iEnd - iBegin;
- if ( iterationCount > grainSize && m_numWorkerThreads > 0 && m_antiNestingLock.tryLock() )
- {
- typedef ParallelSumJob JobType;
- int jobCount = ( iterationCount + grainSize - 1 ) / grainSize;
- m_numJobs = jobCount;
- btAssert( jobCount >= 2 ); // need more than one job for multithreading
- int jobSize = sizeof( JobType );
- for (int i = 0; i < m_numActiveJobQueues; ++i)
- {
- m_jobQueues[i].clearQueue( jobCount, jobSize );
- }
-
- // initialize summation
- for ( int iThread = 0; iThread < m_numThreads; ++iThread )
- {
- m_threadLocalStorage[iThread].m_sumResult = btScalar(0);
- }
-
- // prepare worker threads for incoming work
- prepareWorkerThreads();
- // submit all of the jobs
- int iJob = 0;
- int iThread = kFirstWorkerThreadId; // first worker thread
- for ( int i = iBegin; i < iEnd; i += grainSize )
- {
- btAssert( iJob < jobCount );
- int iE = btMin( i + grainSize, iEnd );
- JobQueue* jq = m_perThreadJobQueues[ iThread ];
- btAssert(jq);
- btAssert((jq - &m_jobQueues[0]) < m_numActiveJobQueues);
- void* jobMem = jq->allocJobMem(jobSize);
- JobType* job = new ( jobMem ) ParallelSumJob( i, iE, body, &m_threadLocalStorage[0] ); // placement new
- jq->submitJob( job );
- iJob++;
- iThread++;
- if ( iThread >= m_numThreads )
- {
- iThread = kFirstWorkerThreadId; // first worker thread
- }
- }
- wakeWorkers( jobCount - 1 );
-
- // put the main thread to work on emptying the job queue and then wait for all workers to finish
- waitJobs();
-
- // add up all the thread sums
- btScalar sum = btScalar(0);
- for ( int iThread = 0; iThread < m_numThreads; ++iThread )
- {
- sum += m_threadLocalStorage[ iThread ].m_sumResult;
- }
- m_antiNestingLock.unlock();
- return sum;
- }
- else
- {
- BT_PROFILE( "parallelSum_mainThread" );
- // just run on main thread
- return body.sumLoop( iBegin, iEnd );
- }
- }
-};
+ virtual ~btTaskSchedulerDefault()
+ {
+ waitForWorkersToSleep();
+
+ for (int i = 0; i < m_jobQueues.size(); ++i)
+ {
+ m_jobQueues[i].exit();
+ }
+
+ if (m_threadSupport)
+ {
+ delete m_threadSupport;
+ m_threadSupport = NULL;
+ }
+ if (m_workerDirective)
+ {
+ btAlignedFree(m_workerDirective);
+ m_workerDirective = NULL;
+ }
+ }
+ void init()
+ {
+ btThreadSupportInterface::ConstructionInfo constructionInfo("TaskScheduler", WorkerThreadFunc);
+ m_threadSupport = btThreadSupportInterface::create(constructionInfo);
+ m_workerDirective = static_cast<WorkerThreadDirectives*>(btAlignedAlloc(sizeof(*m_workerDirective), 64));
+
+ m_numWorkerThreads = m_threadSupport->getNumWorkerThreads();
+ m_maxNumThreads = m_threadSupport->getNumWorkerThreads() + 1;
+ m_numThreads = m_maxNumThreads;
+ // ideal to have one job queue for each physical processor (except for the main thread which needs no queue)
+ int numThreadsPerQueue = m_threadSupport->getLogicalToPhysicalCoreRatio();
+ int numJobQueues = (numThreadsPerQueue == 1) ? (m_maxNumThreads - 1) : (m_maxNumThreads / numThreadsPerQueue);
+ m_jobQueues.resize(numJobQueues);
+ m_numActiveJobQueues = numJobQueues;
+ for (int i = 0; i < m_jobQueues.size(); ++i)
+ {
+ m_jobQueues[i].init(m_threadSupport, &m_jobQueues);
+ }
+ m_perThreadJobQueues.resize(m_numThreads);
+ for (int i = 0; i < m_numThreads; i++)
+ {
+ JobQueue* jq = NULL;
+ // only worker threads get a job queue
+ if (i > 0)
+ {
+ if (numThreadsPerQueue == 1)
+ {
+ // one queue per worker thread
+ jq = &m_jobQueues[i - kFirstWorkerThreadId];
+ }
+ else
+ {
+ // 2 threads share each queue
+ jq = &m_jobQueues[i / numThreadsPerQueue];
+ }
+ }
+ m_perThreadJobQueues[i] = jq;
+ }
+ m_threadLocalStorage.resize(m_numThreads);
+ for (int i = 0; i < m_numThreads; i++)
+ {
+ ThreadLocalStorage& storage = m_threadLocalStorage[i];
+ storage.m_threadId = i;
+ storage.m_directive = m_workerDirective;
+ storage.m_status = WorkerThreadStatus::kSleeping;
+ storage.m_cooldownTime = 100; // 100 microseconds, threads go to sleep after this long if they have nothing to do
+ storage.m_clock = &m_clock;
+ storage.m_queue = m_perThreadJobQueues[i];
+ }
+ setWorkerDirectives(WorkerThreadDirectives::kGoToSleep); // no work for them yet
+ setNumThreads(m_threadSupport->getCacheFriendlyNumThreads());
+ }
+
+ void setWorkerDirectives(WorkerThreadDirectives::Type dir)
+ {
+ m_workerDirective->setDirectiveByRange(kFirstWorkerThreadId, m_numThreads, dir);
+ }
+
+ virtual int getMaxNumThreads() const BT_OVERRIDE
+ {
+ return m_maxNumThreads;
+ }
+ virtual int getNumThreads() const BT_OVERRIDE
+ {
+ return m_numThreads;
+ }
+
+ virtual void setNumThreads(int numThreads) BT_OVERRIDE
+ {
+ m_numThreads = btMax(btMin(numThreads, int(m_maxNumThreads)), 1);
+ m_numWorkerThreads = m_numThreads - 1;
+ m_numActiveJobQueues = 0;
+ // if there is at least 1 worker,
+ if (m_numWorkerThreads > 0)
+ {
+ // re-setup job stealing between queues to avoid attempting to steal from an inactive job queue
+ JobQueue* lastActiveContext = m_perThreadJobQueues[m_numThreads - 1];
+ int iLastActiveContext = lastActiveContext - &m_jobQueues[0];
+ m_numActiveJobQueues = iLastActiveContext + 1;
+ for (int i = 0; i < m_jobQueues.size(); ++i)
+ {
+ m_jobQueues[i].setupJobStealing(&m_jobQueues, m_numActiveJobQueues);
+ }
+ }
+ m_workerDirective->setDirectiveByRange(m_numThreads, BT_MAX_THREAD_COUNT, WorkerThreadDirectives::kGoToSleep);
+ }
+
+ void waitJobs()
+ {
+ BT_PROFILE("waitJobs");
+ // have the main thread work until the job queues are empty
+ int numMainThreadJobsFinished = 0;
+ for (int i = 0; i < m_numActiveJobQueues; ++i)
+ {
+ while (IJob* job = m_jobQueues[i].consumeJob())
+ {
+ job->executeJob(0);
+ numMainThreadJobsFinished++;
+ }
+ }
+
+ // done with jobs for now, tell workers to rest (but not sleep)
+ setWorkerDirectives(WorkerThreadDirectives::kStayAwakeButIdle);
+
+ btU64 clockStart = m_clock.getTimeMicroseconds();
+ // wait for workers to finish any jobs in progress
+ while (true)
+ {
+ int numWorkerJobsFinished = 0;
+ for (int iThread = kFirstWorkerThreadId; iThread < m_numThreads; ++iThread)
+ {
+ ThreadLocalStorage* storage = &m_threadLocalStorage[iThread];
+ storage->m_mutex.lock();
+ numWorkerJobsFinished += storage->m_numJobsFinished;
+ storage->m_mutex.unlock();
+ }
+ if (numWorkerJobsFinished + numMainThreadJobsFinished == m_numJobs)
+ {
+ break;
+ }
+ btU64 timeElapsed = m_clock.getTimeMicroseconds() - clockStart;
+ btAssert(timeElapsed < 1000);
+ if (timeElapsed > 100000)
+ {
+ break;
+ }
+ btSpinPause();
+ }
+ }
+
+ void wakeWorkers(int numWorkersToWake)
+ {
+ BT_PROFILE("wakeWorkers");
+ btAssert(m_workerDirective->getDirective(1) == WorkerThreadDirectives::kScanForJobs);
+ int numDesiredWorkers = btMin(numWorkersToWake, m_numWorkerThreads);
+ int numActiveWorkers = 0;
+ for (int iWorker = 0; iWorker < m_numWorkerThreads; ++iWorker)
+ {
+ // note this count of active workers is not necessarily totally reliable, because a worker thread could be
+ // just about to put itself to sleep. So we may on occasion fail to wake up all the workers. It should be rare.
+ ThreadLocalStorage& storage = m_threadLocalStorage[kFirstWorkerThreadId + iWorker];
+ if (storage.m_status != WorkerThreadStatus::kSleeping)
+ {
+ numActiveWorkers++;
+ }
+ }
+ for (int iWorker = 0; iWorker < m_numWorkerThreads && numActiveWorkers < numDesiredWorkers; ++iWorker)
+ {
+ ThreadLocalStorage& storage = m_threadLocalStorage[kFirstWorkerThreadId + iWorker];
+ if (storage.m_status == WorkerThreadStatus::kSleeping)
+ {
+ m_threadSupport->runTask(iWorker, &storage);
+ numActiveWorkers++;
+ }
+ }
+ }
+
+ void waitForWorkersToSleep()
+ {
+ BT_PROFILE("waitForWorkersToSleep");
+ setWorkerDirectives(WorkerThreadDirectives::kGoToSleep);
+ m_threadSupport->waitForAllTasks();
+ for (int i = kFirstWorkerThreadId; i < m_numThreads; i++)
+ {
+ ThreadLocalStorage& storage = m_threadLocalStorage[i];
+ btAssert(storage.m_status == WorkerThreadStatus::kSleeping);
+ }
+ }
+
+ virtual void sleepWorkerThreadsHint() BT_OVERRIDE
+ {
+ BT_PROFILE("sleepWorkerThreadsHint");
+ // hint the task scheduler that we may not be using these threads for a little while
+ setWorkerDirectives(WorkerThreadDirectives::kGoToSleep);
+ }
+
+ void prepareWorkerThreads()
+ {
+ for (int i = kFirstWorkerThreadId; i < m_numThreads; ++i)
+ {
+ ThreadLocalStorage& storage = m_threadLocalStorage[i];
+ storage.m_mutex.lock();
+ storage.m_numJobsFinished = 0;
+ storage.m_mutex.unlock();
+ }
+ setWorkerDirectives(WorkerThreadDirectives::kScanForJobs);
+ }
+
+ virtual void parallelFor(int iBegin, int iEnd, int grainSize, const btIParallelForBody& body) BT_OVERRIDE
+ {
+ BT_PROFILE("parallelFor_ThreadSupport");
+ btAssert(iEnd >= iBegin);
+ btAssert(grainSize >= 1);
+ int iterationCount = iEnd - iBegin;
+ if (iterationCount > grainSize && m_numWorkerThreads > 0 && m_antiNestingLock.tryLock())
+ {
+ typedef ParallelForJob JobType;
+ int jobCount = (iterationCount + grainSize - 1) / grainSize;
+ m_numJobs = jobCount;
+ btAssert(jobCount >= 2); // need more than one job for multithreading
+ int jobSize = sizeof(JobType);
+
+ for (int i = 0; i < m_numActiveJobQueues; ++i)
+ {
+ m_jobQueues[i].clearQueue(jobCount, jobSize);
+ }
+ // prepare worker threads for incoming work
+ prepareWorkerThreads();
+ // submit all of the jobs
+ int iJob = 0;
+ int iThread = kFirstWorkerThreadId; // first worker thread
+ for (int i = iBegin; i < iEnd; i += grainSize)
+ {
+ btAssert(iJob < jobCount);
+ int iE = btMin(i + grainSize, iEnd);
+ JobQueue* jq = m_perThreadJobQueues[iThread];
+ btAssert(jq);
+ btAssert((jq - &m_jobQueues[0]) < m_numActiveJobQueues);
+ void* jobMem = jq->allocJobMem(jobSize);
+ JobType* job = new (jobMem) ParallelForJob(i, iE, body); // placement new
+ jq->submitJob(job);
+ iJob++;
+ iThread++;
+ if (iThread >= m_numThreads)
+ {
+ iThread = kFirstWorkerThreadId; // first worker thread
+ }
+ }
+ wakeWorkers(jobCount - 1);
+
+ // put the main thread to work on emptying the job queue and then wait for all workers to finish
+ waitJobs();
+ m_antiNestingLock.unlock();
+ }
+ else
+ {
+ BT_PROFILE("parallelFor_mainThread");
+ // just run on main thread
+ body.forLoop(iBegin, iEnd);
+ }
+ }
+ virtual btScalar parallelSum(int iBegin, int iEnd, int grainSize, const btIParallelSumBody& body) BT_OVERRIDE
+ {
+ BT_PROFILE("parallelSum_ThreadSupport");
+ btAssert(iEnd >= iBegin);
+ btAssert(grainSize >= 1);
+ int iterationCount = iEnd - iBegin;
+ if (iterationCount > grainSize && m_numWorkerThreads > 0 && m_antiNestingLock.tryLock())
+ {
+ typedef ParallelSumJob JobType;
+ int jobCount = (iterationCount + grainSize - 1) / grainSize;
+ m_numJobs = jobCount;
+ btAssert(jobCount >= 2); // need more than one job for multithreading
+ int jobSize = sizeof(JobType);
+ for (int i = 0; i < m_numActiveJobQueues; ++i)
+ {
+ m_jobQueues[i].clearQueue(jobCount, jobSize);
+ }
+
+ // initialize summation
+ for (int iThread = 0; iThread < m_numThreads; ++iThread)
+ {
+ m_threadLocalStorage[iThread].m_sumResult = btScalar(0);
+ }
+
+ // prepare worker threads for incoming work
+ prepareWorkerThreads();
+ // submit all of the jobs
+ int iJob = 0;
+ int iThread = kFirstWorkerThreadId; // first worker thread
+ for (int i = iBegin; i < iEnd; i += grainSize)
+ {
+ btAssert(iJob < jobCount);
+ int iE = btMin(i + grainSize, iEnd);
+ JobQueue* jq = m_perThreadJobQueues[iThread];
+ btAssert(jq);
+ btAssert((jq - &m_jobQueues[0]) < m_numActiveJobQueues);
+ void* jobMem = jq->allocJobMem(jobSize);
+ JobType* job = new (jobMem) ParallelSumJob(i, iE, body, &m_threadLocalStorage[0]); // placement new
+ jq->submitJob(job);
+ iJob++;
+ iThread++;
+ if (iThread >= m_numThreads)
+ {
+ iThread = kFirstWorkerThreadId; // first worker thread
+ }
+ }
+ wakeWorkers(jobCount - 1);
+
+ // put the main thread to work on emptying the job queue and then wait for all workers to finish
+ waitJobs();
+
+ // add up all the thread sums
+ btScalar sum = btScalar(0);
+ for (int iThread = 0; iThread < m_numThreads; ++iThread)
+ {
+ sum += m_threadLocalStorage[iThread].m_sumResult;
+ }
+ m_antiNestingLock.unlock();
+ return sum;
+ }
+ else
+ {
+ BT_PROFILE("parallelSum_mainThread");
+ // just run on main thread
+ return body.sumLoop(iBegin, iEnd);
+ }
+ }
+};
btITaskScheduler* btCreateDefaultTaskScheduler()
{
- btTaskSchedulerDefault* ts = new btTaskSchedulerDefault();
- ts->init();
- return ts;
+ btTaskSchedulerDefault* ts = new btTaskSchedulerDefault();
+ ts->init();
+ return ts;
}
-#else // #if BT_THREADSAFE
+#else // #if BT_THREADSAFE
btITaskScheduler* btCreateDefaultTaskScheduler()
{
- return NULL;
+ return NULL;
}
-#endif // #else // #if BT_THREADSAFE
+#endif // #else // #if BT_THREADSAFE
diff --git a/thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportInterface.h b/thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportInterface.h
index a0ad802b1e..1fe49335a1 100644
--- a/thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportInterface.h
+++ b/thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportInterface.h
@@ -16,55 +16,49 @@ subject to the following restrictions:
#ifndef BT_THREAD_SUPPORT_INTERFACE_H
#define BT_THREAD_SUPPORT_INTERFACE_H
-
-
class btCriticalSection
{
public:
- btCriticalSection() {}
- virtual ~btCriticalSection() {}
+ btCriticalSection() {}
+ virtual ~btCriticalSection() {}
- virtual void lock() = 0;
- virtual void unlock() = 0;
+ virtual void lock() = 0;
+ virtual void unlock() = 0;
};
-
class btThreadSupportInterface
{
public:
-
- virtual ~btThreadSupportInterface() {}
-
- virtual int getNumWorkerThreads() const = 0; // number of worker threads (total number of logical processors - 1)
- virtual int getCacheFriendlyNumThreads() const = 0; // the number of logical processors sharing a single L3 cache
- virtual int getLogicalToPhysicalCoreRatio() const = 0; // the number of logical processors per physical processor (usually 1 or 2)
- virtual void runTask( int threadIndex, void* userData ) = 0;
- virtual void waitForAllTasks() = 0;
-
- virtual btCriticalSection* createCriticalSection() = 0;
- virtual void deleteCriticalSection( btCriticalSection* criticalSection ) = 0;
-
- typedef void( *ThreadFunc )( void* userPtr );
-
- struct ConstructionInfo
- {
- ConstructionInfo( const char* uniqueName,
- ThreadFunc userThreadFunc,
- int threadStackSize = 65535
- )
- :m_uniqueName( uniqueName ),
- m_userThreadFunc( userThreadFunc ),
- m_threadStackSize( threadStackSize )
- {
- }
-
- const char* m_uniqueName;
- ThreadFunc m_userThreadFunc;
- int m_threadStackSize;
- };
-
- static btThreadSupportInterface* create( const ConstructionInfo& info );
+ virtual ~btThreadSupportInterface() {}
+
+ virtual int getNumWorkerThreads() const = 0; // number of worker threads (total number of logical processors - 1)
+ virtual int getCacheFriendlyNumThreads() const = 0; // the number of logical processors sharing a single L3 cache
+ virtual int getLogicalToPhysicalCoreRatio() const = 0; // the number of logical processors per physical processor (usually 1 or 2)
+ virtual void runTask(int threadIndex, void* userData) = 0;
+ virtual void waitForAllTasks() = 0;
+
+ virtual btCriticalSection* createCriticalSection() = 0;
+ virtual void deleteCriticalSection(btCriticalSection* criticalSection) = 0;
+
+ typedef void (*ThreadFunc)(void* userPtr);
+
+ struct ConstructionInfo
+ {
+ ConstructionInfo(const char* uniqueName,
+ ThreadFunc userThreadFunc,
+ int threadStackSize = 65535)
+ : m_uniqueName(uniqueName),
+ m_userThreadFunc(userThreadFunc),
+ m_threadStackSize(threadStackSize)
+ {
+ }
+
+ const char* m_uniqueName;
+ ThreadFunc m_userThreadFunc;
+ int m_threadStackSize;
+ };
+
+ static btThreadSupportInterface* create(const ConstructionInfo& info);
};
-#endif //BT_THREAD_SUPPORT_INTERFACE_H
-
+#endif //BT_THREAD_SUPPORT_INTERFACE_H
diff --git a/thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportPosix.cpp b/thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportPosix.cpp
index 50ca060dfe..02f4ed1631 100644
--- a/thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportPosix.cpp
+++ b/thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportPosix.cpp
@@ -1,3 +1,4 @@
+
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2018 Erwin Coumans http://bulletphysics.com
@@ -13,9 +14,7 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
-#if BT_THREADSAFE && !defined( _WIN32 )
-
+#if BT_THREADSAFE && !defined(_WIN32)
#include "LinearMath/btScalar.h"
#include "LinearMath/btAlignedObjectArray.h"
@@ -27,14 +26,12 @@ subject to the following restrictions:
#include <errno.h>
#include <unistd.h>
-
#ifndef _XOPEN_SOURCE
-#define _XOPEN_SOURCE 600 //for definition of pthread_barrier_t, see http://pages.cs.wisc.edu/~travitch/pthreads_primer.html
-#endif //_XOPEN_SOURCE
+#define _XOPEN_SOURCE 600 //for definition of pthread_barrier_t, see http://pages.cs.wisc.edu/~travitch/pthreads_primer.html
+#endif //_XOPEN_SOURCE
#include <pthread.h>
#include <semaphore.h>
-#include <unistd.h> //for sysconf
-
+#include <unistd.h> //for sysconf
///
/// getNumHardwareThreads()
@@ -48,318 +45,309 @@ subject to the following restrictions:
int btGetNumHardwareThreads()
{
- return btMin<int>(BT_MAX_THREAD_COUNT, std::thread::hardware_concurrency());
+ return btMin<int>(BT_MAX_THREAD_COUNT, std::thread::hardware_concurrency());
}
#else
int btGetNumHardwareThreads()
{
- return btMin<int>(BT_MAX_THREAD_COUNT, sysconf( _SC_NPROCESSORS_ONLN ));
+ return btMin<int>(BT_MAX_THREAD_COUNT, sysconf(_SC_NPROCESSORS_ONLN));
}
#endif
-
// btThreadSupportPosix helps to initialize/shutdown libspe2, start/stop SPU tasks and communication
class btThreadSupportPosix : public btThreadSupportInterface
{
public:
- struct btThreadStatus
- {
- int m_taskId;
- int m_commandId;
- int m_status;
-
- ThreadFunc m_userThreadFunc;
- void* m_userPtr; //for taskDesc etc
-
- pthread_t thread;
- //each tread will wait until this signal to start its work
- sem_t* startSemaphore;
-
- // this is a copy of m_mainSemaphore,
- //each tread will signal once it is finished with its work
- sem_t* m_mainSemaphore;
- unsigned long threadUsed;
- };
-private:
- typedef unsigned long long UINT64;
-
- btAlignedObjectArray<btThreadStatus> m_activeThreadStatus;
- // m_mainSemaphoresemaphore will signal, if and how many threads are finished with their work
- sem_t* m_mainSemaphore;
- int m_numThreads;
- UINT64 m_startedThreadsMask;
- void startThreads( const ConstructionInfo& threadInfo );
- void stopThreads();
- int waitForResponse();
+ struct btThreadStatus
+ {
+ int m_taskId;
+ int m_commandId;
+ int m_status;
+
+ ThreadFunc m_userThreadFunc;
+ void* m_userPtr; //for taskDesc etc
+
+ pthread_t thread;
+ //each tread will wait until this signal to start its work
+ sem_t* startSemaphore;
+ btCriticalSection* m_cs;
+ // this is a copy of m_mainSemaphore,
+ //each tread will signal once it is finished with its work
+ sem_t* m_mainSemaphore;
+ unsigned long threadUsed;
+ };
+private:
+ typedef unsigned long long UINT64;
+
+ btAlignedObjectArray<btThreadStatus> m_activeThreadStatus;
+ // m_mainSemaphoresemaphore will signal, if and how many threads are finished with their work
+ sem_t* m_mainSemaphore;
+ int m_numThreads;
+ UINT64 m_startedThreadsMask;
+ void startThreads(const ConstructionInfo& threadInfo);
+ void stopThreads();
+ int waitForResponse();
+ btCriticalSection* m_cs;
public:
- btThreadSupportPosix( const ConstructionInfo& threadConstructionInfo );
- virtual ~btThreadSupportPosix();
+ btThreadSupportPosix(const ConstructionInfo& threadConstructionInfo);
+ virtual ~btThreadSupportPosix();
- virtual int getNumWorkerThreads() const BT_OVERRIDE { return m_numThreads; }
- // TODO: return the number of logical processors sharing the first L3 cache
- virtual int getCacheFriendlyNumThreads() const BT_OVERRIDE { return m_numThreads + 1; }
- // TODO: detect if CPU has hyperthreading enabled
- virtual int getLogicalToPhysicalCoreRatio() const BT_OVERRIDE { return 1; }
+ virtual int getNumWorkerThreads() const BT_OVERRIDE { return m_numThreads; }
+ // TODO: return the number of logical processors sharing the first L3 cache
+ virtual int getCacheFriendlyNumThreads() const BT_OVERRIDE { return m_numThreads + 1; }
+ // TODO: detect if CPU has hyperthreading enabled
+ virtual int getLogicalToPhysicalCoreRatio() const BT_OVERRIDE { return 1; }
- virtual void runTask( int threadIndex, void* userData ) BT_OVERRIDE;
- virtual void waitForAllTasks() BT_OVERRIDE;
+ virtual void runTask(int threadIndex, void* userData) BT_OVERRIDE;
+ virtual void waitForAllTasks() BT_OVERRIDE;
- virtual btCriticalSection* createCriticalSection() BT_OVERRIDE;
- virtual void deleteCriticalSection( btCriticalSection* criticalSection ) BT_OVERRIDE;
+ virtual btCriticalSection* createCriticalSection() BT_OVERRIDE;
+ virtual void deleteCriticalSection(btCriticalSection* criticalSection) BT_OVERRIDE;
};
-
-#define checkPThreadFunction(returnValue) \
- if(0 != returnValue) { \
- printf("PThread problem at line %i in file %s: %i %d\n", __LINE__, __FILE__, returnValue, errno); \
- }
+#define checkPThreadFunction(returnValue) \
+ if (0 != returnValue) \
+ { \
+ printf("PThread problem at line %i in file %s: %i %d\n", __LINE__, __FILE__, returnValue, errno); \
+ }
// The number of threads should be equal to the number of available cores
// Todo: each worker should be linked to a single core, using SetThreadIdealProcessor.
-
-btThreadSupportPosix::btThreadSupportPosix( const ConstructionInfo& threadConstructionInfo )
+btThreadSupportPosix::btThreadSupportPosix(const ConstructionInfo& threadConstructionInfo)
{
- startThreads( threadConstructionInfo );
+ m_cs = createCriticalSection();
+ startThreads(threadConstructionInfo);
}
// cleanup/shutdown Libspe2
btThreadSupportPosix::~btThreadSupportPosix()
{
- stopThreads();
+ stopThreads();
+ deleteCriticalSection(m_cs);
+ m_cs=0;
}
-#if (defined (__APPLE__))
+#if (defined(__APPLE__))
#define NAMED_SEMAPHORES
#endif
-
-static sem_t* createSem( const char* baseName )
+static sem_t* createSem(const char* baseName)
{
- static int semCount = 0;
+ static int semCount = 0;
#ifdef NAMED_SEMAPHORES
- /// Named semaphore begin
- char name[ 32 ];
- snprintf( name, 32, "/%8.s-%4.d-%4.4d", baseName, getpid(), semCount++ );
- sem_t* tempSem = sem_open( name, O_CREAT, 0600, 0 );
-
- if ( tempSem != reinterpret_cast<sem_t *>( SEM_FAILED ) )
- {
- // printf("Created \"%s\" Semaphore %p\n", name, tempSem);
- }
- else
- {
- //printf("Error creating Semaphore %d\n", errno);
- exit( -1 );
- }
- /// Named semaphore end
+ /// Named semaphore begin
+ char name[32];
+ snprintf(name, 32, "/%8.s-%4.d-%4.4d", baseName, getpid(), semCount++);
+ sem_t* tempSem = sem_open(name, O_CREAT, 0600, 0);
+
+ if (tempSem != reinterpret_cast<sem_t*>(SEM_FAILED))
+ {
+ // printf("Created \"%s\" Semaphore %p\n", name, tempSem);
+ }
+ else
+ {
+ //printf("Error creating Semaphore %d\n", errno);
+ exit(-1);
+ }
+ /// Named semaphore end
#else
- sem_t* tempSem = new sem_t;
- checkPThreadFunction( sem_init( tempSem, 0, 0 ) );
+ sem_t* tempSem = new sem_t;
+ checkPThreadFunction(sem_init(tempSem, 0, 0));
#endif
- return tempSem;
+ return tempSem;
}
-static void destroySem( sem_t* semaphore )
+static void destroySem(sem_t* semaphore)
{
#ifdef NAMED_SEMAPHORES
- checkPThreadFunction( sem_close( semaphore ) );
+ checkPThreadFunction(sem_close(semaphore));
#else
- checkPThreadFunction( sem_destroy( semaphore ) );
- delete semaphore;
+ checkPThreadFunction(sem_destroy(semaphore));
+ delete semaphore;
#endif
}
-static void *threadFunction( void *argument )
+static void* threadFunction(void* argument)
{
- btThreadSupportPosix::btThreadStatus* status = ( btThreadSupportPosix::btThreadStatus* )argument;
-
- while ( 1 )
- {
- checkPThreadFunction( sem_wait( status->startSemaphore ) );
- void* userPtr = status->m_userPtr;
-
- if ( userPtr )
- {
- btAssert( status->m_status );
- status->m_userThreadFunc( userPtr );
- status->m_status = 2;
- checkPThreadFunction( sem_post( status->m_mainSemaphore ) );
- status->threadUsed++;
- }
- else
- {
- //exit Thread
- status->m_status = 3;
- checkPThreadFunction( sem_post( status->m_mainSemaphore ) );
- printf( "Thread with taskId %i exiting\n", status->m_taskId );
- break;
- }
- }
-
- printf( "Thread TERMINATED\n" );
- return 0;
+ btThreadSupportPosix::btThreadStatus* status = (btThreadSupportPosix::btThreadStatus*)argument;
+
+ while (1)
+ {
+ checkPThreadFunction(sem_wait(status->startSemaphore));
+ void* userPtr = status->m_userPtr;
+
+ if (userPtr)
+ {
+ btAssert(status->m_status);
+ status->m_userThreadFunc(userPtr);
+ status->m_cs->lock();
+ status->m_status = 2;
+ status->m_cs->unlock();
+ checkPThreadFunction(sem_post(status->m_mainSemaphore));
+ status->threadUsed++;
+ }
+ else
+ {
+ //exit Thread
+ status->m_cs->lock();
+ status->m_status = 3;
+ status->m_cs->unlock();
+ checkPThreadFunction(sem_post(status->m_mainSemaphore));
+ break;
+ }
+ }
+
+ return 0;
}
///send messages to SPUs
-void btThreadSupportPosix::runTask( int threadIndex, void* userData )
+void btThreadSupportPosix::runTask(int threadIndex, void* userData)
{
- ///we should spawn an SPU task here, and in 'waitForResponse' it should wait for response of the (one of) the first tasks that finished
- btThreadStatus& threadStatus = m_activeThreadStatus[ threadIndex ];
- btAssert( threadIndex >= 0 );
- btAssert( threadIndex < m_activeThreadStatus.size() );
-
- threadStatus.m_commandId = 1;
- threadStatus.m_status = 1;
- threadStatus.m_userPtr = userData;
- m_startedThreadsMask |= UINT64( 1 ) << threadIndex;
-
- // fire event to start new task
- checkPThreadFunction( sem_post( threadStatus.startSemaphore ) );
+ ///we should spawn an SPU task here, and in 'waitForResponse' it should wait for response of the (one of) the first tasks that finished
+ btThreadStatus& threadStatus = m_activeThreadStatus[threadIndex];
+ btAssert(threadIndex >= 0);
+ btAssert(threadIndex < m_activeThreadStatus.size());
+ threadStatus.m_cs = m_cs;
+ threadStatus.m_commandId = 1;
+ threadStatus.m_status = 1;
+ threadStatus.m_userPtr = userData;
+ m_startedThreadsMask |= UINT64(1) << threadIndex;
+
+ // fire event to start new task
+ checkPThreadFunction(sem_post(threadStatus.startSemaphore));
}
-
///check for messages from SPUs
int btThreadSupportPosix::waitForResponse()
{
- ///We should wait for (one of) the first tasks to finish (or other SPU messages), and report its response
- ///A possible response can be 'yes, SPU handled it', or 'no, please do a PPU fallback'
-
- btAssert( m_activeThreadStatus.size() );
-
- // wait for any of the threads to finish
- checkPThreadFunction( sem_wait( m_mainSemaphore ) );
- // get at least one thread which has finished
- size_t last = -1;
-
- for ( size_t t = 0; t < size_t( m_activeThreadStatus.size() ); ++t )
- {
- if ( 2 == m_activeThreadStatus[ t ].m_status )
- {
- last = t;
- break;
- }
- }
-
- btThreadStatus& threadStatus = m_activeThreadStatus[ last ];
-
- btAssert( threadStatus.m_status > 1 );
- threadStatus.m_status = 0;
-
- // need to find an active spu
- btAssert( last >= 0 );
- m_startedThreadsMask &= ~( UINT64( 1 ) << last );
-
- return last;
+ ///We should wait for (one of) the first tasks to finish (or other SPU messages), and report its response
+ ///A possible response can be 'yes, SPU handled it', or 'no, please do a PPU fallback'
+
+ btAssert(m_activeThreadStatus.size());
+
+ // wait for any of the threads to finish
+ checkPThreadFunction(sem_wait(m_mainSemaphore));
+ // get at least one thread which has finished
+ size_t last = -1;
+
+ for (size_t t = 0; t < size_t(m_activeThreadStatus.size()); ++t)
+ {
+ m_cs->lock();
+ bool hasFinished = (2 == m_activeThreadStatus[t].m_status);
+ m_cs->unlock();
+ if (hasFinished)
+ {
+ last = t;
+ break;
+ }
+ }
+
+ btThreadStatus& threadStatus = m_activeThreadStatus[last];
+
+ btAssert(threadStatus.m_status > 1);
+ threadStatus.m_status = 0;
+
+ // need to find an active spu
+ btAssert(last >= 0);
+ m_startedThreadsMask &= ~(UINT64(1) << last);
+
+ return last;
}
-
void btThreadSupportPosix::waitForAllTasks()
{
- while ( m_startedThreadsMask )
- {
- waitForResponse();
- }
+ while (m_startedThreadsMask)
+ {
+ waitForResponse();
+ }
}
-
-void btThreadSupportPosix::startThreads( const ConstructionInfo& threadConstructionInfo )
+void btThreadSupportPosix::startThreads(const ConstructionInfo& threadConstructionInfo)
{
- m_numThreads = btGetNumHardwareThreads() - 1; // main thread exists already
- printf( "%s creating %i threads.\n", __FUNCTION__, m_numThreads );
- m_activeThreadStatus.resize( m_numThreads );
- m_startedThreadsMask = 0;
-
- m_mainSemaphore = createSem( "main" );
- //checkPThreadFunction(sem_wait(mainSemaphore));
-
- for ( int i = 0; i < m_numThreads; i++ )
- {
- printf( "starting thread %d\n", i );
- btThreadStatus& threadStatus = m_activeThreadStatus[ i ];
- threadStatus.startSemaphore = createSem( "threadLocal" );
- checkPThreadFunction( pthread_create( &threadStatus.thread, NULL, &threadFunction, (void*) &threadStatus ) );
-
- threadStatus.m_userPtr = 0;
- threadStatus.m_taskId = i;
- threadStatus.m_commandId = 0;
- threadStatus.m_status = 0;
- threadStatus.m_mainSemaphore = m_mainSemaphore;
- threadStatus.m_userThreadFunc = threadConstructionInfo.m_userThreadFunc;
- threadStatus.threadUsed = 0;
-
- printf( "started thread %d \n", i );
- }
+ m_numThreads = btGetNumHardwareThreads() - 1; // main thread exists already
+ m_activeThreadStatus.resize(m_numThreads);
+ m_startedThreadsMask = 0;
+
+ m_mainSemaphore = createSem("main");
+ //checkPThreadFunction(sem_wait(mainSemaphore));
+
+ for (int i = 0; i < m_numThreads; i++)
+ {
+ btThreadStatus& threadStatus = m_activeThreadStatus[i];
+ threadStatus.startSemaphore = createSem("threadLocal");
+ threadStatus.m_userPtr = 0;
+ threadStatus.m_cs = m_cs;
+ threadStatus.m_taskId = i;
+ threadStatus.m_commandId = 0;
+ threadStatus.m_status = 0;
+ threadStatus.m_mainSemaphore = m_mainSemaphore;
+ threadStatus.m_userThreadFunc = threadConstructionInfo.m_userThreadFunc;
+ threadStatus.threadUsed = 0;
+ checkPThreadFunction(pthread_create(&threadStatus.thread, NULL, &threadFunction, (void*)&threadStatus));
+
+ }
}
///tell the task scheduler we are done with the SPU tasks
void btThreadSupportPosix::stopThreads()
{
- for ( size_t t = 0; t < size_t( m_activeThreadStatus.size() ); ++t )
- {
- btThreadStatus& threadStatus = m_activeThreadStatus[ t ];
- printf( "%s: Thread %i used: %ld\n", __FUNCTION__, int( t ), threadStatus.threadUsed );
-
- threadStatus.m_userPtr = 0;
- checkPThreadFunction( sem_post( threadStatus.startSemaphore ) );
- checkPThreadFunction( sem_wait( m_mainSemaphore ) );
-
- printf( "destroy semaphore\n" );
- destroySem( threadStatus.startSemaphore );
- printf( "semaphore destroyed\n" );
- checkPThreadFunction( pthread_join( threadStatus.thread, 0 ) );
-
- }
- printf( "destroy main semaphore\n" );
- destroySem( m_mainSemaphore );
- printf( "main semaphore destroyed\n" );
- m_activeThreadStatus.clear();
+ for (size_t t = 0; t < size_t(m_activeThreadStatus.size()); ++t)
+ {
+ btThreadStatus& threadStatus = m_activeThreadStatus[t];
+
+ threadStatus.m_userPtr = 0;
+ checkPThreadFunction(sem_post(threadStatus.startSemaphore));
+ checkPThreadFunction(sem_wait(m_mainSemaphore));
+
+ destroySem(threadStatus.startSemaphore);
+ checkPThreadFunction(pthread_join(threadStatus.thread, 0));
+ }
+ destroySem(m_mainSemaphore);
+ m_activeThreadStatus.clear();
}
class btCriticalSectionPosix : public btCriticalSection
{
- pthread_mutex_t m_mutex;
+ pthread_mutex_t m_mutex;
public:
- btCriticalSectionPosix()
- {
- pthread_mutex_init( &m_mutex, NULL );
- }
- virtual ~btCriticalSectionPosix()
- {
- pthread_mutex_destroy( &m_mutex );
- }
-
- virtual void lock()
- {
- pthread_mutex_lock( &m_mutex );
- }
- virtual void unlock()
- {
- pthread_mutex_unlock( &m_mutex );
- }
+ btCriticalSectionPosix()
+ {
+ pthread_mutex_init(&m_mutex, NULL);
+ }
+ virtual ~btCriticalSectionPosix()
+ {
+ pthread_mutex_destroy(&m_mutex);
+ }
+
+ virtual void lock()
+ {
+ pthread_mutex_lock(&m_mutex);
+ }
+ virtual void unlock()
+ {
+ pthread_mutex_unlock(&m_mutex);
+ }
};
-
btCriticalSection* btThreadSupportPosix::createCriticalSection()
{
- return new btCriticalSectionPosix();
+ return new btCriticalSectionPosix();
}
-void btThreadSupportPosix::deleteCriticalSection( btCriticalSection* cs )
+void btThreadSupportPosix::deleteCriticalSection(btCriticalSection* cs)
{
- delete cs;
+ delete cs;
}
-
-btThreadSupportInterface* btThreadSupportInterface::create( const ConstructionInfo& info )
+btThreadSupportInterface* btThreadSupportInterface::create(const ConstructionInfo& info)
{
- return new btThreadSupportPosix( info );
+ return new btThreadSupportPosix(info);
}
-#endif // BT_THREADSAFE && !defined( _WIN32 )
-
+#endif // BT_THREADSAFE && !defined( _WIN32 )
diff --git a/thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportWin32.cpp b/thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportWin32.cpp
index 00edac650b..922e449cce 100644
--- a/thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportWin32.cpp
+++ b/thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportWin32.cpp
@@ -13,7 +13,7 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-#if defined( _WIN32 ) && BT_THREADSAFE
+#if defined(_WIN32) && BT_THREADSAFE
#include "LinearMath/btScalar.h"
#include "LinearMath/btMinMax.h"
@@ -23,450 +23,430 @@ subject to the following restrictions:
#include <windows.h>
#include <stdio.h>
-
struct btProcessorInfo
{
- int numLogicalProcessors;
- int numCores;
- int numNumaNodes;
- int numL1Cache;
- int numL2Cache;
- int numL3Cache;
- int numPhysicalPackages;
- static const int maxNumTeamMasks = 32;
- int numTeamMasks;
- UINT64 processorTeamMasks[ maxNumTeamMasks ];
+ int numLogicalProcessors;
+ int numCores;
+ int numNumaNodes;
+ int numL1Cache;
+ int numL2Cache;
+ int numL3Cache;
+ int numPhysicalPackages;
+ static const int maxNumTeamMasks = 32;
+ int numTeamMasks;
+ UINT64 processorTeamMasks[maxNumTeamMasks];
};
-UINT64 getProcessorTeamMask( const btProcessorInfo& procInfo, int procId )
+UINT64 getProcessorTeamMask(const btProcessorInfo& procInfo, int procId)
{
- UINT64 procMask = UINT64( 1 ) << procId;
- for ( int i = 0; i < procInfo.numTeamMasks; ++i )
- {
- if ( procMask & procInfo.processorTeamMasks[ i ] )
- {
- return procInfo.processorTeamMasks[ i ];
- }
- }
- return 0;
+ UINT64 procMask = UINT64(1) << procId;
+ for (int i = 0; i < procInfo.numTeamMasks; ++i)
+ {
+ if (procMask & procInfo.processorTeamMasks[i])
+ {
+ return procInfo.processorTeamMasks[i];
+ }
+ }
+ return 0;
}
-int getProcessorTeamIndex( const btProcessorInfo& procInfo, int procId )
+int getProcessorTeamIndex(const btProcessorInfo& procInfo, int procId)
{
- UINT64 procMask = UINT64( 1 ) << procId;
- for ( int i = 0; i < procInfo.numTeamMasks; ++i )
- {
- if ( procMask & procInfo.processorTeamMasks[ i ] )
- {
- return i;
- }
- }
- return -1;
+ UINT64 procMask = UINT64(1) << procId;
+ for (int i = 0; i < procInfo.numTeamMasks; ++i)
+ {
+ if (procMask & procInfo.processorTeamMasks[i])
+ {
+ return i;
+ }
+ }
+ return -1;
}
-int countSetBits( ULONG64 bits )
+int countSetBits(ULONG64 bits)
{
- int count = 0;
- while ( bits )
- {
- if ( bits & 1 )
- {
- count++;
- }
- bits >>= 1;
- }
- return count;
+ int count = 0;
+ while (bits)
+ {
+ if (bits & 1)
+ {
+ count++;
+ }
+ bits >>= 1;
+ }
+ return count;
}
+typedef BOOL(WINAPI* Pfn_GetLogicalProcessorInformation)(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, PDWORD);
-typedef BOOL( WINAPI *Pfn_GetLogicalProcessorInformation )( PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, PDWORD );
-
-
-void getProcessorInformation( btProcessorInfo* procInfo )
+void getProcessorInformation(btProcessorInfo* procInfo)
{
- memset( procInfo, 0, sizeof( *procInfo ) );
- Pfn_GetLogicalProcessorInformation getLogicalProcInfo =
- (Pfn_GetLogicalProcessorInformation) GetProcAddress( GetModuleHandle( TEXT( "kernel32" ) ), "GetLogicalProcessorInformation" );
- if ( getLogicalProcInfo == NULL )
- {
- // no info
- return;
- }
- PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buf = NULL;
- DWORD bufSize = 0;
- while ( true )
- {
- if ( getLogicalProcInfo( buf, &bufSize ) )
- {
- break;
- }
- else
- {
- if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER )
- {
- if ( buf )
- {
- free( buf );
- }
- buf = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION) malloc( bufSize );
- }
- }
- }
-
- int len = bufSize / sizeof( *buf );
- for ( int i = 0; i < len; ++i )
- {
- PSYSTEM_LOGICAL_PROCESSOR_INFORMATION info = buf + i;
- switch ( info->Relationship )
- {
- case RelationNumaNode:
- procInfo->numNumaNodes++;
- break;
-
- case RelationProcessorCore:
- procInfo->numCores++;
- procInfo->numLogicalProcessors += countSetBits( info->ProcessorMask );
- break;
-
- case RelationCache:
- if ( info->Cache.Level == 1 )
- {
- procInfo->numL1Cache++;
- }
- else if ( info->Cache.Level == 2 )
- {
- procInfo->numL2Cache++;
- }
- else if ( info->Cache.Level == 3 )
- {
- procInfo->numL3Cache++;
- // processors that share L3 cache are considered to be on the same team
- // because they can more easily work together on the same data.
- // Large performance penalties will occur if 2 or more threads from different
- // teams attempt to frequently read and modify the same cache lines.
- //
- // On the AMD Ryzen 7 CPU for example, the 8 cores on the CPU are split into
- // 2 CCX units of 4 cores each. Each CCX has a separate L3 cache, so if both
- // CCXs are operating on the same data, many cycles will be spent keeping the
- // two caches coherent.
- if ( procInfo->numTeamMasks < btProcessorInfo::maxNumTeamMasks )
- {
- procInfo->processorTeamMasks[ procInfo->numTeamMasks ] = info->ProcessorMask;
- procInfo->numTeamMasks++;
- }
- }
- break;
-
- case RelationProcessorPackage:
- procInfo->numPhysicalPackages++;
- break;
- }
- }
- free( buf );
+ memset(procInfo, 0, sizeof(*procInfo));
+ Pfn_GetLogicalProcessorInformation getLogicalProcInfo =
+ (Pfn_GetLogicalProcessorInformation)GetProcAddress(GetModuleHandle(TEXT("kernel32")), "GetLogicalProcessorInformation");
+ if (getLogicalProcInfo == NULL)
+ {
+ // no info
+ return;
+ }
+ PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buf = NULL;
+ DWORD bufSize = 0;
+ while (true)
+ {
+ if (getLogicalProcInfo(buf, &bufSize))
+ {
+ break;
+ }
+ else
+ {
+ if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+ if (buf)
+ {
+ free(buf);
+ }
+ buf = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc(bufSize);
+ }
+ }
+ }
+
+ int len = bufSize / sizeof(*buf);
+ for (int i = 0; i < len; ++i)
+ {
+ PSYSTEM_LOGICAL_PROCESSOR_INFORMATION info = buf + i;
+ switch (info->Relationship)
+ {
+ case RelationNumaNode:
+ procInfo->numNumaNodes++;
+ break;
+
+ case RelationProcessorCore:
+ procInfo->numCores++;
+ procInfo->numLogicalProcessors += countSetBits(info->ProcessorMask);
+ break;
+
+ case RelationCache:
+ if (info->Cache.Level == 1)
+ {
+ procInfo->numL1Cache++;
+ }
+ else if (info->Cache.Level == 2)
+ {
+ procInfo->numL2Cache++;
+ }
+ else if (info->Cache.Level == 3)
+ {
+ procInfo->numL3Cache++;
+ // processors that share L3 cache are considered to be on the same team
+ // because they can more easily work together on the same data.
+ // Large performance penalties will occur if 2 or more threads from different
+ // teams attempt to frequently read and modify the same cache lines.
+ //
+ // On the AMD Ryzen 7 CPU for example, the 8 cores on the CPU are split into
+ // 2 CCX units of 4 cores each. Each CCX has a separate L3 cache, so if both
+ // CCXs are operating on the same data, many cycles will be spent keeping the
+ // two caches coherent.
+ if (procInfo->numTeamMasks < btProcessorInfo::maxNumTeamMasks)
+ {
+ procInfo->processorTeamMasks[procInfo->numTeamMasks] = info->ProcessorMask;
+ procInfo->numTeamMasks++;
+ }
+ }
+ break;
+
+ case RelationProcessorPackage:
+ procInfo->numPhysicalPackages++;
+ break;
+ }
+ }
+ free(buf);
}
-
-
///btThreadSupportWin32 helps to initialize/shutdown libspe2, start/stop SPU tasks and communication
class btThreadSupportWin32 : public btThreadSupportInterface
{
public:
- struct btThreadStatus
- {
- int m_taskId;
- int m_commandId;
- int m_status;
+ struct btThreadStatus
+ {
+ int m_taskId;
+ int m_commandId;
+ int m_status;
- ThreadFunc m_userThreadFunc;
- void* m_userPtr; //for taskDesc etc
+ ThreadFunc m_userThreadFunc;
+ void* m_userPtr; //for taskDesc etc
- void* m_threadHandle; //this one is calling 'Win32ThreadFunc'
+ void* m_threadHandle; //this one is calling 'Win32ThreadFunc'
- void* m_eventStartHandle;
- char m_eventStartHandleName[ 32 ];
+ void* m_eventStartHandle;
+ char m_eventStartHandleName[32];
- void* m_eventCompleteHandle;
- char m_eventCompleteHandleName[ 32 ];
- };
+ void* m_eventCompleteHandle;
+ char m_eventCompleteHandleName[32];
+ };
private:
- btAlignedObjectArray<btThreadStatus> m_activeThreadStatus;
- btAlignedObjectArray<void*> m_completeHandles;
- int m_numThreads;
- DWORD_PTR m_startedThreadMask;
- btProcessorInfo m_processorInfo;
+ btAlignedObjectArray<btThreadStatus> m_activeThreadStatus;
+ btAlignedObjectArray<void*> m_completeHandles;
+ int m_numThreads;
+ DWORD_PTR m_startedThreadMask;
+ btProcessorInfo m_processorInfo;
- void startThreads( const ConstructionInfo& threadInfo );
- void stopThreads();
- int waitForResponse();
+ void startThreads(const ConstructionInfo& threadInfo);
+ void stopThreads();
+ int waitForResponse();
public:
+ btThreadSupportWin32(const ConstructionInfo& threadConstructionInfo);
+ virtual ~btThreadSupportWin32();
- btThreadSupportWin32( const ConstructionInfo& threadConstructionInfo );
- virtual ~btThreadSupportWin32();
+ virtual int getNumWorkerThreads() const BT_OVERRIDE { return m_numThreads; }
+ virtual int getCacheFriendlyNumThreads() const BT_OVERRIDE { return countSetBits(m_processorInfo.processorTeamMasks[0]); }
+ virtual int getLogicalToPhysicalCoreRatio() const BT_OVERRIDE { return m_processorInfo.numLogicalProcessors / m_processorInfo.numCores; }
- virtual int getNumWorkerThreads() const BT_OVERRIDE { return m_numThreads; }
- virtual int getCacheFriendlyNumThreads() const BT_OVERRIDE { return countSetBits(m_processorInfo.processorTeamMasks[0]); }
- virtual int getLogicalToPhysicalCoreRatio() const BT_OVERRIDE { return m_processorInfo.numLogicalProcessors / m_processorInfo.numCores; }
+ virtual void runTask(int threadIndex, void* userData) BT_OVERRIDE;
+ virtual void waitForAllTasks() BT_OVERRIDE;
- virtual void runTask( int threadIndex, void* userData ) BT_OVERRIDE;
- virtual void waitForAllTasks() BT_OVERRIDE;
-
- virtual btCriticalSection* createCriticalSection() BT_OVERRIDE;
- virtual void deleteCriticalSection( btCriticalSection* criticalSection ) BT_OVERRIDE;
+ virtual btCriticalSection* createCriticalSection() BT_OVERRIDE;
+ virtual void deleteCriticalSection(btCriticalSection* criticalSection) BT_OVERRIDE;
};
-
-btThreadSupportWin32::btThreadSupportWin32( const ConstructionInfo & threadConstructionInfo )
+btThreadSupportWin32::btThreadSupportWin32(const ConstructionInfo& threadConstructionInfo)
{
- startThreads( threadConstructionInfo );
+ startThreads(threadConstructionInfo);
}
-
btThreadSupportWin32::~btThreadSupportWin32()
{
- stopThreads();
+ stopThreads();
}
-
-DWORD WINAPI win32threadStartFunc( LPVOID lpParam )
+DWORD WINAPI win32threadStartFunc(LPVOID lpParam)
{
- btThreadSupportWin32::btThreadStatus* status = ( btThreadSupportWin32::btThreadStatus* )lpParam;
-
- while ( 1 )
- {
- WaitForSingleObject( status->m_eventStartHandle, INFINITE );
- void* userPtr = status->m_userPtr;
-
- if ( userPtr )
- {
- btAssert( status->m_status );
- status->m_userThreadFunc( userPtr );
- status->m_status = 2;
- SetEvent( status->m_eventCompleteHandle );
- }
- else
- {
- //exit Thread
- status->m_status = 3;
- printf( "Thread with taskId %i with handle %p exiting\n", status->m_taskId, status->m_threadHandle );
- SetEvent( status->m_eventCompleteHandle );
- break;
- }
- }
- printf( "Thread TERMINATED\n" );
- return 0;
+ btThreadSupportWin32::btThreadStatus* status = (btThreadSupportWin32::btThreadStatus*)lpParam;
+
+ while (1)
+ {
+ WaitForSingleObject(status->m_eventStartHandle, INFINITE);
+ void* userPtr = status->m_userPtr;
+
+ if (userPtr)
+ {
+ btAssert(status->m_status);
+ status->m_userThreadFunc(userPtr);
+ status->m_status = 2;
+ SetEvent(status->m_eventCompleteHandle);
+ }
+ else
+ {
+ //exit Thread
+ status->m_status = 3;
+ printf("Thread with taskId %i with handle %p exiting\n", status->m_taskId, status->m_threadHandle);
+ SetEvent(status->m_eventCompleteHandle);
+ break;
+ }
+ }
+ printf("Thread TERMINATED\n");
+ return 0;
}
-
-void btThreadSupportWin32::runTask( int threadIndex, void* userData )
+void btThreadSupportWin32::runTask(int threadIndex, void* userData)
{
- btThreadStatus& threadStatus = m_activeThreadStatus[ threadIndex ];
- btAssert( threadIndex >= 0 );
- btAssert( int( threadIndex ) < m_activeThreadStatus.size() );
+ btThreadStatus& threadStatus = m_activeThreadStatus[threadIndex];
+ btAssert(threadIndex >= 0);
+ btAssert(int(threadIndex) < m_activeThreadStatus.size());
- threadStatus.m_commandId = 1;
- threadStatus.m_status = 1;
- threadStatus.m_userPtr = userData;
- m_startedThreadMask |= DWORD_PTR( 1 ) << threadIndex;
+ threadStatus.m_commandId = 1;
+ threadStatus.m_status = 1;
+ threadStatus.m_userPtr = userData;
+ m_startedThreadMask |= DWORD_PTR(1) << threadIndex;
- ///fire event to start new task
- SetEvent( threadStatus.m_eventStartHandle );
+ ///fire event to start new task
+ SetEvent(threadStatus.m_eventStartHandle);
}
-
int btThreadSupportWin32::waitForResponse()
{
- btAssert( m_activeThreadStatus.size() );
+ btAssert(m_activeThreadStatus.size());
- int last = -1;
- DWORD res = WaitForMultipleObjects( m_completeHandles.size(), &m_completeHandles[ 0 ], FALSE, INFINITE );
- btAssert( res != WAIT_FAILED );
- last = res - WAIT_OBJECT_0;
+ int last = -1;
+ DWORD res = WaitForMultipleObjects(m_completeHandles.size(), &m_completeHandles[0], FALSE, INFINITE);
+ btAssert(res != WAIT_FAILED);
+ last = res - WAIT_OBJECT_0;
- btThreadStatus& threadStatus = m_activeThreadStatus[ last ];
- btAssert( threadStatus.m_threadHandle );
- btAssert( threadStatus.m_eventCompleteHandle );
+ btThreadStatus& threadStatus = m_activeThreadStatus[last];
+ btAssert(threadStatus.m_threadHandle);
+ btAssert(threadStatus.m_eventCompleteHandle);
- //WaitForSingleObject(threadStatus.m_eventCompleteHandle, INFINITE);
- btAssert( threadStatus.m_status > 1 );
- threadStatus.m_status = 0;
+ //WaitForSingleObject(threadStatus.m_eventCompleteHandle, INFINITE);
+ btAssert(threadStatus.m_status > 1);
+ threadStatus.m_status = 0;
- ///need to find an active spu
- btAssert( last >= 0 );
- m_startedThreadMask &= ~( DWORD_PTR( 1 ) << last );
+ ///need to find an active spu
+ btAssert(last >= 0);
+ m_startedThreadMask &= ~(DWORD_PTR(1) << last);
- return last;
+ return last;
}
-
void btThreadSupportWin32::waitForAllTasks()
{
- while ( m_startedThreadMask )
- {
- waitForResponse();
- }
+ while (m_startedThreadMask)
+ {
+ waitForResponse();
+ }
}
-
-void btThreadSupportWin32::startThreads( const ConstructionInfo& threadConstructionInfo )
+void btThreadSupportWin32::startThreads(const ConstructionInfo& threadConstructionInfo)
{
- static int uniqueId = 0;
- uniqueId++;
- btProcessorInfo& procInfo = m_processorInfo;
- getProcessorInformation( &procInfo );
- DWORD_PTR dwProcessAffinityMask = 0;
- DWORD_PTR dwSystemAffinityMask = 0;
- if ( !GetProcessAffinityMask( GetCurrentProcess(), &dwProcessAffinityMask, &dwSystemAffinityMask ) )
- {
- dwProcessAffinityMask = 0;
- }
- ///The number of threads should be equal to the number of available cores - 1
- m_numThreads = btMin(procInfo.numLogicalProcessors, int(BT_MAX_THREAD_COUNT)) - 1; // cap to max thread count (-1 because main thread already exists)
-
- m_activeThreadStatus.resize( m_numThreads );
- m_completeHandles.resize( m_numThreads );
- m_startedThreadMask = 0;
-
- // set main thread affinity
- if ( DWORD_PTR mask = dwProcessAffinityMask & getProcessorTeamMask( procInfo, 0 ))
- {
- SetThreadAffinityMask( GetCurrentThread(), mask );
- SetThreadIdealProcessor( GetCurrentThread(), 0 );
- }
-
- for ( int i = 0; i < m_numThreads; i++ )
- {
- printf( "starting thread %d\n", i );
-
- btThreadStatus& threadStatus = m_activeThreadStatus[ i ];
-
- LPSECURITY_ATTRIBUTES lpThreadAttributes = NULL;
- SIZE_T dwStackSize = threadConstructionInfo.m_threadStackSize;
- LPTHREAD_START_ROUTINE lpStartAddress = &win32threadStartFunc;
- LPVOID lpParameter = &threadStatus;
- DWORD dwCreationFlags = 0;
- LPDWORD lpThreadId = 0;
-
- threadStatus.m_userPtr = 0;
-
- sprintf( threadStatus.m_eventStartHandleName, "es%.8s%d%d", threadConstructionInfo.m_uniqueName, uniqueId, i );
- threadStatus.m_eventStartHandle = CreateEventA( 0, false, false, threadStatus.m_eventStartHandleName );
-
- sprintf( threadStatus.m_eventCompleteHandleName, "ec%.8s%d%d", threadConstructionInfo.m_uniqueName, uniqueId, i );
- threadStatus.m_eventCompleteHandle = CreateEventA( 0, false, false, threadStatus.m_eventCompleteHandleName );
-
- m_completeHandles[ i ] = threadStatus.m_eventCompleteHandle;
-
- HANDLE handle = CreateThread( lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId );
- //SetThreadPriority( handle, THREAD_PRIORITY_HIGHEST );
- // highest priority -- can cause erratic performance when numThreads > numCores
- // we don't want worker threads to be higher priority than the main thread or the main thread could get
- // totally shut out and unable to tell the workers to stop
- //SetThreadPriority( handle, THREAD_PRIORITY_BELOW_NORMAL );
-
- {
- int processorId = i + 1; // leave processor 0 for main thread
- DWORD_PTR teamMask = getProcessorTeamMask( procInfo, processorId );
- if ( teamMask )
- {
- // bind each thread to only execute on processors of it's assigned team
- // - for single-socket Intel x86 CPUs this has no effect (only a single, shared L3 cache so there is only 1 team)
- // - for multi-socket Intel this will keep threads from migrating from one socket to another
- // - for AMD Ryzen this will keep threads from migrating from one CCX to another
- DWORD_PTR mask = teamMask & dwProcessAffinityMask;
- if ( mask )
- {
- SetThreadAffinityMask( handle, mask );
- }
- }
- SetThreadIdealProcessor( handle, processorId );
- }
-
- threadStatus.m_taskId = i;
- threadStatus.m_commandId = 0;
- threadStatus.m_status = 0;
- threadStatus.m_threadHandle = handle;
- threadStatus.m_userThreadFunc = threadConstructionInfo.m_userThreadFunc;
-
- printf( "started %s thread %d with threadHandle %p\n", threadConstructionInfo.m_uniqueName, i, handle );
- }
+ static int uniqueId = 0;
+ uniqueId++;
+ btProcessorInfo& procInfo = m_processorInfo;
+ getProcessorInformation(&procInfo);
+ DWORD_PTR dwProcessAffinityMask = 0;
+ DWORD_PTR dwSystemAffinityMask = 0;
+ if (!GetProcessAffinityMask(GetCurrentProcess(), &dwProcessAffinityMask, &dwSystemAffinityMask))
+ {
+ dwProcessAffinityMask = 0;
+ }
+ ///The number of threads should be equal to the number of available cores - 1
+ m_numThreads = btMin(procInfo.numLogicalProcessors, int(BT_MAX_THREAD_COUNT)) - 1; // cap to max thread count (-1 because main thread already exists)
+
+ m_activeThreadStatus.resize(m_numThreads);
+ m_completeHandles.resize(m_numThreads);
+ m_startedThreadMask = 0;
+
+ // set main thread affinity
+ if (DWORD_PTR mask = dwProcessAffinityMask & getProcessorTeamMask(procInfo, 0))
+ {
+ SetThreadAffinityMask(GetCurrentThread(), mask);
+ SetThreadIdealProcessor(GetCurrentThread(), 0);
+ }
+
+ for (int i = 0; i < m_numThreads; i++)
+ {
+ printf("starting thread %d\n", i);
+
+ btThreadStatus& threadStatus = m_activeThreadStatus[i];
+
+ LPSECURITY_ATTRIBUTES lpThreadAttributes = NULL;
+ SIZE_T dwStackSize = threadConstructionInfo.m_threadStackSize;
+ LPTHREAD_START_ROUTINE lpStartAddress = &win32threadStartFunc;
+ LPVOID lpParameter = &threadStatus;
+ DWORD dwCreationFlags = 0;
+ LPDWORD lpThreadId = 0;
+
+ threadStatus.m_userPtr = 0;
+
+ sprintf(threadStatus.m_eventStartHandleName, "es%.8s%d%d", threadConstructionInfo.m_uniqueName, uniqueId, i);
+ threadStatus.m_eventStartHandle = CreateEventA(0, false, false, threadStatus.m_eventStartHandleName);
+
+ sprintf(threadStatus.m_eventCompleteHandleName, "ec%.8s%d%d", threadConstructionInfo.m_uniqueName, uniqueId, i);
+ threadStatus.m_eventCompleteHandle = CreateEventA(0, false, false, threadStatus.m_eventCompleteHandleName);
+
+ m_completeHandles[i] = threadStatus.m_eventCompleteHandle;
+
+ HANDLE handle = CreateThread(lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId);
+ //SetThreadPriority( handle, THREAD_PRIORITY_HIGHEST );
+ // highest priority -- can cause erratic performance when numThreads > numCores
+ // we don't want worker threads to be higher priority than the main thread or the main thread could get
+ // totally shut out and unable to tell the workers to stop
+ //SetThreadPriority( handle, THREAD_PRIORITY_BELOW_NORMAL );
+
+ {
+ int processorId = i + 1; // leave processor 0 for main thread
+ DWORD_PTR teamMask = getProcessorTeamMask(procInfo, processorId);
+ if (teamMask)
+ {
+ // bind each thread to only execute on processors of it's assigned team
+ // - for single-socket Intel x86 CPUs this has no effect (only a single, shared L3 cache so there is only 1 team)
+ // - for multi-socket Intel this will keep threads from migrating from one socket to another
+ // - for AMD Ryzen this will keep threads from migrating from one CCX to another
+ DWORD_PTR mask = teamMask & dwProcessAffinityMask;
+ if (mask)
+ {
+ SetThreadAffinityMask(handle, mask);
+ }
+ }
+ SetThreadIdealProcessor(handle, processorId);
+ }
+
+ threadStatus.m_taskId = i;
+ threadStatus.m_commandId = 0;
+ threadStatus.m_status = 0;
+ threadStatus.m_threadHandle = handle;
+ threadStatus.m_userThreadFunc = threadConstructionInfo.m_userThreadFunc;
+
+ printf("started %s thread %d with threadHandle %p\n", threadConstructionInfo.m_uniqueName, i, handle);
+ }
}
///tell the task scheduler we are done with the SPU tasks
void btThreadSupportWin32::stopThreads()
{
- for ( int i = 0; i < m_activeThreadStatus.size(); i++ )
- {
- btThreadStatus& threadStatus = m_activeThreadStatus[ i ];
- if ( threadStatus.m_status > 0 )
- {
- WaitForSingleObject( threadStatus.m_eventCompleteHandle, INFINITE );
- }
-
- threadStatus.m_userPtr = NULL;
- SetEvent( threadStatus.m_eventStartHandle );
- WaitForSingleObject( threadStatus.m_eventCompleteHandle, INFINITE );
-
- CloseHandle( threadStatus.m_eventCompleteHandle );
- CloseHandle( threadStatus.m_eventStartHandle );
- CloseHandle( threadStatus.m_threadHandle );
-
- }
-
- m_activeThreadStatus.clear();
- m_completeHandles.clear();
+ for (int i = 0; i < m_activeThreadStatus.size(); i++)
+ {
+ btThreadStatus& threadStatus = m_activeThreadStatus[i];
+ if (threadStatus.m_status > 0)
+ {
+ WaitForSingleObject(threadStatus.m_eventCompleteHandle, INFINITE);
+ }
+
+ threadStatus.m_userPtr = NULL;
+ SetEvent(threadStatus.m_eventStartHandle);
+ WaitForSingleObject(threadStatus.m_eventCompleteHandle, INFINITE);
+
+ CloseHandle(threadStatus.m_eventCompleteHandle);
+ CloseHandle(threadStatus.m_eventStartHandle);
+ CloseHandle(threadStatus.m_threadHandle);
+ }
+
+ m_activeThreadStatus.clear();
+ m_completeHandles.clear();
}
-
class btWin32CriticalSection : public btCriticalSection
{
private:
- CRITICAL_SECTION mCriticalSection;
+ CRITICAL_SECTION mCriticalSection;
public:
- btWin32CriticalSection()
- {
- InitializeCriticalSection( &mCriticalSection );
- }
-
- ~btWin32CriticalSection()
- {
- DeleteCriticalSection( &mCriticalSection );
- }
-
- void lock()
- {
- EnterCriticalSection( &mCriticalSection );
- }
-
- void unlock()
- {
- LeaveCriticalSection( &mCriticalSection );
- }
+ btWin32CriticalSection()
+ {
+ InitializeCriticalSection(&mCriticalSection);
+ }
+
+ ~btWin32CriticalSection()
+ {
+ DeleteCriticalSection(&mCriticalSection);
+ }
+
+ void lock()
+ {
+ EnterCriticalSection(&mCriticalSection);
+ }
+
+ void unlock()
+ {
+ LeaveCriticalSection(&mCriticalSection);
+ }
};
-
btCriticalSection* btThreadSupportWin32::createCriticalSection()
{
- unsigned char* mem = (unsigned char*) btAlignedAlloc( sizeof( btWin32CriticalSection ), 16 );
- btWin32CriticalSection* cs = new( mem ) btWin32CriticalSection();
- return cs;
+ unsigned char* mem = (unsigned char*)btAlignedAlloc(sizeof(btWin32CriticalSection), 16);
+ btWin32CriticalSection* cs = new (mem) btWin32CriticalSection();
+ return cs;
}
-void btThreadSupportWin32::deleteCriticalSection( btCriticalSection* criticalSection )
+void btThreadSupportWin32::deleteCriticalSection(btCriticalSection* criticalSection)
{
- criticalSection->~btCriticalSection();
- btAlignedFree( criticalSection );
+ criticalSection->~btCriticalSection();
+ btAlignedFree(criticalSection);
}
-
-btThreadSupportInterface* btThreadSupportInterface::create( const ConstructionInfo& info )
+btThreadSupportInterface* btThreadSupportInterface::create(const ConstructionInfo& info)
{
- return new btThreadSupportWin32( info );
+ return new btThreadSupportWin32(info);
}
-
-
-#endif //defined(_WIN32) && BT_THREADSAFE
-
+#endif //defined(_WIN32) && BT_THREADSAFE
diff --git a/thirdparty/bullet/LinearMath/btAabbUtil2.h b/thirdparty/bullet/LinearMath/btAabbUtil2.h
index d2997b4e65..eea49dd33f 100644
--- a/thirdparty/bullet/LinearMath/btAabbUtil2.h
+++ b/thirdparty/bullet/LinearMath/btAabbUtil2.h
@@ -12,8 +12,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
-
#ifndef BT_AABB_UTIL2
#define BT_AABB_UTIL2
@@ -21,20 +19,18 @@ subject to the following restrictions:
#include "btVector3.h"
#include "btMinMax.h"
-
-
-SIMD_FORCE_INLINE void AabbExpand (btVector3& aabbMin,
- btVector3& aabbMax,
- const btVector3& expansionMin,
- const btVector3& expansionMax)
+SIMD_FORCE_INLINE void AabbExpand(btVector3& aabbMin,
+ btVector3& aabbMax,
+ const btVector3& expansionMin,
+ const btVector3& expansionMax)
{
aabbMin = aabbMin + expansionMin;
aabbMax = aabbMax + expansionMax;
}
/// conservative test for overlap between two aabbs
-SIMD_FORCE_INLINE bool TestPointAgainstAabb2(const btVector3 &aabbMin1, const btVector3 &aabbMax1,
- const btVector3 &point)
+SIMD_FORCE_INLINE bool TestPointAgainstAabb2(const btVector3& aabbMin1, const btVector3& aabbMax1,
+ const btVector3& point)
{
bool overlap = true;
overlap = (aabbMin1.getX() > point.getX() || aabbMax1.getX() < point.getX()) ? false : overlap;
@@ -43,10 +39,9 @@ SIMD_FORCE_INLINE bool TestPointAgainstAabb2(const btVector3 &aabbMin1, const bt
return overlap;
}
-
/// conservative test for overlap between two aabbs
-SIMD_FORCE_INLINE bool TestAabbAgainstAabb2(const btVector3 &aabbMin1, const btVector3 &aabbMax1,
- const btVector3 &aabbMin2, const btVector3 &aabbMax2)
+SIMD_FORCE_INLINE bool TestAabbAgainstAabb2(const btVector3& aabbMin1, const btVector3& aabbMax1,
+ const btVector3& aabbMin2, const btVector3& aabbMax2)
{
bool overlap = true;
overlap = (aabbMin1.getX() > aabbMax2.getX() || aabbMax1.getX() < aabbMin2.getX()) ? false : overlap;
@@ -56,37 +51,34 @@ SIMD_FORCE_INLINE bool TestAabbAgainstAabb2(const btVector3 &aabbMin1, const btV
}
/// conservative test for overlap between triangle and aabb
-SIMD_FORCE_INLINE bool TestTriangleAgainstAabb2(const btVector3 *vertices,
- const btVector3 &aabbMin, const btVector3 &aabbMax)
+SIMD_FORCE_INLINE bool TestTriangleAgainstAabb2(const btVector3* vertices,
+ const btVector3& aabbMin, const btVector3& aabbMax)
{
- const btVector3 &p1 = vertices[0];
- const btVector3 &p2 = vertices[1];
- const btVector3 &p3 = vertices[2];
+ const btVector3& p1 = vertices[0];
+ const btVector3& p2 = vertices[1];
+ const btVector3& p3 = vertices[2];
if (btMin(btMin(p1[0], p2[0]), p3[0]) > aabbMax[0]) return false;
if (btMax(btMax(p1[0], p2[0]), p3[0]) < aabbMin[0]) return false;
if (btMin(btMin(p1[2], p2[2]), p3[2]) > aabbMax[2]) return false;
if (btMax(btMax(p1[2], p2[2]), p3[2]) < aabbMin[2]) return false;
-
+
if (btMin(btMin(p1[1], p2[1]), p3[1]) > aabbMax[1]) return false;
if (btMax(btMax(p1[1], p2[1]), p3[1]) < aabbMin[1]) return false;
return true;
}
-
-SIMD_FORCE_INLINE int btOutcode(const btVector3& p,const btVector3& halfExtent)
+SIMD_FORCE_INLINE int btOutcode(const btVector3& p, const btVector3& halfExtent)
{
- return (p.getX() < -halfExtent.getX() ? 0x01 : 0x0) |
- (p.getX() > halfExtent.getX() ? 0x08 : 0x0) |
- (p.getY() < -halfExtent.getY() ? 0x02 : 0x0) |
- (p.getY() > halfExtent.getY() ? 0x10 : 0x0) |
- (p.getZ() < -halfExtent.getZ() ? 0x4 : 0x0) |
- (p.getZ() > halfExtent.getZ() ? 0x20 : 0x0);
+ return (p.getX() < -halfExtent.getX() ? 0x01 : 0x0) |
+ (p.getX() > halfExtent.getX() ? 0x08 : 0x0) |
+ (p.getY() < -halfExtent.getY() ? 0x02 : 0x0) |
+ (p.getY() > halfExtent.getY() ? 0x10 : 0x0) |
+ (p.getZ() < -halfExtent.getZ() ? 0x4 : 0x0) |
+ (p.getZ() > halfExtent.getZ() ? 0x20 : 0x0);
}
-
-
SIMD_FORCE_INLINE bool btRayAabb2(const btVector3& rayFrom,
const btVector3& rayInvDirection,
const unsigned int raySign[3],
@@ -97,11 +89,11 @@ SIMD_FORCE_INLINE bool btRayAabb2(const btVector3& rayFrom,
{
btScalar tmax, tymin, tymax, tzmin, tzmax;
tmin = (bounds[raySign[0]].getX() - rayFrom.getX()) * rayInvDirection.getX();
- tmax = (bounds[1-raySign[0]].getX() - rayFrom.getX()) * rayInvDirection.getX();
+ tmax = (bounds[1 - raySign[0]].getX() - rayFrom.getX()) * rayInvDirection.getX();
tymin = (bounds[raySign[1]].getY() - rayFrom.getY()) * rayInvDirection.getY();
- tymax = (bounds[1-raySign[1]].getY() - rayFrom.getY()) * rayInvDirection.getY();
+ tymax = (bounds[1 - raySign[1]].getY() - rayFrom.getY()) * rayInvDirection.getY();
- if ( (tmin > tymax) || (tymin > tmax) )
+ if ((tmin > tymax) || (tymin > tmax))
return false;
if (tymin > tmin)
@@ -111,59 +103,59 @@ SIMD_FORCE_INLINE bool btRayAabb2(const btVector3& rayFrom,
tmax = tymax;
tzmin = (bounds[raySign[2]].getZ() - rayFrom.getZ()) * rayInvDirection.getZ();
- tzmax = (bounds[1-raySign[2]].getZ() - rayFrom.getZ()) * rayInvDirection.getZ();
+ tzmax = (bounds[1 - raySign[2]].getZ() - rayFrom.getZ()) * rayInvDirection.getZ();
- if ( (tmin > tzmax) || (tzmin > tmax) )
+ if ((tmin > tzmax) || (tzmin > tmax))
return false;
if (tzmin > tmin)
tmin = tzmin;
if (tzmax < tmax)
tmax = tzmax;
- return ( (tmin < lambda_max) && (tmax > lambda_min) );
+ return ((tmin < lambda_max) && (tmax > lambda_min));
}
-SIMD_FORCE_INLINE bool btRayAabb(const btVector3& rayFrom,
- const btVector3& rayTo,
- const btVector3& aabbMin,
+SIMD_FORCE_INLINE bool btRayAabb(const btVector3& rayFrom,
+ const btVector3& rayTo,
+ const btVector3& aabbMin,
const btVector3& aabbMax,
- btScalar& param, btVector3& normal)
+ btScalar& param, btVector3& normal)
{
- btVector3 aabbHalfExtent = (aabbMax-aabbMin)* btScalar(0.5);
- btVector3 aabbCenter = (aabbMax+aabbMin)* btScalar(0.5);
- btVector3 source = rayFrom - aabbCenter;
- btVector3 target = rayTo - aabbCenter;
- int sourceOutcode = btOutcode(source,aabbHalfExtent);
- int targetOutcode = btOutcode(target,aabbHalfExtent);
+ btVector3 aabbHalfExtent = (aabbMax - aabbMin) * btScalar(0.5);
+ btVector3 aabbCenter = (aabbMax + aabbMin) * btScalar(0.5);
+ btVector3 source = rayFrom - aabbCenter;
+ btVector3 target = rayTo - aabbCenter;
+ int sourceOutcode = btOutcode(source, aabbHalfExtent);
+ int targetOutcode = btOutcode(target, aabbHalfExtent);
if ((sourceOutcode & targetOutcode) == 0x0)
{
btScalar lambda_enter = btScalar(0.0);
- btScalar lambda_exit = param;
+ btScalar lambda_exit = param;
btVector3 r = target - source;
int i;
- btScalar normSign = 1;
- btVector3 hitNormal(0,0,0);
- int bit=1;
+ btScalar normSign = 1;
+ btVector3 hitNormal(0, 0, 0);
+ int bit = 1;
- for (int j=0;j<2;j++)
+ for (int j = 0; j < 2; j++)
{
for (i = 0; i != 3; ++i)
{
if (sourceOutcode & bit)
{
- btScalar lambda = (-source[i] - aabbHalfExtent[i]*normSign) / r[i];
+ btScalar lambda = (-source[i] - aabbHalfExtent[i] * normSign) / r[i];
if (lambda_enter <= lambda)
{
lambda_enter = lambda;
- hitNormal.setValue(0,0,0);
+ hitNormal.setValue(0, 0, 0);
hitNormal[i] = normSign;
}
}
- else if (targetOutcode & bit)
+ else if (targetOutcode & bit)
{
- btScalar lambda = (-source[i] - aabbHalfExtent[i]*normSign) / r[i];
+ btScalar lambda = (-source[i] - aabbHalfExtent[i] * normSign) / r[i];
btSetMin(lambda_exit, lambda);
}
- bit<<=1;
+ bit <<= 1;
}
normSign = btScalar(-1.);
}
@@ -177,56 +169,49 @@ SIMD_FORCE_INLINE bool btRayAabb(const btVector3& rayFrom,
return false;
}
-
-
-SIMD_FORCE_INLINE void btTransformAabb(const btVector3& halfExtents, btScalar margin,const btTransform& t,btVector3& aabbMinOut,btVector3& aabbMaxOut)
+SIMD_FORCE_INLINE void btTransformAabb(const btVector3& halfExtents, btScalar margin, const btTransform& t, btVector3& aabbMinOut, btVector3& aabbMaxOut)
{
- btVector3 halfExtentsWithMargin = halfExtents+btVector3(margin,margin,margin);
- btMatrix3x3 abs_b = t.getBasis().absolute();
+ btVector3 halfExtentsWithMargin = halfExtents + btVector3(margin, margin, margin);
+ btMatrix3x3 abs_b = t.getBasis().absolute();
btVector3 center = t.getOrigin();
- btVector3 extent = halfExtentsWithMargin.dot3( abs_b[0], abs_b[1], abs_b[2] );
+ btVector3 extent = halfExtentsWithMargin.dot3(abs_b[0], abs_b[1], abs_b[2]);
aabbMinOut = center - extent;
aabbMaxOut = center + extent;
}
-
-SIMD_FORCE_INLINE void btTransformAabb(const btVector3& localAabbMin,const btVector3& localAabbMax, btScalar margin,const btTransform& trans,btVector3& aabbMinOut,btVector3& aabbMaxOut)
+SIMD_FORCE_INLINE void btTransformAabb(const btVector3& localAabbMin, const btVector3& localAabbMax, btScalar margin, const btTransform& trans, btVector3& aabbMinOut, btVector3& aabbMaxOut)
{
- btAssert(localAabbMin.getX() <= localAabbMax.getX());
- btAssert(localAabbMin.getY() <= localAabbMax.getY());
- btAssert(localAabbMin.getZ() <= localAabbMax.getZ());
- btVector3 localHalfExtents = btScalar(0.5)*(localAabbMax-localAabbMin);
- localHalfExtents+=btVector3(margin,margin,margin);
-
- btVector3 localCenter = btScalar(0.5)*(localAabbMax+localAabbMin);
- btMatrix3x3 abs_b = trans.getBasis().absolute();
- btVector3 center = trans(localCenter);
- btVector3 extent = localHalfExtents.dot3( abs_b[0], abs_b[1], abs_b[2] );
- aabbMinOut = center-extent;
- aabbMaxOut = center+extent;
+ btAssert(localAabbMin.getX() <= localAabbMax.getX());
+ btAssert(localAabbMin.getY() <= localAabbMax.getY());
+ btAssert(localAabbMin.getZ() <= localAabbMax.getZ());
+ btVector3 localHalfExtents = btScalar(0.5) * (localAabbMax - localAabbMin);
+ localHalfExtents += btVector3(margin, margin, margin);
+
+ btVector3 localCenter = btScalar(0.5) * (localAabbMax + localAabbMin);
+ btMatrix3x3 abs_b = trans.getBasis().absolute();
+ btVector3 center = trans(localCenter);
+ btVector3 extent = localHalfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
+ aabbMinOut = center - extent;
+ aabbMaxOut = center + extent;
}
#define USE_BANCHLESS 1
#ifdef USE_BANCHLESS
- //This block replaces the block below and uses no branches, and replaces the 8 bit return with a 32 bit return for improved performance (~3x on XBox 360)
- SIMD_FORCE_INLINE unsigned testQuantizedAabbAgainstQuantizedAabb(const unsigned short int* aabbMin1,const unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2)
- {
- return static_cast<unsigned int>(btSelect((unsigned)((aabbMin1[0] <= aabbMax2[0]) & (aabbMax1[0] >= aabbMin2[0])
- & (aabbMin1[2] <= aabbMax2[2]) & (aabbMax1[2] >= aabbMin2[2])
- & (aabbMin1[1] <= aabbMax2[1]) & (aabbMax1[1] >= aabbMin2[1])),
- 1, 0));
- }
+//This block replaces the block below and uses no branches, and replaces the 8 bit return with a 32 bit return for improved performance (~3x on XBox 360)
+SIMD_FORCE_INLINE unsigned testQuantizedAabbAgainstQuantizedAabb(const unsigned short int* aabbMin1, const unsigned short int* aabbMax1, const unsigned short int* aabbMin2, const unsigned short int* aabbMax2)
+{
+ return static_cast<unsigned int>(btSelect((unsigned)((aabbMin1[0] <= aabbMax2[0]) & (aabbMax1[0] >= aabbMin2[0]) & (aabbMin1[2] <= aabbMax2[2]) & (aabbMax1[2] >= aabbMin2[2]) & (aabbMin1[1] <= aabbMax2[1]) & (aabbMax1[1] >= aabbMin2[1])),
+ 1, 0));
+}
#else
- SIMD_FORCE_INLINE bool testQuantizedAabbAgainstQuantizedAabb(const unsigned short int* aabbMin1,const unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2)
- {
- bool overlap = true;
- overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? false : overlap;
- overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? false : overlap;
- overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? false : overlap;
- return overlap;
- }
-#endif //USE_BANCHLESS
-
-#endif //BT_AABB_UTIL2
-
+SIMD_FORCE_INLINE bool testQuantizedAabbAgainstQuantizedAabb(const unsigned short int* aabbMin1, const unsigned short int* aabbMax1, const unsigned short int* aabbMin2, const unsigned short int* aabbMax2)
+{
+ bool overlap = true;
+ overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? false : overlap;
+ overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? false : overlap;
+ overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? false : overlap;
+ return overlap;
+}
+#endif //USE_BANCHLESS
+#endif //BT_AABB_UTIL2
diff --git a/thirdparty/bullet/LinearMath/btAlignedAllocator.cpp b/thirdparty/bullet/LinearMath/btAlignedAllocator.cpp
index 0526a42283..39b302b600 100644
--- a/thirdparty/bullet/LinearMath/btAlignedAllocator.cpp
+++ b/thirdparty/bullet/LinearMath/btAlignedAllocator.cpp
@@ -18,8 +18,8 @@ subject to the following restrictions:
#ifdef BT_DEBUG_MEMORY_ALLOCATIONS
int gNumAlignedAllocs = 0;
int gNumAlignedFree = 0;
-int gTotalBytesAlignedAllocs = 0;//detect memory leaks
-#endif //BT_DEBUG_MEMORY_ALLOCATIONST_DEBUG_ALLOCATIONS
+int gTotalBytesAlignedAllocs = 0; //detect memory leaks
+#endif //BT_DEBUG_MEMORY_ALLOCATIONST_DEBUG_ALLOCATIONS
static void *btAllocDefault(size_t size)
{
@@ -34,9 +34,7 @@ static void btFreeDefault(void *ptr)
static btAllocFunc *sAllocFunc = btAllocDefault;
static btFreeFunc *sFreeFunc = btFreeDefault;
-
-
-#if defined (BT_HAS_ALIGNED_ALLOCATOR)
+#if defined(BT_HAS_ALIGNED_ALLOCATOR)
#include <malloc.h>
static void *btAlignedAllocDefault(size_t size, int alignment)
{
@@ -61,49 +59,48 @@ static inline void btAlignedFreeDefault(void *ptr)
}
#else
-
-
-
-
static inline void *btAlignedAllocDefault(size_t size, int alignment)
{
- void *ret;
- char *real;
- real = (char *)sAllocFunc(size + sizeof(void *) + (alignment-1));
- if (real) {
- ret = btAlignPointer(real + sizeof(void *),alignment);
- *((void **)(ret)-1) = (void *)(real);
- } else {
- ret = (void *)(real);
- }
- return (ret);
+ void *ret;
+ char *real;
+ real = (char *)sAllocFunc(size + sizeof(void *) + (alignment - 1));
+ if (real)
+ {
+ ret = btAlignPointer(real + sizeof(void *), alignment);
+ *((void **)(ret)-1) = (void *)(real);
+ }
+ else
+ {
+ ret = (void *)(real);
+ }
+ return (ret);
}
static inline void btAlignedFreeDefault(void *ptr)
{
- void* real;
+ void *real;
- if (ptr) {
- real = *((void **)(ptr)-1);
- sFreeFunc(real);
- }
+ if (ptr)
+ {
+ real = *((void **)(ptr)-1);
+ sFreeFunc(real);
+ }
}
#endif
-
static btAlignedAllocFunc *sAlignedAllocFunc = btAlignedAllocDefault;
static btAlignedFreeFunc *sAlignedFreeFunc = btAlignedFreeDefault;
void btAlignedAllocSetCustomAligned(btAlignedAllocFunc *allocFunc, btAlignedFreeFunc *freeFunc)
{
- sAlignedAllocFunc = allocFunc ? allocFunc : btAlignedAllocDefault;
- sAlignedFreeFunc = freeFunc ? freeFunc : btAlignedFreeDefault;
+ sAlignedAllocFunc = allocFunc ? allocFunc : btAlignedAllocDefault;
+ sAlignedFreeFunc = freeFunc ? freeFunc : btAlignedFreeDefault;
}
void btAlignedAllocSetCustom(btAllocFunc *allocFunc, btFreeFunc *freeFunc)
{
- sAllocFunc = allocFunc ? allocFunc : btAllocDefault;
- sFreeFunc = freeFunc ? freeFunc : btFreeDefault;
+ sAllocFunc = allocFunc ? allocFunc : btAllocDefault;
+ sFreeFunc = freeFunc ? freeFunc : btFreeDefault;
}
#ifdef BT_DEBUG_MEMORY_ALLOCATIONS
@@ -116,15 +113,15 @@ static int mynumallocs = 0;
int btDumpMemoryLeaks()
{
int totalLeak = 0;
-
- for (int i=0;i<mynumallocs;i++)
+
+ for (int i = 0; i < mynumallocs; i++)
{
printf("Error: leaked memory of allocation #%d (%d bytes)\n", allocations_id[i], allocations_bytes[i]);
- totalLeak+=allocations_bytes[i];
+ totalLeak += allocations_bytes[i];
}
if (totalLeak)
{
- printf("Error: memory leaks: %d allocations were not freed and leaked together %d bytes\n",mynumallocs,totalLeak);
+ printf("Error: memory leaks: %d allocations were not freed and leaked together %d bytes\n", mynumallocs, totalLeak);
}
return totalLeak;
}
@@ -133,137 +130,134 @@ int btDumpMemoryLeaks()
struct btDebugPtrMagic
{
- union
- {
- void** vptrptr;
- void* vptr;
- int* iptr;
- char* cptr;
+ union {
+ void **vptrptr;
+ void *vptr;
+ int *iptr;
+ char *cptr;
};
};
-
-void* btAlignedAllocInternal (size_t size, int alignment,int line,char* filename)
+void *btAlignedAllocInternal(size_t size, int alignment, int line, char *filename)
{
- if (size==0)
+ if (size == 0)
{
printf("Whaat? size==0");
return 0;
}
static int allocId = 0;
-
- void *ret;
- char *real;
-
-// to find some particular memory leak, you could do something like this:
-// if (allocId==172)
-// {
-// printf("catch me!\n");
-// }
-// if (size>1024*1024)
-// {
-// printf("big alloc!%d\n", size);
-// }
-
- gTotalBytesAlignedAllocs += size;
- gNumAlignedAllocs++;
-
-
-int sz4prt = 4*sizeof(void *);
-
- real = (char *)sAllocFunc(size + sz4prt + (alignment-1));
- if (real) {
-
- ret = (void*) btAlignPointer(real + sz4prt, alignment);
- btDebugPtrMagic p;
- p.vptr = ret;
- p.cptr-=sizeof(void*);
- *p.vptrptr = (void*)real;
- p.cptr-=sizeof(void*);
- *p.iptr = size;
- p.cptr-=sizeof(void*);
- *p.iptr = allocId;
-
- allocations_id[mynumallocs] = allocId;
- allocations_bytes[mynumallocs] = size;
- mynumallocs++;
-
- } else {
- ret = (void *)(real);//??
- }
-
- printf("allocation %d at address %x, from %s,line %d, size %d (total allocated = %d)\n",allocId,real, filename,line,size,gTotalBytesAlignedAllocs);
+
+ void *ret;
+ char *real;
+
+ // to find some particular memory leak, you could do something like this:
+ // if (allocId==172)
+ // {
+ // printf("catch me!\n");
+ // }
+ // if (size>1024*1024)
+ // {
+ // printf("big alloc!%d\n", size);
+ // }
+
+ gTotalBytesAlignedAllocs += size;
+ gNumAlignedAllocs++;
+
+ int sz4prt = 4 * sizeof(void *);
+
+ real = (char *)sAllocFunc(size + sz4prt + (alignment - 1));
+ if (real)
+ {
+ ret = (void *)btAlignPointer(real + sz4prt, alignment);
+ btDebugPtrMagic p;
+ p.vptr = ret;
+ p.cptr -= sizeof(void *);
+ *p.vptrptr = (void *)real;
+ p.cptr -= sizeof(void *);
+ *p.iptr = size;
+ p.cptr -= sizeof(void *);
+ *p.iptr = allocId;
+
+ allocations_id[mynumallocs] = allocId;
+ allocations_bytes[mynumallocs] = size;
+ mynumallocs++;
+ }
+ else
+ {
+ ret = (void *)(real); //??
+ }
+
+ printf("allocation %d at address %x, from %s,line %d, size %d (total allocated = %d)\n", allocId, real, filename, line, size, gTotalBytesAlignedAllocs);
allocId++;
-
- int* ptr = (int*)ret;
- *ptr = 12;
- return (ret);
+
+ int *ptr = (int *)ret;
+ *ptr = 12;
+ return (ret);
}
-void btAlignedFreeInternal (void* ptr,int line,char* filename)
+void btAlignedFreeInternal(void *ptr, int line, char *filename)
{
+ void *real;
- void* real;
-
- if (ptr) {
- gNumAlignedFree++;
-
- btDebugPtrMagic p;
- p.vptr = ptr;
- p.cptr-=sizeof(void*);
- real = *p.vptrptr;
- p.cptr-=sizeof(void*);
- int size = *p.iptr;
- p.cptr-=sizeof(void*);
- int allocId = *p.iptr;
-
- bool found = false;
-
- for (int i=0;i<mynumallocs;i++)
- {
- if ( allocations_id[i] == allocId)
- {
- allocations_id[i] = allocations_id[mynumallocs-1];
- allocations_bytes[i] = allocations_bytes[mynumallocs-1];
- mynumallocs--;
- found = true;
- break;
- }
- }
-
-
- gTotalBytesAlignedAllocs -= size;
-
- int diff = gNumAlignedAllocs-gNumAlignedFree;
- printf("free %d at address %x, from %s,line %d, size %d (total remain = %d in %d non-freed allocations)\n",allocId,real, filename,line,size, gTotalBytesAlignedAllocs, diff);
-
- sFreeFunc(real);
- } else
- {
- //printf("deleting a NULL ptr, no effect\n");
- }
+ if (ptr)
+ {
+ gNumAlignedFree++;
+
+ btDebugPtrMagic p;
+ p.vptr = ptr;
+ p.cptr -= sizeof(void *);
+ real = *p.vptrptr;
+ p.cptr -= sizeof(void *);
+ int size = *p.iptr;
+ p.cptr -= sizeof(void *);
+ int allocId = *p.iptr;
+
+ bool found = false;
+
+ for (int i = 0; i < mynumallocs; i++)
+ {
+ if (allocations_id[i] == allocId)
+ {
+ allocations_id[i] = allocations_id[mynumallocs - 1];
+ allocations_bytes[i] = allocations_bytes[mynumallocs - 1];
+ mynumallocs--;
+ found = true;
+ break;
+ }
+ }
+
+ gTotalBytesAlignedAllocs -= size;
+
+ int diff = gNumAlignedAllocs - gNumAlignedFree;
+ printf("free %d at address %x, from %s,line %d, size %d (total remain = %d in %d non-freed allocations)\n", allocId, real, filename, line, size, gTotalBytesAlignedAllocs, diff);
+
+ sFreeFunc(real);
+ }
+ else
+ {
+ //printf("deleting a NULL ptr, no effect\n");
+ }
}
-#else //BT_DEBUG_MEMORY_ALLOCATIONS
+#else //BT_DEBUG_MEMORY_ALLOCATIONS
-void* btAlignedAllocInternal (size_t size, int alignment)
+void *btAlignedAllocInternal(size_t size, int alignment)
{
- void* ptr;
+ void *ptr;
ptr = sAlignedAllocFunc(size, alignment);
-// printf("btAlignedAllocInternal %d, %x\n",size,ptr);
+ // printf("btAlignedAllocInternal %d, %x\n",size,ptr);
return ptr;
}
-void btAlignedFreeInternal (void* ptr)
+void btAlignedFreeInternal(void *ptr)
{
if (!ptr)
{
return;
}
-// printf("btAlignedFreeInternal %x\n",ptr);
+ // printf("btAlignedFreeInternal %x\n",ptr);
sAlignedFreeFunc(ptr);
}
-#endif //BT_DEBUG_MEMORY_ALLOCATIONS
-
+#endif //BT_DEBUG_MEMORY_ALLOCATIONS
diff --git a/thirdparty/bullet/LinearMath/btAlignedAllocator.h b/thirdparty/bullet/LinearMath/btAlignedAllocator.h
index 9873b338d9..ce4d3585f1 100644
--- a/thirdparty/bullet/LinearMath/btAlignedAllocator.h
+++ b/thirdparty/bullet/LinearMath/btAlignedAllocator.h
@@ -22,7 +22,6 @@ subject to the following restrictions:
#include "btScalar.h"
-
///BT_DEBUG_MEMORY_ALLOCATIONS preprocessor can be set in build system
///for regression tests to detect memory leaks
///#define BT_DEBUG_MEMORY_ALLOCATIONS 1
@@ -30,84 +29,87 @@ subject to the following restrictions:
int btDumpMemoryLeaks();
-#define btAlignedAlloc(a,b) \
- btAlignedAllocInternal(a,b,__LINE__,__FILE__)
+#define btAlignedAlloc(a, b) \
+ btAlignedAllocInternal(a, b, __LINE__, __FILE__)
#define btAlignedFree(ptr) \
- btAlignedFreeInternal(ptr,__LINE__,__FILE__)
+ btAlignedFreeInternal(ptr, __LINE__, __FILE__)
-void* btAlignedAllocInternal (size_t size, int alignment,int line,char* filename);
+void* btAlignedAllocInternal(size_t size, int alignment, int line, char* filename);
-void btAlignedFreeInternal (void* ptr,int line,char* filename);
+void btAlignedFreeInternal(void* ptr, int line, char* filename);
#else
- void* btAlignedAllocInternal (size_t size, int alignment);
- void btAlignedFreeInternal (void* ptr);
+void* btAlignedAllocInternal(size_t size, int alignment);
+void btAlignedFreeInternal(void* ptr);
- #define btAlignedAlloc(size,alignment) btAlignedAllocInternal(size,alignment)
- #define btAlignedFree(ptr) btAlignedFreeInternal(ptr)
+#define btAlignedAlloc(size, alignment) btAlignedAllocInternal(size, alignment)
+#define btAlignedFree(ptr) btAlignedFreeInternal(ptr)
#endif
-typedef int size_type;
+typedef int size_type;
-typedef void *(btAlignedAllocFunc)(size_t size, int alignment);
-typedef void (btAlignedFreeFunc)(void *memblock);
-typedef void *(btAllocFunc)(size_t size);
-typedef void (btFreeFunc)(void *memblock);
+typedef void*(btAlignedAllocFunc)(size_t size, int alignment);
+typedef void(btAlignedFreeFunc)(void* memblock);
+typedef void*(btAllocFunc)(size_t size);
+typedef void(btFreeFunc)(void* memblock);
///The developer can let all Bullet memory allocations go through a custom memory allocator, using btAlignedAllocSetCustom
-void btAlignedAllocSetCustom(btAllocFunc *allocFunc, btFreeFunc *freeFunc);
+void btAlignedAllocSetCustom(btAllocFunc* allocFunc, btFreeFunc* freeFunc);
///If the developer has already an custom aligned allocator, then btAlignedAllocSetCustomAligned can be used. The default aligned allocator pre-allocates extra memory using the non-aligned allocator, and instruments it.
-void btAlignedAllocSetCustomAligned(btAlignedAllocFunc *allocFunc, btAlignedFreeFunc *freeFunc);
-
+void btAlignedAllocSetCustomAligned(btAlignedAllocFunc* allocFunc, btAlignedFreeFunc* freeFunc);
///The btAlignedAllocator is a portable class for aligned memory allocations.
///Default implementations for unaligned and aligned allocations can be overridden by a custom allocator using btAlignedAllocSetCustom and btAlignedAllocSetCustomAligned.
-template < typename T , unsigned Alignment >
-class btAlignedAllocator {
-
- typedef btAlignedAllocator< T , Alignment > self_type;
-
-public:
+template <typename T, unsigned Alignment>
+class btAlignedAllocator
+{
+ typedef btAlignedAllocator<T, Alignment> self_type;
+public:
//just going down a list:
btAlignedAllocator() {}
/*
btAlignedAllocator( const self_type & ) {}
*/
- template < typename Other >
- btAlignedAllocator( const btAlignedAllocator< Other , Alignment > & ) {}
+ template <typename Other>
+ btAlignedAllocator(const btAlignedAllocator<Other, Alignment>&)
+ {
+ }
- typedef const T* const_pointer;
- typedef const T& const_reference;
- typedef T* pointer;
- typedef T& reference;
- typedef T value_type;
+ typedef const T* const_pointer;
+ typedef const T& const_reference;
+ typedef T* pointer;
+ typedef T& reference;
+ typedef T value_type;
- pointer address ( reference ref ) const { return &ref; }
- const_pointer address ( const_reference ref ) const { return &ref; }
- pointer allocate ( size_type n , const_pointer * hint = 0 ) {
+ pointer address(reference ref) const { return &ref; }
+ const_pointer address(const_reference ref) const { return &ref; }
+ pointer allocate(size_type n, const_pointer* hint = 0)
+ {
(void)hint;
- return reinterpret_cast< pointer >(btAlignedAlloc( sizeof(value_type) * n , Alignment ));
+ return reinterpret_cast<pointer>(btAlignedAlloc(sizeof(value_type) * n, Alignment));
}
- void construct ( pointer ptr , const value_type & value ) { new (ptr) value_type( value ); }
- void deallocate( pointer ptr ) {
- btAlignedFree( reinterpret_cast< void * >( ptr ) );
+ void construct(pointer ptr, const value_type& value) { new (ptr) value_type(value); }
+ void deallocate(pointer ptr)
+ {
+ btAlignedFree(reinterpret_cast<void*>(ptr));
}
- void destroy ( pointer ptr ) { ptr->~value_type(); }
-
+ void destroy(pointer ptr) { ptr->~value_type(); }
- template < typename O > struct rebind {
- typedef btAlignedAllocator< O , Alignment > other;
+ template <typename O>
+ struct rebind
+ {
+ typedef btAlignedAllocator<O, Alignment> other;
};
- template < typename O >
- self_type & operator=( const btAlignedAllocator< O , Alignment > & ) { return *this; }
+ template <typename O>
+ self_type& operator=(const btAlignedAllocator<O, Alignment>&)
+ {
+ return *this;
+ }
- friend bool operator==( const self_type & , const self_type & ) { return true; }
+ friend bool operator==(const self_type&, const self_type&) { return true; }
};
-
-
-#endif //BT_ALIGNED_ALLOCATOR
-
+#endif //BT_ALIGNED_ALLOCATOR
diff --git a/thirdparty/bullet/LinearMath/btAlignedObjectArray.h b/thirdparty/bullet/LinearMath/btAlignedObjectArray.h
index f0b646529a..b4671bc19f 100644
--- a/thirdparty/bullet/LinearMath/btAlignedObjectArray.h
+++ b/thirdparty/bullet/LinearMath/btAlignedObjectArray.h
@@ -13,11 +13,10 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#ifndef BT_OBJECT_ARRAY__
#define BT_OBJECT_ARRAY__
-#include "btScalar.h" // has definitions like SIMD_FORCE_INLINE
+#include "btScalar.h" // has definitions like SIMD_FORCE_INLINE
#include "btAlignedAllocator.h"
///If the platform doesn't support placement new, you can disable BT_USE_PLACEMENT_NEW
@@ -28,16 +27,16 @@ subject to the following restrictions:
#define BT_USE_PLACEMENT_NEW 1
//#define BT_USE_MEMCPY 1 //disable, because it is cumbersome to find out for each platform where memcpy is defined. It can be in <memory.h> or <string.h> or otherwise...
-#define BT_ALLOW_ARRAY_COPY_OPERATOR // enabling this can accidently perform deep copies of data if you are not careful
+#define BT_ALLOW_ARRAY_COPY_OPERATOR // enabling this can accidently perform deep copies of data if you are not careful
#ifdef BT_USE_MEMCPY
#include <memory.h>
#include <string.h>
-#endif //BT_USE_MEMCPY
+#endif //BT_USE_MEMCPY
#ifdef BT_USE_PLACEMENT_NEW
-#include <new> //for placement new
-#endif //BT_USE_PLACEMENT_NEW
+#include <new> //for placement new
+#endif //BT_USE_PLACEMENT_NEW
// The register keyword is deprecated in C++11 so don't use it.
#if __cplusplus > 199711L
@@ -48,374 +47,358 @@ subject to the following restrictions:
///The btAlignedObjectArray template class uses a subset of the stl::vector interface for its methods
///It is developed to replace stl::vector to avoid portability issues, including STL alignment issues to add SIMD/SSE data
-template <typename T>
-//template <class T>
+template <typename T>
+//template <class T>
class btAlignedObjectArray
{
- btAlignedAllocator<T , 16> m_allocator;
+ btAlignedAllocator<T, 16> m_allocator;
- int m_size;
- int m_capacity;
- T* m_data;
+ int m_size;
+ int m_capacity;
+ T* m_data;
//PCK: added this line
- bool m_ownsMemory;
+ bool m_ownsMemory;
#ifdef BT_ALLOW_ARRAY_COPY_OPERATOR
public:
- SIMD_FORCE_INLINE btAlignedObjectArray<T>& operator=(const btAlignedObjectArray<T> &other)
+ SIMD_FORCE_INLINE btAlignedObjectArray<T>& operator=(const btAlignedObjectArray<T>& other)
{
copyFromArray(other);
return *this;
}
-#else//BT_ALLOW_ARRAY_COPY_OPERATOR
+#else //BT_ALLOW_ARRAY_COPY_OPERATOR
private:
- SIMD_FORCE_INLINE btAlignedObjectArray<T>& operator=(const btAlignedObjectArray<T> &other);
-#endif//BT_ALLOW_ARRAY_COPY_OPERATOR
+ SIMD_FORCE_INLINE btAlignedObjectArray<T>& operator=(const btAlignedObjectArray<T>& other);
+#endif //BT_ALLOW_ARRAY_COPY_OPERATOR
protected:
- SIMD_FORCE_INLINE int allocSize(int size)
- {
- return (size ? size*2 : 1);
- }
- SIMD_FORCE_INLINE void copy(int start,int end, T* dest) const
- {
- int i;
- for (i=start;i<end;++i)
+ SIMD_FORCE_INLINE int allocSize(int size)
+ {
+ return (size ? size * 2 : 1);
+ }
+ SIMD_FORCE_INLINE void copy(int start, int end, T* dest) const
+ {
+ int i;
+ for (i = start; i < end; ++i)
#ifdef BT_USE_PLACEMENT_NEW
- new (&dest[i]) T(m_data[i]);
+ new (&dest[i]) T(m_data[i]);
#else
- dest[i] = m_data[i];
-#endif //BT_USE_PLACEMENT_NEW
- }
+ dest[i] = m_data[i];
+#endif //BT_USE_PLACEMENT_NEW
+ }
- SIMD_FORCE_INLINE void init()
+ SIMD_FORCE_INLINE void init()
+ {
+ //PCK: added this line
+ m_ownsMemory = true;
+ m_data = 0;
+ m_size = 0;
+ m_capacity = 0;
+ }
+ SIMD_FORCE_INLINE void destroy(int first, int last)
+ {
+ int i;
+ for (i = first; i < last; i++)
{
- //PCK: added this line
- m_ownsMemory = true;
- m_data = 0;
- m_size = 0;
- m_capacity = 0;
+ m_data[i].~T();
}
- SIMD_FORCE_INLINE void destroy(int first,int last)
+ }
+
+ SIMD_FORCE_INLINE void* allocate(int size)
+ {
+ if (size)
+ return m_allocator.allocate(size);
+ return 0;
+ }
+
+ SIMD_FORCE_INLINE void deallocate()
+ {
+ if (m_data)
{
- int i;
- for (i=first; i<last;i++)
+ //PCK: enclosed the deallocation in this block
+ if (m_ownsMemory)
{
- m_data[i].~T();
+ m_allocator.deallocate(m_data);
}
+ m_data = 0;
}
+ }
- SIMD_FORCE_INLINE void* allocate(int size)
- {
- if (size)
- return m_allocator.allocate(size);
- return 0;
- }
+public:
+ btAlignedObjectArray()
+ {
+ init();
+ }
- SIMD_FORCE_INLINE void deallocate()
- {
- if(m_data) {
- //PCK: enclosed the deallocation in this block
- if (m_ownsMemory)
- {
- m_allocator.deallocate(m_data);
- }
- m_data = 0;
- }
- }
+ ~btAlignedObjectArray()
+ {
+ clear();
+ }
-
+ ///Generally it is best to avoid using the copy constructor of an btAlignedObjectArray, and use a (const) reference to the array instead.
+ btAlignedObjectArray(const btAlignedObjectArray& otherArray)
+ {
+ init();
+ int otherSize = otherArray.size();
+ resize(otherSize);
+ otherArray.copy(0, otherSize, m_data);
+ }
- public:
-
- btAlignedObjectArray()
- {
- init();
- }
+ /// return the number of elements in the array
+ SIMD_FORCE_INLINE int size() const
+ {
+ return m_size;
+ }
- ~btAlignedObjectArray()
- {
- clear();
- }
+ SIMD_FORCE_INLINE const T& at(int n) const
+ {
+ btAssert(n >= 0);
+ btAssert(n < size());
+ return m_data[n];
+ }
- ///Generally it is best to avoid using the copy constructor of an btAlignedObjectArray, and use a (const) reference to the array instead.
- btAlignedObjectArray(const btAlignedObjectArray& otherArray)
- {
- init();
+ SIMD_FORCE_INLINE T& at(int n)
+ {
+ btAssert(n >= 0);
+ btAssert(n < size());
+ return m_data[n];
+ }
- int otherSize = otherArray.size();
- resize (otherSize);
- otherArray.copy(0, otherSize, m_data);
- }
+ SIMD_FORCE_INLINE const T& operator[](int n) const
+ {
+ btAssert(n >= 0);
+ btAssert(n < size());
+ return m_data[n];
+ }
-
-
- /// return the number of elements in the array
- SIMD_FORCE_INLINE int size() const
- {
- return m_size;
- }
-
- SIMD_FORCE_INLINE const T& at(int n) const
- {
- btAssert(n>=0);
- btAssert(n<size());
- return m_data[n];
- }
+ SIMD_FORCE_INLINE T& operator[](int n)
+ {
+ btAssert(n >= 0);
+ btAssert(n < size());
+ return m_data[n];
+ }
- SIMD_FORCE_INLINE T& at(int n)
- {
- btAssert(n>=0);
- btAssert(n<size());
- return m_data[n];
- }
+ ///clear the array, deallocated memory. Generally it is better to use array.resize(0), to reduce performance overhead of run-time memory (de)allocations.
+ SIMD_FORCE_INLINE void clear()
+ {
+ destroy(0, size());
- SIMD_FORCE_INLINE const T& operator[](int n) const
- {
- btAssert(n>=0);
- btAssert(n<size());
- return m_data[n];
- }
+ deallocate();
- SIMD_FORCE_INLINE T& operator[](int n)
- {
- btAssert(n>=0);
- btAssert(n<size());
- return m_data[n];
- }
-
+ init();
+ }
- ///clear the array, deallocated memory. Generally it is better to use array.resize(0), to reduce performance overhead of run-time memory (de)allocations.
- SIMD_FORCE_INLINE void clear()
- {
- destroy(0,size());
-
- deallocate();
-
- init();
- }
+ SIMD_FORCE_INLINE void pop_back()
+ {
+ btAssert(m_size > 0);
+ m_size--;
+ m_data[m_size].~T();
+ }
- SIMD_FORCE_INLINE void pop_back()
+ ///resize changes the number of elements in the array. If the new size is larger, the new elements will be constructed using the optional second argument.
+ ///when the new number of elements is smaller, the destructor will be called, but memory will not be freed, to reduce performance overhead of run-time memory (de)allocations.
+ SIMD_FORCE_INLINE void resizeNoInitialize(int newsize)
+ {
+ if (newsize > size())
{
- btAssert(m_size>0);
- m_size--;
- m_data[m_size].~T();
+ reserve(newsize);
}
+ m_size = newsize;
+ }
+ SIMD_FORCE_INLINE void resize(int newsize, const T& fillData = T())
+ {
+ const BT_REGISTER int curSize = size();
- ///resize changes the number of elements in the array. If the new size is larger, the new elements will be constructed using the optional second argument.
- ///when the new number of elements is smaller, the destructor will be called, but memory will not be freed, to reduce performance overhead of run-time memory (de)allocations.
- SIMD_FORCE_INLINE void resizeNoInitialize(int newsize)
+ if (newsize < curSize)
{
- if (newsize > size())
+ for (int i = newsize; i < curSize; i++)
{
- reserve(newsize);
+ m_data[i].~T();
}
- m_size = newsize;
}
-
- SIMD_FORCE_INLINE void resize(int newsize, const T& fillData=T())
+ else
{
- const BT_REGISTER int curSize = size();
-
- if (newsize < curSize)
+ if (newsize > curSize)
{
- for(int i = newsize; i < curSize; i++)
- {
- m_data[i].~T();
- }
- } else
- {
- if (newsize > curSize)
- {
- reserve(newsize);
- }
-#ifdef BT_USE_PLACEMENT_NEW
- for (int i=curSize;i<newsize;i++)
- {
- new ( &m_data[i]) T(fillData);
- }
-#endif //BT_USE_PLACEMENT_NEW
-
+ reserve(newsize);
}
-
- m_size = newsize;
- }
- SIMD_FORCE_INLINE T& expandNonInitializing( )
- {
- const BT_REGISTER int sz = size();
- if( sz == capacity() )
+#ifdef BT_USE_PLACEMENT_NEW
+ for (int i = curSize; i < newsize; i++)
{
- reserve( allocSize(size()) );
+ new (&m_data[i]) T(fillData);
}
- m_size++;
+#endif //BT_USE_PLACEMENT_NEW
+ }
- return m_data[sz];
+ m_size = newsize;
+ }
+ SIMD_FORCE_INLINE T& expandNonInitializing()
+ {
+ const BT_REGISTER int sz = size();
+ if (sz == capacity())
+ {
+ reserve(allocSize(size()));
}
+ m_size++;
+ return m_data[sz];
+ }
- SIMD_FORCE_INLINE T& expand( const T& fillValue=T())
- {
- const BT_REGISTER int sz = size();
- if( sz == capacity() )
- {
- reserve( allocSize(size()) );
- }
- m_size++;
+ SIMD_FORCE_INLINE T& expand(const T& fillValue = T())
+ {
+ const BT_REGISTER int sz = size();
+ if (sz == capacity())
+ {
+ reserve(allocSize(size()));
+ }
+ m_size++;
#ifdef BT_USE_PLACEMENT_NEW
- new (&m_data[sz]) T(fillValue); //use the in-place new (not really allocating heap memory)
+ new (&m_data[sz]) T(fillValue); //use the in-place new (not really allocating heap memory)
#endif
- return m_data[sz];
- }
+ return m_data[sz];
+ }
+ SIMD_FORCE_INLINE void push_back(const T& _Val)
+ {
+ const BT_REGISTER int sz = size();
+ if (sz == capacity())
+ {
+ reserve(allocSize(size()));
+ }
- SIMD_FORCE_INLINE void push_back(const T& _Val)
- {
- const BT_REGISTER int sz = size();
- if( sz == capacity() )
- {
- reserve( allocSize(size()) );
- }
-
#ifdef BT_USE_PLACEMENT_NEW
- new ( &m_data[m_size] ) T(_Val);
+ new (&m_data[m_size]) T(_Val);
#else
- m_data[size()] = _Val;
-#endif //BT_USE_PLACEMENT_NEW
-
- m_size++;
- }
+ m_data[size()] = _Val;
+#endif //BT_USE_PLACEMENT_NEW
-
- /// return the pre-allocated (reserved) elements, this is at least as large as the total number of elements,see size() and reserve()
- SIMD_FORCE_INLINE int capacity() const
- {
- return m_capacity;
- }
-
- SIMD_FORCE_INLINE void reserve(int _Count)
- { // determine new minimum length of allocated storage
- if (capacity() < _Count)
- { // not enough room, reallocate
- T* s = (T*)allocate(_Count);
+ m_size++;
+ }
- copy(0, size(), s);
+ /// return the pre-allocated (reserved) elements, this is at least as large as the total number of elements,see size() and reserve()
+ SIMD_FORCE_INLINE int capacity() const
+ {
+ return m_capacity;
+ }
- destroy(0,size());
+ SIMD_FORCE_INLINE void reserve(int _Count)
+ { // determine new minimum length of allocated storage
+ if (capacity() < _Count)
+ { // not enough room, reallocate
+ T* s = (T*)allocate(_Count);
- deallocate();
-
- //PCK: added this line
- m_ownsMemory = true;
+ copy(0, size(), s);
- m_data = s;
-
- m_capacity = _Count;
+ destroy(0, size());
- }
- }
+ deallocate();
+ //PCK: added this line
+ m_ownsMemory = true;
- class less
- {
- public:
+ m_data = s;
- bool operator() ( const T& a, const T& b ) const
- {
- return ( a < b );
- }
- };
-
+ m_capacity = _Count;
+ }
+ }
- template <typename L>
- void quickSortInternal(const L& CompareFunc,int lo, int hi)
+ class less
+ {
+ public:
+ bool operator()(const T& a, const T& b) const
{
- // lo is the lower index, hi is the upper index
- // of the region of array a that is to be sorted
- int i=lo, j=hi;
- T x=m_data[(lo+hi)/2];
-
- // partition
- do
- {
- while (CompareFunc(m_data[i],x))
- i++;
- while (CompareFunc(x,m_data[j]))
- j--;
- if (i<=j)
- {
- swap(i,j);
- i++; j--;
- }
- } while (i<=j);
-
- // recursion
- if (lo<j)
- quickSortInternal( CompareFunc, lo, j);
- if (i<hi)
- quickSortInternal( CompareFunc, i, hi);
+ return (a < b);
}
+ };
+ template <typename L>
+ void quickSortInternal(const L& CompareFunc, int lo, int hi)
+ {
+ // lo is the lower index, hi is the upper index
+ // of the region of array a that is to be sorted
+ int i = lo, j = hi;
+ T x = m_data[(lo + hi) / 2];
- template <typename L>
- void quickSort(const L& CompareFunc)
+ // partition
+ do
{
- //don't sort 0 or 1 elements
- if (size()>1)
+ while (CompareFunc(m_data[i], x))
+ i++;
+ while (CompareFunc(x, m_data[j]))
+ j--;
+ if (i <= j)
{
- quickSortInternal(CompareFunc,0,size()-1);
+ swap(i, j);
+ i++;
+ j--;
}
+ } while (i <= j);
+
+ // recursion
+ if (lo < j)
+ quickSortInternal(CompareFunc, lo, j);
+ if (i < hi)
+ quickSortInternal(CompareFunc, i, hi);
+ }
+
+ template <typename L>
+ void quickSort(const L& CompareFunc)
+ {
+ //don't sort 0 or 1 elements
+ if (size() > 1)
+ {
+ quickSortInternal(CompareFunc, 0, size() - 1);
}
+ }
+ ///heap sort from http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Heap/
+ template <typename L>
+ void downHeap(T* pArr, int k, int n, const L& CompareFunc)
+ {
+ /* PRE: a[k+1..N] is a heap */
+ /* POST: a[k..N] is a heap */
- ///heap sort from http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Heap/
- template <typename L>
- void downHeap(T *pArr, int k, int n, const L& CompareFunc)
+ T temp = pArr[k - 1];
+ /* k has child(s) */
+ while (k <= n / 2)
{
- /* PRE: a[k+1..N] is a heap */
- /* POST: a[k..N] is a heap */
-
- T temp = pArr[k - 1];
- /* k has child(s) */
- while (k <= n/2)
+ int child = 2 * k;
+
+ if ((child < n) && CompareFunc(pArr[child - 1], pArr[child]))
+ {
+ child++;
+ }
+ /* pick larger child */
+ if (CompareFunc(temp, pArr[child - 1]))
{
- int child = 2*k;
-
- if ((child < n) && CompareFunc(pArr[child - 1] , pArr[child]))
- {
- child++;
- }
- /* pick larger child */
- if (CompareFunc(temp , pArr[child - 1]))
- {
- /* move child up */
- pArr[k - 1] = pArr[child - 1];
- k = child;
- }
- else
- {
- break;
- }
+ /* move child up */
+ pArr[k - 1] = pArr[child - 1];
+ k = child;
}
- pArr[k - 1] = temp;
- } /*downHeap*/
+ else
+ {
+ break;
+ }
+ }
+ pArr[k - 1] = temp;
+ } /*downHeap*/
- void swap(int index0,int index1)
- {
+ void swap(int index0, int index1)
+ {
#ifdef BT_USE_MEMCPY
- char temp[sizeof(T)];
- memcpy(temp,&m_data[index0],sizeof(T));
- memcpy(&m_data[index0],&m_data[index1],sizeof(T));
- memcpy(&m_data[index1],temp,sizeof(T));
+ char temp[sizeof(T)];
+ memcpy(temp, &m_data[index0], sizeof(T));
+ memcpy(&m_data[index0], &m_data[index1], sizeof(T));
+ memcpy(&m_data[index1], temp, sizeof(T));
#else
- T temp = m_data[index0];
- m_data[index0] = m_data[index1];
- m_data[index1] = temp;
-#endif //BT_USE_PLACEMENT_NEW
-
- }
+ T temp = m_data[index0];
+ m_data[index0] = m_data[index1];
+ m_data[index1] = temp;
+#endif //BT_USE_PLACEMENT_NEW
+ }
template <typename L>
void heapSort(const L& CompareFunc)
@@ -423,49 +406,66 @@ protected:
/* sort a[0..N-1], N.B. 0 to N-1 */
int k;
int n = m_size;
- for (k = n/2; k > 0; k--)
+ for (k = n / 2; k > 0; k--)
{
downHeap(m_data, k, n, CompareFunc);
}
/* a[1..N] is now a heap */
- while ( n>=1 )
+ while (n >= 1)
{
- swap(0,n-1); /* largest of a[0..n-1] */
-
+ swap(0, n - 1); /* largest of a[0..n-1] */
n = n - 1;
/* restore a[1..i-1] heap */
downHeap(m_data, 1, n, CompareFunc);
- }
+ }
}
///non-recursive binary search, assumes sorted array
- int findBinarySearch(const T& key) const
+ int findBinarySearch(const T& key) const
{
int first = 0;
- int last = size()-1;
+ int last = size() - 1;
//assume sorted array
- while (first <= last) {
+ while (first <= last)
+ {
int mid = (first + last) / 2; // compute mid point.
- if (key > m_data[mid])
+ if (key > m_data[mid])
first = mid + 1; // repeat search in top half.
- else if (key < m_data[mid])
- last = mid - 1; // repeat search in bottom half.
+ else if (key < m_data[mid])
+ last = mid - 1; // repeat search in bottom half.
else
- return mid; // found it. return position /////
+ return mid; // found it. return position /////
}
- return size(); // failed to find key
+ return size(); // failed to find key
}
+ int findLinearSearch(const T& key) const
+ {
+ int index = size();
+ int i;
- int findLinearSearch(const T& key) const
+ for (i = 0; i < size(); i++)
+ {
+ if (m_data[i] == key)
+ {
+ index = i;
+ break;
+ }
+ }
+ return index;
+ }
+
+ // If the key is not in the array, return -1 instead of 0,
+ // since 0 also means the first element in the array.
+ int findLinearSearch2(const T& key) const
{
- int index=size();
+ int index = -1;
int i;
- for (i=0;i<size();i++)
+ for (i = 0; i < size(); i++)
{
if (m_data[i] == key)
{
@@ -475,41 +475,23 @@ protected:
}
return index;
}
-
- // If the key is not in the array, return -1 instead of 0,
- // since 0 also means the first element in the array.
- int findLinearSearch2(const T& key) const
- {
- int index=-1;
- int i;
-
- for (i=0;i<size();i++)
- {
- if (m_data[i] == key)
- {
- index = i;
- break;
- }
- }
- return index;
- }
-
- void removeAtIndex(int index)
- {
- if (index<size())
- {
- swap( index,size()-1);
- pop_back();
- }
- }
- void remove(const T& key)
+
+ void removeAtIndex(int index)
+ {
+ if (index < size())
+ {
+ swap(index, size() - 1);
+ pop_back();
+ }
+ }
+ void remove(const T& key)
{
int findIndex = findLinearSearch(key);
- removeAtIndex(findIndex);
+ removeAtIndex(findIndex);
}
//PCK: whole function
- void initializeFromBuffer(void *buffer, int size, int capacity)
+ void initializeFromBuffer(void* buffer, int size, int capacity)
{
clear();
m_ownsMemory = false;
@@ -521,10 +503,9 @@ protected:
void copyFromArray(const btAlignedObjectArray& otherArray)
{
int otherSize = otherArray.size();
- resize (otherSize);
+ resize(otherSize);
otherArray.copy(0, otherSize, m_data);
}
-
};
-#endif //BT_OBJECT_ARRAY__
+#endif //BT_OBJECT_ARRAY__
diff --git a/thirdparty/bullet/LinearMath/btConvexHull.cpp b/thirdparty/bullet/LinearMath/btConvexHull.cpp
index f8b79a1aba..e7de2a3694 100644
--- a/thirdparty/bullet/LinearMath/btConvexHull.cpp
+++ b/thirdparty/bullet/LinearMath/btConvexHull.cpp
@@ -20,51 +20,52 @@ subject to the following restrictions:
#include "btMinMax.h"
#include "btVector3.h"
-
-
-
-
//----------------------------------
-class int3
+class int3
{
public:
- int x,y,z;
+ int x, y, z;
int3(){};
- int3(int _x,int _y, int _z){x=_x;y=_y;z=_z;}
- const int& operator[](int i) const {return (&x)[i];}
- int& operator[](int i) {return (&x)[i];}
+ int3(int _x, int _y, int _z)
+ {
+ x = _x;
+ y = _y;
+ z = _z;
+ }
+ const int &operator[](int i) const { return (&x)[i]; }
+ int &operator[](int i) { return (&x)[i]; }
};
-
//------- btPlane ----------
-
-inline btPlane PlaneFlip(const btPlane &plane){return btPlane(-plane.normal,-plane.dist);}
-inline int operator==( const btPlane &a, const btPlane &b ) { return (a.normal==b.normal && a.dist==b.dist); }
-inline int coplanar( const btPlane &a, const btPlane &b ) { return (a==b || a==PlaneFlip(b)); }
-
+inline btPlane PlaneFlip(const btPlane &plane) { return btPlane(-plane.normal, -plane.dist); }
+inline int operator==(const btPlane &a, const btPlane &b) { return (a.normal == b.normal && a.dist == b.dist); }
+inline int coplanar(const btPlane &a, const btPlane &b) { return (a == b || a == PlaneFlip(b)); }
//--------- Utility Functions ------
-btVector3 PlaneLineIntersection(const btPlane &plane, const btVector3 &p0, const btVector3 &p1);
-btVector3 PlaneProject(const btPlane &plane, const btVector3 &point);
+btVector3 PlaneLineIntersection(const btPlane &plane, const btVector3 &p0, const btVector3 &p1);
+btVector3 PlaneProject(const btPlane &plane, const btVector3 &point);
-btVector3 ThreePlaneIntersection(const btPlane &p0,const btPlane &p1, const btPlane &p2);
-btVector3 ThreePlaneIntersection(const btPlane &p0,const btPlane &p1, const btPlane &p2)
+btVector3 ThreePlaneIntersection(const btPlane &p0, const btPlane &p1, const btPlane &p2);
+btVector3 ThreePlaneIntersection(const btPlane &p0, const btPlane &p1, const btPlane &p2)
{
btVector3 N1 = p0.normal;
btVector3 N2 = p1.normal;
btVector3 N3 = p2.normal;
- btVector3 n2n3; n2n3 = N2.cross(N3);
- btVector3 n3n1; n3n1 = N3.cross(N1);
- btVector3 n1n2; n1n2 = N1.cross(N2);
+ btVector3 n2n3;
+ n2n3 = N2.cross(N3);
+ btVector3 n3n1;
+ n3n1 = N3.cross(N1);
+ btVector3 n1n2;
+ n1n2 = N1.cross(N2);
btScalar quotient = (N1.dot(n2n3));
btAssert(btFabs(quotient) > btScalar(0.000001));
-
+
quotient = btScalar(-1.) / quotient;
n2n3 *= p0.dist;
n3n1 *= p1.dist;
@@ -74,105 +75,96 @@ btVector3 ThreePlaneIntersection(const btPlane &p0,const btPlane &p1, const btP
potentialVertex += n1n2;
potentialVertex *= quotient;
- btVector3 result(potentialVertex.getX(),potentialVertex.getY(),potentialVertex.getZ());
+ btVector3 result(potentialVertex.getX(), potentialVertex.getY(), potentialVertex.getZ());
return result;
-
}
-btScalar DistanceBetweenLines(const btVector3 &ustart, const btVector3 &udir, const btVector3 &vstart, const btVector3 &vdir, btVector3 *upoint=NULL, btVector3 *vpoint=NULL);
-btVector3 TriNormal(const btVector3 &v0, const btVector3 &v1, const btVector3 &v2);
-btVector3 NormalOf(const btVector3 *vert, const int n);
-
+btScalar DistanceBetweenLines(const btVector3 &ustart, const btVector3 &udir, const btVector3 &vstart, const btVector3 &vdir, btVector3 *upoint = NULL, btVector3 *vpoint = NULL);
+btVector3 TriNormal(const btVector3 &v0, const btVector3 &v1, const btVector3 &v2);
+btVector3 NormalOf(const btVector3 *vert, const int n);
btVector3 PlaneLineIntersection(const btPlane &plane, const btVector3 &p0, const btVector3 &p1)
{
// returns the point where the line p0-p1 intersects the plane n&d
- btVector3 dif;
- dif = p1-p0;
- btScalar dn= btDot(plane.normal,dif);
- btScalar t = -(plane.dist+btDot(plane.normal,p0) )/dn;
- return p0 + (dif*t);
+ btVector3 dif;
+ dif = p1 - p0;
+ btScalar dn = btDot(plane.normal, dif);
+ btScalar t = -(plane.dist + btDot(plane.normal, p0)) / dn;
+ return p0 + (dif * t);
}
btVector3 PlaneProject(const btPlane &plane, const btVector3 &point)
{
- return point - plane.normal * (btDot(point,plane.normal)+plane.dist);
+ return point - plane.normal * (btDot(point, plane.normal) + plane.dist);
}
btVector3 TriNormal(const btVector3 &v0, const btVector3 &v1, const btVector3 &v2)
{
// return the normal of the triangle
// inscribed by v0, v1, and v2
- btVector3 cp=btCross(v1-v0,v2-v1);
- btScalar m=cp.length();
- if(m==0) return btVector3(1,0,0);
- return cp*(btScalar(1.0)/m);
+ btVector3 cp = btCross(v1 - v0, v2 - v1);
+ btScalar m = cp.length();
+ if (m == 0) return btVector3(1, 0, 0);
+ return cp * (btScalar(1.0) / m);
}
-
btScalar DistanceBetweenLines(const btVector3 &ustart, const btVector3 &udir, const btVector3 &vstart, const btVector3 &vdir, btVector3 *upoint, btVector3 *vpoint)
{
btVector3 cp;
- cp = btCross(udir,vdir).normalized();
+ cp = btCross(udir, vdir).normalized();
- btScalar distu = -btDot(cp,ustart);
- btScalar distv = -btDot(cp,vstart);
- btScalar dist = (btScalar)fabs(distu-distv);
- if(upoint)
- {
+ btScalar distu = -btDot(cp, ustart);
+ btScalar distv = -btDot(cp, vstart);
+ btScalar dist = (btScalar)fabs(distu - distv);
+ if (upoint)
+ {
btPlane plane;
- plane.normal = btCross(vdir,cp).normalized();
- plane.dist = -btDot(plane.normal,vstart);
- *upoint = PlaneLineIntersection(plane,ustart,ustart+udir);
+ plane.normal = btCross(vdir, cp).normalized();
+ plane.dist = -btDot(plane.normal, vstart);
+ *upoint = PlaneLineIntersection(plane, ustart, ustart + udir);
}
- if(vpoint)
- {
+ if (vpoint)
+ {
btPlane plane;
- plane.normal = btCross(udir,cp).normalized();
- plane.dist = -btDot(plane.normal,ustart);
- *vpoint = PlaneLineIntersection(plane,vstart,vstart+vdir);
+ plane.normal = btCross(udir, cp).normalized();
+ plane.dist = -btDot(plane.normal, ustart);
+ *vpoint = PlaneLineIntersection(plane, vstart, vstart + vdir);
}
return dist;
}
-
-
-
-
-
-
-#define COPLANAR (0)
-#define UNDER (1)
-#define OVER (2)
-#define SPLIT (OVER|UNDER)
+#define COPLANAR (0)
+#define UNDER (1)
+#define OVER (2)
+#define SPLIT (OVER | UNDER)
#define PAPERWIDTH (btScalar(0.001))
btScalar planetestepsilon = PAPERWIDTH;
-
-
typedef ConvexH::HalfEdge HalfEdge;
-ConvexH::ConvexH(int vertices_size,int edges_size,int facets_size)
+ConvexH::ConvexH(int vertices_size, int edges_size, int facets_size)
{
vertices.resize(vertices_size);
edges.resize(edges_size);
facets.resize(facets_size);
}
-
int PlaneTest(const btPlane &p, const btVector3 &v);
-int PlaneTest(const btPlane &p, const btVector3 &v) {
- btScalar a = btDot(v,p.normal)+p.dist;
- int flag = (a>planetestepsilon)?OVER:((a<-planetestepsilon)?UNDER:COPLANAR);
+int PlaneTest(const btPlane &p, const btVector3 &v)
+{
+ btScalar a = btDot(v, p.normal) + p.dist;
+ int flag = (a > planetestepsilon) ? OVER : ((a < -planetestepsilon) ? UNDER : COPLANAR);
return flag;
}
-int SplitTest(ConvexH &convex,const btPlane &plane);
-int SplitTest(ConvexH &convex,const btPlane &plane) {
- int flag=0;
- for(int i=0;i<convex.vertices.size();i++) {
- flag |= PlaneTest(plane,convex.vertices[i]);
+int SplitTest(ConvexH &convex, const btPlane &plane);
+int SplitTest(ConvexH &convex, const btPlane &plane)
+{
+ int flag = 0;
+ for (int i = 0; i < convex.vertices.size(); i++)
+ {
+ flag |= PlaneTest(plane, convex.vertices[i]);
}
return flag;
}
@@ -185,7 +177,7 @@ public:
unsigned char undermap;
unsigned char overmap;
};
-class EdgeFlag
+class EdgeFlag
{
public:
unsigned char planetest;
@@ -199,146 +191,135 @@ public:
unsigned char undermap;
unsigned char overmap;
};
-class Coplanar{
+class Coplanar
+{
public:
unsigned short ea;
unsigned char v0;
unsigned char v1;
};
-
-
-
-
-
-
-
-template<class T>
-int maxdirfiltered(const T *p,int count,const T &dir,btAlignedObjectArray<int> &allow)
+template <class T>
+int maxdirfiltered(const T *p, int count, const T &dir, btAlignedObjectArray<int> &allow)
{
btAssert(count);
- int m=-1;
- for(int i=0;i<count;i++)
- if(allow[i])
+ int m = -1;
+ for (int i = 0; i < count; i++)
+ if (allow[i])
{
- if(m==-1 || btDot(p[i],dir)>btDot(p[m],dir))
- m=i;
+ if (m == -1 || btDot(p[i], dir) > btDot(p[m], dir))
+ m = i;
}
- btAssert(m!=-1);
+ btAssert(m != -1);
return m;
-}
+}
btVector3 orth(const btVector3 &v);
btVector3 orth(const btVector3 &v)
{
- btVector3 a=btCross(v,btVector3(0,0,1));
- btVector3 b=btCross(v,btVector3(0,1,0));
+ btVector3 a = btCross(v, btVector3(0, 0, 1));
+ btVector3 b = btCross(v, btVector3(0, 1, 0));
if (a.length() > b.length())
{
return a.normalized();
- } else {
+ }
+ else
+ {
return b.normalized();
}
}
-
-template<class T>
-int maxdirsterid(const T *p,int count,const T &dir,btAlignedObjectArray<int> &allow)
+template <class T>
+int maxdirsterid(const T *p, int count, const T &dir, btAlignedObjectArray<int> &allow)
{
- int m=-1;
- while(m==-1)
+ int m = -1;
+ while (m == -1)
{
- m = maxdirfiltered(p,count,dir,allow);
- if(allow[m]==3) return m;
+ m = maxdirfiltered(p, count, dir, allow);
+ if (allow[m] == 3) return m;
T u = orth(dir);
- T v = btCross(u,dir);
- int ma=-1;
- for(btScalar x = btScalar(0.0) ; x<= btScalar(360.0) ; x+= btScalar(45.0))
+ T v = btCross(u, dir);
+ int ma = -1;
+ for (btScalar x = btScalar(0.0); x <= btScalar(360.0); x += btScalar(45.0))
{
- btScalar s = btSin(SIMD_RADS_PER_DEG*(x));
- btScalar c = btCos(SIMD_RADS_PER_DEG*(x));
- int mb = maxdirfiltered(p,count,dir+(u*s+v*c)*btScalar(0.025),allow);
- if(ma==m && mb==m)
+ btScalar s = btSin(SIMD_RADS_PER_DEG * (x));
+ btScalar c = btCos(SIMD_RADS_PER_DEG * (x));
+ int mb = maxdirfiltered(p, count, dir + (u * s + v * c) * btScalar(0.025), allow);
+ if (ma == m && mb == m)
{
- allow[m]=3;
+ allow[m] = 3;
return m;
}
- if(ma!=-1 && ma!=mb) // Yuck - this is really ugly
+ if (ma != -1 && ma != mb) // Yuck - this is really ugly
{
int mc = ma;
- for(btScalar xx = x-btScalar(40.0) ; xx <= x ; xx+= btScalar(5.0))
+ for (btScalar xx = x - btScalar(40.0); xx <= x; xx += btScalar(5.0))
{
- btScalar s = btSin(SIMD_RADS_PER_DEG*(xx));
- btScalar c = btCos(SIMD_RADS_PER_DEG*(xx));
- int md = maxdirfiltered(p,count,dir+(u*s+v*c)*btScalar(0.025),allow);
- if(mc==m && md==m)
+ btScalar s = btSin(SIMD_RADS_PER_DEG * (xx));
+ btScalar c = btCos(SIMD_RADS_PER_DEG * (xx));
+ int md = maxdirfiltered(p, count, dir + (u * s + v * c) * btScalar(0.025), allow);
+ if (mc == m && md == m)
{
- allow[m]=3;
+ allow[m] = 3;
return m;
}
- mc=md;
+ mc = md;
}
}
- ma=mb;
+ ma = mb;
}
- allow[m]=0;
- m=-1;
+ allow[m] = 0;
+ m = -1;
}
btAssert(0);
return m;
-}
-
-
-
+}
-int operator ==(const int3 &a,const int3 &b);
-int operator ==(const int3 &a,const int3 &b)
+int operator==(const int3 &a, const int3 &b);
+int operator==(const int3 &a, const int3 &b)
{
- for(int i=0;i<3;i++)
+ for (int i = 0; i < 3; i++)
{
- if(a[i]!=b[i]) return 0;
+ if (a[i] != b[i]) return 0;
}
return 1;
}
-
-int above(btVector3* vertices,const int3& t, const btVector3 &p, btScalar epsilon);
-int above(btVector3* vertices,const int3& t, const btVector3 &p, btScalar epsilon)
+int above(btVector3 *vertices, const int3 &t, const btVector3 &p, btScalar epsilon);
+int above(btVector3 *vertices, const int3 &t, const btVector3 &p, btScalar epsilon)
{
- btVector3 n=TriNormal(vertices[t[0]],vertices[t[1]],vertices[t[2]]);
- return (btDot(n,p-vertices[t[0]]) > epsilon); // EPSILON???
+ btVector3 n = TriNormal(vertices[t[0]], vertices[t[1]], vertices[t[2]]);
+ return (btDot(n, p - vertices[t[0]]) > epsilon); // EPSILON???
}
-int hasedge(const int3 &t, int a,int b);
-int hasedge(const int3 &t, int a,int b)
+int hasedge(const int3 &t, int a, int b);
+int hasedge(const int3 &t, int a, int b)
{
- for(int i=0;i<3;i++)
+ for (int i = 0; i < 3; i++)
{
- int i1= (i+1)%3;
- if(t[i]==a && t[i1]==b) return 1;
+ int i1 = (i + 1) % 3;
+ if (t[i] == a && t[i1] == b) return 1;
}
return 0;
}
int hasvert(const int3 &t, int v);
int hasvert(const int3 &t, int v)
{
- return (t[0]==v || t[1]==v || t[2]==v) ;
+ return (t[0] == v || t[1] == v || t[2] == v);
}
-int shareedge(const int3 &a,const int3 &b);
-int shareedge(const int3 &a,const int3 &b)
+int shareedge(const int3 &a, const int3 &b);
+int shareedge(const int3 &a, const int3 &b)
{
int i;
- for(i=0;i<3;i++)
+ for (i = 0; i < 3; i++)
{
- int i1= (i+1)%3;
- if(hasedge(a,b[i1],b[i])) return 1;
+ int i1 = (i + 1) % 3;
+ if (hasedge(a, b[i1], b[i])) return 1;
}
return 0;
}
class btHullTriangle;
-
-
class btHullTriangle : public int3
{
public:
@@ -346,51 +327,50 @@ public:
int id;
int vmax;
btScalar rise;
- btHullTriangle(int a,int b,int c):int3(a,b,c),n(-1,-1,-1)
+ btHullTriangle(int a, int b, int c) : int3(a, b, c), n(-1, -1, -1)
{
- vmax=-1;
+ vmax = -1;
rise = btScalar(0.0);
}
~btHullTriangle()
{
}
- int &neib(int a,int b);
+ int &neib(int a, int b);
};
-
-int &btHullTriangle::neib(int a,int b)
+int &btHullTriangle::neib(int a, int b)
{
- static int er=-1;
+ static int er = -1;
int i;
- for(i=0;i<3;i++)
+ for (i = 0; i < 3; i++)
{
- int i1=(i+1)%3;
- int i2=(i+2)%3;
- if((*this)[i]==a && (*this)[i1]==b) return n[i2];
- if((*this)[i]==b && (*this)[i1]==a) return n[i2];
+ int i1 = (i + 1) % 3;
+ int i2 = (i + 2) % 3;
+ if ((*this)[i] == a && (*this)[i1] == b) return n[i2];
+ if ((*this)[i] == b && (*this)[i1] == a) return n[i2];
}
btAssert(0);
return er;
}
-void HullLibrary::b2bfix(btHullTriangle* s,btHullTriangle*t)
+void HullLibrary::b2bfix(btHullTriangle *s, btHullTriangle *t)
{
int i;
- for(i=0;i<3;i++)
+ for (i = 0; i < 3; i++)
{
- int i1=(i+1)%3;
- int i2=(i+2)%3;
+ int i1 = (i + 1) % 3;
+ int i2 = (i + 2) % 3;
int a = (*s)[i1];
int b = (*s)[i2];
- btAssert(m_tris[s->neib(a,b)]->neib(b,a) == s->id);
- btAssert(m_tris[t->neib(a,b)]->neib(b,a) == t->id);
- m_tris[s->neib(a,b)]->neib(b,a) = t->neib(b,a);
- m_tris[t->neib(b,a)]->neib(a,b) = s->neib(a,b);
+ btAssert(m_tris[s->neib(a, b)]->neib(b, a) == s->id);
+ btAssert(m_tris[t->neib(a, b)]->neib(b, a) == t->id);
+ m_tris[s->neib(a, b)]->neib(b, a) = t->neib(b, a);
+ m_tris[t->neib(b, a)]->neib(a, b) = s->neib(a, b);
}
}
-void HullLibrary::removeb2b(btHullTriangle* s,btHullTriangle*t)
+void HullLibrary::removeb2b(btHullTriangle *s, btHullTriangle *t)
{
- b2bfix(s,t);
+ b2bfix(s, t);
deAllocateTriangle(s);
deAllocateTriangle(t);
@@ -401,11 +381,11 @@ void HullLibrary::checkit(btHullTriangle *t)
(void)t;
int i;
- btAssert(m_tris[t->id]==t);
- for(i=0;i<3;i++)
+ btAssert(m_tris[t->id] == t);
+ for (i = 0; i < 3; i++)
{
- int i1=(i+1)%3;
- int i2=(i+2)%3;
+ int i1 = (i + 1) % 3;
+ int i2 = (i + 2) % 3;
int a = (*t)[i1];
int b = (*t)[i2];
@@ -415,226 +395,233 @@ void HullLibrary::checkit(btHullTriangle *t)
(void)a;
(void)b;
- btAssert(a!=b);
- btAssert( m_tris[t->n[i]]->neib(b,a) == t->id);
+ btAssert(a != b);
+ btAssert(m_tris[t->n[i]]->neib(b, a) == t->id);
}
}
-btHullTriangle* HullLibrary::allocateTriangle(int a,int b,int c)
+btHullTriangle *HullLibrary::allocateTriangle(int a, int b, int c)
{
- void* mem = btAlignedAlloc(sizeof(btHullTriangle),16);
- btHullTriangle* tr = new (mem)btHullTriangle(a,b,c);
+ void *mem = btAlignedAlloc(sizeof(btHullTriangle), 16);
+ btHullTriangle *tr = new (mem) btHullTriangle(a, b, c);
tr->id = m_tris.size();
m_tris.push_back(tr);
return tr;
}
-void HullLibrary::deAllocateTriangle(btHullTriangle* tri)
+void HullLibrary::deAllocateTriangle(btHullTriangle *tri)
{
- btAssert(m_tris[tri->id]==tri);
- m_tris[tri->id]=NULL;
+ btAssert(m_tris[tri->id] == tri);
+ m_tris[tri->id] = NULL;
tri->~btHullTriangle();
btAlignedFree(tri);
}
-
-void HullLibrary::extrude(btHullTriangle *t0,int v)
+void HullLibrary::extrude(btHullTriangle *t0, int v)
{
- int3 t= *t0;
+ int3 t = *t0;
int n = m_tris.size();
- btHullTriangle* ta = allocateTriangle(v,t[1],t[2]);
- ta->n = int3(t0->n[0],n+1,n+2);
- m_tris[t0->n[0]]->neib(t[1],t[2]) = n+0;
- btHullTriangle* tb = allocateTriangle(v,t[2],t[0]);
- tb->n = int3(t0->n[1],n+2,n+0);
- m_tris[t0->n[1]]->neib(t[2],t[0]) = n+1;
- btHullTriangle* tc = allocateTriangle(v,t[0],t[1]);
- tc->n = int3(t0->n[2],n+0,n+1);
- m_tris[t0->n[2]]->neib(t[0],t[1]) = n+2;
+ btHullTriangle *ta = allocateTriangle(v, t[1], t[2]);
+ ta->n = int3(t0->n[0], n + 1, n + 2);
+ m_tris[t0->n[0]]->neib(t[1], t[2]) = n + 0;
+ btHullTriangle *tb = allocateTriangle(v, t[2], t[0]);
+ tb->n = int3(t0->n[1], n + 2, n + 0);
+ m_tris[t0->n[1]]->neib(t[2], t[0]) = n + 1;
+ btHullTriangle *tc = allocateTriangle(v, t[0], t[1]);
+ tc->n = int3(t0->n[2], n + 0, n + 1);
+ m_tris[t0->n[2]]->neib(t[0], t[1]) = n + 2;
checkit(ta);
checkit(tb);
checkit(tc);
- if(hasvert(*m_tris[ta->n[0]],v)) removeb2b(ta,m_tris[ta->n[0]]);
- if(hasvert(*m_tris[tb->n[0]],v)) removeb2b(tb,m_tris[tb->n[0]]);
- if(hasvert(*m_tris[tc->n[0]],v)) removeb2b(tc,m_tris[tc->n[0]]);
+ if (hasvert(*m_tris[ta->n[0]], v)) removeb2b(ta, m_tris[ta->n[0]]);
+ if (hasvert(*m_tris[tb->n[0]], v)) removeb2b(tb, m_tris[tb->n[0]]);
+ if (hasvert(*m_tris[tc->n[0]], v)) removeb2b(tc, m_tris[tc->n[0]]);
deAllocateTriangle(t0);
-
}
-btHullTriangle* HullLibrary::extrudable(btScalar epsilon)
+btHullTriangle *HullLibrary::extrudable(btScalar epsilon)
{
int i;
- btHullTriangle *t=NULL;
- for(i=0;i<m_tris.size();i++)
+ btHullTriangle *t = NULL;
+ for (i = 0; i < m_tris.size(); i++)
{
- if(!t || (m_tris[i] && t->rise<m_tris[i]->rise))
+ if (!t || (m_tris[i] && t->rise < m_tris[i]->rise))
{
t = m_tris[i];
}
}
- return (t->rise >epsilon)?t:NULL ;
+ return (t->rise > epsilon) ? t : NULL;
}
-
-
-
-int4 HullLibrary::FindSimplex(btVector3 *verts,int verts_count,btAlignedObjectArray<int> &allow)
+int4 HullLibrary::FindSimplex(btVector3 *verts, int verts_count, btAlignedObjectArray<int> &allow)
{
btVector3 basis[3];
- basis[0] = btVector3( btScalar(0.01), btScalar(0.02), btScalar(1.0) );
- int p0 = maxdirsterid(verts,verts_count, basis[0],allow);
- int p1 = maxdirsterid(verts,verts_count,-basis[0],allow);
- basis[0] = verts[p0]-verts[p1];
- if(p0==p1 || basis[0]==btVector3(0,0,0))
- return int4(-1,-1,-1,-1);
- basis[1] = btCross(btVector3( btScalar(1),btScalar(0.02), btScalar(0)),basis[0]);
- basis[2] = btCross(btVector3(btScalar(-0.02), btScalar(1), btScalar(0)),basis[0]);
+ basis[0] = btVector3(btScalar(0.01), btScalar(0.02), btScalar(1.0));
+ int p0 = maxdirsterid(verts, verts_count, basis[0], allow);
+ int p1 = maxdirsterid(verts, verts_count, -basis[0], allow);
+ basis[0] = verts[p0] - verts[p1];
+ if (p0 == p1 || basis[0] == btVector3(0, 0, 0))
+ return int4(-1, -1, -1, -1);
+ basis[1] = btCross(btVector3(btScalar(1), btScalar(0.02), btScalar(0)), basis[0]);
+ basis[2] = btCross(btVector3(btScalar(-0.02), btScalar(1), btScalar(0)), basis[0]);
if (basis[1].length() > basis[2].length())
{
basis[1].normalize();
- } else {
+ }
+ else
+ {
basis[1] = basis[2];
- basis[1].normalize ();
+ basis[1].normalize();
}
- int p2 = maxdirsterid(verts,verts_count,basis[1],allow);
- if(p2 == p0 || p2 == p1)
+ int p2 = maxdirsterid(verts, verts_count, basis[1], allow);
+ if (p2 == p0 || p2 == p1)
{
- p2 = maxdirsterid(verts,verts_count,-basis[1],allow);
+ p2 = maxdirsterid(verts, verts_count, -basis[1], allow);
}
- if(p2 == p0 || p2 == p1)
- return int4(-1,-1,-1,-1);
+ if (p2 == p0 || p2 == p1)
+ return int4(-1, -1, -1, -1);
basis[1] = verts[p2] - verts[p0];
- basis[2] = btCross(basis[1],basis[0]).normalized();
- int p3 = maxdirsterid(verts,verts_count,basis[2],allow);
- if(p3==p0||p3==p1||p3==p2) p3 = maxdirsterid(verts,verts_count,-basis[2],allow);
- if(p3==p0||p3==p1||p3==p2)
- return int4(-1,-1,-1,-1);
- btAssert(!(p0==p1||p0==p2||p0==p3||p1==p2||p1==p3||p2==p3));
- if(btDot(verts[p3]-verts[p0],btCross(verts[p1]-verts[p0],verts[p2]-verts[p0])) <0) {btSwap(p2,p3);}
- return int4(p0,p1,p2,p3);
+ basis[2] = btCross(basis[1], basis[0]).normalized();
+ int p3 = maxdirsterid(verts, verts_count, basis[2], allow);
+ if (p3 == p0 || p3 == p1 || p3 == p2) p3 = maxdirsterid(verts, verts_count, -basis[2], allow);
+ if (p3 == p0 || p3 == p1 || p3 == p2)
+ return int4(-1, -1, -1, -1);
+ btAssert(!(p0 == p1 || p0 == p2 || p0 == p3 || p1 == p2 || p1 == p3 || p2 == p3));
+ if (btDot(verts[p3] - verts[p0], btCross(verts[p1] - verts[p0], verts[p2] - verts[p0])) < 0)
+ {
+ btSwap(p2, p3);
+ }
+ return int4(p0, p1, p2, p3);
}
-int HullLibrary::calchullgen(btVector3 *verts,int verts_count, int vlimit)
+int HullLibrary::calchullgen(btVector3 *verts, int verts_count, int vlimit)
{
- if(verts_count <4) return 0;
- if(vlimit==0) vlimit=1000000000;
+ if (verts_count < 4) return 0;
+ if (vlimit == 0) vlimit = 1000000000;
int j;
- btVector3 bmin(*verts),bmax(*verts);
+ btVector3 bmin(*verts), bmax(*verts);
btAlignedObjectArray<int> isextreme;
isextreme.reserve(verts_count);
btAlignedObjectArray<int> allow;
allow.reserve(verts_count);
- for(j=0;j<verts_count;j++)
+ for (j = 0; j < verts_count; j++)
{
allow.push_back(1);
isextreme.push_back(0);
- bmin.setMin (verts[j]);
- bmax.setMax (verts[j]);
+ bmin.setMin(verts[j]);
+ bmax.setMax(verts[j]);
}
- btScalar epsilon = (bmax-bmin).length() * btScalar(0.001);
- btAssert (epsilon != 0.0);
-
-
- int4 p = FindSimplex(verts,verts_count,allow);
- if(p.x==-1) return 0; // simplex failed
-
-
-
- btVector3 center = (verts[p[0]]+verts[p[1]]+verts[p[2]]+verts[p[3]]) / btScalar(4.0); // a valid interior point
- btHullTriangle *t0 = allocateTriangle(p[2],p[3],p[1]); t0->n=int3(2,3,1);
- btHullTriangle *t1 = allocateTriangle(p[3],p[2],p[0]); t1->n=int3(3,2,0);
- btHullTriangle *t2 = allocateTriangle(p[0],p[1],p[3]); t2->n=int3(0,1,3);
- btHullTriangle *t3 = allocateTriangle(p[1],p[0],p[2]); t3->n=int3(1,0,2);
- isextreme[p[0]]=isextreme[p[1]]=isextreme[p[2]]=isextreme[p[3]]=1;
- checkit(t0);checkit(t1);checkit(t2);checkit(t3);
-
- for(j=0;j<m_tris.size();j++)
+ btScalar epsilon = (bmax - bmin).length() * btScalar(0.001);
+ btAssert(epsilon != 0.0);
+
+ int4 p = FindSimplex(verts, verts_count, allow);
+ if (p.x == -1) return 0; // simplex failed
+
+ btVector3 center = (verts[p[0]] + verts[p[1]] + verts[p[2]] + verts[p[3]]) / btScalar(4.0); // a valid interior point
+ btHullTriangle *t0 = allocateTriangle(p[2], p[3], p[1]);
+ t0->n = int3(2, 3, 1);
+ btHullTriangle *t1 = allocateTriangle(p[3], p[2], p[0]);
+ t1->n = int3(3, 2, 0);
+ btHullTriangle *t2 = allocateTriangle(p[0], p[1], p[3]);
+ t2->n = int3(0, 1, 3);
+ btHullTriangle *t3 = allocateTriangle(p[1], p[0], p[2]);
+ t3->n = int3(1, 0, 2);
+ isextreme[p[0]] = isextreme[p[1]] = isextreme[p[2]] = isextreme[p[3]] = 1;
+ checkit(t0);
+ checkit(t1);
+ checkit(t2);
+ checkit(t3);
+
+ for (j = 0; j < m_tris.size(); j++)
{
- btHullTriangle *t=m_tris[j];
+ btHullTriangle *t = m_tris[j];
btAssert(t);
- btAssert(t->vmax<0);
- btVector3 n=TriNormal(verts[(*t)[0]],verts[(*t)[1]],verts[(*t)[2]]);
- t->vmax = maxdirsterid(verts,verts_count,n,allow);
- t->rise = btDot(n,verts[t->vmax]-verts[(*t)[0]]);
+ btAssert(t->vmax < 0);
+ btVector3 n = TriNormal(verts[(*t)[0]], verts[(*t)[1]], verts[(*t)[2]]);
+ t->vmax = maxdirsterid(verts, verts_count, n, allow);
+ t->rise = btDot(n, verts[t->vmax] - verts[(*t)[0]]);
}
btHullTriangle *te;
- vlimit-=4;
- while(vlimit >0 && ((te=extrudable(epsilon)) != 0))
+ vlimit -= 4;
+ while (vlimit > 0 && ((te = extrudable(epsilon)) != 0))
{
//int3 ti=*te;
- int v=te->vmax;
+ int v = te->vmax;
btAssert(v != -1);
btAssert(!isextreme[v]); // wtf we've already done this vertex
- isextreme[v]=1;
+ isextreme[v] = 1;
//if(v==p0 || v==p1 || v==p2 || v==p3) continue; // done these already
- j=m_tris.size();
- while(j--) {
- if(!m_tris[j]) continue;
- int3 t=*m_tris[j];
- if(above(verts,t,verts[v],btScalar(0.01)*epsilon))
+ j = m_tris.size();
+ while (j--)
+ {
+ if (!m_tris[j]) continue;
+ int3 t = *m_tris[j];
+ if (above(verts, t, verts[v], btScalar(0.01) * epsilon))
{
- extrude(m_tris[j],v);
+ extrude(m_tris[j], v);
}
}
// now check for those degenerate cases where we have a flipped triangle or a really skinny triangle
- j=m_tris.size();
- while(j--)
+ j = m_tris.size();
+ while (j--)
{
- if(!m_tris[j]) continue;
- if(!hasvert(*m_tris[j],v)) break;
- int3 nt=*m_tris[j];
- if(above(verts,nt,center,btScalar(0.01)*epsilon) || btCross(verts[nt[1]]-verts[nt[0]],verts[nt[2]]-verts[nt[1]]).length()< epsilon*epsilon*btScalar(0.1) )
+ if (!m_tris[j]) continue;
+ if (!hasvert(*m_tris[j], v)) break;
+ int3 nt = *m_tris[j];
+ if (above(verts, nt, center, btScalar(0.01) * epsilon) || btCross(verts[nt[1]] - verts[nt[0]], verts[nt[2]] - verts[nt[1]]).length() < epsilon * epsilon * btScalar(0.1))
{
btHullTriangle *nb = m_tris[m_tris[j]->n[0]];
- btAssert(nb);btAssert(!hasvert(*nb,v));btAssert(nb->id<j);
- extrude(nb,v);
- j=m_tris.size();
+ btAssert(nb);
+ btAssert(!hasvert(*nb, v));
+ btAssert(nb->id < j);
+ extrude(nb, v);
+ j = m_tris.size();
}
- }
- j=m_tris.size();
- while(j--)
+ }
+ j = m_tris.size();
+ while (j--)
{
- btHullTriangle *t=m_tris[j];
- if(!t) continue;
- if(t->vmax>=0) break;
- btVector3 n=TriNormal(verts[(*t)[0]],verts[(*t)[1]],verts[(*t)[2]]);
- t->vmax = maxdirsterid(verts,verts_count,n,allow);
- if(isextreme[t->vmax])
+ btHullTriangle *t = m_tris[j];
+ if (!t) continue;
+ if (t->vmax >= 0) break;
+ btVector3 n = TriNormal(verts[(*t)[0]], verts[(*t)[1]], verts[(*t)[2]]);
+ t->vmax = maxdirsterid(verts, verts_count, n, allow);
+ if (isextreme[t->vmax])
{
- t->vmax=-1; // already done that vertex - algorithm needs to be able to terminate.
+ t->vmax = -1; // already done that vertex - algorithm needs to be able to terminate.
}
else
{
- t->rise = btDot(n,verts[t->vmax]-verts[(*t)[0]]);
+ t->rise = btDot(n, verts[t->vmax] - verts[(*t)[0]]);
}
}
- vlimit --;
+ vlimit--;
}
return 1;
}
-int HullLibrary::calchull(btVector3 *verts,int verts_count, TUIntArray& tris_out, int &tris_count,int vlimit)
+int HullLibrary::calchull(btVector3 *verts, int verts_count, TUIntArray &tris_out, int &tris_count, int vlimit)
{
- int rc=calchullgen(verts,verts_count, vlimit) ;
- if(!rc) return 0;
+ int rc = calchullgen(verts, verts_count, vlimit);
+ if (!rc) return 0;
btAlignedObjectArray<int> ts;
int i;
- for(i=0;i<m_tris.size();i++)
+ for (i = 0; i < m_tris.size(); i++)
{
- if(m_tris[i])
+ if (m_tris[i])
{
- for(int j=0;j<3;j++)
+ for (int j = 0; j < 3; j++)
ts.push_back((*m_tris[i])[j]);
deAllocateTriangle(m_tris[i]);
}
}
- tris_count = ts.size()/3;
+ tris_count = ts.size() / 3;
tris_out.resize(ts.size());
-
- for (i=0;i<ts.size();i++)
+
+ for (i = 0; i < ts.size(); i++)
{
tris_out[i] = static_cast<unsigned int>(ts[i]);
}
@@ -643,29 +630,22 @@ int HullLibrary::calchull(btVector3 *verts,int verts_count, TUIntArray& tris_out
return 1;
}
-
-
-
-
-bool HullLibrary::ComputeHull(unsigned int vcount,const btVector3 *vertices,PHullResult &result,unsigned int vlimit)
+bool HullLibrary::ComputeHull(unsigned int vcount, const btVector3 *vertices, PHullResult &result, unsigned int vlimit)
{
-
- int tris_count;
- int ret = calchull( (btVector3 *) vertices, (int) vcount, result.m_Indices, tris_count, static_cast<int>(vlimit) );
- if(!ret) return false;
- result.mIndexCount = (unsigned int) (tris_count*3);
- result.mFaceCount = (unsigned int) tris_count;
- result.mVertices = (btVector3*) vertices;
- result.mVcount = (unsigned int) vcount;
+ int tris_count;
+ int ret = calchull((btVector3 *)vertices, (int)vcount, result.m_Indices, tris_count, static_cast<int>(vlimit));
+ if (!ret) return false;
+ result.mIndexCount = (unsigned int)(tris_count * 3);
+ result.mFaceCount = (unsigned int)tris_count;
+ result.mVertices = (btVector3 *)vertices;
+ result.mVcount = (unsigned int)vcount;
return true;
-
}
-
void ReleaseHull(PHullResult &result);
void ReleaseHull(PHullResult &result)
{
- if ( result.m_Indices.size() )
+ if (result.m_Indices.size())
{
result.m_Indices.clear();
}
@@ -675,7 +655,6 @@ void ReleaseHull(PHullResult &result)
result.mVertices = 0;
}
-
//*********************************************************************
//*********************************************************************
//******** HullLib header
@@ -688,16 +667,15 @@ void ReleaseHull(PHullResult &result)
//*********************************************************************
//*********************************************************************
-HullError HullLibrary::CreateConvexHull(const HullDesc &desc, // describes the input request
- HullResult &result) // contains the resulst
+HullError HullLibrary::CreateConvexHull(const HullDesc &desc, // describes the input request
+ HullResult &result) // contains the resulst
{
HullError ret = QE_FAIL;
-
PHullResult hr;
unsigned int vcount = desc.mVcount;
- if ( vcount < 8 ) vcount = 8;
+ if (vcount < 8) vcount = 8;
btAlignedObjectArray<btVector3> vertexSource;
vertexSource.resize(static_cast<int>(vcount));
@@ -706,87 +684,82 @@ HullError HullLibrary::CreateConvexHull(const HullDesc &desc, //
unsigned int ovcount;
- bool ok = CleanupVertices(desc.mVcount,desc.mVertices, desc.mVertexStride, ovcount, &vertexSource[0], desc.mNormalEpsilon, scale ); // normalize point cloud, remove duplicates!
+ bool ok = CleanupVertices(desc.mVcount, desc.mVertices, desc.mVertexStride, ovcount, &vertexSource[0], desc.mNormalEpsilon, scale); // normalize point cloud, remove duplicates!
- if ( ok )
+ if (ok)
{
-
-
-// if ( 1 ) // scale vertices back to their original size.
+ // if ( 1 ) // scale vertices back to their original size.
{
- for (unsigned int i=0; i<ovcount; i++)
+ for (unsigned int i = 0; i < ovcount; i++)
{
- btVector3& v = vertexSource[static_cast<int>(i)];
- v[0]*=scale[0];
- v[1]*=scale[1];
- v[2]*=scale[2];
+ btVector3 &v = vertexSource[static_cast<int>(i)];
+ v[0] *= scale[0];
+ v[1] *= scale[1];
+ v[2] *= scale[2];
}
}
- ok = ComputeHull(ovcount,&vertexSource[0],hr,desc.mMaxVertices);
+ ok = ComputeHull(ovcount, &vertexSource[0], hr, desc.mMaxVertices);
- if ( ok )
+ if (ok)
{
-
// re-index triangle mesh so it refers to only used vertices, rebuild a new vertex table.
- btAlignedObjectArray<btVector3> vertexScratch;
+ btAlignedObjectArray<btVector3> vertexScratch;
vertexScratch.resize(static_cast<int>(hr.mVcount));
- BringOutYourDead(hr.mVertices,hr.mVcount, &vertexScratch[0], ovcount, &hr.m_Indices[0], hr.mIndexCount );
+ BringOutYourDead(hr.mVertices, hr.mVcount, &vertexScratch[0], ovcount, &hr.m_Indices[0], hr.mIndexCount);
ret = QE_OK;
- if ( desc.HasHullFlag(QF_TRIANGLES) ) // if he wants the results as triangle!
+ if (desc.HasHullFlag(QF_TRIANGLES)) // if he wants the results as triangle!
{
- result.mPolygons = false;
+ result.mPolygons = false;
result.mNumOutputVertices = ovcount;
result.m_OutputVertices.resize(static_cast<int>(ovcount));
- result.mNumFaces = hr.mFaceCount;
- result.mNumIndices = hr.mIndexCount;
+ result.mNumFaces = hr.mFaceCount;
+ result.mNumIndices = hr.mIndexCount;
result.m_Indices.resize(static_cast<int>(hr.mIndexCount));
- memcpy(&result.m_OutputVertices[0], &vertexScratch[0], sizeof(btVector3)*ovcount );
+ memcpy(&result.m_OutputVertices[0], &vertexScratch[0], sizeof(btVector3) * ovcount);
- if ( desc.HasHullFlag(QF_REVERSE_ORDER) )
+ if (desc.HasHullFlag(QF_REVERSE_ORDER))
{
-
const unsigned int *source = &hr.m_Indices[0];
- unsigned int *dest = &result.m_Indices[0];
+ unsigned int *dest = &result.m_Indices[0];
- for (unsigned int i=0; i<hr.mFaceCount; i++)
+ for (unsigned int i = 0; i < hr.mFaceCount; i++)
{
dest[0] = source[2];
dest[1] = source[1];
dest[2] = source[0];
- dest+=3;
- source+=3;
+ dest += 3;
+ source += 3;
}
-
}
else
{
- memcpy(&result.m_Indices[0], &hr.m_Indices[0], sizeof(unsigned int)*hr.mIndexCount);
+ memcpy(&result.m_Indices[0], &hr.m_Indices[0], sizeof(unsigned int) * hr.mIndexCount);
}
}
else
{
- result.mPolygons = true;
+ result.mPolygons = true;
result.mNumOutputVertices = ovcount;
result.m_OutputVertices.resize(static_cast<int>(ovcount));
- result.mNumFaces = hr.mFaceCount;
- result.mNumIndices = hr.mIndexCount+hr.mFaceCount;
+ result.mNumFaces = hr.mFaceCount;
+ result.mNumIndices = hr.mIndexCount + hr.mFaceCount;
result.m_Indices.resize(static_cast<int>(result.mNumIndices));
- memcpy(&result.m_OutputVertices[0], &vertexScratch[0], sizeof(btVector3)*ovcount );
+ memcpy(&result.m_OutputVertices[0], &vertexScratch[0], sizeof(btVector3) * ovcount);
-// if ( 1 )
+ // if ( 1 )
{
const unsigned int *source = &hr.m_Indices[0];
- unsigned int *dest = &result.m_Indices[0];
- for (unsigned int i=0; i<hr.mFaceCount; i++)
+ unsigned int *dest = &result.m_Indices[0];
+ for (unsigned int i = 0; i < hr.mFaceCount; i++)
{
dest[0] = 3;
- if ( desc.HasHullFlag(QF_REVERSE_ORDER) )
+ if (desc.HasHullFlag(QF_REVERSE_ORDER))
{
dest[1] = source[2];
dest[2] = source[1];
@@ -799,8 +772,8 @@ HullError HullLibrary::CreateConvexHull(const HullDesc &desc, //
dest[3] = source[2];
}
- dest+=4;
- source+=3;
+ dest += 4;
+ source += 3;
}
}
}
@@ -811,90 +784,83 @@ HullError HullLibrary::CreateConvexHull(const HullDesc &desc, //
return ret;
}
-
-
-HullError HullLibrary::ReleaseResult(HullResult &result) // release memory allocated for this result, we are done with it.
+HullError HullLibrary::ReleaseResult(HullResult &result) // release memory allocated for this result, we are done with it.
{
- if ( result.m_OutputVertices.size())
+ if (result.m_OutputVertices.size())
{
- result.mNumOutputVertices=0;
+ result.mNumOutputVertices = 0;
result.m_OutputVertices.clear();
}
- if ( result.m_Indices.size() )
+ if (result.m_Indices.size())
{
- result.mNumIndices=0;
+ result.mNumIndices = 0;
result.m_Indices.clear();
}
return QE_OK;
}
-
-static void addPoint(unsigned int &vcount,btVector3 *p,btScalar x,btScalar y,btScalar z)
+static void addPoint(unsigned int &vcount, btVector3 *p, btScalar x, btScalar y, btScalar z)
{
// XXX, might be broken
- btVector3& dest = p[vcount];
+ btVector3 &dest = p[vcount];
dest[0] = x;
dest[1] = y;
dest[2] = z;
vcount++;
}
-btScalar GetDist(btScalar px,btScalar py,btScalar pz,const btScalar *p2);
-btScalar GetDist(btScalar px,btScalar py,btScalar pz,const btScalar *p2)
+btScalar GetDist(btScalar px, btScalar py, btScalar pz, const btScalar *p2);
+btScalar GetDist(btScalar px, btScalar py, btScalar pz, const btScalar *p2)
{
-
btScalar dx = px - p2[0];
btScalar dy = py - p2[1];
btScalar dz = pz - p2[2];
- return dx*dx+dy*dy+dz*dz;
+ return dx * dx + dy * dy + dz * dz;
}
-
-
-bool HullLibrary::CleanupVertices(unsigned int svcount,
- const btVector3 *svertices,
- unsigned int stride,
- unsigned int &vcount, // output number of vertices
- btVector3 *vertices, // location to store the results.
- btScalar normalepsilon,
- btVector3& scale)
+bool HullLibrary::CleanupVertices(unsigned int svcount,
+ const btVector3 *svertices,
+ unsigned int stride,
+ unsigned int &vcount, // output number of vertices
+ btVector3 *vertices, // location to store the results.
+ btScalar normalepsilon,
+ btVector3 &scale)
{
- if ( svcount == 0 ) return false;
+ if (svcount == 0) return false;
m_vertexIndexMapping.resize(0);
-
#define EPSILON btScalar(0.000001) /* close enough to consider two btScalaring point numbers to be 'the same'. */
vcount = 0;
- btScalar recip[3]={0.f,0.f,0.f};
+ btScalar recip[3] = {0.f, 0.f, 0.f};
- if ( scale )
+ if (scale)
{
scale[0] = 1;
scale[1] = 1;
scale[2] = 1;
}
- btScalar bmin[3] = { FLT_MAX, FLT_MAX, FLT_MAX };
- btScalar bmax[3] = { -FLT_MAX, -FLT_MAX, -FLT_MAX };
+ btScalar bmin[3] = {FLT_MAX, FLT_MAX, FLT_MAX};
+ btScalar bmax[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX};
- const char *vtx = (const char *) svertices;
+ const char *vtx = (const char *)svertices;
-// if ( 1 )
+ // if ( 1 )
{
- for (unsigned int i=0; i<svcount; i++)
+ for (unsigned int i = 0; i < svcount; i++)
{
- const btScalar *p = (const btScalar *) vtx;
+ const btScalar *p = (const btScalar *)vtx;
- vtx+=stride;
+ vtx += stride;
- for (int j=0; j<3; j++)
+ for (int j = 0; j < 3; j++)
{
- if ( p[j] < bmin[j] ) bmin[j] = p[j];
- if ( p[j] > bmax[j] ) bmax[j] = p[j];
+ if (p[j] < bmin[j]) bmin[j] = p[j];
+ if (p[j] > bmax[j]) bmax[j] = p[j];
}
}
}
@@ -905,28 +871,27 @@ bool HullLibrary::CleanupVertices(unsigned int svcount,
btVector3 center;
- center[0] = dx*btScalar(0.5) + bmin[0];
- center[1] = dy*btScalar(0.5) + bmin[1];
- center[2] = dz*btScalar(0.5) + bmin[2];
+ center[0] = dx * btScalar(0.5) + bmin[0];
+ center[1] = dy * btScalar(0.5) + bmin[1];
+ center[2] = dz * btScalar(0.5) + bmin[2];
- if ( dx < EPSILON || dy < EPSILON || dz < EPSILON || svcount < 3 )
+ if (dx < EPSILON || dy < EPSILON || dz < EPSILON || svcount < 3)
{
-
btScalar len = FLT_MAX;
- if ( dx > EPSILON && dx < len ) len = dx;
- if ( dy > EPSILON && dy < len ) len = dy;
- if ( dz > EPSILON && dz < len ) len = dz;
+ if (dx > EPSILON && dx < len) len = dx;
+ if (dy > EPSILON && dy < len) len = dy;
+ if (dz > EPSILON && dz < len) len = dz;
- if ( len == FLT_MAX )
+ if (len == FLT_MAX)
{
- dx = dy = dz = btScalar(0.01); // one centimeter
+ dx = dy = dz = btScalar(0.01); // one centimeter
}
else
{
- if ( dx < EPSILON ) dx = len * btScalar(0.05); // 1/5th the shortest non-zero edge.
- if ( dy < EPSILON ) dy = len * btScalar(0.05);
- if ( dz < EPSILON ) dz = len * btScalar(0.05);
+ if (dx < EPSILON) dx = len * btScalar(0.05); // 1/5th the shortest non-zero edge.
+ if (dy < EPSILON) dy = len * btScalar(0.05);
+ if (dz < EPSILON) dz = len * btScalar(0.05);
}
btScalar x1 = center[0] - dx;
@@ -938,22 +903,20 @@ bool HullLibrary::CleanupVertices(unsigned int svcount,
btScalar z1 = center[2] - dz;
btScalar z2 = center[2] + dz;
- addPoint(vcount,vertices,x1,y1,z1);
- addPoint(vcount,vertices,x2,y1,z1);
- addPoint(vcount,vertices,x2,y2,z1);
- addPoint(vcount,vertices,x1,y2,z1);
- addPoint(vcount,vertices,x1,y1,z2);
- addPoint(vcount,vertices,x2,y1,z2);
- addPoint(vcount,vertices,x2,y2,z2);
- addPoint(vcount,vertices,x1,y2,z2);
-
- return true; // return cube
-
+ addPoint(vcount, vertices, x1, y1, z1);
+ addPoint(vcount, vertices, x2, y1, z1);
+ addPoint(vcount, vertices, x2, y2, z1);
+ addPoint(vcount, vertices, x1, y2, z1);
+ addPoint(vcount, vertices, x1, y1, z2);
+ addPoint(vcount, vertices, x2, y1, z2);
+ addPoint(vcount, vertices, x2, y2, z2);
+ addPoint(vcount, vertices, x1, y2, z2);
+ return true; // return cube
}
else
{
- if ( scale )
+ if (scale)
{
scale[0] = dx;
scale[1] = dy;
@@ -963,75 +926,70 @@ bool HullLibrary::CleanupVertices(unsigned int svcount,
recip[1] = 1 / dy;
recip[2] = 1 / dz;
- center[0]*=recip[0];
- center[1]*=recip[1];
- center[2]*=recip[2];
-
+ center[0] *= recip[0];
+ center[1] *= recip[1];
+ center[2] *= recip[2];
}
-
}
+ vtx = (const char *)svertices;
-
- vtx = (const char *) svertices;
-
- for (unsigned int i=0; i<svcount; i++)
+ for (unsigned int i = 0; i < svcount; i++)
{
const btVector3 *p = (const btVector3 *)vtx;
- vtx+=stride;
+ vtx += stride;
btScalar px = p->getX();
btScalar py = p->getY();
btScalar pz = p->getZ();
- if ( scale )
+ if (scale)
{
- px = px*recip[0]; // normalize
- py = py*recip[1]; // normalize
- pz = pz*recip[2]; // normalize
+ px = px * recip[0]; // normalize
+ py = py * recip[1]; // normalize
+ pz = pz * recip[2]; // normalize
}
-// if ( 1 )
+ // if ( 1 )
{
unsigned int j;
- for (j=0; j<vcount; j++)
+ for (j = 0; j < vcount; j++)
{
/// XXX might be broken
- btVector3& v = vertices[j];
+ btVector3 &v = vertices[j];
btScalar x = v[0];
btScalar y = v[1];
btScalar z = v[2];
- btScalar dx = btFabs(x - px );
- btScalar dy = btFabs(y - py );
- btScalar dz = btFabs(z - pz );
+ btScalar dx = btFabs(x - px);
+ btScalar dy = btFabs(y - py);
+ btScalar dz = btFabs(z - pz);
- if ( dx < normalepsilon && dy < normalepsilon && dz < normalepsilon )
+ if (dx < normalepsilon && dy < normalepsilon && dz < normalepsilon)
{
// ok, it is close enough to the old one
// now let us see if it is further from the center of the point cloud than the one we already recorded.
// in which case we keep this one instead.
- btScalar dist1 = GetDist(px,py,pz,center);
- btScalar dist2 = GetDist(v[0],v[1],v[2],center);
+ btScalar dist1 = GetDist(px, py, pz, center);
+ btScalar dist2 = GetDist(v[0], v[1], v[2], center);
- if ( dist1 > dist2 )
+ if (dist1 > dist2)
{
v[0] = px;
v[1] = py;
v[2] = pz;
-
}
break;
}
}
- if ( j == vcount )
+ if (j == vcount)
{
- btVector3& dest = vertices[vcount];
+ btVector3 &dest = vertices[vcount];
dest[0] = px;
dest[1] = py;
dest[2] = pz;
@@ -1042,18 +1000,18 @@ bool HullLibrary::CleanupVertices(unsigned int svcount,
}
// ok..now make sure we didn't prune so many vertices it is now invalid.
-// if ( 1 )
+ // if ( 1 )
{
- btScalar bmin[3] = { FLT_MAX, FLT_MAX, FLT_MAX };
- btScalar bmax[3] = { -FLT_MAX, -FLT_MAX, -FLT_MAX };
+ btScalar bmin[3] = {FLT_MAX, FLT_MAX, FLT_MAX};
+ btScalar bmax[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX};
- for (unsigned int i=0; i<vcount; i++)
+ for (unsigned int i = 0; i < vcount; i++)
{
- const btVector3& p = vertices[i];
- for (int j=0; j<3; j++)
+ const btVector3 &p = vertices[i];
+ for (int j = 0; j < 3; j++)
{
- if ( p[j] < bmin[j] ) bmin[j] = p[j];
- if ( p[j] > bmax[j] ) bmax[j] = p[j];
+ if (p[j] < bmin[j]) bmin[j] = p[j];
+ if (p[j] > bmax[j]) bmax[j] = p[j];
}
}
@@ -1061,27 +1019,27 @@ bool HullLibrary::CleanupVertices(unsigned int svcount,
btScalar dy = bmax[1] - bmin[1];
btScalar dz = bmax[2] - bmin[2];
- if ( dx < EPSILON || dy < EPSILON || dz < EPSILON || vcount < 3)
+ if (dx < EPSILON || dy < EPSILON || dz < EPSILON || vcount < 3)
{
- btScalar cx = dx*btScalar(0.5) + bmin[0];
- btScalar cy = dy*btScalar(0.5) + bmin[1];
- btScalar cz = dz*btScalar(0.5) + bmin[2];
+ btScalar cx = dx * btScalar(0.5) + bmin[0];
+ btScalar cy = dy * btScalar(0.5) + bmin[1];
+ btScalar cz = dz * btScalar(0.5) + bmin[2];
btScalar len = FLT_MAX;
- if ( dx >= EPSILON && dx < len ) len = dx;
- if ( dy >= EPSILON && dy < len ) len = dy;
- if ( dz >= EPSILON && dz < len ) len = dz;
+ if (dx >= EPSILON && dx < len) len = dx;
+ if (dy >= EPSILON && dy < len) len = dy;
+ if (dz >= EPSILON && dz < len) len = dz;
- if ( len == FLT_MAX )
+ if (len == FLT_MAX)
{
- dx = dy = dz = btScalar(0.01); // one centimeter
+ dx = dy = dz = btScalar(0.01); // one centimeter
}
else
{
- if ( dx < EPSILON ) dx = len * btScalar(0.05); // 1/5th the shortest non-zero edge.
- if ( dy < EPSILON ) dy = len * btScalar(0.05);
- if ( dz < EPSILON ) dz = len * btScalar(0.05);
+ if (dx < EPSILON) dx = len * btScalar(0.05); // 1/5th the shortest non-zero edge.
+ if (dy < EPSILON) dy = len * btScalar(0.05);
+ if (dz < EPSILON) dz = len * btScalar(0.05);
}
btScalar x1 = cx - dx;
@@ -1093,16 +1051,16 @@ bool HullLibrary::CleanupVertices(unsigned int svcount,
btScalar z1 = cz - dz;
btScalar z2 = cz + dz;
- vcount = 0; // add box
+ vcount = 0; // add box
- addPoint(vcount,vertices,x1,y1,z1);
- addPoint(vcount,vertices,x2,y1,z1);
- addPoint(vcount,vertices,x2,y2,z1);
- addPoint(vcount,vertices,x1,y2,z1);
- addPoint(vcount,vertices,x1,y1,z2);
- addPoint(vcount,vertices,x2,y1,z2);
- addPoint(vcount,vertices,x2,y2,z2);
- addPoint(vcount,vertices,x1,y2,z2);
+ addPoint(vcount, vertices, x1, y1, z1);
+ addPoint(vcount, vertices, x2, y1, z1);
+ addPoint(vcount, vertices, x2, y2, z1);
+ addPoint(vcount, vertices, x1, y2, z1);
+ addPoint(vcount, vertices, x1, y1, z2);
+ addPoint(vcount, vertices, x2, y1, z2);
+ addPoint(vcount, vertices, x2, y2, z2);
+ addPoint(vcount, vertices, x1, y2, z2);
return true;
}
@@ -1111,57 +1069,52 @@ bool HullLibrary::CleanupVertices(unsigned int svcount,
return true;
}
-void HullLibrary::BringOutYourDead(const btVector3* verts,unsigned int vcount, btVector3* overts,unsigned int &ocount,unsigned int *indices,unsigned indexcount)
+void HullLibrary::BringOutYourDead(const btVector3 *verts, unsigned int vcount, btVector3 *overts, unsigned int &ocount, unsigned int *indices, unsigned indexcount)
{
- btAlignedObjectArray<int>tmpIndices;
+ btAlignedObjectArray<int> tmpIndices;
tmpIndices.resize(m_vertexIndexMapping.size());
int i;
- for (i=0;i<m_vertexIndexMapping.size();i++)
+ for (i = 0; i < m_vertexIndexMapping.size(); i++)
{
tmpIndices[i] = m_vertexIndexMapping[i];
}
TUIntArray usedIndices;
usedIndices.resize(static_cast<int>(vcount));
- memset(&usedIndices[0],0,sizeof(unsigned int)*vcount);
+ memset(&usedIndices[0], 0, sizeof(unsigned int) * vcount);
ocount = 0;
- for (i=0; i<int (indexcount); i++)
+ for (i = 0; i < int(indexcount); i++)
{
- unsigned int v = indices[i]; // original array index
+ unsigned int v = indices[i]; // original array index
- btAssert( v >= 0 && v < vcount );
+ btAssert(v >= 0 && v < vcount);
- if ( usedIndices[static_cast<int>(v)] ) // if already remapped
+ if (usedIndices[static_cast<int>(v)]) // if already remapped
{
- indices[i] = usedIndices[static_cast<int>(v)]-1; // index to new array
+ indices[i] = usedIndices[static_cast<int>(v)] - 1; // index to new array
}
else
{
+ indices[i] = ocount; // new index mapping
- indices[i] = ocount; // new index mapping
-
- overts[ocount][0] = verts[v][0]; // copy old vert to new vert array
+ overts[ocount][0] = verts[v][0]; // copy old vert to new vert array
overts[ocount][1] = verts[v][1];
overts[ocount][2] = verts[v][2];
- for (int k=0;k<m_vertexIndexMapping.size();k++)
+ for (int k = 0; k < m_vertexIndexMapping.size(); k++)
{
- if (tmpIndices[k]==int(v))
- m_vertexIndexMapping[k]=ocount;
+ if (tmpIndices[k] == int(v))
+ m_vertexIndexMapping[k] = ocount;
}
- ocount++; // increment output vert count
-
- btAssert( ocount >=0 && ocount <= vcount );
+ ocount++; // increment output vert count
- usedIndices[static_cast<int>(v)] = ocount; // assign new index remapping
+ btAssert(ocount >= 0 && ocount <= vcount);
-
+ usedIndices[static_cast<int>(v)] = ocount; // assign new index remapping
}
}
-
-
}
diff --git a/thirdparty/bullet/LinearMath/btConvexHull.h b/thirdparty/bullet/LinearMath/btConvexHull.h
index 69c52bc6f8..f890d75ea1 100644
--- a/thirdparty/bullet/LinearMath/btConvexHull.h
+++ b/thirdparty/bullet/LinearMath/btConvexHull.h
@@ -34,106 +34,102 @@ public:
mNumFaces = 0;
mNumIndices = 0;
}
- bool mPolygons; // true if indices represents polygons, false indices are triangles
- unsigned int mNumOutputVertices; // number of vertices in the output hull
- btAlignedObjectArray<btVector3> m_OutputVertices; // array of vertices
- unsigned int mNumFaces; // the number of faces produced
- unsigned int mNumIndices; // the total number of indices
- btAlignedObjectArray<unsigned int> m_Indices; // pointer to indices.
-
-// If triangles, then indices are array indexes into the vertex list.
-// If polygons, indices are in the form (number of points in face) (p1, p2, p3, ..) etc..
+ bool mPolygons; // true if indices represents polygons, false indices are triangles
+ unsigned int mNumOutputVertices; // number of vertices in the output hull
+ btAlignedObjectArray<btVector3> m_OutputVertices; // array of vertices
+ unsigned int mNumFaces; // the number of faces produced
+ unsigned int mNumIndices; // the total number of indices
+ btAlignedObjectArray<unsigned int> m_Indices; // pointer to indices.
+
+ // If triangles, then indices are array indexes into the vertex list.
+ // If polygons, indices are in the form (number of points in face) (p1, p2, p3, ..) etc..
};
enum HullFlag
{
- QF_TRIANGLES = (1<<0), // report results as triangles, not polygons.
- QF_REVERSE_ORDER = (1<<1), // reverse order of the triangle indices.
- QF_DEFAULT = QF_TRIANGLES
+ QF_TRIANGLES = (1 << 0), // report results as triangles, not polygons.
+ QF_REVERSE_ORDER = (1 << 1), // reverse order of the triangle indices.
+ QF_DEFAULT = QF_TRIANGLES
};
-
class HullDesc
{
public:
HullDesc(void)
{
- mFlags = QF_DEFAULT;
- mVcount = 0;
- mVertices = 0;
- mVertexStride = sizeof(btVector3);
- mNormalEpsilon = 0.001f;
- mMaxVertices = 4096; // maximum number of points to be considered for a convex hull.
- mMaxFaces = 4096;
+ mFlags = QF_DEFAULT;
+ mVcount = 0;
+ mVertices = 0;
+ mVertexStride = sizeof(btVector3);
+ mNormalEpsilon = 0.001f;
+ mMaxVertices = 4096; // maximum number of points to be considered for a convex hull.
+ mMaxFaces = 4096;
};
HullDesc(HullFlag flag,
- unsigned int vcount,
- const btVector3 *vertices,
- unsigned int stride = sizeof(btVector3))
+ unsigned int vcount,
+ const btVector3* vertices,
+ unsigned int stride = sizeof(btVector3))
{
- mFlags = flag;
- mVcount = vcount;
- mVertices = vertices;
- mVertexStride = stride;
- mNormalEpsilon = btScalar(0.001);
- mMaxVertices = 4096;
+ mFlags = flag;
+ mVcount = vcount;
+ mVertices = vertices;
+ mVertexStride = stride;
+ mNormalEpsilon = btScalar(0.001);
+ mMaxVertices = 4096;
}
bool HasHullFlag(HullFlag flag) const
{
- if ( mFlags & flag ) return true;
+ if (mFlags & flag) return true;
return false;
}
void SetHullFlag(HullFlag flag)
{
- mFlags|=flag;
+ mFlags |= flag;
}
void ClearHullFlag(HullFlag flag)
{
- mFlags&=~flag;
+ mFlags &= ~flag;
}
- unsigned int mFlags; // flags to use when generating the convex hull.
- unsigned int mVcount; // number of vertices in the input point cloud
- const btVector3 *mVertices; // the array of vertices.
- unsigned int mVertexStride; // the stride of each vertex, in bytes.
- btScalar mNormalEpsilon; // the epsilon for removing duplicates. This is a normalized value, if normalized bit is on.
- unsigned int mMaxVertices; // maximum number of vertices to be considered for the hull!
- unsigned int mMaxFaces;
+ unsigned int mFlags; // flags to use when generating the convex hull.
+ unsigned int mVcount; // number of vertices in the input point cloud
+ const btVector3* mVertices; // the array of vertices.
+ unsigned int mVertexStride; // the stride of each vertex, in bytes.
+ btScalar mNormalEpsilon; // the epsilon for removing duplicates. This is a normalized value, if normalized bit is on.
+ unsigned int mMaxVertices; // maximum number of vertices to be considered for the hull!
+ unsigned int mMaxFaces;
};
enum HullError
{
- QE_OK, // success!
- QE_FAIL // failed.
+ QE_OK, // success!
+ QE_FAIL // failed.
};
class btPlane
{
- public:
- btVector3 normal;
- btScalar dist; // distance below origin - the D from plane equasion Ax+By+Cz+D=0
- btPlane(const btVector3 &n,btScalar d):normal(n),dist(d){}
- btPlane():normal(),dist(0){}
-
+public:
+ btVector3 normal;
+ btScalar dist; // distance below origin - the D from plane equasion Ax+By+Cz+D=0
+ btPlane(const btVector3& n, btScalar d) : normal(n), dist(d) {}
+ btPlane() : normal(), dist(0) {}
};
-
-
-class ConvexH
+class ConvexH
{
- public:
+public:
class HalfEdge
{
- public:
+ public:
short ea; // the other half of the edge (index into edges list)
unsigned char v; // the vertex at the start of this edge (index into vertices list)
unsigned char p; // the facet on which this edge lies (index into facets list)
- HalfEdge(){}
- HalfEdge(short _ea,unsigned char _v, unsigned char _p):ea(_ea),v(_v),p(_p){}
+ HalfEdge() {}
+ HalfEdge(short _ea, unsigned char _v, unsigned char _p) : ea(_ea), v(_v), p(_p) {}
};
ConvexH()
{
@@ -143,25 +139,29 @@ class ConvexH
}
btAlignedObjectArray<btVector3> vertices;
btAlignedObjectArray<HalfEdge> edges;
- btAlignedObjectArray<btPlane> facets;
- ConvexH(int vertices_size,int edges_size,int facets_size);
+ btAlignedObjectArray<btPlane> facets;
+ ConvexH(int vertices_size, int edges_size, int facets_size);
};
-
class int4
{
public:
- int x,y,z,w;
+ int x, y, z, w;
int4(){};
- int4(int _x,int _y, int _z,int _w){x=_x;y=_y;z=_z;w=_w;}
- const int& operator[](int i) const {return (&x)[i];}
- int& operator[](int i) {return (&x)[i];}
+ int4(int _x, int _y, int _z, int _w)
+ {
+ x = _x;
+ y = _y;
+ z = _z;
+ w = _w;
+ }
+ const int& operator[](int i) const { return (&x)[i]; }
+ int& operator[](int i) { return (&x)[i]; }
};
class PHullResult
{
public:
-
PHullResult(void)
{
mVcount = 0;
@@ -173,69 +173,61 @@ public:
unsigned int mVcount;
unsigned int mIndexCount;
unsigned int mFaceCount;
- btVector3* mVertices;
+ btVector3* mVertices;
TUIntArray m_Indices;
};
-
-
///The HullLibrary class can create a convex hull from a collection of vertices, using the ComputeHull method.
///The btShapeHull class uses this HullLibrary to create a approximate convex mesh given a general (non-polyhedral) convex shape.
class HullLibrary
{
-
btAlignedObjectArray<class btHullTriangle*> m_tris;
public:
-
btAlignedObjectArray<int> m_vertexIndexMapping;
-
- HullError CreateConvexHull(const HullDesc& desc, // describes the input request
- HullResult& result); // contains the resulst
- HullError ReleaseResult(HullResult &result); // release memory allocated for this result, we are done with it.
+ HullError CreateConvexHull(const HullDesc& desc, // describes the input request
+ HullResult& result); // contains the resulst
+ HullError ReleaseResult(HullResult& result); // release memory allocated for this result, we are done with it.
private:
+ bool ComputeHull(unsigned int vcount, const btVector3* vertices, PHullResult& result, unsigned int vlimit);
- bool ComputeHull(unsigned int vcount,const btVector3 *vertices,PHullResult &result,unsigned int vlimit);
-
- class btHullTriangle* allocateTriangle(int a,int b,int c);
- void deAllocateTriangle(btHullTriangle*);
- void b2bfix(btHullTriangle* s,btHullTriangle*t);
+ class btHullTriangle* allocateTriangle(int a, int b, int c);
+ void deAllocateTriangle(btHullTriangle*);
+ void b2bfix(btHullTriangle* s, btHullTriangle* t);
- void removeb2b(btHullTriangle* s,btHullTriangle*t);
+ void removeb2b(btHullTriangle* s, btHullTriangle* t);
- void checkit(btHullTriangle *t);
+ void checkit(btHullTriangle* t);
btHullTriangle* extrudable(btScalar epsilon);
- int calchull(btVector3 *verts,int verts_count, TUIntArray& tris_out, int &tris_count,int vlimit);
+ int calchull(btVector3* verts, int verts_count, TUIntArray& tris_out, int& tris_count, int vlimit);
- int calchullgen(btVector3 *verts,int verts_count, int vlimit);
+ int calchullgen(btVector3* verts, int verts_count, int vlimit);
- int4 FindSimplex(btVector3 *verts,int verts_count,btAlignedObjectArray<int> &allow);
+ int4 FindSimplex(btVector3* verts, int verts_count, btAlignedObjectArray<int>& allow);
- class ConvexH* ConvexHCrop(ConvexH& convex,const btPlane& slice);
+ class ConvexH* ConvexHCrop(ConvexH& convex, const btPlane& slice);
- void extrude(class btHullTriangle* t0,int v);
+ void extrude(class btHullTriangle* t0, int v);
ConvexH* test_cube();
- //BringOutYourDead (John Ratcliff): When you create a convex hull you hand it a large input set of vertices forming a 'point cloud'.
+ //BringOutYourDead (John Ratcliff): When you create a convex hull you hand it a large input set of vertices forming a 'point cloud'.
//After the hull is generated it give you back a set of polygon faces which index the *original* point cloud.
//The thing is, often times, there are many 'dead vertices' in the point cloud that are on longer referenced by the hull.
//The routine 'BringOutYourDead' find only the referenced vertices, copies them to an new buffer, and re-indexes the hull so that it is a minimal representation.
- void BringOutYourDead(const btVector3* verts,unsigned int vcount, btVector3* overts,unsigned int &ocount,unsigned int* indices,unsigned indexcount);
+ void BringOutYourDead(const btVector3* verts, unsigned int vcount, btVector3* overts, unsigned int& ocount, unsigned int* indices, unsigned indexcount);
bool CleanupVertices(unsigned int svcount,
- const btVector3* svertices,
- unsigned int stride,
- unsigned int &vcount, // output number of vertices
- btVector3* vertices, // location to store the results.
- btScalar normalepsilon,
- btVector3& scale);
+ const btVector3* svertices,
+ unsigned int stride,
+ unsigned int& vcount, // output number of vertices
+ btVector3* vertices, // location to store the results.
+ btScalar normalepsilon,
+ btVector3& scale);
};
-
-#endif //BT_CD_HULL_H
-
+#endif //BT_CD_HULL_H
diff --git a/thirdparty/bullet/LinearMath/btConvexHullComputer.cpp b/thirdparty/bullet/LinearMath/btConvexHullComputer.cpp
index 2ea22cbe3b..8bbfdc5f25 100644
--- a/thirdparty/bullet/LinearMath/btConvexHullComputer.cpp
+++ b/thirdparty/bullet/LinearMath/btConvexHullComputer.cpp
@@ -20,846 +20,847 @@ subject to the following restrictions:
#include "btVector3.h"
#ifdef __GNUC__
- #include <stdint.h>
+#include <stdint.h>
#elif defined(_MSC_VER)
- typedef __int32 int32_t;
- typedef __int64 int64_t;
- typedef unsigned __int32 uint32_t;
- typedef unsigned __int64 uint64_t;
+typedef __int32 int32_t;
+typedef __int64 int64_t;
+typedef unsigned __int32 uint32_t;
+typedef unsigned __int64 uint64_t;
#else
- typedef int int32_t;
- typedef long long int int64_t;
- typedef unsigned int uint32_t;
- typedef unsigned long long int uint64_t;
+typedef int int32_t;
+typedef long long int int64_t;
+typedef unsigned int uint32_t;
+typedef unsigned long long int uint64_t;
#endif
-
//The definition of USE_X86_64_ASM is moved into the build system. You can enable it manually by commenting out the following lines
//#if (defined(__GNUC__) && defined(__x86_64__) && !defined(__ICL)) // || (defined(__ICL) && defined(_M_X64)) bug in Intel compiler, disable inline assembly
// #define USE_X86_64_ASM
//#endif
-
//#define DEBUG_CONVEX_HULL
//#define SHOW_ITERATIONS
#if defined(DEBUG_CONVEX_HULL) || defined(SHOW_ITERATIONS)
- #include <stdio.h>
+#include <stdio.h>
#endif
// Convex hull implementation based on Preparata and Hong
// Ole Kniemeyer, MAXON Computer GmbH
class btConvexHullInternal
{
+public:
+ class Point64
+ {
public:
-
- class Point64
- {
- public:
- int64_t x;
- int64_t y;
- int64_t z;
-
- Point64(int64_t x, int64_t y, int64_t z): x(x), y(y), z(z)
- {
- }
+ int64_t x;
+ int64_t y;
+ int64_t z;
- bool isZero()
- {
- return (x == 0) && (y == 0) && (z == 0);
- }
+ Point64(int64_t x, int64_t y, int64_t z) : x(x), y(y), z(z)
+ {
+ }
- int64_t dot(const Point64& b) const
- {
- return x * b.x + y * b.y + z * b.z;
- }
- };
-
- class Point32
- {
- public:
- int32_t x;
- int32_t y;
- int32_t z;
- int index;
-
- Point32()
- {
- }
-
- Point32(int32_t x, int32_t y, int32_t z): x(x), y(y), z(z), index(-1)
- {
- }
-
- bool operator==(const Point32& b) const
- {
- return (x == b.x) && (y == b.y) && (z == b.z);
- }
+ bool isZero()
+ {
+ return (x == 0) && (y == 0) && (z == 0);
+ }
- bool operator!=(const Point32& b) const
- {
- return (x != b.x) || (y != b.y) || (z != b.z);
- }
+ int64_t dot(const Point64& b) const
+ {
+ return x * b.x + y * b.y + z * b.z;
+ }
+ };
- bool isZero()
- {
- return (x == 0) && (y == 0) && (z == 0);
- }
+ class Point32
+ {
+ public:
+ int32_t x;
+ int32_t y;
+ int32_t z;
+ int index;
- Point64 cross(const Point32& b) const
- {
- return Point64(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x);
- }
+ Point32()
+ {
+ }
- Point64 cross(const Point64& b) const
- {
- return Point64(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x);
- }
+ Point32(int32_t x, int32_t y, int32_t z) : x(x), y(y), z(z), index(-1)
+ {
+ }
- int64_t dot(const Point32& b) const
- {
- return x * b.x + y * b.y + z * b.z;
- }
+ bool operator==(const Point32& b) const
+ {
+ return (x == b.x) && (y == b.y) && (z == b.z);
+ }
- int64_t dot(const Point64& b) const
- {
- return x * b.x + y * b.y + z * b.z;
- }
+ bool operator!=(const Point32& b) const
+ {
+ return (x != b.x) || (y != b.y) || (z != b.z);
+ }
- Point32 operator+(const Point32& b) const
- {
- return Point32(x + b.x, y + b.y, z + b.z);
- }
+ bool isZero()
+ {
+ return (x == 0) && (y == 0) && (z == 0);
+ }
- Point32 operator-(const Point32& b) const
- {
- return Point32(x - b.x, y - b.y, z - b.z);
- }
- };
+ Point64 cross(const Point32& b) const
+ {
+ return Point64(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x);
+ }
- class Int128
+ Point64 cross(const Point64& b) const
{
- public:
- uint64_t low;
- uint64_t high;
+ return Point64(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x);
+ }
- Int128()
- {
- }
+ int64_t dot(const Point32& b) const
+ {
+ return x * b.x + y * b.y + z * b.z;
+ }
- Int128(uint64_t low, uint64_t high): low(low), high(high)
- {
- }
+ int64_t dot(const Point64& b) const
+ {
+ return x * b.x + y * b.y + z * b.z;
+ }
- Int128(uint64_t low): low(low), high(0)
- {
- }
+ Point32 operator+(const Point32& b) const
+ {
+ return Point32(x + b.x, y + b.y, z + b.z);
+ }
- Int128(int64_t value): low(value), high((value >= 0) ? 0 : (uint64_t) -1LL)
- {
- }
+ Point32 operator-(const Point32& b) const
+ {
+ return Point32(x - b.x, y - b.y, z - b.z);
+ }
+ };
- static Int128 mul(int64_t a, int64_t b);
+ class Int128
+ {
+ public:
+ uint64_t low;
+ uint64_t high;
- static Int128 mul(uint64_t a, uint64_t b);
+ Int128()
+ {
+ }
- Int128 operator-() const
- {
- return Int128((uint64_t) -(int64_t)low, ~high + (low == 0));
- }
+ Int128(uint64_t low, uint64_t high) : low(low), high(high)
+ {
+ }
- Int128 operator+(const Int128& b) const
- {
+ Int128(uint64_t low) : low(low), high(0)
+ {
+ }
+
+ Int128(int64_t value) : low(value), high((value >= 0) ? 0 : (uint64_t)-1LL)
+ {
+ }
+
+ static Int128 mul(int64_t a, int64_t b);
+
+ static Int128 mul(uint64_t a, uint64_t b);
+
+ Int128 operator-() const
+ {
+ return Int128((uint64_t) - (int64_t)low, ~high + (low == 0));
+ }
+
+ Int128 operator+(const Int128& b) const
+ {
#ifdef USE_X86_64_ASM
- Int128 result;
- __asm__ ("addq %[bl], %[rl]\n\t"
- "adcq %[bh], %[rh]\n\t"
- : [rl] "=r" (result.low), [rh] "=r" (result.high)
- : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
- : "cc" );
- return result;
+ Int128 result;
+ __asm__(
+ "addq %[bl], %[rl]\n\t"
+ "adcq %[bh], %[rh]\n\t"
+ : [rl] "=r"(result.low), [rh] "=r"(result.high)
+ : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
+ : "cc");
+ return result;
#else
- uint64_t lo = low + b.low;
- return Int128(lo, high + b.high + (lo < low));
+ uint64_t lo = low + b.low;
+ return Int128(lo, high + b.high + (lo < low));
#endif
- }
+ }
- Int128 operator-(const Int128& b) const
- {
+ Int128 operator-(const Int128& b) const
+ {
#ifdef USE_X86_64_ASM
- Int128 result;
- __asm__ ("subq %[bl], %[rl]\n\t"
- "sbbq %[bh], %[rh]\n\t"
- : [rl] "=r" (result.low), [rh] "=r" (result.high)
- : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
- : "cc" );
- return result;
+ Int128 result;
+ __asm__(
+ "subq %[bl], %[rl]\n\t"
+ "sbbq %[bh], %[rh]\n\t"
+ : [rl] "=r"(result.low), [rh] "=r"(result.high)
+ : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
+ : "cc");
+ return result;
#else
- return *this + -b;
+ return *this + -b;
#endif
- }
+ }
- Int128& operator+=(const Int128& b)
- {
+ Int128& operator+=(const Int128& b)
+ {
#ifdef USE_X86_64_ASM
- __asm__ ("addq %[bl], %[rl]\n\t"
- "adcq %[bh], %[rh]\n\t"
- : [rl] "=r" (low), [rh] "=r" (high)
- : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
- : "cc" );
+ __asm__(
+ "addq %[bl], %[rl]\n\t"
+ "adcq %[bh], %[rh]\n\t"
+ : [rl] "=r"(low), [rh] "=r"(high)
+ : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
+ : "cc");
#else
- uint64_t lo = low + b.low;
- if (lo < low)
- {
- ++high;
- }
- low = lo;
- high += b.high;
+ uint64_t lo = low + b.low;
+ if (lo < low)
+ {
+ ++high;
+ }
+ low = lo;
+ high += b.high;
#endif
- return *this;
- }
+ return *this;
+ }
- Int128& operator++()
- {
- if (++low == 0)
- {
- ++high;
- }
- return *this;
- }
+ Int128& operator++()
+ {
+ if (++low == 0)
+ {
+ ++high;
+ }
+ return *this;
+ }
- Int128 operator*(int64_t b) const;
+ Int128 operator*(int64_t b) const;
- btScalar toScalar() const
- {
- return ((int64_t) high >= 0) ? btScalar(high) * (btScalar(0x100000000LL) * btScalar(0x100000000LL)) + btScalar(low)
- : -(-*this).toScalar();
- }
+ btScalar toScalar() const
+ {
+ return ((int64_t)high >= 0) ? btScalar(high) * (btScalar(0x100000000LL) * btScalar(0x100000000LL)) + btScalar(low)
+ : -(-*this).toScalar();
+ }
- int getSign() const
- {
- return ((int64_t) high < 0) ? -1 : (high || low) ? 1 : 0;
- }
+ int getSign() const
+ {
+ return ((int64_t)high < 0) ? -1 : (high || low) ? 1 : 0;
+ }
- bool operator<(const Int128& b) const
- {
- return (high < b.high) || ((high == b.high) && (low < b.low));
- }
+ bool operator<(const Int128& b) const
+ {
+ return (high < b.high) || ((high == b.high) && (low < b.low));
+ }
- int ucmp(const Int128&b) const
- {
- if (high < b.high)
- {
- return -1;
- }
- if (high > b.high)
- {
- return 1;
- }
- if (low < b.low)
- {
- return -1;
- }
- if (low > b.low)
- {
- return 1;
- }
- return 0;
- }
- };
+ int ucmp(const Int128& b) const
+ {
+ if (high < b.high)
+ {
+ return -1;
+ }
+ if (high > b.high)
+ {
+ return 1;
+ }
+ if (low < b.low)
+ {
+ return -1;
+ }
+ if (low > b.low)
+ {
+ return 1;
+ }
+ return 0;
+ }
+ };
+ class Rational64
+ {
+ private:
+ uint64_t m_numerator;
+ uint64_t m_denominator;
+ int sign;
- class Rational64
+ public:
+ Rational64(int64_t numerator, int64_t denominator)
{
- private:
- uint64_t m_numerator;
- uint64_t m_denominator;
- int sign;
-
- public:
- Rational64(int64_t numerator, int64_t denominator)
- {
- if (numerator > 0)
- {
- sign = 1;
- m_numerator = (uint64_t) numerator;
- }
- else if (numerator < 0)
- {
- sign = -1;
- m_numerator = (uint64_t) -numerator;
- }
- else
- {
- sign = 0;
- m_numerator = 0;
- }
- if (denominator > 0)
- {
- m_denominator = (uint64_t) denominator;
- }
- else if (denominator < 0)
- {
- sign = -sign;
- m_denominator = (uint64_t) -denominator;
- }
- else
- {
- m_denominator = 0;
- }
- }
-
- bool isNegativeInfinity() const
- {
- return (sign < 0) && (m_denominator == 0);
- }
-
- bool isNaN() const
- {
- return (sign == 0) && (m_denominator == 0);
- }
-
- int compare(const Rational64& b) const;
-
- btScalar toScalar() const
- {
- return sign * ((m_denominator == 0) ? SIMD_INFINITY : (btScalar) m_numerator / m_denominator);
- }
- };
-
+ if (numerator > 0)
+ {
+ sign = 1;
+ m_numerator = (uint64_t)numerator;
+ }
+ else if (numerator < 0)
+ {
+ sign = -1;
+ m_numerator = (uint64_t)-numerator;
+ }
+ else
+ {
+ sign = 0;
+ m_numerator = 0;
+ }
+ if (denominator > 0)
+ {
+ m_denominator = (uint64_t)denominator;
+ }
+ else if (denominator < 0)
+ {
+ sign = -sign;
+ m_denominator = (uint64_t)-denominator;
+ }
+ else
+ {
+ m_denominator = 0;
+ }
+ }
- class Rational128
+ bool isNegativeInfinity() const
{
- private:
- Int128 numerator;
- Int128 denominator;
- int sign;
- bool isInt64;
+ return (sign < 0) && (m_denominator == 0);
+ }
- public:
- Rational128(int64_t value)
- {
- if (value > 0)
- {
- sign = 1;
- this->numerator = value;
- }
- else if (value < 0)
- {
- sign = -1;
- this->numerator = -value;
- }
- else
- {
- sign = 0;
- this->numerator = (uint64_t) 0;
- }
- this->denominator = (uint64_t) 1;
- isInt64 = true;
- }
+ bool isNaN() const
+ {
+ return (sign == 0) && (m_denominator == 0);
+ }
- Rational128(const Int128& numerator, const Int128& denominator)
- {
- sign = numerator.getSign();
- if (sign >= 0)
- {
- this->numerator = numerator;
- }
- else
- {
- this->numerator = -numerator;
- }
- int dsign = denominator.getSign();
- if (dsign >= 0)
- {
- this->denominator = denominator;
- }
- else
- {
- sign = -sign;
- this->denominator = -denominator;
- }
- isInt64 = false;
- }
+ int compare(const Rational64& b) const;
- int compare(const Rational128& b) const;
+ btScalar toScalar() const
+ {
+ return sign * ((m_denominator == 0) ? SIMD_INFINITY : (btScalar)m_numerator / m_denominator);
+ }
+ };
- int compare(int64_t b) const;
+ class Rational128
+ {
+ private:
+ Int128 numerator;
+ Int128 denominator;
+ int sign;
+ bool isInt64;
- btScalar toScalar() const
- {
- return sign * ((denominator.getSign() == 0) ? SIMD_INFINITY : numerator.toScalar() / denominator.toScalar());
- }
- };
+ public:
+ Rational128(int64_t value)
+ {
+ if (value > 0)
+ {
+ sign = 1;
+ this->numerator = value;
+ }
+ else if (value < 0)
+ {
+ sign = -1;
+ this->numerator = -value;
+ }
+ else
+ {
+ sign = 0;
+ this->numerator = (uint64_t)0;
+ }
+ this->denominator = (uint64_t)1;
+ isInt64 = true;
+ }
- class PointR128
+ Rational128(const Int128& numerator, const Int128& denominator)
{
- public:
- Int128 x;
- Int128 y;
- Int128 z;
- Int128 denominator;
+ sign = numerator.getSign();
+ if (sign >= 0)
+ {
+ this->numerator = numerator;
+ }
+ else
+ {
+ this->numerator = -numerator;
+ }
+ int dsign = denominator.getSign();
+ if (dsign >= 0)
+ {
+ this->denominator = denominator;
+ }
+ else
+ {
+ sign = -sign;
+ this->denominator = -denominator;
+ }
+ isInt64 = false;
+ }
- PointR128()
- {
- }
+ int compare(const Rational128& b) const;
- PointR128(Int128 x, Int128 y, Int128 z, Int128 denominator): x(x), y(y), z(z), denominator(denominator)
- {
- }
+ int compare(int64_t b) const;
- btScalar xvalue() const
- {
- return x.toScalar() / denominator.toScalar();
- }
+ btScalar toScalar() const
+ {
+ return sign * ((denominator.getSign() == 0) ? SIMD_INFINITY : numerator.toScalar() / denominator.toScalar());
+ }
+ };
- btScalar yvalue() const
- {
- return y.toScalar() / denominator.toScalar();
- }
+ class PointR128
+ {
+ public:
+ Int128 x;
+ Int128 y;
+ Int128 z;
+ Int128 denominator;
- btScalar zvalue() const
- {
- return z.toScalar() / denominator.toScalar();
- }
- };
+ PointR128()
+ {
+ }
+ PointR128(Int128 x, Int128 y, Int128 z, Int128 denominator) : x(x), y(y), z(z), denominator(denominator)
+ {
+ }
- class Edge;
- class Face;
+ btScalar xvalue() const
+ {
+ return x.toScalar() / denominator.toScalar();
+ }
- class Vertex
+ btScalar yvalue() const
{
- public:
- Vertex* next;
- Vertex* prev;
- Edge* edges;
- Face* firstNearbyFace;
- Face* lastNearbyFace;
- PointR128 point128;
- Point32 point;
- int copy;
-
- Vertex(): next(NULL), prev(NULL), edges(NULL), firstNearbyFace(NULL), lastNearbyFace(NULL), copy(-1)
- {
- }
+ return y.toScalar() / denominator.toScalar();
+ }
-#ifdef DEBUG_CONVEX_HULL
- void print()
- {
- printf("V%d (%d, %d, %d)", point.index, point.x, point.y, point.z);
- }
+ btScalar zvalue() const
+ {
+ return z.toScalar() / denominator.toScalar();
+ }
+ };
- void printGraph();
-#endif
+ class Edge;
+ class Face;
- Point32 operator-(const Vertex& b) const
- {
- return point - b.point;
- }
+ class Vertex
+ {
+ public:
+ Vertex* next;
+ Vertex* prev;
+ Edge* edges;
+ Face* firstNearbyFace;
+ Face* lastNearbyFace;
+ PointR128 point128;
+ Point32 point;
+ int copy;
- Rational128 dot(const Point64& b) const
- {
- return (point.index >= 0) ? Rational128(point.dot(b))
- : Rational128(point128.x * b.x + point128.y * b.y + point128.z * b.z, point128.denominator);
- }
+ Vertex() : next(NULL), prev(NULL), edges(NULL), firstNearbyFace(NULL), lastNearbyFace(NULL), copy(-1)
+ {
+ }
- btScalar xvalue() const
- {
- return (point.index >= 0) ? btScalar(point.x) : point128.xvalue();
- }
+#ifdef DEBUG_CONVEX_HULL
+ void print()
+ {
+ printf("V%d (%d, %d, %d)", point.index, point.x, point.y, point.z);
+ }
- btScalar yvalue() const
- {
- return (point.index >= 0) ? btScalar(point.y) : point128.yvalue();
- }
+ void printGraph();
+#endif
- btScalar zvalue() const
- {
- return (point.index >= 0) ? btScalar(point.z) : point128.zvalue();
- }
+ Point32 operator-(const Vertex& b) const
+ {
+ return point - b.point;
+ }
- void receiveNearbyFaces(Vertex* src)
- {
- if (lastNearbyFace)
- {
- lastNearbyFace->nextWithSameNearbyVertex = src->firstNearbyFace;
- }
- else
- {
- firstNearbyFace = src->firstNearbyFace;
- }
- if (src->lastNearbyFace)
- {
- lastNearbyFace = src->lastNearbyFace;
- }
- for (Face* f = src->firstNearbyFace; f; f = f->nextWithSameNearbyVertex)
- {
- btAssert(f->nearbyVertex == src);
- f->nearbyVertex = this;
- }
- src->firstNearbyFace = NULL;
- src->lastNearbyFace = NULL;
- }
- };
+ Rational128 dot(const Point64& b) const
+ {
+ return (point.index >= 0) ? Rational128(point.dot(b))
+ : Rational128(point128.x * b.x + point128.y * b.y + point128.z * b.z, point128.denominator);
+ }
+ btScalar xvalue() const
+ {
+ return (point.index >= 0) ? btScalar(point.x) : point128.xvalue();
+ }
- class Edge
+ btScalar yvalue() const
{
- public:
- Edge* next;
- Edge* prev;
- Edge* reverse;
- Vertex* target;
- Face* face;
- int copy;
+ return (point.index >= 0) ? btScalar(point.y) : point128.yvalue();
+ }
- ~Edge()
- {
- next = NULL;
- prev = NULL;
- reverse = NULL;
- target = NULL;
- face = NULL;
- }
+ btScalar zvalue() const
+ {
+ return (point.index >= 0) ? btScalar(point.z) : point128.zvalue();
+ }
- void link(Edge* n)
- {
- btAssert(reverse->target == n->reverse->target);
- next = n;
- n->prev = this;
- }
+ void receiveNearbyFaces(Vertex* src)
+ {
+ if (lastNearbyFace)
+ {
+ lastNearbyFace->nextWithSameNearbyVertex = src->firstNearbyFace;
+ }
+ else
+ {
+ firstNearbyFace = src->firstNearbyFace;
+ }
+ if (src->lastNearbyFace)
+ {
+ lastNearbyFace = src->lastNearbyFace;
+ }
+ for (Face* f = src->firstNearbyFace; f; f = f->nextWithSameNearbyVertex)
+ {
+ btAssert(f->nearbyVertex == src);
+ f->nearbyVertex = this;
+ }
+ src->firstNearbyFace = NULL;
+ src->lastNearbyFace = NULL;
+ }
+ };
-#ifdef DEBUG_CONVEX_HULL
- void print()
- {
- printf("E%p : %d -> %d, n=%p p=%p (0 %d\t%d\t%d) -> (%d %d %d)", this, reverse->target->point.index, target->point.index, next, prev,
- reverse->target->point.x, reverse->target->point.y, reverse->target->point.z, target->point.x, target->point.y, target->point.z);
- }
-#endif
- };
+ class Edge
+ {
+ public:
+ Edge* next;
+ Edge* prev;
+ Edge* reverse;
+ Vertex* target;
+ Face* face;
+ int copy;
+
+ ~Edge()
+ {
+ next = NULL;
+ prev = NULL;
+ reverse = NULL;
+ target = NULL;
+ face = NULL;
+ }
- class Face
+ void link(Edge* n)
{
- public:
- Face* next;
- Vertex* nearbyVertex;
- Face* nextWithSameNearbyVertex;
- Point32 origin;
- Point32 dir0;
- Point32 dir1;
+ btAssert(reverse->target == n->reverse->target);
+ next = n;
+ n->prev = this;
+ }
- Face(): next(NULL), nearbyVertex(NULL), nextWithSameNearbyVertex(NULL)
- {
- }
+#ifdef DEBUG_CONVEX_HULL
+ void print()
+ {
+ printf("E%p : %d -> %d, n=%p p=%p (0 %d\t%d\t%d) -> (%d %d %d)", this, reverse->target->point.index, target->point.index, next, prev,
+ reverse->target->point.x, reverse->target->point.y, reverse->target->point.z, target->point.x, target->point.y, target->point.z);
+ }
+#endif
+ };
- void init(Vertex* a, Vertex* b, Vertex* c)
- {
- nearbyVertex = a;
- origin = a->point;
- dir0 = *b - *a;
- dir1 = *c - *a;
- if (a->lastNearbyFace)
- {
- a->lastNearbyFace->nextWithSameNearbyVertex = this;
- }
- else
- {
- a->firstNearbyFace = this;
- }
- a->lastNearbyFace = this;
- }
+ class Face
+ {
+ public:
+ Face* next;
+ Vertex* nearbyVertex;
+ Face* nextWithSameNearbyVertex;
+ Point32 origin;
+ Point32 dir0;
+ Point32 dir1;
- Point64 getNormal()
- {
- return dir0.cross(dir1);
- }
- };
+ Face() : next(NULL), nearbyVertex(NULL), nextWithSameNearbyVertex(NULL)
+ {
+ }
- template<typename UWord, typename UHWord> class DMul
+ void init(Vertex* a, Vertex* b, Vertex* c)
{
- private:
- static uint32_t high(uint64_t value)
- {
- return (uint32_t) (value >> 32);
- }
-
- static uint32_t low(uint64_t value)
- {
- return (uint32_t) value;
- }
-
- static uint64_t mul(uint32_t a, uint32_t b)
- {
- return (uint64_t) a * (uint64_t) b;
- }
-
- static void shlHalf(uint64_t& value)
- {
- value <<= 32;
- }
-
- static uint64_t high(Int128 value)
- {
- return value.high;
- }
-
- static uint64_t low(Int128 value)
- {
- return value.low;
- }
-
- static Int128 mul(uint64_t a, uint64_t b)
- {
- return Int128::mul(a, b);
- }
-
- static void shlHalf(Int128& value)
- {
- value.high = value.low;
- value.low = 0;
- }
-
- public:
-
- static void mul(UWord a, UWord b, UWord& resLow, UWord& resHigh)
- {
- UWord p00 = mul(low(a), low(b));
- UWord p01 = mul(low(a), high(b));
- UWord p10 = mul(high(a), low(b));
- UWord p11 = mul(high(a), high(b));
- UWord p0110 = UWord(low(p01)) + UWord(low(p10));
- p11 += high(p01);
- p11 += high(p10);
- p11 += high(p0110);
- shlHalf(p0110);
- p00 += p0110;
- if (p00 < p0110)
- {
- ++p11;
- }
- resLow = p00;
- resHigh = p11;
- }
- };
-
- private:
+ nearbyVertex = a;
+ origin = a->point;
+ dir0 = *b - *a;
+ dir1 = *c - *a;
+ if (a->lastNearbyFace)
+ {
+ a->lastNearbyFace->nextWithSameNearbyVertex = this;
+ }
+ else
+ {
+ a->firstNearbyFace = this;
+ }
+ a->lastNearbyFace = this;
+ }
- class IntermediateHull
+ Point64 getNormal()
{
- public:
- Vertex* minXy;
- Vertex* maxXy;
- Vertex* minYx;
- Vertex* maxYx;
-
- IntermediateHull(): minXy(NULL), maxXy(NULL), minYx(NULL), maxYx(NULL)
- {
- }
-
- void print();
- };
-
- enum Orientation {NONE, CLOCKWISE, COUNTER_CLOCKWISE};
+ return dir0.cross(dir1);
+ }
+ };
- template <typename T> class PoolArray
+ template <typename UWord, typename UHWord>
+ class DMul
+ {
+ private:
+ static uint32_t high(uint64_t value)
{
- private:
- T* array;
- int size;
+ return (uint32_t)(value >> 32);
+ }
- public:
- PoolArray<T>* next;
+ static uint32_t low(uint64_t value)
+ {
+ return (uint32_t)value;
+ }
- PoolArray(int size): size(size), next(NULL)
- {
- array = (T*) btAlignedAlloc(sizeof(T) * size, 16);
- }
+ static uint64_t mul(uint32_t a, uint32_t b)
+ {
+ return (uint64_t)a * (uint64_t)b;
+ }
- ~PoolArray()
- {
- btAlignedFree(array);
- }
+ static void shlHalf(uint64_t& value)
+ {
+ value <<= 32;
+ }
- T* init()
- {
- T* o = array;
- for (int i = 0; i < size; i++, o++)
- {
- o->next = (i+1 < size) ? o + 1 : NULL;
- }
- return array;
- }
- };
+ static uint64_t high(Int128 value)
+ {
+ return value.high;
+ }
- template <typename T> class Pool
+ static uint64_t low(Int128 value)
{
- private:
- PoolArray<T>* arrays;
- PoolArray<T>* nextArray;
- T* freeObjects;
- int arraySize;
+ return value.low;
+ }
- public:
- Pool(): arrays(NULL), nextArray(NULL), freeObjects(NULL), arraySize(256)
- {
- }
+ static Int128 mul(uint64_t a, uint64_t b)
+ {
+ return Int128::mul(a, b);
+ }
- ~Pool()
- {
- while (arrays)
- {
- PoolArray<T>* p = arrays;
- arrays = p->next;
- p->~PoolArray<T>();
- btAlignedFree(p);
- }
- }
+ static void shlHalf(Int128& value)
+ {
+ value.high = value.low;
+ value.low = 0;
+ }
- void reset()
- {
- nextArray = arrays;
- freeObjects = NULL;
- }
+ public:
+ static void mul(UWord a, UWord b, UWord& resLow, UWord& resHigh)
+ {
+ UWord p00 = mul(low(a), low(b));
+ UWord p01 = mul(low(a), high(b));
+ UWord p10 = mul(high(a), low(b));
+ UWord p11 = mul(high(a), high(b));
+ UWord p0110 = UWord(low(p01)) + UWord(low(p10));
+ p11 += high(p01);
+ p11 += high(p10);
+ p11 += high(p0110);
+ shlHalf(p0110);
+ p00 += p0110;
+ if (p00 < p0110)
+ {
+ ++p11;
+ }
+ resLow = p00;
+ resHigh = p11;
+ }
+ };
- void setArraySize(int arraySize)
- {
- this->arraySize = arraySize;
- }
+private:
+ class IntermediateHull
+ {
+ public:
+ Vertex* minXy;
+ Vertex* maxXy;
+ Vertex* minYx;
+ Vertex* maxYx;
- T* newObject()
- {
- T* o = freeObjects;
- if (!o)
- {
- PoolArray<T>* p = nextArray;
- if (p)
- {
- nextArray = p->next;
- }
- else
- {
- p = new(btAlignedAlloc(sizeof(PoolArray<T>), 16)) PoolArray<T>(arraySize);
- p->next = arrays;
- arrays = p;
- }
- o = p->init();
- }
- freeObjects = o->next;
- return new(o) T();
- };
+ IntermediateHull() : minXy(NULL), maxXy(NULL), minYx(NULL), maxYx(NULL)
+ {
+ }
- void freeObject(T* object)
- {
- object->~T();
- object->next = freeObjects;
- freeObjects = object;
- }
- };
+ void print();
+ };
- btVector3 scaling;
- btVector3 center;
- Pool<Vertex> vertexPool;
- Pool<Edge> edgePool;
- Pool<Face> facePool;
- btAlignedObjectArray<Vertex*> originalVertices;
- int mergeStamp;
- int minAxis;
- int medAxis;
- int maxAxis;
- int usedEdgePairs;
- int maxUsedEdgePairs;
+ enum Orientation
+ {
+ NONE,
+ CLOCKWISE,
+ COUNTER_CLOCKWISE
+ };
- static Orientation getOrientation(const Edge* prev, const Edge* next, const Point32& s, const Point32& t);
- Edge* findMaxAngle(bool ccw, const Vertex* start, const Point32& s, const Point64& rxs, const Point64& sxrxs, Rational64& minCot);
- void findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge*& e0, Edge*& e1, Vertex* stop0, Vertex* stop1);
+ template <typename T>
+ class PoolArray
+ {
+ private:
+ T* array;
+ int size;
- Edge* newEdgePair(Vertex* from, Vertex* to);
+ public:
+ PoolArray<T>* next;
- void removeEdgePair(Edge* edge)
+ PoolArray(int size) : size(size), next(NULL)
{
- Edge* n = edge->next;
- Edge* r = edge->reverse;
+ array = (T*)btAlignedAlloc(sizeof(T) * size, 16);
+ }
- btAssert(edge->target && r->target);
+ ~PoolArray()
+ {
+ btAlignedFree(array);
+ }
- if (n != edge)
- {
- n->prev = edge->prev;
- edge->prev->next = n;
- r->target->edges = n;
- }
- else
+ T* init()
+ {
+ T* o = array;
+ for (int i = 0; i < size; i++, o++)
{
- r->target->edges = NULL;
+ o->next = (i + 1 < size) ? o + 1 : NULL;
}
-
- n = r->next;
-
- if (n != r)
+ return array;
+ }
+ };
+
+ template <typename T>
+ class Pool
+ {
+ private:
+ PoolArray<T>* arrays;
+ PoolArray<T>* nextArray;
+ T* freeObjects;
+ int arraySize;
+
+ public:
+ Pool() : arrays(NULL), nextArray(NULL), freeObjects(NULL), arraySize(256)
+ {
+ }
+
+ ~Pool()
+ {
+ while (arrays)
{
- n->prev = r->prev;
- r->prev->next = n;
- edge->target->edges = n;
+ PoolArray<T>* p = arrays;
+ arrays = p->next;
+ p->~PoolArray<T>();
+ btAlignedFree(p);
}
- else
+ }
+
+ void reset()
+ {
+ nextArray = arrays;
+ freeObjects = NULL;
+ }
+
+ void setArraySize(int arraySize)
+ {
+ this->arraySize = arraySize;
+ }
+
+ T* newObject()
+ {
+ T* o = freeObjects;
+ if (!o)
{
- edge->target->edges = NULL;
+ PoolArray<T>* p = nextArray;
+ if (p)
+ {
+ nextArray = p->next;
+ }
+ else
+ {
+ p = new (btAlignedAlloc(sizeof(PoolArray<T>), 16)) PoolArray<T>(arraySize);
+ p->next = arrays;
+ arrays = p;
+ }
+ o = p->init();
}
+ freeObjects = o->next;
+ return new (o) T();
+ };
+
+ void freeObject(T* object)
+ {
+ object->~T();
+ object->next = freeObjects;
+ freeObjects = object;
+ }
+ };
+
+ btVector3 scaling;
+ btVector3 center;
+ Pool<Vertex> vertexPool;
+ Pool<Edge> edgePool;
+ Pool<Face> facePool;
+ btAlignedObjectArray<Vertex*> originalVertices;
+ int mergeStamp;
+ int minAxis;
+ int medAxis;
+ int maxAxis;
+ int usedEdgePairs;
+ int maxUsedEdgePairs;
+
+ static Orientation getOrientation(const Edge* prev, const Edge* next, const Point32& s, const Point32& t);
+ Edge* findMaxAngle(bool ccw, const Vertex* start, const Point32& s, const Point64& rxs, const Point64& sxrxs, Rational64& minCot);
+ void findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge*& e0, Edge*& e1, Vertex* stop0, Vertex* stop1);
+
+ Edge* newEdgePair(Vertex* from, Vertex* to);
- edgePool.freeObject(edge);
- edgePool.freeObject(r);
- usedEdgePairs--;
+ void removeEdgePair(Edge* edge)
+ {
+ Edge* n = edge->next;
+ Edge* r = edge->reverse;
+
+ btAssert(edge->target && r->target);
+
+ if (n != edge)
+ {
+ n->prev = edge->prev;
+ edge->prev->next = n;
+ r->target->edges = n;
+ }
+ else
+ {
+ r->target->edges = NULL;
+ }
+
+ n = r->next;
+
+ if (n != r)
+ {
+ n->prev = r->prev;
+ r->prev->next = n;
+ edge->target->edges = n;
+ }
+ else
+ {
+ edge->target->edges = NULL;
}
-
- void computeInternal(int start, int end, IntermediateHull& result);
-
- bool mergeProjection(IntermediateHull& h0, IntermediateHull& h1, Vertex*& c0, Vertex*& c1);
-
- void merge(IntermediateHull& h0, IntermediateHull& h1);
- btVector3 toBtVector(const Point32& v);
+ edgePool.freeObject(edge);
+ edgePool.freeObject(r);
+ usedEdgePairs--;
+ }
- btVector3 getBtNormal(Face* face);
+ void computeInternal(int start, int end, IntermediateHull& result);
- bool shiftFace(Face* face, btScalar amount, btAlignedObjectArray<Vertex*> stack);
+ bool mergeProjection(IntermediateHull& h0, IntermediateHull& h1, Vertex*& c0, Vertex*& c1);
- public:
- Vertex* vertexList;
+ void merge(IntermediateHull& h0, IntermediateHull& h1);
- void compute(const void* coords, bool doubleCoords, int stride, int count);
+ btVector3 toBtVector(const Point32& v);
- btVector3 getCoordinates(const Vertex* v);
+ btVector3 getBtNormal(Face* face);
- btScalar shrink(btScalar amount, btScalar clampAmount);
-};
+ bool shiftFace(Face* face, btScalar amount, btAlignedObjectArray<Vertex*> stack);
+public:
+ Vertex* vertexList;
+
+ void compute(const void* coords, bool doubleCoords, int stride, int count);
+
+ btVector3 getCoordinates(const Vertex* v);
+
+ btScalar shrink(btScalar amount, btScalar clampAmount);
+};
btConvexHullInternal::Int128 btConvexHullInternal::Int128::operator*(int64_t b) const
{
- bool negative = (int64_t) high < 0;
+ bool negative = (int64_t)high < 0;
Int128 a = negative ? -*this : *this;
if (b < 0)
{
negative = !negative;
b = -b;
}
- Int128 result = mul(a.low, (uint64_t) b);
- result.high += a.high * (uint64_t) b;
+ Int128 result = mul(a.low, (uint64_t)b);
+ result.high += a.high * (uint64_t)b;
return negative ? -result : result;
}
btConvexHullInternal::Int128 btConvexHullInternal::Int128::mul(int64_t a, int64_t b)
{
Int128 result;
-
+
#ifdef USE_X86_64_ASM
- __asm__ ("imulq %[b]"
- : "=a" (result.low), "=d" (result.high)
- : "0"(a), [b] "r"(b)
- : "cc" );
+ __asm__("imulq %[b]"
+ : "=a"(result.low), "=d"(result.high)
+ : "0"(a), [b] "r"(b)
+ : "cc");
return result;
-
+
#else
bool negative = a < 0;
if (negative)
@@ -871,7 +872,7 @@ btConvexHullInternal::Int128 btConvexHullInternal::Int128::mul(int64_t a, int64_
negative = !negative;
b = -b;
}
- DMul<uint64_t, uint32_t>::mul((uint64_t) a, (uint64_t) b, result.low, result.high);
+ DMul<uint64_t, uint32_t>::mul((uint64_t)a, (uint64_t)b, result.low, result.high);
return negative ? -result : result;
#endif
}
@@ -881,10 +882,10 @@ btConvexHullInternal::Int128 btConvexHullInternal::Int128::mul(uint64_t a, uint6
Int128 result;
#ifdef USE_X86_64_ASM
- __asm__ ("mulq %[b]"
- : "=a" (result.low), "=d" (result.high)
- : "0"(a), [b] "r"(b)
- : "cc" );
+ __asm__("mulq %[b]"
+ : "=a"(result.low), "=d"(result.high)
+ : "0"(a), [b] "r"(b)
+ : "cc");
#else
DMul<uint64_t, uint32_t>::mul(a, b, result.low, result.high);
@@ -911,24 +912,25 @@ int btConvexHullInternal::Rational64::compare(const Rational64& b) const
int result;
int64_t tmp;
int64_t dummy;
- __asm__ ("mulq %[bn]\n\t"
- "movq %%rax, %[tmp]\n\t"
- "movq %%rdx, %%rbx\n\t"
- "movq %[tn], %%rax\n\t"
- "mulq %[bd]\n\t"
- "subq %[tmp], %%rax\n\t"
- "sbbq %%rbx, %%rdx\n\t" // rdx:rax contains 128-bit-difference "numerator*b.denominator - b.numerator*denominator"
- "setnsb %%bh\n\t" // bh=1 if difference is non-negative, bh=0 otherwise
- "orq %%rdx, %%rax\n\t"
- "setnzb %%bl\n\t" // bl=1 if difference if non-zero, bl=0 if it is zero
- "decb %%bh\n\t" // now bx=0x0000 if difference is zero, 0xff01 if it is negative, 0x0001 if it is positive (i.e., same sign as difference)
- "shll $16, %%ebx\n\t" // ebx has same sign as difference
- : "=&b"(result), [tmp] "=&r"(tmp), "=a"(dummy)
- : "a"(denominator), [bn] "g"(b.numerator), [tn] "g"(numerator), [bd] "g"(b.denominator)
- : "%rdx", "cc" );
- return result ? result ^ sign // if sign is +1, only bit 0 of result is inverted, which does not change the sign of result (and cannot result in zero)
- // if sign is -1, all bits of result are inverted, which changes the sign of result (and again cannot result in zero)
- : 0;
+ __asm__(
+ "mulq %[bn]\n\t"
+ "movq %%rax, %[tmp]\n\t"
+ "movq %%rdx, %%rbx\n\t"
+ "movq %[tn], %%rax\n\t"
+ "mulq %[bd]\n\t"
+ "subq %[tmp], %%rax\n\t"
+ "sbbq %%rbx, %%rdx\n\t" // rdx:rax contains 128-bit-difference "numerator*b.denominator - b.numerator*denominator"
+ "setnsb %%bh\n\t" // bh=1 if difference is non-negative, bh=0 otherwise
+ "orq %%rdx, %%rax\n\t"
+ "setnzb %%bl\n\t" // bl=1 if difference if non-zero, bl=0 if it is zero
+ "decb %%bh\n\t" // now bx=0x0000 if difference is zero, 0xff01 if it is negative, 0x0001 if it is positive (i.e., same sign as difference)
+ "shll $16, %%ebx\n\t" // ebx has same sign as difference
+ : "=&b"(result), [tmp] "=&r"(tmp), "=a"(dummy)
+ : "a"(m_denominator), [bn] "g"(b.m_numerator), [tn] "g"(m_numerator), [bd] "g"(b.m_denominator)
+ : "%rdx", "cc");
+ return result ? result ^ sign // if sign is +1, only bit 0 of result is inverted, which does not change the sign of result (and cannot result in zero)
+ // if sign is -1, all bits of result are inverted, which changes the sign of result (and again cannot result in zero)
+ : 0;
#else
@@ -949,7 +951,7 @@ int btConvexHullInternal::Rational128::compare(const Rational128& b) const
}
if (isInt64)
{
- return -b.compare(sign * (int64_t) numerator.low);
+ return -b.compare(sign * (int64_t)numerator.low);
}
Int128 nbdLow, nbdHigh, dbnLow, dbnHigh;
@@ -968,7 +970,7 @@ int btConvexHullInternal::Rational128::compare(int64_t b) const
{
if (isInt64)
{
- int64_t a = sign * (int64_t) numerator.low;
+ int64_t a = sign * (int64_t)numerator.low;
return (a > b) ? 1 : (a < b) ? -1 : 0;
}
if (b > 0)
@@ -994,7 +996,6 @@ int btConvexHullInternal::Rational128::compare(int64_t b) const
return numerator.ucmp(denominator * b) * sign;
}
-
btConvexHullInternal::Edge* btConvexHullInternal::newEdgePair(Vertex* from, Vertex* to)
{
btAssert(from && to);
@@ -1062,7 +1063,7 @@ bool btConvexHullInternal::mergeProjection(IntermediateHull& h0, IntermediateHul
}
}
}
-
+
v0 = h0.maxXy;
v1 = h1.maxXy;
Vertex* v00 = NULL;
@@ -1070,7 +1071,7 @@ bool btConvexHullInternal::mergeProjection(IntermediateHull& h0, IntermediateHul
int32_t sign = 1;
for (int side = 0; side <= 1; side++)
- {
+ {
int32_t dx = (v1->point.x - v0->point.x) * sign;
if (dx > 0)
{
@@ -1113,7 +1114,7 @@ bool btConvexHullInternal::mergeProjection(IntermediateHull& h0, IntermediateHul
while (true)
{
int32_t dy = v1->point.y - v0->point.y;
-
+
Vertex* w1 = side ? v1->prev : v1->next;
if (w1 != v1)
{
@@ -1126,7 +1127,7 @@ bool btConvexHullInternal::mergeProjection(IntermediateHull& h0, IntermediateHul
continue;
}
}
-
+
Vertex* w0 = side ? v0->prev : v0->next;
if (w0 != v0)
{
@@ -1140,7 +1141,7 @@ bool btConvexHullInternal::mergeProjection(IntermediateHull& h0, IntermediateHul
continue;
}
}
-
+
break;
}
}
@@ -1166,7 +1167,7 @@ bool btConvexHullInternal::mergeProjection(IntermediateHull& h0, IntermediateHul
}
v1 = w1;
}
-
+
if (side == 0)
{
v00 = v0;
@@ -1192,7 +1193,7 @@ bool btConvexHullInternal::mergeProjection(IntermediateHull& h0, IntermediateHul
{
h0.maxXy = h1.maxXy;
}
-
+
h0.maxYx = h1.maxYx;
c0 = v00;
@@ -1279,19 +1280,19 @@ void btConvexHullInternal::computeInternal(int start, int end, IntermediateHull&
}
{
Vertex* v = originalVertices[start];
- v->edges = NULL;
- v->next = v;
- v->prev = v;
-
- result.minXy = v;
- result.maxXy = v;
- result.minYx = v;
- result.maxYx = v;
+ v->edges = NULL;
+ v->next = v;
+ v->prev = v;
+
+ result.minXy = v;
+ result.maxXy = v;
+ result.minYx = v;
+ result.maxYx = v;
}
-
+
return;
}
-
+
case 1:
{
Vertex* v = originalVertices[start];
@@ -1309,7 +1310,7 @@ void btConvexHullInternal::computeInternal(int start, int end, IntermediateHull&
}
int split0 = start + n / 2;
- Point32 p = originalVertices[split0-1]->point;
+ Point32 p = originalVertices[split0 - 1]->point;
int split1 = split0;
while ((split1 < end) && (originalVertices[split1]->point == p))
{
@@ -1334,7 +1335,7 @@ void btConvexHullInternal::computeInternal(int start, int end, IntermediateHull&
void btConvexHullInternal::IntermediateHull::print()
{
printf(" Hull\n");
- for (Vertex* v = minXy; v; )
+ for (Vertex* v = minXy; v;)
{
printf(" ");
v->print();
@@ -1362,7 +1363,7 @@ void btConvexHullInternal::IntermediateHull::print()
}
}
if (minXy)
- {
+ {
minXy->copy = (minXy->copy == -1) ? -2 : -1;
minXy->printGraph();
}
@@ -1438,7 +1439,7 @@ btConvexHullInternal::Edge* btConvexHullInternal::findMaxAngle(bool ccw, const V
Point32 t = *e->target - *start;
Rational64 cot(t.dot(sxrxs), t.dot(rxs));
#ifdef DEBUG_CONVEX_HULL
- printf(" Angle is %f (%d) for ", (float) btAtan(cot.toScalar()), (int) cot.isNaN());
+ printf(" Angle is %f (%d) for ", (float)btAtan(cot.toScalar()), (int)cot.isNaN());
e->print();
#endif
if (cot.isNaN())
@@ -1485,7 +1486,7 @@ void btConvexHullInternal::findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge
btAssert(!start1 || (start1->target->point.dot(normal) == dist));
Point64 perp = s.cross(normal);
btAssert(!perp.isZero());
-
+
#ifdef DEBUG_CONVEX_HULL
printf(" Advancing %d %d (%p %p, %d %d)\n", c0->point.index, c1->point.index, start0, start1, start0 ? start0->target->point.index : -1, start1 ? start1->target->point.index : -1);
#endif
@@ -1515,7 +1516,7 @@ void btConvexHullInternal::findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge
et0 = e->target->point;
}
}
-
+
int64_t maxDot1 = et1.dot(perp);
if (e1)
{
@@ -1552,7 +1553,7 @@ void btConvexHullInternal::findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge
while (true)
{
int64_t dy = (et1 - et0).dot(s);
-
+
if (e0 && (e0->target != stop0))
{
Edge* f0 = e0->next->reverse;
@@ -1569,7 +1570,7 @@ void btConvexHullInternal::findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge
}
}
}
-
+
if (e1 && (e1->target != stop1))
{
Edge* f1 = e1->reverse->next;
@@ -1604,7 +1605,7 @@ void btConvexHullInternal::findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge
while (true)
{
int64_t dy = (et1 - et0).dot(s);
-
+
if (e1 && (e1->target != stop1))
{
Edge* f1 = e1->prev->reverse;
@@ -1621,7 +1622,7 @@ void btConvexHullInternal::findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge
}
}
}
-
+
if (e0 && (e0->target != stop0))
{
Edge* f0 = e0->reverse->prev;
@@ -1656,7 +1657,6 @@ void btConvexHullInternal::findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge
#endif
}
-
void btConvexHullInternal::merge(IntermediateHull& h0, IntermediateHull& h1)
{
if (!h1.maxXy)
@@ -1668,7 +1668,7 @@ void btConvexHullInternal::merge(IntermediateHull& h0, IntermediateHull& h1)
h0 = h1;
return;
}
-
+
mergeStamp--;
Vertex* c0 = NULL;
@@ -1708,7 +1708,7 @@ void btConvexHullInternal::merge(IntermediateHull& h0, IntermediateHull& h1)
e = e->next;
} while (e != c0->edges);
}
-
+
e = c1->edges;
Edge* start1 = NULL;
if (e)
@@ -1760,7 +1760,7 @@ void btConvexHullInternal::merge(IntermediateHull& h0, IntermediateHull& h1)
Point32 r = prevPoint - c0->point;
Point64 rxs = r.cross(s);
Point64 sxrxs = s.cross(rxs);
-
+
#ifdef DEBUG_CONVEX_HULL
printf("\n Checking %d %d\n", c0->point.index, c1->point.index);
#endif
@@ -1811,7 +1811,7 @@ void btConvexHullInternal::merge(IntermediateHull& h0, IntermediateHull& h1)
e->prev = pendingTail1;
pendingTail1 = e;
}
-
+
Edge* e0 = min0;
Edge* e1 = min1;
@@ -1828,7 +1828,7 @@ void btConvexHullInternal::merge(IntermediateHull& h0, IntermediateHull& h1)
{
if (toPrev1)
{
- for (Edge* e = toPrev1->next, *n = NULL; e != min1; e = n)
+ for (Edge *e = toPrev1->next, *n = NULL; e != min1; e = n)
{
n = e->next;
removeEdgePair(e);
@@ -1864,7 +1864,7 @@ void btConvexHullInternal::merge(IntermediateHull& h0, IntermediateHull& h1)
{
if (toPrev0)
{
- for (Edge* e = toPrev0->prev, *n = NULL; e != min0; e = n)
+ for (Edge *e = toPrev0->prev, *n = NULL; e != min0; e = n)
{
n = e->prev;
removeEdgePair(e);
@@ -1906,7 +1906,7 @@ void btConvexHullInternal::merge(IntermediateHull& h0, IntermediateHull& h1)
}
else
{
- for (Edge* e = toPrev0->prev, *n = NULL; e != firstNew0; e = n)
+ for (Edge *e = toPrev0->prev, *n = NULL; e != firstNew0; e = n)
{
n = e->prev;
removeEdgePair(e);
@@ -1925,7 +1925,7 @@ void btConvexHullInternal::merge(IntermediateHull& h0, IntermediateHull& h1)
}
else
{
- for (Edge* e = toPrev1->next, *n = NULL; e != firstNew1; e = n)
+ for (Edge *e = toPrev1->next, *n = NULL; e != firstNew1; e = n)
{
n = e->next;
removeEdgePair(e);
@@ -1936,7 +1936,7 @@ void btConvexHullInternal::merge(IntermediateHull& h0, IntermediateHull& h1)
pendingTail1->link(firstNew1);
}
}
-
+
return;
}
@@ -1946,24 +1946,23 @@ void btConvexHullInternal::merge(IntermediateHull& h0, IntermediateHull& h1)
class pointCmp
{
- public:
-
- bool operator() ( const btConvexHullInternal::Point32& p, const btConvexHullInternal::Point32& q ) const
- {
- return (p.y < q.y) || ((p.y == q.y) && ((p.x < q.x) || ((p.x == q.x) && (p.z < q.z))));
- }
+public:
+ bool operator()(const btConvexHullInternal::Point32& p, const btConvexHullInternal::Point32& q) const
+ {
+ return (p.y < q.y) || ((p.y == q.y) && ((p.x < q.x) || ((p.x == q.x) && (p.z < q.z))));
+ }
};
void btConvexHullInternal::compute(const void* coords, bool doubleCoords, int stride, int count)
{
btVector3 min(btScalar(1e30), btScalar(1e30), btScalar(1e30)), max(btScalar(-1e30), btScalar(-1e30), btScalar(-1e30));
- const char* ptr = (const char*) coords;
+ const char* ptr = (const char*)coords;
if (doubleCoords)
{
for (int i = 0; i < count; i++)
{
- const double* v = (const double*) ptr;
- btVector3 p((btScalar) v[0], (btScalar) v[1], (btScalar) v[2]);
+ const double* v = (const double*)ptr;
+ btVector3 p((btScalar)v[0], (btScalar)v[1], (btScalar)v[2]);
ptr += stride;
min.setMin(p);
max.setMax(p);
@@ -1973,7 +1972,7 @@ void btConvexHullInternal::compute(const void* coords, bool doubleCoords, int st
{
for (int i = 0; i < count; i++)
{
- const float* v = (const float*) ptr;
+ const float* v = (const float*)ptr;
btVector3 p(v[0], v[1], v[2]);
ptr += stride;
min.setMin(p);
@@ -2014,18 +2013,18 @@ void btConvexHullInternal::compute(const void* coords, bool doubleCoords, int st
btAlignedObjectArray<Point32> points;
points.resize(count);
- ptr = (const char*) coords;
+ ptr = (const char*)coords;
if (doubleCoords)
{
for (int i = 0; i < count; i++)
{
- const double* v = (const double*) ptr;
- btVector3 p((btScalar) v[0], (btScalar) v[1], (btScalar) v[2]);
+ const double* v = (const double*)ptr;
+ btVector3 p((btScalar)v[0], (btScalar)v[1], (btScalar)v[2]);
ptr += stride;
p = (p - center) * s;
- points[i].x = (int32_t) p[medAxis];
- points[i].y = (int32_t) p[maxAxis];
- points[i].z = (int32_t) p[minAxis];
+ points[i].x = (int32_t)p[medAxis];
+ points[i].y = (int32_t)p[maxAxis];
+ points[i].z = (int32_t)p[minAxis];
points[i].index = i;
}
}
@@ -2033,13 +2032,13 @@ void btConvexHullInternal::compute(const void* coords, bool doubleCoords, int st
{
for (int i = 0; i < count; i++)
{
- const float* v = (const float*) ptr;
+ const float* v = (const float*)ptr;
btVector3 p(v[0], v[1], v[2]);
ptr += stride;
p = (p - center) * s;
- points[i].x = (int32_t) p[medAxis];
- points[i].y = (int32_t) p[maxAxis];
- points[i].z = (int32_t) p[minAxis];
+ points[i].x = (int32_t)p[medAxis];
+ points[i].y = (int32_t)p[maxAxis];
+ points[i].z = (int32_t)p[minAxis];
points[i].index = i;
}
}
@@ -2193,7 +2192,7 @@ btScalar btConvexHullInternal::shrink(btScalar amount, btScalar clampAmount)
minDist = dist;
}
}
-
+
if (minDist <= 0)
{
return 0;
@@ -2234,7 +2233,7 @@ bool btConvexHullInternal::shiftFace(Face* face, btScalar amount, btAlignedObjec
{
origShift[2] /= scaling[2];
}
- Point32 shift((int32_t) origShift[medAxis], (int32_t) origShift[maxAxis], (int32_t) origShift[minAxis]);
+ Point32 shift((int32_t)origShift[medAxis], (int32_t)origShift[maxAxis], (int32_t)origShift[minAxis]);
if (shift.isZero())
{
return true;
@@ -2242,7 +2241,7 @@ bool btConvexHullInternal::shiftFace(Face* face, btScalar amount, btAlignedObjec
Point64 normal = face->getNormal();
#ifdef DEBUG_CONVEX_HULL
printf("\nShrinking face (%d %d %d) (%d %d %d) (%d %d %d) by (%d %d %d)\n",
- face->origin.x, face->origin.y, face->origin.z, face->dir0.x, face->dir0.y, face->dir0.z, face->dir1.x, face->dir1.y, face->dir1.z, shift.x, shift.y, shift.z);
+ face->origin.x, face->origin.y, face->origin.z, face->dir0.x, face->dir0.y, face->dir0.z, face->dir1.x, face->dir1.y, face->dir1.z, shift.x, shift.y, shift.z);
#endif
int64_t origDot = face->origin.dot(normal);
Point32 shiftedOrigin = face->origin + shift;
@@ -2279,7 +2278,7 @@ bool btConvexHullInternal::shiftFace(Face* face, btScalar amount, btAlignedObjec
#ifdef DEBUG_CONVEX_HULL
printf("Moving downwards, edge is ");
e->print();
- printf(", dot is %f (%f %lld)\n", (float) dot.toScalar(), (float) optDot.toScalar(), shiftedDot);
+ printf(", dot is %f (%f %lld)\n", (float)dot.toScalar(), (float)optDot.toScalar(), shiftedDot);
#endif
if (dot.compare(optDot) < 0)
{
@@ -2315,7 +2314,7 @@ bool btConvexHullInternal::shiftFace(Face* face, btScalar amount, btAlignedObjec
#ifdef DEBUG_CONVEX_HULL
printf("Moving upwards, edge is ");
e->print();
- printf(", dot is %f (%f %lld)\n", (float) dot.toScalar(), (float) optDot.toScalar(), shiftedDot);
+ printf(", dot is %f (%f %lld)\n", (float)dot.toScalar(), (float)optDot.toScalar(), shiftedDot);
#endif
if (dot.compare(optDot) > 0)
{
@@ -2331,7 +2330,7 @@ bool btConvexHullInternal::shiftFace(Face* face, btScalar amount, btAlignedObjec
}
e = e->prev;
} while (e != startEdge);
-
+
if (!intersection)
{
return true;
@@ -2368,7 +2367,7 @@ bool btConvexHullInternal::shiftFace(Face* face, btScalar amount, btAlignedObjec
printf("Needed %d iterations to check for complete containment\n", n);
#endif
}
-
+
Edge* firstIntersection = NULL;
Edge* faceEdge = NULL;
Edge* firstFaceEdge = NULL;
@@ -2477,7 +2476,7 @@ bool btConvexHullInternal::shiftFace(Face* face, btScalar amount, btAlignedObjec
#ifdef DEBUG_CONVEX_HULL
printf("1: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z);
#endif
-
+
Point64 n0 = intersection->face->getNormal();
Point64 n1 = intersection->reverse->face->getNormal();
int64_t m00 = face->dir0.dot(n0);
@@ -2491,16 +2490,13 @@ bool btConvexHullInternal::shiftFace(Face* face, btScalar amount, btAlignedObjec
Vertex* v = vertexPool.newObject();
v->point.index = -1;
v->copy = -1;
- v->point128 = PointR128(Int128::mul(face->dir0.x * r0, m11) - Int128::mul(face->dir0.x * r1, m01)
- + Int128::mul(face->dir1.x * r1, m00) - Int128::mul(face->dir1.x * r0, m10) + det * shiftedOrigin.x,
- Int128::mul(face->dir0.y * r0, m11) - Int128::mul(face->dir0.y * r1, m01)
- + Int128::mul(face->dir1.y * r1, m00) - Int128::mul(face->dir1.y * r0, m10) + det * shiftedOrigin.y,
- Int128::mul(face->dir0.z * r0, m11) - Int128::mul(face->dir0.z * r1, m01)
- + Int128::mul(face->dir1.z * r1, m00) - Int128::mul(face->dir1.z * r0, m10) + det * shiftedOrigin.z,
- det);
- v->point.x = (int32_t) v->point128.xvalue();
- v->point.y = (int32_t) v->point128.yvalue();
- v->point.z = (int32_t) v->point128.zvalue();
+ v->point128 = PointR128(Int128::mul(face->dir0.x * r0, m11) - Int128::mul(face->dir0.x * r1, m01) + Int128::mul(face->dir1.x * r1, m00) - Int128::mul(face->dir1.x * r0, m10) + det * shiftedOrigin.x,
+ Int128::mul(face->dir0.y * r0, m11) - Int128::mul(face->dir0.y * r1, m01) + Int128::mul(face->dir1.y * r1, m00) - Int128::mul(face->dir1.y * r0, m10) + det * shiftedOrigin.y,
+ Int128::mul(face->dir0.z * r0, m11) - Int128::mul(face->dir0.z * r1, m01) + Int128::mul(face->dir1.z * r1, m00) - Int128::mul(face->dir1.z * r0, m10) + det * shiftedOrigin.z,
+ det);
+ v->point.x = (int32_t)v->point128.xvalue();
+ v->point.y = (int32_t)v->point128.yvalue();
+ v->point.z = (int32_t)v->point128.zvalue();
intersection->target = v;
v->edges = e;
@@ -2639,7 +2635,6 @@ bool btConvexHullInternal::shiftFace(Face* face, btScalar amount, btAlignedObjec
return true;
}
-
static int getVertexCopy(btConvexHullInternal::Vertex* vertex, btAlignedObjectArray<btConvexHullInternal::Vertex*>& vertices)
{
int index = vertex->copy;
@@ -2761,8 +2756,3 @@ btScalar btConvexHullComputer::compute(const void* coords, bool doubleCoords, in
return shift;
}
-
-
-
-
-
diff --git a/thirdparty/bullet/LinearMath/btConvexHullComputer.h b/thirdparty/bullet/LinearMath/btConvexHullComputer.h
index 7240ac4fb5..cba684f2dc 100644
--- a/thirdparty/bullet/LinearMath/btConvexHullComputer.h
+++ b/thirdparty/bullet/LinearMath/btConvexHullComputer.h
@@ -23,58 +23,56 @@ subject to the following restrictions:
/// Ole Kniemeyer, MAXON Computer GmbH
class btConvexHullComputer
{
+private:
+ btScalar compute(const void* coords, bool doubleCoords, int stride, int count, btScalar shrink, btScalar shrinkClamp);
+
+public:
+ class Edge
+ {
private:
- btScalar compute(const void* coords, bool doubleCoords, int stride, int count, btScalar shrink, btScalar shrinkClamp);
+ int next;
+ int reverse;
+ int targetVertex;
- public:
+ friend class btConvexHullComputer;
- class Edge
+ public:
+ int getSourceVertex() const
{
- private:
- int next;
- int reverse;
- int targetVertex;
-
- friend class btConvexHullComputer;
-
- public:
- int getSourceVertex() const
- {
- return (this + reverse)->targetVertex;
- }
-
- int getTargetVertex() const
- {
- return targetVertex;
- }
+ return (this + reverse)->targetVertex;
+ }
- const Edge* getNextEdgeOfVertex() const // clockwise list of all edges of a vertex
- {
- return this + next;
- }
+ int getTargetVertex() const
+ {
+ return targetVertex;
+ }
- const Edge* getNextEdgeOfFace() const // counter-clockwise list of all edges of a face
- {
- return (this + reverse)->getNextEdgeOfVertex();
- }
+ const Edge* getNextEdgeOfVertex() const // clockwise list of all edges of a vertex
+ {
+ return this + next;
+ }
- const Edge* getReverseEdge() const
- {
- return this + reverse;
- }
- };
+ const Edge* getNextEdgeOfFace() const // counter-clockwise list of all edges of a face
+ {
+ return (this + reverse)->getNextEdgeOfVertex();
+ }
+ const Edge* getReverseEdge() const
+ {
+ return this + reverse;
+ }
+ };
- // Vertices of the output hull
- btAlignedObjectArray<btVector3> vertices;
+ // Vertices of the output hull
+ btAlignedObjectArray<btVector3> vertices;
- // Edges of the output hull
- btAlignedObjectArray<Edge> edges;
+ // Edges of the output hull
+ btAlignedObjectArray<Edge> edges;
- // Faces of the convex hull. Each entry is an index into the "edges" array pointing to an edge of the face. Faces are planar n-gons
- btAlignedObjectArray<int> faces;
+ // Faces of the convex hull. Each entry is an index into the "edges" array pointing to an edge of the face. Faces are planar n-gons
+ btAlignedObjectArray<int> faces;
- /*
+ /*
Compute convex hull of "count" vertices stored in "coords". "stride" is the difference in bytes
between the addresses of consecutive vertices. If "shrink" is positive, the convex hull is shrunken
by that amount (each face is moved by "shrink" length units towards the center along its normal).
@@ -86,18 +84,16 @@ class btConvexHullComputer
The output convex hull can be found in the member variables "vertices", "edges", "faces".
*/
- btScalar compute(const float* coords, int stride, int count, btScalar shrink, btScalar shrinkClamp)
- {
- return compute(coords, false, stride, count, shrink, shrinkClamp);
- }
-
- // same as above, but double precision
- btScalar compute(const double* coords, int stride, int count, btScalar shrink, btScalar shrinkClamp)
- {
- return compute(coords, true, stride, count, shrink, shrinkClamp);
- }
+ btScalar compute(const float* coords, int stride, int count, btScalar shrink, btScalar shrinkClamp)
+ {
+ return compute(coords, false, stride, count, shrink, shrinkClamp);
+ }
+
+ // same as above, but double precision
+ btScalar compute(const double* coords, int stride, int count, btScalar shrink, btScalar shrinkClamp)
+ {
+ return compute(coords, true, stride, count, shrink, shrinkClamp);
+ }
};
-
-#endif //BT_CONVEX_HULL_COMPUTER_H
-
+#endif //BT_CONVEX_HULL_COMPUTER_H
diff --git a/thirdparty/bullet/LinearMath/btCpuFeatureUtility.h b/thirdparty/bullet/LinearMath/btCpuFeatureUtility.h
index d2cab52d48..5e4b9a313c 100644
--- a/thirdparty/bullet/LinearMath/btCpuFeatureUtility.h
+++ b/thirdparty/bullet/LinearMath/btCpuFeatureUtility.h
@@ -4,20 +4,20 @@
#include "LinearMath/btScalar.h"
-#include <string.h>//memset
-#ifdef USE_SIMD
+#include <string.h> //memset
+#ifdef USE_SIMD
#include <emmintrin.h>
#ifdef BT_ALLOW_SSE4
#include <intrin.h>
-#endif //BT_ALLOW_SSE4
-#endif //USE_SIMD
+#endif //BT_ALLOW_SSE4
+#endif //USE_SIMD
#if defined BT_USE_NEON
-#define ARM_NEON_GCC_COMPATIBILITY 1
+#define ARM_NEON_GCC_COMPATIBILITY 1
#include <arm_neon.h>
#include <sys/types.h>
-#include <sys/sysctl.h> //for sysctlbyname
-#endif //BT_USE_NEON
+#include <sys/sysctl.h> //for sysctlbyname
+#endif //BT_USE_NEON
///Rudimentary btCpuFeatureUtility for CPU features: only report the features that Bullet actually uses (SSE4/FMA3, NEON_HPFP)
///We assume SSE2 in case BT_USE_SSE2 is defined in LinearMath/btScalar.h
@@ -26,14 +26,13 @@ class btCpuFeatureUtility
public:
enum btCpuFeature
{
- CPU_FEATURE_FMA3=1,
- CPU_FEATURE_SSE4_1=2,
- CPU_FEATURE_NEON_HPFP=4
+ CPU_FEATURE_FMA3 = 1,
+ CPU_FEATURE_SSE4_1 = 2,
+ CPU_FEATURE_NEON_HPFP = 4
};
static int getCpuFeatures()
{
-
static int capabilities = 0;
static bool testedCapabilities = false;
if (0 != testedCapabilities)
@@ -49,15 +48,15 @@ public:
if (0 == err && hasFeature)
capabilities |= CPU_FEATURE_NEON_HPFP;
}
-#endif //BT_USE_NEON
+#endif //BT_USE_NEON
-#ifdef BT_ALLOW_SSE4
+#ifdef BT_ALLOW_SSE4
{
- int cpuInfo[4];
+ int cpuInfo[4];
memset(cpuInfo, 0, sizeof(cpuInfo));
- unsigned long long sseExt = 0;
+ unsigned long long sseExt = 0;
__cpuid(cpuInfo, 1);
-
+
bool osUsesXSAVE_XRSTORE = cpuInfo[2] & (1 << 27) || false;
bool cpuAVXSuport = cpuInfo[2] & (1 << 28) || false;
@@ -79,14 +78,11 @@ public:
capabilities |= btCpuFeatureUtility::CPU_FEATURE_SSE4_1;
}
}
-#endif//BT_ALLOW_SSE4
+#endif //BT_ALLOW_SSE4
testedCapabilities = true;
return capabilities;
}
-
-
};
-
-#endif //BT_CPU_UTILITY_H
+#endif //BT_CPU_UTILITY_H
diff --git a/thirdparty/bullet/LinearMath/btDefaultMotionState.h b/thirdparty/bullet/LinearMath/btDefaultMotionState.h
index 01c5f8d932..14c40d36b0 100644
--- a/thirdparty/bullet/LinearMath/btDefaultMotionState.h
+++ b/thirdparty/bullet/LinearMath/btDefaultMotionState.h
@@ -4,39 +4,37 @@
#include "btMotionState.h"
///The btDefaultMotionState provides a common implementation to synchronize world transforms with offsets.
-ATTRIBUTE_ALIGNED16(struct) btDefaultMotionState : public btMotionState
+ATTRIBUTE_ALIGNED16(struct)
+btDefaultMotionState : public btMotionState
{
btTransform m_graphicsWorldTrans;
- btTransform m_centerOfMassOffset;
+ btTransform m_centerOfMassOffset;
btTransform m_startWorldTrans;
- void* m_userPointer;
+ void* m_userPointer;
BT_DECLARE_ALIGNED_ALLOCATOR();
- btDefaultMotionState(const btTransform& startTrans = btTransform::getIdentity(),const btTransform& centerOfMassOffset = btTransform::getIdentity())
+ btDefaultMotionState(const btTransform& startTrans = btTransform::getIdentity(), const btTransform& centerOfMassOffset = btTransform::getIdentity())
: m_graphicsWorldTrans(startTrans),
- m_centerOfMassOffset(centerOfMassOffset),
- m_startWorldTrans(startTrans),
- m_userPointer(0)
+ m_centerOfMassOffset(centerOfMassOffset),
+ m_startWorldTrans(startTrans),
+ m_userPointer(0)
{
}
///synchronizes world transform from user to physics
- virtual void getWorldTransform(btTransform& centerOfMassWorldTrans ) const
+ virtual void getWorldTransform(btTransform & centerOfMassWorldTrans) const
{
- centerOfMassWorldTrans = m_graphicsWorldTrans * m_centerOfMassOffset.inverse() ;
+ centerOfMassWorldTrans = m_graphicsWorldTrans * m_centerOfMassOffset.inverse();
}
///synchronizes world transform from physics to user
///Bullet only calls the update of worldtransform for active objects
- virtual void setWorldTransform(const btTransform& centerOfMassWorldTrans)
+ virtual void setWorldTransform(const btTransform& centerOfMassWorldTrans)
{
- m_graphicsWorldTrans = centerOfMassWorldTrans * m_centerOfMassOffset;
+ m_graphicsWorldTrans = centerOfMassWorldTrans * m_centerOfMassOffset;
}
-
-
-
};
-#endif //BT_DEFAULT_MOTION_STATE_H
+#endif //BT_DEFAULT_MOTION_STATE_H
diff --git a/thirdparty/bullet/LinearMath/btGeometryUtil.cpp b/thirdparty/bullet/LinearMath/btGeometryUtil.cpp
index 5ac230f712..115e3eab81 100644
--- a/thirdparty/bullet/LinearMath/btGeometryUtil.cpp
+++ b/thirdparty/bullet/LinearMath/btGeometryUtil.cpp
@@ -12,49 +12,43 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
-
#include "btGeometryUtil.h"
-
/*
Make sure this dummy function never changes so that it
can be used by probes that are checking whether the
library is actually installed.
*/
extern "C"
-{
- void btBulletMathProbe ();
+{
+ void btBulletMathProbe();
- void btBulletMathProbe () {}
+ void btBulletMathProbe() {}
}
-
-bool btGeometryUtil::isPointInsidePlanes(const btAlignedObjectArray<btVector3>& planeEquations, const btVector3& point, btScalar margin)
+bool btGeometryUtil::isPointInsidePlanes(const btAlignedObjectArray<btVector3>& planeEquations, const btVector3& point, btScalar margin)
{
int numbrushes = planeEquations.size();
- for (int i=0;i<numbrushes;i++)
+ for (int i = 0; i < numbrushes; i++)
{
const btVector3& N1 = planeEquations[i];
- btScalar dist = btScalar(N1.dot(point))+btScalar(N1[3])-margin;
- if (dist>btScalar(0.))
+ btScalar dist = btScalar(N1.dot(point)) + btScalar(N1[3]) - margin;
+ if (dist > btScalar(0.))
{
return false;
}
}
return true;
-
}
-
-bool btGeometryUtil::areVerticesBehindPlane(const btVector3& planeNormal, const btAlignedObjectArray<btVector3>& vertices, btScalar margin)
+bool btGeometryUtil::areVerticesBehindPlane(const btVector3& planeNormal, const btAlignedObjectArray<btVector3>& vertices, btScalar margin)
{
int numvertices = vertices.size();
- for (int i=0;i<numvertices;i++)
+ for (int i = 0; i < numvertices; i++)
{
const btVector3& N1 = vertices[i];
- btScalar dist = btScalar(planeNormal.dot(N1))+btScalar(planeNormal[3])-margin;
- if (dist>btScalar(0.))
+ btScalar dist = btScalar(planeNormal.dot(N1)) + btScalar(planeNormal[3]) - margin;
+ if (dist > btScalar(0.))
{
return false;
}
@@ -62,102 +56,98 @@ bool btGeometryUtil::areVerticesBehindPlane(const btVector3& planeNormal, const
return true;
}
-bool notExist(const btVector3& planeEquation,const btAlignedObjectArray<btVector3>& planeEquations);
+bool notExist(const btVector3& planeEquation, const btAlignedObjectArray<btVector3>& planeEquations);
-bool notExist(const btVector3& planeEquation,const btAlignedObjectArray<btVector3>& planeEquations)
+bool notExist(const btVector3& planeEquation, const btAlignedObjectArray<btVector3>& planeEquations)
{
int numbrushes = planeEquations.size();
- for (int i=0;i<numbrushes;i++)
+ for (int i = 0; i < numbrushes; i++)
{
const btVector3& N1 = planeEquations[i];
if (planeEquation.dot(N1) > btScalar(0.999))
{
return false;
- }
+ }
}
return true;
}
-void btGeometryUtil::getPlaneEquationsFromVertices(btAlignedObjectArray<btVector3>& vertices, btAlignedObjectArray<btVector3>& planeEquationsOut )
+void btGeometryUtil::getPlaneEquationsFromVertices(btAlignedObjectArray<btVector3>& vertices, btAlignedObjectArray<btVector3>& planeEquationsOut)
{
- const int numvertices = vertices.size();
+ const int numvertices = vertices.size();
// brute force:
- for (int i=0;i<numvertices;i++)
+ for (int i = 0; i < numvertices; i++)
{
const btVector3& N1 = vertices[i];
-
- for (int j=i+1;j<numvertices;j++)
+ for (int j = i + 1; j < numvertices; j++)
{
const btVector3& N2 = vertices[j];
-
- for (int k=j+1;k<numvertices;k++)
- {
+ for (int k = j + 1; k < numvertices; k++)
+ {
const btVector3& N3 = vertices[k];
- btVector3 planeEquation,edge0,edge1;
- edge0 = N2-N1;
- edge1 = N3-N1;
+ btVector3 planeEquation, edge0, edge1;
+ edge0 = N2 - N1;
+ edge1 = N3 - N1;
btScalar normalSign = btScalar(1.);
- for (int ww=0;ww<2;ww++)
+ for (int ww = 0; ww < 2; ww++)
{
planeEquation = normalSign * edge0.cross(edge1);
if (planeEquation.length2() > btScalar(0.0001))
{
planeEquation.normalize();
- if (notExist(planeEquation,planeEquationsOut))
+ if (notExist(planeEquation, planeEquationsOut))
{
planeEquation[3] = -planeEquation.dot(N1);
-
- //check if inside, and replace supportingVertexOut if needed
- if (areVerticesBehindPlane(planeEquation,vertices,btScalar(0.01)))
- {
- planeEquationsOut.push_back(planeEquation);
- }
+
+ //check if inside, and replace supportingVertexOut if needed
+ if (areVerticesBehindPlane(planeEquation, vertices, btScalar(0.01)))
+ {
+ planeEquationsOut.push_back(planeEquation);
+ }
}
}
normalSign = btScalar(-1.);
}
-
}
}
}
-
}
-void btGeometryUtil::getVerticesFromPlaneEquations(const btAlignedObjectArray<btVector3>& planeEquations , btAlignedObjectArray<btVector3>& verticesOut )
+void btGeometryUtil::getVerticesFromPlaneEquations(const btAlignedObjectArray<btVector3>& planeEquations, btAlignedObjectArray<btVector3>& verticesOut)
{
const int numbrushes = planeEquations.size();
// brute force:
- for (int i=0;i<numbrushes;i++)
+ for (int i = 0; i < numbrushes; i++)
{
const btVector3& N1 = planeEquations[i];
-
- for (int j=i+1;j<numbrushes;j++)
+ for (int j = i + 1; j < numbrushes; j++)
{
const btVector3& N2 = planeEquations[j];
-
- for (int k=j+1;k<numbrushes;k++)
- {
+ for (int k = j + 1; k < numbrushes; k++)
+ {
const btVector3& N3 = planeEquations[k];
- btVector3 n2n3; n2n3 = N2.cross(N3);
- btVector3 n3n1; n3n1 = N3.cross(N1);
- btVector3 n1n2; n1n2 = N1.cross(N2);
-
- if ( ( n2n3.length2() > btScalar(0.0001) ) &&
- ( n3n1.length2() > btScalar(0.0001) ) &&
- ( n1n2.length2() > btScalar(0.0001) ) )
+ btVector3 n2n3;
+ n2n3 = N2.cross(N3);
+ btVector3 n3n1;
+ n3n1 = N3.cross(N1);
+ btVector3 n1n2;
+ n1n2 = N1.cross(N2);
+
+ if ((n2n3.length2() > btScalar(0.0001)) &&
+ (n3n1.length2() > btScalar(0.0001)) &&
+ (n1n2.length2() > btScalar(0.0001)))
{
//point P out of 3 plane equations:
- // d1 ( N2 * N3 ) + d2 ( N3 * N1 ) + d3 ( N1 * N2 )
- //P = -------------------------------------------------------------------------
- // N1 . ( N2 * N3 )
-
+ // d1 ( N2 * N3 ) + d2 ( N3 * N1 ) + d3 ( N1 * N2 )
+ //P = -------------------------------------------------------------------------
+ // N1 . ( N2 * N3 )
btScalar quotient = (N1.dot(n2n3));
if (btFabs(quotient) > btScalar(0.000001))
@@ -172,7 +162,7 @@ void btGeometryUtil::getVerticesFromPlaneEquations(const btAlignedObjectArray<bt
potentialVertex *= quotient;
//check if inside, and replace supportingVertexOut if needed
- if (isPointInsidePlanes(planeEquations,potentialVertex,btScalar(0.01)))
+ if (isPointInsidePlanes(planeEquations, potentialVertex, btScalar(0.01)))
{
verticesOut.push_back(potentialVertex);
}
@@ -182,4 +172,3 @@ void btGeometryUtil::getVerticesFromPlaneEquations(const btAlignedObjectArray<bt
}
}
}
-
diff --git a/thirdparty/bullet/LinearMath/btGeometryUtil.h b/thirdparty/bullet/LinearMath/btGeometryUtil.h
index a4b13b4560..0ce5b76d92 100644
--- a/thirdparty/bullet/LinearMath/btGeometryUtil.h
+++ b/thirdparty/bullet/LinearMath/btGeometryUtil.h
@@ -12,7 +12,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#ifndef BT_GEOMETRY_UTIL_H
#define BT_GEOMETRY_UTIL_H
@@ -22,21 +21,16 @@ subject to the following restrictions:
///The btGeometryUtil helper class provides a few methods to convert between plane equations and vertices.
class btGeometryUtil
{
- public:
-
-
- static void getPlaneEquationsFromVertices(btAlignedObjectArray<btVector3>& vertices, btAlignedObjectArray<btVector3>& planeEquationsOut );
-
- static void getVerticesFromPlaneEquations(const btAlignedObjectArray<btVector3>& planeEquations , btAlignedObjectArray<btVector3>& verticesOut );
-
- static bool isInside(const btAlignedObjectArray<btVector3>& vertices, const btVector3& planeNormal, btScalar margin);
-
- static bool isPointInsidePlanes(const btAlignedObjectArray<btVector3>& planeEquations, const btVector3& point, btScalar margin);
+public:
+ static void getPlaneEquationsFromVertices(btAlignedObjectArray<btVector3>& vertices, btAlignedObjectArray<btVector3>& planeEquationsOut);
- static bool areVerticesBehindPlane(const btVector3& planeNormal, const btAlignedObjectArray<btVector3>& vertices, btScalar margin);
+ static void getVerticesFromPlaneEquations(const btAlignedObjectArray<btVector3>& planeEquations, btAlignedObjectArray<btVector3>& verticesOut);
-};
+ static bool isInside(const btAlignedObjectArray<btVector3>& vertices, const btVector3& planeNormal, btScalar margin);
+ static bool isPointInsidePlanes(const btAlignedObjectArray<btVector3>& planeEquations, const btVector3& point, btScalar margin);
-#endif //BT_GEOMETRY_UTIL_H
+ static bool areVerticesBehindPlane(const btVector3& planeNormal, const btAlignedObjectArray<btVector3>& vertices, btScalar margin);
+};
+#endif //BT_GEOMETRY_UTIL_H
diff --git a/thirdparty/bullet/LinearMath/btGrahamScan2dConvexHull.h b/thirdparty/bullet/LinearMath/btGrahamScan2dConvexHull.h
index 13a79aa585..0fcb285971 100644
--- a/thirdparty/bullet/LinearMath/btGrahamScan2dConvexHull.h
+++ b/thirdparty/bullet/LinearMath/btGrahamScan2dConvexHull.h
@@ -13,41 +13,40 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#ifndef GRAHAM_SCAN_2D_CONVEX_HULL_H
#define GRAHAM_SCAN_2D_CONVEX_HULL_H
-
#include "btVector3.h"
#include "btAlignedObjectArray.h"
struct GrahamVector3 : public btVector3
{
GrahamVector3(const btVector3& org, int orgIndex)
- :btVector3(org),
- m_orgIndex(orgIndex)
+ : btVector3(org),
+ m_orgIndex(orgIndex)
{
}
- btScalar m_angle;
+ btScalar m_angle;
int m_orgIndex;
};
-
-struct btAngleCompareFunc {
+struct btAngleCompareFunc
+{
btVector3 m_anchor;
btAngleCompareFunc(const btVector3& anchor)
- : m_anchor(anchor)
+ : m_anchor(anchor)
{
}
- bool operator()(const GrahamVector3& a, const GrahamVector3& b) const {
+ bool operator()(const GrahamVector3& a, const GrahamVector3& b) const
+ {
if (a.m_angle != b.m_angle)
return a.m_angle < b.m_angle;
else
{
- btScalar al = (a-m_anchor).length2();
- btScalar bl = (b-m_anchor).length2();
+ btScalar al = (a - m_anchor).length2();
+ btScalar bl = (b - m_anchor).length2();
if (al != bl)
- return al < bl;
+ return al < bl;
else
{
return a.m_orgIndex < b.m_orgIndex;
@@ -58,73 +57,73 @@ struct btAngleCompareFunc {
inline void GrahamScanConvexHull2D(btAlignedObjectArray<GrahamVector3>& originalPoints, btAlignedObjectArray<GrahamVector3>& hull, const btVector3& normalAxis)
{
- btVector3 axis0,axis1;
- btPlaneSpace1(normalAxis,axis0,axis1);
-
+ btVector3 axis0, axis1;
+ btPlaneSpace1(normalAxis, axis0, axis1);
- if (originalPoints.size()<=1)
+ if (originalPoints.size() <= 1)
{
- for (int i=0;i<originalPoints.size();i++)
+ for (int i = 0; i < originalPoints.size(); i++)
hull.push_back(originalPoints[0]);
return;
}
//step1 : find anchor point with smallest projection on axis0 and move it to first location
- for (int i=0;i<originalPoints.size();i++)
+ for (int i = 0; i < originalPoints.size(); i++)
{
-// const btVector3& left = originalPoints[i];
-// const btVector3& right = originalPoints[0];
+ // const btVector3& left = originalPoints[i];
+ // const btVector3& right = originalPoints[0];
btScalar projL = originalPoints[i].dot(axis0);
btScalar projR = originalPoints[0].dot(axis0);
if (projL < projR)
{
- originalPoints.swap(0,i);
+ originalPoints.swap(0, i);
}
}
//also precompute angles
originalPoints[0].m_angle = -1e30f;
- for (int i=1;i<originalPoints.size();i++)
+ for (int i = 1; i < originalPoints.size(); i++)
{
- btVector3 ar = originalPoints[i]-originalPoints[0];
- btScalar ar1 = axis1.dot(ar);
- btScalar ar0 = axis0.dot(ar);
- if( ar1*ar1+ar0*ar0 < FLT_EPSILON )
- {
- originalPoints[i].m_angle = 0.0f;
- }
- else
- {
- originalPoints[i].m_angle = btAtan2Fast(ar1, ar0);
- }
+ btVector3 ar = originalPoints[i] - originalPoints[0];
+ btScalar ar1 = axis1.dot(ar);
+ btScalar ar0 = axis0.dot(ar);
+ if (ar1 * ar1 + ar0 * ar0 < FLT_EPSILON)
+ {
+ originalPoints[i].m_angle = 0.0f;
+ }
+ else
+ {
+ originalPoints[i].m_angle = btAtan2Fast(ar1, ar0);
+ }
}
//step 2: sort all points, based on 'angle' with this anchor
btAngleCompareFunc comp(originalPoints[0]);
- originalPoints.quickSortInternal(comp,1,originalPoints.size()-1);
+ originalPoints.quickSortInternal(comp, 1, originalPoints.size() - 1);
int i;
- for (i = 0; i<2; i++)
+ for (i = 0; i < 2; i++)
hull.push_back(originalPoints[i]);
//step 3: keep all 'convex' points and discard concave points (using back tracking)
- for (; i != originalPoints.size(); i++)
+ for (; i != originalPoints.size(); i++)
{
bool isConvex = false;
- while (!isConvex&& hull.size()>1) {
- btVector3& a = hull[hull.size()-2];
- btVector3& b = hull[hull.size()-1];
- isConvex = btCross(a-b,a-originalPoints[i]).dot(normalAxis)> 0;
+ while (!isConvex && hull.size() > 1)
+ {
+ btVector3& a = hull[hull.size() - 2];
+ btVector3& b = hull[hull.size() - 1];
+ isConvex = btCross(a - b, a - originalPoints[i]).dot(normalAxis) > 0;
if (!isConvex)
hull.pop_back();
- else
+ else
hull.push_back(originalPoints[i]);
}
- if( hull.size() == 1 )
- {
- hull.push_back( originalPoints[i] );
- }
+ if (hull.size() == 1)
+ {
+ hull.push_back(originalPoints[i]);
+ }
}
}
-#endif //GRAHAM_SCAN_2D_CONVEX_HULL_H
+#endif //GRAHAM_SCAN_2D_CONVEX_HULL_H
diff --git a/thirdparty/bullet/LinearMath/btHashMap.h b/thirdparty/bullet/LinearMath/btHashMap.h
index 180e7b44af..1fca0fb73a 100644
--- a/thirdparty/bullet/LinearMath/btHashMap.h
+++ b/thirdparty/bullet/LinearMath/btHashMap.h
@@ -13,7 +13,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#ifndef BT_HASH_MAP_H
#define BT_HASH_MAP_H
@@ -24,32 +23,32 @@ subject to the following restrictions:
struct btHashString
{
std::string m_string1;
- unsigned int m_hash;
+ unsigned int m_hash;
- SIMD_FORCE_INLINE unsigned int getHash()const
+ SIMD_FORCE_INLINE unsigned int getHash() const
{
return m_hash;
}
btHashString()
{
- m_string1="";
- m_hash=0;
+ m_string1 = "";
+ m_hash = 0;
}
btHashString(const char* name)
- :m_string1(name)
+ : m_string1(name)
{
/* magic numbers from http://www.isthe.com/chongo/tech/comp/fnv/ */
- static const unsigned int InitialFNV = 2166136261u;
+ static const unsigned int InitialFNV = 2166136261u;
static const unsigned int FNVMultiple = 16777619u;
/* Fowler / Noll / Vo (FNV) Hash */
unsigned int hash = InitialFNV;
-
- for(int i = 0; m_string1.c_str()[i]; i++)
+
+ for (int i = 0; m_string1.c_str()[i]; i++)
{
- hash = hash ^ (m_string1.c_str()[i]); /* xor the low 8 bits */
- hash = hash * FNVMultiple; /* multiply by the magic number */
+ hash = hash ^ (m_string1.c_str()[i]); /* xor the low 8 bits */
+ hash = hash * FNVMultiple; /* multiply by the magic number */
}
m_hash = hash;
}
@@ -60,28 +59,27 @@ struct btHashString
}
};
-const int BT_HASH_NULL=0xffffffff;
-
+const int BT_HASH_NULL = 0xffffffff;
class btHashInt
{
- int m_uid;
-public:
+ int m_uid;
+public:
btHashInt()
{
}
- btHashInt(int uid) :m_uid(uid)
+ btHashInt(int uid) : m_uid(uid)
{
}
- int getUid1() const
+ int getUid1() const
{
return m_uid;
}
- void setUid1(int uid)
+ void setUid1(int uid)
{
m_uid = uid;
}
@@ -91,35 +89,35 @@ public:
return getUid1() == other.getUid1();
}
//to our success
- SIMD_FORCE_INLINE unsigned int getHash()const
+ SIMD_FORCE_INLINE unsigned int getHash() const
{
unsigned int key = m_uid;
// Thomas Wang's hash
- key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16);
-
+ key += ~(key << 15);
+ key ^= (key >> 10);
+ key += (key << 3);
+ key ^= (key >> 6);
+ key += ~(key << 11);
+ key ^= (key >> 16);
+
return key;
}
};
-
-
class btHashPtr
{
-
- union
- {
- const void* m_pointer;
- unsigned int m_hashValues[2];
+ union {
+ const void* m_pointer;
+ unsigned int m_hashValues[2];
};
public:
-
btHashPtr(const void* ptr)
- :m_pointer(ptr)
+ : m_pointer(ptr)
{
}
- const void* getPointer() const
+ const void* getPointer() const
{
return m_pointer;
}
@@ -130,64 +128,68 @@ public:
}
//to our success
- SIMD_FORCE_INLINE unsigned int getHash()const
+ SIMD_FORCE_INLINE unsigned int getHash() const
{
- const bool VOID_IS_8 = ((sizeof(void*)==8));
-
- unsigned int key = VOID_IS_8? m_hashValues[0]+m_hashValues[1] : m_hashValues[0];
+ const bool VOID_IS_8 = ((sizeof(void*) == 8));
+
+ unsigned int key = VOID_IS_8 ? m_hashValues[0] + m_hashValues[1] : m_hashValues[0];
// Thomas Wang's hash
- key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16);
+ key += ~(key << 15);
+ key ^= (key >> 10);
+ key += (key << 3);
+ key ^= (key >> 6);
+ key += ~(key << 11);
+ key ^= (key >> 16);
return key;
}
-
-
};
-
template <class Value>
class btHashKeyPtr
{
- int m_uid;
+ int m_uid;
+
public:
+ btHashKeyPtr(int uid) : m_uid(uid)
+ {
+ }
- btHashKeyPtr(int uid) :m_uid(uid)
- {
- }
-
- int getUid1() const
- {
- return m_uid;
- }
-
- bool equals(const btHashKeyPtr<Value>& other) const
- {
- return getUid1() == other.getUid1();
- }
-
- //to our success
- SIMD_FORCE_INLINE unsigned int getHash()const
- {
- unsigned int key = m_uid;
- // Thomas Wang's hash
- key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16);
- return key;
- }
-
-
-};
+ int getUid1() const
+ {
+ return m_uid;
+ }
+
+ bool equals(const btHashKeyPtr<Value>& other) const
+ {
+ return getUid1() == other.getUid1();
+ }
+ //to our success
+ SIMD_FORCE_INLINE unsigned int getHash() const
+ {
+ unsigned int key = m_uid;
+ // Thomas Wang's hash
+ key += ~(key << 15);
+ key ^= (key >> 10);
+ key += (key << 3);
+ key ^= (key >> 6);
+ key += ~(key << 11);
+ key ^= (key >> 16);
+ return key;
+ }
+};
template <class Value>
class btHashKey
{
- int m_uid;
-public:
+ int m_uid;
- btHashKey(int uid) :m_uid(uid)
+public:
+ btHashKey(int uid) : m_uid(uid)
{
}
- int getUid1() const
+ int getUid1() const
{
return m_uid;
}
@@ -197,30 +199,33 @@ public:
return getUid1() == other.getUid1();
}
//to our success
- SIMD_FORCE_INLINE unsigned int getHash()const
+ SIMD_FORCE_INLINE unsigned int getHash() const
{
unsigned int key = m_uid;
// Thomas Wang's hash
- key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16);
+ key += ~(key << 15);
+ key ^= (key >> 10);
+ key += (key << 3);
+ key ^= (key >> 6);
+ key += ~(key << 11);
+ key ^= (key >> 16);
return key;
}
};
-
///The btHashMap template class implements a generic and lightweight hashmap.
///A basic sample of how to use btHashMap is located in Demos\BasicDemo\main.cpp
template <class Key, class Value>
class btHashMap
{
-
protected:
- btAlignedObjectArray<int> m_hashTable;
- btAlignedObjectArray<int> m_next;
-
- btAlignedObjectArray<Value> m_valueArray;
- btAlignedObjectArray<Key> m_keyArray;
+ btAlignedObjectArray<int> m_hashTable;
+ btAlignedObjectArray<int> m_next;
+
+ btAlignedObjectArray<Value> m_valueArray;
+ btAlignedObjectArray<Key> m_keyArray;
- void growTables(const Key& /*key*/)
+ void growTables(const Key& /*key*/)
{
int newCapacity = m_valueArray.capacity();
@@ -234,7 +239,7 @@ protected:
int i;
- for (i= 0; i < newCapacity; ++i)
+ for (i = 0; i < newCapacity; ++i)
{
m_hashTable[i] = BT_HASH_NULL;
}
@@ -243,30 +248,28 @@ protected:
m_next[i] = BT_HASH_NULL;
}
- for(i=0;i<curHashtableSize;i++)
+ for (i = 0; i < curHashtableSize; i++)
{
//const Value& value = m_valueArray[i];
//const Key& key = m_keyArray[i];
- int hashValue = m_keyArray[i].getHash() & (m_valueArray.capacity()-1); // New hash value with new mask
+ int hashValue = m_keyArray[i].getHash() & (m_valueArray.capacity() - 1); // New hash value with new mask
m_next[i] = m_hashTable[hashValue];
m_hashTable[hashValue] = i;
}
-
-
}
}
- public:
-
- void insert(const Key& key, const Value& value) {
- int hash = key.getHash() & (m_valueArray.capacity()-1);
+public:
+ void insert(const Key& key, const Value& value)
+ {
+ int hash = key.getHash() & (m_valueArray.capacity() - 1);
//replace value if the key is already there
int index = findIndex(key);
if (index != BT_HASH_NULL)
{
- m_valueArray[index]=value;
+ m_valueArray[index] = value;
return;
}
@@ -280,19 +283,19 @@ protected:
{
growTables(key);
//hash with new capacity
- hash = key.getHash() & (m_valueArray.capacity()-1);
+ hash = key.getHash() & (m_valueArray.capacity() - 1);
}
m_next[count] = m_hashTable[hash];
m_hashTable[hash] = count;
}
- void remove(const Key& key) {
-
- int hash = key.getHash() & (m_valueArray.capacity()-1);
+ void remove(const Key& key)
+ {
+ int hash = key.getHash() & (m_valueArray.capacity() - 1);
int pairIndex = findIndex(key);
-
- if (pairIndex ==BT_HASH_NULL)
+
+ if (pairIndex == BT_HASH_NULL)
{
return;
}
@@ -333,7 +336,7 @@ protected:
}
// Remove the last pair from the hash table.
- int lastHash = m_keyArray[lastPairIndex].getHash() & (m_valueArray.capacity()-1);
+ int lastHash = m_keyArray[lastPairIndex].getHash() & (m_valueArray.capacity() - 1);
index = m_hashTable[lastHash];
btAssert(index != BT_HASH_NULL);
@@ -365,10 +368,8 @@ protected:
m_valueArray.pop_back();
m_keyArray.pop_back();
-
}
-
int size() const
{
return m_valueArray.size();
@@ -377,8 +378,8 @@ protected:
const Value* getAtIndex(int index) const
{
btAssert(index < m_valueArray.size());
- btAssert(index>=0);
- if (index>=0 && index < m_valueArray.size())
+ btAssert(index >= 0);
+ if (index >= 0 && index < m_valueArray.size())
{
return &m_valueArray[index];
}
@@ -388,38 +389,39 @@ protected:
Value* getAtIndex(int index)
{
btAssert(index < m_valueArray.size());
- btAssert(index>=0);
- if (index>=0 && index < m_valueArray.size())
+ btAssert(index >= 0);
+ if (index >= 0 && index < m_valueArray.size())
{
return &m_valueArray[index];
}
return 0;
}
- Key getKeyAtIndex(int index)
- {
- btAssert(index < m_keyArray.size());
- btAssert(index>=0);
- return m_keyArray[index];
- }
-
- const Key getKeyAtIndex(int index) const
- {
- btAssert(index < m_keyArray.size());
- btAssert(index>=0);
+ Key getKeyAtIndex(int index)
+ {
+ btAssert(index < m_keyArray.size());
+ btAssert(index >= 0);
return m_keyArray[index];
- }
+ }
+ const Key getKeyAtIndex(int index) const
+ {
+ btAssert(index < m_keyArray.size());
+ btAssert(index >= 0);
+ return m_keyArray[index];
+ }
- Value* operator[](const Key& key) {
+ Value* operator[](const Key& key)
+ {
return find(key);
}
- const Value* operator[](const Key& key) const {
+ const Value* operator[](const Key& key) const
+ {
return find(key);
}
- const Value* find(const Key& key) const
+ const Value* find(const Key& key) const
{
int index = findIndex(key);
if (index == BT_HASH_NULL)
@@ -429,7 +431,7 @@ protected:
return &m_valueArray[index];
}
- Value* find(const Key& key)
+ Value* find(const Key& key)
{
int index = findIndex(key);
if (index == BT_HASH_NULL)
@@ -439,10 +441,9 @@ protected:
return &m_valueArray[index];
}
-
- int findIndex(const Key& key) const
+ int findIndex(const Key& key) const
{
- unsigned int hash = key.getHash() & (m_valueArray.capacity()-1);
+ unsigned int hash = key.getHash() & (m_valueArray.capacity() - 1);
if (hash >= (unsigned int)m_hashTable.size())
{
@@ -457,14 +458,13 @@ protected:
return index;
}
- void clear()
+ void clear()
{
m_hashTable.clear();
m_next.clear();
m_valueArray.clear();
m_keyArray.clear();
}
-
};
-#endif //BT_HASH_MAP_H
+#endif //BT_HASH_MAP_H
diff --git a/thirdparty/bullet/LinearMath/btIDebugDraw.h b/thirdparty/bullet/LinearMath/btIDebugDraw.h
index b57282717d..82ec19a69b 100644
--- a/thirdparty/bullet/LinearMath/btIDebugDraw.h
+++ b/thirdparty/bullet/LinearMath/btIDebugDraw.h
@@ -13,86 +13,84 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#ifndef BT_IDEBUG_DRAW__H
#define BT_IDEBUG_DRAW__H
#include "btVector3.h"
#include "btTransform.h"
-
-
///The btIDebugDraw interface class allows hooking up a debug renderer to visually debug simulations.
///Typical use case: create a debug drawer object, and assign it to a btCollisionWorld or btDynamicsWorld using setDebugDrawer and call debugDrawWorld.
///A class that implements the btIDebugDraw interface has to implement the drawLine method at a minimum.
///For color arguments the X,Y,Z components refer to Red, Green and Blue each in the range [0..1]
-class btIDebugDraw
+class btIDebugDraw
{
- public:
-
- ATTRIBUTE_ALIGNED16(struct) DefaultColors
+public:
+ ATTRIBUTE_ALIGNED16(struct)
+ DefaultColors
{
- btVector3 m_activeObject;
- btVector3 m_deactivatedObject;
- btVector3 m_wantsDeactivationObject;
- btVector3 m_disabledDeactivationObject;
- btVector3 m_disabledSimulationObject;
- btVector3 m_aabb;
+ btVector3 m_activeObject;
+ btVector3 m_deactivatedObject;
+ btVector3 m_wantsDeactivationObject;
+ btVector3 m_disabledDeactivationObject;
+ btVector3 m_disabledSimulationObject;
+ btVector3 m_aabb;
btVector3 m_contactPoint;
-
+
DefaultColors()
- : m_activeObject(1,1,1),
- m_deactivatedObject(0,1,0),
- m_wantsDeactivationObject(0,1,1),
- m_disabledDeactivationObject(1,0,0),
- m_disabledSimulationObject(1,1,0),
- m_aabb(1,0,0),
- m_contactPoint(1,1,0)
+ : m_activeObject(1, 1, 1),
+ m_deactivatedObject(0, 1, 0),
+ m_wantsDeactivationObject(0, 1, 1),
+ m_disabledDeactivationObject(1, 0, 0),
+ m_disabledSimulationObject(1, 1, 0),
+ m_aabb(1, 0, 0),
+ m_contactPoint(1, 1, 0)
{
}
};
-
- enum DebugDrawModes
+ enum DebugDrawModes
{
- DBG_NoDebug=0,
+ DBG_NoDebug = 0,
DBG_DrawWireframe = 1,
- DBG_DrawAabb=2,
- DBG_DrawFeaturesText=4,
- DBG_DrawContactPoints=8,
- DBG_NoDeactivation=16,
+ DBG_DrawAabb = 2,
+ DBG_DrawFeaturesText = 4,
+ DBG_DrawContactPoints = 8,
+ DBG_NoDeactivation = 16,
DBG_NoHelpText = 32,
- DBG_DrawText=64,
+ DBG_DrawText = 64,
DBG_ProfileTimings = 128,
DBG_EnableSatComparison = 256,
DBG_DisableBulletLCP = 512,
DBG_EnableCCD = 1024,
DBG_DrawConstraints = (1 << 11),
DBG_DrawConstraintLimits = (1 << 12),
- DBG_FastWireframe = (1<<13),
- DBG_DrawNormals = (1<<14),
- DBG_DrawFrames = (1<<15),
+ DBG_FastWireframe = (1 << 13),
+ DBG_DrawNormals = (1 << 14),
+ DBG_DrawFrames = (1 << 15),
DBG_MAX_DEBUG_DRAW_MODE
};
- virtual ~btIDebugDraw() {};
+ virtual ~btIDebugDraw(){};
-
- virtual DefaultColors getDefaultColors() const { DefaultColors colors; return colors; }
+ virtual DefaultColors getDefaultColors() const
+ {
+ DefaultColors colors;
+ return colors;
+ }
///the default implementation for setDefaultColors has no effect. A derived class can implement it and store the colors.
virtual void setDefaultColors(const DefaultColors& /*colors*/) {}
-
- virtual void drawLine(const btVector3& from,const btVector3& to,const btVector3& color)=0;
-
- virtual void drawLine(const btVector3& from,const btVector3& to, const btVector3& fromColor, const btVector3& toColor)
+
+ virtual void drawLine(const btVector3& from, const btVector3& to, const btVector3& color) = 0;
+
+ virtual void drawLine(const btVector3& from, const btVector3& to, const btVector3& fromColor, const btVector3& toColor)
{
- (void) toColor;
- drawLine (from, to, fromColor);
+ (void)toColor;
+ drawLine(from, to, fromColor);
}
- virtual void drawSphere(btScalar radius, const btTransform& transform, const btVector3& color)
+ virtual void drawSphere(btScalar radius, const btTransform& transform, const btVector3& color)
{
-
btVector3 center = transform.getOrigin();
btVector3 up = transform.getBasis().getColumn(1);
btVector3 axis = transform.getBasis().getColumn(0);
@@ -101,103 +99,102 @@ class btIDebugDraw
btScalar minPs = -SIMD_HALF_PI;
btScalar maxPs = SIMD_HALF_PI;
btScalar stepDegrees = 30.f;
- drawSpherePatch(center, up, axis, radius,minTh, maxTh, minPs, maxPs, color, stepDegrees ,false);
- drawSpherePatch(center, up, -axis, radius,minTh, maxTh, minPs, maxPs, color, stepDegrees,false );
+ drawSpherePatch(center, up, axis, radius, minTh, maxTh, minPs, maxPs, color, stepDegrees, false);
+ drawSpherePatch(center, up, -axis, radius, minTh, maxTh, minPs, maxPs, color, stepDegrees, false);
}
-
- virtual void drawSphere (const btVector3& p, btScalar radius, const btVector3& color)
+
+ virtual void drawSphere(const btVector3& p, btScalar radius, const btVector3& color)
{
btTransform tr;
tr.setIdentity();
tr.setOrigin(p);
- drawSphere(radius,tr,color);
+ drawSphere(radius, tr, color);
}
-
- virtual void drawTriangle(const btVector3& v0,const btVector3& v1,const btVector3& v2,const btVector3& /*n0*/,const btVector3& /*n1*/,const btVector3& /*n2*/,const btVector3& color, btScalar alpha)
+
+ virtual void drawTriangle(const btVector3& v0, const btVector3& v1, const btVector3& v2, const btVector3& /*n0*/, const btVector3& /*n1*/, const btVector3& /*n2*/, const btVector3& color, btScalar alpha)
{
- drawTriangle(v0,v1,v2,color,alpha);
+ drawTriangle(v0, v1, v2, color, alpha);
}
- virtual void drawTriangle(const btVector3& v0,const btVector3& v1,const btVector3& v2,const btVector3& color, btScalar /*alpha*/)
+ virtual void drawTriangle(const btVector3& v0, const btVector3& v1, const btVector3& v2, const btVector3& color, btScalar /*alpha*/)
{
- drawLine(v0,v1,color);
- drawLine(v1,v2,color);
- drawLine(v2,v0,color);
+ drawLine(v0, v1, color);
+ drawLine(v1, v2, color);
+ drawLine(v2, v0, color);
}
- virtual void drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,btScalar distance,int lifeTime,const btVector3& color)=0;
+ virtual void drawContactPoint(const btVector3& PointOnB, const btVector3& normalOnB, btScalar distance, int lifeTime, const btVector3& color) = 0;
- virtual void reportErrorWarning(const char* warningString) = 0;
+ virtual void reportErrorWarning(const char* warningString) = 0;
- virtual void draw3dText(const btVector3& location,const char* textString) = 0;
-
- virtual void setDebugMode(int debugMode) =0;
-
- virtual int getDebugMode() const = 0;
+ virtual void draw3dText(const btVector3& location, const char* textString) = 0;
- virtual void drawAabb(const btVector3& from,const btVector3& to,const btVector3& color)
- {
+ virtual void setDebugMode(int debugMode) = 0;
+
+ virtual int getDebugMode() const = 0;
- btVector3 halfExtents = (to-from)* 0.5f;
- btVector3 center = (to+from) *0.5f;
- int i,j;
+ virtual void drawAabb(const btVector3& from, const btVector3& to, const btVector3& color)
+ {
+ btVector3 halfExtents = (to - from) * 0.5f;
+ btVector3 center = (to + from) * 0.5f;
+ int i, j;
- btVector3 edgecoord(1.f,1.f,1.f),pa,pb;
- for (i=0;i<4;i++)
+ btVector3 edgecoord(1.f, 1.f, 1.f), pa, pb;
+ for (i = 0; i < 4; i++)
{
- for (j=0;j<3;j++)
+ for (j = 0; j < 3; j++)
{
- pa = btVector3(edgecoord[0]*halfExtents[0], edgecoord[1]*halfExtents[1],
- edgecoord[2]*halfExtents[2]);
- pa+=center;
+ pa = btVector3(edgecoord[0] * halfExtents[0], edgecoord[1] * halfExtents[1],
+ edgecoord[2] * halfExtents[2]);
+ pa += center;
- int othercoord = j%3;
- edgecoord[othercoord]*=-1.f;
- pb = btVector3(edgecoord[0]*halfExtents[0], edgecoord[1]*halfExtents[1],
- edgecoord[2]*halfExtents[2]);
- pb+=center;
+ int othercoord = j % 3;
+ edgecoord[othercoord] *= -1.f;
+ pb = btVector3(edgecoord[0] * halfExtents[0], edgecoord[1] * halfExtents[1],
+ edgecoord[2] * halfExtents[2]);
+ pb += center;
- drawLine(pa,pb,color);
+ drawLine(pa, pb, color);
}
- edgecoord = btVector3(-1.f,-1.f,-1.f);
- if (i<3)
- edgecoord[i]*=-1.f;
+ edgecoord = btVector3(-1.f, -1.f, -1.f);
+ if (i < 3)
+ edgecoord[i] *= -1.f;
}
}
virtual void drawTransform(const btTransform& transform, btScalar orthoLen)
{
btVector3 start = transform.getOrigin();
- drawLine(start, start+transform.getBasis() * btVector3(orthoLen, 0, 0), btVector3(btScalar(1.), btScalar(0.3), btScalar(0.3)));
- drawLine(start, start+transform.getBasis() * btVector3(0, orthoLen, 0), btVector3(btScalar(0.3), btScalar(1.), btScalar(0.3)));
- drawLine(start, start+transform.getBasis() * btVector3(0, 0, orthoLen), btVector3(btScalar(0.3), btScalar(0.3), btScalar(1.)));
+ drawLine(start, start + transform.getBasis() * btVector3(orthoLen, 0, 0), btVector3(btScalar(1.), btScalar(0.3), btScalar(0.3)));
+ drawLine(start, start + transform.getBasis() * btVector3(0, orthoLen, 0), btVector3(btScalar(0.3), btScalar(1.), btScalar(0.3)));
+ drawLine(start, start + transform.getBasis() * btVector3(0, 0, orthoLen), btVector3(btScalar(0.3), btScalar(0.3), btScalar(1.)));
}
- virtual void drawArc(const btVector3& center, const btVector3& normal, const btVector3& axis, btScalar radiusA, btScalar radiusB, btScalar minAngle, btScalar maxAngle,
- const btVector3& color, bool drawSect, btScalar stepDegrees = btScalar(10.f))
+ virtual void drawArc(const btVector3& center, const btVector3& normal, const btVector3& axis, btScalar radiusA, btScalar radiusB, btScalar minAngle, btScalar maxAngle,
+ const btVector3& color, bool drawSect, btScalar stepDegrees = btScalar(10.f))
{
const btVector3& vx = axis;
btVector3 vy = normal.cross(axis);
btScalar step = stepDegrees * SIMD_RADS_PER_DEG;
int nSteps = (int)btFabs((maxAngle - minAngle) / step);
- if(!nSteps) nSteps = 1;
+ if (!nSteps) nSteps = 1;
btVector3 prev = center + radiusA * vx * btCos(minAngle) + radiusB * vy * btSin(minAngle);
- if(drawSect)
+ if (drawSect)
{
drawLine(center, prev, color);
}
- for(int i = 1; i <= nSteps; i++)
+ for (int i = 1; i <= nSteps; i++)
{
btScalar angle = minAngle + (maxAngle - minAngle) * btScalar(i) / btScalar(nSteps);
btVector3 next = center + radiusA * vx * btCos(angle) + radiusB * vy * btSin(angle);
drawLine(prev, next, color);
prev = next;
}
- if(drawSect)
+ if (drawSect)
{
drawLine(center, prev, color);
}
}
- virtual void drawSpherePatch(const btVector3& center, const btVector3& up, const btVector3& axis, btScalar radius,
- btScalar minTh, btScalar maxTh, btScalar minPs, btScalar maxPs, const btVector3& color, btScalar stepDegrees = btScalar(10.f),bool drawCenter = true)
+ virtual void drawSpherePatch(const btVector3& center, const btVector3& up, const btVector3& axis, btScalar radius,
+ btScalar minTh, btScalar maxTh, btScalar minPs, btScalar maxPs, const btVector3& color, btScalar stepDegrees = btScalar(10.f), bool drawCenter = true)
{
btVector3 vA[74];
btVector3 vB[74];
@@ -211,33 +208,33 @@ class btIDebugDraw
btVector3 jv = kv.cross(iv);
bool drawN = false;
bool drawS = false;
- if(minTh <= -SIMD_HALF_PI)
+ if (minTh <= -SIMD_HALF_PI)
{
minTh = -SIMD_HALF_PI + step;
drawN = true;
}
- if(maxTh >= SIMD_HALF_PI)
+ if (maxTh >= SIMD_HALF_PI)
{
maxTh = SIMD_HALF_PI - step;
drawS = true;
}
- if(minTh > maxTh)
+ if (minTh > maxTh)
{
minTh = -SIMD_HALF_PI + step;
- maxTh = SIMD_HALF_PI - step;
+ maxTh = SIMD_HALF_PI - step;
drawN = drawS = true;
}
int n_hor = (int)((maxTh - minTh) / step) + 1;
- if(n_hor < 2) n_hor = 2;
+ if (n_hor < 2) n_hor = 2;
btScalar step_h = (maxTh - minTh) / btScalar(n_hor - 1);
bool isClosed = false;
- if(minPs > maxPs)
+ if (minPs > maxPs)
{
minPs = -SIMD_PI + step;
- maxPs = SIMD_PI;
+ maxPs = SIMD_PI;
isClosed = true;
}
- else if((maxPs - minPs) >= SIMD_PI * btScalar(2.f))
+ else if ((maxPs - minPs) >= SIMD_PI * btScalar(2.f))
{
isClosed = true;
}
@@ -246,63 +243,64 @@ class btIDebugDraw
isClosed = false;
}
int n_vert = (int)((maxPs - minPs) / step) + 1;
- if(n_vert < 2) n_vert = 2;
+ if (n_vert < 2) n_vert = 2;
btScalar step_v = (maxPs - minPs) / btScalar(n_vert - 1);
- for(int i = 0; i < n_hor; i++)
+ for (int i = 0; i < n_hor; i++)
{
btScalar th = minTh + btScalar(i) * step_h;
btScalar sth = radius * btSin(th);
btScalar cth = radius * btCos(th);
- for(int j = 0; j < n_vert; j++)
+ for (int j = 0; j < n_vert; j++)
{
btScalar psi = minPs + btScalar(j) * step_v;
btScalar sps = btSin(psi);
btScalar cps = btCos(psi);
pvB[j] = center + cth * cps * iv + cth * sps * jv + sth * kv;
- if(i)
+ if (i)
{
drawLine(pvA[j], pvB[j], color);
}
- else if(drawS)
+ else if (drawS)
{
drawLine(spole, pvB[j], color);
}
- if(j)
+ if (j)
{
- drawLine(pvB[j-1], pvB[j], color);
+ drawLine(pvB[j - 1], pvB[j], color);
}
else
{
arcStart = pvB[j];
}
- if((i == (n_hor - 1)) && drawN)
+ if ((i == (n_hor - 1)) && drawN)
{
drawLine(npole, pvB[j], color);
}
-
+
if (drawCenter)
{
- if(isClosed)
+ if (isClosed)
{
- if(j == (n_vert-1))
+ if (j == (n_vert - 1))
{
drawLine(arcStart, pvB[j], color);
}
}
else
{
- if(((!i) || (i == (n_hor-1))) && ((!j) || (j == (n_vert-1))))
+ if (((!i) || (i == (n_hor - 1))) && ((!j) || (j == (n_vert - 1))))
{
drawLine(center, pvB[j], color);
}
}
}
}
- pT = pvA; pvA = pvB; pvB = pT;
+ pT = pvA;
+ pvA = pvB;
+ pvB = pT;
}
}
-
-
+
virtual void drawBox(const btVector3& bbMin, const btVector3& bbMax, const btVector3& color)
{
drawLine(btVector3(bbMin[0], bbMin[1], bbMin[2]), btVector3(bbMax[0], bbMin[1], bbMin[2]), color);
@@ -338,31 +336,27 @@ class btIDebugDraw
{
int stepDegrees = 30;
- btVector3 capStart(0.f,0.f,0.f);
+ btVector3 capStart(0.f, 0.f, 0.f);
capStart[upAxis] = -halfHeight;
- btVector3 capEnd(0.f,0.f,0.f);
+ btVector3 capEnd(0.f, 0.f, 0.f);
capEnd[upAxis] = halfHeight;
// Draw the ends
{
-
btTransform childTransform = transform;
childTransform.getOrigin() = transform * capStart;
{
btVector3 center = childTransform.getOrigin();
- btVector3 up = childTransform.getBasis().getColumn((upAxis+1)%3);
+ btVector3 up = childTransform.getBasis().getColumn((upAxis + 1) % 3);
btVector3 axis = -childTransform.getBasis().getColumn(upAxis);
btScalar minTh = -SIMD_HALF_PI;
btScalar maxTh = SIMD_HALF_PI;
btScalar minPs = -SIMD_HALF_PI;
btScalar maxPs = SIMD_HALF_PI;
-
- drawSpherePatch(center, up, axis, radius,minTh, maxTh, minPs, maxPs, color, btScalar(stepDegrees) ,false);
- }
-
-
+ drawSpherePatch(center, up, axis, radius, minTh, maxTh, minPs, maxPs, color, btScalar(stepDegrees), false);
+ }
}
{
@@ -370,52 +364,51 @@ class btIDebugDraw
childTransform.getOrigin() = transform * capEnd;
{
btVector3 center = childTransform.getOrigin();
- btVector3 up = childTransform.getBasis().getColumn((upAxis+1)%3);
+ btVector3 up = childTransform.getBasis().getColumn((upAxis + 1) % 3);
btVector3 axis = childTransform.getBasis().getColumn(upAxis);
btScalar minTh = -SIMD_HALF_PI;
btScalar maxTh = SIMD_HALF_PI;
btScalar minPs = -SIMD_HALF_PI;
btScalar maxPs = SIMD_HALF_PI;
- drawSpherePatch(center, up, axis, radius,minTh, maxTh, minPs, maxPs, color, btScalar(stepDegrees) ,false);
+ drawSpherePatch(center, up, axis, radius, minTh, maxTh, minPs, maxPs, color, btScalar(stepDegrees), false);
}
}
// Draw some additional lines
btVector3 start = transform.getOrigin();
- for (int i=0;i<360;i+=stepDegrees)
+ for (int i = 0; i < 360; i += stepDegrees)
{
- capEnd[(upAxis+1)%3] = capStart[(upAxis+1)%3] = btSin(btScalar(i)*SIMD_RADS_PER_DEG)*radius;
- capEnd[(upAxis+2)%3] = capStart[(upAxis+2)%3] = btCos(btScalar(i)*SIMD_RADS_PER_DEG)*radius;
- drawLine(start+transform.getBasis() * capStart,start+transform.getBasis() * capEnd, color);
+ capEnd[(upAxis + 1) % 3] = capStart[(upAxis + 1) % 3] = btSin(btScalar(i) * SIMD_RADS_PER_DEG) * radius;
+ capEnd[(upAxis + 2) % 3] = capStart[(upAxis + 2) % 3] = btCos(btScalar(i) * SIMD_RADS_PER_DEG) * radius;
+ drawLine(start + transform.getBasis() * capStart, start + transform.getBasis() * capEnd, color);
}
-
}
virtual void drawCylinder(btScalar radius, btScalar halfHeight, int upAxis, const btTransform& transform, const btVector3& color)
{
btVector3 start = transform.getOrigin();
- btVector3 offsetHeight(0,0,0);
+ btVector3 offsetHeight(0, 0, 0);
offsetHeight[upAxis] = halfHeight;
- int stepDegrees=30;
- btVector3 capStart(0.f,0.f,0.f);
+ int stepDegrees = 30;
+ btVector3 capStart(0.f, 0.f, 0.f);
capStart[upAxis] = -halfHeight;
- btVector3 capEnd(0.f,0.f,0.f);
+ btVector3 capEnd(0.f, 0.f, 0.f);
capEnd[upAxis] = halfHeight;
- for (int i=0;i<360;i+=stepDegrees)
+ for (int i = 0; i < 360; i += stepDegrees)
{
- capEnd[(upAxis+1)%3] = capStart[(upAxis+1)%3] = btSin(btScalar(i)*SIMD_RADS_PER_DEG)*radius;
- capEnd[(upAxis+2)%3] = capStart[(upAxis+2)%3] = btCos(btScalar(i)*SIMD_RADS_PER_DEG)*radius;
- drawLine(start+transform.getBasis() * capStart,start+transform.getBasis() * capEnd, color);
+ capEnd[(upAxis + 1) % 3] = capStart[(upAxis + 1) % 3] = btSin(btScalar(i) * SIMD_RADS_PER_DEG) * radius;
+ capEnd[(upAxis + 2) % 3] = capStart[(upAxis + 2) % 3] = btCos(btScalar(i) * SIMD_RADS_PER_DEG) * radius;
+ drawLine(start + transform.getBasis() * capStart, start + transform.getBasis() * capEnd, color);
}
// Drawing top and bottom caps of the cylinder
- btVector3 yaxis(0,0,0);
+ btVector3 yaxis(0, 0, 0);
yaxis[upAxis] = btScalar(1.0);
- btVector3 xaxis(0,0,0);
- xaxis[(upAxis+1)%3] = btScalar(1.0);
- drawArc(start-transform.getBasis()*(offsetHeight),transform.getBasis()*yaxis,transform.getBasis()*xaxis,radius,radius,0,SIMD_2_PI,color,false,btScalar(10.0));
- drawArc(start+transform.getBasis()*(offsetHeight),transform.getBasis()*yaxis,transform.getBasis()*xaxis,radius,radius,0,SIMD_2_PI,color,false,btScalar(10.0));
+ btVector3 xaxis(0, 0, 0);
+ xaxis[(upAxis + 1) % 3] = btScalar(1.0);
+ drawArc(start - transform.getBasis() * (offsetHeight), transform.getBasis() * yaxis, transform.getBasis() * xaxis, radius, radius, 0, SIMD_2_PI, color, false, btScalar(10.0));
+ drawArc(start + transform.getBasis() * (offsetHeight), transform.getBasis() * yaxis, transform.getBasis() * xaxis, radius, radius, 0, SIMD_2_PI, color, false, btScalar(10.0));
}
virtual void drawCone(btScalar radius, btScalar height, int upAxis, const btTransform& transform, const btVector3& color)
@@ -423,50 +416,49 @@ class btIDebugDraw
int stepDegrees = 30;
btVector3 start = transform.getOrigin();
- btVector3 offsetHeight(0,0,0);
+ btVector3 offsetHeight(0, 0, 0);
btScalar halfHeight = height * btScalar(0.5);
offsetHeight[upAxis] = halfHeight;
- btVector3 offsetRadius(0,0,0);
- offsetRadius[(upAxis+1)%3] = radius;
- btVector3 offset2Radius(0,0,0);
- offset2Radius[(upAxis+2)%3] = radius;
+ btVector3 offsetRadius(0, 0, 0);
+ offsetRadius[(upAxis + 1) % 3] = radius;
+ btVector3 offset2Radius(0, 0, 0);
+ offset2Radius[(upAxis + 2) % 3] = radius;
-
- btVector3 capEnd(0.f,0.f,0.f);
+ btVector3 capEnd(0.f, 0.f, 0.f);
capEnd[upAxis] = -halfHeight;
- for (int i=0;i<360;i+=stepDegrees)
+ for (int i = 0; i < 360; i += stepDegrees)
{
- capEnd[(upAxis+1)%3] = btSin(btScalar(i)*SIMD_RADS_PER_DEG)*radius;
- capEnd[(upAxis+2)%3] = btCos(btScalar(i)*SIMD_RADS_PER_DEG)*radius;
- drawLine(start+transform.getBasis() * (offsetHeight),start+transform.getBasis() * capEnd, color);
+ capEnd[(upAxis + 1) % 3] = btSin(btScalar(i) * SIMD_RADS_PER_DEG) * radius;
+ capEnd[(upAxis + 2) % 3] = btCos(btScalar(i) * SIMD_RADS_PER_DEG) * radius;
+ drawLine(start + transform.getBasis() * (offsetHeight), start + transform.getBasis() * capEnd, color);
}
- drawLine(start+transform.getBasis() * (offsetHeight),start+transform.getBasis() * (-offsetHeight+offsetRadius),color);
- drawLine(start+transform.getBasis() * (offsetHeight),start+transform.getBasis() * (-offsetHeight-offsetRadius),color);
- drawLine(start+transform.getBasis() * (offsetHeight),start+transform.getBasis() * (-offsetHeight+offset2Radius),color);
- drawLine(start+transform.getBasis() * (offsetHeight),start+transform.getBasis() * (-offsetHeight-offset2Radius),color);
+ drawLine(start + transform.getBasis() * (offsetHeight), start + transform.getBasis() * (-offsetHeight + offsetRadius), color);
+ drawLine(start + transform.getBasis() * (offsetHeight), start + transform.getBasis() * (-offsetHeight - offsetRadius), color);
+ drawLine(start + transform.getBasis() * (offsetHeight), start + transform.getBasis() * (-offsetHeight + offset2Radius), color);
+ drawLine(start + transform.getBasis() * (offsetHeight), start + transform.getBasis() * (-offsetHeight - offset2Radius), color);
// Drawing the base of the cone
- btVector3 yaxis(0,0,0);
+ btVector3 yaxis(0, 0, 0);
yaxis[upAxis] = btScalar(1.0);
- btVector3 xaxis(0,0,0);
- xaxis[(upAxis+1)%3] = btScalar(1.0);
- drawArc(start-transform.getBasis()*(offsetHeight),transform.getBasis()*yaxis,transform.getBasis()*xaxis,radius,radius,0,SIMD_2_PI,color,false,10.0);
+ btVector3 xaxis(0, 0, 0);
+ xaxis[(upAxis + 1) % 3] = btScalar(1.0);
+ drawArc(start - transform.getBasis() * (offsetHeight), transform.getBasis() * yaxis, transform.getBasis() * xaxis, radius, radius, 0, SIMD_2_PI, color, false, 10.0);
}
virtual void drawPlane(const btVector3& planeNormal, btScalar planeConst, const btTransform& transform, const btVector3& color)
{
btVector3 planeOrigin = planeNormal * planeConst;
- btVector3 vec0,vec1;
- btPlaneSpace1(planeNormal,vec0,vec1);
+ btVector3 vec0, vec1;
+ btPlaneSpace1(planeNormal, vec0, vec1);
btScalar vecLen = 100.f;
- btVector3 pt0 = planeOrigin + vec0*vecLen;
- btVector3 pt1 = planeOrigin - vec0*vecLen;
- btVector3 pt2 = planeOrigin + vec1*vecLen;
- btVector3 pt3 = planeOrigin - vec1*vecLen;
- drawLine(transform*pt0,transform*pt1,color);
- drawLine(transform*pt2,transform*pt3,color);
+ btVector3 pt0 = planeOrigin + vec0 * vecLen;
+ btVector3 pt1 = planeOrigin - vec0 * vecLen;
+ btVector3 pt2 = planeOrigin + vec1 * vecLen;
+ btVector3 pt3 = planeOrigin - vec1 * vecLen;
+ drawLine(transform * pt0, transform * pt1, color);
+ drawLine(transform * pt2, transform * pt3, color);
}
virtual void clearLines()
@@ -478,6 +470,4 @@ class btIDebugDraw
}
};
-
-#endif //BT_IDEBUG_DRAW__H
-
+#endif //BT_IDEBUG_DRAW__H
diff --git a/thirdparty/bullet/LinearMath/btList.h b/thirdparty/bullet/LinearMath/btList.h
index eec80a7064..b255938c30 100644
--- a/thirdparty/bullet/LinearMath/btList.h
+++ b/thirdparty/bullet/LinearMath/btList.h
@@ -12,62 +12,62 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
-
#ifndef BT_GEN_LIST_H
#define BT_GEN_LIST_H
-class btGEN_Link {
+class btGEN_Link
+{
public:
- btGEN_Link() : m_next(0), m_prev(0) {}
- btGEN_Link(btGEN_Link *next, btGEN_Link *prev) : m_next(next), m_prev(prev) {}
-
- btGEN_Link *getNext() const { return m_next; }
- btGEN_Link *getPrev() const { return m_prev; }
-
- bool isHead() const { return m_prev == 0; }
- bool isTail() const { return m_next == 0; }
-
- void insertBefore(btGEN_Link *link) {
- m_next = link;
- m_prev = link->m_prev;
- m_next->m_prev = this;
- m_prev->m_next = this;
- }
-
- void insertAfter(btGEN_Link *link) {
- m_next = link->m_next;
- m_prev = link;
- m_next->m_prev = this;
- m_prev->m_next = this;
- }
-
- void remove() {
- m_next->m_prev = m_prev;
- m_prev->m_next = m_next;
- }
+ btGEN_Link() : m_next(0), m_prev(0) {}
+ btGEN_Link(btGEN_Link *next, btGEN_Link *prev) : m_next(next), m_prev(prev) {}
+
+ btGEN_Link *getNext() const { return m_next; }
+ btGEN_Link *getPrev() const { return m_prev; }
+
+ bool isHead() const { return m_prev == 0; }
+ bool isTail() const { return m_next == 0; }
+
+ void insertBefore(btGEN_Link *link)
+ {
+ m_next = link;
+ m_prev = link->m_prev;
+ m_next->m_prev = this;
+ m_prev->m_next = this;
+ }
+
+ void insertAfter(btGEN_Link *link)
+ {
+ m_next = link->m_next;
+ m_prev = link;
+ m_next->m_prev = this;
+ m_prev->m_next = this;
+ }
+
+ void remove()
+ {
+ m_next->m_prev = m_prev;
+ m_prev->m_next = m_next;
+ }
-private:
- btGEN_Link *m_next;
- btGEN_Link *m_prev;
+private:
+ btGEN_Link *m_next;
+ btGEN_Link *m_prev;
};
-class btGEN_List {
+class btGEN_List
+{
public:
- btGEN_List() : m_head(&m_tail, 0), m_tail(0, &m_head) {}
+ btGEN_List() : m_head(&m_tail, 0), m_tail(0, &m_head) {}
+
+ btGEN_Link *getHead() const { return m_head.getNext(); }
+ btGEN_Link *getTail() const { return m_tail.getPrev(); }
- btGEN_Link *getHead() const { return m_head.getNext(); }
- btGEN_Link *getTail() const { return m_tail.getPrev(); }
+ void addHead(btGEN_Link *link) { link->insertAfter(&m_head); }
+ void addTail(btGEN_Link *link) { link->insertBefore(&m_tail); }
- void addHead(btGEN_Link *link) { link->insertAfter(&m_head); }
- void addTail(btGEN_Link *link) { link->insertBefore(&m_tail); }
-
private:
- btGEN_Link m_head;
- btGEN_Link m_tail;
+ btGEN_Link m_head;
+ btGEN_Link m_tail;
};
-#endif //BT_GEN_LIST_H
-
-
-
+#endif //BT_GEN_LIST_H
diff --git a/thirdparty/bullet/LinearMath/btMatrix3x3.h b/thirdparty/bullet/LinearMath/btMatrix3x3.h
index 6cc4993da5..0a08ae409a 100644
--- a/thirdparty/bullet/LinearMath/btMatrix3x3.h
+++ b/thirdparty/bullet/LinearMath/btMatrix3x3.h
@@ -12,8 +12,7 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
-#ifndef BT_MATRIX3x3_H
+#ifndef BT_MATRIX3x3_H
#define BT_MATRIX3x3_H
#include "btVector3.h"
@@ -23,13 +22,13 @@ subject to the following restrictions:
#ifdef BT_USE_SSE
//const __m128 ATTRIBUTE_ALIGNED16(v2220) = {2.0f, 2.0f, 2.0f, 0.0f};
//const __m128 ATTRIBUTE_ALIGNED16(vMPPP) = {-0.0f, +0.0f, +0.0f, +0.0f};
-#define vMPPP (_mm_set_ps (+0.0f, +0.0f, +0.0f, -0.0f))
+#define vMPPP (_mm_set_ps(+0.0f, +0.0f, +0.0f, -0.0f))
#endif
#if defined(BT_USE_SSE)
-#define v1000 (_mm_set_ps(0.0f,0.0f,0.0f,1.0f))
-#define v0100 (_mm_set_ps(0.0f,0.0f,1.0f,0.0f))
-#define v0010 (_mm_set_ps(0.0f,1.0f,0.0f,0.0f))
+#define v1000 (_mm_set_ps(0.0f, 0.0f, 0.0f, 1.0f))
+#define v0100 (_mm_set_ps(0.0f, 0.0f, 1.0f, 0.0f))
+#define v0010 (_mm_set_ps(0.0f, 1.0f, 0.0f, 0.0f))
#elif defined(BT_USE_NEON)
const btSimdFloat4 ATTRIBUTE_ALIGNED16(v1000) = {1.0f, 0.0f, 0.0f, 0.0f};
const btSimdFloat4 ATTRIBUTE_ALIGNED16(v0100) = {0.0f, 1.0f, 0.0f, 0.0f};
@@ -37,22 +36,22 @@ const btSimdFloat4 ATTRIBUTE_ALIGNED16(v0010) = {0.0f, 0.0f, 1.0f, 0.0f};
#endif
#ifdef BT_USE_DOUBLE_PRECISION
-#define btMatrix3x3Data btMatrix3x3DoubleData
+#define btMatrix3x3Data btMatrix3x3DoubleData
#else
-#define btMatrix3x3Data btMatrix3x3FloatData
-#endif //BT_USE_DOUBLE_PRECISION
-
+#define btMatrix3x3Data btMatrix3x3FloatData
+#endif //BT_USE_DOUBLE_PRECISION
/**@brief The btMatrix3x3 class implements a 3x3 rotation matrix, to perform linear algebra in combination with btQuaternion, btTransform and btVector3.
* Make sure to only include a pure orthogonal matrix without scaling. */
-ATTRIBUTE_ALIGNED16(class) btMatrix3x3 {
-
+ATTRIBUTE_ALIGNED16(class)
+btMatrix3x3
+{
///Data storage for the matrix, each vector is a row of the matrix
btVector3 m_el[3];
public:
/** @brief No initializaion constructor */
- btMatrix3x3 () {}
+ btMatrix3x3() {}
// explicit btMatrix3x3(const btScalar *m) { setFromOpenGLSubMatrix(m); }
@@ -67,27 +66,27 @@ public:
*/
/** @brief Constructor with row major formatting */
btMatrix3x3(const btScalar& xx, const btScalar& xy, const btScalar& xz,
- const btScalar& yx, const btScalar& yy, const btScalar& yz,
- const btScalar& zx, const btScalar& zy, const btScalar& zz)
- {
- setValue(xx, xy, xz,
- yx, yy, yz,
- zx, zy, zz);
+ const btScalar& yx, const btScalar& yy, const btScalar& yz,
+ const btScalar& zx, const btScalar& zy, const btScalar& zz)
+ {
+ setValue(xx, xy, xz,
+ yx, yy, yz,
+ zx, zy, zz);
}
-#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))|| defined (BT_USE_NEON)
- SIMD_FORCE_INLINE btMatrix3x3 (const btSimdFloat4 v0, const btSimdFloat4 v1, const btSimdFloat4 v2 )
+#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
+ SIMD_FORCE_INLINE btMatrix3x3(const btSimdFloat4 v0, const btSimdFloat4 v1, const btSimdFloat4 v2)
{
- m_el[0].mVec128 = v0;
- m_el[1].mVec128 = v1;
- m_el[2].mVec128 = v2;
+ m_el[0].mVec128 = v0;
+ m_el[1].mVec128 = v1;
+ m_el[2].mVec128 = v2;
}
- SIMD_FORCE_INLINE btMatrix3x3 (const btVector3& v0, const btVector3& v1, const btVector3& v2 )
+ SIMD_FORCE_INLINE btMatrix3x3(const btVector3& v0, const btVector3& v1, const btVector3& v2)
{
- m_el[0] = v0;
- m_el[1] = v1;
- m_el[2] = v2;
+ m_el[0] = v0;
+ m_el[1] = v1;
+ m_el[2] = v2;
}
// Copy constructor
@@ -99,25 +98,25 @@ public:
}
// Assignment Operator
- SIMD_FORCE_INLINE btMatrix3x3& operator=(const btMatrix3x3& m)
+ SIMD_FORCE_INLINE btMatrix3x3& operator=(const btMatrix3x3& m)
{
m_el[0].mVec128 = m.m_el[0].mVec128;
m_el[1].mVec128 = m.m_el[1].mVec128;
m_el[2].mVec128 = m.m_el[2].mVec128;
-
+
return *this;
}
#else
/** @brief Copy constructor */
- SIMD_FORCE_INLINE btMatrix3x3 (const btMatrix3x3& other)
+ SIMD_FORCE_INLINE btMatrix3x3(const btMatrix3x3& other)
{
m_el[0] = other.m_el[0];
m_el[1] = other.m_el[1];
m_el[2] = other.m_el[2];
}
-
+
/** @brief Assignment Operator */
SIMD_FORCE_INLINE btMatrix3x3& operator=(const btMatrix3x3& other)
{
@@ -133,10 +132,9 @@ public:
* @param i Column number 0 indexed */
SIMD_FORCE_INLINE btVector3 getColumn(int i) const
{
- return btVector3(m_el[0][i],m_el[1][i],m_el[2][i]);
+ return btVector3(m_el[0][i], m_el[1][i], m_el[2][i]);
}
-
/** @brief Get a row of the matrix as a vector
* @param i Row number 0 indexed */
SIMD_FORCE_INLINE const btVector3& getRow(int i) const
@@ -147,10 +145,10 @@ public:
/** @brief Get a mutable reference to a row of the matrix as a vector
* @param i Row number 0 indexed */
- SIMD_FORCE_INLINE btVector3& operator[](int i)
- {
+ SIMD_FORCE_INLINE btVector3& operator[](int i)
+ {
btFullAssert(0 <= i && i < 3);
- return m_el[i];
+ return m_el[i];
}
/** @brief Get a const reference to a row of the matrix as a vector
@@ -158,32 +156,31 @@ public:
SIMD_FORCE_INLINE const btVector3& operator[](int i) const
{
btFullAssert(0 <= i && i < 3);
- return m_el[i];
+ return m_el[i];
}
/** @brief Multiply by the target matrix on the right
* @param m Rotation matrix to be applied
* Equivilant to this = this * m */
- btMatrix3x3& operator*=(const btMatrix3x3& m);
+ btMatrix3x3& operator*=(const btMatrix3x3& m);
/** @brief Adds by the target matrix on the right
* @param m matrix to be applied
* Equivilant to this = this + m */
- btMatrix3x3& operator+=(const btMatrix3x3& m);
+ btMatrix3x3& operator+=(const btMatrix3x3& m);
/** @brief Substractss by the target matrix on the right
* @param m matrix to be applied
* Equivilant to this = this - m */
- btMatrix3x3& operator-=(const btMatrix3x3& m);
+ btMatrix3x3& operator-=(const btMatrix3x3& m);
/** @brief Set from the rotational part of a 4x4 OpenGL matrix
* @param m A pointer to the beginning of the array of scalars*/
- void setFromOpenGLSubMatrix(const btScalar *m)
+ void setFromOpenGLSubMatrix(const btScalar* m)
{
- m_el[0].setValue(m[0],m[4],m[8]);
- m_el[1].setValue(m[1],m[5],m[9]);
- m_el[2].setValue(m[2],m[6],m[10]);
-
+ m_el[0].setValue(m[0], m[4], m[8]);
+ m_el[1].setValue(m[1], m[5], m[9]);
+ m_el[2].setValue(m[2], m[6], m[10]);
}
/** @brief Set the values of the matrix explicitly (row major)
* @param xx Top left
@@ -195,93 +192,92 @@ public:
* @param zx Bottom Left
* @param zy Bottom Middle
* @param zz Bottom Right*/
- void setValue(const btScalar& xx, const btScalar& xy, const btScalar& xz,
- const btScalar& yx, const btScalar& yy, const btScalar& yz,
- const btScalar& zx, const btScalar& zy, const btScalar& zz)
+ void setValue(const btScalar& xx, const btScalar& xy, const btScalar& xz,
+ const btScalar& yx, const btScalar& yy, const btScalar& yz,
+ const btScalar& zx, const btScalar& zy, const btScalar& zz)
{
- m_el[0].setValue(xx,xy,xz);
- m_el[1].setValue(yx,yy,yz);
- m_el[2].setValue(zx,zy,zz);
+ m_el[0].setValue(xx, xy, xz);
+ m_el[1].setValue(yx, yy, yz);
+ m_el[2].setValue(zx, zy, zz);
}
/** @brief Set the matrix from a quaternion
- * @param q The Quaternion to match */
- void setRotation(const btQuaternion& q)
+ * @param q The Quaternion to match */
+ void setRotation(const btQuaternion& q)
{
btScalar d = q.length2();
btFullAssert(d != btScalar(0.0));
btScalar s = btScalar(2.0) / d;
-
- #if defined BT_USE_SIMD_VECTOR3 && defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
- __m128 vs, Q = q.get128();
+
+#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+ __m128 vs, Q = q.get128();
__m128i Qi = btCastfTo128i(Q);
- __m128 Y, Z;
- __m128 V1, V2, V3;
- __m128 V11, V21, V31;
- __m128 NQ = _mm_xor_ps(Q, btvMzeroMask);
+ __m128 Y, Z;
+ __m128 V1, V2, V3;
+ __m128 V11, V21, V31;
+ __m128 NQ = _mm_xor_ps(Q, btvMzeroMask);
__m128i NQi = btCastfTo128i(NQ);
-
- V1 = btCastiTo128f(_mm_shuffle_epi32 (Qi, BT_SHUFFLE(1,0,2,3))); // Y X Z W
- V2 = _mm_shuffle_ps(NQ, Q, BT_SHUFFLE(0,0,1,3)); // -X -X Y W
- V3 = btCastiTo128f(_mm_shuffle_epi32 (Qi, BT_SHUFFLE(2,1,0,3))); // Z Y X W
- V1 = _mm_xor_ps(V1, vMPPP); // change the sign of the first element
-
- V11 = btCastiTo128f(_mm_shuffle_epi32 (Qi, BT_SHUFFLE(1,1,0,3))); // Y Y X W
- V21 = _mm_unpackhi_ps(Q, Q); // Z Z W W
- V31 = _mm_shuffle_ps(Q, NQ, BT_SHUFFLE(0,2,0,3)); // X Z -X -W
-
- V2 = V2 * V1; //
- V1 = V1 * V11; //
- V3 = V3 * V31; //
-
- V11 = _mm_shuffle_ps(NQ, Q, BT_SHUFFLE(2,3,1,3)); // -Z -W Y W
- V11 = V11 * V21; //
- V21 = _mm_xor_ps(V21, vMPPP); // change the sign of the first element
- V31 = _mm_shuffle_ps(Q, NQ, BT_SHUFFLE(3,3,1,3)); // W W -Y -W
- V31 = _mm_xor_ps(V31, vMPPP); // change the sign of the first element
- Y = btCastiTo128f(_mm_shuffle_epi32 (NQi, BT_SHUFFLE(3,2,0,3))); // -W -Z -X -W
- Z = btCastiTo128f(_mm_shuffle_epi32 (Qi, BT_SHUFFLE(1,0,1,3))); // Y X Y W
+
+ V1 = btCastiTo128f(_mm_shuffle_epi32(Qi, BT_SHUFFLE(1, 0, 2, 3))); // Y X Z W
+ V2 = _mm_shuffle_ps(NQ, Q, BT_SHUFFLE(0, 0, 1, 3)); // -X -X Y W
+ V3 = btCastiTo128f(_mm_shuffle_epi32(Qi, BT_SHUFFLE(2, 1, 0, 3))); // Z Y X W
+ V1 = _mm_xor_ps(V1, vMPPP); // change the sign of the first element
+
+ V11 = btCastiTo128f(_mm_shuffle_epi32(Qi, BT_SHUFFLE(1, 1, 0, 3))); // Y Y X W
+ V21 = _mm_unpackhi_ps(Q, Q); // Z Z W W
+ V31 = _mm_shuffle_ps(Q, NQ, BT_SHUFFLE(0, 2, 0, 3)); // X Z -X -W
+
+ V2 = V2 * V1; //
+ V1 = V1 * V11; //
+ V3 = V3 * V31; //
+
+ V11 = _mm_shuffle_ps(NQ, Q, BT_SHUFFLE(2, 3, 1, 3)); // -Z -W Y W
+ V11 = V11 * V21; //
+ V21 = _mm_xor_ps(V21, vMPPP); // change the sign of the first element
+ V31 = _mm_shuffle_ps(Q, NQ, BT_SHUFFLE(3, 3, 1, 3)); // W W -Y -W
+ V31 = _mm_xor_ps(V31, vMPPP); // change the sign of the first element
+ Y = btCastiTo128f(_mm_shuffle_epi32(NQi, BT_SHUFFLE(3, 2, 0, 3))); // -W -Z -X -W
+ Z = btCastiTo128f(_mm_shuffle_epi32(Qi, BT_SHUFFLE(1, 0, 1, 3))); // Y X Y W
vs = _mm_load_ss(&s);
V21 = V21 * Y;
V31 = V31 * Z;
V1 = V1 + V11;
- V2 = V2 + V21;
- V3 = V3 + V31;
-
- vs = bt_splat3_ps(vs, 0);
- // s ready
- V1 = V1 * vs;
- V2 = V2 * vs;
- V3 = V3 * vs;
-
- V1 = V1 + v1000;
- V2 = V2 + v0100;
- V3 = V3 + v0010;
-
- m_el[0] = V1;
- m_el[1] = V2;
- m_el[2] = V3;
- #else
- btScalar xs = q.x() * s, ys = q.y() * s, zs = q.z() * s;
- btScalar wx = q.w() * xs, wy = q.w() * ys, wz = q.w() * zs;
- btScalar xx = q.x() * xs, xy = q.x() * ys, xz = q.x() * zs;
- btScalar yy = q.y() * ys, yz = q.y() * zs, zz = q.z() * zs;
+ V2 = V2 + V21;
+ V3 = V3 + V31;
+
+ vs = bt_splat3_ps(vs, 0);
+ // s ready
+ V1 = V1 * vs;
+ V2 = V2 * vs;
+ V3 = V3 * vs;
+
+ V1 = V1 + v1000;
+ V2 = V2 + v0100;
+ V3 = V3 + v0010;
+
+ m_el[0] = V1;
+ m_el[1] = V2;
+ m_el[2] = V3;
+#else
+ btScalar xs = q.x() * s, ys = q.y() * s, zs = q.z() * s;
+ btScalar wx = q.w() * xs, wy = q.w() * ys, wz = q.w() * zs;
+ btScalar xx = q.x() * xs, xy = q.x() * ys, xz = q.x() * zs;
+ btScalar yy = q.y() * ys, yz = q.y() * zs, zz = q.z() * zs;
setValue(
- btScalar(1.0) - (yy + zz), xy - wz, xz + wy,
+ btScalar(1.0) - (yy + zz), xy - wz, xz + wy,
xy + wz, btScalar(1.0) - (xx + zz), yz - wx,
xz - wy, yz + wx, btScalar(1.0) - (xx + yy));
- #endif
- }
-
+#endif
+ }
/** @brief Set the matrix from euler angles using YPR around YXZ respectively
* @param yaw Yaw about Y axis
* @param pitch Pitch about X axis
* @param roll Roll about Z axis
*/
- void setEulerYPR(const btScalar& yaw, const btScalar& pitch, const btScalar& roll)
+ void setEulerYPR(const btScalar& yaw, const btScalar& pitch, const btScalar& roll)
{
setEulerZYX(roll, pitch, yaw);
}
@@ -295,182 +291,197 @@ public:
* angles are applied in ZYX order. I.e a vector is first rotated
* about X then Y and then Z
**/
- void setEulerZYX(btScalar eulerX,btScalar eulerY,btScalar eulerZ) {
+ void setEulerZYX(btScalar eulerX, btScalar eulerY, btScalar eulerZ)
+ {
///@todo proposed to reverse this since it's labeled zyx but takes arguments xyz and it will match all other parts of the code
- btScalar ci ( btCos(eulerX));
- btScalar cj ( btCos(eulerY));
- btScalar ch ( btCos(eulerZ));
- btScalar si ( btSin(eulerX));
- btScalar sj ( btSin(eulerY));
- btScalar sh ( btSin(eulerZ));
- btScalar cc = ci * ch;
- btScalar cs = ci * sh;
- btScalar sc = si * ch;
+ btScalar ci(btCos(eulerX));
+ btScalar cj(btCos(eulerY));
+ btScalar ch(btCos(eulerZ));
+ btScalar si(btSin(eulerX));
+ btScalar sj(btSin(eulerY));
+ btScalar sh(btSin(eulerZ));
+ btScalar cc = ci * ch;
+ btScalar cs = ci * sh;
+ btScalar sc = si * ch;
btScalar ss = si * sh;
setValue(cj * ch, sj * sc - cs, sj * cc + ss,
- cj * sh, sj * ss + cc, sj * cs - sc,
- -sj, cj * si, cj * ci);
+ cj * sh, sj * ss + cc, sj * cs - sc,
+ -sj, cj * si, cj * ci);
}
/**@brief Set the matrix to the identity */
void setIdentity()
- {
-#if (defined(BT_USE_SSE_IN_API)&& defined (BT_USE_SSE)) || defined(BT_USE_NEON)
- m_el[0] = v1000;
- m_el[1] = v0100;
- m_el[2] = v0010;
+ {
+#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
+ m_el[0] = v1000;
+ m_el[1] = v0100;
+ m_el[2] = v0010;
#else
- setValue(btScalar(1.0), btScalar(0.0), btScalar(0.0),
- btScalar(0.0), btScalar(1.0), btScalar(0.0),
- btScalar(0.0), btScalar(0.0), btScalar(1.0));
+ setValue(btScalar(1.0), btScalar(0.0), btScalar(0.0),
+ btScalar(0.0), btScalar(1.0), btScalar(0.0),
+ btScalar(0.0), btScalar(0.0), btScalar(1.0));
#endif
}
- static const btMatrix3x3& getIdentity()
+ static const btMatrix3x3& getIdentity()
{
-#if (defined(BT_USE_SSE_IN_API)&& defined (BT_USE_SSE)) || defined(BT_USE_NEON)
- static const btMatrix3x3
- identityMatrix(v1000, v0100, v0010);
+#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
+ static const btMatrix3x3
+ identityMatrix(v1000, v0100, v0010);
#else
- static const btMatrix3x3
- identityMatrix(
- btScalar(1.0), btScalar(0.0), btScalar(0.0),
- btScalar(0.0), btScalar(1.0), btScalar(0.0),
- btScalar(0.0), btScalar(0.0), btScalar(1.0));
+ static const btMatrix3x3
+ identityMatrix(
+ btScalar(1.0), btScalar(0.0), btScalar(0.0),
+ btScalar(0.0), btScalar(1.0), btScalar(0.0),
+ btScalar(0.0), btScalar(0.0), btScalar(1.0));
#endif
return identityMatrix;
}
/**@brief Fill the rotational part of an OpenGL matrix and clear the shear/perspective
* @param m The array to be filled */
- void getOpenGLSubMatrix(btScalar *m) const
+ void getOpenGLSubMatrix(btScalar * m) const
{
-#if defined BT_USE_SIMD_VECTOR3 && defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
- __m128 v0 = m_el[0].mVec128;
- __m128 v1 = m_el[1].mVec128;
- __m128 v2 = m_el[2].mVec128; // x2 y2 z2 w2
- __m128 *vm = (__m128 *)m;
- __m128 vT;
-
- v2 = _mm_and_ps(v2, btvFFF0fMask); // x2 y2 z2 0
-
- vT = _mm_unpackhi_ps(v0, v1); // z0 z1 * *
- v0 = _mm_unpacklo_ps(v0, v1); // x0 x1 y0 y1
-
- v1 = _mm_shuffle_ps(v0, v2, BT_SHUFFLE(2, 3, 1, 3) ); // y0 y1 y2 0
- v0 = _mm_shuffle_ps(v0, v2, BT_SHUFFLE(0, 1, 0, 3) ); // x0 x1 x2 0
- v2 = btCastdTo128f(_mm_move_sd(btCastfTo128d(v2), btCastfTo128d(vT))); // z0 z1 z2 0
-
- vm[0] = v0;
- vm[1] = v1;
- vm[2] = v2;
+#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+ __m128 v0 = m_el[0].mVec128;
+ __m128 v1 = m_el[1].mVec128;
+ __m128 v2 = m_el[2].mVec128; // x2 y2 z2 w2
+ __m128* vm = (__m128*)m;
+ __m128 vT;
+
+ v2 = _mm_and_ps(v2, btvFFF0fMask); // x2 y2 z2 0
+
+ vT = _mm_unpackhi_ps(v0, v1); // z0 z1 * *
+ v0 = _mm_unpacklo_ps(v0, v1); // x0 x1 y0 y1
+
+ v1 = _mm_shuffle_ps(v0, v2, BT_SHUFFLE(2, 3, 1, 3)); // y0 y1 y2 0
+ v0 = _mm_shuffle_ps(v0, v2, BT_SHUFFLE(0, 1, 0, 3)); // x0 x1 x2 0
+ v2 = btCastdTo128f(_mm_move_sd(btCastfTo128d(v2), btCastfTo128d(vT))); // z0 z1 z2 0
+
+ vm[0] = v0;
+ vm[1] = v1;
+ vm[2] = v2;
#elif defined(BT_USE_NEON)
- // note: zeros the w channel. We can preserve it at the cost of two more vtrn instructions.
- static const uint32x2_t zMask = (const uint32x2_t) {static_cast<uint32_t>(-1), 0 };
- float32x4_t *vm = (float32x4_t *)m;
- float32x4x2_t top = vtrnq_f32( m_el[0].mVec128, m_el[1].mVec128 ); // {x0 x1 z0 z1}, {y0 y1 w0 w1}
- float32x2x2_t bl = vtrn_f32( vget_low_f32(m_el[2].mVec128), vdup_n_f32(0.0f) ); // {x2 0 }, {y2 0}
- float32x4_t v0 = vcombine_f32( vget_low_f32(top.val[0]), bl.val[0] );
- float32x4_t v1 = vcombine_f32( vget_low_f32(top.val[1]), bl.val[1] );
- float32x2_t q = (float32x2_t) vand_u32( (uint32x2_t) vget_high_f32( m_el[2].mVec128), zMask );
- float32x4_t v2 = vcombine_f32( vget_high_f32(top.val[0]), q ); // z0 z1 z2 0
-
- vm[0] = v0;
- vm[1] = v1;
- vm[2] = v2;
+ // note: zeros the w channel. We can preserve it at the cost of two more vtrn instructions.
+ static const uint32x2_t zMask = (const uint32x2_t){static_cast<uint32_t>(-1), 0};
+ float32x4_t* vm = (float32x4_t*)m;
+ float32x4x2_t top = vtrnq_f32(m_el[0].mVec128, m_el[1].mVec128); // {x0 x1 z0 z1}, {y0 y1 w0 w1}
+ float32x2x2_t bl = vtrn_f32(vget_low_f32(m_el[2].mVec128), vdup_n_f32(0.0f)); // {x2 0 }, {y2 0}
+ float32x4_t v0 = vcombine_f32(vget_low_f32(top.val[0]), bl.val[0]);
+ float32x4_t v1 = vcombine_f32(vget_low_f32(top.val[1]), bl.val[1]);
+ float32x2_t q = (float32x2_t)vand_u32((uint32x2_t)vget_high_f32(m_el[2].mVec128), zMask);
+ float32x4_t v2 = vcombine_f32(vget_high_f32(top.val[0]), q); // z0 z1 z2 0
+
+ vm[0] = v0;
+ vm[1] = v1;
+ vm[2] = v2;
#else
- m[0] = btScalar(m_el[0].x());
- m[1] = btScalar(m_el[1].x());
- m[2] = btScalar(m_el[2].x());
- m[3] = btScalar(0.0);
- m[4] = btScalar(m_el[0].y());
- m[5] = btScalar(m_el[1].y());
- m[6] = btScalar(m_el[2].y());
- m[7] = btScalar(0.0);
- m[8] = btScalar(m_el[0].z());
- m[9] = btScalar(m_el[1].z());
+ m[0] = btScalar(m_el[0].x());
+ m[1] = btScalar(m_el[1].x());
+ m[2] = btScalar(m_el[2].x());
+ m[3] = btScalar(0.0);
+ m[4] = btScalar(m_el[0].y());
+ m[5] = btScalar(m_el[1].y());
+ m[6] = btScalar(m_el[2].y());
+ m[7] = btScalar(0.0);
+ m[8] = btScalar(m_el[0].z());
+ m[9] = btScalar(m_el[1].z());
m[10] = btScalar(m_el[2].z());
- m[11] = btScalar(0.0);
+ m[11] = btScalar(0.0);
#endif
}
/**@brief Get the matrix represented as a quaternion
* @param q The quaternion which will be set */
- void getRotation(btQuaternion& q) const
+ void getRotation(btQuaternion & q) const
{
-#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))|| defined (BT_USE_NEON)
- btScalar trace = m_el[0].x() + m_el[1].y() + m_el[2].z();
- btScalar s, x;
-
- union {
- btSimdFloat4 vec;
- btScalar f[4];
- } temp;
-
- if (trace > btScalar(0.0))
- {
- x = trace + btScalar(1.0);
-
- temp.f[0]=m_el[2].y() - m_el[1].z();
- temp.f[1]=m_el[0].z() - m_el[2].x();
- temp.f[2]=m_el[1].x() - m_el[0].y();
- temp.f[3]=x;
- //temp.f[3]= s * btScalar(0.5);
- }
- else
- {
- int i, j, k;
- if(m_el[0].x() < m_el[1].y())
- {
- if( m_el[1].y() < m_el[2].z() )
- { i = 2; j = 0; k = 1; }
- else
- { i = 1; j = 2; k = 0; }
- }
- else
- {
- if( m_el[0].x() < m_el[2].z())
- { i = 2; j = 0; k = 1; }
- else
- { i = 0; j = 1; k = 2; }
- }
-
- x = m_el[i][i] - m_el[j][j] - m_el[k][k] + btScalar(1.0);
-
- temp.f[3] = (m_el[k][j] - m_el[j][k]);
- temp.f[j] = (m_el[j][i] + m_el[i][j]);
- temp.f[k] = (m_el[k][i] + m_el[i][k]);
- temp.f[i] = x;
- //temp.f[i] = s * btScalar(0.5);
- }
-
- s = btSqrt(x);
- q.set128(temp.vec);
- s = btScalar(0.5) / s;
-
- q *= s;
-#else
+#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
+ btScalar trace = m_el[0].x() + m_el[1].y() + m_el[2].z();
+ btScalar s, x;
+
+ union {
+ btSimdFloat4 vec;
+ btScalar f[4];
+ } temp;
+
+ if (trace > btScalar(0.0))
+ {
+ x = trace + btScalar(1.0);
+
+ temp.f[0] = m_el[2].y() - m_el[1].z();
+ temp.f[1] = m_el[0].z() - m_el[2].x();
+ temp.f[2] = m_el[1].x() - m_el[0].y();
+ temp.f[3] = x;
+ //temp.f[3]= s * btScalar(0.5);
+ }
+ else
+ {
+ int i, j, k;
+ if (m_el[0].x() < m_el[1].y())
+ {
+ if (m_el[1].y() < m_el[2].z())
+ {
+ i = 2;
+ j = 0;
+ k = 1;
+ }
+ else
+ {
+ i = 1;
+ j = 2;
+ k = 0;
+ }
+ }
+ else
+ {
+ if (m_el[0].x() < m_el[2].z())
+ {
+ i = 2;
+ j = 0;
+ k = 1;
+ }
+ else
+ {
+ i = 0;
+ j = 1;
+ k = 2;
+ }
+ }
+
+ x = m_el[i][i] - m_el[j][j] - m_el[k][k] + btScalar(1.0);
+
+ temp.f[3] = (m_el[k][j] - m_el[j][k]);
+ temp.f[j] = (m_el[j][i] + m_el[i][j]);
+ temp.f[k] = (m_el[k][i] + m_el[i][k]);
+ temp.f[i] = x;
+ //temp.f[i] = s * btScalar(0.5);
+ }
+
+ s = btSqrt(x);
+ q.set128(temp.vec);
+ s = btScalar(0.5) / s;
+
+ q *= s;
+#else
btScalar trace = m_el[0].x() + m_el[1].y() + m_el[2].z();
btScalar temp[4];
- if (trace > btScalar(0.0))
+ if (trace > btScalar(0.0))
{
btScalar s = btSqrt(trace + btScalar(1.0));
- temp[3]=(s * btScalar(0.5));
+ temp[3] = (s * btScalar(0.5));
s = btScalar(0.5) / s;
- temp[0]=((m_el[2].y() - m_el[1].z()) * s);
- temp[1]=((m_el[0].z() - m_el[2].x()) * s);
- temp[2]=((m_el[1].x() - m_el[0].y()) * s);
- }
- else
+ temp[0] = ((m_el[2].y() - m_el[1].z()) * s);
+ temp[1] = ((m_el[0].z() - m_el[2].x()) * s);
+ temp[2] = ((m_el[1].x() - m_el[0].y()) * s);
+ }
+ else
{
- int i = m_el[0].x() < m_el[1].y() ?
- (m_el[1].y() < m_el[2].z() ? 2 : 1) :
- (m_el[0].x() < m_el[2].z() ? 2 : 0);
- int j = (i + 1) % 3;
+ int i = m_el[0].x() < m_el[1].y() ? (m_el[1].y() < m_el[2].z() ? 2 : 1) : (m_el[0].x() < m_el[2].z() ? 2 : 0);
+ int j = (i + 1) % 3;
int k = (i + 2) % 3;
btScalar s = btSqrt(m_el[i][i] - m_el[j][j] - m_el[k][k] + btScalar(1.0));
@@ -481,44 +492,42 @@ public:
temp[j] = (m_el[j][i] + m_el[i][j]) * s;
temp[k] = (m_el[k][i] + m_el[i][k]) * s;
}
- q.setValue(temp[0],temp[1],temp[2],temp[3]);
+ q.setValue(temp[0], temp[1], temp[2], temp[3]);
#endif
}
/**@brief Get the matrix represented as euler angles around YXZ, roundtrip with setEulerYPR
* @param yaw Yaw around Y axis
* @param pitch Pitch around X axis
- * @param roll around Z axis */
- void getEulerYPR(btScalar& yaw, btScalar& pitch, btScalar& roll) const
+ * @param roll around Z axis */
+ void getEulerYPR(btScalar & yaw, btScalar & pitch, btScalar & roll) const
{
-
// first use the normal calculus
yaw = btScalar(btAtan2(m_el[1].x(), m_el[0].x()));
pitch = btScalar(btAsin(-m_el[2].x()));
roll = btScalar(btAtan2(m_el[2].y(), m_el[2].z()));
// on pitch = +/-HalfPI
- if (btFabs(pitch)==SIMD_HALF_PI)
+ if (btFabs(pitch) == SIMD_HALF_PI)
{
- if (yaw>0)
- yaw-=SIMD_PI;
+ if (yaw > 0)
+ yaw -= SIMD_PI;
else
- yaw+=SIMD_PI;
+ yaw += SIMD_PI;
- if (roll>0)
- roll-=SIMD_PI;
+ if (roll > 0)
+ roll -= SIMD_PI;
else
- roll+=SIMD_PI;
+ roll += SIMD_PI;
}
};
-
/**@brief Get the matrix represented as euler angles around ZYX
* @param yaw Yaw around Z axis
* @param pitch Pitch around Y axis
* @param roll around X axis
- * @param solution_number Which solution of two possible solutions ( 1 or 2) are possible values*/
- void getEulerZYX(btScalar& yaw, btScalar& pitch, btScalar& roll, unsigned int solution_number = 1) const
+ * @param solution_number Which solution of two possible solutions ( 1 or 2) are possible values*/
+ void getEulerZYX(btScalar & yaw, btScalar & pitch, btScalar & roll, unsigned int solution_number = 1) const
{
struct Euler
{
@@ -528,7 +537,7 @@ public:
};
Euler euler_out;
- Euler euler_out2; //second solution
+ Euler euler_out2; //second solution
//get the pointer to the raw data
// Check that pitch is not at a singularity
@@ -538,7 +547,7 @@ public:
euler_out2.yaw = 0;
// From difference of angles formula
- btScalar delta = btAtan2(m_el[0].x(),m_el[0].z());
+ btScalar delta = btAtan2(m_el[0].x(), m_el[0].z());
if (m_el[2].x() > 0) //gimbal locked up
{
euler_out.pitch = SIMD_PI / btScalar(2.0);
@@ -546,7 +555,7 @@ public:
euler_out.roll = euler_out.pitch + delta;
euler_out2.roll = euler_out.pitch + delta;
}
- else // gimbal locked down
+ else // gimbal locked down
{
euler_out.pitch = -SIMD_PI / btScalar(2.0);
euler_out2.pitch = -SIMD_PI / btScalar(2.0);
@@ -556,29 +565,29 @@ public:
}
else
{
- euler_out.pitch = - btAsin(m_el[2].x());
+ euler_out.pitch = -btAsin(m_el[2].x());
euler_out2.pitch = SIMD_PI - euler_out.pitch;
- euler_out.roll = btAtan2(m_el[2].y()/btCos(euler_out.pitch),
- m_el[2].z()/btCos(euler_out.pitch));
- euler_out2.roll = btAtan2(m_el[2].y()/btCos(euler_out2.pitch),
- m_el[2].z()/btCos(euler_out2.pitch));
+ euler_out.roll = btAtan2(m_el[2].y() / btCos(euler_out.pitch),
+ m_el[2].z() / btCos(euler_out.pitch));
+ euler_out2.roll = btAtan2(m_el[2].y() / btCos(euler_out2.pitch),
+ m_el[2].z() / btCos(euler_out2.pitch));
- euler_out.yaw = btAtan2(m_el[1].x()/btCos(euler_out.pitch),
- m_el[0].x()/btCos(euler_out.pitch));
- euler_out2.yaw = btAtan2(m_el[1].x()/btCos(euler_out2.pitch),
- m_el[0].x()/btCos(euler_out2.pitch));
+ euler_out.yaw = btAtan2(m_el[1].x() / btCos(euler_out.pitch),
+ m_el[0].x() / btCos(euler_out.pitch));
+ euler_out2.yaw = btAtan2(m_el[1].x() / btCos(euler_out2.pitch),
+ m_el[0].x() / btCos(euler_out2.pitch));
}
if (solution_number == 1)
- {
- yaw = euler_out.yaw;
+ {
+ yaw = euler_out.yaw;
pitch = euler_out.pitch;
roll = euler_out.roll;
}
else
- {
- yaw = euler_out2.yaw;
+ {
+ yaw = euler_out2.yaw;
pitch = euler_out2.pitch;
roll = euler_out2.roll;
}
@@ -589,18 +598,18 @@ public:
btMatrix3x3 scaled(const btVector3& s) const
{
-#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))|| defined (BT_USE_NEON)
+#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
return btMatrix3x3(m_el[0] * s, m_el[1] * s, m_el[2] * s);
-#else
+#else
return btMatrix3x3(
- m_el[0].x() * s.x(), m_el[0].y() * s.y(), m_el[0].z() * s.z(),
+ m_el[0].x() * s.x(), m_el[0].y() * s.y(), m_el[0].z() * s.z(),
m_el[1].x() * s.x(), m_el[1].y() * s.y(), m_el[1].z() * s.z(),
m_el[2].x() * s.x(), m_el[2].y() * s.y(), m_el[2].z() * s.z());
#endif
}
/**@brief Return the determinant of the matrix */
- btScalar determinant() const;
+ btScalar determinant() const;
/**@brief Return the adjoint of the matrix */
btMatrix3x3 adjoint() const;
/**@brief Return the matrix with all values non negative */
@@ -608,7 +617,7 @@ public:
/**@brief Return the transpose of the matrix */
btMatrix3x3 transpose() const;
/**@brief Return the inverse of the matrix */
- btMatrix3x3 inverse() const;
+ btMatrix3x3 inverse() const;
/// Solve A * x = b, where b is a column vector. This is more efficient
/// than computing the inverse in one-shot cases.
@@ -618,9 +627,9 @@ public:
btVector3 col1 = getColumn(0);
btVector3 col2 = getColumn(1);
btVector3 col3 = getColumn(2);
-
+
btScalar det = btDot(col1, btCross(col2, col3));
- if (btFabs(det)>SIMD_EPSILON)
+ if (btFabs(det) > SIMD_EPSILON)
{
det = 1.0f / det;
}
@@ -634,15 +643,15 @@ public:
btMatrix3x3 transposeTimes(const btMatrix3x3& m) const;
btMatrix3x3 timesTranspose(const btMatrix3x3& m) const;
- SIMD_FORCE_INLINE btScalar tdotx(const btVector3& v) const
+ SIMD_FORCE_INLINE btScalar tdotx(const btVector3& v) const
{
return m_el[0].x() * v.x() + m_el[1].x() * v.y() + m_el[2].x() * v.z();
}
- SIMD_FORCE_INLINE btScalar tdoty(const btVector3& v) const
+ SIMD_FORCE_INLINE btScalar tdoty(const btVector3& v) const
{
return m_el[0].y() * v.x() + m_el[1].y() * v.y() + m_el[2].y() * v.z();
}
- SIMD_FORCE_INLINE btScalar tdotz(const btVector3& v) const
+ SIMD_FORCE_INLINE btScalar tdotz(const btVector3& v) const
{
return m_el[0].z() * v.x() + m_el[1].z() * v.y() + m_el[2].z() * v.z();
}
@@ -653,31 +662,25 @@ public:
///symmetric matrix S:
///A = R*S.
///note that R can include both rotation and scaling.
- SIMD_FORCE_INLINE void extractRotation(btQuaternion &q,btScalar tolerance = 1.0e-9, int maxIter=100)
+ SIMD_FORCE_INLINE void extractRotation(btQuaternion & q, btScalar tolerance = 1.0e-9, int maxIter = 100)
{
- int iter =0;
+ int iter = 0;
btScalar w;
- const btMatrix3x3& A=*this;
- for(iter = 0; iter < maxIter; iter++)
+ const btMatrix3x3& A = *this;
+ for (iter = 0; iter < maxIter; iter++)
{
btMatrix3x3 R(q);
- btVector3 omega = (R.getColumn(0).cross(A.getColumn(0)) + R.getColumn(1).cross(A.getColumn(1))
- + R.getColumn(2).cross(A.getColumn(2))
- ) * (btScalar(1.0) / btFabs(R.getColumn(0).dot(A.getColumn(0)) + R.getColumn
- (1).dot(A.getColumn(1)) + R.getColumn(2).dot(A.getColumn(2))) +
- tolerance);
+ btVector3 omega = (R.getColumn(0).cross(A.getColumn(0)) + R.getColumn(1).cross(A.getColumn(1)) + R.getColumn(2).cross(A.getColumn(2))) * (btScalar(1.0) / btFabs(R.getColumn(0).dot(A.getColumn(0)) + R.getColumn(1).dot(A.getColumn(1)) + R.getColumn(2).dot(A.getColumn(2))) +
+ tolerance);
w = omega.norm();
- if(w < tolerance)
+ if (w < tolerance)
break;
- q = btQuaternion(btVector3((btScalar(1.0) / w) * omega),w) *
+ q = btQuaternion(btVector3((btScalar(1.0) / w) * omega), w) *
q;
q.normalize();
}
}
-
-
-
/**@brief diagonalizes this matrix by the Jacobi method.
* @param rot stores the rotation from the coordinate system in which the matrix is diagonal to the original
* coordinate system, i.e., old_this = rot * new_this * rot^T.
@@ -687,7 +690,7 @@ public:
*
* Note that this matrix is assumed to be symmetric.
*/
- void diagonalize(btMatrix3x3& rot, btScalar threshold, int maxSteps)
+ void diagonalize(btMatrix3x3 & rot, btScalar threshold, int maxSteps)
{
rot.setIdentity();
for (int step = maxSteps; step > 0; step--)
@@ -723,7 +726,7 @@ public:
step = 1;
}
- // compute Jacobi rotation J which leads to a zero for element [p][q]
+ // compute Jacobi rotation J which leads to a zero for element [p][q]
btScalar mpq = m_el[p][q];
btScalar theta = (m_el[q][q] - m_el[p][p]) / (2 * mpq);
btScalar theta2 = theta * theta;
@@ -732,7 +735,7 @@ public:
if (theta2 * theta2 < btScalar(10 / SIMD_EPSILON))
{
t = (theta >= 0) ? 1 / (theta + btSqrt(1 + theta2))
- : 1 / (theta - btSqrt(1 + theta2));
+ : 1 / (theta - btSqrt(1 + theta2));
cos = 1 / btSqrt(1 + t * t);
sin = cos * t;
}
@@ -765,8 +768,6 @@ public:
}
}
-
-
/**@brief Calculate the matrix cofactor
* @param r1 The first row to use for calculating the cofactor
* @param c1 The first column to use for calculating the cofactor
@@ -774,304 +775,298 @@ public:
* @param c1 The second column to use for calculating the cofactor
* See http://en.wikipedia.org/wiki/Cofactor_(linear_algebra) for more details
*/
- btScalar cofac(int r1, int c1, int r2, int c2) const
+ btScalar cofac(int r1, int c1, int r2, int c2) const
{
return m_el[r1][c1] * m_el[r2][c2] - m_el[r1][c2] * m_el[r2][c1];
}
- void serialize(struct btMatrix3x3Data& dataOut) const;
+ void serialize(struct btMatrix3x3Data & dataOut) const;
- void serializeFloat(struct btMatrix3x3FloatData& dataOut) const;
+ void serializeFloat(struct btMatrix3x3FloatData & dataOut) const;
- void deSerialize(const struct btMatrix3x3Data& dataIn);
+ void deSerialize(const struct btMatrix3x3Data& dataIn);
- void deSerializeFloat(const struct btMatrix3x3FloatData& dataIn);
-
- void deSerializeDouble(const struct btMatrix3x3DoubleData& dataIn);
+ void deSerializeFloat(const struct btMatrix3x3FloatData& dataIn);
+ void deSerializeDouble(const struct btMatrix3x3DoubleData& dataIn);
};
-
-SIMD_FORCE_INLINE btMatrix3x3&
+SIMD_FORCE_INLINE btMatrix3x3&
btMatrix3x3::operator*=(const btMatrix3x3& m)
{
-#if defined BT_USE_SIMD_VECTOR3 && defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
- __m128 rv00, rv01, rv02;
- __m128 rv10, rv11, rv12;
- __m128 rv20, rv21, rv22;
- __m128 mv0, mv1, mv2;
-
- rv02 = m_el[0].mVec128;
- rv12 = m_el[1].mVec128;
- rv22 = m_el[2].mVec128;
-
- mv0 = _mm_and_ps(m[0].mVec128, btvFFF0fMask);
- mv1 = _mm_and_ps(m[1].mVec128, btvFFF0fMask);
- mv2 = _mm_and_ps(m[2].mVec128, btvFFF0fMask);
-
- // rv0
- rv00 = bt_splat_ps(rv02, 0);
- rv01 = bt_splat_ps(rv02, 1);
- rv02 = bt_splat_ps(rv02, 2);
-
- rv00 = _mm_mul_ps(rv00, mv0);
- rv01 = _mm_mul_ps(rv01, mv1);
- rv02 = _mm_mul_ps(rv02, mv2);
-
- // rv1
- rv10 = bt_splat_ps(rv12, 0);
- rv11 = bt_splat_ps(rv12, 1);
- rv12 = bt_splat_ps(rv12, 2);
-
- rv10 = _mm_mul_ps(rv10, mv0);
- rv11 = _mm_mul_ps(rv11, mv1);
- rv12 = _mm_mul_ps(rv12, mv2);
-
- // rv2
- rv20 = bt_splat_ps(rv22, 0);
- rv21 = bt_splat_ps(rv22, 1);
- rv22 = bt_splat_ps(rv22, 2);
-
- rv20 = _mm_mul_ps(rv20, mv0);
- rv21 = _mm_mul_ps(rv21, mv1);
- rv22 = _mm_mul_ps(rv22, mv2);
-
- rv00 = _mm_add_ps(rv00, rv01);
- rv10 = _mm_add_ps(rv10, rv11);
- rv20 = _mm_add_ps(rv20, rv21);
-
- m_el[0].mVec128 = _mm_add_ps(rv00, rv02);
- m_el[1].mVec128 = _mm_add_ps(rv10, rv12);
- m_el[2].mVec128 = _mm_add_ps(rv20, rv22);
+#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+ __m128 rv00, rv01, rv02;
+ __m128 rv10, rv11, rv12;
+ __m128 rv20, rv21, rv22;
+ __m128 mv0, mv1, mv2;
+
+ rv02 = m_el[0].mVec128;
+ rv12 = m_el[1].mVec128;
+ rv22 = m_el[2].mVec128;
+
+ mv0 = _mm_and_ps(m[0].mVec128, btvFFF0fMask);
+ mv1 = _mm_and_ps(m[1].mVec128, btvFFF0fMask);
+ mv2 = _mm_and_ps(m[2].mVec128, btvFFF0fMask);
+
+ // rv0
+ rv00 = bt_splat_ps(rv02, 0);
+ rv01 = bt_splat_ps(rv02, 1);
+ rv02 = bt_splat_ps(rv02, 2);
+
+ rv00 = _mm_mul_ps(rv00, mv0);
+ rv01 = _mm_mul_ps(rv01, mv1);
+ rv02 = _mm_mul_ps(rv02, mv2);
+
+ // rv1
+ rv10 = bt_splat_ps(rv12, 0);
+ rv11 = bt_splat_ps(rv12, 1);
+ rv12 = bt_splat_ps(rv12, 2);
+
+ rv10 = _mm_mul_ps(rv10, mv0);
+ rv11 = _mm_mul_ps(rv11, mv1);
+ rv12 = _mm_mul_ps(rv12, mv2);
+
+ // rv2
+ rv20 = bt_splat_ps(rv22, 0);
+ rv21 = bt_splat_ps(rv22, 1);
+ rv22 = bt_splat_ps(rv22, 2);
+
+ rv20 = _mm_mul_ps(rv20, mv0);
+ rv21 = _mm_mul_ps(rv21, mv1);
+ rv22 = _mm_mul_ps(rv22, mv2);
+
+ rv00 = _mm_add_ps(rv00, rv01);
+ rv10 = _mm_add_ps(rv10, rv11);
+ rv20 = _mm_add_ps(rv20, rv21);
+
+ m_el[0].mVec128 = _mm_add_ps(rv00, rv02);
+ m_el[1].mVec128 = _mm_add_ps(rv10, rv12);
+ m_el[2].mVec128 = _mm_add_ps(rv20, rv22);
#elif defined(BT_USE_NEON)
- float32x4_t rv0, rv1, rv2;
- float32x4_t v0, v1, v2;
- float32x4_t mv0, mv1, mv2;
-
- v0 = m_el[0].mVec128;
- v1 = m_el[1].mVec128;
- v2 = m_el[2].mVec128;
-
- mv0 = (float32x4_t) vandq_s32((int32x4_t)m[0].mVec128, btvFFF0Mask);
- mv1 = (float32x4_t) vandq_s32((int32x4_t)m[1].mVec128, btvFFF0Mask);
- mv2 = (float32x4_t) vandq_s32((int32x4_t)m[2].mVec128, btvFFF0Mask);
-
- rv0 = vmulq_lane_f32(mv0, vget_low_f32(v0), 0);
- rv1 = vmulq_lane_f32(mv0, vget_low_f32(v1), 0);
- rv2 = vmulq_lane_f32(mv0, vget_low_f32(v2), 0);
-
- rv0 = vmlaq_lane_f32(rv0, mv1, vget_low_f32(v0), 1);
- rv1 = vmlaq_lane_f32(rv1, mv1, vget_low_f32(v1), 1);
- rv2 = vmlaq_lane_f32(rv2, mv1, vget_low_f32(v2), 1);
-
- rv0 = vmlaq_lane_f32(rv0, mv2, vget_high_f32(v0), 0);
- rv1 = vmlaq_lane_f32(rv1, mv2, vget_high_f32(v1), 0);
- rv2 = vmlaq_lane_f32(rv2, mv2, vget_high_f32(v2), 0);
-
- m_el[0].mVec128 = rv0;
- m_el[1].mVec128 = rv1;
- m_el[2].mVec128 = rv2;
-#else
+ float32x4_t rv0, rv1, rv2;
+ float32x4_t v0, v1, v2;
+ float32x4_t mv0, mv1, mv2;
+
+ v0 = m_el[0].mVec128;
+ v1 = m_el[1].mVec128;
+ v2 = m_el[2].mVec128;
+
+ mv0 = (float32x4_t)vandq_s32((int32x4_t)m[0].mVec128, btvFFF0Mask);
+ mv1 = (float32x4_t)vandq_s32((int32x4_t)m[1].mVec128, btvFFF0Mask);
+ mv2 = (float32x4_t)vandq_s32((int32x4_t)m[2].mVec128, btvFFF0Mask);
+
+ rv0 = vmulq_lane_f32(mv0, vget_low_f32(v0), 0);
+ rv1 = vmulq_lane_f32(mv0, vget_low_f32(v1), 0);
+ rv2 = vmulq_lane_f32(mv0, vget_low_f32(v2), 0);
+
+ rv0 = vmlaq_lane_f32(rv0, mv1, vget_low_f32(v0), 1);
+ rv1 = vmlaq_lane_f32(rv1, mv1, vget_low_f32(v1), 1);
+ rv2 = vmlaq_lane_f32(rv2, mv1, vget_low_f32(v2), 1);
+
+ rv0 = vmlaq_lane_f32(rv0, mv2, vget_high_f32(v0), 0);
+ rv1 = vmlaq_lane_f32(rv1, mv2, vget_high_f32(v1), 0);
+ rv2 = vmlaq_lane_f32(rv2, mv2, vget_high_f32(v2), 0);
+
+ m_el[0].mVec128 = rv0;
+ m_el[1].mVec128 = rv1;
+ m_el[2].mVec128 = rv2;
+#else
setValue(
- m.tdotx(m_el[0]), m.tdoty(m_el[0]), m.tdotz(m_el[0]),
+ m.tdotx(m_el[0]), m.tdoty(m_el[0]), m.tdotz(m_el[0]),
m.tdotx(m_el[1]), m.tdoty(m_el[1]), m.tdotz(m_el[1]),
m.tdotx(m_el[2]), m.tdoty(m_el[2]), m.tdotz(m_el[2]));
#endif
return *this;
}
-SIMD_FORCE_INLINE btMatrix3x3&
+SIMD_FORCE_INLINE btMatrix3x3&
btMatrix3x3::operator+=(const btMatrix3x3& m)
{
-#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))|| defined (BT_USE_NEON)
- m_el[0].mVec128 = m_el[0].mVec128 + m.m_el[0].mVec128;
- m_el[1].mVec128 = m_el[1].mVec128 + m.m_el[1].mVec128;
- m_el[2].mVec128 = m_el[2].mVec128 + m.m_el[2].mVec128;
+#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
+ m_el[0].mVec128 = m_el[0].mVec128 + m.m_el[0].mVec128;
+ m_el[1].mVec128 = m_el[1].mVec128 + m.m_el[1].mVec128;
+ m_el[2].mVec128 = m_el[2].mVec128 + m.m_el[2].mVec128;
#else
setValue(
- m_el[0][0]+m.m_el[0][0],
- m_el[0][1]+m.m_el[0][1],
- m_el[0][2]+m.m_el[0][2],
- m_el[1][0]+m.m_el[1][0],
- m_el[1][1]+m.m_el[1][1],
- m_el[1][2]+m.m_el[1][2],
- m_el[2][0]+m.m_el[2][0],
- m_el[2][1]+m.m_el[2][1],
- m_el[2][2]+m.m_el[2][2]);
+ m_el[0][0] + m.m_el[0][0],
+ m_el[0][1] + m.m_el[0][1],
+ m_el[0][2] + m.m_el[0][2],
+ m_el[1][0] + m.m_el[1][0],
+ m_el[1][1] + m.m_el[1][1],
+ m_el[1][2] + m.m_el[1][2],
+ m_el[2][0] + m.m_el[2][0],
+ m_el[2][1] + m.m_el[2][1],
+ m_el[2][2] + m.m_el[2][2]);
#endif
return *this;
}
SIMD_FORCE_INLINE btMatrix3x3
-operator*(const btMatrix3x3& m, const btScalar & k)
+operator*(const btMatrix3x3& m, const btScalar& k)
{
-#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))
- __m128 vk = bt_splat_ps(_mm_load_ss((float *)&k), 0x80);
- return btMatrix3x3(
- _mm_mul_ps(m[0].mVec128, vk),
- _mm_mul_ps(m[1].mVec128, vk),
- _mm_mul_ps(m[2].mVec128, vk));
+#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))
+ __m128 vk = bt_splat_ps(_mm_load_ss((float*)&k), 0x80);
+ return btMatrix3x3(
+ _mm_mul_ps(m[0].mVec128, vk),
+ _mm_mul_ps(m[1].mVec128, vk),
+ _mm_mul_ps(m[2].mVec128, vk));
#elif defined(BT_USE_NEON)
- return btMatrix3x3(
- vmulq_n_f32(m[0].mVec128, k),
- vmulq_n_f32(m[1].mVec128, k),
- vmulq_n_f32(m[2].mVec128, k));
+ return btMatrix3x3(
+ vmulq_n_f32(m[0].mVec128, k),
+ vmulq_n_f32(m[1].mVec128, k),
+ vmulq_n_f32(m[2].mVec128, k));
#else
return btMatrix3x3(
- m[0].x()*k,m[0].y()*k,m[0].z()*k,
- m[1].x()*k,m[1].y()*k,m[1].z()*k,
- m[2].x()*k,m[2].y()*k,m[2].z()*k);
+ m[0].x() * k, m[0].y() * k, m[0].z() * k,
+ m[1].x() * k, m[1].y() * k, m[1].z() * k,
+ m[2].x() * k, m[2].y() * k, m[2].z() * k);
#endif
}
-SIMD_FORCE_INLINE btMatrix3x3
+SIMD_FORCE_INLINE btMatrix3x3
operator+(const btMatrix3x3& m1, const btMatrix3x3& m2)
{
-#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))|| defined (BT_USE_NEON)
+#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
return btMatrix3x3(
- m1[0].mVec128 + m2[0].mVec128,
- m1[1].mVec128 + m2[1].mVec128,
- m1[2].mVec128 + m2[2].mVec128);
+ m1[0].mVec128 + m2[0].mVec128,
+ m1[1].mVec128 + m2[1].mVec128,
+ m1[2].mVec128 + m2[2].mVec128);
#else
return btMatrix3x3(
- m1[0][0]+m2[0][0],
- m1[0][1]+m2[0][1],
- m1[0][2]+m2[0][2],
-
- m1[1][0]+m2[1][0],
- m1[1][1]+m2[1][1],
- m1[1][2]+m2[1][2],
-
- m1[2][0]+m2[2][0],
- m1[2][1]+m2[2][1],
- m1[2][2]+m2[2][2]);
-#endif
+ m1[0][0] + m2[0][0],
+ m1[0][1] + m2[0][1],
+ m1[0][2] + m2[0][2],
+
+ m1[1][0] + m2[1][0],
+ m1[1][1] + m2[1][1],
+ m1[1][2] + m2[1][2],
+
+ m1[2][0] + m2[2][0],
+ m1[2][1] + m2[2][1],
+ m1[2][2] + m2[2][2]);
+#endif
}
-SIMD_FORCE_INLINE btMatrix3x3
+SIMD_FORCE_INLINE btMatrix3x3
operator-(const btMatrix3x3& m1, const btMatrix3x3& m2)
{
-#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))|| defined (BT_USE_NEON)
+#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
return btMatrix3x3(
- m1[0].mVec128 - m2[0].mVec128,
- m1[1].mVec128 - m2[1].mVec128,
- m1[2].mVec128 - m2[2].mVec128);
+ m1[0].mVec128 - m2[0].mVec128,
+ m1[1].mVec128 - m2[1].mVec128,
+ m1[2].mVec128 - m2[2].mVec128);
#else
return btMatrix3x3(
- m1[0][0]-m2[0][0],
- m1[0][1]-m2[0][1],
- m1[0][2]-m2[0][2],
-
- m1[1][0]-m2[1][0],
- m1[1][1]-m2[1][1],
- m1[1][2]-m2[1][2],
-
- m1[2][0]-m2[2][0],
- m1[2][1]-m2[2][1],
- m1[2][2]-m2[2][2]);
+ m1[0][0] - m2[0][0],
+ m1[0][1] - m2[0][1],
+ m1[0][2] - m2[0][2],
+
+ m1[1][0] - m2[1][0],
+ m1[1][1] - m2[1][1],
+ m1[1][2] - m2[1][2],
+
+ m1[2][0] - m2[2][0],
+ m1[2][1] - m2[2][1],
+ m1[2][2] - m2[2][2]);
#endif
}
-
-SIMD_FORCE_INLINE btMatrix3x3&
+SIMD_FORCE_INLINE btMatrix3x3&
btMatrix3x3::operator-=(const btMatrix3x3& m)
{
-#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))|| defined (BT_USE_NEON)
- m_el[0].mVec128 = m_el[0].mVec128 - m.m_el[0].mVec128;
- m_el[1].mVec128 = m_el[1].mVec128 - m.m_el[1].mVec128;
- m_el[2].mVec128 = m_el[2].mVec128 - m.m_el[2].mVec128;
+#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
+ m_el[0].mVec128 = m_el[0].mVec128 - m.m_el[0].mVec128;
+ m_el[1].mVec128 = m_el[1].mVec128 - m.m_el[1].mVec128;
+ m_el[2].mVec128 = m_el[2].mVec128 - m.m_el[2].mVec128;
#else
setValue(
- m_el[0][0]-m.m_el[0][0],
- m_el[0][1]-m.m_el[0][1],
- m_el[0][2]-m.m_el[0][2],
- m_el[1][0]-m.m_el[1][0],
- m_el[1][1]-m.m_el[1][1],
- m_el[1][2]-m.m_el[1][2],
- m_el[2][0]-m.m_el[2][0],
- m_el[2][1]-m.m_el[2][1],
- m_el[2][2]-m.m_el[2][2]);
+ m_el[0][0] - m.m_el[0][0],
+ m_el[0][1] - m.m_el[0][1],
+ m_el[0][2] - m.m_el[0][2],
+ m_el[1][0] - m.m_el[1][0],
+ m_el[1][1] - m.m_el[1][1],
+ m_el[1][2] - m.m_el[1][2],
+ m_el[2][0] - m.m_el[2][0],
+ m_el[2][1] - m.m_el[2][1],
+ m_el[2][2] - m.m_el[2][2]);
#endif
return *this;
}
-
-SIMD_FORCE_INLINE btScalar
+SIMD_FORCE_INLINE btScalar
btMatrix3x3::determinant() const
-{
+{
return btTriple((*this)[0], (*this)[1], (*this)[2]);
}
-
-SIMD_FORCE_INLINE btMatrix3x3
+SIMD_FORCE_INLINE btMatrix3x3
btMatrix3x3::absolute() const
{
-#if defined BT_USE_SIMD_VECTOR3 && (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))
- return btMatrix3x3(
- _mm_and_ps(m_el[0].mVec128, btvAbsfMask),
- _mm_and_ps(m_el[1].mVec128, btvAbsfMask),
- _mm_and_ps(m_el[2].mVec128, btvAbsfMask));
+#if defined BT_USE_SIMD_VECTOR3 && (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))
+ return btMatrix3x3(
+ _mm_and_ps(m_el[0].mVec128, btvAbsfMask),
+ _mm_and_ps(m_el[1].mVec128, btvAbsfMask),
+ _mm_and_ps(m_el[2].mVec128, btvAbsfMask));
#elif defined(BT_USE_NEON)
- return btMatrix3x3(
- (float32x4_t)vandq_s32((int32x4_t)m_el[0].mVec128, btv3AbsMask),
- (float32x4_t)vandq_s32((int32x4_t)m_el[1].mVec128, btv3AbsMask),
- (float32x4_t)vandq_s32((int32x4_t)m_el[2].mVec128, btv3AbsMask));
-#else
return btMatrix3x3(
- btFabs(m_el[0].x()), btFabs(m_el[0].y()), btFabs(m_el[0].z()),
- btFabs(m_el[1].x()), btFabs(m_el[1].y()), btFabs(m_el[1].z()),
- btFabs(m_el[2].x()), btFabs(m_el[2].y()), btFabs(m_el[2].z()));
+ (float32x4_t)vandq_s32((int32x4_t)m_el[0].mVec128, btv3AbsMask),
+ (float32x4_t)vandq_s32((int32x4_t)m_el[1].mVec128, btv3AbsMask),
+ (float32x4_t)vandq_s32((int32x4_t)m_el[2].mVec128, btv3AbsMask));
+#else
+ return btMatrix3x3(
+ btFabs(m_el[0].x()), btFabs(m_el[0].y()), btFabs(m_el[0].z()),
+ btFabs(m_el[1].x()), btFabs(m_el[1].y()), btFabs(m_el[1].z()),
+ btFabs(m_el[2].x()), btFabs(m_el[2].y()), btFabs(m_el[2].z()));
#endif
}
-SIMD_FORCE_INLINE btMatrix3x3
-btMatrix3x3::transpose() const
+SIMD_FORCE_INLINE btMatrix3x3
+btMatrix3x3::transpose() const
{
-#if defined BT_USE_SIMD_VECTOR3 && (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))
- __m128 v0 = m_el[0].mVec128;
- __m128 v1 = m_el[1].mVec128;
- __m128 v2 = m_el[2].mVec128; // x2 y2 z2 w2
- __m128 vT;
-
- v2 = _mm_and_ps(v2, btvFFF0fMask); // x2 y2 z2 0
-
- vT = _mm_unpackhi_ps(v0, v1); // z0 z1 * *
- v0 = _mm_unpacklo_ps(v0, v1); // x0 x1 y0 y1
-
- v1 = _mm_shuffle_ps(v0, v2, BT_SHUFFLE(2, 3, 1, 3) ); // y0 y1 y2 0
- v0 = _mm_shuffle_ps(v0, v2, BT_SHUFFLE(0, 1, 0, 3) ); // x0 x1 x2 0
- v2 = btCastdTo128f(_mm_move_sd(btCastfTo128d(v2), btCastfTo128d(vT))); // z0 z1 z2 0
-
-
- return btMatrix3x3( v0, v1, v2 );
+#if defined BT_USE_SIMD_VECTOR3 && (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))
+ __m128 v0 = m_el[0].mVec128;
+ __m128 v1 = m_el[1].mVec128;
+ __m128 v2 = m_el[2].mVec128; // x2 y2 z2 w2
+ __m128 vT;
+
+ v2 = _mm_and_ps(v2, btvFFF0fMask); // x2 y2 z2 0
+
+ vT = _mm_unpackhi_ps(v0, v1); // z0 z1 * *
+ v0 = _mm_unpacklo_ps(v0, v1); // x0 x1 y0 y1
+
+ v1 = _mm_shuffle_ps(v0, v2, BT_SHUFFLE(2, 3, 1, 3)); // y0 y1 y2 0
+ v0 = _mm_shuffle_ps(v0, v2, BT_SHUFFLE(0, 1, 0, 3)); // x0 x1 x2 0
+ v2 = btCastdTo128f(_mm_move_sd(btCastfTo128d(v2), btCastfTo128d(vT))); // z0 z1 z2 0
+
+ return btMatrix3x3(v0, v1, v2);
#elif defined(BT_USE_NEON)
- // note: zeros the w channel. We can preserve it at the cost of two more vtrn instructions.
- static const uint32x2_t zMask = (const uint32x2_t) {static_cast<uint32_t>(-1), 0 };
- float32x4x2_t top = vtrnq_f32( m_el[0].mVec128, m_el[1].mVec128 ); // {x0 x1 z0 z1}, {y0 y1 w0 w1}
- float32x2x2_t bl = vtrn_f32( vget_low_f32(m_el[2].mVec128), vdup_n_f32(0.0f) ); // {x2 0 }, {y2 0}
- float32x4_t v0 = vcombine_f32( vget_low_f32(top.val[0]), bl.val[0] );
- float32x4_t v1 = vcombine_f32( vget_low_f32(top.val[1]), bl.val[1] );
- float32x2_t q = (float32x2_t) vand_u32( (uint32x2_t) vget_high_f32( m_el[2].mVec128), zMask );
- float32x4_t v2 = vcombine_f32( vget_high_f32(top.val[0]), q ); // z0 z1 z2 0
- return btMatrix3x3( v0, v1, v2 );
+ // note: zeros the w channel. We can preserve it at the cost of two more vtrn instructions.
+ static const uint32x2_t zMask = (const uint32x2_t){static_cast<uint32_t>(-1), 0};
+ float32x4x2_t top = vtrnq_f32(m_el[0].mVec128, m_el[1].mVec128); // {x0 x1 z0 z1}, {y0 y1 w0 w1}
+ float32x2x2_t bl = vtrn_f32(vget_low_f32(m_el[2].mVec128), vdup_n_f32(0.0f)); // {x2 0 }, {y2 0}
+ float32x4_t v0 = vcombine_f32(vget_low_f32(top.val[0]), bl.val[0]);
+ float32x4_t v1 = vcombine_f32(vget_low_f32(top.val[1]), bl.val[1]);
+ float32x2_t q = (float32x2_t)vand_u32((uint32x2_t)vget_high_f32(m_el[2].mVec128), zMask);
+ float32x4_t v2 = vcombine_f32(vget_high_f32(top.val[0]), q); // z0 z1 z2 0
+ return btMatrix3x3(v0, v1, v2);
#else
- return btMatrix3x3( m_el[0].x(), m_el[1].x(), m_el[2].x(),
- m_el[0].y(), m_el[1].y(), m_el[2].y(),
- m_el[0].z(), m_el[1].z(), m_el[2].z());
+ return btMatrix3x3(m_el[0].x(), m_el[1].x(), m_el[2].x(),
+ m_el[0].y(), m_el[1].y(), m_el[2].y(),
+ m_el[0].z(), m_el[1].z(), m_el[2].z());
#endif
}
-SIMD_FORCE_INLINE btMatrix3x3
-btMatrix3x3::adjoint() const
+SIMD_FORCE_INLINE btMatrix3x3
+btMatrix3x3::adjoint() const
{
return btMatrix3x3(cofac(1, 1, 2, 2), cofac(0, 2, 2, 1), cofac(0, 1, 1, 2),
- cofac(1, 2, 2, 0), cofac(0, 0, 2, 2), cofac(0, 2, 1, 0),
- cofac(1, 0, 2, 1), cofac(0, 1, 2, 0), cofac(0, 0, 1, 1));
+ cofac(1, 2, 2, 0), cofac(0, 0, 2, 2), cofac(0, 2, 1, 0),
+ cofac(1, 0, 2, 1), cofac(0, 1, 2, 0), cofac(0, 0, 1, 1));
}
-SIMD_FORCE_INLINE btMatrix3x3
+SIMD_FORCE_INLINE btMatrix3x3
btMatrix3x3::inverse() const
{
btVector3 co(cofac(1, 1, 2, 2), cofac(1, 2, 2, 0), cofac(1, 0, 2, 1));
@@ -1080,54 +1075,54 @@ btMatrix3x3::inverse() const
btAssert(det != btScalar(0.0));
btScalar s = btScalar(1.0) / det;
return btMatrix3x3(co.x() * s, cofac(0, 2, 2, 1) * s, cofac(0, 1, 1, 2) * s,
- co.y() * s, cofac(0, 0, 2, 2) * s, cofac(0, 2, 1, 0) * s,
- co.z() * s, cofac(0, 1, 2, 0) * s, cofac(0, 0, 1, 1) * s);
+ co.y() * s, cofac(0, 0, 2, 2) * s, cofac(0, 2, 1, 0) * s,
+ co.z() * s, cofac(0, 1, 2, 0) * s, cofac(0, 0, 1, 1) * s);
}
-SIMD_FORCE_INLINE btMatrix3x3
+SIMD_FORCE_INLINE btMatrix3x3
btMatrix3x3::transposeTimes(const btMatrix3x3& m) const
{
-#if defined BT_USE_SIMD_VECTOR3 && (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))
- // zeros w
-// static const __m128i xyzMask = (const __m128i){ -1ULL, 0xffffffffULL };
- __m128 row = m_el[0].mVec128;
- __m128 m0 = _mm_and_ps( m.getRow(0).mVec128, btvFFF0fMask );
- __m128 m1 = _mm_and_ps( m.getRow(1).mVec128, btvFFF0fMask);
- __m128 m2 = _mm_and_ps( m.getRow(2).mVec128, btvFFF0fMask );
- __m128 r0 = _mm_mul_ps(m0, _mm_shuffle_ps(row, row, 0));
- __m128 r1 = _mm_mul_ps(m0, _mm_shuffle_ps(row, row, 0x55));
- __m128 r2 = _mm_mul_ps(m0, _mm_shuffle_ps(row, row, 0xaa));
- row = m_el[1].mVec128;
- r0 = _mm_add_ps( r0, _mm_mul_ps(m1, _mm_shuffle_ps(row, row, 0)));
- r1 = _mm_add_ps( r1, _mm_mul_ps(m1, _mm_shuffle_ps(row, row, 0x55)));
- r2 = _mm_add_ps( r2, _mm_mul_ps(m1, _mm_shuffle_ps(row, row, 0xaa)));
- row = m_el[2].mVec128;
- r0 = _mm_add_ps( r0, _mm_mul_ps(m2, _mm_shuffle_ps(row, row, 0)));
- r1 = _mm_add_ps( r1, _mm_mul_ps(m2, _mm_shuffle_ps(row, row, 0x55)));
- r2 = _mm_add_ps( r2, _mm_mul_ps(m2, _mm_shuffle_ps(row, row, 0xaa)));
- return btMatrix3x3( r0, r1, r2 );
+#if defined BT_USE_SIMD_VECTOR3 && (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))
+ // zeros w
+ // static const __m128i xyzMask = (const __m128i){ -1ULL, 0xffffffffULL };
+ __m128 row = m_el[0].mVec128;
+ __m128 m0 = _mm_and_ps(m.getRow(0).mVec128, btvFFF0fMask);
+ __m128 m1 = _mm_and_ps(m.getRow(1).mVec128, btvFFF0fMask);
+ __m128 m2 = _mm_and_ps(m.getRow(2).mVec128, btvFFF0fMask);
+ __m128 r0 = _mm_mul_ps(m0, _mm_shuffle_ps(row, row, 0));
+ __m128 r1 = _mm_mul_ps(m0, _mm_shuffle_ps(row, row, 0x55));
+ __m128 r2 = _mm_mul_ps(m0, _mm_shuffle_ps(row, row, 0xaa));
+ row = m_el[1].mVec128;
+ r0 = _mm_add_ps(r0, _mm_mul_ps(m1, _mm_shuffle_ps(row, row, 0)));
+ r1 = _mm_add_ps(r1, _mm_mul_ps(m1, _mm_shuffle_ps(row, row, 0x55)));
+ r2 = _mm_add_ps(r2, _mm_mul_ps(m1, _mm_shuffle_ps(row, row, 0xaa)));
+ row = m_el[2].mVec128;
+ r0 = _mm_add_ps(r0, _mm_mul_ps(m2, _mm_shuffle_ps(row, row, 0)));
+ r1 = _mm_add_ps(r1, _mm_mul_ps(m2, _mm_shuffle_ps(row, row, 0x55)));
+ r2 = _mm_add_ps(r2, _mm_mul_ps(m2, _mm_shuffle_ps(row, row, 0xaa)));
+ return btMatrix3x3(r0, r1, r2);
#elif defined BT_USE_NEON
- // zeros w
- static const uint32x4_t xyzMask = (const uint32x4_t){ static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), 0 };
- float32x4_t m0 = (float32x4_t) vandq_u32( (uint32x4_t) m.getRow(0).mVec128, xyzMask );
- float32x4_t m1 = (float32x4_t) vandq_u32( (uint32x4_t) m.getRow(1).mVec128, xyzMask );
- float32x4_t m2 = (float32x4_t) vandq_u32( (uint32x4_t) m.getRow(2).mVec128, xyzMask );
- float32x4_t row = m_el[0].mVec128;
- float32x4_t r0 = vmulq_lane_f32( m0, vget_low_f32(row), 0);
- float32x4_t r1 = vmulq_lane_f32( m0, vget_low_f32(row), 1);
- float32x4_t r2 = vmulq_lane_f32( m0, vget_high_f32(row), 0);
- row = m_el[1].mVec128;
- r0 = vmlaq_lane_f32( r0, m1, vget_low_f32(row), 0);
- r1 = vmlaq_lane_f32( r1, m1, vget_low_f32(row), 1);
- r2 = vmlaq_lane_f32( r2, m1, vget_high_f32(row), 0);
- row = m_el[2].mVec128;
- r0 = vmlaq_lane_f32( r0, m2, vget_low_f32(row), 0);
- r1 = vmlaq_lane_f32( r1, m2, vget_low_f32(row), 1);
- r2 = vmlaq_lane_f32( r2, m2, vget_high_f32(row), 0);
- return btMatrix3x3( r0, r1, r2 );
+ // zeros w
+ static const uint32x4_t xyzMask = (const uint32x4_t){static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), 0};
+ float32x4_t m0 = (float32x4_t)vandq_u32((uint32x4_t)m.getRow(0).mVec128, xyzMask);
+ float32x4_t m1 = (float32x4_t)vandq_u32((uint32x4_t)m.getRow(1).mVec128, xyzMask);
+ float32x4_t m2 = (float32x4_t)vandq_u32((uint32x4_t)m.getRow(2).mVec128, xyzMask);
+ float32x4_t row = m_el[0].mVec128;
+ float32x4_t r0 = vmulq_lane_f32(m0, vget_low_f32(row), 0);
+ float32x4_t r1 = vmulq_lane_f32(m0, vget_low_f32(row), 1);
+ float32x4_t r2 = vmulq_lane_f32(m0, vget_high_f32(row), 0);
+ row = m_el[1].mVec128;
+ r0 = vmlaq_lane_f32(r0, m1, vget_low_f32(row), 0);
+ r1 = vmlaq_lane_f32(r1, m1, vget_low_f32(row), 1);
+ r2 = vmlaq_lane_f32(r2, m1, vget_high_f32(row), 0);
+ row = m_el[2].mVec128;
+ r0 = vmlaq_lane_f32(r0, m2, vget_low_f32(row), 0);
+ r1 = vmlaq_lane_f32(r1, m2, vget_low_f32(row), 1);
+ r2 = vmlaq_lane_f32(r2, m2, vget_high_f32(row), 0);
+ return btMatrix3x3(r0, r1, r2);
#else
- return btMatrix3x3(
+ return btMatrix3x3(
m_el[0].x() * m[0].x() + m_el[1].x() * m[1].x() + m_el[2].x() * m[2].x(),
m_el[0].x() * m[0].y() + m_el[1].x() * m[1].y() + m_el[2].x() * m[2].y(),
m_el[0].x() * m[0].z() + m_el[1].x() * m[1].z() + m_el[2].x() * m[2].z(),
@@ -1140,51 +1135,51 @@ btMatrix3x3::transposeTimes(const btMatrix3x3& m) const
#endif
}
-SIMD_FORCE_INLINE btMatrix3x3
+SIMD_FORCE_INLINE btMatrix3x3
btMatrix3x3::timesTranspose(const btMatrix3x3& m) const
{
-#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))
- __m128 a0 = m_el[0].mVec128;
- __m128 a1 = m_el[1].mVec128;
- __m128 a2 = m_el[2].mVec128;
-
- btMatrix3x3 mT = m.transpose(); // we rely on transpose() zeroing w channel so that we don't have to do it here
- __m128 mx = mT[0].mVec128;
- __m128 my = mT[1].mVec128;
- __m128 mz = mT[2].mVec128;
-
- __m128 r0 = _mm_mul_ps(mx, _mm_shuffle_ps(a0, a0, 0x00));
- __m128 r1 = _mm_mul_ps(mx, _mm_shuffle_ps(a1, a1, 0x00));
- __m128 r2 = _mm_mul_ps(mx, _mm_shuffle_ps(a2, a2, 0x00));
- r0 = _mm_add_ps(r0, _mm_mul_ps(my, _mm_shuffle_ps(a0, a0, 0x55)));
- r1 = _mm_add_ps(r1, _mm_mul_ps(my, _mm_shuffle_ps(a1, a1, 0x55)));
- r2 = _mm_add_ps(r2, _mm_mul_ps(my, _mm_shuffle_ps(a2, a2, 0x55)));
- r0 = _mm_add_ps(r0, _mm_mul_ps(mz, _mm_shuffle_ps(a0, a0, 0xaa)));
- r1 = _mm_add_ps(r1, _mm_mul_ps(mz, _mm_shuffle_ps(a1, a1, 0xaa)));
- r2 = _mm_add_ps(r2, _mm_mul_ps(mz, _mm_shuffle_ps(a2, a2, 0xaa)));
- return btMatrix3x3( r0, r1, r2);
-
+#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))
+ __m128 a0 = m_el[0].mVec128;
+ __m128 a1 = m_el[1].mVec128;
+ __m128 a2 = m_el[2].mVec128;
+
+ btMatrix3x3 mT = m.transpose(); // we rely on transpose() zeroing w channel so that we don't have to do it here
+ __m128 mx = mT[0].mVec128;
+ __m128 my = mT[1].mVec128;
+ __m128 mz = mT[2].mVec128;
+
+ __m128 r0 = _mm_mul_ps(mx, _mm_shuffle_ps(a0, a0, 0x00));
+ __m128 r1 = _mm_mul_ps(mx, _mm_shuffle_ps(a1, a1, 0x00));
+ __m128 r2 = _mm_mul_ps(mx, _mm_shuffle_ps(a2, a2, 0x00));
+ r0 = _mm_add_ps(r0, _mm_mul_ps(my, _mm_shuffle_ps(a0, a0, 0x55)));
+ r1 = _mm_add_ps(r1, _mm_mul_ps(my, _mm_shuffle_ps(a1, a1, 0x55)));
+ r2 = _mm_add_ps(r2, _mm_mul_ps(my, _mm_shuffle_ps(a2, a2, 0x55)));
+ r0 = _mm_add_ps(r0, _mm_mul_ps(mz, _mm_shuffle_ps(a0, a0, 0xaa)));
+ r1 = _mm_add_ps(r1, _mm_mul_ps(mz, _mm_shuffle_ps(a1, a1, 0xaa)));
+ r2 = _mm_add_ps(r2, _mm_mul_ps(mz, _mm_shuffle_ps(a2, a2, 0xaa)));
+ return btMatrix3x3(r0, r1, r2);
+
#elif defined BT_USE_NEON
- float32x4_t a0 = m_el[0].mVec128;
- float32x4_t a1 = m_el[1].mVec128;
- float32x4_t a2 = m_el[2].mVec128;
-
- btMatrix3x3 mT = m.transpose(); // we rely on transpose() zeroing w channel so that we don't have to do it here
- float32x4_t mx = mT[0].mVec128;
- float32x4_t my = mT[1].mVec128;
- float32x4_t mz = mT[2].mVec128;
-
- float32x4_t r0 = vmulq_lane_f32( mx, vget_low_f32(a0), 0);
- float32x4_t r1 = vmulq_lane_f32( mx, vget_low_f32(a1), 0);
- float32x4_t r2 = vmulq_lane_f32( mx, vget_low_f32(a2), 0);
- r0 = vmlaq_lane_f32( r0, my, vget_low_f32(a0), 1);
- r1 = vmlaq_lane_f32( r1, my, vget_low_f32(a1), 1);
- r2 = vmlaq_lane_f32( r2, my, vget_low_f32(a2), 1);
- r0 = vmlaq_lane_f32( r0, mz, vget_high_f32(a0), 0);
- r1 = vmlaq_lane_f32( r1, mz, vget_high_f32(a1), 0);
- r2 = vmlaq_lane_f32( r2, mz, vget_high_f32(a2), 0);
- return btMatrix3x3( r0, r1, r2 );
-
+ float32x4_t a0 = m_el[0].mVec128;
+ float32x4_t a1 = m_el[1].mVec128;
+ float32x4_t a2 = m_el[2].mVec128;
+
+ btMatrix3x3 mT = m.transpose(); // we rely on transpose() zeroing w channel so that we don't have to do it here
+ float32x4_t mx = mT[0].mVec128;
+ float32x4_t my = mT[1].mVec128;
+ float32x4_t mz = mT[2].mVec128;
+
+ float32x4_t r0 = vmulq_lane_f32(mx, vget_low_f32(a0), 0);
+ float32x4_t r1 = vmulq_lane_f32(mx, vget_low_f32(a1), 0);
+ float32x4_t r2 = vmulq_lane_f32(mx, vget_low_f32(a2), 0);
+ r0 = vmlaq_lane_f32(r0, my, vget_low_f32(a0), 1);
+ r1 = vmlaq_lane_f32(r1, my, vget_low_f32(a1), 1);
+ r2 = vmlaq_lane_f32(r2, my, vget_low_f32(a2), 1);
+ r0 = vmlaq_lane_f32(r0, mz, vget_high_f32(a0), 0);
+ r1 = vmlaq_lane_f32(r1, mz, vget_high_f32(a1), 0);
+ r2 = vmlaq_lane_f32(r2, mz, vget_high_f32(a2), 0);
+ return btMatrix3x3(r0, r1, r2);
+
#else
return btMatrix3x3(
m_el[0].dot(m[0]), m_el[0].dot(m[1]), m_el[0].dot(m[2]),
@@ -1193,139 +1188,138 @@ btMatrix3x3::timesTranspose(const btMatrix3x3& m) const
#endif
}
-SIMD_FORCE_INLINE btVector3
-operator*(const btMatrix3x3& m, const btVector3& v)
+SIMD_FORCE_INLINE btVector3
+operator*(const btMatrix3x3& m, const btVector3& v)
{
-#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))|| defined (BT_USE_NEON)
- return v.dot3(m[0], m[1], m[2]);
+#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
+ return v.dot3(m[0], m[1], m[2]);
#else
return btVector3(m[0].dot(v), m[1].dot(v), m[2].dot(v));
#endif
}
-
SIMD_FORCE_INLINE btVector3
operator*(const btVector3& v, const btMatrix3x3& m)
{
-#if defined BT_USE_SIMD_VECTOR3 && (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))
+#if defined BT_USE_SIMD_VECTOR3 && (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))
+
+ const __m128 vv = v.mVec128;
- const __m128 vv = v.mVec128;
+ __m128 c0 = bt_splat_ps(vv, 0);
+ __m128 c1 = bt_splat_ps(vv, 1);
+ __m128 c2 = bt_splat_ps(vv, 2);
- __m128 c0 = bt_splat_ps( vv, 0);
- __m128 c1 = bt_splat_ps( vv, 1);
- __m128 c2 = bt_splat_ps( vv, 2);
+ c0 = _mm_mul_ps(c0, _mm_and_ps(m[0].mVec128, btvFFF0fMask));
+ c1 = _mm_mul_ps(c1, _mm_and_ps(m[1].mVec128, btvFFF0fMask));
+ c0 = _mm_add_ps(c0, c1);
+ c2 = _mm_mul_ps(c2, _mm_and_ps(m[2].mVec128, btvFFF0fMask));
- c0 = _mm_mul_ps(c0, _mm_and_ps(m[0].mVec128, btvFFF0fMask) );
- c1 = _mm_mul_ps(c1, _mm_and_ps(m[1].mVec128, btvFFF0fMask) );
- c0 = _mm_add_ps(c0, c1);
- c2 = _mm_mul_ps(c2, _mm_and_ps(m[2].mVec128, btvFFF0fMask) );
-
- return btVector3(_mm_add_ps(c0, c2));
+ return btVector3(_mm_add_ps(c0, c2));
#elif defined(BT_USE_NEON)
- const float32x4_t vv = v.mVec128;
- const float32x2_t vlo = vget_low_f32(vv);
- const float32x2_t vhi = vget_high_f32(vv);
-
- float32x4_t c0, c1, c2;
-
- c0 = (float32x4_t) vandq_s32((int32x4_t)m[0].mVec128, btvFFF0Mask);
- c1 = (float32x4_t) vandq_s32((int32x4_t)m[1].mVec128, btvFFF0Mask);
- c2 = (float32x4_t) vandq_s32((int32x4_t)m[2].mVec128, btvFFF0Mask);
-
- c0 = vmulq_lane_f32(c0, vlo, 0);
- c1 = vmulq_lane_f32(c1, vlo, 1);
- c2 = vmulq_lane_f32(c2, vhi, 0);
- c0 = vaddq_f32(c0, c1);
- c0 = vaddq_f32(c0, c2);
-
- return btVector3(c0);
+ const float32x4_t vv = v.mVec128;
+ const float32x2_t vlo = vget_low_f32(vv);
+ const float32x2_t vhi = vget_high_f32(vv);
+
+ float32x4_t c0, c1, c2;
+
+ c0 = (float32x4_t)vandq_s32((int32x4_t)m[0].mVec128, btvFFF0Mask);
+ c1 = (float32x4_t)vandq_s32((int32x4_t)m[1].mVec128, btvFFF0Mask);
+ c2 = (float32x4_t)vandq_s32((int32x4_t)m[2].mVec128, btvFFF0Mask);
+
+ c0 = vmulq_lane_f32(c0, vlo, 0);
+ c1 = vmulq_lane_f32(c1, vlo, 1);
+ c2 = vmulq_lane_f32(c2, vhi, 0);
+ c0 = vaddq_f32(c0, c1);
+ c0 = vaddq_f32(c0, c2);
+
+ return btVector3(c0);
#else
return btVector3(m.tdotx(v), m.tdoty(v), m.tdotz(v));
#endif
}
-SIMD_FORCE_INLINE btMatrix3x3
+SIMD_FORCE_INLINE btMatrix3x3
operator*(const btMatrix3x3& m1, const btMatrix3x3& m2)
{
-#if defined BT_USE_SIMD_VECTOR3 && (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))
-
- __m128 m10 = m1[0].mVec128;
- __m128 m11 = m1[1].mVec128;
- __m128 m12 = m1[2].mVec128;
-
- __m128 m2v = _mm_and_ps(m2[0].mVec128, btvFFF0fMask);
-
- __m128 c0 = bt_splat_ps( m10, 0);
- __m128 c1 = bt_splat_ps( m11, 0);
- __m128 c2 = bt_splat_ps( m12, 0);
-
- c0 = _mm_mul_ps(c0, m2v);
- c1 = _mm_mul_ps(c1, m2v);
- c2 = _mm_mul_ps(c2, m2v);
-
- m2v = _mm_and_ps(m2[1].mVec128, btvFFF0fMask);
-
- __m128 c0_1 = bt_splat_ps( m10, 1);
- __m128 c1_1 = bt_splat_ps( m11, 1);
- __m128 c2_1 = bt_splat_ps( m12, 1);
-
- c0_1 = _mm_mul_ps(c0_1, m2v);
- c1_1 = _mm_mul_ps(c1_1, m2v);
- c2_1 = _mm_mul_ps(c2_1, m2v);
-
- m2v = _mm_and_ps(m2[2].mVec128, btvFFF0fMask);
-
- c0 = _mm_add_ps(c0, c0_1);
- c1 = _mm_add_ps(c1, c1_1);
- c2 = _mm_add_ps(c2, c2_1);
-
- m10 = bt_splat_ps( m10, 2);
- m11 = bt_splat_ps( m11, 2);
- m12 = bt_splat_ps( m12, 2);
-
- m10 = _mm_mul_ps(m10, m2v);
- m11 = _mm_mul_ps(m11, m2v);
- m12 = _mm_mul_ps(m12, m2v);
-
- c0 = _mm_add_ps(c0, m10);
- c1 = _mm_add_ps(c1, m11);
- c2 = _mm_add_ps(c2, m12);
-
- return btMatrix3x3(c0, c1, c2);
+#if defined BT_USE_SIMD_VECTOR3 && (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))
+
+ __m128 m10 = m1[0].mVec128;
+ __m128 m11 = m1[1].mVec128;
+ __m128 m12 = m1[2].mVec128;
+
+ __m128 m2v = _mm_and_ps(m2[0].mVec128, btvFFF0fMask);
+
+ __m128 c0 = bt_splat_ps(m10, 0);
+ __m128 c1 = bt_splat_ps(m11, 0);
+ __m128 c2 = bt_splat_ps(m12, 0);
+
+ c0 = _mm_mul_ps(c0, m2v);
+ c1 = _mm_mul_ps(c1, m2v);
+ c2 = _mm_mul_ps(c2, m2v);
+
+ m2v = _mm_and_ps(m2[1].mVec128, btvFFF0fMask);
+
+ __m128 c0_1 = bt_splat_ps(m10, 1);
+ __m128 c1_1 = bt_splat_ps(m11, 1);
+ __m128 c2_1 = bt_splat_ps(m12, 1);
+
+ c0_1 = _mm_mul_ps(c0_1, m2v);
+ c1_1 = _mm_mul_ps(c1_1, m2v);
+ c2_1 = _mm_mul_ps(c2_1, m2v);
+
+ m2v = _mm_and_ps(m2[2].mVec128, btvFFF0fMask);
+
+ c0 = _mm_add_ps(c0, c0_1);
+ c1 = _mm_add_ps(c1, c1_1);
+ c2 = _mm_add_ps(c2, c2_1);
+
+ m10 = bt_splat_ps(m10, 2);
+ m11 = bt_splat_ps(m11, 2);
+ m12 = bt_splat_ps(m12, 2);
+
+ m10 = _mm_mul_ps(m10, m2v);
+ m11 = _mm_mul_ps(m11, m2v);
+ m12 = _mm_mul_ps(m12, m2v);
+
+ c0 = _mm_add_ps(c0, m10);
+ c1 = _mm_add_ps(c1, m11);
+ c2 = _mm_add_ps(c2, m12);
+
+ return btMatrix3x3(c0, c1, c2);
#elif defined(BT_USE_NEON)
- float32x4_t rv0, rv1, rv2;
- float32x4_t v0, v1, v2;
- float32x4_t mv0, mv1, mv2;
-
- v0 = m1[0].mVec128;
- v1 = m1[1].mVec128;
- v2 = m1[2].mVec128;
-
- mv0 = (float32x4_t) vandq_s32((int32x4_t)m2[0].mVec128, btvFFF0Mask);
- mv1 = (float32x4_t) vandq_s32((int32x4_t)m2[1].mVec128, btvFFF0Mask);
- mv2 = (float32x4_t) vandq_s32((int32x4_t)m2[2].mVec128, btvFFF0Mask);
-
- rv0 = vmulq_lane_f32(mv0, vget_low_f32(v0), 0);
- rv1 = vmulq_lane_f32(mv0, vget_low_f32(v1), 0);
- rv2 = vmulq_lane_f32(mv0, vget_low_f32(v2), 0);
-
- rv0 = vmlaq_lane_f32(rv0, mv1, vget_low_f32(v0), 1);
- rv1 = vmlaq_lane_f32(rv1, mv1, vget_low_f32(v1), 1);
- rv2 = vmlaq_lane_f32(rv2, mv1, vget_low_f32(v2), 1);
-
- rv0 = vmlaq_lane_f32(rv0, mv2, vget_high_f32(v0), 0);
- rv1 = vmlaq_lane_f32(rv1, mv2, vget_high_f32(v1), 0);
- rv2 = vmlaq_lane_f32(rv2, mv2, vget_high_f32(v2), 0);
+ float32x4_t rv0, rv1, rv2;
+ float32x4_t v0, v1, v2;
+ float32x4_t mv0, mv1, mv2;
+
+ v0 = m1[0].mVec128;
+ v1 = m1[1].mVec128;
+ v2 = m1[2].mVec128;
+
+ mv0 = (float32x4_t)vandq_s32((int32x4_t)m2[0].mVec128, btvFFF0Mask);
+ mv1 = (float32x4_t)vandq_s32((int32x4_t)m2[1].mVec128, btvFFF0Mask);
+ mv2 = (float32x4_t)vandq_s32((int32x4_t)m2[2].mVec128, btvFFF0Mask);
+
+ rv0 = vmulq_lane_f32(mv0, vget_low_f32(v0), 0);
+ rv1 = vmulq_lane_f32(mv0, vget_low_f32(v1), 0);
+ rv2 = vmulq_lane_f32(mv0, vget_low_f32(v2), 0);
+
+ rv0 = vmlaq_lane_f32(rv0, mv1, vget_low_f32(v0), 1);
+ rv1 = vmlaq_lane_f32(rv1, mv1, vget_low_f32(v1), 1);
+ rv2 = vmlaq_lane_f32(rv2, mv1, vget_low_f32(v2), 1);
+
+ rv0 = vmlaq_lane_f32(rv0, mv2, vget_high_f32(v0), 0);
+ rv1 = vmlaq_lane_f32(rv1, mv2, vget_high_f32(v1), 0);
+ rv2 = vmlaq_lane_f32(rv2, mv2, vget_high_f32(v2), 0);
return btMatrix3x3(rv0, rv1, rv2);
-
-#else
+
+#else
return btMatrix3x3(
- m2.tdotx( m1[0]), m2.tdoty( m1[0]), m2.tdotz( m1[0]),
- m2.tdotx( m1[1]), m2.tdoty( m1[1]), m2.tdotz( m1[1]),
- m2.tdotx( m1[2]), m2.tdoty( m1[2]), m2.tdotz( m1[2]));
+ m2.tdotx(m1[0]), m2.tdoty(m1[0]), m2.tdotz(m1[0]),
+ m2.tdotx(m1[1]), m2.tdoty(m1[1]), m2.tdotz(m1[1]),
+ m2.tdotx(m1[2]), m2.tdoty(m1[2]), m2.tdotz(m1[2]));
#endif
}
@@ -1348,73 +1342,67 @@ m1[0][2] * m2[0][2] + m1[1][2] * m2[1][2] + m1[2][2] * m2[2][2]);
* It will test all elements are equal. */
SIMD_FORCE_INLINE bool operator==(const btMatrix3x3& m1, const btMatrix3x3& m2)
{
-#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))
+#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))
+
+ __m128 c0, c1, c2;
- __m128 c0, c1, c2;
+ c0 = _mm_cmpeq_ps(m1[0].mVec128, m2[0].mVec128);
+ c1 = _mm_cmpeq_ps(m1[1].mVec128, m2[1].mVec128);
+ c2 = _mm_cmpeq_ps(m1[2].mVec128, m2[2].mVec128);
- c0 = _mm_cmpeq_ps(m1[0].mVec128, m2[0].mVec128);
- c1 = _mm_cmpeq_ps(m1[1].mVec128, m2[1].mVec128);
- c2 = _mm_cmpeq_ps(m1[2].mVec128, m2[2].mVec128);
-
- c0 = _mm_and_ps(c0, c1);
- c0 = _mm_and_ps(c0, c2);
+ c0 = _mm_and_ps(c0, c1);
+ c0 = _mm_and_ps(c0, c2);
int m = _mm_movemask_ps((__m128)c0);
return (0x7 == (m & 0x7));
-
-#else
- return
- ( m1[0][0] == m2[0][0] && m1[1][0] == m2[1][0] && m1[2][0] == m2[2][0] &&
- m1[0][1] == m2[0][1] && m1[1][1] == m2[1][1] && m1[2][1] == m2[2][1] &&
- m1[0][2] == m2[0][2] && m1[1][2] == m2[1][2] && m1[2][2] == m2[2][2] );
+
+#else
+ return (m1[0][0] == m2[0][0] && m1[1][0] == m2[1][0] && m1[2][0] == m2[2][0] &&
+ m1[0][1] == m2[0][1] && m1[1][1] == m2[1][1] && m1[2][1] == m2[2][1] &&
+ m1[0][2] == m2[0][2] && m1[1][2] == m2[1][2] && m1[2][2] == m2[2][2]);
#endif
}
///for serialization
-struct btMatrix3x3FloatData
+struct btMatrix3x3FloatData
{
btVector3FloatData m_el[3];
};
///for serialization
-struct btMatrix3x3DoubleData
+struct btMatrix3x3DoubleData
{
btVector3DoubleData m_el[3];
};
-
-
-
-SIMD_FORCE_INLINE void btMatrix3x3::serialize(struct btMatrix3x3Data& dataOut) const
+SIMD_FORCE_INLINE void btMatrix3x3::serialize(struct btMatrix3x3Data& dataOut) const
{
- for (int i=0;i<3;i++)
+ for (int i = 0; i < 3; i++)
m_el[i].serialize(dataOut.m_el[i]);
}
-SIMD_FORCE_INLINE void btMatrix3x3::serializeFloat(struct btMatrix3x3FloatData& dataOut) const
+SIMD_FORCE_INLINE void btMatrix3x3::serializeFloat(struct btMatrix3x3FloatData& dataOut) const
{
- for (int i=0;i<3;i++)
+ for (int i = 0; i < 3; i++)
m_el[i].serializeFloat(dataOut.m_el[i]);
}
-
-SIMD_FORCE_INLINE void btMatrix3x3::deSerialize(const struct btMatrix3x3Data& dataIn)
+SIMD_FORCE_INLINE void btMatrix3x3::deSerialize(const struct btMatrix3x3Data& dataIn)
{
- for (int i=0;i<3;i++)
+ for (int i = 0; i < 3; i++)
m_el[i].deSerialize(dataIn.m_el[i]);
}
-SIMD_FORCE_INLINE void btMatrix3x3::deSerializeFloat(const struct btMatrix3x3FloatData& dataIn)
+SIMD_FORCE_INLINE void btMatrix3x3::deSerializeFloat(const struct btMatrix3x3FloatData& dataIn)
{
- for (int i=0;i<3;i++)
+ for (int i = 0; i < 3; i++)
m_el[i].deSerializeFloat(dataIn.m_el[i]);
}
-SIMD_FORCE_INLINE void btMatrix3x3::deSerializeDouble(const struct btMatrix3x3DoubleData& dataIn)
+SIMD_FORCE_INLINE void btMatrix3x3::deSerializeDouble(const struct btMatrix3x3DoubleData& dataIn)
{
- for (int i=0;i<3;i++)
+ for (int i = 0; i < 3; i++)
m_el[i].deSerializeDouble(dataIn.m_el[i]);
}
-#endif //BT_MATRIX3x3_H
-
+#endif //BT_MATRIX3x3_H
diff --git a/thirdparty/bullet/LinearMath/btMatrixX.h b/thirdparty/bullet/LinearMath/btMatrixX.h
index 42caed42ef..9df9e49469 100644
--- a/thirdparty/bullet/LinearMath/btMatrixX.h
+++ b/thirdparty/bullet/LinearMath/btMatrixX.h
@@ -24,24 +24,23 @@ subject to the following restrictions:
//#define BT_DEBUG_OSTREAM
#ifdef BT_DEBUG_OSTREAM
#include <iostream>
-#include <iomanip> // std::setw
-#endif //BT_DEBUG_OSTREAM
+#include <iomanip> // std::setw
+#endif //BT_DEBUG_OSTREAM
class btIntSortPredicate
{
- public:
- bool operator() ( const int& a, const int& b ) const
- {
- return a < b;
- }
+public:
+ bool operator()(const int& a, const int& b) const
+ {
+ return a < b;
+ }
};
-
template <typename T>
struct btVectorX
{
- btAlignedObjectArray<T> m_storage;
-
+ btAlignedObjectArray<T> m_storage;
+
btVectorX()
{
}
@@ -49,7 +48,7 @@ struct btVectorX
{
m_storage.resize(numRows);
}
-
+
void resize(int rows)
{
m_storage.resize(rows);
@@ -66,13 +65,13 @@ struct btVectorX
{
return rows();
}
-
+
T nrm2() const
{
T norm = T(0);
-
+
int nn = rows();
-
+
{
if (nn == 1)
{
@@ -82,11 +81,11 @@ struct btVectorX
{
T scale = 0.0;
T ssq = 1.0;
-
+
/* The following loop is equivalent to this call to the LAPACK
auxiliary routine: CALL SLASSQ( N, X, INCX, SCALE, SSQ ) */
-
- for (int ix=0;ix<nn;ix++)
+
+ for (int ix = 0; ix < nn; ix++)
{
if ((*this)[ix] != 0.0)
{
@@ -110,38 +109,36 @@ struct btVectorX
}
}
return norm;
-
}
- void setZero()
+ void setZero()
{
if (m_storage.size())
{
// for (int i=0;i<m_storage.size();i++)
// m_storage[i]=0;
//memset(&m_storage[0],0,sizeof(T)*m_storage.size());
- btSetZero(&m_storage[0],m_storage.size());
+ btSetZero(&m_storage[0], m_storage.size());
}
}
- const T& operator[] (int index) const
+ const T& operator[](int index) const
{
return m_storage[index];
}
-
- T& operator[] (int index)
+
+ T& operator[](int index)
{
return m_storage[index];
}
-
+
T* getBufferPointerWritable()
{
return m_storage.size() ? &m_storage[0] : 0;
}
-
+
const T* getBufferPointer() const
{
return m_storage.size() ? &m_storage[0] : 0;
}
-
};
/*
template <typename T>
@@ -151,8 +148,7 @@ struct btVectorX
}
*/
-
-template <typename T>
+template <typename T>
struct btMatrixX
{
int m_rows;
@@ -161,10 +157,10 @@ struct btMatrixX
int m_resizeOperations;
int m_setElemOperations;
- btAlignedObjectArray<T> m_storage;
- mutable btAlignedObjectArray< btAlignedObjectArray<int> > m_rowNonZeroElements1;
+ btAlignedObjectArray<T> m_storage;
+ mutable btAlignedObjectArray<btAlignedObjectArray<int> > m_rowNonZeroElements1;
- T* getBufferPointerWritable()
+ T* getBufferPointerWritable()
{
return m_storage.size() ? &m_storage[0] : 0;
}
@@ -174,21 +170,21 @@ struct btMatrixX
return m_storage.size() ? &m_storage[0] : 0;
}
btMatrixX()
- :m_rows(0),
- m_cols(0),
- m_operations(0),
- m_resizeOperations(0),
- m_setElemOperations(0)
+ : m_rows(0),
+ m_cols(0),
+ m_operations(0),
+ m_resizeOperations(0),
+ m_setElemOperations(0)
{
}
- btMatrixX(int rows,int cols)
- :m_rows(rows),
- m_cols(cols),
- m_operations(0),
- m_resizeOperations(0),
- m_setElemOperations(0)
+ btMatrixX(int rows, int cols)
+ : m_rows(rows),
+ m_cols(cols),
+ m_operations(0),
+ m_resizeOperations(0),
+ m_setElemOperations(0)
{
- resize(rows,cols);
+ resize(rows, cols);
}
void resize(int rows, int cols)
{
@@ -197,7 +193,7 @@ struct btMatrixX
m_cols = cols;
{
BT_PROFILE("m_storage.resize");
- m_storage.resize(rows*cols);
+ m_storage.resize(rows * cols);
}
}
int cols() const
@@ -215,108 +211,99 @@ struct btMatrixX
}
*/
- void addElem(int row,int col, T val)
+ void addElem(int row, int col, T val)
{
if (val)
{
- if (m_storage[col+row*m_cols]==0.f)
+ if (m_storage[col + row * m_cols] == 0.f)
{
- setElem(row,col,val);
- } else
+ setElem(row, col, val);
+ }
+ else
{
- m_storage[row*m_cols+col] += val;
+ m_storage[row * m_cols + col] += val;
}
}
}
-
-
- void setElem(int row,int col, T val)
+
+ void setElem(int row, int col, T val)
{
m_setElemOperations++;
- m_storage[row*m_cols+col] = val;
+ m_storage[row * m_cols + col] = val;
}
-
- void mulElem(int row,int col, T val)
+
+ void mulElem(int row, int col, T val)
{
m_setElemOperations++;
//mul doesn't change sparsity info
- m_storage[row*m_cols+col] *= val;
+ m_storage[row * m_cols + col] *= val;
}
-
-
-
-
+
void copyLowerToUpperTriangle()
{
- int count=0;
- for (int row=0;row<rows();row++)
+ int count = 0;
+ for (int row = 0; row < rows(); row++)
{
- for (int col=0;col<row;col++)
+ for (int col = 0; col < row; col++)
{
- setElem(col,row, (*this)(row,col));
+ setElem(col, row, (*this)(row, col));
count++;
-
}
}
//printf("copyLowerToUpperTriangle copied %d elements out of %dx%d=%d\n", count,rows(),cols(),cols()*rows());
}
-
- const T& operator() (int row,int col) const
+
+ const T& operator()(int row, int col) const
{
- return m_storage[col+row*m_cols];
+ return m_storage[col + row * m_cols];
}
-
void setZero()
{
{
BT_PROFILE("storage=0");
- btSetZero(&m_storage[0],m_storage.size());
+ btSetZero(&m_storage[0], m_storage.size());
//memset(&m_storage[0],0,sizeof(T)*m_storage.size());
//for (int i=0;i<m_storage.size();i++)
- // m_storage[i]=0;
+ // m_storage[i]=0;
}
}
-
+
void setIdentity()
{
btAssert(rows() == cols());
-
+
setZero();
- for (int row=0;row<rows();row++)
+ for (int row = 0; row < rows(); row++)
{
- setElem(row,row,1);
+ setElem(row, row, 1);
}
}
-
-
- void printMatrix(const char* msg)
+ void printMatrix(const char* msg)
{
- printf("%s ---------------------\n",msg);
- for (int i=0;i<rows();i++)
+ printf("%s ---------------------\n", msg);
+ for (int i = 0; i < rows(); i++)
{
printf("\n");
- for (int j=0;j<cols();j++)
+ for (int j = 0; j < cols(); j++)
{
- printf("%2.1f\t",(*this)(i,j));
+ printf("%2.1f\t", (*this)(i, j));
}
}
printf("\n---------------------\n");
-
}
-
void rowComputeNonZeroElements() const
{
m_rowNonZeroElements1.resize(rows());
- for (int i=0;i<rows();i++)
+ for (int i = 0; i < rows(); i++)
{
m_rowNonZeroElements1[i].resize(0);
- for (int j=0;j<cols();j++)
+ for (int j = 0; j < cols(); j++)
{
- if ((*this)(i,j)!=0.f)
+ if ((*this)(i, j) != 0.f)
{
m_rowNonZeroElements1[i].push_back(j);
}
@@ -326,54 +313,52 @@ struct btMatrixX
btMatrixX transpose() const
{
//transpose is optimized for sparse matrices
- btMatrixX tr(m_cols,m_rows);
+ btMatrixX tr(m_cols, m_rows);
tr.setZero();
- for (int i=0;i<m_cols;i++)
- for (int j=0;j<m_rows;j++)
+ for (int i = 0; i < m_cols; i++)
+ for (int j = 0; j < m_rows; j++)
{
- T v = (*this)(j,i);
+ T v = (*this)(j, i);
if (v)
{
- tr.setElem(i,j,v);
+ tr.setElem(i, j, v);
}
}
return tr;
}
-
btMatrixX operator*(const btMatrixX& other)
{
//btMatrixX*btMatrixX implementation, brute force
btAssert(cols() == other.rows());
- btMatrixX res(rows(),other.cols());
+ btMatrixX res(rows(), other.cols());
res.setZero();
-// BT_PROFILE("btMatrixX mul");
- for (int j=0; j < res.cols(); ++j)
+ // BT_PROFILE("btMatrixX mul");
+ for (int j = 0; j < res.cols(); ++j)
{
{
- for (int i=0; i < res.rows(); ++i)
+ for (int i = 0; i < res.rows(); ++i)
{
- T dotProd=0;
-// T dotProd2=0;
+ T dotProd = 0;
+ // T dotProd2=0;
//int waste=0,waste2=0;
{
-// bool useOtherCol = true;
+ // bool useOtherCol = true;
{
- for (int v=0;v<rows();v++)
+ for (int v = 0; v < rows(); v++)
{
- T w = (*this)(i,v);
- if (other(v,j)!=0.f)
+ T w = (*this)(i, v);
+ if (other(v, j) != 0.f)
{
- dotProd+=w*other(v,j);
+ dotProd += w * other(v, j);
}
-
}
}
}
if (dotProd)
- res.setElem(i,j,dotProd);
+ res.setElem(i, j, dotProd);
}
}
}
@@ -381,174 +366,166 @@ struct btMatrixX
}
// this assumes the 4th and 8th rows of B and C are zero.
- void multiplyAdd2_p8r (const btScalar *B, const btScalar *C, int numRows, int numRowsOther ,int row, int col)
+ void multiplyAdd2_p8r(const btScalar* B, const btScalar* C, int numRows, int numRowsOther, int row, int col)
{
- const btScalar *bb = B;
- for ( int i = 0;i<numRows;i++)
+ const btScalar* bb = B;
+ for (int i = 0; i < numRows; i++)
{
- const btScalar *cc = C;
- for ( int j = 0;j<numRowsOther;j++)
+ const btScalar* cc = C;
+ for (int j = 0; j < numRowsOther; j++)
{
btScalar sum;
- sum = bb[0]*cc[0];
- sum += bb[1]*cc[1];
- sum += bb[2]*cc[2];
- sum += bb[4]*cc[4];
- sum += bb[5]*cc[5];
- sum += bb[6]*cc[6];
- addElem(row+i,col+j,sum);
+ sum = bb[0] * cc[0];
+ sum += bb[1] * cc[1];
+ sum += bb[2] * cc[2];
+ sum += bb[4] * cc[4];
+ sum += bb[5] * cc[5];
+ sum += bb[6] * cc[6];
+ addElem(row + i, col + j, sum);
cc += 8;
}
bb += 8;
}
}
- void multiply2_p8r (const btScalar *B, const btScalar *C, int numRows, int numRowsOther, int row, int col)
+ void multiply2_p8r(const btScalar* B, const btScalar* C, int numRows, int numRowsOther, int row, int col)
{
- btAssert (numRows>0 && numRowsOther>0 && B && C);
- const btScalar *bb = B;
- for ( int i = 0;i<numRows;i++)
+ btAssert(numRows > 0 && numRowsOther > 0 && B && C);
+ const btScalar* bb = B;
+ for (int i = 0; i < numRows; i++)
{
- const btScalar *cc = C;
- for ( int j = 0;j<numRowsOther;j++)
+ const btScalar* cc = C;
+ for (int j = 0; j < numRowsOther; j++)
{
btScalar sum;
- sum = bb[0]*cc[0];
- sum += bb[1]*cc[1];
- sum += bb[2]*cc[2];
- sum += bb[4]*cc[4];
- sum += bb[5]*cc[5];
- sum += bb[6]*cc[6];
- setElem(row+i,col+j,sum);
+ sum = bb[0] * cc[0];
+ sum += bb[1] * cc[1];
+ sum += bb[2] * cc[2];
+ sum += bb[4] * cc[4];
+ sum += bb[5] * cc[5];
+ sum += bb[6] * cc[6];
+ setElem(row + i, col + j, sum);
cc += 8;
}
bb += 8;
}
}
-
- void setSubMatrix(int rowstart,int colstart,int rowend,int colend,const T value)
+
+ void setSubMatrix(int rowstart, int colstart, int rowend, int colend, const T value)
{
- int numRows = rowend+1-rowstart;
- int numCols = colend+1-colstart;
-
- for (int row=0;row<numRows;row++)
+ int numRows = rowend + 1 - rowstart;
+ int numCols = colend + 1 - colstart;
+
+ for (int row = 0; row < numRows; row++)
{
- for (int col=0;col<numCols;col++)
+ for (int col = 0; col < numCols; col++)
{
- setElem(rowstart+row,colstart+col,value);
+ setElem(rowstart + row, colstart + col, value);
}
}
}
-
- void setSubMatrix(int rowstart,int colstart,int rowend,int colend,const btMatrixX& block)
+
+ void setSubMatrix(int rowstart, int colstart, int rowend, int colend, const btMatrixX& block)
{
- btAssert(rowend+1-rowstart == block.rows());
- btAssert(colend+1-colstart == block.cols());
- for (int row=0;row<block.rows();row++)
+ btAssert(rowend + 1 - rowstart == block.rows());
+ btAssert(colend + 1 - colstart == block.cols());
+ for (int row = 0; row < block.rows(); row++)
{
- for (int col=0;col<block.cols();col++)
+ for (int col = 0; col < block.cols(); col++)
{
- setElem(rowstart+row,colstart+col,block(row,col));
+ setElem(rowstart + row, colstart + col, block(row, col));
}
}
}
- void setSubMatrix(int rowstart,int colstart,int rowend,int colend,const btVectorX<T>& block)
+ void setSubMatrix(int rowstart, int colstart, int rowend, int colend, const btVectorX<T>& block)
{
- btAssert(rowend+1-rowstart == block.rows());
- btAssert(colend+1-colstart == block.cols());
- for (int row=0;row<block.rows();row++)
+ btAssert(rowend + 1 - rowstart == block.rows());
+ btAssert(colend + 1 - colstart == block.cols());
+ for (int row = 0; row < block.rows(); row++)
{
- for (int col=0;col<block.cols();col++)
+ for (int col = 0; col < block.cols(); col++)
{
- setElem(rowstart+row,colstart+col,block[row]);
+ setElem(rowstart + row, colstart + col, block[row]);
}
}
}
-
-
+
btMatrixX negative()
{
- btMatrixX neg(rows(),cols());
- for (int i=0;i<rows();i++)
- for (int j=0;j<cols();j++)
+ btMatrixX neg(rows(), cols());
+ for (int i = 0; i < rows(); i++)
+ for (int j = 0; j < cols(); j++)
{
- T v = (*this)(i,j);
- neg.setElem(i,j,-v);
+ T v = (*this)(i, j);
+ neg.setElem(i, j, -v);
}
return neg;
}
-
};
-
-
typedef btMatrixX<float> btMatrixXf;
typedef btVectorX<float> btVectorXf;
typedef btMatrixX<double> btMatrixXd;
typedef btVectorX<double> btVectorXd;
-
#ifdef BT_DEBUG_OSTREAM
-template <typename T>
-std::ostream& operator<< (std::ostream& os, const btMatrixX<T>& mat)
+template <typename T>
+std::ostream& operator<<(std::ostream& os, const btMatrixX<T>& mat)
+{
+ os << " [";
+ //printf("%s ---------------------\n",msg);
+ for (int i = 0; i < mat.rows(); i++)
{
-
- os << " [";
- //printf("%s ---------------------\n",msg);
- for (int i=0;i<mat.rows();i++)
+ for (int j = 0; j < mat.cols(); j++)
{
- for (int j=0;j<mat.cols();j++)
- {
- os << std::setw(12) << mat(i,j);
- }
- if (i!=mat.rows()-1)
- os << std::endl << " ";
+ os << std::setw(12) << mat(i, j);
}
- os << " ]";
- //printf("\n---------------------\n");
-
- return os;
+ if (i != mat.rows() - 1)
+ os << std::endl
+ << " ";
}
-template <typename T>
-std::ostream& operator<< (std::ostream& os, const btVectorX<T>& mat)
- {
-
- os << " [";
- //printf("%s ---------------------\n",msg);
- for (int i=0;i<mat.rows();i++)
- {
- os << std::setw(12) << mat[i];
- if (i!=mat.rows()-1)
- os << std::endl << " ";
- }
- os << " ]";
- //printf("\n---------------------\n");
+ os << " ]";
+ //printf("\n---------------------\n");
- return os;
+ return os;
+}
+template <typename T>
+std::ostream& operator<<(std::ostream& os, const btVectorX<T>& mat)
+{
+ os << " [";
+ //printf("%s ---------------------\n",msg);
+ for (int i = 0; i < mat.rows(); i++)
+ {
+ os << std::setw(12) << mat[i];
+ if (i != mat.rows() - 1)
+ os << std::endl
+ << " ";
}
+ os << " ]";
+ //printf("\n---------------------\n");
-#endif //BT_DEBUG_OSTREAM
+ return os;
+}
+#endif //BT_DEBUG_OSTREAM
inline void setElem(btMatrixXd& mat, int row, int col, double val)
{
- mat.setElem(row,col,val);
+ mat.setElem(row, col, val);
}
inline void setElem(btMatrixXf& mat, int row, int col, float val)
{
- mat.setElem(row,col,val);
+ mat.setElem(row, col, val);
}
#ifdef BT_USE_DOUBLE_PRECISION
- #define btVectorXu btVectorXd
- #define btMatrixXu btMatrixXd
+#define btVectorXu btVectorXd
+#define btMatrixXu btMatrixXd
#else
- #define btVectorXu btVectorXf
- #define btMatrixXu btMatrixXf
-#endif //BT_USE_DOUBLE_PRECISION
-
-
+#define btVectorXu btVectorXf
+#define btMatrixXu btMatrixXf
+#endif //BT_USE_DOUBLE_PRECISION
-#endif//BT_MATRIX_H_H
+#endif //BT_MATRIX_H_H
diff --git a/thirdparty/bullet/LinearMath/btMinMax.h b/thirdparty/bullet/LinearMath/btMinMax.h
index 5b436e9ba4..92fea0275a 100644
--- a/thirdparty/bullet/LinearMath/btMinMax.h
+++ b/thirdparty/bullet/LinearMath/btMinMax.h
@@ -12,60 +12,58 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
-
#ifndef BT_GEN_MINMAX_H
#define BT_GEN_MINMAX_H
#include "btScalar.h"
template <class T>
-SIMD_FORCE_INLINE const T& btMin(const T& a, const T& b)
+SIMD_FORCE_INLINE const T& btMin(const T& a, const T& b)
{
- return a < b ? a : b ;
+ return a < b ? a : b;
}
template <class T>
-SIMD_FORCE_INLINE const T& btMax(const T& a, const T& b)
+SIMD_FORCE_INLINE const T& btMax(const T& a, const T& b)
{
- return a > b ? a : b;
+ return a > b ? a : b;
}
template <class T>
-SIMD_FORCE_INLINE const T& btClamped(const T& a, const T& lb, const T& ub)
+SIMD_FORCE_INLINE const T& btClamped(const T& a, const T& lb, const T& ub)
{
- return a < lb ? lb : (ub < a ? ub : a);
+ return a < lb ? lb : (ub < a ? ub : a);
}
template <class T>
-SIMD_FORCE_INLINE void btSetMin(T& a, const T& b)
+SIMD_FORCE_INLINE void btSetMin(T& a, const T& b)
{
- if (b < a)
+ if (b < a)
{
a = b;
}
}
template <class T>
-SIMD_FORCE_INLINE void btSetMax(T& a, const T& b)
+SIMD_FORCE_INLINE void btSetMax(T& a, const T& b)
{
- if (a < b)
+ if (a < b)
{
a = b;
}
}
template <class T>
-SIMD_FORCE_INLINE void btClamp(T& a, const T& lb, const T& ub)
+SIMD_FORCE_INLINE void btClamp(T& a, const T& lb, const T& ub)
{
- if (a < lb)
+ if (a < lb)
{
- a = lb;
+ a = lb;
}
- else if (ub < a)
+ else if (ub < a)
{
a = ub;
}
}
-#endif //BT_GEN_MINMAX_H
+#endif //BT_GEN_MINMAX_H
diff --git a/thirdparty/bullet/LinearMath/btMotionState.h b/thirdparty/bullet/LinearMath/btMotionState.h
index 9431814090..ae6a51611d 100644
--- a/thirdparty/bullet/LinearMath/btMotionState.h
+++ b/thirdparty/bullet/LinearMath/btMotionState.h
@@ -20,21 +20,17 @@ subject to the following restrictions:
///The btMotionState interface class allows the dynamics world to synchronize and interpolate the updated world transforms with graphics
///For optimizations, potentially only moving objects get synchronized (using setWorldPosition/setWorldOrientation)
-class btMotionState
+class btMotionState
{
- public:
-
- virtual ~btMotionState()
- {
-
- }
-
- virtual void getWorldTransform(btTransform& worldTrans ) const =0;
-
- //Bullet only calls the update of worldtransform for active objects
- virtual void setWorldTransform(const btTransform& worldTrans)=0;
-
-
+public:
+ virtual ~btMotionState()
+ {
+ }
+
+ virtual void getWorldTransform(btTransform& worldTrans) const = 0;
+
+ //Bullet only calls the update of worldtransform for active objects
+ virtual void setWorldTransform(const btTransform& worldTrans) = 0;
};
-#endif //BT_MOTIONSTATE_H
+#endif //BT_MOTIONSTATE_H
diff --git a/thirdparty/bullet/LinearMath/btPolarDecomposition.cpp b/thirdparty/bullet/LinearMath/btPolarDecomposition.cpp
index b3664faa4e..d9c72a8014 100644
--- a/thirdparty/bullet/LinearMath/btPolarDecomposition.cpp
+++ b/thirdparty/bullet/LinearMath/btPolarDecomposition.cpp
@@ -3,96 +3,92 @@
namespace
{
- btScalar abs_column_sum(const btMatrix3x3& a, int i)
- {
- return btFabs(a[0][i]) + btFabs(a[1][i]) + btFabs(a[2][i]);
- }
-
- btScalar abs_row_sum(const btMatrix3x3& a, int i)
- {
- return btFabs(a[i][0]) + btFabs(a[i][1]) + btFabs(a[i][2]);
- }
-
- btScalar p1_norm(const btMatrix3x3& a)
- {
- const btScalar sum0 = abs_column_sum(a,0);
- const btScalar sum1 = abs_column_sum(a,1);
- const btScalar sum2 = abs_column_sum(a,2);
- return btMax(btMax(sum0, sum1), sum2);
- }
-
- btScalar pinf_norm(const btMatrix3x3& a)
- {
- const btScalar sum0 = abs_row_sum(a,0);
- const btScalar sum1 = abs_row_sum(a,1);
- const btScalar sum2 = abs_row_sum(a,2);
- return btMax(btMax(sum0, sum1), sum2);
- }
+btScalar abs_column_sum(const btMatrix3x3& a, int i)
+{
+ return btFabs(a[0][i]) + btFabs(a[1][i]) + btFabs(a[2][i]);
}
+btScalar abs_row_sum(const btMatrix3x3& a, int i)
+{
+ return btFabs(a[i][0]) + btFabs(a[i][1]) + btFabs(a[i][2]);
+}
+btScalar p1_norm(const btMatrix3x3& a)
+{
+ const btScalar sum0 = abs_column_sum(a, 0);
+ const btScalar sum1 = abs_column_sum(a, 1);
+ const btScalar sum2 = abs_column_sum(a, 2);
+ return btMax(btMax(sum0, sum1), sum2);
+}
+
+btScalar pinf_norm(const btMatrix3x3& a)
+{
+ const btScalar sum0 = abs_row_sum(a, 0);
+ const btScalar sum1 = abs_row_sum(a, 1);
+ const btScalar sum2 = abs_row_sum(a, 2);
+ return btMax(btMax(sum0, sum1), sum2);
+}
+} // namespace
btPolarDecomposition::btPolarDecomposition(btScalar tolerance, unsigned int maxIterations)
-: m_tolerance(tolerance)
-, m_maxIterations(maxIterations)
+ : m_tolerance(tolerance), m_maxIterations(maxIterations)
{
}
unsigned int btPolarDecomposition::decompose(const btMatrix3x3& a, btMatrix3x3& u, btMatrix3x3& h) const
{
- // Use the 'u' and 'h' matrices for intermediate calculations
- u = a;
- h = a.inverse();
-
- for (unsigned int i = 0; i < m_maxIterations; ++i)
- {
- const btScalar h_1 = p1_norm(h);
- const btScalar h_inf = pinf_norm(h);
- const btScalar u_1 = p1_norm(u);
- const btScalar u_inf = pinf_norm(u);
-
- const btScalar h_norm = h_1 * h_inf;
- const btScalar u_norm = u_1 * u_inf;
-
- // The matrix is effectively singular so we cannot invert it
- if (btFuzzyZero(h_norm) || btFuzzyZero(u_norm))
- break;
-
- const btScalar gamma = btPow(h_norm / u_norm, 0.25f);
- const btScalar inv_gamma = btScalar(1.0) / gamma;
-
- // Determine the delta to 'u'
- const btMatrix3x3 delta = (u * (gamma - btScalar(2.0)) + h.transpose() * inv_gamma) * btScalar(0.5);
-
- // Update the matrices
- u += delta;
- h = u.inverse();
-
- // Check for convergence
- if (p1_norm(delta) <= m_tolerance * u_1)
- {
- h = u.transpose() * a;
- h = (h + h.transpose()) * 0.5;
- return i;
- }
- }
-
- // The algorithm has failed to converge to the specified tolerance, but we
- // want to make sure that the matrices returned are in the right form.
- h = u.transpose() * a;
- h = (h + h.transpose()) * 0.5;
-
- return m_maxIterations;
+ // Use the 'u' and 'h' matrices for intermediate calculations
+ u = a;
+ h = a.inverse();
+
+ for (unsigned int i = 0; i < m_maxIterations; ++i)
+ {
+ const btScalar h_1 = p1_norm(h);
+ const btScalar h_inf = pinf_norm(h);
+ const btScalar u_1 = p1_norm(u);
+ const btScalar u_inf = pinf_norm(u);
+
+ const btScalar h_norm = h_1 * h_inf;
+ const btScalar u_norm = u_1 * u_inf;
+
+ // The matrix is effectively singular so we cannot invert it
+ if (btFuzzyZero(h_norm) || btFuzzyZero(u_norm))
+ break;
+
+ const btScalar gamma = btPow(h_norm / u_norm, 0.25f);
+ const btScalar inv_gamma = btScalar(1.0) / gamma;
+
+ // Determine the delta to 'u'
+ const btMatrix3x3 delta = (u * (gamma - btScalar(2.0)) + h.transpose() * inv_gamma) * btScalar(0.5);
+
+ // Update the matrices
+ u += delta;
+ h = u.inverse();
+
+ // Check for convergence
+ if (p1_norm(delta) <= m_tolerance * u_1)
+ {
+ h = u.transpose() * a;
+ h = (h + h.transpose()) * 0.5;
+ return i;
+ }
+ }
+
+ // The algorithm has failed to converge to the specified tolerance, but we
+ // want to make sure that the matrices returned are in the right form.
+ h = u.transpose() * a;
+ h = (h + h.transpose()) * 0.5;
+
+ return m_maxIterations;
}
unsigned int btPolarDecomposition::maxIterations() const
{
- return m_maxIterations;
+ return m_maxIterations;
}
unsigned int polarDecompose(const btMatrix3x3& a, btMatrix3x3& u, btMatrix3x3& h)
{
- static btPolarDecomposition polar;
- return polar.decompose(a, u, h);
+ static btPolarDecomposition polar;
+ return polar.decompose(a, u, h);
}
-
diff --git a/thirdparty/bullet/LinearMath/btPolarDecomposition.h b/thirdparty/bullet/LinearMath/btPolarDecomposition.h
index 1feea0f78e..bf29140a14 100644
--- a/thirdparty/bullet/LinearMath/btPolarDecomposition.h
+++ b/thirdparty/bullet/LinearMath/btPolarDecomposition.h
@@ -13,10 +13,8 @@
*/
class btPolarDecomposition
{
- public:
-
-
- /**
+public:
+ /**
* Creates an instance with optional parameters.
*
* @param tolerance - the tolerance used to determine convergence of the
@@ -24,10 +22,10 @@ class btPolarDecomposition
* @param maxIterations - the maximum number of iterations used to achieve
* convergence
*/
- btPolarDecomposition(btScalar tolerance = btScalar(0.0001),
- unsigned int maxIterations = 16);
+ btPolarDecomposition(btScalar tolerance = btScalar(0.0001),
+ unsigned int maxIterations = 16);
- /**
+ /**
* Decomposes a matrix into orthogonal and symmetric, positive-definite
* parts. If the number of iterations returned by this function is equal to
* the maximum number of iterations, the algorithm has failed to converge.
@@ -38,19 +36,19 @@ class btPolarDecomposition
*
* @return the number of iterations performed by the algorithm.
*/
- unsigned int decompose(const btMatrix3x3& a, btMatrix3x3& u, btMatrix3x3& h) const;
+ unsigned int decompose(const btMatrix3x3& a, btMatrix3x3& u, btMatrix3x3& h) const;
- /**
+ /**
* Returns the maximum number of iterations that this algorithm will perform
* to achieve convergence.
*
* @return maximum number of iterations
*/
- unsigned int maxIterations() const;
+ unsigned int maxIterations() const;
- private:
- btScalar m_tolerance;
- unsigned int m_maxIterations;
+private:
+ btScalar m_tolerance;
+ unsigned int m_maxIterations;
};
/**
@@ -66,7 +64,6 @@ class btPolarDecomposition
*
* @return the number of iterations performed by the algorithm.
*/
-unsigned int polarDecompose(const btMatrix3x3& a, btMatrix3x3& u, btMatrix3x3& h);
-
-#endif // POLARDECOMPOSITION_H
+unsigned int polarDecompose(const btMatrix3x3& a, btMatrix3x3& u, btMatrix3x3& h);
+#endif // POLARDECOMPOSITION_H
diff --git a/thirdparty/bullet/LinearMath/btPoolAllocator.h b/thirdparty/bullet/LinearMath/btPoolAllocator.h
index efdeda8ffc..4e7b49660a 100644
--- a/thirdparty/bullet/LinearMath/btPoolAllocator.h
+++ b/thirdparty/bullet/LinearMath/btPoolAllocator.h
@@ -12,7 +12,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#ifndef _BT_POOL_ALLOCATOR_H
#define _BT_POOL_ALLOCATOR_H
@@ -23,38 +22,38 @@ subject to the following restrictions:
///The btPoolAllocator class allows to efficiently allocate a large pool of objects, instead of dynamically allocating them separately.
class btPoolAllocator
{
- int m_elemSize;
- int m_maxElements;
- int m_freeCount;
- void* m_firstFree;
- unsigned char* m_pool;
- btSpinMutex m_mutex; // only used if BT_THREADSAFE
+ int m_elemSize;
+ int m_maxElements;
+ int m_freeCount;
+ void* m_firstFree;
+ unsigned char* m_pool;
+ btSpinMutex m_mutex; // only used if BT_THREADSAFE
public:
-
btPoolAllocator(int elemSize, int maxElements)
- :m_elemSize(elemSize),
- m_maxElements(maxElements)
+ : m_elemSize(elemSize),
+ m_maxElements(maxElements)
{
- m_pool = (unsigned char*) btAlignedAlloc( static_cast<unsigned int>(m_elemSize*m_maxElements),16);
+ m_pool = (unsigned char*)btAlignedAlloc(static_cast<unsigned int>(m_elemSize * m_maxElements), 16);
unsigned char* p = m_pool;
- m_firstFree = p;
- m_freeCount = m_maxElements;
- int count = m_maxElements;
- while (--count) {
- *(void**)p = (p + m_elemSize);
- p += m_elemSize;
- }
- *(void**)p = 0;
- }
+ m_firstFree = p;
+ m_freeCount = m_maxElements;
+ int count = m_maxElements;
+ while (--count)
+ {
+ *(void**)p = (p + m_elemSize);
+ p += m_elemSize;
+ }
+ *(void**)p = 0;
+ }
~btPoolAllocator()
{
- btAlignedFree( m_pool);
+ btAlignedFree(m_pool);
}
- int getFreeCount() const
+ int getFreeCount() const
{
return m_freeCount;
}
@@ -69,26 +68,27 @@ public:
return m_maxElements;
}
- void* allocate(int size)
+ void* allocate(int size)
{
// release mode fix
(void)size;
- btMutexLock(&m_mutex);
- btAssert(!size || size<=m_elemSize);
+ btMutexLock(&m_mutex);
+ btAssert(!size || size <= m_elemSize);
//btAssert(m_freeCount>0); // should return null if all full
- void* result = m_firstFree;
- if (NULL != m_firstFree)
- {
- m_firstFree = *(void**)m_firstFree;
- --m_freeCount;
- }
- btMutexUnlock(&m_mutex);
- return result;
+ void* result = m_firstFree;
+ if (NULL != m_firstFree)
+ {
+ m_firstFree = *(void**)m_firstFree;
+ --m_freeCount;
+ }
+ btMutexUnlock(&m_mutex);
+ return result;
}
bool validPtr(void* ptr)
{
- if (ptr) {
+ if (ptr)
+ {
if (((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize))
{
return true;
@@ -97,34 +97,34 @@ public:
return false;
}
- void freeMemory(void* ptr)
+ void freeMemory(void* ptr)
{
- if (ptr) {
- btAssert((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize);
-
- btMutexLock(&m_mutex);
- *(void**)ptr = m_firstFree;
- m_firstFree = ptr;
- ++m_freeCount;
- btMutexUnlock(&m_mutex);
- }
+ if (ptr)
+ {
+ btAssert((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize);
+
+ btMutexLock(&m_mutex);
+ *(void**)ptr = m_firstFree;
+ m_firstFree = ptr;
+ ++m_freeCount;
+ btMutexUnlock(&m_mutex);
+ }
}
- int getElementSize() const
+ int getElementSize() const
{
return m_elemSize;
}
- unsigned char* getPoolAddress()
+ unsigned char* getPoolAddress()
{
return m_pool;
}
- const unsigned char* getPoolAddress() const
+ const unsigned char* getPoolAddress() const
{
return m_pool;
}
-
};
-#endif //_BT_POOL_ALLOCATOR_H
+#endif //_BT_POOL_ALLOCATOR_H
diff --git a/thirdparty/bullet/LinearMath/btQuadWord.h b/thirdparty/bullet/LinearMath/btQuadWord.h
index fcfb3be444..ab2d3175ad 100644
--- a/thirdparty/bullet/LinearMath/btQuadWord.h
+++ b/thirdparty/bullet/LinearMath/btQuadWord.h
@@ -12,18 +12,13 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#ifndef BT_SIMD_QUADWORD_H
#define BT_SIMD_QUADWORD_H
#include "btScalar.h"
#include "btMinMax.h"
-
-
-
-
-#if defined (__CELLOS_LV2) && defined (__SPU__)
+#if defined(__CELLOS_LV2) && defined(__SPU__)
#include <altivec.h>
#endif
@@ -31,51 +26,53 @@ subject to the following restrictions:
* Some issues under PS3 Linux with IBM 2.1 SDK, gcc compiler prevent from using aligned quadword.
*/
#ifndef USE_LIBSPE2
-ATTRIBUTE_ALIGNED16(class) btQuadWord
+ATTRIBUTE_ALIGNED16(class)
+btQuadWord
#else
class btQuadWord
#endif
{
protected:
-
-#if defined (__SPU__) && defined (__CELLOS_LV2__)
+#if defined(__SPU__) && defined(__CELLOS_LV2__)
union {
vec_float4 mVec128;
- btScalar m_floats[4];
+ btScalar m_floats[4];
};
+
public:
- vec_float4 get128() const
+ vec_float4 get128() const
{
return mVec128;
}
+
protected:
-#else //__CELLOS_LV2__ __SPU__
+#else //__CELLOS_LV2__ __SPU__
-#if defined(BT_USE_SSE) || defined(BT_USE_NEON)
+#if defined(BT_USE_SSE) || defined(BT_USE_NEON)
union {
btSimdFloat4 mVec128;
- btScalar m_floats[4];
+ btScalar m_floats[4];
};
+
public:
- SIMD_FORCE_INLINE btSimdFloat4 get128() const
+ SIMD_FORCE_INLINE btSimdFloat4 get128() const
{
return mVec128;
}
- SIMD_FORCE_INLINE void set128(btSimdFloat4 v128)
+ SIMD_FORCE_INLINE void set128(btSimdFloat4 v128)
{
mVec128 = v128;
}
#else
- btScalar m_floats[4];
-#endif // BT_USE_SSE
+ btScalar m_floats[4];
+#endif // BT_USE_SSE
-#endif //__CELLOS_LV2__ __SPU__
+#endif //__CELLOS_LV2__ __SPU__
- public:
-
+public:
#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
- // Set Vector
+ // Set Vector
SIMD_FORCE_INLINE btQuadWord(const btSimdFloat4 vec)
{
mVec128 = vec;
@@ -88,157 +85,154 @@ public:
}
// Assignment Operator
- SIMD_FORCE_INLINE btQuadWord&
- operator=(const btQuadWord& v)
+ SIMD_FORCE_INLINE btQuadWord&
+ operator=(const btQuadWord& v)
{
mVec128 = v.mVec128;
-
+
return *this;
}
-
+
#endif
- /**@brief Return the x value */
- SIMD_FORCE_INLINE const btScalar& getX() const { return m_floats[0]; }
- /**@brief Return the y value */
- SIMD_FORCE_INLINE const btScalar& getY() const { return m_floats[1]; }
- /**@brief Return the z value */
- SIMD_FORCE_INLINE const btScalar& getZ() const { return m_floats[2]; }
- /**@brief Set the x value */
- SIMD_FORCE_INLINE void setX(btScalar _x) { m_floats[0] = _x;};
- /**@brief Set the y value */
- SIMD_FORCE_INLINE void setY(btScalar _y) { m_floats[1] = _y;};
- /**@brief Set the z value */
- SIMD_FORCE_INLINE void setZ(btScalar _z) { m_floats[2] = _z;};
- /**@brief Set the w value */
- SIMD_FORCE_INLINE void setW(btScalar _w) { m_floats[3] = _w;};
- /**@brief Return the x value */
- SIMD_FORCE_INLINE const btScalar& x() const { return m_floats[0]; }
- /**@brief Return the y value */
- SIMD_FORCE_INLINE const btScalar& y() const { return m_floats[1]; }
- /**@brief Return the z value */
- SIMD_FORCE_INLINE const btScalar& z() const { return m_floats[2]; }
- /**@brief Return the w value */
- SIMD_FORCE_INLINE const btScalar& w() const { return m_floats[3]; }
-
- //SIMD_FORCE_INLINE btScalar& operator[](int i) { return (&m_floats[0])[i]; }
+ /**@brief Return the x value */
+ SIMD_FORCE_INLINE const btScalar& getX() const { return m_floats[0]; }
+ /**@brief Return the y value */
+ SIMD_FORCE_INLINE const btScalar& getY() const { return m_floats[1]; }
+ /**@brief Return the z value */
+ SIMD_FORCE_INLINE const btScalar& getZ() const { return m_floats[2]; }
+ /**@brief Set the x value */
+ SIMD_FORCE_INLINE void setX(btScalar _x) { m_floats[0] = _x; };
+ /**@brief Set the y value */
+ SIMD_FORCE_INLINE void setY(btScalar _y) { m_floats[1] = _y; };
+ /**@brief Set the z value */
+ SIMD_FORCE_INLINE void setZ(btScalar _z) { m_floats[2] = _z; };
+ /**@brief Set the w value */
+ SIMD_FORCE_INLINE void setW(btScalar _w) { m_floats[3] = _w; };
+ /**@brief Return the x value */
+ SIMD_FORCE_INLINE const btScalar& x() const { return m_floats[0]; }
+ /**@brief Return the y value */
+ SIMD_FORCE_INLINE const btScalar& y() const { return m_floats[1]; }
+ /**@brief Return the z value */
+ SIMD_FORCE_INLINE const btScalar& z() const { return m_floats[2]; }
+ /**@brief Return the w value */
+ SIMD_FORCE_INLINE const btScalar& w() const { return m_floats[3]; }
+
+ //SIMD_FORCE_INLINE btScalar& operator[](int i) { return (&m_floats[0])[i]; }
//SIMD_FORCE_INLINE const btScalar& operator[](int i) const { return (&m_floats[0])[i]; }
///operator btScalar*() replaces operator[], using implicit conversion. We added operator != and operator == to avoid pointer comparisons.
- SIMD_FORCE_INLINE operator btScalar *() { return &m_floats[0]; }
- SIMD_FORCE_INLINE operator const btScalar *() const { return &m_floats[0]; }
+ SIMD_FORCE_INLINE operator btScalar*() { return &m_floats[0]; }
+ SIMD_FORCE_INLINE operator const btScalar*() const { return &m_floats[0]; }
- SIMD_FORCE_INLINE bool operator==(const btQuadWord& other) const
+ SIMD_FORCE_INLINE bool operator==(const btQuadWord& other) const
{
#ifdef BT_USE_SSE
- return (0xf == _mm_movemask_ps((__m128)_mm_cmpeq_ps(mVec128, other.mVec128)));
-#else
- return ((m_floats[3]==other.m_floats[3]) &&
- (m_floats[2]==other.m_floats[2]) &&
- (m_floats[1]==other.m_floats[1]) &&
- (m_floats[0]==other.m_floats[0]));
+ return (0xf == _mm_movemask_ps((__m128)_mm_cmpeq_ps(mVec128, other.mVec128)));
+#else
+ return ((m_floats[3] == other.m_floats[3]) &&
+ (m_floats[2] == other.m_floats[2]) &&
+ (m_floats[1] == other.m_floats[1]) &&
+ (m_floats[0] == other.m_floats[0]));
#endif
}
- SIMD_FORCE_INLINE bool operator!=(const btQuadWord& other) const
+ SIMD_FORCE_INLINE bool operator!=(const btQuadWord& other) const
{
return !(*this == other);
}
- /**@brief Set x,y,z and zero w
+ /**@brief Set x,y,z and zero w
* @param x Value of x
* @param y Value of y
* @param z Value of z
*/
- SIMD_FORCE_INLINE void setValue(const btScalar& _x, const btScalar& _y, const btScalar& _z)
- {
- m_floats[0]=_x;
- m_floats[1]=_y;
- m_floats[2]=_z;
- m_floats[3] = 0.f;
- }
+ SIMD_FORCE_INLINE void setValue(const btScalar& _x, const btScalar& _y, const btScalar& _z)
+ {
+ m_floats[0] = _x;
+ m_floats[1] = _y;
+ m_floats[2] = _z;
+ m_floats[3] = 0.f;
+ }
-/* void getValue(btScalar *m) const
+ /* void getValue(btScalar *m) const
{
m[0] = m_floats[0];
m[1] = m_floats[1];
m[2] = m_floats[2];
}
*/
-/**@brief Set the values
+ /**@brief Set the values
* @param x Value of x
* @param y Value of y
* @param z Value of z
* @param w Value of w
*/
- SIMD_FORCE_INLINE void setValue(const btScalar& _x, const btScalar& _y, const btScalar& _z,const btScalar& _w)
- {
- m_floats[0]=_x;
- m_floats[1]=_y;
- m_floats[2]=_z;
- m_floats[3]=_w;
- }
- /**@brief No initialization constructor */
- SIMD_FORCE_INLINE btQuadWord()
- // :m_floats[0](btScalar(0.)),m_floats[1](btScalar(0.)),m_floats[2](btScalar(0.)),m_floats[3](btScalar(0.))
- {
- }
-
- /**@brief Three argument constructor (zeros w)
+ SIMD_FORCE_INLINE void setValue(const btScalar& _x, const btScalar& _y, const btScalar& _z, const btScalar& _w)
+ {
+ m_floats[0] = _x;
+ m_floats[1] = _y;
+ m_floats[2] = _z;
+ m_floats[3] = _w;
+ }
+ /**@brief No initialization constructor */
+ SIMD_FORCE_INLINE btQuadWord()
+ // :m_floats[0](btScalar(0.)),m_floats[1](btScalar(0.)),m_floats[2](btScalar(0.)),m_floats[3](btScalar(0.))
+ {
+ }
+
+ /**@brief Three argument constructor (zeros w)
* @param x Value of x
* @param y Value of y
* @param z Value of z
*/
- SIMD_FORCE_INLINE btQuadWord(const btScalar& _x, const btScalar& _y, const btScalar& _z)
- {
- m_floats[0] = _x, m_floats[1] = _y, m_floats[2] = _z, m_floats[3] = 0.0f;
- }
+ SIMD_FORCE_INLINE btQuadWord(const btScalar& _x, const btScalar& _y, const btScalar& _z)
+ {
+ m_floats[0] = _x, m_floats[1] = _y, m_floats[2] = _z, m_floats[3] = 0.0f;
+ }
-/**@brief Initializing constructor
+ /**@brief Initializing constructor
* @param x Value of x
* @param y Value of y
* @param z Value of z
* @param w Value of w
*/
- SIMD_FORCE_INLINE btQuadWord(const btScalar& _x, const btScalar& _y, const btScalar& _z,const btScalar& _w)
- {
- m_floats[0] = _x, m_floats[1] = _y, m_floats[2] = _z, m_floats[3] = _w;
- }
+ SIMD_FORCE_INLINE btQuadWord(const btScalar& _x, const btScalar& _y, const btScalar& _z, const btScalar& _w)
+ {
+ m_floats[0] = _x, m_floats[1] = _y, m_floats[2] = _z, m_floats[3] = _w;
+ }
- /**@brief Set each element to the max of the current values and the values of another btQuadWord
+ /**@brief Set each element to the max of the current values and the values of another btQuadWord
* @param other The other btQuadWord to compare with
*/
- SIMD_FORCE_INLINE void setMax(const btQuadWord& other)
- {
- #ifdef BT_USE_SSE
- mVec128 = _mm_max_ps(mVec128, other.mVec128);
- #elif defined(BT_USE_NEON)
- mVec128 = vmaxq_f32(mVec128, other.mVec128);
- #else
- btSetMax(m_floats[0], other.m_floats[0]);
- btSetMax(m_floats[1], other.m_floats[1]);
- btSetMax(m_floats[2], other.m_floats[2]);
- btSetMax(m_floats[3], other.m_floats[3]);
- #endif
- }
- /**@brief Set each element to the min of the current values and the values of another btQuadWord
+ SIMD_FORCE_INLINE void setMax(const btQuadWord& other)
+ {
+#ifdef BT_USE_SSE
+ mVec128 = _mm_max_ps(mVec128, other.mVec128);
+#elif defined(BT_USE_NEON)
+ mVec128 = vmaxq_f32(mVec128, other.mVec128);
+#else
+ btSetMax(m_floats[0], other.m_floats[0]);
+ btSetMax(m_floats[1], other.m_floats[1]);
+ btSetMax(m_floats[2], other.m_floats[2]);
+ btSetMax(m_floats[3], other.m_floats[3]);
+#endif
+ }
+ /**@brief Set each element to the min of the current values and the values of another btQuadWord
* @param other The other btQuadWord to compare with
*/
- SIMD_FORCE_INLINE void setMin(const btQuadWord& other)
- {
- #ifdef BT_USE_SSE
- mVec128 = _mm_min_ps(mVec128, other.mVec128);
- #elif defined(BT_USE_NEON)
- mVec128 = vminq_f32(mVec128, other.mVec128);
- #else
- btSetMin(m_floats[0], other.m_floats[0]);
- btSetMin(m_floats[1], other.m_floats[1]);
- btSetMin(m_floats[2], other.m_floats[2]);
- btSetMin(m_floats[3], other.m_floats[3]);
- #endif
- }
-
-
-
+ SIMD_FORCE_INLINE void setMin(const btQuadWord& other)
+ {
+#ifdef BT_USE_SSE
+ mVec128 = _mm_min_ps(mVec128, other.mVec128);
+#elif defined(BT_USE_NEON)
+ mVec128 = vminq_f32(mVec128, other.mVec128);
+#else
+ btSetMin(m_floats[0], other.m_floats[0]);
+ btSetMin(m_floats[1], other.m_floats[1]);
+ btSetMin(m_floats[2], other.m_floats[2]);
+ btSetMin(m_floats[3], other.m_floats[3]);
+#endif
+ }
};
-#endif //BT_SIMD_QUADWORD_H
+#endif //BT_SIMD_QUADWORD_H
diff --git a/thirdparty/bullet/LinearMath/btQuaternion.h b/thirdparty/bullet/LinearMath/btQuaternion.h
index a98fec7bc4..53e8169b80 100644
--- a/thirdparty/bullet/LinearMath/btQuaternion.h
+++ b/thirdparty/bullet/LinearMath/btQuaternion.h
@@ -12,25 +12,19 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
-
#ifndef BT_SIMD__QUATERNION_H_
#define BT_SIMD__QUATERNION_H_
-
#include "btVector3.h"
#include "btQuadWord.h"
-
#ifdef BT_USE_DOUBLE_PRECISION
#define btQuaternionData btQuaternionDoubleData
#define btQuaternionDataName "btQuaternionDoubleData"
#else
#define btQuaternionData btQuaternionFloatData
#define btQuaternionDataName "btQuaternionFloatData"
-#endif //BT_USE_DOUBLE_PRECISION
-
-
+#endif //BT_USE_DOUBLE_PRECISION
#ifdef BT_USE_SSE
@@ -39,7 +33,7 @@ subject to the following restrictions:
#endif
-#if defined(BT_USE_SSE)
+#if defined(BT_USE_SSE)
#define vQInv (_mm_set_ps(+0.0f, -0.0f, -0.0f, -0.0f))
#define vPPPM (_mm_set_ps(-0.0f, +0.0f, +0.0f, +0.0f))
@@ -52,13 +46,14 @@ const btSimdFloat4 ATTRIBUTE_ALIGNED16(vPPPM) = {+0.0f, +0.0f, +0.0f, -0.0f};
#endif
/**@brief The btQuaternion implements quaternion to perform linear algebra rotations in combination with btMatrix3x3, btVector3 and btTransform. */
-class btQuaternion : public btQuadWord {
+class btQuaternion : public btQuadWord
+{
public:
- /**@brief No initialization constructor */
+ /**@brief No initialization constructor */
btQuaternion() {}
-#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))|| defined(BT_USE_NEON)
- // Set Vector
+#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
+ // Set Vector
SIMD_FORCE_INLINE btQuaternion(const btSimdFloat4 vec)
{
mVec128 = vec;
@@ -71,42 +66,43 @@ public:
}
// Assignment Operator
- SIMD_FORCE_INLINE btQuaternion&
- operator=(const btQuaternion& v)
+ SIMD_FORCE_INLINE btQuaternion&
+ operator=(const btQuaternion& v)
{
mVec128 = v.mVec128;
-
+
return *this;
}
-
+
#endif
// template <typename btScalar>
// explicit Quaternion(const btScalar *v) : Tuple4<btScalar>(v) {}
- /**@brief Constructor from scalars */
- btQuaternion(const btScalar& _x, const btScalar& _y, const btScalar& _z, const btScalar& _w)
- : btQuadWord(_x, _y, _z, _w)
- {}
- /**@brief Axis angle Constructor
+ /**@brief Constructor from scalars */
+ btQuaternion(const btScalar& _x, const btScalar& _y, const btScalar& _z, const btScalar& _w)
+ : btQuadWord(_x, _y, _z, _w)
+ {
+ }
+ /**@brief Axis angle Constructor
* @param axis The axis which the rotation is around
* @param angle The magnitude of the rotation around the angle (Radians) */
- btQuaternion(const btVector3& _axis, const btScalar& _angle)
- {
- setRotation(_axis, _angle);
+ btQuaternion(const btVector3& _axis, const btScalar& _angle)
+ {
+ setRotation(_axis, _angle);
}
- /**@brief Constructor from Euler angles
+ /**@brief Constructor from Euler angles
* @param yaw Angle around Y unless BT_EULER_DEFAULT_ZYX defined then Z
* @param pitch Angle around X unless BT_EULER_DEFAULT_ZYX defined then Y
* @param roll Angle around Z unless BT_EULER_DEFAULT_ZYX defined then X */
btQuaternion(const btScalar& yaw, const btScalar& pitch, const btScalar& roll)
- {
+ {
#ifndef BT_EULER_DEFAULT_ZYX
- setEuler(yaw, pitch, roll);
+ setEuler(yaw, pitch, roll);
#else
- setEulerZYX(yaw, pitch, roll);
-#endif
+ setEulerZYX(yaw, pitch, roll);
+#endif
}
- /**@brief Set the rotation using axis angle notation
+ /**@brief Set the rotation using axis angle notation
* @param axis The axis around which to rotate
* @param angle The magnitude of the rotation in Radians */
void setRotation(const btVector3& axis, const btScalar& _angle)
@@ -114,18 +110,18 @@ public:
btScalar d = axis.length();
btAssert(d != btScalar(0.0));
btScalar s = btSin(_angle * btScalar(0.5)) / d;
- setValue(axis.x() * s, axis.y() * s, axis.z() * s,
- btCos(_angle * btScalar(0.5)));
+ setValue(axis.x() * s, axis.y() * s, axis.z() * s,
+ btCos(_angle * btScalar(0.5)));
}
- /**@brief Set the quaternion using Euler angles
+ /**@brief Set the quaternion using Euler angles
* @param yaw Angle around Y
* @param pitch Angle around X
* @param roll Angle around Z */
void setEuler(const btScalar& yaw, const btScalar& pitch, const btScalar& roll)
{
- btScalar halfYaw = btScalar(yaw) * btScalar(0.5);
- btScalar halfPitch = btScalar(pitch) * btScalar(0.5);
- btScalar halfRoll = btScalar(roll) * btScalar(0.5);
+ btScalar halfYaw = btScalar(yaw) * btScalar(0.5);
+ btScalar halfPitch = btScalar(pitch) * btScalar(0.5);
+ btScalar halfRoll = btScalar(roll) * btScalar(0.5);
btScalar cosYaw = btCos(halfYaw);
btScalar sinYaw = btSin(halfYaw);
btScalar cosPitch = btCos(halfPitch);
@@ -133,32 +129,32 @@ public:
btScalar cosRoll = btCos(halfRoll);
btScalar sinRoll = btSin(halfRoll);
setValue(cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw,
- cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw,
- sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw,
- cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw);
+ cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw,
+ sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw,
+ cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw);
}
- /**@brief Set the quaternion using euler angles
+ /**@brief Set the quaternion using euler angles
* @param yaw Angle around Z
* @param pitch Angle around Y
* @param roll Angle around X */
void setEulerZYX(const btScalar& yawZ, const btScalar& pitchY, const btScalar& rollX)
{
- btScalar halfYaw = btScalar(yawZ) * btScalar(0.5);
- btScalar halfPitch = btScalar(pitchY) * btScalar(0.5);
- btScalar halfRoll = btScalar(rollX) * btScalar(0.5);
+ btScalar halfYaw = btScalar(yawZ) * btScalar(0.5);
+ btScalar halfPitch = btScalar(pitchY) * btScalar(0.5);
+ btScalar halfRoll = btScalar(rollX) * btScalar(0.5);
btScalar cosYaw = btCos(halfYaw);
btScalar sinYaw = btSin(halfYaw);
btScalar cosPitch = btCos(halfPitch);
btScalar sinPitch = btSin(halfPitch);
btScalar cosRoll = btCos(halfRoll);
btScalar sinRoll = btSin(halfRoll);
- setValue(sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw, //x
- cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw, //y
- cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw, //z
- cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw); //formerly yzx
+ setValue(sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw, //x
+ cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw, //y
+ cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw, //z
+ cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw); //formerly yzx
}
- /**@brief Get the euler angles from this quaternion
+ /**@brief Get the euler angles from this quaternion
* @param yaw Angle around Z
* @param pitch Angle around Y
* @param roll Angle around X */
@@ -173,23 +169,25 @@ public:
sqy = m_floats[1] * m_floats[1];
sqz = m_floats[2] * m_floats[2];
squ = m_floats[3] * m_floats[3];
- sarg = btScalar(-2.) * (m_floats[0] * m_floats[2] - m_floats[3] * m_floats[1]);
-
+ sarg = btScalar(-2.) * (m_floats[0] * m_floats[2] - m_floats[3] * m_floats[1]);
+
// If the pitch angle is PI/2 or -PI/2, we can only compute
// the sum roll + yaw. However, any combination that gives
// the right sum will produce the correct orientation, so we
// set rollX = 0 and compute yawZ.
if (sarg <= -btScalar(0.99999))
{
- pitchY = btScalar(-0.5)*SIMD_PI;
- rollX = 0;
- yawZ = btScalar(2) * btAtan2(m_floats[0],-m_floats[1]);
- } else if (sarg >= btScalar(0.99999))
+ pitchY = btScalar(-0.5) * SIMD_PI;
+ rollX = 0;
+ yawZ = btScalar(2) * btAtan2(m_floats[0], -m_floats[1]);
+ }
+ else if (sarg >= btScalar(0.99999))
{
- pitchY = btScalar(0.5)*SIMD_PI;
- rollX = 0;
- yawZ = btScalar(2) * btAtan2(-m_floats[0], m_floats[1]);
- } else
+ pitchY = btScalar(0.5) * SIMD_PI;
+ rollX = 0;
+ yawZ = btScalar(2) * btAtan2(-m_floats[0], m_floats[1]);
+ }
+ else
{
pitchY = btAsin(sarg);
rollX = btAtan2(2 * (m_floats[1] * m_floats[2] + m_floats[3] * m_floats[0]), squ - sqx - sqy + sqz);
@@ -197,178 +195,178 @@ public:
}
}
- /**@brief Add two quaternions
+ /**@brief Add two quaternions
* @param q The quaternion to add to this one */
- SIMD_FORCE_INLINE btQuaternion& operator+=(const btQuaternion& q)
+ SIMD_FORCE_INLINE btQuaternion& operator+=(const btQuaternion& q)
{
-#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
mVec128 = _mm_add_ps(mVec128, q.mVec128);
#elif defined(BT_USE_NEON)
mVec128 = vaddq_f32(mVec128, q.mVec128);
-#else
- m_floats[0] += q.x();
- m_floats[1] += q.y();
- m_floats[2] += q.z();
- m_floats[3] += q.m_floats[3];
+#else
+ m_floats[0] += q.x();
+ m_floats[1] += q.y();
+ m_floats[2] += q.z();
+ m_floats[3] += q.m_floats[3];
#endif
return *this;
}
- /**@brief Subtract out a quaternion
+ /**@brief Subtract out a quaternion
* @param q The quaternion to subtract from this one */
- btQuaternion& operator-=(const btQuaternion& q)
+ btQuaternion& operator-=(const btQuaternion& q)
{
-#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
mVec128 = _mm_sub_ps(mVec128, q.mVec128);
#elif defined(BT_USE_NEON)
mVec128 = vsubq_f32(mVec128, q.mVec128);
-#else
- m_floats[0] -= q.x();
- m_floats[1] -= q.y();
- m_floats[2] -= q.z();
- m_floats[3] -= q.m_floats[3];
+#else
+ m_floats[0] -= q.x();
+ m_floats[1] -= q.y();
+ m_floats[2] -= q.z();
+ m_floats[3] -= q.m_floats[3];
#endif
- return *this;
+ return *this;
}
- /**@brief Scale this quaternion
+ /**@brief Scale this quaternion
* @param s The scalar to scale by */
btQuaternion& operator*=(const btScalar& s)
{
-#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
- __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
- vs = bt_pshufd_ps(vs, 0); // (S S S S)
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+ __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
+ vs = bt_pshufd_ps(vs, 0); // (S S S S)
mVec128 = _mm_mul_ps(mVec128, vs);
#elif defined(BT_USE_NEON)
mVec128 = vmulq_n_f32(mVec128, s);
#else
- m_floats[0] *= s;
- m_floats[1] *= s;
- m_floats[2] *= s;
- m_floats[3] *= s;
+ m_floats[0] *= s;
+ m_floats[1] *= s;
+ m_floats[2] *= s;
+ m_floats[3] *= s;
#endif
return *this;
}
- /**@brief Multiply this quaternion by q on the right
+ /**@brief Multiply this quaternion by q on the right
* @param q The other quaternion
* Equivilant to this = this * q */
btQuaternion& operator*=(const btQuaternion& q)
{
-#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
__m128 vQ2 = q.get128();
-
- __m128 A1 = bt_pshufd_ps(mVec128, BT_SHUFFLE(0,1,2,0));
- __m128 B1 = bt_pshufd_ps(vQ2, BT_SHUFFLE(3,3,3,0));
-
+
+ __m128 A1 = bt_pshufd_ps(mVec128, BT_SHUFFLE(0, 1, 2, 0));
+ __m128 B1 = bt_pshufd_ps(vQ2, BT_SHUFFLE(3, 3, 3, 0));
+
A1 = A1 * B1;
-
- __m128 A2 = bt_pshufd_ps(mVec128, BT_SHUFFLE(1,2,0,1));
- __m128 B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(2,0,1,1));
-
+
+ __m128 A2 = bt_pshufd_ps(mVec128, BT_SHUFFLE(1, 2, 0, 1));
+ __m128 B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(2, 0, 1, 1));
+
A2 = A2 * B2;
-
- B1 = bt_pshufd_ps(mVec128, BT_SHUFFLE(2,0,1,2));
- B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(1,2,0,2));
-
- B1 = B1 * B2; // A3 *= B3
-
- mVec128 = bt_splat_ps(mVec128, 3); // A0
- mVec128 = mVec128 * vQ2; // A0 * B0
-
- A1 = A1 + A2; // AB12
- mVec128 = mVec128 - B1; // AB03 = AB0 - AB3
- A1 = _mm_xor_ps(A1, vPPPM); // change sign of the last element
- mVec128 = mVec128+ A1; // AB03 + AB12
-
-#elif defined(BT_USE_NEON)
-
- float32x4_t vQ1 = mVec128;
- float32x4_t vQ2 = q.get128();
- float32x4_t A0, A1, B1, A2, B2, A3, B3;
- float32x2_t vQ1zx, vQ2wx, vQ1yz, vQ2zx, vQ2yz, vQ2xz;
-
- {
- float32x2x2_t tmp;
- tmp = vtrn_f32( vget_high_f32(vQ1), vget_low_f32(vQ1) ); // {z x}, {w y}
- vQ1zx = tmp.val[0];
-
- tmp = vtrn_f32( vget_high_f32(vQ2), vget_low_f32(vQ2) ); // {z x}, {w y}
- vQ2zx = tmp.val[0];
- }
- vQ2wx = vext_f32(vget_high_f32(vQ2), vget_low_f32(vQ2), 1);
-
- vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
-
- vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
- vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
-
- A1 = vcombine_f32(vget_low_f32(vQ1), vQ1zx); // X Y z x
- B1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ2), 1), vQ2wx); // W W W X
-
- A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1));
- B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
-
- A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z
- B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z
-
- A1 = vmulq_f32(A1, B1);
- A2 = vmulq_f32(A2, B2);
- A3 = vmulq_f32(A3, B3); // A3 *= B3
- A0 = vmulq_lane_f32(vQ2, vget_high_f32(vQ1), 1); // A0 * B0
-
- A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2
- A0 = vsubq_f32(A0, A3); // AB03 = AB0 - AB3
-
- // change the sign of the last element
- A1 = (btSimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)vPPPM);
- A0 = vaddq_f32(A0, A1); // AB03 + AB12
-
- mVec128 = A0;
+
+ B1 = bt_pshufd_ps(mVec128, BT_SHUFFLE(2, 0, 1, 2));
+ B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(1, 2, 0, 2));
+
+ B1 = B1 * B2; // A3 *= B3
+
+ mVec128 = bt_splat_ps(mVec128, 3); // A0
+ mVec128 = mVec128 * vQ2; // A0 * B0
+
+ A1 = A1 + A2; // AB12
+ mVec128 = mVec128 - B1; // AB03 = AB0 - AB3
+ A1 = _mm_xor_ps(A1, vPPPM); // change sign of the last element
+ mVec128 = mVec128 + A1; // AB03 + AB12
+
+#elif defined(BT_USE_NEON)
+
+ float32x4_t vQ1 = mVec128;
+ float32x4_t vQ2 = q.get128();
+ float32x4_t A0, A1, B1, A2, B2, A3, B3;
+ float32x2_t vQ1zx, vQ2wx, vQ1yz, vQ2zx, vQ2yz, vQ2xz;
+
+ {
+ float32x2x2_t tmp;
+ tmp = vtrn_f32(vget_high_f32(vQ1), vget_low_f32(vQ1)); // {z x}, {w y}
+ vQ1zx = tmp.val[0];
+
+ tmp = vtrn_f32(vget_high_f32(vQ2), vget_low_f32(vQ2)); // {z x}, {w y}
+ vQ2zx = tmp.val[0];
+ }
+ vQ2wx = vext_f32(vget_high_f32(vQ2), vget_low_f32(vQ2), 1);
+
+ vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
+
+ vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
+ vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
+
+ A1 = vcombine_f32(vget_low_f32(vQ1), vQ1zx); // X Y z x
+ B1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ2), 1), vQ2wx); // W W W X
+
+ A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1));
+ B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
+
+ A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z
+ B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z
+
+ A1 = vmulq_f32(A1, B1);
+ A2 = vmulq_f32(A2, B2);
+ A3 = vmulq_f32(A3, B3); // A3 *= B3
+ A0 = vmulq_lane_f32(vQ2, vget_high_f32(vQ1), 1); // A0 * B0
+
+ A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2
+ A0 = vsubq_f32(A0, A3); // AB03 = AB0 - AB3
+
+ // change the sign of the last element
+ A1 = (btSimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)vPPPM);
+ A0 = vaddq_f32(A0, A1); // AB03 + AB12
+
+ mVec128 = A0;
#else
setValue(
- m_floats[3] * q.x() + m_floats[0] * q.m_floats[3] + m_floats[1] * q.z() - m_floats[2] * q.y(),
+ m_floats[3] * q.x() + m_floats[0] * q.m_floats[3] + m_floats[1] * q.z() - m_floats[2] * q.y(),
m_floats[3] * q.y() + m_floats[1] * q.m_floats[3] + m_floats[2] * q.x() - m_floats[0] * q.z(),
m_floats[3] * q.z() + m_floats[2] * q.m_floats[3] + m_floats[0] * q.y() - m_floats[1] * q.x(),
m_floats[3] * q.m_floats[3] - m_floats[0] * q.x() - m_floats[1] * q.y() - m_floats[2] * q.z());
#endif
return *this;
}
- /**@brief Return the dot product between this quaternion and another
+ /**@brief Return the dot product between this quaternion and another
* @param q The other quaternion */
btScalar dot(const btQuaternion& q) const
{
-#if defined BT_USE_SIMD_VECTOR3 && defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
- __m128 vd;
-
+#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+ __m128 vd;
+
vd = _mm_mul_ps(mVec128, q.mVec128);
-
- __m128 t = _mm_movehl_ps(vd, vd);
+
+ __m128 t = _mm_movehl_ps(vd, vd);
vd = _mm_add_ps(vd, t);
t = _mm_shuffle_ps(vd, vd, 0x55);
vd = _mm_add_ss(vd, t);
-
- return _mm_cvtss_f32(vd);
+
+ return _mm_cvtss_f32(vd);
#elif defined(BT_USE_NEON)
float32x4_t vd = vmulq_f32(mVec128, q.mVec128);
- float32x2_t x = vpadd_f32(vget_low_f32(vd), vget_high_f32(vd));
+ float32x2_t x = vpadd_f32(vget_low_f32(vd), vget_high_f32(vd));
x = vpadd_f32(x, x);
return vget_lane_f32(x, 0);
-#else
- return m_floats[0] * q.x() +
- m_floats[1] * q.y() +
- m_floats[2] * q.z() +
- m_floats[3] * q.m_floats[3];
+#else
+ return m_floats[0] * q.x() +
+ m_floats[1] * q.y() +
+ m_floats[2] * q.z() +
+ m_floats[3] * q.m_floats[3];
#endif
}
- /**@brief Return the length squared of the quaternion */
+ /**@brief Return the length squared of the quaternion */
btScalar length2() const
{
return dot(*this);
}
- /**@brief Return the length of the quaternion */
+ /**@brief Return the length of the quaternion */
btScalar length() const
{
return btSqrt(length2());
@@ -376,46 +374,46 @@ public:
btQuaternion& safeNormalize()
{
btScalar l2 = length2();
- if (l2>SIMD_EPSILON)
+ if (l2 > SIMD_EPSILON)
{
normalize();
}
return *this;
}
- /**@brief Normalize the quaternion
+ /**@brief Normalize the quaternion
* Such that x^2 + y^2 + z^2 +w^2 = 1 */
- btQuaternion& normalize()
+ btQuaternion& normalize()
{
-#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
- __m128 vd;
-
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+ __m128 vd;
+
vd = _mm_mul_ps(mVec128, mVec128);
-
- __m128 t = _mm_movehl_ps(vd, vd);
+
+ __m128 t = _mm_movehl_ps(vd, vd);
vd = _mm_add_ps(vd, t);
t = _mm_shuffle_ps(vd, vd, 0x55);
vd = _mm_add_ss(vd, t);
vd = _mm_sqrt_ss(vd);
vd = _mm_div_ss(vOnes, vd);
- vd = bt_pshufd_ps(vd, 0); // splat
+ vd = bt_pshufd_ps(vd, 0); // splat
mVec128 = _mm_mul_ps(mVec128, vd);
-
+
return *this;
-#else
+#else
return *this /= length();
#endif
}
- /**@brief Return a scaled version of this quaternion
+ /**@brief Return a scaled version of this quaternion
* @param s The scale factor */
SIMD_FORCE_INLINE btQuaternion
operator*(const btScalar& s) const
{
-#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
- __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
- vs = bt_pshufd_ps(vs, 0x00); // (S S S S)
-
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+ __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
+ vs = bt_pshufd_ps(vs, 0x00); // (S S S S)
+
return btQuaternion(_mm_mul_ps(mVec128, vs));
#elif defined(BT_USE_NEON)
return btQuaternion(vmulq_n_f32(mVec128, s));
@@ -424,7 +422,7 @@ public:
#endif
}
- /**@brief Return an inversely scaled versionof this quaternion
+ /**@brief Return an inversely scaled versionof this quaternion
* @param s The inverse scale factor */
btQuaternion operator/(const btScalar& s) const
{
@@ -432,49 +430,49 @@ public:
return *this * (btScalar(1.0) / s);
}
- /**@brief Inversely scale this quaternion
+ /**@brief Inversely scale this quaternion
* @param s The scale factor */
- btQuaternion& operator/=(const btScalar& s)
+ btQuaternion& operator/=(const btScalar& s)
{
btAssert(s != btScalar(0.0));
return *this *= btScalar(1.0) / s;
}
- /**@brief Return a normalized version of this quaternion */
- btQuaternion normalized() const
+ /**@brief Return a normalized version of this quaternion */
+ btQuaternion normalized() const
{
return *this / length();
- }
+ }
/**@brief Return the ***half*** angle between this quaternion and the other
* @param q The other quaternion */
- btScalar angle(const btQuaternion& q) const
+ btScalar angle(const btQuaternion& q) const
{
btScalar s = btSqrt(length2() * q.length2());
btAssert(s != btScalar(0.0));
return btAcos(dot(q) / s);
}
-
+
/**@brief Return the angle between this quaternion and the other along the shortest path
* @param q The other quaternion */
- btScalar angleShortestPath(const btQuaternion& q) const
+ btScalar angleShortestPath(const btQuaternion& q) const
{
btScalar s = btSqrt(length2() * q.length2());
btAssert(s != btScalar(0.0));
- if (dot(q) < 0) // Take care of long angle case see http://en.wikipedia.org/wiki/Slerp
+ if (dot(q) < 0) // Take care of long angle case see http://en.wikipedia.org/wiki/Slerp
return btAcos(dot(-q) / s) * btScalar(2.0);
- else
+ else
return btAcos(dot(q) / s) * btScalar(2.0);
}
/**@brief Return the angle [0, 2Pi] of rotation represented by this quaternion */
- btScalar getAngle() const
+ btScalar getAngle() const
{
btScalar s = btScalar(2.) * btAcos(m_floats[3]);
return s;
}
/**@brief Return the angle [0, Pi] of rotation represented by this quaternion along the shortest path */
- btScalar getAngleShortestPath() const
+ btScalar getAngleShortestPath() const
{
btScalar s;
if (m_floats[3] >= 0)
@@ -484,120 +482,117 @@ public:
return s;
}
-
/**@brief Return the axis of the rotation represented by this quaternion */
btVector3 getAxis() const
{
- btScalar s_squared = 1.f-m_floats[3]*m_floats[3];
-
- if (s_squared < btScalar(10.) * SIMD_EPSILON) //Check for divide by zero
- return btVector3(1.0, 0.0, 0.0); // Arbitrary
- btScalar s = 1.f/btSqrt(s_squared);
+ btScalar s_squared = 1.f - m_floats[3] * m_floats[3];
+
+ if (s_squared < btScalar(10.) * SIMD_EPSILON) //Check for divide by zero
+ return btVector3(1.0, 0.0, 0.0); // Arbitrary
+ btScalar s = 1.f / btSqrt(s_squared);
return btVector3(m_floats[0] * s, m_floats[1] * s, m_floats[2] * s);
}
/**@brief Return the inverse of this quaternion */
btQuaternion inverse() const
{
-#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
return btQuaternion(_mm_xor_ps(mVec128, vQInv));
#elif defined(BT_USE_NEON)
- return btQuaternion((btSimdFloat4)veorq_s32((int32x4_t)mVec128, (int32x4_t)vQInv));
-#else
+ return btQuaternion((btSimdFloat4)veorq_s32((int32x4_t)mVec128, (int32x4_t)vQInv));
+#else
return btQuaternion(-m_floats[0], -m_floats[1], -m_floats[2], m_floats[3]);
#endif
}
- /**@brief Return the sum of this quaternion and the other
+ /**@brief Return the sum of this quaternion and the other
* @param q2 The other quaternion */
SIMD_FORCE_INLINE btQuaternion
operator+(const btQuaternion& q2) const
{
-#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
return btQuaternion(_mm_add_ps(mVec128, q2.mVec128));
#elif defined(BT_USE_NEON)
- return btQuaternion(vaddq_f32(mVec128, q2.mVec128));
-#else
+ return btQuaternion(vaddq_f32(mVec128, q2.mVec128));
+#else
const btQuaternion& q1 = *this;
return btQuaternion(q1.x() + q2.x(), q1.y() + q2.y(), q1.z() + q2.z(), q1.m_floats[3] + q2.m_floats[3]);
#endif
}
- /**@brief Return the difference between this quaternion and the other
+ /**@brief Return the difference between this quaternion and the other
* @param q2 The other quaternion */
SIMD_FORCE_INLINE btQuaternion
operator-(const btQuaternion& q2) const
{
-#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
return btQuaternion(_mm_sub_ps(mVec128, q2.mVec128));
#elif defined(BT_USE_NEON)
- return btQuaternion(vsubq_f32(mVec128, q2.mVec128));
-#else
+ return btQuaternion(vsubq_f32(mVec128, q2.mVec128));
+#else
const btQuaternion& q1 = *this;
return btQuaternion(q1.x() - q2.x(), q1.y() - q2.y(), q1.z() - q2.z(), q1.m_floats[3] - q2.m_floats[3]);
#endif
}
- /**@brief Return the negative of this quaternion
+ /**@brief Return the negative of this quaternion
* This simply negates each element */
SIMD_FORCE_INLINE btQuaternion operator-() const
{
-#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
return btQuaternion(_mm_xor_ps(mVec128, btvMzeroMask));
#elif defined(BT_USE_NEON)
- return btQuaternion((btSimdFloat4)veorq_s32((int32x4_t)mVec128, (int32x4_t)btvMzeroMask) );
-#else
+ return btQuaternion((btSimdFloat4)veorq_s32((int32x4_t)mVec128, (int32x4_t)btvMzeroMask));
+#else
const btQuaternion& q2 = *this;
- return btQuaternion( - q2.x(), - q2.y(), - q2.z(), - q2.m_floats[3]);
+ return btQuaternion(-q2.x(), -q2.y(), -q2.z(), -q2.m_floats[3]);
#endif
}
- /**@todo document this and it's use */
- SIMD_FORCE_INLINE btQuaternion farthest( const btQuaternion& qd) const
+ /**@todo document this and it's use */
+ SIMD_FORCE_INLINE btQuaternion farthest(const btQuaternion& qd) const
{
- btQuaternion diff,sum;
+ btQuaternion diff, sum;
diff = *this - qd;
sum = *this + qd;
- if( diff.dot(diff) > sum.dot(sum) )
+ if (diff.dot(diff) > sum.dot(sum))
return qd;
return (-qd);
}
/**@todo document this and it's use */
- SIMD_FORCE_INLINE btQuaternion nearest( const btQuaternion& qd) const
+ SIMD_FORCE_INLINE btQuaternion nearest(const btQuaternion& qd) const
{
- btQuaternion diff,sum;
+ btQuaternion diff, sum;
diff = *this - qd;
sum = *this + qd;
- if( diff.dot(diff) < sum.dot(sum) )
+ if (diff.dot(diff) < sum.dot(sum))
return qd;
return (-qd);
}
-
- /**@brief Return the quaternion which is the result of Spherical Linear Interpolation between this and the other quaternion
+ /**@brief Return the quaternion which is the result of Spherical Linear Interpolation between this and the other quaternion
* @param q The other quaternion to interpolate with
* @param t The ratio between this and q to interpolate. If t = 0 the result is this, if t=1 the result is q.
* Slerp interpolates assuming constant velocity. */
btQuaternion slerp(const btQuaternion& q, const btScalar& t) const
{
-
const btScalar magnitude = btSqrt(length2() * q.length2());
btAssert(magnitude > btScalar(0));
-
+
const btScalar product = dot(q) / magnitude;
const btScalar absproduct = btFabs(product);
-
- if(absproduct < btScalar(1.0 - SIMD_EPSILON))
+
+ if (absproduct < btScalar(1.0 - SIMD_EPSILON))
{
// Take care of long angle case see http://en.wikipedia.org/wiki/Slerp
const btScalar theta = btAcos(absproduct);
const btScalar d = btSin(theta);
btAssert(d > btScalar(0));
-
+
const btScalar sign = (product < 0) ? btScalar(-1) : btScalar(1);
const btScalar s0 = btSin((btScalar(1.0) - t) * theta) / d;
const btScalar s1 = btSin(sign * t * theta) / d;
-
+
return btQuaternion(
(m_floats[0] * s0 + q.x() * s1),
(m_floats[1] * s0 + q.y() * s1),
@@ -610,314 +605,308 @@ public:
}
}
- static const btQuaternion& getIdentity()
+ static const btQuaternion& getIdentity()
{
- static const btQuaternion identityQuat(btScalar(0.),btScalar(0.),btScalar(0.),btScalar(1.));
+ static const btQuaternion identityQuat(btScalar(0.), btScalar(0.), btScalar(0.), btScalar(1.));
return identityQuat;
}
SIMD_FORCE_INLINE const btScalar& getW() const { return m_floats[3]; }
- SIMD_FORCE_INLINE void serialize(struct btQuaternionData& dataOut) const;
-
- SIMD_FORCE_INLINE void deSerialize(const struct btQuaternionFloatData& dataIn);
+ SIMD_FORCE_INLINE void serialize(struct btQuaternionData& dataOut) const;
- SIMD_FORCE_INLINE void deSerialize(const struct btQuaternionDoubleData& dataIn);
+ SIMD_FORCE_INLINE void deSerialize(const struct btQuaternionFloatData& dataIn);
- SIMD_FORCE_INLINE void serializeFloat(struct btQuaternionFloatData& dataOut) const;
+ SIMD_FORCE_INLINE void deSerialize(const struct btQuaternionDoubleData& dataIn);
- SIMD_FORCE_INLINE void deSerializeFloat(const struct btQuaternionFloatData& dataIn);
+ SIMD_FORCE_INLINE void serializeFloat(struct btQuaternionFloatData& dataOut) const;
- SIMD_FORCE_INLINE void serializeDouble(struct btQuaternionDoubleData& dataOut) const;
+ SIMD_FORCE_INLINE void deSerializeFloat(const struct btQuaternionFloatData& dataIn);
- SIMD_FORCE_INLINE void deSerializeDouble(const struct btQuaternionDoubleData& dataIn);
+ SIMD_FORCE_INLINE void serializeDouble(struct btQuaternionDoubleData& dataOut) const;
+ SIMD_FORCE_INLINE void deSerializeDouble(const struct btQuaternionDoubleData& dataIn);
};
-
-
-
-
/**@brief Return the product of two quaternions */
SIMD_FORCE_INLINE btQuaternion
-operator*(const btQuaternion& q1, const btQuaternion& q2)
+operator*(const btQuaternion& q1, const btQuaternion& q2)
{
-#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
__m128 vQ1 = q1.get128();
__m128 vQ2 = q2.get128();
__m128 A0, A1, B1, A2, B2;
-
- A1 = bt_pshufd_ps(vQ1, BT_SHUFFLE(0,1,2,0)); // X Y z x // vtrn
- B1 = bt_pshufd_ps(vQ2, BT_SHUFFLE(3,3,3,0)); // W W W X // vdup vext
+
+ A1 = bt_pshufd_ps(vQ1, BT_SHUFFLE(0, 1, 2, 0)); // X Y z x // vtrn
+ B1 = bt_pshufd_ps(vQ2, BT_SHUFFLE(3, 3, 3, 0)); // W W W X // vdup vext
A1 = A1 * B1;
-
- A2 = bt_pshufd_ps(vQ1, BT_SHUFFLE(1,2,0,1)); // Y Z X Y // vext
- B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(2,0,1,1)); // z x Y Y // vtrn vdup
+
+ A2 = bt_pshufd_ps(vQ1, BT_SHUFFLE(1, 2, 0, 1)); // Y Z X Y // vext
+ B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(2, 0, 1, 1)); // z x Y Y // vtrn vdup
A2 = A2 * B2;
- B1 = bt_pshufd_ps(vQ1, BT_SHUFFLE(2,0,1,2)); // z x Y Z // vtrn vext
- B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(1,2,0,2)); // Y Z x z // vext vtrn
-
- B1 = B1 * B2; // A3 *= B3
+ B1 = bt_pshufd_ps(vQ1, BT_SHUFFLE(2, 0, 1, 2)); // z x Y Z // vtrn vext
+ B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(1, 2, 0, 2)); // Y Z x z // vext vtrn
+
+ B1 = B1 * B2; // A3 *= B3
- A0 = bt_splat_ps(vQ1, 3); // A0
- A0 = A0 * vQ2; // A0 * B0
+ A0 = bt_splat_ps(vQ1, 3); // A0
+ A0 = A0 * vQ2; // A0 * B0
+
+ A1 = A1 + A2; // AB12
+ A0 = A0 - B1; // AB03 = AB0 - AB3
+
+ A1 = _mm_xor_ps(A1, vPPPM); // change sign of the last element
+ A0 = A0 + A1; // AB03 + AB12
- A1 = A1 + A2; // AB12
- A0 = A0 - B1; // AB03 = AB0 - AB3
-
- A1 = _mm_xor_ps(A1, vPPPM); // change sign of the last element
- A0 = A0 + A1; // AB03 + AB12
-
return btQuaternion(A0);
-#elif defined(BT_USE_NEON)
+#elif defined(BT_USE_NEON)
float32x4_t vQ1 = q1.get128();
float32x4_t vQ2 = q2.get128();
float32x4_t A0, A1, B1, A2, B2, A3, B3;
- float32x2_t vQ1zx, vQ2wx, vQ1yz, vQ2zx, vQ2yz, vQ2xz;
-
- {
- float32x2x2_t tmp;
- tmp = vtrn_f32( vget_high_f32(vQ1), vget_low_f32(vQ1) ); // {z x}, {w y}
- vQ1zx = tmp.val[0];
+ float32x2_t vQ1zx, vQ2wx, vQ1yz, vQ2zx, vQ2yz, vQ2xz;
+
+ {
+ float32x2x2_t tmp;
+ tmp = vtrn_f32(vget_high_f32(vQ1), vget_low_f32(vQ1)); // {z x}, {w y}
+ vQ1zx = tmp.val[0];
- tmp = vtrn_f32( vget_high_f32(vQ2), vget_low_f32(vQ2) ); // {z x}, {w y}
- vQ2zx = tmp.val[0];
- }
- vQ2wx = vext_f32(vget_high_f32(vQ2), vget_low_f32(vQ2), 1);
+ tmp = vtrn_f32(vget_high_f32(vQ2), vget_low_f32(vQ2)); // {z x}, {w y}
+ vQ2zx = tmp.val[0];
+ }
+ vQ2wx = vext_f32(vget_high_f32(vQ2), vget_low_f32(vQ2), 1);
- vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
+ vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
- vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
- vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
+ vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
+ vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
- A1 = vcombine_f32(vget_low_f32(vQ1), vQ1zx); // X Y z x
- B1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ2), 1), vQ2wx); // W W W X
+ A1 = vcombine_f32(vget_low_f32(vQ1), vQ1zx); // X Y z x
+ B1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ2), 1), vQ2wx); // W W W X
A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1));
- B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
+ B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
- A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z
- B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z
+ A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z
+ B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z
A1 = vmulq_f32(A1, B1);
A2 = vmulq_f32(A2, B2);
- A3 = vmulq_f32(A3, B3); // A3 *= B3
- A0 = vmulq_lane_f32(vQ2, vget_high_f32(vQ1), 1); // A0 * B0
-
- A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2
- A0 = vsubq_f32(A0, A3); // AB03 = AB0 - AB3
-
- // change the sign of the last element
- A1 = (btSimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)vPPPM);
- A0 = vaddq_f32(A0, A1); // AB03 + AB12
-
+ A3 = vmulq_f32(A3, B3); // A3 *= B3
+ A0 = vmulq_lane_f32(vQ2, vget_high_f32(vQ1), 1); // A0 * B0
+
+ A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2
+ A0 = vsubq_f32(A0, A3); // AB03 = AB0 - AB3
+
+ // change the sign of the last element
+ A1 = (btSimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)vPPPM);
+ A0 = vaddq_f32(A0, A1); // AB03 + AB12
+
return btQuaternion(A0);
#else
return btQuaternion(
- q1.w() * q2.x() + q1.x() * q2.w() + q1.y() * q2.z() - q1.z() * q2.y(),
+ q1.w() * q2.x() + q1.x() * q2.w() + q1.y() * q2.z() - q1.z() * q2.y(),
q1.w() * q2.y() + q1.y() * q2.w() + q1.z() * q2.x() - q1.x() * q2.z(),
q1.w() * q2.z() + q1.z() * q2.w() + q1.x() * q2.y() - q1.y() * q2.x(),
- q1.w() * q2.w() - q1.x() * q2.x() - q1.y() * q2.y() - q1.z() * q2.z());
+ q1.w() * q2.w() - q1.x() * q2.x() - q1.y() * q2.y() - q1.z() * q2.z());
#endif
}
SIMD_FORCE_INLINE btQuaternion
operator*(const btQuaternion& q, const btVector3& w)
{
-#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
__m128 vQ1 = q.get128();
__m128 vQ2 = w.get128();
__m128 A1, B1, A2, B2, A3, B3;
-
- A1 = bt_pshufd_ps(vQ1, BT_SHUFFLE(3,3,3,0));
- B1 = bt_pshufd_ps(vQ2, BT_SHUFFLE(0,1,2,0));
+
+ A1 = bt_pshufd_ps(vQ1, BT_SHUFFLE(3, 3, 3, 0));
+ B1 = bt_pshufd_ps(vQ2, BT_SHUFFLE(0, 1, 2, 0));
A1 = A1 * B1;
-
- A2 = bt_pshufd_ps(vQ1, BT_SHUFFLE(1,2,0,1));
- B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(2,0,1,1));
+
+ A2 = bt_pshufd_ps(vQ1, BT_SHUFFLE(1, 2, 0, 1));
+ B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(2, 0, 1, 1));
A2 = A2 * B2;
- A3 = bt_pshufd_ps(vQ1, BT_SHUFFLE(2,0,1,2));
- B3 = bt_pshufd_ps(vQ2, BT_SHUFFLE(1,2,0,2));
-
- A3 = A3 * B3; // A3 *= B3
+ A3 = bt_pshufd_ps(vQ1, BT_SHUFFLE(2, 0, 1, 2));
+ B3 = bt_pshufd_ps(vQ2, BT_SHUFFLE(1, 2, 0, 2));
+
+ A3 = A3 * B3; // A3 *= B3
+
+ A1 = A1 + A2; // AB12
+ A1 = _mm_xor_ps(A1, vPPPM); // change sign of the last element
+ A1 = A1 - A3; // AB123 = AB12 - AB3
- A1 = A1 + A2; // AB12
- A1 = _mm_xor_ps(A1, vPPPM); // change sign of the last element
- A1 = A1 - A3; // AB123 = AB12 - AB3
-
return btQuaternion(A1);
-
-#elif defined(BT_USE_NEON)
+
+#elif defined(BT_USE_NEON)
float32x4_t vQ1 = q.get128();
float32x4_t vQ2 = w.get128();
float32x4_t A1, B1, A2, B2, A3, B3;
- float32x2_t vQ1wx, vQ2zx, vQ1yz, vQ2yz, vQ1zx, vQ2xz;
-
- vQ1wx = vext_f32(vget_high_f32(vQ1), vget_low_f32(vQ1), 1);
- {
- float32x2x2_t tmp;
+ float32x2_t vQ1wx, vQ2zx, vQ1yz, vQ2yz, vQ1zx, vQ2xz;
- tmp = vtrn_f32( vget_high_f32(vQ2), vget_low_f32(vQ2) ); // {z x}, {w y}
- vQ2zx = tmp.val[0];
+ vQ1wx = vext_f32(vget_high_f32(vQ1), vget_low_f32(vQ1), 1);
+ {
+ float32x2x2_t tmp;
- tmp = vtrn_f32( vget_high_f32(vQ1), vget_low_f32(vQ1) ); // {z x}, {w y}
- vQ1zx = tmp.val[0];
- }
+ tmp = vtrn_f32(vget_high_f32(vQ2), vget_low_f32(vQ2)); // {z x}, {w y}
+ vQ2zx = tmp.val[0];
- vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
+ tmp = vtrn_f32(vget_high_f32(vQ1), vget_low_f32(vQ1)); // {z x}, {w y}
+ vQ1zx = tmp.val[0];
+ }
- vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
- vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
+ vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
- A1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ1), 1), vQ1wx); // W W W X
- B1 = vcombine_f32(vget_low_f32(vQ2), vQ2zx); // X Y z x
+ vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
+ vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
+
+ A1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ1), 1), vQ1wx); // W W W X
+ B1 = vcombine_f32(vget_low_f32(vQ2), vQ2zx); // X Y z x
A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1));
- B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
+ B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
- A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z
- B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z
+ A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z
+ B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z
A1 = vmulq_f32(A1, B1);
A2 = vmulq_f32(A2, B2);
- A3 = vmulq_f32(A3, B3); // A3 *= B3
-
- A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2
-
- // change the sign of the last element
- A1 = (btSimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)vPPPM);
-
- A1 = vsubq_f32(A1, A3); // AB123 = AB12 - AB3
-
+ A3 = vmulq_f32(A3, B3); // A3 *= B3
+
+ A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2
+
+ // change the sign of the last element
+ A1 = (btSimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)vPPPM);
+
+ A1 = vsubq_f32(A1, A3); // AB123 = AB12 - AB3
+
return btQuaternion(A1);
-
+
#else
- return btQuaternion(
- q.w() * w.x() + q.y() * w.z() - q.z() * w.y(),
- q.w() * w.y() + q.z() * w.x() - q.x() * w.z(),
- q.w() * w.z() + q.x() * w.y() - q.y() * w.x(),
- -q.x() * w.x() - q.y() * w.y() - q.z() * w.z());
+ return btQuaternion(
+ q.w() * w.x() + q.y() * w.z() - q.z() * w.y(),
+ q.w() * w.y() + q.z() * w.x() - q.x() * w.z(),
+ q.w() * w.z() + q.x() * w.y() - q.y() * w.x(),
+ -q.x() * w.x() - q.y() * w.y() - q.z() * w.z());
#endif
}
SIMD_FORCE_INLINE btQuaternion
operator*(const btVector3& w, const btQuaternion& q)
{
-#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
__m128 vQ1 = w.get128();
__m128 vQ2 = q.get128();
__m128 A1, B1, A2, B2, A3, B3;
-
- A1 = bt_pshufd_ps(vQ1, BT_SHUFFLE(0,1,2,0)); // X Y z x
- B1 = bt_pshufd_ps(vQ2, BT_SHUFFLE(3,3,3,0)); // W W W X
+
+ A1 = bt_pshufd_ps(vQ1, BT_SHUFFLE(0, 1, 2, 0)); // X Y z x
+ B1 = bt_pshufd_ps(vQ2, BT_SHUFFLE(3, 3, 3, 0)); // W W W X
A1 = A1 * B1;
-
- A2 = bt_pshufd_ps(vQ1, BT_SHUFFLE(1,2,0,1));
- B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(2,0,1,1));
- A2 = A2 *B2;
+ A2 = bt_pshufd_ps(vQ1, BT_SHUFFLE(1, 2, 0, 1));
+ B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(2, 0, 1, 1));
- A3 = bt_pshufd_ps(vQ1, BT_SHUFFLE(2,0,1,2));
- B3 = bt_pshufd_ps(vQ2, BT_SHUFFLE(1,2,0,2));
-
- A3 = A3 * B3; // A3 *= B3
+ A2 = A2 * B2;
+
+ A3 = bt_pshufd_ps(vQ1, BT_SHUFFLE(2, 0, 1, 2));
+ B3 = bt_pshufd_ps(vQ2, BT_SHUFFLE(1, 2, 0, 2));
+
+ A3 = A3 * B3; // A3 *= B3
+
+ A1 = A1 + A2; // AB12
+ A1 = _mm_xor_ps(A1, vPPPM); // change sign of the last element
+ A1 = A1 - A3; // AB123 = AB12 - AB3
- A1 = A1 + A2; // AB12
- A1 = _mm_xor_ps(A1, vPPPM); // change sign of the last element
- A1 = A1 - A3; // AB123 = AB12 - AB3
-
return btQuaternion(A1);
-#elif defined(BT_USE_NEON)
+#elif defined(BT_USE_NEON)
float32x4_t vQ1 = w.get128();
float32x4_t vQ2 = q.get128();
- float32x4_t A1, B1, A2, B2, A3, B3;
- float32x2_t vQ1zx, vQ2wx, vQ1yz, vQ2zx, vQ2yz, vQ2xz;
-
- {
- float32x2x2_t tmp;
-
- tmp = vtrn_f32( vget_high_f32(vQ1), vget_low_f32(vQ1) ); // {z x}, {w y}
- vQ1zx = tmp.val[0];
+ float32x4_t A1, B1, A2, B2, A3, B3;
+ float32x2_t vQ1zx, vQ2wx, vQ1yz, vQ2zx, vQ2yz, vQ2xz;
+
+ {
+ float32x2x2_t tmp;
- tmp = vtrn_f32( vget_high_f32(vQ2), vget_low_f32(vQ2) ); // {z x}, {w y}
- vQ2zx = tmp.val[0];
- }
- vQ2wx = vext_f32(vget_high_f32(vQ2), vget_low_f32(vQ2), 1);
+ tmp = vtrn_f32(vget_high_f32(vQ1), vget_low_f32(vQ1)); // {z x}, {w y}
+ vQ1zx = tmp.val[0];
- vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
+ tmp = vtrn_f32(vget_high_f32(vQ2), vget_low_f32(vQ2)); // {z x}, {w y}
+ vQ2zx = tmp.val[0];
+ }
+ vQ2wx = vext_f32(vget_high_f32(vQ2), vget_low_f32(vQ2), 1);
- vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
- vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
+ vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
- A1 = vcombine_f32(vget_low_f32(vQ1), vQ1zx); // X Y z x
- B1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ2), 1), vQ2wx); // W W W X
+ vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
+ vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
+
+ A1 = vcombine_f32(vget_low_f32(vQ1), vQ1zx); // X Y z x
+ B1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ2), 1), vQ2wx); // W W W X
A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1));
- B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
+ B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
- A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z
- B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z
+ A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z
+ B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z
A1 = vmulq_f32(A1, B1);
A2 = vmulq_f32(A2, B2);
- A3 = vmulq_f32(A3, B3); // A3 *= B3
-
- A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2
-
- // change the sign of the last element
- A1 = (btSimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)vPPPM);
-
- A1 = vsubq_f32(A1, A3); // AB123 = AB12 - AB3
-
+ A3 = vmulq_f32(A3, B3); // A3 *= B3
+
+ A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2
+
+ // change the sign of the last element
+ A1 = (btSimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)vPPPM);
+
+ A1 = vsubq_f32(A1, A3); // AB123 = AB12 - AB3
+
return btQuaternion(A1);
-
+
#else
- return btQuaternion(
- +w.x() * q.w() + w.y() * q.z() - w.z() * q.y(),
+ return btQuaternion(
+ +w.x() * q.w() + w.y() * q.z() - w.z() * q.y(),
+w.y() * q.w() + w.z() * q.x() - w.x() * q.z(),
+w.z() * q.w() + w.x() * q.y() - w.y() * q.x(),
- -w.x() * q.x() - w.y() * q.y() - w.z() * q.z());
+ -w.x() * q.x() - w.y() * q.y() - w.z() * q.z());
#endif
}
/**@brief Calculate the dot product between two quaternions */
-SIMD_FORCE_INLINE btScalar
-dot(const btQuaternion& q1, const btQuaternion& q2)
-{
- return q1.dot(q2);
+SIMD_FORCE_INLINE btScalar
+dot(const btQuaternion& q1, const btQuaternion& q2)
+{
+ return q1.dot(q2);
}
-
/**@brief Return the length of a quaternion */
SIMD_FORCE_INLINE btScalar
-length(const btQuaternion& q)
-{
- return q.length();
+length(const btQuaternion& q)
+{
+ return q.length();
}
/**@brief Return the angle between two quaternions*/
SIMD_FORCE_INLINE btScalar
-btAngle(const btQuaternion& q1, const btQuaternion& q2)
-{
- return q1.angle(q2);
+btAngle(const btQuaternion& q1, const btQuaternion& q2)
+{
+ return q1.angle(q2);
}
/**@brief Return the inverse of a quaternion*/
SIMD_FORCE_INLINE btQuaternion
-inverse(const btQuaternion& q)
+inverse(const btQuaternion& q)
{
return q.inverse();
}
@@ -928,115 +917,105 @@ inverse(const btQuaternion& q)
* @param t The ration between q1 and q2. t = 0 return q1, t=1 returns q2
* Slerp assumes constant velocity between positions. */
SIMD_FORCE_INLINE btQuaternion
-slerp(const btQuaternion& q1, const btQuaternion& q2, const btScalar& t)
+slerp(const btQuaternion& q1, const btQuaternion& q2, const btScalar& t)
{
return q1.slerp(q2, t);
}
-SIMD_FORCE_INLINE btVector3
-quatRotate(const btQuaternion& rotation, const btVector3& v)
+SIMD_FORCE_INLINE btVector3
+quatRotate(const btQuaternion& rotation, const btVector3& v)
{
btQuaternion q = rotation * v;
q *= rotation.inverse();
-#if defined BT_USE_SIMD_VECTOR3 && defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
return btVector3(_mm_and_ps(q.get128(), btvFFF0fMask));
#elif defined(BT_USE_NEON)
- return btVector3((float32x4_t)vandq_s32((int32x4_t)q.get128(), btvFFF0Mask));
-#else
- return btVector3(q.getX(),q.getY(),q.getZ());
+ return btVector3((float32x4_t)vandq_s32((int32x4_t)q.get128(), btvFFF0Mask));
+#else
+ return btVector3(q.getX(), q.getY(), q.getZ());
#endif
}
-SIMD_FORCE_INLINE btQuaternion
-shortestArcQuat(const btVector3& v0, const btVector3& v1) // Game Programming Gems 2.10. make sure v0,v1 are normalized
+SIMD_FORCE_INLINE btQuaternion
+shortestArcQuat(const btVector3& v0, const btVector3& v1) // Game Programming Gems 2.10. make sure v0,v1 are normalized
{
btVector3 c = v0.cross(v1);
- btScalar d = v0.dot(v1);
+ btScalar d = v0.dot(v1);
if (d < -1.0 + SIMD_EPSILON)
{
- btVector3 n,unused;
- btPlaneSpace1(v0,n,unused);
- return btQuaternion(n.x(),n.y(),n.z(),0.0f); // just pick any vector that is orthogonal to v0
+ btVector3 n, unused;
+ btPlaneSpace1(v0, n, unused);
+ return btQuaternion(n.x(), n.y(), n.z(), 0.0f); // just pick any vector that is orthogonal to v0
}
- btScalar s = btSqrt((1.0f + d) * 2.0f);
+ btScalar s = btSqrt((1.0f + d) * 2.0f);
btScalar rs = 1.0f / s;
- return btQuaternion(c.getX()*rs,c.getY()*rs,c.getZ()*rs,s * 0.5f);
+ return btQuaternion(c.getX() * rs, c.getY() * rs, c.getZ() * rs, s * 0.5f);
}
-SIMD_FORCE_INLINE btQuaternion
-shortestArcQuatNormalize2(btVector3& v0,btVector3& v1)
+SIMD_FORCE_INLINE btQuaternion
+shortestArcQuatNormalize2(btVector3& v0, btVector3& v1)
{
v0.normalize();
v1.normalize();
- return shortestArcQuat(v0,v1);
+ return shortestArcQuat(v0, v1);
}
-
-
-
-struct btQuaternionFloatData
+struct btQuaternionFloatData
{
- float m_floats[4];
+ float m_floats[4];
};
-struct btQuaternionDoubleData
+struct btQuaternionDoubleData
{
- double m_floats[4];
-
+ double m_floats[4];
};
-SIMD_FORCE_INLINE void btQuaternion::serializeFloat(struct btQuaternionFloatData& dataOut) const
+SIMD_FORCE_INLINE void btQuaternion::serializeFloat(struct btQuaternionFloatData& dataOut) const
{
///could also do a memcpy, check if it is worth it
- for (int i=0;i<4;i++)
+ for (int i = 0; i < 4; i++)
dataOut.m_floats[i] = float(m_floats[i]);
}
-SIMD_FORCE_INLINE void btQuaternion::deSerializeFloat(const struct btQuaternionFloatData& dataIn)
+SIMD_FORCE_INLINE void btQuaternion::deSerializeFloat(const struct btQuaternionFloatData& dataIn)
{
- for (int i=0;i<4;i++)
+ for (int i = 0; i < 4; i++)
m_floats[i] = btScalar(dataIn.m_floats[i]);
}
-
-SIMD_FORCE_INLINE void btQuaternion::serializeDouble(struct btQuaternionDoubleData& dataOut) const
+SIMD_FORCE_INLINE void btQuaternion::serializeDouble(struct btQuaternionDoubleData& dataOut) const
{
///could also do a memcpy, check if it is worth it
- for (int i=0;i<4;i++)
+ for (int i = 0; i < 4; i++)
dataOut.m_floats[i] = double(m_floats[i]);
}
-SIMD_FORCE_INLINE void btQuaternion::deSerializeDouble(const struct btQuaternionDoubleData& dataIn)
+SIMD_FORCE_INLINE void btQuaternion::deSerializeDouble(const struct btQuaternionDoubleData& dataIn)
{
- for (int i=0;i<4;i++)
+ for (int i = 0; i < 4; i++)
m_floats[i] = btScalar(dataIn.m_floats[i]);
}
-
-SIMD_FORCE_INLINE void btQuaternion::serialize(struct btQuaternionData& dataOut) const
+SIMD_FORCE_INLINE void btQuaternion::serialize(struct btQuaternionData& dataOut) const
{
///could also do a memcpy, check if it is worth it
- for (int i=0;i<4;i++)
+ for (int i = 0; i < 4; i++)
dataOut.m_floats[i] = m_floats[i];
}
-SIMD_FORCE_INLINE void btQuaternion::deSerialize(const struct btQuaternionFloatData& dataIn)
+SIMD_FORCE_INLINE void btQuaternion::deSerialize(const struct btQuaternionFloatData& dataIn)
{
- for (int i = 0; i<4; i++)
+ for (int i = 0; i < 4; i++)
m_floats[i] = (btScalar)dataIn.m_floats[i];
}
-SIMD_FORCE_INLINE void btQuaternion::deSerialize(const struct btQuaternionDoubleData& dataIn)
+SIMD_FORCE_INLINE void btQuaternion::deSerialize(const struct btQuaternionDoubleData& dataIn)
{
- for (int i=0;i<4;i++)
+ for (int i = 0; i < 4; i++)
m_floats[i] = (btScalar)dataIn.m_floats[i];
}
-
-#endif //BT_SIMD__QUATERNION_H_
-
-
-
+#endif //BT_SIMD__QUATERNION_H_
diff --git a/thirdparty/bullet/LinearMath/btQuickprof.cpp b/thirdparty/bullet/LinearMath/btQuickprof.cpp
index 1572b96262..86fd1d7812 100644
--- a/thirdparty/bullet/LinearMath/btQuickprof.cpp
+++ b/thirdparty/bullet/LinearMath/btQuickprof.cpp
@@ -16,16 +16,13 @@
#include "btQuickprof.h"
#include "btThreads.h"
-
-
-
#ifdef __CELLOS_LV2__
#include <sys/sys_time.h>
#include <sys/time_util.h>
#include <stdio.h>
#endif
-#if defined (SUNOS) || defined (__SUNOS__)
+#if defined(SUNOS) || defined(__SUNOS__)
#include <stdio.h>
#endif
#ifdef __APPLE__
@@ -42,49 +39,46 @@
#define NOIME
#ifdef _XBOX
- #include <Xtl.h>
-#else //_XBOX
- #include <windows.h>
+#include <Xtl.h>
+#else //_XBOX
+#include <windows.h>
-#if WINVER <0x0602
+#if WINVER < 0x0602
#define GetTickCount64 GetTickCount
#endif
-#endif //_XBOX
+#endif //_XBOX
#include <time.h>
-
-#else //_WIN32
+#else //_WIN32
#include <sys/time.h>
#ifdef BT_LINUX_REALTIME
//required linking against rt (librt)
#include <time.h>
-#endif //BT_LINUX_REALTIME
+#endif //BT_LINUX_REALTIME
-#endif //_WIN32
+#endif //_WIN32
-#define mymin(a,b) (a > b ? a : b)
+#define mymin(a, b) (a > b ? a : b)
struct btClockData
{
-
#ifdef BT_USE_WINDOWS_TIMERS
LARGE_INTEGER mClockFrequency;
LONGLONG mStartTick;
LARGE_INTEGER mStartTime;
#else
#ifdef __CELLOS_LV2__
- uint64_t mStartTime;
+ uint64_t mStartTime;
#else
#ifdef __APPLE__
- uint64_t mStartTimeNano;
+ uint64_t mStartTimeNano;
#endif
struct timeval mStartTime;
#endif
-#endif //__CELLOS_LV2__
-
+#endif //__CELLOS_LV2__
};
///The btClock is a portable basic clock that measures accurate time in seconds, use for profiling.
@@ -114,8 +108,7 @@ btClock& btClock::operator=(const btClock& other)
return *this;
}
-
- /// Resets the initial reference time.
+/// Resets the initial reference time.
void btClock::reset()
{
#ifdef BT_USE_WINDOWS_TIMERS
@@ -124,14 +117,14 @@ void btClock::reset()
#else
#ifdef __CELLOS_LV2__
- typedef uint64_t ClockSize;
+ typedef uint64_t ClockSize;
ClockSize newTime;
//__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
- SYS_TIMEBASE_GET( newTime );
+ SYS_TIMEBASE_GET(newTime);
m_data->mStartTime = newTime;
#else
#ifdef __APPLE__
- m_data->mStartTimeNano = mach_absolute_time();
+ m_data->mStartTimeNano = mach_absolute_time();
#endif
gettimeofday(&m_data->mStartTime, 0);
#endif
@@ -146,66 +139,66 @@ unsigned long long int btClock::getTimeMilliseconds()
LARGE_INTEGER currentTime;
QueryPerformanceCounter(&currentTime);
LONGLONG elapsedTime = currentTime.QuadPart -
- m_data->mStartTime.QuadPart;
- // Compute the number of millisecond ticks elapsed.
+ m_data->mStartTime.QuadPart;
+ // Compute the number of millisecond ticks elapsed.
unsigned long msecTicks = (unsigned long)(1000 * elapsedTime /
- m_data->mClockFrequency.QuadPart);
+ m_data->mClockFrequency.QuadPart);
- return msecTicks;
+ return msecTicks;
#else
#ifdef __CELLOS_LV2__
- uint64_t freq=sys_time_get_timebase_frequency();
- double dFreq=((double) freq) / 1000.0;
- typedef uint64_t ClockSize;
- ClockSize newTime;
- SYS_TIMEBASE_GET( newTime );
- //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
-
- return (unsigned long int)((double(newTime-m_data->mStartTime)) / dFreq);
+ uint64_t freq = sys_time_get_timebase_frequency();
+ double dFreq = ((double)freq) / 1000.0;
+ typedef uint64_t ClockSize;
+ ClockSize newTime;
+ SYS_TIMEBASE_GET(newTime);
+ //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
+
+ return (unsigned long int)((double(newTime - m_data->mStartTime)) / dFreq);
#else
- struct timeval currentTime;
- gettimeofday(&currentTime, 0);
- return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1000 +
- (currentTime.tv_usec - m_data->mStartTime.tv_usec) / 1000;
-#endif //__CELLOS_LV2__
+ struct timeval currentTime;
+ gettimeofday(&currentTime, 0);
+ return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1000 +
+ (currentTime.tv_usec - m_data->mStartTime.tv_usec) / 1000;
+#endif //__CELLOS_LV2__
#endif
}
- /// Returns the time in us since the last call to reset or since
- /// the Clock was created.
+/// Returns the time in us since the last call to reset or since
+/// the Clock was created.
unsigned long long int btClock::getTimeMicroseconds()
{
#ifdef BT_USE_WINDOWS_TIMERS
- //see https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx
- LARGE_INTEGER currentTime, elapsedTime;
-
- QueryPerformanceCounter(&currentTime);
- elapsedTime.QuadPart = currentTime.QuadPart -
- m_data->mStartTime.QuadPart;
- elapsedTime.QuadPart *= 1000000;
- elapsedTime.QuadPart /= m_data->mClockFrequency.QuadPart;
-
- return (unsigned long long) elapsedTime.QuadPart;
+ //see https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx
+ LARGE_INTEGER currentTime, elapsedTime;
+
+ QueryPerformanceCounter(&currentTime);
+ elapsedTime.QuadPart = currentTime.QuadPart -
+ m_data->mStartTime.QuadPart;
+ elapsedTime.QuadPart *= 1000000;
+ elapsedTime.QuadPart /= m_data->mClockFrequency.QuadPart;
+
+ return (unsigned long long)elapsedTime.QuadPart;
#else
#ifdef __CELLOS_LV2__
- uint64_t freq=sys_time_get_timebase_frequency();
- double dFreq=((double) freq)/ 1000000.0;
- typedef uint64_t ClockSize;
- ClockSize newTime;
- //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
- SYS_TIMEBASE_GET( newTime );
-
- return (unsigned long int)((double(newTime-m_data->mStartTime)) / dFreq);
+ uint64_t freq = sys_time_get_timebase_frequency();
+ double dFreq = ((double)freq) / 1000000.0;
+ typedef uint64_t ClockSize;
+ ClockSize newTime;
+ //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
+ SYS_TIMEBASE_GET(newTime);
+
+ return (unsigned long int)((double(newTime - m_data->mStartTime)) / dFreq);
#else
- struct timeval currentTime;
- gettimeofday(&currentTime, 0);
- return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1000000 +
- (currentTime.tv_usec - m_data->mStartTime.tv_usec);
-#endif//__CELLOS_LV2__
+ struct timeval currentTime;
+ gettimeofday(&currentTime, 0);
+ return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1000000 +
+ (currentTime.tv_usec - m_data->mStartTime.tv_usec);
+#endif //__CELLOS_LV2__
#endif
}
@@ -213,65 +206,63 @@ unsigned long long int btClock::getTimeNanoseconds()
{
#ifdef BT_USE_WINDOWS_TIMERS
//see https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx
- LARGE_INTEGER currentTime, elapsedTime;
-
- QueryPerformanceCounter(&currentTime);
- elapsedTime.QuadPart = currentTime.QuadPart -
- m_data->mStartTime.QuadPart;
- elapsedTime.QuadPart *= 1000000000;
- elapsedTime.QuadPart /= m_data->mClockFrequency.QuadPart;
-
- return (unsigned long long) elapsedTime.QuadPart;
+ LARGE_INTEGER currentTime, elapsedTime;
+
+ QueryPerformanceCounter(&currentTime);
+ elapsedTime.QuadPart = currentTime.QuadPart -
+ m_data->mStartTime.QuadPart;
+ elapsedTime.QuadPart *= 1000000000;
+ elapsedTime.QuadPart /= m_data->mClockFrequency.QuadPart;
+
+ return (unsigned long long)elapsedTime.QuadPart;
#else
#ifdef __CELLOS_LV2__
- uint64_t freq=sys_time_get_timebase_frequency();
- double dFreq=((double) freq)/ 1e9;
- typedef uint64_t ClockSize;
- ClockSize newTime;
- //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
- SYS_TIMEBASE_GET( newTime );
-
- return (unsigned long int)((double(newTime-m_data->mStartTime)) / dFreq);
+ uint64_t freq = sys_time_get_timebase_frequency();
+ double dFreq = ((double)freq) / 1e9;
+ typedef uint64_t ClockSize;
+ ClockSize newTime;
+ //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
+ SYS_TIMEBASE_GET(newTime);
+
+ return (unsigned long int)((double(newTime - m_data->mStartTime)) / dFreq);
#else
#ifdef __APPLE__
- uint64_t ticks = mach_absolute_time() - m_data->mStartTimeNano;
- static long double conversion = 0.0L;
- if( 0.0L == conversion )
- {
- // attempt to get conversion to nanoseconds
- mach_timebase_info_data_t info;
- int err = mach_timebase_info( &info );
- if( err )
- {
- btAssert(0);
- conversion = 1.;
- }
- conversion = info.numer / info.denom;
- }
- return (ticks * conversion);
-
-
-#else//__APPLE__
-
+ uint64_t ticks = mach_absolute_time() - m_data->mStartTimeNano;
+ static long double conversion = 0.0L;
+ if (0.0L == conversion)
+ {
+ // attempt to get conversion to nanoseconds
+ mach_timebase_info_data_t info;
+ int err = mach_timebase_info(&info);
+ if (err)
+ {
+ btAssert(0);
+ conversion = 1.;
+ }
+ conversion = info.numer / info.denom;
+ }
+ return (ticks * conversion);
+
+#else //__APPLE__
+
#ifdef BT_LINUX_REALTIME
- timespec ts;
- clock_gettime(CLOCK_REALTIME,&ts);
- return 1000000000*ts.tv_sec + ts.tv_nsec;
+ timespec ts;
+ clock_gettime(CLOCK_REALTIME, &ts);
+ return 1000000000 * ts.tv_sec + ts.tv_nsec;
#else
- struct timeval currentTime;
- gettimeofday(&currentTime, 0);
- return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1e9 +
- (currentTime.tv_usec - m_data->mStartTime.tv_usec)*1000;
-#endif //BT_LINUX_REALTIME
-
-#endif//__APPLE__
-#endif//__CELLOS_LV2__
-#endif
+ struct timeval currentTime;
+ gettimeofday(&currentTime, 0);
+ return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1e9 +
+ (currentTime.tv_usec - m_data->mStartTime.tv_usec) * 1000;
+#endif //BT_LINUX_REALTIME
+
+#endif //__APPLE__
+#endif //__CELLOS_LV2__
+#endif
}
-
-/// Returns the time in s since the last call to reset or since
+/// Returns the time in s since the last call to reset or since
/// the Clock was created.
btScalar btClock::getTimeSeconds()
{
@@ -281,23 +272,19 @@ btScalar btClock::getTimeSeconds()
#ifndef BT_NO_PROFILE
-
static btClock gProfileClock;
-
-inline void Profile_Get_Ticks(unsigned long int * ticks)
+inline void Profile_Get_Ticks(unsigned long int* ticks)
{
*ticks = (unsigned long int)gProfileClock.getTimeMicroseconds();
}
inline float Profile_Get_Tick_Rate(void)
{
-// return 1000000.f;
+ // return 1000000.f;
return 1000.f;
-
}
-
/***************************************************************************************************
**
** CProfileNode
@@ -313,35 +300,32 @@ inline float Profile_Get_Tick_Rate(void)
* The name is assumed to be a static pointer, only the pointer is stored and compared for *
* efficiency reasons. *
*=============================================================================================*/
-CProfileNode::CProfileNode( const char * name, CProfileNode * parent ) :
- Name( name ),
- TotalCalls( 0 ),
- TotalTime( 0 ),
- StartTime( 0 ),
- RecursionCounter( 0 ),
- Parent( parent ),
- Child( NULL ),
- Sibling( NULL ),
- m_userPtr(0)
+CProfileNode::CProfileNode(const char* name, CProfileNode* parent) : Name(name),
+ TotalCalls(0),
+ TotalTime(0),
+ StartTime(0),
+ RecursionCounter(0),
+ Parent(parent),
+ Child(NULL),
+ Sibling(NULL),
+ m_userPtr(0)
{
Reset();
}
-
-void CProfileNode::CleanupMemory()
+void CProfileNode::CleanupMemory()
{
- delete ( Child);
+ delete (Child);
Child = NULL;
- delete ( Sibling);
+ delete (Sibling);
Sibling = NULL;
}
-CProfileNode::~CProfileNode( void )
+CProfileNode::~CProfileNode(void)
{
CleanupMemory();
}
-
/***********************************************************************************************
* INPUT: *
* name - static string pointer to the name of the node we are searching for *
@@ -350,12 +334,14 @@ CProfileNode::~CProfileNode( void )
* All profile names are assumed to be static strings so this function uses pointer compares *
* to find the named node. *
*=============================================================================================*/
-CProfileNode * CProfileNode::Get_Sub_Node( const char * name )
+CProfileNode* CProfileNode::Get_Sub_Node(const char* name)
{
// Try to find this sub node
- CProfileNode * child = Child;
- while ( child ) {
- if ( child->Name == name ) {
+ CProfileNode* child = Child;
+ while (child)
+ {
+ if (child->Name == name)
+ {
return child;
}
child = child->Sibling;
@@ -363,176 +349,212 @@ CProfileNode * CProfileNode::Get_Sub_Node( const char * name )
// We didn't find it, so add it
- CProfileNode * node = new CProfileNode( name, this );
+ CProfileNode* node = new CProfileNode(name, this);
node->Sibling = Child;
Child = node;
return node;
}
-
-void CProfileNode::Reset( void )
+void CProfileNode::Reset(void)
{
TotalCalls = 0;
TotalTime = 0.0f;
-
- if ( Child ) {
+ if (Child)
+ {
Child->Reset();
}
- if ( Sibling ) {
+ if (Sibling)
+ {
Sibling->Reset();
}
}
-
-void CProfileNode::Call( void )
+void CProfileNode::Call(void)
{
TotalCalls++;
- if (RecursionCounter++ == 0) {
+ if (RecursionCounter++ == 0)
+ {
Profile_Get_Ticks(&StartTime);
}
}
-
-bool CProfileNode::Return( void )
+bool CProfileNode::Return(void)
{
- if ( --RecursionCounter == 0 && TotalCalls != 0 ) {
+ if (--RecursionCounter == 0 && TotalCalls != 0)
+ {
unsigned long int time;
Profile_Get_Ticks(&time);
- time-=StartTime;
+ time -= StartTime;
TotalTime += (float)time / Profile_Get_Tick_Rate();
}
- return ( RecursionCounter == 0 );
+ return (RecursionCounter == 0);
}
-
/***************************************************************************************************
**
** CProfileIterator
**
***************************************************************************************************/
-CProfileIterator::CProfileIterator( CProfileNode * start )
+CProfileIterator::CProfileIterator(CProfileNode* start)
{
CurrentParent = start;
CurrentChild = CurrentParent->Get_Child();
}
-
-void CProfileIterator::First(void)
+void CProfileIterator::First(void)
{
CurrentChild = CurrentParent->Get_Child();
}
-
-void CProfileIterator::Next(void)
+void CProfileIterator::Next(void)
{
CurrentChild = CurrentChild->Get_Sibling();
}
-
-bool CProfileIterator::Is_Done(void)
+bool CProfileIterator::Is_Done(void)
{
return CurrentChild == NULL;
}
-
-void CProfileIterator::Enter_Child( int index )
+void CProfileIterator::Enter_Child(int index)
{
CurrentChild = CurrentParent->Get_Child();
- while ( (CurrentChild != NULL) && (index != 0) ) {
+ while ((CurrentChild != NULL) && (index != 0))
+ {
index--;
CurrentChild = CurrentChild->Get_Sibling();
}
- if ( CurrentChild != NULL ) {
+ if (CurrentChild != NULL)
+ {
CurrentParent = CurrentChild;
CurrentChild = CurrentParent->Get_Child();
}
}
-
-void CProfileIterator::Enter_Parent( void )
+void CProfileIterator::Enter_Parent(void)
{
- if ( CurrentParent->Get_Parent() != NULL ) {
+ if (CurrentParent->Get_Parent() != NULL)
+ {
CurrentParent = CurrentParent->Get_Parent();
}
CurrentChild = CurrentParent->Get_Child();
}
-
/***************************************************************************************************
**
** CProfileManager
**
***************************************************************************************************/
-
-
-
-CProfileNode gRoots[BT_QUICKPROF_MAX_THREAD_COUNT]={
- CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
- CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
- CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
- CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
- CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
- CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
- CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
- CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
- CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
- CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
- CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
- CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
- CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
- CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
- CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
- CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL)
-};
-
-
-CProfileNode* gCurrentNodes[BT_QUICKPROF_MAX_THREAD_COUNT]=
-{
- &gRoots[ 0], &gRoots[ 1], &gRoots[ 2], &gRoots[ 3],
- &gRoots[ 4], &gRoots[ 5], &gRoots[ 6], &gRoots[ 7],
- &gRoots[ 8], &gRoots[ 9], &gRoots[10], &gRoots[11],
- &gRoots[12], &gRoots[13], &gRoots[14], &gRoots[15],
- &gRoots[16], &gRoots[17], &gRoots[18], &gRoots[19],
- &gRoots[20], &gRoots[21], &gRoots[22], &gRoots[23],
- &gRoots[24], &gRoots[25], &gRoots[26], &gRoots[27],
- &gRoots[28], &gRoots[29], &gRoots[30], &gRoots[31],
- &gRoots[32], &gRoots[33], &gRoots[34], &gRoots[35],
- &gRoots[36], &gRoots[37], &gRoots[38], &gRoots[39],
- &gRoots[40], &gRoots[41], &gRoots[42], &gRoots[43],
- &gRoots[44], &gRoots[45], &gRoots[46], &gRoots[47],
- &gRoots[48], &gRoots[49], &gRoots[50], &gRoots[51],
- &gRoots[52], &gRoots[53], &gRoots[54], &gRoots[55],
- &gRoots[56], &gRoots[57], &gRoots[58], &gRoots[59],
- &gRoots[60], &gRoots[61], &gRoots[62], &gRoots[63],
+CProfileNode gRoots[BT_QUICKPROF_MAX_THREAD_COUNT] = {
+ CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
+ CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
+ CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
+ CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
+ CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
+ CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
+ CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
+ CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
+ CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
+ CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
+ CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
+ CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
+ CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
+ CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
+ CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
+ CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL)};
+
+CProfileNode* gCurrentNodes[BT_QUICKPROF_MAX_THREAD_COUNT] =
+ {
+ &gRoots[0],
+ &gRoots[1],
+ &gRoots[2],
+ &gRoots[3],
+ &gRoots[4],
+ &gRoots[5],
+ &gRoots[6],
+ &gRoots[7],
+ &gRoots[8],
+ &gRoots[9],
+ &gRoots[10],
+ &gRoots[11],
+ &gRoots[12],
+ &gRoots[13],
+ &gRoots[14],
+ &gRoots[15],
+ &gRoots[16],
+ &gRoots[17],
+ &gRoots[18],
+ &gRoots[19],
+ &gRoots[20],
+ &gRoots[21],
+ &gRoots[22],
+ &gRoots[23],
+ &gRoots[24],
+ &gRoots[25],
+ &gRoots[26],
+ &gRoots[27],
+ &gRoots[28],
+ &gRoots[29],
+ &gRoots[30],
+ &gRoots[31],
+ &gRoots[32],
+ &gRoots[33],
+ &gRoots[34],
+ &gRoots[35],
+ &gRoots[36],
+ &gRoots[37],
+ &gRoots[38],
+ &gRoots[39],
+ &gRoots[40],
+ &gRoots[41],
+ &gRoots[42],
+ &gRoots[43],
+ &gRoots[44],
+ &gRoots[45],
+ &gRoots[46],
+ &gRoots[47],
+ &gRoots[48],
+ &gRoots[49],
+ &gRoots[50],
+ &gRoots[51],
+ &gRoots[52],
+ &gRoots[53],
+ &gRoots[54],
+ &gRoots[55],
+ &gRoots[56],
+ &gRoots[57],
+ &gRoots[58],
+ &gRoots[59],
+ &gRoots[60],
+ &gRoots[61],
+ &gRoots[62],
+ &gRoots[63],
};
+int CProfileManager::FrameCounter = 0;
+unsigned long int CProfileManager::ResetTime = 0;
-int CProfileManager::FrameCounter = 0;
-unsigned long int CProfileManager::ResetTime = 0;
-
-CProfileIterator * CProfileManager::Get_Iterator( void )
-{
-
- int threadIndex = btQuickprofGetCurrentThreadIndex2();
- if ((threadIndex<0) || threadIndex >= BT_QUICKPROF_MAX_THREAD_COUNT)
- return 0;
+CProfileIterator* CProfileManager::Get_Iterator(void)
+{
+ int threadIndex = btQuickprofGetCurrentThreadIndex2();
+ if ((threadIndex < 0) || threadIndex >= BT_QUICKPROF_MAX_THREAD_COUNT)
+ return 0;
- return new CProfileIterator( &gRoots[threadIndex]);
+ return new CProfileIterator(&gRoots[threadIndex]);
}
-void CProfileManager::CleanupMemory(void)
+void CProfileManager::CleanupMemory(void)
{
- for (int i=0;i<BT_QUICKPROF_MAX_THREAD_COUNT;i++)
+ for (int i = 0; i < BT_QUICKPROF_MAX_THREAD_COUNT; i++)
{
gRoots[i].CleanupMemory();
}
}
-
/***********************************************************************************************
* CProfileManager::Start_Profile -- Begin a named profile *
* *
@@ -546,51 +568,47 @@ void CProfileManager::CleanupMemory(void)
* The string used is assumed to be a static string; pointer compares are used throughout *
* the profiling code for efficiency. *
*=============================================================================================*/
-void CProfileManager::Start_Profile( const char * name )
+void CProfileManager::Start_Profile(const char* name)
{
int threadIndex = btQuickprofGetCurrentThreadIndex2();
- if ((threadIndex<0) || threadIndex >= BT_QUICKPROF_MAX_THREAD_COUNT)
+ if ((threadIndex < 0) || threadIndex >= BT_QUICKPROF_MAX_THREAD_COUNT)
return;
- if (name != gCurrentNodes[threadIndex]->Get_Name()) {
- gCurrentNodes[threadIndex] = gCurrentNodes[threadIndex]->Get_Sub_Node( name );
+ if (name != gCurrentNodes[threadIndex]->Get_Name())
+ {
+ gCurrentNodes[threadIndex] = gCurrentNodes[threadIndex]->Get_Sub_Node(name);
}
gCurrentNodes[threadIndex]->Call();
}
-
/***********************************************************************************************
* CProfileManager::Stop_Profile -- Stop timing and record the results. *
*=============================================================================================*/
-void CProfileManager::Stop_Profile( void )
+void CProfileManager::Stop_Profile(void)
{
int threadIndex = btQuickprofGetCurrentThreadIndex2();
- if ((threadIndex<0) || threadIndex >= BT_QUICKPROF_MAX_THREAD_COUNT)
+ if ((threadIndex < 0) || threadIndex >= BT_QUICKPROF_MAX_THREAD_COUNT)
return;
// Return will indicate whether we should back up to our parent (we may
// be profiling a recursive function)
- if (gCurrentNodes[threadIndex]->Return()) {
+ if (gCurrentNodes[threadIndex]->Return())
+ {
gCurrentNodes[threadIndex] = gCurrentNodes[threadIndex]->Get_Parent();
}
}
-
-
-
-
-
/***********************************************************************************************
* CProfileManager::Reset -- Reset the contents of the profiling system *
* *
* This resets everything except for the tree structure. All of the timing data is reset. *
*=============================================================================================*/
-void CProfileManager::Reset( void )
+void CProfileManager::Reset(void)
{
gProfileClock.reset();
int threadIndex = btQuickprofGetCurrentThreadIndex2();
- if ((threadIndex<0) || threadIndex >= BT_QUICKPROF_MAX_THREAD_COUNT)
+ if ((threadIndex < 0) || threadIndex >= BT_QUICKPROF_MAX_THREAD_COUNT)
return;
gRoots[threadIndex].Reset();
gRoots[threadIndex].Call();
@@ -598,20 +616,18 @@ void CProfileManager::Reset( void )
Profile_Get_Ticks(&ResetTime);
}
-
/***********************************************************************************************
* CProfileManager::Increment_Frame_Counter -- Increment the frame counter *
*=============================================================================================*/
-void CProfileManager::Increment_Frame_Counter( void )
+void CProfileManager::Increment_Frame_Counter(void)
{
FrameCounter++;
}
-
/***********************************************************************************************
* CProfileManager::Get_Time_Since_Reset -- returns the elapsed time since last reset *
*=============================================================================================*/
-float CProfileManager::Get_Time_Since_Reset( void )
+float CProfileManager::Get_Time_Since_Reset(void)
{
unsigned long int time;
Profile_Get_Ticks(&time);
@@ -621,34 +637,34 @@ float CProfileManager::Get_Time_Since_Reset( void )
#include <stdio.h>
-void CProfileManager::dumpRecursive(CProfileIterator* profileIterator, int spacing)
+void CProfileManager::dumpRecursive(CProfileIterator* profileIterator, int spacing)
{
profileIterator->First();
if (profileIterator->Is_Done())
return;
- float accumulated_time=0,parent_time = profileIterator->Is_Root() ? CProfileManager::Get_Time_Since_Reset() : profileIterator->Get_Current_Parent_Total_Time();
+ float accumulated_time = 0, parent_time = profileIterator->Is_Root() ? CProfileManager::Get_Time_Since_Reset() : profileIterator->Get_Current_Parent_Total_Time();
int i;
int frames_since_reset = CProfileManager::Get_Frame_Count_Since_Reset();
- for (i=0;i<spacing;i++) printf(".");
+ for (i = 0; i < spacing; i++) printf(".");
printf("----------------------------------\n");
- for (i=0;i<spacing;i++) printf(".");
- printf("Profiling: %s (total running time: %.3f ms) ---\n", profileIterator->Get_Current_Parent_Name(), parent_time );
+ for (i = 0; i < spacing; i++) printf(".");
+ printf("Profiling: %s (total running time: %.3f ms) ---\n", profileIterator->Get_Current_Parent_Name(), parent_time);
float totalTime = 0.f;
-
int numChildren = 0;
- for (i = 0; !profileIterator->Is_Done(); i++,profileIterator->Next())
+ for (i = 0; !profileIterator->Is_Done(); i++, profileIterator->Next())
{
numChildren++;
float current_total_time = profileIterator->Get_Current_Total_Time();
accumulated_time += current_total_time;
float fraction = parent_time > SIMD_EPSILON ? (current_total_time / parent_time) * 100 : 0.f;
{
- int i; for (i=0;i<spacing;i++) printf(".");
+ int i;
+ for (i = 0; i < spacing; i++) printf(".");
}
- printf("%d -- %s (%.2f %%) :: %.3f ms / frame (%d calls)\n",i, profileIterator->Get_Current_Name(), fraction,(current_total_time / (double)frames_since_reset),profileIterator->Get_Current_Total_Calls());
+ printf("%d -- %s (%.2f %%) :: %.3f ms / frame (%d calls)\n", i, profileIterator->Get_Current_Name(), fraction, (current_total_time / (double)frames_since_reset), profileIterator->Get_Current_Total_Calls());
totalTime += current_total_time;
//recurse into children
}
@@ -657,29 +673,45 @@ void CProfileManager::dumpRecursive(CProfileIterator* profileIterator, int spaci
{
//printf("what's wrong\n");
}
- for (i=0;i<spacing;i++) printf(".");
- printf("%s (%.3f %%) :: %.3f ms\n", "Unaccounted:",parent_time > SIMD_EPSILON ? ((parent_time - accumulated_time) / parent_time) * 100 : 0.f, parent_time - accumulated_time);
+ for (i = 0; i < spacing; i++) printf(".");
+ printf("%s (%.3f %%) :: %.3f ms\n", "Unaccounted:", parent_time > SIMD_EPSILON ? ((parent_time - accumulated_time) / parent_time) * 100 : 0.f, parent_time - accumulated_time);
- for (i=0;i<numChildren;i++)
+ for (i = 0; i < numChildren; i++)
{
profileIterator->Enter_Child(i);
- dumpRecursive(profileIterator,spacing+3);
+ dumpRecursive(profileIterator, spacing + 3);
profileIterator->Enter_Parent();
}
}
-
-
-void CProfileManager::dumpAll()
+void CProfileManager::dumpAll()
{
CProfileIterator* profileIterator = 0;
profileIterator = CProfileManager::Get_Iterator();
- dumpRecursive(profileIterator,0);
+ dumpRecursive(profileIterator, 0);
CProfileManager::Release_Iterator(profileIterator);
}
+
+void btEnterProfileZoneDefault(const char* name)
+{
+}
+void btLeaveProfileZoneDefault()
+{
+}
+
+#else
+void btEnterProfileZoneDefault(const char* name)
+{
+}
+void btLeaveProfileZoneDefault()
+{
+}
+#endif //BT_NO_PROFILE
+
+
// clang-format off
#if defined(_WIN32) && (defined(__MINGW32__) || defined(__MINGW64__))
#define BT_HAVE_TLS 1
@@ -703,50 +735,31 @@ void CProfileManager::dumpAll()
#endif // defined(__ANDROID__) && defined(__clang__)
// clang-format on
-unsigned int btQuickprofGetCurrentThreadIndex2() {
- const unsigned int kNullIndex = ~0U;
+unsigned int btQuickprofGetCurrentThreadIndex2()
+{
+ const unsigned int kNullIndex = ~0U;
#if BT_THREADSAFE
- return btGetCurrentThreadIndex();
+ return btGetCurrentThreadIndex();
#else
#if defined(BT_HAVE_TLS)
- static __thread unsigned int sThreadIndex = kNullIndex;
+ static __thread unsigned int sThreadIndex = kNullIndex;
#elif defined(_WIN32)
- __declspec(thread) static unsigned int sThreadIndex = kNullIndex;
+ __declspec(thread) static unsigned int sThreadIndex = kNullIndex;
#else
- unsigned int sThreadIndex = 0;
- return -1;
+ unsigned int sThreadIndex = 0;
+ return -1;
#endif
- static int gThreadCounter = 0;
-
- if (sThreadIndex == kNullIndex) {
- sThreadIndex = gThreadCounter++;
- }
- return sThreadIndex;
-#endif //BT_THREADSAFE
-}
-
-void btEnterProfileZoneDefault(const char* name)
-{
-}
-void btLeaveProfileZoneDefault()
-{
-}
-
+ static int gThreadCounter = 0;
-#else
-void btEnterProfileZoneDefault(const char* name)
-{
-}
-void btLeaveProfileZoneDefault()
-{
+ if (sThreadIndex == kNullIndex)
+ {
+ sThreadIndex = gThreadCounter++;
+ }
+ return sThreadIndex;
+#endif //BT_THREADSAFE
}
-#endif //BT_NO_PROFILE
-
-
-
-
static btEnterProfileZoneFunc* bts_enterFunc = btEnterProfileZoneDefault;
static btLeaveProfileZoneFunc* bts_leaveFunc = btLeaveProfileZoneDefault;
@@ -762,14 +775,13 @@ void btLeaveProfileZone()
btEnterProfileZoneFunc* btGetCurrentEnterProfileZoneFunc()
{
- return bts_enterFunc ;
+ return bts_enterFunc;
}
btLeaveProfileZoneFunc* btGetCurrentLeaveProfileZoneFunc()
{
return bts_leaveFunc;
}
-
void btSetCustomEnterProfileZoneFunc(btEnterProfileZoneFunc* enterFunc)
{
bts_enterFunc = enterFunc;
@@ -779,13 +791,12 @@ void btSetCustomLeaveProfileZoneFunc(btLeaveProfileZoneFunc* leaveFunc)
bts_leaveFunc = leaveFunc;
}
-CProfileSample::CProfileSample( const char * name )
-{
+CProfileSample::CProfileSample(const char* name)
+{
btEnterProfileZone(name);
}
-CProfileSample::~CProfileSample( void )
-{
+CProfileSample::~CProfileSample(void)
+{
btLeaveProfileZone();
}
-
diff --git a/thirdparty/bullet/LinearMath/btQuickprof.h b/thirdparty/bullet/LinearMath/btQuickprof.h
index 98a2675771..990d401d50 100644
--- a/thirdparty/bullet/LinearMath/btQuickprof.h
+++ b/thirdparty/bullet/LinearMath/btQuickprof.h
@@ -7,11 +7,9 @@
**
***************************************************************************************************/
-// Credits: The Clock class was inspired by the Timer classes in
+// Credits: The Clock class was inspired by the Timer classes in
// Ogre (www.ogre3d.org).
-
-
#ifndef BT_QUICK_PROF_H
#define BT_QUICK_PROF_H
@@ -34,97 +32,88 @@ public:
/// Resets the initial reference time.
void reset();
- /// Returns the time in ms since the last call to reset or since
+ /// Returns the time in ms since the last call to reset or since
/// the btClock was created.
unsigned long long int getTimeMilliseconds();
- /// Returns the time in us since the last call to reset or since
+ /// Returns the time in us since the last call to reset or since
/// the Clock was created.
unsigned long long int getTimeMicroseconds();
-
+
unsigned long long int getTimeNanoseconds();
- /// Returns the time in s since the last call to reset or since
+ /// Returns the time in s since the last call to reset or since
/// the Clock was created.
btScalar getTimeSeconds();
-
+
private:
struct btClockData* m_data;
};
-#endif //USE_BT_CLOCK
+#endif //USE_BT_CLOCK
-typedef void (btEnterProfileZoneFunc)(const char* msg);
-typedef void (btLeaveProfileZoneFunc)();
+typedef void(btEnterProfileZoneFunc)(const char* msg);
+typedef void(btLeaveProfileZoneFunc)();
btEnterProfileZoneFunc* btGetCurrentEnterProfileZoneFunc();
btLeaveProfileZoneFunc* btGetCurrentLeaveProfileZoneFunc();
-
-
void btSetCustomEnterProfileZoneFunc(btEnterProfileZoneFunc* enterFunc);
void btSetCustomLeaveProfileZoneFunc(btLeaveProfileZoneFunc* leaveFunc);
-#ifndef BT_NO_PROFILE // FIX redefinition
-//To disable built-in profiling, please comment out next line
-//#define BT_NO_PROFILE 1
-#endif //BT_NO_PROFILE
+#ifndef BT_ENABLE_PROFILE
+#define BT_NO_PROFILE 1
+#endif //BT_NO_PROFILE
const unsigned int BT_QUICKPROF_MAX_THREAD_COUNT = 64;
-#ifndef BT_NO_PROFILE
-//btQuickprofGetCurrentThreadIndex will return -1 if thread index cannot be determined,
+//btQuickprofGetCurrentThreadIndex will return -1 if thread index cannot be determined,
//otherwise returns thread index in range [0..maxThreads]
unsigned int btQuickprofGetCurrentThreadIndex2();
-#include <stdio.h>//@todo remove this, backwards compatibility
-
-#include "btAlignedAllocator.h"
-#include <new>
-
-
-
-
-
+#ifndef BT_NO_PROFILE
+#include <stdio.h> //@todo remove this, backwards compatibility
+#include "btAlignedAllocator.h"
+#include <new>
///A node in the Profile Hierarchy Tree
-class CProfileNode {
-
+class CProfileNode
+{
public:
- CProfileNode( const char * name, CProfileNode * parent );
- ~CProfileNode( void );
+ CProfileNode(const char* name, CProfileNode* parent);
+ ~CProfileNode(void);
- CProfileNode * Get_Sub_Node( const char * name );
+ CProfileNode* Get_Sub_Node(const char* name);
- CProfileNode * Get_Parent( void ) { return Parent; }
- CProfileNode * Get_Sibling( void ) { return Sibling; }
- CProfileNode * Get_Child( void ) { return Child; }
+ CProfileNode* Get_Parent(void) { return Parent; }
+ CProfileNode* Get_Sibling(void) { return Sibling; }
+ CProfileNode* Get_Child(void) { return Child; }
- void CleanupMemory();
- void Reset( void );
- void Call( void );
- bool Return( void );
+ void CleanupMemory();
+ void Reset(void);
+ void Call(void);
+ bool Return(void);
- const char * Get_Name( void ) { return Name; }
- int Get_Total_Calls( void ) { return TotalCalls; }
- float Get_Total_Time( void ) { return TotalTime; }
- void* GetUserPointer() const {return m_userPtr;}
- void SetUserPointer(void* ptr) { m_userPtr = ptr;}
-protected:
+ const char* Get_Name(void) { return Name; }
+ int Get_Total_Calls(void) { return TotalCalls; }
+ float Get_Total_Time(void) { return TotalTime; }
+ void* GetUserPointer() const { return m_userPtr; }
+ void SetUserPointer(void* ptr) { m_userPtr = ptr; }
- const char * Name;
- int TotalCalls;
- float TotalTime;
- unsigned long int StartTime;
- int RecursionCounter;
-
- CProfileNode * Parent;
- CProfileNode * Child;
- CProfileNode * Sibling;
- void* m_userPtr;
+protected:
+ const char* Name;
+ int TotalCalls;
+ float TotalTime;
+ unsigned long int StartTime;
+ int RecursionCounter;
+
+ CProfileNode* Parent;
+ CProfileNode* Child;
+ CProfileNode* Sibling;
+ void* m_userPtr;
};
///An iterator to navigate through the tree
@@ -132,91 +121,80 @@ class CProfileIterator
{
public:
// Access all the children of the current parent
- void First(void);
- void Next(void);
- bool Is_Done(void);
- bool Is_Root(void) { return (CurrentParent->Get_Parent() == 0); }
+ void First(void);
+ void Next(void);
+ bool Is_Done(void);
+ bool Is_Root(void) { return (CurrentParent->Get_Parent() == 0); }
- void Enter_Child( int index ); // Make the given child the new parent
- void Enter_Largest_Child( void ); // Make the largest child the new parent
- void Enter_Parent( void ); // Make the current parent's parent the new parent
+ void Enter_Child(int index); // Make the given child the new parent
+ void Enter_Largest_Child(void); // Make the largest child the new parent
+ void Enter_Parent(void); // Make the current parent's parent the new parent
// Access the current child
- const char * Get_Current_Name( void ) { return CurrentChild->Get_Name(); }
- int Get_Current_Total_Calls( void ) { return CurrentChild->Get_Total_Calls(); }
- float Get_Current_Total_Time( void ) { return CurrentChild->Get_Total_Time(); }
+ const char* Get_Current_Name(void) { return CurrentChild->Get_Name(); }
+ int Get_Current_Total_Calls(void) { return CurrentChild->Get_Total_Calls(); }
+ float Get_Current_Total_Time(void) { return CurrentChild->Get_Total_Time(); }
- void* Get_Current_UserPointer( void ) { return CurrentChild->GetUserPointer(); }
- void Set_Current_UserPointer(void* ptr) {CurrentChild->SetUserPointer(ptr);}
+ void* Get_Current_UserPointer(void) { return CurrentChild->GetUserPointer(); }
+ void Set_Current_UserPointer(void* ptr) { CurrentChild->SetUserPointer(ptr); }
// Access the current parent
- const char * Get_Current_Parent_Name( void ) { return CurrentParent->Get_Name(); }
- int Get_Current_Parent_Total_Calls( void ) { return CurrentParent->Get_Total_Calls(); }
- float Get_Current_Parent_Total_Time( void ) { return CurrentParent->Get_Total_Time(); }
-
-
+ const char* Get_Current_Parent_Name(void) { return CurrentParent->Get_Name(); }
+ int Get_Current_Parent_Total_Calls(void) { return CurrentParent->Get_Total_Calls(); }
+ float Get_Current_Parent_Total_Time(void) { return CurrentParent->Get_Total_Time(); }
protected:
+ CProfileNode* CurrentParent;
+ CProfileNode* CurrentChild;
- CProfileNode * CurrentParent;
- CProfileNode * CurrentChild;
-
-
- CProfileIterator( CProfileNode * start );
- friend class CProfileManager;
+ CProfileIterator(CProfileNode* start);
+ friend class CProfileManager;
};
-
///The Manager for the Profile system
-class CProfileManager {
+class CProfileManager
+{
public:
- static void Start_Profile( const char * name );
- static void Stop_Profile( void );
+ static void Start_Profile(const char* name);
+ static void Stop_Profile(void);
- static void CleanupMemory(void);
-// {
-// Root.CleanupMemory();
-// }
+ static void CleanupMemory(void);
+ // {
+ // Root.CleanupMemory();
+ // }
- static void Reset( void );
- static void Increment_Frame_Counter( void );
- static int Get_Frame_Count_Since_Reset( void ) { return FrameCounter; }
- static float Get_Time_Since_Reset( void );
+ static void Reset(void);
+ static void Increment_Frame_Counter(void);
+ static int Get_Frame_Count_Since_Reset(void) { return FrameCounter; }
+ static float Get_Time_Since_Reset(void);
- static CProfileIterator * Get_Iterator( void );
-// {
-//
-// return new CProfileIterator( &Root );
-// }
- static void Release_Iterator( CProfileIterator * iterator ) { delete ( iterator); }
+ static CProfileIterator* Get_Iterator(void);
+ // {
+ //
+ // return new CProfileIterator( &Root );
+ // }
+ static void Release_Iterator(CProfileIterator* iterator) { delete (iterator); }
- static void dumpRecursive(CProfileIterator* profileIterator, int spacing);
+ static void dumpRecursive(CProfileIterator* profileIterator, int spacing);
- static void dumpAll();
+ static void dumpAll();
private:
-
- static int FrameCounter;
- static unsigned long int ResetTime;
+ static int FrameCounter;
+ static unsigned long int ResetTime;
};
-
-
-
-#endif //#ifndef BT_NO_PROFILE
+#endif //#ifndef BT_NO_PROFILE
///ProfileSampleClass is a simple way to profile a function's scope
///Use the BT_PROFILE macro at the start of scope to time
-class CProfileSample {
+class CProfileSample
+{
public:
- CProfileSample( const char * name );
+ CProfileSample(const char* name);
- ~CProfileSample( void );
+ ~CProfileSample(void);
};
-#define BT_PROFILE( name ) CProfileSample __profile( name )
-
-
-
-#endif //BT_QUICK_PROF_H
-
+#define BT_PROFILE(name) CProfileSample __profile(name)
+#endif //BT_QUICK_PROF_H
diff --git a/thirdparty/bullet/LinearMath/btRandom.h b/thirdparty/bullet/LinearMath/btRandom.h
index 4cbfc6bfe9..e659af8605 100644
--- a/thirdparty/bullet/LinearMath/btRandom.h
+++ b/thirdparty/bullet/LinearMath/btRandom.h
@@ -12,8 +12,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
-
#ifndef BT_GEN_RANDOM_H
#define BT_GEN_RANDOM_H
@@ -24,8 +22,8 @@ subject to the following restrictions:
#define GEN_RAND_MAX UINT_MAX
-SIMD_FORCE_INLINE void GEN_srand(unsigned int seed) { init_genrand(seed); }
-SIMD_FORCE_INLINE unsigned int GEN_rand() { return genrand_int32(); }
+SIMD_FORCE_INLINE void GEN_srand(unsigned int seed) { init_genrand(seed); }
+SIMD_FORCE_INLINE unsigned int GEN_rand() { return genrand_int32(); }
#else
@@ -33,10 +31,9 @@ SIMD_FORCE_INLINE unsigned int GEN_rand() { return genrand_int
#define GEN_RAND_MAX RAND_MAX
-SIMD_FORCE_INLINE void GEN_srand(unsigned int seed) { srand(seed); }
-SIMD_FORCE_INLINE unsigned int GEN_rand() { return rand(); }
+SIMD_FORCE_INLINE void GEN_srand(unsigned int seed) { srand(seed); }
+SIMD_FORCE_INLINE unsigned int GEN_rand() { return rand(); }
#endif
-#endif //BT_GEN_RANDOM_H
-
+#endif //BT_GEN_RANDOM_H
diff --git a/thirdparty/bullet/LinearMath/btScalar.h b/thirdparty/bullet/LinearMath/btScalar.h
index 24e8454c1f..c198bd4b35 100644
--- a/thirdparty/bullet/LinearMath/btScalar.h
+++ b/thirdparty/bullet/LinearMath/btScalar.h
@@ -32,7 +32,6 @@ inline int btGetVersion()
return BT_BULLET_VERSION;
}
-
// The following macro "BT_NOT_EMPTY_FILE" can be put into a file
// in order suppress the MS Visual C++ Linker warning 4221
//
@@ -44,16 +43,19 @@ inline int btGetVersion()
//
// see more https://stackoverflow.com/questions/1822887/what-is-the-best-way-to-eliminate-ms-visual-c-linker-warning-warning-lnk422
-#if defined (_MSC_VER)
- #define BT_NOT_EMPTY_FILE_CAT_II(p, res) res
- #define BT_NOT_EMPTY_FILE_CAT_I(a, b) BT_NOT_EMPTY_FILE_CAT_II(~, a ## b)
- #define BT_NOT_EMPTY_FILE_CAT(a, b) BT_NOT_EMPTY_FILE_CAT_I(a, b)
- #define BT_NOT_EMPTY_FILE namespace { char BT_NOT_EMPTY_FILE_CAT(NoEmptyFileDummy, __COUNTER__); }
+#if defined(_MSC_VER)
+#define BT_NOT_EMPTY_FILE_CAT_II(p, res) res
+#define BT_NOT_EMPTY_FILE_CAT_I(a, b) BT_NOT_EMPTY_FILE_CAT_II(~, a##b)
+#define BT_NOT_EMPTY_FILE_CAT(a, b) BT_NOT_EMPTY_FILE_CAT_I(a, b)
+#define BT_NOT_EMPTY_FILE \
+ namespace \
+ { \
+ char BT_NOT_EMPTY_FILE_CAT(NoEmptyFileDummy, __COUNTER__); \
+ }
#else
- #define BT_NOT_EMPTY_FILE
+#define BT_NOT_EMPTY_FILE
#endif
-
// clang and most formatting tools don't support indentation of preprocessor guards, so turn it off
// clang-format off
#if defined(DEBUG) || defined (_DEBUG)
diff --git a/thirdparty/bullet/LinearMath/btSerializer.cpp b/thirdparty/bullet/LinearMath/btSerializer.cpp
index 4faa8f536b..18683c8fa7 100644
--- a/thirdparty/bullet/LinearMath/btSerializer.cpp
+++ b/thirdparty/bullet/LinearMath/btSerializer.cpp
@@ -1,3 +1,4 @@
+// clang-format off
char sBulletDNAstr[]= {
char(83),char(68),char(78),char(65),char(78),char(65),char(77),char(69),char(-76),char(1),char(0),char(0),char(109),char(95),char(115),char(105),char(122),char(101),char(0),char(109),
char(95),char(99),char(97),char(112),char(97),char(99),char(105),char(116),char(121),char(0),char(42),char(109),char(95),char(100),char(97),char(116),char(97),char(0),char(109),char(95),
@@ -687,3 +688,5 @@ char(97),char(0),char(4),char(0),char(50),char(0),char(-79),char(1),char(96),cha
char(98),char(0),char(4),char(0),char(48),char(0),char(-79),char(1),char(95),char(0),char(-78),char(1),char(4),char(0),char(-77),char(1),char(0),char(0),char(37),char(0),
};
int sBulletDNAlen= sizeof(sBulletDNAstr);
+
+// clang-format on
diff --git a/thirdparty/bullet/LinearMath/btSerializer.h b/thirdparty/bullet/LinearMath/btSerializer.h
index 39be3f810e..ba34441615 100644
--- a/thirdparty/bullet/LinearMath/btSerializer.h
+++ b/thirdparty/bullet/LinearMath/btSerializer.h
@@ -16,49 +16,45 @@ subject to the following restrictions:
#ifndef BT_SERIALIZER_H
#define BT_SERIALIZER_H
-#include "btScalar.h" // has definitions like SIMD_FORCE_INLINE
+#include "btScalar.h" // has definitions like SIMD_FORCE_INLINE
#include "btHashMap.h"
-#if !defined( __CELLOS_LV2__) && !defined(__MWERKS__)
+#if !defined(__CELLOS_LV2__) && !defined(__MWERKS__)
#include <memory.h>
#endif
#include <string.h>
-
-
-
extern char sBulletDNAstr[];
extern int sBulletDNAlen;
extern char sBulletDNAstr64[];
extern int sBulletDNAlen64;
-SIMD_FORCE_INLINE int btStrLen(const char* str)
+SIMD_FORCE_INLINE int btStrLen(const char* str)
{
- if (!str)
- return(0);
+ if (!str)
+ return (0);
int len = 0;
while (*str != 0)
{
- str++;
- len++;
- }
+ str++;
+ len++;
+ }
- return len;
+ return len;
}
-
class btChunk
{
public:
- int m_chunkCode;
- int m_length;
- void *m_oldPtr;
- int m_dna_nr;
- int m_number;
+ int m_chunkCode;
+ int m_length;
+ void* m_oldPtr;
+ int m_dna_nr;
+ int m_number;
};
-enum btSerializationFlags
+enum btSerializationFlags
{
BT_SERIALIZE_NO_BVH = 1,
BT_SERIALIZE_NO_TRIANGLEINFOMAP = 2,
@@ -66,78 +62,71 @@ enum btSerializationFlags
BT_SERIALIZE_CONTACT_MANIFOLDS = 8,
};
-class btSerializer
+class btSerializer
{
-
public:
-
virtual ~btSerializer() {}
- virtual const unsigned char* getBufferPointer() const = 0;
+ virtual const unsigned char* getBufferPointer() const = 0;
- virtual int getCurrentBufferSize() const = 0;
+ virtual int getCurrentBufferSize() const = 0;
- virtual btChunk* allocate(size_t size, int numElements) = 0;
+ virtual btChunk* allocate(size_t size, int numElements) = 0;
- virtual void finalizeChunk(btChunk* chunk, const char* structType, int chunkCode,void* oldPtr)= 0;
+ virtual void finalizeChunk(btChunk* chunk, const char* structType, int chunkCode, void* oldPtr) = 0;
- virtual void* findPointer(void* oldPtr) = 0;
+ virtual void* findPointer(void* oldPtr) = 0;
- virtual void* getUniquePointer(void*oldPtr) = 0;
+ virtual void* getUniquePointer(void* oldPtr) = 0;
- virtual void startSerialization() = 0;
+ virtual void startSerialization() = 0;
- virtual void finishSerialization() = 0;
+ virtual void finishSerialization() = 0;
- virtual const char* findNameForPointer(const void* ptr) const = 0;
+ virtual const char* findNameForPointer(const void* ptr) const = 0;
- virtual void registerNameForPointer(const void* ptr, const char* name) = 0;
+ virtual void registerNameForPointer(const void* ptr, const char* name) = 0;
- virtual void serializeName(const char* ptr) = 0;
+ virtual void serializeName(const char* ptr) = 0;
- virtual int getSerializationFlags() const = 0;
+ virtual int getSerializationFlags() const = 0;
- virtual void setSerializationFlags(int flags) = 0;
+ virtual void setSerializationFlags(int flags) = 0;
virtual int getNumChunks() const = 0;
virtual const btChunk* getChunk(int chunkIndex) const = 0;
-
};
-
-
#define BT_HEADER_LENGTH 12
-#if defined(__sgi) || defined (__sparc) || defined (__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__)
-# define BT_MAKE_ID(a,b,c,d) ( (int)(a)<<24 | (int)(b)<<16 | (c)<<8 | (d) )
+#if defined(__sgi) || defined(__sparc) || defined(__sparc__) || defined(__PPC__) || defined(__ppc__) || defined(__BIG_ENDIAN__)
+#define BT_MAKE_ID(a, b, c, d) ((int)(a) << 24 | (int)(b) << 16 | (c) << 8 | (d))
#else
-# define BT_MAKE_ID(a,b,c,d) ( (int)(d)<<24 | (int)(c)<<16 | (b)<<8 | (a) )
+#define BT_MAKE_ID(a, b, c, d) ((int)(d) << 24 | (int)(c) << 16 | (b) << 8 | (a))
#endif
-
-#define BT_MULTIBODY_CODE BT_MAKE_ID('M','B','D','Y')
-#define BT_MB_LINKCOLLIDER_CODE BT_MAKE_ID('M','B','L','C')
-#define BT_SOFTBODY_CODE BT_MAKE_ID('S','B','D','Y')
-#define BT_COLLISIONOBJECT_CODE BT_MAKE_ID('C','O','B','J')
-#define BT_RIGIDBODY_CODE BT_MAKE_ID('R','B','D','Y')
-#define BT_CONSTRAINT_CODE BT_MAKE_ID('C','O','N','S')
-#define BT_BOXSHAPE_CODE BT_MAKE_ID('B','O','X','S')
-#define BT_QUANTIZED_BVH_CODE BT_MAKE_ID('Q','B','V','H')
-#define BT_TRIANLGE_INFO_MAP BT_MAKE_ID('T','M','A','P')
-#define BT_SHAPE_CODE BT_MAKE_ID('S','H','A','P')
-#define BT_ARRAY_CODE BT_MAKE_ID('A','R','A','Y')
-#define BT_SBMATERIAL_CODE BT_MAKE_ID('S','B','M','T')
-#define BT_SBNODE_CODE BT_MAKE_ID('S','B','N','D')
-#define BT_DYNAMICSWORLD_CODE BT_MAKE_ID('D','W','L','D')
-#define BT_CONTACTMANIFOLD_CODE BT_MAKE_ID('C','O','N','T')
-#define BT_DNA_CODE BT_MAKE_ID('D','N','A','1')
-
-struct btPointerUid
+#define BT_MULTIBODY_CODE BT_MAKE_ID('M', 'B', 'D', 'Y')
+#define BT_MB_LINKCOLLIDER_CODE BT_MAKE_ID('M', 'B', 'L', 'C')
+#define BT_SOFTBODY_CODE BT_MAKE_ID('S', 'B', 'D', 'Y')
+#define BT_COLLISIONOBJECT_CODE BT_MAKE_ID('C', 'O', 'B', 'J')
+#define BT_RIGIDBODY_CODE BT_MAKE_ID('R', 'B', 'D', 'Y')
+#define BT_CONSTRAINT_CODE BT_MAKE_ID('C', 'O', 'N', 'S')
+#define BT_BOXSHAPE_CODE BT_MAKE_ID('B', 'O', 'X', 'S')
+#define BT_QUANTIZED_BVH_CODE BT_MAKE_ID('Q', 'B', 'V', 'H')
+#define BT_TRIANLGE_INFO_MAP BT_MAKE_ID('T', 'M', 'A', 'P')
+#define BT_SHAPE_CODE BT_MAKE_ID('S', 'H', 'A', 'P')
+#define BT_ARRAY_CODE BT_MAKE_ID('A', 'R', 'A', 'Y')
+#define BT_SBMATERIAL_CODE BT_MAKE_ID('S', 'B', 'M', 'T')
+#define BT_SBNODE_CODE BT_MAKE_ID('S', 'B', 'N', 'D')
+#define BT_DYNAMICSWORLD_CODE BT_MAKE_ID('D', 'W', 'L', 'D')
+#define BT_CONTACTMANIFOLD_CODE BT_MAKE_ID('C', 'O', 'N', 'T')
+#define BT_DNA_CODE BT_MAKE_ID('D', 'N', 'A', '1')
+
+struct btPointerUid
{
- union
- {
- void* m_ptr;
- int m_uniqueIds[2];
+ union {
+ void* m_ptr;
+ int m_uniqueIds[2];
};
};
@@ -146,8 +135,8 @@ struct btBulletSerializedArrays
btBulletSerializedArrays()
{
}
- btAlignedObjectArray<struct btQuantizedBvhDoubleData*> m_bvhsDouble;
- btAlignedObjectArray<struct btQuantizedBvhFloatData*> m_bvhsFloat;
+ btAlignedObjectArray<struct btQuantizedBvhDoubleData*> m_bvhsDouble;
+ btAlignedObjectArray<struct btQuantizedBvhFloatData*> m_bvhsFloat;
btAlignedObjectArray<struct btCollisionShapeData*> m_colShapeData;
btAlignedObjectArray<struct btDynamicsWorldDoubleData*> m_dynamicWorldInfoDataDouble;
btAlignedObjectArray<struct btDynamicsWorldFloatData*> m_dynamicWorldInfoDataFloat;
@@ -157,51 +146,42 @@ struct btBulletSerializedArrays
btAlignedObjectArray<struct btCollisionObjectFloatData*> m_collisionObjectDataFloat;
btAlignedObjectArray<struct btTypedConstraintFloatData*> m_constraintDataFloat;
btAlignedObjectArray<struct btTypedConstraintDoubleData*> m_constraintDataDouble;
- btAlignedObjectArray<struct btTypedConstraintData*> m_constraintData;//for backwards compatibility
+ btAlignedObjectArray<struct btTypedConstraintData*> m_constraintData; //for backwards compatibility
btAlignedObjectArray<struct btSoftBodyFloatData*> m_softBodyFloatData;
btAlignedObjectArray<struct btSoftBodyDoubleData*> m_softBodyDoubleData;
-
};
-
///The btDefaultSerializer is the main Bullet serialization class.
///The constructor takes an optional argument for backwards compatibility, it is recommended to leave this empty/zero.
-class btDefaultSerializer : public btSerializer
+class btDefaultSerializer : public btSerializer
{
-
protected:
+ btAlignedObjectArray<char*> mTypes;
+ btAlignedObjectArray<short*> mStructs;
+ btAlignedObjectArray<short> mTlens;
+ btHashMap<btHashInt, int> mStructReverse;
+ btHashMap<btHashString, int> mTypeLookup;
- btAlignedObjectArray<char*> mTypes;
- btAlignedObjectArray<short*> mStructs;
- btAlignedObjectArray<short> mTlens;
- btHashMap<btHashInt, int> mStructReverse;
- btHashMap<btHashString,int> mTypeLookup;
-
+ btHashMap<btHashPtr, void*> m_chunkP;
+ btHashMap<btHashPtr, const char*> m_nameMap;
- btHashMap<btHashPtr,void*> m_chunkP;
+ btHashMap<btHashPtr, btPointerUid> m_uniquePointers;
+ int m_uniqueIdGenerator;
- btHashMap<btHashPtr,const char*> m_nameMap;
+ int m_totalSize;
+ unsigned char* m_buffer;
+ bool m_ownsBuffer;
+ int m_currentSize;
+ void* m_dna;
+ int m_dnaLength;
- btHashMap<btHashPtr,btPointerUid> m_uniquePointers;
- int m_uniqueIdGenerator;
+ int m_serializationFlags;
- int m_totalSize;
- unsigned char* m_buffer;
- bool m_ownsBuffer;
- int m_currentSize;
- void* m_dna;
- int m_dnaLength;
-
- int m_serializationFlags;
-
-
- btAlignedObjectArray<btChunk*> m_chunkPtrs;
+ btAlignedObjectArray<btChunk*> m_chunkPtrs;
protected:
-
-
- virtual void* findPointer(void* oldPtr)
+ virtual void* findPointer(void* oldPtr)
{
void** ptr = m_chunkP.find(oldPtr);
if (ptr && *ptr)
@@ -209,48 +189,43 @@ protected:
return 0;
}
+ virtual void writeDNA()
+ {
+ btChunk* dnaChunk = allocate(m_dnaLength, 1);
+ memcpy(dnaChunk->m_oldPtr, m_dna, m_dnaLength);
+ finalizeChunk(dnaChunk, "DNA1", BT_DNA_CODE, m_dna);
+ }
+ int getReverseType(const char* type) const
+ {
+ btHashString key(type);
+ const int* valuePtr = mTypeLookup.find(key);
+ if (valuePtr)
+ return *valuePtr;
+ return -1;
+ }
+ void initDNA(const char* bdnaOrg, int dnalen)
+ {
+ ///was already initialized
+ if (m_dna)
+ return;
- virtual void writeDNA()
- {
- btChunk* dnaChunk = allocate(m_dnaLength,1);
- memcpy(dnaChunk->m_oldPtr,m_dna,m_dnaLength);
- finalizeChunk(dnaChunk,"DNA1",BT_DNA_CODE, m_dna);
- }
-
- int getReverseType(const char *type) const
- {
-
- btHashString key(type);
- const int* valuePtr = mTypeLookup.find(key);
- if (valuePtr)
- return *valuePtr;
-
- return -1;
- }
-
- void initDNA(const char* bdnaOrg,int dnalen)
- {
- ///was already initialized
- if (m_dna)
- return;
-
- int littleEndian= 1;
- littleEndian= ((char*)&littleEndian)[0];
-
+ int littleEndian = 1;
+ littleEndian = ((char*)&littleEndian)[0];
- m_dna = btAlignedAlloc(dnalen,16);
- memcpy(m_dna,bdnaOrg,dnalen);
- m_dnaLength = dnalen;
+ m_dna = btAlignedAlloc(dnalen, 16);
+ memcpy(m_dna, bdnaOrg, dnalen);
+ m_dnaLength = dnalen;
- int *intPtr=0;
- short *shtPtr=0;
- char *cp = 0;int dataLen =0;
- intPtr = (int*)m_dna;
+ int* intPtr = 0;
+ short* shtPtr = 0;
+ char* cp = 0;
+ int dataLen = 0;
+ intPtr = (int*)m_dna;
- /*
+ /*
SDNA (4 bytes) (magic number)
NAME (4 bytes)
<nr> (4 bytes) amount of names (int)
@@ -258,81 +233,81 @@ protected:
<string>
*/
- if (strncmp((const char*)m_dna, "SDNA", 4)==0)
- {
- // skip ++ NAME
- intPtr++; intPtr++;
- }
-
- // Parse names
- if (!littleEndian)
- *intPtr = btSwapEndian(*intPtr);
+ if (strncmp((const char*)m_dna, "SDNA", 4) == 0)
+ {
+ // skip ++ NAME
+ intPtr++;
+ intPtr++;
+ }
- dataLen = *intPtr;
+ // Parse names
+ if (!littleEndian)
+ *intPtr = btSwapEndian(*intPtr);
- intPtr++;
+ dataLen = *intPtr;
- cp = (char*)intPtr;
- int i;
- for ( i=0; i<dataLen; i++)
- {
+ intPtr++;
- while (*cp)cp++;
- cp++;
- }
- cp = btAlignPointer(cp,4);
+ cp = (char*)intPtr;
+ int i;
+ for (i = 0; i < dataLen; i++)
+ {
+ while (*cp) cp++;
+ cp++;
+ }
+ cp = btAlignPointer(cp, 4);
- /*
+ /*
TYPE (4 bytes)
<nr> amount of types (int)
<string>
<string>
*/
- intPtr = (int*)cp;
- btAssert(strncmp(cp, "TYPE", 4)==0); intPtr++;
+ intPtr = (int*)cp;
+ btAssert(strncmp(cp, "TYPE", 4) == 0);
+ intPtr++;
- if (!littleEndian)
- *intPtr = btSwapEndian(*intPtr);
+ if (!littleEndian)
+ *intPtr = btSwapEndian(*intPtr);
- dataLen = *intPtr;
- intPtr++;
+ dataLen = *intPtr;
+ intPtr++;
+ cp = (char*)intPtr;
+ for (i = 0; i < dataLen; i++)
+ {
+ mTypes.push_back(cp);
+ while (*cp) cp++;
+ cp++;
+ }
- cp = (char*)intPtr;
- for (i=0; i<dataLen; i++)
- {
- mTypes.push_back(cp);
- while (*cp)cp++;
- cp++;
- }
-
- cp = btAlignPointer(cp,4);
-
+ cp = btAlignPointer(cp, 4);
- /*
+ /*
TLEN (4 bytes)
<len> (short) the lengths of types
<len>
*/
- // Parse type lens
- intPtr = (int*)cp;
- btAssert(strncmp(cp, "TLEN", 4)==0); intPtr++;
+ // Parse type lens
+ intPtr = (int*)cp;
+ btAssert(strncmp(cp, "TLEN", 4) == 0);
+ intPtr++;
- dataLen = (int)mTypes.size();
+ dataLen = (int)mTypes.size();
- shtPtr = (short*)intPtr;
- for (i=0; i<dataLen; i++, shtPtr++)
- {
- if (!littleEndian)
- shtPtr[0] = btSwapEndian(shtPtr[0]);
- mTlens.push_back(shtPtr[0]);
- }
+ shtPtr = (short*)intPtr;
+ for (i = 0; i < dataLen; i++, shtPtr++)
+ {
+ if (!littleEndian)
+ shtPtr[0] = btSwapEndian(shtPtr[0]);
+ mTlens.push_back(shtPtr[0]);
+ }
- if (dataLen & 1) shtPtr++;
+ if (dataLen & 1) shtPtr++;
- /*
+ /*
STRC (4 bytes)
<nr> amount of structs (int)
<typenr>
@@ -343,384 +318,372 @@ protected:
<namenr>
*/
- intPtr = (int*)shtPtr;
- cp = (char*)intPtr;
- btAssert(strncmp(cp, "STRC", 4)==0); intPtr++;
+ intPtr = (int*)shtPtr;
+ cp = (char*)intPtr;
+ btAssert(strncmp(cp, "STRC", 4) == 0);
+ intPtr++;
- if (!littleEndian)
- *intPtr = btSwapEndian(*intPtr);
- dataLen = *intPtr ;
- intPtr++;
+ if (!littleEndian)
+ *intPtr = btSwapEndian(*intPtr);
+ dataLen = *intPtr;
+ intPtr++;
+ shtPtr = (short*)intPtr;
+ for (i = 0; i < dataLen; i++)
+ {
+ mStructs.push_back(shtPtr);
- shtPtr = (short*)intPtr;
- for (i=0; i<dataLen; i++)
+ if (!littleEndian)
{
- mStructs.push_back (shtPtr);
+ shtPtr[0] = btSwapEndian(shtPtr[0]);
+ shtPtr[1] = btSwapEndian(shtPtr[1]);
- if (!littleEndian)
- {
- shtPtr[0]= btSwapEndian(shtPtr[0]);
- shtPtr[1]= btSwapEndian(shtPtr[1]);
-
- int len = shtPtr[1];
- shtPtr+= 2;
-
- for (int a=0; a<len; a++, shtPtr+=2)
- {
- shtPtr[0]= btSwapEndian(shtPtr[0]);
- shtPtr[1]= btSwapEndian(shtPtr[1]);
- }
+ int len = shtPtr[1];
+ shtPtr += 2;
- } else
+ for (int a = 0; a < len; a++, shtPtr += 2)
{
- shtPtr+= (2*shtPtr[1])+2;
+ shtPtr[0] = btSwapEndian(shtPtr[0]);
+ shtPtr[1] = btSwapEndian(shtPtr[1]);
}
}
-
- // build reverse lookups
- for (i=0; i<(int)mStructs.size(); i++)
+ else
{
- short *strc = mStructs.at(i);
- mStructReverse.insert(strc[0], i);
- mTypeLookup.insert(btHashString(mTypes[strc[0]]),i);
+ shtPtr += (2 * shtPtr[1]) + 2;
}
}
-public:
-
- btHashMap<btHashPtr,void*> m_skipPointers;
-
+ // build reverse lookups
+ for (i = 0; i < (int)mStructs.size(); i++)
+ {
+ short* strc = mStructs.at(i);
+ mStructReverse.insert(strc[0], i);
+ mTypeLookup.insert(btHashString(mTypes[strc[0]]), i);
+ }
+ }
- btDefaultSerializer(int totalSize=0, unsigned char* buffer=0)
- :m_uniqueIdGenerator(0),
- m_totalSize(totalSize),
- m_currentSize(0),
- m_dna(0),
- m_dnaLength(0),
- m_serializationFlags(0)
+public:
+ btHashMap<btHashPtr, void*> m_skipPointers;
+
+ btDefaultSerializer(int totalSize = 0, unsigned char* buffer = 0)
+ : m_uniqueIdGenerator(0),
+ m_totalSize(totalSize),
+ m_currentSize(0),
+ m_dna(0),
+ m_dnaLength(0),
+ m_serializationFlags(0)
+ {
+ if (buffer == 0)
+ {
+ m_buffer = m_totalSize ? (unsigned char*)btAlignedAlloc(totalSize, 16) : 0;
+ m_ownsBuffer = true;
+ }
+ else
{
- if (buffer==0)
- {
- m_buffer = m_totalSize?(unsigned char*)btAlignedAlloc(totalSize,16):0;
- m_ownsBuffer = true;
- } else
- {
- m_buffer = buffer;
- m_ownsBuffer = false;
- }
-
- const bool VOID_IS_8 = ((sizeof(void*)==8));
+ m_buffer = buffer;
+ m_ownsBuffer = false;
+ }
+
+ const bool VOID_IS_8 = ((sizeof(void*) == 8));
#ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
- if (VOID_IS_8)
- {
+ if (VOID_IS_8)
+ {
#if _WIN64
- initDNA((const char*)sBulletDNAstr64,sBulletDNAlen64);
+ initDNA((const char*)sBulletDNAstr64, sBulletDNAlen64);
#else
- btAssert(0);
+ btAssert(0);
#endif
- } else
- {
+ }
+ else
+ {
#ifndef _WIN64
- initDNA((const char*)sBulletDNAstr,sBulletDNAlen);
+ initDNA((const char*)sBulletDNAstr, sBulletDNAlen);
#else
- btAssert(0);
+ btAssert(0);
#endif
- }
-
-#else //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
- if (VOID_IS_8)
- {
- initDNA((const char*)sBulletDNAstr64,sBulletDNAlen64);
- } else
- {
- initDNA((const char*)sBulletDNAstr,sBulletDNAlen);
- }
-#endif //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
-
}
- virtual ~btDefaultSerializer()
+#else //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+ if (VOID_IS_8)
{
- if (m_buffer && m_ownsBuffer)
- btAlignedFree(m_buffer);
- if (m_dna)
- btAlignedFree(m_dna);
- }
-
- static int getMemoryDnaSizeInBytes()
- {
- const bool VOID_IS_8 = ((sizeof(void*) == 8));
-
- if (VOID_IS_8)
- {
- return sBulletDNAlen64;
- }
- return sBulletDNAlen;
+ initDNA((const char*)sBulletDNAstr64, sBulletDNAlen64);
}
- static const char* getMemoryDna()
+ else
{
- const bool VOID_IS_8 = ((sizeof(void*) == 8));
- if (VOID_IS_8)
- {
- return (const char*)sBulletDNAstr64;
- }
- return (const char*)sBulletDNAstr;
+ initDNA((const char*)sBulletDNAstr, sBulletDNAlen);
}
+#endif //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+ }
- void insertHeader()
+ virtual ~btDefaultSerializer()
+ {
+ if (m_buffer && m_ownsBuffer)
+ btAlignedFree(m_buffer);
+ if (m_dna)
+ btAlignedFree(m_dna);
+ }
+
+ static int getMemoryDnaSizeInBytes()
+ {
+ const bool VOID_IS_8 = ((sizeof(void*) == 8));
+
+ if (VOID_IS_8)
{
- writeHeader(m_buffer);
- m_currentSize += BT_HEADER_LENGTH;
+ return sBulletDNAlen64;
}
-
- void writeHeader(unsigned char* buffer) const
+ return sBulletDNAlen;
+ }
+ static const char* getMemoryDna()
+ {
+ const bool VOID_IS_8 = ((sizeof(void*) == 8));
+ if (VOID_IS_8)
{
+ return (const char*)sBulletDNAstr64;
+ }
+ return (const char*)sBulletDNAstr;
+ }
+ void insertHeader()
+ {
+ writeHeader(m_buffer);
+ m_currentSize += BT_HEADER_LENGTH;
+ }
-#ifdef BT_USE_DOUBLE_PRECISION
- memcpy(buffer, "BULLETd", 7);
+ void writeHeader(unsigned char* buffer) const
+ {
+#ifdef BT_USE_DOUBLE_PRECISION
+ memcpy(buffer, "BULLETd", 7);
#else
- memcpy(buffer, "BULLETf", 7);
-#endif //BT_USE_DOUBLE_PRECISION
-
- int littleEndian= 1;
- littleEndian= ((char*)&littleEndian)[0];
+ memcpy(buffer, "BULLETf", 7);
+#endif //BT_USE_DOUBLE_PRECISION
- if (sizeof(void*)==8)
- {
- buffer[7] = '-';
- } else
- {
- buffer[7] = '_';
- }
-
- if (littleEndian)
- {
- buffer[8]='v';
- } else
- {
- buffer[8]='V';
- }
-
-
- buffer[9] = '2';
- buffer[10] = '8';
- buffer[11] = '8';
+ int littleEndian = 1;
+ littleEndian = ((char*)&littleEndian)[0];
+ if (sizeof(void*) == 8)
+ {
+ buffer[7] = '-';
}
-
- virtual void startSerialization()
+ else
{
- m_uniqueIdGenerator= 1;
- if (m_totalSize)
- {
- unsigned char* buffer = internalAlloc(BT_HEADER_LENGTH);
- writeHeader(buffer);
- }
-
+ buffer[7] = '_';
}
- virtual void finishSerialization()
+ if (littleEndian)
{
- writeDNA();
-
- //if we didn't pre-allocate a buffer, we need to create a contiguous buffer now
- int mysize = 0;
- if (!m_totalSize)
- {
- if (m_buffer)
- btAlignedFree(m_buffer);
-
- m_currentSize += BT_HEADER_LENGTH;
- m_buffer = (unsigned char*)btAlignedAlloc(m_currentSize,16);
+ buffer[8] = 'v';
+ }
+ else
+ {
+ buffer[8] = 'V';
+ }
- unsigned char* currentPtr = m_buffer;
- writeHeader(m_buffer);
- currentPtr += BT_HEADER_LENGTH;
- mysize+=BT_HEADER_LENGTH;
- for (int i=0;i< m_chunkPtrs.size();i++)
- {
- int curLength = sizeof(btChunk)+m_chunkPtrs[i]->m_length;
- memcpy(currentPtr,m_chunkPtrs[i], curLength);
- btAlignedFree(m_chunkPtrs[i]);
- currentPtr+=curLength;
- mysize+=curLength;
- }
- }
+ buffer[9] = '2';
+ buffer[10] = '8';
+ buffer[11] = '8';
+ }
- mTypes.clear();
- mStructs.clear();
- mTlens.clear();
- mStructReverse.clear();
- mTypeLookup.clear();
- m_skipPointers.clear();
- m_chunkP.clear();
- m_nameMap.clear();
- m_uniquePointers.clear();
- m_chunkPtrs.clear();
+ virtual void startSerialization()
+ {
+ m_uniqueIdGenerator = 1;
+ if (m_totalSize)
+ {
+ unsigned char* buffer = internalAlloc(BT_HEADER_LENGTH);
+ writeHeader(buffer);
}
+ }
- virtual void* getUniquePointer(void*oldPtr)
+ virtual void finishSerialization()
+ {
+ writeDNA();
+
+ //if we didn't pre-allocate a buffer, we need to create a contiguous buffer now
+ int mysize = 0;
+ if (!m_totalSize)
{
- btAssert(m_uniqueIdGenerator >= 0);
- if (!oldPtr)
- return 0;
+ if (m_buffer)
+ btAlignedFree(m_buffer);
- btPointerUid* uptr = (btPointerUid*)m_uniquePointers.find(oldPtr);
- if (uptr)
- {
- return uptr->m_ptr;
- }
+ m_currentSize += BT_HEADER_LENGTH;
+ m_buffer = (unsigned char*)btAlignedAlloc(m_currentSize, 16);
- void** ptr2 = m_skipPointers[oldPtr];
- if (ptr2)
+ unsigned char* currentPtr = m_buffer;
+ writeHeader(m_buffer);
+ currentPtr += BT_HEADER_LENGTH;
+ mysize += BT_HEADER_LENGTH;
+ for (int i = 0; i < m_chunkPtrs.size(); i++)
{
- return 0;
+ int curLength = sizeof(btChunk) + m_chunkPtrs[i]->m_length;
+ memcpy(currentPtr, m_chunkPtrs[i], curLength);
+ btAlignedFree(m_chunkPtrs[i]);
+ currentPtr += curLength;
+ mysize += curLength;
}
+ }
- m_uniqueIdGenerator++;
-
- btPointerUid uid;
- uid.m_uniqueIds[0] = m_uniqueIdGenerator;
- uid.m_uniqueIds[1] = m_uniqueIdGenerator;
- m_uniquePointers.insert(oldPtr,uid);
- return uid.m_ptr;
+ mTypes.clear();
+ mStructs.clear();
+ mTlens.clear();
+ mStructReverse.clear();
+ mTypeLookup.clear();
+ m_skipPointers.clear();
+ m_chunkP.clear();
+ m_nameMap.clear();
+ m_uniquePointers.clear();
+ m_chunkPtrs.clear();
+ }
- }
+ virtual void* getUniquePointer(void* oldPtr)
+ {
+ btAssert(m_uniqueIdGenerator >= 0);
+ if (!oldPtr)
+ return 0;
- virtual const unsigned char* getBufferPointer() const
+ btPointerUid* uptr = (btPointerUid*)m_uniquePointers.find(oldPtr);
+ if (uptr)
{
- return m_buffer;
+ return uptr->m_ptr;
}
- virtual int getCurrentBufferSize() const
+ void** ptr2 = m_skipPointers[oldPtr];
+ if (ptr2)
{
- return m_currentSize;
+ return 0;
}
- virtual void finalizeChunk(btChunk* chunk, const char* structType, int chunkCode,void* oldPtr)
- {
- if (!(m_serializationFlags&BT_SERIALIZE_NO_DUPLICATE_ASSERT))
- {
- btAssert(!findPointer(oldPtr));
- }
+ m_uniqueIdGenerator++;
- chunk->m_dna_nr = getReverseType(structType);
-
- chunk->m_chunkCode = chunkCode;
+ btPointerUid uid;
+ uid.m_uniqueIds[0] = m_uniqueIdGenerator;
+ uid.m_uniqueIds[1] = m_uniqueIdGenerator;
+ m_uniquePointers.insert(oldPtr, uid);
+ return uid.m_ptr;
+ }
- void* uniquePtr = getUniquePointer(oldPtr);
+ virtual const unsigned char* getBufferPointer() const
+ {
+ return m_buffer;
+ }
- m_chunkP.insert(oldPtr,uniquePtr);//chunk->m_oldPtr);
- chunk->m_oldPtr = uniquePtr;//oldPtr;
+ virtual int getCurrentBufferSize() const
+ {
+ return m_currentSize;
+ }
+ virtual void finalizeChunk(btChunk* chunk, const char* structType, int chunkCode, void* oldPtr)
+ {
+ if (!(m_serializationFlags & BT_SERIALIZE_NO_DUPLICATE_ASSERT))
+ {
+ btAssert(!findPointer(oldPtr));
}
+ chunk->m_dna_nr = getReverseType(structType);
- virtual unsigned char* internalAlloc(size_t size)
- {
- unsigned char* ptr = 0;
+ chunk->m_chunkCode = chunkCode;
- if (m_totalSize)
- {
- ptr = m_buffer+m_currentSize;
- m_currentSize += int(size);
- btAssert(m_currentSize<m_totalSize);
- } else
- {
- ptr = (unsigned char*)btAlignedAlloc(size,16);
- m_currentSize += int(size);
- }
- return ptr;
- }
+ void* uniquePtr = getUniquePointer(oldPtr);
+ m_chunkP.insert(oldPtr, uniquePtr); //chunk->m_oldPtr);
+ chunk->m_oldPtr = uniquePtr; //oldPtr;
+ }
+ virtual unsigned char* internalAlloc(size_t size)
+ {
+ unsigned char* ptr = 0;
- virtual btChunk* allocate(size_t size, int numElements)
+ if (m_totalSize)
{
+ ptr = m_buffer + m_currentSize;
+ m_currentSize += int(size);
+ btAssert(m_currentSize < m_totalSize);
+ }
+ else
+ {
+ ptr = (unsigned char*)btAlignedAlloc(size, 16);
+ m_currentSize += int(size);
+ }
+ return ptr;
+ }
- unsigned char* ptr = internalAlloc(int(size)*numElements+sizeof(btChunk));
-
- unsigned char* data = ptr + sizeof(btChunk);
+ virtual btChunk* allocate(size_t size, int numElements)
+ {
+ unsigned char* ptr = internalAlloc(int(size) * numElements + sizeof(btChunk));
- btChunk* chunk = (btChunk*)ptr;
- chunk->m_chunkCode = 0;
- chunk->m_oldPtr = data;
- chunk->m_length = int(size)*numElements;
- chunk->m_number = numElements;
+ unsigned char* data = ptr + sizeof(btChunk);
- m_chunkPtrs.push_back(chunk);
+ btChunk* chunk = (btChunk*)ptr;
+ chunk->m_chunkCode = 0;
+ chunk->m_oldPtr = data;
+ chunk->m_length = int(size) * numElements;
+ chunk->m_number = numElements;
+ m_chunkPtrs.push_back(chunk);
- return chunk;
- }
+ return chunk;
+ }
- virtual const char* findNameForPointer(const void* ptr) const
- {
- const char*const * namePtr = m_nameMap.find(ptr);
- if (namePtr && *namePtr)
- return *namePtr;
- return 0;
+ virtual const char* findNameForPointer(const void* ptr) const
+ {
+ const char* const* namePtr = m_nameMap.find(ptr);
+ if (namePtr && *namePtr)
+ return *namePtr;
+ return 0;
+ }
- }
+ virtual void registerNameForPointer(const void* ptr, const char* name)
+ {
+ m_nameMap.insert(ptr, name);
+ }
- virtual void registerNameForPointer(const void* ptr, const char* name)
+ virtual void serializeName(const char* name)
+ {
+ if (name)
{
- m_nameMap.insert(ptr,name);
- }
+ //don't serialize name twice
+ if (findPointer((void*)name))
+ return;
- virtual void serializeName(const char* name)
- {
- if (name)
+ int len = btStrLen(name);
+ if (len)
{
- //don't serialize name twice
- if (findPointer((void*)name))
- return;
-
- int len = btStrLen(name);
- if (len)
+ int newLen = len + 1;
+ int padding = ((newLen + 3) & ~3) - newLen;
+ newLen += padding;
+
+ //serialize name string now
+ btChunk* chunk = allocate(sizeof(char), newLen);
+ char* destinationName = (char*)chunk->m_oldPtr;
+ for (int i = 0; i < len; i++)
{
-
- int newLen = len+1;
- int padding = ((newLen+3)&~3)-newLen;
- newLen += padding;
-
- //serialize name string now
- btChunk* chunk = allocate(sizeof(char),newLen);
- char* destinationName = (char*)chunk->m_oldPtr;
- for (int i=0;i<len;i++)
- {
- destinationName[i] = name[i];
- }
- destinationName[len] = 0;
- finalizeChunk(chunk,"char",BT_ARRAY_CODE,(void*)name);
+ destinationName[i] = name[i];
}
+ destinationName[len] = 0;
+ finalizeChunk(chunk, "char", BT_ARRAY_CODE, (void*)name);
}
}
+ }
- virtual int getSerializationFlags() const
- {
- return m_serializationFlags;
- }
+ virtual int getSerializationFlags() const
+ {
+ return m_serializationFlags;
+ }
- virtual void setSerializationFlags(int flags)
- {
- m_serializationFlags = flags;
- }
- int getNumChunks() const
- {
- return m_chunkPtrs.size();
- }
+ virtual void setSerializationFlags(int flags)
+ {
+ m_serializationFlags = flags;
+ }
+ int getNumChunks() const
+ {
+ return m_chunkPtrs.size();
+ }
- const btChunk* getChunk(int chunkIndex) const
- {
- return m_chunkPtrs[chunkIndex];
- }
+ const btChunk* getChunk(int chunkIndex) const
+ {
+ return m_chunkPtrs[chunkIndex];
+ }
};
-
///In general it is best to use btDefaultSerializer,
///in particular when writing the data to disk or sending it over the network.
///The btInMemorySerializer is experimental and only suitable in a few cases.
@@ -730,181 +693,177 @@ public:
struct btInMemorySerializer : public btDefaultSerializer
{
- btHashMap<btHashPtr,btChunk*> m_uid2ChunkPtr;
- btHashMap<btHashPtr,void*> m_orgPtr2UniqueDataPtr;
- btHashMap<btHashString,const void*> m_names2Ptr;
-
-
- btBulletSerializedArrays m_arrays;
-
- btInMemorySerializer(int totalSize=0, unsigned char* buffer=0)
- :btDefaultSerializer(totalSize,buffer)
- {
-
- }
-
- virtual void startSerialization()
- {
- m_uid2ChunkPtr.clear();
- //todo: m_arrays.clear();
- btDefaultSerializer::startSerialization();
- }
-
-
-
- btChunk* findChunkFromUniquePointer(void* uniquePointer)
- {
- btChunk** chkPtr = m_uid2ChunkPtr[uniquePointer];
- if (chkPtr)
- {
- return *chkPtr;
- }
- return 0;
- }
-
- virtual void registerNameForPointer(const void* ptr, const char* name)
- {
- btDefaultSerializer::registerNameForPointer(ptr,name);
- m_names2Ptr.insert(name,ptr);
- }
-
- virtual void finishSerialization()
- {
- }
-
- virtual void* getUniquePointer(void*oldPtr)
- {
- if (oldPtr==0)
- return 0;
-
- // void* uniquePtr = getUniquePointer(oldPtr);
- btChunk* chunk = findChunkFromUniquePointer(oldPtr);
- if (chunk)
- {
- return chunk->m_oldPtr;
- } else
- {
- const char* n = (const char*) oldPtr;
- const void** ptr = m_names2Ptr[n];
- if (ptr)
- {
- return oldPtr;
- } else
- {
- void** ptr2 = m_skipPointers[oldPtr];
- if (ptr2)
- {
- return 0;
- } else
- {
- //If this assert hit, serialization happened in the wrong order
- // 'getUniquePointer'
- btAssert(0);
- }
-
- }
- return 0;
- }
- return oldPtr;
- }
+ btHashMap<btHashPtr, btChunk*> m_uid2ChunkPtr;
+ btHashMap<btHashPtr, void*> m_orgPtr2UniqueDataPtr;
+ btHashMap<btHashString, const void*> m_names2Ptr;
+
+ btBulletSerializedArrays m_arrays;
+
+ btInMemorySerializer(int totalSize = 0, unsigned char* buffer = 0)
+ : btDefaultSerializer(totalSize, buffer)
+ {
+ }
+
+ virtual void startSerialization()
+ {
+ m_uid2ChunkPtr.clear();
+ //todo: m_arrays.clear();
+ btDefaultSerializer::startSerialization();
+ }
- virtual void finalizeChunk(btChunk* chunk, const char* structType, int chunkCode,void* oldPtr)
- {
- if (!(m_serializationFlags&BT_SERIALIZE_NO_DUPLICATE_ASSERT))
- {
- btAssert(!findPointer(oldPtr));
- }
+ btChunk* findChunkFromUniquePointer(void* uniquePointer)
+ {
+ btChunk** chkPtr = m_uid2ChunkPtr[uniquePointer];
+ if (chkPtr)
+ {
+ return *chkPtr;
+ }
+ return 0;
+ }
- chunk->m_dna_nr = getReverseType(structType);
- chunk->m_chunkCode = chunkCode;
- //void* uniquePtr = getUniquePointer(oldPtr);
- m_chunkP.insert(oldPtr,oldPtr);//chunk->m_oldPtr);
- // chunk->m_oldPtr = uniquePtr;//oldPtr;
+ virtual void registerNameForPointer(const void* ptr, const char* name)
+ {
+ btDefaultSerializer::registerNameForPointer(ptr, name);
+ m_names2Ptr.insert(name, ptr);
+ }
- void* uid = findPointer(oldPtr);
- m_uid2ChunkPtr.insert(uid,chunk);
+ virtual void finishSerialization()
+ {
+ }
- switch (chunk->m_chunkCode)
+ virtual void* getUniquePointer(void* oldPtr)
+ {
+ if (oldPtr == 0)
+ return 0;
+
+ // void* uniquePtr = getUniquePointer(oldPtr);
+ btChunk* chunk = findChunkFromUniquePointer(oldPtr);
+ if (chunk)
+ {
+ return chunk->m_oldPtr;
+ }
+ else
+ {
+ const char* n = (const char*)oldPtr;
+ const void** ptr = m_names2Ptr[n];
+ if (ptr)
{
- case BT_SOFTBODY_CODE:
+ return oldPtr;
+ }
+ else
{
- #ifdef BT_USE_DOUBLE_PRECISION
- m_arrays.m_softBodyDoubleData.push_back((btSoftBodyDoubleData*) chunk->m_oldPtr);
- #else
- m_arrays.m_softBodyFloatData.push_back((btSoftBodyFloatData*) chunk->m_oldPtr);
- #endif
- break;
+ void** ptr2 = m_skipPointers[oldPtr];
+ if (ptr2)
+ {
+ return 0;
}
- case BT_COLLISIONOBJECT_CODE:
+ else
{
- #ifdef BT_USE_DOUBLE_PRECISION
- m_arrays.m_collisionObjectDataDouble.push_back((btCollisionObjectDoubleData*)chunk->m_oldPtr);
- #else//BT_USE_DOUBLE_PRECISION
- m_arrays.m_collisionObjectDataFloat.push_back((btCollisionObjectFloatData*)chunk->m_oldPtr);
- #endif //BT_USE_DOUBLE_PRECISION
- break;
+ //If this assert hit, serialization happened in the wrong order
+ // 'getUniquePointer'
+ btAssert(0);
}
+ }
+ return 0;
+ }
+ return oldPtr;
+ }
+
+ virtual void finalizeChunk(btChunk* chunk, const char* structType, int chunkCode, void* oldPtr)
+ {
+ if (!(m_serializationFlags & BT_SERIALIZE_NO_DUPLICATE_ASSERT))
+ {
+ btAssert(!findPointer(oldPtr));
+ }
+
+ chunk->m_dna_nr = getReverseType(structType);
+ chunk->m_chunkCode = chunkCode;
+ //void* uniquePtr = getUniquePointer(oldPtr);
+ m_chunkP.insert(oldPtr, oldPtr); //chunk->m_oldPtr);
+ // chunk->m_oldPtr = uniquePtr;//oldPtr;
+
+ void* uid = findPointer(oldPtr);
+ m_uid2ChunkPtr.insert(uid, chunk);
+
+ switch (chunk->m_chunkCode)
+ {
+ case BT_SOFTBODY_CODE:
+ {
+#ifdef BT_USE_DOUBLE_PRECISION
+ m_arrays.m_softBodyDoubleData.push_back((btSoftBodyDoubleData*)chunk->m_oldPtr);
+#else
+ m_arrays.m_softBodyFloatData.push_back((btSoftBodyFloatData*)chunk->m_oldPtr);
+#endif
+ break;
+ }
+ case BT_COLLISIONOBJECT_CODE:
+ {
+#ifdef BT_USE_DOUBLE_PRECISION
+ m_arrays.m_collisionObjectDataDouble.push_back((btCollisionObjectDoubleData*)chunk->m_oldPtr);
+#else //BT_USE_DOUBLE_PRECISION
+ m_arrays.m_collisionObjectDataFloat.push_back((btCollisionObjectFloatData*)chunk->m_oldPtr);
+#endif //BT_USE_DOUBLE_PRECISION
+ break;
+ }
case BT_RIGIDBODY_CODE:
- {
- #ifdef BT_USE_DOUBLE_PRECISION
- m_arrays.m_rigidBodyDataDouble.push_back((btRigidBodyDoubleData*)chunk->m_oldPtr);
- #else
- m_arrays.m_rigidBodyDataFloat.push_back((btRigidBodyFloatData*)chunk->m_oldPtr);
- #endif//BT_USE_DOUBLE_PRECISION
- break;
- };
+ {
+#ifdef BT_USE_DOUBLE_PRECISION
+ m_arrays.m_rigidBodyDataDouble.push_back((btRigidBodyDoubleData*)chunk->m_oldPtr);
+#else
+ m_arrays.m_rigidBodyDataFloat.push_back((btRigidBodyFloatData*)chunk->m_oldPtr);
+#endif //BT_USE_DOUBLE_PRECISION
+ break;
+ };
case BT_CONSTRAINT_CODE:
- {
- #ifdef BT_USE_DOUBLE_PRECISION
- m_arrays.m_constraintDataDouble.push_back((btTypedConstraintDoubleData*)chunk->m_oldPtr);
- #else
- m_arrays.m_constraintDataFloat.push_back((btTypedConstraintFloatData*)chunk->m_oldPtr);
- #endif
- break;
- }
+ {
+#ifdef BT_USE_DOUBLE_PRECISION
+ m_arrays.m_constraintDataDouble.push_back((btTypedConstraintDoubleData*)chunk->m_oldPtr);
+#else
+ m_arrays.m_constraintDataFloat.push_back((btTypedConstraintFloatData*)chunk->m_oldPtr);
+#endif
+ break;
+ }
case BT_QUANTIZED_BVH_CODE:
- {
- #ifdef BT_USE_DOUBLE_PRECISION
- m_arrays.m_bvhsDouble.push_back((btQuantizedBvhDoubleData*) chunk->m_oldPtr);
- #else
- m_arrays.m_bvhsFloat.push_back((btQuantizedBvhFloatData*) chunk->m_oldPtr);
- #endif
- break;
- }
+ {
+#ifdef BT_USE_DOUBLE_PRECISION
+ m_arrays.m_bvhsDouble.push_back((btQuantizedBvhDoubleData*)chunk->m_oldPtr);
+#else
+ m_arrays.m_bvhsFloat.push_back((btQuantizedBvhFloatData*)chunk->m_oldPtr);
+#endif
+ break;
+ }
case BT_SHAPE_CODE:
- {
- btCollisionShapeData* shapeData = (btCollisionShapeData*) chunk->m_oldPtr;
- m_arrays.m_colShapeData.push_back(shapeData);
- break;
- }
+ {
+ btCollisionShapeData* shapeData = (btCollisionShapeData*)chunk->m_oldPtr;
+ m_arrays.m_colShapeData.push_back(shapeData);
+ break;
+ }
case BT_TRIANLGE_INFO_MAP:
case BT_ARRAY_CODE:
case BT_SBMATERIAL_CODE:
case BT_SBNODE_CODE:
case BT_DYNAMICSWORLD_CODE:
case BT_DNA_CODE:
- {
- break;
- }
+ {
+ break;
+ }
default:
- {
- }
- };
- }
-
- int getNumChunks() const
- {
- return m_uid2ChunkPtr.size();
- }
+ {
+ }
+ };
+ }
- const btChunk* getChunk(int chunkIndex) const
- {
- return *m_uid2ChunkPtr.getAtIndex(chunkIndex);
- }
+ int getNumChunks() const
+ {
+ return m_uid2ChunkPtr.size();
+ }
+ const btChunk* getChunk(int chunkIndex) const
+ {
+ return *m_uid2ChunkPtr.getAtIndex(chunkIndex);
+ }
};
-#endif //ENABLE_INMEMORY_SERIALIZER
-
-#endif //BT_SERIALIZER_H
+#endif //ENABLE_INMEMORY_SERIALIZER
+#endif //BT_SERIALIZER_H
diff --git a/thirdparty/bullet/LinearMath/btSerializer64.cpp b/thirdparty/bullet/LinearMath/btSerializer64.cpp
index 0aa5cbf30e..cf281cdb36 100644
--- a/thirdparty/bullet/LinearMath/btSerializer64.cpp
+++ b/thirdparty/bullet/LinearMath/btSerializer64.cpp
@@ -1,3 +1,4 @@
+// clang-format off
char sBulletDNAstr64[]= {
char(83),char(68),char(78),char(65),char(78),char(65),char(77),char(69),char(-76),char(1),char(0),char(0),char(109),char(95),char(115),char(105),char(122),char(101),char(0),char(109),
char(95),char(99),char(97),char(112),char(97),char(99),char(105),char(116),char(121),char(0),char(42),char(109),char(95),char(100),char(97),char(116),char(97),char(0),char(109),char(95),
@@ -687,3 +688,4 @@ char(97),char(0),char(4),char(0),char(50),char(0),char(-79),char(1),char(96),cha
char(98),char(0),char(4),char(0),char(48),char(0),char(-79),char(1),char(95),char(0),char(-78),char(1),char(4),char(0),char(-77),char(1),char(0),char(0),char(37),char(0),
};
int sBulletDNAlen64= sizeof(sBulletDNAstr64);
+// clang-format on
diff --git a/thirdparty/bullet/LinearMath/btSpatialAlgebra.h b/thirdparty/bullet/LinearMath/btSpatialAlgebra.h
index 8e59658bca..6ad67a1081 100644
--- a/thirdparty/bullet/LinearMath/btSpatialAlgebra.h
+++ b/thirdparty/bullet/LinearMath/btSpatialAlgebra.h
@@ -12,18 +12,17 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-///These spatial algebra classes are used for btMultiBody,
+///These spatial algebra classes are used for btMultiBody,
///see BulletDynamics/Featherstone
#ifndef BT_SPATIAL_ALGEBRA_H
#define BT_SPATIAL_ALGEBRA_H
-
#include "btMatrix3x3.h"
struct btSpatialForceVector
-{
- btVector3 m_topVec, m_bottomVec;
+{
+ btVector3 m_topVec, m_bottomVec;
//
btSpatialForceVector() { setZero(); }
btSpatialForceVector(const btVector3 &angular, const btVector3 &linear) : m_topVec(linear), m_bottomVec(angular) {}
@@ -32,21 +31,34 @@ struct btSpatialForceVector
setValue(ax, ay, az, lx, ly, lz);
}
//
- void setVector(const btVector3 &angular, const btVector3 &linear) { m_topVec = linear; m_bottomVec = angular; }
+ void setVector(const btVector3 &angular, const btVector3 &linear)
+ {
+ m_topVec = linear;
+ m_bottomVec = angular;
+ }
void setValue(const btScalar &ax, const btScalar &ay, const btScalar &az, const btScalar &lx, const btScalar &ly, const btScalar &lz)
{
- m_bottomVec.setValue(ax, ay, az); m_topVec.setValue(lx, ly, lz);
+ m_bottomVec.setValue(ax, ay, az);
+ m_topVec.setValue(lx, ly, lz);
}
//
- void addVector(const btVector3 &angular, const btVector3 &linear) { m_topVec += linear; m_bottomVec += angular; }
+ void addVector(const btVector3 &angular, const btVector3 &linear)
+ {
+ m_topVec += linear;
+ m_bottomVec += angular;
+ }
void addValue(const btScalar &ax, const btScalar &ay, const btScalar &az, const btScalar &lx, const btScalar &ly, const btScalar &lz)
{
- m_bottomVec[0] += ax; m_bottomVec[1] += ay; m_bottomVec[2] += az;
- m_topVec[0] += lx; m_topVec[1] += ly; m_topVec[2] += lz;
+ m_bottomVec[0] += ax;
+ m_bottomVec[1] += ay;
+ m_bottomVec[2] += az;
+ m_topVec[0] += lx;
+ m_topVec[1] += ly;
+ m_topVec[2] += lz;
}
//
- const btVector3 & getLinear() const { return m_topVec; }
- const btVector3 & getAngular() const { return m_bottomVec; }
+ const btVector3 &getLinear() const { return m_topVec; }
+ const btVector3 &getAngular() const { return m_bottomVec; }
//
void setLinear(const btVector3 &linear) { m_topVec = linear; }
void setAngular(const btVector3 &angular) { m_bottomVec = angular; }
@@ -54,14 +66,28 @@ struct btSpatialForceVector
void addAngular(const btVector3 &angular) { m_bottomVec += angular; }
void addLinear(const btVector3 &linear) { m_topVec += linear; }
//
- void setZero() { m_topVec.setZero(); m_bottomVec.setZero(); }
+ void setZero()
+ {
+ m_topVec.setZero();
+ m_bottomVec.setZero();
+ }
//
- btSpatialForceVector & operator += (const btSpatialForceVector &vec) { m_topVec += vec.m_topVec; m_bottomVec += vec.m_bottomVec; return *this; }
- btSpatialForceVector & operator -= (const btSpatialForceVector &vec) { m_topVec -= vec.m_topVec; m_bottomVec -= vec.m_bottomVec; return *this; }
- btSpatialForceVector operator - (const btSpatialForceVector &vec) const { return btSpatialForceVector(m_bottomVec - vec.m_bottomVec, m_topVec - vec.m_topVec); }
- btSpatialForceVector operator + (const btSpatialForceVector &vec) const { return btSpatialForceVector(m_bottomVec + vec.m_bottomVec, m_topVec + vec.m_topVec); }
- btSpatialForceVector operator - () const { return btSpatialForceVector(-m_bottomVec, -m_topVec); }
- btSpatialForceVector operator * (const btScalar &s) const { return btSpatialForceVector(s * m_bottomVec, s * m_topVec); }
+ btSpatialForceVector &operator+=(const btSpatialForceVector &vec)
+ {
+ m_topVec += vec.m_topVec;
+ m_bottomVec += vec.m_bottomVec;
+ return *this;
+ }
+ btSpatialForceVector &operator-=(const btSpatialForceVector &vec)
+ {
+ m_topVec -= vec.m_topVec;
+ m_bottomVec -= vec.m_bottomVec;
+ return *this;
+ }
+ btSpatialForceVector operator-(const btSpatialForceVector &vec) const { return btSpatialForceVector(m_bottomVec - vec.m_bottomVec, m_topVec - vec.m_topVec); }
+ btSpatialForceVector operator+(const btSpatialForceVector &vec) const { return btSpatialForceVector(m_bottomVec + vec.m_bottomVec, m_topVec + vec.m_topVec); }
+ btSpatialForceVector operator-() const { return btSpatialForceVector(-m_bottomVec, -m_topVec); }
+ btSpatialForceVector operator*(const btScalar &s) const { return btSpatialForceVector(s * m_bottomVec, s * m_topVec); }
//btSpatialForceVector & operator = (const btSpatialForceVector &vec) { m_topVec = vec.m_topVec; m_bottomVec = vec.m_bottomVec; return *this; }
};
@@ -70,23 +96,36 @@ struct btSpatialMotionVector
btVector3 m_topVec, m_bottomVec;
//
btSpatialMotionVector() { setZero(); }
- btSpatialMotionVector(const btVector3 &angular, const btVector3 &linear) : m_topVec(angular), m_bottomVec(linear) {}
+ btSpatialMotionVector(const btVector3 &angular, const btVector3 &linear) : m_topVec(angular), m_bottomVec(linear) {}
//
- void setVector(const btVector3 &angular, const btVector3 &linear) { m_topVec = angular; m_bottomVec = linear; }
+ void setVector(const btVector3 &angular, const btVector3 &linear)
+ {
+ m_topVec = angular;
+ m_bottomVec = linear;
+ }
void setValue(const btScalar &ax, const btScalar &ay, const btScalar &az, const btScalar &lx, const btScalar &ly, const btScalar &lz)
{
- m_topVec.setValue(ax, ay, az); m_bottomVec.setValue(lx, ly, lz);
+ m_topVec.setValue(ax, ay, az);
+ m_bottomVec.setValue(lx, ly, lz);
}
//
- void addVector(const btVector3 &angular, const btVector3 &linear) { m_topVec += linear; m_bottomVec += angular; }
+ void addVector(const btVector3 &angular, const btVector3 &linear)
+ {
+ m_topVec += linear;
+ m_bottomVec += angular;
+ }
void addValue(const btScalar &ax, const btScalar &ay, const btScalar &az, const btScalar &lx, const btScalar &ly, const btScalar &lz)
{
- m_topVec[0] += ax; m_topVec[1] += ay; m_topVec[2] += az;
- m_bottomVec[0] += lx; m_bottomVec[1] += ly; m_bottomVec[2] += lz;
+ m_topVec[0] += ax;
+ m_topVec[1] += ay;
+ m_topVec[2] += az;
+ m_bottomVec[0] += lx;
+ m_bottomVec[1] += ly;
+ m_bottomVec[2] += lz;
}
- //
- const btVector3 & getAngular() const { return m_topVec; }
- const btVector3 & getLinear() const { return m_bottomVec; }
+ //
+ const btVector3 &getAngular() const { return m_topVec; }
+ const btVector3 &getLinear() const { return m_bottomVec; }
//
void setAngular(const btVector3 &angular) { m_topVec = angular; }
void setLinear(const btVector3 &linear) { m_bottomVec = linear; }
@@ -94,20 +133,24 @@ struct btSpatialMotionVector
void addAngular(const btVector3 &angular) { m_topVec += angular; }
void addLinear(const btVector3 &linear) { m_bottomVec += linear; }
//
- void setZero() { m_topVec.setZero(); m_bottomVec.setZero(); }
+ void setZero()
+ {
+ m_topVec.setZero();
+ m_bottomVec.setZero();
+ }
//
btScalar dot(const btSpatialForceVector &b) const
{
return m_bottomVec.dot(b.m_topVec) + m_topVec.dot(b.m_bottomVec);
}
//
- template<typename SpatialVectorType>
+ template <typename SpatialVectorType>
void cross(const SpatialVectorType &b, SpatialVectorType &out) const
{
out.m_topVec = m_topVec.cross(b.m_topVec);
out.m_bottomVec = m_bottomVec.cross(b.m_topVec) + m_topVec.cross(b.m_bottomVec);
}
- template<typename SpatialVectorType>
+ template <typename SpatialVectorType>
SpatialVectorType cross(const SpatialVectorType &b) const
{
SpatialVectorType out;
@@ -116,21 +159,36 @@ struct btSpatialMotionVector
return out;
}
//
- btSpatialMotionVector & operator += (const btSpatialMotionVector &vec) { m_topVec += vec.m_topVec; m_bottomVec += vec.m_bottomVec; return *this; }
- btSpatialMotionVector & operator -= (const btSpatialMotionVector &vec) { m_topVec -= vec.m_topVec; m_bottomVec -= vec.m_bottomVec; return *this; }
- btSpatialMotionVector & operator *= (const btScalar &s) { m_topVec *= s; m_bottomVec *= s; return *this; }
- btSpatialMotionVector operator - (const btSpatialMotionVector &vec) const { return btSpatialMotionVector(m_topVec - vec.m_topVec, m_bottomVec - vec.m_bottomVec); }
- btSpatialMotionVector operator + (const btSpatialMotionVector &vec) const { return btSpatialMotionVector(m_topVec + vec.m_topVec, m_bottomVec + vec.m_bottomVec); }
- btSpatialMotionVector operator - () const { return btSpatialMotionVector(-m_topVec, -m_bottomVec); }
- btSpatialMotionVector operator * (const btScalar &s) const { return btSpatialMotionVector(s * m_topVec, s * m_bottomVec); }
+ btSpatialMotionVector &operator+=(const btSpatialMotionVector &vec)
+ {
+ m_topVec += vec.m_topVec;
+ m_bottomVec += vec.m_bottomVec;
+ return *this;
+ }
+ btSpatialMotionVector &operator-=(const btSpatialMotionVector &vec)
+ {
+ m_topVec -= vec.m_topVec;
+ m_bottomVec -= vec.m_bottomVec;
+ return *this;
+ }
+ btSpatialMotionVector &operator*=(const btScalar &s)
+ {
+ m_topVec *= s;
+ m_bottomVec *= s;
+ return *this;
+ }
+ btSpatialMotionVector operator-(const btSpatialMotionVector &vec) const { return btSpatialMotionVector(m_topVec - vec.m_topVec, m_bottomVec - vec.m_bottomVec); }
+ btSpatialMotionVector operator+(const btSpatialMotionVector &vec) const { return btSpatialMotionVector(m_topVec + vec.m_topVec, m_bottomVec + vec.m_bottomVec); }
+ btSpatialMotionVector operator-() const { return btSpatialMotionVector(-m_topVec, -m_bottomVec); }
+ btSpatialMotionVector operator*(const btScalar &s) const { return btSpatialMotionVector(s * m_topVec, s * m_bottomVec); }
};
struct btSymmetricSpatialDyad
{
btMatrix3x3 m_topLeftMat, m_topRightMat, m_bottomLeftMat;
- //
+ //
btSymmetricSpatialDyad() { setIdentity(); }
- btSymmetricSpatialDyad(const btMatrix3x3 &topLeftMat, const btMatrix3x3 &topRightMat, const btMatrix3x3 &bottomLeftMat) { setMatrix(topLeftMat, topRightMat, bottomLeftMat); }
+ btSymmetricSpatialDyad(const btMatrix3x3 &topLeftMat, const btMatrix3x3 &topRightMat, const btMatrix3x3 &bottomLeftMat) { setMatrix(topLeftMat, topRightMat, bottomLeftMat); }
//
void setMatrix(const btMatrix3x3 &topLeftMat, const btMatrix3x3 &topRightMat, const btMatrix3x3 &bottomLeftMat)
{
@@ -146,17 +204,22 @@ struct btSymmetricSpatialDyad
m_bottomLeftMat += bottomLeftMat;
}
//
- void setIdentity() { m_topLeftMat.setIdentity(); m_topRightMat.setIdentity(); m_bottomLeftMat.setIdentity(); }
+ void setIdentity()
+ {
+ m_topLeftMat.setIdentity();
+ m_topRightMat.setIdentity();
+ m_bottomLeftMat.setIdentity();
+ }
//
- btSymmetricSpatialDyad & operator -= (const btSymmetricSpatialDyad &mat)
+ btSymmetricSpatialDyad &operator-=(const btSymmetricSpatialDyad &mat)
{
m_topLeftMat -= mat.m_topLeftMat;
m_topRightMat -= mat.m_topRightMat;
m_bottomLeftMat -= mat.m_bottomLeftMat;
- return *this;
+ return *this;
}
//
- btSpatialForceVector operator * (const btSpatialMotionVector &vec)
+ btSpatialForceVector operator*(const btSpatialMotionVector &vec)
{
return btSpatialForceVector(m_bottomLeftMat * vec.m_topVec + m_topLeftMat.transpose() * vec.m_bottomVec, m_topLeftMat * vec.m_topVec + m_topRightMat * vec.m_bottomVec);
}
@@ -164,7 +227,7 @@ struct btSymmetricSpatialDyad
struct btSpatialTransformationMatrix
{
- btMatrix3x3 m_rotMat; //btMatrix3x3 m_trnCrossMat;
+ btMatrix3x3 m_rotMat; //btMatrix3x3 m_trnCrossMat;
btVector3 m_trnVec;
//
enum eOutputOperation
@@ -174,128 +237,124 @@ struct btSpatialTransformationMatrix
Subtract = 2
};
//
- template<typename SpatialVectorType>
- void transform( const SpatialVectorType &inVec,
- SpatialVectorType &outVec,
- eOutputOperation outOp = None)
+ template <typename SpatialVectorType>
+ void transform(const SpatialVectorType &inVec,
+ SpatialVectorType &outVec,
+ eOutputOperation outOp = None)
{
- if(outOp == None)
+ if (outOp == None)
{
outVec.m_topVec = m_rotMat * inVec.m_topVec;
outVec.m_bottomVec = -m_trnVec.cross(outVec.m_topVec) + m_rotMat * inVec.m_bottomVec;
}
- else if(outOp == Add)
+ else if (outOp == Add)
{
outVec.m_topVec += m_rotMat * inVec.m_topVec;
outVec.m_bottomVec += -m_trnVec.cross(outVec.m_topVec) + m_rotMat * inVec.m_bottomVec;
}
- else if(outOp == Subtract)
+ else if (outOp == Subtract)
{
outVec.m_topVec -= m_rotMat * inVec.m_topVec;
outVec.m_bottomVec -= -m_trnVec.cross(outVec.m_topVec) + m_rotMat * inVec.m_bottomVec;
}
-
}
- template<typename SpatialVectorType>
- void transformRotationOnly( const SpatialVectorType &inVec,
- SpatialVectorType &outVec,
- eOutputOperation outOp = None)
+ template <typename SpatialVectorType>
+ void transformRotationOnly(const SpatialVectorType &inVec,
+ SpatialVectorType &outVec,
+ eOutputOperation outOp = None)
{
- if(outOp == None)
+ if (outOp == None)
{
outVec.m_topVec = m_rotMat * inVec.m_topVec;
outVec.m_bottomVec = m_rotMat * inVec.m_bottomVec;
}
- else if(outOp == Add)
+ else if (outOp == Add)
{
outVec.m_topVec += m_rotMat * inVec.m_topVec;
outVec.m_bottomVec += m_rotMat * inVec.m_bottomVec;
}
- else if(outOp == Subtract)
+ else if (outOp == Subtract)
{
outVec.m_topVec -= m_rotMat * inVec.m_topVec;
outVec.m_bottomVec -= m_rotMat * inVec.m_bottomVec;
}
-
}
- template<typename SpatialVectorType>
- void transformInverse( const SpatialVectorType &inVec,
- SpatialVectorType &outVec,
- eOutputOperation outOp = None)
+ template <typename SpatialVectorType>
+ void transformInverse(const SpatialVectorType &inVec,
+ SpatialVectorType &outVec,
+ eOutputOperation outOp = None)
{
- if(outOp == None)
+ if (outOp == None)
{
outVec.m_topVec = m_rotMat.transpose() * inVec.m_topVec;
outVec.m_bottomVec = m_rotMat.transpose() * (inVec.m_bottomVec + m_trnVec.cross(inVec.m_topVec));
}
- else if(outOp == Add)
+ else if (outOp == Add)
{
outVec.m_topVec += m_rotMat.transpose() * inVec.m_topVec;
outVec.m_bottomVec += m_rotMat.transpose() * (inVec.m_bottomVec + m_trnVec.cross(inVec.m_topVec));
}
- else if(outOp == Subtract)
+ else if (outOp == Subtract)
{
outVec.m_topVec -= m_rotMat.transpose() * inVec.m_topVec;
outVec.m_bottomVec -= m_rotMat.transpose() * (inVec.m_bottomVec + m_trnVec.cross(inVec.m_topVec));
- }
+ }
}
- template<typename SpatialVectorType>
- void transformInverseRotationOnly( const SpatialVectorType &inVec,
- SpatialVectorType &outVec,
- eOutputOperation outOp = None)
+ template <typename SpatialVectorType>
+ void transformInverseRotationOnly(const SpatialVectorType &inVec,
+ SpatialVectorType &outVec,
+ eOutputOperation outOp = None)
{
- if(outOp == None)
+ if (outOp == None)
{
outVec.m_topVec = m_rotMat.transpose() * inVec.m_topVec;
outVec.m_bottomVec = m_rotMat.transpose() * inVec.m_bottomVec;
}
- else if(outOp == Add)
+ else if (outOp == Add)
{
outVec.m_topVec += m_rotMat.transpose() * inVec.m_topVec;
outVec.m_bottomVec += m_rotMat.transpose() * inVec.m_bottomVec;
}
- else if(outOp == Subtract)
+ else if (outOp == Subtract)
{
outVec.m_topVec -= m_rotMat.transpose() * inVec.m_topVec;
outVec.m_bottomVec -= m_rotMat.transpose() * inVec.m_bottomVec;
}
-
}
- void transformInverse( const btSymmetricSpatialDyad &inMat,
- btSymmetricSpatialDyad &outMat,
- eOutputOperation outOp = None)
+ void transformInverse(const btSymmetricSpatialDyad &inMat,
+ btSymmetricSpatialDyad &outMat,
+ eOutputOperation outOp = None)
{
- const btMatrix3x3 r_cross( 0, -m_trnVec[2], m_trnVec[1],
- m_trnVec[2], 0, -m_trnVec[0],
- -m_trnVec[1], m_trnVec[0], 0);
+ const btMatrix3x3 r_cross(0, -m_trnVec[2], m_trnVec[1],
+ m_trnVec[2], 0, -m_trnVec[0],
+ -m_trnVec[1], m_trnVec[0], 0);
-
- if(outOp == None)
+ if (outOp == None)
{
- outMat.m_topLeftMat = m_rotMat.transpose() * ( inMat.m_topLeftMat - inMat.m_topRightMat * r_cross ) * m_rotMat;
+ outMat.m_topLeftMat = m_rotMat.transpose() * (inMat.m_topLeftMat - inMat.m_topRightMat * r_cross) * m_rotMat;
outMat.m_topRightMat = m_rotMat.transpose() * inMat.m_topRightMat * m_rotMat;
outMat.m_bottomLeftMat = m_rotMat.transpose() * (r_cross * (inMat.m_topLeftMat - inMat.m_topRightMat * r_cross) + inMat.m_bottomLeftMat - inMat.m_topLeftMat.transpose() * r_cross) * m_rotMat;
}
- else if(outOp == Add)
+ else if (outOp == Add)
{
- outMat.m_topLeftMat += m_rotMat.transpose() * ( inMat.m_topLeftMat - inMat.m_topRightMat * r_cross ) * m_rotMat;
+ outMat.m_topLeftMat += m_rotMat.transpose() * (inMat.m_topLeftMat - inMat.m_topRightMat * r_cross) * m_rotMat;
outMat.m_topRightMat += m_rotMat.transpose() * inMat.m_topRightMat * m_rotMat;
outMat.m_bottomLeftMat += m_rotMat.transpose() * (r_cross * (inMat.m_topLeftMat - inMat.m_topRightMat * r_cross) + inMat.m_bottomLeftMat - inMat.m_topLeftMat.transpose() * r_cross) * m_rotMat;
}
- else if(outOp == Subtract)
+ else if (outOp == Subtract)
{
- outMat.m_topLeftMat -= m_rotMat.transpose() * ( inMat.m_topLeftMat - inMat.m_topRightMat * r_cross ) * m_rotMat;
+ outMat.m_topLeftMat -= m_rotMat.transpose() * (inMat.m_topLeftMat - inMat.m_topRightMat * r_cross) * m_rotMat;
outMat.m_topRightMat -= m_rotMat.transpose() * inMat.m_topRightMat * m_rotMat;
outMat.m_bottomLeftMat -= m_rotMat.transpose() * (r_cross * (inMat.m_topLeftMat - inMat.m_topRightMat * r_cross) + inMat.m_bottomLeftMat - inMat.m_topLeftMat.transpose() * r_cross) * m_rotMat;
}
}
- template<typename SpatialVectorType>
- SpatialVectorType operator * (const SpatialVectorType &vec)
+ template <typename SpatialVectorType>
+ SpatialVectorType operator*(const SpatialVectorType &vec)
{
SpatialVectorType out;
transform(vec, out);
@@ -303,7 +362,7 @@ struct btSpatialTransformationMatrix
}
};
-template<typename SpatialVectorType>
+template <typename SpatialVectorType>
void symmetricSpatialOuterProduct(const SpatialVectorType &a, const SpatialVectorType &b, btSymmetricSpatialDyad &out)
{
//output op maybe?
@@ -314,7 +373,7 @@ void symmetricSpatialOuterProduct(const SpatialVectorType &a, const SpatialVecto
//maybe simple a*spatTranspose(a) would be nicer?
}
-template<typename SpatialVectorType>
+template <typename SpatialVectorType>
btSymmetricSpatialDyad symmetricSpatialOuterProduct(const SpatialVectorType &a, const SpatialVectorType &b)
{
btSymmetricSpatialDyad out;
@@ -327,5 +386,4 @@ btSymmetricSpatialDyad symmetricSpatialOuterProduct(const SpatialVectorType &a,
//maybe simple a*spatTranspose(a) would be nicer?
}
-#endif //BT_SPATIAL_ALGEBRA_H
-
+#endif //BT_SPATIAL_ALGEBRA_H
diff --git a/thirdparty/bullet/LinearMath/btStackAlloc.h b/thirdparty/bullet/LinearMath/btStackAlloc.h
index 397b084877..3fc2084976 100644
--- a/thirdparty/bullet/LinearMath/btStackAlloc.h
+++ b/thirdparty/bullet/LinearMath/btStackAlloc.h
@@ -20,97 +20,99 @@ Nov.2006
#ifndef BT_STACK_ALLOC
#define BT_STACK_ALLOC
-#include "btScalar.h" //for btAssert
+#include "btScalar.h" //for btAssert
#include "btAlignedAllocator.h"
///The btBlock class is an internal structure for the btStackAlloc memory allocator.
struct btBlock
{
- btBlock* previous;
- unsigned char* address;
+ btBlock* previous;
+ unsigned char* address;
};
///The StackAlloc class provides some fast stack-based memory allocator (LIFO last-in first-out)
class btStackAlloc
{
public:
+ btStackAlloc(unsigned int size)
+ {
+ ctor();
+ create(size);
+ }
+ ~btStackAlloc() { destroy(); }
- btStackAlloc(unsigned int size) { ctor();create(size); }
- ~btStackAlloc() { destroy(); }
-
- inline void create(unsigned int size)
+ inline void create(unsigned int size)
{
destroy();
- data = (unsigned char*) btAlignedAlloc(size,16);
- totalsize = size;
+ data = (unsigned char*)btAlignedAlloc(size, 16);
+ totalsize = size;
}
- inline void destroy()
+ inline void destroy()
{
- btAssert(usedsize==0);
+ btAssert(usedsize == 0);
//Raise(L"StackAlloc is still in use");
- if(usedsize==0)
+ if (usedsize == 0)
{
- if(!ischild && data)
+ if (!ischild && data)
btAlignedFree(data);
- data = 0;
- usedsize = 0;
+ data = 0;
+ usedsize = 0;
}
-
}
- int getAvailableMemory() const
+ int getAvailableMemory() const
{
return static_cast<int>(totalsize - usedsize);
}
- unsigned char* allocate(unsigned int size)
+ unsigned char* allocate(unsigned int size)
{
- const unsigned int nus(usedsize+size);
- if(nus<totalsize)
+ const unsigned int nus(usedsize + size);
+ if (nus < totalsize)
{
- usedsize=nus;
- return(data+(usedsize-size));
+ usedsize = nus;
+ return (data + (usedsize - size));
}
btAssert(0);
//&& (L"Not enough memory"));
-
- return(0);
+
+ return (0);
}
- SIMD_FORCE_INLINE btBlock* beginBlock()
+ SIMD_FORCE_INLINE btBlock* beginBlock()
{
- btBlock* pb = (btBlock*)allocate(sizeof(btBlock));
- pb->previous = current;
- pb->address = data+usedsize;
- current = pb;
- return(pb);
+ btBlock* pb = (btBlock*)allocate(sizeof(btBlock));
+ pb->previous = current;
+ pb->address = data + usedsize;
+ current = pb;
+ return (pb);
}
- SIMD_FORCE_INLINE void endBlock(btBlock* block)
+ SIMD_FORCE_INLINE void endBlock(btBlock* block)
{
- btAssert(block==current);
+ btAssert(block == current);
//Raise(L"Unmatched blocks");
- if(block==current)
+ if (block == current)
{
- current = block->previous;
- usedsize = (unsigned int)((block->address-data)-sizeof(btBlock));
+ current = block->previous;
+ usedsize = (unsigned int)((block->address - data) - sizeof(btBlock));
}
}
private:
- void ctor()
+ void ctor()
{
- data = 0;
- totalsize = 0;
- usedsize = 0;
- current = 0;
- ischild = false;
+ data = 0;
+ totalsize = 0;
+ usedsize = 0;
+ current = 0;
+ ischild = false;
}
- unsigned char* data;
- unsigned int totalsize;
- unsigned int usedsize;
- btBlock* current;
- bool ischild;
+ unsigned char* data;
+ unsigned int totalsize;
+ unsigned int usedsize;
+ btBlock* current;
+ bool ischild;
};
-#endif //BT_STACK_ALLOC
+#endif //BT_STACK_ALLOC
diff --git a/thirdparty/bullet/LinearMath/btThreads.cpp b/thirdparty/bullet/LinearMath/btThreads.cpp
index c037626ffb..69a86799fa 100644
--- a/thirdparty/bullet/LinearMath/btThreads.cpp
+++ b/thirdparty/bullet/LinearMath/btThreads.cpp
@@ -12,18 +12,15 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#include "btThreads.h"
#include "btQuickprof.h"
#include <algorithm> // for min and max
-
#if BT_USE_OPENMP && BT_THREADSAFE
#include <omp.h>
-#endif // #if BT_USE_OPENMP && BT_THREADSAFE
-
+#endif // #if BT_USE_OPENMP && BT_THREADSAFE
#if BT_USE_PPL && BT_THREADSAFE
@@ -32,8 +29,7 @@ subject to the following restrictions:
// Visual Studio 2010 and later should come with it
#include <concrtrm.h> // for GetProcessorCount()
-#endif // #if BT_USE_PPL && BT_THREADSAFE
-
+#endif // #if BT_USE_PPL && BT_THREADSAFE
#if BT_USE_TBB && BT_THREADSAFE
@@ -44,8 +40,7 @@ subject to the following restrictions:
#include <tbb/parallel_for.h>
#include <tbb/blocked_range.h>
-#endif // #if BT_USE_TBB && BT_THREADSAFE
-
+#endif // #if BT_USE_TBB && BT_THREADSAFE
#if BT_THREADSAFE
//
@@ -53,7 +48,7 @@ subject to the following restrictions:
// Using ordinary system-provided mutexes like Windows critical sections was noticeably slower
// presumably because when it fails to lock at first it would sleep the thread and trigger costly
// context switching.
-//
+//
#if __cplusplus >= 201103L
@@ -61,25 +56,24 @@ subject to the following restrictions:
// on GCC or Clang you need to compile with -std=c++11
#define USE_CPP11_ATOMICS 1
-#elif defined( _MSC_VER )
+#elif defined(_MSC_VER)
// on MSVC, use intrinsics instead
#define USE_MSVC_INTRINSICS 1
-#elif defined( __GNUC__ ) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))
+#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))
// available since GCC 4.7 and some versions of clang
// todo: check for clang
#define USE_GCC_BUILTIN_ATOMICS 1
-#elif defined( __GNUC__ ) && (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)
+#elif defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)
// available since GCC 4.1
#define USE_GCC_BUILTIN_ATOMICS_OLD 1
#endif
-
#if USE_CPP11_ATOMICS
#include <atomic>
@@ -89,27 +83,26 @@ subject to the following restrictions:
bool btSpinMutex::tryLock()
{
- std::atomic<int>* aDest = reinterpret_cast<std::atomic<int>*>(&mLock);
- int expected = 0;
- return std::atomic_compare_exchange_weak_explicit( aDest, &expected, int(1), std::memory_order_acq_rel, std::memory_order_acquire );
+ std::atomic<int>* aDest = reinterpret_cast<std::atomic<int>*>(&mLock);
+ int expected = 0;
+ return std::atomic_compare_exchange_weak_explicit(aDest, &expected, int(1), std::memory_order_acq_rel, std::memory_order_acquire);
}
void btSpinMutex::lock()
{
- // note: this lock does not sleep the thread.
- while (! tryLock())
- {
- // spin
- }
+ // note: this lock does not sleep the thread.
+ while (!tryLock())
+ {
+ // spin
+ }
}
void btSpinMutex::unlock()
{
- std::atomic<int>* aDest = reinterpret_cast<std::atomic<int>*>(&mLock);
- std::atomic_store_explicit( aDest, int(0), std::memory_order_release );
+ std::atomic<int>* aDest = reinterpret_cast<std::atomic<int>*>(&mLock);
+ std::atomic_store_explicit(aDest, int(0), std::memory_order_release);
}
-
#elif USE_MSVC_INTRINSICS
#define WIN32_LEAN_AND_MEAN
@@ -117,148 +110,142 @@ void btSpinMutex::unlock()
#include <windows.h>
#include <intrin.h>
-#define THREAD_LOCAL_STATIC __declspec( thread ) static
-
+#define THREAD_LOCAL_STATIC __declspec(thread) static
bool btSpinMutex::tryLock()
{
- volatile long* aDest = reinterpret_cast<long*>(&mLock);
- return ( 0 == _InterlockedCompareExchange( aDest, 1, 0) );
+ volatile long* aDest = reinterpret_cast<long*>(&mLock);
+ return (0 == _InterlockedCompareExchange(aDest, 1, 0));
}
void btSpinMutex::lock()
{
- // note: this lock does not sleep the thread
- while (! tryLock())
- {
- // spin
- }
+ // note: this lock does not sleep the thread
+ while (!tryLock())
+ {
+ // spin
+ }
}
void btSpinMutex::unlock()
{
- volatile long* aDest = reinterpret_cast<long*>( &mLock );
- _InterlockedExchange( aDest, 0 );
+ volatile long* aDest = reinterpret_cast<long*>(&mLock);
+ _InterlockedExchange(aDest, 0);
}
#elif USE_GCC_BUILTIN_ATOMICS
#define THREAD_LOCAL_STATIC static __thread
-
bool btSpinMutex::tryLock()
{
- int expected = 0;
- bool weak = false;
- const int memOrderSuccess = __ATOMIC_ACQ_REL;
- const int memOrderFail = __ATOMIC_ACQUIRE;
- return __atomic_compare_exchange_n(&mLock, &expected, int(1), weak, memOrderSuccess, memOrderFail);
+ int expected = 0;
+ bool weak = false;
+ const int memOrderSuccess = __ATOMIC_ACQ_REL;
+ const int memOrderFail = __ATOMIC_ACQUIRE;
+ return __atomic_compare_exchange_n(&mLock, &expected, int(1), weak, memOrderSuccess, memOrderFail);
}
void btSpinMutex::lock()
{
- // note: this lock does not sleep the thread
- while (! tryLock())
- {
- // spin
- }
+ // note: this lock does not sleep the thread
+ while (!tryLock())
+ {
+ // spin
+ }
}
void btSpinMutex::unlock()
{
- __atomic_store_n(&mLock, int(0), __ATOMIC_RELEASE);
+ __atomic_store_n(&mLock, int(0), __ATOMIC_RELEASE);
}
#elif USE_GCC_BUILTIN_ATOMICS_OLD
-
#define THREAD_LOCAL_STATIC static __thread
bool btSpinMutex::tryLock()
{
- return __sync_bool_compare_and_swap(&mLock, int(0), int(1));
+ return __sync_bool_compare_and_swap(&mLock, int(0), int(1));
}
void btSpinMutex::lock()
{
- // note: this lock does not sleep the thread
- while (! tryLock())
- {
- // spin
- }
+ // note: this lock does not sleep the thread
+ while (!tryLock())
+ {
+ // spin
+ }
}
void btSpinMutex::unlock()
{
- // write 0
- __sync_fetch_and_and(&mLock, int(0));
+ // write 0
+ __sync_fetch_and_and(&mLock, int(0));
}
-#else //#elif USE_MSVC_INTRINSICS
+#else //#elif USE_MSVC_INTRINSICS
#error "no threading primitives defined -- unknown platform"
#endif //#else //#elif USE_MSVC_INTRINSICS
-#else //#if BT_THREADSAFE
+#else //#if BT_THREADSAFE
// These should not be called ever
void btSpinMutex::lock()
{
- btAssert( !"unimplemented btSpinMutex::lock() called" );
+ btAssert(!"unimplemented btSpinMutex::lock() called");
}
void btSpinMutex::unlock()
{
- btAssert( !"unimplemented btSpinMutex::unlock() called" );
+ btAssert(!"unimplemented btSpinMutex::unlock() called");
}
bool btSpinMutex::tryLock()
{
- btAssert( !"unimplemented btSpinMutex::tryLock() called" );
- return true;
+ btAssert(!"unimplemented btSpinMutex::tryLock() called");
+ return true;
}
#define THREAD_LOCAL_STATIC static
-#endif // #else //#if BT_THREADSAFE
-
+#endif // #else //#if BT_THREADSAFE
struct ThreadsafeCounter
{
- unsigned int mCounter;
- btSpinMutex mMutex;
-
- ThreadsafeCounter()
- {
- mCounter = 0;
- --mCounter; // first count should come back 0
- }
-
- unsigned int getNext()
- {
- // no need to optimize this with atomics, it is only called ONCE per thread!
- mMutex.lock();
- mCounter++;
- if ( mCounter >= BT_MAX_THREAD_COUNT )
- {
- btAssert( !"thread counter exceeded" );
- // wrap back to the first worker index
- mCounter = 1;
- }
- unsigned int val = mCounter;
- mMutex.unlock();
- return val;
- }
+ unsigned int mCounter;
+ btSpinMutex mMutex;
+
+ ThreadsafeCounter()
+ {
+ mCounter = 0;
+ --mCounter; // first count should come back 0
+ }
+
+ unsigned int getNext()
+ {
+ // no need to optimize this with atomics, it is only called ONCE per thread!
+ mMutex.lock();
+ mCounter++;
+ if (mCounter >= BT_MAX_THREAD_COUNT)
+ {
+ btAssert(!"thread counter exceeded");
+ // wrap back to the first worker index
+ mCounter = 1;
+ }
+ unsigned int val = mCounter;
+ mMutex.unlock();
+ return val;
+ }
};
-
-static btITaskScheduler* gBtTaskScheduler;
+static btITaskScheduler* gBtTaskScheduler=0;
static int gThreadsRunningCounter = 0; // useful for detecting if we are trying to do nested parallel-for calls
static btSpinMutex gThreadsRunningCounterMutex;
static ThreadsafeCounter gThreadCounter;
-
//
// BT_DETECT_BAD_THREAD_INDEX tries to detect when there are multiple threads assigned the same thread index.
//
@@ -276,7 +263,7 @@ static ThreadsafeCounter gThreadCounter;
// We allocate thread-indexes as needed with a sequential global thread counter.
//
// Our simple thread-counting scheme falls apart if the task scheduler destroys some threads but
-// continues to re-use other threads and the application repeatedly resizes the thread pool of the
+// continues to re-use other threads and the application repeatedly resizes the thread pool of the
// task scheduler.
// In order to prevent the thread-counter from exceeding the global max (BT_MAX_THREAD_COUNT), we
// wrap the thread counter back to 1. This should only happen if the worker threads have all been
@@ -290,197 +277,192 @@ static ThreadsafeCounter gThreadCounter;
typedef DWORD ThreadId_t;
const static ThreadId_t kInvalidThreadId = 0;
-ThreadId_t gDebugThreadIds[ BT_MAX_THREAD_COUNT ];
+ThreadId_t gDebugThreadIds[BT_MAX_THREAD_COUNT];
static ThreadId_t getDebugThreadId()
{
- return GetCurrentThreadId();
+ return GetCurrentThreadId();
}
-#endif // #if BT_DETECT_BAD_THREAD_INDEX
-
+#endif // #if BT_DETECT_BAD_THREAD_INDEX
// return a unique index per thread, main thread is 0, worker threads are in [1, BT_MAX_THREAD_COUNT)
unsigned int btGetCurrentThreadIndex()
{
- const unsigned int kNullIndex = ~0U;
- THREAD_LOCAL_STATIC unsigned int sThreadIndex = kNullIndex;
- if ( sThreadIndex == kNullIndex )
- {
- sThreadIndex = gThreadCounter.getNext();
- btAssert( sThreadIndex < BT_MAX_THREAD_COUNT );
- }
+ const unsigned int kNullIndex = ~0U;
+ THREAD_LOCAL_STATIC unsigned int sThreadIndex = kNullIndex;
+ if (sThreadIndex == kNullIndex)
+ {
+ sThreadIndex = gThreadCounter.getNext();
+ btAssert(sThreadIndex < BT_MAX_THREAD_COUNT);
+ }
#if BT_DETECT_BAD_THREAD_INDEX
- if ( gBtTaskScheduler && sThreadIndex > 0 )
- {
- ThreadId_t tid = getDebugThreadId();
- // if not set
- if ( gDebugThreadIds[ sThreadIndex ] == kInvalidThreadId )
- {
- // set it
- gDebugThreadIds[ sThreadIndex ] = tid;
- }
- else
- {
- if ( gDebugThreadIds[ sThreadIndex ] != tid )
- {
- // this could indicate the task scheduler is breaking our assumptions about
- // how threads are managed when threadpool is resized
- btAssert( !"there are 2 or more threads with the same thread-index!" );
- __debugbreak();
- }
- }
- }
-#endif // #if BT_DETECT_BAD_THREAD_INDEX
- return sThreadIndex;
+ if (gBtTaskScheduler && sThreadIndex > 0)
+ {
+ ThreadId_t tid = getDebugThreadId();
+ // if not set
+ if (gDebugThreadIds[sThreadIndex] == kInvalidThreadId)
+ {
+ // set it
+ gDebugThreadIds[sThreadIndex] = tid;
+ }
+ else
+ {
+ if (gDebugThreadIds[sThreadIndex] != tid)
+ {
+ // this could indicate the task scheduler is breaking our assumptions about
+ // how threads are managed when threadpool is resized
+ btAssert(!"there are 2 or more threads with the same thread-index!");
+ __debugbreak();
+ }
+ }
+ }
+#endif // #if BT_DETECT_BAD_THREAD_INDEX
+ return sThreadIndex;
}
bool btIsMainThread()
{
- return btGetCurrentThreadIndex() == 0;
+ return btGetCurrentThreadIndex() == 0;
}
void btResetThreadIndexCounter()
{
- // for when all current worker threads are destroyed
- btAssert( btIsMainThread() );
- gThreadCounter.mCounter = 0;
+ // for when all current worker threads are destroyed
+ btAssert(btIsMainThread());
+ gThreadCounter.mCounter = 0;
}
-btITaskScheduler::btITaskScheduler( const char* name )
+btITaskScheduler::btITaskScheduler(const char* name)
{
- m_name = name;
- m_savedThreadCounter = 0;
- m_isActive = false;
+ m_name = name;
+ m_savedThreadCounter = 0;
+ m_isActive = false;
}
void btITaskScheduler::activate()
{
- // gThreadCounter is used to assign a thread-index to each worker thread in a task scheduler.
- // The main thread is always thread-index 0, and worker threads are numbered from 1 to 63 (BT_MAX_THREAD_COUNT-1)
- // The thread-indexes need to be unique amongst the threads that can be running simultaneously.
- // Since only one task scheduler can be used at a time, it is OK for a pair of threads that belong to different
- // task schedulers to share the same thread index because they can't be running at the same time.
- // So each task scheduler needs to keep its own thread counter value
- if ( !m_isActive )
- {
- gThreadCounter.mCounter = m_savedThreadCounter; // restore saved thread counter
- m_isActive = true;
- }
+ // gThreadCounter is used to assign a thread-index to each worker thread in a task scheduler.
+ // The main thread is always thread-index 0, and worker threads are numbered from 1 to 63 (BT_MAX_THREAD_COUNT-1)
+ // The thread-indexes need to be unique amongst the threads that can be running simultaneously.
+ // Since only one task scheduler can be used at a time, it is OK for a pair of threads that belong to different
+ // task schedulers to share the same thread index because they can't be running at the same time.
+ // So each task scheduler needs to keep its own thread counter value
+ if (!m_isActive)
+ {
+ gThreadCounter.mCounter = m_savedThreadCounter; // restore saved thread counter
+ m_isActive = true;
+ }
}
void btITaskScheduler::deactivate()
{
- if ( m_isActive )
- {
- m_savedThreadCounter = gThreadCounter.mCounter; // save thread counter
- m_isActive = false;
- }
+ if (m_isActive)
+ {
+ m_savedThreadCounter = gThreadCounter.mCounter; // save thread counter
+ m_isActive = false;
+ }
}
void btPushThreadsAreRunning()
{
- gThreadsRunningCounterMutex.lock();
- gThreadsRunningCounter++;
- gThreadsRunningCounterMutex.unlock();
+ gThreadsRunningCounterMutex.lock();
+ gThreadsRunningCounter++;
+ gThreadsRunningCounterMutex.unlock();
}
void btPopThreadsAreRunning()
{
- gThreadsRunningCounterMutex.lock();
- gThreadsRunningCounter--;
- gThreadsRunningCounterMutex.unlock();
+ gThreadsRunningCounterMutex.lock();
+ gThreadsRunningCounter--;
+ gThreadsRunningCounterMutex.unlock();
}
bool btThreadsAreRunning()
{
- return gThreadsRunningCounter != 0;
+ return gThreadsRunningCounter != 0;
}
-
-void btSetTaskScheduler( btITaskScheduler* ts )
+void btSetTaskScheduler(btITaskScheduler* ts)
{
- int threadId = btGetCurrentThreadIndex(); // make sure we call this on main thread at least once before any workers run
- if ( threadId != 0 )
- {
- btAssert( !"btSetTaskScheduler must be called from the main thread!" );
- return;
- }
- if ( gBtTaskScheduler )
- {
- // deactivate old task scheduler
- gBtTaskScheduler->deactivate();
- }
- gBtTaskScheduler = ts;
- if ( ts )
- {
- // activate new task scheduler
- ts->activate();
- }
+ int threadId = btGetCurrentThreadIndex(); // make sure we call this on main thread at least once before any workers run
+ if (threadId != 0)
+ {
+ btAssert(!"btSetTaskScheduler must be called from the main thread!");
+ return;
+ }
+ if (gBtTaskScheduler)
+ {
+ // deactivate old task scheduler
+ gBtTaskScheduler->deactivate();
+ }
+ gBtTaskScheduler = ts;
+ if (ts)
+ {
+ // activate new task scheduler
+ ts->activate();
+ }
}
-
btITaskScheduler* btGetTaskScheduler()
{
- return gBtTaskScheduler;
+ return gBtTaskScheduler;
}
-
-void btParallelFor( int iBegin, int iEnd, int grainSize, const btIParallelForBody& body )
+void btParallelFor(int iBegin, int iEnd, int grainSize, const btIParallelForBody& body)
{
#if BT_THREADSAFE
#if BT_DETECT_BAD_THREAD_INDEX
- if ( !btThreadsAreRunning() )
- {
- // clear out thread ids
- for ( int i = 0; i < BT_MAX_THREAD_COUNT; ++i )
- {
- gDebugThreadIds[ i ] = kInvalidThreadId;
- }
- }
-#endif // #if BT_DETECT_BAD_THREAD_INDEX
+ if (!btThreadsAreRunning())
+ {
+ // clear out thread ids
+ for (int i = 0; i < BT_MAX_THREAD_COUNT; ++i)
+ {
+ gDebugThreadIds[i] = kInvalidThreadId;
+ }
+ }
+#endif // #if BT_DETECT_BAD_THREAD_INDEX
- btAssert( gBtTaskScheduler != NULL ); // call btSetTaskScheduler() with a valid task scheduler first!
- gBtTaskScheduler->parallelFor( iBegin, iEnd, grainSize, body );
+ btAssert(gBtTaskScheduler != NULL); // call btSetTaskScheduler() with a valid task scheduler first!
+ gBtTaskScheduler->parallelFor(iBegin, iEnd, grainSize, body);
-#else // #if BT_THREADSAFE
+#else // #if BT_THREADSAFE
- // non-parallel version of btParallelFor
- btAssert( !"called btParallelFor in non-threadsafe build. enable BT_THREADSAFE" );
- body.forLoop( iBegin, iEnd );
+ // non-parallel version of btParallelFor
+ btAssert(!"called btParallelFor in non-threadsafe build. enable BT_THREADSAFE");
+ body.forLoop(iBegin, iEnd);
-#endif// #if BT_THREADSAFE
+#endif // #if BT_THREADSAFE
}
-btScalar btParallelSum( int iBegin, int iEnd, int grainSize, const btIParallelSumBody& body )
+btScalar btParallelSum(int iBegin, int iEnd, int grainSize, const btIParallelSumBody& body)
{
#if BT_THREADSAFE
#if BT_DETECT_BAD_THREAD_INDEX
- if ( !btThreadsAreRunning() )
- {
- // clear out thread ids
- for ( int i = 0; i < BT_MAX_THREAD_COUNT; ++i )
- {
- gDebugThreadIds[ i ] = kInvalidThreadId;
- }
- }
-#endif // #if BT_DETECT_BAD_THREAD_INDEX
+ if (!btThreadsAreRunning())
+ {
+ // clear out thread ids
+ for (int i = 0; i < BT_MAX_THREAD_COUNT; ++i)
+ {
+ gDebugThreadIds[i] = kInvalidThreadId;
+ }
+ }
+#endif // #if BT_DETECT_BAD_THREAD_INDEX
- btAssert( gBtTaskScheduler != NULL ); // call btSetTaskScheduler() with a valid task scheduler first!
- return gBtTaskScheduler->parallelSum( iBegin, iEnd, grainSize, body );
+ btAssert(gBtTaskScheduler != NULL); // call btSetTaskScheduler() with a valid task scheduler first!
+ return gBtTaskScheduler->parallelSum(iBegin, iEnd, grainSize, body);
-#else // #if BT_THREADSAFE
+#else // #if BT_THREADSAFE
- // non-parallel version of btParallelSum
- btAssert( !"called btParallelFor in non-threadsafe build. enable BT_THREADSAFE" );
- return body.sumLoop( iBegin, iEnd );
+ // non-parallel version of btParallelSum
+ btAssert(!"called btParallelFor in non-threadsafe build. enable BT_THREADSAFE");
+ return body.sumLoop(iBegin, iEnd);
-#endif //#else // #if BT_THREADSAFE
+#endif //#else // #if BT_THREADSAFE
}
-
///
/// btTaskSchedulerSequential -- non-threaded implementation of task scheduler
/// (really just useful for testing performance of single threaded vs multi)
@@ -488,86 +470,86 @@ btScalar btParallelSum( int iBegin, int iEnd, int grainSize, const btIParallelSu
class btTaskSchedulerSequential : public btITaskScheduler
{
public:
- btTaskSchedulerSequential() : btITaskScheduler( "Sequential" ) {}
- virtual int getMaxNumThreads() const BT_OVERRIDE { return 1; }
- virtual int getNumThreads() const BT_OVERRIDE { return 1; }
- virtual void setNumThreads( int numThreads ) BT_OVERRIDE {}
- virtual void parallelFor( int iBegin, int iEnd, int grainSize, const btIParallelForBody& body ) BT_OVERRIDE
- {
- BT_PROFILE( "parallelFor_sequential" );
- body.forLoop( iBegin, iEnd );
- }
- virtual btScalar parallelSum( int iBegin, int iEnd, int grainSize, const btIParallelSumBody& body ) BT_OVERRIDE
- {
- BT_PROFILE( "parallelSum_sequential" );
- return body.sumLoop( iBegin, iEnd );
- }
+ btTaskSchedulerSequential() : btITaskScheduler("Sequential") {}
+ virtual int getMaxNumThreads() const BT_OVERRIDE { return 1; }
+ virtual int getNumThreads() const BT_OVERRIDE { return 1; }
+ virtual void setNumThreads(int numThreads) BT_OVERRIDE {}
+ virtual void parallelFor(int iBegin, int iEnd, int grainSize, const btIParallelForBody& body) BT_OVERRIDE
+ {
+ BT_PROFILE("parallelFor_sequential");
+ body.forLoop(iBegin, iEnd);
+ }
+ virtual btScalar parallelSum(int iBegin, int iEnd, int grainSize, const btIParallelSumBody& body) BT_OVERRIDE
+ {
+ BT_PROFILE("parallelSum_sequential");
+ return body.sumLoop(iBegin, iEnd);
+ }
};
-
#if BT_USE_OPENMP && BT_THREADSAFE
///
/// btTaskSchedulerOpenMP -- wrapper around OpenMP task scheduler
///
class btTaskSchedulerOpenMP : public btITaskScheduler
{
- int m_numThreads;
+ int m_numThreads;
+
public:
- btTaskSchedulerOpenMP() : btITaskScheduler( "OpenMP" )
- {
- m_numThreads = 0;
- }
- virtual int getMaxNumThreads() const BT_OVERRIDE
- {
- return omp_get_max_threads();
- }
- virtual int getNumThreads() const BT_OVERRIDE
- {
- return m_numThreads;
- }
- virtual void setNumThreads( int numThreads ) BT_OVERRIDE
- {
- // With OpenMP, because it is a standard with various implementations, we can't
- // know for sure if every implementation has the same behavior of destroying all
- // previous threads when resizing the threadpool
- m_numThreads = ( std::max )( 1, ( std::min )( int( BT_MAX_THREAD_COUNT ), numThreads ) );
- omp_set_num_threads( 1 ); // hopefully, all previous threads get destroyed here
- omp_set_num_threads( m_numThreads );
- m_savedThreadCounter = 0;
- if ( m_isActive )
- {
- btResetThreadIndexCounter();
- }
- }
- virtual void parallelFor( int iBegin, int iEnd, int grainSize, const btIParallelForBody& body ) BT_OVERRIDE
- {
- BT_PROFILE( "parallelFor_OpenMP" );
- btPushThreadsAreRunning();
-#pragma omp parallel for schedule( static, 1 )
- for ( int i = iBegin; i < iEnd; i += grainSize )
- {
- BT_PROFILE( "OpenMP_forJob" );
- body.forLoop( i, ( std::min )( i + grainSize, iEnd ) );
- }
- btPopThreadsAreRunning();
- }
- virtual btScalar parallelSum( int iBegin, int iEnd, int grainSize, const btIParallelSumBody& body ) BT_OVERRIDE
- {
- BT_PROFILE( "parallelFor_OpenMP" );
- btPushThreadsAreRunning();
- btScalar sum = btScalar( 0 );
-#pragma omp parallel for schedule( static, 1 ) reduction(+:sum)
- for ( int i = iBegin; i < iEnd; i += grainSize )
- {
- BT_PROFILE( "OpenMP_sumJob" );
- sum += body.sumLoop( i, ( std::min )( i + grainSize, iEnd ) );
- }
- btPopThreadsAreRunning();
- return sum;
- }
+ btTaskSchedulerOpenMP() : btITaskScheduler("OpenMP")
+ {
+ m_numThreads = 0;
+ }
+ virtual int getMaxNumThreads() const BT_OVERRIDE
+ {
+ return omp_get_max_threads();
+ }
+ virtual int getNumThreads() const BT_OVERRIDE
+ {
+ return m_numThreads;
+ }
+ virtual void setNumThreads(int numThreads) BT_OVERRIDE
+ {
+ // With OpenMP, because it is a standard with various implementations, we can't
+ // know for sure if every implementation has the same behavior of destroying all
+ // previous threads when resizing the threadpool
+ m_numThreads = (std::max)(1, (std::min)(int(BT_MAX_THREAD_COUNT), numThreads));
+ omp_set_num_threads(1); // hopefully, all previous threads get destroyed here
+ omp_set_num_threads(m_numThreads);
+ m_savedThreadCounter = 0;
+ if (m_isActive)
+ {
+ btResetThreadIndexCounter();
+ }
+ }
+ virtual void parallelFor(int iBegin, int iEnd, int grainSize, const btIParallelForBody& body) BT_OVERRIDE
+ {
+ BT_PROFILE("parallelFor_OpenMP");
+ btPushThreadsAreRunning();
+#pragma omp parallel for schedule(static, 1)
+ for (int i = iBegin; i < iEnd; i += grainSize)
+ {
+ BT_PROFILE("OpenMP_forJob");
+ body.forLoop(i, (std::min)(i + grainSize, iEnd));
+ }
+ btPopThreadsAreRunning();
+ }
+ virtual btScalar parallelSum(int iBegin, int iEnd, int grainSize, const btIParallelSumBody& body) BT_OVERRIDE
+ {
+ BT_PROFILE("parallelFor_OpenMP");
+ btPushThreadsAreRunning();
+ btScalar sum = btScalar(0);
+#pragma omp parallel for schedule(static, 1) reduction(+ \
+ : sum)
+ for (int i = iBegin; i < iEnd; i += grainSize)
+ {
+ BT_PROFILE("OpenMP_sumJob");
+ sum += body.sumLoop(i, (std::min)(i + grainSize, iEnd));
+ }
+ btPopThreadsAreRunning();
+ return sum;
+ }
};
-#endif // #if BT_USE_OPENMP && BT_THREADSAFE
-
+#endif // #if BT_USE_OPENMP && BT_THREADSAFE
#if BT_USE_TBB && BT_THREADSAFE
///
@@ -575,96 +557,94 @@ public:
///
class btTaskSchedulerTBB : public btITaskScheduler
{
- int m_numThreads;
- tbb::task_scheduler_init* m_tbbSchedulerInit;
+ int m_numThreads;
+ tbb::task_scheduler_init* m_tbbSchedulerInit;
public:
- btTaskSchedulerTBB() : btITaskScheduler( "IntelTBB" )
- {
- m_numThreads = 0;
- m_tbbSchedulerInit = NULL;
- }
- ~btTaskSchedulerTBB()
- {
- if ( m_tbbSchedulerInit )
- {
- delete m_tbbSchedulerInit;
- m_tbbSchedulerInit = NULL;
- }
- }
-
- virtual int getMaxNumThreads() const BT_OVERRIDE
- {
- return tbb::task_scheduler_init::default_num_threads();
- }
- virtual int getNumThreads() const BT_OVERRIDE
- {
- return m_numThreads;
- }
- virtual void setNumThreads( int numThreads ) BT_OVERRIDE
- {
- m_numThreads = ( std::max )( 1, ( std::min )( int(BT_MAX_THREAD_COUNT), numThreads ) );
- if ( m_tbbSchedulerInit )
- {
- // destroys all previous threads
- delete m_tbbSchedulerInit;
- m_tbbSchedulerInit = NULL;
- }
- m_tbbSchedulerInit = new tbb::task_scheduler_init( m_numThreads );
- m_savedThreadCounter = 0;
- if ( m_isActive )
- {
- btResetThreadIndexCounter();
- }
- }
- struct ForBodyAdapter
- {
- const btIParallelForBody* mBody;
-
- ForBodyAdapter( const btIParallelForBody* body ) : mBody( body ) {}
- void operator()( const tbb::blocked_range<int>& range ) const
- {
- BT_PROFILE( "TBB_forJob" );
- mBody->forLoop( range.begin(), range.end() );
- }
- };
- virtual void parallelFor( int iBegin, int iEnd, int grainSize, const btIParallelForBody& body ) BT_OVERRIDE
- {
- BT_PROFILE( "parallelFor_TBB" );
- ForBodyAdapter tbbBody( &body );
- btPushThreadsAreRunning();
- tbb::parallel_for( tbb::blocked_range<int>( iBegin, iEnd, grainSize ),
- tbbBody,
- tbb::simple_partitioner()
- );
- btPopThreadsAreRunning();
- }
- struct SumBodyAdapter
- {
- const btIParallelSumBody* mBody;
- btScalar mSum;
-
- SumBodyAdapter( const btIParallelSumBody* body ) : mBody( body ), mSum( btScalar( 0 ) ) {}
- SumBodyAdapter( const SumBodyAdapter& src, tbb::split ) : mBody( src.mBody ), mSum( btScalar( 0 ) ) {}
- void join( const SumBodyAdapter& src ) { mSum += src.mSum; }
- void operator()( const tbb::blocked_range<int>& range )
- {
- BT_PROFILE( "TBB_sumJob" );
- mSum += mBody->sumLoop( range.begin(), range.end() );
- }
- };
- virtual btScalar parallelSum( int iBegin, int iEnd, int grainSize, const btIParallelSumBody& body ) BT_OVERRIDE
- {
- BT_PROFILE( "parallelSum_TBB" );
- SumBodyAdapter tbbBody( &body );
- btPushThreadsAreRunning();
- tbb::parallel_deterministic_reduce( tbb::blocked_range<int>( iBegin, iEnd, grainSize ), tbbBody );
- btPopThreadsAreRunning();
- return tbbBody.mSum;
- }
+ btTaskSchedulerTBB() : btITaskScheduler("IntelTBB")
+ {
+ m_numThreads = 0;
+ m_tbbSchedulerInit = NULL;
+ }
+ ~btTaskSchedulerTBB()
+ {
+ if (m_tbbSchedulerInit)
+ {
+ delete m_tbbSchedulerInit;
+ m_tbbSchedulerInit = NULL;
+ }
+ }
+
+ virtual int getMaxNumThreads() const BT_OVERRIDE
+ {
+ return tbb::task_scheduler_init::default_num_threads();
+ }
+ virtual int getNumThreads() const BT_OVERRIDE
+ {
+ return m_numThreads;
+ }
+ virtual void setNumThreads(int numThreads) BT_OVERRIDE
+ {
+ m_numThreads = (std::max)(1, (std::min)(int(BT_MAX_THREAD_COUNT), numThreads));
+ if (m_tbbSchedulerInit)
+ {
+ // destroys all previous threads
+ delete m_tbbSchedulerInit;
+ m_tbbSchedulerInit = NULL;
+ }
+ m_tbbSchedulerInit = new tbb::task_scheduler_init(m_numThreads);
+ m_savedThreadCounter = 0;
+ if (m_isActive)
+ {
+ btResetThreadIndexCounter();
+ }
+ }
+ struct ForBodyAdapter
+ {
+ const btIParallelForBody* mBody;
+
+ ForBodyAdapter(const btIParallelForBody* body) : mBody(body) {}
+ void operator()(const tbb::blocked_range<int>& range) const
+ {
+ BT_PROFILE("TBB_forJob");
+ mBody->forLoop(range.begin(), range.end());
+ }
+ };
+ virtual void parallelFor(int iBegin, int iEnd, int grainSize, const btIParallelForBody& body) BT_OVERRIDE
+ {
+ BT_PROFILE("parallelFor_TBB");
+ ForBodyAdapter tbbBody(&body);
+ btPushThreadsAreRunning();
+ tbb::parallel_for(tbb::blocked_range<int>(iBegin, iEnd, grainSize),
+ tbbBody,
+ tbb::simple_partitioner());
+ btPopThreadsAreRunning();
+ }
+ struct SumBodyAdapter
+ {
+ const btIParallelSumBody* mBody;
+ btScalar mSum;
+
+ SumBodyAdapter(const btIParallelSumBody* body) : mBody(body), mSum(btScalar(0)) {}
+ SumBodyAdapter(const SumBodyAdapter& src, tbb::split) : mBody(src.mBody), mSum(btScalar(0)) {}
+ void join(const SumBodyAdapter& src) { mSum += src.mSum; }
+ void operator()(const tbb::blocked_range<int>& range)
+ {
+ BT_PROFILE("TBB_sumJob");
+ mSum += mBody->sumLoop(range.begin(), range.end());
+ }
+ };
+ virtual btScalar parallelSum(int iBegin, int iEnd, int grainSize, const btIParallelSumBody& body) BT_OVERRIDE
+ {
+ BT_PROFILE("parallelSum_TBB");
+ SumBodyAdapter tbbBody(&body);
+ btPushThreadsAreRunning();
+ tbb::parallel_deterministic_reduce(tbb::blocked_range<int>(iBegin, iEnd, grainSize), tbbBody);
+ btPopThreadsAreRunning();
+ return tbbBody.mSum;
+ }
};
-#endif // #if BT_USE_TBB && BT_THREADSAFE
-
+#endif // #if BT_USE_TBB && BT_THREADSAFE
#if BT_USE_PPL && BT_THREADSAFE
///
@@ -672,148 +652,141 @@ public:
///
class btTaskSchedulerPPL : public btITaskScheduler
{
- int m_numThreads;
- concurrency::combinable<btScalar> m_sum; // for parallelSum
+ int m_numThreads;
+ concurrency::combinable<btScalar> m_sum; // for parallelSum
public:
- btTaskSchedulerPPL() : btITaskScheduler( "PPL" )
- {
- m_numThreads = 0;
- }
- virtual int getMaxNumThreads() const BT_OVERRIDE
- {
- return concurrency::GetProcessorCount();
- }
- virtual int getNumThreads() const BT_OVERRIDE
- {
- return m_numThreads;
- }
- virtual void setNumThreads( int numThreads ) BT_OVERRIDE
- {
- // capping the thread count for PPL due to a thread-index issue
- const int maxThreadCount = (std::min)(int(BT_MAX_THREAD_COUNT), 31);
- m_numThreads = ( std::max )( 1, ( std::min )( maxThreadCount, numThreads ) );
- using namespace concurrency;
- if ( CurrentScheduler::Id() != -1 )
- {
- CurrentScheduler::Detach();
- }
- SchedulerPolicy policy;
- {
- // PPL seems to destroy threads when threadpool is shrunk, but keeps reusing old threads
- // force it to destroy old threads
- policy.SetConcurrencyLimits( 1, 1 );
- CurrentScheduler::Create( policy );
- CurrentScheduler::Detach();
- }
- policy.SetConcurrencyLimits( m_numThreads, m_numThreads );
- CurrentScheduler::Create( policy );
- m_savedThreadCounter = 0;
- if ( m_isActive )
- {
- btResetThreadIndexCounter();
- }
- }
- struct ForBodyAdapter
- {
- const btIParallelForBody* mBody;
- int mGrainSize;
- int mIndexEnd;
-
- ForBodyAdapter( const btIParallelForBody* body, int grainSize, int end ) : mBody( body ), mGrainSize( grainSize ), mIndexEnd( end ) {}
- void operator()( int i ) const
- {
- BT_PROFILE( "PPL_forJob" );
- mBody->forLoop( i, ( std::min )( i + mGrainSize, mIndexEnd ) );
- }
- };
- virtual void parallelFor( int iBegin, int iEnd, int grainSize, const btIParallelForBody& body ) BT_OVERRIDE
- {
- BT_PROFILE( "parallelFor_PPL" );
- // PPL dispatch
- ForBodyAdapter pplBody( &body, grainSize, iEnd );
- btPushThreadsAreRunning();
- // note: MSVC 2010 doesn't support partitioner args, so avoid them
- concurrency::parallel_for( iBegin,
- iEnd,
- grainSize,
- pplBody
- );
- btPopThreadsAreRunning();
- }
- struct SumBodyAdapter
- {
- const btIParallelSumBody* mBody;
- concurrency::combinable<btScalar>* mSum;
- int mGrainSize;
- int mIndexEnd;
-
- SumBodyAdapter( const btIParallelSumBody* body, concurrency::combinable<btScalar>* sum, int grainSize, int end ) : mBody( body ), mSum(sum), mGrainSize( grainSize ), mIndexEnd( end ) {}
- void operator()( int i ) const
- {
- BT_PROFILE( "PPL_sumJob" );
- mSum->local() += mBody->sumLoop( i, ( std::min )( i + mGrainSize, mIndexEnd ) );
- }
- };
- static btScalar sumFunc( btScalar a, btScalar b ) { return a + b; }
- virtual btScalar parallelSum( int iBegin, int iEnd, int grainSize, const btIParallelSumBody& body ) BT_OVERRIDE
- {
- BT_PROFILE( "parallelSum_PPL" );
- m_sum.clear();
- SumBodyAdapter pplBody( &body, &m_sum, grainSize, iEnd );
- btPushThreadsAreRunning();
- // note: MSVC 2010 doesn't support partitioner args, so avoid them
- concurrency::parallel_for( iBegin,
- iEnd,
- grainSize,
- pplBody
- );
- btPopThreadsAreRunning();
- return m_sum.combine( sumFunc );
- }
+ btTaskSchedulerPPL() : btITaskScheduler("PPL")
+ {
+ m_numThreads = 0;
+ }
+ virtual int getMaxNumThreads() const BT_OVERRIDE
+ {
+ return concurrency::GetProcessorCount();
+ }
+ virtual int getNumThreads() const BT_OVERRIDE
+ {
+ return m_numThreads;
+ }
+ virtual void setNumThreads(int numThreads) BT_OVERRIDE
+ {
+ // capping the thread count for PPL due to a thread-index issue
+ const int maxThreadCount = (std::min)(int(BT_MAX_THREAD_COUNT), 31);
+ m_numThreads = (std::max)(1, (std::min)(maxThreadCount, numThreads));
+ using namespace concurrency;
+ if (CurrentScheduler::Id() != -1)
+ {
+ CurrentScheduler::Detach();
+ }
+ SchedulerPolicy policy;
+ {
+ // PPL seems to destroy threads when threadpool is shrunk, but keeps reusing old threads
+ // force it to destroy old threads
+ policy.SetConcurrencyLimits(1, 1);
+ CurrentScheduler::Create(policy);
+ CurrentScheduler::Detach();
+ }
+ policy.SetConcurrencyLimits(m_numThreads, m_numThreads);
+ CurrentScheduler::Create(policy);
+ m_savedThreadCounter = 0;
+ if (m_isActive)
+ {
+ btResetThreadIndexCounter();
+ }
+ }
+ struct ForBodyAdapter
+ {
+ const btIParallelForBody* mBody;
+ int mGrainSize;
+ int mIndexEnd;
+
+ ForBodyAdapter(const btIParallelForBody* body, int grainSize, int end) : mBody(body), mGrainSize(grainSize), mIndexEnd(end) {}
+ void operator()(int i) const
+ {
+ BT_PROFILE("PPL_forJob");
+ mBody->forLoop(i, (std::min)(i + mGrainSize, mIndexEnd));
+ }
+ };
+ virtual void parallelFor(int iBegin, int iEnd, int grainSize, const btIParallelForBody& body) BT_OVERRIDE
+ {
+ BT_PROFILE("parallelFor_PPL");
+ // PPL dispatch
+ ForBodyAdapter pplBody(&body, grainSize, iEnd);
+ btPushThreadsAreRunning();
+ // note: MSVC 2010 doesn't support partitioner args, so avoid them
+ concurrency::parallel_for(iBegin,
+ iEnd,
+ grainSize,
+ pplBody);
+ btPopThreadsAreRunning();
+ }
+ struct SumBodyAdapter
+ {
+ const btIParallelSumBody* mBody;
+ concurrency::combinable<btScalar>* mSum;
+ int mGrainSize;
+ int mIndexEnd;
+
+ SumBodyAdapter(const btIParallelSumBody* body, concurrency::combinable<btScalar>* sum, int grainSize, int end) : mBody(body), mSum(sum), mGrainSize(grainSize), mIndexEnd(end) {}
+ void operator()(int i) const
+ {
+ BT_PROFILE("PPL_sumJob");
+ mSum->local() += mBody->sumLoop(i, (std::min)(i + mGrainSize, mIndexEnd));
+ }
+ };
+ static btScalar sumFunc(btScalar a, btScalar b) { return a + b; }
+ virtual btScalar parallelSum(int iBegin, int iEnd, int grainSize, const btIParallelSumBody& body) BT_OVERRIDE
+ {
+ BT_PROFILE("parallelSum_PPL");
+ m_sum.clear();
+ SumBodyAdapter pplBody(&body, &m_sum, grainSize, iEnd);
+ btPushThreadsAreRunning();
+ // note: MSVC 2010 doesn't support partitioner args, so avoid them
+ concurrency::parallel_for(iBegin,
+ iEnd,
+ grainSize,
+ pplBody);
+ btPopThreadsAreRunning();
+ return m_sum.combine(sumFunc);
+ }
};
-#endif // #if BT_USE_PPL && BT_THREADSAFE
-
+#endif // #if BT_USE_PPL && BT_THREADSAFE
// create a non-threaded task scheduler (always available)
btITaskScheduler* btGetSequentialTaskScheduler()
{
- static btTaskSchedulerSequential sTaskScheduler;
- return &sTaskScheduler;
+ static btTaskSchedulerSequential sTaskScheduler;
+ return &sTaskScheduler;
}
-
// create an OpenMP task scheduler (if available, otherwise returns null)
btITaskScheduler* btGetOpenMPTaskScheduler()
{
#if BT_USE_OPENMP && BT_THREADSAFE
- static btTaskSchedulerOpenMP sTaskScheduler;
- return &sTaskScheduler;
+ static btTaskSchedulerOpenMP sTaskScheduler;
+ return &sTaskScheduler;
#else
- return NULL;
+ return NULL;
#endif
}
-
// create an Intel TBB task scheduler (if available, otherwise returns null)
btITaskScheduler* btGetTBBTaskScheduler()
{
#if BT_USE_TBB && BT_THREADSAFE
- static btTaskSchedulerTBB sTaskScheduler;
- return &sTaskScheduler;
+ static btTaskSchedulerTBB sTaskScheduler;
+ return &sTaskScheduler;
#else
- return NULL;
+ return NULL;
#endif
}
-
// create a PPL task scheduler (if available, otherwise returns null)
btITaskScheduler* btGetPPLTaskScheduler()
{
#if BT_USE_PPL && BT_THREADSAFE
- static btTaskSchedulerPPL sTaskScheduler;
- return &sTaskScheduler;
+ static btTaskSchedulerPPL sTaskScheduler;
+ return &sTaskScheduler;
#else
- return NULL;
+ return NULL;
#endif
}
-
diff --git a/thirdparty/bullet/LinearMath/btThreads.h b/thirdparty/bullet/LinearMath/btThreads.h
index 921fd088c0..b2227e1724 100644
--- a/thirdparty/bullet/LinearMath/btThreads.h
+++ b/thirdparty/bullet/LinearMath/btThreads.h
@@ -12,14 +12,12 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
-
#ifndef BT_THREADS_H
#define BT_THREADS_H
-#include "btScalar.h" // has definitions like SIMD_FORCE_INLINE
+#include "btScalar.h" // has definitions like SIMD_FORCE_INLINE
-#if defined (_MSC_VER) && _MSC_VER >= 1600
+#if defined(_MSC_VER) && _MSC_VER >= 1600
// give us a compile error if any signatures of overriden methods is changed
#define BT_OVERRIDE override
#endif
@@ -36,7 +34,7 @@ const unsigned int BT_MAX_THREAD_COUNT = 64; // only if BT_THREADSAFE is 1
bool btIsMainThread();
bool btThreadsAreRunning();
unsigned int btGetCurrentThreadIndex();
-void btResetThreadIndexCounter(); // notify that all worker threads have been destroyed
+void btResetThreadIndexCounter(); // notify that all worker threads have been destroyed
///
/// btSpinMutex -- lightweight spin-mutex implemented with atomic ops, never puts
@@ -46,19 +44,18 @@ void btResetThreadIndexCounter(); // notify that all worker threads have been de
///
class btSpinMutex
{
- int mLock;
+ int mLock;
public:
- btSpinMutex()
- {
- mLock = 0;
- }
- void lock();
- void unlock();
- bool tryLock();
+ btSpinMutex()
+ {
+ mLock = 0;
+ }
+ void lock();
+ void unlock();
+ bool tryLock();
};
-
//
// NOTE: btMutex* is for internal Bullet use only
//
@@ -70,43 +67,42 @@ public:
// of bad because if you call any of these functions from external code
// (where BT_THREADSAFE is undefined) you will get unexpected race conditions.
//
-SIMD_FORCE_INLINE void btMutexLock( btSpinMutex* mutex )
+SIMD_FORCE_INLINE void btMutexLock(btSpinMutex* mutex)
{
#if BT_THREADSAFE
- mutex->lock();
+ mutex->lock();
#else
- (void)mutex;
-#endif // #if BT_THREADSAFE
+ (void)mutex;
+#endif // #if BT_THREADSAFE
}
-SIMD_FORCE_INLINE void btMutexUnlock( btSpinMutex* mutex )
+SIMD_FORCE_INLINE void btMutexUnlock(btSpinMutex* mutex)
{
#if BT_THREADSAFE
- mutex->unlock();
+ mutex->unlock();
#else
- (void)mutex;
-#endif // #if BT_THREADSAFE
+ (void)mutex;
+#endif // #if BT_THREADSAFE
}
-SIMD_FORCE_INLINE bool btMutexTryLock( btSpinMutex* mutex )
+SIMD_FORCE_INLINE bool btMutexTryLock(btSpinMutex* mutex)
{
#if BT_THREADSAFE
- return mutex->tryLock();
+ return mutex->tryLock();
#else
- (void)mutex;
- return true;
-#endif // #if BT_THREADSAFE
+ (void)mutex;
+ return true;
+#endif // #if BT_THREADSAFE
}
-
//
// btIParallelForBody -- subclass this to express work that can be done in parallel
//
class btIParallelForBody
{
public:
- virtual ~btIParallelForBody() {}
- virtual void forLoop( int iBegin, int iEnd ) const = 0;
+ virtual ~btIParallelForBody() {}
+ virtual void forLoop(int iBegin, int iEnd) const = 0;
};
//
@@ -116,8 +112,8 @@ public:
class btIParallelSumBody
{
public:
- virtual ~btIParallelSumBody() {}
- virtual btScalar sumLoop( int iBegin, int iEnd ) const = 0;
+ virtual ~btIParallelSumBody() {}
+ virtual btScalar sumLoop(int iBegin, int iEnd) const = 0;
};
//
@@ -127,30 +123,30 @@ public:
class btITaskScheduler
{
public:
- btITaskScheduler( const char* name );
- virtual ~btITaskScheduler() {}
- const char* getName() const { return m_name; }
+ btITaskScheduler(const char* name);
+ virtual ~btITaskScheduler() {}
+ const char* getName() const { return m_name; }
- virtual int getMaxNumThreads() const = 0;
- virtual int getNumThreads() const = 0;
- virtual void setNumThreads( int numThreads ) = 0;
- virtual void parallelFor( int iBegin, int iEnd, int grainSize, const btIParallelForBody& body ) = 0;
- virtual btScalar parallelSum( int iBegin, int iEnd, int grainSize, const btIParallelSumBody& body ) = 0;
- virtual void sleepWorkerThreadsHint() {} // hint the task scheduler that we may not be using these threads for a little while
+ virtual int getMaxNumThreads() const = 0;
+ virtual int getNumThreads() const = 0;
+ virtual void setNumThreads(int numThreads) = 0;
+ virtual void parallelFor(int iBegin, int iEnd, int grainSize, const btIParallelForBody& body) = 0;
+ virtual btScalar parallelSum(int iBegin, int iEnd, int grainSize, const btIParallelSumBody& body) = 0;
+ virtual void sleepWorkerThreadsHint() {} // hint the task scheduler that we may not be using these threads for a little while
- // internal use only
- virtual void activate();
- virtual void deactivate();
+ // internal use only
+ virtual void activate();
+ virtual void deactivate();
protected:
- const char* m_name;
- unsigned int m_savedThreadCounter;
- bool m_isActive;
+ const char* m_name;
+ unsigned int m_savedThreadCounter;
+ bool m_isActive;
};
// set the task scheduler to use for all calls to btParallelFor()
// NOTE: you must set this prior to using any of the multi-threaded "Mt" classes
-void btSetTaskScheduler( btITaskScheduler* ts );
+void btSetTaskScheduler(btITaskScheduler* ts);
// get the current task scheduler
btITaskScheduler* btGetTaskScheduler();
@@ -172,11 +168,10 @@ btITaskScheduler* btGetPPLTaskScheduler();
// btParallelFor -- call this to dispatch work like a for-loop
// (iterations may be done out of order, so no dependencies are allowed)
-void btParallelFor( int iBegin, int iEnd, int grainSize, const btIParallelForBody& body );
+void btParallelFor(int iBegin, int iEnd, int grainSize, const btIParallelForBody& body);
// btParallelSum -- call this to dispatch work like a for-loop, returns the sum of all iterations
// (iterations may be done out of order, so no dependencies are allowed)
-btScalar btParallelSum( int iBegin, int iEnd, int grainSize, const btIParallelSumBody& body );
-
+btScalar btParallelSum(int iBegin, int iEnd, int grainSize, const btIParallelSumBody& body);
#endif
diff --git a/thirdparty/bullet/LinearMath/btTransform.h b/thirdparty/bullet/LinearMath/btTransform.h
index d4f939a5d9..6f2f99818c 100644
--- a/thirdparty/bullet/LinearMath/btTransform.h
+++ b/thirdparty/bullet/LinearMath/btTransform.h
@@ -12,12 +12,9 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
-
#ifndef BT_TRANSFORM_H
#define BT_TRANSFORM_H
-
#include "btMatrix3x3.h"
#ifdef BT_USE_DOUBLE_PRECISION
@@ -26,46 +23,45 @@ subject to the following restrictions:
#define btTransformData btTransformFloatData
#endif
-
-
-
/**@brief The btTransform class supports rigid transforms with only translation and rotation and no scaling/shear.
*It can be used in combination with btVector3, btQuaternion and btMatrix3x3 linear algebra classes. */
-ATTRIBUTE_ALIGNED16(class) btTransform {
-
- ///Storage for the rotation
+ATTRIBUTE_ALIGNED16(class)
+btTransform
+{
+ ///Storage for the rotation
btMatrix3x3 m_basis;
- ///Storage for the translation
- btVector3 m_origin;
+ ///Storage for the translation
+ btVector3 m_origin;
public:
-
- /**@brief No initialization constructor */
+ /**@brief No initialization constructor */
btTransform() {}
- /**@brief Constructor from btQuaternion (optional btVector3 )
+ /**@brief Constructor from btQuaternion (optional btVector3 )
* @param q Rotation from quaternion
* @param c Translation from Vector (default 0,0,0) */
- explicit SIMD_FORCE_INLINE btTransform(const btQuaternion& q,
- const btVector3& c = btVector3(btScalar(0), btScalar(0), btScalar(0)))
+ explicit SIMD_FORCE_INLINE btTransform(const btQuaternion& q,
+ const btVector3& c = btVector3(btScalar(0), btScalar(0), btScalar(0)))
: m_basis(q),
- m_origin(c)
- {}
+ m_origin(c)
+ {
+ }
- /**@brief Constructor from btMatrix3x3 (optional btVector3)
+ /**@brief Constructor from btMatrix3x3 (optional btVector3)
* @param b Rotation from Matrix
* @param c Translation from Vector default (0,0,0)*/
- explicit SIMD_FORCE_INLINE btTransform(const btMatrix3x3& b,
- const btVector3& c = btVector3(btScalar(0), btScalar(0), btScalar(0)))
+ explicit SIMD_FORCE_INLINE btTransform(const btMatrix3x3& b,
+ const btVector3& c = btVector3(btScalar(0), btScalar(0), btScalar(0)))
: m_basis(b),
- m_origin(c)
- {}
- /**@brief Copy constructor */
- SIMD_FORCE_INLINE btTransform (const btTransform& other)
+ m_origin(c)
+ {
+ }
+ /**@brief Copy constructor */
+ SIMD_FORCE_INLINE btTransform(const btTransform& other)
: m_basis(other.m_basis),
- m_origin(other.m_origin)
+ m_origin(other.m_origin)
{
}
- /**@brief Assignment Operator */
+ /**@brief Assignment Operator */
SIMD_FORCE_INLINE btTransform& operator=(const btTransform& other)
{
m_basis = other.m_basis;
@@ -73,70 +69,70 @@ public:
return *this;
}
-
- /**@brief Set the current transform as the value of the product of two transforms
+ /**@brief Set the current transform as the value of the product of two transforms
* @param t1 Transform 1
* @param t2 Transform 2
* This = Transform1 * Transform2 */
- SIMD_FORCE_INLINE void mult(const btTransform& t1, const btTransform& t2) {
- m_basis = t1.m_basis * t2.m_basis;
- m_origin = t1(t2.m_origin);
- }
+ SIMD_FORCE_INLINE void mult(const btTransform& t1, const btTransform& t2)
+ {
+ m_basis = t1.m_basis * t2.m_basis;
+ m_origin = t1(t2.m_origin);
+ }
-/* void multInverseLeft(const btTransform& t1, const btTransform& t2) {
+ /* void multInverseLeft(const btTransform& t1, const btTransform& t2) {
btVector3 v = t2.m_origin - t1.m_origin;
m_basis = btMultTransposeLeft(t1.m_basis, t2.m_basis);
m_origin = v * t1.m_basis;
}
*/
-/**@brief Return the transform of the vector */
+ /**@brief Return the transform of the vector */
SIMD_FORCE_INLINE btVector3 operator()(const btVector3& x) const
{
- return x.dot3(m_basis[0], m_basis[1], m_basis[2]) + m_origin;
+ return x.dot3(m_basis[0], m_basis[1], m_basis[2]) + m_origin;
}
- /**@brief Return the transform of the vector */
+ /**@brief Return the transform of the vector */
SIMD_FORCE_INLINE btVector3 operator*(const btVector3& x) const
{
return (*this)(x);
}
- /**@brief Return the transform of the btQuaternion */
+ /**@brief Return the transform of the btQuaternion */
SIMD_FORCE_INLINE btQuaternion operator*(const btQuaternion& q) const
{
return getRotation() * q;
}
- /**@brief Return the basis matrix for the rotation */
- SIMD_FORCE_INLINE btMatrix3x3& getBasis() { return m_basis; }
- /**@brief Return the basis matrix for the rotation */
- SIMD_FORCE_INLINE const btMatrix3x3& getBasis() const { return m_basis; }
+ /**@brief Return the basis matrix for the rotation */
+ SIMD_FORCE_INLINE btMatrix3x3& getBasis() { return m_basis; }
+ /**@brief Return the basis matrix for the rotation */
+ SIMD_FORCE_INLINE const btMatrix3x3& getBasis() const { return m_basis; }
- /**@brief Return the origin vector translation */
- SIMD_FORCE_INLINE btVector3& getOrigin() { return m_origin; }
- /**@brief Return the origin vector translation */
- SIMD_FORCE_INLINE const btVector3& getOrigin() const { return m_origin; }
+ /**@brief Return the origin vector translation */
+ SIMD_FORCE_INLINE btVector3& getOrigin() { return m_origin; }
+ /**@brief Return the origin vector translation */
+ SIMD_FORCE_INLINE const btVector3& getOrigin() const { return m_origin; }
- /**@brief Return a quaternion representing the rotation */
- btQuaternion getRotation() const {
+ /**@brief Return a quaternion representing the rotation */
+ btQuaternion getRotation() const
+ {
btQuaternion q;
m_basis.getRotation(q);
return q;
}
-
-
- /**@brief Set from an array
+
+ /**@brief Set from an array
* @param m A pointer to a 16 element array (12 rotation(row major padded on the right by 1), and 3 translation */
- void setFromOpenGLMatrix(const btScalar *m)
+ void setFromOpenGLMatrix(const btScalar* m)
{
m_basis.setFromOpenGLSubMatrix(m);
- m_origin.setValue(m[12],m[13],m[14]);
+ m_origin.setValue(m[12], m[13], m[14]);
}
- /**@brief Fill an array representation
+ /**@brief Fill an array representation
* @param m A pointer to a 16 element array (12 rotation(row major padded on the right by 1), and 3 translation */
- void getOpenGLMatrix(btScalar *m) const
+ void getOpenGLMatrix(btScalar * m) const
{
m_basis.getOpenGLSubMatrix(m);
m[12] = m_origin.x();
@@ -145,80 +141,76 @@ public:
m[15] = btScalar(1.0);
}
- /**@brief Set the translational element
+ /**@brief Set the translational element
* @param origin The vector to set the translation to */
- SIMD_FORCE_INLINE void setOrigin(const btVector3& origin)
- {
+ SIMD_FORCE_INLINE void setOrigin(const btVector3& origin)
+ {
m_origin = origin;
}
SIMD_FORCE_INLINE btVector3 invXform(const btVector3& inVec) const;
-
- /**@brief Set the rotational element by btMatrix3x3 */
+ /**@brief Set the rotational element by btMatrix3x3 */
SIMD_FORCE_INLINE void setBasis(const btMatrix3x3& basis)
- {
+ {
m_basis = basis;
}
- /**@brief Set the rotational element by btQuaternion */
+ /**@brief Set the rotational element by btQuaternion */
SIMD_FORCE_INLINE void setRotation(const btQuaternion& q)
{
m_basis.setRotation(q);
}
-
- /**@brief Set this transformation to the identity */
+ /**@brief Set this transformation to the identity */
void setIdentity()
{
m_basis.setIdentity();
m_origin.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
}
- /**@brief Multiply this Transform by another(this = this * another)
+ /**@brief Multiply this Transform by another(this = this * another)
* @param t The other transform */
- btTransform& operator*=(const btTransform& t)
+ btTransform& operator*=(const btTransform& t)
{
m_origin += m_basis * t.m_origin;
m_basis *= t.m_basis;
return *this;
}
- /**@brief Return the inverse of this transform */
+ /**@brief Return the inverse of this transform */
btTransform inverse() const
- {
+ {
btMatrix3x3 inv = m_basis.transpose();
return btTransform(inv, inv * -m_origin);
}
- /**@brief Return the inverse of this transform times the other transform
+ /**@brief Return the inverse of this transform times the other transform
* @param t The other transform
* return this.inverse() * the other */
- btTransform inverseTimes(const btTransform& t) const;
+ btTransform inverseTimes(const btTransform& t) const;
- /**@brief Return the product of this transform and the other */
+ /**@brief Return the product of this transform and the other */
btTransform operator*(const btTransform& t) const;
- /**@brief Return an identity transform */
- static const btTransform& getIdentity()
+ /**@brief Return an identity transform */
+ static const btTransform& getIdentity()
{
static const btTransform identityTransform(btMatrix3x3::getIdentity());
return identityTransform;
}
- void serialize(struct btTransformData& dataOut) const;
-
- void serializeFloat(struct btTransformFloatData& dataOut) const;
+ void serialize(struct btTransformData & dataOut) const;
- void deSerialize(const struct btTransformData& dataIn);
+ void serializeFloat(struct btTransformFloatData & dataOut) const;
- void deSerializeDouble(const struct btTransformDoubleData& dataIn);
+ void deSerialize(const struct btTransformData& dataIn);
- void deSerializeFloat(const struct btTransformFloatData& dataIn);
+ void deSerializeDouble(const struct btTransformDoubleData& dataIn);
+ void deSerializeFloat(const struct btTransformFloatData& dataIn);
};
-
SIMD_FORCE_INLINE btVector3
btTransform::invXform(const btVector3& inVec) const
{
@@ -226,80 +218,69 @@ btTransform::invXform(const btVector3& inVec) const
return (m_basis.transpose() * v);
}
-SIMD_FORCE_INLINE btTransform
-btTransform::inverseTimes(const btTransform& t) const
+SIMD_FORCE_INLINE btTransform
+btTransform::inverseTimes(const btTransform& t) const
{
btVector3 v = t.getOrigin() - m_origin;
- return btTransform(m_basis.transposeTimes(t.m_basis),
- v * m_basis);
+ return btTransform(m_basis.transposeTimes(t.m_basis),
+ v * m_basis);
}
-SIMD_FORCE_INLINE btTransform
-btTransform::operator*(const btTransform& t) const
+SIMD_FORCE_INLINE btTransform
+ btTransform::operator*(const btTransform& t) const
{
- return btTransform(m_basis * t.m_basis,
- (*this)(t.m_origin));
+ return btTransform(m_basis * t.m_basis,
+ (*this)(t.m_origin));
}
/**@brief Test if two transforms have all elements equal */
SIMD_FORCE_INLINE bool operator==(const btTransform& t1, const btTransform& t2)
{
- return ( t1.getBasis() == t2.getBasis() &&
- t1.getOrigin() == t2.getOrigin() );
+ return (t1.getBasis() == t2.getBasis() &&
+ t1.getOrigin() == t2.getOrigin());
}
-
///for serialization
-struct btTransformFloatData
+struct btTransformFloatData
{
- btMatrix3x3FloatData m_basis;
- btVector3FloatData m_origin;
+ btMatrix3x3FloatData m_basis;
+ btVector3FloatData m_origin;
};
-struct btTransformDoubleData
+struct btTransformDoubleData
{
- btMatrix3x3DoubleData m_basis;
- btVector3DoubleData m_origin;
+ btMatrix3x3DoubleData m_basis;
+ btVector3DoubleData m_origin;
};
-
-
-SIMD_FORCE_INLINE void btTransform::serialize(btTransformData& dataOut) const
+SIMD_FORCE_INLINE void btTransform::serialize(btTransformData& dataOut) const
{
m_basis.serialize(dataOut.m_basis);
m_origin.serialize(dataOut.m_origin);
}
-SIMD_FORCE_INLINE void btTransform::serializeFloat(btTransformFloatData& dataOut) const
+SIMD_FORCE_INLINE void btTransform::serializeFloat(btTransformFloatData& dataOut) const
{
m_basis.serializeFloat(dataOut.m_basis);
m_origin.serializeFloat(dataOut.m_origin);
}
-
-SIMD_FORCE_INLINE void btTransform::deSerialize(const btTransformData& dataIn)
+SIMD_FORCE_INLINE void btTransform::deSerialize(const btTransformData& dataIn)
{
m_basis.deSerialize(dataIn.m_basis);
m_origin.deSerialize(dataIn.m_origin);
}
-SIMD_FORCE_INLINE void btTransform::deSerializeFloat(const btTransformFloatData& dataIn)
+SIMD_FORCE_INLINE void btTransform::deSerializeFloat(const btTransformFloatData& dataIn)
{
m_basis.deSerializeFloat(dataIn.m_basis);
m_origin.deSerializeFloat(dataIn.m_origin);
}
-SIMD_FORCE_INLINE void btTransform::deSerializeDouble(const btTransformDoubleData& dataIn)
+SIMD_FORCE_INLINE void btTransform::deSerializeDouble(const btTransformDoubleData& dataIn)
{
m_basis.deSerializeDouble(dataIn.m_basis);
m_origin.deSerializeDouble(dataIn.m_origin);
}
-
-#endif //BT_TRANSFORM_H
-
-
-
-
-
-
+#endif //BT_TRANSFORM_H
diff --git a/thirdparty/bullet/LinearMath/btTransformUtil.h b/thirdparty/bullet/LinearMath/btTransformUtil.h
index 182cc43fab..b874dd6807 100644
--- a/thirdparty/bullet/LinearMath/btTransformUtil.h
+++ b/thirdparty/bullet/LinearMath/btTransformUtil.h
@@ -12,77 +12,66 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
#ifndef BT_TRANSFORM_UTIL_H
#define BT_TRANSFORM_UTIL_H
#include "btTransform.h"
-#define ANGULAR_MOTION_THRESHOLD btScalar(0.5)*SIMD_HALF_PI
-
-
-
+#define ANGULAR_MOTION_THRESHOLD btScalar(0.5) * SIMD_HALF_PI
-SIMD_FORCE_INLINE btVector3 btAabbSupport(const btVector3& halfExtents,const btVector3& supportDir)
+SIMD_FORCE_INLINE btVector3 btAabbSupport(const btVector3& halfExtents, const btVector3& supportDir)
{
return btVector3(supportDir.x() < btScalar(0.0) ? -halfExtents.x() : halfExtents.x(),
- supportDir.y() < btScalar(0.0) ? -halfExtents.y() : halfExtents.y(),
- supportDir.z() < btScalar(0.0) ? -halfExtents.z() : halfExtents.z());
+ supportDir.y() < btScalar(0.0) ? -halfExtents.y() : halfExtents.y(),
+ supportDir.z() < btScalar(0.0) ? -halfExtents.z() : halfExtents.z());
}
-
-
-
-
-
/// Utils related to temporal transforms
class btTransformUtil
{
-
public:
-
- static void integrateTransform(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep,btTransform& predictedTransform)
+ static void integrateTransform(const btTransform& curTrans, const btVector3& linvel, const btVector3& angvel, btScalar timeStep, btTransform& predictedTransform)
{
predictedTransform.setOrigin(curTrans.getOrigin() + linvel * timeStep);
-// #define QUATERNION_DERIVATIVE
- #ifdef QUATERNION_DERIVATIVE
+ // #define QUATERNION_DERIVATIVE
+#ifdef QUATERNION_DERIVATIVE
btQuaternion predictedOrn = curTrans.getRotation();
predictedOrn += (angvel * predictedOrn) * (timeStep * btScalar(0.5));
predictedOrn.safeNormalize();
- #else
+#else
//Exponential map
//google for "Practical Parameterization of Rotations Using the Exponential Map", F. Sebastian Grassia
btVector3 axis;
- btScalar fAngle2 = angvel.length2();
- btScalar fAngle = 0;
- if (fAngle2>SIMD_EPSILON)
- {
- fAngle = btSqrt(fAngle2);
- }
+ btScalar fAngle2 = angvel.length2();
+ btScalar fAngle = 0;
+ if (fAngle2 > SIMD_EPSILON)
+ {
+ fAngle = btSqrt(fAngle2);
+ }
//limit the angular motion
- if (fAngle*timeStep > ANGULAR_MOTION_THRESHOLD)
+ if (fAngle * timeStep > ANGULAR_MOTION_THRESHOLD)
{
fAngle = ANGULAR_MOTION_THRESHOLD / timeStep;
}
- if ( fAngle < btScalar(0.001) )
+ if (fAngle < btScalar(0.001))
{
// use Taylor's expansions of sync function
- axis = angvel*( btScalar(0.5)*timeStep-(timeStep*timeStep*timeStep)*(btScalar(0.020833333333))*fAngle*fAngle );
+ axis = angvel * (btScalar(0.5) * timeStep - (timeStep * timeStep * timeStep) * (btScalar(0.020833333333)) * fAngle * fAngle);
}
else
{
// sync(fAngle) = sin(c*fAngle)/t
- axis = angvel*( btSin(btScalar(0.5)*fAngle*timeStep)/fAngle );
+ axis = angvel * (btSin(btScalar(0.5) * fAngle * timeStep) / fAngle);
}
- btQuaternion dorn (axis.x(),axis.y(),axis.z(),btCos( fAngle*timeStep*btScalar(0.5) ));
+ btQuaternion dorn(axis.x(), axis.y(), axis.z(), btCos(fAngle * timeStep * btScalar(0.5)));
btQuaternion orn0 = curTrans.getRotation();
btQuaternion predictedOrn = dorn * orn0;
predictedOrn.safeNormalize();
- #endif
- if (predictedOrn.length2()>SIMD_EPSILON)
+#endif
+ if (predictedOrn.length2() > SIMD_EPSILON)
{
predictedTransform.setRotation(predictedOrn);
}
@@ -92,137 +81,133 @@ public:
}
}
- static void calculateVelocityQuaternion(const btVector3& pos0,const btVector3& pos1,const btQuaternion& orn0,const btQuaternion& orn1,btScalar timeStep,btVector3& linVel,btVector3& angVel)
+ static void calculateVelocityQuaternion(const btVector3& pos0, const btVector3& pos1, const btQuaternion& orn0, const btQuaternion& orn1, btScalar timeStep, btVector3& linVel, btVector3& angVel)
{
linVel = (pos1 - pos0) / timeStep;
btVector3 axis;
- btScalar angle;
+ btScalar angle;
if (orn0 != orn1)
{
- calculateDiffAxisAngleQuaternion(orn0,orn1,axis,angle);
+ calculateDiffAxisAngleQuaternion(orn0, orn1, axis, angle);
angVel = axis * angle / timeStep;
- } else
+ }
+ else
{
- angVel.setValue(0,0,0);
+ angVel.setValue(0, 0, 0);
}
}
- static void calculateDiffAxisAngleQuaternion(const btQuaternion& orn0,const btQuaternion& orn1a,btVector3& axis,btScalar& angle)
+ static void calculateDiffAxisAngleQuaternion(const btQuaternion& orn0, const btQuaternion& orn1a, btVector3& axis, btScalar& angle)
{
btQuaternion orn1 = orn0.nearest(orn1a);
btQuaternion dorn = orn1 * orn0.inverse();
angle = dorn.getAngle();
- axis = btVector3(dorn.x(),dorn.y(),dorn.z());
+ axis = btVector3(dorn.x(), dorn.y(), dorn.z());
axis[3] = btScalar(0.);
//check for axis length
btScalar len = axis.length2();
- if (len < SIMD_EPSILON*SIMD_EPSILON)
- axis = btVector3(btScalar(1.),btScalar(0.),btScalar(0.));
+ if (len < SIMD_EPSILON * SIMD_EPSILON)
+ axis = btVector3(btScalar(1.), btScalar(0.), btScalar(0.));
else
axis /= btSqrt(len);
}
- static void calculateVelocity(const btTransform& transform0,const btTransform& transform1,btScalar timeStep,btVector3& linVel,btVector3& angVel)
+ static void calculateVelocity(const btTransform& transform0, const btTransform& transform1, btScalar timeStep, btVector3& linVel, btVector3& angVel)
{
linVel = (transform1.getOrigin() - transform0.getOrigin()) / timeStep;
btVector3 axis;
- btScalar angle;
- calculateDiffAxisAngle(transform0,transform1,axis,angle);
+ btScalar angle;
+ calculateDiffAxisAngle(transform0, transform1, axis, angle);
angVel = axis * angle / timeStep;
}
- static void calculateDiffAxisAngle(const btTransform& transform0,const btTransform& transform1,btVector3& axis,btScalar& angle)
+ static void calculateDiffAxisAngle(const btTransform& transform0, const btTransform& transform1, btVector3& axis, btScalar& angle)
{
btMatrix3x3 dmat = transform1.getBasis() * transform0.getBasis().inverse();
btQuaternion dorn;
dmat.getRotation(dorn);
- ///floating point inaccuracy can lead to w component > 1..., which breaks
+ ///floating point inaccuracy can lead to w component > 1..., which breaks
dorn.normalize();
-
+
angle = dorn.getAngle();
- axis = btVector3(dorn.x(),dorn.y(),dorn.z());
+ axis = btVector3(dorn.x(), dorn.y(), dorn.z());
axis[3] = btScalar(0.);
//check for axis length
btScalar len = axis.length2();
- if (len < SIMD_EPSILON*SIMD_EPSILON)
- axis = btVector3(btScalar(1.),btScalar(0.),btScalar(0.));
+ if (len < SIMD_EPSILON * SIMD_EPSILON)
+ axis = btVector3(btScalar(1.), btScalar(0.), btScalar(0.));
else
axis /= btSqrt(len);
}
-
};
-
-///The btConvexSeparatingDistanceUtil can help speed up convex collision detection
+///The btConvexSeparatingDistanceUtil can help speed up convex collision detection
///by conservatively updating a cached separating distance/vector instead of re-calculating the closest distance
-class btConvexSeparatingDistanceUtil
+class btConvexSeparatingDistanceUtil
{
- btQuaternion m_ornA;
- btQuaternion m_ornB;
- btVector3 m_posA;
- btVector3 m_posB;
-
- btVector3 m_separatingNormal;
+ btQuaternion m_ornA;
+ btQuaternion m_ornB;
+ btVector3 m_posA;
+ btVector3 m_posB;
- btScalar m_boundingRadiusA;
- btScalar m_boundingRadiusB;
- btScalar m_separatingDistance;
+ btVector3 m_separatingNormal;
-public:
+ btScalar m_boundingRadiusA;
+ btScalar m_boundingRadiusB;
+ btScalar m_separatingDistance;
- btConvexSeparatingDistanceUtil(btScalar boundingRadiusA,btScalar boundingRadiusB)
- :m_boundingRadiusA(boundingRadiusA),
- m_boundingRadiusB(boundingRadiusB),
- m_separatingDistance(0.f)
+public:
+ btConvexSeparatingDistanceUtil(btScalar boundingRadiusA, btScalar boundingRadiusB)
+ : m_boundingRadiusA(boundingRadiusA),
+ m_boundingRadiusB(boundingRadiusB),
+ m_separatingDistance(0.f)
{
}
- btScalar getConservativeSeparatingDistance()
+ btScalar getConservativeSeparatingDistance()
{
return m_separatingDistance;
}
- void updateSeparatingDistance(const btTransform& transA,const btTransform& transB)
+ void updateSeparatingDistance(const btTransform& transA, const btTransform& transB)
{
const btVector3& toPosA = transA.getOrigin();
const btVector3& toPosB = transB.getOrigin();
btQuaternion toOrnA = transA.getRotation();
btQuaternion toOrnB = transB.getRotation();
- if (m_separatingDistance>0.f)
+ if (m_separatingDistance > 0.f)
{
-
-
- btVector3 linVelA,angVelA,linVelB,angVelB;
- btTransformUtil::calculateVelocityQuaternion(m_posA,toPosA,m_ornA,toOrnA,btScalar(1.),linVelA,angVelA);
- btTransformUtil::calculateVelocityQuaternion(m_posB,toPosB,m_ornB,toOrnB,btScalar(1.),linVelB,angVelB);
+ btVector3 linVelA, angVelA, linVelB, angVelB;
+ btTransformUtil::calculateVelocityQuaternion(m_posA, toPosA, m_ornA, toOrnA, btScalar(1.), linVelA, angVelA);
+ btTransformUtil::calculateVelocityQuaternion(m_posB, toPosB, m_ornB, toOrnB, btScalar(1.), linVelB, angVelB);
btScalar maxAngularProjectedVelocity = angVelA.length() * m_boundingRadiusA + angVelB.length() * m_boundingRadiusB;
- btVector3 relLinVel = (linVelB-linVelA);
+ btVector3 relLinVel = (linVelB - linVelA);
btScalar relLinVelocLength = relLinVel.dot(m_separatingNormal);
- if (relLinVelocLength<0.f)
+ if (relLinVelocLength < 0.f)
{
relLinVelocLength = 0.f;
}
-
- btScalar projectedMotion = maxAngularProjectedVelocity +relLinVelocLength;
+
+ btScalar projectedMotion = maxAngularProjectedVelocity + relLinVelocLength;
m_separatingDistance -= projectedMotion;
}
-
+
m_posA = toPosA;
m_posB = toPosB;
m_ornA = toOrnA;
m_ornB = toOrnB;
}
- void initSeparatingDistance(const btVector3& separatingVector,btScalar separatingDistance,const btTransform& transA,const btTransform& transB)
+ void initSeparatingDistance(const btVector3& separatingVector, btScalar separatingDistance, const btTransform& transA, const btTransform& transB)
{
m_separatingDistance = separatingDistance;
- if (m_separatingDistance>0.f)
+ if (m_separatingDistance > 0.f)
{
m_separatingNormal = separatingVector;
-
+
const btVector3& toPosA = transA.getOrigin();
const btVector3& toPosB = transB.getOrigin();
btQuaternion toOrnA = transA.getRotation();
@@ -233,9 +218,6 @@ public:
m_ornB = toOrnB;
}
}
-
};
-
-#endif //BT_TRANSFORM_UTIL_H
-
+#endif //BT_TRANSFORM_UTIL_H
diff --git a/thirdparty/bullet/LinearMath/btVector3.cpp b/thirdparty/bullet/LinearMath/btVector3.cpp
index e05bdccd67..13111157af 100644
--- a/thirdparty/bullet/LinearMath/btVector3.cpp
+++ b/thirdparty/bullet/LinearMath/btVector3.cpp
@@ -15,282 +15,285 @@
This source version has been altered.
*/
-#if defined (_WIN32) || defined (__i386__)
+#if defined(_WIN32) || defined(__i386__)
#define BT_USE_SSE_IN_API
#endif
-
#include "btVector3.h"
-
-
#if defined BT_USE_SIMD_VECTOR3
#if DEBUG
-#include <string.h>//for memset
+#include <string.h> //for memset
#endif
-
#ifdef __APPLE__
#include <stdint.h>
-typedef float float4 __attribute__ ((vector_size(16)));
+typedef float float4 __attribute__((vector_size(16)));
#else
#define float4 __m128
#endif
//typedef uint32_t uint4 __attribute__ ((vector_size(16)));
-
#if defined BT_USE_SSE || defined _WIN32
-#define LOG2_ARRAY_SIZE 6
-#define STACK_ARRAY_COUNT (1UL << LOG2_ARRAY_SIZE)
+#define LOG2_ARRAY_SIZE 6
+#define STACK_ARRAY_COUNT (1UL << LOG2_ARRAY_SIZE)
#include <emmintrin.h>
-long _maxdot_large( const float *vv, const float *vec, unsigned long count, float *dotResult );
-long _maxdot_large( const float *vv, const float *vec, unsigned long count, float *dotResult )
+long _maxdot_large(const float *vv, const float *vec, unsigned long count, float *dotResult);
+long _maxdot_large(const float *vv, const float *vec, unsigned long count, float *dotResult)
{
- const float4 *vertices = (const float4*) vv;
- static const unsigned char indexTable[16] = {(unsigned char)-1, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 };
- float4 dotMax = btAssign128( -BT_INFINITY, -BT_INFINITY, -BT_INFINITY, -BT_INFINITY );
- float4 vvec = _mm_loadu_ps( vec );
- float4 vHi = btCastiTo128f(_mm_shuffle_epi32( btCastfTo128i( vvec), 0xaa )); /// zzzz
- float4 vLo = _mm_movelh_ps( vvec, vvec ); /// xyxy
-
- long maxIndex = -1L;
-
- size_t segment = 0;
- float4 stack_array[ STACK_ARRAY_COUNT ];
-
+ const float4 *vertices = (const float4 *)vv;
+ static const unsigned char indexTable[16] = {(unsigned char)-1, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0};
+ float4 dotMax = btAssign128(-BT_INFINITY, -BT_INFINITY, -BT_INFINITY, -BT_INFINITY);
+ float4 vvec = _mm_loadu_ps(vec);
+ float4 vHi = btCastiTo128f(_mm_shuffle_epi32(btCastfTo128i(vvec), 0xaa)); /// zzzz
+ float4 vLo = _mm_movelh_ps(vvec, vvec); /// xyxy
+
+ long maxIndex = -1L;
+
+ size_t segment = 0;
+ float4 stack_array[STACK_ARRAY_COUNT];
+
#if DEBUG
- //memset( stack_array, -1, STACK_ARRAY_COUNT * sizeof(stack_array[0]) );
+ //memset( stack_array, -1, STACK_ARRAY_COUNT * sizeof(stack_array[0]) );
#endif
-
- size_t index;
- float4 max;
- // Faster loop without cleanup code for full tiles
- for ( segment = 0; segment + STACK_ARRAY_COUNT*4 <= count; segment += STACK_ARRAY_COUNT*4 )
- {
- max = dotMax;
-
- for( index = 0; index < STACK_ARRAY_COUNT; index+= 4 )
- { // do four dot products at a time. Carefully avoid touching the w element.
- float4 v0 = vertices[0];
- float4 v1 = vertices[1];
- float4 v2 = vertices[2];
- float4 v3 = vertices[3]; vertices += 4;
-
- float4 lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
- float4 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
- float4 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
- float4 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
-
- lo0 = lo0*vLo;
- lo1 = lo1*vLo;
- float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
- float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
- float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z*vHi;
- x = x+y;
- x = x+z;
- stack_array[index] = x;
- max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3]; vertices += 4;
-
- lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
-
- lo0 = lo0*vLo;
- lo1 = lo1*vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z*vHi;
- x = x+y;
- x = x+z;
- stack_array[index+1] = x;
- max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3]; vertices += 4;
-
- lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
-
- lo0 = lo0*vLo;
- lo1 = lo1*vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z*vHi;
- x = x+y;
- x = x+z;
- stack_array[index+2] = x;
- max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3]; vertices += 4;
-
- lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
-
- lo0 = lo0*vLo;
- lo1 = lo1*vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z*vHi;
- x = x+y;
- x = x+z;
- stack_array[index+3] = x;
- max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
-
- // It is too costly to keep the index of the max here. We will look for it again later. We save a lot of work this way.
- }
-
- // If we found a new max
- if( 0xf != _mm_movemask_ps( (float4) _mm_cmpeq_ps(max, dotMax)))
- {
- // copy the new max across all lanes of our max accumulator
- max = _mm_max_ps(max, (float4) _mm_shuffle_ps( max, max, 0x4e));
- max = _mm_max_ps(max, (float4) _mm_shuffle_ps( max, max, 0xb1));
-
- dotMax = max;
-
- // find first occurrence of that max
- size_t test;
- for( index = 0; 0 == (test=_mm_movemask_ps( _mm_cmpeq_ps( stack_array[index], max))); index++ ) // local_count must be a multiple of 4
- {}
- // record where it is.
- maxIndex = 4*index + segment + indexTable[test];
- }
- }
-
- // account for work we've already done
- count -= segment;
-
- // Deal with the last < STACK_ARRAY_COUNT vectors
- max = dotMax;
- index = 0;
-
-
- if( btUnlikely( count > 16) )
- {
- for( ; index + 4 <= count / 4; index+=4 )
- { // do four dot products at a time. Carefully avoid touching the w element.
- float4 v0 = vertices[0];
- float4 v1 = vertices[1];
- float4 v2 = vertices[2];
- float4 v3 = vertices[3]; vertices += 4;
-
- float4 lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
- float4 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
- float4 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
- float4 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
-
- lo0 = lo0*vLo;
- lo1 = lo1*vLo;
- float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
- float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
- float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z*vHi;
- x = x+y;
- x = x+z;
- stack_array[index] = x;
- max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3]; vertices += 4;
-
- lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
-
- lo0 = lo0*vLo;
- lo1 = lo1*vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z*vHi;
- x = x+y;
- x = x+z;
- stack_array[index+1] = x;
- max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3]; vertices += 4;
-
- lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
-
- lo0 = lo0*vLo;
- lo1 = lo1*vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z*vHi;
- x = x+y;
- x = x+z;
- stack_array[index+2] = x;
- max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3]; vertices += 4;
-
- lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
-
- lo0 = lo0*vLo;
- lo1 = lo1*vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z*vHi;
- x = x+y;
- x = x+z;
- stack_array[index+3] = x;
- max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
-
- // It is too costly to keep the index of the max here. We will look for it again later. We save a lot of work this way.
- }
- }
-
- size_t localCount = (count & -4L) - 4*index;
- if( localCount )
- {
+
+ size_t index;
+ float4 max;
+ // Faster loop without cleanup code for full tiles
+ for (segment = 0; segment + STACK_ARRAY_COUNT * 4 <= count; segment += STACK_ARRAY_COUNT * 4)
+ {
+ max = dotMax;
+
+ for (index = 0; index < STACK_ARRAY_COUNT; index += 4)
+ { // do four dot products at a time. Carefully avoid touching the w element.
+ float4 v0 = vertices[0];
+ float4 v1 = vertices[1];
+ float4 v2 = vertices[2];
+ float4 v3 = vertices[3];
+ vertices += 4;
+
+ float4 lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
+ float4 hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
+ float4 lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
+ float4 hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
+
+ lo0 = lo0 * vLo;
+ lo1 = lo1 * vLo;
+ float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z * vHi;
+ x = x + y;
+ x = x + z;
+ stack_array[index] = x;
+ max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3];
+ vertices += 4;
+
+ lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
+
+ lo0 = lo0 * vLo;
+ lo1 = lo1 * vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z * vHi;
+ x = x + y;
+ x = x + z;
+ stack_array[index + 1] = x;
+ max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3];
+ vertices += 4;
+
+ lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
+
+ lo0 = lo0 * vLo;
+ lo1 = lo1 * vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z * vHi;
+ x = x + y;
+ x = x + z;
+ stack_array[index + 2] = x;
+ max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3];
+ vertices += 4;
+
+ lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
+
+ lo0 = lo0 * vLo;
+ lo1 = lo1 * vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z * vHi;
+ x = x + y;
+ x = x + z;
+ stack_array[index + 3] = x;
+ max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
+
+ // It is too costly to keep the index of the max here. We will look for it again later. We save a lot of work this way.
+ }
+
+ // If we found a new max
+ if (0xf != _mm_movemask_ps((float4)_mm_cmpeq_ps(max, dotMax)))
+ {
+ // copy the new max across all lanes of our max accumulator
+ max = _mm_max_ps(max, (float4)_mm_shuffle_ps(max, max, 0x4e));
+ max = _mm_max_ps(max, (float4)_mm_shuffle_ps(max, max, 0xb1));
+
+ dotMax = max;
+
+ // find first occurrence of that max
+ size_t test;
+ for (index = 0; 0 == (test = _mm_movemask_ps(_mm_cmpeq_ps(stack_array[index], max))); index++) // local_count must be a multiple of 4
+ {
+ }
+ // record where it is.
+ maxIndex = 4 * index + segment + indexTable[test];
+ }
+ }
+
+ // account for work we've already done
+ count -= segment;
+
+ // Deal with the last < STACK_ARRAY_COUNT vectors
+ max = dotMax;
+ index = 0;
+
+ if (btUnlikely(count > 16))
+ {
+ for (; index + 4 <= count / 4; index += 4)
+ { // do four dot products at a time. Carefully avoid touching the w element.
+ float4 v0 = vertices[0];
+ float4 v1 = vertices[1];
+ float4 v2 = vertices[2];
+ float4 v3 = vertices[3];
+ vertices += 4;
+
+ float4 lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
+ float4 hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
+ float4 lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
+ float4 hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
+
+ lo0 = lo0 * vLo;
+ lo1 = lo1 * vLo;
+ float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z * vHi;
+ x = x + y;
+ x = x + z;
+ stack_array[index] = x;
+ max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3];
+ vertices += 4;
+
+ lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
+
+ lo0 = lo0 * vLo;
+ lo1 = lo1 * vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z * vHi;
+ x = x + y;
+ x = x + z;
+ stack_array[index + 1] = x;
+ max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3];
+ vertices += 4;
+
+ lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
+
+ lo0 = lo0 * vLo;
+ lo1 = lo1 * vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z * vHi;
+ x = x + y;
+ x = x + z;
+ stack_array[index + 2] = x;
+ max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3];
+ vertices += 4;
+
+ lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
+
+ lo0 = lo0 * vLo;
+ lo1 = lo1 * vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z * vHi;
+ x = x + y;
+ x = x + z;
+ stack_array[index + 3] = x;
+ max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
+
+ // It is too costly to keep the index of the max here. We will look for it again later. We save a lot of work this way.
+ }
+ }
+
+ size_t localCount = (count & -4L) - 4 * index;
+ if (localCount)
+ {
#ifdef __APPLE__
- float4 t0, t1, t2, t3, t4;
- float4 * sap = &stack_array[index + localCount / 4];
- vertices += localCount; // counter the offset
- size_t byteIndex = -(localCount) * sizeof(float);
- //AT&T Code style assembly
- asm volatile
- ( ".align 4 \n\
+ float4 t0, t1, t2, t3, t4;
+ float4 *sap = &stack_array[index + localCount / 4];
+ vertices += localCount; // counter the offset
+ size_t byteIndex = -(localCount) * sizeof(float);
+ //AT&T Code style assembly
+ asm volatile(
+ ".align 4 \n\
0: movaps %[max], %[t2] // move max out of the way to avoid propagating NaNs in max \n\
movaps (%[vertices], %[byteIndex], 4), %[t0] // vertices[0] \n\
movaps 16(%[vertices], %[byteIndex], 4), %[t1] // vertices[1] \n\
@@ -316,368 +319,374 @@ long _maxdot_large( const float *vv, const float *vec, unsigned long count, floa
add $16, %[byteIndex] // advance loop counter\n\
jnz 0b \n\
"
- : [max] "+x" (max), [t0] "=&x" (t0), [t1] "=&x" (t1), [t2] "=&x" (t2), [t3] "=&x" (t3), [t4] "=&x" (t4), [byteIndex] "+r" (byteIndex)
- : [vLo] "x" (vLo), [vHi] "x" (vHi), [vertices] "r" (vertices), [sap] "r" (sap)
- : "memory", "cc"
- );
- index += localCount/4;
+ : [max] "+x"(max), [t0] "=&x"(t0), [t1] "=&x"(t1), [t2] "=&x"(t2), [t3] "=&x"(t3), [t4] "=&x"(t4), [byteIndex] "+r"(byteIndex)
+ : [vLo] "x"(vLo), [vHi] "x"(vHi), [vertices] "r"(vertices), [sap] "r"(sap)
+ : "memory", "cc");
+ index += localCount / 4;
#else
- {
- for( unsigned int i=0; i<localCount/4; i++,index++)
- { // do four dot products at a time. Carefully avoid touching the w element.
- float4 v0 = vertices[0];
- float4 v1 = vertices[1];
- float4 v2 = vertices[2];
- float4 v3 = vertices[3];
- vertices += 4;
-
- float4 lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
- float4 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
- float4 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
- float4 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
-
- lo0 = lo0*vLo;
- lo1 = lo1*vLo;
- float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
- float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
- float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z*vHi;
- x = x+y;
- x = x+z;
- stack_array[index] = x;
- max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
- }
- }
-#endif //__APPLE__
- }
-
- // process the last few points
- if( count & 3 )
- {
- float4 v0, v1, v2, x, y, z;
- switch( count & 3 )
- {
- case 3:
- {
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
-
- // Calculate 3 dot products, transpose, duplicate v2
- float4 lo0 = _mm_movelh_ps( v0, v1); // xyxy.lo
- float4 hi0 = _mm_movehl_ps( v1, v0); // z?z?.lo
- lo0 = lo0*vLo;
- z = _mm_shuffle_ps(hi0, v2, 0xa8 ); // z0z1z2z2
- z = z*vHi;
- float4 lo1 = _mm_movelh_ps(v2, v2); // xyxy
- lo1 = lo1*vLo;
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- }
- break;
- case 2:
- {
- v0 = vertices[0];
- v1 = vertices[1];
- float4 xy = _mm_movelh_ps(v0, v1);
- z = _mm_movehl_ps(v1, v0);
- xy = xy*vLo;
- z = _mm_shuffle_ps( z, z, 0xa8);
- x = _mm_shuffle_ps( xy, xy, 0xa8);
- y = _mm_shuffle_ps( xy, xy, 0xfd);
- z = z*vHi;
- }
- break;
- case 1:
- {
- float4 xy = vertices[0];
- z = _mm_shuffle_ps( xy, xy, 0xaa);
- xy = xy*vLo;
- z = z*vHi;
- x = _mm_shuffle_ps(xy, xy, 0);
- y = _mm_shuffle_ps(xy, xy, 0x55);
- }
- break;
- }
- x = x+y;
- x = x+z;
- stack_array[index] = x;
- max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
- index++;
- }
-
- // if we found a new max.
- if( 0 == segment || 0xf != _mm_movemask_ps( (float4) _mm_cmpeq_ps(max, dotMax)))
- { // we found a new max. Search for it
- // find max across the max vector, place in all elements of max -- big latency hit here
- max = _mm_max_ps(max, (float4) _mm_shuffle_ps( max, max, 0x4e));
- max = _mm_max_ps(max, (float4) _mm_shuffle_ps( max, max, 0xb1));
-
- // It is slightly faster to do this part in scalar code when count < 8. However, the common case for
- // this where it actually makes a difference is handled in the early out at the top of the function,
- // so it is less than a 1% difference here. I opted for improved code size, fewer branches and reduced
- // complexity, and removed it.
-
- dotMax = max;
-
- // scan for the first occurence of max in the array
- size_t test;
- for( index = 0; 0 == (test=_mm_movemask_ps( _mm_cmpeq_ps( stack_array[index], max))); index++ ) // local_count must be a multiple of 4
- {}
- maxIndex = 4*index + segment + indexTable[test];
- }
-
- _mm_store_ss( dotResult, dotMax);
- return maxIndex;
+ {
+ for (unsigned int i = 0; i < localCount / 4; i++, index++)
+ { // do four dot products at a time. Carefully avoid touching the w element.
+ float4 v0 = vertices[0];
+ float4 v1 = vertices[1];
+ float4 v2 = vertices[2];
+ float4 v3 = vertices[3];
+ vertices += 4;
+
+ float4 lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
+ float4 hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
+ float4 lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
+ float4 hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
+
+ lo0 = lo0 * vLo;
+ lo1 = lo1 * vLo;
+ float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z * vHi;
+ x = x + y;
+ x = x + z;
+ stack_array[index] = x;
+ max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
+ }
+ }
+#endif //__APPLE__
+ }
+
+ // process the last few points
+ if (count & 3)
+ {
+ float4 v0, v1, v2, x, y, z;
+ switch (count & 3)
+ {
+ case 3:
+ {
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+
+ // Calculate 3 dot products, transpose, duplicate v2
+ float4 lo0 = _mm_movelh_ps(v0, v1); // xyxy.lo
+ float4 hi0 = _mm_movehl_ps(v1, v0); // z?z?.lo
+ lo0 = lo0 * vLo;
+ z = _mm_shuffle_ps(hi0, v2, 0xa8); // z0z1z2z2
+ z = z * vHi;
+ float4 lo1 = _mm_movelh_ps(v2, v2); // xyxy
+ lo1 = lo1 * vLo;
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ }
+ break;
+ case 2:
+ {
+ v0 = vertices[0];
+ v1 = vertices[1];
+ float4 xy = _mm_movelh_ps(v0, v1);
+ z = _mm_movehl_ps(v1, v0);
+ xy = xy * vLo;
+ z = _mm_shuffle_ps(z, z, 0xa8);
+ x = _mm_shuffle_ps(xy, xy, 0xa8);
+ y = _mm_shuffle_ps(xy, xy, 0xfd);
+ z = z * vHi;
+ }
+ break;
+ case 1:
+ {
+ float4 xy = vertices[0];
+ z = _mm_shuffle_ps(xy, xy, 0xaa);
+ xy = xy * vLo;
+ z = z * vHi;
+ x = _mm_shuffle_ps(xy, xy, 0);
+ y = _mm_shuffle_ps(xy, xy, 0x55);
+ }
+ break;
+ }
+ x = x + y;
+ x = x + z;
+ stack_array[index] = x;
+ max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
+ index++;
+ }
+
+ // if we found a new max.
+ if (0 == segment || 0xf != _mm_movemask_ps((float4)_mm_cmpeq_ps(max, dotMax)))
+ { // we found a new max. Search for it
+ // find max across the max vector, place in all elements of max -- big latency hit here
+ max = _mm_max_ps(max, (float4)_mm_shuffle_ps(max, max, 0x4e));
+ max = _mm_max_ps(max, (float4)_mm_shuffle_ps(max, max, 0xb1));
+
+ // It is slightly faster to do this part in scalar code when count < 8. However, the common case for
+ // this where it actually makes a difference is handled in the early out at the top of the function,
+ // so it is less than a 1% difference here. I opted for improved code size, fewer branches and reduced
+ // complexity, and removed it.
+
+ dotMax = max;
+
+ // scan for the first occurence of max in the array
+ size_t test;
+ for (index = 0; 0 == (test = _mm_movemask_ps(_mm_cmpeq_ps(stack_array[index], max))); index++) // local_count must be a multiple of 4
+ {
+ }
+ maxIndex = 4 * index + segment + indexTable[test];
+ }
+
+ _mm_store_ss(dotResult, dotMax);
+ return maxIndex;
}
-long _mindot_large( const float *vv, const float *vec, unsigned long count, float *dotResult );
+long _mindot_large(const float *vv, const float *vec, unsigned long count, float *dotResult);
-long _mindot_large( const float *vv, const float *vec, unsigned long count, float *dotResult )
+long _mindot_large(const float *vv, const float *vec, unsigned long count, float *dotResult)
{
- const float4 *vertices = (const float4*) vv;
- static const unsigned char indexTable[16] = {(unsigned char)-1, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 };
- float4 dotmin = btAssign128( BT_INFINITY, BT_INFINITY, BT_INFINITY, BT_INFINITY );
- float4 vvec = _mm_loadu_ps( vec );
- float4 vHi = btCastiTo128f(_mm_shuffle_epi32( btCastfTo128i( vvec), 0xaa )); /// zzzz
- float4 vLo = _mm_movelh_ps( vvec, vvec ); /// xyxy
-
- long minIndex = -1L;
-
- size_t segment = 0;
- float4 stack_array[ STACK_ARRAY_COUNT ];
-
+ const float4 *vertices = (const float4 *)vv;
+ static const unsigned char indexTable[16] = {(unsigned char)-1, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0};
+ float4 dotmin = btAssign128(BT_INFINITY, BT_INFINITY, BT_INFINITY, BT_INFINITY);
+ float4 vvec = _mm_loadu_ps(vec);
+ float4 vHi = btCastiTo128f(_mm_shuffle_epi32(btCastfTo128i(vvec), 0xaa)); /// zzzz
+ float4 vLo = _mm_movelh_ps(vvec, vvec); /// xyxy
+
+ long minIndex = -1L;
+
+ size_t segment = 0;
+ float4 stack_array[STACK_ARRAY_COUNT];
+
#if DEBUG
- //memset( stack_array, -1, STACK_ARRAY_COUNT * sizeof(stack_array[0]) );
+ //memset( stack_array, -1, STACK_ARRAY_COUNT * sizeof(stack_array[0]) );
#endif
-
- size_t index;
- float4 min;
- // Faster loop without cleanup code for full tiles
- for ( segment = 0; segment + STACK_ARRAY_COUNT*4 <= count; segment += STACK_ARRAY_COUNT*4 )
- {
- min = dotmin;
-
- for( index = 0; index < STACK_ARRAY_COUNT; index+= 4 )
- { // do four dot products at a time. Carefully avoid touching the w element.
- float4 v0 = vertices[0];
- float4 v1 = vertices[1];
- float4 v2 = vertices[2];
- float4 v3 = vertices[3]; vertices += 4;
-
- float4 lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
- float4 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
- float4 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
- float4 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
-
- lo0 = lo0*vLo;
- lo1 = lo1*vLo;
- float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
- float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
- float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z*vHi;
- x = x+y;
- x = x+z;
- stack_array[index] = x;
- min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3]; vertices += 4;
-
- lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
-
- lo0 = lo0*vLo;
- lo1 = lo1*vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z*vHi;
- x = x+y;
- x = x+z;
- stack_array[index+1] = x;
- min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3]; vertices += 4;
-
- lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
-
- lo0 = lo0*vLo;
- lo1 = lo1*vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z*vHi;
- x = x+y;
- x = x+z;
- stack_array[index+2] = x;
- min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3]; vertices += 4;
-
- lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
-
- lo0 = lo0*vLo;
- lo1 = lo1*vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z*vHi;
- x = x+y;
- x = x+z;
- stack_array[index+3] = x;
- min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
-
- // It is too costly to keep the index of the min here. We will look for it again later. We save a lot of work this way.
- }
-
- // If we found a new min
- if( 0xf != _mm_movemask_ps( (float4) _mm_cmpeq_ps(min, dotmin)))
- {
- // copy the new min across all lanes of our min accumulator
- min = _mm_min_ps(min, (float4) _mm_shuffle_ps( min, min, 0x4e));
- min = _mm_min_ps(min, (float4) _mm_shuffle_ps( min, min, 0xb1));
-
- dotmin = min;
-
- // find first occurrence of that min
- size_t test;
- for( index = 0; 0 == (test=_mm_movemask_ps( _mm_cmpeq_ps( stack_array[index], min))); index++ ) // local_count must be a multiple of 4
- {}
- // record where it is.
- minIndex = 4*index + segment + indexTable[test];
- }
- }
-
- // account for work we've already done
- count -= segment;
-
- // Deal with the last < STACK_ARRAY_COUNT vectors
- min = dotmin;
- index = 0;
-
-
- if(btUnlikely( count > 16) )
- {
- for( ; index + 4 <= count / 4; index+=4 )
- { // do four dot products at a time. Carefully avoid touching the w element.
- float4 v0 = vertices[0];
- float4 v1 = vertices[1];
- float4 v2 = vertices[2];
- float4 v3 = vertices[3]; vertices += 4;
-
- float4 lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
- float4 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
- float4 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
- float4 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
-
- lo0 = lo0*vLo;
- lo1 = lo1*vLo;
- float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
- float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
- float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z*vHi;
- x = x+y;
- x = x+z;
- stack_array[index] = x;
- min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3]; vertices += 4;
-
- lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
-
- lo0 = lo0*vLo;
- lo1 = lo1*vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z*vHi;
- x = x+y;
- x = x+z;
- stack_array[index+1] = x;
- min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3]; vertices += 4;
-
- lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
-
- lo0 = lo0*vLo;
- lo1 = lo1*vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z*vHi;
- x = x+y;
- x = x+z;
- stack_array[index+2] = x;
- min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3]; vertices += 4;
-
- lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
-
- lo0 = lo0*vLo;
- lo1 = lo1*vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z*vHi;
- x = x+y;
- x = x+z;
- stack_array[index+3] = x;
- min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
-
- // It is too costly to keep the index of the min here. We will look for it again later. We save a lot of work this way.
- }
- }
-
- size_t localCount = (count & -4L) - 4*index;
- if( localCount )
- {
-
-
+
+ size_t index;
+ float4 min;
+ // Faster loop without cleanup code for full tiles
+ for (segment = 0; segment + STACK_ARRAY_COUNT * 4 <= count; segment += STACK_ARRAY_COUNT * 4)
+ {
+ min = dotmin;
+
+ for (index = 0; index < STACK_ARRAY_COUNT; index += 4)
+ { // do four dot products at a time. Carefully avoid touching the w element.
+ float4 v0 = vertices[0];
+ float4 v1 = vertices[1];
+ float4 v2 = vertices[2];
+ float4 v3 = vertices[3];
+ vertices += 4;
+
+ float4 lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
+ float4 hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
+ float4 lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
+ float4 hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
+
+ lo0 = lo0 * vLo;
+ lo1 = lo1 * vLo;
+ float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z * vHi;
+ x = x + y;
+ x = x + z;
+ stack_array[index] = x;
+ min = _mm_min_ps(x, min); // control the order here so that min is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3];
+ vertices += 4;
+
+ lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
+
+ lo0 = lo0 * vLo;
+ lo1 = lo1 * vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z * vHi;
+ x = x + y;
+ x = x + z;
+ stack_array[index + 1] = x;
+ min = _mm_min_ps(x, min); // control the order here so that min is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3];
+ vertices += 4;
+
+ lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
+
+ lo0 = lo0 * vLo;
+ lo1 = lo1 * vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z * vHi;
+ x = x + y;
+ x = x + z;
+ stack_array[index + 2] = x;
+ min = _mm_min_ps(x, min); // control the order here so that min is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3];
+ vertices += 4;
+
+ lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
+
+ lo0 = lo0 * vLo;
+ lo1 = lo1 * vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z * vHi;
+ x = x + y;
+ x = x + z;
+ stack_array[index + 3] = x;
+ min = _mm_min_ps(x, min); // control the order here so that min is never NaN even if x is nan
+
+ // It is too costly to keep the index of the min here. We will look for it again later. We save a lot of work this way.
+ }
+
+ // If we found a new min
+ if (0xf != _mm_movemask_ps((float4)_mm_cmpeq_ps(min, dotmin)))
+ {
+ // copy the new min across all lanes of our min accumulator
+ min = _mm_min_ps(min, (float4)_mm_shuffle_ps(min, min, 0x4e));
+ min = _mm_min_ps(min, (float4)_mm_shuffle_ps(min, min, 0xb1));
+
+ dotmin = min;
+
+ // find first occurrence of that min
+ size_t test;
+ for (index = 0; 0 == (test = _mm_movemask_ps(_mm_cmpeq_ps(stack_array[index], min))); index++) // local_count must be a multiple of 4
+ {
+ }
+ // record where it is.
+ minIndex = 4 * index + segment + indexTable[test];
+ }
+ }
+
+ // account for work we've already done
+ count -= segment;
+
+ // Deal with the last < STACK_ARRAY_COUNT vectors
+ min = dotmin;
+ index = 0;
+
+ if (btUnlikely(count > 16))
+ {
+ for (; index + 4 <= count / 4; index += 4)
+ { // do four dot products at a time. Carefully avoid touching the w element.
+ float4 v0 = vertices[0];
+ float4 v1 = vertices[1];
+ float4 v2 = vertices[2];
+ float4 v3 = vertices[3];
+ vertices += 4;
+
+ float4 lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
+ float4 hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
+ float4 lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
+ float4 hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
+
+ lo0 = lo0 * vLo;
+ lo1 = lo1 * vLo;
+ float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z * vHi;
+ x = x + y;
+ x = x + z;
+ stack_array[index] = x;
+ min = _mm_min_ps(x, min); // control the order here so that min is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3];
+ vertices += 4;
+
+ lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
+
+ lo0 = lo0 * vLo;
+ lo1 = lo1 * vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z * vHi;
+ x = x + y;
+ x = x + z;
+ stack_array[index + 1] = x;
+ min = _mm_min_ps(x, min); // control the order here so that min is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3];
+ vertices += 4;
+
+ lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
+
+ lo0 = lo0 * vLo;
+ lo1 = lo1 * vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z * vHi;
+ x = x + y;
+ x = x + z;
+ stack_array[index + 2] = x;
+ min = _mm_min_ps(x, min); // control the order here so that min is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3];
+ vertices += 4;
+
+ lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
+
+ lo0 = lo0 * vLo;
+ lo1 = lo1 * vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z * vHi;
+ x = x + y;
+ x = x + z;
+ stack_array[index + 3] = x;
+ min = _mm_min_ps(x, min); // control the order here so that min is never NaN even if x is nan
+
+ // It is too costly to keep the index of the min here. We will look for it again later. We save a lot of work this way.
+ }
+ }
+
+ size_t localCount = (count & -4L) - 4 * index;
+ if (localCount)
+ {
#ifdef __APPLE__
- vertices += localCount; // counter the offset
- float4 t0, t1, t2, t3, t4;
- size_t byteIndex = -(localCount) * sizeof(float);
- float4 * sap = &stack_array[index + localCount / 4];
-
- asm volatile
- ( ".align 4 \n\
+ vertices += localCount; // counter the offset
+ float4 t0, t1, t2, t3, t4;
+ size_t byteIndex = -(localCount) * sizeof(float);
+ float4 *sap = &stack_array[index + localCount / 4];
+
+ asm volatile(
+ ".align 4 \n\
0: movaps %[min], %[t2] // move min out of the way to avoid propagating NaNs in min \n\
movaps (%[vertices], %[byteIndex], 4), %[t0] // vertices[0] \n\
movaps 16(%[vertices], %[byteIndex], 4), %[t1] // vertices[1] \n\
@@ -703,968 +712,953 @@ long _mindot_large( const float *vv, const float *vec, unsigned long count, floa
add $16, %[byteIndex] // advance loop counter\n\
jnz 0b \n\
"
- : [min] "+x" (min), [t0] "=&x" (t0), [t1] "=&x" (t1), [t2] "=&x" (t2), [t3] "=&x" (t3), [t4] "=&x" (t4), [byteIndex] "+r" (byteIndex)
- : [vLo] "x" (vLo), [vHi] "x" (vHi), [vertices] "r" (vertices), [sap] "r" (sap)
- : "memory", "cc"
- );
- index += localCount/4;
+ : [min] "+x"(min), [t0] "=&x"(t0), [t1] "=&x"(t1), [t2] "=&x"(t2), [t3] "=&x"(t3), [t4] "=&x"(t4), [byteIndex] "+r"(byteIndex)
+ : [vLo] "x"(vLo), [vHi] "x"(vHi), [vertices] "r"(vertices), [sap] "r"(sap)
+ : "memory", "cc");
+ index += localCount / 4;
#else
- {
- for( unsigned int i=0; i<localCount/4; i++,index++)
- { // do four dot products at a time. Carefully avoid touching the w element.
- float4 v0 = vertices[0];
- float4 v1 = vertices[1];
- float4 v2 = vertices[2];
- float4 v3 = vertices[3];
- vertices += 4;
-
- float4 lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
- float4 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
- float4 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
- float4 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
-
- lo0 = lo0*vLo;
- lo1 = lo1*vLo;
- float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
- float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
- float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z*vHi;
- x = x+y;
- x = x+z;
- stack_array[index] = x;
- min = _mm_min_ps( x, min ); // control the order here so that max is never NaN even if x is nan
- }
- }
+ {
+ for (unsigned int i = 0; i < localCount / 4; i++, index++)
+ { // do four dot products at a time. Carefully avoid touching the w element.
+ float4 v0 = vertices[0];
+ float4 v1 = vertices[1];
+ float4 v2 = vertices[2];
+ float4 v3 = vertices[3];
+ vertices += 4;
+
+ float4 lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
+ float4 hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
+ float4 lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
+ float4 hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
+
+ lo0 = lo0 * vLo;
+ lo1 = lo1 * vLo;
+ float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z * vHi;
+ x = x + y;
+ x = x + z;
+ stack_array[index] = x;
+ min = _mm_min_ps(x, min); // control the order here so that max is never NaN even if x is nan
+ }
+ }
#endif
- }
-
- // process the last few points
- if( count & 3 )
- {
- float4 v0, v1, v2, x, y, z;
- switch( count & 3 )
- {
- case 3:
- {
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
-
- // Calculate 3 dot products, transpose, duplicate v2
- float4 lo0 = _mm_movelh_ps( v0, v1); // xyxy.lo
- float4 hi0 = _mm_movehl_ps( v1, v0); // z?z?.lo
- lo0 = lo0*vLo;
- z = _mm_shuffle_ps(hi0, v2, 0xa8 ); // z0z1z2z2
- z = z*vHi;
- float4 lo1 = _mm_movelh_ps(v2, v2); // xyxy
- lo1 = lo1*vLo;
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- }
- break;
- case 2:
- {
- v0 = vertices[0];
- v1 = vertices[1];
- float4 xy = _mm_movelh_ps(v0, v1);
- z = _mm_movehl_ps(v1, v0);
- xy = xy*vLo;
- z = _mm_shuffle_ps( z, z, 0xa8);
- x = _mm_shuffle_ps( xy, xy, 0xa8);
- y = _mm_shuffle_ps( xy, xy, 0xfd);
- z = z*vHi;
- }
- break;
- case 1:
- {
- float4 xy = vertices[0];
- z = _mm_shuffle_ps( xy, xy, 0xaa);
- xy = xy*vLo;
- z = z*vHi;
- x = _mm_shuffle_ps(xy, xy, 0);
- y = _mm_shuffle_ps(xy, xy, 0x55);
- }
- break;
- }
- x = x+y;
- x = x+z;
- stack_array[index] = x;
- min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
- index++;
- }
-
- // if we found a new min.
- if( 0 == segment || 0xf != _mm_movemask_ps( (float4) _mm_cmpeq_ps(min, dotmin)))
- { // we found a new min. Search for it
- // find min across the min vector, place in all elements of min -- big latency hit here
- min = _mm_min_ps(min, (float4) _mm_shuffle_ps( min, min, 0x4e));
- min = _mm_min_ps(min, (float4) _mm_shuffle_ps( min, min, 0xb1));
-
- // It is slightly faster to do this part in scalar code when count < 8. However, the common case for
- // this where it actually makes a difference is handled in the early out at the top of the function,
- // so it is less than a 1% difference here. I opted for improved code size, fewer branches and reduced
- // complexity, and removed it.
-
- dotmin = min;
-
- // scan for the first occurence of min in the array
- size_t test;
- for( index = 0; 0 == (test=_mm_movemask_ps( _mm_cmpeq_ps( stack_array[index], min))); index++ ) // local_count must be a multiple of 4
- {}
- minIndex = 4*index + segment + indexTable[test];
- }
-
- _mm_store_ss( dotResult, dotmin);
- return minIndex;
-}
+ }
+
+ // process the last few points
+ if (count & 3)
+ {
+ float4 v0, v1, v2, x, y, z;
+ switch (count & 3)
+ {
+ case 3:
+ {
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+
+ // Calculate 3 dot products, transpose, duplicate v2
+ float4 lo0 = _mm_movelh_ps(v0, v1); // xyxy.lo
+ float4 hi0 = _mm_movehl_ps(v1, v0); // z?z?.lo
+ lo0 = lo0 * vLo;
+ z = _mm_shuffle_ps(hi0, v2, 0xa8); // z0z1z2z2
+ z = z * vHi;
+ float4 lo1 = _mm_movelh_ps(v2, v2); // xyxy
+ lo1 = lo1 * vLo;
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ }
+ break;
+ case 2:
+ {
+ v0 = vertices[0];
+ v1 = vertices[1];
+ float4 xy = _mm_movelh_ps(v0, v1);
+ z = _mm_movehl_ps(v1, v0);
+ xy = xy * vLo;
+ z = _mm_shuffle_ps(z, z, 0xa8);
+ x = _mm_shuffle_ps(xy, xy, 0xa8);
+ y = _mm_shuffle_ps(xy, xy, 0xfd);
+ z = z * vHi;
+ }
+ break;
+ case 1:
+ {
+ float4 xy = vertices[0];
+ z = _mm_shuffle_ps(xy, xy, 0xaa);
+ xy = xy * vLo;
+ z = z * vHi;
+ x = _mm_shuffle_ps(xy, xy, 0);
+ y = _mm_shuffle_ps(xy, xy, 0x55);
+ }
+ break;
+ }
+ x = x + y;
+ x = x + z;
+ stack_array[index] = x;
+ min = _mm_min_ps(x, min); // control the order here so that min is never NaN even if x is nan
+ index++;
+ }
+
+ // if we found a new min.
+ if (0 == segment || 0xf != _mm_movemask_ps((float4)_mm_cmpeq_ps(min, dotmin)))
+ { // we found a new min. Search for it
+ // find min across the min vector, place in all elements of min -- big latency hit here
+ min = _mm_min_ps(min, (float4)_mm_shuffle_ps(min, min, 0x4e));
+ min = _mm_min_ps(min, (float4)_mm_shuffle_ps(min, min, 0xb1));
+
+ // It is slightly faster to do this part in scalar code when count < 8. However, the common case for
+ // this where it actually makes a difference is handled in the early out at the top of the function,
+ // so it is less than a 1% difference here. I opted for improved code size, fewer branches and reduced
+ // complexity, and removed it.
+
+ dotmin = min;
+ // scan for the first occurence of min in the array
+ size_t test;
+ for (index = 0; 0 == (test = _mm_movemask_ps(_mm_cmpeq_ps(stack_array[index], min))); index++) // local_count must be a multiple of 4
+ {
+ }
+ minIndex = 4 * index + segment + indexTable[test];
+ }
+
+ _mm_store_ss(dotResult, dotmin);
+ return minIndex;
+}
#elif defined BT_USE_NEON
-#define ARM_NEON_GCC_COMPATIBILITY 1
+#define ARM_NEON_GCC_COMPATIBILITY 1
#include <arm_neon.h>
#include <sys/types.h>
-#include <sys/sysctl.h> //for sysctlbyname
+#include <sys/sysctl.h> //for sysctlbyname
-static long _maxdot_large_v0( const float *vv, const float *vec, unsigned long count, float *dotResult );
-static long _maxdot_large_v1( const float *vv, const float *vec, unsigned long count, float *dotResult );
-static long _maxdot_large_sel( const float *vv, const float *vec, unsigned long count, float *dotResult );
-static long _mindot_large_v0( const float *vv, const float *vec, unsigned long count, float *dotResult );
-static long _mindot_large_v1( const float *vv, const float *vec, unsigned long count, float *dotResult );
-static long _mindot_large_sel( const float *vv, const float *vec, unsigned long count, float *dotResult );
+static long _maxdot_large_v0(const float *vv, const float *vec, unsigned long count, float *dotResult);
+static long _maxdot_large_v1(const float *vv, const float *vec, unsigned long count, float *dotResult);
+static long _maxdot_large_sel(const float *vv, const float *vec, unsigned long count, float *dotResult);
+static long _mindot_large_v0(const float *vv, const float *vec, unsigned long count, float *dotResult);
+static long _mindot_large_v1(const float *vv, const float *vec, unsigned long count, float *dotResult);
+static long _mindot_large_sel(const float *vv, const float *vec, unsigned long count, float *dotResult);
-long (*_maxdot_large)( const float *vv, const float *vec, unsigned long count, float *dotResult ) = _maxdot_large_sel;
-long (*_mindot_large)( const float *vv, const float *vec, unsigned long count, float *dotResult ) = _mindot_large_sel;
+long (*_maxdot_large)(const float *vv, const float *vec, unsigned long count, float *dotResult) = _maxdot_large_sel;
+long (*_mindot_large)(const float *vv, const float *vec, unsigned long count, float *dotResult) = _mindot_large_sel;
-
-static inline uint32_t btGetCpuCapabilities( void )
+static inline uint32_t btGetCpuCapabilities(void)
{
- static uint32_t capabilities = 0;
- static bool testedCapabilities = false;
+ static uint32_t capabilities = 0;
+ static bool testedCapabilities = false;
- if( 0 == testedCapabilities)
- {
- uint32_t hasFeature = 0;
- size_t featureSize = sizeof( hasFeature );
- int err = sysctlbyname( "hw.optional.neon_hpfp", &hasFeature, &featureSize, NULL, 0 );
+ if (0 == testedCapabilities)
+ {
+ uint32_t hasFeature = 0;
+ size_t featureSize = sizeof(hasFeature);
+ int err = sysctlbyname("hw.optional.neon_hpfp", &hasFeature, &featureSize, NULL, 0);
- if( 0 == err && hasFeature)
- capabilities |= 0x2000;
+ if (0 == err && hasFeature)
+ capabilities |= 0x2000;
testedCapabilities = true;
- }
-
- return capabilities;
-}
-
-
+ }
+ return capabilities;
+}
-static long _maxdot_large_sel( const float *vv, const float *vec, unsigned long count, float *dotResult )
+static long _maxdot_large_sel(const float *vv, const float *vec, unsigned long count, float *dotResult)
{
+ if (btGetCpuCapabilities() & 0x2000)
+ _maxdot_large = _maxdot_large_v1;
+ else
+ _maxdot_large = _maxdot_large_v0;
- if( btGetCpuCapabilities() & 0x2000 )
- _maxdot_large = _maxdot_large_v1;
- else
- _maxdot_large = _maxdot_large_v0;
-
- return _maxdot_large(vv, vec, count, dotResult);
+ return _maxdot_large(vv, vec, count, dotResult);
}
-static long _mindot_large_sel( const float *vv, const float *vec, unsigned long count, float *dotResult )
+static long _mindot_large_sel(const float *vv, const float *vec, unsigned long count, float *dotResult)
{
+ if (btGetCpuCapabilities() & 0x2000)
+ _mindot_large = _mindot_large_v1;
+ else
+ _mindot_large = _mindot_large_v0;
- if( btGetCpuCapabilities() & 0x2000 )
- _mindot_large = _mindot_large_v1;
- else
- _mindot_large = _mindot_large_v0;
-
- return _mindot_large(vv, vec, count, dotResult);
+ return _mindot_large(vv, vec, count, dotResult);
}
-
-
#if defined __arm__
-# define vld1q_f32_aligned_postincrement( _ptr ) ({ float32x4_t _r; asm( "vld1.f32 {%0}, [%1, :128]!\n" : "=w" (_r), "+r" (_ptr) ); /*return*/ _r; })
+#define vld1q_f32_aligned_postincrement(_ptr) ({ float32x4_t _r; asm( "vld1.f32 {%0}, [%1, :128]!\n" : "=w" (_r), "+r" (_ptr) ); /*return*/ _r; })
#else
//support 64bit arm
-# define vld1q_f32_aligned_postincrement( _ptr) ({ float32x4_t _r = ((float32x4_t*)(_ptr))[0]; (_ptr) = (const float*) ((const char*)(_ptr) + 16L); /*return*/ _r; })
+#define vld1q_f32_aligned_postincrement(_ptr) ({ float32x4_t _r = ((float32x4_t*)(_ptr))[0]; (_ptr) = (const float*) ((const char*)(_ptr) + 16L); /*return*/ _r; })
#endif
-
-long _maxdot_large_v0( const float *vv, const float *vec, unsigned long count, float *dotResult )
+long _maxdot_large_v0(const float *vv, const float *vec, unsigned long count, float *dotResult)
{
- unsigned long i = 0;
- float32x4_t vvec = vld1q_f32_aligned_postincrement( vec );
- float32x2_t vLo = vget_low_f32(vvec);
- float32x2_t vHi = vdup_lane_f32(vget_high_f32(vvec), 0);
- float32x2_t dotMaxLo = (float32x2_t) { -BT_INFINITY, -BT_INFINITY };
- float32x2_t dotMaxHi = (float32x2_t) { -BT_INFINITY, -BT_INFINITY };
- uint32x2_t indexLo = (uint32x2_t) {0, 1};
- uint32x2_t indexHi = (uint32x2_t) {2, 3};
- uint32x2_t iLo = (uint32x2_t) {static_cast<uint32_t>(-1), static_cast<uint32_t>(-1)};
- uint32x2_t iHi = (uint32x2_t) {static_cast<uint32_t>(-1), static_cast<uint32_t>(-1)};
- const uint32x2_t four = (uint32x2_t) {4,4};
-
- for( ; i+8 <= count; i+= 8 )
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
-
- float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
- float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
- float32x2_t xy2 = vmul_f32( vget_low_f32(v2), vLo);
- float32x2_t xy3 = vmul_f32( vget_low_f32(v3), vLo);
-
- float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
- float32x2x2_t z1 = vtrn_f32( vget_high_f32(v2), vget_high_f32(v3));
- float32x2_t zLo = vmul_f32( z0.val[0], vHi);
- float32x2_t zHi = vmul_f32( z1.val[0], vHi);
-
- float32x2_t rLo = vpadd_f32( xy0, xy1);
- float32x2_t rHi = vpadd_f32( xy2, xy3);
- rLo = vadd_f32(rLo, zLo);
- rHi = vadd_f32(rHi, zHi);
-
- uint32x2_t maskLo = vcgt_f32( rLo, dotMaxLo );
- uint32x2_t maskHi = vcgt_f32( rHi, dotMaxHi );
- dotMaxLo = vbsl_f32( maskLo, rLo, dotMaxLo);
- dotMaxHi = vbsl_f32( maskHi, rHi, dotMaxHi);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- iHi = vbsl_u32(maskHi, indexHi, iHi);
- indexLo = vadd_u32(indexLo, four);
- indexHi = vadd_u32(indexHi, four);
-
- v0 = vld1q_f32_aligned_postincrement( vv );
- v1 = vld1q_f32_aligned_postincrement( vv );
- v2 = vld1q_f32_aligned_postincrement( vv );
- v3 = vld1q_f32_aligned_postincrement( vv );
-
- xy0 = vmul_f32( vget_low_f32(v0), vLo);
- xy1 = vmul_f32( vget_low_f32(v1), vLo);
- xy2 = vmul_f32( vget_low_f32(v2), vLo);
- xy3 = vmul_f32( vget_low_f32(v3), vLo);
-
- z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
- z1 = vtrn_f32( vget_high_f32(v2), vget_high_f32(v3));
- zLo = vmul_f32( z0.val[0], vHi);
- zHi = vmul_f32( z1.val[0], vHi);
-
- rLo = vpadd_f32( xy0, xy1);
- rHi = vpadd_f32( xy2, xy3);
- rLo = vadd_f32(rLo, zLo);
- rHi = vadd_f32(rHi, zHi);
-
- maskLo = vcgt_f32( rLo, dotMaxLo );
- maskHi = vcgt_f32( rHi, dotMaxHi );
- dotMaxLo = vbsl_f32( maskLo, rLo, dotMaxLo);
- dotMaxHi = vbsl_f32( maskHi, rHi, dotMaxHi);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- iHi = vbsl_u32(maskHi, indexHi, iHi);
- indexLo = vadd_u32(indexLo, four);
- indexHi = vadd_u32(indexHi, four);
- }
-
- for( ; i+4 <= count; i+= 4 )
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
-
- float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
- float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
- float32x2_t xy2 = vmul_f32( vget_low_f32(v2), vLo);
- float32x2_t xy3 = vmul_f32( vget_low_f32(v3), vLo);
-
- float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
- float32x2x2_t z1 = vtrn_f32( vget_high_f32(v2), vget_high_f32(v3));
- float32x2_t zLo = vmul_f32( z0.val[0], vHi);
- float32x2_t zHi = vmul_f32( z1.val[0], vHi);
-
- float32x2_t rLo = vpadd_f32( xy0, xy1);
- float32x2_t rHi = vpadd_f32( xy2, xy3);
- rLo = vadd_f32(rLo, zLo);
- rHi = vadd_f32(rHi, zHi);
-
- uint32x2_t maskLo = vcgt_f32( rLo, dotMaxLo );
- uint32x2_t maskHi = vcgt_f32( rHi, dotMaxHi );
- dotMaxLo = vbsl_f32( maskLo, rLo, dotMaxLo);
- dotMaxHi = vbsl_f32( maskHi, rHi, dotMaxHi);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- iHi = vbsl_u32(maskHi, indexHi, iHi);
- indexLo = vadd_u32(indexLo, four);
- indexHi = vadd_u32(indexHi, four);
- }
-
- switch( count & 3 )
- {
- case 3:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
-
- float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
- float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
- float32x2_t xy2 = vmul_f32( vget_low_f32(v2), vLo);
-
- float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
- float32x2_t zLo = vmul_f32( z0.val[0], vHi);
- float32x2_t zHi = vmul_f32( vdup_lane_f32(vget_high_f32(v2), 0), vHi);
-
- float32x2_t rLo = vpadd_f32( xy0, xy1);
- float32x2_t rHi = vpadd_f32( xy2, xy2);
- rLo = vadd_f32(rLo, zLo);
- rHi = vadd_f32(rHi, zHi);
-
- uint32x2_t maskLo = vcgt_f32( rLo, dotMaxLo );
- uint32x2_t maskHi = vcgt_f32( rHi, dotMaxHi );
- dotMaxLo = vbsl_f32( maskLo, rLo, dotMaxLo);
- dotMaxHi = vbsl_f32( maskHi, rHi, dotMaxHi);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- iHi = vbsl_u32(maskHi, indexHi, iHi);
- }
- break;
- case 2:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
-
- float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
- float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
-
- float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
- float32x2_t zLo = vmul_f32( z0.val[0], vHi);
-
- float32x2_t rLo = vpadd_f32( xy0, xy1);
- rLo = vadd_f32(rLo, zLo);
-
- uint32x2_t maskLo = vcgt_f32( rLo, dotMaxLo );
- dotMaxLo = vbsl_f32( maskLo, rLo, dotMaxLo);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- }
- break;
- case 1:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
- float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
- float32x2_t z0 = vdup_lane_f32(vget_high_f32(v0), 0);
- float32x2_t zLo = vmul_f32( z0, vHi);
- float32x2_t rLo = vpadd_f32( xy0, xy0);
- rLo = vadd_f32(rLo, zLo);
- uint32x2_t maskLo = vcgt_f32( rLo, dotMaxLo );
- dotMaxLo = vbsl_f32( maskLo, rLo, dotMaxLo);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- }
- break;
-
- default:
- break;
- }
-
- // select best answer between hi and lo results
- uint32x2_t mask = vcgt_f32( dotMaxHi, dotMaxLo );
- dotMaxLo = vbsl_f32(mask, dotMaxHi, dotMaxLo);
- iLo = vbsl_u32(mask, iHi, iLo);
-
- // select best answer between even and odd results
- dotMaxHi = vdup_lane_f32(dotMaxLo, 1);
- iHi = vdup_lane_u32(iLo, 1);
- mask = vcgt_f32( dotMaxHi, dotMaxLo );
- dotMaxLo = vbsl_f32(mask, dotMaxHi, dotMaxLo);
- iLo = vbsl_u32(mask, iHi, iLo);
-
- *dotResult = vget_lane_f32( dotMaxLo, 0);
- return vget_lane_u32(iLo, 0);
-}
+ unsigned long i = 0;
+ float32x4_t vvec = vld1q_f32_aligned_postincrement(vec);
+ float32x2_t vLo = vget_low_f32(vvec);
+ float32x2_t vHi = vdup_lane_f32(vget_high_f32(vvec), 0);
+ float32x2_t dotMaxLo = (float32x2_t){-BT_INFINITY, -BT_INFINITY};
+ float32x2_t dotMaxHi = (float32x2_t){-BT_INFINITY, -BT_INFINITY};
+ uint32x2_t indexLo = (uint32x2_t){0, 1};
+ uint32x2_t indexHi = (uint32x2_t){2, 3};
+ uint32x2_t iLo = (uint32x2_t){static_cast<uint32_t>(-1), static_cast<uint32_t>(-1)};
+ uint32x2_t iHi = (uint32x2_t){static_cast<uint32_t>(-1), static_cast<uint32_t>(-1)};
+ const uint32x2_t four = (uint32x2_t){4, 4};
+
+ for (; i + 8 <= count; i += 8)
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
+
+ float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
+ float32x2_t xy2 = vmul_f32(vget_low_f32(v2), vLo);
+ float32x2_t xy3 = vmul_f32(vget_low_f32(v3), vLo);
+
+ float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+ float32x2x2_t z1 = vtrn_f32(vget_high_f32(v2), vget_high_f32(v3));
+ float32x2_t zLo = vmul_f32(z0.val[0], vHi);
+ float32x2_t zHi = vmul_f32(z1.val[0], vHi);
+
+ float32x2_t rLo = vpadd_f32(xy0, xy1);
+ float32x2_t rHi = vpadd_f32(xy2, xy3);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ uint32x2_t maskLo = vcgt_f32(rLo, dotMaxLo);
+ uint32x2_t maskHi = vcgt_f32(rHi, dotMaxHi);
+ dotMaxLo = vbsl_f32(maskLo, rLo, dotMaxLo);
+ dotMaxHi = vbsl_f32(maskHi, rHi, dotMaxHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ indexLo = vadd_u32(indexLo, four);
+ indexHi = vadd_u32(indexHi, four);
+
+ v0 = vld1q_f32_aligned_postincrement(vv);
+ v1 = vld1q_f32_aligned_postincrement(vv);
+ v2 = vld1q_f32_aligned_postincrement(vv);
+ v3 = vld1q_f32_aligned_postincrement(vv);
+
+ xy0 = vmul_f32(vget_low_f32(v0), vLo);
+ xy1 = vmul_f32(vget_low_f32(v1), vLo);
+ xy2 = vmul_f32(vget_low_f32(v2), vLo);
+ xy3 = vmul_f32(vget_low_f32(v3), vLo);
+
+ z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+ z1 = vtrn_f32(vget_high_f32(v2), vget_high_f32(v3));
+ zLo = vmul_f32(z0.val[0], vHi);
+ zHi = vmul_f32(z1.val[0], vHi);
+
+ rLo = vpadd_f32(xy0, xy1);
+ rHi = vpadd_f32(xy2, xy3);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ maskLo = vcgt_f32(rLo, dotMaxLo);
+ maskHi = vcgt_f32(rHi, dotMaxHi);
+ dotMaxLo = vbsl_f32(maskLo, rLo, dotMaxLo);
+ dotMaxHi = vbsl_f32(maskHi, rHi, dotMaxHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ indexLo = vadd_u32(indexLo, four);
+ indexHi = vadd_u32(indexHi, four);
+ }
+ for (; i + 4 <= count; i += 4)
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
-long _maxdot_large_v1( const float *vv, const float *vec, unsigned long count, float *dotResult )
+ float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
+ float32x2_t xy2 = vmul_f32(vget_low_f32(v2), vLo);
+ float32x2_t xy3 = vmul_f32(vget_low_f32(v3), vLo);
+
+ float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+ float32x2x2_t z1 = vtrn_f32(vget_high_f32(v2), vget_high_f32(v3));
+ float32x2_t zLo = vmul_f32(z0.val[0], vHi);
+ float32x2_t zHi = vmul_f32(z1.val[0], vHi);
+
+ float32x2_t rLo = vpadd_f32(xy0, xy1);
+ float32x2_t rHi = vpadd_f32(xy2, xy3);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ uint32x2_t maskLo = vcgt_f32(rLo, dotMaxLo);
+ uint32x2_t maskHi = vcgt_f32(rHi, dotMaxHi);
+ dotMaxLo = vbsl_f32(maskLo, rLo, dotMaxLo);
+ dotMaxHi = vbsl_f32(maskHi, rHi, dotMaxHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ indexLo = vadd_u32(indexLo, four);
+ indexHi = vadd_u32(indexHi, four);
+ }
+
+ switch (count & 3)
+ {
+ case 3:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+
+ float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
+ float32x2_t xy2 = vmul_f32(vget_low_f32(v2), vLo);
+
+ float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+ float32x2_t zLo = vmul_f32(z0.val[0], vHi);
+ float32x2_t zHi = vmul_f32(vdup_lane_f32(vget_high_f32(v2), 0), vHi);
+
+ float32x2_t rLo = vpadd_f32(xy0, xy1);
+ float32x2_t rHi = vpadd_f32(xy2, xy2);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ uint32x2_t maskLo = vcgt_f32(rLo, dotMaxLo);
+ uint32x2_t maskHi = vcgt_f32(rHi, dotMaxHi);
+ dotMaxLo = vbsl_f32(maskLo, rLo, dotMaxLo);
+ dotMaxHi = vbsl_f32(maskHi, rHi, dotMaxHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ }
+ break;
+ case 2:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+
+ float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
+
+ float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+ float32x2_t zLo = vmul_f32(z0.val[0], vHi);
+
+ float32x2_t rLo = vpadd_f32(xy0, xy1);
+ rLo = vadd_f32(rLo, zLo);
+
+ uint32x2_t maskLo = vcgt_f32(rLo, dotMaxLo);
+ dotMaxLo = vbsl_f32(maskLo, rLo, dotMaxLo);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ }
+ break;
+ case 1:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+ float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+ float32x2_t z0 = vdup_lane_f32(vget_high_f32(v0), 0);
+ float32x2_t zLo = vmul_f32(z0, vHi);
+ float32x2_t rLo = vpadd_f32(xy0, xy0);
+ rLo = vadd_f32(rLo, zLo);
+ uint32x2_t maskLo = vcgt_f32(rLo, dotMaxLo);
+ dotMaxLo = vbsl_f32(maskLo, rLo, dotMaxLo);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ // select best answer between hi and lo results
+ uint32x2_t mask = vcgt_f32(dotMaxHi, dotMaxLo);
+ dotMaxLo = vbsl_f32(mask, dotMaxHi, dotMaxLo);
+ iLo = vbsl_u32(mask, iHi, iLo);
+
+ // select best answer between even and odd results
+ dotMaxHi = vdup_lane_f32(dotMaxLo, 1);
+ iHi = vdup_lane_u32(iLo, 1);
+ mask = vcgt_f32(dotMaxHi, dotMaxLo);
+ dotMaxLo = vbsl_f32(mask, dotMaxHi, dotMaxLo);
+ iLo = vbsl_u32(mask, iHi, iLo);
+
+ *dotResult = vget_lane_f32(dotMaxLo, 0);
+ return vget_lane_u32(iLo, 0);
+}
+
+long _maxdot_large_v1(const float *vv, const float *vec, unsigned long count, float *dotResult)
{
- float32x4_t vvec = vld1q_f32_aligned_postincrement( vec );
- float32x4_t vLo = vcombine_f32(vget_low_f32(vvec), vget_low_f32(vvec));
- float32x4_t vHi = vdupq_lane_f32(vget_high_f32(vvec), 0);
- const uint32x4_t four = (uint32x4_t){ 4, 4, 4, 4 };
- uint32x4_t local_index = (uint32x4_t) {0, 1, 2, 3};
- uint32x4_t index = (uint32x4_t) { static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), static_cast<uint32_t>(-1) };
- float32x4_t maxDot = (float32x4_t) { -BT_INFINITY, -BT_INFINITY, -BT_INFINITY, -BT_INFINITY };
-
- unsigned long i = 0;
- for( ; i + 8 <= count; i += 8 )
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
- float32x4_t xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v3));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
- float32x4_t z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v3));
-
- xy0 = vmulq_f32(xy0, vLo);
- xy1 = vmulq_f32(xy1, vLo);
-
- float32x4x2_t zb = vuzpq_f32( z0, z1);
- float32x4_t z = vmulq_f32( zb.val[0], vHi);
- float32x4x2_t xy = vuzpq_f32( xy0, xy1);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcgtq_f32(x, maxDot);
- maxDot = vbslq_f32( mask, x, maxDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
-
- v0 = vld1q_f32_aligned_postincrement( vv );
- v1 = vld1q_f32_aligned_postincrement( vv );
- v2 = vld1q_f32_aligned_postincrement( vv );
- v3 = vld1q_f32_aligned_postincrement( vv );
-
- // the next two lines should resolve to a single vswp d, d
- xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
- xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v3));
- // the next two lines should resolve to a single vswp d, d
- z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
- z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v3));
-
- xy0 = vmulq_f32(xy0, vLo);
- xy1 = vmulq_f32(xy1, vLo);
-
- zb = vuzpq_f32( z0, z1);
- z = vmulq_f32( zb.val[0], vHi);
- xy = vuzpq_f32( xy0, xy1);
- x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- mask = vcgtq_f32(x, maxDot);
- maxDot = vbslq_f32( mask, x, maxDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
-
- for( ; i + 4 <= count; i += 4 )
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
- float32x4_t xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v3));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
- float32x4_t z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v3));
-
- xy0 = vmulq_f32(xy0, vLo);
- xy1 = vmulq_f32(xy1, vLo);
-
- float32x4x2_t zb = vuzpq_f32( z0, z1);
- float32x4_t z = vmulq_f32( zb.val[0], vHi);
- float32x4x2_t xy = vuzpq_f32( xy0, xy1);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcgtq_f32(x, maxDot);
- maxDot = vbslq_f32( mask, x, maxDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
-
- switch (count & 3) {
- case 3:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
- float32x4_t xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v2));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
- float32x4_t z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v2));
-
- xy0 = vmulq_f32(xy0, vLo);
- xy1 = vmulq_f32(xy1, vLo);
-
- float32x4x2_t zb = vuzpq_f32( z0, z1);
- float32x4_t z = vmulq_f32( zb.val[0], vHi);
- float32x4x2_t xy = vuzpq_f32( xy0, xy1);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcgtq_f32(x, maxDot);
- maxDot = vbslq_f32( mask, x, maxDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
- break;
-
- case 2:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
-
- xy0 = vmulq_f32(xy0, vLo);
-
- float32x4x2_t zb = vuzpq_f32( z0, z0);
- float32x4_t z = vmulq_f32( zb.val[0], vHi);
- float32x4x2_t xy = vuzpq_f32( xy0, xy0);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcgtq_f32(x, maxDot);
- maxDot = vbslq_f32( mask, x, maxDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
- break;
-
- case 1:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v0));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z = vdupq_lane_f32(vget_high_f32(v0), 0);
-
- xy0 = vmulq_f32(xy0, vLo);
-
- z = vmulq_f32( z, vHi);
- float32x4x2_t xy = vuzpq_f32( xy0, xy0);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcgtq_f32(x, maxDot);
- maxDot = vbslq_f32( mask, x, maxDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
- break;
-
- default:
- break;
- }
-
-
- // select best answer between hi and lo results
- uint32x2_t mask = vcgt_f32( vget_high_f32(maxDot), vget_low_f32(maxDot));
- float32x2_t maxDot2 = vbsl_f32(mask, vget_high_f32(maxDot), vget_low_f32(maxDot));
- uint32x2_t index2 = vbsl_u32(mask, vget_high_u32(index), vget_low_u32(index));
-
- // select best answer between even and odd results
- float32x2_t maxDotO = vdup_lane_f32(maxDot2, 1);
- uint32x2_t indexHi = vdup_lane_u32(index2, 1);
- mask = vcgt_f32( maxDotO, maxDot2 );
- maxDot2 = vbsl_f32(mask, maxDotO, maxDot2);
- index2 = vbsl_u32(mask, indexHi, index2);
-
- *dotResult = vget_lane_f32( maxDot2, 0);
- return vget_lane_u32(index2, 0);
-
+ float32x4_t vvec = vld1q_f32_aligned_postincrement(vec);
+ float32x4_t vLo = vcombine_f32(vget_low_f32(vvec), vget_low_f32(vvec));
+ float32x4_t vHi = vdupq_lane_f32(vget_high_f32(vvec), 0);
+ const uint32x4_t four = (uint32x4_t){4, 4, 4, 4};
+ uint32x4_t local_index = (uint32x4_t){0, 1, 2, 3};
+ uint32x4_t index = (uint32x4_t){static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), static_cast<uint32_t>(-1)};
+ float32x4_t maxDot = (float32x4_t){-BT_INFINITY, -BT_INFINITY, -BT_INFINITY, -BT_INFINITY};
+
+ unsigned long i = 0;
+ for (; i + 8 <= count; i += 8)
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+ float32x4_t xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v3));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+ float32x4_t z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v3));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ float32x4x2_t zb = vuzpq_f32(z0, z1);
+ float32x4_t z = vmulq_f32(zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32(xy0, xy1);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcgtq_f32(x, maxDot);
+ maxDot = vbslq_f32(mask, x, maxDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+
+ v0 = vld1q_f32_aligned_postincrement(vv);
+ v1 = vld1q_f32_aligned_postincrement(vv);
+ v2 = vld1q_f32_aligned_postincrement(vv);
+ v3 = vld1q_f32_aligned_postincrement(vv);
+
+ // the next two lines should resolve to a single vswp d, d
+ xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+ xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v3));
+ // the next two lines should resolve to a single vswp d, d
+ z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+ z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v3));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ zb = vuzpq_f32(z0, z1);
+ z = vmulq_f32(zb.val[0], vHi);
+ xy = vuzpq_f32(xy0, xy1);
+ x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ mask = vcgtq_f32(x, maxDot);
+ maxDot = vbslq_f32(mask, x, maxDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+
+ for (; i + 4 <= count; i += 4)
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+ float32x4_t xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v3));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+ float32x4_t z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v3));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ float32x4x2_t zb = vuzpq_f32(z0, z1);
+ float32x4_t z = vmulq_f32(zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32(xy0, xy1);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcgtq_f32(x, maxDot);
+ maxDot = vbslq_f32(mask, x, maxDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+
+ switch (count & 3)
+ {
+ case 3:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+ float32x4_t xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v2));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+ float32x4_t z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v2));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ float32x4x2_t zb = vuzpq_f32(z0, z1);
+ float32x4_t z = vmulq_f32(zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32(xy0, xy1);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcgtq_f32(x, maxDot);
+ maxDot = vbslq_f32(mask, x, maxDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+ break;
+
+ case 2:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+
+ xy0 = vmulq_f32(xy0, vLo);
+
+ float32x4x2_t zb = vuzpq_f32(z0, z0);
+ float32x4_t z = vmulq_f32(zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32(xy0, xy0);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcgtq_f32(x, maxDot);
+ maxDot = vbslq_f32(mask, x, maxDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+ break;
+
+ case 1:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v0));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z = vdupq_lane_f32(vget_high_f32(v0), 0);
+
+ xy0 = vmulq_f32(xy0, vLo);
+
+ z = vmulq_f32(z, vHi);
+ float32x4x2_t xy = vuzpq_f32(xy0, xy0);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcgtq_f32(x, maxDot);
+ maxDot = vbslq_f32(mask, x, maxDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ // select best answer between hi and lo results
+ uint32x2_t mask = vcgt_f32(vget_high_f32(maxDot), vget_low_f32(maxDot));
+ float32x2_t maxDot2 = vbsl_f32(mask, vget_high_f32(maxDot), vget_low_f32(maxDot));
+ uint32x2_t index2 = vbsl_u32(mask, vget_high_u32(index), vget_low_u32(index));
+
+ // select best answer between even and odd results
+ float32x2_t maxDotO = vdup_lane_f32(maxDot2, 1);
+ uint32x2_t indexHi = vdup_lane_u32(index2, 1);
+ mask = vcgt_f32(maxDotO, maxDot2);
+ maxDot2 = vbsl_f32(mask, maxDotO, maxDot2);
+ index2 = vbsl_u32(mask, indexHi, index2);
+
+ *dotResult = vget_lane_f32(maxDot2, 0);
+ return vget_lane_u32(index2, 0);
}
-long _mindot_large_v0( const float *vv, const float *vec, unsigned long count, float *dotResult )
+long _mindot_large_v0(const float *vv, const float *vec, unsigned long count, float *dotResult)
{
- unsigned long i = 0;
- float32x4_t vvec = vld1q_f32_aligned_postincrement( vec );
- float32x2_t vLo = vget_low_f32(vvec);
- float32x2_t vHi = vdup_lane_f32(vget_high_f32(vvec), 0);
- float32x2_t dotMinLo = (float32x2_t) { BT_INFINITY, BT_INFINITY };
- float32x2_t dotMinHi = (float32x2_t) { BT_INFINITY, BT_INFINITY };
- uint32x2_t indexLo = (uint32x2_t) {0, 1};
- uint32x2_t indexHi = (uint32x2_t) {2, 3};
- uint32x2_t iLo = (uint32x2_t) {static_cast<uint32_t>(-1), static_cast<uint32_t>(-1)};
- uint32x2_t iHi = (uint32x2_t) {static_cast<uint32_t>(-1), static_cast<uint32_t>(-1)};
- const uint32x2_t four = (uint32x2_t) {4,4};
-
- for( ; i+8 <= count; i+= 8 )
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
-
- float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
- float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
- float32x2_t xy2 = vmul_f32( vget_low_f32(v2), vLo);
- float32x2_t xy3 = vmul_f32( vget_low_f32(v3), vLo);
-
- float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
- float32x2x2_t z1 = vtrn_f32( vget_high_f32(v2), vget_high_f32(v3));
- float32x2_t zLo = vmul_f32( z0.val[0], vHi);
- float32x2_t zHi = vmul_f32( z1.val[0], vHi);
-
- float32x2_t rLo = vpadd_f32( xy0, xy1);
- float32x2_t rHi = vpadd_f32( xy2, xy3);
- rLo = vadd_f32(rLo, zLo);
- rHi = vadd_f32(rHi, zHi);
-
- uint32x2_t maskLo = vclt_f32( rLo, dotMinLo );
- uint32x2_t maskHi = vclt_f32( rHi, dotMinHi );
- dotMinLo = vbsl_f32( maskLo, rLo, dotMinLo);
- dotMinHi = vbsl_f32( maskHi, rHi, dotMinHi);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- iHi = vbsl_u32(maskHi, indexHi, iHi);
- indexLo = vadd_u32(indexLo, four);
- indexHi = vadd_u32(indexHi, four);
-
- v0 = vld1q_f32_aligned_postincrement( vv );
- v1 = vld1q_f32_aligned_postincrement( vv );
- v2 = vld1q_f32_aligned_postincrement( vv );
- v3 = vld1q_f32_aligned_postincrement( vv );
-
- xy0 = vmul_f32( vget_low_f32(v0), vLo);
- xy1 = vmul_f32( vget_low_f32(v1), vLo);
- xy2 = vmul_f32( vget_low_f32(v2), vLo);
- xy3 = vmul_f32( vget_low_f32(v3), vLo);
-
- z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
- z1 = vtrn_f32( vget_high_f32(v2), vget_high_f32(v3));
- zLo = vmul_f32( z0.val[0], vHi);
- zHi = vmul_f32( z1.val[0], vHi);
-
- rLo = vpadd_f32( xy0, xy1);
- rHi = vpadd_f32( xy2, xy3);
- rLo = vadd_f32(rLo, zLo);
- rHi = vadd_f32(rHi, zHi);
-
- maskLo = vclt_f32( rLo, dotMinLo );
- maskHi = vclt_f32( rHi, dotMinHi );
- dotMinLo = vbsl_f32( maskLo, rLo, dotMinLo);
- dotMinHi = vbsl_f32( maskHi, rHi, dotMinHi);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- iHi = vbsl_u32(maskHi, indexHi, iHi);
- indexLo = vadd_u32(indexLo, four);
- indexHi = vadd_u32(indexHi, four);
- }
-
- for( ; i+4 <= count; i+= 4 )
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
-
- float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
- float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
- float32x2_t xy2 = vmul_f32( vget_low_f32(v2), vLo);
- float32x2_t xy3 = vmul_f32( vget_low_f32(v3), vLo);
-
- float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
- float32x2x2_t z1 = vtrn_f32( vget_high_f32(v2), vget_high_f32(v3));
- float32x2_t zLo = vmul_f32( z0.val[0], vHi);
- float32x2_t zHi = vmul_f32( z1.val[0], vHi);
-
- float32x2_t rLo = vpadd_f32( xy0, xy1);
- float32x2_t rHi = vpadd_f32( xy2, xy3);
- rLo = vadd_f32(rLo, zLo);
- rHi = vadd_f32(rHi, zHi);
-
- uint32x2_t maskLo = vclt_f32( rLo, dotMinLo );
- uint32x2_t maskHi = vclt_f32( rHi, dotMinHi );
- dotMinLo = vbsl_f32( maskLo, rLo, dotMinLo);
- dotMinHi = vbsl_f32( maskHi, rHi, dotMinHi);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- iHi = vbsl_u32(maskHi, indexHi, iHi);
- indexLo = vadd_u32(indexLo, four);
- indexHi = vadd_u32(indexHi, four);
- }
- switch( count & 3 )
- {
- case 3:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
-
- float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
- float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
- float32x2_t xy2 = vmul_f32( vget_low_f32(v2), vLo);
-
- float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
- float32x2_t zLo = vmul_f32( z0.val[0], vHi);
- float32x2_t zHi = vmul_f32( vdup_lane_f32(vget_high_f32(v2), 0), vHi);
-
- float32x2_t rLo = vpadd_f32( xy0, xy1);
- float32x2_t rHi = vpadd_f32( xy2, xy2);
- rLo = vadd_f32(rLo, zLo);
- rHi = vadd_f32(rHi, zHi);
-
- uint32x2_t maskLo = vclt_f32( rLo, dotMinLo );
- uint32x2_t maskHi = vclt_f32( rHi, dotMinHi );
- dotMinLo = vbsl_f32( maskLo, rLo, dotMinLo);
- dotMinHi = vbsl_f32( maskHi, rHi, dotMinHi);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- iHi = vbsl_u32(maskHi, indexHi, iHi);
- }
- break;
- case 2:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
-
- float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
- float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
-
- float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
- float32x2_t zLo = vmul_f32( z0.val[0], vHi);
-
- float32x2_t rLo = vpadd_f32( xy0, xy1);
- rLo = vadd_f32(rLo, zLo);
-
- uint32x2_t maskLo = vclt_f32( rLo, dotMinLo );
- dotMinLo = vbsl_f32( maskLo, rLo, dotMinLo);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- }
- break;
- case 1:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
- float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
- float32x2_t z0 = vdup_lane_f32(vget_high_f32(v0), 0);
- float32x2_t zLo = vmul_f32( z0, vHi);
- float32x2_t rLo = vpadd_f32( xy0, xy0);
- rLo = vadd_f32(rLo, zLo);
- uint32x2_t maskLo = vclt_f32( rLo, dotMinLo );
- dotMinLo = vbsl_f32( maskLo, rLo, dotMinLo);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- }
- break;
-
- default:
- break;
- }
-
- // select best answer between hi and lo results
- uint32x2_t mask = vclt_f32( dotMinHi, dotMinLo );
- dotMinLo = vbsl_f32(mask, dotMinHi, dotMinLo);
- iLo = vbsl_u32(mask, iHi, iLo);
-
- // select best answer between even and odd results
- dotMinHi = vdup_lane_f32(dotMinLo, 1);
- iHi = vdup_lane_u32(iLo, 1);
- mask = vclt_f32( dotMinHi, dotMinLo );
- dotMinLo = vbsl_f32(mask, dotMinHi, dotMinLo);
- iLo = vbsl_u32(mask, iHi, iLo);
-
- *dotResult = vget_lane_f32( dotMinLo, 0);
- return vget_lane_u32(iLo, 0);
+ unsigned long i = 0;
+ float32x4_t vvec = vld1q_f32_aligned_postincrement(vec);
+ float32x2_t vLo = vget_low_f32(vvec);
+ float32x2_t vHi = vdup_lane_f32(vget_high_f32(vvec), 0);
+ float32x2_t dotMinLo = (float32x2_t){BT_INFINITY, BT_INFINITY};
+ float32x2_t dotMinHi = (float32x2_t){BT_INFINITY, BT_INFINITY};
+ uint32x2_t indexLo = (uint32x2_t){0, 1};
+ uint32x2_t indexHi = (uint32x2_t){2, 3};
+ uint32x2_t iLo = (uint32x2_t){static_cast<uint32_t>(-1), static_cast<uint32_t>(-1)};
+ uint32x2_t iHi = (uint32x2_t){static_cast<uint32_t>(-1), static_cast<uint32_t>(-1)};
+ const uint32x2_t four = (uint32x2_t){4, 4};
+
+ for (; i + 8 <= count; i += 8)
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
+
+ float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
+ float32x2_t xy2 = vmul_f32(vget_low_f32(v2), vLo);
+ float32x2_t xy3 = vmul_f32(vget_low_f32(v3), vLo);
+
+ float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+ float32x2x2_t z1 = vtrn_f32(vget_high_f32(v2), vget_high_f32(v3));
+ float32x2_t zLo = vmul_f32(z0.val[0], vHi);
+ float32x2_t zHi = vmul_f32(z1.val[0], vHi);
+
+ float32x2_t rLo = vpadd_f32(xy0, xy1);
+ float32x2_t rHi = vpadd_f32(xy2, xy3);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ uint32x2_t maskLo = vclt_f32(rLo, dotMinLo);
+ uint32x2_t maskHi = vclt_f32(rHi, dotMinHi);
+ dotMinLo = vbsl_f32(maskLo, rLo, dotMinLo);
+ dotMinHi = vbsl_f32(maskHi, rHi, dotMinHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ indexLo = vadd_u32(indexLo, four);
+ indexHi = vadd_u32(indexHi, four);
+
+ v0 = vld1q_f32_aligned_postincrement(vv);
+ v1 = vld1q_f32_aligned_postincrement(vv);
+ v2 = vld1q_f32_aligned_postincrement(vv);
+ v3 = vld1q_f32_aligned_postincrement(vv);
+
+ xy0 = vmul_f32(vget_low_f32(v0), vLo);
+ xy1 = vmul_f32(vget_low_f32(v1), vLo);
+ xy2 = vmul_f32(vget_low_f32(v2), vLo);
+ xy3 = vmul_f32(vget_low_f32(v3), vLo);
+
+ z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+ z1 = vtrn_f32(vget_high_f32(v2), vget_high_f32(v3));
+ zLo = vmul_f32(z0.val[0], vHi);
+ zHi = vmul_f32(z1.val[0], vHi);
+
+ rLo = vpadd_f32(xy0, xy1);
+ rHi = vpadd_f32(xy2, xy3);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ maskLo = vclt_f32(rLo, dotMinLo);
+ maskHi = vclt_f32(rHi, dotMinHi);
+ dotMinLo = vbsl_f32(maskLo, rLo, dotMinLo);
+ dotMinHi = vbsl_f32(maskHi, rHi, dotMinHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ indexLo = vadd_u32(indexLo, four);
+ indexHi = vadd_u32(indexHi, four);
+ }
+
+ for (; i + 4 <= count; i += 4)
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
+
+ float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
+ float32x2_t xy2 = vmul_f32(vget_low_f32(v2), vLo);
+ float32x2_t xy3 = vmul_f32(vget_low_f32(v3), vLo);
+
+ float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+ float32x2x2_t z1 = vtrn_f32(vget_high_f32(v2), vget_high_f32(v3));
+ float32x2_t zLo = vmul_f32(z0.val[0], vHi);
+ float32x2_t zHi = vmul_f32(z1.val[0], vHi);
+
+ float32x2_t rLo = vpadd_f32(xy0, xy1);
+ float32x2_t rHi = vpadd_f32(xy2, xy3);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ uint32x2_t maskLo = vclt_f32(rLo, dotMinLo);
+ uint32x2_t maskHi = vclt_f32(rHi, dotMinHi);
+ dotMinLo = vbsl_f32(maskLo, rLo, dotMinLo);
+ dotMinHi = vbsl_f32(maskHi, rHi, dotMinHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ indexLo = vadd_u32(indexLo, four);
+ indexHi = vadd_u32(indexHi, four);
+ }
+ switch (count & 3)
+ {
+ case 3:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+
+ float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
+ float32x2_t xy2 = vmul_f32(vget_low_f32(v2), vLo);
+
+ float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+ float32x2_t zLo = vmul_f32(z0.val[0], vHi);
+ float32x2_t zHi = vmul_f32(vdup_lane_f32(vget_high_f32(v2), 0), vHi);
+
+ float32x2_t rLo = vpadd_f32(xy0, xy1);
+ float32x2_t rHi = vpadd_f32(xy2, xy2);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ uint32x2_t maskLo = vclt_f32(rLo, dotMinLo);
+ uint32x2_t maskHi = vclt_f32(rHi, dotMinHi);
+ dotMinLo = vbsl_f32(maskLo, rLo, dotMinLo);
+ dotMinHi = vbsl_f32(maskHi, rHi, dotMinHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ }
+ break;
+ case 2:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+
+ float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
+
+ float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+ float32x2_t zLo = vmul_f32(z0.val[0], vHi);
+
+ float32x2_t rLo = vpadd_f32(xy0, xy1);
+ rLo = vadd_f32(rLo, zLo);
+
+ uint32x2_t maskLo = vclt_f32(rLo, dotMinLo);
+ dotMinLo = vbsl_f32(maskLo, rLo, dotMinLo);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ }
+ break;
+ case 1:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+ float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+ float32x2_t z0 = vdup_lane_f32(vget_high_f32(v0), 0);
+ float32x2_t zLo = vmul_f32(z0, vHi);
+ float32x2_t rLo = vpadd_f32(xy0, xy0);
+ rLo = vadd_f32(rLo, zLo);
+ uint32x2_t maskLo = vclt_f32(rLo, dotMinLo);
+ dotMinLo = vbsl_f32(maskLo, rLo, dotMinLo);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ // select best answer between hi and lo results
+ uint32x2_t mask = vclt_f32(dotMinHi, dotMinLo);
+ dotMinLo = vbsl_f32(mask, dotMinHi, dotMinLo);
+ iLo = vbsl_u32(mask, iHi, iLo);
+
+ // select best answer between even and odd results
+ dotMinHi = vdup_lane_f32(dotMinLo, 1);
+ iHi = vdup_lane_u32(iLo, 1);
+ mask = vclt_f32(dotMinHi, dotMinLo);
+ dotMinLo = vbsl_f32(mask, dotMinHi, dotMinLo);
+ iLo = vbsl_u32(mask, iHi, iLo);
+
+ *dotResult = vget_lane_f32(dotMinLo, 0);
+ return vget_lane_u32(iLo, 0);
}
-long _mindot_large_v1( const float *vv, const float *vec, unsigned long count, float *dotResult )
+long _mindot_large_v1(const float *vv, const float *vec, unsigned long count, float *dotResult)
{
- float32x4_t vvec = vld1q_f32_aligned_postincrement( vec );
- float32x4_t vLo = vcombine_f32(vget_low_f32(vvec), vget_low_f32(vvec));
- float32x4_t vHi = vdupq_lane_f32(vget_high_f32(vvec), 0);
- const uint32x4_t four = (uint32x4_t){ 4, 4, 4, 4 };
- uint32x4_t local_index = (uint32x4_t) {0, 1, 2, 3};
- uint32x4_t index = (uint32x4_t) { static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), static_cast<uint32_t>(-1) };
- float32x4_t minDot = (float32x4_t) { BT_INFINITY, BT_INFINITY, BT_INFINITY, BT_INFINITY };
-
- unsigned long i = 0;
- for( ; i + 8 <= count; i += 8 )
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
- float32x4_t xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v3));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
- float32x4_t z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v3));
-
- xy0 = vmulq_f32(xy0, vLo);
- xy1 = vmulq_f32(xy1, vLo);
-
- float32x4x2_t zb = vuzpq_f32( z0, z1);
- float32x4_t z = vmulq_f32( zb.val[0], vHi);
- float32x4x2_t xy = vuzpq_f32( xy0, xy1);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcltq_f32(x, minDot);
- minDot = vbslq_f32( mask, x, minDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
-
- v0 = vld1q_f32_aligned_postincrement( vv );
- v1 = vld1q_f32_aligned_postincrement( vv );
- v2 = vld1q_f32_aligned_postincrement( vv );
- v3 = vld1q_f32_aligned_postincrement( vv );
-
- // the next two lines should resolve to a single vswp d, d
- xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
- xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v3));
- // the next two lines should resolve to a single vswp d, d
- z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
- z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v3));
-
- xy0 = vmulq_f32(xy0, vLo);
- xy1 = vmulq_f32(xy1, vLo);
-
- zb = vuzpq_f32( z0, z1);
- z = vmulq_f32( zb.val[0], vHi);
- xy = vuzpq_f32( xy0, xy1);
- x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- mask = vcltq_f32(x, minDot);
- minDot = vbslq_f32( mask, x, minDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
-
- for( ; i + 4 <= count; i += 4 )
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
- float32x4_t xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v3));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
- float32x4_t z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v3));
-
- xy0 = vmulq_f32(xy0, vLo);
- xy1 = vmulq_f32(xy1, vLo);
-
- float32x4x2_t zb = vuzpq_f32( z0, z1);
- float32x4_t z = vmulq_f32( zb.val[0], vHi);
- float32x4x2_t xy = vuzpq_f32( xy0, xy1);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcltq_f32(x, minDot);
- minDot = vbslq_f32( mask, x, minDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
-
- switch (count & 3) {
- case 3:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
- float32x4_t xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v2));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
- float32x4_t z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v2));
-
- xy0 = vmulq_f32(xy0, vLo);
- xy1 = vmulq_f32(xy1, vLo);
-
- float32x4x2_t zb = vuzpq_f32( z0, z1);
- float32x4_t z = vmulq_f32( zb.val[0], vHi);
- float32x4x2_t xy = vuzpq_f32( xy0, xy1);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcltq_f32(x, minDot);
- minDot = vbslq_f32( mask, x, minDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
- break;
-
- case 2:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
- float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
-
- xy0 = vmulq_f32(xy0, vLo);
-
- float32x4x2_t zb = vuzpq_f32( z0, z0);
- float32x4_t z = vmulq_f32( zb.val[0], vHi);
- float32x4x2_t xy = vuzpq_f32( xy0, xy0);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcltq_f32(x, minDot);
- minDot = vbslq_f32( mask, x, minDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
- break;
-
- case 1:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v0));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z = vdupq_lane_f32(vget_high_f32(v0), 0);
-
- xy0 = vmulq_f32(xy0, vLo);
-
- z = vmulq_f32( z, vHi);
- float32x4x2_t xy = vuzpq_f32( xy0, xy0);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcltq_f32(x, minDot);
- minDot = vbslq_f32( mask, x, minDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
- break;
-
- default:
- break;
- }
-
-
- // select best answer between hi and lo results
- uint32x2_t mask = vclt_f32( vget_high_f32(minDot), vget_low_f32(minDot));
- float32x2_t minDot2 = vbsl_f32(mask, vget_high_f32(minDot), vget_low_f32(minDot));
- uint32x2_t index2 = vbsl_u32(mask, vget_high_u32(index), vget_low_u32(index));
-
- // select best answer between even and odd results
- float32x2_t minDotO = vdup_lane_f32(minDot2, 1);
- uint32x2_t indexHi = vdup_lane_u32(index2, 1);
- mask = vclt_f32( minDotO, minDot2 );
- minDot2 = vbsl_f32(mask, minDotO, minDot2);
- index2 = vbsl_u32(mask, indexHi, index2);
-
- *dotResult = vget_lane_f32( minDot2, 0);
- return vget_lane_u32(index2, 0);
-
+ float32x4_t vvec = vld1q_f32_aligned_postincrement(vec);
+ float32x4_t vLo = vcombine_f32(vget_low_f32(vvec), vget_low_f32(vvec));
+ float32x4_t vHi = vdupq_lane_f32(vget_high_f32(vvec), 0);
+ const uint32x4_t four = (uint32x4_t){4, 4, 4, 4};
+ uint32x4_t local_index = (uint32x4_t){0, 1, 2, 3};
+ uint32x4_t index = (uint32x4_t){static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), static_cast<uint32_t>(-1)};
+ float32x4_t minDot = (float32x4_t){BT_INFINITY, BT_INFINITY, BT_INFINITY, BT_INFINITY};
+
+ unsigned long i = 0;
+ for (; i + 8 <= count; i += 8)
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+ float32x4_t xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v3));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+ float32x4_t z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v3));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ float32x4x2_t zb = vuzpq_f32(z0, z1);
+ float32x4_t z = vmulq_f32(zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32(xy0, xy1);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcltq_f32(x, minDot);
+ minDot = vbslq_f32(mask, x, minDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+
+ v0 = vld1q_f32_aligned_postincrement(vv);
+ v1 = vld1q_f32_aligned_postincrement(vv);
+ v2 = vld1q_f32_aligned_postincrement(vv);
+ v3 = vld1q_f32_aligned_postincrement(vv);
+
+ // the next two lines should resolve to a single vswp d, d
+ xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+ xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v3));
+ // the next two lines should resolve to a single vswp d, d
+ z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+ z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v3));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ zb = vuzpq_f32(z0, z1);
+ z = vmulq_f32(zb.val[0], vHi);
+ xy = vuzpq_f32(xy0, xy1);
+ x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ mask = vcltq_f32(x, minDot);
+ minDot = vbslq_f32(mask, x, minDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+
+ for (; i + 4 <= count; i += 4)
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+ float32x4_t xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v3));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+ float32x4_t z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v3));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ float32x4x2_t zb = vuzpq_f32(z0, z1);
+ float32x4_t z = vmulq_f32(zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32(xy0, xy1);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcltq_f32(x, minDot);
+ minDot = vbslq_f32(mask, x, minDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+
+ switch (count & 3)
+ {
+ case 3:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+ float32x4_t xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v2));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+ float32x4_t z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v2));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ float32x4x2_t zb = vuzpq_f32(z0, z1);
+ float32x4_t z = vmulq_f32(zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32(xy0, xy1);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcltq_f32(x, minDot);
+ minDot = vbslq_f32(mask, x, minDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+ break;
+
+ case 2:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+ float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+
+ xy0 = vmulq_f32(xy0, vLo);
+
+ float32x4x2_t zb = vuzpq_f32(z0, z0);
+ float32x4_t z = vmulq_f32(zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32(xy0, xy0);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcltq_f32(x, minDot);
+ minDot = vbslq_f32(mask, x, minDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+ break;
+
+ case 1:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v0));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z = vdupq_lane_f32(vget_high_f32(v0), 0);
+
+ xy0 = vmulq_f32(xy0, vLo);
+
+ z = vmulq_f32(z, vHi);
+ float32x4x2_t xy = vuzpq_f32(xy0, xy0);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcltq_f32(x, minDot);
+ minDot = vbslq_f32(mask, x, minDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ // select best answer between hi and lo results
+ uint32x2_t mask = vclt_f32(vget_high_f32(minDot), vget_low_f32(minDot));
+ float32x2_t minDot2 = vbsl_f32(mask, vget_high_f32(minDot), vget_low_f32(minDot));
+ uint32x2_t index2 = vbsl_u32(mask, vget_high_u32(index), vget_low_u32(index));
+
+ // select best answer between even and odd results
+ float32x2_t minDotO = vdup_lane_f32(minDot2, 1);
+ uint32x2_t indexHi = vdup_lane_u32(index2, 1);
+ mask = vclt_f32(minDotO, minDot2);
+ minDot2 = vbsl_f32(mask, minDotO, minDot2);
+ index2 = vbsl_u32(mask, indexHi, index2);
+
+ *dotResult = vget_lane_f32(minDot2, 0);
+ return vget_lane_u32(index2, 0);
}
#else
- #error Unhandled __APPLE__ arch
+#error Unhandled __APPLE__ arch
#endif
-#endif /* __APPLE__ */
-
-
+#endif /* __APPLE__ */
diff --git a/thirdparty/bullet/LinearMath/btVector3.h b/thirdparty/bullet/LinearMath/btVector3.h
index 76024f1236..61fd8d1e46 100644
--- a/thirdparty/bullet/LinearMath/btVector3.h
+++ b/thirdparty/bullet/LinearMath/btVector3.h
@@ -12,8 +12,6 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
-
#ifndef BT_VECTOR3_H
#define BT_VECTOR3_H
@@ -28,25 +26,24 @@ subject to the following restrictions:
#else
#define btVector3Data btVector3FloatData
#define btVector3DataName "btVector3FloatData"
-#endif //BT_USE_DOUBLE_PRECISION
+#endif //BT_USE_DOUBLE_PRECISION
#if defined BT_USE_SSE
//typedef uint32_t __m128i __attribute__ ((vector_size(16)));
#ifdef _MSC_VER
-#pragma warning(disable: 4556) // value of intrinsic immediate argument '4294967239' is out of range '0 - 255'
+#pragma warning(disable : 4556) // value of intrinsic immediate argument '4294967239' is out of range '0 - 255'
#endif
-
-#define BT_SHUFFLE(x,y,z,w) ((w)<<6 | (z)<<4 | (y)<<2 | (x))
+#define BT_SHUFFLE(x, y, z, w) ((w) << 6 | (z) << 4 | (y) << 2 | (x))
//#define bt_pshufd_ps( _a, _mask ) (__m128) _mm_shuffle_epi32((__m128i)(_a), (_mask) )
-#define bt_pshufd_ps( _a, _mask ) _mm_shuffle_ps((_a), (_a), (_mask) )
-#define bt_splat3_ps( _a, _i ) bt_pshufd_ps((_a), BT_SHUFFLE(_i,_i,_i, 3) )
-#define bt_splat_ps( _a, _i ) bt_pshufd_ps((_a), BT_SHUFFLE(_i,_i,_i,_i) )
+#define bt_pshufd_ps(_a, _mask) _mm_shuffle_ps((_a), (_a), (_mask))
+#define bt_splat3_ps(_a, _i) bt_pshufd_ps((_a), BT_SHUFFLE(_i, _i, _i, 3))
+#define bt_splat_ps(_a, _i) bt_pshufd_ps((_a), BT_SHUFFLE(_i, _i, _i, _i))
#define btv3AbsiMask (_mm_set_epi32(0x00000000, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF))
-#define btvAbsMask (_mm_set_epi32( 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF))
+#define btvAbsMask (_mm_set_epi32(0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF))
#define btvFFF0Mask (_mm_set_epi32(0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF))
#define btv3AbsfMask btCastiTo128f(btv3AbsiMask)
#define btvFFF0fMask btCastiTo128f(btvFFF0Mask)
@@ -55,9 +52,9 @@ subject to the following restrictions:
//there is an issue with XCode 3.2 (LCx errors)
#define btvMzeroMask (_mm_set_ps(-0.0f, -0.0f, -0.0f, -0.0f))
-#define v1110 (_mm_set_ps(0.0f, 1.0f, 1.0f, 1.0f))
-#define vHalf (_mm_set_ps(0.5f, 0.5f, 0.5f, 0.5f))
-#define v1_5 (_mm_set_ps(1.5f, 1.5f, 1.5f, 1.5f))
+#define v1110 (_mm_set_ps(0.0f, 1.0f, 1.0f, 1.0f))
+#define vHalf (_mm_set_ps(0.5f, 0.5f, 0.5f, 0.5f))
+#define v1_5 (_mm_set_ps(1.5f, 1.5f, 1.5f, 1.5f))
//const __m128 ATTRIBUTE_ALIGNED16(btvMzeroMask) = {-0.0f, -0.0f, -0.0f, -0.0f};
//const __m128 ATTRIBUTE_ALIGNED16(v1110) = {1.0f, 1.0f, 1.0f, 0.0f};
@@ -70,7 +67,7 @@ subject to the following restrictions:
const float32x4_t ATTRIBUTE_ALIGNED16(btvMzeroMask) = (float32x4_t){-0.0f, -0.0f, -0.0f, -0.0f};
const int32x4_t ATTRIBUTE_ALIGNED16(btvFFF0Mask) = (int32x4_t){static_cast<int32_t>(0xFFFFFFFF),
- static_cast<int32_t>(0xFFFFFFFF), static_cast<int32_t>(0xFFFFFFFF), 0x0};
+ static_cast<int32_t>(0xFFFFFFFF), static_cast<int32_t>(0xFFFFFFFF), 0x0};
const int32x4_t ATTRIBUTE_ALIGNED16(btvAbsMask) = (int32x4_t){0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF};
const int32x4_t ATTRIBUTE_ALIGNED16(btv3AbsMask) = (int32x4_t){0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x0};
@@ -80,50 +77,48 @@ const int32x4_t ATTRIBUTE_ALIGNED16(btv3AbsMask) = (int32x4_t){0x7FFFFFFF, 0x7FF
* It has an un-used w component to suit 16-byte alignment when btVector3 is stored in containers. This extra component can be used by derived classes (Quaternion?) or by user
* Ideally, this class should be replaced by a platform optimized SIMD version that keeps the data in registers
*/
-ATTRIBUTE_ALIGNED16(class) btVector3
+ATTRIBUTE_ALIGNED16(class)
+btVector3
{
public:
-
BT_DECLARE_ALIGNED_ALLOCATOR();
-#if defined (__SPU__) && defined (__CELLOS_LV2__)
- btScalar m_floats[4];
+#if defined(__SPU__) && defined(__CELLOS_LV2__)
+ btScalar m_floats[4];
+
public:
- SIMD_FORCE_INLINE const vec_float4& get128() const
+ SIMD_FORCE_INLINE const vec_float4& get128() const
{
return *((const vec_float4*)&m_floats[0]);
}
+
public:
-#else //__CELLOS_LV2__ __SPU__
- #if defined (BT_USE_SSE) || defined(BT_USE_NEON) // _WIN32 || ARM
- union {
- btSimdFloat4 mVec128;
- btScalar m_floats[4];
- };
- SIMD_FORCE_INLINE btSimdFloat4 get128() const
- {
- return mVec128;
- }
- SIMD_FORCE_INLINE void set128(btSimdFloat4 v128)
- {
- mVec128 = v128;
- }
- #else
- btScalar m_floats[4];
- #endif
-#endif //__CELLOS_LV2__ __SPU__
-
- public:
-
- /**@brief No initialization constructor */
- SIMD_FORCE_INLINE btVector3()
+#else //__CELLOS_LV2__ __SPU__
+#if defined(BT_USE_SSE) || defined(BT_USE_NEON) // _WIN32 || ARM
+ union {
+ btSimdFloat4 mVec128;
+ btScalar m_floats[4];
+ };
+ SIMD_FORCE_INLINE btSimdFloat4 get128() const
+ {
+ return mVec128;
+ }
+ SIMD_FORCE_INLINE void set128(btSimdFloat4 v128)
{
+ mVec128 = v128;
+ }
+#else
+ btScalar m_floats[4];
+#endif
+#endif //__CELLOS_LV2__ __SPU__
+public:
+ /**@brief No initialization constructor */
+ SIMD_FORCE_INLINE btVector3()
+ {
}
-
-
- /**@brief Constructor from scalars
+ /**@brief Constructor from scalars
* @param x X value
* @param y Y value
* @param z Z value
@@ -136,9 +131,9 @@ public:
m_floats[3] = btScalar(0.f);
}
-#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE) )|| defined (BT_USE_NEON)
- // Set Vector
- SIMD_FORCE_INLINE btVector3( btSimdFloat4 v)
+#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
+ // Set Vector
+ SIMD_FORCE_INLINE btVector3(btSimdFloat4 v)
{
mVec128 = v;
}
@@ -150,73 +145,72 @@ public:
}
// Assignment Operator
- SIMD_FORCE_INLINE btVector3&
- operator=(const btVector3& v)
+ SIMD_FORCE_INLINE btVector3&
+ operator=(const btVector3& v)
{
mVec128 = v.mVec128;
-
+
return *this;
}
-#endif // #if defined (BT_USE_SSE_IN_API) || defined (BT_USE_NEON)
-
-/**@brief Add a vector to this one
+#endif // #if defined (BT_USE_SSE_IN_API) || defined (BT_USE_NEON)
+
+ /**@brief Add a vector to this one
* @param The vector to add to this one */
SIMD_FORCE_INLINE btVector3& operator+=(const btVector3& v)
{
-#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
mVec128 = _mm_add_ps(mVec128, v.mVec128);
#elif defined(BT_USE_NEON)
mVec128 = vaddq_f32(mVec128, v.mVec128);
#else
- m_floats[0] += v.m_floats[0];
+ m_floats[0] += v.m_floats[0];
m_floats[1] += v.m_floats[1];
m_floats[2] += v.m_floats[2];
#endif
return *this;
}
-
- /**@brief Subtract a vector from this one
+ /**@brief Subtract a vector from this one
* @param The vector to subtract */
- SIMD_FORCE_INLINE btVector3& operator-=(const btVector3& v)
+ SIMD_FORCE_INLINE btVector3& operator-=(const btVector3& v)
{
-#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
mVec128 = _mm_sub_ps(mVec128, v.mVec128);
#elif defined(BT_USE_NEON)
mVec128 = vsubq_f32(mVec128, v.mVec128);
#else
- m_floats[0] -= v.m_floats[0];
+ m_floats[0] -= v.m_floats[0];
m_floats[1] -= v.m_floats[1];
m_floats[2] -= v.m_floats[2];
#endif
return *this;
}
-
- /**@brief Scale the vector
+
+ /**@brief Scale the vector
* @param s Scale factor */
SIMD_FORCE_INLINE btVector3& operator*=(const btScalar& s)
{
-#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
- __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
- vs = bt_pshufd_ps(vs, 0x80); // (S S S 0.0)
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+ __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
+ vs = bt_pshufd_ps(vs, 0x80); // (S S S 0.0)
mVec128 = _mm_mul_ps(mVec128, vs);
#elif defined(BT_USE_NEON)
mVec128 = vmulq_n_f32(mVec128, s);
#else
- m_floats[0] *= s;
+ m_floats[0] *= s;
m_floats[1] *= s;
m_floats[2] *= s;
#endif
return *this;
}
- /**@brief Inversely scale the vector
+ /**@brief Inversely scale the vector
* @param s Scale factor to divide by */
- SIMD_FORCE_INLINE btVector3& operator/=(const btScalar& s)
+ SIMD_FORCE_INLINE btVector3& operator/=(const btScalar& s)
{
btFullAssert(s != btScalar(0.0));
-#if 0 //defined(BT_USE_SSE_IN_API)
+#if 0 //defined(BT_USE_SSE_IN_API)
// this code is not faster !
__m128 vs = _mm_load_ss(&s);
vs = _mm_div_ss(v1110, vs);
@@ -230,11 +224,11 @@ public:
#endif
}
- /**@brief Return the dot product
+ /**@brief Return the dot product
* @param v The other vector in the dot product */
SIMD_FORCE_INLINE btScalar dot(const btVector3& v) const
{
-#if defined BT_USE_SIMD_VECTOR3 && defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
__m128 vd = _mm_mul_ps(mVec128, v.mVec128);
__m128 z = _mm_movehl_ps(vd, vd);
__m128 y = _mm_shuffle_ps(vd, vd, 0x55);
@@ -243,23 +237,23 @@ public:
return _mm_cvtss_f32(vd);
#elif defined(BT_USE_NEON)
float32x4_t vd = vmulq_f32(mVec128, v.mVec128);
- float32x2_t x = vpadd_f32(vget_low_f32(vd), vget_low_f32(vd));
+ float32x2_t x = vpadd_f32(vget_low_f32(vd), vget_low_f32(vd));
x = vadd_f32(x, vget_high_f32(vd));
return vget_lane_f32(x, 0);
-#else
- return m_floats[0] * v.m_floats[0] +
- m_floats[1] * v.m_floats[1] +
- m_floats[2] * v.m_floats[2];
+#else
+ return m_floats[0] * v.m_floats[0] +
+ m_floats[1] * v.m_floats[1] +
+ m_floats[2] * v.m_floats[2];
#endif
}
- /**@brief Return the length of the vector squared */
+ /**@brief Return the length of the vector squared */
SIMD_FORCE_INLINE btScalar length2() const
{
return dot(*this);
}
- /**@brief Return the length of the vector */
+ /**@brief Return the length of the vector */
SIMD_FORCE_INLINE btScalar length() const
{
return btSqrt(length2());
@@ -267,7 +261,7 @@ public:
/**@brief Return the norm (length) of the vector */
SIMD_FORCE_INLINE btScalar norm() const
- {
+ {
return length();
}
@@ -276,24 +270,24 @@ public:
{
btScalar d = length2();
//workaround for some clang/gcc issue of sqrtf(tiny number) = -INF
- if (d>SIMD_EPSILON)
+ if (d > SIMD_EPSILON)
return btSqrt(d);
return btScalar(0);
}
- /**@brief Return the distance squared between the ends of this and another vector
+ /**@brief Return the distance squared between the ends of this and another vector
* This is symantically treating the vector like a point */
SIMD_FORCE_INLINE btScalar distance2(const btVector3& v) const;
- /**@brief Return the distance between the ends of this and another vector
+ /**@brief Return the distance between the ends of this and another vector
* This is symantically treating the vector like a point */
SIMD_FORCE_INLINE btScalar distance(const btVector3& v) const;
- SIMD_FORCE_INLINE btVector3& safeNormalize()
+ SIMD_FORCE_INLINE btVector3& safeNormalize()
{
btScalar l2 = length2();
//triNormal.normalize();
- if (l2 >= SIMD_EPSILON*SIMD_EPSILON)
+ if (l2 >= SIMD_EPSILON * SIMD_EPSILON)
{
(*this) /= btSqrt(l2);
}
@@ -304,100 +298,97 @@ public:
return *this;
}
- /**@brief Normalize this vector
+ /**@brief Normalize this vector
* x^2 + y^2 + z^2 = 1 */
- SIMD_FORCE_INLINE btVector3& normalize()
+ SIMD_FORCE_INLINE btVector3& normalize()
{
-
btAssert(!fuzzyZero());
-#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
- // dot product first
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+ // dot product first
__m128 vd = _mm_mul_ps(mVec128, mVec128);
__m128 z = _mm_movehl_ps(vd, vd);
__m128 y = _mm_shuffle_ps(vd, vd, 0x55);
vd = _mm_add_ss(vd, y);
vd = _mm_add_ss(vd, z);
-
- #if 0
+
+#if 0
vd = _mm_sqrt_ss(vd);
vd = _mm_div_ss(v1110, vd);
vd = bt_splat_ps(vd, 0x80);
mVec128 = _mm_mul_ps(mVec128, vd);
- #else
-
- // NR step 1/sqrt(x) - vd is x, y is output
- y = _mm_rsqrt_ss(vd); // estimate
-
- // one step NR
- z = v1_5;
- vd = _mm_mul_ss(vd, vHalf); // vd * 0.5
- //x2 = vd;
- vd = _mm_mul_ss(vd, y); // vd * 0.5 * y0
- vd = _mm_mul_ss(vd, y); // vd * 0.5 * y0 * y0
- z = _mm_sub_ss(z, vd); // 1.5 - vd * 0.5 * y0 * y0
-
- y = _mm_mul_ss(y, z); // y0 * (1.5 - vd * 0.5 * y0 * y0)
+#else
+
+ // NR step 1/sqrt(x) - vd is x, y is output
+ y = _mm_rsqrt_ss(vd); // estimate
+
+ // one step NR
+ z = v1_5;
+ vd = _mm_mul_ss(vd, vHalf); // vd * 0.5
+ //x2 = vd;
+ vd = _mm_mul_ss(vd, y); // vd * 0.5 * y0
+ vd = _mm_mul_ss(vd, y); // vd * 0.5 * y0 * y0
+ z = _mm_sub_ss(z, vd); // 1.5 - vd * 0.5 * y0 * y0
+
+ y = _mm_mul_ss(y, z); // y0 * (1.5 - vd * 0.5 * y0 * y0)
y = bt_splat_ps(y, 0x80);
mVec128 = _mm_mul_ps(mVec128, y);
- #endif
+#endif
-
return *this;
-#else
+#else
return *this /= length();
#endif
}
- /**@brief Return a normalized version of this vector */
+ /**@brief Return a normalized version of this vector */
SIMD_FORCE_INLINE btVector3 normalized() const;
- /**@brief Return a rotated version of this vector
+ /**@brief Return a rotated version of this vector
* @param wAxis The axis to rotate about
* @param angle The angle to rotate by */
- SIMD_FORCE_INLINE btVector3 rotate( const btVector3& wAxis, const btScalar angle ) const;
+ SIMD_FORCE_INLINE btVector3 rotate(const btVector3& wAxis, const btScalar angle) const;
- /**@brief Return the angle between this and another vector
+ /**@brief Return the angle between this and another vector
* @param v The other vector */
- SIMD_FORCE_INLINE btScalar angle(const btVector3& v) const
+ SIMD_FORCE_INLINE btScalar angle(const btVector3& v) const
{
btScalar s = btSqrt(length2() * v.length2());
btFullAssert(s != btScalar(0.0));
return btAcos(dot(v) / s);
}
-
- /**@brief Return a vector with the absolute values of each element */
- SIMD_FORCE_INLINE btVector3 absolute() const
- {
-#if defined BT_USE_SIMD_VECTOR3 && defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ /**@brief Return a vector with the absolute values of each element */
+ SIMD_FORCE_INLINE btVector3 absolute() const
+ {
+#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
return btVector3(_mm_and_ps(mVec128, btv3AbsfMask));
#elif defined(BT_USE_NEON)
return btVector3(vabsq_f32(mVec128));
-#else
+#else
return btVector3(
- btFabs(m_floats[0]),
- btFabs(m_floats[1]),
+ btFabs(m_floats[0]),
+ btFabs(m_floats[1]),
btFabs(m_floats[2]));
#endif
}
-
- /**@brief Return the cross product between this and another vector
+
+ /**@brief Return the cross product between this and another vector
* @param v The other vector */
SIMD_FORCE_INLINE btVector3 cross(const btVector3& v) const
{
-#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
- __m128 T, V;
-
- T = bt_pshufd_ps(mVec128, BT_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
- V = bt_pshufd_ps(v.mVec128, BT_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
-
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+ __m128 T, V;
+
+ T = bt_pshufd_ps(mVec128, BT_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
+ V = bt_pshufd_ps(v.mVec128, BT_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
+
V = _mm_mul_ps(V, mVec128);
T = _mm_mul_ps(T, v.mVec128);
V = _mm_sub_ps(V, T);
-
+
V = bt_pshufd_ps(V, BT_SHUFFLE(1, 2, 0, 3));
return btVector3(V);
#elif defined(BT_USE_NEON)
@@ -407,7 +398,7 @@ public:
float32x2_t Vlow = vget_low_f32(v.mVec128);
T = vcombine_f32(vext_f32(Tlow, vget_high_f32(mVec128), 1), Tlow);
V = vcombine_f32(vext_f32(Vlow, vget_high_f32(v.mVec128), 1), Vlow);
-
+
V = vmulq_f32(V, mVec128);
T = vmulq_f32(T, v.mVec128);
V = vsubq_f32(V, T);
@@ -415,7 +406,7 @@ public:
// form (Y, Z, X, _);
V = vcombine_f32(vext_f32(Vlow, vget_high_f32(V), 1), Vlow);
V = (float32x4_t)vandq_s32((int32x4_t)V, btvFFF0Mask);
-
+
return btVector3(V);
#else
return btVector3(
@@ -427,18 +418,18 @@ public:
SIMD_FORCE_INLINE btScalar triple(const btVector3& v1, const btVector3& v2) const
{
-#if defined BT_USE_SIMD_VECTOR3 && defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
// cross:
- __m128 T = _mm_shuffle_ps(v1.mVec128, v1.mVec128, BT_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
- __m128 V = _mm_shuffle_ps(v2.mVec128, v2.mVec128, BT_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
-
+ __m128 T = _mm_shuffle_ps(v1.mVec128, v1.mVec128, BT_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
+ __m128 V = _mm_shuffle_ps(v2.mVec128, v2.mVec128, BT_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
+
V = _mm_mul_ps(V, v1.mVec128);
T = _mm_mul_ps(T, v2.mVec128);
V = _mm_sub_ps(V, T);
-
+
V = _mm_shuffle_ps(V, V, BT_SHUFFLE(1, 2, 0, 3));
- // dot:
+ // dot:
V = _mm_mul_ps(V, mVec128);
__m128 z = _mm_movehl_ps(V, V);
__m128 y = _mm_shuffle_ps(V, V, 0x55);
@@ -454,7 +445,7 @@ public:
float32x2_t Vlow = vget_low_f32(v2.mVec128);
T = vcombine_f32(vext_f32(Tlow, vget_high_f32(v1.mVec128), 1), Tlow);
V = vcombine_f32(vext_f32(Vlow, vget_high_f32(v2.mVec128), 1), Vlow);
-
+
V = vmulq_f32(V, v1.mVec128);
T = vmulq_f32(T, v2.mVec128);
V = vsubq_f32(V, T);
@@ -462,31 +453,30 @@ public:
// form (Y, Z, X, _);
V = vcombine_f32(vext_f32(Vlow, vget_high_f32(V), 1), Vlow);
- // dot:
+ // dot:
V = vmulq_f32(mVec128, V);
- float32x2_t x = vpadd_f32(vget_low_f32(V), vget_low_f32(V));
+ float32x2_t x = vpadd_f32(vget_low_f32(V), vget_low_f32(V));
x = vadd_f32(x, vget_high_f32(V));
return vget_lane_f32(x, 0);
#else
- return
- m_floats[0] * (v1.m_floats[1] * v2.m_floats[2] - v1.m_floats[2] * v2.m_floats[1]) +
- m_floats[1] * (v1.m_floats[2] * v2.m_floats[0] - v1.m_floats[0] * v2.m_floats[2]) +
- m_floats[2] * (v1.m_floats[0] * v2.m_floats[1] - v1.m_floats[1] * v2.m_floats[0]);
+ return m_floats[0] * (v1.m_floats[1] * v2.m_floats[2] - v1.m_floats[2] * v2.m_floats[1]) +
+ m_floats[1] * (v1.m_floats[2] * v2.m_floats[0] - v1.m_floats[0] * v2.m_floats[2]) +
+ m_floats[2] * (v1.m_floats[0] * v2.m_floats[1] - v1.m_floats[1] * v2.m_floats[0]);
#endif
}
- /**@brief Return the axis with the smallest value
+ /**@brief Return the axis with the smallest value
* Note return values are 0,1,2 for x, y, or z */
SIMD_FORCE_INLINE int minAxis() const
{
- return m_floats[0] < m_floats[1] ? (m_floats[0] <m_floats[2] ? 0 : 2) : (m_floats[1] <m_floats[2] ? 1 : 2);
+ return m_floats[0] < m_floats[1] ? (m_floats[0] < m_floats[2] ? 0 : 2) : (m_floats[1] < m_floats[2] ? 1 : 2);
}
- /**@brief Return the axis with the largest value
+ /**@brief Return the axis with the largest value
* Note return values are 0,1,2 for x, y, or z */
- SIMD_FORCE_INLINE int maxAxis() const
+ SIMD_FORCE_INLINE int maxAxis() const
{
- return m_floats[0] < m_floats[1] ? (m_floats[1] <m_floats[2] ? 2 : 1) : (m_floats[0] <m_floats[2] ? 2 : 0);
+ return m_floats[0] < m_floats[1] ? (m_floats[1] < m_floats[2] ? 2 : 1) : (m_floats[0] < m_floats[2] ? 2 : 0);
}
SIMD_FORCE_INLINE int furthestAxis() const
@@ -494,23 +484,22 @@ public:
return absolute().minAxis();
}
- SIMD_FORCE_INLINE int closestAxis() const
+ SIMD_FORCE_INLINE int closestAxis() const
{
return absolute().maxAxis();
}
-
SIMD_FORCE_INLINE void setInterpolate3(const btVector3& v0, const btVector3& v1, btScalar rt)
{
-#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
- __m128 vrt = _mm_load_ss(&rt); // (rt 0 0 0)
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+ __m128 vrt = _mm_load_ss(&rt); // (rt 0 0 0)
btScalar s = btScalar(1.0) - rt;
- __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
- vs = bt_pshufd_ps(vs, 0x80); // (S S S 0.0)
+ __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
+ vs = bt_pshufd_ps(vs, 0x80); // (S S S 0.0)
__m128 r0 = _mm_mul_ps(v0.mVec128, vs);
- vrt = bt_pshufd_ps(vrt, 0x80); // (rt rt rt 0.0)
+ vrt = bt_pshufd_ps(vrt, 0x80); // (rt rt rt 0.0)
__m128 r1 = _mm_mul_ps(v1.mVec128, vrt);
- __m128 tmp3 = _mm_add_ps(r0,r1);
+ __m128 tmp3 = _mm_add_ps(r0, r1);
mVec128 = tmp3;
#elif defined(BT_USE_NEON)
float32x4_t vl = vsubq_f32(v1.mVec128, v0.mVec128);
@@ -526,101 +515,100 @@ public:
#endif
}
- /**@brief Return the linear interpolation between this and another vector
+ /**@brief Return the linear interpolation between this and another vector
* @param v The other vector
* @param t The ration of this to v (t = 0 => return this, t=1 => return other) */
- SIMD_FORCE_INLINE btVector3 lerp(const btVector3& v, const btScalar& t) const
+ SIMD_FORCE_INLINE btVector3 lerp(const btVector3& v, const btScalar& t) const
{
-#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
- __m128 vt = _mm_load_ss(&t); // (t 0 0 0)
- vt = bt_pshufd_ps(vt, 0x80); // (rt rt rt 0.0)
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+ __m128 vt = _mm_load_ss(&t); // (t 0 0 0)
+ vt = bt_pshufd_ps(vt, 0x80); // (rt rt rt 0.0)
__m128 vl = _mm_sub_ps(v.mVec128, mVec128);
vl = _mm_mul_ps(vl, vt);
vl = _mm_add_ps(vl, mVec128);
-
+
return btVector3(vl);
#elif defined(BT_USE_NEON)
float32x4_t vl = vsubq_f32(v.mVec128, mVec128);
vl = vmulq_n_f32(vl, t);
vl = vaddq_f32(vl, mVec128);
-
+
return btVector3(vl);
-#else
- return
- btVector3( m_floats[0] + (v.m_floats[0] - m_floats[0]) * t,
- m_floats[1] + (v.m_floats[1] - m_floats[1]) * t,
- m_floats[2] + (v.m_floats[2] - m_floats[2]) * t);
+#else
+ return btVector3(m_floats[0] + (v.m_floats[0] - m_floats[0]) * t,
+ m_floats[1] + (v.m_floats[1] - m_floats[1]) * t,
+ m_floats[2] + (v.m_floats[2] - m_floats[2]) * t);
#endif
}
- /**@brief Elementwise multiply this vector by the other
+ /**@brief Elementwise multiply this vector by the other
* @param v The other vector */
SIMD_FORCE_INLINE btVector3& operator*=(const btVector3& v)
{
-#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
mVec128 = _mm_mul_ps(mVec128, v.mVec128);
#elif defined(BT_USE_NEON)
mVec128 = vmulq_f32(mVec128, v.mVec128);
-#else
- m_floats[0] *= v.m_floats[0];
+#else
+ m_floats[0] *= v.m_floats[0];
m_floats[1] *= v.m_floats[1];
m_floats[2] *= v.m_floats[2];
#endif
return *this;
}
- /**@brief Return the x value */
- SIMD_FORCE_INLINE const btScalar& getX() const { return m_floats[0]; }
- /**@brief Return the y value */
- SIMD_FORCE_INLINE const btScalar& getY() const { return m_floats[1]; }
- /**@brief Return the z value */
- SIMD_FORCE_INLINE const btScalar& getZ() const { return m_floats[2]; }
- /**@brief Set the x value */
- SIMD_FORCE_INLINE void setX(btScalar _x) { m_floats[0] = _x;};
- /**@brief Set the y value */
- SIMD_FORCE_INLINE void setY(btScalar _y) { m_floats[1] = _y;};
- /**@brief Set the z value */
- SIMD_FORCE_INLINE void setZ(btScalar _z) { m_floats[2] = _z;};
- /**@brief Set the w value */
- SIMD_FORCE_INLINE void setW(btScalar _w) { m_floats[3] = _w;};
- /**@brief Return the x value */
- SIMD_FORCE_INLINE const btScalar& x() const { return m_floats[0]; }
- /**@brief Return the y value */
- SIMD_FORCE_INLINE const btScalar& y() const { return m_floats[1]; }
- /**@brief Return the z value */
- SIMD_FORCE_INLINE const btScalar& z() const { return m_floats[2]; }
- /**@brief Return the w value */
- SIMD_FORCE_INLINE const btScalar& w() const { return m_floats[3]; }
-
- //SIMD_FORCE_INLINE btScalar& operator[](int i) { return (&m_floats[0])[i]; }
+ /**@brief Return the x value */
+ SIMD_FORCE_INLINE const btScalar& getX() const { return m_floats[0]; }
+ /**@brief Return the y value */
+ SIMD_FORCE_INLINE const btScalar& getY() const { return m_floats[1]; }
+ /**@brief Return the z value */
+ SIMD_FORCE_INLINE const btScalar& getZ() const { return m_floats[2]; }
+ /**@brief Set the x value */
+ SIMD_FORCE_INLINE void setX(btScalar _x) { m_floats[0] = _x; };
+ /**@brief Set the y value */
+ SIMD_FORCE_INLINE void setY(btScalar _y) { m_floats[1] = _y; };
+ /**@brief Set the z value */
+ SIMD_FORCE_INLINE void setZ(btScalar _z) { m_floats[2] = _z; };
+ /**@brief Set the w value */
+ SIMD_FORCE_INLINE void setW(btScalar _w) { m_floats[3] = _w; };
+ /**@brief Return the x value */
+ SIMD_FORCE_INLINE const btScalar& x() const { return m_floats[0]; }
+ /**@brief Return the y value */
+ SIMD_FORCE_INLINE const btScalar& y() const { return m_floats[1]; }
+ /**@brief Return the z value */
+ SIMD_FORCE_INLINE const btScalar& z() const { return m_floats[2]; }
+ /**@brief Return the w value */
+ SIMD_FORCE_INLINE const btScalar& w() const { return m_floats[3]; }
+
+ //SIMD_FORCE_INLINE btScalar& operator[](int i) { return (&m_floats[0])[i]; }
//SIMD_FORCE_INLINE const btScalar& operator[](int i) const { return (&m_floats[0])[i]; }
///operator btScalar*() replaces operator[], using implicit conversion. We added operator != and operator == to avoid pointer comparisons.
- SIMD_FORCE_INLINE operator btScalar *() { return &m_floats[0]; }
- SIMD_FORCE_INLINE operator const btScalar *() const { return &m_floats[0]; }
+ SIMD_FORCE_INLINE operator btScalar*() { return &m_floats[0]; }
+ SIMD_FORCE_INLINE operator const btScalar*() const { return &m_floats[0]; }
- SIMD_FORCE_INLINE bool operator==(const btVector3& other) const
+ SIMD_FORCE_INLINE bool operator==(const btVector3& other) const
{
-#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
- return (0xf == _mm_movemask_ps((__m128)_mm_cmpeq_ps(mVec128, other.mVec128)));
-#else
- return ((m_floats[3]==other.m_floats[3]) &&
- (m_floats[2]==other.m_floats[2]) &&
- (m_floats[1]==other.m_floats[1]) &&
- (m_floats[0]==other.m_floats[0]));
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+ return (0xf == _mm_movemask_ps((__m128)_mm_cmpeq_ps(mVec128, other.mVec128)));
+#else
+ return ((m_floats[3] == other.m_floats[3]) &&
+ (m_floats[2] == other.m_floats[2]) &&
+ (m_floats[1] == other.m_floats[1]) &&
+ (m_floats[0] == other.m_floats[0]));
#endif
}
- SIMD_FORCE_INLINE bool operator!=(const btVector3& other) const
+ SIMD_FORCE_INLINE bool operator!=(const btVector3& other) const
{
return !(*this == other);
}
- /**@brief Set each element to the max of the current values and the values of another btVector3
+ /**@brief Set each element to the max of the current values and the values of another btVector3
* @param other The other btVector3 to compare with
*/
- SIMD_FORCE_INLINE void setMax(const btVector3& other)
+ SIMD_FORCE_INLINE void setMax(const btVector3& other)
{
-#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
mVec128 = _mm_max_ps(mVec128, other.mVec128);
#elif defined(BT_USE_NEON)
mVec128 = vmaxq_f32(mVec128, other.mVec128);
@@ -632,12 +620,12 @@ public:
#endif
}
- /**@brief Set each element to the min of the current values and the values of another btVector3
+ /**@brief Set each element to the min of the current values and the values of another btVector3
* @param other The other btVector3 to compare with
*/
- SIMD_FORCE_INLINE void setMin(const btVector3& other)
+ SIMD_FORCE_INLINE void setMin(const btVector3& other)
{
-#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
mVec128 = _mm_min_ps(mVec128, other.mVec128);
#elif defined(BT_USE_NEON)
mVec128 = vminq_f32(mVec128, other.mVec128);
@@ -649,156 +637,155 @@ public:
#endif
}
- SIMD_FORCE_INLINE void setValue(const btScalar& _x, const btScalar& _y, const btScalar& _z)
+ SIMD_FORCE_INLINE void setValue(const btScalar& _x, const btScalar& _y, const btScalar& _z)
{
- m_floats[0]=_x;
- m_floats[1]=_y;
- m_floats[2]=_z;
+ m_floats[0] = _x;
+ m_floats[1] = _y;
+ m_floats[2] = _z;
m_floats[3] = btScalar(0.f);
}
- void getSkewSymmetricMatrix(btVector3* v0,btVector3* v1,btVector3* v2) const
+ void getSkewSymmetricMatrix(btVector3 * v0, btVector3 * v1, btVector3 * v2) const
{
-#if defined BT_USE_SIMD_VECTOR3 && defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
-
- __m128 V = _mm_and_ps(mVec128, btvFFF0fMask);
+#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+
+ __m128 V = _mm_and_ps(mVec128, btvFFF0fMask);
__m128 V0 = _mm_xor_ps(btvMzeroMask, V);
__m128 V2 = _mm_movelh_ps(V0, V);
-
+
__m128 V1 = _mm_shuffle_ps(V, V0, 0xCE);
-
- V0 = _mm_shuffle_ps(V0, V, 0xDB);
+
+ V0 = _mm_shuffle_ps(V0, V, 0xDB);
V2 = _mm_shuffle_ps(V2, V, 0xF9);
-
+
v0->mVec128 = V0;
v1->mVec128 = V1;
v2->mVec128 = V2;
#else
- v0->setValue(0. ,-z() ,y());
- v1->setValue(z() ,0. ,-x());
- v2->setValue(-y() ,x() ,0.);
+ v0->setValue(0., -z(), y());
+ v1->setValue(z(), 0., -x());
+ v2->setValue(-y(), x(), 0.);
#endif
}
void setZero()
{
-#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
mVec128 = (__m128)_mm_xor_ps(mVec128, mVec128);
#elif defined(BT_USE_NEON)
- int32x4_t vi = vdupq_n_s32(0);
+ int32x4_t vi = vdupq_n_s32(0);
mVec128 = vreinterpretq_f32_s32(vi);
-#else
- setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+#else
+ setValue(btScalar(0.), btScalar(0.), btScalar(0.));
#endif
}
- SIMD_FORCE_INLINE bool isZero() const
+ SIMD_FORCE_INLINE bool isZero() const
{
return m_floats[0] == btScalar(0) && m_floats[1] == btScalar(0) && m_floats[2] == btScalar(0);
}
-
- SIMD_FORCE_INLINE bool fuzzyZero() const
+ SIMD_FORCE_INLINE bool fuzzyZero() const
{
- return length2() < SIMD_EPSILON*SIMD_EPSILON;
+ return length2() < SIMD_EPSILON * SIMD_EPSILON;
}
- SIMD_FORCE_INLINE void serialize(struct btVector3Data& dataOut) const;
+ SIMD_FORCE_INLINE void serialize(struct btVector3Data & dataOut) const;
+
+ SIMD_FORCE_INLINE void deSerialize(const struct btVector3DoubleData& dataIn);
- SIMD_FORCE_INLINE void deSerialize(const struct btVector3DoubleData& dataIn);
+ SIMD_FORCE_INLINE void deSerialize(const struct btVector3FloatData& dataIn);
- SIMD_FORCE_INLINE void deSerialize(const struct btVector3FloatData& dataIn);
+ SIMD_FORCE_INLINE void serializeFloat(struct btVector3FloatData & dataOut) const;
- SIMD_FORCE_INLINE void serializeFloat(struct btVector3FloatData& dataOut) const;
+ SIMD_FORCE_INLINE void deSerializeFloat(const struct btVector3FloatData& dataIn);
- SIMD_FORCE_INLINE void deSerializeFloat(const struct btVector3FloatData& dataIn);
+ SIMD_FORCE_INLINE void serializeDouble(struct btVector3DoubleData & dataOut) const;
- SIMD_FORCE_INLINE void serializeDouble(struct btVector3DoubleData& dataOut) const;
+ SIMD_FORCE_INLINE void deSerializeDouble(const struct btVector3DoubleData& dataIn);
- SIMD_FORCE_INLINE void deSerializeDouble(const struct btVector3DoubleData& dataIn);
-
- /**@brief returns index of maximum dot product between this and vectors in array[]
+ /**@brief returns index of maximum dot product between this and vectors in array[]
* @param array The other vectors
* @param array_count The number of other vectors
* @param dotOut The maximum dot product */
- SIMD_FORCE_INLINE long maxDot( const btVector3 *array, long array_count, btScalar &dotOut ) const;
+ SIMD_FORCE_INLINE long maxDot(const btVector3* array, long array_count, btScalar& dotOut) const;
- /**@brief returns index of minimum dot product between this and vectors in array[]
+ /**@brief returns index of minimum dot product between this and vectors in array[]
* @param array The other vectors
* @param array_count The number of other vectors
- * @param dotOut The minimum dot product */
- SIMD_FORCE_INLINE long minDot( const btVector3 *array, long array_count, btScalar &dotOut ) const;
-
- /* create a vector as btVector3( this->dot( btVector3 v0 ), this->dot( btVector3 v1), this->dot( btVector3 v2 )) */
- SIMD_FORCE_INLINE btVector3 dot3( const btVector3 &v0, const btVector3 &v1, const btVector3 &v2 ) const
- {
-#if defined BT_USE_SIMD_VECTOR3 && defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
-
- __m128 a0 = _mm_mul_ps( v0.mVec128, this->mVec128 );
- __m128 a1 = _mm_mul_ps( v1.mVec128, this->mVec128 );
- __m128 a2 = _mm_mul_ps( v2.mVec128, this->mVec128 );
- __m128 b0 = _mm_unpacklo_ps( a0, a1 );
- __m128 b1 = _mm_unpackhi_ps( a0, a1 );
- __m128 b2 = _mm_unpacklo_ps( a2, _mm_setzero_ps() );
- __m128 r = _mm_movelh_ps( b0, b2 );
- r = _mm_add_ps( r, _mm_movehl_ps( b2, b0 ));
- a2 = _mm_and_ps( a2, btvxyzMaskf);
- r = _mm_add_ps( r, btCastdTo128f (_mm_move_sd( btCastfTo128d(a2), btCastfTo128d(b1) )));
- return btVector3(r);
-
+ * @param dotOut The minimum dot product */
+ SIMD_FORCE_INLINE long minDot(const btVector3* array, long array_count, btScalar& dotOut) const;
+
+ /* create a vector as btVector3( this->dot( btVector3 v0 ), this->dot( btVector3 v1), this->dot( btVector3 v2 )) */
+ SIMD_FORCE_INLINE btVector3 dot3(const btVector3& v0, const btVector3& v1, const btVector3& v2) const
+ {
+#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+
+ __m128 a0 = _mm_mul_ps(v0.mVec128, this->mVec128);
+ __m128 a1 = _mm_mul_ps(v1.mVec128, this->mVec128);
+ __m128 a2 = _mm_mul_ps(v2.mVec128, this->mVec128);
+ __m128 b0 = _mm_unpacklo_ps(a0, a1);
+ __m128 b1 = _mm_unpackhi_ps(a0, a1);
+ __m128 b2 = _mm_unpacklo_ps(a2, _mm_setzero_ps());
+ __m128 r = _mm_movelh_ps(b0, b2);
+ r = _mm_add_ps(r, _mm_movehl_ps(b2, b0));
+ a2 = _mm_and_ps(a2, btvxyzMaskf);
+ r = _mm_add_ps(r, btCastdTo128f(_mm_move_sd(btCastfTo128d(a2), btCastfTo128d(b1))));
+ return btVector3(r);
+
#elif defined(BT_USE_NEON)
- static const uint32x4_t xyzMask = (const uint32x4_t){ static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), 0 };
- float32x4_t a0 = vmulq_f32( v0.mVec128, this->mVec128);
- float32x4_t a1 = vmulq_f32( v1.mVec128, this->mVec128);
- float32x4_t a2 = vmulq_f32( v2.mVec128, this->mVec128);
- float32x2x2_t zLo = vtrn_f32( vget_high_f32(a0), vget_high_f32(a1));
- a2 = (float32x4_t) vandq_u32((uint32x4_t) a2, xyzMask );
- float32x2_t b0 = vadd_f32( vpadd_f32( vget_low_f32(a0), vget_low_f32(a1)), zLo.val[0] );
- float32x2_t b1 = vpadd_f32( vpadd_f32( vget_low_f32(a2), vget_high_f32(a2)), vdup_n_f32(0.0f));
- return btVector3( vcombine_f32(b0, b1) );
-#else
- return btVector3( dot(v0), dot(v1), dot(v2));
+ static const uint32x4_t xyzMask = (const uint32x4_t){static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), 0};
+ float32x4_t a0 = vmulq_f32(v0.mVec128, this->mVec128);
+ float32x4_t a1 = vmulq_f32(v1.mVec128, this->mVec128);
+ float32x4_t a2 = vmulq_f32(v2.mVec128, this->mVec128);
+ float32x2x2_t zLo = vtrn_f32(vget_high_f32(a0), vget_high_f32(a1));
+ a2 = (float32x4_t)vandq_u32((uint32x4_t)a2, xyzMask);
+ float32x2_t b0 = vadd_f32(vpadd_f32(vget_low_f32(a0), vget_low_f32(a1)), zLo.val[0]);
+ float32x2_t b1 = vpadd_f32(vpadd_f32(vget_low_f32(a2), vget_high_f32(a2)), vdup_n_f32(0.0f));
+ return btVector3(vcombine_f32(b0, b1));
+#else
+ return btVector3(dot(v0), dot(v1), dot(v2));
#endif
- }
+ }
};
/**@brief Return the sum of two vectors (Point symantics)*/
-SIMD_FORCE_INLINE btVector3
-operator+(const btVector3& v1, const btVector3& v2)
+SIMD_FORCE_INLINE btVector3
+operator+(const btVector3& v1, const btVector3& v2)
{
-#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
return btVector3(_mm_add_ps(v1.mVec128, v2.mVec128));
#elif defined(BT_USE_NEON)
return btVector3(vaddq_f32(v1.mVec128, v2.mVec128));
#else
return btVector3(
- v1.m_floats[0] + v2.m_floats[0],
- v1.m_floats[1] + v2.m_floats[1],
- v1.m_floats[2] + v2.m_floats[2]);
+ v1.m_floats[0] + v2.m_floats[0],
+ v1.m_floats[1] + v2.m_floats[1],
+ v1.m_floats[2] + v2.m_floats[2]);
#endif
}
/**@brief Return the elementwise product of two vectors */
-SIMD_FORCE_INLINE btVector3
-operator*(const btVector3& v1, const btVector3& v2)
+SIMD_FORCE_INLINE btVector3
+operator*(const btVector3& v1, const btVector3& v2)
{
-#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
return btVector3(_mm_mul_ps(v1.mVec128, v2.mVec128));
#elif defined(BT_USE_NEON)
return btVector3(vmulq_f32(v1.mVec128, v2.mVec128));
#else
return btVector3(
- v1.m_floats[0] * v2.m_floats[0],
- v1.m_floats[1] * v2.m_floats[1],
- v1.m_floats[2] * v2.m_floats[2]);
+ v1.m_floats[0] * v2.m_floats[0],
+ v1.m_floats[1] * v2.m_floats[1],
+ v1.m_floats[2] * v2.m_floats[2]);
#endif
}
/**@brief Return the difference between two vectors */
-SIMD_FORCE_INLINE btVector3
+SIMD_FORCE_INLINE btVector3
operator-(const btVector3& v1, const btVector3& v2)
{
-#if defined BT_USE_SIMD_VECTOR3 && (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))
+#if defined BT_USE_SIMD_VECTOR3 && (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))
// without _mm_and_ps this code causes slowdown in Concave moving
__m128 r = _mm_sub_ps(v1.mVec128, v2.mVec128);
@@ -808,33 +795,33 @@ operator-(const btVector3& v1, const btVector3& v2)
return btVector3((float32x4_t)vandq_s32((int32x4_t)r, btvFFF0Mask));
#else
return btVector3(
- v1.m_floats[0] - v2.m_floats[0],
- v1.m_floats[1] - v2.m_floats[1],
- v1.m_floats[2] - v2.m_floats[2]);
+ v1.m_floats[0] - v2.m_floats[0],
+ v1.m_floats[1] - v2.m_floats[1],
+ v1.m_floats[2] - v2.m_floats[2]);
#endif
}
/**@brief Return the negative of the vector */
-SIMD_FORCE_INLINE btVector3
+SIMD_FORCE_INLINE btVector3
operator-(const btVector3& v)
{
-#if defined BT_USE_SIMD_VECTOR3 && (defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE))
+#if defined BT_USE_SIMD_VECTOR3 && (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))
__m128 r = _mm_xor_ps(v.mVec128, btvMzeroMask);
- return btVector3(_mm_and_ps(r, btvFFF0fMask));
+ return btVector3(_mm_and_ps(r, btvFFF0fMask));
#elif defined(BT_USE_NEON)
return btVector3((btSimdFloat4)veorq_s32((int32x4_t)v.mVec128, (int32x4_t)btvMzeroMask));
-#else
+#else
return btVector3(-v.m_floats[0], -v.m_floats[1], -v.m_floats[2]);
#endif
}
/**@brief Return the vector scaled by s */
-SIMD_FORCE_INLINE btVector3
+SIMD_FORCE_INLINE btVector3
operator*(const btVector3& v, const btScalar& s)
{
-#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
- __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
- vs = bt_pshufd_ps(vs, 0x80); // (S S S 0.0)
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+ __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
+ vs = bt_pshufd_ps(vs, 0x80); // (S S S 0.0)
return btVector3(_mm_mul_ps(v.mVec128, vs));
#elif defined(BT_USE_NEON)
float32x4_t r = vmulq_n_f32(v.mVec128, s);
@@ -845,10 +832,10 @@ operator*(const btVector3& v, const btScalar& s)
}
/**@brief Return the vector scaled by s */
-SIMD_FORCE_INLINE btVector3
+SIMD_FORCE_INLINE btVector3
operator*(const btScalar& s, const btVector3& v)
-{
- return v * s;
+{
+ return v * s;
}
/**@brief Return the vector inversely scaled by s */
@@ -856,7 +843,7 @@ SIMD_FORCE_INLINE btVector3
operator/(const btVector3& v, const btScalar& s)
{
btFullAssert(s != btScalar(0.0));
-#if 0 //defined(BT_USE_SSE_IN_API)
+#if 0 //defined(BT_USE_SSE_IN_API)
// this code is not faster !
__m128 vs = _mm_load_ss(&s);
vs = _mm_div_ss(v1110, vs);
@@ -872,67 +859,65 @@ operator/(const btVector3& v, const btScalar& s)
SIMD_FORCE_INLINE btVector3
operator/(const btVector3& v1, const btVector3& v2)
{
-#if defined BT_USE_SIMD_VECTOR3 && (defined(BT_USE_SSE_IN_API)&& defined (BT_USE_SSE))
+#if defined BT_USE_SIMD_VECTOR3 && (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))
__m128 vec = _mm_div_ps(v1.mVec128, v2.mVec128);
vec = _mm_and_ps(vec, btvFFF0fMask);
- return btVector3(vec);
+ return btVector3(vec);
#elif defined(BT_USE_NEON)
float32x4_t x, y, v, m;
x = v1.mVec128;
y = v2.mVec128;
-
- v = vrecpeq_f32(y); // v ~ 1/y
- m = vrecpsq_f32(y, v); // m = (2-v*y)
- v = vmulq_f32(v, m); // vv = v*m ~~ 1/y
- m = vrecpsq_f32(y, v); // mm = (2-vv*y)
- v = vmulq_f32(v, x); // x*vv
- v = vmulq_f32(v, m); // (x*vv)*(2-vv*y) = x*(vv(2-vv*y)) ~~~ x/y
+
+ v = vrecpeq_f32(y); // v ~ 1/y
+ m = vrecpsq_f32(y, v); // m = (2-v*y)
+ v = vmulq_f32(v, m); // vv = v*m ~~ 1/y
+ m = vrecpsq_f32(y, v); // mm = (2-vv*y)
+ v = vmulq_f32(v, x); // x*vv
+ v = vmulq_f32(v, m); // (x*vv)*(2-vv*y) = x*(vv(2-vv*y)) ~~~ x/y
return btVector3(v);
#else
return btVector3(
- v1.m_floats[0] / v2.m_floats[0],
- v1.m_floats[1] / v2.m_floats[1],
- v1.m_floats[2] / v2.m_floats[2]);
+ v1.m_floats[0] / v2.m_floats[0],
+ v1.m_floats[1] / v2.m_floats[1],
+ v1.m_floats[2] / v2.m_floats[2]);
#endif
}
/**@brief Return the dot product between two vectors */
-SIMD_FORCE_INLINE btScalar
-btDot(const btVector3& v1, const btVector3& v2)
-{
- return v1.dot(v2);
+SIMD_FORCE_INLINE btScalar
+btDot(const btVector3& v1, const btVector3& v2)
+{
+ return v1.dot(v2);
}
-
/**@brief Return the distance squared between two vectors */
SIMD_FORCE_INLINE btScalar
-btDistance2(const btVector3& v1, const btVector3& v2)
-{
- return v1.distance2(v2);
+btDistance2(const btVector3& v1, const btVector3& v2)
+{
+ return v1.distance2(v2);
}
-
/**@brief Return the distance between two vectors */
SIMD_FORCE_INLINE btScalar
-btDistance(const btVector3& v1, const btVector3& v2)
-{
- return v1.distance(v2);
+btDistance(const btVector3& v1, const btVector3& v2)
+{
+ return v1.distance(v2);
}
/**@brief Return the angle between two vectors */
SIMD_FORCE_INLINE btScalar
-btAngle(const btVector3& v1, const btVector3& v2)
-{
- return v1.angle(v2);
+btAngle(const btVector3& v1, const btVector3& v2)
+{
+ return v1.angle(v2);
}
/**@brief Return the cross product of two vectors */
-SIMD_FORCE_INLINE btVector3
-btCross(const btVector3& v1, const btVector3& v2)
-{
- return v1.cross(v2);
+SIMD_FORCE_INLINE btVector3
+btCross(const btVector3& v1, const btVector3& v2)
+{
+ return v1.cross(v2);
}
SIMD_FORCE_INLINE btScalar
@@ -945,14 +930,12 @@ btTriple(const btVector3& v1, const btVector3& v2, const btVector3& v3)
* @param v1 One vector
* @param v2 The other vector
* @param t The ration of this to v (t = 0 => return v1, t=1 => return v2) */
-SIMD_FORCE_INLINE btVector3
+SIMD_FORCE_INLINE btVector3
lerp(const btVector3& v1, const btVector3& v2, const btScalar& t)
{
return v1.lerp(v2, t);
}
-
-
SIMD_FORCE_INLINE btScalar btVector3::distance2(const btVector3& v) const
{
return (v - *this).length2();
@@ -968,140 +951,137 @@ SIMD_FORCE_INLINE btVector3 btVector3::normalized() const
btVector3 nrm = *this;
return nrm.normalize();
-}
+}
-SIMD_FORCE_INLINE btVector3 btVector3::rotate( const btVector3& wAxis, const btScalar _angle ) const
+SIMD_FORCE_INLINE btVector3 btVector3::rotate(const btVector3& wAxis, const btScalar _angle) const
{
// wAxis must be a unit lenght vector
-#if defined BT_USE_SIMD_VECTOR3 && defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- __m128 O = _mm_mul_ps(wAxis.mVec128, mVec128);
- btScalar ssin = btSin( _angle );
- __m128 C = wAxis.cross( mVec128 ).mVec128;
+ __m128 O = _mm_mul_ps(wAxis.mVec128, mVec128);
+ btScalar ssin = btSin(_angle);
+ __m128 C = wAxis.cross(mVec128).mVec128;
O = _mm_and_ps(O, btvFFF0fMask);
- btScalar scos = btCos( _angle );
-
- __m128 vsin = _mm_load_ss(&ssin); // (S 0 0 0)
- __m128 vcos = _mm_load_ss(&scos); // (S 0 0 0)
-
- __m128 Y = bt_pshufd_ps(O, 0xC9); // (Y Z X 0)
- __m128 Z = bt_pshufd_ps(O, 0xD2); // (Z X Y 0)
+ btScalar scos = btCos(_angle);
+
+ __m128 vsin = _mm_load_ss(&ssin); // (S 0 0 0)
+ __m128 vcos = _mm_load_ss(&scos); // (S 0 0 0)
+
+ __m128 Y = bt_pshufd_ps(O, 0xC9); // (Y Z X 0)
+ __m128 Z = bt_pshufd_ps(O, 0xD2); // (Z X Y 0)
O = _mm_add_ps(O, Y);
- vsin = bt_pshufd_ps(vsin, 0x80); // (S S S 0)
+ vsin = bt_pshufd_ps(vsin, 0x80); // (S S S 0)
O = _mm_add_ps(O, Z);
- vcos = bt_pshufd_ps(vcos, 0x80); // (S S S 0)
-
- vsin = vsin * C;
- O = O * wAxis.mVec128;
- __m128 X = mVec128 - O;
-
- O = O + vsin;
+ vcos = bt_pshufd_ps(vcos, 0x80); // (S S S 0)
+
+ vsin = vsin * C;
+ O = O * wAxis.mVec128;
+ __m128 X = mVec128 - O;
+
+ O = O + vsin;
vcos = vcos * X;
- O = O + vcos;
-
+ O = O + vcos;
+
return btVector3(O);
#else
- btVector3 o = wAxis * wAxis.dot( *this );
+ btVector3 o = wAxis * wAxis.dot(*this);
btVector3 _x = *this - o;
btVector3 _y;
- _y = wAxis.cross( *this );
+ _y = wAxis.cross(*this);
- return ( o + _x * btCos( _angle ) + _y * btSin( _angle ) );
+ return (o + _x * btCos(_angle) + _y * btSin(_angle));
#endif
}
-SIMD_FORCE_INLINE long btVector3::maxDot( const btVector3 *array, long array_count, btScalar &dotOut ) const
+SIMD_FORCE_INLINE long btVector3::maxDot(const btVector3* array, long array_count, btScalar& dotOut) const
{
-#if (defined BT_USE_SSE && defined BT_USE_SIMD_VECTOR3 && defined BT_USE_SSE_IN_API) || defined (BT_USE_NEON)
- #if defined _WIN32 || defined (BT_USE_SSE)
- const long scalar_cutoff = 10;
- long _maxdot_large( const float *array, const float *vec, unsigned long array_count, float *dotOut );
- #elif defined BT_USE_NEON
- const long scalar_cutoff = 4;
- extern long (*_maxdot_large)( const float *array, const float *vec, unsigned long array_count, float *dotOut );
- #endif
- if( array_count < scalar_cutoff )
+#if (defined BT_USE_SSE && defined BT_USE_SIMD_VECTOR3 && defined BT_USE_SSE_IN_API) || defined(BT_USE_NEON)
+#if defined _WIN32 || defined(BT_USE_SSE)
+ const long scalar_cutoff = 10;
+ long _maxdot_large(const float* array, const float* vec, unsigned long array_count, float* dotOut);
+#elif defined BT_USE_NEON
+ const long scalar_cutoff = 4;
+ extern long (*_maxdot_large)(const float* array, const float* vec, unsigned long array_count, float* dotOut);
#endif
- {
- btScalar maxDot1 = -SIMD_INFINITY;
- int i = 0;
- int ptIndex = -1;
- for( i = 0; i < array_count; i++ )
- {
- btScalar dot = array[i].dot(*this);
-
- if( dot > maxDot1 )
- {
- maxDot1 = dot;
- ptIndex = i;
- }
- }
-
- dotOut = maxDot1;
- return ptIndex;
- }
-#if (defined BT_USE_SSE && defined BT_USE_SIMD_VECTOR3 && defined BT_USE_SSE_IN_API) || defined (BT_USE_NEON)
- return _maxdot_large( (float*) array, (float*) &m_floats[0], array_count, &dotOut );
+ if (array_count < scalar_cutoff)
+#endif
+ {
+ btScalar maxDot1 = -SIMD_INFINITY;
+ int i = 0;
+ int ptIndex = -1;
+ for (i = 0; i < array_count; i++)
+ {
+ btScalar dot = array[i].dot(*this);
+
+ if (dot > maxDot1)
+ {
+ maxDot1 = dot;
+ ptIndex = i;
+ }
+ }
+
+ dotOut = maxDot1;
+ return ptIndex;
+ }
+#if (defined BT_USE_SSE && defined BT_USE_SIMD_VECTOR3 && defined BT_USE_SSE_IN_API) || defined(BT_USE_NEON)
+ return _maxdot_large((float*)array, (float*)&m_floats[0], array_count, &dotOut);
#endif
}
-SIMD_FORCE_INLINE long btVector3::minDot( const btVector3 *array, long array_count, btScalar &dotOut ) const
+SIMD_FORCE_INLINE long btVector3::minDot(const btVector3* array, long array_count, btScalar& dotOut) const
{
-#if (defined BT_USE_SSE && defined BT_USE_SIMD_VECTOR3 && defined BT_USE_SSE_IN_API) || defined (BT_USE_NEON)
- #if defined BT_USE_SSE
- const long scalar_cutoff = 10;
- long _mindot_large( const float *array, const float *vec, unsigned long array_count, float *dotOut );
- #elif defined BT_USE_NEON
- const long scalar_cutoff = 4;
- extern long (*_mindot_large)( const float *array, const float *vec, unsigned long array_count, float *dotOut );
- #else
- #error unhandled arch!
- #endif
-
- if( array_count < scalar_cutoff )
+#if (defined BT_USE_SSE && defined BT_USE_SIMD_VECTOR3 && defined BT_USE_SSE_IN_API) || defined(BT_USE_NEON)
+#if defined BT_USE_SSE
+ const long scalar_cutoff = 10;
+ long _mindot_large(const float* array, const float* vec, unsigned long array_count, float* dotOut);
+#elif defined BT_USE_NEON
+ const long scalar_cutoff = 4;
+ extern long (*_mindot_large)(const float* array, const float* vec, unsigned long array_count, float* dotOut);
+#else
+#error unhandled arch!
#endif
- {
- btScalar minDot = SIMD_INFINITY;
- int i = 0;
- int ptIndex = -1;
-
- for( i = 0; i < array_count; i++ )
- {
- btScalar dot = array[i].dot(*this);
-
- if( dot < minDot )
- {
- minDot = dot;
- ptIndex = i;
- }
- }
-
- dotOut = minDot;
-
- return ptIndex;
- }
-#if (defined BT_USE_SSE && defined BT_USE_SIMD_VECTOR3 && defined BT_USE_SSE_IN_API) || defined (BT_USE_NEON)
- return _mindot_large( (float*) array, (float*) &m_floats[0], array_count, &dotOut );
-#endif//BT_USE_SIMD_VECTOR3
-}
+ if (array_count < scalar_cutoff)
+#endif
+ {
+ btScalar minDot = SIMD_INFINITY;
+ int i = 0;
+ int ptIndex = -1;
+
+ for (i = 0; i < array_count; i++)
+ {
+ btScalar dot = array[i].dot(*this);
+
+ if (dot < minDot)
+ {
+ minDot = dot;
+ ptIndex = i;
+ }
+ }
+
+ dotOut = minDot;
+
+ return ptIndex;
+ }
+#if (defined BT_USE_SSE && defined BT_USE_SIMD_VECTOR3 && defined BT_USE_SSE_IN_API) || defined(BT_USE_NEON)
+ return _mindot_large((float*)array, (float*)&m_floats[0], array_count, &dotOut);
+#endif //BT_USE_SIMD_VECTOR3
+}
class btVector4 : public btVector3
{
public:
-
SIMD_FORCE_INLINE btVector4() {}
-
- SIMD_FORCE_INLINE btVector4(const btScalar& _x, const btScalar& _y, const btScalar& _z,const btScalar& _w)
- : btVector3(_x,_y,_z)
+ SIMD_FORCE_INLINE btVector4(const btScalar& _x, const btScalar& _y, const btScalar& _z, const btScalar& _w)
+ : btVector3(_x, _y, _z)
{
m_floats[3] = _w;
}
-#if (defined (BT_USE_SSE_IN_API)&& defined (BT_USE_SSE)) || defined (BT_USE_NEON)
+#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
SIMD_FORCE_INLINE btVector4(const btSimdFloat4 vec)
{
mVec128 = vec;
@@ -1112,34 +1092,32 @@ public:
mVec128 = rhs.mVec128;
}
- SIMD_FORCE_INLINE btVector4&
- operator=(const btVector4& v)
+ SIMD_FORCE_INLINE btVector4&
+ operator=(const btVector4& v)
{
mVec128 = v.mVec128;
return *this;
}
-#endif // #if defined (BT_USE_SSE_IN_API) || defined (BT_USE_NEON)
+#endif // #if defined (BT_USE_SSE_IN_API) || defined (BT_USE_NEON)
- SIMD_FORCE_INLINE btVector4 absolute4() const
+ SIMD_FORCE_INLINE btVector4 absolute4() const
{
-#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
return btVector4(_mm_and_ps(mVec128, btvAbsfMask));
#elif defined(BT_USE_NEON)
return btVector4(vabsq_f32(mVec128));
-#else
+#else
return btVector4(
- btFabs(m_floats[0]),
- btFabs(m_floats[1]),
+ btFabs(m_floats[0]),
+ btFabs(m_floats[1]),
btFabs(m_floats[2]),
btFabs(m_floats[3]));
#endif
}
+ btScalar getW() const { return m_floats[3]; }
- btScalar getW() const { return m_floats[3];}
-
-
- SIMD_FORCE_INLINE int maxAxis4() const
+ SIMD_FORCE_INLINE int maxAxis4() const
{
int maxIndex = -1;
btScalar maxVal = btScalar(-BT_LARGE_FLOAT);
@@ -1156,7 +1134,7 @@ public:
if (m_floats[2] > maxVal)
{
maxIndex = 2;
- maxVal =m_floats[2];
+ maxVal = m_floats[2];
}
if (m_floats[3] > maxVal)
{
@@ -1166,7 +1144,6 @@ public:
return maxIndex;
}
-
SIMD_FORCE_INLINE int minAxis4() const
{
int minIndex = -1;
@@ -1184,190 +1161,176 @@ public:
if (m_floats[2] < minVal)
{
minIndex = 2;
- minVal =m_floats[2];
+ minVal = m_floats[2];
}
if (m_floats[3] < minVal)
{
minIndex = 3;
}
-
+
return minIndex;
}
-
- SIMD_FORCE_INLINE int closestAxis4() const
+ SIMD_FORCE_INLINE int closestAxis4() const
{
return absolute4().maxAxis4();
}
-
-
-
- /**@brief Set x,y,z and zero w
+ /**@brief Set x,y,z and zero w
* @param x Value of x
* @param y Value of y
* @param z Value of z
*/
-
-/* void getValue(btScalar *m) const
+ /* void getValue(btScalar *m) const
{
m[0] = m_floats[0];
m[1] = m_floats[1];
m[2] =m_floats[2];
}
*/
-/**@brief Set the values
+ /**@brief Set the values
* @param x Value of x
* @param y Value of y
* @param z Value of z
* @param w Value of w
*/
- SIMD_FORCE_INLINE void setValue(const btScalar& _x, const btScalar& _y, const btScalar& _z,const btScalar& _w)
- {
- m_floats[0]=_x;
- m_floats[1]=_y;
- m_floats[2]=_z;
- m_floats[3]=_w;
- }
-
-
+ SIMD_FORCE_INLINE void setValue(const btScalar& _x, const btScalar& _y, const btScalar& _z, const btScalar& _w)
+ {
+ m_floats[0] = _x;
+ m_floats[1] = _y;
+ m_floats[2] = _z;
+ m_floats[3] = _w;
+ }
};
-
///btSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization
-SIMD_FORCE_INLINE void btSwapScalarEndian(const btScalar& sourceVal, btScalar& destVal)
+SIMD_FORCE_INLINE void btSwapScalarEndian(const btScalar& sourceVal, btScalar& destVal)
{
#ifdef BT_USE_DOUBLE_PRECISION
- unsigned char* dest = (unsigned char*) &destVal;
- const unsigned char* src = (const unsigned char*) &sourceVal;
+ unsigned char* dest = (unsigned char*)&destVal;
+ const unsigned char* src = (const unsigned char*)&sourceVal;
dest[0] = src[7];
- dest[1] = src[6];
- dest[2] = src[5];
- dest[3] = src[4];
- dest[4] = src[3];
- dest[5] = src[2];
- dest[6] = src[1];
- dest[7] = src[0];
+ dest[1] = src[6];
+ dest[2] = src[5];
+ dest[3] = src[4];
+ dest[4] = src[3];
+ dest[5] = src[2];
+ dest[6] = src[1];
+ dest[7] = src[0];
#else
- unsigned char* dest = (unsigned char*) &destVal;
- const unsigned char* src = (const unsigned char*) &sourceVal;
+ unsigned char* dest = (unsigned char*)&destVal;
+ const unsigned char* src = (const unsigned char*)&sourceVal;
dest[0] = src[3];
- dest[1] = src[2];
- dest[2] = src[1];
- dest[3] = src[0];
-#endif //BT_USE_DOUBLE_PRECISION
+ dest[1] = src[2];
+ dest[2] = src[1];
+ dest[3] = src[0];
+#endif //BT_USE_DOUBLE_PRECISION
}
///btSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization
-SIMD_FORCE_INLINE void btSwapVector3Endian(const btVector3& sourceVec, btVector3& destVec)
+SIMD_FORCE_INLINE void btSwapVector3Endian(const btVector3& sourceVec, btVector3& destVec)
{
- for (int i=0;i<4;i++)
+ for (int i = 0; i < 4; i++)
{
- btSwapScalarEndian(sourceVec[i],destVec[i]);
+ btSwapScalarEndian(sourceVec[i], destVec[i]);
}
-
}
///btUnSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization
-SIMD_FORCE_INLINE void btUnSwapVector3Endian(btVector3& vector)
+SIMD_FORCE_INLINE void btUnSwapVector3Endian(btVector3& vector)
{
-
- btVector3 swappedVec;
- for (int i=0;i<4;i++)
+ btVector3 swappedVec;
+ for (int i = 0; i < 4; i++)
{
- btSwapScalarEndian(vector[i],swappedVec[i]);
+ btSwapScalarEndian(vector[i], swappedVec[i]);
}
vector = swappedVec;
}
template <class T>
-SIMD_FORCE_INLINE void btPlaneSpace1 (const T& n, T& p, T& q)
+SIMD_FORCE_INLINE void btPlaneSpace1(const T& n, T& p, T& q)
{
- if (btFabs(n[2]) > SIMDSQRT12) {
- // choose p in y-z plane
- btScalar a = n[1]*n[1] + n[2]*n[2];
- btScalar k = btRecipSqrt (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
- btScalar a = n[0]*n[0] + n[1]*n[1];
- btScalar k = btRecipSqrt (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;
- }
+ if (btFabs(n[2]) > SIMDSQRT12)
+ {
+ // choose p in y-z plane
+ btScalar a = n[1] * n[1] + n[2] * n[2];
+ btScalar k = btRecipSqrt(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
+ btScalar a = n[0] * n[0] + n[1] * n[1];
+ btScalar k = btRecipSqrt(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;
+ }
}
-
-struct btVector3FloatData
+struct btVector3FloatData
{
- float m_floats[4];
+ float m_floats[4];
};
-struct btVector3DoubleData
+struct btVector3DoubleData
{
- double m_floats[4];
-
+ double m_floats[4];
};
-SIMD_FORCE_INLINE void btVector3::serializeFloat(struct btVector3FloatData& dataOut) const
+SIMD_FORCE_INLINE void btVector3::serializeFloat(struct btVector3FloatData& dataOut) const
{
///could also do a memcpy, check if it is worth it
- for (int i=0;i<4;i++)
+ for (int i = 0; i < 4; i++)
dataOut.m_floats[i] = float(m_floats[i]);
}
-SIMD_FORCE_INLINE void btVector3::deSerializeFloat(const struct btVector3FloatData& dataIn)
+SIMD_FORCE_INLINE void btVector3::deSerializeFloat(const struct btVector3FloatData& dataIn)
{
- for (int i=0;i<4;i++)
+ for (int i = 0; i < 4; i++)
m_floats[i] = btScalar(dataIn.m_floats[i]);
}
-
-SIMD_FORCE_INLINE void btVector3::serializeDouble(struct btVector3DoubleData& dataOut) const
+SIMD_FORCE_INLINE void btVector3::serializeDouble(struct btVector3DoubleData& dataOut) const
{
///could also do a memcpy, check if it is worth it
- for (int i=0;i<4;i++)
+ for (int i = 0; i < 4; i++)
dataOut.m_floats[i] = double(m_floats[i]);
}
-SIMD_FORCE_INLINE void btVector3::deSerializeDouble(const struct btVector3DoubleData& dataIn)
+SIMD_FORCE_INLINE void btVector3::deSerializeDouble(const struct btVector3DoubleData& dataIn)
{
- for (int i=0;i<4;i++)
+ for (int i = 0; i < 4; i++)
m_floats[i] = btScalar(dataIn.m_floats[i]);
}
-
-SIMD_FORCE_INLINE void btVector3::serialize(struct btVector3Data& dataOut) const
+SIMD_FORCE_INLINE void btVector3::serialize(struct btVector3Data& dataOut) const
{
///could also do a memcpy, check if it is worth it
- for (int i=0;i<4;i++)
+ for (int i = 0; i < 4; i++)
dataOut.m_floats[i] = m_floats[i];
}
-
-SIMD_FORCE_INLINE void btVector3::deSerialize(const struct btVector3FloatData& dataIn)
+SIMD_FORCE_INLINE void btVector3::deSerialize(const struct btVector3FloatData& dataIn)
{
- for (int i = 0; i<4; i++)
+ for (int i = 0; i < 4; i++)
m_floats[i] = (btScalar)dataIn.m_floats[i];
}
-
-SIMD_FORCE_INLINE void btVector3::deSerialize(const struct btVector3DoubleData& dataIn)
+SIMD_FORCE_INLINE void btVector3::deSerialize(const struct btVector3DoubleData& dataIn)
{
- for (int i=0;i<4;i++)
+ for (int i = 0; i < 4; i++)
m_floats[i] = (btScalar)dataIn.m_floats[i];
}
-#endif //BT_VECTOR3_H
+#endif //BT_VECTOR3_H
diff --git a/thirdparty/bullet/btBulletCollisionCommon.h b/thirdparty/bullet/btBulletCollisionCommon.h
index 948e02eb4c..4f523756a7 100644
--- a/thirdparty/bullet/btBulletCollisionCommon.h
+++ b/thirdparty/bullet/btBulletCollisionCommon.h
@@ -62,6 +62,4 @@ subject to the following restrictions:
#include "LinearMath/btIDebugDraw.h"
#include "LinearMath/btSerializer.h"
-
-#endif //BULLET_COLLISION_COMMON_H
-
+#endif //BULLET_COLLISION_COMMON_H
diff --git a/thirdparty/bullet/btBulletDynamicsCommon.h b/thirdparty/bullet/btBulletDynamicsCommon.h
index 50282bf210..a421fa4461 100644
--- a/thirdparty/bullet/btBulletDynamicsCommon.h
+++ b/thirdparty/bullet/btBulletDynamicsCommon.h
@@ -35,17 +35,9 @@ subject to the following restrictions:
#include "BulletDynamics/ConstraintSolver/btGearConstraint.h"
#include "BulletDynamics/ConstraintSolver/btFixedConstraint.h"
-
#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
-
///Vehicle simulation, with wheel contact simulated by raycasts
#include "BulletDynamics/Vehicle/btRaycastVehicle.h"
-
-
-
-
-
-#endif //BULLET_DYNAMICS_COMMON_H
-
+#endif //BULLET_DYNAMICS_COMMON_H
diff --git a/thirdparty/bullet/clew/clew.c b/thirdparty/bullet/clew/clew.c
index 5afc42a485..90caced535 100644
--- a/thirdparty/bullet/clew/clew.c
+++ b/thirdparty/bullet/clew/clew.c
@@ -9,23 +9,23 @@
#include "clew.h"
#ifdef _WIN32
- #define WIN32_LEAN_AND_MEAN
- #define VC_EXTRALEAN
- #include <windows.h>
+#define WIN32_LEAN_AND_MEAN
+#define VC_EXTRALEAN
+#include <windows.h>
- typedef HMODULE CLEW_DYNLIB_HANDLE;
+typedef HMODULE CLEW_DYNLIB_HANDLE;
- #define CLEW_DYNLIB_OPEN LoadLibraryA
- #define CLEW_DYNLIB_CLOSE FreeLibrary
- #define CLEW_DYNLIB_IMPORT GetProcAddress
+#define CLEW_DYNLIB_OPEN LoadLibraryA
+#define CLEW_DYNLIB_CLOSE FreeLibrary
+#define CLEW_DYNLIB_IMPORT GetProcAddress
#else
- #include <dlfcn.h>
-
- typedef void* CLEW_DYNLIB_HANDLE;
+#include <dlfcn.h>
- #define CLEW_DYNLIB_OPEN(path) dlopen(path, RTLD_NOW | RTLD_GLOBAL)
- #define CLEW_DYNLIB_CLOSE dlclose
- #define CLEW_DYNLIB_IMPORT dlsym
+typedef void* CLEW_DYNLIB_HANDLE;
+
+#define CLEW_DYNLIB_OPEN(path) dlopen(path, RTLD_NOW | RTLD_GLOBAL)
+#define CLEW_DYNLIB_CLOSE dlclose
+#define CLEW_DYNLIB_IMPORT dlsym
#endif
#include <stdlib.h>
@@ -34,279 +34,341 @@
static CLEW_DYNLIB_HANDLE module = NULL;
// Variables holding function entry points
-PFNCLGETPLATFORMIDS __clewGetPlatformIDs = NULL;
-PFNCLGETPLATFORMINFO __clewGetPlatformInfo = NULL;
-PFNCLGETDEVICEIDS __clewGetDeviceIDs = NULL;
-PFNCLGETDEVICEINFO __clewGetDeviceInfo = NULL;
-PFNCLCREATECONTEXT __clewCreateContext = NULL;
-PFNCLCREATECONTEXTFROMTYPE __clewCreateContextFromType = NULL;
-PFNCLRETAINCONTEXT __clewRetainContext = NULL;
-PFNCLRELEASECONTEXT __clewReleaseContext = NULL;
-PFNCLGETCONTEXTINFO __clewGetContextInfo = NULL;
-PFNCLCREATECOMMANDQUEUE __clewCreateCommandQueue = NULL;
-PFNCLRETAINCOMMANDQUEUE __clewRetainCommandQueue = NULL;
-PFNCLRELEASECOMMANDQUEUE __clewReleaseCommandQueue = NULL;
-PFNCLGETCOMMANDQUEUEINFO __clewGetCommandQueueInfo = NULL;
+PFNCLGETPLATFORMIDS __clewGetPlatformIDs = NULL;
+PFNCLGETPLATFORMINFO __clewGetPlatformInfo = NULL;
+PFNCLGETDEVICEIDS __clewGetDeviceIDs = NULL;
+PFNCLGETDEVICEINFO __clewGetDeviceInfo = NULL;
+PFNCLCREATECONTEXT __clewCreateContext = NULL;
+PFNCLCREATECONTEXTFROMTYPE __clewCreateContextFromType = NULL;
+PFNCLRETAINCONTEXT __clewRetainContext = NULL;
+PFNCLRELEASECONTEXT __clewReleaseContext = NULL;
+PFNCLGETCONTEXTINFO __clewGetContextInfo = NULL;
+PFNCLCREATECOMMANDQUEUE __clewCreateCommandQueue = NULL;
+PFNCLRETAINCOMMANDQUEUE __clewRetainCommandQueue = NULL;
+PFNCLRELEASECOMMANDQUEUE __clewReleaseCommandQueue = NULL;
+PFNCLGETCOMMANDQUEUEINFO __clewGetCommandQueueInfo = NULL;
#ifdef CL_USE_DEPRECATED_OPENCL_1_0_APIS
-PFNCLSETCOMMANDQUEUEPROPERTY __clewSetCommandQueueProperty = NULL;
+PFNCLSETCOMMANDQUEUEPROPERTY __clewSetCommandQueueProperty = NULL;
#endif
-PFNCLCREATEBUFFER __clewCreateBuffer = NULL;
-PFNCLCREATESUBBUFFER __clewCreateSubBuffer = NULL;
-PFNCLCREATEIMAGE2D __clewCreateImage2D = NULL;
-PFNCLCREATEIMAGE3D __clewCreateImage3D = NULL;
-PFNCLRETAINMEMOBJECT __clewRetainMemObject = NULL;
-PFNCLRELEASEMEMOBJECT __clewReleaseMemObject = NULL;
-PFNCLGETSUPPORTEDIMAGEFORMATS __clewGetSupportedImageFormats = NULL;
-PFNCLGETMEMOBJECTINFO __clewGetMemObjectInfo = NULL;
-PFNCLGETIMAGEINFO __clewGetImageInfo = NULL;
+PFNCLCREATEBUFFER __clewCreateBuffer = NULL;
+PFNCLCREATESUBBUFFER __clewCreateSubBuffer = NULL;
+PFNCLCREATEIMAGE2D __clewCreateImage2D = NULL;
+PFNCLCREATEIMAGE3D __clewCreateImage3D = NULL;
+PFNCLRETAINMEMOBJECT __clewRetainMemObject = NULL;
+PFNCLRELEASEMEMOBJECT __clewReleaseMemObject = NULL;
+PFNCLGETSUPPORTEDIMAGEFORMATS __clewGetSupportedImageFormats = NULL;
+PFNCLGETMEMOBJECTINFO __clewGetMemObjectInfo = NULL;
+PFNCLGETIMAGEINFO __clewGetImageInfo = NULL;
PFNCLSETMEMOBJECTDESTRUCTORCALLBACK __clewSetMemObjectDestructorCallback = NULL;
-PFNCLCREATESAMPLER __clewCreateSampler = NULL;
-PFNCLRETAINSAMPLER __clewRetainSampler = NULL;
-PFNCLRELEASESAMPLER __clewReleaseSampler = NULL;
-PFNCLGETSAMPLERINFO __clewGetSamplerInfo = NULL;
-PFNCLCREATEPROGRAMWITHSOURCE __clewCreateProgramWithSource = NULL;
-PFNCLCREATEPROGRAMWITHBINARY __clewCreateProgramWithBinary = NULL;
-PFNCLRETAINPROGRAM __clewRetainProgram = NULL;
-PFNCLRELEASEPROGRAM __clewReleaseProgram = NULL;
-PFNCLBUILDPROGRAM __clewBuildProgram = NULL;
-PFNCLUNLOADCOMPILER __clewUnloadCompiler = NULL;
-PFNCLGETPROGRAMINFO __clewGetProgramInfo = NULL;
-PFNCLGETPROGRAMBUILDINFO __clewGetProgramBuildInfo = NULL;
-PFNCLCREATEKERNEL __clewCreateKernel = NULL;
-PFNCLCREATEKERNELSINPROGRAM __clewCreateKernelsInProgram = NULL;
-PFNCLRETAINKERNEL __clewRetainKernel = NULL;
-PFNCLRELEASEKERNEL __clewReleaseKernel = NULL;
-PFNCLSETKERNELARG __clewSetKernelArg = NULL;
-PFNCLGETKERNELINFO __clewGetKernelInfo = NULL;
-PFNCLGETKERNELWORKGROUPINFO __clewGetKernelWorkGroupInfo = NULL;
-PFNCLWAITFOREVENTS __clewWaitForEvents = NULL;
-PFNCLGETEVENTINFO __clewGetEventInfo = NULL;
-PFNCLCREATEUSEREVENT __clewCreateUserEvent = NULL;
-PFNCLRETAINEVENT __clewRetainEvent = NULL;
-PFNCLRELEASEEVENT __clewReleaseEvent = NULL;
-PFNCLSETUSEREVENTSTATUS __clewSetUserEventStatus = NULL;
-PFNCLSETEVENTCALLBACK __clewSetEventCallback = NULL;
-PFNCLGETEVENTPROFILINGINFO __clewGetEventProfilingInfo = NULL;
-PFNCLFLUSH __clewFlush = NULL;
-PFNCLFINISH __clewFinish = NULL;
-PFNCLENQUEUEREADBUFFER __clewEnqueueReadBuffer = NULL;
-PFNCLENQUEUEREADBUFFERRECT __clewEnqueueReadBufferRect = NULL;
-PFNCLENQUEUEWRITEBUFFER __clewEnqueueWriteBuffer = NULL;
-PFNCLENQUEUEWRITEBUFFERRECT __clewEnqueueWriteBufferRect = NULL;
-PFNCLENQUEUECOPYBUFFER __clewEnqueueCopyBuffer = NULL;
-PFNCLENQUEUEREADIMAGE __clewEnqueueReadImage = NULL;
-PFNCLENQUEUEWRITEIMAGE __clewEnqueueWriteImage = NULL;
-PFNCLENQUEUECOPYIMAGE __clewEnqueueCopyImage = NULL;
-PFNCLENQUEUECOPYBUFFERRECT __clewEnqueueCopyBufferRect = NULL;
-PFNCLENQUEUECOPYIMAGETOBUFFER __clewEnqueueCopyImageToBuffer = NULL;
-PFNCLENQUEUECOPYBUFFERTOIMAGE __clewEnqueueCopyBufferToImage = NULL;
-PFNCLENQUEUEMAPBUFFER __clewEnqueueMapBuffer = NULL;
-PFNCLENQUEUEMAPIMAGE __clewEnqueueMapImage = NULL;
-PFNCLENQUEUEUNMAPMEMOBJECT __clewEnqueueUnmapMemObject = NULL;
-PFNCLENQUEUENDRANGEKERNEL __clewEnqueueNDRangeKernel = NULL;
-PFNCLENQUEUETASK __clewEnqueueTask = NULL;
-PFNCLENQUEUENATIVEKERNEL __clewEnqueueNativeKernel = NULL;
-PFNCLENQUEUEMARKER __clewEnqueueMarker = NULL;
-PFNCLENQUEUEWAITFOREVENTS __clewEnqueueWaitForEvents = NULL;
-PFNCLENQUEUEBARRIER __clewEnqueueBarrier = NULL;
-PFNCLGETEXTENSIONFUNCTIONADDRESS __clewGetExtensionFunctionAddress = NULL;
-
+PFNCLCREATESAMPLER __clewCreateSampler = NULL;
+PFNCLRETAINSAMPLER __clewRetainSampler = NULL;
+PFNCLRELEASESAMPLER __clewReleaseSampler = NULL;
+PFNCLGETSAMPLERINFO __clewGetSamplerInfo = NULL;
+PFNCLCREATEPROGRAMWITHSOURCE __clewCreateProgramWithSource = NULL;
+PFNCLCREATEPROGRAMWITHBINARY __clewCreateProgramWithBinary = NULL;
+PFNCLRETAINPROGRAM __clewRetainProgram = NULL;
+PFNCLRELEASEPROGRAM __clewReleaseProgram = NULL;
+PFNCLBUILDPROGRAM __clewBuildProgram = NULL;
+PFNCLUNLOADCOMPILER __clewUnloadCompiler = NULL;
+PFNCLGETPROGRAMINFO __clewGetProgramInfo = NULL;
+PFNCLGETPROGRAMBUILDINFO __clewGetProgramBuildInfo = NULL;
+PFNCLCREATEKERNEL __clewCreateKernel = NULL;
+PFNCLCREATEKERNELSINPROGRAM __clewCreateKernelsInProgram = NULL;
+PFNCLRETAINKERNEL __clewRetainKernel = NULL;
+PFNCLRELEASEKERNEL __clewReleaseKernel = NULL;
+PFNCLSETKERNELARG __clewSetKernelArg = NULL;
+PFNCLGETKERNELINFO __clewGetKernelInfo = NULL;
+PFNCLGETKERNELWORKGROUPINFO __clewGetKernelWorkGroupInfo = NULL;
+PFNCLWAITFOREVENTS __clewWaitForEvents = NULL;
+PFNCLGETEVENTINFO __clewGetEventInfo = NULL;
+PFNCLCREATEUSEREVENT __clewCreateUserEvent = NULL;
+PFNCLRETAINEVENT __clewRetainEvent = NULL;
+PFNCLRELEASEEVENT __clewReleaseEvent = NULL;
+PFNCLSETUSEREVENTSTATUS __clewSetUserEventStatus = NULL;
+PFNCLSETEVENTCALLBACK __clewSetEventCallback = NULL;
+PFNCLGETEVENTPROFILINGINFO __clewGetEventProfilingInfo = NULL;
+PFNCLFLUSH __clewFlush = NULL;
+PFNCLFINISH __clewFinish = NULL;
+PFNCLENQUEUEREADBUFFER __clewEnqueueReadBuffer = NULL;
+PFNCLENQUEUEREADBUFFERRECT __clewEnqueueReadBufferRect = NULL;
+PFNCLENQUEUEWRITEBUFFER __clewEnqueueWriteBuffer = NULL;
+PFNCLENQUEUEWRITEBUFFERRECT __clewEnqueueWriteBufferRect = NULL;
+PFNCLENQUEUECOPYBUFFER __clewEnqueueCopyBuffer = NULL;
+PFNCLENQUEUEREADIMAGE __clewEnqueueReadImage = NULL;
+PFNCLENQUEUEWRITEIMAGE __clewEnqueueWriteImage = NULL;
+PFNCLENQUEUECOPYIMAGE __clewEnqueueCopyImage = NULL;
+PFNCLENQUEUECOPYBUFFERRECT __clewEnqueueCopyBufferRect = NULL;
+PFNCLENQUEUECOPYIMAGETOBUFFER __clewEnqueueCopyImageToBuffer = NULL;
+PFNCLENQUEUECOPYBUFFERTOIMAGE __clewEnqueueCopyBufferToImage = NULL;
+PFNCLENQUEUEMAPBUFFER __clewEnqueueMapBuffer = NULL;
+PFNCLENQUEUEMAPIMAGE __clewEnqueueMapImage = NULL;
+PFNCLENQUEUEUNMAPMEMOBJECT __clewEnqueueUnmapMemObject = NULL;
+PFNCLENQUEUENDRANGEKERNEL __clewEnqueueNDRangeKernel = NULL;
+PFNCLENQUEUETASK __clewEnqueueTask = NULL;
+PFNCLENQUEUENATIVEKERNEL __clewEnqueueNativeKernel = NULL;
+PFNCLENQUEUEMARKER __clewEnqueueMarker = NULL;
+PFNCLENQUEUEWAITFOREVENTS __clewEnqueueWaitForEvents = NULL;
+PFNCLENQUEUEBARRIER __clewEnqueueBarrier = NULL;
+PFNCLGETEXTENSIONFUNCTIONADDRESS __clewGetExtensionFunctionAddress = NULL;
void clewExit(void)
{
- if (module != NULL)
- {
- // Ignore errors
- CLEW_DYNLIB_CLOSE(module);
- module = NULL;
- }
+ if (module != NULL)
+ {
+ // Ignore errors
+ CLEW_DYNLIB_CLOSE(module);
+ module = NULL;
+ }
}
int clewInit(const char* path)
{
- int error = 0;
+ int error = 0;
- // Check if already initialized
- if (module != NULL)
- {
- return CLEW_SUCCESS;
- }
+ // Check if already initialized
+ if (module != NULL)
+ {
+ return CLEW_SUCCESS;
+ }
- // Load library
- module = CLEW_DYNLIB_OPEN(path);
+ // Load library
+ module = CLEW_DYNLIB_OPEN(path);
- // Check for errors
- if (module == NULL)
- {
- return CLEW_ERROR_OPEN_FAILED;
- }
+ // Check for errors
+ if (module == NULL)
+ {
+ return CLEW_ERROR_OPEN_FAILED;
+ }
- // Set unloading
- error = atexit(clewExit);
+ // Set unloading
+ error = atexit(clewExit);
- if (error)
- {
- // Failure queuing atexit, shutdown with error
- CLEW_DYNLIB_CLOSE(module);
- module = NULL;
+ if (error)
+ {
+ // Failure queuing atexit, shutdown with error
+ CLEW_DYNLIB_CLOSE(module);
+ module = NULL;
- return CLEW_ERROR_ATEXIT_FAILED;
- }
+ return CLEW_ERROR_ATEXIT_FAILED;
+ }
- // Determine function entry-points
- __clewGetPlatformIDs = (PFNCLGETPLATFORMIDS )CLEW_DYNLIB_IMPORT(module, "clGetPlatformIDs");
- __clewGetPlatformInfo = (PFNCLGETPLATFORMINFO )CLEW_DYNLIB_IMPORT(module, "clGetPlatformInfo");
- __clewGetDeviceIDs = (PFNCLGETDEVICEIDS )CLEW_DYNLIB_IMPORT(module, "clGetDeviceIDs");
- __clewGetDeviceInfo = (PFNCLGETDEVICEINFO )CLEW_DYNLIB_IMPORT(module, "clGetDeviceInfo");
- __clewCreateContext = (PFNCLCREATECONTEXT )CLEW_DYNLIB_IMPORT(module, "clCreateContext");
- __clewCreateContextFromType = (PFNCLCREATECONTEXTFROMTYPE )CLEW_DYNLIB_IMPORT(module, "clCreateContextFromType");
- __clewRetainContext = (PFNCLRETAINCONTEXT )CLEW_DYNLIB_IMPORT(module, "clRetainContext");
- __clewReleaseContext = (PFNCLRELEASECONTEXT )CLEW_DYNLIB_IMPORT(module, "clReleaseContext");
- __clewGetContextInfo = (PFNCLGETCONTEXTINFO )CLEW_DYNLIB_IMPORT(module, "clGetContextInfo");
- __clewCreateCommandQueue = (PFNCLCREATECOMMANDQUEUE )CLEW_DYNLIB_IMPORT(module, "clCreateCommandQueue");
- __clewRetainCommandQueue = (PFNCLRETAINCOMMANDQUEUE )CLEW_DYNLIB_IMPORT(module, "clRetainCommandQueue");
- __clewReleaseCommandQueue = (PFNCLRELEASECOMMANDQUEUE )CLEW_DYNLIB_IMPORT(module, "clReleaseCommandQueue");
- __clewGetCommandQueueInfo = (PFNCLGETCOMMANDQUEUEINFO )CLEW_DYNLIB_IMPORT(module, "clGetCommandQueueInfo");
+ // Determine function entry-points
+ __clewGetPlatformIDs = (PFNCLGETPLATFORMIDS)CLEW_DYNLIB_IMPORT(module, "clGetPlatformIDs");
+ __clewGetPlatformInfo = (PFNCLGETPLATFORMINFO)CLEW_DYNLIB_IMPORT(module, "clGetPlatformInfo");
+ __clewGetDeviceIDs = (PFNCLGETDEVICEIDS)CLEW_DYNLIB_IMPORT(module, "clGetDeviceIDs");
+ __clewGetDeviceInfo = (PFNCLGETDEVICEINFO)CLEW_DYNLIB_IMPORT(module, "clGetDeviceInfo");
+ __clewCreateContext = (PFNCLCREATECONTEXT)CLEW_DYNLIB_IMPORT(module, "clCreateContext");
+ __clewCreateContextFromType = (PFNCLCREATECONTEXTFROMTYPE)CLEW_DYNLIB_IMPORT(module, "clCreateContextFromType");
+ __clewRetainContext = (PFNCLRETAINCONTEXT)CLEW_DYNLIB_IMPORT(module, "clRetainContext");
+ __clewReleaseContext = (PFNCLRELEASECONTEXT)CLEW_DYNLIB_IMPORT(module, "clReleaseContext");
+ __clewGetContextInfo = (PFNCLGETCONTEXTINFO)CLEW_DYNLIB_IMPORT(module, "clGetContextInfo");
+ __clewCreateCommandQueue = (PFNCLCREATECOMMANDQUEUE)CLEW_DYNLIB_IMPORT(module, "clCreateCommandQueue");
+ __clewRetainCommandQueue = (PFNCLRETAINCOMMANDQUEUE)CLEW_DYNLIB_IMPORT(module, "clRetainCommandQueue");
+ __clewReleaseCommandQueue = (PFNCLRELEASECOMMANDQUEUE)CLEW_DYNLIB_IMPORT(module, "clReleaseCommandQueue");
+ __clewGetCommandQueueInfo = (PFNCLGETCOMMANDQUEUEINFO)CLEW_DYNLIB_IMPORT(module, "clGetCommandQueueInfo");
#ifdef CL_USE_DEPRECATED_OPENCL_1_0_APIS
- __clewSetCommandQueueProperty = (PFNCLSETCOMMANDQUEUEPROPERTY )CLEW_DYNLIB_IMPORT(module, "clSetCommandQueueProperty");
+ __clewSetCommandQueueProperty = (PFNCLSETCOMMANDQUEUEPROPERTY)CLEW_DYNLIB_IMPORT(module, "clSetCommandQueueProperty");
#endif
- __clewCreateBuffer = (PFNCLCREATEBUFFER )CLEW_DYNLIB_IMPORT(module, "clCreateBuffer");
- __clewCreateSubBuffer = (PFNCLCREATESUBBUFFER )CLEW_DYNLIB_IMPORT(module, "clCreateBuffer");
- __clewCreateImage2D = (PFNCLCREATEIMAGE2D )CLEW_DYNLIB_IMPORT(module, "clCreateImage2D");
- __clewCreateImage3D = (PFNCLCREATEIMAGE3D )CLEW_DYNLIB_IMPORT(module, "clCreateImage3D");
- __clewRetainMemObject = (PFNCLRETAINMEMOBJECT )CLEW_DYNLIB_IMPORT(module, "clRetainMemObject");
- __clewReleaseMemObject = (PFNCLRELEASEMEMOBJECT )CLEW_DYNLIB_IMPORT(module, "clReleaseMemObject");
- __clewGetSupportedImageFormats = (PFNCLGETSUPPORTEDIMAGEFORMATS )CLEW_DYNLIB_IMPORT(module, "clGetSupportedImageFormats");
- __clewGetMemObjectInfo = (PFNCLGETMEMOBJECTINFO )CLEW_DYNLIB_IMPORT(module, "clGetMemObjectInfo");
- __clewGetImageInfo = (PFNCLGETIMAGEINFO )CLEW_DYNLIB_IMPORT(module, "clGetImageInfo");
- __clewSetMemObjectDestructorCallback = (PFNCLSETMEMOBJECTDESTRUCTORCALLBACK)CLEW_DYNLIB_IMPORT(module, "clSetMemObjectDestructorCallback");
- __clewCreateSampler = (PFNCLCREATESAMPLER )CLEW_DYNLIB_IMPORT(module, "clCreateSampler");
- __clewRetainSampler = (PFNCLRETAINSAMPLER )CLEW_DYNLIB_IMPORT(module, "clRetainSampler");
- __clewReleaseSampler = (PFNCLRELEASESAMPLER )CLEW_DYNLIB_IMPORT(module, "clReleaseSampler");
- __clewGetSamplerInfo = (PFNCLGETSAMPLERINFO )CLEW_DYNLIB_IMPORT(module, "clGetSamplerInfo");
- __clewCreateProgramWithSource = (PFNCLCREATEPROGRAMWITHSOURCE )CLEW_DYNLIB_IMPORT(module, "clCreateProgramWithSource");
- __clewCreateProgramWithBinary = (PFNCLCREATEPROGRAMWITHBINARY )CLEW_DYNLIB_IMPORT(module, "clCreateProgramWithBinary");
- __clewRetainProgram = (PFNCLRETAINPROGRAM )CLEW_DYNLIB_IMPORT(module, "clRetainProgram");
- __clewReleaseProgram = (PFNCLRELEASEPROGRAM )CLEW_DYNLIB_IMPORT(module, "clReleaseProgram");
- __clewBuildProgram = (PFNCLBUILDPROGRAM )CLEW_DYNLIB_IMPORT(module, "clBuildProgram");
- __clewUnloadCompiler = (PFNCLUNLOADCOMPILER )CLEW_DYNLIB_IMPORT(module, "clUnloadCompiler");
- __clewGetProgramInfo = (PFNCLGETPROGRAMINFO )CLEW_DYNLIB_IMPORT(module, "clGetProgramInfo");
- __clewGetProgramBuildInfo = (PFNCLGETPROGRAMBUILDINFO )CLEW_DYNLIB_IMPORT(module, "clGetProgramBuildInfo");
- __clewCreateKernel = (PFNCLCREATEKERNEL )CLEW_DYNLIB_IMPORT(module, "clCreateKernel");
- __clewCreateKernelsInProgram = (PFNCLCREATEKERNELSINPROGRAM )CLEW_DYNLIB_IMPORT(module, "clCreateKernelsInProgram");
- __clewRetainKernel = (PFNCLRETAINKERNEL )CLEW_DYNLIB_IMPORT(module, "clRetainKernel");
- __clewReleaseKernel = (PFNCLRELEASEKERNEL )CLEW_DYNLIB_IMPORT(module, "clReleaseKernel");
- __clewSetKernelArg = (PFNCLSETKERNELARG )CLEW_DYNLIB_IMPORT(module, "clSetKernelArg");
- __clewGetKernelInfo = (PFNCLGETKERNELINFO )CLEW_DYNLIB_IMPORT(module, "clGetKernelInfo");
- __clewGetKernelWorkGroupInfo = (PFNCLGETKERNELWORKGROUPINFO )CLEW_DYNLIB_IMPORT(module, "clGetKernelWorkGroupInfo");
- __clewWaitForEvents = (PFNCLWAITFOREVENTS )CLEW_DYNLIB_IMPORT(module, "clWaitForEvents");
- __clewGetEventInfo = (PFNCLGETEVENTINFO )CLEW_DYNLIB_IMPORT(module, "clGetEventInfo");
- __clewCreateUserEvent = (PFNCLCREATEUSEREVENT )CLEW_DYNLIB_IMPORT(module, "clCreateUserEvent");
- __clewRetainEvent = (PFNCLRETAINEVENT )CLEW_DYNLIB_IMPORT(module, "clRetainEvent");
- __clewReleaseEvent = (PFNCLRELEASEEVENT )CLEW_DYNLIB_IMPORT(module, "clReleaseEvent");
- __clewSetUserEventStatus = (PFNCLSETUSEREVENTSTATUS )CLEW_DYNLIB_IMPORT(module, "clSetUserEventStatus");
- __clewSetEventCallback = (PFNCLSETEVENTCALLBACK )CLEW_DYNLIB_IMPORT(module, "clSetEventCallback");
- __clewGetEventProfilingInfo = (PFNCLGETEVENTPROFILINGINFO )CLEW_DYNLIB_IMPORT(module, "clGetEventProfilingInfo");
- __clewFlush = (PFNCLFLUSH )CLEW_DYNLIB_IMPORT(module, "clFlush");
- __clewFinish = (PFNCLFINISH )CLEW_DYNLIB_IMPORT(module, "clFinish");
- __clewEnqueueReadBuffer = (PFNCLENQUEUEREADBUFFER )CLEW_DYNLIB_IMPORT(module, "clEnqueueReadBuffer");
- __clewEnqueueReadBufferRect = (PFNCLENQUEUEREADBUFFERRECT )CLEW_DYNLIB_IMPORT(module, "clEnqueueReadBufferRect");
- __clewEnqueueWriteBuffer = (PFNCLENQUEUEWRITEBUFFER )CLEW_DYNLIB_IMPORT(module, "clEnqueueWriteBuffer");
- __clewEnqueueWriteBufferRect = (PFNCLENQUEUEWRITEBUFFERRECT )CLEW_DYNLIB_IMPORT(module, "clEnqueueWriteBufferRect");
- __clewEnqueueCopyBuffer = (PFNCLENQUEUECOPYBUFFER )CLEW_DYNLIB_IMPORT(module, "clEnqueueCopyBuffer");
- __clewEnqueueCopyBufferRect = (PFNCLENQUEUECOPYBUFFERRECT )CLEW_DYNLIB_IMPORT(module, "clEnqueueCopyBufferRect");
- __clewEnqueueReadImage = (PFNCLENQUEUEREADIMAGE )CLEW_DYNLIB_IMPORT(module, "clEnqueueReadImage");
- __clewEnqueueWriteImage = (PFNCLENQUEUEWRITEIMAGE )CLEW_DYNLIB_IMPORT(module, "clEnqueueWriteImage");
- __clewEnqueueCopyImage = (PFNCLENQUEUECOPYIMAGE )CLEW_DYNLIB_IMPORT(module, "clEnqueueCopyImage");
- __clewEnqueueCopyImageToBuffer = (PFNCLENQUEUECOPYIMAGETOBUFFER )CLEW_DYNLIB_IMPORT(module, "clEnqueueCopyImageToBuffer");
- __clewEnqueueCopyBufferToImage = (PFNCLENQUEUECOPYBUFFERTOIMAGE )CLEW_DYNLIB_IMPORT(module, "clEnqueueCopyBufferToImage");
- __clewEnqueueMapBuffer = (PFNCLENQUEUEMAPBUFFER )CLEW_DYNLIB_IMPORT(module, "clEnqueueMapBuffer");
- __clewEnqueueMapImage = (PFNCLENQUEUEMAPIMAGE )CLEW_DYNLIB_IMPORT(module, "clEnqueueMapImage");
- __clewEnqueueUnmapMemObject = (PFNCLENQUEUEUNMAPMEMOBJECT )CLEW_DYNLIB_IMPORT(module, "clEnqueueUnmapMemObject");
- __clewEnqueueNDRangeKernel = (PFNCLENQUEUENDRANGEKERNEL )CLEW_DYNLIB_IMPORT(module, "clEnqueueNDRangeKernel");
- __clewEnqueueTask = (PFNCLENQUEUETASK )CLEW_DYNLIB_IMPORT(module, "clEnqueueTask");
- __clewEnqueueNativeKernel = (PFNCLENQUEUENATIVEKERNEL )CLEW_DYNLIB_IMPORT(module, "clEnqueueNativeKernel");
- __clewEnqueueMarker = (PFNCLENQUEUEMARKER )CLEW_DYNLIB_IMPORT(module, "clEnqueueMarker");
- __clewEnqueueWaitForEvents = (PFNCLENQUEUEWAITFOREVENTS )CLEW_DYNLIB_IMPORT(module, "clEnqueueWaitForEvents");
- __clewEnqueueBarrier = (PFNCLENQUEUEBARRIER )CLEW_DYNLIB_IMPORT(module, "clEnqueueBarrier");
- __clewGetExtensionFunctionAddress = (PFNCLGETEXTENSIONFUNCTIONADDRESS )CLEW_DYNLIB_IMPORT(module, "clGetExtensionFunctionAddress");
+ __clewCreateBuffer = (PFNCLCREATEBUFFER)CLEW_DYNLIB_IMPORT(module, "clCreateBuffer");
+ __clewCreateSubBuffer = (PFNCLCREATESUBBUFFER)CLEW_DYNLIB_IMPORT(module, "clCreateBuffer");
+ __clewCreateImage2D = (PFNCLCREATEIMAGE2D)CLEW_DYNLIB_IMPORT(module, "clCreateImage2D");
+ __clewCreateImage3D = (PFNCLCREATEIMAGE3D)CLEW_DYNLIB_IMPORT(module, "clCreateImage3D");
+ __clewRetainMemObject = (PFNCLRETAINMEMOBJECT)CLEW_DYNLIB_IMPORT(module, "clRetainMemObject");
+ __clewReleaseMemObject = (PFNCLRELEASEMEMOBJECT)CLEW_DYNLIB_IMPORT(module, "clReleaseMemObject");
+ __clewGetSupportedImageFormats = (PFNCLGETSUPPORTEDIMAGEFORMATS)CLEW_DYNLIB_IMPORT(module, "clGetSupportedImageFormats");
+ __clewGetMemObjectInfo = (PFNCLGETMEMOBJECTINFO)CLEW_DYNLIB_IMPORT(module, "clGetMemObjectInfo");
+ __clewGetImageInfo = (PFNCLGETIMAGEINFO)CLEW_DYNLIB_IMPORT(module, "clGetImageInfo");
+ __clewSetMemObjectDestructorCallback = (PFNCLSETMEMOBJECTDESTRUCTORCALLBACK)CLEW_DYNLIB_IMPORT(module, "clSetMemObjectDestructorCallback");
+ __clewCreateSampler = (PFNCLCREATESAMPLER)CLEW_DYNLIB_IMPORT(module, "clCreateSampler");
+ __clewRetainSampler = (PFNCLRETAINSAMPLER)CLEW_DYNLIB_IMPORT(module, "clRetainSampler");
+ __clewReleaseSampler = (PFNCLRELEASESAMPLER)CLEW_DYNLIB_IMPORT(module, "clReleaseSampler");
+ __clewGetSamplerInfo = (PFNCLGETSAMPLERINFO)CLEW_DYNLIB_IMPORT(module, "clGetSamplerInfo");
+ __clewCreateProgramWithSource = (PFNCLCREATEPROGRAMWITHSOURCE)CLEW_DYNLIB_IMPORT(module, "clCreateProgramWithSource");
+ __clewCreateProgramWithBinary = (PFNCLCREATEPROGRAMWITHBINARY)CLEW_DYNLIB_IMPORT(module, "clCreateProgramWithBinary");
+ __clewRetainProgram = (PFNCLRETAINPROGRAM)CLEW_DYNLIB_IMPORT(module, "clRetainProgram");
+ __clewReleaseProgram = (PFNCLRELEASEPROGRAM)CLEW_DYNLIB_IMPORT(module, "clReleaseProgram");
+ __clewBuildProgram = (PFNCLBUILDPROGRAM)CLEW_DYNLIB_IMPORT(module, "clBuildProgram");
+ __clewUnloadCompiler = (PFNCLUNLOADCOMPILER)CLEW_DYNLIB_IMPORT(module, "clUnloadCompiler");
+ __clewGetProgramInfo = (PFNCLGETPROGRAMINFO)CLEW_DYNLIB_IMPORT(module, "clGetProgramInfo");
+ __clewGetProgramBuildInfo = (PFNCLGETPROGRAMBUILDINFO)CLEW_DYNLIB_IMPORT(module, "clGetProgramBuildInfo");
+ __clewCreateKernel = (PFNCLCREATEKERNEL)CLEW_DYNLIB_IMPORT(module, "clCreateKernel");
+ __clewCreateKernelsInProgram = (PFNCLCREATEKERNELSINPROGRAM)CLEW_DYNLIB_IMPORT(module, "clCreateKernelsInProgram");
+ __clewRetainKernel = (PFNCLRETAINKERNEL)CLEW_DYNLIB_IMPORT(module, "clRetainKernel");
+ __clewReleaseKernel = (PFNCLRELEASEKERNEL)CLEW_DYNLIB_IMPORT(module, "clReleaseKernel");
+ __clewSetKernelArg = (PFNCLSETKERNELARG)CLEW_DYNLIB_IMPORT(module, "clSetKernelArg");
+ __clewGetKernelInfo = (PFNCLGETKERNELINFO)CLEW_DYNLIB_IMPORT(module, "clGetKernelInfo");
+ __clewGetKernelWorkGroupInfo = (PFNCLGETKERNELWORKGROUPINFO)CLEW_DYNLIB_IMPORT(module, "clGetKernelWorkGroupInfo");
+ __clewWaitForEvents = (PFNCLWAITFOREVENTS)CLEW_DYNLIB_IMPORT(module, "clWaitForEvents");
+ __clewGetEventInfo = (PFNCLGETEVENTINFO)CLEW_DYNLIB_IMPORT(module, "clGetEventInfo");
+ __clewCreateUserEvent = (PFNCLCREATEUSEREVENT)CLEW_DYNLIB_IMPORT(module, "clCreateUserEvent");
+ __clewRetainEvent = (PFNCLRETAINEVENT)CLEW_DYNLIB_IMPORT(module, "clRetainEvent");
+ __clewReleaseEvent = (PFNCLRELEASEEVENT)CLEW_DYNLIB_IMPORT(module, "clReleaseEvent");
+ __clewSetUserEventStatus = (PFNCLSETUSEREVENTSTATUS)CLEW_DYNLIB_IMPORT(module, "clSetUserEventStatus");
+ __clewSetEventCallback = (PFNCLSETEVENTCALLBACK)CLEW_DYNLIB_IMPORT(module, "clSetEventCallback");
+ __clewGetEventProfilingInfo = (PFNCLGETEVENTPROFILINGINFO)CLEW_DYNLIB_IMPORT(module, "clGetEventProfilingInfo");
+ __clewFlush = (PFNCLFLUSH)CLEW_DYNLIB_IMPORT(module, "clFlush");
+ __clewFinish = (PFNCLFINISH)CLEW_DYNLIB_IMPORT(module, "clFinish");
+ __clewEnqueueReadBuffer = (PFNCLENQUEUEREADBUFFER)CLEW_DYNLIB_IMPORT(module, "clEnqueueReadBuffer");
+ __clewEnqueueReadBufferRect = (PFNCLENQUEUEREADBUFFERRECT)CLEW_DYNLIB_IMPORT(module, "clEnqueueReadBufferRect");
+ __clewEnqueueWriteBuffer = (PFNCLENQUEUEWRITEBUFFER)CLEW_DYNLIB_IMPORT(module, "clEnqueueWriteBuffer");
+ __clewEnqueueWriteBufferRect = (PFNCLENQUEUEWRITEBUFFERRECT)CLEW_DYNLIB_IMPORT(module, "clEnqueueWriteBufferRect");
+ __clewEnqueueCopyBuffer = (PFNCLENQUEUECOPYBUFFER)CLEW_DYNLIB_IMPORT(module, "clEnqueueCopyBuffer");
+ __clewEnqueueCopyBufferRect = (PFNCLENQUEUECOPYBUFFERRECT)CLEW_DYNLIB_IMPORT(module, "clEnqueueCopyBufferRect");
+ __clewEnqueueReadImage = (PFNCLENQUEUEREADIMAGE)CLEW_DYNLIB_IMPORT(module, "clEnqueueReadImage");
+ __clewEnqueueWriteImage = (PFNCLENQUEUEWRITEIMAGE)CLEW_DYNLIB_IMPORT(module, "clEnqueueWriteImage");
+ __clewEnqueueCopyImage = (PFNCLENQUEUECOPYIMAGE)CLEW_DYNLIB_IMPORT(module, "clEnqueueCopyImage");
+ __clewEnqueueCopyImageToBuffer = (PFNCLENQUEUECOPYIMAGETOBUFFER)CLEW_DYNLIB_IMPORT(module, "clEnqueueCopyImageToBuffer");
+ __clewEnqueueCopyBufferToImage = (PFNCLENQUEUECOPYBUFFERTOIMAGE)CLEW_DYNLIB_IMPORT(module, "clEnqueueCopyBufferToImage");
+ __clewEnqueueMapBuffer = (PFNCLENQUEUEMAPBUFFER)CLEW_DYNLIB_IMPORT(module, "clEnqueueMapBuffer");
+ __clewEnqueueMapImage = (PFNCLENQUEUEMAPIMAGE)CLEW_DYNLIB_IMPORT(module, "clEnqueueMapImage");
+ __clewEnqueueUnmapMemObject = (PFNCLENQUEUEUNMAPMEMOBJECT)CLEW_DYNLIB_IMPORT(module, "clEnqueueUnmapMemObject");
+ __clewEnqueueNDRangeKernel = (PFNCLENQUEUENDRANGEKERNEL)CLEW_DYNLIB_IMPORT(module, "clEnqueueNDRangeKernel");
+ __clewEnqueueTask = (PFNCLENQUEUETASK)CLEW_DYNLIB_IMPORT(module, "clEnqueueTask");
+ __clewEnqueueNativeKernel = (PFNCLENQUEUENATIVEKERNEL)CLEW_DYNLIB_IMPORT(module, "clEnqueueNativeKernel");
+ __clewEnqueueMarker = (PFNCLENQUEUEMARKER)CLEW_DYNLIB_IMPORT(module, "clEnqueueMarker");
+ __clewEnqueueWaitForEvents = (PFNCLENQUEUEWAITFOREVENTS)CLEW_DYNLIB_IMPORT(module, "clEnqueueWaitForEvents");
+ __clewEnqueueBarrier = (PFNCLENQUEUEBARRIER)CLEW_DYNLIB_IMPORT(module, "clEnqueueBarrier");
+ __clewGetExtensionFunctionAddress = (PFNCLGETEXTENSIONFUNCTIONADDRESS)CLEW_DYNLIB_IMPORT(module, "clGetExtensionFunctionAddress");
- return CLEW_SUCCESS;
+ return CLEW_SUCCESS;
}
const char* clewErrorString(cl_int error)
{
- static const char* strings[] =
- {
- // Error Codes
- "CL_SUCCESS" // 0
- , "CL_DEVICE_NOT_FOUND" // -1
- , "CL_DEVICE_NOT_AVAILABLE" // -2
- , "CL_COMPILER_NOT_AVAILABLE" // -3
- , "CL_MEM_OBJECT_ALLOCATION_FAILURE" // -4
- , "CL_OUT_OF_RESOURCES" // -5
- , "CL_OUT_OF_HOST_MEMORY" // -6
- , "CL_PROFILING_INFO_NOT_AVAILABLE" // -7
- , "CL_MEM_COPY_OVERLAP" // -8
- , "CL_IMAGE_FORMAT_MISMATCH" // -9
- , "CL_IMAGE_FORMAT_NOT_SUPPORTED" // -10
- , "CL_BUILD_PROGRAM_FAILURE" // -11
- , "CL_MAP_FAILURE" // -12
+ static const char* strings[] =
+ {
+ // Error Codes
+ "CL_SUCCESS" // 0
+ ,
+ "CL_DEVICE_NOT_FOUND" // -1
+ ,
+ "CL_DEVICE_NOT_AVAILABLE" // -2
+ ,
+ "CL_COMPILER_NOT_AVAILABLE" // -3
+ ,
+ "CL_MEM_OBJECT_ALLOCATION_FAILURE" // -4
+ ,
+ "CL_OUT_OF_RESOURCES" // -5
+ ,
+ "CL_OUT_OF_HOST_MEMORY" // -6
+ ,
+ "CL_PROFILING_INFO_NOT_AVAILABLE" // -7
+ ,
+ "CL_MEM_COPY_OVERLAP" // -8
+ ,
+ "CL_IMAGE_FORMAT_MISMATCH" // -9
+ ,
+ "CL_IMAGE_FORMAT_NOT_SUPPORTED" // -10
+ ,
+ "CL_BUILD_PROGRAM_FAILURE" // -11
+ ,
+ "CL_MAP_FAILURE" // -12
- , "" // -13
- , "" // -14
- , "" // -15
- , "" // -16
- , "" // -17
- , "" // -18
- , "" // -19
+ ,
+ "" // -13
+ ,
+ "" // -14
+ ,
+ "" // -15
+ ,
+ "" // -16
+ ,
+ "" // -17
+ ,
+ "" // -18
+ ,
+ "" // -19
- , "" // -20
- , "" // -21
- , "" // -22
- , "" // -23
- , "" // -24
- , "" // -25
- , "" // -26
- , "" // -27
- , "" // -28
- , "" // -29
+ ,
+ "" // -20
+ ,
+ "" // -21
+ ,
+ "" // -22
+ ,
+ "" // -23
+ ,
+ "" // -24
+ ,
+ "" // -25
+ ,
+ "" // -26
+ ,
+ "" // -27
+ ,
+ "" // -28
+ ,
+ "" // -29
- , "CL_INVALID_VALUE" // -30
- , "CL_INVALID_DEVICE_TYPE" // -31
- , "CL_INVALID_PLATFORM" // -32
- , "CL_INVALID_DEVICE" // -33
- , "CL_INVALID_CONTEXT" // -34
- , "CL_INVALID_QUEUE_PROPERTIES" // -35
- , "CL_INVALID_COMMAND_QUEUE" // -36
- , "CL_INVALID_HOST_PTR" // -37
- , "CL_INVALID_MEM_OBJECT" // -38
- , "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR" // -39
- , "CL_INVALID_IMAGE_SIZE" // -40
- , "CL_INVALID_SAMPLER" // -41
- , "CL_INVALID_BINARY" // -42
- , "CL_INVALID_BUILD_OPTIONS" // -43
- , "CL_INVALID_PROGRAM" // -44
- , "CL_INVALID_PROGRAM_EXECUTABLE" // -45
- , "CL_INVALID_KERNEL_NAME" // -46
- , "CL_INVALID_KERNEL_DEFINITION" // -47
- , "CL_INVALID_KERNEL" // -48
- , "CL_INVALID_ARG_INDEX" // -49
- , "CL_INVALID_ARG_VALUE" // -50
- , "CL_INVALID_ARG_SIZE" // -51
- , "CL_INVALID_KERNEL_ARGS" // -52
- , "CL_INVALID_WORK_DIMENSION" // -53
- , "CL_INVALID_WORK_GROUP_SIZE" // -54
- , "CL_INVALID_WORK_ITEM_SIZE" // -55
- , "CL_INVALID_GLOBAL_OFFSET" // -56
- , "CL_INVALID_EVENT_WAIT_LIST" // -57
- , "CL_INVALID_EVENT" // -58
- , "CL_INVALID_OPERATION" // -59
- , "CL_INVALID_GL_OBJECT" // -60
- , "CL_INVALID_BUFFER_SIZE" // -61
- , "CL_INVALID_MIP_LEVEL" // -62
- , "CL_INVALID_GLOBAL_WORK_SIZE" // -63
- };
+ ,
+ "CL_INVALID_VALUE" // -30
+ ,
+ "CL_INVALID_DEVICE_TYPE" // -31
+ ,
+ "CL_INVALID_PLATFORM" // -32
+ ,
+ "CL_INVALID_DEVICE" // -33
+ ,
+ "CL_INVALID_CONTEXT" // -34
+ ,
+ "CL_INVALID_QUEUE_PROPERTIES" // -35
+ ,
+ "CL_INVALID_COMMAND_QUEUE" // -36
+ ,
+ "CL_INVALID_HOST_PTR" // -37
+ ,
+ "CL_INVALID_MEM_OBJECT" // -38
+ ,
+ "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR" // -39
+ ,
+ "CL_INVALID_IMAGE_SIZE" // -40
+ ,
+ "CL_INVALID_SAMPLER" // -41
+ ,
+ "CL_INVALID_BINARY" // -42
+ ,
+ "CL_INVALID_BUILD_OPTIONS" // -43
+ ,
+ "CL_INVALID_PROGRAM" // -44
+ ,
+ "CL_INVALID_PROGRAM_EXECUTABLE" // -45
+ ,
+ "CL_INVALID_KERNEL_NAME" // -46
+ ,
+ "CL_INVALID_KERNEL_DEFINITION" // -47
+ ,
+ "CL_INVALID_KERNEL" // -48
+ ,
+ "CL_INVALID_ARG_INDEX" // -49
+ ,
+ "CL_INVALID_ARG_VALUE" // -50
+ ,
+ "CL_INVALID_ARG_SIZE" // -51
+ ,
+ "CL_INVALID_KERNEL_ARGS" // -52
+ ,
+ "CL_INVALID_WORK_DIMENSION" // -53
+ ,
+ "CL_INVALID_WORK_GROUP_SIZE" // -54
+ ,
+ "CL_INVALID_WORK_ITEM_SIZE" // -55
+ ,
+ "CL_INVALID_GLOBAL_OFFSET" // -56
+ ,
+ "CL_INVALID_EVENT_WAIT_LIST" // -57
+ ,
+ "CL_INVALID_EVENT" // -58
+ ,
+ "CL_INVALID_OPERATION" // -59
+ ,
+ "CL_INVALID_GL_OBJECT" // -60
+ ,
+ "CL_INVALID_BUFFER_SIZE" // -61
+ ,
+ "CL_INVALID_MIP_LEVEL" // -62
+ ,
+ "CL_INVALID_GLOBAL_WORK_SIZE" // -63
+ };
- return strings[-error];
+ return strings[-error];
}
diff --git a/thirdparty/bullet/clew/clew.h b/thirdparty/bullet/clew/clew.h
index ee0fef18b4..cba8585233 100644
--- a/thirdparty/bullet/clew/clew.h
+++ b/thirdparty/bullet/clew/clew.h
@@ -11,7 +11,7 @@
//! \file clew.h
//! \brief OpenCL run-time loader header
//!
-//! This file contains a copy of the contents of CL.H and CL_PLATFORM.H from the
+//! This file contains a copy of the contents of CL.H and CL_PLATFORM.H from the
//! official OpenCL spec. The purpose of this code is to load the OpenCL dynamic
//! library at run-time and thus allow the executable to function on many
//! platforms regardless of the vendor of the OpenCL driver actually installed.
@@ -19,11 +19,11 @@
//! library (http://glew.sourceforge.net/)
// Run-time dynamic linking functionality based on concepts used in GLEW
-#ifdef __OPENCL_CL_H
+#ifdef __OPENCL_CL_H
#error cl.h included before clew.h
#endif
-#ifdef __OPENCL_CL_PLATFORM_H
+#ifdef __OPENCL_CL_PLATFORM_H
#error cl_platform.h included before clew.h
#endif
@@ -55,238 +55,239 @@
* MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
******************************************************************************/
#ifdef __APPLE__
- /* Contains #defines for AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER below */
- #include <AvailabilityMacros.h>
+/* Contains #defines for AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER below */
+#include <AvailabilityMacros.h>
#endif
#ifdef __cplusplus
-extern "C" {
+extern "C"
+{
#endif
#if defined(_WIN32)
- #define CL_API_ENTRY
- #define CL_API_CALL __stdcall
- #define CL_CALLBACK __stdcall
+#define CL_API_ENTRY
+#define CL_API_CALL __stdcall
+#define CL_CALLBACK __stdcall
#else
- #define CL_API_ENTRY
- #define CL_API_CALL
- #define CL_CALLBACK
+#define CL_API_ENTRY
+#define CL_API_CALL
+#define CL_CALLBACK
#endif
-//disabled the APPLE thing, don't know why it is there, is just causes tons of warnings
+ //disabled the APPLE thing, don't know why it is there, is just causes tons of warnings
#ifdef __APPLE1__
- #define CL_EXTENSION_WEAK_LINK __attribute__((weak_import))
- #define CL_API_SUFFIX__VERSION_1_0 AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
- #define CL_EXT_SUFFIX__VERSION_1_0 CL_EXTENSION_WEAK_LINK AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
- #define CL_API_SUFFIX__VERSION_1_1 CL_EXTENSION_WEAK_LINK
- #define CL_EXT_SUFFIX__VERSION_1_1 CL_EXTENSION_WEAK_LINK
- #define CL_EXT_SUFFIX__VERSION_1_0_DEPRECATED CL_EXTENSION_WEAK_LINK AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
+#define CL_EXTENSION_WEAK_LINK __attribute__((weak_import))
+#define CL_API_SUFFIX__VERSION_1_0 AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
+#define CL_EXT_SUFFIX__VERSION_1_0 CL_EXTENSION_WEAK_LINK AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
+#define CL_API_SUFFIX__VERSION_1_1 CL_EXTENSION_WEAK_LINK
+#define CL_EXT_SUFFIX__VERSION_1_1 CL_EXTENSION_WEAK_LINK
+#define CL_EXT_SUFFIX__VERSION_1_0_DEPRECATED CL_EXTENSION_WEAK_LINK AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
#else
- #define CL_EXTENSION_WEAK_LINK
- #define CL_API_SUFFIX__VERSION_1_0
- #define CL_EXT_SUFFIX__VERSION_1_0
- #define CL_API_SUFFIX__VERSION_1_1
- #define CL_EXT_SUFFIX__VERSION_1_1
- #define CL_EXT_SUFFIX__VERSION_1_0_DEPRECATED
-#endif
-
-#if (defined (_WIN32) && defined(_MSC_VER))
-
-/* scalar types */
-typedef signed __int8 cl_char;
-typedef unsigned __int8 cl_uchar;
-typedef signed __int16 cl_short;
-typedef unsigned __int16 cl_ushort;
-typedef signed __int32 cl_int;
-typedef unsigned __int32 cl_uint;
-typedef signed __int64 cl_long;
-typedef unsigned __int64 cl_ulong;
-
-typedef unsigned __int16 cl_half;
-typedef float cl_float;
-typedef double cl_double;
+#define CL_EXTENSION_WEAK_LINK
+#define CL_API_SUFFIX__VERSION_1_0
+#define CL_EXT_SUFFIX__VERSION_1_0
+#define CL_API_SUFFIX__VERSION_1_1
+#define CL_EXT_SUFFIX__VERSION_1_1
+#define CL_EXT_SUFFIX__VERSION_1_0_DEPRECATED
+#endif
+
+#if (defined(_WIN32) && defined(_MSC_VER))
+
+ /* scalar types */
+ typedef signed __int8 cl_char;
+ typedef unsigned __int8 cl_uchar;
+ typedef signed __int16 cl_short;
+ typedef unsigned __int16 cl_ushort;
+ typedef signed __int32 cl_int;
+ typedef unsigned __int32 cl_uint;
+ typedef signed __int64 cl_long;
+ typedef unsigned __int64 cl_ulong;
+
+ typedef unsigned __int16 cl_half;
+ typedef float cl_float;
+ typedef double cl_double;
/* Macro names and corresponding values defined by OpenCL */
-#define CL_CHAR_BIT 8
-#define CL_SCHAR_MAX 127
-#define CL_SCHAR_MIN (-127-1)
-#define CL_CHAR_MAX CL_SCHAR_MAX
-#define CL_CHAR_MIN CL_SCHAR_MIN
-#define CL_UCHAR_MAX 255
-#define CL_SHRT_MAX 32767
-#define CL_SHRT_MIN (-32767-1)
-#define CL_USHRT_MAX 65535
-#define CL_INT_MAX 2147483647
-#define CL_INT_MIN (-2147483647-1)
-#define CL_UINT_MAX 0xffffffffU
-#define CL_LONG_MAX ((cl_long) 0x7FFFFFFFFFFFFFFFLL)
-#define CL_LONG_MIN ((cl_long) -0x7FFFFFFFFFFFFFFFLL - 1LL)
-#define CL_ULONG_MAX ((cl_ulong) 0xFFFFFFFFFFFFFFFFULL)
-
-#define CL_FLT_DIG 6
-#define CL_FLT_MANT_DIG 24
-#define CL_FLT_MAX_10_EXP +38
-#define CL_FLT_MAX_EXP +128
-#define CL_FLT_MIN_10_EXP -37
-#define CL_FLT_MIN_EXP -125
-#define CL_FLT_RADIX 2
-#define CL_FLT_MAX 340282346638528859811704183484516925440.0f
-#define CL_FLT_MIN 1.175494350822287507969e-38f
-#define CL_FLT_EPSILON 0x1.0p-23f
-
-#define CL_DBL_DIG 15
-#define CL_DBL_MANT_DIG 53
-#define CL_DBL_MAX_10_EXP +308
-#define CL_DBL_MAX_EXP +1024
-#define CL_DBL_MIN_10_EXP -307
-#define CL_DBL_MIN_EXP -1021
-#define CL_DBL_RADIX 2
-#define CL_DBL_MAX 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0
-#define CL_DBL_MIN 2.225073858507201383090e-308
-#define CL_DBL_EPSILON 2.220446049250313080847e-16
-
-#define CL_M_E 2.718281828459045090796
-#define CL_M_LOG2E 1.442695040888963387005
-#define CL_M_LOG10E 0.434294481903251816668
-#define CL_M_LN2 0.693147180559945286227
-#define CL_M_LN10 2.302585092994045901094
-#define CL_M_PI 3.141592653589793115998
-#define CL_M_PI_2 1.570796326794896557999
-#define CL_M_PI_4 0.785398163397448278999
-#define CL_M_1_PI 0.318309886183790691216
-#define CL_M_2_PI 0.636619772367581382433
-#define CL_M_2_SQRTPI 1.128379167095512558561
-#define CL_M_SQRT2 1.414213562373095145475
-#define CL_M_SQRT1_2 0.707106781186547572737
-
-#define CL_M_E_F 2.71828174591064f
-#define CL_M_LOG2E_F 1.44269502162933f
-#define CL_M_LOG10E_F 0.43429449200630f
-#define CL_M_LN2_F 0.69314718246460f
-#define CL_M_LN10_F 2.30258512496948f
-#define CL_M_PI_F 3.14159274101257f
-#define CL_M_PI_2_F 1.57079637050629f
-#define CL_M_PI_4_F 0.78539818525314f
-#define CL_M_1_PI_F 0.31830987334251f
-#define CL_M_2_PI_F 0.63661974668503f
-#define CL_M_2_SQRTPI_F 1.12837922573090f
-#define CL_M_SQRT2_F 1.41421353816986f
-#define CL_M_SQRT1_2_F 0.70710676908493f
-
-#define CL_NAN (CL_INFINITY - CL_INFINITY)
-#define CL_HUGE_VALF ((cl_float) 1e50)
-#define CL_HUGE_VAL ((cl_double) 1e500)
-#define CL_MAXFLOAT CL_FLT_MAX
-#define CL_INFINITY CL_HUGE_VALF
+#define CL_CHAR_BIT 8
+#define CL_SCHAR_MAX 127
+#define CL_SCHAR_MIN (-127 - 1)
+#define CL_CHAR_MAX CL_SCHAR_MAX
+#define CL_CHAR_MIN CL_SCHAR_MIN
+#define CL_UCHAR_MAX 255
+#define CL_SHRT_MAX 32767
+#define CL_SHRT_MIN (-32767 - 1)
+#define CL_USHRT_MAX 65535
+#define CL_INT_MAX 2147483647
+#define CL_INT_MIN (-2147483647 - 1)
+#define CL_UINT_MAX 0xffffffffU
+#define CL_LONG_MAX ((cl_long)0x7FFFFFFFFFFFFFFFLL)
+#define CL_LONG_MIN ((cl_long)-0x7FFFFFFFFFFFFFFFLL - 1LL)
+#define CL_ULONG_MAX ((cl_ulong)0xFFFFFFFFFFFFFFFFULL)
+
+#define CL_FLT_DIG 6
+#define CL_FLT_MANT_DIG 24
+#define CL_FLT_MAX_10_EXP +38
+#define CL_FLT_MAX_EXP +128
+#define CL_FLT_MIN_10_EXP -37
+#define CL_FLT_MIN_EXP -125
+#define CL_FLT_RADIX 2
+#define CL_FLT_MAX 340282346638528859811704183484516925440.0f
+#define CL_FLT_MIN 1.175494350822287507969e-38f
+#define CL_FLT_EPSILON 0x1.0p-23f
+
+#define CL_DBL_DIG 15
+#define CL_DBL_MANT_DIG 53
+#define CL_DBL_MAX_10_EXP +308
+#define CL_DBL_MAX_EXP +1024
+#define CL_DBL_MIN_10_EXP -307
+#define CL_DBL_MIN_EXP -1021
+#define CL_DBL_RADIX 2
+#define CL_DBL_MAX 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0
+#define CL_DBL_MIN 2.225073858507201383090e-308
+#define CL_DBL_EPSILON 2.220446049250313080847e-16
+
+#define CL_M_E 2.718281828459045090796
+#define CL_M_LOG2E 1.442695040888963387005
+#define CL_M_LOG10E 0.434294481903251816668
+#define CL_M_LN2 0.693147180559945286227
+#define CL_M_LN10 2.302585092994045901094
+#define CL_M_PI 3.141592653589793115998
+#define CL_M_PI_2 1.570796326794896557999
+#define CL_M_PI_4 0.785398163397448278999
+#define CL_M_1_PI 0.318309886183790691216
+#define CL_M_2_PI 0.636619772367581382433
+#define CL_M_2_SQRTPI 1.128379167095512558561
+#define CL_M_SQRT2 1.414213562373095145475
+#define CL_M_SQRT1_2 0.707106781186547572737
+
+#define CL_M_E_F 2.71828174591064f
+#define CL_M_LOG2E_F 1.44269502162933f
+#define CL_M_LOG10E_F 0.43429449200630f
+#define CL_M_LN2_F 0.69314718246460f
+#define CL_M_LN10_F 2.30258512496948f
+#define CL_M_PI_F 3.14159274101257f
+#define CL_M_PI_2_F 1.57079637050629f
+#define CL_M_PI_4_F 0.78539818525314f
+#define CL_M_1_PI_F 0.31830987334251f
+#define CL_M_2_PI_F 0.63661974668503f
+#define CL_M_2_SQRTPI_F 1.12837922573090f
+#define CL_M_SQRT2_F 1.41421353816986f
+#define CL_M_SQRT1_2_F 0.70710676908493f
+
+#define CL_NAN (CL_INFINITY - CL_INFINITY)
+#define CL_HUGE_VALF ((cl_float)1e50)
+#define CL_HUGE_VAL ((cl_double)1e500)
+#define CL_MAXFLOAT CL_FLT_MAX
+#define CL_INFINITY CL_HUGE_VALF
#else
#include <stdint.h>
/* scalar types */
-typedef int8_t cl_char;
-typedef uint8_t cl_uchar;
-typedef int16_t cl_short __attribute__((aligned(2)));
-typedef uint16_t cl_ushort __attribute__((aligned(2)));
-typedef int32_t cl_int __attribute__((aligned(4)));
-typedef uint32_t cl_uint __attribute__((aligned(4)));
-typedef int64_t cl_long __attribute__((aligned(8)));
-typedef uint64_t cl_ulong __attribute__((aligned(8)));
-
-typedef uint16_t cl_half __attribute__((aligned(2)));
-typedef float cl_float __attribute__((aligned(4)));
-typedef double cl_double __attribute__((aligned(8)));
+typedef int8_t cl_char;
+typedef uint8_t cl_uchar;
+typedef int16_t cl_short __attribute__((aligned(2)));
+typedef uint16_t cl_ushort __attribute__((aligned(2)));
+typedef int32_t cl_int __attribute__((aligned(4)));
+typedef uint32_t cl_uint __attribute__((aligned(4)));
+typedef int64_t cl_long __attribute__((aligned(8)));
+typedef uint64_t cl_ulong __attribute__((aligned(8)));
+
+typedef uint16_t cl_half __attribute__((aligned(2)));
+typedef float cl_float __attribute__((aligned(4)));
+typedef double cl_double __attribute__((aligned(8)));
/* Macro names and corresponding values defined by OpenCL */
-#define CL_CHAR_BIT 8
-#define CL_SCHAR_MAX 127
-#define CL_SCHAR_MIN (-127-1)
-#define CL_CHAR_MAX CL_SCHAR_MAX
-#define CL_CHAR_MIN CL_SCHAR_MIN
-#define CL_UCHAR_MAX 255
-#define CL_SHRT_MAX 32767
-#define CL_SHRT_MIN (-32767-1)
-#define CL_USHRT_MAX 65535
-#define CL_INT_MAX 2147483647
-#define CL_INT_MIN (-2147483647-1)
-#define CL_UINT_MAX 0xffffffffU
-#define CL_LONG_MAX ((cl_long) 0x7FFFFFFFFFFFFFFFLL)
-#define CL_LONG_MIN ((cl_long) -0x7FFFFFFFFFFFFFFFLL - 1LL)
-#define CL_ULONG_MAX ((cl_ulong) 0xFFFFFFFFFFFFFFFFULL)
-
-#define CL_FLT_DIG 6
-#define CL_FLT_MANT_DIG 24
-#define CL_FLT_MAX_10_EXP +38
-#define CL_FLT_MAX_EXP +128
-#define CL_FLT_MIN_10_EXP -37
-#define CL_FLT_MIN_EXP -125
-#define CL_FLT_RADIX 2
-#define CL_FLT_MAX 0x1.fffffep127f
-#define CL_FLT_MIN 0x1.0p-126f
-#define CL_FLT_EPSILON 0x1.0p-23f
-
-#define CL_DBL_DIG 15
-#define CL_DBL_MANT_DIG 53
-#define CL_DBL_MAX_10_EXP +308
-#define CL_DBL_MAX_EXP +1024
-#define CL_DBL_MIN_10_EXP -307
-#define CL_DBL_MIN_EXP -1021
-#define CL_DBL_RADIX 2
-#define CL_DBL_MAX 0x1.fffffffffffffp1023
-#define CL_DBL_MIN 0x1.0p-1022
-#define CL_DBL_EPSILON 0x1.0p-52
-
-#define CL_M_E 2.718281828459045090796
-#define CL_M_LOG2E 1.442695040888963387005
-#define CL_M_LOG10E 0.434294481903251816668
-#define CL_M_LN2 0.693147180559945286227
-#define CL_M_LN10 2.302585092994045901094
-#define CL_M_PI 3.141592653589793115998
-#define CL_M_PI_2 1.570796326794896557999
-#define CL_M_PI_4 0.785398163397448278999
-#define CL_M_1_PI 0.318309886183790691216
-#define CL_M_2_PI 0.636619772367581382433
-#define CL_M_2_SQRTPI 1.128379167095512558561
-#define CL_M_SQRT2 1.414213562373095145475
-#define CL_M_SQRT1_2 0.707106781186547572737
-
-#define CL_M_E_F 2.71828174591064f
-#define CL_M_LOG2E_F 1.44269502162933f
-#define CL_M_LOG10E_F 0.43429449200630f
-#define CL_M_LN2_F 0.69314718246460f
-#define CL_M_LN10_F 2.30258512496948f
-#define CL_M_PI_F 3.14159274101257f
-#define CL_M_PI_2_F 1.57079637050629f
-#define CL_M_PI_4_F 0.78539818525314f
-#define CL_M_1_PI_F 0.31830987334251f
-#define CL_M_2_PI_F 0.63661974668503f
-#define CL_M_2_SQRTPI_F 1.12837922573090f
-#define CL_M_SQRT2_F 1.41421353816986f
-#define CL_M_SQRT1_2_F 0.70710676908493f
-
-#if defined( __GNUC__ )
- #define CL_HUGE_VALF __builtin_huge_valf()
- #define CL_HUGE_VAL __builtin_huge_val()
- #define CL_NAN __builtin_nanf( "" )
+#define CL_CHAR_BIT 8
+#define CL_SCHAR_MAX 127
+#define CL_SCHAR_MIN (-127 - 1)
+#define CL_CHAR_MAX CL_SCHAR_MAX
+#define CL_CHAR_MIN CL_SCHAR_MIN
+#define CL_UCHAR_MAX 255
+#define CL_SHRT_MAX 32767
+#define CL_SHRT_MIN (-32767 - 1)
+#define CL_USHRT_MAX 65535
+#define CL_INT_MAX 2147483647
+#define CL_INT_MIN (-2147483647 - 1)
+#define CL_UINT_MAX 0xffffffffU
+#define CL_LONG_MAX ((cl_long)0x7FFFFFFFFFFFFFFFLL)
+#define CL_LONG_MIN ((cl_long)-0x7FFFFFFFFFFFFFFFLL - 1LL)
+#define CL_ULONG_MAX ((cl_ulong)0xFFFFFFFFFFFFFFFFULL)
+
+#define CL_FLT_DIG 6
+#define CL_FLT_MANT_DIG 24
+#define CL_FLT_MAX_10_EXP +38
+#define CL_FLT_MAX_EXP +128
+#define CL_FLT_MIN_10_EXP -37
+#define CL_FLT_MIN_EXP -125
+#define CL_FLT_RADIX 2
+#define CL_FLT_MAX 0x1.fffffep127f
+#define CL_FLT_MIN 0x1.0p-126f
+#define CL_FLT_EPSILON 0x1.0p-23f
+
+#define CL_DBL_DIG 15
+#define CL_DBL_MANT_DIG 53
+#define CL_DBL_MAX_10_EXP +308
+#define CL_DBL_MAX_EXP +1024
+#define CL_DBL_MIN_10_EXP -307
+#define CL_DBL_MIN_EXP -1021
+#define CL_DBL_RADIX 2
+#define CL_DBL_MAX 0x1.fffffffffffffp1023
+#define CL_DBL_MIN 0x1.0p-1022
+#define CL_DBL_EPSILON 0x1.0p-52
+
+#define CL_M_E 2.718281828459045090796
+#define CL_M_LOG2E 1.442695040888963387005
+#define CL_M_LOG10E 0.434294481903251816668
+#define CL_M_LN2 0.693147180559945286227
+#define CL_M_LN10 2.302585092994045901094
+#define CL_M_PI 3.141592653589793115998
+#define CL_M_PI_2 1.570796326794896557999
+#define CL_M_PI_4 0.785398163397448278999
+#define CL_M_1_PI 0.318309886183790691216
+#define CL_M_2_PI 0.636619772367581382433
+#define CL_M_2_SQRTPI 1.128379167095512558561
+#define CL_M_SQRT2 1.414213562373095145475
+#define CL_M_SQRT1_2 0.707106781186547572737
+
+#define CL_M_E_F 2.71828174591064f
+#define CL_M_LOG2E_F 1.44269502162933f
+#define CL_M_LOG10E_F 0.43429449200630f
+#define CL_M_LN2_F 0.69314718246460f
+#define CL_M_LN10_F 2.30258512496948f
+#define CL_M_PI_F 3.14159274101257f
+#define CL_M_PI_2_F 1.57079637050629f
+#define CL_M_PI_4_F 0.78539818525314f
+#define CL_M_1_PI_F 0.31830987334251f
+#define CL_M_2_PI_F 0.63661974668503f
+#define CL_M_2_SQRTPI_F 1.12837922573090f
+#define CL_M_SQRT2_F 1.41421353816986f
+#define CL_M_SQRT1_2_F 0.70710676908493f
+
+#if defined(__GNUC__)
+#define CL_HUGE_VALF __builtin_huge_valf()
+#define CL_HUGE_VAL __builtin_huge_val()
+#define CL_NAN __builtin_nanf("")
#else
- #define CL_HUGE_VALF ((cl_float) 1e50)
- #define CL_HUGE_VAL ((cl_double) 1e500)
- float nanf( const char * );
- #define CL_NAN nanf( "" )
+#define CL_HUGE_VALF ((cl_float)1e50)
+#define CL_HUGE_VAL ((cl_double)1e500)
+float nanf(const char *);
+#define CL_NAN nanf("")
#endif
-#define CL_MAXFLOAT CL_FLT_MAX
-#define CL_INFINITY CL_HUGE_VALF
+#define CL_MAXFLOAT CL_FLT_MAX
+#define CL_INFINITY CL_HUGE_VALF
#endif
#include <stddef.h>
-/* Mirror types to GL types. Mirror types allow us to avoid deciding which headers to load based on whether we are using GL or GLES here. */
-typedef unsigned int cl_GLuint;
-typedef int cl_GLint;
-typedef unsigned int cl_GLenum;
+ /* Mirror types to GL types. Mirror types allow us to avoid deciding which headers to load based on whether we are using GL or GLES here. */
+ typedef unsigned int cl_GLuint;
+ typedef int cl_GLint;
+ typedef unsigned int cl_GLenum;
-/*
+ /*
* Vector types
*
* Note: OpenCL requires that all types be naturally aligned.
@@ -302,7 +303,6 @@ typedef unsigned int cl_GLenum;
* Maintaining proper alignment is the user's responsibility.
*/
-
#ifdef _MSC_VER
#if defined(_M_IX86)
#if _M_IX86_FP >= 0
@@ -318,904 +318,1218 @@ typedef unsigned int cl_GLenum;
#endif
/* Define basic vector types */
-#if defined( __VEC__ )
- #include <altivec.h> /* may be omitted depending on compiler. AltiVec spec provides no way to detect whether the header is required. */
- typedef vector unsigned char __cl_uchar16;
- typedef vector signed char __cl_char16;
- typedef vector unsigned short __cl_ushort8;
- typedef vector signed short __cl_short8;
- typedef vector unsigned int __cl_uint4;
- typedef vector signed int __cl_int4;
- typedef vector float __cl_float4;
- #define __CL_UCHAR16__ 1
- #define __CL_CHAR16__ 1
- #define __CL_USHORT8__ 1
- #define __CL_SHORT8__ 1
- #define __CL_UINT4__ 1
- #define __CL_INT4__ 1
- #define __CL_FLOAT4__ 1
-#endif
-
-#if defined( __SSE__ )
- #if defined( __MINGW64__ )
- #include <intrin.h>
- #else
- #include <xmmintrin.h>
- #endif
- #if defined( __GNUC__ ) && !defined( __ICC )
- typedef float __cl_float4 __attribute__((vector_size(16)));
- #else
- typedef __m128 __cl_float4;
- #endif
- #define __CL_FLOAT4__ 1
-#endif
-
-#if defined( __SSE2__ )
- #if defined( __MINGW64__ )
- #include <intrin.h>
- #else
- #include <emmintrin.h>
- #endif
- #if defined( __GNUC__ ) && !defined( __ICC )
- typedef cl_uchar __cl_uchar16 __attribute__((vector_size(16)));
- typedef cl_char __cl_char16 __attribute__((vector_size(16)));
- typedef cl_ushort __cl_ushort8 __attribute__((vector_size(16)));
- typedef cl_short __cl_short8 __attribute__((vector_size(16)));
- typedef cl_uint __cl_uint4 __attribute__((vector_size(16)));
- typedef cl_int __cl_int4 __attribute__((vector_size(16)));
- typedef cl_ulong __cl_ulong2 __attribute__((vector_size(16)));
- typedef cl_long __cl_long2 __attribute__((vector_size(16)));
- typedef cl_double __cl_double2 __attribute__((vector_size(16)));
- #else
- typedef __m128i __cl_uchar16;
- typedef __m128i __cl_char16;
- typedef __m128i __cl_ushort8;
- typedef __m128i __cl_short8;
- typedef __m128i __cl_uint4;
- typedef __m128i __cl_int4;
- typedef __m128i __cl_ulong2;
- typedef __m128i __cl_long2;
- typedef __m128d __cl_double2;
- #endif
- #define __CL_UCHAR16__ 1
- #define __CL_CHAR16__ 1
- #define __CL_USHORT8__ 1
- #define __CL_SHORT8__ 1
- #define __CL_INT4__ 1
- #define __CL_UINT4__ 1
- #define __CL_ULONG2__ 1
- #define __CL_LONG2__ 1
- #define __CL_DOUBLE2__ 1
-#endif
-
-#if defined( __MMX__ )
- #include <mmintrin.h>
- #if defined( __GNUC__ ) && !defined( __ICC )
- typedef cl_uchar __cl_uchar8 __attribute__((vector_size(8)));
- typedef cl_char __cl_char8 __attribute__((vector_size(8)));
- typedef cl_ushort __cl_ushort4 __attribute__((vector_size(8)));
- typedef cl_short __cl_short4 __attribute__((vector_size(8)));
- typedef cl_uint __cl_uint2 __attribute__((vector_size(8)));
- typedef cl_int __cl_int2 __attribute__((vector_size(8)));
- typedef cl_ulong __cl_ulong1 __attribute__((vector_size(8)));
- typedef cl_long __cl_long1 __attribute__((vector_size(8)));
- typedef cl_float __cl_float2 __attribute__((vector_size(8)));
- #else
- typedef __m64 __cl_uchar8;
- typedef __m64 __cl_char8;
- typedef __m64 __cl_ushort4;
- typedef __m64 __cl_short4;
- typedef __m64 __cl_uint2;
- typedef __m64 __cl_int2;
- typedef __m64 __cl_ulong1;
- typedef __m64 __cl_long1;
- typedef __m64 __cl_float2;
- #endif
- #define __CL_UCHAR8__ 1
- #define __CL_CHAR8__ 1
- #define __CL_USHORT4__ 1
- #define __CL_SHORT4__ 1
- #define __CL_INT2__ 1
- #define __CL_UINT2__ 1
- #define __CL_ULONG1__ 1
- #define __CL_LONG1__ 1
- #define __CL_FLOAT2__ 1
-#endif
-
-#if defined( __AVX__ )
- #if defined( __MINGW64__ )
- #include <intrin.h>
- #else
- #include <immintrin.h>
- #endif
- #if defined( __GNUC__ ) && !defined( __ICC )
- typedef cl_float __cl_float8 __attribute__((vector_size(32)));
- typedef cl_double __cl_double4 __attribute__((vector_size(32)));
- #else
- typedef __m256 __cl_float8;
- typedef __m256d __cl_double4;
- #endif
- #define __CL_FLOAT8__ 1
- #define __CL_DOUBLE4__ 1
-#endif
-
-/* Define alignment keys */
-#if defined( __GNUC__ )
- #define CL_ALIGNED(_x) __attribute__ ((aligned(_x)))
-#elif defined( _WIN32) && (_MSC_VER)
- /* Alignment keys neutered on windows because MSVC can't swallow function arguments with alignment requirements */
- /* http://msdn.microsoft.com/en-us/library/373ak2y1%28VS.71%29.aspx */
- /* #include <crtdefs.h> */
- /* #define CL_ALIGNED(_x) _CRT_ALIGN(_x) */
- #define CL_ALIGNED(_x)
+#if defined(__VEC__)
+#include <altivec.h> /* may be omitted depending on compiler. AltiVec spec provides no way to detect whether the header is required. */
+ typedef vector unsigned char __cl_uchar16;
+ typedef vector signed char __cl_char16;
+ typedef vector unsigned short __cl_ushort8;
+ typedef vector signed short __cl_short8;
+ typedef vector unsigned int __cl_uint4;
+ typedef vector signed int __cl_int4;
+ typedef vector float __cl_float4;
+#define __CL_UCHAR16__ 1
+#define __CL_CHAR16__ 1
+#define __CL_USHORT8__ 1
+#define __CL_SHORT8__ 1
+#define __CL_UINT4__ 1
+#define __CL_INT4__ 1
+#define __CL_FLOAT4__ 1
+#endif
+
+#if defined(__SSE__)
+#if defined(__MINGW64__)
+#include <intrin.h>
#else
- #warning Need to implement some method to align data here
- #define CL_ALIGNED(_x)
-#endif
-
-/* Indicate whether .xyzw, .s0123 and .hi.lo are supported */
-#if (defined( __GNUC__) && ! defined( __STRICT_ANSI__ )) || (defined( _MSC_VER ) && ! defined( __STDC__ ))
- /* .xyzw and .s0123...{f|F} are supported */
- #define CL_HAS_NAMED_VECTOR_FIELDS 1
- /* .hi and .lo are supported */
- #define CL_HAS_HI_LO_VECTOR_FIELDS 1
-
- #define CL_NAMED_STRUCT_SUPPORTED
-#endif
-
-#if defined( CL_NAMED_STRUCT_SUPPORTED) && defined( _MSC_VER )
-#define __extension__ __pragma(warning(suppress:4201))
-#endif
-
-/* Define cl_vector types */
-
-/* ---- cl_charn ---- */
-typedef union
-{
- cl_char CL_ALIGNED(2) s[2];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_char x, y; };
- __extension__ struct{ cl_char s0, s1; };
- __extension__ struct{ cl_char lo, hi; };
-#endif
-#if defined( __CL_CHAR2__)
- __cl_char2 v2;
-#endif
-}cl_char2;
-
-typedef union
-{
- cl_char CL_ALIGNED(4) s[4];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_char x, y, z, w; };
- __extension__ struct{ cl_char s0, s1, s2, s3; };
- __extension__ struct{ cl_char2 lo, hi; };
-#endif
-#if defined( __CL_CHAR2__)
- __cl_char2 v2[2];
-#endif
-#if defined( __CL_CHAR4__)
- __cl_char4 v4;
-#endif
-}cl_char4;
-
-/* cl_char3 is identical in size, alignment and behavior to cl_char4. See section 6.1.5. */
-typedef cl_char4 cl_char3;
-
-typedef union
-{
- cl_char CL_ALIGNED(8) s[8];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_char x, y, z, w; };
- __extension__ struct{ cl_char s0, s1, s2, s3, s4, s5, s6, s7; };
- __extension__ struct{ cl_char4 lo, hi; };
-#endif
-#if defined( __CL_CHAR2__)
- __cl_char2 v2[4];
-#endif
-#if defined( __CL_CHAR4__)
- __cl_char4 v4[2];
-#endif
-#if defined( __CL_CHAR8__ )
- __cl_char8 v8;
-#endif
-}cl_char8;
-
-typedef union
-{
- cl_char CL_ALIGNED(16) s[16];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_char x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf; };
- __extension__ struct{ cl_char s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF; };
- __extension__ struct{ cl_char8 lo, hi; };
-#endif
-#if defined( __CL_CHAR2__)
- __cl_char2 v2[8];
-#endif
-#if defined( __CL_CHAR4__)
- __cl_char4 v4[4];
-#endif
-#if defined( __CL_CHAR8__ )
- __cl_char8 v8[2];
-#endif
-#if defined( __CL_CHAR16__ )
- __cl_char16 v16;
-#endif
-}cl_char16;
-
-
-/* ---- cl_ucharn ---- */
-typedef union
-{
- cl_uchar CL_ALIGNED(2) s[2];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_uchar x, y; };
- __extension__ struct{ cl_uchar s0, s1; };
- __extension__ struct{ cl_uchar lo, hi; };
-#endif
-#if defined( __cl_uchar2__)
- __cl_uchar2 v2;
-#endif
-}cl_uchar2;
-
-typedef union
-{
- cl_uchar CL_ALIGNED(4) s[4];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_uchar x, y, z, w; };
- __extension__ struct{ cl_uchar s0, s1, s2, s3; };
- __extension__ struct{ cl_uchar2 lo, hi; };
-#endif
-#if defined( __CL_UCHAR2__)
- __cl_uchar2 v2[2];
-#endif
-#if defined( __CL_UCHAR4__)
- __cl_uchar4 v4;
-#endif
-}cl_uchar4;
-
-/* cl_uchar3 is identical in size, alignment and behavior to cl_uchar4. See section 6.1.5. */
-typedef cl_uchar4 cl_uchar3;
-
-typedef union
-{
- cl_uchar CL_ALIGNED(8) s[8];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_uchar x, y, z, w; };
- __extension__ struct{ cl_uchar s0, s1, s2, s3, s4, s5, s6, s7; };
- __extension__ struct{ cl_uchar4 lo, hi; };
-#endif
-#if defined( __CL_UCHAR2__)
- __cl_uchar2 v2[4];
-#endif
-#if defined( __CL_UCHAR4__)
- __cl_uchar4 v4[2];
-#endif
-#if defined( __CL_UCHAR8__ )
- __cl_uchar8 v8;
-#endif
-}cl_uchar8;
-
-typedef union
-{
- cl_uchar CL_ALIGNED(16) s[16];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_uchar x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf; };
- __extension__ struct{ cl_uchar s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF; };
- __extension__ struct{ cl_uchar8 lo, hi; };
-#endif
-#if defined( __CL_UCHAR2__)
- __cl_uchar2 v2[8];
-#endif
-#if defined( __CL_UCHAR4__)
- __cl_uchar4 v4[4];
-#endif
-#if defined( __CL_UCHAR8__ )
- __cl_uchar8 v8[2];
-#endif
-#if defined( __CL_UCHAR16__ )
- __cl_uchar16 v16;
-#endif
-}cl_uchar16;
-
-
-/* ---- cl_shortn ---- */
-typedef union
-{
- cl_short CL_ALIGNED(4) s[2];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_short x, y; };
- __extension__ struct{ cl_short s0, s1; };
- __extension__ struct{ cl_short lo, hi; };
-#endif
-#if defined( __CL_SHORT2__)
- __cl_short2 v2;
-#endif
-}cl_short2;
-
-typedef union
-{
- cl_short CL_ALIGNED(8) s[4];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_short x, y, z, w; };
- __extension__ struct{ cl_short s0, s1, s2, s3; };
- __extension__ struct{ cl_short2 lo, hi; };
-#endif
-#if defined( __CL_SHORT2__)
- __cl_short2 v2[2];
-#endif
-#if defined( __CL_SHORT4__)
- __cl_short4 v4;
-#endif
-}cl_short4;
-
-/* cl_short3 is identical in size, alignment and behavior to cl_short4. See section 6.1.5. */
-typedef cl_short4 cl_short3;
-
-typedef union
-{
- cl_short CL_ALIGNED(16) s[8];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_short x, y, z, w; };
- __extension__ struct{ cl_short s0, s1, s2, s3, s4, s5, s6, s7; };
- __extension__ struct{ cl_short4 lo, hi; };
-#endif
-#if defined( __CL_SHORT2__)
- __cl_short2 v2[4];
-#endif
-#if defined( __CL_SHORT4__)
- __cl_short4 v4[2];
-#endif
-#if defined( __CL_SHORT8__ )
- __cl_short8 v8;
-#endif
-}cl_short8;
-
-typedef union
-{
- cl_short CL_ALIGNED(32) s[16];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_short x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf; };
- __extension__ struct{ cl_short s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF; };
- __extension__ struct{ cl_short8 lo, hi; };
-#endif
-#if defined( __CL_SHORT2__)
- __cl_short2 v2[8];
-#endif
-#if defined( __CL_SHORT4__)
- __cl_short4 v4[4];
-#endif
-#if defined( __CL_SHORT8__ )
- __cl_short8 v8[2];
-#endif
-#if defined( __CL_SHORT16__ )
- __cl_short16 v16;
-#endif
-}cl_short16;
-
-
-/* ---- cl_ushortn ---- */
-typedef union
-{
- cl_ushort CL_ALIGNED(4) s[2];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_ushort x, y; };
- __extension__ struct{ cl_ushort s0, s1; };
- __extension__ struct{ cl_ushort lo, hi; };
-#endif
-#if defined( __CL_USHORT2__)
- __cl_ushort2 v2;
-#endif
-}cl_ushort2;
-
-typedef union
-{
- cl_ushort CL_ALIGNED(8) s[4];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_ushort x, y, z, w; };
- __extension__ struct{ cl_ushort s0, s1, s2, s3; };
- __extension__ struct{ cl_ushort2 lo, hi; };
-#endif
-#if defined( __CL_USHORT2__)
- __cl_ushort2 v2[2];
-#endif
-#if defined( __CL_USHORT4__)
- __cl_ushort4 v4;
-#endif
-}cl_ushort4;
-
-/* cl_ushort3 is identical in size, alignment and behavior to cl_ushort4. See section 6.1.5. */
-typedef cl_ushort4 cl_ushort3;
-
-typedef union
-{
- cl_ushort CL_ALIGNED(16) s[8];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_ushort x, y, z, w; };
- __extension__ struct{ cl_ushort s0, s1, s2, s3, s4, s5, s6, s7; };
- __extension__ struct{ cl_ushort4 lo, hi; };
-#endif
-#if defined( __CL_USHORT2__)
- __cl_ushort2 v2[4];
-#endif
-#if defined( __CL_USHORT4__)
- __cl_ushort4 v4[2];
-#endif
-#if defined( __CL_USHORT8__ )
- __cl_ushort8 v8;
-#endif
-}cl_ushort8;
-
-typedef union
-{
- cl_ushort CL_ALIGNED(32) s[16];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_ushort x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf; };
- __extension__ struct{ cl_ushort s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF; };
- __extension__ struct{ cl_ushort8 lo, hi; };
-#endif
-#if defined( __CL_USHORT2__)
- __cl_ushort2 v2[8];
-#endif
-#if defined( __CL_USHORT4__)
- __cl_ushort4 v4[4];
-#endif
-#if defined( __CL_USHORT8__ )
- __cl_ushort8 v8[2];
-#endif
-#if defined( __CL_USHORT16__ )
- __cl_ushort16 v16;
-#endif
-}cl_ushort16;
-
-/* ---- cl_intn ---- */
-typedef union
-{
- cl_int CL_ALIGNED(8) s[2];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_int x, y; };
- __extension__ struct{ cl_int s0, s1; };
- __extension__ struct{ cl_int lo, hi; };
-#endif
-#if defined( __CL_INT2__)
- __cl_int2 v2;
-#endif
-}cl_int2;
-
-typedef union
-{
- cl_int CL_ALIGNED(16) s[4];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_int x, y, z, w; };
- __extension__ struct{ cl_int s0, s1, s2, s3; };
- __extension__ struct{ cl_int2 lo, hi; };
-#endif
-#if defined( __CL_INT2__)
- __cl_int2 v2[2];
-#endif
-#if defined( __CL_INT4__)
- __cl_int4 v4;
-#endif
-}cl_int4;
-
-/* cl_int3 is identical in size, alignment and behavior to cl_int4. See section 6.1.5. */
-typedef cl_int4 cl_int3;
-
-typedef union
-{
- cl_int CL_ALIGNED(32) s[8];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_int x, y, z, w; };
- __extension__ struct{ cl_int s0, s1, s2, s3, s4, s5, s6, s7; };
- __extension__ struct{ cl_int4 lo, hi; };
-#endif
-#if defined( __CL_INT2__)
- __cl_int2 v2[4];
-#endif
-#if defined( __CL_INT4__)
- __cl_int4 v4[2];
-#endif
-#if defined( __CL_INT8__ )
- __cl_int8 v8;
-#endif
-}cl_int8;
-
-typedef union
-{
- cl_int CL_ALIGNED(64) s[16];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_int x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf; };
- __extension__ struct{ cl_int s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF; };
- __extension__ struct{ cl_int8 lo, hi; };
-#endif
-#if defined( __CL_INT2__)
- __cl_int2 v2[8];
-#endif
-#if defined( __CL_INT4__)
- __cl_int4 v4[4];
+#include <xmmintrin.h>
#endif
-#if defined( __CL_INT8__ )
- __cl_int8 v8[2];
-#endif
-#if defined( __CL_INT16__ )
- __cl_int16 v16;
-#endif
-}cl_int16;
-
-
-/* ---- cl_uintn ---- */
-typedef union
-{
- cl_uint CL_ALIGNED(8) s[2];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_uint x, y; };
- __extension__ struct{ cl_uint s0, s1; };
- __extension__ struct{ cl_uint lo, hi; };
-#endif
-#if defined( __CL_UINT2__)
- __cl_uint2 v2;
-#endif
-}cl_uint2;
-
-typedef union
-{
- cl_uint CL_ALIGNED(16) s[4];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_uint x, y, z, w; };
- __extension__ struct{ cl_uint s0, s1, s2, s3; };
- __extension__ struct{ cl_uint2 lo, hi; };
-#endif
-#if defined( __CL_UINT2__)
- __cl_uint2 v2[2];
-#endif
-#if defined( __CL_UINT4__)
- __cl_uint4 v4;
-#endif
-}cl_uint4;
-
-/* cl_uint3 is identical in size, alignment and behavior to cl_uint4. See section 6.1.5. */
-typedef cl_uint4 cl_uint3;
-
-typedef union
-{
- cl_uint CL_ALIGNED(32) s[8];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_uint x, y, z, w; };
- __extension__ struct{ cl_uint s0, s1, s2, s3, s4, s5, s6, s7; };
- __extension__ struct{ cl_uint4 lo, hi; };
-#endif
-#if defined( __CL_UINT2__)
- __cl_uint2 v2[4];
-#endif
-#if defined( __CL_UINT4__)
- __cl_uint4 v4[2];
-#endif
-#if defined( __CL_UINT8__ )
- __cl_uint8 v8;
-#endif
-}cl_uint8;
-
-typedef union
-{
- cl_uint CL_ALIGNED(64) s[16];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_uint x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf; };
- __extension__ struct{ cl_uint s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF; };
- __extension__ struct{ cl_uint8 lo, hi; };
-#endif
-#if defined( __CL_UINT2__)
- __cl_uint2 v2[8];
-#endif
-#if defined( __CL_UINT4__)
- __cl_uint4 v4[4];
-#endif
-#if defined( __CL_UINT8__ )
- __cl_uint8 v8[2];
-#endif
-#if defined( __CL_UINT16__ )
- __cl_uint16 v16;
-#endif
-}cl_uint16;
-
-/* ---- cl_longn ---- */
-typedef union
-{
- cl_long CL_ALIGNED(16) s[2];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_long x, y; };
- __extension__ struct{ cl_long s0, s1; };
- __extension__ struct{ cl_long lo, hi; };
-#endif
-#if defined( __CL_LONG2__)
- __cl_long2 v2;
-#endif
-}cl_long2;
-
-typedef union
-{
- cl_long CL_ALIGNED(32) s[4];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_long x, y, z, w; };
- __extension__ struct{ cl_long s0, s1, s2, s3; };
- __extension__ struct{ cl_long2 lo, hi; };
-#endif
-#if defined( __CL_LONG2__)
- __cl_long2 v2[2];
-#endif
-#if defined( __CL_LONG4__)
- __cl_long4 v4;
-#endif
-}cl_long4;
-
-/* cl_long3 is identical in size, alignment and behavior to cl_long4. See section 6.1.5. */
-typedef cl_long4 cl_long3;
-
-typedef union
-{
- cl_long CL_ALIGNED(64) s[8];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_long x, y, z, w; };
- __extension__ struct{ cl_long s0, s1, s2, s3, s4, s5, s6, s7; };
- __extension__ struct{ cl_long4 lo, hi; };
-#endif
-#if defined( __CL_LONG2__)
- __cl_long2 v2[4];
-#endif
-#if defined( __CL_LONG4__)
- __cl_long4 v4[2];
-#endif
-#if defined( __CL_LONG8__ )
- __cl_long8 v8;
-#endif
-}cl_long8;
-
-typedef union
-{
- cl_long CL_ALIGNED(128) s[16];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_long x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf; };
- __extension__ struct{ cl_long s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF; };
- __extension__ struct{ cl_long8 lo, hi; };
-#endif
-#if defined( __CL_LONG2__)
- __cl_long2 v2[8];
-#endif
-#if defined( __CL_LONG4__)
- __cl_long4 v4[4];
-#endif
-#if defined( __CL_LONG8__ )
- __cl_long8 v8[2];
-#endif
-#if defined( __CL_LONG16__ )
- __cl_long16 v16;
-#endif
-}cl_long16;
-
-
-/* ---- cl_ulongn ---- */
-typedef union
-{
- cl_ulong CL_ALIGNED(16) s[2];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_ulong x, y; };
- __extension__ struct{ cl_ulong s0, s1; };
- __extension__ struct{ cl_ulong lo, hi; };
-#endif
-#if defined( __CL_ULONG2__)
- __cl_ulong2 v2;
-#endif
-}cl_ulong2;
-
-typedef union
-{
- cl_ulong CL_ALIGNED(32) s[4];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_ulong x, y, z, w; };
- __extension__ struct{ cl_ulong s0, s1, s2, s3; };
- __extension__ struct{ cl_ulong2 lo, hi; };
-#endif
-#if defined( __CL_ULONG2__)
- __cl_ulong2 v2[2];
-#endif
-#if defined( __CL_ULONG4__)
- __cl_ulong4 v4;
-#endif
-}cl_ulong4;
-
-/* cl_ulong3 is identical in size, alignment and behavior to cl_ulong4. See section 6.1.5. */
-typedef cl_ulong4 cl_ulong3;
-
-typedef union
-{
- cl_ulong CL_ALIGNED(64) s[8];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_ulong x, y, z, w; };
- __extension__ struct{ cl_ulong s0, s1, s2, s3, s4, s5, s6, s7; };
- __extension__ struct{ cl_ulong4 lo, hi; };
-#endif
-#if defined( __CL_ULONG2__)
- __cl_ulong2 v2[4];
-#endif
-#if defined( __CL_ULONG4__)
- __cl_ulong4 v4[2];
-#endif
-#if defined( __CL_ULONG8__ )
- __cl_ulong8 v8;
-#endif
-}cl_ulong8;
-
-typedef union
-{
- cl_ulong CL_ALIGNED(128) s[16];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_ulong x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf; };
- __extension__ struct{ cl_ulong s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF; };
- __extension__ struct{ cl_ulong8 lo, hi; };
-#endif
-#if defined( __CL_ULONG2__)
- __cl_ulong2 v2[8];
-#endif
-#if defined( __CL_ULONG4__)
- __cl_ulong4 v4[4];
-#endif
-#if defined( __CL_ULONG8__ )
- __cl_ulong8 v8[2];
-#endif
-#if defined( __CL_ULONG16__ )
- __cl_ulong16 v16;
-#endif
-}cl_ulong16;
-
-
-/* --- cl_floatn ---- */
-
-typedef union
-{
- cl_float CL_ALIGNED(8) s[2];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_float x, y; };
- __extension__ struct{ cl_float s0, s1; };
- __extension__ struct{ cl_float lo, hi; };
-#endif
-#if defined( __CL_FLOAT2__)
- __cl_float2 v2;
-#endif
-}cl_float2;
-
-typedef union
-{
- cl_float CL_ALIGNED(16) s[4];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_float x, y, z, w; };
- __extension__ struct{ cl_float s0, s1, s2, s3; };
- __extension__ struct{ cl_float2 lo, hi; };
-#endif
-#if defined( __CL_FLOAT2__)
- __cl_float2 v2[2];
-#endif
-#if defined( __CL_FLOAT4__)
- __cl_float4 v4;
-#endif
-}cl_float4;
-
-/* cl_float3 is identical in size, alignment and behavior to cl_float4. See section 6.1.5. */
-typedef cl_float4 cl_float3;
-
-typedef union
-{
- cl_float CL_ALIGNED(32) s[8];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_float x, y, z, w; };
- __extension__ struct{ cl_float s0, s1, s2, s3, s4, s5, s6, s7; };
- __extension__ struct{ cl_float4 lo, hi; };
-#endif
-#if defined( __CL_FLOAT2__)
- __cl_float2 v2[4];
-#endif
-#if defined( __CL_FLOAT4__)
- __cl_float4 v4[2];
-#endif
-#if defined( __CL_FLOAT8__ )
- __cl_float8 v8;
-#endif
-}cl_float8;
-
-typedef union
-{
- cl_float CL_ALIGNED(64) s[16];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_float x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf; };
- __extension__ struct{ cl_float s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF; };
- __extension__ struct{ cl_float8 lo, hi; };
-#endif
-#if defined( __CL_FLOAT2__)
- __cl_float2 v2[8];
-#endif
-#if defined( __CL_FLOAT4__)
- __cl_float4 v4[4];
-#endif
-#if defined( __CL_FLOAT8__ )
- __cl_float8 v8[2];
-#endif
-#if defined( __CL_FLOAT16__ )
- __cl_float16 v16;
-#endif
-}cl_float16;
-
-/* --- cl_doublen ---- */
-
-typedef union
-{
- cl_double CL_ALIGNED(16) s[2];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_double x, y; };
- __extension__ struct{ cl_double s0, s1; };
- __extension__ struct{ cl_double lo, hi; };
+#if defined(__GNUC__) && !defined(__ICC)
+ typedef float __cl_float4 __attribute__((vector_size(16)));
+#else
+ typedef __m128 __cl_float4;
#endif
-#if defined( __CL_DOUBLE2__)
- __cl_double2 v2;
+#define __CL_FLOAT4__ 1
#endif
-}cl_double2;
-typedef union
-{
- cl_double CL_ALIGNED(32) s[4];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_double x, y, z, w; };
- __extension__ struct{ cl_double s0, s1, s2, s3; };
- __extension__ struct{ cl_double2 lo, hi; };
+#if defined(__SSE2__)
+#if defined(__MINGW64__)
+#include <intrin.h>
+#else
+#include <emmintrin.h>
+#endif
+#if defined(__GNUC__) && !defined(__ICC)
+ typedef cl_uchar __cl_uchar16 __attribute__((vector_size(16)));
+ typedef cl_char __cl_char16 __attribute__((vector_size(16)));
+ typedef cl_ushort __cl_ushort8 __attribute__((vector_size(16)));
+ typedef cl_short __cl_short8 __attribute__((vector_size(16)));
+ typedef cl_uint __cl_uint4 __attribute__((vector_size(16)));
+ typedef cl_int __cl_int4 __attribute__((vector_size(16)));
+ typedef cl_ulong __cl_ulong2 __attribute__((vector_size(16)));
+ typedef cl_long __cl_long2 __attribute__((vector_size(16)));
+ typedef cl_double __cl_double2 __attribute__((vector_size(16)));
+#else
+ typedef __m128i __cl_uchar16;
+ typedef __m128i __cl_char16;
+ typedef __m128i __cl_ushort8;
+ typedef __m128i __cl_short8;
+ typedef __m128i __cl_uint4;
+ typedef __m128i __cl_int4;
+ typedef __m128i __cl_ulong2;
+ typedef __m128i __cl_long2;
+ typedef __m128d __cl_double2;
+#endif
+#define __CL_UCHAR16__ 1
+#define __CL_CHAR16__ 1
+#define __CL_USHORT8__ 1
+#define __CL_SHORT8__ 1
+#define __CL_INT4__ 1
+#define __CL_UINT4__ 1
+#define __CL_ULONG2__ 1
+#define __CL_LONG2__ 1
+#define __CL_DOUBLE2__ 1
+#endif
+
+#if defined(__MMX__)
+#include <mmintrin.h>
+#if defined(__GNUC__) && !defined(__ICC)
+ typedef cl_uchar __cl_uchar8 __attribute__((vector_size(8)));
+ typedef cl_char __cl_char8 __attribute__((vector_size(8)));
+ typedef cl_ushort __cl_ushort4 __attribute__((vector_size(8)));
+ typedef cl_short __cl_short4 __attribute__((vector_size(8)));
+ typedef cl_uint __cl_uint2 __attribute__((vector_size(8)));
+ typedef cl_int __cl_int2 __attribute__((vector_size(8)));
+ typedef cl_ulong __cl_ulong1 __attribute__((vector_size(8)));
+ typedef cl_long __cl_long1 __attribute__((vector_size(8)));
+ typedef cl_float __cl_float2 __attribute__((vector_size(8)));
+#else
+ typedef __m64 __cl_uchar8;
+ typedef __m64 __cl_char8;
+ typedef __m64 __cl_ushort4;
+ typedef __m64 __cl_short4;
+ typedef __m64 __cl_uint2;
+ typedef __m64 __cl_int2;
+ typedef __m64 __cl_ulong1;
+ typedef __m64 __cl_long1;
+ typedef __m64 __cl_float2;
+#endif
+#define __CL_UCHAR8__ 1
+#define __CL_CHAR8__ 1
+#define __CL_USHORT4__ 1
+#define __CL_SHORT4__ 1
+#define __CL_INT2__ 1
+#define __CL_UINT2__ 1
+#define __CL_ULONG1__ 1
+#define __CL_LONG1__ 1
+#define __CL_FLOAT2__ 1
+#endif
+
+#if defined(__AVX__)
+#if defined(__MINGW64__)
+#include <intrin.h>
+#else
+#include <immintrin.h>
#endif
-#if defined( __CL_DOUBLE2__)
- __cl_double2 v2[2];
+#if defined(__GNUC__) && !defined(__ICC)
+ typedef cl_float __cl_float8 __attribute__((vector_size(32)));
+ typedef cl_double __cl_double4 __attribute__((vector_size(32)));
+#else
+ typedef __m256 __cl_float8;
+ typedef __m256d __cl_double4;
#endif
-#if defined( __CL_DOUBLE4__)
- __cl_double4 v4;
+#define __CL_FLOAT8__ 1
+#define __CL_DOUBLE4__ 1
#endif
-}cl_double4;
-/* cl_double3 is identical in size, alignment and behavior to cl_double4. See section 6.1.5. */
-typedef cl_double4 cl_double3;
-
-typedef union
-{
- cl_double CL_ALIGNED(64) s[8];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_double x, y, z, w; };
- __extension__ struct{ cl_double s0, s1, s2, s3, s4, s5, s6, s7; };
- __extension__ struct{ cl_double4 lo, hi; };
-#endif
-#if defined( __CL_DOUBLE2__)
- __cl_double2 v2[4];
-#endif
-#if defined( __CL_DOUBLE4__)
- __cl_double4 v4[2];
-#endif
-#if defined( __CL_DOUBLE8__ )
- __cl_double8 v8;
+/* Define alignment keys */
+#if defined(__GNUC__)
+#define CL_ALIGNED(_x) __attribute__((aligned(_x)))
+#elif defined(_WIN32) && (_MSC_VER)
+/* Alignment keys neutered on windows because MSVC can't swallow function arguments with alignment requirements */
+/* http://msdn.microsoft.com/en-us/library/373ak2y1%28VS.71%29.aspx */
+/* #include <crtdefs.h> */
+/* #define CL_ALIGNED(_x) _CRT_ALIGN(_x) */
+#define CL_ALIGNED(_x)
+#else
+#warning Need to implement some method to align data here
+#define CL_ALIGNED(_x)
#endif
-}cl_double8;
-typedef union
-{
- cl_double CL_ALIGNED(128) s[16];
-#if defined( CL_NAMED_STRUCT_SUPPORTED )
- __extension__ struct{ cl_double x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf; };
- __extension__ struct{ cl_double s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF; };
- __extension__ struct{ cl_double8 lo, hi; };
-#endif
-#if defined( __CL_DOUBLE2__)
- __cl_double2 v2[8];
-#endif
-#if defined( __CL_DOUBLE4__)
- __cl_double4 v4[4];
-#endif
-#if defined( __CL_DOUBLE8__ )
- __cl_double8 v8[2];
-#endif
-#if defined( __CL_DOUBLE16__ )
- __cl_double16 v16;
-#endif
-}cl_double16;
+/* Indicate whether .xyzw, .s0123 and .hi.lo are supported */
+#if (defined(__GNUC__) && !defined(__STRICT_ANSI__)) || (defined(_MSC_VER) && !defined(__STDC__))
+/* .xyzw and .s0123...{f|F} are supported */
+#define CL_HAS_NAMED_VECTOR_FIELDS 1
+/* .hi and .lo are supported */
+#define CL_HAS_HI_LO_VECTOR_FIELDS 1
+
+#define CL_NAMED_STRUCT_SUPPORTED
+#endif
+
+#if defined(CL_NAMED_STRUCT_SUPPORTED) && defined(_MSC_VER)
+#define __extension__ __pragma(warning(suppress : 4201))
+#endif
+
+ /* Define cl_vector types */
+
+ /* ---- cl_charn ---- */
+ typedef union {
+ cl_char CL_ALIGNED(2) s[2];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_char x, y;
+ };
+ __extension__ struct
+ {
+ cl_char s0, s1;
+ };
+ __extension__ struct
+ {
+ cl_char lo, hi;
+ };
+#endif
+#if defined(__CL_CHAR2__)
+ __cl_char2 v2;
+#endif
+ } cl_char2;
+
+ typedef union {
+ cl_char CL_ALIGNED(4) s[4];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_char x, y, z, w;
+ };
+ __extension__ struct
+ {
+ cl_char s0, s1, s2, s3;
+ };
+ __extension__ struct
+ {
+ cl_char2 lo, hi;
+ };
+#endif
+#if defined(__CL_CHAR2__)
+ __cl_char2 v2[2];
+#endif
+#if defined(__CL_CHAR4__)
+ __cl_char4 v4;
+#endif
+ } cl_char4;
+
+ /* cl_char3 is identical in size, alignment and behavior to cl_char4. See section 6.1.5. */
+ typedef cl_char4 cl_char3;
+
+ typedef union {
+ cl_char CL_ALIGNED(8) s[8];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_char x, y, z, w;
+ };
+ __extension__ struct
+ {
+ cl_char s0, s1, s2, s3, s4, s5, s6, s7;
+ };
+ __extension__ struct
+ {
+ cl_char4 lo, hi;
+ };
+#endif
+#if defined(__CL_CHAR2__)
+ __cl_char2 v2[4];
+#endif
+#if defined(__CL_CHAR4__)
+ __cl_char4 v4[2];
+#endif
+#if defined(__CL_CHAR8__)
+ __cl_char8 v8;
+#endif
+ } cl_char8;
+
+ typedef union {
+ cl_char CL_ALIGNED(16) s[16];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_char x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf;
+ };
+ __extension__ struct
+ {
+ cl_char s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF;
+ };
+ __extension__ struct
+ {
+ cl_char8 lo, hi;
+ };
+#endif
+#if defined(__CL_CHAR2__)
+ __cl_char2 v2[8];
+#endif
+#if defined(__CL_CHAR4__)
+ __cl_char4 v4[4];
+#endif
+#if defined(__CL_CHAR8__)
+ __cl_char8 v8[2];
+#endif
+#if defined(__CL_CHAR16__)
+ __cl_char16 v16;
+#endif
+ } cl_char16;
+
+ /* ---- cl_ucharn ---- */
+ typedef union {
+ cl_uchar CL_ALIGNED(2) s[2];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_uchar x, y;
+ };
+ __extension__ struct
+ {
+ cl_uchar s0, s1;
+ };
+ __extension__ struct
+ {
+ cl_uchar lo, hi;
+ };
+#endif
+#if defined(__cl_uchar2__)
+ __cl_uchar2 v2;
+#endif
+ } cl_uchar2;
+
+ typedef union {
+ cl_uchar CL_ALIGNED(4) s[4];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_uchar x, y, z, w;
+ };
+ __extension__ struct
+ {
+ cl_uchar s0, s1, s2, s3;
+ };
+ __extension__ struct
+ {
+ cl_uchar2 lo, hi;
+ };
+#endif
+#if defined(__CL_UCHAR2__)
+ __cl_uchar2 v2[2];
+#endif
+#if defined(__CL_UCHAR4__)
+ __cl_uchar4 v4;
+#endif
+ } cl_uchar4;
+
+ /* cl_uchar3 is identical in size, alignment and behavior to cl_uchar4. See section 6.1.5. */
+ typedef cl_uchar4 cl_uchar3;
+
+ typedef union {
+ cl_uchar CL_ALIGNED(8) s[8];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_uchar x, y, z, w;
+ };
+ __extension__ struct
+ {
+ cl_uchar s0, s1, s2, s3, s4, s5, s6, s7;
+ };
+ __extension__ struct
+ {
+ cl_uchar4 lo, hi;
+ };
+#endif
+#if defined(__CL_UCHAR2__)
+ __cl_uchar2 v2[4];
+#endif
+#if defined(__CL_UCHAR4__)
+ __cl_uchar4 v4[2];
+#endif
+#if defined(__CL_UCHAR8__)
+ __cl_uchar8 v8;
+#endif
+ } cl_uchar8;
+
+ typedef union {
+ cl_uchar CL_ALIGNED(16) s[16];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_uchar x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf;
+ };
+ __extension__ struct
+ {
+ cl_uchar s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF;
+ };
+ __extension__ struct
+ {
+ cl_uchar8 lo, hi;
+ };
+#endif
+#if defined(__CL_UCHAR2__)
+ __cl_uchar2 v2[8];
+#endif
+#if defined(__CL_UCHAR4__)
+ __cl_uchar4 v4[4];
+#endif
+#if defined(__CL_UCHAR8__)
+ __cl_uchar8 v8[2];
+#endif
+#if defined(__CL_UCHAR16__)
+ __cl_uchar16 v16;
+#endif
+ } cl_uchar16;
+
+ /* ---- cl_shortn ---- */
+ typedef union {
+ cl_short CL_ALIGNED(4) s[2];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_short x, y;
+ };
+ __extension__ struct
+ {
+ cl_short s0, s1;
+ };
+ __extension__ struct
+ {
+ cl_short lo, hi;
+ };
+#endif
+#if defined(__CL_SHORT2__)
+ __cl_short2 v2;
+#endif
+ } cl_short2;
+
+ typedef union {
+ cl_short CL_ALIGNED(8) s[4];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_short x, y, z, w;
+ };
+ __extension__ struct
+ {
+ cl_short s0, s1, s2, s3;
+ };
+ __extension__ struct
+ {
+ cl_short2 lo, hi;
+ };
+#endif
+#if defined(__CL_SHORT2__)
+ __cl_short2 v2[2];
+#endif
+#if defined(__CL_SHORT4__)
+ __cl_short4 v4;
+#endif
+ } cl_short4;
+
+ /* cl_short3 is identical in size, alignment and behavior to cl_short4. See section 6.1.5. */
+ typedef cl_short4 cl_short3;
+
+ typedef union {
+ cl_short CL_ALIGNED(16) s[8];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_short x, y, z, w;
+ };
+ __extension__ struct
+ {
+ cl_short s0, s1, s2, s3, s4, s5, s6, s7;
+ };
+ __extension__ struct
+ {
+ cl_short4 lo, hi;
+ };
+#endif
+#if defined(__CL_SHORT2__)
+ __cl_short2 v2[4];
+#endif
+#if defined(__CL_SHORT4__)
+ __cl_short4 v4[2];
+#endif
+#if defined(__CL_SHORT8__)
+ __cl_short8 v8;
+#endif
+ } cl_short8;
+
+ typedef union {
+ cl_short CL_ALIGNED(32) s[16];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_short x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf;
+ };
+ __extension__ struct
+ {
+ cl_short s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF;
+ };
+ __extension__ struct
+ {
+ cl_short8 lo, hi;
+ };
+#endif
+#if defined(__CL_SHORT2__)
+ __cl_short2 v2[8];
+#endif
+#if defined(__CL_SHORT4__)
+ __cl_short4 v4[4];
+#endif
+#if defined(__CL_SHORT8__)
+ __cl_short8 v8[2];
+#endif
+#if defined(__CL_SHORT16__)
+ __cl_short16 v16;
+#endif
+ } cl_short16;
+
+ /* ---- cl_ushortn ---- */
+ typedef union {
+ cl_ushort CL_ALIGNED(4) s[2];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_ushort x, y;
+ };
+ __extension__ struct
+ {
+ cl_ushort s0, s1;
+ };
+ __extension__ struct
+ {
+ cl_ushort lo, hi;
+ };
+#endif
+#if defined(__CL_USHORT2__)
+ __cl_ushort2 v2;
+#endif
+ } cl_ushort2;
+
+ typedef union {
+ cl_ushort CL_ALIGNED(8) s[4];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_ushort x, y, z, w;
+ };
+ __extension__ struct
+ {
+ cl_ushort s0, s1, s2, s3;
+ };
+ __extension__ struct
+ {
+ cl_ushort2 lo, hi;
+ };
+#endif
+#if defined(__CL_USHORT2__)
+ __cl_ushort2 v2[2];
+#endif
+#if defined(__CL_USHORT4__)
+ __cl_ushort4 v4;
+#endif
+ } cl_ushort4;
+
+ /* cl_ushort3 is identical in size, alignment and behavior to cl_ushort4. See section 6.1.5. */
+ typedef cl_ushort4 cl_ushort3;
+
+ typedef union {
+ cl_ushort CL_ALIGNED(16) s[8];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_ushort x, y, z, w;
+ };
+ __extension__ struct
+ {
+ cl_ushort s0, s1, s2, s3, s4, s5, s6, s7;
+ };
+ __extension__ struct
+ {
+ cl_ushort4 lo, hi;
+ };
+#endif
+#if defined(__CL_USHORT2__)
+ __cl_ushort2 v2[4];
+#endif
+#if defined(__CL_USHORT4__)
+ __cl_ushort4 v4[2];
+#endif
+#if defined(__CL_USHORT8__)
+ __cl_ushort8 v8;
+#endif
+ } cl_ushort8;
+
+ typedef union {
+ cl_ushort CL_ALIGNED(32) s[16];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_ushort x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf;
+ };
+ __extension__ struct
+ {
+ cl_ushort s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF;
+ };
+ __extension__ struct
+ {
+ cl_ushort8 lo, hi;
+ };
+#endif
+#if defined(__CL_USHORT2__)
+ __cl_ushort2 v2[8];
+#endif
+#if defined(__CL_USHORT4__)
+ __cl_ushort4 v4[4];
+#endif
+#if defined(__CL_USHORT8__)
+ __cl_ushort8 v8[2];
+#endif
+#if defined(__CL_USHORT16__)
+ __cl_ushort16 v16;
+#endif
+ } cl_ushort16;
+
+ /* ---- cl_intn ---- */
+ typedef union {
+ cl_int CL_ALIGNED(8) s[2];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_int x, y;
+ };
+ __extension__ struct
+ {
+ cl_int s0, s1;
+ };
+ __extension__ struct
+ {
+ cl_int lo, hi;
+ };
+#endif
+#if defined(__CL_INT2__)
+ __cl_int2 v2;
+#endif
+ } cl_int2;
+
+ typedef union {
+ cl_int CL_ALIGNED(16) s[4];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_int x, y, z, w;
+ };
+ __extension__ struct
+ {
+ cl_int s0, s1, s2, s3;
+ };
+ __extension__ struct
+ {
+ cl_int2 lo, hi;
+ };
+#endif
+#if defined(__CL_INT2__)
+ __cl_int2 v2[2];
+#endif
+#if defined(__CL_INT4__)
+ __cl_int4 v4;
+#endif
+ } cl_int4;
+
+ /* cl_int3 is identical in size, alignment and behavior to cl_int4. See section 6.1.5. */
+ typedef cl_int4 cl_int3;
+
+ typedef union {
+ cl_int CL_ALIGNED(32) s[8];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_int x, y, z, w;
+ };
+ __extension__ struct
+ {
+ cl_int s0, s1, s2, s3, s4, s5, s6, s7;
+ };
+ __extension__ struct
+ {
+ cl_int4 lo, hi;
+ };
+#endif
+#if defined(__CL_INT2__)
+ __cl_int2 v2[4];
+#endif
+#if defined(__CL_INT4__)
+ __cl_int4 v4[2];
+#endif
+#if defined(__CL_INT8__)
+ __cl_int8 v8;
+#endif
+ } cl_int8;
+
+ typedef union {
+ cl_int CL_ALIGNED(64) s[16];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_int x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf;
+ };
+ __extension__ struct
+ {
+ cl_int s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF;
+ };
+ __extension__ struct
+ {
+ cl_int8 lo, hi;
+ };
+#endif
+#if defined(__CL_INT2__)
+ __cl_int2 v2[8];
+#endif
+#if defined(__CL_INT4__)
+ __cl_int4 v4[4];
+#endif
+#if defined(__CL_INT8__)
+ __cl_int8 v8[2];
+#endif
+#if defined(__CL_INT16__)
+ __cl_int16 v16;
+#endif
+ } cl_int16;
+
+ /* ---- cl_uintn ---- */
+ typedef union {
+ cl_uint CL_ALIGNED(8) s[2];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_uint x, y;
+ };
+ __extension__ struct
+ {
+ cl_uint s0, s1;
+ };
+ __extension__ struct
+ {
+ cl_uint lo, hi;
+ };
+#endif
+#if defined(__CL_UINT2__)
+ __cl_uint2 v2;
+#endif
+ } cl_uint2;
+
+ typedef union {
+ cl_uint CL_ALIGNED(16) s[4];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_uint x, y, z, w;
+ };
+ __extension__ struct
+ {
+ cl_uint s0, s1, s2, s3;
+ };
+ __extension__ struct
+ {
+ cl_uint2 lo, hi;
+ };
+#endif
+#if defined(__CL_UINT2__)
+ __cl_uint2 v2[2];
+#endif
+#if defined(__CL_UINT4__)
+ __cl_uint4 v4;
+#endif
+ } cl_uint4;
+
+ /* cl_uint3 is identical in size, alignment and behavior to cl_uint4. See section 6.1.5. */
+ typedef cl_uint4 cl_uint3;
+
+ typedef union {
+ cl_uint CL_ALIGNED(32) s[8];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_uint x, y, z, w;
+ };
+ __extension__ struct
+ {
+ cl_uint s0, s1, s2, s3, s4, s5, s6, s7;
+ };
+ __extension__ struct
+ {
+ cl_uint4 lo, hi;
+ };
+#endif
+#if defined(__CL_UINT2__)
+ __cl_uint2 v2[4];
+#endif
+#if defined(__CL_UINT4__)
+ __cl_uint4 v4[2];
+#endif
+#if defined(__CL_UINT8__)
+ __cl_uint8 v8;
+#endif
+ } cl_uint8;
+
+ typedef union {
+ cl_uint CL_ALIGNED(64) s[16];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_uint x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf;
+ };
+ __extension__ struct
+ {
+ cl_uint s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF;
+ };
+ __extension__ struct
+ {
+ cl_uint8 lo, hi;
+ };
+#endif
+#if defined(__CL_UINT2__)
+ __cl_uint2 v2[8];
+#endif
+#if defined(__CL_UINT4__)
+ __cl_uint4 v4[4];
+#endif
+#if defined(__CL_UINT8__)
+ __cl_uint8 v8[2];
+#endif
+#if defined(__CL_UINT16__)
+ __cl_uint16 v16;
+#endif
+ } cl_uint16;
+
+ /* ---- cl_longn ---- */
+ typedef union {
+ cl_long CL_ALIGNED(16) s[2];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_long x, y;
+ };
+ __extension__ struct
+ {
+ cl_long s0, s1;
+ };
+ __extension__ struct
+ {
+ cl_long lo, hi;
+ };
+#endif
+#if defined(__CL_LONG2__)
+ __cl_long2 v2;
+#endif
+ } cl_long2;
+
+ typedef union {
+ cl_long CL_ALIGNED(32) s[4];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_long x, y, z, w;
+ };
+ __extension__ struct
+ {
+ cl_long s0, s1, s2, s3;
+ };
+ __extension__ struct
+ {
+ cl_long2 lo, hi;
+ };
+#endif
+#if defined(__CL_LONG2__)
+ __cl_long2 v2[2];
+#endif
+#if defined(__CL_LONG4__)
+ __cl_long4 v4;
+#endif
+ } cl_long4;
+
+ /* cl_long3 is identical in size, alignment and behavior to cl_long4. See section 6.1.5. */
+ typedef cl_long4 cl_long3;
+
+ typedef union {
+ cl_long CL_ALIGNED(64) s[8];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_long x, y, z, w;
+ };
+ __extension__ struct
+ {
+ cl_long s0, s1, s2, s3, s4, s5, s6, s7;
+ };
+ __extension__ struct
+ {
+ cl_long4 lo, hi;
+ };
+#endif
+#if defined(__CL_LONG2__)
+ __cl_long2 v2[4];
+#endif
+#if defined(__CL_LONG4__)
+ __cl_long4 v4[2];
+#endif
+#if defined(__CL_LONG8__)
+ __cl_long8 v8;
+#endif
+ } cl_long8;
+
+ typedef union {
+ cl_long CL_ALIGNED(128) s[16];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_long x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf;
+ };
+ __extension__ struct
+ {
+ cl_long s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF;
+ };
+ __extension__ struct
+ {
+ cl_long8 lo, hi;
+ };
+#endif
+#if defined(__CL_LONG2__)
+ __cl_long2 v2[8];
+#endif
+#if defined(__CL_LONG4__)
+ __cl_long4 v4[4];
+#endif
+#if defined(__CL_LONG8__)
+ __cl_long8 v8[2];
+#endif
+#if defined(__CL_LONG16__)
+ __cl_long16 v16;
+#endif
+ } cl_long16;
+
+ /* ---- cl_ulongn ---- */
+ typedef union {
+ cl_ulong CL_ALIGNED(16) s[2];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_ulong x, y;
+ };
+ __extension__ struct
+ {
+ cl_ulong s0, s1;
+ };
+ __extension__ struct
+ {
+ cl_ulong lo, hi;
+ };
+#endif
+#if defined(__CL_ULONG2__)
+ __cl_ulong2 v2;
+#endif
+ } cl_ulong2;
+
+ typedef union {
+ cl_ulong CL_ALIGNED(32) s[4];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_ulong x, y, z, w;
+ };
+ __extension__ struct
+ {
+ cl_ulong s0, s1, s2, s3;
+ };
+ __extension__ struct
+ {
+ cl_ulong2 lo, hi;
+ };
+#endif
+#if defined(__CL_ULONG2__)
+ __cl_ulong2 v2[2];
+#endif
+#if defined(__CL_ULONG4__)
+ __cl_ulong4 v4;
+#endif
+ } cl_ulong4;
+
+ /* cl_ulong3 is identical in size, alignment and behavior to cl_ulong4. See section 6.1.5. */
+ typedef cl_ulong4 cl_ulong3;
+
+ typedef union {
+ cl_ulong CL_ALIGNED(64) s[8];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_ulong x, y, z, w;
+ };
+ __extension__ struct
+ {
+ cl_ulong s0, s1, s2, s3, s4, s5, s6, s7;
+ };
+ __extension__ struct
+ {
+ cl_ulong4 lo, hi;
+ };
+#endif
+#if defined(__CL_ULONG2__)
+ __cl_ulong2 v2[4];
+#endif
+#if defined(__CL_ULONG4__)
+ __cl_ulong4 v4[2];
+#endif
+#if defined(__CL_ULONG8__)
+ __cl_ulong8 v8;
+#endif
+ } cl_ulong8;
+
+ typedef union {
+ cl_ulong CL_ALIGNED(128) s[16];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_ulong x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf;
+ };
+ __extension__ struct
+ {
+ cl_ulong s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF;
+ };
+ __extension__ struct
+ {
+ cl_ulong8 lo, hi;
+ };
+#endif
+#if defined(__CL_ULONG2__)
+ __cl_ulong2 v2[8];
+#endif
+#if defined(__CL_ULONG4__)
+ __cl_ulong4 v4[4];
+#endif
+#if defined(__CL_ULONG8__)
+ __cl_ulong8 v8[2];
+#endif
+#if defined(__CL_ULONG16__)
+ __cl_ulong16 v16;
+#endif
+ } cl_ulong16;
+
+ /* --- cl_floatn ---- */
+
+ typedef union {
+ cl_float CL_ALIGNED(8) s[2];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_float x, y;
+ };
+ __extension__ struct
+ {
+ cl_float s0, s1;
+ };
+ __extension__ struct
+ {
+ cl_float lo, hi;
+ };
+#endif
+#if defined(__CL_FLOAT2__)
+ __cl_float2 v2;
+#endif
+ } cl_float2;
+
+ typedef union {
+ cl_float CL_ALIGNED(16) s[4];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_float x, y, z, w;
+ };
+ __extension__ struct
+ {
+ cl_float s0, s1, s2, s3;
+ };
+ __extension__ struct
+ {
+ cl_float2 lo, hi;
+ };
+#endif
+#if defined(__CL_FLOAT2__)
+ __cl_float2 v2[2];
+#endif
+#if defined(__CL_FLOAT4__)
+ __cl_float4 v4;
+#endif
+ } cl_float4;
+
+ /* cl_float3 is identical in size, alignment and behavior to cl_float4. See section 6.1.5. */
+ typedef cl_float4 cl_float3;
+
+ typedef union {
+ cl_float CL_ALIGNED(32) s[8];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_float x, y, z, w;
+ };
+ __extension__ struct
+ {
+ cl_float s0, s1, s2, s3, s4, s5, s6, s7;
+ };
+ __extension__ struct
+ {
+ cl_float4 lo, hi;
+ };
+#endif
+#if defined(__CL_FLOAT2__)
+ __cl_float2 v2[4];
+#endif
+#if defined(__CL_FLOAT4__)
+ __cl_float4 v4[2];
+#endif
+#if defined(__CL_FLOAT8__)
+ __cl_float8 v8;
+#endif
+ } cl_float8;
+
+ typedef union {
+ cl_float CL_ALIGNED(64) s[16];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_float x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf;
+ };
+ __extension__ struct
+ {
+ cl_float s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF;
+ };
+ __extension__ struct
+ {
+ cl_float8 lo, hi;
+ };
+#endif
+#if defined(__CL_FLOAT2__)
+ __cl_float2 v2[8];
+#endif
+#if defined(__CL_FLOAT4__)
+ __cl_float4 v4[4];
+#endif
+#if defined(__CL_FLOAT8__)
+ __cl_float8 v8[2];
+#endif
+#if defined(__CL_FLOAT16__)
+ __cl_float16 v16;
+#endif
+ } cl_float16;
+
+ /* --- cl_doublen ---- */
+
+ typedef union {
+ cl_double CL_ALIGNED(16) s[2];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_double x, y;
+ };
+ __extension__ struct
+ {
+ cl_double s0, s1;
+ };
+ __extension__ struct
+ {
+ cl_double lo, hi;
+ };
+#endif
+#if defined(__CL_DOUBLE2__)
+ __cl_double2 v2;
+#endif
+ } cl_double2;
+
+ typedef union {
+ cl_double CL_ALIGNED(32) s[4];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_double x, y, z, w;
+ };
+ __extension__ struct
+ {
+ cl_double s0, s1, s2, s3;
+ };
+ __extension__ struct
+ {
+ cl_double2 lo, hi;
+ };
+#endif
+#if defined(__CL_DOUBLE2__)
+ __cl_double2 v2[2];
+#endif
+#if defined(__CL_DOUBLE4__)
+ __cl_double4 v4;
+#endif
+ } cl_double4;
+
+ /* cl_double3 is identical in size, alignment and behavior to cl_double4. See section 6.1.5. */
+ typedef cl_double4 cl_double3;
+
+ typedef union {
+ cl_double CL_ALIGNED(64) s[8];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_double x, y, z, w;
+ };
+ __extension__ struct
+ {
+ cl_double s0, s1, s2, s3, s4, s5, s6, s7;
+ };
+ __extension__ struct
+ {
+ cl_double4 lo, hi;
+ };
+#endif
+#if defined(__CL_DOUBLE2__)
+ __cl_double2 v2[4];
+#endif
+#if defined(__CL_DOUBLE4__)
+ __cl_double4 v4[2];
+#endif
+#if defined(__CL_DOUBLE8__)
+ __cl_double8 v8;
+#endif
+ } cl_double8;
+
+ typedef union {
+ cl_double CL_ALIGNED(128) s[16];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+ __extension__ struct
+ {
+ cl_double x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf;
+ };
+ __extension__ struct
+ {
+ cl_double s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF;
+ };
+ __extension__ struct
+ {
+ cl_double8 lo, hi;
+ };
+#endif
+#if defined(__CL_DOUBLE2__)
+ __cl_double2 v2[8];
+#endif
+#if defined(__CL_DOUBLE4__)
+ __cl_double4 v4[4];
+#endif
+#if defined(__CL_DOUBLE8__)
+ __cl_double8 v8[2];
+#endif
+#if defined(__CL_DOUBLE16__)
+ __cl_double16 v16;
+#endif
+ } cl_double16;
/* Macro to facilitate debugging
* Usage:
@@ -1237,967 +1551,967 @@ typedef union
* This should correctly set up the line, (column) and file information for your source
* string so you can do source level debugging.
*/
-#define __CL_STRINGIFY( _x ) # _x
-#define _CL_STRINGIFY( _x ) __CL_STRINGIFY( _x )
-#define CL_PROGRAM_STRING_DEBUG_INFO "#line " _CL_STRINGIFY(__LINE__) " \"" __FILE__ "\" \n\n"
-
-// CL.h contents
-/******************************************************************************/
-
-typedef struct _cl_platform_id * cl_platform_id;
-typedef struct _cl_device_id * cl_device_id;
-typedef struct _cl_context * cl_context;
-typedef struct _cl_command_queue * cl_command_queue;
-typedef struct _cl_mem * cl_mem;
-typedef struct _cl_program * cl_program;
-typedef struct _cl_kernel * cl_kernel;
-typedef struct _cl_event * cl_event;
-typedef struct _cl_sampler * cl_sampler;
-
-typedef cl_uint cl_bool; /* WARNING! Unlike cl_ types in cl_platform.h, cl_bool is not guaranteed to be the same size as the bool in kernels. */
-typedef cl_ulong cl_bitfield;
-typedef cl_bitfield cl_device_type;
-typedef cl_uint cl_platform_info;
-typedef cl_uint cl_device_info;
-typedef cl_bitfield cl_device_fp_config;
-typedef cl_uint cl_device_mem_cache_type;
-typedef cl_uint cl_device_local_mem_type;
-typedef cl_bitfield cl_device_exec_capabilities;
-typedef cl_bitfield cl_command_queue_properties;
-
-typedef intptr_t cl_context_properties;
-typedef cl_uint cl_context_info;
-typedef cl_uint cl_command_queue_info;
-typedef cl_uint cl_channel_order;
-typedef cl_uint cl_channel_type;
-typedef cl_bitfield cl_mem_flags;
-typedef cl_uint cl_mem_object_type;
-typedef cl_uint cl_mem_info;
-typedef cl_uint cl_image_info;
-typedef cl_uint cl_buffer_create_type;
-typedef cl_uint cl_addressing_mode;
-typedef cl_uint cl_filter_mode;
-typedef cl_uint cl_sampler_info;
-typedef cl_bitfield cl_map_flags;
-typedef cl_uint cl_program_info;
-typedef cl_uint cl_program_build_info;
-typedef cl_int cl_build_status;
-typedef cl_uint cl_kernel_info;
-typedef cl_uint cl_kernel_work_group_info;
-typedef cl_uint cl_event_info;
-typedef cl_uint cl_command_type;
-typedef cl_uint cl_profiling_info;
-
-typedef struct _cl_image_format {
- cl_channel_order image_channel_order;
- cl_channel_type image_channel_data_type;
-} cl_image_format;
-
-
-typedef struct _cl_buffer_region {
- size_t origin;
- size_t size;
-} cl_buffer_region;
+#define __CL_STRINGIFY(_x) #_x
+#define _CL_STRINGIFY(_x) __CL_STRINGIFY(_x)
+#define CL_PROGRAM_STRING_DEBUG_INFO "#line " _CL_STRINGIFY(__LINE__) " \"" __FILE__ "\" \n\n"
+
+ // CL.h contents
+ /******************************************************************************/
+
+ typedef struct _cl_platform_id *cl_platform_id;
+ typedef struct _cl_device_id *cl_device_id;
+ typedef struct _cl_context *cl_context;
+ typedef struct _cl_command_queue *cl_command_queue;
+ typedef struct _cl_mem *cl_mem;
+ typedef struct _cl_program *cl_program;
+ typedef struct _cl_kernel *cl_kernel;
+ typedef struct _cl_event *cl_event;
+ typedef struct _cl_sampler *cl_sampler;
+
+ typedef cl_uint cl_bool; /* WARNING! Unlike cl_ types in cl_platform.h, cl_bool is not guaranteed to be the same size as the bool in kernels. */
+ typedef cl_ulong cl_bitfield;
+ typedef cl_bitfield cl_device_type;
+ typedef cl_uint cl_platform_info;
+ typedef cl_uint cl_device_info;
+ typedef cl_bitfield cl_device_fp_config;
+ typedef cl_uint cl_device_mem_cache_type;
+ typedef cl_uint cl_device_local_mem_type;
+ typedef cl_bitfield cl_device_exec_capabilities;
+ typedef cl_bitfield cl_command_queue_properties;
+
+ typedef intptr_t cl_context_properties;
+ typedef cl_uint cl_context_info;
+ typedef cl_uint cl_command_queue_info;
+ typedef cl_uint cl_channel_order;
+ typedef cl_uint cl_channel_type;
+ typedef cl_bitfield cl_mem_flags;
+ typedef cl_uint cl_mem_object_type;
+ typedef cl_uint cl_mem_info;
+ typedef cl_uint cl_image_info;
+ typedef cl_uint cl_buffer_create_type;
+ typedef cl_uint cl_addressing_mode;
+ typedef cl_uint cl_filter_mode;
+ typedef cl_uint cl_sampler_info;
+ typedef cl_bitfield cl_map_flags;
+ typedef cl_uint cl_program_info;
+ typedef cl_uint cl_program_build_info;
+ typedef cl_int cl_build_status;
+ typedef cl_uint cl_kernel_info;
+ typedef cl_uint cl_kernel_work_group_info;
+ typedef cl_uint cl_event_info;
+ typedef cl_uint cl_command_type;
+ typedef cl_uint cl_profiling_info;
+
+ typedef struct _cl_image_format
+ {
+ cl_channel_order image_channel_order;
+ cl_channel_type image_channel_data_type;
+ } cl_image_format;
+
+ typedef struct _cl_buffer_region
+ {
+ size_t origin;
+ size_t size;
+ } cl_buffer_region;
/******************************************************************************/
/* Error Codes */
-#define CL_SUCCESS 0
-#define CL_DEVICE_NOT_FOUND -1
-#define CL_DEVICE_NOT_AVAILABLE -2
-#define CL_COMPILER_NOT_AVAILABLE -3
-#define CL_MEM_OBJECT_ALLOCATION_FAILURE -4
-#define CL_OUT_OF_RESOURCES -5
-#define CL_OUT_OF_HOST_MEMORY -6
-#define CL_PROFILING_INFO_NOT_AVAILABLE -7
-#define CL_MEM_COPY_OVERLAP -8
-#define CL_IMAGE_FORMAT_MISMATCH -9
-#define CL_IMAGE_FORMAT_NOT_SUPPORTED -10
-#define CL_BUILD_PROGRAM_FAILURE -11
-#define CL_MAP_FAILURE -12
-#define CL_MISALIGNED_SUB_BUFFER_OFFSET -13
+#define CL_SUCCESS 0
+#define CL_DEVICE_NOT_FOUND -1
+#define CL_DEVICE_NOT_AVAILABLE -2
+#define CL_COMPILER_NOT_AVAILABLE -3
+#define CL_MEM_OBJECT_ALLOCATION_FAILURE -4
+#define CL_OUT_OF_RESOURCES -5
+#define CL_OUT_OF_HOST_MEMORY -6
+#define CL_PROFILING_INFO_NOT_AVAILABLE -7
+#define CL_MEM_COPY_OVERLAP -8
+#define CL_IMAGE_FORMAT_MISMATCH -9
+#define CL_IMAGE_FORMAT_NOT_SUPPORTED -10
+#define CL_BUILD_PROGRAM_FAILURE -11
+#define CL_MAP_FAILURE -12
+#define CL_MISALIGNED_SUB_BUFFER_OFFSET -13
#define CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST -14
-#define CL_INVALID_VALUE -30
-#define CL_INVALID_DEVICE_TYPE -31
-#define CL_INVALID_PLATFORM -32
-#define CL_INVALID_DEVICE -33
-#define CL_INVALID_CONTEXT -34
-#define CL_INVALID_QUEUE_PROPERTIES -35
-#define CL_INVALID_COMMAND_QUEUE -36
-#define CL_INVALID_HOST_PTR -37
-#define CL_INVALID_MEM_OBJECT -38
-#define CL_INVALID_IMAGE_FORMAT_DESCRIPTOR -39
-#define CL_INVALID_IMAGE_SIZE -40
-#define CL_INVALID_SAMPLER -41
-#define CL_INVALID_BINARY -42
-#define CL_INVALID_BUILD_OPTIONS -43
-#define CL_INVALID_PROGRAM -44
-#define CL_INVALID_PROGRAM_EXECUTABLE -45
-#define CL_INVALID_KERNEL_NAME -46
-#define CL_INVALID_KERNEL_DEFINITION -47
-#define CL_INVALID_KERNEL -48
-#define CL_INVALID_ARG_INDEX -49
-#define CL_INVALID_ARG_VALUE -50
-#define CL_INVALID_ARG_SIZE -51
-#define CL_INVALID_KERNEL_ARGS -52
-#define CL_INVALID_WORK_DIMENSION -53
-#define CL_INVALID_WORK_GROUP_SIZE -54
-#define CL_INVALID_WORK_ITEM_SIZE -55
-#define CL_INVALID_GLOBAL_OFFSET -56
-#define CL_INVALID_EVENT_WAIT_LIST -57
-#define CL_INVALID_EVENT -58
-#define CL_INVALID_OPERATION -59
-#define CL_INVALID_GL_OBJECT -60
-#define CL_INVALID_BUFFER_SIZE -61
-#define CL_INVALID_MIP_LEVEL -62
-#define CL_INVALID_GLOBAL_WORK_SIZE -63
-#define CL_INVALID_PROPERTY -64
+#define CL_INVALID_VALUE -30
+#define CL_INVALID_DEVICE_TYPE -31
+#define CL_INVALID_PLATFORM -32
+#define CL_INVALID_DEVICE -33
+#define CL_INVALID_CONTEXT -34
+#define CL_INVALID_QUEUE_PROPERTIES -35
+#define CL_INVALID_COMMAND_QUEUE -36
+#define CL_INVALID_HOST_PTR -37
+#define CL_INVALID_MEM_OBJECT -38
+#define CL_INVALID_IMAGE_FORMAT_DESCRIPTOR -39
+#define CL_INVALID_IMAGE_SIZE -40
+#define CL_INVALID_SAMPLER -41
+#define CL_INVALID_BINARY -42
+#define CL_INVALID_BUILD_OPTIONS -43
+#define CL_INVALID_PROGRAM -44
+#define CL_INVALID_PROGRAM_EXECUTABLE -45
+#define CL_INVALID_KERNEL_NAME -46
+#define CL_INVALID_KERNEL_DEFINITION -47
+#define CL_INVALID_KERNEL -48
+#define CL_INVALID_ARG_INDEX -49
+#define CL_INVALID_ARG_VALUE -50
+#define CL_INVALID_ARG_SIZE -51
+#define CL_INVALID_KERNEL_ARGS -52
+#define CL_INVALID_WORK_DIMENSION -53
+#define CL_INVALID_WORK_GROUP_SIZE -54
+#define CL_INVALID_WORK_ITEM_SIZE -55
+#define CL_INVALID_GLOBAL_OFFSET -56
+#define CL_INVALID_EVENT_WAIT_LIST -57
+#define CL_INVALID_EVENT -58
+#define CL_INVALID_OPERATION -59
+#define CL_INVALID_GL_OBJECT -60
+#define CL_INVALID_BUFFER_SIZE -61
+#define CL_INVALID_MIP_LEVEL -62
+#define CL_INVALID_GLOBAL_WORK_SIZE -63
+#define CL_INVALID_PROPERTY -64
/* OpenCL Version */
-#define CL_VERSION_1_0 1
-#define CL_VERSION_1_1 1
+#define CL_VERSION_1_0 1
+#define CL_VERSION_1_1 1
/* cl_bool */
-#define CL_FALSE 0
-#define CL_TRUE 1
+#define CL_FALSE 0
+#define CL_TRUE 1
/* cl_platform_info */
-#define CL_PLATFORM_PROFILE 0x0900
-#define CL_PLATFORM_VERSION 0x0901
-#define CL_PLATFORM_NAME 0x0902
-#define CL_PLATFORM_VENDOR 0x0903
-#define CL_PLATFORM_EXTENSIONS 0x0904
+#define CL_PLATFORM_PROFILE 0x0900
+#define CL_PLATFORM_VERSION 0x0901
+#define CL_PLATFORM_NAME 0x0902
+#define CL_PLATFORM_VENDOR 0x0903
+#define CL_PLATFORM_EXTENSIONS 0x0904
/* cl_device_type - bitfield */
-#define CL_DEVICE_TYPE_DEFAULT (1 << 0)
-#define CL_DEVICE_TYPE_CPU (1 << 1)
-#define CL_DEVICE_TYPE_GPU (1 << 2)
-#define CL_DEVICE_TYPE_ACCELERATOR (1 << 3)
-#define CL_DEVICE_TYPE_ALL 0xFFFFFFFF
+#define CL_DEVICE_TYPE_DEFAULT (1 << 0)
+#define CL_DEVICE_TYPE_CPU (1 << 1)
+#define CL_DEVICE_TYPE_GPU (1 << 2)
+#define CL_DEVICE_TYPE_ACCELERATOR (1 << 3)
+#define CL_DEVICE_TYPE_ALL 0xFFFFFFFF
/* cl_device_info */
-#define CL_DEVICE_TYPE 0x1000
-#define CL_DEVICE_VENDOR_ID 0x1001
-#define CL_DEVICE_MAX_COMPUTE_UNITS 0x1002
-#define CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS 0x1003
-#define CL_DEVICE_MAX_WORK_GROUP_SIZE 0x1004
-#define CL_DEVICE_MAX_WORK_ITEM_SIZES 0x1005
-#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR 0x1006
-#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT 0x1007
-#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT 0x1008
-#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG 0x1009
-#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT 0x100A
-#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE 0x100B
-#define CL_DEVICE_MAX_CLOCK_FREQUENCY 0x100C
-#define CL_DEVICE_ADDRESS_BITS 0x100D
-#define CL_DEVICE_MAX_READ_IMAGE_ARGS 0x100E
-#define CL_DEVICE_MAX_WRITE_IMAGE_ARGS 0x100F
-#define CL_DEVICE_MAX_MEM_ALLOC_SIZE 0x1010
-#define CL_DEVICE_IMAGE2D_MAX_WIDTH 0x1011
-#define CL_DEVICE_IMAGE2D_MAX_HEIGHT 0x1012
-#define CL_DEVICE_IMAGE3D_MAX_WIDTH 0x1013
-#define CL_DEVICE_IMAGE3D_MAX_HEIGHT 0x1014
-#define CL_DEVICE_IMAGE3D_MAX_DEPTH 0x1015
-#define CL_DEVICE_IMAGE_SUPPORT 0x1016
-#define CL_DEVICE_MAX_PARAMETER_SIZE 0x1017
-#define CL_DEVICE_MAX_SAMPLERS 0x1018
-#define CL_DEVICE_MEM_BASE_ADDR_ALIGN 0x1019
-#define CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE 0x101A
-#define CL_DEVICE_SINGLE_FP_CONFIG 0x101B
-#define CL_DEVICE_GLOBAL_MEM_CACHE_TYPE 0x101C
-#define CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE 0x101D
-#define CL_DEVICE_GLOBAL_MEM_CACHE_SIZE 0x101E
-#define CL_DEVICE_GLOBAL_MEM_SIZE 0x101F
-#define CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE 0x1020
-#define CL_DEVICE_MAX_CONSTANT_ARGS 0x1021
-#define CL_DEVICE_LOCAL_MEM_TYPE 0x1022
-#define CL_DEVICE_LOCAL_MEM_SIZE 0x1023
-#define CL_DEVICE_ERROR_CORRECTION_SUPPORT 0x1024
-#define CL_DEVICE_PROFILING_TIMER_RESOLUTION 0x1025
-#define CL_DEVICE_ENDIAN_LITTLE 0x1026
-#define CL_DEVICE_AVAILABLE 0x1027
-#define CL_DEVICE_COMPILER_AVAILABLE 0x1028
-#define CL_DEVICE_EXECUTION_CAPABILITIES 0x1029
-#define CL_DEVICE_QUEUE_PROPERTIES 0x102A
-#define CL_DEVICE_NAME 0x102B
-#define CL_DEVICE_VENDOR 0x102C
-#define CL_DRIVER_VERSION 0x102D
-#define CL_DEVICE_PROFILE 0x102E
-#define CL_DEVICE_VERSION 0x102F
-#define CL_DEVICE_EXTENSIONS 0x1030
-#define CL_DEVICE_PLATFORM 0x1031
+#define CL_DEVICE_TYPE 0x1000
+#define CL_DEVICE_VENDOR_ID 0x1001
+#define CL_DEVICE_MAX_COMPUTE_UNITS 0x1002
+#define CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS 0x1003
+#define CL_DEVICE_MAX_WORK_GROUP_SIZE 0x1004
+#define CL_DEVICE_MAX_WORK_ITEM_SIZES 0x1005
+#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR 0x1006
+#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT 0x1007
+#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT 0x1008
+#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG 0x1009
+#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT 0x100A
+#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE 0x100B
+#define CL_DEVICE_MAX_CLOCK_FREQUENCY 0x100C
+#define CL_DEVICE_ADDRESS_BITS 0x100D
+#define CL_DEVICE_MAX_READ_IMAGE_ARGS 0x100E
+#define CL_DEVICE_MAX_WRITE_IMAGE_ARGS 0x100F
+#define CL_DEVICE_MAX_MEM_ALLOC_SIZE 0x1010
+#define CL_DEVICE_IMAGE2D_MAX_WIDTH 0x1011
+#define CL_DEVICE_IMAGE2D_MAX_HEIGHT 0x1012
+#define CL_DEVICE_IMAGE3D_MAX_WIDTH 0x1013
+#define CL_DEVICE_IMAGE3D_MAX_HEIGHT 0x1014
+#define CL_DEVICE_IMAGE3D_MAX_DEPTH 0x1015
+#define CL_DEVICE_IMAGE_SUPPORT 0x1016
+#define CL_DEVICE_MAX_PARAMETER_SIZE 0x1017
+#define CL_DEVICE_MAX_SAMPLERS 0x1018
+#define CL_DEVICE_MEM_BASE_ADDR_ALIGN 0x1019
+#define CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE 0x101A
+#define CL_DEVICE_SINGLE_FP_CONFIG 0x101B
+#define CL_DEVICE_GLOBAL_MEM_CACHE_TYPE 0x101C
+#define CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE 0x101D
+#define CL_DEVICE_GLOBAL_MEM_CACHE_SIZE 0x101E
+#define CL_DEVICE_GLOBAL_MEM_SIZE 0x101F
+#define CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE 0x1020
+#define CL_DEVICE_MAX_CONSTANT_ARGS 0x1021
+#define CL_DEVICE_LOCAL_MEM_TYPE 0x1022
+#define CL_DEVICE_LOCAL_MEM_SIZE 0x1023
+#define CL_DEVICE_ERROR_CORRECTION_SUPPORT 0x1024
+#define CL_DEVICE_PROFILING_TIMER_RESOLUTION 0x1025
+#define CL_DEVICE_ENDIAN_LITTLE 0x1026
+#define CL_DEVICE_AVAILABLE 0x1027
+#define CL_DEVICE_COMPILER_AVAILABLE 0x1028
+#define CL_DEVICE_EXECUTION_CAPABILITIES 0x1029
+#define CL_DEVICE_QUEUE_PROPERTIES 0x102A
+#define CL_DEVICE_NAME 0x102B
+#define CL_DEVICE_VENDOR 0x102C
+#define CL_DRIVER_VERSION 0x102D
+#define CL_DEVICE_PROFILE 0x102E
+#define CL_DEVICE_VERSION 0x102F
+#define CL_DEVICE_EXTENSIONS 0x1030
+#define CL_DEVICE_PLATFORM 0x1031
/* 0x1032 reserved for CL_DEVICE_DOUBLE_FP_CONFIG */
/* 0x1033 reserved for CL_DEVICE_HALF_FP_CONFIG */
-#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF 0x1034
-#define CL_DEVICE_HOST_UNIFIED_MEMORY 0x1035
-#define CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR 0x1036
-#define CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT 0x1037
-#define CL_DEVICE_NATIVE_VECTOR_WIDTH_INT 0x1038
-#define CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG 0x1039
-#define CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT 0x103A
-#define CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE 0x103B
-#define CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF 0x103C
-#define CL_DEVICE_OPENCL_C_VERSION 0x103D
+#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF 0x1034
+#define CL_DEVICE_HOST_UNIFIED_MEMORY 0x1035
+#define CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR 0x1036
+#define CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT 0x1037
+#define CL_DEVICE_NATIVE_VECTOR_WIDTH_INT 0x1038
+#define CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG 0x1039
+#define CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT 0x103A
+#define CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE 0x103B
+#define CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF 0x103C
+#define CL_DEVICE_OPENCL_C_VERSION 0x103D
/* cl_device_fp_config - bitfield */
-#define CL_FP_DENORM (1 << 0)
-#define CL_FP_INF_NAN (1 << 1)
-#define CL_FP_ROUND_TO_NEAREST (1 << 2)
-#define CL_FP_ROUND_TO_ZERO (1 << 3)
-#define CL_FP_ROUND_TO_INF (1 << 4)
-#define CL_FP_FMA (1 << 5)
-#define CL_FP_SOFT_FLOAT (1 << 6)
+#define CL_FP_DENORM (1 << 0)
+#define CL_FP_INF_NAN (1 << 1)
+#define CL_FP_ROUND_TO_NEAREST (1 << 2)
+#define CL_FP_ROUND_TO_ZERO (1 << 3)
+#define CL_FP_ROUND_TO_INF (1 << 4)
+#define CL_FP_FMA (1 << 5)
+#define CL_FP_SOFT_FLOAT (1 << 6)
/* cl_device_mem_cache_type */
-#define CL_NONE 0x0
-#define CL_READ_ONLY_CACHE 0x1
-#define CL_READ_WRITE_CACHE 0x2
+#define CL_NONE 0x0
+#define CL_READ_ONLY_CACHE 0x1
+#define CL_READ_WRITE_CACHE 0x2
/* cl_device_local_mem_type */
-#define CL_LOCAL 0x1
-#define CL_GLOBAL 0x2
+#define CL_LOCAL 0x1
+#define CL_GLOBAL 0x2
/* cl_device_exec_capabilities - bitfield */
-#define CL_EXEC_KERNEL (1 << 0)
-#define CL_EXEC_NATIVE_KERNEL (1 << 1)
+#define CL_EXEC_KERNEL (1 << 0)
+#define CL_EXEC_NATIVE_KERNEL (1 << 1)
/* cl_command_queue_properties - bitfield */
-#define CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE (1 << 0)
-#define CL_QUEUE_PROFILING_ENABLE (1 << 1)
+#define CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE (1 << 0)
+#define CL_QUEUE_PROFILING_ENABLE (1 << 1)
/* cl_context_info */
-#define CL_CONTEXT_REFERENCE_COUNT 0x1080
-#define CL_CONTEXT_DEVICES 0x1081
-#define CL_CONTEXT_PROPERTIES 0x1082
-#define CL_CONTEXT_NUM_DEVICES 0x1083
+#define CL_CONTEXT_REFERENCE_COUNT 0x1080
+#define CL_CONTEXT_DEVICES 0x1081
+#define CL_CONTEXT_PROPERTIES 0x1082
+#define CL_CONTEXT_NUM_DEVICES 0x1083
/* cl_context_info + cl_context_properties */
-#define CL_CONTEXT_PLATFORM 0x1084
+#define CL_CONTEXT_PLATFORM 0x1084
/* cl_command_queue_info */
-#define CL_QUEUE_CONTEXT 0x1090
-#define CL_QUEUE_DEVICE 0x1091
-#define CL_QUEUE_REFERENCE_COUNT 0x1092
-#define CL_QUEUE_PROPERTIES 0x1093
+#define CL_QUEUE_CONTEXT 0x1090
+#define CL_QUEUE_DEVICE 0x1091
+#define CL_QUEUE_REFERENCE_COUNT 0x1092
+#define CL_QUEUE_PROPERTIES 0x1093
/* cl_mem_flags - bitfield */
-#define CL_MEM_READ_WRITE (1 << 0)
-#define CL_MEM_WRITE_ONLY (1 << 1)
-#define CL_MEM_READ_ONLY (1 << 2)
-#define CL_MEM_USE_HOST_PTR (1 << 3)
-#define CL_MEM_ALLOC_HOST_PTR (1 << 4)
-#define CL_MEM_COPY_HOST_PTR (1 << 5)
+#define CL_MEM_READ_WRITE (1 << 0)
+#define CL_MEM_WRITE_ONLY (1 << 1)
+#define CL_MEM_READ_ONLY (1 << 2)
+#define CL_MEM_USE_HOST_PTR (1 << 3)
+#define CL_MEM_ALLOC_HOST_PTR (1 << 4)
+#define CL_MEM_COPY_HOST_PTR (1 << 5)
/* cl_channel_order */
-#define CL_R 0x10B0
-#define CL_A 0x10B1
-#define CL_RG 0x10B2
-#define CL_RA 0x10B3
-#define CL_RGB 0x10B4
-#define CL_RGBA 0x10B5
-#define CL_BGRA 0x10B6
-#define CL_ARGB 0x10B7
-#define CL_INTENSITY 0x10B8
-#define CL_LUMINANCE 0x10B9
-#define CL_Rx 0x10BA
-#define CL_RGx 0x10BB
-#define CL_RGBx 0x10BC
+#define CL_R 0x10B0
+#define CL_A 0x10B1
+#define CL_RG 0x10B2
+#define CL_RA 0x10B3
+#define CL_RGB 0x10B4
+#define CL_RGBA 0x10B5
+#define CL_BGRA 0x10B6
+#define CL_ARGB 0x10B7
+#define CL_INTENSITY 0x10B8
+#define CL_LUMINANCE 0x10B9
+#define CL_Rx 0x10BA
+#define CL_RGx 0x10BB
+#define CL_RGBx 0x10BC
/* cl_channel_type */
-#define CL_SNORM_INT8 0x10D0
-#define CL_SNORM_INT16 0x10D1
-#define CL_UNORM_INT8 0x10D2
-#define CL_UNORM_INT16 0x10D3
-#define CL_UNORM_SHORT_565 0x10D4
-#define CL_UNORM_SHORT_555 0x10D5
-#define CL_UNORM_INT_101010 0x10D6
-#define CL_SIGNED_INT8 0x10D7
-#define CL_SIGNED_INT16 0x10D8
-#define CL_SIGNED_INT32 0x10D9
-#define CL_UNSIGNED_INT8 0x10DA
-#define CL_UNSIGNED_INT16 0x10DB
-#define CL_UNSIGNED_INT32 0x10DC
-#define CL_HALF_FLOAT 0x10DD
-#define CL_FLOAT 0x10DE
+#define CL_SNORM_INT8 0x10D0
+#define CL_SNORM_INT16 0x10D1
+#define CL_UNORM_INT8 0x10D2
+#define CL_UNORM_INT16 0x10D3
+#define CL_UNORM_SHORT_565 0x10D4
+#define CL_UNORM_SHORT_555 0x10D5
+#define CL_UNORM_INT_101010 0x10D6
+#define CL_SIGNED_INT8 0x10D7
+#define CL_SIGNED_INT16 0x10D8
+#define CL_SIGNED_INT32 0x10D9
+#define CL_UNSIGNED_INT8 0x10DA
+#define CL_UNSIGNED_INT16 0x10DB
+#define CL_UNSIGNED_INT32 0x10DC
+#define CL_HALF_FLOAT 0x10DD
+#define CL_FLOAT 0x10DE
/* cl_mem_object_type */
-#define CL_MEM_OBJECT_BUFFER 0x10F0
-#define CL_MEM_OBJECT_IMAGE2D 0x10F1
-#define CL_MEM_OBJECT_IMAGE3D 0x10F2
+#define CL_MEM_OBJECT_BUFFER 0x10F0
+#define CL_MEM_OBJECT_IMAGE2D 0x10F1
+#define CL_MEM_OBJECT_IMAGE3D 0x10F2
/* cl_mem_info */
-#define CL_MEM_TYPE 0x1100
-#define CL_MEM_FLAGS 0x1101
-#define CL_MEM_SIZE 0x1102
-#define CL_MEM_HOST_PTR 0x1103
-#define CL_MEM_MAP_COUNT 0x1104
-#define CL_MEM_REFERENCE_COUNT 0x1105
-#define CL_MEM_CONTEXT 0x1106
-#define CL_MEM_ASSOCIATED_MEMOBJECT 0x1107
-#define CL_MEM_OFFSET 0x1108
+#define CL_MEM_TYPE 0x1100
+#define CL_MEM_FLAGS 0x1101
+#define CL_MEM_SIZE 0x1102
+#define CL_MEM_HOST_PTR 0x1103
+#define CL_MEM_MAP_COUNT 0x1104
+#define CL_MEM_REFERENCE_COUNT 0x1105
+#define CL_MEM_CONTEXT 0x1106
+#define CL_MEM_ASSOCIATED_MEMOBJECT 0x1107
+#define CL_MEM_OFFSET 0x1108
/* cl_image_info */
-#define CL_IMAGE_FORMAT 0x1110
-#define CL_IMAGE_ELEMENT_SIZE 0x1111
-#define CL_IMAGE_ROW_PITCH 0x1112
-#define CL_IMAGE_SLICE_PITCH 0x1113
-#define CL_IMAGE_WIDTH 0x1114
-#define CL_IMAGE_HEIGHT 0x1115
-#define CL_IMAGE_DEPTH 0x1116
+#define CL_IMAGE_FORMAT 0x1110
+#define CL_IMAGE_ELEMENT_SIZE 0x1111
+#define CL_IMAGE_ROW_PITCH 0x1112
+#define CL_IMAGE_SLICE_PITCH 0x1113
+#define CL_IMAGE_WIDTH 0x1114
+#define CL_IMAGE_HEIGHT 0x1115
+#define CL_IMAGE_DEPTH 0x1116
/* cl_addressing_mode */
-#define CL_ADDRESS_NONE 0x1130
-#define CL_ADDRESS_CLAMP_TO_EDGE 0x1131
-#define CL_ADDRESS_CLAMP 0x1132
-#define CL_ADDRESS_REPEAT 0x1133
-#define CL_ADDRESS_MIRRORED_REPEAT 0x1134
+#define CL_ADDRESS_NONE 0x1130
+#define CL_ADDRESS_CLAMP_TO_EDGE 0x1131
+#define CL_ADDRESS_CLAMP 0x1132
+#define CL_ADDRESS_REPEAT 0x1133
+#define CL_ADDRESS_MIRRORED_REPEAT 0x1134
/* cl_filter_mode */
-#define CL_FILTER_NEAREST 0x1140
-#define CL_FILTER_LINEAR 0x1141
+#define CL_FILTER_NEAREST 0x1140
+#define CL_FILTER_LINEAR 0x1141
/* cl_sampler_info */
-#define CL_SAMPLER_REFERENCE_COUNT 0x1150
-#define CL_SAMPLER_CONTEXT 0x1151
-#define CL_SAMPLER_NORMALIZED_COORDS 0x1152
-#define CL_SAMPLER_ADDRESSING_MODE 0x1153
-#define CL_SAMPLER_FILTER_MODE 0x1154
+#define CL_SAMPLER_REFERENCE_COUNT 0x1150
+#define CL_SAMPLER_CONTEXT 0x1151
+#define CL_SAMPLER_NORMALIZED_COORDS 0x1152
+#define CL_SAMPLER_ADDRESSING_MODE 0x1153
+#define CL_SAMPLER_FILTER_MODE 0x1154
/* cl_map_flags - bitfield */
-#define CL_MAP_READ (1 << 0)
-#define CL_MAP_WRITE (1 << 1)
+#define CL_MAP_READ (1 << 0)
+#define CL_MAP_WRITE (1 << 1)
/* cl_program_info */
-#define CL_PROGRAM_REFERENCE_COUNT 0x1160
-#define CL_PROGRAM_CONTEXT 0x1161
-#define CL_PROGRAM_NUM_DEVICES 0x1162
-#define CL_PROGRAM_DEVICES 0x1163
-#define CL_PROGRAM_SOURCE 0x1164
-#define CL_PROGRAM_BINARY_SIZES 0x1165
-#define CL_PROGRAM_BINARIES 0x1166
+#define CL_PROGRAM_REFERENCE_COUNT 0x1160
+#define CL_PROGRAM_CONTEXT 0x1161
+#define CL_PROGRAM_NUM_DEVICES 0x1162
+#define CL_PROGRAM_DEVICES 0x1163
+#define CL_PROGRAM_SOURCE 0x1164
+#define CL_PROGRAM_BINARY_SIZES 0x1165
+#define CL_PROGRAM_BINARIES 0x1166
/* cl_program_build_info */
-#define CL_PROGRAM_BUILD_STATUS 0x1181
-#define CL_PROGRAM_BUILD_OPTIONS 0x1182
-#define CL_PROGRAM_BUILD_LOG 0x1183
+#define CL_PROGRAM_BUILD_STATUS 0x1181
+#define CL_PROGRAM_BUILD_OPTIONS 0x1182
+#define CL_PROGRAM_BUILD_LOG 0x1183
/* cl_build_status */
-#define CL_BUILD_SUCCESS 0
-#define CL_BUILD_NONE -1
-#define CL_BUILD_ERROR -2
-#define CL_BUILD_IN_PROGRESS -3
+#define CL_BUILD_SUCCESS 0
+#define CL_BUILD_NONE -1
+#define CL_BUILD_ERROR -2
+#define CL_BUILD_IN_PROGRESS -3
/* cl_kernel_info */
-#define CL_KERNEL_FUNCTION_NAME 0x1190
-#define CL_KERNEL_NUM_ARGS 0x1191
-#define CL_KERNEL_REFERENCE_COUNT 0x1192
-#define CL_KERNEL_CONTEXT 0x1193
-#define CL_KERNEL_PROGRAM 0x1194
+#define CL_KERNEL_FUNCTION_NAME 0x1190
+#define CL_KERNEL_NUM_ARGS 0x1191
+#define CL_KERNEL_REFERENCE_COUNT 0x1192
+#define CL_KERNEL_CONTEXT 0x1193
+#define CL_KERNEL_PROGRAM 0x1194
/* cl_kernel_work_group_info */
-#define CL_KERNEL_WORK_GROUP_SIZE 0x11B0
-#define CL_KERNEL_COMPILE_WORK_GROUP_SIZE 0x11B1
-#define CL_KERNEL_LOCAL_MEM_SIZE 0x11B2
+#define CL_KERNEL_WORK_GROUP_SIZE 0x11B0
+#define CL_KERNEL_COMPILE_WORK_GROUP_SIZE 0x11B1
+#define CL_KERNEL_LOCAL_MEM_SIZE 0x11B2
#define CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE 0x11B3
-#define CL_KERNEL_PRIVATE_MEM_SIZE 0x11B4
+#define CL_KERNEL_PRIVATE_MEM_SIZE 0x11B4
/* cl_event_info */
-#define CL_EVENT_COMMAND_QUEUE 0x11D0
-#define CL_EVENT_COMMAND_TYPE 0x11D1
-#define CL_EVENT_REFERENCE_COUNT 0x11D2
-#define CL_EVENT_COMMAND_EXECUTION_STATUS 0x11D3
-#define CL_EVENT_CONTEXT 0x11D4
+#define CL_EVENT_COMMAND_QUEUE 0x11D0
+#define CL_EVENT_COMMAND_TYPE 0x11D1
+#define CL_EVENT_REFERENCE_COUNT 0x11D2
+#define CL_EVENT_COMMAND_EXECUTION_STATUS 0x11D3
+#define CL_EVENT_CONTEXT 0x11D4
/* cl_command_type */
-#define CL_COMMAND_NDRANGE_KERNEL 0x11F0
-#define CL_COMMAND_TASK 0x11F1
-#define CL_COMMAND_NATIVE_KERNEL 0x11F2
-#define CL_COMMAND_READ_BUFFER 0x11F3
-#define CL_COMMAND_WRITE_BUFFER 0x11F4
-#define CL_COMMAND_COPY_BUFFER 0x11F5
-#define CL_COMMAND_READ_IMAGE 0x11F6
-#define CL_COMMAND_WRITE_IMAGE 0x11F7
-#define CL_COMMAND_COPY_IMAGE 0x11F8
-#define CL_COMMAND_COPY_IMAGE_TO_BUFFER 0x11F9
-#define CL_COMMAND_COPY_BUFFER_TO_IMAGE 0x11FA
-#define CL_COMMAND_MAP_BUFFER 0x11FB
-#define CL_COMMAND_MAP_IMAGE 0x11FC
-#define CL_COMMAND_UNMAP_MEM_OBJECT 0x11FD
-#define CL_COMMAND_MARKER 0x11FE
-#define CL_COMMAND_ACQUIRE_GL_OBJECTS 0x11FF
-#define CL_COMMAND_RELEASE_GL_OBJECTS 0x1200
-#define CL_COMMAND_READ_BUFFER_RECT 0x1201
-#define CL_COMMAND_WRITE_BUFFER_RECT 0x1202
-#define CL_COMMAND_COPY_BUFFER_RECT 0x1203
-#define CL_COMMAND_USER 0x1204
+#define CL_COMMAND_NDRANGE_KERNEL 0x11F0
+#define CL_COMMAND_TASK 0x11F1
+#define CL_COMMAND_NATIVE_KERNEL 0x11F2
+#define CL_COMMAND_READ_BUFFER 0x11F3
+#define CL_COMMAND_WRITE_BUFFER 0x11F4
+#define CL_COMMAND_COPY_BUFFER 0x11F5
+#define CL_COMMAND_READ_IMAGE 0x11F6
+#define CL_COMMAND_WRITE_IMAGE 0x11F7
+#define CL_COMMAND_COPY_IMAGE 0x11F8
+#define CL_COMMAND_COPY_IMAGE_TO_BUFFER 0x11F9
+#define CL_COMMAND_COPY_BUFFER_TO_IMAGE 0x11FA
+#define CL_COMMAND_MAP_BUFFER 0x11FB
+#define CL_COMMAND_MAP_IMAGE 0x11FC
+#define CL_COMMAND_UNMAP_MEM_OBJECT 0x11FD
+#define CL_COMMAND_MARKER 0x11FE
+#define CL_COMMAND_ACQUIRE_GL_OBJECTS 0x11FF
+#define CL_COMMAND_RELEASE_GL_OBJECTS 0x1200
+#define CL_COMMAND_READ_BUFFER_RECT 0x1201
+#define CL_COMMAND_WRITE_BUFFER_RECT 0x1202
+#define CL_COMMAND_COPY_BUFFER_RECT 0x1203
+#define CL_COMMAND_USER 0x1204
/* command execution status */
-#define CL_COMPLETE 0x0
-#define CL_RUNNING 0x1
-#define CL_SUBMITTED 0x2
-#define CL_QUEUED 0x3
-
+#define CL_COMPLETE 0x0
+#define CL_RUNNING 0x1
+#define CL_SUBMITTED 0x2
+#define CL_QUEUED 0x3
+
/* cl_buffer_create_type */
-#define CL_BUFFER_CREATE_TYPE_REGION 0x1220
+#define CL_BUFFER_CREATE_TYPE_REGION 0x1220
/* cl_profiling_info */
-#define CL_PROFILING_COMMAND_QUEUED 0x1280
-#define CL_PROFILING_COMMAND_SUBMIT 0x1281
-#define CL_PROFILING_COMMAND_START 0x1282
-#define CL_PROFILING_COMMAND_END 0x1283
-
-/********************************************************************************************************/
-
-/********************************************************************************************************/
-
-/* Function signature typedef's */
-
-/* Platform API */
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETPLATFORMIDS)(cl_uint /* num_entries */,
- cl_platform_id * /* platforms */,
- cl_uint * /* num_platforms */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETPLATFORMINFO)(cl_platform_id /* platform */,
- cl_platform_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-/* Device APIs */
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETDEVICEIDS)(cl_platform_id /* platform */,
- cl_device_type /* device_type */,
- cl_uint /* num_entries */,
- cl_device_id * /* devices */,
- cl_uint * /* num_devices */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETDEVICEINFO)(cl_device_id /* device */,
- cl_device_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-// Context APIs
-typedef CL_API_ENTRY cl_context (CL_API_CALL *
-PFNCLCREATECONTEXT)(const cl_context_properties * /* properties */,
- cl_uint /* num_devices */,
- const cl_device_id * /* devices */,
- void (CL_CALLBACK * /* pfn_notify */)(const char *, const void *, size_t, void *),
- void * /* user_data */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_context (CL_API_CALL *
-PFNCLCREATECONTEXTFROMTYPE)(const cl_context_properties * /* properties */,
- cl_device_type /* device_type */,
- void (CL_CALLBACK * /* pfn_notify*/ )(const char *, const void *, size_t, void *),
- void * /* user_data */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRETAINCONTEXT)(cl_context /* context */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRELEASECONTEXT)(cl_context /* context */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETCONTEXTINFO)(cl_context /* context */,
- cl_context_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-/* Command Queue APIs */
-typedef CL_API_ENTRY cl_command_queue (CL_API_CALL *
-PFNCLCREATECOMMANDQUEUE)(cl_context /* context */,
- cl_device_id /* device */,
- cl_command_queue_properties /* properties */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRETAINCOMMANDQUEUE)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRELEASECOMMANDQUEUE)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETCOMMANDQUEUEINFO)(cl_command_queue /* command_queue */,
- cl_command_queue_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLSETCOMMANDQUEUEPROPERTY)(cl_command_queue /* command_queue */,
- cl_command_queue_properties /* properties */,
- cl_bool /* enable */,
- cl_command_queue_properties * /* old_properties */) CL_API_SUFFIX__VERSION_1_0;
-
-/* Memory Object APIs */
-typedef CL_API_ENTRY cl_mem (CL_API_CALL *
-PFNCLCREATEBUFFER)(cl_context /* context */,
- cl_mem_flags /* flags */,
- size_t /* size */,
- void * /* host_ptr */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_mem (CL_API_CALL *
-PFNCLCREATESUBBUFFER)(cl_mem /* buffer */,
- cl_mem_flags /* flags */,
- cl_buffer_create_type /* buffer_create_type */,
- const void * /* buffer_create_info */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_1;
-
-typedef CL_API_ENTRY cl_mem (CL_API_CALL *
-PFNCLCREATEIMAGE2D)(cl_context /* context */,
- cl_mem_flags /* flags */,
- const cl_image_format * /* image_format */,
- size_t /* image_width */,
- size_t /* image_height */,
- size_t /* image_row_pitch */,
- void * /* host_ptr */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_mem (CL_API_CALL *
-PFNCLCREATEIMAGE3D)(cl_context /* context */,
- cl_mem_flags /* flags */,
- const cl_image_format * /* image_format */,
- size_t /* image_width */,
- size_t /* image_height */,
- size_t /* image_depth */,
- size_t /* image_row_pitch */,
- size_t /* image_slice_pitch */,
- void * /* host_ptr */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRETAINMEMOBJECT)(cl_mem /* memobj */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRELEASEMEMOBJECT)(cl_mem /* memobj */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETSUPPORTEDIMAGEFORMATS)(cl_context /* context */,
- cl_mem_flags /* flags */,
- cl_mem_object_type /* image_type */,
- cl_uint /* num_entries */,
- cl_image_format * /* image_formats */,
- cl_uint * /* num_image_formats */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETMEMOBJECTINFO)(cl_mem /* memobj */,
- cl_mem_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETIMAGEINFO)(cl_mem /* image */,
- cl_image_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLSETMEMOBJECTDESTRUCTORCALLBACK)( cl_mem /* memobj */,
- void (CL_CALLBACK * /*pfn_notify*/)( cl_mem /* memobj */, void* /*user_data*/),
- void * /*user_data */ ) CL_API_SUFFIX__VERSION_1_1;
-
-/* Sampler APIs */
-typedef CL_API_ENTRY cl_sampler (CL_API_CALL *
-PFNCLCREATESAMPLER)(cl_context /* context */,
- cl_bool /* normalized_coords */,
- cl_addressing_mode /* addressing_mode */,
- cl_filter_mode /* filter_mode */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRETAINSAMPLER)(cl_sampler /* sampler */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRELEASESAMPLER)(cl_sampler /* sampler */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETSAMPLERINFO)(cl_sampler /* sampler */,
- cl_sampler_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-/* Program Object APIs */
-typedef CL_API_ENTRY cl_program (CL_API_CALL *
-PFNCLCREATEPROGRAMWITHSOURCE)(cl_context /* context */,
- cl_uint /* count */,
- const char ** /* strings */,
- const size_t * /* lengths */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_program (CL_API_CALL *
-PFNCLCREATEPROGRAMWITHBINARY)(cl_context /* context */,
- cl_uint /* num_devices */,
- const cl_device_id * /* device_list */,
- const size_t * /* lengths */,
- const unsigned char ** /* binaries */,
- cl_int * /* binary_status */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRETAINPROGRAM)(cl_program /* program */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRELEASEPROGRAM)(cl_program /* program */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLBUILDPROGRAM)(cl_program /* program */,
- cl_uint /* num_devices */,
- const cl_device_id * /* device_list */,
- const char * /* options */,
- void (CL_CALLBACK * /* pfn_notify */)(cl_program /* program */, void * /* user_data */),
- void * /* user_data */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLUNLOADCOMPILER)(void) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETPROGRAMINFO)(cl_program /* program */,
- cl_program_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETPROGRAMBUILDINFO)(cl_program /* program */,
- cl_device_id /* device */,
- cl_program_build_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-/* Kernel Object APIs */
-typedef CL_API_ENTRY cl_kernel (CL_API_CALL *
-PFNCLCREATEKERNEL)(cl_program /* program */,
- const char * /* kernel_name */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLCREATEKERNELSINPROGRAM)(cl_program /* program */,
- cl_uint /* num_kernels */,
- cl_kernel * /* kernels */,
- cl_uint * /* num_kernels_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRETAINKERNEL)(cl_kernel /* kernel */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRELEASEKERNEL)(cl_kernel /* kernel */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLSETKERNELARG)(cl_kernel /* kernel */,
- cl_uint /* arg_index */,
- size_t /* arg_size */,
- const void * /* arg_value */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETKERNELINFO)(cl_kernel /* kernel */,
- cl_kernel_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETKERNELWORKGROUPINFO)(cl_kernel /* kernel */,
- cl_device_id /* device */,
- cl_kernel_work_group_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-// Event Object APIs
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLWAITFOREVENTS)(cl_uint /* num_events */,
- const cl_event * /* event_list */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETEVENTINFO)(cl_event /* event */,
- cl_event_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_event (CL_API_CALL *
-PFNCLCREATEUSEREVENT)(cl_context /* context */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_1;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRETAINEVENT)(cl_event /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRELEASEEVENT)(cl_event /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLSETUSEREVENTSTATUS)(cl_event /* event */,
- cl_int /* execution_status */) CL_API_SUFFIX__VERSION_1_1;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLSETEVENTCALLBACK)( cl_event /* event */,
- cl_int /* command_exec_callback_type */,
- void (CL_CALLBACK * /* pfn_notify */)(cl_event, cl_int, void *),
- void * /* user_data */) CL_API_SUFFIX__VERSION_1_1;
-
-/* Profiling APIs */
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETEVENTPROFILINGINFO)(cl_event /* event */,
- cl_profiling_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-// Flush and Finish APIs
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLFLUSH)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLFINISH)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
-
-/* Enqueued Commands APIs */
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUEREADBUFFER)(cl_command_queue /* command_queue */,
- cl_mem /* buffer */,
- cl_bool /* blocking_read */,
- size_t /* offset */,
- size_t /* cb */,
- void * /* ptr */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUEREADBUFFERRECT)(cl_command_queue /* command_queue */,
- cl_mem /* buffer */,
- cl_bool /* blocking_read */,
- const size_t * /* buffer_origin */,
- const size_t * /* host_origin */,
- const size_t * /* region */,
- size_t /* buffer_row_pitch */,
- size_t /* buffer_slice_pitch */,
- size_t /* host_row_pitch */,
- size_t /* host_slice_pitch */,
- void * /* ptr */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_1;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUEWRITEBUFFER)(cl_command_queue /* command_queue */,
- cl_mem /* buffer */,
- cl_bool /* blocking_write */,
- size_t /* offset */,
- size_t /* cb */,
- const void * /* ptr */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUEWRITEBUFFERRECT)(cl_command_queue /* command_queue */,
- cl_mem /* buffer */,
- cl_bool /* blocking_write */,
- const size_t * /* buffer_origin */,
- const size_t * /* host_origin */,
- const size_t * /* region */,
- size_t /* buffer_row_pitch */,
- size_t /* buffer_slice_pitch */,
- size_t /* host_row_pitch */,
- size_t /* host_slice_pitch */,
- const void * /* ptr */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_1;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUECOPYBUFFER)(cl_command_queue /* command_queue */,
- cl_mem /* src_buffer */,
- cl_mem /* dst_buffer */,
- size_t /* src_offset */,
- size_t /* dst_offset */,
- size_t /* cb */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUECOPYBUFFERRECT)(cl_command_queue /* command_queue */,
- cl_mem /* src_buffer */,
- cl_mem /* dst_buffer */,
- const size_t * /* src_origin */,
- const size_t * /* dst_origin */,
- const size_t * /* region */,
- size_t /* src_row_pitch */,
- size_t /* src_slice_pitch */,
- size_t /* dst_row_pitch */,
- size_t /* dst_slice_pitch */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_1;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUEREADIMAGE)(cl_command_queue /* command_queue */,
- cl_mem /* image */,
- cl_bool /* blocking_read */,
- const size_t * /* origin[3] */,
- const size_t * /* region[3] */,
- size_t /* row_pitch */,
- size_t /* slice_pitch */,
- void * /* ptr */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUEWRITEIMAGE)(cl_command_queue /* command_queue */,
- cl_mem /* image */,
- cl_bool /* blocking_write */,
- const size_t * /* origin[3] */,
- const size_t * /* region[3] */,
- size_t /* input_row_pitch */,
- size_t /* input_slice_pitch */,
- const void * /* ptr */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUECOPYIMAGE)(cl_command_queue /* command_queue */,
- cl_mem /* src_image */,
- cl_mem /* dst_image */,
- const size_t * /* src_origin[3] */,
- const size_t * /* dst_origin[3] */,
- const size_t * /* region[3] */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUECOPYIMAGETOBUFFER)(cl_command_queue /* command_queue */,
- cl_mem /* src_image */,
- cl_mem /* dst_buffer */,
- const size_t * /* src_origin[3] */,
- const size_t * /* region[3] */,
- size_t /* dst_offset */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUECOPYBUFFERTOIMAGE)(cl_command_queue /* command_queue */,
- cl_mem /* src_buffer */,
- cl_mem /* dst_image */,
- size_t /* src_offset */,
- const size_t * /* dst_origin[3] */,
- const size_t * /* region[3] */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY void * (CL_API_CALL *
-PFNCLENQUEUEMAPBUFFER)(cl_command_queue /* command_queue */,
- cl_mem /* buffer */,
- cl_bool /* blocking_map */,
- cl_map_flags /* map_flags */,
- size_t /* offset */,
- size_t /* cb */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY void * (CL_API_CALL *
-PFNCLENQUEUEMAPIMAGE)(cl_command_queue /* command_queue */,
- cl_mem /* image */,
- cl_bool /* blocking_map */,
- cl_map_flags /* map_flags */,
- const size_t * /* origin[3] */,
- const size_t * /* region[3] */,
- size_t * /* image_row_pitch */,
- size_t * /* image_slice_pitch */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUEUNMAPMEMOBJECT)(cl_command_queue /* command_queue */,
- cl_mem /* memobj */,
- void * /* mapped_ptr */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUENDRANGEKERNEL)(cl_command_queue /* command_queue */,
- cl_kernel /* kernel */,
- cl_uint /* work_dim */,
- const size_t * /* global_work_offset */,
- const size_t * /* global_work_size */,
- const size_t * /* local_work_size */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUETASK)(cl_command_queue /* command_queue */,
- cl_kernel /* kernel */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUENATIVEKERNEL)(cl_command_queue /* command_queue */,
- void (*user_func)(void *),
- void * /* args */,
- size_t /* cb_args */,
- cl_uint /* num_mem_objects */,
- const cl_mem * /* mem_list */,
- const void ** /* args_mem_loc */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUEMARKER)(cl_command_queue /* command_queue */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUEWAITFOREVENTS)(cl_command_queue /* command_queue */,
- cl_uint /* num_events */,
- const cl_event * /* event_list */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUEBARRIER)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
-
-// Extension function access
-//
-// Returns the extension function address for the given function name,
-// or NULL if a valid function can not be found. The client must
-// check to make sure the address is not NULL, before using or
-// calling the returned function address.
-//
-typedef CL_API_ENTRY void * (CL_API_CALL * PFNCLGETEXTENSIONFUNCTIONADDRESS)(const char * /* func_name */) CL_API_SUFFIX__VERSION_1_0;
-
+#define CL_PROFILING_COMMAND_QUEUED 0x1280
+#define CL_PROFILING_COMMAND_SUBMIT 0x1281
+#define CL_PROFILING_COMMAND_START 0x1282
+#define CL_PROFILING_COMMAND_END 0x1283
+
+ /********************************************************************************************************/
+
+ /********************************************************************************************************/
+
+ /* Function signature typedef's */
+
+ /* Platform API */
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLGETPLATFORMIDS)(cl_uint /* num_entries */,
+ cl_platform_id * /* platforms */,
+ cl_uint * /* num_platforms */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLGETPLATFORMINFO)(cl_platform_id /* platform */,
+ cl_platform_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+ /* Device APIs */
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLGETDEVICEIDS)(cl_platform_id /* platform */,
+ cl_device_type /* device_type */,
+ cl_uint /* num_entries */,
+ cl_device_id * /* devices */,
+ cl_uint * /* num_devices */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLGETDEVICEINFO)(cl_device_id /* device */,
+ cl_device_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+ // Context APIs
+ typedef CL_API_ENTRY cl_context(CL_API_CALL *
+ PFNCLCREATECONTEXT)(const cl_context_properties * /* properties */,
+ cl_uint /* num_devices */,
+ const cl_device_id * /* devices */,
+ void(CL_CALLBACK * /* pfn_notify */)(const char *, const void *, size_t, void *),
+ void * /* user_data */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_context(CL_API_CALL *
+ PFNCLCREATECONTEXTFROMTYPE)(const cl_context_properties * /* properties */,
+ cl_device_type /* device_type */,
+ void(CL_CALLBACK * /* pfn_notify*/)(const char *, const void *, size_t, void *),
+ void * /* user_data */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLRETAINCONTEXT)(cl_context /* context */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLRELEASECONTEXT)(cl_context /* context */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLGETCONTEXTINFO)(cl_context /* context */,
+ cl_context_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+ /* Command Queue APIs */
+ typedef CL_API_ENTRY cl_command_queue(CL_API_CALL *
+ PFNCLCREATECOMMANDQUEUE)(cl_context /* context */,
+ cl_device_id /* device */,
+ cl_command_queue_properties /* properties */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLRETAINCOMMANDQUEUE)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLRELEASECOMMANDQUEUE)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLGETCOMMANDQUEUEINFO)(cl_command_queue /* command_queue */,
+ cl_command_queue_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLSETCOMMANDQUEUEPROPERTY)(cl_command_queue /* command_queue */,
+ cl_command_queue_properties /* properties */,
+ cl_bool /* enable */,
+ cl_command_queue_properties * /* old_properties */) CL_API_SUFFIX__VERSION_1_0;
+
+ /* Memory Object APIs */
+ typedef CL_API_ENTRY cl_mem(CL_API_CALL *
+ PFNCLCREATEBUFFER)(cl_context /* context */,
+ cl_mem_flags /* flags */,
+ size_t /* size */,
+ void * /* host_ptr */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_mem(CL_API_CALL *
+ PFNCLCREATESUBBUFFER)(cl_mem /* buffer */,
+ cl_mem_flags /* flags */,
+ cl_buffer_create_type /* buffer_create_type */,
+ const void * /* buffer_create_info */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_1;
+
+ typedef CL_API_ENTRY cl_mem(CL_API_CALL *
+ PFNCLCREATEIMAGE2D)(cl_context /* context */,
+ cl_mem_flags /* flags */,
+ const cl_image_format * /* image_format */,
+ size_t /* image_width */,
+ size_t /* image_height */,
+ size_t /* image_row_pitch */,
+ void * /* host_ptr */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_mem(CL_API_CALL *
+ PFNCLCREATEIMAGE3D)(cl_context /* context */,
+ cl_mem_flags /* flags */,
+ const cl_image_format * /* image_format */,
+ size_t /* image_width */,
+ size_t /* image_height */,
+ size_t /* image_depth */,
+ size_t /* image_row_pitch */,
+ size_t /* image_slice_pitch */,
+ void * /* host_ptr */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLRETAINMEMOBJECT)(cl_mem /* memobj */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLRELEASEMEMOBJECT)(cl_mem /* memobj */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLGETSUPPORTEDIMAGEFORMATS)(cl_context /* context */,
+ cl_mem_flags /* flags */,
+ cl_mem_object_type /* image_type */,
+ cl_uint /* num_entries */,
+ cl_image_format * /* image_formats */,
+ cl_uint * /* num_image_formats */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLGETMEMOBJECTINFO)(cl_mem /* memobj */,
+ cl_mem_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLGETIMAGEINFO)(cl_mem /* image */,
+ cl_image_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLSETMEMOBJECTDESTRUCTORCALLBACK)(cl_mem /* memobj */,
+ void(CL_CALLBACK * /*pfn_notify*/)(cl_mem /* memobj */, void * /*user_data*/),
+ void * /*user_data */) CL_API_SUFFIX__VERSION_1_1;
+
+ /* Sampler APIs */
+ typedef CL_API_ENTRY cl_sampler(CL_API_CALL *
+ PFNCLCREATESAMPLER)(cl_context /* context */,
+ cl_bool /* normalized_coords */,
+ cl_addressing_mode /* addressing_mode */,
+ cl_filter_mode /* filter_mode */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLRETAINSAMPLER)(cl_sampler /* sampler */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLRELEASESAMPLER)(cl_sampler /* sampler */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLGETSAMPLERINFO)(cl_sampler /* sampler */,
+ cl_sampler_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+ /* Program Object APIs */
+ typedef CL_API_ENTRY cl_program(CL_API_CALL *
+ PFNCLCREATEPROGRAMWITHSOURCE)(cl_context /* context */,
+ cl_uint /* count */,
+ const char ** /* strings */,
+ const size_t * /* lengths */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_program(CL_API_CALL *
+ PFNCLCREATEPROGRAMWITHBINARY)(cl_context /* context */,
+ cl_uint /* num_devices */,
+ const cl_device_id * /* device_list */,
+ const size_t * /* lengths */,
+ const unsigned char ** /* binaries */,
+ cl_int * /* binary_status */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLRETAINPROGRAM)(cl_program /* program */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLRELEASEPROGRAM)(cl_program /* program */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLBUILDPROGRAM)(cl_program /* program */,
+ cl_uint /* num_devices */,
+ const cl_device_id * /* device_list */,
+ const char * /* options */,
+ void(CL_CALLBACK * /* pfn_notify */)(cl_program /* program */, void * /* user_data */),
+ void * /* user_data */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLUNLOADCOMPILER)(void) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLGETPROGRAMINFO)(cl_program /* program */,
+ cl_program_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLGETPROGRAMBUILDINFO)(cl_program /* program */,
+ cl_device_id /* device */,
+ cl_program_build_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+ /* Kernel Object APIs */
+ typedef CL_API_ENTRY cl_kernel(CL_API_CALL *
+ PFNCLCREATEKERNEL)(cl_program /* program */,
+ const char * /* kernel_name */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLCREATEKERNELSINPROGRAM)(cl_program /* program */,
+ cl_uint /* num_kernels */,
+ cl_kernel * /* kernels */,
+ cl_uint * /* num_kernels_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLRETAINKERNEL)(cl_kernel /* kernel */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLRELEASEKERNEL)(cl_kernel /* kernel */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLSETKERNELARG)(cl_kernel /* kernel */,
+ cl_uint /* arg_index */,
+ size_t /* arg_size */,
+ const void * /* arg_value */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLGETKERNELINFO)(cl_kernel /* kernel */,
+ cl_kernel_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLGETKERNELWORKGROUPINFO)(cl_kernel /* kernel */,
+ cl_device_id /* device */,
+ cl_kernel_work_group_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+ // Event Object APIs
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLWAITFOREVENTS)(cl_uint /* num_events */,
+ const cl_event * /* event_list */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLGETEVENTINFO)(cl_event /* event */,
+ cl_event_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_event(CL_API_CALL *
+ PFNCLCREATEUSEREVENT)(cl_context /* context */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_1;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLRETAINEVENT)(cl_event /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLRELEASEEVENT)(cl_event /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLSETUSEREVENTSTATUS)(cl_event /* event */,
+ cl_int /* execution_status */) CL_API_SUFFIX__VERSION_1_1;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLSETEVENTCALLBACK)(cl_event /* event */,
+ cl_int /* command_exec_callback_type */,
+ void(CL_CALLBACK * /* pfn_notify */)(cl_event, cl_int, void *),
+ void * /* user_data */) CL_API_SUFFIX__VERSION_1_1;
+
+ /* Profiling APIs */
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLGETEVENTPROFILINGINFO)(cl_event /* event */,
+ cl_profiling_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+ // Flush and Finish APIs
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLFLUSH)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLFINISH)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
+
+ /* Enqueued Commands APIs */
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLENQUEUEREADBUFFER)(cl_command_queue /* command_queue */,
+ cl_mem /* buffer */,
+ cl_bool /* blocking_read */,
+ size_t /* offset */,
+ size_t /* cb */,
+ void * /* ptr */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLENQUEUEREADBUFFERRECT)(cl_command_queue /* command_queue */,
+ cl_mem /* buffer */,
+ cl_bool /* blocking_read */,
+ const size_t * /* buffer_origin */,
+ const size_t * /* host_origin */,
+ const size_t * /* region */,
+ size_t /* buffer_row_pitch */,
+ size_t /* buffer_slice_pitch */,
+ size_t /* host_row_pitch */,
+ size_t /* host_slice_pitch */,
+ void * /* ptr */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_1;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLENQUEUEWRITEBUFFER)(cl_command_queue /* command_queue */,
+ cl_mem /* buffer */,
+ cl_bool /* blocking_write */,
+ size_t /* offset */,
+ size_t /* cb */,
+ const void * /* ptr */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLENQUEUEWRITEBUFFERRECT)(cl_command_queue /* command_queue */,
+ cl_mem /* buffer */,
+ cl_bool /* blocking_write */,
+ const size_t * /* buffer_origin */,
+ const size_t * /* host_origin */,
+ const size_t * /* region */,
+ size_t /* buffer_row_pitch */,
+ size_t /* buffer_slice_pitch */,
+ size_t /* host_row_pitch */,
+ size_t /* host_slice_pitch */,
+ const void * /* ptr */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_1;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLENQUEUECOPYBUFFER)(cl_command_queue /* command_queue */,
+ cl_mem /* src_buffer */,
+ cl_mem /* dst_buffer */,
+ size_t /* src_offset */,
+ size_t /* dst_offset */,
+ size_t /* cb */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLENQUEUECOPYBUFFERRECT)(cl_command_queue /* command_queue */,
+ cl_mem /* src_buffer */,
+ cl_mem /* dst_buffer */,
+ const size_t * /* src_origin */,
+ const size_t * /* dst_origin */,
+ const size_t * /* region */,
+ size_t /* src_row_pitch */,
+ size_t /* src_slice_pitch */,
+ size_t /* dst_row_pitch */,
+ size_t /* dst_slice_pitch */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_1;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLENQUEUEREADIMAGE)(cl_command_queue /* command_queue */,
+ cl_mem /* image */,
+ cl_bool /* blocking_read */,
+ const size_t * /* origin[3] */,
+ const size_t * /* region[3] */,
+ size_t /* row_pitch */,
+ size_t /* slice_pitch */,
+ void * /* ptr */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLENQUEUEWRITEIMAGE)(cl_command_queue /* command_queue */,
+ cl_mem /* image */,
+ cl_bool /* blocking_write */,
+ const size_t * /* origin[3] */,
+ const size_t * /* region[3] */,
+ size_t /* input_row_pitch */,
+ size_t /* input_slice_pitch */,
+ const void * /* ptr */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLENQUEUECOPYIMAGE)(cl_command_queue /* command_queue */,
+ cl_mem /* src_image */,
+ cl_mem /* dst_image */,
+ const size_t * /* src_origin[3] */,
+ const size_t * /* dst_origin[3] */,
+ const size_t * /* region[3] */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLENQUEUECOPYIMAGETOBUFFER)(cl_command_queue /* command_queue */,
+ cl_mem /* src_image */,
+ cl_mem /* dst_buffer */,
+ const size_t * /* src_origin[3] */,
+ const size_t * /* region[3] */,
+ size_t /* dst_offset */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLENQUEUECOPYBUFFERTOIMAGE)(cl_command_queue /* command_queue */,
+ cl_mem /* src_buffer */,
+ cl_mem /* dst_image */,
+ size_t /* src_offset */,
+ const size_t * /* dst_origin[3] */,
+ const size_t * /* region[3] */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY void *(CL_API_CALL *
+ PFNCLENQUEUEMAPBUFFER)(cl_command_queue /* command_queue */,
+ cl_mem /* buffer */,
+ cl_bool /* blocking_map */,
+ cl_map_flags /* map_flags */,
+ size_t /* offset */,
+ size_t /* cb */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */,
+ cl_int * /* errcode_ret */)CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY void *(CL_API_CALL *
+ PFNCLENQUEUEMAPIMAGE)(cl_command_queue /* command_queue */,
+ cl_mem /* image */,
+ cl_bool /* blocking_map */,
+ cl_map_flags /* map_flags */,
+ const size_t * /* origin[3] */,
+ const size_t * /* region[3] */,
+ size_t * /* image_row_pitch */,
+ size_t * /* image_slice_pitch */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */,
+ cl_int * /* errcode_ret */)CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLENQUEUEUNMAPMEMOBJECT)(cl_command_queue /* command_queue */,
+ cl_mem /* memobj */,
+ void * /* mapped_ptr */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLENQUEUENDRANGEKERNEL)(cl_command_queue /* command_queue */,
+ cl_kernel /* kernel */,
+ cl_uint /* work_dim */,
+ const size_t * /* global_work_offset */,
+ const size_t * /* global_work_size */,
+ const size_t * /* local_work_size */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLENQUEUETASK)(cl_command_queue /* command_queue */,
+ cl_kernel /* kernel */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLENQUEUENATIVEKERNEL)(cl_command_queue /* command_queue */,
+ void (*user_func)(void *),
+ void * /* args */,
+ size_t /* cb_args */,
+ cl_uint /* num_mem_objects */,
+ const cl_mem * /* mem_list */,
+ const void ** /* args_mem_loc */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLENQUEUEMARKER)(cl_command_queue /* command_queue */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLENQUEUEWAITFOREVENTS)(cl_command_queue /* command_queue */,
+ cl_uint /* num_events */,
+ const cl_event * /* event_list */) CL_API_SUFFIX__VERSION_1_0;
+
+ typedef CL_API_ENTRY cl_int(CL_API_CALL *
+ PFNCLENQUEUEBARRIER)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
+
+ // Extension function access
+ //
+ // Returns the extension function address for the given function name,
+ // or NULL if a valid function can not be found. The client must
+ // check to make sure the address is not NULL, before using or
+ // calling the returned function address.
+ //
+ typedef CL_API_ENTRY void *(CL_API_CALL *PFNCLGETEXTENSIONFUNCTIONADDRESS)(const char * /* func_name */)CL_API_SUFFIX__VERSION_1_0;
#define CLEW_STATIC
#ifdef CLEW_STATIC
-# define CLEWAPI extern
+#define CLEWAPI extern
+#else
+#ifdef CLEW_BUILD
+#define CLEWAPI extern __declspec(dllexport)
#else
-# ifdef CLEW_BUILD
-# define CLEWAPI extern __declspec(dllexport)
-# else
-# define CLEWAPI extern __declspec(dllimport)
-# endif
+#define CLEWAPI extern __declspec(dllimport)
+#endif
#endif
#if defined(_WIN32)
@@ -2208,99 +2522,97 @@ typedef CL_API_ENTRY void * (CL_API_CALL * PFNCLGETEXTENSIONFUNCTIONADDRESS)(con
#define CLEW_GET_FUN(x) x
-
-// Variables holding function entry points
-CLEW_FUN_EXPORT PFNCLGETPLATFORMIDS __clewGetPlatformIDs ;
-CLEW_FUN_EXPORT PFNCLGETPLATFORMINFO __clewGetPlatformInfo ;
-CLEW_FUN_EXPORT PFNCLGETDEVICEIDS __clewGetDeviceIDs ;
-CLEW_FUN_EXPORT PFNCLGETDEVICEINFO __clewGetDeviceInfo ;
-CLEW_FUN_EXPORT PFNCLCREATECONTEXT __clewCreateContext ;
-CLEW_FUN_EXPORT PFNCLCREATECONTEXTFROMTYPE __clewCreateContextFromType ;
-CLEW_FUN_EXPORT PFNCLRETAINCONTEXT __clewRetainContext ;
-CLEW_FUN_EXPORT PFNCLRELEASECONTEXT __clewReleaseContext ;
-CLEW_FUN_EXPORT PFNCLGETCONTEXTINFO __clewGetContextInfo ;
-CLEW_FUN_EXPORT PFNCLCREATECOMMANDQUEUE __clewCreateCommandQueue ;
-CLEW_FUN_EXPORT PFNCLRETAINCOMMANDQUEUE __clewRetainCommandQueue ;
-CLEW_FUN_EXPORT PFNCLRELEASECOMMANDQUEUE __clewReleaseCommandQueue ;
-CLEW_FUN_EXPORT PFNCLGETCOMMANDQUEUEINFO __clewGetCommandQueueInfo ;
+ // Variables holding function entry points
+ CLEW_FUN_EXPORT PFNCLGETPLATFORMIDS __clewGetPlatformIDs;
+ CLEW_FUN_EXPORT PFNCLGETPLATFORMINFO __clewGetPlatformInfo;
+ CLEW_FUN_EXPORT PFNCLGETDEVICEIDS __clewGetDeviceIDs;
+ CLEW_FUN_EXPORT PFNCLGETDEVICEINFO __clewGetDeviceInfo;
+ CLEW_FUN_EXPORT PFNCLCREATECONTEXT __clewCreateContext;
+ CLEW_FUN_EXPORT PFNCLCREATECONTEXTFROMTYPE __clewCreateContextFromType;
+ CLEW_FUN_EXPORT PFNCLRETAINCONTEXT __clewRetainContext;
+ CLEW_FUN_EXPORT PFNCLRELEASECONTEXT __clewReleaseContext;
+ CLEW_FUN_EXPORT PFNCLGETCONTEXTINFO __clewGetContextInfo;
+ CLEW_FUN_EXPORT PFNCLCREATECOMMANDQUEUE __clewCreateCommandQueue;
+ CLEW_FUN_EXPORT PFNCLRETAINCOMMANDQUEUE __clewRetainCommandQueue;
+ CLEW_FUN_EXPORT PFNCLRELEASECOMMANDQUEUE __clewReleaseCommandQueue;
+ CLEW_FUN_EXPORT PFNCLGETCOMMANDQUEUEINFO __clewGetCommandQueueInfo;
#ifdef CL_USE_DEPRECATED_OPENCL_1_0_APIS
-CLEW_FUN_EXPORT PFNCLSETCOMMANDQUEUEPROPERTY __clewSetCommandQueueProperty ;
-#endif
-CLEW_FUN_EXPORT PFNCLCREATEBUFFER __clewCreateBuffer ;
-CLEW_FUN_EXPORT PFNCLCREATESUBBUFFER __clewCreateSubBuffer ;
-CLEW_FUN_EXPORT PFNCLCREATEIMAGE2D __clewCreateImage2D ;
-CLEW_FUN_EXPORT PFNCLCREATEIMAGE3D __clewCreateImage3D ;
-CLEW_FUN_EXPORT PFNCLRETAINMEMOBJECT __clewRetainMemObject ;
-CLEW_FUN_EXPORT PFNCLRELEASEMEMOBJECT __clewReleaseMemObject ;
-CLEW_FUN_EXPORT PFNCLGETSUPPORTEDIMAGEFORMATS __clewGetSupportedImageFormats ;
-CLEW_FUN_EXPORT PFNCLGETMEMOBJECTINFO __clewGetMemObjectInfo ;
-CLEW_FUN_EXPORT PFNCLGETIMAGEINFO __clewGetImageInfo ;
-CLEW_FUN_EXPORT PFNCLSETMEMOBJECTDESTRUCTORCALLBACK __clewSetMemObjectDestructorCallback;
-CLEW_FUN_EXPORT PFNCLCREATESAMPLER __clewCreateSampler ;
-CLEW_FUN_EXPORT PFNCLRETAINSAMPLER __clewRetainSampler ;
-CLEW_FUN_EXPORT PFNCLRELEASESAMPLER __clewReleaseSampler ;
-CLEW_FUN_EXPORT PFNCLGETSAMPLERINFO __clewGetSamplerInfo ;
-CLEW_FUN_EXPORT PFNCLCREATEPROGRAMWITHSOURCE __clewCreateProgramWithSource ;
-CLEW_FUN_EXPORT PFNCLCREATEPROGRAMWITHBINARY __clewCreateProgramWithBinary ;
-CLEW_FUN_EXPORT PFNCLRETAINPROGRAM __clewRetainProgram ;
-CLEW_FUN_EXPORT PFNCLRELEASEPROGRAM __clewReleaseProgram ;
-CLEW_FUN_EXPORT PFNCLBUILDPROGRAM __clewBuildProgram ;
-CLEW_FUN_EXPORT PFNCLUNLOADCOMPILER __clewUnloadCompiler ;
-CLEW_FUN_EXPORT PFNCLGETPROGRAMINFO __clewGetProgramInfo ;
-CLEW_FUN_EXPORT PFNCLGETPROGRAMBUILDINFO __clewGetProgramBuildInfo ;
-CLEW_FUN_EXPORT PFNCLCREATEKERNEL __clewCreateKernel ;
-CLEW_FUN_EXPORT PFNCLCREATEKERNELSINPROGRAM __clewCreateKernelsInProgram ;
-CLEW_FUN_EXPORT PFNCLRETAINKERNEL __clewRetainKernel ;
-CLEW_FUN_EXPORT PFNCLRELEASEKERNEL __clewReleaseKernel ;
-CLEW_FUN_EXPORT PFNCLSETKERNELARG __clewSetKernelArg ;
-CLEW_FUN_EXPORT PFNCLGETKERNELINFO __clewGetKernelInfo ;
-CLEW_FUN_EXPORT PFNCLGETKERNELWORKGROUPINFO __clewGetKernelWorkGroupInfo ;
-CLEW_FUN_EXPORT PFNCLWAITFOREVENTS __clewWaitForEvents ;
-CLEW_FUN_EXPORT PFNCLGETEVENTINFO __clewGetEventInfo ;
-CLEW_FUN_EXPORT PFNCLCREATEUSEREVENT __clewCreateUserEvent ;
-CLEW_FUN_EXPORT PFNCLRETAINEVENT __clewRetainEvent ;
-CLEW_FUN_EXPORT PFNCLRELEASEEVENT __clewReleaseEvent ;
-CLEW_FUN_EXPORT PFNCLSETUSEREVENTSTATUS __clewSetUserEventStatus ;
-CLEW_FUN_EXPORT PFNCLSETEVENTCALLBACK __clewSetEventCallback ;
-CLEW_FUN_EXPORT PFNCLGETEVENTPROFILINGINFO __clewGetEventProfilingInfo ;
-CLEW_FUN_EXPORT PFNCLFLUSH __clewFlush ;
-CLEW_FUN_EXPORT PFNCLFINISH __clewFinish ;
-CLEW_FUN_EXPORT PFNCLENQUEUEREADBUFFER __clewEnqueueReadBuffer ;
-CLEW_FUN_EXPORT PFNCLENQUEUEREADBUFFERRECT __clewEnqueueReadBufferRect ;
-CLEW_FUN_EXPORT PFNCLENQUEUEWRITEBUFFER __clewEnqueueWriteBuffer ;
-CLEW_FUN_EXPORT PFNCLENQUEUEWRITEBUFFERRECT __clewEnqueueWriteBufferRect ;
-CLEW_FUN_EXPORT PFNCLENQUEUECOPYBUFFER __clewEnqueueCopyBuffer ;
-CLEW_FUN_EXPORT PFNCLENQUEUECOPYBUFFERRECT __clewEnqueueCopyBufferRect ;
-CLEW_FUN_EXPORT PFNCLENQUEUEREADIMAGE __clewEnqueueReadImage ;
-CLEW_FUN_EXPORT PFNCLENQUEUEWRITEIMAGE __clewEnqueueWriteImage ;
-CLEW_FUN_EXPORT PFNCLENQUEUECOPYIMAGE __clewEnqueueCopyImage ;
-CLEW_FUN_EXPORT PFNCLENQUEUECOPYIMAGETOBUFFER __clewEnqueueCopyImageToBuffer ;
-CLEW_FUN_EXPORT PFNCLENQUEUECOPYBUFFERTOIMAGE __clewEnqueueCopyBufferToImage ;
-CLEW_FUN_EXPORT PFNCLENQUEUEMAPBUFFER __clewEnqueueMapBuffer ;
-CLEW_FUN_EXPORT PFNCLENQUEUEMAPIMAGE __clewEnqueueMapImage ;
-CLEW_FUN_EXPORT PFNCLENQUEUEUNMAPMEMOBJECT __clewEnqueueUnmapMemObject ;
-CLEW_FUN_EXPORT PFNCLENQUEUENDRANGEKERNEL __clewEnqueueNDRangeKernel ;
-CLEW_FUN_EXPORT PFNCLENQUEUETASK __clewEnqueueTask ;
-CLEW_FUN_EXPORT PFNCLENQUEUENATIVEKERNEL __clewEnqueueNativeKernel ;
-CLEW_FUN_EXPORT PFNCLENQUEUEMARKER __clewEnqueueMarker ;
-CLEW_FUN_EXPORT PFNCLENQUEUEWAITFOREVENTS __clewEnqueueWaitForEvents ;
-CLEW_FUN_EXPORT PFNCLENQUEUEBARRIER __clewEnqueueBarrier ;
-CLEW_FUN_EXPORT PFNCLGETEXTENSIONFUNCTIONADDRESS __clewGetExtensionFunctionAddress ;
-
-
-#define clGetPlatformIDs CLEW_GET_FUN(__clewGetPlatformIDs )
-#define clGetPlatformInfo CLEW_GET_FUN(__clewGetPlatformInfo )
-#define clGetDeviceIDs CLEW_GET_FUN(__clewGetDeviceIDs )
-#define clGetDeviceInfo CLEW_GET_FUN(__clewGetDeviceInfo )
-#define clCreateContext CLEW_GET_FUN(__clewCreateContext )
-#define clCreateContextFromType CLEW_GET_FUN(__clewCreateContextFromType )
-#define clRetainContext CLEW_GET_FUN(__clewRetainContext )
-#define clReleaseContext CLEW_GET_FUN(__clewReleaseContext )
-#define clGetContextInfo CLEW_GET_FUN(__clewGetContextInfo )
-#define clCreateCommandQueue CLEW_GET_FUN(__clewCreateCommandQueue )
-#define clRetainCommandQueue CLEW_GET_FUN(__clewRetainCommandQueue )
-#define clReleaseCommandQueue CLEW_GET_FUN(__clewReleaseCommandQueue )
-#define clGetCommandQueueInfo CLEW_GET_FUN(__clewGetCommandQueueInfo )
+ CLEW_FUN_EXPORT PFNCLSETCOMMANDQUEUEPROPERTY __clewSetCommandQueueProperty;
+#endif
+ CLEW_FUN_EXPORT PFNCLCREATEBUFFER __clewCreateBuffer;
+ CLEW_FUN_EXPORT PFNCLCREATESUBBUFFER __clewCreateSubBuffer;
+ CLEW_FUN_EXPORT PFNCLCREATEIMAGE2D __clewCreateImage2D;
+ CLEW_FUN_EXPORT PFNCLCREATEIMAGE3D __clewCreateImage3D;
+ CLEW_FUN_EXPORT PFNCLRETAINMEMOBJECT __clewRetainMemObject;
+ CLEW_FUN_EXPORT PFNCLRELEASEMEMOBJECT __clewReleaseMemObject;
+ CLEW_FUN_EXPORT PFNCLGETSUPPORTEDIMAGEFORMATS __clewGetSupportedImageFormats;
+ CLEW_FUN_EXPORT PFNCLGETMEMOBJECTINFO __clewGetMemObjectInfo;
+ CLEW_FUN_EXPORT PFNCLGETIMAGEINFO __clewGetImageInfo;
+ CLEW_FUN_EXPORT PFNCLSETMEMOBJECTDESTRUCTORCALLBACK __clewSetMemObjectDestructorCallback;
+ CLEW_FUN_EXPORT PFNCLCREATESAMPLER __clewCreateSampler;
+ CLEW_FUN_EXPORT PFNCLRETAINSAMPLER __clewRetainSampler;
+ CLEW_FUN_EXPORT PFNCLRELEASESAMPLER __clewReleaseSampler;
+ CLEW_FUN_EXPORT PFNCLGETSAMPLERINFO __clewGetSamplerInfo;
+ CLEW_FUN_EXPORT PFNCLCREATEPROGRAMWITHSOURCE __clewCreateProgramWithSource;
+ CLEW_FUN_EXPORT PFNCLCREATEPROGRAMWITHBINARY __clewCreateProgramWithBinary;
+ CLEW_FUN_EXPORT PFNCLRETAINPROGRAM __clewRetainProgram;
+ CLEW_FUN_EXPORT PFNCLRELEASEPROGRAM __clewReleaseProgram;
+ CLEW_FUN_EXPORT PFNCLBUILDPROGRAM __clewBuildProgram;
+ CLEW_FUN_EXPORT PFNCLUNLOADCOMPILER __clewUnloadCompiler;
+ CLEW_FUN_EXPORT PFNCLGETPROGRAMINFO __clewGetProgramInfo;
+ CLEW_FUN_EXPORT PFNCLGETPROGRAMBUILDINFO __clewGetProgramBuildInfo;
+ CLEW_FUN_EXPORT PFNCLCREATEKERNEL __clewCreateKernel;
+ CLEW_FUN_EXPORT PFNCLCREATEKERNELSINPROGRAM __clewCreateKernelsInProgram;
+ CLEW_FUN_EXPORT PFNCLRETAINKERNEL __clewRetainKernel;
+ CLEW_FUN_EXPORT PFNCLRELEASEKERNEL __clewReleaseKernel;
+ CLEW_FUN_EXPORT PFNCLSETKERNELARG __clewSetKernelArg;
+ CLEW_FUN_EXPORT PFNCLGETKERNELINFO __clewGetKernelInfo;
+ CLEW_FUN_EXPORT PFNCLGETKERNELWORKGROUPINFO __clewGetKernelWorkGroupInfo;
+ CLEW_FUN_EXPORT PFNCLWAITFOREVENTS __clewWaitForEvents;
+ CLEW_FUN_EXPORT PFNCLGETEVENTINFO __clewGetEventInfo;
+ CLEW_FUN_EXPORT PFNCLCREATEUSEREVENT __clewCreateUserEvent;
+ CLEW_FUN_EXPORT PFNCLRETAINEVENT __clewRetainEvent;
+ CLEW_FUN_EXPORT PFNCLRELEASEEVENT __clewReleaseEvent;
+ CLEW_FUN_EXPORT PFNCLSETUSEREVENTSTATUS __clewSetUserEventStatus;
+ CLEW_FUN_EXPORT PFNCLSETEVENTCALLBACK __clewSetEventCallback;
+ CLEW_FUN_EXPORT PFNCLGETEVENTPROFILINGINFO __clewGetEventProfilingInfo;
+ CLEW_FUN_EXPORT PFNCLFLUSH __clewFlush;
+ CLEW_FUN_EXPORT PFNCLFINISH __clewFinish;
+ CLEW_FUN_EXPORT PFNCLENQUEUEREADBUFFER __clewEnqueueReadBuffer;
+ CLEW_FUN_EXPORT PFNCLENQUEUEREADBUFFERRECT __clewEnqueueReadBufferRect;
+ CLEW_FUN_EXPORT PFNCLENQUEUEWRITEBUFFER __clewEnqueueWriteBuffer;
+ CLEW_FUN_EXPORT PFNCLENQUEUEWRITEBUFFERRECT __clewEnqueueWriteBufferRect;
+ CLEW_FUN_EXPORT PFNCLENQUEUECOPYBUFFER __clewEnqueueCopyBuffer;
+ CLEW_FUN_EXPORT PFNCLENQUEUECOPYBUFFERRECT __clewEnqueueCopyBufferRect;
+ CLEW_FUN_EXPORT PFNCLENQUEUEREADIMAGE __clewEnqueueReadImage;
+ CLEW_FUN_EXPORT PFNCLENQUEUEWRITEIMAGE __clewEnqueueWriteImage;
+ CLEW_FUN_EXPORT PFNCLENQUEUECOPYIMAGE __clewEnqueueCopyImage;
+ CLEW_FUN_EXPORT PFNCLENQUEUECOPYIMAGETOBUFFER __clewEnqueueCopyImageToBuffer;
+ CLEW_FUN_EXPORT PFNCLENQUEUECOPYBUFFERTOIMAGE __clewEnqueueCopyBufferToImage;
+ CLEW_FUN_EXPORT PFNCLENQUEUEMAPBUFFER __clewEnqueueMapBuffer;
+ CLEW_FUN_EXPORT PFNCLENQUEUEMAPIMAGE __clewEnqueueMapImage;
+ CLEW_FUN_EXPORT PFNCLENQUEUEUNMAPMEMOBJECT __clewEnqueueUnmapMemObject;
+ CLEW_FUN_EXPORT PFNCLENQUEUENDRANGEKERNEL __clewEnqueueNDRangeKernel;
+ CLEW_FUN_EXPORT PFNCLENQUEUETASK __clewEnqueueTask;
+ CLEW_FUN_EXPORT PFNCLENQUEUENATIVEKERNEL __clewEnqueueNativeKernel;
+ CLEW_FUN_EXPORT PFNCLENQUEUEMARKER __clewEnqueueMarker;
+ CLEW_FUN_EXPORT PFNCLENQUEUEWAITFOREVENTS __clewEnqueueWaitForEvents;
+ CLEW_FUN_EXPORT PFNCLENQUEUEBARRIER __clewEnqueueBarrier;
+ CLEW_FUN_EXPORT PFNCLGETEXTENSIONFUNCTIONADDRESS __clewGetExtensionFunctionAddress;
+
+#define clGetPlatformIDs CLEW_GET_FUN(__clewGetPlatformIDs)
+#define clGetPlatformInfo CLEW_GET_FUN(__clewGetPlatformInfo)
+#define clGetDeviceIDs CLEW_GET_FUN(__clewGetDeviceIDs)
+#define clGetDeviceInfo CLEW_GET_FUN(__clewGetDeviceInfo)
+#define clCreateContext CLEW_GET_FUN(__clewCreateContext)
+#define clCreateContextFromType CLEW_GET_FUN(__clewCreateContextFromType)
+#define clRetainContext CLEW_GET_FUN(__clewRetainContext)
+#define clReleaseContext CLEW_GET_FUN(__clewReleaseContext)
+#define clGetContextInfo CLEW_GET_FUN(__clewGetContextInfo)
+#define clCreateCommandQueue CLEW_GET_FUN(__clewCreateCommandQueue)
+#define clRetainCommandQueue CLEW_GET_FUN(__clewRetainCommandQueue)
+#define clReleaseCommandQueue CLEW_GET_FUN(__clewReleaseCommandQueue)
+#define clGetCommandQueueInfo CLEW_GET_FUN(__clewGetCommandQueueInfo)
#ifdef CL_USE_DEPRECATED_OPENCL_1_0_APIS
#warning CL_USE_DEPRECATED_OPENCL_1_0_APIS is defined. These APIs are unsupported and untested in OpenCL 1.1!
/*
@@ -2313,82 +2625,81 @@ CLEW_FUN_EXPORT PFNCLGETEXTENSIONFUNCTIONADDRESS __clewGetExtensionFuncti
* Software developers previously relying on this API are instructed to set the command queue
* properties when creating the queue, instead.
*/
-#define clSetCommandQueueProperty CLEW_GET_FUN(__clewSetCommandQueueProperty )
+#define clSetCommandQueueProperty CLEW_GET_FUN(__clewSetCommandQueueProperty)
#endif /* CL_USE_DEPRECATED_OPENCL_1_0_APIS */
-#define clCreateBuffer CLEW_GET_FUN(__clewCreateBuffer )
-#define clCreateSubBuffer CLEW_GET_FUN(__clewCreateSubBuffer )
-#define clCreateImage2D CLEW_GET_FUN(__clewCreateImage2D )
-#define clCreateImage3D CLEW_GET_FUN(__clewCreateImage3D )
-#define clRetainMemObject CLEW_GET_FUN(__clewRetainMemObject )
-#define clReleaseMemObject CLEW_GET_FUN(__clewReleaseMemObject )
-#define clGetSupportedImageFormats CLEW_GET_FUN(__clewGetSupportedImageFormats )
-#define clGetMemObjectInfo CLEW_GET_FUN(__clewGetMemObjectInfo )
-#define clGetImageInfo CLEW_GET_FUN(__clewGetImageInfo )
-#define clSetMemObjectDestructorCallback CLEW_GET_FUN(__clewSetMemObjectDestructorCallback)
-#define clCreateSampler CLEW_GET_FUN(__clewCreateSampler )
-#define clRetainSampler CLEW_GET_FUN(__clewRetainSampler )
-#define clReleaseSampler CLEW_GET_FUN(__clewReleaseSampler )
-#define clGetSamplerInfo CLEW_GET_FUN(__clewGetSamplerInfo )
-#define clCreateProgramWithSource CLEW_GET_FUN(__clewCreateProgramWithSource )
-#define clCreateProgramWithBinary CLEW_GET_FUN(__clewCreateProgramWithBinary )
-#define clRetainProgram CLEW_GET_FUN(__clewRetainProgram )
-#define clReleaseProgram CLEW_GET_FUN(__clewReleaseProgram )
-#define clBuildProgram CLEW_GET_FUN(__clewBuildProgram )
-#define clUnloadCompiler CLEW_GET_FUN(__clewUnloadCompiler )
-#define clGetProgramInfo CLEW_GET_FUN(__clewGetProgramInfo )
-#define clGetProgramBuildInfo CLEW_GET_FUN(__clewGetProgramBuildInfo )
-#define clCreateKernel CLEW_GET_FUN(__clewCreateKernel )
-#define clCreateKernelsInProgram CLEW_GET_FUN(__clewCreateKernelsInProgram )
-#define clRetainKernel CLEW_GET_FUN(__clewRetainKernel )
-#define clReleaseKernel CLEW_GET_FUN(__clewReleaseKernel )
-#define clSetKernelArg CLEW_GET_FUN(__clewSetKernelArg )
-#define clGetKernelInfo CLEW_GET_FUN(__clewGetKernelInfo )
-#define clGetKernelWorkGroupInfo CLEW_GET_FUN(__clewGetKernelWorkGroupInfo )
-#define clWaitForEvents CLEW_GET_FUN(__clewWaitForEvents )
-#define clGetEventInfo CLEW_GET_FUN(__clewGetEventInfo )
-#define clCreateUserEvent CLEW_GET_FUN(__clewCreateUserEvent )
-#define clRetainEvent CLEW_GET_FUN(__clewRetainEvent )
-#define clReleaseEvent CLEW_GET_FUN(__clewReleaseEvent )
-#define clSetUserEventStatus CLEW_GET_FUN(__clewSetUserEventStatus )
-#define clSetEventCallback CLEW_GET_FUN(__clewSetEventCallback )
-#define clGetEventProfilingInfo CLEW_GET_FUN(__clewGetEventProfilingInfo )
-#define clFlush CLEW_GET_FUN(__clewFlush )
-#define clFinish CLEW_GET_FUN(__clewFinish )
-#define clEnqueueReadBuffer CLEW_GET_FUN(__clewEnqueueReadBuffer )
-#define clEnqueueReadBufferRect CLEW_GET_FUN(__clewEnqueueReadBufferRect )
-#define clEnqueueWriteBuffer CLEW_GET_FUN(__clewEnqueueWriteBuffer )
-#define clEnqueueWriteBufferRect CLEW_GET_FUN(__clewEnqueueWriteBufferRect )
-#define clEnqueueCopyBuffer CLEW_GET_FUN(__clewEnqueueCopyBuffer )
-#define clEnqueueCopyBufferRect CLEW_GET_FUN(__clewEnqueueCopyBufferRect )
-#define clEnqueueReadImage CLEW_GET_FUN(__clewEnqueueReadImage )
-#define clEnqueueWriteImage CLEW_GET_FUN(__clewEnqueueWriteImage )
-#define clEnqueueCopyImage CLEW_GET_FUN(__clewEnqueueCopyImage )
-#define clEnqueueCopyImageToBuffer CLEW_GET_FUN(__clewEnqueueCopyImageToBuffer )
-#define clEnqueueCopyBufferToImage CLEW_GET_FUN(__clewEnqueueCopyBufferToImage )
-#define clEnqueueMapBuffer CLEW_GET_FUN(__clewEnqueueMapBuffer )
-#define clEnqueueMapImage CLEW_GET_FUN(__clewEnqueueMapImage )
-#define clEnqueueUnmapMemObject CLEW_GET_FUN(__clewEnqueueUnmapMemObject )
-#define clEnqueueNDRangeKernel CLEW_GET_FUN(__clewEnqueueNDRangeKernel )
-#define clEnqueueTask CLEW_GET_FUN(__clewEnqueueTask )
-#define clEnqueueNativeKernel CLEW_GET_FUN(__clewEnqueueNativeKernel )
-#define clEnqueueMarker CLEW_GET_FUN(__clewEnqueueMarker )
-#define clEnqueueWaitForEvents CLEW_GET_FUN(__clewEnqueueWaitForEvents )
-#define clEnqueueBarrier CLEW_GET_FUN(__clewEnqueueBarrier )
-#define clGetExtensionFunctionAddress CLEW_GET_FUN(__clewGetExtensionFunctionAddress )
-
-
-#define CLEW_SUCCESS 0 //!< Success error code
-#define CLEW_ERROR_OPEN_FAILED -1 //!< Error code for failing to open the dynamic library
-#define CLEW_ERROR_ATEXIT_FAILED -2 //!< Error code for failing to queue the closing of the dynamic library to atexit()
-
-//! \brief Load OpenCL dynamic library and set function entry points
-int clewInit (const char*);
-
-//! \brief Exit clew and unload OpenCL dynamic library
-void clewExit();
-
-//! \brief Convert an OpenCL error code to its string equivalent
-const char* clewErrorString (cl_int error);
+#define clCreateBuffer CLEW_GET_FUN(__clewCreateBuffer)
+#define clCreateSubBuffer CLEW_GET_FUN(__clewCreateSubBuffer)
+#define clCreateImage2D CLEW_GET_FUN(__clewCreateImage2D)
+#define clCreateImage3D CLEW_GET_FUN(__clewCreateImage3D)
+#define clRetainMemObject CLEW_GET_FUN(__clewRetainMemObject)
+#define clReleaseMemObject CLEW_GET_FUN(__clewReleaseMemObject)
+#define clGetSupportedImageFormats CLEW_GET_FUN(__clewGetSupportedImageFormats)
+#define clGetMemObjectInfo CLEW_GET_FUN(__clewGetMemObjectInfo)
+#define clGetImageInfo CLEW_GET_FUN(__clewGetImageInfo)
+#define clSetMemObjectDestructorCallback CLEW_GET_FUN(__clewSetMemObjectDestructorCallback)
+#define clCreateSampler CLEW_GET_FUN(__clewCreateSampler)
+#define clRetainSampler CLEW_GET_FUN(__clewRetainSampler)
+#define clReleaseSampler CLEW_GET_FUN(__clewReleaseSampler)
+#define clGetSamplerInfo CLEW_GET_FUN(__clewGetSamplerInfo)
+#define clCreateProgramWithSource CLEW_GET_FUN(__clewCreateProgramWithSource)
+#define clCreateProgramWithBinary CLEW_GET_FUN(__clewCreateProgramWithBinary)
+#define clRetainProgram CLEW_GET_FUN(__clewRetainProgram)
+#define clReleaseProgram CLEW_GET_FUN(__clewReleaseProgram)
+#define clBuildProgram CLEW_GET_FUN(__clewBuildProgram)
+#define clUnloadCompiler CLEW_GET_FUN(__clewUnloadCompiler)
+#define clGetProgramInfo CLEW_GET_FUN(__clewGetProgramInfo)
+#define clGetProgramBuildInfo CLEW_GET_FUN(__clewGetProgramBuildInfo)
+#define clCreateKernel CLEW_GET_FUN(__clewCreateKernel)
+#define clCreateKernelsInProgram CLEW_GET_FUN(__clewCreateKernelsInProgram)
+#define clRetainKernel CLEW_GET_FUN(__clewRetainKernel)
+#define clReleaseKernel CLEW_GET_FUN(__clewReleaseKernel)
+#define clSetKernelArg CLEW_GET_FUN(__clewSetKernelArg)
+#define clGetKernelInfo CLEW_GET_FUN(__clewGetKernelInfo)
+#define clGetKernelWorkGroupInfo CLEW_GET_FUN(__clewGetKernelWorkGroupInfo)
+#define clWaitForEvents CLEW_GET_FUN(__clewWaitForEvents)
+#define clGetEventInfo CLEW_GET_FUN(__clewGetEventInfo)
+#define clCreateUserEvent CLEW_GET_FUN(__clewCreateUserEvent)
+#define clRetainEvent CLEW_GET_FUN(__clewRetainEvent)
+#define clReleaseEvent CLEW_GET_FUN(__clewReleaseEvent)
+#define clSetUserEventStatus CLEW_GET_FUN(__clewSetUserEventStatus)
+#define clSetEventCallback CLEW_GET_FUN(__clewSetEventCallback)
+#define clGetEventProfilingInfo CLEW_GET_FUN(__clewGetEventProfilingInfo)
+#define clFlush CLEW_GET_FUN(__clewFlush)
+#define clFinish CLEW_GET_FUN(__clewFinish)
+#define clEnqueueReadBuffer CLEW_GET_FUN(__clewEnqueueReadBuffer)
+#define clEnqueueReadBufferRect CLEW_GET_FUN(__clewEnqueueReadBufferRect)
+#define clEnqueueWriteBuffer CLEW_GET_FUN(__clewEnqueueWriteBuffer)
+#define clEnqueueWriteBufferRect CLEW_GET_FUN(__clewEnqueueWriteBufferRect)
+#define clEnqueueCopyBuffer CLEW_GET_FUN(__clewEnqueueCopyBuffer)
+#define clEnqueueCopyBufferRect CLEW_GET_FUN(__clewEnqueueCopyBufferRect)
+#define clEnqueueReadImage CLEW_GET_FUN(__clewEnqueueReadImage)
+#define clEnqueueWriteImage CLEW_GET_FUN(__clewEnqueueWriteImage)
+#define clEnqueueCopyImage CLEW_GET_FUN(__clewEnqueueCopyImage)
+#define clEnqueueCopyImageToBuffer CLEW_GET_FUN(__clewEnqueueCopyImageToBuffer)
+#define clEnqueueCopyBufferToImage CLEW_GET_FUN(__clewEnqueueCopyBufferToImage)
+#define clEnqueueMapBuffer CLEW_GET_FUN(__clewEnqueueMapBuffer)
+#define clEnqueueMapImage CLEW_GET_FUN(__clewEnqueueMapImage)
+#define clEnqueueUnmapMemObject CLEW_GET_FUN(__clewEnqueueUnmapMemObject)
+#define clEnqueueNDRangeKernel CLEW_GET_FUN(__clewEnqueueNDRangeKernel)
+#define clEnqueueTask CLEW_GET_FUN(__clewEnqueueTask)
+#define clEnqueueNativeKernel CLEW_GET_FUN(__clewEnqueueNativeKernel)
+#define clEnqueueMarker CLEW_GET_FUN(__clewEnqueueMarker)
+#define clEnqueueWaitForEvents CLEW_GET_FUN(__clewEnqueueWaitForEvents)
+#define clEnqueueBarrier CLEW_GET_FUN(__clewEnqueueBarrier)
+#define clGetExtensionFunctionAddress CLEW_GET_FUN(__clewGetExtensionFunctionAddress)
+
+#define CLEW_SUCCESS 0 //!< Success error code
+#define CLEW_ERROR_OPEN_FAILED -1 //!< Error code for failing to open the dynamic library
+#define CLEW_ERROR_ATEXIT_FAILED -2 //!< Error code for failing to queue the closing of the dynamic library to atexit()
+
+ //! \brief Load OpenCL dynamic library and set function entry points
+ int clewInit(const char *);
+
+ //! \brief Exit clew and unload OpenCL dynamic library
+ void clewExit();
+
+ //! \brief Convert an OpenCL error code to its string equivalent
+ const char *clewErrorString(cl_int error);
#ifdef __cplusplus
}
diff --git a/thirdparty/cvtt/LICENSE.txt b/thirdparty/cvtt/LICENSE.txt
index 6964f6e43f..d79aec44e3 100644
--- a/thirdparty/cvtt/LICENSE.txt
+++ b/thirdparty/cvtt/LICENSE.txt
@@ -1,45 +1,45 @@
-Convection Texture Tools Stand-Alone Kernels
-
-Copyright (c) 2018 Eric Lasota
-
-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.
-
-**************************************************************************
-
-Based on DirectX Texture Library
-
-Copyright (c) 2018 Microsoft Corp
-
-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
+Convection Texture Tools Stand-Alone Kernels
+
+Copyright (c) 2018 Eric Lasota
+
+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.
+
+**************************************************************************
+
+Based on DirectX Texture Library
+
+Copyright (c) 2018 Microsoft Corp
+
+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. \ No newline at end of file
diff --git a/thirdparty/enet/enet/godot.h b/thirdparty/enet/enet/godot.h
index 7e2be12b22..9230af428b 100644
--- a/thirdparty/enet/enet/godot.h
+++ b/thirdparty/enet/enet/godot.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/thirdparty/enet/godot.cpp b/thirdparty/enet/godot.cpp
index 73a09f9b1d..822a294781 100644
--- a/thirdparty/enet/godot.cpp
+++ b/thirdparty/enet/godot.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -95,7 +95,6 @@ ENetSocket enet_socket_create(ENetSocketType type) {
NetSocket *socket = NetSocket::create();
IP::Type ip_type = IP::TYPE_ANY;
socket->open(NetSocket::TYPE_UDP, ip_type);
- socket->set_blocking_enabled(false);
return socket;
}
@@ -216,6 +215,46 @@ int enet_socket_listen(ENetSocket socket, int backlog) {
int enet_socket_set_option(ENetSocket socket, ENetSocketOption option, int value) {
+ NetSocket *sock = (NetSocket *)socket;
+
+ switch (option) {
+ case ENET_SOCKOPT_NONBLOCK: {
+ sock->set_blocking_enabled(value ? false : true);
+ return 0;
+ } break;
+
+ case ENET_SOCKOPT_BROADCAST: {
+ sock->set_broadcasting_enabled(value ? true : false);
+ return 0;
+ } break;
+
+ case ENET_SOCKOPT_REUSEADDR: {
+ sock->set_reuse_address_enabled(value ? true : false);
+ return 0;
+ } break;
+
+ case ENET_SOCKOPT_RCVBUF: {
+ return -1;
+ } break;
+
+ case ENET_SOCKOPT_SNDBUF: {
+ return -1;
+ } break;
+
+ case ENET_SOCKOPT_RCVTIMEO: {
+ return -1;
+ } break;
+
+ case ENET_SOCKOPT_SNDTIMEO: {
+ return -1;
+ } break;
+
+ case ENET_SOCKOPT_NODELAY: {
+ sock->set_tcp_no_delay_enabled(value ? true : false);
+ return 0;
+ } break;
+ }
+
return -1;
}
diff --git a/thirdparty/freetype/include/freetype/config/ftconfig.h b/thirdparty/freetype/include/freetype/config/ftconfig.h
index eedebf4082..9466603377 100644
--- a/thirdparty/freetype/include/freetype/config/ftconfig.h
+++ b/thirdparty/freetype/include/freetype/config/ftconfig.h
@@ -1,39 +1,38 @@
-/***************************************************************************/
-/* */
-/* ftconfig.h */
-/* */
-/* ANSI-specific configuration file (specification only). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* This header file contains a number of macro definitions that are used */
- /* by the rest of the engine. Most of the macros here are automatically */
- /* determined at compile time, and you should not need to change it to */
- /* port FreeType, except to compile the library with a non-ANSI */
- /* compiler. */
- /* */
- /* Note however that if some specific modifications are needed, we */
- /* advise you to place a modified copy in your build directory. */
- /* */
- /* The build directory is usually `builds/<system>', and contains */
- /* system-specific files that are always included first when building */
- /* the library. */
- /* */
- /* This ANSI version should stay in `include/config/'. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * ftconfig.h
+ *
+ * ANSI-specific configuration file (specification only).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * This header file contains a number of macro definitions that are used by
+ * the rest of the engine. Most of the macros here are automatically
+ * determined at compile time, and you should not need to change it to port
+ * FreeType, except to compile the library with a non-ANSI compiler.
+ *
+ * Note however that if some specific modifications are needed, we advise
+ * you to place a modified copy in your build directory.
+ *
+ * The build directory is usually `builds/<system>`, and contains
+ * system-specific files that are always included first when building the
+ * library.
+ *
+ * This ANSI version should stay in `include/config/`.
+ *
+ */
#ifndef FTCONFIG_H_
#define FTCONFIG_H_
@@ -46,32 +45,32 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* PLATFORM-SPECIFIC CONFIGURATION MACROS */
- /* */
- /* These macros can be toggled to suit a specific system. The current */
- /* ones are defaults used to compile FreeType in an ANSI C environment */
- /* (16bit compilers are also supported). Copy this file to your own */
- /* `builds/<system>' directory, and edit it to port the engine. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * PLATFORM-SPECIFIC CONFIGURATION MACROS
+ *
+ * These macros can be toggled to suit a specific system. The current ones
+ * are defaults used to compile FreeType in an ANSI C environment (16bit
+ * compilers are also supported). Copy this file to your own
+ * `builds/<system>` directory, and edit it to port the engine.
+ *
+ */
- /* There are systems (like the Texas Instruments 'C54x) where a `char' */
- /* has 16 bits. ANSI C says that sizeof(char) is always 1. Since an */
- /* `int' has 16 bits also for this system, sizeof(int) gives 1 which */
- /* is probably unexpected. */
- /* */
- /* `CHAR_BIT' (defined in limits.h) gives the number of bits in a */
- /* `char' type. */
+ /* There are systems (like the Texas Instruments 'C54x) where a `char` */
+ /* has 16~bits. ANSI~C says that `sizeof(char)` is always~1. Since an */
+ /* `int` has 16~bits also for this system, `sizeof(int)` gives~1 which */
+ /* is probably unexpected. */
+ /* */
+ /* `CHAR_BIT` (defined in `limits.h`) gives the number of bits in a */
+ /* `char` type. */
#ifndef FT_CHAR_BIT
#define FT_CHAR_BIT CHAR_BIT
#endif
- /* The size of an `int' type. */
+ /* The size of an `int` type. */
#if FT_UINT_MAX == 0xFFFFUL
#define FT_SIZEOF_INT ( 16 / FT_CHAR_BIT )
#elif FT_UINT_MAX == 0xFFFFFFFFUL
@@ -82,7 +81,7 @@ FT_BEGIN_HEADER
#error "Unsupported size of `int' type!"
#endif
- /* The size of a `long' type. A five-byte `long' (as used e.g. on the */
+ /* The size of a `long` type. A five-byte `long` (as used e.g. on the */
/* DM642) is recognized but avoided. */
#if FT_ULONG_MAX == 0xFFFFFFFFUL
#define FT_SIZEOF_LONG ( 32 / FT_CHAR_BIT )
@@ -95,35 +94,35 @@ FT_BEGIN_HEADER
#endif
- /* FT_UNUSED is a macro used to indicate that a given parameter is not */
- /* used -- this is only used to get rid of unpleasant compiler warnings */
+ /* `FT_UNUSED` indicates that a given parameter is not used -- */
+ /* this is only used to get rid of unpleasant compiler warnings. */
#ifndef FT_UNUSED
#define FT_UNUSED( arg ) ( (arg) = (arg) )
#endif
- /*************************************************************************/
- /* */
- /* AUTOMATIC CONFIGURATION MACROS */
- /* */
- /* These macros are computed from the ones defined above. Don't touch */
- /* their definition, unless you know precisely what you are doing. No */
- /* porter should need to mess with them. */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* Mac support */
- /* */
- /* This is the only necessary change, so it is defined here instead */
- /* providing a new configuration file. */
- /* */
+ /**************************************************************************
+ *
+ * AUTOMATIC CONFIGURATION MACROS
+ *
+ * These macros are computed from the ones defined above. Don't touch
+ * their definition, unless you know precisely what you are doing. No
+ * porter should need to mess with them.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * Mac support
+ *
+ * This is the only necessary change, so it is defined here instead
+ * providing a new configuration file.
+ */
#if defined( __APPLE__ ) || ( defined( __MWERKS__ ) && defined( macintosh ) )
- /* no Carbon frameworks for 64bit 10.4.x */
- /* AvailabilityMacros.h is available since Mac OS X 10.2, */
- /* so guess the system version by maximum errno before inclusion */
+ /* No Carbon frameworks for 64bit 10.4.x. */
+ /* `AvailabilityMacros.h` is available since Mac OS X 10.2, */
+ /* so guess the system version by maximum errno before inclusion. */
#include <errno.h>
#ifdef ECANCELED /* defined since 10.2 */
#include "AvailabilityMacros.h"
@@ -143,7 +142,7 @@ FT_BEGIN_HEADER
#endif
- /* Fix compiler warning with sgi compiler */
+ /* Fix compiler warning with sgi compiler. */
#if defined( __sgi ) && !defined( __GNUC__ )
#if defined( _COMPILER_VERSION ) && ( _COMPILER_VERSION >= 730 )
#pragma set woff 3505
@@ -151,33 +150,33 @@ FT_BEGIN_HEADER
#endif
- /*************************************************************************/
- /* */
- /* <Section> */
- /* basic_types */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * @section:
+ * basic_types
+ *
+ */
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_Int16 */
- /* */
- /* <Description> */
- /* A typedef for a 16bit signed integer type. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Int16
+ *
+ * @description:
+ * A typedef for a 16bit signed integer type.
+ */
typedef signed short FT_Int16;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_UInt16 */
- /* */
- /* <Description> */
- /* A typedef for a 16bit unsigned integer type. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_UInt16
+ *
+ * @description:
+ * A typedef for a 16bit unsigned integer type.
+ */
typedef unsigned short FT_UInt16;
/* */
@@ -186,50 +185,50 @@ FT_BEGIN_HEADER
/* this #if 0 ... #endif clause is for documentation purposes */
#if 0
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_Int32 */
- /* */
- /* <Description> */
- /* A typedef for a 32bit signed integer type. The size depends on */
- /* the configuration. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Int32
+ *
+ * @description:
+ * A typedef for a 32bit signed integer type. The size depends on the
+ * configuration.
+ */
typedef signed XXX FT_Int32;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_UInt32 */
- /* */
- /* A typedef for a 32bit unsigned integer type. The size depends on */
- /* the configuration. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_UInt32
+ *
+ * A typedef for a 32bit unsigned integer type. The size depends on the
+ * configuration.
+ */
typedef unsigned XXX FT_UInt32;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_Int64 */
- /* */
- /* A typedef for a 64bit signed integer type. The size depends on */
- /* the configuration. Only defined if there is real 64bit support; */
- /* otherwise, it gets emulated with a structure (if necessary). */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Int64
+ *
+ * A typedef for a 64bit signed integer type. The size depends on the
+ * configuration. Only defined if there is real 64bit support;
+ * otherwise, it gets emulated with a structure (if necessary).
+ */
typedef signed XXX FT_Int64;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_UInt64 */
- /* */
- /* A typedef for a 64bit unsigned integer type. The size depends on */
- /* the configuration. Only defined if there is real 64bit support; */
- /* otherwise, it gets emulated with a structure (if necessary). */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_UInt64
+ *
+ * A typedef for a 64bit unsigned integer type. The size depends on the
+ * configuration. Only defined if there is real 64bit support;
+ * otherwise, it gets emulated with a structure (if necessary).
+ */
typedef unsigned XXX FT_UInt64;
/* */
@@ -251,7 +250,7 @@ FT_BEGIN_HEADER
#endif
- /* look up an integer type that is at least 32 bits */
+ /* look up an integer type that is at least 32~bits */
#if FT_SIZEOF_INT >= ( 32 / FT_CHAR_BIT )
typedef int FT_Fast;
@@ -265,22 +264,22 @@ FT_BEGIN_HEADER
#endif
- /* determine whether we have a 64-bit int type for platforms without */
- /* Autoconf */
+ /* determine whether we have a 64-bit `int` type for platforms without */
+ /* Autoconf */
#if FT_SIZEOF_LONG == ( 64 / FT_CHAR_BIT )
- /* FT_LONG64 must be defined if a 64-bit type is available */
+ /* `FT_LONG64` must be defined if a 64-bit type is available */
#define FT_LONG64
#define FT_INT64 long
#define FT_UINT64 unsigned long
- /*************************************************************************/
- /* */
- /* A 64-bit data type may create compilation problems if you compile */
- /* in strict ANSI mode. To avoid them, we disable other 64-bit data */
- /* types if __STDC__ is defined. You can however ignore this rule */
- /* by defining the FT_CONFIG_OPTION_FORCE_INT64 configuration macro. */
- /* */
+ /**************************************************************************
+ *
+ * A 64-bit data type may create compilation problems if you compile in
+ * strict ANSI mode. To avoid them, we disable other 64-bit data types if
+ * `__STDC__` is defined. You can however ignore this rule by defining the
+ * `FT_CONFIG_OPTION_FORCE_INT64` configuration macro.
+ */
#elif !defined( __STDC__ ) || defined( FT_CONFIG_OPTION_FORCE_INT64 )
#if defined( __STDC_VERSION__ ) && __STDC_VERSION__ >= 199901L
@@ -289,19 +288,19 @@ FT_BEGIN_HEADER
#define FT_INT64 long long int
#define FT_UINT64 unsigned long long int
-#elif defined( _MSC_VER ) && _MSC_VER >= 900 /* Visual C++ (and Intel C++) */
+#elif defined( _MSC_VER ) && _MSC_VER >= 900 /* Visual C++ (and Intel C++) */
- /* this compiler provides the __int64 type */
+ /* this compiler provides the `__int64` type */
#define FT_LONG64
#define FT_INT64 __int64
#define FT_UINT64 unsigned __int64
#elif defined( __BORLANDC__ ) /* Borland C++ */
- /* XXXX: We should probably check the value of __BORLANDC__ in order */
- /* to test the compiler version. */
+ /* XXXX: We should probably check the value of `__BORLANDC__` in order */
+ /* to test the compiler version. */
- /* this compiler provides the __int64 type */
+ /* this compiler provides the `__int64` type */
#define FT_LONG64
#define FT_INT64 __int64
#define FT_UINT64 unsigned __int64
@@ -318,7 +317,7 @@ FT_BEGIN_HEADER
#elif defined( __GNUC__ )
- /* GCC provides the `long long' type */
+ /* GCC provides the `long long` type */
#define FT_LONG64
#define FT_INT64 long long int
#define FT_UINT64 unsigned long long int
@@ -342,11 +341,11 @@ FT_BEGIN_HEADER
#endif
- /*************************************************************************/
- /* */
- /* miscellaneous */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * miscellaneous
+ *
+ */
#define FT_BEGIN_STMNT do {
@@ -354,7 +353,7 @@ FT_BEGIN_HEADER
#define FT_DUMMY_STMNT FT_BEGIN_STMNT FT_END_STMNT
- /* typeof condition taken from gnulib's `intprops.h' header file */
+ /* `typeof` condition taken from gnulib's `intprops.h` header file */
#if ( ( defined( __GNUC__ ) && __GNUC__ >= 2 ) || \
( defined( __IBMC__ ) && __IBMC__ >= 1210 && \
defined( __IBM__TYPEOF__ ) ) || \
@@ -365,14 +364,14 @@ FT_BEGIN_HEADER
#endif
- /* Use FT_LOCAL and FT_LOCAL_DEF to declare and define, respectively, */
- /* a function that gets used only within the scope of a module. */
- /* Normally, both the header and source code files for such a */
- /* function are within a single module directory. */
- /* */
- /* Intra-module arrays should be tagged with FT_LOCAL_ARRAY and */
- /* FT_LOCAL_ARRAY_DEF. */
- /* */
+ /* Use `FT_LOCAL` and `FT_LOCAL_DEF` to declare and define, */
+ /* respectively, a function that gets used only within the scope of a */
+ /* module. Normally, both the header and source code files for such a */
+ /* function are within a single module directory. */
+ /* */
+ /* Intra-module arrays should be tagged with `FT_LOCAL_ARRAY` and */
+ /* `FT_LOCAL_ARRAY_DEF`. */
+ /* */
#ifdef FT_MAKE_OPTION_SINGLE_OBJECT
#define FT_LOCAL( x ) static x
@@ -394,12 +393,12 @@ FT_BEGIN_HEADER
#define FT_LOCAL_ARRAY_DEF( x ) const x
- /* Use FT_BASE and FT_BASE_DEF to declare and define, respectively, */
- /* functions that are used in more than a single module. In the */
- /* current setup this implies that the declaration is in a header */
- /* file in the `include/freetype/internal' directory, and the */
- /* function body is in a file in `src/base'. */
- /* */
+ /* Use `FT_BASE` and `FT_BASE_DEF` to declare and define, respectively, */
+ /* functions that are used in more than a single module. In the */
+ /* current setup this implies that the declaration is in a header file */
+ /* in the `include/freetype/internal` directory, and the function body */
+ /* is in a file in `src/base`. */
+ /* */
#ifndef FT_BASE
#ifdef __cplusplus
@@ -422,45 +421,50 @@ FT_BEGIN_HEADER
#endif /* !FT_BASE_DEF */
- /* When compiling FreeType as a DLL or DSO with hidden visibility */
- /* some systems/compilers need a special attribute in front OR after */
- /* the return type of function declarations. */
- /* */
- /* Two macros are used within the FreeType source code to define */
- /* exported library functions: FT_EXPORT and FT_EXPORT_DEF. */
- /* */
- /* FT_EXPORT( return_type ) */
- /* */
- /* is used in a function declaration, as in */
- /* */
- /* FT_EXPORT( FT_Error ) */
- /* FT_Init_FreeType( FT_Library* alibrary ); */
- /* */
- /* */
- /* FT_EXPORT_DEF( return_type ) */
- /* */
- /* is used in a function definition, as in */
- /* */
- /* FT_EXPORT_DEF( FT_Error ) */
- /* FT_Init_FreeType( FT_Library* alibrary ) */
- /* { */
- /* ... some code ... */
- /* return FT_Err_Ok; */
- /* } */
- /* */
- /* You can provide your own implementation of FT_EXPORT and */
- /* FT_EXPORT_DEF here if you want. */
- /* */
- /* To export a variable, use FT_EXPORT_VAR. */
- /* */
+ /* When compiling FreeType as a DLL or DSO with hidden visibility */
+ /* some systems/compilers need a special attribute in front OR after */
+ /* the return type of function declarations. */
+ /* */
+ /* Two macros are used within the FreeType source code to define */
+ /* exported library functions: `FT_EXPORT` and `FT_EXPORT_DEF`. */
+ /* */
+ /* - `FT_EXPORT( return_type )` */
+ /* */
+ /* is used in a function declaration, as in */
+ /* */
+ /* ``` */
+ /* FT_EXPORT( FT_Error ) */
+ /* FT_Init_FreeType( FT_Library* alibrary ); */
+ /* ``` */
+ /* */
+ /* - `FT_EXPORT_DEF( return_type )` */
+ /* */
+ /* is used in a function definition, as in */
+ /* */
+ /* ``` */
+ /* FT_EXPORT_DEF( FT_Error ) */
+ /* FT_Init_FreeType( FT_Library* alibrary ) */
+ /* { */
+ /* ... some code ... */
+ /* return FT_Err_Ok; */
+ /* } */
+ /* ``` */
+ /* */
+ /* You can provide your own implementation of `FT_EXPORT` and */
+ /* `FT_EXPORT_DEF` here if you want. */
+ /* */
+ /* To export a variable, use `FT_EXPORT_VAR`. */
+ /* */
#ifndef FT_EXPORT
#ifdef FT2_BUILD_LIBRARY
-#if defined( _WIN32 ) && ( defined( _DLL ) || defined( DLL_EXPORT ) )
+#if defined( _WIN32 ) && defined( DLL_EXPORT )
#define FT_EXPORT( x ) __declspec( dllexport ) x
#elif defined( __GNUC__ ) && __GNUC__ >= 4
#define FT_EXPORT( x ) __attribute__(( visibility( "default" ) )) x
+#elif defined( __SUNPRO_C ) && __SUNPRO_C >= 0x550
+#define FT_EXPORT( x ) __global x
#elif defined( __cplusplus )
#define FT_EXPORT( x ) extern "C" x
#else
@@ -469,7 +473,7 @@ FT_BEGIN_HEADER
#else
-#if defined( FT2_DLLIMPORT )
+#if defined( _WIN32 ) && defined( DLL_IMPORT )
#define FT_EXPORT( x ) __declspec( dllimport ) x
#elif defined( __cplusplus )
#define FT_EXPORT( x ) extern "C" x
@@ -508,7 +512,7 @@ FT_BEGIN_HEADER
/* C++ compiler and with 16bit compilers. */
/* */
- /* This is special. Within C++, you must specify `extern "C"' for */
+ /* This is special. Within C++, you must specify `extern "C"` for */
/* functions which are used via function pointers, and you also */
/* must do that for structures which contain function pointers to */
/* assure C linkage -- it's not possible to have (local) anonymous */
@@ -531,7 +535,7 @@ FT_BEGIN_HEADER
/* */
/* */
/* Some 16bit compilers have to redefine these macros to insert */
- /* the infamous `_cdecl' or `__fastcall' declarations. */
+ /* the infamous `_cdecl` or `__fastcall` declarations. */
/* */
#ifndef FT_CALLBACK_DEF
#ifdef __cplusplus
diff --git a/thirdparty/freetype/include/freetype/config/ftheader.h b/thirdparty/freetype/include/freetype/config/ftheader.h
index 702f77cc42..696d6ba906 100644
--- a/thirdparty/freetype/include/freetype/config/ftheader.h
+++ b/thirdparty/freetype/include/freetype/config/ftheader.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftheader.h */
-/* */
-/* Build macros of the FreeType 2 library. */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftheader.h
+ *
+ * Build macros of the FreeType 2 library.
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTHEADER_H_
#define FTHEADER_H_
@@ -27,7 +27,7 @@
/* <Description> */
/* This macro is used in association with @FT_END_HEADER in header */
/* files to ensure that the declarations within are properly */
- /* encapsulated in an `extern "C" { .. }' block when included from a */
+ /* encapsulated in an `extern "C" { .. }` block when included from a */
/* C++ compiler. */
/* */
#ifdef __cplusplus
@@ -45,7 +45,7 @@
/* <Description> */
/* This macro is used in association with @FT_BEGIN_HEADER in header */
/* files to ensure that the declarations within are properly */
- /* encapsulated in an `extern "C" { .. }' block when included from a */
+ /* encapsulated in an `extern "C" { .. }` block when included from a */
/* C++ compiler. */
/* */
#ifdef __cplusplus
@@ -55,54 +55,54 @@
#endif
- /*************************************************************************/
- /* */
- /* Aliases for the FreeType 2 public and configuration files. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * Aliases for the FreeType 2 public and configuration files.
+ *
+ */
- /*************************************************************************/
- /* */
- /* <Section> */
- /* header_file_macros */
- /* */
- /* <Title> */
- /* Header File Macros */
- /* */
- /* <Abstract> */
- /* Macro definitions used to #include specific header files. */
- /* */
- /* <Description> */
- /* The following macros are defined to the name of specific */
- /* FreeType~2 header files. They can be used directly in #include */
- /* statements as in: */
- /* */
- /* { */
- /* #include FT_FREETYPE_H */
- /* #include FT_MULTIPLE_MASTERS_H */
- /* #include FT_GLYPH_H */
- /* } */
- /* */
- /* There are several reasons why we are now using macros to name */
- /* public header files. The first one is that such macros are not */
- /* limited to the infamous 8.3~naming rule required by DOS (and */
- /* `FT_MULTIPLE_MASTERS_H' is a lot more meaningful than `ftmm.h'). */
- /* */
- /* The second reason is that it allows for more flexibility in the */
- /* way FreeType~2 is installed on a given system. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * @section:
+ * header_file_macros
+ *
+ * @title:
+ * Header File Macros
+ *
+ * @abstract:
+ * Macro definitions used to `#include` specific header files.
+ *
+ * @description:
+ * The following macros are defined to the name of specific FreeType~2
+ * header files. They can be used directly in `#include` statements as
+ * in:
+ *
+ * ```
+ * #include FT_FREETYPE_H
+ * #include FT_MULTIPLE_MASTERS_H
+ * #include FT_GLYPH_H
+ * ```
+ *
+ * There are several reasons why we are now using macros to name public
+ * header files. The first one is that such macros are not limited to
+ * the infamous 8.3~naming rule required by DOS (and
+ * `FT_MULTIPLE_MASTERS_H` is a lot more meaningful than `ftmm.h`).
+ *
+ * The second reason is that it allows for more flexibility in the way
+ * FreeType~2 is installed on a given system.
+ *
+ */
/* configuration files */
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_CONFIG_CONFIG_H
*
* @description:
- * A macro used in #include statements to name the file containing
+ * A macro used in `#include` statements to name the file containing
* FreeType~2 configuration data.
*
*/
@@ -111,13 +111,13 @@
#endif
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_CONFIG_STANDARD_LIBRARY_H
*
* @description:
- * A macro used in #include statements to name the file containing
+ * A macro used in `#include` statements to name the file containing
* FreeType~2 interface to the standard C library functions.
*
*/
@@ -126,13 +126,13 @@
#endif
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_CONFIG_OPTIONS_H
*
* @description:
- * A macro used in #include statements to name the file containing
+ * A macro used in `#include` statements to name the file containing
* FreeType~2 project-specific configuration options.
*
*/
@@ -141,13 +141,13 @@
#endif
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_CONFIG_MODULES_H
*
* @description:
- * A macro used in #include statements to name the file containing the
+ * A macro used in `#include` statements to name the file containing the
* list of FreeType~2 modules that are statically linked to new library
* instances in @FT_Init_FreeType.
*
@@ -160,26 +160,26 @@
/* public headers */
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_FREETYPE_H
*
* @description:
- * A macro used in #include statements to name the file containing the
+ * A macro used in `#include` statements to name the file containing the
* base FreeType~2 API.
*
*/
#define FT_FREETYPE_H <freetype/freetype.h>
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_ERRORS_H
*
* @description:
- * A macro used in #include statements to name the file containing the
+ * A macro used in `#include` statements to name the file containing the
* list of FreeType~2 error codes (and messages).
*
* It is included by @FT_FREETYPE_H.
@@ -188,26 +188,26 @@
#define FT_ERRORS_H <freetype/fterrors.h>
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_MODULE_ERRORS_H
*
* @description:
- * A macro used in #include statements to name the file containing the
+ * A macro used in `#include` statements to name the file containing the
* list of FreeType~2 module error offsets (and messages).
*
*/
#define FT_MODULE_ERRORS_H <freetype/ftmoderr.h>
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_SYSTEM_H
*
* @description:
- * A macro used in #include statements to name the file containing the
+ * A macro used in `#include` statements to name the file containing the
* FreeType~2 interface to low-level operations (i.e., memory management
* and stream i/o).
*
@@ -217,13 +217,13 @@
#define FT_SYSTEM_H <freetype/ftsystem.h>
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_IMAGE_H
*
* @description:
- * A macro used in #include statements to name the file containing type
+ * A macro used in `#include` statements to name the file containing type
* definitions related to glyph images (i.e., bitmaps, outlines,
* scan-converter parameters).
*
@@ -233,13 +233,13 @@
#define FT_IMAGE_H <freetype/ftimage.h>
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_TYPES_H
*
* @description:
- * A macro used in #include statements to name the file containing the
+ * A macro used in `#include` statements to name the file containing the
* basic data types defined by FreeType~2.
*
* It is included by @FT_FREETYPE_H.
@@ -248,13 +248,13 @@
#define FT_TYPES_H <freetype/fttypes.h>
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_LIST_H
*
* @description:
- * A macro used in #include statements to name the file containing the
+ * A macro used in `#include` statements to name the file containing the
* list management API of FreeType~2.
*
* (Most applications will never need to include this file.)
@@ -263,151 +263,151 @@
#define FT_LIST_H <freetype/ftlist.h>
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_OUTLINE_H
*
* @description:
- * A macro used in #include statements to name the file containing the
+ * A macro used in `#include` statements to name the file containing the
* scalable outline management API of FreeType~2.
*
*/
#define FT_OUTLINE_H <freetype/ftoutln.h>
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_SIZES_H
*
* @description:
- * A macro used in #include statements to name the file containing the
+ * A macro used in `#include` statements to name the file containing the
* API which manages multiple @FT_Size objects per face.
*
*/
#define FT_SIZES_H <freetype/ftsizes.h>
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_MODULE_H
*
* @description:
- * A macro used in #include statements to name the file containing the
+ * A macro used in `#include` statements to name the file containing the
* module management API of FreeType~2.
*
*/
#define FT_MODULE_H <freetype/ftmodapi.h>
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_RENDER_H
*
* @description:
- * A macro used in #include statements to name the file containing the
+ * A macro used in `#include` statements to name the file containing the
* renderer module management API of FreeType~2.
*
*/
#define FT_RENDER_H <freetype/ftrender.h>
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_DRIVER_H
*
* @description:
- * A macro used in #include statements to name the file containing
+ * A macro used in `#include` statements to name the file containing
* structures and macros related to the driver modules.
*
*/
#define FT_DRIVER_H <freetype/ftdriver.h>
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_AUTOHINTER_H
*
* @description:
- * A macro used in #include statements to name the file containing
+ * A macro used in `#include` statements to name the file containing
* structures and macros related to the auto-hinting module.
*
- * Deprecated since version 2.9; use @FT_DRIVER_H instead.
+ * Deprecated since version~2.9; use @FT_DRIVER_H instead.
*
*/
#define FT_AUTOHINTER_H FT_DRIVER_H
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_CFF_DRIVER_H
*
* @description:
- * A macro used in #include statements to name the file containing
+ * A macro used in `#include` statements to name the file containing
* structures and macros related to the CFF driver module.
*
- * Deprecated since version 2.9; use @FT_DRIVER_H instead.
+ * Deprecated since version~2.9; use @FT_DRIVER_H instead.
*
*/
#define FT_CFF_DRIVER_H FT_DRIVER_H
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_TRUETYPE_DRIVER_H
*
* @description:
- * A macro used in #include statements to name the file containing
+ * A macro used in `#include` statements to name the file containing
* structures and macros related to the TrueType driver module.
*
- * Deprecated since version 2.9; use @FT_DRIVER_H instead.
+ * Deprecated since version~2.9; use @FT_DRIVER_H instead.
*
*/
#define FT_TRUETYPE_DRIVER_H FT_DRIVER_H
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_PCF_DRIVER_H
*
* @description:
- * A macro used in #include statements to name the file containing
+ * A macro used in `#include` statements to name the file containing
* structures and macros related to the PCF driver module.
*
- * Deprecated since version 2.9; use @FT_DRIVER_H instead.
+ * Deprecated since version~2.9; use @FT_DRIVER_H instead.
*
*/
#define FT_PCF_DRIVER_H FT_DRIVER_H
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_TYPE1_TABLES_H
*
* @description:
- * A macro used in #include statements to name the file containing the
+ * A macro used in `#include` statements to name the file containing the
* types and API specific to the Type~1 format.
*
*/
#define FT_TYPE1_TABLES_H <freetype/t1tables.h>
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_TRUETYPE_IDS_H
*
* @description:
- * A macro used in #include statements to name the file containing the
+ * A macro used in `#include` statements to name the file containing the
* enumeration values which identify name strings, languages, encodings,
* etc. This file really contains a _large_ set of constant macro
* definitions, taken from the TrueType and OpenType specifications.
@@ -416,174 +416,172 @@
#define FT_TRUETYPE_IDS_H <freetype/ttnameid.h>
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_TRUETYPE_TABLES_H
*
* @description:
- * A macro used in #include statements to name the file containing the
+ * A macro used in `#include` statements to name the file containing the
* types and API specific to the TrueType (as well as OpenType) format.
*
*/
#define FT_TRUETYPE_TABLES_H <freetype/tttables.h>
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_TRUETYPE_TAGS_H
*
* @description:
- * A macro used in #include statements to name the file containing the
- * definitions of TrueType four-byte `tags' which identify blocks in
+ * A macro used in `#include` statements to name the file containing the
+ * definitions of TrueType four-byte 'tags' which identify blocks in
* SFNT-based font formats (i.e., TrueType and OpenType).
*
*/
#define FT_TRUETYPE_TAGS_H <freetype/tttags.h>
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_BDF_H
*
* @description:
- * A macro used in #include statements to name the file containing the
- * definitions of an API which accesses BDF-specific strings from a
- * face.
+ * A macro used in `#include` statements to name the file containing the
+ * definitions of an API which accesses BDF-specific strings from a face.
*
*/
#define FT_BDF_H <freetype/ftbdf.h>
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_CID_H
*
* @description:
- * A macro used in #include statements to name the file containing the
- * definitions of an API which access CID font information from a
- * face.
+ * A macro used in `#include` statements to name the file containing the
+ * definitions of an API which access CID font information from a face.
*
*/
#define FT_CID_H <freetype/ftcid.h>
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_GZIP_H
*
* @description:
- * A macro used in #include statements to name the file containing the
+ * A macro used in `#include` statements to name the file containing the
* definitions of an API which supports gzip-compressed files.
*
*/
#define FT_GZIP_H <freetype/ftgzip.h>
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_LZW_H
*
* @description:
- * A macro used in #include statements to name the file containing the
+ * A macro used in `#include` statements to name the file containing the
* definitions of an API which supports LZW-compressed files.
*
*/
#define FT_LZW_H <freetype/ftlzw.h>
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_BZIP2_H
*
* @description:
- * A macro used in #include statements to name the file containing the
+ * A macro used in `#include` statements to name the file containing the
* definitions of an API which supports bzip2-compressed files.
*
*/
#define FT_BZIP2_H <freetype/ftbzip2.h>
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_WINFONTS_H
*
* @description:
- * A macro used in #include statements to name the file containing the
+ * A macro used in `#include` statements to name the file containing the
* definitions of an API which supports Windows FNT files.
*
*/
#define FT_WINFONTS_H <freetype/ftwinfnt.h>
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_GLYPH_H
*
* @description:
- * A macro used in #include statements to name the file containing the
+ * A macro used in `#include` statements to name the file containing the
* API of the optional glyph management component.
*
*/
#define FT_GLYPH_H <freetype/ftglyph.h>
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_BITMAP_H
*
* @description:
- * A macro used in #include statements to name the file containing the
+ * A macro used in `#include` statements to name the file containing the
* API of the optional bitmap conversion component.
*
*/
#define FT_BITMAP_H <freetype/ftbitmap.h>
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_BBOX_H
*
* @description:
- * A macro used in #include statements to name the file containing the
+ * A macro used in `#include` statements to name the file containing the
* API of the optional exact bounding box computation routines.
*
*/
#define FT_BBOX_H <freetype/ftbbox.h>
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_CACHE_H
*
* @description:
- * A macro used in #include statements to name the file containing the
+ * A macro used in `#include` statements to name the file containing the
* API of the optional FreeType~2 cache sub-system.
*
*/
#define FT_CACHE_H <freetype/ftcache.h>
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_MAC_H
*
* @description:
- * A macro used in #include statements to name the file containing the
- * Macintosh-specific FreeType~2 API. The latter is used to access
- * fonts embedded in resource forks.
+ * A macro used in `#include` statements to name the file containing the
+ * Macintosh-specific FreeType~2 API. The latter is used to access fonts
+ * embedded in resource forks.
*
* This header file must be explicitly included by client applications
* compiled on the Mac (note that the base API still works though).
@@ -592,105 +590,105 @@
#define FT_MAC_H <freetype/ftmac.h>
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_MULTIPLE_MASTERS_H
*
* @description:
- * A macro used in #include statements to name the file containing the
+ * A macro used in `#include` statements to name the file containing the
* optional multiple-masters management API of FreeType~2.
*
*/
#define FT_MULTIPLE_MASTERS_H <freetype/ftmm.h>
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_SFNT_NAMES_H
*
* @description:
- * A macro used in #include statements to name the file containing the
- * optional FreeType~2 API which accesses embedded `name' strings in
+ * A macro used in `#include` statements to name the file containing the
+ * optional FreeType~2 API which accesses embedded 'name' strings in
* SFNT-based font formats (i.e., TrueType and OpenType).
*
*/
#define FT_SFNT_NAMES_H <freetype/ftsnames.h>
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_OPENTYPE_VALIDATE_H
*
* @description:
- * A macro used in #include statements to name the file containing the
- * optional FreeType~2 API which validates OpenType tables (BASE, GDEF,
- * GPOS, GSUB, JSTF).
+ * A macro used in `#include` statements to name the file containing the
+ * optional FreeType~2 API which validates OpenType tables ('BASE',
+ * 'GDEF', 'GPOS', 'GSUB', 'JSTF').
*
*/
#define FT_OPENTYPE_VALIDATE_H <freetype/ftotval.h>
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_GX_VALIDATE_H
*
* @description:
- * A macro used in #include statements to name the file containing the
- * optional FreeType~2 API which validates TrueTypeGX/AAT tables (feat,
- * mort, morx, bsln, just, kern, opbd, trak, prop).
+ * A macro used in `#include` statements to name the file containing the
+ * optional FreeType~2 API which validates TrueTypeGX/AAT tables ('feat',
+ * 'mort', 'morx', 'bsln', 'just', 'kern', 'opbd', 'trak', 'prop').
*
*/
#define FT_GX_VALIDATE_H <freetype/ftgxval.h>
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_PFR_H
*
* @description:
- * A macro used in #include statements to name the file containing the
+ * A macro used in `#include` statements to name the file containing the
* FreeType~2 API which accesses PFR-specific data.
*
*/
#define FT_PFR_H <freetype/ftpfr.h>
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_STROKER_H
*
* @description:
- * A macro used in #include statements to name the file containing the
+ * A macro used in `#include` statements to name the file containing the
* FreeType~2 API which provides functions to stroke outline paths.
*/
#define FT_STROKER_H <freetype/ftstroke.h>
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_SYNTHESIS_H
*
* @description:
- * A macro used in #include statements to name the file containing the
+ * A macro used in `#include` statements to name the file containing the
* FreeType~2 API which performs artificial obliquing and emboldening.
*/
#define FT_SYNTHESIS_H <freetype/ftsynth.h>
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_FONT_FORMATS_H
*
* @description:
- * A macro used in #include statements to name the file containing the
+ * A macro used in `#include` statements to name the file containing the
* FreeType~2 API which provides functions specific to font formats.
*/
#define FT_FONT_FORMATS_H <freetype/ftfntfmt.h>
@@ -699,67 +697,79 @@
#define FT_XFREE86_H FT_FONT_FORMATS_H
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_TRIGONOMETRY_H
*
* @description:
- * A macro used in #include statements to name the file containing the
+ * A macro used in `#include` statements to name the file containing the
* FreeType~2 API which performs trigonometric computations (e.g.,
* cosines and arc tangents).
*/
#define FT_TRIGONOMETRY_H <freetype/fttrigon.h>
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_LCD_FILTER_H
*
* @description:
- * A macro used in #include statements to name the file containing the
+ * A macro used in `#include` statements to name the file containing the
* FreeType~2 API which performs color filtering for subpixel rendering.
*/
#define FT_LCD_FILTER_H <freetype/ftlcdfil.h>
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_INCREMENTAL_H
*
* @description:
- * A macro used in #include statements to name the file containing the
+ * A macro used in `#include` statements to name the file containing the
* FreeType~2 API which performs incremental glyph loading.
*/
#define FT_INCREMENTAL_H <freetype/ftincrem.h>
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_GASP_H
*
* @description:
- * A macro used in #include statements to name the file containing the
+ * A macro used in `#include` statements to name the file containing the
* FreeType~2 API which returns entries from the TrueType GASP table.
*/
#define FT_GASP_H <freetype/ftgasp.h>
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_ADVANCES_H
*
* @description:
- * A macro used in #include statements to name the file containing the
+ * A macro used in `#include` statements to name the file containing the
* FreeType~2 API which returns individual and ranged glyph advances.
*/
#define FT_ADVANCES_H <freetype/ftadvanc.h>
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_COLOR_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * FreeType~2 API which handles the OpenType 'CPAL' table.
+ */
+#define FT_COLOR_H <freetype/ftcolor.h>
+
+
/* */
/* These header files don't need to be included by the user. */
@@ -770,14 +780,14 @@
#define FT_UNPATENTED_HINTING_H <freetype/ftparams.h>
#define FT_TRUETYPE_UNPATENTED_H <freetype/ftparams.h>
- /* FT_CACHE_H is the only header file needed for the cache subsystem. */
+ /* `FT_CACHE_H` is the only header file needed for the cache subsystem. */
#define FT_CACHE_IMAGE_H FT_CACHE_H
#define FT_CACHE_SMALL_BITMAPS_H FT_CACHE_H
#define FT_CACHE_CHARMAP_H FT_CACHE_H
/* The internals of the cache sub-system are no longer exposed. We */
- /* default to FT_CACHE_H at the moment just in case, but we know of */
- /* no rogue client that uses them. */
+ /* default to `FT_CACHE_H` at the moment just in case, but we know */
+ /* of no rogue client that uses them. */
/* */
#define FT_CACHE_MANAGER_H FT_CACHE_H
#define FT_CACHE_INTERNAL_MRU_H FT_CACHE_H
@@ -789,8 +799,8 @@
/*
- * Include internal headers definitions from <internal/...>
- * only when building the library.
+ * Include internal headers definitions from `<internal/...>` only when
+ * building the library.
*/
#ifdef FT2_BUILD_LIBRARY
#define FT_INTERNAL_INTERNAL_H <freetype/internal/internal.h>
diff --git a/thirdparty/freetype/include/freetype/config/ftmodule.h b/thirdparty/freetype/include/freetype/config/ftmodule.h
index 76d271a74b..7c603e5327 100644
--- a/thirdparty/freetype/include/freetype/config/ftmodule.h
+++ b/thirdparty/freetype/include/freetype/config/ftmodule.h
@@ -1,12 +1,12 @@
/*
- * This file registers the FreeType modules compiled into the library.
+ * This file registers the FreeType modules compiled into the library.
*
- * If you use GNU make, this file IS NOT USED! Instead, it is created in
- * the objects directory (normally `<topdir>/objs/') based on information
- * from `<topdir>/modules.cfg'.
+ * If you use GNU make, this file IS NOT USED! Instead, it is created in
+ * the objects directory (normally `<topdir>/objs/`) based on information
+ * from `<topdir>/modules.cfg`.
*
- * Please read `docs/INSTALL.ANY' and `docs/CUSTOMIZE' how to compile
- * FreeType without GNU make.
+ * Please read `docs/INSTALL.ANY` and `docs/CUSTOMIZE` how to compile
+ * FreeType without GNU make.
*
*/
diff --git a/thirdparty/freetype/include/freetype/config/ftoption.h b/thirdparty/freetype/include/freetype/config/ftoption.h
index 1fc7295a2c..12f47a82e8 100644
--- a/thirdparty/freetype/include/freetype/config/ftoption.h
+++ b/thirdparty/freetype/include/freetype/config/ftoption.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftoption.h */
-/* */
-/* User-selectable configuration macros (specification only). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftoption.h
+ *
+ * User-selectable configuration macros (specification only).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTOPTION_H_
@@ -25,45 +25,47 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* USER-SELECTABLE CONFIGURATION MACROS */
- /* */
- /* This file contains the default configuration macro definitions for */
- /* a standard build of the FreeType library. There are three ways to */
- /* use this file to build project-specific versions of the library: */
- /* */
- /* - You can modify this file by hand, but this is not recommended in */
- /* cases where you would like to build several versions of the */
- /* library from a single source directory. */
- /* */
- /* - You can put a copy of this file in your build directory, more */
- /* precisely in `$BUILD/freetype/config/ftoption.h', where `$BUILD' */
- /* is the name of a directory that is included _before_ the FreeType */
- /* include path during compilation. */
- /* */
- /* The default FreeType Makefiles and Jamfiles use the build */
- /* directory `builds/<system>' by default, but you can easily change */
- /* that for your own projects. */
- /* */
- /* - Copy the file <ft2build.h> to `$BUILD/ft2build.h' and modify it */
- /* slightly to pre-define the macro FT_CONFIG_OPTIONS_H used to */
- /* locate this file during the build. For example, */
- /* */
- /* #define FT_CONFIG_OPTIONS_H <myftoptions.h> */
- /* #include <freetype/config/ftheader.h> */
- /* */
- /* will use `$BUILD/myftoptions.h' instead of this file for macro */
- /* definitions. */
- /* */
- /* Note also that you can similarly pre-define the macro */
- /* FT_CONFIG_MODULES_H used to locate the file listing of the modules */
- /* that are statically linked to the library at compile time. By */
- /* default, this file is <freetype/config/ftmodule.h>. */
- /* */
- /* We highly recommend using the third method whenever possible. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * USER-SELECTABLE CONFIGURATION MACROS
+ *
+ * This file contains the default configuration macro definitions for a
+ * standard build of the FreeType library. There are three ways to use
+ * this file to build project-specific versions of the library:
+ *
+ * - You can modify this file by hand, but this is not recommended in
+ * cases where you would like to build several versions of the library
+ * from a single source directory.
+ *
+ * - You can put a copy of this file in your build directory, more
+ * precisely in `$BUILD/freetype/config/ftoption.h`, where `$BUILD` is
+ * the name of a directory that is included _before_ the FreeType include
+ * path during compilation.
+ *
+ * The default FreeType Makefiles and Jamfiles use the build directory
+ * `builds/<system>` by default, but you can easily change that for your
+ * own projects.
+ *
+ * - Copy the file <ft2build.h> to `$BUILD/ft2build.h` and modify it
+ * slightly to pre-define the macro `FT_CONFIG_OPTIONS_H` used to locate
+ * this file during the build. For example,
+ *
+ * ```
+ * #define FT_CONFIG_OPTIONS_H <myftoptions.h>
+ * #include <freetype/config/ftheader.h>
+ * ```
+ *
+ * will use `$BUILD/myftoptions.h` instead of this file for macro
+ * definitions.
+ *
+ * Note also that you can similarly pre-define the macro
+ * `FT_CONFIG_MODULES_H` used to locate the file listing of the modules
+ * that are statically linked to the library at compile time. By
+ * default, this file is `<freetype/config/ftmodule.h>`.
+ *
+ * We highly recommend using the third method whenever possible.
+ *
+ */
/*************************************************************************/
@@ -75,444 +77,433 @@ FT_BEGIN_HEADER
/*************************************************************************/
- /*#***********************************************************************/
- /* */
- /* If you enable this configuration option, FreeType recognizes an */
- /* environment variable called `FREETYPE_PROPERTIES', which can be used */
- /* to control the various font drivers and modules. The controllable */
- /* properties are listed in the section @properties. */
- /* */
- /* You have to undefine this configuration option on platforms that lack */
- /* the concept of environment variables (and thus don't have the */
- /* `getenv' function), for example Windows CE. */
- /* */
- /* `FREETYPE_PROPERTIES' has the following syntax form (broken here into */
- /* multiple lines for better readability). */
- /* */
- /* { */
- /* <optional whitespace> */
- /* <module-name1> ':' */
- /* <property-name1> '=' <property-value1> */
- /* <whitespace> */
- /* <module-name2> ':' */
- /* <property-name2> '=' <property-value2> */
- /* ... */
- /* } */
- /* */
- /* Example: */
- /* */
- /* FREETYPE_PROPERTIES=truetype:interpreter-version=35 \ */
- /* cff:no-stem-darkening=1 \ */
- /* autofitter:warping=1 */
- /* */
+ /*#************************************************************************
+ *
+ * If you enable this configuration option, FreeType recognizes an
+ * environment variable called `FREETYPE_PROPERTIES`, which can be used to
+ * control the various font drivers and modules. The controllable
+ * properties are listed in the section @properties.
+ *
+ * You have to undefine this configuration option on platforms that lack
+ * the concept of environment variables (and thus don't have the `getenv`
+ * function), for example Windows CE.
+ *
+ * `FREETYPE_PROPERTIES` has the following syntax form (broken here into
+ * multiple lines for better readability).
+ *
+ * ```
+ * <optional whitespace>
+ * <module-name1> ':'
+ * <property-name1> '=' <property-value1>
+ * <whitespace>
+ * <module-name2> ':'
+ * <property-name2> '=' <property-value2>
+ * ...
+ * ```
+ *
+ * Example:
+ *
+ * ```
+ * FREETYPE_PROPERTIES=truetype:interpreter-version=35 \
+ * cff:no-stem-darkening=1 \
+ * autofitter:warping=1
+ * ```
+ *
+ */
#define FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
- /*************************************************************************/
- /* */
- /* Uncomment the line below if you want to activate LCD rendering */
- /* technology similar to ClearType in this build of the library. This */
- /* technology triples the resolution in the direction color subpixels. */
- /* To mitigate color fringes inherent to this technology, you also need */
- /* to explicitly set up LCD filtering. */
- /* */
- /* Note that this feature is covered by several Microsoft patents */
- /* and should not be activated in any default build of the library. */
- /* When this macro is not defined, FreeType offers alternative LCD */
- /* rendering technology that produces excellent output without LCD */
- /* filtering. */
- /* */
+ /**************************************************************************
+ *
+ * Uncomment the line below if you want to activate LCD rendering
+ * technology similar to ClearType in this build of the library. This
+ * technology triples the resolution in the direction color subpixels. To
+ * mitigate color fringes inherent to this technology, you also need to
+ * explicitly set up LCD filtering.
+ *
+ * Note that this feature is covered by several Microsoft patents and
+ * should not be activated in any default build of the library. When this
+ * macro is not defined, FreeType offers alternative LCD rendering
+ * technology that produces excellent output without LCD filtering.
+ */
/* #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
- /*************************************************************************/
- /* */
- /* Many compilers provide a non-ANSI 64-bit data type that can be used */
- /* by FreeType to speed up some computations. However, this will create */
- /* some problems when compiling the library in strict ANSI mode. */
- /* */
- /* For this reason, the use of 64-bit integers is normally disabled when */
- /* the __STDC__ macro is defined. You can however disable this by */
- /* defining the macro FT_CONFIG_OPTION_FORCE_INT64 here. */
- /* */
- /* For most compilers, this will only create compilation warnings when */
- /* building the library. */
- /* */
- /* ObNote: The compiler-specific 64-bit integers are detected in the */
- /* file `ftconfig.h' either statically or through the */
- /* `configure' script on supported platforms. */
- /* */
+ /**************************************************************************
+ *
+ * Many compilers provide a non-ANSI 64-bit data type that can be used by
+ * FreeType to speed up some computations. However, this will create some
+ * problems when compiling the library in strict ANSI mode.
+ *
+ * For this reason, the use of 64-bit integers is normally disabled when
+ * the `__STDC__` macro is defined. You can however disable this by
+ * defining the macro `FT_CONFIG_OPTION_FORCE_INT64` here.
+ *
+ * For most compilers, this will only create compilation warnings when
+ * building the library.
+ *
+ * ObNote: The compiler-specific 64-bit integers are detected in the
+ * file `ftconfig.h` either statically or through the `configure`
+ * script on supported platforms.
+ */
#undef FT_CONFIG_OPTION_FORCE_INT64
- /*************************************************************************/
- /* */
- /* If this macro is defined, do not try to use an assembler version of */
- /* performance-critical functions (e.g. FT_MulFix). You should only do */
- /* that to verify that the assembler function works properly, or to */
- /* execute benchmark tests of the various implementations. */
+ /**************************************************************************
+ *
+ * If this macro is defined, do not try to use an assembler version of
+ * performance-critical functions (e.g., @FT_MulFix). You should only do
+ * that to verify that the assembler function works properly, or to execute
+ * benchmark tests of the various implementations.
+ */
/* #define FT_CONFIG_OPTION_NO_ASSEMBLER */
- /*************************************************************************/
- /* */
- /* If this macro is defined, try to use an inlined assembler version of */
- /* the `FT_MulFix' function, which is a `hotspot' when loading and */
- /* hinting glyphs, and which should be executed as fast as possible. */
- /* */
- /* Note that if your compiler or CPU is not supported, this will default */
- /* to the standard and portable implementation found in `ftcalc.c'. */
- /* */
+ /**************************************************************************
+ *
+ * If this macro is defined, try to use an inlined assembler version of the
+ * @FT_MulFix function, which is a 'hotspot' when loading and hinting
+ * glyphs, and which should be executed as fast as possible.
+ *
+ * Note that if your compiler or CPU is not supported, this will default to
+ * the standard and portable implementation found in `ftcalc.c`.
+ */
#define FT_CONFIG_OPTION_INLINE_MULFIX
- /*************************************************************************/
- /* */
- /* LZW-compressed file support. */
- /* */
- /* FreeType now handles font files that have been compressed with the */
- /* `compress' program. This is mostly used to parse many of the PCF */
- /* files that come with various X11 distributions. The implementation */
- /* uses NetBSD's `zopen' to partially uncompress the file on the fly */
- /* (see src/lzw/ftgzip.c). */
- /* */
- /* Define this macro if you want to enable this `feature'. */
- /* */
-/* #define FT_CONFIG_OPTION_USE_LZW */ // -GODOT-
-
-
- /*************************************************************************/
- /* */
- /* Gzip-compressed file support. */
- /* */
- /* FreeType now handles font files that have been compressed with the */
- /* `gzip' program. This is mostly used to parse many of the PCF files */
- /* that come with XFree86. The implementation uses `zlib' to */
- /* partially uncompress the file on the fly (see src/gzip/ftgzip.c). */
- /* */
- /* Define this macro if you want to enable this `feature'. See also */
- /* the macro FT_CONFIG_OPTION_SYSTEM_ZLIB below. */
- /* */
-/* #define FT_CONFIG_OPTION_USE_ZLIB */ // -GODOT-
-
-
- /*************************************************************************/
- /* */
- /* ZLib library selection */
- /* */
- /* This macro is only used when FT_CONFIG_OPTION_USE_ZLIB is defined. */
- /* It allows FreeType's `ftgzip' component to link to the system's */
- /* installation of the ZLib library. This is useful on systems like */
- /* Unix or VMS where it generally is already available. */
- /* */
- /* If you let it undefined, the component will use its own copy */
- /* of the zlib sources instead. These have been modified to be */
- /* included directly within the component and *not* export external */
- /* function names. This allows you to link any program with FreeType */
- /* _and_ ZLib without linking conflicts. */
- /* */
- /* Do not #undef this macro here since the build system might define */
- /* it for certain configurations only. */
- /* */
- /* If you use a build system like cmake or the `configure' script, */
- /* options set by those programs have precendence, overwriting the */
- /* value here with the configured one. */
- /* */
+ /**************************************************************************
+ *
+ * LZW-compressed file support.
+ *
+ * FreeType now handles font files that have been compressed with the
+ * `compress` program. This is mostly used to parse many of the PCF
+ * files that come with various X11 distributions. The implementation
+ * uses NetBSD's `zopen` to partially uncompress the file on the fly (see
+ * `src/lzw/ftgzip.c`).
+ *
+ * Define this macro if you want to enable this 'feature'.
+ */
+#define FT_CONFIG_OPTION_USE_LZW
+
+
+ /**************************************************************************
+ *
+ * Gzip-compressed file support.
+ *
+ * FreeType now handles font files that have been compressed with the
+ * `gzip` program. This is mostly used to parse many of the PCF files
+ * that come with XFree86. The implementation uses 'zlib' to partially
+ * uncompress the file on the fly (see `src/gzip/ftgzip.c`).
+ *
+ * Define this macro if you want to enable this 'feature'. See also the
+ * macro `FT_CONFIG_OPTION_SYSTEM_ZLIB` below.
+ */
+#define FT_CONFIG_OPTION_USE_ZLIB
+
+
+ /**************************************************************************
+ *
+ * ZLib library selection
+ *
+ * This macro is only used when `FT_CONFIG_OPTION_USE_ZLIB` is defined.
+ * It allows FreeType's 'ftgzip' component to link to the system's
+ * installation of the ZLib library. This is useful on systems like
+ * Unix or VMS where it generally is already available.
+ *
+ * If you let it undefined, the component will use its own copy of the
+ * zlib sources instead. These have been modified to be included
+ * directly within the component and **not** export external function
+ * names. This allows you to link any program with FreeType _and_ ZLib
+ * without linking conflicts.
+ *
+ * Do not `#undef` this macro here since the build system might define
+ * it for certain configurations only.
+ *
+ * If you use a build system like cmake or the `configure` script,
+ * options set by those programs have precedence, overwriting the value
+ * here with the configured one.
+ */
/* #define FT_CONFIG_OPTION_SYSTEM_ZLIB */
- /*************************************************************************/
- /* */
- /* Bzip2-compressed file support. */
- /* */
- /* FreeType now handles font files that have been compressed with the */
- /* `bzip2' program. This is mostly used to parse many of the PCF */
- /* files that come with XFree86. The implementation uses `libbz2' to */
- /* partially uncompress the file on the fly (see src/bzip2/ftbzip2.c). */
- /* Contrary to gzip, bzip2 currently is not included and need to use */
- /* the system available bzip2 implementation. */
- /* */
- /* Define this macro if you want to enable this `feature'. */
- /* */
- /* If you use a build system like cmake or the `configure' script, */
- /* options set by those programs have precendence, overwriting the */
- /* value here with the configured one. */
- /* */
+ /**************************************************************************
+ *
+ * Bzip2-compressed file support.
+ *
+ * FreeType now handles font files that have been compressed with the
+ * `bzip2` program. This is mostly used to parse many of the PCF files
+ * that come with XFree86. The implementation uses `libbz2` to partially
+ * uncompress the file on the fly (see `src/bzip2/ftbzip2.c`). Contrary
+ * to gzip, bzip2 currently is not included and need to use the system
+ * available bzip2 implementation.
+ *
+ * Define this macro if you want to enable this 'feature'.
+ *
+ * If you use a build system like cmake or the `configure` script,
+ * options set by those programs have precedence, overwriting the value
+ * here with the configured one.
+ */
/* #define FT_CONFIG_OPTION_USE_BZIP2 */
- /*************************************************************************/
- /* */
- /* Define to disable the use of file stream functions and types, FILE, */
- /* fopen() etc. Enables the use of smaller system libraries on embedded */
- /* systems that have multiple system libraries, some with or without */
- /* file stream support, in the cases where file stream support is not */
- /* necessary such as memory loading of font files. */
- /* */
+ /**************************************************************************
+ *
+ * Define to disable the use of file stream functions and types, `FILE`,
+ * `fopen`, etc. Enables the use of smaller system libraries on embedded
+ * systems that have multiple system libraries, some with or without file
+ * stream support, in the cases where file stream support is not necessary
+ * such as memory loading of font files.
+ */
/* #define FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT */
- /*************************************************************************/
- /* */
- /* PNG bitmap support. */
- /* */
- /* FreeType now handles loading color bitmap glyphs in the PNG format. */
- /* This requires help from the external libpng library. Uncompressed */
- /* color bitmaps do not need any external libraries and will be */
- /* supported regardless of this configuration. */
- /* */
- /* Define this macro if you want to enable this `feature'. */
- /* */
- /* If you use a build system like cmake or the `configure' script, */
- /* options set by those programs have precendence, overwriting the */
- /* value here with the configured one. */
- /* */
+ /**************************************************************************
+ *
+ * PNG bitmap support.
+ *
+ * FreeType now handles loading color bitmap glyphs in the PNG format.
+ * This requires help from the external libpng library. Uncompressed
+ * color bitmaps do not need any external libraries and will be supported
+ * regardless of this configuration.
+ *
+ * Define this macro if you want to enable this 'feature'.
+ *
+ * If you use a build system like cmake or the `configure` script,
+ * options set by those programs have precedence, overwriting the value
+ * here with the configured one.
+ */
/* #define FT_CONFIG_OPTION_USE_PNG */
- /*************************************************************************/
- /* */
- /* HarfBuzz support. */
- /* */
- /* FreeType uses the HarfBuzz library to improve auto-hinting of */
- /* OpenType fonts. If available, many glyphs not directly addressable */
- /* by a font's character map will be hinted also. */
- /* */
- /* Define this macro if you want to enable this `feature'. */
- /* */
- /* If you use a build system like cmake or the `configure' script, */
- /* options set by those programs have precendence, overwriting the */
- /* value here with the configured one. */
- /* */
+ /**************************************************************************
+ *
+ * HarfBuzz support.
+ *
+ * FreeType uses the HarfBuzz library to improve auto-hinting of OpenType
+ * fonts. If available, many glyphs not directly addressable by a font's
+ * character map will be hinted also.
+ *
+ * Define this macro if you want to enable this 'feature'.
+ *
+ * If you use a build system like cmake or the `configure` script,
+ * options set by those programs have precedence, overwriting the value
+ * here with the configured one.
+ */
/* #define FT_CONFIG_OPTION_USE_HARFBUZZ */
- /*************************************************************************/
- /* */
- /* Glyph Postscript Names handling */
- /* */
- /* By default, FreeType 2 is compiled with the `psnames' module. This */
- /* module is in charge of converting a glyph name string into a */
- /* Unicode value, or return a Macintosh standard glyph name for the */
- /* use with the TrueType `post' table. */
- /* */
- /* Undefine this macro if you do not want `psnames' compiled in your */
- /* build of FreeType. This has the following effects: */
- /* */
- /* - The TrueType driver will provide its own set of glyph names, */
- /* if you build it to support postscript names in the TrueType */
- /* `post' table, but will not synthesize a missing Unicode charmap. */
- /* */
- /* - The Type 1 driver will not be able to synthesize a Unicode */
- /* charmap out of the glyphs found in the fonts. */
- /* */
- /* You would normally undefine this configuration macro when building */
- /* a version of FreeType that doesn't contain a Type 1 or CFF driver. */
- /* */
+ /**************************************************************************
+ *
+ * Glyph Postscript Names handling
+ *
+ * By default, FreeType 2 is compiled with the 'psnames' module. This
+ * module is in charge of converting a glyph name string into a Unicode
+ * value, or return a Macintosh standard glyph name for the use with the
+ * TrueType 'post' table.
+ *
+ * Undefine this macro if you do not want 'psnames' compiled in your
+ * build of FreeType. This has the following effects:
+ *
+ * - The TrueType driver will provide its own set of glyph names, if you
+ * build it to support postscript names in the TrueType 'post' table,
+ * but will not synthesize a missing Unicode charmap.
+ *
+ * - The Type~1 driver will not be able to synthesize a Unicode charmap
+ * out of the glyphs found in the fonts.
+ *
+ * You would normally undefine this configuration macro when building a
+ * version of FreeType that doesn't contain a Type~1 or CFF driver.
+ */
#define FT_CONFIG_OPTION_POSTSCRIPT_NAMES
- /*************************************************************************/
- /* */
- /* Postscript Names to Unicode Values support */
- /* */
- /* By default, FreeType 2 is built with the `PSNames' module compiled */
- /* in. Among other things, the module is used to convert a glyph name */
- /* into a Unicode value. This is especially useful in order to */
- /* synthesize on the fly a Unicode charmap from the CFF/Type 1 driver */
- /* through a big table named the `Adobe Glyph List' (AGL). */
- /* */
- /* Undefine this macro if you do not want the Adobe Glyph List */
- /* compiled in your `PSNames' module. The Type 1 driver will not be */
- /* able to synthesize a Unicode charmap out of the glyphs found in the */
- /* fonts. */
- /* */
+ /**************************************************************************
+ *
+ * Postscript Names to Unicode Values support
+ *
+ * By default, FreeType~2 is built with the 'psnames' module compiled in.
+ * Among other things, the module is used to convert a glyph name into a
+ * Unicode value. This is especially useful in order to synthesize on
+ * the fly a Unicode charmap from the CFF/Type~1 driver through a big
+ * table named the 'Adobe Glyph List' (AGL).
+ *
+ * Undefine this macro if you do not want the Adobe Glyph List compiled
+ * in your 'psnames' module. The Type~1 driver will not be able to
+ * synthesize a Unicode charmap out of the glyphs found in the fonts.
+ */
#define FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
- /*************************************************************************/
- /* */
- /* Support for Mac fonts */
- /* */
- /* Define this macro if you want support for outline fonts in Mac */
- /* format (mac dfont, mac resource, macbinary containing a mac */
- /* resource) on non-Mac platforms. */
- /* */
- /* Note that the `FOND' resource isn't checked. */
- /* */
+ /**************************************************************************
+ *
+ * Support for Mac fonts
+ *
+ * Define this macro if you want support for outline fonts in Mac format
+ * (mac dfont, mac resource, macbinary containing a mac resource) on
+ * non-Mac platforms.
+ *
+ * Note that the 'FOND' resource isn't checked.
+ */
#define FT_CONFIG_OPTION_MAC_FONTS
- /*************************************************************************/
- /* */
- /* Guessing methods to access embedded resource forks */
- /* */
- /* Enable extra Mac fonts support on non-Mac platforms (e.g. */
- /* GNU/Linux). */
- /* */
- /* Resource forks which include fonts data are stored sometimes in */
- /* locations which users or developers don't expected. In some cases, */
- /* resource forks start with some offset from the head of a file. In */
- /* other cases, the actual resource fork is stored in file different */
- /* from what the user specifies. If this option is activated, */
- /* FreeType tries to guess whether such offsets or different file */
- /* names must be used. */
- /* */
- /* Note that normal, direct access of resource forks is controlled via */
- /* the FT_CONFIG_OPTION_MAC_FONTS option. */
- /* */
+ /**************************************************************************
+ *
+ * Guessing methods to access embedded resource forks
+ *
+ * Enable extra Mac fonts support on non-Mac platforms (e.g., GNU/Linux).
+ *
+ * Resource forks which include fonts data are stored sometimes in
+ * locations which users or developers don't expected. In some cases,
+ * resource forks start with some offset from the head of a file. In
+ * other cases, the actual resource fork is stored in file different from
+ * what the user specifies. If this option is activated, FreeType tries
+ * to guess whether such offsets or different file names must be used.
+ *
+ * Note that normal, direct access of resource forks is controlled via
+ * the `FT_CONFIG_OPTION_MAC_FONTS` option.
+ */
#ifdef FT_CONFIG_OPTION_MAC_FONTS
#define FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK
#endif
- /*************************************************************************/
- /* */
- /* Allow the use of FT_Incremental_Interface to load typefaces that */
- /* contain no glyph data, but supply it via a callback function. */
- /* This is required by clients supporting document formats which */
- /* supply font data incrementally as the document is parsed, such */
- /* as the Ghostscript interpreter for the PostScript language. */
- /* */
+ /**************************************************************************
+ *
+ * Allow the use of `FT_Incremental_Interface` to load typefaces that
+ * contain no glyph data, but supply it via a callback function. This is
+ * required by clients supporting document formats which supply font data
+ * incrementally as the document is parsed, such as the Ghostscript
+ * interpreter for the PostScript language.
+ */
#define FT_CONFIG_OPTION_INCREMENTAL
- /*************************************************************************/
- /* */
- /* The size in bytes of the render pool used by the scan-line converter */
- /* to do all of its work. */
- /* */
+ /**************************************************************************
+ *
+ * The size in bytes of the render pool used by the scan-line converter to
+ * do all of its work.
+ */
#define FT_RENDER_POOL_SIZE 16384L
- /*************************************************************************/
- /* */
- /* FT_MAX_MODULES */
- /* */
- /* The maximum number of modules that can be registered in a single */
- /* FreeType library object. 32 is the default. */
- /* */
+ /**************************************************************************
+ *
+ * FT_MAX_MODULES
+ *
+ * The maximum number of modules that can be registered in a single
+ * FreeType library object. 32~is the default.
+ */
#define FT_MAX_MODULES 32
- /*************************************************************************/
- /* */
- /* Debug level */
- /* */
- /* FreeType can be compiled in debug or trace mode. In debug mode, */
- /* errors are reported through the `ftdebug' component. In trace */
- /* mode, additional messages are sent to the standard output during */
- /* execution. */
- /* */
- /* Define FT_DEBUG_LEVEL_ERROR to build the library in debug mode. */
- /* Define FT_DEBUG_LEVEL_TRACE to build it in trace mode. */
- /* */
- /* Don't define any of these macros to compile in `release' mode! */
- /* */
- /* Do not #undef these macros here since the build system might define */
- /* them for certain configurations only. */
- /* */
+ /**************************************************************************
+ *
+ * Debug level
+ *
+ * FreeType can be compiled in debug or trace mode. In debug mode,
+ * errors are reported through the 'ftdebug' component. In trace mode,
+ * additional messages are sent to the standard output during execution.
+ *
+ * Define `FT_DEBUG_LEVEL_ERROR` to build the library in debug mode.
+ * Define `FT_DEBUG_LEVEL_TRACE` to build it in trace mode.
+ *
+ * Don't define any of these macros to compile in 'release' mode!
+ *
+ * Do not `#undef` these macros here since the build system might define
+ * them for certain configurations only.
+ */
/* #define FT_DEBUG_LEVEL_ERROR */
/* #define FT_DEBUG_LEVEL_TRACE */
- /*************************************************************************/
- /* */
- /* Autofitter debugging */
- /* */
- /* If FT_DEBUG_AUTOFIT is defined, FreeType provides some means to */
- /* control the autofitter behaviour for debugging purposes with global */
- /* boolean variables (consequently, you should *never* enable this */
- /* while compiling in `release' mode): */
- /* */
- /* _af_debug_disable_horz_hints */
- /* _af_debug_disable_vert_hints */
- /* _af_debug_disable_blue_hints */
- /* */
- /* Additionally, the following functions provide dumps of various */
- /* internal autofit structures to stdout (using `printf'): */
- /* */
- /* af_glyph_hints_dump_points */
- /* af_glyph_hints_dump_segments */
- /* af_glyph_hints_dump_edges */
- /* af_glyph_hints_get_num_segments */
- /* af_glyph_hints_get_segment_offset */
- /* */
- /* As an argument, they use another global variable: */
- /* */
- /* _af_debug_hints */
- /* */
- /* Please have a look at the `ftgrid' demo program to see how those */
- /* variables and macros should be used. */
- /* */
- /* Do not #undef these macros here since the build system might define */
- /* them for certain configurations only. */
- /* */
+ /**************************************************************************
+ *
+ * Autofitter debugging
+ *
+ * If `FT_DEBUG_AUTOFIT` is defined, FreeType provides some means to
+ * control the autofitter behaviour for debugging purposes with global
+ * boolean variables (consequently, you should **never** enable this
+ * while compiling in 'release' mode):
+ *
+ * ```
+ * _af_debug_disable_horz_hints
+ * _af_debug_disable_vert_hints
+ * _af_debug_disable_blue_hints
+ * ```
+ *
+ * Additionally, the following functions provide dumps of various
+ * internal autofit structures to stdout (using `printf`):
+ *
+ * ```
+ * af_glyph_hints_dump_points
+ * af_glyph_hints_dump_segments
+ * af_glyph_hints_dump_edges
+ * af_glyph_hints_get_num_segments
+ * af_glyph_hints_get_segment_offset
+ * ```
+ *
+ * As an argument, they use another global variable:
+ *
+ * ```
+ * _af_debug_hints
+ * ```
+ *
+ * Please have a look at the `ftgrid` demo program to see how those
+ * variables and macros should be used.
+ *
+ * Do not `#undef` these macros here since the build system might define
+ * them for certain configurations only.
+ */
/* #define FT_DEBUG_AUTOFIT */
- /*************************************************************************/
- /* */
- /* Memory Debugging */
- /* */
- /* FreeType now comes with an integrated memory debugger that is */
- /* capable of detecting simple errors like memory leaks or double */
- /* deletes. To compile it within your build of the library, you */
- /* should define FT_DEBUG_MEMORY here. */
- /* */
- /* Note that the memory debugger is only activated at runtime when */
- /* when the _environment_ variable `FT2_DEBUG_MEMORY' is defined also! */
- /* */
- /* Do not #undef this macro here since the build system might define */
- /* it for certain configurations only. */
- /* */
+ /**************************************************************************
+ *
+ * Memory Debugging
+ *
+ * FreeType now comes with an integrated memory debugger that is capable
+ * of detecting simple errors like memory leaks or double deletes. To
+ * compile it within your build of the library, you should define
+ * `FT_DEBUG_MEMORY` here.
+ *
+ * Note that the memory debugger is only activated at runtime when when
+ * the _environment_ variable `FT2_DEBUG_MEMORY` is defined also!
+ *
+ * Do not `#undef` this macro here since the build system might define it
+ * for certain configurations only.
+ */
/* #define FT_DEBUG_MEMORY */
- /*************************************************************************/
- /* */
- /* Module errors */
- /* */
- /* If this macro is set (which is _not_ the default), the higher byte */
- /* of an error code gives the module in which the error has occurred, */
- /* while the lower byte is the real error code. */
- /* */
- /* Setting this macro makes sense for debugging purposes only, since */
- /* it would break source compatibility of certain programs that use */
- /* FreeType 2. */
- /* */
- /* More details can be found in the files ftmoderr.h and fterrors.h. */
- /* */
+ /**************************************************************************
+ *
+ * Module errors
+ *
+ * If this macro is set (which is _not_ the default), the higher byte of
+ * an error code gives the module in which the error has occurred, while
+ * the lower byte is the real error code.
+ *
+ * Setting this macro makes sense for debugging purposes only, since it
+ * would break source compatibility of certain programs that use
+ * FreeType~2.
+ *
+ * More details can be found in the files `ftmoderr.h` and `fterrors.h`.
+ */
#undef FT_CONFIG_OPTION_USE_MODULE_ERRORS
- /*************************************************************************/
- /* */
- /* Position Independent Code */
- /* */
- /* If this macro is set (which is _not_ the default), FreeType2 will */
- /* avoid creating constants that require address fixups. Instead the */
- /* constants will be moved into a struct and additional intialization */
- /* code will be used. */
- /* */
- /* Setting this macro is needed for systems that prohibit address */
- /* fixups, such as BREW. [Note that standard compilers like gcc or */
- /* clang handle PIC generation automatically; you don't have to set */
- /* FT_CONFIG_OPTION_PIC, which is only necessary for very special */
- /* compilers.] */
- /* */
- /* Note that FT_CONFIG_OPTION_PIC support is not available for all */
- /* modules (see `modules.cfg' for a complete list). For building with */
- /* FT_CONFIG_OPTION_PIC support, do the following. */
- /* */
- /* 0. Clone the repository. */
- /* 1. Define FT_CONFIG_OPTION_PIC. */
- /* 2. Remove all subdirectories in `src' that don't have */
- /* FT_CONFIG_OPTION_PIC support. */
- /* 3. Comment out the corresponding modules in `modules.cfg'. */
- /* 4. Compile. */
- /* */
-/* #define FT_CONFIG_OPTION_PIC */
+ /**************************************************************************
+ *
+ * Error Strings
+ *
+ * If this macro is set, `FT_Error_String` will return meaningful
+ * descriptions. This is not enabled by default to reduce the overall
+ * size of FreeType.
+ *
+ * More details can be found in the file `fterrors.h`.
+ */
+/* #define FT_CONFIG_OPTION_ERROR_STRINGS */
/*************************************************************************/
@@ -524,50 +515,60 @@ FT_BEGIN_HEADER
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* Define TT_CONFIG_OPTION_EMBEDDED_BITMAPS if you want to support */
- /* embedded bitmaps in all formats using the SFNT module (namely */
- /* TrueType & OpenType). */
- /* */
+ /**************************************************************************
+ *
+ * Define `TT_CONFIG_OPTION_EMBEDDED_BITMAPS` if you want to support
+ * embedded bitmaps in all formats using the 'sfnt' module (namely
+ * TrueType~& OpenType).
+ */
#define TT_CONFIG_OPTION_EMBEDDED_BITMAPS
- /*************************************************************************/
- /* */
- /* Define TT_CONFIG_OPTION_POSTSCRIPT_NAMES if you want to be able to */
- /* load and enumerate the glyph Postscript names in a TrueType or */
- /* OpenType file. */
- /* */
- /* Note that when you do not compile the `PSNames' module by undefining */
- /* the above FT_CONFIG_OPTION_POSTSCRIPT_NAMES, the `sfnt' module will */
- /* contain additional code used to read the PS Names table from a font. */
- /* */
- /* (By default, the module uses `PSNames' to extract glyph names.) */
- /* */
+ /**************************************************************************
+ *
+ * Define `TT_CONFIG_OPTION_COLOR_LAYERS` if you want to support coloured
+ * outlines (from the 'COLR'/'CPAL' tables) in all formats using the 'sfnt'
+ * module (namely TrueType~& OpenType).
+ */
+#define TT_CONFIG_OPTION_COLOR_LAYERS
+
+
+ /**************************************************************************
+ *
+ * Define `TT_CONFIG_OPTION_POSTSCRIPT_NAMES` if you want to be able to
+ * load and enumerate the glyph Postscript names in a TrueType or OpenType
+ * file.
+ *
+ * Note that when you do not compile the 'psnames' module by undefining the
+ * above `FT_CONFIG_OPTION_POSTSCRIPT_NAMES`, the 'sfnt' module will
+ * contain additional code used to read the PS Names table from a font.
+ *
+ * (By default, the module uses 'psnames' to extract glyph names.)
+ */
#define TT_CONFIG_OPTION_POSTSCRIPT_NAMES
- /*************************************************************************/
- /* */
- /* Define TT_CONFIG_OPTION_SFNT_NAMES if your applications need to */
- /* access the internal name table in a SFNT-based format like TrueType */
- /* or OpenType. The name table contains various strings used to */
- /* describe the font, like family name, copyright, version, etc. It */
- /* does not contain any glyph name though. */
- /* */
- /* Accessing SFNT names is done through the functions declared in */
- /* `ftsnames.h'. */
- /* */
+ /**************************************************************************
+ *
+ * Define `TT_CONFIG_OPTION_SFNT_NAMES` if your applications need to access
+ * the internal name table in a SFNT-based format like TrueType or
+ * OpenType. The name table contains various strings used to describe the
+ * font, like family name, copyright, version, etc. It does not contain
+ * any glyph name though.
+ *
+ * Accessing SFNT names is done through the functions declared in
+ * `ftsnames.h`.
+ */
#define TT_CONFIG_OPTION_SFNT_NAMES
- /*************************************************************************/
- /* */
- /* TrueType CMap support */
- /* */
- /* Here you can fine-tune which TrueType CMap table format shall be */
- /* supported. */
+ /**************************************************************************
+ *
+ * TrueType CMap support
+ *
+ * Here you can fine-tune which TrueType CMap table format shall be
+ * supported.
+ */
#define TT_CONFIG_CMAP_FORMAT_0
#define TT_CONFIG_CMAP_FORMAT_2
#define TT_CONFIG_CMAP_FORMAT_4
@@ -587,131 +588,130 @@ FT_BEGIN_HEADER
/*************************************************************************/
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* Define TT_CONFIG_OPTION_BYTECODE_INTERPRETER if you want to compile */
- /* a bytecode interpreter in the TrueType driver. */
- /* */
- /* By undefining this, you will only compile the code necessary to load */
- /* TrueType glyphs without hinting. */
- /* */
- /* Do not #undef this macro here, since the build system might */
- /* define it for certain configurations only. */
- /* */
+ /**************************************************************************
+ *
+ * Define `TT_CONFIG_OPTION_BYTECODE_INTERPRETER` if you want to compile a
+ * bytecode interpreter in the TrueType driver.
+ *
+ * By undefining this, you will only compile the code necessary to load
+ * TrueType glyphs without hinting.
+ *
+ * Do not `#undef` this macro here, since the build system might define it
+ * for certain configurations only.
+ */
#define TT_CONFIG_OPTION_BYTECODE_INTERPRETER
- /*************************************************************************/
- /* */
- /* Define TT_CONFIG_OPTION_SUBPIXEL_HINTING if you want to compile */
- /* subpixel hinting support into the TrueType driver. This modifies the */
- /* TrueType hinting mechanism when anything but FT_RENDER_MODE_MONO is */
- /* requested. */
- /* */
- /* In particular, it modifies the bytecode interpreter to interpret (or */
- /* not) instructions in a certain way so that all TrueType fonts look */
- /* like they do in a Windows ClearType (DirectWrite) environment. See */
- /* [1] for a technical overview on what this means. See `ttinterp.h' */
- /* for more details on the LEAN option. */
- /* */
- /* There are three possible values. */
- /* */
- /* Value 1: */
- /* This value is associated with the `Infinality' moniker, */
- /* contributed by an individual nicknamed Infinality with the goal of */
- /* making TrueType fonts render better than on Windows. A high */
- /* amount of configurability and flexibility, down to rules for */
- /* single glyphs in fonts, but also very slow. Its experimental and */
- /* slow nature and the original developer losing interest meant that */
- /* this option was never enabled in default builds. */
- /* */
- /* The corresponding interpreter version is v38. */
- /* */
- /* Value 2: */
- /* The new default mode for the TrueType driver. The Infinality code */
- /* base was stripped to the bare minimum and all configurability */
- /* removed in the name of speed and simplicity. The configurability */
- /* was mainly aimed at legacy fonts like Arial, Times New Roman, or */
- /* Courier. Legacy fonts are fonts that modify vertical stems to */
- /* achieve clean black-and-white bitmaps. The new mode focuses on */
- /* applying a minimal set of rules to all fonts indiscriminately so */
- /* that modern and web fonts render well while legacy fonts render */
- /* okay. */
- /* */
- /* The corresponding interpreter version is v40. */
- /* */
- /* Value 3: */
- /* Compile both, making both v38 and v40 available (the latter is the */
- /* default). */
- /* */
- /* By undefining these, you get rendering behavior like on Windows */
- /* without ClearType, i.e., Windows XP without ClearType enabled and */
- /* Win9x (interpreter version v35). Or not, depending on how much */
- /* hinting blood and testing tears the font designer put into a given */
- /* font. If you define one or both subpixel hinting options, you can */
- /* switch between between v35 and the ones you define (using */
- /* `FT_Property_Set'). */
- /* */
- /* This option requires TT_CONFIG_OPTION_BYTECODE_INTERPRETER to be */
- /* defined. */
- /* */
- /* [1] https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx */
- /* */
+ /**************************************************************************
+ *
+ * Define `TT_CONFIG_OPTION_SUBPIXEL_HINTING` if you want to compile
+ * subpixel hinting support into the TrueType driver. This modifies the
+ * TrueType hinting mechanism when anything but `FT_RENDER_MODE_MONO` is
+ * requested.
+ *
+ * In particular, it modifies the bytecode interpreter to interpret (or
+ * not) instructions in a certain way so that all TrueType fonts look like
+ * they do in a Windows ClearType (DirectWrite) environment. See [1] for a
+ * technical overview on what this means. See `ttinterp.h` for more
+ * details on the LEAN option.
+ *
+ * There are three possible values.
+ *
+ * Value 1:
+ * This value is associated with the 'Infinality' moniker, contributed by
+ * an individual nicknamed Infinality with the goal of making TrueType
+ * fonts render better than on Windows. A high amount of configurability
+ * and flexibility, down to rules for single glyphs in fonts, but also
+ * very slow. Its experimental and slow nature and the original
+ * developer losing interest meant that this option was never enabled in
+ * default builds.
+ *
+ * The corresponding interpreter version is v38.
+ *
+ * Value 2:
+ * The new default mode for the TrueType driver. The Infinality code
+ * base was stripped to the bare minimum and all configurability removed
+ * in the name of speed and simplicity. The configurability was mainly
+ * aimed at legacy fonts like 'Arial', 'Times New Roman', or 'Courier'.
+ * Legacy fonts are fonts that modify vertical stems to achieve clean
+ * black-and-white bitmaps. The new mode focuses on applying a minimal
+ * set of rules to all fonts indiscriminately so that modern and web
+ * fonts render well while legacy fonts render okay.
+ *
+ * The corresponding interpreter version is v40.
+ *
+ * Value 3:
+ * Compile both, making both v38 and v40 available (the latter is the
+ * default).
+ *
+ * By undefining these, you get rendering behavior like on Windows without
+ * ClearType, i.e., Windows XP without ClearType enabled and Win9x
+ * (interpreter version v35). Or not, depending on how much hinting blood
+ * and testing tears the font designer put into a given font. If you
+ * define one or both subpixel hinting options, you can switch between
+ * between v35 and the ones you define (using `FT_Property_Set`).
+ *
+ * This option requires `TT_CONFIG_OPTION_BYTECODE_INTERPRETER` to be
+ * defined.
+ *
+ * [1]
+ * https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx
+ */
/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING 1 */
#define TT_CONFIG_OPTION_SUBPIXEL_HINTING 2
/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING ( 1 | 2 ) */
- /*************************************************************************/
- /* */
- /* Define TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED to compile the */
- /* TrueType glyph loader to use Apple's definition of how to handle */
- /* component offsets in composite glyphs. */
- /* */
- /* Apple and MS disagree on the default behavior of component offsets */
- /* in composites. Apple says that they should be scaled by the scaling */
- /* factors in the transformation matrix (roughly, it's more complex) */
- /* while MS says they should not. OpenType defines two bits in the */
- /* composite flags array which can be used to disambiguate, but old */
- /* fonts will not have them. */
- /* */
- /* https://www.microsoft.com/typography/otspec/glyf.htm */
- /* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6glyf.html */
- /* */
+ /**************************************************************************
+ *
+ * Define `TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED` to compile the
+ * TrueType glyph loader to use Apple's definition of how to handle
+ * component offsets in composite glyphs.
+ *
+ * Apple and MS disagree on the default behavior of component offsets in
+ * composites. Apple says that they should be scaled by the scaling
+ * factors in the transformation matrix (roughly, it's more complex) while
+ * MS says they should not. OpenType defines two bits in the composite
+ * flags array which can be used to disambiguate, but old fonts will not
+ * have them.
+ *
+ * https://www.microsoft.com/typography/otspec/glyf.htm
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6glyf.html
+ */
#undef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED
- /*************************************************************************/
- /* */
- /* Define TT_CONFIG_OPTION_GX_VAR_SUPPORT if you want to include */
- /* support for Apple's distortable font technology (fvar, gvar, cvar, */
- /* and avar tables). This has many similarities to Type 1 Multiple */
- /* Masters support. */
- /* */
+ /**************************************************************************
+ *
+ * Define `TT_CONFIG_OPTION_GX_VAR_SUPPORT` if you want to include support
+ * for Apple's distortable font technology ('fvar', 'gvar', 'cvar', and
+ * 'avar' tables). Tagged 'Font Variations', this is now part of OpenType
+ * also. This has many similarities to Type~1 Multiple Masters support.
+ */
#define TT_CONFIG_OPTION_GX_VAR_SUPPORT
- /*************************************************************************/
- /* */
- /* Define TT_CONFIG_OPTION_BDF if you want to include support for */
- /* an embedded `BDF ' table within SFNT-based bitmap formats. */
- /* */
+ /**************************************************************************
+ *
+ * Define `TT_CONFIG_OPTION_BDF` if you want to include support for an
+ * embedded 'BDF~' table within SFNT-based bitmap formats.
+ */
#define TT_CONFIG_OPTION_BDF
- /*************************************************************************/
- /* */
- /* Option TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES controls the maximum */
- /* number of bytecode instructions executed for a single run of the */
- /* bytecode interpreter, needed to prevent infinite loops. You don't */
- /* want to change this except for very special situations (e.g., making */
- /* a library fuzzer spend less time to handle broken fonts). */
- /* */
- /* It is not expected that this value is ever modified by a configuring */
- /* script; instead, it gets surrounded with #ifndef ... #endif so that */
- /* the value can be set as a preprocessor option on the compiler's */
- /* command line. */
- /* */
+ /**************************************************************************
+ *
+ * Option `TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES` controls the maximum
+ * number of bytecode instructions executed for a single run of the
+ * bytecode interpreter, needed to prevent infinite loops. You don't want
+ * to change this except for very special situations (e.g., making a
+ * library fuzzer spend less time to handle broken fonts).
+ *
+ * It is not expected that this value is ever modified by a configuring
+ * script; instead, it gets surrounded with `#ifndef ... #endif` so that
+ * the value can be set as a preprocessor option on the compiler's command
+ * line.
+ */
#ifndef TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES
#define TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES 1000000L
#endif
@@ -726,59 +726,58 @@ FT_BEGIN_HEADER
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* T1_MAX_DICT_DEPTH is the maximum depth of nest dictionaries and */
- /* arrays in the Type 1 stream (see t1load.c). A minimum of 4 is */
- /* required. */
- /* */
+ /**************************************************************************
+ *
+ * `T1_MAX_DICT_DEPTH` is the maximum depth of nest dictionaries and arrays
+ * in the Type~1 stream (see `t1load.c`). A minimum of~4 is required.
+ */
#define T1_MAX_DICT_DEPTH 5
- /*************************************************************************/
- /* */
- /* T1_MAX_SUBRS_CALLS details the maximum number of nested sub-routine */
- /* calls during glyph loading. */
- /* */
+ /**************************************************************************
+ *
+ * `T1_MAX_SUBRS_CALLS` details the maximum number of nested sub-routine
+ * calls during glyph loading.
+ */
#define T1_MAX_SUBRS_CALLS 16
- /*************************************************************************/
- /* */
- /* T1_MAX_CHARSTRING_OPERANDS is the charstring stack's capacity. A */
- /* minimum of 16 is required. */
- /* */
- /* The Chinese font MingTiEG-Medium (CNS 11643 character set) needs 256. */
- /* */
+ /**************************************************************************
+ *
+ * `T1_MAX_CHARSTRING_OPERANDS` is the charstring stack's capacity. A
+ * minimum of~16 is required.
+ *
+ * The Chinese font 'MingTiEG-Medium' (covering the CNS 11643 character
+ * set) needs 256.
+ */
#define T1_MAX_CHARSTRINGS_OPERANDS 256
- /*************************************************************************/
- /* */
- /* Define this configuration macro if you want to prevent the */
- /* compilation of `t1afm', which is in charge of reading Type 1 AFM */
- /* files into an existing face. Note that if set, the T1 driver will be */
- /* unable to produce kerning distances. */
- /* */
+ /**************************************************************************
+ *
+ * Define this configuration macro if you want to prevent the compilation
+ * of the 't1afm' module, which is in charge of reading Type~1 AFM files
+ * into an existing face. Note that if set, the Type~1 driver will be
+ * unable to produce kerning distances.
+ */
#undef T1_CONFIG_OPTION_NO_AFM
- /*************************************************************************/
- /* */
- /* Define this configuration macro if you want to prevent the */
- /* compilation of the Multiple Masters font support in the Type 1 */
- /* driver. */
- /* */
+ /**************************************************************************
+ *
+ * Define this configuration macro if you want to prevent the compilation
+ * of the Multiple Masters font support in the Type~1 driver.
+ */
#undef T1_CONFIG_OPTION_NO_MM_SUPPORT
- /*************************************************************************/
- /* */
- /* T1_CONFIG_OPTION_OLD_ENGINE controls whether the pre-Adobe Type 1 */
- /* engine gets compiled into FreeType. If defined, it is possible to */
- /* switch between the two engines using the `hinting-engine' property of */
- /* the type1 driver module. */
- /* */
+ /**************************************************************************
+ *
+ * `T1_CONFIG_OPTION_OLD_ENGINE` controls whether the pre-Adobe Type~1
+ * engine gets compiled into FreeType. If defined, it is possible to
+ * switch between the two engines using the `hinting-engine` property of
+ * the 'type1' driver module.
+ */
/* #define T1_CONFIG_OPTION_OLD_ENGINE */
@@ -791,17 +790,16 @@ FT_BEGIN_HEADER
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* Using CFF_CONFIG_OPTION_DARKENING_PARAMETER_{X,Y}{1,2,3,4} it is */
- /* possible to set up the default values of the four control points that */
- /* define the stem darkening behaviour of the (new) CFF engine. For */
- /* more details please read the documentation of the */
- /* `darkening-parameters' property (file `ftdriver.h'), which allows the */
- /* control at run-time. */
- /* */
- /* Do *not* undefine these macros! */
- /* */
+ /**************************************************************************
+ *
+ * Using `CFF_CONFIG_OPTION_DARKENING_PARAMETER_{X,Y}{1,2,3,4}` it is
+ * possible to set up the default values of the four control points that
+ * define the stem darkening behaviour of the (new) CFF engine. For more
+ * details please read the documentation of the `darkening-parameters`
+ * property (file `ftdriver.h`), which allows the control at run-time.
+ *
+ * Do **not** undefine these macros!
+ */
#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1 500
#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1 400
@@ -815,13 +813,13 @@ FT_BEGIN_HEADER
#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4 0
- /*************************************************************************/
- /* */
- /* CFF_CONFIG_OPTION_OLD_ENGINE controls whether the pre-Adobe CFF */
- /* engine gets compiled into FreeType. If defined, it is possible to */
- /* switch between the two engines using the `hinting-engine' property of */
- /* the cff driver module. */
- /* */
+ /**************************************************************************
+ *
+ * `CFF_CONFIG_OPTION_OLD_ENGINE` controls whether the pre-Adobe CFF engine
+ * gets compiled into FreeType. If defined, it is possible to switch
+ * between the two engines using the `hinting-engine` property of the 'cff'
+ * driver module.
+ */
/* #define CFF_CONFIG_OPTION_OLD_ENGINE */
@@ -834,21 +832,21 @@ FT_BEGIN_HEADER
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* There are many PCF fonts just called `Fixed' which look completely */
- /* different, and which have nothing to do with each other. When */
- /* selecting `Fixed' in KDE or Gnome one gets results that appear rather */
- /* random, the style changes often if one changes the size and one */
- /* cannot select some fonts at all. This option makes the PCF module */
- /* prepend the foundry name (plus a space) to the family name. */
- /* */
- /* We also check whether we have `wide' characters; all put together, we */
- /* get family names like `Sony Fixed' or `Misc Fixed Wide'. */
- /* */
- /* If this option is activated, it can be controlled with the */
- /* `no-long-family-names' property of the pcf driver module. */
- /* */
+ /**************************************************************************
+ *
+ * There are many PCF fonts just called 'Fixed' which look completely
+ * different, and which have nothing to do with each other. When selecting
+ * 'Fixed' in KDE or Gnome one gets results that appear rather random, the
+ * style changes often if one changes the size and one cannot select some
+ * fonts at all. This option makes the 'pcf' module prepend the foundry
+ * name (plus a space) to the family name.
+ *
+ * We also check whether we have 'wide' characters; all put together, we
+ * get family names like 'Sony Fixed' or 'Misc Fixed Wide'.
+ *
+ * If this option is activated, it can be controlled with the
+ * `no-long-family-names` property of the 'pcf' driver module.
+ */
/* #define PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */
@@ -861,69 +859,76 @@ FT_BEGIN_HEADER
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* Compile autofit module with CJK (Chinese, Japanese, Korean) script */
- /* support. */
- /* */
+ /**************************************************************************
+ *
+ * Compile 'autofit' module with CJK (Chinese, Japanese, Korean) script
+ * support.
+ */
#define AF_CONFIG_OPTION_CJK
- /*************************************************************************/
- /* */
- /* Compile autofit module with fallback Indic script support, covering */
- /* some scripts that the `latin' submodule of the autofit module doesn't */
- /* (yet) handle. */
- /* */
+
+ /**************************************************************************
+ *
+ * Compile 'autofit' module with fallback Indic script support, covering
+ * some scripts that the 'latin' submodule of the 'autofit' module doesn't
+ * (yet) handle.
+ */
#define AF_CONFIG_OPTION_INDIC
- /*************************************************************************/
- /* */
- /* Compile autofit module with warp hinting. The idea of the warping */
- /* code is to slightly scale and shift a glyph within a single dimension */
- /* so that as much of its segments are aligned (more or less) on the */
- /* grid. To find out the optimal scaling and shifting value, various */
- /* parameter combinations are tried and scored. */
- /* */
- /* This experimental option is active only if the rendering mode is */
- /* FT_RENDER_MODE_LIGHT; you can switch warping on and off with the */
- /* `warping' property of the auto-hinter (see file `ftdriver.h' for more */
- /* information; by default it is switched off). */
- /* */
+
+ /**************************************************************************
+ *
+ * Compile 'autofit' module with warp hinting. The idea of the warping
+ * code is to slightly scale and shift a glyph within a single dimension so
+ * that as much of its segments are aligned (more or less) on the grid. To
+ * find out the optimal scaling and shifting value, various parameter
+ * combinations are tried and scored.
+ *
+ * You can switch warping on and off with the `warping` property of the
+ * auto-hinter (see file `ftdriver.h` for more information; by default it
+ * is switched off).
+ *
+ * This experimental option is not active if the rendering mode is
+ * `FT_RENDER_MODE_LIGHT`.
+ */
#define AF_CONFIG_OPTION_USE_WARPER
- /*************************************************************************/
- /* */
- /* Use TrueType-like size metrics for `light' auto-hinting. */
- /* */
- /* It is strongly recommended to avoid this option, which exists only to */
- /* help some legacy applications retain its appearance and behaviour */
- /* with respect to auto-hinted TrueType fonts. */
- /* */
- /* The very reason this option exists at all are GNU/Linux distributions */
- /* like Fedora that did not un-patch the following change (which was */
- /* present in FreeType between versions 2.4.6 and 2.7.1, inclusive). */
- /* */
- /* 2011-07-16 Steven Chu <steven.f.chu@gmail.com> */
- /* */
- /* [truetype] Fix metrics on size request for scalable fonts. */
- /* */
- /* This problematic commit is now reverted (more or less). */
- /* */
+
+ /**************************************************************************
+ *
+ * Use TrueType-like size metrics for 'light' auto-hinting.
+ *
+ * It is strongly recommended to avoid this option, which exists only to
+ * help some legacy applications retain its appearance and behaviour with
+ * respect to auto-hinted TrueType fonts.
+ *
+ * The very reason this option exists at all are GNU/Linux distributions
+ * like Fedora that did not un-patch the following change (which was
+ * present in FreeType between versions 2.4.6 and 2.7.1, inclusive).
+ *
+ * ```
+ * 2011-07-16 Steven Chu <steven.f.chu@gmail.com>
+ *
+ * [truetype] Fix metrics on size request for scalable fonts.
+ * ```
+ *
+ * This problematic commit is now reverted (more or less).
+ */
/* #define AF_CONFIG_OPTION_TT_SIZE_METRICS */
/* */
/*
- * This macro is obsolete. Support has been removed in FreeType
- * version 2.5.
+ * This macro is obsolete. Support has been removed in FreeType version
+ * 2.5.
*/
/* #define FT_CONFIG_OPTION_OLD_INTERNALS */
/*
- * This macro is defined if native TrueType hinting is requested by the
- * definitions above.
+ * The next three macros are defined if native TrueType hinting is
+ * requested by the definitions above. Don't change this.
*/
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
#define TT_USE_BYTECODE_INTERPRETER
@@ -942,7 +947,7 @@ FT_BEGIN_HEADER
/*
* Check CFF darkening parameters. The checks are the same as in function
- * `cff_property_set' in file `cffdrivr.c'.
+ * `cff_property_set` in file `cffdrivr.c`.
*/
#if CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1 < 0 || \
CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2 < 0 || \
diff --git a/thirdparty/freetype/include/freetype/config/ftstdlib.h b/thirdparty/freetype/include/freetype/config/ftstdlib.h
index 42f9a06e43..438b6145d5 100644
--- a/thirdparty/freetype/include/freetype/config/ftstdlib.h
+++ b/thirdparty/freetype/include/freetype/config/ftstdlib.h
@@ -1,31 +1,31 @@
-/***************************************************************************/
-/* */
-/* ftstdlib.h */
-/* */
-/* ANSI-specific library and header configuration file (specification */
-/* only). */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* This file is used to group all #includes to the ANSI C library that */
- /* FreeType normally requires. It also defines macros to rename the */
- /* standard functions within the FreeType source code. */
- /* */
- /* Load a file which defines FTSTDLIB_H_ before this one to override it. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * ftstdlib.h
+ *
+ * ANSI-specific library and header configuration file (specification
+ * only).
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * This file is used to group all `#includes` to the ANSI~C library that
+ * FreeType normally requires. It also defines macros to rename the
+ * standard functions within the FreeType source code.
+ *
+ * Load a file which defines `FTSTDLIB_H_` before this one to override it.
+ *
+ */
#ifndef FTSTDLIB_H_
@@ -37,23 +37,23 @@
#define ft_ptrdiff_t ptrdiff_t
- /**********************************************************************/
- /* */
- /* integer limits */
- /* */
- /* UINT_MAX and ULONG_MAX are used to automatically compute the size */
- /* of `int' and `long' in bytes at compile-time. So far, this works */
- /* for all platforms the library has been tested on. */
- /* */
- /* Note that on the extremely rare platforms that do not provide */
- /* integer types that are _exactly_ 16 and 32 bits wide (e.g. some */
- /* old Crays where `int' is 36 bits), we do not make any guarantee */
- /* about the correct behaviour of FT2 with all fonts. */
- /* */
- /* In these case, `ftconfig.h' will refuse to compile anyway with a */
- /* message like `couldn't find 32-bit type' or something similar. */
- /* */
- /**********************************************************************/
+ /**************************************************************************
+ *
+ * integer limits
+ *
+ * `UINT_MAX` and `ULONG_MAX` are used to automatically compute the size of
+ * `int` and `long` in bytes at compile-time. So far, this works for all
+ * platforms the library has been tested on.
+ *
+ * Note that on the extremely rare platforms that do not provide integer
+ * types that are _exactly_ 16 and 32~bits wide (e.g., some old Crays where
+ * `int` is 36~bits), we do not make any guarantee about the correct
+ * behaviour of FreeType~2 with all fonts.
+ *
+ * In these cases, `ftconfig.h` will refuse to compile anyway with a
+ * message like 'couldn't find 32-bit type' or something similar.
+ *
+ */
#include <limits.h>
@@ -68,11 +68,11 @@
#define FT_ULONG_MAX ULONG_MAX
- /**********************************************************************/
- /* */
- /* character and string processing */
- /* */
- /**********************************************************************/
+ /**************************************************************************
+ *
+ * character and string processing
+ *
+ */
#include <string.h>
@@ -92,11 +92,11 @@
#define ft_strstr strstr
- /**********************************************************************/
- /* */
- /* file handling */
- /* */
- /**********************************************************************/
+ /**************************************************************************
+ *
+ * file handling
+ *
+ */
#include <stdio.h>
@@ -110,11 +110,11 @@
#define ft_sprintf sprintf
- /**********************************************************************/
- /* */
- /* sorting */
- /* */
- /**********************************************************************/
+ /**************************************************************************
+ *
+ * sorting
+ *
+ */
#include <stdlib.h>
@@ -122,11 +122,11 @@
#define ft_qsort qsort
- /**********************************************************************/
- /* */
- /* memory allocation */
- /* */
- /**********************************************************************/
+ /**************************************************************************
+ *
+ * memory allocation
+ *
+ */
#define ft_scalloc calloc
@@ -135,36 +135,36 @@
#define ft_srealloc realloc
- /**********************************************************************/
- /* */
- /* miscellaneous */
- /* */
- /**********************************************************************/
+ /**************************************************************************
+ *
+ * miscellaneous
+ *
+ */
#define ft_strtol strtol
#define ft_getenv getenv
- /**********************************************************************/
- /* */
- /* execution control */
- /* */
- /**********************************************************************/
+ /**************************************************************************
+ *
+ * execution control
+ *
+ */
#include <setjmp.h>
-#define ft_jmp_buf jmp_buf /* note: this cannot be a typedef since */
- /* jmp_buf is defined as a macro */
- /* on certain platforms */
+#define ft_jmp_buf jmp_buf /* note: this cannot be a typedef since */
+ /* `jmp_buf` is defined as a macro */
+ /* on certain platforms */
#define ft_longjmp longjmp
#define ft_setjmp( b ) setjmp( *(ft_jmp_buf*) &(b) ) /* same thing here */
- /* the following is only used for debugging purposes, i.e., if */
- /* FT_DEBUG_LEVEL_ERROR or FT_DEBUG_LEVEL_TRACE are defined */
+ /* The following is only used for debugging purposes, i.e., if */
+ /* `FT_DEBUG_LEVEL_ERROR` or `FT_DEBUG_LEVEL_TRACE` are defined. */
#include <stdarg.h>
diff --git a/thirdparty/freetype/include/freetype/freetype.h b/thirdparty/freetype/include/freetype/freetype.h
index 96644046e4..4f2eaca691 100644
--- a/thirdparty/freetype/include/freetype/freetype.h
+++ b/thirdparty/freetype/include/freetype/freetype.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* freetype.h */
-/* */
-/* FreeType high-level API and common types (specification only). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * freetype.h
+ *
+ * FreeType high-level API and common types (specification only).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FREETYPE_H_
@@ -39,56 +39,55 @@ FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* <Section> */
- /* header_inclusion */
- /* */
- /* <Title> */
- /* FreeType's header inclusion scheme */
- /* */
- /* <Abstract> */
- /* How client applications should include FreeType header files. */
- /* */
- /* <Description> */
- /* To be as flexible as possible (and for historical reasons), */
- /* FreeType uses a very special inclusion scheme to load header */
- /* files, for example */
- /* */
- /* { */
- /* #include <ft2build.h> */
- /* */
- /* #include FT_FREETYPE_H */
- /* #include FT_OUTLINE_H */
- /* } */
- /* */
- /* A compiler and its preprocessor only needs an include path to find */
- /* the file `ft2build.h'; the exact locations and names of the other */
- /* FreeType header files are hidden by preprocessor macro names, */
- /* loaded by `ft2build.h'. The API documentation always gives the */
- /* header macro name needed for a particular function. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * @section:
+ * header_inclusion
+ *
+ * @title:
+ * FreeType's header inclusion scheme
+ *
+ * @abstract:
+ * How client applications should include FreeType header files.
+ *
+ * @description:
+ * To be as flexible as possible (and for historical reasons), FreeType
+ * uses a very special inclusion scheme to load header files, for example
+ *
+ * ```
+ * #include <ft2build.h>
+ *
+ * #include FT_FREETYPE_H
+ * #include FT_OUTLINE_H
+ * ```
+ *
+ * A compiler and its preprocessor only needs an include path to find the
+ * file `ft2build.h`; the exact locations and names of the other FreeType
+ * header files are hidden by @header_file_macros, loaded by
+ * `ft2build.h`. The API documentation always gives the header macro
+ * name needed for a particular function.
+ *
+ */
- /*************************************************************************/
- /* */
- /* <Section> */
- /* user_allocation */
- /* */
- /* <Title> */
- /* User allocation */
- /* */
- /* <Abstract> */
- /* How client applications should allocate FreeType data structures. */
- /* */
- /* <Description> */
- /* FreeType assumes that structures allocated by the user and passed */
- /* as arguments are zeroed out except for the actual data. In other */
- /* words, it is recommended to use `calloc' (or variants of it) */
- /* instead of `malloc' for allocation. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * @section:
+ * user_allocation
+ *
+ * @title:
+ * User allocation
+ *
+ * @abstract:
+ * How client applications should allocate FreeType data structures.
+ *
+ * @description:
+ * FreeType assumes that structures allocated by the user and passed as
+ * arguments are zeroed out except for the actual data. In other words,
+ * it is recommended to use `calloc` (or variants of it) instead of
+ * `malloc` for allocation.
+ *
+ */
@@ -101,219 +100,219 @@ FT_BEGIN_HEADER
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* <Section> */
- /* base_interface */
- /* */
- /* <Title> */
- /* Base Interface */
- /* */
- /* <Abstract> */
- /* The FreeType~2 base font interface. */
- /* */
- /* <Description> */
- /* This section describes the most important public high-level API */
- /* functions of FreeType~2. */
- /* */
- /* <Order> */
- /* FT_Library */
- /* FT_Face */
- /* FT_Size */
- /* FT_GlyphSlot */
- /* FT_CharMap */
- /* FT_Encoding */
- /* FT_ENC_TAG */
- /* */
- /* FT_FaceRec */
- /* */
- /* FT_FACE_FLAG_SCALABLE */
- /* FT_FACE_FLAG_FIXED_SIZES */
- /* FT_FACE_FLAG_FIXED_WIDTH */
- /* FT_FACE_FLAG_HORIZONTAL */
- /* FT_FACE_FLAG_VERTICAL */
- /* FT_FACE_FLAG_COLOR */
- /* FT_FACE_FLAG_SFNT */
- /* FT_FACE_FLAG_CID_KEYED */
- /* FT_FACE_FLAG_TRICKY */
- /* FT_FACE_FLAG_KERNING */
- /* FT_FACE_FLAG_MULTIPLE_MASTERS */
- /* FT_FACE_FLAG_VARIATION */
- /* FT_FACE_FLAG_GLYPH_NAMES */
- /* FT_FACE_FLAG_EXTERNAL_STREAM */
- /* FT_FACE_FLAG_HINTER */
- /* */
- /* FT_HAS_HORIZONTAL */
- /* FT_HAS_VERTICAL */
- /* FT_HAS_KERNING */
- /* FT_HAS_FIXED_SIZES */
- /* FT_HAS_GLYPH_NAMES */
- /* FT_HAS_COLOR */
- /* FT_HAS_MULTIPLE_MASTERS */
- /* */
- /* FT_IS_SFNT */
- /* FT_IS_SCALABLE */
- /* FT_IS_FIXED_WIDTH */
- /* FT_IS_CID_KEYED */
- /* FT_IS_TRICKY */
- /* FT_IS_NAMED_INSTANCE */
- /* FT_IS_VARIATION */
- /* */
- /* FT_STYLE_FLAG_BOLD */
- /* FT_STYLE_FLAG_ITALIC */
- /* */
- /* FT_SizeRec */
- /* FT_Size_Metrics */
- /* */
- /* FT_GlyphSlotRec */
- /* FT_Glyph_Metrics */
- /* FT_SubGlyph */
- /* */
- /* FT_Bitmap_Size */
- /* */
- /* FT_Init_FreeType */
- /* FT_Done_FreeType */
- /* */
- /* FT_New_Face */
- /* FT_Done_Face */
- /* FT_Reference_Face */
- /* FT_New_Memory_Face */
- /* FT_Face_Properties */
- /* FT_Open_Face */
- /* FT_Open_Args */
- /* FT_Parameter */
- /* FT_Attach_File */
- /* FT_Attach_Stream */
- /* */
- /* FT_Set_Char_Size */
- /* FT_Set_Pixel_Sizes */
- /* FT_Request_Size */
- /* FT_Select_Size */
- /* FT_Size_Request_Type */
- /* FT_Size_RequestRec */
- /* FT_Size_Request */
- /* FT_Set_Transform */
- /* FT_Load_Glyph */
- /* FT_Get_Char_Index */
- /* FT_Get_First_Char */
- /* FT_Get_Next_Char */
- /* FT_Get_Name_Index */
- /* FT_Load_Char */
- /* */
- /* FT_OPEN_MEMORY */
- /* FT_OPEN_STREAM */
- /* FT_OPEN_PATHNAME */
- /* FT_OPEN_DRIVER */
- /* FT_OPEN_PARAMS */
- /* */
- /* FT_LOAD_DEFAULT */
- /* FT_LOAD_RENDER */
- /* FT_LOAD_MONOCHROME */
- /* FT_LOAD_LINEAR_DESIGN */
- /* FT_LOAD_NO_SCALE */
- /* FT_LOAD_NO_HINTING */
- /* FT_LOAD_NO_BITMAP */
- /* FT_LOAD_NO_AUTOHINT */
- /* FT_LOAD_COLOR */
- /* */
- /* FT_LOAD_VERTICAL_LAYOUT */
- /* FT_LOAD_IGNORE_TRANSFORM */
- /* FT_LOAD_FORCE_AUTOHINT */
- /* FT_LOAD_NO_RECURSE */
- /* FT_LOAD_PEDANTIC */
- /* */
- /* FT_LOAD_TARGET_NORMAL */
- /* FT_LOAD_TARGET_LIGHT */
- /* FT_LOAD_TARGET_MONO */
- /* FT_LOAD_TARGET_LCD */
- /* FT_LOAD_TARGET_LCD_V */
- /* */
- /* FT_LOAD_TARGET_MODE */
- /* */
- /* FT_Render_Glyph */
- /* FT_Render_Mode */
- /* FT_Get_Kerning */
- /* FT_Kerning_Mode */
- /* FT_Get_Track_Kerning */
- /* FT_Get_Glyph_Name */
- /* FT_Get_Postscript_Name */
- /* */
- /* FT_CharMapRec */
- /* FT_Select_Charmap */
- /* FT_Set_Charmap */
- /* FT_Get_Charmap_Index */
- /* */
- /* FT_Get_FSType_Flags */
- /* FT_Get_SubGlyph_Info */
- /* */
- /* FT_Face_Internal */
- /* FT_Size_Internal */
- /* FT_Slot_Internal */
- /* */
- /* FT_FACE_FLAG_XXX */
- /* FT_STYLE_FLAG_XXX */
- /* FT_OPEN_XXX */
- /* FT_LOAD_XXX */
- /* FT_LOAD_TARGET_XXX */
- /* FT_SUBGLYPH_FLAG_XXX */
- /* FT_FSTYPE_XXX */
- /* */
- /* FT_HAS_FAST_GLYPHS */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * @section:
+ * base_interface
+ *
+ * @title:
+ * Base Interface
+ *
+ * @abstract:
+ * The FreeType~2 base font interface.
+ *
+ * @description:
+ * This section describes the most important public high-level API
+ * functions of FreeType~2.
+ *
+ * @order:
+ * FT_Library
+ * FT_Face
+ * FT_Size
+ * FT_GlyphSlot
+ * FT_CharMap
+ * FT_Encoding
+ * FT_ENC_TAG
+ *
+ * FT_FaceRec
+ *
+ * FT_FACE_FLAG_SCALABLE
+ * FT_FACE_FLAG_FIXED_SIZES
+ * FT_FACE_FLAG_FIXED_WIDTH
+ * FT_FACE_FLAG_HORIZONTAL
+ * FT_FACE_FLAG_VERTICAL
+ * FT_FACE_FLAG_COLOR
+ * FT_FACE_FLAG_SFNT
+ * FT_FACE_FLAG_CID_KEYED
+ * FT_FACE_FLAG_TRICKY
+ * FT_FACE_FLAG_KERNING
+ * FT_FACE_FLAG_MULTIPLE_MASTERS
+ * FT_FACE_FLAG_VARIATION
+ * FT_FACE_FLAG_GLYPH_NAMES
+ * FT_FACE_FLAG_EXTERNAL_STREAM
+ * FT_FACE_FLAG_HINTER
+ *
+ * FT_HAS_HORIZONTAL
+ * FT_HAS_VERTICAL
+ * FT_HAS_KERNING
+ * FT_HAS_FIXED_SIZES
+ * FT_HAS_GLYPH_NAMES
+ * FT_HAS_COLOR
+ * FT_HAS_MULTIPLE_MASTERS
+ *
+ * FT_IS_SFNT
+ * FT_IS_SCALABLE
+ * FT_IS_FIXED_WIDTH
+ * FT_IS_CID_KEYED
+ * FT_IS_TRICKY
+ * FT_IS_NAMED_INSTANCE
+ * FT_IS_VARIATION
+ *
+ * FT_STYLE_FLAG_BOLD
+ * FT_STYLE_FLAG_ITALIC
+ *
+ * FT_SizeRec
+ * FT_Size_Metrics
+ *
+ * FT_GlyphSlotRec
+ * FT_Glyph_Metrics
+ * FT_SubGlyph
+ *
+ * FT_Bitmap_Size
+ *
+ * FT_Init_FreeType
+ * FT_Done_FreeType
+ *
+ * FT_New_Face
+ * FT_Done_Face
+ * FT_Reference_Face
+ * FT_New_Memory_Face
+ * FT_Face_Properties
+ * FT_Open_Face
+ * FT_Open_Args
+ * FT_Parameter
+ * FT_Attach_File
+ * FT_Attach_Stream
+ *
+ * FT_Set_Char_Size
+ * FT_Set_Pixel_Sizes
+ * FT_Request_Size
+ * FT_Select_Size
+ * FT_Size_Request_Type
+ * FT_Size_RequestRec
+ * FT_Size_Request
+ * FT_Set_Transform
+ * FT_Load_Glyph
+ * FT_Get_Char_Index
+ * FT_Get_First_Char
+ * FT_Get_Next_Char
+ * FT_Get_Name_Index
+ * FT_Load_Char
+ *
+ * FT_OPEN_MEMORY
+ * FT_OPEN_STREAM
+ * FT_OPEN_PATHNAME
+ * FT_OPEN_DRIVER
+ * FT_OPEN_PARAMS
+ *
+ * FT_LOAD_DEFAULT
+ * FT_LOAD_RENDER
+ * FT_LOAD_MONOCHROME
+ * FT_LOAD_LINEAR_DESIGN
+ * FT_LOAD_NO_SCALE
+ * FT_LOAD_NO_HINTING
+ * FT_LOAD_NO_BITMAP
+ * FT_LOAD_NO_AUTOHINT
+ * FT_LOAD_COLOR
+ *
+ * FT_LOAD_VERTICAL_LAYOUT
+ * FT_LOAD_IGNORE_TRANSFORM
+ * FT_LOAD_FORCE_AUTOHINT
+ * FT_LOAD_NO_RECURSE
+ * FT_LOAD_PEDANTIC
+ *
+ * FT_LOAD_TARGET_NORMAL
+ * FT_LOAD_TARGET_LIGHT
+ * FT_LOAD_TARGET_MONO
+ * FT_LOAD_TARGET_LCD
+ * FT_LOAD_TARGET_LCD_V
+ *
+ * FT_LOAD_TARGET_MODE
+ *
+ * FT_Render_Glyph
+ * FT_Render_Mode
+ * FT_Get_Kerning
+ * FT_Kerning_Mode
+ * FT_Get_Track_Kerning
+ * FT_Get_Glyph_Name
+ * FT_Get_Postscript_Name
+ *
+ * FT_CharMapRec
+ * FT_Select_Charmap
+ * FT_Set_Charmap
+ * FT_Get_Charmap_Index
+ *
+ * FT_Get_FSType_Flags
+ * FT_Get_SubGlyph_Info
+ *
+ * FT_Face_Internal
+ * FT_Size_Internal
+ * FT_Slot_Internal
+ *
+ * FT_FACE_FLAG_XXX
+ * FT_STYLE_FLAG_XXX
+ * FT_OPEN_XXX
+ * FT_LOAD_XXX
+ * FT_LOAD_TARGET_XXX
+ * FT_SUBGLYPH_FLAG_XXX
+ * FT_FSTYPE_XXX
+ *
+ * FT_HAS_FAST_GLYPHS
+ *
+ */
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_Glyph_Metrics */
- /* */
- /* <Description> */
- /* A structure to model the metrics of a single glyph. The values */
- /* are expressed in 26.6 fractional pixel format; if the flag */
- /* @FT_LOAD_NO_SCALE has been used while loading the glyph, values */
- /* are expressed in font units instead. */
- /* */
- /* <Fields> */
- /* width :: */
- /* The glyph's width. */
- /* */
- /* height :: */
- /* The glyph's height. */
- /* */
- /* horiBearingX :: */
- /* Left side bearing for horizontal layout. */
- /* */
- /* horiBearingY :: */
- /* Top side bearing for horizontal layout. */
- /* */
- /* horiAdvance :: */
- /* Advance width for horizontal layout. */
- /* */
- /* vertBearingX :: */
- /* Left side bearing for vertical layout. */
- /* */
- /* vertBearingY :: */
- /* Top side bearing for vertical layout. Larger positive values */
- /* mean further below the vertical glyph origin. */
- /* */
- /* vertAdvance :: */
- /* Advance height for vertical layout. Positive values mean the */
- /* glyph has a positive advance downward. */
- /* */
- /* <Note> */
- /* If not disabled with @FT_LOAD_NO_HINTING, the values represent */
- /* dimensions of the hinted glyph (in case hinting is applicable). */
- /* */
- /* Stroking a glyph with an outside border does not increase */
- /* `horiAdvance' or `vertAdvance'; you have to manually adjust these */
- /* values to account for the added width and height. */
- /* */
- /* FreeType doesn't use the `VORG' table data for CFF fonts because */
- /* it doesn't have an interface to quickly retrieve the glyph height. */
- /* The y~coordinate of the vertical origin can be simply computed as */
- /* `vertBearingY + height' after loading a glyph. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Glyph_Metrics
+ *
+ * @description:
+ * A structure to model the metrics of a single glyph. The values are
+ * expressed in 26.6 fractional pixel format; if the flag
+ * @FT_LOAD_NO_SCALE has been used while loading the glyph, values are
+ * expressed in font units instead.
+ *
+ * @fields:
+ * width ::
+ * The glyph's width.
+ *
+ * height ::
+ * The glyph's height.
+ *
+ * horiBearingX ::
+ * Left side bearing for horizontal layout.
+ *
+ * horiBearingY ::
+ * Top side bearing for horizontal layout.
+ *
+ * horiAdvance ::
+ * Advance width for horizontal layout.
+ *
+ * vertBearingX ::
+ * Left side bearing for vertical layout.
+ *
+ * vertBearingY ::
+ * Top side bearing for vertical layout. Larger positive values mean
+ * further below the vertical glyph origin.
+ *
+ * vertAdvance ::
+ * Advance height for vertical layout. Positive values mean the glyph
+ * has a positive advance downward.
+ *
+ * @note:
+ * If not disabled with @FT_LOAD_NO_HINTING, the values represent
+ * dimensions of the hinted glyph (in case hinting is applicable).
+ *
+ * Stroking a glyph with an outside border does not increase
+ * `horiAdvance` or `vertAdvance`; you have to manually adjust these
+ * values to account for the added width and height.
+ *
+ * FreeType doesn't use the 'VORG' table data for CFF fonts because it
+ * doesn't have an interface to quickly retrieve the glyph height. The
+ * y~coordinate of the vertical origin can be simply computed as
+ * `vertBearingY + height` after loading a glyph.
+ */
typedef struct FT_Glyph_Metrics_
{
FT_Pos width;
@@ -330,44 +329,45 @@ FT_BEGIN_HEADER
} FT_Glyph_Metrics;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_Bitmap_Size */
- /* */
- /* <Description> */
- /* This structure models the metrics of a bitmap strike (i.e., a set */
- /* of glyphs for a given point size and resolution) in a bitmap font. */
- /* It is used for the `available_sizes' field of @FT_Face. */
- /* */
- /* <Fields> */
- /* height :: The vertical distance, in pixels, between two */
- /* consecutive baselines. It is always positive. */
- /* */
- /* width :: The average width, in pixels, of all glyphs in the */
- /* strike. */
- /* */
- /* size :: The nominal size of the strike in 26.6 fractional */
- /* points. This field is not very useful. */
- /* */
- /* x_ppem :: The horizontal ppem (nominal width) in 26.6 fractional */
- /* pixels. */
- /* */
- /* y_ppem :: The vertical ppem (nominal height) in 26.6 fractional */
- /* pixels. */
- /* */
- /* <Note> */
- /* Windows FNT: */
- /* The nominal size given in a FNT font is not reliable. If the */
- /* driver finds it incorrect, it sets `size' to some calculated */
- /* values, and `x_ppem' and `y_ppem' to the pixel width and height */
- /* given in the font, respectively. */
- /* */
- /* TrueType embedded bitmaps: */
- /* `size', `width', and `height' values are not contained in the */
- /* bitmap strike itself. They are computed from the global font */
- /* parameters. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Bitmap_Size
+ *
+ * @description:
+ * This structure models the metrics of a bitmap strike (i.e., a set of
+ * glyphs for a given point size and resolution) in a bitmap font. It is
+ * used for the `available_sizes` field of @FT_Face.
+ *
+ * @fields:
+ * height ::
+ * The vertical distance, in pixels, between two consecutive baselines.
+ * It is always positive.
+ *
+ * width ::
+ * The average width, in pixels, of all glyphs in the strike.
+ *
+ * size ::
+ * The nominal size of the strike in 26.6 fractional points. This
+ * field is not very useful.
+ *
+ * x_ppem ::
+ * The horizontal ppem (nominal width) in 26.6 fractional pixels.
+ *
+ * y_ppem ::
+ * The vertical ppem (nominal height) in 26.6 fractional pixels.
+ *
+ * @note:
+ * Windows FNT:
+ * The nominal size given in a FNT font is not reliable. If the driver
+ * finds it incorrect, it sets `size` to some calculated values, and
+ * `x_ppem` and `y_ppem` to the pixel width and height given in the
+ * font, respectively.
+ *
+ * TrueType embedded bitmaps:
+ * `size`, `width`, and `height` values are not contained in the bitmap
+ * strike itself. They are computed from the global font parameters.
+ */
typedef struct FT_Bitmap_Size_
{
FT_Short height;
@@ -389,225 +389,218 @@ FT_BEGIN_HEADER
/*************************************************************************/
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_Library */
- /* */
- /* <Description> */
- /* A handle to a FreeType library instance. Each `library' is */
- /* completely independent from the others; it is the `root' of a set */
- /* of objects like fonts, faces, sizes, etc. */
- /* */
- /* It also embeds a memory manager (see @FT_Memory), as well as a */
- /* scan-line converter object (see @FT_Raster). */
- /* */
- /* In multi-threaded applications it is easiest to use one */
- /* `FT_Library' object per thread. In case this is too cumbersome, */
- /* a single `FT_Library' object across threads is possible also */
- /* (since FreeType version 2.5.6), as long as a mutex lock is used */
- /* around @FT_New_Face and @FT_Done_Face. */
- /* */
- /* <Note> */
- /* Library objects are normally created by @FT_Init_FreeType, and */
- /* destroyed with @FT_Done_FreeType. If you need reference-counting */
- /* (cf. @FT_Reference_Library), use @FT_New_Library and */
- /* @FT_Done_Library. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Library
+ *
+ * @description:
+ * A handle to a FreeType library instance. Each 'library' is completely
+ * independent from the others; it is the 'root' of a set of objects like
+ * fonts, faces, sizes, etc.
+ *
+ * It also embeds a memory manager (see @FT_Memory), as well as a
+ * scan-line converter object (see @FT_Raster).
+ *
+ * [Since 2.5.6] In multi-threaded applications it is easiest to use one
+ * `FT_Library` object per thread. In case this is too cumbersome, a
+ * single `FT_Library` object across threads is possible also, as long as
+ * a mutex lock is used around @FT_New_Face and @FT_Done_Face.
+ *
+ * @note:
+ * Library objects are normally created by @FT_Init_FreeType, and
+ * destroyed with @FT_Done_FreeType. If you need reference-counting
+ * (cf. @FT_Reference_Library), use @FT_New_Library and @FT_Done_Library.
+ */
typedef struct FT_LibraryRec_ *FT_Library;
- /*************************************************************************/
- /* */
- /* <Section> */
- /* module_management */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * @section:
+ * module_management
+ *
+ */
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_Module */
- /* */
- /* <Description> */
- /* A handle to a given FreeType module object. A module can be a */
- /* font driver, a renderer, or anything else that provides services */
- /* to the former. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Module
+ *
+ * @description:
+ * A handle to a given FreeType module object. A module can be a font
+ * driver, a renderer, or anything else that provides services to the
+ * former.
+ */
typedef struct FT_ModuleRec_* FT_Module;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_Driver */
- /* */
- /* <Description> */
- /* A handle to a given FreeType font driver object. A font driver */
- /* is a module capable of creating faces from font files. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Driver
+ *
+ * @description:
+ * A handle to a given FreeType font driver object. A font driver is a
+ * module capable of creating faces from font files.
+ */
typedef struct FT_DriverRec_* FT_Driver;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_Renderer */
- /* */
- /* <Description> */
- /* A handle to a given FreeType renderer. A renderer is a module in */
- /* charge of converting a glyph's outline image to a bitmap. It */
- /* supports a single glyph image format, and one or more target */
- /* surface depths. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Renderer
+ *
+ * @description:
+ * A handle to a given FreeType renderer. A renderer is a module in
+ * charge of converting a glyph's outline image to a bitmap. It supports
+ * a single glyph image format, and one or more target surface depths.
+ */
typedef struct FT_RendererRec_* FT_Renderer;
- /*************************************************************************/
- /* */
- /* <Section> */
- /* base_interface */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * @section:
+ * base_interface
+ *
+ */
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_Face */
- /* */
- /* <Description> */
- /* A handle to a typographic face object. A face object models a */
- /* given typeface, in a given style. */
- /* */
- /* <Note> */
- /* A face object also owns a single @FT_GlyphSlot object, as well */
- /* as one or more @FT_Size objects. */
- /* */
- /* Use @FT_New_Face or @FT_Open_Face to create a new face object from */
- /* a given filepath or a custom input stream. */
- /* */
- /* Use @FT_Done_Face to destroy it (along with its slot and sizes). */
- /* */
- /* An `FT_Face' object can only be safely used from one thread at a */
- /* time. Similarly, creation and destruction of `FT_Face' with the */
- /* same @FT_Library object can only be done from one thread at a */
- /* time. On the other hand, functions like @FT_Load_Glyph and its */
- /* siblings are thread-safe and do not need the lock to be held as */
- /* long as the same `FT_Face' object is not used from multiple */
- /* threads at the same time. */
- /* */
- /* <Also> */
- /* See @FT_FaceRec for the publicly accessible fields of a given face */
- /* object. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Face
+ *
+ * @description:
+ * A handle to a typographic face object. A face object models a given
+ * typeface, in a given style.
+ *
+ * @note:
+ * A face object also owns a single @FT_GlyphSlot object, as well as one
+ * or more @FT_Size objects.
+ *
+ * Use @FT_New_Face or @FT_Open_Face to create a new face object from a
+ * given filepath or a custom input stream.
+ *
+ * Use @FT_Done_Face to destroy it (along with its slot and sizes).
+ *
+ * An `FT_Face` object can only be safely used from one thread at a time.
+ * Similarly, creation and destruction of `FT_Face` with the same
+ * @FT_Library object can only be done from one thread at a time. On the
+ * other hand, functions like @FT_Load_Glyph and its siblings are
+ * thread-safe and do not need the lock to be held as long as the same
+ * `FT_Face` object is not used from multiple threads at the same time.
+ *
+ * @also:
+ * See @FT_FaceRec for the publicly accessible fields of a given face
+ * object.
+ */
typedef struct FT_FaceRec_* FT_Face;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_Size */
- /* */
- /* <Description> */
- /* A handle to an object that models a face scaled to a given */
- /* character size. */
- /* */
- /* <Note> */
- /* An @FT_Face has one _active_ @FT_Size object that is used by */
- /* functions like @FT_Load_Glyph to determine the scaling */
- /* transformation that in turn is used to load and hint glyphs and */
- /* metrics. */
- /* */
- /* You can use @FT_Set_Char_Size, @FT_Set_Pixel_Sizes, */
- /* @FT_Request_Size or even @FT_Select_Size to change the content */
- /* (i.e., the scaling values) of the active @FT_Size. */
- /* */
- /* You can use @FT_New_Size to create additional size objects for a */
- /* given @FT_Face, but they won't be used by other functions until */
- /* you activate it through @FT_Activate_Size. Only one size can be */
- /* activated at any given time per face. */
- /* */
- /* <Also> */
- /* See @FT_SizeRec for the publicly accessible fields of a given size */
- /* object. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Size
+ *
+ * @description:
+ * A handle to an object that models a face scaled to a given character
+ * size.
+ *
+ * @note:
+ * An @FT_Face has one _active_ @FT_Size object that is used by functions
+ * like @FT_Load_Glyph to determine the scaling transformation that in
+ * turn is used to load and hint glyphs and metrics.
+ *
+ * You can use @FT_Set_Char_Size, @FT_Set_Pixel_Sizes, @FT_Request_Size
+ * or even @FT_Select_Size to change the content (i.e., the scaling
+ * values) of the active @FT_Size.
+ *
+ * You can use @FT_New_Size to create additional size objects for a given
+ * @FT_Face, but they won't be used by other functions until you activate
+ * it through @FT_Activate_Size. Only one size can be activated at any
+ * given time per face.
+ *
+ * @also:
+ * See @FT_SizeRec for the publicly accessible fields of a given size
+ * object.
+ */
typedef struct FT_SizeRec_* FT_Size;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_GlyphSlot */
- /* */
- /* <Description> */
- /* A handle to a given `glyph slot'. A slot is a container that can */
- /* hold any of the glyphs contained in its parent face. */
- /* */
- /* In other words, each time you call @FT_Load_Glyph or */
- /* @FT_Load_Char, the slot's content is erased by the new glyph data, */
- /* i.e., the glyph's metrics, its image (bitmap or outline), and */
- /* other control information. */
- /* */
- /* <Also> */
- /* See @FT_GlyphSlotRec for the publicly accessible glyph fields. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_GlyphSlot
+ *
+ * @description:
+ * A handle to a given 'glyph slot'. A slot is a container that can hold
+ * any of the glyphs contained in its parent face.
+ *
+ * In other words, each time you call @FT_Load_Glyph or @FT_Load_Char,
+ * the slot's content is erased by the new glyph data, i.e., the glyph's
+ * metrics, its image (bitmap or outline), and other control information.
+ *
+ * @also:
+ * See @FT_GlyphSlotRec for the publicly accessible glyph fields.
+ */
typedef struct FT_GlyphSlotRec_* FT_GlyphSlot;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_CharMap */
- /* */
- /* <Description> */
- /* A handle to a character map (usually abbreviated to `charmap'). A */
- /* charmap is used to translate character codes in a given encoding */
- /* into glyph indexes for its parent's face. Some font formats may */
- /* provide several charmaps per font. */
- /* */
- /* Each face object owns zero or more charmaps, but only one of them */
- /* can be `active', providing the data used by @FT_Get_Char_Index or */
- /* @FT_Load_Char. */
- /* */
- /* The list of available charmaps in a face is available through the */
- /* `face->num_charmaps' and `face->charmaps' fields of @FT_FaceRec. */
- /* */
- /* The currently active charmap is available as `face->charmap'. */
- /* You should call @FT_Set_Charmap to change it. */
- /* */
- /* <Note> */
- /* When a new face is created (either through @FT_New_Face or */
- /* @FT_Open_Face), the library looks for a Unicode charmap within */
- /* the list and automatically activates it. If there is no Unicode */
- /* charmap, FreeType doesn't set an `active' charmap. */
- /* */
- /* <Also> */
- /* See @FT_CharMapRec for the publicly accessible fields of a given */
- /* character map. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_CharMap
+ *
+ * @description:
+ * A handle to a character map (usually abbreviated to 'charmap'). A
+ * charmap is used to translate character codes in a given encoding into
+ * glyph indexes for its parent's face. Some font formats may provide
+ * several charmaps per font.
+ *
+ * Each face object owns zero or more charmaps, but only one of them can
+ * be 'active', providing the data used by @FT_Get_Char_Index or
+ * @FT_Load_Char.
+ *
+ * The list of available charmaps in a face is available through the
+ * `face->num_charmaps` and `face->charmaps` fields of @FT_FaceRec.
+ *
+ * The currently active charmap is available as `face->charmap`. You
+ * should call @FT_Set_Charmap to change it.
+ *
+ * @note:
+ * When a new face is created (either through @FT_New_Face or
+ * @FT_Open_Face), the library looks for a Unicode charmap within the
+ * list and automatically activates it. If there is no Unicode charmap,
+ * FreeType doesn't set an 'active' charmap.
+ *
+ * @also:
+ * See @FT_CharMapRec for the publicly accessible fields of a given
+ * character map.
+ */
typedef struct FT_CharMapRec_* FT_CharMap;
- /*************************************************************************/
- /* */
- /* <Macro> */
- /* FT_ENC_TAG */
- /* */
- /* <Description> */
- /* This macro converts four-letter tags into an unsigned long. It is */
- /* used to define `encoding' identifiers (see @FT_Encoding). */
- /* */
- /* <Note> */
- /* Since many 16-bit compilers don't like 32-bit enumerations, you */
- /* should redefine this macro in case of problems to something like */
- /* this: */
- /* */
- /* { */
- /* #define FT_ENC_TAG( value, a, b, c, d ) value */
- /* } */
- /* */
- /* to get a simple enumeration without assigning special numbers. */
- /* */
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_ENC_TAG
+ *
+ * @description:
+ * This macro converts four-letter tags into an unsigned long. It is
+ * used to define 'encoding' identifiers (see @FT_Encoding).
+ *
+ * @note:
+ * Since many 16-bit compilers don't like 32-bit enumerations, you should
+ * redefine this macro in case of problems to something like this:
+ *
+ * ```
+ * #define FT_ENC_TAG( value, a, b, c, d ) value
+ * ```
+ *
+ * to get a simple enumeration without assigning special numbers.
+ */
#ifndef FT_ENC_TAG
#define FT_ENC_TAG( value, a, b, c, d ) \
@@ -619,150 +612,147 @@ FT_BEGIN_HEADER
#endif /* FT_ENC_TAG */
- /*************************************************************************/
- /* */
- /* <Enum> */
- /* FT_Encoding */
- /* */
- /* <Description> */
- /* An enumeration to specify character sets supported by charmaps. */
- /* Used in the @FT_Select_Charmap API function. */
- /* */
- /* <Note> */
- /* Despite the name, this enumeration lists specific character */
- /* repertories (i.e., charsets), and not text encoding methods (e.g., */
- /* UTF-8, UTF-16, etc.). */
- /* */
- /* Other encodings might be defined in the future. */
- /* */
- /* <Values> */
- /* FT_ENCODING_NONE :: */
- /* The encoding value~0 is reserved. */
- /* */
- /* FT_ENCODING_UNICODE :: */
- /* The Unicode character set. This value covers all versions of */
- /* the Unicode repertoire, including ASCII and Latin-1. Most fonts */
- /* include a Unicode charmap, but not all of them. */
- /* */
- /* For example, if you want to access Unicode value U+1F028 (and */
- /* the font contains it), use value 0x1F028 as the input value for */
- /* @FT_Get_Char_Index. */
- /* */
- /* FT_ENCODING_MS_SYMBOL :: */
- /* Microsoft Symbol encoding, used to encode mathematical symbols */
- /* and wingdings. For more information, see */
- /* `https://www.microsoft.com/typography/otspec/recom.htm', */
- /* `http://www.kostis.net/charsets/symbol.htm', and */
- /* `http://www.kostis.net/charsets/wingding.htm'. */
- /* */
- /* This encoding uses character codes from the PUA (Private Unicode */
- /* Area) in the range U+F020-U+F0FF. */
- /* */
- /* FT_ENCODING_SJIS :: */
- /* Shift JIS encoding for Japanese. More info at */
- /* `https://en.wikipedia.org/wiki/Shift_JIS'. See note on */
- /* multi-byte encodings below. */
- /* */
- /* FT_ENCODING_PRC :: */
- /* Corresponds to encoding systems mainly for Simplified Chinese as */
- /* used in People's Republic of China (PRC). The encoding layout */
- /* is based on GB~2312 and its supersets GBK and GB~18030. */
- /* */
- /* FT_ENCODING_BIG5 :: */
- /* Corresponds to an encoding system for Traditional Chinese as */
- /* used in Taiwan and Hong Kong. */
- /* */
- /* FT_ENCODING_WANSUNG :: */
- /* Corresponds to the Korean encoding system known as Extended */
- /* Wansung (MS Windows code page 949). */
- /* For more information see */
- /* `https://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WindowsBestFit/bestfit949.txt'. */
- /* */
- /* FT_ENCODING_JOHAB :: */
- /* The Korean standard character set (KS~C 5601-1992), which */
- /* corresponds to MS Windows code page 1361. This character set */
- /* includes all possible Hangul character combinations. */
- /* */
- /* FT_ENCODING_ADOBE_LATIN_1 :: */
- /* Corresponds to a Latin-1 encoding as defined in a Type~1 */
- /* PostScript font. It is limited to 256 character codes. */
- /* */
- /* FT_ENCODING_ADOBE_STANDARD :: */
- /* Adobe Standard encoding, as found in Type~1, CFF, and */
- /* OpenType/CFF fonts. It is limited to 256 character codes. */
- /* */
- /* FT_ENCODING_ADOBE_EXPERT :: */
- /* Adobe Expert encoding, as found in Type~1, CFF, and OpenType/CFF */
- /* fonts. It is limited to 256 character codes. */
- /* */
- /* FT_ENCODING_ADOBE_CUSTOM :: */
- /* Corresponds to a custom encoding, as found in Type~1, CFF, and */
- /* OpenType/CFF fonts. It is limited to 256 character codes. */
- /* */
- /* FT_ENCODING_APPLE_ROMAN :: */
- /* Apple roman encoding. Many TrueType and OpenType fonts contain */
- /* a charmap for this 8-bit encoding, since older versions of Mac */
- /* OS are able to use it. */
- /* */
- /* FT_ENCODING_OLD_LATIN_2 :: */
- /* This value is deprecated and was neither used nor reported by */
- /* FreeType. Don't use or test for it. */
- /* */
- /* FT_ENCODING_MS_SJIS :: */
- /* Same as FT_ENCODING_SJIS. Deprecated. */
- /* */
- /* FT_ENCODING_MS_GB2312 :: */
- /* Same as FT_ENCODING_PRC. Deprecated. */
- /* */
- /* FT_ENCODING_MS_BIG5 :: */
- /* Same as FT_ENCODING_BIG5. Deprecated. */
- /* */
- /* FT_ENCODING_MS_WANSUNG :: */
- /* Same as FT_ENCODING_WANSUNG. Deprecated. */
- /* */
- /* FT_ENCODING_MS_JOHAB :: */
- /* Same as FT_ENCODING_JOHAB. Deprecated. */
- /* */
- /* <Note> */
- /* By default, FreeType enables a Unicode charmap and tags it with */
- /* FT_ENCODING_UNICODE when it is either provided or can be generated */
- /* from PostScript glyph name dictionaries in the font file. */
- /* All other encodings are considered legacy and tagged only if */
- /* explicitly defined in the font file. Otherwise, FT_ENCODING_NONE */
- /* is used. */
- /* */
- /* FT_ENCODING_NONE is set by the BDF and PCF drivers if the charmap */
- /* is neither Unicode nor ISO-8859-1 (otherwise it is set to */
- /* FT_ENCODING_UNICODE). Use @FT_Get_BDF_Charset_ID to find out */
- /* which encoding is really present. If, for example, the */
- /* `cs_registry' field is `KOI8' and the `cs_encoding' field is `R', */
- /* the font is encoded in KOI8-R. */
- /* */
- /* FT_ENCODING_NONE is always set (with a single exception) by the */
- /* winfonts driver. Use @FT_Get_WinFNT_Header and examine the */
- /* `charset' field of the @FT_WinFNT_HeaderRec structure to find out */
- /* which encoding is really present. For example, */
- /* @FT_WinFNT_ID_CP1251 (204) means Windows code page 1251 (for */
- /* Russian). */
- /* */
- /* FT_ENCODING_NONE is set if `platform_id' is @TT_PLATFORM_MACINTOSH */
- /* and `encoding_id' is not `TT_MAC_ID_ROMAN' (otherwise it is set to */
- /* FT_ENCODING_APPLE_ROMAN). */
- /* */
- /* If `platform_id' is @TT_PLATFORM_MACINTOSH, use the function */
- /* @FT_Get_CMap_Language_ID to query the Mac language ID that may */
- /* be needed to be able to distinguish Apple encoding variants. See */
- /* */
- /* https://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/Readme.txt */
- /* */
- /* to get an idea how to do that. Basically, if the language ID */
- /* is~0, don't use it, otherwise subtract 1 from the language ID. */
- /* Then examine `encoding_id'. If, for example, `encoding_id' is */
- /* `TT_MAC_ID_ROMAN' and the language ID (minus~1) is */
- /* `TT_MAC_LANGID_GREEK', it is the Greek encoding, not Roman. */
- /* `TT_MAC_ID_ARABIC' with `TT_MAC_LANGID_FARSI' means the Farsi */
- /* variant the Arabic encoding. */
- /* */
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_Encoding
+ *
+ * @description:
+ * An enumeration to specify character sets supported by charmaps. Used
+ * in the @FT_Select_Charmap API function.
+ *
+ * @note:
+ * Despite the name, this enumeration lists specific character
+ * repertories (i.e., charsets), and not text encoding methods (e.g.,
+ * UTF-8, UTF-16, etc.).
+ *
+ * Other encodings might be defined in the future.
+ *
+ * @values:
+ * FT_ENCODING_NONE ::
+ * The encoding value~0 is reserved for all formats except BDF, PCF,
+ * and Windows FNT; see below for more information.
+ *
+ * FT_ENCODING_UNICODE ::
+ * The Unicode character set. This value covers all versions of the
+ * Unicode repertoire, including ASCII and Latin-1. Most fonts include
+ * a Unicode charmap, but not all of them.
+ *
+ * For example, if you want to access Unicode value U+1F028 (and the
+ * font contains it), use value 0x1F028 as the input value for
+ * @FT_Get_Char_Index.
+ *
+ * FT_ENCODING_MS_SYMBOL ::
+ * Microsoft Symbol encoding, used to encode mathematical symbols and
+ * wingdings. For more information, see
+ * 'https://www.microsoft.com/typography/otspec/recom.htm',
+ * 'http://www.kostis.net/charsets/symbol.htm', and
+ * 'http://www.kostis.net/charsets/wingding.htm'.
+ *
+ * This encoding uses character codes from the PUA (Private Unicode
+ * Area) in the range U+F020-U+F0FF.
+ *
+ * FT_ENCODING_SJIS ::
+ * Shift JIS encoding for Japanese. More info at
+ * 'https://en.wikipedia.org/wiki/Shift_JIS'. See note on multi-byte
+ * encodings below.
+ *
+ * FT_ENCODING_PRC ::
+ * Corresponds to encoding systems mainly for Simplified Chinese as
+ * used in People's Republic of China (PRC). The encoding layout is
+ * based on GB~2312 and its supersets GBK and GB~18030.
+ *
+ * FT_ENCODING_BIG5 ::
+ * Corresponds to an encoding system for Traditional Chinese as used in
+ * Taiwan and Hong Kong.
+ *
+ * FT_ENCODING_WANSUNG ::
+ * Corresponds to the Korean encoding system known as Extended Wansung
+ * (MS Windows code page 949). For more information see
+ * 'https://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WindowsBestFit/bestfit949.txt'.
+ *
+ * FT_ENCODING_JOHAB ::
+ * The Korean standard character set (KS~C 5601-1992), which
+ * corresponds to MS Windows code page 1361. This character set
+ * includes all possible Hangul character combinations.
+ *
+ * FT_ENCODING_ADOBE_LATIN_1 ::
+ * Corresponds to a Latin-1 encoding as defined in a Type~1 PostScript
+ * font. It is limited to 256 character codes.
+ *
+ * FT_ENCODING_ADOBE_STANDARD ::
+ * Adobe Standard encoding, as found in Type~1, CFF, and OpenType/CFF
+ * fonts. It is limited to 256 character codes.
+ *
+ * FT_ENCODING_ADOBE_EXPERT ::
+ * Adobe Expert encoding, as found in Type~1, CFF, and OpenType/CFF
+ * fonts. It is limited to 256 character codes.
+ *
+ * FT_ENCODING_ADOBE_CUSTOM ::
+ * Corresponds to a custom encoding, as found in Type~1, CFF, and
+ * OpenType/CFF fonts. It is limited to 256 character codes.
+ *
+ * FT_ENCODING_APPLE_ROMAN ::
+ * Apple roman encoding. Many TrueType and OpenType fonts contain a
+ * charmap for this 8-bit encoding, since older versions of Mac OS are
+ * able to use it.
+ *
+ * FT_ENCODING_OLD_LATIN_2 ::
+ * This value is deprecated and was neither used nor reported by
+ * FreeType. Don't use or test for it.
+ *
+ * FT_ENCODING_MS_SJIS ::
+ * Same as FT_ENCODING_SJIS. Deprecated.
+ *
+ * FT_ENCODING_MS_GB2312 ::
+ * Same as FT_ENCODING_PRC. Deprecated.
+ *
+ * FT_ENCODING_MS_BIG5 ::
+ * Same as FT_ENCODING_BIG5. Deprecated.
+ *
+ * FT_ENCODING_MS_WANSUNG ::
+ * Same as FT_ENCODING_WANSUNG. Deprecated.
+ *
+ * FT_ENCODING_MS_JOHAB ::
+ * Same as FT_ENCODING_JOHAB. Deprecated.
+ *
+ * @note:
+ * By default, FreeType enables a Unicode charmap and tags it with
+ * `FT_ENCODING_UNICODE` when it is either provided or can be generated
+ * from PostScript glyph name dictionaries in the font file. All other
+ * encodings are considered legacy and tagged only if explicitly defined
+ * in the font file. Otherwise, `FT_ENCODING_NONE` is used.
+ *
+ * `FT_ENCODING_NONE` is set by the BDF and PCF drivers if the charmap is
+ * neither Unicode nor ISO-8859-1 (otherwise it is set to
+ * `FT_ENCODING_UNICODE`). Use @FT_Get_BDF_Charset_ID to find out which
+ * encoding is really present. If, for example, the `cs_registry` field
+ * is 'KOI8' and the `cs_encoding` field is 'R', the font is encoded in
+ * KOI8-R.
+ *
+ * `FT_ENCODING_NONE` is always set (with a single exception) by the
+ * winfonts driver. Use @FT_Get_WinFNT_Header and examine the `charset`
+ * field of the @FT_WinFNT_HeaderRec structure to find out which encoding
+ * is really present. For example, @FT_WinFNT_ID_CP1251 (204) means
+ * Windows code page 1251 (for Russian).
+ *
+ * `FT_ENCODING_NONE` is set if `platform_id` is @TT_PLATFORM_MACINTOSH
+ * and `encoding_id` is not `TT_MAC_ID_ROMAN` (otherwise it is set to
+ * `FT_ENCODING_APPLE_ROMAN`).
+ *
+ * If `platform_id` is @TT_PLATFORM_MACINTOSH, use the function
+ * @FT_Get_CMap_Language_ID to query the Mac language ID that may be
+ * needed to be able to distinguish Apple encoding variants. See
+ *
+ * https://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/Readme.txt
+ *
+ * to get an idea how to do that. Basically, if the language ID is~0,
+ * don't use it, otherwise subtract 1 from the language ID. Then examine
+ * `encoding_id`. If, for example, `encoding_id` is `TT_MAC_ID_ROMAN`
+ * and the language ID (minus~1) is `TT_MAC_LANGID_GREEK`, it is the
+ * Greek encoding, not Roman. `TT_MAC_ID_ARABIC` with
+ * `TT_MAC_LANGID_FARSI` means the Farsi variant the Arabic encoding.
+ */
typedef enum FT_Encoding_
{
FT_ENC_TAG( FT_ENCODING_NONE, 0, 0, 0, 0 ),
@@ -796,7 +786,7 @@ FT_BEGIN_HEADER
} FT_Encoding;
- /* these constants are deprecated; use the corresponding `FT_Encoding' */
+ /* these constants are deprecated; use the corresponding `FT_Encoding` */
/* values instead */
#define ft_encoding_none FT_ENCODING_NONE
#define ft_encoding_unicode FT_ENCODING_UNICODE
@@ -815,29 +805,31 @@ FT_BEGIN_HEADER
#define ft_encoding_apple_roman FT_ENCODING_APPLE_ROMAN
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_CharMapRec */
- /* */
- /* <Description> */
- /* The base charmap structure. */
- /* */
- /* <Fields> */
- /* face :: A handle to the parent face object. */
- /* */
- /* encoding :: An @FT_Encoding tag identifying the charmap. Use */
- /* this with @FT_Select_Charmap. */
- /* */
- /* platform_id :: An ID number describing the platform for the */
- /* following encoding ID. This comes directly from */
- /* the TrueType specification and gets emulated for */
- /* other formats. */
- /* */
- /* encoding_id :: A platform specific encoding number. This also */
- /* comes from the TrueType specification and gets */
- /* emulated similarly. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_CharMapRec
+ *
+ * @description:
+ * The base charmap structure.
+ *
+ * @fields:
+ * face ::
+ * A handle to the parent face object.
+ *
+ * encoding ::
+ * An @FT_Encoding tag identifying the charmap. Use this with
+ * @FT_Select_Charmap.
+ *
+ * platform_id ::
+ * An ID number describing the platform for the following encoding ID.
+ * This comes directly from the TrueType specification and gets
+ * emulated for other formats.
+ *
+ * encoding_id ::
+ * A platform-specific encoding number. This also comes from the
+ * TrueType specification and gets emulated similarly.
+ */
typedef struct FT_CharMapRec_
{
FT_Face face;
@@ -857,215 +849,195 @@ FT_BEGIN_HEADER
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_Face_Internal */
- /* */
- /* <Description> */
- /* An opaque handle to an `FT_Face_InternalRec' structure that models */
- /* the private data of a given @FT_Face object. */
- /* */
- /* This structure might change between releases of FreeType~2 and is */
- /* not generally available to client applications. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Face_Internal
+ *
+ * @description:
+ * An opaque handle to an `FT_Face_InternalRec` structure that models the
+ * private data of a given @FT_Face object.
+ *
+ * This structure might change between releases of FreeType~2 and is not
+ * generally available to client applications.
+ */
typedef struct FT_Face_InternalRec_* FT_Face_Internal;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_FaceRec */
- /* */
- /* <Description> */
- /* FreeType root face class structure. A face object models a */
- /* typeface in a font file. */
- /* */
- /* <Fields> */
- /* num_faces :: The number of faces in the font file. Some */
- /* font formats can have multiple faces in */
- /* a single font file. */
- /* */
- /* face_index :: This field holds two different values. */
- /* Bits 0-15 are the index of the face in the */
- /* font file (starting with value~0). They */
- /* are set to~0 if there is only one face in */
- /* the font file. */
- /* */
- /* [Since 2.6.1] Bits 16-30 are relevant to GX */
- /* and OpenType variation fonts only, holding */
- /* the named instance index for the current */
- /* face index (starting with value~1; value~0 */
- /* indicates font access without a named */
- /* instance). For non-variation fonts, bits */
- /* 16-30 are ignored. If we have the third */
- /* named instance of face~4, say, `face_index' */
- /* is set to 0x00030004. */
- /* */
- /* Bit 31 is always zero (this is, */
- /* `face_index' is always a positive value). */
- /* */
- /* [Since 2.9] Changing the design coordinates */
- /* with @FT_Set_Var_Design_Coordinates or */
- /* @FT_Set_Var_Blend_Coordinates does not */
- /* influence the named instance index value */
- /* (only @FT_Set_Named_Instance does that). */
- /* */
- /* face_flags :: A set of bit flags that give important */
- /* information about the face; see */
- /* @FT_FACE_FLAG_XXX for the details. */
- /* */
- /* style_flags :: The lower 16~bits contain a set of bit */
- /* flags indicating the style of the face; see */
- /* @FT_STYLE_FLAG_XXX for the details. */
- /* */
- /* [Since 2.6.1] Bits 16-30 hold the number */
- /* of named instances available for the */
- /* current face if we have a GX or OpenType */
- /* variation (sub)font. Bit 31 is always zero */
- /* (this is, `style_flags' is always a */
- /* positive value). Note that a variation */
- /* font has always at least one named */
- /* instance, namely the default instance. */
- /* */
- /* num_glyphs :: The number of glyphs in the face. If the */
- /* face is scalable and has sbits (see */
- /* `num_fixed_sizes'), it is set to the number */
- /* of outline glyphs. */
- /* */
- /* For CID-keyed fonts (not in an SFNT */
- /* wrapper) this value gives the highest CID */
- /* used in the font. */
- /* */
- /* family_name :: The face's family name. This is an ASCII */
- /* string, usually in English, that describes */
- /* the typeface's family (like `Times New */
- /* Roman', `Bodoni', `Garamond', etc). This */
- /* is a least common denominator used to list */
- /* fonts. Some formats (TrueType & OpenType) */
- /* provide localized and Unicode versions of */
- /* this string. Applications should use the */
- /* format specific interface to access them. */
- /* Can be NULL (e.g., in fonts embedded in a */
- /* PDF file). */
- /* */
- /* In case the font doesn't provide a specific */
- /* family name entry, FreeType tries to */
- /* synthesize one, deriving it from other name */
- /* entries. */
- /* */
- /* style_name :: The face's style name. This is an ASCII */
- /* string, usually in English, that describes */
- /* the typeface's style (like `Italic', */
- /* `Bold', `Condensed', etc). Not all font */
- /* formats provide a style name, so this field */
- /* is optional, and can be set to NULL. As */
- /* for `family_name', some formats provide */
- /* localized and Unicode versions of this */
- /* string. Applications should use the format */
- /* specific interface to access them. */
- /* */
- /* num_fixed_sizes :: The number of bitmap strikes in the face. */
- /* Even if the face is scalable, there might */
- /* still be bitmap strikes, which are called */
- /* `sbits' in that case. */
- /* */
- /* available_sizes :: An array of @FT_Bitmap_Size for all bitmap */
- /* strikes in the face. It is set to NULL if */
- /* there is no bitmap strike. */
- /* */
- /* Note that FreeType tries to sanitize the */
- /* strike data since they are sometimes sloppy */
- /* or incorrect, but this can easily fail. */
- /* */
- /* num_charmaps :: The number of charmaps in the face. */
- /* */
- /* charmaps :: An array of the charmaps of the face. */
- /* */
- /* generic :: A field reserved for client uses. See the */
- /* @FT_Generic type description. */
- /* */
- /* bbox :: The font bounding box. Coordinates are */
- /* expressed in font units (see */
- /* `units_per_EM'). The box is large enough */
- /* to contain any glyph from the font. Thus, */
- /* `bbox.yMax' can be seen as the `maximum */
- /* ascender', and `bbox.yMin' as the `minimum */
- /* descender'. Only relevant for scalable */
- /* formats. */
- /* */
- /* Note that the bounding box might be off by */
- /* (at least) one pixel for hinted fonts. See */
- /* @FT_Size_Metrics for further discussion. */
- /* */
- /* units_per_EM :: The number of font units per EM square for */
- /* this face. This is typically 2048 for */
- /* TrueType fonts, and 1000 for Type~1 fonts. */
- /* Only relevant for scalable formats. */
- /* */
- /* ascender :: The typographic ascender of the face, */
- /* expressed in font units. For font formats */
- /* not having this information, it is set to */
- /* `bbox.yMax'. Only relevant for scalable */
- /* formats. */
- /* */
- /* descender :: The typographic descender of the face, */
- /* expressed in font units. For font formats */
- /* not having this information, it is set to */
- /* `bbox.yMin'. Note that this field is */
- /* negative for values below the baseline. */
- /* Only relevant for scalable formats. */
- /* */
- /* height :: This value is the vertical distance */
- /* between two consecutive baselines, */
- /* expressed in font units. It is always */
- /* positive. Only relevant for scalable */
- /* formats. */
- /* */
- /* If you want the global glyph height, use */
- /* `ascender - descender'. */
- /* */
- /* max_advance_width :: The maximum advance width, in font units, */
- /* for all glyphs in this face. This can be */
- /* used to make word wrapping computations */
- /* faster. Only relevant for scalable */
- /* formats. */
- /* */
- /* max_advance_height :: The maximum advance height, in font units, */
- /* for all glyphs in this face. This is only */
- /* relevant for vertical layouts, and is set */
- /* to `height' for fonts that do not provide */
- /* vertical metrics. Only relevant for */
- /* scalable formats. */
- /* */
- /* underline_position :: The position, in font units, of the */
- /* underline line for this face. It is the */
- /* center of the underlining stem. Only */
- /* relevant for scalable formats. */
- /* */
- /* underline_thickness :: The thickness, in font units, of the */
- /* underline for this face. Only relevant for */
- /* scalable formats. */
- /* */
- /* glyph :: The face's associated glyph slot(s). */
- /* */
- /* size :: The current active size for this face. */
- /* */
- /* charmap :: The current active charmap for this face. */
- /* */
- /* <Note> */
- /* Fields may be changed after a call to @FT_Attach_File or */
- /* @FT_Attach_Stream. */
- /* */
- /* For an OpenType variation font, the values of the following fields */
- /* can change after a call to @FT_Set_Var_Design_Coordinates (and */
- /* friends) if the font contains an `MVAR' table: `ascender', */
- /* `descender', `height', `underline_position', and */
- /* `underline_thickness'. */
- /* */
- /* Especially for TrueType fonts see also the documentation for */
- /* @FT_Size_Metrics. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_FaceRec
+ *
+ * @description:
+ * FreeType root face class structure. A face object models a typeface
+ * in a font file.
+ *
+ * @fields:
+ * num_faces ::
+ * The number of faces in the font file. Some font formats can have
+ * multiple faces in a single font file.
+ *
+ * face_index ::
+ * This field holds two different values. Bits 0-15 are the index of
+ * the face in the font file (starting with value~0). They are set
+ * to~0 if there is only one face in the font file.
+ *
+ * [Since 2.6.1] Bits 16-30 are relevant to GX and OpenType variation
+ * fonts only, holding the named instance index for the current face
+ * index (starting with value~1; value~0 indicates font access without
+ * a named instance). For non-variation fonts, bits 16-30 are ignored.
+ * If we have the third named instance of face~4, say, `face_index` is
+ * set to 0x00030004.
+ *
+ * Bit 31 is always zero (this is, `face_index` is always a positive
+ * value).
+ *
+ * [Since 2.9] Changing the design coordinates with
+ * @FT_Set_Var_Design_Coordinates or @FT_Set_Var_Blend_Coordinates does
+ * not influence the named instance index value (only
+ * @FT_Set_Named_Instance does that).
+ *
+ * face_flags ::
+ * A set of bit flags that give important information about the face;
+ * see @FT_FACE_FLAG_XXX for the details.
+ *
+ * style_flags ::
+ * The lower 16~bits contain a set of bit flags indicating the style of
+ * the face; see @FT_STYLE_FLAG_XXX for the details.
+ *
+ * [Since 2.6.1] Bits 16-30 hold the number of named instances
+ * available for the current face if we have a GX or OpenType variation
+ * (sub)font. Bit 31 is always zero (this is, `style_flags` is always
+ * a positive value). Note that a variation font has always at least
+ * one named instance, namely the default instance.
+ *
+ * num_glyphs ::
+ * The number of glyphs in the face. If the face is scalable and has
+ * sbits (see `num_fixed_sizes`), it is set to the number of outline
+ * glyphs.
+ *
+ * For CID-keyed fonts (not in an SFNT wrapper) this value gives the
+ * highest CID used in the font.
+ *
+ * family_name ::
+ * The face's family name. This is an ASCII string, usually in
+ * English, that describes the typeface's family (like 'Times New
+ * Roman', 'Bodoni', 'Garamond', etc). This is a least common
+ * denominator used to list fonts. Some formats (TrueType & OpenType)
+ * provide localized and Unicode versions of this string. Applications
+ * should use the format-specific interface to access them. Can be
+ * `NULL` (e.g., in fonts embedded in a PDF file).
+ *
+ * In case the font doesn't provide a specific family name entry,
+ * FreeType tries to synthesize one, deriving it from other name
+ * entries.
+ *
+ * style_name ::
+ * The face's style name. This is an ASCII string, usually in English,
+ * that describes the typeface's style (like 'Italic', 'Bold',
+ * 'Condensed', etc). Not all font formats provide a style name, so
+ * this field is optional, and can be set to `NULL`. As for
+ * `family_name`, some formats provide localized and Unicode versions
+ * of this string. Applications should use the format-specific
+ * interface to access them.
+ *
+ * num_fixed_sizes ::
+ * The number of bitmap strikes in the face. Even if the face is
+ * scalable, there might still be bitmap strikes, which are called
+ * 'sbits' in that case.
+ *
+ * available_sizes ::
+ * An array of @FT_Bitmap_Size for all bitmap strikes in the face. It
+ * is set to `NULL` if there is no bitmap strike.
+ *
+ * Note that FreeType tries to sanitize the strike data since they are
+ * sometimes sloppy or incorrect, but this can easily fail.
+ *
+ * num_charmaps ::
+ * The number of charmaps in the face.
+ *
+ * charmaps ::
+ * An array of the charmaps of the face.
+ *
+ * generic ::
+ * A field reserved for client uses. See the @FT_Generic type
+ * description.
+ *
+ * bbox ::
+ * The font bounding box. Coordinates are expressed in font units (see
+ * `units_per_EM`). The box is large enough to contain any glyph from
+ * the font. Thus, `bbox.yMax` can be seen as the 'maximum ascender',
+ * and `bbox.yMin` as the 'minimum descender'. Only relevant for
+ * scalable formats.
+ *
+ * Note that the bounding box might be off by (at least) one pixel for
+ * hinted fonts. See @FT_Size_Metrics for further discussion.
+ *
+ * units_per_EM ::
+ * The number of font units per EM square for this face. This is
+ * typically 2048 for TrueType fonts, and 1000 for Type~1 fonts. Only
+ * relevant for scalable formats.
+ *
+ * ascender ::
+ * The typographic ascender of the face, expressed in font units. For
+ * font formats not having this information, it is set to `bbox.yMax`.
+ * Only relevant for scalable formats.
+ *
+ * descender ::
+ * The typographic descender of the face, expressed in font units. For
+ * font formats not having this information, it is set to `bbox.yMin`.
+ * Note that this field is negative for values below the baseline.
+ * Only relevant for scalable formats.
+ *
+ * height ::
+ * This value is the vertical distance between two consecutive
+ * baselines, expressed in font units. It is always positive. Only
+ * relevant for scalable formats.
+ *
+ * If you want the global glyph height, use `ascender - descender`.
+ *
+ * max_advance_width ::
+ * The maximum advance width, in font units, for all glyphs in this
+ * face. This can be used to make word wrapping computations faster.
+ * Only relevant for scalable formats.
+ *
+ * max_advance_height ::
+ * The maximum advance height, in font units, for all glyphs in this
+ * face. This is only relevant for vertical layouts, and is set to
+ * `height` for fonts that do not provide vertical metrics. Only
+ * relevant for scalable formats.
+ *
+ * underline_position ::
+ * The position, in font units, of the underline line for this face.
+ * It is the center of the underlining stem. Only relevant for
+ * scalable formats.
+ *
+ * underline_thickness ::
+ * The thickness, in font units, of the underline for this face. Only
+ * relevant for scalable formats.
+ *
+ * glyph ::
+ * The face's associated glyph slot(s).
+ *
+ * size ::
+ * The current active size for this face.
+ *
+ * charmap ::
+ * The current active charmap for this face.
+ *
+ * @note:
+ * Fields may be changed after a call to @FT_Attach_File or
+ * @FT_Attach_Stream.
+ *
+ * For an OpenType variation font, the values of the following fields can
+ * change after a call to @FT_Set_Var_Design_Coordinates (and friends) if
+ * the font contains an 'MVAR' table: `ascender`, `descender`, `height`,
+ * `underline_position`, and `underline_thickness`.
+ *
+ * Especially for TrueType fonts see also the documentation for
+ * @FT_Size_Metrics.
+ */
typedef struct FT_FaceRec_
{
FT_Long num_faces;
@@ -1087,7 +1059,7 @@ FT_BEGIN_HEADER
FT_Generic generic;
- /*# The following member variables (down to `underline_thickness') */
+ /*# The following member variables (down to `underline_thickness`) */
/*# are only relevant to scalable outlines; cf. @FT_Bitmap_Size */
/*# for bitmap fonts. */
FT_BBox bbox;
@@ -1125,117 +1097,116 @@ FT_BEGIN_HEADER
} FT_FaceRec;
- /*************************************************************************/
- /* */
- /* <Enum> */
- /* FT_FACE_FLAG_XXX */
- /* */
- /* <Description> */
- /* A list of bit flags used in the `face_flags' field of the */
- /* @FT_FaceRec structure. They inform client applications of */
- /* properties of the corresponding face. */
- /* */
- /* <Values> */
- /* FT_FACE_FLAG_SCALABLE :: */
- /* The face contains outline glyphs. Note that a face can contain */
- /* bitmap strikes also, i.e., a face can have both this flag and */
- /* @FT_FACE_FLAG_FIXED_SIZES set. */
- /* */
- /* FT_FACE_FLAG_FIXED_SIZES :: */
- /* The face contains bitmap strikes. See also the */
- /* `num_fixed_sizes' and `available_sizes' fields of @FT_FaceRec. */
- /* */
- /* FT_FACE_FLAG_FIXED_WIDTH :: */
- /* The face contains fixed-width characters (like Courier, Lucida, */
- /* MonoType, etc.). */
- /* */
- /* FT_FACE_FLAG_SFNT :: */
- /* The face uses the SFNT storage scheme. For now, this means */
- /* TrueType and OpenType. */
- /* */
- /* FT_FACE_FLAG_HORIZONTAL :: */
- /* The face contains horizontal glyph metrics. This should be set */
- /* for all common formats. */
- /* */
- /* FT_FACE_FLAG_VERTICAL :: */
- /* The face contains vertical glyph metrics. This is only */
- /* available in some formats, not all of them. */
- /* */
- /* FT_FACE_FLAG_KERNING :: */
- /* The face contains kerning information. If set, the kerning */
- /* distance can be retrieved using the function @FT_Get_Kerning. */
- /* Otherwise the function always return the vector (0,0). Note */
- /* that FreeType doesn't handle kerning data from the SFNT `GPOS' */
- /* table (as present in many OpenType fonts). */
- /* */
- /* FT_FACE_FLAG_FAST_GLYPHS :: */
- /* THIS FLAG IS DEPRECATED. DO NOT USE OR TEST IT. */
- /* */
- /* FT_FACE_FLAG_MULTIPLE_MASTERS :: */
- /* The face contains multiple masters and is capable of */
- /* interpolating between them. Supported formats are Adobe MM, */
- /* TrueType GX, and OpenType variation fonts. */
- /* */
- /* See section @multiple_masters for API details. */
- /* */
- /* FT_FACE_FLAG_GLYPH_NAMES :: */
- /* The face contains glyph names, which can be retrieved using */
- /* @FT_Get_Glyph_Name. Note that some TrueType fonts contain */
- /* broken glyph name tables. Use the function */
- /* @FT_Has_PS_Glyph_Names when needed. */
- /* */
- /* FT_FACE_FLAG_EXTERNAL_STREAM :: */
- /* Used internally by FreeType to indicate that a face's stream was */
- /* provided by the client application and should not be destroyed */
- /* when @FT_Done_Face is called. Don't read or test this flag. */
- /* */
- /* FT_FACE_FLAG_HINTER :: */
- /* The font driver has a hinting machine of its own. For example, */
- /* with TrueType fonts, it makes sense to use data from the SFNT */
- /* `gasp' table only if the native TrueType hinting engine (with */
- /* the bytecode interpreter) is available and active. */
- /* */
- /* FT_FACE_FLAG_CID_KEYED :: */
- /* The face is CID-keyed. In that case, the face is not accessed */
- /* by glyph indices but by CID values. For subsetted CID-keyed */
- /* fonts this has the consequence that not all index values are a */
- /* valid argument to @FT_Load_Glyph. Only the CID values for which */
- /* corresponding glyphs in the subsetted font exist make */
- /* `FT_Load_Glyph' return successfully; in all other cases you get */
- /* an `FT_Err_Invalid_Argument' error. */
- /* */
- /* Note that CID-keyed fonts that are in an SFNT wrapper (this is, */
- /* all OpenType/CFF fonts) don't have this flag set since the */
- /* glyphs are accessed in the normal way (using contiguous */
- /* indices); the `CID-ness' isn't visible to the application. */
- /* */
- /* FT_FACE_FLAG_TRICKY :: */
- /* The face is `tricky', this is, it always needs the font format's */
- /* native hinting engine to get a reasonable result. A typical */
- /* example is the old Chinese font `mingli.ttf' (but not */
- /* `mingliu.ttc') that uses TrueType bytecode instructions to move */
- /* and scale all of its subglyphs. */
- /* */
- /* It is not possible to auto-hint such fonts using */
- /* @FT_LOAD_FORCE_AUTOHINT; it will also ignore */
- /* @FT_LOAD_NO_HINTING. You have to set both @FT_LOAD_NO_HINTING */
- /* and @FT_LOAD_NO_AUTOHINT to really disable hinting; however, you */
- /* probably never want this except for demonstration purposes. */
- /* */
- /* Currently, there are about a dozen TrueType fonts in the list of */
- /* tricky fonts; they are hard-coded in file `ttobjs.c'. */
- /* */
- /* FT_FACE_FLAG_COLOR :: */
- /* [Since 2.5.1] The face has color glyph tables. To access color */
- /* glyphs use @FT_LOAD_COLOR. */
- /* */
- /* FT_FACE_FLAG_VARIATION :: */
- /* [Since 2.9] Set if the current face (or named instance) has been */
- /* altered with @FT_Set_MM_Design_Coordinates, */
- /* @FT_Set_Var_Design_Coordinates, or */
- /* @FT_Set_Var_Blend_Coordinates. This flag is unset by a call to */
- /* @FT_Set_Named_Instance. */
- /* */
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_FACE_FLAG_XXX
+ *
+ * @description:
+ * A list of bit flags used in the `face_flags` field of the @FT_FaceRec
+ * structure. They inform client applications of properties of the
+ * corresponding face.
+ *
+ * @values:
+ * FT_FACE_FLAG_SCALABLE ::
+ * The face contains outline glyphs. Note that a face can contain
+ * bitmap strikes also, i.e., a face can have both this flag and
+ * @FT_FACE_FLAG_FIXED_SIZES set.
+ *
+ * FT_FACE_FLAG_FIXED_SIZES ::
+ * The face contains bitmap strikes. See also the `num_fixed_sizes`
+ * and `available_sizes` fields of @FT_FaceRec.
+ *
+ * FT_FACE_FLAG_FIXED_WIDTH ::
+ * The face contains fixed-width characters (like Courier, Lucida,
+ * MonoType, etc.).
+ *
+ * FT_FACE_FLAG_SFNT ::
+ * The face uses the SFNT storage scheme. For now, this means TrueType
+ * and OpenType.
+ *
+ * FT_FACE_FLAG_HORIZONTAL ::
+ * The face contains horizontal glyph metrics. This should be set for
+ * all common formats.
+ *
+ * FT_FACE_FLAG_VERTICAL ::
+ * The face contains vertical glyph metrics. This is only available in
+ * some formats, not all of them.
+ *
+ * FT_FACE_FLAG_KERNING ::
+ * The face contains kerning information. If set, the kerning distance
+ * can be retrieved using the function @FT_Get_Kerning. Otherwise the
+ * function always return the vector (0,0). Note that FreeType doesn't
+ * handle kerning data from the SFNT 'GPOS' table (as present in many
+ * OpenType fonts).
+ *
+ * FT_FACE_FLAG_FAST_GLYPHS ::
+ * THIS FLAG IS DEPRECATED. DO NOT USE OR TEST IT.
+ *
+ * FT_FACE_FLAG_MULTIPLE_MASTERS ::
+ * The face contains multiple masters and is capable of interpolating
+ * between them. Supported formats are Adobe MM, TrueType GX, and
+ * OpenType variation fonts.
+ *
+ * See section @multiple_masters for API details.
+ *
+ * FT_FACE_FLAG_GLYPH_NAMES ::
+ * The face contains glyph names, which can be retrieved using
+ * @FT_Get_Glyph_Name. Note that some TrueType fonts contain broken
+ * glyph name tables. Use the function @FT_Has_PS_Glyph_Names when
+ * needed.
+ *
+ * FT_FACE_FLAG_EXTERNAL_STREAM ::
+ * Used internally by FreeType to indicate that a face's stream was
+ * provided by the client application and should not be destroyed when
+ * @FT_Done_Face is called. Don't read or test this flag.
+ *
+ * FT_FACE_FLAG_HINTER ::
+ * The font driver has a hinting machine of its own. For example, with
+ * TrueType fonts, it makes sense to use data from the SFNT 'gasp'
+ * table only if the native TrueType hinting engine (with the bytecode
+ * interpreter) is available and active.
+ *
+ * FT_FACE_FLAG_CID_KEYED ::
+ * The face is CID-keyed. In that case, the face is not accessed by
+ * glyph indices but by CID values. For subsetted CID-keyed fonts this
+ * has the consequence that not all index values are a valid argument
+ * to @FT_Load_Glyph. Only the CID values for which corresponding
+ * glyphs in the subsetted font exist make `FT_Load_Glyph` return
+ * successfully; in all other cases you get an
+ * `FT_Err_Invalid_Argument` error.
+ *
+ * Note that CID-keyed fonts that are in an SFNT wrapper (this is, all
+ * OpenType/CFF fonts) don't have this flag set since the glyphs are
+ * accessed in the normal way (using contiguous indices); the
+ * 'CID-ness' isn't visible to the application.
+ *
+ * FT_FACE_FLAG_TRICKY ::
+ * The face is 'tricky', this is, it always needs the font format's
+ * native hinting engine to get a reasonable result. A typical example
+ * is the old Chinese font `mingli.ttf` (but not `mingliu.ttc`) that
+ * uses TrueType bytecode instructions to move and scale all of its
+ * subglyphs.
+ *
+ * It is not possible to auto-hint such fonts using
+ * @FT_LOAD_FORCE_AUTOHINT; it will also ignore @FT_LOAD_NO_HINTING.
+ * You have to set both @FT_LOAD_NO_HINTING and @FT_LOAD_NO_AUTOHINT to
+ * really disable hinting; however, you probably never want this except
+ * for demonstration purposes.
+ *
+ * Currently, there are about a dozen TrueType fonts in the list of
+ * tricky fonts; they are hard-coded in file `ttobjs.c`.
+ *
+ * FT_FACE_FLAG_COLOR ::
+ * [Since 2.5.1] The face has color glyph tables. See @FT_LOAD_COLOR
+ * for more information.
+ *
+ * FT_FACE_FLAG_VARIATION ::
+ * [Since 2.9] Set if the current face (or named instance) has been
+ * altered with @FT_Set_MM_Design_Coordinates,
+ * @FT_Set_Var_Design_Coordinates, or @FT_Set_Var_Blend_Coordinates.
+ * This flag is unset by a call to @FT_Set_Named_Instance.
+ */
#define FT_FACE_FLAG_SCALABLE ( 1L << 0 )
#define FT_FACE_FLAG_FIXED_SIZES ( 1L << 1 )
#define FT_FACE_FLAG_FIXED_WIDTH ( 1L << 2 )
@@ -1254,14 +1225,14 @@ FT_BEGIN_HEADER
#define FT_FACE_FLAG_VARIATION ( 1L << 15 )
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
- * FT_HAS_HORIZONTAL( face )
+ * FT_HAS_HORIZONTAL
*
* @description:
- * A macro that returns true whenever a face object contains
- * horizontal metrics (this is true for all font formats though).
+ * A macro that returns true whenever a face object contains horizontal
+ * metrics (this is true for all font formats though).
*
* @also:
* @FT_HAS_VERTICAL can be used to check for vertical metrics.
@@ -1271,10 +1242,10 @@ FT_BEGIN_HEADER
( (face)->face_flags & FT_FACE_FLAG_HORIZONTAL )
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
- * FT_HAS_VERTICAL( face )
+ * FT_HAS_VERTICAL
*
* @description:
* A macro that returns true whenever a face object contains real
@@ -1285,45 +1256,45 @@ FT_BEGIN_HEADER
( (face)->face_flags & FT_FACE_FLAG_VERTICAL )
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
- * FT_HAS_KERNING( face )
+ * FT_HAS_KERNING
*
* @description:
- * A macro that returns true whenever a face object contains kerning
- * data that can be accessed with @FT_Get_Kerning.
+ * A macro that returns true whenever a face object contains kerning data
+ * that can be accessed with @FT_Get_Kerning.
*
*/
#define FT_HAS_KERNING( face ) \
( (face)->face_flags & FT_FACE_FLAG_KERNING )
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
- * FT_IS_SCALABLE( face )
+ * FT_IS_SCALABLE
*
* @description:
* A macro that returns true whenever a face object contains a scalable
- * font face (true for TrueType, Type~1, Type~42, CID, OpenType/CFF,
- * and PFR font formats).
+ * font face (true for TrueType, Type~1, Type~42, CID, OpenType/CFF, and
+ * PFR font formats).
*
*/
#define FT_IS_SCALABLE( face ) \
( (face)->face_flags & FT_FACE_FLAG_SCALABLE )
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
- * FT_IS_SFNT( face )
+ * FT_IS_SFNT
*
* @description:
- * A macro that returns true whenever a face object contains a font
- * whose format is based on the SFNT storage scheme. This usually
- * means: TrueType fonts, OpenType fonts, as well as SFNT-based embedded
- * bitmap fonts.
+ * A macro that returns true whenever a face object contains a font whose
+ * format is based on the SFNT storage scheme. This usually means:
+ * TrueType fonts, OpenType fonts, as well as SFNT-based embedded bitmap
+ * fonts.
*
* If this macro is true, all functions defined in @FT_SFNT_NAMES_H and
* @FT_TRUETYPE_TABLES_H are available.
@@ -1333,14 +1304,14 @@ FT_BEGIN_HEADER
( (face)->face_flags & FT_FACE_FLAG_SFNT )
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
- * FT_IS_FIXED_WIDTH( face )
+ * FT_IS_FIXED_WIDTH
*
* @description:
* A macro that returns true whenever a face object contains a font face
- * that contains fixed-width (or `monospace', `fixed-pitch', etc.)
+ * that contains fixed-width (or 'monospace', 'fixed-pitch', etc.)
* glyphs.
*
*/
@@ -1348,25 +1319,25 @@ FT_BEGIN_HEADER
( (face)->face_flags & FT_FACE_FLAG_FIXED_WIDTH )
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
- * FT_HAS_FIXED_SIZES( face )
+ * FT_HAS_FIXED_SIZES
*
* @description:
* A macro that returns true whenever a face object contains some
- * embedded bitmaps. See the `available_sizes' field of the
- * @FT_FaceRec structure.
+ * embedded bitmaps. See the `available_sizes` field of the @FT_FaceRec
+ * structure.
*
*/
#define FT_HAS_FIXED_SIZES( face ) \
( (face)->face_flags & FT_FACE_FLAG_FIXED_SIZES )
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
- * FT_HAS_FAST_GLYPHS( face )
+ * FT_HAS_FAST_GLYPHS
*
* @description:
* Deprecated.
@@ -1375,10 +1346,10 @@ FT_BEGIN_HEADER
#define FT_HAS_FAST_GLYPHS( face ) 0
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
- * FT_HAS_GLYPH_NAMES( face )
+ * FT_HAS_GLYPH_NAMES
*
* @description:
* A macro that returns true whenever a face object contains some glyph
@@ -1389,10 +1360,10 @@ FT_BEGIN_HEADER
( (face)->face_flags & FT_FACE_FLAG_GLYPH_NAMES )
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
- * FT_HAS_MULTIPLE_MASTERS( face )
+ * FT_HAS_MULTIPLE_MASTERS
*
* @description:
* A macro that returns true whenever a face object contains some
@@ -1404,10 +1375,10 @@ FT_BEGIN_HEADER
( (face)->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS )
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
- * FT_IS_NAMED_INSTANCE( face )
+ * FT_IS_NAMED_INSTANCE
*
* @description:
* A macro that returns true whenever a face object is a named instance
@@ -1426,14 +1397,14 @@ FT_BEGIN_HEADER
( (face)->face_index & 0x7FFF0000L )
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
- * FT_IS_VARIATION( face )
+ * FT_IS_VARIATION
*
* @description:
- * A macro that returns true whenever a face object has been altered
- * by @FT_Set_MM_Design_Coordinates, @FT_Set_Var_Design_Coordinates, or
+ * A macro that returns true whenever a face object has been altered by
+ * @FT_Set_MM_Design_Coordinates, @FT_Set_Var_Design_Coordinates, or
* @FT_Set_Var_Blend_Coordinates.
*
* @since:
@@ -1444,15 +1415,14 @@ FT_BEGIN_HEADER
( (face)->face_flags & FT_FACE_FLAG_VARIATION )
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
- * FT_IS_CID_KEYED( face )
+ * FT_IS_CID_KEYED
*
* @description:
* A macro that returns true whenever a face object contains a CID-keyed
- * font. See the discussion of @FT_FACE_FLAG_CID_KEYED for more
- * details.
+ * font. See the discussion of @FT_FACE_FLAG_CID_KEYED for more details.
*
* If this macro is true, all functions defined in @FT_CID_H are
* available.
@@ -1462,13 +1432,13 @@ FT_BEGIN_HEADER
( (face)->face_flags & FT_FACE_FLAG_CID_KEYED )
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
- * FT_IS_TRICKY( face )
+ * FT_IS_TRICKY
*
* @description:
- * A macro that returns true whenever a face represents a `tricky' font.
+ * A macro that returns true whenever a face represents a 'tricky' font.
* See the discussion of @FT_FACE_FLAG_TRICKY for more details.
*
*/
@@ -1476,14 +1446,14 @@ FT_BEGIN_HEADER
( (face)->face_flags & FT_FACE_FLAG_TRICKY )
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
- * FT_HAS_COLOR( face )
+ * FT_HAS_COLOR
*
* @description:
- * A macro that returns true whenever a face object contains
- * tables for color glyphs.
+ * A macro that returns true whenever a face object contains tables for
+ * color glyphs.
*
* @since:
* 2.5.1
@@ -1493,149 +1463,148 @@ FT_BEGIN_HEADER
( (face)->face_flags & FT_FACE_FLAG_COLOR )
- /*************************************************************************/
- /* */
- /* <Const> */
- /* FT_STYLE_FLAG_XXX */
- /* */
- /* <Description> */
- /* A list of bit flags to indicate the style of a given face. These */
- /* are used in the `style_flags' field of @FT_FaceRec. */
- /* */
- /* <Values> */
- /* FT_STYLE_FLAG_ITALIC :: */
- /* The face style is italic or oblique. */
- /* */
- /* FT_STYLE_FLAG_BOLD :: */
- /* The face is bold. */
- /* */
- /* <Note> */
- /* The style information as provided by FreeType is very basic. More */
- /* details are beyond the scope and should be done on a higher level */
- /* (for example, by analyzing various fields of the `OS/2' table in */
- /* SFNT based fonts). */
- /* */
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_STYLE_FLAG_XXX
+ *
+ * @description:
+ * A list of bit flags to indicate the style of a given face. These are
+ * used in the `style_flags` field of @FT_FaceRec.
+ *
+ * @values:
+ * FT_STYLE_FLAG_ITALIC ::
+ * The face style is italic or oblique.
+ *
+ * FT_STYLE_FLAG_BOLD ::
+ * The face is bold.
+ *
+ * @note:
+ * The style information as provided by FreeType is very basic. More
+ * details are beyond the scope and should be done on a higher level (for
+ * example, by analyzing various fields of the 'OS/2' table in SFNT based
+ * fonts).
+ */
#define FT_STYLE_FLAG_ITALIC ( 1 << 0 )
#define FT_STYLE_FLAG_BOLD ( 1 << 1 )
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_Size_Internal */
- /* */
- /* <Description> */
- /* An opaque handle to an `FT_Size_InternalRec' structure, used to */
- /* model private data of a given @FT_Size object. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Size_Internal
+ *
+ * @description:
+ * An opaque handle to an `FT_Size_InternalRec` structure, used to model
+ * private data of a given @FT_Size object.
+ */
typedef struct FT_Size_InternalRec_* FT_Size_Internal;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_Size_Metrics */
- /* */
- /* <Description> */
- /* The size metrics structure gives the metrics of a size object. */
- /* */
- /* <Fields> */
- /* x_ppem :: The width of the scaled EM square in pixels, hence */
- /* the term `ppem' (pixels per EM). It is also */
- /* referred to as `nominal width'. */
- /* */
- /* y_ppem :: The height of the scaled EM square in pixels, */
- /* hence the term `ppem' (pixels per EM). It is also */
- /* referred to as `nominal height'. */
- /* */
- /* x_scale :: A 16.16 fractional scaling value to convert */
- /* horizontal metrics from font units to 26.6 */
- /* fractional pixels. Only relevant for scalable */
- /* font formats. */
- /* */
- /* y_scale :: A 16.16 fractional scaling value to convert */
- /* vertical metrics from font units to 26.6 */
- /* fractional pixels. Only relevant for scalable */
- /* font formats. */
- /* */
- /* ascender :: The ascender in 26.6 fractional pixels, rounded up */
- /* to an integer value. See @FT_FaceRec for the */
- /* details. */
- /* */
- /* descender :: The descender in 26.6 fractional pixels, rounded */
- /* down to an integer value. See @FT_FaceRec for the */
- /* details. */
- /* */
- /* height :: The height in 26.6 fractional pixels, rounded to */
- /* an integer value. See @FT_FaceRec for the */
- /* details. */
- /* */
- /* max_advance :: The maximum advance width in 26.6 fractional */
- /* pixels, rounded to an integer value. See */
- /* @FT_FaceRec for the details. */
- /* */
- /* <Note> */
- /* The scaling values, if relevant, are determined first during a */
- /* size changing operation. The remaining fields are then set by the */
- /* driver. For scalable formats, they are usually set to scaled */
- /* values of the corresponding fields in @FT_FaceRec. Some values */
- /* like ascender or descender are rounded for historical reasons; */
- /* more precise values (for outline fonts) can be derived by scaling */
- /* the corresponding @FT_FaceRec values manually, with code similar */
- /* to the following. */
- /* */
- /* { */
- /* scaled_ascender = FT_MulFix( face->ascender, */
- /* size_metrics->y_scale ); */
- /* } */
- /* */
- /* Note that due to glyph hinting and the selected rendering mode */
- /* these values are usually not exact; consequently, they must be */
- /* treated as unreliable with an error margin of at least one pixel! */
- /* */
- /* Indeed, the only way to get the exact metrics is to render _all_ */
- /* glyphs. As this would be a definite performance hit, it is up to */
- /* client applications to perform such computations. */
- /* */
- /* The `FT_Size_Metrics' structure is valid for bitmap fonts also. */
- /* */
- /* */
- /* *TrueType* *fonts* *with* *native* *bytecode* *hinting* */
- /* */
- /* All applications that handle TrueType fonts with native hinting */
- /* must be aware that TTFs expect different rounding of vertical font */
- /* dimensions. The application has to cater for this, especially if */
- /* it wants to rely on a TTF's vertical data (for example, to */
- /* properly align box characters vertically). */
- /* */
- /* Only the application knows _in_ _advance_ that it is going to use */
- /* native hinting for TTFs! FreeType, on the other hand, selects the */
- /* hinting mode not at the time of creating an @FT_Size object but */
- /* much later, namely while calling @FT_Load_Glyph. */
- /* */
- /* Here is some pseudo code that illustrates a possible solution. */
- /* */
- /* { */
- /* font_format = FT_Get_Font_Format( face ); */
- /* */
- /* if ( !strcmp( font_format, "TrueType" ) && */
- /* do_native_bytecode_hinting ) */
- /* { */
- /* ascender = ROUND( FT_MulFix( face->ascender, */
- /* size_metrics->y_scale ) ); */
- /* descender = ROUND( FT_MulFix( face->descender, */
- /* size_metrics->y_scale ) ); */
- /* } */
- /* else */
- /* { */
- /* ascender = size_metrics->ascender; */
- /* descender = size_metrics->descender; */
- /* } */
- /* */
- /* height = size_metrics->height; */
- /* max_advance = size_metrics->max_advance; */
- /* } */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Size_Metrics
+ *
+ * @description:
+ * The size metrics structure gives the metrics of a size object.
+ *
+ * @fields:
+ * x_ppem ::
+ * The width of the scaled EM square in pixels, hence the term 'ppem'
+ * (pixels per EM). It is also referred to as 'nominal width'.
+ *
+ * y_ppem ::
+ * The height of the scaled EM square in pixels, hence the term 'ppem'
+ * (pixels per EM). It is also referred to as 'nominal height'.
+ *
+ * x_scale ::
+ * A 16.16 fractional scaling value to convert horizontal metrics from
+ * font units to 26.6 fractional pixels. Only relevant for scalable
+ * font formats.
+ *
+ * y_scale ::
+ * A 16.16 fractional scaling value to convert vertical metrics from
+ * font units to 26.6 fractional pixels. Only relevant for scalable
+ * font formats.
+ *
+ * ascender ::
+ * The ascender in 26.6 fractional pixels, rounded up to an integer
+ * value. See @FT_FaceRec for the details.
+ *
+ * descender ::
+ * The descender in 26.6 fractional pixels, rounded down to an integer
+ * value. See @FT_FaceRec for the details.
+ *
+ * height ::
+ * The height in 26.6 fractional pixels, rounded to an integer value.
+ * See @FT_FaceRec for the details.
+ *
+ * max_advance ::
+ * The maximum advance width in 26.6 fractional pixels, rounded to an
+ * integer value. See @FT_FaceRec for the details.
+ *
+ * @note:
+ * The scaling values, if relevant, are determined first during a size
+ * changing operation. The remaining fields are then set by the driver.
+ * For scalable formats, they are usually set to scaled values of the
+ * corresponding fields in @FT_FaceRec. Some values like ascender or
+ * descender are rounded for historical reasons; more precise values (for
+ * outline fonts) can be derived by scaling the corresponding @FT_FaceRec
+ * values manually, with code similar to the following.
+ *
+ * ```
+ * scaled_ascender = FT_MulFix( face->ascender,
+ * size_metrics->y_scale );
+ * ```
+ *
+ * Note that due to glyph hinting and the selected rendering mode these
+ * values are usually not exact; consequently, they must be treated as
+ * unreliable with an error margin of at least one pixel!
+ *
+ * Indeed, the only way to get the exact metrics is to render _all_
+ * glyphs. As this would be a definite performance hit, it is up to
+ * client applications to perform such computations.
+ *
+ * The `FT_Size_Metrics` structure is valid for bitmap fonts also.
+ *
+ *
+ * **TrueType fonts with native bytecode hinting**
+ *
+ * All applications that handle TrueType fonts with native hinting must
+ * be aware that TTFs expect different rounding of vertical font
+ * dimensions. The application has to cater for this, especially if it
+ * wants to rely on a TTF's vertical data (for example, to properly align
+ * box characters vertically).
+ *
+ * Only the application knows _in advance_ that it is going to use native
+ * hinting for TTFs! FreeType, on the other hand, selects the hinting
+ * mode not at the time of creating an @FT_Size object but much later,
+ * namely while calling @FT_Load_Glyph.
+ *
+ * Here is some pseudo code that illustrates a possible solution.
+ *
+ * ```
+ * font_format = FT_Get_Font_Format( face );
+ *
+ * if ( !strcmp( font_format, "TrueType" ) &&
+ * do_native_bytecode_hinting )
+ * {
+ * ascender = ROUND( FT_MulFix( face->ascender,
+ * size_metrics->y_scale ) );
+ * descender = ROUND( FT_MulFix( face->descender,
+ * size_metrics->y_scale ) );
+ * }
+ * else
+ * {
+ * ascender = size_metrics->ascender;
+ * descender = size_metrics->descender;
+ * }
+ *
+ * height = size_metrics->height;
+ * max_advance = size_metrics->max_advance;
+ * ```
+ */
typedef struct FT_Size_Metrics_
{
FT_UShort x_ppem; /* horizontal pixels per EM */
@@ -1652,25 +1621,27 @@ FT_BEGIN_HEADER
} FT_Size_Metrics;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_SizeRec */
- /* */
- /* <Description> */
- /* FreeType root size class structure. A size object models a face */
- /* object at a given size. */
- /* */
- /* <Fields> */
- /* face :: Handle to the parent face object. */
- /* */
- /* generic :: A typeless pointer, unused by the FreeType library or */
- /* any of its drivers. It can be used by client */
- /* applications to link their own data to each size */
- /* object. */
- /* */
- /* metrics :: Metrics for this size object. This field is read-only. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_SizeRec
+ *
+ * @description:
+ * FreeType root size class structure. A size object models a face
+ * object at a given size.
+ *
+ * @fields:
+ * face ::
+ * Handle to the parent face object.
+ *
+ * generic ::
+ * A typeless pointer, unused by the FreeType library or any of its
+ * drivers. It can be used by client applications to link their own
+ * data to each size object.
+ *
+ * metrics ::
+ * Metrics for this size object. This field is read-only.
+ */
typedef struct FT_SizeRec_
{
FT_Face face; /* parent face object */
@@ -1681,237 +1652,234 @@ FT_BEGIN_HEADER
} FT_SizeRec;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_SubGlyph */
- /* */
- /* <Description> */
- /* The subglyph structure is an internal object used to describe */
- /* subglyphs (for example, in the case of composites). */
- /* */
- /* <Note> */
- /* The subglyph implementation is not part of the high-level API, */
- /* hence the forward structure declaration. */
- /* */
- /* You can however retrieve subglyph information with */
- /* @FT_Get_SubGlyph_Info. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_SubGlyph
+ *
+ * @description:
+ * The subglyph structure is an internal object used to describe
+ * subglyphs (for example, in the case of composites).
+ *
+ * @note:
+ * The subglyph implementation is not part of the high-level API, hence
+ * the forward structure declaration.
+ *
+ * You can however retrieve subglyph information with
+ * @FT_Get_SubGlyph_Info.
+ */
typedef struct FT_SubGlyphRec_* FT_SubGlyph;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_Slot_Internal */
- /* */
- /* <Description> */
- /* An opaque handle to an `FT_Slot_InternalRec' structure, used to */
- /* model private data of a given @FT_GlyphSlot object. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Slot_Internal
+ *
+ * @description:
+ * An opaque handle to an `FT_Slot_InternalRec` structure, used to model
+ * private data of a given @FT_GlyphSlot object.
+ */
typedef struct FT_Slot_InternalRec_* FT_Slot_Internal;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_GlyphSlotRec */
- /* */
- /* <Description> */
- /* FreeType root glyph slot class structure. A glyph slot is a */
- /* container where individual glyphs can be loaded, be they in */
- /* outline or bitmap format. */
- /* */
- /* <Fields> */
- /* library :: A handle to the FreeType library instance */
- /* this slot belongs to. */
- /* */
- /* face :: A handle to the parent face object. */
- /* */
- /* next :: In some cases (like some font tools), several */
- /* glyph slots per face object can be a good */
- /* thing. As this is rare, the glyph slots are */
- /* listed through a direct, single-linked list */
- /* using its `next' field. */
- /* */
- /* generic :: A typeless pointer unused by the FreeType */
- /* library or any of its drivers. It can be */
- /* used by client applications to link their own */
- /* data to each glyph slot object. */
- /* */
- /* metrics :: The metrics of the last loaded glyph in the */
- /* slot. The returned values depend on the last */
- /* load flags (see the @FT_Load_Glyph API */
- /* function) and can be expressed either in 26.6 */
- /* fractional pixels or font units. */
- /* */
- /* Note that even when the glyph image is */
- /* transformed, the metrics are not. */
- /* */
- /* linearHoriAdvance :: The advance width of the unhinted glyph. */
- /* Its value is expressed in 16.16 fractional */
- /* pixels, unless @FT_LOAD_LINEAR_DESIGN is set */
- /* when loading the glyph. This field can be */
- /* important to perform correct WYSIWYG layout. */
- /* Only relevant for outline glyphs. */
- /* */
- /* linearVertAdvance :: The advance height of the unhinted glyph. */
- /* Its value is expressed in 16.16 fractional */
- /* pixels, unless @FT_LOAD_LINEAR_DESIGN is set */
- /* when loading the glyph. This field can be */
- /* important to perform correct WYSIWYG layout. */
- /* Only relevant for outline glyphs. */
- /* */
- /* advance :: This shorthand is, depending on */
- /* @FT_LOAD_IGNORE_TRANSFORM, the transformed */
- /* (hinted) advance width for the glyph, in 26.6 */
- /* fractional pixel format. As specified with */
- /* @FT_LOAD_VERTICAL_LAYOUT, it uses either the */
- /* `horiAdvance' or the `vertAdvance' value of */
- /* `metrics' field. */
- /* */
- /* format :: This field indicates the format of the image */
- /* contained in the glyph slot. Typically */
- /* @FT_GLYPH_FORMAT_BITMAP, */
- /* @FT_GLYPH_FORMAT_OUTLINE, or */
- /* @FT_GLYPH_FORMAT_COMPOSITE, but other values */
- /* are possible. */
- /* */
- /* bitmap :: This field is used as a bitmap descriptor. */
- /* Note that the address and content of the */
- /* bitmap buffer can change between calls of */
- /* @FT_Load_Glyph and a few other functions. */
- /* */
- /* bitmap_left :: The bitmap's left bearing expressed in */
- /* integer pixels. */
- /* */
- /* bitmap_top :: The bitmap's top bearing expressed in integer */
- /* pixels. This is the distance from the */
- /* baseline to the top-most glyph scanline, */
- /* upwards y~coordinates being *positive*. */
- /* */
- /* outline :: The outline descriptor for the current glyph */
- /* image if its format is */
- /* @FT_GLYPH_FORMAT_OUTLINE. Once a glyph is */
- /* loaded, `outline' can be transformed, */
- /* distorted, emboldened, etc. However, it must */
- /* not be freed. */
- /* */
- /* num_subglyphs :: The number of subglyphs in a composite glyph. */
- /* This field is only valid for the composite */
- /* glyph format that should normally only be */
- /* loaded with the @FT_LOAD_NO_RECURSE flag. */
- /* */
- /* subglyphs :: An array of subglyph descriptors for */
- /* composite glyphs. There are `num_subglyphs' */
- /* elements in there. Currently internal to */
- /* FreeType. */
- /* */
- /* control_data :: Certain font drivers can also return the */
- /* control data for a given glyph image (e.g. */
- /* TrueType bytecode, Type~1 charstrings, etc.). */
- /* This field is a pointer to such data; it is */
- /* currently internal to FreeType. */
- /* */
- /* control_len :: This is the length in bytes of the control */
- /* data. Currently internal to FreeType. */
- /* */
- /* other :: Reserved. */
- /* */
- /* lsb_delta :: The difference between hinted and unhinted */
- /* left side bearing while auto-hinting is */
- /* active. Zero otherwise. */
- /* */
- /* rsb_delta :: The difference between hinted and unhinted */
- /* right side bearing while auto-hinting is */
- /* active. Zero otherwise. */
- /* */
- /* <Note> */
- /* If @FT_Load_Glyph is called with default flags (see */
- /* @FT_LOAD_DEFAULT) the glyph image is loaded in the glyph slot in */
- /* its native format (e.g., an outline glyph for TrueType and Type~1 */
- /* formats). [Since 2.9] The prospective bitmap metrics are */
- /* calculated according to @FT_LOAD_TARGET_XXX and other flags even */
- /* for the outline glyph, even if @FT_LOAD_RENDER is not set. */
- /* */
- /* This image can later be converted into a bitmap by calling */
- /* @FT_Render_Glyph. This function searches the current renderer for */
- /* the native image's format, then invokes it. */
- /* */
- /* The renderer is in charge of transforming the native image through */
- /* the slot's face transformation fields, then converting it into a */
- /* bitmap that is returned in `slot->bitmap'. */
- /* */
- /* Note that `slot->bitmap_left' and `slot->bitmap_top' are also used */
- /* to specify the position of the bitmap relative to the current pen */
- /* position (e.g., coordinates (0,0) on the baseline). Of course, */
- /* `slot->format' is also changed to @FT_GLYPH_FORMAT_BITMAP. */
- /* */
- /* Here is a small pseudo code fragment that shows how to use */
- /* `lsb_delta' and `rsb_delta' to do fractional positioning of */
- /* glyphs: */
- /* */
- /* { */
- /* FT_GlyphSlot slot = face->glyph; */
- /* FT_Pos origin_x = 0; */
- /* */
- /* */
- /* for all glyphs do */
- /* <load glyph with `FT_Load_Glyph'> */
- /* */
- /* FT_Outline_Translate( slot->outline, origin_x & 63, 0 ); */
- /* */
- /* <save glyph image, or render glyph, or ...> */
- /* */
- /* <compute kern between current and next glyph */
- /* and add it to `origin_x'> */
- /* */
- /* origin_x += slot->advance.x; */
- /* origin_x += slot->rsb_delta - slot->lsb_delta; */
- /* endfor */
- /* } */
- /* */
- /* Here is another small pseudo code fragment that shows how to use */
- /* `lsb_delta' and `rsb_delta' to improve integer positioning of */
- /* glyphs: */
- /* */
- /* { */
- /* FT_GlyphSlot slot = face->glyph; */
- /* FT_Pos origin_x = 0; */
- /* FT_Pos prev_rsb_delta = 0; */
- /* */
- /* */
- /* for all glyphs do */
- /* <compute kern between current and previous glyph */
- /* and add it to `origin_x'> */
- /* */
- /* <load glyph with `FT_Load_Glyph'> */
- /* */
- /* if ( prev_rsb_delta - slot->lsb_delta > 32 ) */
- /* origin_x -= 64; */
- /* else if ( prev_rsb_delta - slot->lsb_delta < -31 ) */
- /* origin_x += 64; */
- /* */
- /* prev_rsb_delta = slot->rsb_delta; */
- /* */
- /* <save glyph image, or render glyph, or ...> */
- /* */
- /* origin_x += slot->advance.x; */
- /* endfor */
- /* } */
- /* */
- /* If you use strong auto-hinting, you *must* apply these delta */
- /* values! Otherwise you will experience far too large inter-glyph */
- /* spacing at small rendering sizes in most cases. Note that it */
- /* doesn't harm to use the above code for other hinting modes also, */
- /* since the delta values are zero then. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_GlyphSlotRec
+ *
+ * @description:
+ * FreeType root glyph slot class structure. A glyph slot is a container
+ * where individual glyphs can be loaded, be they in outline or bitmap
+ * format.
+ *
+ * @fields:
+ * library ::
+ * A handle to the FreeType library instance this slot belongs to.
+ *
+ * face ::
+ * A handle to the parent face object.
+ *
+ * next ::
+ * In some cases (like some font tools), several glyph slots per face
+ * object can be a good thing. As this is rare, the glyph slots are
+ * listed through a direct, single-linked list using its `next` field.
+ *
+ * glyph_index ::
+ * [Since 2.10] The glyph index passed as an argument to @FT_Load_Glyph
+ * while initializing the glyph slot.
+ *
+ * generic ::
+ * A typeless pointer unused by the FreeType library or any of its
+ * drivers. It can be used by client applications to link their own
+ * data to each glyph slot object.
+ *
+ * metrics ::
+ * The metrics of the last loaded glyph in the slot. The returned
+ * values depend on the last load flags (see the @FT_Load_Glyph API
+ * function) and can be expressed either in 26.6 fractional pixels or
+ * font units.
+ *
+ * Note that even when the glyph image is transformed, the metrics are
+ * not.
+ *
+ * linearHoriAdvance ::
+ * The advance width of the unhinted glyph. Its value is expressed in
+ * 16.16 fractional pixels, unless @FT_LOAD_LINEAR_DESIGN is set when
+ * loading the glyph. This field can be important to perform correct
+ * WYSIWYG layout. Only relevant for outline glyphs.
+ *
+ * linearVertAdvance ::
+ * The advance height of the unhinted glyph. Its value is expressed in
+ * 16.16 fractional pixels, unless @FT_LOAD_LINEAR_DESIGN is set when
+ * loading the glyph. This field can be important to perform correct
+ * WYSIWYG layout. Only relevant for outline glyphs.
+ *
+ * advance ::
+ * This shorthand is, depending on @FT_LOAD_IGNORE_TRANSFORM, the
+ * transformed (hinted) advance width for the glyph, in 26.6 fractional
+ * pixel format. As specified with @FT_LOAD_VERTICAL_LAYOUT, it uses
+ * either the `horiAdvance` or the `vertAdvance` value of `metrics`
+ * field.
+ *
+ * format ::
+ * This field indicates the format of the image contained in the glyph
+ * slot. Typically @FT_GLYPH_FORMAT_BITMAP, @FT_GLYPH_FORMAT_OUTLINE,
+ * or @FT_GLYPH_FORMAT_COMPOSITE, but other values are possible.
+ *
+ * bitmap ::
+ * This field is used as a bitmap descriptor. Note that the address
+ * and content of the bitmap buffer can change between calls of
+ * @FT_Load_Glyph and a few other functions.
+ *
+ * bitmap_left ::
+ * The bitmap's left bearing expressed in integer pixels.
+ *
+ * bitmap_top ::
+ * The bitmap's top bearing expressed in integer pixels. This is the
+ * distance from the baseline to the top-most glyph scanline, upwards
+ * y~coordinates being **positive**.
+ *
+ * outline ::
+ * The outline descriptor for the current glyph image if its format is
+ * @FT_GLYPH_FORMAT_OUTLINE. Once a glyph is loaded, `outline` can be
+ * transformed, distorted, emboldened, etc. However, it must not be
+ * freed.
+ *
+ * num_subglyphs ::
+ * The number of subglyphs in a composite glyph. This field is only
+ * valid for the composite glyph format that should normally only be
+ * loaded with the @FT_LOAD_NO_RECURSE flag.
+ *
+ * subglyphs ::
+ * An array of subglyph descriptors for composite glyphs. There are
+ * `num_subglyphs` elements in there. Currently internal to FreeType.
+ *
+ * control_data ::
+ * Certain font drivers can also return the control data for a given
+ * glyph image (e.g. TrueType bytecode, Type~1 charstrings, etc.).
+ * This field is a pointer to such data; it is currently internal to
+ * FreeType.
+ *
+ * control_len ::
+ * This is the length in bytes of the control data. Currently internal
+ * to FreeType.
+ *
+ * other ::
+ * Reserved.
+ *
+ * lsb_delta ::
+ * The difference between hinted and unhinted left side bearing while
+ * auto-hinting is active. Zero otherwise.
+ *
+ * rsb_delta ::
+ * The difference between hinted and unhinted right side bearing while
+ * auto-hinting is active. Zero otherwise.
+ *
+ * @note:
+ * If @FT_Load_Glyph is called with default flags (see @FT_LOAD_DEFAULT)
+ * the glyph image is loaded in the glyph slot in its native format
+ * (e.g., an outline glyph for TrueType and Type~1 formats). [Since 2.9]
+ * The prospective bitmap metrics are calculated according to
+ * @FT_LOAD_TARGET_XXX and other flags even for the outline glyph, even
+ * if @FT_LOAD_RENDER is not set.
+ *
+ * This image can later be converted into a bitmap by calling
+ * @FT_Render_Glyph. This function searches the current renderer for the
+ * native image's format, then invokes it.
+ *
+ * The renderer is in charge of transforming the native image through the
+ * slot's face transformation fields, then converting it into a bitmap
+ * that is returned in `slot->bitmap`.
+ *
+ * Note that `slot->bitmap_left` and `slot->bitmap_top` are also used to
+ * specify the position of the bitmap relative to the current pen
+ * position (e.g., coordinates (0,0) on the baseline). Of course,
+ * `slot->format` is also changed to @FT_GLYPH_FORMAT_BITMAP.
+ *
+ * Here is a small pseudo code fragment that shows how to use `lsb_delta`
+ * and `rsb_delta` to do fractional positioning of glyphs:
+ *
+ * ```
+ * FT_GlyphSlot slot = face->glyph;
+ * FT_Pos origin_x = 0;
+ *
+ *
+ * for all glyphs do
+ * <load glyph with `FT_Load_Glyph'>
+ *
+ * FT_Outline_Translate( slot->outline, origin_x & 63, 0 );
+ *
+ * <save glyph image, or render glyph, or ...>
+ *
+ * <compute kern between current and next glyph
+ * and add it to `origin_x'>
+ *
+ * origin_x += slot->advance.x;
+ * origin_x += slot->lsb_delta - slot->rsb_delta;
+ * endfor
+ * ```
+ *
+ * Here is another small pseudo code fragment that shows how to use
+ * `lsb_delta` and `rsb_delta` to improve integer positioning of glyphs:
+ *
+ * ```
+ * FT_GlyphSlot slot = face->glyph;
+ * FT_Pos origin_x = 0;
+ * FT_Pos prev_rsb_delta = 0;
+ *
+ *
+ * for all glyphs do
+ * <compute kern between current and previous glyph
+ * and add it to `origin_x'>
+ *
+ * <load glyph with `FT_Load_Glyph'>
+ *
+ * if ( prev_rsb_delta - slot->lsb_delta > 32 )
+ * origin_x -= 64;
+ * else if ( prev_rsb_delta - slot->lsb_delta < -31 )
+ * origin_x += 64;
+ *
+ * prev_rsb_delta = slot->rsb_delta;
+ *
+ * <save glyph image, or render glyph, or ...>
+ *
+ * origin_x += slot->advance.x;
+ * endfor
+ * ```
+ *
+ * If you use strong auto-hinting, you **must** apply these delta values!
+ * Otherwise you will experience far too large inter-glyph spacing at
+ * small rendering sizes in most cases. Note that it doesn't harm to use
+ * the above code for other hinting modes also, since the delta values
+ * are zero then.
+ */
typedef struct FT_GlyphSlotRec_
{
FT_Library library;
FT_Face face;
FT_GlyphSlot next;
- FT_UInt reserved; /* retained for binary compatibility */
+ FT_UInt glyph_index; /* new in 2.10; was reserved previously */
FT_Generic generic;
FT_Glyph_Metrics metrics;
@@ -1952,86 +1920,92 @@ FT_BEGIN_HEADER
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Init_FreeType */
- /* */
- /* <Description> */
- /* Initialize a new FreeType library object. The set of modules */
- /* that are registered by this function is determined at build time. */
- /* */
- /* <Output> */
- /* alibrary :: A handle to a new library object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* In case you want to provide your own memory allocating routines, */
- /* use @FT_New_Library instead, followed by a call to */
- /* @FT_Add_Default_Modules (or a series of calls to @FT_Add_Module) */
- /* and @FT_Set_Default_Properties. */
- /* */
- /* See the documentation of @FT_Library and @FT_Face for */
- /* multi-threading issues. */
- /* */
- /* If you need reference-counting (cf. @FT_Reference_Library), use */
- /* @FT_New_Library and @FT_Done_Library. */
- /* */
- /* If compilation option FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES is */
- /* set, this function reads the `FREETYPE_PROPERTIES' environment */
- /* variable to control driver properties. See section @properties */
- /* for more. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Init_FreeType
+ *
+ * @description:
+ * Initialize a new FreeType library object. The set of modules that are
+ * registered by this function is determined at build time.
+ *
+ * @output:
+ * alibrary ::
+ * A handle to a new library object.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * In case you want to provide your own memory allocating routines, use
+ * @FT_New_Library instead, followed by a call to @FT_Add_Default_Modules
+ * (or a series of calls to @FT_Add_Module) and
+ * @FT_Set_Default_Properties.
+ *
+ * See the documentation of @FT_Library and @FT_Face for multi-threading
+ * issues.
+ *
+ * If you need reference-counting (cf. @FT_Reference_Library), use
+ * @FT_New_Library and @FT_Done_Library.
+ *
+ * If compilation option `FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES` is
+ * set, this function reads the `FREETYPE_PROPERTIES` environment
+ * variable to control driver properties. See section @properties for
+ * more.
+ */
FT_EXPORT( FT_Error )
FT_Init_FreeType( FT_Library *alibrary );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Done_FreeType */
- /* */
- /* <Description> */
- /* Destroy a given FreeType library object and all of its children, */
- /* including resources, drivers, faces, sizes, etc. */
- /* */
- /* <Input> */
- /* library :: A handle to the target library object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Done_FreeType
+ *
+ * @description:
+ * Destroy a given FreeType library object and all of its children,
+ * including resources, drivers, faces, sizes, etc.
+ *
+ * @input:
+ * library ::
+ * A handle to the target library object.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ */
FT_EXPORT( FT_Error )
FT_Done_FreeType( FT_Library library );
- /*************************************************************************/
- /* */
- /* <Enum> */
- /* FT_OPEN_XXX */
- /* */
- /* <Description> */
- /* A list of bit field constants used within the `flags' field of the */
- /* @FT_Open_Args structure. */
- /* */
- /* <Values> */
- /* FT_OPEN_MEMORY :: This is a memory-based stream. */
- /* */
- /* FT_OPEN_STREAM :: Copy the stream from the `stream' field. */
- /* */
- /* FT_OPEN_PATHNAME :: Create a new input stream from a C~path */
- /* name. */
- /* */
- /* FT_OPEN_DRIVER :: Use the `driver' field. */
- /* */
- /* FT_OPEN_PARAMS :: Use the `num_params' and `params' fields. */
- /* */
- /* <Note> */
- /* The `FT_OPEN_MEMORY', `FT_OPEN_STREAM', and `FT_OPEN_PATHNAME' */
- /* flags are mutually exclusive. */
- /* */
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_OPEN_XXX
+ *
+ * @description:
+ * A list of bit field constants used within the `flags` field of the
+ * @FT_Open_Args structure.
+ *
+ * @values:
+ * FT_OPEN_MEMORY ::
+ * This is a memory-based stream.
+ *
+ * FT_OPEN_STREAM ::
+ * Copy the stream from the `stream` field.
+ *
+ * FT_OPEN_PATHNAME ::
+ * Create a new input stream from a C~path name.
+ *
+ * FT_OPEN_DRIVER ::
+ * Use the `driver` field.
+ *
+ * FT_OPEN_PARAMS ::
+ * Use the `num_params` and `params` fields.
+ *
+ * @note:
+ * The `FT_OPEN_MEMORY`, `FT_OPEN_STREAM`, and `FT_OPEN_PATHNAME` flags
+ * are mutually exclusive.
+ */
#define FT_OPEN_MEMORY 0x1
#define FT_OPEN_STREAM 0x2
#define FT_OPEN_PATHNAME 0x4
@@ -2039,7 +2013,7 @@ FT_BEGIN_HEADER
#define FT_OPEN_PARAMS 0x10
- /* these constants are deprecated; use the corresponding `FT_OPEN_XXX' */
+ /* these constants are deprecated; use the corresponding `FT_OPEN_XXX` */
/* values instead */
#define ft_open_memory FT_OPEN_MEMORY
#define ft_open_stream FT_OPEN_STREAM
@@ -2048,24 +2022,26 @@ FT_BEGIN_HEADER
#define ft_open_params FT_OPEN_PARAMS
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_Parameter */
- /* */
- /* <Description> */
- /* A simple structure to pass more or less generic parameters to */
- /* @FT_Open_Face and @FT_Face_Properties. */
- /* */
- /* <Fields> */
- /* tag :: A four-byte identification tag. */
- /* */
- /* data :: A pointer to the parameter data. */
- /* */
- /* <Note> */
- /* The ID and function of parameters are driver-specific. See */
- /* section @parameter_tags for more information. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Parameter
+ *
+ * @description:
+ * A simple structure to pass more or less generic parameters to
+ * @FT_Open_Face and @FT_Face_Properties.
+ *
+ * @fields:
+ * tag ::
+ * A four-byte identification tag.
+ *
+ * data ::
+ * A pointer to the parameter data.
+ *
+ * @note:
+ * The ID and function of parameters are driver-specific. See section
+ * @parameter_tags for more information.
+ */
typedef struct FT_Parameter_
{
FT_ULong tag;
@@ -2074,65 +2050,69 @@ FT_BEGIN_HEADER
} FT_Parameter;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_Open_Args */
- /* */
- /* <Description> */
- /* A structure to indicate how to open a new font file or stream. A */
- /* pointer to such a structure can be used as a parameter for the */
- /* functions @FT_Open_Face and @FT_Attach_Stream. */
- /* */
- /* <Fields> */
- /* flags :: A set of bit flags indicating how to use the */
- /* structure. */
- /* */
- /* memory_base :: The first byte of the file in memory. */
- /* */
- /* memory_size :: The size in bytes of the file in memory. */
- /* */
- /* pathname :: A pointer to an 8-bit file pathname. */
- /* */
- /* stream :: A handle to a source stream object. */
- /* */
- /* driver :: This field is exclusively used by @FT_Open_Face; */
- /* it simply specifies the font driver to use for */
- /* opening the face. If set to NULL, FreeType tries */
- /* to load the face with each one of the drivers in */
- /* its list. */
- /* */
- /* num_params :: The number of extra parameters. */
- /* */
- /* params :: Extra parameters passed to the font driver when */
- /* opening a new face. */
- /* */
- /* <Note> */
- /* The stream type is determined by the contents of `flags' that */
- /* are tested in the following order by @FT_Open_Face: */
- /* */
- /* If the @FT_OPEN_MEMORY bit is set, assume that this is a */
- /* memory file of `memory_size' bytes, located at `memory_address'. */
- /* The data are not copied, and the client is responsible for */
- /* releasing and destroying them _after_ the corresponding call to */
- /* @FT_Done_Face. */
- /* */
- /* Otherwise, if the @FT_OPEN_STREAM bit is set, assume that a */
- /* custom input stream `stream' is used. */
- /* */
- /* Otherwise, if the @FT_OPEN_PATHNAME bit is set, assume that this */
- /* is a normal file and use `pathname' to open it. */
- /* */
- /* If the @FT_OPEN_DRIVER bit is set, @FT_Open_Face only tries to */
- /* open the file with the driver whose handler is in `driver'. */
- /* */
- /* If the @FT_OPEN_PARAMS bit is set, the parameters given by */
- /* `num_params' and `params' is used. They are ignored otherwise. */
- /* */
- /* Ideally, both the `pathname' and `params' fields should be tagged */
- /* as `const'; this is missing for API backward compatibility. In */
- /* other words, applications should treat them as read-only. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Open_Args
+ *
+ * @description:
+ * A structure to indicate how to open a new font file or stream. A
+ * pointer to such a structure can be used as a parameter for the
+ * functions @FT_Open_Face and @FT_Attach_Stream.
+ *
+ * @fields:
+ * flags ::
+ * A set of bit flags indicating how to use the structure.
+ *
+ * memory_base ::
+ * The first byte of the file in memory.
+ *
+ * memory_size ::
+ * The size in bytes of the file in memory.
+ *
+ * pathname ::
+ * A pointer to an 8-bit file pathname.
+ *
+ * stream ::
+ * A handle to a source stream object.
+ *
+ * driver ::
+ * This field is exclusively used by @FT_Open_Face; it simply specifies
+ * the font driver to use for opening the face. If set to `NULL`,
+ * FreeType tries to load the face with each one of the drivers in its
+ * list.
+ *
+ * num_params ::
+ * The number of extra parameters.
+ *
+ * params ::
+ * Extra parameters passed to the font driver when opening a new face.
+ *
+ * @note:
+ * The stream type is determined by the contents of `flags` that are
+ * tested in the following order by @FT_Open_Face:
+ *
+ * If the @FT_OPEN_MEMORY bit is set, assume that this is a memory file
+ * of `memory_size` bytes, located at `memory_address`. The data are not
+ * copied, and the client is responsible for releasing and destroying
+ * them _after_ the corresponding call to @FT_Done_Face.
+ *
+ * Otherwise, if the @FT_OPEN_STREAM bit is set, assume that a custom
+ * input stream `stream` is used.
+ *
+ * Otherwise, if the @FT_OPEN_PATHNAME bit is set, assume that this is a
+ * normal file and use `pathname` to open it.
+ *
+ * If the @FT_OPEN_DRIVER bit is set, @FT_Open_Face only tries to open
+ * the file with the driver whose handler is in `driver`.
+ *
+ * If the @FT_OPEN_PARAMS bit is set, the parameters given by
+ * `num_params` and `params` is used. They are ignored otherwise.
+ *
+ * Ideally, both the `pathname` and `params` fields should be tagged as
+ * 'const'; this is missing for API backward compatibility. In other
+ * words, applications should treat them as read-only.
+ */
typedef struct FT_Open_Args_
{
FT_UInt flags;
@@ -2147,34 +2127,37 @@ FT_BEGIN_HEADER
} FT_Open_Args;
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_New_Face */
- /* */
- /* <Description> */
- /* Call @FT_Open_Face to open a font by its pathname. */
- /* */
- /* <InOut> */
- /* library :: A handle to the library resource. */
- /* */
- /* <Input> */
- /* pathname :: A path to the font file. */
- /* */
- /* face_index :: See @FT_Open_Face for a detailed description of this */
- /* parameter. */
- /* */
- /* <Output> */
- /* aface :: A handle to a new face object. If `face_index' is */
- /* greater than or equal to zero, it must be non-NULL. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* Use @FT_Done_Face to destroy the created @FT_Face object (along */
- /* with its slot and sizes). */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_New_Face
+ *
+ * @description:
+ * Call @FT_Open_Face to open a font by its pathname.
+ *
+ * @inout:
+ * library ::
+ * A handle to the library resource.
+ *
+ * @input:
+ * pathname ::
+ * A path to the font file.
+ *
+ * face_index ::
+ * See @FT_Open_Face for a detailed description of this parameter.
+ *
+ * @output:
+ * aface ::
+ * A handle to a new face object. If `face_index` is greater than or
+ * equal to zero, it must be non-`NULL`.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * Use @FT_Done_Face to destroy the created @FT_Face object (along with
+ * its slot and sizes).
+ */
FT_EXPORT( FT_Error )
FT_New_Face( FT_Library library,
const char* filepathname,
@@ -2182,36 +2165,39 @@ FT_BEGIN_HEADER
FT_Face *aface );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_New_Memory_Face */
- /* */
- /* <Description> */
- /* Call @FT_Open_Face to open a font that has been loaded into */
- /* memory. */
- /* */
- /* <InOut> */
- /* library :: A handle to the library resource. */
- /* */
- /* <Input> */
- /* file_base :: A pointer to the beginning of the font data. */
- /* */
- /* file_size :: The size of the memory chunk used by the font data. */
- /* */
- /* face_index :: See @FT_Open_Face for a detailed description of this */
- /* parameter. */
- /* */
- /* <Output> */
- /* aface :: A handle to a new face object. If `face_index' is */
- /* greater than or equal to zero, it must be non-NULL. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* You must not deallocate the memory before calling @FT_Done_Face. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_New_Memory_Face
+ *
+ * @description:
+ * Call @FT_Open_Face to open a font that has been loaded into memory.
+ *
+ * @inout:
+ * library ::
+ * A handle to the library resource.
+ *
+ * @input:
+ * file_base ::
+ * A pointer to the beginning of the font data.
+ *
+ * file_size ::
+ * The size of the memory chunk used by the font data.
+ *
+ * face_index ::
+ * See @FT_Open_Face for a detailed description of this parameter.
+ *
+ * @output:
+ * aface ::
+ * A handle to a new face object. If `face_index` is greater than or
+ * equal to zero, it must be non-`NULL`.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * You must not deallocate the memory before calling @FT_Done_Face.
+ */
FT_EXPORT( FT_Error )
FT_New_Memory_Face( FT_Library library,
const FT_Byte* file_base,
@@ -2220,147 +2206,143 @@ FT_BEGIN_HEADER
FT_Face *aface );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Open_Face */
- /* */
- /* <Description> */
- /* Create a face object from a given resource described by */
- /* @FT_Open_Args. */
- /* */
- /* <InOut> */
- /* library :: A handle to the library resource. */
- /* */
- /* <Input> */
- /* args :: A pointer to an `FT_Open_Args' structure that must */
- /* be filled by the caller. */
- /* */
- /* face_index :: This field holds two different values. Bits 0-15 */
- /* are the index of the face in the font file (starting */
- /* with value~0). Set it to~0 if there is only one */
- /* face in the font file. */
- /* */
- /* [Since 2.6.1] Bits 16-30 are relevant to GX and */
- /* OpenType variation fonts only, specifying the named */
- /* instance index for the current face index (starting */
- /* with value~1; value~0 makes FreeType ignore named */
- /* instances). For non-variation fonts, bits 16-30 are */
- /* ignored. Assuming that you want to access the third */
- /* named instance in face~4, `face_index' should be set */
- /* to 0x00030004. If you want to access face~4 without */
- /* variation handling, simply set `face_index' to */
- /* value~4. */
- /* */
- /* `FT_Open_Face' and its siblings can be used to */
- /* quickly check whether the font format of a given */
- /* font resource is supported by FreeType. In general, */
- /* if the `face_index' argument is negative, the */
- /* function's return value is~0 if the font format is */
- /* recognized, or non-zero otherwise. The function */
- /* allocates a more or less empty face handle in */
- /* `*aface' (if `aface' isn't NULL); the only two */
- /* useful fields in this special case are */
- /* `face->num_faces' and `face->style_flags'. For any */
- /* negative value of `face_index', `face->num_faces' */
- /* gives the number of faces within the font file. For */
- /* the negative value `-(N+1)' (with `N' a non-negative */
- /* 16-bit value), bits 16-30 in `face->style_flags' */
- /* give the number of named instances in face `N' if we */
- /* have a variation font (or zero otherwise). After */
- /* examination, the returned @FT_Face structure should */
- /* be deallocated with a call to @FT_Done_Face. */
- /* */
- /* <Output> */
- /* aface :: A handle to a new face object. If `face_index' is */
- /* greater than or equal to zero, it must be non-NULL. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* Unlike FreeType 1.x, this function automatically creates a glyph */
- /* slot for the face object that can be accessed directly through */
- /* `face->glyph'. */
- /* */
- /* Each new face object created with this function also owns a */
- /* default @FT_Size object, accessible as `face->size'. */
- /* */
- /* One @FT_Library instance can have multiple face objects, this is, */
- /* @FT_Open_Face and its siblings can be called multiple times using */
- /* the same `library' argument. */
- /* */
- /* See the discussion of reference counters in the description of */
- /* @FT_Reference_Face. */
- /* */
- /* To loop over all faces, use code similar to the following snippet */
- /* (omitting the error handling). */
- /* */
- /* { */
- /* ... */
- /* FT_Face face; */
- /* FT_Long i, num_faces; */
- /* */
- /* */
- /* error = FT_Open_Face( library, args, -1, &face ); */
- /* if ( error ) { ... } */
- /* */
- /* num_faces = face->num_faces; */
- /* FT_Done_Face( face ); */
- /* */
- /* for ( i = 0; i < num_faces; i++ ) */
- /* { */
- /* ... */
- /* error = FT_Open_Face( library, args, i, &face ); */
- /* ... */
- /* FT_Done_Face( face ); */
- /* ... */
- /* } */
- /* } */
- /* */
- /* To loop over all valid values for `face_index', use something */
- /* similar to the following snippet, again without error handling. */
- /* The code accesses all faces immediately (thus only a single call */
- /* of `FT_Open_Face' within the do-loop), with and without named */
- /* instances. */
- /* */
- /* { */
- /* ... */
- /* FT_Face face; */
- /* */
- /* FT_Long num_faces = 0; */
- /* FT_Long num_instances = 0; */
- /* */
- /* FT_Long face_idx = 0; */
- /* FT_Long instance_idx = 0; */
- /* */
- /* */
- /* do */
- /* { */
- /* FT_Long id = ( instance_idx << 16 ) + face_idx; */
- /* */
- /* */
- /* error = FT_Open_Face( library, args, id, &face ); */
- /* if ( error ) { ... } */
- /* */
- /* num_faces = face->num_faces; */
- /* num_instances = face->style_flags >> 16; */
- /* */
- /* ... */
- /* */
- /* FT_Done_Face( face ); */
- /* */
- /* if ( instance_idx < num_instances ) */
- /* instance_idx++; */
- /* else */
- /* { */
- /* face_idx++; */
- /* instance_idx = 0; */
- /* } */
- /* */
- /* } while ( face_idx < num_faces ) */
- /* } */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Open_Face
+ *
+ * @description:
+ * Create a face object from a given resource described by @FT_Open_Args.
+ *
+ * @inout:
+ * library ::
+ * A handle to the library resource.
+ *
+ * @input:
+ * args ::
+ * A pointer to an `FT_Open_Args` structure that must be filled by the
+ * caller.
+ *
+ * face_index ::
+ * This field holds two different values. Bits 0-15 are the index of
+ * the face in the font file (starting with value~0). Set it to~0 if
+ * there is only one face in the font file.
+ *
+ * [Since 2.6.1] Bits 16-30 are relevant to GX and OpenType variation
+ * fonts only, specifying the named instance index for the current face
+ * index (starting with value~1; value~0 makes FreeType ignore named
+ * instances). For non-variation fonts, bits 16-30 are ignored.
+ * Assuming that you want to access the third named instance in face~4,
+ * `face_index` should be set to 0x00030004. If you want to access
+ * face~4 without variation handling, simply set `face_index` to
+ * value~4.
+ *
+ * `FT_Open_Face` and its siblings can be used to quickly check whether
+ * the font format of a given font resource is supported by FreeType.
+ * In general, if the `face_index` argument is negative, the function's
+ * return value is~0 if the font format is recognized, or non-zero
+ * otherwise. The function allocates a more or less empty face handle
+ * in `*aface` (if `aface` isn't `NULL`); the only two useful fields in
+ * this special case are `face->num_faces` and `face->style_flags`.
+ * For any negative value of `face_index`, `face->num_faces` gives the
+ * number of faces within the font file. For the negative value
+ * '-(N+1)' (with 'N' a non-negative 16-bit value), bits 16-30 in
+ * `face->style_flags` give the number of named instances in face 'N'
+ * if we have a variation font (or zero otherwise). After examination,
+ * the returned @FT_Face structure should be deallocated with a call to
+ * @FT_Done_Face.
+ *
+ * @output:
+ * aface ::
+ * A handle to a new face object. If `face_index` is greater than or
+ * equal to zero, it must be non-`NULL`.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * Unlike FreeType 1.x, this function automatically creates a glyph slot
+ * for the face object that can be accessed directly through
+ * `face->glyph`.
+ *
+ * Each new face object created with this function also owns a default
+ * @FT_Size object, accessible as `face->size`.
+ *
+ * One @FT_Library instance can have multiple face objects, this is,
+ * @FT_Open_Face and its siblings can be called multiple times using the
+ * same `library` argument.
+ *
+ * See the discussion of reference counters in the description of
+ * @FT_Reference_Face.
+ *
+ * @example:
+ * To loop over all faces, use code similar to the following snippet
+ * (omitting the error handling).
+ *
+ * ```
+ * ...
+ * FT_Face face;
+ * FT_Long i, num_faces;
+ *
+ *
+ * error = FT_Open_Face( library, args, -1, &face );
+ * if ( error ) { ... }
+ *
+ * num_faces = face->num_faces;
+ * FT_Done_Face( face );
+ *
+ * for ( i = 0; i < num_faces; i++ )
+ * {
+ * ...
+ * error = FT_Open_Face( library, args, i, &face );
+ * ...
+ * FT_Done_Face( face );
+ * ...
+ * }
+ * ```
+ *
+ * To loop over all valid values for `face_index`, use something similar
+ * to the following snippet, again without error handling. The code
+ * accesses all faces immediately (thus only a single call of
+ * `FT_Open_Face` within the do-loop), with and without named instances.
+ *
+ * ```
+ * ...
+ * FT_Face face;
+ *
+ * FT_Long num_faces = 0;
+ * FT_Long num_instances = 0;
+ *
+ * FT_Long face_idx = 0;
+ * FT_Long instance_idx = 0;
+ *
+ *
+ * do
+ * {
+ * FT_Long id = ( instance_idx << 16 ) + face_idx;
+ *
+ *
+ * error = FT_Open_Face( library, args, id, &face );
+ * if ( error ) { ... }
+ *
+ * num_faces = face->num_faces;
+ * num_instances = face->style_flags >> 16;
+ *
+ * ...
+ *
+ * FT_Done_Face( face );
+ *
+ * if ( instance_idx < num_instances )
+ * instance_idx++;
+ * else
+ * {
+ * face_idx++;
+ * instance_idx = 0;
+ * }
+ *
+ * } while ( face_idx < num_faces )
+ * ```
+ */
FT_EXPORT( FT_Error )
FT_Open_Face( FT_Library library,
const FT_Open_Args* args,
@@ -2368,204 +2350,208 @@ FT_BEGIN_HEADER
FT_Face *aface );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Attach_File */
- /* */
- /* <Description> */
- /* Call @FT_Attach_Stream to attach a file. */
- /* */
- /* <InOut> */
- /* face :: The target face object. */
- /* */
- /* <Input> */
- /* filepathname :: The pathname. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Attach_File
+ *
+ * @description:
+ * Call @FT_Attach_Stream to attach a file.
+ *
+ * @inout:
+ * face ::
+ * The target face object.
+ *
+ * @input:
+ * filepathname ::
+ * The pathname.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ */
FT_EXPORT( FT_Error )
FT_Attach_File( FT_Face face,
const char* filepathname );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Attach_Stream */
- /* */
- /* <Description> */
- /* `Attach' data to a face object. Normally, this is used to read */
- /* additional information for the face object. For example, you can */
- /* attach an AFM file that comes with a Type~1 font to get the */
- /* kerning values and other metrics. */
- /* */
- /* <InOut> */
- /* face :: The target face object. */
- /* */
- /* <Input> */
- /* parameters :: A pointer to @FT_Open_Args that must be filled by */
- /* the caller. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* The meaning of the `attach' (i.e., what really happens when the */
- /* new file is read) is not fixed by FreeType itself. It really */
- /* depends on the font format (and thus the font driver). */
- /* */
- /* Client applications are expected to know what they are doing */
- /* when invoking this function. Most drivers simply do not implement */
- /* file or stream attachments. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Attach_Stream
+ *
+ * @description:
+ * 'Attach' data to a face object. Normally, this is used to read
+ * additional information for the face object. For example, you can
+ * attach an AFM file that comes with a Type~1 font to get the kerning
+ * values and other metrics.
+ *
+ * @inout:
+ * face ::
+ * The target face object.
+ *
+ * @input:
+ * parameters ::
+ * A pointer to @FT_Open_Args that must be filled by the caller.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The meaning of the 'attach' (i.e., what really happens when the new
+ * file is read) is not fixed by FreeType itself. It really depends on
+ * the font format (and thus the font driver).
+ *
+ * Client applications are expected to know what they are doing when
+ * invoking this function. Most drivers simply do not implement file or
+ * stream attachments.
+ */
FT_EXPORT( FT_Error )
FT_Attach_Stream( FT_Face face,
FT_Open_Args* parameters );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Reference_Face */
- /* */
- /* <Description> */
- /* A counter gets initialized to~1 at the time an @FT_Face structure */
- /* is created. This function increments the counter. @FT_Done_Face */
- /* then only destroys a face if the counter is~1, otherwise it simply */
- /* decrements the counter. */
- /* */
- /* This function helps in managing life-cycles of structures that */
- /* reference @FT_Face objects. */
- /* */
- /* <Input> */
- /* face :: A handle to a target face object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Since> */
- /* 2.4.2 */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Reference_Face
+ *
+ * @description:
+ * A counter gets initialized to~1 at the time an @FT_Face structure is
+ * created. This function increments the counter. @FT_Done_Face then
+ * only destroys a face if the counter is~1, otherwise it simply
+ * decrements the counter.
+ *
+ * This function helps in managing life-cycles of structures that
+ * reference @FT_Face objects.
+ *
+ * @input:
+ * face ::
+ * A handle to a target face object.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @since:
+ * 2.4.2
+ */
FT_EXPORT( FT_Error )
FT_Reference_Face( FT_Face face );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Done_Face */
- /* */
- /* <Description> */
- /* Discard a given face object, as well as all of its child slots and */
- /* sizes. */
- /* */
- /* <Input> */
- /* face :: A handle to a target face object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* See the discussion of reference counters in the description of */
- /* @FT_Reference_Face. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Done_Face
+ *
+ * @description:
+ * Discard a given face object, as well as all of its child slots and
+ * sizes.
+ *
+ * @input:
+ * face ::
+ * A handle to a target face object.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * See the discussion of reference counters in the description of
+ * @FT_Reference_Face.
+ */
FT_EXPORT( FT_Error )
FT_Done_Face( FT_Face face );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Select_Size */
- /* */
- /* <Description> */
- /* Select a bitmap strike. To be more precise, this function sets */
- /* the scaling factors of the active @FT_Size object in a face so */
- /* that bitmaps from this particular strike are taken by */
- /* @FT_Load_Glyph and friends. */
- /* */
- /* <InOut> */
- /* face :: A handle to a target face object. */
- /* */
- /* <Input> */
- /* strike_index :: The index of the bitmap strike in the */
- /* `available_sizes' field of @FT_FaceRec structure. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* For bitmaps embedded in outline fonts it is common that only a */
- /* subset of the available glyphs at a given ppem value is available. */
- /* FreeType silently uses outlines if there is no bitmap for a given */
- /* glyph index. */
- /* */
- /* For GX and OpenType variation fonts, a bitmap strike makes sense */
- /* only if the default instance is active (this is, no glyph */
- /* variation takes place); otherwise, FreeType simply ignores bitmap */
- /* strikes. The same is true for all named instances that are */
- /* different from the default instance. */
- /* */
- /* Don't use this function if you are using the FreeType cache API. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Select_Size
+ *
+ * @description:
+ * Select a bitmap strike. To be more precise, this function sets the
+ * scaling factors of the active @FT_Size object in a face so that
+ * bitmaps from this particular strike are taken by @FT_Load_Glyph and
+ * friends.
+ *
+ * @inout:
+ * face ::
+ * A handle to a target face object.
+ *
+ * @input:
+ * strike_index ::
+ * The index of the bitmap strike in the `available_sizes` field of
+ * @FT_FaceRec structure.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * For bitmaps embedded in outline fonts it is common that only a subset
+ * of the available glyphs at a given ppem value is available. FreeType
+ * silently uses outlines if there is no bitmap for a given glyph index.
+ *
+ * For GX and OpenType variation fonts, a bitmap strike makes sense only
+ * if the default instance is active (this is, no glyph variation takes
+ * place); otherwise, FreeType simply ignores bitmap strikes. The same
+ * is true for all named instances that are different from the default
+ * instance.
+ *
+ * Don't use this function if you are using the FreeType cache API.
+ */
FT_EXPORT( FT_Error )
FT_Select_Size( FT_Face face,
FT_Int strike_index );
- /*************************************************************************/
- /* */
- /* <Enum> */
- /* FT_Size_Request_Type */
- /* */
- /* <Description> */
- /* An enumeration type that lists the supported size request types, */
- /* i.e., what input size (in font units) maps to the requested output */
- /* size (in pixels, as computed from the arguments of */
- /* @FT_Size_Request). */
- /* */
- /* <Values> */
- /* FT_SIZE_REQUEST_TYPE_NOMINAL :: */
- /* The nominal size. The `units_per_EM' field of @FT_FaceRec is */
- /* used to determine both scaling values. */
- /* */
- /* This is the standard scaling found in most applications. In */
- /* particular, use this size request type for TrueType fonts if */
- /* they provide optical scaling or something similar. Note, */
- /* however, that `units_per_EM' is a rather abstract value which */
- /* bears no relation to the actual size of the glyphs in a font. */
- /* */
- /* FT_SIZE_REQUEST_TYPE_REAL_DIM :: */
- /* The real dimension. The sum of the `ascender' and (minus of) */
- /* the `descender' fields of @FT_FaceRec is used to determine both */
- /* scaling values. */
- /* */
- /* FT_SIZE_REQUEST_TYPE_BBOX :: */
- /* The font bounding box. The width and height of the `bbox' field */
- /* of @FT_FaceRec are used to determine the horizontal and vertical */
- /* scaling value, respectively. */
- /* */
- /* FT_SIZE_REQUEST_TYPE_CELL :: */
- /* The `max_advance_width' field of @FT_FaceRec is used to */
- /* determine the horizontal scaling value; the vertical scaling */
- /* value is determined the same way as */
- /* @FT_SIZE_REQUEST_TYPE_REAL_DIM does. Finally, both scaling */
- /* values are set to the smaller one. This type is useful if you */
- /* want to specify the font size for, say, a window of a given */
- /* dimension and 80x24 cells. */
- /* */
- /* FT_SIZE_REQUEST_TYPE_SCALES :: */
- /* Specify the scaling values directly. */
- /* */
- /* <Note> */
- /* The above descriptions only apply to scalable formats. For bitmap */
- /* formats, the behaviour is up to the driver. */
- /* */
- /* See the note section of @FT_Size_Metrics if you wonder how size */
- /* requesting relates to scaling values. */
- /* */
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_Size_Request_Type
+ *
+ * @description:
+ * An enumeration type that lists the supported size request types, i.e.,
+ * what input size (in font units) maps to the requested output size (in
+ * pixels, as computed from the arguments of @FT_Size_Request).
+ *
+ * @values:
+ * FT_SIZE_REQUEST_TYPE_NOMINAL ::
+ * The nominal size. The `units_per_EM` field of @FT_FaceRec is used
+ * to determine both scaling values.
+ *
+ * This is the standard scaling found in most applications. In
+ * particular, use this size request type for TrueType fonts if they
+ * provide optical scaling or something similar. Note, however, that
+ * `units_per_EM` is a rather abstract value which bears no relation to
+ * the actual size of the glyphs in a font.
+ *
+ * FT_SIZE_REQUEST_TYPE_REAL_DIM ::
+ * The real dimension. The sum of the `ascender` and (minus of) the
+ * `descender` fields of @FT_FaceRec is used to determine both scaling
+ * values.
+ *
+ * FT_SIZE_REQUEST_TYPE_BBOX ::
+ * The font bounding box. The width and height of the `bbox` field of
+ * @FT_FaceRec are used to determine the horizontal and vertical
+ * scaling value, respectively.
+ *
+ * FT_SIZE_REQUEST_TYPE_CELL ::
+ * The `max_advance_width` field of @FT_FaceRec is used to determine
+ * the horizontal scaling value; the vertical scaling value is
+ * determined the same way as @FT_SIZE_REQUEST_TYPE_REAL_DIM does.
+ * Finally, both scaling values are set to the smaller one. This type
+ * is useful if you want to specify the font size for, say, a window of
+ * a given dimension and 80x24 cells.
+ *
+ * FT_SIZE_REQUEST_TYPE_SCALES ::
+ * Specify the scaling values directly.
+ *
+ * @note:
+ * The above descriptions only apply to scalable formats. For bitmap
+ * formats, the behaviour is up to the driver.
+ *
+ * See the note section of @FT_Size_Metrics if you wonder how size
+ * requesting relates to scaling values.
+ */
typedef enum FT_Size_Request_Type_
{
FT_SIZE_REQUEST_TYPE_NOMINAL,
@@ -2579,42 +2565,45 @@ FT_BEGIN_HEADER
} FT_Size_Request_Type;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_Size_RequestRec */
- /* */
- /* <Description> */
- /* A structure to model a size request. */
- /* */
- /* <Fields> */
- /* type :: See @FT_Size_Request_Type. */
- /* */
- /* width :: The desired width, given as a 26.6 fractional */
- /* point value (with 72pt = 1in). */
- /* */
- /* height :: The desired height, given as a 26.6 fractional */
- /* point value (with 72pt = 1in). */
- /* */
- /* horiResolution :: The horizontal resolution (dpi, i.e., pixels per */
- /* inch). If set to zero, `width' is treated as a */
- /* 26.6 fractional *pixel* value, which gets */
- /* internally rounded to an integer. */
- /* */
- /* vertResolution :: The vertical resolution (dpi, i.e., pixels per */
- /* inch). If set to zero, `height' is treated as a */
- /* 26.6 fractional *pixel* value, which gets */
- /* internally rounded to an integer. */
- /* */
- /* <Note> */
- /* If `width' is zero, the horizontal scaling value is set equal */
- /* to the vertical scaling value, and vice versa. */
- /* */
- /* If `type' is FT_SIZE_REQUEST_TYPE_SCALES, `width' and `height' are */
- /* interpreted directly as 16.16 fractional scaling values, without */
- /* any further modification, and both `horiResolution' and */
- /* `vertResolution' are ignored. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Size_RequestRec
+ *
+ * @description:
+ * A structure to model a size request.
+ *
+ * @fields:
+ * type ::
+ * See @FT_Size_Request_Type.
+ *
+ * width ::
+ * The desired width, given as a 26.6 fractional point value (with 72pt
+ * = 1in).
+ *
+ * height ::
+ * The desired height, given as a 26.6 fractional point value (with
+ * 72pt = 1in).
+ *
+ * horiResolution ::
+ * The horizontal resolution (dpi, i.e., pixels per inch). If set to
+ * zero, `width` is treated as a 26.6 fractional **pixel** value, which
+ * gets internally rounded to an integer.
+ *
+ * vertResolution ::
+ * The vertical resolution (dpi, i.e., pixels per inch). If set to
+ * zero, `height` is treated as a 26.6 fractional **pixel** value,
+ * which gets internally rounded to an integer.
+ *
+ * @note:
+ * If `width` is zero, the horizontal scaling value is set equal to the
+ * vertical scaling value, and vice versa.
+ *
+ * If `type` is `FT_SIZE_REQUEST_TYPE_SCALES`, `width` and `height` are
+ * interpreted directly as 16.16 fractional scaling values, without any
+ * further modification, and both `horiResolution` and `vertResolution`
+ * are ignored.
+ */
typedef struct FT_Size_RequestRec_
{
FT_Size_Request_Type type;
@@ -2626,96 +2615,102 @@ FT_BEGIN_HEADER
} FT_Size_RequestRec;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_Size_Request */
- /* */
- /* <Description> */
- /* A handle to a size request structure. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Size_Request
+ *
+ * @description:
+ * A handle to a size request structure.
+ */
typedef struct FT_Size_RequestRec_ *FT_Size_Request;
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Request_Size */
- /* */
- /* <Description> */
- /* Resize the scale of the active @FT_Size object in a face. */
- /* */
- /* <InOut> */
- /* face :: A handle to a target face object. */
- /* */
- /* <Input> */
- /* req :: A pointer to a @FT_Size_RequestRec. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* Although drivers may select the bitmap strike matching the */
- /* request, you should not rely on this if you intend to select a */
- /* particular bitmap strike. Use @FT_Select_Size instead in that */
- /* case. */
- /* */
- /* The relation between the requested size and the resulting glyph */
- /* size is dependent entirely on how the size is defined in the */
- /* source face. The font designer chooses the final size of each */
- /* glyph relative to this size. For more information refer to */
- /* `https://www.freetype.org/freetype2/docs/glyphs/glyphs-2.html'. */
- /* */
- /* Contrary to @FT_Set_Char_Size, this function doesn't have special */
- /* code to normalize zero-valued widths, heights, or resolutions */
- /* (which lead to errors in most cases). */
- /* */
- /* Don't use this function if you are using the FreeType cache API. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Request_Size
+ *
+ * @description:
+ * Resize the scale of the active @FT_Size object in a face.
+ *
+ * @inout:
+ * face ::
+ * A handle to a target face object.
+ *
+ * @input:
+ * req ::
+ * A pointer to a @FT_Size_RequestRec.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * Although drivers may select the bitmap strike matching the request,
+ * you should not rely on this if you intend to select a particular
+ * bitmap strike. Use @FT_Select_Size instead in that case.
+ *
+ * The relation between the requested size and the resulting glyph size
+ * is dependent entirely on how the size is defined in the source face.
+ * The font designer chooses the final size of each glyph relative to
+ * this size. For more information refer to
+ * 'https://www.freetype.org/freetype2/docs/glyphs/glyphs-2.html'.
+ *
+ * Contrary to @FT_Set_Char_Size, this function doesn't have special code
+ * to normalize zero-valued widths, heights, or resolutions (which lead
+ * to errors in most cases).
+ *
+ * Don't use this function if you are using the FreeType cache API.
+ */
FT_EXPORT( FT_Error )
FT_Request_Size( FT_Face face,
FT_Size_Request req );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Set_Char_Size */
- /* */
- /* <Description> */
- /* Call @FT_Request_Size to request the nominal size (in points). */
- /* */
- /* <InOut> */
- /* face :: A handle to a target face object. */
- /* */
- /* <Input> */
- /* char_width :: The nominal width, in 26.6 fractional points. */
- /* */
- /* char_height :: The nominal height, in 26.6 fractional points. */
- /* */
- /* horz_resolution :: The horizontal resolution in dpi. */
- /* */
- /* vert_resolution :: The vertical resolution in dpi. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* While this function allows fractional points as input values, the */
- /* resulting ppem value for the given resolution is always rounded to */
- /* the nearest integer. */
- /* */
- /* If either the character width or height is zero, it is set equal */
- /* to the other value. */
- /* */
- /* If either the horizontal or vertical resolution is zero, it is set */
- /* equal to the other value. */
- /* */
- /* A character width or height smaller than 1pt is set to 1pt; if */
- /* both resolution values are zero, they are set to 72dpi. */
- /* */
- /* Don't use this function if you are using the FreeType cache API. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Set_Char_Size
+ *
+ * @description:
+ * Call @FT_Request_Size to request the nominal size (in points).
+ *
+ * @inout:
+ * face ::
+ * A handle to a target face object.
+ *
+ * @input:
+ * char_width ::
+ * The nominal width, in 26.6 fractional points.
+ *
+ * char_height ::
+ * The nominal height, in 26.6 fractional points.
+ *
+ * horz_resolution ::
+ * The horizontal resolution in dpi.
+ *
+ * vert_resolution ::
+ * The vertical resolution in dpi.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * While this function allows fractional points as input values, the
+ * resulting ppem value for the given resolution is always rounded to the
+ * nearest integer.
+ *
+ * If either the character width or height is zero, it is set equal to
+ * the other value.
+ *
+ * If either the horizontal or vertical resolution is zero, it is set
+ * equal to the other value.
+ *
+ * A character width or height smaller than 1pt is set to 1pt; if both
+ * resolution values are zero, they are set to 72dpi.
+ *
+ * Don't use this function if you are using the FreeType cache API.
+ */
FT_EXPORT( FT_Error )
FT_Set_Char_Size( FT_Face face,
FT_F26Dot6 char_width,
@@ -2724,134 +2719,138 @@ FT_BEGIN_HEADER
FT_UInt vert_resolution );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Set_Pixel_Sizes */
- /* */
- /* <Description> */
- /* Call @FT_Request_Size to request the nominal size (in pixels). */
- /* */
- /* <InOut> */
- /* face :: A handle to the target face object. */
- /* */
- /* <Input> */
- /* pixel_width :: The nominal width, in pixels. */
- /* */
- /* pixel_height :: The nominal height, in pixels. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* You should not rely on the resulting glyphs matching or being */
- /* constrained to this pixel size. Refer to @FT_Request_Size to */
- /* understand how requested sizes relate to actual sizes. */
- /* */
- /* Don't use this function if you are using the FreeType cache API. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Set_Pixel_Sizes
+ *
+ * @description:
+ * Call @FT_Request_Size to request the nominal size (in pixels).
+ *
+ * @inout:
+ * face ::
+ * A handle to the target face object.
+ *
+ * @input:
+ * pixel_width ::
+ * The nominal width, in pixels.
+ *
+ * pixel_height ::
+ * The nominal height, in pixels.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * You should not rely on the resulting glyphs matching or being
+ * constrained to this pixel size. Refer to @FT_Request_Size to
+ * understand how requested sizes relate to actual sizes.
+ *
+ * Don't use this function if you are using the FreeType cache API.
+ */
FT_EXPORT( FT_Error )
FT_Set_Pixel_Sizes( FT_Face face,
FT_UInt pixel_width,
FT_UInt pixel_height );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Load_Glyph */
- /* */
- /* <Description> */
- /* Load a glyph into the glyph slot of a face object. */
- /* */
- /* <InOut> */
- /* face :: A handle to the target face object where the glyph */
- /* is loaded. */
- /* */
- /* <Input> */
- /* glyph_index :: The index of the glyph in the font file. For */
- /* CID-keyed fonts (either in PS or in CFF format) */
- /* this argument specifies the CID value. */
- /* */
- /* load_flags :: A flag indicating what to load for this glyph. The */
- /* @FT_LOAD_XXX constants can be used to control the */
- /* glyph loading process (e.g., whether the outline */
- /* should be scaled, whether to load bitmaps or not, */
- /* whether to hint the outline, etc). */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* The loaded glyph may be transformed. See @FT_Set_Transform for */
- /* the details. */
- /* */
- /* For subsetted CID-keyed fonts, `FT_Err_Invalid_Argument' is */
- /* returned for invalid CID values (this is, for CID values that */
- /* don't have a corresponding glyph in the font). See the discussion */
- /* of the @FT_FACE_FLAG_CID_KEYED flag for more details. */
- /* */
- /* If you receive `FT_Err_Glyph_Too_Big', try getting the glyph */
- /* outline at EM size, then scale it manually and fill it as a */
- /* graphics operation. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Load_Glyph
+ *
+ * @description:
+ * Load a glyph into the glyph slot of a face object.
+ *
+ * @inout:
+ * face ::
+ * A handle to the target face object where the glyph is loaded.
+ *
+ * @input:
+ * glyph_index ::
+ * The index of the glyph in the font file. For CID-keyed fonts
+ * (either in PS or in CFF format) this argument specifies the CID
+ * value.
+ *
+ * load_flags ::
+ * A flag indicating what to load for this glyph. The @FT_LOAD_XXX
+ * constants can be used to control the glyph loading process (e.g.,
+ * whether the outline should be scaled, whether to load bitmaps or
+ * not, whether to hint the outline, etc).
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The loaded glyph may be transformed. See @FT_Set_Transform for the
+ * details.
+ *
+ * For subsetted CID-keyed fonts, `FT_Err_Invalid_Argument` is returned
+ * for invalid CID values (this is, for CID values that don't have a
+ * corresponding glyph in the font). See the discussion of the
+ * @FT_FACE_FLAG_CID_KEYED flag for more details.
+ *
+ * If you receive `FT_Err_Glyph_Too_Big`, try getting the glyph outline
+ * at EM size, then scale it manually and fill it as a graphics
+ * operation.
+ */
FT_EXPORT( FT_Error )
FT_Load_Glyph( FT_Face face,
FT_UInt glyph_index,
FT_Int32 load_flags );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Load_Char */
- /* */
- /* <Description> */
- /* Load a glyph into the glyph slot of a face object, accessed by its */
- /* character code. */
- /* */
- /* <InOut> */
- /* face :: A handle to a target face object where the glyph */
- /* is loaded. */
- /* */
- /* <Input> */
- /* char_code :: The glyph's character code, according to the */
- /* current charmap used in the face. */
- /* */
- /* load_flags :: A flag indicating what to load for this glyph. The */
- /* @FT_LOAD_XXX constants can be used to control the */
- /* glyph loading process (e.g., whether the outline */
- /* should be scaled, whether to load bitmaps or not, */
- /* whether to hint the outline, etc). */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* This function simply calls @FT_Get_Char_Index and @FT_Load_Glyph. */
- /* */
- /* Many fonts contain glyphs that can't be loaded by this function */
- /* since its glyph indices are not listed in any of the font's */
- /* charmaps. */
- /* */
- /* If no active cmap is set up (i.e., `face->charmap' is zero), the */
- /* call to @FT_Get_Char_Index is omitted, and the function behaves */
- /* identically to @FT_Load_Glyph. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Load_Char
+ *
+ * @description:
+ * Load a glyph into the glyph slot of a face object, accessed by its
+ * character code.
+ *
+ * @inout:
+ * face ::
+ * A handle to a target face object where the glyph is loaded.
+ *
+ * @input:
+ * char_code ::
+ * The glyph's character code, according to the current charmap used in
+ * the face.
+ *
+ * load_flags ::
+ * A flag indicating what to load for this glyph. The @FT_LOAD_XXX
+ * constants can be used to control the glyph loading process (e.g.,
+ * whether the outline should be scaled, whether to load bitmaps or
+ * not, whether to hint the outline, etc).
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * This function simply calls @FT_Get_Char_Index and @FT_Load_Glyph.
+ *
+ * Many fonts contain glyphs that can't be loaded by this function since
+ * its glyph indices are not listed in any of the font's charmaps.
+ *
+ * If no active cmap is set up (i.e., `face->charmap` is zero), the call
+ * to @FT_Get_Char_Index is omitted, and the function behaves identically
+ * to @FT_Load_Glyph.
+ */
FT_EXPORT( FT_Error )
FT_Load_Char( FT_Face face,
FT_ULong char_code,
FT_Int32 load_flags );
- /*************************************************************************
+ /**************************************************************************
*
* @enum:
* FT_LOAD_XXX
*
* @description:
- * A list of bit field constants for @FT_Load_Glyph to indicate what
- * kind of operations to perform during glyph loading.
+ * A list of bit field constants for @FT_Load_Glyph to indicate what kind
+ * of operations to perform during glyph loading.
*
* @values:
* FT_LOAD_DEFAULT ::
@@ -2859,15 +2858,14 @@ FT_BEGIN_HEADER
* operation. In this case, the following happens:
*
* 1. FreeType looks for a bitmap for the glyph corresponding to the
- * face's current size. If one is found, the function returns.
- * The bitmap data can be accessed from the glyph slot (see note
- * below).
+ * face's current size. If one is found, the function returns. The
+ * bitmap data can be accessed from the glyph slot (see note below).
*
* 2. If no embedded bitmap is searched for or found, FreeType looks
- * for a scalable outline. If one is found, it is loaded from
- * the font file, scaled to device pixels, then `hinted' to the
- * pixel grid in order to optimize it. The outline data can be
- * accessed from the glyph slot (see note below).
+ * for a scalable outline. If one is found, it is loaded from the font
+ * file, scaled to device pixels, then 'hinted' to the pixel grid in
+ * order to optimize it. The outline data can be accessed from the
+ * glyph slot (see note below).
*
* Note that by default the glyph loader doesn't render outlines into
* bitmaps. The following flags are used to modify this default
@@ -2879,14 +2877,14 @@ FT_BEGIN_HEADER
* This flag implies @FT_LOAD_NO_HINTING and @FT_LOAD_NO_BITMAP, and
* unsets @FT_LOAD_RENDER.
*
- * If the font is `tricky' (see @FT_FACE_FLAG_TRICKY for more), using
- * FT_LOAD_NO_SCALE usually yields meaningless outlines because the
- * subglyphs must be scaled and positioned with hinting instructions.
- * This can be solved by loading the font without FT_LOAD_NO_SCALE and
- * setting the character size to `font->units_per_EM'.
+ * If the font is 'tricky' (see @FT_FACE_FLAG_TRICKY for more), using
+ * `FT_LOAD_NO_SCALE` usually yields meaningless outlines because the
+ * subglyphs must be scaled and positioned with hinting instructions.
+ * This can be solved by loading the font without `FT_LOAD_NO_SCALE`
+ * and setting the character size to `font->units_per_EM`.
*
* FT_LOAD_NO_HINTING ::
- * Disable hinting. This generally generates `blurrier' bitmap glyphs
+ * Disable hinting. This generally generates 'blurrier' bitmap glyphs
* when the glyph are rendered in any of the anti-aliased modes. See
* also the note below.
*
@@ -2907,34 +2905,37 @@ FT_BEGIN_HEADER
*
* FT_LOAD_VERTICAL_LAYOUT ::
* Load the glyph for vertical text layout. In particular, the
- * `advance' value in the @FT_GlyphSlotRec structure is set to the
- * `vertAdvance' value of the `metrics' field.
+ * `advance` value in the @FT_GlyphSlotRec structure is set to the
+ * `vertAdvance` value of the `metrics` field.
*
- * In case @FT_HAS_VERTICAL doesn't return true, you shouldn't use
- * this flag currently. Reason is that in this case vertical metrics
- * get synthesized, and those values are not always consistent across
+ * In case @FT_HAS_VERTICAL doesn't return true, you shouldn't use this
+ * flag currently. Reason is that in this case vertical metrics get
+ * synthesized, and those values are not always consistent across
* various font formats.
*
* FT_LOAD_FORCE_AUTOHINT ::
- * Prefer the auto-hinter over the font's native hinter. See also
- * the note below.
+ * Prefer the auto-hinter over the font's native hinter. See also the
+ * note below.
*
* FT_LOAD_PEDANTIC ::
* Make the font driver perform pedantic verifications during glyph
- * loading. This is mostly used to detect broken glyphs in fonts.
- * By default, FreeType tries to handle broken fonts also.
+ * loading and hinting. This is mostly used to detect broken glyphs in
+ * fonts. By default, FreeType tries to handle broken fonts also.
*
* In particular, errors from the TrueType bytecode engine are not
- * passed to the application if this flag is not set; this might
- * result in partially hinted or distorted glyphs in case a glyph's
- * bytecode is buggy.
+ * passed to the application if this flag is not set; this might result
+ * in partially hinted or distorted glyphs in case a glyph's bytecode
+ * is buggy.
*
* FT_LOAD_NO_RECURSE ::
- * Don't load composite glyphs recursively. Instead, the font
- * driver should set the `num_subglyph' and `subglyphs' values of
- * the glyph slot accordingly, and set `glyph->format' to
- * @FT_GLYPH_FORMAT_COMPOSITE. The description of subglyphs can
- * then be accessed with @FT_Get_SubGlyph_Info.
+ * Don't load composite glyphs recursively. Instead, the font driver
+ * fills the `num_subglyph` and `subglyphs` values of the glyph slot;
+ * it also sets `glyph->format` to @FT_GLYPH_FORMAT_COMPOSITE. The
+ * description of subglyphs can then be accessed with
+ * @FT_Get_SubGlyph_Info.
+ *
+ * Don't use this flag for retrieving metrics information since some
+ * font drivers only return rudimentary data.
*
* This flag implies @FT_LOAD_NO_SCALE and @FT_LOAD_IGNORE_TRANSFORM.
*
@@ -2951,23 +2952,35 @@ FT_BEGIN_HEADER
* monochrome-optimized hinting algorithm is used.
*
* FT_LOAD_LINEAR_DESIGN ::
- * Keep `linearHoriAdvance' and `linearVertAdvance' fields of
- * @FT_GlyphSlotRec in font units. See @FT_GlyphSlotRec for
- * details.
+ * Keep `linearHoriAdvance` and `linearVertAdvance` fields of
+ * @FT_GlyphSlotRec in font units. See @FT_GlyphSlotRec for details.
*
* FT_LOAD_NO_AUTOHINT ::
* Disable the auto-hinter. See also the note below.
*
* FT_LOAD_COLOR ::
+ * Load colored glyphs. There are slight differences depending on the
+ * font format.
+ *
* [Since 2.5] Load embedded color bitmap images. The resulting color
- * bitmaps, if available, will have the @FT_PIXEL_MODE_BGRA format.
- * If the flag is not set and color bitmaps are found, they are
- * converted to 256-level gray bitmaps transparently, using the
- * @FT_PIXEL_MODE_GRAY format.
+ * bitmaps, if available, will have the @FT_PIXEL_MODE_BGRA format,
+ * with pre-multiplied color channels. If the flag is not set and
+ * color bitmaps are found, they are converted to 256-level gray
+ * bitmaps, using the @FT_PIXEL_MODE_GRAY format.
+ *
+ * [Since 2.10, experimental] If the glyph index contains an entry in
+ * the face's 'COLR' table with a 'CPAL' palette table (as defined in
+ * the OpenType specification), make @FT_Render_Glyph provide a default
+ * blending of the color glyph layers associated with the glyph index,
+ * using the same bitmap format as embedded color bitmap images. This
+ * is mainly for convenience; for full control of color layers use
+ * @FT_Get_Color_Glyph_Layer and FreeType's color functions like
+ * @FT_Palette_Select instead of setting @FT_LOAD_COLOR for rendering
+ * so that the client application can handle blending by itself.
*
* FT_LOAD_COMPUTE_METRICS ::
- * [Since 2.6.1] Compute glyph metrics from the glyph data, without
- * the use of bundled metrics tables (for example, the `hdmx' table in
+ * [Since 2.6.1] Compute glyph metrics from the glyph data, without the
+ * use of bundled metrics tables (for example, the 'hdmx' table in
* TrueType fonts). This flag is mainly used by font validating or
* font editing applications, which need to ignore, verify, or edit
* those tables.
@@ -2976,9 +2989,9 @@ FT_BEGIN_HEADER
*
* FT_LOAD_BITMAP_METRICS_ONLY ::
* [Since 2.7.1] Request loading of the metrics and bitmap image
- * information of a (possibly embedded) bitmap glyph without
- * allocating or copying the bitmap image data itself. No effect if
- * the target glyph is not a bitmap image.
+ * information of a (possibly embedded) bitmap glyph without allocating
+ * or copying the bitmap image data itself. No effect if the target
+ * glyph is not a bitmap image.
*
* This flag unsets @FT_LOAD_RENDER.
*
@@ -2993,8 +3006,8 @@ FT_BEGIN_HEADER
* @FT_FACE_FLAG_HINTER) is preferred over the auto-hinter. You can
* disable hinting by setting @FT_LOAD_NO_HINTING or change the
* precedence by setting @FT_LOAD_FORCE_AUTOHINT. You can also set
- * @FT_LOAD_NO_AUTOHINT in case you don't want the auto-hinter to be
- * used at all.
+ * @FT_LOAD_NO_AUTOHINT in case you don't want the auto-hinter to be used
+ * at all.
*
* See the description of @FT_FACE_FLAG_TRICKY for a special exception
* (affecting only a handful of Asian fonts).
@@ -3005,7 +3018,7 @@ FT_BEGIN_HEADER
* Note that the auto-hinter needs a valid Unicode cmap (either a native
* one or synthesized by FreeType) for producing correct results. If a
* font provides an incorrect mapping (for example, assigning the
- * character code U+005A, LATIN CAPITAL LETTER Z, to a glyph depicting a
+ * character code U+005A, LATIN CAPITAL LETTER~Z, to a glyph depicting a
* mathematical integral sign), the auto-hinter might produce useless
* results.
*
@@ -3025,7 +3038,7 @@ FT_BEGIN_HEADER
#define FT_LOAD_MONOCHROME ( 1L << 12 )
#define FT_LOAD_LINEAR_DESIGN ( 1L << 13 )
#define FT_LOAD_NO_AUTOHINT ( 1L << 15 )
- /* Bits 16-19 are used by `FT_LOAD_TARGET_' */
+ /* Bits 16-19 are used by `FT_LOAD_TARGET_` */
#define FT_LOAD_COLOR ( 1L << 20 )
#define FT_LOAD_COMPUTE_METRICS ( 1L << 21 )
#define FT_LOAD_BITMAP_METRICS_ONLY ( 1L << 22 )
@@ -3044,19 +3057,17 @@ FT_BEGIN_HEADER
*
* @description:
* A list of values to select a specific hinting algorithm for the
- * hinter. You should OR one of these values to your `load_flags'
- * when calling @FT_Load_Glyph.
+ * hinter. You should OR one of these values to your `load_flags` when
+ * calling @FT_Load_Glyph.
*
- * Note that a font's native hinters may ignore the hinting algorithm
- * you have specified (e.g., the TrueType bytecode interpreter). You
- * can set @FT_LOAD_FORCE_AUTOHINT to ensure that the auto-hinter is
- * used.
+ * Note that a font's native hinters may ignore the hinting algorithm you
+ * have specified (e.g., the TrueType bytecode interpreter). You can set
+ * @FT_LOAD_FORCE_AUTOHINT to ensure that the auto-hinter is used.
*
* @values:
* FT_LOAD_TARGET_NORMAL ::
* The default hinting algorithm, optimized for standard gray-level
- * rendering. For monochrome output, use @FT_LOAD_TARGET_MONO
- * instead.
+ * rendering. For monochrome output, use @FT_LOAD_TARGET_MONO instead.
*
* FT_LOAD_TARGET_LIGHT ::
* A lighter hinting algorithm for gray-level modes. Many generated
@@ -3069,13 +3080,13 @@ FT_BEGIN_HEADER
* auto-hinter.
*
* Advance widths are rounded to integer values; however, using the
- * `lsb_delta' and `rsb_delta' fields of @FT_GlyphSlotRec, it is
+ * `lsb_delta` and `rsb_delta` fields of @FT_GlyphSlotRec, it is
* possible to get fractional advance widths for subpixel positioning
* (which is recommended to use).
*
- * If configuration option AF_CONFIG_OPTION_TT_SIZE_METRICS is active,
- * TrueType-like metrics are used to make this mode behave similarly
- * as in unpatched FreeType versions between 2.4.6 and 2.7.1
+ * If configuration option `AF_CONFIG_OPTION_TT_SIZE_METRICS` is
+ * active, TrueType-like metrics are used to make this mode behave
+ * similarly as in unpatched FreeType versions between 2.4.6 and 2.7.1
* (inclusive).
*
* FT_LOAD_TARGET_MONO ::
@@ -3083,6 +3094,12 @@ FT_BEGIN_HEADER
* output. The result is probably unpleasant if the glyph is rendered
* in non-monochrome modes.
*
+ * Note that for outline fonts only the TrueType font driver has proper
+ * monochrome hinting support, provided the TTFs contain hints for B/W
+ * rendering (which most fonts no longer provide). If these conditions
+ * are not met it is very likely that you get ugly results at smaller
+ * sizes.
+ *
* FT_LOAD_TARGET_LCD ::
* A variant of @FT_LOAD_TARGET_LIGHT optimized for horizontally
* decimated LCD displays.
@@ -3092,25 +3109,25 @@ FT_BEGIN_HEADER
* decimated LCD displays.
*
* @note:
- * You should use only _one_ of the FT_LOAD_TARGET_XXX values in your
- * `load_flags'. They can't be ORed.
+ * You should use only _one_ of the `FT_LOAD_TARGET_XXX` values in your
+ * `load_flags`. They can't be ORed.
*
* If @FT_LOAD_RENDER is also set, the glyph is rendered in the
* corresponding mode (i.e., the mode that matches the used algorithm
- * best). An exception is FT_LOAD_TARGET_MONO since it implies
+ * best). An exception is `FT_LOAD_TARGET_MONO` since it implies
* @FT_LOAD_MONOCHROME.
*
* You can use a hinting algorithm that doesn't correspond to the same
- * rendering mode. As an example, it is possible to use the `light'
+ * rendering mode. As an example, it is possible to use the 'light'
* hinting algorithm and have the results rendered in horizontal LCD
* pixel mode, with code like
*
- * {
- * FT_Load_Glyph( face, glyph_index,
- * load_flags | FT_LOAD_TARGET_LIGHT );
+ * ```
+ * FT_Load_Glyph( face, glyph_index,
+ * load_flags | FT_LOAD_TARGET_LIGHT );
*
- * FT_Render_Glyph( face->glyph, FT_RENDER_MODE_LCD );
- * }
+ * FT_Render_Glyph( face->glyph, FT_RENDER_MODE_LCD );
+ * ```
*
* In general, you should stick with one rendering mode. For example,
* switching between @FT_LOAD_TARGET_NORMAL and @FT_LOAD_TARGET_MONO
@@ -3142,98 +3159,98 @@ FT_BEGIN_HEADER
#define FT_LOAD_TARGET_MODE( x ) ( (FT_Render_Mode)( ( (x) >> 16 ) & 15 ) )
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Set_Transform */
- /* */
- /* <Description> */
- /* Set the transformation that is applied to glyph images when they */
- /* are loaded into a glyph slot through @FT_Load_Glyph. */
- /* */
- /* <InOut> */
- /* face :: A handle to the source face object. */
- /* */
- /* <Input> */
- /* matrix :: A pointer to the transformation's 2x2 matrix. Use NULL */
- /* for the identity matrix. */
- /* delta :: A pointer to the translation vector. Use NULL for the */
- /* null vector. */
- /* */
- /* <Note> */
- /* The transformation is only applied to scalable image formats after */
- /* the glyph has been loaded. It means that hinting is unaltered by */
- /* the transformation and is performed on the character size given in */
- /* the last call to @FT_Set_Char_Size or @FT_Set_Pixel_Sizes. */
- /* */
- /* Note that this also transforms the `face.glyph.advance' field, but */
- /* *not* the values in `face.glyph.metrics'. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Set_Transform
+ *
+ * @description:
+ * Set the transformation that is applied to glyph images when they are
+ * loaded into a glyph slot through @FT_Load_Glyph.
+ *
+ * @inout:
+ * face ::
+ * A handle to the source face object.
+ *
+ * @input:
+ * matrix ::
+ * A pointer to the transformation's 2x2 matrix. Use `NULL` for the
+ * identity matrix.
+ * delta ::
+ * A pointer to the translation vector. Use `NULL` for the null vector.
+ *
+ * @note:
+ * The transformation is only applied to scalable image formats after the
+ * glyph has been loaded. It means that hinting is unaltered by the
+ * transformation and is performed on the character size given in the
+ * last call to @FT_Set_Char_Size or @FT_Set_Pixel_Sizes.
+ *
+ * Note that this also transforms the `face.glyph.advance` field, but
+ * **not** the values in `face.glyph.metrics`.
+ */
FT_EXPORT( void )
FT_Set_Transform( FT_Face face,
FT_Matrix* matrix,
FT_Vector* delta );
- /*************************************************************************/
- /* */
- /* <Enum> */
- /* FT_Render_Mode */
- /* */
- /* <Description> */
- /* Render modes supported by FreeType~2. Each mode corresponds to a */
- /* specific type of scanline conversion performed on the outline. */
- /* */
- /* For bitmap fonts and embedded bitmaps the `bitmap->pixel_mode' */
- /* field in the @FT_GlyphSlotRec structure gives the format of the */
- /* returned bitmap. */
- /* */
- /* All modes except @FT_RENDER_MODE_MONO use 256 levels of opacity, */
- /* indicating pixel coverage. Use linear alpha blending and gamma */
- /* correction to correctly render non-monochrome glyph bitmaps onto a */
- /* surface; see @FT_Render_Glyph. */
- /* */
- /* <Values> */
- /* FT_RENDER_MODE_NORMAL :: */
- /* Default render mode; it corresponds to 8-bit anti-aliased */
- /* bitmaps. */
- /* */
- /* FT_RENDER_MODE_LIGHT :: */
- /* This is equivalent to @FT_RENDER_MODE_NORMAL. It is only */
- /* defined as a separate value because render modes are also used */
- /* indirectly to define hinting algorithm selectors. See */
- /* @FT_LOAD_TARGET_XXX for details. */
- /* */
- /* FT_RENDER_MODE_MONO :: */
- /* This mode corresponds to 1-bit bitmaps (with 2~levels of */
- /* opacity). */
- /* */
- /* FT_RENDER_MODE_LCD :: */
- /* This mode corresponds to horizontal RGB and BGR subpixel */
- /* displays like LCD screens. It produces 8-bit bitmaps that are */
- /* 3~times the width of the original glyph outline in pixels, and */
- /* which use the @FT_PIXEL_MODE_LCD mode. */
- /* */
- /* FT_RENDER_MODE_LCD_V :: */
- /* This mode corresponds to vertical RGB and BGR subpixel displays */
- /* (like PDA screens, rotated LCD displays, etc.). It produces */
- /* 8-bit bitmaps that are 3~times the height of the original */
- /* glyph outline in pixels and use the @FT_PIXEL_MODE_LCD_V mode. */
- /* */
- /* <Note> */
- /* Should you define FT_CONFIG_OPTION_SUBPIXEL_RENDERING in your */
- /* `ftoption.h', which enables patented ClearType-style rendering, */
- /* the LCD-optimized glyph bitmaps should be filtered to reduce color */
- /* fringes inherent to this technology. You can either set up LCD */
- /* filtering with @FT_Library_SetLcdFilter or @FT_Face_Properties, */
- /* or do the filtering yourself. The default FreeType LCD rendering */
- /* technology does not require filtering. */
- /* */
- /* The selected render mode only affects vector glyphs of a font. */
- /* Embedded bitmaps often have a different pixel mode like */
- /* @FT_PIXEL_MODE_MONO. You can use @FT_Bitmap_Convert to transform */
- /* them into 8-bit pixmaps. */
- /* */
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_Render_Mode
+ *
+ * @description:
+ * Render modes supported by FreeType~2. Each mode corresponds to a
+ * specific type of scanline conversion performed on the outline.
+ *
+ * For bitmap fonts and embedded bitmaps the `bitmap->pixel_mode` field
+ * in the @FT_GlyphSlotRec structure gives the format of the returned
+ * bitmap.
+ *
+ * All modes except @FT_RENDER_MODE_MONO use 256 levels of opacity,
+ * indicating pixel coverage. Use linear alpha blending and gamma
+ * correction to correctly render non-monochrome glyph bitmaps onto a
+ * surface; see @FT_Render_Glyph.
+ *
+ * @values:
+ * FT_RENDER_MODE_NORMAL ::
+ * Default render mode; it corresponds to 8-bit anti-aliased bitmaps.
+ *
+ * FT_RENDER_MODE_LIGHT ::
+ * This is equivalent to @FT_RENDER_MODE_NORMAL. It is only defined as
+ * a separate value because render modes are also used indirectly to
+ * define hinting algorithm selectors. See @FT_LOAD_TARGET_XXX for
+ * details.
+ *
+ * FT_RENDER_MODE_MONO ::
+ * This mode corresponds to 1-bit bitmaps (with 2~levels of opacity).
+ *
+ * FT_RENDER_MODE_LCD ::
+ * This mode corresponds to horizontal RGB and BGR subpixel displays
+ * like LCD screens. It produces 8-bit bitmaps that are 3~times the
+ * width of the original glyph outline in pixels, and which use the
+ * @FT_PIXEL_MODE_LCD mode.
+ *
+ * FT_RENDER_MODE_LCD_V ::
+ * This mode corresponds to vertical RGB and BGR subpixel displays
+ * (like PDA screens, rotated LCD displays, etc.). It produces 8-bit
+ * bitmaps that are 3~times the height of the original glyph outline in
+ * pixels and use the @FT_PIXEL_MODE_LCD_V mode.
+ *
+ * @note:
+ * Should you define `FT_CONFIG_OPTION_SUBPIXEL_RENDERING` in your
+ * `ftoption.h`, which enables patented ClearType-style rendering, the
+ * LCD-optimized glyph bitmaps should be filtered to reduce color fringes
+ * inherent to this technology. You can either set up LCD filtering with
+ * @FT_Library_SetLcdFilter or @FT_Face_Properties, or do the filtering
+ * yourself. The default FreeType LCD rendering technology does not
+ * require filtering.
+ *
+ * The selected render mode only affects vector glyphs of a font.
+ * Embedded bitmaps often have a different pixel mode like
+ * @FT_PIXEL_MODE_MONO. You can use @FT_Bitmap_Convert to transform them
+ * into 8-bit pixmaps.
+ */
typedef enum FT_Render_Mode_
{
FT_RENDER_MODE_NORMAL = 0,
@@ -3248,147 +3265,149 @@ FT_BEGIN_HEADER
/* these constants are deprecated; use the corresponding */
- /* `FT_Render_Mode' values instead */
+ /* `FT_Render_Mode` values instead */
#define ft_render_mode_normal FT_RENDER_MODE_NORMAL
#define ft_render_mode_mono FT_RENDER_MODE_MONO
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Render_Glyph */
- /* */
- /* <Description> */
- /* Convert a given glyph image to a bitmap. It does so by inspecting */
- /* the glyph image format, finding the relevant renderer, and */
- /* invoking it. */
- /* */
- /* <InOut> */
- /* slot :: A handle to the glyph slot containing the image to */
- /* convert. */
- /* */
- /* <Input> */
- /* render_mode :: The render mode used to render the glyph image into */
- /* a bitmap. See @FT_Render_Mode for a list of */
- /* possible values. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* To get meaningful results, font scaling values must be set with */
- /* functions like @FT_Set_Char_Size before calling `FT_Render_Glyph'. */
- /* */
- /* When FreeType outputs a bitmap of a glyph, it really outputs an */
- /* alpha coverage map. If a pixel is completely covered by a */
- /* filled-in outline, the bitmap contains 0xFF at that pixel, meaning */
- /* that 0xFF/0xFF fraction of that pixel is covered, meaning the */
- /* pixel is 100% black (or 0% bright). If a pixel is only 50% */
- /* covered (value 0x80), the pixel is made 50% black (50% bright or a */
- /* middle shade of grey). 0% covered means 0% black (100% bright or */
- /* white). */
- /* */
- /* On high-DPI screens like on smartphones and tablets, the pixels */
- /* are so small that their chance of being completely covered and */
- /* therefore completely black are fairly good. On the low-DPI */
- /* screens, however, the situation is different. The pixels are too */
- /* large for most of the details of a glyph and shades of gray are */
- /* the norm rather than the exception. */
- /* */
- /* This is relevant because all our screens have a second problem: */
- /* they are not linear. 1~+~1 is not~2. Twice the value does not */
- /* result in twice the brightness. When a pixel is only 50% covered, */
- /* the coverage map says 50% black, and this translates to a pixel */
- /* value of 128 when you use 8~bits per channel (0-255). However, */
- /* this does not translate to 50% brightness for that pixel on our */
- /* sRGB and gamma~2.2 screens. Due to their non-linearity, they */
- /* dwell longer in the darks and only a pixel value of about 186 */
- /* results in 50% brightness -- 128 ends up too dark on both bright */
- /* and dark backgrounds. The net result is that dark text looks */
- /* burnt-out, pixely and blotchy on bright background, bright text */
- /* too frail on dark backgrounds, and colored text on colored */
- /* background (for example, red on green) seems to have dark halos or */
- /* `dirt' around it. The situation is especially ugly for diagonal */
- /* stems like in `w' glyph shapes where the quality of FreeType's */
- /* anti-aliasing depends on the correct display of grays. On */
- /* high-DPI screens where smaller, fully black pixels reign supreme, */
- /* this doesn't matter, but on our low-DPI screens with all the gray */
- /* shades, it does. 0% and 100% brightness are the same things in */
- /* linear and non-linear space, just all the shades in-between */
- /* aren't. */
- /* */
- /* The blending function for placing text over a background is */
- /* */
- /* { */
- /* dst = alpha * src + (1 - alpha) * dst , */
- /* } */
- /* */
- /* which is known as the OVER operator. */
- /* */
- /* To correctly composite an antialiased pixel of a glyph onto a */
- /* surface, */
- /* */
- /* 1. take the foreground and background colors (e.g., in sRGB space) */
- /* and apply gamma to get them in a linear space, */
- /* */
- /* 2. use OVER to blend the two linear colors using the glyph pixel */
- /* as the alpha value (remember, the glyph bitmap is an alpha */
- /* coverage bitmap), and */
- /* */
- /* 3. apply inverse gamma to the blended pixel and write it back to */
- /* the image. */
- /* */
- /* Internal testing at Adobe found that a target inverse gamma of~1.8 */
- /* for step~3 gives good results across a wide range of displays with */
- /* an sRGB gamma curve or a similar one. */
- /* */
- /* This process can cost performance. There is an approximation that */
- /* does not need to know about the background color; see */
- /* https://bel.fi/alankila/lcd/ and */
- /* https://bel.fi/alankila/lcd/alpcor.html for details. */
- /* */
- /* *ATTENTION*: Linear blending is even more important when dealing */
- /* with subpixel-rendered glyphs to prevent color-fringing! A */
- /* subpixel-rendered glyph must first be filtered with a filter that */
- /* gives equal weight to the three color primaries and does not */
- /* exceed a sum of 0x100, see section @lcd_filtering. Then the */
- /* only difference to gray linear blending is that subpixel-rendered */
- /* linear blending is done 3~times per pixel: red foreground subpixel */
- /* to red background subpixel and so on for green and blue. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Render_Glyph
+ *
+ * @description:
+ * Convert a given glyph image to a bitmap. It does so by inspecting the
+ * glyph image format, finding the relevant renderer, and invoking it.
+ *
+ * @inout:
+ * slot ::
+ * A handle to the glyph slot containing the image to convert.
+ *
+ * @input:
+ * render_mode ::
+ * The render mode used to render the glyph image into a bitmap. See
+ * @FT_Render_Mode for a list of possible values.
+ *
+ * If @FT_RENDER_MODE_NORMAL is used, a previous call of @FT_Load_Glyph
+ * with flag @FT_LOAD_COLOR makes FT_Render_Glyph provide a default
+ * blending of colored glyph layers associated with the current glyph
+ * slot (provided the font contains such layers) instead of rendering
+ * the glyph slot's outline. This is an experimental feature; see
+ * @FT_LOAD_COLOR for more information.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * To get meaningful results, font scaling values must be set with
+ * functions like @FT_Set_Char_Size before calling `FT_Render_Glyph`.
+ *
+ * When FreeType outputs a bitmap of a glyph, it really outputs an alpha
+ * coverage map. If a pixel is completely covered by a filled-in
+ * outline, the bitmap contains 0xFF at that pixel, meaning that
+ * 0xFF/0xFF fraction of that pixel is covered, meaning the pixel is 100%
+ * black (or 0% bright). If a pixel is only 50% covered (value 0x80),
+ * the pixel is made 50% black (50% bright or a middle shade of grey).
+ * 0% covered means 0% black (100% bright or white).
+ *
+ * On high-DPI screens like on smartphones and tablets, the pixels are so
+ * small that their chance of being completely covered and therefore
+ * completely black are fairly good. On the low-DPI screens, however,
+ * the situation is different. The pixels are too large for most of the
+ * details of a glyph and shades of gray are the norm rather than the
+ * exception.
+ *
+ * This is relevant because all our screens have a second problem: they
+ * are not linear. 1~+~1 is not~2. Twice the value does not result in
+ * twice the brightness. When a pixel is only 50% covered, the coverage
+ * map says 50% black, and this translates to a pixel value of 128 when
+ * you use 8~bits per channel (0-255). However, this does not translate
+ * to 50% brightness for that pixel on our sRGB and gamma~2.2 screens.
+ * Due to their non-linearity, they dwell longer in the darks and only a
+ * pixel value of about 186 results in 50% brightness -- 128 ends up too
+ * dark on both bright and dark backgrounds. The net result is that dark
+ * text looks burnt-out, pixely and blotchy on bright background, bright
+ * text too frail on dark backgrounds, and colored text on colored
+ * background (for example, red on green) seems to have dark halos or
+ * 'dirt' around it. The situation is especially ugly for diagonal stems
+ * like in 'w' glyph shapes where the quality of FreeType's anti-aliasing
+ * depends on the correct display of grays. On high-DPI screens where
+ * smaller, fully black pixels reign supreme, this doesn't matter, but on
+ * our low-DPI screens with all the gray shades, it does. 0% and 100%
+ * brightness are the same things in linear and non-linear space, just
+ * all the shades in-between aren't.
+ *
+ * The blending function for placing text over a background is
+ *
+ * ```
+ * dst = alpha * src + (1 - alpha) * dst ,
+ * ```
+ *
+ * which is known as the OVER operator.
+ *
+ * To correctly composite an antialiased pixel of a glyph onto a surface,
+ *
+ * 1. take the foreground and background colors (e.g., in sRGB space)
+ * and apply gamma to get them in a linear space,
+ *
+ * 2. use OVER to blend the two linear colors using the glyph pixel
+ * as the alpha value (remember, the glyph bitmap is an alpha coverage
+ * bitmap), and
+ *
+ * 3. apply inverse gamma to the blended pixel and write it back to
+ * the image.
+ *
+ * Internal testing at Adobe found that a target inverse gamma of~1.8 for
+ * step~3 gives good results across a wide range of displays with an sRGB
+ * gamma curve or a similar one.
+ *
+ * This process can cost performance. There is an approximation that
+ * does not need to know about the background color; see
+ * https://bel.fi/alankila/lcd/ and
+ * https://bel.fi/alankila/lcd/alpcor.html for details.
+ *
+ * **ATTENTION**: Linear blending is even more important when dealing
+ * with subpixel-rendered glyphs to prevent color-fringing! A
+ * subpixel-rendered glyph must first be filtered with a filter that
+ * gives equal weight to the three color primaries and does not exceed a
+ * sum of 0x100, see section @lcd_rendering. Then the only difference to
+ * gray linear blending is that subpixel-rendered linear blending is done
+ * 3~times per pixel: red foreground subpixel to red background subpixel
+ * and so on for green and blue.
+ */
FT_EXPORT( FT_Error )
FT_Render_Glyph( FT_GlyphSlot slot,
FT_Render_Mode render_mode );
- /*************************************************************************/
- /* */
- /* <Enum> */
- /* FT_Kerning_Mode */
- /* */
- /* <Description> */
- /* An enumeration to specify the format of kerning values returned by */
- /* @FT_Get_Kerning. */
- /* */
- /* <Values> */
- /* FT_KERNING_DEFAULT :: Return grid-fitted kerning distances in */
- /* 26.6 fractional pixels. */
- /* */
- /* FT_KERNING_UNFITTED :: Return un-grid-fitted kerning distances in */
- /* 26.6 fractional pixels. */
- /* */
- /* FT_KERNING_UNSCALED :: Return the kerning vector in original font */
- /* units. */
- /* */
- /* <Note> */
- /* FT_KERNING_DEFAULT returns full pixel values; it also makes */
- /* FreeType heuristically scale down kerning distances at small ppem */
- /* values so that they don't become too big. */
- /* */
- /* Both FT_KERNING_DEFAULT and FT_KERNING_UNFITTED use the current */
- /* horizontal scaling factor (as set e.g. with @FT_Set_Char_Size) to */
- /* convert font units to pixels. */
- /* */
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_Kerning_Mode
+ *
+ * @description:
+ * An enumeration to specify the format of kerning values returned by
+ * @FT_Get_Kerning.
+ *
+ * @values:
+ * FT_KERNING_DEFAULT ::
+ * Return grid-fitted kerning distances in 26.6 fractional pixels.
+ *
+ * FT_KERNING_UNFITTED ::
+ * Return un-grid-fitted kerning distances in 26.6 fractional pixels.
+ *
+ * FT_KERNING_UNSCALED ::
+ * Return the kerning vector in original font units.
+ *
+ * @note:
+ * `FT_KERNING_DEFAULT` returns full pixel values; it also makes FreeType
+ * heuristically scale down kerning distances at small ppem values so
+ * that they don't become too big.
+ *
+ * Both `FT_KERNING_DEFAULT` and `FT_KERNING_UNFITTED` use the current
+ * horizontal scaling factor (as set e.g. with @FT_Set_Char_Size) to
+ * convert font units to pixels.
+ */
typedef enum FT_Kerning_Mode_
{
FT_KERNING_DEFAULT = 0,
@@ -3399,50 +3418,53 @@ FT_BEGIN_HEADER
/* these constants are deprecated; use the corresponding */
- /* `FT_Kerning_Mode' values instead */
+ /* `FT_Kerning_Mode` values instead */
#define ft_kerning_default FT_KERNING_DEFAULT
#define ft_kerning_unfitted FT_KERNING_UNFITTED
#define ft_kerning_unscaled FT_KERNING_UNSCALED
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Get_Kerning */
- /* */
- /* <Description> */
- /* Return the kerning vector between two glyphs of the same face. */
- /* */
- /* <Input> */
- /* face :: A handle to a source face object. */
- /* */
- /* left_glyph :: The index of the left glyph in the kern pair. */
- /* */
- /* right_glyph :: The index of the right glyph in the kern pair. */
- /* */
- /* kern_mode :: See @FT_Kerning_Mode for more information. */
- /* Determines the scale and dimension of the returned */
- /* kerning vector. */
- /* */
- /* <Output> */
- /* akerning :: The kerning vector. This is either in font units, */
- /* fractional pixels (26.6 format), or pixels for */
- /* scalable formats, and in pixels for fixed-sizes */
- /* formats. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* Only horizontal layouts (left-to-right & right-to-left) are */
- /* supported by this method. Other layouts, or more sophisticated */
- /* kernings, are out of the scope of this API function -- they can be */
- /* implemented through format-specific interfaces. */
- /* */
- /* Kerning for OpenType fonts implemented in a `GPOS' table is not */
- /* supported; use @FT_HAS_KERNING to find out whether a font has data */
- /* that can be extracted with `FT_Get_Kerning'. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Kerning
+ *
+ * @description:
+ * Return the kerning vector between two glyphs of the same face.
+ *
+ * @input:
+ * face ::
+ * A handle to a source face object.
+ *
+ * left_glyph ::
+ * The index of the left glyph in the kern pair.
+ *
+ * right_glyph ::
+ * The index of the right glyph in the kern pair.
+ *
+ * kern_mode ::
+ * See @FT_Kerning_Mode for more information. Determines the scale and
+ * dimension of the returned kerning vector.
+ *
+ * @output:
+ * akerning ::
+ * The kerning vector. This is either in font units, fractional pixels
+ * (26.6 format), or pixels for scalable formats, and in pixels for
+ * fixed-sizes formats.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * Only horizontal layouts (left-to-right & right-to-left) are supported
+ * by this method. Other layouts, or more sophisticated kernings, are
+ * out of the scope of this API function -- they can be implemented
+ * through format-specific interfaces.
+ *
+ * Kerning for OpenType fonts implemented in a 'GPOS' table is not
+ * supported; use @FT_HAS_KERNING to find out whether a font has data
+ * that can be extracted with `FT_Get_Kerning`.
+ */
FT_EXPORT( FT_Error )
FT_Get_Kerning( FT_Face face,
FT_UInt left_glyph,
@@ -3451,39 +3473,42 @@ FT_BEGIN_HEADER
FT_Vector *akerning );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Get_Track_Kerning */
- /* */
- /* <Description> */
- /* Return the track kerning for a given face object at a given size. */
- /* */
- /* <Input> */
- /* face :: A handle to a source face object. */
- /* */
- /* point_size :: The point size in 16.16 fractional points. */
- /* */
- /* degree :: The degree of tightness. Increasingly negative */
- /* values represent tighter track kerning, while */
- /* increasingly positive values represent looser track */
- /* kerning. Value zero means no track kerning. */
- /* */
- /* <Output> */
- /* akerning :: The kerning in 16.16 fractional points, to be */
- /* uniformly applied between all glyphs. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* Currently, only the Type~1 font driver supports track kerning, */
- /* using data from AFM files (if attached with @FT_Attach_File or */
- /* @FT_Attach_Stream). */
- /* */
- /* Only very few AFM files come with track kerning data; please refer */
- /* to Adobe's AFM specification for more details. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Track_Kerning
+ *
+ * @description:
+ * Return the track kerning for a given face object at a given size.
+ *
+ * @input:
+ * face ::
+ * A handle to a source face object.
+ *
+ * point_size ::
+ * The point size in 16.16 fractional points.
+ *
+ * degree ::
+ * The degree of tightness. Increasingly negative values represent
+ * tighter track kerning, while increasingly positive values represent
+ * looser track kerning. Value zero means no track kerning.
+ *
+ * @output:
+ * akerning ::
+ * The kerning in 16.16 fractional points, to be uniformly applied
+ * between all glyphs.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * Currently, only the Type~1 font driver supports track kerning, using
+ * data from AFM files (if attached with @FT_Attach_File or
+ * @FT_Attach_Stream).
+ *
+ * Only very few AFM files come with track kerning data; please refer to
+ * Adobe's AFM specification for more details.
+ */
FT_EXPORT( FT_Error )
FT_Get_Track_Kerning( FT_Face face,
FT_Fixed point_size,
@@ -3491,45 +3516,46 @@ FT_BEGIN_HEADER
FT_Fixed* akerning );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Get_Glyph_Name */
- /* */
- /* <Description> */
- /* Retrieve the ASCII name of a given glyph in a face. This only */
- /* works for those faces where @FT_HAS_GLYPH_NAMES(face) returns~1. */
- /* */
- /* <Input> */
- /* face :: A handle to a source face object. */
- /* */
- /* glyph_index :: The glyph index. */
- /* */
- /* buffer_max :: The maximum number of bytes available in the */
- /* buffer. */
- /* */
- /* <Output> */
- /* buffer :: A pointer to a target buffer where the name is */
- /* copied to. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* An error is returned if the face doesn't provide glyph names or if */
- /* the glyph index is invalid. In all cases of failure, the first */
- /* byte of `buffer' is set to~0 to indicate an empty name. */
- /* */
- /* The glyph name is truncated to fit within the buffer if it is too */
- /* long. The returned string is always zero-terminated. */
- /* */
- /* Be aware that FreeType reorders glyph indices internally so that */
- /* glyph index~0 always corresponds to the `missing glyph' (called */
- /* `.notdef'). */
- /* */
- /* This function always returns an error if the config macro */
- /* `FT_CONFIG_OPTION_NO_GLYPH_NAMES' is not defined in `ftoption.h'. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Glyph_Name
+ *
+ * @description:
+ * Retrieve the ASCII name of a given glyph in a face. This only works
+ * for those faces where @FT_HAS_GLYPH_NAMES(face) returns~1.
+ *
+ * @input:
+ * face ::
+ * A handle to a source face object.
+ *
+ * glyph_index ::
+ * The glyph index.
+ *
+ * buffer_max ::
+ * The maximum number of bytes available in the buffer.
+ *
+ * @output:
+ * buffer ::
+ * A pointer to a target buffer where the name is copied to.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * An error is returned if the face doesn't provide glyph names or if the
+ * glyph index is invalid. In all cases of failure, the first byte of
+ * `buffer` is set to~0 to indicate an empty name.
+ *
+ * The glyph name is truncated to fit within the buffer if it is too
+ * long. The returned string is always zero-terminated.
+ *
+ * Be aware that FreeType reorders glyph indices internally so that glyph
+ * index~0 always corresponds to the 'missing glyph' (called '.notdef').
+ *
+ * This function always returns an error if the config macro
+ * `FT_CONFIG_OPTION_NO_GLYPH_NAMES` is not defined in `ftoption.h`.
+ */
FT_EXPORT( FT_Error )
FT_Get_Glyph_Name( FT_Face face,
FT_UInt glyph_index,
@@ -3537,107 +3563,109 @@ FT_BEGIN_HEADER
FT_UInt buffer_max );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Get_Postscript_Name */
- /* */
- /* <Description> */
- /* Retrieve the ASCII PostScript name of a given face, if available. */
- /* This only works with PostScript, TrueType, and OpenType fonts. */
- /* */
- /* <Input> */
- /* face :: A handle to the source face object. */
- /* */
- /* <Return> */
- /* A pointer to the face's PostScript name. NULL if unavailable. */
- /* */
- /* <Note> */
- /* The returned pointer is owned by the face and is destroyed with */
- /* it. */
- /* */
- /* For variation fonts, this string changes if you select a different */
- /* instance, and you have to call `FT_Get_PostScript_Name' again to */
- /* retrieve it. FreeType follows Adobe TechNote #5902, `Generating */
- /* PostScript Names for Fonts Using OpenType Font Variations'. */
- /* */
- /* https://download.macromedia.com/pub/developer/opentype/tech-notes/5902.AdobePSNameGeneration.html */
- /* */
- /* [Since 2.9] Special PostScript names for named instances are only */
- /* returned if the named instance is set with @FT_Set_Named_Instance */
- /* (and the font has corresponding entries in its `fvar' table). If */
- /* @FT_IS_VARIATION returns true, the algorithmically derived */
- /* PostScript name is provided, not looking up special entries for */
- /* named instances. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Postscript_Name
+ *
+ * @description:
+ * Retrieve the ASCII PostScript name of a given face, if available.
+ * This only works with PostScript, TrueType, and OpenType fonts.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face object.
+ *
+ * @return:
+ * A pointer to the face's PostScript name. `NULL` if unavailable.
+ *
+ * @note:
+ * The returned pointer is owned by the face and is destroyed with it.
+ *
+ * For variation fonts, this string changes if you select a different
+ * instance, and you have to call `FT_Get_PostScript_Name` again to
+ * retrieve it. FreeType follows Adobe TechNote #5902, 'Generating
+ * PostScript Names for Fonts Using OpenType Font Variations'.
+ *
+ * https://download.macromedia.com/pub/developer/opentype/tech-notes/5902.AdobePSNameGeneration.html
+ *
+ * [Since 2.9] Special PostScript names for named instances are only
+ * returned if the named instance is set with @FT_Set_Named_Instance (and
+ * the font has corresponding entries in its 'fvar' table). If
+ * @FT_IS_VARIATION returns true, the algorithmically derived PostScript
+ * name is provided, not looking up special entries for named instances.
+ */
FT_EXPORT( const char* )
FT_Get_Postscript_Name( FT_Face face );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Select_Charmap */
- /* */
- /* <Description> */
- /* Select a given charmap by its encoding tag (as listed in */
- /* `freetype.h'). */
- /* */
- /* <InOut> */
- /* face :: A handle to the source face object. */
- /* */
- /* <Input> */
- /* encoding :: A handle to the selected encoding. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* This function returns an error if no charmap in the face */
- /* corresponds to the encoding queried here. */
- /* */
- /* Because many fonts contain more than a single cmap for Unicode */
- /* encoding, this function has some special code to select the one */
- /* that covers Unicode best (`best' in the sense that a UCS-4 cmap is */
- /* preferred to a UCS-2 cmap). It is thus preferable to */
- /* @FT_Set_Charmap in this case. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Select_Charmap
+ *
+ * @description:
+ * Select a given charmap by its encoding tag (as listed in
+ * `freetype.h`).
+ *
+ * @inout:
+ * face ::
+ * A handle to the source face object.
+ *
+ * @input:
+ * encoding ::
+ * A handle to the selected encoding.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * This function returns an error if no charmap in the face corresponds
+ * to the encoding queried here.
+ *
+ * Because many fonts contain more than a single cmap for Unicode
+ * encoding, this function has some special code to select the one that
+ * covers Unicode best ('best' in the sense that a UCS-4 cmap is
+ * preferred to a UCS-2 cmap). It is thus preferable to @FT_Set_Charmap
+ * in this case.
+ */
FT_EXPORT( FT_Error )
FT_Select_Charmap( FT_Face face,
FT_Encoding encoding );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Set_Charmap */
- /* */
- /* <Description> */
- /* Select a given charmap for character code to glyph index mapping. */
- /* */
- /* <InOut> */
- /* face :: A handle to the source face object. */
- /* */
- /* <Input> */
- /* charmap :: A handle to the selected charmap. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* This function returns an error if the charmap is not part of */
- /* the face (i.e., if it is not listed in the `face->charmaps' */
- /* table). */
- /* */
- /* It also fails if an OpenType type~14 charmap is selected (which */
- /* doesn't map character codes to glyph indices at all). */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Set_Charmap
+ *
+ * @description:
+ * Select a given charmap for character code to glyph index mapping.
+ *
+ * @inout:
+ * face ::
+ * A handle to the source face object.
+ *
+ * @input:
+ * charmap ::
+ * A handle to the selected charmap.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * This function returns an error if the charmap is not part of the face
+ * (i.e., if it is not listed in the `face->charmaps` table).
+ *
+ * It also fails if an OpenType type~14 charmap is selected (which
+ * doesn't map character codes to glyph indices at all).
+ */
FT_EXPORT( FT_Error )
FT_Set_Charmap( FT_Face face,
FT_CharMap charmap );
- /*************************************************************************
+ /**************************************************************************
*
* @function:
* FT_Get_Charmap_Index
@@ -3651,139 +3679,143 @@ FT_BEGIN_HEADER
*
* @return:
* The index into the array of character maps within the face to which
- * `charmap' belongs. If an error occurs, -1 is returned.
+ * `charmap` belongs. If an error occurs, -1 is returned.
*
*/
FT_EXPORT( FT_Int )
FT_Get_Charmap_Index( FT_CharMap charmap );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Get_Char_Index */
- /* */
- /* <Description> */
- /* Return the glyph index of a given character code. This function */
- /* uses the currently selected charmap to do the mapping. */
- /* */
- /* <Input> */
- /* face :: A handle to the source face object. */
- /* */
- /* charcode :: The character code. */
- /* */
- /* <Return> */
- /* The glyph index. 0~means `undefined character code'. */
- /* */
- /* <Note> */
- /* If you use FreeType to manipulate the contents of font files */
- /* directly, be aware that the glyph index returned by this function */
- /* doesn't always correspond to the internal indices used within the */
- /* file. This is done to ensure that value~0 always corresponds to */
- /* the `missing glyph'. If the first glyph is not named `.notdef', */
- /* then for Type~1 and Type~42 fonts, `.notdef' will be moved into */
- /* the glyph ID~0 position, and whatever was there will be moved to */
- /* the position `.notdef' had. For Type~1 fonts, if there is no */
- /* `.notdef' glyph at all, then one will be created at index~0 and */
- /* whatever was there will be moved to the last index -- Type~42 */
- /* fonts are considered invalid under this condition. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Char_Index
+ *
+ * @description:
+ * Return the glyph index of a given character code. This function uses
+ * the currently selected charmap to do the mapping.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face object.
+ *
+ * charcode ::
+ * The character code.
+ *
+ * @return:
+ * The glyph index. 0~means 'undefined character code'.
+ *
+ * @note:
+ * If you use FreeType to manipulate the contents of font files directly,
+ * be aware that the glyph index returned by this function doesn't always
+ * correspond to the internal indices used within the file. This is done
+ * to ensure that value~0 always corresponds to the 'missing glyph'. If
+ * the first glyph is not named '.notdef', then for Type~1 and Type~42
+ * fonts, '.notdef' will be moved into the glyph ID~0 position, and
+ * whatever was there will be moved to the position '.notdef' had. For
+ * Type~1 fonts, if there is no '.notdef' glyph at all, then one will be
+ * created at index~0 and whatever was there will be moved to the last
+ * index -- Type~42 fonts are considered invalid under this condition.
+ */
FT_EXPORT( FT_UInt )
FT_Get_Char_Index( FT_Face face,
FT_ULong charcode );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Get_First_Char */
- /* */
- /* <Description> */
- /* Return the first character code in the current charmap of a given */
- /* face, together with its corresponding glyph index. */
- /* */
- /* <Input> */
- /* face :: A handle to the source face object. */
- /* */
- /* <Output> */
- /* agindex :: Glyph index of first character code. 0~if charmap is */
- /* empty. */
- /* */
- /* <Return> */
- /* The charmap's first character code. */
- /* */
- /* <Note> */
- /* You should use this function together with @FT_Get_Next_Char to */
- /* parse all character codes available in a given charmap. The code */
- /* should look like this: */
- /* */
- /* { */
- /* FT_ULong charcode; */
- /* FT_UInt gindex; */
- /* */
- /* */
- /* charcode = FT_Get_First_Char( face, &gindex ); */
- /* while ( gindex != 0 ) */
- /* { */
- /* ... do something with (charcode,gindex) pair ... */
- /* */
- /* charcode = FT_Get_Next_Char( face, charcode, &gindex ); */
- /* } */
- /* } */
- /* */
- /* Be aware that character codes can have values up to 0xFFFFFFFF; */
- /* this might happen for non-Unicode or malformed cmaps. However, */
- /* even with regular Unicode encoding, so-called `last resort fonts' */
- /* (using SFNT cmap format 13, see function @FT_Get_CMap_Format) */
- /* normally have entries for all Unicode characters up to 0x1FFFFF, */
- /* which can cause *a lot* of iterations. */
- /* */
- /* Note that `*agindex' is set to~0 if the charmap is empty. The */
- /* result itself can be~0 in two cases: if the charmap is empty or */
- /* if the value~0 is the first valid character code. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_First_Char
+ *
+ * @description:
+ * Return the first character code in the current charmap of a given
+ * face, together with its corresponding glyph index.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face object.
+ *
+ * @output:
+ * agindex ::
+ * Glyph index of first character code. 0~if charmap is empty.
+ *
+ * @return:
+ * The charmap's first character code.
+ *
+ * @note:
+ * You should use this function together with @FT_Get_Next_Char to parse
+ * all character codes available in a given charmap. The code should
+ * look like this:
+ *
+ * ```
+ * FT_ULong charcode;
+ * FT_UInt gindex;
+ *
+ *
+ * charcode = FT_Get_First_Char( face, &gindex );
+ * while ( gindex != 0 )
+ * {
+ * ... do something with (charcode,gindex) pair ...
+ *
+ * charcode = FT_Get_Next_Char( face, charcode, &gindex );
+ * }
+ * ```
+ *
+ * Be aware that character codes can have values up to 0xFFFFFFFF; this
+ * might happen for non-Unicode or malformed cmaps. However, even with
+ * regular Unicode encoding, so-called 'last resort fonts' (using SFNT
+ * cmap format 13, see function @FT_Get_CMap_Format) normally have
+ * entries for all Unicode characters up to 0x1FFFFF, which can cause *a
+ * lot* of iterations.
+ *
+ * Note that `*agindex` is set to~0 if the charmap is empty. The result
+ * itself can be~0 in two cases: if the charmap is empty or if the
+ * value~0 is the first valid character code.
+ */
FT_EXPORT( FT_ULong )
FT_Get_First_Char( FT_Face face,
FT_UInt *agindex );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Get_Next_Char */
- /* */
- /* <Description> */
- /* Return the next character code in the current charmap of a given */
- /* face following the value `char_code', as well as the corresponding */
- /* glyph index. */
- /* */
- /* <Input> */
- /* face :: A handle to the source face object. */
- /* */
- /* char_code :: The starting character code. */
- /* */
- /* <Output> */
- /* agindex :: Glyph index of next character code. 0~if charmap */
- /* is empty. */
- /* */
- /* <Return> */
- /* The charmap's next character code. */
- /* */
- /* <Note> */
- /* You should use this function with @FT_Get_First_Char to walk */
- /* over all character codes available in a given charmap. See the */
- /* note for that function for a simple code example. */
- /* */
- /* Note that `*agindex' is set to~0 when there are no more codes in */
- /* the charmap. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Next_Char
+ *
+ * @description:
+ * Return the next character code in the current charmap of a given face
+ * following the value `char_code`, as well as the corresponding glyph
+ * index.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face object.
+ *
+ * char_code ::
+ * The starting character code.
+ *
+ * @output:
+ * agindex ::
+ * Glyph index of next character code. 0~if charmap is empty.
+ *
+ * @return:
+ * The charmap's next character code.
+ *
+ * @note:
+ * You should use this function with @FT_Get_First_Char to walk over all
+ * character codes available in a given charmap. See the note for that
+ * function for a simple code example.
+ *
+ * Note that `*agindex` is set to~0 when there are no more codes in the
+ * charmap.
+ */
FT_EXPORT( FT_ULong )
FT_Get_Next_Char( FT_Face face,
FT_ULong char_code,
FT_UInt *agindex );
- /*************************************************************************
+ /**************************************************************************
*
* @function:
* FT_Face_Properties
@@ -3791,27 +3823,26 @@ FT_BEGIN_HEADER
* @description:
* Set or override certain (library or module-wide) properties on a
* face-by-face basis. Useful for finer-grained control and avoiding
- * locks on shared structures (threads can modify their own faces as
- * they see fit).
+ * locks on shared structures (threads can modify their own faces as they
+ * see fit).
*
- * Contrary to @FT_Property_Set, this function uses @FT_Parameter so
- * that you can pass multiple properties to the target face in one call.
- * Note that only a subset of the available properties can be
- * controlled.
+ * Contrary to @FT_Property_Set, this function uses @FT_Parameter so that
+ * you can pass multiple properties to the target face in one call. Note
+ * that only a subset of the available properties can be controlled.
*
* * @FT_PARAM_TAG_STEM_DARKENING (stem darkening, corresponding to the
- * property `no-stem-darkening' provided by the `autofit', `cff',
- * `type1', and `t1cid' modules; see @no-stem-darkening).
+ * property `no-stem-darkening` provided by the 'autofit', 'cff',
+ * 'type1', and 't1cid' modules; see @no-stem-darkening).
*
* * @FT_PARAM_TAG_LCD_FILTER_WEIGHTS (LCD filter weights, corresponding
* to function @FT_Library_SetLcdFilterWeights).
*
* * @FT_PARAM_TAG_RANDOM_SEED (seed value for the CFF, Type~1, and CID
- * `random' operator, corresponding to the `random-seed' property
- * provided by the `cff', `type1', and `t1cid' modules; see
+ * 'random' operator, corresponding to the `random-seed` property
+ * provided by the 'cff', 'type1', and 't1cid' modules; see
* @random-seed).
*
- * Pass NULL as `data' in @FT_Parameter for a given tag to reset the
+ * Pass `NULL` as `data` in @FT_Parameter for a given tag to reset the
* option and use the library or module default again.
*
* @input:
@@ -3822,17 +3853,17 @@ FT_BEGIN_HEADER
* The number of properties that follow.
*
* properties ::
- * A handle to an @FT_Parameter array with `num_properties' elements.
+ * A handle to an @FT_Parameter array with `num_properties` elements.
*
* @return:
* FreeType error code. 0~means success.
*
- * @note:
- * Here an example that sets three properties. You must define
- * FT_CONFIG_OPTION_SUBPIXEL_RENDERING to make the LCD filter examples
+ * @example:
+ * Here is an example that sets three properties. You must define
+ * `FT_CONFIG_OPTION_SUBPIXEL_RENDERING` to make the LCD filter examples
* work.
*
- * {
+ * ```
* FT_Parameter property1;
* FT_Bool darken_stems = 1;
*
@@ -3858,11 +3889,11 @@ FT_BEGIN_HEADER
* property3.data = &random_seed;
*
* FT_Face_Properties( face, 3, properties );
- * }
+ * ```
*
* The next example resets a single property to its default value.
*
- * {
+ * ```
* FT_Parameter property;
*
*
@@ -3870,7 +3901,7 @@ FT_BEGIN_HEADER
* property.data = NULL;
*
* FT_Face_Properties( face, 1, &property );
- * }
+ * ```
*
* @since:
* 2.8
@@ -3882,37 +3913,40 @@ FT_BEGIN_HEADER
FT_Parameter* properties );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Get_Name_Index */
- /* */
- /* <Description> */
- /* Return the glyph index of a given glyph name. */
- /* */
- /* <Input> */
- /* face :: A handle to the source face object. */
- /* */
- /* glyph_name :: The glyph name. */
- /* */
- /* <Return> */
- /* The glyph index. 0~means `undefined character code'. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Name_Index
+ *
+ * @description:
+ * Return the glyph index of a given glyph name.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face object.
+ *
+ * glyph_name ::
+ * The glyph name.
+ *
+ * @return:
+ * The glyph index. 0~means 'undefined character code'.
+ */
FT_EXPORT( FT_UInt )
FT_Get_Name_Index( FT_Face face,
FT_String* glyph_name );
- /*************************************************************************
+ /**************************************************************************
*
- * @macro:
+ * @enum:
* FT_SUBGLYPH_FLAG_XXX
*
* @description:
- * A list of constants describing subglyphs. Please refer to the
- * `glyf' table description in the OpenType specification for the
- * meaning of the various flags (which get synthesized for
- * non-OpenType subglyphs).
+ * A list of constants describing subglyphs. Please refer to the 'glyf'
+ * table description in the OpenType specification for the meaning of the
+ * various flags (which get synthesized for non-OpenType subglyphs).
+ *
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/glyf#composite-glyph-description
*
* @values:
* FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS ::
@@ -3933,15 +3967,15 @@ FT_BEGIN_HEADER
#define FT_SUBGLYPH_FLAG_USE_MY_METRICS 0x200
- /*************************************************************************
+ /**************************************************************************
*
- * @func:
+ * @function:
* FT_Get_SubGlyph_Info
*
* @description:
* Retrieve a description of a given subglyph. Only use it if
- * `glyph->format' is @FT_GLYPH_FORMAT_COMPOSITE; an error is
- * returned otherwise.
+ * `glyph->format` is @FT_GLYPH_FORMAT_COMPOSITE; an error is returned
+ * otherwise.
*
* @input:
* glyph ::
@@ -3949,7 +3983,7 @@ FT_BEGIN_HEADER
*
* sub_index ::
* The index of the subglyph. Must be less than
- * `glyph->num_subglyphs'.
+ * `glyph->num_subglyphs`.
*
* @output:
* p_index ::
@@ -3971,10 +4005,12 @@ FT_BEGIN_HEADER
* FreeType error code. 0~means success.
*
* @note:
- * The values of `*p_arg1', `*p_arg2', and `*p_transform' must be
- * interpreted depending on the flags returned in `*p_flags'. See the
+ * The values of `*p_arg1`, `*p_arg2`, and `*p_transform` must be
+ * interpreted depending on the flags returned in `*p_flags`. See the
* OpenType specification for details.
*
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/glyf#composite-glyph-description
+ *
*/
FT_EXPORT( FT_Error )
FT_Get_SubGlyph_Info( FT_GlyphSlot glyph,
@@ -3986,59 +4022,228 @@ FT_BEGIN_HEADER
FT_Matrix *p_transform );
- /*************************************************************************/
- /* */
- /* <Enum> */
- /* FT_FSTYPE_XXX */
- /* */
- /* <Description> */
- /* A list of bit flags used in the `fsType' field of the OS/2 table */
- /* in a TrueType or OpenType font and the `FSType' entry in a */
- /* PostScript font. These bit flags are returned by */
- /* @FT_Get_FSType_Flags; they inform client applications of embedding */
- /* and subsetting restrictions associated with a font. */
- /* */
- /* See */
- /* https://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/FontPolicies.pdf */
- /* for more details. */
- /* */
- /* <Values> */
- /* FT_FSTYPE_INSTALLABLE_EMBEDDING :: */
- /* Fonts with no fsType bit set may be embedded and permanently */
- /* installed on the remote system by an application. */
- /* */
- /* FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING :: */
- /* Fonts that have only this bit set must not be modified, embedded */
- /* or exchanged in any manner without first obtaining permission of */
- /* the font software copyright owner. */
- /* */
- /* FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING :: */
- /* The font may be embedded and temporarily loaded on the remote */
- /* system. Documents containing Preview & Print fonts must be */
- /* opened `read-only'; no edits can be applied to the document. */
- /* */
- /* FT_FSTYPE_EDITABLE_EMBEDDING :: */
- /* The font may be embedded but must only be installed temporarily */
- /* on other systems. In contrast to Preview & Print fonts, */
- /* documents containing editable fonts may be opened for reading, */
- /* editing is permitted, and changes may be saved. */
- /* */
- /* FT_FSTYPE_NO_SUBSETTING :: */
- /* The font may not be subsetted prior to embedding. */
- /* */
- /* FT_FSTYPE_BITMAP_EMBEDDING_ONLY :: */
- /* Only bitmaps contained in the font may be embedded; no outline */
- /* data may be embedded. If there are no bitmaps available in the */
- /* font, then the font is unembeddable. */
- /* */
- /* <Note> */
- /* The flags are ORed together, thus more than a single value can be */
- /* returned. */
- /* */
- /* While the `fsType' flags can indicate that a font may be embedded, */
- /* a license with the font vendor may be separately required to use */
- /* the font in this way. */
- /* */
+ /**************************************************************************
+ *
+ * @section:
+ * layer_management
+ *
+ * @title:
+ * Glyph Layer Management
+ *
+ * @abstract:
+ * Retrieving and manipulating OpenType's 'COLR' table data.
+ *
+ * @description:
+ * The functions described here allow access of colored glyph layer data
+ * in OpenType's 'COLR' tables.
+ */
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_LayerIterator
+ *
+ * @description:
+ * This iterator object is needed for @FT_Get_Color_Glyph_Layer.
+ *
+ * @fields:
+ * num_layers ::
+ * The number of glyph layers for the requested glyph index. Will be
+ * set by @FT_Get_Color_Glyph_Layer.
+ *
+ * layer ::
+ * The current layer. Will be set by @FT_Get_Color_Glyph_Layer.
+ *
+ * p ::
+ * An opaque pointer into 'COLR' table data. The caller must set this
+ * to `NULL` before the first call of @FT_Get_Color_Glyph_Layer.
+ */
+ typedef struct FT_LayerIterator_
+ {
+ FT_UInt num_layers;
+ FT_UInt layer;
+ FT_Byte* p;
+
+ } FT_LayerIterator;
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Color_Glyph_Layer
+ *
+ * @description:
+ * This is an interface to the 'COLR' table in OpenType fonts to
+ * iteratively retrieve the colored glyph layers associated with the
+ * current glyph slot.
+ *
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/colr
+ *
+ * The glyph layer data for a given glyph index, if present, provides an
+ * alternative, multi-colour glyph representation: Instead of rendering
+ * the outline or bitmap with the given glyph index, glyphs with the
+ * indices and colors returned by this function are rendered layer by
+ * layer.
+ *
+ * The returned elements are ordered in the z~direction from bottom to
+ * top; the 'n'th element should be rendered with the associated palette
+ * color and blended on top of the already rendered layers (elements 0,
+ * 1, ..., n-1).
+ *
+ * @input:
+ * face ::
+ * A handle to the parent face object.
+ *
+ * base_glyph ::
+ * The glyph index the colored glyph layers are associated with.
+ *
+ * @inout:
+ * iterator ::
+ * An @FT_LayerIterator object. For the first call you should set
+ * `iterator->p` to `NULL`. For all following calls, simply use the
+ * same object again.
+ *
+ * @output:
+ * aglyph_index ::
+ * The glyph index of the current layer.
+ *
+ * acolor_index ::
+ * The color index into the font face's color palette of the current
+ * layer. The value 0xFFFF is special; it doesn't reference a palette
+ * entry but indicates that the text foreground color should be used
+ * instead (to be set up by the application outside of FreeType).
+ *
+ * The color palette can be retrieved with @FT_Palette_Select.
+ *
+ * @return:
+ * Value~1 if everything is OK. If there are no more layers (or if there
+ * are no layers at all), value~0 gets returned. In case of an error,
+ * value~0 is returned also.
+ *
+ * @note:
+ * This function is necessary if you want to handle glyph layers by
+ * yourself. In particular, functions that operate with @FT_GlyphRec
+ * objects (like @FT_Get_Glyph or @FT_Glyph_To_Bitmap) don't have access
+ * to this information.
+ *
+ * Note that @FT_Render_Glyph is able to handle colored glyph layers
+ * automatically if the @FT_LOAD_COLOR flag is passed to a previous call
+ * to @FT_Load_Glyph. [This is an experimental feature.]
+ *
+ * @example:
+ * ```
+ * FT_Color* palette;
+ * FT_LayerIterator iterator;
+ *
+ * FT_Bool have_layers;
+ * FT_UInt layer_glyph_index;
+ * FT_UInt layer_color_index;
+ *
+ *
+ * error = FT_Palette_Select( face, palette_index, &palette );
+ * if ( error )
+ * palette = NULL;
+ *
+ * iterator.p = NULL;
+ * have_layers = FT_Get_Color_Glyph_Layer( face,
+ * glyph_index,
+ * &layer_glyph_index,
+ * &layer_color_index,
+ * &iterator );
+ *
+ * if ( palette && have_layers )
+ * {
+ * do
+ * {
+ * FT_Color layer_color;
+ *
+ *
+ * if ( layer_color_index == 0xFFFF )
+ * layer_color = text_foreground_color;
+ * else
+ * layer_color = palette[layer_color_index];
+ *
+ * // Load and render glyph `layer_glyph_index', then
+ * // blend resulting pixmap (using color `layer_color')
+ * // with previously created pixmaps.
+ *
+ * } while ( FT_Get_Color_Glyph_Layer( face,
+ * glyph_index,
+ * &layer_glyph_index,
+ * &layer_color_index,
+ * &iterator ) );
+ * }
+ * ```
+ */
+ FT_EXPORT( FT_Bool )
+ FT_Get_Color_Glyph_Layer( FT_Face face,
+ FT_UInt base_glyph,
+ FT_UInt *aglyph_index,
+ FT_UInt *acolor_index,
+ FT_LayerIterator* iterator );
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * base_interface
+ *
+ */
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_FSTYPE_XXX
+ *
+ * @description:
+ * A list of bit flags used in the `fsType` field of the OS/2 table in a
+ * TrueType or OpenType font and the `FSType` entry in a PostScript font.
+ * These bit flags are returned by @FT_Get_FSType_Flags; they inform
+ * client applications of embedding and subsetting restrictions
+ * associated with a font.
+ *
+ * See
+ * https://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/FontPolicies.pdf
+ * for more details.
+ *
+ * @values:
+ * FT_FSTYPE_INSTALLABLE_EMBEDDING ::
+ * Fonts with no fsType bit set may be embedded and permanently
+ * installed on the remote system by an application.
+ *
+ * FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING ::
+ * Fonts that have only this bit set must not be modified, embedded or
+ * exchanged in any manner without first obtaining permission of the
+ * font software copyright owner.
+ *
+ * FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING ::
+ * The font may be embedded and temporarily loaded on the remote
+ * system. Documents containing Preview & Print fonts must be opened
+ * 'read-only'; no edits can be applied to the document.
+ *
+ * FT_FSTYPE_EDITABLE_EMBEDDING ::
+ * The font may be embedded but must only be installed temporarily on
+ * other systems. In contrast to Preview & Print fonts, documents
+ * containing editable fonts may be opened for reading, editing is
+ * permitted, and changes may be saved.
+ *
+ * FT_FSTYPE_NO_SUBSETTING ::
+ * The font may not be subsetted prior to embedding.
+ *
+ * FT_FSTYPE_BITMAP_EMBEDDING_ONLY ::
+ * Only bitmaps contained in the font may be embedded; no outline data
+ * may be embedded. If there are no bitmaps available in the font,
+ * then the font is unembeddable.
+ *
+ * @note:
+ * The flags are ORed together, thus more than a single value can be
+ * returned.
+ *
+ * While the `fsType` flags can indicate that a font may be embedded, a
+ * license with the font vendor may be separately required to use the
+ * font in this way.
+ */
#define FT_FSTYPE_INSTALLABLE_EMBEDDING 0x0000
#define FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING 0x0002
#define FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING 0x0004
@@ -4047,548 +4252,563 @@ FT_BEGIN_HEADER
#define FT_FSTYPE_BITMAP_EMBEDDING_ONLY 0x0200
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Get_FSType_Flags */
- /* */
- /* <Description> */
- /* Return the `fsType' flags for a font. */
- /* */
- /* <Input> */
- /* face :: A handle to the source face object. */
- /* */
- /* <Return> */
- /* The `fsType' flags, see @FT_FSTYPE_XXX. */
- /* */
- /* <Note> */
- /* Use this function rather than directly reading the `fs_type' field */
- /* in the @PS_FontInfoRec structure, which is only guaranteed to */
- /* return the correct results for Type~1 fonts. */
- /* */
- /* <Since> */
- /* 2.3.8 */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_FSType_Flags
+ *
+ * @description:
+ * Return the `fsType` flags for a font.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face object.
+ *
+ * @return:
+ * The `fsType` flags, see @FT_FSTYPE_XXX.
+ *
+ * @note:
+ * Use this function rather than directly reading the `fs_type` field in
+ * the @PS_FontInfoRec structure, which is only guaranteed to return the
+ * correct results for Type~1 fonts.
+ *
+ * @since:
+ * 2.3.8
+ */
FT_EXPORT( FT_UShort )
FT_Get_FSType_Flags( FT_Face face );
- /*************************************************************************/
- /* */
- /* <Section> */
- /* glyph_variants */
- /* */
- /* <Title> */
- /* Unicode Variation Sequences */
- /* */
- /* <Abstract> */
- /* The FreeType~2 interface to Unicode Variation Sequences (UVS), */
- /* using the SFNT cmap format~14. */
- /* */
- /* <Description> */
- /* Many characters, especially for CJK scripts, have variant forms. */
- /* They are a sort of grey area somewhere between being totally */
- /* irrelevant and semantically distinct; for this reason, the Unicode */
- /* consortium decided to introduce Variation Sequences (VS), */
- /* consisting of a Unicode base character and a variation selector */
- /* instead of further extending the already huge number of */
- /* characters. */
- /* */
- /* Unicode maintains two different sets, namely `Standardized */
- /* Variation Sequences' and registered `Ideographic Variation */
- /* Sequences' (IVS), collected in the `Ideographic Variation */
- /* Database' (IVD). */
- /* */
- /* https://unicode.org/Public/UCD/latest/ucd/StandardizedVariants.txt */
- /* https://unicode.org/reports/tr37/ */
- /* https://unicode.org/ivd/ */
- /* */
- /* To date (January 2017), the character with the most ideographic */
- /* variations is U+9089, having 32 such IVS. */
- /* */
- /* Three Mongolian Variation Selectors have the values U+180B-U+180D; */
- /* 256 generic Variation Selectors are encoded in the ranges */
- /* U+FE00-U+FE0F and U+E0100-U+E01EF. IVS currently use Variation */
- /* Selectors from the range U+E0100-U+E01EF only. */
- /* */
- /* A VS consists of the base character value followed by a single */
- /* Variation Selector. For example, to get the first variation of */
- /* U+9089, you have to write the character sequence `U+9089 U+E0100'. */
- /* */
- /* Adobe and MS decided to support both standardized and ideographic */
- /* VS with a new cmap subtable (format~14). It is an odd subtable */
- /* because it is not a mapping of input code points to glyphs, but */
- /* contains lists of all variations supported by the font. */
- /* */
- /* A variation may be either `default' or `non-default' for a given */
- /* font. A default variation is the one you will get for that code */
- /* point if you look it up in the standard Unicode cmap. A */
- /* non-default variation is a different glyph. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * @section:
+ * glyph_variants
+ *
+ * @title:
+ * Unicode Variation Sequences
+ *
+ * @abstract:
+ * The FreeType~2 interface to Unicode Variation Sequences (UVS), using
+ * the SFNT cmap format~14.
+ *
+ * @description:
+ * Many characters, especially for CJK scripts, have variant forms. They
+ * are a sort of grey area somewhere between being totally irrelevant and
+ * semantically distinct; for this reason, the Unicode consortium decided
+ * to introduce Variation Sequences (VS), consisting of a Unicode base
+ * character and a variation selector instead of further extending the
+ * already huge number of characters.
+ *
+ * Unicode maintains two different sets, namely 'Standardized Variation
+ * Sequences' and registered 'Ideographic Variation Sequences' (IVS),
+ * collected in the 'Ideographic Variation Database' (IVD).
+ *
+ * https://unicode.org/Public/UCD/latest/ucd/StandardizedVariants.txt
+ * https://unicode.org/reports/tr37/ https://unicode.org/ivd/
+ *
+ * To date (January 2017), the character with the most ideographic
+ * variations is U+9089, having 32 such IVS.
+ *
+ * Three Mongolian Variation Selectors have the values U+180B-U+180D; 256
+ * generic Variation Selectors are encoded in the ranges U+FE00-U+FE0F
+ * and U+E0100-U+E01EF. IVS currently use Variation Selectors from the
+ * range U+E0100-U+E01EF only.
+ *
+ * A VS consists of the base character value followed by a single
+ * Variation Selector. For example, to get the first variation of
+ * U+9089, you have to write the character sequence `U+9089 U+E0100`.
+ *
+ * Adobe and MS decided to support both standardized and ideographic VS
+ * with a new cmap subtable (format~14). It is an odd subtable because
+ * it is not a mapping of input code points to glyphs, but contains lists
+ * of all variations supported by the font.
+ *
+ * A variation may be either 'default' or 'non-default' for a given font.
+ * A default variation is the one you will get for that code point if you
+ * look it up in the standard Unicode cmap. A non-default variation is a
+ * different glyph.
+ *
+ */
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Face_GetCharVariantIndex */
- /* */
- /* <Description> */
- /* Return the glyph index of a given character code as modified by */
- /* the variation selector. */
- /* */
- /* <Input> */
- /* face :: */
- /* A handle to the source face object. */
- /* */
- /* charcode :: */
- /* The character code point in Unicode. */
- /* */
- /* variantSelector :: */
- /* The Unicode code point of the variation selector. */
- /* */
- /* <Return> */
- /* The glyph index. 0~means either `undefined character code', or */
- /* `undefined selector code', or `no variation selector cmap */
- /* subtable', or `current CharMap is not Unicode'. */
- /* */
- /* <Note> */
- /* If you use FreeType to manipulate the contents of font files */
- /* directly, be aware that the glyph index returned by this function */
- /* doesn't always correspond to the internal indices used within */
- /* the file. This is done to ensure that value~0 always corresponds */
- /* to the `missing glyph'. */
- /* */
- /* This function is only meaningful if */
- /* a) the font has a variation selector cmap sub table, */
- /* and */
- /* b) the current charmap has a Unicode encoding. */
- /* */
- /* <Since> */
- /* 2.3.6 */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Face_GetCharVariantIndex
+ *
+ * @description:
+ * Return the glyph index of a given character code as modified by the
+ * variation selector.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face object.
+ *
+ * charcode ::
+ * The character code point in Unicode.
+ *
+ * variantSelector ::
+ * The Unicode code point of the variation selector.
+ *
+ * @return:
+ * The glyph index. 0~means either 'undefined character code', or
+ * 'undefined selector code', or 'no variation selector cmap subtable',
+ * or 'current CharMap is not Unicode'.
+ *
+ * @note:
+ * If you use FreeType to manipulate the contents of font files directly,
+ * be aware that the glyph index returned by this function doesn't always
+ * correspond to the internal indices used within the file. This is done
+ * to ensure that value~0 always corresponds to the 'missing glyph'.
+ *
+ * This function is only meaningful if
+ * a) the font has a variation selector cmap sub table, and
+ * b) the current charmap has a Unicode encoding.
+ *
+ * @since:
+ * 2.3.6
+ */
FT_EXPORT( FT_UInt )
FT_Face_GetCharVariantIndex( FT_Face face,
FT_ULong charcode,
FT_ULong variantSelector );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Face_GetCharVariantIsDefault */
- /* */
- /* <Description> */
- /* Check whether this variation of this Unicode character is the one */
- /* to be found in the `cmap'. */
- /* */
- /* <Input> */
- /* face :: */
- /* A handle to the source face object. */
- /* */
- /* charcode :: */
- /* The character codepoint in Unicode. */
- /* */
- /* variantSelector :: */
- /* The Unicode codepoint of the variation selector. */
- /* */
- /* <Return> */
- /* 1~if found in the standard (Unicode) cmap, 0~if found in the */
- /* variation selector cmap, or -1 if it is not a variation. */
- /* */
- /* <Note> */
- /* This function is only meaningful if the font has a variation */
- /* selector cmap subtable. */
- /* */
- /* <Since> */
- /* 2.3.6 */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Face_GetCharVariantIsDefault
+ *
+ * @description:
+ * Check whether this variation of this Unicode character is the one to
+ * be found in the charmap.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face object.
+ *
+ * charcode ::
+ * The character codepoint in Unicode.
+ *
+ * variantSelector ::
+ * The Unicode codepoint of the variation selector.
+ *
+ * @return:
+ * 1~if found in the standard (Unicode) cmap, 0~if found in the variation
+ * selector cmap, or -1 if it is not a variation.
+ *
+ * @note:
+ * This function is only meaningful if the font has a variation selector
+ * cmap subtable.
+ *
+ * @since:
+ * 2.3.6
+ */
FT_EXPORT( FT_Int )
FT_Face_GetCharVariantIsDefault( FT_Face face,
FT_ULong charcode,
FT_ULong variantSelector );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Face_GetVariantSelectors */
- /* */
- /* <Description> */
- /* Return a zero-terminated list of Unicode variation selectors found */
- /* in the font. */
- /* */
- /* <Input> */
- /* face :: */
- /* A handle to the source face object. */
- /* */
- /* <Return> */
- /* A pointer to an array of selector code points, or NULL if there is */
- /* no valid variation selector cmap subtable. */
- /* */
- /* <Note> */
- /* The last item in the array is~0; the array is owned by the */
- /* @FT_Face object but can be overwritten or released on the next */
- /* call to a FreeType function. */
- /* */
- /* <Since> */
- /* 2.3.6 */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Face_GetVariantSelectors
+ *
+ * @description:
+ * Return a zero-terminated list of Unicode variation selectors found in
+ * the font.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face object.
+ *
+ * @return:
+ * A pointer to an array of selector code points, or `NULL` if there is
+ * no valid variation selector cmap subtable.
+ *
+ * @note:
+ * The last item in the array is~0; the array is owned by the @FT_Face
+ * object but can be overwritten or released on the next call to a
+ * FreeType function.
+ *
+ * @since:
+ * 2.3.6
+ */
FT_EXPORT( FT_UInt32* )
FT_Face_GetVariantSelectors( FT_Face face );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Face_GetVariantsOfChar */
- /* */
- /* <Description> */
- /* Return a zero-terminated list of Unicode variation selectors found */
- /* for the specified character code. */
- /* */
- /* <Input> */
- /* face :: */
- /* A handle to the source face object. */
- /* */
- /* charcode :: */
- /* The character codepoint in Unicode. */
- /* */
- /* <Return> */
- /* A pointer to an array of variation selector code points that are */
- /* active for the given character, or NULL if the corresponding list */
- /* is empty. */
- /* */
- /* <Note> */
- /* The last item in the array is~0; the array is owned by the */
- /* @FT_Face object but can be overwritten or released on the next */
- /* call to a FreeType function. */
- /* */
- /* <Since> */
- /* 2.3.6 */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Face_GetVariantsOfChar
+ *
+ * @description:
+ * Return a zero-terminated list of Unicode variation selectors found for
+ * the specified character code.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face object.
+ *
+ * charcode ::
+ * The character codepoint in Unicode.
+ *
+ * @return:
+ * A pointer to an array of variation selector code points that are
+ * active for the given character, or `NULL` if the corresponding list is
+ * empty.
+ *
+ * @note:
+ * The last item in the array is~0; the array is owned by the @FT_Face
+ * object but can be overwritten or released on the next call to a
+ * FreeType function.
+ *
+ * @since:
+ * 2.3.6
+ */
FT_EXPORT( FT_UInt32* )
FT_Face_GetVariantsOfChar( FT_Face face,
FT_ULong charcode );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Face_GetCharsOfVariant */
- /* */
- /* <Description> */
- /* Return a zero-terminated list of Unicode character codes found for */
- /* the specified variation selector. */
- /* */
- /* <Input> */
- /* face :: */
- /* A handle to the source face object. */
- /* */
- /* variantSelector :: */
- /* The variation selector code point in Unicode. */
- /* */
- /* <Return> */
- /* A list of all the code points that are specified by this selector */
- /* (both default and non-default codes are returned) or NULL if there */
- /* is no valid cmap or the variation selector is invalid. */
- /* */
- /* <Note> */
- /* The last item in the array is~0; the array is owned by the */
- /* @FT_Face object but can be overwritten or released on the next */
- /* call to a FreeType function. */
- /* */
- /* <Since> */
- /* 2.3.6 */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Face_GetCharsOfVariant
+ *
+ * @description:
+ * Return a zero-terminated list of Unicode character codes found for the
+ * specified variation selector.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face object.
+ *
+ * variantSelector ::
+ * The variation selector code point in Unicode.
+ *
+ * @return:
+ * A list of all the code points that are specified by this selector
+ * (both default and non-default codes are returned) or `NULL` if there
+ * is no valid cmap or the variation selector is invalid.
+ *
+ * @note:
+ * The last item in the array is~0; the array is owned by the @FT_Face
+ * object but can be overwritten or released on the next call to a
+ * FreeType function.
+ *
+ * @since:
+ * 2.3.6
+ */
FT_EXPORT( FT_UInt32* )
FT_Face_GetCharsOfVariant( FT_Face face,
FT_ULong variantSelector );
- /*************************************************************************/
- /* */
- /* <Section> */
- /* computations */
- /* */
- /* <Title> */
- /* Computations */
- /* */
- /* <Abstract> */
- /* Crunching fixed numbers and vectors. */
- /* */
- /* <Description> */
- /* This section contains various functions used to perform */
- /* computations on 16.16 fixed-float numbers or 2d vectors. */
- /* */
- /* <Order> */
- /* FT_MulDiv */
- /* FT_MulFix */
- /* FT_DivFix */
- /* FT_RoundFix */
- /* FT_CeilFix */
- /* FT_FloorFix */
- /* FT_Vector_Transform */
- /* FT_Matrix_Multiply */
- /* FT_Matrix_Invert */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * @section:
+ * computations
+ *
+ * @title:
+ * Computations
+ *
+ * @abstract:
+ * Crunching fixed numbers and vectors.
+ *
+ * @description:
+ * This section contains various functions used to perform computations
+ * on 16.16 fixed-float numbers or 2d vectors.
+ *
+ * **Attention**: Most arithmetic functions take `FT_Long` as arguments.
+ * For historical reasons, FreeType was designed under the assumption
+ * that `FT_Long` is a 32-bit integer; results can thus be undefined if
+ * the arguments don't fit into 32 bits.
+ *
+ * @order:
+ * FT_MulDiv
+ * FT_MulFix
+ * FT_DivFix
+ * FT_RoundFix
+ * FT_CeilFix
+ * FT_FloorFix
+ * FT_Vector_Transform
+ * FT_Matrix_Multiply
+ * FT_Matrix_Invert
+ *
+ */
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_MulDiv */
- /* */
- /* <Description> */
- /* Compute `(a*b)/c' with maximum accuracy, using a 64-bit */
- /* intermediate integer whenever necessary. */
- /* */
- /* This function isn't necessarily as fast as some processor specific */
- /* operations, but is at least completely portable. */
- /* */
- /* <Input> */
- /* a :: The first multiplier. */
- /* */
- /* b :: The second multiplier. */
- /* */
- /* c :: The divisor. */
- /* */
- /* <Return> */
- /* The result of `(a*b)/c'. This function never traps when trying to */
- /* divide by zero; it simply returns `MaxInt' or `MinInt' depending */
- /* on the signs of `a' and `b'. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_MulDiv
+ *
+ * @description:
+ * Compute `(a*b)/c` with maximum accuracy, using a 64-bit intermediate
+ * integer whenever necessary.
+ *
+ * This function isn't necessarily as fast as some processor-specific
+ * operations, but is at least completely portable.
+ *
+ * @input:
+ * a ::
+ * The first multiplier.
+ *
+ * b ::
+ * The second multiplier.
+ *
+ * c ::
+ * The divisor.
+ *
+ * @return:
+ * The result of `(a*b)/c`. This function never traps when trying to
+ * divide by zero; it simply returns 'MaxInt' or 'MinInt' depending on
+ * the signs of `a` and `b`.
+ */
FT_EXPORT( FT_Long )
FT_MulDiv( FT_Long a,
FT_Long b,
FT_Long c );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_MulFix */
- /* */
- /* <Description> */
- /* Compute `(a*b)/0x10000' with maximum accuracy. Its main use is to */
- /* multiply a given value by a 16.16 fixed-point factor. */
- /* */
- /* <Input> */
- /* a :: The first multiplier. */
- /* */
- /* b :: The second multiplier. Use a 16.16 factor here whenever */
- /* possible (see note below). */
- /* */
- /* <Return> */
- /* The result of `(a*b)/0x10000'. */
- /* */
- /* <Note> */
- /* This function has been optimized for the case where the absolute */
- /* value of `a' is less than 2048, and `b' is a 16.16 scaling factor. */
- /* As this happens mainly when scaling from notional units to */
- /* fractional pixels in FreeType, it resulted in noticeable speed */
- /* improvements between versions 2.x and 1.x. */
- /* */
- /* As a conclusion, always try to place a 16.16 factor as the */
- /* _second_ argument of this function; this can make a great */
- /* difference. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_MulFix
+ *
+ * @description:
+ * Compute `(a*b)/0x10000` with maximum accuracy. Its main use is to
+ * multiply a given value by a 16.16 fixed-point factor.
+ *
+ * @input:
+ * a ::
+ * The first multiplier.
+ *
+ * b ::
+ * The second multiplier. Use a 16.16 factor here whenever possible
+ * (see note below).
+ *
+ * @return:
+ * The result of `(a*b)/0x10000`.
+ *
+ * @note:
+ * This function has been optimized for the case where the absolute value
+ * of `a` is less than 2048, and `b` is a 16.16 scaling factor. As this
+ * happens mainly when scaling from notional units to fractional pixels
+ * in FreeType, it resulted in noticeable speed improvements between
+ * versions 2.x and 1.x.
+ *
+ * As a conclusion, always try to place a 16.16 factor as the _second_
+ * argument of this function; this can make a great difference.
+ */
FT_EXPORT( FT_Long )
FT_MulFix( FT_Long a,
FT_Long b );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_DivFix */
- /* */
- /* <Description> */
- /* Compute `(a*0x10000)/b' with maximum accuracy. Its main use is to */
- /* divide a given value by a 16.16 fixed-point factor. */
- /* */
- /* <Input> */
- /* a :: The numerator. */
- /* */
- /* b :: The denominator. Use a 16.16 factor here. */
- /* */
- /* <Return> */
- /* The result of `(a*0x10000)/b'. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_DivFix
+ *
+ * @description:
+ * Compute `(a*0x10000)/b` with maximum accuracy. Its main use is to
+ * divide a given value by a 16.16 fixed-point factor.
+ *
+ * @input:
+ * a ::
+ * The numerator.
+ *
+ * b ::
+ * The denominator. Use a 16.16 factor here.
+ *
+ * @return:
+ * The result of `(a*0x10000)/b`.
+ */
FT_EXPORT( FT_Long )
FT_DivFix( FT_Long a,
FT_Long b );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_RoundFix */
- /* */
- /* <Description> */
- /* Round a 16.16 fixed number. */
- /* */
- /* <Input> */
- /* a :: The number to be rounded. */
- /* */
- /* <Return> */
- /* `a' rounded to the nearest 16.16 fixed integer, halfway cases away */
- /* from zero. */
- /* */
- /* <Note> */
- /* The function uses wrap-around arithmetic. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_RoundFix
+ *
+ * @description:
+ * Round a 16.16 fixed number.
+ *
+ * @input:
+ * a ::
+ * The number to be rounded.
+ *
+ * @return:
+ * `a` rounded to the nearest 16.16 fixed integer, halfway cases away
+ * from zero.
+ *
+ * @note:
+ * The function uses wrap-around arithmetic.
+ */
FT_EXPORT( FT_Fixed )
FT_RoundFix( FT_Fixed a );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_CeilFix */
- /* */
- /* <Description> */
- /* Compute the smallest following integer of a 16.16 fixed number. */
- /* */
- /* <Input> */
- /* a :: The number for which the ceiling function is to be computed. */
- /* */
- /* <Return> */
- /* `a' rounded towards plus infinity. */
- /* */
- /* <Note> */
- /* The function uses wrap-around arithmetic. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_CeilFix
+ *
+ * @description:
+ * Compute the smallest following integer of a 16.16 fixed number.
+ *
+ * @input:
+ * a ::
+ * The number for which the ceiling function is to be computed.
+ *
+ * @return:
+ * `a` rounded towards plus infinity.
+ *
+ * @note:
+ * The function uses wrap-around arithmetic.
+ */
FT_EXPORT( FT_Fixed )
FT_CeilFix( FT_Fixed a );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_FloorFix */
- /* */
- /* <Description> */
- /* Compute the largest previous integer of a 16.16 fixed number. */
- /* */
- /* <Input> */
- /* a :: The number for which the floor function is to be computed. */
- /* */
- /* <Return> */
- /* `a' rounded towards minus infinity. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_FloorFix
+ *
+ * @description:
+ * Compute the largest previous integer of a 16.16 fixed number.
+ *
+ * @input:
+ * a ::
+ * The number for which the floor function is to be computed.
+ *
+ * @return:
+ * `a` rounded towards minus infinity.
+ */
FT_EXPORT( FT_Fixed )
FT_FloorFix( FT_Fixed a );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Vector_Transform */
- /* */
- /* <Description> */
- /* Transform a single vector through a 2x2 matrix. */
- /* */
- /* <InOut> */
- /* vector :: The target vector to transform. */
- /* */
- /* <Input> */
- /* matrix :: A pointer to the source 2x2 matrix. */
- /* */
- /* <Note> */
- /* The result is undefined if either `vector' or `matrix' is invalid. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Vector_Transform
+ *
+ * @description:
+ * Transform a single vector through a 2x2 matrix.
+ *
+ * @inout:
+ * vector ::
+ * The target vector to transform.
+ *
+ * @input:
+ * matrix ::
+ * A pointer to the source 2x2 matrix.
+ *
+ * @note:
+ * The result is undefined if either `vector` or `matrix` is invalid.
+ */
FT_EXPORT( void )
- FT_Vector_Transform( FT_Vector* vec,
+ FT_Vector_Transform( FT_Vector* vector,
const FT_Matrix* matrix );
- /*************************************************************************/
- /* */
- /* <Section> */
- /* version */
- /* */
- /* <Title> */
- /* FreeType Version */
- /* */
- /* <Abstract> */
- /* Functions and macros related to FreeType versions. */
- /* */
- /* <Description> */
- /* Note that those functions and macros are of limited use because */
- /* even a new release of FreeType with only documentation changes */
- /* increases the version number. */
- /* */
- /* <Order> */
- /* FT_Library_Version */
- /* */
- /* FREETYPE_MAJOR */
- /* FREETYPE_MINOR */
- /* FREETYPE_PATCH */
- /* */
- /* FT_Face_CheckTrueTypePatents */
- /* FT_Face_SetUnpatentedHinting */
- /* */
- /* FREETYPE_XXX */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * @section:
+ * version
+ *
+ * @title:
+ * FreeType Version
+ *
+ * @abstract:
+ * Functions and macros related to FreeType versions.
+ *
+ * @description:
+ * Note that those functions and macros are of limited use because even a
+ * new release of FreeType with only documentation changes increases the
+ * version number.
+ *
+ * @order:
+ * FT_Library_Version
+ *
+ * FREETYPE_MAJOR
+ * FREETYPE_MINOR
+ * FREETYPE_PATCH
+ *
+ * FT_Face_CheckTrueTypePatents
+ * FT_Face_SetUnpatentedHinting
+ *
+ */
- /*************************************************************************
+ /**************************************************************************
*
* @enum:
* FREETYPE_XXX
*
* @description:
- * These three macros identify the FreeType source code version.
- * Use @FT_Library_Version to access them at runtime.
+ * These three macros identify the FreeType source code version. Use
+ * @FT_Library_Version to access them at runtime.
*
* @values:
- * FREETYPE_MAJOR :: The major version number.
- * FREETYPE_MINOR :: The minor version number.
- * FREETYPE_PATCH :: The patch level.
+ * FREETYPE_MAJOR ::
+ * The major version number.
+ * FREETYPE_MINOR ::
+ * The minor version number.
+ * FREETYPE_PATCH ::
+ * The patch level.
*
* @note:
- * The version number of FreeType if built as a dynamic link library
- * with the `libtool' package is _not_ controlled by these three
- * macros.
+ * The version number of FreeType if built as a dynamic link library with
+ * the 'libtool' package is _not_ controlled by these three macros.
*
*/
#define FREETYPE_MAJOR 2
-#define FREETYPE_MINOR 9
-#define FREETYPE_PATCH 1
+#define FREETYPE_MINOR 10
+#define FREETYPE_PATCH 0
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Library_Version */
- /* */
- /* <Description> */
- /* Return the version of the FreeType library being used. This is */
- /* useful when dynamically linking to the library, since one cannot */
- /* use the macros @FREETYPE_MAJOR, @FREETYPE_MINOR, and */
- /* @FREETYPE_PATCH. */
- /* */
- /* <Input> */
- /* library :: A source library handle. */
- /* */
- /* <Output> */
- /* amajor :: The major version number. */
- /* */
- /* aminor :: The minor version number. */
- /* */
- /* apatch :: The patch version number. */
- /* */
- /* <Note> */
- /* The reason why this function takes a `library' argument is because */
- /* certain programs implement library initialization in a custom way */
- /* that doesn't use @FT_Init_FreeType. */
- /* */
- /* In such cases, the library version might not be available before */
- /* the library object has been created. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Library_Version
+ *
+ * @description:
+ * Return the version of the FreeType library being used. This is useful
+ * when dynamically linking to the library, since one cannot use the
+ * macros @FREETYPE_MAJOR, @FREETYPE_MINOR, and @FREETYPE_PATCH.
+ *
+ * @input:
+ * library ::
+ * A source library handle.
+ *
+ * @output:
+ * amajor ::
+ * The major version number.
+ *
+ * aminor ::
+ * The minor version number.
+ *
+ * apatch ::
+ * The patch version number.
+ *
+ * @note:
+ * The reason why this function takes a `library` argument is because
+ * certain programs implement library initialization in a custom way that
+ * doesn't use @FT_Init_FreeType.
+ *
+ * In such cases, the library version might not be available before the
+ * library object has been created.
+ */
FT_EXPORT( void )
FT_Library_Version( FT_Library library,
FT_Int *amajor,
@@ -4596,52 +4816,55 @@ FT_BEGIN_HEADER
FT_Int *apatch );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Face_CheckTrueTypePatents */
- /* */
- /* <Description> */
- /* Deprecated, does nothing. */
- /* */
- /* <Input> */
- /* face :: A face handle. */
- /* */
- /* <Return> */
- /* Always returns false. */
- /* */
- /* <Note> */
- /* Since May 2010, TrueType hinting is no longer patented. */
- /* */
- /* <Since> */
- /* 2.3.5 */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Face_CheckTrueTypePatents
+ *
+ * @description:
+ * Deprecated, does nothing.
+ *
+ * @input:
+ * face ::
+ * A face handle.
+ *
+ * @return:
+ * Always returns false.
+ *
+ * @note:
+ * Since May 2010, TrueType hinting is no longer patented.
+ *
+ * @since:
+ * 2.3.5
+ */
FT_EXPORT( FT_Bool )
FT_Face_CheckTrueTypePatents( FT_Face face );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Face_SetUnpatentedHinting */
- /* */
- /* <Description> */
- /* Deprecated, does nothing. */
- /* */
- /* <Input> */
- /* face :: A face handle. */
- /* */
- /* value :: New boolean setting. */
- /* */
- /* <Return> */
- /* Always returns false. */
- /* */
- /* <Note> */
- /* Since May 2010, TrueType hinting is no longer patented. */
- /* */
- /* <Since> */
- /* 2.3.5 */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Face_SetUnpatentedHinting
+ *
+ * @description:
+ * Deprecated, does nothing.
+ *
+ * @input:
+ * face ::
+ * A face handle.
+ *
+ * value ::
+ * New boolean setting.
+ *
+ * @return:
+ * Always returns false.
+ *
+ * @note:
+ * Since May 2010, TrueType hinting is no longer patented.
+ *
+ * @since:
+ * 2.3.5
+ */
FT_EXPORT( FT_Bool )
FT_Face_SetUnpatentedHinting( FT_Face face,
FT_Bool value );
diff --git a/thirdparty/freetype/include/freetype/ftadvanc.h b/thirdparty/freetype/include/freetype/ftadvanc.h
index f78e8b1a9d..95c38f92bd 100644
--- a/thirdparty/freetype/include/freetype/ftadvanc.h
+++ b/thirdparty/freetype/include/freetype/ftadvanc.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftadvanc.h */
-/* */
-/* Quick computation of advance widths (specification only). */
-/* */
-/* Copyright 2008-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftadvanc.h
+ *
+ * Quick computation of advance widths (specification only).
+ *
+ * Copyright (C) 2008-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTADVANC_H_
@@ -56,68 +56,67 @@ FT_BEGIN_HEADER
*/
- /*************************************************************************/
- /* */
- /* <Const> */
- /* FT_ADVANCE_FLAG_FAST_ONLY */
- /* */
- /* <Description> */
- /* A bit-flag to be OR-ed with the `flags' parameter of the */
- /* @FT_Get_Advance and @FT_Get_Advances functions. */
- /* */
- /* If set, it indicates that you want these functions to fail if the */
- /* corresponding hinting mode or font driver doesn't allow for very */
- /* quick advance computation. */
- /* */
- /* Typically, glyphs that are either unscaled, unhinted, bitmapped, */
- /* or light-hinted can have their advance width computed very */
- /* quickly. */
- /* */
- /* Normal and bytecode hinted modes that require loading, scaling, */
- /* and hinting of the glyph outline, are extremely slow by */
- /* comparison. */
- /* */
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_ADVANCE_FLAG_FAST_ONLY
+ *
+ * @description:
+ * A bit-flag to be OR-ed with the `flags` parameter of the
+ * @FT_Get_Advance and @FT_Get_Advances functions.
+ *
+ * If set, it indicates that you want these functions to fail if the
+ * corresponding hinting mode or font driver doesn't allow for very quick
+ * advance computation.
+ *
+ * Typically, glyphs that are either unscaled, unhinted, bitmapped, or
+ * light-hinted can have their advance width computed very quickly.
+ *
+ * Normal and bytecode hinted modes that require loading, scaling, and
+ * hinting of the glyph outline, are extremely slow by comparison.
+ */
#define FT_ADVANCE_FLAG_FAST_ONLY 0x20000000L
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Get_Advance */
- /* */
- /* <Description> */
- /* Retrieve the advance value of a given glyph outline in an */
- /* @FT_Face. */
- /* */
- /* <Input> */
- /* face :: The source @FT_Face handle. */
- /* */
- /* gindex :: The glyph index. */
- /* */
- /* load_flags :: A set of bit flags similar to those used when */
- /* calling @FT_Load_Glyph, used to determine what kind */
- /* of advances you need. */
- /* <Output> */
- /* padvance :: The advance value. If scaling is performed (based on */
- /* the value of `load_flags'), the advance value is in */
- /* 16.16 format. Otherwise, it is in font units. */
- /* */
- /* If @FT_LOAD_VERTICAL_LAYOUT is set, this is the */
- /* vertical advance corresponding to a vertical layout. */
- /* Otherwise, it is the horizontal advance in a */
- /* horizontal layout. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- /* <Note> */
- /* This function may fail if you use @FT_ADVANCE_FLAG_FAST_ONLY and */
- /* if the corresponding font backend doesn't have a quick way to */
- /* retrieve the advances. */
- /* */
- /* A scaled advance is returned in 16.16 format but isn't transformed */
- /* by the affine transformation specified by @FT_Set_Transform. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Advance
+ *
+ * @description:
+ * Retrieve the advance value of a given glyph outline in an @FT_Face.
+ *
+ * @input:
+ * face ::
+ * The source @FT_Face handle.
+ *
+ * gindex ::
+ * The glyph index.
+ *
+ * load_flags ::
+ * A set of bit flags similar to those used when calling
+ * @FT_Load_Glyph, used to determine what kind of advances you need.
+ * @output:
+ * padvance ::
+ * The advance value. If scaling is performed (based on the value of
+ * `load_flags`), the advance value is in 16.16 format. Otherwise, it
+ * is in font units.
+ *
+ * If @FT_LOAD_VERTICAL_LAYOUT is set, this is the vertical advance
+ * corresponding to a vertical layout. Otherwise, it is the horizontal
+ * advance in a horizontal layout.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * This function may fail if you use @FT_ADVANCE_FLAG_FAST_ONLY and if
+ * the corresponding font backend doesn't have a quick way to retrieve
+ * the advances.
+ *
+ * A scaled advance is returned in 16.16 format but isn't transformed by
+ * the affine transformation specified by @FT_Set_Transform.
+ */
FT_EXPORT( FT_Error )
FT_Get_Advance( FT_Face face,
FT_UInt gindex,
@@ -125,50 +124,52 @@ FT_BEGIN_HEADER
FT_Fixed *padvance );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Get_Advances */
- /* */
- /* <Description> */
- /* Retrieve the advance values of several glyph outlines in an */
- /* @FT_Face. */
- /* */
- /* <Input> */
- /* face :: The source @FT_Face handle. */
- /* */
- /* start :: The first glyph index. */
- /* */
- /* count :: The number of advance values you want to retrieve. */
- /* */
- /* load_flags :: A set of bit flags similar to those used when */
- /* calling @FT_Load_Glyph. */
- /* */
- /* <Output> */
- /* padvance :: The advance values. This array, to be provided by the */
- /* caller, must contain at least `count' elements. */
- /* */
- /* If scaling is performed (based on the value of */
- /* `load_flags'), the advance values are in 16.16 format. */
- /* Otherwise, they are in font units. */
- /* */
- /* If @FT_LOAD_VERTICAL_LAYOUT is set, these are the */
- /* vertical advances corresponding to a vertical layout. */
- /* Otherwise, they are the horizontal advances in a */
- /* horizontal layout. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- /* <Note> */
- /* This function may fail if you use @FT_ADVANCE_FLAG_FAST_ONLY and */
- /* if the corresponding font backend doesn't have a quick way to */
- /* retrieve the advances. */
- /* */
- /* Scaled advances are returned in 16.16 format but aren't */
- /* transformed by the affine transformation specified by */
- /* @FT_Set_Transform. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Advances
+ *
+ * @description:
+ * Retrieve the advance values of several glyph outlines in an @FT_Face.
+ *
+ * @input:
+ * face ::
+ * The source @FT_Face handle.
+ *
+ * start ::
+ * The first glyph index.
+ *
+ * count ::
+ * The number of advance values you want to retrieve.
+ *
+ * load_flags ::
+ * A set of bit flags similar to those used when calling
+ * @FT_Load_Glyph.
+ *
+ * @output:
+ * padvance ::
+ * The advance values. This array, to be provided by the caller, must
+ * contain at least `count` elements.
+ *
+ * If scaling is performed (based on the value of `load_flags`), the
+ * advance values are in 16.16 format. Otherwise, they are in font
+ * units.
+ *
+ * If @FT_LOAD_VERTICAL_LAYOUT is set, these are the vertical advances
+ * corresponding to a vertical layout. Otherwise, they are the
+ * horizontal advances in a horizontal layout.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * This function may fail if you use @FT_ADVANCE_FLAG_FAST_ONLY and if
+ * the corresponding font backend doesn't have a quick way to retrieve
+ * the advances.
+ *
+ * Scaled advances are returned in 16.16 format but aren't transformed by
+ * the affine transformation specified by @FT_Set_Transform.
+ */
FT_EXPORT( FT_Error )
FT_Get_Advances( FT_Face face,
FT_UInt start,
diff --git a/thirdparty/freetype/include/freetype/ftautoh.h b/thirdparty/freetype/include/freetype/ftautoh.h
deleted file mode 100644
index 2bb675ae46..0000000000
--- a/thirdparty/freetype/include/freetype/ftautoh.h
+++ /dev/null
@@ -1,533 +0,0 @@
-/***************************************************************************/
-/* */
-/* ftautoh.h */
-/* */
-/* FreeType API for controlling the auto-hinter (specification only). */
-/* */
-/* Copyright 2012-2017 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#ifndef FTAUTOH_H_
-#define FTAUTOH_H_
-
-#include <ft2build.h>
-#include FT_FREETYPE_H
-
-#ifdef FREETYPE_H
-#error "freetype.h of FreeType 1 has been loaded!"
-#error "Please fix the directory search order for header files"
-#error "so that freetype.h of FreeType 2 is found first."
-#endif
-
-
-FT_BEGIN_HEADER
-
-
- /**************************************************************************
- *
- * @section:
- * auto_hinter
- *
- * @title:
- * The auto-hinter
- *
- * @abstract:
- * Controlling the auto-hinting module.
- *
- * @description:
- * While FreeType's auto-hinter doesn't expose API functions by itself,
- * it is possible to control its behaviour with @FT_Property_Set and
- * @FT_Property_Get. The following lists the available properties
- * together with the necessary macros and structures.
- *
- * Note that the auto-hinter's module name is `autofitter' for
- * historical reasons.
- *
- */
-
-
- /**************************************************************************
- *
- * @property:
- * glyph-to-script-map
- *
- * @description:
- * *Experimental* *only*
- *
- * The auto-hinter provides various script modules to hint glyphs.
- * Examples of supported scripts are Latin or CJK. Before a glyph is
- * auto-hinted, the Unicode character map of the font gets examined, and
- * the script is then determined based on Unicode character ranges, see
- * below.
- *
- * OpenType fonts, however, often provide much more glyphs than
- * character codes (small caps, superscripts, ligatures, swashes, etc.),
- * to be controlled by so-called `features'. Handling OpenType features
- * can be quite complicated and thus needs a separate library on top of
- * FreeType.
- *
- * The mapping between glyph indices and scripts (in the auto-hinter
- * sense, see the @FT_AUTOHINTER_SCRIPT_XXX values) is stored as an
- * array with `num_glyphs' elements, as found in the font's @FT_Face
- * structure. The `glyph-to-script-map' property returns a pointer to
- * this array, which can be modified as needed. Note that the
- * modification should happen before the first glyph gets processed by
- * the auto-hinter so that the global analysis of the font shapes
- * actually uses the modified mapping.
- *
- * The following example code demonstrates how to access it (omitting
- * the error handling).
- *
- * {
- * FT_Library library;
- * FT_Face face;
- * FT_Prop_GlyphToScriptMap prop;
- *
- *
- * FT_Init_FreeType( &library );
- * FT_New_Face( library, "foo.ttf", 0, &face );
- *
- * prop.face = face;
- *
- * FT_Property_Get( library, "autofitter",
- * "glyph-to-script-map", &prop );
- *
- * // adjust `prop.map' as needed right here
- *
- * FT_Load_Glyph( face, ..., FT_LOAD_FORCE_AUTOHINT );
- * }
- *
- */
-
-
- /**************************************************************************
- *
- * @enum:
- * FT_AUTOHINTER_SCRIPT_XXX
- *
- * @description:
- * *Experimental* *only*
- *
- * A list of constants used for the @glyph-to-script-map property to
- * specify the script submodule the auto-hinter should use for hinting a
- * particular glyph.
- *
- * @values:
- * FT_AUTOHINTER_SCRIPT_NONE ::
- * Don't auto-hint this glyph.
- *
- * FT_AUTOHINTER_SCRIPT_LATIN ::
- * Apply the latin auto-hinter. For the auto-hinter, `latin' is a
- * very broad term, including Cyrillic and Greek also since characters
- * from those scripts share the same design constraints.
- *
- * By default, characters from the following Unicode ranges are
- * assigned to this submodule.
- *
- * {
- * U+0020 - U+007F // Basic Latin (no control characters)
- * U+00A0 - U+00FF // Latin-1 Supplement (no control characters)
- * U+0100 - U+017F // Latin Extended-A
- * U+0180 - U+024F // Latin Extended-B
- * U+0250 - U+02AF // IPA Extensions
- * U+02B0 - U+02FF // Spacing Modifier Letters
- * U+0300 - U+036F // Combining Diacritical Marks
- * U+0370 - U+03FF // Greek and Coptic
- * U+0400 - U+04FF // Cyrillic
- * U+0500 - U+052F // Cyrillic Supplement
- * U+1D00 - U+1D7F // Phonetic Extensions
- * U+1D80 - U+1DBF // Phonetic Extensions Supplement
- * U+1DC0 - U+1DFF // Combining Diacritical Marks Supplement
- * U+1E00 - U+1EFF // Latin Extended Additional
- * U+1F00 - U+1FFF // Greek Extended
- * U+2000 - U+206F // General Punctuation
- * U+2070 - U+209F // Superscripts and Subscripts
- * U+20A0 - U+20CF // Currency Symbols
- * U+2150 - U+218F // Number Forms
- * U+2460 - U+24FF // Enclosed Alphanumerics
- * U+2C60 - U+2C7F // Latin Extended-C
- * U+2DE0 - U+2DFF // Cyrillic Extended-A
- * U+2E00 - U+2E7F // Supplemental Punctuation
- * U+A640 - U+A69F // Cyrillic Extended-B
- * U+A720 - U+A7FF // Latin Extended-D
- * U+FB00 - U+FB06 // Alphab. Present. Forms (Latin Ligatures)
- * U+1D400 - U+1D7FF // Mathematical Alphanumeric Symbols
- * U+1F100 - U+1F1FF // Enclosed Alphanumeric Supplement
- * }
- *
- * FT_AUTOHINTER_SCRIPT_CJK ::
- * Apply the CJK auto-hinter, covering Chinese, Japanese, Korean, old
- * Vietnamese, and some other scripts.
- *
- * By default, characters from the following Unicode ranges are
- * assigned to this submodule.
- *
- * {
- * U+1100 - U+11FF // Hangul Jamo
- * U+2E80 - U+2EFF // CJK Radicals Supplement
- * U+2F00 - U+2FDF // Kangxi Radicals
- * U+2FF0 - U+2FFF // Ideographic Description Characters
- * U+3000 - U+303F // CJK Symbols and Punctuation
- * U+3040 - U+309F // Hiragana
- * U+30A0 - U+30FF // Katakana
- * U+3100 - U+312F // Bopomofo
- * U+3130 - U+318F // Hangul Compatibility Jamo
- * U+3190 - U+319F // Kanbun
- * U+31A0 - U+31BF // Bopomofo Extended
- * U+31C0 - U+31EF // CJK Strokes
- * U+31F0 - U+31FF // Katakana Phonetic Extensions
- * U+3200 - U+32FF // Enclosed CJK Letters and Months
- * U+3300 - U+33FF // CJK Compatibility
- * U+3400 - U+4DBF // CJK Unified Ideographs Extension A
- * U+4DC0 - U+4DFF // Yijing Hexagram Symbols
- * U+4E00 - U+9FFF // CJK Unified Ideographs
- * U+A960 - U+A97F // Hangul Jamo Extended-A
- * U+AC00 - U+D7AF // Hangul Syllables
- * U+D7B0 - U+D7FF // Hangul Jamo Extended-B
- * U+F900 - U+FAFF // CJK Compatibility Ideographs
- * U+FE10 - U+FE1F // Vertical forms
- * U+FE30 - U+FE4F // CJK Compatibility Forms
- * U+FF00 - U+FFEF // Halfwidth and Fullwidth Forms
- * U+1B000 - U+1B0FF // Kana Supplement
- * U+1D300 - U+1D35F // Tai Xuan Hing Symbols
- * U+1F200 - U+1F2FF // Enclosed Ideographic Supplement
- * U+20000 - U+2A6DF // CJK Unified Ideographs Extension B
- * U+2A700 - U+2B73F // CJK Unified Ideographs Extension C
- * U+2B740 - U+2B81F // CJK Unified Ideographs Extension D
- * U+2F800 - U+2FA1F // CJK Compatibility Ideographs Supplement
- * }
- *
- * FT_AUTOHINTER_SCRIPT_INDIC ::
- * Apply the indic auto-hinter, covering all major scripts from the
- * Indian sub-continent and some other related scripts like Thai, Lao,
- * or Tibetan.
- *
- * By default, characters from the following Unicode ranges are
- * assigned to this submodule.
- *
- * {
- * U+0900 - U+0DFF // Indic Range
- * U+0F00 - U+0FFF // Tibetan
- * U+1900 - U+194F // Limbu
- * U+1B80 - U+1BBF // Sundanese
- * U+A800 - U+A82F // Syloti Nagri
- * U+ABC0 - U+ABFF // Meetei Mayek
- * U+11800 - U+118DF // Sharada
- * }
- *
- * Note that currently Indic support is rudimentary only, missing blue
- * zone support.
- *
- */
-#define FT_AUTOHINTER_SCRIPT_NONE 0
-#define FT_AUTOHINTER_SCRIPT_LATIN 1
-#define FT_AUTOHINTER_SCRIPT_CJK 2
-#define FT_AUTOHINTER_SCRIPT_INDIC 3
-
-
- /**************************************************************************
- *
- * @struct:
- * FT_Prop_GlyphToScriptMap
- *
- * @description:
- * *Experimental* *only*
- *
- * The data exchange structure for the @glyph-to-script-map property.
- *
- */
- typedef struct FT_Prop_GlyphToScriptMap_
- {
- FT_Face face;
- FT_UShort* map;
-
- } FT_Prop_GlyphToScriptMap;
-
-
- /**************************************************************************
- *
- * @property:
- * fallback-script
- *
- * @description:
- * *Experimental* *only*
- *
- * If no auto-hinter script module can be assigned to a glyph, a
- * fallback script gets assigned to it (see also the
- * @glyph-to-script-map property). By default, this is
- * @FT_AUTOHINTER_SCRIPT_CJK. Using the `fallback-script' property,
- * this fallback value can be changed.
- *
- * {
- * FT_Library library;
- * FT_UInt fallback_script = FT_AUTOHINTER_SCRIPT_NONE;
- *
- *
- * FT_Init_FreeType( &library );
- *
- * FT_Property_Set( library, "autofitter",
- * "fallback-script", &fallback_script );
- * }
- *
- * @note:
- * This property can be used with @FT_Property_Get also.
- *
- * It's important to use the right timing for changing this value: The
- * creation of the glyph-to-script map that eventually uses the
- * fallback script value gets triggered either by setting or reading a
- * face-specific property like @glyph-to-script-map, or by auto-hinting
- * any glyph from that face. In particular, if you have already created
- * an @FT_Face structure but not loaded any glyph (using the
- * auto-hinter), a change of the fallback script will affect this face.
- *
- */
-
-
- /**************************************************************************
- *
- * @property:
- * default-script
- *
- * @description:
- * *Experimental* *only*
- *
- * If FreeType gets compiled with FT_CONFIG_OPTION_USE_HARFBUZZ to make
- * the HarfBuzz library access OpenType features for getting better
- * glyph coverages, this property sets the (auto-fitter) script to be
- * used for the default (OpenType) script data of a font's GSUB table.
- * Features for the default script are intended for all scripts not
- * explicitly handled in GSUB; an example is a `dlig' feature,
- * containing the combination of the characters `T', `E', and `L' to
- * form a `TEL' ligature.
- *
- * By default, this is @FT_AUTOHINTER_SCRIPT_LATIN. Using the
- * `default-script' property, this default value can be changed.
- *
- * {
- * FT_Library library;
- * FT_UInt default_script = FT_AUTOHINTER_SCRIPT_NONE;
- *
- *
- * FT_Init_FreeType( &library );
- *
- * FT_Property_Set( library, "autofitter",
- * "default-script", &default_script );
- * }
- *
- * @note:
- * This property can be used with @FT_Property_Get also.
- *
- * It's important to use the right timing for changing this value: The
- * creation of the glyph-to-script map that eventually uses the
- * default script value gets triggered either by setting or reading a
- * face-specific property like @glyph-to-script-map, or by auto-hinting
- * any glyph from that face. In particular, if you have already created
- * an @FT_Face structure but not loaded any glyph (using the
- * auto-hinter), a change of the default script will affect this face.
- *
- */
-
-
- /**************************************************************************
- *
- * @property:
- * increase-x-height
- *
- * @description:
- * For ppem values in the range 6~<= ppem <= `increase-x-height', round
- * up the font's x~height much more often than normally. If the value
- * is set to~0, which is the default, this feature is switched off. Use
- * this property to improve the legibility of small font sizes if
- * necessary.
- *
- * {
- * FT_Library library;
- * FT_Face face;
- * FT_Prop_IncreaseXHeight prop;
- *
- *
- * FT_Init_FreeType( &library );
- * FT_New_Face( library, "foo.ttf", 0, &face );
- * FT_Set_Char_Size( face, 10 * 64, 0, 72, 0 );
- *
- * prop.face = face;
- * prop.limit = 14;
- *
- * FT_Property_Set( library, "autofitter",
- * "increase-x-height", &prop );
- * }
- *
- * @note:
- * This property can be used with @FT_Property_Get also.
- *
- * Set this value right after calling @FT_Set_Char_Size, but before
- * loading any glyph (using the auto-hinter).
- *
- */
-
-
- /**************************************************************************
- *
- * @struct:
- * FT_Prop_IncreaseXHeight
- *
- * @description:
- * The data exchange structure for the @increase-x-height property.
- *
- */
- typedef struct FT_Prop_IncreaseXHeight_
- {
- FT_Face face;
- FT_UInt limit;
-
- } FT_Prop_IncreaseXHeight;
-
-
- /**************************************************************************
- *
- * @property:
- * warping
- *
- * @description:
- * *Experimental* *only*
- *
- * If FreeType gets compiled with option AF_CONFIG_OPTION_USE_WARPER to
- * activate the warp hinting code in the auto-hinter, this property
- * switches warping on and off.
- *
- * Warping only works in `normal' auto-hinting mode replacing it.
- * The idea of the code is to slightly scale and shift a glyph along
- * the non-hinted dimension (which is usually the horizontal axis) so
- * that as much of its segments are aligned (more or less) to the grid.
- * To find out a glyph's optimal scaling and shifting value, various
- * parameter combinations are tried and scored.
- *
- * By default, warping is off. The example below shows how to switch on
- * warping (omitting the error handling).
- *
- * {
- * FT_Library library;
- * FT_Bool warping = 1;
- *
- *
- * FT_Init_FreeType( &library );
- *
- * FT_Property_Set( library, "autofitter",
- * "warping", &warping );
- * }
- *
- * @note:
- * This property can be used with @FT_Property_Get also.
- *
- * This property can be set via the `FREETYPE_PROPERTIES' environment
- * variable (using values 1 and 0 for `on' and `off', respectively).
- *
- * The warping code can also change advance widths. Have a look at the
- * `lsb_delta' and `rsb_delta' fields in the @FT_GlyphSlotRec structure
- * for details on improving inter-glyph distances while rendering.
- *
- * Since warping is a global property of the auto-hinter it is best to
- * change its value before rendering any face. Otherwise, you should
- * reload all faces that get auto-hinted in `normal' hinting mode.
- *
- */
-
-
- /**************************************************************************
- *
- * @property:
- * no-stem-darkening[autofit]
- *
- * @description:
- * *Experimental* *only*, *requires* *linear* *alpha* *blending* *and*
- * *gamma* *correction*
- *
- * Stem darkening emboldens glyphs at smaller sizes to make them more
- * readable on common low-DPI screens when using linear alpha blending
- * and gamma correction, see @FT_Render_Glyph. When not using linear
- * alpha blending and gamma correction, glyphs will appear heavy and
- * fuzzy!
- *
- * Gamma correction essentially lightens fonts since shades of grey are
- * shifted to higher pixel values (=~higher brightness) to match the
- * original intention to the reality of our screens. The side-effect is
- * that glyphs `thin out'. Mac OS~X and Adobe's proprietary font
- * rendering library implement a counter-measure: stem darkening at
- * smaller sizes where shades of gray dominate. By emboldening a glyph
- * slightly in relation to its pixel size, individual pixels get higher
- * coverage of filled-in outlines and are therefore `blacker'. This
- * counteracts the `thinning out' of glyphs, making text remain readable
- * at smaller sizes. All glyphs that pass through the auto-hinter will
- * be emboldened unless this property is set to TRUE.
- *
- * See the description of the CFF driver for algorithmic details. Total
- * consistency with the CFF driver is currently not achieved because the
- * emboldening method differs and glyphs must be scaled down on the
- * Y-axis to keep outline points inside their precomputed blue zones.
- * The smaller the size (especially 9ppem and down), the higher the loss
- * of emboldening versus the CFF driver.
- *
- * This property can be set via the `FREETYPE_PROPERTIES' environment
- * variable similar to the CFF driver. It can also be set per face
- * using @FT_Face_Properties with @FT_PARAM_TAG_STEM_DARKENING.
- *
- */
-
-
- /**************************************************************************
- *
- * @constant:
- * FT_PARAM_TAG_STEM_DARKENING
- *
- * @description:
- * An @FT_Parameter tag to be used with @FT_Face_Properties. The
- * corresponding Boolean argument specifies whether to apply stem
- * darkening, overriding the global default values or the values set up
- * with @FT_Property_Set (see @no-stem-darkening[autofit] and
- * @no-stem-darkening[cff]).
- *
- * This is a passive setting that only takes effect if the font driver
- * or autohinter honors it, which the CFF driver always does, but the
- * autohinter only in `light' hinting mode (as of version 2.7.0).
- *
- */
-#define FT_PARAM_TAG_STEM_DARKENING \
- FT_MAKE_TAG( 'd', 'a', 'r', 'k' )
-
-
- /**************************************************************************
- *
- * @property:
- * darkening-parameters[autofit]
- *
- * @description:
- * *Experimental* *only*
- *
- * See the description of the CFF driver for details. This
- * implementation appropriates the
- * CFF_CONFIG_OPTION_DARKENING_PARAMETER_* #defines for consistency.
- * Note the differences described in @no-stem-darkening[autofit].
- *
- * This property can be set via the `FREETYPE_PROPERTIES' environment
- * variable similar to the CFF driver.
- */
-
-
- /* */
-
-
-FT_END_HEADER
-
-#endif /* FTAUTOH_H_ */
-
-
-/* END */
diff --git a/thirdparty/freetype/include/freetype/ftbbox.h b/thirdparty/freetype/include/freetype/ftbbox.h
index f9eb70b137..22da70c0dc 100644
--- a/thirdparty/freetype/include/freetype/ftbbox.h
+++ b/thirdparty/freetype/include/freetype/ftbbox.h
@@ -1,30 +1,30 @@
-/***************************************************************************/
-/* */
-/* ftbbox.h */
-/* */
-/* FreeType exact bbox computation (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* This component has a _single_ role: to compute exact outline bounding */
- /* boxes. */
- /* */
- /* It is separated from the rest of the engine for various technical */
- /* reasons. It may well be integrated in `ftoutln' later. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * ftbbox.h
+ *
+ * FreeType exact bbox computation (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * This component has a _single_ role: to compute exact outline bounding
+ * boxes.
+ *
+ * It is separated from the rest of the engine for various technical
+ * reasons. It may well be integrated in 'ftoutln' later.
+ *
+ */
#ifndef FTBBOX_H_
@@ -44,43 +44,44 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* <Section> */
- /* outline_processing */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Outline_Get_BBox */
- /* */
- /* <Description> */
- /* Compute the exact bounding box of an outline. This is slower */
- /* than computing the control box. However, it uses an advanced */
- /* algorithm that returns _very_ quickly when the two boxes */
- /* coincide. Otherwise, the outline Bezier arcs are traversed to */
- /* extract their extrema. */
- /* */
- /* <Input> */
- /* outline :: A pointer to the source outline. */
- /* */
- /* <Output> */
- /* abbox :: The outline's exact bounding box. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* If the font is tricky and the glyph has been loaded with */
- /* @FT_LOAD_NO_SCALE, the resulting BBox is meaningless. To get */
- /* reasonable values for the BBox it is necessary to load the glyph */
- /* at a large ppem value (so that the hinting instructions can */
- /* properly shift and scale the subglyphs), then extracting the BBox, */
- /* which can be eventually converted back to font units. */
- /* */
+ /**************************************************************************
+ *
+ * @section:
+ * outline_processing
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Outline_Get_BBox
+ *
+ * @description:
+ * Compute the exact bounding box of an outline. This is slower than
+ * computing the control box. However, it uses an advanced algorithm
+ * that returns _very_ quickly when the two boxes coincide. Otherwise,
+ * the outline Bezier arcs are traversed to extract their extrema.
+ *
+ * @input:
+ * outline ::
+ * A pointer to the source outline.
+ *
+ * @output:
+ * abbox ::
+ * The outline's exact bounding box.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * If the font is tricky and the glyph has been loaded with
+ * @FT_LOAD_NO_SCALE, the resulting BBox is meaningless. To get
+ * reasonable values for the BBox it is necessary to load the glyph at a
+ * large ppem value (so that the hinting instructions can properly shift
+ * and scale the subglyphs), then extracting the BBox, which can be
+ * eventually converted back to font units.
+ */
FT_EXPORT( FT_Error )
FT_Outline_Get_BBox( FT_Outline* outline,
FT_BBox *abbox );
diff --git a/thirdparty/freetype/include/freetype/ftbdf.h b/thirdparty/freetype/include/freetype/ftbdf.h
index 1b6dea6586..1c46da5985 100644
--- a/thirdparty/freetype/include/freetype/ftbdf.h
+++ b/thirdparty/freetype/include/freetype/ftbdf.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftbdf.h */
-/* */
-/* FreeType API for accessing BDF-specific strings (specification). */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftbdf.h
+ *
+ * FreeType API for accessing BDF-specific strings (specification).
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTBDF_H_
@@ -32,25 +32,25 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* <Section> */
- /* bdf_fonts */
- /* */
- /* <Title> */
- /* BDF and PCF Files */
- /* */
- /* <Abstract> */
- /* BDF and PCF specific API. */
- /* */
- /* <Description> */
- /* This section contains the declaration of functions specific to BDF */
- /* and PCF fonts. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * @section:
+ * bdf_fonts
+ *
+ * @title:
+ * BDF and PCF Files
+ *
+ * @abstract:
+ * BDF and PCF specific API.
+ *
+ * @description:
+ * This section contains the declaration of functions specific to BDF and
+ * PCF fonts.
+ *
+ */
- /**********************************************************************
+ /**************************************************************************
*
* @enum:
* BDF_PropertyType
@@ -81,40 +81,40 @@ FT_BEGIN_HEADER
} BDF_PropertyType;
- /**********************************************************************
+ /**************************************************************************
*
* @type:
* BDF_Property
*
* @description:
- * A handle to a @BDF_PropertyRec structure to model a given
- * BDF/PCF property.
+ * A handle to a @BDF_PropertyRec structure to model a given BDF/PCF
+ * property.
*/
typedef struct BDF_PropertyRec_* BDF_Property;
- /**********************************************************************
- *
- * @struct:
- * BDF_PropertyRec
- *
- * @description:
- * This structure models a given BDF/PCF property.
- *
- * @fields:
- * type ::
- * The property type.
- *
- * u.atom ::
- * The atom string, if type is @BDF_PROPERTY_TYPE_ATOM. May be
- * NULL, indicating an empty string.
- *
- * u.integer ::
- * A signed integer, if type is @BDF_PROPERTY_TYPE_INTEGER.
- *
- * u.cardinal ::
- * An unsigned integer, if type is @BDF_PROPERTY_TYPE_CARDINAL.
- */
+ /**************************************************************************
+ *
+ * @struct:
+ * BDF_PropertyRec
+ *
+ * @description:
+ * This structure models a given BDF/PCF property.
+ *
+ * @fields:
+ * type ::
+ * The property type.
+ *
+ * u.atom ::
+ * The atom string, if type is @BDF_PROPERTY_TYPE_ATOM. May be
+ * `NULL`, indicating an empty string.
+ *
+ * u.integer ::
+ * A signed integer, if type is @BDF_PROPERTY_TYPE_INTEGER.
+ *
+ * u.cardinal ::
+ * An unsigned integer, if type is @BDF_PROPERTY_TYPE_CARDINAL.
+ */
typedef struct BDF_PropertyRec_
{
BDF_PropertyType type;
@@ -128,73 +128,76 @@ FT_BEGIN_HEADER
} BDF_PropertyRec;
- /**********************************************************************
- *
- * @function:
- * FT_Get_BDF_Charset_ID
- *
- * @description:
- * Retrieve a BDF font character set identity, according to
- * the BDF specification.
- *
- * @input:
- * face ::
- * A handle to the input face.
- *
- * @output:
- * acharset_encoding ::
- * Charset encoding, as a C~string, owned by the face.
- *
- * acharset_registry ::
- * Charset registry, as a C~string, owned by the face.
- *
- * @return:
- * FreeType error code. 0~means success.
- *
- * @note:
- * This function only works with BDF faces, returning an error otherwise.
- */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_BDF_Charset_ID
+ *
+ * @description:
+ * Retrieve a BDF font character set identity, according to the BDF
+ * specification.
+ *
+ * @input:
+ * face ::
+ * A handle to the input face.
+ *
+ * @output:
+ * acharset_encoding ::
+ * Charset encoding, as a C~string, owned by the face.
+ *
+ * acharset_registry ::
+ * Charset registry, as a C~string, owned by the face.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * This function only works with BDF faces, returning an error otherwise.
+ */
FT_EXPORT( FT_Error )
FT_Get_BDF_Charset_ID( FT_Face face,
const char* *acharset_encoding,
const char* *acharset_registry );
- /**********************************************************************
- *
- * @function:
- * FT_Get_BDF_Property
- *
- * @description:
- * Retrieve a BDF property from a BDF or PCF font file.
- *
- * @input:
- * face :: A handle to the input face.
- *
- * name :: The property name.
- *
- * @output:
- * aproperty :: The property.
- *
- * @return:
- * FreeType error code. 0~means success.
- *
- * @note:
- * This function works with BDF _and_ PCF fonts. It returns an error
- * otherwise. It also returns an error if the property is not in the
- * font.
- *
- * A `property' is a either key-value pair within the STARTPROPERTIES
- * ... ENDPROPERTIES block of a BDF font or a key-value pair from the
- * `info->props' array within a `FontRec' structure of a PCF font.
- *
- * Integer properties are always stored as `signed' within PCF fonts;
- * consequently, @BDF_PROPERTY_TYPE_CARDINAL is a possible return value
- * for BDF fonts only.
- *
- * In case of error, `aproperty->type' is always set to
- * @BDF_PROPERTY_TYPE_NONE.
- */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_BDF_Property
+ *
+ * @description:
+ * Retrieve a BDF property from a BDF or PCF font file.
+ *
+ * @input:
+ * face ::
+ * A handle to the input face.
+ *
+ * name ::
+ * The property name.
+ *
+ * @output:
+ * aproperty ::
+ * The property.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * This function works with BDF _and_ PCF fonts. It returns an error
+ * otherwise. It also returns an error if the property is not in the
+ * font.
+ *
+ * A 'property' is a either key-value pair within the STARTPROPERTIES
+ * ... ENDPROPERTIES block of a BDF font or a key-value pair from the
+ * `info->props` array within a `FontRec` structure of a PCF font.
+ *
+ * Integer properties are always stored as 'signed' within PCF fonts;
+ * consequently, @BDF_PROPERTY_TYPE_CARDINAL is a possible return value
+ * for BDF fonts only.
+ *
+ * In case of error, `aproperty->type` is always set to
+ * @BDF_PROPERTY_TYPE_NONE.
+ */
FT_EXPORT( FT_Error )
FT_Get_BDF_Property( FT_Face face,
const char* prop_name,
diff --git a/thirdparty/freetype/include/freetype/ftbitmap.h b/thirdparty/freetype/include/freetype/ftbitmap.h
index a43187cad4..a6acdb9690 100644
--- a/thirdparty/freetype/include/freetype/ftbitmap.h
+++ b/thirdparty/freetype/include/freetype/ftbitmap.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftbitmap.h */
-/* */
-/* FreeType utility functions for bitmaps (specification). */
-/* */
-/* Copyright 2004-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftbitmap.h
+ *
+ * FreeType utility functions for bitmaps (specification).
+ *
+ * Copyright (C) 2004-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTBITMAP_H_
@@ -22,6 +22,7 @@
#include <ft2build.h>
#include FT_FREETYPE_H
+#include FT_COLOR_H
#ifdef FREETYPE_H
#error "freetype.h of FreeType 1 has been loaded!"
@@ -33,39 +34,46 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* <Section> */
- /* bitmap_handling */
- /* */
- /* <Title> */
- /* Bitmap Handling */
- /* */
- /* <Abstract> */
- /* Handling FT_Bitmap objects. */
- /* */
- /* <Description> */
- /* This section contains functions for handling @FT_Bitmap objects. */
- /* Note that none of the functions changes the bitmap's `flow' (as */
- /* indicated by the sign of the `pitch' field in `FT_Bitmap'). */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Bitmap_Init */
- /* */
- /* <Description> */
- /* Initialize a pointer to an @FT_Bitmap structure. */
- /* */
- /* <InOut> */
- /* abitmap :: A pointer to the bitmap structure. */
- /* */
- /* <Note> */
- /* A deprecated name for the same function is `FT_Bitmap_New'. */
- /* */
+ /**************************************************************************
+ *
+ * @section:
+ * bitmap_handling
+ *
+ * @title:
+ * Bitmap Handling
+ *
+ * @abstract:
+ * Handling FT_Bitmap objects.
+ *
+ * @description:
+ * This section contains functions for handling @FT_Bitmap objects,
+ * automatically adjusting the target's bitmap buffer size as needed.
+ *
+ * Note that none of the functions changes the bitmap's 'flow' (as
+ * indicated by the sign of the `pitch` field in @FT_Bitmap).
+ *
+ * To set the flow, assign an appropriate positive or negative value to
+ * the `pitch` field of the target @FT_Bitmap object after calling
+ * @FT_Bitmap_Init but before calling any of the other functions
+ * described here.
+ */
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Bitmap_Init
+ *
+ * @description:
+ * Initialize a pointer to an @FT_Bitmap structure.
+ *
+ * @inout:
+ * abitmap ::
+ * A pointer to the bitmap structure.
+ *
+ * @note:
+ * A deprecated name for the same function is `FT_Bitmap_New`.
+ */
FT_EXPORT( void )
FT_Bitmap_Init( FT_Bitmap *abitmap );
@@ -75,66 +83,77 @@ FT_BEGIN_HEADER
FT_Bitmap_New( FT_Bitmap *abitmap );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Bitmap_Copy */
- /* */
- /* <Description> */
- /* Copy a bitmap into another one. */
- /* */
- /* <Input> */
- /* library :: A handle to a library object. */
- /* */
- /* source :: A handle to the source bitmap. */
- /* */
- /* <Output> */
- /* target :: A handle to the target bitmap. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Bitmap_Copy
+ *
+ * @description:
+ * Copy a bitmap into another one.
+ *
+ * @input:
+ * library ::
+ * A handle to a library object.
+ *
+ * source ::
+ * A handle to the source bitmap.
+ *
+ * @output:
+ * target ::
+ * A handle to the target bitmap.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * `source->buffer` and `target->buffer` must neither be equal nor
+ * overlap.
+ */
FT_EXPORT( FT_Error )
FT_Bitmap_Copy( FT_Library library,
const FT_Bitmap *source,
FT_Bitmap *target );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Bitmap_Embolden */
- /* */
- /* <Description> */
- /* Embolden a bitmap. The new bitmap will be about `xStrength' */
- /* pixels wider and `yStrength' pixels higher. The left and bottom */
- /* borders are kept unchanged. */
- /* */
- /* <Input> */
- /* library :: A handle to a library object. */
- /* */
- /* xStrength :: How strong the glyph is emboldened horizontally. */
- /* Expressed in 26.6 pixel format. */
- /* */
- /* yStrength :: How strong the glyph is emboldened vertically. */
- /* Expressed in 26.6 pixel format. */
- /* */
- /* <InOut> */
- /* bitmap :: A handle to the target bitmap. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* The current implementation restricts `xStrength' to be less than */
- /* or equal to~8 if bitmap is of pixel_mode @FT_PIXEL_MODE_MONO. */
- /* */
- /* If you want to embolden the bitmap owned by a @FT_GlyphSlotRec, */
- /* you should call @FT_GlyphSlot_Own_Bitmap on the slot first. */
- /* */
- /* Bitmaps in @FT_PIXEL_MODE_GRAY2 and @FT_PIXEL_MODE_GRAY@ format */
- /* are converted to @FT_PIXEL_MODE_GRAY format (i.e., 8bpp). */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Bitmap_Embolden
+ *
+ * @description:
+ * Embolden a bitmap. The new bitmap will be about `xStrength` pixels
+ * wider and `yStrength` pixels higher. The left and bottom borders are
+ * kept unchanged.
+ *
+ * @input:
+ * library ::
+ * A handle to a library object.
+ *
+ * xStrength ::
+ * How strong the glyph is emboldened horizontally. Expressed in 26.6
+ * pixel format.
+ *
+ * yStrength ::
+ * How strong the glyph is emboldened vertically. Expressed in 26.6
+ * pixel format.
+ *
+ * @inout:
+ * bitmap ::
+ * A handle to the target bitmap.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The current implementation restricts `xStrength` to be less than or
+ * equal to~8 if bitmap is of pixel_mode @FT_PIXEL_MODE_MONO.
+ *
+ * If you want to embolden the bitmap owned by a @FT_GlyphSlotRec, you
+ * should call @FT_GlyphSlot_Own_Bitmap on the slot first.
+ *
+ * Bitmaps in @FT_PIXEL_MODE_GRAY2 and @FT_PIXEL_MODE_GRAY@ format are
+ * converted to @FT_PIXEL_MODE_GRAY format (i.e., 8bpp).
+ */
FT_EXPORT( FT_Error )
FT_Bitmap_Embolden( FT_Library library,
FT_Bitmap* bitmap,
@@ -142,39 +161,46 @@ FT_BEGIN_HEADER
FT_Pos yStrength );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Bitmap_Convert */
- /* */
- /* <Description> */
- /* Convert a bitmap object with depth 1bpp, 2bpp, 4bpp, 8bpp or 32bpp */
- /* to a bitmap object with depth 8bpp, making the number of used */
- /* bytes line (a.k.a. the `pitch') a multiple of `alignment'. */
- /* */
- /* <Input> */
- /* library :: A handle to a library object. */
- /* */
- /* source :: The source bitmap. */
- /* */
- /* alignment :: The pitch of the bitmap is a multiple of this */
- /* parameter. Common values are 1, 2, or 4. */
- /* */
- /* <Output> */
- /* target :: The target bitmap. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* It is possible to call @FT_Bitmap_Convert multiple times without */
- /* calling @FT_Bitmap_Done (the memory is simply reallocated). */
- /* */
- /* Use @FT_Bitmap_Done to finally remove the bitmap object. */
- /* */
- /* The `library' argument is taken to have access to FreeType's */
- /* memory handling functions. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Bitmap_Convert
+ *
+ * @description:
+ * Convert a bitmap object with depth 1bpp, 2bpp, 4bpp, 8bpp or 32bpp to
+ * a bitmap object with depth 8bpp, making the number of used bytes per
+ * line (a.k.a. the 'pitch') a multiple of `alignment`.
+ *
+ * @input:
+ * library ::
+ * A handle to a library object.
+ *
+ * source ::
+ * The source bitmap.
+ *
+ * alignment ::
+ * The pitch of the bitmap is a multiple of this argument. Common
+ * values are 1, 2, or 4.
+ *
+ * @output:
+ * target ::
+ * The target bitmap.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * It is possible to call @FT_Bitmap_Convert multiple times without
+ * calling @FT_Bitmap_Done (the memory is simply reallocated).
+ *
+ * Use @FT_Bitmap_Done to finally remove the bitmap object.
+ *
+ * The `library` argument is taken to have access to FreeType's memory
+ * handling functions.
+ *
+ * `source->buffer` and `target->buffer` must neither be equal nor
+ * overlap.
+ */
FT_EXPORT( FT_Error )
FT_Bitmap_Convert( FT_Library library,
const FT_Bitmap *source,
@@ -182,48 +208,112 @@ FT_BEGIN_HEADER
FT_Int alignment );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_GlyphSlot_Own_Bitmap */
- /* */
- /* <Description> */
- /* Make sure that a glyph slot owns `slot->bitmap'. */
- /* */
- /* <Input> */
- /* slot :: The glyph slot. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* This function is to be used in combination with */
- /* @FT_Bitmap_Embolden. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Bitmap_Blend
+ *
+ * @description:
+ * Blend a bitmap onto another bitmap, using a given color.
+ *
+ * @input:
+ * library ::
+ * A handle to a library object.
+ *
+ * source ::
+ * The source bitmap, which can have any @FT_Pixel_Mode format.
+ *
+ * source_offset ::
+ * The offset vector to the upper left corner of the source bitmap in
+ * 26.6 pixel format. It should represent an integer offset; the
+ * function will set the lowest six bits to zero to enforce that.
+ *
+ * color ::
+ * The color used to draw `source` onto `target`.
+ *
+ * @inout:
+ * target ::
+ * A handle to an `FT_Bitmap` object. It should be either initialized
+ * as empty with a call to @FT_Bitmap_Init, or it should be of type
+ * @FT_PIXEL_MODE_BGRA.
+ *
+ * atarget_offset ::
+ * The offset vector to the upper left corner of the target bitmap in
+ * 26.6 pixel format. It should represent an integer offset; the
+ * function will set the lowest six bits to zero to enforce that.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * This function doesn't perform clipping.
+ *
+ * The bitmap in `target` gets allocated or reallocated as needed; the
+ * vector `atarget_offset` is updated accordingly.
+ *
+ * In case of allocation or reallocation, the bitmap's pitch is set to
+ * `4 * width`. Both `source` and `target` must have the same bitmap
+ * flow (as indicated by the sign of the `pitch` field).
+ *
+ * `source->buffer` and `target->buffer` must neither be equal nor
+ * overlap.
+ *
+ * @since:
+ * 2.10
+ */
+ FT_EXPORT( FT_Error )
+ FT_Bitmap_Blend( FT_Library library,
+ const FT_Bitmap* source,
+ const FT_Vector source_offset,
+ FT_Bitmap* target,
+ FT_Vector *atarget_offset,
+ FT_Color color );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_GlyphSlot_Own_Bitmap
+ *
+ * @description:
+ * Make sure that a glyph slot owns `slot->bitmap`.
+ *
+ * @input:
+ * slot ::
+ * The glyph slot.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * This function is to be used in combination with @FT_Bitmap_Embolden.
+ */
FT_EXPORT( FT_Error )
FT_GlyphSlot_Own_Bitmap( FT_GlyphSlot slot );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Bitmap_Done */
- /* */
- /* <Description> */
- /* Destroy a bitmap object initialized with @FT_Bitmap_Init. */
- /* */
- /* <Input> */
- /* library :: A handle to a library object. */
- /* */
- /* bitmap :: The bitmap object to be freed. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* The `library' argument is taken to have access to FreeType's */
- /* memory handling functions. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Bitmap_Done
+ *
+ * @description:
+ * Destroy a bitmap object initialized with @FT_Bitmap_Init.
+ *
+ * @input:
+ * library ::
+ * A handle to a library object.
+ *
+ * bitmap ::
+ * The bitmap object to be freed.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The `library` argument is taken to have access to FreeType's memory
+ * handling functions.
+ */
FT_EXPORT( FT_Error )
FT_Bitmap_Done( FT_Library library,
FT_Bitmap *bitmap );
diff --git a/thirdparty/freetype/include/freetype/ftbzip2.h b/thirdparty/freetype/include/freetype/ftbzip2.h
index 6edfa031b5..ae88cfdbdb 100644
--- a/thirdparty/freetype/include/freetype/ftbzip2.h
+++ b/thirdparty/freetype/include/freetype/ftbzip2.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftbzip2.h */
-/* */
-/* Bzip2-compressed stream support. */
-/* */
-/* Copyright 2010-2018 by */
-/* Joel Klinghed. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftbzip2.h
+ *
+ * Bzip2-compressed stream support.
+ *
+ * Copyright (C) 2010-2019 by
+ * Joel Klinghed.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTBZIP2_H_
@@ -31,62 +31,62 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* <Section> */
- /* bzip2 */
- /* */
- /* <Title> */
- /* BZIP2 Streams */
- /* */
- /* <Abstract> */
- /* Using bzip2-compressed font files. */
- /* */
- /* <Description> */
- /* This section contains the declaration of Bzip2-specific functions. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * @section:
+ * bzip2
+ *
+ * @title:
+ * BZIP2 Streams
+ *
+ * @abstract:
+ * Using bzip2-compressed font files.
+ *
+ * @description:
+ * This section contains the declaration of Bzip2-specific functions.
+ *
+ */
- /************************************************************************
- *
- * @function:
- * FT_Stream_OpenBzip2
- *
- * @description:
- * Open a new stream to parse bzip2-compressed font files. This is
- * mainly used to support the compressed `*.pcf.bz2' fonts that come
- * with XFree86.
- *
- * @input:
- * stream ::
- * The target embedding stream.
- *
- * source ::
- * The source stream.
- *
- * @return:
- * FreeType error code. 0~means success.
- *
- * @note:
- * The source stream must be opened _before_ calling this function.
- *
- * Calling the internal function `FT_Stream_Close' on the new stream will
- * *not* call `FT_Stream_Close' on the source stream. None of the stream
- * objects will be released to the heap.
- *
- * The stream implementation is very basic and resets the decompression
- * process each time seeking backwards is needed within the stream.
- *
- * In certain builds of the library, bzip2 compression recognition is
- * automatically handled when calling @FT_New_Face or @FT_Open_Face.
- * This means that if no font driver is capable of handling the raw
- * compressed file, the library will try to open a bzip2 compressed stream
- * from it and re-open the face with it.
- *
- * This function may return `FT_Err_Unimplemented_Feature' if your build
- * of FreeType was not compiled with bzip2 support.
- */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Stream_OpenBzip2
+ *
+ * @description:
+ * Open a new stream to parse bzip2-compressed font files. This is
+ * mainly used to support the compressed `*.pcf.bz2` fonts that come with
+ * XFree86.
+ *
+ * @input:
+ * stream ::
+ * The target embedding stream.
+ *
+ * source ::
+ * The source stream.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The source stream must be opened _before_ calling this function.
+ *
+ * Calling the internal function `FT_Stream_Close` on the new stream will
+ * **not** call `FT_Stream_Close` on the source stream. None of the
+ * stream objects will be released to the heap.
+ *
+ * The stream implementation is very basic and resets the decompression
+ * process each time seeking backwards is needed within the stream.
+ *
+ * In certain builds of the library, bzip2 compression recognition is
+ * automatically handled when calling @FT_New_Face or @FT_Open_Face.
+ * This means that if no font driver is capable of handling the raw
+ * compressed file, the library will try to open a bzip2 compressed
+ * stream from it and re-open the face with it.
+ *
+ * This function may return `FT_Err_Unimplemented_Feature` if your build
+ * of FreeType was not compiled with bzip2 support.
+ */
FT_EXPORT( FT_Error )
FT_Stream_OpenBzip2( FT_Stream stream,
FT_Stream source );
diff --git a/thirdparty/freetype/include/freetype/ftcache.h b/thirdparty/freetype/include/freetype/ftcache.h
index 52d5f00e06..0d589d0b34 100644
--- a/thirdparty/freetype/include/freetype/ftcache.h
+++ b/thirdparty/freetype/include/freetype/ftcache.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftcache.h */
-/* */
-/* FreeType Cache subsystem (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftcache.h
+ *
+ * FreeType Cache subsystem (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTCACHE_H_
@@ -27,24 +27,24 @@
FT_BEGIN_HEADER
- /*************************************************************************
+ /**************************************************************************
*
- * <Section>
- * cache_subsystem
+ * @section:
+ * cache_subsystem
*
- * <Title>
- * Cache Sub-System
+ * @title:
+ * Cache Sub-System
*
- * <Abstract>
- * How to cache face, size, and glyph data with FreeType~2.
+ * @abstract:
+ * How to cache face, size, and glyph data with FreeType~2.
*
- * <Description>
+ * @description:
* This section describes the FreeType~2 cache sub-system, which is used
* to limit the number of concurrently opened @FT_Face and @FT_Size
* objects, as well as caching information like character maps and glyph
* images while limiting their maximum memory usage.
*
- * Note that all types and functions begin with the `FTC_' prefix.
+ * Note that all types and functions begin with the `FTC_` prefix.
*
* The cache is highly portable and thus doesn't know anything about the
* fonts installed on your system, or how to access them. This implies
@@ -59,7 +59,7 @@ FT_BEGIN_HEADER
* to convert an @FTC_FaceID into a new @FT_Face object. The latter is
* then completely managed by the cache, including its termination
* through @FT_Done_Face. To monitor termination of face objects, the
- * finalizer callback in the `generic' field of the @FT_Face object can
+ * finalizer callback in the `generic` field of the @FT_Face object can
* be used, which might also be used to store the @FTC_FaceID of the
* face.
*
@@ -69,14 +69,14 @@ FT_BEGIN_HEADER
* possible.
*
* Note that for the cache to work correctly, the face ID values must be
- * *persistent*, which means that the contents they point to should not
+ * **persistent**, which means that the contents they point to should not
* change at runtime, or that their value should not become invalid.
*
* If this is unavoidable (e.g., when a font is uninstalled at runtime),
* you should call @FTC_Manager_RemoveFaceID as soon as possible, to let
- * the cache get rid of any references to the old @FTC_FaceID it may
- * keep internally. Failure to do so will lead to incorrect behaviour
- * or even crashes.
+ * the cache get rid of any references to the old @FTC_FaceID it may keep
+ * internally. Failure to do so will lead to incorrect behaviour or even
+ * crashes.
*
* To use the cache, start with calling @FTC_Manager_New to create a new
* @FTC_Manager object, which models a single cache instance. You can
@@ -91,16 +91,16 @@ FT_BEGIN_HEADER
* later use @FTC_ImageCache_Lookup to retrieve the corresponding
* @FT_Glyph objects from the cache.
*
- * If you need lots of small bitmaps, it is much more memory efficient
- * to call @FTC_SBitCache_New followed by @FTC_SBitCache_Lookup. This
- * returns @FTC_SBitRec structures, which are used to store small
- * bitmaps directly. (A small bitmap is one whose metrics and
- * dimensions all fit into 8-bit integers).
+ * If you need lots of small bitmaps, it is much more memory efficient to
+ * call @FTC_SBitCache_New followed by @FTC_SBitCache_Lookup. This
+ * returns @FTC_SBitRec structures, which are used to store small bitmaps
+ * directly. (A small bitmap is one whose metrics and dimensions all fit
+ * into 8-bit integers).
*
* We hope to also provide a kerning cache in the near future.
*
*
- * <Order>
+ * @order:
* FTC_Manager
* FTC_FaceID
* FTC_Face_Requester
@@ -142,19 +142,20 @@ FT_BEGIN_HEADER
/*************************************************************************/
- /*************************************************************************
+ /**************************************************************************
*
- * @type: FTC_FaceID
+ * @type:
+ * FTC_FaceID
*
* @description:
* An opaque pointer type that is used to identity face objects. The
* contents of such objects is application-dependent.
*
- * These pointers are typically used to point to a user-defined
- * structure containing a font file path, and face index.
+ * These pointers are typically used to point to a user-defined structure
+ * containing a font file path, and face index.
*
* @note:
- * Never use NULL as a valid @FTC_FaceID.
+ * Never use `NULL` as a valid @FTC_FaceID.
*
* Face IDs are passed by the client to the cache manager that calls,
* when needed, the @FTC_Face_Requester to translate them into new
@@ -165,13 +166,13 @@ FT_BEGIN_HEADER
* immediately call @FTC_Manager_RemoveFaceID before any other cache
* function.
*
- * Failure to do so will result in incorrect behaviour or even
- * memory leaks and crashes.
+ * Failure to do so will result in incorrect behaviour or even memory
+ * leaks and crashes.
*/
typedef FT_Pointer FTC_FaceID;
- /************************************************************************
+ /**************************************************************************
*
* @functype:
* FTC_Face_Requester
@@ -181,7 +182,7 @@ FT_BEGIN_HEADER
* the cache manager to translate a given @FTC_FaceID into a new valid
* @FT_Face object, on demand.
*
- * <Input>
+ * @input:
* face_id ::
* The face ID to resolve.
*
@@ -191,15 +192,15 @@ FT_BEGIN_HEADER
* req_data ::
* Application-provided request data (see note below).
*
- * <Output>
+ * @output:
* aface ::
* A new @FT_Face handle.
*
- * <Return>
+ * @return:
* FreeType error code. 0~means success.
*
- * <Note>
- * The third parameter `req_data' is the same as the one passed by the
+ * @note:
+ * The third parameter `req_data` is the same as the one passed by the
* client when @FTC_Manager_New is called.
*
* The face requester should not perform funny things on the returned
@@ -226,84 +227,90 @@ FT_BEGIN_HEADER
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FTC_Manager */
- /* */
- /* <Description> */
- /* This object corresponds to one instance of the cache-subsystem. */
- /* It is used to cache one or more @FT_Face objects, along with */
- /* corresponding @FT_Size objects. */
- /* */
- /* The manager intentionally limits the total number of opened */
- /* @FT_Face and @FT_Size objects to control memory usage. See the */
- /* `max_faces' and `max_sizes' parameters of @FTC_Manager_New. */
- /* */
- /* The manager is also used to cache `nodes' of various types while */
- /* limiting their total memory usage. */
- /* */
- /* All limitations are enforced by keeping lists of managed objects */
- /* in most-recently-used order, and flushing old nodes to make room */
- /* for new ones. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FTC_Manager
+ *
+ * @description:
+ * This object corresponds to one instance of the cache-subsystem. It is
+ * used to cache one or more @FT_Face objects, along with corresponding
+ * @FT_Size objects.
+ *
+ * The manager intentionally limits the total number of opened @FT_Face
+ * and @FT_Size objects to control memory usage. See the `max_faces` and
+ * `max_sizes` parameters of @FTC_Manager_New.
+ *
+ * The manager is also used to cache 'nodes' of various types while
+ * limiting their total memory usage.
+ *
+ * All limitations are enforced by keeping lists of managed objects in
+ * most-recently-used order, and flushing old nodes to make room for new
+ * ones.
+ */
typedef struct FTC_ManagerRec_* FTC_Manager;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FTC_Node */
- /* */
- /* <Description> */
- /* An opaque handle to a cache node object. Each cache node is */
- /* reference-counted. A node with a count of~0 might be flushed */
- /* out of a full cache whenever a lookup request is performed. */
- /* */
- /* If you look up nodes, you have the ability to `acquire' them, */
- /* i.e., to increment their reference count. This will prevent the */
- /* node from being flushed out of the cache until you explicitly */
- /* `release' it (see @FTC_Node_Unref). */
- /* */
- /* See also @FTC_SBitCache_Lookup and @FTC_ImageCache_Lookup. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FTC_Node
+ *
+ * @description:
+ * An opaque handle to a cache node object. Each cache node is
+ * reference-counted. A node with a count of~0 might be flushed out of a
+ * full cache whenever a lookup request is performed.
+ *
+ * If you look up nodes, you have the ability to 'acquire' them, i.e., to
+ * increment their reference count. This will prevent the node from
+ * being flushed out of the cache until you explicitly 'release' it (see
+ * @FTC_Node_Unref).
+ *
+ * See also @FTC_SBitCache_Lookup and @FTC_ImageCache_Lookup.
+ */
typedef struct FTC_NodeRec_* FTC_Node;
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FTC_Manager_New */
- /* */
- /* <Description> */
- /* Create a new cache manager. */
- /* */
- /* <Input> */
- /* library :: The parent FreeType library handle to use. */
- /* */
- /* max_faces :: Maximum number of opened @FT_Face objects managed by */
- /* this cache instance. Use~0 for defaults. */
- /* */
- /* max_sizes :: Maximum number of opened @FT_Size objects managed by */
- /* this cache instance. Use~0 for defaults. */
- /* */
- /* max_bytes :: Maximum number of bytes to use for cached data nodes. */
- /* Use~0 for defaults. Note that this value does not */
- /* account for managed @FT_Face and @FT_Size objects. */
- /* */
- /* requester :: An application-provided callback used to translate */
- /* face IDs into real @FT_Face objects. */
- /* */
- /* req_data :: A generic pointer that is passed to the requester */
- /* each time it is called (see @FTC_Face_Requester). */
- /* */
- /* <Output> */
- /* amanager :: A handle to a new manager object. 0~in case of */
- /* failure. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FTC_Manager_New
+ *
+ * @description:
+ * Create a new cache manager.
+ *
+ * @input:
+ * library ::
+ * The parent FreeType library handle to use.
+ *
+ * max_faces ::
+ * Maximum number of opened @FT_Face objects managed by this cache
+ * instance. Use~0 for defaults.
+ *
+ * max_sizes ::
+ * Maximum number of opened @FT_Size objects managed by this cache
+ * instance. Use~0 for defaults.
+ *
+ * max_bytes ::
+ * Maximum number of bytes to use for cached data nodes. Use~0 for
+ * defaults. Note that this value does not account for managed
+ * @FT_Face and @FT_Size objects.
+ *
+ * requester ::
+ * An application-provided callback used to translate face IDs into
+ * real @FT_Face objects.
+ *
+ * req_data ::
+ * A generic pointer that is passed to the requester each time it is
+ * called (see @FTC_Face_Requester).
+ *
+ * @output:
+ * amanager ::
+ * A handle to a new manager object. 0~in case of failure.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ */
FT_EXPORT( FT_Error )
FTC_Manager_New( FT_Library library,
FT_UInt max_faces,
@@ -314,114 +321,124 @@ FT_BEGIN_HEADER
FTC_Manager *amanager );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FTC_Manager_Reset */
- /* */
- /* <Description> */
- /* Empty a given cache manager. This simply gets rid of all the */
- /* currently cached @FT_Face and @FT_Size objects within the manager. */
- /* */
- /* <InOut> */
- /* manager :: A handle to the manager. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FTC_Manager_Reset
+ *
+ * @description:
+ * Empty a given cache manager. This simply gets rid of all the
+ * currently cached @FT_Face and @FT_Size objects within the manager.
+ *
+ * @inout:
+ * manager ::
+ * A handle to the manager.
+ */
FT_EXPORT( void )
FTC_Manager_Reset( FTC_Manager manager );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FTC_Manager_Done */
- /* */
- /* <Description> */
- /* Destroy a given manager after emptying it. */
- /* */
- /* <Input> */
- /* manager :: A handle to the target cache manager object. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FTC_Manager_Done
+ *
+ * @description:
+ * Destroy a given manager after emptying it.
+ *
+ * @input:
+ * manager ::
+ * A handle to the target cache manager object.
+ */
FT_EXPORT( void )
FTC_Manager_Done( FTC_Manager manager );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FTC_Manager_LookupFace */
- /* */
- /* <Description> */
- /* Retrieve the @FT_Face object that corresponds to a given face ID */
- /* through a cache manager. */
- /* */
- /* <Input> */
- /* manager :: A handle to the cache manager. */
- /* */
- /* face_id :: The ID of the face object. */
- /* */
- /* <Output> */
- /* aface :: A handle to the face object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* The returned @FT_Face object is always owned by the manager. You */
- /* should never try to discard it yourself. */
- /* */
- /* The @FT_Face object doesn't necessarily have a current size object */
- /* (i.e., face->size can be~0). If you need a specific `font size', */
- /* use @FTC_Manager_LookupSize instead. */
- /* */
- /* Never change the face's transformation matrix (i.e., never call */
- /* the @FT_Set_Transform function) on a returned face! If you need */
- /* to transform glyphs, do it yourself after glyph loading. */
- /* */
- /* When you perform a lookup, out-of-memory errors are detected */
- /* _within_ the lookup and force incremental flushes of the cache */
- /* until enough memory is released for the lookup to succeed. */
- /* */
- /* If a lookup fails with `FT_Err_Out_Of_Memory' the cache has */
- /* already been completely flushed, and still no memory was available */
- /* for the operation. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FTC_Manager_LookupFace
+ *
+ * @description:
+ * Retrieve the @FT_Face object that corresponds to a given face ID
+ * through a cache manager.
+ *
+ * @input:
+ * manager ::
+ * A handle to the cache manager.
+ *
+ * face_id ::
+ * The ID of the face object.
+ *
+ * @output:
+ * aface ::
+ * A handle to the face object.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The returned @FT_Face object is always owned by the manager. You
+ * should never try to discard it yourself.
+ *
+ * The @FT_Face object doesn't necessarily have a current size object
+ * (i.e., face->size can be~0). If you need a specific 'font size', use
+ * @FTC_Manager_LookupSize instead.
+ *
+ * Never change the face's transformation matrix (i.e., never call the
+ * @FT_Set_Transform function) on a returned face! If you need to
+ * transform glyphs, do it yourself after glyph loading.
+ *
+ * When you perform a lookup, out-of-memory errors are detected _within_
+ * the lookup and force incremental flushes of the cache until enough
+ * memory is released for the lookup to succeed.
+ *
+ * If a lookup fails with `FT_Err_Out_Of_Memory` the cache has already
+ * been completely flushed, and still no memory was available for the
+ * operation.
+ */
FT_EXPORT( FT_Error )
FTC_Manager_LookupFace( FTC_Manager manager,
FTC_FaceID face_id,
FT_Face *aface );
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FTC_ScalerRec */
- /* */
- /* <Description> */
- /* A structure used to describe a given character size in either */
- /* pixels or points to the cache manager. See */
- /* @FTC_Manager_LookupSize. */
- /* */
- /* <Fields> */
- /* face_id :: The source face ID. */
- /* */
- /* width :: The character width. */
- /* */
- /* height :: The character height. */
- /* */
- /* pixel :: A Boolean. If 1, the `width' and `height' fields are */
- /* interpreted as integer pixel character sizes. */
- /* Otherwise, they are expressed as 1/64th of points. */
- /* */
- /* x_res :: Only used when `pixel' is value~0 to indicate the */
- /* horizontal resolution in dpi. */
- /* */
- /* y_res :: Only used when `pixel' is value~0 to indicate the */
- /* vertical resolution in dpi. */
- /* */
- /* <Note> */
- /* This type is mainly used to retrieve @FT_Size objects through the */
- /* cache manager. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FTC_ScalerRec
+ *
+ * @description:
+ * A structure used to describe a given character size in either pixels
+ * or points to the cache manager. See @FTC_Manager_LookupSize.
+ *
+ * @fields:
+ * face_id ::
+ * The source face ID.
+ *
+ * width ::
+ * The character width.
+ *
+ * height ::
+ * The character height.
+ *
+ * pixel ::
+ * A Boolean. If 1, the `width` and `height` fields are interpreted as
+ * integer pixel character sizes. Otherwise, they are expressed as
+ * 1/64th of points.
+ *
+ * x_res ::
+ * Only used when `pixel` is value~0 to indicate the horizontal
+ * resolution in dpi.
+ *
+ * y_res ::
+ * Only used when `pixel` is value~0 to indicate the vertical
+ * resolution in dpi.
+ *
+ * @note:
+ * This type is mainly used to retrieve @FT_Size objects through the
+ * cache manager.
+ */
typedef struct FTC_ScalerRec_
{
FTC_FaceID face_id;
@@ -434,89 +451,93 @@ FT_BEGIN_HEADER
} FTC_ScalerRec;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FTC_Scaler */
- /* */
- /* <Description> */
- /* A handle to an @FTC_ScalerRec structure. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FTC_Scaler
+ *
+ * @description:
+ * A handle to an @FTC_ScalerRec structure.
+ */
typedef struct FTC_ScalerRec_* FTC_Scaler;
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FTC_Manager_LookupSize */
- /* */
- /* <Description> */
- /* Retrieve the @FT_Size object that corresponds to a given */
- /* @FTC_ScalerRec pointer through a cache manager. */
- /* */
- /* <Input> */
- /* manager :: A handle to the cache manager. */
- /* */
- /* scaler :: A scaler handle. */
- /* */
- /* <Output> */
- /* asize :: A handle to the size object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* The returned @FT_Size object is always owned by the manager. You */
- /* should never try to discard it by yourself. */
- /* */
- /* You can access the parent @FT_Face object simply as `size->face' */
- /* if you need it. Note that this object is also owned by the */
- /* manager. */
- /* */
- /* <Note> */
- /* When you perform a lookup, out-of-memory errors are detected */
- /* _within_ the lookup and force incremental flushes of the cache */
- /* until enough memory is released for the lookup to succeed. */
- /* */
- /* If a lookup fails with `FT_Err_Out_Of_Memory' the cache has */
- /* already been completely flushed, and still no memory is available */
- /* for the operation. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FTC_Manager_LookupSize
+ *
+ * @description:
+ * Retrieve the @FT_Size object that corresponds to a given
+ * @FTC_ScalerRec pointer through a cache manager.
+ *
+ * @input:
+ * manager ::
+ * A handle to the cache manager.
+ *
+ * scaler ::
+ * A scaler handle.
+ *
+ * @output:
+ * asize ::
+ * A handle to the size object.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The returned @FT_Size object is always owned by the manager. You
+ * should never try to discard it by yourself.
+ *
+ * You can access the parent @FT_Face object simply as `size->face` if
+ * you need it. Note that this object is also owned by the manager.
+ *
+ * @note:
+ * When you perform a lookup, out-of-memory errors are detected _within_
+ * the lookup and force incremental flushes of the cache until enough
+ * memory is released for the lookup to succeed.
+ *
+ * If a lookup fails with `FT_Err_Out_Of_Memory` the cache has already
+ * been completely flushed, and still no memory is available for the
+ * operation.
+ */
FT_EXPORT( FT_Error )
FTC_Manager_LookupSize( FTC_Manager manager,
FTC_Scaler scaler,
FT_Size *asize );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FTC_Node_Unref */
- /* */
- /* <Description> */
- /* Decrement a cache node's internal reference count. When the count */
- /* reaches 0, it is not destroyed but becomes eligible for subsequent */
- /* cache flushes. */
- /* */
- /* <Input> */
- /* node :: The cache node handle. */
- /* */
- /* manager :: The cache manager handle. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FTC_Node_Unref
+ *
+ * @description:
+ * Decrement a cache node's internal reference count. When the count
+ * reaches 0, it is not destroyed but becomes eligible for subsequent
+ * cache flushes.
+ *
+ * @input:
+ * node ::
+ * The cache node handle.
+ *
+ * manager ::
+ * The cache manager handle.
+ */
FT_EXPORT( void )
FTC_Node_Unref( FTC_Node node,
FTC_Manager manager );
- /*************************************************************************
+ /**************************************************************************
*
* @function:
* FTC_Manager_RemoveFaceID
*
* @description:
- * A special function used to indicate to the cache manager that
- * a given @FTC_FaceID is no longer valid, either because its
- * content changed, or because it was deallocated or uninstalled.
+ * A special function used to indicate to the cache manager that a given
+ * @FTC_FaceID is no longer valid, either because its content changed, or
+ * because it was deallocated or uninstalled.
*
* @input:
* manager ::
@@ -527,11 +548,11 @@ FT_BEGIN_HEADER
*
* @note:
* This function flushes all nodes from the cache corresponding to this
- * `face_id', with the exception of nodes with a non-null reference
+ * `face_id`, with the exception of nodes with a non-null reference
* count.
*
- * Such nodes are however modified internally so as to never appear
- * in later lookups with the same `face_id' value, and to be immediately
+ * Such nodes are however modified internally so as to never appear in
+ * later lookups with the same `face_id` value, and to be immediately
* destroyed when released by all their users.
*
*/
@@ -540,20 +561,20 @@ FT_BEGIN_HEADER
FTC_FaceID face_id );
- /*************************************************************************
+ /**************************************************************************
*
* @type:
* FTC_CMapCache
*
* @description:
- * An opaque handle used to model a charmap cache. This cache is to
- * hold character codes -> glyph indices mappings.
+ * An opaque handle used to model a charmap cache. This cache is to hold
+ * character codes -> glyph indices mappings.
*
*/
typedef struct FTC_CMapCacheRec_* FTC_CMapCache;
- /*************************************************************************
+ /**************************************************************************
*
* @function:
* FTC_CMapCache_New
@@ -567,7 +588,7 @@ FT_BEGIN_HEADER
*
* @output:
* acache ::
- * A new cache handle. NULL in case of error.
+ * A new cache handle. `NULL` in case of error.
*
* @return:
* FreeType error code. 0~means success.
@@ -582,7 +603,7 @@ FT_BEGIN_HEADER
FTC_CMapCache *acache );
- /************************************************************************
+ /**************************************************************************
*
* @function:
* FTC_CMapCache_Lookup
@@ -606,7 +627,7 @@ FT_BEGIN_HEADER
* The character code (in the corresponding charmap).
*
* @return:
- * Glyph index. 0~means `no glyph'.
+ * Glyph index. 0~means 'no glyph'.
*
*/
FT_EXPORT( FT_UInt )
@@ -627,7 +648,7 @@ FT_BEGIN_HEADER
/*************************************************************************/
- /*************************************************************************
+ /**************************************************************************
*
* @struct:
* FTC_ImageTypeRec
@@ -659,7 +680,7 @@ FT_BEGIN_HEADER
} FTC_ImageTypeRec;
- /*************************************************************************
+ /**************************************************************************
*
* @type:
* FTC_ImageType
@@ -680,83 +701,87 @@ FT_BEGIN_HEADER
(d1)->flags == (d2)->flags )
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FTC_ImageCache */
- /* */
- /* <Description> */
- /* A handle to a glyph image cache object. They are designed to */
- /* hold many distinct glyph images while not exceeding a certain */
- /* memory threshold. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FTC_ImageCache
+ *
+ * @description:
+ * A handle to a glyph image cache object. They are designed to hold
+ * many distinct glyph images while not exceeding a certain memory
+ * threshold.
+ */
typedef struct FTC_ImageCacheRec_* FTC_ImageCache;
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FTC_ImageCache_New */
- /* */
- /* <Description> */
- /* Create a new glyph image cache. */
- /* */
- /* <Input> */
- /* manager :: The parent manager for the image cache. */
- /* */
- /* <Output> */
- /* acache :: A handle to the new glyph image cache object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FTC_ImageCache_New
+ *
+ * @description:
+ * Create a new glyph image cache.
+ *
+ * @input:
+ * manager ::
+ * The parent manager for the image cache.
+ *
+ * @output:
+ * acache ::
+ * A handle to the new glyph image cache object.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ */
FT_EXPORT( FT_Error )
FTC_ImageCache_New( FTC_Manager manager,
FTC_ImageCache *acache );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FTC_ImageCache_Lookup */
- /* */
- /* <Description> */
- /* Retrieve a given glyph image from a glyph image cache. */
- /* */
- /* <Input> */
- /* cache :: A handle to the source glyph image cache. */
- /* */
- /* type :: A pointer to a glyph image type descriptor. */
- /* */
- /* gindex :: The glyph index to retrieve. */
- /* */
- /* <Output> */
- /* aglyph :: The corresponding @FT_Glyph object. 0~in case of */
- /* failure. */
- /* */
- /* anode :: Used to return the address of the corresponding cache */
- /* node after incrementing its reference count (see note */
- /* below). */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* The returned glyph is owned and managed by the glyph image cache. */
- /* Never try to transform or discard it manually! You can however */
- /* create a copy with @FT_Glyph_Copy and modify the new one. */
- /* */
- /* If `anode' is _not_ NULL, it receives the address of the cache */
- /* node containing the glyph image, after increasing its reference */
- /* count. This ensures that the node (as well as the @FT_Glyph) will */
- /* always be kept in the cache until you call @FTC_Node_Unref to */
- /* `release' it. */
- /* */
- /* If `anode' is NULL, the cache node is left unchanged, which means */
- /* that the @FT_Glyph could be flushed out of the cache on the next */
- /* call to one of the caching sub-system APIs. Don't assume that it */
- /* is persistent! */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FTC_ImageCache_Lookup
+ *
+ * @description:
+ * Retrieve a given glyph image from a glyph image cache.
+ *
+ * @input:
+ * cache ::
+ * A handle to the source glyph image cache.
+ *
+ * type ::
+ * A pointer to a glyph image type descriptor.
+ *
+ * gindex ::
+ * The glyph index to retrieve.
+ *
+ * @output:
+ * aglyph ::
+ * The corresponding @FT_Glyph object. 0~in case of failure.
+ *
+ * anode ::
+ * Used to return the address of the corresponding cache node after
+ * incrementing its reference count (see note below).
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The returned glyph is owned and managed by the glyph image cache.
+ * Never try to transform or discard it manually! You can however create
+ * a copy with @FT_Glyph_Copy and modify the new one.
+ *
+ * If `anode` is _not_ `NULL`, it receives the address of the cache node
+ * containing the glyph image, after increasing its reference count.
+ * This ensures that the node (as well as the @FT_Glyph) will always be
+ * kept in the cache until you call @FTC_Node_Unref to 'release' it.
+ *
+ * If `anode` is `NULL`, the cache node is left unchanged, which means
+ * that the @FT_Glyph could be flushed out of the cache on the next call
+ * to one of the caching sub-system APIs. Don't assume that it is
+ * persistent!
+ */
FT_EXPORT( FT_Error )
FTC_ImageCache_Lookup( FTC_ImageCache cache,
FTC_ImageType type,
@@ -765,54 +790,57 @@ FT_BEGIN_HEADER
FTC_Node *anode );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FTC_ImageCache_LookupScaler */
- /* */
- /* <Description> */
- /* A variant of @FTC_ImageCache_Lookup that uses an @FTC_ScalerRec */
- /* to specify the face ID and its size. */
- /* */
- /* <Input> */
- /* cache :: A handle to the source glyph image cache. */
- /* */
- /* scaler :: A pointer to a scaler descriptor. */
- /* */
- /* load_flags :: The corresponding load flags. */
- /* */
- /* gindex :: The glyph index to retrieve. */
- /* */
- /* <Output> */
- /* aglyph :: The corresponding @FT_Glyph object. 0~in case of */
- /* failure. */
- /* */
- /* anode :: Used to return the address of the corresponding */
- /* cache node after incrementing its reference count */
- /* (see note below). */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* The returned glyph is owned and managed by the glyph image cache. */
- /* Never try to transform or discard it manually! You can however */
- /* create a copy with @FT_Glyph_Copy and modify the new one. */
- /* */
- /* If `anode' is _not_ NULL, it receives the address of the cache */
- /* node containing the glyph image, after increasing its reference */
- /* count. This ensures that the node (as well as the @FT_Glyph) will */
- /* always be kept in the cache until you call @FTC_Node_Unref to */
- /* `release' it. */
- /* */
- /* If `anode' is NULL, the cache node is left unchanged, which means */
- /* that the @FT_Glyph could be flushed out of the cache on the next */
- /* call to one of the caching sub-system APIs. Don't assume that it */
- /* is persistent! */
- /* */
- /* Calls to @FT_Set_Char_Size and friends have no effect on cached */
- /* glyphs; you should always use the FreeType cache API instead. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FTC_ImageCache_LookupScaler
+ *
+ * @description:
+ * A variant of @FTC_ImageCache_Lookup that uses an @FTC_ScalerRec to
+ * specify the face ID and its size.
+ *
+ * @input:
+ * cache ::
+ * A handle to the source glyph image cache.
+ *
+ * scaler ::
+ * A pointer to a scaler descriptor.
+ *
+ * load_flags ::
+ * The corresponding load flags.
+ *
+ * gindex ::
+ * The glyph index to retrieve.
+ *
+ * @output:
+ * aglyph ::
+ * The corresponding @FT_Glyph object. 0~in case of failure.
+ *
+ * anode ::
+ * Used to return the address of the corresponding cache node after
+ * incrementing its reference count (see note below).
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The returned glyph is owned and managed by the glyph image cache.
+ * Never try to transform or discard it manually! You can however create
+ * a copy with @FT_Glyph_Copy and modify the new one.
+ *
+ * If `anode` is _not_ `NULL`, it receives the address of the cache node
+ * containing the glyph image, after increasing its reference count.
+ * This ensures that the node (as well as the @FT_Glyph) will always be
+ * kept in the cache until you call @FTC_Node_Unref to 'release' it.
+ *
+ * If `anode` is `NULL`, the cache node is left unchanged, which means
+ * that the @FT_Glyph could be flushed out of the cache on the next call
+ * to one of the caching sub-system APIs. Don't assume that it is
+ * persistent!
+ *
+ * Calls to @FT_Set_Char_Size and friends have no effect on cached
+ * glyphs; you should always use the FreeType cache API instead.
+ */
FT_EXPORT( FT_Error )
FTC_ImageCache_LookupScaler( FTC_ImageCache cache,
FTC_Scaler scaler,
@@ -822,53 +850,60 @@ FT_BEGIN_HEADER
FTC_Node *anode );
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FTC_SBit */
- /* */
- /* <Description> */
- /* A handle to a small bitmap descriptor. See the @FTC_SBitRec */
- /* structure for details. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FTC_SBit
+ *
+ * @description:
+ * A handle to a small bitmap descriptor. See the @FTC_SBitRec structure
+ * for details.
+ */
typedef struct FTC_SBitRec_* FTC_SBit;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FTC_SBitRec */
- /* */
- /* <Description> */
- /* A very compact structure used to describe a small glyph bitmap. */
- /* */
- /* <Fields> */
- /* width :: The bitmap width in pixels. */
- /* */
- /* height :: The bitmap height in pixels. */
- /* */
- /* left :: The horizontal distance from the pen position to the */
- /* left bitmap border (a.k.a. `left side bearing', or */
- /* `lsb'). */
- /* */
- /* top :: The vertical distance from the pen position (on the */
- /* baseline) to the upper bitmap border (a.k.a. `top */
- /* side bearing'). The distance is positive for upwards */
- /* y~coordinates. */
- /* */
- /* format :: The format of the glyph bitmap (monochrome or gray). */
- /* */
- /* max_grays :: Maximum gray level value (in the range 1 to~255). */
- /* */
- /* pitch :: The number of bytes per bitmap line. May be positive */
- /* or negative. */
- /* */
- /* xadvance :: The horizontal advance width in pixels. */
- /* */
- /* yadvance :: The vertical advance height in pixels. */
- /* */
- /* buffer :: A pointer to the bitmap pixels. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FTC_SBitRec
+ *
+ * @description:
+ * A very compact structure used to describe a small glyph bitmap.
+ *
+ * @fields:
+ * width ::
+ * The bitmap width in pixels.
+ *
+ * height ::
+ * The bitmap height in pixels.
+ *
+ * left ::
+ * The horizontal distance from the pen position to the left bitmap
+ * border (a.k.a. 'left side bearing', or 'lsb').
+ *
+ * top ::
+ * The vertical distance from the pen position (on the baseline) to the
+ * upper bitmap border (a.k.a. 'top side bearing'). The distance is
+ * positive for upwards y~coordinates.
+ *
+ * format ::
+ * The format of the glyph bitmap (monochrome or gray).
+ *
+ * max_grays ::
+ * Maximum gray level value (in the range 1 to~255).
+ *
+ * pitch ::
+ * The number of bytes per bitmap line. May be positive or negative.
+ *
+ * xadvance ::
+ * The horizontal advance width in pixels.
+ *
+ * yadvance ::
+ * The vertical advance height in pixels.
+ *
+ * buffer ::
+ * A pointer to the bitmap pixels.
+ */
typedef struct FTC_SBitRec_
{
FT_Byte width;
@@ -887,87 +922,93 @@ FT_BEGIN_HEADER
} FTC_SBitRec;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FTC_SBitCache */
- /* */
- /* <Description> */
- /* A handle to a small bitmap cache. These are special cache objects */
- /* used to store small glyph bitmaps (and anti-aliased pixmaps) in a */
- /* much more efficient way than the traditional glyph image cache */
- /* implemented by @FTC_ImageCache. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FTC_SBitCache
+ *
+ * @description:
+ * A handle to a small bitmap cache. These are special cache objects
+ * used to store small glyph bitmaps (and anti-aliased pixmaps) in a much
+ * more efficient way than the traditional glyph image cache implemented
+ * by @FTC_ImageCache.
+ */
typedef struct FTC_SBitCacheRec_* FTC_SBitCache;
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FTC_SBitCache_New */
- /* */
- /* <Description> */
- /* Create a new cache to store small glyph bitmaps. */
- /* */
- /* <Input> */
- /* manager :: A handle to the source cache manager. */
- /* */
- /* <Output> */
- /* acache :: A handle to the new sbit cache. NULL in case of error. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FTC_SBitCache_New
+ *
+ * @description:
+ * Create a new cache to store small glyph bitmaps.
+ *
+ * @input:
+ * manager ::
+ * A handle to the source cache manager.
+ *
+ * @output:
+ * acache ::
+ * A handle to the new sbit cache. `NULL` in case of error.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ */
FT_EXPORT( FT_Error )
FTC_SBitCache_New( FTC_Manager manager,
FTC_SBitCache *acache );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FTC_SBitCache_Lookup */
- /* */
- /* <Description> */
- /* Look up a given small glyph bitmap in a given sbit cache and */
- /* `lock' it to prevent its flushing from the cache until needed. */
- /* */
- /* <Input> */
- /* cache :: A handle to the source sbit cache. */
- /* */
- /* type :: A pointer to the glyph image type descriptor. */
- /* */
- /* gindex :: The glyph index. */
- /* */
- /* <Output> */
- /* sbit :: A handle to a small bitmap descriptor. */
- /* */
- /* anode :: Used to return the address of the corresponding cache */
- /* node after incrementing its reference count (see note */
- /* below). */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* The small bitmap descriptor and its bit buffer are owned by the */
- /* cache and should never be freed by the application. They might */
- /* as well disappear from memory on the next cache lookup, so don't */
- /* treat them as persistent data. */
- /* */
- /* The descriptor's `buffer' field is set to~0 to indicate a missing */
- /* glyph bitmap. */
- /* */
- /* If `anode' is _not_ NULL, it receives the address of the cache */
- /* node containing the bitmap, after increasing its reference count. */
- /* This ensures that the node (as well as the image) will always be */
- /* kept in the cache until you call @FTC_Node_Unref to `release' it. */
- /* */
- /* If `anode' is NULL, the cache node is left unchanged, which means */
- /* that the bitmap could be flushed out of the cache on the next */
- /* call to one of the caching sub-system APIs. Don't assume that it */
- /* is persistent! */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FTC_SBitCache_Lookup
+ *
+ * @description:
+ * Look up a given small glyph bitmap in a given sbit cache and 'lock' it
+ * to prevent its flushing from the cache until needed.
+ *
+ * @input:
+ * cache ::
+ * A handle to the source sbit cache.
+ *
+ * type ::
+ * A pointer to the glyph image type descriptor.
+ *
+ * gindex ::
+ * The glyph index.
+ *
+ * @output:
+ * sbit ::
+ * A handle to a small bitmap descriptor.
+ *
+ * anode ::
+ * Used to return the address of the corresponding cache node after
+ * incrementing its reference count (see note below).
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The small bitmap descriptor and its bit buffer are owned by the cache
+ * and should never be freed by the application. They might as well
+ * disappear from memory on the next cache lookup, so don't treat them as
+ * persistent data.
+ *
+ * The descriptor's `buffer` field is set to~0 to indicate a missing
+ * glyph bitmap.
+ *
+ * If `anode` is _not_ `NULL`, it receives the address of the cache node
+ * containing the bitmap, after increasing its reference count. This
+ * ensures that the node (as well as the image) will always be kept in
+ * the cache until you call @FTC_Node_Unref to 'release' it.
+ *
+ * If `anode` is `NULL`, the cache node is left unchanged, which means
+ * that the bitmap could be flushed out of the cache on the next call to
+ * one of the caching sub-system APIs. Don't assume that it is
+ * persistent!
+ */
FT_EXPORT( FT_Error )
FTC_SBitCache_Lookup( FTC_SBitCache cache,
FTC_ImageType type,
@@ -976,53 +1017,58 @@ FT_BEGIN_HEADER
FTC_Node *anode );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FTC_SBitCache_LookupScaler */
- /* */
- /* <Description> */
- /* A variant of @FTC_SBitCache_Lookup that uses an @FTC_ScalerRec */
- /* to specify the face ID and its size. */
- /* */
- /* <Input> */
- /* cache :: A handle to the source sbit cache. */
- /* */
- /* scaler :: A pointer to the scaler descriptor. */
- /* */
- /* load_flags :: The corresponding load flags. */
- /* */
- /* gindex :: The glyph index. */
- /* */
- /* <Output> */
- /* sbit :: A handle to a small bitmap descriptor. */
- /* */
- /* anode :: Used to return the address of the corresponding */
- /* cache node after incrementing its reference count */
- /* (see note below). */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* The small bitmap descriptor and its bit buffer are owned by the */
- /* cache and should never be freed by the application. They might */
- /* as well disappear from memory on the next cache lookup, so don't */
- /* treat them as persistent data. */
- /* */
- /* The descriptor's `buffer' field is set to~0 to indicate a missing */
- /* glyph bitmap. */
- /* */
- /* If `anode' is _not_ NULL, it receives the address of the cache */
- /* node containing the bitmap, after increasing its reference count. */
- /* This ensures that the node (as well as the image) will always be */
- /* kept in the cache until you call @FTC_Node_Unref to `release' it. */
- /* */
- /* If `anode' is NULL, the cache node is left unchanged, which means */
- /* that the bitmap could be flushed out of the cache on the next */
- /* call to one of the caching sub-system APIs. Don't assume that it */
- /* is persistent! */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FTC_SBitCache_LookupScaler
+ *
+ * @description:
+ * A variant of @FTC_SBitCache_Lookup that uses an @FTC_ScalerRec to
+ * specify the face ID and its size.
+ *
+ * @input:
+ * cache ::
+ * A handle to the source sbit cache.
+ *
+ * scaler ::
+ * A pointer to the scaler descriptor.
+ *
+ * load_flags ::
+ * The corresponding load flags.
+ *
+ * gindex ::
+ * The glyph index.
+ *
+ * @output:
+ * sbit ::
+ * A handle to a small bitmap descriptor.
+ *
+ * anode ::
+ * Used to return the address of the corresponding cache node after
+ * incrementing its reference count (see note below).
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The small bitmap descriptor and its bit buffer are owned by the cache
+ * and should never be freed by the application. They might as well
+ * disappear from memory on the next cache lookup, so don't treat them as
+ * persistent data.
+ *
+ * The descriptor's `buffer` field is set to~0 to indicate a missing
+ * glyph bitmap.
+ *
+ * If `anode` is _not_ `NULL`, it receives the address of the cache node
+ * containing the bitmap, after increasing its reference count. This
+ * ensures that the node (as well as the image) will always be kept in
+ * the cache until you call @FTC_Node_Unref to 'release' it.
+ *
+ * If `anode` is `NULL`, the cache node is left unchanged, which means
+ * that the bitmap could be flushed out of the cache on the next call to
+ * one of the caching sub-system APIs. Don't assume that it is
+ * persistent!
+ */
FT_EXPORT( FT_Error )
FTC_SBitCache_LookupScaler( FTC_SBitCache cache,
FTC_Scaler scaler,
diff --git a/thirdparty/freetype/include/freetype/ftcffdrv.h b/thirdparty/freetype/include/freetype/ftcffdrv.h
deleted file mode 100644
index 477b6ddb18..0000000000
--- a/thirdparty/freetype/include/freetype/ftcffdrv.h
+++ /dev/null
@@ -1,321 +0,0 @@
-/***************************************************************************/
-/* */
-/* ftcffdrv.h */
-/* */
-/* FreeType API for controlling the CFF driver (specification only). */
-/* */
-/* Copyright 2013-2017 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#ifndef FTCFFDRV_H_
-#define FTCFFDRV_H_
-
-#include <ft2build.h>
-#include FT_FREETYPE_H
-
-#ifdef FREETYPE_H
-#error "freetype.h of FreeType 1 has been loaded!"
-#error "Please fix the directory search order for header files"
-#error "so that freetype.h of FreeType 2 is found first."
-#endif
-
-
-FT_BEGIN_HEADER
-
-
- /**************************************************************************
- *
- * @section:
- * cff_driver
- *
- * @title:
- * The CFF driver
- *
- * @abstract:
- * Controlling the CFF driver module.
- *
- * @description:
- * While FreeType's CFF driver doesn't expose API functions by itself,
- * it is possible to control its behaviour with @FT_Property_Set and
- * @FT_Property_Get. The list below gives the available properties
- * together with the necessary macros and structures.
- *
- * The CFF driver's module name is `cff'.
- *
- * *Hinting* *and* *antialiasing* *principles* *of* *the* *new* *engine*
- *
- * The rasterizer is positioning horizontal features (e.g., ascender
- * height & x-height, or crossbars) on the pixel grid and minimizing the
- * amount of antialiasing applied to them, while placing vertical
- * features (vertical stems) on the pixel grid without hinting, thus
- * representing the stem position and weight accurately. Sometimes the
- * vertical stems may be only partially black. In this context,
- * `antialiasing' means that stems are not positioned exactly on pixel
- * borders, causing a fuzzy appearance.
- *
- * There are two principles behind this approach.
- *
- * 1) No hinting in the horizontal direction: Unlike `superhinted'
- * TrueType, which changes glyph widths to accommodate regular
- * inter-glyph spacing, Adobe's approach is `faithful to the design' in
- * representing both the glyph width and the inter-glyph spacing
- * designed for the font. This makes the screen display as close as it
- * can be to the result one would get with infinite resolution, while
- * preserving what is considered the key characteristics of each glyph.
- * Note that the distances between unhinted and grid-fitted positions at
- * small sizes are comparable to kerning values and thus would be
- * noticeable (and distracting) while reading if hinting were applied.
- *
- * One of the reasons to not hint horizontally is antialiasing for LCD
- * screens: The pixel geometry of modern displays supplies three
- * vertical sub-pixels as the eye moves horizontally across each visible
- * pixel. On devices where we can be certain this characteristic is
- * present a rasterizer can take advantage of the sub-pixels to add
- * increments of weight. In Western writing systems this turns out to
- * be the more critical direction anyway; the weights and spacing of
- * vertical stems (see above) are central to Armenian, Cyrillic, Greek,
- * and Latin type designs. Even when the rasterizer uses greyscale
- * antialiasing instead of color (a necessary compromise when one
- * doesn't know the screen characteristics), the unhinted vertical
- * features preserve the design's weight and spacing much better than
- * aliased type would.
- *
- * 2) Alignment in the vertical direction: Weights and spacing along the
- * y~axis are less critical; what is much more important is the visual
- * alignment of related features (like cap-height and x-height). The
- * sense of alignment for these is enhanced by the sharpness of grid-fit
- * edges, while the cruder vertical resolution (full pixels instead of
- * 1/3 pixels) is less of a problem.
- *
- * On the technical side, horizontal alignment zones for ascender,
- * x-height, and other important height values (traditionally called
- * `blue zones') as defined in the font are positioned independently,
- * each being rounded to the nearest pixel edge, taking care of
- * overshoot suppression at small sizes, stem darkening, and scaling.
- *
- * Hstems (this is, hint values defined in the font to help align
- * horizontal features) that fall within a blue zone are said to be
- * `captured' and are aligned to that zone. Uncaptured stems are moved
- * in one of four ways, top edge up or down, bottom edge up or down.
- * Unless there are conflicting hstems, the smallest movement is taken
- * to minimize distortion.
- *
- * @order:
- * hinting-engine[cff]
- * no-stem-darkening[cff]
- * darkening-parameters[cff]
- * random-seed
- *
- */
-
-
- /**************************************************************************
- *
- * @property:
- * hinting-engine[cff]
- *
- * @description:
- * Thanks to Adobe, which contributed a new hinting (and parsing)
- * engine, an application can select between `freetype' and `adobe' if
- * compiled with CFF_CONFIG_OPTION_OLD_ENGINE. If this configuration
- * macro isn't defined, `hinting-engine' does nothing.
- *
- * The default engine is `freetype' if CFF_CONFIG_OPTION_OLD_ENGINE is
- * defined, and `adobe' otherwise.
- *
- * The following example code demonstrates how to select Adobe's hinting
- * engine (omitting the error handling).
- *
- * {
- * FT_Library library;
- * FT_UInt hinting_engine = FT_CFF_HINTING_ADOBE;
- *
- *
- * FT_Init_FreeType( &library );
- *
- * FT_Property_Set( library, "cff",
- * "hinting-engine", &hinting_engine );
- * }
- *
- * @note:
- * This property can be used with @FT_Property_Get also.
- *
- * This property can be set via the `FREETYPE_PROPERTIES' environment
- * variable (using values `adobe' or `freetype').
- */
-
-
- /**************************************************************************
- *
- * @enum:
- * FT_CFF_HINTING_XXX
- *
- * @description:
- * A list of constants used for the @hinting-engine[cff] property to
- * select the hinting engine for CFF fonts.
- *
- * @values:
- * FT_CFF_HINTING_FREETYPE ::
- * Use the old FreeType hinting engine.
- *
- * FT_CFF_HINTING_ADOBE ::
- * Use the hinting engine contributed by Adobe.
- *
- */
-#define FT_CFF_HINTING_FREETYPE 0
-#define FT_CFF_HINTING_ADOBE 1
-
-
- /**************************************************************************
- *
- * @property:
- * no-stem-darkening[cff]
- *
- * @description:
- * By default, the Adobe CFF engine darkens stems at smaller sizes,
- * regardless of hinting, to enhance contrast. This feature requires
- * a rendering system with proper gamma correction. Setting this
- * property, stem darkening gets switched off.
- *
- * Note that stem darkening is never applied if @FT_LOAD_NO_SCALE is set.
- *
- * {
- * FT_Library library;
- * FT_Bool no_stem_darkening = TRUE;
- *
- *
- * FT_Init_FreeType( &library );
- *
- * FT_Property_Set( library, "cff",
- * "no-stem-darkening", &no_stem_darkening );
- * }
- *
- * @note:
- * This property can be used with @FT_Property_Get also.
- *
- * This property can be set via the `FREETYPE_PROPERTIES' environment
- * variable (using values 1 and 0 for `on' and `off', respectively).
- * It can also be set per face using @FT_Face_Properties with
- * @FT_PARAM_TAG_STEM_DARKENING.
- *
- */
-
-
- /**************************************************************************
- *
- * @property:
- * darkening-parameters[cff]
- *
- * @description:
- * By default, the Adobe CFF engine darkens stems as follows (if the
- * `no-stem-darkening' property isn't set):
- *
- * {
- * stem width <= 0.5px: darkening amount = 0.4px
- * stem width = 1px: darkening amount = 0.275px
- * stem width = 1.667px: darkening amount = 0.275px
- * stem width >= 2.333px: darkening amount = 0px
- * }
- *
- * and piecewise linear in-between. At configuration time, these four
- * control points can be set with the macro
- * `CFF_CONFIG_OPTION_DARKENING_PARAMETERS'. At runtime, the control
- * points can be changed using the `darkening-parameters' property, as
- * the following example demonstrates.
- *
- * {
- * FT_Library library;
- * FT_Int darken_params[8] = { 500, 300, // x1, y1
- * 1000, 200, // x2, y2
- * 1500, 100, // x3, y3
- * 2000, 0 }; // x4, y4
- *
- *
- * FT_Init_FreeType( &library );
- *
- * FT_Property_Set( library, "cff",
- * "darkening-parameters", darken_params );
- * }
- *
- * The x~values give the stem width, and the y~values the darkening
- * amount. The unit is 1000th of pixels. All coordinate values must be
- * positive; the x~values must be monotonically increasing; the
- * y~values must be monotonically decreasing and smaller than or
- * equal to 500 (corresponding to half a pixel); the slope of each
- * linear piece must be shallower than -1 (e.g., -.4).
- *
- * @note:
- * This property can be used with @FT_Property_Get also.
- *
- * This property can be set via the `FREETYPE_PROPERTIES' environment
- * variable, using eight comma-separated integers without spaces. Here
- * the above example, using `\' to break the line for readability.
- *
- * {
- * FREETYPE_PROPERTIES=\
- * cff:darkening-parameters=500,300,1000,200,1500,100,2000,0
- * }
- */
-
-
- /**************************************************************************
- *
- * @property:
- * random-seed
- *
- * @description:
- * By default, the seed value for the CFF `random' operator is set to a
- * random value. However, mainly for debugging purposes, it is often
- * necessary to use a known value as a seed so that the pseudo-random
- * number sequences generated by `random' are repeatable.
- *
- * The `random-seed' property does that. Its argument is a signed 32bit
- * integer; if the value is zero or negative, the seed given by the
- * `intitialRandomSeed' private DICT operator in a CFF file gets used
- * (or a default value if there is no such operator). If the value is
- * positive, use it instead of `initialRandomSeed', which is
- * consequently ignored.
- *
- * @note:
- * This property can be set via the `FREETYPE_PROPERTIES' environment
- * variable. It can also be set per face using @FT_Face_Properties with
- * @FT_PARAM_TAG_RANDOM_SEED.
- *
- */
-
-
- /**************************************************************************
- *
- * @constant:
- * FT_PARAM_TAG_RANDOM_SEED
- *
- * @description:
- * An @FT_Parameter tag to be used with @FT_Face_Properties. The
- * corresponding 32bit signed integer argument overrides the CFF
- * module's random seed value with a face-specific one; see
- * @random-seed.
- *
- */
-#define FT_PARAM_TAG_RANDOM_SEED \
- FT_MAKE_TAG( 's', 'e', 'e', 'd' )
-
-
- /* */
-
-
-FT_END_HEADER
-
-
-#endif /* FTCFFDRV_H_ */
-
-
-/* END */
diff --git a/thirdparty/freetype/include/freetype/ftchapters.h b/thirdparty/freetype/include/freetype/ftchapters.h
index 51257bb7ca..2ee26973e4 100644
--- a/thirdparty/freetype/include/freetype/ftchapters.h
+++ b/thirdparty/freetype/include/freetype/ftchapters.h
@@ -1,139 +1,145 @@
-/***************************************************************************/
-/* */
-/* This file defines the structure of the FreeType reference. */
-/* It is used by the python script that generates the HTML files. */
-/* */
-/***************************************************************************/
-
-
-/***************************************************************************/
-/* */
-/* <Chapter> */
-/* general_remarks */
-/* */
-/* <Title> */
-/* General Remarks */
-/* */
-/* <Sections> */
-/* header_inclusion */
-/* user_allocation */
-/* */
-/***************************************************************************/
-
-
-/***************************************************************************/
-/* */
-/* <Chapter> */
-/* core_api */
-/* */
-/* <Title> */
-/* Core API */
-/* */
-/* <Sections> */
-/* version */
-/* basic_types */
-/* base_interface */
-/* glyph_variants */
-/* glyph_management */
-/* mac_specific */
-/* sizes_management */
-/* header_file_macros */
-/* */
-/***************************************************************************/
-
-
-/***************************************************************************/
-/* */
-/* <Chapter> */
-/* format_specific */
-/* */
-/* <Title> */
-/* Format-Specific API */
-/* */
-/* <Sections> */
-/* multiple_masters */
-/* truetype_tables */
-/* type1_tables */
-/* sfnt_names */
-/* bdf_fonts */
-/* cid_fonts */
-/* pfr_fonts */
-/* winfnt_fonts */
-/* font_formats */
-/* gasp_table */
-/* */
-/***************************************************************************/
-
-
-/***************************************************************************/
-/* */
-/* <Chapter> */
-/* module_specific */
-/* */
-/* <Title> */
-/* Controlling FreeType Modules */
-/* */
-/* <Sections> */
-/* auto_hinter */
-/* cff_driver */
-/* t1_cid_driver */
-/* tt_driver */
-/* pcf_driver */
-/* properties */
-/* parameter_tags */
-/* */
-/***************************************************************************/
-
-
-/***************************************************************************/
-/* */
-/* <Chapter> */
-/* cache_subsystem */
-/* */
-/* <Title> */
-/* Cache Sub-System */
-/* */
-/* <Sections> */
-/* cache_subsystem */
-/* */
-/***************************************************************************/
-
-
-/***************************************************************************/
-/* */
-/* <Chapter> */
-/* support_api */
-/* */
-/* <Title> */
-/* Support API */
-/* */
-/* <Sections> */
-/* computations */
-/* list_processing */
-/* outline_processing */
-/* quick_advance */
-/* bitmap_handling */
-/* raster */
-/* glyph_stroker */
-/* system_interface */
-/* module_management */
-/* gzip */
-/* lzw */
-/* bzip2 */
-/* lcd_filtering */
-/* */
-/***************************************************************************/
-
-/***************************************************************************/
-/* */
-/* <Chapter> */
-/* error_codes */
-/* */
-/* <Title> */
-/* Error Codes */
-/* */
-/* <Sections> */
-/* error_enumerations */
-/* error_code_values */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * This file defines the structure of the FreeType reference.
+ * It is used by the python script that generates the HTML files.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @chapter:
+ * general_remarks
+ *
+ * @title:
+ * General Remarks
+ *
+ * @sections:
+ * header_inclusion
+ * user_allocation
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @chapter:
+ * core_api
+ *
+ * @title:
+ * Core API
+ *
+ * @sections:
+ * version
+ * basic_types
+ * base_interface
+ * glyph_variants
+ * color_management
+ * layer_management
+ * glyph_management
+ * mac_specific
+ * sizes_management
+ * header_file_macros
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @chapter:
+ * format_specific
+ *
+ * @title:
+ * Format-Specific API
+ *
+ * @sections:
+ * multiple_masters
+ * truetype_tables
+ * type1_tables
+ * sfnt_names
+ * bdf_fonts
+ * cid_fonts
+ * pfr_fonts
+ * winfnt_fonts
+ * font_formats
+ * gasp_table
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @chapter:
+ * module_specific
+ *
+ * @title:
+ * Controlling FreeType Modules
+ *
+ * @sections:
+ * auto_hinter
+ * cff_driver
+ * t1_cid_driver
+ * tt_driver
+ * pcf_driver
+ * properties
+ * parameter_tags
+ * lcd_rendering
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @chapter:
+ * cache_subsystem
+ *
+ * @title:
+ * Cache Sub-System
+ *
+ * @sections:
+ * cache_subsystem
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @chapter:
+ * support_api
+ *
+ * @title:
+ * Support API
+ *
+ * @sections:
+ * computations
+ * list_processing
+ * outline_processing
+ * quick_advance
+ * bitmap_handling
+ * raster
+ * glyph_stroker
+ * system_interface
+ * module_management
+ * gzip
+ * lzw
+ * bzip2
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @chapter:
+ * error_codes
+ *
+ * @title:
+ * Error Codes
+ *
+ * @sections:
+ * error_enumerations
+ * error_code_values
+ *
+ */
+
+
+/* END */
diff --git a/thirdparty/freetype/include/freetype/ftcid.h b/thirdparty/freetype/include/freetype/ftcid.h
index 5e9100a67c..8eafc1c78f 100644
--- a/thirdparty/freetype/include/freetype/ftcid.h
+++ b/thirdparty/freetype/include/freetype/ftcid.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftcid.h */
-/* */
-/* FreeType API for accessing CID font information (specification). */
-/* */
-/* Copyright 2007-2018 by */
-/* Dereg Clegg and Michael Toftdal. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftcid.h
+ *
+ * FreeType API for accessing CID font information (specification).
+ *
+ * Copyright (C) 2007-2019 by
+ * Dereg Clegg and Michael Toftdal.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTCID_H_
@@ -32,25 +32,25 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* <Section> */
- /* cid_fonts */
- /* */
- /* <Title> */
- /* CID Fonts */
- /* */
- /* <Abstract> */
- /* CID-keyed font specific API. */
- /* */
- /* <Description> */
- /* This section contains the declaration of CID-keyed font specific */
- /* functions. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * @section:
+ * cid_fonts
+ *
+ * @title:
+ * CID Fonts
+ *
+ * @abstract:
+ * CID-keyed font-specific API.
+ *
+ * @description:
+ * This section contains the declaration of CID-keyed font-specific
+ * functions.
+ *
+ */
- /**********************************************************************
+ /**************************************************************************
*
* @function:
* FT_Get_CID_Registry_Ordering_Supplement
@@ -61,17 +61,17 @@ FT_BEGIN_HEADER
*
* @input:
* face ::
- * A handle to the input face.
+ * A handle to the input face.
*
* @output:
* registry ::
- * The registry, as a C~string, owned by the face.
+ * The registry, as a C~string, owned by the face.
*
* ordering ::
- * The ordering, as a C~string, owned by the face.
+ * The ordering, as a C~string, owned by the face.
*
* supplement ::
- * The supplement.
+ * The supplement.
*
* @return:
* FreeType error code. 0~means success.
@@ -90,30 +90,30 @@ FT_BEGIN_HEADER
FT_Int *supplement );
- /**********************************************************************
+ /**************************************************************************
*
* @function:
* FT_Get_CID_Is_Internally_CID_Keyed
*
* @description:
- * Retrieve the type of the input face, CID keyed or not. In
- * contrast to the @FT_IS_CID_KEYED macro this function returns
- * successfully also for CID-keyed fonts in an SFNT wrapper.
+ * Retrieve the type of the input face, CID keyed or not. In contrast
+ * to the @FT_IS_CID_KEYED macro this function returns successfully also
+ * for CID-keyed fonts in an SFNT wrapper.
*
* @input:
* face ::
- * A handle to the input face.
+ * A handle to the input face.
*
* @output:
* is_cid ::
- * The type of the face as an @FT_Bool.
+ * The type of the face as an @FT_Bool.
*
* @return:
* FreeType error code. 0~means success.
*
* @note:
- * This function only works with CID faces and OpenType fonts,
- * returning an error otherwise.
+ * This function only works with CID faces and OpenType fonts, returning
+ * an error otherwise.
*
* @since:
* 2.3.9
@@ -123,7 +123,7 @@ FT_BEGIN_HEADER
FT_Bool *is_cid );
- /**********************************************************************
+ /**************************************************************************
*
* @function:
* FT_Get_CID_From_Glyph_Index
@@ -133,21 +133,21 @@ FT_BEGIN_HEADER
*
* @input:
* face ::
- * A handle to the input face.
+ * A handle to the input face.
*
* glyph_index ::
- * The input glyph index.
+ * The input glyph index.
*
* @output:
* cid ::
- * The CID as an @FT_UInt.
+ * The CID as an @FT_UInt.
*
* @return:
* FreeType error code. 0~means success.
*
* @note:
- * This function only works with CID faces and OpenType fonts,
- * returning an error otherwise.
+ * This function only works with CID faces and OpenType fonts, returning
+ * an error otherwise.
*
* @since:
* 2.3.9
diff --git a/thirdparty/freetype/include/freetype/ftcolor.h b/thirdparty/freetype/include/freetype/ftcolor.h
new file mode 100644
index 0000000000..cf18021953
--- /dev/null
+++ b/thirdparty/freetype/include/freetype/ftcolor.h
@@ -0,0 +1,311 @@
+/****************************************************************************
+ *
+ * ftcolor.h
+ *
+ * FreeType's glyph color management (specification).
+ *
+ * Copyright (C) 2018-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef FTCOLOR_H_
+#define FTCOLOR_H_
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * color_management
+ *
+ * @title:
+ * Glyph Color Management
+ *
+ * @abstract:
+ * Retrieving and manipulating OpenType's 'CPAL' table data.
+ *
+ * @description:
+ * The functions described here allow access and manipulation of color
+ * palette entries in OpenType's 'CPAL' tables.
+ */
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Color
+ *
+ * @description:
+ * This structure models a BGRA color value of a 'CPAL' palette entry.
+ *
+ * The used color space is sRGB; the colors are not pre-multiplied, and
+ * alpha values must be explicitly set.
+ *
+ * @fields:
+ * blue ::
+ * Blue value.
+ *
+ * green ::
+ * Green value.
+ *
+ * red ::
+ * Red value.
+ *
+ * alpha ::
+ * Alpha value, giving the red, green, and blue color's opacity.
+ *
+ * @since:
+ * 2.10
+ */
+ typedef struct FT_Color_
+ {
+ FT_Byte blue;
+ FT_Byte green;
+ FT_Byte red;
+ FT_Byte alpha;
+
+ } FT_Color;
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_PALETTE_XXX
+ *
+ * @description:
+ * A list of bit field constants used in the `palette_flags` array of the
+ * @FT_Palette_Data structure to indicate for which background a palette
+ * with a given index is usable.
+ *
+ * @values:
+ * FT_PALETTE_FOR_LIGHT_BACKGROUND ::
+ * The palette is appropriate to use when displaying the font on a
+ * light background such as white.
+ *
+ * FT_PALETTE_FOR_DARK_BACKGROUND ::
+ * The palette is appropriate to use when displaying the font on a dark
+ * background such as black.
+ *
+ * @since:
+ * 2.10
+ */
+#define FT_PALETTE_FOR_LIGHT_BACKGROUND 0x01
+#define FT_PALETTE_FOR_DARK_BACKGROUND 0x02
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Palette_Data
+ *
+ * @description:
+ * This structure holds the data of the 'CPAL' table.
+ *
+ * @fields:
+ * num_palettes ::
+ * The number of palettes.
+ *
+ * palette_name_ids ::
+ * A read-only array of palette name IDs with `num_palettes` elements,
+ * corresponding to entries like 'dark' or 'light' in the font's 'name'
+ * table.
+ *
+ * An empty name ID in the 'CPAL' table gets represented as value
+ * 0xFFFF.
+ *
+ * `NULL` if the font's 'CPAL' table doesn't contain appropriate data.
+ *
+ * palette_flags ::
+ * A read-only array of palette flags with `num_palettes` elements.
+ * Possible values are an ORed combination of
+ * @FT_PALETTE_FOR_LIGHT_BACKGROUND and
+ * @FT_PALETTE_FOR_DARK_BACKGROUND.
+ *
+ * `NULL` if the font's 'CPAL' table doesn't contain appropriate data.
+ *
+ * num_palette_entries ::
+ * The number of entries in a single palette. All palettes have the
+ * same size.
+ *
+ * palette_entry_name_ids ::
+ * A read-only array of palette entry name IDs with
+ * `num_palette_entries`. In each palette, entries with the same index
+ * have the same function. For example, index~0 might correspond to
+ * string 'outline' in the font's 'name' table to indicate that this
+ * palette entry is used for outlines, index~1 might correspond to
+ * 'fill' to indicate the filling color palette entry, etc.
+ *
+ * An empty entry name ID in the 'CPAL' table gets represented as value
+ * 0xFFFF.
+ *
+ * `NULL` if the font's 'CPAL' table doesn't contain appropriate data.
+ *
+ * @note:
+ * Use function @FT_Get_Sfnt_Name to map name IDs and entry name IDs to
+ * name strings.
+ *
+ * @since:
+ * 2.10
+ */
+ typedef struct FT_Palette_Data_ {
+ FT_UShort num_palettes;
+ const FT_UShort* palette_name_ids;
+ const FT_UShort* palette_flags;
+
+ FT_UShort num_palette_entries;
+ const FT_UShort* palette_entry_name_ids;
+
+ } FT_Palette_Data;
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Palette_Data_Get
+ *
+ * @description:
+ * Retrieve the face's color palette data.
+ *
+ * @input:
+ * face ::
+ * The source face handle.
+ *
+ * @output:
+ * apalette ::
+ * A pointer to an @FT_Palette_Data structure.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * All arrays in the returned @FT_Palette_Data structure are read-only.
+ *
+ * This function always returns an error if the config macro
+ * `TT_CONFIG_OPTION_COLOR_LAYERS` is not defined in `ftoption.h`.
+ *
+ * @since:
+ * 2.10
+ */
+ FT_EXPORT( FT_Error )
+ FT_Palette_Data_Get( FT_Face face,
+ FT_Palette_Data *apalette );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Palette_Select
+ *
+ * @description:
+ * This function has two purposes.
+ *
+ * (1) It activates a palette for rendering color glyphs, and
+ *
+ * (2) it retrieves all (unmodified) color entries of this palette. This
+ * function returns a read-write array, which means that a calling
+ * application can modify the palette entries on demand.
+ *
+ * A corollary of (2) is that calling the function, then modifying some
+ * values, then calling the function again with the same arguments resets
+ * all color entries to the original 'CPAL' values; all user modifications
+ * are lost.
+ *
+ * @input:
+ * face ::
+ * The source face handle.
+ *
+ * palette_index ::
+ * The palette index.
+ *
+ * @output:
+ * apalette ::
+ * An array of color entries for a palette with index `palette_index`,
+ * having `num_palette_entries` elements (as found in the
+ * `FT_Palette_Data` structure). If `apalette` is set to `NULL`, no
+ * array gets returned (and no color entries can be modified).
+ *
+ * In case the font doesn't support color palettes, `NULL` is returned.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The array pointed to by `apalette_entries` is owned and managed by
+ * FreeType.
+ *
+ * This function always returns an error if the config macro
+ * `TT_CONFIG_OPTION_COLOR_LAYERS` is not defined in `ftoption.h`.
+ *
+ * @since:
+ * 2.10
+ */
+ FT_EXPORT( FT_Error )
+ FT_Palette_Select( FT_Face face,
+ FT_UShort palette_index,
+ FT_Color* *apalette );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Palette_Set_Foreground_Color
+ *
+ * @description:
+ * 'COLR' uses palette index 0xFFFF to indicate a 'text foreground
+ * color'. This function sets this value.
+ *
+ * @input:
+ * face ::
+ * The source face handle.
+ *
+ * foreground_color ::
+ * An `FT_Color` structure to define the text foreground color.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * If this function isn't called, the text foreground color is set to
+ * white opaque (BGRA value 0xFFFFFFFF) if
+ * @FT_PALETTE_FOR_DARK_BACKGROUND is present for the current palette,
+ * and black opaque (BGRA value 0x000000FF) otherwise, including the case
+ * that no palette types are available in the 'CPAL' table.
+ *
+ * This function always returns an error if the config macro
+ * `TT_CONFIG_OPTION_COLOR_LAYERS` is not defined in `ftoption.h`.
+ *
+ * @since:
+ * 2.10
+ */
+ FT_EXPORT( FT_Error )
+ FT_Palette_Set_Foreground_Color( FT_Face face,
+ FT_Color foreground_color );
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* FTCOLOR_H_ */
+
+
+/* END */
diff --git a/thirdparty/freetype/include/freetype/ftdriver.h b/thirdparty/freetype/include/freetype/ftdriver.h
index e90475b2af..497bde9f6e 100644
--- a/thirdparty/freetype/include/freetype/ftdriver.h
+++ b/thirdparty/freetype/include/freetype/ftdriver.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftdriver.h */
-/* */
-/* FreeType API for controlling driver modules (specification only). */
-/* */
-/* Copyright 2017-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftdriver.h
+ *
+ * FreeType API for controlling driver modules (specification only).
+ *
+ * Copyright (C) 2017-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTDRIVER_H_
@@ -50,8 +50,8 @@ FT_BEGIN_HEADER
* @FT_Property_Get. The following lists the available properties
* together with the necessary macros and structures.
*
- * Note that the auto-hinter's module name is `autofitter' for
- * historical reasons.
+ * Note that the auto-hinter's module name is 'autofitter' for historical
+ * reasons.
*
* Available properties are @increase-x-height, @no-stem-darkening
* (experimental), @darkening-parameters (experimental), @warping
@@ -74,18 +74,18 @@ FT_BEGIN_HEADER
* Controlling the CFF driver module.
*
* @description:
- * While FreeType's CFF driver doesn't expose API functions by itself,
- * it is possible to control its behaviour with @FT_Property_Set and
+ * While FreeType's CFF driver doesn't expose API functions by itself, it
+ * is possible to control its behaviour with @FT_Property_Set and
* @FT_Property_Get.
*
- * The CFF driver's module name is `cff'.
+ * The CFF driver's module name is 'cff'.
*
* Available properties are @hinting-engine, @no-stem-darkening,
* @darkening-parameters, and @random-seed, as documented in the
* @properties section.
*
*
- * *Hinting* *and* *antialiasing* *principles* *of* *the* *new* *engine*
+ * **Hinting and antialiasing principles of the new engine**
*
* The rasterizer is positioning horizontal features (e.g., ascender
* height & x-height, or crossbars) on the pixel grid and minimizing the
@@ -93,35 +93,34 @@ FT_BEGIN_HEADER
* features (vertical stems) on the pixel grid without hinting, thus
* representing the stem position and weight accurately. Sometimes the
* vertical stems may be only partially black. In this context,
- * `antialiasing' means that stems are not positioned exactly on pixel
+ * 'antialiasing' means that stems are not positioned exactly on pixel
* borders, causing a fuzzy appearance.
*
* There are two principles behind this approach.
*
- * 1) No hinting in the horizontal direction: Unlike `superhinted'
+ * 1) No hinting in the horizontal direction: Unlike 'superhinted'
* TrueType, which changes glyph widths to accommodate regular
- * inter-glyph spacing, Adobe's approach is `faithful to the design' in
- * representing both the glyph width and the inter-glyph spacing
- * designed for the font. This makes the screen display as close as it
- * can be to the result one would get with infinite resolution, while
- * preserving what is considered the key characteristics of each glyph.
- * Note that the distances between unhinted and grid-fitted positions at
- * small sizes are comparable to kerning values and thus would be
- * noticeable (and distracting) while reading if hinting were applied.
+ * inter-glyph spacing, Adobe's approach is 'faithful to the design' in
+ * representing both the glyph width and the inter-glyph spacing designed
+ * for the font. This makes the screen display as close as it can be to
+ * the result one would get with infinite resolution, while preserving
+ * what is considered the key characteristics of each glyph. Note that
+ * the distances between unhinted and grid-fitted positions at small
+ * sizes are comparable to kerning values and thus would be noticeable
+ * (and distracting) while reading if hinting were applied.
*
* One of the reasons to not hint horizontally is antialiasing for LCD
- * screens: The pixel geometry of modern displays supplies three
- * vertical subpixels as the eye moves horizontally across each visible
- * pixel. On devices where we can be certain this characteristic is
- * present a rasterizer can take advantage of the subpixels to add
- * increments of weight. In Western writing systems this turns out to
- * be the more critical direction anyway; the weights and spacing of
- * vertical stems (see above) are central to Armenian, Cyrillic, Greek,
- * and Latin type designs. Even when the rasterizer uses greyscale
- * antialiasing instead of color (a necessary compromise when one
- * doesn't know the screen characteristics), the unhinted vertical
- * features preserve the design's weight and spacing much better than
- * aliased type would.
+ * screens: The pixel geometry of modern displays supplies three vertical
+ * subpixels as the eye moves horizontally across each visible pixel. On
+ * devices where we can be certain this characteristic is present a
+ * rasterizer can take advantage of the subpixels to add increments of
+ * weight. In Western writing systems this turns out to be the more
+ * critical direction anyway; the weights and spacing of vertical stems
+ * (see above) are central to Armenian, Cyrillic, Greek, and Latin type
+ * designs. Even when the rasterizer uses greyscale antialiasing instead
+ * of color (a necessary compromise when one doesn't know the screen
+ * characteristics), the unhinted vertical features preserve the design's
+ * weight and spacing much better than aliased type would.
*
* 2) Alignment in the vertical direction: Weights and spacing along the
* y~axis are less critical; what is much more important is the visual
@@ -132,16 +131,16 @@ FT_BEGIN_HEADER
*
* On the technical side, horizontal alignment zones for ascender,
* x-height, and other important height values (traditionally called
- * `blue zones') as defined in the font are positioned independently,
- * each being rounded to the nearest pixel edge, taking care of
- * overshoot suppression at small sizes, stem darkening, and scaling.
+ * 'blue zones') as defined in the font are positioned independently,
+ * each being rounded to the nearest pixel edge, taking care of overshoot
+ * suppression at small sizes, stem darkening, and scaling.
*
* Hstems (this is, hint values defined in the font to help align
* horizontal features) that fall within a blue zone are said to be
- * `captured' and are aligned to that zone. Uncaptured stems are moved
+ * 'captured' and are aligned to that zone. Uncaptured stems are moved
* in one of four ways, top edge up or down, bottom edge up or down.
- * Unless there are conflicting hstems, the smallest movement is taken
- * to minimize distortion.
+ * Unless there are conflicting hstems, the smallest movement is taken to
+ * minimize distortion.
*
*/
@@ -158,13 +157,13 @@ FT_BEGIN_HEADER
* Controlling the PCF driver module.
*
* @description:
- * While FreeType's PCF driver doesn't expose API functions by itself,
- * it is possible to control its behaviour with @FT_Property_Set and
+ * While FreeType's PCF driver doesn't expose API functions by itself, it
+ * is possible to control its behaviour with @FT_Property_Set and
* @FT_Property_Get. Right now, there is a single property
* @no-long-family-names available if FreeType is compiled with
* PCF_CONFIG_OPTION_LONG_FAMILY_NAMES.
*
- * The PCF driver's module name is `pcf'.
+ * The PCF driver's module name is 'pcf'.
*
*/
@@ -187,15 +186,15 @@ FT_BEGIN_HEADER
* Behind the scenes, both drivers use the Adobe CFF engine for hinting;
* however, the used properties must be specified separately.
*
- * The Type~1 driver's module name is `type1'; the CID driver's module
- * name is `t1cid'.
+ * The Type~1 driver's module name is 'type1'; the CID driver's module
+ * name is 't1cid'.
*
* Available properties are @hinting-engine, @no-stem-darkening,
* @darkening-parameters, and @random-seed, as documented in the
* @properties section.
*
- * Please see the @cff_driver section for more details on the new
- * hinting engine.
+ * Please see the @cff_driver section for more details on the new hinting
+ * engine.
*
*/
@@ -217,7 +216,7 @@ FT_BEGIN_HEADER
* and @FT_Property_Get. The following lists the available properties
* together with the necessary macros and structures.
*
- * The TrueType driver's module name is `truetype'.
+ * The TrueType driver's module name is 'truetype'.
*
* A single property @interpreter-version is available, as documented in
* the @properties section.
@@ -225,36 +224,36 @@ FT_BEGIN_HEADER
* We start with a list of definitions, kindly provided by Greg
* Hitchcock.
*
- * _Bi-Level_ _Rendering_
+ * _Bi-Level Rendering_
*
* Monochromatic rendering, exclusively used in the early days of
* TrueType by both Apple and Microsoft. Microsoft's GDI interface
* supported hinting of the right-side bearing point, such that the
* advance width could be non-linear. Most often this was done to
* achieve some level of glyph symmetry. To enable reasonable
- * performance (e.g., not having to run hinting on all glyphs just to
- * get the widths) there was a bit in the head table indicating if the
- * side bearing was hinted, and additional tables, `hdmx' and `LTSH', to
- * cache hinting widths across multiple sizes and device aspect ratios.
+ * performance (e.g., not having to run hinting on all glyphs just to get
+ * the widths) there was a bit in the head table indicating if the side
+ * bearing was hinted, and additional tables, 'hdmx' and 'LTSH', to cache
+ * hinting widths across multiple sizes and device aspect ratios.
*
- * _Font_ _Smoothing_
+ * _Font Smoothing_
*
* Microsoft's GDI implementation of anti-aliasing. Not traditional
* anti-aliasing as the outlines were hinted before the sampling. The
* widths matched the bi-level rendering.
*
- * _ClearType_ _Rendering_
+ * _ClearType Rendering_
*
* Technique that uses physical subpixels to improve rendering on LCD
* (and other) displays. Because of the higher resolution, many methods
- * of improving symmetry in glyphs through hinting the right-side
- * bearing were no longer necessary. This lead to what GDI calls
- * `natural widths' ClearType, see
- * http://www.beatstamm.com/typography/RTRCh4.htm#Sec21. Since hinting
+ * of improving symmetry in glyphs through hinting the right-side bearing
+ * were no longer necessary. This lead to what GDI calls 'natural
+ * widths' ClearType, see
+ * http://rastertragedy.com/RTRCh4.htm#Sec21. Since hinting
* has extra resolution, most non-linearity went away, but it is still
* possible for hints to change the advance widths in this mode.
*
- * _ClearType_ _Compatible_ _Widths_
+ * _ClearType Compatible Widths_
*
* One of the earliest challenges with ClearType was allowing the
* implementation in GDI to be selected without requiring all UI and
@@ -263,41 +262,41 @@ FT_BEGIN_HEADER
* to determine the width in bi-level rendering, and then re-run in
* ClearType, with the difference in widths being absorbed in the font
* hints for ClearType (mostly in the white space of hints); see
- * http://www.beatstamm.com/typography/RTRCh4.htm#Sec20. Somewhat by
+ * http://rastertragedy.com/RTRCh4.htm#Sec20. Somewhat by
* definition, compatible width ClearType allows for non-linear widths,
* but only when the bi-level version has non-linear widths.
*
- * _ClearType_ _Subpixel_ _Positioning_
+ * _ClearType Subpixel Positioning_
*
* One of the nice benefits of ClearType is the ability to more crisply
* display fractional widths; unfortunately, the GDI model of integer
* bitmaps did not support this. However, the WPF and Direct Write
- * frameworks do support fractional widths. DWrite calls this `natural
- * mode', not to be confused with GDI's `natural widths'. Subpixel
+ * frameworks do support fractional widths. DWrite calls this 'natural
+ * mode', not to be confused with GDI's 'natural widths'. Subpixel
* positioning, in the current implementation of Direct Write,
* unfortunately does not support hinted advance widths, see
- * http://www.beatstamm.com/typography/RTRCh4.htm#Sec22. Note that the
+ * http://rastertragedy.com/RTRCh4.htm#Sec22. Note that the
* TrueType interpreter fully allows the advance width to be adjusted in
* this mode, just the DWrite client will ignore those changes.
*
- * _ClearType_ _Backward_ _Compatibility_
+ * _ClearType Backward Compatibility_
*
* This is a set of exceptions made in the TrueType interpreter to
* minimize hinting techniques that were problematic with the extra
* resolution of ClearType; see
- * http://www.beatstamm.com/typography/RTRCh4.htm#Sec1 and
+ * http://rastertragedy.com/RTRCh4.htm#Sec1 and
* https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx.
- * This technique is not to be confused with ClearType compatible
- * widths. ClearType backward compatibility has no direct impact on
- * changing advance widths, but there might be an indirect impact on
- * disabling some deltas. This could be worked around in backward
- * compatibility mode.
+ * This technique is not to be confused with ClearType compatible widths.
+ * ClearType backward compatibility has no direct impact on changing
+ * advance widths, but there might be an indirect impact on disabling
+ * some deltas. This could be worked around in backward compatibility
+ * mode.
*
- * _Native_ _ClearType_ _Mode_
+ * _Native ClearType Mode_
*
- * (Not to be confused with `natural widths'.) This mode removes all
- * the exceptions in the TrueType interpreter when running with
- * ClearType. Any issues on widths would still apply, though.
+ * (Not to be confused with 'natural widths'.) This mode removes all the
+ * exceptions in the TrueType interpreter when running with ClearType.
+ * Any issues on widths would still apply, though.
*
*/
@@ -328,8 +327,8 @@ FT_BEGIN_HEADER
* FT_HINTING_XXX
*
* @description:
- * A list of constants used for the @hinting-engine property to
- * select the hinting engine for CFF, Type~1, and CID fonts.
+ * A list of constants used for the @hinting-engine property to select
+ * the hinting engine for CFF, Type~1, and CID fonts.
*
* @values:
* FT_HINTING_FREETYPE ::
@@ -356,45 +355,46 @@ FT_BEGIN_HEADER
* hinting-engine
*
* @description:
- * Thanks to Adobe, which contributed a new hinting (and parsing)
- * engine, an application can select between `freetype' and `adobe' if
- * compiled with CFF_CONFIG_OPTION_OLD_ENGINE. If this configuration
- * macro isn't defined, `hinting-engine' does nothing.
+ * Thanks to Adobe, which contributed a new hinting (and parsing) engine,
+ * an application can select between 'freetype' and 'adobe' if compiled
+ * with `CFF_CONFIG_OPTION_OLD_ENGINE`. If this configuration macro
+ * isn't defined, 'hinting-engine' does nothing.
*
* The same holds for the Type~1 and CID modules if compiled with
- * T1_CONFIG_OPTION_OLD_ENGINE.
+ * `T1_CONFIG_OPTION_OLD_ENGINE`.
*
- * For the `cff' module, the default engine is `freetype' if
- * CFF_CONFIG_OPTION_OLD_ENGINE is defined, and `adobe' otherwise.
+ * For the 'cff' module, the default engine is 'freetype' if
+ * `CFF_CONFIG_OPTION_OLD_ENGINE` is defined, and 'adobe' otherwise.
*
- * For both the `type1' and `t1cid' modules, the default engine is
- * `freetype' if T1_CONFIG_OPTION_OLD_ENGINE is defined, and `adobe'
+ * For both the 'type1' and 't1cid' modules, the default engine is
+ * 'freetype' if `T1_CONFIG_OPTION_OLD_ENGINE` is defined, and 'adobe'
* otherwise.
*
+ * @note:
+ * This property can be used with @FT_Property_Get also.
+ *
+ * This property can be set via the `FREETYPE_PROPERTIES` environment
+ * variable (using values 'adobe' or 'freetype').
+ *
+ * @example:
* The following example code demonstrates how to select Adobe's hinting
- * engine for the `cff' module (omitting the error handling).
+ * engine for the 'cff' module (omitting the error handling).
*
- * {
+ * ```
* FT_Library library;
- * FT_UInt hinting_engine = FT_CFF_HINTING_ADOBE;
+ * FT_UInt hinting_engine = FT_HINTING_ADOBE;
*
*
* FT_Init_FreeType( &library );
*
* FT_Property_Set( library, "cff",
* "hinting-engine", &hinting_engine );
- * }
- *
- * @note:
- * This property can be used with @FT_Property_Get also.
- *
- * This property can be set via the `FREETYPE_PROPERTIES' environment
- * variable (using values `adobe' or `freetype').
+ * ```
*
* @since:
- * 2.4.12 (for `cff' module)
+ * 2.4.12 (for 'cff' module)
*
- * 2.9 (for `type1' and `t1cid' modules)
+ * 2.9 (for 'type1' and 't1cid' modules)
*
*/
@@ -405,10 +405,10 @@ FT_BEGIN_HEADER
* no-stem-darkening
*
* @description:
- * All glyphs that pass through the auto-hinter will be emboldened
- * unless this property is set to TRUE. The same is true for the CFF,
- * Type~1, and CID font modules if the `Adobe' engine is selected (which
- * is the default).
+ * All glyphs that pass through the auto-hinter will be emboldened unless
+ * this property is set to TRUE. The same is true for the CFF, Type~1,
+ * and CID font modules if the 'Adobe' engine is selected (which is the
+ * default).
*
* Stem darkening emboldens glyphs at smaller sizes to make them more
* readable on common low-DPI screens when using linear alpha blending
@@ -419,30 +419,38 @@ FT_BEGIN_HEADER
* Gamma correction essentially lightens fonts since shades of grey are
* shifted to higher pixel values (=~higher brightness) to match the
* original intention to the reality of our screens. The side-effect is
- * that glyphs `thin out'. Mac OS~X and Adobe's proprietary font
+ * that glyphs 'thin out'. Mac OS~X and Adobe's proprietary font
* rendering library implement a counter-measure: stem darkening at
* smaller sizes where shades of gray dominate. By emboldening a glyph
* slightly in relation to its pixel size, individual pixels get higher
- * coverage of filled-in outlines and are therefore `blacker'. This
- * counteracts the `thinning out' of glyphs, making text remain readable
+ * coverage of filled-in outlines and are therefore 'blacker'. This
+ * counteracts the 'thinning out' of glyphs, making text remain readable
* at smaller sizes.
*
* By default, the Adobe engines for CFF, Type~1, and CID fonts darken
- * stems at smaller sizes, regardless of hinting, to enhance contrast.
+ * stems at smaller sizes, regardless of hinting, to enhance contrast.
* Setting this property, stem darkening gets switched off.
*
- * For the auto-hinter, stem-darkening is experimental currently and
- * thus switched off by default (this is, `no-stem-darkening' is set to
- * TRUE by default). Total consistency with the CFF driver is not
- * achieved right now because the emboldening method differs and glyphs
- * must be scaled down on the Y-axis to keep outline points inside their
+ * For the auto-hinter, stem-darkening is experimental currently and thus
+ * switched off by default (this is, `no-stem-darkening` is set to TRUE
+ * by default). Total consistency with the CFF driver is not achieved
+ * right now because the emboldening method differs and glyphs must be
+ * scaled down on the Y-axis to keep outline points inside their
* precomputed blue zones. The smaller the size (especially 9ppem and
* down), the higher the loss of emboldening versus the CFF driver.
*
- * Note that stem darkening is never applied if @FT_LOAD_NO_SCALE is
- * set.
+ * Note that stem darkening is never applied if @FT_LOAD_NO_SCALE is set.
+ *
+ * @note:
+ * This property can be used with @FT_Property_Get also.
+ *
+ * This property can be set via the `FREETYPE_PROPERTIES` environment
+ * variable (using values 1 and 0 for 'on' and 'off', respectively). It
+ * can also be set per face using @FT_Face_Properties with
+ * @FT_PARAM_TAG_STEM_DARKENING.
*
- * {
+ * @example:
+ * ```
* FT_Library library;
* FT_Bool no_stem_darkening = TRUE;
*
@@ -451,22 +459,14 @@ FT_BEGIN_HEADER
*
* FT_Property_Set( library, "cff",
* "no-stem-darkening", &no_stem_darkening );
- * }
- *
- * @note:
- * This property can be used with @FT_Property_Get also.
- *
- * This property can be set via the `FREETYPE_PROPERTIES' environment
- * variable (using values 1 and 0 for `on' and `off', respectively).
- * It can also be set per face using @FT_Face_Properties with
- * @FT_PARAM_TAG_STEM_DARKENING.
+ * ```
*
* @since:
- * 2.4.12 (for `cff' module)
+ * 2.4.12 (for 'cff' module)
*
- * 2.6.2 (for `autofitter' module)
+ * 2.6.2 (for 'autofitter' module)
*
- * 2.9 (for `type1' and `t1cid' modules)
+ * 2.9 (for 'type1' and 't1cid' modules)
*
*/
@@ -478,43 +478,29 @@ FT_BEGIN_HEADER
*
* @description:
* By default, the Adobe hinting engine, as used by the CFF, Type~1, and
- * CID font drivers, darkens stems as follows (if the
- * `no-stem-darkening' property isn't set):
+ * CID font drivers, darkens stems as follows (if the `no-stem-darkening`
+ * property isn't set):
*
- * {
+ * ```
* stem width <= 0.5px: darkening amount = 0.4px
* stem width = 1px: darkening amount = 0.275px
* stem width = 1.667px: darkening amount = 0.275px
* stem width >= 2.333px: darkening amount = 0px
- * }
+ * ```
*
* and piecewise linear in-between. At configuration time, these four
* control points can be set with the macro
- * `CFF_CONFIG_OPTION_DARKENING_PARAMETERS'; the CFF, Type~1, and CID
+ * `CFF_CONFIG_OPTION_DARKENING_PARAMETERS`; the CFF, Type~1, and CID
* drivers share these values. At runtime, the control points can be
- * changed using the `darkening-parameters' property, as the following
- * example demonstrates for the Type~1 driver.
- *
- * {
- * FT_Library library;
- * FT_Int darken_params[8] = { 500, 300, // x1, y1
- * 1000, 200, // x2, y2
- * 1500, 100, // x3, y3
- * 2000, 0 }; // x4, y4
- *
- *
- * FT_Init_FreeType( &library );
- *
- * FT_Property_Set( library, "type1",
- * "darkening-parameters", darken_params );
- * }
+ * changed using the `darkening-parameters` property (see the example
+ * below that demonstrates this for the Type~1 driver).
*
* The x~values give the stem width, and the y~values the darkening
* amount. The unit is 1000th of pixels. All coordinate values must be
- * positive; the x~values must be monotonically increasing; the
- * y~values must be monotonically decreasing and smaller than or
- * equal to 500 (corresponding to half a pixel); the slope of each
- * linear piece must be shallower than -1 (e.g., -.4).
+ * positive; the x~values must be monotonically increasing; the y~values
+ * must be monotonically decreasing and smaller than or equal to 500
+ * (corresponding to half a pixel); the slope of each linear piece must
+ * be shallower than -1 (e.g., -.4).
*
* The auto-hinter provides this property, too, as an experimental
* feature. See @no-stem-darkening for more.
@@ -522,21 +508,36 @@ FT_BEGIN_HEADER
* @note:
* This property can be used with @FT_Property_Get also.
*
- * This property can be set via the `FREETYPE_PROPERTIES' environment
+ * This property can be set via the `FREETYPE_PROPERTIES` environment
* variable, using eight comma-separated integers without spaces. Here
- * the above example, using `\' to break the line for readability.
+ * the above example, using `\` to break the line for readability.
*
- * {
+ * ```
* FREETYPE_PROPERTIES=\
* type1:darkening-parameters=500,300,1000,200,1500,100,2000,0
- * }
+ * ```
+ *
+ * @example:
+ * ```
+ * FT_Library library;
+ * FT_Int darken_params[8] = { 500, 300, // x1, y1
+ * 1000, 200, // x2, y2
+ * 1500, 100, // x3, y3
+ * 2000, 0 }; // x4, y4
+ *
+ *
+ * FT_Init_FreeType( &library );
+ *
+ * FT_Property_Set( library, "type1",
+ * "darkening-parameters", darken_params );
+ * ```
*
* @since:
- * 2.5.1 (for `cff' module)
+ * 2.5.1 (for 'cff' module)
*
- * 2.6.2 (for `autofitter' module)
+ * 2.6.2 (for 'autofitter' module)
*
- * 2.9 (for `type1' and `t1cid' modules)
+ * 2.9 (for 'type1' and 't1cid' modules)
*
*/
@@ -547,29 +548,29 @@ FT_BEGIN_HEADER
* random-seed
*
* @description:
- * By default, the seed value for the CFF `random' operator and the
- * similar `0 28 callothersubr pop' command for the Type~1 and CID
+ * By default, the seed value for the CFF 'random' operator and the
+ * similar '0 28 callothersubr pop' command for the Type~1 and CID
* drivers is set to a random value. However, mainly for debugging
- * purposes, it is often necessary to use a known value as a seed so
- * that the pseudo-random number sequences generated by `random' are
+ * purposes, it is often necessary to use a known value as a seed so that
+ * the pseudo-random number sequences generated by 'random' are
* repeatable.
*
- * The `random-seed' property does that. Its argument is a signed 32bit
+ * The `random-seed` property does that. Its argument is a signed 32bit
* integer; if the value is zero or negative, the seed given by the
- * `intitialRandomSeed' private DICT operator in a CFF file gets used
- * (or a default value if there is no such operator). If the value is
- * positive, use it instead of `initialRandomSeed', which is
- * consequently ignored.
+ * `intitialRandomSeed` private DICT operator in a CFF file gets used (or
+ * a default value if there is no such operator). If the value is
+ * positive, use it instead of `initialRandomSeed`, which is consequently
+ * ignored.
*
* @note:
- * This property can be set via the `FREETYPE_PROPERTIES' environment
+ * This property can be set via the `FREETYPE_PROPERTIES` environment
* variable. It can also be set per face using @FT_Face_Properties with
* @FT_PARAM_TAG_RANDOM_SEED.
*
* @since:
- * 2.8 (for `cff' module)
+ * 2.8 (for 'cff' module)
*
- * 2.9 (for `type1' and `t1cid' modules)
+ * 2.9 (for 'type1' and 't1cid' modules)
*
*/
@@ -580,21 +581,28 @@ FT_BEGIN_HEADER
* no-long-family-names
*
* @description:
- * If PCF_CONFIG_OPTION_LONG_FAMILY_NAMES is active while compiling
+ * If `PCF_CONFIG_OPTION_LONG_FAMILY_NAMES` is active while compiling
* FreeType, the PCF driver constructs long family names.
*
- * There are many PCF fonts just called `Fixed' which look completely
+ * There are many PCF fonts just called 'Fixed' which look completely
* different, and which have nothing to do with each other. When
- * selecting `Fixed' in KDE or Gnome one gets results that appear rather
- * random, the style changes often if one changes the size and one
- * cannot select some fonts at all. The improve this situation, the PCF
- * module prepends the foundry name (plus a space) to the family name.
- * It also checks whether there are `wide' characters; all put together,
- * family names like `Sony Fixed' or `Misc Fixed Wide' are constructed.
+ * selecting 'Fixed' in KDE or Gnome one gets results that appear rather
+ * random, the style changes often if one changes the size and one cannot
+ * select some fonts at all. The improve this situation, the PCF module
+ * prepends the foundry name (plus a space) to the family name. It also
+ * checks whether there are 'wide' characters; all put together, family
+ * names like 'Sony Fixed' or 'Misc Fixed Wide' are constructed.
+ *
+ * If `no-long-family-names` is set, this feature gets switched off.
*
- * If `no-long-family-names' is set, this feature gets switched off.
+ * @note:
+ * This property can be used with @FT_Property_Get also.
*
- * {
+ * This property can be set via the `FREETYPE_PROPERTIES` environment
+ * variable (using values 1 and 0 for 'on' and 'off', respectively).
+ *
+ * @example:
+ * ```
* FT_Library library;
* FT_Bool no_long_family_names = TRUE;
*
@@ -604,13 +612,7 @@ FT_BEGIN_HEADER
* FT_Property_Set( library, "pcf",
* "no-long-family-names",
* &no_long_family_names );
- * }
- *
- * @note:
- * This property can be used with @FT_Property_Get also.
- *
- * This property can be set via the `FREETYPE_PROPERTIES' environment
- * variable (using values 1 and 0 for `on' and `off', respectively).
+ * ```
*
* @since:
* 2.8
@@ -626,8 +628,8 @@ FT_BEGIN_HEADER
* A list of constants used for the @interpreter-version property to
* select the hinting engine for Truetype fonts.
*
- * The numeric value in the constant names represents the version
- * number as returned by the `GETINFO' bytecode instruction.
+ * The numeric value in the constant names represents the version number
+ * as returned by the 'GETINFO' bytecode instruction.
*
* @values:
* TT_INTERPRETER_VERSION_35 ::
@@ -638,38 +640,37 @@ FT_BEGIN_HEADER
* Version~38 corresponds to MS rasterizer v.1.9; it is roughly
* equivalent to the hinting provided by DirectWrite ClearType (as can
* be found, for example, in the Internet Explorer~9 running on
- * Windows~7). It is used in FreeType to select the `Infinality'
- * subpixel hinting code. The code may be removed in a future
- * version.
+ * Windows~7). It is used in FreeType to select the 'Infinality'
+ * subpixel hinting code. The code may be removed in a future version.
*
* TT_INTERPRETER_VERSION_40 ::
* Version~40 corresponds to MS rasterizer v.2.1; it is roughly
* equivalent to the hinting provided by DirectWrite ClearType (as can
* be found, for example, in Microsoft's Edge Browser on Windows~10).
- * It is used in FreeType to select the `minimal' subpixel hinting
+ * It is used in FreeType to select the 'minimal' subpixel hinting
* code, a stripped-down and higher performance version of the
- * `Infinality' code.
+ * 'Infinality' code.
*
* @note:
- * This property controls the behaviour of the bytecode interpreter
- * and thus how outlines get hinted. It does *not* control how glyph
- * get rasterized! In particular, it does not control subpixel color
+ * This property controls the behaviour of the bytecode interpreter and
+ * thus how outlines get hinted. It does **not** control how glyph get
+ * rasterized! In particular, it does not control subpixel color
* filtering.
*
* If FreeType has not been compiled with the configuration option
- * TT_CONFIG_OPTION_SUBPIXEL_HINTING, selecting version~38 or~40 causes
- * an `FT_Err_Unimplemented_Feature' error.
+ * `TT_CONFIG_OPTION_SUBPIXEL_HINTING`, selecting version~38 or~40 causes
+ * an `FT_Err_Unimplemented_Feature` error.
*
- * Depending on the graphics framework, Microsoft uses different
- * bytecode and rendering engines. As a consequence, the version
- * numbers returned by a call to the `GETINFO' bytecode instruction are
- * more convoluted than desired.
+ * Depending on the graphics framework, Microsoft uses different bytecode
+ * and rendering engines. As a consequence, the version numbers returned
+ * by a call to the 'GETINFO' bytecode instruction are more convoluted
+ * than desired.
*
- * Here are two tables that try to shed some light on the possible
- * values for the MS rasterizer engine, together with the additional
- * features introduced by it.
+ * Here are two tables that try to shed some light on the possible values
+ * for the MS rasterizer engine, together with the additional features
+ * introduced by it.
*
- * {
+ * ```
* GETINFO framework version feature
* -------------------------------------------------------------------
* 3 GDI (Win 3.1), v1.0 16-bit, first version
@@ -692,15 +693,15 @@ FT_BEGIN_HEADER
* 40 GDI+ (after Win 7), v2.1 Y-direction ClearType flag
* DWrite (Win 8) in GETINFO opcode,
* Gray ClearType
- * }
+ * ```
*
- * The `version' field gives a rough orientation only, since some
+ * The 'version' field gives a rough orientation only, since some
* applications provided certain features much earlier (as an example,
* Microsoft Reader used subpixel and Y-direction ClearType already in
* Windows 2000). Similarly, updates to a given framework might include
* improved hinting support.
*
- * {
+ * ```
* version sampling rendering comment
* x y x y
* --------------------------------------------------------------
@@ -710,38 +711,38 @@ FT_BEGIN_HEADER
* v1.9 high high color-filter gray Color ClearType
* v2.1 high normal gray B/W Gray ClearType
* v2.1 high high gray gray Gray ClearType
- * }
+ * ```
*
* Color and Gray ClearType are the two available variants of
- * `Y-direction ClearType', meaning grayscale rasterization along the
+ * 'Y-direction ClearType', meaning grayscale rasterization along the
* Y-direction; the name used in the TrueType specification for this
- * feature is `symmetric smoothing'. `Classic ClearType' is the
- * original algorithm used before introducing a modified version in
- * Win~XP. Another name for v1.6's grayscale rendering is `font
- * smoothing', and `Color ClearType' is sometimes also called `DWrite
- * ClearType'. To differentiate between today's Color ClearType and the
- * earlier ClearType variant with B/W rendering along the vertical axis,
- * the latter is sometimes called `GDI ClearType'.
- *
- * `Normal' and `high' sampling describe the (virtual) resolution to
- * access the rasterized outline after the hinting process. `Normal'
+ * feature is 'symmetric smoothing'. 'Classic ClearType' is the original
+ * algorithm used before introducing a modified version in Win~XP.
+ * Another name for v1.6's grayscale rendering is 'font smoothing', and
+ * 'Color ClearType' is sometimes also called 'DWrite ClearType'. To
+ * differentiate between today's Color ClearType and the earlier
+ * ClearType variant with B/W rendering along the vertical axis, the
+ * latter is sometimes called 'GDI ClearType'.
+ *
+ * 'Normal' and 'high' sampling describe the (virtual) resolution to
+ * access the rasterized outline after the hinting process. 'Normal'
* means 1 sample per grid line (i.e., B/W). In the current Microsoft
- * implementation, `high' means an extra virtual resolution of 16x16 (or
- * 16x1) grid lines per pixel for bytecode instructions like `MIRP'.
+ * implementation, 'high' means an extra virtual resolution of 16x16 (or
+ * 16x1) grid lines per pixel for bytecode instructions like 'MIRP'.
* After hinting, these 16 grid lines are mapped to 6x5 (or 6x1) grid
* lines for color filtering if Color ClearType is activated.
*
- * Note that `Gray ClearType' is essentially the same as v1.6's
- * grayscale rendering. However, the GETINFO instruction handles it
- * differently: v1.6 returns bit~12 (hinting for grayscale), while v2.1
- * returns bits~13 (hinting for ClearType), 18 (symmetrical smoothing),
- * and~19 (Gray ClearType). Also, this mode respects bits 2 and~3 for
- * the version~1 gasp table exclusively (like Color ClearType), while
- * v1.6 only respects the values of version~0 (bits 0 and~1).
+ * Note that 'Gray ClearType' is essentially the same as v1.6's grayscale
+ * rendering. However, the GETINFO instruction handles it differently:
+ * v1.6 returns bit~12 (hinting for grayscale), while v2.1 returns
+ * bits~13 (hinting for ClearType), 18 (symmetrical smoothing), and~19
+ * (Gray ClearType). Also, this mode respects bits 2 and~3 for the
+ * version~1 gasp table exclusively (like Color ClearType), while v1.6
+ * only respects the values of version~0 (bits 0 and~1).
*
- * Keep in mind that the features of the above interpreter versions
- * might not map exactly to FreeType features or behavior because it is
- * a fundamentally different library with different internals.
+ * Keep in mind that the features of the above interpreter versions might
+ * not map exactly to FreeType features or behavior because it is a
+ * fundamentally different library with different internals.
*
*/
#define TT_INTERPRETER_VERSION_35 35
@@ -755,33 +756,40 @@ FT_BEGIN_HEADER
* interpreter-version
*
* @description:
- * Currently, three versions are available, two representing the
- * bytecode interpreter with subpixel hinting support (old `Infinality'
- * code and new stripped-down and higher performance `minimal' code) and
- * one without, respectively. The default is subpixel support if
- * TT_CONFIG_OPTION_SUBPIXEL_HINTING is defined, and no subpixel support
- * otherwise (since it isn't available then).
+ * Currently, three versions are available, two representing the bytecode
+ * interpreter with subpixel hinting support (old 'Infinality' code and
+ * new stripped-down and higher performance 'minimal' code) and one
+ * without, respectively. The default is subpixel support if
+ * `TT_CONFIG_OPTION_SUBPIXEL_HINTING` is defined, and no subpixel
+ * support otherwise (since it isn't available then).
*
* If subpixel hinting is on, many TrueType bytecode instructions behave
- * differently compared to B/W or grayscale rendering (except if `native
+ * differently compared to B/W or grayscale rendering (except if 'native
* ClearType' is selected by the font). Microsoft's main idea is to
* render at a much increased horizontal resolution, then sampling down
* the created output to subpixel precision. However, many older fonts
- * are not suited to this and must be specially taken care of by
- * applying (hardcoded) tweaks in Microsoft's interpreter.
+ * are not suited to this and must be specially taken care of by applying
+ * (hardcoded) tweaks in Microsoft's interpreter.
*
* Details on subpixel hinting and some of the necessary tweaks can be
* found in Greg Hitchcock's whitepaper at
- * `https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx'.
- * Note that FreeType currently doesn't really `subpixel hint' (6x1, 6x2,
+ * 'https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx'.
+ * Note that FreeType currently doesn't really 'subpixel hint' (6x1, 6x2,
* or 6x5 supersampling) like discussed in the paper. Depending on the
* chosen interpreter, it simply ignores instructions on vertical stems
* to arrive at very similar results.
*
+ * @note:
+ * This property can be used with @FT_Property_Get also.
+ *
+ * This property can be set via the `FREETYPE_PROPERTIES` environment
+ * variable (using values '35', '38', or '40').
+ *
+ * @example:
* The following example code demonstrates how to deactivate subpixel
* hinting (omitting the error handling).
*
- * {
+ * ```
* FT_Library library;
* FT_Face face;
* FT_UInt interpreter_version = TT_INTERPRETER_VERSION_35;
@@ -792,13 +800,7 @@ FT_BEGIN_HEADER
* FT_Property_Set( library, "truetype",
* "interpreter-version",
* &interpreter_version );
- * }
- *
- * @note:
- * This property can be used with @FT_Property_Get also.
- *
- * This property can be set via the `FREETYPE_PROPERTIES' environment
- * variable (using values `35', `38', or `40').
+ * ```
*
* @since:
* 2.5
@@ -811,7 +813,7 @@ FT_BEGIN_HEADER
* glyph-to-script-map
*
* @description:
- * *Experimental* *only*
+ * **Experimental only**
*
* The auto-hinter provides various script modules to hint glyphs.
* Examples of supported scripts are Latin or CJK. Before a glyph is
@@ -819,25 +821,26 @@ FT_BEGIN_HEADER
* the script is then determined based on Unicode character ranges, see
* below.
*
- * OpenType fonts, however, often provide much more glyphs than
- * character codes (small caps, superscripts, ligatures, swashes, etc.),
- * to be controlled by so-called `features'. Handling OpenType features
- * can be quite complicated and thus needs a separate library on top of
+ * OpenType fonts, however, often provide much more glyphs than character
+ * codes (small caps, superscripts, ligatures, swashes, etc.), to be
+ * controlled by so-called 'features'. Handling OpenType features can be
+ * quite complicated and thus needs a separate library on top of
* FreeType.
*
* The mapping between glyph indices and scripts (in the auto-hinter
- * sense, see the @FT_AUTOHINTER_SCRIPT_XXX values) is stored as an
- * array with `num_glyphs' elements, as found in the font's @FT_Face
- * structure. The `glyph-to-script-map' property returns a pointer to
- * this array, which can be modified as needed. Note that the
- * modification should happen before the first glyph gets processed by
- * the auto-hinter so that the global analysis of the font shapes
- * actually uses the modified mapping.
- *
- * The following example code demonstrates how to access it (omitting
- * the error handling).
- *
- * {
+ * sense, see the @FT_AUTOHINTER_SCRIPT_XXX values) is stored as an array
+ * with `num_glyphs` elements, as found in the font's @FT_Face structure.
+ * The `glyph-to-script-map` property returns a pointer to this array,
+ * which can be modified as needed. Note that the modification should
+ * happen before the first glyph gets processed by the auto-hinter so
+ * that the global analysis of the font shapes actually uses the modified
+ * mapping.
+ *
+ * @example:
+ * The following example code demonstrates how to access it (omitting the
+ * error handling).
+ *
+ * ```
* FT_Library library;
* FT_Face face;
* FT_Prop_GlyphToScriptMap prop;
@@ -854,7 +857,7 @@ FT_BEGIN_HEADER
* // adjust `prop.map' as needed right here
*
* FT_Load_Glyph( face, ..., FT_LOAD_FORCE_AUTOHINT );
- * }
+ * ```
*
* @since:
* 2.4.11
@@ -868,7 +871,7 @@ FT_BEGIN_HEADER
* FT_AUTOHINTER_SCRIPT_XXX
*
* @description:
- * *Experimental* *only*
+ * **Experimental only**
*
* A list of constants used for the @glyph-to-script-map property to
* specify the script submodule the auto-hinter should use for hinting a
@@ -879,14 +882,14 @@ FT_BEGIN_HEADER
* Don't auto-hint this glyph.
*
* FT_AUTOHINTER_SCRIPT_LATIN ::
- * Apply the latin auto-hinter. For the auto-hinter, `latin' is a
- * very broad term, including Cyrillic and Greek also since characters
- * from those scripts share the same design constraints.
+ * Apply the latin auto-hinter. For the auto-hinter, 'latin' is a very
+ * broad term, including Cyrillic and Greek also since characters from
+ * those scripts share the same design constraints.
*
* By default, characters from the following Unicode ranges are
* assigned to this submodule.
*
- * {
+ * ```
* U+0020 - U+007F // Basic Latin (no control characters)
* U+00A0 - U+00FF // Latin-1 Supplement (no control characters)
* U+0100 - U+017F // Latin Extended-A
@@ -915,7 +918,7 @@ FT_BEGIN_HEADER
* U+FB00 - U+FB06 // Alphab. Present. Forms (Latin Ligatures)
* U+1D400 - U+1D7FF // Mathematical Alphanumeric Symbols
* U+1F100 - U+1F1FF // Enclosed Alphanumeric Supplement
- * }
+ * ```
*
* FT_AUTOHINTER_SCRIPT_CJK ::
* Apply the CJK auto-hinter, covering Chinese, Japanese, Korean, old
@@ -924,7 +927,7 @@ FT_BEGIN_HEADER
* By default, characters from the following Unicode ranges are
* assigned to this submodule.
*
- * {
+ * ```
* U+1100 - U+11FF // Hangul Jamo
* U+2E80 - U+2EFF // CJK Radicals Supplement
* U+2F00 - U+2FDF // Kangxi Radicals
@@ -957,7 +960,7 @@ FT_BEGIN_HEADER
* U+2A700 - U+2B73F // CJK Unified Ideographs Extension C
* U+2B740 - U+2B81F // CJK Unified Ideographs Extension D
* U+2F800 - U+2FA1F // CJK Compatibility Ideographs Supplement
- * }
+ * ```
*
* FT_AUTOHINTER_SCRIPT_INDIC ::
* Apply the indic auto-hinter, covering all major scripts from the
@@ -967,7 +970,7 @@ FT_BEGIN_HEADER
* By default, characters from the following Unicode ranges are
* assigned to this submodule.
*
- * {
+ * ```
* U+0900 - U+0DFF // Indic Range
* U+0F00 - U+0FFF // Tibetan
* U+1900 - U+194F // Limbu
@@ -975,7 +978,7 @@ FT_BEGIN_HEADER
* U+A800 - U+A82F // Syloti Nagri
* U+ABC0 - U+ABFF // Meetei Mayek
* U+11800 - U+118DF // Sharada
- * }
+ * ```
*
* Note that currently Indic support is rudimentary only, missing blue
* zone support.
@@ -996,7 +999,7 @@ FT_BEGIN_HEADER
* FT_Prop_GlyphToScriptMap
*
* @description:
- * *Experimental* *only*
+ * **Experimental only**
*
* The data exchange structure for the @glyph-to-script-map property.
*
@@ -1018,36 +1021,36 @@ FT_BEGIN_HEADER
* fallback-script
*
* @description:
- * *Experimental* *only*
- *
- * If no auto-hinter script module can be assigned to a glyph, a
- * fallback script gets assigned to it (see also the
- * @glyph-to-script-map property). By default, this is
- * @FT_AUTOHINTER_SCRIPT_CJK. Using the `fallback-script' property,
- * this fallback value can be changed.
- *
- * {
- * FT_Library library;
- * FT_UInt fallback_script = FT_AUTOHINTER_SCRIPT_NONE;
- *
- *
- * FT_Init_FreeType( &library );
+ * **Experimental only**
*
- * FT_Property_Set( library, "autofitter",
- * "fallback-script", &fallback_script );
- * }
+ * If no auto-hinter script module can be assigned to a glyph, a fallback
+ * script gets assigned to it (see also the @glyph-to-script-map
+ * property). By default, this is @FT_AUTOHINTER_SCRIPT_CJK. Using the
+ * `fallback-script` property, this fallback value can be changed.
*
* @note:
* This property can be used with @FT_Property_Get also.
*
* It's important to use the right timing for changing this value: The
- * creation of the glyph-to-script map that eventually uses the
- * fallback script value gets triggered either by setting or reading a
+ * creation of the glyph-to-script map that eventually uses the fallback
+ * script value gets triggered either by setting or reading a
* face-specific property like @glyph-to-script-map, or by auto-hinting
* any glyph from that face. In particular, if you have already created
* an @FT_Face structure but not loaded any glyph (using the
* auto-hinter), a change of the fallback script will affect this face.
*
+ * @example:
+ * ```
+ * FT_Library library;
+ * FT_UInt fallback_script = FT_AUTOHINTER_SCRIPT_NONE;
+ *
+ *
+ * FT_Init_FreeType( &library );
+ *
+ * FT_Property_Set( library, "autofitter",
+ * "fallback-script", &fallback_script );
+ * ```
+ *
* @since:
* 2.4.11
*
@@ -1060,42 +1063,43 @@ FT_BEGIN_HEADER
* default-script
*
* @description:
- * *Experimental* *only*
+ * **Experimental only**
*
- * If FreeType gets compiled with FT_CONFIG_OPTION_USE_HARFBUZZ to make
- * the HarfBuzz library access OpenType features for getting better
- * glyph coverages, this property sets the (auto-fitter) script to be
- * used for the default (OpenType) script data of a font's GSUB table.
- * Features for the default script are intended for all scripts not
- * explicitly handled in GSUB; an example is a `dlig' feature,
- * containing the combination of the characters `T', `E', and `L' to
- * form a `TEL' ligature.
+ * If FreeType gets compiled with `FT_CONFIG_OPTION_USE_HARFBUZZ` to make
+ * the HarfBuzz library access OpenType features for getting better glyph
+ * coverages, this property sets the (auto-fitter) script to be used for
+ * the default (OpenType) script data of a font's GSUB table. Features
+ * for the default script are intended for all scripts not explicitly
+ * handled in GSUB; an example is a 'dlig' feature, containing the
+ * combination of the characters 'T', 'E', and 'L' to form a 'TEL'
+ * ligature.
*
* By default, this is @FT_AUTOHINTER_SCRIPT_LATIN. Using the
- * `default-script' property, this default value can be changed.
- *
- * {
- * FT_Library library;
- * FT_UInt default_script = FT_AUTOHINTER_SCRIPT_NONE;
- *
- *
- * FT_Init_FreeType( &library );
- *
- * FT_Property_Set( library, "autofitter",
- * "default-script", &default_script );
- * }
+ * `default-script` property, this default value can be changed.
*
* @note:
* This property can be used with @FT_Property_Get also.
*
* It's important to use the right timing for changing this value: The
- * creation of the glyph-to-script map that eventually uses the
- * default script value gets triggered either by setting or reading a
+ * creation of the glyph-to-script map that eventually uses the default
+ * script value gets triggered either by setting or reading a
* face-specific property like @glyph-to-script-map, or by auto-hinting
* any glyph from that face. In particular, if you have already created
* an @FT_Face structure but not loaded any glyph (using the
* auto-hinter), a change of the default script will affect this face.
*
+ * @example:
+ * ```
+ * FT_Library library;
+ * FT_UInt default_script = FT_AUTOHINTER_SCRIPT_NONE;
+ *
+ *
+ * FT_Init_FreeType( &library );
+ *
+ * FT_Property_Set( library, "autofitter",
+ * "default-script", &default_script );
+ * ```
+ *
* @since:
* 2.5.3
*
@@ -1108,13 +1112,20 @@ FT_BEGIN_HEADER
* increase-x-height
*
* @description:
- * For ppem values in the range 6~<= ppem <= `increase-x-height', round
- * up the font's x~height much more often than normally. If the value
- * is set to~0, which is the default, this feature is switched off. Use
+ * For ppem values in the range 6~<= ppem <= `increase-x-height`, round
+ * up the font's x~height much more often than normally. If the value is
+ * set to~0, which is the default, this feature is switched off. Use
* this property to improve the legibility of small font sizes if
* necessary.
*
- * {
+ * @note:
+ * This property can be used with @FT_Property_Get also.
+ *
+ * Set this value right after calling @FT_Set_Char_Size, but before
+ * loading any glyph (using the auto-hinter).
+ *
+ * @example:
+ * ```
* FT_Library library;
* FT_Face face;
* FT_Prop_IncreaseXHeight prop;
@@ -1129,13 +1140,7 @@ FT_BEGIN_HEADER
*
* FT_Property_Set( library, "autofitter",
* "increase-x-height", &prop );
- * }
- *
- * @note:
- * This property can be used with @FT_Property_Get also.
- *
- * Set this value right after calling @FT_Set_Char_Size, but before
- * loading any glyph (using the auto-hinter).
+ * ```
*
* @since:
* 2.4.11
@@ -1166,46 +1171,48 @@ FT_BEGIN_HEADER
* warping
*
* @description:
- * *Experimental* *only*
+ * **Experimental only**
*
- * If FreeType gets compiled with option AF_CONFIG_OPTION_USE_WARPER to
+ * If FreeType gets compiled with option `AF_CONFIG_OPTION_USE_WARPER` to
* activate the warp hinting code in the auto-hinter, this property
* switches warping on and off.
*
- * Warping only works in `normal' auto-hinting mode replacing it.
- * The idea of the code is to slightly scale and shift a glyph along
- * the non-hinted dimension (which is usually the horizontal axis) so
- * that as much of its segments are aligned (more or less) to the grid.
- * To find out a glyph's optimal scaling and shifting value, various
- * parameter combinations are tried and scored.
+ * Warping only works in 'normal' auto-hinting mode replacing it. The
+ * idea of the code is to slightly scale and shift a glyph along the
+ * non-hinted dimension (which is usually the horizontal axis) so that as
+ * much of its segments are aligned (more or less) to the grid. To find
+ * out a glyph's optimal scaling and shifting value, various parameter
+ * combinations are tried and scored.
*
- * By default, warping is off. The example below shows how to switch on
- * warping (omitting the error handling).
- *
- * {
- * FT_Library library;
- * FT_Bool warping = 1;
- *
- *
- * FT_Init_FreeType( &library );
- *
- * FT_Property_Set( library, "autofitter",
- * "warping", &warping );
- * }
+ * By default, warping is off.
*
* @note:
* This property can be used with @FT_Property_Get also.
*
- * This property can be set via the `FREETYPE_PROPERTIES' environment
- * variable (using values 1 and 0 for `on' and `off', respectively).
+ * This property can be set via the `FREETYPE_PROPERTIES` environment
+ * variable (using values 1 and 0 for 'on' and 'off', respectively).
*
* The warping code can also change advance widths. Have a look at the
- * `lsb_delta' and `rsb_delta' fields in the @FT_GlyphSlotRec structure
+ * `lsb_delta` and `rsb_delta` fields in the @FT_GlyphSlotRec structure
* for details on improving inter-glyph distances while rendering.
*
* Since warping is a global property of the auto-hinter it is best to
* change its value before rendering any face. Otherwise, you should
- * reload all faces that get auto-hinted in `normal' hinting mode.
+ * reload all faces that get auto-hinted in 'normal' hinting mode.
+ *
+ * @example:
+ * This example shows how to switch on warping (omitting the error
+ * handling).
+ *
+ * ```
+ * FT_Library library;
+ * FT_Bool warping = 1;
+ *
+ *
+ * FT_Init_FreeType( &library );
+ *
+ * FT_Property_Set( library, "autofitter", "warping", &warping );
+ * ```
*
* @since:
* 2.6
diff --git a/thirdparty/freetype/include/freetype/fterrdef.h b/thirdparty/freetype/include/freetype/fterrdef.h
index 8ffd346ca8..9bc7dc65e3 100644
--- a/thirdparty/freetype/include/freetype/fterrdef.h
+++ b/thirdparty/freetype/include/freetype/fterrdef.h
@@ -1,58 +1,57 @@
-/***************************************************************************/
-/* */
-/* fterrdef.h */
-/* */
-/* FreeType error codes (specification). */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * fterrdef.h
+ *
+ * FreeType error codes (specification).
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
- /*************************************************************************/
- /* */
- /* <Section> */
- /* error_code_values */
- /* */
- /* <Title> */
- /* Error Code Values */
- /* */
- /* <Abstract> */
- /* All possible error codes returned by FreeType functions. */
- /* */
- /* <Description> */
- /* The list below is taken verbatim from the file `fterrdef.h' */
- /* (loaded automatically by including `FT_FREETYPE_H'). The first */
- /* argument of the `FT_ERROR_DEF_' macro is the error label; by */
- /* default, the prefix `FT_Err_' gets added so that you get error */
- /* names like `FT_Err_Cannot_Open_Resource'. The second argument is */
- /* the error code, and the last argument an error string, which is not */
- /* used by FreeType. */
- /* */
- /* Within your application you should *only* use error names and */
- /* *never* its numeric values! The latter might (and actually do) */
- /* change in forthcoming FreeType versions. */
- /* */
- /* Macro `FT_NOERRORDEF_' defines `FT_Err_Ok', which is always zero. */
- /* See the `Error Enumerations' subsection how to automatically */
- /* generate a list of error strings. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * @section:
+ * error_code_values
+ *
+ * @title:
+ * Error Code Values
+ *
+ * @abstract:
+ * All possible error codes returned by FreeType functions.
+ *
+ * @description:
+ * The list below is taken verbatim from the file `fterrdef.h` (loaded
+ * automatically by including `FT_FREETYPE_H`). The first argument of the
+ * `FT_ERROR_DEF_` macro is the error label; by default, the prefix
+ * `FT_Err_` gets added so that you get error names like
+ * `FT_Err_Cannot_Open_Resource`. The second argument is the error code,
+ * and the last argument an error string, which is not used by FreeType.
+ *
+ * Within your application you should **only** use error names and
+ * **never** its numeric values! The latter might (and actually do)
+ * change in forthcoming FreeType versions.
+ *
+ * Macro `FT_NOERRORDEF_` defines `FT_Err_Ok`, which is always zero. See
+ * the 'Error Enumerations' subsection how to automatically generate a
+ * list of error strings.
+ *
+ */
- /*************************************************************************/
- /* */
- /* <Enum> */
- /* FT_Err_XXX */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_Err_XXX
+ *
+ */
/* generic errors */
diff --git a/thirdparty/freetype/include/freetype/fterrors.h b/thirdparty/freetype/include/freetype/fterrors.h
index f6ee5c24e2..58f5a3ead1 100644
--- a/thirdparty/freetype/include/freetype/fterrors.h
+++ b/thirdparty/freetype/include/freetype/fterrors.h
@@ -1,110 +1,120 @@
-/***************************************************************************/
-/* */
-/* fterrors.h */
-/* */
-/* FreeType error code handling (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* <Section> */
- /* error_enumerations */
- /* */
- /* <Title> */
- /* Error Enumerations */
- /* */
- /* <Abstract> */
- /* How to handle errors and error strings. */
- /* */
- /* <Description> */
- /* The header file `fterrors.h' (which is automatically included by */
- /* `freetype.h' defines the handling of FreeType's enumeration */
- /* constants. It can also be used to generate error message strings */
- /* with a small macro trick explained below. */
- /* */
- /* *Error* *Formats* */
- /* */
- /* The configuration macro FT_CONFIG_OPTION_USE_MODULE_ERRORS can be */
- /* defined in `ftoption.h' in order to make the higher byte indicate */
- /* the module where the error has happened (this is not compatible */
- /* with standard builds of FreeType~2, however). See the file */
- /* `ftmoderr.h' for more details. */
- /* */
- /* *Error* *Message* *Strings* */
- /* */
- /* Error definitions are set up with special macros that allow client */
- /* applications to build a table of error message strings. The */
- /* strings are not included in a normal build of FreeType~2 to save */
- /* space (most client applications do not use them). */
- /* */
- /* To do so, you have to define the following macros before including */
- /* this file. */
- /* */
- /* { */
- /* FT_ERROR_START_LIST */
- /* } */
- /* */
- /* This macro is called before anything else to define the start of */
- /* the error list. It is followed by several FT_ERROR_DEF calls. */
- /* */
- /* { */
- /* FT_ERROR_DEF( e, v, s ) */
- /* } */
- /* */
- /* This macro is called to define one single error. `e' is the error */
- /* code identifier (e.g., `Invalid_Argument'), `v' is the error's */
- /* numerical value, and `s' is the corresponding error string. */
- /* */
- /* { */
- /* FT_ERROR_END_LIST */
- /* } */
- /* */
- /* This macro ends the list. */
- /* */
- /* Additionally, you have to undefine `FTERRORS_H_' before #including */
- /* this file. */
- /* */
- /* Here is a simple example. */
- /* */
- /* { */
- /* #undef FTERRORS_H_ */
- /* #define FT_ERRORDEF( e, v, s ) { e, s }, */
- /* #define FT_ERROR_START_LIST { */
- /* #define FT_ERROR_END_LIST { 0, NULL } }; */
- /* */
- /* const struct */
- /* { */
- /* int err_code; */
- /* const char* err_msg; */
- /* } ft_errors[] = */
- /* */
- /* #include FT_ERRORS_H */
- /* } */
- /* */
- /* Note that `FT_Err_Ok' is _not_ defined with `FT_ERRORDEF' but with */
- /* `FT_NOERRORDEF'; it is always zero. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * fterrors.h
+ *
+ * FreeType error code handling (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * error_enumerations
+ *
+ * @title:
+ * Error Enumerations
+ *
+ * @abstract:
+ * How to handle errors and error strings.
+ *
+ * @description:
+ * The header file `fterrors.h` (which is automatically included by
+ * `freetype.h` defines the handling of FreeType's enumeration
+ * constants. It can also be used to generate error message strings
+ * with a small macro trick explained below.
+ *
+ * **Error Formats**
+ *
+ * The configuration macro `FT_CONFIG_OPTION_USE_MODULE_ERRORS` can be
+ * defined in `ftoption.h` in order to make the higher byte indicate the
+ * module where the error has happened (this is not compatible with
+ * standard builds of FreeType~2, however). See the file `ftmoderr.h`
+ * for more details.
+ *
+ * **Error Message Strings**
+ *
+ * Error definitions are set up with special macros that allow client
+ * applications to build a table of error message strings. The strings
+ * are not included in a normal build of FreeType~2 to save space (most
+ * client applications do not use them).
+ *
+ * To do so, you have to define the following macros before including
+ * this file.
+ *
+ * ```
+ * FT_ERROR_START_LIST
+ * ```
+ *
+ * This macro is called before anything else to define the start of the
+ * error list. It is followed by several `FT_ERROR_DEF` calls.
+ *
+ * ```
+ * FT_ERROR_DEF( e, v, s )
+ * ```
+ *
+ * This macro is called to define one single error. 'e' is the error
+ * code identifier (e.g., `Invalid_Argument`), 'v' is the error's
+ * numerical value, and 's' is the corresponding error string.
+ *
+ * ```
+ * FT_ERROR_END_LIST
+ * ```
+ *
+ * This macro ends the list.
+ *
+ * Additionally, you have to undefine `FTERRORS_H_` before #including
+ * this file.
+ *
+ * Here is a simple example.
+ *
+ * ```
+ * #undef FTERRORS_H_
+ * #define FT_ERRORDEF( e, v, s ) { e, s },
+ * #define FT_ERROR_START_LIST {
+ * #define FT_ERROR_END_LIST { 0, NULL } };
+ *
+ * const struct
+ * {
+ * int err_code;
+ * const char* err_msg;
+ * } ft_errors[] =
+ *
+ * #include FT_ERRORS_H
+ * ```
+ *
+ * An alternative to using an array is a switch statement.
+ *
+ * ```
+ * #undef FTERRORS_H_
+ * #define FT_ERROR_START_LIST switch ( error_code ) {
+ * #define FT_ERRORDEF( e, v, s ) case v: return s;
+ * #define FT_ERROR_END_LIST }
+ * ```
+ *
+ * If you use `FT_CONFIG_OPTION_USE_MODULE_ERRORS`, `error_code` should
+ * be replaced with `FT_ERROR_BASE(error_code)` in the last example.
+ */
/* */
- /* In previous FreeType versions we used `__FTERRORS_H__'. However, */
+ /* In previous FreeType versions we used `__FTERRORS_H__`. However, */
/* using two successive underscores in a non-system symbol name */
/* violates the C (and C++) standard, so it was changed to the */
/* current form. In spite of this, we have to make */
/* */
+ /* ``` */
/* #undefine __FTERRORS_H__ */
+ /* ``` */
/* */
/* work for backward compatibility. */
/* */
@@ -130,7 +140,7 @@
/* FT_ERR_PREFIX is used as a prefix for error identifiers. */
- /* By default, we use `FT_Err_'. */
+ /* By default, we use `FT_Err_`. */
/* */
#ifndef FT_ERR_PREFIX
#define FT_ERR_PREFIX FT_Err_
@@ -158,6 +168,8 @@
/* */
#ifndef FT_ERRORDEF
+#define FT_INCLUDE_ERR_PROTOS
+
#define FT_ERRORDEF( e, v, s ) e = v,
#define FT_ERROR_START_LIST enum {
#define FT_ERROR_END_LIST FT_ERR_CAT( FT_ERR_PREFIX, Max ) };
@@ -220,6 +232,53 @@
#undef FT_ERR_PREFIX
#endif
+ /* FT_INCLUDE_ERR_PROTOS: Control if function prototypes should be */
+ /* included with `#include FT_ERRORS_H'. This is */
+ /* only true where `FT_ERRORDEF` is undefined. */
+ /* FT_ERR_PROTOS_DEFINED: Actual multiple-inclusion protection of */
+ /* `fterrors.h`. */
+#ifdef FT_INCLUDE_ERR_PROTOS
+#undef FT_INCLUDE_ERR_PROTOS
+
+#ifndef FT_ERR_PROTOS_DEFINED
+#define FT_ERR_PROTOS_DEFINED
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Error_String
+ *
+ * @description:
+ * Retrieve the description of a valid FreeType error code.
+ *
+ * @input:
+ * error_code ::
+ * A valid FreeType error code.
+ *
+ * @return:
+ * A C~string or `NULL`, if any error occurred.
+ *
+ * @note:
+ * FreeType has to be compiled with `FT_CONFIG_OPTION_ERROR_STRINGS` or
+ * `FT_DEBUG_LEVEL_ERROR` to get meaningful descriptions.
+ * 'error_string' will be `NULL` otherwise.
+ *
+ * Module identification will be ignored:
+ *
+ * ```c
+ * strcmp( FT_Error_String( FT_Err_Unknown_File_Format ),
+ * FT_Error_String( BDF_Err_Unknown_File_Format ) ) == 0;
+ * ```
+ */
+ FT_EXPORT( const char* )
+ FT_Error_String( FT_Error error_code );
+
+
+#endif /* FT_ERR_PROTOS_DEFINED */
+
+#endif /* FT_INCLUDE_ERR_PROTOS */
+
#endif /* !(FTERRORS_H_ && __FTERRORS_H__) */
diff --git a/thirdparty/freetype/include/freetype/ftfntfmt.h b/thirdparty/freetype/include/freetype/ftfntfmt.h
index cc86efac23..aae0b13264 100644
--- a/thirdparty/freetype/include/freetype/ftfntfmt.h
+++ b/thirdparty/freetype/include/freetype/ftfntfmt.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftfntfmt.h */
-/* */
-/* Support functions for font formats. */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftfntfmt.h
+ *
+ * Support functions for font formats.
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTFNTFMT_H_
@@ -32,49 +32,48 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* <Section> */
- /* font_formats */
- /* */
- /* <Title> */
- /* Font Formats */
- /* */
- /* <Abstract> */
- /* Getting the font format. */
- /* */
- /* <Description> */
- /* The single function in this section can be used to get the font */
- /* format. Note that this information is not needed normally; */
- /* however, there are special cases (like in PDF devices) where it is */
- /* important to differentiate, in spite of FreeType's uniform API. */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Get_Font_Format */
- /* */
- /* <Description> */
- /* Return a string describing the format of a given face. Possible */
- /* values are `TrueType', `Type~1', `BDF', `PCF', `Type~42', */
- /* `CID~Type~1', `CFF', `PFR', and `Windows~FNT'. */
- /* */
- /* The return value is suitable to be used as an X11 FONT_PROPERTY. */
- /* */
- /* <Input> */
- /* face :: */
- /* Input face handle. */
- /* */
- /* <Return> */
- /* Font format string. NULL in case of error. */
- /* */
- /* <Note> */
- /* A deprecated name for the same function is */
- /* `FT_Get_X11_Font_Format'. */
- /* */
+ /**************************************************************************
+ *
+ * @section:
+ * font_formats
+ *
+ * @title:
+ * Font Formats
+ *
+ * @abstract:
+ * Getting the font format.
+ *
+ * @description:
+ * The single function in this section can be used to get the font format.
+ * Note that this information is not needed normally; however, there are
+ * special cases (like in PDF devices) where it is important to
+ * differentiate, in spite of FreeType's uniform API.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Font_Format
+ *
+ * @description:
+ * Return a string describing the format of a given face. Possible values
+ * are 'TrueType', 'Type~1', 'BDF', 'PCF', 'Type~42', 'CID~Type~1', 'CFF',
+ * 'PFR', and 'Windows~FNT'.
+ *
+ * The return value is suitable to be used as an X11 FONT_PROPERTY.
+ *
+ * @input:
+ * face ::
+ * Input face handle.
+ *
+ * @return:
+ * Font format string. `NULL` in case of error.
+ *
+ * @note:
+ * A deprecated name for the same function is `FT_Get_X11_Font_Format`.
+ */
FT_EXPORT( const char* )
FT_Get_Font_Format( FT_Face face );
diff --git a/thirdparty/freetype/include/freetype/ftgasp.h b/thirdparty/freetype/include/freetype/ftgasp.h
index fc1248ff48..24673d8ce1 100644
--- a/thirdparty/freetype/include/freetype/ftgasp.h
+++ b/thirdparty/freetype/include/freetype/ftgasp.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftgasp.h */
-/* */
-/* Access of TrueType's `gasp' table (specification). */
-/* */
-/* Copyright 2007-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftgasp.h
+ *
+ * Access of TrueType's 'gasp' table (specification).
+ *
+ * Copyright (C) 2007-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTGASP_H_
@@ -32,7 +32,7 @@
FT_BEGIN_HEADER
- /***************************************************************************
+ /**************************************************************************
*
* @section:
* gasp_table
@@ -41,16 +41,16 @@ FT_BEGIN_HEADER
* Gasp Table
*
* @abstract:
- * Retrieving TrueType `gasp' table entries.
+ * Retrieving TrueType 'gasp' table entries.
*
* @description:
* The function @FT_Get_Gasp can be used to query a TrueType or OpenType
- * font for specific entries in its `gasp' table, if any. This is
- * mainly useful when implementing native TrueType hinting with the
- * bytecode interpreter to duplicate the Windows text rendering results.
+ * font for specific entries in its 'gasp' table, if any. This is mainly
+ * useful when implementing native TrueType hinting with the bytecode
+ * interpreter to duplicate the Windows text rendering results.
*/
- /*************************************************************************
+ /**************************************************************************
*
* @enum:
* FT_GASP_XXX
@@ -66,7 +66,7 @@ FT_BEGIN_HEADER
*
* FT_GASP_DO_GRIDFIT ::
* Grid-fitting and hinting should be performed at the specified ppem.
- * This *really* means TrueType bytecode interpretation. If this bit
+ * This **really** means TrueType bytecode interpretation. If this bit
* is not set, no hinting gets applied.
*
* FT_GASP_DO_GRAY ::
@@ -80,13 +80,13 @@ FT_BEGIN_HEADER
* Grid-fitting must be used with ClearType's symmetric smoothing.
*
* @note:
- * The bit-flags `FT_GASP_DO_GRIDFIT' and `FT_GASP_DO_GRAY' are to be
+ * The bit-flags `FT_GASP_DO_GRIDFIT` and `FT_GASP_DO_GRAY` are to be
* used for standard font rasterization only. Independently of that,
- * `FT_GASP_SYMMETRIC_SMOOTHING' and `FT_GASP_SYMMETRIC_GRIDFIT' are to
- * be used if ClearType is enabled (and `FT_GASP_DO_GRIDFIT' and
- * `FT_GASP_DO_GRAY' are consequently ignored).
+ * `FT_GASP_SYMMETRIC_SMOOTHING` and `FT_GASP_SYMMETRIC_GRIDFIT` are to
+ * be used if ClearType is enabled (and `FT_GASP_DO_GRIDFIT` and
+ * `FT_GASP_DO_GRAY` are consequently ignored).
*
- * `ClearType' is Microsoft's implementation of LCD rendering, partly
+ * 'ClearType' is Microsoft's implementation of LCD rendering, partly
* protected by patents.
*
* @since:
@@ -99,29 +99,31 @@ FT_BEGIN_HEADER
#define FT_GASP_SYMMETRIC_SMOOTHING 0x08
- /*************************************************************************
+ /**************************************************************************
*
- * @func:
+ * @function:
* FT_Get_Gasp
*
* @description:
* For a TrueType or OpenType font file, return the rasterizer behaviour
- * flags from the font's `gasp' table corresponding to a given
- * character pixel size.
+ * flags from the font's 'gasp' table corresponding to a given character
+ * pixel size.
*
* @input:
- * face :: The source face handle.
+ * face ::
+ * The source face handle.
*
- * ppem :: The vertical character pixel size.
+ * ppem ::
+ * The vertical character pixel size.
*
* @return:
* Bit flags (see @FT_GASP_XXX), or @FT_GASP_NO_TABLE if there is no
- * `gasp' table in the face.
+ * 'gasp' table in the face.
*
* @note:
* If you want to use the MM functionality of OpenType variation fonts
* (i.e., using @FT_Set_Var_Design_Coordinates and friends), call this
- * function *after* setting an instance since the return values can
+ * function **after** setting an instance since the return values can
* change.
*
* @since:
diff --git a/thirdparty/freetype/include/freetype/ftglyph.h b/thirdparty/freetype/include/freetype/ftglyph.h
index 5f3fc009cd..4067c2e62f 100644
--- a/thirdparty/freetype/include/freetype/ftglyph.h
+++ b/thirdparty/freetype/include/freetype/ftglyph.h
@@ -1,32 +1,32 @@
-/***************************************************************************/
-/* */
-/* ftglyph.h */
-/* */
-/* FreeType convenience functions to handle glyphs (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* This file contains the definition of several convenience functions */
- /* that can be used by client applications to easily retrieve glyph */
- /* bitmaps and outlines from a given face. */
- /* */
- /* These functions should be optional if you are writing a font server */
- /* or text layout engine on top of FreeType. However, they are pretty */
- /* handy for many other simple uses of the library. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * ftglyph.h
+ *
+ * FreeType convenience functions to handle glyphs (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * This file contains the definition of several convenience functions that
+ * can be used by client applications to easily retrieve glyph bitmaps and
+ * outlines from a given face.
+ *
+ * These functions should be optional if you are writing a font server or
+ * text layout engine on top of FreeType. However, they are pretty handy
+ * for many other simple uses of the library.
+ *
+ */
#ifndef FTGLYPH_H_
@@ -46,65 +46,70 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* <Section> */
- /* glyph_management */
- /* */
- /* <Title> */
- /* Glyph Management */
- /* */
- /* <Abstract> */
- /* Generic interface to manage individual glyph data. */
- /* */
- /* <Description> */
- /* This section contains definitions used to manage glyph data */
- /* through generic FT_Glyph objects. Each of them can contain a */
- /* bitmap, a vector outline, or even images in other formats. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * @section:
+ * glyph_management
+ *
+ * @title:
+ * Glyph Management
+ *
+ * @abstract:
+ * Generic interface to manage individual glyph data.
+ *
+ * @description:
+ * This section contains definitions used to manage glyph data through
+ * generic @FT_Glyph objects. Each of them can contain a bitmap,
+ * a vector outline, or even images in other formats. These objects are
+ * detached from @FT_Face, contrary to @FT_GlyphSlot.
+ *
+ */
/* forward declaration to a private type */
typedef struct FT_Glyph_Class_ FT_Glyph_Class;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_Glyph */
- /* */
- /* <Description> */
- /* Handle to an object used to model generic glyph images. It is a */
- /* pointer to the @FT_GlyphRec structure and can contain a glyph */
- /* bitmap or pointer. */
- /* */
- /* <Note> */
- /* Glyph objects are not owned by the library. You must thus release */
- /* them manually (through @FT_Done_Glyph) _before_ calling */
- /* @FT_Done_FreeType. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Glyph
+ *
+ * @description:
+ * Handle to an object used to model generic glyph images. It is a
+ * pointer to the @FT_GlyphRec structure and can contain a glyph bitmap
+ * or pointer.
+ *
+ * @note:
+ * Glyph objects are not owned by the library. You must thus release
+ * them manually (through @FT_Done_Glyph) _before_ calling
+ * @FT_Done_FreeType.
+ */
typedef struct FT_GlyphRec_* FT_Glyph;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_GlyphRec */
- /* */
- /* <Description> */
- /* The root glyph structure contains a given glyph image plus its */
- /* advance width in 16.16 fixed-point format. */
- /* */
- /* <Fields> */
- /* library :: A handle to the FreeType library object. */
- /* */
- /* clazz :: A pointer to the glyph's class. Private. */
- /* */
- /* format :: The format of the glyph's image. */
- /* */
- /* advance :: A 16.16 vector that gives the glyph's advance width. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_GlyphRec
+ *
+ * @description:
+ * The root glyph structure contains a given glyph image plus its advance
+ * width in 16.16 fixed-point format.
+ *
+ * @fields:
+ * library ::
+ * A handle to the FreeType library object.
+ *
+ * clazz ::
+ * A pointer to the glyph's class. Private.
+ *
+ * format ::
+ * The format of the glyph's image.
+ *
+ * advance ::
+ * A 16.16 vector that gives the glyph's advance width.
+ */
typedef struct FT_GlyphRec_
{
FT_Library library;
@@ -115,48 +120,51 @@ FT_BEGIN_HEADER
} FT_GlyphRec;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_BitmapGlyph */
- /* */
- /* <Description> */
- /* A handle to an object used to model a bitmap glyph image. This is */
- /* a sub-class of @FT_Glyph, and a pointer to @FT_BitmapGlyphRec. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_BitmapGlyph
+ *
+ * @description:
+ * A handle to an object used to model a bitmap glyph image. This is a
+ * sub-class of @FT_Glyph, and a pointer to @FT_BitmapGlyphRec.
+ */
typedef struct FT_BitmapGlyphRec_* FT_BitmapGlyph;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_BitmapGlyphRec */
- /* */
- /* <Description> */
- /* A structure used for bitmap glyph images. This really is a */
- /* `sub-class' of @FT_GlyphRec. */
- /* */
- /* <Fields> */
- /* root :: The root @FT_Glyph fields. */
- /* */
- /* left :: The left-side bearing, i.e., the horizontal distance */
- /* from the current pen position to the left border of the */
- /* glyph bitmap. */
- /* */
- /* top :: The top-side bearing, i.e., the vertical distance from */
- /* the current pen position to the top border of the glyph */
- /* bitmap. This distance is positive for upwards~y! */
- /* */
- /* bitmap :: A descriptor for the bitmap. */
- /* */
- /* <Note> */
- /* You can typecast an @FT_Glyph to @FT_BitmapGlyph if you have */
- /* `glyph->format == FT_GLYPH_FORMAT_BITMAP'. This lets you access */
- /* the bitmap's contents easily. */
- /* */
- /* The corresponding pixel buffer is always owned by @FT_BitmapGlyph */
- /* and is thus created and destroyed with it. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_BitmapGlyphRec
+ *
+ * @description:
+ * A structure used for bitmap glyph images. This really is a
+ * 'sub-class' of @FT_GlyphRec.
+ *
+ * @fields:
+ * root ::
+ * The root @FT_Glyph fields.
+ *
+ * left ::
+ * The left-side bearing, i.e., the horizontal distance from the
+ * current pen position to the left border of the glyph bitmap.
+ *
+ * top ::
+ * The top-side bearing, i.e., the vertical distance from the current
+ * pen position to the top border of the glyph bitmap. This distance
+ * is positive for upwards~y!
+ *
+ * bitmap ::
+ * A descriptor for the bitmap.
+ *
+ * @note:
+ * You can typecast an @FT_Glyph to @FT_BitmapGlyph if you have
+ * `glyph->format == FT_GLYPH_FORMAT_BITMAP`. This lets you access the
+ * bitmap's contents easily.
+ *
+ * The corresponding pixel buffer is always owned by @FT_BitmapGlyph and
+ * is thus created and destroyed with it.
+ */
typedef struct FT_BitmapGlyphRec_
{
FT_GlyphRec root;
@@ -167,44 +175,46 @@ FT_BEGIN_HEADER
} FT_BitmapGlyphRec;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_OutlineGlyph */
- /* */
- /* <Description> */
- /* A handle to an object used to model an outline glyph image. This */
- /* is a sub-class of @FT_Glyph, and a pointer to @FT_OutlineGlyphRec. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_OutlineGlyph
+ *
+ * @description:
+ * A handle to an object used to model an outline glyph image. This is a
+ * sub-class of @FT_Glyph, and a pointer to @FT_OutlineGlyphRec.
+ */
typedef struct FT_OutlineGlyphRec_* FT_OutlineGlyph;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_OutlineGlyphRec */
- /* */
- /* <Description> */
- /* A structure used for outline (vectorial) glyph images. This */
- /* really is a `sub-class' of @FT_GlyphRec. */
- /* */
- /* <Fields> */
- /* root :: The root @FT_Glyph fields. */
- /* */
- /* outline :: A descriptor for the outline. */
- /* */
- /* <Note> */
- /* You can typecast an @FT_Glyph to @FT_OutlineGlyph if you have */
- /* `glyph->format == FT_GLYPH_FORMAT_OUTLINE'. This lets you access */
- /* the outline's content easily. */
- /* */
- /* As the outline is extracted from a glyph slot, its coordinates are */
- /* expressed normally in 26.6 pixels, unless the flag */
- /* @FT_LOAD_NO_SCALE was used in @FT_Load_Glyph() or @FT_Load_Char(). */
- /* */
- /* The outline's tables are always owned by the object and are */
- /* destroyed with it. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_OutlineGlyphRec
+ *
+ * @description:
+ * A structure used for outline (vectorial) glyph images. This really is
+ * a 'sub-class' of @FT_GlyphRec.
+ *
+ * @fields:
+ * root ::
+ * The root @FT_Glyph fields.
+ *
+ * outline ::
+ * A descriptor for the outline.
+ *
+ * @note:
+ * You can typecast an @FT_Glyph to @FT_OutlineGlyph if you have
+ * `glyph->format == FT_GLYPH_FORMAT_OUTLINE`. This lets you access the
+ * outline's content easily.
+ *
+ * As the outline is extracted from a glyph slot, its coordinates are
+ * expressed normally in 26.6 pixels, unless the flag @FT_LOAD_NO_SCALE
+ * was used in @FT_Load_Glyph() or @FT_Load_Char().
+ *
+ * The outline's tables are always owned by the object and are destroyed
+ * with it.
+ */
typedef struct FT_OutlineGlyphRec_
{
FT_GlyphRec root;
@@ -213,113 +223,150 @@ FT_BEGIN_HEADER
} FT_OutlineGlyphRec;
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Get_Glyph */
- /* */
- /* <Description> */
- /* A function used to extract a glyph image from a slot. Note that */
- /* the created @FT_Glyph object must be released with @FT_Done_Glyph. */
- /* */
- /* <Input> */
- /* slot :: A handle to the source glyph slot. */
- /* */
- /* <Output> */
- /* aglyph :: A handle to the glyph object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* Because `*aglyph->advance.x' and '*aglyph->advance.y' are 16.16 */
- /* fixed-point numbers, `slot->advance.x' and `slot->advance.y' */
- /* (which are in 26.6 fixed-point format) must be in the range */
- /* ]-32768;32768[. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_New_Glyph
+ *
+ * @description:
+ * A function used to create a new empty glyph image. Note that the
+ * created @FT_Glyph object must be released with @FT_Done_Glyph.
+ *
+ * @input:
+ * library ::
+ * A handle to the FreeType library object.
+ *
+ * format ::
+ * The format of the glyph's image.
+ *
+ * @output:
+ * aglyph ::
+ * A handle to the glyph object.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @since:
+ * 2.10
+ */
+ FT_EXPORT( FT_Error )
+ FT_New_Glyph( FT_Library library,
+ FT_Glyph_Format format,
+ FT_Glyph *aglyph );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Glyph
+ *
+ * @description:
+ * A function used to extract a glyph image from a slot. Note that the
+ * created @FT_Glyph object must be released with @FT_Done_Glyph.
+ *
+ * @input:
+ * slot ::
+ * A handle to the source glyph slot.
+ *
+ * @output:
+ * aglyph ::
+ * A handle to the glyph object.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * Because `*aglyph->advance.x` and `*aglyph->advance.y` are 16.16
+ * fixed-point numbers, `slot->advance.x` and `slot->advance.y` (which
+ * are in 26.6 fixed-point format) must be in the range ]-32768;32768[.
+ */
FT_EXPORT( FT_Error )
FT_Get_Glyph( FT_GlyphSlot slot,
FT_Glyph *aglyph );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Glyph_Copy */
- /* */
- /* <Description> */
- /* A function used to copy a glyph image. Note that the created */
- /* @FT_Glyph object must be released with @FT_Done_Glyph. */
- /* */
- /* <Input> */
- /* source :: A handle to the source glyph object. */
- /* */
- /* <Output> */
- /* target :: A handle to the target glyph object. 0~in case of */
- /* error. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Glyph_Copy
+ *
+ * @description:
+ * A function used to copy a glyph image. Note that the created
+ * @FT_Glyph object must be released with @FT_Done_Glyph.
+ *
+ * @input:
+ * source ::
+ * A handle to the source glyph object.
+ *
+ * @output:
+ * target ::
+ * A handle to the target glyph object. 0~in case of error.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ */
FT_EXPORT( FT_Error )
FT_Glyph_Copy( FT_Glyph source,
FT_Glyph *target );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Glyph_Transform */
- /* */
- /* <Description> */
- /* Transform a glyph image if its format is scalable. */
- /* */
- /* <InOut> */
- /* glyph :: A handle to the target glyph object. */
- /* */
- /* <Input> */
- /* matrix :: A pointer to a 2x2 matrix to apply. */
- /* */
- /* delta :: A pointer to a 2d vector to apply. Coordinates are */
- /* expressed in 1/64th of a pixel. */
- /* */
- /* <Return> */
- /* FreeType error code (if not 0, the glyph format is not scalable). */
- /* */
- /* <Note> */
- /* The 2x2 transformation matrix is also applied to the glyph's */
- /* advance vector. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Glyph_Transform
+ *
+ * @description:
+ * Transform a glyph image if its format is scalable.
+ *
+ * @inout:
+ * glyph ::
+ * A handle to the target glyph object.
+ *
+ * @input:
+ * matrix ::
+ * A pointer to a 2x2 matrix to apply.
+ *
+ * delta ::
+ * A pointer to a 2d vector to apply. Coordinates are expressed in
+ * 1/64th of a pixel.
+ *
+ * @return:
+ * FreeType error code (if not 0, the glyph format is not scalable).
+ *
+ * @note:
+ * The 2x2 transformation matrix is also applied to the glyph's advance
+ * vector.
+ */
FT_EXPORT( FT_Error )
FT_Glyph_Transform( FT_Glyph glyph,
FT_Matrix* matrix,
FT_Vector* delta );
- /*************************************************************************/
- /* */
- /* <Enum> */
- /* FT_Glyph_BBox_Mode */
- /* */
- /* <Description> */
- /* The mode how the values of @FT_Glyph_Get_CBox are returned. */
- /* */
- /* <Values> */
- /* FT_GLYPH_BBOX_UNSCALED :: */
- /* Return unscaled font units. */
- /* */
- /* FT_GLYPH_BBOX_SUBPIXELS :: */
- /* Return unfitted 26.6 coordinates. */
- /* */
- /* FT_GLYPH_BBOX_GRIDFIT :: */
- /* Return grid-fitted 26.6 coordinates. */
- /* */
- /* FT_GLYPH_BBOX_TRUNCATE :: */
- /* Return coordinates in integer pixels. */
- /* */
- /* FT_GLYPH_BBOX_PIXELS :: */
- /* Return grid-fitted pixel coordinates. */
- /* */
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_Glyph_BBox_Mode
+ *
+ * @description:
+ * The mode how the values of @FT_Glyph_Get_CBox are returned.
+ *
+ * @values:
+ * FT_GLYPH_BBOX_UNSCALED ::
+ * Return unscaled font units.
+ *
+ * FT_GLYPH_BBOX_SUBPIXELS ::
+ * Return unfitted 26.6 coordinates.
+ *
+ * FT_GLYPH_BBOX_GRIDFIT ::
+ * Return grid-fitted 26.6 coordinates.
+ *
+ * FT_GLYPH_BBOX_TRUNCATE ::
+ * Return coordinates in integer pixels.
+ *
+ * FT_GLYPH_BBOX_PIXELS ::
+ * Return grid-fitted pixel coordinates.
+ */
typedef enum FT_Glyph_BBox_Mode_
{
FT_GLYPH_BBOX_UNSCALED = 0,
@@ -332,7 +379,7 @@ FT_BEGIN_HEADER
/* these constants are deprecated; use the corresponding */
- /* `FT_Glyph_BBox_Mode' values instead */
+ /* `FT_Glyph_BBox_Mode` values instead */
#define ft_glyph_bbox_unscaled FT_GLYPH_BBOX_UNSCALED
#define ft_glyph_bbox_subpixels FT_GLYPH_BBOX_SUBPIXELS
#define ft_glyph_bbox_gridfit FT_GLYPH_BBOX_GRIDFIT
@@ -340,187 +387,188 @@ FT_BEGIN_HEADER
#define ft_glyph_bbox_pixels FT_GLYPH_BBOX_PIXELS
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Glyph_Get_CBox */
- /* */
- /* <Description> */
- /* Return a glyph's `control box'. The control box encloses all the */
- /* outline's points, including Bezier control points. Though it */
- /* coincides with the exact bounding box for most glyphs, it can be */
- /* slightly larger in some situations (like when rotating an outline */
- /* that contains Bezier outside arcs). */
- /* */
- /* Computing the control box is very fast, while getting the bounding */
- /* box can take much more time as it needs to walk over all segments */
- /* and arcs in the outline. To get the latter, you can use the */
- /* `ftbbox' component, which is dedicated to this single task. */
- /* */
- /* <Input> */
- /* glyph :: A handle to the source glyph object. */
- /* */
- /* mode :: The mode that indicates how to interpret the returned */
- /* bounding box values. */
- /* */
- /* <Output> */
- /* acbox :: The glyph coordinate bounding box. Coordinates are */
- /* expressed in 1/64th of pixels if it is grid-fitted. */
- /* */
- /* <Note> */
- /* Coordinates are relative to the glyph origin, using the y~upwards */
- /* convention. */
- /* */
- /* If the glyph has been loaded with @FT_LOAD_NO_SCALE, `bbox_mode' */
- /* must be set to @FT_GLYPH_BBOX_UNSCALED to get unscaled font */
- /* units in 26.6 pixel format. The value @FT_GLYPH_BBOX_SUBPIXELS */
- /* is another name for this constant. */
- /* */
- /* If the font is tricky and the glyph has been loaded with */
- /* @FT_LOAD_NO_SCALE, the resulting CBox is meaningless. To get */
- /* reasonable values for the CBox it is necessary to load the glyph */
- /* at a large ppem value (so that the hinting instructions can */
- /* properly shift and scale the subglyphs), then extracting the CBox, */
- /* which can be eventually converted back to font units. */
- /* */
- /* Note that the maximum coordinates are exclusive, which means that */
- /* one can compute the width and height of the glyph image (be it in */
- /* integer or 26.6 pixels) as: */
- /* */
- /* { */
- /* width = bbox.xMax - bbox.xMin; */
- /* height = bbox.yMax - bbox.yMin; */
- /* } */
- /* */
- /* Note also that for 26.6 coordinates, if `bbox_mode' is set to */
- /* @FT_GLYPH_BBOX_GRIDFIT, the coordinates will also be grid-fitted, */
- /* which corresponds to: */
- /* */
- /* { */
- /* bbox.xMin = FLOOR(bbox.xMin); */
- /* bbox.yMin = FLOOR(bbox.yMin); */
- /* bbox.xMax = CEILING(bbox.xMax); */
- /* bbox.yMax = CEILING(bbox.yMax); */
- /* } */
- /* */
- /* To get the bbox in pixel coordinates, set `bbox_mode' to */
- /* @FT_GLYPH_BBOX_TRUNCATE. */
- /* */
- /* To get the bbox in grid-fitted pixel coordinates, set `bbox_mode' */
- /* to @FT_GLYPH_BBOX_PIXELS. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Glyph_Get_CBox
+ *
+ * @description:
+ * Return a glyph's 'control box'. The control box encloses all the
+ * outline's points, including Bezier control points. Though it
+ * coincides with the exact bounding box for most glyphs, it can be
+ * slightly larger in some situations (like when rotating an outline that
+ * contains Bezier outside arcs).
+ *
+ * Computing the control box is very fast, while getting the bounding box
+ * can take much more time as it needs to walk over all segments and arcs
+ * in the outline. To get the latter, you can use the 'ftbbox'
+ * component, which is dedicated to this single task.
+ *
+ * @input:
+ * glyph ::
+ * A handle to the source glyph object.
+ *
+ * mode ::
+ * The mode that indicates how to interpret the returned bounding box
+ * values.
+ *
+ * @output:
+ * acbox ::
+ * The glyph coordinate bounding box. Coordinates are expressed in
+ * 1/64th of pixels if it is grid-fitted.
+ *
+ * @note:
+ * Coordinates are relative to the glyph origin, using the y~upwards
+ * convention.
+ *
+ * If the glyph has been loaded with @FT_LOAD_NO_SCALE, `bbox_mode` must
+ * be set to @FT_GLYPH_BBOX_UNSCALED to get unscaled font units in 26.6
+ * pixel format. The value @FT_GLYPH_BBOX_SUBPIXELS is another name for
+ * this constant.
+ *
+ * If the font is tricky and the glyph has been loaded with
+ * @FT_LOAD_NO_SCALE, the resulting CBox is meaningless. To get
+ * reasonable values for the CBox it is necessary to load the glyph at a
+ * large ppem value (so that the hinting instructions can properly shift
+ * and scale the subglyphs), then extracting the CBox, which can be
+ * eventually converted back to font units.
+ *
+ * Note that the maximum coordinates are exclusive, which means that one
+ * can compute the width and height of the glyph image (be it in integer
+ * or 26.6 pixels) as:
+ *
+ * ```
+ * width = bbox.xMax - bbox.xMin;
+ * height = bbox.yMax - bbox.yMin;
+ * ```
+ *
+ * Note also that for 26.6 coordinates, if `bbox_mode` is set to
+ * @FT_GLYPH_BBOX_GRIDFIT, the coordinates will also be grid-fitted,
+ * which corresponds to:
+ *
+ * ```
+ * bbox.xMin = FLOOR(bbox.xMin);
+ * bbox.yMin = FLOOR(bbox.yMin);
+ * bbox.xMax = CEILING(bbox.xMax);
+ * bbox.yMax = CEILING(bbox.yMax);
+ * ```
+ *
+ * To get the bbox in pixel coordinates, set `bbox_mode` to
+ * @FT_GLYPH_BBOX_TRUNCATE.
+ *
+ * To get the bbox in grid-fitted pixel coordinates, set `bbox_mode` to
+ * @FT_GLYPH_BBOX_PIXELS.
+ */
FT_EXPORT( void )
FT_Glyph_Get_CBox( FT_Glyph glyph,
FT_UInt bbox_mode,
FT_BBox *acbox );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Glyph_To_Bitmap */
- /* */
- /* <Description> */
- /* Convert a given glyph object to a bitmap glyph object. */
- /* */
- /* <InOut> */
- /* the_glyph :: A pointer to a handle to the target glyph. */
- /* */
- /* <Input> */
- /* render_mode :: An enumeration that describes how the data is */
- /* rendered. */
- /* */
- /* origin :: A pointer to a vector used to translate the glyph */
- /* image before rendering. Can be~0 (if no */
- /* translation). The origin is expressed in */
- /* 26.6 pixels. */
- /* */
- /* destroy :: A boolean that indicates that the original glyph */
- /* image should be destroyed by this function. It is */
- /* never destroyed in case of error. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* This function does nothing if the glyph format isn't scalable. */
- /* */
- /* The glyph image is translated with the `origin' vector before */
- /* rendering. */
- /* */
- /* The first parameter is a pointer to an @FT_Glyph handle, that will */
- /* be _replaced_ by this function (with newly allocated data). */
- /* Typically, you would use (omitting error handling): */
- /* */
- /* */
- /* { */
- /* FT_Glyph glyph; */
- /* FT_BitmapGlyph glyph_bitmap; */
- /* */
- /* */
- /* // load glyph */
- /* error = FT_Load_Char( face, glyph_index, FT_LOAD_DEFAULT ); */
- /* */
- /* // extract glyph image */
- /* error = FT_Get_Glyph( face->glyph, &glyph ); */
- /* */
- /* // convert to a bitmap (default render mode + destroying old) */
- /* if ( glyph->format != FT_GLYPH_FORMAT_BITMAP ) */
- /* { */
- /* error = FT_Glyph_To_Bitmap( &glyph, FT_RENDER_MODE_NORMAL, */
- /* 0, 1 ); */
- /* if ( error ) // `glyph' unchanged */
- /* ... */
- /* } */
- /* */
- /* // access bitmap content by typecasting */
- /* glyph_bitmap = (FT_BitmapGlyph)glyph; */
- /* */
- /* // do funny stuff with it, like blitting/drawing */
- /* ... */
- /* */
- /* // discard glyph image (bitmap or not) */
- /* FT_Done_Glyph( glyph ); */
- /* } */
- /* */
- /* */
- /* Here another example, again without error handling: */
- /* */
- /* */
- /* { */
- /* FT_Glyph glyphs[MAX_GLYPHS] */
- /* */
- /* */
- /* ... */
- /* */
- /* for ( idx = 0; i < MAX_GLYPHS; i++ ) */
- /* error = FT_Load_Glyph( face, idx, FT_LOAD_DEFAULT ) || */
- /* FT_Get_Glyph ( face->glyph, &glyph[idx] ); */
- /* */
- /* ... */
- /* */
- /* for ( idx = 0; i < MAX_GLYPHS; i++ ) */
- /* { */
- /* FT_Glyph bitmap = glyphs[idx]; */
- /* */
- /* */
- /* ... */
- /* */
- /* // after this call, `bitmap' no longer points into */
- /* // the `glyphs' array (and the old value isn't destroyed) */
- /* FT_Glyph_To_Bitmap( &bitmap, FT_RENDER_MODE_MONO, 0, 0 ); */
- /* */
- /* ... */
- /* */
- /* FT_Done_Glyph( bitmap ); */
- /* } */
- /* */
- /* ... */
- /* */
- /* for ( idx = 0; i < MAX_GLYPHS; i++ ) */
- /* FT_Done_Glyph( glyphs[idx] ); */
- /* } */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Glyph_To_Bitmap
+ *
+ * @description:
+ * Convert a given glyph object to a bitmap glyph object.
+ *
+ * @inout:
+ * the_glyph ::
+ * A pointer to a handle to the target glyph.
+ *
+ * @input:
+ * render_mode ::
+ * An enumeration that describes how the data is rendered.
+ *
+ * origin ::
+ * A pointer to a vector used to translate the glyph image before
+ * rendering. Can be~0 (if no translation). The origin is expressed
+ * in 26.6 pixels.
+ *
+ * destroy ::
+ * A boolean that indicates that the original glyph image should be
+ * destroyed by this function. It is never destroyed in case of error.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * This function does nothing if the glyph format isn't scalable.
+ *
+ * The glyph image is translated with the `origin` vector before
+ * rendering.
+ *
+ * The first parameter is a pointer to an @FT_Glyph handle, that will be
+ * _replaced_ by this function (with newly allocated data). Typically,
+ * you would use (omitting error handling):
+ *
+ * ```
+ * FT_Glyph glyph;
+ * FT_BitmapGlyph glyph_bitmap;
+ *
+ *
+ * // load glyph
+ * error = FT_Load_Char( face, glyph_index, FT_LOAD_DEFAULT );
+ *
+ * // extract glyph image
+ * error = FT_Get_Glyph( face->glyph, &glyph );
+ *
+ * // convert to a bitmap (default render mode + destroying old)
+ * if ( glyph->format != FT_GLYPH_FORMAT_BITMAP )
+ * {
+ * error = FT_Glyph_To_Bitmap( &glyph, FT_RENDER_MODE_NORMAL,
+ * 0, 1 );
+ * if ( error ) // `glyph' unchanged
+ * ...
+ * }
+ *
+ * // access bitmap content by typecasting
+ * glyph_bitmap = (FT_BitmapGlyph)glyph;
+ *
+ * // do funny stuff with it, like blitting/drawing
+ * ...
+ *
+ * // discard glyph image (bitmap or not)
+ * FT_Done_Glyph( glyph );
+ * ```
+ *
+ * Here is another example, again without error handling:
+ *
+ * ```
+ * FT_Glyph glyphs[MAX_GLYPHS]
+ *
+ *
+ * ...
+ *
+ * for ( idx = 0; i < MAX_GLYPHS; i++ )
+ * error = FT_Load_Glyph( face, idx, FT_LOAD_DEFAULT ) ||
+ * FT_Get_Glyph ( face->glyph, &glyphs[idx] );
+ *
+ * ...
+ *
+ * for ( idx = 0; i < MAX_GLYPHS; i++ )
+ * {
+ * FT_Glyph bitmap = glyphs[idx];
+ *
+ *
+ * ...
+ *
+ * // after this call, `bitmap' no longer points into
+ * // the `glyphs' array (and the old value isn't destroyed)
+ * FT_Glyph_To_Bitmap( &bitmap, FT_RENDER_MODE_MONO, 0, 0 );
+ *
+ * ...
+ *
+ * FT_Done_Glyph( bitmap );
+ * }
+ *
+ * ...
+ *
+ * for ( idx = 0; i < MAX_GLYPHS; i++ )
+ * FT_Done_Glyph( glyphs[idx] );
+ * ```
+ */
FT_EXPORT( FT_Error )
FT_Glyph_To_Bitmap( FT_Glyph* the_glyph,
FT_Render_Mode render_mode,
@@ -528,17 +576,18 @@ FT_BEGIN_HEADER
FT_Bool destroy );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Done_Glyph */
- /* */
- /* <Description> */
- /* Destroy a given glyph. */
- /* */
- /* <Input> */
- /* glyph :: A handle to the target glyph object. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Done_Glyph
+ *
+ * @description:
+ * Destroy a given glyph.
+ *
+ * @input:
+ * glyph ::
+ * A handle to the target glyph object.
+ */
FT_EXPORT( void )
FT_Done_Glyph( FT_Glyph glyph );
@@ -547,54 +596,56 @@ FT_BEGIN_HEADER
/* other helpful functions */
- /*************************************************************************/
- /* */
- /* <Section> */
- /* computations */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Matrix_Multiply */
- /* */
- /* <Description> */
- /* Perform the matrix operation `b = a*b'. */
- /* */
- /* <Input> */
- /* a :: A pointer to matrix `a'. */
- /* */
- /* <InOut> */
- /* b :: A pointer to matrix `b'. */
- /* */
- /* <Note> */
- /* The result is undefined if either `a' or `b' is zero. */
- /* */
- /* Since the function uses wrap-around arithmetic, results become */
- /* meaningless if the arguments are very large. */
- /* */
+ /**************************************************************************
+ *
+ * @section:
+ * computations
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Matrix_Multiply
+ *
+ * @description:
+ * Perform the matrix operation `b = a*b`.
+ *
+ * @input:
+ * a ::
+ * A pointer to matrix `a`.
+ *
+ * @inout:
+ * b ::
+ * A pointer to matrix `b`.
+ *
+ * @note:
+ * The result is undefined if either `a` or `b` is zero.
+ *
+ * Since the function uses wrap-around arithmetic, results become
+ * meaningless if the arguments are very large.
+ */
FT_EXPORT( void )
FT_Matrix_Multiply( const FT_Matrix* a,
FT_Matrix* b );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Matrix_Invert */
- /* */
- /* <Description> */
- /* Invert a 2x2 matrix. Return an error if it can't be inverted. */
- /* */
- /* <InOut> */
- /* matrix :: A pointer to the target matrix. Remains untouched in */
- /* case of error. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Matrix_Invert
+ *
+ * @description:
+ * Invert a 2x2 matrix. Return an error if it can't be inverted.
+ *
+ * @inout:
+ * matrix ::
+ * A pointer to the target matrix. Remains untouched in case of error.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ */
FT_EXPORT( FT_Error )
FT_Matrix_Invert( FT_Matrix* matrix );
diff --git a/thirdparty/freetype/include/freetype/ftgxval.h b/thirdparty/freetype/include/freetype/ftgxval.h
index 8382d59954..b14f637c56 100644
--- a/thirdparty/freetype/include/freetype/ftgxval.h
+++ b/thirdparty/freetype/include/freetype/ftgxval.h
@@ -1,28 +1,28 @@
-/***************************************************************************/
-/* */
-/* ftgxval.h */
-/* */
-/* FreeType API for validating TrueTypeGX/AAT tables (specification). */
-/* */
-/* Copyright 2004-2018 by */
-/* Masatake YAMATO, Redhat K.K, */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-/***************************************************************************/
-/* */
-/* gxvalid is derived from both gxlayout module and otvalid module. */
-/* Development of gxlayout is supported by the Information-technology */
-/* Promotion Agency(IPA), Japan. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftgxval.h
+ *
+ * FreeType API for validating TrueTypeGX/AAT tables (specification).
+ *
+ * Copyright (C) 2004-2019 by
+ * Masatake YAMATO, Redhat K.K,
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+/****************************************************************************
+ *
+ * gxvalid is derived from both gxlayout module and otvalid module.
+ * Development of gxlayout is supported by the Information-technology
+ * Promotion Agency(IPA), Japan.
+ *
+ */
#ifndef FTGXVAL_H_
@@ -41,43 +41,43 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* <Section> */
- /* gx_validation */
- /* */
- /* <Title> */
- /* TrueTypeGX/AAT Validation */
- /* */
- /* <Abstract> */
- /* An API to validate TrueTypeGX/AAT tables. */
- /* */
- /* <Description> */
- /* This section contains the declaration of functions to validate */
- /* some TrueTypeGX tables (feat, mort, morx, bsln, just, kern, opbd, */
- /* trak, prop, lcar). */
- /* */
- /* <Order> */
- /* FT_TrueTypeGX_Validate */
- /* FT_TrueTypeGX_Free */
- /* */
- /* FT_ClassicKern_Validate */
- /* FT_ClassicKern_Free */
- /* */
- /* FT_VALIDATE_GX_LENGTH */
- /* FT_VALIDATE_GXXXX */
- /* FT_VALIDATE_CKERNXXX */
- /* */
- /*************************************************************************/
-
- /*************************************************************************/
- /* */
- /* */
- /* Warning: Use FT_VALIDATE_XXX to validate a table. */
- /* Following definitions are for gxvalid developers. */
- /* */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * @section:
+ * gx_validation
+ *
+ * @title:
+ * TrueTypeGX/AAT Validation
+ *
+ * @abstract:
+ * An API to validate TrueTypeGX/AAT tables.
+ *
+ * @description:
+ * This section contains the declaration of functions to validate some
+ * TrueTypeGX tables (feat, mort, morx, bsln, just, kern, opbd, trak,
+ * prop, lcar).
+ *
+ * @order:
+ * FT_TrueTypeGX_Validate
+ * FT_TrueTypeGX_Free
+ *
+ * FT_ClassicKern_Validate
+ * FT_ClassicKern_Free
+ *
+ * FT_VALIDATE_GX_LENGTH
+ * FT_VALIDATE_GXXXX
+ * FT_VALIDATE_CKERNXXX
+ *
+ */
+
+ /**************************************************************************
+ *
+ *
+ * Warning: Use `FT_VALIDATE_XXX` to validate a table.
+ * Following definitions are for gxvalid developers.
+ *
+ *
+ */
#define FT_VALIDATE_feat_INDEX 0
#define FT_VALIDATE_mort_INDEX 1
@@ -92,14 +92,14 @@ FT_BEGIN_HEADER
#define FT_VALIDATE_GX_LAST_INDEX FT_VALIDATE_lcar_INDEX
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_VALIDATE_GX_LENGTH
*
* @description:
* The number of tables checked in this module. Use it as a parameter
- * for the `table-length' argument of function @FT_TrueTypeGX_Validate.
+ * for the `table-length` argument of function @FT_TrueTypeGX_Validate.
*/
#define FT_VALIDATE_GX_LENGTH ( FT_VALIDATE_GX_LAST_INDEX + 1 )
@@ -112,51 +112,51 @@ FT_BEGIN_HEADER
( FT_VALIDATE_GX_START << FT_VALIDATE_##tag##_INDEX )
- /**********************************************************************
- *
- * @enum:
- * FT_VALIDATE_GXXXX
- *
- * @description:
- * A list of bit-field constants used with @FT_TrueTypeGX_Validate to
- * indicate which TrueTypeGX/AAT Type tables should be validated.
- *
- * @values:
- * FT_VALIDATE_feat ::
- * Validate `feat' table.
- *
- * FT_VALIDATE_mort ::
- * Validate `mort' table.
- *
- * FT_VALIDATE_morx ::
- * Validate `morx' table.
- *
- * FT_VALIDATE_bsln ::
- * Validate `bsln' table.
- *
- * FT_VALIDATE_just ::
- * Validate `just' table.
- *
- * FT_VALIDATE_kern ::
- * Validate `kern' table.
- *
- * FT_VALIDATE_opbd ::
- * Validate `opbd' table.
- *
- * FT_VALIDATE_trak ::
- * Validate `trak' table.
- *
- * FT_VALIDATE_prop ::
- * Validate `prop' table.
- *
- * FT_VALIDATE_lcar ::
- * Validate `lcar' table.
- *
- * FT_VALIDATE_GX ::
- * Validate all TrueTypeGX tables (feat, mort, morx, bsln, just, kern,
- * opbd, trak, prop and lcar).
- *
- */
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_VALIDATE_GXXXX
+ *
+ * @description:
+ * A list of bit-field constants used with @FT_TrueTypeGX_Validate to
+ * indicate which TrueTypeGX/AAT Type tables should be validated.
+ *
+ * @values:
+ * FT_VALIDATE_feat ::
+ * Validate 'feat' table.
+ *
+ * FT_VALIDATE_mort ::
+ * Validate 'mort' table.
+ *
+ * FT_VALIDATE_morx ::
+ * Validate 'morx' table.
+ *
+ * FT_VALIDATE_bsln ::
+ * Validate 'bsln' table.
+ *
+ * FT_VALIDATE_just ::
+ * Validate 'just' table.
+ *
+ * FT_VALIDATE_kern ::
+ * Validate 'kern' table.
+ *
+ * FT_VALIDATE_opbd ::
+ * Validate 'opbd' table.
+ *
+ * FT_VALIDATE_trak ::
+ * Validate 'trak' table.
+ *
+ * FT_VALIDATE_prop ::
+ * Validate 'prop' table.
+ *
+ * FT_VALIDATE_lcar ::
+ * Validate 'lcar' table.
+ *
+ * FT_VALIDATE_GX ::
+ * Validate all TrueTypeGX tables (feat, mort, morx, bsln, just, kern,
+ * opbd, trak, prop and lcar).
+ *
+ */
#define FT_VALIDATE_feat FT_VALIDATE_GX_BITFIELD( feat )
#define FT_VALIDATE_mort FT_VALIDATE_GX_BITFIELD( mort )
@@ -181,47 +181,47 @@ FT_BEGIN_HEADER
FT_VALIDATE_lcar )
- /**********************************************************************
- *
- * @function:
- * FT_TrueTypeGX_Validate
- *
- * @description:
- * Validate various TrueTypeGX tables to assure that all offsets and
- * indices are valid. The idea is that a higher-level library that
- * actually does the text layout can access those tables without
- * error checking (which can be quite time consuming).
- *
- * @input:
- * face ::
- * A handle to the input face.
- *
- * validation_flags ::
- * A bit field that specifies the tables to be validated. See
- * @FT_VALIDATE_GXXXX for possible values.
- *
- * table_length ::
- * The size of the `tables' array. Normally, @FT_VALIDATE_GX_LENGTH
- * should be passed.
- *
- * @output:
- * tables ::
- * The array where all validated sfnt tables are stored.
- * The array itself must be allocated by a client.
- *
- * @return:
- * FreeType error code. 0~means success.
- *
- * @note:
- * This function only works with TrueTypeGX fonts, returning an error
- * otherwise.
- *
- * After use, the application should deallocate the buffers pointed to by
- * each `tables' element, by calling @FT_TrueTypeGX_Free. A NULL value
- * indicates that the table either doesn't exist in the font, the
- * application hasn't asked for validation, or the validator doesn't have
- * the ability to validate the sfnt table.
- */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_TrueTypeGX_Validate
+ *
+ * @description:
+ * Validate various TrueTypeGX tables to assure that all offsets and
+ * indices are valid. The idea is that a higher-level library that
+ * actually does the text layout can access those tables without error
+ * checking (which can be quite time consuming).
+ *
+ * @input:
+ * face ::
+ * A handle to the input face.
+ *
+ * validation_flags ::
+ * A bit field that specifies the tables to be validated. See
+ * @FT_VALIDATE_GXXXX for possible values.
+ *
+ * table_length ::
+ * The size of the `tables` array. Normally, @FT_VALIDATE_GX_LENGTH
+ * should be passed.
+ *
+ * @output:
+ * tables ::
+ * The array where all validated sfnt tables are stored. The array
+ * itself must be allocated by a client.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * This function only works with TrueTypeGX fonts, returning an error
+ * otherwise.
+ *
+ * After use, the application should deallocate the buffers pointed to by
+ * each `tables` element, by calling @FT_TrueTypeGX_Free. A `NULL` value
+ * indicates that the table either doesn't exist in the font, the
+ * application hasn't asked for validation, or the validator doesn't have
+ * the ability to validate the sfnt table.
+ */
FT_EXPORT( FT_Error )
FT_TrueTypeGX_Validate( FT_Face face,
FT_UInt validation_flags,
@@ -229,119 +229,117 @@ FT_BEGIN_HEADER
FT_UInt table_length );
- /**********************************************************************
- *
- * @function:
- * FT_TrueTypeGX_Free
- *
- * @description:
- * Free the buffer allocated by TrueTypeGX validator.
- *
- * @input:
- * face ::
- * A handle to the input face.
- *
- * table ::
- * The pointer to the buffer allocated by
- * @FT_TrueTypeGX_Validate.
- *
- * @note:
- * This function must be used to free the buffer allocated by
- * @FT_TrueTypeGX_Validate only.
- */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_TrueTypeGX_Free
+ *
+ * @description:
+ * Free the buffer allocated by TrueTypeGX validator.
+ *
+ * @input:
+ * face ::
+ * A handle to the input face.
+ *
+ * table ::
+ * The pointer to the buffer allocated by @FT_TrueTypeGX_Validate.
+ *
+ * @note:
+ * This function must be used to free the buffer allocated by
+ * @FT_TrueTypeGX_Validate only.
+ */
FT_EXPORT( void )
FT_TrueTypeGX_Free( FT_Face face,
FT_Bytes table );
- /**********************************************************************
- *
- * @enum:
- * FT_VALIDATE_CKERNXXX
- *
- * @description:
- * A list of bit-field constants used with @FT_ClassicKern_Validate
- * to indicate the classic kern dialect or dialects. If the selected
- * type doesn't fit, @FT_ClassicKern_Validate regards the table as
- * invalid.
- *
- * @values:
- * FT_VALIDATE_MS ::
- * Handle the `kern' table as a classic Microsoft kern table.
- *
- * FT_VALIDATE_APPLE ::
- * Handle the `kern' table as a classic Apple kern table.
- *
- * FT_VALIDATE_CKERN ::
- * Handle the `kern' as either classic Apple or Microsoft kern table.
- */
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_VALIDATE_CKERNXXX
+ *
+ * @description:
+ * A list of bit-field constants used with @FT_ClassicKern_Validate to
+ * indicate the classic kern dialect or dialects. If the selected type
+ * doesn't fit, @FT_ClassicKern_Validate regards the table as invalid.
+ *
+ * @values:
+ * FT_VALIDATE_MS ::
+ * Handle the 'kern' table as a classic Microsoft kern table.
+ *
+ * FT_VALIDATE_APPLE ::
+ * Handle the 'kern' table as a classic Apple kern table.
+ *
+ * FT_VALIDATE_CKERN ::
+ * Handle the 'kern' as either classic Apple or Microsoft kern table.
+ */
#define FT_VALIDATE_MS ( FT_VALIDATE_GX_START << 0 )
#define FT_VALIDATE_APPLE ( FT_VALIDATE_GX_START << 1 )
#define FT_VALIDATE_CKERN ( FT_VALIDATE_MS | FT_VALIDATE_APPLE )
- /**********************************************************************
- *
- * @function:
- * FT_ClassicKern_Validate
- *
- * @description:
- * Validate classic (16-bit format) kern table to assure that the offsets
- * and indices are valid. The idea is that a higher-level library that
- * actually does the text layout can access those tables without error
- * checking (which can be quite time consuming).
- *
- * The `kern' table validator in @FT_TrueTypeGX_Validate deals with both
- * the new 32-bit format and the classic 16-bit format, while
- * FT_ClassicKern_Validate only supports the classic 16-bit format.
- *
- * @input:
- * face ::
- * A handle to the input face.
- *
- * validation_flags ::
- * A bit field that specifies the dialect to be validated. See
- * @FT_VALIDATE_CKERNXXX for possible values.
- *
- * @output:
- * ckern_table ::
- * A pointer to the kern table.
- *
- * @return:
- * FreeType error code. 0~means success.
- *
- * @note:
- * After use, the application should deallocate the buffers pointed to by
- * `ckern_table', by calling @FT_ClassicKern_Free. A NULL value
- * indicates that the table doesn't exist in the font.
- */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_ClassicKern_Validate
+ *
+ * @description:
+ * Validate classic (16-bit format) kern table to assure that the
+ * offsets and indices are valid. The idea is that a higher-level
+ * library that actually does the text layout can access those tables
+ * without error checking (which can be quite time consuming).
+ *
+ * The 'kern' table validator in @FT_TrueTypeGX_Validate deals with both
+ * the new 32-bit format and the classic 16-bit format, while
+ * FT_ClassicKern_Validate only supports the classic 16-bit format.
+ *
+ * @input:
+ * face ::
+ * A handle to the input face.
+ *
+ * validation_flags ::
+ * A bit field that specifies the dialect to be validated. See
+ * @FT_VALIDATE_CKERNXXX for possible values.
+ *
+ * @output:
+ * ckern_table ::
+ * A pointer to the kern table.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * After use, the application should deallocate the buffers pointed to by
+ * `ckern_table`, by calling @FT_ClassicKern_Free. A `NULL` value
+ * indicates that the table doesn't exist in the font.
+ */
FT_EXPORT( FT_Error )
FT_ClassicKern_Validate( FT_Face face,
FT_UInt validation_flags,
FT_Bytes *ckern_table );
- /**********************************************************************
- *
- * @function:
- * FT_ClassicKern_Free
- *
- * @description:
- * Free the buffer allocated by classic Kern validator.
- *
- * @input:
- * face ::
- * A handle to the input face.
- *
- * table ::
- * The pointer to the buffer that is allocated by
- * @FT_ClassicKern_Validate.
- *
- * @note:
- * This function must be used to free the buffer allocated by
- * @FT_ClassicKern_Validate only.
- */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_ClassicKern_Free
+ *
+ * @description:
+ * Free the buffer allocated by classic Kern validator.
+ *
+ * @input:
+ * face ::
+ * A handle to the input face.
+ *
+ * table ::
+ * The pointer to the buffer that is allocated by
+ * @FT_ClassicKern_Validate.
+ *
+ * @note:
+ * This function must be used to free the buffer allocated by
+ * @FT_ClassicKern_Validate only.
+ */
FT_EXPORT( void )
FT_ClassicKern_Free( FT_Face face,
FT_Bytes table );
diff --git a/thirdparty/freetype/include/freetype/ftgzip.h b/thirdparty/freetype/include/freetype/ftgzip.h
index db033da0ed..418c61228e 100644
--- a/thirdparty/freetype/include/freetype/ftgzip.h
+++ b/thirdparty/freetype/include/freetype/ftgzip.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftgzip.h */
-/* */
-/* Gzip-compressed stream support. */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftgzip.h
+ *
+ * Gzip-compressed stream support.
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTGZIP_H_
@@ -31,108 +31,108 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* <Section> */
- /* gzip */
- /* */
- /* <Title> */
- /* GZIP Streams */
- /* */
- /* <Abstract> */
- /* Using gzip-compressed font files. */
- /* */
- /* <Description> */
- /* This section contains the declaration of Gzip-specific functions. */
- /* */
- /*************************************************************************/
-
-
- /************************************************************************
- *
- * @function:
- * FT_Stream_OpenGzip
- *
- * @description:
- * Open a new stream to parse gzip-compressed font files. This is
- * mainly used to support the compressed `*.pcf.gz' fonts that come
- * with XFree86.
- *
- * @input:
- * stream ::
- * The target embedding stream.
- *
- * source ::
- * The source stream.
- *
- * @return:
- * FreeType error code. 0~means success.
- *
- * @note:
- * The source stream must be opened _before_ calling this function.
- *
- * Calling the internal function `FT_Stream_Close' on the new stream will
- * *not* call `FT_Stream_Close' on the source stream. None of the stream
- * objects will be released to the heap.
- *
- * The stream implementation is very basic and resets the decompression
- * process each time seeking backwards is needed within the stream.
- *
- * In certain builds of the library, gzip compression recognition is
- * automatically handled when calling @FT_New_Face or @FT_Open_Face.
- * This means that if no font driver is capable of handling the raw
- * compressed file, the library will try to open a gzipped stream from
- * it and re-open the face with it.
- *
- * This function may return `FT_Err_Unimplemented_Feature' if your build
- * of FreeType was not compiled with zlib support.
- */
+ /**************************************************************************
+ *
+ * @section:
+ * gzip
+ *
+ * @title:
+ * GZIP Streams
+ *
+ * @abstract:
+ * Using gzip-compressed font files.
+ *
+ * @description:
+ * This section contains the declaration of Gzip-specific functions.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Stream_OpenGzip
+ *
+ * @description:
+ * Open a new stream to parse gzip-compressed font files. This is mainly
+ * used to support the compressed `*.pcf.gz` fonts that come with
+ * XFree86.
+ *
+ * @input:
+ * stream ::
+ * The target embedding stream.
+ *
+ * source ::
+ * The source stream.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The source stream must be opened _before_ calling this function.
+ *
+ * Calling the internal function `FT_Stream_Close` on the new stream will
+ * **not** call `FT_Stream_Close` on the source stream. None of the
+ * stream objects will be released to the heap.
+ *
+ * The stream implementation is very basic and resets the decompression
+ * process each time seeking backwards is needed within the stream.
+ *
+ * In certain builds of the library, gzip compression recognition is
+ * automatically handled when calling @FT_New_Face or @FT_Open_Face.
+ * This means that if no font driver is capable of handling the raw
+ * compressed file, the library will try to open a gzipped stream from it
+ * and re-open the face with it.
+ *
+ * This function may return `FT_Err_Unimplemented_Feature` if your build
+ * of FreeType was not compiled with zlib support.
+ */
FT_EXPORT( FT_Error )
FT_Stream_OpenGzip( FT_Stream stream,
FT_Stream source );
- /************************************************************************
- *
- * @function:
- * FT_Gzip_Uncompress
- *
- * @description:
- * Decompress a zipped input buffer into an output buffer. This function
- * is modeled after zlib's `uncompress' function.
- *
- * @input:
- * memory ::
- * A FreeType memory handle.
- *
- * input ::
- * The input buffer.
- *
- * input_len ::
- * The length of the input buffer.
- *
- * @output:
- * output::
- * The output buffer.
- *
- * @inout:
- * output_len ::
- * Before calling the function, this is the total size of the output
- * buffer, which must be large enough to hold the entire uncompressed
- * data (so the size of the uncompressed data must be known in
- * advance). After calling the function, `output_len' is the size of
- * the used data in `output'.
- *
- * @return:
- * FreeType error code. 0~means success.
- *
- * @note:
- * This function may return `FT_Err_Unimplemented_Feature' if your build
- * of FreeType was not compiled with zlib support.
- *
- * @since:
- * 2.5.1
- */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Gzip_Uncompress
+ *
+ * @description:
+ * Decompress a zipped input buffer into an output buffer. This function
+ * is modeled after zlib's `uncompress` function.
+ *
+ * @input:
+ * memory ::
+ * A FreeType memory handle.
+ *
+ * input ::
+ * The input buffer.
+ *
+ * input_len ::
+ * The length of the input buffer.
+ *
+ * @output:
+ * output ::
+ * The output buffer.
+ *
+ * @inout:
+ * output_len ::
+ * Before calling the function, this is the total size of the output
+ * buffer, which must be large enough to hold the entire uncompressed
+ * data (so the size of the uncompressed data must be known in
+ * advance). After calling the function, `output_len` is the size of
+ * the used data in `output`.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * This function may return `FT_Err_Unimplemented_Feature` if your build
+ * of FreeType was not compiled with zlib support.
+ *
+ * @since:
+ * 2.5.1
+ */
FT_EXPORT( FT_Error )
FT_Gzip_Uncompress( FT_Memory memory,
FT_Byte* output,
diff --git a/thirdparty/freetype/include/freetype/ftimage.h b/thirdparty/freetype/include/freetype/ftimage.h
index 79ede1959d..d640b0b0aa 100644
--- a/thirdparty/freetype/include/freetype/ftimage.h
+++ b/thirdparty/freetype/include/freetype/ftimage.h
@@ -1,27 +1,27 @@
-/***************************************************************************/
-/* */
-/* ftimage.h */
-/* */
-/* FreeType glyph image formats and default raster interface */
-/* (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
- /*************************************************************************/
- /* */
- /* Note: A `raster' is simply a scan-line converter, used to render */
- /* FT_Outlines into FT_Bitmaps. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * ftimage.h
+ *
+ * FreeType glyph image formats and default raster interface
+ * (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+ /**************************************************************************
+ *
+ * Note: A 'raster' is simply a scan-line converter, used to render
+ * FT_Outlines into FT_Bitmaps.
+ *
+ */
#ifndef FTIMAGE_H_
@@ -37,40 +37,42 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* <Section> */
- /* basic_types */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_Pos */
- /* */
- /* <Description> */
- /* The type FT_Pos is used to store vectorial coordinates. Depending */
- /* on the context, these can represent distances in integer font */
- /* units, or 16.16, or 26.6 fixed-point pixel coordinates. */
- /* */
+ /**************************************************************************
+ *
+ * @section:
+ * basic_types
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Pos
+ *
+ * @description:
+ * The type FT_Pos is used to store vectorial coordinates. Depending on
+ * the context, these can represent distances in integer font units, or
+ * 16.16, or 26.6 fixed-point pixel coordinates.
+ */
typedef signed long FT_Pos;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_Vector */
- /* */
- /* <Description> */
- /* A simple structure used to store a 2D vector; coordinates are of */
- /* the FT_Pos type. */
- /* */
- /* <Fields> */
- /* x :: The horizontal coordinate. */
- /* y :: The vertical coordinate. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Vector
+ *
+ * @description:
+ * A simple structure used to store a 2D vector; coordinates are of the
+ * FT_Pos type.
+ *
+ * @fields:
+ * x ::
+ * The horizontal coordinate.
+ * y ::
+ * The vertical coordinate.
+ */
typedef struct FT_Vector_
{
FT_Pos x;
@@ -79,39 +81,41 @@ FT_BEGIN_HEADER
} FT_Vector;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_BBox */
- /* */
- /* <Description> */
- /* A structure used to hold an outline's bounding box, i.e., the */
- /* coordinates of its extrema in the horizontal and vertical */
- /* directions. */
- /* */
- /* <Fields> */
- /* xMin :: The horizontal minimum (left-most). */
- /* */
- /* yMin :: The vertical minimum (bottom-most). */
- /* */
- /* xMax :: The horizontal maximum (right-most). */
- /* */
- /* yMax :: The vertical maximum (top-most). */
- /* */
- /* <Note> */
- /* The bounding box is specified with the coordinates of the lower */
- /* left and the upper right corner. In PostScript, those values are */
- /* often called (llx,lly) and (urx,ury), respectively. */
- /* */
- /* If `yMin' is negative, this value gives the glyph's descender. */
- /* Otherwise, the glyph doesn't descend below the baseline. */
- /* Similarly, if `ymax' is positive, this value gives the glyph's */
- /* ascender. */
- /* */
- /* `xMin' gives the horizontal distance from the glyph's origin to */
- /* the left edge of the glyph's bounding box. If `xMin' is negative, */
- /* the glyph extends to the left of the origin. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_BBox
+ *
+ * @description:
+ * A structure used to hold an outline's bounding box, i.e., the
+ * coordinates of its extrema in the horizontal and vertical directions.
+ *
+ * @fields:
+ * xMin ::
+ * The horizontal minimum (left-most).
+ *
+ * yMin ::
+ * The vertical minimum (bottom-most).
+ *
+ * xMax ::
+ * The horizontal maximum (right-most).
+ *
+ * yMax ::
+ * The vertical maximum (top-most).
+ *
+ * @note:
+ * The bounding box is specified with the coordinates of the lower left
+ * and the upper right corner. In PostScript, those values are often
+ * called (llx,lly) and (urx,ury), respectively.
+ *
+ * If `yMin` is negative, this value gives the glyph's descender.
+ * Otherwise, the glyph doesn't descend below the baseline. Similarly,
+ * if `ymax` is positive, this value gives the glyph's ascender.
+ *
+ * `xMin` gives the horizontal distance from the glyph's origin to the
+ * left edge of the glyph's bounding box. If `xMin` is negative, the
+ * glyph extends to the left of the origin.
+ */
typedef struct FT_BBox_
{
FT_Pos xMin, yMin;
@@ -120,63 +124,60 @@ FT_BEGIN_HEADER
} FT_BBox;
- /*************************************************************************/
- /* */
- /* <Enum> */
- /* FT_Pixel_Mode */
- /* */
- /* <Description> */
- /* An enumeration type used to describe the format of pixels in a */
- /* given bitmap. Note that additional formats may be added in the */
- /* future. */
- /* */
- /* <Values> */
- /* FT_PIXEL_MODE_NONE :: */
- /* Value~0 is reserved. */
- /* */
- /* FT_PIXEL_MODE_MONO :: */
- /* A monochrome bitmap, using 1~bit per pixel. Note that pixels */
- /* are stored in most-significant order (MSB), which means that */
- /* the left-most pixel in a byte has value 128. */
- /* */
- /* FT_PIXEL_MODE_GRAY :: */
- /* An 8-bit bitmap, generally used to represent anti-aliased glyph */
- /* images. Each pixel is stored in one byte. Note that the number */
- /* of `gray' levels is stored in the `num_grays' field of the */
- /* @FT_Bitmap structure (it generally is 256). */
- /* */
- /* FT_PIXEL_MODE_GRAY2 :: */
- /* A 2-bit per pixel bitmap, used to represent embedded */
- /* anti-aliased bitmaps in font files according to the OpenType */
- /* specification. We haven't found a single font using this */
- /* format, however. */
- /* */
- /* FT_PIXEL_MODE_GRAY4 :: */
- /* A 4-bit per pixel bitmap, representing embedded anti-aliased */
- /* bitmaps in font files according to the OpenType specification. */
- /* We haven't found a single font using this format, however. */
- /* */
- /* FT_PIXEL_MODE_LCD :: */
- /* An 8-bit bitmap, representing RGB or BGR decimated glyph images */
- /* used for display on LCD displays; the bitmap is three times */
- /* wider than the original glyph image. See also */
- /* @FT_RENDER_MODE_LCD. */
- /* */
- /* FT_PIXEL_MODE_LCD_V :: */
- /* An 8-bit bitmap, representing RGB or BGR decimated glyph images */
- /* used for display on rotated LCD displays; the bitmap is three */
- /* times taller than the original glyph image. See also */
- /* @FT_RENDER_MODE_LCD_V. */
- /* */
- /* FT_PIXEL_MODE_BGRA :: */
- /* [Since 2.5] An image with four 8-bit channels per pixel, */
- /* representing a color image (such as emoticons) with alpha */
- /* channel. For each pixel, the format is BGRA, which means, the */
- /* blue channel comes first in memory. The color channels are */
- /* pre-multiplied and in the sRGB colorspace. For example, full */
- /* red at half-translucent opacity will be represented as */
- /* `00,00,80,80', not `00,00,FF,80'. See also @FT_LOAD_COLOR. */
- /* */
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_Pixel_Mode
+ *
+ * @description:
+ * An enumeration type used to describe the format of pixels in a given
+ * bitmap. Note that additional formats may be added in the future.
+ *
+ * @values:
+ * FT_PIXEL_MODE_NONE ::
+ * Value~0 is reserved.
+ *
+ * FT_PIXEL_MODE_MONO ::
+ * A monochrome bitmap, using 1~bit per pixel. Note that pixels are
+ * stored in most-significant order (MSB), which means that the
+ * left-most pixel in a byte has value 128.
+ *
+ * FT_PIXEL_MODE_GRAY ::
+ * An 8-bit bitmap, generally used to represent anti-aliased glyph
+ * images. Each pixel is stored in one byte. Note that the number of
+ * 'gray' levels is stored in the `num_grays` field of the @FT_Bitmap
+ * structure (it generally is 256).
+ *
+ * FT_PIXEL_MODE_GRAY2 ::
+ * A 2-bit per pixel bitmap, used to represent embedded anti-aliased
+ * bitmaps in font files according to the OpenType specification. We
+ * haven't found a single font using this format, however.
+ *
+ * FT_PIXEL_MODE_GRAY4 ::
+ * A 4-bit per pixel bitmap, representing embedded anti-aliased bitmaps
+ * in font files according to the OpenType specification. We haven't
+ * found a single font using this format, however.
+ *
+ * FT_PIXEL_MODE_LCD ::
+ * An 8-bit bitmap, representing RGB or BGR decimated glyph images used
+ * for display on LCD displays; the bitmap is three times wider than
+ * the original glyph image. See also @FT_RENDER_MODE_LCD.
+ *
+ * FT_PIXEL_MODE_LCD_V ::
+ * An 8-bit bitmap, representing RGB or BGR decimated glyph images used
+ * for display on rotated LCD displays; the bitmap is three times
+ * taller than the original glyph image. See also
+ * @FT_RENDER_MODE_LCD_V.
+ *
+ * FT_PIXEL_MODE_BGRA ::
+ * [Since 2.5] An image with four 8-bit channels per pixel,
+ * representing a color image (such as emoticons) with alpha channel.
+ * For each pixel, the format is BGRA, which means, the blue channel
+ * comes first in memory. The color channels are pre-multiplied and in
+ * the sRGB colorspace. For example, full red at half-translucent
+ * opacity will be represented as '00,00,80,80', not '00,00,FF,80'.
+ * See also @FT_LOAD_COLOR.
+ */
typedef enum FT_Pixel_Mode_
{
FT_PIXEL_MODE_NONE = 0,
@@ -193,7 +194,7 @@ FT_BEGIN_HEADER
} FT_Pixel_Mode;
- /* these constants are deprecated; use the corresponding `FT_Pixel_Mode' */
+ /* these constants are deprecated; use the corresponding `FT_Pixel_Mode` */
/* values instead. */
#define ft_pixel_mode_none FT_PIXEL_MODE_NONE
#define ft_pixel_mode_mono FT_PIXEL_MODE_MONO
@@ -202,62 +203,61 @@ FT_BEGIN_HEADER
#define ft_pixel_mode_pal4 FT_PIXEL_MODE_GRAY4
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_Bitmap */
- /* */
- /* <Description> */
- /* A structure used to describe a bitmap or pixmap to the raster. */
- /* Note that we now manage pixmaps of various depths through the */
- /* `pixel_mode' field. */
- /* */
- /* <Fields> */
- /* rows :: The number of bitmap rows. */
- /* */
- /* width :: The number of pixels in bitmap row. */
- /* */
- /* pitch :: The pitch's absolute value is the number of bytes */
- /* taken by one bitmap row, including padding. */
- /* However, the pitch is positive when the bitmap has */
- /* a `down' flow, and negative when it has an `up' */
- /* flow. In all cases, the pitch is an offset to add */
- /* to a bitmap pointer in order to go down one row. */
- /* */
- /* Note that `padding' means the alignment of a */
- /* bitmap to a byte border, and FreeType functions */
- /* normally align to the smallest possible integer */
- /* value. */
- /* */
- /* For the B/W rasterizer, `pitch' is always an even */
- /* number. */
- /* */
- /* To change the pitch of a bitmap (say, to make it a */
- /* multiple of 4), use @FT_Bitmap_Convert. */
- /* Alternatively, you might use callback functions to */
- /* directly render to the application's surface; see */
- /* the file `example2.cpp' in the tutorial for a */
- /* demonstration. */
- /* */
- /* buffer :: A typeless pointer to the bitmap buffer. This */
- /* value should be aligned on 32-bit boundaries in */
- /* most cases. */
- /* */
- /* num_grays :: This field is only used with */
- /* @FT_PIXEL_MODE_GRAY; it gives the number of gray */
- /* levels used in the bitmap. */
- /* */
- /* pixel_mode :: The pixel mode, i.e., how pixel bits are stored. */
- /* See @FT_Pixel_Mode for possible values. */
- /* */
- /* palette_mode :: This field is intended for paletted pixel modes; */
- /* it indicates how the palette is stored. Not */
- /* used currently. */
- /* */
- /* palette :: A typeless pointer to the bitmap palette; this */
- /* field is intended for paletted pixel modes. Not */
- /* used currently. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Bitmap
+ *
+ * @description:
+ * A structure used to describe a bitmap or pixmap to the raster. Note
+ * that we now manage pixmaps of various depths through the `pixel_mode`
+ * field.
+ *
+ * @fields:
+ * rows ::
+ * The number of bitmap rows.
+ *
+ * width ::
+ * The number of pixels in bitmap row.
+ *
+ * pitch ::
+ * The pitch's absolute value is the number of bytes taken by one
+ * bitmap row, including padding. However, the pitch is positive when
+ * the bitmap has a 'down' flow, and negative when it has an 'up' flow.
+ * In all cases, the pitch is an offset to add to a bitmap pointer in
+ * order to go down one row.
+ *
+ * Note that 'padding' means the alignment of a bitmap to a byte
+ * border, and FreeType functions normally align to the smallest
+ * possible integer value.
+ *
+ * For the B/W rasterizer, `pitch` is always an even number.
+ *
+ * To change the pitch of a bitmap (say, to make it a multiple of 4),
+ * use @FT_Bitmap_Convert. Alternatively, you might use callback
+ * functions to directly render to the application's surface; see the
+ * file `example2.cpp` in the tutorial for a demonstration.
+ *
+ * buffer ::
+ * A typeless pointer to the bitmap buffer. This value should be
+ * aligned on 32-bit boundaries in most cases.
+ *
+ * num_grays ::
+ * This field is only used with @FT_PIXEL_MODE_GRAY; it gives the
+ * number of gray levels used in the bitmap.
+ *
+ * pixel_mode ::
+ * The pixel mode, i.e., how pixel bits are stored. See @FT_Pixel_Mode
+ * for possible values.
+ *
+ * palette_mode ::
+ * This field is intended for paletted pixel modes; it indicates how
+ * the palette is stored. Not used currently.
+ *
+ * palette ::
+ * A typeless pointer to the bitmap palette; this field is intended for
+ * paletted pixel modes. Not used currently.
+ */
typedef struct FT_Bitmap_
{
unsigned int rows;
@@ -272,65 +272,68 @@ FT_BEGIN_HEADER
} FT_Bitmap;
- /*************************************************************************/
- /* */
- /* <Section> */
- /* outline_processing */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_Outline */
- /* */
- /* <Description> */
- /* This structure is used to describe an outline to the scan-line */
- /* converter. */
- /* */
- /* <Fields> */
- /* n_contours :: The number of contours in the outline. */
- /* */
- /* n_points :: The number of points in the outline. */
- /* */
- /* points :: A pointer to an array of `n_points' @FT_Vector */
- /* elements, giving the outline's point coordinates. */
- /* */
- /* tags :: A pointer to an array of `n_points' chars, giving */
- /* each outline point's type. */
- /* */
- /* If bit~0 is unset, the point is `off' the curve, */
- /* i.e., a Bezier control point, while it is `on' if */
- /* set. */
- /* */
- /* Bit~1 is meaningful for `off' points only. If set, */
- /* it indicates a third-order Bezier arc control point; */
- /* and a second-order control point if unset. */
- /* */
- /* If bit~2 is set, bits 5-7 contain the drop-out mode */
- /* (as defined in the OpenType specification; the value */
- /* is the same as the argument to the SCANMODE */
- /* instruction). */
- /* */
- /* Bits 3 and~4 are reserved for internal purposes. */
- /* */
- /* contours :: An array of `n_contours' shorts, giving the end */
- /* point of each contour within the outline. For */
- /* example, the first contour is defined by the points */
- /* `0' to `contours[0]', the second one is defined by */
- /* the points `contours[0]+1' to `contours[1]', etc. */
- /* */
- /* flags :: A set of bit flags used to characterize the outline */
- /* and give hints to the scan-converter and hinter on */
- /* how to convert/grid-fit it. See @FT_OUTLINE_XXX. */
- /* */
- /* <Note> */
- /* The B/W rasterizer only checks bit~2 in the `tags' array for the */
- /* first point of each contour. The drop-out mode as given with */
- /* @FT_OUTLINE_IGNORE_DROPOUTS, @FT_OUTLINE_SMART_DROPOUTS, and */
- /* @FT_OUTLINE_INCLUDE_STUBS in `flags' is then overridden. */
- /* */
+ /**************************************************************************
+ *
+ * @section:
+ * outline_processing
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Outline
+ *
+ * @description:
+ * This structure is used to describe an outline to the scan-line
+ * converter.
+ *
+ * @fields:
+ * n_contours ::
+ * The number of contours in the outline.
+ *
+ * n_points ::
+ * The number of points in the outline.
+ *
+ * points ::
+ * A pointer to an array of `n_points` @FT_Vector elements, giving the
+ * outline's point coordinates.
+ *
+ * tags ::
+ * A pointer to an array of `n_points` chars, giving each outline
+ * point's type.
+ *
+ * If bit~0 is unset, the point is 'off' the curve, i.e., a Bezier
+ * control point, while it is 'on' if set.
+ *
+ * Bit~1 is meaningful for 'off' points only. If set, it indicates a
+ * third-order Bezier arc control point; and a second-order control
+ * point if unset.
+ *
+ * If bit~2 is set, bits 5-7 contain the drop-out mode (as defined in
+ * the OpenType specification; the value is the same as the argument to
+ * the 'SCANMODE' instruction).
+ *
+ * Bits 3 and~4 are reserved for internal purposes.
+ *
+ * contours ::
+ * An array of `n_contours` shorts, giving the end point of each
+ * contour within the outline. For example, the first contour is
+ * defined by the points '0' to `contours[0]`, the second one is
+ * defined by the points `contours[0]+1` to `contours[1]`, etc.
+ *
+ * flags ::
+ * A set of bit flags used to characterize the outline and give hints
+ * to the scan-converter and hinter on how to convert/grid-fit it. See
+ * @FT_OUTLINE_XXX.
+ *
+ * @note:
+ * The B/W rasterizer only checks bit~2 in the `tags` array for the first
+ * point of each contour. The drop-out mode as given with
+ * @FT_OUTLINE_IGNORE_DROPOUTS, @FT_OUTLINE_SMART_DROPOUTS, and
+ * @FT_OUTLINE_INCLUDE_STUBS in `flags` is then overridden.
+ */
typedef struct FT_Outline_
{
short n_contours; /* number of contours in glyph */
@@ -352,78 +355,76 @@ FT_BEGIN_HEADER
#define FT_OUTLINE_POINTS_MAX SHRT_MAX
- /*************************************************************************/
- /* */
- /* <Enum> */
- /* FT_OUTLINE_XXX */
- /* */
- /* <Description> */
- /* A list of bit-field constants use for the flags in an outline's */
- /* `flags' field. */
- /* */
- /* <Values> */
- /* FT_OUTLINE_NONE :: */
- /* Value~0 is reserved. */
- /* */
- /* FT_OUTLINE_OWNER :: */
- /* If set, this flag indicates that the outline's field arrays */
- /* (i.e., `points', `flags', and `contours') are `owned' by the */
- /* outline object, and should thus be freed when it is destroyed. */
- /* */
- /* FT_OUTLINE_EVEN_ODD_FILL :: */
- /* By default, outlines are filled using the non-zero winding rule. */
- /* If set to 1, the outline will be filled using the even-odd fill */
- /* rule (only works with the smooth rasterizer). */
- /* */
- /* FT_OUTLINE_REVERSE_FILL :: */
- /* By default, outside contours of an outline are oriented in */
- /* clock-wise direction, as defined in the TrueType specification. */
- /* This flag is set if the outline uses the opposite direction */
- /* (typically for Type~1 fonts). This flag is ignored by the scan */
- /* converter. */
- /* */
- /* FT_OUTLINE_IGNORE_DROPOUTS :: */
- /* By default, the scan converter will try to detect drop-outs in */
- /* an outline and correct the glyph bitmap to ensure consistent */
- /* shape continuity. If set, this flag hints the scan-line */
- /* converter to ignore such cases. See below for more information. */
- /* */
- /* FT_OUTLINE_SMART_DROPOUTS :: */
- /* Select smart dropout control. If unset, use simple dropout */
- /* control. Ignored if @FT_OUTLINE_IGNORE_DROPOUTS is set. See */
- /* below for more information. */
- /* */
- /* FT_OUTLINE_INCLUDE_STUBS :: */
- /* If set, turn pixels on for `stubs', otherwise exclude them. */
- /* Ignored if @FT_OUTLINE_IGNORE_DROPOUTS is set. See below for */
- /* more information. */
- /* */
- /* FT_OUTLINE_HIGH_PRECISION :: */
- /* This flag indicates that the scan-line converter should try to */
- /* convert this outline to bitmaps with the highest possible */
- /* quality. It is typically set for small character sizes. Note */
- /* that this is only a hint that might be completely ignored by a */
- /* given scan-converter. */
- /* */
- /* FT_OUTLINE_SINGLE_PASS :: */
- /* This flag is set to force a given scan-converter to only use a */
- /* single pass over the outline to render a bitmap glyph image. */
- /* Normally, it is set for very large character sizes. It is only */
- /* a hint that might be completely ignored by a given */
- /* scan-converter. */
- /* */
- /* <Note> */
- /* The flags @FT_OUTLINE_IGNORE_DROPOUTS, @FT_OUTLINE_SMART_DROPOUTS, */
- /* and @FT_OUTLINE_INCLUDE_STUBS are ignored by the smooth */
- /* rasterizer. */
- /* */
- /* There exists a second mechanism to pass the drop-out mode to the */
- /* B/W rasterizer; see the `tags' field in @FT_Outline. */
- /* */
- /* Please refer to the description of the `SCANTYPE' instruction in */
- /* the OpenType specification (in file `ttinst1.doc') how simple */
- /* drop-outs, smart drop-outs, and stubs are defined. */
- /* */
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_OUTLINE_XXX
+ *
+ * @description:
+ * A list of bit-field constants used for the flags in an outline's
+ * `flags` field.
+ *
+ * @values:
+ * FT_OUTLINE_NONE ::
+ * Value~0 is reserved.
+ *
+ * FT_OUTLINE_OWNER ::
+ * If set, this flag indicates that the outline's field arrays (i.e.,
+ * `points`, `flags`, and `contours`) are 'owned' by the outline
+ * object, and should thus be freed when it is destroyed.
+ *
+ * FT_OUTLINE_EVEN_ODD_FILL ::
+ * By default, outlines are filled using the non-zero winding rule. If
+ * set to 1, the outline will be filled using the even-odd fill rule
+ * (only works with the smooth rasterizer).
+ *
+ * FT_OUTLINE_REVERSE_FILL ::
+ * By default, outside contours of an outline are oriented in
+ * clock-wise direction, as defined in the TrueType specification.
+ * This flag is set if the outline uses the opposite direction
+ * (typically for Type~1 fonts). This flag is ignored by the scan
+ * converter.
+ *
+ * FT_OUTLINE_IGNORE_DROPOUTS ::
+ * By default, the scan converter will try to detect drop-outs in an
+ * outline and correct the glyph bitmap to ensure consistent shape
+ * continuity. If set, this flag hints the scan-line converter to
+ * ignore such cases. See below for more information.
+ *
+ * FT_OUTLINE_SMART_DROPOUTS ::
+ * Select smart dropout control. If unset, use simple dropout control.
+ * Ignored if @FT_OUTLINE_IGNORE_DROPOUTS is set. See below for more
+ * information.
+ *
+ * FT_OUTLINE_INCLUDE_STUBS ::
+ * If set, turn pixels on for 'stubs', otherwise exclude them. Ignored
+ * if @FT_OUTLINE_IGNORE_DROPOUTS is set. See below for more
+ * information.
+ *
+ * FT_OUTLINE_HIGH_PRECISION ::
+ * This flag indicates that the scan-line converter should try to
+ * convert this outline to bitmaps with the highest possible quality.
+ * It is typically set for small character sizes. Note that this is
+ * only a hint that might be completely ignored by a given
+ * scan-converter.
+ *
+ * FT_OUTLINE_SINGLE_PASS ::
+ * This flag is set to force a given scan-converter to only use a
+ * single pass over the outline to render a bitmap glyph image.
+ * Normally, it is set for very large character sizes. It is only a
+ * hint that might be completely ignored by a given scan-converter.
+ *
+ * @note:
+ * The flags @FT_OUTLINE_IGNORE_DROPOUTS, @FT_OUTLINE_SMART_DROPOUTS, and
+ * @FT_OUTLINE_INCLUDE_STUBS are ignored by the smooth rasterizer.
+ *
+ * There exists a second mechanism to pass the drop-out mode to the B/W
+ * rasterizer; see the `tags` field in @FT_Outline.
+ *
+ * Please refer to the description of the 'SCANTYPE' instruction in the
+ * OpenType specification (in file `ttinst1.doc`) how simple drop-outs,
+ * smart drop-outs, and stubs are defined.
+ */
#define FT_OUTLINE_NONE 0x0
#define FT_OUTLINE_OWNER 0x1
#define FT_OUTLINE_EVEN_ODD_FILL 0x2
@@ -437,7 +438,7 @@ FT_BEGIN_HEADER
/* these constants are deprecated; use the corresponding */
- /* `FT_OUTLINE_XXX' values instead */
+ /* `FT_OUTLINE_XXX` values instead */
#define ft_outline_none FT_OUTLINE_NONE
#define ft_outline_owner FT_OUTLINE_OWNER
#define ft_outline_even_odd_fill FT_OUTLINE_EVEN_ODD_FILL
@@ -448,20 +449,25 @@ FT_BEGIN_HEADER
/* */
-#define FT_CURVE_TAG( flag ) ( flag & 3 )
+#define FT_CURVE_TAG( flag ) ( flag & 0x03 )
-#define FT_CURVE_TAG_ON 1
-#define FT_CURVE_TAG_CONIC 0
-#define FT_CURVE_TAG_CUBIC 2
+ /* see the `tags` field in `FT_Outline` for a description of the values */
+#define FT_CURVE_TAG_ON 0x01
+#define FT_CURVE_TAG_CONIC 0x00
+#define FT_CURVE_TAG_CUBIC 0x02
-#define FT_CURVE_TAG_HAS_SCANMODE 4
+#define FT_CURVE_TAG_HAS_SCANMODE 0x04
-#define FT_CURVE_TAG_TOUCH_X 8 /* reserved for the TrueType hinter */
-#define FT_CURVE_TAG_TOUCH_Y 16 /* reserved for the TrueType hinter */
+#define FT_CURVE_TAG_TOUCH_X 0x08 /* reserved for TrueType hinter */
+#define FT_CURVE_TAG_TOUCH_Y 0x10 /* reserved for TrueType hinter */
#define FT_CURVE_TAG_TOUCH_BOTH ( FT_CURVE_TAG_TOUCH_X | \
FT_CURVE_TAG_TOUCH_Y )
+ /* values 0x20, 0x40, and 0x80 are reserved */
+
+ /* these constants are deprecated; use the corresponding */
+ /* `FT_CURVE_TAG_XXX` values instead */
#define FT_Curve_Tag_On FT_CURVE_TAG_ON
#define FT_Curve_Tag_Conic FT_CURVE_TAG_CONIC
#define FT_Curve_Tag_Cubic FT_CURVE_TAG_CUBIC
@@ -469,26 +475,28 @@ FT_BEGIN_HEADER
#define FT_Curve_Tag_Touch_Y FT_CURVE_TAG_TOUCH_Y
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* FT_Outline_MoveToFunc */
- /* */
- /* <Description> */
- /* A function pointer type used to describe the signature of a `move */
- /* to' function during outline walking/decomposition. */
- /* */
- /* A `move to' is emitted to start a new contour in an outline. */
- /* */
- /* <Input> */
- /* to :: A pointer to the target point of the `move to'. */
- /* */
- /* user :: A typeless pointer, which is passed from the caller of the */
- /* decomposition function. */
- /* */
- /* <Return> */
- /* Error code. 0~means success. */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_Outline_MoveToFunc
+ *
+ * @description:
+ * A function pointer type used to describe the signature of a 'move to'
+ * function during outline walking/decomposition.
+ *
+ * A 'move to' is emitted to start a new contour in an outline.
+ *
+ * @input:
+ * to ::
+ * A pointer to the target point of the 'move to'.
+ *
+ * user ::
+ * A typeless pointer, which is passed from the caller of the
+ * decomposition function.
+ *
+ * @return:
+ * Error code. 0~means success.
+ */
typedef int
(*FT_Outline_MoveToFunc)( const FT_Vector* to,
void* user );
@@ -496,26 +504,28 @@ FT_BEGIN_HEADER
#define FT_Outline_MoveTo_Func FT_Outline_MoveToFunc
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* FT_Outline_LineToFunc */
- /* */
- /* <Description> */
- /* A function pointer type used to describe the signature of a `line */
- /* to' function during outline walking/decomposition. */
- /* */
- /* A `line to' is emitted to indicate a segment in the outline. */
- /* */
- /* <Input> */
- /* to :: A pointer to the target point of the `line to'. */
- /* */
- /* user :: A typeless pointer, which is passed from the caller of the */
- /* decomposition function. */
- /* */
- /* <Return> */
- /* Error code. 0~means success. */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_Outline_LineToFunc
+ *
+ * @description:
+ * A function pointer type used to describe the signature of a 'line to'
+ * function during outline walking/decomposition.
+ *
+ * A 'line to' is emitted to indicate a segment in the outline.
+ *
+ * @input:
+ * to ::
+ * A pointer to the target point of the 'line to'.
+ *
+ * user ::
+ * A typeless pointer, which is passed from the caller of the
+ * decomposition function.
+ *
+ * @return:
+ * Error code. 0~means success.
+ */
typedef int
(*FT_Outline_LineToFunc)( const FT_Vector* to,
void* user );
@@ -523,30 +533,33 @@ FT_BEGIN_HEADER
#define FT_Outline_LineTo_Func FT_Outline_LineToFunc
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* FT_Outline_ConicToFunc */
- /* */
- /* <Description> */
- /* A function pointer type used to describe the signature of a `conic */
- /* to' function during outline walking or decomposition. */
- /* */
- /* A `conic to' is emitted to indicate a second-order Bezier arc in */
- /* the outline. */
- /* */
- /* <Input> */
- /* control :: An intermediate control point between the last position */
- /* and the new target in `to'. */
- /* */
- /* to :: A pointer to the target end point of the conic arc. */
- /* */
- /* user :: A typeless pointer, which is passed from the caller of */
- /* the decomposition function. */
- /* */
- /* <Return> */
- /* Error code. 0~means success. */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_Outline_ConicToFunc
+ *
+ * @description:
+ * A function pointer type used to describe the signature of a 'conic to'
+ * function during outline walking or decomposition.
+ *
+ * A 'conic to' is emitted to indicate a second-order Bezier arc in the
+ * outline.
+ *
+ * @input:
+ * control ::
+ * An intermediate control point between the last position and the new
+ * target in `to`.
+ *
+ * to ::
+ * A pointer to the target end point of the conic arc.
+ *
+ * user ::
+ * A typeless pointer, which is passed from the caller of the
+ * decomposition function.
+ *
+ * @return:
+ * Error code. 0~means success.
+ */
typedef int
(*FT_Outline_ConicToFunc)( const FT_Vector* control,
const FT_Vector* to,
@@ -555,30 +568,34 @@ FT_BEGIN_HEADER
#define FT_Outline_ConicTo_Func FT_Outline_ConicToFunc
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* FT_Outline_CubicToFunc */
- /* */
- /* <Description> */
- /* A function pointer type used to describe the signature of a `cubic */
- /* to' function during outline walking or decomposition. */
- /* */
- /* A `cubic to' is emitted to indicate a third-order Bezier arc. */
- /* */
- /* <Input> */
- /* control1 :: A pointer to the first Bezier control point. */
- /* */
- /* control2 :: A pointer to the second Bezier control point. */
- /* */
- /* to :: A pointer to the target end point. */
- /* */
- /* user :: A typeless pointer, which is passed from the caller of */
- /* the decomposition function. */
- /* */
- /* <Return> */
- /* Error code. 0~means success. */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_Outline_CubicToFunc
+ *
+ * @description:
+ * A function pointer type used to describe the signature of a 'cubic to'
+ * function during outline walking or decomposition.
+ *
+ * A 'cubic to' is emitted to indicate a third-order Bezier arc.
+ *
+ * @input:
+ * control1 ::
+ * A pointer to the first Bezier control point.
+ *
+ * control2 ::
+ * A pointer to the second Bezier control point.
+ *
+ * to ::
+ * A pointer to the target end point.
+ *
+ * user ::
+ * A typeless pointer, which is passed from the caller of the
+ * decomposition function.
+ *
+ * @return:
+ * Error code. 0~means success.
+ */
typedef int
(*FT_Outline_CubicToFunc)( const FT_Vector* control1,
const FT_Vector* control2,
@@ -588,43 +605,49 @@ FT_BEGIN_HEADER
#define FT_Outline_CubicTo_Func FT_Outline_CubicToFunc
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_Outline_Funcs */
- /* */
- /* <Description> */
- /* A structure to hold various function pointers used during outline */
- /* decomposition in order to emit segments, conic, and cubic Beziers. */
- /* */
- /* <Fields> */
- /* move_to :: The `move to' emitter. */
- /* */
- /* line_to :: The segment emitter. */
- /* */
- /* conic_to :: The second-order Bezier arc emitter. */
- /* */
- /* cubic_to :: The third-order Bezier arc emitter. */
- /* */
- /* shift :: The shift that is applied to coordinates before they */
- /* are sent to the emitter. */
- /* */
- /* delta :: The delta that is applied to coordinates before they */
- /* are sent to the emitter, but after the shift. */
- /* */
- /* <Note> */
- /* The point coordinates sent to the emitters are the transformed */
- /* version of the original coordinates (this is important for high */
- /* accuracy during scan-conversion). The transformation is simple: */
- /* */
- /* { */
- /* x' = (x << shift) - delta */
- /* y' = (y << shift) - delta */
- /* } */
- /* */
- /* Set the values of `shift' and `delta' to~0 to get the original */
- /* point coordinates. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Outline_Funcs
+ *
+ * @description:
+ * A structure to hold various function pointers used during outline
+ * decomposition in order to emit segments, conic, and cubic Beziers.
+ *
+ * @fields:
+ * move_to ::
+ * The 'move to' emitter.
+ *
+ * line_to ::
+ * The segment emitter.
+ *
+ * conic_to ::
+ * The second-order Bezier arc emitter.
+ *
+ * cubic_to ::
+ * The third-order Bezier arc emitter.
+ *
+ * shift ::
+ * The shift that is applied to coordinates before they are sent to the
+ * emitter.
+ *
+ * delta ::
+ * The delta that is applied to coordinates before they are sent to the
+ * emitter, but after the shift.
+ *
+ * @note:
+ * The point coordinates sent to the emitters are the transformed version
+ * of the original coordinates (this is important for high accuracy
+ * during scan-conversion). The transformation is simple:
+ *
+ * ```
+ * x' = (x << shift) - delta
+ * y' = (y << shift) - delta
+ * ```
+ *
+ * Set the values of `shift` and `delta` to~0 to get the original point
+ * coordinates.
+ */
typedef struct FT_Outline_Funcs_
{
FT_Outline_MoveToFunc move_to;
@@ -638,33 +661,32 @@ FT_BEGIN_HEADER
} FT_Outline_Funcs;
- /*************************************************************************/
- /* */
- /* <Section> */
- /* basic_types */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* <Macro> */
- /* FT_IMAGE_TAG */
- /* */
- /* <Description> */
- /* This macro converts four-letter tags to an unsigned long type. */
- /* */
- /* <Note> */
- /* Since many 16-bit compilers don't like 32-bit enumerations, you */
- /* should redefine this macro in case of problems to something like */
- /* this: */
- /* */
- /* { */
- /* #define FT_IMAGE_TAG( value, _x1, _x2, _x3, _x4 ) value */
- /* } */
- /* */
- /* to get a simple enumeration without assigning special numbers. */
- /* */
+ /**************************************************************************
+ *
+ * @section:
+ * basic_types
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_IMAGE_TAG
+ *
+ * @description:
+ * This macro converts four-letter tags to an unsigned long type.
+ *
+ * @note:
+ * Since many 16-bit compilers don't like 32-bit enumerations, you should
+ * redefine this macro in case of problems to something like this:
+ *
+ * ```
+ * #define FT_IMAGE_TAG( value, _x1, _x2, _x3, _x4 ) value
+ * ```
+ *
+ * to get a simple enumeration without assigning special numbers.
+ */
#ifndef FT_IMAGE_TAG
#define FT_IMAGE_TAG( value, _x1, _x2, _x3, _x4 ) \
value = ( ( (unsigned long)_x1 << 24 ) | \
@@ -674,44 +696,43 @@ FT_BEGIN_HEADER
#endif /* FT_IMAGE_TAG */
- /*************************************************************************/
- /* */
- /* <Enum> */
- /* FT_Glyph_Format */
- /* */
- /* <Description> */
- /* An enumeration type used to describe the format of a given glyph */
- /* image. Note that this version of FreeType only supports two image */
- /* formats, even though future font drivers will be able to register */
- /* their own format. */
- /* */
- /* <Values> */
- /* FT_GLYPH_FORMAT_NONE :: */
- /* The value~0 is reserved. */
- /* */
- /* FT_GLYPH_FORMAT_COMPOSITE :: */
- /* The glyph image is a composite of several other images. This */
- /* format is _only_ used with @FT_LOAD_NO_RECURSE, and is used to */
- /* report compound glyphs (like accented characters). */
- /* */
- /* FT_GLYPH_FORMAT_BITMAP :: */
- /* The glyph image is a bitmap, and can be described as an */
- /* @FT_Bitmap. You generally need to access the `bitmap' field of */
- /* the @FT_GlyphSlotRec structure to read it. */
- /* */
- /* FT_GLYPH_FORMAT_OUTLINE :: */
- /* The glyph image is a vectorial outline made of line segments */
- /* and Bezier arcs; it can be described as an @FT_Outline; you */
- /* generally want to access the `outline' field of the */
- /* @FT_GlyphSlotRec structure to read it. */
- /* */
- /* FT_GLYPH_FORMAT_PLOTTER :: */
- /* The glyph image is a vectorial path with no inside and outside */
- /* contours. Some Type~1 fonts, like those in the Hershey family, */
- /* contain glyphs in this format. These are described as */
- /* @FT_Outline, but FreeType isn't currently capable of rendering */
- /* them correctly. */
- /* */
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_Glyph_Format
+ *
+ * @description:
+ * An enumeration type used to describe the format of a given glyph
+ * image. Note that this version of FreeType only supports two image
+ * formats, even though future font drivers will be able to register
+ * their own format.
+ *
+ * @values:
+ * FT_GLYPH_FORMAT_NONE ::
+ * The value~0 is reserved.
+ *
+ * FT_GLYPH_FORMAT_COMPOSITE ::
+ * The glyph image is a composite of several other images. This format
+ * is _only_ used with @FT_LOAD_NO_RECURSE, and is used to report
+ * compound glyphs (like accented characters).
+ *
+ * FT_GLYPH_FORMAT_BITMAP ::
+ * The glyph image is a bitmap, and can be described as an @FT_Bitmap.
+ * You generally need to access the `bitmap` field of the
+ * @FT_GlyphSlotRec structure to read it.
+ *
+ * FT_GLYPH_FORMAT_OUTLINE ::
+ * The glyph image is a vectorial outline made of line segments and
+ * Bezier arcs; it can be described as an @FT_Outline; you generally
+ * want to access the `outline` field of the @FT_GlyphSlotRec structure
+ * to read it.
+ *
+ * FT_GLYPH_FORMAT_PLOTTER ::
+ * The glyph image is a vectorial path with no inside and outside
+ * contours. Some Type~1 fonts, like those in the Hershey family,
+ * contain glyphs in this format. These are described as @FT_Outline,
+ * but FreeType isn't currently capable of rendering them correctly.
+ */
typedef enum FT_Glyph_Format_
{
FT_IMAGE_TAG( FT_GLYPH_FORMAT_NONE, 0, 0, 0, 0 ),
@@ -725,7 +746,7 @@ FT_BEGIN_HEADER
/* these constants are deprecated; use the corresponding */
- /* `FT_Glyph_Format' values instead. */
+ /* `FT_Glyph_Format` values instead. */
#define ft_glyph_format_none FT_GLYPH_FORMAT_NONE
#define ft_glyph_format_composite FT_GLYPH_FORMAT_COMPOSITE
#define ft_glyph_format_bitmap FT_GLYPH_FORMAT_BITMAP
@@ -744,87 +765,89 @@ FT_BEGIN_HEADER
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* A raster is a scan converter, in charge of rendering an outline into */
- /* a bitmap. This section contains the public API for rasters. */
- /* */
- /* Note that in FreeType 2, all rasters are now encapsulated within */
- /* specific modules called `renderers'. See `ftrender.h' for more */
- /* details on renderers. */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* <Section> */
- /* raster */
- /* */
- /* <Title> */
- /* Scanline Converter */
- /* */
- /* <Abstract> */
- /* How vectorial outlines are converted into bitmaps and pixmaps. */
- /* */
- /* <Description> */
- /* This section contains technical definitions. */
- /* */
- /* <Order> */
- /* FT_Raster */
- /* FT_Span */
- /* FT_SpanFunc */
- /* */
- /* FT_Raster_Params */
- /* FT_RASTER_FLAG_XXX */
- /* */
- /* FT_Raster_NewFunc */
- /* FT_Raster_DoneFunc */
- /* FT_Raster_ResetFunc */
- /* FT_Raster_SetModeFunc */
- /* FT_Raster_RenderFunc */
- /* FT_Raster_Funcs */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_Raster */
- /* */
- /* <Description> */
- /* An opaque handle (pointer) to a raster object. Each object can be */
- /* used independently to convert an outline into a bitmap or pixmap. */
- /* */
+ /**************************************************************************
+ *
+ * A raster is a scan converter, in charge of rendering an outline into a
+ * bitmap. This section contains the public API for rasters.
+ *
+ * Note that in FreeType 2, all rasters are now encapsulated within
+ * specific modules called 'renderers'. See `ftrender.h` for more details
+ * on renderers.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * raster
+ *
+ * @title:
+ * Scanline Converter
+ *
+ * @abstract:
+ * How vectorial outlines are converted into bitmaps and pixmaps.
+ *
+ * @description:
+ * This section contains technical definitions.
+ *
+ * @order:
+ * FT_Raster
+ * FT_Span
+ * FT_SpanFunc
+ *
+ * FT_Raster_Params
+ * FT_RASTER_FLAG_XXX
+ *
+ * FT_Raster_NewFunc
+ * FT_Raster_DoneFunc
+ * FT_Raster_ResetFunc
+ * FT_Raster_SetModeFunc
+ * FT_Raster_RenderFunc
+ * FT_Raster_Funcs
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Raster
+ *
+ * @description:
+ * An opaque handle (pointer) to a raster object. Each object can be
+ * used independently to convert an outline into a bitmap or pixmap.
+ */
typedef struct FT_RasterRec_* FT_Raster;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_Span */
- /* */
- /* <Description> */
- /* A structure used to model a single span of gray pixels when */
- /* rendering an anti-aliased bitmap. */
- /* */
- /* <Fields> */
- /* x :: The span's horizontal start position. */
- /* */
- /* len :: The span's length in pixels. */
- /* */
- /* coverage :: The span color/coverage, ranging from 0 (background) */
- /* to 255 (foreground). */
- /* */
- /* <Note> */
- /* This structure is used by the span drawing callback type named */
- /* @FT_SpanFunc that takes the y~coordinate of the span as a */
- /* parameter. */
- /* */
- /* The coverage value is always between 0 and 255. If you want less */
- /* gray values, the callback function has to reduce them. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Span
+ *
+ * @description:
+ * A structure used to model a single span of gray pixels when rendering
+ * an anti-aliased bitmap.
+ *
+ * @fields:
+ * x ::
+ * The span's horizontal start position.
+ *
+ * len ::
+ * The span's length in pixels.
+ *
+ * coverage ::
+ * The span color/coverage, ranging from 0 (background) to 255
+ * (foreground).
+ *
+ * @note:
+ * This structure is used by the span drawing callback type named
+ * @FT_SpanFunc that takes the y~coordinate of the span as a parameter.
+ *
+ * The coverage value is always between 0 and 255. If you want less gray
+ * values, the callback function has to reduce them.
+ */
typedef struct FT_Span_
{
short x;
@@ -834,32 +857,36 @@ FT_BEGIN_HEADER
} FT_Span;
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* FT_SpanFunc */
- /* */
- /* <Description> */
- /* A function used as a call-back by the anti-aliased renderer in */
- /* order to let client applications draw themselves the gray pixel */
- /* spans on each scan line. */
- /* */
- /* <Input> */
- /* y :: The scanline's y~coordinate. */
- /* */
- /* count :: The number of spans to draw on this scanline. */
- /* */
- /* spans :: A table of `count' spans to draw on the scanline. */
- /* */
- /* user :: User-supplied data that is passed to the callback. */
- /* */
- /* <Note> */
- /* This callback allows client applications to directly render the */
- /* gray spans of the anti-aliased bitmap to any kind of surfaces. */
- /* */
- /* This can be used to write anti-aliased outlines directly to a */
- /* given background bitmap, and even perform translucency. */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_SpanFunc
+ *
+ * @description:
+ * A function used as a call-back by the anti-aliased renderer in order
+ * to let client applications draw themselves the gray pixel spans on
+ * each scan line.
+ *
+ * @input:
+ * y ::
+ * The scanline's y~coordinate.
+ *
+ * count ::
+ * The number of spans to draw on this scanline.
+ *
+ * spans ::
+ * A table of `count` spans to draw on the scanline.
+ *
+ * user ::
+ * User-supplied data that is passed to the callback.
+ *
+ * @note:
+ * This callback allows client applications to directly render the gray
+ * spans of the anti-aliased bitmap to any kind of surfaces.
+ *
+ * This can be used to write anti-aliased outlines directly to a given
+ * background bitmap, and even perform translucency.
+ */
typedef void
(*FT_SpanFunc)( int y,
int count,
@@ -869,131 +896,131 @@ FT_BEGIN_HEADER
#define FT_Raster_Span_Func FT_SpanFunc
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* FT_Raster_BitTest_Func */
- /* */
- /* <Description> */
- /* Deprecated, unimplemented. */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_Raster_BitTest_Func
+ *
+ * @description:
+ * Deprecated, unimplemented.
+ */
typedef int
(*FT_Raster_BitTest_Func)( int y,
int x,
void* user );
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* FT_Raster_BitSet_Func */
- /* */
- /* <Description> */
- /* Deprecated, unimplemented. */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_Raster_BitSet_Func
+ *
+ * @description:
+ * Deprecated, unimplemented.
+ */
typedef void
(*FT_Raster_BitSet_Func)( int y,
int x,
void* user );
- /*************************************************************************/
- /* */
- /* <Enum> */
- /* FT_RASTER_FLAG_XXX */
- /* */
- /* <Description> */
- /* A list of bit flag constants as used in the `flags' field of a */
- /* @FT_Raster_Params structure. */
- /* */
- /* <Values> */
- /* FT_RASTER_FLAG_DEFAULT :: This value is 0. */
- /* */
- /* FT_RASTER_FLAG_AA :: This flag is set to indicate that an */
- /* anti-aliased glyph image should be */
- /* generated. Otherwise, it will be */
- /* monochrome (1-bit). */
- /* */
- /* FT_RASTER_FLAG_DIRECT :: This flag is set to indicate direct */
- /* rendering. In this mode, client */
- /* applications must provide their own span */
- /* callback. This lets them directly */
- /* draw or compose over an existing bitmap. */
- /* If this bit is not set, the target */
- /* pixmap's buffer _must_ be zeroed before */
- /* rendering. */
- /* */
- /* Direct rendering is only possible with */
- /* anti-aliased glyphs. */
- /* */
- /* FT_RASTER_FLAG_CLIP :: This flag is only used in direct */
- /* rendering mode. If set, the output will */
- /* be clipped to a box specified in the */
- /* `clip_box' field of the */
- /* @FT_Raster_Params structure. */
- /* */
- /* Note that by default, the glyph bitmap */
- /* is clipped to the target pixmap, except */
- /* in direct rendering mode where all spans */
- /* are generated if no clipping box is set. */
- /* */
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_RASTER_FLAG_XXX
+ *
+ * @description:
+ * A list of bit flag constants as used in the `flags` field of a
+ * @FT_Raster_Params structure.
+ *
+ * @values:
+ * FT_RASTER_FLAG_DEFAULT ::
+ * This value is 0.
+ *
+ * FT_RASTER_FLAG_AA ::
+ * This flag is set to indicate that an anti-aliased glyph image should
+ * be generated. Otherwise, it will be monochrome (1-bit).
+ *
+ * FT_RASTER_FLAG_DIRECT ::
+ * This flag is set to indicate direct rendering. In this mode, client
+ * applications must provide their own span callback. This lets them
+ * directly draw or compose over an existing bitmap. If this bit is
+ * not set, the target pixmap's buffer _must_ be zeroed before
+ * rendering.
+ *
+ * Direct rendering is only possible with anti-aliased glyphs.
+ *
+ * FT_RASTER_FLAG_CLIP ::
+ * This flag is only used in direct rendering mode. If set, the output
+ * will be clipped to a box specified in the `clip_box` field of the
+ * @FT_Raster_Params structure.
+ *
+ * Note that by default, the glyph bitmap is clipped to the target
+ * pixmap, except in direct rendering mode where all spans are
+ * generated if no clipping box is set.
+ */
#define FT_RASTER_FLAG_DEFAULT 0x0
#define FT_RASTER_FLAG_AA 0x1
#define FT_RASTER_FLAG_DIRECT 0x2
#define FT_RASTER_FLAG_CLIP 0x4
/* these constants are deprecated; use the corresponding */
- /* `FT_RASTER_FLAG_XXX' values instead */
+ /* `FT_RASTER_FLAG_XXX` values instead */
#define ft_raster_flag_default FT_RASTER_FLAG_DEFAULT
#define ft_raster_flag_aa FT_RASTER_FLAG_AA
#define ft_raster_flag_direct FT_RASTER_FLAG_DIRECT
#define ft_raster_flag_clip FT_RASTER_FLAG_CLIP
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_Raster_Params */
- /* */
- /* <Description> */
- /* A structure to hold the arguments used by a raster's render */
- /* function. */
- /* */
- /* <Fields> */
- /* target :: The target bitmap. */
- /* */
- /* source :: A pointer to the source glyph image (e.g., an */
- /* @FT_Outline). */
- /* */
- /* flags :: The rendering flags. */
- /* */
- /* gray_spans :: The gray span drawing callback. */
- /* */
- /* black_spans :: Unused. */
- /* */
- /* bit_test :: Unused. */
- /* */
- /* bit_set :: Unused. */
- /* */
- /* user :: User-supplied data that is passed to each drawing */
- /* callback. */
- /* */
- /* clip_box :: An optional clipping box. It is only used in */
- /* direct rendering mode. Note that coordinates here */
- /* should be expressed in _integer_ pixels (and not in */
- /* 26.6 fixed-point units). */
- /* */
- /* <Note> */
- /* An anti-aliased glyph bitmap is drawn if the @FT_RASTER_FLAG_AA */
- /* bit flag is set in the `flags' field, otherwise a monochrome */
- /* bitmap is generated. */
- /* */
- /* If the @FT_RASTER_FLAG_DIRECT bit flag is set in `flags', the */
- /* raster will call the `gray_spans' callback to draw gray pixel */
- /* spans. This allows direct composition over a pre-existing bitmap */
- /* through user-provided callbacks to perform the span drawing and */
- /* composition. Not supported by the monochrome rasterizer. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Raster_Params
+ *
+ * @description:
+ * A structure to hold the arguments used by a raster's render function.
+ *
+ * @fields:
+ * target ::
+ * The target bitmap.
+ *
+ * source ::
+ * A pointer to the source glyph image (e.g., an @FT_Outline).
+ *
+ * flags ::
+ * The rendering flags.
+ *
+ * gray_spans ::
+ * The gray span drawing callback.
+ *
+ * black_spans ::
+ * Unused.
+ *
+ * bit_test ::
+ * Unused.
+ *
+ * bit_set ::
+ * Unused.
+ *
+ * user ::
+ * User-supplied data that is passed to each drawing callback.
+ *
+ * clip_box ::
+ * An optional clipping box. It is only used in direct rendering mode.
+ * Note that coordinates here should be expressed in _integer_ pixels
+ * (and not in 26.6 fixed-point units).
+ *
+ * @note:
+ * An anti-aliased glyph bitmap is drawn if the @FT_RASTER_FLAG_AA bit
+ * flag is set in the `flags` field, otherwise a monochrome bitmap is
+ * generated.
+ *
+ * If the @FT_RASTER_FLAG_DIRECT bit flag is set in `flags`, the raster
+ * will call the `gray_spans` callback to draw gray pixel spans. This
+ * allows direct composition over a pre-existing bitmap through
+ * user-provided callbacks to perform the span drawing and composition.
+ * Not supported by the monochrome rasterizer.
+ */
typedef struct FT_Raster_Params_
{
const FT_Bitmap* target;
@@ -1009,30 +1036,32 @@ FT_BEGIN_HEADER
} FT_Raster_Params;
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* FT_Raster_NewFunc */
- /* */
- /* <Description> */
- /* A function used to create a new raster object. */
- /* */
- /* <Input> */
- /* memory :: A handle to the memory allocator. */
- /* */
- /* <Output> */
- /* raster :: A handle to the new raster object. */
- /* */
- /* <Return> */
- /* Error code. 0~means success. */
- /* */
- /* <Note> */
- /* The `memory' parameter is a typeless pointer in order to avoid */
- /* un-wanted dependencies on the rest of the FreeType code. In */
- /* practice, it is an @FT_Memory object, i.e., a handle to the */
- /* standard FreeType memory allocator. However, this field can be */
- /* completely ignored by a given raster implementation. */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_Raster_NewFunc
+ *
+ * @description:
+ * A function used to create a new raster object.
+ *
+ * @input:
+ * memory ::
+ * A handle to the memory allocator.
+ *
+ * @output:
+ * raster ::
+ * A handle to the new raster object.
+ *
+ * @return:
+ * Error code. 0~means success.
+ *
+ * @note:
+ * The `memory` parameter is a typeless pointer in order to avoid
+ * un-wanted dependencies on the rest of the FreeType code. In practice,
+ * it is an @FT_Memory object, i.e., a handle to the standard FreeType
+ * memory allocator. However, this field can be completely ignored by a
+ * given raster implementation.
+ */
typedef int
(*FT_Raster_NewFunc)( void* memory,
FT_Raster* raster );
@@ -1040,49 +1069,52 @@ FT_BEGIN_HEADER
#define FT_Raster_New_Func FT_Raster_NewFunc
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* FT_Raster_DoneFunc */
- /* */
- /* <Description> */
- /* A function used to destroy a given raster object. */
- /* */
- /* <Input> */
- /* raster :: A handle to the raster object. */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_Raster_DoneFunc
+ *
+ * @description:
+ * A function used to destroy a given raster object.
+ *
+ * @input:
+ * raster ::
+ * A handle to the raster object.
+ */
typedef void
(*FT_Raster_DoneFunc)( FT_Raster raster );
#define FT_Raster_Done_Func FT_Raster_DoneFunc
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* FT_Raster_ResetFunc */
- /* */
- /* <Description> */
- /* FreeType used to provide an area of memory called the `render */
- /* pool' available to all registered rasterizers. This was not */
- /* thread safe, however, and now FreeType never allocates this pool. */
- /* */
- /* This function is called after a new raster object is created. */
- /* */
- /* <Input> */
- /* raster :: A handle to the new raster object. */
- /* */
- /* pool_base :: Previously, the address in memory of the render pool. */
- /* Set this to NULL. */
- /* */
- /* pool_size :: Previously, the size in bytes of the render pool. */
- /* Set this to 0. */
- /* */
- /* <Note> */
- /* Rasterizers should rely on dynamic or stack allocation if they */
- /* want to (a handle to the memory allocator is passed to the */
- /* rasterizer constructor). */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_Raster_ResetFunc
+ *
+ * @description:
+ * FreeType used to provide an area of memory called the 'render pool'
+ * available to all registered rasterizers. This was not thread safe,
+ * however, and now FreeType never allocates this pool.
+ *
+ * This function is called after a new raster object is created.
+ *
+ * @input:
+ * raster ::
+ * A handle to the new raster object.
+ *
+ * pool_base ::
+ * Previously, the address in memory of the render pool. Set this to
+ * `NULL`.
+ *
+ * pool_size ::
+ * Previously, the size in bytes of the render pool. Set this to 0.
+ *
+ * @note:
+ * Rasterizers should rely on dynamic or stack allocation if they want to
+ * (a handle to the memory allocator is passed to the rasterizer
+ * constructor).
+ */
typedef void
(*FT_Raster_ResetFunc)( FT_Raster raster,
unsigned char* pool_base,
@@ -1091,24 +1123,26 @@ FT_BEGIN_HEADER
#define FT_Raster_Reset_Func FT_Raster_ResetFunc
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* FT_Raster_SetModeFunc */
- /* */
- /* <Description> */
- /* This function is a generic facility to change modes or attributes */
- /* in a given raster. This can be used for debugging purposes, or */
- /* simply to allow implementation-specific `features' in a given */
- /* raster module. */
- /* */
- /* <Input> */
- /* raster :: A handle to the new raster object. */
- /* */
- /* mode :: A 4-byte tag used to name the mode or property. */
- /* */
- /* args :: A pointer to the new mode/property to use. */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_Raster_SetModeFunc
+ *
+ * @description:
+ * This function is a generic facility to change modes or attributes in a
+ * given raster. This can be used for debugging purposes, or simply to
+ * allow implementation-specific 'features' in a given raster module.
+ *
+ * @input:
+ * raster ::
+ * A handle to the new raster object.
+ *
+ * mode ::
+ * A 4-byte tag used to name the mode or property.
+ *
+ * args ::
+ * A pointer to the new mode/property to use.
+ */
typedef int
(*FT_Raster_SetModeFunc)( FT_Raster raster,
unsigned long mode,
@@ -1117,40 +1151,36 @@ FT_BEGIN_HEADER
#define FT_Raster_Set_Mode_Func FT_Raster_SetModeFunc
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* FT_Raster_RenderFunc */
- /* */
- /* <Description> */
- /* Invoke a given raster to scan-convert a given glyph image into a */
- /* target bitmap. */
- /* */
- /* <Input> */
- /* raster :: A handle to the raster object. */
- /* */
- /* params :: A pointer to an @FT_Raster_Params structure used to */
- /* store the rendering parameters. */
- /* */
- /* <Return> */
- /* Error code. 0~means success. */
- /* */
- /* <Note> */
- /* The exact format of the source image depends on the raster's glyph */
- /* format defined in its @FT_Raster_Funcs structure. It can be an */
- /* @FT_Outline or anything else in order to support a large array of */
- /* glyph formats. */
- /* */
- /* Note also that the render function can fail and return a */
- /* `FT_Err_Unimplemented_Feature' error code if the raster used does */
- /* not support direct composition. */
- /* */
- /* XXX: For now, the standard raster doesn't support direct */
- /* composition but this should change for the final release (see */
- /* the files `demos/src/ftgrays.c' and `demos/src/ftgrays2.c' */
- /* for examples of distinct implementations that support direct */
- /* composition). */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_Raster_RenderFunc
+ *
+ * @description:
+ * Invoke a given raster to scan-convert a given glyph image into a
+ * target bitmap.
+ *
+ * @input:
+ * raster ::
+ * A handle to the raster object.
+ *
+ * params ::
+ * A pointer to an @FT_Raster_Params structure used to store the
+ * rendering parameters.
+ *
+ * @return:
+ * Error code. 0~means success.
+ *
+ * @note:
+ * The exact format of the source image depends on the raster's glyph
+ * format defined in its @FT_Raster_Funcs structure. It can be an
+ * @FT_Outline or anything else in order to support a large array of
+ * glyph formats.
+ *
+ * Note also that the render function can fail and return a
+ * `FT_Err_Unimplemented_Feature` error code if the raster used does not
+ * support direct composition.
+ */
typedef int
(*FT_Raster_RenderFunc)( FT_Raster raster,
const FT_Raster_Params* params );
@@ -1158,25 +1188,30 @@ FT_BEGIN_HEADER
#define FT_Raster_Render_Func FT_Raster_RenderFunc
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_Raster_Funcs */
- /* */
- /* <Description> */
- /* A structure used to describe a given raster class to the library. */
- /* */
- /* <Fields> */
- /* glyph_format :: The supported glyph format for this raster. */
- /* */
- /* raster_new :: The raster constructor. */
- /* */
- /* raster_reset :: Used to reset the render pool within the raster. */
- /* */
- /* raster_render :: A function to render a glyph into a given bitmap. */
- /* */
- /* raster_done :: The raster destructor. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Raster_Funcs
+ *
+ * @description:
+ * A structure used to describe a given raster class to the library.
+ *
+ * @fields:
+ * glyph_format ::
+ * The supported glyph format for this raster.
+ *
+ * raster_new ::
+ * The raster constructor.
+ *
+ * raster_reset ::
+ * Used to reset the render pool within the raster.
+ *
+ * raster_render ::
+ * A function to render a glyph into a given bitmap.
+ *
+ * raster_done ::
+ * The raster destructor.
+ */
typedef struct FT_Raster_Funcs_
{
FT_Glyph_Format glyph_format;
diff --git a/thirdparty/freetype/include/freetype/ftincrem.h b/thirdparty/freetype/include/freetype/ftincrem.h
index 44619f941e..a4db02b585 100644
--- a/thirdparty/freetype/include/freetype/ftincrem.h
+++ b/thirdparty/freetype/include/freetype/ftincrem.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftincrem.h */
-/* */
-/* FreeType incremental loading (specification). */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftincrem.h
+ *
+ * FreeType incremental loading (specification).
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTINCREM_H_
@@ -32,7 +32,7 @@
FT_BEGIN_HEADER
- /***************************************************************************
+ /**************************************************************************
*
* @section:
* incremental
@@ -45,7 +45,7 @@ FT_BEGIN_HEADER
*
* @description:
* This section contains various functions used to perform so-called
- * `incremental' glyph loading. This is a mode where all glyphs loaded
+ * 'incremental' glyph loading. This is a mode where all glyphs loaded
* from a given @FT_Face are provided by the client application.
*
* Apart from that, all other tables are loaded normally from the font
@@ -60,23 +60,24 @@ FT_BEGIN_HEADER
*/
- /***************************************************************************
+ /**************************************************************************
*
* @type:
* FT_Incremental
*
* @description:
* An opaque type describing a user-provided object used to implement
- * `incremental' glyph loading within FreeType. This is used to support
- * embedded fonts in certain environments (e.g., PostScript interpreters),
- * where the glyph data isn't in the font file, or must be overridden by
- * different values.
+ * 'incremental' glyph loading within FreeType. This is used to support
+ * embedded fonts in certain environments (e.g., PostScript
+ * interpreters), where the glyph data isn't in the font file, or must be
+ * overridden by different values.
*
* @note:
- * It is up to client applications to create and implement @FT_Incremental
- * objects, as long as they provide implementations for the methods
- * @FT_Incremental_GetGlyphDataFunc, @FT_Incremental_FreeGlyphDataFunc
- * and @FT_Incremental_GetGlyphMetricsFunc.
+ * It is up to client applications to create and implement
+ * @FT_Incremental objects, as long as they provide implementations for
+ * the methods @FT_Incremental_GetGlyphDataFunc,
+ * @FT_Incremental_FreeGlyphDataFunc and
+ * @FT_Incremental_GetGlyphMetricsFunc.
*
* See the description of @FT_Incremental_InterfaceRec to understand how
* to use incremental objects with FreeType.
@@ -85,14 +86,14 @@ FT_BEGIN_HEADER
typedef struct FT_IncrementalRec_* FT_Incremental;
- /***************************************************************************
+ /**************************************************************************
*
* @struct:
* FT_Incremental_MetricsRec
*
* @description:
- * A small structure used to contain the basic glyph metrics returned
- * by the @FT_Incremental_GetGlyphMetricsFunc method.
+ * A small structure used to contain the basic glyph metrics returned by
+ * the @FT_Incremental_GetGlyphMetricsFunc method.
*
* @fields:
* bearing_x ::
@@ -109,7 +110,7 @@ FT_BEGIN_HEADER
*
* @note:
* These correspond to horizontal or vertical metrics depending on the
- * value of the `vertical' argument to the function
+ * value of the `vertical` argument to the function
* @FT_Incremental_GetGlyphMetricsFunc.
*
*/
@@ -123,7 +124,7 @@ FT_BEGIN_HEADER
} FT_Incremental_MetricsRec;
- /***************************************************************************
+ /**************************************************************************
*
* @struct:
* FT_Incremental_Metrics
@@ -135,7 +136,7 @@ FT_BEGIN_HEADER
typedef struct FT_Incremental_MetricsRec_* FT_Incremental_Metrics;
- /***************************************************************************
+ /**************************************************************************
*
* @type:
* FT_Incremental_GetGlyphDataFunc
@@ -147,8 +148,8 @@ FT_BEGIN_HEADER
*
* Note that the format of the glyph's data bytes depends on the font
* file format. For TrueType, it must correspond to the raw bytes within
- * the `glyf' table. For PostScript formats, it must correspond to the
- * *unencrypted* charstring bytes, without any `lenIV' header. It is
+ * the 'glyf' table. For PostScript formats, it must correspond to the
+ * **unencrypted** charstring bytes, without any `lenIV` header. It is
* undefined for any other format.
*
* @input:
@@ -169,8 +170,8 @@ FT_BEGIN_HEADER
*
* @note:
* If this function returns successfully the method
- * @FT_Incremental_FreeGlyphDataFunc will be called later to release
- * the data bytes.
+ * @FT_Incremental_FreeGlyphDataFunc will be called later to release the
+ * data bytes.
*
* Nested calls to @FT_Incremental_GetGlyphDataFunc can happen for
* compound glyphs.
@@ -182,7 +183,7 @@ FT_BEGIN_HEADER
FT_Data* adata );
- /***************************************************************************
+ /**************************************************************************
*
* @type:
* FT_Incremental_FreeGlyphDataFunc
@@ -206,7 +207,7 @@ FT_BEGIN_HEADER
FT_Data* data );
- /***************************************************************************
+ /**************************************************************************
*
* @type:
* FT_Incremental_GetGlyphMetricsFunc
@@ -214,8 +215,8 @@ FT_BEGIN_HEADER
* @description:
* A function used to retrieve the basic metrics of a given glyph index
* before accessing its data. This is necessary because, in certain
- * formats like TrueType, the metrics are stored in a different place from
- * the glyph images proper.
+ * formats like TrueType, the metrics are stored in a different place
+ * from the glyph images proper.
*
* @input:
* incremental ::
@@ -229,9 +230,9 @@ FT_BEGIN_HEADER
* If true, return vertical metrics.
*
* ametrics ::
- * This parameter is used for both input and output.
- * The original glyph metrics, if any, in font units. If metrics are
- * not available all the values must be set to zero.
+ * This parameter is used for both input and output. The original
+ * glyph metrics, if any, in font units. If metrics are not available
+ * all the values must be set to zero.
*
* @output:
* ametrics ::
@@ -252,8 +253,8 @@ FT_BEGIN_HEADER
* FT_Incremental_FuncsRec
*
* @description:
- * A table of functions for accessing fonts that load data
- * incrementally. Used in @FT_Incremental_InterfaceRec.
+ * A table of functions for accessing fonts that load data incrementally.
+ * Used in @FT_Incremental_InterfaceRec.
*
* @fields:
* get_glyph_data ::
@@ -263,8 +264,8 @@ FT_BEGIN_HEADER
* The function to release glyph data. Must not be null.
*
* get_glyph_metrics ::
- * The function to get glyph metrics. May be null if the font does
- * not provide overriding glyph metrics.
+ * The function to get glyph metrics. May be null if the font does not
+ * provide overriding glyph metrics.
*
*/
typedef struct FT_Incremental_FuncsRec_
@@ -276,7 +277,7 @@ FT_BEGIN_HEADER
} FT_Incremental_FuncsRec;
- /***************************************************************************
+ /**************************************************************************
*
* @struct:
* FT_Incremental_InterfaceRec
@@ -286,30 +287,30 @@ FT_BEGIN_HEADER
* wants to support incremental glyph loading. You should use it with
* @FT_PARAM_TAG_INCREMENTAL as in the following example:
*
- * {
- * FT_Incremental_InterfaceRec inc_int;
- * FT_Parameter parameter;
- * FT_Open_Args open_args;
+ * ```
+ * FT_Incremental_InterfaceRec inc_int;
+ * FT_Parameter parameter;
+ * FT_Open_Args open_args;
*
*
- * // set up incremental descriptor
- * inc_int.funcs = my_funcs;
- * inc_int.object = my_object;
+ * // set up incremental descriptor
+ * inc_int.funcs = my_funcs;
+ * inc_int.object = my_object;
*
- * // set up optional parameter
- * parameter.tag = FT_PARAM_TAG_INCREMENTAL;
- * parameter.data = &inc_int;
+ * // set up optional parameter
+ * parameter.tag = FT_PARAM_TAG_INCREMENTAL;
+ * parameter.data = &inc_int;
*
- * // set up FT_Open_Args structure
- * open_args.flags = FT_OPEN_PATHNAME | FT_OPEN_PARAMS;
- * open_args.pathname = my_font_pathname;
- * open_args.num_params = 1;
- * open_args.params = &parameter; // we use one optional argument
+ * // set up FT_Open_Args structure
+ * open_args.flags = FT_OPEN_PATHNAME | FT_OPEN_PARAMS;
+ * open_args.pathname = my_font_pathname;
+ * open_args.num_params = 1;
+ * open_args.params = &parameter; // we use one optional argument
*
- * // open the font
- * error = FT_Open_Face( library, &open_args, index, &face );
- * ...
- * }
+ * // open the font
+ * error = FT_Open_Face( library, &open_args, index, &face );
+ * ...
+ * ```
*
*/
typedef struct FT_Incremental_InterfaceRec_
@@ -320,7 +321,7 @@ FT_BEGIN_HEADER
} FT_Incremental_InterfaceRec;
- /***************************************************************************
+ /**************************************************************************
*
* @type:
* FT_Incremental_Interface
diff --git a/thirdparty/freetype/include/freetype/ftlcdfil.h b/thirdparty/freetype/include/freetype/ftlcdfil.h
index 2a27196cbb..3a19d043bb 100644
--- a/thirdparty/freetype/include/freetype/ftlcdfil.h
+++ b/thirdparty/freetype/include/freetype/ftlcdfil.h
@@ -1,20 +1,20 @@
-/***************************************************************************/
-/* */
-/* ftlcdfil.h */
-/* */
-/* FreeType API for color filtering of subpixel bitmap glyphs */
-/* (specification). */
-/* */
-/* Copyright 2006-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftlcdfil.h
+ *
+ * FreeType API for color filtering of subpixel bitmap glyphs
+ * (specification).
+ *
+ * Copyright (C) 2006-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTLCDFIL_H_
@@ -33,105 +33,98 @@
FT_BEGIN_HEADER
- /***************************************************************************
+ /**************************************************************************
*
* @section:
- * lcd_filtering
+ * lcd_rendering
*
* @title:
- * LCD Filtering
+ * Subpixel Rendering
*
* @abstract:
- * Reduce color fringes of subpixel-rendered bitmaps.
+ * API to control subpixel rendering.
*
* @description:
- * Should you #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING in your
- * `ftoption.h', which enables patented ClearType-style rendering,
- * the LCD-optimized glyph bitmaps should be filtered to reduce color
- * fringes inherent to this technology. The default FreeType LCD
- * rendering uses different technology, and API described below,
- * although available, does nothing.
+ * FreeType provides two alternative subpixel rendering technologies.
+ * Should you define `FT_CONFIG_OPTION_SUBPIXEL_RENDERING` in your
+ * `ftoption.h` file, this enables patented ClearType-style rendering.
+ * Otherwise, Harmony LCD rendering is enabled. These technologies are
+ * controlled differently and API described below, although always
+ * available, performs its function when appropriate method is enabled
+ * and does nothing otherwise.
*
* ClearType-style LCD rendering exploits the color-striped structure of
* LCD pixels, increasing the available resolution in the direction of
- * the stripe (usually horizontal RGB) by a factor of~3. Since these
- * subpixels are color pixels, using them unfiltered creates severe
- * color fringes. Use the @FT_Library_SetLcdFilter API to specify a
- * low-pass filter, which is then applied to subpixel-rendered bitmaps
- * generated through @FT_Render_Glyph. The filter sacrifices some of
- * the higher resolution to reduce color fringes, making the glyph image
- * slightly blurrier. Positional improvements will remain.
- *
- * A filter should have two properties:
- *
- * 1) It should be normalized, meaning the sum of the 5~components
- * should be 256 (0x100). It is possible to go above or under this
- * target sum, however: going under means tossing out contrast, going
- * over means invoking clamping and thereby non-linearities that
- * increase contrast somewhat at the expense of greater distortion
- * and color-fringing. Contrast is better enhanced through stem
- * darkening.
- *
- * 2) It should be color-balanced, meaning a filter `{~a, b, c, b, a~}'
- * where a~+ b~=~c. It distributes the computed coverage for one
- * subpixel to all subpixels equally, sacrificing some won resolution
- * but drastically reducing color-fringing. Positioning improvements
- * remain! Note that color-fringing can only really be minimized
- * when using a color-balanced filter and alpha-blending the glyph
- * onto a surface in linear space; see @FT_Render_Glyph.
- *
- * Regarding the form, a filter can be a `boxy' filter or a `beveled'
- * filter. Boxy filters are sharper but are less forgiving of non-ideal
- * gamma curves of a screen (viewing angles!), beveled filters are
- * fuzzier but more tolerant.
- *
- * Examples:
- *
- * - [0x10 0x40 0x70 0x40 0x10] is beveled and neither balanced nor
- * normalized.
- *
- * - [0x1A 0x33 0x4D 0x33 0x1A] is beveled and balanced but not
- * normalized.
- *
- * - [0x19 0x33 0x66 0x4c 0x19] is beveled and normalized but not
- * balanced.
- *
- * - [0x00 0x4c 0x66 0x4c 0x00] is boxily beveled and normalized but not
- * balanced.
- *
- * - [0x00 0x55 0x56 0x55 0x00] is boxy, normalized, and almost
- * balanced.
- *
- * - [0x08 0x4D 0x56 0x4D 0x08] is beveled, normalized and, almost
- * balanced.
- *
- * The filter affects glyph bitmaps rendered through @FT_Render_Glyph,
- * @FT_Load_Glyph, and @FT_Load_Char. It does _not_ affect the output
- * of @FT_Outline_Render and @FT_Outline_Get_Bitmap.
- *
- * If this feature is activated, the dimensions of LCD glyph bitmaps are
- * either wider or taller than the dimensions of the corresponding
- * outline with regard to the pixel grid. For example, for
- * @FT_RENDER_MODE_LCD, the filter adds 3~subpixels to the left, and
- * 3~subpixels to the right. The bitmap offset values are adjusted
- * accordingly, so clients shouldn't need to modify their layout and
- * glyph positioning code when enabling the filter.
- *
- * It is important to understand that linear alpha blending and gamma
- * correction is critical for correctly rendering glyphs onto surfaces
- * without artifacts and even more critical when subpixel rendering is
- * involved.
- *
- * Each of the 3~alpha values (subpixels) is independently used to blend
- * one color channel. That is, red alpha blends the red channel of the
- * text color with the red channel of the background pixel. The
- * distribution of density values by the color-balanced filter assumes
- * alpha blending is done in linear space; only then color artifacts
- * cancel out.
+ * the stripe (usually horizontal RGB) by a factor of~3. Using the
+ * subpixels coverages unfiltered can create severe color fringes
+ * especially when rendering thin features. Indeed, to produce
+ * black-on-white text, the nearby color subpixels must be dimmed
+ * equally.
+ *
+ * A good 5-tap FIR filter should be applied to subpixel coverages
+ * regardless of pixel boundaries and should have these properties:
+ *
+ * 1. It should be symmetrical, like {~a, b, c, b, a~}, to avoid
+ * any shifts in appearance.
+ *
+ * 2. It should be color-balanced, meaning a~+ b~=~c, to reduce color
+ * fringes by distributing the computed coverage for one subpixel to
+ * all subpixels equally.
+ *
+ * 3. It should be normalized, meaning 2a~+ 2b~+ c~=~1.0 to maintain
+ * overall brightness.
+ *
+ * Boxy 3-tap filter {0, 1/3, 1/3, 1/3, 0} is sharper but is less
+ * forgiving of non-ideal gamma curves of a screen (and viewing angles),
+ * beveled filters are fuzzier but more tolerant.
+ *
+ * Use the @FT_Library_SetLcdFilter or @FT_Library_SetLcdFilterWeights
+ * API to specify a low-pass filter, which is then applied to
+ * subpixel-rendered bitmaps generated through @FT_Render_Glyph.
+ *
+ * Harmony LCD rendering is suitable to panels with any regular subpixel
+ * structure, not just monitors with 3 color striped subpixels, as long
+ * as the color subpixels have fixed positions relative to the pixel
+ * center. In this case, each color channel is then rendered separately
+ * after shifting the outline opposite to the subpixel shift so that the
+ * coverage maps are aligned. This method is immune to color fringes
+ * because the shifts do not change integral coverage.
+ *
+ * The subpixel geometry must be specified by xy-coordinates for each
+ * subpixel. By convention they may come in the RGB order: {{-1/3, 0},
+ * {0, 0}, {1/3, 0}} for standard RGB striped panel or {{-1/6, 1/4},
+ * {-1/6, -1/4}, {1/3, 0}} for a certain PenTile panel.
+ *
+ * Use the @FT_Library_SetLcdGeometry API to specify subpixel positions.
+ * If one follows the RGB order convention, the same order applies to the
+ * resulting @FT_PIXEL_MODE_LCD and @FT_PIXEL_MODE_LCD_V bitmaps. Note,
+ * however, that the coordinate frame for the latter must be rotated
+ * clockwise. Harmony with default LCD geometry is equivalent to
+ * ClearType with light filter.
+ *
+ * As a result of ClearType filtering or Harmony rendering, the
+ * dimensions of LCD bitmaps can be either wider or taller than the
+ * dimensions of the corresponding outline with regard to the pixel grid.
+ * For example, for @FT_RENDER_MODE_LCD, the filter adds 2~subpixels to
+ * the left, and 2~subpixels to the right. The bitmap offset values are
+ * adjusted accordingly, so clients shouldn't need to modify their layout
+ * and glyph positioning code when enabling the filter.
+ *
+ * The ClearType and Harmony rendering is applicable to glyph bitmaps
+ * rendered through @FT_Render_Glyph, @FT_Load_Glyph, @FT_Load_Char, and
+ * @FT_Glyph_To_Bitmap, when @FT_RENDER_MODE_LCD or @FT_RENDER_MODE_LCD_V
+ * is specified. This API does not control @FT_Outline_Render and
+ * @FT_Outline_Get_Bitmap.
+ *
+ * The described algorithms can completely remove color artefacts when
+ * combined with gamma-corrected alpha blending in linear space. Each of
+ * the 3~alpha values (subpixels) must by independently used to blend one
+ * color channel. That is, red alpha blends the red channel of the text
+ * color with the red channel of the background pixel.
*/
- /****************************************************************************
+ /**************************************************************************
*
* @enum:
* FT_LcdFilter
@@ -145,47 +138,25 @@ FT_BEGIN_HEADER
* results in sometimes severe color fringes.
*
* FT_LCD_FILTER_DEFAULT ::
- * The default filter reduces color fringes considerably, at the cost
- * of a slight blurriness in the output.
- *
- * It is a beveled, normalized, and color-balanced five-tap filter
- * that is more forgiving to screens with non-ideal gamma curves and
- * viewing angles. Note that while color-fringing is reduced, it can
- * only be minimized by using linear alpha blending and gamma
- * correction to render glyphs onto surfaces. The default filter
- * weights are [0x08 0x4D 0x56 0x4D 0x08].
+ * This is a beveled, normalized, and color-balanced five-tap filter
+ * with weights of [0x08 0x4D 0x56 0x4D 0x08] in 1/256th units.
*
* FT_LCD_FILTER_LIGHT ::
- * The light filter is a variant that is sharper at the cost of
- * slightly more color fringes than the default one.
- *
- * It is a boxy, normalized, and color-balanced three-tap filter that
- * is less forgiving to screens with non-ideal gamma curves and
- * viewing angles. This filter works best when the rendering system
- * uses linear alpha blending and gamma correction to render glyphs
- * onto surfaces. The light filter weights are
- * [0x00 0x55 0x56 0x55 0x00].
+ * this is a boxy, normalized, and color-balanced three-tap filter with
+ * weights of [0x00 0x55 0x56 0x55 0x00] in 1/256th units.
*
* FT_LCD_FILTER_LEGACY ::
+ * FT_LCD_FILTER_LEGACY1 ::
* This filter corresponds to the original libXft color filter. It
* provides high contrast output but can exhibit really bad color
* fringes if glyphs are not extremely well hinted to the pixel grid.
- * In other words, it only works well if the TrueType bytecode
- * interpreter is enabled *and* high-quality hinted fonts are used.
- *
* This filter is only provided for comparison purposes, and might be
- * disabled or stay unsupported in the future.
- *
- * FT_LCD_FILTER_LEGACY1 ::
- * For historical reasons, the FontConfig library returns a different
- * enumeration value for legacy LCD filtering. To make code work that
- * (incorrectly) forwards FontConfig's enumeration value to
- * @FT_Library_SetLcdFilter without proper mapping, it is thus easiest
- * to have another enumeration value, which is completely equal to
- * `FT_LCD_FILTER_LEGACY'.
+ * disabled or stay unsupported in the future. The second value is
+ * provided for compatibility with FontConfig, which historically used
+ * different enumeration, sometimes incorrectly forwarded to FreeType.
*
* @since:
- * 2.3.0 (`FT_LCD_FILTER_LEGACY1' since 2.6.2)
+ * 2.3.0 (`FT_LCD_FILTER_LEGACY1` since 2.6.2)
*/
typedef enum FT_LcdFilter_
{
@@ -202,7 +173,7 @@ FT_BEGIN_HEADER
/**************************************************************************
*
- * @func:
+ * @function:
* FT_Library_SetLcdFilter
*
* @description:
@@ -218,20 +189,20 @@ FT_BEGIN_HEADER
* The filter type.
*
* You can use @FT_LCD_FILTER_NONE here to disable this feature, or
- * @FT_LCD_FILTER_DEFAULT to use a default filter that should work
- * well on most LCD screens.
+ * @FT_LCD_FILTER_DEFAULT to use a default filter that should work well
+ * on most LCD screens.
*
* @return:
* FreeType error code. 0~means success.
*
* @note:
* This feature is always disabled by default. Clients must make an
- * explicit call to this function with a `filter' value other than
+ * explicit call to this function with a `filter` value other than
* @FT_LCD_FILTER_NONE in order to enable it.
*
- * Due to *PATENTS* covering subpixel rendering, this function doesn't
- * do anything except returning `FT_Err_Unimplemented_Feature' if the
- * configuration macro FT_CONFIG_OPTION_SUBPIXEL_RENDERING is not
+ * Due to **PATENTS** covering subpixel rendering, this function doesn't
+ * do anything except returning `FT_Err_Unimplemented_Feature` if the
+ * configuration macro `FT_CONFIG_OPTION_SUBPIXEL_RENDERING` is not
* defined in your build of the library, which should correspond to all
* default builds of FreeType.
*
@@ -245,7 +216,7 @@ FT_BEGIN_HEADER
/**************************************************************************
*
- * @func:
+ * @function:
* FT_Library_SetLcdFilterWeights
*
* @description:
@@ -258,15 +229,15 @@ FT_BEGIN_HEADER
*
* weights ::
* A pointer to an array; the function copies the first five bytes and
- * uses them to specify the filter weights.
+ * uses them to specify the filter weights in 1/256th units.
*
* @return:
* FreeType error code. 0~means success.
*
* @note:
- * Due to *PATENTS* covering subpixel rendering, this function doesn't
- * do anything except returning `FT_Err_Unimplemented_Feature' if the
- * configuration macro FT_CONFIG_OPTION_SUBPIXEL_RENDERING is not
+ * Due to **PATENTS** covering subpixel rendering, this function doesn't
+ * do anything except returning `FT_Err_Unimplemented_Feature` if the
+ * configuration macro `FT_CONFIG_OPTION_SUBPIXEL_RENDERING` is not
* defined in your build of the library, which should correspond to all
* default builds of FreeType.
*
@@ -281,7 +252,8 @@ FT_BEGIN_HEADER
unsigned char *weights );
- /*
+ /**************************************************************************
+ *
* @type:
* FT_LcdFiveTapFilter
*
@@ -298,6 +270,53 @@ FT_BEGIN_HEADER
typedef FT_Byte FT_LcdFiveTapFilter[FT_LCD_FILTER_FIVE_TAPS];
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Library_SetLcdGeometry
+ *
+ * @description:
+ * This function can be used to modify default positions of color
+ * subpixels, which controls Harmony LCD rendering.
+ *
+ * @input:
+ * library ::
+ * A handle to the target library instance.
+ *
+ * sub ::
+ * A pointer to an array of 3 vectors in 26.6 fractional pixel format;
+ * the function modifies the default values, see the note below.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * Subpixel geometry examples:
+ *
+ * - {{-21, 0}, {0, 0}, {21, 0}} is the default, corresponding to 3 color
+ * stripes shifted by a third of a pixel. This could be an RGB panel.
+ *
+ * - {{21, 0}, {0, 0}, {-21, 0}} looks the same as the default but can
+ * specify a BGR panel instead, while keeping the bitmap in the same
+ * RGB888 format.
+ *
+ * - {{0, 21}, {0, 0}, {0, -21}} is the vertical RGB, but the bitmap
+ * stays RGB888 as a result.
+ *
+ * - {{-11, 16}, {-11, -16}, {22, 0}} is a certain PenTile arrangement.
+ *
+ * This function does nothing and returns `FT_Err_Unimplemented_Feature`
+ * in the context of ClearType-style subpixel rendering when
+ * `FT_CONFIG_OPTION_SUBPIXEL_RENDERING` is defined in your build of the
+ * library.
+ *
+ * @since:
+ * 2.10.0
+ */
+ FT_EXPORT( FT_Error )
+ FT_Library_SetLcdGeometry( FT_Library library,
+ FT_Vector sub[3] );
+
/* */
diff --git a/thirdparty/freetype/include/freetype/ftlist.h b/thirdparty/freetype/include/freetype/ftlist.h
index 117473b96a..4782892d1a 100644
--- a/thirdparty/freetype/include/freetype/ftlist.h
+++ b/thirdparty/freetype/include/freetype/ftlist.h
@@ -1,27 +1,27 @@
-/***************************************************************************/
-/* */
-/* ftlist.h */
-/* */
-/* Generic list support for FreeType (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* This file implements functions relative to list processing. Its */
- /* data structures are defined in `freetype.h'. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * ftlist.h
+ *
+ * Generic list support for FreeType (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * This file implements functions relative to list processing. Its data
+ * structures are defined in `freetype.h`.
+ *
+ */
#ifndef FTLIST_H_
@@ -41,224 +41,245 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* <Section> */
- /* list_processing */
- /* */
- /* <Title> */
- /* List Processing */
- /* */
- /* <Abstract> */
- /* Simple management of lists. */
- /* */
- /* <Description> */
- /* This section contains various definitions related to list */
- /* processing using doubly-linked nodes. */
- /* */
- /* <Order> */
- /* FT_List */
- /* FT_ListNode */
- /* FT_ListRec */
- /* FT_ListNodeRec */
- /* */
- /* FT_List_Add */
- /* FT_List_Insert */
- /* FT_List_Find */
- /* FT_List_Remove */
- /* FT_List_Up */
- /* FT_List_Iterate */
- /* FT_List_Iterator */
- /* FT_List_Finalize */
- /* FT_List_Destructor */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_List_Find */
- /* */
- /* <Description> */
- /* Find the list node for a given listed object. */
- /* */
- /* <Input> */
- /* list :: A pointer to the parent list. */
- /* data :: The address of the listed object. */
- /* */
- /* <Return> */
- /* List node. NULL if it wasn't found. */
- /* */
+ /**************************************************************************
+ *
+ * @section:
+ * list_processing
+ *
+ * @title:
+ * List Processing
+ *
+ * @abstract:
+ * Simple management of lists.
+ *
+ * @description:
+ * This section contains various definitions related to list processing
+ * using doubly-linked nodes.
+ *
+ * @order:
+ * FT_List
+ * FT_ListNode
+ * FT_ListRec
+ * FT_ListNodeRec
+ *
+ * FT_List_Add
+ * FT_List_Insert
+ * FT_List_Find
+ * FT_List_Remove
+ * FT_List_Up
+ * FT_List_Iterate
+ * FT_List_Iterator
+ * FT_List_Finalize
+ * FT_List_Destructor
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_List_Find
+ *
+ * @description:
+ * Find the list node for a given listed object.
+ *
+ * @input:
+ * list ::
+ * A pointer to the parent list.
+ * data ::
+ * The address of the listed object.
+ *
+ * @return:
+ * List node. `NULL` if it wasn't found.
+ */
FT_EXPORT( FT_ListNode )
FT_List_Find( FT_List list,
void* data );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_List_Add */
- /* */
- /* <Description> */
- /* Append an element to the end of a list. */
- /* */
- /* <InOut> */
- /* list :: A pointer to the parent list. */
- /* node :: The node to append. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_List_Add
+ *
+ * @description:
+ * Append an element to the end of a list.
+ *
+ * @inout:
+ * list ::
+ * A pointer to the parent list.
+ * node ::
+ * The node to append.
+ */
FT_EXPORT( void )
FT_List_Add( FT_List list,
FT_ListNode node );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_List_Insert */
- /* */
- /* <Description> */
- /* Insert an element at the head of a list. */
- /* */
- /* <InOut> */
- /* list :: A pointer to parent list. */
- /* node :: The node to insert. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_List_Insert
+ *
+ * @description:
+ * Insert an element at the head of a list.
+ *
+ * @inout:
+ * list ::
+ * A pointer to parent list.
+ * node ::
+ * The node to insert.
+ */
FT_EXPORT( void )
FT_List_Insert( FT_List list,
FT_ListNode node );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_List_Remove */
- /* */
- /* <Description> */
- /* Remove a node from a list. This function doesn't check whether */
- /* the node is in the list! */
- /* */
- /* <Input> */
- /* node :: The node to remove. */
- /* */
- /* <InOut> */
- /* list :: A pointer to the parent list. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_List_Remove
+ *
+ * @description:
+ * Remove a node from a list. This function doesn't check whether the
+ * node is in the list!
+ *
+ * @input:
+ * node ::
+ * The node to remove.
+ *
+ * @inout:
+ * list ::
+ * A pointer to the parent list.
+ */
FT_EXPORT( void )
FT_List_Remove( FT_List list,
FT_ListNode node );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_List_Up */
- /* */
- /* <Description> */
- /* Move a node to the head/top of a list. Used to maintain LRU */
- /* lists. */
- /* */
- /* <InOut> */
- /* list :: A pointer to the parent list. */
- /* node :: The node to move. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_List_Up
+ *
+ * @description:
+ * Move a node to the head/top of a list. Used to maintain LRU lists.
+ *
+ * @inout:
+ * list ::
+ * A pointer to the parent list.
+ * node ::
+ * The node to move.
+ */
FT_EXPORT( void )
FT_List_Up( FT_List list,
FT_ListNode node );
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* FT_List_Iterator */
- /* */
- /* <Description> */
- /* An FT_List iterator function that is called during a list parse */
- /* by @FT_List_Iterate. */
- /* */
- /* <Input> */
- /* node :: The current iteration list node. */
- /* */
- /* user :: A typeless pointer passed to @FT_List_Iterate. */
- /* Can be used to point to the iteration's state. */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_List_Iterator
+ *
+ * @description:
+ * An FT_List iterator function that is called during a list parse by
+ * @FT_List_Iterate.
+ *
+ * @input:
+ * node ::
+ * The current iteration list node.
+ *
+ * user ::
+ * A typeless pointer passed to @FT_List_Iterate. Can be used to point
+ * to the iteration's state.
+ */
typedef FT_Error
(*FT_List_Iterator)( FT_ListNode node,
void* user );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_List_Iterate */
- /* */
- /* <Description> */
- /* Parse a list and calls a given iterator function on each element. */
- /* Note that parsing is stopped as soon as one of the iterator calls */
- /* returns a non-zero value. */
- /* */
- /* <Input> */
- /* list :: A handle to the list. */
- /* iterator :: An iterator function, called on each node of the list. */
- /* user :: A user-supplied field that is passed as the second */
- /* argument to the iterator. */
- /* */
- /* <Return> */
- /* The result (a FreeType error code) of the last iterator call. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_List_Iterate
+ *
+ * @description:
+ * Parse a list and calls a given iterator function on each element.
+ * Note that parsing is stopped as soon as one of the iterator calls
+ * returns a non-zero value.
+ *
+ * @input:
+ * list ::
+ * A handle to the list.
+ * iterator ::
+ * An iterator function, called on each node of the list.
+ * user ::
+ * A user-supplied field that is passed as the second argument to the
+ * iterator.
+ *
+ * @return:
+ * The result (a FreeType error code) of the last iterator call.
+ */
FT_EXPORT( FT_Error )
FT_List_Iterate( FT_List list,
FT_List_Iterator iterator,
void* user );
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* FT_List_Destructor */
- /* */
- /* <Description> */
- /* An @FT_List iterator function that is called during a list */
- /* finalization by @FT_List_Finalize to destroy all elements in a */
- /* given list. */
- /* */
- /* <Input> */
- /* system :: The current system object. */
- /* */
- /* data :: The current object to destroy. */
- /* */
- /* user :: A typeless pointer passed to @FT_List_Iterate. It can */
- /* be used to point to the iteration's state. */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_List_Destructor
+ *
+ * @description:
+ * An @FT_List iterator function that is called during a list
+ * finalization by @FT_List_Finalize to destroy all elements in a given
+ * list.
+ *
+ * @input:
+ * system ::
+ * The current system object.
+ *
+ * data ::
+ * The current object to destroy.
+ *
+ * user ::
+ * A typeless pointer passed to @FT_List_Iterate. It can be used to
+ * point to the iteration's state.
+ */
typedef void
(*FT_List_Destructor)( FT_Memory memory,
void* data,
void* user );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_List_Finalize */
- /* */
- /* <Description> */
- /* Destroy all elements in the list as well as the list itself. */
- /* */
- /* <Input> */
- /* list :: A handle to the list. */
- /* */
- /* destroy :: A list destructor that will be applied to each element */
- /* of the list. Set this to NULL if not needed. */
- /* */
- /* memory :: The current memory object that handles deallocation. */
- /* */
- /* user :: A user-supplied field that is passed as the last */
- /* argument to the destructor. */
- /* */
- /* <Note> */
- /* This function expects that all nodes added by @FT_List_Add or */
- /* @FT_List_Insert have been dynamically allocated. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_List_Finalize
+ *
+ * @description:
+ * Destroy all elements in the list as well as the list itself.
+ *
+ * @input:
+ * list ::
+ * A handle to the list.
+ *
+ * destroy ::
+ * A list destructor that will be applied to each element of the list.
+ * Set this to `NULL` if not needed.
+ *
+ * memory ::
+ * The current memory object that handles deallocation.
+ *
+ * user ::
+ * A user-supplied field that is passed as the last argument to the
+ * destructor.
+ *
+ * @note:
+ * This function expects that all nodes added by @FT_List_Add or
+ * @FT_List_Insert have been dynamically allocated.
+ */
FT_EXPORT( void )
FT_List_Finalize( FT_List list,
FT_List_Destructor destroy,
diff --git a/thirdparty/freetype/include/freetype/ftlzw.h b/thirdparty/freetype/include/freetype/ftlzw.h
index 1615912d62..fd22968f5a 100644
--- a/thirdparty/freetype/include/freetype/ftlzw.h
+++ b/thirdparty/freetype/include/freetype/ftlzw.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftlzw.h */
-/* */
-/* LZW-compressed stream support. */
-/* */
-/* Copyright 2004-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftlzw.h
+ *
+ * LZW-compressed stream support.
+ *
+ * Copyright (C) 2004-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTLZW_H_
@@ -31,59 +31,60 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* <Section> */
- /* lzw */
- /* */
- /* <Title> */
- /* LZW Streams */
- /* */
- /* <Abstract> */
- /* Using LZW-compressed font files. */
- /* */
- /* <Description> */
- /* This section contains the declaration of LZW-specific functions. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * @section:
+ * lzw
+ *
+ * @title:
+ * LZW Streams
+ *
+ * @abstract:
+ * Using LZW-compressed font files.
+ *
+ * @description:
+ * This section contains the declaration of LZW-specific functions.
+ *
+ */
- /************************************************************************
- *
- * @function:
- * FT_Stream_OpenLZW
- *
- * @description:
- * Open a new stream to parse LZW-compressed font files. This is
- * mainly used to support the compressed `*.pcf.Z' fonts that come
- * with XFree86.
- *
- * @input:
- * stream :: The target embedding stream.
- *
- * source :: The source stream.
- *
- * @return:
- * FreeType error code. 0~means success.
- *
- * @note:
- * The source stream must be opened _before_ calling this function.
- *
- * Calling the internal function `FT_Stream_Close' on the new stream will
- * *not* call `FT_Stream_Close' on the source stream. None of the stream
- * objects will be released to the heap.
- *
- * The stream implementation is very basic and resets the decompression
- * process each time seeking backwards is needed within the stream
- *
- * In certain builds of the library, LZW compression recognition is
- * automatically handled when calling @FT_New_Face or @FT_Open_Face.
- * This means that if no font driver is capable of handling the raw
- * compressed file, the library will try to open a LZW stream from it
- * and re-open the face with it.
- *
- * This function may return `FT_Err_Unimplemented_Feature' if your build
- * of FreeType was not compiled with LZW support.
- */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Stream_OpenLZW
+ *
+ * @description:
+ * Open a new stream to parse LZW-compressed font files. This is mainly
+ * used to support the compressed `*.pcf.Z` fonts that come with XFree86.
+ *
+ * @input:
+ * stream ::
+ * The target embedding stream.
+ *
+ * source ::
+ * The source stream.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The source stream must be opened _before_ calling this function.
+ *
+ * Calling the internal function `FT_Stream_Close` on the new stream will
+ * **not** call `FT_Stream_Close` on the source stream. None of the
+ * stream objects will be released to the heap.
+ *
+ * The stream implementation is very basic and resets the decompression
+ * process each time seeking backwards is needed within the stream
+ *
+ * In certain builds of the library, LZW compression recognition is
+ * automatically handled when calling @FT_New_Face or @FT_Open_Face.
+ * This means that if no font driver is capable of handling the raw
+ * compressed file, the library will try to open a LZW stream from it and
+ * re-open the face with it.
+ *
+ * This function may return `FT_Err_Unimplemented_Feature` if your build
+ * of FreeType was not compiled with LZW support.
+ */
FT_EXPORT( FT_Error )
FT_Stream_OpenLZW( FT_Stream stream,
FT_Stream source );
diff --git a/thirdparty/freetype/include/freetype/ftmac.h b/thirdparty/freetype/include/freetype/ftmac.h
index c1e497ca2d..92b9f3dc0f 100644
--- a/thirdparty/freetype/include/freetype/ftmac.h
+++ b/thirdparty/freetype/include/freetype/ftmac.h
@@ -1,28 +1,28 @@
-/***************************************************************************/
-/* */
-/* ftmac.h */
-/* */
-/* Additional Mac-specific API. */
-/* */
-/* Copyright 1996-2018 by */
-/* Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftmac.h
+ *
+ * Additional Mac-specific API.
+ *
+ * Copyright (C) 1996-2019 by
+ * Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
-/***************************************************************************/
-/* */
-/* NOTE: Include this file after FT_FREETYPE_H and after any */
-/* Mac-specific headers (because this header uses Mac types such as */
-/* Handle, FSSpec, FSRef, etc.) */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * NOTE: Include this file after `FT_FREETYPE_H` and after any
+ * Mac-specific headers (because this header uses Mac types such as
+ * 'Handle', 'FSSpec', 'FSRef', etc.)
+ *
+ */
#ifndef FTMAC_H_
@@ -47,56 +47,59 @@ FT_BEGIN_HEADER
#endif
- /*************************************************************************/
- /* */
- /* <Section> */
- /* mac_specific */
- /* */
- /* <Title> */
- /* Mac Specific Interface */
- /* */
- /* <Abstract> */
- /* Only available on the Macintosh. */
- /* */
- /* <Description> */
- /* The following definitions are only available if FreeType is */
- /* compiled on a Macintosh. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * @section:
+ * mac_specific
+ *
+ * @title:
+ * Mac Specific Interface
+ *
+ * @abstract:
+ * Only available on the Macintosh.
+ *
+ * @description:
+ * The following definitions are only available if FreeType is compiled
+ * on a Macintosh.
+ *
+ */
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_New_Face_From_FOND */
- /* */
- /* <Description> */
- /* Create a new face object from a FOND resource. */
- /* */
- /* <InOut> */
- /* library :: A handle to the library resource. */
- /* */
- /* <Input> */
- /* fond :: A FOND resource. */
- /* */
- /* face_index :: Only supported for the -1 `sanity check' special */
- /* case. */
- /* */
- /* <Output> */
- /* aface :: A handle to a new face object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Notes> */
- /* This function can be used to create @FT_Face objects from fonts */
- /* that are installed in the system as follows. */
- /* */
- /* { */
- /* fond = GetResource( 'FOND', fontName ); */
- /* error = FT_New_Face_From_FOND( library, fond, 0, &face ); */
- /* } */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_New_Face_From_FOND
+ *
+ * @description:
+ * Create a new face object from a FOND resource.
+ *
+ * @inout:
+ * library ::
+ * A handle to the library resource.
+ *
+ * @input:
+ * fond ::
+ * A FOND resource.
+ *
+ * face_index ::
+ * Only supported for the -1 'sanity check' special case.
+ *
+ * @output:
+ * aface ::
+ * A handle to a new face object.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @example:
+ * This function can be used to create @FT_Face objects from fonts that
+ * are installed in the system as follows.
+ *
+ * ```
+ * fond = GetResource( 'FOND', fontName );
+ * error = FT_New_Face_From_FOND( library, fond, 0, &face );
+ * ```
+ */
FT_EXPORT( FT_Error )
FT_New_Face_From_FOND( FT_Library library,
Handle fond,
@@ -105,28 +108,28 @@ FT_BEGIN_HEADER
FT_DEPRECATED_ATTRIBUTE;
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_GetFile_From_Mac_Name */
- /* */
- /* <Description> */
- /* Return an FSSpec for the disk file containing the named font. */
- /* */
- /* <Input> */
- /* fontName :: Mac OS name of the font (e.g., Times New Roman */
- /* Bold). */
- /* */
- /* <Output> */
- /* pathSpec :: FSSpec to the file. For passing to */
- /* @FT_New_Face_From_FSSpec. */
- /* */
- /* face_index :: Index of the face. For passing to */
- /* @FT_New_Face_From_FSSpec. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_GetFile_From_Mac_Name
+ *
+ * @description:
+ * Return an FSSpec for the disk file containing the named font.
+ *
+ * @input:
+ * fontName ::
+ * Mac OS name of the font (e.g., Times New Roman Bold).
+ *
+ * @output:
+ * pathSpec ::
+ * FSSpec to the file. For passing to @FT_New_Face_From_FSSpec.
+ *
+ * face_index ::
+ * Index of the face. For passing to @FT_New_Face_From_FSSpec.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ */
FT_EXPORT( FT_Error )
FT_GetFile_From_Mac_Name( const char* fontName,
FSSpec* pathSpec,
@@ -134,27 +137,28 @@ FT_BEGIN_HEADER
FT_DEPRECATED_ATTRIBUTE;
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_GetFile_From_Mac_ATS_Name */
- /* */
- /* <Description> */
- /* Return an FSSpec for the disk file containing the named font. */
- /* */
- /* <Input> */
- /* fontName :: Mac OS name of the font in ATS framework. */
- /* */
- /* <Output> */
- /* pathSpec :: FSSpec to the file. For passing to */
- /* @FT_New_Face_From_FSSpec. */
- /* */
- /* face_index :: Index of the face. For passing to */
- /* @FT_New_Face_From_FSSpec. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_GetFile_From_Mac_ATS_Name
+ *
+ * @description:
+ * Return an FSSpec for the disk file containing the named font.
+ *
+ * @input:
+ * fontName ::
+ * Mac OS name of the font in ATS framework.
+ *
+ * @output:
+ * pathSpec ::
+ * FSSpec to the file. For passing to @FT_New_Face_From_FSSpec.
+ *
+ * face_index ::
+ * Index of the face. For passing to @FT_New_Face_From_FSSpec.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ */
FT_EXPORT( FT_Error )
FT_GetFile_From_Mac_ATS_Name( const char* fontName,
FSSpec* pathSpec,
@@ -162,30 +166,33 @@ FT_BEGIN_HEADER
FT_DEPRECATED_ATTRIBUTE;
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_GetFilePath_From_Mac_ATS_Name */
- /* */
- /* <Description> */
- /* Return a pathname of the disk file and face index for given font */
- /* name that is handled by ATS framework. */
- /* */
- /* <Input> */
- /* fontName :: Mac OS name of the font in ATS framework. */
- /* */
- /* <Output> */
- /* path :: Buffer to store pathname of the file. For passing */
- /* to @FT_New_Face. The client must allocate this */
- /* buffer before calling this function. */
- /* */
- /* maxPathSize :: Lengths of the buffer `path' that client allocated. */
- /* */
- /* face_index :: Index of the face. For passing to @FT_New_Face. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_GetFilePath_From_Mac_ATS_Name
+ *
+ * @description:
+ * Return a pathname of the disk file and face index for given font name
+ * that is handled by ATS framework.
+ *
+ * @input:
+ * fontName ::
+ * Mac OS name of the font in ATS framework.
+ *
+ * @output:
+ * path ::
+ * Buffer to store pathname of the file. For passing to @FT_New_Face.
+ * The client must allocate this buffer before calling this function.
+ *
+ * maxPathSize ::
+ * Lengths of the buffer `path` that client allocated.
+ *
+ * face_index ::
+ * Index of the face. For passing to @FT_New_Face.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ */
FT_EXPORT( FT_Error )
FT_GetFilePath_From_Mac_ATS_Name( const char* fontName,
UInt8* path,
@@ -194,33 +201,37 @@ FT_BEGIN_HEADER
FT_DEPRECATED_ATTRIBUTE;
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_New_Face_From_FSSpec */
- /* */
- /* <Description> */
- /* Create a new face object from a given resource and typeface index */
- /* using an FSSpec to the font file. */
- /* */
- /* <InOut> */
- /* library :: A handle to the library resource. */
- /* */
- /* <Input> */
- /* spec :: FSSpec to the font file. */
- /* */
- /* face_index :: The index of the face within the resource. The */
- /* first face has index~0. */
- /* <Output> */
- /* aface :: A handle to a new face object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* @FT_New_Face_From_FSSpec is identical to @FT_New_Face except */
- /* it accepts an FSSpec instead of a path. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_New_Face_From_FSSpec
+ *
+ * @description:
+ * Create a new face object from a given resource and typeface index
+ * using an FSSpec to the font file.
+ *
+ * @inout:
+ * library ::
+ * A handle to the library resource.
+ *
+ * @input:
+ * spec ::
+ * FSSpec to the font file.
+ *
+ * face_index ::
+ * The index of the face within the resource. The first face has
+ * index~0.
+ * @output:
+ * aface ::
+ * A handle to a new face object.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * @FT_New_Face_From_FSSpec is identical to @FT_New_Face except it
+ * accepts an FSSpec instead of a path.
+ */
FT_EXPORT( FT_Error )
FT_New_Face_From_FSSpec( FT_Library library,
const FSSpec *spec,
@@ -229,33 +240,37 @@ FT_BEGIN_HEADER
FT_DEPRECATED_ATTRIBUTE;
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_New_Face_From_FSRef */
- /* */
- /* <Description> */
- /* Create a new face object from a given resource and typeface index */
- /* using an FSRef to the font file. */
- /* */
- /* <InOut> */
- /* library :: A handle to the library resource. */
- /* */
- /* <Input> */
- /* spec :: FSRef to the font file. */
- /* */
- /* face_index :: The index of the face within the resource. The */
- /* first face has index~0. */
- /* <Output> */
- /* aface :: A handle to a new face object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* @FT_New_Face_From_FSRef is identical to @FT_New_Face except */
- /* it accepts an FSRef instead of a path. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_New_Face_From_FSRef
+ *
+ * @description:
+ * Create a new face object from a given resource and typeface index
+ * using an FSRef to the font file.
+ *
+ * @inout:
+ * library ::
+ * A handle to the library resource.
+ *
+ * @input:
+ * spec ::
+ * FSRef to the font file.
+ *
+ * face_index ::
+ * The index of the face within the resource. The first face has
+ * index~0.
+ * @output:
+ * aface ::
+ * A handle to a new face object.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * @FT_New_Face_From_FSRef is identical to @FT_New_Face except it accepts
+ * an FSRef instead of a path.
+ */
FT_EXPORT( FT_Error )
FT_New_Face_From_FSRef( FT_Library library,
const FSRef *ref,
diff --git a/thirdparty/freetype/include/freetype/ftmm.h b/thirdparty/freetype/include/freetype/ftmm.h
index 9948102c14..f2e16b6408 100644
--- a/thirdparty/freetype/include/freetype/ftmm.h
+++ b/thirdparty/freetype/include/freetype/ftmm.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftmm.h */
-/* */
-/* FreeType Multiple Master font interface (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftmm.h
+ *
+ * FreeType Multiple Master font interface (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTMM_H_
@@ -27,49 +27,52 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* <Section> */
- /* multiple_masters */
- /* */
- /* <Title> */
- /* Multiple Masters */
- /* */
- /* <Abstract> */
- /* How to manage Multiple Masters fonts. */
- /* */
- /* <Description> */
- /* The following types and functions are used to manage Multiple */
- /* Master fonts, i.e., the selection of specific design instances by */
- /* setting design axis coordinates. */
- /* */
- /* Besides Adobe MM fonts, the interface supports Apple's TrueType GX */
- /* and OpenType variation fonts. Some of the routines only work with */
- /* Adobe MM fonts, others will work with all three types. They are */
- /* similar enough that a consistent interface makes sense. */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_MM_Axis */
- /* */
- /* <Description> */
- /* A structure to model a given axis in design space for Multiple */
- /* Masters fonts. */
- /* */
- /* This structure can't be used for TrueType GX or OpenType variation */
- /* fonts. */
- /* */
- /* <Fields> */
- /* name :: The axis's name. */
- /* */
- /* minimum :: The axis's minimum design coordinate. */
- /* */
- /* maximum :: The axis's maximum design coordinate. */
- /* */
+ /**************************************************************************
+ *
+ * @section:
+ * multiple_masters
+ *
+ * @title:
+ * Multiple Masters
+ *
+ * @abstract:
+ * How to manage Multiple Masters fonts.
+ *
+ * @description:
+ * The following types and functions are used to manage Multiple Master
+ * fonts, i.e., the selection of specific design instances by setting
+ * design axis coordinates.
+ *
+ * Besides Adobe MM fonts, the interface supports Apple's TrueType GX and
+ * OpenType variation fonts. Some of the routines only work with Adobe
+ * MM fonts, others will work with all three types. They are similar
+ * enough that a consistent interface makes sense.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_MM_Axis
+ *
+ * @description:
+ * A structure to model a given axis in design space for Multiple Masters
+ * fonts.
+ *
+ * This structure can't be used for TrueType GX or OpenType variation
+ * fonts.
+ *
+ * @fields:
+ * name ::
+ * The axis's name.
+ *
+ * minimum ::
+ * The axis's minimum design coordinate.
+ *
+ * maximum ::
+ * The axis's maximum design coordinate.
+ */
typedef struct FT_MM_Axis_
{
FT_String* name;
@@ -79,28 +82,29 @@ FT_BEGIN_HEADER
} FT_MM_Axis;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_Multi_Master */
- /* */
- /* <Description> */
- /* A structure to model the axes and space of a Multiple Masters */
- /* font. */
- /* */
- /* This structure can't be used for TrueType GX or OpenType variation */
- /* fonts. */
- /* */
- /* <Fields> */
- /* num_axis :: Number of axes. Cannot exceed~4. */
- /* */
- /* num_designs :: Number of designs; should be normally 2^num_axis */
- /* even though the Type~1 specification strangely */
- /* allows for intermediate designs to be present. */
- /* This number cannot exceed~16. */
- /* */
- /* axis :: A table of axis descriptors. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Multi_Master
+ *
+ * @description:
+ * A structure to model the axes and space of a Multiple Masters font.
+ *
+ * This structure can't be used for TrueType GX or OpenType variation
+ * fonts.
+ *
+ * @fields:
+ * num_axis ::
+ * Number of axes. Cannot exceed~4.
+ *
+ * num_designs ::
+ * Number of designs; should be normally 2^num_axis even though the
+ * Type~1 specification strangely allows for intermediate designs to be
+ * present. This number cannot exceed~16.
+ *
+ * axis ::
+ * A table of axis descriptors.
+ */
typedef struct FT_Multi_Master_
{
FT_UInt num_axis;
@@ -110,42 +114,45 @@ FT_BEGIN_HEADER
} FT_Multi_Master;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_Var_Axis */
- /* */
- /* <Description> */
- /* A structure to model a given axis in design space for Multiple */
- /* Masters, TrueType GX, and OpenType variation fonts. */
- /* */
- /* <Fields> */
- /* name :: The axis's name. */
- /* Not always meaningful for TrueType GX or OpenType */
- /* variation fonts. */
- /* */
- /* minimum :: The axis's minimum design coordinate. */
- /* */
- /* def :: The axis's default design coordinate. */
- /* FreeType computes meaningful default values for Adobe */
- /* MM fonts. */
- /* */
- /* maximum :: The axis's maximum design coordinate. */
- /* */
- /* tag :: The axis's tag (the equivalent to `name' for TrueType */
- /* GX and OpenType variation fonts). FreeType provides */
- /* default values for Adobe MM fonts if possible. */
- /* */
- /* strid :: The axis name entry in the font's `name' table. This */
- /* is another (and often better) version of the `name' */
- /* field for TrueType GX or OpenType variation fonts. Not */
- /* meaningful for Adobe MM fonts. */
- /* */
- /* <Note> */
- /* The fields `minimum', `def', and `maximum' are 16.16 fractional */
- /* values for TrueType GX and OpenType variation fonts. For Adobe MM */
- /* fonts, the values are integers. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Var_Axis
+ *
+ * @description:
+ * A structure to model a given axis in design space for Multiple
+ * Masters, TrueType GX, and OpenType variation fonts.
+ *
+ * @fields:
+ * name ::
+ * The axis's name. Not always meaningful for TrueType GX or OpenType
+ * variation fonts.
+ *
+ * minimum ::
+ * The axis's minimum design coordinate.
+ *
+ * def ::
+ * The axis's default design coordinate. FreeType computes meaningful
+ * default values for Adobe MM fonts.
+ *
+ * maximum ::
+ * The axis's maximum design coordinate.
+ *
+ * tag ::
+ * The axis's tag (the equivalent to 'name' for TrueType GX and
+ * OpenType variation fonts). FreeType provides default values for
+ * Adobe MM fonts if possible.
+ *
+ * strid ::
+ * The axis name entry in the font's 'name' table. This is another
+ * (and often better) version of the 'name' field for TrueType GX or
+ * OpenType variation fonts. Not meaningful for Adobe MM fonts.
+ *
+ * @note:
+ * The fields `minimum`, `def`, and `maximum` are 16.16 fractional values
+ * for TrueType GX and OpenType variation fonts. For Adobe MM fonts, the
+ * values are integers.
+ */
typedef struct FT_Var_Axis_
{
FT_String* name;
@@ -160,27 +167,29 @@ FT_BEGIN_HEADER
} FT_Var_Axis;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_Var_Named_Style */
- /* */
- /* <Description> */
- /* A structure to model a named instance in a TrueType GX or OpenType */
- /* variation font. */
- /* */
- /* This structure can't be used for Adobe MM fonts. */
- /* */
- /* <Fields> */
- /* coords :: The design coordinates for this instance. */
- /* This is an array with one entry for each axis. */
- /* */
- /* strid :: The entry in `name' table identifying this instance. */
- /* */
- /* psid :: The entry in `name' table identifying a PostScript name */
- /* for this instance. Value 0xFFFF indicates a missing */
- /* entry. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Var_Named_Style
+ *
+ * @description:
+ * A structure to model a named instance in a TrueType GX or OpenType
+ * variation font.
+ *
+ * This structure can't be used for Adobe MM fonts.
+ *
+ * @fields:
+ * coords ::
+ * The design coordinates for this instance. This is an array with one
+ * entry for each axis.
+ *
+ * strid ::
+ * The entry in 'name' table identifying this instance.
+ *
+ * psid ::
+ * The entry in 'name' table identifying a PostScript name for this
+ * instance. Value 0xFFFF indicates a missing entry.
+ */
typedef struct FT_Var_Named_Style_
{
FT_Fixed* coords;
@@ -190,50 +199,47 @@ FT_BEGIN_HEADER
} FT_Var_Named_Style;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_MM_Var */
- /* */
- /* <Description> */
- /* A structure to model the axes and space of an Adobe MM, TrueType */
- /* GX, or OpenType variation font. */
- /* */
- /* Some fields are specific to one format and not to the others. */
- /* */
- /* <Fields> */
- /* num_axis :: The number of axes. The maximum value is~4 for */
- /* Adobe MM fonts; no limit in TrueType GX or */
- /* OpenType variation fonts. */
- /* */
- /* num_designs :: The number of designs; should be normally */
- /* 2^num_axis for Adobe MM fonts. Not meaningful */
- /* for TrueType GX or OpenType variation fonts */
- /* (where every glyph could have a different */
- /* number of designs). */
- /* */
- /* num_namedstyles :: The number of named styles; a `named style' is */
- /* a tuple of design coordinates that has a string */
- /* ID (in the `name' table) associated with it. */
- /* The font can tell the user that, for example, */
- /* [Weight=1.5,Width=1.1] is `Bold'. Another name */
- /* for `named style' is `named instance'. */
- /* */
- /* For Adobe Multiple Masters fonts, this value is */
- /* always zero because the format does not support */
- /* named styles. */
- /* */
- /* axis :: An axis descriptor table. */
- /* TrueType GX and OpenType variation fonts */
- /* contain slightly more data than Adobe MM fonts. */
- /* Memory management of this pointer is done */
- /* internally by FreeType. */
- /* */
- /* namedstyle :: A named style (instance) table. */
- /* Only meaningful for TrueType GX and OpenType */
- /* variation fonts. Memory management of this */
- /* pointer is done internally by FreeType. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_MM_Var
+ *
+ * @description:
+ * A structure to model the axes and space of an Adobe MM, TrueType GX,
+ * or OpenType variation font.
+ *
+ * Some fields are specific to one format and not to the others.
+ *
+ * @fields:
+ * num_axis ::
+ * The number of axes. The maximum value is~4 for Adobe MM fonts; no
+ * limit in TrueType GX or OpenType variation fonts.
+ *
+ * num_designs ::
+ * The number of designs; should be normally 2^num_axis for Adobe MM
+ * fonts. Not meaningful for TrueType GX or OpenType variation fonts
+ * (where every glyph could have a different number of designs).
+ *
+ * num_namedstyles ::
+ * The number of named styles; a 'named style' is a tuple of design
+ * coordinates that has a string ID (in the 'name' table) associated
+ * with it. The font can tell the user that, for example,
+ * [Weight=1.5,Width=1.1] is 'Bold'. Another name for 'named style' is
+ * 'named instance'.
+ *
+ * For Adobe Multiple Masters fonts, this value is always zero because
+ * the format does not support named styles.
+ *
+ * axis ::
+ * An axis descriptor table. TrueType GX and OpenType variation fonts
+ * contain slightly more data than Adobe MM fonts. Memory management
+ * of this pointer is done internally by FreeType.
+ *
+ * namedstyle ::
+ * A named style (instance) table. Only meaningful for TrueType GX and
+ * OpenType variation fonts. Memory management of this pointer is done
+ * internally by FreeType.
+ */
typedef struct FT_MM_Var_
{
FT_UInt num_axis;
@@ -245,384 +251,493 @@ FT_BEGIN_HEADER
} FT_MM_Var;
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Get_Multi_Master */
- /* */
- /* <Description> */
- /* Retrieve a variation descriptor of a given Adobe MM font. */
- /* */
- /* This function can't be used with TrueType GX or OpenType variation */
- /* fonts. */
- /* */
- /* <Input> */
- /* face :: A handle to the source face. */
- /* */
- /* <Output> */
- /* amaster :: The Multiple Masters descriptor. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Multi_Master
+ *
+ * @description:
+ * Retrieve a variation descriptor of a given Adobe MM font.
+ *
+ * This function can't be used with TrueType GX or OpenType variation
+ * fonts.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face.
+ *
+ * @output:
+ * amaster ::
+ * The Multiple Masters descriptor.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ */
FT_EXPORT( FT_Error )
FT_Get_Multi_Master( FT_Face face,
FT_Multi_Master *amaster );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Get_MM_Var */
- /* */
- /* <Description> */
- /* Retrieve a variation descriptor for a given font. */
- /* */
- /* This function works with all supported variation formats. */
- /* */
- /* <Input> */
- /* face :: A handle to the source face. */
- /* */
- /* <Output> */
- /* amaster :: The variation descriptor. */
- /* Allocates a data structure, which the user must */
- /* deallocate with a call to @FT_Done_MM_Var after use. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_MM_Var
+ *
+ * @description:
+ * Retrieve a variation descriptor for a given font.
+ *
+ * This function works with all supported variation formats.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face.
+ *
+ * @output:
+ * amaster ::
+ * The variation descriptor. Allocates a data structure, which the
+ * user must deallocate with a call to @FT_Done_MM_Var after use.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ */
FT_EXPORT( FT_Error )
FT_Get_MM_Var( FT_Face face,
FT_MM_Var* *amaster );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Done_MM_Var */
- /* */
- /* <Description> */
- /* Free the memory allocated by @FT_Get_MM_Var. */
- /* */
- /* <Input> */
- /* library :: A handle of the face's parent library object that was */
- /* used in the call to @FT_Get_MM_Var to create `amaster'. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Done_MM_Var
+ *
+ * @description:
+ * Free the memory allocated by @FT_Get_MM_Var.
+ *
+ * @input:
+ * library ::
+ * A handle of the face's parent library object that was used in the
+ * call to @FT_Get_MM_Var to create `amaster`.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ */
FT_EXPORT( FT_Error )
FT_Done_MM_Var( FT_Library library,
FT_MM_Var *amaster );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Set_MM_Design_Coordinates */
- /* */
- /* <Description> */
- /* For Adobe MM fonts, choose an interpolated font design through */
- /* design coordinates. */
- /* */
- /* This function can't be used with TrueType GX or OpenType variation */
- /* fonts. */
- /* */
- /* <InOut> */
- /* face :: A handle to the source face. */
- /* */
- /* <Input> */
- /* num_coords :: The number of available design coordinates. If it */
- /* is larger than the number of axes, ignore the excess */
- /* values. If it is smaller than the number of axes, */
- /* use default values for the remaining axes. */
- /* */
- /* coords :: An array of design coordinates. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* [Since 2.8.1] To reset all axes to the default values, call the */
- /* function with `num_coords' set to zero and `coords' set to NULL. */
- /* */
- /* [Since 2.9] If `num_coords' is larger than zero, this function */
- /* sets the @FT_FACE_FLAG_VARIATION bit in @FT_Face's `face_flags' */
- /* field (i.e., @FT_IS_VARIATION will return true). If `num_coords' */
- /* is zero, this bit flag gets unset. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Set_MM_Design_Coordinates
+ *
+ * @description:
+ * For Adobe MM fonts, choose an interpolated font design through design
+ * coordinates.
+ *
+ * This function can't be used with TrueType GX or OpenType variation
+ * fonts.
+ *
+ * @inout:
+ * face ::
+ * A handle to the source face.
+ *
+ * @input:
+ * num_coords ::
+ * The number of available design coordinates. If it is larger than
+ * the number of axes, ignore the excess values. If it is smaller than
+ * the number of axes, use default values for the remaining axes.
+ *
+ * coords ::
+ * An array of design coordinates.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * [Since 2.8.1] To reset all axes to the default values, call the
+ * function with `num_coords` set to zero and `coords` set to `NULL`.
+ *
+ * [Since 2.9] If `num_coords` is larger than zero, this function sets
+ * the @FT_FACE_FLAG_VARIATION bit in @FT_Face's `face_flags` field
+ * (i.e., @FT_IS_VARIATION will return true). If `num_coords` is zero,
+ * this bit flag gets unset.
+ */
FT_EXPORT( FT_Error )
FT_Set_MM_Design_Coordinates( FT_Face face,
FT_UInt num_coords,
FT_Long* coords );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Set_Var_Design_Coordinates */
- /* */
- /* <Description> */
- /* Choose an interpolated font design through design coordinates. */
- /* */
- /* This function works with all supported variation formats. */
- /* */
- /* <InOut> */
- /* face :: A handle to the source face. */
- /* */
- /* <Input> */
- /* num_coords :: The number of available design coordinates. If it */
- /* is larger than the number of axes, ignore the excess */
- /* values. If it is smaller than the number of axes, */
- /* use default values for the remaining axes. */
- /* */
- /* coords :: An array of design coordinates. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* [Since 2.8.1] To reset all axes to the default values, call the */
- /* function with `num_coords' set to zero and `coords' set to NULL. */
- /* [Since 2.9] `Default values' means the currently selected named */
- /* instance (or the base font if no named instance is selected). */
- /* */
- /* [Since 2.9] If `num_coords' is larger than zero, this function */
- /* sets the @FT_FACE_FLAG_VARIATION bit in @FT_Face's `face_flags' */
- /* field (i.e., @FT_IS_VARIATION will return true). If `num_coords' */
- /* is zero, this bit flag gets unset. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Set_Var_Design_Coordinates
+ *
+ * @description:
+ * Choose an interpolated font design through design coordinates.
+ *
+ * This function works with all supported variation formats.
+ *
+ * @inout:
+ * face ::
+ * A handle to the source face.
+ *
+ * @input:
+ * num_coords ::
+ * The number of available design coordinates. If it is larger than
+ * the number of axes, ignore the excess values. If it is smaller than
+ * the number of axes, use default values for the remaining axes.
+ *
+ * coords ::
+ * An array of design coordinates.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * [Since 2.8.1] To reset all axes to the default values, call the
+ * function with `num_coords` set to zero and `coords` set to `NULL`.
+ * [Since 2.9] 'Default values' means the currently selected named
+ * instance (or the base font if no named instance is selected).
+ *
+ * [Since 2.9] If `num_coords` is larger than zero, this function sets
+ * the @FT_FACE_FLAG_VARIATION bit in @FT_Face's `face_flags` field
+ * (i.e., @FT_IS_VARIATION will return true). If `num_coords` is zero,
+ * this bit flag gets unset.
+ */
FT_EXPORT( FT_Error )
FT_Set_Var_Design_Coordinates( FT_Face face,
FT_UInt num_coords,
FT_Fixed* coords );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Get_Var_Design_Coordinates */
- /* */
- /* <Description> */
- /* Get the design coordinates of the currently selected interpolated */
- /* font. */
- /* */
- /* This function works with all supported variation formats. */
- /* */
- /* <Input> */
- /* face :: A handle to the source face. */
- /* */
- /* num_coords :: The number of design coordinates to retrieve. If it */
- /* is larger than the number of axes, set the excess */
- /* values to~0. */
- /* */
- /* <Output> */
- /* coords :: The design coordinates array. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Since> */
- /* 2.7.1 */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Var_Design_Coordinates
+ *
+ * @description:
+ * Get the design coordinates of the currently selected interpolated
+ * font.
+ *
+ * This function works with all supported variation formats.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face.
+ *
+ * num_coords ::
+ * The number of design coordinates to retrieve. If it is larger than
+ * the number of axes, set the excess values to~0.
+ *
+ * @output:
+ * coords ::
+ * The design coordinates array.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @since:
+ * 2.7.1
+ */
FT_EXPORT( FT_Error )
FT_Get_Var_Design_Coordinates( FT_Face face,
FT_UInt num_coords,
FT_Fixed* coords );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Set_MM_Blend_Coordinates */
- /* */
- /* <Description> */
- /* Choose an interpolated font design through normalized blend */
- /* coordinates. */
- /* */
- /* This function works with all supported variation formats. */
- /* */
- /* <InOut> */
- /* face :: A handle to the source face. */
- /* */
- /* <Input> */
- /* num_coords :: The number of available design coordinates. If it */
- /* is larger than the number of axes, ignore the excess */
- /* values. If it is smaller than the number of axes, */
- /* use default values for the remaining axes. */
- /* */
- /* coords :: The design coordinates array (each element must be */
- /* between 0 and 1.0 for Adobe MM fonts, and between */
- /* -1.0 and 1.0 for TrueType GX and OpenType variation */
- /* fonts). */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* [Since 2.8.1] To reset all axes to the default values, call the */
- /* function with `num_coords' set to zero and `coords' set to NULL. */
- /* [Since 2.9] `Default values' means the currently selected named */
- /* instance (or the base font if no named instance is selected). */
- /* */
- /* [Since 2.9] If `num_coords' is larger than zero, this function */
- /* sets the @FT_FACE_FLAG_VARIATION bit in @FT_Face's `face_flags' */
- /* field (i.e., @FT_IS_VARIATION will return true). If `num_coords' */
- /* is zero, this bit flag gets unset. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Set_MM_Blend_Coordinates
+ *
+ * @description:
+ * Choose an interpolated font design through normalized blend
+ * coordinates.
+ *
+ * This function works with all supported variation formats.
+ *
+ * @inout:
+ * face ::
+ * A handle to the source face.
+ *
+ * @input:
+ * num_coords ::
+ * The number of available design coordinates. If it is larger than
+ * the number of axes, ignore the excess values. If it is smaller than
+ * the number of axes, use default values for the remaining axes.
+ *
+ * coords ::
+ * The design coordinates array (each element must be between 0 and 1.0
+ * for Adobe MM fonts, and between -1.0 and 1.0 for TrueType GX and
+ * OpenType variation fonts).
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * [Since 2.8.1] To reset all axes to the default values, call the
+ * function with `num_coords` set to zero and `coords` set to `NULL`.
+ * [Since 2.9] 'Default values' means the currently selected named
+ * instance (or the base font if no named instance is selected).
+ *
+ * [Since 2.9] If `num_coords` is larger than zero, this function sets
+ * the @FT_FACE_FLAG_VARIATION bit in @FT_Face's `face_flags` field
+ * (i.e., @FT_IS_VARIATION will return true). If `num_coords` is zero,
+ * this bit flag gets unset.
+ */
FT_EXPORT( FT_Error )
FT_Set_MM_Blend_Coordinates( FT_Face face,
FT_UInt num_coords,
FT_Fixed* coords );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Get_MM_Blend_Coordinates */
- /* */
- /* <Description> */
- /* Get the normalized blend coordinates of the currently selected */
- /* interpolated font. */
- /* */
- /* This function works with all supported variation formats. */
- /* */
- /* <Input> */
- /* face :: A handle to the source face. */
- /* */
- /* num_coords :: The number of normalized blend coordinates to */
- /* retrieve. If it is larger than the number of axes, */
- /* set the excess values to~0.5 for Adobe MM fonts, and */
- /* to~0 for TrueType GX and OpenType variation fonts. */
- /* */
- /* <Output> */
- /* coords :: The normalized blend coordinates array. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Since> */
- /* 2.7.1 */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_MM_Blend_Coordinates
+ *
+ * @description:
+ * Get the normalized blend coordinates of the currently selected
+ * interpolated font.
+ *
+ * This function works with all supported variation formats.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face.
+ *
+ * num_coords ::
+ * The number of normalized blend coordinates to retrieve. If it is
+ * larger than the number of axes, set the excess values to~0.5 for
+ * Adobe MM fonts, and to~0 for TrueType GX and OpenType variation
+ * fonts.
+ *
+ * @output:
+ * coords ::
+ * The normalized blend coordinates array.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @since:
+ * 2.7.1
+ */
FT_EXPORT( FT_Error )
FT_Get_MM_Blend_Coordinates( FT_Face face,
FT_UInt num_coords,
FT_Fixed* coords );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Set_Var_Blend_Coordinates */
- /* */
- /* <Description> */
- /* This is another name of @FT_Set_MM_Blend_Coordinates. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Set_Var_Blend_Coordinates
+ *
+ * @description:
+ * This is another name of @FT_Set_MM_Blend_Coordinates.
+ */
FT_EXPORT( FT_Error )
FT_Set_Var_Blend_Coordinates( FT_Face face,
FT_UInt num_coords,
FT_Fixed* coords );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Get_Var_Blend_Coordinates */
- /* */
- /* <Description> */
- /* This is another name of @FT_Get_MM_Blend_Coordinates. */
- /* */
- /* <Since> */
- /* 2.7.1 */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Var_Blend_Coordinates
+ *
+ * @description:
+ * This is another name of @FT_Get_MM_Blend_Coordinates.
+ *
+ * @since:
+ * 2.7.1
+ */
FT_EXPORT( FT_Error )
FT_Get_Var_Blend_Coordinates( FT_Face face,
FT_UInt num_coords,
FT_Fixed* coords );
- /*************************************************************************/
- /* */
- /* <Enum> */
- /* FT_VAR_AXIS_FLAG_XXX */
- /* */
- /* <Description> */
- /* A list of bit flags used in the return value of */
- /* @FT_Get_Var_Axis_Flags. */
- /* */
- /* <Values> */
- /* FT_VAR_AXIS_FLAG_HIDDEN :: */
- /* The variation axis should not be exposed to user interfaces. */
- /* */
- /* <Since> */
- /* 2.8.1 */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Set_MM_WeightVector
+ *
+ * @description:
+ * For Adobe MM fonts, choose an interpolated font design by directly
+ * setting the weight vector.
+ *
+ * This function can't be used with TrueType GX or OpenType variation
+ * fonts.
+ *
+ * @inout:
+ * face ::
+ * A handle to the source face.
+ *
+ * @input:
+ * len ::
+ * The length of the weight vector array. If it is larger than the
+ * number of designs, the extra values are ignored. If it is less than
+ * the number of designs, the remaining values are set to zero.
+ *
+ * weightvector ::
+ * An array representing the weight vector.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * Adobe Multiple Master fonts limit the number of designs, and thus the
+ * length of the weight vector to~16.
+ *
+ * If `len` is zero and `weightvector` is `NULL`, the weight vector array
+ * is reset to the default values.
+ *
+ * The Adobe documentation also states that the values in the
+ * WeightVector array must total 1.0 +/-~0.001. In practice this does
+ * not seem to be enforced, so is not enforced here, either.
+ *
+ * @since:
+ * 2.10
+ */
+ FT_EXPORT( FT_Error )
+ FT_Set_MM_WeightVector( FT_Face face,
+ FT_UInt len,
+ FT_Fixed* weightvector );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_MM_WeightVector
+ *
+ * @description:
+ * For Adobe MM fonts, retrieve the current weight vector of the font.
+ *
+ * This function can't be used with TrueType GX or OpenType variation
+ * fonts.
+ *
+ * @inout:
+ * face ::
+ * A handle to the source face.
+ *
+ * len ::
+ * A pointer to the size of the array to be filled. If the size of the
+ * array is less than the number of designs, `FT_Err_Invalid_Argument`
+ * is returned, and `len` is set to the required size (the number of
+ * designs). If the size of the array is greater than the number of
+ * designs, the remaining entries are set to~0. On successful
+ * completion, `len` is set to the number of designs (i.e., the number
+ * of values written to the array).
+ *
+ * @output:
+ * weightvector ::
+ * An array to be filled.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * Adobe Multiple Master fonts limit the number of designs, and thus the
+ * length of the WeightVector to~16.
+ *
+ * @since:
+ * 2.10
+ */
+ FT_EXPORT( FT_Error )
+ FT_Get_MM_WeightVector( FT_Face face,
+ FT_UInt* len,
+ FT_Fixed* weightvector );
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_VAR_AXIS_FLAG_XXX
+ *
+ * @description:
+ * A list of bit flags used in the return value of
+ * @FT_Get_Var_Axis_Flags.
+ *
+ * @values:
+ * FT_VAR_AXIS_FLAG_HIDDEN ::
+ * The variation axis should not be exposed to user interfaces.
+ *
+ * @since:
+ * 2.8.1
+ */
#define FT_VAR_AXIS_FLAG_HIDDEN 1
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Get_Var_Axis_Flags */
- /* */
- /* <Description> */
- /* Get the `flags' field of an OpenType Variation Axis Record. */
- /* */
- /* Not meaningful for Adobe MM fonts (`*flags' is always zero). */
- /* */
- /* <Input> */
- /* master :: The variation descriptor. */
- /* */
- /* axis_index :: The index of the requested variation axis. */
- /* */
- /* <Output> */
- /* flags :: The `flags' field. See @FT_VAR_AXIS_FLAG_XXX for */
- /* possible values. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Since> */
- /* 2.8.1 */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Var_Axis_Flags
+ *
+ * @description:
+ * Get the 'flags' field of an OpenType Variation Axis Record.
+ *
+ * Not meaningful for Adobe MM fonts (`*flags` is always zero).
+ *
+ * @input:
+ * master ::
+ * The variation descriptor.
+ *
+ * axis_index ::
+ * The index of the requested variation axis.
+ *
+ * @output:
+ * flags ::
+ * The 'flags' field. See @FT_VAR_AXIS_FLAG_XXX for possible values.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @since:
+ * 2.8.1
+ */
FT_EXPORT( FT_Error )
FT_Get_Var_Axis_Flags( FT_MM_Var* master,
FT_UInt axis_index,
FT_UInt* flags );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Set_Named_Instance */
- /* */
- /* <Description> */
- /* Set or change the current named instance. */
- /* */
- /* <Input> */
- /* face :: A handle to the source face. */
- /* */
- /* instance_index :: The index of the requested instance, starting */
- /* with value 1. If set to value 0, FreeType */
- /* switches to font access without a named */
- /* instance. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* The function uses the value of `instance_index' to set bits 16-30 */
- /* of the face's `face_index' field. It also resets any variation */
- /* applied to the font, and the @FT_FACE_FLAG_VARIATION bit of the */
- /* face's `face_flags' field gets reset to zero (i.e., */
- /* @FT_IS_VARIATION will return false). */
- /* */
- /* For Adobe MM fonts (which don't have named instances) this */
- /* function simply resets the current face to the default instance. */
- /* */
- /* <Since> */
- /* 2.9 */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Set_Named_Instance
+ *
+ * @description:
+ * Set or change the current named instance.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face.
+ *
+ * instance_index ::
+ * The index of the requested instance, starting with value 1. If set
+ * to value 0, FreeType switches to font access without a named
+ * instance.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The function uses the value of `instance_index` to set bits 16-30 of
+ * the face's `face_index` field. It also resets any variation applied
+ * to the font, and the @FT_FACE_FLAG_VARIATION bit of the face's
+ * `face_flags` field gets reset to zero (i.e., @FT_IS_VARIATION will
+ * return false).
+ *
+ * For Adobe MM fonts (which don't have named instances) this function
+ * simply resets the current face to the default instance.
+ *
+ * @since:
+ * 2.9
+ */
FT_EXPORT( FT_Error )
FT_Set_Named_Instance( FT_Face face,
FT_UInt instance_index );
diff --git a/thirdparty/freetype/include/freetype/ftmodapi.h b/thirdparty/freetype/include/freetype/ftmodapi.h
index a6eb876ebe..88488bfe89 100644
--- a/thirdparty/freetype/include/freetype/ftmodapi.h
+++ b/thirdparty/freetype/include/freetype/ftmodapi.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftmodapi.h */
-/* */
-/* FreeType modules public interface (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftmodapi.h
+ *
+ * FreeType modules public interface (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTMODAPI_H_
@@ -33,77 +33,77 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* <Section> */
- /* module_management */
- /* */
- /* <Title> */
- /* Module Management */
- /* */
- /* <Abstract> */
- /* How to add, upgrade, remove, and control modules from FreeType. */
- /* */
- /* <Description> */
- /* The definitions below are used to manage modules within FreeType. */
- /* Modules can be added, upgraded, and removed at runtime. */
- /* Additionally, some module properties can be controlled also. */
- /* */
- /* Here is a list of possible values of the `module_name' field in */
- /* the @FT_Module_Class structure. */
- /* */
- /* { */
- /* autofitter */
- /* bdf */
- /* cff */
- /* gxvalid */
- /* otvalid */
- /* pcf */
- /* pfr */
- /* psaux */
- /* pshinter */
- /* psnames */
- /* raster1 */
- /* sfnt */
- /* smooth, smooth-lcd, smooth-lcdv */
- /* truetype */
- /* type1 */
- /* type42 */
- /* t1cid */
- /* winfonts */
- /* } */
- /* */
- /* Note that the FreeType Cache sub-system is not a FreeType module. */
- /* */
- /* <Order> */
- /* FT_Module */
- /* FT_Module_Constructor */
- /* FT_Module_Destructor */
- /* FT_Module_Requester */
- /* FT_Module_Class */
- /* */
- /* FT_Add_Module */
- /* FT_Get_Module */
- /* FT_Remove_Module */
- /* FT_Add_Default_Modules */
- /* */
- /* FT_Property_Set */
- /* FT_Property_Get */
- /* FT_Set_Default_Properties */
- /* */
- /* FT_New_Library */
- /* FT_Done_Library */
- /* FT_Reference_Library */
- /* */
- /* FT_Renderer */
- /* FT_Renderer_Class */
- /* */
- /* FT_Get_Renderer */
- /* FT_Set_Renderer */
- /* */
- /* FT_Set_Debug_Hook */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * @section:
+ * module_management
+ *
+ * @title:
+ * Module Management
+ *
+ * @abstract:
+ * How to add, upgrade, remove, and control modules from FreeType.
+ *
+ * @description:
+ * The definitions below are used to manage modules within FreeType.
+ * Modules can be added, upgraded, and removed at runtime. Additionally,
+ * some module properties can be controlled also.
+ *
+ * Here is a list of possible values of the `module_name` field in the
+ * @FT_Module_Class structure.
+ *
+ * ```
+ * autofitter
+ * bdf
+ * cff
+ * gxvalid
+ * otvalid
+ * pcf
+ * pfr
+ * psaux
+ * pshinter
+ * psnames
+ * raster1
+ * sfnt
+ * smooth, smooth-lcd, smooth-lcdv
+ * truetype
+ * type1
+ * type42
+ * t1cid
+ * winfonts
+ * ```
+ *
+ * Note that the FreeType Cache sub-system is not a FreeType module.
+ *
+ * @order:
+ * FT_Module
+ * FT_Module_Constructor
+ * FT_Module_Destructor
+ * FT_Module_Requester
+ * FT_Module_Class
+ *
+ * FT_Add_Module
+ * FT_Get_Module
+ * FT_Remove_Module
+ * FT_Add_Default_Modules
+ *
+ * FT_Property_Set
+ * FT_Property_Get
+ * FT_Set_Default_Properties
+ *
+ * FT_New_Library
+ * FT_Done_Library
+ * FT_Reference_Library
+ *
+ * FT_Renderer
+ * FT_Renderer_Class
+ *
+ * FT_Get_Renderer
+ * FT_Set_Renderer
+ *
+ * FT_Set_Debug_Hook
+ *
+ */
/* module bit flags */
@@ -137,83 +137,99 @@ FT_BEGIN_HEADER
typedef FT_Pointer FT_Module_Interface;
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* FT_Module_Constructor */
- /* */
- /* <Description> */
- /* A function used to initialize (not create) a new module object. */
- /* */
- /* <Input> */
- /* module :: The module to initialize. */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_Module_Constructor
+ *
+ * @description:
+ * A function used to initialize (not create) a new module object.
+ *
+ * @input:
+ * module ::
+ * The module to initialize.
+ */
typedef FT_Error
(*FT_Module_Constructor)( FT_Module module );
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* FT_Module_Destructor */
- /* */
- /* <Description> */
- /* A function used to finalize (not destroy) a given module object. */
- /* */
- /* <Input> */
- /* module :: The module to finalize. */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_Module_Destructor
+ *
+ * @description:
+ * A function used to finalize (not destroy) a given module object.
+ *
+ * @input:
+ * module ::
+ * The module to finalize.
+ */
typedef void
(*FT_Module_Destructor)( FT_Module module );
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* FT_Module_Requester */
- /* */
- /* <Description> */
- /* A function used to query a given module for a specific interface. */
- /* */
- /* <Input> */
- /* module :: The module to be searched. */
- /* */
- /* name :: The name of the interface in the module. */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_Module_Requester
+ *
+ * @description:
+ * A function used to query a given module for a specific interface.
+ *
+ * @input:
+ * module ::
+ * The module to be searched.
+ *
+ * name ::
+ * The name of the interface in the module.
+ */
typedef FT_Module_Interface
(*FT_Module_Requester)( FT_Module module,
const char* name );
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_Module_Class */
- /* */
- /* <Description> */
- /* The module class descriptor. */
- /* */
- /* <Fields> */
- /* module_flags :: Bit flags describing the module. */
- /* */
- /* module_size :: The size of one module object/instance in */
- /* bytes. */
- /* */
- /* module_name :: The name of the module. */
- /* */
- /* module_version :: The version, as a 16.16 fixed number */
- /* (major.minor). */
- /* */
- /* module_requires :: The version of FreeType this module requires, */
- /* as a 16.16 fixed number (major.minor). Starts */
- /* at version 2.0, i.e., 0x20000. */
- /* */
- /* module_init :: The initializing function. */
- /* */
- /* module_done :: The finalizing function. */
- /* */
- /* get_interface :: The interface requesting function. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Module_Class
+ *
+ * @description:
+ * The module class descriptor. While being a public structure necessary
+ * for FreeType's module bookkeeping, most of the fields are essentially
+ * internal, not to be used directly by an application.
+ *
+ * @fields:
+ * module_flags ::
+ * Bit flags describing the module.
+ *
+ * module_size ::
+ * The size of one module object/instance in bytes.
+ *
+ * module_name ::
+ * The name of the module.
+ *
+ * module_version ::
+ * The version, as a 16.16 fixed number (major.minor).
+ *
+ * module_requires ::
+ * The version of FreeType this module requires, as a 16.16 fixed
+ * number (major.minor). Starts at version 2.0, i.e., 0x20000.
+ *
+ * module_interface ::
+ * A typeless pointer to a structure (which varies between different
+ * modules) that holds the module's interface functions. This is
+ * essentially what `get_interface` returns.
+ *
+ * module_init ::
+ * The initializing function.
+ *
+ * module_done ::
+ * The finalizing function.
+ *
+ * get_interface ::
+ * The interface requesting function.
+ */
typedef struct FT_Module_Class_
{
FT_ULong module_flags;
@@ -231,83 +247,89 @@ FT_BEGIN_HEADER
} FT_Module_Class;
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Add_Module */
- /* */
- /* <Description> */
- /* Add a new module to a given library instance. */
- /* */
- /* <InOut> */
- /* library :: A handle to the library object. */
- /* */
- /* <Input> */
- /* clazz :: A pointer to class descriptor for the module. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* An error will be returned if a module already exists by that name, */
- /* or if the module requires a version of FreeType that is too great. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Add_Module
+ *
+ * @description:
+ * Add a new module to a given library instance.
+ *
+ * @inout:
+ * library ::
+ * A handle to the library object.
+ *
+ * @input:
+ * clazz ::
+ * A pointer to class descriptor for the module.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * An error will be returned if a module already exists by that name, or
+ * if the module requires a version of FreeType that is too great.
+ */
FT_EXPORT( FT_Error )
FT_Add_Module( FT_Library library,
const FT_Module_Class* clazz );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Get_Module */
- /* */
- /* <Description> */
- /* Find a module by its name. */
- /* */
- /* <Input> */
- /* library :: A handle to the library object. */
- /* */
- /* module_name :: The module's name (as an ASCII string). */
- /* */
- /* <Return> */
- /* A module handle. 0~if none was found. */
- /* */
- /* <Note> */
- /* FreeType's internal modules aren't documented very well, and you */
- /* should look up the source code for details. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Module
+ *
+ * @description:
+ * Find a module by its name.
+ *
+ * @input:
+ * library ::
+ * A handle to the library object.
+ *
+ * module_name ::
+ * The module's name (as an ASCII string).
+ *
+ * @return:
+ * A module handle. 0~if none was found.
+ *
+ * @note:
+ * FreeType's internal modules aren't documented very well, and you
+ * should look up the source code for details.
+ */
FT_EXPORT( FT_Module )
FT_Get_Module( FT_Library library,
const char* module_name );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Remove_Module */
- /* */
- /* <Description> */
- /* Remove a given module from a library instance. */
- /* */
- /* <InOut> */
- /* library :: A handle to a library object. */
- /* */
- /* <Input> */
- /* module :: A handle to a module object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* The module object is destroyed by the function in case of success. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Remove_Module
+ *
+ * @description:
+ * Remove a given module from a library instance.
+ *
+ * @inout:
+ * library ::
+ * A handle to a library object.
+ *
+ * @input:
+ * module ::
+ * A handle to a module object.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The module object is destroyed by the function in case of success.
+ */
FT_EXPORT( FT_Error )
FT_Remove_Module( FT_Library library,
FT_Module module );
- /**********************************************************************
+ /**************************************************************************
*
* @function:
* FT_Property_Set
@@ -317,53 +339,51 @@ FT_BEGIN_HEADER
*
* @input:
* library ::
- * A handle to the library the module is part of.
+ * A handle to the library the module is part of.
*
* module_name ::
- * The module name.
+ * The module name.
*
* property_name ::
- * The property name. Properties are described in section
- * @properties.
+ * The property name. Properties are described in section
+ * @properties.
*
- * Note that only a few modules have properties.
+ * Note that only a few modules have properties.
*
* value ::
- * A generic pointer to a variable or structure that gives the new
- * value of the property. The exact definition of `value' is
- * dependent on the property; see section @properties.
+ * A generic pointer to a variable or structure that gives the new
+ * value of the property. The exact definition of `value` is
+ * dependent on the property; see section @properties.
*
* @return:
* FreeType error code. 0~means success.
*
* @note:
- * If `module_name' isn't a valid module name, or `property_name'
- * doesn't specify a valid property, or if `value' doesn't represent a
+ * If `module_name` isn't a valid module name, or `property_name`
+ * doesn't specify a valid property, or if `value` doesn't represent a
* valid value for the given property, an error is returned.
*
- * The following example sets property `bar' (a simple integer) in
- * module `foo' to value~1.
+ * The following example sets property 'bar' (a simple integer) in
+ * module 'foo' to value~1.
*
- * {
+ * ```
* FT_UInt bar;
*
*
* bar = 1;
* FT_Property_Set( library, "foo", "bar", &bar );
- * }
+ * ```
*
* Note that the FreeType Cache sub-system doesn't recognize module
* property changes. To avoid glyph lookup confusion within the cache
- * you should call @FTC_Manager_Reset to completely flush the cache if
- * a module property gets changed after @FTC_Manager_New has been
- * called.
+ * you should call @FTC_Manager_Reset to completely flush the cache if a
+ * module property gets changed after @FTC_Manager_New has been called.
*
- * It is not possible to set properties of the FreeType Cache
- * sub-system itself with FT_Property_Set; use @FTC_Property_Set
- * instead.
+ * It is not possible to set properties of the FreeType Cache sub-system
+ * itself with FT_Property_Set; use @FTC_Property_Set instead.
*
- * @since:
- * 2.4.11
+ * @since:
+ * 2.4.11
*
*/
FT_EXPORT( FT_Error )
@@ -373,7 +393,7 @@ FT_BEGIN_HEADER
const void* value );
- /**********************************************************************
+ /**************************************************************************
*
* @function:
* FT_Property_Get
@@ -383,32 +403,32 @@ FT_BEGIN_HEADER
*
* @input:
* library ::
- * A handle to the library the module is part of.
+ * A handle to the library the module is part of.
*
* module_name ::
- * The module name.
+ * The module name.
*
* property_name ::
- * The property name. Properties are described in section
- * @properties.
+ * The property name. Properties are described in section
+ * @properties.
*
* @inout:
* value ::
- * A generic pointer to a variable or structure that gives the
- * value of the property. The exact definition of `value' is
- * dependent on the property; see section @properties.
+ * A generic pointer to a variable or structure that gives the value
+ * of the property. The exact definition of `value` is dependent on
+ * the property; see section @properties.
*
* @return:
* FreeType error code. 0~means success.
*
* @note:
- * If `module_name' isn't a valid module name, or `property_name'
- * doesn't specify a valid property, or if `value' doesn't represent a
+ * If `module_name` isn't a valid module name, or `property_name`
+ * doesn't specify a valid property, or if `value` doesn't represent a
* valid value for the given property, an error is returned.
*
- * The following example gets property `baz' (a range) in module `foo'.
+ * The following example gets property 'baz' (a range) in module 'foo'.
*
- * {
+ * ```
* typedef range_
* {
* FT_Int32 min;
@@ -420,13 +440,13 @@ FT_BEGIN_HEADER
*
*
* FT_Property_Get( library, "foo", "baz", &baz );
- * }
+ * ```
*
* It is not possible to retrieve properties of the FreeType Cache
* sub-system with FT_Property_Get; use @FTC_Property_Get instead.
*
- * @since:
- * 2.4.11
+ * @since:
+ * 2.4.11
*
*/
FT_EXPORT( FT_Error )
@@ -436,189 +456,243 @@ FT_BEGIN_HEADER
void* value );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Set_Default_Properties */
- /* */
- /* <Description> */
- /* If compilation option FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES is */
- /* set, this function reads the `FREETYPE_PROPERTIES' environment */
- /* variable to control driver properties. See section @properties */
- /* for more. */
- /* */
- /* If the compilation option is not set, this function does nothing. */
- /* */
- /* `FREETYPE_PROPERTIES' has the following syntax form (broken here */
- /* into multiple lines for better readability). */
- /* */
- /* { */
- /* <optional whitespace> */
- /* <module-name1> ':' */
- /* <property-name1> '=' <property-value1> */
- /* <whitespace> */
- /* <module-name2> ':' */
- /* <property-name2> '=' <property-value2> */
- /* ... */
- /* } */
- /* */
- /* Example: */
- /* */
- /* { */
- /* FREETYPE_PROPERTIES=truetype:interpreter-version=35 \ */
- /* cff:no-stem-darkening=1 \ */
- /* autofitter:warping=1 */
- /* } */
- /* */
- /* <InOut> */
- /* library :: A handle to a new library object. */
- /* */
- /* <Since> */
- /* 2.8 */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Set_Default_Properties
+ *
+ * @description:
+ * If compilation option `FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES` is
+ * set, this function reads the `FREETYPE_PROPERTIES` environment
+ * variable to control driver properties. See section @properties for
+ * more.
+ *
+ * If the compilation option is not set, this function does nothing.
+ *
+ * `FREETYPE_PROPERTIES` has the following syntax form (broken here into
+ * multiple lines for better readability).
+ *
+ * ```
+ * <optional whitespace>
+ * <module-name1> ':'
+ * <property-name1> '=' <property-value1>
+ * <whitespace>
+ * <module-name2> ':'
+ * <property-name2> '=' <property-value2>
+ * ...
+ * ```
+ *
+ * Example:
+ *
+ * ```
+ * FREETYPE_PROPERTIES=truetype:interpreter-version=35 \
+ * cff:no-stem-darkening=1 \
+ * autofitter:warping=1
+ * ```
+ *
+ * @inout:
+ * library ::
+ * A handle to a new library object.
+ *
+ * @since:
+ * 2.8
+ */
FT_EXPORT( void )
FT_Set_Default_Properties( FT_Library library );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Reference_Library */
- /* */
- /* <Description> */
- /* A counter gets initialized to~1 at the time an @FT_Library */
- /* structure is created. This function increments the counter. */
- /* @FT_Done_Library then only destroys a library if the counter is~1, */
- /* otherwise it simply decrements the counter. */
- /* */
- /* This function helps in managing life-cycles of structures that */
- /* reference @FT_Library objects. */
- /* */
- /* <Input> */
- /* library :: A handle to a target library object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Since> */
- /* 2.4.2 */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Reference_Library
+ *
+ * @description:
+ * A counter gets initialized to~1 at the time an @FT_Library structure
+ * is created. This function increments the counter. @FT_Done_Library
+ * then only destroys a library if the counter is~1, otherwise it simply
+ * decrements the counter.
+ *
+ * This function helps in managing life-cycles of structures that
+ * reference @FT_Library objects.
+ *
+ * @input:
+ * library ::
+ * A handle to a target library object.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @since:
+ * 2.4.2
+ */
FT_EXPORT( FT_Error )
FT_Reference_Library( FT_Library library );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_New_Library */
- /* */
- /* <Description> */
- /* This function is used to create a new FreeType library instance */
- /* from a given memory object. It is thus possible to use libraries */
- /* with distinct memory allocators within the same program. Note, */
- /* however, that the used @FT_Memory structure is expected to remain */
- /* valid for the life of the @FT_Library object. */
- /* */
- /* Normally, you would call this function (followed by a call to */
- /* @FT_Add_Default_Modules or a series of calls to @FT_Add_Module, */
- /* and a call to @FT_Set_Default_Properties) instead of */
- /* @FT_Init_FreeType to initialize the FreeType library. */
- /* */
- /* Don't use @FT_Done_FreeType but @FT_Done_Library to destroy a */
- /* library instance. */
- /* */
- /* <Input> */
- /* memory :: A handle to the original memory object. */
- /* */
- /* <Output> */
- /* alibrary :: A pointer to handle of a new library object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* See the discussion of reference counters in the description of */
- /* @FT_Reference_Library. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_New_Library
+ *
+ * @description:
+ * This function is used to create a new FreeType library instance from a
+ * given memory object. It is thus possible to use libraries with
+ * distinct memory allocators within the same program. Note, however,
+ * that the used @FT_Memory structure is expected to remain valid for the
+ * life of the @FT_Library object.
+ *
+ * Normally, you would call this function (followed by a call to
+ * @FT_Add_Default_Modules or a series of calls to @FT_Add_Module, and a
+ * call to @FT_Set_Default_Properties) instead of @FT_Init_FreeType to
+ * initialize the FreeType library.
+ *
+ * Don't use @FT_Done_FreeType but @FT_Done_Library to destroy a library
+ * instance.
+ *
+ * @input:
+ * memory ::
+ * A handle to the original memory object.
+ *
+ * @output:
+ * alibrary ::
+ * A pointer to handle of a new library object.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * See the discussion of reference counters in the description of
+ * @FT_Reference_Library.
+ */
FT_EXPORT( FT_Error )
FT_New_Library( FT_Memory memory,
FT_Library *alibrary );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Done_Library */
- /* */
- /* <Description> */
- /* Discard a given library object. This closes all drivers and */
- /* discards all resource objects. */
- /* */
- /* <Input> */
- /* library :: A handle to the target library. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* See the discussion of reference counters in the description of */
- /* @FT_Reference_Library. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Done_Library
+ *
+ * @description:
+ * Discard a given library object. This closes all drivers and discards
+ * all resource objects.
+ *
+ * @input:
+ * library ::
+ * A handle to the target library.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * See the discussion of reference counters in the description of
+ * @FT_Reference_Library.
+ */
FT_EXPORT( FT_Error )
FT_Done_Library( FT_Library library );
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_DebugHook_Func
+ *
+ * @description:
+ * A drop-in replacement (or rather a wrapper) for the bytecode or
+ * charstring interpreter's main loop function.
+ *
+ * Its job is essentially
+ *
+ * - to activate debug mode to enforce single-stepping,
+ *
+ * - to call the main loop function to interpret the next opcode, and
+ *
+ * - to show the changed context to the user.
+ *
+ * An example for such a main loop function is `TT_RunIns` (declared in
+ * FreeType's internal header file `src/truetype/ttinterp.h`).
+ *
+ * Have a look at the source code of the `ttdebug` FreeType demo program
+ * for an example of a drop-in replacement.
+ *
+ * @inout:
+ * arg ::
+ * A typeless pointer, to be cast to the main loop function's data
+ * structure (which depends on the font module). For TrueType fonts
+ * it is bytecode interpreter's execution context, `TT_ExecContext`,
+ * which is declared in FreeType's internal header file `tttypes.h`.
+ */
typedef void
(*FT_DebugHook_Func)( void* arg );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Set_Debug_Hook */
- /* */
- /* <Description> */
- /* Set a debug hook function for debugging the interpreter of a font */
- /* format. */
- /* */
- /* <InOut> */
- /* library :: A handle to the library object. */
- /* */
- /* <Input> */
- /* hook_index :: The index of the debug hook. You should use the */
- /* values defined in `ftobjs.h', e.g., */
- /* `FT_DEBUG_HOOK_TRUETYPE'. */
- /* */
- /* debug_hook :: The function used to debug the interpreter. */
- /* */
- /* <Note> */
- /* Currently, four debug hook slots are available, but only two (for */
- /* the TrueType and the Type~1 interpreter) are defined. */
- /* */
- /* Since the internal headers of FreeType are no longer installed, */
- /* the symbol `FT_DEBUG_HOOK_TRUETYPE' isn't available publicly. */
- /* This is a bug and will be fixed in a forthcoming release. */
- /* */
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_DEBUG_HOOK_XXX
+ *
+ * @description:
+ * A list of named debug hook indices.
+ *
+ * @values:
+ * FT_DEBUG_HOOK_TRUETYPE::
+ * This hook index identifies the TrueType bytecode debugger.
+ */
+#define FT_DEBUG_HOOK_TRUETYPE 0
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Set_Debug_Hook
+ *
+ * @description:
+ * Set a debug hook function for debugging the interpreter of a font
+ * format.
+ *
+ * While this is a public API function, an application needs access to
+ * FreeType's internal header files to do something useful.
+ *
+ * Have a look at the source code of the `ttdebug` FreeType demo program
+ * for an example of its usage.
+ *
+ * @inout:
+ * library ::
+ * A handle to the library object.
+ *
+ * @input:
+ * hook_index ::
+ * The index of the debug hook. You should use defined enumeration
+ * macros like @FT_DEBUG_HOOK_TRUETYPE.
+ *
+ * debug_hook ::
+ * The function used to debug the interpreter.
+ *
+ * @note:
+ * Currently, four debug hook slots are available, but only one (for the
+ * TrueType interpreter) is defined.
+ */
FT_EXPORT( void )
FT_Set_Debug_Hook( FT_Library library,
FT_UInt hook_index,
FT_DebugHook_Func debug_hook );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Add_Default_Modules */
- /* */
- /* <Description> */
- /* Add the set of default drivers to a given library object. */
- /* This is only useful when you create a library object with */
- /* @FT_New_Library (usually to plug a custom memory manager). */
- /* */
- /* <InOut> */
- /* library :: A handle to a new library object. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Add_Default_Modules
+ *
+ * @description:
+ * Add the set of default drivers to a given library object. This is
+ * only useful when you create a library object with @FT_New_Library
+ * (usually to plug a custom memory manager).
+ *
+ * @inout:
+ * library ::
+ * A handle to a new library object.
+ */
FT_EXPORT( void )
FT_Add_Default_Modules( FT_Library library );
@@ -644,28 +718,28 @@ FT_BEGIN_HEADER
/**************************************************************************
*
- * @enum:
- * FT_TrueTypeEngineType
+ * @enum:
+ * FT_TrueTypeEngineType
*
- * @description:
- * A list of values describing which kind of TrueType bytecode
- * engine is implemented in a given FT_Library instance. It is used
- * by the @FT_Get_TrueType_Engine_Type function.
+ * @description:
+ * A list of values describing which kind of TrueType bytecode engine is
+ * implemented in a given FT_Library instance. It is used by the
+ * @FT_Get_TrueType_Engine_Type function.
*
- * @values:
- * FT_TRUETYPE_ENGINE_TYPE_NONE ::
- * The library doesn't implement any kind of bytecode interpreter.
+ * @values:
+ * FT_TRUETYPE_ENGINE_TYPE_NONE ::
+ * The library doesn't implement any kind of bytecode interpreter.
*
- * FT_TRUETYPE_ENGINE_TYPE_UNPATENTED ::
- * Deprecated and removed.
+ * FT_TRUETYPE_ENGINE_TYPE_UNPATENTED ::
+ * Deprecated and removed.
*
- * FT_TRUETYPE_ENGINE_TYPE_PATENTED ::
- * The library implements a bytecode interpreter that covers
- * the full instruction set of the TrueType virtual machine (this
- * was governed by patents until May 2010, hence the name).
+ * FT_TRUETYPE_ENGINE_TYPE_PATENTED ::
+ * The library implements a bytecode interpreter that covers the full
+ * instruction set of the TrueType virtual machine (this was governed
+ * by patents until May 2010, hence the name).
*
- * @since:
- * 2.2
+ * @since:
+ * 2.2
*
*/
typedef enum FT_TrueTypeEngineType_
@@ -679,22 +753,22 @@ FT_BEGIN_HEADER
/**************************************************************************
*
- * @func:
- * FT_Get_TrueType_Engine_Type
+ * @function:
+ * FT_Get_TrueType_Engine_Type
*
- * @description:
- * Return an @FT_TrueTypeEngineType value to indicate which level of
- * the TrueType virtual machine a given library instance supports.
+ * @description:
+ * Return an @FT_TrueTypeEngineType value to indicate which level of the
+ * TrueType virtual machine a given library instance supports.
*
- * @input:
- * library ::
- * A library instance.
+ * @input:
+ * library ::
+ * A library instance.
*
- * @return:
- * A value indicating which level is supported.
+ * @return:
+ * A value indicating which level is supported.
*
- * @since:
- * 2.2
+ * @since:
+ * 2.2
*
*/
FT_EXPORT( FT_TrueTypeEngineType )
diff --git a/thirdparty/freetype/include/freetype/ftmoderr.h b/thirdparty/freetype/include/freetype/ftmoderr.h
index e0fc1312bd..e16993572c 100644
--- a/thirdparty/freetype/include/freetype/ftmoderr.h
+++ b/thirdparty/freetype/include/freetype/ftmoderr.h
@@ -1,94 +1,103 @@
-/***************************************************************************/
-/* */
-/* ftmoderr.h */
-/* */
-/* FreeType module error offsets (specification). */
-/* */
-/* Copyright 2001-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* This file is used to define the FreeType module error codes. */
- /* */
- /* If the macro FT_CONFIG_OPTION_USE_MODULE_ERRORS in `ftoption.h' is */
- /* set, the lower byte of an error value identifies the error code as */
- /* usual. In addition, the higher byte identifies the module. For */
- /* example, the error `FT_Err_Invalid_File_Format' has value 0x0003, the */
- /* error `TT_Err_Invalid_File_Format' has value 0x1303, the error */
- /* `T1_Err_Invalid_File_Format' has value 0x1403, etc. */
- /* */
- /* Note that `FT_Err_Ok', `TT_Err_Ok', etc. are always equal to zero, */
- /* including the high byte. */
- /* */
- /* If FT_CONFIG_OPTION_USE_MODULE_ERRORS isn't set, the higher byte of */
- /* an error value is set to zero. */
- /* */
- /* To hide the various `XXX_Err_' prefixes in the source code, FreeType */
- /* provides some macros in `fttypes.h'. */
- /* */
- /* FT_ERR( err ) */
- /* Add current error module prefix (as defined with the */
- /* `FT_ERR_PREFIX' macro) to `err'. For example, in the BDF module */
- /* the line */
- /* */
- /* error = FT_ERR( Invalid_Outline ); */
- /* */
- /* expands to */
- /* */
- /* error = BDF_Err_Invalid_Outline; */
- /* */
- /* For simplicity, you can always use `FT_Err_Ok' directly instead */
- /* of `FT_ERR( Ok )'. */
- /* */
- /* FT_ERR_EQ( errcode, err ) */
- /* FT_ERR_NEQ( errcode, err ) */
- /* Compare error code `errcode' with the error `err' for equality */
- /* and inequality, respectively. Example: */
- /* */
- /* if ( FT_ERR_EQ( error, Invalid_Outline ) ) */
- /* ... */
- /* */
- /* Using this macro you don't have to think about error prefixes. */
- /* Of course, if module errors are not active, the above example is */
- /* the same as */
- /* */
- /* if ( error == FT_Err_Invalid_Outline ) */
- /* ... */
- /* */
- /* FT_ERROR_BASE( errcode ) */
- /* FT_ERROR_MODULE( errcode ) */
- /* Get base error and module error code, respectively. */
- /* */
- /* */
- /* It can also be used to create a module error message table easily */
- /* with something like */
- /* */
- /* { */
- /* #undef FTMODERR_H_ */
- /* #define FT_MODERRDEF( e, v, s ) { FT_Mod_Err_ ## e, s }, */
- /* #define FT_MODERR_START_LIST { */
- /* #define FT_MODERR_END_LIST { 0, 0 } }; */
- /* */
- /* const struct */
- /* { */
- /* int mod_err_offset; */
- /* const char* mod_err_msg */
- /* } ft_mod_errors[] = */
- /* */
- /* #include FT_MODULE_ERRORS_H */
- /* } */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * ftmoderr.h
+ *
+ * FreeType module error offsets (specification).
+ *
+ * Copyright (C) 2001-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * This file is used to define the FreeType module error codes.
+ *
+ * If the macro `FT_CONFIG_OPTION_USE_MODULE_ERRORS` in `ftoption.h` is
+ * set, the lower byte of an error value identifies the error code as
+ * usual. In addition, the higher byte identifies the module. For
+ * example, the error `FT_Err_Invalid_File_Format` has value 0x0003, the
+ * error `TT_Err_Invalid_File_Format` has value 0x1303, the error
+ * `T1_Err_Invalid_File_Format` has value 0x1403, etc.
+ *
+ * Note that `FT_Err_Ok`, `TT_Err_Ok`, etc. are always equal to zero,
+ * including the high byte.
+ *
+ * If `FT_CONFIG_OPTION_USE_MODULE_ERRORS` isn't set, the higher byte of an
+ * error value is set to zero.
+ *
+ * To hide the various `XXX_Err_` prefixes in the source code, FreeType
+ * provides some macros in `fttypes.h`.
+ *
+ * FT_ERR( err )
+ *
+ * Add current error module prefix (as defined with the `FT_ERR_PREFIX`
+ * macro) to `err`. For example, in the BDF module the line
+ *
+ * ```
+ * error = FT_ERR( Invalid_Outline );
+ * ```
+ *
+ * expands to
+ *
+ * ```
+ * error = BDF_Err_Invalid_Outline;
+ * ```
+ *
+ * For simplicity, you can always use `FT_Err_Ok` directly instead of
+ * `FT_ERR( Ok )`.
+ *
+ * FT_ERR_EQ( errcode, err )
+ * FT_ERR_NEQ( errcode, err )
+ *
+ * Compare error code `errcode` with the error `err` for equality and
+ * inequality, respectively. Example:
+ *
+ * ```
+ * if ( FT_ERR_EQ( error, Invalid_Outline ) )
+ * ...
+ * ```
+ *
+ * Using this macro you don't have to think about error prefixes. Of
+ * course, if module errors are not active, the above example is the
+ * same as
+ *
+ * ```
+ * if ( error == FT_Err_Invalid_Outline )
+ * ...
+ * ```
+ *
+ * FT_ERROR_BASE( errcode )
+ * FT_ERROR_MODULE( errcode )
+ *
+ * Get base error and module error code, respectively.
+ *
+ * It can also be used to create a module error message table easily with
+ * something like
+ *
+ * ```
+ * #undef FTMODERR_H_
+ * #define FT_MODERRDEF( e, v, s ) { FT_Mod_Err_ ## e, s },
+ * #define FT_MODERR_START_LIST {
+ * #define FT_MODERR_END_LIST { 0, 0 } };
+ *
+ * const struct
+ * {
+ * int mod_err_offset;
+ * const char* mod_err_msg
+ * } ft_mod_errors[] =
+ *
+ * #include FT_MODULE_ERRORS_H
+ * ```
+ *
+ */
#ifndef FTMODERR_H_
diff --git a/thirdparty/freetype/include/freetype/ftotval.h b/thirdparty/freetype/include/freetype/ftotval.h
index 26731c2b9f..c034f48959 100644
--- a/thirdparty/freetype/include/freetype/ftotval.h
+++ b/thirdparty/freetype/include/freetype/ftotval.h
@@ -1,30 +1,30 @@
-/***************************************************************************/
-/* */
-/* ftotval.h */
-/* */
-/* FreeType API for validating OpenType tables (specification). */
-/* */
-/* Copyright 2004-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-/***************************************************************************/
-/* */
-/* */
-/* Warning: This module might be moved to a different library in the */
-/* future to avoid a tight dependency between FreeType and the */
-/* OpenType specification. */
-/* */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftotval.h
+ *
+ * FreeType API for validating OpenType tables (specification).
+ *
+ * Copyright (C) 2004-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+/****************************************************************************
+ *
+ *
+ * Warning: This module might be moved to a different library in the
+ * future to avoid a tight dependency between FreeType and the
+ * OpenType specification.
+ *
+ *
+ */
#ifndef FTOTVAL_H_
@@ -43,62 +43,62 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* <Section> */
- /* ot_validation */
- /* */
- /* <Title> */
- /* OpenType Validation */
- /* */
- /* <Abstract> */
- /* An API to validate OpenType tables. */
- /* */
- /* <Description> */
- /* This section contains the declaration of functions to validate */
- /* some OpenType tables (BASE, GDEF, GPOS, GSUB, JSTF, MATH). */
- /* */
- /* <Order> */
- /* FT_OpenType_Validate */
- /* FT_OpenType_Free */
- /* */
- /* FT_VALIDATE_OTXXX */
- /* */
- /*************************************************************************/
-
-
- /**********************************************************************
- *
- * @enum:
- * FT_VALIDATE_OTXXX
- *
- * @description:
- * A list of bit-field constants used with @FT_OpenType_Validate to
- * indicate which OpenType tables should be validated.
- *
- * @values:
- * FT_VALIDATE_BASE ::
- * Validate BASE table.
- *
- * FT_VALIDATE_GDEF ::
- * Validate GDEF table.
- *
- * FT_VALIDATE_GPOS ::
- * Validate GPOS table.
- *
- * FT_VALIDATE_GSUB ::
- * Validate GSUB table.
- *
- * FT_VALIDATE_JSTF ::
- * Validate JSTF table.
- *
- * FT_VALIDATE_MATH ::
- * Validate MATH table.
- *
- * FT_VALIDATE_OT ::
- * Validate all OpenType tables (BASE, GDEF, GPOS, GSUB, JSTF, MATH).
- *
- */
+ /**************************************************************************
+ *
+ * @section:
+ * ot_validation
+ *
+ * @title:
+ * OpenType Validation
+ *
+ * @abstract:
+ * An API to validate OpenType tables.
+ *
+ * @description:
+ * This section contains the declaration of functions to validate some
+ * OpenType tables (BASE, GDEF, GPOS, GSUB, JSTF, MATH).
+ *
+ * @order:
+ * FT_OpenType_Validate
+ * FT_OpenType_Free
+ *
+ * FT_VALIDATE_OTXXX
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_VALIDATE_OTXXX
+ *
+ * @description:
+ * A list of bit-field constants used with @FT_OpenType_Validate to
+ * indicate which OpenType tables should be validated.
+ *
+ * @values:
+ * FT_VALIDATE_BASE ::
+ * Validate BASE table.
+ *
+ * FT_VALIDATE_GDEF ::
+ * Validate GDEF table.
+ *
+ * FT_VALIDATE_GPOS ::
+ * Validate GPOS table.
+ *
+ * FT_VALIDATE_GSUB ::
+ * Validate GSUB table.
+ *
+ * FT_VALIDATE_JSTF ::
+ * Validate JSTF table.
+ *
+ * FT_VALIDATE_MATH ::
+ * Validate MATH table.
+ *
+ * FT_VALIDATE_OT ::
+ * Validate all OpenType tables (BASE, GDEF, GPOS, GSUB, JSTF, MATH).
+ *
+ */
#define FT_VALIDATE_BASE 0x0100
#define FT_VALIDATE_GDEF 0x0200
#define FT_VALIDATE_GPOS 0x0400
@@ -113,53 +113,54 @@ FT_BEGIN_HEADER
FT_VALIDATE_JSTF | \
FT_VALIDATE_MATH )
- /**********************************************************************
- *
- * @function:
- * FT_OpenType_Validate
- *
- * @description:
- * Validate various OpenType tables to assure that all offsets and
- * indices are valid. The idea is that a higher-level library that
- * actually does the text layout can access those tables without
- * error checking (which can be quite time consuming).
- *
- * @input:
- * face ::
- * A handle to the input face.
- *
- * validation_flags ::
- * A bit field that specifies the tables to be validated. See
- * @FT_VALIDATE_OTXXX for possible values.
- *
- * @output:
- * BASE_table ::
- * A pointer to the BASE table.
- *
- * GDEF_table ::
- * A pointer to the GDEF table.
- *
- * GPOS_table ::
- * A pointer to the GPOS table.
- *
- * GSUB_table ::
- * A pointer to the GSUB table.
- *
- * JSTF_table ::
- * A pointer to the JSTF table.
- *
- * @return:
- * FreeType error code. 0~means success.
- *
- * @note:
- * This function only works with OpenType fonts, returning an error
- * otherwise.
- *
- * After use, the application should deallocate the five tables with
- * @FT_OpenType_Free. A NULL value indicates that the table either
- * doesn't exist in the font, or the application hasn't asked for
- * validation.
- */
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_OpenType_Validate
+ *
+ * @description:
+ * Validate various OpenType tables to assure that all offsets and
+ * indices are valid. The idea is that a higher-level library that
+ * actually does the text layout can access those tables without error
+ * checking (which can be quite time consuming).
+ *
+ * @input:
+ * face ::
+ * A handle to the input face.
+ *
+ * validation_flags ::
+ * A bit field that specifies the tables to be validated. See
+ * @FT_VALIDATE_OTXXX for possible values.
+ *
+ * @output:
+ * BASE_table ::
+ * A pointer to the BASE table.
+ *
+ * GDEF_table ::
+ * A pointer to the GDEF table.
+ *
+ * GPOS_table ::
+ * A pointer to the GPOS table.
+ *
+ * GSUB_table ::
+ * A pointer to the GSUB table.
+ *
+ * JSTF_table ::
+ * A pointer to the JSTF table.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * This function only works with OpenType fonts, returning an error
+ * otherwise.
+ *
+ * After use, the application should deallocate the five tables with
+ * @FT_OpenType_Free. A `NULL` value indicates that the table either
+ * doesn't exist in the font, or the application hasn't asked for
+ * validation.
+ */
FT_EXPORT( FT_Error )
FT_OpenType_Validate( FT_Face face,
FT_UInt validation_flags,
@@ -169,30 +170,32 @@ FT_BEGIN_HEADER
FT_Bytes *GSUB_table,
FT_Bytes *JSTF_table );
- /**********************************************************************
- *
- * @function:
- * FT_OpenType_Free
- *
- * @description:
- * Free the buffer allocated by OpenType validator.
- *
- * @input:
- * face ::
- * A handle to the input face.
- *
- * table ::
- * The pointer to the buffer that is allocated by
- * @FT_OpenType_Validate.
- *
- * @note:
- * This function must be used to free the buffer allocated by
- * @FT_OpenType_Validate only.
- */
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_OpenType_Free
+ *
+ * @description:
+ * Free the buffer allocated by OpenType validator.
+ *
+ * @input:
+ * face ::
+ * A handle to the input face.
+ *
+ * table ::
+ * The pointer to the buffer that is allocated by
+ * @FT_OpenType_Validate.
+ *
+ * @note:
+ * This function must be used to free the buffer allocated by
+ * @FT_OpenType_Validate only.
+ */
FT_EXPORT( void )
FT_OpenType_Free( FT_Face face,
FT_Bytes table );
+
/* */
diff --git a/thirdparty/freetype/include/freetype/ftoutln.h b/thirdparty/freetype/include/freetype/ftoutln.h
index 89389a49b7..75c3d01596 100644
--- a/thirdparty/freetype/include/freetype/ftoutln.h
+++ b/thirdparty/freetype/include/freetype/ftoutln.h
@@ -1,20 +1,20 @@
-/***************************************************************************/
-/* */
-/* ftoutln.h */
-/* */
-/* Support for the FT_Outline type used to store glyph shapes of */
-/* most scalable font formats (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftoutln.h
+ *
+ * Support for the FT_Outline type used to store glyph shapes of
+ * most scalable font formats (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTOUTLN_H_
@@ -34,127 +34,131 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* <Section> */
- /* outline_processing */
- /* */
- /* <Title> */
- /* Outline Processing */
- /* */
- /* <Abstract> */
- /* Functions to create, transform, and render vectorial glyph images. */
- /* */
- /* <Description> */
- /* This section contains routines used to create and destroy scalable */
- /* glyph images known as `outlines'. These can also be measured, */
- /* transformed, and converted into bitmaps and pixmaps. */
- /* */
- /* <Order> */
- /* FT_Outline */
- /* FT_Outline_New */
- /* FT_Outline_Done */
- /* FT_Outline_Copy */
- /* FT_Outline_Translate */
- /* FT_Outline_Transform */
- /* FT_Outline_Embolden */
- /* FT_Outline_EmboldenXY */
- /* FT_Outline_Reverse */
- /* FT_Outline_Check */
- /* */
- /* FT_Outline_Get_CBox */
- /* FT_Outline_Get_BBox */
- /* */
- /* FT_Outline_Get_Bitmap */
- /* FT_Outline_Render */
- /* FT_Outline_Decompose */
- /* FT_Outline_Funcs */
- /* FT_Outline_MoveToFunc */
- /* FT_Outline_LineToFunc */
- /* FT_Outline_ConicToFunc */
- /* FT_Outline_CubicToFunc */
- /* */
- /* FT_Orientation */
- /* FT_Outline_Get_Orientation */
- /* */
- /* FT_OUTLINE_XXX */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Outline_Decompose */
- /* */
- /* <Description> */
- /* Walk over an outline's structure to decompose it into individual */
- /* segments and Bezier arcs. This function also emits `move to' */
- /* operations to indicate the start of new contours in the outline. */
- /* */
- /* <Input> */
- /* outline :: A pointer to the source target. */
- /* */
- /* func_interface :: A table of `emitters', i.e., function pointers */
- /* called during decomposition to indicate path */
- /* operations. */
- /* */
- /* <InOut> */
- /* user :: A typeless pointer that is passed to each */
- /* emitter during the decomposition. It can be */
- /* used to store the state during the */
- /* decomposition. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* A contour that contains a single point only is represented by a */
- /* `move to' operation followed by `line to' to the same point. In */
- /* most cases, it is best to filter this out before using the */
- /* outline for stroking purposes (otherwise it would result in a */
- /* visible dot when round caps are used). */
- /* */
- /* Similarly, the function returns success for an empty outline also */
- /* (doing nothing, this is, not calling any emitter); if necessary, */
- /* you should filter this out, too. */
- /* */
+ /**************************************************************************
+ *
+ * @section:
+ * outline_processing
+ *
+ * @title:
+ * Outline Processing
+ *
+ * @abstract:
+ * Functions to create, transform, and render vectorial glyph images.
+ *
+ * @description:
+ * This section contains routines used to create and destroy scalable
+ * glyph images known as 'outlines'. These can also be measured,
+ * transformed, and converted into bitmaps and pixmaps.
+ *
+ * @order:
+ * FT_Outline
+ * FT_Outline_New
+ * FT_Outline_Done
+ * FT_Outline_Copy
+ * FT_Outline_Translate
+ * FT_Outline_Transform
+ * FT_Outline_Embolden
+ * FT_Outline_EmboldenXY
+ * FT_Outline_Reverse
+ * FT_Outline_Check
+ *
+ * FT_Outline_Get_CBox
+ * FT_Outline_Get_BBox
+ *
+ * FT_Outline_Get_Bitmap
+ * FT_Outline_Render
+ * FT_Outline_Decompose
+ * FT_Outline_Funcs
+ * FT_Outline_MoveToFunc
+ * FT_Outline_LineToFunc
+ * FT_Outline_ConicToFunc
+ * FT_Outline_CubicToFunc
+ *
+ * FT_Orientation
+ * FT_Outline_Get_Orientation
+ *
+ * FT_OUTLINE_XXX
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Outline_Decompose
+ *
+ * @description:
+ * Walk over an outline's structure to decompose it into individual
+ * segments and Bezier arcs. This function also emits 'move to'
+ * operations to indicate the start of new contours in the outline.
+ *
+ * @input:
+ * outline ::
+ * A pointer to the source target.
+ *
+ * func_interface ::
+ * A table of 'emitters', i.e., function pointers called during
+ * decomposition to indicate path operations.
+ *
+ * @inout:
+ * user ::
+ * A typeless pointer that is passed to each emitter during the
+ * decomposition. It can be used to store the state during the
+ * decomposition.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * A contour that contains a single point only is represented by a 'move
+ * to' operation followed by 'line to' to the same point. In most cases,
+ * it is best to filter this out before using the outline for stroking
+ * purposes (otherwise it would result in a visible dot when round caps
+ * are used).
+ *
+ * Similarly, the function returns success for an empty outline also
+ * (doing nothing, this is, not calling any emitter); if necessary, you
+ * should filter this out, too.
+ */
FT_EXPORT( FT_Error )
FT_Outline_Decompose( FT_Outline* outline,
const FT_Outline_Funcs* func_interface,
void* user );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Outline_New */
- /* */
- /* <Description> */
- /* Create a new outline of a given size. */
- /* */
- /* <Input> */
- /* library :: A handle to the library object from where the */
- /* outline is allocated. Note however that the new */
- /* outline will *not* necessarily be *freed*, when */
- /* destroying the library, by @FT_Done_FreeType. */
- /* */
- /* numPoints :: The maximum number of points within the outline. */
- /* Must be smaller than or equal to 0xFFFF (65535). */
- /* */
- /* numContours :: The maximum number of contours within the outline. */
- /* This value must be in the range 0 to `numPoints'. */
- /* */
- /* <Output> */
- /* anoutline :: A handle to the new outline. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* The reason why this function takes a `library' parameter is simply */
- /* to use the library's memory allocator. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Outline_New
+ *
+ * @description:
+ * Create a new outline of a given size.
+ *
+ * @input:
+ * library ::
+ * A handle to the library object from where the outline is allocated.
+ * Note however that the new outline will **not** necessarily be
+ * **freed**, when destroying the library, by @FT_Done_FreeType.
+ *
+ * numPoints ::
+ * The maximum number of points within the outline. Must be smaller
+ * than or equal to 0xFFFF (65535).
+ *
+ * numContours ::
+ * The maximum number of contours within the outline. This value must
+ * be in the range 0 to `numPoints`.
+ *
+ * @output:
+ * anoutline ::
+ * A handle to the new outline.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The reason why this function takes a `library` parameter is simply to
+ * use the library's memory allocator.
+ */
FT_EXPORT( FT_Error )
FT_Outline_New( FT_Library library,
FT_UInt numPoints,
@@ -162,372 +166,378 @@ FT_BEGIN_HEADER
FT_Outline *anoutline );
- FT_EXPORT( FT_Error )
- FT_Outline_New_Internal( FT_Memory memory,
- FT_UInt numPoints,
- FT_Int numContours,
- FT_Outline *anoutline );
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Outline_Done */
- /* */
- /* <Description> */
- /* Destroy an outline created with @FT_Outline_New. */
- /* */
- /* <Input> */
- /* library :: A handle of the library object used to allocate the */
- /* outline. */
- /* */
- /* outline :: A pointer to the outline object to be discarded. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* If the outline's `owner' field is not set, only the outline */
- /* descriptor will be released. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Outline_Done
+ *
+ * @description:
+ * Destroy an outline created with @FT_Outline_New.
+ *
+ * @input:
+ * library ::
+ * A handle of the library object used to allocate the outline.
+ *
+ * outline ::
+ * A pointer to the outline object to be discarded.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * If the outline's 'owner' field is not set, only the outline descriptor
+ * will be released.
+ */
FT_EXPORT( FT_Error )
FT_Outline_Done( FT_Library library,
FT_Outline* outline );
- FT_EXPORT( FT_Error )
- FT_Outline_Done_Internal( FT_Memory memory,
- FT_Outline* outline );
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Outline_Check */
- /* */
- /* <Description> */
- /* Check the contents of an outline descriptor. */
- /* */
- /* <Input> */
- /* outline :: A handle to a source outline. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* An empty outline, or an outline with a single point only is also */
- /* valid. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Outline_Check
+ *
+ * @description:
+ * Check the contents of an outline descriptor.
+ *
+ * @input:
+ * outline ::
+ * A handle to a source outline.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * An empty outline, or an outline with a single point only is also
+ * valid.
+ */
FT_EXPORT( FT_Error )
FT_Outline_Check( FT_Outline* outline );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Outline_Get_CBox */
- /* */
- /* <Description> */
- /* Return an outline's `control box'. The control box encloses all */
- /* the outline's points, including Bezier control points. Though it */
- /* coincides with the exact bounding box for most glyphs, it can be */
- /* slightly larger in some situations (like when rotating an outline */
- /* that contains Bezier outside arcs). */
- /* */
- /* Computing the control box is very fast, while getting the bounding */
- /* box can take much more time as it needs to walk over all segments */
- /* and arcs in the outline. To get the latter, you can use the */
- /* `ftbbox' component, which is dedicated to this single task. */
- /* */
- /* <Input> */
- /* outline :: A pointer to the source outline descriptor. */
- /* */
- /* <Output> */
- /* acbox :: The outline's control box. */
- /* */
- /* <Note> */
- /* See @FT_Glyph_Get_CBox for a discussion of tricky fonts. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Outline_Get_CBox
+ *
+ * @description:
+ * Return an outline's 'control box'. The control box encloses all the
+ * outline's points, including Bezier control points. Though it
+ * coincides with the exact bounding box for most glyphs, it can be
+ * slightly larger in some situations (like when rotating an outline that
+ * contains Bezier outside arcs).
+ *
+ * Computing the control box is very fast, while getting the bounding box
+ * can take much more time as it needs to walk over all segments and arcs
+ * in the outline. To get the latter, you can use the 'ftbbox'
+ * component, which is dedicated to this single task.
+ *
+ * @input:
+ * outline ::
+ * A pointer to the source outline descriptor.
+ *
+ * @output:
+ * acbox ::
+ * The outline's control box.
+ *
+ * @note:
+ * See @FT_Glyph_Get_CBox for a discussion of tricky fonts.
+ */
FT_EXPORT( void )
FT_Outline_Get_CBox( const FT_Outline* outline,
FT_BBox *acbox );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Outline_Translate */
- /* */
- /* <Description> */
- /* Apply a simple translation to the points of an outline. */
- /* */
- /* <InOut> */
- /* outline :: A pointer to the target outline descriptor. */
- /* */
- /* <Input> */
- /* xOffset :: The horizontal offset. */
- /* */
- /* yOffset :: The vertical offset. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Outline_Translate
+ *
+ * @description:
+ * Apply a simple translation to the points of an outline.
+ *
+ * @inout:
+ * outline ::
+ * A pointer to the target outline descriptor.
+ *
+ * @input:
+ * xOffset ::
+ * The horizontal offset.
+ *
+ * yOffset ::
+ * The vertical offset.
+ */
FT_EXPORT( void )
FT_Outline_Translate( const FT_Outline* outline,
FT_Pos xOffset,
FT_Pos yOffset );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Outline_Copy */
- /* */
- /* <Description> */
- /* Copy an outline into another one. Both objects must have the */
- /* same sizes (number of points & number of contours) when this */
- /* function is called. */
- /* */
- /* <Input> */
- /* source :: A handle to the source outline. */
- /* */
- /* <Output> */
- /* target :: A handle to the target outline. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Outline_Copy
+ *
+ * @description:
+ * Copy an outline into another one. Both objects must have the same
+ * sizes (number of points & number of contours) when this function is
+ * called.
+ *
+ * @input:
+ * source ::
+ * A handle to the source outline.
+ *
+ * @output:
+ * target ::
+ * A handle to the target outline.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ */
FT_EXPORT( FT_Error )
FT_Outline_Copy( const FT_Outline* source,
FT_Outline *target );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Outline_Transform */
- /* */
- /* <Description> */
- /* Apply a simple 2x2 matrix to all of an outline's points. Useful */
- /* for applying rotations, slanting, flipping, etc. */
- /* */
- /* <InOut> */
- /* outline :: A pointer to the target outline descriptor. */
- /* */
- /* <Input> */
- /* matrix :: A pointer to the transformation matrix. */
- /* */
- /* <Note> */
- /* You can use @FT_Outline_Translate if you need to translate the */
- /* outline's points. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Outline_Transform
+ *
+ * @description:
+ * Apply a simple 2x2 matrix to all of an outline's points. Useful for
+ * applying rotations, slanting, flipping, etc.
+ *
+ * @inout:
+ * outline ::
+ * A pointer to the target outline descriptor.
+ *
+ * @input:
+ * matrix ::
+ * A pointer to the transformation matrix.
+ *
+ * @note:
+ * You can use @FT_Outline_Translate if you need to translate the
+ * outline's points.
+ */
FT_EXPORT( void )
FT_Outline_Transform( const FT_Outline* outline,
const FT_Matrix* matrix );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Outline_Embolden */
- /* */
- /* <Description> */
- /* Embolden an outline. The new outline will be at most 4~times */
- /* `strength' pixels wider and higher. You may think of the left and */
- /* bottom borders as unchanged. */
- /* */
- /* Negative `strength' values to reduce the outline thickness are */
- /* possible also. */
- /* */
- /* <InOut> */
- /* outline :: A handle to the target outline. */
- /* */
- /* <Input> */
- /* strength :: How strong the glyph is emboldened. Expressed in */
- /* 26.6 pixel format. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* The used algorithm to increase or decrease the thickness of the */
- /* glyph doesn't change the number of points; this means that certain */
- /* situations like acute angles or intersections are sometimes */
- /* handled incorrectly. */
- /* */
- /* If you need `better' metrics values you should call */
- /* @FT_Outline_Get_CBox or @FT_Outline_Get_BBox. */
- /* */
- /* Example call: */
- /* */
- /* { */
- /* FT_Load_Glyph( face, index, FT_LOAD_DEFAULT ); */
- /* if ( face->glyph->format == FT_GLYPH_FORMAT_OUTLINE ) */
- /* FT_Outline_Embolden( &face->glyph->outline, strength ); */
- /* } */
- /* */
- /* To get meaningful results, font scaling values must be set with */
- /* functions like @FT_Set_Char_Size before calling FT_Render_Glyph. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Outline_Embolden
+ *
+ * @description:
+ * Embolden an outline. The new outline will be at most 4~times
+ * `strength` pixels wider and higher. You may think of the left and
+ * bottom borders as unchanged.
+ *
+ * Negative `strength` values to reduce the outline thickness are
+ * possible also.
+ *
+ * @inout:
+ * outline ::
+ * A handle to the target outline.
+ *
+ * @input:
+ * strength ::
+ * How strong the glyph is emboldened. Expressed in 26.6 pixel format.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The used algorithm to increase or decrease the thickness of the glyph
+ * doesn't change the number of points; this means that certain
+ * situations like acute angles or intersections are sometimes handled
+ * incorrectly.
+ *
+ * If you need 'better' metrics values you should call
+ * @FT_Outline_Get_CBox or @FT_Outline_Get_BBox.
+ *
+ * To get meaningful results, font scaling values must be set with
+ * functions like @FT_Set_Char_Size before calling FT_Render_Glyph.
+ *
+ * @example:
+ * ```
+ * FT_Load_Glyph( face, index, FT_LOAD_DEFAULT );
+ *
+ * if ( face->glyph->format == FT_GLYPH_FORMAT_OUTLINE )
+ * FT_Outline_Embolden( &face->glyph->outline, strength );
+ * ```
+ *
+ */
FT_EXPORT( FT_Error )
FT_Outline_Embolden( FT_Outline* outline,
FT_Pos strength );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Outline_EmboldenXY */
- /* */
- /* <Description> */
- /* Embolden an outline. The new outline will be `xstrength' pixels */
- /* wider and `ystrength' pixels higher. Otherwise, it is similar to */
- /* @FT_Outline_Embolden, which uses the same strength in both */
- /* directions. */
- /* */
- /* <Since> */
- /* 2.4.10 */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Outline_EmboldenXY
+ *
+ * @description:
+ * Embolden an outline. The new outline will be `xstrength` pixels wider
+ * and `ystrength` pixels higher. Otherwise, it is similar to
+ * @FT_Outline_Embolden, which uses the same strength in both directions.
+ *
+ * @since:
+ * 2.4.10
+ */
FT_EXPORT( FT_Error )
FT_Outline_EmboldenXY( FT_Outline* outline,
FT_Pos xstrength,
FT_Pos ystrength );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Outline_Reverse */
- /* */
- /* <Description> */
- /* Reverse the drawing direction of an outline. This is used to */
- /* ensure consistent fill conventions for mirrored glyphs. */
- /* */
- /* <InOut> */
- /* outline :: A pointer to the target outline descriptor. */
- /* */
- /* <Note> */
- /* This function toggles the bit flag @FT_OUTLINE_REVERSE_FILL in */
- /* the outline's `flags' field. */
- /* */
- /* It shouldn't be used by a normal client application, unless it */
- /* knows what it is doing. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Outline_Reverse
+ *
+ * @description:
+ * Reverse the drawing direction of an outline. This is used to ensure
+ * consistent fill conventions for mirrored glyphs.
+ *
+ * @inout:
+ * outline ::
+ * A pointer to the target outline descriptor.
+ *
+ * @note:
+ * This function toggles the bit flag @FT_OUTLINE_REVERSE_FILL in the
+ * outline's `flags` field.
+ *
+ * It shouldn't be used by a normal client application, unless it knows
+ * what it is doing.
+ */
FT_EXPORT( void )
FT_Outline_Reverse( FT_Outline* outline );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Outline_Get_Bitmap */
- /* */
- /* <Description> */
- /* Render an outline within a bitmap. The outline's image is simply */
- /* OR-ed to the target bitmap. */
- /* */
- /* <Input> */
- /* library :: A handle to a FreeType library object. */
- /* */
- /* outline :: A pointer to the source outline descriptor. */
- /* */
- /* <InOut> */
- /* abitmap :: A pointer to the target bitmap descriptor. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* This function does NOT CREATE the bitmap, it only renders an */
- /* outline image within the one you pass to it! Consequently, the */
- /* various fields in `abitmap' should be set accordingly. */
- /* */
- /* It will use the raster corresponding to the default glyph format. */
- /* */
- /* The value of the `num_grays' field in `abitmap' is ignored. If */
- /* you select the gray-level rasterizer, and you want less than 256 */
- /* gray levels, you have to use @FT_Outline_Render directly. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Outline_Get_Bitmap
+ *
+ * @description:
+ * Render an outline within a bitmap. The outline's image is simply
+ * OR-ed to the target bitmap.
+ *
+ * @input:
+ * library ::
+ * A handle to a FreeType library object.
+ *
+ * outline ::
+ * A pointer to the source outline descriptor.
+ *
+ * @inout:
+ * abitmap ::
+ * A pointer to the target bitmap descriptor.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * This function does **not create** the bitmap, it only renders an
+ * outline image within the one you pass to it! Consequently, the
+ * various fields in `abitmap` should be set accordingly.
+ *
+ * It will use the raster corresponding to the default glyph format.
+ *
+ * The value of the `num_grays` field in `abitmap` is ignored. If you
+ * select the gray-level rasterizer, and you want less than 256 gray
+ * levels, you have to use @FT_Outline_Render directly.
+ */
FT_EXPORT( FT_Error )
FT_Outline_Get_Bitmap( FT_Library library,
FT_Outline* outline,
const FT_Bitmap *abitmap );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Outline_Render */
- /* */
- /* <Description> */
- /* Render an outline within a bitmap using the current scan-convert. */
- /* This function uses an @FT_Raster_Params structure as an argument, */
- /* allowing advanced features like direct composition, translucency, */
- /* etc. */
- /* */
- /* <Input> */
- /* library :: A handle to a FreeType library object. */
- /* */
- /* outline :: A pointer to the source outline descriptor. */
- /* */
- /* <InOut> */
- /* params :: A pointer to an @FT_Raster_Params structure used to */
- /* describe the rendering operation. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* You should know what you are doing and how @FT_Raster_Params works */
- /* to use this function. */
- /* */
- /* The field `params.source' will be set to `outline' before the scan */
- /* converter is called, which means that the value you give to it is */
- /* actually ignored. */
- /* */
- /* The gray-level rasterizer always uses 256 gray levels. If you */
- /* want less gray levels, you have to provide your own span callback. */
- /* See the @FT_RASTER_FLAG_DIRECT value of the `flags' field in the */
- /* @FT_Raster_Params structure for more details. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Outline_Render
+ *
+ * @description:
+ * Render an outline within a bitmap using the current scan-convert.
+ * This function uses an @FT_Raster_Params structure as an argument,
+ * allowing advanced features like direct composition, translucency, etc.
+ *
+ * @input:
+ * library ::
+ * A handle to a FreeType library object.
+ *
+ * outline ::
+ * A pointer to the source outline descriptor.
+ *
+ * @inout:
+ * params ::
+ * A pointer to an @FT_Raster_Params structure used to describe the
+ * rendering operation.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * You should know what you are doing and how @FT_Raster_Params works to
+ * use this function.
+ *
+ * The field `params.source` will be set to `outline` before the scan
+ * converter is called, which means that the value you give to it is
+ * actually ignored.
+ *
+ * The gray-level rasterizer always uses 256 gray levels. If you want
+ * less gray levels, you have to provide your own span callback. See the
+ * @FT_RASTER_FLAG_DIRECT value of the `flags` field in the
+ * @FT_Raster_Params structure for more details.
+ */
FT_EXPORT( FT_Error )
FT_Outline_Render( FT_Library library,
FT_Outline* outline,
FT_Raster_Params* params );
- /**************************************************************************
- *
- * @enum:
- * FT_Orientation
- *
- * @description:
- * A list of values used to describe an outline's contour orientation.
- *
- * The TrueType and PostScript specifications use different conventions
- * to determine whether outline contours should be filled or unfilled.
- *
- * @values:
- * FT_ORIENTATION_TRUETYPE ::
- * According to the TrueType specification, clockwise contours must
- * be filled, and counter-clockwise ones must be unfilled.
- *
- * FT_ORIENTATION_POSTSCRIPT ::
- * According to the PostScript specification, counter-clockwise contours
- * must be filled, and clockwise ones must be unfilled.
- *
- * FT_ORIENTATION_FILL_RIGHT ::
- * This is identical to @FT_ORIENTATION_TRUETYPE, but is used to
- * remember that in TrueType, everything that is to the right of
- * the drawing direction of a contour must be filled.
- *
- * FT_ORIENTATION_FILL_LEFT ::
- * This is identical to @FT_ORIENTATION_POSTSCRIPT, but is used to
- * remember that in PostScript, everything that is to the left of
- * the drawing direction of a contour must be filled.
- *
- * FT_ORIENTATION_NONE ::
- * The orientation cannot be determined. That is, different parts of
- * the glyph have different orientation.
- *
- */
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_Orientation
+ *
+ * @description:
+ * A list of values used to describe an outline's contour orientation.
+ *
+ * The TrueType and PostScript specifications use different conventions
+ * to determine whether outline contours should be filled or unfilled.
+ *
+ * @values:
+ * FT_ORIENTATION_TRUETYPE ::
+ * According to the TrueType specification, clockwise contours must be
+ * filled, and counter-clockwise ones must be unfilled.
+ *
+ * FT_ORIENTATION_POSTSCRIPT ::
+ * According to the PostScript specification, counter-clockwise
+ * contours must be filled, and clockwise ones must be unfilled.
+ *
+ * FT_ORIENTATION_FILL_RIGHT ::
+ * This is identical to @FT_ORIENTATION_TRUETYPE, but is used to
+ * remember that in TrueType, everything that is to the right of the
+ * drawing direction of a contour must be filled.
+ *
+ * FT_ORIENTATION_FILL_LEFT ::
+ * This is identical to @FT_ORIENTATION_POSTSCRIPT, but is used to
+ * remember that in PostScript, everything that is to the left of the
+ * drawing direction of a contour must be filled.
+ *
+ * FT_ORIENTATION_NONE ::
+ * The orientation cannot be determined. That is, different parts of
+ * the glyph have different orientation.
+ *
+ */
typedef enum FT_Orientation_
{
FT_ORIENTATION_TRUETYPE = 0,
@@ -539,33 +549,34 @@ FT_BEGIN_HEADER
} FT_Orientation;
- /**************************************************************************
- *
- * @function:
- * FT_Outline_Get_Orientation
- *
- * @description:
- * This function analyzes a glyph outline and tries to compute its
- * fill orientation (see @FT_Orientation). This is done by integrating
- * the total area covered by the outline. The positive integral
- * corresponds to the clockwise orientation and @FT_ORIENTATION_POSTSCRIPT
- * is returned. The negative integral corresponds to the counter-clockwise
- * orientation and @FT_ORIENTATION_TRUETYPE is returned.
- *
- * Note that this will return @FT_ORIENTATION_TRUETYPE for empty
- * outlines.
- *
- * @input:
- * outline ::
- * A handle to the source outline.
- *
- * @return:
- * The orientation.
- *
- */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Outline_Get_Orientation
+ *
+ * @description:
+ * This function analyzes a glyph outline and tries to compute its fill
+ * orientation (see @FT_Orientation). This is done by integrating the
+ * total area covered by the outline. The positive integral corresponds
+ * to the clockwise orientation and @FT_ORIENTATION_POSTSCRIPT is
+ * returned. The negative integral corresponds to the counter-clockwise
+ * orientation and @FT_ORIENTATION_TRUETYPE is returned.
+ *
+ * Note that this will return @FT_ORIENTATION_TRUETYPE for empty
+ * outlines.
+ *
+ * @input:
+ * outline ::
+ * A handle to the source outline.
+ *
+ * @return:
+ * The orientation.
+ *
+ */
FT_EXPORT( FT_Orientation )
FT_Outline_Get_Orientation( FT_Outline* outline );
+
/* */
diff --git a/thirdparty/freetype/include/freetype/ftparams.h b/thirdparty/freetype/include/freetype/ftparams.h
index 5a9006c505..c374ee2f2f 100644
--- a/thirdparty/freetype/include/freetype/ftparams.h
+++ b/thirdparty/freetype/include/freetype/ftparams.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftparams.h */
-/* */
-/* FreeType API for possible FT_Parameter tags (specification only). */
-/* */
-/* Copyright 2017-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftparams.h
+ *
+ * FreeType API for possible FT_Parameter tags (specification only).
+ *
+ * Copyright (C) 2017-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTPARAMS_H_
@@ -51,16 +51,16 @@ FT_BEGIN_HEADER
*/
- /***************************************************************************
+ /**************************************************************************
*
- * @constant:
+ * @enum:
* FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_FAMILY
*
* @description:
* A tag for @FT_Parameter to make @FT_Open_Face ignore typographic
- * family names in the `name' table (introduced in OpenType version
- * 1.4). Use this for backward compatibility with legacy systems that
- * have a four-faces-per-family restriction.
+ * family names in the 'name' table (introduced in OpenType version 1.4).
+ * Use this for backward compatibility with legacy systems that have a
+ * four-faces-per-family restriction.
*
* @since:
* 2.8
@@ -75,14 +75,14 @@ FT_BEGIN_HEADER
FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_FAMILY
- /***************************************************************************
+ /**************************************************************************
*
- * @constant:
+ * @enum:
* FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY
*
* @description:
* A tag for @FT_Parameter to make @FT_Open_Face ignore typographic
- * subfamily names in the `name' table (introduced in OpenType version
+ * subfamily names in the 'name' table (introduced in OpenType version
* 1.4). Use this for backward compatibility with legacy systems that
* have a four-faces-per-family restriction.
*
@@ -99,9 +99,9 @@ FT_BEGIN_HEADER
FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY
- /***************************************************************************
+ /**************************************************************************
*
- * @constant:
+ * @enum:
* FT_PARAM_TAG_INCREMENTAL
*
* @description:
@@ -115,14 +115,14 @@ FT_BEGIN_HEADER
/**************************************************************************
*
- * @constant:
+ * @enum:
* FT_PARAM_TAG_LCD_FILTER_WEIGHTS
*
* @description:
* An @FT_Parameter tag to be used with @FT_Face_Properties. The
* corresponding argument specifies the five LCD filter weights for a
- * given face (if using @FT_LOAD_TARGET_LCD, for example), overriding
- * the global default values or the values set up with
+ * given face (if using @FT_LOAD_TARGET_LCD, for example), overriding the
+ * global default values or the values set up with
* @FT_Library_SetLcdFilterWeights.
*
* @since:
@@ -135,14 +135,13 @@ FT_BEGIN_HEADER
/**************************************************************************
*
- * @constant:
+ * @enum:
* FT_PARAM_TAG_RANDOM_SEED
*
* @description:
* An @FT_Parameter tag to be used with @FT_Face_Properties. The
* corresponding 32bit signed integer argument overrides the font
- * driver's random seed value with a face-specific one; see
- * @random-seed.
+ * driver's random seed value with a face-specific one; see @random-seed.
*
* @since:
* 2.8
@@ -154,7 +153,7 @@ FT_BEGIN_HEADER
/**************************************************************************
*
- * @constant:
+ * @enum:
* FT_PARAM_TAG_STEM_DARKENING
*
* @description:
@@ -163,10 +162,10 @@ FT_BEGIN_HEADER
* darkening, overriding the global default values or the values set up
* with @FT_Property_Set (see @no-stem-darkening).
*
- * This is a passive setting that only takes effect if the font driver
- * or autohinter honors it, which the CFF, Type~1, and CID drivers
- * always do, but the autohinter only in `light' hinting mode (as of
- * version 2.9).
+ * This is a passive setting that only takes effect if the font driver or
+ * autohinter honors it, which the CFF, Type~1, and CID drivers always
+ * do, but the autohinter only in 'light' hinting mode (as of version
+ * 2.9).
*
* @since:
* 2.8
@@ -176,19 +175,19 @@ FT_BEGIN_HEADER
FT_MAKE_TAG( 'd', 'a', 'r', 'k' )
- /***************************************************************************
- *
- * @constant:
- * FT_PARAM_TAG_UNPATENTED_HINTING
- *
- * @description:
- * Deprecated, no effect.
- *
- * Previously: A constant used as the tag of an @FT_Parameter structure to
- * indicate that unpatented methods only should be used by the TrueType
- * bytecode interpreter for a typeface opened by @FT_Open_Face.
- *
- */
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_PARAM_TAG_UNPATENTED_HINTING
+ *
+ * @description:
+ * Deprecated, no effect.
+ *
+ * Previously: A constant used as the tag of an @FT_Parameter structure
+ * to indicate that unpatented methods only should be used by the
+ * TrueType bytecode interpreter for a typeface opened by @FT_Open_Face.
+ *
+ */
#define FT_PARAM_TAG_UNPATENTED_HINTING \
FT_MAKE_TAG( 'u', 'n', 'p', 'a' )
diff --git a/thirdparty/freetype/include/freetype/ftpcfdrv.h b/thirdparty/freetype/include/freetype/ftpcfdrv.h
deleted file mode 100644
index 6622c936fb..0000000000
--- a/thirdparty/freetype/include/freetype/ftpcfdrv.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/***************************************************************************/
-/* */
-/* ftpcfdrv.h */
-/* */
-/* FreeType API for controlling the PCF driver (specification only). */
-/* */
-/* Copyright 2017 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#ifndef FTPCFDRV_H_
-#define FTPCFDRV_H_
-
-#include <ft2build.h>
-#include FT_FREETYPE_H
-
-#ifdef FREETYPE_H
-#error "freetype.h of FreeType 1 has been loaded!"
-#error "Please fix the directory search order for header files"
-#error "so that freetype.h of FreeType 2 is found first."
-#endif
-
-
-FT_BEGIN_HEADER
-
-
- /**************************************************************************
- *
- * @section:
- * pcf_driver
- *
- * @title:
- * The PCF driver
- *
- * @abstract:
- * Controlling the PCF driver module.
- *
- * @description:
- * While FreeType's PCF driver doesn't expose API functions by itself,
- * it is possible to control its behaviour with @FT_Property_Set and
- * @FT_Property_Get. Right now, there is a single property
- * `no-long-family-names' available if FreeType is compiled with
- * PCF_CONFIG_OPTION_LONG_FAMILY_NAMES.
- *
- * The PCF driver's module name is `pcf'.
- *
- */
-
-
- /**************************************************************************
- *
- * @property:
- * no-long-family-names
- *
- * @description:
- * If PCF_CONFIG_OPTION_LONG_FAMILY_NAMES is active while compiling
- * FreeType, the PCF driver constructs long family names.
- *
- * There are many PCF fonts just called `Fixed' which look completely
- * different, and which have nothing to do with each other. When
- * selecting `Fixed' in KDE or Gnome one gets results that appear rather
- * random, the style changes often if one changes the size and one
- * cannot select some fonts at all. The improve this situation, the PCF
- * module prepends the foundry name (plus a space) to the family name.
- * It also checks whether there are `wide' characters; all put together,
- * family names like `Sony Fixed' or `Misc Fixed Wide' are constructed.
- *
- * If `no-long-family-names' is set, this feature gets switched off.
- *
- * {
- * FT_Library library;
- * FT_Bool no_long_family_names = TRUE;
- *
- *
- * FT_Init_FreeType( &library );
- *
- * FT_Property_Set( library, "pcf",
- * "no-long-family-names",
- * &no_long_family_names );
- * }
- *
- * @note:
- * This property can be used with @FT_Property_Get also.
- *
- * This property can be set via the `FREETYPE_PROPERTIES' environment
- * variable (using values 1 and 0 for `on' and `off', respectively).
- *
- */
-
-
-FT_END_HEADER
-
-
-#endif /* FTPCFDRV_H_ */
-
-
-/* END */
diff --git a/thirdparty/freetype/include/freetype/ftpfr.h b/thirdparty/freetype/include/freetype/ftpfr.h
index a69cc482dc..b4eca76eb7 100644
--- a/thirdparty/freetype/include/freetype/ftpfr.h
+++ b/thirdparty/freetype/include/freetype/ftpfr.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftpfr.h */
-/* */
-/* FreeType API for accessing PFR-specific data (specification only). */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftpfr.h
+ *
+ * FreeType API for accessing PFR-specific data (specification only).
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTPFR_H_
@@ -32,60 +32,61 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* <Section> */
- /* pfr_fonts */
- /* */
- /* <Title> */
- /* PFR Fonts */
- /* */
- /* <Abstract> */
- /* PFR/TrueDoc specific API. */
- /* */
- /* <Description> */
- /* This section contains the declaration of PFR-specific functions. */
- /* */
- /*************************************************************************/
-
-
- /**********************************************************************
- *
- * @function:
- * FT_Get_PFR_Metrics
- *
- * @description:
- * Return the outline and metrics resolutions of a given PFR face.
- *
- * @input:
- * face :: Handle to the input face. It can be a non-PFR face.
- *
- * @output:
- * aoutline_resolution ::
- * Outline resolution. This is equivalent to `face->units_per_EM'
- * for non-PFR fonts. Optional (parameter can be NULL).
- *
- * ametrics_resolution ::
- * Metrics resolution. This is equivalent to `outline_resolution'
- * for non-PFR fonts. Optional (parameter can be NULL).
- *
- * ametrics_x_scale ::
- * A 16.16 fixed-point number used to scale distance expressed
- * in metrics units to device subpixels. This is equivalent to
- * `face->size->x_scale', but for metrics only. Optional (parameter
- * can be NULL).
- *
- * ametrics_y_scale ::
- * Same as `ametrics_x_scale' but for the vertical direction.
- * optional (parameter can be NULL).
- *
- * @return:
- * FreeType error code. 0~means success.
- *
- * @note:
- * If the input face is not a PFR, this function will return an error.
- * However, in all cases, it will return valid values.
- */
+ /**************************************************************************
+ *
+ * @section:
+ * pfr_fonts
+ *
+ * @title:
+ * PFR Fonts
+ *
+ * @abstract:
+ * PFR/TrueDoc-specific API.
+ *
+ * @description:
+ * This section contains the declaration of PFR-specific functions.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_PFR_Metrics
+ *
+ * @description:
+ * Return the outline and metrics resolutions of a given PFR face.
+ *
+ * @input:
+ * face ::
+ * Handle to the input face. It can be a non-PFR face.
+ *
+ * @output:
+ * aoutline_resolution ::
+ * Outline resolution. This is equivalent to `face->units_per_EM` for
+ * non-PFR fonts. Optional (parameter can be `NULL`).
+ *
+ * ametrics_resolution ::
+ * Metrics resolution. This is equivalent to `outline_resolution` for
+ * non-PFR fonts. Optional (parameter can be `NULL`).
+ *
+ * ametrics_x_scale ::
+ * A 16.16 fixed-point number used to scale distance expressed in
+ * metrics units to device subpixels. This is equivalent to
+ * `face->size->x_scale`, but for metrics only. Optional (parameter
+ * can be `NULL`).
+ *
+ * ametrics_y_scale ::
+ * Same as `ametrics_x_scale` but for the vertical direction.
+ * optional (parameter can be `NULL`).
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * If the input face is not a PFR, this function will return an error.
+ * However, in all cases, it will return valid values.
+ */
FT_EXPORT( FT_Error )
FT_Get_PFR_Metrics( FT_Face face,
FT_UInt *aoutline_resolution,
@@ -94,37 +95,41 @@ FT_BEGIN_HEADER
FT_Fixed *ametrics_y_scale );
- /**********************************************************************
- *
- * @function:
- * FT_Get_PFR_Kerning
- *
- * @description:
- * Return the kerning pair corresponding to two glyphs in a PFR face.
- * The distance is expressed in metrics units, unlike the result of
- * @FT_Get_Kerning.
- *
- * @input:
- * face :: A handle to the input face.
- *
- * left :: Index of the left glyph.
- *
- * right :: Index of the right glyph.
- *
- * @output:
- * avector :: A kerning vector.
- *
- * @return:
- * FreeType error code. 0~means success.
- *
- * @note:
- * This function always return distances in original PFR metrics
- * units. This is unlike @FT_Get_Kerning with the @FT_KERNING_UNSCALED
- * mode, which always returns distances converted to outline units.
- *
- * You can use the value of the `x_scale' and `y_scale' parameters
- * returned by @FT_Get_PFR_Metrics to scale these to device subpixels.
- */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_PFR_Kerning
+ *
+ * @description:
+ * Return the kerning pair corresponding to two glyphs in a PFR face.
+ * The distance is expressed in metrics units, unlike the result of
+ * @FT_Get_Kerning.
+ *
+ * @input:
+ * face ::
+ * A handle to the input face.
+ *
+ * left ::
+ * Index of the left glyph.
+ *
+ * right ::
+ * Index of the right glyph.
+ *
+ * @output:
+ * avector ::
+ * A kerning vector.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * This function always return distances in original PFR metrics units.
+ * This is unlike @FT_Get_Kerning with the @FT_KERNING_UNSCALED mode,
+ * which always returns distances converted to outline units.
+ *
+ * You can use the value of the `x_scale` and `y_scale` parameters
+ * returned by @FT_Get_PFR_Metrics to scale these to device subpixels.
+ */
FT_EXPORT( FT_Error )
FT_Get_PFR_Kerning( FT_Face face,
FT_UInt left,
@@ -132,30 +137,33 @@ FT_BEGIN_HEADER
FT_Vector *avector );
- /**********************************************************************
- *
- * @function:
- * FT_Get_PFR_Advance
- *
- * @description:
- * Return a given glyph advance, expressed in original metrics units,
- * from a PFR font.
- *
- * @input:
- * face :: A handle to the input face.
- *
- * gindex :: The glyph index.
- *
- * @output:
- * aadvance :: The glyph advance in metrics units.
- *
- * @return:
- * FreeType error code. 0~means success.
- *
- * @note:
- * You can use the `x_scale' or `y_scale' results of @FT_Get_PFR_Metrics
- * to convert the advance to device subpixels (i.e., 1/64th of pixels).
- */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_PFR_Advance
+ *
+ * @description:
+ * Return a given glyph advance, expressed in original metrics units,
+ * from a PFR font.
+ *
+ * @input:
+ * face ::
+ * A handle to the input face.
+ *
+ * gindex ::
+ * The glyph index.
+ *
+ * @output:
+ * aadvance ::
+ * The glyph advance in metrics units.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * You can use the `x_scale` or `y_scale` results of @FT_Get_PFR_Metrics
+ * to convert the advance to device subpixels (i.e., 1/64th of pixels).
+ */
FT_EXPORT( FT_Error )
FT_Get_PFR_Advance( FT_Face face,
FT_UInt gindex,
diff --git a/thirdparty/freetype/include/freetype/ftrender.h b/thirdparty/freetype/include/freetype/ftrender.h
index fa8ad22b98..a01c774272 100644
--- a/thirdparty/freetype/include/freetype/ftrender.h
+++ b/thirdparty/freetype/include/freetype/ftrender.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftrender.h */
-/* */
-/* FreeType renderer modules public interface (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftrender.h
+ *
+ * FreeType renderer modules public interface (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTRENDER_H_
@@ -28,12 +28,12 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* <Section> */
- /* module_management */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * @section:
+ * module_management
+ *
+ */
/* create a new glyph object */
@@ -116,32 +116,38 @@ FT_BEGIN_HEADER
#define FTRenderer_setMode FT_Renderer_SetModeFunc
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_Renderer_Class */
- /* */
- /* <Description> */
- /* The renderer module class descriptor. */
- /* */
- /* <Fields> */
- /* root :: The root @FT_Module_Class fields. */
- /* */
- /* glyph_format :: The glyph image format this renderer handles. */
- /* */
- /* render_glyph :: A method used to render the image that is in a */
- /* given glyph slot into a bitmap. */
- /* */
- /* transform_glyph :: A method used to transform the image that is in */
- /* a given glyph slot. */
- /* */
- /* get_glyph_cbox :: A method used to access the glyph's cbox. */
- /* */
- /* set_mode :: A method used to pass additional parameters. */
- /* */
- /* raster_class :: For @FT_GLYPH_FORMAT_OUTLINE renderers only. */
- /* This is a pointer to its raster's class. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Renderer_Class
+ *
+ * @description:
+ * The renderer module class descriptor.
+ *
+ * @fields:
+ * root ::
+ * The root @FT_Module_Class fields.
+ *
+ * glyph_format ::
+ * The glyph image format this renderer handles.
+ *
+ * render_glyph ::
+ * A method used to render the image that is in a given glyph slot into
+ * a bitmap.
+ *
+ * transform_glyph ::
+ * A method used to transform the image that is in a given glyph slot.
+ *
+ * get_glyph_cbox ::
+ * A method used to access the glyph's cbox.
+ *
+ * set_mode ::
+ * A method used to pass additional parameters.
+ *
+ * raster_class ::
+ * For @FT_GLYPH_FORMAT_OUTLINE renderers only. This is a pointer to
+ * its raster's class.
+ */
typedef struct FT_Renderer_Class_
{
FT_Module_Class root;
@@ -158,64 +164,70 @@ FT_BEGIN_HEADER
} FT_Renderer_Class;
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Get_Renderer */
- /* */
- /* <Description> */
- /* Retrieve the current renderer for a given glyph format. */
- /* */
- /* <Input> */
- /* library :: A handle to the library object. */
- /* */
- /* format :: The glyph format. */
- /* */
- /* <Return> */
- /* A renderer handle. 0~if none found. */
- /* */
- /* <Note> */
- /* An error will be returned if a module already exists by that name, */
- /* or if the module requires a version of FreeType that is too great. */
- /* */
- /* To add a new renderer, simply use @FT_Add_Module. To retrieve a */
- /* renderer by its name, use @FT_Get_Module. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Renderer
+ *
+ * @description:
+ * Retrieve the current renderer for a given glyph format.
+ *
+ * @input:
+ * library ::
+ * A handle to the library object.
+ *
+ * format ::
+ * The glyph format.
+ *
+ * @return:
+ * A renderer handle. 0~if none found.
+ *
+ * @note:
+ * An error will be returned if a module already exists by that name, or
+ * if the module requires a version of FreeType that is too great.
+ *
+ * To add a new renderer, simply use @FT_Add_Module. To retrieve a
+ * renderer by its name, use @FT_Get_Module.
+ */
FT_EXPORT( FT_Renderer )
FT_Get_Renderer( FT_Library library,
FT_Glyph_Format format );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Set_Renderer */
- /* */
- /* <Description> */
- /* Set the current renderer to use, and set additional mode. */
- /* */
- /* <InOut> */
- /* library :: A handle to the library object. */
- /* */
- /* <Input> */
- /* renderer :: A handle to the renderer object. */
- /* */
- /* num_params :: The number of additional parameters. */
- /* */
- /* parameters :: Additional parameters. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* In case of success, the renderer will be used to convert glyph */
- /* images in the renderer's known format into bitmaps. */
- /* */
- /* This doesn't change the current renderer for other formats. */
- /* */
- /* Currently, no FreeType renderer module uses `parameters'; you */
- /* should thus always pass NULL as the value. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Set_Renderer
+ *
+ * @description:
+ * Set the current renderer to use, and set additional mode.
+ *
+ * @inout:
+ * library ::
+ * A handle to the library object.
+ *
+ * @input:
+ * renderer ::
+ * A handle to the renderer object.
+ *
+ * num_params ::
+ * The number of additional parameters.
+ *
+ * parameters ::
+ * Additional parameters.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * In case of success, the renderer will be used to convert glyph images
+ * in the renderer's known format into bitmaps.
+ *
+ * This doesn't change the current renderer for other formats.
+ *
+ * Currently, no FreeType renderer module uses `parameters`; you should
+ * thus always pass `NULL` as the value.
+ */
FT_EXPORT( FT_Error )
FT_Set_Renderer( FT_Library library,
FT_Renderer renderer,
diff --git a/thirdparty/freetype/include/freetype/ftsizes.h b/thirdparty/freetype/include/freetype/ftsizes.h
index 72cb08bf2a..6c63cef2bf 100644
--- a/thirdparty/freetype/include/freetype/ftsizes.h
+++ b/thirdparty/freetype/include/freetype/ftsizes.h
@@ -1,28 +1,28 @@
-/***************************************************************************/
-/* */
-/* ftsizes.h */
-/* */
-/* FreeType size objects management (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* Typical application would normally not need to use these functions. */
- /* However, they have been placed in a public API for the rare cases */
- /* where they are needed. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * ftsizes.h
+ *
+ * FreeType size objects management (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * Typical application would normally not need to use these functions.
+ * However, they have been placed in a public API for the rare cases where
+ * they are needed.
+ *
+ */
#ifndef FTSIZES_H_
@@ -42,109 +42,110 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* <Section> */
- /* sizes_management */
- /* */
- /* <Title> */
- /* Size Management */
- /* */
- /* <Abstract> */
- /* Managing multiple sizes per face. */
- /* */
- /* <Description> */
- /* When creating a new face object (e.g., with @FT_New_Face), an */
- /* @FT_Size object is automatically created and used to store all */
- /* pixel-size dependent information, available in the `face->size' */
- /* field. */
- /* */
- /* It is however possible to create more sizes for a given face, */
- /* mostly in order to manage several character pixel sizes of the */
- /* same font family and style. See @FT_New_Size and @FT_Done_Size. */
- /* */
- /* Note that @FT_Set_Pixel_Sizes and @FT_Set_Char_Size only */
- /* modify the contents of the current `active' size; you thus need */
- /* to use @FT_Activate_Size to change it. */
- /* */
- /* 99% of applications won't need the functions provided here, */
- /* especially if they use the caching sub-system, so be cautious */
- /* when using these. */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_New_Size */
- /* */
- /* <Description> */
- /* Create a new size object from a given face object. */
- /* */
- /* <Input> */
- /* face :: A handle to a parent face object. */
- /* */
- /* <Output> */
- /* asize :: A handle to a new size object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* You need to call @FT_Activate_Size in order to select the new size */
- /* for upcoming calls to @FT_Set_Pixel_Sizes, @FT_Set_Char_Size, */
- /* @FT_Load_Glyph, @FT_Load_Char, etc. */
- /* */
+ /**************************************************************************
+ *
+ * @section:
+ * sizes_management
+ *
+ * @title:
+ * Size Management
+ *
+ * @abstract:
+ * Managing multiple sizes per face.
+ *
+ * @description:
+ * When creating a new face object (e.g., with @FT_New_Face), an @FT_Size
+ * object is automatically created and used to store all pixel-size
+ * dependent information, available in the `face->size` field.
+ *
+ * It is however possible to create more sizes for a given face, mostly
+ * in order to manage several character pixel sizes of the same font
+ * family and style. See @FT_New_Size and @FT_Done_Size.
+ *
+ * Note that @FT_Set_Pixel_Sizes and @FT_Set_Char_Size only modify the
+ * contents of the current 'active' size; you thus need to use
+ * @FT_Activate_Size to change it.
+ *
+ * 99% of applications won't need the functions provided here, especially
+ * if they use the caching sub-system, so be cautious when using these.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_New_Size
+ *
+ * @description:
+ * Create a new size object from a given face object.
+ *
+ * @input:
+ * face ::
+ * A handle to a parent face object.
+ *
+ * @output:
+ * asize ::
+ * A handle to a new size object.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * You need to call @FT_Activate_Size in order to select the new size for
+ * upcoming calls to @FT_Set_Pixel_Sizes, @FT_Set_Char_Size,
+ * @FT_Load_Glyph, @FT_Load_Char, etc.
+ */
FT_EXPORT( FT_Error )
FT_New_Size( FT_Face face,
FT_Size* size );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Done_Size */
- /* */
- /* <Description> */
- /* Discard a given size object. Note that @FT_Done_Face */
- /* automatically discards all size objects allocated with */
- /* @FT_New_Size. */
- /* */
- /* <Input> */
- /* size :: A handle to a target size object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Done_Size
+ *
+ * @description:
+ * Discard a given size object. Note that @FT_Done_Face automatically
+ * discards all size objects allocated with @FT_New_Size.
+ *
+ * @input:
+ * size ::
+ * A handle to a target size object.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ */
FT_EXPORT( FT_Error )
FT_Done_Size( FT_Size size );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Activate_Size */
- /* */
- /* <Description> */
- /* Even though it is possible to create several size objects for a */
- /* given face (see @FT_New_Size for details), functions like */
- /* @FT_Load_Glyph or @FT_Load_Char only use the one that has been */
- /* activated last to determine the `current character pixel size'. */
- /* */
- /* This function can be used to `activate' a previously created size */
- /* object. */
- /* */
- /* <Input> */
- /* size :: A handle to a target size object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* If `face' is the size's parent face object, this function changes */
- /* the value of `face->size' to the input size handle. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Activate_Size
+ *
+ * @description:
+ * Even though it is possible to create several size objects for a given
+ * face (see @FT_New_Size for details), functions like @FT_Load_Glyph or
+ * @FT_Load_Char only use the one that has been activated last to
+ * determine the 'current character pixel size'.
+ *
+ * This function can be used to 'activate' a previously created size
+ * object.
+ *
+ * @input:
+ * size ::
+ * A handle to a target size object.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * If `face` is the size's parent face object, this function changes the
+ * value of `face->size` to the input size handle.
+ */
FT_EXPORT( FT_Error )
FT_Activate_Size( FT_Size size );
diff --git a/thirdparty/freetype/include/freetype/ftsnames.h b/thirdparty/freetype/include/freetype/ftsnames.h
index 8eb8d70ff7..4d43602a42 100644
--- a/thirdparty/freetype/include/freetype/ftsnames.h
+++ b/thirdparty/freetype/include/freetype/ftsnames.h
@@ -1,22 +1,22 @@
-/***************************************************************************/
-/* */
-/* ftsnames.h */
-/* */
-/* Simple interface to access SFNT `name' tables (which are used */
-/* to hold font names, copyright info, notices, etc.) (specification). */
-/* */
-/* This is _not_ used to retrieve glyph names! */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftsnames.h
+ *
+ * Simple interface to access SFNT 'name' tables (which are used
+ * to hold font names, copyright info, notices, etc.) (specification).
+ *
+ * This is _not_ used to retrieve glyph names!
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTSNAMES_H_
@@ -37,72 +37,74 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* <Section> */
- /* sfnt_names */
- /* */
- /* <Title> */
- /* SFNT Names */
- /* */
- /* <Abstract> */
- /* Access the names embedded in TrueType and OpenType files. */
- /* */
- /* <Description> */
- /* The TrueType and OpenType specifications allow the inclusion of */
- /* a special names table (`name') in font files. This table contains */
- /* textual (and internationalized) information regarding the font, */
- /* like family name, copyright, version, etc. */
- /* */
- /* The definitions below are used to access them if available. */
- /* */
- /* Note that this has nothing to do with glyph names! */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_SfntName */
- /* */
- /* <Description> */
- /* A structure used to model an SFNT `name' table entry. */
- /* */
- /* <Fields> */
- /* platform_id :: The platform ID for `string'. */
- /* See @TT_PLATFORM_XXX for possible values. */
- /* */
- /* encoding_id :: The encoding ID for `string'. */
- /* See @TT_APPLE_ID_XXX, @TT_MAC_ID_XXX, */
- /* @TT_ISO_ID_XXX, @TT_MS_ID_XXX, and @TT_ADOBE_ID_XXX */
- /* for possible values. */
- /* */
- /* language_id :: The language ID for `string'. */
- /* See @TT_MAC_LANGID_XXX and @TT_MS_LANGID_XXX for */
- /* possible values. */
- /* */
- /* Registered OpenType values for `language_id' are */
- /* always smaller than 0x8000; values equal or larger */
- /* than 0x8000 usually indicate a language tag string */
- /* (introduced in OpenType version 1.6). Use function */
- /* @FT_Get_Sfnt_LangTag with `language_id' as its */
- /* argument to retrieve the associated language tag. */
- /* */
- /* name_id :: An identifier for `string'. */
- /* See @TT_NAME_ID_XXX for possible values. */
- /* */
- /* string :: The `name' string. Note that its format differs */
- /* depending on the (platform,encoding) pair, being */
- /* either a string of bytes (without a terminating */
- /* NULL byte) or containing UTF-16BE entities. */
- /* */
- /* string_len :: The length of `string' in bytes. */
- /* */
- /* <Note> */
- /* Please refer to the TrueType or OpenType specification for more */
- /* details. */
- /* */
+ /**************************************************************************
+ *
+ * @section:
+ * sfnt_names
+ *
+ * @title:
+ * SFNT Names
+ *
+ * @abstract:
+ * Access the names embedded in TrueType and OpenType files.
+ *
+ * @description:
+ * The TrueType and OpenType specifications allow the inclusion of a
+ * special names table ('name') in font files. This table contains
+ * textual (and internationalized) information regarding the font, like
+ * family name, copyright, version, etc.
+ *
+ * The definitions below are used to access them if available.
+ *
+ * Note that this has nothing to do with glyph names!
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_SfntName
+ *
+ * @description:
+ * A structure used to model an SFNT 'name' table entry.
+ *
+ * @fields:
+ * platform_id ::
+ * The platform ID for `string`. See @TT_PLATFORM_XXX for possible
+ * values.
+ *
+ * encoding_id ::
+ * The encoding ID for `string`. See @TT_APPLE_ID_XXX, @TT_MAC_ID_XXX,
+ * @TT_ISO_ID_XXX, @TT_MS_ID_XXX, and @TT_ADOBE_ID_XXX for possible
+ * values.
+ *
+ * language_id ::
+ * The language ID for `string`. See @TT_MAC_LANGID_XXX and
+ * @TT_MS_LANGID_XXX for possible values.
+ *
+ * Registered OpenType values for `language_id` are always smaller than
+ * 0x8000; values equal or larger than 0x8000 usually indicate a
+ * language tag string (introduced in OpenType version 1.6). Use
+ * function @FT_Get_Sfnt_LangTag with `language_id` as its argument to
+ * retrieve the associated language tag.
+ *
+ * name_id ::
+ * An identifier for `string`. See @TT_NAME_ID_XXX for possible
+ * values.
+ *
+ * string ::
+ * The 'name' string. Note that its format differs depending on the
+ * (platform,encoding) pair, being either a string of bytes (without a
+ * terminating `NULL` byte) or containing UTF-16BE entities.
+ *
+ * string_len ::
+ * The length of `string` in bytes.
+ *
+ * @note:
+ * Please refer to the TrueType or OpenType specification for more
+ * details.
+ */
typedef struct FT_SfntName_
{
FT_UShort platform_id;
@@ -116,83 +118,95 @@ FT_BEGIN_HEADER
} FT_SfntName;
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Get_Sfnt_Name_Count */
- /* */
- /* <Description> */
- /* Retrieve the number of name strings in the SFNT `name' table. */
- /* */
- /* <Input> */
- /* face :: A handle to the source face. */
- /* */
- /* <Return> */
- /* The number of strings in the `name' table. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Sfnt_Name_Count
+ *
+ * @description:
+ * Retrieve the number of name strings in the SFNT 'name' table.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face.
+ *
+ * @return:
+ * The number of strings in the 'name' table.
+ *
+ * @note:
+ * This function always returns an error if the config macro
+ * `TT_CONFIG_OPTION_SFNT_NAMES` is not defined in `ftoption.h`.
+ */
FT_EXPORT( FT_UInt )
FT_Get_Sfnt_Name_Count( FT_Face face );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Get_Sfnt_Name */
- /* */
- /* <Description> */
- /* Retrieve a string of the SFNT `name' table for a given index. */
- /* */
- /* <Input> */
- /* face :: A handle to the source face. */
- /* */
- /* idx :: The index of the `name' string. */
- /* */
- /* <Output> */
- /* aname :: The indexed @FT_SfntName structure. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* The `string' array returned in the `aname' structure is not */
- /* null-terminated. Note that you don't have to deallocate `string' */
- /* by yourself; FreeType takes care of it if you call @FT_Done_Face. */
- /* */
- /* Use @FT_Get_Sfnt_Name_Count to get the total number of available */
- /* `name' table entries, then do a loop until you get the right */
- /* platform, encoding, and name ID. */
- /* */
- /* `name' table format~1 entries can use language tags also, see */
- /* @FT_Get_Sfnt_LangTag. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Sfnt_Name
+ *
+ * @description:
+ * Retrieve a string of the SFNT 'name' table for a given index.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face.
+ *
+ * idx ::
+ * The index of the 'name' string.
+ *
+ * @output:
+ * aname ::
+ * The indexed @FT_SfntName structure.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The `string` array returned in the `aname` structure is not
+ * null-terminated. Note that you don't have to deallocate `string` by
+ * yourself; FreeType takes care of it if you call @FT_Done_Face.
+ *
+ * Use @FT_Get_Sfnt_Name_Count to get the total number of available
+ * 'name' table entries, then do a loop until you get the right platform,
+ * encoding, and name ID.
+ *
+ * 'name' table format~1 entries can use language tags also, see
+ * @FT_Get_Sfnt_LangTag.
+ *
+ * This function always returns an error if the config macro
+ * `TT_CONFIG_OPTION_SFNT_NAMES` is not defined in `ftoption.h`.
+ */
FT_EXPORT( FT_Error )
FT_Get_Sfnt_Name( FT_Face face,
FT_UInt idx,
FT_SfntName *aname );
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_SfntLangTag */
- /* */
- /* <Description> */
- /* A structure to model a language tag entry from an SFNT `name' */
- /* table. */
- /* */
- /* <Fields> */
- /* string :: The language tag string, encoded in UTF-16BE */
- /* (without trailing NULL bytes). */
- /* */
- /* string_len :: The length of `string' in *bytes*. */
- /* */
- /* <Note> */
- /* Please refer to the TrueType or OpenType specification for more */
- /* details. */
- /* */
- /* <Since> */
- /* 2.8 */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_SfntLangTag
+ *
+ * @description:
+ * A structure to model a language tag entry from an SFNT 'name' table.
+ *
+ * @fields:
+ * string ::
+ * The language tag string, encoded in UTF-16BE (without trailing
+ * `NULL` bytes).
+ *
+ * string_len ::
+ * The length of `string` in **bytes**.
+ *
+ * @note:
+ * Please refer to the TrueType or OpenType specification for more
+ * details.
+ *
+ * @since:
+ * 2.8
+ */
typedef struct FT_SfntLangTag_
{
FT_Byte* string; /* this string is *not* null-terminated! */
@@ -201,41 +215,47 @@ FT_BEGIN_HEADER
} FT_SfntLangTag;
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Get_Sfnt_LangTag */
- /* */
- /* <Description> */
- /* Retrieve the language tag associated with a language ID of an SFNT */
- /* `name' table entry. */
- /* */
- /* <Input> */
- /* face :: A handle to the source face. */
- /* */
- /* langID :: The language ID, as returned by @FT_Get_Sfnt_Name. */
- /* This is always a value larger than 0x8000. */
- /* */
- /* <Output> */
- /* alangTag :: The language tag associated with the `name' table */
- /* entry's language ID. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
- /* <Note> */
- /* The `string' array returned in the `alangTag' structure is not */
- /* null-terminated. Note that you don't have to deallocate `string' */
- /* by yourself; FreeType takes care of it if you call @FT_Done_Face. */
- /* */
- /* Only `name' table format~1 supports language tags. For format~0 */
- /* tables, this function always returns FT_Err_Invalid_Table. For */
- /* invalid format~1 language ID values, FT_Err_Invalid_Argument is */
- /* returned. */
- /* */
- /* <Since> */
- /* 2.8 */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Sfnt_LangTag
+ *
+ * @description:
+ * Retrieve the language tag associated with a language ID of an SFNT
+ * 'name' table entry.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face.
+ *
+ * langID ::
+ * The language ID, as returned by @FT_Get_Sfnt_Name. This is always a
+ * value larger than 0x8000.
+ *
+ * @output:
+ * alangTag ::
+ * The language tag associated with the 'name' table entry's language
+ * ID.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The `string` array returned in the `alangTag` structure is not
+ * null-terminated. Note that you don't have to deallocate `string` by
+ * yourself; FreeType takes care of it if you call @FT_Done_Face.
+ *
+ * Only 'name' table format~1 supports language tags. For format~0
+ * tables, this function always returns FT_Err_Invalid_Table. For
+ * invalid format~1 language ID values, FT_Err_Invalid_Argument is
+ * returned.
+ *
+ * This function always returns an error if the config macro
+ * `TT_CONFIG_OPTION_SFNT_NAMES` is not defined in `ftoption.h`.
+ *
+ * @since:
+ * 2.8
+ */
FT_EXPORT( FT_Error )
FT_Get_Sfnt_LangTag( FT_Face face,
FT_UInt langID,
diff --git a/thirdparty/freetype/include/freetype/ftstroke.h b/thirdparty/freetype/include/freetype/ftstroke.h
index 44b6fbe19f..01a9c1811c 100644
--- a/thirdparty/freetype/include/freetype/ftstroke.h
+++ b/thirdparty/freetype/include/freetype/ftstroke.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftstroke.h */
-/* */
-/* FreeType path stroker (specification). */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftstroke.h
+ *
+ * FreeType path stroker (specification).
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTSTROKE_H_
@@ -27,116 +27,113 @@
FT_BEGIN_HEADER
- /************************************************************************
- *
- * @section:
- * glyph_stroker
- *
- * @title:
- * Glyph Stroker
- *
- * @abstract:
- * Generating bordered and stroked glyphs.
- *
- * @description:
- * This component generates stroked outlines of a given vectorial
- * glyph. It also allows you to retrieve the `outside' and/or the
- * `inside' borders of the stroke.
- *
- * This can be useful to generate `bordered' glyph, i.e., glyphs
- * displayed with a coloured (and anti-aliased) border around their
- * shape.
- *
- * @order:
- * FT_Stroker
- *
- * FT_Stroker_LineJoin
- * FT_Stroker_LineCap
- * FT_StrokerBorder
- *
- * FT_Outline_GetInsideBorder
- * FT_Outline_GetOutsideBorder
- *
- * FT_Glyph_Stroke
- * FT_Glyph_StrokeBorder
- *
- * FT_Stroker_New
- * FT_Stroker_Set
- * FT_Stroker_Rewind
- * FT_Stroker_ParseOutline
- * FT_Stroker_Done
- *
- * FT_Stroker_BeginSubPath
- * FT_Stroker_EndSubPath
- *
- * FT_Stroker_LineTo
- * FT_Stroker_ConicTo
- * FT_Stroker_CubicTo
- *
- * FT_Stroker_GetBorderCounts
- * FT_Stroker_ExportBorder
- * FT_Stroker_GetCounts
- * FT_Stroker_Export
- *
- */
-
-
- /**************************************************************
- *
- * @type:
- * FT_Stroker
- *
- * @description:
- * Opaque handle to a path stroker object.
- */
+ /**************************************************************************
+ *
+ * @section:
+ * glyph_stroker
+ *
+ * @title:
+ * Glyph Stroker
+ *
+ * @abstract:
+ * Generating bordered and stroked glyphs.
+ *
+ * @description:
+ * This component generates stroked outlines of a given vectorial glyph.
+ * It also allows you to retrieve the 'outside' and/or the 'inside'
+ * borders of the stroke.
+ *
+ * This can be useful to generate 'bordered' glyph, i.e., glyphs
+ * displayed with a coloured (and anti-aliased) border around their
+ * shape.
+ *
+ * @order:
+ * FT_Stroker
+ *
+ * FT_Stroker_LineJoin
+ * FT_Stroker_LineCap
+ * FT_StrokerBorder
+ *
+ * FT_Outline_GetInsideBorder
+ * FT_Outline_GetOutsideBorder
+ *
+ * FT_Glyph_Stroke
+ * FT_Glyph_StrokeBorder
+ *
+ * FT_Stroker_New
+ * FT_Stroker_Set
+ * FT_Stroker_Rewind
+ * FT_Stroker_ParseOutline
+ * FT_Stroker_Done
+ *
+ * FT_Stroker_BeginSubPath
+ * FT_Stroker_EndSubPath
+ *
+ * FT_Stroker_LineTo
+ * FT_Stroker_ConicTo
+ * FT_Stroker_CubicTo
+ *
+ * FT_Stroker_GetBorderCounts
+ * FT_Stroker_ExportBorder
+ * FT_Stroker_GetCounts
+ * FT_Stroker_Export
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Stroker
+ *
+ * @description:
+ * Opaque handle to a path stroker object.
+ */
typedef struct FT_StrokerRec_* FT_Stroker;
- /**************************************************************
+ /**************************************************************************
*
* @enum:
* FT_Stroker_LineJoin
*
* @description:
- * These values determine how two joining lines are rendered
- * in a stroker.
+ * These values determine how two joining lines are rendered in a
+ * stroker.
*
* @values:
* FT_STROKER_LINEJOIN_ROUND ::
- * Used to render rounded line joins. Circular arcs are used
- * to join two lines smoothly.
+ * Used to render rounded line joins. Circular arcs are used to join
+ * two lines smoothly.
*
* FT_STROKER_LINEJOIN_BEVEL ::
- * Used to render beveled line joins. The outer corner of
- * the joined lines is filled by enclosing the triangular
- * region of the corner with a straight line between the
- * outer corners of each stroke.
+ * Used to render beveled line joins. The outer corner of the joined
+ * lines is filled by enclosing the triangular region of the corner
+ * with a straight line between the outer corners of each stroke.
*
* FT_STROKER_LINEJOIN_MITER_FIXED ::
- * Used to render mitered line joins, with fixed bevels if the
- * miter limit is exceeded. The outer edges of the strokes
- * for the two segments are extended until they meet at an
- * angle. If the segments meet at too sharp an angle (such
- * that the miter would extend from the intersection of the
- * segments a distance greater than the product of the miter
- * limit value and the border radius), then a bevel join (see
- * above) is used instead. This prevents long spikes being
- * created. FT_STROKER_LINEJOIN_MITER_FIXED generates a miter
- * line join as used in PostScript and PDF.
+ * Used to render mitered line joins, with fixed bevels if the miter
+ * limit is exceeded. The outer edges of the strokes for the two
+ * segments are extended until they meet at an angle. If the segments
+ * meet at too sharp an angle (such that the miter would extend from
+ * the intersection of the segments a distance greater than the product
+ * of the miter limit value and the border radius), then a bevel join
+ * (see above) is used instead. This prevents long spikes being
+ * created. `FT_STROKER_LINEJOIN_MITER_FIXED` generates a miter line
+ * join as used in PostScript and PDF.
*
* FT_STROKER_LINEJOIN_MITER_VARIABLE ::
* FT_STROKER_LINEJOIN_MITER ::
- * Used to render mitered line joins, with variable bevels if
- * the miter limit is exceeded. The intersection of the
- * strokes is clipped at a line perpendicular to the bisector
- * of the angle between the strokes, at the distance from the
- * intersection of the segments equal to the product of the
- * miter limit value and the border radius. This prevents
- * long spikes being created.
- * FT_STROKER_LINEJOIN_MITER_VARIABLE generates a mitered line
- * join as used in XPS. FT_STROKER_LINEJOIN_MITER is an alias
- * for FT_STROKER_LINEJOIN_MITER_VARIABLE, retained for
- * backward compatibility.
+ * Used to render mitered line joins, with variable bevels if the miter
+ * limit is exceeded. The intersection of the strokes is clipped at a
+ * line perpendicular to the bisector of the angle between the strokes,
+ * at the distance from the intersection of the segments equal to the
+ * product of the miter limit value and the border radius. This
+ * prevents long spikes being created.
+ * `FT_STROKER_LINEJOIN_MITER_VARIABLE` generates a mitered line join
+ * as used in XPS. `FT_STROKER_LINEJOIN_MITER` is an alias for
+ * `FT_STROKER_LINEJOIN_MITER_VARIABLE`, retained for backward
+ * compatibility.
*/
typedef enum FT_Stroker_LineJoin_
{
@@ -149,27 +146,25 @@ FT_BEGIN_HEADER
} FT_Stroker_LineJoin;
- /**************************************************************
+ /**************************************************************************
*
* @enum:
* FT_Stroker_LineCap
*
* @description:
- * These values determine how the end of opened sub-paths are
- * rendered in a stroke.
+ * These values determine how the end of opened sub-paths are rendered in
+ * a stroke.
*
* @values:
* FT_STROKER_LINECAP_BUTT ::
- * The end of lines is rendered as a full stop on the last
- * point itself.
+ * The end of lines is rendered as a full stop on the last point
+ * itself.
*
* FT_STROKER_LINECAP_ROUND ::
- * The end of lines is rendered as a half-circle around the
- * last point.
+ * The end of lines is rendered as a half-circle around the last point.
*
* FT_STROKER_LINECAP_SQUARE ::
- * The end of lines is rendered as a square around the
- * last point.
+ * The end of lines is rendered as a square around the last point.
*/
typedef enum FT_Stroker_LineCap_
{
@@ -180,14 +175,14 @@ FT_BEGIN_HEADER
} FT_Stroker_LineCap;
- /**************************************************************
+ /**************************************************************************
*
* @enum:
* FT_StrokerBorder
*
* @description:
- * These values are used to select a given stroke border
- * in @FT_Stroker_GetBorderCounts and @FT_Stroker_ExportBorder.
+ * These values are used to select a given stroke border in
+ * @FT_Stroker_GetBorderCounts and @FT_Stroker_ExportBorder.
*
* @values:
* FT_STROKER_BORDER_LEFT ::
@@ -197,9 +192,9 @@ FT_BEGIN_HEADER
* Select the right border, relative to the drawing direction.
*
* @note:
- * Applications are generally interested in the `inside' and `outside'
+ * Applications are generally interested in the 'inside' and 'outside'
* borders. However, there is no direct mapping between these and the
- * `left' and `right' ones, since this really depends on the glyph's
+ * 'left' and 'right' ones, since this really depends on the glyph's
* drawing orientation, which varies between font formats.
*
* You can however use @FT_Outline_GetInsideBorder and
@@ -213,14 +208,14 @@ FT_BEGIN_HEADER
} FT_StrokerBorder;
- /**************************************************************
+ /**************************************************************************
*
* @function:
* FT_Outline_GetInsideBorder
*
* @description:
- * Retrieve the @FT_StrokerBorder value corresponding to the
- * `inside' borders of a given outline.
+ * Retrieve the @FT_StrokerBorder value corresponding to the 'inside'
+ * borders of a given outline.
*
* @input:
* outline ::
@@ -234,14 +229,14 @@ FT_BEGIN_HEADER
FT_Outline_GetInsideBorder( FT_Outline* outline );
- /**************************************************************
+ /**************************************************************************
*
* @function:
* FT_Outline_GetOutsideBorder
*
* @description:
- * Retrieve the @FT_StrokerBorder value corresponding to the
- * `outside' borders of a given outline.
+ * Retrieve the @FT_StrokerBorder value corresponding to the 'outside'
+ * borders of a given outline.
*
* @input:
* outline ::
@@ -255,7 +250,7 @@ FT_BEGIN_HEADER
FT_Outline_GetOutsideBorder( FT_Outline* outline );
- /**************************************************************
+ /**************************************************************************
*
* @function:
* FT_Stroker_New
@@ -269,7 +264,7 @@ FT_BEGIN_HEADER
*
* @output:
* astroker ::
- * A new stroker object handle. NULL in case of error.
+ * A new stroker object handle. `NULL` in case of error.
*
* @return:
* FreeType error code. 0~means success.
@@ -279,7 +274,7 @@ FT_BEGIN_HEADER
FT_Stroker *astroker );
- /**************************************************************
+ /**************************************************************************
*
* @function:
* FT_Stroker_Set
@@ -301,13 +296,12 @@ FT_BEGIN_HEADER
* The line join style.
*
* miter_limit ::
- * The miter limit for the FT_STROKER_LINEJOIN_MITER_FIXED and
- * FT_STROKER_LINEJOIN_MITER_VARIABLE line join styles,
- * expressed as 16.16 fixed-point value.
+ * The miter limit for the `FT_STROKER_LINEJOIN_MITER_FIXED` and
+ * `FT_STROKER_LINEJOIN_MITER_VARIABLE` line join styles, expressed as
+ * 16.16 fixed-point value.
*
* @note:
- * The radius is expressed in the same units as the outline
- * coordinates.
+ * The radius is expressed in the same units as the outline coordinates.
*
* This function calls @FT_Stroker_Rewind automatically.
*/
@@ -319,16 +313,15 @@ FT_BEGIN_HEADER
FT_Fixed miter_limit );
- /**************************************************************
+ /**************************************************************************
*
* @function:
* FT_Stroker_Rewind
*
* @description:
- * Reset a stroker object without changing its attributes.
- * You should call this function before beginning a new
- * series of calls to @FT_Stroker_BeginSubPath or
- * @FT_Stroker_EndSubPath.
+ * Reset a stroker object without changing its attributes. You should
+ * call this function before beginning a new series of calls to
+ * @FT_Stroker_BeginSubPath or @FT_Stroker_EndSubPath.
*
* @input:
* stroker ::
@@ -338,15 +331,15 @@ FT_BEGIN_HEADER
FT_Stroker_Rewind( FT_Stroker stroker );
- /**************************************************************
+ /**************************************************************************
*
* @function:
* FT_Stroker_ParseOutline
*
* @description:
- * A convenience function used to parse a whole outline with
- * the stroker. The resulting outline(s) can be retrieved
- * later by functions like @FT_Stroker_GetCounts and @FT_Stroker_Export.
+ * A convenience function used to parse a whole outline with the stroker.
+ * The resulting outline(s) can be retrieved later by functions like
+ * @FT_Stroker_GetCounts and @FT_Stroker_Export.
*
* @input:
* stroker ::
@@ -356,18 +349,18 @@ FT_BEGIN_HEADER
* The source outline.
*
* opened ::
- * A boolean. If~1, the outline is treated as an open path instead
- * of a closed one.
+ * A boolean. If~1, the outline is treated as an open path instead of
+ * a closed one.
*
* @return:
* FreeType error code. 0~means success.
*
* @note:
- * If `opened' is~0 (the default), the outline is treated as a closed
- * path, and the stroker generates two distinct `border' outlines.
+ * If `opened` is~0 (the default), the outline is treated as a closed
+ * path, and the stroker generates two distinct 'border' outlines.
*
- * If `opened' is~1, the outline is processed as an open path, and the
- * stroker generates a single `stroke' outline.
+ * If `opened` is~1, the outline is processed as an open path, and the
+ * stroker generates a single 'stroke' outline.
*
* This function calls @FT_Stroker_Rewind automatically.
*/
@@ -377,7 +370,7 @@ FT_BEGIN_HEADER
FT_Bool opened );
- /**************************************************************
+ /**************************************************************************
*
* @function:
* FT_Stroker_BeginSubPath
@@ -399,8 +392,8 @@ FT_BEGIN_HEADER
* FreeType error code. 0~means success.
*
* @note:
- * This function is useful when you need to stroke a path that is
- * not stored as an @FT_Outline object.
+ * This function is useful when you need to stroke a path that is not
+ * stored as an @FT_Outline object.
*/
FT_EXPORT( FT_Error )
FT_Stroker_BeginSubPath( FT_Stroker stroker,
@@ -408,7 +401,7 @@ FT_BEGIN_HEADER
FT_Bool open );
- /**************************************************************
+ /**************************************************************************
*
* @function:
* FT_Stroker_EndSubPath
@@ -424,22 +417,22 @@ FT_BEGIN_HEADER
* FreeType error code. 0~means success.
*
* @note:
- * You should call this function after @FT_Stroker_BeginSubPath.
- * If the subpath was not `opened', this function `draws' a
- * single line segment to the start position when needed.
+ * You should call this function after @FT_Stroker_BeginSubPath. If the
+ * subpath was not 'opened', this function 'draws' a single line segment
+ * to the start position when needed.
*/
FT_EXPORT( FT_Error )
FT_Stroker_EndSubPath( FT_Stroker stroker );
- /**************************************************************
+ /**************************************************************************
*
* @function:
* FT_Stroker_LineTo
*
* @description:
- * `Draw' a single line segment in the stroker's current sub-path,
- * from the last position.
+ * 'Draw' a single line segment in the stroker's current sub-path, from
+ * the last position.
*
* @input:
* stroker ::
@@ -460,13 +453,13 @@ FT_BEGIN_HEADER
FT_Vector* to );
- /**************************************************************
+ /**************************************************************************
*
* @function:
* FT_Stroker_ConicTo
*
* @description:
- * `Draw' a single quadratic Bezier in the stroker's current sub-path,
+ * 'Draw' a single quadratic Bezier in the stroker's current sub-path,
* from the last position.
*
* @input:
@@ -492,14 +485,14 @@ FT_BEGIN_HEADER
FT_Vector* to );
- /**************************************************************
+ /**************************************************************************
*
* @function:
* FT_Stroker_CubicTo
*
* @description:
- * `Draw' a single cubic Bezier in the stroker's current sub-path,
- * from the last position.
+ * 'Draw' a single cubic Bezier in the stroker's current sub-path, from
+ * the last position.
*
* @input:
* stroker ::
@@ -528,16 +521,16 @@ FT_BEGIN_HEADER
FT_Vector* to );
- /**************************************************************
+ /**************************************************************************
*
* @function:
* FT_Stroker_GetBorderCounts
*
* @description:
- * Call this function once you have finished parsing your paths
- * with the stroker. It returns the number of points and
- * contours necessary to export one of the `border' or `stroke'
- * outlines generated by the stroker.
+ * Call this function once you have finished parsing your paths with the
+ * stroker. It returns the number of points and contours necessary to
+ * export one of the 'border' or 'stroke' outlines generated by the
+ * stroker.
*
* @input:
* stroker ::
@@ -557,15 +550,15 @@ FT_BEGIN_HEADER
* FreeType error code. 0~means success.
*
* @note:
- * When an outline, or a sub-path, is `closed', the stroker generates
- * two independent `border' outlines, named `left' and `right'.
+ * When an outline, or a sub-path, is 'closed', the stroker generates two
+ * independent 'border' outlines, named 'left' and 'right'.
*
- * When the outline, or a sub-path, is `opened', the stroker merges
- * the `border' outlines with caps. The `left' border receives all
- * points, while the `right' border becomes empty.
+ * When the outline, or a sub-path, is 'opened', the stroker merges the
+ * 'border' outlines with caps. The 'left' border receives all points,
+ * while the 'right' border becomes empty.
*
- * Use the function @FT_Stroker_GetCounts instead if you want to
- * retrieve the counts associated to both borders.
+ * Use the function @FT_Stroker_GetCounts instead if you want to retrieve
+ * the counts associated to both borders.
*/
FT_EXPORT( FT_Error )
FT_Stroker_GetBorderCounts( FT_Stroker stroker,
@@ -574,19 +567,17 @@ FT_BEGIN_HEADER
FT_UInt *anum_contours );
- /**************************************************************
+ /**************************************************************************
*
* @function:
* FT_Stroker_ExportBorder
*
* @description:
- * Call this function after @FT_Stroker_GetBorderCounts to
- * export the corresponding border to your own @FT_Outline
- * structure.
+ * Call this function after @FT_Stroker_GetBorderCounts to export the
+ * corresponding border to your own @FT_Outline structure.
*
- * Note that this function appends the border points and
- * contours to your outline, but does not try to resize its
- * arrays.
+ * Note that this function appends the border points and contours to your
+ * outline, but does not try to resize its arrays.
*
* @input:
* stroker ::
@@ -599,19 +590,19 @@ FT_BEGIN_HEADER
* The target outline handle.
*
* @note:
- * Always call this function after @FT_Stroker_GetBorderCounts to
- * get sure that there is enough room in your @FT_Outline object to
- * receive all new data.
+ * Always call this function after @FT_Stroker_GetBorderCounts to get
+ * sure that there is enough room in your @FT_Outline object to receive
+ * all new data.
*
- * When an outline, or a sub-path, is `closed', the stroker generates
- * two independent `border' outlines, named `left' and `right'.
+ * When an outline, or a sub-path, is 'closed', the stroker generates two
+ * independent 'border' outlines, named 'left' and 'right'.
*
- * When the outline, or a sub-path, is `opened', the stroker merges
- * the `border' outlines with caps. The `left' border receives all
- * points, while the `right' border becomes empty.
+ * When the outline, or a sub-path, is 'opened', the stroker merges the
+ * 'border' outlines with caps. The 'left' border receives all points,
+ * while the 'right' border becomes empty.
*
- * Use the function @FT_Stroker_Export instead if you want to
- * retrieve all borders at once.
+ * Use the function @FT_Stroker_Export instead if you want to retrieve
+ * all borders at once.
*/
FT_EXPORT( void )
FT_Stroker_ExportBorder( FT_Stroker stroker,
@@ -619,16 +610,15 @@ FT_BEGIN_HEADER
FT_Outline* outline );
- /**************************************************************
+ /**************************************************************************
*
* @function:
* FT_Stroker_GetCounts
*
* @description:
- * Call this function once you have finished parsing your paths
- * with the stroker. It returns the number of points and
- * contours necessary to export all points/borders from the stroked
- * outline/path.
+ * Call this function once you have finished parsing your paths with the
+ * stroker. It returns the number of points and contours necessary to
+ * export all points/borders from the stroked outline/path.
*
* @input:
* stroker ::
@@ -650,18 +640,17 @@ FT_BEGIN_HEADER
FT_UInt *anum_contours );
- /**************************************************************
+ /**************************************************************************
*
* @function:
* FT_Stroker_Export
*
* @description:
- * Call this function after @FT_Stroker_GetBorderCounts to
- * export all borders to your own @FT_Outline structure.
+ * Call this function after @FT_Stroker_GetBorderCounts to export all
+ * borders to your own @FT_Outline structure.
*
- * Note that this function appends the border points and
- * contours to your outline, but does not try to resize its
- * arrays.
+ * Note that this function appends the border points and contours to your
+ * outline, but does not try to resize its arrays.
*
* @input:
* stroker ::
@@ -675,7 +664,7 @@ FT_BEGIN_HEADER
FT_Outline* outline );
- /**************************************************************
+ /**************************************************************************
*
* @function:
* FT_Stroker_Done
@@ -685,13 +674,13 @@ FT_BEGIN_HEADER
*
* @input:
* stroker ::
- * A stroker handle. Can be NULL.
+ * A stroker handle. Can be `NULL`.
*/
FT_EXPORT( void )
FT_Stroker_Done( FT_Stroker stroker );
- /**************************************************************
+ /**************************************************************************
*
* @function:
* FT_Glyph_Stroke
@@ -708,8 +697,7 @@ FT_BEGIN_HEADER
* A stroker handle.
*
* destroy ::
- * A Boolean. If~1, the source glyph object is destroyed
- * on success.
+ * A Boolean. If~1, the source glyph object is destroyed on success.
*
* @return:
* FreeType error code. 0~means success.
@@ -719,8 +707,8 @@ FT_BEGIN_HEADER
*
* Adding stroke may yield a significantly wider and taller glyph
* depending on how large of a radius was used to stroke the glyph. You
- * may need to manually adjust horizontal and vertical advance amounts
- * to account for this added size.
+ * may need to manually adjust horizontal and vertical advance amounts to
+ * account for this added size.
*/
FT_EXPORT( FT_Error )
FT_Glyph_Stroke( FT_Glyph *pglyph,
@@ -728,14 +716,14 @@ FT_BEGIN_HEADER
FT_Bool destroy );
- /**************************************************************
+ /**************************************************************************
*
* @function:
* FT_Glyph_StrokeBorder
*
* @description:
- * Stroke a given outline glyph object with a given stroker, but
- * only return either its inside or outside border.
+ * Stroke a given outline glyph object with a given stroker, but only
+ * return either its inside or outside border.
*
* @inout:
* pglyph ::
@@ -746,12 +734,11 @@ FT_BEGIN_HEADER
* A stroker handle.
*
* inside ::
- * A Boolean. If~1, return the inside border, otherwise
- * the outside border.
+ * A Boolean. If~1, return the inside border, otherwise the outside
+ * border.
*
* destroy ::
- * A Boolean. If~1, the source glyph object is destroyed
- * on success.
+ * A Boolean. If~1, the source glyph object is destroyed on success.
*
* @return:
* FreeType error code. 0~means success.
@@ -761,8 +748,8 @@ FT_BEGIN_HEADER
*
* Adding stroke may yield a significantly wider and taller glyph
* depending on how large of a radius was used to stroke the glyph. You
- * may need to manually adjust horizontal and vertical advance amounts
- * to account for this added size.
+ * may need to manually adjust horizontal and vertical advance amounts to
+ * account for this added size.
*/
FT_EXPORT( FT_Error )
FT_Glyph_StrokeBorder( FT_Glyph *pglyph,
diff --git a/thirdparty/freetype/include/freetype/ftsynth.h b/thirdparty/freetype/include/freetype/ftsynth.h
index ff9fb43d96..8754f97cee 100644
--- a/thirdparty/freetype/include/freetype/ftsynth.h
+++ b/thirdparty/freetype/include/freetype/ftsynth.h
@@ -1,20 +1,20 @@
-/***************************************************************************/
-/* */
-/* ftsynth.h */
-/* */
-/* FreeType synthesizing code for emboldening and slanting */
-/* (specification). */
-/* */
-/* Copyright 2000-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftsynth.h
+ *
+ * FreeType synthesizing code for emboldening and slanting
+ * (specification).
+ *
+ * Copyright (C) 2000-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
/*************************************************************************/
@@ -35,7 +35,7 @@
/* Main reason for not lifting the functions in this module to a */
- /* `standard' API is that the used parameters for emboldening and */
+ /* 'standard' API is that the used parameters for emboldening and */
/* slanting are not configurable. Consider the functions as a */
/* code resource that should be copied into the application and */
/* adapted to the particular needs. */
@@ -57,7 +57,7 @@
FT_BEGIN_HEADER
- /* Embolden a glyph by a `reasonable' value (which is highly a matter of */
+ /* Embolden a glyph by a 'reasonable' value (which is highly a matter of */
/* taste). This function is actually a convenience function, providing */
/* a wrapper for @FT_Outline_Embolden and @FT_Bitmap_Embolden. */
/* */
diff --git a/thirdparty/freetype/include/freetype/ftsystem.h b/thirdparty/freetype/include/freetype/ftsystem.h
index f6b1629ef2..889a6ba172 100644
--- a/thirdparty/freetype/include/freetype/ftsystem.h
+++ b/thirdparty/freetype/include/freetype/ftsystem.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftsystem.h */
-/* */
-/* FreeType low-level system interface definition (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftsystem.h
+ *
+ * FreeType low-level system interface definition (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTSYSTEM_H_
@@ -26,34 +26,33 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* <Section> */
- /* system_interface */
- /* */
- /* <Title> */
- /* System Interface */
- /* */
- /* <Abstract> */
- /* How FreeType manages memory and i/o. */
- /* */
- /* <Description> */
- /* This section contains various definitions related to memory */
- /* management and i/o access. You need to understand this */
- /* information if you want to use a custom memory manager or you own */
- /* i/o streams. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * @section:
+ * system_interface
+ *
+ * @title:
+ * System Interface
+ *
+ * @abstract:
+ * How FreeType manages memory and i/o.
+ *
+ * @description:
+ * This section contains various definitions related to memory management
+ * and i/o access. You need to understand this information if you want to
+ * use a custom memory manager or you own i/o streams.
+ *
+ */
- /*************************************************************************/
- /* */
- /* M E M O R Y M A N A G E M E N T */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * M E M O R Y M A N A G E M E N T
+ *
+ */
- /*************************************************************************
+ /**************************************************************************
*
* @type:
* FT_Memory
@@ -66,13 +65,13 @@ FT_BEGIN_HEADER
typedef struct FT_MemoryRec_* FT_Memory;
- /*************************************************************************
+ /**************************************************************************
*
* @functype:
* FT_Alloc_Func
*
* @description:
- * A function used to allocate `size' bytes from `memory'.
+ * A function used to allocate `size` bytes from `memory`.
*
* @input:
* memory ::
@@ -90,7 +89,7 @@ FT_BEGIN_HEADER
long size );
- /*************************************************************************
+ /**************************************************************************
*
* @functype:
* FT_Free_Func
@@ -111,7 +110,7 @@ FT_BEGIN_HEADER
void* block );
- /*************************************************************************
+ /**************************************************************************
*
* @functype:
* FT_Realloc_Func
@@ -146,7 +145,7 @@ FT_BEGIN_HEADER
void* block );
- /*************************************************************************
+ /**************************************************************************
*
* @struct:
* FT_MemoryRec
@@ -177,14 +176,14 @@ FT_BEGIN_HEADER
};
- /*************************************************************************/
- /* */
- /* I / O M A N A G E M E N T */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * I / O M A N A G E M E N T
+ *
+ */
- /*************************************************************************
+ /**************************************************************************
*
* @type:
* FT_Stream
@@ -193,21 +192,21 @@ FT_BEGIN_HEADER
* A handle to an input stream.
*
* @also:
- * See @FT_StreamRec for the publicly accessible fields of a given
- * stream object.
+ * See @FT_StreamRec for the publicly accessible fields of a given stream
+ * object.
*
*/
typedef struct FT_StreamRec_* FT_Stream;
- /*************************************************************************
+ /**************************************************************************
*
* @struct:
* FT_StreamDesc
*
* @description:
* A union type used to store either a long or a pointer. This is used
- * to store a file descriptor or a `FILE*' in an input stream.
+ * to store a file descriptor or a `FILE*` in an input stream.
*
*/
typedef union FT_StreamDesc_
@@ -218,7 +217,7 @@ FT_BEGIN_HEADER
} FT_StreamDesc;
- /*************************************************************************
+ /**************************************************************************
*
* @functype:
* FT_Stream_IoFunc
@@ -243,9 +242,8 @@ FT_BEGIN_HEADER
* The number of bytes effectively read by the stream.
*
* @note:
- * This function might be called to perform a seek or skip operation
- * with a `count' of~0. A non-zero return value then indicates an
- * error.
+ * This function might be called to perform a seek or skip operation with
+ * a `count` of~0. A non-zero return value then indicates an error.
*
*/
typedef unsigned long
@@ -255,7 +253,7 @@ FT_BEGIN_HEADER
unsigned long count );
- /*************************************************************************
+ /**************************************************************************
*
* @functype:
* FT_Stream_CloseFunc
@@ -265,14 +263,14 @@ FT_BEGIN_HEADER
*
* @input:
* stream ::
- * A handle to the target stream.
+ * A handle to the target stream.
*
*/
typedef void
(*FT_Stream_CloseFunc)( FT_Stream stream );
- /*************************************************************************
+ /**************************************************************************
*
* @struct:
* FT_StreamRec
@@ -283,7 +281,7 @@ FT_BEGIN_HEADER
* @input:
* base ::
* For memory-based streams, this is the address of the first stream
- * byte in memory. This field should always be set to NULL for
+ * byte in memory. This field should always be set to `NULL` for
* disk-based streams.
*
* size ::
@@ -299,7 +297,7 @@ FT_BEGIN_HEADER
*
* descriptor ::
* This field is a union that can hold an integer or a pointer. It is
- * used by stream implementations to store file descriptors or `FILE*'
+ * used by stream implementations to store file descriptors or `FILE*`
* pointers.
*
* pathname ::
@@ -314,13 +312,13 @@ FT_BEGIN_HEADER
* The stream's close function.
*
* memory ::
- * The memory manager to use to preload frames. This is set
- * internally by FreeType and shouldn't be touched by stream
- * implementations.
+ * The memory manager to use to preload frames. This is set internally
+ * by FreeType and shouldn't be touched by stream implementations.
*
* cursor ::
* This field is set and used internally by FreeType when parsing
- * frames.
+ * frames. In particular, the `FT_GET_XXX` macros use this instead of
+ * the `pos` field.
*
* limit ::
* This field is set and used internally by FreeType when parsing
diff --git a/thirdparty/freetype/include/freetype/fttrigon.h b/thirdparty/freetype/include/freetype/fttrigon.h
index 2e3f3f1f73..37e1412fdf 100644
--- a/thirdparty/freetype/include/freetype/fttrigon.h
+++ b/thirdparty/freetype/include/freetype/fttrigon.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* fttrigon.h */
-/* */
-/* FreeType trigonometric functions (specification). */
-/* */
-/* Copyright 2001-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * fttrigon.h
+ *
+ * FreeType trigonometric functions (specification).
+ *
+ * Copyright (C) 2001-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTTRIGON_H_
@@ -31,15 +31,15 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* <Section> */
- /* computations */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * @section:
+ * computations
+ *
+ */
- /*************************************************************************
+ /**************************************************************************
*
* @type:
* FT_Angle
@@ -52,7 +52,7 @@ FT_BEGIN_HEADER
typedef FT_Fixed FT_Angle;
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_ANGLE_PI
@@ -64,7 +64,7 @@ FT_BEGIN_HEADER
#define FT_ANGLE_PI ( 180L << 16 )
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_ANGLE_2PI
@@ -76,7 +76,7 @@ FT_BEGIN_HEADER
#define FT_ANGLE_2PI ( FT_ANGLE_PI * 2 )
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_ANGLE_PI2
@@ -88,7 +88,7 @@ FT_BEGIN_HEADER
#define FT_ANGLE_PI2 ( FT_ANGLE_PI / 2 )
- /*************************************************************************
+ /**************************************************************************
*
* @macro:
* FT_ANGLE_PI4
@@ -100,7 +100,7 @@ FT_BEGIN_HEADER
#define FT_ANGLE_PI4 ( FT_ANGLE_PI / 4 )
- /*************************************************************************
+ /**************************************************************************
*
* @function:
* FT_Sin
@@ -124,7 +124,7 @@ FT_BEGIN_HEADER
FT_Sin( FT_Angle angle );
- /*************************************************************************
+ /**************************************************************************
*
* @function:
* FT_Cos
@@ -148,7 +148,7 @@ FT_BEGIN_HEADER
FT_Cos( FT_Angle angle );
- /*************************************************************************
+ /**************************************************************************
*
* @function:
* FT_Tan
@@ -168,14 +168,14 @@ FT_BEGIN_HEADER
FT_Tan( FT_Angle angle );
- /*************************************************************************
+ /**************************************************************************
*
* @function:
* FT_Atan2
*
* @description:
- * Return the arc-tangent corresponding to a given vector (x,y) in
- * the 2d plane.
+ * Return the arc-tangent corresponding to a given vector (x,y) in the 2d
+ * plane.
*
* @input:
* x ::
@@ -193,7 +193,7 @@ FT_BEGIN_HEADER
FT_Fixed y );
- /*************************************************************************
+ /**************************************************************************
*
* @function:
* FT_Angle_Diff
@@ -210,7 +210,7 @@ FT_BEGIN_HEADER
* Second angle.
*
* @return:
- * Constrained value of `value2-value1'.
+ * Constrained value of `angle2-angle1`.
*
*/
FT_EXPORT( FT_Angle )
@@ -218,15 +218,15 @@ FT_BEGIN_HEADER
FT_Angle angle2 );
- /*************************************************************************
+ /**************************************************************************
*
* @function:
* FT_Vector_Unit
*
* @description:
* Return the unit vector corresponding to a given angle. After the
- * call, the value of `vec.x' will be `cos(angle)', and the value of
- * `vec.y' will be `sin(angle)'.
+ * call, the value of `vec.x` will be `cos(angle)`, and the value of
+ * `vec.y` will be `sin(angle)`.
*
* This function is useful to retrieve both the sinus and cosinus of a
* given angle quickly.
@@ -245,7 +245,7 @@ FT_BEGIN_HEADER
FT_Angle angle );
- /*************************************************************************
+ /**************************************************************************
*
* @function:
* FT_Vector_Rotate
@@ -267,7 +267,7 @@ FT_BEGIN_HEADER
FT_Angle angle );
- /*************************************************************************
+ /**************************************************************************
*
* @function:
* FT_Vector_Length
@@ -288,7 +288,7 @@ FT_BEGIN_HEADER
FT_Vector_Length( FT_Vector* vec );
- /*************************************************************************
+ /**************************************************************************
*
* @function:
* FT_Vector_Polarize
@@ -314,7 +314,7 @@ FT_BEGIN_HEADER
FT_Angle *angle );
- /*************************************************************************
+ /**************************************************************************
*
* @function:
* FT_Vector_From_Polar
diff --git a/thirdparty/freetype/include/freetype/ftttdrv.h b/thirdparty/freetype/include/freetype/ftttdrv.h
deleted file mode 100644
index 26bc5e966a..0000000000
--- a/thirdparty/freetype/include/freetype/ftttdrv.h
+++ /dev/null
@@ -1,328 +0,0 @@
-/***************************************************************************/
-/* */
-/* ftttdrv.h */
-/* */
-/* FreeType API for controlling the TrueType driver */
-/* (specification only). */
-/* */
-/* Copyright 2013-2017 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#ifndef FTTTDRV_H_
-#define FTTTDRV_H_
-
-#include <ft2build.h>
-#include FT_FREETYPE_H
-
-#ifdef FREETYPE_H
-#error "freetype.h of FreeType 1 has been loaded!"
-#error "Please fix the directory search order for header files"
-#error "so that freetype.h of FreeType 2 is found first."
-#endif
-
-
-FT_BEGIN_HEADER
-
-
- /**************************************************************************
- *
- * @section:
- * tt_driver
- *
- * @title:
- * The TrueType driver
- *
- * @abstract:
- * Controlling the TrueType driver module.
- *
- * @description:
- * While FreeType's TrueType driver doesn't expose API functions by
- * itself, it is possible to control its behaviour with @FT_Property_Set
- * and @FT_Property_Get. The following lists the available properties
- * together with the necessary macros and structures.
- *
- * The TrueType driver's module name is `truetype'.
- *
- * We start with a list of definitions, kindly provided by Greg
- * Hitchcock.
- *
- * _Bi-Level_ _Rendering_
- *
- * Monochromatic rendering, exclusively used in the early days of
- * TrueType by both Apple and Microsoft. Microsoft's GDI interface
- * supported hinting of the right-side bearing point, such that the
- * advance width could be non-linear. Most often this was done to
- * achieve some level of glyph symmetry. To enable reasonable
- * performance (e.g., not having to run hinting on all glyphs just to
- * get the widths) there was a bit in the head table indicating if the
- * side bearing was hinted, and additional tables, `hdmx' and `LTSH', to
- * cache hinting widths across multiple sizes and device aspect ratios.
- *
- * _Font_ _Smoothing_
- *
- * Microsoft's GDI implementation of anti-aliasing. Not traditional
- * anti-aliasing as the outlines were hinted before the sampling. The
- * widths matched the bi-level rendering.
- *
- * _ClearType_ _Rendering_
- *
- * Technique that uses physical subpixels to improve rendering on LCD
- * (and other) displays. Because of the higher resolution, many methods
- * of improving symmetry in glyphs through hinting the right-side
- * bearing were no longer necessary. This lead to what GDI calls
- * `natural widths' ClearType, see
- * http://www.beatstamm.com/typography/RTRCh4.htm#Sec21. Since hinting
- * has extra resolution, most non-linearity went away, but it is still
- * possible for hints to change the advance widths in this mode.
- *
- * _ClearType_ _Compatible_ _Widths_
- *
- * One of the earliest challenges with ClearType was allowing the
- * implementation in GDI to be selected without requiring all UI and
- * documents to reflow. To address this, a compatible method of
- * rendering ClearType was added where the font hints are executed once
- * to determine the width in bi-level rendering, and then re-run in
- * ClearType, with the difference in widths being absorbed in the font
- * hints for ClearType (mostly in the white space of hints); see
- * http://www.beatstamm.com/typography/RTRCh4.htm#Sec20. Somewhat by
- * definition, compatible width ClearType allows for non-linear widths,
- * but only when the bi-level version has non-linear widths.
- *
- * _ClearType_ _Subpixel_ _Positioning_
- *
- * One of the nice benefits of ClearType is the ability to more crisply
- * display fractional widths; unfortunately, the GDI model of integer
- * bitmaps did not support this. However, the WPF and Direct Write
- * frameworks do support fractional widths. DWrite calls this `natural
- * mode', not to be confused with GDI's `natural widths'. Subpixel
- * positioning, in the current implementation of Direct Write,
- * unfortunately does not support hinted advance widths, see
- * http://www.beatstamm.com/typography/RTRCh4.htm#Sec22. Note that the
- * TrueType interpreter fully allows the advance width to be adjusted in
- * this mode, just the DWrite client will ignore those changes.
- *
- * _ClearType_ _Backward_ _Compatibility_
- *
- * This is a set of exceptions made in the TrueType interpreter to
- * minimize hinting techniques that were problematic with the extra
- * resolution of ClearType; see
- * http://www.beatstamm.com/typography/RTRCh4.htm#Sec1 and
- * http://www.microsoft.com/typography/cleartype/truetypecleartype.aspx.
- * This technique is not to be confused with ClearType compatible
- * widths. ClearType backward compatibility has no direct impact on
- * changing advance widths, but there might be an indirect impact on
- * disabling some deltas. This could be worked around in backward
- * compatibility mode.
- *
- * _Native_ _ClearType_ _Mode_
- *
- * (Not to be confused with `natural widths'.) This mode removes all
- * the exceptions in the TrueType interpreter when running with
- * ClearType. Any issues on widths would still apply, though.
- *
- */
-
-
- /**************************************************************************
- *
- * @property:
- * interpreter-version
- *
- * @description:
- * Currently, three versions are available, two representing the
- * bytecode interpreter with subpixel hinting support (old `Infinality'
- * code and new stripped-down and higher performance `minimal' code) and
- * one without, respectively. The default is subpixel support if
- * TT_CONFIG_OPTION_SUBPIXEL_HINTING is defined, and no subpixel support
- * otherwise (since it isn't available then).
- *
- * If subpixel hinting is on, many TrueType bytecode instructions behave
- * differently compared to B/W or grayscale rendering (except if `native
- * ClearType' is selected by the font). Microsoft's main idea is to
- * render at a much increased horizontal resolution, then sampling down
- * the created output to subpixel precision. However, many older fonts
- * are not suited to this and must be specially taken care of by
- * applying (hardcoded) tweaks in Microsoft's interpreter.
- *
- * Details on subpixel hinting and some of the necessary tweaks can be
- * found in Greg Hitchcock's whitepaper at
- * `http://www.microsoft.com/typography/cleartype/truetypecleartype.aspx'.
- * Note that FreeType currently doesn't really `subpixel hint' (6x1, 6x2,
- * or 6x5 supersampling) like discussed in the paper. Depending on the
- * chosen interpreter, it simply ignores instructions on vertical stems
- * to arrive at very similar results.
- *
- * The following example code demonstrates how to deactivate subpixel
- * hinting (omitting the error handling).
- *
- * {
- * FT_Library library;
- * FT_Face face;
- * FT_UInt interpreter_version = TT_INTERPRETER_VERSION_35;
- *
- *
- * FT_Init_FreeType( &library );
- *
- * FT_Property_Set( library, "truetype",
- * "interpreter-version",
- * &interpreter_version );
- * }
- *
- * @note:
- * This property can be used with @FT_Property_Get also.
- *
- * This property can be set via the `FREETYPE_PROPERTIES' environment
- * variable (using values `35', `38', or `40').
- */
-
-
- /**************************************************************************
- *
- * @enum:
- * TT_INTERPRETER_VERSION_XXX
- *
- * @description:
- * A list of constants used for the @interpreter-version property to
- * select the hinting engine for Truetype fonts.
- *
- * The numeric value in the constant names represents the version
- * number as returned by the `GETINFO' bytecode instruction.
- *
- * @values:
- * TT_INTERPRETER_VERSION_35 ::
- * Version~35 corresponds to MS rasterizer v.1.7 as used e.g. in
- * Windows~98; only grayscale and B/W rasterizing is supported.
- *
- * TT_INTERPRETER_VERSION_38 ::
- * Version~38 corresponds to MS rasterizer v.1.9; it is roughly
- * equivalent to the hinting provided by DirectWrite ClearType (as can
- * be found, for example, in the Internet Explorer~9 running on
- * Windows~7). It is used in FreeType to select the `Infinality'
- * subpixel hinting code. The code may be removed in a future
- * version.
- *
- * TT_INTERPRETER_VERSION_40 ::
- * Version~40 corresponds to MS rasterizer v.2.1; it is roughly
- * equivalent to the hinting provided by DirectWrite ClearType (as can
- * be found, for example, in Microsoft's Edge Browser on Windows~10).
- * It is used in FreeType to select the `minimal' subpixel hinting
- * code, a stripped-down and higher performance version of the
- * `Infinality' code.
- *
- * @note:
- * This property controls the behaviour of the bytecode interpreter
- * and thus how outlines get hinted. It does *not* control how glyph
- * get rasterized! In particular, it does not control subpixel color
- * filtering.
- *
- * If FreeType has not been compiled with the configuration option
- * TT_CONFIG_OPTION_SUBPIXEL_HINTING, selecting version~38 or~40 causes
- * an `FT_Err_Unimplemented_Feature' error.
- *
- * Depending on the graphics framework, Microsoft uses different
- * bytecode and rendering engines. As a consequence, the version
- * numbers returned by a call to the `GETINFO' bytecode instruction are
- * more convoluted than desired.
- *
- * Here are two tables that try to shed some light on the possible
- * values for the MS rasterizer engine, together with the additional
- * features introduced by it.
- *
- * {
- * GETINFO framework version feature
- * -------------------------------------------------------------------
- * 3 GDI (Win 3.1), v1.0 16-bit, first version
- * TrueImage
- * 33 GDI (Win NT 3.1), v1.5 32-bit
- * HP Laserjet
- * 34 GDI (Win 95) v1.6 font smoothing,
- * new SCANTYPE opcode
- * 35 GDI (Win 98/2000) v1.7 (UN)SCALED_COMPONENT_OFFSET
- * bits in composite glyphs
- * 36 MGDI (Win CE 2) v1.6+ classic ClearType
- * 37 GDI (XP and later), v1.8 ClearType
- * GDI+ old (before Vista)
- * 38 GDI+ old (Vista, Win 7), v1.9 subpixel ClearType,
- * WPF Y-direction ClearType,
- * additional error checking
- * 39 DWrite (before Win 8) v2.0 subpixel ClearType flags
- * in GETINFO opcode,
- * bug fixes
- * 40 GDI+ (after Win 7), v2.1 Y-direction ClearType flag
- * DWrite (Win 8) in GETINFO opcode,
- * Gray ClearType
- * }
- *
- * The `version' field gives a rough orientation only, since some
- * applications provided certain features much earlier (as an example,
- * Microsoft Reader used subpixel and Y-direction ClearType already in
- * Windows 2000). Similarly, updates to a given framework might include
- * improved hinting support.
- *
- * {
- * version sampling rendering comment
- * x y x y
- * --------------------------------------------------------------
- * v1.0 normal normal B/W B/W bi-level
- * v1.6 high high gray gray grayscale
- * v1.8 high normal color-filter B/W (GDI) ClearType
- * v1.9 high high color-filter gray Color ClearType
- * v2.1 high normal gray B/W Gray ClearType
- * v2.1 high high gray gray Gray ClearType
- * }
- *
- * Color and Gray ClearType are the two available variants of
- * `Y-direction ClearType', meaning grayscale rasterization along the
- * Y-direction; the name used in the TrueType specification for this
- * feature is `symmetric smoothing'. `Classic ClearType' is the
- * original algorithm used before introducing a modified version in
- * Win~XP. Another name for v1.6's grayscale rendering is `font
- * smoothing', and `Color ClearType' is sometimes also called `DWrite
- * ClearType'. To differentiate between today's Color ClearType and the
- * earlier ClearType variant with B/W rendering along the vertical axis,
- * the latter is sometimes called `GDI ClearType'.
- *
- * `Normal' and `high' sampling describe the (virtual) resolution to
- * access the rasterized outline after the hinting process. `Normal'
- * means 1 sample per grid line (i.e., B/W). In the current Microsoft
- * implementation, `high' means an extra virtual resolution of 16x16 (or
- * 16x1) grid lines per pixel for bytecode instructions like `MIRP'.
- * After hinting, these 16 grid lines are mapped to 6x5 (or 6x1) grid
- * lines for color filtering if Color ClearType is activated.
- *
- * Note that `Gray ClearType' is essentially the same as v1.6's
- * grayscale rendering. However, the GETINFO instruction handles it
- * differently: v1.6 returns bit~12 (hinting for grayscale), while v2.1
- * returns bits~13 (hinting for ClearType), 18 (symmetrical smoothing),
- * and~19 (Gray ClearType). Also, this mode respects bits 2 and~3 for
- * the version~1 gasp table exclusively (like Color ClearType), while
- * v1.6 only respects the values of version~0 (bits 0 and~1).
- *
- * Keep in mind that the features of the above interpreter versions
- * might not map exactly to FreeType features or behavior because it is
- * a fundamentally different library with different internals.
- *
- */
-#define TT_INTERPRETER_VERSION_35 35
-#define TT_INTERPRETER_VERSION_38 38
-#define TT_INTERPRETER_VERSION_40 40
-
- /* */
-
-
-FT_END_HEADER
-
-
-#endif /* FTTTDRV_H_ */
-
-
-/* END */
diff --git a/thirdparty/freetype/include/freetype/fttypes.h b/thirdparty/freetype/include/freetype/fttypes.h
index f638c2e54f..10571505a5 100644
--- a/thirdparty/freetype/include/freetype/fttypes.h
+++ b/thirdparty/freetype/include/freetype/fttypes.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* fttypes.h */
-/* */
-/* FreeType simple types definitions (specification only). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * fttypes.h
+ *
+ * FreeType simple types definitions (specification only).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTTYPES_H_
@@ -31,326 +31,327 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* <Section> */
- /* basic_types */
- /* */
- /* <Title> */
- /* Basic Data Types */
- /* */
- /* <Abstract> */
- /* The basic data types defined by the library. */
- /* */
- /* <Description> */
- /* This section contains the basic data types defined by FreeType~2, */
- /* ranging from simple scalar types to bitmap descriptors. More */
- /* font-specific structures are defined in a different section. */
- /* */
- /* <Order> */
- /* FT_Byte */
- /* FT_Bytes */
- /* FT_Char */
- /* FT_Int */
- /* FT_UInt */
- /* FT_Int16 */
- /* FT_UInt16 */
- /* FT_Int32 */
- /* FT_UInt32 */
- /* FT_Int64 */
- /* FT_UInt64 */
- /* FT_Short */
- /* FT_UShort */
- /* FT_Long */
- /* FT_ULong */
- /* FT_Bool */
- /* FT_Offset */
- /* FT_PtrDist */
- /* FT_String */
- /* FT_Tag */
- /* FT_Error */
- /* FT_Fixed */
- /* FT_Pointer */
- /* FT_Pos */
- /* FT_Vector */
- /* FT_BBox */
- /* FT_Matrix */
- /* FT_FWord */
- /* FT_UFWord */
- /* FT_F2Dot14 */
- /* FT_UnitVector */
- /* FT_F26Dot6 */
- /* FT_Data */
- /* */
- /* FT_MAKE_TAG */
- /* */
- /* FT_Generic */
- /* FT_Generic_Finalizer */
- /* */
- /* FT_Bitmap */
- /* FT_Pixel_Mode */
- /* FT_Palette_Mode */
- /* FT_Glyph_Format */
- /* FT_IMAGE_TAG */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_Bool */
- /* */
- /* <Description> */
- /* A typedef of unsigned char, used for simple booleans. As usual, */
- /* values 1 and~0 represent true and false, respectively. */
- /* */
+ /**************************************************************************
+ *
+ * @section:
+ * basic_types
+ *
+ * @title:
+ * Basic Data Types
+ *
+ * @abstract:
+ * The basic data types defined by the library.
+ *
+ * @description:
+ * This section contains the basic data types defined by FreeType~2,
+ * ranging from simple scalar types to bitmap descriptors. More
+ * font-specific structures are defined in a different section.
+ *
+ * @order:
+ * FT_Byte
+ * FT_Bytes
+ * FT_Char
+ * FT_Int
+ * FT_UInt
+ * FT_Int16
+ * FT_UInt16
+ * FT_Int32
+ * FT_UInt32
+ * FT_Int64
+ * FT_UInt64
+ * FT_Short
+ * FT_UShort
+ * FT_Long
+ * FT_ULong
+ * FT_Bool
+ * FT_Offset
+ * FT_PtrDist
+ * FT_String
+ * FT_Tag
+ * FT_Error
+ * FT_Fixed
+ * FT_Pointer
+ * FT_Pos
+ * FT_Vector
+ * FT_BBox
+ * FT_Matrix
+ * FT_FWord
+ * FT_UFWord
+ * FT_F2Dot14
+ * FT_UnitVector
+ * FT_F26Dot6
+ * FT_Data
+ *
+ * FT_MAKE_TAG
+ *
+ * FT_Generic
+ * FT_Generic_Finalizer
+ *
+ * FT_Bitmap
+ * FT_Pixel_Mode
+ * FT_Palette_Mode
+ * FT_Glyph_Format
+ * FT_IMAGE_TAG
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Bool
+ *
+ * @description:
+ * A typedef of unsigned char, used for simple booleans. As usual,
+ * values 1 and~0 represent true and false, respectively.
+ */
typedef unsigned char FT_Bool;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_FWord */
- /* */
- /* <Description> */
- /* A signed 16-bit integer used to store a distance in original font */
- /* units. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_FWord
+ *
+ * @description:
+ * A signed 16-bit integer used to store a distance in original font
+ * units.
+ */
typedef signed short FT_FWord; /* distance in FUnits */
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_UFWord */
- /* */
- /* <Description> */
- /* An unsigned 16-bit integer used to store a distance in original */
- /* font units. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_UFWord
+ *
+ * @description:
+ * An unsigned 16-bit integer used to store a distance in original font
+ * units.
+ */
typedef unsigned short FT_UFWord; /* unsigned distance */
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_Char */
- /* */
- /* <Description> */
- /* A simple typedef for the _signed_ char type. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Char
+ *
+ * @description:
+ * A simple typedef for the _signed_ char type.
+ */
typedef signed char FT_Char;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_Byte */
- /* */
- /* <Description> */
- /* A simple typedef for the _unsigned_ char type. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Byte
+ *
+ * @description:
+ * A simple typedef for the _unsigned_ char type.
+ */
typedef unsigned char FT_Byte;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_Bytes */
- /* */
- /* <Description> */
- /* A typedef for constant memory areas. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Bytes
+ *
+ * @description:
+ * A typedef for constant memory areas.
+ */
typedef const FT_Byte* FT_Bytes;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_Tag */
- /* */
- /* <Description> */
- /* A typedef for 32-bit tags (as used in the SFNT format). */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Tag
+ *
+ * @description:
+ * A typedef for 32-bit tags (as used in the SFNT format).
+ */
typedef FT_UInt32 FT_Tag;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_String */
- /* */
- /* <Description> */
- /* A simple typedef for the char type, usually used for strings. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_String
+ *
+ * @description:
+ * A simple typedef for the char type, usually used for strings.
+ */
typedef char FT_String;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_Short */
- /* */
- /* <Description> */
- /* A typedef for signed short. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Short
+ *
+ * @description:
+ * A typedef for signed short.
+ */
typedef signed short FT_Short;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_UShort */
- /* */
- /* <Description> */
- /* A typedef for unsigned short. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_UShort
+ *
+ * @description:
+ * A typedef for unsigned short.
+ */
typedef unsigned short FT_UShort;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_Int */
- /* */
- /* <Description> */
- /* A typedef for the int type. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Int
+ *
+ * @description:
+ * A typedef for the int type.
+ */
typedef signed int FT_Int;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_UInt */
- /* */
- /* <Description> */
- /* A typedef for the unsigned int type. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_UInt
+ *
+ * @description:
+ * A typedef for the unsigned int type.
+ */
typedef unsigned int FT_UInt;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_Long */
- /* */
- /* <Description> */
- /* A typedef for signed long. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Long
+ *
+ * @description:
+ * A typedef for signed long.
+ */
typedef signed long FT_Long;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_ULong */
- /* */
- /* <Description> */
- /* A typedef for unsigned long. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_ULong
+ *
+ * @description:
+ * A typedef for unsigned long.
+ */
typedef unsigned long FT_ULong;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_F2Dot14 */
- /* */
- /* <Description> */
- /* A signed 2.14 fixed-point type used for unit vectors. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_F2Dot14
+ *
+ * @description:
+ * A signed 2.14 fixed-point type used for unit vectors.
+ */
typedef signed short FT_F2Dot14;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_F26Dot6 */
- /* */
- /* <Description> */
- /* A signed 26.6 fixed-point type used for vectorial pixel */
- /* coordinates. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_F26Dot6
+ *
+ * @description:
+ * A signed 26.6 fixed-point type used for vectorial pixel coordinates.
+ */
typedef signed long FT_F26Dot6;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_Fixed */
- /* */
- /* <Description> */
- /* This type is used to store 16.16 fixed-point values, like scaling */
- /* values or matrix coefficients. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Fixed
+ *
+ * @description:
+ * This type is used to store 16.16 fixed-point values, like scaling
+ * values or matrix coefficients.
+ */
typedef signed long FT_Fixed;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_Error */
- /* */
- /* <Description> */
- /* The FreeType error code type. A value of~0 is always interpreted */
- /* as a successful operation. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Error
+ *
+ * @description:
+ * The FreeType error code type. A value of~0 is always interpreted as a
+ * successful operation.
+ */
typedef int FT_Error;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_Pointer */
- /* */
- /* <Description> */
- /* A simple typedef for a typeless pointer. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Pointer
+ *
+ * @description:
+ * A simple typedef for a typeless pointer.
+ */
typedef void* FT_Pointer;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_Offset */
- /* */
- /* <Description> */
- /* This is equivalent to the ANSI~C `size_t' type, i.e., the largest */
- /* _unsigned_ integer type used to express a file size or position, */
- /* or a memory block size. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Offset
+ *
+ * @description:
+ * This is equivalent to the ANSI~C `size_t` type, i.e., the largest
+ * _unsigned_ integer type used to express a file size or position, or a
+ * memory block size.
+ */
typedef size_t FT_Offset;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_PtrDist */
- /* */
- /* <Description> */
- /* This is equivalent to the ANSI~C `ptrdiff_t' type, i.e., the */
- /* largest _signed_ integer type used to express the distance */
- /* between two pointers. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_PtrDist
+ *
+ * @description:
+ * This is equivalent to the ANSI~C `ptrdiff_t` type, i.e., the largest
+ * _signed_ integer type used to express the distance between two
+ * pointers.
+ */
typedef ft_ptrdiff_t FT_PtrDist;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_UnitVector */
- /* */
- /* <Description> */
- /* A simple structure used to store a 2D vector unit vector. Uses */
- /* FT_F2Dot14 types. */
- /* */
- /* <Fields> */
- /* x :: Horizontal coordinate. */
- /* */
- /* y :: Vertical coordinate. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_UnitVector
+ *
+ * @description:
+ * A simple structure used to store a 2D vector unit vector. Uses
+ * FT_F2Dot14 types.
+ *
+ * @fields:
+ * x ::
+ * Horizontal coordinate.
+ *
+ * y ::
+ * Vertical coordinate.
+ */
typedef struct FT_UnitVector_
{
FT_F2Dot14 x;
@@ -359,29 +360,33 @@ FT_BEGIN_HEADER
} FT_UnitVector;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_Matrix */
- /* */
- /* <Description> */
- /* A simple structure used to store a 2x2 matrix. Coefficients are */
- /* in 16.16 fixed-point format. The computation performed is: */
- /* */
- /* { */
- /* x' = x*xx + y*xy */
- /* y' = x*yx + y*yy */
- /* } */
- /* */
- /* <Fields> */
- /* xx :: Matrix coefficient. */
- /* */
- /* xy :: Matrix coefficient. */
- /* */
- /* yx :: Matrix coefficient. */
- /* */
- /* yy :: Matrix coefficient. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Matrix
+ *
+ * @description:
+ * A simple structure used to store a 2x2 matrix. Coefficients are in
+ * 16.16 fixed-point format. The computation performed is:
+ *
+ * ```
+ * x' = x*xx + y*xy
+ * y' = x*yx + y*yy
+ * ```
+ *
+ * @fields:
+ * xx ::
+ * Matrix coefficient.
+ *
+ * xy ::
+ * Matrix coefficient.
+ *
+ * yx ::
+ * Matrix coefficient.
+ *
+ * yy ::
+ * Matrix coefficient.
+ */
typedef struct FT_Matrix_
{
FT_Fixed xx, xy;
@@ -390,19 +395,21 @@ FT_BEGIN_HEADER
} FT_Matrix;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_Data */
- /* */
- /* <Description> */
- /* Read-only binary data represented as a pointer and a length. */
- /* */
- /* <Fields> */
- /* pointer :: The data. */
- /* */
- /* length :: The length of the data in bytes. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Data
+ *
+ * @description:
+ * Read-only binary data represented as a pointer and a length.
+ *
+ * @fields:
+ * pointer ::
+ * The data.
+ *
+ * length ::
+ * The length of the data in bytes.
+ */
typedef struct FT_Data_
{
const FT_Byte* pointer;
@@ -411,51 +418,52 @@ FT_BEGIN_HEADER
} FT_Data;
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* FT_Generic_Finalizer */
- /* */
- /* <Description> */
- /* Describe a function used to destroy the `client' data of any */
- /* FreeType object. See the description of the @FT_Generic type for */
- /* details of usage. */
- /* */
- /* <Input> */
- /* The address of the FreeType object that is under finalization. */
- /* Its client data is accessed through its `generic' field. */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_Generic_Finalizer
+ *
+ * @description:
+ * Describe a function used to destroy the 'client' data of any FreeType
+ * object. See the description of the @FT_Generic type for details of
+ * usage.
+ *
+ * @input:
+ * The address of the FreeType object that is under finalization. Its
+ * client data is accessed through its `generic` field.
+ */
typedef void (*FT_Generic_Finalizer)( void* object );
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_Generic */
- /* */
- /* <Description> */
- /* Client applications often need to associate their own data to a */
- /* variety of FreeType core objects. For example, a text layout API */
- /* might want to associate a glyph cache to a given size object. */
- /* */
- /* Some FreeType object contains a `generic' field, of type */
- /* FT_Generic, which usage is left to client applications and font */
- /* servers. */
- /* */
- /* It can be used to store a pointer to client-specific data, as well */
- /* as the address of a `finalizer' function, which will be called by */
- /* FreeType when the object is destroyed (for example, the previous */
- /* client example would put the address of the glyph cache destructor */
- /* in the `finalizer' field). */
- /* */
- /* <Fields> */
- /* data :: A typeless pointer to any client-specified data. This */
- /* field is completely ignored by the FreeType library. */
- /* */
- /* finalizer :: A pointer to a `generic finalizer' function, which */
- /* will be called when the object is destroyed. If this */
- /* field is set to NULL, no code will be called. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Generic
+ *
+ * @description:
+ * Client applications often need to associate their own data to a
+ * variety of FreeType core objects. For example, a text layout API
+ * might want to associate a glyph cache to a given size object.
+ *
+ * Some FreeType object contains a `generic` field, of type `FT_Generic`,
+ * which usage is left to client applications and font servers.
+ *
+ * It can be used to store a pointer to client-specific data, as well as
+ * the address of a 'finalizer' function, which will be called by
+ * FreeType when the object is destroyed (for example, the previous
+ * client example would put the address of the glyph cache destructor in
+ * the `finalizer` field).
+ *
+ * @fields:
+ * data ::
+ * A typeless pointer to any client-specified data. This field is
+ * completely ignored by the FreeType library.
+ *
+ * finalizer ::
+ * A pointer to a 'generic finalizer' function, which will be called
+ * when the object is destroyed. If this field is set to `NULL`, no
+ * code will be called.
+ */
typedef struct FT_Generic_
{
void* data;
@@ -464,19 +472,19 @@ FT_BEGIN_HEADER
} FT_Generic;
- /*************************************************************************/
- /* */
- /* <Macro> */
- /* FT_MAKE_TAG */
- /* */
- /* <Description> */
- /* This macro converts four-letter tags that are used to label */
- /* TrueType tables into an unsigned long, to be used within FreeType. */
- /* */
- /* <Note> */
- /* The produced values *must* be 32-bit integers. Don't redefine */
- /* this macro. */
- /* */
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_MAKE_TAG
+ *
+ * @description:
+ * This macro converts four-letter tags that are used to label TrueType
+ * tables into an unsigned long, to be used within FreeType.
+ *
+ * @note:
+ * The produced values **must** be 32-bit integers. Don't redefine this
+ * macro.
+ */
#define FT_MAKE_TAG( _x1, _x2, _x3, _x4 ) \
(FT_Tag) \
( ( (FT_ULong)_x1 << 24 ) | \
@@ -494,53 +502,56 @@ FT_BEGIN_HEADER
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* <Section> */
- /* list_processing */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * @section:
+ * list_processing
+ *
+ */
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_ListNode */
- /* */
- /* <Description> */
- /* Many elements and objects in FreeType are listed through an */
- /* @FT_List record (see @FT_ListRec). As its name suggests, an */
- /* FT_ListNode is a handle to a single list element. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_ListNode
+ *
+ * @description:
+ * Many elements and objects in FreeType are listed through an @FT_List
+ * record (see @FT_ListRec). As its name suggests, an FT_ListNode is a
+ * handle to a single list element.
+ */
typedef struct FT_ListNodeRec_* FT_ListNode;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_List */
- /* */
- /* <Description> */
- /* A handle to a list record (see @FT_ListRec). */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * FT_List
+ *
+ * @description:
+ * A handle to a list record (see @FT_ListRec).
+ */
typedef struct FT_ListRec_* FT_List;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_ListNodeRec */
- /* */
- /* <Description> */
- /* A structure used to hold a single list element. */
- /* */
- /* <Fields> */
- /* prev :: The previous element in the list. NULL if first. */
- /* */
- /* next :: The next element in the list. NULL if last. */
- /* */
- /* data :: A typeless pointer to the listed object. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_ListNodeRec
+ *
+ * @description:
+ * A structure used to hold a single list element.
+ *
+ * @fields:
+ * prev ::
+ * The previous element in the list. `NULL` if first.
+ *
+ * next ::
+ * The next element in the list. `NULL` if last.
+ *
+ * data ::
+ * A typeless pointer to the listed object.
+ */
typedef struct FT_ListNodeRec_
{
FT_ListNode prev;
@@ -550,20 +561,22 @@ FT_BEGIN_HEADER
} FT_ListNodeRec;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_ListRec */
- /* */
- /* <Description> */
- /* A structure used to hold a simple doubly-linked list. These are */
- /* used in many parts of FreeType. */
- /* */
- /* <Fields> */
- /* head :: The head (first element) of doubly-linked list. */
- /* */
- /* tail :: The tail (last element) of doubly-linked list. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_ListRec
+ *
+ * @description:
+ * A structure used to hold a simple doubly-linked list. These are used
+ * in many parts of FreeType.
+ *
+ * @fields:
+ * head ::
+ * The head (first element) of doubly-linked list.
+ *
+ * tail ::
+ * The tail (last element) of doubly-linked list.
+ */
typedef struct FT_ListRec_
{
FT_ListNode head;
@@ -575,13 +588,13 @@ FT_BEGIN_HEADER
#define FT_IS_EMPTY( list ) ( (list).head == 0 )
-#define FT_BOOL( x ) ( (FT_Bool)( x ) )
+#define FT_BOOL( x ) ( (FT_Bool)( (x) != 0 ) )
/* concatenate C tokens */
#define FT_ERR_XCAT( x, y ) x ## y
#define FT_ERR_CAT( x, y ) FT_ERR_XCAT( x, y )
- /* see `ftmoderr.h' for descriptions of the following macros */
+ /* see `ftmoderr.h` for descriptions of the following macros */
#define FT_ERR( e ) FT_ERR_CAT( FT_ERR_PREFIX, e )
diff --git a/thirdparty/freetype/include/freetype/ftwinfnt.h b/thirdparty/freetype/include/freetype/ftwinfnt.h
index 461c65b779..3437913d53 100644
--- a/thirdparty/freetype/include/freetype/ftwinfnt.h
+++ b/thirdparty/freetype/include/freetype/ftwinfnt.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftwinfnt.h */
-/* */
-/* FreeType API for accessing Windows fnt-specific data. */
-/* */
-/* Copyright 2003-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftwinfnt.h
+ *
+ * FreeType API for accessing Windows fnt-specific data.
+ *
+ * Copyright (C) 2003-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTWINFNT_H_
@@ -32,44 +32,43 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* <Section> */
- /* winfnt_fonts */
- /* */
- /* <Title> */
- /* Window FNT Files */
- /* */
- /* <Abstract> */
- /* Windows FNT specific API. */
- /* */
- /* <Description> */
- /* This section contains the declaration of Windows FNT specific */
- /* functions. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * @section:
+ * winfnt_fonts
+ *
+ * @title:
+ * Window FNT Files
+ *
+ * @abstract:
+ * Windows FNT-specific API.
+ *
+ * @description:
+ * This section contains the declaration of Windows FNT-specific
+ * functions.
+ *
+ */
- /*************************************************************************
+ /**************************************************************************
*
* @enum:
* FT_WinFNT_ID_XXX
*
* @description:
- * A list of valid values for the `charset' byte in
- * @FT_WinFNT_HeaderRec. Exact mapping tables for the various cpXXXX
- * encodings (except for cp1361) can be found at
- * ftp://ftp.unicode.org/Public in the MAPPINGS/VENDORS/MICSFT/WINDOWS
- * subdirectory. cp1361 is roughly a superset of
- * MAPPINGS/OBSOLETE/EASTASIA/KSC/JOHAB.TXT.
+ * A list of valid values for the `charset` byte in @FT_WinFNT_HeaderRec.
+ * Exact mapping tables for the various 'cpXXXX' encodings (except for
+ * 'cp1361') can be found at 'ftp://ftp.unicode.org/Public' in the
+ * `MAPPINGS/VENDORS/MICSFT/WINDOWS` subdirectory. 'cp1361' is roughly a
+ * superset of `MAPPINGS/OBSOLETE/EASTASIA/KSC/JOHAB.TXT`.
*
* @values:
* FT_WinFNT_ID_DEFAULT ::
- * This is used for font enumeration and font creation as a
- * `don't care' value. Valid font files don't contain this value.
- * When querying for information about the character set of the font
- * that is currently selected into a specified device context, this
- * return value (of the related Windows API) simply denotes failure.
+ * This is used for font enumeration and font creation as a 'don't
+ * care' value. Valid font files don't contain this value. When
+ * querying for information about the character set of the font that is
+ * currently selected into a specified device context, this return
+ * value (of the related Windows API) simply denotes failure.
*
* FT_WinFNT_ID_SYMBOL ::
* There is no known mapping table available.
@@ -80,26 +79,27 @@ FT_BEGIN_HEADER
* FT_WinFNT_ID_OEM ::
* From Michael Poettgen <michael@poettgen.de>:
*
- * The `Windows Font Mapping' article says that FT_WinFNT_ID_OEM
- * is used for the charset of vector fonts, like `modern.fon',
- * `roman.fon', and `script.fon' on Windows.
+ * The 'Windows Font Mapping' article says that `FT_WinFNT_ID_OEM` is
+ * used for the charset of vector fonts, like `modern.fon`,
+ * `roman.fon`, and `script.fon` on Windows.
*
- * The `CreateFont' documentation says: The FT_WinFNT_ID_OEM value
- * specifies a character set that is operating-system dependent.
+ * The 'CreateFont' documentation says: The `FT_WinFNT_ID_OEM` value
+ * specifies a character set that is operating-system dependent.
*
- * The `IFIMETRICS' documentation from the `Windows Driver
- * Development Kit' says: This font supports an OEM-specific
- * character set. The OEM character set is system dependent.
+ * The 'IFIMETRICS' documentation from the 'Windows Driver Development
+ * Kit' says: This font supports an OEM-specific character set. The
+ * OEM character set is system dependent.
*
- * In general OEM, as opposed to ANSI (i.e., cp1252), denotes the
- * second default codepage that most international versions of
- * Windows have. It is one of the OEM codepages from
+ * In general OEM, as opposed to ANSI (i.e., 'cp1252'), denotes the
+ * second default codepage that most international versions of Windows
+ * have. It is one of the OEM codepages from
*
- * https://msdn.microsoft.com/en-us/goglobal/bb964655,
+ * https://docs.microsoft.com/en-us/windows/desktop/intl/code-page-identifiers
+ * ,
*
- * and is used for the `DOS boxes', to support legacy applications.
- * A German Windows version for example usually uses ANSI codepage
- * 1252 and OEM codepage 850.
+ * and is used for the 'DOS boxes', to support legacy applications. A
+ * German Windows version for example usually uses ANSI codepage 1252
+ * and OEM codepage 850.
*
* FT_WinFNT_ID_CP874 ::
* A superset of Thai TIS 620 and ISO 8859-11.
@@ -112,8 +112,8 @@ FT_BEGIN_HEADER
* ordering and minor deviations).
*
* FT_WinFNT_ID_CP949 ::
- * A superset of Korean Hangul KS~C 5601-1987 (with different
- * ordering and minor deviations).
+ * A superset of Korean Hangul KS~C 5601-1987 (with different ordering
+ * and minor deviations).
*
* FT_WinFNT_ID_CP950 ::
* A superset of traditional Chinese Big~5 ETen (with different
@@ -173,14 +173,14 @@ FT_BEGIN_HEADER
#define FT_WinFNT_ID_OEM 255
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_WinFNT_HeaderRec */
- /* */
- /* <Description> */
- /* Windows FNT Header info. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_WinFNT_HeaderRec
+ *
+ * @description:
+ * Windows FNT Header info.
+ */
typedef struct FT_WinFNT_HeaderRec_
{
FT_UShort version;
@@ -223,18 +223,18 @@ FT_BEGIN_HEADER
} FT_WinFNT_HeaderRec;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_WinFNT_Header */
- /* */
- /* <Description> */
- /* A handle to an @FT_WinFNT_HeaderRec structure. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_WinFNT_Header
+ *
+ * @description:
+ * A handle to an @FT_WinFNT_HeaderRec structure.
+ */
typedef struct FT_WinFNT_HeaderRec_* FT_WinFNT_Header;
- /**********************************************************************
+ /**************************************************************************
*
* @function:
* FT_Get_WinFNT_Header
@@ -243,10 +243,12 @@ FT_BEGIN_HEADER
* Retrieve a Windows FNT font info header.
*
* @input:
- * face :: A handle to the input face.
+ * face ::
+ * A handle to the input face.
*
* @output:
- * aheader :: The WinFNT header.
+ * aheader ::
+ * The WinFNT header.
*
* @return:
* FreeType error code. 0~means success.
diff --git a/thirdparty/freetype/include/freetype/internal/autohint.h b/thirdparty/freetype/include/freetype/internal/autohint.h
index f4d308f68c..f64c28bb2c 100644
--- a/thirdparty/freetype/include/freetype/internal/autohint.h
+++ b/thirdparty/freetype/include/freetype/internal/autohint.h
@@ -1,73 +1,73 @@
-/***************************************************************************/
-/* */
-/* autohint.h */
-/* */
-/* High-level `autohint' module-specific interface (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* The auto-hinter is used to load and automatically hint glyphs if a */
- /* format-specific hinter isn't available. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * autohint.h
+ *
+ * High-level 'autohint' module-specific interface (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * The auto-hinter is used to load and automatically hint glyphs if a
+ * format-specific hinter isn't available.
+ *
+ */
#ifndef AUTOHINT_H_
#define AUTOHINT_H_
- /*************************************************************************/
- /* */
- /* A small technical note regarding automatic hinting in order to */
- /* clarify this module interface. */
- /* */
- /* An automatic hinter might compute two kinds of data for a given face: */
- /* */
- /* - global hints: Usually some metrics that describe global properties */
- /* of the face. It is computed by scanning more or less */
- /* aggressively the glyphs in the face, and thus can be */
- /* very slow to compute (even if the size of global */
- /* hints is really small). */
- /* */
- /* - glyph hints: These describe some important features of the glyph */
- /* outline, as well as how to align them. They are */
- /* generally much faster to compute than global hints. */
- /* */
- /* The current FreeType auto-hinter does a pretty good job while */
- /* performing fast computations for both global and glyph hints. */
- /* However, we might be interested in introducing more complex and */
- /* powerful algorithms in the future, like the one described in the John */
- /* D. Hobby paper, which unfortunately requires a lot more horsepower. */
- /* */
- /* Because a sufficiently sophisticated font management system would */
- /* typically implement an LRU cache of opened face objects to reduce */
- /* memory usage, it is a good idea to be able to avoid recomputing */
- /* global hints every time the same face is re-opened. */
- /* */
- /* We thus provide the ability to cache global hints outside of the face */
- /* object, in order to speed up font re-opening time. Of course, this */
- /* feature is purely optional, so most client programs won't even notice */
- /* it. */
- /* */
- /* I initially thought that it would be a good idea to cache the glyph */
- /* hints too. However, my general idea now is that if you really need */
- /* to cache these too, you are simply in need of a new font format, */
- /* where all this information could be stored within the font file and */
- /* decoded on the fly. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * A small technical note regarding automatic hinting in order to clarify
+ * this module interface.
+ *
+ * An automatic hinter might compute two kinds of data for a given face:
+ *
+ * - global hints: Usually some metrics that describe global properties
+ * of the face. It is computed by scanning more or less
+ * aggressively the glyphs in the face, and thus can be
+ * very slow to compute (even if the size of global hints
+ * is really small).
+ *
+ * - glyph hints: These describe some important features of the glyph
+ * outline, as well as how to align them. They are
+ * generally much faster to compute than global hints.
+ *
+ * The current FreeType auto-hinter does a pretty good job while performing
+ * fast computations for both global and glyph hints. However, we might be
+ * interested in introducing more complex and powerful algorithms in the
+ * future, like the one described in the John D. Hobby paper, which
+ * unfortunately requires a lot more horsepower.
+ *
+ * Because a sufficiently sophisticated font management system would
+ * typically implement an LRU cache of opened face objects to reduce memory
+ * usage, it is a good idea to be able to avoid recomputing global hints
+ * every time the same face is re-opened.
+ *
+ * We thus provide the ability to cache global hints outside of the face
+ * object, in order to speed up font re-opening time. Of course, this
+ * feature is purely optional, so most client programs won't even notice
+ * it.
+ *
+ * I initially thought that it would be a good idea to cache the glyph
+ * hints too. However, my general idea now is that if you really need to
+ * cache these too, you are simply in need of a new font format, where all
+ * this information could be stored within the font file and decoded on the
+ * fly.
+ *
+ */
#include <ft2build.h>
@@ -80,27 +80,31 @@ FT_BEGIN_HEADER
typedef struct FT_AutoHinterRec_ *FT_AutoHinter;
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* FT_AutoHinter_GlobalGetFunc */
- /* */
- /* <Description> */
- /* Retrieve the global hints computed for a given face object. The */
- /* resulting data is dissociated from the face and will survive a */
- /* call to FT_Done_Face(). It must be discarded through the API */
- /* FT_AutoHinter_GlobalDoneFunc(). */
- /* */
- /* <Input> */
- /* hinter :: A handle to the source auto-hinter. */
- /* */
- /* face :: A handle to the source face object. */
- /* */
- /* <Output> */
- /* global_hints :: A typeless pointer to the global hints. */
- /* */
- /* global_len :: The size in bytes of the global hints. */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_AutoHinter_GlobalGetFunc
+ *
+ * @description:
+ * Retrieve the global hints computed for a given face object. The
+ * resulting data is dissociated from the face and will survive a call to
+ * FT_Done_Face(). It must be discarded through the API
+ * FT_AutoHinter_GlobalDoneFunc().
+ *
+ * @input:
+ * hinter ::
+ * A handle to the source auto-hinter.
+ *
+ * face ::
+ * A handle to the source face object.
+ *
+ * @output:
+ * global_hints ::
+ * A typeless pointer to the global hints.
+ *
+ * global_len ::
+ * The size in bytes of the global hints.
+ */
typedef void
(*FT_AutoHinter_GlobalGetFunc)( FT_AutoHinter hinter,
FT_Face face,
@@ -108,69 +112,76 @@ FT_BEGIN_HEADER
long* global_len );
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* FT_AutoHinter_GlobalDoneFunc */
- /* */
- /* <Description> */
- /* Discard the global hints retrieved through */
- /* FT_AutoHinter_GlobalGetFunc(). This is the only way these hints */
- /* are freed from memory. */
- /* */
- /* <Input> */
- /* hinter :: A handle to the auto-hinter module. */
- /* */
- /* global :: A pointer to retrieved global hints to discard. */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_AutoHinter_GlobalDoneFunc
+ *
+ * @description:
+ * Discard the global hints retrieved through
+ * FT_AutoHinter_GlobalGetFunc(). This is the only way these hints are
+ * freed from memory.
+ *
+ * @input:
+ * hinter ::
+ * A handle to the auto-hinter module.
+ *
+ * global ::
+ * A pointer to retrieved global hints to discard.
+ */
typedef void
(*FT_AutoHinter_GlobalDoneFunc)( FT_AutoHinter hinter,
void* global );
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* FT_AutoHinter_GlobalResetFunc */
- /* */
- /* <Description> */
- /* This function is used to recompute the global metrics in a given */
- /* font. This is useful when global font data changes (e.g. Multiple */
- /* Masters fonts where blend coordinates change). */
- /* */
- /* <Input> */
- /* hinter :: A handle to the source auto-hinter. */
- /* */
- /* face :: A handle to the face. */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_AutoHinter_GlobalResetFunc
+ *
+ * @description:
+ * This function is used to recompute the global metrics in a given font.
+ * This is useful when global font data changes (e.g. Multiple Masters
+ * fonts where blend coordinates change).
+ *
+ * @input:
+ * hinter ::
+ * A handle to the source auto-hinter.
+ *
+ * face ::
+ * A handle to the face.
+ */
typedef void
(*FT_AutoHinter_GlobalResetFunc)( FT_AutoHinter hinter,
FT_Face face );
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* FT_AutoHinter_GlyphLoadFunc */
- /* */
- /* <Description> */
- /* This function is used to load, scale, and automatically hint a */
- /* glyph from a given face. */
- /* */
- /* <Input> */
- /* face :: A handle to the face. */
- /* */
- /* glyph_index :: The glyph index. */
- /* */
- /* load_flags :: The load flags. */
- /* */
- /* <Note> */
- /* This function is capable of loading composite glyphs by hinting */
- /* each sub-glyph independently (which improves quality). */
- /* */
- /* It will call the font driver with @FT_Load_Glyph, with */
- /* @FT_LOAD_NO_SCALE set. */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_AutoHinter_GlyphLoadFunc
+ *
+ * @description:
+ * This function is used to load, scale, and automatically hint a glyph
+ * from a given face.
+ *
+ * @input:
+ * face ::
+ * A handle to the face.
+ *
+ * glyph_index ::
+ * The glyph index.
+ *
+ * load_flags ::
+ * The load flags.
+ *
+ * @note:
+ * This function is capable of loading composite glyphs by hinting each
+ * sub-glyph independently (which improves quality).
+ *
+ * It will call the font driver with @FT_Load_Glyph, with
+ * @FT_LOAD_NO_SCALE set.
+ */
typedef FT_Error
(*FT_AutoHinter_GlyphLoadFunc)( FT_AutoHinter hinter,
FT_GlyphSlot slot,
@@ -179,14 +190,14 @@ FT_BEGIN_HEADER
FT_Int32 load_flags );
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_AutoHinter_InterfaceRec */
- /* */
- /* <Description> */
- /* The auto-hinter module's interface. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_AutoHinter_InterfaceRec
+ *
+ * @description:
+ * The auto-hinter module's interface.
+ */
typedef struct FT_AutoHinter_InterfaceRec_
{
FT_AutoHinter_GlobalResetFunc reset_face;
@@ -197,8 +208,6 @@ FT_BEGIN_HEADER
} FT_AutoHinter_InterfaceRec, *FT_AutoHinter_Interface;
-#ifndef FT_CONFIG_OPTION_PIC
-
#define FT_DEFINE_AUTOHINTER_INTERFACE( \
class_, \
reset_face_, \
@@ -214,27 +223,6 @@ FT_BEGIN_HEADER
load_glyph_ \
};
-#else /* FT_CONFIG_OPTION_PIC */
-
-#define FT_DEFINE_AUTOHINTER_INTERFACE( \
- class_, \
- reset_face_, \
- get_global_hints_, \
- done_global_hints_, \
- load_glyph_ ) \
- void \
- FT_Init_Class_ ## class_( FT_Library library, \
- FT_AutoHinter_InterfaceRec* clazz ) \
- { \
- FT_UNUSED( library ); \
- \
- clazz->reset_face = reset_face_; \
- clazz->get_global_hints = get_global_hints_; \
- clazz->done_global_hints = done_global_hints_; \
- clazz->load_glyph = load_glyph_; \
- }
-
-#endif /* FT_CONFIG_OPTION_PIC */
FT_END_HEADER
diff --git a/thirdparty/freetype/include/freetype/internal/cffotypes.h b/thirdparty/freetype/include/freetype/internal/cffotypes.h
index 57e7591d41..b26893eab3 100644
--- a/thirdparty/freetype/include/freetype/internal/cffotypes.h
+++ b/thirdparty/freetype/include/freetype/internal/cffotypes.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* cffotypes.h */
-/* */
-/* Basic OpenType/CFF object type definitions (specification). */
-/* */
-/* Copyright 2017-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * cffotypes.h
+ *
+ * Basic OpenType/CFF object type definitions (specification).
+ *
+ * Copyright (C) 2017-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef CFFOTYPES_H_
@@ -33,14 +33,14 @@ FT_BEGIN_HEADER
typedef TT_Face CFF_Face;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* CFF_Size */
- /* */
- /* <Description> */
- /* A handle to an OpenType size object. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * CFF_Size
+ *
+ * @description:
+ * A handle to an OpenType size object.
+ */
typedef struct CFF_SizeRec_
{
FT_SizeRec root;
@@ -49,14 +49,14 @@ FT_BEGIN_HEADER
} CFF_SizeRec, *CFF_Size;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* CFF_GlyphSlot */
- /* */
- /* <Description> */
- /* A handle to an OpenType glyph slot object. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * CFF_GlyphSlot
+ *
+ * @description:
+ * A handle to an OpenType glyph slot object.
+ */
typedef struct CFF_GlyphSlotRec_
{
FT_GlyphSlotRec root;
@@ -70,14 +70,14 @@ FT_BEGIN_HEADER
} CFF_GlyphSlotRec, *CFF_GlyphSlot;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* CFF_Internal */
- /* */
- /* <Description> */
- /* The interface to the `internal' field of `FT_Size'. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * CFF_Internal
+ *
+ * @description:
+ * The interface to the 'internal' field of `FT_Size`.
+ */
typedef struct CFF_InternalRec_
{
PSH_Globals topfont;
@@ -86,10 +86,10 @@ FT_BEGIN_HEADER
} CFF_InternalRec, *CFF_Internal;
- /*************************************************************************/
- /* */
- /* Subglyph transformation record. */
- /* */
+ /**************************************************************************
+ *
+ * Subglyph transformation record.
+ */
typedef struct CFF_Transform_
{
FT_Fixed xx, xy; /* transformation matrix coefficients */
diff --git a/thirdparty/freetype/include/freetype/internal/cfftypes.h b/thirdparty/freetype/include/freetype/internal/cfftypes.h
index 7c07e1a376..2fc905ec79 100644
--- a/thirdparty/freetype/include/freetype/internal/cfftypes.h
+++ b/thirdparty/freetype/include/freetype/internal/cfftypes.h
@@ -1,20 +1,20 @@
-/***************************************************************************/
-/* */
-/* cfftypes.h */
-/* */
-/* Basic OpenType/CFF type definitions and interface (specification */
-/* only). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * cfftypes.h
+ *
+ * Basic OpenType/CFF type definitions and interface (specification
+ * only).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef CFFTYPES_H_
@@ -33,34 +33,39 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* CFF_IndexRec */
- /* */
- /* <Description> */
- /* A structure used to model a CFF Index table. */
- /* */
- /* <Fields> */
- /* stream :: The source input stream. */
- /* */
- /* start :: The position of the first index byte in the */
- /* input stream. */
- /* */
- /* count :: The number of elements in the index. */
- /* */
- /* off_size :: The size in bytes of object offsets in index. */
- /* */
- /* data_offset :: The position of first data byte in the index's */
- /* bytes. */
- /* */
- /* data_size :: The size of the data table in this index. */
- /* */
- /* offsets :: A table of element offsets in the index. Must be */
- /* loaded explicitly. */
- /* */
- /* bytes :: If the index is loaded in memory, its bytes. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * CFF_IndexRec
+ *
+ * @description:
+ * A structure used to model a CFF Index table.
+ *
+ * @fields:
+ * stream ::
+ * The source input stream.
+ *
+ * start ::
+ * The position of the first index byte in the input stream.
+ *
+ * count ::
+ * The number of elements in the index.
+ *
+ * off_size ::
+ * The size in bytes of object offsets in index.
+ *
+ * data_offset ::
+ * The position of first data byte in the index's bytes.
+ *
+ * data_size ::
+ * The size of the data table in this index.
+ *
+ * offsets ::
+ * A table of element offsets in the index. Must be loaded explicitly.
+ *
+ * bytes ::
+ * If the index is loaded in memory, its bytes.
+ */
typedef struct CFF_IndexRec_
{
FT_Stream stream;
diff --git a/thirdparty/freetype/include/freetype/internal/ftcalc.h b/thirdparty/freetype/include/freetype/internal/ftcalc.h
index 818a812359..2986ec359b 100644
--- a/thirdparty/freetype/include/freetype/internal/ftcalc.h
+++ b/thirdparty/freetype/include/freetype/internal/ftcalc.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftcalc.h */
-/* */
-/* Arithmetic computations (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftcalc.h
+ *
+ * Arithmetic computations (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTCALC_H_
@@ -27,11 +27,11 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* FT_MulDiv() and FT_MulFix() are declared in freetype.h. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * FT_MulDiv() and FT_MulFix() are declared in freetype.h.
+ *
+ */
#ifndef FT_CONFIG_OPTION_NO_ASSEMBLER
/* Provide assembler fragments for performance-critical functions. */
@@ -246,29 +246,32 @@ FT_BEGIN_HEADER
#endif
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_MulDiv_No_Round */
- /* */
- /* <Description> */
- /* A very simple function used to perform the computation `(a*b)/c' */
- /* (without rounding) with maximum accuracy (it uses a 64-bit */
- /* intermediate integer whenever necessary). */
- /* */
- /* This function isn't necessarily as fast as some processor specific */
- /* operations, but is at least completely portable. */
- /* */
- /* <Input> */
- /* a :: The first multiplier. */
- /* b :: The second multiplier. */
- /* c :: The divisor. */
- /* */
- /* <Return> */
- /* The result of `(a*b)/c'. This function never traps when trying to */
- /* divide by zero; it simply returns `MaxInt' or `MinInt' depending */
- /* on the signs of `a' and `b'. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_MulDiv_No_Round
+ *
+ * @description:
+ * A very simple function used to perform the computation '(a*b)/c'
+ * (without rounding) with maximum accuracy (it uses a 64-bit
+ * intermediate integer whenever necessary).
+ *
+ * This function isn't necessarily as fast as some processor-specific
+ * operations, but is at least completely portable.
+ *
+ * @input:
+ * a ::
+ * The first multiplier.
+ * b ::
+ * The second multiplier.
+ * c ::
+ * The divisor.
+ *
+ * @return:
+ * The result of '(a*b)/c'. This function never traps when trying to
+ * divide by zero; it simply returns 'MaxInt' or 'MinInt' depending on
+ * the signs of 'a' and 'b'.
+ */
FT_BASE( FT_Long )
FT_MulDiv_No_Round( FT_Long a,
FT_Long b,
@@ -276,12 +279,11 @@ FT_BEGIN_HEADER
/*
- * A variant of FT_Matrix_Multiply which scales its result afterwards.
- * The idea is that both `a' and `b' are scaled by factors of 10 so that
- * the values are as precise as possible to get a correct result during
- * the 64bit multiplication. Let `sa' and `sb' be the scaling factors of
- * `a' and `b', respectively, then the scaling factor of the result is
- * `sa*sb'.
+ * A variant of FT_Matrix_Multiply which scales its result afterwards. The
+ * idea is that both `a' and `b' are scaled by factors of 10 so that the
+ * values are as precise as possible to get a correct result during the
+ * 64bit multiplication. Let `sa' and `sb' be the scaling factors of `a'
+ * and `b', respectively, then the scaling factor of the result is `sa*sb'.
*/
FT_BASE( void )
FT_Matrix_Multiply_Scaled( const FT_Matrix* a,
@@ -290,8 +292,23 @@ FT_BEGIN_HEADER
/*
- * A variant of FT_Vector_Transform. See comments for
- * FT_Matrix_Multiply_Scaled.
+ * Check a matrix. If the transformation would lead to extreme shear or
+ * extreme scaling, for example, return 0. If everything is OK, return 1.
+ *
+ * Based on geometric considerations we use the following inequality to
+ * identify a degenerate matrix.
+ *
+ * 50 * abs(xx*yy - xy*yx) < xx^2 + xy^2 + yx^2 + yy^2
+ *
+ * Value 50 is heuristic.
+ */
+ FT_BASE( FT_Bool )
+ FT_Matrix_Check( const FT_Matrix* matrix );
+
+
+ /*
+ * A variant of FT_Vector_Transform. See comments for
+ * FT_Matrix_Multiply_Scaled.
*/
FT_BASE( void )
FT_Vector_Transform_Scaled( FT_Vector* vector,
@@ -300,22 +317,22 @@ FT_BEGIN_HEADER
/*
- * This function normalizes a vector and returns its original length.
- * The normalized vector is a 16.16 fixed-point unit vector with length
- * close to 0x10000. The accuracy of the returned length is limited to
- * 16 bits also. The function utilizes quick inverse square root
- * approximation without divisions and square roots relying on Newton's
- * iterations instead.
+ * This function normalizes a vector and returns its original length. The
+ * normalized vector is a 16.16 fixed-point unit vector with length close
+ * to 0x10000. The accuracy of the returned length is limited to 16 bits
+ * also. The function utilizes quick inverse square root approximation
+ * without divisions and square roots relying on Newton's iterations
+ * instead.
*/
FT_BASE( FT_UInt32 )
FT_Vector_NormLen( FT_Vector* vector );
/*
- * Return -1, 0, or +1, depending on the orientation of a given corner.
- * We use the Cartesian coordinate system, with positive vertical values
- * going upwards. The function returns +1 if the corner turns to the
- * left, -1 to the right, and 0 for undecidable cases.
+ * Return -1, 0, or +1, depending on the orientation of a given corner. We
+ * use the Cartesian coordinate system, with positive vertical values going
+ * upwards. The function returns +1 if the corner turns to the left, -1 to
+ * the right, and 0 for undecidable cases.
*/
FT_BASE( FT_Int )
ft_corner_orientation( FT_Pos in_x,
@@ -325,9 +342,9 @@ FT_BEGIN_HEADER
/*
- * Return TRUE if a corner is flat or nearly flat. This is equivalent to
- * saying that the corner point is close to its neighbors, or inside an
- * ellipse defined by the neighbor focal points to be more precise.
+ * Return TRUE if a corner is flat or nearly flat. This is equivalent to
+ * saying that the corner point is close to its neighbors, or inside an
+ * ellipse defined by the neighbor focal points to be more precise.
*/
FT_BASE( FT_Int )
ft_corner_is_flat( FT_Pos in_x,
@@ -337,10 +354,11 @@ FT_BEGIN_HEADER
/*
- * Return the most significant bit index.
+ * Return the most significant bit index.
*/
#ifndef FT_CONFIG_OPTION_NO_ASSEMBLER
+
#if defined( __GNUC__ ) && \
( __GNUC__ > 3 || ( __GNUC__ == 3 && __GNUC_MINOR__ >= 4 ) )
@@ -352,9 +370,34 @@ FT_BEGIN_HEADER
#define FT_MSB( x ) ( 31 - __builtin_clzl( x ) )
+#endif /* __GNUC__ */
+
+
+#elif defined( _MSC_VER ) && ( _MSC_VER >= 1400 )
+
+#if FT_SIZEOF_INT == 4
+
+#include <intrin.h>
+
+ static __inline FT_Int32
+ FT_MSB_i386( FT_UInt32 x )
+ {
+ unsigned long where;
+
+
+ /* not available in older VC versions */
+ _BitScanReverse( &where, x );
+
+ return (FT_Int32)where;
+ }
+
+#define FT_MSB( x ) ( FT_MSB_i386( x ) )
+
#endif
-#endif /* __GNUC__ */
+#endif /* _MSC_VER */
+
+
#endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */
#ifndef FT_MSB
@@ -366,8 +409,8 @@ FT_BEGIN_HEADER
/*
- * Return sqrt(x*x+y*y), which is the same as `FT_Vector_Length' but uses
- * two fixed-point arguments instead.
+ * Return sqrt(x*x+y*y), which is the same as `FT_Vector_Length' but uses
+ * two fixed-point arguments instead.
*/
FT_BASE( FT_Fixed )
FT_Hypot( FT_Fixed x,
@@ -376,23 +419,24 @@ FT_BEGIN_HEADER
#if 0
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_SqrtFixed */
- /* */
- /* <Description> */
- /* Computes the square root of a 16.16 fixed-point value. */
- /* */
- /* <Input> */
- /* x :: The value to compute the root for. */
- /* */
- /* <Return> */
- /* The result of `sqrt(x)'. */
- /* */
- /* <Note> */
- /* This function is not very fast. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_SqrtFixed
+ *
+ * @description:
+ * Computes the square root of a 16.16 fixed-point value.
+ *
+ * @input:
+ * x ::
+ * The value to compute the root for.
+ *
+ * @return:
+ * The result of 'sqrt(x)'.
+ *
+ * @note:
+ * This function is not very fast.
+ */
FT_BASE( FT_Int32 )
FT_SqrtFixed( FT_Int32 x );
@@ -409,14 +453,23 @@ FT_BEGIN_HEADER
: ( -( ( 32 - (x) ) & -64 ) ) )
/*
- * The following macros have two purposes.
+ * The following macros have two purposes.
*
- * . Tag places where overflow is expected and harmless.
+ * - Tag places where overflow is expected and harmless.
*
- * . Avoid run-time sanitizer errors.
+ * - Avoid run-time sanitizer errors.
*
- * Use with care!
+ * Use with care!
*/
+#define ADD_INT( a, b ) \
+ (FT_Int)( (FT_UInt)(a) + (FT_UInt)(b) )
+#define SUB_INT( a, b ) \
+ (FT_Int)( (FT_UInt)(a) - (FT_UInt)(b) )
+#define MUL_INT( a, b ) \
+ (FT_Int)( (FT_UInt)(a) * (FT_UInt)(b) )
+#define NEG_INT( a ) \
+ (FT_Int)( (FT_UInt)0 - (FT_UInt)(a) )
+
#define ADD_LONG( a, b ) \
(FT_Long)( (FT_ULong)(a) + (FT_ULong)(b) )
#define SUB_LONG( a, b ) \
@@ -435,6 +488,19 @@ FT_BEGIN_HEADER
#define NEG_INT32( a ) \
(FT_Int32)( (FT_UInt32)0 - (FT_UInt32)(a) )
+#ifdef FT_LONG64
+
+#define ADD_INT64( a, b ) \
+ (FT_Int64)( (FT_UInt64)(a) + (FT_UInt64)(b) )
+#define SUB_INT64( a, b ) \
+ (FT_Int64)( (FT_UInt64)(a) - (FT_UInt64)(b) )
+#define MUL_INT64( a, b ) \
+ (FT_Int64)( (FT_UInt64)(a) * (FT_UInt64)(b) )
+#define NEG_INT64( a ) \
+ (FT_Int64)( (FT_UInt64)0 - (FT_UInt64)(a) )
+
+#endif /* FT_LONG64 */
+
FT_END_HEADER
diff --git a/thirdparty/freetype/include/freetype/internal/ftdebug.h b/thirdparty/freetype/include/freetype/internal/ftdebug.h
index 292a4eedb8..54a9673afa 100644
--- a/thirdparty/freetype/include/freetype/internal/ftdebug.h
+++ b/thirdparty/freetype/include/freetype/internal/ftdebug.h
@@ -1,24 +1,24 @@
-/***************************************************************************/
-/* */
-/* ftdebug.h */
-/* */
-/* Debugging and logging component (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/* */
-/* IMPORTANT: A description of FreeType's debugging support can be */
-/* found in `docs/DEBUG.TXT'. Read it if you need to use or */
-/* understand this code. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftdebug.h
+ *
+ * Debugging and logging component (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ *
+ * IMPORTANT: A description of FreeType's debugging support can be
+ * found in 'docs/DEBUG.TXT'. Read it if you need to use or
+ * understand this code.
+ *
+ */
#ifndef FTDEBUG_H_
@@ -42,12 +42,12 @@ FT_BEGIN_HEADER
#endif
- /*************************************************************************/
- /* */
- /* Define the trace enums as well as the trace levels array when they */
- /* are needed. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * Define the trace enums as well as the trace levels array when they are
+ * needed.
+ *
+ */
#ifdef FT_DEBUG_LEVEL_TRACE
@@ -62,32 +62,37 @@ FT_BEGIN_HEADER
} FT_Trace;
- /* defining the array of trace levels, provided by `src/base/ftdebug.c' */
- extern int ft_trace_levels[trace_count];
+ /* a pointer to the array of trace levels, */
+ /* provided by `src/base/ftdebug.c' */
+ extern int* ft_trace_levels;
#undef FT_TRACE_DEF
#endif /* FT_DEBUG_LEVEL_TRACE */
- /*************************************************************************/
- /* */
- /* Define the FT_TRACE macro */
- /* */
- /* IMPORTANT! */
- /* */
- /* Each component must define the macro FT_COMPONENT to a valid FT_Trace */
- /* value before using any TRACE macro. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * Define the FT_TRACE macro
+ *
+ * IMPORTANT!
+ *
+ * Each component must define the macro FT_COMPONENT to a valid FT_Trace
+ * value before using any TRACE macro.
+ *
+ */
#ifdef FT_DEBUG_LEVEL_TRACE
-#define FT_TRACE( level, varformat ) \
- do \
- { \
- if ( ft_trace_levels[FT_COMPONENT] >= level ) \
- FT_Message varformat; \
+ /* we need two macros here to make cpp expand `FT_COMPONENT' */
+#define FT_TRACE_COMP( x ) FT_TRACE_COMP_( x )
+#define FT_TRACE_COMP_( x ) trace_ ## x
+
+#define FT_TRACE( level, varformat ) \
+ do \
+ { \
+ if ( ft_trace_levels[FT_TRACE_COMP( FT_COMPONENT )] >= level ) \
+ FT_Message varformat; \
} while ( 0 )
#else /* !FT_DEBUG_LEVEL_TRACE */
@@ -97,62 +102,85 @@ FT_BEGIN_HEADER
#endif /* !FT_DEBUG_LEVEL_TRACE */
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Trace_Get_Count */
- /* */
- /* <Description> */
- /* Return the number of available trace components. */
- /* */
- /* <Return> */
- /* The number of trace components. 0 if FreeType 2 is not built with */
- /* FT_DEBUG_LEVEL_TRACE definition. */
- /* */
- /* <Note> */
- /* This function may be useful if you want to access elements of */
- /* the internal `ft_trace_levels' array by an index. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Trace_Get_Count
+ *
+ * @description:
+ * Return the number of available trace components.
+ *
+ * @return:
+ * The number of trace components. 0 if FreeType 2 is not built with
+ * FT_DEBUG_LEVEL_TRACE definition.
+ *
+ * @note:
+ * This function may be useful if you want to access elements of the
+ * internal trace levels array by an index.
+ */
FT_BASE( FT_Int )
FT_Trace_Get_Count( void );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Trace_Get_Name */
- /* */
- /* <Description> */
- /* Return the name of a trace component. */
- /* */
- /* <Input> */
- /* The index of the trace component. */
- /* */
- /* <Return> */
- /* The name of the trace component. This is a statically allocated */
- /* C string, so do not free it after use. NULL if FreeType 2 is not */
- /* built with FT_DEBUG_LEVEL_TRACE definition. */
- /* */
- /* <Note> */
- /* Use @FT_Trace_Get_Count to get the number of available trace */
- /* components. */
- /* */
- /* This function may be useful if you want to control FreeType 2's */
- /* debug level in your application. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Trace_Get_Name
+ *
+ * @description:
+ * Return the name of a trace component.
+ *
+ * @input:
+ * The index of the trace component.
+ *
+ * @return:
+ * The name of the trace component. This is a statically allocated
+ * C~string, so do not free it after use. `NULL` if FreeType is not
+ * built with FT_DEBUG_LEVEL_TRACE definition.
+ *
+ * @note:
+ * Use @FT_Trace_Get_Count to get the number of available trace
+ * components.
+ */
FT_BASE( const char* )
FT_Trace_Get_Name( FT_Int idx );
- /*************************************************************************/
- /* */
- /* You need two opening and closing parentheses! */
- /* */
- /* Example: FT_TRACE0(( "Value is %i", foo )) */
- /* */
- /* Output of the FT_TRACEX macros is sent to stderr. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Trace_Disable
+ *
+ * @description:
+ * Switch off tracing temporarily. It can be activated again with
+ * @FT_Trace_Enable.
+ */
+ FT_BASE( void )
+ FT_Trace_Disable( void );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Trace_Enable
+ *
+ * @description:
+ * Activate tracing. Use it after tracing has been switched off with
+ * @FT_Trace_Disable.
+ */
+ FT_BASE( void )
+ FT_Trace_Enable( void );
+
+
+ /**************************************************************************
+ *
+ * You need two opening and closing parentheses!
+ *
+ * Example: FT_TRACE0(( "Value is %i", foo ))
+ *
+ * Output of the FT_TRACEX macros is sent to stderr.
+ *
+ */
#define FT_TRACE0( varformat ) FT_TRACE( 0, varformat )
#define FT_TRACE1( varformat ) FT_TRACE( 1, varformat )
@@ -164,13 +192,13 @@ FT_BEGIN_HEADER
#define FT_TRACE7( varformat ) FT_TRACE( 7, varformat )
- /*************************************************************************/
- /* */
- /* Define the FT_ERROR macro. */
- /* */
- /* Output of this macro is sent to stderr. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * Define the FT_ERROR macro.
+ *
+ * Output of this macro is sent to stderr.
+ *
+ */
#ifdef FT_DEBUG_LEVEL_ERROR
@@ -183,12 +211,12 @@ FT_BEGIN_HEADER
#endif /* !FT_DEBUG_LEVEL_ERROR */
- /*************************************************************************/
- /* */
- /* Define the FT_ASSERT and FT_THROW macros. The call to `FT_Throw' */
- /* makes it possible to easily set a breakpoint at this function. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * Define the FT_ASSERT and FT_THROW macros. The call to `FT_Throw` makes
+ * it possible to easily set a breakpoint at this function.
+ *
+ */
#ifdef FT_DEBUG_LEVEL_ERROR
@@ -215,11 +243,11 @@ FT_BEGIN_HEADER
#endif /* !FT_DEBUG_LEVEL_ERROR */
- /*************************************************************************/
- /* */
- /* Define `FT_Message' and `FT_Panic' when needed. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * Define `FT_Message` and `FT_Panic` when needed.
+ *
+ */
#ifdef FT_DEBUG_LEVEL_ERROR
diff --git a/thirdparty/freetype/include/freetype/internal/ftdriver.h b/thirdparty/freetype/include/freetype/internal/ftdriver.h
deleted file mode 100644
index e82fa8d41f..0000000000
--- a/thirdparty/freetype/include/freetype/internal/ftdriver.h
+++ /dev/null
@@ -1,400 +0,0 @@
-/***************************************************************************/
-/* */
-/* ftdriver.h */
-/* */
-/* FreeType font driver interface (specification). */
-/* */
-/* Copyright 1996-2017 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#ifndef FTDRIVER_H_
-#define FTDRIVER_H_
-
-
-#include <ft2build.h>
-#include FT_MODULE_H
-
-
-FT_BEGIN_HEADER
-
-
- typedef FT_Error
- (*FT_Face_InitFunc)( FT_Stream stream,
- FT_Face face,
- FT_Int typeface_index,
- FT_Int num_params,
- FT_Parameter* parameters );
-
- typedef void
- (*FT_Face_DoneFunc)( FT_Face face );
-
-
- typedef FT_Error
- (*FT_Size_InitFunc)( FT_Size size );
-
- typedef void
- (*FT_Size_DoneFunc)( FT_Size size );
-
-
- typedef FT_Error
- (*FT_Slot_InitFunc)( FT_GlyphSlot slot );
-
- typedef void
- (*FT_Slot_DoneFunc)( FT_GlyphSlot slot );
-
-
- typedef FT_Error
- (*FT_Size_RequestFunc)( FT_Size size,
- FT_Size_Request req );
-
- typedef FT_Error
- (*FT_Size_SelectFunc)( FT_Size size,
- FT_ULong size_index );
-
- typedef FT_Error
- (*FT_Slot_LoadFunc)( FT_GlyphSlot slot,
- FT_Size size,
- FT_UInt glyph_index,
- FT_Int32 load_flags );
-
-
- typedef FT_Error
- (*FT_Face_GetKerningFunc)( FT_Face face,
- FT_UInt left_glyph,
- FT_UInt right_glyph,
- FT_Vector* kerning );
-
-
- typedef FT_Error
- (*FT_Face_AttachFunc)( FT_Face face,
- FT_Stream stream );
-
-
- typedef FT_Error
- (*FT_Face_GetAdvancesFunc)( FT_Face face,
- FT_UInt first,
- FT_UInt count,
- FT_Int32 flags,
- FT_Fixed* advances );
-
-
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_Driver_ClassRec */
- /* */
- /* <Description> */
- /* The font driver class. This structure mostly contains pointers to */
- /* driver methods. */
- /* */
- /* <Fields> */
- /* root :: The parent module. */
- /* */
- /* face_object_size :: The size of a face object in bytes. */
- /* */
- /* size_object_size :: The size of a size object in bytes. */
- /* */
- /* slot_object_size :: The size of a glyph object in bytes. */
- /* */
- /* init_face :: The format-specific face constructor. */
- /* */
- /* done_face :: The format-specific face destructor. */
- /* */
- /* init_size :: The format-specific size constructor. */
- /* */
- /* done_size :: The format-specific size destructor. */
- /* */
- /* init_slot :: The format-specific slot constructor. */
- /* */
- /* done_slot :: The format-specific slot destructor. */
- /* */
- /* */
- /* load_glyph :: A function handle to load a glyph to a slot. */
- /* This field is mandatory! */
- /* */
- /* get_kerning :: A function handle to return the unscaled */
- /* kerning for a given pair of glyphs. Can be */
- /* set to 0 if the format doesn't support */
- /* kerning. */
- /* */
- /* attach_file :: This function handle is used to read */
- /* additional data for a face from another */
- /* file/stream. For example, this can be used to */
- /* add data from AFM or PFM files on a Type 1 */
- /* face, or a CIDMap on a CID-keyed face. */
- /* */
- /* get_advances :: A function handle used to return advance */
- /* widths of `count' glyphs (in font units), */
- /* starting at `first'. The `vertical' flag must */
- /* be set to get vertical advance heights. The */
- /* `advances' buffer is caller-allocated. */
- /* The idea of this function is to be able to */
- /* perform device-independent text layout without */
- /* loading a single glyph image. */
- /* */
- /* request_size :: A handle to a function used to request the new */
- /* character size. Can be set to 0 if the */
- /* scaling done in the base layer suffices. */
- /* */
- /* select_size :: A handle to a function used to select a new */
- /* fixed size. It is used only if */
- /* @FT_FACE_FLAG_FIXED_SIZES is set. Can be set */
- /* to 0 if the scaling done in the base layer */
- /* suffices. */
- /* <Note> */
- /* Most function pointers, with the exception of `load_glyph', can be */
- /* set to 0 to indicate a default behaviour. */
- /* */
- typedef struct FT_Driver_ClassRec_
- {
- FT_Module_Class root;
-
- FT_Long face_object_size;
- FT_Long size_object_size;
- FT_Long slot_object_size;
-
- FT_Face_InitFunc init_face;
- FT_Face_DoneFunc done_face;
-
- FT_Size_InitFunc init_size;
- FT_Size_DoneFunc done_size;
-
- FT_Slot_InitFunc init_slot;
- FT_Slot_DoneFunc done_slot;
-
- FT_Slot_LoadFunc load_glyph;
-
- FT_Face_GetKerningFunc get_kerning;
- FT_Face_AttachFunc attach_file;
- FT_Face_GetAdvancesFunc get_advances;
-
- /* since version 2.2 */
- FT_Size_RequestFunc request_size;
- FT_Size_SelectFunc select_size;
-
- } FT_Driver_ClassRec, *FT_Driver_Class;
-
-
- /*************************************************************************/
- /* */
- /* <Macro> */
- /* FT_DECLARE_DRIVER */
- /* */
- /* <Description> */
- /* Used to create a forward declaration of an FT_Driver_ClassRec */
- /* struct instance. */
- /* */
- /* <Macro> */
- /* FT_DEFINE_DRIVER */
- /* */
- /* <Description> */
- /* Used to initialize an instance of FT_Driver_ClassRec struct. */
- /* */
- /* When FT_CONFIG_OPTION_PIC is defined a `create' function has to be */
- /* called with a pointer where the allocated structure is returned. */
- /* And when it is no longer needed a `destroy' function needs to be */
- /* called to release that allocation. */
- /* */
- /* `ftinit.c' (ft_create_default_module_classes) already contains a */
- /* mechanism to call these functions for the default modules */
- /* described in `ftmodule.h'. */
- /* */
- /* Notice that the created `create' and `destroy' functions call */
- /* `pic_init' and `pic_free' to allow you to manually allocate and */
- /* initialize any additional global data, like a module specific */
- /* interface, and put them in the global pic container defined in */
- /* `ftpic.h'. If you don't need them just implement the functions as */
- /* empty to resolve the link error. Also the `pic_init' and */
- /* `pic_free' functions should be declared in `pic.h', to be referred */
- /* by driver definition calling `FT_DEFINE_DRIVER' in following. */
- /* */
- /* When FT_CONFIG_OPTION_PIC is not defined the struct will be */
- /* allocated in the global scope (or the scope where the macro is */
- /* used). */
- /* */
-#ifndef FT_CONFIG_OPTION_PIC
-
-#define FT_DECLARE_DRIVER( class_ ) \
- FT_CALLBACK_TABLE \
- const FT_Driver_ClassRec class_;
-
-#define FT_DEFINE_DRIVER( \
- class_, \
- flags_, \
- size_, \
- name_, \
- version_, \
- requires_, \
- interface_, \
- init_, \
- done_, \
- get_interface_, \
- face_object_size_, \
- size_object_size_, \
- slot_object_size_, \
- init_face_, \
- done_face_, \
- init_size_, \
- done_size_, \
- init_slot_, \
- done_slot_, \
- load_glyph_, \
- get_kerning_, \
- attach_file_, \
- get_advances_, \
- request_size_, \
- select_size_ ) \
- FT_CALLBACK_TABLE_DEF \
- const FT_Driver_ClassRec class_ = \
- { \
- FT_DEFINE_ROOT_MODULE( flags_, \
- size_, \
- name_, \
- version_, \
- requires_, \
- interface_, \
- init_, \
- done_, \
- get_interface_ ) \
- \
- face_object_size_, \
- size_object_size_, \
- slot_object_size_, \
- \
- init_face_, \
- done_face_, \
- \
- init_size_, \
- done_size_, \
- \
- init_slot_, \
- done_slot_, \
- \
- load_glyph_, \
- \
- get_kerning_, \
- attach_file_, \
- get_advances_, \
- \
- request_size_, \
- select_size_ \
- };
-
-#else /* FT_CONFIG_OPTION_PIC */
-
-#define FT_DECLARE_DRIVER( class_ ) FT_DECLARE_MODULE( class_ )
-
-#define FT_DEFINE_DRIVER( \
- class_, \
- flags_, \
- size_, \
- name_, \
- version_, \
- requires_, \
- interface_, \
- init_, \
- done_, \
- get_interface_, \
- face_object_size_, \
- size_object_size_, \
- slot_object_size_, \
- init_face_, \
- done_face_, \
- init_size_, \
- done_size_, \
- init_slot_, \
- done_slot_, \
- load_glyph_, \
- get_kerning_, \
- attach_file_, \
- get_advances_, \
- request_size_, \
- select_size_ ) \
- void \
- FT_Destroy_Class_ ## class_( FT_Library library, \
- FT_Module_Class* clazz ) \
- { \
- FT_Memory memory = library->memory; \
- FT_Driver_Class dclazz = (FT_Driver_Class)clazz; \
- \
- \
- class_ ## _pic_free( library ); \
- if ( dclazz ) \
- FT_FREE( dclazz ); \
- } \
- \
- \
- FT_Error \
- FT_Create_Class_ ## class_( FT_Library library, \
- FT_Module_Class** output_class ) \
- { \
- FT_Driver_Class clazz = NULL; \
- FT_Error error; \
- FT_Memory memory = library->memory; \
- \
- \
- if ( FT_ALLOC( clazz, sizeof ( *clazz ) ) ) \
- return error; \
- \
- error = class_ ## _pic_init( library ); \
- if ( error ) \
- { \
- FT_FREE( clazz ); \
- return error; \
- } \
- \
- FT_DEFINE_ROOT_MODULE( flags_, \
- size_, \
- name_, \
- version_, \
- requires_, \
- interface_, \
- init_, \
- done_, \
- get_interface_ ) \
- \
- clazz->face_object_size = face_object_size_; \
- clazz->size_object_size = size_object_size_; \
- clazz->slot_object_size = slot_object_size_; \
- \
- clazz->init_face = init_face_; \
- clazz->done_face = done_face_; \
- \
- clazz->init_size = init_size_; \
- clazz->done_size = done_size_; \
- \
- clazz->init_slot = init_slot_; \
- clazz->done_slot = done_slot_; \
- \
- clazz->load_glyph = load_glyph_; \
- \
- clazz->get_kerning = get_kerning_; \
- clazz->attach_file = attach_file_; \
- clazz->get_advances = get_advances_; \
- \
- clazz->request_size = request_size_; \
- clazz->select_size = select_size_; \
- \
- *output_class = (FT_Module_Class*)clazz; \
- \
- return FT_Err_Ok; \
- }
-
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
-FT_END_HEADER
-
-#endif /* FTDRIVER_H_ */
-
-
-/* END */
diff --git a/thirdparty/freetype/include/freetype/internal/ftdrv.h b/thirdparty/freetype/include/freetype/internal/ftdrv.h
index 58dd35a933..09e846e1c7 100644
--- a/thirdparty/freetype/include/freetype/internal/ftdrv.h
+++ b/thirdparty/freetype/include/freetype/internal/ftdrv.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftdrv.h */
-/* */
-/* FreeType internal font driver interface (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftdrv.h
+ *
+ * FreeType internal font driver interface (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTDRV_H_
@@ -87,73 +87,80 @@ FT_BEGIN_HEADER
FT_Fixed* advances );
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_Driver_ClassRec */
- /* */
- /* <Description> */
- /* The font driver class. This structure mostly contains pointers to */
- /* driver methods. */
- /* */
- /* <Fields> */
- /* root :: The parent module. */
- /* */
- /* face_object_size :: The size of a face object in bytes. */
- /* */
- /* size_object_size :: The size of a size object in bytes. */
- /* */
- /* slot_object_size :: The size of a glyph object in bytes. */
- /* */
- /* init_face :: The format-specific face constructor. */
- /* */
- /* done_face :: The format-specific face destructor. */
- /* */
- /* init_size :: The format-specific size constructor. */
- /* */
- /* done_size :: The format-specific size destructor. */
- /* */
- /* init_slot :: The format-specific slot constructor. */
- /* */
- /* done_slot :: The format-specific slot destructor. */
- /* */
- /* */
- /* load_glyph :: A function handle to load a glyph to a slot. */
- /* This field is mandatory! */
- /* */
- /* get_kerning :: A function handle to return the unscaled */
- /* kerning for a given pair of glyphs. Can be */
- /* set to 0 if the format doesn't support */
- /* kerning. */
- /* */
- /* attach_file :: This function handle is used to read */
- /* additional data for a face from another */
- /* file/stream. For example, this can be used to */
- /* add data from AFM or PFM files on a Type 1 */
- /* face, or a CIDMap on a CID-keyed face. */
- /* */
- /* get_advances :: A function handle used to return advance */
- /* widths of `count' glyphs (in font units), */
- /* starting at `first'. The `vertical' flag must */
- /* be set to get vertical advance heights. The */
- /* `advances' buffer is caller-allocated. */
- /* The idea of this function is to be able to */
- /* perform device-independent text layout without */
- /* loading a single glyph image. */
- /* */
- /* request_size :: A handle to a function used to request the new */
- /* character size. Can be set to 0 if the */
- /* scaling done in the base layer suffices. */
- /* */
- /* select_size :: A handle to a function used to select a new */
- /* fixed size. It is used only if */
- /* @FT_FACE_FLAG_FIXED_SIZES is set. Can be set */
- /* to 0 if the scaling done in the base layer */
- /* suffices. */
- /* <Note> */
- /* Most function pointers, with the exception of `load_glyph', can be */
- /* set to 0 to indicate a default behaviour. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Driver_ClassRec
+ *
+ * @description:
+ * The font driver class. This structure mostly contains pointers to
+ * driver methods.
+ *
+ * @fields:
+ * root ::
+ * The parent module.
+ *
+ * face_object_size ::
+ * The size of a face object in bytes.
+ *
+ * size_object_size ::
+ * The size of a size object in bytes.
+ *
+ * slot_object_size ::
+ * The size of a glyph object in bytes.
+ *
+ * init_face ::
+ * The format-specific face constructor.
+ *
+ * done_face ::
+ * The format-specific face destructor.
+ *
+ * init_size ::
+ * The format-specific size constructor.
+ *
+ * done_size ::
+ * The format-specific size destructor.
+ *
+ * init_slot ::
+ * The format-specific slot constructor.
+ *
+ * done_slot ::
+ * The format-specific slot destructor.
+ *
+ *
+ * load_glyph ::
+ * A function handle to load a glyph to a slot. This field is
+ * mandatory!
+ *
+ * get_kerning ::
+ * A function handle to return the unscaled kerning for a given pair of
+ * glyphs. Can be set to 0 if the format doesn't support kerning.
+ *
+ * attach_file ::
+ * This function handle is used to read additional data for a face from
+ * another file/stream. For example, this can be used to add data from
+ * AFM or PFM files on a Type 1 face, or a CIDMap on a CID-keyed face.
+ *
+ * get_advances ::
+ * A function handle used to return advance widths of 'count' glyphs
+ * (in font units), starting at 'first'. The 'vertical' flag must be
+ * set to get vertical advance heights. The 'advances' buffer is
+ * caller-allocated. The idea of this function is to be able to
+ * perform device-independent text layout without loading a single
+ * glyph image.
+ *
+ * request_size ::
+ * A handle to a function used to request the new character size. Can
+ * be set to 0 if the scaling done in the base layer suffices.
+ *
+ * select_size ::
+ * A handle to a function used to select a new fixed size. It is used
+ * only if @FT_FACE_FLAG_FIXED_SIZES is set. Can be set to 0 if the
+ * scaling done in the base layer suffices.
+ * @note:
+ * Most function pointers, with the exception of `load_glyph`, can be set
+ * to 0 to indicate a default behaviour.
+ */
typedef struct FT_Driver_ClassRec_
{
FT_Module_Class root;
@@ -184,45 +191,28 @@ FT_BEGIN_HEADER
} FT_Driver_ClassRec, *FT_Driver_Class;
- /*************************************************************************/
- /* */
- /* <Macro> */
- /* FT_DECLARE_DRIVER */
- /* */
- /* <Description> */
- /* Used to create a forward declaration of an FT_Driver_ClassRec */
- /* struct instance. */
- /* */
- /* <Macro> */
- /* FT_DEFINE_DRIVER */
- /* */
- /* <Description> */
- /* Used to initialize an instance of FT_Driver_ClassRec struct. */
- /* */
- /* When FT_CONFIG_OPTION_PIC is defined a `create' function has to be */
- /* called with a pointer where the allocated structure is returned. */
- /* And when it is no longer needed a `destroy' function needs to be */
- /* called to release that allocation. */
- /* */
- /* `ftinit.c' (ft_create_default_module_classes) already contains a */
- /* mechanism to call these functions for the default modules */
- /* described in `ftmodule.h'. */
- /* */
- /* Notice that the created `create' and `destroy' functions call */
- /* `pic_init' and `pic_free' to allow you to manually allocate and */
- /* initialize any additional global data, like a module specific */
- /* interface, and put them in the global pic container defined in */
- /* `ftpic.h'. If you don't need them just implement the functions as */
- /* empty to resolve the link error. Also the `pic_init' and */
- /* `pic_free' functions should be declared in `pic.h', to be referred */
- /* by driver definition calling `FT_DEFINE_DRIVER' in following. */
- /* */
- /* When FT_CONFIG_OPTION_PIC is not defined the struct will be */
- /* allocated in the global scope (or the scope where the macro is */
- /* used). */
- /* */
-#ifndef FT_CONFIG_OPTION_PIC
-
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_DECLARE_DRIVER
+ *
+ * @description:
+ * Used to create a forward declaration of an FT_Driver_ClassRec struct
+ * instance.
+ *
+ * @macro:
+ * FT_DEFINE_DRIVER
+ *
+ * @description:
+ * Used to initialize an instance of FT_Driver_ClassRec struct.
+ *
+ * `ftinit.c` (ft_create_default_module_classes) already contains a
+ * mechanism to call these functions for the default modules described in
+ * `ftmodule.h`.
+ *
+ * The struct will be allocated in the global scope (or the scope where
+ * the macro is used).
+ */
#define FT_DECLARE_DRIVER( class_ ) \
FT_CALLBACK_TABLE \
const FT_Driver_ClassRec class_;
@@ -289,108 +279,6 @@ FT_BEGIN_HEADER
select_size_ \
};
-#else /* FT_CONFIG_OPTION_PIC */
-
-#define FT_DECLARE_DRIVER( class_ ) FT_DECLARE_MODULE( class_ )
-
-#define FT_DEFINE_DRIVER( \
- class_, \
- flags_, \
- size_, \
- name_, \
- version_, \
- requires_, \
- interface_, \
- init_, \
- done_, \
- get_interface_, \
- face_object_size_, \
- size_object_size_, \
- slot_object_size_, \
- init_face_, \
- done_face_, \
- init_size_, \
- done_size_, \
- init_slot_, \
- done_slot_, \
- load_glyph_, \
- get_kerning_, \
- attach_file_, \
- get_advances_, \
- request_size_, \
- select_size_ ) \
- void \
- FT_Destroy_Class_ ## class_( FT_Library library, \
- FT_Module_Class* clazz ) \
- { \
- FT_Memory memory = library->memory; \
- FT_Driver_Class dclazz = (FT_Driver_Class)clazz; \
- \
- \
- class_ ## _pic_free( library ); \
- if ( dclazz ) \
- FT_FREE( dclazz ); \
- } \
- \
- \
- FT_Error \
- FT_Create_Class_ ## class_( FT_Library library, \
- FT_Module_Class** output_class ) \
- { \
- FT_Driver_Class clazz = NULL; \
- FT_Error error; \
- FT_Memory memory = library->memory; \
- \
- \
- if ( FT_ALLOC( clazz, sizeof ( *clazz ) ) ) \
- return error; \
- \
- error = class_ ## _pic_init( library ); \
- if ( error ) \
- { \
- FT_FREE( clazz ); \
- return error; \
- } \
- \
- FT_DEFINE_ROOT_MODULE( flags_, \
- size_, \
- name_, \
- version_, \
- requires_, \
- interface_, \
- init_, \
- done_, \
- get_interface_ ) \
- \
- clazz->face_object_size = face_object_size_; \
- clazz->size_object_size = size_object_size_; \
- clazz->slot_object_size = slot_object_size_; \
- \
- clazz->init_face = init_face_; \
- clazz->done_face = done_face_; \
- \
- clazz->init_size = init_size_; \
- clazz->done_size = done_size_; \
- \
- clazz->init_slot = init_slot_; \
- clazz->done_slot = done_slot_; \
- \
- clazz->load_glyph = load_glyph_; \
- \
- clazz->get_kerning = get_kerning_; \
- clazz->attach_file = attach_file_; \
- clazz->get_advances = get_advances_; \
- \
- clazz->request_size = request_size_; \
- clazz->select_size = select_size_; \
- \
- *output_class = (FT_Module_Class*)clazz; \
- \
- return FT_Err_Ok; \
- }
-
-
-#endif /* FT_CONFIG_OPTION_PIC */
FT_END_HEADER
diff --git a/thirdparty/freetype/include/freetype/internal/ftgloadr.h b/thirdparty/freetype/include/freetype/internal/ftgloadr.h
index a002fdbfca..770871d81b 100644
--- a/thirdparty/freetype/include/freetype/internal/ftgloadr.h
+++ b/thirdparty/freetype/include/freetype/internal/ftgloadr.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftgloadr.h */
-/* */
-/* The FreeType glyph loader (specification). */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftgloadr.h
+ *
+ * The FreeType glyph loader (specification).
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTGLOADR_H_
@@ -27,15 +27,15 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_GlyphLoader */
- /* */
- /* <Description> */
- /* The glyph loader is an internal object used to load several glyphs */
- /* together (for example, in the case of composites). */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_GlyphLoader
+ *
+ * @description:
+ * The glyph loader is an internal object used to load several glyphs
+ * together (for example, in the case of composites).
+ */
typedef struct FT_SubGlyphRec_
{
FT_Int index;
@@ -138,11 +138,6 @@ FT_BEGIN_HEADER
FT_BASE( void )
FT_GlyphLoader_Add( FT_GlyphLoader loader );
- /* copy points from one glyph loader to another */
- FT_BASE( FT_Error )
- FT_GlyphLoader_CopyPoints( FT_GlyphLoader target,
- FT_GlyphLoader source );
-
/* */
diff --git a/thirdparty/freetype/include/freetype/internal/fthash.h b/thirdparty/freetype/include/freetype/internal/fthash.h
index f22f9d5d39..249188040b 100644
--- a/thirdparty/freetype/include/freetype/internal/fthash.h
+++ b/thirdparty/freetype/include/freetype/internal/fthash.h
@@ -1,10 +1,10 @@
-/***************************************************************************/
-/* */
-/* fthash.h */
-/* */
-/* Hashing functions (specification). */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * fthash.h
+ *
+ * Hashing functions (specification).
+ *
+ */
/*
* Copyright 2000 Computing Research Labs, New Mexico State University
@@ -30,13 +30,13 @@
* THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
- /*************************************************************************/
- /* */
- /* This file is based on code from bdf.c,v 1.22 2000/03/16 20:08:50 */
- /* */
- /* taken from Mark Leisher's xmbdfed package */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * This file is based on code from bdf.c,v 1.22 2000/03/16 20:08:50
+ *
+ * taken from Mark Leisher's xmbdfed package
+ *
+ */
#ifndef FTHASH_H_
diff --git a/thirdparty/freetype/include/freetype/internal/ftmemory.h b/thirdparty/freetype/include/freetype/internal/ftmemory.h
index 054eaec31f..78bd3bc229 100644
--- a/thirdparty/freetype/include/freetype/internal/ftmemory.h
+++ b/thirdparty/freetype/include/freetype/internal/ftmemory.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftmemory.h */
-/* */
-/* The FreeType memory management macros (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftmemory.h
+ *
+ * The FreeType memory management macros (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTMEMORY_H_
@@ -28,16 +28,16 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* <Macro> */
- /* FT_SET_ERROR */
- /* */
- /* <Description> */
- /* This macro is used to set an implicit `error' variable to a given */
- /* expression's value (usually a function call), and convert it to a */
- /* boolean which is set whenever the value is != 0. */
- /* */
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_SET_ERROR
+ *
+ * @description:
+ * This macro is used to set an implicit 'error' variable to a given
+ * expression's value (usually a function call), and convert it to a
+ * boolean which is set whenever the value is != 0.
+ */
#undef FT_SET_ERROR
#define FT_SET_ERROR( expression ) \
( ( error = (expression) ) != 0 )
@@ -58,9 +58,9 @@ FT_BEGIN_HEADER
/*
- * C++ refuses to handle statements like p = (void*)anything, with `p' a
- * typed pointer. Since we don't have a `typeof' operator in standard
- * C++, we have to use a template to emulate it.
+ * C++ refuses to handle statements like p = (void*)anything, with `p' a
+ * typed pointer. Since we don't have a `typeof' operator in standard C++,
+ * we have to use a template to emulate it.
*/
#ifdef __cplusplus
@@ -107,8 +107,8 @@ extern "C++"
/*
- * The allocation functions return a pointer, and the error code
- * is written to through the `p_error' parameter.
+ * The allocation functions return a pointer, and the error code is written
+ * to through the `p_error' parameter.
*/
/* The `q' variants of the functions below (`q' for `quick') don't fill */
@@ -253,20 +253,19 @@ extern "C++"
/*
- * Return the maximum number of addressable elements in an array.
- * We limit ourselves to INT_MAX, rather than UINT_MAX, to avoid
- * any problems.
+ * Return the maximum number of addressable elements in an array. We limit
+ * ourselves to INT_MAX, rather than UINT_MAX, to avoid any problems.
*/
#define FT_ARRAY_MAX( ptr ) ( FT_INT_MAX / sizeof ( *(ptr) ) )
#define FT_ARRAY_CHECK( ptr, count ) ( (count) <= FT_ARRAY_MAX( ptr ) )
- /*************************************************************************/
- /* */
- /* The following functions macros expect that their pointer argument is */
- /* _typed_ in order to automatically compute array element sizes. */
- /* */
+ /**************************************************************************
+ *
+ * The following functions macros expect that their pointer argument is
+ * _typed_ in order to automatically compute array element sizes.
+ */
#define FT_MEM_NEW_ARRAY( ptr, count ) \
FT_ASSIGNP_INNER( ptr, ft_mem_realloc( memory, \
diff --git a/thirdparty/freetype/include/freetype/internal/ftobjs.h b/thirdparty/freetype/include/freetype/internal/ftobjs.h
index 1c3c6ad456..f3a41b35ab 100644
--- a/thirdparty/freetype/include/freetype/internal/ftobjs.h
+++ b/thirdparty/freetype/include/freetype/internal/ftobjs.h
@@ -1,26 +1,26 @@
-/***************************************************************************/
-/* */
-/* ftobjs.h */
-/* */
-/* The FreeType private base classes (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* This file contains the definition of all internal FreeType classes. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * ftobjs.h
+ *
+ * The FreeType private base classes (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * This file contains the definition of all internal FreeType classes.
+ *
+ */
#ifndef FTOBJS_H_
@@ -35,7 +35,6 @@
#include FT_INTERNAL_DRIVER_H
#include FT_INTERNAL_AUTOHINT_H
#include FT_INTERNAL_SERVICE_H
-#include FT_INTERNAL_PIC_H
#include FT_INTERNAL_CALC_H
#ifdef FT_CONFIG_OPTION_INCREMENTAL
@@ -46,10 +45,10 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* Some generic definitions. */
- /* */
+ /**************************************************************************
+ *
+ * Some generic definitions.
+ */
#ifndef TRUE
#define TRUE 1
#endif
@@ -63,20 +62,20 @@ FT_BEGIN_HEADER
#endif
- /*************************************************************************/
- /* */
- /* The min and max functions missing in C. As usual, be careful not to */
- /* write things like FT_MIN( a++, b++ ) to avoid side effects. */
- /* */
+ /**************************************************************************
+ *
+ * The min and max functions missing in C. As usual, be careful not to
+ * write things like FT_MIN( a++, b++ ) to avoid side effects.
+ */
#define FT_MIN( a, b ) ( (a) < (b) ? (a) : (b) )
#define FT_MAX( a, b ) ( (a) > (b) ? (a) : (b) )
#define FT_ABS( a ) ( (a) < 0 ? -(a) : (a) )
/*
- * Approximate sqrt(x*x+y*y) using the `alpha max plus beta min'
- * algorithm. We use alpha = 1, beta = 3/8, giving us results with a
- * largest error less than 7% compared to the exact value.
+ * Approximate sqrt(x*x+y*y) using the `alpha max plus beta min' algorithm.
+ * We use alpha = 1, beta = 3/8, giving us results with a largest error
+ * less than 7% compared to the exact value.
*/
#define FT_HYPOT( x, y ) \
( x = FT_ABS( x ), \
@@ -111,9 +110,8 @@ FT_BEGIN_HEADER
/*
- * character classification functions -- since these are used to parse
- * font files, we must not use those in <ctypes.h> which are
- * locale-dependent
+ * character classification functions -- since these are used to parse font
+ * files, we must not use those in <ctypes.h> which are locale-dependent
*/
#define ft_isdigit( x ) ( ( (unsigned)(x) - '0' ) < 10U )
@@ -187,7 +185,7 @@ FT_BEGIN_HEADER
FT_UInt32 char_code,
FT_UInt32 variant_selector );
- typedef FT_Bool
+ typedef FT_Int
(*FT_CMap_CharVarIsDefaultFunc)( FT_CMap cmap,
FT_UInt32 char_code,
FT_UInt32 variant_selector );
@@ -228,8 +226,6 @@ FT_BEGIN_HEADER
} FT_CMap_ClassRec;
-#ifndef FT_CONFIG_OPTION_PIC
-
#define FT_DECLARE_CMAP_CLASS( class_ ) \
FT_CALLBACK_TABLE const FT_CMap_ClassRec class_;
@@ -260,45 +256,6 @@ FT_BEGIN_HEADER
variantchar_list_ \
};
-#else /* FT_CONFIG_OPTION_PIC */
-
-#define FT_DECLARE_CMAP_CLASS( class_ ) \
- void \
- FT_Init_Class_ ## class_( FT_Library library, \
- FT_CMap_ClassRec* clazz );
-
-#define FT_DEFINE_CMAP_CLASS( \
- class_, \
- size_, \
- init_, \
- done_, \
- char_index_, \
- char_next_, \
- char_var_index_, \
- char_var_default_, \
- variant_list_, \
- charvariant_list_, \
- variantchar_list_ ) \
- void \
- FT_Init_Class_ ## class_( FT_Library library, \
- FT_CMap_ClassRec* clazz ) \
- { \
- FT_UNUSED( library ); \
- \
- clazz->size = size_; \
- clazz->init = init_; \
- clazz->done = done_; \
- clazz->char_index = char_index_; \
- clazz->char_next = char_next_; \
- clazz->char_var_index = char_var_index_; \
- clazz->char_var_default = char_var_default_; \
- clazz->variant_list = variant_list_; \
- clazz->charvariant_list = charvariant_list_; \
- clazz->variantchar_list = variantchar_list_; \
- }
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
/* create a new charmap and add it to charmap->face */
FT_BASE( FT_Error )
@@ -312,11 +269,11 @@ FT_BEGIN_HEADER
FT_CMap_Done( FT_CMap cmap );
- /* adds LCD padding to Min and Max boundaries */
+ /* add LCD padding to CBox */
FT_BASE( void )
- ft_lcd_padding( FT_Pos* Min,
- FT_Pos* Max,
- FT_GlyphSlot slot );
+ ft_lcd_padding( FT_BBox* cbox,
+ FT_GlyphSlot slot,
+ FT_Render_Mode mode );
#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
@@ -333,74 +290,72 @@ FT_BEGIN_HEADER
#endif /* FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_Face_InternalRec */
- /* */
- /* <Description> */
- /* This structure contains the internal fields of each FT_Face */
- /* object. These fields may change between different releases of */
- /* FreeType. */
- /* */
- /* <Fields> */
- /* max_points :: */
- /* The maximum number of points used to store the vectorial outline */
- /* of any glyph in this face. If this value cannot be known in */
- /* advance, or if the face isn't scalable, this should be set to 0. */
- /* Only relevant for scalable formats. */
- /* */
- /* max_contours :: */
- /* The maximum number of contours used to store the vectorial */
- /* outline of any glyph in this face. If this value cannot be */
- /* known in advance, or if the face isn't scalable, this should be */
- /* set to 0. Only relevant for scalable formats. */
- /* */
- /* transform_matrix :: */
- /* A 2x2 matrix of 16.16 coefficients used to transform glyph */
- /* outlines after they are loaded from the font. Only used by the */
- /* convenience functions. */
- /* */
- /* transform_delta :: */
- /* A translation vector used to transform glyph outlines after they */
- /* are loaded from the font. Only used by the convenience */
- /* functions. */
- /* */
- /* transform_flags :: */
- /* Some flags used to classify the transform. Only used by the */
- /* convenience functions. */
- /* */
- /* services :: */
- /* A cache for frequently used services. It should be only */
- /* accessed with the macro `FT_FACE_LOOKUP_SERVICE'. */
- /* */
- /* incremental_interface :: */
- /* If non-null, the interface through which glyph data and metrics */
- /* are loaded incrementally for faces that do not provide all of */
- /* this data when first opened. This field exists only if */
- /* @FT_CONFIG_OPTION_INCREMENTAL is defined. */
- /* */
- /* no_stem_darkening :: */
- /* Overrides the module-level default, see @stem-darkening[cff], */
- /* for example. FALSE and TRUE toggle stem darkening on and off, */
- /* respectively, value~-1 means to use the module/driver default. */
- /* */
- /* random_seed :: */
- /* If positive, override the seed value for the CFF `random' */
- /* operator. Value~0 means to use the font's value. Value~-1 */
- /* means to use the CFF driver's default. */
- /* */
- /* lcd_weights :: */
- /* lcd_filter_func :: */
- /* If subpixel rendering is activated, the LCD filtering weights */
- /* and callback function. */
- /* */
- /* refcount :: */
- /* A counter initialized to~1 at the time an @FT_Face structure is */
- /* created. @FT_Reference_Face increments this counter, and */
- /* @FT_Done_Face only destroys a face if the counter is~1, */
- /* otherwise it simply decrements it. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Face_InternalRec
+ *
+ * @description:
+ * This structure contains the internal fields of each FT_Face object.
+ * These fields may change between different releases of FreeType.
+ *
+ * @fields:
+ * max_points ::
+ * The maximum number of points used to store the vectorial outline of
+ * any glyph in this face. If this value cannot be known in advance,
+ * or if the face isn't scalable, this should be set to 0. Only
+ * relevant for scalable formats.
+ *
+ * max_contours ::
+ * The maximum number of contours used to store the vectorial outline
+ * of any glyph in this face. If this value cannot be known in
+ * advance, or if the face isn't scalable, this should be set to 0.
+ * Only relevant for scalable formats.
+ *
+ * transform_matrix ::
+ * A 2x2 matrix of 16.16 coefficients used to transform glyph outlines
+ * after they are loaded from the font. Only used by the convenience
+ * functions.
+ *
+ * transform_delta ::
+ * A translation vector used to transform glyph outlines after they are
+ * loaded from the font. Only used by the convenience functions.
+ *
+ * transform_flags ::
+ * Some flags used to classify the transform. Only used by the
+ * convenience functions.
+ *
+ * services ::
+ * A cache for frequently used services. It should be only accessed
+ * with the macro `FT_FACE_LOOKUP_SERVICE`.
+ *
+ * incremental_interface ::
+ * If non-null, the interface through which glyph data and metrics are
+ * loaded incrementally for faces that do not provide all of this data
+ * when first opened. This field exists only if
+ * @FT_CONFIG_OPTION_INCREMENTAL is defined.
+ *
+ * no_stem_darkening ::
+ * Overrides the module-level default, see @stem-darkening[cff], for
+ * example. FALSE and TRUE toggle stem darkening on and off,
+ * respectively, value~-1 means to use the module/driver default.
+ *
+ * random_seed ::
+ * If positive, override the seed value for the CFF 'random' operator.
+ * Value~0 means to use the font's value. Value~-1 means to use the
+ * CFF driver's default.
+ *
+ * lcd_weights ::
+ * lcd_filter_func ::
+ * These fields specify the LCD filtering weights and callback function
+ * for ClearType-style subpixel rendering.
+ *
+ * refcount ::
+ * A counter initialized to~1 at the time an @FT_Face structure is
+ * created. @FT_Reference_Face increments this counter, and
+ * @FT_Done_Face only destroys a face if the counter is~1, otherwise it
+ * simply decrements it.
+ */
typedef struct FT_Face_InternalRec_
{
FT_Matrix transform_matrix;
@@ -426,39 +381,44 @@ FT_BEGIN_HEADER
} FT_Face_InternalRec;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_Slot_InternalRec */
- /* */
- /* <Description> */
- /* This structure contains the internal fields of each FT_GlyphSlot */
- /* object. These fields may change between different releases of */
- /* FreeType. */
- /* */
- /* <Fields> */
- /* loader :: The glyph loader object used to load outlines */
- /* into the glyph slot. */
- /* */
- /* flags :: Possible values are zero or */
- /* FT_GLYPH_OWN_BITMAP. The latter indicates */
- /* that the FT_GlyphSlot structure owns the */
- /* bitmap buffer. */
- /* */
- /* glyph_transformed :: Boolean. Set to TRUE when the loaded glyph */
- /* must be transformed through a specific */
- /* font transformation. This is _not_ the same */
- /* as the face transform set through */
- /* FT_Set_Transform(). */
- /* */
- /* glyph_matrix :: The 2x2 matrix corresponding to the glyph */
- /* transformation, if necessary. */
- /* */
- /* glyph_delta :: The 2d translation vector corresponding to */
- /* the glyph transformation, if necessary. */
- /* */
- /* glyph_hints :: Format-specific glyph hints management. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Slot_InternalRec
+ *
+ * @description:
+ * This structure contains the internal fields of each FT_GlyphSlot
+ * object. These fields may change between different releases of
+ * FreeType.
+ *
+ * @fields:
+ * loader ::
+ * The glyph loader object used to load outlines into the glyph slot.
+ *
+ * flags ::
+ * Possible values are zero or FT_GLYPH_OWN_BITMAP. The latter
+ * indicates that the FT_GlyphSlot structure owns the bitmap buffer.
+ *
+ * glyph_transformed ::
+ * Boolean. Set to TRUE when the loaded glyph must be transformed
+ * through a specific font transformation. This is _not_ the same as
+ * the face transform set through FT_Set_Transform().
+ *
+ * glyph_matrix ::
+ * The 2x2 matrix corresponding to the glyph transformation, if
+ * necessary.
+ *
+ * glyph_delta ::
+ * The 2d translation vector corresponding to the glyph transformation,
+ * if necessary.
+ *
+ * glyph_hints ::
+ * Format-specific glyph hints management.
+ *
+ * load_flags ::
+ * The load flags passed as an argument to @FT_Load_Glyph while
+ * initializing the glyph slot.
+ */
#define FT_GLYPH_OWN_BITMAP 0x1U
@@ -471,26 +431,30 @@ FT_BEGIN_HEADER
FT_Vector glyph_delta;
void* glyph_hints;
+ FT_Int32 load_flags;
+
} FT_GlyphSlot_InternalRec;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_Size_InternalRec */
- /* */
- /* <Description> */
- /* This structure contains the internal fields of each FT_Size */
- /* object. */
- /* */
- /* <Fields> */
- /* module_data :: Data specific to a driver module. */
- /* */
- /* autohint_mode :: The used auto-hinting mode. */
- /* */
- /* autohint_metrics :: Metrics used by the auto-hinter. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Size_InternalRec
+ *
+ * @description:
+ * This structure contains the internal fields of each FT_Size object.
+ *
+ * @fields:
+ * module_data ::
+ * Data specific to a driver module.
+ *
+ * autohint_mode ::
+ * The used auto-hinting mode.
+ *
+ * autohint_metrics ::
+ * Metrics used by the auto-hinter.
+ *
+ */
typedef struct FT_Size_InternalRec_
{
@@ -515,21 +479,24 @@ FT_BEGIN_HEADER
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_ModuleRec */
- /* */
- /* <Description> */
- /* A module object instance. */
- /* */
- /* <Fields> */
- /* clazz :: A pointer to the module's class. */
- /* */
- /* library :: A handle to the parent library object. */
- /* */
- /* memory :: A handle to the memory manager. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_ModuleRec
+ *
+ * @description:
+ * A module object instance.
+ *
+ * @fields:
+ * clazz ::
+ * A pointer to the module's class.
+ *
+ * library ::
+ * A handle to the parent library object.
+ *
+ * memory ::
+ * A handle to the memory manager.
+ */
typedef struct FT_ModuleRec_
{
FT_Module_Class* clazz;
@@ -572,27 +539,29 @@ FT_BEGIN_HEADER
FT_MODULE_DRIVER_HINTS_LIGHTLY )
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Get_Module_Interface */
- /* */
- /* <Description> */
- /* Finds a module and returns its specific interface as a typeless */
- /* pointer. */
- /* */
- /* <Input> */
- /* library :: A handle to the library object. */
- /* */
- /* module_name :: The module's name (as an ASCII string). */
- /* */
- /* <Return> */
- /* A module-specific interface if available, 0 otherwise. */
- /* */
- /* <Note> */
- /* You should better be familiar with FreeType internals to know */
- /* which module to look for, and what its interface is :-) */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Module_Interface
+ *
+ * @description:
+ * Finds a module and returns its specific interface as a typeless
+ * pointer.
+ *
+ * @input:
+ * library ::
+ * A handle to the library object.
+ *
+ * module_name ::
+ * The module's name (as an ASCII string).
+ *
+ * @return:
+ * A module-specific interface if available, 0 otherwise.
+ *
+ * @note:
+ * You should better be familiar with FreeType internals to know which
+ * module to look for, and what its interface is :-)
+ */
FT_BASE( const void* )
FT_Get_Module_Interface( FT_Library library,
const char* mod_name );
@@ -643,44 +612,46 @@ FT_BEGIN_HEADER
#define FT_FACE_SIZE( x ) FT_FACE( x )->size
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_New_GlyphSlot */
- /* */
- /* <Description> */
- /* It is sometimes useful to have more than one glyph slot for a */
- /* given face object. This function is used to create additional */
- /* slots. All of them are automatically discarded when the face is */
- /* destroyed. */
- /* */
- /* <Input> */
- /* face :: A handle to a parent face object. */
- /* */
- /* <Output> */
- /* aslot :: A handle to a new glyph slot object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_New_GlyphSlot
+ *
+ * @description:
+ * It is sometimes useful to have more than one glyph slot for a given
+ * face object. This function is used to create additional slots. All
+ * of them are automatically discarded when the face is destroyed.
+ *
+ * @input:
+ * face ::
+ * A handle to a parent face object.
+ *
+ * @output:
+ * aslot ::
+ * A handle to a new glyph slot object.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ */
FT_BASE( FT_Error )
FT_New_GlyphSlot( FT_Face face,
FT_GlyphSlot *aslot );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Done_GlyphSlot */
- /* */
- /* <Description> */
- /* Destroys a given glyph slot. Remember however that all slots are */
- /* automatically destroyed with its parent. Using this function is */
- /* not always mandatory. */
- /* */
- /* <Input> */
- /* slot :: A handle to a target glyph slot. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Done_GlyphSlot
+ *
+ * @description:
+ * Destroys a given glyph slot. Remember however that all slots are
+ * automatically destroyed with its parent. Using this function is not
+ * always mandatory.
+ *
+ * @input:
+ * slot ::
+ * A handle to a target glyph slot.
+ */
FT_BASE( void )
FT_Done_GlyphSlot( FT_GlyphSlot slot );
@@ -730,8 +701,9 @@ FT_BEGIN_HEADER
ft_glyphslot_free_bitmap( FT_GlyphSlot slot );
- /* Preset bitmap metrics of an outline glyphslot prior to rendering. */
- FT_BASE( void )
+ /* Preset bitmap metrics of an outline glyphslot prior to rendering */
+ /* and check whether the truncated bbox is too large for rendering. */
+ FT_BASE( FT_Bool )
ft_glyphslot_preset_bitmap( FT_GlyphSlot slot,
FT_Render_Mode mode,
const FT_Vector* origin );
@@ -802,28 +774,30 @@ FT_BEGIN_HEADER
#define FT_DRIVER_CLASS( x ) FT_DRIVER( x )->clazz
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_DriverRec */
- /* */
- /* <Description> */
- /* The root font driver class. A font driver is responsible for */
- /* managing and loading font files of a given format. */
- /* */
- /* <Fields> */
- /* root :: Contains the fields of the root module class. */
- /* */
- /* clazz :: A pointer to the font driver's class. Note that */
- /* this is NOT root.clazz. `class' wasn't used */
- /* as it is a reserved word in C++. */
- /* */
- /* faces_list :: The list of faces currently opened by this */
- /* driver. */
- /* */
- /* glyph_loader :: Unused. Used to be glyph loader for all faces */
- /* managed by this driver. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_DriverRec
+ *
+ * @description:
+ * The root font driver class. A font driver is responsible for managing
+ * and loading font files of a given format.
+ *
+ * @fields:
+ * root ::
+ * Contains the fields of the root module class.
+ *
+ * clazz ::
+ * A pointer to the font driver's class. Note that this is NOT
+ * root.clazz. 'class' wasn't used as it is a reserved word in C++.
+ *
+ * faces_list ::
+ * The list of faces currently opened by this driver.
+ *
+ * glyph_loader ::
+ * Unused. Used to be glyph loader for all faces managed by this
+ * driver.
+ */
typedef struct FT_DriverRec_
{
FT_ModuleRec root;
@@ -847,72 +821,77 @@ FT_BEGIN_HEADER
/*************************************************************************/
- /* This hook is used by the TrueType debugger. It must be set to an */
- /* alternate truetype bytecode interpreter function. */
-#define FT_DEBUG_HOOK_TRUETYPE 0
-
-
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_LibraryRec */
- /* */
- /* <Description> */
- /* The FreeType library class. This is the root of all FreeType */
- /* data. Use FT_New_Library() to create a library object, and */
- /* FT_Done_Library() to discard it and all child objects. */
- /* */
- /* <Fields> */
- /* memory :: The library's memory object. Manages memory */
- /* allocation. */
- /* */
- /* version_major :: The major version number of the library. */
- /* */
- /* version_minor :: The minor version number of the library. */
- /* */
- /* version_patch :: The current patch level of the library. */
- /* */
- /* num_modules :: The number of modules currently registered */
- /* within this library. This is set to 0 for new */
- /* libraries. New modules are added through the */
- /* FT_Add_Module() API function. */
- /* */
- /* modules :: A table used to store handles to the currently */
- /* registered modules. Note that each font driver */
- /* contains a list of its opened faces. */
- /* */
- /* renderers :: The list of renderers currently registered */
- /* within the library. */
- /* */
- /* cur_renderer :: The current outline renderer. This is a */
- /* shortcut used to avoid parsing the list on */
- /* each call to FT_Outline_Render(). It is a */
- /* handle to the current renderer for the */
- /* FT_GLYPH_FORMAT_OUTLINE format. */
- /* */
- /* auto_hinter :: The auto-hinter module interface. */
- /* */
- /* debug_hooks :: An array of four function pointers that allow */
- /* debuggers to hook into a font format's */
- /* interpreter. Currently, only the TrueType */
- /* bytecode debugger uses this. */
- /* */
- /* lcd_weights :: If subpixel rendering is activated, the LCD */
- /* filter weights, if any. */
- /* */
- /* lcd_filter_func :: If subpixel rendering is activated, the LCD */
- /* filtering callback function. */
- /* */
- /* pic_container :: Contains global structs and tables, instead */
- /* of defining them globally. */
- /* */
- /* refcount :: A counter initialized to~1 at the time an */
- /* @FT_Library structure is created. */
- /* @FT_Reference_Library increments this counter, */
- /* and @FT_Done_Library only destroys a library */
- /* if the counter is~1, otherwise it simply */
- /* decrements it. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_LibraryRec
+ *
+ * @description:
+ * The FreeType library class. This is the root of all FreeType data.
+ * Use FT_New_Library() to create a library object, and FT_Done_Library()
+ * to discard it and all child objects.
+ *
+ * @fields:
+ * memory ::
+ * The library's memory object. Manages memory allocation.
+ *
+ * version_major ::
+ * The major version number of the library.
+ *
+ * version_minor ::
+ * The minor version number of the library.
+ *
+ * version_patch ::
+ * The current patch level of the library.
+ *
+ * num_modules ::
+ * The number of modules currently registered within this library.
+ * This is set to 0 for new libraries. New modules are added through
+ * the FT_Add_Module() API function.
+ *
+ * modules ::
+ * A table used to store handles to the currently registered
+ * modules. Note that each font driver contains a list of its opened
+ * faces.
+ *
+ * renderers ::
+ * The list of renderers currently registered within the library.
+ *
+ * cur_renderer ::
+ * The current outline renderer. This is a shortcut used to avoid
+ * parsing the list on each call to FT_Outline_Render(). It is a
+ * handle to the current renderer for the FT_GLYPH_FORMAT_OUTLINE
+ * format.
+ *
+ * auto_hinter ::
+ * The auto-hinter module interface.
+ *
+ * debug_hooks ::
+ * An array of four function pointers that allow debuggers to hook into
+ * a font format's interpreter. Currently, only the TrueType bytecode
+ * debugger uses this.
+ *
+ * lcd_weights ::
+ * The LCD filter weights for ClearType-style subpixel rendering.
+ *
+ * lcd_filter_func ::
+ * The LCD filtering callback function for for ClearType-style subpixel
+ * rendering.
+ *
+ * lcd_geometry ::
+ * This array specifies LCD subpixel geometry and controls Harmony LCD
+ * rendering technique, alternative to ClearType.
+ *
+ * pic_container ::
+ * Contains global structs and tables, instead of defining them
+ * globally.
+ *
+ * refcount ::
+ * A counter initialized to~1 at the time an @FT_Library structure is
+ * created. @FT_Reference_Library increments this counter, and
+ * @FT_Done_Library only destroys a library if the counter is~1,
+ * otherwise it simply decrements it.
+ */
typedef struct FT_LibraryRec_
{
FT_Memory memory; /* library's memory manager */
@@ -933,10 +912,8 @@ FT_BEGIN_HEADER
#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
FT_LcdFiveTapFilter lcd_weights; /* filter weights, if any */
FT_Bitmap_LcdFilterFunc lcd_filter_func; /* filtering callback */
-#endif
-
-#ifdef FT_CONFIG_OPTION_PIC
- FT_PIC_Container pic_container;
+#else
+ FT_Vector lcd_geometry[3]; /* RGB subpixel positions */
#endif
FT_Int refcount;
@@ -970,32 +947,33 @@ FT_BEGIN_HEADER
#ifndef FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_New_Memory */
- /* */
- /* <Description> */
- /* Creates a new memory object. */
- /* */
- /* <Return> */
- /* A pointer to the new memory object. 0 in case of error. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_New_Memory
+ *
+ * @description:
+ * Creates a new memory object.
+ *
+ * @return:
+ * A pointer to the new memory object. 0 in case of error.
+ */
FT_BASE( FT_Memory )
FT_New_Memory( void );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Done_Memory */
- /* */
- /* <Description> */
- /* Discards memory manager. */
- /* */
- /* <Input> */
- /* memory :: A handle to the memory manager. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Done_Memory
+ *
+ * @description:
+ * Discards memory manager.
+ *
+ * @input:
+ * memory ::
+ * A handle to the memory manager.
+ */
FT_BASE( void )
FT_Done_Memory( FT_Memory memory );
@@ -1013,37 +991,16 @@ FT_BEGIN_HEADER
#endif
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
- /**** ****/
- /**** ****/
- /**** P I C S U P P O R T ****/
- /**** ****/
- /**** ****/
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
-
-
- /* PIC support macros for ftimage.h */
-
-
- /*************************************************************************/
- /* */
- /* <Macro> */
- /* FT_DEFINE_OUTLINE_FUNCS */
- /* */
- /* <Description> */
- /* Used to initialize an instance of FT_Outline_Funcs struct. */
- /* When FT_CONFIG_OPTION_PIC is defined an init function will need */
- /* to be called with a pre-allocated structure to be filled. */
- /* When FT_CONFIG_OPTION_PIC is not defined the struct will be */
- /* allocated in the global scope (or the scope where the macro */
- /* is used). */
- /* */
-#ifndef FT_CONFIG_OPTION_PIC
-
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_DEFINE_OUTLINE_FUNCS
+ *
+ * @description:
+ * Used to initialize an instance of FT_Outline_Funcs struct. The struct
+ * will be allocated in the global scope (or the scope where the macro is
+ * used).
+ */
#define FT_DEFINE_OUTLINE_FUNCS( \
class_, \
move_to_, \
@@ -1062,47 +1019,17 @@ FT_BEGIN_HEADER
delta_ \
};
-#else /* FT_CONFIG_OPTION_PIC */
-
-#define FT_DEFINE_OUTLINE_FUNCS( \
- class_, \
- move_to_, \
- line_to_, \
- conic_to_, \
- cubic_to_, \
- shift_, \
- delta_ ) \
- static FT_Error \
- Init_Class_ ## class_( FT_Outline_Funcs* clazz ) \
- { \
- clazz->move_to = move_to_; \
- clazz->line_to = line_to_; \
- clazz->conic_to = conic_to_; \
- clazz->cubic_to = cubic_to_; \
- clazz->shift = shift_; \
- clazz->delta = delta_; \
- \
- return FT_Err_Ok; \
- }
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
-
- /*************************************************************************/
- /* */
- /* <Macro> */
- /* FT_DEFINE_RASTER_FUNCS */
- /* */
- /* <Description> */
- /* Used to initialize an instance of FT_Raster_Funcs struct. */
- /* When FT_CONFIG_OPTION_PIC is defined an init function will need */
- /* to be called with a pre-allocated structure to be filled. */
- /* When FT_CONFIG_OPTION_PIC is not defined the struct will be */
- /* allocated in the global scope (or the scope where the macro */
- /* is used). */
- /* */
-#ifndef FT_CONFIG_OPTION_PIC
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_DEFINE_RASTER_FUNCS
+ *
+ * @description:
+ * Used to initialize an instance of FT_Raster_Funcs struct. The struct
+ * will be allocated in the global scope (or the scope where the macro is
+ * used).
+ */
#define FT_DEFINE_RASTER_FUNCS( \
class_, \
glyph_format_, \
@@ -1121,48 +1048,17 @@ FT_BEGIN_HEADER
raster_done_ \
};
-#else /* FT_CONFIG_OPTION_PIC */
-
-#define FT_DEFINE_RASTER_FUNCS( \
- class_, \
- glyph_format_, \
- raster_new_, \
- raster_reset_, \
- raster_set_mode_, \
- raster_render_, \
- raster_done_ ) \
- void \
- FT_Init_Class_ ## class_( FT_Raster_Funcs* clazz ) \
- { \
- clazz->glyph_format = glyph_format_; \
- clazz->raster_new = raster_new_; \
- clazz->raster_reset = raster_reset_; \
- clazz->raster_set_mode = raster_set_mode_; \
- clazz->raster_render = raster_render_; \
- clazz->raster_done = raster_done_; \
- }
-
-#endif /* FT_CONFIG_OPTION_PIC */
- /* PIC support macros for ftrender.h */
-
-
- /*************************************************************************/
- /* */
- /* <Macro> */
- /* FT_DEFINE_GLYPH */
- /* */
- /* <Description> */
- /* Used to initialize an instance of FT_Glyph_Class struct. */
- /* When FT_CONFIG_OPTION_PIC is defined an init function will need */
- /* to be called with a pre-allocated structure to be filled. */
- /* When FT_CONFIG_OPTION_PIC is not defined the struct will be */
- /* allocated in the global scope (or the scope where the macro */
- /* is used). */
- /* */
-#ifndef FT_CONFIG_OPTION_PIC
-
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_DEFINE_GLYPH
+ *
+ * @description:
+ * The struct will be allocated in the global scope (or the scope where
+ * the macro is used).
+ */
#define FT_DEFINE_GLYPH( \
class_, \
size_, \
@@ -1186,73 +1082,25 @@ FT_BEGIN_HEADER
prepare_ \
};
-#else /* FT_CONFIG_OPTION_PIC */
-
-#define FT_DEFINE_GLYPH( \
- class_, \
- size_, \
- format_, \
- init_, \
- done_, \
- copy_, \
- transform_, \
- bbox_, \
- prepare_ ) \
- void \
- FT_Init_Class_ ## class_( FT_Glyph_Class* clazz ) \
- { \
- clazz->glyph_size = size_; \
- clazz->glyph_format = format_; \
- clazz->glyph_init = init_; \
- clazz->glyph_done = done_; \
- clazz->glyph_copy = copy_; \
- clazz->glyph_transform = transform_; \
- clazz->glyph_bbox = bbox_; \
- clazz->glyph_prepare = prepare_; \
- }
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
-
- /*************************************************************************/
- /* */
- /* <Macro> */
- /* FT_DECLARE_RENDERER */
- /* */
- /* <Description> */
- /* Used to create a forward declaration of a */
- /* FT_Renderer_Class struct instance. */
- /* */
- /* <Macro> */
- /* FT_DEFINE_RENDERER */
- /* */
- /* <Description> */
- /* Used to initialize an instance of FT_Renderer_Class struct. */
- /* */
- /* When FT_CONFIG_OPTION_PIC is defined a `create' function will */
- /* need to be called with a pointer where the allocated structure is */
- /* returned. And when it is no longer needed a `destroy' function */
- /* needs to be called to release that allocation. */
- /* `ftinit.c' (ft_create_default_module_classes) already contains */
- /* a mechanism to call these functions for the default modules */
- /* described in `ftmodule.h'. */
- /* */
- /* Notice that the created `create' and `destroy' functions call */
- /* `pic_init' and `pic_free' to allow you to manually allocate and */
- /* initialize any additional global data, like a module specific */
- /* interface, and put them in the global pic container defined in */
- /* `ftpic.h'. If you don't need them just implement the functions as */
- /* empty to resolve the link error. Also the `pic_init' and */
- /* `pic_free' functions should be declared in `pic.h', to be referred */
- /* by the renderer definition calling `FT_DEFINE_RENDERER' in the */
- /* following. */
- /* */
- /* When FT_CONFIG_OPTION_PIC is not defined the struct will be */
- /* allocated in the global scope (or the scope where the macro */
- /* is used). */
- /* */
-#ifndef FT_CONFIG_OPTION_PIC
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_DECLARE_RENDERER
+ *
+ * @description:
+ * Used to create a forward declaration of a FT_Renderer_Class struct
+ * instance.
+ *
+ * @macro:
+ * FT_DEFINE_RENDERER
+ *
+ * @description:
+ * Used to initialize an instance of FT_Renderer_Class struct.
+ *
+ * The struct will be allocated in the global scope (or the scope where
+ * the macro is used).
+ */
#define FT_DECLARE_RENDERER( class_ ) \
FT_EXPORT_VAR( const FT_Renderer_Class ) class_;
@@ -1295,176 +1143,33 @@ FT_BEGIN_HEADER
raster_class_ \
};
-#else /* FT_CONFIG_OPTION_PIC */
-
-#define FT_DECLARE_RENDERER( class_ ) FT_DECLARE_MODULE( class_ )
-
-#define FT_DEFINE_RENDERER( \
- class_, \
- flags_, \
- size_, \
- name_, \
- version_, \
- requires_, \
- interface_, \
- init_, \
- done_, \
- get_interface_, \
- glyph_format_, \
- render_glyph_, \
- transform_glyph_, \
- get_glyph_cbox_, \
- set_mode_, \
- raster_class_ ) \
- void \
- FT_Destroy_Class_ ## class_( FT_Library library, \
- FT_Module_Class* clazz ) \
- { \
- FT_Renderer_Class* rclazz = (FT_Renderer_Class*)clazz; \
- FT_Memory memory = library->memory; \
- \
- \
- class_ ## _pic_free( library ); \
- if ( rclazz ) \
- FT_FREE( rclazz ); \
- } \
- \
- \
- FT_Error \
- FT_Create_Class_ ## class_( FT_Library library, \
- FT_Module_Class** output_class ) \
- { \
- FT_Renderer_Class* clazz = NULL; \
- FT_Error error; \
- FT_Memory memory = library->memory; \
- \
- \
- if ( FT_ALLOC( clazz, sizeof ( *clazz ) ) ) \
- return error; \
- \
- error = class_ ## _pic_init( library ); \
- if ( error ) \
- { \
- FT_FREE( clazz ); \
- return error; \
- } \
- \
- FT_DEFINE_ROOT_MODULE( flags_, \
- size_, \
- name_, \
- version_, \
- requires_, \
- interface_, \
- init_, \
- done_, \
- get_interface_ ) \
- \
- clazz->glyph_format = glyph_format_; \
- \
- clazz->render_glyph = render_glyph_; \
- clazz->transform_glyph = transform_glyph_; \
- clazz->get_glyph_cbox = get_glyph_cbox_; \
- clazz->set_mode = set_mode_; \
- \
- clazz->raster_class = raster_class_; \
- \
- *output_class = (FT_Module_Class*)clazz; \
- \
- return FT_Err_Ok; \
- }
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
-
- /* PIC support macros for ftmodapi.h **/
-
-
-#ifdef FT_CONFIG_OPTION_PIC
-
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* FT_Module_Creator */
- /* */
- /* <Description> */
- /* A function used to create (allocate) a new module class object. */
- /* The object's members are initialized, but the module itself is */
- /* not. */
- /* */
- /* <Input> */
- /* memory :: A handle to the memory manager. */
- /* output_class :: Initialized with the newly allocated class. */
- /* */
- typedef FT_Error
- (*FT_Module_Creator)( FT_Memory memory,
- FT_Module_Class** output_class );
-
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* FT_Module_Destroyer */
- /* */
- /* <Description> */
- /* A function used to destroy (deallocate) a module class object. */
- /* */
- /* <Input> */
- /* memory :: A handle to the memory manager. */
- /* clazz :: Module class to destroy. */
- /* */
- typedef void
- (*FT_Module_Destroyer)( FT_Memory memory,
- FT_Module_Class* clazz );
-
-#endif
-
-
- /*************************************************************************/
- /* */
- /* <Macro> */
- /* FT_DECLARE_MODULE */
- /* */
- /* <Description> */
- /* Used to create a forward declaration of a */
- /* FT_Module_Class struct instance. */
- /* */
- /* <Macro> */
- /* FT_DEFINE_MODULE */
- /* */
- /* <Description> */
- /* Used to initialize an instance of an FT_Module_Class struct. */
- /* */
- /* When FT_CONFIG_OPTION_PIC is defined a `create' function needs */
- /* to be called with a pointer where the allocated structure is */
- /* returned. And when it is no longer needed a `destroy' function */
- /* needs to be called to release that allocation. */
- /* `ftinit.c' (ft_create_default_module_classes) already contains */
- /* a mechanism to call these functions for the default modules */
- /* described in `ftmodule.h'. */
- /* */
- /* Notice that the created `create' and `destroy' functions call */
- /* `pic_init' and `pic_free' to allow you to manually allocate and */
- /* initialize any additional global data, like a module specific */
- /* interface, and put them in the global pic container defined in */
- /* `ftpic.h'. If you don't need them just implement the functions as */
- /* empty to resolve the link error. Also the `pic_init' and */
- /* `pic_free' functions should be declared in `pic.h', to be referred */
- /* by the module definition calling `FT_DEFINE_MODULE' in the */
- /* following. */
- /* */
- /* When FT_CONFIG_OPTION_PIC is not defined the struct will be */
- /* allocated in the global scope (or the scope where the macro */
- /* is used). */
- /* */
- /* <Macro> */
- /* FT_DEFINE_ROOT_MODULE */
- /* */
- /* <Description> */
- /* Used to initialize an instance of an FT_Module_Class struct inside */
- /* another struct that contains it or in a function that initializes */
- /* that containing struct. */
- /* */
-#ifndef FT_CONFIG_OPTION_PIC
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_DECLARE_MODULE
+ *
+ * @description:
+ * Used to create a forward declaration of a FT_Module_Class struct
+ * instance.
+ *
+ * @macro:
+ * FT_DEFINE_MODULE
+ *
+ * @description:
+ * Used to initialize an instance of an FT_Module_Class struct.
+ *
+ * The struct will be allocated in the global scope (or the scope where
+ * the macro is used).
+ *
+ * @macro:
+ * FT_DEFINE_ROOT_MODULE
+ *
+ * @description:
+ * Used to initialize an instance of an FT_Module_Class struct inside
+ * another struct that contains it or in a function that initializes that
+ * containing struct.
+ */
#define FT_DECLARE_MODULE( class_ ) \
FT_CALLBACK_TABLE \
const FT_Module_Class class_;
@@ -1523,100 +1228,6 @@ FT_BEGIN_HEADER
};
-#else /* FT_CONFIG_OPTION_PIC */
-
-#define FT_DECLARE_MODULE( class_ ) \
- FT_Error \
- FT_Create_Class_ ## class_( FT_Library library, \
- FT_Module_Class** output_class ); \
- void \
- FT_Destroy_Class_ ## class_( FT_Library library, \
- FT_Module_Class* clazz );
-
-#define FT_DEFINE_ROOT_MODULE( \
- flags_, \
- size_, \
- name_, \
- version_, \
- requires_, \
- interface_, \
- init_, \
- done_, \
- get_interface_ ) \
- clazz->root.module_flags = flags_; \
- clazz->root.module_size = size_; \
- clazz->root.module_name = name_; \
- clazz->root.module_version = version_; \
- clazz->root.module_requires = requires_; \
- \
- clazz->root.module_interface = interface_; \
- \
- clazz->root.module_init = init_; \
- clazz->root.module_done = done_; \
- clazz->root.get_interface = get_interface_;
-
-#define FT_DEFINE_MODULE( \
- class_, \
- flags_, \
- size_, \
- name_, \
- version_, \
- requires_, \
- interface_, \
- init_, \
- done_, \
- get_interface_ ) \
- void \
- FT_Destroy_Class_ ## class_( FT_Library library, \
- FT_Module_Class* clazz ) \
- { \
- FT_Memory memory = library->memory; \
- \
- \
- class_ ## _pic_free( library ); \
- if ( clazz ) \
- FT_FREE( clazz ); \
- } \
- \
- \
- FT_Error \
- FT_Create_Class_ ## class_( FT_Library library, \
- FT_Module_Class** output_class ) \
- { \
- FT_Memory memory = library->memory; \
- FT_Module_Class* clazz = NULL; \
- FT_Error error; \
- \
- \
- if ( FT_ALLOC( clazz, sizeof ( *clazz ) ) ) \
- return error; \
- error = class_ ## _pic_init( library ); \
- if ( error ) \
- { \
- FT_FREE( clazz ); \
- return error; \
- } \
- \
- clazz->module_flags = flags_; \
- clazz->module_size = size_; \
- clazz->module_name = name_; \
- clazz->module_version = version_; \
- clazz->module_requires = requires_; \
- \
- clazz->module_interface = interface_; \
- \
- clazz->module_init = init_; \
- clazz->module_done = done_; \
- clazz->get_interface = get_interface_; \
- \
- *output_class = clazz; \
- \
- return FT_Err_Ok; \
- }
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
-
FT_END_HEADER
#endif /* FTOBJS_H_ */
diff --git a/thirdparty/freetype/include/freetype/internal/ftpic.h b/thirdparty/freetype/include/freetype/internal/ftpic.h
deleted file mode 100644
index 5214f05989..0000000000
--- a/thirdparty/freetype/include/freetype/internal/ftpic.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/***************************************************************************/
-/* */
-/* ftpic.h */
-/* */
-/* The FreeType position independent code services (declaration). */
-/* */
-/* Copyright 2009-2018 by */
-/* Oran Agra and Mickey Gabel. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
- /*************************************************************************/
- /* */
- /* Modules that ordinarily have const global data that need address */
- /* can instead define pointers here. */
- /* */
- /*************************************************************************/
-
-
-#ifndef FTPIC_H_
-#define FTPIC_H_
-
-
-FT_BEGIN_HEADER
-
-#ifdef FT_CONFIG_OPTION_PIC
-
- typedef struct FT_PIC_Container_
- {
- /* pic containers for base */
- void* base;
-
- /* pic containers for modules */
- void* autofit;
- void* cff;
- void* pshinter;
- void* psnames;
- void* raster;
- void* sfnt;
- void* smooth;
- void* truetype;
-
- } FT_PIC_Container;
-
-
- /* Initialize the various function tables, structs, etc. */
- /* stored in the container. */
- FT_BASE( FT_Error )
- ft_pic_container_init( FT_Library library );
-
-
- /* Destroy the contents of the container. */
- FT_BASE( void )
- ft_pic_container_destroy( FT_Library library );
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
- /* */
-
-FT_END_HEADER
-
-#endif /* FTPIC_H_ */
-
-
-/* END */
diff --git a/thirdparty/freetype/include/freetype/internal/ftpsprop.h b/thirdparty/freetype/include/freetype/internal/ftpsprop.h
index abbb62862b..574837f6d4 100644
--- a/thirdparty/freetype/include/freetype/internal/ftpsprop.h
+++ b/thirdparty/freetype/include/freetype/internal/ftpsprop.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftpsprop.h */
-/* */
-/* Get and set properties of PostScript drivers (specification). */
-/* */
-/* Copyright 2017-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftpsprop.h
+ *
+ * Get and set properties of PostScript drivers (specification).
+ *
+ * Copyright (C) 2017-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTPSPROP_H_
diff --git a/thirdparty/freetype/include/freetype/internal/ftrfork.h b/thirdparty/freetype/include/freetype/internal/ftrfork.h
index 1aca48a0e7..75b3e531bb 100644
--- a/thirdparty/freetype/include/freetype/internal/ftrfork.h
+++ b/thirdparty/freetype/include/freetype/internal/ftrfork.h
@@ -1,24 +1,24 @@
-/***************************************************************************/
-/* */
-/* ftrfork.h */
-/* */
-/* Embedded resource forks accessor (specification). */
-/* */
-/* Copyright 2004-2018 by */
-/* Masatake YAMATO and Redhat K.K. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-/***************************************************************************/
-/* Development of the code in this file is support of */
-/* Information-technology Promotion Agency, Japan. */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftrfork.h
+ *
+ * Embedded resource forks accessor (specification).
+ *
+ * Copyright (C) 2004-2019 by
+ * Masatake YAMATO and Redhat K.K.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+/****************************************************************************
+ * Development of the code in this file is support of
+ * Information-technology Promotion Agency, Japan.
+ */
#ifndef FTRFORK_H_
@@ -72,85 +72,65 @@ FT_BEGIN_HEADER
} FT_RFork_Rule;
/* For fast translation between rule index and rule type,
- * the macros FT_RFORK_xxx should be kept consistent with
- * the raccess_guess_funcs table
+ * the macros FT_RFORK_xxx should be kept consistent with the
+ * raccess_guess_funcs table
*/
typedef struct ft_raccess_guess_rec_ {
ft_raccess_guess_func func;
FT_RFork_Rule type;
} ft_raccess_guess_rec;
-#ifndef FT_CONFIG_OPTION_PIC
- /* this array is a storage in non-PIC mode, so ; is needed in END */
#define CONST_FT_RFORK_RULE_ARRAY_BEGIN( name, type ) \
static const type name[] = {
#define CONST_FT_RFORK_RULE_ARRAY_ENTRY( func_suffix, type_suffix ) \
{ raccess_guess_ ## func_suffix, \
FT_RFork_Rule_ ## type_suffix },
+ /* this array is a storage, thus a final `;' is needed */
#define CONST_FT_RFORK_RULE_ARRAY_END };
-#else /* FT_CONFIG_OPTION_PIC */
-
- /* this array is a function in PIC mode, so no ; is needed in END */
-#define CONST_FT_RFORK_RULE_ARRAY_BEGIN( name, type ) \
- void \
- FT_Init_Table_ ## name( type* storage ) \
- { \
- type* local = storage; \
- \
- \
- int i = 0;
-#define CONST_FT_RFORK_RULE_ARRAY_ENTRY( func_suffix, type_suffix ) \
- local[i].func = raccess_guess_ ## func_suffix; \
- local[i].type = FT_RFork_Rule_ ## type_suffix; \
- i++;
-#define CONST_FT_RFORK_RULE_ARRAY_END }
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
#endif /* FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Raccess_Guess */
- /* */
- /* <Description> */
- /* Guess a file name and offset where the actual resource fork is */
- /* stored. The macro FT_RACCESS_N_RULES holds the number of */
- /* guessing rules; the guessed result for the Nth rule is */
- /* represented as a triplet: a new file name (new_names[N]), a file */
- /* offset (offsets[N]), and an error code (errors[N]). */
- /* */
- /* <Input> */
- /* library :: */
- /* A FreeType library instance. */
- /* */
- /* stream :: */
- /* A file stream containing the resource fork. */
- /* */
- /* base_name :: */
- /* The (base) file name of the resource fork used for some */
- /* guessing rules. */
- /* */
- /* <Output> */
- /* new_names :: */
- /* An array of guessed file names in which the resource forks may */
- /* exist. If `new_names[N]' is NULL, the guessed file name is */
- /* equal to `base_name'. */
- /* */
- /* offsets :: */
- /* An array of guessed file offsets. `offsets[N]' holds the file */
- /* offset of the possible start of the resource fork in file */
- /* `new_names[N]'. */
- /* */
- /* errors :: */
- /* An array of FreeType error codes. `errors[N]' is the error */
- /* code of Nth guessing rule function. If `errors[N]' is not */
- /* FT_Err_Ok, `new_names[N]' and `offsets[N]' are meaningless. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Raccess_Guess
+ *
+ * @description:
+ * Guess a file name and offset where the actual resource fork is stored.
+ * The macro FT_RACCESS_N_RULES holds the number of guessing rules; the
+ * guessed result for the Nth rule is represented as a triplet: a new
+ * file name (new_names[N]), a file offset (offsets[N]), and an error
+ * code (errors[N]).
+ *
+ * @input:
+ * library ::
+ * A FreeType library instance.
+ *
+ * stream ::
+ * A file stream containing the resource fork.
+ *
+ * base_name ::
+ * The (base) file name of the resource fork used for some guessing
+ * rules.
+ *
+ * @output:
+ * new_names ::
+ * An array of guessed file names in which the resource forks may
+ * exist. If 'new_names[N]' is `NULL`, the guessed file name is equal
+ * to `base_name`.
+ *
+ * offsets ::
+ * An array of guessed file offsets. 'offsets[N]' holds the file
+ * offset of the possible start of the resource fork in file
+ * 'new_names[N]'.
+ *
+ * errors ::
+ * An array of FreeType error codes. 'errors[N]' is the error code of
+ * Nth guessing rule function. If 'errors[N]' is not FT_Err_Ok,
+ * 'new_names[N]' and 'offsets[N]' are meaningless.
+ */
FT_BASE( void )
FT_Raccess_Guess( FT_Library library,
FT_Stream stream,
@@ -160,37 +140,37 @@ FT_BEGIN_HEADER
FT_Error* errors );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Raccess_Get_HeaderInfo */
- /* */
- /* <Description> */
- /* Get the information from the header of resource fork. The */
- /* information includes the file offset where the resource map */
- /* starts, and the file offset where the resource data starts. */
- /* `FT_Raccess_Get_DataOffsets' requires these two data. */
- /* */
- /* <Input> */
- /* library :: */
- /* A FreeType library instance. */
- /* */
- /* stream :: */
- /* A file stream containing the resource fork. */
- /* */
- /* rfork_offset :: */
- /* The file offset where the resource fork starts. */
- /* */
- /* <Output> */
- /* map_offset :: */
- /* The file offset where the resource map starts. */
- /* */
- /* rdata_pos :: */
- /* The file offset where the resource data starts. */
- /* */
- /* <Return> */
- /* FreeType error code. FT_Err_Ok means success. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Raccess_Get_HeaderInfo
+ *
+ * @description:
+ * Get the information from the header of resource fork. The information
+ * includes the file offset where the resource map starts, and the file
+ * offset where the resource data starts. `FT_Raccess_Get_DataOffsets`
+ * requires these two data.
+ *
+ * @input:
+ * library ::
+ * A FreeType library instance.
+ *
+ * stream ::
+ * A file stream containing the resource fork.
+ *
+ * rfork_offset ::
+ * The file offset where the resource fork starts.
+ *
+ * @output:
+ * map_offset ::
+ * The file offset where the resource map starts.
+ *
+ * rdata_pos ::
+ * The file offset where the resource data starts.
+ *
+ * @return:
+ * FreeType error code. FT_Err_Ok means success.
+ */
FT_BASE( FT_Error )
FT_Raccess_Get_HeaderInfo( FT_Library library,
FT_Stream stream,
@@ -199,55 +179,54 @@ FT_BEGIN_HEADER
FT_Long *rdata_pos );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Raccess_Get_DataOffsets */
- /* */
- /* <Description> */
- /* Get the data offsets for a tag in a resource fork. Offsets are */
- /* stored in an array because, in some cases, resources in a resource */
- /* fork have the same tag. */
- /* */
- /* <Input> */
- /* library :: */
- /* A FreeType library instance. */
- /* */
- /* stream :: */
- /* A file stream containing the resource fork. */
- /* */
- /* map_offset :: */
- /* The file offset where the resource map starts. */
- /* */
- /* rdata_pos :: */
- /* The file offset where the resource data starts. */
- /* */
- /* tag :: */
- /* The resource tag. */
- /* */
- /* sort_by_res_id :: */
- /* A Boolean to sort the fragmented resource by their ids. */
- /* The fragmented resources for `POST' resource should be sorted */
- /* to restore Type1 font properly. For `sfnt' resources, sorting */
- /* may induce a different order of the faces in comparison to that */
- /* by QuickDraw API. */
- /* */
- /* <Output> */
- /* offsets :: */
- /* The stream offsets for the resource data specified by `tag'. */
- /* This array is allocated by the function, so you have to call */
- /* @ft_mem_free after use. */
- /* */
- /* count :: */
- /* The length of offsets array. */
- /* */
- /* <Return> */
- /* FreeType error code. FT_Err_Ok means success. */
- /* */
- /* <Note> */
- /* Normally you should use `FT_Raccess_Get_HeaderInfo' to get the */
- /* value for `map_offset' and `rdata_pos'. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Raccess_Get_DataOffsets
+ *
+ * @description:
+ * Get the data offsets for a tag in a resource fork. Offsets are stored
+ * in an array because, in some cases, resources in a resource fork have
+ * the same tag.
+ *
+ * @input:
+ * library ::
+ * A FreeType library instance.
+ *
+ * stream ::
+ * A file stream containing the resource fork.
+ *
+ * map_offset ::
+ * The file offset where the resource map starts.
+ *
+ * rdata_pos ::
+ * The file offset where the resource data starts.
+ *
+ * tag ::
+ * The resource tag.
+ *
+ * sort_by_res_id ::
+ * A Boolean to sort the fragmented resource by their ids. The
+ * fragmented resources for 'POST' resource should be sorted to restore
+ * Type1 font properly. For 'sfnt' resources, sorting may induce a
+ * different order of the faces in comparison to that by QuickDraw API.
+ *
+ * @output:
+ * offsets ::
+ * The stream offsets for the resource data specified by 'tag'. This
+ * array is allocated by the function, so you have to call @ft_mem_free
+ * after use.
+ *
+ * count ::
+ * The length of offsets array.
+ *
+ * @return:
+ * FreeType error code. FT_Err_Ok means success.
+ *
+ * @note:
+ * Normally you should use `FT_Raccess_Get_HeaderInfo` to get the value
+ * for `map_offset` and `rdata_pos`.
+ */
FT_BASE( FT_Error )
FT_Raccess_Get_DataOffsets( FT_Library library,
FT_Stream stream,
diff --git a/thirdparty/freetype/include/freetype/internal/ftserv.h b/thirdparty/freetype/include/freetype/internal/ftserv.h
index e01c1679b5..8836cf3f18 100644
--- a/thirdparty/freetype/include/freetype/internal/ftserv.h
+++ b/thirdparty/freetype/include/freetype/internal/ftserv.h
@@ -1,31 +1,31 @@
-/***************************************************************************/
-/* */
-/* ftserv.h */
-/* */
-/* The FreeType services (specification only). */
-/* */
-/* Copyright 2003-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
- /*************************************************************************/
- /* */
- /* Each module can export one or more `services'. Each service is */
- /* identified by a constant string and modeled by a pointer; the latter */
- /* generally corresponds to a structure containing function pointers. */
- /* */
- /* Note that a service's data cannot be a mere function pointer because */
- /* in C it is possible that function pointers might be implemented */
- /* differently than data pointers (e.g. 48 bits instead of 32). */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * ftserv.h
+ *
+ * The FreeType services (specification only).
+ *
+ * Copyright (C) 2003-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+ /**************************************************************************
+ *
+ * Each module can export one or more 'services'. Each service is
+ * identified by a constant string and modeled by a pointer; the latter
+ * generally corresponds to a structure containing function pointers.
+ *
+ * Note that a service's data cannot be a mere function pointer because in
+ * C it is possible that function pointers might be implemented differently
+ * than data pointers (e.g. 48 bits instead of 32).
+ *
+ */
#ifndef FTSERV_H_
@@ -34,7 +34,8 @@
FT_BEGIN_HEADER
- /*
+ /**************************************************************************
+ *
* @macro:
* FT_FACE_FIND_SERVICE
*
@@ -46,15 +47,15 @@ FT_BEGIN_HEADER
* The source face handle.
*
* id ::
- * A string describing the service as defined in the service's
- * header files (e.g. FT_SERVICE_ID_MULTI_MASTERS which expands to
- * `multi-masters'). It is automatically prefixed with
- * `FT_SERVICE_ID_'.
+ * A string describing the service as defined in the service's header
+ * files (e.g. FT_SERVICE_ID_MULTI_MASTERS which expands to
+ * 'multi-masters'). It is automatically prefixed with
+ * `FT_SERVICE_ID_`.
*
* @output:
* ptr ::
- * A variable that receives the service pointer. Will be NULL
- * if not found.
+ * A variable that receives the service pointer. Will be `NULL` if not
+ * found.
*/
#ifdef __cplusplus
@@ -85,7 +86,8 @@ FT_BEGIN_HEADER
#endif /* !C++ */
- /*
+ /**************************************************************************
+ *
* @macro:
* FT_FACE_FIND_GLOBAL_SERVICE
*
@@ -97,15 +99,15 @@ FT_BEGIN_HEADER
* The source face handle.
*
* id ::
- * A string describing the service as defined in the service's
- * header files (e.g. FT_SERVICE_ID_MULTI_MASTERS which expands to
- * `multi-masters'). It is automatically prefixed with
- * `FT_SERVICE_ID_'.
+ * A string describing the service as defined in the service's header
+ * files (e.g. FT_SERVICE_ID_MULTI_MASTERS which expands to
+ * 'multi-masters'). It is automatically prefixed with
+ * `FT_SERVICE_ID_`.
*
* @output:
* ptr ::
- * A variable that receives the service pointer. Will be NULL
- * if not found.
+ * A variable that receives the service pointer. Will be `NULL` if not
+ * found.
*/
#ifdef __cplusplus
@@ -144,8 +146,8 @@ FT_BEGIN_HEADER
/*************************************************************************/
/*
- * The following structure is used to _describe_ a given service
- * to the library. This is useful to build simple static service lists.
+ * The following structure is used to _describe_ a given service to the
+ * library. This is useful to build simple static service lists.
*/
typedef struct FT_ServiceDescRec_
{
@@ -157,35 +159,26 @@ FT_BEGIN_HEADER
typedef const FT_ServiceDescRec* FT_ServiceDesc;
- /*************************************************************************/
- /* */
- /* <Macro> */
- /* FT_DEFINE_SERVICEDESCREC1 */
- /* FT_DEFINE_SERVICEDESCREC2 */
- /* FT_DEFINE_SERVICEDESCREC3 */
- /* FT_DEFINE_SERVICEDESCREC4 */
- /* FT_DEFINE_SERVICEDESCREC5 */
- /* FT_DEFINE_SERVICEDESCREC6 */
- /* FT_DEFINE_SERVICEDESCREC7 */
- /* FT_DEFINE_SERVICEDESCREC8 */
- /* */
- /* <Description> */
- /* Used to initialize an array of FT_ServiceDescRec structures. */
- /* */
- /* When FT_CONFIG_OPTION_PIC is defined a `create' function needs to */
- /* be called with a pointer to return an allocated array. As soon as */
- /* it is no longer needed, a `destroy' function needs to be called to */
- /* release that allocation. */
- /* */
- /* These functions should be manually called from the `pic_init' and */
- /* `pic_free' functions of your module (see FT_DEFINE_MODULE). */
- /* */
- /* When FT_CONFIG_OPTION_PIC is not defined the array will be */
- /* allocated in the global scope (or the scope where the macro is */
- /* used). */
- /* */
-#ifndef FT_CONFIG_OPTION_PIC
-
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_DEFINE_SERVICEDESCREC1
+ * FT_DEFINE_SERVICEDESCREC2
+ * FT_DEFINE_SERVICEDESCREC3
+ * FT_DEFINE_SERVICEDESCREC4
+ * FT_DEFINE_SERVICEDESCREC5
+ * FT_DEFINE_SERVICEDESCREC6
+ * FT_DEFINE_SERVICEDESCREC7
+ * FT_DEFINE_SERVICEDESCREC8
+ * FT_DEFINE_SERVICEDESCREC9
+ * FT_DEFINE_SERVICEDESCREC10
+ *
+ * @description:
+ * Used to initialize an array of FT_ServiceDescRec structures.
+ *
+ * The array will be allocated in the global scope (or the scope where
+ * the macro is used).
+ */
#define FT_DEFINE_SERVICEDESCREC1( class_, \
serv_id_1, serv_data_1 ) \
static const FT_ServiceDescRec class_[] = \
@@ -356,504 +349,15 @@ FT_BEGIN_HEADER
{ NULL, NULL } \
};
-#else /* FT_CONFIG_OPTION_PIC */
-
-#define FT_DEFINE_SERVICEDESCREC1( class_, \
- serv_id_1, serv_data_1 ) \
- void \
- FT_Destroy_Class_ ## class_( FT_Library library, \
- FT_ServiceDescRec* clazz ) \
- { \
- FT_Memory memory = library->memory; \
- \
- \
- if ( clazz ) \
- FT_FREE( clazz ); \
- } \
- \
- FT_Error \
- FT_Create_Class_ ## class_( FT_Library library, \
- FT_ServiceDescRec** output_class ) \
- { \
- FT_ServiceDescRec* clazz = NULL; \
- FT_Error error; \
- FT_Memory memory = library->memory; \
- \
- \
- if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 2 ) ) \
- return error; \
- \
- clazz[0].serv_id = serv_id_1; \
- clazz[0].serv_data = serv_data_1; \
- clazz[1].serv_id = NULL; \
- clazz[1].serv_data = NULL; \
- \
- *output_class = clazz; \
- \
- return FT_Err_Ok; \
- }
-
-#define FT_DEFINE_SERVICEDESCREC2( class_, \
- serv_id_1, serv_data_1, \
- serv_id_2, serv_data_2 ) \
- void \
- FT_Destroy_Class_ ## class_( FT_Library library, \
- FT_ServiceDescRec* clazz ) \
- { \
- FT_Memory memory = library->memory; \
- \
- \
- if ( clazz ) \
- FT_FREE( clazz ); \
- } \
- \
- FT_Error \
- FT_Create_Class_ ## class_( FT_Library library, \
- FT_ServiceDescRec** output_class ) \
- { \
- FT_ServiceDescRec* clazz = NULL; \
- FT_Error error; \
- FT_Memory memory = library->memory; \
- \
- \
- if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 3 ) ) \
- return error; \
- \
- clazz[0].serv_id = serv_id_1; \
- clazz[0].serv_data = serv_data_1; \
- clazz[1].serv_id = serv_id_2; \
- clazz[1].serv_data = serv_data_2; \
- clazz[2].serv_id = NULL; \
- clazz[2].serv_data = NULL; \
- \
- *output_class = clazz; \
- \
- return FT_Err_Ok; \
- }
-
-#define FT_DEFINE_SERVICEDESCREC3( class_, \
- serv_id_1, serv_data_1, \
- serv_id_2, serv_data_2, \
- serv_id_3, serv_data_3 ) \
- void \
- FT_Destroy_Class_ ## class_( FT_Library library, \
- FT_ServiceDescRec* clazz ) \
- { \
- FT_Memory memory = library->memory; \
- \
- \
- if ( clazz ) \
- FT_FREE( clazz ); \
- } \
- \
- FT_Error \
- FT_Create_Class_ ## class_( FT_Library library, \
- FT_ServiceDescRec** output_class ) \
- { \
- FT_ServiceDescRec* clazz = NULL; \
- FT_Error error; \
- FT_Memory memory = library->memory; \
- \
- \
- if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 4 ) ) \
- return error; \
- \
- clazz[0].serv_id = serv_id_1; \
- clazz[0].serv_data = serv_data_1; \
- clazz[1].serv_id = serv_id_2; \
- clazz[1].serv_data = serv_data_2; \
- clazz[2].serv_id = serv_id_3; \
- clazz[2].serv_data = serv_data_3; \
- clazz[3].serv_id = NULL; \
- clazz[3].serv_data = NULL; \
- \
- *output_class = clazz; \
- \
- return FT_Err_Ok; \
- }
-
-#define FT_DEFINE_SERVICEDESCREC4( class_, \
- serv_id_1, serv_data_1, \
- serv_id_2, serv_data_2, \
- serv_id_3, serv_data_3, \
- serv_id_4, serv_data_4 ) \
- void \
- FT_Destroy_Class_ ## class_( FT_Library library, \
- FT_ServiceDescRec* clazz ) \
- { \
- FT_Memory memory = library->memory; \
- \
- \
- if ( clazz ) \
- FT_FREE( clazz ); \
- } \
- \
- FT_Error \
- FT_Create_Class_ ## class_( FT_Library library, \
- FT_ServiceDescRec** output_class ) \
- { \
- FT_ServiceDescRec* clazz = NULL; \
- FT_Error error; \
- FT_Memory memory = library->memory; \
- \
- \
- if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 5 ) ) \
- return error; \
- \
- clazz[0].serv_id = serv_id_1; \
- clazz[0].serv_data = serv_data_1; \
- clazz[1].serv_id = serv_id_2; \
- clazz[1].serv_data = serv_data_2; \
- clazz[2].serv_id = serv_id_3; \
- clazz[2].serv_data = serv_data_3; \
- clazz[3].serv_id = serv_id_4; \
- clazz[3].serv_data = serv_data_4; \
- clazz[4].serv_id = NULL; \
- clazz[4].serv_data = NULL; \
- \
- *output_class = clazz; \
- \
- return FT_Err_Ok; \
- }
-
-#define FT_DEFINE_SERVICEDESCREC5( class_, \
- serv_id_1, serv_data_1, \
- serv_id_2, serv_data_2, \
- serv_id_3, serv_data_3, \
- serv_id_4, serv_data_4, \
- serv_id_5, serv_data_5 ) \
- void \
- FT_Destroy_Class_ ## class_( FT_Library library, \
- FT_ServiceDescRec* clazz ) \
- { \
- FT_Memory memory = library->memory; \
- \
- \
- if ( clazz ) \
- FT_FREE( clazz ); \
- } \
- \
- FT_Error \
- FT_Create_Class_ ## class_( FT_Library library, \
- FT_ServiceDescRec** output_class ) \
- { \
- FT_ServiceDescRec* clazz = NULL; \
- FT_Error error; \
- FT_Memory memory = library->memory; \
- \
- \
- if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 6 ) ) \
- return error; \
- \
- clazz[0].serv_id = serv_id_1; \
- clazz[0].serv_data = serv_data_1; \
- clazz[1].serv_id = serv_id_2; \
- clazz[1].serv_data = serv_data_2; \
- clazz[2].serv_id = serv_id_3; \
- clazz[2].serv_data = serv_data_3; \
- clazz[3].serv_id = serv_id_4; \
- clazz[3].serv_data = serv_data_4; \
- clazz[4].serv_id = serv_id_5; \
- clazz[4].serv_data = serv_data_5; \
- clazz[5].serv_id = NULL; \
- clazz[5].serv_data = NULL; \
- \
- *output_class = clazz; \
- \
- return FT_Err_Ok; \
- }
-
-#define FT_DEFINE_SERVICEDESCREC6( class_, \
- serv_id_1, serv_data_1, \
- serv_id_2, serv_data_2, \
- serv_id_3, serv_data_3, \
- serv_id_4, serv_data_4, \
- serv_id_5, serv_data_5, \
- serv_id_6, serv_data_6 ) \
- void \
- FT_Destroy_Class_ ## class_( FT_Library library, \
- FT_ServiceDescRec* clazz ) \
- { \
- FT_Memory memory = library->memory; \
- \
- \
- if ( clazz ) \
- FT_FREE( clazz ); \
- } \
- \
- FT_Error \
- FT_Create_Class_ ## class_( FT_Library library, \
- FT_ServiceDescRec** output_class ) \
- { \
- FT_ServiceDescRec* clazz = NULL; \
- FT_Error error; \
- FT_Memory memory = library->memory; \
- \
- \
- if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 7 ) ) \
- return error; \
- \
- clazz[0].serv_id = serv_id_1; \
- clazz[0].serv_data = serv_data_1; \
- clazz[1].serv_id = serv_id_2; \
- clazz[1].serv_data = serv_data_2; \
- clazz[2].serv_id = serv_id_3; \
- clazz[2].serv_data = serv_data_3; \
- clazz[3].serv_id = serv_id_4; \
- clazz[3].serv_data = serv_data_4; \
- clazz[4].serv_id = serv_id_5; \
- clazz[4].serv_data = serv_data_5; \
- clazz[5].serv_id = serv_id_6; \
- clazz[5].serv_data = serv_data_6; \
- clazz[6].serv_id = NULL; \
- clazz[6].serv_data = NULL; \
- \
- *output_class = clazz; \
- \
- return FT_Err_Ok; \
- }
-
-#define FT_DEFINE_SERVICEDESCREC7( class_, \
- serv_id_1, serv_data_1, \
- serv_id_2, serv_data_2, \
- serv_id_3, serv_data_3, \
- serv_id_4, serv_data_4, \
- serv_id_5, serv_data_5, \
- serv_id_6, serv_data_6, \
- serv_id_7, serv_data_7 ) \
- void \
- FT_Destroy_Class_ ## class_( FT_Library library, \
- FT_ServiceDescRec* clazz ) \
- { \
- FT_Memory memory = library->memory; \
- \
- \
- if ( clazz ) \
- FT_FREE( clazz ); \
- } \
- \
- FT_Error \
- FT_Create_Class_ ## class_( FT_Library library, \
- FT_ServiceDescRec** output_class ) \
- { \
- FT_ServiceDescRec* clazz = NULL; \
- FT_Error error; \
- FT_Memory memory = library->memory; \
- \
- \
- if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 8 ) ) \
- return error; \
- \
- clazz[0].serv_id = serv_id_1; \
- clazz[0].serv_data = serv_data_1; \
- clazz[1].serv_id = serv_id_2; \
- clazz[1].serv_data = serv_data_2; \
- clazz[2].serv_id = serv_id_3; \
- clazz[2].serv_data = serv_data_3; \
- clazz[3].serv_id = serv_id_4; \
- clazz[3].serv_data = serv_data_4; \
- clazz[4].serv_id = serv_id_5; \
- clazz[4].serv_data = serv_data_5; \
- clazz[5].serv_id = serv_id_6; \
- clazz[5].serv_data = serv_data_6; \
- clazz[6].serv_id = serv_id_7; \
- clazz[6].serv_data = serv_data_7; \
- clazz[7].serv_id = NULL; \
- clazz[7].serv_data = NULL; \
- \
- *output_class = clazz; \
- \
- return FT_Err_Ok; \
- }
-
-#define FT_DEFINE_SERVICEDESCREC8( class_, \
- serv_id_1, serv_data_1, \
- serv_id_2, serv_data_2, \
- serv_id_3, serv_data_3, \
- serv_id_4, serv_data_4, \
- serv_id_5, serv_data_5, \
- serv_id_6, serv_data_6, \
- serv_id_7, serv_data_7, \
- serv_id_8, serv_data_8 ) \
- void \
- FT_Destroy_Class_ ## class_( FT_Library library, \
- FT_ServiceDescRec* clazz ) \
- { \
- FT_Memory memory = library->memory; \
- \
- \
- if ( clazz ) \
- FT_FREE( clazz ); \
- } \
- \
- FT_Error \
- FT_Create_Class_ ## class_( FT_Library library, \
- FT_ServiceDescRec** output_class ) \
- { \
- FT_ServiceDescRec* clazz = NULL; \
- FT_Error error; \
- FT_Memory memory = library->memory; \
- \
- \
- if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 9 ) ) \
- return error; \
- \
- clazz[0].serv_id = serv_id_1; \
- clazz[0].serv_data = serv_data_1; \
- clazz[1].serv_id = serv_id_2; \
- clazz[1].serv_data = serv_data_2; \
- clazz[2].serv_id = serv_id_3; \
- clazz[2].serv_data = serv_data_3; \
- clazz[3].serv_id = serv_id_4; \
- clazz[3].serv_data = serv_data_4; \
- clazz[4].serv_id = serv_id_5; \
- clazz[4].serv_data = serv_data_5; \
- clazz[5].serv_id = serv_id_6; \
- clazz[5].serv_data = serv_data_6; \
- clazz[6].serv_id = serv_id_7; \
- clazz[6].serv_data = serv_data_7; \
- clazz[7].serv_id = serv_id_8; \
- clazz[7].serv_data = serv_data_8; \
- clazz[8].serv_id = NULL; \
- clazz[8].serv_data = NULL; \
- \
- *output_class = clazz; \
- \
- return FT_Err_Ok; \
- }
-
-#define FT_DEFINE_SERVICEDESCREC9( class_, \
- serv_id_1, serv_data_1, \
- serv_id_2, serv_data_2, \
- serv_id_3, serv_data_3, \
- serv_id_4, serv_data_4, \
- serv_id_5, serv_data_5, \
- serv_id_6, serv_data_6, \
- serv_id_7, serv_data_7, \
- serv_id_8, serv_data_8, \
- serv_id_9, serv_data_9 ) \
- void \
- FT_Destroy_Class_ ## class_( FT_Library library, \
- FT_ServiceDescRec* clazz ) \
- { \
- FT_Memory memory = library->memory; \
- \
- \
- if ( clazz ) \
- FT_FREE( clazz ); \
- } \
- \
- FT_Error \
- FT_Create_Class_ ## class_( FT_Library library, \
- FT_ServiceDescRec** output_class ) \
- { \
- FT_ServiceDescRec* clazz = NULL; \
- FT_Error error; \
- FT_Memory memory = library->memory; \
- \
- \
- if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 10 ) ) \
- return error; \
- \
- clazz[0].serv_id = serv_id_1; \
- clazz[0].serv_data = serv_data_1; \
- clazz[1].serv_id = serv_id_2; \
- clazz[1].serv_data = serv_data_2; \
- clazz[2].serv_id = serv_id_3; \
- clazz[2].serv_data = serv_data_3; \
- clazz[3].serv_id = serv_id_4; \
- clazz[3].serv_data = serv_data_4; \
- clazz[4].serv_id = serv_id_5; \
- clazz[4].serv_data = serv_data_5; \
- clazz[5].serv_id = serv_id_6; \
- clazz[5].serv_data = serv_data_6; \
- clazz[6].serv_id = serv_id_7; \
- clazz[6].serv_data = serv_data_7; \
- clazz[7].serv_id = serv_id_8; \
- clazz[7].serv_data = serv_data_8; \
- clazz[8].serv_id = serv_id_9; \
- clazz[8].serv_data = serv_data_9; \
- clazz[9].serv_id = NULL; \
- clazz[9].serv_data = NULL; \
- \
- *output_class = clazz; \
- \
- return FT_Err_Ok; \
- }
-
-#define FT_DEFINE_SERVICEDESCREC10( class_, \
- serv_id_1, serv_data_1, \
- serv_id_2, serv_data_2, \
- serv_id_3, serv_data_3, \
- serv_id_4, serv_data_4, \
- serv_id_5, serv_data_5, \
- serv_id_6, serv_data_6, \
- serv_id_7, serv_data_7, \
- serv_id_8, serv_data_8, \
- serv_id_9, serv_data_9, \
- serv_id_10, serv_data_10 ) \
- void \
- FT_Destroy_Class_ ## class_( FT_Library library, \
- FT_ServiceDescRec* clazz ) \
- { \
- FT_Memory memory = library->memory; \
- \
- \
- if ( clazz ) \
- FT_FREE( clazz ); \
- } \
- \
- FT_Error \
- FT_Create_Class_ ## class_( FT_Library library, \
- FT_ServiceDescRec** output_class ) \
- { \
- FT_ServiceDescRec* clazz = NULL; \
- FT_Error error; \
- FT_Memory memory = library->memory; \
- \
- \
- if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 11 ) ) \
- return error; \
- \
- clazz[ 0].serv_id = serv_id_1; \
- clazz[ 0].serv_data = serv_data_1; \
- clazz[ 1].serv_id = serv_id_2; \
- clazz[ 1].serv_data = serv_data_2; \
- clazz[ 2].serv_id = serv_id_3; \
- clazz[ 2].serv_data = serv_data_3; \
- clazz[ 3].serv_id = serv_id_4; \
- clazz[ 3].serv_data = serv_data_4; \
- clazz[ 4].serv_id = serv_id_5; \
- clazz[ 4].serv_data = serv_data_5; \
- clazz[ 5].serv_id = serv_id_6; \
- clazz[ 5].serv_data = serv_data_6; \
- clazz[ 6].serv_id = serv_id_7; \
- clazz[ 6].serv_data = serv_data_7; \
- clazz[ 7].serv_id = serv_id_8; \
- clazz[ 7].serv_data = serv_data_8; \
- clazz[ 8].serv_id = serv_id_9; \
- clazz[ 8].serv_data = serv_data_9; \
- clazz[ 9].serv_id = serv_id_10; \
- clazz[ 9].serv_data = serv_data_10; \
- clazz[10].serv_id = NULL; \
- clazz[10].serv_data = NULL; \
- \
- *output_class = clazz; \
- \
- return FT_Err_Ok; \
- }
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
/*
- * Parse a list of FT_ServiceDescRec descriptors and look for
- * a specific service by ID. Note that the last element in the
- * array must be { NULL, NULL }, and that the function should
- * return NULL if the service isn't available.
+ * Parse a list of FT_ServiceDescRec descriptors and look for a specific
+ * service by ID. Note that the last element in the array must be { NULL,
+ * NULL }, and that the function should return NULL if the service isn't
+ * available.
*
- * This function can be used by modules to implement their
- * `get_service' method.
+ * This function can be used by modules to implement their `get_service'
+ * method.
*/
FT_BASE( FT_Pointer )
ft_service_list_lookup( FT_ServiceDesc service_descriptors,
@@ -869,16 +373,16 @@ FT_BEGIN_HEADER
/*************************************************************************/
/*
- * This structure is used to store a cache for several frequently used
- * services. It is the type of `face->internal->services'. You
- * should only use FT_FACE_LOOKUP_SERVICE to access it.
+ * This structure is used to store a cache for several frequently used
+ * services. It is the type of `face->internal->services'. You should
+ * only use FT_FACE_LOOKUP_SERVICE to access it.
*
- * All fields should have the type FT_Pointer to relax compilation
- * dependencies. We assume the developer isn't completely stupid.
+ * All fields should have the type FT_Pointer to relax compilation
+ * dependencies. We assume the developer isn't completely stupid.
*
- * Each field must be named `service_XXXX' where `XXX' corresponds to
- * the correct FT_SERVICE_ID_XXXX macro. See the definition of
- * FT_FACE_LOOKUP_SERVICE below how this is implemented.
+ * Each field must be named `service_XXXX' where `XXX' corresponds to the
+ * correct FT_SERVICE_ID_XXXX macro. See the definition of
+ * FT_FACE_LOOKUP_SERVICE below how this is implemented.
*
*/
typedef struct FT_ServiceCacheRec_
@@ -894,14 +398,15 @@ FT_BEGIN_HEADER
/*
- * A magic number used within the services cache.
+ * A magic number used within the services cache.
*/
/* ensure that value `1' has the same width as a pointer */
#define FT_SERVICE_UNAVAILABLE ((FT_Pointer)~(FT_PtrDist)1)
- /*
+ /**************************************************************************
+ *
* @macro:
* FT_FACE_LOOKUP_SERVICE
*
@@ -910,7 +415,7 @@ FT_BEGIN_HEADER
* using its cache.
*
* @input:
- * face::
+ * face ::
* The source face handle containing the cache.
*
* field ::
@@ -921,7 +426,7 @@ FT_BEGIN_HEADER
*
* @output:
* ptr ::
- * A variable receiving the service data. NULL if not available.
+ * A variable receiving the service data. `NULL` if not available.
*/
#ifdef __cplusplus
@@ -969,7 +474,7 @@ FT_BEGIN_HEADER
#endif /* !C++ */
/*
- * A macro used to define new service structure types.
+ * A macro used to define new service structure types.
*/
#define FT_DEFINE_SERVICE( name ) \
@@ -982,7 +487,7 @@ FT_BEGIN_HEADER
/* */
/*
- * The header files containing the services.
+ * The header files containing the services.
*/
#define FT_SERVICE_BDF_H <freetype/internal/services/svbdf.h>
diff --git a/thirdparty/freetype/include/freetype/internal/ftstream.h b/thirdparty/freetype/include/freetype/internal/ftstream.h
index f90002fe77..e4dca0b0a5 100644
--- a/thirdparty/freetype/include/freetype/internal/ftstream.h
+++ b/thirdparty/freetype/include/freetype/internal/ftstream.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftstream.h */
-/* */
-/* Stream handling (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftstream.h
+ *
+ * Stream handling (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTSTREAM_H_
@@ -96,13 +96,13 @@ FT_BEGIN_HEADER
/* The structure type must be set in the FT_STRUCTURE macro before */
/* calling the FT_FRAME_START() macro. */
/* */
-#define FT_FIELD_SIZE( f ) \
+#define FT_FIELD_SIZE( f ) \
(FT_Byte)sizeof ( ((FT_STRUCTURE*)0)->f )
-#define FT_FIELD_SIZE_DELTA( f ) \
+#define FT_FIELD_SIZE_DELTA( f ) \
(FT_Byte)sizeof ( ((FT_STRUCTURE*)0)->f[0] )
-#define FT_FIELD_OFFSET( f ) \
+#define FT_FIELD_OFFSET( f ) \
(FT_UShort)( offsetof( FT_STRUCTURE, f ) )
#define FT_FRAME_FIELD( frame_op, field ) \
@@ -147,11 +147,11 @@ FT_BEGIN_HEADER
#define FT_FRAME_SKIP_BYTES( count ) { ft_frame_skip, count, 0 }
- /*************************************************************************/
- /* */
- /* Integer extraction macros -- the `buffer' parameter must ALWAYS be of */
- /* type `char*' or equivalent (1-byte elements). */
- /* */
+ /**************************************************************************
+ *
+ * Integer extraction macros -- the 'buffer' parameter must ALWAYS be of
+ * type 'char*' or equivalent (1-byte elements).
+ */
#define FT_BYTE_( p, i ) ( ((const FT_Byte*)(p))[(i)] )
@@ -165,6 +165,10 @@ FT_BEGIN_HEADER
#define FT_BYTE_U32( p, i, s ) ( FT_UINT32( FT_BYTE_( p, i ) ) << (s) )
+ /*
+ * `FT_PEEK_XXX' are generic macros to get data from a buffer position. No
+ * safety checks are performed.
+ */
#define FT_PEEK_SHORT( p ) FT_INT16( FT_BYTE_U16( p, 0, 8 ) | \
FT_BYTE_U16( p, 1, 0 ) )
@@ -213,7 +217,10 @@ FT_BEGIN_HEADER
FT_BYTE_U32( p, 1, 8 ) | \
FT_BYTE_U32( p, 0, 0 ) )
-
+ /*
+ * `FT_NEXT_XXX' are generic macros to get data from a buffer position
+ * which is then increased appropriately. No safety checks are performed.
+ */
#define FT_NEXT_CHAR( buffer ) \
( (signed char)*buffer++ )
@@ -258,10 +265,14 @@ FT_BEGIN_HEADER
( (unsigned long)( buffer += 4, FT_PEEK_ULONG_LE( buffer - 4 ) ) )
- /*************************************************************************/
- /* */
- /* Each GET_xxxx() macro uses an implicit `stream' variable. */
- /* */
+ /**************************************************************************
+ *
+ * The `FT_GET_XXX` macros use an implicit 'stream' variable.
+ *
+ * Note that a call to `FT_STREAM_SEEK` or `FT_STREAM_POS` has **no**
+ * effect on `FT_GET_XXX`! They operate on `stream->pos`, while
+ * `FT_GET_XXX` use `stream->cursor`.
+ */
#if 0
#define FT_GET_MACRO( type ) FT_NEXT_ ## type ( stream->cursor )
@@ -299,10 +310,18 @@ FT_BEGIN_HEADER
#define FT_GET_ULONG_LE() FT_GET_MACRO( FT_Stream_GetULongLE, FT_ULong )
#endif
+
#define FT_READ_MACRO( func, type, var ) \
( var = (type)func( stream, &error ), \
error != FT_Err_Ok )
+ /*
+ * The `FT_READ_XXX' macros use implicit `stream' and `error' variables.
+ *
+ * `FT_READ_XXX' can be controlled with `FT_STREAM_SEEK' and
+ * `FT_STREAM_POS'. They use the full machinery to check whether a read is
+ * valid.
+ */
#define FT_READ_BYTE( var ) FT_READ_MACRO( FT_Stream_ReadChar, FT_Byte, var )
#define FT_READ_CHAR( var ) FT_READ_MACRO( FT_Stream_ReadChar, FT_Char, var )
#define FT_READ_SHORT( var ) FT_READ_MACRO( FT_Stream_ReadUShort, FT_Short, var )
@@ -387,12 +406,14 @@ FT_BEGIN_HEADER
/* Enter a frame of `count' consecutive bytes in a stream. Returns an */
/* error if the frame could not be read/accessed. The caller can use */
- /* the FT_Stream_Get_XXX functions to retrieve frame data without */
+ /* the `FT_Stream_GetXXX' functions to retrieve frame data without */
/* error checks. */
/* */
- /* You must _always_ call FT_Stream_ExitFrame() once you have entered */
+ /* You must _always_ call `FT_Stream_ExitFrame' once you have entered */
/* a stream frame! */
/* */
+ /* Nested frames are not permitted. */
+ /* */
FT_BASE( FT_Error )
FT_Stream_EnterFrame( FT_Stream stream,
FT_ULong count );
@@ -401,25 +422,29 @@ FT_BEGIN_HEADER
FT_BASE( void )
FT_Stream_ExitFrame( FT_Stream stream );
+
/* Extract a stream frame. If the stream is disk-based, a heap block */
/* is allocated and the frame bytes are read into it. If the stream */
- /* is memory-based, this function simply set a pointer to the data. */
+ /* is memory-based, this function simply sets a pointer to the data. */
/* */
/* Useful to optimize access to memory-based streams transparently. */
/* */
- /* All extracted frames must be `freed' with a call to the function */
- /* FT_Stream_ReleaseFrame(). */
+ /* `FT_Stream_GetXXX' functions can't be used. */
+ /* */
+ /* An extracted frame must be `freed' with a call to the function */
+ /* `FT_Stream_ReleaseFrame'. */
/* */
FT_BASE( FT_Error )
FT_Stream_ExtractFrame( FT_Stream stream,
FT_ULong count,
FT_Byte** pbytes );
- /* release an extract frame (see FT_Stream_ExtractFrame) */
+ /* release an extract frame (see `FT_Stream_ExtractFrame') */
FT_BASE( void )
FT_Stream_ReleaseFrame( FT_Stream stream,
FT_Byte** pbytes );
+
/* read a byte from an entered frame */
FT_BASE( FT_Char )
FT_Stream_GetChar( FT_Stream stream );
diff --git a/thirdparty/freetype/include/freetype/internal/fttrace.h b/thirdparty/freetype/include/freetype/internal/fttrace.h
index 8092e41fd7..8089babfb6 100644
--- a/thirdparty/freetype/include/freetype/internal/fttrace.h
+++ b/thirdparty/freetype/include/freetype/internal/fttrace.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* fttrace.h */
-/* */
-/* Tracing handling (specification only). */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * fttrace.h
+ *
+ * Tracing handling (specification only).
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
/* definitions of trace levels for FreeType 2 */
@@ -23,23 +23,24 @@ FT_TRACE_DEF( any )
/* base components */
FT_TRACE_DEF( calc ) /* calculations (ftcalc.c) */
+FT_TRACE_DEF( gloader ) /* glyph loader (ftgloadr.c) */
+FT_TRACE_DEF( glyph ) /* glyph management (ftglyph.c) */
FT_TRACE_DEF( memory ) /* memory manager (ftobjs.c) */
-FT_TRACE_DEF( stream ) /* stream manager (ftstream.c) */
+FT_TRACE_DEF( init ) /* initialization (ftinit.c) */
FT_TRACE_DEF( io ) /* i/o interface (ftsystem.c) */
FT_TRACE_DEF( list ) /* list management (ftlist.c) */
-FT_TRACE_DEF( init ) /* initialization (ftinit.c) */
FT_TRACE_DEF( objs ) /* base objects (ftobjs.c) */
FT_TRACE_DEF( outline ) /* outline management (ftoutln.c) */
-FT_TRACE_DEF( glyph ) /* glyph management (ftglyph.c) */
-FT_TRACE_DEF( gloader ) /* glyph loader (ftgloadr.c) */
+FT_TRACE_DEF( stream ) /* stream manager (ftstream.c) */
-FT_TRACE_DEF( raster ) /* monochrome rasterizer (ftraster.c) */
-FT_TRACE_DEF( smooth ) /* anti-aliasing raster (ftgrays.c) */
+FT_TRACE_DEF( bitmap ) /* bitmap manipulation (ftbitmap.c) */
+FT_TRACE_DEF( checksum ) /* bitmap checksum (ftobjs.c) */
FT_TRACE_DEF( mm ) /* MM interface (ftmm.c) */
+FT_TRACE_DEF( psprops ) /* PS driver properties (ftpsprop.c) */
FT_TRACE_DEF( raccess ) /* resource fork accessor (ftrfork.c) */
+FT_TRACE_DEF( raster ) /* monochrome rasterizer (ftraster.c) */
+FT_TRACE_DEF( smooth ) /* anti-aliasing raster (ftgrays.c) */
FT_TRACE_DEF( synth ) /* bold/slant synthesizer (ftsynth.c) */
-FT_TRACE_DEF( bitmap ) /* bitmap checksum (ftobjs.c) */
-FT_TRACE_DEF( psprops ) /* PS driver properties (ftpsprop.c) */
/* Cache sub-system */
FT_TRACE_DEF( cache ) /* cache sub-system (ftcache.c, etc.) */
@@ -47,21 +48,23 @@ FT_TRACE_DEF( cache ) /* cache sub-system (ftcache.c, etc.) */
/* SFNT driver components */
FT_TRACE_DEF( sfdriver ) /* SFNT font driver (sfdriver.c) */
FT_TRACE_DEF( sfobjs ) /* SFNT object handler (sfobjs.c) */
+FT_TRACE_DEF( ttbdf ) /* TrueType embedded BDF (ttbdf.c) */
FT_TRACE_DEF( ttcmap ) /* charmap handler (ttcmap.c) */
+FT_TRACE_DEF( ttcolr ) /* glyph layer table (ttcolr.c) */
+FT_TRACE_DEF( ttcpal ) /* color palette table (ttcpal.c) */
FT_TRACE_DEF( ttkern ) /* kerning handler (ttkern.c) */
FT_TRACE_DEF( ttload ) /* basic TrueType tables (ttload.c) */
FT_TRACE_DEF( ttmtx ) /* metrics-related tables (ttmtx.c) */
FT_TRACE_DEF( ttpost ) /* PS table processing (ttpost.c) */
FT_TRACE_DEF( ttsbit ) /* TrueType sbit handling (ttsbit.c) */
-FT_TRACE_DEF( ttbdf ) /* TrueType embedded BDF (ttbdf.c) */
/* TrueType driver components */
FT_TRACE_DEF( ttdriver ) /* TT font driver (ttdriver.c) */
FT_TRACE_DEF( ttgload ) /* TT glyph loader (ttgload.c) */
+FT_TRACE_DEF( ttgxvar ) /* TrueType GX var handler (ttgxvar.c) */
FT_TRACE_DEF( ttinterp ) /* bytecode interpreter (ttinterp.c) */
FT_TRACE_DEF( ttobjs ) /* TT objects manager (ttobjs.c) */
FT_TRACE_DEF( ttpload ) /* TT data/program loader (ttpload.c) */
-FT_TRACE_DEF( ttgxvar ) /* TrueType GX var handler (ttgxvar.c) */
/* Type 1 driver components */
FT_TRACE_DEF( t1afm )
@@ -72,14 +75,14 @@ FT_TRACE_DEF( t1objs )
FT_TRACE_DEF( t1parse )
/* PostScript helper module `psaux' */
-FT_TRACE_DEF( t1decode )
FT_TRACE_DEF( cffdecode )
-FT_TRACE_DEF( psobjs )
FT_TRACE_DEF( psconv )
+FT_TRACE_DEF( psobjs )
+FT_TRACE_DEF( t1decode )
/* PostScript hinting module `pshinter' */
-FT_TRACE_DEF( pshrec )
FT_TRACE_DEF( pshalgo )
+FT_TRACE_DEF( pshrec )
/* Type 2 driver components */
FT_TRACE_DEF( cffdriver )
@@ -117,7 +120,6 @@ FT_TRACE_DEF( bdflib )
FT_TRACE_DEF( pfr )
/* OpenType validation components */
-FT_TRACE_DEF( otvmodule )
FT_TRACE_DEF( otvcommon )
FT_TRACE_DEF( otvbase )
FT_TRACE_DEF( otvgdef )
@@ -125,29 +127,30 @@ FT_TRACE_DEF( otvgpos )
FT_TRACE_DEF( otvgsub )
FT_TRACE_DEF( otvjstf )
FT_TRACE_DEF( otvmath )
+FT_TRACE_DEF( otvmodule )
/* TrueTypeGX/AAT validation components */
-FT_TRACE_DEF( gxvmodule )
+FT_TRACE_DEF( gxvbsln )
FT_TRACE_DEF( gxvcommon )
FT_TRACE_DEF( gxvfeat )
-FT_TRACE_DEF( gxvmort )
-FT_TRACE_DEF( gxvmorx )
-FT_TRACE_DEF( gxvbsln )
FT_TRACE_DEF( gxvjust )
FT_TRACE_DEF( gxvkern )
+FT_TRACE_DEF( gxvmodule )
+FT_TRACE_DEF( gxvmort )
+FT_TRACE_DEF( gxvmorx )
+FT_TRACE_DEF( gxvlcar )
FT_TRACE_DEF( gxvopbd )
-FT_TRACE_DEF( gxvtrak )
FT_TRACE_DEF( gxvprop )
-FT_TRACE_DEF( gxvlcar )
+FT_TRACE_DEF( gxvtrak )
/* autofit components */
-FT_TRACE_DEF( afmodule )
-FT_TRACE_DEF( afhints )
FT_TRACE_DEF( afcjk )
+FT_TRACE_DEF( afglobal )
+FT_TRACE_DEF( afhints )
+FT_TRACE_DEF( afmodule )
FT_TRACE_DEF( aflatin )
FT_TRACE_DEF( aflatin2 )
-FT_TRACE_DEF( afwarp )
FT_TRACE_DEF( afshaper )
-FT_TRACE_DEF( afglobal )
+FT_TRACE_DEF( afwarp )
/* END */
diff --git a/thirdparty/freetype/include/freetype/internal/ftvalid.h b/thirdparty/freetype/include/freetype/internal/ftvalid.h
index cad47a556d..38aa06cc4e 100644
--- a/thirdparty/freetype/include/freetype/internal/ftvalid.h
+++ b/thirdparty/freetype/include/freetype/internal/ftvalid.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftvalid.h */
-/* */
-/* FreeType validation support (specification). */
-/* */
-/* Copyright 2004-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftvalid.h
+ *
+ * FreeType validation support (specification).
+ *
+ * Copyright (C) 2004-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTVALID_H_
@@ -42,31 +42,31 @@ FT_BEGIN_HEADER
typedef struct FT_ValidatorRec_ volatile* FT_Validator;
- /*************************************************************************/
- /* */
- /* There are three distinct validation levels defined here: */
- /* */
- /* FT_VALIDATE_DEFAULT :: */
- /* A table that passes this validation level can be used reliably by */
- /* FreeType. It generally means that all offsets have been checked to */
- /* prevent out-of-bound reads, that array counts are correct, etc. */
- /* */
- /* FT_VALIDATE_TIGHT :: */
- /* A table that passes this validation level can be used reliably and */
- /* doesn't contain invalid data. For example, a charmap table that */
- /* returns invalid glyph indices will not pass, even though it can */
- /* be used with FreeType in default mode (the library will simply */
- /* return an error later when trying to load the glyph). */
- /* */
- /* It also checks that fields which must be a multiple of 2, 4, or 8, */
- /* don't have incorrect values, etc. */
- /* */
- /* FT_VALIDATE_PARANOID :: */
- /* Only for font debugging. Checks that a table follows the */
- /* specification by 100%. Very few fonts will be able to pass this */
- /* level anyway but it can be useful for certain tools like font */
- /* editors/converters. */
- /* */
+ /**************************************************************************
+ *
+ * There are three distinct validation levels defined here:
+ *
+ * FT_VALIDATE_DEFAULT ::
+ * A table that passes this validation level can be used reliably by
+ * FreeType. It generally means that all offsets have been checked to
+ * prevent out-of-bound reads, that array counts are correct, etc.
+ *
+ * FT_VALIDATE_TIGHT ::
+ * A table that passes this validation level can be used reliably and
+ * doesn't contain invalid data. For example, a charmap table that
+ * returns invalid glyph indices will not pass, even though it can be
+ * used with FreeType in default mode (the library will simply return an
+ * error later when trying to load the glyph).
+ *
+ * It also checks that fields which must be a multiple of 2, 4, or 8,
+ * don't have incorrect values, etc.
+ *
+ * FT_VALIDATE_PARANOID ::
+ * Only for font debugging. Checks that a table follows the
+ * specification by 100%. Very few fonts will be able to pass this level
+ * anyway but it can be useful for certain tools like font
+ * editors/converters.
+ */
typedef enum FT_ValidationLevel_
{
FT_VALIDATE_DEFAULT = 0,
diff --git a/thirdparty/freetype/include/freetype/internal/internal.h b/thirdparty/freetype/include/freetype/internal/internal.h
index 8f546e443b..173d8ad906 100644
--- a/thirdparty/freetype/include/freetype/internal/internal.h
+++ b/thirdparty/freetype/include/freetype/internal/internal.h
@@ -1,31 +1,30 @@
-/***************************************************************************/
-/* */
-/* internal.h */
-/* */
-/* Internal header files (specification only). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * internal.h
+ *
+ * Internal header files (specification only).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
- /*************************************************************************/
- /* */
- /* This file is automatically included by `ft2build.h'. */
- /* Do not include it manually! */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * This file is automatically included by `ft2build.h`. Do not include it
+ * manually!
+ *
+ */
#define FT_INTERNAL_OBJECTS_H <freetype/internal/ftobjs.h>
-#define FT_INTERNAL_PIC_H <freetype/internal/ftpic.h>
#define FT_INTERNAL_STREAM_H <freetype/internal/ftstream.h>
#define FT_INTERNAL_MEMORY_H <freetype/internal/ftmemory.h>
#define FT_INTERNAL_DEBUG_H <freetype/internal/ftdebug.h>
diff --git a/thirdparty/freetype/include/freetype/internal/psaux.h b/thirdparty/freetype/include/freetype/internal/psaux.h
index f77380d25f..3ab01c3e68 100644
--- a/thirdparty/freetype/include/freetype/internal/psaux.h
+++ b/thirdparty/freetype/include/freetype/internal/psaux.h
@@ -1,20 +1,20 @@
-/***************************************************************************/
-/* */
-/* psaux.h */
-/* */
-/* Auxiliary functions and data structures related to PostScript fonts */
-/* (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * psaux.h
+ *
+ * Auxiliary functions and data structures related to PostScript fonts
+ * (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef PSAUX_H_
@@ -35,10 +35,10 @@
FT_BEGIN_HEADER
- /***********************************************************************/
- /* */
- /* PostScript modules driver class. */
- /* */
+ /**************************************************************************
+ *
+ * PostScript modules driver class.
+ */
typedef struct PS_DriverRec_
{
FT_DriverRec root;
@@ -64,23 +64,27 @@ FT_BEGIN_HEADER
typedef const struct PS_Table_FuncsRec_* PS_Table_Funcs;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* PS_Table_FuncsRec */
- /* */
- /* <Description> */
- /* A set of function pointers to manage PS_Table objects. */
- /* */
- /* <Fields> */
- /* table_init :: Used to initialize a table. */
- /* */
- /* table_done :: Finalizes resp. destroy a given table. */
- /* */
- /* table_add :: Adds a new object to a table. */
- /* */
- /* table_release :: Releases table data, then finalizes it. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * PS_Table_FuncsRec
+ *
+ * @description:
+ * A set of function pointers to manage PS_Table objects.
+ *
+ * @fields:
+ * table_init ::
+ * Used to initialize a table.
+ *
+ * table_done ::
+ * Finalizes resp. destroy a given table.
+ *
+ * table_add ::
+ * Adds a new object to a table.
+ *
+ * table_release ::
+ * Releases table data, then finalizes it.
+ */
typedef struct PS_Table_FuncsRec_
{
FT_Error
@@ -103,41 +107,47 @@ FT_BEGIN_HEADER
} PS_Table_FuncsRec;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* PS_TableRec */
- /* */
- /* <Description> */
- /* A PS_Table is a simple object used to store an array of objects in */
- /* a single memory block. */
- /* */
- /* <Fields> */
- /* block :: The address in memory of the growheap's block. This */
- /* can change between two object adds, due to */
- /* reallocation. */
- /* */
- /* cursor :: The current top of the grow heap within its block. */
- /* */
- /* capacity :: The current size of the heap block. Increments by */
- /* 1kByte chunks. */
- /* */
- /* init :: Set to 0xDEADBEEF if `elements' and `lengths' have */
- /* been allocated. */
- /* */
- /* max_elems :: The maximum number of elements in table. */
- /* */
- /* num_elems :: The current number of elements in table. */
- /* */
- /* elements :: A table of element addresses within the block. */
- /* */
- /* lengths :: A table of element sizes within the block. */
- /* */
- /* memory :: The object used for memory operations */
- /* (alloc/realloc). */
- /* */
- /* funcs :: A table of method pointers for this object. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * PS_TableRec
+ *
+ * @description:
+ * A PS_Table is a simple object used to store an array of objects in a
+ * single memory block.
+ *
+ * @fields:
+ * block ::
+ * The address in memory of the growheap's block. This can change
+ * between two object adds, due to reallocation.
+ *
+ * cursor ::
+ * The current top of the grow heap within its block.
+ *
+ * capacity ::
+ * The current size of the heap block. Increments by 1kByte chunks.
+ *
+ * init ::
+ * Set to 0xDEADBEEF if 'elements' and 'lengths' have been allocated.
+ *
+ * max_elems ::
+ * The maximum number of elements in table.
+ *
+ * num_elems ::
+ * The current number of elements in table.
+ *
+ * elements ::
+ * A table of element addresses within the block.
+ *
+ * lengths ::
+ * A table of element sizes within the block.
+ *
+ * memory ::
+ * The object used for memory operations (alloc/realloc).
+ *
+ * funcs ::
+ * A table of method pointers for this object.
+ */
typedef struct PS_TableRec_
{
FT_Byte* block; /* current memory block */
@@ -425,27 +435,33 @@ FT_BEGIN_HEADER
} PS_Parser_FuncsRec;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* PS_ParserRec */
- /* */
- /* <Description> */
- /* A PS_Parser is an object used to parse a Type 1 font very quickly. */
- /* */
- /* <Fields> */
- /* cursor :: The current position in the text. */
- /* */
- /* base :: Start of the processed text. */
- /* */
- /* limit :: End of the processed text. */
- /* */
- /* error :: The last error returned. */
- /* */
- /* memory :: The object used for memory operations (alloc/realloc). */
- /* */
- /* funcs :: A table of functions for the parser. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * PS_ParserRec
+ *
+ * @description:
+ * A PS_Parser is an object used to parse a Type 1 font very quickly.
+ *
+ * @fields:
+ * cursor ::
+ * The current position in the text.
+ *
+ * base ::
+ * Start of the processed text.
+ *
+ * limit ::
+ * End of the processed text.
+ *
+ * error ::
+ * The last error returned.
+ *
+ * memory ::
+ * The object used for memory operations (alloc/realloc).
+ *
+ * funcs ::
+ * A table of functions for the parser.
+ */
typedef struct PS_ParserRec_
{
FT_Byte* cursor;
@@ -484,51 +500,67 @@ FT_BEGIN_HEADER
} PS_Builder_FuncsRec;
- /*************************************************************************/
- /* */
- /* <Structure> */
- /* PS_Builder */
- /* */
- /* <Description> */
- /* A structure used during glyph loading to store its outline. */
- /* */
- /* <Fields> */
- /* memory :: The current memory object. */
- /* */
- /* face :: The current face object. */
- /* */
- /* glyph :: The current glyph slot. */
- /* */
- /* loader :: XXX */
- /* */
- /* base :: The base glyph outline. */
- /* */
- /* current :: The current glyph outline. */
- /* */
- /* pos_x :: The horizontal translation (if composite glyph). */
- /* */
- /* pos_y :: The vertical translation (if composite glyph). */
- /* */
- /* left_bearing :: The left side bearing point. */
- /* */
- /* advance :: The horizontal advance vector. */
- /* */
- /* bbox :: Unused. */
- /* */
- /* path_begun :: A flag which indicates that a new path has begun. */
- /* */
- /* load_points :: If this flag is not set, no points are loaded. */
- /* */
- /* no_recurse :: Set but not used. */
- /* */
- /* metrics_only :: A boolean indicating that we only want to compute */
- /* the metrics of a given glyph, not load all of its */
- /* points. */
- /* */
- /* is_t1 :: Set if current font type is Type 1. */
- /* */
- /* funcs :: An array of function pointers for the builder. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * PS_Builder
+ *
+ * @description:
+ * A structure used during glyph loading to store its outline.
+ *
+ * @fields:
+ * memory ::
+ * The current memory object.
+ *
+ * face ::
+ * The current face object.
+ *
+ * glyph ::
+ * The current glyph slot.
+ *
+ * loader ::
+ * XXX
+ *
+ * base ::
+ * The base glyph outline.
+ *
+ * current ::
+ * The current glyph outline.
+ *
+ * pos_x ::
+ * The horizontal translation (if composite glyph).
+ *
+ * pos_y ::
+ * The vertical translation (if composite glyph).
+ *
+ * left_bearing ::
+ * The left side bearing point.
+ *
+ * advance ::
+ * The horizontal advance vector.
+ *
+ * bbox ::
+ * Unused.
+ *
+ * path_begun ::
+ * A flag which indicates that a new path has begun.
+ *
+ * load_points ::
+ * If this flag is not set, no points are loaded.
+ *
+ * no_recurse ::
+ * Set but not used.
+ *
+ * metrics_only ::
+ * A boolean indicating that we only want to compute the metrics of a
+ * given glyph, not load all of its points.
+ *
+ * is_t1 ::
+ * Set if current font type is Type 1.
+ *
+ * funcs ::
+ * An array of function pointers for the builder.
+ */
struct PS_Builder_
{
FT_Memory memory;
@@ -729,54 +761,70 @@ FT_BEGIN_HEADER
} T1_ParseState;
- /*************************************************************************/
- /* */
- /* <Structure> */
- /* T1_BuilderRec */
- /* */
- /* <Description> */
- /* A structure used during glyph loading to store its outline. */
- /* */
- /* <Fields> */
- /* memory :: The current memory object. */
- /* */
- /* face :: The current face object. */
- /* */
- /* glyph :: The current glyph slot. */
- /* */
- /* loader :: XXX */
- /* */
- /* base :: The base glyph outline. */
- /* */
- /* current :: The current glyph outline. */
- /* */
- /* max_points :: maximum points in builder outline */
- /* */
- /* max_contours :: Maximum number of contours in builder outline. */
- /* */
- /* pos_x :: The horizontal translation (if composite glyph). */
- /* */
- /* pos_y :: The vertical translation (if composite glyph). */
- /* */
- /* left_bearing :: The left side bearing point. */
- /* */
- /* advance :: The horizontal advance vector. */
- /* */
- /* bbox :: Unused. */
- /* */
- /* parse_state :: An enumeration which controls the charstring */
- /* parsing state. */
- /* */
- /* load_points :: If this flag is not set, no points are loaded. */
- /* */
- /* no_recurse :: Set but not used. */
- /* */
- /* metrics_only :: A boolean indicating that we only want to compute */
- /* the metrics of a given glyph, not load all of its */
- /* points. */
- /* */
- /* funcs :: An array of function pointers for the builder. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * T1_BuilderRec
+ *
+ * @description:
+ * A structure used during glyph loading to store its outline.
+ *
+ * @fields:
+ * memory ::
+ * The current memory object.
+ *
+ * face ::
+ * The current face object.
+ *
+ * glyph ::
+ * The current glyph slot.
+ *
+ * loader ::
+ * XXX
+ *
+ * base ::
+ * The base glyph outline.
+ *
+ * current ::
+ * The current glyph outline.
+ *
+ * max_points ::
+ * maximum points in builder outline
+ *
+ * max_contours ::
+ * Maximum number of contours in builder outline.
+ *
+ * pos_x ::
+ * The horizontal translation (if composite glyph).
+ *
+ * pos_y ::
+ * The vertical translation (if composite glyph).
+ *
+ * left_bearing ::
+ * The left side bearing point.
+ *
+ * advance ::
+ * The horizontal advance vector.
+ *
+ * bbox ::
+ * Unused.
+ *
+ * parse_state ::
+ * An enumeration which controls the charstring parsing state.
+ *
+ * load_points ::
+ * If this flag is not set, no points are loaded.
+ *
+ * no_recurse ::
+ * Set but not used.
+ *
+ * metrics_only ::
+ * A boolean indicating that we only want to compute the metrics of a
+ * given glyph, not load all of its points.
+ *
+ * funcs ::
+ * An array of function pointers for the builder.
+ */
typedef struct T1_BuilderRec_
{
FT_Memory memory;
@@ -817,19 +865,19 @@ FT_BEGIN_HEADER
#if 0
- /*************************************************************************/
- /* */
- /* T1_MAX_SUBRS_CALLS details the maximum number of nested sub-routine */
- /* calls during glyph loading. */
- /* */
+ /**************************************************************************
+ *
+ * T1_MAX_SUBRS_CALLS details the maximum number of nested sub-routine
+ * calls during glyph loading.
+ */
#define T1_MAX_SUBRS_CALLS 8
- /*************************************************************************/
- /* */
- /* T1_MAX_CHARSTRING_OPERANDS is the charstring stack's capacity. A */
- /* minimum of 16 is required. */
- /* */
+ /**************************************************************************
+ *
+ * T1_MAX_CHARSTRING_OPERANDS is the charstring stack's capacity. A
+ * minimum of 16 is required.
+ */
#define T1_MAX_CHARSTRINGS_OPERANDS 32
#endif /* 0 */
@@ -993,53 +1041,70 @@ FT_BEGIN_HEADER
} CFF_Builder_FuncsRec;
- /*************************************************************************/
- /* */
- /* <Structure> */
- /* CFF_Builder */
- /* */
- /* <Description> */
- /* A structure used during glyph loading to store its outline. */
- /* */
- /* <Fields> */
- /* memory :: The current memory object. */
- /* */
- /* face :: The current face object. */
- /* */
- /* glyph :: The current glyph slot. */
- /* */
- /* loader :: The current glyph loader. */
- /* */
- /* base :: The base glyph outline. */
- /* */
- /* current :: The current glyph outline. */
- /* */
- /* pos_x :: The horizontal translation (if composite glyph). */
- /* */
- /* pos_y :: The vertical translation (if composite glyph). */
- /* */
- /* left_bearing :: The left side bearing point. */
- /* */
- /* advance :: The horizontal advance vector. */
- /* */
- /* bbox :: Unused. */
- /* */
- /* path_begun :: A flag which indicates that a new path has begun. */
- /* */
- /* load_points :: If this flag is not set, no points are loaded. */
- /* */
- /* no_recurse :: Set but not used. */
- /* */
- /* metrics_only :: A boolean indicating that we only want to compute */
- /* the metrics of a given glyph, not load all of its */
- /* points. */
- /* */
- /* hints_funcs :: Auxiliary pointer for hinting. */
- /* */
- /* hints_globals :: Auxiliary pointer for hinting. */
- /* */
- /* funcs :: A table of method pointers for this object. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * CFF_Builder
+ *
+ * @description:
+ * A structure used during glyph loading to store its outline.
+ *
+ * @fields:
+ * memory ::
+ * The current memory object.
+ *
+ * face ::
+ * The current face object.
+ *
+ * glyph ::
+ * The current glyph slot.
+ *
+ * loader ::
+ * The current glyph loader.
+ *
+ * base ::
+ * The base glyph outline.
+ *
+ * current ::
+ * The current glyph outline.
+ *
+ * pos_x ::
+ * The horizontal translation (if composite glyph).
+ *
+ * pos_y ::
+ * The vertical translation (if composite glyph).
+ *
+ * left_bearing ::
+ * The left side bearing point.
+ *
+ * advance ::
+ * The horizontal advance vector.
+ *
+ * bbox ::
+ * Unused.
+ *
+ * path_begun ::
+ * A flag which indicates that a new path has begun.
+ *
+ * load_points ::
+ * If this flag is not set, no points are loaded.
+ *
+ * no_recurse ::
+ * Set but not used.
+ *
+ * metrics_only ::
+ * A boolean indicating that we only want to compute the metrics of a
+ * given glyph, not load all of its points.
+ *
+ * hints_funcs ::
+ * Auxiliary pointer for hinting.
+ *
+ * hints_globals ::
+ * Auxiliary pointer for hinting.
+ *
+ * funcs ::
+ * A table of method pointers for this object.
+ */
struct CFF_Builder_
{
FT_Memory memory;
@@ -1211,25 +1276,27 @@ FT_BEGIN_HEADER
typedef struct AFM_StreamRec_* AFM_Stream;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* AFM_ParserRec */
- /* */
- /* <Description> */
- /* An AFM_Parser is a parser for the AFM files. */
- /* */
- /* <Fields> */
- /* memory :: The object used for memory operations (alloc and */
- /* realloc). */
- /* */
- /* stream :: This is an opaque object. */
- /* */
- /* FontInfo :: The result will be stored here. */
- /* */
- /* get_index :: A user provided function to get a glyph index by its */
- /* name. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * AFM_ParserRec
+ *
+ * @description:
+ * An AFM_Parser is a parser for the AFM files.
+ *
+ * @fields:
+ * memory ::
+ * The object used for memory operations (alloc and realloc).
+ *
+ * stream ::
+ * This is an opaque object.
+ *
+ * FontInfo ::
+ * The result will be stored here.
+ *
+ * get_index ::
+ * A user provided function to get a glyph index by its name.
+ */
typedef struct AFM_ParserRec_
{
FT_Memory memory;
diff --git a/thirdparty/freetype/include/freetype/internal/pshints.h b/thirdparty/freetype/include/freetype/internal/pshints.h
index d29314ec2e..699acea6f5 100644
--- a/thirdparty/freetype/include/freetype/internal/pshints.h
+++ b/thirdparty/freetype/include/freetype/internal/pshints.h
@@ -1,21 +1,21 @@
-/***************************************************************************/
-/* */
-/* pshints.h */
-/* */
-/* Interface to Postscript-specific (Type 1 and Type 2) hints */
-/* recorders (specification only). These are used to support native */
-/* T1/T2 hints in the `type1', `cid', and `cff' font drivers. */
-/* */
-/* Copyright 2001-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * pshints.h
+ *
+ * Interface to Postscript-specific (Type 1 and Type 2) hints
+ * recorders (specification only). These are used to support native
+ * T1/T2 hints in the 'type1', 'cid', and 'cff' font drivers.
+ *
+ * Copyright (C) 2001-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef PSHINTS_H_
@@ -73,7 +73,7 @@ FT_BEGIN_HEADER
/*************************************************************************/
/*************************************************************************/
- /*************************************************************************
+ /**************************************************************************
*
* @type:
* T1_Hints
@@ -86,16 +86,16 @@ FT_BEGIN_HEADER
* @T1_Hints_FuncsRec structure. Recording glyph hints is normally
* achieved through the following scheme:
*
- * - Open a new hint recording session by calling the `open' method.
+ * - Open a new hint recording session by calling the 'open' method.
* This rewinds the recorder and prepare it for new input.
*
* - For each hint found in the glyph charstring, call the corresponding
- * method (`stem', `stem3', or `reset'). Note that these functions do
+ * method ('stem', 'stem3', or 'reset'). Note that these functions do
* not return an error code.
*
- * - Close the recording session by calling the `close' method. It
- * returns an error code if the hints were invalid or something
- * strange happened (e.g., memory shortage).
+ * - Close the recording session by calling the 'close' method. It
+ * returns an error code if the hints were invalid or something strange
+ * happened (e.g., memory shortage).
*
* The hints accumulated in the object can later be used by the
* PostScript hinter.
@@ -104,7 +104,7 @@ FT_BEGIN_HEADER
typedef struct T1_HintsRec_* T1_Hints;
- /*************************************************************************
+ /**************************************************************************
*
* @type:
* T1_Hints_Funcs
@@ -117,7 +117,7 @@ FT_BEGIN_HEADER
typedef const struct T1_Hints_FuncsRec_* T1_Hints_Funcs;
- /*************************************************************************
+ /**************************************************************************
*
* @functype:
* T1_Hints_OpenFunc
@@ -139,14 +139,14 @@ FT_BEGIN_HEADER
(*T1_Hints_OpenFunc)( T1_Hints hints );
- /*************************************************************************
+ /**************************************************************************
*
* @functype:
* T1_Hints_SetStemFunc
*
* @description:
* A method of the @T1_Hints class used to record a new horizontal or
- * vertical stem. This corresponds to the Type 1 `hstem' and `vstem'
+ * vertical stem. This corresponds to the Type 1 'hstem' and 'vstem'
* operators.
*
* @input:
@@ -164,15 +164,15 @@ FT_BEGIN_HEADER
* Use vertical coordinates (y) for horizontal stems (dim=0). Use
* horizontal coordinates (x) for vertical stems (dim=1).
*
- * `coords[0]' is the absolute stem position (lowest coordinate);
- * `coords[1]' is the length.
+ * 'coords[0]' is the absolute stem position (lowest coordinate);
+ * 'coords[1]' is the length.
*
* The length can be negative, in which case it must be either -20 or
- * -21. It is interpreted as a `ghost' stem, according to the Type 1
+ * -21. It is interpreted as a 'ghost' stem, according to the Type 1
* specification.
*
- * If the length is -21 (corresponding to a bottom ghost stem), then
- * the real stem position is `coords[0]+coords[1]'.
+ * If the length is -21 (corresponding to a bottom ghost stem), then the
+ * real stem position is 'coords[0]+coords[1]'.
*
*/
typedef void
@@ -181,7 +181,7 @@ FT_BEGIN_HEADER
FT_Fixed* coords );
- /*************************************************************************
+ /**************************************************************************
*
* @functype:
* T1_Hints_SetStem3Func
@@ -215,7 +215,7 @@ FT_BEGIN_HEADER
FT_Fixed* coords );
- /*************************************************************************
+ /**************************************************************************
*
* @functype:
* T1_Hints_ResetFunc
@@ -238,7 +238,7 @@ FT_BEGIN_HEADER
FT_UInt end_point );
- /*************************************************************************
+ /**************************************************************************
*
* @functype:
* T1_Hints_CloseFunc
@@ -267,7 +267,7 @@ FT_BEGIN_HEADER
FT_UInt end_point );
- /*************************************************************************
+ /**************************************************************************
*
* @functype:
* T1_Hints_ApplyFunc
@@ -297,7 +297,7 @@ FT_BEGIN_HEADER
* On input, all points within the outline are in font coordinates. On
* output, they are in 1/64th of pixels.
*
- * The scaling transformation is taken from the `globals' object which
+ * The scaling transformation is taken from the 'globals' object which
* must correspond to the same font as the glyph.
*
*/
@@ -308,7 +308,7 @@ FT_BEGIN_HEADER
FT_Render_Mode hint_mode );
- /*************************************************************************
+ /**************************************************************************
*
* @struct:
* T1_Hints_FuncsRec
@@ -360,7 +360,7 @@ FT_BEGIN_HEADER
/*************************************************************************/
/*************************************************************************/
- /*************************************************************************
+ /**************************************************************************
*
* @type:
* T2_Hints
@@ -373,16 +373,16 @@ FT_BEGIN_HEADER
* @T2_Hints_FuncsRec structure. Recording glyph hints is normally
* achieved through the following scheme:
*
- * - Open a new hint recording session by calling the `open' method.
+ * - Open a new hint recording session by calling the 'open' method.
* This rewinds the recorder and prepare it for new input.
*
* - For each hint found in the glyph charstring, call the corresponding
- * method (`stems', `hintmask', `counters'). Note that these
- * functions do not return an error code.
+ * method ('stems', 'hintmask', 'counters'). Note that these functions
+ * do not return an error code.
*
- * - Close the recording session by calling the `close' method. It
- * returns an error code if the hints were invalid or something
- * strange happened (e.g., memory shortage).
+ * - Close the recording session by calling the 'close' method. It
+ * returns an error code if the hints were invalid or something strange
+ * happened (e.g., memory shortage).
*
* The hints accumulated in the object can later be used by the
* Postscript hinter.
@@ -391,7 +391,7 @@ FT_BEGIN_HEADER
typedef struct T2_HintsRec_* T2_Hints;
- /*************************************************************************
+ /**************************************************************************
*
* @type:
* T2_Hints_Funcs
@@ -404,7 +404,7 @@ FT_BEGIN_HEADER
typedef const struct T2_Hints_FuncsRec_* T2_Hints_Funcs;
- /*************************************************************************
+ /**************************************************************************
*
* @functype:
* T2_Hints_OpenFunc
@@ -426,7 +426,7 @@ FT_BEGIN_HEADER
(*T2_Hints_OpenFunc)( T2_Hints hints );
- /*************************************************************************
+ /**************************************************************************
*
* @functype:
* T2_Hints_StemsFunc
@@ -434,7 +434,7 @@ FT_BEGIN_HEADER
* @description:
* A method of the @T2_Hints class used to set the table of stems in
* either the vertical or horizontal dimension. Equivalent to the
- * `hstem', `vstem', `hstemhm', and `vstemhm' Type 2 operators.
+ * 'hstem', 'vstem', 'hstemhm', and 'vstemhm' Type 2 operators.
*
* @input:
* hints ::
@@ -447,18 +447,18 @@ FT_BEGIN_HEADER
* The number of stems.
*
* coords ::
- * An array of `count' (position,length) pairs in 16.16 format.
+ * An array of 'count' (position,length) pairs in 16.16 format.
*
* @note:
* Use vertical coordinates (y) for horizontal stems (dim=0). Use
* horizontal coordinates (x) for vertical stems (dim=1).
*
- * There are `2*count' elements in the `coords' array. Each even
- * element is an absolute position in font units, each odd element is a
- * length in font units.
+ * There are '2*count' elements in the 'coords' array. Each even element
+ * is an absolute position in font units, each odd element is a length in
+ * font units.
*
- * A length can be negative, in which case it must be either -20 or
- * -21. It is interpreted as a `ghost' stem, according to the Type 1
+ * A length can be negative, in which case it must be either -20 or -21.
+ * It is interpreted as a 'ghost' stem, according to the Type 1
* specification.
*
*/
@@ -469,22 +469,22 @@ FT_BEGIN_HEADER
FT_Fixed* coordinates );
- /*************************************************************************
+ /**************************************************************************
*
* @functype:
* T2_Hints_MaskFunc
*
* @description:
* A method of the @T2_Hints class used to set a given hintmask (this
- * corresponds to the `hintmask' Type 2 operator).
+ * corresponds to the 'hintmask' Type 2 operator).
*
* @input:
* hints ::
* A handle to the Type 2 hints recorder.
*
* end_point ::
- * The glyph index of the last point to which the previously defined
- * or activated hints apply.
+ * The glyph index of the last point to which the previously defined or
+ * activated hints apply.
*
* bit_count ::
* The number of bits in the hint mask.
@@ -494,13 +494,13 @@ FT_BEGIN_HEADER
*
* @note:
* If the hintmask starts the charstring (before any glyph point
- * definition), the value of `end_point' should be 0.
+ * definition), the value of `end_point` should be 0.
*
- * `bit_count' is the number of meaningful bits in the `bytes' array; it
+ * `bit_count` is the number of meaningful bits in the 'bytes' array; it
* must be equal to the total number of hints defined so far (i.e.,
* horizontal+verticals).
*
- * The `bytes' array can come directly from the Type 2 charstring and
+ * The 'bytes' array can come directly from the Type 2 charstring and
* respects the same format.
*
*/
@@ -511,14 +511,14 @@ FT_BEGIN_HEADER
const FT_Byte* bytes );
- /*************************************************************************
+ /**************************************************************************
*
* @functype:
* T2_Hints_CounterFunc
*
* @description:
- * A method of the @T2_Hints class used to set a given counter mask
- * (this corresponds to the `hintmask' Type 2 operator).
+ * A method of the @T2_Hints class used to set a given counter mask (this
+ * corresponds to the 'hintmask' Type 2 operator).
*
* @input:
* hints ::
@@ -536,13 +536,13 @@ FT_BEGIN_HEADER
*
* @note:
* If the hintmask starts the charstring (before any glyph point
- * definition), the value of `end_point' should be 0.
+ * definition), the value of `end_point` should be 0.
*
- * `bit_count' is the number of meaningful bits in the `bytes' array; it
+ * `bit_count` is the number of meaningful bits in the 'bytes' array; it
* must be equal to the total number of hints defined so far (i.e.,
* horizontal+verticals).
*
- * The `bytes' array can come directly from the Type 2 charstring and
+ * The 'bytes' array can come directly from the Type 2 charstring and
* respects the same format.
*
*/
@@ -552,7 +552,7 @@ FT_BEGIN_HEADER
const FT_Byte* bytes );
- /*************************************************************************
+ /**************************************************************************
*
* @functype:
* T2_Hints_CloseFunc
@@ -581,15 +581,14 @@ FT_BEGIN_HEADER
FT_UInt end_point );
- /*************************************************************************
+ /**************************************************************************
*
* @functype:
* T2_Hints_ApplyFunc
*
* @description:
* A method of the @T2_Hints class used to apply hints to the
- * corresponding glyph outline. Must be called after the `close'
- * method.
+ * corresponding glyph outline. Must be called after the 'close' method.
*
* @input:
* hints ::
@@ -611,7 +610,7 @@ FT_BEGIN_HEADER
* On input, all points within the outline are in font coordinates. On
* output, they are in 1/64th of pixels.
*
- * The scaling transformation is taken from the `globals' object which
+ * The scaling transformation is taken from the 'globals' object which
* must correspond to the same font than the glyph.
*
*/
@@ -622,7 +621,7 @@ FT_BEGIN_HEADER
FT_Render_Mode hint_mode );
- /*************************************************************************
+ /**************************************************************************
*
* @struct:
* T2_Hints_FuncsRec
@@ -680,8 +679,6 @@ FT_BEGIN_HEADER
typedef PSHinter_Interface* PSHinter_Service;
-#ifndef FT_CONFIG_OPTION_PIC
-
#define FT_DEFINE_PSHINTER_INTERFACE( \
class_, \
get_globals_funcs_, \
@@ -694,25 +691,6 @@ FT_BEGIN_HEADER
get_t2_funcs_ \
};
-#else /* FT_CONFIG_OPTION_PIC */
-
-#define FT_DEFINE_PSHINTER_INTERFACE( \
- class_, \
- get_globals_funcs_, \
- get_t1_funcs_, \
- get_t2_funcs_ ) \
- void \
- FT_Init_Class_ ## class_( FT_Library library, \
- PSHinter_Interface* clazz ) \
- { \
- FT_UNUSED( library ); \
- \
- clazz->get_globals_funcs = get_globals_funcs_; \
- clazz->get_t1_funcs = get_t1_funcs_; \
- clazz->get_t2_funcs = get_t2_funcs_; \
- }
-
-#endif /* FT_CONFIG_OPTION_PIC */
FT_END_HEADER
diff --git a/thirdparty/freetype/include/freetype/internal/services/svbdf.h b/thirdparty/freetype/include/freetype/internal/services/svbdf.h
index 4a9ec20075..e4786ed038 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svbdf.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svbdf.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* svbdf.h */
-/* */
-/* The FreeType BDF services (specification). */
-/* */
-/* Copyright 2003-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * svbdf.h
+ *
+ * The FreeType BDF services (specification).
+ *
+ * Copyright (C) 2003-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef SVBDF_H_
@@ -46,8 +46,6 @@ FT_BEGIN_HEADER
};
-#ifndef FT_CONFIG_OPTION_PIC
-
#define FT_DEFINE_SERVICE_BDFRec( class_, \
get_charset_id_, \
get_property_ ) \
@@ -56,20 +54,6 @@ FT_BEGIN_HEADER
get_charset_id_, get_property_ \
};
-#else /* FT_CONFIG_OPTION_PIC */
-
-#define FT_DEFINE_SERVICE_BDFRec( class_, \
- get_charset_id_, \
- get_property_ ) \
- void \
- FT_Init_Class_ ## class_( FT_Service_BDFRec* clazz ) \
- { \
- clazz->get_charset_id = get_charset_id_; \
- clazz->get_property = get_property_; \
- }
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
/* */
diff --git a/thirdparty/freetype/include/freetype/internal/services/svcfftl.h b/thirdparty/freetype/include/freetype/internal/services/svcfftl.h
index db623e6840..6c621732da 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svcfftl.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svcfftl.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* svcfftl.h */
-/* */
-/* The FreeType CFF tables loader service (specification). */
-/* */
-/* Copyright 2017-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * svcfftl.h
+ *
+ * The FreeType CFF tables loader service (specification).
+ *
+ * Copyright (C) 2017-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef SVCFFTL_H_
@@ -65,8 +65,6 @@ FT_BEGIN_HEADER
};
-#ifndef FT_CONFIG_OPTION_PIC
-
#define FT_DEFINE_SERVICE_CFFLOADREC( class_, \
get_standard_encoding_, \
load_private_dict_, \
@@ -82,26 +80,6 @@ FT_BEGIN_HEADER
blend_build_vector_ \
};
-#else /* FT_CONFIG_OPTION_PIC */
-
-#define FT_DEFINE_SERVICE_CFFLOADREC( class_, \
- get_standard_encoding_, \
- load_private_dict_, \
- fd_select_get_, \
- blend_check_vector_, \
- blend_build_vector_ ) \
- void \
- FT_Init_Class_ ## class_( FT_Service_CFFLoadRec* clazz ) \
- { \
- clazz->get_standard_encoding = get_standard_encoding_; \
- clazz->load_private_dict = load_private_dict_; \
- clazz->fd_select_get = fd_select_get_; \
- clazz->blend_check_vector = blend_check_vector_; \
- clazz->blend_build_vector = blend_build_vector_; \
- }
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
FT_END_HEADER
diff --git a/thirdparty/freetype/include/freetype/internal/services/svcid.h b/thirdparty/freetype/include/freetype/internal/services/svcid.h
index cb59ac6a29..555a5af5b9 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svcid.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svcid.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* svcid.h */
-/* */
-/* The FreeType CID font services (specification). */
-/* */
-/* Copyright 2007-2018 by */
-/* Derek Clegg and Michael Toftdal. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * svcid.h
+ *
+ * The FreeType CID font services (specification).
+ *
+ * Copyright (C) 2007-2019 by
+ * Derek Clegg and Michael Toftdal.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef SVCID_H_
@@ -48,8 +48,6 @@ FT_BEGIN_HEADER
};
-#ifndef FT_CONFIG_OPTION_PIC
-
#define FT_DEFINE_SERVICE_CIDREC( class_, \
get_ros_, \
get_is_cid_, \
@@ -59,25 +57,6 @@ FT_BEGIN_HEADER
get_ros_, get_is_cid_, get_cid_from_glyph_index_ \
};
-#else /* FT_CONFIG_OPTION_PIC */
-
-#define FT_DEFINE_SERVICE_CIDREC( class_, \
- get_ros_, \
- get_is_cid_, \
- get_cid_from_glyph_index_ ) \
- void \
- FT_Init_Class_ ## class_( FT_Library library, \
- FT_Service_CIDRec* clazz ) \
- { \
- FT_UNUSED( library ); \
- \
- clazz->get_ros = get_ros_; \
- clazz->get_is_cid = get_is_cid_; \
- clazz->get_cid_from_glyph_index = get_cid_from_glyph_index_; \
- }
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
/* */
diff --git a/thirdparty/freetype/include/freetype/internal/services/svfntfmt.h b/thirdparty/freetype/include/freetype/internal/services/svfntfmt.h
index 3b732be1a1..6f4285ea8c 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svfntfmt.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svfntfmt.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* svfntfmt.h */
-/* */
-/* The FreeType font format service (specification only). */
-/* */
-/* Copyright 2003-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * svfntfmt.h
+ *
+ * The FreeType font format service (specification only).
+ *
+ * Copyright (C) 2003-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef SVFNTFMT_H_
@@ -26,9 +26,9 @@ FT_BEGIN_HEADER
/*
- * A trivial service used to return the name of a face's font driver,
- * according to the XFree86 nomenclature. Note that the service data
- * is a simple constant string pointer.
+ * A trivial service used to return the name of a face's font driver,
+ * according to the XFree86 nomenclature. Note that the service data is a
+ * simple constant string pointer.
*/
#define FT_SERVICE_ID_FONT_FORMAT "font-format"
diff --git a/thirdparty/freetype/include/freetype/internal/services/svgldict.h b/thirdparty/freetype/include/freetype/internal/services/svgldict.h
index f1a68e3110..ca8edf0eb5 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svgldict.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svgldict.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* svgldict.h */
-/* */
-/* The FreeType glyph dictionary services (specification). */
-/* */
-/* Copyright 2003-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * svgldict.h
+ *
+ * The FreeType glyph dictionary services (specification).
+ *
+ * Copyright (C) 2003-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef SVGLDICT_H_
@@ -26,8 +26,8 @@ FT_BEGIN_HEADER
/*
- * A service used to retrieve glyph names, as well as to find the
- * index of a given glyph name in a font.
+ * A service used to retrieve glyph names, as well as to find the index of
+ * a given glyph name in a font.
*
*/
@@ -52,8 +52,6 @@ FT_BEGIN_HEADER
};
-#ifndef FT_CONFIG_OPTION_PIC
-
#define FT_DEFINE_SERVICE_GLYPHDICTREC( class_, \
get_name_, \
name_index_ ) \
@@ -62,23 +60,6 @@ FT_BEGIN_HEADER
get_name_, name_index_ \
};
-#else /* FT_CONFIG_OPTION_PIC */
-
-#define FT_DEFINE_SERVICE_GLYPHDICTREC( class_, \
- get_name_, \
- name_index_ ) \
- void \
- FT_Init_Class_ ## class_( FT_Library library, \
- FT_Service_GlyphDictRec* clazz ) \
- { \
- FT_UNUSED( library ); \
- \
- clazz->get_name = get_name_; \
- clazz->name_index = name_index_; \
- }
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
/* */
diff --git a/thirdparty/freetype/include/freetype/internal/services/svgxval.h b/thirdparty/freetype/include/freetype/internal/services/svgxval.h
index ed79ebeaa8..0bb76f3144 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svgxval.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svgxval.h
@@ -1,28 +1,28 @@
-/***************************************************************************/
-/* */
-/* svgxval.h */
-/* */
-/* FreeType API for validating TrueTypeGX/AAT tables (specification). */
-/* */
-/* Copyright 2004-2018 by */
-/* Masatake YAMATO, Red Hat K.K., */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-/***************************************************************************/
-/* */
-/* gxvalid is derived from both gxlayout module and otvalid module. */
-/* Development of gxlayout is supported by the Information-technology */
-/* Promotion Agency(IPA), Japan. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * svgxval.h
+ *
+ * FreeType API for validating TrueTypeGX/AAT tables (specification).
+ *
+ * Copyright (C) 2004-2019 by
+ * Masatake YAMATO, Red Hat K.K.,
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+/****************************************************************************
+ *
+ * gxvalid is derived from both gxlayout module and otvalid module.
+ * Development of gxlayout is supported by the Information-technology
+ * Promotion Agency(IPA), Japan.
+ *
+ */
#ifndef SVGXVAL_H_
diff --git a/thirdparty/freetype/include/freetype/internal/services/svkern.h b/thirdparty/freetype/include/freetype/internal/services/svkern.h
index c7e8f6ef27..f992a327c1 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svkern.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svkern.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* svkern.h */
-/* */
-/* The FreeType Kerning service (specification). */
-/* */
-/* Copyright 2006-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * svkern.h
+ *
+ * The FreeType Kerning service (specification).
+ *
+ * Copyright (C) 2006-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef SVKERN_H_
diff --git a/thirdparty/freetype/include/freetype/internal/services/svmetric.h b/thirdparty/freetype/include/freetype/internal/services/svmetric.h
index abaacddbbe..d688bc7c60 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svmetric.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svmetric.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* svmetric.h */
-/* */
-/* The FreeType services for metrics variations (specification). */
-/* */
-/* Copyright 2016-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * svmetric.h
+ *
+ * The FreeType services for metrics variations (specification).
+ *
+ * Copyright (C) 2016-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef SVMETRIC_H_
@@ -26,7 +26,7 @@ FT_BEGIN_HEADER
/*
- * A service to manage the `HVAR, `MVAR', and `VVAR' OpenType tables.
+ * A service to manage the `HVAR, `MVAR', and `VVAR' OpenType tables.
*
*/
@@ -93,8 +93,6 @@ FT_BEGIN_HEADER
};
-#ifndef FT_CONFIG_OPTION_PIC
-
#define FT_DEFINE_SERVICE_METRICSVARIATIONSREC( class_, \
hadvance_adjust_, \
lsb_adjust_, \
@@ -116,32 +114,6 @@ FT_BEGIN_HEADER
metrics_adjust_ \
};
-#else /* FT_CONFIG_OPTION_PIC */
-
-#define FT_DEFINE_SERVICE_METRICSVARIATIONSREC( class_, \
- hadvance_adjust_, \
- lsb_adjust_, \
- rsb_adjust_, \
- vadvance_adjust_, \
- tsb_adjust_, \
- bsb_adjust_, \
- vorg_adjust_, \
- metrics_adjust_ ) \
- void \
- FT_Init_Class_ ## class_( FT_Service_MetricsVariationsRec* clazz ) \
- { \
- clazz->hadvance_adjust = hadvance_adjust_; \
- clazz->lsb_adjust = lsb_adjust_; \
- clazz->rsb_adjust = rsb_adjust_; \
- clazz->vadvance_adjust = vadvance_adjust_; \
- clazz->tsb_adjust = tsb_adjust_; \
- clazz->bsb_adjust = bsb_adjust_; \
- clazz->vorg_adjust = vorg_adjust_; \
- clazz->metrics_adjust = metrics_adjust_; \
- }
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
/* */
diff --git a/thirdparty/freetype/include/freetype/internal/services/svmm.h b/thirdparty/freetype/include/freetype/internal/services/svmm.h
index bcbb38e2ce..3652f2050a 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svmm.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svmm.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* svmm.h */
-/* */
-/* The FreeType Multiple Masters and GX var services (specification). */
-/* */
-/* Copyright 2003-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * svmm.h
+ *
+ * The FreeType Multiple Masters and GX var services (specification).
+ *
+ * Copyright (C) 2003-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef SVMM_H_
@@ -26,9 +26,9 @@ FT_BEGIN_HEADER
/*
- * A service used to manage multiple-masters data in a given face.
+ * A service used to manage multiple-masters data in a given face.
*
- * See the related APIs in `ftmm.h' (FT_MULTIPLE_MASTERS_H).
+ * See the related APIs in `ftmm.h' (FT_MULTIPLE_MASTERS_H).
*
*/
@@ -86,81 +86,65 @@ FT_BEGIN_HEADER
typedef void
(*FT_Done_Blend_Func)( FT_Face );
+ typedef FT_Error
+ (*FT_Set_MM_WeightVector_Func)( FT_Face face,
+ FT_UInt len,
+ FT_Fixed* weight_vector );
+
+ typedef FT_Error
+ (*FT_Get_MM_WeightVector_Func)( FT_Face face,
+ FT_UInt* len,
+ FT_Fixed* weight_vector );
+
FT_DEFINE_SERVICE( MultiMasters )
{
- FT_Get_MM_Func get_mm;
- FT_Set_MM_Design_Func set_mm_design;
- FT_Set_MM_Blend_Func set_mm_blend;
- FT_Get_MM_Blend_Func get_mm_blend;
- FT_Get_MM_Var_Func get_mm_var;
- FT_Set_Var_Design_Func set_var_design;
- FT_Get_Var_Design_Func get_var_design;
- FT_Set_Instance_Func set_instance;
+ FT_Get_MM_Func get_mm;
+ FT_Set_MM_Design_Func set_mm_design;
+ FT_Set_MM_Blend_Func set_mm_blend;
+ FT_Get_MM_Blend_Func get_mm_blend;
+ FT_Get_MM_Var_Func get_mm_var;
+ FT_Set_Var_Design_Func set_var_design;
+ FT_Get_Var_Design_Func get_var_design;
+ FT_Set_Instance_Func set_instance;
+ FT_Set_MM_WeightVector_Func set_mm_weightvector;
+ FT_Get_MM_WeightVector_Func get_mm_weightvector;
/* for internal use; only needed for code sharing between modules */
- FT_Get_Var_Blend_Func get_var_blend;
- FT_Done_Blend_Func done_blend;
+ FT_Get_Var_Blend_Func get_var_blend;
+ FT_Done_Blend_Func done_blend;
};
-#ifndef FT_CONFIG_OPTION_PIC
-
-#define FT_DEFINE_SERVICE_MULTIMASTERSREC( class_, \
- get_mm_, \
- set_mm_design_, \
- set_mm_blend_, \
- get_mm_blend_, \
- get_mm_var_, \
- set_var_design_, \
- get_var_design_, \
- set_instance_, \
- get_var_blend_, \
- done_blend_ ) \
- static const FT_Service_MultiMastersRec class_ = \
- { \
- get_mm_, \
- set_mm_design_, \
- set_mm_blend_, \
- get_mm_blend_, \
- get_mm_var_, \
- set_var_design_, \
- get_var_design_, \
- set_instance_, \
- get_var_blend_, \
- done_blend_ \
+#define FT_DEFINE_SERVICE_MULTIMASTERSREC( class_, \
+ get_mm_, \
+ set_mm_design_, \
+ set_mm_blend_, \
+ get_mm_blend_, \
+ get_mm_var_, \
+ set_var_design_, \
+ get_var_design_, \
+ set_instance_, \
+ set_weightvector_, \
+ get_weightvector_, \
+ get_var_blend_, \
+ done_blend_ ) \
+ static const FT_Service_MultiMastersRec class_ = \
+ { \
+ get_mm_, \
+ set_mm_design_, \
+ set_mm_blend_, \
+ get_mm_blend_, \
+ get_mm_var_, \
+ set_var_design_, \
+ get_var_design_, \
+ set_instance_, \
+ set_weightvector_, \
+ get_weightvector_, \
+ get_var_blend_, \
+ done_blend_ \
};
-#else /* FT_CONFIG_OPTION_PIC */
-
-#define FT_DEFINE_SERVICE_MULTIMASTERSREC( class_, \
- get_mm_, \
- set_mm_design_, \
- set_mm_blend_, \
- get_mm_blend_, \
- get_mm_var_, \
- set_var_design_, \
- get_var_design_, \
- set_instance_, \
- get_var_blend_, \
- done_blend_ ) \
- void \
- FT_Init_Class_ ## class_( FT_Service_MultiMastersRec* clazz ) \
- { \
- clazz->get_mm = get_mm_; \
- clazz->set_mm_design = set_mm_design_; \
- clazz->set_mm_blend = set_mm_blend_; \
- clazz->get_mm_blend = get_mm_blend_; \
- clazz->get_mm_var = get_mm_var_; \
- clazz->set_var_design = set_var_design_; \
- clazz->get_var_design = get_var_design_; \
- clazz->set_instance = set_instance_; \
- clazz->get_var_blend = get_var_blend_; \
- clazz->done_blend = done_blend_; \
- }
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
/* */
diff --git a/thirdparty/freetype/include/freetype/internal/services/svotval.h b/thirdparty/freetype/include/freetype/internal/services/svotval.h
index 31294296a6..cab4c6efbb 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svotval.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svotval.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* svotval.h */
-/* */
-/* The FreeType OpenType validation service (specification). */
-/* */
-/* Copyright 2004-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * svotval.h
+ *
+ * The FreeType OpenType validation service (specification).
+ *
+ * Copyright (C) 2004-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef SVOTVAL_H_
diff --git a/thirdparty/freetype/include/freetype/internal/services/svpfr.h b/thirdparty/freetype/include/freetype/internal/services/svpfr.h
index e65d57e91b..fd01d614dd 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svpfr.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svpfr.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* svpfr.h */
-/* */
-/* Internal PFR service functions (specification). */
-/* */
-/* Copyright 2003-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * svpfr.h
+ *
+ * Internal PFR service functions (specification).
+ *
+ * Copyright (C) 2003-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef SVPFR_H_
diff --git a/thirdparty/freetype/include/freetype/internal/services/svpostnm.h b/thirdparty/freetype/include/freetype/internal/services/svpostnm.h
index 4a49d8b053..18e3843cbe 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svpostnm.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svpostnm.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* svpostnm.h */
-/* */
-/* The FreeType PostScript name services (specification). */
-/* */
-/* Copyright 2003-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * svpostnm.h
+ *
+ * The FreeType PostScript name services (specification).
+ *
+ * Copyright (C) 2003-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef SVPOSTNM_H_
@@ -25,13 +25,13 @@
FT_BEGIN_HEADER
/*
- * A trivial service used to retrieve the PostScript name of a given
- * font when available. The `get_name' field should never be NULL.
+ * A trivial service used to retrieve the PostScript name of a given font
+ * when available. The `get_name' field should never be `NULL`.
*
- * The corresponding function can return NULL to indicate that the
- * PostScript name is not available.
+ * The corresponding function can return `NULL` to indicate that the
+ * PostScript name is not available.
*
- * The name is owned by the face and will be destroyed with it.
+ * The name is owned by the face and will be destroyed with it.
*/
#define FT_SERVICE_ID_POSTSCRIPT_FONT_NAME "postscript-font-name"
@@ -47,28 +47,12 @@ FT_BEGIN_HEADER
};
-#ifndef FT_CONFIG_OPTION_PIC
-
#define FT_DEFINE_SERVICE_PSFONTNAMEREC( class_, get_ps_font_name_ ) \
static const FT_Service_PsFontNameRec class_ = \
{ \
get_ps_font_name_ \
};
-#else /* FT_CONFIG_OPTION_PIC */
-
-#define FT_DEFINE_SERVICE_PSFONTNAMEREC( class_, get_ps_font_name_ ) \
- void \
- FT_Init_Class_ ## class_( FT_Library library, \
- FT_Service_PsFontNameRec* clazz ) \
- { \
- FT_UNUSED( library ); \
- \
- clazz->get_ps_font_name = get_ps_font_name_; \
- }
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
/* */
diff --git a/thirdparty/freetype/include/freetype/internal/services/svprop.h b/thirdparty/freetype/include/freetype/internal/services/svprop.h
index adc0bcf439..e48d0151ec 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svprop.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svprop.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* svprop.h */
-/* */
-/* The FreeType property service (specification). */
-/* */
-/* Copyright 2012-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * svprop.h
+ *
+ * The FreeType property service (specification).
+ *
+ * Copyright (C) 2012-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef SVPROP_H_
@@ -45,8 +45,6 @@ FT_BEGIN_HEADER
};
-#ifndef FT_CONFIG_OPTION_PIC
-
#define FT_DEFINE_SERVICE_PROPERTIESREC( class_, \
set_property_, \
get_property_ ) \
@@ -56,20 +54,6 @@ FT_BEGIN_HEADER
get_property_ \
};
-#else /* FT_CONFIG_OPTION_PIC */
-
-#define FT_DEFINE_SERVICE_PROPERTIESREC( class_, \
- set_property_, \
- get_property_ ) \
- void \
- FT_Init_Class_ ## class_( FT_Service_PropertiesRec* clazz ) \
- { \
- clazz->set_property = set_property_; \
- clazz->get_property = get_property_; \
- }
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
/* */
diff --git a/thirdparty/freetype/include/freetype/internal/services/svpscmap.h b/thirdparty/freetype/include/freetype/internal/services/svpscmap.h
index 5589575b92..dfac3bafa9 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svpscmap.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svpscmap.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* svpscmap.h */
-/* */
-/* The FreeType PostScript charmap service (specification). */
-/* */
-/* Copyright 2003-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * svpscmap.h
+ *
+ * The FreeType PostScript charmap service (specification).
+ *
+ * Copyright (C) 2003-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef SVPSCMAP_H_
@@ -29,27 +29,26 @@ FT_BEGIN_HEADER
/*
- * Adobe glyph name to unicode value.
+ * Adobe glyph name to unicode value.
*/
typedef FT_UInt32
(*PS_Unicode_ValueFunc)( const char* glyph_name );
/*
- * Macintosh name id to glyph name. NULL if invalid index.
+ * Macintosh name id to glyph name. `NULL` if invalid index.
*/
typedef const char*
(*PS_Macintosh_NameFunc)( FT_UInt name_index );
/*
- * Adobe standard string ID to glyph name. NULL if invalid index.
+ * Adobe standard string ID to glyph name. `NULL` if invalid index.
*/
typedef const char*
(*PS_Adobe_Std_StringsFunc)( FT_UInt string_index );
/*
- * Simple unicode -> glyph index charmap built from font glyph names
- * table.
+ * Simple unicode -> glyph index charmap built from font glyph names table.
*/
typedef struct PS_UniMap_
{
@@ -71,16 +70,16 @@ FT_BEGIN_HEADER
/*
- * A function which returns a glyph name for a given index. Returns
- * NULL if invalid index.
+ * A function which returns a glyph name for a given index. Returns
+ * `NULL` if invalid index.
*/
typedef const char*
(*PS_GetGlyphNameFunc)( FT_Pointer data,
FT_UInt string_index );
/*
- * A function used to release the glyph name returned by
- * PS_GetGlyphNameFunc, when needed
+ * A function used to release the glyph name returned by
+ * PS_GetGlyphNameFunc, when needed
*/
typedef void
(*PS_FreeGlyphNameFunc)( FT_Pointer data,
@@ -118,8 +117,6 @@ FT_BEGIN_HEADER
};
-#ifndef FT_CONFIG_OPTION_PIC
-
#define FT_DEFINE_SERVICE_PSCMAPSREC( class_, \
unicode_value_, \
unicodes_init_, \
@@ -136,35 +133,6 @@ FT_BEGIN_HEADER
adobe_std_strings_, adobe_std_encoding_, adobe_expert_encoding_ \
};
-#else /* FT_CONFIG_OPTION_PIC */
-
-#define FT_DEFINE_SERVICE_PSCMAPSREC( class_, \
- unicode_value_, \
- unicodes_init_, \
- unicodes_char_index_, \
- unicodes_char_next_, \
- macintosh_name_, \
- adobe_std_strings_, \
- adobe_std_encoding_, \
- adobe_expert_encoding_ ) \
- void \
- FT_Init_Class_ ## class_( FT_Library library, \
- FT_Service_PsCMapsRec* clazz ) \
- { \
- FT_UNUSED( library ); \
- \
- clazz->unicode_value = unicode_value_; \
- clazz->unicodes_init = unicodes_init_; \
- clazz->unicodes_char_index = unicodes_char_index_; \
- clazz->unicodes_char_next = unicodes_char_next_; \
- clazz->macintosh_name = macintosh_name_; \
- clazz->adobe_std_strings = adobe_std_strings_; \
- clazz->adobe_std_encoding = adobe_std_encoding_; \
- clazz->adobe_expert_encoding = adobe_expert_encoding_; \
- }
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
/* */
diff --git a/thirdparty/freetype/include/freetype/internal/services/svpsinfo.h b/thirdparty/freetype/include/freetype/internal/services/svpsinfo.h
index 408f406dfa..fb4e0e3fa9 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svpsinfo.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svpsinfo.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* svpsinfo.h */
-/* */
-/* The FreeType PostScript info service (specification). */
-/* */
-/* Copyright 2003-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * svpsinfo.h
+ *
+ * The FreeType PostScript info service (specification).
+ *
+ * Copyright (C) 2003-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef SVPSINFO_H_
@@ -62,8 +62,6 @@ FT_BEGIN_HEADER
};
-#ifndef FT_CONFIG_OPTION_PIC
-
#define FT_DEFINE_SERVICE_PSINFOREC( class_, \
get_font_info_, \
ps_get_font_extra_, \
@@ -76,29 +74,6 @@ FT_BEGIN_HEADER
get_font_private_, get_font_value_ \
};
-#else /* FT_CONFIG_OPTION_PIC */
-
-#define FT_DEFINE_SERVICE_PSINFOREC( class_, \
- get_font_info_, \
- ps_get_font_extra_, \
- has_glyph_names_, \
- get_font_private_, \
- get_font_value_ ) \
- void \
- FT_Init_Class_ ## class_( FT_Library library, \
- FT_Service_PsInfoRec* clazz ) \
- { \
- FT_UNUSED( library ); \
- \
- clazz->ps_get_font_info = get_font_info_; \
- clazz->ps_get_font_extra = ps_get_font_extra_; \
- clazz->ps_has_glyph_names = has_glyph_names_; \
- clazz->ps_get_font_private = get_font_private_; \
- clazz->ps_get_font_value = get_font_value_; \
- }
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
/* */
diff --git a/thirdparty/freetype/include/freetype/internal/services/svsfnt.h b/thirdparty/freetype/include/freetype/internal/services/svsfnt.h
index e8b37bc47f..464aa209f7 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svsfnt.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svsfnt.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* svsfnt.h */
-/* */
-/* The FreeType SFNT table loading service (specification). */
-/* */
-/* Copyright 2003-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * svsfnt.h
+ *
+ * The FreeType SFNT table loading service (specification).
+ *
+ * Copyright (C) 2003-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef SVSFNT_H_
@@ -27,7 +27,7 @@ FT_BEGIN_HEADER
/*
- * SFNT table loading service.
+ * SFNT table loading service.
*/
#define FT_SERVICE_ID_SFNT_TABLE "sfnt-table"
@@ -70,27 +70,12 @@ FT_BEGIN_HEADER
};
-#ifndef FT_CONFIG_OPTION_PIC
-
#define FT_DEFINE_SERVICE_SFNT_TABLEREC( class_, load_, get_, info_ ) \
static const FT_Service_SFNT_TableRec class_ = \
{ \
load_, get_, info_ \
};
-#else /* FT_CONFIG_OPTION_PIC */
-
-#define FT_DEFINE_SERVICE_SFNT_TABLEREC( class_, load_, get_, info_ ) \
- void \
- FT_Init_Class_ ## class_( FT_Service_SFNT_TableRec* clazz ) \
- { \
- clazz->load_table = load_; \
- clazz->get_table = get_; \
- clazz->table_info = info_; \
- }
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
/* */
diff --git a/thirdparty/freetype/include/freetype/internal/services/svttcmap.h b/thirdparty/freetype/include/freetype/internal/services/svttcmap.h
index cd0e6fda6f..0fcb81371d 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svttcmap.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svttcmap.h
@@ -1,20 +1,20 @@
-/***************************************************************************/
-/* */
-/* svttcmap.h */
-/* */
-/* The FreeType TrueType/sfnt cmap extra information service. */
-/* */
-/* Copyright 2003-2018 by */
-/* Masatake YAMATO, Redhat K.K., */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * svttcmap.h
+ *
+ * The FreeType TrueType/sfnt cmap extra information service.
+ *
+ * Copyright (C) 2003-2019 by
+ * Masatake YAMATO, Redhat K.K.,
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
/* Development of this service is support of
Information-technology Promotion Agency, Japan. */
@@ -32,29 +32,28 @@ FT_BEGIN_HEADER
#define FT_SERVICE_ID_TT_CMAP "tt-cmaps"
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* TT_CMapInfo */
- /* */
- /* <Description> */
- /* A structure used to store TrueType/sfnt specific cmap information */
- /* which is not covered by the generic @FT_CharMap structure. This */
- /* structure can be accessed with the @FT_Get_TT_CMap_Info function. */
- /* */
- /* <Fields> */
- /* language :: */
- /* The language ID used in Mac fonts. Definitions of values are in */
- /* `ttnameid.h'. */
- /* */
- /* format :: */
- /* The cmap format. OpenType 1.6 defines the formats 0 (byte */
- /* encoding table), 2~(high-byte mapping through table), 4~(segment */
- /* mapping to delta values), 6~(trimmed table mapping), 8~(mixed */
- /* 16-bit and 32-bit coverage), 10~(trimmed array), 12~(segmented */
- /* coverage), 13~(last resort font), and 14 (Unicode Variation */
- /* Sequences). */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * TT_CMapInfo
+ *
+ * @description:
+ * A structure used to store TrueType/sfnt specific cmap information
+ * which is not covered by the generic @FT_CharMap structure. This
+ * structure can be accessed with the @FT_Get_TT_CMap_Info function.
+ *
+ * @fields:
+ * language ::
+ * The language ID used in Mac fonts. Definitions of values are in
+ * `ttnameid.h`.
+ *
+ * format ::
+ * The cmap format. OpenType 1.6 defines the formats 0 (byte encoding
+ * table), 2~(high-byte mapping through table), 4~(segment mapping to
+ * delta values), 6~(trimmed table mapping), 8~(mixed 16-bit and 32-bit
+ * coverage), 10~(trimmed array), 12~(segmented coverage), 13~(last
+ * resort font), and 14 (Unicode Variation Sequences).
+ */
typedef struct TT_CMapInfo_
{
FT_ULong language;
@@ -73,7 +72,6 @@ FT_BEGIN_HEADER
TT_CMap_Info_GetFunc get_cmap_info;
};
-#ifndef FT_CONFIG_OPTION_PIC
#define FT_DEFINE_SERVICE_TTCMAPSREC( class_, get_cmap_info_ ) \
static const FT_Service_TTCMapsRec class_ = \
@@ -81,20 +79,6 @@ FT_BEGIN_HEADER
get_cmap_info_ \
};
-#else /* FT_CONFIG_OPTION_PIC */
-
-#define FT_DEFINE_SERVICE_TTCMAPSREC( class_, get_cmap_info_ ) \
- void \
- FT_Init_Class_ ## class_( FT_Library library, \
- FT_Service_TTCMapsRec* clazz ) \
- { \
- FT_UNUSED( library ); \
- \
- clazz->get_cmap_info = get_cmap_info_; \
- }
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
/* */
diff --git a/thirdparty/freetype/include/freetype/internal/services/svtteng.h b/thirdparty/freetype/include/freetype/internal/services/svtteng.h
index 92e3c541f5..a852f5c6fb 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svtteng.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svtteng.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* svtteng.h */
-/* */
-/* The FreeType TrueType engine query service (specification). */
-/* */
-/* Copyright 2006-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * svtteng.h
+ *
+ * The FreeType TrueType engine query service (specification).
+ *
+ * Copyright (C) 2006-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef SVTTENG_H_
@@ -27,7 +27,7 @@ FT_BEGIN_HEADER
/*
- * SFNT table loading service.
+ * SFNT table loading service.
*/
#define FT_SERVICE_ID_TRUETYPE_ENGINE "truetype-engine"
diff --git a/thirdparty/freetype/include/freetype/internal/services/svttglyf.h b/thirdparty/freetype/include/freetype/internal/services/svttglyf.h
index 16fac1ca18..c8798771fb 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svttglyf.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svttglyf.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* svttglyf.h */
-/* */
-/* The FreeType TrueType glyph service. */
-/* */
-/* Copyright 2007-2018 by */
-/* David Turner. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * svttglyf.h
+ *
+ * The FreeType TrueType glyph service.
+ *
+ * Copyright (C) 2007-2019 by
+ * David Turner.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef SVTTGLYF_H_
#define SVTTGLYF_H_
@@ -39,25 +39,12 @@ FT_BEGIN_HEADER
};
-#ifndef FT_CONFIG_OPTION_PIC
-
#define FT_DEFINE_SERVICE_TTGLYFREC( class_, get_location_ ) \
static const FT_Service_TTGlyfRec class_ = \
{ \
get_location_ \
};
-#else /* FT_CONFIG_OPTION_PIC */
-
-#define FT_DEFINE_SERVICE_TTGLYFREC( class_, get_location_ ) \
- void \
- FT_Init_Class_ ## class_( FT_Service_TTGlyfRec* clazz ) \
- { \
- clazz->get_location = get_location_; \
- }
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
/* */
diff --git a/thirdparty/freetype/include/freetype/internal/services/svwinfnt.h b/thirdparty/freetype/include/freetype/internal/services/svwinfnt.h
index 80d481cbd1..38ee020965 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svwinfnt.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svwinfnt.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* svwinfnt.h */
-/* */
-/* The FreeType Windows FNT/FONT service (specification). */
-/* */
-/* Copyright 2003-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * svwinfnt.h
+ *
+ * The FreeType Windows FNT/FONT service (specification).
+ *
+ * Copyright (C) 2003-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef SVWINFNT_H_
diff --git a/thirdparty/freetype/include/freetype/internal/sfnt.h b/thirdparty/freetype/include/freetype/internal/sfnt.h
index fb1e327aeb..225f40df6e 100644
--- a/thirdparty/freetype/include/freetype/internal/sfnt.h
+++ b/thirdparty/freetype/include/freetype/internal/sfnt.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* sfnt.h */
-/* */
-/* High-level `sfnt' driver interface (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * sfnt.h
+ *
+ * High-level 'sfnt' driver interface (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef SFNT_H_
@@ -28,43 +28,46 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* TT_Init_Face_Func */
- /* */
- /* <Description> */
- /* First part of the SFNT face object initialization. This finds */
- /* the face in a SFNT file or collection, and load its format tag in */
- /* face->format_tag. */
- /* */
- /* <Input> */
- /* stream :: The input stream. */
- /* */
- /* face :: A handle to the target face object. */
- /* */
- /* face_index :: The index of the TrueType font, if we are opening a */
- /* collection, in bits 0-15. The numbered instance */
- /* index~+~1 of a GX (sub)font, if applicable, in bits */
- /* 16-30. */
- /* */
- /* num_params :: The number of additional parameters. */
- /* */
- /* params :: Optional additional parameters. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- /* <Note> */
- /* The stream cursor must be at the font file's origin. */
- /* */
- /* This function recognizes fonts embedded in a `TrueType */
- /* collection'. */
- /* */
- /* Once the format tag has been validated by the font driver, it */
- /* should then call the TT_Load_Face_Func() callback to read the rest */
- /* of the SFNT tables in the object. */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * TT_Init_Face_Func
+ *
+ * @description:
+ * First part of the SFNT face object initialization. This finds the
+ * face in a SFNT file or collection, and load its format tag in
+ * face->format_tag.
+ *
+ * @input:
+ * stream ::
+ * The input stream.
+ *
+ * face ::
+ * A handle to the target face object.
+ *
+ * face_index ::
+ * The index of the TrueType font, if we are opening a collection, in
+ * bits 0-15. The numbered instance index~+~1 of a GX (sub)font, if
+ * applicable, in bits 16-30.
+ *
+ * num_params ::
+ * The number of additional parameters.
+ *
+ * params ::
+ * Optional additional parameters.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * The stream cursor must be at the font file's origin.
+ *
+ * This function recognizes fonts embedded in a 'TrueType collection'.
+ *
+ * Once the format tag has been validated by the font driver, it should
+ * then call the TT_Load_Face_Func() callback to read the rest of the
+ * SFNT tables in the object.
+ */
typedef FT_Error
(*TT_Init_Face_Func)( FT_Stream stream,
TT_Face face,
@@ -73,36 +76,40 @@ FT_BEGIN_HEADER
FT_Parameter* params );
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* TT_Load_Face_Func */
- /* */
- /* <Description> */
- /* Second part of the SFNT face object initialization. This loads */
- /* the common SFNT tables (head, OS/2, maxp, metrics, etc.) in the */
- /* face object. */
- /* */
- /* <Input> */
- /* stream :: The input stream. */
- /* */
- /* face :: A handle to the target face object. */
- /* */
- /* face_index :: The index of the TrueType font, if we are opening a */
- /* collection, in bits 0-15. The numbered instance */
- /* index~+~1 of a GX (sub)font, if applicable, in bits */
- /* 16-30. */
- /* */
- /* num_params :: The number of additional parameters. */
- /* */
- /* params :: Optional additional parameters. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- /* <Note> */
- /* This function must be called after TT_Init_Face_Func(). */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * TT_Load_Face_Func
+ *
+ * @description:
+ * Second part of the SFNT face object initialization. This loads the
+ * common SFNT tables (head, OS/2, maxp, metrics, etc.) in the face
+ * object.
+ *
+ * @input:
+ * stream ::
+ * The input stream.
+ *
+ * face ::
+ * A handle to the target face object.
+ *
+ * face_index ::
+ * The index of the TrueType font, if we are opening a collection, in
+ * bits 0-15. The numbered instance index~+~1 of a GX (sub)font, if
+ * applicable, in bits 16-30.
+ *
+ * num_params ::
+ * The number of additional parameters.
+ *
+ * params ::
+ * Optional additional parameters.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * This function must be called after TT_Init_Face_Func().
+ */
typedef FT_Error
(*TT_Load_Face_Func)( FT_Stream stream,
TT_Face face,
@@ -111,64 +118,64 @@ FT_BEGIN_HEADER
FT_Parameter* params );
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* TT_Done_Face_Func */
- /* */
- /* <Description> */
- /* A callback used to delete the common SFNT data from a face. */
- /* */
- /* <Input> */
- /* face :: A handle to the target face object. */
- /* */
- /* <Note> */
- /* This function does NOT destroy the face object. */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * TT_Done_Face_Func
+ *
+ * @description:
+ * A callback used to delete the common SFNT data from a face.
+ *
+ * @input:
+ * face ::
+ * A handle to the target face object.
+ *
+ * @note:
+ * This function does NOT destroy the face object.
+ */
typedef void
(*TT_Done_Face_Func)( TT_Face face );
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* TT_Load_Any_Func */
- /* */
- /* <Description> */
- /* Load any font table into client memory. */
- /* */
- /* <Input> */
- /* face :: The face object to look for. */
- /* */
- /* tag :: The tag of table to load. Use the value 0 if you want */
- /* to access the whole font file, else set this parameter */
- /* to a valid TrueType table tag that you can forge with */
- /* the MAKE_TT_TAG macro. */
- /* */
- /* offset :: The starting offset in the table (or the file if */
- /* tag == 0). */
- /* */
- /* length :: The address of the decision variable: */
- /* */
- /* If length == NULL: */
- /* Loads the whole table. Returns an error if */
- /* `offset' == 0! */
- /* */
- /* If *length == 0: */
- /* Exits immediately; returning the length of the given */
- /* table or of the font file, depending on the value of */
- /* `tag'. */
- /* */
- /* If *length != 0: */
- /* Loads the next `length' bytes of table or font, */
- /* starting at offset `offset' (in table or font too). */
- /* */
- /* <Output> */
- /* buffer :: The address of target buffer. */
- /* */
- /* <Return> */
- /* TrueType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * TT_Load_Any_Func
+ *
+ * @description:
+ * Load any font table into client memory.
+ *
+ * @input:
+ * face ::
+ * The face object to look for.
+ *
+ * tag ::
+ * The tag of table to load. Use the value 0 if you want to access the
+ * whole font file, else set this parameter to a valid TrueType table
+ * tag that you can forge with the MAKE_TT_TAG macro.
+ *
+ * offset ::
+ * The starting offset in the table (or the file if tag == 0).
+ *
+ * length ::
+ * The address of the decision variable:
+ *
+ * If `length == NULL`: Loads the whole table. Returns an error if
+ * 'offset' == 0!
+ *
+ * If `*length == 0`: Exits immediately; returning the length of the
+ * given table or of the font file, depending on the value of 'tag'.
+ *
+ * If `*length != 0`: Loads the next 'length' bytes of table or font,
+ * starting at offset 'offset' (in table or font too).
+ *
+ * @output:
+ * buffer ::
+ * The address of target buffer.
+ *
+ * @return:
+ * TrueType error code. 0 means success.
+ */
typedef FT_Error
(*TT_Load_Any_Func)( TT_Face face,
FT_ULong tag,
@@ -177,34 +184,39 @@ FT_BEGIN_HEADER
FT_ULong* length );
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* TT_Find_SBit_Image_Func */
- /* */
- /* <Description> */
- /* Check whether an embedded bitmap (an `sbit') exists for a given */
- /* glyph, at a given strike. */
- /* */
- /* <Input> */
- /* face :: The target face object. */
- /* */
- /* glyph_index :: The glyph index. */
- /* */
- /* strike_index :: The current strike index. */
- /* */
- /* <Output> */
- /* arange :: The SBit range containing the glyph index. */
- /* */
- /* astrike :: The SBit strike containing the glyph index. */
- /* */
- /* aglyph_offset :: The offset of the glyph data in `EBDT' table. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. Returns */
- /* SFNT_Err_Invalid_Argument if no sbit exists for the requested */
- /* glyph. */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * TT_Find_SBit_Image_Func
+ *
+ * @description:
+ * Check whether an embedded bitmap (an 'sbit') exists for a given glyph,
+ * at a given strike.
+ *
+ * @input:
+ * face ::
+ * The target face object.
+ *
+ * glyph_index ::
+ * The glyph index.
+ *
+ * strike_index ::
+ * The current strike index.
+ *
+ * @output:
+ * arange ::
+ * The SBit range containing the glyph index.
+ *
+ * astrike ::
+ * The SBit strike containing the glyph index.
+ *
+ * aglyph_offset ::
+ * The offset of the glyph data in 'EBDT' table.
+ *
+ * @return:
+ * FreeType error code. 0 means success. Returns
+ * SFNT_Err_Invalid_Argument if no sbit exists for the requested glyph.
+ */
typedef FT_Error
(*TT_Find_SBit_Image_Func)( TT_Face face,
FT_UInt glyph_index,
@@ -214,78 +226,81 @@ FT_BEGIN_HEADER
FT_ULong *aglyph_offset );
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* TT_Load_SBit_Metrics_Func */
- /* */
- /* <Description> */
- /* Get the big metrics for a given embedded bitmap. */
- /* */
- /* <Input> */
- /* stream :: The input stream. */
- /* */
- /* range :: The SBit range containing the glyph. */
- /* */
- /* <Output> */
- /* big_metrics :: A big SBit metrics structure for the glyph. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- /* <Note> */
- /* The stream cursor must be positioned at the glyph's offset within */
- /* the `EBDT' table before the call. */
- /* */
- /* If the image format uses variable metrics, the stream cursor is */
- /* positioned just after the metrics header in the `EBDT' table on */
- /* function exit. */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * TT_Load_SBit_Metrics_Func
+ *
+ * @description:
+ * Get the big metrics for a given embedded bitmap.
+ *
+ * @input:
+ * stream ::
+ * The input stream.
+ *
+ * range ::
+ * The SBit range containing the glyph.
+ *
+ * @output:
+ * big_metrics ::
+ * A big SBit metrics structure for the glyph.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * The stream cursor must be positioned at the glyph's offset within the
+ * 'EBDT' table before the call.
+ *
+ * If the image format uses variable metrics, the stream cursor is
+ * positioned just after the metrics header in the 'EBDT' table on
+ * function exit.
+ */
typedef FT_Error
(*TT_Load_SBit_Metrics_Func)( FT_Stream stream,
TT_SBit_Range range,
TT_SBit_Metrics metrics );
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* TT_Load_SBit_Image_Func */
- /* */
- /* <Description> */
- /* Load a given glyph sbit image from the font resource. This also */
- /* returns its metrics. */
- /* */
- /* <Input> */
- /* face :: */
- /* The target face object. */
- /* */
- /* strike_index :: */
- /* The strike index. */
- /* */
- /* glyph_index :: */
- /* The current glyph index. */
- /* */
- /* load_flags :: */
- /* The current load flags. */
- /* */
- /* stream :: */
- /* The input stream. */
- /* */
- /* <Output> */
- /* amap :: */
- /* The target pixmap. */
- /* */
- /* ametrics :: */
- /* A big sbit metrics structure for the glyph image. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. Returns an error if no */
- /* glyph sbit exists for the index. */
- /* */
- /* <Note> */
- /* The `map.buffer' field is always freed before the glyph is loaded. */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * TT_Load_SBit_Image_Func
+ *
+ * @description:
+ * Load a given glyph sbit image from the font resource. This also
+ * returns its metrics.
+ *
+ * @input:
+ * face ::
+ * The target face object.
+ *
+ * strike_index ::
+ * The strike index.
+ *
+ * glyph_index ::
+ * The current glyph index.
+ *
+ * load_flags ::
+ * The current load flags.
+ *
+ * stream ::
+ * The input stream.
+ *
+ * @output:
+ * amap ::
+ * The target pixmap.
+ *
+ * ametrics ::
+ * A big sbit metrics structure for the glyph image.
+ *
+ * @return:
+ * FreeType error code. 0 means success. Returns an error if no glyph
+ * sbit exists for the index.
+ *
+ * @note:
+ * The `map.buffer` field is always freed before the glyph is loaded.
+ */
typedef FT_Error
(*TT_Load_SBit_Image_Func)( TT_Face face,
FT_ULong strike_index,
@@ -296,130 +311,144 @@ FT_BEGIN_HEADER
TT_SBit_MetricsRec *ametrics );
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* TT_Set_SBit_Strike_Func */
- /* */
- /* <Description> */
- /* Select an sbit strike for a given size request. */
- /* */
- /* <Input> */
- /* face :: The target face object. */
- /* */
- /* req :: The size request. */
- /* */
- /* <Output> */
- /* astrike_index :: The index of the sbit strike. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. Returns an error if no */
- /* sbit strike exists for the selected ppem values. */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * TT_Set_SBit_Strike_Func
+ *
+ * @description:
+ * Select an sbit strike for a given size request.
+ *
+ * @input:
+ * face ::
+ * The target face object.
+ *
+ * req ::
+ * The size request.
+ *
+ * @output:
+ * astrike_index ::
+ * The index of the sbit strike.
+ *
+ * @return:
+ * FreeType error code. 0 means success. Returns an error if no sbit
+ * strike exists for the selected ppem values.
+ */
typedef FT_Error
(*TT_Set_SBit_Strike_Func)( TT_Face face,
FT_Size_Request req,
FT_ULong* astrike_index );
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* TT_Load_Strike_Metrics_Func */
- /* */
- /* <Description> */
- /* Load the metrics of a given strike. */
- /* */
- /* <Input> */
- /* face :: The target face object. */
- /* */
- /* strike_index :: The strike index. */
- /* */
- /* <Output> */
- /* metrics :: the metrics of the strike. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. Returns an error if no */
- /* such sbit strike exists. */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * TT_Load_Strike_Metrics_Func
+ *
+ * @description:
+ * Load the metrics of a given strike.
+ *
+ * @input:
+ * face ::
+ * The target face object.
+ *
+ * strike_index ::
+ * The strike index.
+ *
+ * @output:
+ * metrics ::
+ * the metrics of the strike.
+ *
+ * @return:
+ * FreeType error code. 0 means success. Returns an error if no such
+ * sbit strike exists.
+ */
typedef FT_Error
(*TT_Load_Strike_Metrics_Func)( TT_Face face,
FT_ULong strike_index,
FT_Size_Metrics* metrics );
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* TT_Get_PS_Name_Func */
- /* */
- /* <Description> */
- /* Get the PostScript glyph name of a glyph. */
- /* */
- /* <Input> */
- /* idx :: The glyph index. */
- /* */
- /* PSname :: The address of a string pointer. Will be NULL in case */
- /* of error, otherwise it is a pointer to the glyph name. */
- /* */
- /* You must not modify the returned string! */
- /* */
- /* <Output> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * TT_Get_PS_Name_Func
+ *
+ * @description:
+ * Get the PostScript glyph name of a glyph.
+ *
+ * @input:
+ * idx ::
+ * The glyph index.
+ *
+ * PSname ::
+ * The address of a string pointer. Will be `NULL` in case of error,
+ * otherwise it is a pointer to the glyph name.
+ *
+ * You must not modify the returned string!
+ *
+ * @output:
+ * FreeType error code. 0 means success.
+ */
typedef FT_Error
(*TT_Get_PS_Name_Func)( TT_Face face,
FT_UInt idx,
FT_String** PSname );
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* TT_Load_Metrics_Func */
- /* */
- /* <Description> */
- /* Load a metrics table, which is a table with a horizontal and a */
- /* vertical version. */
- /* */
- /* <Input> */
- /* face :: A handle to the target face object. */
- /* */
- /* stream :: The input stream. */
- /* */
- /* vertical :: A boolean flag. If set, load the vertical one. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * TT_Load_Metrics_Func
+ *
+ * @description:
+ * Load a metrics table, which is a table with a horizontal and a
+ * vertical version.
+ *
+ * @input:
+ * face ::
+ * A handle to the target face object.
+ *
+ * stream ::
+ * The input stream.
+ *
+ * vertical ::
+ * A boolean flag. If set, load the vertical one.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ */
typedef FT_Error
(*TT_Load_Metrics_Func)( TT_Face face,
FT_Stream stream,
FT_Bool vertical );
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* TT_Get_Metrics_Func */
- /* */
- /* <Description> */
- /* Load the horizontal or vertical header in a face object. */
- /* */
- /* <Input> */
- /* face :: A handle to the target face object. */
- /* */
- /* vertical :: A boolean flag. If set, load vertical metrics. */
- /* */
- /* gindex :: The glyph index. */
- /* */
- /* <Output> */
- /* abearing :: The horizontal (or vertical) bearing. Set to zero in */
- /* case of error. */
- /* */
- /* aadvance :: The horizontal (or vertical) advance. Set to zero in */
- /* case of error. */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * TT_Get_Metrics_Func
+ *
+ * @description:
+ * Load the horizontal or vertical header in a face object.
+ *
+ * @input:
+ * face ::
+ * A handle to the target face object.
+ *
+ * vertical ::
+ * A boolean flag. If set, load vertical metrics.
+ *
+ * gindex ::
+ * The glyph index.
+ *
+ * @output:
+ * abearing ::
+ * The horizontal (or vertical) bearing. Set to zero in case of error.
+ *
+ * aadvance ::
+ * The horizontal (or vertical) advance. Set to zero in case of error.
+ */
typedef void
(*TT_Get_Metrics_Func)( TT_Face face,
FT_Bool vertical,
@@ -428,57 +457,168 @@ FT_BEGIN_HEADER
FT_UShort* aadvance );
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* TT_Get_Name_Func */
- /* */
- /* <Description> */
- /* From the `name' table, return a given ENGLISH name record in */
- /* ASCII. */
- /* */
- /* <Input> */
- /* face :: A handle to the source face object. */
- /* */
- /* nameid :: The name id of the name record to return. */
- /* */
- /* <InOut> */
- /* name :: The address of an allocated string pointer. NULL if */
- /* no name is present. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * TT_Set_Palette_Func
+ *
+ * @description:
+ * Load the colors into `face->palette` for a given palette index.
+ *
+ * @input:
+ * face ::
+ * The target face object.
+ *
+ * idx ::
+ * The palette index.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ */
+ typedef FT_Error
+ (*TT_Set_Palette_Func)( TT_Face face,
+ FT_UInt idx );
+
+
+ /**************************************************************************
+ *
+ * @functype:
+ * TT_Get_Colr_Layer_Func
+ *
+ * @description:
+ * Iteratively get the color layer data of a given glyph index.
+ *
+ * @input:
+ * face ::
+ * The target face object.
+ *
+ * base_glyph ::
+ * The glyph index the colored glyph layers are associated with.
+ *
+ * @inout:
+ * iterator ::
+ * An @FT_LayerIterator object. For the first call you should set
+ * `iterator->p` to `NULL`. For all following calls, simply use the
+ * same object again.
+ *
+ * @output:
+ * aglyph_index ::
+ * The glyph index of the current layer.
+ *
+ * acolor_index ::
+ * The color index into the font face's color palette of the current
+ * layer. The value 0xFFFF is special; it doesn't reference a palette
+ * entry but indicates that the text foreground color should be used
+ * instead (to be set up by the application outside of FreeType).
+ *
+ * @return:
+ * Value~1 if everything is OK. If there are no more layers (or if there
+ * are no layers at all), value~0 gets returned. In case of an error,
+ * value~0 is returned also.
+ */
+ typedef FT_Bool
+ (*TT_Get_Colr_Layer_Func)( TT_Face face,
+ FT_UInt base_glyph,
+ FT_UInt *aglyph_index,
+ FT_UInt *acolor_index,
+ FT_LayerIterator* iterator );
+
+
+ /**************************************************************************
+ *
+ * @functype:
+ * TT_Blend_Colr_Func
+ *
+ * @description:
+ * Blend the bitmap in `new_glyph` into `base_glyph` using the color
+ * specified by `color_index`. If `color_index` is 0xFFFF, use
+ * `face->foreground_color` if `face->have_foreground_color` is set.
+ * Otherwise check `face->palette_data.palette_flags`: If present and
+ * @FT_PALETTE_FOR_DARK_BACKGROUND is set, use BGRA value 0xFFFFFFFF
+ * (white opaque). Otherwise use BGRA value 0x000000FF (black opaque).
+ *
+ * @input:
+ * face ::
+ * The target face object.
+ *
+ * color_index ::
+ * Color index from the COLR table.
+ *
+ * base_glyph ::
+ * Slot for bitmap to be merged into. The underlying bitmap may get
+ * reallocated.
+ *
+ * new_glyph ::
+ * Slot to be incooperated into `base_glyph`.
+ *
+ * @return:
+ * FreeType error code. 0 means success. Returns an error if
+ * color_index is invalid or reallocation fails.
+ */
+ typedef FT_Error
+ (*TT_Blend_Colr_Func)( TT_Face face,
+ FT_UInt color_index,
+ FT_GlyphSlot base_glyph,
+ FT_GlyphSlot new_glyph );
+
+
+ /**************************************************************************
+ *
+ * @functype:
+ * TT_Get_Name_Func
+ *
+ * @description:
+ * From the 'name' table, return a given ENGLISH name record in ASCII.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face object.
+ *
+ * nameid ::
+ * The name id of the name record to return.
+ *
+ * @inout:
+ * name ::
+ * The address of an allocated string pointer. `NULL` if no name is
+ * present.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ */
typedef FT_Error
(*TT_Get_Name_Func)( TT_Face face,
FT_UShort nameid,
FT_String** name );
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* TT_Get_Name_ID_Func */
- /* */
- /* <Description> */
- /* Search whether an ENGLISH version for a given name ID is in the */
- /* `name' table. */
- /* */
- /* <Input> */
- /* face :: A handle to the source face object. */
- /* */
- /* nameid :: The name id of the name record to return. */
- /* */
- /* <Out> */
- /* win :: If non-negative, an index into the `name' table with */
- /* the corresponding (3,1) or (3,0) Windows entry. */
- /* */
- /* apple :: If non-negative, an index into the `name' table with */
- /* the corresponding (1,0) Apple entry. */
- /* */
- /* <Return> */
- /* 1 if there is either a win or apple entry (or both), 0 otheriwse. */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * TT_Get_Name_ID_Func
+ *
+ * @description:
+ * Search whether an ENGLISH version for a given name ID is in the 'name'
+ * table.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face object.
+ *
+ * nameid ::
+ * The name id of the name record to return.
+ *
+ * @output:
+ * win ::
+ * If non-negative, an index into the 'name' table with the
+ * corresponding (3,1) or (3,0) Windows entry.
+ *
+ * apple ::
+ * If non-negative, an index into the 'name' table with the
+ * corresponding (1,0) Apple entry.
+ *
+ * @return:
+ * 1 if there is either a win or apple entry (or both), 0 otheriwse.
+ */
typedef FT_Bool
(*TT_Get_Name_ID_Func)( TT_Face face,
FT_UShort nameid,
@@ -486,42 +626,45 @@ FT_BEGIN_HEADER
FT_Int *apple );
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* TT_Load_Table_Func */
- /* */
- /* <Description> */
- /* Load a given TrueType table. */
- /* */
- /* <Input> */
- /* face :: A handle to the target face object. */
- /* */
- /* stream :: The input stream. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- /* <Note> */
- /* The function uses `face->goto_table' to seek the stream to the */
- /* start of the table, except while loading the font directory. */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * TT_Load_Table_Func
+ *
+ * @description:
+ * Load a given TrueType table.
+ *
+ * @input:
+ * face ::
+ * A handle to the target face object.
+ *
+ * stream ::
+ * The input stream.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * The function uses `face->goto_table` to seek the stream to the start
+ * of the table, except while loading the font directory.
+ */
typedef FT_Error
(*TT_Load_Table_Func)( TT_Face face,
FT_Stream stream );
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* TT_Free_Table_Func */
- /* */
- /* <Description> */
- /* Free a given TrueType table. */
- /* */
- /* <Input> */
- /* face :: A handle to the target face object. */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * TT_Free_Table_Func
+ *
+ * @description:
+ * Free a given TrueType table.
+ *
+ * @input:
+ * face ::
+ * A handle to the target face object.
+ */
typedef void
(*TT_Free_Table_Func)( TT_Face face );
@@ -534,9 +677,14 @@ FT_BEGIN_HEADER
* Return the horizontal kerning value between two glyphs.
*
* @input:
- * face :: A handle to the source face object.
- * left_glyph :: The left glyph index.
- * right_glyph :: The right glyph index.
+ * face ::
+ * A handle to the source face object.
+ *
+ * left_glyph ::
+ * The left glyph index.
+ *
+ * right_glyph ::
+ * The right glyph index.
*
* @return:
* The kerning value in font units.
@@ -547,18 +695,18 @@ FT_BEGIN_HEADER
FT_UInt right_glyph );
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* SFNT_Interface */
- /* */
- /* <Description> */
- /* This structure holds pointers to the functions used to load and */
- /* free the basic tables that are required in a `sfnt' font file. */
- /* */
- /* <Fields> */
- /* Check the various xxx_Func() descriptions for details. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * SFNT_Interface
+ *
+ * @description:
+ * This structure holds pointers to the functions used to load and free
+ * the basic tables that are required in a 'sfnt' font file.
+ *
+ * @fields:
+ * Check the various xxx_Func() descriptions for details.
+ */
typedef struct SFNT_Interface_
{
TT_Loader_GotoTableFunc goto_table;
@@ -616,6 +764,14 @@ FT_BEGIN_HEADER
TT_Set_SBit_Strike_Func set_sbit_strike;
TT_Load_Strike_Metrics_Func load_strike_metrics;
+ TT_Load_Table_Func load_cpal;
+ TT_Load_Table_Func load_colr;
+ TT_Free_Table_Func free_cpal;
+ TT_Free_Table_Func free_colr;
+ TT_Set_Palette_Func set_palette;
+ TT_Get_Colr_Layer_Func get_colr_layer;
+ TT_Blend_Colr_Func colr_blend;
+
TT_Get_Metrics_Func get_metrics;
TT_Get_Name_Func get_name;
@@ -627,7 +783,6 @@ FT_BEGIN_HEADER
/* transitional */
typedef SFNT_Interface* SFNT_Service;
-#ifndef FT_CONFIG_OPTION_PIC
#define FT_DEFINE_SFNT_INTERFACE( \
class_, \
@@ -659,6 +814,13 @@ FT_BEGIN_HEADER
free_eblc_, \
set_sbit_strike_, \
load_strike_metrics_, \
+ load_cpal_, \
+ load_colr_, \
+ free_cpal_, \
+ free_colr_, \
+ set_palette_, \
+ get_colr_layer_, \
+ colr_blend_, \
get_metrics_, \
get_name_, \
get_name_id_ ) \
@@ -692,89 +854,18 @@ FT_BEGIN_HEADER
free_eblc_, \
set_sbit_strike_, \
load_strike_metrics_, \
+ load_cpal_, \
+ load_colr_, \
+ free_cpal_, \
+ free_colr_, \
+ set_palette_, \
+ get_colr_layer_, \
+ colr_blend_, \
get_metrics_, \
get_name_, \
get_name_id_ \
};
-#else /* FT_CONFIG_OPTION_PIC */
-
-#define FT_INTERNAL( a, a_ ) \
- clazz->a = a_;
-
-#define FT_DEFINE_SFNT_INTERFACE( \
- class_, \
- goto_table_, \
- init_face_, \
- load_face_, \
- done_face_, \
- get_interface_, \
- load_any_, \
- load_head_, \
- load_hhea_, \
- load_cmap_, \
- load_maxp_, \
- load_os2_, \
- load_post_, \
- load_name_, \
- free_name_, \
- load_kern_, \
- load_gasp_, \
- load_pclt_, \
- load_bhed_, \
- load_sbit_image_, \
- get_psname_, \
- free_psnames_, \
- get_kerning_, \
- load_font_dir_, \
- load_hmtx_, \
- load_eblc_, \
- free_eblc_, \
- set_sbit_strike_, \
- load_strike_metrics_, \
- get_metrics_, \
- get_name_, \
- get_name_id_ ) \
- void \
- FT_Init_Class_ ## class_( FT_Library library, \
- SFNT_Interface* clazz ) \
- { \
- FT_UNUSED( library ); \
- \
- clazz->goto_table = goto_table_; \
- clazz->init_face = init_face_; \
- clazz->load_face = load_face_; \
- clazz->done_face = done_face_; \
- clazz->get_interface = get_interface_; \
- clazz->load_any = load_any_; \
- clazz->load_head = load_head_; \
- clazz->load_hhea = load_hhea_; \
- clazz->load_cmap = load_cmap_; \
- clazz->load_maxp = load_maxp_; \
- clazz->load_os2 = load_os2_; \
- clazz->load_post = load_post_; \
- clazz->load_name = load_name_; \
- clazz->free_name = free_name_; \
- clazz->load_kern = load_kern_; \
- clazz->load_gasp = load_gasp_; \
- clazz->load_pclt = load_pclt_; \
- clazz->load_bhed = load_bhed_; \
- clazz->load_sbit_image = load_sbit_image_; \
- clazz->get_psname = get_psname_; \
- clazz->free_psnames = free_psnames_; \
- clazz->get_kerning = get_kerning_; \
- clazz->load_font_dir = load_font_dir_; \
- clazz->load_hmtx = load_hmtx_; \
- clazz->load_eblc = load_eblc_; \
- clazz->free_eblc = free_eblc_; \
- clazz->set_sbit_strike = set_sbit_strike_; \
- clazz->load_strike_metrics = load_strike_metrics_; \
- clazz->get_metrics = get_metrics_; \
- clazz->get_name = get_name_; \
- clazz->get_name_id = get_name_id_; \
- }
-
-#endif /* FT_CONFIG_OPTION_PIC */
FT_END_HEADER
diff --git a/thirdparty/freetype/include/freetype/internal/t1types.h b/thirdparty/freetype/include/freetype/internal/t1types.h
index 2118e33674..e197a1afca 100644
--- a/thirdparty/freetype/include/freetype/internal/t1types.h
+++ b/thirdparty/freetype/include/freetype/internal/t1types.h
@@ -1,20 +1,20 @@
-/***************************************************************************/
-/* */
-/* t1types.h */
-/* */
-/* Basic Type1/Type2 type definitions and interface (specification */
-/* only). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * t1types.h
+ *
+ * Basic Type1/Type2 type definitions and interface (specification
+ * only).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef T1TYPES_H_
@@ -45,28 +45,31 @@ FT_BEGIN_HEADER
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* T1_EncodingRec */
- /* */
- /* <Description> */
- /* A structure modeling a custom encoding. */
- /* */
- /* <Fields> */
- /* num_chars :: The number of character codes in the encoding. */
- /* Usually 256. */
- /* */
- /* code_first :: The lowest valid character code in the encoding. */
- /* */
- /* code_last :: The highest valid character code in the encoding */
- /* + 1. When equal to code_first there are no valid */
- /* character codes. */
- /* */
- /* char_index :: An array of corresponding glyph indices. */
- /* */
- /* char_name :: An array of corresponding glyph names. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * T1_EncodingRec
+ *
+ * @description:
+ * A structure modeling a custom encoding.
+ *
+ * @fields:
+ * num_chars ::
+ * The number of character codes in the encoding. Usually 256.
+ *
+ * code_first ::
+ * The lowest valid character code in the encoding.
+ *
+ * code_last ::
+ * The highest valid character code in the encoding + 1. When equal to
+ * code_first there are no valid character codes.
+ *
+ * char_index ::
+ * An array of corresponding glyph indices.
+ *
+ * char_name ::
+ * An array of corresponding glyph names.
+ */
typedef struct T1_EncodingRecRec_
{
FT_Int num_chars;
diff --git a/thirdparty/freetype/include/freetype/internal/tttypes.h b/thirdparty/freetype/include/freetype/internal/tttypes.h
index 10dd336a89..5e9f40ec3f 100644
--- a/thirdparty/freetype/include/freetype/internal/tttypes.h
+++ b/thirdparty/freetype/include/freetype/internal/tttypes.h
@@ -1,20 +1,20 @@
-/***************************************************************************/
-/* */
-/* tttypes.h */
-/* */
-/* Basic SFNT/TrueType type definitions and interface (specification */
-/* only). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * tttypes.h
+ *
+ * Basic SFNT/TrueType type definitions and interface (specification
+ * only).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef TTTYPES_H_
@@ -24,6 +24,7 @@
#include <ft2build.h>
#include FT_TRUETYPE_TABLES_H
#include FT_INTERNAL_OBJECTS_H
+#include FT_COLOR_H
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
#include FT_MULTIPLE_MASTERS_H
@@ -46,27 +47,30 @@ FT_BEGIN_HEADER
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* TTC_HeaderRec */
- /* */
- /* <Description> */
- /* TrueType collection header. This table contains the offsets of */
- /* the font headers of each distinct TrueType face in the file. */
- /* */
- /* <Fields> */
- /* tag :: Must be `ttc ' to indicate a TrueType collection. */
- /* */
- /* version :: The version number. */
- /* */
- /* count :: The number of faces in the collection. The */
- /* specification says this should be an unsigned long, but */
- /* we use a signed long since we need the value -1 for */
- /* specific purposes. */
- /* */
- /* offsets :: The offsets of the font headers, one per face. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * TTC_HeaderRec
+ *
+ * @description:
+ * TrueType collection header. This table contains the offsets of the
+ * font headers of each distinct TrueType face in the file.
+ *
+ * @fields:
+ * tag ::
+ * Must be 'ttc~' to indicate a TrueType collection.
+ *
+ * version ::
+ * The version number.
+ *
+ * count ::
+ * The number of faces in the collection. The specification says this
+ * should be an unsigned long, but we use a signed long since we need
+ * the value -1 for specific purposes.
+ *
+ * offsets ::
+ * The offsets of the font headers, one per face.
+ */
typedef struct TTC_HeaderRec_
{
FT_ULong tag;
@@ -77,25 +81,30 @@ FT_BEGIN_HEADER
} TTC_HeaderRec;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* SFNT_HeaderRec */
- /* */
- /* <Description> */
- /* SFNT file format header. */
- /* */
- /* <Fields> */
- /* format_tag :: The font format tag. */
- /* */
- /* num_tables :: The number of tables in file. */
- /* */
- /* search_range :: Must be `16 * (max power of 2 <= num_tables)'. */
- /* */
- /* entry_selector :: Must be log2 of `search_range / 16'. */
- /* */
- /* range_shift :: Must be `num_tables * 16 - search_range'. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * SFNT_HeaderRec
+ *
+ * @description:
+ * SFNT file format header.
+ *
+ * @fields:
+ * format_tag ::
+ * The font format tag.
+ *
+ * num_tables ::
+ * The number of tables in file.
+ *
+ * search_range ::
+ * Must be '16 * (max power of 2 <= num_tables)'.
+ *
+ * entry_selector ::
+ * Must be log2 of 'search_range / 16'.
+ *
+ * range_shift ::
+ * Must be 'num_tables * 16 - search_range'.
+ */
typedef struct SFNT_HeaderRec_
{
FT_ULong format_tag;
@@ -109,24 +118,28 @@ FT_BEGIN_HEADER
} SFNT_HeaderRec, *SFNT_Header;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* TT_TableRec */
- /* */
- /* <Description> */
- /* This structure describes a given table of a TrueType font. */
- /* */
- /* <Fields> */
- /* Tag :: A four-bytes tag describing the table. */
- /* */
- /* CheckSum :: The table checksum. This value can be ignored. */
- /* */
- /* Offset :: The offset of the table from the start of the TrueType */
- /* font in its resource. */
- /* */
- /* Length :: The table length (in bytes). */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * TT_TableRec
+ *
+ * @description:
+ * This structure describes a given table of a TrueType font.
+ *
+ * @fields:
+ * Tag ::
+ * A four-bytes tag describing the table.
+ *
+ * CheckSum ::
+ * The table checksum. This value can be ignored.
+ *
+ * Offset ::
+ * The offset of the table from the start of the TrueType font in its
+ * resource.
+ *
+ * Length ::
+ * The table length (in bytes).
+ */
typedef struct TT_TableRec_
{
FT_ULong Tag; /* table type */
@@ -137,19 +150,19 @@ FT_BEGIN_HEADER
} TT_TableRec, *TT_Table;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* WOFF_HeaderRec */
- /* */
- /* <Description> */
- /* WOFF file format header. */
- /* */
- /* <Fields> */
- /* See */
- /* */
- /* https://www.w3.org/TR/WOFF/#WOFFHeader */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * WOFF_HeaderRec
+ *
+ * @description:
+ * WOFF file format header.
+ *
+ * @fields:
+ * See
+ *
+ * https://www.w3.org/TR/WOFF/#WOFFHeader
+ */
typedef struct WOFF_HeaderRec_
{
FT_ULong signature;
@@ -169,30 +182,36 @@ FT_BEGIN_HEADER
} WOFF_HeaderRec, *WOFF_Header;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* WOFF_TableRec */
- /* */
- /* <Description> */
- /* This structure describes a given table of a WOFF font. */
- /* */
- /* <Fields> */
- /* Tag :: A four-bytes tag describing the table. */
- /* */
- /* Offset :: The offset of the table from the start of the WOFF */
- /* font in its resource. */
- /* */
- /* CompLength :: Compressed table length (in bytes). */
- /* */
- /* OrigLength :: Uncompressed table length (in bytes). */
- /* */
- /* CheckSum :: The table checksum. This value can be ignored. */
- /* */
- /* OrigOffset :: The uncompressed table file offset. This value gets */
- /* computed while constructing the (uncompressed) SFNT */
- /* header. It is not contained in the WOFF file. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * WOFF_TableRec
+ *
+ * @description:
+ * This structure describes a given table of a WOFF font.
+ *
+ * @fields:
+ * Tag ::
+ * A four-bytes tag describing the table.
+ *
+ * Offset ::
+ * The offset of the table from the start of the WOFF font in its
+ * resource.
+ *
+ * CompLength ::
+ * Compressed table length (in bytes).
+ *
+ * OrigLength ::
+ * Uncompressed table length (in bytes).
+ *
+ * CheckSum ::
+ * The table checksum. This value can be ignored.
+ *
+ * OrigOffset ::
+ * The uncompressed table file offset. This value gets computed while
+ * constructing the (uncompressed) SFNT header. It is not contained in
+ * the WOFF file.
+ */
typedef struct WOFF_TableRec_
{
FT_ULong Tag; /* table ID */
@@ -206,20 +225,22 @@ FT_BEGIN_HEADER
} WOFF_TableRec, *WOFF_Table;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* TT_LongMetricsRec */
- /* */
- /* <Description> */
- /* A structure modeling the long metrics of the `hmtx' and `vmtx' */
- /* TrueType tables. The values are expressed in font units. */
- /* */
- /* <Fields> */
- /* advance :: The advance width or height for the glyph. */
- /* */
- /* bearing :: The left-side or top-side bearing for the glyph. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * TT_LongMetricsRec
+ *
+ * @description:
+ * A structure modeling the long metrics of the 'hmtx' and 'vmtx'
+ * TrueType tables. The values are expressed in font units.
+ *
+ * @fields:
+ * advance ::
+ * The advance width or height for the glyph.
+ *
+ * bearing ::
+ * The left-side or top-side bearing for the glyph.
+ */
typedef struct TT_LongMetricsRec_
{
FT_UShort advance;
@@ -228,45 +249,51 @@ FT_BEGIN_HEADER
} TT_LongMetricsRec, *TT_LongMetrics;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* TT_ShortMetrics */
- /* */
- /* <Description> */
- /* A simple type to model the short metrics of the `hmtx' and `vmtx' */
- /* tables. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * TT_ShortMetrics
+ *
+ * @description:
+ * A simple type to model the short metrics of the 'hmtx' and 'vmtx'
+ * tables.
+ */
typedef FT_Short TT_ShortMetrics;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* TT_NameRec */
- /* */
- /* <Description> */
- /* A structure modeling TrueType name records. Name records are used */
- /* to store important strings like family name, style name, */
- /* copyright, etc. in _localized_ versions (i.e., language, encoding, */
- /* etc). */
- /* */
- /* <Fields> */
- /* platformID :: The ID of the name's encoding platform. */
- /* */
- /* encodingID :: The platform-specific ID for the name's encoding. */
- /* */
- /* languageID :: The platform-specific ID for the name's language. */
- /* */
- /* nameID :: The ID specifying what kind of name this is. */
- /* */
- /* stringLength :: The length of the string in bytes. */
- /* */
- /* stringOffset :: The offset to the string in the `name' table. */
- /* */
- /* string :: A pointer to the string's bytes. Note that these */
- /* are usually UTF-16 encoded characters. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * TT_NameRec
+ *
+ * @description:
+ * A structure modeling TrueType name records. Name records are used to
+ * store important strings like family name, style name, copyright,
+ * etc. in _localized_ versions (i.e., language, encoding, etc).
+ *
+ * @fields:
+ * platformID ::
+ * The ID of the name's encoding platform.
+ *
+ * encodingID ::
+ * The platform-specific ID for the name's encoding.
+ *
+ * languageID ::
+ * The platform-specific ID for the name's language.
+ *
+ * nameID ::
+ * The ID specifying what kind of name this is.
+ *
+ * stringLength ::
+ * The length of the string in bytes.
+ *
+ * stringOffset ::
+ * The offset to the string in the 'name' table.
+ *
+ * string ::
+ * A pointer to the string's bytes. Note that these are usually UTF-16
+ * encoded characters.
+ */
typedef struct TT_NameRec_
{
FT_UShort platformID;
@@ -284,23 +311,26 @@ FT_BEGIN_HEADER
} TT_NameRec, *TT_Name;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* TT_LangTagRec */
- /* */
- /* <Description> */
- /* A structure modeling language tag records in SFNT `name' tables, */
- /* introduced in OpenType version 1.6. */
- /* */
- /* <Fields> */
- /* stringLength :: The length of the string in bytes. */
- /* */
- /* stringOffset :: The offset to the string in the `name' table. */
- /* */
- /* string :: A pointer to the string's bytes. Note that these */
- /* are UTF-16BE encoded characters. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * TT_LangTagRec
+ *
+ * @description:
+ * A structure modeling language tag records in SFNT 'name' tables,
+ * introduced in OpenType version 1.6.
+ *
+ * @fields:
+ * stringLength ::
+ * The length of the string in bytes.
+ *
+ * stringOffset ::
+ * The offset to the string in the 'name' table.
+ *
+ * string ::
+ * A pointer to the string's bytes. Note that these are UTF-16BE
+ * encoded characters.
+ */
typedef struct TT_LangTagRec_
{
FT_UShort stringLength;
@@ -314,30 +344,36 @@ FT_BEGIN_HEADER
} TT_LangTagRec, *TT_LangTag;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* TT_NameTableRec */
- /* */
- /* <Description> */
- /* A structure modeling the TrueType name table. */
- /* */
- /* <Fields> */
- /* format :: The format of the name table. */
- /* */
- /* numNameRecords :: The number of names in table. */
- /* */
- /* storageOffset :: The offset of the name table in the `name' */
- /* TrueType table. */
- /* */
- /* names :: An array of name records. */
- /* */
- /* numLangTagRecords :: The number of language tags in table. */
- /* */
- /* langTags :: An array of language tag records. */
- /* */
- /* stream :: The file's input stream. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * TT_NameTableRec
+ *
+ * @description:
+ * A structure modeling the TrueType name table.
+ *
+ * @fields:
+ * format ::
+ * The format of the name table.
+ *
+ * numNameRecords ::
+ * The number of names in table.
+ *
+ * storageOffset ::
+ * The offset of the name table in the 'name' TrueType table.
+ *
+ * names ::
+ * An array of name records.
+ *
+ * numLangTagRecords ::
+ * The number of language tags in table.
+ *
+ * langTags ::
+ * An array of language tag records.
+ *
+ * stream ::
+ * The file's input stream.
+ */
typedef struct TT_NameTableRec_
{
FT_UShort format;
@@ -364,21 +400,23 @@ FT_BEGIN_HEADER
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* TT_GaspRangeRec */
- /* */
- /* <Description> */
- /* A tiny structure used to model a gasp range according to the */
- /* TrueType specification. */
- /* */
- /* <Fields> */
- /* maxPPEM :: The maximum ppem value to which `gaspFlag' applies. */
- /* */
- /* gaspFlag :: A flag describing the grid-fitting and anti-aliasing */
- /* modes to be used. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * TT_GaspRangeRec
+ *
+ * @description:
+ * A tiny structure used to model a gasp range according to the TrueType
+ * specification.
+ *
+ * @fields:
+ * maxPPEM ::
+ * The maximum ppem value to which `gaspFlag` applies.
+ *
+ * gaspFlag ::
+ * A flag describing the grid-fitting and anti-aliasing modes to be
+ * used.
+ */
typedef struct TT_GaspRangeRec_
{
FT_UShort maxPPEM;
@@ -391,22 +429,25 @@ FT_BEGIN_HEADER
#define TT_GASP_DOGRAY 0x02
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* TT_GaspRec */
- /* */
- /* <Description> */
- /* A structure modeling the TrueType `gasp' table used to specify */
- /* grid-fitting and anti-aliasing behaviour. */
- /* */
- /* <Fields> */
- /* version :: The version number. */
- /* */
- /* numRanges :: The number of gasp ranges in table. */
- /* */
- /* gaspRanges :: An array of gasp ranges. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * TT_GaspRec
+ *
+ * @description:
+ * A structure modeling the TrueType 'gasp' table used to specify
+ * grid-fitting and anti-aliasing behaviour.
+ *
+ * @fields:
+ * version ::
+ * The version number.
+ *
+ * numRanges ::
+ * The number of gasp ranges in table.
+ *
+ * gaspRanges ::
+ * An array of gasp ranges.
+ */
typedef struct TT_Gasp_
{
FT_UShort version;
@@ -429,33 +470,41 @@ FT_BEGIN_HEADER
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* TT_SBit_MetricsRec */
- /* */
- /* <Description> */
- /* A structure used to hold the big metrics of a given glyph bitmap */
- /* in a TrueType or OpenType font. These are usually found in the */
- /* `EBDT' (Microsoft) or `bloc' (Apple) table. */
- /* */
- /* <Fields> */
- /* height :: The glyph height in pixels. */
- /* */
- /* width :: The glyph width in pixels. */
- /* */
- /* horiBearingX :: The horizontal left bearing. */
- /* */
- /* horiBearingY :: The horizontal top bearing. */
- /* */
- /* horiAdvance :: The horizontal advance. */
- /* */
- /* vertBearingX :: The vertical left bearing. */
- /* */
- /* vertBearingY :: The vertical top bearing. */
- /* */
- /* vertAdvance :: The vertical advance. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * TT_SBit_MetricsRec
+ *
+ * @description:
+ * A structure used to hold the big metrics of a given glyph bitmap in a
+ * TrueType or OpenType font. These are usually found in the 'EBDT'
+ * (Microsoft) or 'bloc' (Apple) table.
+ *
+ * @fields:
+ * height ::
+ * The glyph height in pixels.
+ *
+ * width ::
+ * The glyph width in pixels.
+ *
+ * horiBearingX ::
+ * The horizontal left bearing.
+ *
+ * horiBearingY ::
+ * The horizontal top bearing.
+ *
+ * horiAdvance ::
+ * The horizontal advance.
+ *
+ * vertBearingX ::
+ * The vertical left bearing.
+ *
+ * vertBearingY ::
+ * The vertical top bearing.
+ *
+ * vertAdvance ::
+ * The vertical advance.
+ */
typedef struct TT_SBit_MetricsRec_
{
FT_UShort height;
@@ -472,27 +521,32 @@ FT_BEGIN_HEADER
} TT_SBit_MetricsRec, *TT_SBit_Metrics;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* TT_SBit_SmallMetricsRec */
- /* */
- /* <Description> */
- /* A structure used to hold the small metrics of a given glyph bitmap */
- /* in a TrueType or OpenType font. These are usually found in the */
- /* `EBDT' (Microsoft) or the `bdat' (Apple) table. */
- /* */
- /* <Fields> */
- /* height :: The glyph height in pixels. */
- /* */
- /* width :: The glyph width in pixels. */
- /* */
- /* bearingX :: The left-side bearing. */
- /* */
- /* bearingY :: The top-side bearing. */
- /* */
- /* advance :: The advance width or height. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * TT_SBit_SmallMetricsRec
+ *
+ * @description:
+ * A structure used to hold the small metrics of a given glyph bitmap in
+ * a TrueType or OpenType font. These are usually found in the 'EBDT'
+ * (Microsoft) or the 'bdat' (Apple) table.
+ *
+ * @fields:
+ * height ::
+ * The glyph height in pixels.
+ *
+ * width ::
+ * The glyph width in pixels.
+ *
+ * bearingX ::
+ * The left-side bearing.
+ *
+ * bearingY ::
+ * The top-side bearing.
+ *
+ * advance ::
+ * The advance width or height.
+ */
typedef struct TT_SBit_Small_Metrics_
{
FT_Byte height;
@@ -505,57 +559,60 @@ FT_BEGIN_HEADER
} TT_SBit_SmallMetricsRec, *TT_SBit_SmallMetrics;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* TT_SBit_LineMetricsRec */
- /* */
- /* <Description> */
- /* A structure used to describe the text line metrics of a given */
- /* bitmap strike, for either a horizontal or vertical layout. */
- /* */
- /* <Fields> */
- /* ascender :: The ascender in pixels. */
- /* */
- /* descender :: The descender in pixels. */
- /* */
- /* max_width :: The maximum glyph width in pixels. */
- /* */
- /* caret_slope_enumerator :: Rise of the caret slope, typically set */
- /* to 1 for non-italic fonts. */
- /* */
- /* caret_slope_denominator :: Rise of the caret slope, typically set */
- /* to 0 for non-italic fonts. */
- /* */
- /* caret_offset :: Offset in pixels to move the caret for */
- /* proper positioning. */
- /* */
- /* min_origin_SB :: Minimum of horiBearingX (resp. */
- /* vertBearingY). */
- /* min_advance_SB :: Minimum of */
- /* */
- /* horizontal advance - */
- /* ( horiBearingX + width ) */
- /* */
- /* resp. */
- /* */
- /* vertical advance - */
- /* ( vertBearingY + height ) */
- /* */
- /* max_before_BL :: Maximum of horiBearingY (resp. */
- /* vertBearingY). */
- /* */
- /* min_after_BL :: Minimum of */
- /* */
- /* horiBearingY - height */
- /* */
- /* resp. */
- /* */
- /* vertBearingX - width */
- /* */
- /* pads :: Unused (to make the size of the record */
- /* a multiple of 32 bits. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * TT_SBit_LineMetricsRec
+ *
+ * @description:
+ * A structure used to describe the text line metrics of a given bitmap
+ * strike, for either a horizontal or vertical layout.
+ *
+ * @fields:
+ * ascender ::
+ * The ascender in pixels.
+ *
+ * descender ::
+ * The descender in pixels.
+ *
+ * max_width ::
+ * The maximum glyph width in pixels.
+ *
+ * caret_slope_enumerator ::
+ * Rise of the caret slope, typically set to 1 for non-italic fonts.
+ *
+ * caret_slope_denominator ::
+ * Rise of the caret slope, typically set to 0 for non-italic fonts.
+ *
+ * caret_offset ::
+ * Offset in pixels to move the caret for proper positioning.
+ *
+ * min_origin_SB ::
+ * Minimum of horiBearingX (resp. vertBearingY).
+ * min_advance_SB ::
+ * Minimum of
+ *
+ * horizontal advance - ( horiBearingX + width )
+ *
+ * resp.
+ *
+ * vertical advance - ( vertBearingY + height )
+ *
+ * max_before_BL ::
+ * Maximum of horiBearingY (resp. vertBearingY).
+ *
+ * min_after_BL ::
+ * Minimum of
+ *
+ * horiBearingY - height
+ *
+ * resp.
+ *
+ * vertBearingX - width
+ *
+ * pads ::
+ * Unused (to make the size of the record a multiple of 32 bits.
+ */
typedef struct TT_SBit_LineMetricsRec_
{
FT_Char ascender;
@@ -573,43 +630,53 @@ FT_BEGIN_HEADER
} TT_SBit_LineMetricsRec, *TT_SBit_LineMetrics;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* TT_SBit_RangeRec */
- /* */
- /* <Description> */
- /* A TrueType/OpenType subIndexTable as defined in the `EBLC' */
- /* (Microsoft) or `bloc' (Apple) tables. */
- /* */
- /* <Fields> */
- /* first_glyph :: The first glyph index in the range. */
- /* */
- /* last_glyph :: The last glyph index in the range. */
- /* */
- /* index_format :: The format of index table. Valid values are 1 */
- /* to 5. */
- /* */
- /* image_format :: The format of `EBDT' image data. */
- /* */
- /* image_offset :: The offset to image data in `EBDT'. */
- /* */
- /* image_size :: For index formats 2 and 5. This is the size in */
- /* bytes of each glyph bitmap. */
- /* */
- /* big_metrics :: For index formats 2 and 5. This is the big */
- /* metrics for each glyph bitmap. */
- /* */
- /* num_glyphs :: For index formats 4 and 5. This is the number of */
- /* glyphs in the code array. */
- /* */
- /* glyph_offsets :: For index formats 1 and 3. */
- /* */
- /* glyph_codes :: For index formats 4 and 5. */
- /* */
- /* table_offset :: The offset of the index table in the `EBLC' */
- /* table. Only used during strike loading. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * TT_SBit_RangeRec
+ *
+ * @description:
+ * A TrueType/OpenType subIndexTable as defined in the 'EBLC' (Microsoft)
+ * or 'bloc' (Apple) tables.
+ *
+ * @fields:
+ * first_glyph ::
+ * The first glyph index in the range.
+ *
+ * last_glyph ::
+ * The last glyph index in the range.
+ *
+ * index_format ::
+ * The format of index table. Valid values are 1 to 5.
+ *
+ * image_format ::
+ * The format of 'EBDT' image data.
+ *
+ * image_offset ::
+ * The offset to image data in 'EBDT'.
+ *
+ * image_size ::
+ * For index formats 2 and 5. This is the size in bytes of each glyph
+ * bitmap.
+ *
+ * big_metrics ::
+ * For index formats 2 and 5. This is the big metrics for each glyph
+ * bitmap.
+ *
+ * num_glyphs ::
+ * For index formats 4 and 5. This is the number of glyphs in the code
+ * array.
+ *
+ * glyph_offsets ::
+ * For index formats 1 and 3.
+ *
+ * glyph_codes ::
+ * For index formats 4 and 5.
+ *
+ * table_offset ::
+ * The offset of the index table in the 'EBLC' table. Only used during
+ * strike loading.
+ */
typedef struct TT_SBit_RangeRec_
{
FT_UShort first_glyph;
@@ -631,47 +698,55 @@ FT_BEGIN_HEADER
} TT_SBit_RangeRec, *TT_SBit_Range;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* TT_SBit_StrikeRec */
- /* */
- /* <Description> */
- /* A structure used describe a given bitmap strike in the `EBLC' */
- /* (Microsoft) or `bloc' (Apple) tables. */
- /* */
- /* <Fields> */
- /* num_index_ranges :: The number of index ranges. */
- /* */
- /* index_ranges :: An array of glyph index ranges. */
- /* */
- /* color_ref :: Unused. `color_ref' is put in for future */
- /* enhancements, but these fields are already */
- /* in use by other platforms (e.g. Newton). */
- /* For details, please see */
- /* */
- /* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6bloc.html */
- /* */
- /* hori :: The line metrics for horizontal layouts. */
- /* */
- /* vert :: The line metrics for vertical layouts. */
- /* */
- /* start_glyph :: The lowest glyph index for this strike. */
- /* */
- /* end_glyph :: The highest glyph index for this strike. */
- /* */
- /* x_ppem :: The number of horizontal pixels per EM. */
- /* */
- /* y_ppem :: The number of vertical pixels per EM. */
- /* */
- /* bit_depth :: The bit depth. Valid values are 1, 2, 4, */
- /* and 8. */
- /* */
- /* flags :: Is this a vertical or horizontal strike? For */
- /* details, please see */
- /* */
- /* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6bloc.html */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * TT_SBit_StrikeRec
+ *
+ * @description:
+ * A structure used describe a given bitmap strike in the 'EBLC'
+ * (Microsoft) or 'bloc' (Apple) tables.
+ *
+ * @fields:
+ * num_index_ranges ::
+ * The number of index ranges.
+ *
+ * index_ranges ::
+ * An array of glyph index ranges.
+ *
+ * color_ref ::
+ * Unused. `color_ref` is put in for future enhancements, but these
+ * fields are already in use by other platforms (e.g. Newton). For
+ * details, please see
+ *
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6bloc.html
+ *
+ * hori ::
+ * The line metrics for horizontal layouts.
+ *
+ * vert ::
+ * The line metrics for vertical layouts.
+ *
+ * start_glyph ::
+ * The lowest glyph index for this strike.
+ *
+ * end_glyph ::
+ * The highest glyph index for this strike.
+ *
+ * x_ppem ::
+ * The number of horizontal pixels per EM.
+ *
+ * y_ppem ::
+ * The number of vertical pixels per EM.
+ *
+ * bit_depth ::
+ * The bit depth. Valid values are 1, 2, 4, and 8.
+ *
+ * flags ::
+ * Is this a vertical or horizontal strike? For details, please see
+ *
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6bloc.html
+ */
typedef struct TT_SBit_StrikeRec_
{
FT_Int num_ranges;
@@ -695,21 +770,24 @@ FT_BEGIN_HEADER
} TT_SBit_StrikeRec, *TT_SBit_Strike;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* TT_SBit_ComponentRec */
- /* */
- /* <Description> */
- /* A simple structure to describe a compound sbit element. */
- /* */
- /* <Fields> */
- /* glyph_code :: The element's glyph index. */
- /* */
- /* x_offset :: The element's left bearing. */
- /* */
- /* y_offset :: The element's top bearing. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * TT_SBit_ComponentRec
+ *
+ * @description:
+ * A simple structure to describe a compound sbit element.
+ *
+ * @fields:
+ * glyph_code ::
+ * The element's glyph index.
+ *
+ * x_offset ::
+ * The element's left bearing.
+ *
+ * y_offset ::
+ * The element's top bearing.
+ */
typedef struct TT_SBit_ComponentRec_
{
FT_UShort glyph_code;
@@ -719,28 +797,34 @@ FT_BEGIN_HEADER
} TT_SBit_ComponentRec, *TT_SBit_Component;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* TT_SBit_ScaleRec */
- /* */
- /* <Description> */
- /* A structure used describe a given bitmap scaling table, as defined */
- /* in the `EBSC' table. */
- /* */
- /* <Fields> */
- /* hori :: The horizontal line metrics. */
- /* */
- /* vert :: The vertical line metrics. */
- /* */
- /* x_ppem :: The number of horizontal pixels per EM. */
- /* */
- /* y_ppem :: The number of vertical pixels per EM. */
- /* */
- /* x_ppem_substitute :: Substitution x_ppem value. */
- /* */
- /* y_ppem_substitute :: Substitution y_ppem value. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * TT_SBit_ScaleRec
+ *
+ * @description:
+ * A structure used describe a given bitmap scaling table, as defined in
+ * the 'EBSC' table.
+ *
+ * @fields:
+ * hori ::
+ * The horizontal line metrics.
+ *
+ * vert ::
+ * The vertical line metrics.
+ *
+ * x_ppem ::
+ * The number of horizontal pixels per EM.
+ *
+ * y_ppem ::
+ * The number of vertical pixels per EM.
+ *
+ * x_ppem_substitute ::
+ * Substitution x_ppem value.
+ *
+ * y_ppem_substitute ::
+ * Substitution y_ppem value.
+ */
typedef struct TT_SBit_ScaleRec_
{
TT_SBit_LineMetricsRec hori;
@@ -768,24 +852,28 @@ FT_BEGIN_HEADER
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* TT_Post_20Rec */
- /* */
- /* <Description> */
- /* Postscript names sub-table, format 2.0. Stores the PS name of */
- /* each glyph in the font face. */
- /* */
- /* <Fields> */
- /* num_glyphs :: The number of named glyphs in the table. */
- /* */
- /* num_names :: The number of PS names stored in the table. */
- /* */
- /* glyph_indices :: The indices of the glyphs in the names arrays. */
- /* */
- /* glyph_names :: The PS names not in Mac Encoding. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * TT_Post_20Rec
+ *
+ * @description:
+ * Postscript names sub-table, format 2.0. Stores the PS name of each
+ * glyph in the font face.
+ *
+ * @fields:
+ * num_glyphs ::
+ * The number of named glyphs in the table.
+ *
+ * num_names ::
+ * The number of PS names stored in the table.
+ *
+ * glyph_indices ::
+ * The indices of the glyphs in the names arrays.
+ *
+ * glyph_names ::
+ * The PS names not in Mac Encoding.
+ */
typedef struct TT_Post_20Rec_
{
FT_UShort num_glyphs;
@@ -796,21 +884,22 @@ FT_BEGIN_HEADER
} TT_Post_20Rec, *TT_Post_20;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* TT_Post_25Rec */
- /* */
- /* <Description> */
- /* Postscript names sub-table, format 2.5. Stores the PS name of */
- /* each glyph in the font face. */
- /* */
- /* <Fields> */
- /* num_glyphs :: The number of glyphs in the table. */
- /* */
- /* offsets :: An array of signed offsets in a normal Mac */
- /* Postscript name encoding. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * TT_Post_25Rec
+ *
+ * @description:
+ * Postscript names sub-table, format 2.5. Stores the PS name of each
+ * glyph in the font face.
+ *
+ * @fields:
+ * num_glyphs ::
+ * The number of glyphs in the table.
+ *
+ * offsets ::
+ * An array of signed offsets in a normal Mac Postscript name encoding.
+ */
typedef struct TT_Post_25_
{
FT_UShort num_glyphs;
@@ -819,21 +908,24 @@ FT_BEGIN_HEADER
} TT_Post_25Rec, *TT_Post_25;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* TT_Post_NamesRec */
- /* */
- /* <Description> */
- /* Postscript names table, either format 2.0 or 2.5. */
- /* */
- /* <Fields> */
- /* loaded :: A flag to indicate whether the PS names are loaded. */
- /* */
- /* format_20 :: The sub-table used for format 2.0. */
- /* */
- /* format_25 :: The sub-table used for format 2.5. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * TT_Post_NamesRec
+ *
+ * @description:
+ * Postscript names table, either format 2.0 or 2.5.
+ *
+ * @fields:
+ * loaded ::
+ * A flag to indicate whether the PS names are loaded.
+ *
+ * format_20 ::
+ * The sub-table used for format 2.0.
+ *
+ * format_25 ::
+ * The sub-table used for format 2.5.
+ */
typedef struct TT_Post_NamesRec_
{
FT_Bool loaded;
@@ -879,25 +971,25 @@ FT_BEGIN_HEADER
/*
* These types are used to support a `BDF ' table that isn't part of the
- * official TrueType specification. It is mainly used in SFNT-based
- * bitmap fonts that were generated from a set of BDF fonts.
+ * official TrueType specification. It is mainly used in SFNT-based bitmap
+ * fonts that were generated from a set of BDF fonts.
*
* The format of the table is as follows.
*
- * USHORT version `BDF ' table version number, should be 0x0001.
- * USHORT strikeCount Number of strikes (bitmap sizes) in this table.
- * ULONG stringTable Offset (from start of BDF table) to string
+ * USHORT version `BDF ' table version number, should be 0x0001. USHORT
+ * strikeCount Number of strikes (bitmap sizes) in this table. ULONG
+ * stringTable Offset (from start of BDF table) to string
* table.
*
* This is followed by an array of `strikeCount' descriptors, having the
* following format.
*
- * USHORT ppem Vertical pixels per EM for this strike.
- * USHORT numItems Number of items for this strike (properties and
+ * USHORT ppem Vertical pixels per EM for this strike. USHORT numItems
+ * Number of items for this strike (properties and
* atoms). Maximum is 255.
*
- * This array in turn is followed by `strikeCount' value sets. Each
- * `value set' is an array of `numItems' items with the following format.
+ * This array in turn is followed by `strikeCount' value sets. Each `value
+ * set' is an array of `numItems' items with the following format.
*
* ULONG item_name Offset in string table to item name.
* USHORT item_type The item type. Possible values are
@@ -945,31 +1037,30 @@ FT_BEGIN_HEADER
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* This structure/class is defined here because it is common to the */
- /* following formats: TTF, OpenType-TT, and OpenType-CFF. */
- /* */
- /* Note, however, that the classes TT_Size and TT_GlyphSlot are not */
- /* shared between font drivers, and are thus defined in `ttobjs.h'. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * This structure/class is defined here because it is common to the
+ * following formats: TTF, OpenType-TT, and OpenType-CFF.
+ *
+ * Note, however, that the classes TT_Size and TT_GlyphSlot are not shared
+ * between font drivers, and are thus defined in `ttobjs.h`.
+ *
+ */
- /*************************************************************************/
- /* */
- /* <Type> */
- /* TT_Face */
- /* */
- /* <Description> */
- /* A handle to a TrueType face/font object. A TT_Face encapsulates */
- /* the resolution and scaling independent parts of a TrueType font */
- /* resource. */
- /* */
- /* <Note> */
- /* The TT_Face structure is also used as a `parent class' for the */
- /* OpenType-CFF class (T2_Face). */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * TT_Face
+ *
+ * @description:
+ * A handle to a TrueType face/font object. A TT_Face encapsulates the
+ * resolution and scaling independent parts of a TrueType font resource.
+ *
+ * @note:
+ * The TT_Face structure is also used as a 'parent class' for the
+ * OpenType-CFF class (T2_Face).
+ */
typedef struct TT_FaceRec_* TT_Face;
@@ -981,31 +1072,34 @@ FT_BEGIN_HEADER
typedef struct TT_LoaderRec_* TT_Loader;
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* TT_Loader_GotoTableFunc */
- /* */
- /* <Description> */
- /* Seeks a stream to the start of a given TrueType table. */
- /* */
- /* <Input> */
- /* face :: A handle to the target face object. */
- /* */
- /* tag :: A 4-byte tag used to name the table. */
- /* */
- /* stream :: The input stream. */
- /* */
- /* <Output> */
- /* length :: The length of the table in bytes. Set to 0 if not */
- /* needed. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- /* <Note> */
- /* The stream cursor must be at the font file's origin. */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * TT_Loader_GotoTableFunc
+ *
+ * @description:
+ * Seeks a stream to the start of a given TrueType table.
+ *
+ * @input:
+ * face ::
+ * A handle to the target face object.
+ *
+ * tag ::
+ * A 4-byte tag used to name the table.
+ *
+ * stream ::
+ * The input stream.
+ *
+ * @output:
+ * length ::
+ * The length of the table in bytes. Set to 0 if not needed.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * The stream cursor must be at the font file's origin.
+ */
typedef FT_Error
(*TT_Loader_GotoTableFunc)( TT_Face face,
FT_ULong tag,
@@ -1013,34 +1107,36 @@ FT_BEGIN_HEADER
FT_ULong* length );
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* TT_Loader_StartGlyphFunc */
- /* */
- /* <Description> */
- /* Seeks a stream to the start of a given glyph element, and opens a */
- /* frame for it. */
- /* */
- /* <Input> */
- /* loader :: The current TrueType glyph loader object. */
- /* */
- /* glyph index :: The index of the glyph to access. */
- /* */
- /* offset :: The offset of the glyph according to the */
- /* `locations' table. */
- /* */
- /* byte_count :: The size of the frame in bytes. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- /* <Note> */
- /* This function is normally equivalent to FT_STREAM_SEEK(offset) */
- /* followed by FT_FRAME_ENTER(byte_count) with the loader's stream, */
- /* but alternative formats (e.g. compressed ones) might use something */
- /* different. */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * TT_Loader_StartGlyphFunc
+ *
+ * @description:
+ * Seeks a stream to the start of a given glyph element, and opens a
+ * frame for it.
+ *
+ * @input:
+ * loader ::
+ * The current TrueType glyph loader object.
+ *
+ * glyph index :: The index of the glyph to access.
+ *
+ * offset ::
+ * The offset of the glyph according to the 'locations' table.
+ *
+ * byte_count ::
+ * The size of the frame in bytes.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * This function is normally equivalent to FT_STREAM_SEEK(offset)
+ * followed by FT_FRAME_ENTER(byte_count) with the loader's stream, but
+ * alternative formats (e.g. compressed ones) might use something
+ * different.
+ */
typedef FT_Error
(*TT_Loader_StartGlyphFunc)( TT_Loader loader,
FT_UInt glyph_index,
@@ -1048,36 +1144,38 @@ FT_BEGIN_HEADER
FT_UInt byte_count );
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* TT_Loader_ReadGlyphFunc */
- /* */
- /* <Description> */
- /* Reads one glyph element (its header, a simple glyph, or a */
- /* composite) from the loader's current stream frame. */
- /* */
- /* <Input> */
- /* loader :: The current TrueType glyph loader object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * TT_Loader_ReadGlyphFunc
+ *
+ * @description:
+ * Reads one glyph element (its header, a simple glyph, or a composite)
+ * from the loader's current stream frame.
+ *
+ * @input:
+ * loader ::
+ * The current TrueType glyph loader object.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ */
typedef FT_Error
(*TT_Loader_ReadGlyphFunc)( TT_Loader loader );
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* TT_Loader_EndGlyphFunc */
- /* */
- /* <Description> */
- /* Closes the current loader stream frame for the glyph. */
- /* */
- /* <Input> */
- /* loader :: The current TrueType glyph loader object. */
- /* */
+ /**************************************************************************
+ *
+ * @functype:
+ * TT_Loader_EndGlyphFunc
+ *
+ * @description:
+ * Closes the current loader stream frame for the glyph.
+ *
+ * @input:
+ * loader ::
+ * The current TrueType glyph loader object.
+ */
typedef void
(*TT_Loader_EndGlyphFunc)( TT_Loader loader );
@@ -1124,270 +1222,317 @@ FT_BEGIN_HEADER
#define TT_FACE_FLAG_VAR_MVAR ( 1 << 8 )
- /*************************************************************************/
- /* */
- /* TrueType Face Type */
- /* */
- /* <Struct> */
- /* TT_Face */
- /* */
- /* <Description> */
- /* The TrueType face class. These objects model the resolution and */
- /* point-size independent data found in a TrueType font file. */
- /* */
- /* <Fields> */
- /* root :: The base FT_Face structure, managed by the */
- /* base layer. */
- /* */
- /* ttc_header :: The TrueType collection header, used when */
- /* the file is a `ttc' rather than a `ttf'. */
- /* For ordinary font files, the field */
- /* `ttc_header.count' is set to 0. */
- /* */
- /* format_tag :: The font format tag. */
- /* */
- /* num_tables :: The number of TrueType tables in this font */
- /* file. */
- /* */
- /* dir_tables :: The directory of TrueType tables for this */
- /* font file. */
- /* */
- /* header :: The font's font header (`head' table). */
- /* Read on font opening. */
- /* */
- /* horizontal :: The font's horizontal header (`hhea' */
- /* table). This field also contains the */
- /* associated horizontal metrics table */
- /* (`hmtx'). */
- /* */
- /* max_profile :: The font's maximum profile table. Read on */
- /* font opening. Note that some maximum */
- /* values cannot be taken directly from this */
- /* table. We thus define additional fields */
- /* below to hold the computed maxima. */
- /* */
- /* vertical_info :: A boolean which is set when the font file */
- /* contains vertical metrics. If not, the */
- /* value of the `vertical' field is */
- /* undefined. */
- /* */
- /* vertical :: The font's vertical header (`vhea' table). */
- /* This field also contains the associated */
- /* vertical metrics table (`vmtx'), if found. */
- /* IMPORTANT: The contents of this field is */
- /* undefined if the `vertical_info' field is */
- /* unset. */
- /* */
- /* num_names :: The number of name records within this */
- /* TrueType font. */
- /* */
- /* name_table :: The table of name records (`name'). */
- /* */
- /* os2 :: The font's OS/2 table (`OS/2'). */
- /* */
- /* postscript :: The font's PostScript table (`post' */
- /* table). The PostScript glyph names are */
- /* not loaded by the driver on face opening. */
- /* See the `ttpost' module for more details. */
- /* */
- /* cmap_table :: Address of the face's `cmap' SFNT table */
- /* in memory (it's an extracted frame). */
- /* */
- /* cmap_size :: The size in bytes of the `cmap_table' */
- /* described above. */
- /* */
- /* goto_table :: A function called by each TrueType table */
- /* loader to position a stream's cursor to */
- /* the start of a given table according to */
- /* its tag. It defaults to TT_Goto_Face but */
- /* can be different for strange formats (e.g. */
- /* Type 42). */
- /* */
- /* access_glyph_frame :: A function used to access the frame of a */
- /* given glyph within the face's font file. */
- /* */
- /* forget_glyph_frame :: A function used to forget the frame of a */
- /* given glyph when all data has been loaded. */
- /* */
- /* read_glyph_header :: A function used to read a glyph header. */
- /* It must be called between an `access' and */
- /* `forget'. */
- /* */
- /* read_simple_glyph :: A function used to read a simple glyph. */
- /* It must be called after the header was */
- /* read, and before the `forget'. */
- /* */
- /* read_composite_glyph :: A function used to read a composite glyph. */
- /* It must be called after the header was */
- /* read, and before the `forget'. */
- /* */
- /* sfnt :: A pointer to the SFNT service. */
- /* */
- /* psnames :: A pointer to the PostScript names service. */
- /* */
- /* mm :: A pointer to the Multiple Masters service. */
- /* */
- /* var :: A pointer to the Metrics Variations */
- /* service. */
- /* */
- /* hdmx :: The face's horizontal device metrics */
- /* (`hdmx' table). This table is optional in */
- /* TrueType/OpenType fonts. */
- /* */
- /* gasp :: The grid-fitting and scaling properties */
- /* table (`gasp'). This table is optional in */
- /* TrueType/OpenType fonts. */
- /* */
- /* pclt :: The `pclt' SFNT table. */
- /* */
- /* num_sbit_scales :: The number of sbit scales for this font. */
- /* */
- /* sbit_scales :: Array of sbit scales embedded in this */
- /* font. This table is optional in a */
- /* TrueType/OpenType font. */
- /* */
- /* postscript_names :: A table used to store the Postscript names */
- /* of the glyphs for this font. See the */
- /* file `ttconfig.h' for comments on the */
- /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES option. */
- /* */
- /* font_program_size :: Size in bytecodes of the face's font */
- /* program. 0 if none defined. Ignored for */
- /* Type 2 fonts. */
- /* */
- /* font_program :: The face's font program (bytecode stream) */
- /* executed at load time, also used during */
- /* glyph rendering. Comes from the `fpgm' */
- /* table. Ignored for Type 2 font fonts. */
- /* */
- /* cvt_program_size :: The size in bytecodes of the face's cvt */
- /* program. Ignored for Type 2 fonts. */
- /* */
- /* cvt_program :: The face's cvt program (bytecode stream) */
- /* executed each time an instance/size is */
- /* changed/reset. Comes from the `prep' */
- /* table. Ignored for Type 2 fonts. */
- /* */
- /* cvt_size :: Size of the control value table (in */
- /* entries). Ignored for Type 2 fonts. */
- /* */
- /* cvt :: The face's original control value table. */
- /* Coordinates are expressed in unscaled font */
- /* units. Comes from the `cvt ' table. */
- /* Ignored for Type 2 fonts. */
- /* */
- /* interpreter :: A pointer to the TrueType bytecode */
- /* interpreters field is also used to hook */
- /* the debugger in `ttdebug'. */
- /* */
- /* extra :: Reserved for third-party font drivers. */
- /* */
- /* postscript_name :: The PS name of the font. Used by the */
- /* postscript name service. */
- /* */
- /* glyf_len :: The length of the `glyf' table. Needed */
- /* for malformed `loca' tables. */
- /* */
- /* glyf_offset :: The file offset of the `glyf' table. */
- /* */
- /* is_cff2 :: Set if the font format is CFF2. */
- /* */
- /* doblend :: A boolean which is set if the font should */
- /* be blended (this is for GX var). */
- /* */
- /* blend :: Contains the data needed to control GX */
- /* variation tables (rather like Multiple */
- /* Master data). */
- /* */
- /* variation_support :: Flags that indicate which OpenType */
- /* functionality related to font variation */
- /* support is present, valid, and usable. */
- /* For example, TT_FACE_FLAG_VAR_FVAR is only */
- /* set if we have at least one design axis. */
- /* */
- /* var_postscript_prefix :: */
- /* The PostScript name prefix needed for */
- /* constructing a variation font instance's */
- /* PS name . */
- /* */
- /* var_postscript_prefix_len :: */
- /* The length of the `var_postscript_prefix' */
- /* string. */
- /* */
- /* horz_metrics_size :: The size of the `hmtx' table. */
- /* */
- /* vert_metrics_size :: The size of the `vmtx' table. */
- /* */
- /* num_locations :: The number of glyph locations in this */
- /* TrueType file. This should be */
- /* identical to the number of glyphs. */
- /* Ignored for Type 2 fonts. */
- /* */
- /* glyph_locations :: An array of longs. These are offsets to */
- /* glyph data within the `glyf' table. */
- /* Ignored for Type 2 font faces. */
- /* */
- /* hdmx_table :: A pointer to the `hdmx' table. */
- /* */
- /* hdmx_table_size :: The size of the `hdmx' table. */
- /* */
- /* hdmx_record_count :: The number of hdmx records. */
- /* */
- /* hdmx_record_size :: The size of a single hdmx record. */
- /* */
- /* hdmx_record_sizes :: An array holding the ppem sizes available */
- /* in the `hdmx' table. */
- /* */
- /* sbit_table :: A pointer to the font's embedded bitmap */
- /* location table. */
- /* */
- /* sbit_table_size :: The size of `sbit_table'. */
- /* */
- /* sbit_table_type :: The sbit table type (CBLC, sbix, etc.). */
- /* */
- /* sbit_num_strikes :: The number of sbit strikes exposed by */
- /* FreeType's API, omitting invalid strikes. */
- /* */
- /* sbit_strike_map :: A mapping between the strike indices */
- /* exposed by the API and the indices used in */
- /* the font's sbit table. */
- /* */
- /* kern_table :: A pointer to the `kern' table. */
- /* */
- /* kern_table_size :: The size of the `kern' table. */
- /* */
- /* num_kern_tables :: The number of supported kern subtables */
- /* (up to 32; FreeType recognizes only */
- /* horizontal ones with format 0). */
- /* */
- /* kern_avail_bits :: The availability status of kern subtables; */
- /* if bit n is set, table n is available. */
- /* */
- /* kern_order_bits :: The sortedness status of kern subtables; */
- /* if bit n is set, table n is sorted. */
- /* */
- /* bdf :: Data related to an SFNT font's `bdf' */
- /* table; see `tttypes.h'. */
- /* */
- /* horz_metrics_offset :: The file offset of the `hmtx' table. */
- /* */
- /* vert_metrics_offset :: The file offset of the `vmtx' table. */
- /* */
- /* sph_found_func_flags :: Flags identifying special bytecode */
- /* functions (used by the v38 implementation */
- /* of the bytecode interpreter). */
- /* */
- /* sph_compatibility_mode :: */
- /* This flag is set if we are in ClearType */
- /* backward compatibility mode (used by the */
- /* v38 implementation of the bytecode */
- /* interpreter). */
- /* */
- /* ebdt_start :: The file offset of the sbit data table */
- /* (CBDT, bdat, etc.). */
- /* */
- /* ebdt_size :: The size of the sbit data table. */
- /* */
+ /**************************************************************************
+ *
+ * TrueType Face Type
+ *
+ * @struct:
+ * TT_Face
+ *
+ * @description:
+ * The TrueType face class. These objects model the resolution and
+ * point-size independent data found in a TrueType font file.
+ *
+ * @fields:
+ * root ::
+ * The base FT_Face structure, managed by the base layer.
+ *
+ * ttc_header ::
+ * The TrueType collection header, used when the file is a 'ttc' rather
+ * than a 'ttf'. For ordinary font files, the field `ttc_header.count`
+ * is set to 0.
+ *
+ * format_tag ::
+ * The font format tag.
+ *
+ * num_tables ::
+ * The number of TrueType tables in this font file.
+ *
+ * dir_tables ::
+ * The directory of TrueType tables for this font file.
+ *
+ * header ::
+ * The font's font header ('head' table). Read on font opening.
+ *
+ * horizontal ::
+ * The font's horizontal header ('hhea' table). This field also
+ * contains the associated horizontal metrics table ('hmtx').
+ *
+ * max_profile ::
+ * The font's maximum profile table. Read on font opening. Note that
+ * some maximum values cannot be taken directly from this table. We
+ * thus define additional fields below to hold the computed maxima.
+ *
+ * vertical_info ::
+ * A boolean which is set when the font file contains vertical metrics.
+ * If not, the value of the 'vertical' field is undefined.
+ *
+ * vertical ::
+ * The font's vertical header ('vhea' table). This field also contains
+ * the associated vertical metrics table ('vmtx'), if found.
+ * IMPORTANT: The contents of this field is undefined if the
+ * `vertical_info` field is unset.
+ *
+ * num_names ::
+ * The number of name records within this TrueType font.
+ *
+ * name_table ::
+ * The table of name records ('name').
+ *
+ * os2 ::
+ * The font's OS/2 table ('OS/2').
+ *
+ * postscript ::
+ * The font's PostScript table ('post' table). The PostScript glyph
+ * names are not loaded by the driver on face opening. See the
+ * 'ttpost' module for more details.
+ *
+ * cmap_table ::
+ * Address of the face's 'cmap' SFNT table in memory (it's an extracted
+ * frame).
+ *
+ * cmap_size ::
+ * The size in bytes of the `cmap_table` described above.
+ *
+ * goto_table ::
+ * A function called by each TrueType table loader to position a
+ * stream's cursor to the start of a given table according to its tag.
+ * It defaults to TT_Goto_Face but can be different for strange formats
+ * (e.g. Type 42).
+ *
+ * access_glyph_frame ::
+ * A function used to access the frame of a given glyph within the
+ * face's font file.
+ *
+ * forget_glyph_frame ::
+ * A function used to forget the frame of a given glyph when all data
+ * has been loaded.
+ *
+ * read_glyph_header ::
+ * A function used to read a glyph header. It must be called between
+ * an 'access' and 'forget'.
+ *
+ * read_simple_glyph ::
+ * A function used to read a simple glyph. It must be called after the
+ * header was read, and before the 'forget'.
+ *
+ * read_composite_glyph ::
+ * A function used to read a composite glyph. It must be called after
+ * the header was read, and before the 'forget'.
+ *
+ * sfnt ::
+ * A pointer to the SFNT service.
+ *
+ * psnames ::
+ * A pointer to the PostScript names service.
+ *
+ * mm ::
+ * A pointer to the Multiple Masters service.
+ *
+ * var ::
+ * A pointer to the Metrics Variations service.
+ *
+ * hdmx ::
+ * The face's horizontal device metrics ('hdmx' table). This table is
+ * optional in TrueType/OpenType fonts.
+ *
+ * gasp ::
+ * The grid-fitting and scaling properties table ('gasp'). This table
+ * is optional in TrueType/OpenType fonts.
+ *
+ * pclt ::
+ * The 'pclt' SFNT table.
+ *
+ * num_sbit_scales ::
+ * The number of sbit scales for this font.
+ *
+ * sbit_scales ::
+ * Array of sbit scales embedded in this font. This table is optional
+ * in a TrueType/OpenType font.
+ *
+ * postscript_names ::
+ * A table used to store the Postscript names of the glyphs for this
+ * font. See the file `ttconfig.h` for comments on the
+ * TT_CONFIG_OPTION_POSTSCRIPT_NAMES option.
+ *
+ * palette_data ::
+ * Some fields from the 'CPAL' table that are directly indexed.
+ *
+ * palette_index ::
+ * The current palette index, as set by @FT_Palette_Select.
+ *
+ * palette ::
+ * An array containing the current palette's colors.
+ *
+ * have_foreground_color ::
+ * There was a call to @FT_Palette_Set_Foreground_Color.
+ *
+ * foreground_color ::
+ * The current foreground color corresponding to 'CPAL' color index
+ * 0xFFFF. Only valid if `have_foreground_color` is set.
+ *
+ * font_program_size ::
+ * Size in bytecodes of the face's font program. 0 if none defined.
+ * Ignored for Type 2 fonts.
+ *
+ * font_program ::
+ * The face's font program (bytecode stream) executed at load time,
+ * also used during glyph rendering. Comes from the 'fpgm' table.
+ * Ignored for Type 2 font fonts.
+ *
+ * cvt_program_size ::
+ * The size in bytecodes of the face's cvt program. Ignored for Type 2
+ * fonts.
+ *
+ * cvt_program ::
+ * The face's cvt program (bytecode stream) executed each time an
+ * instance/size is changed/reset. Comes from the 'prep' table.
+ * Ignored for Type 2 fonts.
+ *
+ * cvt_size ::
+ * Size of the control value table (in entries). Ignored for Type 2
+ * fonts.
+ *
+ * cvt ::
+ * The face's original control value table. Coordinates are expressed
+ * in unscaled font units. Comes from the 'cvt~' table. Ignored for
+ * Type 2 fonts.
+ *
+ * interpreter ::
+ * A pointer to the TrueType bytecode interpreters field is also used
+ * to hook the debugger in 'ttdebug'.
+ *
+ * extra ::
+ * Reserved for third-party font drivers.
+ *
+ * postscript_name ::
+ * The PS name of the font. Used by the postscript name service.
+ *
+ * glyf_len ::
+ * The length of the 'glyf' table. Needed for malformed 'loca' tables.
+ *
+ * glyf_offset ::
+ * The file offset of the 'glyf' table.
+ *
+ * is_cff2 ::
+ * Set if the font format is CFF2.
+ *
+ * doblend ::
+ * A boolean which is set if the font should be blended (this is for GX
+ * var).
+ *
+ * blend ::
+ * Contains the data needed to control GX variation tables (rather like
+ * Multiple Master data).
+ *
+ * variation_support ::
+ * Flags that indicate which OpenType functionality related to font
+ * variation support is present, valid, and usable. For example,
+ * TT_FACE_FLAG_VAR_FVAR is only set if we have at least one design
+ * axis.
+ *
+ * var_postscript_prefix ::
+ * The PostScript name prefix needed for constructing a variation font
+ * instance's PS name .
+ *
+ * var_postscript_prefix_len ::
+ * The length of the `var_postscript_prefix` string.
+ *
+ * horz_metrics_size ::
+ * The size of the 'hmtx' table.
+ *
+ * vert_metrics_size ::
+ * The size of the 'vmtx' table.
+ *
+ * num_locations ::
+ * The number of glyph locations in this TrueType file. This should be
+ * identical to the number of glyphs. Ignored for Type 2 fonts.
+ *
+ * glyph_locations ::
+ * An array of longs. These are offsets to glyph data within the
+ * 'glyf' table. Ignored for Type 2 font faces.
+ *
+ * hdmx_table ::
+ * A pointer to the 'hdmx' table.
+ *
+ * hdmx_table_size ::
+ * The size of the 'hdmx' table.
+ *
+ * hdmx_record_count ::
+ * The number of hdmx records.
+ *
+ * hdmx_record_size ::
+ * The size of a single hdmx record.
+ *
+ * hdmx_record_sizes ::
+ * An array holding the ppem sizes available in the 'hdmx' table.
+ *
+ * sbit_table ::
+ * A pointer to the font's embedded bitmap location table.
+ *
+ * sbit_table_size ::
+ * The size of `sbit_table`.
+ *
+ * sbit_table_type ::
+ * The sbit table type (CBLC, sbix, etc.).
+ *
+ * sbit_num_strikes ::
+ * The number of sbit strikes exposed by FreeType's API, omitting
+ * invalid strikes.
+ *
+ * sbit_strike_map ::
+ * A mapping between the strike indices exposed by the API and the
+ * indices used in the font's sbit table.
+ *
+ * cpal ::
+ * A pointer to data related to the 'CPAL' table. `NULL` if the table
+ * is not available.
+ *
+ * colr ::
+ * A pointer to data related to the 'COLR' table. `NULL` if the table
+ * is not available.
+ *
+ * kern_table ::
+ * A pointer to the 'kern' table.
+ *
+ * kern_table_size ::
+ * The size of the 'kern' table.
+ *
+ * num_kern_tables ::
+ * The number of supported kern subtables (up to 32; FreeType
+ * recognizes only horizontal ones with format 0).
+ *
+ * kern_avail_bits ::
+ * The availability status of kern subtables; if bit n is set, table n
+ * is available.
+ *
+ * kern_order_bits ::
+ * The sortedness status of kern subtables; if bit n is set, table n is
+ * sorted.
+ *
+ * bdf ::
+ * Data related to an SFNT font's 'bdf' table; see `tttypes.h`.
+ *
+ * horz_metrics_offset ::
+ * The file offset of the 'hmtx' table.
+ *
+ * vert_metrics_offset ::
+ * The file offset of the 'vmtx' table.
+ *
+ * sph_found_func_flags ::
+ * Flags identifying special bytecode functions (used by the v38
+ * implementation of the bytecode interpreter).
+ *
+ * sph_compatibility_mode ::
+ * This flag is set if we are in ClearType backward compatibility mode
+ * (used by the v38 implementation of the bytecode interpreter).
+ *
+ * ebdt_start ::
+ * The file offset of the sbit data table (CBDT, bdat, etc.).
+ *
+ * ebdt_size ::
+ * The size of the sbit data table.
+ */
typedef struct TT_FaceRec_
{
FT_FaceRec root;
@@ -1445,11 +1590,11 @@ FT_BEGIN_HEADER
void* psaux;
- /***********************************************************************/
- /* */
- /* Optional TrueType/OpenType tables */
- /* */
- /***********************************************************************/
+ /************************************************************************
+ *
+ * Optional TrueType/OpenType tables
+ *
+ */
/* grid-fitting and scaling table */
TT_GaspRec gasp; /* the `gasp' table */
@@ -1464,12 +1609,19 @@ FT_BEGIN_HEADER
/* postscript names table */
TT_Post_NamesRec postscript_names;
+ /* glyph colors */
+ FT_Palette_Data palette_data; /* since 2.10 */
+ FT_UShort palette_index;
+ FT_Color* palette;
+ FT_Bool have_foreground_color;
+ FT_Color foreground_color;
+
- /***********************************************************************/
- /* */
- /* TrueType-specific fields (ignored by the CFF driver) */
- /* */
- /***********************************************************************/
+ /************************************************************************
+ *
+ * TrueType-specific fields (ignored by the CFF driver)
+ *
+ */
/* the font program, if any */
FT_ULong font_program_size;
@@ -1488,12 +1640,12 @@ FT_BEGIN_HEADER
TT_Interpreter interpreter;
- /***********************************************************************/
- /* */
- /* Other tables or fields. This is used by derivative formats like */
- /* OpenType. */
- /* */
- /***********************************************************************/
+ /************************************************************************
+ *
+ * Other tables or fields. This is used by derivative formats like
+ * OpenType.
+ *
+ */
FT_Generic extra;
@@ -1562,40 +1714,53 @@ FT_BEGIN_HEADER
FT_ULong ebdt_size;
#endif
+ /* since 2.10 */
+ void* cpal;
+ void* colr;
+
} TT_FaceRec;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* TT_GlyphZoneRec */
- /* */
- /* <Description> */
- /* A glyph zone is used to load, scale and hint glyph outline */
- /* coordinates. */
- /* */
- /* <Fields> */
- /* memory :: A handle to the memory manager. */
- /* */
- /* max_points :: The maximum size in points of the zone. */
- /* */
- /* max_contours :: Max size in links contours of the zone. */
- /* */
- /* n_points :: The current number of points in the zone. */
- /* */
- /* n_contours :: The current number of contours in the zone. */
- /* */
- /* org :: The original glyph coordinates (font */
- /* units/scaled). */
- /* */
- /* cur :: The current glyph coordinates (scaled/hinted). */
- /* */
- /* tags :: The point control tags. */
- /* */
- /* contours :: The contours end points. */
- /* */
- /* first_point :: Offset of the current subglyph's first point. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * TT_GlyphZoneRec
+ *
+ * @description:
+ * A glyph zone is used to load, scale and hint glyph outline
+ * coordinates.
+ *
+ * @fields:
+ * memory ::
+ * A handle to the memory manager.
+ *
+ * max_points ::
+ * The maximum size in points of the zone.
+ *
+ * max_contours ::
+ * Max size in links contours of the zone.
+ *
+ * n_points ::
+ * The current number of points in the zone.
+ *
+ * n_contours ::
+ * The current number of contours in the zone.
+ *
+ * org ::
+ * The original glyph coordinates (font units/scaled).
+ *
+ * cur ::
+ * The current glyph coordinates (scaled/hinted).
+ *
+ * tags ::
+ * The point control tags.
+ *
+ * contours ::
+ * The contours end points.
+ *
+ * first_point ::
+ * Offset of the current subglyph's first point.
+ */
typedef struct TT_GlyphZoneRec_
{
FT_Memory memory;
@@ -1620,14 +1785,14 @@ FT_BEGIN_HEADER
typedef struct TT_ExecContextRec_* TT_ExecContext;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* TT_Size */
- /* */
- /* <Description> */
- /* A handle to a TrueType size object. */
- /* */
+ /**************************************************************************
+ *
+ * @type:
+ * TT_Size
+ *
+ * @description:
+ * A handle to a TrueType size object.
+ */
typedef struct TT_SizeRec_* TT_Size;
diff --git a/thirdparty/freetype/include/freetype/t1tables.h b/thirdparty/freetype/include/freetype/t1tables.h
index 3503c2616b..645e645720 100644
--- a/thirdparty/freetype/include/freetype/t1tables.h
+++ b/thirdparty/freetype/include/freetype/t1tables.h
@@ -1,20 +1,20 @@
-/***************************************************************************/
-/* */
-/* t1tables.h */
-/* */
-/* Basic Type 1/Type 2 tables definitions and interface (specification */
-/* only). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * t1tables.h
+ *
+ * Basic Type 1/Type 2 tables definitions and interface (specification
+ * only).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef T1TABLES_H_
@@ -34,58 +34,58 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* <Section> */
- /* type1_tables */
- /* */
- /* <Title> */
- /* Type 1 Tables */
- /* */
- /* <Abstract> */
- /* Type~1 (PostScript) specific font tables. */
- /* */
- /* <Description> */
- /* This section contains the definition of Type 1-specific tables, */
- /* including structures related to other PostScript font formats. */
- /* */
- /* <Order> */
- /* PS_FontInfoRec */
- /* PS_FontInfo */
- /* PS_PrivateRec */
- /* PS_Private */
- /* */
- /* CID_FaceDictRec */
- /* CID_FaceDict */
- /* CID_FaceInfoRec */
- /* CID_FaceInfo */
- /* */
- /* FT_Has_PS_Glyph_Names */
- /* FT_Get_PS_Font_Info */
- /* FT_Get_PS_Font_Private */
- /* FT_Get_PS_Font_Value */
- /* */
- /* T1_Blend_Flags */
- /* T1_EncodingType */
- /* PS_Dict_Keys */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * @section:
+ * type1_tables
+ *
+ * @title:
+ * Type 1 Tables
+ *
+ * @abstract:
+ * Type~1-specific font tables.
+ *
+ * @description:
+ * This section contains the definition of Type~1-specific tables,
+ * including structures related to other PostScript font formats.
+ *
+ * @order:
+ * PS_FontInfoRec
+ * PS_FontInfo
+ * PS_PrivateRec
+ * PS_Private
+ *
+ * CID_FaceDictRec
+ * CID_FaceDict
+ * CID_FaceInfoRec
+ * CID_FaceInfo
+ *
+ * FT_Has_PS_Glyph_Names
+ * FT_Get_PS_Font_Info
+ * FT_Get_PS_Font_Private
+ * FT_Get_PS_Font_Value
+ *
+ * T1_Blend_Flags
+ * T1_EncodingType
+ * PS_Dict_Keys
+ *
+ */
/* Note that we separate font data in PS_FontInfoRec and PS_PrivateRec */
/* structures in order to support Multiple Master fonts. */
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* PS_FontInfoRec */
- /* */
- /* <Description> */
- /* A structure used to model a Type~1 or Type~2 FontInfo dictionary. */
- /* Note that for Multiple Master fonts, each instance has its own */
- /* FontInfo dictionary. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * PS_FontInfoRec
+ *
+ * @description:
+ * A structure used to model a Type~1 or Type~2 FontInfo dictionary.
+ * Note that for Multiple Master fonts, each instance has its own
+ * FontInfo dictionary.
+ */
typedef struct PS_FontInfoRec_
{
FT_String* version;
@@ -101,40 +101,39 @@ FT_BEGIN_HEADER
} PS_FontInfoRec;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* PS_FontInfo */
- /* */
- /* <Description> */
- /* A handle to a @PS_FontInfoRec structure. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * PS_FontInfo
+ *
+ * @description:
+ * A handle to a @PS_FontInfoRec structure.
+ */
typedef struct PS_FontInfoRec_* PS_FontInfo;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* T1_FontInfo */
- /* */
- /* <Description> */
- /* This type is equivalent to @PS_FontInfoRec. It is deprecated but */
- /* kept to maintain source compatibility between various versions of */
- /* FreeType. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * T1_FontInfo
+ *
+ * @description:
+ * This type is equivalent to @PS_FontInfoRec. It is deprecated but kept
+ * to maintain source compatibility between various versions of FreeType.
+ */
typedef PS_FontInfoRec T1_FontInfo;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* PS_PrivateRec */
- /* */
- /* <Description> */
- /* A structure used to model a Type~1 or Type~2 private dictionary. */
- /* Note that for Multiple Master fonts, each instance has its own */
- /* Private dictionary. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * PS_PrivateRec
+ *
+ * @description:
+ * A structure used to model a Type~1 or Type~2 private dictionary. Note
+ * that for Multiple Master fonts, each instance has its own Private
+ * dictionary.
+ */
typedef struct PS_PrivateRec_
{
FT_Int unique_id;
@@ -176,56 +175,55 @@ FT_BEGIN_HEADER
} PS_PrivateRec;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* PS_Private */
- /* */
- /* <Description> */
- /* A handle to a @PS_PrivateRec structure. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * PS_Private
+ *
+ * @description:
+ * A handle to a @PS_PrivateRec structure.
+ */
typedef struct PS_PrivateRec_* PS_Private;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* T1_Private */
- /* */
- /* <Description> */
- /* This type is equivalent to @PS_PrivateRec. It is deprecated but */
- /* kept to maintain source compatibility between various versions of */
- /* FreeType. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * T1_Private
+ *
+ * @description:
+ * This type is equivalent to @PS_PrivateRec. It is deprecated but kept
+ * to maintain source compatibility between various versions of FreeType.
+ */
typedef PS_PrivateRec T1_Private;
- /*************************************************************************/
- /* */
- /* <Enum> */
- /* T1_Blend_Flags */
- /* */
- /* <Description> */
- /* A set of flags used to indicate which fields are present in a */
- /* given blend dictionary (font info or private). Used to support */
- /* Multiple Masters fonts. */
- /* */
- /* <Values> */
- /* T1_BLEND_UNDERLINE_POSITION :: */
- /* T1_BLEND_UNDERLINE_THICKNESS :: */
- /* T1_BLEND_ITALIC_ANGLE :: */
- /* T1_BLEND_BLUE_VALUES :: */
- /* T1_BLEND_OTHER_BLUES :: */
- /* T1_BLEND_STANDARD_WIDTH :: */
- /* T1_BLEND_STANDARD_HEIGHT :: */
- /* T1_BLEND_STEM_SNAP_WIDTHS :: */
- /* T1_BLEND_STEM_SNAP_HEIGHTS :: */
- /* T1_BLEND_BLUE_SCALE :: */
- /* T1_BLEND_BLUE_SHIFT :: */
- /* T1_BLEND_FAMILY_BLUES :: */
- /* T1_BLEND_FAMILY_OTHER_BLUES :: */
- /* T1_BLEND_FORCE_BOLD :: */
- /* */
+ /**************************************************************************
+ *
+ * @enum:
+ * T1_Blend_Flags
+ *
+ * @description:
+ * A set of flags used to indicate which fields are present in a given
+ * blend dictionary (font info or private). Used to support Multiple
+ * Masters fonts.
+ *
+ * @values:
+ * T1_BLEND_UNDERLINE_POSITION ::
+ * T1_BLEND_UNDERLINE_THICKNESS ::
+ * T1_BLEND_ITALIC_ANGLE ::
+ * T1_BLEND_BLUE_VALUES ::
+ * T1_BLEND_OTHER_BLUES ::
+ * T1_BLEND_STANDARD_WIDTH ::
+ * T1_BLEND_STANDARD_HEIGHT ::
+ * T1_BLEND_STEM_SNAP_WIDTHS ::
+ * T1_BLEND_STEM_SNAP_HEIGHTS ::
+ * T1_BLEND_BLUE_SCALE ::
+ * T1_BLEND_BLUE_SHIFT ::
+ * T1_BLEND_FAMILY_BLUES ::
+ * T1_BLEND_FAMILY_OTHER_BLUES ::
+ * T1_BLEND_FORCE_BOLD ::
+ */
typedef enum T1_Blend_Flags_
{
/* required fields in a FontInfo blend dictionary */
@@ -252,7 +250,7 @@ FT_BEGIN_HEADER
/* these constants are deprecated; use the corresponding */
- /* `T1_Blend_Flags' values instead */
+ /* `T1_Blend_Flags` values instead */
#define t1_blend_underline_position T1_BLEND_UNDERLINE_POSITION
#define t1_blend_underline_thickness T1_BLEND_UNDERLINE_THICKNESS
#define t1_blend_italic_angle T1_BLEND_ITALIC_ANGLE
@@ -330,14 +328,23 @@ FT_BEGIN_HEADER
typedef PS_BlendRec T1_Blend;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* CID_FaceDictRec */
- /* */
- /* <Description> */
- /* A structure used to represent data in a CID top-level dictionary. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * CID_FaceDictRec
+ *
+ * @description:
+ * A structure used to represent data in a CID top-level dictionary. In
+ * most cases, they are part of the font's '/FDArray' array. Within a
+ * CID font file, such (internal) subfont dictionaries are enclosed by
+ * '%ADOBeginFontDict' and '%ADOEndFontDict' comments.
+ *
+ * Note that `CID_FaceDictRec` misses a field for the '/FontName'
+ * keyword, specifying the subfont's name (the top-level font name is
+ * given by the '/CIDFontName' keyword). This is an oversight, but it
+ * doesn't limit the 'cid' font module's functionality because FreeType
+ * neither needs this entry nor gives access to CID subfonts.
+ */
typedef struct CID_FaceDictRec_
{
PS_PrivateRec private_dict;
@@ -345,8 +352,8 @@ FT_BEGIN_HEADER
FT_UInt len_buildchar;
FT_Fixed forcebold_threshold;
FT_Pos stroke_width;
- FT_Fixed expansion_factor;
-
+ FT_Fixed expansion_factor; /* this is a duplicate of */
+ /* `private_dict->expansion_factor' */
FT_Byte paint_type;
FT_Byte font_type;
FT_Matrix font_matrix;
@@ -359,38 +366,38 @@ FT_BEGIN_HEADER
} CID_FaceDictRec;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* CID_FaceDict */
- /* */
- /* <Description> */
- /* A handle to a @CID_FaceDictRec structure. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * CID_FaceDict
+ *
+ * @description:
+ * A handle to a @CID_FaceDictRec structure.
+ */
typedef struct CID_FaceDictRec_* CID_FaceDict;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* CID_FontDict */
- /* */
- /* <Description> */
- /* This type is equivalent to @CID_FaceDictRec. It is deprecated but */
- /* kept to maintain source compatibility between various versions of */
- /* FreeType. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * CID_FontDict
+ *
+ * @description:
+ * This type is equivalent to @CID_FaceDictRec. It is deprecated but
+ * kept to maintain source compatibility between various versions of
+ * FreeType.
+ */
typedef CID_FaceDictRec CID_FontDict;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* CID_FaceInfoRec */
- /* */
- /* <Description> */
- /* A structure used to represent CID Face information. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * CID_FaceInfoRec
+ *
+ * @description:
+ * A structure used to represent CID Face information.
+ */
typedef struct CID_FaceInfoRec_
{
FT_String* cid_font_name;
@@ -421,47 +428,45 @@ FT_BEGIN_HEADER
} CID_FaceInfoRec;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* CID_FaceInfo */
- /* */
- /* <Description> */
- /* A handle to a @CID_FaceInfoRec structure. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * CID_FaceInfo
+ *
+ * @description:
+ * A handle to a @CID_FaceInfoRec structure.
+ */
typedef struct CID_FaceInfoRec_* CID_FaceInfo;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* CID_Info */
- /* */
- /* <Description> */
- /* This type is equivalent to @CID_FaceInfoRec. It is deprecated but */
- /* kept to maintain source compatibility between various versions of */
- /* FreeType. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * CID_Info
+ *
+ * @description:
+ * This type is equivalent to @CID_FaceInfoRec. It is deprecated but kept
+ * to maintain source compatibility between various versions of FreeType.
+ */
typedef CID_FaceInfoRec CID_Info;
- /************************************************************************
+ /**************************************************************************
*
* @function:
* FT_Has_PS_Glyph_Names
*
* @description:
- * Return true if a given face provides reliable PostScript glyph
- * names. This is similar to using the @FT_HAS_GLYPH_NAMES macro,
- * except that certain fonts (mostly TrueType) contain incorrect
- * glyph name tables.
+ * Return true if a given face provides reliable PostScript glyph names.
+ * This is similar to using the @FT_HAS_GLYPH_NAMES macro, except that
+ * certain fonts (mostly TrueType) contain incorrect glyph name tables.
*
* When this function returns true, the caller is sure that the glyph
* names returned by @FT_Get_Glyph_Name are reliable.
*
* @input:
* face ::
- * face handle
+ * face handle
*
* @return:
* Boolean. True if glyph names are reliable.
@@ -471,7 +476,7 @@ FT_BEGIN_HEADER
FT_Has_PS_Glyph_Names( FT_Face face );
- /************************************************************************
+ /**************************************************************************
*
* @function:
* FT_Get_PS_Font_Info
@@ -482,22 +487,22 @@ FT_BEGIN_HEADER
*
* @input:
* face ::
- * PostScript face handle.
+ * PostScript face handle.
*
* @output:
* afont_info ::
- * Output font info structure pointer.
+ * Output font info structure pointer.
*
* @return:
* FreeType error code. 0~means success.
*
* @note:
- * String pointers within the @PS_FontInfoRec structure are owned by
- * the face and don't need to be freed by the caller. Missing entries
- * in the font's FontInfo dictionary are represented by NULL pointers.
+ * String pointers within the @PS_FontInfoRec structure are owned by the
+ * face and don't need to be freed by the caller. Missing entries in
+ * the font's FontInfo dictionary are represented by `NULL` pointers.
*
* If the font's format is not PostScript-based, this function will
- * return the `FT_Err_Invalid_Argument' error code.
+ * return the `FT_Err_Invalid_Argument` error code.
*
*/
FT_EXPORT( FT_Error )
@@ -505,7 +510,7 @@ FT_BEGIN_HEADER
PS_FontInfo afont_info );
- /************************************************************************
+ /**************************************************************************
*
* @function:
* FT_Get_PS_Font_Private
@@ -516,11 +521,11 @@ FT_BEGIN_HEADER
*
* @input:
* face ::
- * PostScript face handle.
+ * PostScript face handle.
*
* @output:
* afont_private ::
- * Output private dictionary structure pointer.
+ * Output private dictionary structure pointer.
*
* @return:
* FreeType error code. 0~means success.
@@ -530,7 +535,7 @@ FT_BEGIN_HEADER
* the face and don't need to be freed by the caller.
*
* If the font's format is not PostScript-based, this function returns
- * the `FT_Err_Invalid_Argument' error code.
+ * the `FT_Err_Invalid_Argument` error code.
*
*/
FT_EXPORT( FT_Error )
@@ -538,25 +543,24 @@ FT_BEGIN_HEADER
PS_Private afont_private );
- /*************************************************************************/
- /* */
- /* <Enum> */
- /* T1_EncodingType */
- /* */
- /* <Description> */
- /* An enumeration describing the `Encoding' entry in a Type 1 */
- /* dictionary. */
- /* */
- /* <Values> */
- /* T1_ENCODING_TYPE_NONE :: */
- /* T1_ENCODING_TYPE_ARRAY :: */
- /* T1_ENCODING_TYPE_STANDARD :: */
- /* T1_ENCODING_TYPE_ISOLATIN1 :: */
- /* T1_ENCODING_TYPE_EXPERT :: */
- /* */
- /* <Since> */
- /* 2.4.8 */
- /* */
+ /**************************************************************************
+ *
+ * @enum:
+ * T1_EncodingType
+ *
+ * @description:
+ * An enumeration describing the 'Encoding' entry in a Type 1 dictionary.
+ *
+ * @values:
+ * T1_ENCODING_TYPE_NONE ::
+ * T1_ENCODING_TYPE_ARRAY ::
+ * T1_ENCODING_TYPE_STANDARD ::
+ * T1_ENCODING_TYPE_ISOLATIN1 ::
+ * T1_ENCODING_TYPE_EXPERT ::
+ *
+ * @since:
+ * 2.4.8
+ */
typedef enum T1_EncodingType_
{
T1_ENCODING_TYPE_NONE = 0,
@@ -568,66 +572,66 @@ FT_BEGIN_HEADER
} T1_EncodingType;
- /*************************************************************************/
- /* */
- /* <Enum> */
- /* PS_Dict_Keys */
- /* */
- /* <Description> */
- /* An enumeration used in calls to @FT_Get_PS_Font_Value to identify */
- /* the Type~1 dictionary entry to retrieve. */
- /* */
- /* <Values> */
- /* PS_DICT_FONT_TYPE :: */
- /* PS_DICT_FONT_MATRIX :: */
- /* PS_DICT_FONT_BBOX :: */
- /* PS_DICT_PAINT_TYPE :: */
- /* PS_DICT_FONT_NAME :: */
- /* PS_DICT_UNIQUE_ID :: */
- /* PS_DICT_NUM_CHAR_STRINGS :: */
- /* PS_DICT_CHAR_STRING_KEY :: */
- /* PS_DICT_CHAR_STRING :: */
- /* PS_DICT_ENCODING_TYPE :: */
- /* PS_DICT_ENCODING_ENTRY :: */
- /* PS_DICT_NUM_SUBRS :: */
- /* PS_DICT_SUBR :: */
- /* PS_DICT_STD_HW :: */
- /* PS_DICT_STD_VW :: */
- /* PS_DICT_NUM_BLUE_VALUES :: */
- /* PS_DICT_BLUE_VALUE :: */
- /* PS_DICT_BLUE_FUZZ :: */
- /* PS_DICT_NUM_OTHER_BLUES :: */
- /* PS_DICT_OTHER_BLUE :: */
- /* PS_DICT_NUM_FAMILY_BLUES :: */
- /* PS_DICT_FAMILY_BLUE :: */
- /* PS_DICT_NUM_FAMILY_OTHER_BLUES :: */
- /* PS_DICT_FAMILY_OTHER_BLUE :: */
- /* PS_DICT_BLUE_SCALE :: */
- /* PS_DICT_BLUE_SHIFT :: */
- /* PS_DICT_NUM_STEM_SNAP_H :: */
- /* PS_DICT_STEM_SNAP_H :: */
- /* PS_DICT_NUM_STEM_SNAP_V :: */
- /* PS_DICT_STEM_SNAP_V :: */
- /* PS_DICT_FORCE_BOLD :: */
- /* PS_DICT_RND_STEM_UP :: */
- /* PS_DICT_MIN_FEATURE :: */
- /* PS_DICT_LEN_IV :: */
- /* PS_DICT_PASSWORD :: */
- /* PS_DICT_LANGUAGE_GROUP :: */
- /* PS_DICT_VERSION :: */
- /* PS_DICT_NOTICE :: */
- /* PS_DICT_FULL_NAME :: */
- /* PS_DICT_FAMILY_NAME :: */
- /* PS_DICT_WEIGHT :: */
- /* PS_DICT_IS_FIXED_PITCH :: */
- /* PS_DICT_UNDERLINE_POSITION :: */
- /* PS_DICT_UNDERLINE_THICKNESS :: */
- /* PS_DICT_FS_TYPE :: */
- /* PS_DICT_ITALIC_ANGLE :: */
- /* */
- /* <Since> */
- /* 2.4.8 */
- /* */
+ /**************************************************************************
+ *
+ * @enum:
+ * PS_Dict_Keys
+ *
+ * @description:
+ * An enumeration used in calls to @FT_Get_PS_Font_Value to identify the
+ * Type~1 dictionary entry to retrieve.
+ *
+ * @values:
+ * PS_DICT_FONT_TYPE ::
+ * PS_DICT_FONT_MATRIX ::
+ * PS_DICT_FONT_BBOX ::
+ * PS_DICT_PAINT_TYPE ::
+ * PS_DICT_FONT_NAME ::
+ * PS_DICT_UNIQUE_ID ::
+ * PS_DICT_NUM_CHAR_STRINGS ::
+ * PS_DICT_CHAR_STRING_KEY ::
+ * PS_DICT_CHAR_STRING ::
+ * PS_DICT_ENCODING_TYPE ::
+ * PS_DICT_ENCODING_ENTRY ::
+ * PS_DICT_NUM_SUBRS ::
+ * PS_DICT_SUBR ::
+ * PS_DICT_STD_HW ::
+ * PS_DICT_STD_VW ::
+ * PS_DICT_NUM_BLUE_VALUES ::
+ * PS_DICT_BLUE_VALUE ::
+ * PS_DICT_BLUE_FUZZ ::
+ * PS_DICT_NUM_OTHER_BLUES ::
+ * PS_DICT_OTHER_BLUE ::
+ * PS_DICT_NUM_FAMILY_BLUES ::
+ * PS_DICT_FAMILY_BLUE ::
+ * PS_DICT_NUM_FAMILY_OTHER_BLUES ::
+ * PS_DICT_FAMILY_OTHER_BLUE ::
+ * PS_DICT_BLUE_SCALE ::
+ * PS_DICT_BLUE_SHIFT ::
+ * PS_DICT_NUM_STEM_SNAP_H ::
+ * PS_DICT_STEM_SNAP_H ::
+ * PS_DICT_NUM_STEM_SNAP_V ::
+ * PS_DICT_STEM_SNAP_V ::
+ * PS_DICT_FORCE_BOLD ::
+ * PS_DICT_RND_STEM_UP ::
+ * PS_DICT_MIN_FEATURE ::
+ * PS_DICT_LEN_IV ::
+ * PS_DICT_PASSWORD ::
+ * PS_DICT_LANGUAGE_GROUP ::
+ * PS_DICT_VERSION ::
+ * PS_DICT_NOTICE ::
+ * PS_DICT_FULL_NAME ::
+ * PS_DICT_FAMILY_NAME ::
+ * PS_DICT_WEIGHT ::
+ * PS_DICT_IS_FIXED_PITCH ::
+ * PS_DICT_UNDERLINE_POSITION ::
+ * PS_DICT_UNDERLINE_THICKNESS ::
+ * PS_DICT_FS_TYPE ::
+ * PS_DICT_ITALIC_ANGLE ::
+ *
+ * @since:
+ * 2.4.8
+ */
typedef enum PS_Dict_Keys_
{
/* conventionally in the font dictionary */
@@ -687,7 +691,7 @@ FT_BEGIN_HEADER
} PS_Dict_Keys;
- /************************************************************************
+ /**************************************************************************
*
* @function:
* FT_Get_PS_Font_Value
@@ -697,57 +701,57 @@ FT_BEGIN_HEADER
*
* @input:
* face ::
- * PostScript face handle.
+ * PostScript face handle.
*
* key ::
- * An enumeration value representing the dictionary key to retrieve.
+ * An enumeration value representing the dictionary key to retrieve.
*
* idx ::
- * For array values, this specifies the index to be returned.
+ * For array values, this specifies the index to be returned.
*
* value ::
- * A pointer to memory into which to write the value.
+ * A pointer to memory into which to write the value.
*
* valen_len ::
- * The size, in bytes, of the memory supplied for the value.
+ * The size, in bytes, of the memory supplied for the value.
*
* @output:
* value ::
- * The value matching the above key, if it exists.
+ * The value matching the above key, if it exists.
*
* @return:
- * The amount of memory (in bytes) required to hold the requested
- * value (if it exists, -1 otherwise).
+ * The amount of memory (in bytes) required to hold the requested value
+ * (if it exists, -1 otherwise).
*
* @note:
* The values returned are not pointers into the internal structures of
- * the face, but are `fresh' copies, so that the memory containing them
+ * the face, but are 'fresh' copies, so that the memory containing them
* belongs to the calling application. This also enforces the
- * `read-only' nature of these values, i.e., this function cannot be
+ * 'read-only' nature of these values, i.e., this function cannot be
* used to manipulate the face.
*
- * `value' is a void pointer because the values returned can be of
+ * `value` is a void pointer because the values returned can be of
* various types.
*
- * If either `value' is NULL or `value_len' is too small, just the
+ * If either `value` is `NULL` or `value_len` is too small, just the
* required memory size for the requested entry is returned.
*
- * The `idx' parameter is used, not only to retrieve elements of, for
+ * The `idx` parameter is used, not only to retrieve elements of, for
* example, the FontMatrix or FontBBox, but also to retrieve name keys
* from the CharStrings dictionary, and the charstrings themselves. It
* is ignored for atomic values.
*
- * PS_DICT_BLUE_SCALE returns a value that is scaled up by 1000. To
- * get the value as in the font stream, you need to divide by
- * 65536000.0 (to remove the FT_Fixed scale, and the x1000 scale).
+ * `PS_DICT_BLUE_SCALE` returns a value that is scaled up by 1000. To
+ * get the value as in the font stream, you need to divide by 65536000.0
+ * (to remove the FT_Fixed scale, and the x1000 scale).
*
* IMPORTANT: Only key/value pairs read by the FreeType interpreter can
- * be retrieved. So, for example, PostScript procedures such as NP,
- * ND, and RD are not available. Arbitrary keys are, obviously, not be
+ * be retrieved. So, for example, PostScript procedures such as NP, ND,
+ * and RD are not available. Arbitrary keys are, obviously, not be
* available either.
*
* If the font's format is not PostScript-based, this function returns
- * the `FT_Err_Invalid_Argument' error code.
+ * the `FT_Err_Invalid_Argument` error code.
*
* @since:
* 2.4.8
diff --git a/thirdparty/freetype/include/freetype/ttnameid.h b/thirdparty/freetype/include/freetype/ttnameid.h
index 8605183dc7..cc677de75a 100644
--- a/thirdparty/freetype/include/freetype/ttnameid.h
+++ b/thirdparty/freetype/include/freetype/ttnameid.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ttnameid.h */
-/* */
-/* TrueType name ID definitions (specification only). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ttnameid.h
+ *
+ * TrueType name ID definitions (specification only).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef TTNAMEID_H_
@@ -26,53 +26,54 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* <Section> */
- /* truetype_tables */
- /* */
+ /**************************************************************************
+ *
+ * @section:
+ * truetype_tables
+ */
- /*************************************************************************/
- /* */
- /* Possible values for the `platform' identifier code in the name */
- /* records of an SFNT `name' table. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * Possible values for the 'platform' identifier code in the name records
+ * of an SFNT 'name' table.
+ *
+ */
- /***********************************************************************
+ /**************************************************************************
*
* @enum:
* TT_PLATFORM_XXX
*
* @description:
- * A list of valid values for the `platform_id' identifier code in
+ * A list of valid values for the `platform_id` identifier code in
* @FT_CharMapRec and @FT_SfntName structures.
*
* @values:
* TT_PLATFORM_APPLE_UNICODE ::
* Used by Apple to indicate a Unicode character map and/or name entry.
- * See @TT_APPLE_ID_XXX for corresponding `encoding_id' values. Note
+ * See @TT_APPLE_ID_XXX for corresponding `encoding_id` values. Note
* that name entries in this format are coded as big-endian UCS-2
* character codes _only_.
*
* TT_PLATFORM_MACINTOSH ::
- * Used by Apple to indicate a MacOS-specific charmap and/or name entry.
- * See @TT_MAC_ID_XXX for corresponding `encoding_id' values. Note that
- * most TrueType fonts contain an Apple roman charmap to be usable on
- * MacOS systems (even if they contain a Microsoft charmap as well).
+ * Used by Apple to indicate a MacOS-specific charmap and/or name
+ * entry. See @TT_MAC_ID_XXX for corresponding `encoding_id` values.
+ * Note that most TrueType fonts contain an Apple roman charmap to be
+ * usable on MacOS systems (even if they contain a Microsoft charmap as
+ * well).
*
* TT_PLATFORM_ISO ::
- * This value was used to specify ISO/IEC 10646 charmaps. It is however
- * now deprecated. See @TT_ISO_ID_XXX for a list of corresponding
- * `encoding_id' values.
+ * This value was used to specify ISO/IEC 10646 charmaps. It is
+ * however now deprecated. See @TT_ISO_ID_XXX for a list of
+ * corresponding `encoding_id` values.
*
* TT_PLATFORM_MICROSOFT ::
* Used by Microsoft to indicate Windows-specific charmaps. See
- * @TT_MS_ID_XXX for a list of corresponding `encoding_id' values.
+ * @TT_MS_ID_XXX for a list of corresponding `encoding_id` values.
* Note that most fonts contain a Unicode charmap using
- * (TT_PLATFORM_MICROSOFT, @TT_MS_ID_UNICODE_CS).
+ * (`TT_PLATFORM_MICROSOFT`, @TT_MS_ID_UNICODE_CS).
*
* TT_PLATFORM_CUSTOM ::
* Used to indicate application-specific charmaps.
@@ -91,13 +92,13 @@ FT_BEGIN_HEADER
#define TT_PLATFORM_ADOBE 7 /* artificial */
- /***********************************************************************
+ /**************************************************************************
*
* @enum:
* TT_APPLE_ID_XXX
*
* @description:
- * A list of valid values for the `encoding_id' for
+ * A list of valid values for the `encoding_id` for
* @TT_PLATFORM_APPLE_UNICODE charmaps and name entries.
*
* @values:
@@ -117,8 +118,8 @@ FT_BEGIN_HEADER
* Unicode 3.1 and beyond, using UTF-32.
*
* TT_APPLE_ID_VARIANT_SELECTOR ::
- * From Adobe, not Apple. Not a normal cmap. Specifies variations
- * on a real cmap.
+ * From Adobe, not Apple. Not a normal cmap. Specifies variations on
+ * a real cmap.
*
* TT_APPLE_ID_FULL_UNICODE ::
* Used for fallback fonts that provide complete Unicode coverage with
@@ -134,13 +135,13 @@ FT_BEGIN_HEADER
#define TT_APPLE_ID_FULL_UNICODE 6 /* used with type 13 cmaps */
- /***********************************************************************
+ /**************************************************************************
*
* @enum:
* TT_MAC_ID_XXX
*
* @description:
- * A list of valid values for the `encoding_id' for
+ * A list of valid values for the `encoding_id` for
* @TT_PLATFORM_MACINTOSH charmaps and name entries.
*/
@@ -180,14 +181,14 @@ FT_BEGIN_HEADER
#define TT_MAC_ID_UNINTERP 32
- /***********************************************************************
+ /**************************************************************************
*
* @enum:
* TT_ISO_ID_XXX
*
* @description:
- * A list of valid values for the `encoding_id' for
- * @TT_PLATFORM_ISO charmaps and name entries.
+ * A list of valid values for the `encoding_id` for @TT_PLATFORM_ISO
+ * charmaps and name entries.
*
* Their use is now deprecated.
*
@@ -205,13 +206,13 @@ FT_BEGIN_HEADER
#define TT_ISO_ID_8859_1 2
- /***********************************************************************
+ /**************************************************************************
*
* @enum:
* TT_MS_ID_XXX
*
* @description:
- * A list of valid values for the `encoding_id' for
+ * A list of valid values for the `encoding_id` for
* @TT_PLATFORM_MICROSOFT charmaps and name entries.
*
* @values:
@@ -219,16 +220,15 @@ FT_BEGIN_HEADER
* Microsoft symbol encoding. See @FT_ENCODING_MS_SYMBOL.
*
* TT_MS_ID_UNICODE_CS ::
- * Microsoft WGL4 charmap, matching Unicode. See
- * @FT_ENCODING_UNICODE.
+ * Microsoft WGL4 charmap, matching Unicode. See @FT_ENCODING_UNICODE.
*
* TT_MS_ID_SJIS ::
* Shift JIS Japanese encoding. See @FT_ENCODING_SJIS.
*
* TT_MS_ID_PRC ::
* Chinese encodings as used in the People's Republic of China (PRC).
- * This means the encodings GB~2312 and its supersets GBK and
- * GB~18030. See @FT_ENCODING_PRC.
+ * This means the encodings GB~2312 and its supersets GBK and GB~18030.
+ * See @FT_ENCODING_PRC.
*
* TT_MS_ID_BIG_5 ::
* Traditional Chinese as used in Taiwan and Hong Kong. See
@@ -258,14 +258,14 @@ FT_BEGIN_HEADER
#define TT_MS_ID_GB2312 TT_MS_ID_PRC
- /***********************************************************************
+ /**************************************************************************
*
* @enum:
* TT_ADOBE_ID_XXX
*
* @description:
- * A list of valid values for the `encoding_id' for
- * @TT_PLATFORM_ADOBE charmaps. This is a FreeType-specific extension!
+ * A list of valid values for the `encoding_id` for @TT_PLATFORM_ADOBE
+ * charmaps. This is a FreeType-specific extension!
*
* @values:
* TT_ADOBE_ID_STANDARD ::
@@ -284,14 +284,14 @@ FT_BEGIN_HEADER
#define TT_ADOBE_ID_LATIN_1 3
- /***********************************************************************
+ /**************************************************************************
*
* @enum:
* TT_MAC_LANGID_XXX
*
* @description:
* Possible values of the language identifier field in the name records
- * of the SFNT `name' table if the `platform' identifier code is
+ * of the SFNT 'name' table if the 'platform' identifier code is
* @TT_PLATFORM_MACINTOSH. These values are also used as return values
* for function @FT_Get_CMap_Language_ID.
*
@@ -424,24 +424,24 @@ FT_BEGIN_HEADER
#define TT_MAC_LANGID_AZERBAIJANI_ROMAN_SCRIPT 150
- /***********************************************************************
+ /**************************************************************************
*
* @enum:
* TT_MS_LANGID_XXX
*
* @description:
* Possible values of the language identifier field in the name records
- * of the SFNT `name' table if the `platform' identifier code is
+ * of the SFNT 'name' table if the 'platform' identifier code is
* @TT_PLATFORM_MICROSOFT. These values are also used as return values
* for function @FT_Get_CMap_Language_ID.
*
* The canonical source for Microsoft's IDs is
*
- * https://www.microsoft.com/globaldev/reference/lcid-all.mspx ,
+ * https://docs.microsoft.com/en-us/windows/desktop/Intl/language-identifier-constants-and-strings ,
*
* however, we only provide macros for language identifiers present in
* the OpenType specification: Microsoft has abandoned the concept of
- * LCIDs (language code identifiers), and format~1 of the `name' table
+ * LCIDs (language code identifiers), and format~1 of the 'name' table
* provides a better mechanism for languages not covered here.
*
* More legacy values not listed in the reference can be found in the
@@ -780,14 +780,14 @@ FT_BEGIN_HEADER
TT_MS_LANGID_UIGHUR_PRC
- /***********************************************************************
+ /**************************************************************************
*
* @enum:
* TT_NAME_ID_XXX
*
* @description:
- * Possible values of the `name' identifier field in the name records of
- * an SFNT `name' table. These values are platform independent.
+ * Possible values of the 'name' identifier field in the name records of
+ * an SFNT 'name' table. These values are platform independent.
*/
#define TT_NAME_ID_COPYRIGHT 0
@@ -834,14 +834,14 @@ FT_BEGIN_HEADER
#define TT_NAME_ID_PREFERRED_SUBFAMILY TT_NAME_ID_TYPOGRAPHIC_SUBFAMILY
- /***********************************************************************
+ /**************************************************************************
*
* @enum:
* TT_UCR_XXX
*
* @description:
- * Possible bit mask values for the `ulUnicodeRangeX' fields in an SFNT
- * `OS/2' table.
+ * Possible bit mask values for the `ulUnicodeRangeX` fields in an SFNT
+ * 'OS/2' table.
*/
/* ulUnicodeRange1 */
diff --git a/thirdparty/freetype/include/freetype/tttables.h b/thirdparty/freetype/include/freetype/tttables.h
index ce6a61779c..d04f810218 100644
--- a/thirdparty/freetype/include/freetype/tttables.h
+++ b/thirdparty/freetype/include/freetype/tttables.h
@@ -1,20 +1,20 @@
-/***************************************************************************/
-/* */
-/* tttables.h */
-/* */
-/* Basic SFNT/TrueType tables definitions and interface */
-/* (specification only). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * tttables.h
+ *
+ * Basic SFNT/TrueType tables definitions and interface
+ * (specification only).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef TTTABLES_H_
@@ -33,53 +33,55 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* <Section> */
- /* truetype_tables */
- /* */
- /* <Title> */
- /* TrueType Tables */
- /* */
- /* <Abstract> */
- /* TrueType specific table types and functions. */
- /* */
- /* <Description> */
- /* This section contains definitions of some basic tables specific to */
- /* TrueType and OpenType as well as some routines used to access and */
- /* process them. */
- /* */
- /* <Order> */
- /* TT_Header */
- /* TT_HoriHeader */
- /* TT_VertHeader */
- /* TT_OS2 */
- /* TT_Postscript */
- /* TT_PCLT */
- /* TT_MaxProfile */
- /* */
- /* FT_Sfnt_Tag */
- /* FT_Get_Sfnt_Table */
- /* FT_Load_Sfnt_Table */
- /* FT_Sfnt_Table_Info */
- /* */
- /* FT_Get_CMap_Language_ID */
- /* FT_Get_CMap_Format */
- /* */
- /* FT_PARAM_TAG_UNPATENTED_HINTING */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* TT_Header */
- /* */
- /* <Description> */
- /* A structure to model a TrueType font header table. All fields */
- /* follow the OpenType specification. */
- /* */
+ /**************************************************************************
+ *
+ * @section:
+ * truetype_tables
+ *
+ * @title:
+ * TrueType Tables
+ *
+ * @abstract:
+ * TrueType-specific table types and functions.
+ *
+ * @description:
+ * This section contains definitions of some basic tables specific to
+ * TrueType and OpenType as well as some routines used to access and
+ * process them.
+ *
+ * @order:
+ * TT_Header
+ * TT_HoriHeader
+ * TT_VertHeader
+ * TT_OS2
+ * TT_Postscript
+ * TT_PCLT
+ * TT_MaxProfile
+ *
+ * FT_Sfnt_Tag
+ * FT_Get_Sfnt_Table
+ * FT_Load_Sfnt_Table
+ * FT_Sfnt_Table_Info
+ *
+ * FT_Get_CMap_Language_ID
+ * FT_Get_CMap_Format
+ *
+ * FT_PARAM_TAG_UNPATENTED_HINTING
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * TT_Header
+ *
+ * @description:
+ * A structure to model a TrueType font header table. All fields follow
+ * the OpenType specification. The 64-bit timestamps are stored in
+ * two-element arrays `Created` and `Modified`, first the upper then
+ * the lower 32~bits.
+ */
typedef struct TT_Header_
{
FT_Fixed Table_Version;
@@ -91,8 +93,8 @@ FT_BEGIN_HEADER
FT_UShort Flags;
FT_UShort Units_Per_EM;
- FT_Long Created [2];
- FT_Long Modified[2];
+ FT_ULong Created [2];
+ FT_ULong Modified[2];
FT_Short xMin;
FT_Short yMin;
@@ -109,93 +111,93 @@ FT_BEGIN_HEADER
} TT_Header;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* TT_HoriHeader */
- /* */
- /* <Description> */
- /* A structure to model a TrueType horizontal header, the `hhea' */
- /* table, as well as the corresponding horizontal metrics table, */
- /* `hmtx'. */
- /* */
- /* <Fields> */
- /* Version :: The table version. */
- /* */
- /* Ascender :: The font's ascender, i.e., the distance */
- /* from the baseline to the top-most of all */
- /* glyph points found in the font. */
- /* */
- /* This value is invalid in many fonts, as */
- /* it is usually set by the font designer, */
- /* and often reflects only a portion of the */
- /* glyphs found in the font (maybe ASCII). */
- /* */
- /* You should use the `sTypoAscender' field */
- /* of the `OS/2' table instead if you want */
- /* the correct one. */
- /* */
- /* Descender :: The font's descender, i.e., the distance */
- /* from the baseline to the bottom-most of */
- /* all glyph points found in the font. It */
- /* is negative. */
- /* */
- /* This value is invalid in many fonts, as */
- /* it is usually set by the font designer, */
- /* and often reflects only a portion of the */
- /* glyphs found in the font (maybe ASCII). */
- /* */
- /* You should use the `sTypoDescender' */
- /* field of the `OS/2' table instead if you */
- /* want the correct one. */
- /* */
- /* Line_Gap :: The font's line gap, i.e., the distance */
- /* to add to the ascender and descender to */
- /* get the BTB, i.e., the */
- /* baseline-to-baseline distance for the */
- /* font. */
- /* */
- /* advance_Width_Max :: This field is the maximum of all advance */
- /* widths found in the font. It can be */
- /* used to compute the maximum width of an */
- /* arbitrary string of text. */
- /* */
- /* min_Left_Side_Bearing :: The minimum left side bearing of all */
- /* glyphs within the font. */
- /* */
- /* min_Right_Side_Bearing :: The minimum right side bearing of all */
- /* glyphs within the font. */
- /* */
- /* xMax_Extent :: The maximum horizontal extent (i.e., the */
- /* `width' of a glyph's bounding box) for */
- /* all glyphs in the font. */
- /* */
- /* caret_Slope_Rise :: The rise coefficient of the cursor's */
- /* slope of the cursor (slope=rise/run). */
- /* */
- /* caret_Slope_Run :: The run coefficient of the cursor's */
- /* slope. */
- /* */
- /* caret_Offset :: The cursor's offset for slanted fonts. */
- /* */
- /* Reserved :: 8~reserved bytes. */
- /* */
- /* metric_Data_Format :: Always~0. */
- /* */
- /* number_Of_HMetrics :: Number of HMetrics entries in the `hmtx' */
- /* table -- this value can be smaller than */
- /* the total number of glyphs in the font. */
- /* */
- /* long_metrics :: A pointer into the `hmtx' table. */
- /* */
- /* short_metrics :: A pointer into the `hmtx' table. */
- /* */
- /* <Note> */
- /* For an OpenType variation font, the values of the following fields */
- /* can change after a call to @FT_Set_Var_Design_Coordinates (and */
- /* friends) if the font contains an `MVAR' table: `caret_Slope_Rise', */
- /* `caret_Slope_Run', and `caret_Offset'. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * TT_HoriHeader
+ *
+ * @description:
+ * A structure to model a TrueType horizontal header, the 'hhea' table,
+ * as well as the corresponding horizontal metrics table, 'hmtx'.
+ *
+ * @fields:
+ * Version ::
+ * The table version.
+ *
+ * Ascender ::
+ * The font's ascender, i.e., the distance from the baseline to the
+ * top-most of all glyph points found in the font.
+ *
+ * This value is invalid in many fonts, as it is usually set by the
+ * font designer, and often reflects only a portion of the glyphs found
+ * in the font (maybe ASCII).
+ *
+ * You should use the `sTypoAscender` field of the 'OS/2' table instead
+ * if you want the correct one.
+ *
+ * Descender ::
+ * The font's descender, i.e., the distance from the baseline to the
+ * bottom-most of all glyph points found in the font. It is negative.
+ *
+ * This value is invalid in many fonts, as it is usually set by the
+ * font designer, and often reflects only a portion of the glyphs found
+ * in the font (maybe ASCII).
+ *
+ * You should use the `sTypoDescender` field of the 'OS/2' table
+ * instead if you want the correct one.
+ *
+ * Line_Gap ::
+ * The font's line gap, i.e., the distance to add to the ascender and
+ * descender to get the BTB, i.e., the baseline-to-baseline distance
+ * for the font.
+ *
+ * advance_Width_Max ::
+ * This field is the maximum of all advance widths found in the font.
+ * It can be used to compute the maximum width of an arbitrary string
+ * of text.
+ *
+ * min_Left_Side_Bearing ::
+ * The minimum left side bearing of all glyphs within the font.
+ *
+ * min_Right_Side_Bearing ::
+ * The minimum right side bearing of all glyphs within the font.
+ *
+ * xMax_Extent ::
+ * The maximum horizontal extent (i.e., the 'width' of a glyph's
+ * bounding box) for all glyphs in the font.
+ *
+ * caret_Slope_Rise ::
+ * The rise coefficient of the cursor's slope of the cursor
+ * (slope=rise/run).
+ *
+ * caret_Slope_Run ::
+ * The run coefficient of the cursor's slope.
+ *
+ * caret_Offset ::
+ * The cursor's offset for slanted fonts.
+ *
+ * Reserved ::
+ * 8~reserved bytes.
+ *
+ * metric_Data_Format ::
+ * Always~0.
+ *
+ * number_Of_HMetrics ::
+ * Number of HMetrics entries in the 'hmtx' table -- this value can be
+ * smaller than the total number of glyphs in the font.
+ *
+ * long_metrics ::
+ * A pointer into the 'hmtx' table.
+ *
+ * short_metrics ::
+ * A pointer into the 'hmtx' table.
+ *
+ * @note:
+ * For an OpenType variation font, the values of the following fields can
+ * change after a call to @FT_Set_Var_Design_Coordinates (and friends) if
+ * the font contains an 'MVAR' table: `caret_Slope_Rise`,
+ * `caret_Slope_Run`, and `caret_Offset`.
+ */
typedef struct TT_HoriHeader_
{
FT_Fixed Version;
@@ -219,7 +221,7 @@ FT_BEGIN_HEADER
/* The following fields are not defined by the OpenType specification */
/* but they are used to connect the metrics header to the relevant */
- /* `hmtx' table. */
+ /* 'hmtx' table. */
void* long_metrics;
void* short_metrics;
@@ -227,97 +229,93 @@ FT_BEGIN_HEADER
} TT_HoriHeader;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* TT_VertHeader */
- /* */
- /* <Description> */
- /* A structure used to model a TrueType vertical header, the `vhea' */
- /* table, as well as the corresponding vertical metrics table, */
- /* `vmtx'. */
- /* */
- /* <Fields> */
- /* Version :: The table version. */
- /* */
- /* Ascender :: The font's ascender, i.e., the distance */
- /* from the baseline to the top-most of */
- /* all glyph points found in the font. */
- /* */
- /* This value is invalid in many fonts, as */
- /* it is usually set by the font designer, */
- /* and often reflects only a portion of */
- /* the glyphs found in the font (maybe */
- /* ASCII). */
- /* */
- /* You should use the `sTypoAscender' */
- /* field of the `OS/2' table instead if */
- /* you want the correct one. */
- /* */
- /* Descender :: The font's descender, i.e., the */
- /* distance from the baseline to the */
- /* bottom-most of all glyph points found */
- /* in the font. It is negative. */
- /* */
- /* This value is invalid in many fonts, as */
- /* it is usually set by the font designer, */
- /* and often reflects only a portion of */
- /* the glyphs found in the font (maybe */
- /* ASCII). */
- /* */
- /* You should use the `sTypoDescender' */
- /* field of the `OS/2' table instead if */
- /* you want the correct one. */
- /* */
- /* Line_Gap :: The font's line gap, i.e., the distance */
- /* to add to the ascender and descender to */
- /* get the BTB, i.e., the */
- /* baseline-to-baseline distance for the */
- /* font. */
- /* */
- /* advance_Height_Max :: This field is the maximum of all */
- /* advance heights found in the font. It */
- /* can be used to compute the maximum */
- /* height of an arbitrary string of text. */
- /* */
- /* min_Top_Side_Bearing :: The minimum top side bearing of all */
- /* glyphs within the font. */
- /* */
- /* min_Bottom_Side_Bearing :: The minimum bottom side bearing of all */
- /* glyphs within the font. */
- /* */
- /* yMax_Extent :: The maximum vertical extent (i.e., the */
- /* `height' of a glyph's bounding box) for */
- /* all glyphs in the font. */
- /* */
- /* caret_Slope_Rise :: The rise coefficient of the cursor's */
- /* slope of the cursor (slope=rise/run). */
- /* */
- /* caret_Slope_Run :: The run coefficient of the cursor's */
- /* slope. */
- /* */
- /* caret_Offset :: The cursor's offset for slanted fonts. */
- /* */
- /* Reserved :: 8~reserved bytes. */
- /* */
- /* metric_Data_Format :: Always~0. */
- /* */
- /* number_Of_VMetrics :: Number of VMetrics entries in the */
- /* `vmtx' table -- this value can be */
- /* smaller than the total number of glyphs */
- /* in the font. */
- /* */
- /* long_metrics :: A pointer into the `vmtx' table. */
- /* */
- /* short_metrics :: A pointer into the `vmtx' table. */
- /* */
- /* <Note> */
- /* For an OpenType variation font, the values of the following fields */
- /* can change after a call to @FT_Set_Var_Design_Coordinates (and */
- /* friends) if the font contains an `MVAR' table: `Ascender', */
- /* `Descender', `Line_Gap', `caret_Slope_Rise', `caret_Slope_Run', */
- /* and `caret_Offset'. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * TT_VertHeader
+ *
+ * @description:
+ * A structure used to model a TrueType vertical header, the 'vhea'
+ * table, as well as the corresponding vertical metrics table, 'vmtx'.
+ *
+ * @fields:
+ * Version ::
+ * The table version.
+ *
+ * Ascender ::
+ * The font's ascender, i.e., the distance from the baseline to the
+ * top-most of all glyph points found in the font.
+ *
+ * This value is invalid in many fonts, as it is usually set by the
+ * font designer, and often reflects only a portion of the glyphs found
+ * in the font (maybe ASCII).
+ *
+ * You should use the `sTypoAscender` field of the 'OS/2' table instead
+ * if you want the correct one.
+ *
+ * Descender ::
+ * The font's descender, i.e., the distance from the baseline to the
+ * bottom-most of all glyph points found in the font. It is negative.
+ *
+ * This value is invalid in many fonts, as it is usually set by the
+ * font designer, and often reflects only a portion of the glyphs found
+ * in the font (maybe ASCII).
+ *
+ * You should use the `sTypoDescender` field of the 'OS/2' table
+ * instead if you want the correct one.
+ *
+ * Line_Gap ::
+ * The font's line gap, i.e., the distance to add to the ascender and
+ * descender to get the BTB, i.e., the baseline-to-baseline distance
+ * for the font.
+ *
+ * advance_Height_Max ::
+ * This field is the maximum of all advance heights found in the font.
+ * It can be used to compute the maximum height of an arbitrary string
+ * of text.
+ *
+ * min_Top_Side_Bearing ::
+ * The minimum top side bearing of all glyphs within the font.
+ *
+ * min_Bottom_Side_Bearing ::
+ * The minimum bottom side bearing of all glyphs within the font.
+ *
+ * yMax_Extent ::
+ * The maximum vertical extent (i.e., the 'height' of a glyph's
+ * bounding box) for all glyphs in the font.
+ *
+ * caret_Slope_Rise ::
+ * The rise coefficient of the cursor's slope of the cursor
+ * (slope=rise/run).
+ *
+ * caret_Slope_Run ::
+ * The run coefficient of the cursor's slope.
+ *
+ * caret_Offset ::
+ * The cursor's offset for slanted fonts.
+ *
+ * Reserved ::
+ * 8~reserved bytes.
+ *
+ * metric_Data_Format ::
+ * Always~0.
+ *
+ * number_Of_VMetrics ::
+ * Number of VMetrics entries in the 'vmtx' table -- this value can be
+ * smaller than the total number of glyphs in the font.
+ *
+ * long_metrics ::
+ * A pointer into the 'vmtx' table.
+ *
+ * short_metrics ::
+ * A pointer into the 'vmtx' table.
+ *
+ * @note:
+ * For an OpenType variation font, the values of the following fields can
+ * change after a call to @FT_Set_Var_Design_Coordinates (and friends) if
+ * the font contains an 'MVAR' table: `Ascender`, `Descender`,
+ * `Line_Gap`, `caret_Slope_Rise`, `caret_Slope_Run`, and `caret_Offset`.
+ */
typedef struct TT_VertHeader_
{
FT_Fixed Version;
@@ -341,7 +339,7 @@ FT_BEGIN_HEADER
/* The following fields are not defined by the OpenType specification */
/* but they are used to connect the metrics header to the relevant */
- /* `vmtx' table. */
+ /* 'vmtx' table. */
void* long_metrics;
void* short_metrics;
@@ -349,33 +347,31 @@ FT_BEGIN_HEADER
} TT_VertHeader;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* TT_OS2 */
- /* */
- /* <Description> */
- /* A structure to model a TrueType `OS/2' table. All fields comply */
- /* to the OpenType specification. */
- /* */
- /* Note that we now support old Mac fonts that do not include an */
- /* `OS/2' table. In this case, the `version' field is always set to */
- /* 0xFFFF. */
- /* */
- /* <Note> */
- /* For an OpenType variation font, the values of the following fields */
- /* can change after a call to @FT_Set_Var_Design_Coordinates (and */
- /* friends) if the font contains an `MVAR' table: `sCapHeight', */
- /* `sTypoAscender', `sTypoDescender', `sTypoLineGap', `sxHeight', */
- /* `usWinAscent', `usWinDescent', `yStrikeoutPosition', */
- /* `yStrikeoutSize', `ySubscriptXOffset', `ySubScriptXSize', */
- /* `ySubscriptYOffset', `ySubscriptYSize', `ySuperscriptXOffset', */
- /* `ySuperscriptXSize', `ySuperscriptYOffset', and */
- /* `ySuperscriptYSize'. */
- /* */
- /* Possible values for bits in the `ulUnicodeRangeX' fields are given */
- /* by the @TT_UCR_XXX macros. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * TT_OS2
+ *
+ * @description:
+ * A structure to model a TrueType 'OS/2' table. All fields comply to
+ * the OpenType specification.
+ *
+ * Note that we now support old Mac fonts that do not include an 'OS/2'
+ * table. In this case, the `version` field is always set to 0xFFFF.
+ *
+ * @note:
+ * For an OpenType variation font, the values of the following fields can
+ * change after a call to @FT_Set_Var_Design_Coordinates (and friends) if
+ * the font contains an 'MVAR' table: `sCapHeight`, `sTypoAscender`,
+ * `sTypoDescender`, `sTypoLineGap`, `sxHeight`, `usWinAscent`,
+ * `usWinDescent`, `yStrikeoutPosition`, `yStrikeoutSize`,
+ * `ySubscriptXOffset`, `ySubScriptXSize`, `ySubscriptYOffset`,
+ * `ySubscriptYSize`, `ySuperscriptXOffset`, `ySuperscriptXSize`,
+ * `ySuperscriptYOffset`, and `ySuperscriptYSize`.
+ *
+ * Possible values for bits in the `ulUnicodeRangeX` fields are given by
+ * the @TT_UCR_XXX macros.
+ */
typedef struct TT_OS2_
{
@@ -435,23 +431,23 @@ FT_BEGIN_HEADER
} TT_OS2;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* TT_Postscript */
- /* */
- /* <Description> */
- /* A structure to model a TrueType `post' table. All fields comply */
- /* to the OpenType specification. This structure does not reference */
- /* a font's PostScript glyph names; use @FT_Get_Glyph_Name to */
- /* retrieve them. */
- /* */
- /* <Note> */
- /* For an OpenType variation font, the values of the following fields */
- /* can change after a call to @FT_Set_Var_Design_Coordinates (and */
- /* friends) if the font contains an `MVAR' table: `underlinePosition' */
- /* and `underlineThickness'. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * TT_Postscript
+ *
+ * @description:
+ * A structure to model a TrueType 'post' table. All fields comply to
+ * the OpenType specification. This structure does not reference a
+ * font's PostScript glyph names; use @FT_Get_Glyph_Name to retrieve
+ * them.
+ *
+ * @note:
+ * For an OpenType variation font, the values of the following fields can
+ * change after a call to @FT_Set_Var_Design_Coordinates (and friends) if
+ * the font contains an 'MVAR' table: `underlinePosition` and
+ * `underlineThickness`.
+ */
typedef struct TT_Postscript_
{
FT_Fixed FormatType;
@@ -464,21 +460,21 @@ FT_BEGIN_HEADER
FT_ULong minMemType1;
FT_ULong maxMemType1;
- /* Glyph names follow in the `post' table, but we don't */
+ /* Glyph names follow in the 'post' table, but we don't */
/* load them by default. */
} TT_Postscript;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* TT_PCLT */
- /* */
- /* <Description> */
- /* A structure to model a TrueType `PCLT' table. All fields comply */
- /* to the OpenType specification. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * TT_PCLT
+ *
+ * @description:
+ * A structure to model a TrueType 'PCLT' table. All fields comply to
+ * the OpenType specification.
+ */
typedef struct TT_PCLT_
{
FT_Fixed Version;
@@ -500,70 +496,75 @@ FT_BEGIN_HEADER
} TT_PCLT;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* TT_MaxProfile */
- /* */
- /* <Description> */
- /* The maximum profile (`maxp') table contains many max values, which */
- /* can be used to pre-allocate arrays for speeding up glyph loading */
- /* and hinting. */
- /* */
- /* <Fields> */
- /* version :: The version number. */
- /* */
- /* numGlyphs :: The number of glyphs in this TrueType */
- /* font. */
- /* */
- /* maxPoints :: The maximum number of points in a */
- /* non-composite TrueType glyph. See also */
- /* `maxCompositePoints'. */
- /* */
- /* maxContours :: The maximum number of contours in a */
- /* non-composite TrueType glyph. See also */
- /* `maxCompositeContours'. */
- /* */
- /* maxCompositePoints :: The maximum number of points in a */
- /* composite TrueType glyph. See also */
- /* `maxPoints'. */
- /* */
- /* maxCompositeContours :: The maximum number of contours in a */
- /* composite TrueType glyph. See also */
- /* `maxContours'. */
- /* */
- /* maxZones :: The maximum number of zones used for */
- /* glyph hinting. */
- /* */
- /* maxTwilightPoints :: The maximum number of points in the */
- /* twilight zone used for glyph hinting. */
- /* */
- /* maxStorage :: The maximum number of elements in the */
- /* storage area used for glyph hinting. */
- /* */
- /* maxFunctionDefs :: The maximum number of function */
- /* definitions in the TrueType bytecode for */
- /* this font. */
- /* */
- /* maxInstructionDefs :: The maximum number of instruction */
- /* definitions in the TrueType bytecode for */
- /* this font. */
- /* */
- /* maxStackElements :: The maximum number of stack elements used */
- /* during bytecode interpretation. */
- /* */
- /* maxSizeOfInstructions :: The maximum number of TrueType opcodes */
- /* used for glyph hinting. */
- /* */
- /* maxComponentElements :: The maximum number of simple (i.e., non- */
- /* composite) glyphs in a composite glyph. */
- /* */
- /* maxComponentDepth :: The maximum nesting depth of composite */
- /* glyphs. */
- /* */
- /* <Note> */
- /* This structure is only used during font loading. */
- /* */
+ /**************************************************************************
+ *
+ * @struct:
+ * TT_MaxProfile
+ *
+ * @description:
+ * The maximum profile ('maxp') table contains many max values, which can
+ * be used to pre-allocate arrays for speeding up glyph loading and
+ * hinting.
+ *
+ * @fields:
+ * version ::
+ * The version number.
+ *
+ * numGlyphs ::
+ * The number of glyphs in this TrueType font.
+ *
+ * maxPoints ::
+ * The maximum number of points in a non-composite TrueType glyph. See
+ * also `maxCompositePoints`.
+ *
+ * maxContours ::
+ * The maximum number of contours in a non-composite TrueType glyph.
+ * See also `maxCompositeContours`.
+ *
+ * maxCompositePoints ::
+ * The maximum number of points in a composite TrueType glyph. See
+ * also `maxPoints`.
+ *
+ * maxCompositeContours ::
+ * The maximum number of contours in a composite TrueType glyph. See
+ * also `maxContours`.
+ *
+ * maxZones ::
+ * The maximum number of zones used for glyph hinting.
+ *
+ * maxTwilightPoints ::
+ * The maximum number of points in the twilight zone used for glyph
+ * hinting.
+ *
+ * maxStorage ::
+ * The maximum number of elements in the storage area used for glyph
+ * hinting.
+ *
+ * maxFunctionDefs ::
+ * The maximum number of function definitions in the TrueType bytecode
+ * for this font.
+ *
+ * maxInstructionDefs ::
+ * The maximum number of instruction definitions in the TrueType
+ * bytecode for this font.
+ *
+ * maxStackElements ::
+ * The maximum number of stack elements used during bytecode
+ * interpretation.
+ *
+ * maxSizeOfInstructions ::
+ * The maximum number of TrueType opcodes used for glyph hinting.
+ *
+ * maxComponentElements ::
+ * The maximum number of simple (i.e., non-composite) glyphs in a
+ * composite glyph.
+ *
+ * maxComponentDepth ::
+ * The maximum nesting depth of composite glyphs.
+ *
+ * @note:
+ * This structure is only used during font loading.
+ */
typedef struct TT_MaxProfile_
{
FT_Fixed version;
@@ -585,31 +586,38 @@ FT_BEGIN_HEADER
} TT_MaxProfile;
- /*************************************************************************/
- /* */
- /* <Enum> */
- /* FT_Sfnt_Tag */
- /* */
- /* <Description> */
- /* An enumeration to specify indices of SFNT tables loaded and parsed */
- /* by FreeType during initialization of an SFNT font. Used in the */
- /* @FT_Get_Sfnt_Table API function. */
- /* */
- /* <Values> */
- /* FT_SFNT_HEAD :: To access the font's @TT_Header structure. */
- /* */
- /* FT_SFNT_MAXP :: To access the font's @TT_MaxProfile structure. */
- /* */
- /* FT_SFNT_OS2 :: To access the font's @TT_OS2 structure. */
- /* */
- /* FT_SFNT_HHEA :: To access the font's @TT_HoriHeader structure. */
- /* */
- /* FT_SFNT_VHEA :: To access the font's @TT_VertHeader structure. */
- /* */
- /* FT_SFNT_POST :: To access the font's @TT_Postscript structure. */
- /* */
- /* FT_SFNT_PCLT :: To access the font's @TT_PCLT structure. */
- /* */
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_Sfnt_Tag
+ *
+ * @description:
+ * An enumeration to specify indices of SFNT tables loaded and parsed by
+ * FreeType during initialization of an SFNT font. Used in the
+ * @FT_Get_Sfnt_Table API function.
+ *
+ * @values:
+ * FT_SFNT_HEAD ::
+ * To access the font's @TT_Header structure.
+ *
+ * FT_SFNT_MAXP ::
+ * To access the font's @TT_MaxProfile structure.
+ *
+ * FT_SFNT_OS2 ::
+ * To access the font's @TT_OS2 structure.
+ *
+ * FT_SFNT_HHEA ::
+ * To access the font's @TT_HoriHeader structure.
+ *
+ * FT_SFNT_VHEA ::
+ * To access the font's @TT_VertHeader structure.
+ *
+ * FT_SFNT_POST ::
+ * To access the font's @TT_Postscript structure.
+ *
+ * FT_SFNT_PCLT ::
+ * To access the font's @TT_PCLT structure.
+ */
typedef enum FT_Sfnt_Tag_
{
FT_SFNT_HEAD,
@@ -624,7 +632,7 @@ FT_BEGIN_HEADER
} FT_Sfnt_Tag;
- /* these constants are deprecated; use the corresponding `FT_Sfnt_Tag' */
+ /* these constants are deprecated; use the corresponding `FT_Sfnt_Tag` */
/* values instead */
#define ft_sfnt_head FT_SFNT_HEAD
#define ft_sfnt_maxp FT_SFNT_MAXP
@@ -635,44 +643,46 @@ FT_BEGIN_HEADER
#define ft_sfnt_pclt FT_SFNT_PCLT
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Get_Sfnt_Table */
- /* */
- /* <Description> */
- /* Return a pointer to a given SFNT table stored within a face. */
- /* */
- /* <Input> */
- /* face :: A handle to the source. */
- /* */
- /* tag :: The index of the SFNT table. */
- /* */
- /* <Return> */
- /* A type-less pointer to the table. This will be NULL in case of */
- /* error, or if the corresponding table was not found *OR* loaded */
- /* from the file. */
- /* */
- /* Use a typecast according to `tag' to access the structure */
- /* elements. */
- /* */
- /* <Note> */
- /* The table is owned by the face object and disappears with it. */
- /* */
- /* This function is only useful to access SFNT tables that are loaded */
- /* by the sfnt, truetype, and opentype drivers. See @FT_Sfnt_Tag for */
- /* a list. */
- /* */
- /* Here an example how to access the `vhea' table: */
- /* */
- /* { */
- /* TT_VertHeader* vert_header; */
- /* */
- /* */
- /* vert_header = */
- /* (TT_VertHeader*)FT_Get_Sfnt_Table( face, FT_SFNT_VHEA ); */
- /* } */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Sfnt_Table
+ *
+ * @description:
+ * Return a pointer to a given SFNT table stored within a face.
+ *
+ * @input:
+ * face ::
+ * A handle to the source.
+ *
+ * tag ::
+ * The index of the SFNT table.
+ *
+ * @return:
+ * A type-less pointer to the table. This will be `NULL` in case of
+ * error, or if the corresponding table was not found **OR** loaded from
+ * the file.
+ *
+ * Use a typecast according to `tag` to access the structure elements.
+ *
+ * @note:
+ * The table is owned by the face object and disappears with it.
+ *
+ * This function is only useful to access SFNT tables that are loaded by
+ * the sfnt, truetype, and opentype drivers. See @FT_Sfnt_Tag for a
+ * list.
+ *
+ * @example:
+ * Here is an example demonstrating access to the 'vhea' table.
+ *
+ * ```
+ * TT_VertHeader* vert_header;
+ *
+ *
+ * vert_header =
+ * (TT_VertHeader*)FT_Get_Sfnt_Table( face, FT_SFNT_VHEA );
+ * ```
+ */
FT_EXPORT( void* )
FT_Get_Sfnt_Table( FT_Face face,
FT_Sfnt_Tag tag );
@@ -691,8 +701,8 @@ FT_BEGIN_HEADER
* A handle to the source face.
*
* tag ::
- * The four-byte tag of the table to load. Use value~0 if you want
- * to access the whole font file. Otherwise, you can use one of the
+ * The four-byte tag of the table to load. Use value~0 if you want to
+ * access the whole font file. Otherwise, you can use one of the
* definitions found in the @FT_TRUETYPE_TAGS_H file, or forge a new
* one with @FT_MAKE_TAG.
*
@@ -706,10 +716,10 @@ FT_BEGIN_HEADER
*
* @inout:
* length ::
- * If the `length' parameter is NULL, try to load the whole table.
+ * If the `length` parameter is `NULL`, try to load the whole table.
* Return an error code if it fails.
*
- * Else, if `*length' is~0, exit immediately while returning the
+ * Else, if `*length` is~0, exit immediately while returning the
* table's (or file) full size in it.
*
* Else the number of bytes to read from the table or file, from the
@@ -720,21 +730,21 @@ FT_BEGIN_HEADER
*
* @note:
* If you need to determine the table's length you should first call this
- * function with `*length' set to~0, as in the following example:
+ * function with `*length` set to~0, as in the following example:
*
- * {
- * FT_ULong length = 0;
+ * ```
+ * FT_ULong length = 0;
*
*
- * error = FT_Load_Sfnt_Table( face, tag, 0, NULL, &length );
- * if ( error ) { ... table does not exist ... }
+ * error = FT_Load_Sfnt_Table( face, tag, 0, NULL, &length );
+ * if ( error ) { ... table does not exist ... }
*
- * buffer = malloc( length );
- * if ( buffer == NULL ) { ... not enough memory ... }
+ * buffer = malloc( length );
+ * if ( buffer == NULL ) { ... not enough memory ... }
*
- * error = FT_Load_Sfnt_Table( face, tag, 0, buffer, &length );
- * if ( error ) { ... could not load table ... }
- * }
+ * error = FT_Load_Sfnt_Table( face, tag, 0, buffer, &length );
+ * if ( error ) { ... could not load table ... }
+ * ```
*
* Note that structures like @TT_Header or @TT_OS2 can't be used with
* this function; they are limited to @FT_Get_Sfnt_Table. Reason is that
@@ -768,14 +778,14 @@ FT_BEGIN_HEADER
*
* @inout:
* tag ::
- * The name tag of the SFNT table. If the value is NULL, `table_index'
- * is ignored, and `length' returns the number of SFNT tables in the
- * font.
+ * The name tag of the SFNT table. If the value is `NULL`,
+ * `table_index` is ignored, and `length` returns the number of SFNT
+ * tables in the font.
*
* @output:
* length ::
- * The length of the SFNT table (or the number of SFNT tables, depending
- * on `tag').
+ * The length of the SFNT table (or the number of SFNT tables,
+ * depending on `tag`).
*
* @return:
* FreeType error code. 0~means success.
@@ -792,46 +802,46 @@ FT_BEGIN_HEADER
FT_ULong *length );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Get_CMap_Language_ID */
- /* */
- /* <Description> */
- /* Return cmap language ID as specified in the OpenType standard. */
- /* Definitions of language ID values are in file @FT_TRUETYPE_IDS_H. */
- /* */
- /* <Input> */
- /* charmap :: */
- /* The target charmap. */
- /* */
- /* <Return> */
- /* The language ID of `charmap'. If `charmap' doesn't belong to an */
- /* SFNT face, just return~0 as the default value. */
- /* */
- /* For a format~14 cmap (to access Unicode IVS), the return value is */
- /* 0xFFFFFFFF. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_CMap_Language_ID
+ *
+ * @description:
+ * Return cmap language ID as specified in the OpenType standard.
+ * Definitions of language ID values are in file @FT_TRUETYPE_IDS_H.
+ *
+ * @input:
+ * charmap ::
+ * The target charmap.
+ *
+ * @return:
+ * The language ID of `charmap`. If `charmap` doesn't belong to an SFNT
+ * face, just return~0 as the default value.
+ *
+ * For a format~14 cmap (to access Unicode IVS), the return value is
+ * 0xFFFFFFFF.
+ */
FT_EXPORT( FT_ULong )
FT_Get_CMap_Language_ID( FT_CharMap charmap );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Get_CMap_Format */
- /* */
- /* <Description> */
- /* Return the format of an SFNT `cmap' table. */
- /* */
- /* <Input> */
- /* charmap :: */
- /* The target charmap. */
- /* */
- /* <Return> */
- /* The format of `charmap'. If `charmap' doesn't belong to an SFNT */
- /* face, return -1. */
- /* */
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_CMap_Format
+ *
+ * @description:
+ * Return the format of an SFNT 'cmap' table.
+ *
+ * @input:
+ * charmap ::
+ * The target charmap.
+ *
+ * @return:
+ * The format of `charmap`. If `charmap` doesn't belong to an SFNT face,
+ * return -1.
+ */
FT_EXPORT( FT_Long )
FT_Get_CMap_Format( FT_CharMap charmap );
diff --git a/thirdparty/freetype/include/freetype/tttags.h b/thirdparty/freetype/include/freetype/tttags.h
index e5cee68a15..bd0986eff0 100644
--- a/thirdparty/freetype/include/freetype/tttags.h
+++ b/thirdparty/freetype/include/freetype/tttags.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* tttags.h */
-/* */
-/* Tags for TrueType and OpenType tables (specification only). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * tttags.h
+ *
+ * Tags for TrueType and OpenType tables (specification only).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef TTAGS_H_
@@ -46,6 +46,8 @@ FT_BEGIN_HEADER
#define TTAG_CFF2 FT_MAKE_TAG( 'C', 'F', 'F', '2' )
#define TTAG_CID FT_MAKE_TAG( 'C', 'I', 'D', ' ' )
#define TTAG_cmap FT_MAKE_TAG( 'c', 'm', 'a', 'p' )
+#define TTAG_COLR FT_MAKE_TAG( 'C', 'O', 'L', 'R' )
+#define TTAG_CPAL FT_MAKE_TAG( 'C', 'P', 'A', 'L' )
#define TTAG_cvar FT_MAKE_TAG( 'c', 'v', 'a', 'r' )
#define TTAG_cvt FT_MAKE_TAG( 'c', 'v', 't', ' ' )
#define TTAG_DSIG FT_MAKE_TAG( 'D', 'S', 'I', 'G' )
diff --git a/thirdparty/freetype/include/freetype/ttunpat.h b/thirdparty/freetype/include/freetype/ttunpat.h
deleted file mode 100644
index f5e417089e..0000000000
--- a/thirdparty/freetype/include/freetype/ttunpat.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/***************************************************************************/
-/* */
-/* ttunpat.h */
-/* */
-/* Definitions for the unpatented TrueType hinting system. */
-/* Obsolete, retained for backward compatibility. */
-/* */
-/* Copyright 2003-2017 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* Written by Graham Asher <graham.asher@btinternet.com> */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#ifndef TTUNPAT_H_
-#define TTUNPAT_H_
-
-
-#include <ft2build.h>
-#include FT_FREETYPE_H
-
-#ifdef FREETYPE_H
-#error "freetype.h of FreeType 1 has been loaded!"
-#error "Please fix the directory search order for header files"
-#error "so that freetype.h of FreeType 2 is found first."
-#endif
-
-
-FT_BEGIN_HEADER
-
-
- /***************************************************************************
- *
- * @constant:
- * FT_PARAM_TAG_UNPATENTED_HINTING
- *
- * @description:
- * Deprecated.
- *
- * Previously: A constant used as the tag of an @FT_Parameter structure to
- * indicate that unpatented methods only should be used by the TrueType
- * bytecode interpreter for a typeface opened by @FT_Open_Face.
- *
- */
-#define FT_PARAM_TAG_UNPATENTED_HINTING FT_MAKE_TAG( 'u', 'n', 'p', 'a' )
-
- /* */
-
-
-FT_END_HEADER
-
-
-#endif /* TTUNPAT_H_ */
-
-
-/* END */
diff --git a/thirdparty/freetype/include/ft2build.h b/thirdparty/freetype/include/ft2build.h
index e7ce99bc94..e3f4887943 100644
--- a/thirdparty/freetype/include/ft2build.h
+++ b/thirdparty/freetype/include/ft2build.h
@@ -1,34 +1,36 @@
-/***************************************************************************/
-/* */
-/* ft2build.h */
-/* */
-/* FreeType 2 build and setup macros. */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* This is the `entry point' for FreeType header file inclusions. It is */
- /* the only header file which should be included directly; all other */
- /* FreeType header files should be accessed with macro names (after */
- /* including `ft2build.h'). */
- /* */
- /* A typical example is */
- /* */
- /* #include <ft2build.h> */
- /* #include FT_FREETYPE_H */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * ft2build.h
+ *
+ * FreeType 2 build and setup macros.
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * This is the 'entry point' for FreeType header file inclusions. It is
+ * the only header file which should be included directly; all other
+ * FreeType header files should be accessed with macro names (after
+ * including `ft2build.h`).
+ *
+ * A typical example is
+ *
+ * ```
+ * #include <ft2build.h>
+ * #include FT_FREETYPE_H
+ * ```
+ *
+ */
#ifndef FT2BUILD_H_
diff --git a/thirdparty/freetype/src/autofit/afangles.c b/thirdparty/freetype/src/autofit/afangles.c
index c65a3ae23e..9e1f7a21ff 100644
--- a/thirdparty/freetype/src/autofit/afangles.c
+++ b/thirdparty/freetype/src/autofit/afangles.c
@@ -1,28 +1,28 @@
-/***************************************************************************/
-/* */
-/* afangles.c */
-/* */
-/* Routines used to compute vector angles with limited accuracy */
-/* and very high speed. It also contains sorting routines (body). */
-/* */
-/* Copyright 2003-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * afangles.c
+ *
+ * Routines used to compute vector angles with limited accuracy
+ * and very high speed. It also contains sorting routines (body).
+ *
+ * Copyright (C) 2003-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include "aftypes.h"
/*
- * We are not using `af_angle_atan' anymore, but we keep the source
- * code below just in case...
+ * We are not using `af_angle_atan' anymore, but we keep the source
+ * code below just in case...
*/
@@ -30,16 +30,16 @@
/*
- * The trick here is to realize that we don't need a very accurate angle
- * approximation. We are going to use the result of `af_angle_atan' to
- * only compare the sign of angle differences, or check whether its
- * magnitude is very small.
+ * The trick here is to realize that we don't need a very accurate angle
+ * approximation. We are going to use the result of `af_angle_atan' to
+ * only compare the sign of angle differences, or check whether its
+ * magnitude is very small.
*
- * The approximation
+ * The approximation
*
- * dy * PI / (|dx|+|dy|)
+ * dy * PI / (|dx|+|dy|)
*
- * should be enough, and much faster to compute.
+ * should be enough, and much faster to compute.
*/
FT_LOCAL_DEF( AF_Angle )
af_angle_atan( FT_Fixed dx,
diff --git a/thirdparty/freetype/src/autofit/afangles.h b/thirdparty/freetype/src/autofit/afangles.h
index f33f9e108e..18d7dae3a6 100644
--- a/thirdparty/freetype/src/autofit/afangles.h
+++ b/thirdparty/freetype/src/autofit/afangles.h
@@ -1,7 +1,7 @@
/*
- * afangles.h
+ * afangles.h
*
- * This is a dummy file, used to please the build system. It is never
- * included by the auto-fitter sources.
+ * This is a dummy file, used to please the build system. It is never
+ * included by the auto-fitter sources.
*
*/
diff --git a/thirdparty/freetype/src/autofit/afblue.c b/thirdparty/freetype/src/autofit/afblue.c
index e4078fd044..28da159008 100644
--- a/thirdparty/freetype/src/autofit/afblue.c
+++ b/thirdparty/freetype/src/autofit/afblue.c
@@ -1,22 +1,22 @@
/* This file has been generated by the Perl script `afblue.pl', */
/* using data from file `afblue.dat'. */
-/***************************************************************************/
-/* */
-/* afblue.c */
-/* */
-/* Auto-fitter data for blue strings (body). */
-/* */
-/* Copyright 2013-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * afblue.c
+ *
+ * Auto-fitter data for blue strings (body).
+ *
+ * Copyright (C) 2013-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include "aftypes.h"
diff --git a/thirdparty/freetype/src/autofit/afblue.cin b/thirdparty/freetype/src/autofit/afblue.cin
index 4913e2eb6f..6545d1fd43 100644
--- a/thirdparty/freetype/src/autofit/afblue.cin
+++ b/thirdparty/freetype/src/autofit/afblue.cin
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* afblue.c */
-/* */
-/* Auto-fitter data for blue strings (body). */
-/* */
-/* Copyright 2013-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * afblue.c
+ *
+ * Auto-fitter data for blue strings (body).
+ *
+ * Copyright (C) 2013-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include "aftypes.h"
diff --git a/thirdparty/freetype/src/autofit/afblue.dat b/thirdparty/freetype/src/autofit/afblue.dat
index bc2f0d2754..14a0993b61 100644
--- a/thirdparty/freetype/src/autofit/afblue.dat
+++ b/thirdparty/freetype/src/autofit/afblue.dat
@@ -1,15 +1,15 @@
-// afblue.dat
+// afblue.dat
//
-// Auto-fitter data for blue strings.
+// Auto-fitter data for blue strings.
//
-// Copyright 2013-2018 by
-// David Turner, Robert Wilhelm, and Werner Lemberg.
+// Copyright (C) 2013-2019 by
+// David Turner, Robert Wilhelm, and Werner Lemberg.
//
-// This file is part of the FreeType project, and may only be used,
-// modified, and distributed under the terms of the FreeType project
-// license, LICENSE.TXT. By continuing to use, modify, or distribute
-// this file you indicate that you have read the license and
-// understand and accept it fully.
+// This file is part of the FreeType project, and may only be used,
+// modified, and distributed under the terms of the FreeType project
+// license, LICENSE.TXT. By continuing to use, modify, or distribute
+// this file you indicate that you have read the license and
+// understand and accept it fully.
// This file contains data specific to blue zones. It gets processed by
diff --git a/thirdparty/freetype/src/autofit/afblue.h b/thirdparty/freetype/src/autofit/afblue.h
index de31e259c3..a2ff597b8e 100644
--- a/thirdparty/freetype/src/autofit/afblue.h
+++ b/thirdparty/freetype/src/autofit/afblue.h
@@ -1,22 +1,22 @@
/* This file has been generated by the Perl script `afblue.pl', */
/* using data from file `afblue.dat'. */
-/***************************************************************************/
-/* */
-/* afblue.h */
-/* */
-/* Auto-fitter data for blue strings (specification). */
-/* */
-/* Copyright 2013-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * afblue.h
+ *
+ * Auto-fitter data for blue strings (specification).
+ *
+ * Copyright (C) 2013-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef AFBLUE_H_
diff --git a/thirdparty/freetype/src/autofit/afblue.hin b/thirdparty/freetype/src/autofit/afblue.hin
index 682147cb30..30a28dafa5 100644
--- a/thirdparty/freetype/src/autofit/afblue.hin
+++ b/thirdparty/freetype/src/autofit/afblue.hin
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* afblue.h */
-/* */
-/* Auto-fitter data for blue strings (specification). */
-/* */
-/* Copyright 2013-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * afblue.h
+ *
+ * Auto-fitter data for blue strings (specification).
+ *
+ * Copyright (C) 2013-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef AFBLUE_H_
diff --git a/thirdparty/freetype/src/autofit/afcjk.c b/thirdparty/freetype/src/autofit/afcjk.c
index 21b6bffa33..3b2b1cf24c 100644
--- a/thirdparty/freetype/src/autofit/afcjk.c
+++ b/thirdparty/freetype/src/autofit/afcjk.c
@@ -1,24 +1,24 @@
-/***************************************************************************/
-/* */
-/* afcjk.c */
-/* */
-/* Auto-fitter hinting routines for CJK writing system (body). */
-/* */
-/* Copyright 2006-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * afcjk.c
+ *
+ * Auto-fitter hinting routines for CJK writing system (body).
+ *
+ * Copyright (C) 2006-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
/*
- * The algorithm is based on akito's autohint patch, archived at
+ * The algorithm is based on akito's autohint patch, archived at
*
- * https://web.archive.org/web/20051219160454/http://www.kde.gr.jp:80/~akito/patch/freetype2/2.1.7/
+ * https://web.archive.org/web/20051219160454/http://www.kde.gr.jp:80/~akito/patch/freetype2/2.1.7/
*
*/
@@ -27,7 +27,6 @@
#include FT_INTERNAL_DEBUG_H
#include "afglobal.h"
-#include "afpic.h"
#include "aflatin.h"
#include "afcjk.h"
@@ -44,14 +43,14 @@
#endif
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_afcjk
+#define FT_COMPONENT afcjk
/*************************************************************************/
@@ -92,23 +91,29 @@
AF_CJKMetricsRec dummy[1];
AF_Scaler scaler = &dummy->root.scaler;
-#ifdef FT_CONFIG_OPTION_PIC
- AF_FaceGlobals globals = metrics->root.globals;
-#endif
-
AF_StyleClass style_class = metrics->root.style_class;
- AF_ScriptClass script_class = AF_SCRIPT_CLASSES_GET
- [style_class->script];
+ AF_ScriptClass script_class = af_script_classes[style_class->script];
+
+ /* If HarfBuzz is not available, we need a pointer to a single */
+ /* unsigned long value. */
+#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
+ void* shaper_buf;
+#else
+ FT_ULong shaper_buf_;
+ void* shaper_buf = &shaper_buf_;
+#endif
- void* shaper_buf;
const char* p;
#ifdef FT_DEBUG_LEVEL_TRACE
FT_ULong ch = 0;
#endif
- p = script_class->standard_charstring;
+ p = script_class->standard_charstring;
+
+#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
shaper_buf = af_shaper_buf_create( face );
+#endif
/* We check a list of standard characters. The first match wins. */
@@ -193,10 +198,10 @@
goto Exit;
/*
- * We assume that the glyphs selected for the stem width
- * computation are `featureless' enough so that the linking
- * algorithm works fine without adjustments of its scoring
- * function.
+ * We assume that the glyphs selected for the stem width
+ * computation are `featureless' enough so that the linking
+ * algorithm works fine without adjustments of its scoring
+ * function.
*/
af_latin_hints_link_segments( hints,
0,
@@ -296,7 +301,14 @@
AF_Blue_Stringset bss = sc->blue_stringset;
const AF_Blue_StringRec* bs = &af_blue_stringsets[bss];
- void* shaper_buf;
+ /* If HarfBuzz is not available, we need a pointer to a single */
+ /* unsigned long value. */
+#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
+ void* shaper_buf;
+#else
+ FT_ULong shaper_buf_;
+ void* shaper_buf = &shaper_buf_;
+#endif
/* we walk over the blue character strings as specified in the */
@@ -307,7 +319,9 @@
"==========================\n"
"\n" ));
+#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
shaper_buf = af_shaper_buf_create( face );
+#endif
for ( ; bs->string != AF_BLUE_STRING_MAX; bs++ )
{
@@ -483,8 +497,8 @@
if ( num_flats == 0 && num_fills == 0 )
{
/*
- * we couldn't find a single glyph to compute this blue zone,
- * we will simply ignore it then
+ * we couldn't find a single glyph to compute this blue zone,
+ * we will simply ignore it then
*/
FT_TRACE5(( " empty\n" ));
continue;
@@ -565,15 +579,25 @@
FT_Bool started = 0, same_width = 1;
FT_Fixed advance = 0, old_advance = 0;
- void* shaper_buf;
+ /* If HarfBuzz is not available, we need a pointer to a single */
+ /* unsigned long value. */
+#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
+ void* shaper_buf;
+#else
+ FT_ULong shaper_buf_;
+ void* shaper_buf = &shaper_buf_;
+#endif
/* in all supported charmaps, digits have character codes 0x30-0x39 */
const char digits[] = "0 1 2 3 4 5 6 7 8 9";
const char* p;
- p = digits;
+ p = digits;
+
+#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
shaper_buf = af_shaper_buf_create( face );
+#endif
while ( *p )
{
@@ -890,11 +914,11 @@
}
/*
- * now compute the `serif' segments
+ * now compute the `serif' segments
*
- * In Hanzi, some strokes are wider on one or both of the ends.
- * We either identify the stems on the ends as serifs or remove
- * the linkage, depending on the length of the stems.
+ * In Hanzi, some strokes are wider on one or both of the ends.
+ * We either identify the stems on the ends as serifs or remove
+ * the linkage, depending on the length of the stems.
*
*/
@@ -1000,21 +1024,21 @@
scale = ( dim == AF_DIMENSION_HORZ ) ? hints->x_scale
: hints->y_scale;
- /*********************************************************************/
- /* */
- /* We begin by generating a sorted table of edges for the current */
- /* direction. To do so, we simply scan each segment and try to find */
- /* an edge in our table that corresponds to its position. */
- /* */
- /* If no edge is found, we create and insert a new edge in the */
- /* sorted table. Otherwise, we simply add the segment to the edge's */
- /* list which is then processed in the second step to compute the */
- /* edge's properties. */
- /* */
- /* Note that the edges table is sorted along the segment/edge */
- /* position. */
- /* */
- /*********************************************************************/
+ /**********************************************************************
+ *
+ * We begin by generating a sorted table of edges for the current
+ * direction. To do so, we simply scan each segment and try to find
+ * an edge in our table that corresponds to its position.
+ *
+ * If no edge is found, we create and insert a new edge in the
+ * sorted table. Otherwise, we simply add the segment to the edge's
+ * list which is then processed in the second step to compute the
+ * edge's properties.
+ *
+ * Note that the edges table is sorted along the segment/edge
+ * position.
+ *
+ */
edge_distance_threshold = FT_MulFix( laxis->edge_distance_threshold,
scale );
@@ -1114,17 +1138,17 @@
}
}
- /******************************************************************/
- /* */
- /* Good, we now compute each edge's properties according to the */
- /* segments found on its position. Basically, these are */
- /* */
- /* - the edge's main direction */
- /* - stem edge, serif edge or both (which defaults to stem then) */
- /* - rounded edge, straight or both (which defaults to straight) */
- /* - link for edge */
- /* */
- /******************************************************************/
+ /*******************************************************************
+ *
+ * Good, we now compute each edge's properties according to the
+ * segments found on its position. Basically, these are
+ *
+ * - the edge's main direction
+ * - stem edge, serif edge or both (which defaults to stem then)
+ * - rounded edge, straight or both (which defaults to straight)
+ * - link for edge
+ *
+ */
/* first of all, set the `edge' field in each segment -- this is */
/* required in order to compute edge links */
@@ -1174,7 +1198,7 @@
/* check for links -- if seg->serif is set, then seg->link must */
/* be ignored */
- is_serif = (FT_Bool)( seg->serif && seg->serif->edge != edge );
+ is_serif = FT_BOOL( seg->serif && seg->serif->edge != edge );
if ( seg->link || is_serif )
{
@@ -1364,8 +1388,8 @@
af_glyph_hints_rescale( hints, (AF_StyleMetrics)metrics );
/*
- * correct x_scale and y_scale when needed, since they may have
- * been modified af_cjk_scale_dim above
+ * correct x_scale and y_scale when needed, since they may have
+ * been modified af_cjk_scale_dim above
*/
hints->x_scale = metrics->axis[AF_DIMENSION_HORZ].scale;
hints->x_delta = metrics->axis[AF_DIMENSION_HORZ].delta;
@@ -1384,21 +1408,21 @@
other_flags = 0;
/*
- * We snap the width of vertical stems for the monochrome and
- * horizontal LCD rendering targets only.
+ * We snap the width of vertical stems for the monochrome and
+ * horizontal LCD rendering targets only.
*/
if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD )
other_flags |= AF_LATIN_HINTS_HORZ_SNAP;
/*
- * We snap the width of horizontal stems for the monochrome and
- * vertical LCD rendering targets only.
+ * We snap the width of horizontal stems for the monochrome and
+ * vertical LCD rendering targets only.
*/
if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD_V )
other_flags |= AF_LATIN_HINTS_VERT_SNAP;
/*
- * We adjust stems to full pixels unless in `light' or `lcd' mode.
+ * We adjust stems to full pixels unless in `light' or `lcd' mode.
*/
if ( mode != FT_RENDER_MODE_LIGHT && mode != FT_RENDER_MODE_LCD )
other_flags |= AF_LATIN_HINTS_STEM_ADJUST;
@@ -2094,8 +2118,8 @@
goto Exit;
/*
- * now hint the remaining edges (serifs and single) in order
- * to complete our processing
+ * now hint the remaining edges (serifs and single) in order
+ * to complete our processing
*/
for ( edge = edges; edge < edge_limit; edge++ )
{
diff --git a/thirdparty/freetype/src/autofit/afcjk.h b/thirdparty/freetype/src/autofit/afcjk.h
index d229c0c9cf..59acae5342 100644
--- a/thirdparty/freetype/src/autofit/afcjk.h
+++ b/thirdparty/freetype/src/autofit/afcjk.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* afcjk.h */
-/* */
-/* Auto-fitter hinting routines for CJK writing system (specification). */
-/* */
-/* Copyright 2006-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * afcjk.h
+ *
+ * Auto-fitter hinting routines for CJK writing system (specification).
+ *
+ * Copyright (C) 2006-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef AFCJK_H_
@@ -41,9 +41,9 @@ FT_BEGIN_HEADER
/*
- * CJK glyphs tend to fill the square. So we have both vertical and
- * horizontal blue zones. But some glyphs have flat bounding strokes that
- * leave some space between neighbour glyphs.
+ * CJK glyphs tend to fill the square. So we have both vertical and
+ * horizontal blue zones. But some glyphs have flat bounding strokes that
+ * leave some space between neighbour glyphs.
*/
#define AF_CJK_IS_TOP_BLUE( b ) \
diff --git a/thirdparty/freetype/src/autofit/afcover.h b/thirdparty/freetype/src/autofit/afcover.h
index 6eeb8fc9fb..ff207a97e0 100644
--- a/thirdparty/freetype/src/autofit/afcover.h
+++ b/thirdparty/freetype/src/autofit/afcover.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* afcover.h */
-/* */
-/* Auto-fitter coverages (specification only). */
-/* */
-/* Copyright 2013-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * afcover.h
+ *
+ * Auto-fitter coverages (specification only).
+ *
+ * Copyright (C) 2013-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
/* This header file can be included multiple times. */
diff --git a/thirdparty/freetype/src/autofit/afdummy.c b/thirdparty/freetype/src/autofit/afdummy.c
index f30c517cbb..7e07a41e7d 100644
--- a/thirdparty/freetype/src/autofit/afdummy.c
+++ b/thirdparty/freetype/src/autofit/afdummy.c
@@ -1,20 +1,20 @@
-/***************************************************************************/
-/* */
-/* afdummy.c */
-/* */
-/* Auto-fitter dummy routines to be used if no hinting should be */
-/* performed (body). */
-/* */
-/* Copyright 2003-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * afdummy.c
+ *
+ * Auto-fitter dummy routines to be used if no hinting should be
+ * performed (body).
+ *
+ * Copyright (C) 2003-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include "afdummy.h"
@@ -38,13 +38,15 @@
static FT_Error
- af_dummy_hints_apply( FT_UInt glyph_index,
- AF_GlyphHints hints,
- FT_Outline* outline )
+ af_dummy_hints_apply( FT_UInt glyph_index,
+ AF_GlyphHints hints,
+ FT_Outline* outline,
+ AF_StyleMetrics metrics )
{
FT_Error error;
FT_UNUSED( glyph_index );
+ FT_UNUSED( metrics );
error = af_glyph_hints_reload( hints, outline );
diff --git a/thirdparty/freetype/src/autofit/afdummy.h b/thirdparty/freetype/src/autofit/afdummy.h
index b382acd92a..ab9227d35d 100644
--- a/thirdparty/freetype/src/autofit/afdummy.h
+++ b/thirdparty/freetype/src/autofit/afdummy.h
@@ -1,20 +1,20 @@
-/***************************************************************************/
-/* */
-/* afdummy.h */
-/* */
-/* Auto-fitter dummy routines to be used if no hinting should be */
-/* performed (specification). */
-/* */
-/* Copyright 2003-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * afdummy.h
+ *
+ * Auto-fitter dummy routines to be used if no hinting should be
+ * performed (specification).
+ *
+ * Copyright (C) 2003-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef AFDUMMY_H_
diff --git a/thirdparty/freetype/src/autofit/aferrors.h b/thirdparty/freetype/src/autofit/aferrors.h
index e5de54360f..2ec336f72c 100644
--- a/thirdparty/freetype/src/autofit/aferrors.h
+++ b/thirdparty/freetype/src/autofit/aferrors.h
@@ -1,27 +1,27 @@
-/***************************************************************************/
-/* */
-/* aferrors.h */
-/* */
-/* Autofitter error codes (specification only). */
-/* */
-/* Copyright 2005-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* This file is used to define the Autofitter error enumeration */
- /* constants. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * aferrors.h
+ *
+ * Autofitter error codes (specification only).
+ *
+ * Copyright (C) 2005-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * This file is used to define the Autofitter error enumeration
+ * constants.
+ *
+ */
#ifndef AFERRORS_H_
#define AFERRORS_H_
diff --git a/thirdparty/freetype/src/autofit/afglobal.c b/thirdparty/freetype/src/autofit/afglobal.c
index 3d09c53e8a..7183ce4a78 100644
--- a/thirdparty/freetype/src/autofit/afglobal.c
+++ b/thirdparty/freetype/src/autofit/afglobal.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* afglobal.c */
-/* */
-/* Auto-fitter routines to compute global hinting values (body). */
-/* */
-/* Copyright 2003-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * afglobal.c
+ *
+ * Auto-fitter routines to compute global hinting values (body).
+ *
+ * Copyright (C) 2003-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include "afglobal.h"
@@ -22,14 +22,14 @@
#include FT_INTERNAL_DEBUG_H
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_afglobal
+#define FT_COMPONENT afglobal
/* get writing system specific header files */
@@ -38,7 +38,6 @@
#include "afwrtsys.h"
#include "aferrors.h"
-#include "afpic.h"
#undef SCRIPT
@@ -67,8 +66,6 @@
#include "afstyles.h"
-#ifndef FT_CONFIG_OPTION_PIC
-
#undef WRITING_SYSTEM
#define WRITING_SYSTEM( ws, WS ) \
&af_ ## ws ## _writing_system_class,
@@ -110,8 +107,6 @@
NULL /* do not remove */
};
-#endif /* !FT_CONFIG_OPTION_PIC */
-
#ifdef FT_DEBUG_LEVEL_TRACE
@@ -159,12 +154,12 @@
}
/* scan each style in a Unicode charmap */
- for ( ss = 0; AF_STYLE_CLASSES_GET[ss]; ss++ )
+ for ( ss = 0; af_style_classes[ss]; ss++ )
{
AF_StyleClass style_class =
- AF_STYLE_CLASSES_GET[ss];
+ af_style_classes[ss];
AF_ScriptClass script_class =
- AF_SCRIPT_CLASSES_GET[style_class->script];
+ af_script_classes[style_class->script];
AF_Script_UniRange range;
@@ -172,8 +167,8 @@
continue;
/*
- * Scan all Unicode points in the range and set the corresponding
- * glyph style index.
+ * Scan all Unicode points in the range and set the corresponding
+ * glyph style index.
*/
if ( style_class->coverage == AF_COVERAGE_DEFAULT )
{
@@ -246,9 +241,9 @@
}
/* handle the remaining default OpenType features ... */
- for ( ss = 0; AF_STYLE_CLASSES_GET[ss]; ss++ )
+ for ( ss = 0; af_style_classes[ss]; ss++ )
{
- AF_StyleClass style_class = AF_STYLE_CLASSES_GET[ss];
+ AF_StyleClass style_class = af_style_classes[ss];
if ( style_class->coverage == AF_COVERAGE_DEFAULT )
@@ -256,7 +251,7 @@
}
/* ... and finally the default OpenType features of the default script */
- af_shaper_get_coverage( globals, AF_STYLE_CLASSES_GET[dflt], gstyles, 1 );
+ af_shaper_get_coverage( globals, af_style_classes[dflt], gstyles, 1 );
/* mark ASCII digits */
for ( i = 0x30; i <= 0x39; i++ )
@@ -270,8 +265,8 @@
Exit:
/*
- * By default, all uncovered glyphs are set to the fallback style.
- * XXX: Shouldn't we disable hinting or do something similar?
+ * By default, all uncovered glyphs are set to the fallback style.
+ * XXX: Shouldn't we disable hinting or do something similar?
*/
if ( globals->module->fallback_style != AF_STYLE_UNASSIGNED )
{
@@ -295,9 +290,9 @@
"==============\n"
"\n" ));
- for ( ss = 0; AF_STYLE_CLASSES_GET[ss]; ss++ )
+ for ( ss = 0; af_style_classes[ss]; ss++ )
{
- AF_StyleClass style_class = AF_STYLE_CLASSES_GET[ss];
+ AF_StyleClass style_class = af_style_classes[ss];
FT_UInt count = 0;
FT_Long idx;
@@ -397,9 +392,9 @@
if ( globals->metrics[nn] )
{
AF_StyleClass style_class =
- AF_STYLE_CLASSES_GET[nn];
+ af_style_classes[nn];
AF_WritingSystemClass writing_system_class =
- AF_WRITING_SYSTEM_CLASSES_GET[style_class->writing_system];
+ af_writing_system_classes[style_class->writing_system];
if ( writing_system_class->style_metrics_done )
@@ -448,8 +443,8 @@
style = (AF_Style)( globals->glyph_styles[gindex] &
AF_STYLE_UNASSIGNED );
- style_class = AF_STYLE_CLASSES_GET[style];
- writing_system_class = AF_WRITING_SYSTEM_CLASSES_GET
+ style_class = af_style_classes[style];
+ writing_system_class = af_writing_system_classes
[style_class->writing_system];
metrics = globals->metrics[style];
@@ -494,9 +489,9 @@
FT_UInt gindex )
{
if ( gindex < (FT_ULong)globals->glyph_count )
- return (FT_Bool)( globals->glyph_styles[gindex] & AF_DIGIT );
+ return FT_BOOL( globals->glyph_styles[gindex] & AF_DIGIT );
- return (FT_Bool)0;
+ return FT_BOOL( 0 );
}
diff --git a/thirdparty/freetype/src/autofit/afglobal.h b/thirdparty/freetype/src/autofit/afglobal.h
index 489ed46d9e..52f38350db 100644
--- a/thirdparty/freetype/src/autofit/afglobal.h
+++ b/thirdparty/freetype/src/autofit/afglobal.h
@@ -1,20 +1,20 @@
-/***************************************************************************/
-/* */
-/* afglobal.h */
-/* */
-/* Auto-fitter routines to compute global hinting values */
-/* (specification). */
-/* */
-/* Copyright 2003-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * afglobal.h
+ *
+ * Auto-fitter routines to compute global hinting values
+ * (specification).
+ *
+ * Copyright (C) 2003-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef AFGLOBAL_H_
@@ -60,8 +60,8 @@ FT_BEGIN_HEADER
/*
- * Default values and flags for both autofitter globals (found in
- * AF_ModuleRec) and face globals (in AF_FaceGlobalsRec).
+ * Default values and flags for both autofitter globals (found in
+ * AF_ModuleRec) and face globals (in AF_FaceGlobalsRec).
*/
/* index of fallback style in `af_style_classes' */
@@ -98,8 +98,8 @@ FT_BEGIN_HEADER
/*
- * Note that glyph_styles[] maps each glyph to an index into the
- * `af_style_classes' array.
+ * Note that glyph_styles[] maps each glyph to an index into the
+ * `af_style_classes' array.
*
*/
typedef struct AF_FaceGlobalsRec_
@@ -140,8 +140,8 @@ FT_BEGIN_HEADER
/*
- * model the global hints data for a given face, decomposed into
- * style-specific items
+ * model the global hints data for a given face, decomposed into
+ * style-specific items
*/
FT_LOCAL( FT_Error )
diff --git a/thirdparty/freetype/src/autofit/afhints.c b/thirdparty/freetype/src/autofit/afhints.c
index 0666dbc8e2..ed111c4117 100644
--- a/thirdparty/freetype/src/autofit/afhints.c
+++ b/thirdparty/freetype/src/autofit/afhints.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* afhints.c */
-/* */
-/* Auto-fitter hinting routines (body). */
-/* */
-/* Copyright 2003-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * afhints.c
+ *
+ * Auto-fitter hinting routines (body).
+ *
+ * Copyright (C) 2003-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include "afhints.h"
@@ -22,14 +22,14 @@
#include FT_INTERNAL_DEBUG_H
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_afhints
+#define FT_COMPONENT afhints
/* Get new segment for given axis. */
@@ -297,6 +297,19 @@
}
+ static int
+ af_get_strong_edge_index( AF_GlyphHints hints,
+ AF_Edge* strong_edges,
+ int dimension )
+ {
+ AF_AxisHints axis = &hints->axis[dimension];
+ AF_Edge edges = axis->edges;
+
+
+ return AF_INDEX_NUM( strong_edges[dimension], edges );
+ }
+
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -317,8 +330,10 @@
{
AF_DUMP(( " index hedge hseg vedge vseg flags "
/* " XXXXX XXXXX XXXXX XXXXX XXXXX XXXXXX" */
- " xorg yorg xscale yscale xfit yfit" ));
+ " xorg yorg xscale yscale xfit yfit "
/* " XXXXX XXXXX XXXX.XX XXXX.XX XXXX.XX XXXX.XX" */
+ " hbef haft vbef vaft" ));
+ /* " XXXXX XXXXX XXXXX XXXXX" */
}
else
AF_DUMP(( " (none)\n" ));
@@ -330,6 +345,7 @@
int segment_idx_1 = af_get_segment_index( hints, point_idx, 1 );
char buf1[16], buf2[16], buf3[16], buf4[16];
+ char buf5[16], buf6[16], buf7[16], buf8[16];
/* insert extra newline at the beginning of a contour */
@@ -340,7 +356,8 @@
}
AF_DUMP(( " %5d %5s %5s %5s %5s %s"
- " %5d %5d %7.2f %7.2f %7.2f %7.2f\n",
+ " %5d %5d %7.2f %7.2f %7.2f %7.2f"
+ " %5s %5s %5s %5s\n",
point_idx,
af_print_idx( buf1,
af_get_edge_index( hints, segment_idx_1, 1 ) ),
@@ -359,7 +376,20 @@
point->ox / 64.0,
point->oy / 64.0,
point->x / 64.0,
- point->y / 64.0 ));
+ point->y / 64.0,
+
+ af_print_idx( buf5, af_get_strong_edge_index( hints,
+ point->before,
+ 1 ) ),
+ af_print_idx( buf6, af_get_strong_edge_index( hints,
+ point->after,
+ 1 ) ),
+ af_print_idx( buf7, af_get_strong_edge_index( hints,
+ point->before,
+ 0 ) ),
+ af_print_idx( buf8, af_get_strong_edge_index( hints,
+ point->after,
+ 0 ) ) ));
}
AF_DUMP(( "\n" ));
}
@@ -519,7 +549,7 @@
*offset = ( dim == AF_DIMENSION_HORZ ) ? seg->first->fx
: seg->first->fy;
if ( seg->edge )
- *is_blue = (FT_Bool)( seg->edge->blue_edge != 0 );
+ *is_blue = FT_BOOL( seg->edge->blue_edge );
else
*is_blue = FALSE;
@@ -558,8 +588,8 @@
/*
- * note: AF_DIMENSION_HORZ corresponds to _vertical_ edges
- * since they have a constant X coordinate.
+ * note: AF_DIMENSION_HORZ corresponds to _vertical_ edges
+ * since they have a constant X coordinate.
*/
if ( dimension == AF_DIMENSION_HORZ )
AF_DUMP(( "Table of %s edges (1px=%.2fu, 10u=%.2fpx):\n",
@@ -681,8 +711,8 @@
memory = hints->memory;
/*
- * note that we don't need to free the segment and edge
- * buffers since they are really within the hints->points array
+ * note that we don't need to free the segment and edge
+ * buffers since they are really within the hints->points array
*/
for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
{
@@ -776,9 +806,9 @@
}
/*
- * then reallocate the points arrays if necessary --
- * note that we reserve two additional point positions, used to
- * hint metrics appropriately
+ * then reallocate the points arrays if necessary --
+ * note that we reserve two additional point positions, used to
+ * hint metrics appropriately
*/
new_max = (FT_UInt)( outline->n_points + 2 );
old_max = (FT_UInt)hints->max_points;
@@ -898,6 +928,14 @@
prev = end;
}
}
+
+#ifdef FT_DEBUG_AUTOFIT
+ point->before[0] = NULL;
+ point->before[1] = NULL;
+ point->after[0] = NULL;
+ point->after[1] = NULL;
+#endif
+
}
}
@@ -918,15 +956,15 @@
{
/*
- * Compute directions of `in' and `out' vectors.
+ * Compute directions of `in' and `out' vectors.
*
- * Note that distances between points that are very near to each
- * other are accumulated. In other words, the auto-hinter either
- * prepends the small vectors between near points to the first
- * non-near vector, or the sum of small vector lengths exceeds a
- * threshold, thus `grouping' the small vectors. All intermediate
- * points are tagged as weak; the directions are adjusted also to
- * be equal to the accumulated one.
+ * Note that distances between points that are very near to each
+ * other are accumulated. In other words, the auto-hinter either
+ * prepends the small vectors between near points to the first
+ * non-near vector, or the sum of small vector lengths exceeds a
+ * threshold, thus `grouping' the small vectors. All intermediate
+ * points are tagged as weak; the directions are adjusted also to
+ * be equal to the accumulated one.
*/
FT_Int near_limit2 = 2 * near_limit - 1;
@@ -956,12 +994,12 @@
out_y = point->fy - prev->fy;
/*
- * We use Taxicab metrics to measure the vector length.
+ * We use Taxicab metrics to measure the vector length.
*
- * Note that the accumulated distances so far could have the
- * opposite direction of the distance measured here. For this
- * reason we use `near_limit2' for the comparison to get a
- * non-near point even in the worst case.
+ * Note that the accumulated distances so far could have the
+ * opposite direction of the distance measured here. For this
+ * reason we use `near_limit2' for the comparison to get a
+ * non-near point even in the worst case.
*/
if ( FT_ABS( out_x ) + FT_ABS( out_y ) >= near_limit2 )
break;
@@ -979,11 +1017,11 @@
curr = first;
/*
- * We abuse the `u' and `v' fields to store index deltas to the
- * next and previous non-near point, respectively.
+ * We abuse the `u' and `v' fields to store index deltas to the
+ * next and previous non-near point, respectively.
*
- * To avoid problems with not having non-near points, we point to
- * `first' by default as the next non-near point.
+ * To avoid problems with not having non-near points, we point to
+ * `first' by default as the next non-near point.
*
*/
curr->u = (FT_Pos)( first - curr );
@@ -1035,12 +1073,12 @@
}
/*
- * The next step is to `simplify' an outline's topology so that we
- * can identify local extrema more reliably: A series of
- * non-horizontal or non-vertical vectors pointing into the same
- * quadrant are handled as a single, long vector. From a
- * topological point of the view, the intermediate points are of no
- * interest and thus tagged as weak.
+ * The next step is to `simplify' an outline's topology so that we
+ * can identify local extrema more reliably: A series of
+ * non-horizontal or non-vertical vectors pointing into the same
+ * quadrant are handled as a single, long vector. From a
+ * topological point of the view, the intermediate points are of no
+ * interest and thus tagged as weak.
*/
for ( point = points; point < point_limit; point++ )
@@ -1080,9 +1118,9 @@
}
/*
- * Finally, check for remaining weak points. Everything else not
- * collected in edges so far is then implicitly classified as strong
- * points.
+ * Finally, check for remaining weak points. Everything else not
+ * collected in edges so far is then implicitly classified as strong
+ * points.
*/
for ( point = points; point < point_limit; point++ )
@@ -1309,6 +1347,12 @@
if ( delta >= 0 )
{
u = edge->pos - ( edge->opos - ou );
+
+#ifdef FT_DEBUG_AUTOFIT
+ point->before[dim] = edge;
+ point->after[dim] = NULL;
+#endif
+
goto Store_Point;
}
@@ -1318,6 +1362,12 @@
if ( delta >= 0 )
{
u = edge->pos + ( ou - edge->opos );
+
+#ifdef FT_DEBUG_AUTOFIT
+ point->before[dim] = NULL;
+ point->after[dim] = edge;
+#endif
+
goto Store_Point;
}
@@ -1364,6 +1414,12 @@
{
/* we are on the edge */
u = edge->pos;
+
+#ifdef FT_DEBUG_AUTOFIT
+ point->before[dim] = NULL;
+ point->after[dim] = NULL;
+#endif
+
goto Store_Point;
}
}
@@ -1374,6 +1430,11 @@
AF_Edge after = edges + min + 0;
+#ifdef FT_DEBUG_AUTOFIT
+ point->before[dim] = before;
+ point->after[dim] = after;
+#endif
+
/* assert( before && after && before != after ) */
if ( before->scale == 0 )
before->scale = FT_DivFix( after->pos - before->pos,
diff --git a/thirdparty/freetype/src/autofit/afhints.h b/thirdparty/freetype/src/autofit/afhints.h
index 3326ebc44e..e0cf612f0c 100644
--- a/thirdparty/freetype/src/autofit/afhints.h
+++ b/thirdparty/freetype/src/autofit/afhints.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* afhints.h */
-/* */
-/* Auto-fitter hinting routines (specification). */
-/* */
-/* Copyright 2003-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * afhints.h
+ *
+ * Auto-fitter hinting routines (specification).
+ *
+ * Copyright (C) 2003-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef AFHINTS_H_
@@ -26,8 +26,8 @@
FT_BEGIN_HEADER
/*
- * The definition of outline glyph hints. These are shared by all
- * writing system analysis routines (until now).
+ * The definition of outline glyph hints. These are shared by all
+ * writing system analysis routines (until now).
*/
typedef enum AF_Dimension_
@@ -56,153 +56,153 @@ FT_BEGIN_HEADER
/*
- * The following explanations are mostly taken from the article
+ * The following explanations are mostly taken from the article
*
- * Real-Time Grid Fitting of Typographic Outlines
+ * Real-Time Grid Fitting of Typographic Outlines
*
- * by David Turner and Werner Lemberg
+ * by David Turner and Werner Lemberg
*
- * https://www.tug.org/TUGboat/Articles/tb24-3/lemberg.pdf
+ * https://www.tug.org/TUGboat/Articles/tb24-3/lemberg.pdf
*
- * with appropriate updates.
+ * with appropriate updates.
*
*
- * Segments
+ * Segments
*
- * `af_{cjk,latin,...}_hints_compute_segments' are the functions to
- * find segments in an outline.
+ * `af_{cjk,latin,...}_hints_compute_segments' are the functions to
+ * find segments in an outline.
*
- * A segment is a series of at least two consecutive points that are
- * approximately aligned along a coordinate axis. The analysis to do
- * so is specific to a writing system.
+ * A segment is a series of at least two consecutive points that are
+ * approximately aligned along a coordinate axis. The analysis to do
+ * so is specific to a writing system.
*
*
- * Edges
+ * Edges
*
- * `af_{cjk,latin,...}_hints_compute_edges' are the functions to find
- * edges.
+ * `af_{cjk,latin,...}_hints_compute_edges' are the functions to find
+ * edges.
*
- * As soon as segments are defined, the auto-hinter groups them into
- * edges. An edge corresponds to a single position on the main
- * dimension that collects one or more segments (allowing for a small
- * threshold).
+ * As soon as segments are defined, the auto-hinter groups them into
+ * edges. An edge corresponds to a single position on the main
+ * dimension that collects one or more segments (allowing for a small
+ * threshold).
*
- * As an example, the `latin' writing system first tries to grid-fit
- * edges, then to align segments on the edges unless it detects that
- * they form a serif.
+ * As an example, the `latin' writing system first tries to grid-fit
+ * edges, then to align segments on the edges unless it detects that
+ * they form a serif.
*
*
- * A H
- * | |
- * | |
- * | |
- * | |
- * C | | F
- * +------<-----+ +-----<------+
- * | B G |
- * | |
- * | |
- * +--------------->------------------+
- * D E
+ * A H
+ * | |
+ * | |
+ * | |
+ * | |
+ * C | | F
+ * +------<-----+ +-----<------+
+ * | B G |
+ * | |
+ * | |
+ * +--------------->------------------+
+ * D E
*
*
- * Stems
+ * Stems
*
- * Stems are detected by `af_{cjk,latin,...}_hint_edges'.
+ * Stems are detected by `af_{cjk,latin,...}_hint_edges'.
*
- * Segments need to be `linked' to other ones in order to detect stems.
- * A stem is made of two segments that face each other in opposite
- * directions and that are sufficiently close to each other. Using
- * vocabulary from the TrueType specification, stem segments form a
- * `black distance'.
+ * Segments need to be `linked' to other ones in order to detect stems.
+ * A stem is made of two segments that face each other in opposite
+ * directions and that are sufficiently close to each other. Using
+ * vocabulary from the TrueType specification, stem segments form a
+ * `black distance'.
*
- * In the above ASCII drawing, the horizontal segments are BC, DE, and
- * FG; the vertical segments are AB, CD, EF, and GH.
+ * In the above ASCII drawing, the horizontal segments are BC, DE, and
+ * FG; the vertical segments are AB, CD, EF, and GH.
*
- * Each segment has at most one `best' candidate to form a black
- * distance, or no candidate at all. Notice that two distinct segments
- * can have the same candidate, which frequently means a serif.
+ * Each segment has at most one `best' candidate to form a black
+ * distance, or no candidate at all. Notice that two distinct segments
+ * can have the same candidate, which frequently means a serif.
*
- * A stem is recognized by the following condition:
+ * A stem is recognized by the following condition:
*
- * best segment_1 = segment_2 && best segment_2 = segment_1
+ * best segment_1 = segment_2 && best segment_2 = segment_1
*
- * The best candidate is stored in field `link' in structure
- * `AF_Segment'.
+ * The best candidate is stored in field `link' in structure
+ * `AF_Segment'.
*
- * In the above ASCII drawing, the best candidate for both AB and CD is
- * GH, while the best candidate for GH is AB. Similarly, the best
- * candidate for EF and GH is AB, while the best candidate for AB is
- * GH.
+ * In the above ASCII drawing, the best candidate for both AB and CD is
+ * GH, while the best candidate for GH is AB. Similarly, the best
+ * candidate for EF and GH is AB, while the best candidate for AB is
+ * GH.
*
- * The detection and handling of stems is dependent on the writing
- * system.
+ * The detection and handling of stems is dependent on the writing
+ * system.
*
*
- * Serifs
+ * Serifs
*
- * Serifs are detected by `af_{cjk,latin,...}_hint_edges'.
+ * Serifs are detected by `af_{cjk,latin,...}_hint_edges'.
*
- * In comparison to a stem, a serif (as handled by the auto-hinter
- * module that takes care of the `latin' writing system) has
+ * In comparison to a stem, a serif (as handled by the auto-hinter
+ * module that takes care of the `latin' writing system) has
*
- * best segment_1 = segment_2 && best segment_2 != segment_1
+ * best segment_1 = segment_2 && best segment_2 != segment_1
*
- * where segment_1 corresponds to the serif segment (CD and EF in the
- * above ASCII drawing).
+ * where segment_1 corresponds to the serif segment (CD and EF in the
+ * above ASCII drawing).
*
- * The best candidate is stored in field `serif' in structure
- * `AF_Segment' (and `link' is set to NULL).
+ * The best candidate is stored in field `serif' in structure
+ * `AF_Segment' (and `link' is set to NULL).
*
*
- * Touched points
+ * Touched points
*
- * A point is called `touched' if it has been processed somehow by the
- * auto-hinter. It basically means that it shouldn't be moved again
- * (or moved only under certain constraints to preserve the already
- * applied processing).
+ * A point is called `touched' if it has been processed somehow by the
+ * auto-hinter. It basically means that it shouldn't be moved again
+ * (or moved only under certain constraints to preserve the already
+ * applied processing).
*
*
- * Flat and round segments
+ * Flat and round segments
*
- * Segments are `round' or `flat', depending on the series of points
- * that define them. A segment is round if the next and previous point
- * of an extremum (which can be either a single point or sequence of
- * points) are both conic or cubic control points. Otherwise, a
- * segment with an extremum is flat.
+ * Segments are `round' or `flat', depending on the series of points
+ * that define them. A segment is round if the next and previous point
+ * of an extremum (which can be either a single point or sequence of
+ * points) are both conic or cubic control points. Otherwise, a
+ * segment with an extremum is flat.
*
*
- * Strong Points
+ * Strong Points
*
- * Experience has shown that points not part of an edge need to be
- * interpolated linearly between their two closest edges, even if these
- * are not part of the contour of those particular points. Typical
- * candidates for this are
+ * Experience has shown that points not part of an edge need to be
+ * interpolated linearly between their two closest edges, even if these
+ * are not part of the contour of those particular points. Typical
+ * candidates for this are
*
- * - angle points (i.e., points where the `in' and `out' direction
- * differ greatly)
+ * - angle points (i.e., points where the `in' and `out' direction
+ * differ greatly)
*
- * - inflection points (i.e., where the `in' and `out' angles are the
- * same, but the curvature changes sign) [currently, such points
- * aren't handled specially in the auto-hinter]
+ * - inflection points (i.e., where the `in' and `out' angles are the
+ * same, but the curvature changes sign) [currently, such points
+ * aren't handled specially in the auto-hinter]
*
- * `af_glyph_hints_align_strong_points' is the function that takes
- * care of such situations; it is equivalent to the TrueType `IP'
- * hinting instruction.
+ * `af_glyph_hints_align_strong_points' is the function that takes
+ * care of such situations; it is equivalent to the TrueType `IP'
+ * hinting instruction.
*
*
- * Weak Points
+ * Weak Points
*
- * Other points in the outline must be interpolated using the
- * coordinates of their previous and next unfitted contour neighbours.
- * These are called `weak points' and are touched by the function
- * `af_glyph_hints_align_weak_points', equivalent to the TrueType `IUP'
- * hinting instruction. Typical candidates are control points and
- * points on the contour without a major direction.
+ * Other points in the outline must be interpolated using the
+ * coordinates of their previous and next unfitted contour neighbours.
+ * These are called `weak points' and are touched by the function
+ * `af_glyph_hints_align_weak_points', equivalent to the TrueType `IUP'
+ * hinting instruction. Typical candidates are control points and
+ * points on the contour without a major direction.
*
- * The major effect is to reduce possible distortion caused by
- * alignment of edges and strong points, thus weak points are processed
- * after strong points.
+ * The major effect is to reduce possible distortion caused by
+ * alignment of edges and strong points, thus weak points are processed
+ * after strong points.
*/
@@ -252,6 +252,12 @@ FT_BEGIN_HEADER
AF_Point next; /* next point in contour */
AF_Point prev; /* previous point in contour */
+#ifdef FT_DEBUG_AUTOFIT
+ /* track `before' and `after' edges for strong points */
+ AF_Edge before[2];
+ AF_Edge after[2];
+#endif
+
} AF_PointRec;
diff --git a/thirdparty/freetype/src/autofit/afindic.c b/thirdparty/freetype/src/autofit/afindic.c
index dfbea5f34c..a17117c712 100644
--- a/thirdparty/freetype/src/autofit/afindic.c
+++ b/thirdparty/freetype/src/autofit/afindic.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* afindic.c */
-/* */
-/* Auto-fitter hinting routines for Indic writing system (body). */
-/* */
-/* Copyright 2007-2018 by */
-/* Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * afindic.c
+ *
+ * Auto-fitter hinting routines for Indic writing system (body).
+ *
+ * Copyright (C) 2007-2019 by
+ * Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include "aftypes.h"
diff --git a/thirdparty/freetype/src/autofit/afindic.h b/thirdparty/freetype/src/autofit/afindic.h
index 5688738e6e..bc5bc59fa5 100644
--- a/thirdparty/freetype/src/autofit/afindic.h
+++ b/thirdparty/freetype/src/autofit/afindic.h
@@ -1,20 +1,20 @@
-/***************************************************************************/
-/* */
-/* afindic.h */
-/* */
-/* Auto-fitter hinting routines for Indic writing system */
-/* (specification). */
-/* */
-/* Copyright 2007-2018 by */
-/* Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * afindic.h
+ *
+ * Auto-fitter hinting routines for Indic writing system
+ * (specification).
+ *
+ * Copyright (C) 2007-2019 by
+ * Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef AFINDIC_H_
diff --git a/thirdparty/freetype/src/autofit/aflatin.c b/thirdparty/freetype/src/autofit/aflatin.c
index 9f1b54056f..dccdcaf345 100644
--- a/thirdparty/freetype/src/autofit/aflatin.c
+++ b/thirdparty/freetype/src/autofit/aflatin.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* aflatin.c */
-/* */
-/* Auto-fitter hinting routines for latin writing system (body). */
-/* */
-/* Copyright 2003-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * aflatin.c
+ *
+ * Auto-fitter hinting routines for latin writing system (body).
+ *
+ * Copyright (C) 2003-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -21,7 +21,6 @@
#include FT_INTERNAL_DEBUG_H
#include "afglobal.h"
-#include "afpic.h"
#include "aflatin.h"
#include "aferrors.h"
@@ -31,14 +30,14 @@
#endif
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_aflatin
+#define FT_COMPONENT aflatin
/* needed for computation of round vs. flat segments */
@@ -83,24 +82,30 @@
AF_LatinMetricsRec dummy[1];
AF_Scaler scaler = &dummy->root.scaler;
-#ifdef FT_CONFIG_OPTION_PIC
- AF_FaceGlobals globals = metrics->root.globals;
-#endif
-
AF_StyleClass style_class = metrics->root.style_class;
- AF_ScriptClass script_class = AF_SCRIPT_CLASSES_GET
- [style_class->script];
+ AF_ScriptClass script_class = af_script_classes[style_class->script];
+
+ /* If HarfBuzz is not available, we need a pointer to a single */
+ /* unsigned long value. */
+#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
+ void* shaper_buf;
+#else
+ FT_ULong shaper_buf_;
+ void* shaper_buf = &shaper_buf_;
+#endif
- void* shaper_buf;
const char* p;
#ifdef FT_DEBUG_LEVEL_TRACE
FT_ULong ch = 0;
#endif
- p = script_class->standard_charstring;
- shaper_buf = af_shaper_buf_create( face );
+ p = script_class->standard_charstring;
+
+#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
+ shaper_buf = af_shaper_buf_create( face );
+#endif
/*
* We check a list of standard characters to catch features like
* `c2sc' (small caps from caps) that don't contain lowercase letters
@@ -186,10 +191,10 @@
goto Exit;
/*
- * We assume that the glyphs selected for the stem width
- * computation are `featureless' enough so that the linking
- * algorithm works fine without adjustments of its scoring
- * function.
+ * We assume that the glyphs selected for the stem width
+ * computation are `featureless' enough so that the linking
+ * algorithm works fine without adjustments of its scoring
+ * function.
*/
af_latin_hints_link_segments( hints,
0,
@@ -329,7 +334,14 @@
FT_Pos flat_threshold = FLAT_THRESHOLD( metrics->units_per_em );
- void* shaper_buf;
+ /* If HarfBuzz is not available, we need a pointer to a single */
+ /* unsigned long value. */
+#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
+ void* shaper_buf;
+#else
+ FT_ULong shaper_buf_;
+ void* shaper_buf = &shaper_buf_;
+#endif
/* we walk over the blue character strings as specified in the */
@@ -339,7 +351,9 @@
"============================\n"
"\n" ));
+#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
shaper_buf = af_shaper_buf_create( face );
+#endif
for ( ; bs->string != AF_BLUE_STRING_MAX; bs++ )
{
@@ -884,8 +898,8 @@
if ( num_flats == 0 && num_rounds == 0 )
{
/*
- * we couldn't find a single glyph to compute this blue zone,
- * we will simply ignore it then
+ * we couldn't find a single glyph to compute this blue zone,
+ * we will simply ignore it then
*/
FT_TRACE5(( " empty\n" ));
continue;
@@ -1036,15 +1050,25 @@
FT_Bool started = 0, same_width = 1;
FT_Fixed advance = 0, old_advance = 0;
- void* shaper_buf;
+ /* If HarfBuzz is not available, we need a pointer to a single */
+ /* unsigned long value. */
+#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
+ void* shaper_buf;
+#else
+ FT_ULong shaper_buf_;
+ void* shaper_buf = &shaper_buf_;
+#endif
/* in all supported charmaps, digits have character codes 0x30-0x39 */
const char digits[] = "0 1 2 3 4 5 6 7 8 9";
const char* p;
- p = digits;
+ p = digits;
+
+#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
shaper_buf = af_shaper_buf_create( face );
+#endif
while ( *p )
{
@@ -1283,7 +1307,7 @@
/* an extra-light axis corresponds to a standard width that is */
/* smaller than 5/8 pixels */
axis->extra_light =
- (FT_Bool)( FT_MulFix( axis->standard_width, scale ) < 32 + 8 );
+ FT_BOOL( FT_MulFix( axis->standard_width, scale ) < 32 + 8 );
#ifdef FT_DEBUG_LEVEL_TRACE
if ( axis->extra_light )
@@ -1967,17 +1991,17 @@
if ( len >= len_threshold )
{
/*
- * The score is the sum of two demerits indicating the
- * `badness' of a fit, measured along the segments' main axis
- * and orthogonal to it, respectively.
+ * The score is the sum of two demerits indicating the
+ * `badness' of a fit, measured along the segments' main axis
+ * and orthogonal to it, respectively.
*
- * o The less overlapping along the main axis, the worse it
- * is, causing a larger demerit.
+ * - The less overlapping along the main axis, the worse it
+ * is, causing a larger demerit.
*
- * o The nearer the orthogonal distance to a stem width, the
- * better it is, causing a smaller demerit. For simplicity,
- * however, we only increase the demerit for values that
- * exceed the largest stem width.
+ * - The nearer the orthogonal distance to a stem width, the
+ * better it is, causing a smaller demerit. For simplicity,
+ * however, we only increase the demerit for values that
+ * exceed the largest stem width.
*/
FT_Pos dist = pos2 - pos1;
@@ -2049,13 +2073,8 @@
FT_Memory memory = hints->memory;
AF_LatinAxis laxis = &((AF_LatinMetrics)hints->metrics)->axis[dim];
-#ifdef FT_CONFIG_OPTION_PIC
- AF_FaceGlobals globals = hints->metrics->globals;
-#endif
-
AF_StyleClass style_class = hints->metrics->style_class;
- AF_ScriptClass script_class = AF_SCRIPT_CLASSES_GET
- [style_class->script];
+ AF_ScriptClass script_class = af_script_classes[style_class->script];
FT_Bool top_to_bottom_hinting = 0;
@@ -2086,9 +2105,9 @@
top_to_bottom_hinting = script_class->top_to_bottom_hinting;
/*
- * We ignore all segments that are less than 1 pixel in length
- * to avoid many problems with serif fonts. We compute the
- * corresponding threshold in font units.
+ * We ignore all segments that are less than 1 pixel in length
+ * to avoid many problems with serif fonts. We compute the
+ * corresponding threshold in font units.
*/
if ( dim == AF_DIMENSION_HORZ )
segment_length_threshold = FT_DivFix( 64, hints->y_scale );
@@ -2096,26 +2115,26 @@
segment_length_threshold = 0;
/*
- * Similarly, we ignore segments that have a width delta
- * larger than 0.5px (i.e., a width larger than 1px).
+ * Similarly, we ignore segments that have a width delta
+ * larger than 0.5px (i.e., a width larger than 1px).
*/
segment_width_threshold = FT_DivFix( 32, scale );
- /*********************************************************************/
- /* */
- /* We begin by generating a sorted table of edges for the current */
- /* direction. To do so, we simply scan each segment and try to find */
- /* an edge in our table that corresponds to its position. */
- /* */
- /* If no edge is found, we create and insert a new edge in the */
- /* sorted table. Otherwise, we simply add the segment to the edge's */
- /* list which gets processed in the second step to compute the */
- /* edge's properties. */
- /* */
- /* Note that the table of edges is sorted along the segment/edge */
- /* position. */
- /* */
- /*********************************************************************/
+ /**********************************************************************
+ *
+ * We begin by generating a sorted table of edges for the current
+ * direction. To do so, we simply scan each segment and try to find
+ * an edge in our table that corresponds to its position.
+ *
+ * If no edge is found, we create and insert a new edge in the
+ * sorted table. Otherwise, we simply add the segment to the edge's
+ * list which gets processed in the second step to compute the
+ * edge's properties.
+ *
+ * Note that the table of edges is sorted along the segment/edge
+ * position.
+ *
+ */
/* assure that edge distance threshold is at most 0.25px */
edge_distance_threshold = FT_MulFix( laxis->edge_distance_threshold,
@@ -2237,17 +2256,17 @@
}
- /******************************************************************/
- /* */
- /* Good, we now compute each edge's properties according to the */
- /* segments found on its position. Basically, these are */
- /* */
- /* - the edge's main direction */
- /* - stem edge, serif edge or both (which defaults to stem then) */
- /* - rounded edge, straight or both (which defaults to straight) */
- /* - link for edge */
- /* */
- /******************************************************************/
+ /*******************************************************************
+ *
+ * Good, we now compute each edge's properties according to the
+ * segments found on its position. Basically, these are
+ *
+ * - the edge's main direction
+ * - stem edge, serif edge or both (which defaults to stem then)
+ * - rounded edge, straight or both (which defaults to straight)
+ * - link for edge
+ *
+ */
/* first of all, set the `edge' field in each segment -- this is */
/* required in order to compute edge links */
@@ -2309,9 +2328,9 @@
/* check for links -- if seg->serif is set, then seg->link must */
/* be ignored */
- is_serif = (FT_Bool)( seg->serif &&
- seg->serif->edge &&
- seg->serif->edge != edge );
+ is_serif = FT_BOOL( seg->serif &&
+ seg->serif->edge &&
+ seg->serif->edge != edge );
if ( ( seg->link && seg->link->edge ) || is_serif )
{
@@ -2546,8 +2565,8 @@
af_glyph_hints_rescale( hints, (AF_StyleMetrics)metrics );
/*
- * correct x_scale and y_scale if needed, since they may have
- * been modified by `af_latin_metrics_scale_dim' above
+ * correct x_scale and y_scale if needed, since they may have
+ * been modified by `af_latin_metrics_scale_dim' above
*/
hints->x_scale = metrics->axis[AF_DIMENSION_HORZ].scale;
hints->x_delta = metrics->axis[AF_DIMENSION_HORZ].delta;
@@ -2566,21 +2585,21 @@
other_flags = 0;
/*
- * We snap the width of vertical stems for the monochrome and
- * horizontal LCD rendering targets only.
+ * We snap the width of vertical stems for the monochrome and
+ * horizontal LCD rendering targets only.
*/
if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD )
other_flags |= AF_LATIN_HINTS_HORZ_SNAP;
/*
- * We snap the width of horizontal stems for the monochrome and
- * vertical LCD rendering targets only.
+ * We snap the width of horizontal stems for the monochrome and
+ * vertical LCD rendering targets only.
*/
if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD_V )
other_flags |= AF_LATIN_HINTS_VERT_SNAP;
/*
- * We adjust stems to full pixels unless in `light' or `lcd' mode.
+ * We adjust stems to full pixels unless in `light' or `lcd' mode.
*/
if ( mode != FT_RENDER_MODE_LIGHT && mode != FT_RENDER_MODE_LCD )
other_flags |= AF_LATIN_HINTS_STEM_ADJUST;
@@ -2589,11 +2608,11 @@
other_flags |= AF_LATIN_HINTS_MONO;
/*
- * In `light' or `lcd' mode we disable horizontal hinting completely.
- * We also do it if the face is italic.
+ * In `light' or `lcd' mode we disable horizontal hinting completely.
+ * We also do it if the face is italic.
*
- * However, if warping is enabled (which only works in `light' hinting
- * mode), advance widths get adjusted, too.
+ * However, if warping is enabled (which only works in `light' hinting
+ * mode), advance widths get adjusted, too.
*/
if ( mode == FT_RENDER_MODE_LIGHT || mode == FT_RENDER_MODE_LCD ||
( face->style_flags & FT_STYLE_FLAG_ITALIC ) != 0 )
@@ -2936,13 +2955,8 @@
AF_Edge anchor = NULL;
FT_Int has_serifs = 0;
-#ifdef FT_CONFIG_OPTION_PIC
- AF_FaceGlobals globals = hints->metrics->globals;
-#endif
-
AF_StyleClass style_class = hints->metrics->style_class;
- AF_ScriptClass script_class = AF_SCRIPT_CLASSES_GET
- [style_class->script];
+ AF_ScriptClass script_class = af_script_classes[style_class->script];
FT_Bool top_to_bottom_hinting = 0;
@@ -2976,12 +2990,12 @@
edge2 = edge->link;
/*
- * If a stem contains both a neutral and a non-neutral blue zone,
- * skip the neutral one. Otherwise, outlines with different
- * directions might be incorrectly aligned at the same vertical
- * position.
+ * If a stem contains both a neutral and a non-neutral blue zone,
+ * skip the neutral one. Otherwise, outlines with different
+ * directions might be incorrectly aligned at the same vertical
+ * position.
*
- * If we have two neutral blue zones, skip one of them.
+ * If we have two neutral blue zones, skip one of them.
*
*/
if ( edge->blue_edge && edge2 && edge2->blue_edge )
@@ -3344,8 +3358,8 @@
if ( has_serifs || !anchor )
{
/*
- * now hint the remaining edges (serifs and single) in order
- * to complete our processing
+ * now hint the remaining edges (serifs and single) in order
+ * to complete our processing
*/
for ( edge = edges; edge < edge_limit; edge++ )
{
diff --git a/thirdparty/freetype/src/autofit/aflatin.h b/thirdparty/freetype/src/autofit/aflatin.h
index 432cccce4e..40479538c2 100644
--- a/thirdparty/freetype/src/autofit/aflatin.h
+++ b/thirdparty/freetype/src/autofit/aflatin.h
@@ -1,20 +1,20 @@
-/***************************************************************************/
-/* */
-/* aflatin.h */
-/* */
-/* Auto-fitter hinting routines for latin writing system */
-/* (specification). */
-/* */
-/* Copyright 2003-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * aflatin.h
+ *
+ * Auto-fitter hinting routines for latin writing system
+ * (specification).
+ *
+ * Copyright (C) 2003-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef AFLATIN_H_
@@ -45,9 +45,9 @@ FT_BEGIN_HEADER
/*
- * The following declarations could be embedded in the file `aflatin.c';
- * they have been made semi-public to allow alternate writing system
- * hinters to re-use some of them.
+ * The following declarations could be embedded in the file `aflatin.c';
+ * they have been made semi-public to allow alternate writing system
+ * hinters to re-use some of them.
*/
@@ -161,8 +161,8 @@ FT_BEGIN_HEADER
/*
- * The next functions shouldn't normally be exported. However, other
- * writing systems might like to use these functions as-is.
+ * The next functions shouldn't normally be exported. However, other
+ * writing systems might like to use these functions as-is.
*/
FT_LOCAL( FT_Error )
af_latin_hints_compute_segments( AF_GlyphHints hints,
diff --git a/thirdparty/freetype/src/autofit/aflatin2.c b/thirdparty/freetype/src/autofit/aflatin2.c
index 5c71378118..c601ab8d9a 100644
--- a/thirdparty/freetype/src/autofit/aflatin2.c
+++ b/thirdparty/freetype/src/autofit/aflatin2.c
@@ -3,22 +3,22 @@
/* marked as experimental. */
-/***************************************************************************/
-/* */
-/* aflatin2.c */
-/* */
-/* Auto-fitter hinting routines for latin writing system (body). */
-/* */
-/* Copyright 2003-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * aflatin2.c
+ *
+ * Auto-fitter hinting routines for latin writing system (body).
+ *
+ * Copyright (C) 2003-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include FT_ADVANCES_H
@@ -37,14 +37,14 @@
#endif
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_aflatin2
+#define FT_COMPONENT aflatin2
FT_LOCAL_DEF( FT_Error )
@@ -265,7 +265,7 @@
/* Avoid single-point contours since they are never rasterized. */
/* In some fonts, they correspond to mark attachment points */
/* which are way outside of the glyph's real outline. */
- if ( last == first )
+ if ( last <= first )
continue;
if ( AF_LATIN_IS_TOP_BLUE( bb ) )
@@ -299,6 +299,7 @@
/* now check whether the point belongs to a straight or round */
/* segment; we first need to find in which contour the extremum */
/* lies, then inspect its previous and next points */
+ if ( best_point >= 0 )
{
FT_Pos best_x = points[best_point].x;
FT_Int start, end, prev, next;
@@ -358,8 +359,8 @@
if ( num_flats == 0 && num_rounds == 0 )
{
/*
- * we couldn't find a single glyph to compute this blue zone,
- * we will simply ignore it then
+ * we couldn't find a single glyph to compute this blue zone,
+ * we will simply ignore it then
*/
FT_TRACE5(( " empty\n" ));
continue;
@@ -632,7 +633,7 @@
/* an extra-light axis corresponds to a standard width that is */
/* smaller than 5/8 pixels */
axis->extra_light =
- (FT_Bool)( FT_MulFix( axis->standard_width, scale ) < 32 + 8 );
+ FT_BOOL( FT_MulFix( axis->standard_width, scale ) < 32 + 8 );
if ( dim == AF_DIMENSION_VERT )
{
@@ -1108,13 +1109,13 @@
: AF_DIR_RIGHT;
/*
- * We want to ignore very small (mostly serif) segments, we do that
- * by ignoring those that whose length is less than a given fraction
- * of the standard width. If there is no standard width, we ignore
- * those that are less than a given size in pixels
+ * We want to ignore very small (mostly serif) segments, we do that
+ * by ignoring those that whose length is less than a given fraction
+ * of the standard width. If there is no standard width, we ignore
+ * those that are less than a given size in pixels
*
- * also, unlink serif segments that are linked to segments farther
- * than 50% of the standard width
+ * also, unlink serif segments that are linked to segments farther
+ * than 50% of the standard width
*/
if ( dim == AF_DIMENSION_HORZ )
{
@@ -1126,21 +1127,21 @@
else
segment_length_threshold = 0;
- /*********************************************************************/
- /* */
- /* We will begin by generating a sorted table of edges for the */
- /* current direction. To do so, we simply scan each segment and try */
- /* to find an edge in our table that corresponds to its position. */
- /* */
- /* If no edge is found, we create and insert a new edge in the */
- /* sorted table. Otherwise, we simply add the segment to the edge's */
- /* list which will be processed in the second step to compute the */
- /* edge's properties. */
- /* */
- /* Note that the edges table is sorted along the segment/edge */
- /* position. */
- /* */
- /*********************************************************************/
+ /**********************************************************************
+ *
+ * We will begin by generating a sorted table of edges for the
+ * current direction. To do so, we simply scan each segment and try
+ * to find an edge in our table that corresponds to its position.
+ *
+ * If no edge is found, we create and insert a new edge in the
+ * sorted table. Otherwise, we simply add the segment to the edge's
+ * list which will be processed in the second step to compute the
+ * edge's properties.
+ *
+ * Note that the edges table is sorted along the segment/edge
+ * position.
+ *
+ */
edge_distance_threshold = FT_MulFix( laxis->edge_distance_threshold,
scale );
@@ -1230,17 +1231,17 @@
}
- /*********************************************************************/
- /* */
- /* Good, we will now compute each edge's properties according to */
- /* segments found on its position. Basically, these are: */
- /* */
- /* - edge's main direction */
- /* - stem edge, serif edge or both (which defaults to stem then) */
- /* - rounded edge, straight or both (which defaults to straight) */
- /* - link for edge */
- /* */
- /*********************************************************************/
+ /**********************************************************************
+ *
+ * Good, we will now compute each edge's properties according to
+ * segments found on its position. Basically, these are:
+ *
+ * - edge's main direction
+ * - stem edge, serif edge or both (which defaults to stem then)
+ * - rounded edge, straight or both (which defaults to straight)
+ * - link for edge
+ *
+ */
/* first of all, set the `edge' field in each segment -- this is */
/* required in order to compute edge links */
@@ -1302,9 +1303,9 @@
/* check for links -- if seg->serif is set, then seg->link must */
/* be ignored */
- is_serif = (FT_Bool)( seg->serif &&
- seg->serif->edge &&
- seg->serif->edge != edge );
+ is_serif = FT_BOOL( seg->serif &&
+ seg->serif->edge &&
+ seg->serif->edge != edge );
if ( ( seg->link && seg->link->edge ) || is_serif )
{
@@ -1524,8 +1525,8 @@
af_glyph_hints_rescale( hints, (AF_StyleMetrics)metrics );
/*
- * correct x_scale and y_scale if needed, since they may have
- * been modified `af_latin2_metrics_scale_dim' above
+ * correct x_scale and y_scale if needed, since they may have
+ * been modified `af_latin2_metrics_scale_dim' above
*/
hints->x_scale = metrics->axis[AF_DIMENSION_HORZ].scale;
hints->x_delta = metrics->axis[AF_DIMENSION_HORZ].delta;
@@ -1544,21 +1545,21 @@
other_flags = 0;
/*
- * We snap the width of vertical stems for the monochrome and
- * horizontal LCD rendering targets only.
+ * We snap the width of vertical stems for the monochrome and
+ * horizontal LCD rendering targets only.
*/
if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD )
other_flags |= AF_LATIN_HINTS_HORZ_SNAP;
/*
- * We snap the width of horizontal stems for the monochrome and
- * vertical LCD rendering targets only.
+ * We snap the width of horizontal stems for the monochrome and
+ * vertical LCD rendering targets only.
*/
if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD_V )
other_flags |= AF_LATIN_HINTS_VERT_SNAP;
/*
- * We adjust stems to full pixels unless in `light' or `lcd' mode.
+ * We adjust stems to full pixels unless in `light' or `lcd' mode.
*/
if ( mode != FT_RENDER_MODE_LIGHT && mode != FT_RENDER_MODE_LCD )
other_flags |= AF_LATIN_HINTS_STEM_ADJUST;
@@ -1567,8 +1568,8 @@
other_flags |= AF_LATIN_HINTS_MONO;
/*
- * In `light' or `lcd' mode we disable horizontal hinting completely.
- * We also do it if the face is italic.
+ * In `light' or `lcd' mode we disable horizontal hinting completely.
+ * We also do it if the face is italic.
*/
if ( mode == FT_RENDER_MODE_LIGHT || mode == FT_RENDER_MODE_LCD ||
( face->style_flags & FT_STYLE_FLAG_ITALIC ) != 0 )
@@ -2233,8 +2234,8 @@
if ( has_serifs || !anchor )
{
/*
- * now hint the remaining edges (serifs and single) in order
- * to complete our processing
+ * now hint the remaining edges (serifs and single) in order
+ * to complete our processing
*/
for ( edge = edges; edge < edge_limit; edge++ )
{
diff --git a/thirdparty/freetype/src/autofit/aflatin2.h b/thirdparty/freetype/src/autofit/aflatin2.h
index 0129dc707e..507cef3df2 100644
--- a/thirdparty/freetype/src/autofit/aflatin2.h
+++ b/thirdparty/freetype/src/autofit/aflatin2.h
@@ -3,23 +3,23 @@
/* marked as experimental. */
-/***************************************************************************/
-/* */
-/* aflatin2.h */
-/* */
-/* Auto-fitter hinting routines for latin writing system */
-/* (specification). */
-/* */
-/* Copyright 2003-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * aflatin2.h
+ *
+ * Auto-fitter hinting routines for latin writing system
+ * (specification).
+ *
+ * Copyright (C) 2003-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef AFLATIN2_H_
diff --git a/thirdparty/freetype/src/autofit/afloader.c b/thirdparty/freetype/src/autofit/afloader.c
index a55550b338..83743b7be1 100644
--- a/thirdparty/freetype/src/autofit/afloader.c
+++ b/thirdparty/freetype/src/autofit/afloader.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* afloader.c */
-/* */
-/* Auto-fitter glyph loading routines (body). */
-/* */
-/* Copyright 2003-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * afloader.c
+ *
+ * Auto-fitter glyph loading routines (body).
+ *
+ * Copyright (C) 2003-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include "afglobal.h"
@@ -21,7 +21,6 @@
#include "afhints.h"
#include "aferrors.h"
#include "afmodule.h"
-#include "afpic.h"
#include FT_INTERNAL_CALC_H
@@ -119,12 +118,12 @@
}
/*
- * We depend on the writing system (script analyzers) to supply
- * standard widths for the script of the glyph we are looking at. If
- * it can't deliver, stem darkening is disabled.
+ * We depend on the writing system (script analyzers) to supply
+ * standard widths for the script of the glyph we are looking at. If
+ * it can't deliver, stem darkening is disabled.
*/
writing_system_class =
- AF_WRITING_SYSTEM_CLASSES_GET[style_metrics->style_class->writing_system];
+ af_writing_system_classes[style_metrics->style_class->writing_system];
if ( writing_system_class->style_metrics_getstdw )
writing_system_class->style_metrics_getstdw( style_metrics,
@@ -174,22 +173,22 @@
globals->darken_y = af_fixedToInt( darken_y );
/*
- * Scale outlines down on the Y-axis to keep them inside their blue
- * zones. The stronger the emboldening, the stronger the downscaling
- * (plus heuristical padding to prevent outlines still falling out
- * their zones due to rounding).
+ * Scale outlines down on the Y-axis to keep them inside their blue
+ * zones. The stronger the emboldening, the stronger the downscaling
+ * (plus heuristical padding to prevent outlines still falling out
+ * their zones due to rounding).
*
- * Reason: `FT_Outline_Embolden' works by shifting the rightmost
- * points of stems farther to the right, and topmost points farther
- * up. This positions points on the Y-axis outside their
- * pre-computed blue zones and leads to distortion when applying the
- * hints in the code further below. Code outside this emboldening
- * block doesn't know we are presenting it with modified outlines the
- * analyzer didn't see!
+ * Reason: `FT_Outline_Embolden' works by shifting the rightmost
+ * points of stems farther to the right, and topmost points farther
+ * up. This positions points on the Y-axis outside their
+ * pre-computed blue zones and leads to distortion when applying the
+ * hints in the code further below. Code outside this emboldening
+ * block doesn't know we are presenting it with modified outlines the
+ * analyzer didn't see!
*
- * An unfortunate side effect of downscaling is that the emboldening
- * effect is slightly decreased. The loss becomes more pronounced
- * versus the CFF driver at smaller sizes, e.g., at 9ppem and below.
+ * An unfortunate side effect of downscaling is that the emboldening
+ * effect is slightly decreased. The loss becomes more pronounced
+ * versus the CFF driver at smaller sizes, e.g., at 9ppem and below.
*/
globals->scale_down_factor =
FT_DivFix( em_size - ( darken_by_font_units_y + af_intToFixed( 8 ) ),
@@ -232,10 +231,6 @@
AF_StyleClass style_class;
AF_WritingSystemClass writing_system_class;
-#ifdef FT_CONFIG_OPTION_PIC
- AF_FaceGlobals globals = loader->globals;
-#endif
-
if ( !size )
return FT_THROW( Invalid_Size_Handle );
@@ -282,13 +277,13 @@
}
/*
- * TODO: This code currently doesn't support fractional advance widths,
- * i.e., placing hinted glyphs at anything other than integer
- * x-positions. This is only relevant for the warper code, which
- * scales and shifts glyphs to optimize blackness of stems (hinting on
- * the x-axis by nature places things on pixel integers, hinting on the
- * y-axis only, i.e., LIGHT mode, doesn't touch the x-axis). The delta
- * values of the scaler would need to be adjusted.
+ * TODO: This code currently doesn't support fractional advance widths,
+ * i.e., placing hinted glyphs at anything other than integer
+ * x-positions. This is only relevant for the warper code, which
+ * scales and shifts glyphs to optimize blackness of stems (hinting on
+ * the x-axis by nature places things on pixel integers, hinting on the
+ * y-axis only, i.e., LIGHT mode, doesn't touch the x-axis). The delta
+ * values of the scaler would need to be adjusted.
*/
scaler.face = face;
scaler.x_scale = size_internal->autohint_metrics.x_scale;
@@ -312,10 +307,10 @@
#endif
/*
- * Glyphs (really code points) are assigned to scripts. Script
- * analysis is done lazily: For each glyph that passes through here,
- * the corresponding script analyzer is called, but returns immediately
- * if it has been run already.
+ * Glyphs (really code points) are assigned to scripts. Script
+ * analysis is done lazily: For each glyph that passes through here,
+ * the corresponding script analyzer is called, but returns immediately
+ * if it has been run already.
*/
error = af_face_globals_get_metrics( loader->globals, glyph_index,
style_options, &style_metrics );
@@ -324,7 +319,7 @@
style_class = style_metrics->style_class;
writing_system_class =
- AF_WRITING_SYSTEM_CLASSES_GET[style_class->writing_system];
+ af_writing_system_classes[style_class->writing_system];
loader->metrics = style_metrics;
@@ -342,11 +337,11 @@
}
/*
- * Do the main work of `af_loader_load_glyph'. Note that we never have
- * to deal with composite glyphs as those get loaded into
- * FT_GLYPH_FORMAT_OUTLINE by the recursed `FT_Load_Glyph' function.
- * In the rare cases where FT_LOAD_NO_RECURSE is set, it implies
- * FT_LOAD_NO_SCALE and as such the auto-hinter is never called.
+ * Do the main work of `af_loader_load_glyph'. Note that we never have
+ * to deal with composite glyphs as those get loaded into
+ * FT_GLYPH_FORMAT_OUTLINE by the recursed `FT_Load_Glyph' function.
+ * In the rare cases where FT_LOAD_NO_RECURSE is set, it implies
+ * FT_LOAD_NO_SCALE and as such the auto-hinter is never called.
*/
load_flags |= FT_LOAD_NO_SCALE |
FT_LOAD_IGNORE_TRANSFORM |
@@ -358,26 +353,26 @@
goto Exit;
/*
- * Apply stem darkening (emboldening) here before hints are applied to
- * the outline. Glyphs are scaled down proportionally to the
- * emboldening so that curve points don't fall outside their
- * precomputed blue zones.
+ * Apply stem darkening (emboldening) here before hints are applied to
+ * the outline. Glyphs are scaled down proportionally to the
+ * emboldening so that curve points don't fall outside their
+ * precomputed blue zones.
*
- * Any emboldening done by the font driver (e.g., the CFF driver)
- * doesn't reach here because the autohinter loads the unprocessed
- * glyphs in font units for analysis (functions `af_*_metrics_init_*')
- * and then above to prepare it for the rasterizers by itself,
- * independently of the font driver. So emboldening must be done here,
- * within the autohinter.
+ * Any emboldening done by the font driver (e.g., the CFF driver)
+ * doesn't reach here because the autohinter loads the unprocessed
+ * glyphs in font units for analysis (functions `af_*_metrics_init_*')
+ * and then above to prepare it for the rasterizers by itself,
+ * independently of the font driver. So emboldening must be done here,
+ * within the autohinter.
*
- * All glyphs to be autohinted pass through here one by one. The
- * standard widths can therefore change from one glyph to the next,
- * depending on what script a glyph is assigned to (each script has its
- * own set of standard widths and other metrics). The darkening amount
- * must therefore be recomputed for each size and
- * `standard_{vertical,horizontal}_width' change.
+ * All glyphs to be autohinted pass through here one by one. The
+ * standard widths can therefore change from one glyph to the next,
+ * depending on what script a glyph is assigned to (each script has its
+ * own set of standard widths and other metrics). The darkening amount
+ * must therefore be recomputed for each size and
+ * `standard_{vertical,horizontal}_width' change.
*
- * Ignore errors and carry on without emboldening.
+ * Ignore errors and carry on without emboldening.
*
*/
@@ -426,35 +421,39 @@
/* now load the slot image into the auto-outline */
/* and run the automatic hinting process */
if ( writing_system_class->style_hints_apply )
- writing_system_class->style_hints_apply( glyph_index,
- hints,
- &gloader->base.outline,
- style_metrics );
+ {
+ error = writing_system_class->style_hints_apply(
+ glyph_index,
+ hints,
+ &gloader->base.outline,
+ style_metrics );
+ if ( error )
+ goto Exit;
+ }
/* we now need to adjust the metrics according to the change in */
/* width/positioning that occurred during the hinting process */
if ( scaler.render_mode != FT_RENDER_MODE_LIGHT )
{
- FT_Pos old_rsb, old_lsb, new_lsb;
- FT_Pos pp1x_uh, pp2x_uh;
-
AF_AxisHints axis = &hints->axis[AF_DIMENSION_HORZ];
- AF_Edge edge1 = axis->edges; /* leftmost edge */
- AF_Edge edge2 = edge1 +
- axis->num_edges - 1; /* rightmost edge */
if ( axis->num_edges > 1 && AF_HINTS_DO_ADVANCE( hints ) )
{
- old_rsb = loader->pp2.x - edge2->opos;
+ AF_Edge edge1 = axis->edges; /* leftmost edge */
+ AF_Edge edge2 = edge1 +
+ axis->num_edges - 1; /* rightmost edge */
+
+ FT_Pos old_rsb = loader->pp2.x - edge2->opos;
/* loader->pp1.x is always zero at this point of time */
- old_lsb = edge1->opos /* - loader->pp1.x */;
- new_lsb = edge1->pos;
+ FT_Pos old_lsb = edge1->opos; /* - loader->pp1.x */
+ FT_Pos new_lsb = edge1->pos;
/* remember unhinted values to later account */
/* for rounding errors */
- pp1x_uh = new_lsb - old_lsb;
- pp2x_uh = edge2->pos + old_rsb;
+ FT_Pos pp1x_uh = new_lsb - old_lsb;
+ FT_Pos pp2x_uh = edge2->pos + old_rsb;
+
/* prefer too much space over too little space */
/* for very small sizes */
diff --git a/thirdparty/freetype/src/autofit/afloader.h b/thirdparty/freetype/src/autofit/afloader.h
index d4d72d1583..d1e0f3c093 100644
--- a/thirdparty/freetype/src/autofit/afloader.h
+++ b/thirdparty/freetype/src/autofit/afloader.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* afloader.h */
-/* */
-/* Auto-fitter glyph loading routines (specification). */
-/* */
-/* Copyright 2003-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * afloader.h
+ *
+ * Auto-fitter glyph loading routines (specification).
+ *
+ * Copyright (C) 2003-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef AFLOADER_H_
@@ -27,11 +27,11 @@
FT_BEGIN_HEADER
/*
- * The autofitter module's (global) data structure to communicate with
- * actual fonts. If necessary, `local' data like the current face, the
- * current face's auto-hint data, or the current glyph's parameters
- * relevant to auto-hinting are `swapped in'. Cf. functions like
- * `af_loader_reset' and `af_loader_load_g'.
+ * The autofitter module's (global) data structure to communicate with
+ * actual fonts. If necessary, `local' data like the current face, the
+ * current face's auto-hint data, or the current glyph's parameters
+ * relevant to auto-hinting are `swapped in'. Cf. functions like
+ * `af_loader_reset' and `af_loader_load_g'.
*/
typedef struct AF_LoaderRec_
diff --git a/thirdparty/freetype/src/autofit/afmodule.c b/thirdparty/freetype/src/autofit/afmodule.c
index dcaa17a27e..3e46a3655a 100644
--- a/thirdparty/freetype/src/autofit/afmodule.c
+++ b/thirdparty/freetype/src/autofit/afmodule.c
@@ -1,26 +1,25 @@
-/***************************************************************************/
-/* */
-/* afmodule.c */
-/* */
-/* Auto-fitter module implementation (body). */
-/* */
-/* Copyright 2003-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * afmodule.c
+ *
+ * Auto-fitter module implementation (body).
+ *
+ * Copyright (C) 2003-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include "afglobal.h"
#include "afmodule.h"
#include "afloader.h"
#include "aferrors.h"
-#include "afpic.h"
#ifdef FT_DEBUG_AUTOFIT
@@ -60,14 +59,14 @@
#include FT_SERVICE_PROPERTIES_H
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_afmodule
+#define FT_COMPONENT afmodule
static FT_Error
@@ -104,19 +103,6 @@
}
-#ifdef FT_CONFIG_OPTION_PIC
-
-#undef AF_SCRIPT_CLASSES_GET
-#define AF_SCRIPT_CLASSES_GET \
- ( GET_PIC( ft_module->library )->af_script_classes )
-
-#undef AF_STYLE_CLASSES_GET
-#define AF_STYLE_CLASSES_GET \
- ( GET_PIC( ft_module->library )->af_style_classes )
-
-#endif
-
-
static FT_Error
af_property_set( FT_Module ft_module,
const char* property_name,
@@ -147,9 +133,9 @@
/* We translate the fallback script to a fallback style that uses */
/* `fallback-script' as its script and `AF_COVERAGE_NONE' as its */
/* coverage value. */
- for ( ss = 0; AF_STYLE_CLASSES_GET[ss]; ss++ )
+ for ( ss = 0; af_style_classes[ss]; ss++ )
{
- AF_StyleClass style_class = AF_STYLE_CLASSES_GET[ss];
+ AF_StyleClass style_class = af_style_classes[ss];
if ( (FT_UInt)style_class->script == *fallback_script &&
@@ -160,7 +146,7 @@
}
}
- if ( !AF_STYLE_CLASSES_GET[ss] )
+ if ( !af_style_classes[ss] )
{
FT_TRACE0(( "af_property_set: Invalid value %d for property `%s'\n",
fallback_script, property_name ));
@@ -357,7 +343,7 @@
{
FT_UInt* val = (FT_UInt*)value;
- AF_StyleClass style_class = AF_STYLE_CLASSES_GET[fallback_style];
+ AF_StyleClass style_class = af_style_classes[fallback_style];
*val = style_class->script;
@@ -440,28 +426,16 @@
FT_DEFINE_SERVICEDESCREC1(
af_services,
- FT_SERVICE_ID_PROPERTIES, &AF_SERVICE_PROPERTIES_GET )
+ FT_SERVICE_ID_PROPERTIES, &af_service_properties )
FT_CALLBACK_DEF( FT_Module_Interface )
af_get_interface( FT_Module module,
const char* module_interface )
{
- /* AF_SERVICES_GET dereferences `library' in PIC mode */
-#ifdef FT_CONFIG_OPTION_PIC
- FT_Library library;
-
-
- if ( !module )
- return NULL;
- library = module->library;
- if ( !library )
- return NULL;
-#else
FT_UNUSED( module );
-#endif
- return ft_service_list_lookup( AF_SERVICES_GET, module_interface );
+ return ft_service_list_lookup( af_services, module_interface );
}
@@ -533,7 +507,7 @@
glyph_index, load_flags );
#ifdef FT_DEBUG_LEVEL_TRACE
- if ( ft_trace_levels[FT_COMPONENT] )
+ if ( ft_trace_levels[FT_TRACE_COMP( FT_COMPONENT )] )
{
#endif
af_glyph_hints_dump_points( hints, 0 );
@@ -589,7 +563,7 @@
0x10000L, /* version 1.0 of the autofitter */
0x20000L, /* requires FreeType 2.0 or above */
- (const void*)&AF_INTERFACE_GET,
+ (const void*)&af_autofitter_interface,
(FT_Module_Constructor)af_autofitter_init, /* module_init */
(FT_Module_Destructor) af_autofitter_done, /* module_done */
diff --git a/thirdparty/freetype/src/autofit/afmodule.h b/thirdparty/freetype/src/autofit/afmodule.h
index 56f64eaf23..b410809aa8 100644
--- a/thirdparty/freetype/src/autofit/afmodule.h
+++ b/thirdparty/freetype/src/autofit/afmodule.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* afmodule.h */
-/* */
-/* Auto-fitter module implementation (specification). */
-/* */
-/* Copyright 2003-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * afmodule.h
+ *
+ * Auto-fitter module implementation (specification).
+ *
+ * Copyright (C) 2003-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef AFMODULE_H_
@@ -28,8 +28,8 @@ FT_BEGIN_HEADER
/*
- * This is the `extended' FT_Module structure that holds the
- * autofitter's global data.
+ * This is the `extended' FT_Module structure that holds the
+ * autofitter's global data.
*/
typedef struct AF_ModuleRec_
diff --git a/thirdparty/freetype/src/autofit/afpic.c b/thirdparty/freetype/src/autofit/afpic.c
deleted file mode 100644
index d48d016a0e..0000000000
--- a/thirdparty/freetype/src/autofit/afpic.c
+++ /dev/null
@@ -1,152 +0,0 @@
-/***************************************************************************/
-/* */
-/* afpic.c */
-/* */
-/* The FreeType position independent code services for autofit module. */
-/* */
-/* Copyright 2009-2018 by */
-/* Oran Agra and Mickey Gabel. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#include <ft2build.h>
-#include FT_FREETYPE_H
-#include FT_INTERNAL_OBJECTS_H
-#include "afpic.h"
-#include "afglobal.h"
-#include "aferrors.h"
-
-
-#ifdef FT_CONFIG_OPTION_PIC
-
- /* forward declaration of PIC init functions from afmodule.c */
- FT_Error
- FT_Create_Class_af_services( FT_Library library,
- FT_ServiceDescRec** output_class );
-
- void
- FT_Destroy_Class_af_services( FT_Library library,
- FT_ServiceDescRec* clazz );
-
- void
- FT_Init_Class_af_service_properties( FT_Service_PropertiesRec* clazz );
-
- void FT_Init_Class_af_autofitter_interface(
- FT_Library library,
- FT_AutoHinter_InterfaceRec* clazz );
-
-
- /* forward declaration of PIC init functions from writing system classes */
-#undef WRITING_SYSTEM
-#define WRITING_SYSTEM( ws, WS ) /* empty */
-
-#include "afwrtsys.h"
-
-
- void
- autofit_module_class_pic_free( FT_Library library )
- {
- FT_PIC_Container* pic_container = &library->pic_container;
- FT_Memory memory = library->memory;
-
-
- if ( pic_container->autofit )
- {
- AFModulePIC* container = (AFModulePIC*)pic_container->autofit;
-
-
- if ( container->af_services )
- FT_Destroy_Class_af_services( library,
- container->af_services );
- container->af_services = NULL;
-
- FT_FREE( container );
- pic_container->autofit = NULL;
- }
- }
-
-
- FT_Error
- autofit_module_class_pic_init( FT_Library library )
- {
- FT_PIC_Container* pic_container = &library->pic_container;
- FT_UInt ss;
- FT_Error error = FT_Err_Ok;
- AFModulePIC* container = NULL;
- FT_Memory memory = library->memory;
-
-
- /* allocate pointer, clear and set global container pointer */
- if ( FT_ALLOC ( container, sizeof ( *container ) ) )
- return error;
- FT_MEM_SET( container, 0, sizeof ( *container ) );
- pic_container->autofit = container;
-
- /* initialize pointer table - */
- /* this is how the module usually expects this data */
- error = FT_Create_Class_af_services( library,
- &container->af_services );
- if ( error )
- goto Exit;
-
- FT_Init_Class_af_service_properties( &container->af_service_properties );
-
- for ( ss = 0; ss < AF_WRITING_SYSTEM_MAX; ss++ )
- container->af_writing_system_classes[ss] =
- &container->af_writing_system_classes_rec[ss];
- container->af_writing_system_classes[AF_WRITING_SYSTEM_MAX] = NULL;
-
- for ( ss = 0; ss < AF_SCRIPT_MAX; ss++ )
- container->af_script_classes[ss] =
- &container->af_script_classes_rec[ss];
- container->af_script_classes[AF_SCRIPT_MAX] = NULL;
-
- for ( ss = 0; ss < AF_STYLE_MAX; ss++ )
- container->af_style_classes[ss] =
- &container->af_style_classes_rec[ss];
- container->af_style_classes[AF_STYLE_MAX] = NULL;
-
-#undef WRITING_SYSTEM
-#define WRITING_SYSTEM( ws, WS ) \
- FT_Init_Class_af_ ## ws ## _writing_system_class( \
- &container->af_writing_system_classes_rec[ss++] );
-
- ss = 0;
-#include "afwrtsys.h"
-
-#undef SCRIPT
-#define SCRIPT( s, S, d, h, H, sss ) \
- FT_Init_Class_af_ ## s ## _script_class( \
- &container->af_script_classes_rec[ss++] );
-
- ss = 0;
-#include "afscript.h"
-
-#undef STYLE
-#define STYLE( s, S, d, ws, sc, bss, c ) \
- FT_Init_Class_af_ ## s ## _style_class( \
- &container->af_style_classes_rec[ss++] );
-
- ss = 0;
-#include "afstyles.h"
-
- FT_Init_Class_af_autofitter_interface(
- library, &container->af_autofitter_interface );
-
- Exit:
- if ( error )
- autofit_module_class_pic_free( library );
- return error;
- }
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
-
-/* END */
diff --git a/thirdparty/freetype/src/autofit/afpic.h b/thirdparty/freetype/src/autofit/afpic.h
deleted file mode 100644
index 0c73456785..0000000000
--- a/thirdparty/freetype/src/autofit/afpic.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/***************************************************************************/
-/* */
-/* afpic.h */
-/* */
-/* The FreeType position independent code services for autofit module. */
-/* */
-/* Copyright 2009-2018 by */
-/* Oran Agra and Mickey Gabel. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#ifndef AFPIC_H_
-#define AFPIC_H_
-
-
-#include FT_INTERNAL_PIC_H
-
-
-#ifndef FT_CONFIG_OPTION_PIC
-
-#define AF_SERVICES_GET af_services
-#define AF_SERVICE_PROPERTIES_GET af_service_properties
-
-#define AF_WRITING_SYSTEM_CLASSES_GET af_writing_system_classes
-#define AF_SCRIPT_CLASSES_GET af_script_classes
-#define AF_STYLE_CLASSES_GET af_style_classes
-#define AF_INTERFACE_GET af_autofitter_interface
-
-#else /* FT_CONFIG_OPTION_PIC */
-
- /* some include files required for members of AFModulePIC */
-#include FT_SERVICE_PROPERTIES_H
-
-#include "aftypes.h"
-
-
-FT_BEGIN_HEADER
-
- typedef struct AFModulePIC_
- {
- FT_ServiceDescRec* af_services;
- FT_Service_PropertiesRec af_service_properties;
-
- AF_WritingSystemClass af_writing_system_classes
- [AF_WRITING_SYSTEM_MAX + 1];
- AF_WritingSystemClassRec af_writing_system_classes_rec
- [AF_WRITING_SYSTEM_MAX];
-
- AF_ScriptClass af_script_classes
- [AF_SCRIPT_MAX + 1];
- AF_ScriptClassRec af_script_classes_rec
- [AF_SCRIPT_MAX];
-
- AF_StyleClass af_style_classes
- [AF_STYLE_MAX + 1];
- AF_StyleClassRec af_style_classes_rec
- [AF_STYLE_MAX];
-
- FT_AutoHinter_InterfaceRec af_autofitter_interface;
-
- } AFModulePIC;
-
-
-#define GET_PIC( lib ) \
- ( (AFModulePIC*)( (lib)->pic_container.autofit ) )
-
-#define AF_SERVICES_GET \
- ( GET_PIC( library )->af_services )
-#define AF_SERVICE_PROPERTIES_GET \
- ( GET_PIC( library )->af_service_properties )
-
-#define AF_WRITING_SYSTEM_CLASSES_GET \
- ( GET_PIC( FT_FACE_LIBRARY( globals->face ) )->af_writing_system_classes )
-#define AF_SCRIPT_CLASSES_GET \
- ( GET_PIC( FT_FACE_LIBRARY( globals->face ) )->af_script_classes )
-#define AF_STYLE_CLASSES_GET \
- ( GET_PIC( FT_FACE_LIBRARY( globals->face ) )->af_style_classes )
-#define AF_INTERFACE_GET \
- ( GET_PIC( library )->af_autofitter_interface )
-
-
- /* see afpic.c for the implementation */
- void
- autofit_module_class_pic_free( FT_Library library );
-
- FT_Error
- autofit_module_class_pic_init( FT_Library library );
-
-FT_END_HEADER
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
- /* */
-
-#endif /* AFPIC_H_ */
-
-
-/* END */
diff --git a/thirdparty/freetype/src/autofit/afranges.c b/thirdparty/freetype/src/autofit/afranges.c
index cf67fafb11..c0dba818a1 100644
--- a/thirdparty/freetype/src/autofit/afranges.c
+++ b/thirdparty/freetype/src/autofit/afranges.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* afranges.c */
-/* */
-/* Auto-fitter Unicode script ranges (body). */
-/* */
-/* Copyright 2013-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * afranges.c
+ *
+ * Auto-fitter Unicode script ranges (body).
+ *
+ * Copyright (C) 2013-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include "afranges.h"
diff --git a/thirdparty/freetype/src/autofit/afranges.h b/thirdparty/freetype/src/autofit/afranges.h
index ba3b5e7ccb..d5917aefed 100644
--- a/thirdparty/freetype/src/autofit/afranges.h
+++ b/thirdparty/freetype/src/autofit/afranges.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* afranges.h */
-/* */
-/* Auto-fitter Unicode script ranges (specification). */
-/* */
-/* Copyright 2013-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * afranges.h
+ *
+ * Auto-fitter Unicode script ranges (specification).
+ *
+ * Copyright (C) 2013-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef AFRANGES_H_
diff --git a/thirdparty/freetype/src/autofit/afscript.h b/thirdparty/freetype/src/autofit/afscript.h
index 623a1734a6..c2f0c7ac60 100644
--- a/thirdparty/freetype/src/autofit/afscript.h
+++ b/thirdparty/freetype/src/autofit/afscript.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* afscript.h */
-/* */
-/* Auto-fitter scripts (specification only). */
-/* */
-/* Copyright 2013-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * afscript.h
+ *
+ * Auto-fitter scripts (specification only).
+ *
+ * Copyright (C) 2013-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
/* The following part can be included multiple times. */
diff --git a/thirdparty/freetype/src/autofit/afshaper.c b/thirdparty/freetype/src/autofit/afshaper.c
index f30828173c..a5191c6915 100644
--- a/thirdparty/freetype/src/autofit/afshaper.c
+++ b/thirdparty/freetype/src/autofit/afshaper.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* afshaper.c */
-/* */
-/* HarfBuzz interface for accessing OpenType features (body). */
-/* */
-/* Copyright 2013-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * afshaper.c
+ *
+ * HarfBuzz interface for accessing OpenType features (body).
+ *
+ * Copyright (C) 2013-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -26,14 +26,14 @@
#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_afshaper
+#define FT_COMPONENT afshaper
/*
@@ -591,14 +591,9 @@
void*
af_shaper_buf_create( FT_Face face )
{
- FT_Error error;
- FT_Memory memory = face->memory;
- FT_ULong* buf;
-
-
- FT_MEM_ALLOC( buf, sizeof ( FT_ULong ) );
+ FT_UNUSED( face );
- return (void*)buf;
+ return NULL;
}
@@ -606,10 +601,8 @@
af_shaper_buf_destroy( FT_Face face,
void* buf )
{
- FT_Memory memory = face->memory;
-
-
- FT_FREE( buf );
+ FT_UNUSED( face );
+ FT_UNUSED( buf );
}
diff --git a/thirdparty/freetype/src/autofit/afshaper.h b/thirdparty/freetype/src/autofit/afshaper.h
index 7efd9f6a4e..06a1e06616 100644
--- a/thirdparty/freetype/src/autofit/afshaper.h
+++ b/thirdparty/freetype/src/autofit/afshaper.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* afshaper.h */
-/* */
-/* HarfBuzz interface for accessing OpenType features (specification). */
-/* */
-/* Copyright 2013-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * afshaper.h
+ *
+ * HarfBuzz interface for accessing OpenType features (specification).
+ *
+ * Copyright (C) 2013-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef AFSHAPER_H_
diff --git a/thirdparty/freetype/src/autofit/afstyles.h b/thirdparty/freetype/src/autofit/afstyles.h
index e2688b3fc2..edf4f54edd 100644
--- a/thirdparty/freetype/src/autofit/afstyles.h
+++ b/thirdparty/freetype/src/autofit/afstyles.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* afstyles.h */
-/* */
-/* Auto-fitter styles (specification only). */
-/* */
-/* Copyright 2013-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * afstyles.h
+ *
+ * Auto-fitter styles (specification only).
+ *
+ * Copyright (C) 2013-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
/* The following part can be included multiple times. */
diff --git a/thirdparty/freetype/src/autofit/aftypes.h b/thirdparty/freetype/src/autofit/aftypes.h
index 6bd8c895b2..579003d27d 100644
--- a/thirdparty/freetype/src/autofit/aftypes.h
+++ b/thirdparty/freetype/src/autofit/aftypes.h
@@ -1,30 +1,30 @@
-/***************************************************************************/
-/* */
-/* aftypes.h */
-/* */
-/* Auto-fitter types (specification only). */
-/* */
-/* Copyright 2003-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * aftypes.h
+ *
+ * Auto-fitter types (specification only).
+ *
+ * Copyright (C) 2003-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
/*************************************************************************
*
- * The auto-fitter is a complete rewrite of the old auto-hinter.
- * Its main feature is the ability to differentiate between different
- * writing systems and scripts in order to apply specific rules.
+ * The auto-fitter is a complete rewrite of the old auto-hinter.
+ * Its main feature is the ability to differentiate between different
+ * writing systems and scripts in order to apply specific rules.
*
- * The code has also been compartmentalized into several entities that
- * should make algorithmic experimentation easier than with the old
- * code.
+ * The code has also been compartmentalized into several entities that
+ * should make algorithmic experimentation easier than with the old
+ * code.
*
*************************************************************************/
@@ -102,9 +102,9 @@ extern void* _af_debug_hints;
/*************************************************************************/
/*
- * The auto-fitter doesn't need a very high angular accuracy;
- * this allows us to speed up some computations considerably with a
- * light Cordic algorithm (see afangles.c).
+ * The auto-fitter doesn't need a very high angular accuracy;
+ * this allows us to speed up some computations considerably with a
+ * light Cordic algorithm (see afangles.c).
*/
typedef FT_Int AF_Angle;
@@ -118,7 +118,7 @@ extern void* _af_debug_hints;
#if 0
/*
- * compute the angle of a given 2-D vector
+ * compute the angle of a given 2-D vector
*/
FT_LOCAL( AF_Angle )
af_angle_atan( FT_Pos dx,
@@ -126,8 +126,8 @@ extern void* _af_debug_hints;
/*
- * compute `angle2 - angle1'; the result is always within
- * the range [-AF_ANGLE_PI .. AF_ANGLE_PI - 1]
+ * compute `angle2 - angle1'; the result is always within
+ * the range [-AF_ANGLE_PI .. AF_ANGLE_PI - 1]
*/
FT_LOCAL( AF_Angle )
af_angle_diff( AF_Angle angle1,
@@ -150,8 +150,9 @@ extern void* _af_debug_hints;
FT_END_STMNT
- /* opaque handle to glyph-specific hints -- see `afhints.h' for more
- * details
+ /*
+ * opaque handle to glyph-specific hints -- see `afhints.h' for more
+ * details
*/
typedef struct AF_GlyphHintsRec_* AF_GlyphHints;
@@ -165,8 +166,8 @@ extern void* _af_debug_hints;
/*************************************************************************/
/*
- * A scaler models the target pixel device that will receive the
- * auto-hinted glyph image.
+ * A scaler models the target pixel device that will receive the
+ * auto-hinted glyph image.
*/
#define AF_SCALER_FLAG_NO_HORIZONTAL 1U /* disable horizontal hinting */
@@ -197,8 +198,9 @@ extern void* _af_debug_hints;
typedef struct AF_StyleMetricsRec_* AF_StyleMetrics;
- /* This function parses an FT_Face to compute global metrics for
- * a specific style.
+ /*
+ * This function parses an FT_Face to compute global metrics for
+ * a specific style.
*/
typedef FT_Error
(*AF_WritingSystem_InitMetricsFunc)( AF_StyleMetrics metrics,
@@ -237,22 +239,22 @@ extern void* _af_debug_hints;
/*************************************************************************/
/*
- * For the auto-hinter, a writing system consists of multiple scripts that
- * can be handled similarly *in a typographical way*; the relationship is
- * not based on history. For example, both the Greek and the unrelated
- * Armenian scripts share the same features like ascender, descender,
- * x-height, etc. Essentially, a writing system is covered by a
- * submodule of the auto-fitter; it contains
+ * For the auto-hinter, a writing system consists of multiple scripts that
+ * can be handled similarly *in a typographical way*; the relationship is
+ * not based on history. For example, both the Greek and the unrelated
+ * Armenian scripts share the same features like ascender, descender,
+ * x-height, etc. Essentially, a writing system is covered by a
+ * submodule of the auto-fitter; it contains
*
- * - a specific global analyzer that computes global metrics specific to
- * the script (based on script-specific characters to identify ascender
- * height, x-height, etc.),
+ * - a specific global analyzer that computes global metrics specific to
+ * the script (based on script-specific characters to identify ascender
+ * height, x-height, etc.),
*
- * - a specific glyph analyzer that computes segments and edges for each
- * glyph covered by the script,
+ * - a specific glyph analyzer that computes segments and edges for each
+ * glyph covered by the script,
*
- * - a specific grid-fitting algorithm that distorts the scaled glyph
- * outline according to the results of the glyph analyzer.
+ * - a specific grid-fitting algorithm that distorts the scaled glyph
+ * outline according to the results of the glyph analyzer.
*/
#define AFWRTSYS_H_ /* don't load header files */
@@ -300,12 +302,12 @@ extern void* _af_debug_hints;
/*************************************************************************/
/*
- * Each script is associated with two sets of Unicode ranges to test
- * whether the font face supports the script, and which non-base
- * characters the script contains.
+ * Each script is associated with two sets of Unicode ranges to test
+ * whether the font face supports the script, and which non-base
+ * characters the script contains.
*
- * We use four-letter script tags from the OpenType specification,
- * extended by `NONE', which indicates `no script'.
+ * We use four-letter script tags from the OpenType specification,
+ * extended by `NONE', which indicates `no script'.
*/
#undef SCRIPT
@@ -361,41 +363,41 @@ extern void* _af_debug_hints;
/*************************************************************************/
/*
- * Usually, a font contains more glyphs than can be addressed by its
- * character map.
+ * Usually, a font contains more glyphs than can be addressed by its
+ * character map.
*
- * In the PostScript font world, encoding vectors specific to a given
- * task are used to select such glyphs, and these glyphs can be often
- * recognized by having a suffix in its glyph names. For example, a
- * superscript glyph `A' might be called `A.sup'. Unfortunately, this
- * naming scheme is not standardized and thus unusable for us.
+ * In the PostScript font world, encoding vectors specific to a given
+ * task are used to select such glyphs, and these glyphs can be often
+ * recognized by having a suffix in its glyph names. For example, a
+ * superscript glyph `A' might be called `A.sup'. Unfortunately, this
+ * naming scheme is not standardized and thus unusable for us.
*
- * In the OpenType world, a better solution was invented, namely
- * `features', which cleanly separate a character's input encoding from
- * the corresponding glyph's appearance, and which don't use glyph names
- * at all. For our purposes, and slightly generalized, an OpenType
- * feature is a name of a mapping that maps character codes to
- * non-standard glyph indices (features get used for other things also).
- * For example, the `sups' feature provides superscript glyphs, thus
- * mapping character codes like `A' or `B' to superscript glyph
- * representation forms. How this mapping happens is completely
- * uninteresting to us.
+ * In the OpenType world, a better solution was invented, namely
+ * `features', which cleanly separate a character's input encoding from
+ * the corresponding glyph's appearance, and which don't use glyph names
+ * at all. For our purposes, and slightly generalized, an OpenType
+ * feature is a name of a mapping that maps character codes to
+ * non-standard glyph indices (features get used for other things also).
+ * For example, the `sups' feature provides superscript glyphs, thus
+ * mapping character codes like `A' or `B' to superscript glyph
+ * representation forms. How this mapping happens is completely
+ * uninteresting to us.
*
- * For the auto-hinter, a `coverage' represents all glyphs of an OpenType
- * feature collected in a set (as listed below) that can be hinted
- * together. To continue the above example, superscript glyphs must not
- * be hinted together with normal glyphs because the blue zones
- * completely differ.
+ * For the auto-hinter, a `coverage' represents all glyphs of an OpenType
+ * feature collected in a set (as listed below) that can be hinted
+ * together. To continue the above example, superscript glyphs must not
+ * be hinted together with normal glyphs because the blue zones
+ * completely differ.
*
- * Note that FreeType itself doesn't compute coverages; it only provides
- * the glyphs addressable by the default Unicode character map. Instead,
- * we use the HarfBuzz library (if available), which has many functions
- * exactly for this purpose.
+ * Note that FreeType itself doesn't compute coverages; it only provides
+ * the glyphs addressable by the default Unicode character map. Instead,
+ * we use the HarfBuzz library (if available), which has many functions
+ * exactly for this purpose.
*
- * AF_COVERAGE_DEFAULT is special: It should cover everything that isn't
- * listed separately (including the glyphs addressable by the character
- * map). In case HarfBuzz isn't available, it exactly covers the glyphs
- * addressable by the character map.
+ * AF_COVERAGE_DEFAULT is special: It should cover everything that isn't
+ * listed separately (including the glyphs addressable by the character
+ * map). In case HarfBuzz isn't available, it exactly covers the glyphs
+ * addressable by the character map.
*
*/
@@ -423,8 +425,8 @@ extern void* _af_debug_hints;
/*************************************************************************/
/*
- * The topmost structure for modelling the auto-hinter glyph input data
- * is a `style class', grouping everything together.
+ * The topmost structure for modelling the auto-hinter glyph input data
+ * is a `style class', grouping everything together.
*/
#undef STYLE
@@ -486,8 +488,6 @@ extern void* _af_debug_hints;
/* Declare and define vtables for classes */
-#ifndef FT_CONFIG_OPTION_PIC
-
#define AF_DECLARE_WRITING_SYSTEM_CLASS( writing_system_class ) \
FT_CALLBACK_TABLE const AF_WritingSystemClassRec \
writing_system_class;
@@ -562,87 +562,9 @@ extern void* _af_debug_hints;
coverage \
};
-#else /* FT_CONFIG_OPTION_PIC */
-
-#define AF_DECLARE_WRITING_SYSTEM_CLASS( writing_system_class ) \
- FT_LOCAL( void ) \
- FT_Init_Class_ ## writing_system_class( AF_WritingSystemClassRec* ac );
-
-#define AF_DEFINE_WRITING_SYSTEM_CLASS( \
- writing_system_class, \
- system, \
- m_size, \
- m_init, \
- m_scale, \
- m_done, \
- m_stdw, \
- h_init, \
- h_apply ) \
- FT_LOCAL_DEF( void ) \
- FT_Init_Class_ ## writing_system_class( AF_WritingSystemClassRec* ac ) \
- { \
- ac->writing_system = system; \
- \
- ac->style_metrics_size = m_size; \
- \
- ac->style_metrics_init = m_init; \
- ac->style_metrics_scale = m_scale; \
- ac->style_metrics_done = m_done; \
- ac->style_metrics_getstdw = m_stdw; \
- \
- ac->style_hints_init = h_init; \
- ac->style_hints_apply = h_apply; \
- }
-
-
-#define AF_DECLARE_SCRIPT_CLASS( script_class ) \
- FT_LOCAL( void ) \
- FT_Init_Class_ ## script_class( AF_ScriptClassRec* ac );
-
-#define AF_DEFINE_SCRIPT_CLASS( \
- script_class, \
- script_, \
- ranges, \
- nonbase_ranges, \
- top_to_bottom, \
- std_charstring ) \
- FT_LOCAL_DEF( void ) \
- FT_Init_Class_ ## script_class( AF_ScriptClassRec* ac ) \
- { \
- ac->script = script_; \
- ac->script_uni_ranges = ranges; \
- ac->script_uni_nonbase_ranges = nonbase_ranges; \
- ac->top_to_bottom_hinting = top_to_bottom; \
- ac->standard_charstring = std_charstring; \
- }
-
-
-#define AF_DECLARE_STYLE_CLASS( style_class ) \
- FT_LOCAL( void ) \
- FT_Init_Class_ ## style_class( AF_StyleClassRec* ac );
-
-#define AF_DEFINE_STYLE_CLASS( \
- style_class, \
- style_, \
- writing_system_, \
- script_, \
- blue_stringset_, \
- coverage_ ) \
- FT_LOCAL_DEF( void ) \
- FT_Init_Class_ ## style_class( AF_StyleClassRec* ac ) \
- { \
- ac->style = style_; \
- ac->writing_system = writing_system_; \
- ac->script = script_; \
- ac->blue_stringset = blue_stringset_; \
- ac->coverage = coverage_; \
- }
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
-
/* */
+
FT_END_HEADER
#endif /* AFTYPES_H_ */
diff --git a/thirdparty/freetype/src/autofit/afwarp.c b/thirdparty/freetype/src/autofit/afwarp.c
index 2a75ea7b35..84e9753ad9 100644
--- a/thirdparty/freetype/src/autofit/afwarp.c
+++ b/thirdparty/freetype/src/autofit/afwarp.c
@@ -1,40 +1,40 @@
-/***************************************************************************/
-/* */
-/* afwarp.c */
-/* */
-/* Auto-fitter warping algorithm (body). */
-/* */
-/* Copyright 2006-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * afwarp.c
+ *
+ * Auto-fitter warping algorithm (body).
+ *
+ * Copyright (C) 2006-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
/*
- * The idea of the warping code is to slightly scale and shift a glyph
- * within a single dimension so that as much of its segments are aligned
- * (more or less) on the grid. To find out the optimal scaling and
- * shifting value, various parameter combinations are tried and scored.
+ * The idea of the warping code is to slightly scale and shift a glyph
+ * within a single dimension so that as much of its segments are aligned
+ * (more or less) on the grid. To find out the optimal scaling and
+ * shifting value, various parameter combinations are tried and scored.
*/
#include "afwarp.h"
#ifdef AF_CONFIG_OPTION_USE_WARPER
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_afwarp
+#define FT_COMPONENT afwarp
/* The weights cover the range 0/64 - 63/64 of a pixel. Obviously, */
diff --git a/thirdparty/freetype/src/autofit/afwarp.h b/thirdparty/freetype/src/autofit/afwarp.h
index 520b1be907..9a2c9a42c1 100644
--- a/thirdparty/freetype/src/autofit/afwarp.h
+++ b/thirdparty/freetype/src/autofit/afwarp.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* afwarp.h */
-/* */
-/* Auto-fitter warping algorithm (specification). */
-/* */
-/* Copyright 2006-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * afwarp.h
+ *
+ * Auto-fitter warping algorithm (specification).
+ *
+ * Copyright (C) 2006-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef AFWARP_H_
@@ -47,12 +47,14 @@ FT_BEGIN_HEADER
} AF_WarperRec, *AF_Warper;
+#ifdef AF_CONFIG_OPTION_USE_WARPER
FT_LOCAL( void )
af_warper_compute( AF_Warper warper,
AF_GlyphHints hints,
AF_Dimension dim,
FT_Fixed *a_scale,
- FT_Fixed *a_delta );
+ FT_Pos *a_delta );
+#endif
FT_END_HEADER
diff --git a/thirdparty/freetype/src/autofit/afwrtsys.h b/thirdparty/freetype/src/autofit/afwrtsys.h
index 4675f3242d..5611cf441a 100644
--- a/thirdparty/freetype/src/autofit/afwrtsys.h
+++ b/thirdparty/freetype/src/autofit/afwrtsys.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* afwrtsys.h */
-/* */
-/* Auto-fitter writing systems (specification only). */
-/* */
-/* Copyright 2013-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * afwrtsys.h
+ *
+ * Auto-fitter writing systems (specification only).
+ *
+ * Copyright (C) 2013-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef AFWRTSYS_H_
diff --git a/thirdparty/freetype/src/autofit/autofit.c b/thirdparty/freetype/src/autofit/autofit.c
index c1605160a1..facfec1744 100644
--- a/thirdparty/freetype/src/autofit/autofit.c
+++ b/thirdparty/freetype/src/autofit/autofit.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* autofit.c */
-/* */
-/* Auto-fitter module (body). */
-/* */
-/* Copyright 2003-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * autofit.c
+ *
+ * Auto-fitter module (body).
+ *
+ * Copyright (C) 2003-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#define FT_MAKE_OPTION_SINGLE_OBJECT
@@ -30,7 +30,6 @@
#include "aflatin2.c"
#include "afloader.c"
#include "afmodule.c"
-#include "afpic.c"
#include "afranges.c"
#include "afshaper.c"
#include "afwarp.c"
diff --git a/thirdparty/freetype/src/autofit/module.mk b/thirdparty/freetype/src/autofit/module.mk
index ff05f83e7e..cf77b169f7 100644
--- a/thirdparty/freetype/src/autofit/module.mk
+++ b/thirdparty/freetype/src/autofit/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright 2003-2018 by
+# Copyright (C) 2003-2019 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/autofit/rules.mk b/thirdparty/freetype/src/autofit/rules.mk
index 75171b412c..c59da33a55 100644
--- a/thirdparty/freetype/src/autofit/rules.mk
+++ b/thirdparty/freetype/src/autofit/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 2003-2018 by
+# Copyright (C) 2003-2019 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
@@ -38,7 +38,6 @@ AUTOF_DRV_SRC := $(AUTOF_DIR)/afangles.c \
$(AUTOF_DIR)/aflatin.c \
$(AUTOF_DIR)/afloader.c \
$(AUTOF_DIR)/afmodule.c \
- $(AUTOF_DIR)/afpic.c \
$(AUTOF_DIR)/afranges.c \
$(AUTOF_DIR)/afshaper.c \
$(AUTOF_DIR)/afwarp.c
diff --git a/thirdparty/freetype/src/base/basepic.c b/thirdparty/freetype/src/base/basepic.c
deleted file mode 100644
index bc80406441..0000000000
--- a/thirdparty/freetype/src/base/basepic.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/***************************************************************************/
-/* */
-/* basepic.c */
-/* */
-/* The FreeType position independent code services for base. */
-/* */
-/* Copyright 2009-2018 by */
-/* Oran Agra and Mickey Gabel. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#include <ft2build.h>
-#include FT_FREETYPE_H
-#include FT_INTERNAL_OBJECTS_H
-#include "basepic.h"
-
-
-#ifdef FT_CONFIG_OPTION_PIC
-
- /* forward declaration of PIC init functions from ftglyph.c */
- void
- FT_Init_Class_ft_outline_glyph_class( FT_Glyph_Class* clazz );
-
- void
- FT_Init_Class_ft_bitmap_glyph_class( FT_Glyph_Class* clazz );
-
-#ifdef FT_CONFIG_OPTION_MAC_FONTS
- /* forward declaration of PIC init function from ftrfork.c */
- /* (not modularized) */
- void
- FT_Init_Table_ft_raccess_guess_table( ft_raccess_guess_rec* record );
-#endif
-
- /* forward declaration of PIC init functions from ftinit.c */
- FT_Error
- ft_create_default_module_classes( FT_Library library );
-
- void
- ft_destroy_default_module_classes( FT_Library library );
-
-
- void
- ft_base_pic_free( FT_Library library )
- {
- FT_PIC_Container* pic_container = &library->pic_container;
- FT_Memory memory = library->memory;
-
-
- if ( pic_container->base )
- {
- /* destroy default module classes */
- /* (in case FT_Add_Default_Modules was used) */
- ft_destroy_default_module_classes( library );
-
- FT_FREE( pic_container->base );
- pic_container->base = NULL;
- }
- }
-
-
- FT_Error
- ft_base_pic_init( FT_Library library )
- {
- FT_PIC_Container* pic_container = &library->pic_container;
- FT_Error error = FT_Err_Ok;
- BasePIC* container = NULL;
- FT_Memory memory = library->memory;
-
-
- /* allocate pointer, clear and set global container pointer */
- if ( FT_ALLOC( container, sizeof ( *container ) ) )
- return error;
- FT_MEM_SET( container, 0, sizeof ( *container ) );
- pic_container->base = container;
-
- /* initialize default modules list and pointers */
- error = ft_create_default_module_classes( library );
- if ( error )
- goto Exit;
-
- /* initialize pointer table - */
- /* this is how the module usually expects this data */
- FT_Init_Class_ft_outline_glyph_class(
- &container->ft_outline_glyph_class );
- FT_Init_Class_ft_bitmap_glyph_class(
- &container->ft_bitmap_glyph_class );
-#ifdef FT_CONFIG_OPTION_MAC_FONTS
- FT_Init_Table_ft_raccess_guess_table(
- (ft_raccess_guess_rec*)&container->ft_raccess_guess_table );
-#endif
-
- Exit:
- if ( error )
- ft_base_pic_free( library );
- return error;
- }
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
-
-/* END */
diff --git a/thirdparty/freetype/src/base/basepic.h b/thirdparty/freetype/src/base/basepic.h
deleted file mode 100644
index 492d1ede56..0000000000
--- a/thirdparty/freetype/src/base/basepic.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/***************************************************************************/
-/* */
-/* basepic.h */
-/* */
-/* The FreeType position independent code services for base. */
-/* */
-/* Copyright 2009-2018 by */
-/* Oran Agra and Mickey Gabel. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#ifndef BASEPIC_H_
-#define BASEPIC_H_
-
-
-#include FT_INTERNAL_PIC_H
-
-
-#ifndef FT_CONFIG_OPTION_PIC
-
-#define FT_OUTLINE_GLYPH_CLASS_GET &ft_outline_glyph_class
-#define FT_BITMAP_GLYPH_CLASS_GET &ft_bitmap_glyph_class
-#define FT_DEFAULT_MODULES_GET ft_default_modules
-
-#ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK
-#define FT_RACCESS_GUESS_TABLE_GET ft_raccess_guess_table
-#endif
-
-#else /* FT_CONFIG_OPTION_PIC */
-
-#include FT_GLYPH_H
-
-#ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK
-#include FT_INTERNAL_RFORK_H
-#endif
-
-
-FT_BEGIN_HEADER
-
- typedef struct BasePIC_
- {
- FT_Module_Class** default_module_classes;
- FT_Glyph_Class ft_outline_glyph_class;
- FT_Glyph_Class ft_bitmap_glyph_class;
-
-#ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK
- ft_raccess_guess_rec ft_raccess_guess_table[FT_RACCESS_N_RULES];
-#endif
-
- } BasePIC;
-
-
-#define GET_PIC( lib ) ( (BasePIC*)( (lib)->pic_container.base ) )
-
-#define FT_OUTLINE_GLYPH_CLASS_GET \
- ( &GET_PIC( library )->ft_outline_glyph_class )
-#define FT_BITMAP_GLYPH_CLASS_GET \
- ( &GET_PIC( library )->ft_bitmap_glyph_class )
-#define FT_DEFAULT_MODULES_GET \
- ( GET_PIC( library )->default_module_classes )
-
-#ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK
-#define FT_RACCESS_GUESS_TABLE_GET \
- ( GET_PIC( library )->ft_raccess_guess_table )
-#endif
-
-
- /* see basepic.c for the implementation */
- void
- ft_base_pic_free( FT_Library library );
-
- FT_Error
- ft_base_pic_init( FT_Library library );
-
-FT_END_HEADER
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
- /* */
-
-#endif /* BASEPIC_H_ */
-
-
-/* END */
diff --git a/thirdparty/freetype/src/base/ftadvanc.c b/thirdparty/freetype/src/base/ftadvanc.c
index 230c84d6ad..0dfba57036 100644
--- a/thirdparty/freetype/src/base/ftadvanc.c
+++ b/thirdparty/freetype/src/base/ftadvanc.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftadvanc.c */
-/* */
-/* Quick computation of advance widths (body). */
-/* */
-/* Copyright 2008-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftadvanc.c
+ *
+ * Quick computation of advance widths (body).
+ *
+ * Copyright (C) 2008-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
diff --git a/thirdparty/freetype/src/base/ftapi.c b/thirdparty/freetype/src/base/ftapi.c
deleted file mode 100644
index 32d6e95d19..0000000000
--- a/thirdparty/freetype/src/base/ftapi.c
+++ /dev/null
@@ -1,121 +0,0 @@
-/***************************************************************************/
-/* */
-/* ftapi.c */
-/* */
-/* The FreeType compatibility functions (body). */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#include <ft2build.h>
-#include FT_LIST_H
-#include FT_OUTLINE_H
-#include FT_INTERNAL_OBJECTS_H
-#include FT_INTERNAL_DEBUG_H
-#include FT_INTERNAL_STREAM_H
-#include FT_TRUETYPE_TABLES_H
-#include FT_OUTLINE_H
-
-
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
- /**** ****/
- /**** ****/
- /**** C O M P A T I B I L I T Y ****/
- /**** ****/
- /**** ****/
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
-
- /* backward compatibility API */
-
- FT_BASE_DEF( void )
- FT_New_Memory_Stream( FT_Library library,
- FT_Byte* base,
- FT_ULong size,
- FT_Stream stream )
- {
- FT_UNUSED( library );
-
- FT_Stream_OpenMemory( stream, base, size );
- }
-
-
- FT_BASE_DEF( FT_Error )
- FT_Seek_Stream( FT_Stream stream,
- FT_ULong pos )
- {
- return FT_Stream_Seek( stream, pos );
- }
-
-
- FT_BASE_DEF( FT_Error )
- FT_Skip_Stream( FT_Stream stream,
- FT_Long distance )
- {
- return FT_Stream_Skip( stream, distance );
- }
-
-
- FT_BASE_DEF( FT_Error )
- FT_Read_Stream( FT_Stream stream,
- FT_Byte* buffer,
- FT_ULong count )
- {
- return FT_Stream_Read( stream, buffer, count );
- }
-
-
- FT_BASE_DEF( FT_Error )
- FT_Read_Stream_At( FT_Stream stream,
- FT_ULong pos,
- FT_Byte* buffer,
- FT_ULong count )
- {
- return FT_Stream_ReadAt( stream, pos, buffer, count );
- }
-
-
- FT_BASE_DEF( FT_Error )
- FT_Extract_Frame( FT_Stream stream,
- FT_ULong count,
- FT_Byte** pbytes )
- {
- return FT_Stream_ExtractFrame( stream, count, pbytes );
- }
-
-
- FT_BASE_DEF( void )
- FT_Release_Frame( FT_Stream stream,
- FT_Byte** pbytes )
- {
- FT_Stream_ReleaseFrame( stream, pbytes );
- }
-
- FT_BASE_DEF( FT_Error )
- FT_Access_Frame( FT_Stream stream,
- FT_ULong count )
- {
- return FT_Stream_EnterFrame( stream, count );
- }
-
-
- FT_BASE_DEF( void )
- FT_Forget_Frame( FT_Stream stream )
- {
- FT_Stream_ExitFrame( stream );
- }
-
-
-/* END */
diff --git a/thirdparty/freetype/src/base/ftbase.c b/thirdparty/freetype/src/base/ftbase.c
index f914b9b247..fb8cbfcc27 100644
--- a/thirdparty/freetype/src/base/ftbase.c
+++ b/thirdparty/freetype/src/base/ftbase.c
@@ -1,28 +1,29 @@
-/***************************************************************************/
-/* */
-/* ftbase.c */
-/* */
-/* Single object library component (body only). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftbase.c
+ *
+ * Single object library component (body only).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
#define FT_MAKE_OPTION_SINGLE_OBJECT
-#include "basepic.c"
#include "ftadvanc.c"
#include "ftcalc.c"
+#include "ftcolor.c"
#include "ftdbgmem.c"
+#include "fterrors.c"
#include "ftfntfmt.c"
#include "ftgloadr.c"
#include "fthash.c"
@@ -30,7 +31,6 @@
#include "ftmac.c"
#include "ftobjs.c"
#include "ftoutln.c"
-#include "ftpic.c"
#include "ftpsprop.c"
#include "ftrfork.c"
#include "ftsnames.c"
diff --git a/thirdparty/freetype/src/base/ftbase.h b/thirdparty/freetype/src/base/ftbase.h
index 7e8cfad959..35b1c47fd9 100644
--- a/thirdparty/freetype/src/base/ftbase.h
+++ b/thirdparty/freetype/src/base/ftbase.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftbase.h */
-/* */
-/* Private functions used in the `base' module (specification). */
-/* */
-/* Copyright 2008-2018 by */
-/* David Turner, Robert Wilhelm, Werner Lemberg, and suzuki toshiya. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftbase.h
+ *
+ * Private functions used in the `base' module (specification).
+ *
+ * Copyright (C) 2008-2019 by
+ * David Turner, Robert Wilhelm, Werner Lemberg, and suzuki toshiya.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTBASE_H_
diff --git a/thirdparty/freetype/src/base/ftbbox.c b/thirdparty/freetype/src/base/ftbbox.c
index 151e85c97a..0b04fde635 100644
--- a/thirdparty/freetype/src/base/ftbbox.c
+++ b/thirdparty/freetype/src/base/ftbbox.c
@@ -1,27 +1,27 @@
-/***************************************************************************/
-/* */
-/* ftbbox.c */
-/* */
-/* FreeType bbox computation (body). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used */
-/* modified and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* This component has a _single_ role: to compute exact outline bounding */
- /* boxes. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * ftbbox.c
+ *
+ * FreeType bbox computation (body).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used
+ * modified and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * This component has a _single_ role: to compute exact outline bounding
+ * boxes.
+ *
+ */
#include <ft2build.h>
@@ -61,26 +61,28 @@
( p->y < bbox.yMin || p->y > bbox.yMax )
- /*************************************************************************/
- /* */
- /* <Function> */
- /* BBox_Move_To */
- /* */
- /* <Description> */
- /* This function is used as a `move_to' emitter during */
- /* FT_Outline_Decompose(). It simply records the destination point */
- /* in `user->last'. We also update bbox in case contour starts with */
- /* an implicit `on' point. */
- /* */
- /* <Input> */
- /* to :: A pointer to the destination vector. */
- /* */
- /* <InOut> */
- /* user :: A pointer to the current walk context. */
- /* */
- /* <Return> */
- /* Always 0. Needed for the interface only. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * BBox_Move_To
+ *
+ * @Description:
+ * This function is used as a `move_to' emitter during
+ * FT_Outline_Decompose(). It simply records the destination point
+ * in `user->last'. We also update bbox in case contour starts with
+ * an implicit `on' point.
+ *
+ * @Input:
+ * to ::
+ * A pointer to the destination vector.
+ *
+ * @InOut:
+ * user ::
+ * A pointer to the current walk context.
+ *
+ * @Return:
+ * Always 0. Needed for the interface only.
+ */
static int
BBox_Move_To( FT_Vector* to,
TBBox_Rec* user )
@@ -93,26 +95,28 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* BBox_Line_To */
- /* */
- /* <Description> */
- /* This function is used as a `line_to' emitter during */
- /* FT_Outline_Decompose(). It simply records the destination point */
- /* in `user->last'; no further computations are necessary because */
- /* bbox already contains both explicit ends of the line segment. */
- /* */
- /* <Input> */
- /* to :: A pointer to the destination vector. */
- /* */
- /* <InOut> */
- /* user :: A pointer to the current walk context. */
- /* */
- /* <Return> */
- /* Always 0. Needed for the interface only. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * BBox_Line_To
+ *
+ * @Description:
+ * This function is used as a `line_to' emitter during
+ * FT_Outline_Decompose(). It simply records the destination point
+ * in `user->last'; no further computations are necessary because
+ * bbox already contains both explicit ends of the line segment.
+ *
+ * @Input:
+ * to ::
+ * A pointer to the destination vector.
+ *
+ * @InOut:
+ * user ::
+ * A pointer to the current walk context.
+ *
+ * @Return:
+ * Always 0. Needed for the interface only.
+ */
static int
BBox_Line_To( FT_Vector* to,
TBBox_Rec* user )
@@ -123,28 +127,33 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* BBox_Conic_Check */
- /* */
- /* <Description> */
- /* Find the extrema of a 1-dimensional conic Bezier curve and update */
- /* a bounding range. This version uses direct computation, as it */
- /* doesn't need square roots. */
- /* */
- /* <Input> */
- /* y1 :: The start coordinate. */
- /* */
- /* y2 :: The coordinate of the control point. */
- /* */
- /* y3 :: The end coordinate. */
- /* */
- /* <InOut> */
- /* min :: The address of the current minimum. */
- /* */
- /* max :: The address of the current maximum. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * BBox_Conic_Check
+ *
+ * @Description:
+ * Find the extrema of a 1-dimensional conic Bezier curve and update
+ * a bounding range. This version uses direct computation, as it
+ * doesn't need square roots.
+ *
+ * @Input:
+ * y1 ::
+ * The start coordinate.
+ *
+ * y2 ::
+ * The coordinate of the control point.
+ *
+ * y3 ::
+ * The end coordinate.
+ *
+ * @InOut:
+ * min ::
+ * The address of the current minimum.
+ *
+ * max ::
+ * The address of the current maximum.
+ */
static void
BBox_Conic_Check( FT_Pos y1,
FT_Pos y2,
@@ -168,32 +177,35 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* BBox_Conic_To */
- /* */
- /* <Description> */
- /* This function is used as a `conic_to' emitter during */
- /* FT_Outline_Decompose(). It checks a conic Bezier curve with the */
- /* current bounding box, and computes its extrema if necessary to */
- /* update it. */
- /* */
- /* <Input> */
- /* control :: A pointer to a control point. */
- /* */
- /* to :: A pointer to the destination vector. */
- /* */
- /* <InOut> */
- /* user :: The address of the current walk context. */
- /* */
- /* <Return> */
- /* Always 0. Needed for the interface only. */
- /* */
- /* <Note> */
- /* In the case of a non-monotonous arc, we compute directly the */
- /* extremum coordinates, as it is sufficiently fast. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * BBox_Conic_To
+ *
+ * @Description:
+ * This function is used as a `conic_to' emitter during
+ * FT_Outline_Decompose(). It checks a conic Bezier curve with the
+ * current bounding box, and computes its extrema if necessary to
+ * update it.
+ *
+ * @Input:
+ * control ::
+ * A pointer to a control point.
+ *
+ * to ::
+ * A pointer to the destination vector.
+ *
+ * @InOut:
+ * user ::
+ * The address of the current walk context.
+ *
+ * @Return:
+ * Always 0. Needed for the interface only.
+ *
+ * @Note:
+ * In the case of a non-monotonous arc, we compute directly the
+ * extremum coordinates, as it is sufficiently fast.
+ */
static int
BBox_Conic_To( FT_Vector* control,
FT_Vector* to,
@@ -222,30 +234,36 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* BBox_Cubic_Check */
- /* */
- /* <Description> */
- /* Find the extrema of a 1-dimensional cubic Bezier curve and */
- /* update a bounding range. This version uses iterative splitting */
- /* because it is faster than the exact solution with square roots. */
- /* */
- /* <Input> */
- /* p1 :: The start coordinate. */
- /* */
- /* p2 :: The coordinate of the first control point. */
- /* */
- /* p3 :: The coordinate of the second control point. */
- /* */
- /* p4 :: The end coordinate. */
- /* */
- /* <InOut> */
- /* min :: The address of the current minimum. */
- /* */
- /* max :: The address of the current maximum. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * BBox_Cubic_Check
+ *
+ * @Description:
+ * Find the extrema of a 1-dimensional cubic Bezier curve and
+ * update a bounding range. This version uses iterative splitting
+ * because it is faster than the exact solution with square roots.
+ *
+ * @Input:
+ * p1 ::
+ * The start coordinate.
+ *
+ * p2 ::
+ * The coordinate of the first control point.
+ *
+ * p3 ::
+ * The coordinate of the second control point.
+ *
+ * p4 ::
+ * The end coordinate.
+ *
+ * @InOut:
+ * min ::
+ * The address of the current minimum.
+ *
+ * max ::
+ * The address of the current maximum.
+ */
static FT_Pos
cubic_peak( FT_Pos q1,
FT_Pos q2,
@@ -361,34 +379,38 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* BBox_Cubic_To */
- /* */
- /* <Description> */
- /* This function is used as a `cubic_to' emitter during */
- /* FT_Outline_Decompose(). It checks a cubic Bezier curve with the */
- /* current bounding box, and computes its extrema if necessary to */
- /* update it. */
- /* */
- /* <Input> */
- /* control1 :: A pointer to the first control point. */
- /* */
- /* control2 :: A pointer to the second control point. */
- /* */
- /* to :: A pointer to the destination vector. */
- /* */
- /* <InOut> */
- /* user :: The address of the current walk context. */
- /* */
- /* <Return> */
- /* Always 0. Needed for the interface only. */
- /* */
- /* <Note> */
- /* In the case of a non-monotonous arc, we don't compute directly */
- /* extremum coordinates, we subdivide instead. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * BBox_Cubic_To
+ *
+ * @Description:
+ * This function is used as a `cubic_to' emitter during
+ * FT_Outline_Decompose(). It checks a cubic Bezier curve with the
+ * current bounding box, and computes its extrema if necessary to
+ * update it.
+ *
+ * @Input:
+ * control1 ::
+ * A pointer to the first control point.
+ *
+ * control2 ::
+ * A pointer to the second control point.
+ *
+ * to ::
+ * A pointer to the destination vector.
+ *
+ * @InOut:
+ * user ::
+ * The address of the current walk context.
+ *
+ * @Return:
+ * Always 0. Needed for the interface only.
+ *
+ * @Note:
+ * In the case of a non-monotonous arc, we don't compute directly
+ * extremum coordinates, we subdivide instead.
+ */
static int
BBox_Cubic_To( FT_Vector* control1,
FT_Vector* control2,
@@ -490,12 +512,6 @@
FT_Error error;
TBBox_Rec user;
-#ifdef FT_CONFIG_OPTION_PIC
- FT_Outline_Funcs bbox_interface;
-
-
- Init_Class_bbox_interface( &bbox_interface );
-#endif
user.bbox = bbox;
diff --git a/thirdparty/freetype/src/base/ftbdf.c b/thirdparty/freetype/src/base/ftbdf.c
index c4ea502fbc..c0fccd7b7c 100644
--- a/thirdparty/freetype/src/base/ftbdf.c
+++ b/thirdparty/freetype/src/base/ftbdf.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftbdf.c */
-/* */
-/* FreeType API for accessing BDF-specific strings (body). */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftbdf.c
+ *
+ * FreeType API for accessing BDF-specific strings (body).
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
diff --git a/thirdparty/freetype/src/base/ftbitmap.c b/thirdparty/freetype/src/base/ftbitmap.c
index a9746663fa..1bdcd9eff3 100644
--- a/thirdparty/freetype/src/base/ftbitmap.c
+++ b/thirdparty/freetype/src/base/ftbitmap.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftbitmap.c */
-/* */
-/* FreeType utility functions for bitmaps (body). */
-/* */
-/* Copyright 2004-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftbitmap.c
+ *
+ * FreeType utility functions for bitmaps (body).
+ *
+ * Copyright (C) 2004-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -24,8 +24,18 @@
#include FT_INTERNAL_OBJECTS_H
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
+#undef FT_COMPONENT
+#define FT_COMPONENT bitmap
+
+
static
- const FT_Bitmap null_bitmap = { 0, 0, 0, 0, 0, 0, 0, 0 };
+ const FT_Bitmap null_bitmap = { 0, 0, 0, NULL, 0, 0, 0, NULL };
/* documentation is in ftbitmap.h */
@@ -786,6 +796,331 @@
/* documentation is in ftbitmap.h */
FT_EXPORT_DEF( FT_Error )
+ FT_Bitmap_Blend( FT_Library library,
+ const FT_Bitmap* source_,
+ const FT_Vector source_offset_,
+ FT_Bitmap* target,
+ FT_Vector *atarget_offset,
+ FT_Color color )
+ {
+ FT_Error error = FT_Err_Ok;
+ FT_Memory memory;
+
+ FT_Bitmap source_bitmap;
+ const FT_Bitmap* source;
+
+ FT_Vector source_offset;
+ FT_Vector target_offset;
+
+ FT_Bool free_source_bitmap = 0;
+ FT_Bool free_target_bitmap_on_error = 0;
+
+ FT_Pos source_llx, source_lly, source_urx, source_ury;
+ FT_Pos target_llx, target_lly, target_urx, target_ury;
+ FT_Pos final_llx, final_lly, final_urx, final_ury;
+
+ unsigned int final_rows, final_width;
+ long x, y;
+
+
+ if ( !library || !target || !source_ || !atarget_offset )
+ return FT_THROW( Invalid_Argument );
+
+ memory = library->memory;
+
+ if ( !( target->pixel_mode == FT_PIXEL_MODE_NONE ||
+ ( target->pixel_mode == FT_PIXEL_MODE_BGRA &&
+ target->buffer ) ) )
+ return FT_THROW( Invalid_Argument );
+
+ if ( source_->pixel_mode == FT_PIXEL_MODE_NONE )
+ return FT_Err_Ok; /* nothing to do */
+
+ /* pitches must have the same sign */
+ if ( target->pixel_mode == FT_PIXEL_MODE_BGRA &&
+ ( source_->pitch ^ target->pitch ) < 0 )
+ return FT_THROW( Invalid_Argument );
+
+ if ( !( source_->width && source_->rows ) )
+ return FT_Err_Ok; /* nothing to do */
+
+ /* assure integer pixel offsets */
+ source_offset.x = FT_PIX_FLOOR( source_offset_.x );
+ source_offset.y = FT_PIX_FLOOR( source_offset_.y );
+ target_offset.x = FT_PIX_FLOOR( atarget_offset->x );
+ target_offset.y = FT_PIX_FLOOR( atarget_offset->y );
+
+ /* get source bitmap dimensions */
+ source_llx = source_offset.x;
+ if ( FT_LONG_MIN + (FT_Pos)( source_->rows << 6 ) + 64 > source_offset.y )
+ {
+ FT_TRACE5((
+ "FT_Bitmap_Blend: y coordinate overflow in source bitmap\n" ));
+ return FT_THROW( Invalid_Argument );
+ }
+ source_lly = source_offset.y - ( source_->rows << 6 );
+
+ if ( FT_LONG_MAX - (FT_Pos)( source_->width << 6 ) - 64 < source_llx )
+ {
+ FT_TRACE5((
+ "FT_Bitmap_Blend: x coordinate overflow in source bitmap\n" ));
+ return FT_THROW( Invalid_Argument );
+ }
+ source_urx = source_llx + ( source_->width << 6 );
+ source_ury = source_offset.y;
+
+ /* get target bitmap dimensions */
+ if ( target->width && target->rows )
+ {
+ target_llx = target_offset.x;
+ if ( FT_LONG_MIN + (FT_Pos)( target->rows << 6 ) > target_offset.y )
+ {
+ FT_TRACE5((
+ "FT_Bitmap_Blend: y coordinate overflow in target bitmap\n" ));
+ return FT_THROW( Invalid_Argument );
+ }
+ target_lly = target_offset.y - ( target->rows << 6 );
+
+ if ( FT_LONG_MAX - (FT_Pos)( target->width << 6 ) < target_llx )
+ {
+ FT_TRACE5((
+ "FT_Bitmap_Blend: x coordinate overflow in target bitmap\n" ));
+ return FT_THROW( Invalid_Argument );
+ }
+ target_urx = target_llx + ( target->width << 6 );
+ target_ury = target_offset.y;
+ }
+ else
+ {
+ target_llx = FT_LONG_MAX;
+ target_lly = FT_LONG_MAX;
+ target_urx = FT_LONG_MIN;
+ target_ury = FT_LONG_MIN;
+ }
+
+ /* compute final bitmap dimensions */
+ final_llx = FT_MIN( source_llx, target_llx );
+ final_lly = FT_MIN( source_lly, target_lly );
+ final_urx = FT_MAX( source_urx, target_urx );
+ final_ury = FT_MAX( source_ury, target_ury );
+
+ final_width = ( final_urx - final_llx ) >> 6;
+ final_rows = ( final_ury - final_lly ) >> 6;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ FT_TRACE5(( "FT_Bitmap_Blend:\n"
+ " source bitmap: (%d, %d) -- (%d, %d); %d x %d\n",
+ source_llx / 64, source_lly / 64,
+ source_urx / 64, source_ury / 64,
+ source_->width, source_->rows ));
+
+ if ( target->width && target->rows )
+ FT_TRACE5(( " target bitmap: (%d, %d) -- (%d, %d); %d x %d\n",
+ target_llx / 64, target_lly / 64,
+ target_urx / 64, target_ury / 64,
+ target->width, target->rows ));
+ else
+ FT_TRACE5(( " target bitmap: empty\n" ));
+
+ FT_TRACE5(( " final bitmap: (%d, %d) -- (%d, %d); %d x %d\n",
+ final_llx / 64, final_lly / 64,
+ final_urx / 64, final_ury / 64,
+ final_width, final_rows ));
+#endif /* FT_DEBUG_LEVEL_TRACE */
+
+ /* for blending, set offset vector of final bitmap */
+ /* temporarily to (0,0) */
+ source_llx -= final_llx;
+ source_lly -= final_lly;
+
+ if ( target->width && target->rows )
+ {
+ target_llx -= final_llx;
+ target_lly -= final_lly;
+ }
+
+ /* set up target bitmap */
+ if ( target->pixel_mode == FT_PIXEL_MODE_NONE )
+ {
+ /* create new empty bitmap */
+ target->width = final_width;
+ target->rows = final_rows;
+ target->pixel_mode = FT_PIXEL_MODE_BGRA;
+ target->pitch = (int)final_width * 4;
+ target->num_grays = 256;
+
+ if ( FT_LONG_MAX / target->pitch < (int)target->rows )
+ {
+ FT_TRACE5(( "FT_Blend_Bitmap: target bitmap too large (%d x %d)\n",
+ final_width, final_rows ));
+ return FT_THROW( Invalid_Argument );
+ }
+
+ if ( FT_ALLOC( target->buffer, target->pitch * (int)target->rows ) )
+ return error;
+
+ free_target_bitmap_on_error = 1;
+ }
+ else if ( target->width != final_width ||
+ target->rows != final_rows )
+ {
+ /* adjust old bitmap to enlarged size */
+ int pitch, new_pitch;
+
+ unsigned char* buffer = NULL;
+
+
+ pitch = target->pitch;
+ if ( pitch < 0 )
+ pitch = -pitch;
+
+ new_pitch = (int)final_width * 4;
+
+ if ( FT_LONG_MAX / new_pitch < (int)final_rows )
+ {
+ FT_TRACE5(( "FT_Blend_Bitmap: target bitmap too large (%d x %d)\n",
+ final_width, final_rows ));
+ return FT_THROW( Invalid_Argument );
+ }
+
+ /* TODO: provide an in-buffer solution for large bitmaps */
+ /* to avoid allocation of a new buffer */
+ if ( FT_ALLOC( buffer, new_pitch * (int)final_rows ) )
+ goto Error;
+
+ /* copy data to new buffer */
+ x = target_llx >> 6;
+ y = target_lly >> 6;
+
+ /* the bitmap flow is from top to bottom, */
+ /* but y is measured from bottom to top */
+ if ( target->pitch < 0 )
+ {
+ /* XXX */
+ }
+ else
+ {
+ unsigned char* p =
+ target->buffer;
+ unsigned char* q =
+ buffer +
+ ( final_rows - y - target->rows ) * new_pitch +
+ x * 4;
+ unsigned char* limit_p =
+ p + pitch * (int)target->rows;
+
+
+ while ( p < limit_p )
+ {
+ FT_MEM_COPY( q, p, pitch );
+
+ p += pitch;
+ q += new_pitch;
+ }
+ }
+
+ FT_FREE( target->buffer );
+
+ target->width = final_width;
+ target->rows = final_rows;
+
+ if ( target->pitch < 0 )
+ target->pitch = -new_pitch;
+ else
+ target->pitch = new_pitch;
+
+ target->buffer = buffer;
+ }
+
+ /* adjust source bitmap if necessary */
+ if ( source_->pixel_mode != FT_PIXEL_MODE_GRAY )
+ {
+ FT_Bitmap_Init( &source_bitmap );
+ error = FT_Bitmap_Convert( library, source_, &source_bitmap, 1 );
+ if ( error )
+ goto Error;
+
+ source = &source_bitmap;
+ free_source_bitmap = 1;
+ }
+ else
+ source = source_;
+
+ /* do blending; the code below returns pre-multiplied channels, */
+ /* similar to what FreeType gets from `CBDT' tables */
+ x = source_llx >> 6;
+ y = source_lly >> 6;
+
+ /* the bitmap flow is from top to bottom, */
+ /* but y is measured from bottom to top */
+ if ( target->pitch < 0 )
+ {
+ /* XXX */
+ }
+ else
+ {
+ unsigned char* p =
+ source->buffer;
+ unsigned char* q =
+ target->buffer +
+ ( target->rows - y - source->rows ) * target->pitch +
+ x * 4;
+ unsigned char* limit_p =
+ p + source->pitch * (int)source->rows;
+
+
+ while ( p < limit_p )
+ {
+ unsigned char* r = p;
+ unsigned char* s = q;
+ unsigned char* limit_r = r + source->width;
+
+
+ while ( r < limit_r )
+ {
+ int aa = *r++;
+ int fa = color.alpha * aa / 255;
+
+ int fb = color.blue * fa / 255;
+ int fg = color.green * fa / 255;
+ int fr = color.red * fa / 255;
+
+ int ba2 = 255 - fa;
+
+ int bb = s[0];
+ int bg = s[1];
+ int br = s[2];
+ int ba = s[3];
+
+
+ *s++ = (unsigned char)( bb * ba2 / 255 + fb );
+ *s++ = (unsigned char)( bg * ba2 / 255 + fg );
+ *s++ = (unsigned char)( br * ba2 / 255 + fr );
+ *s++ = (unsigned char)( ba * ba2 / 255 + fa );
+ }
+
+ p += source->pitch;
+ q += target->pitch;
+ }
+ }
+
+ atarget_offset->x = final_llx;
+ atarget_offset->y = final_lly + ( final_rows << 6 );
+
+ Error:
+ if ( error && free_target_bitmap_on_error )
+ FT_Bitmap_Done( library, target );
+
+ if ( free_source_bitmap )
+ FT_Bitmap_Done( library, &source_bitmap );
+
+ return error;
+ }
+
+
+ /* documentation is in ftbitmap.h */
+
+ FT_EXPORT_DEF( FT_Error )
FT_GlyphSlot_Own_Bitmap( FT_GlyphSlot slot )
{
if ( slot && slot->format == FT_GLYPH_FORMAT_BITMAP &&
diff --git a/thirdparty/freetype/src/base/ftcalc.c b/thirdparty/freetype/src/base/ftcalc.c
index f4ff45f8ef..315dc44185 100644
--- a/thirdparty/freetype/src/base/ftcalc.c
+++ b/thirdparty/freetype/src/base/ftcalc.c
@@ -1,35 +1,35 @@
-/***************************************************************************/
-/* */
-/* ftcalc.c */
-/* */
-/* Arithmetic computations (body). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
- /*************************************************************************/
- /* */
- /* Support for 1-complement arithmetic has been totally dropped in this */
- /* release. You can still write your own code if you need it. */
- /* */
- /*************************************************************************/
-
- /*************************************************************************/
- /* */
- /* Implementing basic computation routines. */
- /* */
- /* FT_MulDiv(), FT_MulFix(), FT_DivFix(), FT_RoundFix(), FT_CeilFix(), */
- /* and FT_FloorFix() are declared in freetype.h. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * ftcalc.c
+ *
+ * Arithmetic computations (body).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+ /**************************************************************************
+ *
+ * Support for 1-complement arithmetic has been totally dropped in this
+ * release. You can still write your own code if you need it.
+ *
+ */
+
+ /**************************************************************************
+ *
+ * Implementing basic computation routines.
+ *
+ * FT_MulDiv(), FT_MulFix(), FT_DivFix(), FT_RoundFix(), FT_CeilFix(),
+ * and FT_FloorFix() are declared in freetype.h.
+ *
+ */
#include <ft2build.h>
@@ -58,14 +58,14 @@
#endif /* !FT_LONG64 */
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_calc
+#define FT_COMPONENT calc
/* transfer sign, leaving a positive number; */
@@ -516,10 +516,10 @@
#elif 0
/*
- * This code is nonportable. See comment below.
+ * This code is nonportable. See comment below.
*
- * However, on a platform where right-shift of a signed quantity fills
- * the leftmost bits by copying the sign bit, it might be faster.
+ * However, on a platform where right-shift of a signed quantity fills
+ * the leftmost bits by copying the sign bit, it might be faster.
*/
FT_Long sa, sb;
@@ -527,22 +527,22 @@
/*
- * This is a clever way of converting a signed number `a' into its
- * absolute value (stored back into `a') and its sign. The sign is
- * stored in `sa'; 0 means `a' was positive or zero, and -1 means `a'
- * was negative. (Similarly for `b' and `sb').
+ * This is a clever way of converting a signed number `a' into its
+ * absolute value (stored back into `a') and its sign. The sign is
+ * stored in `sa'; 0 means `a' was positive or zero, and -1 means `a'
+ * was negative. (Similarly for `b' and `sb').
*
- * Unfortunately, it doesn't work (at least not portably).
+ * Unfortunately, it doesn't work (at least not portably).
*
- * It makes the assumption that right-shift on a negative signed value
- * fills the leftmost bits by copying the sign bit. This is wrong.
- * According to K&R 2nd ed, section `A7.8 Shift Operators' on page 206,
- * the result of right-shift of a negative signed value is
- * implementation-defined. At least one implementation fills the
- * leftmost bits with 0s (i.e., it is exactly the same as an unsigned
- * right shift). This means that when `a' is negative, `sa' ends up
- * with the value 1 rather than -1. After that, everything else goes
- * wrong.
+ * It makes the assumption that right-shift on a negative signed value
+ * fills the leftmost bits by copying the sign bit. This is wrong.
+ * According to K&R 2nd ed, section `A7.8 Shift Operators' on page 206,
+ * the result of right-shift of a negative signed value is
+ * implementation-defined. At least one implementation fills the
+ * leftmost bits with 0s (i.e., it is exactly the same as an unsigned
+ * right shift). This means that when `a' is negative, `sa' ends up
+ * with the value 1 rather than -1. After that, everything else goes
+ * wrong.
*/
sa = ( a_ >> ( sizeof ( a_ ) * 8 - 1 ) );
a = ( a_ ^ sa ) - sa;
@@ -701,8 +701,8 @@
if ( !delta )
return FT_THROW( Invalid_Argument ); /* matrix can't be inverted */
- matrix->xy = - FT_DivFix( matrix->xy, delta );
- matrix->yx = - FT_DivFix( matrix->yx, delta );
+ matrix->xy = -FT_DivFix( matrix->xy, delta );
+ matrix->yx = -FT_DivFix( matrix->yx, delta );
xx = matrix->xx;
yy = matrix->yy;
@@ -747,6 +747,76 @@
/* documentation is in ftcalc.h */
+ FT_BASE_DEF( FT_Bool )
+ FT_Matrix_Check( const FT_Matrix* matrix )
+ {
+ FT_Matrix m;
+ FT_Fixed val[4];
+ FT_Fixed nonzero_minval, maxval;
+ FT_Fixed temp1, temp2;
+ FT_UInt i;
+
+
+ if ( !matrix )
+ return 0;
+
+ val[0] = FT_ABS( matrix->xx );
+ val[1] = FT_ABS( matrix->xy );
+ val[2] = FT_ABS( matrix->yx );
+ val[3] = FT_ABS( matrix->yy );
+
+ /*
+ * To avoid overflow, we ensure that each value is not larger than
+ *
+ * int(sqrt(2^31 / 4)) = 23170 ;
+ *
+ * we also check that no value becomes zero if we have to scale.
+ */
+
+ maxval = 0;
+ nonzero_minval = FT_LONG_MAX;
+
+ for ( i = 0; i < 4; i++ )
+ {
+ if ( val[i] > maxval )
+ maxval = val[i];
+ if ( val[i] && val[i] < nonzero_minval )
+ nonzero_minval = val[i];
+ }
+
+ /* we only handle 32bit values */
+ if ( maxval > 0x7FFFFFFFL )
+ return 0;
+
+ if ( maxval > 23170 )
+ {
+ FT_Fixed scale = FT_DivFix( maxval, 23170 );
+
+
+ if ( !FT_DivFix( nonzero_minval, scale ) )
+ return 0; /* value range too large */
+
+ m.xx = FT_DivFix( matrix->xx, scale );
+ m.xy = FT_DivFix( matrix->xy, scale );
+ m.yx = FT_DivFix( matrix->yx, scale );
+ m.yy = FT_DivFix( matrix->yy, scale );
+ }
+ else
+ m = *matrix;
+
+ temp1 = FT_ABS( m.xx * m.yy - m.xy * m.yx );
+ temp2 = m.xx * m.xx + m.xy * m.xy + m.yx * m.yx + m.yy * m.yy;
+
+ if ( temp1 == 0 ||
+ temp2 / temp1 > 50 )
+ return 0;
+
+ return 1;
+ }
+
+
+ /* documentation is in ftcalc.h */
+
FT_BASE_DEF( void )
FT_Vector_Transform_Scaled( FT_Vector* vector,
const FT_Matrix* matrix,
@@ -913,9 +983,13 @@
FT_Pos out_x,
FT_Pos out_y )
{
+ /* we silently ignore overflow errors since such large values */
+ /* lead to even more (harmless) rendering errors later on */
+
#ifdef FT_LONG64
- FT_Int64 delta = (FT_Int64)in_x * out_y - (FT_Int64)in_y * out_x;
+ FT_Int64 delta = SUB_INT64( MUL_INT64( in_x, out_y ),
+ MUL_INT64( in_y, out_x ) );
return ( delta > 0 ) - ( delta < 0 );
@@ -925,8 +999,6 @@
FT_Int result;
- /* we silently ignore overflow errors, since such large values */
- /* lead to even more (harmless) rendering errors later on */
if ( ADD_LONG( FT_ABS( in_x ), FT_ABS( out_y ) ) <= 131071L &&
ADD_LONG( FT_ABS( in_y ), FT_ABS( out_x ) ) <= 131071L )
{
diff --git a/thirdparty/freetype/src/base/ftcid.c b/thirdparty/freetype/src/base/ftcid.c
index f5184649bf..190b23f357 100644
--- a/thirdparty/freetype/src/base/ftcid.c
+++ b/thirdparty/freetype/src/base/ftcid.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftcid.c */
-/* */
-/* FreeType API for accessing CID font information. */
-/* */
-/* Copyright 2007-2018 by */
-/* Derek Clegg and Michael Toftdal. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftcid.c
+ *
+ * FreeType API for accessing CID font information.
+ *
+ * Copyright (C) 2007-2019 by
+ * Derek Clegg and Michael Toftdal.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
diff --git a/thirdparty/freetype/src/base/ftcolor.c b/thirdparty/freetype/src/base/ftcolor.c
new file mode 100644
index 0000000000..8cb057a365
--- /dev/null
+++ b/thirdparty/freetype/src/base/ftcolor.c
@@ -0,0 +1,157 @@
+/****************************************************************************
+ *
+ * ftcolor.c
+ *
+ * FreeType's glyph color management (body).
+ *
+ * Copyright (C) 2018-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_SFNT_H
+#include FT_INTERNAL_TRUETYPE_TYPES_H
+#include FT_COLOR_H
+
+
+#ifdef TT_CONFIG_OPTION_COLOR_LAYERS
+
+ static
+ const FT_Palette_Data null_palette_data = { 0, NULL, NULL, 0, NULL };
+
+
+ /* documentation is in ftcolor.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Palette_Data_Get( FT_Face face,
+ FT_Palette_Data *apalette_data )
+ {
+ if ( !face )
+ return FT_THROW( Invalid_Face_Handle );
+ if ( !apalette_data)
+ return FT_THROW( Invalid_Argument );
+
+ if ( FT_IS_SFNT( face ) )
+ *apalette_data = ( (TT_Face)face )->palette_data;
+ else
+ *apalette_data = null_palette_data;
+
+ return FT_Err_Ok;
+ }
+
+
+ /* documentation is in ftcolor.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Palette_Select( FT_Face face,
+ FT_UShort palette_index,
+ FT_Color* *apalette )
+ {
+ FT_Error error;
+
+ TT_Face ttface;
+ SFNT_Service sfnt;
+
+
+ if ( !face )
+ return FT_THROW( Invalid_Face_Handle );
+
+ if ( !FT_IS_SFNT( face ) )
+ {
+ if ( apalette )
+ *apalette = NULL;
+
+ return FT_Err_Ok;
+ }
+
+ ttface = (TT_Face)face;
+ sfnt = (SFNT_Service)ttface->sfnt;
+
+ error = sfnt->set_palette( ttface, palette_index );
+ if ( error )
+ return error;
+
+ ttface->palette_index = palette_index;
+
+ if ( apalette )
+ *apalette = ttface->palette;
+
+ return FT_Err_Ok;
+ }
+
+
+ /* documentation is in ftcolor.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Palette_Set_Foreground_Color( FT_Face face,
+ FT_Color foreground_color )
+ {
+ TT_Face ttface;
+
+
+ if ( !face )
+ return FT_THROW( Invalid_Face_Handle );
+
+ if ( !FT_IS_SFNT( face ) )
+ return FT_Err_Ok;
+
+ ttface = (TT_Face)face;
+
+ ttface->foreground_color = foreground_color;
+ ttface->have_foreground_color = 1;
+
+ return FT_Err_Ok;
+ }
+
+#else /* !TT_CONFIG_OPTION_COLOR_LAYERS */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Palette_Data_Get( FT_Face face,
+ FT_Palette_Data *apalette_data )
+ {
+ FT_UNUSED( face );
+ FT_UNUSED( apalette_data );
+
+
+ return FT_THROW( Unimplemented_Feature );
+ }
+
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Palette_Select( FT_Face face,
+ FT_UShort palette_index,
+ FT_Color* *apalette )
+ {
+ FT_UNUSED( face );
+ FT_UNUSED( palette_index );
+ FT_UNUSED( apalette );
+
+
+ return FT_THROW( Unimplemented_Feature );
+ }
+
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Palette_Set_Foreground_Color( FT_Face face,
+ FT_Color foreground_color )
+ {
+ FT_UNUSED( face );
+ FT_UNUSED( foreground_color );
+
+
+ return FT_THROW( Unimplemented_Feature );
+ }
+
+#endif /* !TT_CONFIG_OPTION_COLOR_LAYERS */
+
+
+/* END */
diff --git a/thirdparty/freetype/src/base/ftdbgmem.c b/thirdparty/freetype/src/base/ftdbgmem.c
index c33d8acb4e..55cd269e1f 100644
--- a/thirdparty/freetype/src/base/ftdbgmem.c
+++ b/thirdparty/freetype/src/base/ftdbgmem.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftdbgmem.c */
-/* */
-/* Memory debugger (body). */
-/* */
-/* Copyright 2001-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftdbgmem.c
+ *
+ * Memory debugger (body).
+ *
+ * Copyright (C) 2001-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -50,9 +50,9 @@
#define FT_MEM_VAL( addr ) ( (FT_PtrDist)(FT_Pointer)( addr ) )
/*
- * This structure holds statistics for a single allocation/release
- * site. This is useful to know where memory operations happen the
- * most.
+ * This structure holds statistics for a single allocation/release
+ * site. This is useful to know where memory operations happen the
+ * most.
*/
typedef struct FT_MemSourceRec_
{
@@ -76,17 +76,17 @@
/*
- * We don't need a resizable array for the memory sources because
- * their number is pretty limited within FreeType.
+ * We don't need a resizable array for the memory sources because
+ * their number is pretty limited within FreeType.
*/
#define FT_MEM_SOURCE_BUCKETS 128
/*
- * This structure holds information related to a single allocated
- * memory block. If KEEPALIVE is defined, blocks that are freed by
- * FreeType are never released to the system. Instead, their `size'
- * field is set to `-size'. This is mainly useful to detect double
- * frees, at the price of a large memory footprint during execution.
+ * This structure holds information related to a single allocated
+ * memory block. If KEEPALIVE is defined, blocks that are freed by
+ * FreeType are never released to the system. Instead, their `size'
+ * field is set to `-size'. This is mainly useful to detect double
+ * frees, at the price of a large memory footprint during execution.
*/
typedef struct FT_MemNodeRec_
{
@@ -106,8 +106,8 @@
/*
- * The global structure, containing compound statistics and all hash
- * tables.
+ * The global structure, containing compound statistics and all hash
+ * tables.
*/
typedef struct FT_MemTableRec_
{
@@ -146,8 +146,8 @@
/*
- * Prime numbers are ugly to handle. It would be better to implement
- * L-Hashing, which is 10% faster and doesn't require divisions.
+ * Prime numbers are ugly to handle. It would be better to implement
+ * L-Hashing, which is 10% faster and doesn't require divisions.
*/
static const FT_Int ft_mem_primes[] =
{
diff --git a/thirdparty/freetype/src/base/ftdebug.c b/thirdparty/freetype/src/base/ftdebug.c
index fe26309101..ec72337873 100644
--- a/thirdparty/freetype/src/base/ftdebug.c
+++ b/thirdparty/freetype/src/base/ftdebug.c
@@ -1,44 +1,44 @@
-/***************************************************************************/
-/* */
-/* ftdebug.c */
-/* */
-/* Debugging and logging component (body). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* This component contains various macros and functions used to ease the */
- /* debugging of the FreeType engine. Its main purpose is in assertion */
- /* checking, tracing, and error detection. */
- /* */
- /* There are now three debugging modes: */
- /* */
- /* - trace mode */
- /* */
- /* Error and trace messages are sent to the log file (which can be the */
- /* standard error output). */
- /* */
- /* - error mode */
- /* */
- /* Only error messages are generated. */
- /* */
- /* - release mode: */
- /* */
- /* No error message is sent or generated. The code is free from any */
- /* debugging parts. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * ftdebug.c
+ *
+ * Debugging and logging component (body).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * This component contains various macros and functions used to ease the
+ * debugging of the FreeType engine. Its main purpose is in assertion
+ * checking, tracing, and error detection.
+ *
+ * There are now three debugging modes:
+ *
+ * - trace mode
+ *
+ * Error and trace messages are sent to the log file (which can be the
+ * standard error output).
+ *
+ * - error mode
+ *
+ * Only error messages are generated.
+ *
+ * - release mode:
+ *
+ * No error message is sent or generated. The code is free from any
+ * debugging parts.
+ *
+ */
#include <ft2build.h>
@@ -87,9 +87,19 @@
int line,
const char* file )
{
+#if 0
+ /* activating the code in this block makes FreeType very chatty */
+ fprintf( stderr,
+ "%s:%d: error 0x%02x: %s\n",
+ file,
+ line,
+ error,
+ FT_Error_String( error ) );
+#else
FT_UNUSED( error );
FT_UNUSED( line );
FT_UNUSED( file );
+#endif
return 0;
}
@@ -100,9 +110,16 @@
#ifdef FT_DEBUG_LEVEL_TRACE
- /* array of trace levels, initialized to 0 */
- int ft_trace_levels[trace_count];
+ /* array of trace levels, initialized to 0; */
+ /* this gets adjusted at run-time */
+ static int ft_trace_levels_enabled[trace_count];
+ /* array of trace levels, always initialized to 0 */
+ static int ft_trace_levels_disabled[trace_count];
+
+ /* a pointer to either `ft_trace_levels_enabled' */
+ /* or `ft_trace_levels_disabled' */
+ int* ft_trace_levels;
/* define array of trace toggle names */
#define FT_TRACE_DEF( x ) #x ,
@@ -140,24 +157,42 @@
}
- /*************************************************************************/
- /* */
- /* Initialize the tracing sub-system. This is done by retrieving the */
- /* value of the `FT2_DEBUG' environment variable. It must be a list of */
- /* toggles, separated by spaces, `;', or `,'. Example: */
- /* */
- /* export FT2_DEBUG="any:3 memory:7 stream:5" */
- /* */
- /* This requests that all levels be set to 3, except the trace level for */
- /* the memory and stream components which are set to 7 and 5, */
- /* respectively. */
- /* */
- /* See the file `include/freetype/internal/fttrace.h' for details of */
- /* the available toggle names. */
- /* */
- /* The level must be between 0 and 7; 0 means quiet (except for serious */
- /* runtime errors), and 7 means _very_ verbose. */
- /* */
+ /* documentation is in ftdebug.h */
+
+ FT_BASE_DEF( void )
+ FT_Trace_Disable( void )
+ {
+ ft_trace_levels = ft_trace_levels_disabled;
+ }
+
+
+ /* documentation is in ftdebug.h */
+
+ FT_BASE_DEF( void )
+ FT_Trace_Enable( void )
+ {
+ ft_trace_levels = ft_trace_levels_enabled;
+ }
+
+
+ /**************************************************************************
+ *
+ * Initialize the tracing sub-system. This is done by retrieving the
+ * value of the `FT2_DEBUG' environment variable. It must be a list of
+ * toggles, separated by spaces, `;', or `,'. Example:
+ *
+ * export FT2_DEBUG="any:3 memory:7 stream:5"
+ *
+ * This requests that all levels be set to 3, except the trace level for
+ * the memory and stream components which are set to 7 and 5,
+ * respectively.
+ *
+ * See the file `include/freetype/internal/fttrace.h' for details of
+ * the available toggle names.
+ *
+ * The level must be between 0 and 7; 0 means quiet (except for serious
+ * runtime errors), and 7 means _very_ verbose.
+ */
FT_BASE_DEF( void )
ft_debug_init( void )
{
@@ -223,14 +258,16 @@
{
/* special case for `any' */
for ( n = 0; n < trace_count; n++ )
- ft_trace_levels[n] = level;
+ ft_trace_levels_enabled[n] = level;
}
else
- ft_trace_levels[found] = level;
+ ft_trace_levels_enabled[found] = level;
}
}
}
}
+
+ ft_trace_levels = ft_trace_levels_enabled;
}
@@ -260,6 +297,22 @@
}
+ FT_BASE_DEF( void )
+ FT_Trace_Disable( void )
+ {
+ /* nothing */
+ }
+
+
+ /* documentation is in ftdebug.h */
+
+ FT_BASE_DEF( void )
+ FT_Trace_Enable( void )
+ {
+ /* nothing */
+ }
+
+
#endif /* !FT_DEBUG_LEVEL_TRACE */
diff --git a/thirdparty/freetype/src/base/fterrors.c b/thirdparty/freetype/src/base/fterrors.c
new file mode 100644
index 0000000000..4ef326d8e2
--- /dev/null
+++ b/thirdparty/freetype/src/base/fterrors.c
@@ -0,0 +1,45 @@
+/****************************************************************************
+ *
+ * fterrors.c
+ *
+ * FreeType API for error code handling.
+ *
+ * Copyright (C) 2018-2019 by
+ * Armin Hasitzka, David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#include <ft2build.h>
+#include FT_ERRORS_H
+
+
+ /* documentation is in fterrors.h */
+
+ FT_EXPORT_DEF( const char* )
+ FT_Error_String( FT_Error error_code )
+ {
+ if ( error_code < 0 ||
+ error_code >= FT_ERR_CAT( FT_ERR_PREFIX, Max ) )
+ return NULL;
+
+#if defined( FT_CONFIG_OPTION_ERROR_STRINGS ) || \
+ defined( FT_DEBUG_LEVEL_ERROR )
+
+#undef FTERRORS_H_
+#define FT_ERROR_START_LIST switch ( FT_ERROR_BASE( error_code ) ) {
+#define FT_ERRORDEF( e, v, s ) case v: return s;
+#define FT_ERROR_END_LIST }
+
+#include FT_ERRORS_H
+
+#endif /* defined( FT_CONFIG_OPTION_ERROR_STRINGS ) || ... */
+
+ return NULL;
+ }
diff --git a/thirdparty/freetype/src/base/ftfntfmt.c b/thirdparty/freetype/src/base/ftfntfmt.c
index a2900ceb09..54ba537416 100644
--- a/thirdparty/freetype/src/base/ftfntfmt.c
+++ b/thirdparty/freetype/src/base/ftfntfmt.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftfntfmt.c */
-/* */
-/* FreeType utility file for font formats (body). */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftfntfmt.c
+ *
+ * FreeType utility file for font formats (body).
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
diff --git a/thirdparty/freetype/src/base/ftfstype.c b/thirdparty/freetype/src/base/ftfstype.c
index e6cdf6e2ec..45e2d8089b 100644
--- a/thirdparty/freetype/src/base/ftfstype.c
+++ b/thirdparty/freetype/src/base/ftfstype.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftfstype.c */
-/* */
-/* FreeType utility file to access FSType data (body). */
-/* */
-/* Copyright 2008-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftfstype.c
+ *
+ * FreeType utility file to access FSType data (body).
+ *
+ * Copyright (C) 2008-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
#include FT_TYPE1_TABLES_H
diff --git a/thirdparty/freetype/src/base/ftgasp.c b/thirdparty/freetype/src/base/ftgasp.c
index 4f80bba630..720fb113ca 100644
--- a/thirdparty/freetype/src/base/ftgasp.c
+++ b/thirdparty/freetype/src/base/ftgasp.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftgasp.c */
-/* */
-/* Access of TrueType's `gasp' table (body). */
-/* */
-/* Copyright 2007-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftgasp.c
+ *
+ * Access of TrueType's `gasp' table (body).
+ *
+ * Copyright (C) 2007-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
diff --git a/thirdparty/freetype/src/base/ftgloadr.c b/thirdparty/freetype/src/base/ftgloadr.c
index 47202496b9..bfeed461a8 100644
--- a/thirdparty/freetype/src/base/ftgloadr.c
+++ b/thirdparty/freetype/src/base/ftgloadr.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftgloadr.c */
-/* */
-/* The FreeType glyph loader (body). */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftgloadr.c
+ *
+ * The FreeType glyph loader (body).
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -23,7 +23,7 @@
#include FT_INTERNAL_OBJECTS_H
#undef FT_COMPONENT
-#define FT_COMPONENT trace_gloader
+#define FT_COMPONENT gloader
/*************************************************************************/
@@ -38,31 +38,31 @@
/*************************************************************************/
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* The glyph loader is a simple object which is used to load a set of */
- /* glyphs easily. It is critical for the correct loading of composites. */
- /* */
- /* Ideally, one can see it as a stack of abstract `glyph' objects. */
- /* */
- /* loader.base Is really the bottom of the stack. It describes a */
- /* single glyph image made of the juxtaposition of */
- /* several glyphs (those `in the stack'). */
- /* */
- /* loader.current Describes the top of the stack, on which a new */
- /* glyph can be loaded. */
- /* */
- /* Rewind Clears the stack. */
- /* Prepare Set up `loader.current' for addition of a new glyph */
- /* image. */
- /* Add Add the `current' glyph image to the `base' one, */
- /* and prepare for another one. */
- /* */
- /* The glyph loader is now a base object. Each driver used to */
- /* re-implement it in one way or the other, which wasted code and */
- /* energy. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * The glyph loader is a simple object which is used to load a set of
+ * glyphs easily. It is critical for the correct loading of composites.
+ *
+ * Ideally, one can see it as a stack of abstract `glyph' objects.
+ *
+ * loader.base Is really the bottom of the stack. It describes a
+ * single glyph image made of the juxtaposition of
+ * several glyphs (those `in the stack').
+ *
+ * loader.current Describes the top of the stack, on which a new
+ * glyph can be loaded.
+ *
+ * Rewind Clears the stack.
+ * Prepare Set up `loader.current' for addition of a new glyph
+ * image.
+ * Add Add the `current' glyph image to the `base' one,
+ * and prepare for another one.
+ *
+ * The glyph loader is now a base object. Each driver used to
+ * re-implement it in one way or the other, which wasted code and
+ * energy.
+ *
+ */
/* create a new glyph loader */
@@ -99,12 +99,12 @@
}
- /* reset the glyph loader, frees all allocated tables */
- /* and starts from zero */
+ /* reset glyph loader, free all allocated tables, */
+ /* and start from zero */
FT_BASE_DEF( void )
FT_GlyphLoader_Reset( FT_GlyphLoader loader )
{
- FT_Memory memory = loader->memory;
+ FT_Memory memory = loader->memory;
FT_FREE( loader->base.outline.points );
@@ -129,7 +129,7 @@
{
if ( loader )
{
- FT_Memory memory = loader->memory;
+ FT_Memory memory = loader->memory;
FT_GlyphLoader_Reset( loader );
@@ -361,46 +361,4 @@
}
- FT_BASE_DEF( FT_Error )
- FT_GlyphLoader_CopyPoints( FT_GlyphLoader target,
- FT_GlyphLoader source )
- {
- FT_Error error;
- FT_UInt num_points = (FT_UInt)source->base.outline.n_points;
- FT_UInt num_contours = (FT_UInt)source->base.outline.n_contours;
-
-
- error = FT_GlyphLoader_CheckPoints( target, num_points, num_contours );
- if ( !error )
- {
- FT_Outline* out = &target->base.outline;
- FT_Outline* in = &source->base.outline;
-
-
- FT_ARRAY_COPY( out->points, in->points,
- num_points );
- FT_ARRAY_COPY( out->tags, in->tags,
- num_points );
- FT_ARRAY_COPY( out->contours, in->contours,
- num_contours );
-
- /* do we need to copy the extra points? */
- if ( target->use_extra && source->use_extra )
- {
- FT_ARRAY_COPY( target->base.extra_points, source->base.extra_points,
- num_points );
- FT_ARRAY_COPY( target->base.extra_points2, source->base.extra_points2,
- num_points );
- }
-
- out->n_points = (short)num_points;
- out->n_contours = (short)num_contours;
-
- FT_GlyphLoader_Adjust_Points( target );
- }
-
- return error;
- }
-
-
/* END */
diff --git a/thirdparty/freetype/src/base/ftglyph.c b/thirdparty/freetype/src/base/ftglyph.c
index 6759aa25d0..e6b1327901 100644
--- a/thirdparty/freetype/src/base/ftglyph.c
+++ b/thirdparty/freetype/src/base/ftglyph.c
@@ -1,31 +1,31 @@
-/***************************************************************************/
-/* */
-/* ftglyph.c */
-/* */
-/* FreeType convenience functions to handle glyphs (body). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
- /*************************************************************************/
- /* */
- /* This file contains the definition of several convenience functions */
- /* that can be used by client applications to easily retrieve glyph */
- /* bitmaps and outlines from a given face. */
- /* */
- /* These functions should be optional if you are writing a font server */
- /* or text layout engine on top of FreeType. However, they are pretty */
- /* handy for many other simple uses of the library. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * ftglyph.c
+ *
+ * FreeType convenience functions to handle glyphs (body).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+ /**************************************************************************
+ *
+ * This file contains the definition of several convenience functions
+ * that can be used by client applications to easily retrieve glyph
+ * bitmaps and outlines from a given face.
+ *
+ * These functions should be optional if you are writing a font server
+ * or text layout engine on top of FreeType. However, they are pretty
+ * handy for many other simple uses of the library.
+ *
+ */
#include <ft2build.h>
@@ -36,16 +36,15 @@
#include FT_BITMAP_H
#include FT_INTERNAL_OBJECTS_H
-#include "basepic.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_glyph
+#define FT_COMPONENT glyph
/*************************************************************************/
@@ -77,7 +76,7 @@
/* do lazy copying whenever possible */
if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
{
- glyph->bitmap = slot->bitmap;
+ glyph->bitmap = slot->bitmap;
slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
}
else
@@ -359,37 +358,28 @@
/* documentation is in ftglyph.h */
- FT_EXPORT_DEF( FT_Error )
- FT_Get_Glyph( FT_GlyphSlot slot,
- FT_Glyph *aglyph )
+ FT_EXPORT( FT_Error )
+ FT_New_Glyph( FT_Library library,
+ FT_Glyph_Format format,
+ FT_Glyph *aglyph )
{
- FT_Library library;
- FT_Error error;
- FT_Glyph glyph;
-
const FT_Glyph_Class* clazz = NULL;
-
- if ( !slot )
- return FT_THROW( Invalid_Slot_Handle );
-
- library = slot->library;
-
- if ( !aglyph )
+ if ( !library || !aglyph )
return FT_THROW( Invalid_Argument );
/* if it is a bitmap, that's easy :-) */
- if ( slot->format == FT_GLYPH_FORMAT_BITMAP )
- clazz = FT_BITMAP_GLYPH_CLASS_GET;
+ if ( format == FT_GLYPH_FORMAT_BITMAP )
+ clazz = &ft_bitmap_glyph_class;
/* if it is an outline */
- else if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
- clazz = FT_OUTLINE_GLYPH_CLASS_GET;
+ else if ( format == FT_GLYPH_FORMAT_OUTLINE )
+ clazz = &ft_outline_glyph_class;
else
{
/* try to find a renderer that supports the glyph image format */
- FT_Renderer render = FT_Lookup_Renderer( library, slot->format, 0 );
+ FT_Renderer render = FT_Lookup_Renderer( library, format, 0 );
if ( render )
@@ -397,13 +387,31 @@
}
if ( !clazz )
- {
- error = FT_THROW( Invalid_Glyph_Format );
- goto Exit;
- }
+ return FT_THROW( Invalid_Glyph_Format );
+
+ /* create FT_Glyph object */
+ return ft_new_glyph( library, clazz, aglyph );
+ }
+
+
+ /* documentation is in ftglyph.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Get_Glyph( FT_GlyphSlot slot,
+ FT_Glyph *aglyph )
+ {
+ FT_Error error;
+ FT_Glyph glyph;
+
+
+ if ( !slot )
+ return FT_THROW( Invalid_Slot_Handle );
+
+ if ( !aglyph )
+ return FT_THROW( Invalid_Argument );
/* create FT_Glyph object */
- error = ft_new_glyph( library, clazz, &glyph );
+ error = FT_New_Glyph( slot->library, slot->format, &glyph );
if ( error )
goto Exit;
@@ -427,7 +435,7 @@
glyph->advance.y = slot->advance.y * 1024;
/* now import the image from the glyph slot */
- error = clazz->glyph_init( glyph, slot );
+ error = glyph->clazz->glyph_init( glyph, slot );
Exit2:
/* if an error occurred, destroy the glyph */
@@ -505,8 +513,8 @@
{
acbox->xMin = FT_PIX_FLOOR( acbox->xMin );
acbox->yMin = FT_PIX_FLOOR( acbox->yMin );
- acbox->xMax = FT_PIX_CEIL( acbox->xMax );
- acbox->yMax = FT_PIX_CEIL( acbox->yMax );
+ acbox->xMax = FT_PIX_CEIL_LONG( acbox->xMax );
+ acbox->yMax = FT_PIX_CEIL_LONG( acbox->yMax );
}
/* convert to integer pixels if needed */
@@ -536,7 +544,6 @@
FT_BitmapGlyph bitmap = NULL;
const FT_Glyph_Class* clazz;
- /* FT_BITMAP_GLYPH_CLASS_GET dereferences `library' in PIC mode */
FT_Library library;
@@ -553,7 +560,7 @@
goto Bad;
/* when called with a bitmap glyph, do nothing and return successfully */
- if ( clazz == FT_BITMAP_GLYPH_CLASS_GET )
+ if ( clazz == &ft_bitmap_glyph_class )
goto Exit;
if ( !clazz->glyph_prepare )
@@ -569,7 +576,7 @@
dummy.format = clazz->glyph_format;
/* create result bitmap glyph */
- error = ft_new_glyph( library, FT_BITMAP_GLYPH_CLASS_GET, &b );
+ error = ft_new_glyph( library, &ft_bitmap_glyph_class, &b );
if ( error )
goto Exit;
bitmap = (FT_BitmapGlyph)b;
diff --git a/thirdparty/freetype/src/base/ftgxval.c b/thirdparty/freetype/src/base/ftgxval.c
index 19e2d6acb5..0677d26faa 100644
--- a/thirdparty/freetype/src/base/ftgxval.c
+++ b/thirdparty/freetype/src/base/ftgxval.c
@@ -1,28 +1,28 @@
-/***************************************************************************/
-/* */
-/* ftgxval.c */
-/* */
-/* FreeType API for validating TrueTypeGX/AAT tables (body). */
-/* */
-/* Copyright 2004-2018 by */
-/* Masatake YAMATO, Redhat K.K, */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-/***************************************************************************/
-/* */
-/* gxvalid is derived from both gxlayout module and otvalid module. */
-/* Development of gxlayout is supported by the Information-technology */
-/* Promotion Agency(IPA), Japan. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftgxval.c
+ *
+ * FreeType API for validating TrueTypeGX/AAT tables (body).
+ *
+ * Copyright (C) 2004-2019 by
+ * Masatake YAMATO, Redhat K.K,
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+/****************************************************************************
+ *
+ * gxvalid is derived from both gxlayout module and otvalid module.
+ * Development of gxlayout is supported by the Information-technology
+ * Promotion Agency(IPA), Japan.
+ *
+ */
#include <ft2build.h>
diff --git a/thirdparty/freetype/src/base/fthash.c b/thirdparty/freetype/src/base/fthash.c
index 21bc8dd5b4..387e6d26db 100644
--- a/thirdparty/freetype/src/base/fthash.c
+++ b/thirdparty/freetype/src/base/fthash.c
@@ -1,10 +1,10 @@
-/***************************************************************************/
-/* */
-/* fthash.c */
-/* */
-/* Hashing functions (body). */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * fthash.c
+ *
+ * Hashing functions (body).
+ *
+ */
/*
* Copyright 2000 Computing Research Labs, New Mexico State University
@@ -30,13 +30,13 @@
* THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
- /*************************************************************************/
- /* */
- /* This file is based on code from bdf.c,v 1.22 2000/03/16 20:08:50 */
- /* */
- /* taken from Mark Leisher's xmbdfed package */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * This file is based on code from bdf.c,v 1.22 2000/03/16 20:08:50
+ *
+ * taken from Mark Leisher's xmbdfed package
+ *
+ */
#include <ft2build.h>
diff --git a/thirdparty/freetype/src/base/ftinit.c b/thirdparty/freetype/src/base/ftinit.c
index 1fa4721094..9d524effa9 100644
--- a/thirdparty/freetype/src/base/ftinit.c
+++ b/thirdparty/freetype/src/base/ftinit.c
@@ -1,40 +1,40 @@
-/***************************************************************************/
-/* */
-/* ftinit.c */
-/* */
-/* FreeType initialization layer (body). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
- /*************************************************************************/
- /* */
- /* The purpose of this file is to implement the following two */
- /* functions: */
- /* */
- /* FT_Add_Default_Modules(): */
- /* This function is used to add the set of default modules to a */
- /* fresh new library object. The set is taken from the header file */
- /* `freetype/config/ftmodule.h'. See the document `FreeType 2.0 */
- /* Build System' for more information. */
- /* */
- /* FT_Init_FreeType(): */
- /* This function creates a system object for the current platform, */
- /* builds a library out of it, then calls FT_Default_Drivers(). */
- /* */
- /* Note that even if FT_Init_FreeType() uses the implementation of the */
- /* system object defined at build time, client applications are still */
- /* able to provide their own `ftsystem.c'. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * ftinit.c
+ *
+ * FreeType initialization layer (body).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+ /**************************************************************************
+ *
+ * The purpose of this file is to implement the following two
+ * functions:
+ *
+ * FT_Add_Default_Modules():
+ * This function is used to add the set of default modules to a
+ * fresh new library object. The set is taken from the header file
+ * `freetype/config/ftmodule.h'. See the document `FreeType 2.0
+ * Build System' for more information.
+ *
+ * FT_Init_FreeType():
+ * This function creates a system object for the current platform,
+ * builds a library out of it, then calls FT_Default_Drivers().
+ *
+ * Note that even if FT_Init_FreeType() uses the implementation of the
+ * system object defined at build time, client applications are still
+ * able to provide their own `ftsystem.c'.
+ *
+ */
#include <ft2build.h>
@@ -42,20 +42,16 @@
#include FT_INTERNAL_OBJECTS_H
#include FT_INTERNAL_DEBUG_H
#include FT_MODULE_H
-#include "basepic.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_init
-
-
-#ifndef FT_CONFIG_OPTION_PIC
+#define FT_COMPONENT init
#undef FT_USE_MODULE
@@ -78,120 +74,6 @@
};
-#else /* FT_CONFIG_OPTION_PIC */
-
-
-#ifdef __cplusplus
-#define FT_EXTERNC extern "C"
-#else
-#define FT_EXTERNC extern
-#endif
-
- /* declare the module's class creation/destruction functions */
-#undef FT_USE_MODULE
-#define FT_USE_MODULE( type, x ) \
- FT_EXTERNC FT_Error \
- FT_Create_Class_ ## x( FT_Library library, \
- FT_Module_Class* *output_class ); \
- FT_EXTERNC void \
- FT_Destroy_Class_ ## x( FT_Library library, \
- FT_Module_Class* clazz );
-
-#include FT_CONFIG_MODULES_H
-
- /* count all module classes */
-#undef FT_USE_MODULE
-#define FT_USE_MODULE( type, x ) MODULE_CLASS_ ## x,
-
- enum
- {
-#include FT_CONFIG_MODULES_H
- FT_NUM_MODULE_CLASSES
- };
-
- /* destroy all module classes */
-#undef FT_USE_MODULE
-#define FT_USE_MODULE( type, x ) \
- if ( classes[i] ) \
- { \
- FT_Destroy_Class_ ## x( library, classes[i] ); \
- } \
- i++;
-
-
- FT_BASE_DEF( void )
- ft_destroy_default_module_classes( FT_Library library )
- {
- FT_Module_Class* *classes;
- FT_Memory memory;
- FT_UInt i;
- BasePIC* pic_container = (BasePIC*)library->pic_container.base;
-
-
- if ( !pic_container->default_module_classes )
- return;
-
- memory = library->memory;
- classes = pic_container->default_module_classes;
- i = 0;
-
-#include FT_CONFIG_MODULES_H
-
- FT_FREE( classes );
- pic_container->default_module_classes = NULL;
- }
-
-
- /* initialize all module classes and the pointer table */
-#undef FT_USE_MODULE
-#define FT_USE_MODULE( type, x ) \
- error = FT_Create_Class_ ## x( library, &clazz ); \
- if ( error ) \
- goto Exit; \
- classes[i++] = clazz;
-
-
- FT_BASE_DEF( FT_Error )
- ft_create_default_module_classes( FT_Library library )
- {
- FT_Error error;
- FT_Memory memory;
- FT_Module_Class* *classes = NULL;
- FT_Module_Class* clazz;
- FT_UInt i;
- BasePIC* pic_container = (BasePIC*)library->pic_container.base;
-
-
- memory = library->memory;
-
- pic_container->default_module_classes = NULL;
-
- if ( FT_ALLOC( classes, sizeof ( FT_Module_Class* ) *
- ( FT_NUM_MODULE_CLASSES + 1 ) ) )
- return error;
-
- /* initialize all pointers to 0, especially the last one */
- for ( i = 0; i < FT_NUM_MODULE_CLASSES; i++ )
- classes[i] = NULL;
- classes[FT_NUM_MODULE_CLASSES] = NULL;
-
- i = 0;
-
-#include FT_CONFIG_MODULES_H
-
- Exit:
- if ( error )
- ft_destroy_default_module_classes( library );
- else
- pic_container->default_module_classes = classes;
-
- return error;
- }
-
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
-
/* documentation is in ftmodapi.h */
FT_EXPORT_DEF( void )
@@ -201,16 +83,10 @@
const FT_Module_Class* const* cur;
- /* FT_DEFAULT_MODULES_GET dereferences `library' in PIC mode */
-#ifdef FT_CONFIG_OPTION_PIC
- if ( !library )
- return;
-#endif
-
/* GCC 4.6 warns the type difference:
* FT_Module_Class** != const FT_Module_Class* const*
*/
- cur = (const FT_Module_Class* const*)FT_DEFAULT_MODULES_GET;
+ cur = (const FT_Module_Class* const*)ft_default_modules;
/* test for valid `library' delayed to FT_Add_Module() */
while ( *cur )
diff --git a/thirdparty/freetype/src/base/ftlcdfil.c b/thirdparty/freetype/src/base/ftlcdfil.c
index 8d314df080..9fb49ba116 100644
--- a/thirdparty/freetype/src/base/ftlcdfil.c
+++ b/thirdparty/freetype/src/base/ftlcdfil.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftlcdfil.c */
-/* */
-/* FreeType API for color filtering of subpixel bitmap glyphs (body). */
-/* */
-/* Copyright 2006-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftlcdfil.c
+ *
+ * FreeType API for color filtering of subpixel bitmap glyphs (body).
+ *
+ * Copyright (C) 2006-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -34,9 +34,9 @@
/* add padding according to filter weights */
FT_BASE_DEF (void)
- ft_lcd_padding( FT_Pos* Min,
- FT_Pos* Max,
- FT_GlyphSlot slot )
+ ft_lcd_padding( FT_BBox* cbox,
+ FT_GlyphSlot slot,
+ FT_Render_Mode mode )
{
FT_Byte* lcd_weights;
FT_Bitmap_LcdFilterFunc lcd_filter_func;
@@ -56,10 +56,20 @@
if ( lcd_filter_func == ft_lcd_filter_fir )
{
- *Min -= lcd_weights[0] ? 43 :
- lcd_weights[1] ? 22 : 0;
- *Max += lcd_weights[4] ? 43 :
- lcd_weights[3] ? 22 : 0;
+ if ( mode == FT_RENDER_MODE_LCD )
+ {
+ cbox->xMin -= lcd_weights[0] ? 43 :
+ lcd_weights[1] ? 22 : 0;
+ cbox->xMax += lcd_weights[4] ? 43 :
+ lcd_weights[3] ? 22 : 0;
+ }
+ else if ( mode == FT_RENDER_MODE_LCD_V )
+ {
+ cbox->yMin -= lcd_weights[0] ? 43 :
+ lcd_weights[1] ? 22 : 0;
+ cbox->yMax += lcd_weights[4] ? 43 :
+ lcd_weights[3] ? 22 : 0;
+ }
}
}
@@ -275,6 +285,8 @@
#endif /* USE_LEGACY */
+ /* documentation in ftlcdfil.h */
+
FT_EXPORT_DEF( FT_Error )
FT_Library_SetLcdFilterWeights( FT_Library library,
unsigned char *weights )
@@ -292,6 +304,8 @@
}
+ /* documentation in ftlcdfil.h */
+
FT_EXPORT_DEF( FT_Error )
FT_Library_SetLcdFilter( FT_Library library,
FT_LcdFilter filter )
@@ -341,18 +355,41 @@
return FT_Err_Ok;
}
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Library_SetLcdGeometry( FT_Library library,
+ FT_Vector* sub )
+ {
+ FT_UNUSED( library );
+ FT_UNUSED( sub );
+
+ return FT_THROW( Unimplemented_Feature );
+ }
+
#else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
- /* add padding according to accommodate outline shifts */
+ /* add padding to accommodate outline shifts */
FT_BASE_DEF (void)
- ft_lcd_padding( FT_Pos* Min,
- FT_Pos* Max,
- FT_GlyphSlot slot )
+ ft_lcd_padding( FT_BBox* cbox,
+ FT_GlyphSlot slot,
+ FT_Render_Mode mode )
{
- FT_UNUSED( slot );
+ FT_Vector* sub = slot->library->lcd_geometry;
- *Min -= 21;
- *Max += 21;
+ if ( mode == FT_RENDER_MODE_LCD )
+ {
+ cbox->xMin -= FT_MAX( FT_MAX( sub[0].x, sub[1].x ), sub[2].x );
+ cbox->xMax -= FT_MIN( FT_MIN( sub[0].x, sub[1].x ), sub[2].x );
+ cbox->yMin -= FT_MAX( FT_MAX( sub[0].y, sub[1].y ), sub[2].y );
+ cbox->yMax -= FT_MIN( FT_MIN( sub[0].y, sub[1].y ), sub[2].y );
+ }
+ else if ( mode == FT_RENDER_MODE_LCD_V )
+ {
+ cbox->xMin -= FT_MAX( FT_MAX( sub[0].y, sub[1].y ), sub[2].y );
+ cbox->xMax -= FT_MIN( FT_MIN( sub[0].y, sub[1].y ), sub[2].y );
+ cbox->yMin += FT_MIN( FT_MIN( sub[0].x, sub[1].x ), sub[2].x );
+ cbox->yMax += FT_MAX( FT_MAX( sub[0].x, sub[1].x ), sub[2].x );
+ }
}
@@ -377,6 +414,24 @@
return FT_THROW( Unimplemented_Feature );
}
+
+ /* documentation in ftlcdfil.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Library_SetLcdGeometry( FT_Library library,
+ FT_Vector sub[3] )
+ {
+ if ( !library )
+ return FT_THROW( Invalid_Library_Handle );
+
+ if ( !sub )
+ return FT_THROW( Invalid_Argument );
+
+ ft_memcpy( library->lcd_geometry, sub, 3 * sizeof( FT_Vector ) );
+
+ return FT_THROW( Unimplemented_Feature );
+ }
+
#endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
diff --git a/thirdparty/freetype/src/base/ftmac.c b/thirdparty/freetype/src/base/ftmac.c
index fd4c0cc274..5f23ceea9f 100644
--- a/thirdparty/freetype/src/base/ftmac.c
+++ b/thirdparty/freetype/src/base/ftmac.c
@@ -1,23 +1,23 @@
-/***************************************************************************/
-/* */
-/* ftmac.c */
-/* */
-/* Mac FOND support. Written by just@letterror.com. */
-/* Heavily modified by mpsuzuki, George Williams, and Sean McBride. */
-/* */
-/* This file is for Mac OS X only; see builds/mac/ftoldmac.c for */
-/* classic platforms built by MPW. */
-/* */
-/* Copyright 1996-2018 by */
-/* Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftmac.c
+ *
+ * Mac FOND support. Written by just@letterror.com.
+ * Heavily modified by mpsuzuki, George Williams, and Sean McBride.
+ *
+ * This file is for Mac OS X only; see builds/mac/ftoldmac.c for
+ * classic platforms built by MPW.
+ *
+ * Copyright (C) 1996-2019 by
+ * Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
/*
@@ -954,17 +954,17 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_New_Face */
- /* */
- /* <Description> */
- /* This is the Mac-specific implementation of FT_New_Face. In */
- /* addition to the standard FT_New_Face() functionality, it also */
- /* accepts pathnames to Mac suitcase files. For further */
- /* documentation see the original FT_New_Face() in freetype.h. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * FT_New_Face
+ *
+ * @Description:
+ * This is the Mac-specific implementation of FT_New_Face. In
+ * addition to the standard FT_New_Face() functionality, it also
+ * accepts pathnames to Mac suitcase files. For further
+ * documentation see the original FT_New_Face() in freetype.h.
+ */
FT_EXPORT_DEF( FT_Error )
FT_New_Face( FT_Library library,
const char* pathname,
@@ -995,17 +995,18 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_New_Face_From_FSRef */
- /* */
- /* <Description> */
- /* FT_New_Face_From_FSRef is identical to FT_New_Face except it */
- /* accepts an FSRef instead of a path. */
- /* */
- /* This function is deprecated because Carbon data types (FSRef) */
- /* are not cross-platform, and thus not suitable for the FreeType API. */
+ /**************************************************************************
+ *
+ * @Function:
+ * FT_New_Face_From_FSRef
+ *
+ * @Description:
+ * FT_New_Face_From_FSRef is identical to FT_New_Face except it
+ * accepts an FSRef instead of a path.
+ *
+ * This function is deprecated because Carbon data types (FSRef)
+ * are not cross-platform, and thus not suitable for the FreeType API.
+ */
FT_EXPORT_DEF( FT_Error )
FT_New_Face_From_FSRef( FT_Library library,
const FSRef* ref,
@@ -1040,16 +1041,17 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_New_Face_From_FSSpec */
- /* */
- /* <Description> */
- /* FT_New_Face_From_FSSpec is identical to FT_New_Face except it */
- /* accepts an FSSpec instead of a path. */
- /* */
- /* This function is deprecated because FSSpec is deprecated in Mac OS X */
+ /**************************************************************************
+ *
+ * @Function:
+ * FT_New_Face_From_FSSpec
+ *
+ * @Description:
+ * FT_New_Face_From_FSSpec is identical to FT_New_Face except it
+ * accepts an FSSpec instead of a path.
+ *
+ * This function is deprecated because FSSpec is deprecated in Mac OS X
+ */
FT_EXPORT_DEF( FT_Error )
FT_New_Face_From_FSSpec( FT_Library library,
const FSSpec* spec,
diff --git a/thirdparty/freetype/src/base/ftmm.c b/thirdparty/freetype/src/base/ftmm.c
index 800441bcac..ba9e67f008 100644
--- a/thirdparty/freetype/src/base/ftmm.c
+++ b/thirdparty/freetype/src/base/ftmm.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftmm.c */
-/* */
-/* Multiple Master font support (body). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftmm.c
+ *
+ * Multiple Master font support (body).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -25,14 +25,14 @@
#include FT_SERVICE_METRICS_VARIATIONS_H
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_mm
+#define FT_COMPONENT mm
static FT_Error
@@ -202,6 +202,67 @@
/* documentation is in ftmm.h */
FT_EXPORT_DEF( FT_Error )
+ FT_Set_MM_WeightVector( FT_Face face,
+ FT_UInt len,
+ FT_Fixed* weightvector )
+ {
+ FT_Error error;
+ FT_Service_MultiMasters service;
+
+
+ /* check of `face' delayed to `ft_face_get_mm_service' */
+
+ if ( len && !weightvector )
+ return FT_THROW( Invalid_Argument );
+
+ error = ft_face_get_mm_service( face, &service );
+ if ( !error )
+ {
+ error = FT_ERR( Invalid_Argument );
+ if ( service->set_mm_weightvector )
+ error = service->set_mm_weightvector( face, len, weightvector );
+ }
+
+ /* enforce recomputation of auto-hinting data */
+ if ( !error && face->autohint.finalizer )
+ {
+ face->autohint.finalizer( face->autohint.data );
+ face->autohint.data = NULL;
+ }
+
+ return error;
+ }
+
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Get_MM_WeightVector( FT_Face face,
+ FT_UInt* len,
+ FT_Fixed* weightvector )
+ {
+ FT_Error error;
+ FT_Service_MultiMasters service;
+
+
+ /* check of `face' delayed to `ft_face_get_mm_service' */
+
+ if ( len && !weightvector )
+ return FT_THROW( Invalid_Argument );
+
+ error = ft_face_get_mm_service( face, &service );
+ if ( !error )
+ {
+ error = FT_ERR( Invalid_Argument );
+ if ( service->get_mm_weightvector )
+ error = service->get_mm_weightvector( face, len, weightvector );
+ }
+
+ return error;
+ }
+
+
+ /* documentation is in ftmm.h */
+
+ FT_EXPORT_DEF( FT_Error )
FT_Set_Var_Design_Coordinates( FT_Face face,
FT_UInt num_coords,
FT_Fixed* coords )
diff --git a/thirdparty/freetype/src/base/ftobjs.c b/thirdparty/freetype/src/base/ftobjs.c
index 8d07e35ae3..3f8619d3b3 100644
--- a/thirdparty/freetype/src/base/ftobjs.c
+++ b/thirdparty/freetype/src/base/ftobjs.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftobjs.c */
-/* */
-/* The FreeType private base classes (body). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftobjs.c
+ *
+ * The FreeType private base classes (body).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -79,6 +79,18 @@
#pragma warning( pop )
#endif
+ static const char* const pixel_modes[] =
+ {
+ "none",
+ "monochrome bitmap",
+ "gray 8-bit bitmap",
+ "gray 2-bit bitmap",
+ "gray 4-bit bitmap",
+ "LCD 8-bit bitmap",
+ "vertical LCD 8-bit bitmap",
+ "BGRA 32-bit color image bitmap"
+ };
+
#endif /* FT_DEBUG_LEVEL_TRACE */
@@ -259,14 +271,14 @@
}
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_objs
+#define FT_COMPONENT objs
/*************************************************************************/
@@ -330,7 +342,9 @@
}
- FT_BASE_DEF( void )
+ /* overflow-resistant presetting of bitmap position and dimensions; */
+ /* also check whether the size is too large for rendering */
+ FT_BASE_DEF( FT_Bool )
ft_glyphslot_preset_bitmap( FT_GlyphSlot slot,
FT_Render_Mode mode,
const FT_Vector* origin )
@@ -340,15 +354,15 @@
FT_Pixel_Mode pixel_mode;
- FT_BBox cbox;
+ FT_BBox cbox, pbox;
FT_Pos x_shift = 0;
FT_Pos y_shift = 0;
FT_Pos x_left, y_top;
FT_Pos width, height, pitch;
- if ( slot->internal && ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) )
- return;
+ if ( slot->format != FT_GLYPH_FORMAT_OUTLINE )
+ return 1;
if ( origin )
{
@@ -360,76 +374,89 @@
/* taking into account the origin shift */
FT_Outline_Get_CBox( outline, &cbox );
- cbox.xMin += x_shift;
- cbox.yMin += y_shift;
- cbox.xMax += x_shift;
- cbox.yMax += y_shift;
+ /* rough estimate of pixel box */
+ pbox.xMin = ( cbox.xMin >> 6 ) + ( x_shift >> 6 );
+ pbox.yMin = ( cbox.yMin >> 6 ) + ( y_shift >> 6 );
+ pbox.xMax = ( cbox.xMax >> 6 ) + ( x_shift >> 6 );
+ pbox.yMax = ( cbox.yMax >> 6 ) + ( y_shift >> 6 );
+
+ /* tiny remainder box */
+ cbox.xMin = ( cbox.xMin & 63 ) + ( x_shift & 63 );
+ cbox.yMin = ( cbox.yMin & 63 ) + ( y_shift & 63 );
+ cbox.xMax = ( cbox.xMax & 63 ) + ( x_shift & 63 );
+ cbox.yMax = ( cbox.yMax & 63 ) + ( y_shift & 63 );
switch ( mode )
{
case FT_RENDER_MODE_MONO:
pixel_mode = FT_PIXEL_MODE_MONO;
#if 1
- /* undocumented but confirmed: bbox values get rounded */
- /* unless the rounded box can collapse for a narrow glyph */
- if ( cbox.xMax - cbox.xMin < 64 )
- {
- cbox.xMin = FT_PIX_FLOOR( cbox.xMin );
- cbox.xMax = FT_PIX_CEIL_LONG( cbox.xMax );
- }
- else
- {
- cbox.xMin = FT_PIX_ROUND_LONG( cbox.xMin );
- cbox.xMax = FT_PIX_ROUND_LONG( cbox.xMax );
- }
+ /* x */
+
+ /* undocumented but confirmed: bbox values get rounded; */
+ /* we do asymmetric rounding so that the center of a pixel */
+ /* gets always included */
+
+ pbox.xMin += ( cbox.xMin + 31 ) >> 6;
+ pbox.xMax += ( cbox.xMax + 32 ) >> 6;
- if ( cbox.yMax - cbox.yMin < 64 )
+ /* if the bbox collapsed, we add a pixel based on the total */
+ /* rounding remainder to cover most of the original cbox */
+
+ if ( pbox.xMin == pbox.xMax )
{
- cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
- cbox.yMax = FT_PIX_CEIL_LONG( cbox.yMax );
+ if ( ( ( cbox.xMin + 31 ) & 63 ) - 31 +
+ ( ( cbox.xMax + 32 ) & 63 ) - 32 < 0 )
+ pbox.xMin -= 1;
+ else
+ pbox.xMax += 1;
}
- else
+
+ /* y */
+
+ pbox.yMin += ( cbox.yMin + 31 ) >> 6;
+ pbox.yMax += ( cbox.yMax + 32 ) >> 6;
+
+ if ( pbox.yMin == pbox.yMax )
{
- cbox.yMin = FT_PIX_ROUND_LONG( cbox.yMin );
- cbox.yMax = FT_PIX_ROUND_LONG( cbox.yMax );
+ if ( ( ( cbox.yMin + 31 ) & 63 ) - 31 +
+ ( ( cbox.yMax + 32 ) & 63 ) - 32 < 0 )
+ pbox.yMin -= 1;
+ else
+ pbox.yMax += 1;
}
+
+ break;
#else
- cbox.xMin = FT_PIX_FLOOR( cbox.xMin );
- cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
- cbox.xMax = FT_PIX_CEIL_LONG( cbox.xMax );
- cbox.yMax = FT_PIX_CEIL_LONG( cbox.yMax );
+ goto Adjust;
#endif
- break;
case FT_RENDER_MODE_LCD:
pixel_mode = FT_PIXEL_MODE_LCD;
- ft_lcd_padding( &cbox.xMin, &cbox.xMax, slot );
- goto Round;
+ ft_lcd_padding( &cbox, slot, mode );
+ goto Adjust;
case FT_RENDER_MODE_LCD_V:
pixel_mode = FT_PIXEL_MODE_LCD_V;
- ft_lcd_padding( &cbox.yMin, &cbox.yMax, slot );
- goto Round;
+ ft_lcd_padding( &cbox, slot, mode );
+ goto Adjust;
case FT_RENDER_MODE_NORMAL:
case FT_RENDER_MODE_LIGHT:
default:
pixel_mode = FT_PIXEL_MODE_GRAY;
- Round:
- cbox.xMin = FT_PIX_FLOOR( cbox.xMin );
- cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
- cbox.xMax = FT_PIX_CEIL_LONG( cbox.xMax );
- cbox.yMax = FT_PIX_CEIL_LONG( cbox.yMax );
+ Adjust:
+ pbox.xMin += cbox.xMin >> 6;
+ pbox.yMin += cbox.yMin >> 6;
+ pbox.xMax += ( cbox.xMax + 63 ) >> 6;
+ pbox.yMax += ( cbox.yMax + 63 ) >> 6;
}
- x_shift = SUB_LONG( x_shift, cbox.xMin );
- y_shift = SUB_LONG( y_shift, cbox.yMin );
+ x_left = pbox.xMin;
+ y_top = pbox.yMax;
- x_left = cbox.xMin >> 6;
- y_top = cbox.yMax >> 6;
-
- width = ( (FT_ULong)cbox.xMax - (FT_ULong)cbox.xMin ) >> 6;
- height = ( (FT_ULong)cbox.yMax - (FT_ULong)cbox.yMin ) >> 6;
+ width = pbox.xMax - pbox.xMin;
+ height = pbox.yMax - pbox.yMin;
switch ( pixel_mode )
{
@@ -459,6 +486,16 @@
bitmap->width = (unsigned int)width;
bitmap->rows = (unsigned int)height;
bitmap->pitch = pitch;
+
+ if ( pbox.xMin < -0x8000 || pbox.xMax > 0x7FFF ||
+ pbox.yMin < -0x8000 || pbox.yMax > 0x7FFF )
+ {
+ FT_TRACE3(( "ft_glyphslot_preset_bitmap: [%ld %ld %ld %ld]\n",
+ pbox.xMin, pbox.yMin, pbox.xMax, pbox.yMax ));
+ return 1;
+ }
+
+ return 0;
}
@@ -807,7 +844,7 @@
* - Do only auto-hinting if we have
*
* - a hinter module,
- * - a scalable font format dealing with outlines,
+ * - a scalable font,
* - not a tricky font, and
* - no transforms except simple slants and/or rotations by
* integer multiples of 90 degrees.
@@ -825,8 +862,7 @@
if ( hinter &&
!( load_flags & FT_LOAD_NO_HINTING ) &&
!( load_flags & FT_LOAD_NO_AUTOHINT ) &&
- FT_DRIVER_IS_SCALABLE( driver ) &&
- FT_DRIVER_USES_OUTLINES( driver ) &&
+ FT_IS_SCALABLE( face ) &&
!FT_IS_TRICKY( face ) &&
( ( load_flags & FT_LOAD_IGNORE_TRANSFORM ) ||
( face->internal->transform_matrix.yx == 0 &&
@@ -846,7 +882,7 @@
/* only the new Adobe engine (for both CFF and Type 1) is `light'; */
/* we use `strstr' to catch both `Type 1' and `CID Type 1' */
is_light_type1 =
- ft_strstr( FT_Get_Font_Format( face ), "Type 1" ) != NULL &&
+ ft_strstr( FT_Get_Font_Format( face ), "Type 1" ) != NULL &&
((PS_Driver)driver)->hinting_engine == FT_HINTING_ADOBE;
/* the check for `num_locations' assures that we actually */
@@ -926,8 +962,9 @@
#ifdef GRID_FIT_METRICS
if ( !( load_flags & FT_LOAD_NO_HINTING ) )
- ft_glyphslot_grid_fit_metrics( slot,
- FT_BOOL( load_flags & FT_LOAD_VERTICAL_LAYOUT ) );
+ ft_glyphslot_grid_fit_metrics(
+ slot,
+ FT_BOOL( load_flags & FT_LOAD_VERTICAL_LAYOUT ) );
#endif
}
}
@@ -995,6 +1032,9 @@
}
}
+ slot->glyph_index = glyph_index;
+ slot->internal->load_flags = load_flags;
+
/* do we need to render the image or preset the bitmap now? */
if ( !error &&
( load_flags & FT_LOAD_NO_SCALE ) == 0 &&
@@ -1014,17 +1054,21 @@
ft_glyphslot_preset_bitmap( slot, mode, NULL );
}
- FT_TRACE5(( "FT_Load_Glyph: index %d, flags %x\n",
- glyph_index, load_flags ));
+#ifdef FT_DEBUG_LEVEL_TRACE
+ FT_TRACE5(( "FT_Load_Glyph: index %d, flags 0x%x\n",
+ glyph_index, load_flags ));
FT_TRACE5(( " x advance: %f\n", slot->advance.x / 64.0 ));
FT_TRACE5(( " y advance: %f\n", slot->advance.y / 64.0 ));
FT_TRACE5(( " linear x advance: %f\n",
slot->linearHoriAdvance / 65536.0 ));
FT_TRACE5(( " linear y advance: %f\n",
slot->linearVertAdvance / 65536.0 ));
- FT_TRACE5(( " bitmap %dx%d, mode %d\n",
- slot->bitmap.width, slot->bitmap.rows,
- slot->bitmap.pixel_mode ));
+ FT_TRACE5(( " bitmap %dx%d, %s (mode %d)\n",
+ slot->bitmap.width,
+ slot->bitmap.rows,
+ pixel_modes[slot->bitmap.pixel_mode],
+ slot->bitmap.pixel_mode ));
+#endif
Exit:
return error;
@@ -1162,20 +1206,20 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* find_unicode_charmap */
- /* */
- /* <Description> */
- /* This function finds a Unicode charmap, if there is one. */
- /* And if there is more than one, it tries to favour the more */
- /* extensive one, i.e., one that supports UCS-4 against those which */
- /* are limited to the BMP (said UCS-2 encoding.) */
- /* */
- /* This function is called from open_face() (just below), and also */
- /* from FT_Select_Charmap( ..., FT_ENCODING_UNICODE ). */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * find_unicode_charmap
+ *
+ * @Description:
+ * This function finds a Unicode charmap, if there is one.
+ * And if there is more than one, it tries to favour the more
+ * extensive one, i.e., one that supports UCS-4 against those which
+ * are limited to the BMP (said UCS-2 encoding.)
+ *
+ * This function is called from open_face() (just below), and also
+ * from FT_Select_Charmap( ..., FT_ENCODING_UNICODE ).
+ */
static FT_Error
find_unicode_charmap( FT_Face face )
{
@@ -1192,26 +1236,26 @@
return FT_THROW( Invalid_CharMap_Handle );
/*
- * The original TrueType specification(s) only specified charmap
- * formats that are capable of mapping 8 or 16 bit character codes to
- * glyph indices.
+ * The original TrueType specification(s) only specified charmap
+ * formats that are capable of mapping 8 or 16 bit character codes to
+ * glyph indices.
*
- * However, recent updates to the Apple and OpenType specifications
- * introduced new formats that are capable of mapping 32-bit character
- * codes as well. And these are already used on some fonts, mainly to
- * map non-BMP Asian ideographs as defined in Unicode.
+ * However, recent updates to the Apple and OpenType specifications
+ * introduced new formats that are capable of mapping 32-bit character
+ * codes as well. And these are already used on some fonts, mainly to
+ * map non-BMP Asian ideographs as defined in Unicode.
*
- * For compatibility purposes, these fonts generally come with
- * *several* Unicode charmaps:
+ * For compatibility purposes, these fonts generally come with
+ * *several* Unicode charmaps:
*
- * - One of them in the "old" 16-bit format, that cannot access
- * all glyphs in the font.
+ * - One of them in the "old" 16-bit format, that cannot access
+ * all glyphs in the font.
*
- * - Another one in the "new" 32-bit format, that can access all
- * the glyphs.
+ * - Another one in the "new" 32-bit format, that can access all
+ * the glyphs.
*
- * This function has been written to always favor a 32-bit charmap
- * when found. Otherwise, a 16-bit one is returned when found.
+ * This function has been written to always favor a 32-bit charmap
+ * when found. Otherwise, a 16-bit one is returned when found.
*/
/* Since the `interesting' table, with IDs (3,10), is normally the */
@@ -1255,15 +1299,15 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* find_variant_selector_charmap */
- /* */
- /* <Description> */
- /* This function finds the variant selector charmap, if there is one. */
- /* There can only be one (platform=0, specific=5, format=14). */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * find_variant_selector_charmap
+ *
+ * @Description:
+ * This function finds the variant selector charmap, if there is one.
+ * There can only be one (platform=0, specific=5, format=14).
+ */
static FT_CharMap
find_variant_selector_charmap( FT_Face face )
{
@@ -1294,14 +1338,14 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* open_face */
- /* */
- /* <Description> */
- /* This function does some work for FT_Open_Face(). */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * open_face
+ *
+ * @Description:
+ * This function does some work for FT_Open_Face().
+ */
static FT_Error
open_face( FT_Driver driver,
FT_Stream *astream,
@@ -2176,13 +2220,13 @@
{
#undef FT_COMPONENT
-#define FT_COMPONENT trace_raccess
+#define FT_COMPONENT raccess
FT_Memory memory = library->memory;
FT_Error error = FT_ERR( Unknown_File_Format );
FT_UInt i;
- char * file_names[FT_RACCESS_N_RULES];
+ char* file_names[FT_RACCESS_N_RULES];
FT_Long offsets[FT_RACCESS_N_RULES];
FT_Error errors[FT_RACCESS_N_RULES];
FT_Bool is_darwin_vfs, vfs_rfork_has_no_font = FALSE; /* not tested */
@@ -2254,7 +2298,7 @@
return error;
#undef FT_COMPONENT
-#define FT_COMPONENT trace_objs
+#define FT_COMPONENT objs
}
@@ -2282,7 +2326,7 @@
{
#undef FT_COMPONENT
-#define FT_COMPONENT trace_raccess
+#define FT_COMPONENT raccess
#ifdef FT_DEBUG_LEVEL_TRACE
FT_TRACE3(( "Try as dfont: " ));
@@ -2295,7 +2339,7 @@
FT_TRACE3(( "%s\n", error ? "failed" : "successful" ));
#undef FT_COMPONENT
-#define FT_COMPONENT trace_objs
+#define FT_COMPONENT objs
}
@@ -2693,8 +2737,8 @@
/* close the attached stream */
FT_Stream_Free( stream,
- (FT_Bool)( parameters->stream &&
- ( parameters->flags & FT_OPEN_STREAM ) ) );
+ FT_BOOL( parameters->stream &&
+ ( parameters->flags & FT_OPEN_STREAM ) ) );
Exit:
return error;
@@ -3464,7 +3508,8 @@
if ( !face )
return FT_THROW( Invalid_Face_Handle );
- if ( encoding == FT_ENCODING_NONE )
+ /* FT_ENCODING_NONE is a valid encoding for BDF, PCF, and Windows FNT */
+ if ( encoding == FT_ENCODING_NONE && !face->num_charmaps )
return FT_THROW( Invalid_Argument );
/* FT_ENCODING_UNICODE is special. We try to find the `best' Unicode */
@@ -3485,7 +3530,7 @@
if ( cur[0]->encoding == encoding )
{
face->charmap = cur[0];
- return 0;
+ return FT_Err_Ok;
}
}
@@ -3510,14 +3555,12 @@
if ( !cur || !charmap )
return FT_THROW( Invalid_CharMap_Handle );
- if ( FT_Get_CMap_Format( charmap ) == 14 )
- return FT_THROW( Invalid_Argument );
-
limit = cur + face->num_charmaps;
for ( ; cur < limit; cur++ )
{
- if ( cur[0] == charmap )
+ if ( cur[0] == charmap &&
+ FT_Get_CMap_Format ( charmap ) != 14 )
{
face->charmap = cur[0];
return FT_Err_Ok;
@@ -4487,16 +4530,89 @@
FT_Render_Mode render_mode )
{
FT_Error error = FT_Err_Ok;
+ FT_Face face = slot->face;
FT_Renderer renderer;
- /* if it is already a bitmap, no need to do anything */
switch ( slot->format )
{
case FT_GLYPH_FORMAT_BITMAP: /* already a bitmap, don't do anything */
break;
default:
+ if ( slot->internal->load_flags & FT_LOAD_COLOR )
+ {
+ FT_LayerIterator iterator;
+
+ FT_UInt base_glyph = slot->glyph_index;
+
+ FT_Bool have_layers;
+ FT_UInt glyph_index;
+ FT_UInt color_index;
+
+
+ /* check whether we have colored glyph layers */
+ iterator.p = NULL;
+ have_layers = FT_Get_Color_Glyph_Layer( face,
+ base_glyph,
+ &glyph_index,
+ &color_index,
+ &iterator );
+ if ( have_layers )
+ {
+ error = FT_New_GlyphSlot( face, NULL );
+ if ( !error )
+ {
+ TT_Face ttface = (TT_Face)face;
+ SFNT_Service sfnt = (SFNT_Service)ttface->sfnt;
+
+
+ do
+ {
+ FT_Int32 load_flags = slot->internal->load_flags;
+
+
+ /* disable the `FT_LOAD_COLOR' flag to avoid recursion */
+ /* right here in this function */
+ load_flags &= ~FT_LOAD_COLOR;
+
+ /* render into the new `face->glyph' glyph slot */
+ load_flags |= FT_LOAD_RENDER;
+
+ error = FT_Load_Glyph( face, glyph_index, load_flags );
+ if ( error )
+ break;
+
+ /* blend new `face->glyph' into old `slot'; */
+ /* at the first call, `slot' is still empty */
+ error = sfnt->colr_blend( ttface,
+ color_index,
+ slot,
+ face->glyph );
+ if ( error )
+ break;
+
+ } while ( FT_Get_Color_Glyph_Layer( face,
+ base_glyph,
+ &glyph_index,
+ &color_index,
+ &iterator ) );
+
+ if ( !error )
+ slot->format = FT_GLYPH_FORMAT_BITMAP;
+
+ /* this call also restores `slot' as the glyph slot */
+ FT_Done_GlyphSlot( face->glyph );
+ }
+
+ if ( !error )
+ return error;
+
+ /* Failed to do the colored layer. Draw outline instead. */
+ slot->format = FT_GLYPH_FORMAT_OUTLINE;
+ }
+ }
+
{
FT_ListNode node = NULL;
@@ -4532,7 +4648,7 @@
#ifdef FT_DEBUG_LEVEL_TRACE
#undef FT_COMPONENT
-#define FT_COMPONENT trace_bitmap
+#define FT_COMPONENT checksum
/*
* Computing the MD5 checksum is expensive, unnecessarily distorting a
@@ -4542,9 +4658,9 @@
*/
/* we use FT_TRACE3 in this block */
- if ( !error &&
- ft_trace_levels[trace_bitmap] >= 3 &&
- slot->bitmap.buffer )
+ if ( !error &&
+ ft_trace_levels[trace_checksum] >= 3 &&
+ slot->bitmap.buffer )
{
FT_Bitmap bitmap;
FT_Error err;
@@ -4565,8 +4681,11 @@
int pitch = bitmap.pitch;
- FT_TRACE3(( "FT_Render_Glyph: bitmap %dx%d, mode %d\n",
- rows, pitch, slot->bitmap.pixel_mode ));
+ FT_TRACE3(( "FT_Render_Glyph: bitmap %dx%d, %s (mode %d)\n",
+ pitch,
+ rows,
+ pixel_modes[slot->bitmap.pixel_mode],
+ slot->bitmap.pixel_mode ));
for ( i = 0; i < rows; i++ )
for ( j = 0; j < pitch; j++ )
@@ -4594,49 +4713,56 @@
*/
/* we use FT_TRACE7 in this block */
- if ( !error &&
- ft_trace_levels[trace_bitmap] >= 7 &&
- slot->bitmap.rows < 128U &&
- slot->bitmap.width < 128U &&
- slot->bitmap.buffer )
+ if ( !error &&
+ ft_trace_levels[trace_checksum] >= 7 )
{
- int rows = (int)slot->bitmap.rows;
- int width = (int)slot->bitmap.width;
- int pitch = slot->bitmap.pitch;
- int i, j, m;
- unsigned char* topleft = slot->bitmap.buffer;
+ if ( slot->bitmap.rows < 128U &&
+ slot->bitmap.width < 128U &&
+ slot->bitmap.buffer )
+ {
+ int rows = (int)slot->bitmap.rows;
+ int width = (int)slot->bitmap.width;
+ int pitch = slot->bitmap.pitch;
+ int i, j, m;
- if ( pitch < 0 )
- topleft -= pitch * ( rows - 1 );
+ unsigned char* topleft = slot->bitmap.buffer;
- FT_TRACE7(( "Netpbm image: start\n" ));
- switch ( slot->bitmap.pixel_mode )
- {
- case FT_PIXEL_MODE_MONO:
- FT_TRACE7(( "P1 %d %d\n", width, rows ));
- for ( i = 0; i < rows; i++ )
- {
- for ( j = 0; j < width; )
- for ( m = 128; m > 0 && j < width; m >>= 1, j++ )
- FT_TRACE7(( " %d", ( topleft[i * pitch + j / 8] & m ) != 0 ));
- FT_TRACE7(( "\n" ));
- }
- break;
- default:
- FT_TRACE7(( "P2 %d %d 255\n", width, rows ));
- for ( i = 0; i < rows; i++ )
+ if ( pitch < 0 )
+ topleft -= pitch * ( rows - 1 );
+
+ FT_TRACE7(( "Netpbm image: start\n" ));
+ switch ( slot->bitmap.pixel_mode )
{
- for ( j = 0; j < width; j += 1 )
- FT_TRACE7(( " %3u", topleft[i * pitch + j] ));
- FT_TRACE7(( "\n" ));
+ case FT_PIXEL_MODE_MONO:
+ FT_TRACE7(( "P1 %d %d\n", width, rows ));
+ for ( i = 0; i < rows; i++ )
+ {
+ for ( j = 0; j < width; )
+ for ( m = 128; m > 0 && j < width; m >>= 1, j++ )
+ FT_TRACE7(( " %d",
+ ( topleft[i * pitch + j / 8] & m ) != 0 ));
+ FT_TRACE7(( "\n" ));
+ }
+ break;
+
+ default:
+ FT_TRACE7(( "P2 %d %d 255\n", width, rows ));
+ for ( i = 0; i < rows; i++ )
+ {
+ for ( j = 0; j < width; j += 1 )
+ FT_TRACE7(( " %3u", topleft[i * pitch + j] ));
+ FT_TRACE7(( "\n" ));
+ }
}
+ FT_TRACE7(( "Netpbm image: end\n" ));
}
- FT_TRACE7(( "Netpbm image: end\n" ));
+ else
+ FT_TRACE7(( "Netpbm image: too large, omitted\n" ));
}
#undef FT_COMPONENT
-#define FT_COMPONENT trace_objs
+#define FT_COMPONENT objs
#endif /* FT_DEBUG_LEVEL_TRACE */
@@ -4675,21 +4801,22 @@
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Destroy_Module */
- /* */
- /* <Description> */
- /* Destroys a given module object. For drivers, this also destroys */
- /* all child faces. */
- /* */
- /* <InOut> */
- /* module :: A handle to the target driver object. */
- /* */
- /* <Note> */
- /* The driver _must_ be LOCKED! */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * Destroy_Module
+ *
+ * @Description:
+ * Destroys a given module object. For drivers, this also destroys
+ * all child faces.
+ *
+ * @InOut:
+ * module ::
+ * A handle to the target driver object.
+ *
+ * @Note:
+ * The driver _must_ be LOCKED!
+ */
static void
Destroy_Module( FT_Module module )
{
@@ -5028,9 +5155,9 @@
service = (FT_Service_Properties)interface;
if ( set )
- missing_func = (FT_Bool)( !service->set_property );
+ missing_func = FT_BOOL( !service->set_property );
else
- missing_func = (FT_Bool)( !service->get_property );
+ missing_func = FT_BOOL( !service->get_property );
if ( missing_func )
{
@@ -5156,13 +5283,6 @@
library->memory = memory;
-#ifdef FT_CONFIG_OPTION_PIC
- /* initialize position independent code containers */
- error = ft_pic_container_init( library );
- if ( error )
- goto Fail;
-#endif
-
library->version_major = FREETYPE_MAJOR;
library->version_minor = FREETYPE_MINOR;
library->version_patch = FREETYPE_PATCH;
@@ -5173,13 +5293,6 @@
*alibrary = library;
return FT_Err_Ok;
-
-#ifdef FT_CONFIG_OPTION_PIC
- Fail:
- ft_pic_container_destroy( library );
- FT_FREE( library );
- return error;
-#endif
}
@@ -5237,10 +5350,10 @@
*
* Example:
*
- * - the cff font driver uses the pshinter module in cff_size_done
- * - if the pshinter module is destroyed before the cff font driver,
- * opened FT_Face objects managed by the driver are not properly
- * destroyed, resulting in a memory leak
+ * - the cff font driver uses the pshinter module in cff_size_done
+ * - if the pshinter module is destroyed before the cff font driver,
+ * opened FT_Face objects managed by the driver are not properly
+ * destroyed, resulting in a memory leak
*
* Some faces are dependent on other faces, like Type42 faces that
* depend on TrueType faces synthesized internally.
@@ -5310,11 +5423,6 @@
}
#endif
-#ifdef FT_CONFIG_OPTION_PIC
- /* Destroy pic container contents */
- ft_pic_container_destroy( library );
-#endif
-
FT_FREE( library );
Exit:
@@ -5402,4 +5510,41 @@
}
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_Bool )
+ FT_Get_Color_Glyph_Layer( FT_Face face,
+ FT_UInt base_glyph,
+ FT_UInt *aglyph_index,
+ FT_UInt *acolor_index,
+ FT_LayerIterator* iterator )
+ {
+ TT_Face ttface;
+ SFNT_Service sfnt;
+
+
+ if ( !face ||
+ !aglyph_index ||
+ !acolor_index ||
+ !iterator ||
+ base_glyph >= (FT_UInt)face->num_glyphs )
+ return 0;
+
+ if ( !FT_IS_SFNT( face ) )
+ return 0;
+
+ ttface = (TT_Face)face;
+ sfnt = (SFNT_Service)ttface->sfnt;
+
+ if ( sfnt->get_colr_layer )
+ return sfnt->get_colr_layer( ttface,
+ base_glyph,
+ aglyph_index,
+ acolor_index,
+ iterator );
+ else
+ return 0;
+ }
+
+
/* END */
diff --git a/thirdparty/freetype/src/base/ftotval.c b/thirdparty/freetype/src/base/ftotval.c
index a2944a7950..007576ce6e 100644
--- a/thirdparty/freetype/src/base/ftotval.c
+++ b/thirdparty/freetype/src/base/ftotval.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftotval.c */
-/* */
-/* FreeType API for validating OpenType tables (body). */
-/* */
-/* Copyright 2004-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftotval.c
+ *
+ * FreeType API for validating OpenType tables (body).
+ *
+ * Copyright (C) 2004-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
#include FT_INTERNAL_DEBUG_H
diff --git a/thirdparty/freetype/src/base/ftoutln.c b/thirdparty/freetype/src/base/ftoutln.c
index cb91321deb..00329b46c6 100644
--- a/thirdparty/freetype/src/base/ftoutln.c
+++ b/thirdparty/freetype/src/base/ftoutln.c
@@ -1,26 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftoutln.c */
-/* */
-/* FreeType outline management (body). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* All functions are declared in freetype.h. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * ftoutln.c
+ *
+ * FreeType outline management (body).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -31,14 +24,14 @@
#include FT_TRIGONOMETRY_H
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_outline
+#define FT_COMPONENT outline
static
@@ -296,15 +289,23 @@
}
+ /* documentation is in ftoutln.h */
+
FT_EXPORT_DEF( FT_Error )
- FT_Outline_New_Internal( FT_Memory memory,
- FT_UInt numPoints,
- FT_Int numContours,
- FT_Outline *anoutline )
+ FT_Outline_New( FT_Library library,
+ FT_UInt numPoints,
+ FT_Int numContours,
+ FT_Outline *anoutline )
{
- FT_Error error;
+ FT_Error error;
+ FT_Memory memory;
+ if ( !library )
+ return FT_THROW( Invalid_Library_Handle );
+
+ memory = library->memory;
+
if ( !anoutline || !memory )
return FT_THROW( Invalid_Argument );
@@ -330,7 +331,7 @@
Fail:
anoutline->flags |= FT_OUTLINE_OWNER;
- FT_Outline_Done_Internal( memory, anoutline );
+ FT_Outline_Done( library, anoutline );
return error;
}
@@ -339,22 +340,6 @@
/* documentation is in ftoutln.h */
FT_EXPORT_DEF( FT_Error )
- FT_Outline_New( FT_Library library,
- FT_UInt numPoints,
- FT_Int numContours,
- FT_Outline *anoutline )
- {
- if ( !library )
- return FT_THROW( Invalid_Library_Handle );
-
- return FT_Outline_New_Internal( library->memory, numPoints,
- numContours, anoutline );
- }
-
-
- /* documentation is in ftoutln.h */
-
- FT_EXPORT_DEF( FT_Error )
FT_Outline_Check( FT_Outline* outline )
{
if ( outline )
@@ -436,13 +421,23 @@
}
+ /* documentation is in ftoutln.h */
+
FT_EXPORT_DEF( FT_Error )
- FT_Outline_Done_Internal( FT_Memory memory,
- FT_Outline* outline )
+ FT_Outline_Done( FT_Library library,
+ FT_Outline* outline )
{
+ FT_Memory memory;
+
+
+ if ( !library )
+ return FT_THROW( Invalid_Library_Handle );
+
if ( !outline )
return FT_THROW( Invalid_Outline );
+ memory = library->memory;
+
if ( !memory )
return FT_THROW( Invalid_Argument );
@@ -460,21 +455,6 @@
/* documentation is in ftoutln.h */
- FT_EXPORT_DEF( FT_Error )
- FT_Outline_Done( FT_Library library,
- FT_Outline* outline )
- {
- /* check for valid `outline' in FT_Outline_Done_Internal() */
-
- if ( !library )
- return FT_THROW( Invalid_Library_Handle );
-
- return FT_Outline_Done_Internal( library->memory, outline );
- }
-
-
- /* documentation is in ftoutln.h */
-
FT_EXPORT_DEF( void )
FT_Outline_Get_CBox( const FT_Outline* outline,
FT_BBox *acbox )
@@ -619,6 +599,7 @@
FT_Error error;
FT_Renderer renderer;
FT_ListNode node;
+ FT_BBox cbox;
if ( !library )
@@ -630,6 +611,11 @@
if ( !params )
return FT_THROW( Invalid_Argument );
+ FT_Outline_Get_CBox( outline, &cbox );
+ if ( cbox.xMin < -0x1000000L || cbox.yMin < -0x1000000L ||
+ cbox.xMax > 0x1000000L || cbox.yMax > 0x1000000L )
+ return FT_THROW( Invalid_Outline );
+
renderer = library->cur_renderer;
node = library->renderers.head;
@@ -911,9 +897,9 @@
FT_Pos xstrength,
FT_Pos ystrength )
{
- FT_Vector* points;
- FT_Int c, first, last;
- FT_Int orientation;
+ FT_Vector* points;
+ FT_Int c, first, last;
+ FT_Orientation orientation;
if ( !outline )
@@ -1044,7 +1030,7 @@
FT_EXPORT_DEF( FT_Orientation )
FT_Outline_Get_Orientation( FT_Outline* outline )
{
- FT_BBox cbox;
+ FT_BBox cbox = { 0, 0, 0, 0 };
FT_Int xshift, yshift;
FT_Vector* points;
FT_Vector v_prev, v_cur;
@@ -1090,7 +1076,8 @@
v_cur.y = points[n].y >> yshift;
area = ADD_LONG( area,
- ( v_cur.y - v_prev.y ) * ( v_cur.x + v_prev.x ) );
+ MUL_LONG( v_cur.y - v_prev.y,
+ v_cur.x + v_prev.x ) );
v_prev = v_cur;
}
diff --git a/thirdparty/freetype/src/base/ftpatent.c b/thirdparty/freetype/src/base/ftpatent.c
index e23ee2e3f4..020f4646eb 100644
--- a/thirdparty/freetype/src/base/ftpatent.c
+++ b/thirdparty/freetype/src/base/ftpatent.c
@@ -1,20 +1,20 @@
-/***************************************************************************/
-/* */
-/* ftpatent.c */
-/* */
-/* FreeType API for checking patented TrueType bytecode instructions */
-/* (body). Obsolete, retained for backward compatibility. */
-/* */
-/* Copyright 2007-2018 by */
-/* David Turner. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftpatent.c
+ *
+ * FreeType API for checking patented TrueType bytecode instructions
+ * (body). Obsolete, retained for backward compatibility.
+ *
+ * Copyright (C) 2007-2019 by
+ * David Turner.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
#include FT_FREETYPE_H
diff --git a/thirdparty/freetype/src/base/ftpfr.c b/thirdparty/freetype/src/base/ftpfr.c
index bfe13520eb..aeff1db8bd 100644
--- a/thirdparty/freetype/src/base/ftpfr.c
+++ b/thirdparty/freetype/src/base/ftpfr.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftpfr.c */
-/* */
-/* FreeType API for accessing PFR-specific data (body). */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftpfr.c
+ *
+ * FreeType API for accessing PFR-specific data (body).
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
#include FT_INTERNAL_DEBUG_H
diff --git a/thirdparty/freetype/src/base/ftpic.c b/thirdparty/freetype/src/base/ftpic.c
deleted file mode 100644
index 1492e1809a..0000000000
--- a/thirdparty/freetype/src/base/ftpic.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/***************************************************************************/
-/* */
-/* ftpic.c */
-/* */
-/* The FreeType position independent code services (body). */
-/* */
-/* Copyright 2009-2018 by */
-/* Oran Agra and Mickey Gabel. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#include <ft2build.h>
-#include FT_FREETYPE_H
-#include FT_INTERNAL_OBJECTS_H
-#include "basepic.h"
-
-#ifdef FT_CONFIG_OPTION_PIC
-
- /* documentation is in ftpic.h */
-
- FT_BASE_DEF( FT_Error )
- ft_pic_container_init( FT_Library library )
- {
- FT_PIC_Container* pic_container = &library->pic_container;
- FT_Error error;
-
-
- FT_MEM_SET( pic_container, 0, sizeof ( *pic_container ) );
-
- error = ft_base_pic_init( library );
- if ( error )
- return error;
-
- return FT_Err_Ok;
- }
-
-
- /* Destroy the contents of the container. */
- FT_BASE_DEF( void )
- ft_pic_container_destroy( FT_Library library )
- {
- ft_base_pic_free( library );
- }
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
-
-/* END */
diff --git a/thirdparty/freetype/src/base/ftpsprop.c b/thirdparty/freetype/src/base/ftpsprop.c
index 459b5e6054..52b9d453ad 100644
--- a/thirdparty/freetype/src/base/ftpsprop.c
+++ b/thirdparty/freetype/src/base/ftpsprop.c
@@ -1,20 +1,20 @@
-/***************************************************************************/
-/* */
-/* ftpsprop.c */
-/* */
-/* Get and set properties of PostScript drivers (body). */
-/* See `ftdriver.h' for available properties. */
-/* */
-/* Copyright 2017-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftpsprop.c
+ *
+ * Get and set properties of PostScript drivers (body).
+ * See `ftdriver.h' for available properties.
+ *
+ * Copyright (C) 2017-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -25,14 +25,14 @@
#include FT_INTERNAL_POSTSCRIPT_PROPS_H
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_psprops
+#define FT_COMPONENT psprops
FT_BASE_CALLBACK_DEF( FT_Error )
diff --git a/thirdparty/freetype/src/base/ftrfork.c b/thirdparty/freetype/src/base/ftrfork.c
index c3a2b9151a..73b7eb0ded 100644
--- a/thirdparty/freetype/src/base/ftrfork.c
+++ b/thirdparty/freetype/src/base/ftrfork.c
@@ -1,38 +1,38 @@
-/***************************************************************************/
-/* */
-/* ftrfork.c */
-/* */
-/* Embedded resource forks accessor (body). */
-/* */
-/* Copyright 2004-2018 by */
-/* Masatake YAMATO and Redhat K.K. */
-/* */
-/* FT_Raccess_Get_HeaderInfo() and raccess_guess_darwin_hfsplus() are */
-/* derived from ftobjs.c. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-/***************************************************************************/
-/* Development of the code in this file is support of */
-/* Information-technology Promotion Agency, Japan. */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftrfork.c
+ *
+ * Embedded resource forks accessor (body).
+ *
+ * Copyright (C) 2004-2019 by
+ * Masatake YAMATO and Redhat K.K.
+ *
+ * FT_Raccess_Get_HeaderInfo() and raccess_guess_darwin_hfsplus() are
+ * derived from ftobjs.c.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+/****************************************************************************
+ * Development of the code in this file is support of
+ * Information-technology Promotion Agency, Japan.
+ */
#include <ft2build.h>
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_STREAM_H
#include FT_INTERNAL_RFORK_H
-#include "basepic.h"
+
#include "ftbase.h"
#undef FT_COMPONENT
-#define FT_COMPONENT trace_raccess
+#define FT_COMPONENT raccess
/*************************************************************************/
@@ -438,7 +438,7 @@
static FT_Error
raccess_guess_linux_double_from_file_name( FT_Library library,
- char * file_name,
+ char* file_name,
FT_Long *result_offset );
static char *
@@ -468,10 +468,10 @@
if ( errors[i] )
continue;
- errors[i] = (FT_RACCESS_GUESS_TABLE_GET[i].func)( library,
- stream, base_name,
- &(new_names[i]),
- &(offsets[i]) );
+ errors[i] = ft_raccess_guess_table[i].func( library,
+ stream, base_name,
+ &(new_names[i]),
+ &(offsets[i]) );
}
return;
@@ -488,7 +488,7 @@
if ( rule_index >= FT_RACCESS_N_RULES )
return FT_RFork_Rule_invalid;
- return FT_RACCESS_GUESS_TABLE_GET[rule_index].type;
+ return ft_raccess_guess_table[rule_index].type;
}
@@ -847,7 +847,7 @@
{
FT_Open_Args args2;
FT_Stream stream2;
- char * nouse = NULL;
+ char* nouse = NULL;
FT_Error error;
@@ -909,9 +909,9 @@
#else /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */
- /*************************************************************************/
- /* Dummy function; just sets errors */
- /*************************************************************************/
+ /**************************************************************************
+ * Dummy function; just sets errors
+ */
FT_BASE_DEF( void )
FT_Raccess_Guess( FT_Library library,
diff --git a/thirdparty/freetype/src/base/ftsnames.c b/thirdparty/freetype/src/base/ftsnames.c
index 90ea1e2be7..7ab3fe3cfa 100644
--- a/thirdparty/freetype/src/base/ftsnames.c
+++ b/thirdparty/freetype/src/base/ftsnames.c
@@ -1,22 +1,22 @@
-/***************************************************************************/
-/* */
-/* ftsnames.c */
-/* */
-/* Simple interface to access SFNT name tables (which are used */
-/* to hold font names, copyright info, notices, etc.) (body). */
-/* */
-/* This is _not_ used to retrieve glyph names! */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftsnames.c
+ *
+ * Simple interface to access SFNT name tables (which are used
+ * to hold font names, copyright info, notices, etc.) (body).
+ *
+ * This is _not_ used to retrieve glyph names!
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -142,7 +142,45 @@
}
-#endif /* TT_CONFIG_OPTION_SFNT_NAMES */
+#else /* !TT_CONFIG_OPTION_SFNT_NAMES */
+
+
+ FT_EXPORT_DEF( FT_UInt )
+ FT_Get_Sfnt_Name_Count( FT_Face face )
+ {
+ FT_UNUSED( face );
+
+ return 0;
+ }
+
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Get_Sfnt_Name( FT_Face face,
+ FT_UInt idx,
+ FT_SfntName *aname )
+ {
+ FT_UNUSED( face );
+ FT_UNUSED( idx );
+ FT_UNUSED( aname );
+
+ return FT_THROW( Unimplemented_Feature );
+ }
+
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Get_Sfnt_LangTag( FT_Face face,
+ FT_UInt langID,
+ FT_SfntLangTag *alangTag )
+ {
+ FT_UNUSED( face );
+ FT_UNUSED( langID );
+ FT_UNUSED( alangTag );
+
+ return FT_THROW( Unimplemented_Feature );
+ }
+
+
+#endif /* !TT_CONFIG_OPTION_SFNT_NAMES */
/* END */
diff --git a/thirdparty/freetype/src/base/ftstream.c b/thirdparty/freetype/src/base/ftstream.c
index 18df7dcfef..4b0890d7fd 100644
--- a/thirdparty/freetype/src/base/ftstream.c
+++ b/thirdparty/freetype/src/base/ftstream.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftstream.c */
-/* */
-/* I/O stream support (body). */
-/* */
-/* Copyright 2000-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftstream.c
+ *
+ * I/O stream support (body).
+ *
+ * Copyright (C) 2000-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -21,14 +21,14 @@
#include FT_INTERNAL_DEBUG_H
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_stream
+#define FT_COMPONENT stream
FT_BASE_DEF( void )
@@ -219,13 +219,14 @@
{
FT_Memory memory = stream->memory;
+
#ifdef FT_DEBUG_MEMORY
ft_mem_free( memory, *pbytes );
- *pbytes = NULL;
#else
FT_FREE( *pbytes );
#endif
}
+
*pbytes = NULL;
}
@@ -238,6 +239,8 @@
FT_ULong read_bytes;
+ FT_TRACE7(( "FT_Stream_EnterFrame: %ld bytes\n", count ));
+
/* check for nested frame access */
FT_ASSERT( stream && stream->cursor == 0 );
@@ -281,6 +284,7 @@
FT_FREE( stream->base );
error = FT_THROW( Invalid_Stream_Operation );
}
+
stream->cursor = stream->base;
stream->limit = stream->cursor + count;
stream->pos += read_bytes;
@@ -321,13 +325,16 @@
/* In this case, the loader code handles the 0-length table */
/* gracefully; however, stream.cursor is really set to 0 by the */
/* FT_Stream_EnterFrame() call, and this is not an error. */
- /* */
+
+ FT_TRACE7(( "FT_Stream_ExitFrame\n" ));
+
FT_ASSERT( stream );
if ( stream->read )
{
FT_Memory memory = stream->memory;
+
#ifdef FT_DEBUG_MEMORY
ft_mem_free( memory, stream->base );
stream->base = NULL;
@@ -335,6 +342,7 @@
FT_FREE( stream->base );
#endif
}
+
stream->cursor = NULL;
stream->limit = NULL;
}
diff --git a/thirdparty/freetype/src/base/ftstroke.c b/thirdparty/freetype/src/base/ftstroke.c
index 6ae1819067..826062c94e 100644
--- a/thirdparty/freetype/src/base/ftstroke.c
+++ b/thirdparty/freetype/src/base/ftstroke.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftstroke.c */
-/* */
-/* FreeType path stroker (body). */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftstroke.c
+ *
+ * FreeType path stroker (body).
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -24,15 +24,10 @@
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_OBJECTS_H
-#include "basepic.h"
-
- /* declare an extern to access `ft_outline_glyph_class' globally */
- /* allocated in `ftglyph.c', and use the FT_OUTLINE_GLYPH_CLASS_GET */
- /* macro to access it when FT_CONFIG_OPTION_PIC is defined */
-#ifndef FT_CONFIG_OPTION_PIC
+ /* declare an extern to access `ft_outline_glyph_class' globally */
+ /* allocated in `ftglyph.c' */
FT_CALLBACK_TABLE const FT_Glyph_Class ft_outline_glyph_class;
-#endif
/* documentation is in ftstroke.h */
@@ -372,6 +367,7 @@
/* it contains the `adjusted' starting coordinates */
border->num_points = --count;
border->points[start] = border->points[count];
+ border->tags[start] = border->tags[count];
if ( reverse )
{
@@ -436,8 +432,8 @@
}
else
{
- /* don't add zero-length lineto */
- if ( border->num_points > 0 &&
+ /* don't add zero-length lineto, but always add moveto */
+ if ( border->num_points > (FT_UInt)border->start &&
FT_IS_SMALL( border->points[border->num_points - 1].x - to->x ) &&
FT_IS_SMALL( border->points[border->num_points - 1].y - to->y ) )
return error;
@@ -2087,8 +2083,8 @@
/* documentation is in ftstroke.h */
/*
- * The following is very similar to FT_Outline_Decompose, except
- * that we do support opened paths, and do not scale the outline.
+ * The following is very similar to FT_Outline_Decompose, except
+ * that we do support opened paths, and do not scale the outline.
*/
FT_EXPORT_DEF( FT_Error )
FT_Stroker_ParseOutline( FT_Stroker stroker,
@@ -2306,17 +2302,12 @@
FT_Error error = FT_ERR( Invalid_Argument );
FT_Glyph glyph = NULL;
- /* for FT_OUTLINE_GLYPH_CLASS_GET (in PIC mode) */
- FT_Library library = stroker->library;
-
- FT_UNUSED( library );
-
if ( !pglyph )
goto Exit;
glyph = *pglyph;
- if ( !glyph || glyph->clazz != FT_OUTLINE_GLYPH_CLASS_GET )
+ if ( !glyph || glyph->clazz != &ft_outline_glyph_class )
goto Exit;
{
@@ -2386,17 +2377,12 @@
FT_Error error = FT_ERR( Invalid_Argument );
FT_Glyph glyph = NULL;
- /* for FT_OUTLINE_GLYPH_CLASS_GET (in PIC mode) */
- FT_Library library = stroker->library;
-
- FT_UNUSED( library );
-
if ( !pglyph )
goto Exit;
glyph = *pglyph;
- if ( !glyph || glyph->clazz != FT_OUTLINE_GLYPH_CLASS_GET )
+ if ( !glyph || glyph->clazz != &ft_outline_glyph_class )
goto Exit;
{
diff --git a/thirdparty/freetype/src/base/ftsynth.c b/thirdparty/freetype/src/base/ftsynth.c
index c28346707b..f87ed65e75 100644
--- a/thirdparty/freetype/src/base/ftsynth.c
+++ b/thirdparty/freetype/src/base/ftsynth.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftsynth.c */
-/* */
-/* FreeType synthesizing code for emboldening and slanting (body). */
-/* */
-/* Copyright 2000-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftsynth.c
+ *
+ * FreeType synthesizing code for emboldening and slanting (body).
+ *
+ * Copyright (C) 2000-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -24,14 +24,14 @@
#include FT_BITMAP_H
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_synth
+#define FT_COMPONENT synth
/*************************************************************************/
diff --git a/thirdparty/freetype/src/base/ftsystem.c b/thirdparty/freetype/src/base/ftsystem.c
index 6adebdb938..f92b3a03d5 100644
--- a/thirdparty/freetype/src/base/ftsystem.c
+++ b/thirdparty/freetype/src/base/ftsystem.c
@@ -1,28 +1,28 @@
-/***************************************************************************/
-/* */
-/* ftsystem.c */
-/* */
-/* ANSI-specific FreeType low-level system interface (body). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
- /*************************************************************************/
- /* */
- /* This file contains the default interface used by FreeType to access */
- /* low-level, i.e. memory management, i/o access as well as thread */
- /* synchronisation. It can be replaced by user-specific routines if */
- /* necessary. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * ftsystem.c
+ *
+ * ANSI-specific FreeType low-level system interface (body).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+ /**************************************************************************
+ *
+ * This file contains the default interface used by FreeType to access
+ * low-level, i.e. memory management, i/o access as well as thread
+ * synchronisation. It can be replaced by user-specific routines if
+ * necessary.
+ *
+ */
#include <ft2build.h>
@@ -34,37 +34,39 @@
#include FT_TYPES_H
- /*************************************************************************/
- /* */
- /* MEMORY MANAGEMENT INTERFACE */
- /* */
- /*************************************************************************/
-
- /*************************************************************************/
- /* */
- /* It is not necessary to do any error checking for the */
- /* allocation-related functions. This will be done by the higher level */
- /* routines like ft_mem_alloc() or ft_mem_realloc(). */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* ft_alloc */
- /* */
- /* <Description> */
- /* The memory allocation function. */
- /* */
- /* <Input> */
- /* memory :: A pointer to the memory object. */
- /* */
- /* size :: The requested size in bytes. */
- /* */
- /* <Return> */
- /* The address of newly allocated block. */
- /* */
+ /**************************************************************************
+ *
+ * MEMORY MANAGEMENT INTERFACE
+ *
+ */
+
+ /**************************************************************************
+ *
+ * It is not necessary to do any error checking for the
+ * allocation-related functions. This will be done by the higher level
+ * routines like ft_mem_alloc() or ft_mem_realloc().
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @Function:
+ * ft_alloc
+ *
+ * @Description:
+ * The memory allocation function.
+ *
+ * @Input:
+ * memory ::
+ * A pointer to the memory object.
+ *
+ * size ::
+ * The requested size in bytes.
+ *
+ * @Return:
+ * The address of newly allocated block.
+ */
FT_CALLBACK_DEF( void* )
ft_alloc( FT_Memory memory,
long size )
@@ -75,26 +77,30 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* ft_realloc */
- /* */
- /* <Description> */
- /* The memory reallocation function. */
- /* */
- /* <Input> */
- /* memory :: A pointer to the memory object. */
- /* */
- /* cur_size :: The current size of the allocated memory block. */
- /* */
- /* new_size :: The newly requested size in bytes. */
- /* */
- /* block :: The current address of the block in memory. */
- /* */
- /* <Return> */
- /* The address of the reallocated memory block. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * ft_realloc
+ *
+ * @Description:
+ * The memory reallocation function.
+ *
+ * @Input:
+ * memory ::
+ * A pointer to the memory object.
+ *
+ * cur_size ::
+ * The current size of the allocated memory block.
+ *
+ * new_size ::
+ * The newly requested size in bytes.
+ *
+ * block ::
+ * The current address of the block in memory.
+ *
+ * @Return:
+ * The address of the reallocated memory block.
+ */
FT_CALLBACK_DEF( void* )
ft_realloc( FT_Memory memory,
long cur_size,
@@ -108,19 +114,21 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* ft_free */
- /* */
- /* <Description> */
- /* The memory release function. */
- /* */
- /* <Input> */
- /* memory :: A pointer to the memory object. */
- /* */
- /* block :: The address of block in memory to be freed. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * ft_free
+ *
+ * @Description:
+ * The memory release function.
+ *
+ * @Input:
+ * memory ::
+ * A pointer to the memory object.
+ *
+ * block ::
+ * The address of block in memory to be freed.
+ */
FT_CALLBACK_DEF( void )
ft_free( FT_Memory memory,
void* block )
@@ -131,39 +139,40 @@
}
- /*************************************************************************/
- /* */
- /* RESOURCE MANAGEMENT INTERFACE */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * RESOURCE MANAGEMENT INTERFACE
+ *
+ */
#ifndef FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_io
+#define FT_COMPONENT io
/* We use the macro STREAM_FILE for convenience to extract the */
/* system-specific stream handle from a given FreeType stream object */
#define STREAM_FILE( stream ) ( (FT_FILE*)stream->descriptor.pointer )
- /*************************************************************************/
- /* */
- /* <Function> */
- /* ft_ansi_stream_close */
- /* */
- /* <Description> */
- /* The function to close a stream. */
- /* */
- /* <Input> */
- /* stream :: A pointer to the stream object. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * ft_ansi_stream_close
+ *
+ * @Description:
+ * The function to close a stream.
+ *
+ * @Input:
+ * stream ::
+ * A pointer to the stream object.
+ */
FT_CALLBACK_DEF( void )
ft_ansi_stream_close( FT_Stream stream )
{
@@ -175,28 +184,32 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* ft_ansi_stream_io */
- /* */
- /* <Description> */
- /* The function to open a stream. */
- /* */
- /* <Input> */
- /* stream :: A pointer to the stream object. */
- /* */
- /* offset :: The position in the data stream to start reading. */
- /* */
- /* buffer :: The address of buffer to store the read data. */
- /* */
- /* count :: The number of bytes to read from the stream. */
- /* */
- /* <Return> */
- /* The number of bytes actually read. If `count' is zero (this is, */
- /* the function is used for seeking), a non-zero return value */
- /* indicates an error. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * ft_ansi_stream_io
+ *
+ * @Description:
+ * The function to open a stream.
+ *
+ * @Input:
+ * stream ::
+ * A pointer to the stream object.
+ *
+ * offset ::
+ * The position in the data stream to start reading.
+ *
+ * buffer ::
+ * The address of buffer to store the read data.
+ *
+ * count ::
+ * The number of bytes to read from the stream.
+ *
+ * @Return:
+ * The number of bytes actually read. If `count' is zero (this is,
+ * the function is used for seeking), a non-zero return value
+ * indicates an error.
+ */
FT_CALLBACK_DEF( unsigned long )
ft_ansi_stream_io( FT_Stream stream,
unsigned long offset,
diff --git a/thirdparty/freetype/src/base/fttrigon.c b/thirdparty/freetype/src/base/fttrigon.c
index d6dd098c42..38721977c7 100644
--- a/thirdparty/freetype/src/base/fttrigon.c
+++ b/thirdparty/freetype/src/base/fttrigon.c
@@ -1,33 +1,33 @@
-/***************************************************************************/
-/* */
-/* fttrigon.c */
-/* */
-/* FreeType trigonometric functions (body). */
-/* */
-/* Copyright 2001-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
- /*************************************************************************/
- /* */
- /* This is a fixed-point CORDIC implementation of trigonometric */
- /* functions as well as transformations between Cartesian and polar */
- /* coordinates. The angles are represented as 16.16 fixed-point values */
- /* in degrees, i.e., the angular resolution is 2^-16 degrees. Note that */
- /* only vectors longer than 2^16*180/pi (or at least 22 bits) on a */
- /* discrete Cartesian grid can have the same or better angular */
- /* resolution. Therefore, to maintain this precision, some functions */
- /* require an interim upscaling of the vectors, whereas others operate */
- /* with 24-bit long vectors directly. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * fttrigon.c
+ *
+ * FreeType trigonometric functions (body).
+ *
+ * Copyright (C) 2001-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+ /**************************************************************************
+ *
+ * This is a fixed-point CORDIC implementation of trigonometric
+ * functions as well as transformations between Cartesian and polar
+ * coordinates. The angles are represented as 16.16 fixed-point values
+ * in degrees, i.e., the angular resolution is 2^-16 degrees. Note that
+ * only vectors longer than 2^16*180/pi (or at least 22 bits) on a
+ * discrete Cartesian grid can have the same or better angular
+ * resolution. Therefore, to maintain this precision, some functions
+ * require an interim upscaling of the vectors, whereas others operate
+ * with 24-bit long vectors directly.
+ *
+ */
#include <ft2build.h>
#include FT_INTERNAL_OBJECTS_H
@@ -325,10 +325,10 @@
FT_EXPORT_DEF( FT_Fixed )
FT_Tan( FT_Angle angle )
{
- FT_Vector v;
+ FT_Vector v = { 1 << 24, 0 };
- FT_Vector_Unit( &v, angle );
+ ft_trig_pseudo_rotate( &v, angle );
return FT_DivFix( v.y, v.x );
}
@@ -372,14 +372,6 @@
}
- /* these macros return 0 for positive numbers,
- and -1 for negative ones */
-#define FT_SIGN_LONG( x ) ( (x) >> ( FT_SIZEOF_LONG * 8 - 1 ) )
-#define FT_SIGN_INT( x ) ( (x) >> ( FT_SIZEOF_INT * 8 - 1 ) )
-#define FT_SIGN_INT32( x ) ( (x) >> 31 )
-#define FT_SIGN_INT16( x ) ( (x) >> 15 )
-
-
/* documentation is in fttrigon.h */
FT_EXPORT_DEF( void )
@@ -408,8 +400,8 @@
FT_Int32 half = (FT_Int32)1L << ( shift - 1 );
- vec->x = ( v.x + half + FT_SIGN_LONG( v.x ) ) >> shift;
- vec->y = ( v.y + half + FT_SIGN_LONG( v.y ) ) >> shift;
+ vec->x = ( v.x + half - ( v.x < 0 ) ) >> shift;
+ vec->y = ( v.y + half - ( v.y < 0 ) ) >> shift;
}
else
{
diff --git a/thirdparty/freetype/src/base/fttype1.c b/thirdparty/freetype/src/base/fttype1.c
index aa8f8ccbbb..26d4f1c3a8 100644
--- a/thirdparty/freetype/src/base/fttype1.c
+++ b/thirdparty/freetype/src/base/fttype1.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* fttype1.c */
-/* */
-/* FreeType utility file for PS names support (body). */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * fttype1.c
+ *
+ * FreeType utility file for PS names support (body).
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
diff --git a/thirdparty/freetype/src/base/ftutil.c b/thirdparty/freetype/src/base/ftutil.c
index 4de5f2c145..92bd857e92 100644
--- a/thirdparty/freetype/src/base/ftutil.c
+++ b/thirdparty/freetype/src/base/ftutil.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftutil.c */
-/* */
-/* FreeType utility file for memory and list management (body). */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftutil.c
+ *
+ * FreeType utility file for memory and list management (body).
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -23,14 +23,14 @@
#include FT_LIST_H
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_memory
+#define FT_COMPONENT memory
/*************************************************************************/
@@ -54,7 +54,7 @@
FT_Error error;
FT_Pointer block = ft_mem_qalloc( memory, size, &error );
- if ( !error && size > 0 )
+ if ( !error && block && size > 0 )
FT_MEM_ZERO( block, size );
*p_error = error;
@@ -101,7 +101,7 @@
block = ft_mem_qrealloc( memory, item_size,
cur_count, new_count, block, &error );
- if ( !error && new_count > cur_count )
+ if ( !error && block && new_count > cur_count )
FT_MEM_ZERO( (char*)block + cur_count * item_size,
( new_count - cur_count ) * item_size );
@@ -185,7 +185,7 @@
FT_Pointer p = ft_mem_qalloc( memory, (FT_Long)size, &error );
- if ( !error && address )
+ if ( !error && address && size > 0 )
ft_memcpy( p, address, size );
*p_error = error;
@@ -236,7 +236,7 @@
/*************************************************************************/
#undef FT_COMPONENT
-#define FT_COMPONENT trace_list
+#define FT_COMPONENT list
/* documentation is in ftlist.h */
diff --git a/thirdparty/freetype/src/base/ftver.rc b/thirdparty/freetype/src/base/ftver.rc
index a2903d5883..e02a88652c 100644
--- a/thirdparty/freetype/src/base/ftver.rc
+++ b/thirdparty/freetype/src/base/ftver.rc
@@ -4,7 +4,7 @@
/* */
/* FreeType VERSIONINFO resource for Windows DLLs. */
/* */
-/* Copyright 2018 by */
+/* Copyright (C) 2018-2019 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -18,8 +18,8 @@
#include<windows.h>
-#define FT_VERSION 2,9,1,0
-#define FT_VERSION_STR "2.9.1"
+#define FT_VERSION 2,10,0,0
+#define FT_VERSION_STR "2.10.0"
VS_VERSION_INFO VERSIONINFO
FILEVERSION FT_VERSION
@@ -28,7 +28,7 @@ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
#ifdef _DEBUG
FILEFLAGS VS_FF_DEBUG
#endif
-#ifdef _DLL
+#ifdef DLL_EXPORT
FILETYPE VFT_DLL
#define FT_FILENAME "freetype.dll"
#else
@@ -45,7 +45,7 @@ BEGIN
VALUE "FileVersion", FT_VERSION_STR
VALUE "ProductName", "FreeType"
VALUE "ProductVersion", FT_VERSION_STR
- VALUE "LegalCopyright", "\251 2018 The FreeType Project www.freetype.org. All rights reserved."
+ VALUE "LegalCopyright", "\251 2018-2019 The FreeType Project www.freetype.org. All rights reserved."
VALUE "InternalName", "freetype"
VALUE "OriginalFilename", FT_FILENAME
END
diff --git a/thirdparty/freetype/src/base/ftwinfnt.c b/thirdparty/freetype/src/base/ftwinfnt.c
index 11bd28afb7..59daa77031 100644
--- a/thirdparty/freetype/src/base/ftwinfnt.c
+++ b/thirdparty/freetype/src/base/ftwinfnt.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftwinfnt.c */
-/* */
-/* FreeType API for accessing Windows FNT specific info (body). */
-/* */
-/* Copyright 2003-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftwinfnt.c
+ *
+ * FreeType API for accessing Windows FNT specific info (body).
+ *
+ * Copyright (C) 2003-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
diff --git a/thirdparty/freetype/src/base/rules.mk b/thirdparty/freetype/src/base/rules.mk
index e9805bd068..4b24c6dce7 100644
--- a/thirdparty/freetype/src/base/rules.mk
+++ b/thirdparty/freetype/src/base/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2018 by
+# Copyright (C) 1996-2019 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
@@ -36,17 +36,17 @@ BASE_COMPILE := $(CC) $(ANSIFLAGS) \
# All files listed here should be included in `ftbase.c' (for a `single'
# build).
#
-BASE_SRC := $(BASE_DIR)/basepic.c \
- $(BASE_DIR)/ftadvanc.c \
+BASE_SRC := $(BASE_DIR)/ftadvanc.c \
$(BASE_DIR)/ftcalc.c \
+ $(BASE_DIR)/ftcolor.c \
$(BASE_DIR)/ftdbgmem.c \
+ $(BASE_DIR)/fterrors.c \
$(BASE_DIR)/ftfntfmt.c \
$(BASE_DIR)/ftgloadr.c \
$(BASE_DIR)/fthash.c \
$(BASE_DIR)/ftlcdfil.c \
$(BASE_DIR)/ftobjs.c \
$(BASE_DIR)/ftoutln.c \
- $(BASE_DIR)/ftpic.c \
$(BASE_DIR)/ftpsprop.c \
$(BASE_DIR)/ftrfork.c \
$(BASE_DIR)/ftsnames.c \
@@ -60,8 +60,7 @@ ifneq ($(ftmac_c),)
endif
# for simplicity, we also handle `md5.c' (which gets included by `ftobjs.h')
-BASE_H := $(BASE_DIR)/basepic.h \
- $(BASE_DIR)/ftbase.h \
+BASE_H := $(BASE_DIR)/ftbase.h \
$(BASE_DIR)/md5.c \
$(BASE_DIR)/md5.h
diff --git a/thirdparty/freetype/src/bdf/bdf.h b/thirdparty/freetype/src/bdf/bdf.h
index 9012727c7e..4018756f72 100644
--- a/thirdparty/freetype/src/bdf/bdf.h
+++ b/thirdparty/freetype/src/bdf/bdf.h
@@ -51,11 +51,11 @@ FT_BEGIN_HEADER
/* end of bdfP.h */
- /*************************************************************************/
- /* */
- /* BDF font options macros and types. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * BDF font options macros and types.
+ *
+ */
#define BDF_CORRECT_METRICS 0x01 /* Correct invalid metrics when loading. */
@@ -93,11 +93,11 @@ FT_BEGIN_HEADER
void* client_data );
- /*************************************************************************/
- /* */
- /* BDF font property macros and types. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * BDF font property macros and types.
+ *
+ */
#define BDF_ATOM 1
@@ -123,11 +123,11 @@ FT_BEGIN_HEADER
} bdf_property_t;
- /*************************************************************************/
- /* */
- /* BDF font metric and glyph types. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * BDF font metric and glyph types.
+ *
+ */
typedef struct bdf_bbx_t_
@@ -147,7 +147,7 @@ FT_BEGIN_HEADER
typedef struct bdf_glyph_t_
{
char* name; /* Glyph name. */
- long encoding; /* Glyph encoding. */
+ unsigned long encoding; /* Glyph encoding. */
unsigned short swidth; /* Scalable width. */
unsigned short dwidth; /* Device width. */
bdf_bbx_t bbx; /* Glyph bounding box. */
@@ -158,20 +158,6 @@ FT_BEGIN_HEADER
} bdf_glyph_t;
- typedef struct bdf_glyphlist_t_
- {
- unsigned short pad; /* Pad to 4-byte boundary. */
- unsigned short bpp; /* Bits per pixel. */
- long start; /* Beginning encoding value of glyphs. */
- long end; /* Ending encoding value of glyphs. */
- bdf_glyph_t* glyphs; /* Glyphs themselves. */
- unsigned long glyphs_size; /* Glyph structures allocated. */
- unsigned long glyphs_used; /* Glyph structures used. */
- bdf_bbx_t bbx; /* Overall bounding box of glyphs. */
-
- } bdf_glyphlist_t;
-
-
typedef struct bdf_font_t_
{
char* name; /* Name of the font. */
@@ -185,7 +171,7 @@ FT_BEGIN_HEADER
unsigned short monowidth; /* Logical width for monowidth font. */
- long default_char; /* Encoding of the default glyph. */
+ unsigned long default_char; /* Encoding of the default glyph. */
long font_ascent; /* Font ascent. */
long font_descent; /* Font descent. */
@@ -205,16 +191,8 @@ FT_BEGIN_HEADER
char* comments; /* Font comments. */
unsigned long comments_len; /* Length of comment string. */
- bdf_glyphlist_t overflow; /* Storage used for glyph insertion. */
-
void* internal; /* Internal data for the font. */
- /* The size of the next two arrays must be in sync with the */
- /* size of the `have' array in the `bdf_parse_t' structure. */
- unsigned long nmod[34816]; /* Bitmap indicating modified glyphs. */
- unsigned long umod[34816]; /* Bitmap indicating modified */
- /* unencoded glyphs. */
- unsigned short modified; /* Boolean indicating font modified. */
unsigned short bpp; /* Bits per pixel. */
FT_Memory memory;
@@ -226,11 +204,11 @@ FT_BEGIN_HEADER
} bdf_font_t;
- /*************************************************************************/
- /* */
- /* Types for load/save callbacks. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * Types for load/save callbacks.
+ *
+ */
/* Error codes. */
@@ -247,11 +225,11 @@ FT_BEGIN_HEADER
#define BDF_INVALID_LINE -100
- /*************************************************************************/
- /* */
- /* BDF font API. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * BDF font API.
+ *
+ */
FT_LOCAL( FT_Error )
bdf_load_font( FT_Stream stream,
diff --git a/thirdparty/freetype/src/bdf/bdfdrivr.c b/thirdparty/freetype/src/bdf/bdfdrivr.c
index ca937f89ce..4a11843a1c 100644
--- a/thirdparty/freetype/src/bdf/bdfdrivr.c
+++ b/thirdparty/freetype/src/bdf/bdfdrivr.c
@@ -41,14 +41,14 @@ THE SOFTWARE.
#include "bdferror.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_bdfdriver
+#define FT_COMPONENT bdfdriver
typedef struct BDF_CMapRec_
@@ -99,14 +99,17 @@ THE SOFTWARE.
min = 0;
max = cmap->num_encodings;
+ mid = ( min + max ) >> 1;
while ( min < max )
{
FT_ULong code;
- mid = ( min + max ) >> 1;
- code = (FT_ULong)encodings[mid].enc;
+ if ( mid > max || mid < min )
+ mid = ( min + max ) >> 1;
+
+ code = encodings[mid].enc;
if ( charcode == code )
{
@@ -120,6 +123,9 @@ THE SOFTWARE.
max = mid;
else
min = mid + 1;
+
+ /* prediction in a continuous block */
+ mid += charcode - code;
}
return result;
@@ -139,14 +145,17 @@ THE SOFTWARE.
min = 0;
max = cmap->num_encodings;
+ mid = ( min + max ) >> 1;
while ( min < max )
{
FT_ULong code; /* same as BDF_encoding_el.enc */
- mid = ( min + max ) >> 1;
- code = (FT_ULong)encodings[mid].enc;
+ if ( mid > max || mid < min )
+ mid = ( min + max ) >> 1;
+
+ code = encodings[mid].enc;
if ( charcode == code )
{
@@ -160,12 +169,15 @@ THE SOFTWARE.
max = mid;
else
min = mid + 1;
+
+ /* prediction in a continuous block */
+ mid += charcode - code;
}
charcode = 0;
if ( min < cmap->num_encodings )
{
- charcode = (FT_ULong)encodings[min].enc;
+ charcode = encodings[min].enc;
result = encodings[min].glyph + 1;
}
@@ -401,8 +413,7 @@ THE SOFTWARE.
bdfface->face_index = 0;
bdfface->face_flags |= FT_FACE_FLAG_FIXED_SIZES |
- FT_FACE_FLAG_HORIZONTAL |
- FT_FACE_FLAG_FAST_GLYPHS;
+ FT_FACE_FLAG_HORIZONTAL;
prop = bdf_get_font_property( font, "SPACING" );
if ( prop && prop->format == BDF_ATOM &&
@@ -863,7 +874,7 @@ THE SOFTWARE.
/*
*
- * BDF SERVICE
+ * BDF SERVICE
*
*/
@@ -939,7 +950,7 @@ THE SOFTWARE.
/*
*
- * SERVICES LIST
+ * SERVICES LIST
*
*/
diff --git a/thirdparty/freetype/src/bdf/bdfdrivr.h b/thirdparty/freetype/src/bdf/bdfdrivr.h
index 94550818c1..b37b84ea31 100644
--- a/thirdparty/freetype/src/bdf/bdfdrivr.h
+++ b/thirdparty/freetype/src/bdf/bdfdrivr.h
@@ -36,14 +36,10 @@ THE SOFTWARE.
FT_BEGIN_HEADER
-#ifdef FT_CONFIG_OPTION_PIC
-#error "this module does not support PIC yet"
-#endif
-
typedef struct BDF_encoding_el_
{
- FT_Long enc;
+ FT_ULong enc;
FT_UShort glyph;
} BDF_encoding_el;
@@ -60,9 +56,6 @@ FT_BEGIN_HEADER
BDF_encoding_el* en_table;
- FT_CharMap charmap_handle;
- FT_CharMapRec charmap; /* a single charmap per face */
-
FT_UInt default_glyph;
} BDF_FaceRec, *BDF_Face;
diff --git a/thirdparty/freetype/src/bdf/bdferror.h b/thirdparty/freetype/src/bdf/bdferror.h
index b462c7d3b5..dbe41c02ab 100644
--- a/thirdparty/freetype/src/bdf/bdferror.h
+++ b/thirdparty/freetype/src/bdf/bdferror.h
@@ -20,11 +20,11 @@
* THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
- /*************************************************************************/
- /* */
- /* This file is used to define the BDF error enumeration constants. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * This file is used to define the BDF error enumeration constants.
+ *
+ */
#ifndef BDFERROR_H_
#define BDFERROR_H_
diff --git a/thirdparty/freetype/src/bdf/bdflib.c b/thirdparty/freetype/src/bdf/bdflib.c
index 2f5c99d544..0898b0d470 100644
--- a/thirdparty/freetype/src/bdf/bdflib.c
+++ b/thirdparty/freetype/src/bdf/bdflib.c
@@ -22,13 +22,13 @@
* THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
- /*************************************************************************/
- /* */
- /* This file is based on bdf.c,v 1.22 2000/03/16 20:08:50 */
- /* */
- /* taken from Mark Leisher's xmbdfed package */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * This file is based on bdf.c,v 1.22 2000/03/16 20:08:50
+ *
+ * taken from Mark Leisher's xmbdfed package
+ *
+ */
#include <ft2build.h>
@@ -42,21 +42,21 @@
#include "bdferror.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_bdflib
+#define FT_COMPONENT bdflib
- /*************************************************************************/
- /* */
- /* Default BDF font options. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * Default BDF font options.
+ *
+ */
static const bdf_options_t _bdf_opts =
@@ -68,11 +68,11 @@
};
- /*************************************************************************/
- /* */
- /* Builtin BDF font properties. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * Builtin BDF font properties.
+ *
+ */
/* List of most properties that might appear in a font. Doesn't include */
/* the RAW_* and AXIS_* properties in X11R6 polymorphic fonts. */
@@ -196,11 +196,10 @@
#define ACMSG9 "SWIDTH field missing at line %ld. Set automatically.\n"
#define ACMSG10 "DWIDTH field missing at line %ld. Set to glyph width.\n"
#define ACMSG11 "SIZE bits per pixel field adjusted to %hd.\n"
-#define ACMSG12 "Duplicate encoding %ld (%s) changed to unencoded.\n"
-#define ACMSG13 "Glyph %ld extra rows removed.\n"
-#define ACMSG14 "Glyph %ld extra columns removed.\n"
+#define ACMSG13 "Glyph %lu extra rows removed.\n"
+#define ACMSG14 "Glyph %lu extra columns removed.\n"
#define ACMSG15 "Incorrect glyph count: %ld indicated but %ld found.\n"
-#define ACMSG16 "Glyph %ld missing columns padded with zero bits.\n"
+#define ACMSG16 "Glyph %lu missing columns padded with zero bits.\n"
#define ACMSG17 "Adjusting number of glyphs to %ld.\n"
/* Error messages. */
@@ -219,11 +218,11 @@
#define DBGMSG2 " (0x%lX)\n"
- /*************************************************************************/
- /* */
- /* Utility types and functions. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * Utility types and functions.
+ *
+ */
/* Function type for parsing lines of a BDF font. */
@@ -270,8 +269,6 @@
bdf_font_t* font;
bdf_options_t* opts;
- unsigned long have[34816]; /* must be in sync with `nmod' and `umod' */
- /* arrays from `bdf_font_t' structure */
_bdf_list_t list;
FT_Memory memory;
@@ -900,11 +897,11 @@
}
- /*************************************************************************/
- /* */
- /* BDF font file parsing flags and functions. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * BDF font file parsing flags and functions.
+ *
+ */
/* Parse flags. */
@@ -1232,7 +1229,7 @@
/* present, and the SPACING property should override the default */
/* spacing. */
if ( _bdf_strncmp( name, "DEFAULT_CHAR", 12 ) == 0 )
- font->default_char = fp->value.l;
+ font->default_char = fp->value.ul;
else if ( _bdf_strncmp( name, "FONT_ASCENT", 11 ) == 0 )
font->font_ascent = fp->value.l;
else if ( _bdf_strncmp( name, "FONT_DESCENT", 12 ) == 0 )
@@ -1265,6 +1262,25 @@
};
+ static FT_Error
+ _bdf_parse_end( char* line,
+ unsigned long linelen,
+ unsigned long lineno,
+ void* call_data,
+ void* client_data )
+ {
+ /* a no-op; we ignore everything after `ENDFONT' */
+
+ FT_UNUSED( line );
+ FT_UNUSED( linelen );
+ FT_UNUSED( lineno );
+ FT_UNUSED( call_data );
+ FT_UNUSED( client_data );
+
+ return FT_Err_Ok;
+ }
+
+
/* Actually parse the glyph info and bitmaps. */
static FT_Error
_bdf_parse_glyphs( char* line,
@@ -1278,6 +1294,7 @@
unsigned char* bp;
unsigned long i, slen, nibbles;
+ _bdf_line_func_t* next;
_bdf_parse_t* p;
bdf_glyph_t* glyph;
bdf_font_t* font;
@@ -1285,11 +1302,11 @@
FT_Memory memory;
FT_Error error = FT_Err_Ok;
- FT_UNUSED( call_data );
FT_UNUSED( lineno ); /* only used in debug mode */
- p = (_bdf_parse_t *)client_data;
+ next = (_bdf_line_func_t *)call_data;
+ p = (_bdf_parse_t *) client_data;
font = p->font;
memory = font->memory;
@@ -1370,6 +1387,7 @@
by_encoding );
p->flags &= ~BDF_START_;
+ *next = _bdf_parse_end;
goto Exit;
}
@@ -1458,40 +1476,11 @@
if ( p->glyph_enc == -1 && p->list.used > 2 )
p->glyph_enc = _bdf_atol( p->list.field[2] );
- if ( p->glyph_enc < -1 )
+ if ( p->glyph_enc < -1 || p->glyph_enc >= 0x110000L )
p->glyph_enc = -1;
FT_TRACE4(( DBGMSG2, p->glyph_enc ));
- /* Check that the encoding is in the Unicode range because */
- /* otherwise p->have (a bitmap with static size) overflows. */
- if ( p->glyph_enc > 0 &&
- (size_t)p->glyph_enc >= sizeof ( p->have ) /
- sizeof ( unsigned long ) * 32 )
- {
- FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG5, lineno, "ENCODING" ));
- error = FT_THROW( Invalid_File_Format );
- goto Exit;
- }
-
- /* Check whether this encoding has already been encountered. */
- /* If it has then change it to unencoded so it gets added if */
- /* indicated. */
- if ( p->glyph_enc >= 0 )
- {
- if ( _bdf_glyph_modified( p->have, p->glyph_enc ) )
- {
- /* Emit a message saying a glyph has been moved to the */
- /* unencoded area. */
- FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG12,
- p->glyph_enc, p->glyph_name ));
- p->glyph_enc = -1;
- font->modified = 1;
- }
- else
- _bdf_set_glyph_modified( p->have, p->glyph_enc );
- }
-
if ( p->glyph_enc >= 0 )
{
/* Make sure there are enough glyphs allocated in case the */
@@ -1508,7 +1497,7 @@
glyph = font->glyphs + font->glyphs_used++;
glyph->name = p->glyph_name;
- glyph->encoding = p->glyph_enc;
+ glyph->encoding = (unsigned long)p->glyph_enc;
/* Reset the initial glyph info. */
p->glyph_name = NULL;
@@ -1532,7 +1521,7 @@
glyph = font->unencoded + font->unencoded_used;
glyph->name = p->glyph_name;
- glyph->encoding = (long)font->unencoded_used++;
+ glyph->encoding = font->unencoded_used++;
/* Reset the initial glyph info. */
p->glyph_name = NULL;
@@ -1556,6 +1545,9 @@
goto Exit;
}
+ if ( !( p->flags & BDF_ENCODING_ ) )
+ goto Missing_Encoding;
+
/* Point at the glyph being constructed. */
if ( p->glyph_enc == -1 )
glyph = font->unencoded + ( font->unencoded_used - 1 );
@@ -1573,7 +1565,6 @@
{
FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG13, glyph->encoding ));
p->flags |= BDF_GLYPH_HEIGHT_CHECK_;
- font->modified = 1;
}
goto Exit;
@@ -1601,7 +1592,6 @@
{
FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG16, glyph->encoding ));
p->flags |= BDF_GLYPH_WIDTH_CHECK_;
- font->modified = 1;
}
/* Remove possible garbage at the right. */
@@ -1616,7 +1606,6 @@
{
FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG14, glyph->encoding ));
p->flags |= BDF_GLYPH_WIDTH_CHECK_;
- font->modified = 1;
}
p->row++;
@@ -1626,9 +1615,6 @@
/* Expect the SWIDTH (scalable width) field next. */
if ( _bdf_strncmp( line, "SWIDTH", 6 ) == 0 )
{
- if ( !( p->flags & BDF_ENCODING_ ) )
- goto Missing_Encoding;
-
error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
if ( error )
goto Exit;
@@ -1642,9 +1628,6 @@
/* Expect the DWIDTH (scalable width) field next. */
if ( _bdf_strncmp( line, "DWIDTH", 6 ) == 0 )
{
- if ( !( p->flags & BDF_ENCODING_ ) )
- goto Missing_Encoding;
-
error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
if ( error )
goto Exit;
@@ -1670,9 +1653,6 @@
/* Expect the BBX field next. */
if ( _bdf_strncmp( line, "BBX", 3 ) == 0 )
{
- if ( !( p->flags & BDF_ENCODING_ ) )
- goto Missing_Encoding;
-
error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
if ( error )
goto Exit;
@@ -1720,14 +1700,7 @@
{
glyph->swidth = sw;
- if ( p->glyph_enc == -1 )
- _bdf_set_glyph_modified( font->umod,
- font->unencoded_used - 1 );
- else
- _bdf_set_glyph_modified( font->nmod, glyph->encoding );
-
p->flags |= BDF_SWIDTH_ADJ_;
- font->modified = 1;
}
}
@@ -1829,7 +1802,6 @@
goto Exit;
FT_TRACE2(( "_bdf_parse_properties: " ACMSG1, p->font->bbx.ascent ));
- p->font->modified = 1;
}
if ( bdf_get_font_property( p->font, "FONT_DESCENT" ) == 0 )
@@ -1842,7 +1814,6 @@
goto Exit;
FT_TRACE2(( "_bdf_parse_properties: " ACMSG2, p->font->bbx.descent ));
- p->font->modified = 1;
}
p->flags &= ~BDF_PROPS_;
@@ -1989,7 +1960,7 @@
if ( error )
goto Exit;
p->font->spacing = p->opts->font_spacing;
- p->font->default_char = -1;
+ p->font->default_char = ~0UL;
goto Exit;
}
@@ -2179,8 +2150,6 @@
goto Exit;
FT_TRACE2(( "_bdf_parse_properties: " ACMSG2, p->font->bbx.descent ));
- p->font->modified = 1;
-
*next = _bdf_parse_glyphs;
/* A special return value. */
@@ -2196,11 +2165,11 @@
}
- /*************************************************************************/
- /* */
- /* API. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * API.
+ *
+ */
FT_LOCAL_DEF( FT_Error )
@@ -2246,7 +2215,6 @@
{
FT_TRACE2(( "bdf_load_font: " ACMSG15, p->cnt,
p->font->glyphs_used + p->font->unencoded_used ));
- p->font->modified = 1;
}
/* Once the font has been loaded, adjust the overall font metrics if */
@@ -2259,7 +2227,6 @@
FT_TRACE2(( "bdf_load_font: " ACMSG3,
p->font->bbx.width, p->maxrb - p->minlb ));
p->font->bbx.width = (unsigned short)( p->maxrb - p->minlb );
- p->font->modified = 1;
}
if ( p->font->bbx.x_offset != p->minlb )
@@ -2267,7 +2234,6 @@
FT_TRACE2(( "bdf_load_font: " ACMSG4,
p->font->bbx.x_offset, p->minlb ));
p->font->bbx.x_offset = p->minlb;
- p->font->modified = 1;
}
if ( p->font->bbx.ascent != p->maxas )
@@ -2275,7 +2241,6 @@
FT_TRACE2(( "bdf_load_font: " ACMSG5,
p->font->bbx.ascent, p->maxas ));
p->font->bbx.ascent = p->maxas;
- p->font->modified = 1;
}
if ( p->font->bbx.descent != p->maxds )
@@ -2284,7 +2249,6 @@
p->font->bbx.descent, p->maxds ));
p->font->bbx.descent = p->maxds;
p->font->bbx.y_offset = (short)( -p->maxds );
- p->font->modified = 1;
}
if ( p->maxas + p->maxds != p->font->bbx.height )
@@ -2415,16 +2379,6 @@
FT_FREE( font->glyphs );
FT_FREE( font->unencoded );
- /* Free up the overflow storage if it was used. */
- for ( i = 0, glyphs = font->overflow.glyphs;
- i < font->overflow.glyphs_used; i++, glyphs++ )
- {
- FT_FREE( glyphs->name );
- FT_FREE( glyphs->bitmap );
- }
-
- FT_FREE( font->overflow.glyphs );
-
/* bdf_cleanup */
ft_hash_str_free( &(font->proptbl), memory );
diff --git a/thirdparty/freetype/src/bzip2/ftbzip2.c b/thirdparty/freetype/src/bzip2/ftbzip2.c
index 16019485a9..1fda59b60c 100644
--- a/thirdparty/freetype/src/bzip2/ftbzip2.c
+++ b/thirdparty/freetype/src/bzip2/ftbzip2.c
@@ -1,25 +1,25 @@
-/***************************************************************************/
-/* */
-/* ftbzip2.c */
-/* */
-/* FreeType support for .bz2 compressed files. */
-/* */
-/* This optional component relies on libbz2. It should mainly be used to */
-/* parse compressed PCF fonts, as found with many X11 server */
-/* distributions. */
-/* */
-/* Copyright 2010-2018 by */
-/* Joel Klinghed. */
-/* */
-/* based on `src/gzip/ftgzip.c' */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftbzip2.c
+ *
+ * FreeType support for .bz2 compressed files.
+ *
+ * This optional component relies on libbz2. It should mainly be used to
+ * parse compressed PCF fonts, as found with many X11 server
+ * distributions.
+ *
+ * Copyright (C) 2010-2019 by
+ * Joel Klinghed.
+ *
+ * based on `src/gzip/ftgzip.c'
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -43,10 +43,6 @@
#ifdef FT_CONFIG_OPTION_USE_BZIP2
-#ifdef FT_CONFIG_OPTION_PIC
-#error "bzip2 code does not support PIC yet"
-#endif
-
#define BZ_NO_STDIO /* Do not need FILE */
#include <bzlib.h>
@@ -475,8 +471,8 @@
memory = source->memory;
/*
- * check the header right now; this prevents allocating unnecessary
- * objects when we don't need them
+ * check the header right now; this prevents allocating unnecessary
+ * objects when we don't need them
*/
error = ft_bzip2_check_header( source );
if ( error )
diff --git a/thirdparty/freetype/src/bzip2/rules.mk b/thirdparty/freetype/src/bzip2/rules.mk
index 95954d7520..f365c1f76d 100644
--- a/thirdparty/freetype/src/bzip2/rules.mk
+++ b/thirdparty/freetype/src/bzip2/rules.mk
@@ -2,7 +2,7 @@
# FreeType 2 BZIP2 support configuration rules
#
-# Copyright 2010-2018 by
+# Copyright (C) 2010-2019 by
# Joel Klinghed.
#
# based on `src/lzw/rules.mk'
diff --git a/thirdparty/freetype/src/cache/ftcache.c b/thirdparty/freetype/src/cache/ftcache.c
index 1b425af911..a6a3e63ef0 100644
--- a/thirdparty/freetype/src/cache/ftcache.c
+++ b/thirdparty/freetype/src/cache/ftcache.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftcache.c */
-/* */
-/* The FreeType Caching sub-system (body only). */
-/* */
-/* Copyright 2000-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftcache.c
+ *
+ * The FreeType Caching sub-system (body only).
+ *
+ * Copyright (C) 2000-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#define FT_MAKE_OPTION_SINGLE_OBJECT
diff --git a/thirdparty/freetype/src/cache/ftcbasic.c b/thirdparty/freetype/src/cache/ftcbasic.c
index 994aa12286..a473585ebc 100644
--- a/thirdparty/freetype/src/cache/ftcbasic.c
+++ b/thirdparty/freetype/src/cache/ftcbasic.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftcbasic.c */
-/* */
-/* The FreeType basic cache interface (body). */
-/* */
-/* Copyright 2003-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftcbasic.c
+ *
+ * The FreeType basic cache interface (body).
+ *
+ * Copyright (C) 2003-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -27,11 +27,11 @@
#include "ftccback.h"
#include "ftcerror.h"
-#define FT_COMPONENT trace_cache
+#define FT_COMPONENT cache
/*
- * Basic Families
+ * Basic Families
*
*/
typedef struct FTC_BasicAttrRec_
diff --git a/thirdparty/freetype/src/cache/ftccache.c b/thirdparty/freetype/src/cache/ftccache.c
index 12ec585a25..f38ca44ddd 100644
--- a/thirdparty/freetype/src/cache/ftccache.c
+++ b/thirdparty/freetype/src/cache/ftccache.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftccache.c */
-/* */
-/* The FreeType internal cache interface (body). */
-/* */
-/* Copyright 2000-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftccache.c
+ *
+ * The FreeType internal cache interface (body).
+ *
+ * Copyright (C) 2000-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -25,7 +25,7 @@
#include "ftcerror.h"
#undef FT_COMPONENT
-#define FT_COMPONENT trace_cache
+#define FT_COMPONENT cache
#define FTC_HASH_MAX_LOAD 2
diff --git a/thirdparty/freetype/src/cache/ftccache.h b/thirdparty/freetype/src/cache/ftccache.h
index 859c547e46..140ceadb11 100644
--- a/thirdparty/freetype/src/cache/ftccache.h
+++ b/thirdparty/freetype/src/cache/ftccache.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftccache.h */
-/* */
-/* FreeType internal cache interface (specification). */
-/* */
-/* Copyright 2000-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftccache.h
+ *
+ * FreeType internal cache interface (specification).
+ *
+ * Copyright (C) 2000-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTCCACHE_H_
@@ -42,17 +42,17 @@ FT_BEGIN_HEADER
/*************************************************************************/
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* Each cache controls one or more cache nodes. Each node is part of */
- /* the global_lru list of the manager. Its `data' field however is used */
- /* as a reference count for now. */
- /* */
- /* A node can be anything, depending on the type of information held by */
- /* the cache. It can be an individual glyph image, a set of bitmaps */
- /* glyphs for a given size, some metrics, etc. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * Each cache controls one or more cache nodes. Each node is part of
+ * the global_lru list of the manager. Its `data' field however is used
+ * as a reference count for now.
+ *
+ * A node can be anything, depending on the type of information held by
+ * the cache. It can be an individual glyph image, a set of bitmaps
+ * glyphs for a given size, some metrics, etc.
+ *
+ */
/* structure size should be 20 bytes on 32-bits machines */
typedef struct FTC_NodeRec_
@@ -302,11 +302,11 @@ FT_BEGIN_HEADER
*
* Example:
*
- * {
- * FTC_CACHE_TRYLOOP( cache )
- * error = load_data( ... );
- * FTC_CACHE_TRYLOOP_END()
- * }
+ * {
+ * FTC_CACHE_TRYLOOP( cache )
+ * error = load_data( ... );
+ * FTC_CACHE_TRYLOOP_END()
+ * }
*
*/
#define FTC_CACHE_TRYLOOP( cache ) \
diff --git a/thirdparty/freetype/src/cache/ftccback.h b/thirdparty/freetype/src/cache/ftccback.h
index e51d8d6e55..9321bc3d4e 100644
--- a/thirdparty/freetype/src/cache/ftccback.h
+++ b/thirdparty/freetype/src/cache/ftccback.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftccback.h */
-/* */
-/* Callback functions of the caching sub-system (specification only). */
-/* */
-/* Copyright 2004-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftccback.h
+ *
+ * Callback functions of the caching sub-system (specification only).
+ *
+ * Copyright (C) 2004-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTCCBACK_H_
#define FTCCBACK_H_
diff --git a/thirdparty/freetype/src/cache/ftccmap.c b/thirdparty/freetype/src/cache/ftccmap.c
index d20b0f48fe..76ba10e3e9 100644
--- a/thirdparty/freetype/src/cache/ftccmap.c
+++ b/thirdparty/freetype/src/cache/ftccmap.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftccmap.c */
-/* */
-/* FreeType CharMap cache (body) */
-/* */
-/* Copyright 2000-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftccmap.c
+ *
+ * FreeType CharMap cache (body)
+ *
+ * Copyright (C) 2000-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -28,21 +28,21 @@
#include "ftcerror.h"
#undef FT_COMPONENT
-#define FT_COMPONENT trace_cache
-
-
- /*************************************************************************/
- /* */
- /* Each FTC_CMapNode contains a simple array to map a range of character */
- /* codes to equivalent glyph indices. */
- /* */
- /* For now, the implementation is very basic: Each node maps a range of */
- /* 128 consecutive character codes to their corresponding glyph indices. */
- /* */
- /* We could do more complex things, but I don't think it is really very */
- /* useful. */
- /* */
- /*************************************************************************/
+#define FT_COMPONENT cache
+
+
+ /**************************************************************************
+ *
+ * Each FTC_CMapNode contains a simple array to map a range of character
+ * codes to equivalent glyph indices.
+ *
+ * For now, the implementation is very basic: Each node maps a range of
+ * 128 consecutive character codes to their corresponding glyph indices.
+ *
+ * We could do more complex things, but I don't think it is really very
+ * useful.
+ *
+ */
/* number of glyph indices / character code per node */
diff --git a/thirdparty/freetype/src/cache/ftcerror.h b/thirdparty/freetype/src/cache/ftcerror.h
index a26cd5935b..e2d6417180 100644
--- a/thirdparty/freetype/src/cache/ftcerror.h
+++ b/thirdparty/freetype/src/cache/ftcerror.h
@@ -1,27 +1,27 @@
-/***************************************************************************/
-/* */
-/* ftcerror.h */
-/* */
-/* Caching sub-system error codes (specification only). */
-/* */
-/* Copyright 2001-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* This file is used to define the caching sub-system error enumeration */
- /* constants. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * ftcerror.h
+ *
+ * Caching sub-system error codes (specification only).
+ *
+ * Copyright (C) 2001-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * This file is used to define the caching sub-system error enumeration
+ * constants.
+ *
+ */
#ifndef FTCERROR_H_
#define FTCERROR_H_
diff --git a/thirdparty/freetype/src/cache/ftcglyph.c b/thirdparty/freetype/src/cache/ftcglyph.c
index 782cc0ed09..2a0e97d4af 100644
--- a/thirdparty/freetype/src/cache/ftcglyph.c
+++ b/thirdparty/freetype/src/cache/ftcglyph.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftcglyph.c */
-/* */
-/* FreeType Glyph Image (FT_Glyph) cache (body). */
-/* */
-/* Copyright 2000-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftcglyph.c
+ *
+ * FreeType Glyph Image (FT_Glyph) cache (body).
+ *
+ * Copyright (C) 2000-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
diff --git a/thirdparty/freetype/src/cache/ftcglyph.h b/thirdparty/freetype/src/cache/ftcglyph.h
index 23c24d223f..5a1f0e2a74 100644
--- a/thirdparty/freetype/src/cache/ftcglyph.h
+++ b/thirdparty/freetype/src/cache/ftcglyph.h
@@ -1,101 +1,101 @@
-/***************************************************************************/
-/* */
-/* ftcglyph.h */
-/* */
-/* FreeType abstract glyph cache (specification). */
-/* */
-/* Copyright 2000-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftcglyph.h
+ *
+ * FreeType abstract glyph cache (specification).
+ *
+ * Copyright (C) 2000-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
/*
*
- * FTC_GCache is an _abstract_ cache object optimized to store glyph
- * data. It works as follows:
+ * FTC_GCache is an _abstract_ cache object optimized to store glyph
+ * data. It works as follows:
*
- * - It manages FTC_GNode objects. Each one of them can hold one or more
- * glyph `items'. Item types are not specified in the FTC_GCache but
- * in classes that extend it.
+ * - It manages FTC_GNode objects. Each one of them can hold one or more
+ * glyph `items'. Item types are not specified in the FTC_GCache but
+ * in classes that extend it.
*
- * - Glyph attributes, like face ID, character size, render mode, etc.,
- * can be grouped into abstract `glyph families'. This avoids storing
- * the attributes within the FTC_GCache, since it is likely that many
- * FTC_GNodes will belong to the same family in typical uses.
+ * - Glyph attributes, like face ID, character size, render mode, etc.,
+ * can be grouped into abstract `glyph families'. This avoids storing
+ * the attributes within the FTC_GCache, since it is likely that many
+ * FTC_GNodes will belong to the same family in typical uses.
*
- * - Each FTC_GNode is thus an FTC_Node with two additional fields:
+ * - Each FTC_GNode is thus an FTC_Node with two additional fields:
*
- * * gindex: A glyph index, or the first index in a glyph range.
- * * family: A pointer to a glyph `family'.
+ * * gindex: A glyph index, or the first index in a glyph range.
+ * * family: A pointer to a glyph `family'.
*
- * - Family types are not fully specific in the FTC_Family type, but
- * by classes that extend it.
+ * - Family types are not fully specific in the FTC_Family type, but
+ * by classes that extend it.
*
- * Note that both FTC_ImageCache and FTC_SBitCache extend FTC_GCache.
- * They share an FTC_Family sub-class called FTC_BasicFamily which is
- * used to store the following data: face ID, pixel/point sizes, load
- * flags. For more details see the file `src/cache/ftcbasic.c'.
+ * Note that both FTC_ImageCache and FTC_SBitCache extend FTC_GCache.
+ * They share an FTC_Family sub-class called FTC_BasicFamily which is
+ * used to store the following data: face ID, pixel/point sizes, load
+ * flags. For more details see the file `src/cache/ftcbasic.c'.
*
- * Client applications can extend FTC_GNode with their own FTC_GNode
- * and FTC_Family sub-classes to implement more complex caches (e.g.,
- * handling automatic synthesis, like obliquing & emboldening, colored
- * glyphs, etc.).
+ * Client applications can extend FTC_GNode with their own FTC_GNode
+ * and FTC_Family sub-classes to implement more complex caches (e.g.,
+ * handling automatic synthesis, like obliquing & emboldening, colored
+ * glyphs, etc.).
*
- * See also the FTC_ICache & FTC_SCache classes in `ftcimage.h' and
- * `ftcsbits.h', which both extend FTC_GCache with additional
- * optimizations.
+ * See also the FTC_ICache & FTC_SCache classes in `ftcimage.h' and
+ * `ftcsbits.h', which both extend FTC_GCache with additional
+ * optimizations.
*
- * A typical FTC_GCache implementation must provide at least the
- * following:
+ * A typical FTC_GCache implementation must provide at least the
+ * following:
*
- * - FTC_GNode sub-class, e.g. MyNode, with relevant methods:
- * my_node_new (must call FTC_GNode_Init)
- * my_node_free (must call FTC_GNode_Done)
- * my_node_compare (must call FTC_GNode_Compare)
- * my_node_remove_faceid (must call ftc_gnode_unselect in case
- * of match)
+ * - FTC_GNode sub-class, e.g. MyNode, with relevant methods:
+ * my_node_new (must call FTC_GNode_Init)
+ * my_node_free (must call FTC_GNode_Done)
+ * my_node_compare (must call FTC_GNode_Compare)
+ * my_node_remove_faceid (must call ftc_gnode_unselect in case
+ * of match)
*
- * - FTC_Family sub-class, e.g. MyFamily, with relevant methods:
- * my_family_compare
- * my_family_init
- * my_family_reset (optional)
- * my_family_done
+ * - FTC_Family sub-class, e.g. MyFamily, with relevant methods:
+ * my_family_compare
+ * my_family_init
+ * my_family_reset (optional)
+ * my_family_done
*
- * - FTC_GQuery sub-class, e.g. MyQuery, to hold cache-specific query
- * data.
+ * - FTC_GQuery sub-class, e.g. MyQuery, to hold cache-specific query
+ * data.
*
- * - Constant structures for a FTC_GNodeClass.
+ * - Constant structures for a FTC_GNodeClass.
*
- * - MyCacheNew() can be implemented easily as a call to the convenience
- * function FTC_GCache_New.
+ * - MyCacheNew() can be implemented easily as a call to the convenience
+ * function FTC_GCache_New.
*
- * - MyCacheLookup with a call to FTC_GCache_Lookup. This function will
- * automatically:
+ * - MyCacheLookup with a call to FTC_GCache_Lookup. This function will
+ * automatically:
*
- * - Search for the corresponding family in the cache, or create
- * a new one if necessary. Put it in FTC_GQUERY(myquery).family
+ * - Search for the corresponding family in the cache, or create
+ * a new one if necessary. Put it in FTC_GQUERY(myquery).family
*
- * - Call FTC_Cache_Lookup.
+ * - Call FTC_Cache_Lookup.
*
- * If it returns NULL, you should create a new node, then call
- * ftc_cache_add as usual.
+ * If it returns NULL, you should create a new node, then call
+ * ftc_cache_add as usual.
*/
- /*************************************************************************/
- /* */
- /* Important: The functions defined in this file are only used to */
- /* implement an abstract glyph cache class. You need to */
- /* provide additional logic to implement a complete cache. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * Important: The functions defined in this file are only used to
+ * implement an abstract glyph cache class. You need to
+ * provide additional logic to implement a complete cache.
+ *
+ */
/*************************************************************************/
@@ -125,11 +125,11 @@ FT_BEGIN_HEADER
/*
- * We can group glyphs into `families'. Each family correspond to a
- * given face ID, character size, transform, etc.
+ * We can group glyphs into `families'. Each family correspond to a
+ * given face ID, character size, transform, etc.
*
- * Families are implemented as MRU list nodes. They are
- * reference-counted.
+ * Families are implemented as MRU list nodes. They are
+ * reference-counted.
*/
typedef struct FTC_FamilyRec_
@@ -167,12 +167,12 @@ FT_BEGIN_HEADER
#define FTC_GQUERY( x ) ( (FTC_GQuery)(x) )
- /*************************************************************************/
- /* */
- /* These functions are exported so that they can be called from */
- /* user-provided cache classes; otherwise, they are really part of the */
- /* cache sub-system internals. */
- /* */
+ /**************************************************************************
+ *
+ * These functions are exported so that they can be called from
+ * user-provided cache classes; otherwise, they are really part of the
+ * cache sub-system internals.
+ */
/* must be called by derived FTC_Node_InitFunc routines */
FT_LOCAL( void )
diff --git a/thirdparty/freetype/src/cache/ftcimage.c b/thirdparty/freetype/src/cache/ftcimage.c
index 77a100153e..9e64d51a22 100644
--- a/thirdparty/freetype/src/cache/ftcimage.c
+++ b/thirdparty/freetype/src/cache/ftcimage.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftcimage.c */
-/* */
-/* FreeType Image cache (body). */
-/* */
-/* Copyright 2000-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftcimage.c
+ *
+ * FreeType Image cache (body).
+ *
+ * Copyright (C) 2000-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
diff --git a/thirdparty/freetype/src/cache/ftcimage.h b/thirdparty/freetype/src/cache/ftcimage.h
index 24a221053b..dcb101fabc 100644
--- a/thirdparty/freetype/src/cache/ftcimage.h
+++ b/thirdparty/freetype/src/cache/ftcimage.h
@@ -1,35 +1,35 @@
-/***************************************************************************/
-/* */
-/* ftcimage.h */
-/* */
-/* FreeType Generic Image cache (specification) */
-/* */
-/* Copyright 2000-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftcimage.h
+ *
+ * FreeType Generic Image cache (specification)
+ *
+ * Copyright (C) 2000-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
/*
- * FTC_ICache is an _abstract_ cache used to store a single FT_Glyph
- * image per cache node.
+ * FTC_ICache is an _abstract_ cache used to store a single FT_Glyph
+ * image per cache node.
*
- * FTC_ICache extends FTC_GCache. For an implementation example,
- * see FTC_ImageCache in `src/cache/ftbasic.c'.
+ * FTC_ICache extends FTC_GCache. For an implementation example,
+ * see FTC_ImageCache in `src/cache/ftbasic.c'.
*/
- /*************************************************************************/
- /* */
- /* Each image cache really manages FT_Glyph objects. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * Each image cache really manages FT_Glyph objects.
+ *
+ */
#ifndef FTCIMAGE_H_
diff --git a/thirdparty/freetype/src/cache/ftcmanag.c b/thirdparty/freetype/src/cache/ftcmanag.c
index 2bcd9df502..bd585968e3 100644
--- a/thirdparty/freetype/src/cache/ftcmanag.c
+++ b/thirdparty/freetype/src/cache/ftcmanag.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftcmanag.c */
-/* */
-/* FreeType Cache Manager (body). */
-/* */
-/* Copyright 2000-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftcmanag.c
+ *
+ * FreeType Cache Manager (body).
+ *
+ * Copyright (C) 2000-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -26,13 +26,9 @@
#include "ftccback.h"
#include "ftcerror.h"
-#ifdef FT_CONFIG_OPTION_PIC
-#error "cache system does not support PIC yet"
-#endif
-
#undef FT_COMPONENT
-#define FT_COMPONENT trace_cache
+#define FT_COMPONENT cache
static FT_Error
diff --git a/thirdparty/freetype/src/cache/ftcmanag.h b/thirdparty/freetype/src/cache/ftcmanag.h
index b4b4755356..60c66c8fc8 100644
--- a/thirdparty/freetype/src/cache/ftcmanag.h
+++ b/thirdparty/freetype/src/cache/ftcmanag.h
@@ -1,47 +1,47 @@
-/***************************************************************************/
-/* */
-/* ftcmanag.h */
-/* */
-/* FreeType Cache Manager (specification). */
-/* */
-/* Copyright 2000-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* A cache manager is in charge of the following: */
- /* */
- /* - Maintain a mapping between generic FTC_FaceIDs and live FT_Face */
- /* objects. The mapping itself is performed through a user-provided */
- /* callback. However, the manager maintains a small cache of FT_Face */
- /* and FT_Size objects in order to speed up things considerably. */
- /* */
- /* - Manage one or more cache objects. Each cache is in charge of */
- /* holding a varying number of `cache nodes'. Each cache node */
- /* represents a minimal amount of individually accessible cached */
- /* data. For example, a cache node can be an FT_Glyph image */
- /* containing a vector outline, or some glyph metrics, or anything */
- /* else. */
- /* */
- /* Each cache node has a certain size in bytes that is added to the */
- /* total amount of `cache memory' within the manager. */
- /* */
- /* All cache nodes are located in a global LRU list, where the oldest */
- /* node is at the tail of the list. */
- /* */
- /* Each node belongs to a single cache, and includes a reference */
- /* count to avoid destroying it (due to caching). */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * ftcmanag.h
+ *
+ * FreeType Cache Manager (specification).
+ *
+ * Copyright (C) 2000-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * A cache manager is in charge of the following:
+ *
+ * - Maintain a mapping between generic FTC_FaceIDs and live FT_Face
+ * objects. The mapping itself is performed through a user-provided
+ * callback. However, the manager maintains a small cache of FT_Face
+ * and FT_Size objects in order to speed up things considerably.
+ *
+ * - Manage one or more cache objects. Each cache is in charge of
+ * holding a varying number of `cache nodes'. Each cache node
+ * represents a minimal amount of individually accessible cached
+ * data. For example, a cache node can be an FT_Glyph image
+ * containing a vector outline, or some glyph metrics, or anything
+ * else.
+ *
+ * Each cache node has a certain size in bytes that is added to the
+ * total amount of `cache memory' within the manager.
+ *
+ * All cache nodes are located in a global LRU list, where the oldest
+ * node is at the tail of the list.
+ *
+ * Each node belongs to a single cache, and includes a reference
+ * count to avoid destroying it (due to caching).
+ *
+ */
/*************************************************************************/
@@ -72,12 +72,12 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* <Section> */
- /* cache_subsystem */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * @Section:
+ * cache_subsystem
+ *
+ */
#define FTC_MAX_FACES_DEFAULT 2
@@ -110,27 +110,28 @@ FT_BEGIN_HEADER
} FTC_ManagerRec;
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FTC_Manager_Compress */
- /* */
- /* <Description> */
- /* This function is used to check the state of the cache manager if */
- /* its `num_bytes' field is greater than its `max_bytes' field. It */
- /* will flush as many old cache nodes as possible (ignoring cache */
- /* nodes with a non-zero reference count). */
- /* */
- /* <InOut> */
- /* manager :: A handle to the cache manager. */
- /* */
- /* <Note> */
- /* Client applications should not call this function directly. It is */
- /* normally invoked by specific cache implementations. */
- /* */
- /* The reason this function is exported is to allow client-specific */
- /* cache classes. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * FTC_Manager_Compress
+ *
+ * @Description:
+ * This function is used to check the state of the cache manager if
+ * its `num_bytes' field is greater than its `max_bytes' field. It
+ * will flush as many old cache nodes as possible (ignoring cache
+ * nodes with a non-zero reference count).
+ *
+ * @InOut:
+ * manager ::
+ * A handle to the cache manager.
+ *
+ * @Note:
+ * Client applications should not call this function directly. It is
+ * normally invoked by specific cache implementations.
+ *
+ * The reason this function is exported is to allow client-specific
+ * cache classes.
+ */
FT_LOCAL( void )
FTC_Manager_Compress( FTC_Manager manager );
diff --git a/thirdparty/freetype/src/cache/ftcmru.c b/thirdparty/freetype/src/cache/ftcmru.c
index 1087be4d89..18a7b80054 100644
--- a/thirdparty/freetype/src/cache/ftcmru.c
+++ b/thirdparty/freetype/src/cache/ftcmru.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftcmru.c */
-/* */
-/* FreeType MRU support (body). */
-/* */
-/* Copyright 2003-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftcmru.c
+ *
+ * FreeType MRU support (body).
+ *
+ * Copyright (C) 2003-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
diff --git a/thirdparty/freetype/src/cache/ftcmru.h b/thirdparty/freetype/src/cache/ftcmru.h
index 82396b917d..58721ed340 100644
--- a/thirdparty/freetype/src/cache/ftcmru.h
+++ b/thirdparty/freetype/src/cache/ftcmru.h
@@ -1,43 +1,43 @@
-/***************************************************************************/
-/* */
-/* ftcmru.h */
-/* */
-/* Simple MRU list-cache (specification). */
-/* */
-/* Copyright 2000-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* An MRU is a list that cannot hold more than a certain number of */
- /* elements (`max_elements'). All elements in the list are sorted in */
- /* least-recently-used order, i.e., the `oldest' element is at the tail */
- /* of the list. */
- /* */
- /* When doing a lookup (either through `Lookup()' or `Lookup_Node()'), */
- /* the list is searched for an element with the corresponding key. If */
- /* it is found, the element is moved to the head of the list and is */
- /* returned. */
- /* */
- /* If no corresponding element is found, the lookup routine will try to */
- /* obtain a new element with the relevant key. If the list is already */
- /* full, the oldest element from the list is discarded and replaced by a */
- /* new one; a new element is added to the list otherwise. */
- /* */
- /* Note that it is possible to pre-allocate the element list nodes. */
- /* This is handy if `max_elements' is sufficiently small, as it saves */
- /* allocations/releases during the lookup process. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * ftcmru.h
+ *
+ * Simple MRU list-cache (specification).
+ *
+ * Copyright (C) 2000-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * An MRU is a list that cannot hold more than a certain number of
+ * elements (`max_elements'). All elements in the list are sorted in
+ * least-recently-used order, i.e., the `oldest' element is at the tail
+ * of the list.
+ *
+ * When doing a lookup (either through `Lookup()' or `Lookup_Node()'),
+ * the list is searched for an element with the corresponding key. If
+ * it is found, the element is moved to the head of the list and is
+ * returned.
+ *
+ * If no corresponding element is found, the lookup routine will try to
+ * obtain a new element with the relevant key. If the list is already
+ * full, the oldest element from the list is discarded and replaced by a
+ * new one; a new element is added to the list otherwise.
+ *
+ * Note that it is possible to pre-allocate the element list nodes.
+ * This is handy if `max_elements' is sufficiently small, as it saves
+ * allocations/releases during the lookup process.
+ *
+ */
#ifndef FTCMRU_H_
diff --git a/thirdparty/freetype/src/cache/ftcsbits.c b/thirdparty/freetype/src/cache/ftcsbits.c
index 018f1ecdb7..06b46c896e 100644
--- a/thirdparty/freetype/src/cache/ftcsbits.c
+++ b/thirdparty/freetype/src/cache/ftcsbits.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftcsbits.c */
-/* */
-/* FreeType sbits manager (body). */
-/* */
-/* Copyright 2000-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftcsbits.c
+ *
+ * FreeType sbits manager (body).
+ *
+ * Copyright (C) 2000-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -27,7 +27,7 @@
#include "ftcerror.h"
#undef FT_COMPONENT
-#define FT_COMPONENT trace_cache
+#define FT_COMPONENT cache
/*************************************************************************/
@@ -91,14 +91,14 @@
/*
- * This function tries to load a small bitmap within a given FTC_SNode.
- * Note that it returns a non-zero error code _only_ in the case of
- * out-of-memory condition. For all other errors (e.g., corresponding
- * to a bad font file), this function will mark the sbit as `unavailable'
- * and return a value of 0.
+ * This function tries to load a small bitmap within a given FTC_SNode.
+ * Note that it returns a non-zero error code _only_ in the case of
+ * out-of-memory condition. For all other errors (e.g., corresponding
+ * to a bad font file), this function will mark the sbit as `unavailable'
+ * and return a value of 0.
*
- * You should also read the comment within the @ftc_snode_compare
- * function below to see how out-of-memory is handled during a lookup.
+ * You should also read the comment within the @ftc_snode_compare
+ * function below to see how out-of-memory is handled during a lookup.
*/
static FT_Error
ftc_snode_load( FTC_SNode snode,
@@ -347,34 +347,34 @@
/*
- * The following code illustrates what to do when you want to
- * perform operations that may fail within a lookup function.
+ * The following code illustrates what to do when you want to
+ * perform operations that may fail within a lookup function.
*
- * Here, we want to load a small bitmap on-demand; we thus
- * need to call the `ftc_snode_load' function which may return
- * a non-zero error code only when we are out of memory (OOM).
+ * Here, we want to load a small bitmap on-demand; we thus
+ * need to call the `ftc_snode_load' function which may return
+ * a non-zero error code only when we are out of memory (OOM).
*
- * The correct thing to do is to use @FTC_CACHE_TRYLOOP and
- * @FTC_CACHE_TRYLOOP_END in order to implement a retry loop
- * that is capable of flushing the cache incrementally when
- * an OOM errors occur.
+ * The correct thing to do is to use @FTC_CACHE_TRYLOOP and
+ * @FTC_CACHE_TRYLOOP_END in order to implement a retry loop
+ * that is capable of flushing the cache incrementally when
+ * an OOM errors occur.
*
- * However, we need to `lock' the node before this operation to
- * prevent it from being flushed within the loop.
+ * However, we need to `lock' the node before this operation to
+ * prevent it from being flushed within the loop.
*
- * When we exit the loop, we unlock the node, then check the `error'
- * variable. If it is non-zero, this means that the cache was
- * completely flushed and that no usable memory was found to load
- * the bitmap.
+ * When we exit the loop, we unlock the node, then check the `error'
+ * variable. If it is non-zero, this means that the cache was
+ * completely flushed and that no usable memory was found to load
+ * the bitmap.
*
- * We then prefer to return a value of 0 (i.e., NO MATCH). This
- * ensures that the caller will try to allocate a new node.
- * This operation consequently _fail_ and the lookup function
- * returns the appropriate OOM error code.
+ * We then prefer to return a value of 0 (i.e., NO MATCH). This
+ * ensures that the caller will try to allocate a new node.
+ * This operation consequently _fail_ and the lookup function
+ * returns the appropriate OOM error code.
*
- * Note that `buffer == NULL && width == 255' is a hack used to
- * tag `unavailable' bitmaps in the array. We should never try
- * to load these.
+ * Note that `buffer == NULL && width == 255' is a hack used to
+ * tag `unavailable' bitmaps in the array. We should never try
+ * to load these.
*
*/
diff --git a/thirdparty/freetype/src/cache/ftcsbits.h b/thirdparty/freetype/src/cache/ftcsbits.h
index 206a1bb3fc..f1b71c2835 100644
--- a/thirdparty/freetype/src/cache/ftcsbits.h
+++ b/thirdparty/freetype/src/cache/ftcsbits.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftcsbits.h */
-/* */
-/* A small-bitmap cache (specification). */
-/* */
-/* Copyright 2000-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftcsbits.h
+ *
+ * A small-bitmap cache (specification).
+ *
+ * Copyright (C) 2000-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTCSBITS_H_
diff --git a/thirdparty/freetype/src/cache/rules.mk b/thirdparty/freetype/src/cache/rules.mk
index 558935976d..abcb242239 100644
--- a/thirdparty/freetype/src/cache/rules.mk
+++ b/thirdparty/freetype/src/cache/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 2000-2018 by
+# Copyright (C) 2000-2019 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/cff/cf2arrst.c b/thirdparty/freetype/src/cff/cf2arrst.c
deleted file mode 100644
index 6796450fe1..0000000000
--- a/thirdparty/freetype/src/cff/cf2arrst.c
+++ /dev/null
@@ -1,241 +0,0 @@
-/***************************************************************************/
-/* */
-/* cf2arrst.c */
-/* */
-/* Adobe's code for Array Stacks (body). */
-/* */
-/* Copyright 2007-2013 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
-
-
-#include "cf2ft.h"
-#include FT_INTERNAL_DEBUG_H
-
-#include "cf2glue.h"
-#include "cf2arrst.h"
-
-#include "cf2error.h"
-
-
- /*
- * CF2_ArrStack uses an error pointer, to enable shared errors.
- * Shared errors are necessary when multiple objects allow the program
- * to continue after detecting errors. Only the first error should be
- * recorded.
- */
-
- FT_LOCAL_DEF( void )
- cf2_arrstack_init( CF2_ArrStack arrstack,
- FT_Memory memory,
- FT_Error* error,
- size_t sizeItem )
- {
- FT_ASSERT( arrstack );
-
- /* initialize the structure */
- arrstack->memory = memory;
- arrstack->error = error;
- arrstack->sizeItem = sizeItem;
- arrstack->allocated = 0;
- arrstack->chunk = 10; /* chunks of 10 items */
- arrstack->count = 0;
- arrstack->totalSize = 0;
- arrstack->ptr = NULL;
- }
-
-
- FT_LOCAL_DEF( void )
- cf2_arrstack_finalize( CF2_ArrStack arrstack )
- {
- FT_Memory memory = arrstack->memory; /* for FT_FREE */
-
-
- FT_ASSERT( arrstack );
-
- arrstack->allocated = 0;
- arrstack->count = 0;
- arrstack->totalSize = 0;
-
- /* free the data buffer */
- FT_FREE( arrstack->ptr );
- }
-
-
- /* allocate or reallocate the buffer size; */
- /* return false on memory error */
- static FT_Bool
- cf2_arrstack_setNumElements( CF2_ArrStack arrstack,
- size_t numElements )
- {
- FT_ASSERT( arrstack );
-
- {
- FT_Error error = FT_Err_Ok; /* for FT_REALLOC */
- FT_Memory memory = arrstack->memory; /* for FT_REALLOC */
-
- size_t newSize = numElements * arrstack->sizeItem;
-
-
- if ( numElements > FT_LONG_MAX / arrstack->sizeItem )
- goto exit;
-
-
- FT_ASSERT( newSize > 0 ); /* avoid realloc with zero size */
-
- if ( !FT_REALLOC( arrstack->ptr, arrstack->totalSize, newSize ) )
- {
- arrstack->allocated = numElements;
- arrstack->totalSize = newSize;
-
- if ( arrstack->count > numElements )
- {
- /* we truncated the list! */
- CF2_SET_ERROR( arrstack->error, Stack_Overflow );
- arrstack->count = numElements;
- return FALSE;
- }
-
- return TRUE; /* success */
- }
- }
-
- exit:
- /* if there's not already an error, store this one */
- CF2_SET_ERROR( arrstack->error, Out_Of_Memory );
-
- return FALSE;
- }
-
-
- /* set the count, ensuring allocation is sufficient */
- FT_LOCAL_DEF( void )
- cf2_arrstack_setCount( CF2_ArrStack arrstack,
- size_t numElements )
- {
- FT_ASSERT( arrstack );
-
- if ( numElements > arrstack->allocated )
- {
- /* expand the allocation first */
- if ( !cf2_arrstack_setNumElements( arrstack, numElements ) )
- return;
- }
-
- arrstack->count = numElements;
- }
-
-
- /* clear the count */
- FT_LOCAL_DEF( void )
- cf2_arrstack_clear( CF2_ArrStack arrstack )
- {
- FT_ASSERT( arrstack );
-
- arrstack->count = 0;
- }
-
-
- /* current number of items */
- FT_LOCAL_DEF( size_t )
- cf2_arrstack_size( const CF2_ArrStack arrstack )
- {
- FT_ASSERT( arrstack );
-
- return arrstack->count;
- }
-
-
- FT_LOCAL_DEF( void* )
- cf2_arrstack_getBuffer( const CF2_ArrStack arrstack )
- {
- FT_ASSERT( arrstack );
-
- return arrstack->ptr;
- }
-
-
- /* return pointer to the given element */
- FT_LOCAL_DEF( void* )
- cf2_arrstack_getPointer( const CF2_ArrStack arrstack,
- size_t idx )
- {
- void* newPtr;
-
-
- FT_ASSERT( arrstack );
-
- if ( idx >= arrstack->count )
- {
- /* overflow */
- CF2_SET_ERROR( arrstack->error, Stack_Overflow );
- idx = 0; /* choose safe default */
- }
-
- newPtr = (FT_Byte*)arrstack->ptr + idx * arrstack->sizeItem;
-
- return newPtr;
- }
-
-
- /* push (append) an element at the end of the list; */
- /* return false on memory error */
- /* TODO: should there be a length param for extra checking? */
- FT_LOCAL_DEF( void )
- cf2_arrstack_push( CF2_ArrStack arrstack,
- const void* ptr )
- {
- FT_ASSERT( arrstack );
-
- if ( arrstack->count == arrstack->allocated )
- {
- /* grow the buffer by one chunk */
- if ( !cf2_arrstack_setNumElements(
- arrstack, arrstack->allocated + arrstack->chunk ) )
- {
- /* on error, ignore the push */
- return;
- }
- }
-
- FT_ASSERT( ptr );
-
- {
- size_t offset = arrstack->count * arrstack->sizeItem;
- void* newPtr = (FT_Byte*)arrstack->ptr + offset;
-
-
- FT_MEM_COPY( newPtr, ptr, arrstack->sizeItem );
- arrstack->count += 1;
- }
- }
-
-
-/* END */
diff --git a/thirdparty/freetype/src/cff/cf2arrst.h b/thirdparty/freetype/src/cff/cf2arrst.h
deleted file mode 100644
index 3c21a3b672..0000000000
--- a/thirdparty/freetype/src/cff/cf2arrst.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/***************************************************************************/
-/* */
-/* cf2arrst.h */
-/* */
-/* Adobe's code for Array Stacks (specification). */
-/* */
-/* Copyright 2007-2013 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
-
-
-#ifndef CF2ARRST_H_
-#define CF2ARRST_H_
-
-
-#include "cf2error.h"
-
-
-FT_BEGIN_HEADER
-
-
- /* need to define the struct here (not opaque) so it can be allocated by */
- /* clients */
- typedef struct CF2_ArrStackRec_
- {
- FT_Memory memory;
- FT_Error* error;
-
- size_t sizeItem; /* bytes per element */
- size_t allocated; /* items allocated */
- size_t chunk; /* allocation increment in items */
- size_t count; /* number of elements allocated */
- size_t totalSize; /* total bytes allocated */
-
- void* ptr; /* ptr to data */
-
- } CF2_ArrStackRec, *CF2_ArrStack;
-
-
- FT_LOCAL( void )
- cf2_arrstack_init( CF2_ArrStack arrstack,
- FT_Memory memory,
- FT_Error* error,
- size_t sizeItem );
- FT_LOCAL( void )
- cf2_arrstack_finalize( CF2_ArrStack arrstack );
-
- FT_LOCAL( void )
- cf2_arrstack_setCount( CF2_ArrStack arrstack,
- size_t numElements );
- FT_LOCAL( void )
- cf2_arrstack_clear( CF2_ArrStack arrstack );
- FT_LOCAL( size_t )
- cf2_arrstack_size( const CF2_ArrStack arrstack );
-
- FT_LOCAL( void* )
- cf2_arrstack_getBuffer( const CF2_ArrStack arrstack );
- FT_LOCAL( void* )
- cf2_arrstack_getPointer( const CF2_ArrStack arrstack,
- size_t idx );
-
- FT_LOCAL( void )
- cf2_arrstack_push( CF2_ArrStack arrstack,
- const void* ptr );
-
-
-FT_END_HEADER
-
-
-#endif /* CF2ARRST_H_ */
-
-
-/* END */
diff --git a/thirdparty/freetype/src/cff/cf2blues.c b/thirdparty/freetype/src/cff/cf2blues.c
deleted file mode 100644
index c491f2f9e5..0000000000
--- a/thirdparty/freetype/src/cff/cf2blues.c
+++ /dev/null
@@ -1,582 +0,0 @@
-/***************************************************************************/
-/* */
-/* cf2blues.c */
-/* */
-/* Adobe's code for handling Blue Zones (body). */
-/* */
-/* Copyright 2009-2014 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
-
-
-#include "cf2ft.h"
-#include FT_INTERNAL_DEBUG_H
-
-#include "cf2blues.h"
-#include "cf2hints.h"
-#include "cf2font.h"
-
-
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
-#undef FT_COMPONENT
-#define FT_COMPONENT trace_cf2blues
-
-
- /*
- * For blue values, the FreeType parser produces an array of integers,
- * while the Adobe CFF engine produces an array of fixed.
- * Define a macro to convert FreeType to fixed.
- */
-#define cf2_blueToFixed( x ) cf2_intToFixed( x )
-
-
- FT_LOCAL_DEF( void )
- cf2_blues_init( CF2_Blues blues,
- CF2_Font font )
- {
- /* pointer to parsed font object */
- CFF_Decoder* decoder = font->decoder;
-
- CF2_Fixed zoneHeight;
- CF2_Fixed maxZoneHeight = 0;
- CF2_Fixed csUnitsPerPixel;
-
- size_t numBlueValues;
- size_t numOtherBlues;
- size_t numFamilyBlues;
- size_t numFamilyOtherBlues;
-
- FT_Pos* blueValues;
- FT_Pos* otherBlues;
- FT_Pos* familyBlues;
- FT_Pos* familyOtherBlues;
-
- size_t i;
- CF2_Fixed emBoxBottom, emBoxTop;
-
-#if 0
- CF2_Int unitsPerEm = font->unitsPerEm;
-
-
- if ( unitsPerEm == 0 )
- unitsPerEm = 1000;
-#endif
-
- FT_ZERO( blues );
- blues->scale = font->innerTransform.d;
-
- cf2_getBlueMetrics( decoder,
- &blues->blueScale,
- &blues->blueShift,
- &blues->blueFuzz );
-
- cf2_getBlueValues( decoder, &numBlueValues, &blueValues );
- cf2_getOtherBlues( decoder, &numOtherBlues, &otherBlues );
- cf2_getFamilyBlues( decoder, &numFamilyBlues, &familyBlues );
- cf2_getFamilyOtherBlues( decoder, &numFamilyOtherBlues, &familyOtherBlues );
-
- /*
- * synthetic em box hint heuristic
- *
- * Apply this when ideographic dictionary (LanguageGroup 1) has no
- * real alignment zones. Adobe tools generate dummy zones at -250 and
- * 1100 for a 1000 unit em. Fonts with ICF-based alignment zones
- * should not enable the heuristic. When the heuristic is enabled,
- * the font's blue zones are ignored.
- *
- */
-
- /* get em box from OS/2 typoAscender/Descender */
- /* TODO: FreeType does not parse these metrics. Skip them for now. */
-#if 0
- FCM_getHorizontalLineMetrics( &e,
- font->font,
- &ascender,
- &descender,
- &linegap );
- if ( ascender - descender == unitsPerEm )
- {
- emBoxBottom = cf2_intToFixed( descender );
- emBoxTop = cf2_intToFixed( ascender );
- }
- else
-#endif
- {
- emBoxBottom = CF2_ICF_Bottom;
- emBoxTop = CF2_ICF_Top;
- }
-
- if ( cf2_getLanguageGroup( decoder ) == 1 &&
- ( numBlueValues == 0 ||
- ( numBlueValues == 4 &&
- cf2_blueToFixed( blueValues[0] ) < emBoxBottom &&
- cf2_blueToFixed( blueValues[1] ) < emBoxBottom &&
- cf2_blueToFixed( blueValues[2] ) > emBoxTop &&
- cf2_blueToFixed( blueValues[3] ) > emBoxTop ) ) )
- {
- /*
- * Construct hint edges suitable for synthetic ghost hints at top
- * and bottom of em box. +-CF2_MIN_COUNTER allows for unhinted
- * features above or below the last hinted edge. This also gives a
- * net 1 pixel boost to the height of ideographic glyphs.
- *
- * Note: Adjust synthetic hints outward by epsilon (0x.0001) to
- * avoid interference. E.g., some fonts have real hints at
- * 880 and -120.
- */
-
- blues->emBoxBottomEdge.csCoord = emBoxBottom - CF2_FIXED_EPSILON;
- blues->emBoxBottomEdge.dsCoord = cf2_fixedRound(
- FT_MulFix(
- blues->emBoxBottomEdge.csCoord,
- blues->scale ) ) -
- CF2_MIN_COUNTER;
- blues->emBoxBottomEdge.scale = blues->scale;
- blues->emBoxBottomEdge.flags = CF2_GhostBottom |
- CF2_Locked |
- CF2_Synthetic;
-
- blues->emBoxTopEdge.csCoord = emBoxTop + CF2_FIXED_EPSILON +
- 2 * font->darkenY;
- blues->emBoxTopEdge.dsCoord = cf2_fixedRound(
- FT_MulFix(
- blues->emBoxTopEdge.csCoord,
- blues->scale ) ) +
- CF2_MIN_COUNTER;
- blues->emBoxTopEdge.scale = blues->scale;
- blues->emBoxTopEdge.flags = CF2_GhostTop |
- CF2_Locked |
- CF2_Synthetic;
-
- blues->doEmBoxHints = TRUE; /* enable the heuristic */
-
- return;
- }
-
- /* copy `BlueValues' and `OtherBlues' to a combined array of top and */
- /* bottom zones */
- for ( i = 0; i < numBlueValues; i += 2 )
- {
- blues->zone[blues->count].csBottomEdge =
- cf2_blueToFixed( blueValues[i] );
- blues->zone[blues->count].csTopEdge =
- cf2_blueToFixed( blueValues[i + 1] );
-
- zoneHeight = SUB_INT32( blues->zone[blues->count].csTopEdge,
- blues->zone[blues->count].csBottomEdge );
-
- if ( zoneHeight < 0 )
- {
- FT_TRACE4(( "cf2_blues_init: ignoring negative zone height\n" ));
- continue; /* reject this zone */
- }
-
- if ( zoneHeight > maxZoneHeight )
- {
- /* take maximum before darkening adjustment */
- /* so overshoot suppression point doesn't change */
- maxZoneHeight = zoneHeight;
- }
-
- /* adjust both edges of top zone upward by twice darkening amount */
- if ( i != 0 )
- {
- blues->zone[blues->count].csTopEdge += 2 * font->darkenY;
- blues->zone[blues->count].csBottomEdge += 2 * font->darkenY;
- }
-
- /* first `BlueValue' is bottom zone; others are top */
- if ( i == 0 )
- {
- blues->zone[blues->count].bottomZone =
- TRUE;
- blues->zone[blues->count].csFlatEdge =
- blues->zone[blues->count].csTopEdge;
- }
- else
- {
- blues->zone[blues->count].bottomZone =
- FALSE;
- blues->zone[blues->count].csFlatEdge =
- blues->zone[blues->count].csBottomEdge;
- }
-
- blues->count += 1;
- }
-
- for ( i = 0; i < numOtherBlues; i += 2 )
- {
- blues->zone[blues->count].csBottomEdge =
- cf2_blueToFixed( otherBlues[i] );
- blues->zone[blues->count].csTopEdge =
- cf2_blueToFixed( otherBlues[i + 1] );
-
- zoneHeight = SUB_INT32( blues->zone[blues->count].csTopEdge,
- blues->zone[blues->count].csBottomEdge );
-
- if ( zoneHeight < 0 )
- {
- FT_TRACE4(( "cf2_blues_init: ignoring negative zone height\n" ));
- continue; /* reject this zone */
- }
-
- if ( zoneHeight > maxZoneHeight )
- {
- /* take maximum before darkening adjustment */
- /* so overshoot suppression point doesn't change */
- maxZoneHeight = zoneHeight;
- }
-
- /* Note: bottom zones are not adjusted for darkening amount */
-
- /* all OtherBlues are bottom zone */
- blues->zone[blues->count].bottomZone =
- TRUE;
- blues->zone[blues->count].csFlatEdge =
- blues->zone[blues->count].csTopEdge;
-
- blues->count += 1;
- }
-
- /* Adjust for FamilyBlues */
-
- /* Search for the nearest flat edge in `FamilyBlues' or */
- /* `FamilyOtherBlues'. According to the Black Book, any matching edge */
- /* must be within one device pixel */
-
- csUnitsPerPixel = FT_DivFix( cf2_intToFixed( 1 ), blues->scale );
-
- /* loop on all zones in this font */
- for ( i = 0; i < blues->count; i++ )
- {
- size_t j;
- CF2_Fixed minDiff;
- CF2_Fixed flatFamilyEdge, diff;
- /* value for this font */
- CF2_Fixed flatEdge = blues->zone[i].csFlatEdge;
-
-
- if ( blues->zone[i].bottomZone )
- {
- /* In a bottom zone, the top edge is the flat edge. */
- /* Search `FamilyOtherBlues' for bottom zones; look for closest */
- /* Family edge that is within the one pixel threshold. */
-
- minDiff = CF2_FIXED_MAX;
-
- for ( j = 0; j < numFamilyOtherBlues; j += 2 )
- {
- /* top edge */
- flatFamilyEdge = cf2_blueToFixed( familyOtherBlues[j + 1] );
-
- diff = cf2_fixedAbs( SUB_INT32( flatEdge, flatFamilyEdge ) );
-
- if ( diff < minDiff && diff < csUnitsPerPixel )
- {
- blues->zone[i].csFlatEdge = flatFamilyEdge;
- minDiff = diff;
-
- if ( diff == 0 )
- break;
- }
- }
-
- /* check the first member of FamilyBlues, which is a bottom zone */
- if ( numFamilyBlues >= 2 )
- {
- /* top edge */
- flatFamilyEdge = cf2_blueToFixed( familyBlues[1] );
-
- diff = cf2_fixedAbs( SUB_INT32( flatEdge, flatFamilyEdge ) );
-
- if ( diff < minDiff && diff < csUnitsPerPixel )
- blues->zone[i].csFlatEdge = flatFamilyEdge;
- }
- }
- else
- {
- /* In a top zone, the bottom edge is the flat edge. */
- /* Search `FamilyBlues' for top zones; skip first zone, which is a */
- /* bottom zone; look for closest Family edge that is within the */
- /* one pixel threshold */
-
- minDiff = CF2_FIXED_MAX;
-
- for ( j = 2; j < numFamilyBlues; j += 2 )
- {
- /* bottom edge */
- flatFamilyEdge = cf2_blueToFixed( familyBlues[j] );
-
- /* adjust edges of top zone upward by twice darkening amount */
- flatFamilyEdge += 2 * font->darkenY; /* bottom edge */
-
- diff = cf2_fixedAbs( SUB_INT32( flatEdge, flatFamilyEdge ) );
-
- if ( diff < minDiff && diff < csUnitsPerPixel )
- {
- blues->zone[i].csFlatEdge = flatFamilyEdge;
- minDiff = diff;
-
- if ( diff == 0 )
- break;
- }
- }
- }
- }
-
- /* TODO: enforce separation of zones, including BlueFuzz */
-
- /* Adjust BlueScale; similar to AdjustBlueScale() in coretype */
- /* `bcsetup.c'. */
-
- if ( maxZoneHeight > 0 )
- {
- if ( blues->blueScale > FT_DivFix( cf2_intToFixed( 1 ),
- maxZoneHeight ) )
- {
- /* clamp at maximum scale */
- blues->blueScale = FT_DivFix( cf2_intToFixed( 1 ),
- maxZoneHeight );
- }
-
- /*
- * TODO: Revisit the bug fix for 613448. The minimum scale
- * requirement catches a number of library fonts. For
- * example, with default BlueScale (.039625) and 0.4 minimum,
- * the test below catches any font with maxZoneHeight < 10.1.
- * There are library fonts ranging from 2 to 10 that get
- * caught, including e.g., Eurostile LT Std Medium with
- * maxZoneHeight of 6.
- *
- */
-#if 0
- if ( blueScale < .4 / maxZoneHeight )
- {
- tetraphilia_assert( 0 );
- /* clamp at minimum scale, per bug 0613448 fix */
- blueScale = .4 / maxZoneHeight;
- }
-#endif
-
- }
-
- /*
- * Suppress overshoot and boost blue zones at small sizes. Boost
- * amount varies linearly from 0.5 pixel near 0 to 0 pixel at
- * blueScale cutoff.
- * Note: This boost amount is different from the coretype heuristic.
- *
- */
-
- if ( blues->scale < blues->blueScale )
- {
- blues->suppressOvershoot = TRUE;
-
- /* Change rounding threshold for `dsFlatEdge'. */
- /* Note: constant changed from 0.5 to 0.6 to avoid a problem with */
- /* 10ppem Arial */
-
- blues->boost = cf2_doubleToFixed( .6 ) -
- FT_MulDiv( cf2_doubleToFixed ( .6 ),
- blues->scale,
- blues->blueScale );
- if ( blues->boost > 0x7FFF )
- {
- /* boost must remain less than 0.5, or baseline could go negative */
- blues->boost = 0x7FFF;
- }
- }
-
- /* boost and darkening have similar effects; don't do both */
- if ( font->stemDarkened )
- blues->boost = 0;
-
- /* set device space alignment for each zone; */
- /* apply boost amount before rounding flat edge */
-
- for ( i = 0; i < blues->count; i++ )
- {
- if ( blues->zone[i].bottomZone )
- blues->zone[i].dsFlatEdge = cf2_fixedRound(
- FT_MulFix(
- blues->zone[i].csFlatEdge,
- blues->scale ) -
- blues->boost );
- else
- blues->zone[i].dsFlatEdge = cf2_fixedRound(
- FT_MulFix(
- blues->zone[i].csFlatEdge,
- blues->scale ) +
- blues->boost );
- }
- }
-
-
- /*
- * Check whether `stemHint' is captured by one of the blue zones.
- *
- * Zero, one or both edges may be valid; only valid edges can be
- * captured. For compatibility with CoolType, search top and bottom
- * zones in the same pass (see `BlueLock'). If a hint is captured,
- * return true and position the edge(s) in one of 3 ways:
- *
- * 1) If `BlueScale' suppresses overshoot, position the captured edge
- * at the flat edge of the zone.
- * 2) If overshoot is not suppressed and `BlueShift' requires
- * overshoot, position the captured edge a minimum of 1 device pixel
- * from the flat edge.
- * 3) If overshoot is not suppressed or required, position the captured
- * edge at the nearest device pixel.
- *
- */
- FT_LOCAL_DEF( FT_Bool )
- cf2_blues_capture( const CF2_Blues blues,
- CF2_Hint bottomHintEdge,
- CF2_Hint topHintEdge )
- {
- /* TODO: validate? */
- CF2_Fixed csFuzz = blues->blueFuzz;
-
- /* new position of captured edge */
- CF2_Fixed dsNew;
-
- /* amount that hint is moved when positioned */
- CF2_Fixed dsMove = 0;
-
- FT_Bool captured = FALSE;
- CF2_UInt i;
-
-
- /* assert edge flags are consistent */
- FT_ASSERT( !cf2_hint_isTop( bottomHintEdge ) &&
- !cf2_hint_isBottom( topHintEdge ) );
-
- /* TODO: search once without blue fuzz for compatibility with coretype? */
- for ( i = 0; i < blues->count; i++ )
- {
- if ( blues->zone[i].bottomZone &&
- cf2_hint_isBottom( bottomHintEdge ) )
- {
- if ( SUB_INT32( blues->zone[i].csBottomEdge, csFuzz ) <=
- bottomHintEdge->csCoord &&
- bottomHintEdge->csCoord <=
- ADD_INT32( blues->zone[i].csTopEdge, csFuzz ) )
- {
- /* bottom edge captured by bottom zone */
-
- if ( blues->suppressOvershoot )
- dsNew = blues->zone[i].dsFlatEdge;
-
- else if ( SUB_INT32( blues->zone[i].csTopEdge,
- bottomHintEdge->csCoord ) >=
- blues->blueShift )
- {
- /* guarantee minimum of 1 pixel overshoot */
- dsNew = FT_MIN(
- cf2_fixedRound( bottomHintEdge->dsCoord ),
- blues->zone[i].dsFlatEdge - cf2_intToFixed( 1 ) );
- }
-
- else
- {
- /* simply round captured edge */
- dsNew = cf2_fixedRound( bottomHintEdge->dsCoord );
- }
-
- dsMove = SUB_INT32( dsNew, bottomHintEdge->dsCoord );
- captured = TRUE;
-
- break;
- }
- }
-
- if ( !blues->zone[i].bottomZone && cf2_hint_isTop( topHintEdge ) )
- {
- if ( SUB_INT32( blues->zone[i].csBottomEdge, csFuzz ) <=
- topHintEdge->csCoord &&
- topHintEdge->csCoord <=
- ADD_INT32( blues->zone[i].csTopEdge, csFuzz ) )
- {
- /* top edge captured by top zone */
-
- if ( blues->suppressOvershoot )
- dsNew = blues->zone[i].dsFlatEdge;
-
- else if ( SUB_INT32( topHintEdge->csCoord,
- blues->zone[i].csBottomEdge ) >=
- blues->blueShift )
- {
- /* guarantee minimum of 1 pixel overshoot */
- dsNew = FT_MAX(
- cf2_fixedRound( topHintEdge->dsCoord ),
- blues->zone[i].dsFlatEdge + cf2_intToFixed( 1 ) );
- }
-
- else
- {
- /* simply round captured edge */
- dsNew = cf2_fixedRound( topHintEdge->dsCoord );
- }
-
- dsMove = SUB_INT32( dsNew, topHintEdge->dsCoord );
- captured = TRUE;
-
- break;
- }
- }
- }
-
- if ( captured )
- {
- /* move both edges and flag them `locked' */
- if ( cf2_hint_isValid( bottomHintEdge ) )
- {
- bottomHintEdge->dsCoord = ADD_INT32( bottomHintEdge->dsCoord,
- dsMove );
- cf2_hint_lock( bottomHintEdge );
- }
-
- if ( cf2_hint_isValid( topHintEdge ) )
- {
- topHintEdge->dsCoord = ADD_INT32( topHintEdge->dsCoord, dsMove );
- cf2_hint_lock( topHintEdge );
- }
- }
-
- return captured;
- }
-
-
-/* END */
diff --git a/thirdparty/freetype/src/cff/cf2blues.h b/thirdparty/freetype/src/cff/cf2blues.h
deleted file mode 100644
index a6bcd9de57..0000000000
--- a/thirdparty/freetype/src/cff/cf2blues.h
+++ /dev/null
@@ -1,185 +0,0 @@
-/***************************************************************************/
-/* */
-/* cf2blues.h */
-/* */
-/* Adobe's code for handling Blue Zones (specification). */
-/* */
-/* Copyright 2009-2013 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
-
-
- /*
- * A `CF2_Blues' object stores the blue zones (horizontal alignment
- * zones) of a font. These are specified in the CFF private dictionary
- * by `BlueValues', `OtherBlues', `FamilyBlues', and `FamilyOtherBlues'.
- * Each zone is defined by a top and bottom edge in character space.
- * Further, each zone is either a top zone or a bottom zone, as recorded
- * by `bottomZone'.
- *
- * The maximum number of `BlueValues' and `FamilyBlues' is 7 each.
- * However, these are combined to produce a total of 7 zones.
- * Similarly, the maximum number of `OtherBlues' and `FamilyOtherBlues'
- * is 5 and these are combined to produce an additional 5 zones.
- *
- * Blue zones are used to `capture' hints and force them to a common
- * alignment point. This alignment is recorded in device space in
- * `dsFlatEdge'. Except for this value, a `CF2_Blues' object could be
- * constructed independently of scaling. Construction may occur once
- * the matrix is known. Other features implemented in the Capture
- * method are overshoot suppression, overshoot enforcement, and Blue
- * Boost.
- *
- * Capture is determined by `BlueValues' and `OtherBlues', but the
- * alignment point may be adjusted to the scaled flat edge of
- * `FamilyBlues' or `FamilyOtherBlues'. No alignment is done to the
- * curved edge of a zone.
- *
- */
-
-
-#ifndef CF2BLUES_H_
-#define CF2BLUES_H_
-
-
-#include "cf2glue.h"
-
-
-FT_BEGIN_HEADER
-
-
- /*
- * `CF2_Hint' is shared by `cf2hints.h' and
- * `cf2blues.h', but `cf2blues.h' depends on
- * `cf2hints.h', so define it here. Note: The typedef is in
- * `cf2glue.h'.
- *
- */
- enum
- {
- CF2_GhostBottom = 0x1, /* a single bottom edge */
- CF2_GhostTop = 0x2, /* a single top edge */
- CF2_PairBottom = 0x4, /* the bottom edge of a stem hint */
- CF2_PairTop = 0x8, /* the top edge of a stem hint */
- CF2_Locked = 0x10, /* this edge has been aligned */
- /* by a blue zone */
- CF2_Synthetic = 0x20 /* this edge was synthesized */
- };
-
-
- /*
- * Default value for OS/2 typoAscender/Descender when their difference
- * is not equal to `unitsPerEm'. The default is based on -250 and 1100
- * in `CF2_Blues', assuming 1000 units per em here.
- *
- */
- enum
- {
- CF2_ICF_Top = cf2_intToFixed( 880 ),
- CF2_ICF_Bottom = cf2_intToFixed( -120 )
- };
-
-
- /*
- * Constant used for hint adjustment and for synthetic em box hint
- * placement.
- */
-#define CF2_MIN_COUNTER cf2_doubleToFixed( 0.5 )
-
-
- /* shared typedef is in cf2glue.h */
- struct CF2_HintRec_
- {
- CF2_UInt flags; /* attributes of the edge */
- size_t index; /* index in original stem hint array */
- /* (if not synthetic) */
- CF2_Fixed csCoord;
- CF2_Fixed dsCoord;
- CF2_Fixed scale;
- };
-
-
- typedef struct CF2_BlueRec_
- {
- CF2_Fixed csBottomEdge;
- CF2_Fixed csTopEdge;
- CF2_Fixed csFlatEdge; /* may be from either local or Family zones */
- CF2_Fixed dsFlatEdge; /* top edge of bottom zone or bottom edge */
- /* of top zone (rounded) */
- FT_Bool bottomZone;
-
- } CF2_BlueRec;
-
-
- /* max total blue zones is 12 */
- enum
- {
- CF2_MAX_BLUES = 7,
- CF2_MAX_OTHERBLUES = 5
- };
-
-
- typedef struct CF2_BluesRec_
- {
- CF2_Fixed scale;
- CF2_UInt count;
- FT_Bool suppressOvershoot;
- FT_Bool doEmBoxHints;
-
- CF2_Fixed blueScale;
- CF2_Fixed blueShift;
- CF2_Fixed blueFuzz;
-
- CF2_Fixed boost;
-
- CF2_HintRec emBoxTopEdge;
- CF2_HintRec emBoxBottomEdge;
-
- CF2_BlueRec zone[CF2_MAX_BLUES + CF2_MAX_OTHERBLUES];
-
- } CF2_BluesRec, *CF2_Blues;
-
-
- FT_LOCAL( void )
- cf2_blues_init( CF2_Blues blues,
- CF2_Font font );
- FT_LOCAL( FT_Bool )
- cf2_blues_capture( const CF2_Blues blues,
- CF2_Hint bottomHintEdge,
- CF2_Hint topHintEdge );
-
-
-FT_END_HEADER
-
-
-#endif /* CF2BLUES_H_ */
-
-
-/* END */
diff --git a/thirdparty/freetype/src/cff/cf2error.c b/thirdparty/freetype/src/cff/cf2error.c
deleted file mode 100644
index e3dd69f50d..0000000000
--- a/thirdparty/freetype/src/cff/cf2error.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/***************************************************************************/
-/* */
-/* cf2error.c */
-/* */
-/* Adobe's code for error handling (body). */
-/* */
-/* Copyright 2006-2013 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
-
-
-#include "cf2ft.h"
-#include "cf2error.h"
-
-
- FT_LOCAL_DEF( void )
- cf2_setError( FT_Error* error,
- FT_Error value )
- {
- if ( error && !*error )
- *error = value;
- }
-
-
-/* END */
diff --git a/thirdparty/freetype/src/cff/cf2error.h b/thirdparty/freetype/src/cff/cf2error.h
deleted file mode 100644
index d2c770d297..0000000000
--- a/thirdparty/freetype/src/cff/cf2error.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/***************************************************************************/
-/* */
-/* cf2error.h */
-/* */
-/* Adobe's code for error handling (specification). */
-/* */
-/* Copyright 2006-2013 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
-
-
-#ifndef CF2ERROR_H_
-#define CF2ERROR_H_
-
-
-#include FT_MODULE_ERRORS_H
-
-#undef FTERRORS_H_
-
-#undef FT_ERR_PREFIX
-#define FT_ERR_PREFIX CF2_Err_
-#define FT_ERR_BASE FT_Mod_Err_CF2
-
-
-#include FT_ERRORS_H
-#include "cf2ft.h"
-
-
-FT_BEGIN_HEADER
-
-
- /*
- * A poor-man error facility.
- *
- * This code being written in vanilla C, doesn't have the luxury of a
- * language-supported exception mechanism such as the one available in
- * Java. Instead, we are stuck with using error codes that must be
- * carefully managed and preserved. However, it is convenient for us to
- * model our error mechanism on a Java-like exception mechanism.
- * When we assign an error code we are thus `throwing' an error.
- *
- * The preservation of an error code is done by coding convention.
- * Upon a function call if the error code is anything other than
- * `FT_Err_Ok', which is guaranteed to be zero, we
- * will return without altering that error. This will allow the
- * error to propagate and be handled at the appropriate location in
- * the code.
- *
- * This allows a style of code where the error code is initialized
- * up front and a block of calls are made with the error code only
- * being checked after the block. If a new error occurs, the original
- * error will be preserved and a functional no-op should result in any
- * subsequent function that has an initial error code not equal to
- * `FT_Err_Ok'.
- *
- * Errors are encoded by calling the `FT_THROW' macro. For example,
- *
- * {
- * FT_Error e;
- *
- *
- * ...
- * e = FT_THROW( Out_Of_Memory );
- * }
- *
- */
-
-
- /* Set error code to a particular value. */
- FT_LOCAL( void )
- cf2_setError( FT_Error* error,
- FT_Error value );
-
-
- /*
- * A macro that conditionally sets an error code.
- *
- * This macro will first check whether `error' is set;
- * if not, it will set it to `e'.
- *
- */
-#define CF2_SET_ERROR( error, e ) \
- cf2_setError( error, FT_THROW( e ) )
-
-
-FT_END_HEADER
-
-
-#endif /* CF2ERROR_H_ */
-
-
-/* END */
diff --git a/thirdparty/freetype/src/cff/cf2fixed.h b/thirdparty/freetype/src/cff/cf2fixed.h
deleted file mode 100644
index a041184bda..0000000000
--- a/thirdparty/freetype/src/cff/cf2fixed.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/***************************************************************************/
-/* */
-/* cf2fixed.h */
-/* */
-/* Adobe's code for Fixed Point Mathematics (specification only). */
-/* */
-/* Copyright 2007-2013 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
-
-
-#ifndef CF2FIXED_H_
-#define CF2FIXED_H_
-
-
-FT_BEGIN_HEADER
-
-
- /* rasterizer integer and fixed point arithmetic must be 32-bit */
-
-#define CF2_Fixed CF2_F16Dot16
- typedef FT_Int32 CF2_Frac; /* 2.30 fixed point */
-
-
-#define CF2_FIXED_MAX ( (CF2_Fixed)0x7FFFFFFFL )
-#define CF2_FIXED_MIN ( (CF2_Fixed)0x80000000L )
-#define CF2_FIXED_ONE ( (CF2_Fixed)0x10000L )
-#define CF2_FIXED_EPSILON ( (CF2_Fixed)0x0001 )
-
- /* in C 89, left and right shift of negative numbers is */
- /* implementation specific behaviour in the general case */
-
-#define cf2_intToFixed( i ) \
- ( (CF2_Fixed)( (FT_UInt32)(i) << 16 ) )
-#define cf2_fixedToInt( x ) \
- ( (FT_Short)( ( (FT_UInt32)(x) + 0x8000U ) >> 16 ) )
-#define cf2_fixedRound( x ) \
- ( (CF2_Fixed)( ( (FT_UInt32)(x) + 0x8000U ) & 0xFFFF0000UL ) )
-#define cf2_doubleToFixed( f ) \
- ( (CF2_Fixed)( (f) * 65536.0 + 0.5 ) )
-#define cf2_fixedAbs( x ) \
- ( (x) < 0 ? NEG_INT32( x ) : (x) )
-#define cf2_fixedFloor( x ) \
- ( (CF2_Fixed)( (FT_UInt32)(x) & 0xFFFF0000UL ) )
-#define cf2_fixedFraction( x ) \
- ( (x) - cf2_fixedFloor( x ) )
-#define cf2_fracToFixed( x ) \
- ( (x) < 0 ? -( ( -(x) + 0x2000 ) >> 14 ) \
- : ( ( (x) + 0x2000 ) >> 14 ) )
-
-
- /* signed numeric types */
- typedef enum CF2_NumberType_
- {
- CF2_NumberFixed, /* 16.16 */
- CF2_NumberFrac, /* 2.30 */
- CF2_NumberInt /* 32.0 */
-
- } CF2_NumberType;
-
-
-FT_END_HEADER
-
-
-#endif /* CF2FIXED_H_ */
-
-
-/* END */
diff --git a/thirdparty/freetype/src/cff/cf2font.c b/thirdparty/freetype/src/cff/cf2font.c
deleted file mode 100644
index 4ac71a8d71..0000000000
--- a/thirdparty/freetype/src/cff/cf2font.c
+++ /dev/null
@@ -1,562 +0,0 @@
-/***************************************************************************/
-/* */
-/* cf2font.c */
-/* */
-/* Adobe's code for font instances (body). */
-/* */
-/* Copyright 2007-2014 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
-
-
-#include <ft2build.h>
-#include FT_INTERNAL_CALC_H
-
-#include "cf2ft.h"
-
-#include "cf2glue.h"
-#include "cf2font.h"
-#include "cf2error.h"
-#include "cf2intrp.h"
-
-
- /* Compute a stem darkening amount in character space. */
- static void
- cf2_computeDarkening( CF2_Fixed emRatio,
- CF2_Fixed ppem,
- CF2_Fixed stemWidth,
- CF2_Fixed* darkenAmount,
- CF2_Fixed boldenAmount,
- FT_Bool stemDarkened,
- FT_Int* darkenParams )
- {
- /*
- * Total darkening amount is computed in 1000 unit character space
- * using the modified 5 part curve as Adobe's Avalon rasterizer.
- * The darkening amount is smaller for thicker stems.
- * It becomes zero when the stem is thicker than 2.333 pixels.
- *
- * By default, we use
- *
- * darkenAmount = 0.4 pixels if scaledStem <= 0.5 pixels,
- * darkenAmount = 0.275 pixels if 1 <= scaledStem <= 1.667 pixels,
- * darkenAmount = 0 pixel if scaledStem >= 2.333 pixels,
- *
- * and piecewise linear in-between:
- *
- *
- * darkening
- * ^
- * |
- * | (x1,y1)
- * |--------+
- * | \
- * | \
- * | \ (x3,y3)
- * | +----------+
- * | (x2,y2) \
- * | \
- * | \
- * | +-----------------
- * | (x4,y4)
- * +---------------------------------------------> stem
- * thickness
- *
- *
- * This corresponds to the following values for the
- * `darkening-parameters' property:
- *
- * (x1, y1) = (500, 400)
- * (x2, y2) = (1000, 275)
- * (x3, y3) = (1667, 275)
- * (x4, y4) = (2333, 0)
- *
- */
-
- /* Internal calculations are done in units per thousand for */
- /* convenience. The x axis is scaled stem width in */
- /* thousandths of a pixel. That is, 1000 is 1 pixel. */
- /* The y axis is darkening amount in thousandths of a pixel.*/
- /* In the code, below, dividing by ppem and */
- /* adjusting for emRatio converts darkenAmount to character */
- /* space (font units). */
- CF2_Fixed stemWidthPer1000, scaledStem;
- FT_Int logBase2;
-
-
- *darkenAmount = 0;
-
- if ( boldenAmount == 0 && !stemDarkened )
- return;
-
- /* protect against range problems and divide by zero */
- if ( emRatio < cf2_doubleToFixed( .01 ) )
- return;
-
- if ( stemDarkened )
- {
- FT_Int x1 = darkenParams[0];
- FT_Int y1 = darkenParams[1];
- FT_Int x2 = darkenParams[2];
- FT_Int y2 = darkenParams[3];
- FT_Int x3 = darkenParams[4];
- FT_Int y3 = darkenParams[5];
- FT_Int x4 = darkenParams[6];
- FT_Int y4 = darkenParams[7];
-
-
- /* convert from true character space to 1000 unit character space; */
- /* add synthetic emboldening effect */
-
- /* `stemWidthPer1000' will not overflow for a legitimate font */
-
- stemWidthPer1000 = FT_MulFix( stemWidth + boldenAmount, emRatio );
-
- /* `scaledStem' can easily overflow, so we must clamp its maximum */
- /* value; the test doesn't need to be precise, but must be */
- /* conservative. The clamp value (default 2333) where */
- /* `darkenAmount' is zero is well below the overflow value of */
- /* 32767. */
- /* */
- /* FT_MSB computes the integer part of the base 2 logarithm. The */
- /* number of bits for the product is 1 or 2 more than the sum of */
- /* logarithms; remembering that the 16 lowest bits of the fraction */
- /* are dropped this is correct to within a factor of almost 4. */
- /* For example, 0x80.0000 * 0x80.0000 = 0x4000.0000 is 23+23 and */
- /* is flagged as possible overflow because 0xFF.FFFF * 0xFF.FFFF = */
- /* 0xFFFF.FE00 is also 23+23. */
-
- logBase2 = FT_MSB( (FT_UInt32)stemWidthPer1000 ) +
- FT_MSB( (FT_UInt32)ppem );
-
- if ( logBase2 >= 46 )
- /* possible overflow */
- scaledStem = cf2_intToFixed( x4 );
- else
- scaledStem = FT_MulFix( stemWidthPer1000, ppem );
-
- /* now apply the darkening parameters */
-
- if ( scaledStem < cf2_intToFixed( x1 ) )
- *darkenAmount = FT_DivFix( cf2_intToFixed( y1 ), ppem );
-
- else if ( scaledStem < cf2_intToFixed( x2 ) )
- {
- FT_Int xdelta = x2 - x1;
- FT_Int ydelta = y2 - y1;
- FT_Int x = stemWidthPer1000 -
- FT_DivFix( cf2_intToFixed( x1 ), ppem );
-
-
- if ( !xdelta )
- goto Try_x3;
-
- *darkenAmount = FT_MulDiv( x, ydelta, xdelta ) +
- FT_DivFix( cf2_intToFixed( y1 ), ppem );
- }
-
- else if ( scaledStem < cf2_intToFixed( x3 ) )
- {
- Try_x3:
- {
- FT_Int xdelta = x3 - x2;
- FT_Int ydelta = y3 - y2;
- FT_Int x = stemWidthPer1000 -
- FT_DivFix( cf2_intToFixed( x2 ), ppem );
-
-
- if ( !xdelta )
- goto Try_x4;
-
- *darkenAmount = FT_MulDiv( x, ydelta, xdelta ) +
- FT_DivFix( cf2_intToFixed( y2 ), ppem );
- }
- }
-
- else if ( scaledStem < cf2_intToFixed( x4 ) )
- {
- Try_x4:
- {
- FT_Int xdelta = x4 - x3;
- FT_Int ydelta = y4 - y3;
- FT_Int x = stemWidthPer1000 -
- FT_DivFix( cf2_intToFixed( x3 ), ppem );
-
-
- if ( !xdelta )
- goto Use_y4;
-
- *darkenAmount = FT_MulDiv( x, ydelta, xdelta ) +
- FT_DivFix( cf2_intToFixed( y3 ), ppem );
- }
- }
-
- else
- {
- Use_y4:
- *darkenAmount = FT_DivFix( cf2_intToFixed( y4 ), ppem );
- }
-
- /* use half the amount on each side and convert back to true */
- /* character space */
- *darkenAmount = FT_DivFix( *darkenAmount, 2 * emRatio );
- }
-
- /* add synthetic emboldening effect in character space */
- *darkenAmount += boldenAmount / 2;
- }
-
-
- /* set up values for the current FontDict and matrix; */
- /* called for each glyph to be rendered */
-
- /* caller's transform is adjusted for subpixel positioning */
- static void
- cf2_font_setup( CF2_Font font,
- const CF2_Matrix* transform )
- {
- /* pointer to parsed font object */
- CFF_Decoder* decoder = font->decoder;
-
- FT_Bool needExtraSetup = FALSE;
-
- CFF_VStoreRec* vstore;
- FT_Bool hasVariations = FALSE;
-
- /* character space units */
- CF2_Fixed boldenX = font->syntheticEmboldeningAmountX;
- CF2_Fixed boldenY = font->syntheticEmboldeningAmountY;
-
- CFF_SubFont subFont;
- CF2_Fixed ppem;
-
- CF2_UInt lenNormalizedV = 0;
- FT_Fixed* normalizedV = NULL;
-
-
- /* clear previous error */
- font->error = FT_Err_Ok;
-
- /* if a CID fontDict has changed, we need to recompute some cached */
- /* data */
- subFont = cf2_getSubfont( decoder );
- if ( font->lastSubfont != subFont )
- {
- font->lastSubfont = subFont;
- needExtraSetup = TRUE;
- }
-
- /* check for variation vectors */
- vstore = cf2_getVStore( decoder );
- hasVariations = ( vstore->dataCount != 0 );
-
- if ( hasVariations )
- {
-#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
- /* check whether Private DICT in this subfont needs to be reparsed */
- font->error = cf2_getNormalizedVector( decoder,
- &lenNormalizedV,
- &normalizedV );
- if ( font->error )
- return;
-
- if ( cff_blend_check_vector( &subFont->blend,
- subFont->private_dict.vsindex,
- lenNormalizedV,
- normalizedV ) )
- {
- /* blend has changed, reparse */
- cff_load_private_dict( decoder->cff,
- subFont,
- lenNormalizedV,
- normalizedV );
- needExtraSetup = TRUE;
- }
-#endif
-
- /* copy from subfont */
- font->blend.font = subFont->blend.font;
-
- /* clear state of charstring blend */
- font->blend.usedBV = FALSE;
-
- /* initialize value for charstring */
- font->vsindex = subFont->private_dict.vsindex;
-
- /* store vector inputs for blends in charstring */
- font->lenNDV = lenNormalizedV;
- font->NDV = normalizedV;
- }
-
- /* if ppem has changed, we need to recompute some cached data */
- /* note: because of CID font matrix concatenation, ppem and transform */
- /* do not necessarily track. */
- ppem = cf2_getPpemY( decoder );
- if ( font->ppem != ppem )
- {
- font->ppem = ppem;
- needExtraSetup = TRUE;
- }
-
- /* copy hinted flag on each call */
- font->hinted = (FT_Bool)( font->renderingFlags & CF2_FlagsHinted );
-
- /* determine if transform has changed; */
- /* include Fontmatrix but ignore translation */
- if ( ft_memcmp( transform,
- &font->currentTransform,
- 4 * sizeof ( CF2_Fixed ) ) != 0 )
- {
- /* save `key' information for `cache of one' matrix data; */
- /* save client transform, without the translation */
- font->currentTransform = *transform;
- font->currentTransform.tx =
- font->currentTransform.ty = cf2_intToFixed( 0 );
-
- /* TODO: FreeType transform is simple scalar; for now, use identity */
- /* for outer */
- font->innerTransform = *transform;
- font->outerTransform.a =
- font->outerTransform.d = cf2_intToFixed( 1 );
- font->outerTransform.b =
- font->outerTransform.c = cf2_intToFixed( 0 );
-
- needExtraSetup = TRUE;
- }
-
- /*
- * font->darkened is set to true if there is a stem darkening request or
- * the font is synthetic emboldened.
- * font->darkened controls whether to adjust blue zones, winding order,
- * and hinting.
- *
- */
- if ( font->stemDarkened != ( font->renderingFlags & CF2_FlagsDarkened ) )
- {
- font->stemDarkened =
- (FT_Bool)( font->renderingFlags & CF2_FlagsDarkened );
-
- /* blue zones depend on darkened flag */
- needExtraSetup = TRUE;
- }
-
- /* recompute variables that are dependent on transform or FontDict or */
- /* darken flag */
- if ( needExtraSetup )
- {
- /* StdVW is found in the private dictionary; */
- /* recompute darkening amounts whenever private dictionary or */
- /* transform change */
- /* Note: a rendering flag turns darkening on or off, so we want to */
- /* store the `on' amounts; */
- /* darkening amount is computed in character space */
- /* TODO: testing size-dependent darkening here; */
- /* what to do for rotations? */
-
- CF2_Fixed emRatio;
- CF2_Fixed stdHW;
- CF2_Int unitsPerEm = font->unitsPerEm;
-
-
- if ( unitsPerEm == 0 )
- unitsPerEm = 1000;
-
- ppem = FT_MAX( cf2_intToFixed( 4 ),
- font->ppem ); /* use minimum ppem of 4 */
-
-#if 0
- /* since vstem is measured in the x-direction, we use the `a' member */
- /* of the fontMatrix */
- emRatio = cf2_fixedFracMul( cf2_intToFixed( 1000 ), fontMatrix->a );
-#endif
-
- /* Freetype does not preserve the fontMatrix when parsing; use */
- /* unitsPerEm instead. */
- /* TODO: check precision of this */
- emRatio = cf2_intToFixed( 1000 ) / unitsPerEm;
- font->stdVW = cf2_getStdVW( decoder );
-
- if ( font->stdVW <= 0 )
- font->stdVW = FT_DivFix( cf2_intToFixed( 75 ), emRatio );
-
- if ( boldenX > 0 )
- {
- /* Ensure that boldenX is at least 1 pixel for synthetic bold font */
- /* (similar to what Avalon does) */
- boldenX = FT_MAX( boldenX,
- FT_DivFix( cf2_intToFixed( unitsPerEm ), ppem ) );
-
- /* Synthetic emboldening adds at least 1 pixel to darkenX, while */
- /* stem darkening adds at most half pixel. Since the purpose of */
- /* stem darkening (readability at small sizes) is met with */
- /* synthetic emboldening, no need to add stem darkening for a */
- /* synthetic bold font. */
- cf2_computeDarkening( emRatio,
- ppem,
- font->stdVW,
- &font->darkenX,
- boldenX,
- FALSE,
- font->darkenParams );
- }
- else
- cf2_computeDarkening( emRatio,
- ppem,
- font->stdVW,
- &font->darkenX,
- 0,
- font->stemDarkened,
- font->darkenParams );
-
-#if 0
- /* since hstem is measured in the y-direction, we use the `d' member */
- /* of the fontMatrix */
- /* TODO: use the same units per em as above; check this */
- emRatio = cf2_fixedFracMul( cf2_intToFixed( 1000 ), fontMatrix->d );
-#endif
-
- /* set the default stem width, because it must be the same for all */
- /* family members; */
- /* choose a constant for StdHW that depends on font contrast */
- stdHW = cf2_getStdHW( decoder );
-
- if ( stdHW > 0 && font->stdVW > MUL_INT32( 2, stdHW ) )
- font->stdHW = FT_DivFix( cf2_intToFixed( 75 ), emRatio );
- else
- {
- /* low contrast font gets less hstem darkening */
- font->stdHW = FT_DivFix( cf2_intToFixed( 110 ), emRatio );
- }
-
- cf2_computeDarkening( emRatio,
- ppem,
- font->stdHW,
- &font->darkenY,
- boldenY,
- font->stemDarkened,
- font->darkenParams );
-
- if ( font->darkenX != 0 || font->darkenY != 0 )
- font->darkened = TRUE;
- else
- font->darkened = FALSE;
-
- font->reverseWinding = FALSE; /* initial expectation is CCW */
-
- /* compute blue zones for this instance */
- cf2_blues_init( &font->blues, font );
-
- } /* needExtraSetup */
- }
-
-
- /* equivalent to AdobeGetOutline */
- FT_LOCAL_DEF( FT_Error )
- cf2_getGlyphOutline( CF2_Font font,
- CF2_Buffer charstring,
- const CF2_Matrix* transform,
- CF2_F16Dot16* glyphWidth )
- {
- FT_Error lastError = FT_Err_Ok;
-
- FT_Vector translation;
-
-#if 0
- FT_Vector advancePoint;
-#endif
-
- CF2_Fixed advWidth = 0;
- FT_Bool needWinding;
-
-
- /* Note: use both integer and fraction for outlines. This allows bbox */
- /* to come out directly. */
-
- translation.x = transform->tx;
- translation.y = transform->ty;
-
- /* set up values based on transform */
- cf2_font_setup( font, transform );
- if ( font->error )
- goto exit; /* setup encountered an error */
-
- /* reset darken direction */
- font->reverseWinding = FALSE;
-
- /* winding order only affects darkening */
- needWinding = font->darkened;
-
- while ( 1 )
- {
- /* reset output buffer */
- cf2_outline_reset( &font->outline );
-
- /* build the outline, passing the full translation */
- cf2_interpT2CharString( font,
- charstring,
- (CF2_OutlineCallbacks)&font->outline,
- &translation,
- FALSE,
- 0,
- 0,
- &advWidth );
-
- if ( font->error )
- goto exit;
-
- if ( !needWinding )
- break;
-
- /* check winding order */
- if ( font->outline.root.windingMomentum >= 0 ) /* CFF is CCW */
- break;
-
- /* invert darkening and render again */
- /* TODO: this should be a parameter to getOutline-computeOffset */
- font->reverseWinding = TRUE;
-
- needWinding = FALSE; /* exit after next iteration */
- }
-
- /* finish storing client outline */
- cf2_outline_close( &font->outline );
-
- exit:
- /* FreeType just wants the advance width; there is no translation */
- *glyphWidth = advWidth;
-
- /* free resources and collect errors from objects we've used */
- cf2_setError( &font->error, lastError );
-
- return font->error;
- }
-
-
-/* END */
diff --git a/thirdparty/freetype/src/cff/cf2font.h b/thirdparty/freetype/src/cff/cf2font.h
deleted file mode 100644
index 17ecd17bbb..0000000000
--- a/thirdparty/freetype/src/cff/cf2font.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/***************************************************************************/
-/* */
-/* cf2font.h */
-/* */
-/* Adobe's code for font instances (specification). */
-/* */
-/* Copyright 2007-2013 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
-
-
-#ifndef CF2FONT_H_
-#define CF2FONT_H_
-
-
-#include "cf2ft.h"
-#include "cf2blues.h"
-#include "cffload.h"
-
-
-FT_BEGIN_HEADER
-
-
-#define CF2_OPERAND_STACK_SIZE 48
-#define CF2_MAX_SUBR 16 /* maximum subroutine nesting; */
- /* only 10 are allowed but there exist */
- /* fonts like `HiraKakuProN-W3.ttf' */
- /* (Hiragino Kaku Gothic ProN W3; */
- /* 8.2d6e1; 2014-12-19) that exceed */
- /* this limit */
-#define CF2_STORAGE_SIZE 32
-
-
- /* typedef is in `cf2glue.h' */
- struct CF2_FontRec_
- {
- FT_Memory memory;
- FT_Error error; /* shared error for this instance */
-
- FT_Bool isCFF2;
- CF2_RenderingFlags renderingFlags;
-
- /* variables that depend on Transform: */
- /* the following have zero translation; */
- /* inner * outer = font * original */
-
- CF2_Matrix currentTransform; /* original client matrix */
- CF2_Matrix innerTransform; /* for hinting; erect, scaled */
- CF2_Matrix outerTransform; /* post hinting; includes rotations */
- CF2_Fixed ppem; /* transform-dependent */
-
- /* variation data */
- CFF_BlendRec blend; /* cached charstring blend vector */
- CF2_UInt vsindex; /* current vsindex */
- CF2_UInt lenNDV; /* current length NDV or zero */
- FT_Fixed* NDV; /* ptr to current NDV or NULL */
-
- CF2_Int unitsPerEm;
-
- CF2_Fixed syntheticEmboldeningAmountX; /* character space units */
- CF2_Fixed syntheticEmboldeningAmountY; /* character space units */
-
- /* FreeType related members */
- CF2_OutlineRec outline; /* freetype glyph outline functions */
- CFF_Decoder* decoder;
- CFF_SubFont lastSubfont; /* FreeType parsed data; */
- /* top font or subfont */
-
- /* these flags can vary from one call to the next */
- FT_Bool hinted;
- FT_Bool darkened; /* true if stemDarkened or synthetic bold */
- /* i.e. darkenX != 0 || darkenY != 0 */
- FT_Bool stemDarkened;
-
- FT_Int darkenParams[8]; /* 1000 unit character space */
-
- /* variables that depend on both FontDict and Transform */
- CF2_Fixed stdVW; /* in character space; depends on dict entry */
- CF2_Fixed stdHW; /* in character space; depends on dict entry */
- CF2_Fixed darkenX; /* character space units */
- CF2_Fixed darkenY; /* depends on transform */
- /* and private dict (StdVW) */
- FT_Bool reverseWinding; /* darken assuming */
- /* counterclockwise winding */
-
- CF2_BluesRec blues; /* computed zone data */
- };
-
-
- FT_LOCAL( FT_Error )
- cf2_getGlyphOutline( CF2_Font font,
- CF2_Buffer charstring,
- const CF2_Matrix* transform,
- CF2_F16Dot16* glyphWidth );
-
-
-FT_END_HEADER
-
-
-#endif /* CF2FONT_H_ */
-
-
-/* END */
diff --git a/thirdparty/freetype/src/cff/cf2ft.c b/thirdparty/freetype/src/cff/cf2ft.c
deleted file mode 100644
index c6c00d1623..0000000000
--- a/thirdparty/freetype/src/cff/cf2ft.c
+++ /dev/null
@@ -1,755 +0,0 @@
-/***************************************************************************/
-/* */
-/* cf2ft.c */
-/* */
-/* FreeType Glue Component to Adobe's Interpreter (body). */
-/* */
-/* Copyright 2013-2014 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
-
-
-#include "cf2ft.h"
-#include FT_INTERNAL_DEBUG_H
-
-#include "cf2font.h"
-#include "cf2error.h"
-
-
-#define CF2_MAX_SIZE cf2_intToFixed( 2000 ) /* max ppem */
-
-
- /*
- * This check should avoid most internal overflow cases. Clients should
- * generally respond to `Glyph_Too_Big' by getting a glyph outline
- * at EM size, scaling it and filling it as a graphics operation.
- *
- */
- static FT_Error
- cf2_checkTransform( const CF2_Matrix* transform,
- CF2_Int unitsPerEm )
- {
- CF2_Fixed maxScale;
-
-
- FT_ASSERT( unitsPerEm > 0 );
-
- if ( transform->a <= 0 || transform->d <= 0 )
- return FT_THROW( Invalid_Size_Handle );
-
- FT_ASSERT( transform->b == 0 && transform->c == 0 );
- FT_ASSERT( transform->tx == 0 && transform->ty == 0 );
-
- if ( unitsPerEm > 0x7FFF )
- return FT_THROW( Glyph_Too_Big );
-
- maxScale = FT_DivFix( CF2_MAX_SIZE, cf2_intToFixed( unitsPerEm ) );
-
- if ( transform->a > maxScale || transform->d > maxScale )
- return FT_THROW( Glyph_Too_Big );
-
- return FT_Err_Ok;
- }
-
-
- static void
- cf2_setGlyphWidth( CF2_Outline outline,
- CF2_Fixed width )
- {
- CFF_Decoder* decoder = outline->decoder;
-
-
- FT_ASSERT( decoder );
-
- decoder->glyph_width = cf2_fixedToInt( width );
- }
-
-
- /* Clean up font instance. */
- static void
- cf2_free_instance( void* ptr )
- {
- CF2_Font font = (CF2_Font)ptr;
-
-
- if ( font )
- {
- FT_Memory memory = font->memory;
-
-
- FT_FREE( font->blend.lastNDV );
- FT_FREE( font->blend.BV );
- }
- }
-
-
- /********************************************/
- /* */
- /* functions for handling client outline; */
- /* FreeType uses coordinates in 26.6 format */
- /* */
- /********************************************/
-
- static void
- cf2_builder_moveTo( CF2_OutlineCallbacks callbacks,
- const CF2_CallbackParams params )
- {
- /* downcast the object pointer */
- CF2_Outline outline = (CF2_Outline)callbacks;
- CFF_Builder* builder;
-
- (void)params; /* only used in debug mode */
-
-
- FT_ASSERT( outline && outline->decoder );
- FT_ASSERT( params->op == CF2_PathOpMoveTo );
-
- builder = &outline->decoder->builder;
-
- /* note: two successive moves simply close the contour twice */
- cff_builder_close_contour( builder );
- builder->path_begun = 0;
- }
-
-
- static void
- cf2_builder_lineTo( CF2_OutlineCallbacks callbacks,
- const CF2_CallbackParams params )
- {
- FT_Error error;
-
- /* downcast the object pointer */
- CF2_Outline outline = (CF2_Outline)callbacks;
- CFF_Builder* builder;
-
-
- FT_ASSERT( outline && outline->decoder );
- FT_ASSERT( params->op == CF2_PathOpLineTo );
-
- builder = &outline->decoder->builder;
-
- if ( !builder->path_begun )
- {
- /* record the move before the line; also check points and set */
- /* `path_begun' */
- error = cff_builder_start_point( builder,
- params->pt0.x,
- params->pt0.y );
- if ( error )
- {
- if ( !*callbacks->error )
- *callbacks->error = error;
- return;
- }
- }
-
- /* `cff_builder_add_point1' includes a check_points call for one point */
- error = cff_builder_add_point1( builder,
- params->pt1.x,
- params->pt1.y );
- if ( error )
- {
- if ( !*callbacks->error )
- *callbacks->error = error;
- return;
- }
- }
-
-
- static void
- cf2_builder_cubeTo( CF2_OutlineCallbacks callbacks,
- const CF2_CallbackParams params )
- {
- FT_Error error;
-
- /* downcast the object pointer */
- CF2_Outline outline = (CF2_Outline)callbacks;
- CFF_Builder* builder;
-
-
- FT_ASSERT( outline && outline->decoder );
- FT_ASSERT( params->op == CF2_PathOpCubeTo );
-
- builder = &outline->decoder->builder;
-
- if ( !builder->path_begun )
- {
- /* record the move before the line; also check points and set */
- /* `path_begun' */
- error = cff_builder_start_point( builder,
- params->pt0.x,
- params->pt0.y );
- if ( error )
- {
- if ( !*callbacks->error )
- *callbacks->error = error;
- return;
- }
- }
-
- /* prepare room for 3 points: 2 off-curve, 1 on-curve */
- error = cff_check_points( builder, 3 );
- if ( error )
- {
- if ( !*callbacks->error )
- *callbacks->error = error;
- return;
- }
-
- cff_builder_add_point( builder,
- params->pt1.x,
- params->pt1.y, 0 );
- cff_builder_add_point( builder,
- params->pt2.x,
- params->pt2.y, 0 );
- cff_builder_add_point( builder,
- params->pt3.x,
- params->pt3.y, 1 );
- }
-
-
- static void
- cf2_outline_init( CF2_Outline outline,
- FT_Memory memory,
- FT_Error* error )
- {
- FT_ZERO( outline );
-
- outline->root.memory = memory;
- outline->root.error = error;
-
- outline->root.moveTo = cf2_builder_moveTo;
- outline->root.lineTo = cf2_builder_lineTo;
- outline->root.cubeTo = cf2_builder_cubeTo;
- }
-
-
- /* get scaling and hint flag from GlyphSlot */
- static void
- cf2_getScaleAndHintFlag( CFF_Decoder* decoder,
- CF2_Fixed* x_scale,
- CF2_Fixed* y_scale,
- FT_Bool* hinted,
- FT_Bool* scaled )
- {
- FT_ASSERT( decoder && decoder->builder.glyph );
-
- /* note: FreeType scale includes a factor of 64 */
- *hinted = decoder->builder.glyph->hint;
- *scaled = decoder->builder.glyph->scaled;
-
- if ( *hinted )
- {
- *x_scale = ADD_INT32( decoder->builder.glyph->x_scale, 32 ) / 64;
- *y_scale = ADD_INT32( decoder->builder.glyph->y_scale, 32 ) / 64;
- }
- else
- {
- /* for unhinted outlines, `cff_slot_load' does the scaling, */
- /* thus render at `unity' scale */
-
- *x_scale = 0x0400; /* 1/64 as 16.16 */
- *y_scale = 0x0400;
- }
- }
-
-
- /* get units per em from `FT_Face' */
- /* TODO: should handle font matrix concatenation? */
- static FT_UShort
- cf2_getUnitsPerEm( CFF_Decoder* decoder )
- {
- FT_ASSERT( decoder && decoder->builder.face );
- FT_ASSERT( decoder->builder.face->root.units_per_EM );
-
- return decoder->builder.face->root.units_per_EM;
- }
-
-
- /* Main entry point: Render one glyph. */
- FT_LOCAL_DEF( FT_Error )
- cf2_decoder_parse_charstrings( CFF_Decoder* decoder,
- FT_Byte* charstring_base,
- FT_ULong charstring_len )
- {
- FT_Memory memory;
- FT_Error error = FT_Err_Ok;
- CF2_Font font;
-
-
- FT_ASSERT( decoder && decoder->cff );
-
- memory = decoder->builder.memory;
-
- /* CF2 data is saved here across glyphs */
- font = (CF2_Font)decoder->cff->cf2_instance.data;
-
- /* on first glyph, allocate instance structure */
- if ( !decoder->cff->cf2_instance.data )
- {
- decoder->cff->cf2_instance.finalizer =
- (FT_Generic_Finalizer)cf2_free_instance;
-
- if ( FT_ALLOC( decoder->cff->cf2_instance.data,
- sizeof ( CF2_FontRec ) ) )
- return FT_THROW( Out_Of_Memory );
-
- font = (CF2_Font)decoder->cff->cf2_instance.data;
-
- font->memory = memory;
-
- /* initialize a client outline, to be shared by each glyph rendered */
- cf2_outline_init( &font->outline, font->memory, &font->error );
- }
-
- /* save decoder; it is a stack variable and will be different on each */
- /* call */
- font->decoder = decoder;
- font->outline.decoder = decoder;
-
- {
- /* build parameters for Adobe engine */
-
- CFF_Builder* builder = &decoder->builder;
- CFF_Driver driver = (CFF_Driver)FT_FACE_DRIVER( builder->face );
-
- FT_Bool no_stem_darkening_driver =
- driver->no_stem_darkening;
- FT_Char no_stem_darkening_font =
- builder->face->root.internal->no_stem_darkening;
-
- /* local error */
- FT_Error error2 = FT_Err_Ok;
- CF2_BufferRec buf;
- CF2_Matrix transform;
- CF2_F16Dot16 glyphWidth;
-
- FT_Bool hinted;
- FT_Bool scaled;
-
-
- /* FreeType has already looked up the GID; convert to */
- /* `RegionBuffer', assuming that the input has been validated */
- FT_ASSERT( charstring_base + charstring_len >= charstring_base );
-
- FT_ZERO( &buf );
- buf.start =
- buf.ptr = charstring_base;
- buf.end = charstring_base + charstring_len;
-
- FT_ZERO( &transform );
-
- cf2_getScaleAndHintFlag( decoder,
- &transform.a,
- &transform.d,
- &hinted,
- &scaled );
-
- /* copy isCFF2 boolean from TT_Face to CF2_Font */
- font->isCFF2 = builder->face->is_cff2;
-
- font->renderingFlags = 0;
- if ( hinted )
- font->renderingFlags |= CF2_FlagsHinted;
- if ( scaled && ( !no_stem_darkening_font ||
- ( no_stem_darkening_font < 0 &&
- !no_stem_darkening_driver ) ) )
- font->renderingFlags |= CF2_FlagsDarkened;
-
- font->darkenParams[0] = driver->darken_params[0];
- font->darkenParams[1] = driver->darken_params[1];
- font->darkenParams[2] = driver->darken_params[2];
- font->darkenParams[3] = driver->darken_params[3];
- font->darkenParams[4] = driver->darken_params[4];
- font->darkenParams[5] = driver->darken_params[5];
- font->darkenParams[6] = driver->darken_params[6];
- font->darkenParams[7] = driver->darken_params[7];
-
- /* now get an outline for this glyph; */
- /* also get units per em to validate scale */
- font->unitsPerEm = (CF2_Int)cf2_getUnitsPerEm( decoder );
-
- if ( scaled )
- {
- error2 = cf2_checkTransform( &transform, font->unitsPerEm );
- if ( error2 )
- return error2;
- }
-
- error2 = cf2_getGlyphOutline( font, &buf, &transform, &glyphWidth );
- if ( error2 )
- return FT_ERR( Invalid_File_Format );
-
- cf2_setGlyphWidth( &font->outline, glyphWidth );
-
- return FT_Err_Ok;
- }
- }
-
-
- /* get pointer to current FreeType subfont (based on current glyphID) */
- FT_LOCAL_DEF( CFF_SubFont )
- cf2_getSubfont( CFF_Decoder* decoder )
- {
- FT_ASSERT( decoder && decoder->current_subfont );
-
- return decoder->current_subfont;
- }
-
-
- /* get pointer to VStore structure */
- FT_LOCAL_DEF( CFF_VStore )
- cf2_getVStore( CFF_Decoder* decoder )
- {
- FT_ASSERT( decoder && decoder->cff );
-
- return &decoder->cff->vstore;
- }
-
-
- /* get maxstack value from CFF2 Top DICT */
- FT_LOCAL_DEF( FT_UInt )
- cf2_getMaxstack( CFF_Decoder* decoder )
- {
- FT_ASSERT( decoder && decoder->cff );
-
- return decoder->cff->top_font.font_dict.maxstack;
- }
-
-
-#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
- /* Get normalized design vector for current render request; */
- /* return pointer and length. */
- /* */
- /* Note: Uses FT_Fixed not CF2_Fixed for the vector. */
- FT_LOCAL_DEF( FT_Error )
- cf2_getNormalizedVector( CFF_Decoder* decoder,
- CF2_UInt *len,
- FT_Fixed* *vec )
- {
- FT_ASSERT( decoder && decoder->builder.face );
- FT_ASSERT( vec && len );
-
- return cff_get_var_blend( decoder->builder.face, len, NULL, vec, NULL );
- }
-#endif
-
-
- /* get `y_ppem' from `CFF_Size' */
- FT_LOCAL_DEF( CF2_Fixed )
- cf2_getPpemY( CFF_Decoder* decoder )
- {
- FT_ASSERT( decoder &&
- decoder->builder.face &&
- decoder->builder.face->root.size );
-
- /*
- * Note that `y_ppem' can be zero if there wasn't a call to
- * `FT_Set_Char_Size' or something similar. However, this isn't a
- * problem since we come to this place in the code only if
- * FT_LOAD_NO_SCALE is set (the other case gets caught by
- * `cf2_checkTransform'). The ppem value is needed to compute the stem
- * darkening, which is disabled for getting the unscaled outline.
- *
- */
- return cf2_intToFixed(
- decoder->builder.face->root.size->metrics.y_ppem );
- }
-
-
- /* get standard stem widths for the current subfont; */
- /* FreeType stores these as integer font units */
- /* (note: variable names seem swapped) */
- FT_LOCAL_DEF( CF2_Fixed )
- cf2_getStdVW( CFF_Decoder* decoder )
- {
- FT_ASSERT( decoder && decoder->current_subfont );
-
- return cf2_intToFixed(
- decoder->current_subfont->private_dict.standard_height );
- }
-
-
- FT_LOCAL_DEF( CF2_Fixed )
- cf2_getStdHW( CFF_Decoder* decoder )
- {
- FT_ASSERT( decoder && decoder->current_subfont );
-
- return cf2_intToFixed(
- decoder->current_subfont->private_dict.standard_width );
- }
-
-
- /* note: FreeType stores 1000 times the actual value for `BlueScale' */
- FT_LOCAL_DEF( void )
- cf2_getBlueMetrics( CFF_Decoder* decoder,
- CF2_Fixed* blueScale,
- CF2_Fixed* blueShift,
- CF2_Fixed* blueFuzz )
- {
- FT_ASSERT( decoder && decoder->current_subfont );
-
- *blueScale = FT_DivFix(
- decoder->current_subfont->private_dict.blue_scale,
- cf2_intToFixed( 1000 ) );
- *blueShift = cf2_intToFixed(
- decoder->current_subfont->private_dict.blue_shift );
- *blueFuzz = cf2_intToFixed(
- decoder->current_subfont->private_dict.blue_fuzz );
- }
-
-
- /* get blue values counts and arrays; the FreeType parser has validated */
- /* the counts and verified that each is an even number */
- FT_LOCAL_DEF( void )
- cf2_getBlueValues( CFF_Decoder* decoder,
- size_t* count,
- FT_Pos* *data )
- {
- FT_ASSERT( decoder && decoder->current_subfont );
-
- *count = decoder->current_subfont->private_dict.num_blue_values;
- *data = (FT_Pos*)
- &decoder->current_subfont->private_dict.blue_values;
- }
-
-
- FT_LOCAL_DEF( void )
- cf2_getOtherBlues( CFF_Decoder* decoder,
- size_t* count,
- FT_Pos* *data )
- {
- FT_ASSERT( decoder && decoder->current_subfont );
-
- *count = decoder->current_subfont->private_dict.num_other_blues;
- *data = (FT_Pos*)
- &decoder->current_subfont->private_dict.other_blues;
- }
-
-
- FT_LOCAL_DEF( void )
- cf2_getFamilyBlues( CFF_Decoder* decoder,
- size_t* count,
- FT_Pos* *data )
- {
- FT_ASSERT( decoder && decoder->current_subfont );
-
- *count = decoder->current_subfont->private_dict.num_family_blues;
- *data = (FT_Pos*)
- &decoder->current_subfont->private_dict.family_blues;
- }
-
-
- FT_LOCAL_DEF( void )
- cf2_getFamilyOtherBlues( CFF_Decoder* decoder,
- size_t* count,
- FT_Pos* *data )
- {
- FT_ASSERT( decoder && decoder->current_subfont );
-
- *count = decoder->current_subfont->private_dict.num_family_other_blues;
- *data = (FT_Pos*)
- &decoder->current_subfont->private_dict.family_other_blues;
- }
-
-
- FT_LOCAL_DEF( CF2_Int )
- cf2_getLanguageGroup( CFF_Decoder* decoder )
- {
- FT_ASSERT( decoder && decoder->current_subfont );
-
- return decoder->current_subfont->private_dict.language_group;
- }
-
-
- /* convert unbiased subroutine index to `CF2_Buffer' and */
- /* return 0 on success */
- FT_LOCAL_DEF( CF2_Int )
- cf2_initGlobalRegionBuffer( CFF_Decoder* decoder,
- CF2_Int subrNum,
- CF2_Buffer buf )
- {
- CF2_UInt idx;
-
-
- FT_ASSERT( decoder );
-
- FT_ZERO( buf );
-
- idx = (CF2_UInt)( subrNum + decoder->globals_bias );
- if ( idx >= decoder->num_globals )
- return TRUE; /* error */
-
- FT_ASSERT( decoder->globals );
-
- buf->start =
- buf->ptr = decoder->globals[idx];
- buf->end = decoder->globals[idx + 1];
-
- return FALSE; /* success */
- }
-
-
- /* convert AdobeStandardEncoding code to CF2_Buffer; */
- /* used for seac component */
- FT_LOCAL_DEF( FT_Error )
- cf2_getSeacComponent( CFF_Decoder* decoder,
- CF2_Int code,
- CF2_Buffer buf )
- {
- CF2_Int gid;
- FT_Byte* charstring;
- FT_ULong len;
- FT_Error error;
-
-
- FT_ASSERT( decoder );
-
- FT_ZERO( buf );
-
-#ifdef FT_CONFIG_OPTION_INCREMENTAL
- /* Incremental fonts don't necessarily have valid charsets. */
- /* They use the character code, not the glyph index, in this case. */
- if ( decoder->builder.face->root.internal->incremental_interface )
- gid = code;
- else
-#endif /* FT_CONFIG_OPTION_INCREMENTAL */
- {
- gid = cff_lookup_glyph_by_stdcharcode( decoder->cff, code );
- if ( gid < 0 )
- return FT_THROW( Invalid_Glyph_Format );
- }
-
- error = cff_get_glyph_data( decoder->builder.face,
- (CF2_UInt)gid,
- &charstring,
- &len );
- /* TODO: for now, just pass the FreeType error through */
- if ( error )
- return error;
-
- /* assume input has been validated */
- FT_ASSERT( charstring + len >= charstring );
-
- buf->start = charstring;
- buf->end = charstring + len;
- buf->ptr = buf->start;
-
- return FT_Err_Ok;
- }
-
-
- FT_LOCAL_DEF( void )
- cf2_freeSeacComponent( CFF_Decoder* decoder,
- CF2_Buffer buf )
- {
- FT_ASSERT( decoder );
-
- cff_free_glyph_data( decoder->builder.face,
- (FT_Byte**)&buf->start,
- (FT_ULong)( buf->end - buf->start ) );
- }
-
-
- FT_LOCAL_DEF( CF2_Int )
- cf2_initLocalRegionBuffer( CFF_Decoder* decoder,
- CF2_Int subrNum,
- CF2_Buffer buf )
- {
- CF2_UInt idx;
-
-
- FT_ASSERT( decoder );
-
- FT_ZERO( buf );
-
- idx = (CF2_UInt)( subrNum + decoder->locals_bias );
- if ( idx >= decoder->num_locals )
- return TRUE; /* error */
-
- FT_ASSERT( decoder->locals );
-
- buf->start =
- buf->ptr = decoder->locals[idx];
- buf->end = decoder->locals[idx + 1];
-
- return FALSE; /* success */
- }
-
-
- FT_LOCAL_DEF( CF2_Fixed )
- cf2_getDefaultWidthX( CFF_Decoder* decoder )
- {
- FT_ASSERT( decoder && decoder->current_subfont );
-
- return cf2_intToFixed(
- decoder->current_subfont->private_dict.default_width );
- }
-
-
- FT_LOCAL_DEF( CF2_Fixed )
- cf2_getNominalWidthX( CFF_Decoder* decoder )
- {
- FT_ASSERT( decoder && decoder->current_subfont );
-
- return cf2_intToFixed(
- decoder->current_subfont->private_dict.nominal_width );
- }
-
-
- FT_LOCAL_DEF( void )
- cf2_outline_reset( CF2_Outline outline )
- {
- CFF_Decoder* decoder = outline->decoder;
-
-
- FT_ASSERT( decoder );
-
- outline->root.windingMomentum = 0;
-
- FT_GlyphLoader_Rewind( decoder->builder.loader );
- }
-
-
- FT_LOCAL_DEF( void )
- cf2_outline_close( CF2_Outline outline )
- {
- CFF_Decoder* decoder = outline->decoder;
-
-
- FT_ASSERT( decoder );
-
- cff_builder_close_contour( &decoder->builder );
-
- FT_GlyphLoader_Add( decoder->builder.loader );
- }
-
-
-/* END */
diff --git a/thirdparty/freetype/src/cff/cf2ft.h b/thirdparty/freetype/src/cff/cf2ft.h
deleted file mode 100644
index b054a6e950..0000000000
--- a/thirdparty/freetype/src/cff/cf2ft.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/***************************************************************************/
-/* */
-/* cf2ft.h */
-/* */
-/* FreeType Glue Component to Adobe's Interpreter (specification). */
-/* */
-/* Copyright 2013 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
-
-
-#ifndef CF2FT_H_
-#define CF2FT_H_
-
-
-#include "cf2types.h"
-
-
- /* TODO: disable asserts for now */
-#define CF2_NDEBUG
-
-
-#include FT_SYSTEM_H
-
-#include "cf2glue.h"
-#include "cffgload.h" /* for CFF_Decoder */
-
-
-FT_BEGIN_HEADER
-
-
- FT_LOCAL( FT_Error )
- cf2_decoder_parse_charstrings( CFF_Decoder* decoder,
- FT_Byte* charstring_base,
- FT_ULong charstring_len );
-
- FT_LOCAL( CFF_SubFont )
- cf2_getSubfont( CFF_Decoder* decoder );
-
- FT_LOCAL( CFF_VStore )
- cf2_getVStore( CFF_Decoder* decoder );
-
- FT_LOCAL( FT_UInt )
- cf2_getMaxstack( CFF_Decoder* decoder );
-
-#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
- FT_LOCAL( FT_Error )
- cf2_getNormalizedVector( CFF_Decoder* decoder,
- CF2_UInt *len,
- FT_Fixed* *vec );
-#endif
-
- FT_LOCAL( CF2_Fixed )
- cf2_getPpemY( CFF_Decoder* decoder );
- FT_LOCAL( CF2_Fixed )
- cf2_getStdVW( CFF_Decoder* decoder );
- FT_LOCAL( CF2_Fixed )
- cf2_getStdHW( CFF_Decoder* decoder );
-
- FT_LOCAL( void )
- cf2_getBlueMetrics( CFF_Decoder* decoder,
- CF2_Fixed* blueScale,
- CF2_Fixed* blueShift,
- CF2_Fixed* blueFuzz );
- FT_LOCAL( void )
- cf2_getBlueValues( CFF_Decoder* decoder,
- size_t* count,
- FT_Pos* *data );
- FT_LOCAL( void )
- cf2_getOtherBlues( CFF_Decoder* decoder,
- size_t* count,
- FT_Pos* *data );
- FT_LOCAL( void )
- cf2_getFamilyBlues( CFF_Decoder* decoder,
- size_t* count,
- FT_Pos* *data );
- FT_LOCAL( void )
- cf2_getFamilyOtherBlues( CFF_Decoder* decoder,
- size_t* count,
- FT_Pos* *data );
-
- FT_LOCAL( CF2_Int )
- cf2_getLanguageGroup( CFF_Decoder* decoder );
-
- FT_LOCAL( CF2_Int )
- cf2_initGlobalRegionBuffer( CFF_Decoder* decoder,
- CF2_Int subrNum,
- CF2_Buffer buf );
- FT_LOCAL( FT_Error )
- cf2_getSeacComponent( CFF_Decoder* decoder,
- CF2_Int code,
- CF2_Buffer buf );
- FT_LOCAL( void )
- cf2_freeSeacComponent( CFF_Decoder* decoder,
- CF2_Buffer buf );
- FT_LOCAL( CF2_Int )
- cf2_initLocalRegionBuffer( CFF_Decoder* decoder,
- CF2_Int subrNum,
- CF2_Buffer buf );
-
- FT_LOCAL( CF2_Fixed )
- cf2_getDefaultWidthX( CFF_Decoder* decoder );
- FT_LOCAL( CF2_Fixed )
- cf2_getNominalWidthX( CFF_Decoder* decoder );
-
-
- /*
- * FreeType client outline
- *
- * process output from the charstring interpreter
- */
- typedef struct CF2_OutlineRec_
- {
- CF2_OutlineCallbacksRec root; /* base class must be first */
- CFF_Decoder* decoder;
-
- } CF2_OutlineRec, *CF2_Outline;
-
-
- FT_LOCAL( void )
- cf2_outline_reset( CF2_Outline outline );
- FT_LOCAL( void )
- cf2_outline_close( CF2_Outline outline );
-
-
-FT_END_HEADER
-
-
-#endif /* CF2FT_H_ */
-
-
-/* END */
diff --git a/thirdparty/freetype/src/cff/cf2glue.h b/thirdparty/freetype/src/cff/cf2glue.h
deleted file mode 100644
index 56a7c248f4..0000000000
--- a/thirdparty/freetype/src/cff/cf2glue.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/***************************************************************************/
-/* */
-/* cf2glue.h */
-/* */
-/* Adobe's code for shared stuff (specification only). */
-/* */
-/* Copyright 2007-2013 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
-
-
-#ifndef CF2GLUE_H_
-#define CF2GLUE_H_
-
-
-/* common includes for other modules */
-#include "cf2error.h"
-#include "cf2fixed.h"
-#include "cf2arrst.h"
-#include "cf2read.h"
-
-
-FT_BEGIN_HEADER
-
-
- /* rendering parameters */
-
- /* apply hints to rendered glyphs */
-#define CF2_FlagsHinted 1
- /* for testing */
-#define CF2_FlagsDarkened 2
-
- /* type for holding the flags */
- typedef CF2_Int CF2_RenderingFlags;
-
-
- /* elements of a glyph outline */
- typedef enum CF2_PathOp_
- {
- CF2_PathOpMoveTo = 1, /* change the current point */
- CF2_PathOpLineTo = 2, /* line */
- CF2_PathOpQuadTo = 3, /* quadratic curve */
- CF2_PathOpCubeTo = 4 /* cubic curve */
-
- } CF2_PathOp;
-
-
- /* a matrix of fixed point values */
- typedef struct CF2_Matrix_
- {
- CF2_F16Dot16 a;
- CF2_F16Dot16 b;
- CF2_F16Dot16 c;
- CF2_F16Dot16 d;
- CF2_F16Dot16 tx;
- CF2_F16Dot16 ty;
-
- } CF2_Matrix;
-
-
- /* these typedefs are needed by more than one header file */
- /* and gcc compiler doesn't allow redefinition */
- typedef struct CF2_FontRec_ CF2_FontRec, *CF2_Font;
- typedef struct CF2_HintRec_ CF2_HintRec, *CF2_Hint;
-
-
- /* A common structure for all callback parameters. */
- /* */
- /* Some members may be unused. For example, `pt0' is not used for */
- /* `moveTo' and `pt3' is not used for `quadTo'. The initial point `pt0' */
- /* is included for each path element for generality; curve conversions */
- /* need it. The `op' parameter allows one function to handle multiple */
- /* element types. */
-
- typedef struct CF2_CallbackParamsRec_
- {
- FT_Vector pt0;
- FT_Vector pt1;
- FT_Vector pt2;
- FT_Vector pt3;
-
- CF2_Int op;
-
- } CF2_CallbackParamsRec, *CF2_CallbackParams;
-
-
- /* forward reference */
- typedef struct CF2_OutlineCallbacksRec_ CF2_OutlineCallbacksRec,
- *CF2_OutlineCallbacks;
-
- /* callback function pointers */
- typedef void
- (*CF2_Callback_Type)( CF2_OutlineCallbacks callbacks,
- const CF2_CallbackParams params );
-
-
- struct CF2_OutlineCallbacksRec_
- {
- CF2_Callback_Type moveTo;
- CF2_Callback_Type lineTo;
- CF2_Callback_Type quadTo;
- CF2_Callback_Type cubeTo;
-
- CF2_Int windingMomentum; /* for winding order detection */
-
- FT_Memory memory;
- FT_Error* error;
- };
-
-
-FT_END_HEADER
-
-
-#endif /* CF2GLUE_H_ */
-
-
-/* END */
diff --git a/thirdparty/freetype/src/cff/cf2hints.c b/thirdparty/freetype/src/cff/cf2hints.c
deleted file mode 100644
index 656eb2cff1..0000000000
--- a/thirdparty/freetype/src/cff/cf2hints.c
+++ /dev/null
@@ -1,1875 +0,0 @@
-/***************************************************************************/
-/* */
-/* cf2hints.c */
-/* */
-/* Adobe's code for handling CFF hints (body). */
-/* */
-/* Copyright 2007-2014 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
-
-
-#include "cf2ft.h"
-#include FT_INTERNAL_DEBUG_H
-
-#include "cf2glue.h"
-#include "cf2font.h"
-#include "cf2hints.h"
-#include "cf2intrp.h"
-
-
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
-#undef FT_COMPONENT
-#define FT_COMPONENT trace_cf2hints
-
-
- typedef struct CF2_HintMoveRec_
- {
- size_t j; /* index of upper hint map edge */
- CF2_Fixed moveUp; /* adjustment to optimum position */
-
- } CF2_HintMoveRec, *CF2_HintMove;
-
-
- /* Compute angular momentum for winding order detection. It is called */
- /* for all lines and curves, but not necessarily in element order. */
- static CF2_Int
- cf2_getWindingMomentum( CF2_Fixed x1,
- CF2_Fixed y1,
- CF2_Fixed x2,
- CF2_Fixed y2 )
- {
- /* cross product of pt1 position from origin with pt2 position from */
- /* pt1; we reduce the precision so that the result fits into 32 bits */
-
- return ( x1 >> 16 ) * ( SUB_INT32( y2, y1 ) >> 16 ) -
- ( y1 >> 16 ) * ( SUB_INT32( x2, x1 ) >> 16 );
- }
-
-
- /*
- * Construct from a StemHint; this is used as a parameter to
- * `cf2_blues_capture'.
- * `hintOrigin' is the character space displacement of a seac accent.
- * Adjust stem hint for darkening here.
- *
- */
- static void
- cf2_hint_init( CF2_Hint hint,
- const CF2_ArrStack stemHintArray,
- size_t indexStemHint,
- const CF2_Font font,
- CF2_Fixed hintOrigin,
- CF2_Fixed scale,
- FT_Bool bottom )
- {
- CF2_Fixed width;
- const CF2_StemHintRec* stemHint;
-
-
- FT_ZERO( hint );
-
- stemHint = (const CF2_StemHintRec*)cf2_arrstack_getPointer(
- stemHintArray,
- indexStemHint );
-
- width = SUB_INT32( stemHint->max, stemHint->min );
-
- if ( width == cf2_intToFixed( -21 ) )
- {
- /* ghost bottom */
-
- if ( bottom )
- {
- hint->csCoord = stemHint->max;
- hint->flags = CF2_GhostBottom;
- }
- else
- hint->flags = 0;
- }
-
- else if ( width == cf2_intToFixed( -20 ) )
- {
- /* ghost top */
-
- if ( bottom )
- hint->flags = 0;
- else
- {
- hint->csCoord = stemHint->min;
- hint->flags = CF2_GhostTop;
- }
- }
-
- else if ( width < 0 )
- {
- /* inverted pair */
-
- /*
- * Hints with negative widths were produced by an early version of a
- * non-Adobe font tool. The Type 2 spec allows edge (ghost) hints
- * with negative widths, but says
- *
- * All other negative widths have undefined meaning.
- *
- * CoolType has a silent workaround that negates the hint width; for
- * permissive mode, we do the same here.
- *
- * Note: Such fonts cannot use ghost hints, but should otherwise work.
- * Note: Some poor hints in our faux fonts can produce negative
- * widths at some blends. For example, see a light weight of
- * `u' in ASerifMM.
- *
- */
- if ( bottom )
- {
- hint->csCoord = stemHint->max;
- hint->flags = CF2_PairBottom;
- }
- else
- {
- hint->csCoord = stemHint->min;
- hint->flags = CF2_PairTop;
- }
- }
-
- else
- {
- /* normal pair */
-
- if ( bottom )
- {
- hint->csCoord = stemHint->min;
- hint->flags = CF2_PairBottom;
- }
- else
- {
- hint->csCoord = stemHint->max;
- hint->flags = CF2_PairTop;
- }
- }
-
- /* Now that ghost hints have been detected, adjust this edge for */
- /* darkening. Bottoms are not changed; tops are incremented by twice */
- /* `darkenY'. */
- if ( cf2_hint_isTop( hint ) )
- hint->csCoord = ADD_INT32( hint->csCoord, 2 * font->darkenY );
-
- hint->csCoord = ADD_INT32( hint->csCoord, hintOrigin );
- hint->scale = scale;
- hint->index = indexStemHint; /* index in original stem hint array */
-
- /* if original stem hint has been used, use the same position */
- if ( hint->flags != 0 && stemHint->used )
- {
- if ( cf2_hint_isTop( hint ) )
- hint->dsCoord = stemHint->maxDS;
- else
- hint->dsCoord = stemHint->minDS;
-
- cf2_hint_lock( hint );
- }
- else
- hint->dsCoord = FT_MulFix( hint->csCoord, scale );
- }
-
-
- /* initialize an invalid hint map element */
- static void
- cf2_hint_initZero( CF2_Hint hint )
- {
- FT_ZERO( hint );
- }
-
-
- FT_LOCAL_DEF( FT_Bool )
- cf2_hint_isValid( const CF2_Hint hint )
- {
- return (FT_Bool)( hint->flags != 0 );
- }
-
-
- static FT_Bool
- cf2_hint_isPair( const CF2_Hint hint )
- {
- return (FT_Bool)( ( hint->flags &
- ( CF2_PairBottom | CF2_PairTop ) ) != 0 );
- }
-
-
- static FT_Bool
- cf2_hint_isPairTop( const CF2_Hint hint )
- {
- return (FT_Bool)( ( hint->flags & CF2_PairTop ) != 0 );
- }
-
-
- FT_LOCAL_DEF( FT_Bool )
- cf2_hint_isTop( const CF2_Hint hint )
- {
- return (FT_Bool)( ( hint->flags &
- ( CF2_PairTop | CF2_GhostTop ) ) != 0 );
- }
-
-
- FT_LOCAL_DEF( FT_Bool )
- cf2_hint_isBottom( const CF2_Hint hint )
- {
- return (FT_Bool)( ( hint->flags &
- ( CF2_PairBottom | CF2_GhostBottom ) ) != 0 );
- }
-
-
- static FT_Bool
- cf2_hint_isLocked( const CF2_Hint hint )
- {
- return (FT_Bool)( ( hint->flags & CF2_Locked ) != 0 );
- }
-
-
- static FT_Bool
- cf2_hint_isSynthetic( const CF2_Hint hint )
- {
- return (FT_Bool)( ( hint->flags & CF2_Synthetic ) != 0 );
- }
-
-
- FT_LOCAL_DEF( void )
- cf2_hint_lock( CF2_Hint hint )
- {
- hint->flags |= CF2_Locked;
- }
-
-
- FT_LOCAL_DEF( void )
- cf2_hintmap_init( CF2_HintMap hintmap,
- CF2_Font font,
- CF2_HintMap initialMap,
- CF2_ArrStack hintMoves,
- CF2_Fixed scale )
- {
- FT_ZERO( hintmap );
-
- /* copy parameters from font instance */
- hintmap->hinted = font->hinted;
- hintmap->scale = scale;
- hintmap->font = font;
- hintmap->initialHintMap = initialMap;
- /* will clear in `cf2_hintmap_adjustHints' */
- hintmap->hintMoves = hintMoves;
- }
-
-
- static FT_Bool
- cf2_hintmap_isValid( const CF2_HintMap hintmap )
- {
- return hintmap->isValid;
- }
-
-
- /* transform character space coordinate to device space using hint map */
- static CF2_Fixed
- cf2_hintmap_map( CF2_HintMap hintmap,
- CF2_Fixed csCoord )
- {
- if ( hintmap->count == 0 || ! hintmap->hinted )
- {
- /* there are no hints; use uniform scale and zero offset */
- return FT_MulFix( csCoord, hintmap->scale );
- }
- else
- {
- /* start linear search from last hit */
- CF2_UInt i = hintmap->lastIndex;
-
-
- FT_ASSERT( hintmap->lastIndex < CF2_MAX_HINT_EDGES );
-
- /* search up */
- while ( i < hintmap->count - 1 &&
- csCoord >= hintmap->edge[i + 1].csCoord )
- i += 1;
-
- /* search down */
- while ( i > 0 && csCoord < hintmap->edge[i].csCoord )
- i -= 1;
-
- hintmap->lastIndex = i;
-
- if ( i == 0 && csCoord < hintmap->edge[0].csCoord )
- {
- /* special case for points below first edge: use uniform scale */
- return ADD_INT32( FT_MulFix( SUB_INT32( csCoord,
- hintmap->edge[0].csCoord ),
- hintmap->scale ),
- hintmap->edge[0].dsCoord );
- }
- else
- {
- /*
- * Note: entries with duplicate csCoord are allowed.
- * Use edge[i], the highest entry where csCoord >= entry[i].csCoord
- */
- return ADD_INT32( FT_MulFix( SUB_INT32( csCoord,
- hintmap->edge[i].csCoord ),
- hintmap->edge[i].scale ),
- hintmap->edge[i].dsCoord );
- }
- }
- }
-
-
- /*
- * This hinting policy moves a hint pair in device space so that one of
- * its two edges is on a device pixel boundary (its fractional part is
- * zero). `cf2_hintmap_insertHint' guarantees no overlap in CS
- * space. Ensure here that there is no overlap in DS.
- *
- * In the first pass, edges are adjusted relative to adjacent hints.
- * Those that are below have already been adjusted. Those that are
- * above have not yet been adjusted. If a hint above blocks an
- * adjustment to an optimal position, we will try again in a second
- * pass. The second pass is top-down.
- *
- */
-
- static void
- cf2_hintmap_adjustHints( CF2_HintMap hintmap )
- {
- size_t i, j;
-
-
- cf2_arrstack_clear( hintmap->hintMoves ); /* working storage */
-
- /*
- * First pass is bottom-up (font hint order) without look-ahead.
- * Locked edges are already adjusted.
- * Unlocked edges begin with dsCoord from `initialHintMap'.
- * Save edges that are not optimally adjusted in `hintMoves' array,
- * and process them in second pass.
- */
-
- for ( i = 0; i < hintmap->count; i++ )
- {
- FT_Bool isPair = cf2_hint_isPair( &hintmap->edge[i] );
-
-
- /* index of upper edge (same value for ghost hint) */
- j = isPair ? i + 1 : i;
-
- FT_ASSERT( j < hintmap->count );
- FT_ASSERT( cf2_hint_isValid( &hintmap->edge[i] ) );
- FT_ASSERT( cf2_hint_isValid( &hintmap->edge[j] ) );
- FT_ASSERT( cf2_hint_isLocked( &hintmap->edge[i] ) ==
- cf2_hint_isLocked( &hintmap->edge[j] ) );
-
- if ( !cf2_hint_isLocked( &hintmap->edge[i] ) )
- {
- /* hint edge is not locked, we can adjust it */
- CF2_Fixed fracDown = cf2_fixedFraction( hintmap->edge[i].dsCoord );
- CF2_Fixed fracUp = cf2_fixedFraction( hintmap->edge[j].dsCoord );
-
- /* calculate all four possibilities; moves down are negative */
- CF2_Fixed downMoveDown = 0 - fracDown;
- CF2_Fixed upMoveDown = 0 - fracUp;
- CF2_Fixed downMoveUp = ( fracDown == 0 )
- ? 0
- : cf2_intToFixed( 1 ) - fracDown;
- CF2_Fixed upMoveUp = ( fracUp == 0 )
- ? 0
- : cf2_intToFixed( 1 ) - fracUp;
-
- /* smallest move up */
- CF2_Fixed moveUp = FT_MIN( downMoveUp, upMoveUp );
- /* smallest move down */
- CF2_Fixed moveDown = FT_MAX( downMoveDown, upMoveDown );
-
- /* final amount to move edge or edge pair */
- CF2_Fixed move;
-
- CF2_Fixed downMinCounter = CF2_MIN_COUNTER;
- CF2_Fixed upMinCounter = CF2_MIN_COUNTER;
- FT_Bool saveEdge = FALSE;
-
-
- /* minimum counter constraint doesn't apply when adjacent edges */
- /* are synthetic */
- /* TODO: doesn't seem a big effect; for now, reduce the code */
-#if 0
- if ( i == 0 ||
- cf2_hint_isSynthetic( &hintmap->edge[i - 1] ) )
- downMinCounter = 0;
-
- if ( j >= hintmap->count - 1 ||
- cf2_hint_isSynthetic( &hintmap->edge[j + 1] ) )
- upMinCounter = 0;
-#endif
-
- /* is there room to move up? */
- /* there is if we are at top of array or the next edge is at or */
- /* beyond proposed move up? */
- if ( j >= hintmap->count - 1 ||
- hintmap->edge[j + 1].dsCoord >=
- ADD_INT32( hintmap->edge[j].dsCoord,
- moveUp + upMinCounter ) )
- {
- /* there is room to move up; is there also room to move down? */
- if ( i == 0 ||
- hintmap->edge[i - 1].dsCoord <=
- ADD_INT32( hintmap->edge[i].dsCoord,
- moveDown - downMinCounter ) )
- {
- /* move smaller absolute amount */
- move = ( -moveDown < moveUp ) ? moveDown : moveUp; /* optimum */
- }
- else
- move = moveUp;
- }
- else
- {
- /* is there room to move down? */
- if ( i == 0 ||
- hintmap->edge[i - 1].dsCoord <=
- ADD_INT32( hintmap->edge[i].dsCoord,
- moveDown - downMinCounter ) )
- {
- move = moveDown;
- /* true if non-optimum move */
- saveEdge = (FT_Bool)( moveUp < -moveDown );
- }
- else
- {
- /* no room to move either way without overlapping or reducing */
- /* the counter too much */
- move = 0;
- saveEdge = TRUE;
- }
- }
-
- /* Identify non-moves and moves down that aren't optimal, and save */
- /* them for second pass. */
- /* Do this only if there is an unlocked edge above (which could */
- /* possibly move). */
- if ( saveEdge &&
- j < hintmap->count - 1 &&
- !cf2_hint_isLocked( &hintmap->edge[j + 1] ) )
- {
- CF2_HintMoveRec savedMove;
-
-
- savedMove.j = j;
- /* desired adjustment in second pass */
- savedMove.moveUp = moveUp - move;
-
- cf2_arrstack_push( hintmap->hintMoves, &savedMove );
- }
-
- /* move the edge(s) */
- hintmap->edge[i].dsCoord = ADD_INT32( hintmap->edge[i].dsCoord,
- move );
- if ( isPair )
- hintmap->edge[j].dsCoord = ADD_INT32( hintmap->edge[j].dsCoord,
- move );
- }
-
- /* assert there are no overlaps in device space */
- FT_ASSERT( i == 0 ||
- hintmap->edge[i - 1].dsCoord <= hintmap->edge[i].dsCoord );
- FT_ASSERT( i < j ||
- hintmap->edge[i].dsCoord <= hintmap->edge[j].dsCoord );
-
- /* adjust the scales, avoiding divide by zero */
- if ( i > 0 )
- {
- if ( hintmap->edge[i].csCoord != hintmap->edge[i - 1].csCoord )
- hintmap->edge[i - 1].scale =
- FT_DivFix( SUB_INT32( hintmap->edge[i].dsCoord,
- hintmap->edge[i - 1].dsCoord ),
- SUB_INT32( hintmap->edge[i].csCoord,
- hintmap->edge[i - 1].csCoord ) );
- }
-
- if ( isPair )
- {
- if ( hintmap->edge[j].csCoord != hintmap->edge[j - 1].csCoord )
- hintmap->edge[j - 1].scale =
- FT_DivFix( SUB_INT32( hintmap->edge[j].dsCoord,
- hintmap->edge[j - 1].dsCoord ),
- SUB_INT32( hintmap->edge[j].csCoord,
- hintmap->edge[j - 1].csCoord ) );
-
- i += 1; /* skip upper edge on next loop */
- }
- }
-
- /* second pass tries to move non-optimal hints up, in case there is */
- /* room now */
- for ( i = cf2_arrstack_size( hintmap->hintMoves ); i > 0; i-- )
- {
- CF2_HintMove hintMove = (CF2_HintMove)
- cf2_arrstack_getPointer( hintmap->hintMoves, i - 1 );
-
-
- j = hintMove->j;
-
- /* this was tested before the push, above */
- FT_ASSERT( j < hintmap->count - 1 );
-
- /* is there room to move up? */
- if ( hintmap->edge[j + 1].dsCoord >=
- ADD_INT32( hintmap->edge[j].dsCoord,
- hintMove->moveUp + CF2_MIN_COUNTER ) )
- {
- /* there is more room now, move edge up */
- hintmap->edge[j].dsCoord = ADD_INT32( hintmap->edge[j].dsCoord,
- hintMove->moveUp );
-
- if ( cf2_hint_isPair( &hintmap->edge[j] ) )
- {
- FT_ASSERT( j > 0 );
- hintmap->edge[j - 1].dsCoord =
- ADD_INT32( hintmap->edge[j - 1].dsCoord, hintMove->moveUp );
- }
- }
- }
- }
-
-
- /* insert hint edges into map, sorted by csCoord */
- static void
- cf2_hintmap_insertHint( CF2_HintMap hintmap,
- CF2_Hint bottomHintEdge,
- CF2_Hint topHintEdge )
- {
- CF2_UInt indexInsert;
-
- /* set default values, then check for edge hints */
- FT_Bool isPair = TRUE;
- CF2_Hint firstHintEdge = bottomHintEdge;
- CF2_Hint secondHintEdge = topHintEdge;
-
-
- /* one or none of the input params may be invalid when dealing with */
- /* edge hints; at least one edge must be valid */
- FT_ASSERT( cf2_hint_isValid( bottomHintEdge ) ||
- cf2_hint_isValid( topHintEdge ) );
-
- /* determine how many and which edges to insert */
- if ( !cf2_hint_isValid( bottomHintEdge ) )
- {
- /* insert only the top edge */
- firstHintEdge = topHintEdge;
- isPair = FALSE;
- }
- else if ( !cf2_hint_isValid( topHintEdge ) )
- {
- /* insert only the bottom edge */
- isPair = FALSE;
- }
-
- /* paired edges must be in proper order */
- if ( isPair &&
- topHintEdge->csCoord < bottomHintEdge->csCoord )
- return;
-
- /* linear search to find index value of insertion point */
- indexInsert = 0;
- for ( ; indexInsert < hintmap->count; indexInsert++ )
- {
- if ( hintmap->edge[indexInsert].csCoord >= firstHintEdge->csCoord )
- break;
- }
-
- /*
- * Discard any hints that overlap in character space. Most often, this
- * is while building the initial map, where captured hints from all
- * zones are combined. Define overlap to include hints that `touch'
- * (overlap zero). Hiragino Sans/Gothic fonts have numerous hints that
- * touch. Some fonts have non-ideographic glyphs that overlap our
- * synthetic hints.
- *
- * Overlap also occurs when darkening stem hints that are close.
- *
- */
- if ( indexInsert < hintmap->count )
- {
- /* we are inserting before an existing edge: */
- /* verify that an existing edge is not the same */
- if ( hintmap->edge[indexInsert].csCoord == firstHintEdge->csCoord )
- return; /* ignore overlapping stem hint */
-
- /* verify that a new pair does not straddle the next edge */
- if ( isPair &&
- hintmap->edge[indexInsert].csCoord <= secondHintEdge->csCoord )
- return; /* ignore overlapping stem hint */
-
- /* verify that we are not inserting between paired edges */
- if ( cf2_hint_isPairTop( &hintmap->edge[indexInsert] ) )
- return; /* ignore overlapping stem hint */
- }
-
- /* recompute device space locations using initial hint map */
- if ( cf2_hintmap_isValid( hintmap->initialHintMap ) &&
- !cf2_hint_isLocked( firstHintEdge ) )
- {
- if ( isPair )
- {
- /* Use hint map to position the center of stem, and nominal scale */
- /* to position the two edges. This preserves the stem width. */
- CF2_Fixed midpoint =
- cf2_hintmap_map(
- hintmap->initialHintMap,
- ADD_INT32( secondHintEdge->csCoord,
- firstHintEdge->csCoord ) / 2 );
- CF2_Fixed halfWidth =
- FT_MulFix( SUB_INT32( secondHintEdge->csCoord,
- firstHintEdge->csCoord ) / 2,
- hintmap->scale );
-
-
- firstHintEdge->dsCoord = SUB_INT32( midpoint, halfWidth );
- secondHintEdge->dsCoord = ADD_INT32( midpoint, halfWidth );
- }
- else
- firstHintEdge->dsCoord = cf2_hintmap_map( hintmap->initialHintMap,
- firstHintEdge->csCoord );
- }
-
- /*
- * Discard any hints that overlap in device space; this can occur
- * because locked hints have been moved to align with blue zones.
- *
- * TODO: Although we might correct this later during adjustment, we
- * don't currently have a way to delete a conflicting hint once it has
- * been inserted. See v2.030 MinionPro-Regular, 12 ppem darkened,
- * initial hint map for second path, glyph 945 (the perispomeni (tilde)
- * in U+1F6E, Greek omega with psili and perispomeni). Darkening is
- * 25. Pair 667,747 initially conflicts in design space with top edge
- * 660. This is because 667 maps to 7.87, and the top edge was
- * captured by a zone at 8.0. The pair is later successfully inserted
- * in a zone without the top edge. In this zone it is adjusted to 8.0,
- * and no longer conflicts with the top edge in design space. This
- * means it can be included in yet a later zone which does have the top
- * edge hint. This produces a small mismatch between the first and
- * last points of this path, even though the hint masks are the same.
- * The density map difference is tiny (1/256).
- *
- */
-
- if ( indexInsert > 0 )
- {
- /* we are inserting after an existing edge */
- if ( firstHintEdge->dsCoord < hintmap->edge[indexInsert - 1].dsCoord )
- return;
- }
-
- if ( indexInsert < hintmap->count )
- {
- /* we are inserting before an existing edge */
- if ( isPair )
- {
- if ( secondHintEdge->dsCoord > hintmap->edge[indexInsert].dsCoord )
- return;
- }
- else
- {
- if ( firstHintEdge->dsCoord > hintmap->edge[indexInsert].dsCoord )
- return;
- }
- }
-
- /* make room to insert */
- {
- CF2_UInt iSrc = hintmap->count - 1;
- CF2_UInt iDst = isPair ? hintmap->count + 1 : hintmap->count;
-
- CF2_UInt count = hintmap->count - indexInsert;
-
-
- if ( iDst >= CF2_MAX_HINT_EDGES )
- {
- FT_TRACE4(( "cf2_hintmap_insertHint: too many hintmaps\n" ));
- return;
- }
-
- while ( count-- )
- hintmap->edge[iDst--] = hintmap->edge[iSrc--];
-
- /* insert first edge */
- hintmap->edge[indexInsert] = *firstHintEdge; /* copy struct */
- hintmap->count += 1;
-
- if ( isPair )
- {
- /* insert second edge */
- hintmap->edge[indexInsert + 1] = *secondHintEdge; /* copy struct */
- hintmap->count += 1;
- }
- }
-
- return;
- }
-
-
- /*
- * Build a map from hints and mask.
- *
- * This function may recur one level if `hintmap->initialHintMap' is not yet
- * valid.
- * If `initialMap' is true, simply build initial map.
- *
- * Synthetic hints are used in two ways. A hint at zero is inserted, if
- * needed, in the initial hint map, to prevent translations from
- * propagating across the origin. If synthetic em box hints are enabled
- * for ideographic dictionaries, then they are inserted in all hint
- * maps, including the initial one.
- *
- */
- FT_LOCAL_DEF( void )
- cf2_hintmap_build( CF2_HintMap hintmap,
- CF2_ArrStack hStemHintArray,
- CF2_ArrStack vStemHintArray,
- CF2_HintMask hintMask,
- CF2_Fixed hintOrigin,
- FT_Bool initialMap )
- {
- FT_Byte* maskPtr;
-
- CF2_Font font = hintmap->font;
- CF2_HintMaskRec tempHintMask;
-
- size_t bitCount, i;
- FT_Byte maskByte;
-
-
- /* check whether initial map is constructed */
- if ( !initialMap && !cf2_hintmap_isValid( hintmap->initialHintMap ) )
- {
- /* make recursive call with initialHintMap and temporary mask; */
- /* temporary mask will get all bits set, below */
- cf2_hintmask_init( &tempHintMask, hintMask->error );
- cf2_hintmap_build( hintmap->initialHintMap,
- hStemHintArray,
- vStemHintArray,
- &tempHintMask,
- hintOrigin,
- TRUE );
- }
-
- if ( !cf2_hintmask_isValid( hintMask ) )
- {
- /* without a hint mask, assume all hints are active */
- cf2_hintmask_setAll( hintMask,
- cf2_arrstack_size( hStemHintArray ) +
- cf2_arrstack_size( vStemHintArray ) );
- if ( !cf2_hintmask_isValid( hintMask ) )
- return; /* too many stem hints */
- }
-
- /* begin by clearing the map */
- hintmap->count = 0;
- hintmap->lastIndex = 0;
-
- /* make a copy of the hint mask so we can modify it */
- tempHintMask = *hintMask;
- maskPtr = cf2_hintmask_getMaskPtr( &tempHintMask );
-
- /* use the hStem hints only, which are first in the mask */
- bitCount = cf2_arrstack_size( hStemHintArray );
-
- /* Defense-in-depth. Should never return here. */
- if ( bitCount > hintMask->bitCount )
- return;
-
- /* synthetic embox hints get highest priority */
- if ( font->blues.doEmBoxHints )
- {
- CF2_HintRec dummy;
-
-
- cf2_hint_initZero( &dummy ); /* invalid hint map element */
-
- /* ghost bottom */
- cf2_hintmap_insertHint( hintmap,
- &font->blues.emBoxBottomEdge,
- &dummy );
- /* ghost top */
- cf2_hintmap_insertHint( hintmap,
- &dummy,
- &font->blues.emBoxTopEdge );
- }
-
- /* insert hints captured by a blue zone or already locked (higher */
- /* priority) */
- for ( i = 0, maskByte = 0x80; i < bitCount; i++ )
- {
- if ( maskByte & *maskPtr )
- {
- /* expand StemHint into two `CF2_Hint' elements */
- CF2_HintRec bottomHintEdge, topHintEdge;
-
-
- cf2_hint_init( &bottomHintEdge,
- hStemHintArray,
- i,
- font,
- hintOrigin,
- hintmap->scale,
- TRUE /* bottom */ );
- cf2_hint_init( &topHintEdge,
- hStemHintArray,
- i,
- font,
- hintOrigin,
- hintmap->scale,
- FALSE /* top */ );
-
- if ( cf2_hint_isLocked( &bottomHintEdge ) ||
- cf2_hint_isLocked( &topHintEdge ) ||
- cf2_blues_capture( &font->blues,
- &bottomHintEdge,
- &topHintEdge ) )
- {
- /* insert captured hint into map */
- cf2_hintmap_insertHint( hintmap, &bottomHintEdge, &topHintEdge );
-
- *maskPtr &= ~maskByte; /* turn off the bit for this hint */
- }
- }
-
- if ( ( i & 7 ) == 7 )
- {
- /* move to next mask byte */
- maskPtr++;
- maskByte = 0x80;
- }
- else
- maskByte >>= 1;
- }
-
- /* initial hint map includes only captured hints plus maybe one at 0 */
-
- /*
- * TODO: There is a problem here because we are trying to build a
- * single hint map containing all captured hints. It is
- * possible for there to be conflicts between captured hints,
- * either because of darkening or because the hints are in
- * separate hint zones (we are ignoring hint zones for the
- * initial map). An example of the latter is MinionPro-Regular
- * v2.030 glyph 883 (Greek Capital Alpha with Psili) at 15ppem.
- * A stem hint for the psili conflicts with the top edge hint
- * for the base character. The stem hint gets priority because
- * of its sort order. In glyph 884 (Greek Capital Alpha with
- * Psili and Oxia), the top of the base character gets a stem
- * hint, and the psili does not. This creates different initial
- * maps for the two glyphs resulting in different renderings of
- * the base character. Will probably defer this either as not
- * worth the cost or as a font bug. I don't think there is any
- * good reason for an accent to be captured by an alignment
- * zone. -darnold 2/12/10
- */
-
- if ( initialMap )
- {
- /* Apply a heuristic that inserts a point for (0,0), unless it's */
- /* already covered by a mapping. This locks the baseline for glyphs */
- /* that have no baseline hints. */
-
- if ( hintmap->count == 0 ||
- hintmap->edge[0].csCoord > 0 ||
- hintmap->edge[hintmap->count - 1].csCoord < 0 )
- {
- /* all edges are above 0 or all edges are below 0; */
- /* construct a locked edge hint at 0 */
-
- CF2_HintRec edge, invalid;
-
-
- cf2_hint_initZero( &edge );
-
- edge.flags = CF2_GhostBottom |
- CF2_Locked |
- CF2_Synthetic;
- edge.scale = hintmap->scale;
-
- cf2_hint_initZero( &invalid );
- cf2_hintmap_insertHint( hintmap, &edge, &invalid );
- }
- }
- else
- {
- /* insert remaining hints */
-
- maskPtr = cf2_hintmask_getMaskPtr( &tempHintMask );
-
- for ( i = 0, maskByte = 0x80; i < bitCount; i++ )
- {
- if ( maskByte & *maskPtr )
- {
- CF2_HintRec bottomHintEdge, topHintEdge;
-
-
- cf2_hint_init( &bottomHintEdge,
- hStemHintArray,
- i,
- font,
- hintOrigin,
- hintmap->scale,
- TRUE /* bottom */ );
- cf2_hint_init( &topHintEdge,
- hStemHintArray,
- i,
- font,
- hintOrigin,
- hintmap->scale,
- FALSE /* top */ );
-
- cf2_hintmap_insertHint( hintmap, &bottomHintEdge, &topHintEdge );
- }
-
- if ( ( i & 7 ) == 7 )
- {
- /* move to next mask byte */
- maskPtr++;
- maskByte = 0x80;
- }
- else
- maskByte >>= 1;
- }
- }
-
- /*
- * Note: The following line is a convenient place to break when
- * debugging hinting. Examine `hintmap->edge' for the list of
- * enabled hints, then step over the call to see the effect of
- * adjustment. We stop here first on the recursive call that
- * creates the initial map, and then on each counter group and
- * hint zone.
- */
-
- /* adjust positions of hint edges that are not locked to blue zones */
- cf2_hintmap_adjustHints( hintmap );
-
- /* save the position of all hints that were used in this hint map; */
- /* if we use them again, we'll locate them in the same position */
- if ( !initialMap )
- {
- for ( i = 0; i < hintmap->count; i++ )
- {
- if ( !cf2_hint_isSynthetic( &hintmap->edge[i] ) )
- {
- /* Note: include both valid and invalid edges */
- /* Note: top and bottom edges are copied back separately */
- CF2_StemHint stemhint = (CF2_StemHint)
- cf2_arrstack_getPointer( hStemHintArray,
- hintmap->edge[i].index );
-
-
- if ( cf2_hint_isTop( &hintmap->edge[i] ) )
- stemhint->maxDS = hintmap->edge[i].dsCoord;
- else
- stemhint->minDS = hintmap->edge[i].dsCoord;
-
- stemhint->used = TRUE;
- }
- }
- }
-
- /* hint map is ready to use */
- hintmap->isValid = TRUE;
-
- /* remember this mask has been used */
- cf2_hintmask_setNew( hintMask, FALSE );
- }
-
-
- FT_LOCAL_DEF( void )
- cf2_glyphpath_init( CF2_GlyphPath glyphpath,
- CF2_Font font,
- CF2_OutlineCallbacks callbacks,
- CF2_Fixed scaleY,
- /* CF2_Fixed hShift, */
- CF2_ArrStack hStemHintArray,
- CF2_ArrStack vStemHintArray,
- CF2_HintMask hintMask,
- CF2_Fixed hintOriginY,
- const CF2_Blues blues,
- const FT_Vector* fractionalTranslation )
- {
- FT_ZERO( glyphpath );
-
- glyphpath->font = font;
- glyphpath->callbacks = callbacks;
-
- cf2_arrstack_init( &glyphpath->hintMoves,
- font->memory,
- &font->error,
- sizeof ( CF2_HintMoveRec ) );
-
- cf2_hintmap_init( &glyphpath->initialHintMap,
- font,
- &glyphpath->initialHintMap,
- &glyphpath->hintMoves,
- scaleY );
- cf2_hintmap_init( &glyphpath->firstHintMap,
- font,
- &glyphpath->initialHintMap,
- &glyphpath->hintMoves,
- scaleY );
- cf2_hintmap_init( &glyphpath->hintMap,
- font,
- &glyphpath->initialHintMap,
- &glyphpath->hintMoves,
- scaleY );
-
- glyphpath->scaleX = font->innerTransform.a;
- glyphpath->scaleC = font->innerTransform.c;
- glyphpath->scaleY = font->innerTransform.d;
-
- glyphpath->fractionalTranslation = *fractionalTranslation;
-
-#if 0
- glyphpath->hShift = hShift; /* for fauxing */
-#endif
-
- glyphpath->hStemHintArray = hStemHintArray;
- glyphpath->vStemHintArray = vStemHintArray;
- glyphpath->hintMask = hintMask; /* ptr to current mask */
- glyphpath->hintOriginY = hintOriginY;
- glyphpath->blues = blues;
- glyphpath->darken = font->darkened; /* TODO: should we make copies? */
- glyphpath->xOffset = font->darkenX;
- glyphpath->yOffset = font->darkenY;
- glyphpath->miterLimit = 2 * FT_MAX(
- cf2_fixedAbs( glyphpath->xOffset ),
- cf2_fixedAbs( glyphpath->yOffset ) );
-
- /* .1 character space unit */
- glyphpath->snapThreshold = cf2_doubleToFixed( 0.1 );
-
- glyphpath->moveIsPending = TRUE;
- glyphpath->pathIsOpen = FALSE;
- glyphpath->pathIsClosing = FALSE;
- glyphpath->elemIsQueued = FALSE;
- }
-
-
- FT_LOCAL_DEF( void )
- cf2_glyphpath_finalize( CF2_GlyphPath glyphpath )
- {
- cf2_arrstack_finalize( &glyphpath->hintMoves );
- }
-
-
- /*
- * Hint point in y-direction and apply outerTransform.
- * Input `current' hint map (which is actually delayed by one element).
- * Input x,y point in Character Space.
- * Output x,y point in Device Space, including translation.
- */
- static void
- cf2_glyphpath_hintPoint( CF2_GlyphPath glyphpath,
- CF2_HintMap hintmap,
- FT_Vector* ppt,
- CF2_Fixed x,
- CF2_Fixed y )
- {
- FT_Vector pt; /* hinted point in upright DS */
-
-
- pt.x = ADD_INT32( FT_MulFix( glyphpath->scaleX, x ),
- FT_MulFix( glyphpath->scaleC, y ) );
- pt.y = cf2_hintmap_map( hintmap, y );
-
- ppt->x = ADD_INT32(
- FT_MulFix( glyphpath->font->outerTransform.a, pt.x ),
- ADD_INT32(
- FT_MulFix( glyphpath->font->outerTransform.c, pt.y ),
- glyphpath->fractionalTranslation.x ) );
- ppt->y = ADD_INT32(
- FT_MulFix( glyphpath->font->outerTransform.b, pt.x ),
- ADD_INT32(
- FT_MulFix( glyphpath->font->outerTransform.d, pt.y ),
- glyphpath->fractionalTranslation.y ) );
- }
-
-
- /*
- * From two line segments, (u1,u2) and (v1,v2), compute a point of
- * intersection on the corresponding lines.
- * Return false if no intersection is found, or if the intersection is
- * too far away from the ends of the line segments, u2 and v1.
- *
- */
- static FT_Bool
- cf2_glyphpath_computeIntersection( CF2_GlyphPath glyphpath,
- const FT_Vector* u1,
- const FT_Vector* u2,
- const FT_Vector* v1,
- const FT_Vector* v2,
- FT_Vector* intersection )
- {
- /*
- * Let `u' be a zero-based vector from the first segment, `v' from the
- * second segment.
- * Let `w 'be the zero-based vector from `u1' to `v1'.
- * `perp' is the `perpendicular dot product'; see
- * http://mathworld.wolfram.com/PerpDotProduct.html.
- * `s' is the parameter for the parametric line for the first segment
- * (`u').
- *
- * See notation in
- * http://softsurfer.com/Archive/algorithm_0104/algorithm_0104B.htm.
- * Calculations are done in 16.16, but must handle the squaring of
- * line lengths in character space. We scale all vectors by 1/32 to
- * avoid overflow. This allows values up to 4095 to be squared. The
- * scale factor cancels in the divide.
- *
- * TODO: the scale factor could be computed from UnitsPerEm.
- *
- */
-
-#define cf2_perp( a, b ) \
- ( FT_MulFix( a.x, b.y ) - FT_MulFix( a.y, b.x ) )
-
- /* round and divide by 32 */
-#define CF2_CS_SCALE( x ) \
- ( ( (x) + 0x10 ) >> 5 )
-
- FT_Vector u, v, w; /* scaled vectors */
- CF2_Fixed denominator, s;
-
-
- u.x = CF2_CS_SCALE( SUB_INT32( u2->x, u1->x ) );
- u.y = CF2_CS_SCALE( SUB_INT32( u2->y, u1->y ) );
- v.x = CF2_CS_SCALE( SUB_INT32( v2->x, v1->x ) );
- v.y = CF2_CS_SCALE( SUB_INT32( v2->y, v1->y ) );
- w.x = CF2_CS_SCALE( SUB_INT32( v1->x, u1->x ) );
- w.y = CF2_CS_SCALE( SUB_INT32( v1->y, u1->y ) );
-
- denominator = cf2_perp( u, v );
-
- if ( denominator == 0 )
- return FALSE; /* parallel or coincident lines */
-
- s = FT_DivFix( cf2_perp( w, v ), denominator );
-
- intersection->x = ADD_INT32( u1->x,
- FT_MulFix( s, SUB_INT32( u2->x, u1->x ) ) );
- intersection->y = ADD_INT32( u1->y,
- FT_MulFix( s, SUB_INT32( u2->y, u1->y ) ) );
-
-
- /*
- * Special case snapping for horizontal and vertical lines.
- * This cleans up intersections and reduces problems with winding
- * order detection.
- * Sample case is sbc cd KozGoPr6N-Medium.otf 20 16685.
- * Note: these calculations are in character space.
- *
- */
-
- if ( u1->x == u2->x &&
- cf2_fixedAbs( SUB_INT32( intersection->x,
- u1->x ) ) < glyphpath->snapThreshold )
- intersection->x = u1->x;
- if ( u1->y == u2->y &&
- cf2_fixedAbs( SUB_INT32( intersection->y,
- u1->y ) ) < glyphpath->snapThreshold )
- intersection->y = u1->y;
-
- if ( v1->x == v2->x &&
- cf2_fixedAbs( SUB_INT32( intersection->x,
- v1->x ) ) < glyphpath->snapThreshold )
- intersection->x = v1->x;
- if ( v1->y == v2->y &&
- cf2_fixedAbs( SUB_INT32( intersection->y,
- v1->y ) ) < glyphpath->snapThreshold )
- intersection->y = v1->y;
-
- /* limit the intersection distance from midpoint of u2 and v1 */
- if ( cf2_fixedAbs( intersection->x - ADD_INT32( u2->x, v1->x ) / 2 ) >
- glyphpath->miterLimit ||
- cf2_fixedAbs( intersection->y - ADD_INT32( u2->y, v1->y ) / 2 ) >
- glyphpath->miterLimit )
- return FALSE;
-
- return TRUE;
- }
-
-
- /*
- * Push the cached element (glyphpath->prevElem*) to the outline
- * consumer. When a darkening offset is used, the end point of the
- * cached element may be adjusted to an intersection point or we may
- * synthesize a connecting line to the current element. If we are
- * closing a subpath, we may also generate a connecting line to the start
- * point.
- *
- * This is where Character Space (CS) is converted to Device Space (DS)
- * using a hint map. This calculation must use a HintMap that was valid
- * at the time the element was saved. For the first point in a subpath,
- * that is a saved HintMap. For most elements, it just means the caller
- * has delayed building a HintMap from the current HintMask.
- *
- * Transform each point with outerTransform and call the outline
- * callbacks. This is a general 3x3 transform:
- *
- * x' = a*x + c*y + tx, y' = b*x + d*y + ty
- *
- * but it uses 4 elements from CF2_Font and the translation part
- * from CF2_GlyphPath.
- *
- */
- static void
- cf2_glyphpath_pushPrevElem( CF2_GlyphPath glyphpath,
- CF2_HintMap hintmap,
- FT_Vector* nextP0,
- FT_Vector nextP1,
- FT_Bool close )
- {
- CF2_CallbackParamsRec params;
-
- FT_Vector* prevP0;
- FT_Vector* prevP1;
-
- FT_Vector intersection = { 0, 0 };
- FT_Bool useIntersection = FALSE;
-
-
- FT_ASSERT( glyphpath->prevElemOp == CF2_PathOpLineTo ||
- glyphpath->prevElemOp == CF2_PathOpCubeTo );
-
- if ( glyphpath->prevElemOp == CF2_PathOpLineTo )
- {
- prevP0 = &glyphpath->prevElemP0;
- prevP1 = &glyphpath->prevElemP1;
- }
- else
- {
- prevP0 = &glyphpath->prevElemP2;
- prevP1 = &glyphpath->prevElemP3;
- }
-
- /* optimization: if previous and next elements are offset by the same */
- /* amount, then there will be no gap, and no need to compute an */
- /* intersection. */
- if ( prevP1->x != nextP0->x || prevP1->y != nextP0->y )
- {
- /* previous element does not join next element: */
- /* adjust end point of previous element to the intersection */
- useIntersection = cf2_glyphpath_computeIntersection( glyphpath,
- prevP0,
- prevP1,
- nextP0,
- &nextP1,
- &intersection );
- if ( useIntersection )
- {
- /* modify the last point of the cached element (either line or */
- /* curve) */
- *prevP1 = intersection;
- }
- }
-
- params.pt0 = glyphpath->currentDS;
-
- switch( glyphpath->prevElemOp )
- {
- case CF2_PathOpLineTo:
- params.op = CF2_PathOpLineTo;
-
- /* note: pt2 and pt3 are unused */
-
- if ( close )
- {
- /* use first hint map if closing */
- cf2_glyphpath_hintPoint( glyphpath,
- &glyphpath->firstHintMap,
- &params.pt1,
- glyphpath->prevElemP1.x,
- glyphpath->prevElemP1.y );
- }
- else
- {
- cf2_glyphpath_hintPoint( glyphpath,
- hintmap,
- &params.pt1,
- glyphpath->prevElemP1.x,
- glyphpath->prevElemP1.y );
- }
-
- /* output only non-zero length lines */
- if ( params.pt0.x != params.pt1.x || params.pt0.y != params.pt1.y )
- {
- glyphpath->callbacks->lineTo( glyphpath->callbacks, &params );
-
- glyphpath->currentDS = params.pt1;
- }
- break;
-
- case CF2_PathOpCubeTo:
- params.op = CF2_PathOpCubeTo;
-
- /* TODO: should we intersect the interior joins (p1-p2 and p2-p3)? */
- cf2_glyphpath_hintPoint( glyphpath,
- hintmap,
- &params.pt1,
- glyphpath->prevElemP1.x,
- glyphpath->prevElemP1.y );
- cf2_glyphpath_hintPoint( glyphpath,
- hintmap,
- &params.pt2,
- glyphpath->prevElemP2.x,
- glyphpath->prevElemP2.y );
- cf2_glyphpath_hintPoint( glyphpath,
- hintmap,
- &params.pt3,
- glyphpath->prevElemP3.x,
- glyphpath->prevElemP3.y );
-
- glyphpath->callbacks->cubeTo( glyphpath->callbacks, &params );
-
- glyphpath->currentDS = params.pt3;
-
- break;
- }
-
- if ( !useIntersection || close )
- {
- /* insert connecting line between end of previous element and start */
- /* of current one */
- /* note: at the end of a subpath, we might do both, so use `nextP0' */
- /* before we change it, below */
-
- if ( close )
- {
- /* if we are closing the subpath, then nextP0 is in the first */
- /* hint zone */
- cf2_glyphpath_hintPoint( glyphpath,
- &glyphpath->firstHintMap,
- &params.pt1,
- nextP0->x,
- nextP0->y );
- }
- else
- {
- cf2_glyphpath_hintPoint( glyphpath,
- hintmap,
- &params.pt1,
- nextP0->x,
- nextP0->y );
- }
-
- if ( params.pt1.x != glyphpath->currentDS.x ||
- params.pt1.y != glyphpath->currentDS.y )
- {
- /* length is nonzero */
- params.op = CF2_PathOpLineTo;
- params.pt0 = glyphpath->currentDS;
-
- /* note: pt2 and pt3 are unused */
- glyphpath->callbacks->lineTo( glyphpath->callbacks, &params );
-
- glyphpath->currentDS = params.pt1;
- }
- }
-
- if ( useIntersection )
- {
- /* return intersection point to caller */
- *nextP0 = intersection;
- }
- }
-
-
- /* push a MoveTo element based on current point and offset of current */
- /* element */
- static void
- cf2_glyphpath_pushMove( CF2_GlyphPath glyphpath,
- FT_Vector start )
- {
- CF2_CallbackParamsRec params;
-
-
- params.op = CF2_PathOpMoveTo;
- params.pt0 = glyphpath->currentDS;
-
- /* Test if move has really happened yet; it would have called */
- /* `cf2_hintmap_build' to set `isValid'. */
- if ( !cf2_hintmap_isValid( &glyphpath->hintMap ) )
- {
- /* we are here iff first subpath is missing a moveto operator: */
- /* synthesize first moveTo to finish initialization of hintMap */
- cf2_glyphpath_moveTo( glyphpath,
- glyphpath->start.x,
- glyphpath->start.y );
- }
-
- cf2_glyphpath_hintPoint( glyphpath,
- &glyphpath->hintMap,
- &params.pt1,
- start.x,
- start.y );
-
- /* note: pt2 and pt3 are unused */
- glyphpath->callbacks->moveTo( glyphpath->callbacks, &params );
-
- glyphpath->currentDS = params.pt1;
- glyphpath->offsetStart0 = start;
- }
-
-
- /*
- * All coordinates are in character space.
- * On input, (x1, y1) and (x2, y2) give line segment.
- * On output, (x, y) give offset vector.
- * We use a piecewise approximation to trig functions.
- *
- * TODO: Offset true perpendicular and proper length
- * supply the y-translation for hinting here, too,
- * that adds yOffset unconditionally to *y.
- */
- static void
- cf2_glyphpath_computeOffset( CF2_GlyphPath glyphpath,
- CF2_Fixed x1,
- CF2_Fixed y1,
- CF2_Fixed x2,
- CF2_Fixed y2,
- CF2_Fixed* x,
- CF2_Fixed* y )
- {
- CF2_Fixed dx = SUB_INT32( x2, x1 );
- CF2_Fixed dy = SUB_INT32( y2, y1 );
-
-
- /* note: negative offsets don't work here; negate deltas to change */
- /* quadrants, below */
- if ( glyphpath->font->reverseWinding )
- {
- dx = NEG_INT32( dx );
- dy = NEG_INT32( dy );
- }
-
- *x = *y = 0;
-
- if ( !glyphpath->darken )
- return;
-
- /* add momentum for this path element */
- glyphpath->callbacks->windingMomentum =
- ADD_INT32( glyphpath->callbacks->windingMomentum,
- cf2_getWindingMomentum( x1, y1, x2, y2 ) );
-
- /* note: allow mixed integer and fixed multiplication here */
- if ( dx >= 0 )
- {
- if ( dy >= 0 )
- {
- /* first quadrant, +x +y */
-
- if ( dx > MUL_INT32( 2, dy ) )
- {
- /* +x */
- *x = 0;
- *y = 0;
- }
- else if ( dy > MUL_INT32( 2, dx ) )
- {
- /* +y */
- *x = glyphpath->xOffset;
- *y = glyphpath->yOffset;
- }
- else
- {
- /* +x +y */
- *x = FT_MulFix( cf2_doubleToFixed( 0.7 ),
- glyphpath->xOffset );
- *y = FT_MulFix( cf2_doubleToFixed( 1.0 - 0.7 ),
- glyphpath->yOffset );
- }
- }
- else
- {
- /* fourth quadrant, +x -y */
-
- if ( dx > MUL_INT32( -2, dy ) )
- {
- /* +x */
- *x = 0;
- *y = 0;
- }
- else if ( NEG_INT32( dy ) > MUL_INT32( 2, dx ) )
- {
- /* -y */
- *x = NEG_INT32( glyphpath->xOffset );
- *y = glyphpath->yOffset;
- }
- else
- {
- /* +x -y */
- *x = FT_MulFix( cf2_doubleToFixed( -0.7 ),
- glyphpath->xOffset );
- *y = FT_MulFix( cf2_doubleToFixed( 1.0 - 0.7 ),
- glyphpath->yOffset );
- }
- }
- }
- else
- {
- if ( dy >= 0 )
- {
- /* second quadrant, -x +y */
-
- if ( NEG_INT32( dx ) > MUL_INT32( 2, dy ) )
- {
- /* -x */
- *x = 0;
- *y = MUL_INT32( 2, glyphpath->yOffset );
- }
- else if ( dy > MUL_INT32( -2, dx ) )
- {
- /* +y */
- *x = glyphpath->xOffset;
- *y = glyphpath->yOffset;
- }
- else
- {
- /* -x +y */
- *x = FT_MulFix( cf2_doubleToFixed( 0.7 ),
- glyphpath->xOffset );
- *y = FT_MulFix( cf2_doubleToFixed( 1.0 + 0.7 ),
- glyphpath->yOffset );
- }
- }
- else
- {
- /* third quadrant, -x -y */
-
- if ( NEG_INT32( dx ) > MUL_INT32( -2, dy ) )
- {
- /* -x */
- *x = 0;
- *y = MUL_INT32( 2, glyphpath->yOffset );
- }
- else if ( NEG_INT32( dy ) > MUL_INT32( -2, dx ) )
- {
- /* -y */
- *x = NEG_INT32( glyphpath->xOffset );
- *y = glyphpath->yOffset;
- }
- else
- {
- /* -x -y */
- *x = FT_MulFix( cf2_doubleToFixed( -0.7 ),
- glyphpath->xOffset );
- *y = FT_MulFix( cf2_doubleToFixed( 1.0 + 0.7 ),
- glyphpath->yOffset );
- }
- }
- }
- }
-
-
- /*
- * The functions cf2_glyphpath_{moveTo,lineTo,curveTo,closeOpenPath} are
- * called by the interpreter with Character Space (CS) coordinates. Each
- * path element is placed into a queue of length one to await the
- * calculation of the following element. At that time, the darkening
- * offset of the following element is known and joins can be computed,
- * including possible modification of this element, before mapping to
- * Device Space (DS) and passing it on to the outline consumer.
- *
- */
- FT_LOCAL_DEF( void )
- cf2_glyphpath_moveTo( CF2_GlyphPath glyphpath,
- CF2_Fixed x,
- CF2_Fixed y )
- {
- cf2_glyphpath_closeOpenPath( glyphpath );
-
- /* save the parameters of the move for later, when we'll know how to */
- /* offset it; */
- /* also save last move point */
- glyphpath->currentCS.x = glyphpath->start.x = x;
- glyphpath->currentCS.y = glyphpath->start.y = y;
-
- glyphpath->moveIsPending = TRUE;
-
- /* ensure we have a valid map with current mask */
- if ( !cf2_hintmap_isValid( &glyphpath->hintMap ) ||
- cf2_hintmask_isNew( glyphpath->hintMask ) )
- cf2_hintmap_build( &glyphpath->hintMap,
- glyphpath->hStemHintArray,
- glyphpath->vStemHintArray,
- glyphpath->hintMask,
- glyphpath->hintOriginY,
- FALSE );
-
- /* save a copy of current HintMap to use when drawing initial point */
- glyphpath->firstHintMap = glyphpath->hintMap; /* structure copy */
- }
-
-
- FT_LOCAL_DEF( void )
- cf2_glyphpath_lineTo( CF2_GlyphPath glyphpath,
- CF2_Fixed x,
- CF2_Fixed y )
- {
- CF2_Fixed xOffset, yOffset;
- FT_Vector P0, P1;
- FT_Bool newHintMap;
-
- /*
- * New hints will be applied after cf2_glyphpath_pushPrevElem has run.
- * In case this is a synthesized closing line, any new hints should be
- * delayed until this path is closed (`cf2_hintmask_isNew' will be
- * called again before the next line or curve).
- */
-
- /* true if new hint map not on close */
- newHintMap = cf2_hintmask_isNew( glyphpath->hintMask ) &&
- !glyphpath->pathIsClosing;
-
- /*
- * Zero-length lines may occur in the charstring. Because we cannot
- * compute darkening offsets or intersections from zero-length lines,
- * it is best to remove them and avoid artifacts. However, zero-length
- * lines in CS at the start of a new hint map can generate non-zero
- * lines in DS due to hint substitution. We detect a change in hint
- * map here and pass those zero-length lines along.
- */
-
- /*
- * Note: Find explicitly closed paths here with a conditional
- * breakpoint using
- *
- * !gp->pathIsClosing && gp->start.x == x && gp->start.y == y
- *
- */
-
- if ( glyphpath->currentCS.x == x &&
- glyphpath->currentCS.y == y &&
- !newHintMap )
- /*
- * Ignore zero-length lines in CS where the hint map is the same
- * because the line in DS will also be zero length.
- *
- * Ignore zero-length lines when we synthesize a closing line because
- * the close will be handled in cf2_glyphPath_pushPrevElem.
- */
- return;
-
- cf2_glyphpath_computeOffset( glyphpath,
- glyphpath->currentCS.x,
- glyphpath->currentCS.y,
- x,
- y,
- &xOffset,
- &yOffset );
-
- /* construct offset points */
- P0.x = ADD_INT32( glyphpath->currentCS.x, xOffset );
- P0.y = ADD_INT32( glyphpath->currentCS.y, yOffset );
- P1.x = ADD_INT32( x, xOffset );
- P1.y = ADD_INT32( y, yOffset );
-
- if ( glyphpath->moveIsPending )
- {
- /* emit offset 1st point as MoveTo */
- cf2_glyphpath_pushMove( glyphpath, P0 );
-
- glyphpath->moveIsPending = FALSE; /* adjust state machine */
- glyphpath->pathIsOpen = TRUE;
-
- glyphpath->offsetStart1 = P1; /* record second point */
- }
-
- if ( glyphpath->elemIsQueued )
- {
- FT_ASSERT( cf2_hintmap_isValid( &glyphpath->hintMap ) ||
- glyphpath->hintMap.count == 0 );
-
- cf2_glyphpath_pushPrevElem( glyphpath,
- &glyphpath->hintMap,
- &P0,
- P1,
- FALSE );
- }
-
- /* queue the current element with offset points */
- glyphpath->elemIsQueued = TRUE;
- glyphpath->prevElemOp = CF2_PathOpLineTo;
- glyphpath->prevElemP0 = P0;
- glyphpath->prevElemP1 = P1;
-
- /* update current map */
- if ( newHintMap )
- cf2_hintmap_build( &glyphpath->hintMap,
- glyphpath->hStemHintArray,
- glyphpath->vStemHintArray,
- glyphpath->hintMask,
- glyphpath->hintOriginY,
- FALSE );
-
- glyphpath->currentCS.x = x; /* pre-offset current point */
- glyphpath->currentCS.y = y;
- }
-
-
- FT_LOCAL_DEF( void )
- cf2_glyphpath_curveTo( CF2_GlyphPath glyphpath,
- CF2_Fixed x1,
- CF2_Fixed y1,
- CF2_Fixed x2,
- CF2_Fixed y2,
- CF2_Fixed x3,
- CF2_Fixed y3 )
- {
- CF2_Fixed xOffset1, yOffset1, xOffset3, yOffset3;
- FT_Vector P0, P1, P2, P3;
-
-
- /* TODO: ignore zero length portions of curve?? */
- cf2_glyphpath_computeOffset( glyphpath,
- glyphpath->currentCS.x,
- glyphpath->currentCS.y,
- x1,
- y1,
- &xOffset1,
- &yOffset1 );
- cf2_glyphpath_computeOffset( glyphpath,
- x2,
- y2,
- x3,
- y3,
- &xOffset3,
- &yOffset3 );
-
- /* add momentum from the middle segment */
- glyphpath->callbacks->windingMomentum =
- ADD_INT32( glyphpath->callbacks->windingMomentum,
- cf2_getWindingMomentum( x1, y1, x2, y2 ) );
-
- /* construct offset points */
- P0.x = ADD_INT32( glyphpath->currentCS.x, xOffset1 );
- P0.y = ADD_INT32( glyphpath->currentCS.y, yOffset1 );
- P1.x = ADD_INT32( x1, xOffset1 );
- P1.y = ADD_INT32( y1, yOffset1 );
- /* note: preserve angle of final segment by using offset3 at both ends */
- P2.x = ADD_INT32( x2, xOffset3 );
- P2.y = ADD_INT32( y2, yOffset3 );
- P3.x = ADD_INT32( x3, xOffset3 );
- P3.y = ADD_INT32( y3, yOffset3 );
-
- if ( glyphpath->moveIsPending )
- {
- /* emit offset 1st point as MoveTo */
- cf2_glyphpath_pushMove( glyphpath, P0 );
-
- glyphpath->moveIsPending = FALSE;
- glyphpath->pathIsOpen = TRUE;
-
- glyphpath->offsetStart1 = P1; /* record second point */
- }
-
- if ( glyphpath->elemIsQueued )
- {
- FT_ASSERT( cf2_hintmap_isValid( &glyphpath->hintMap ) ||
- glyphpath->hintMap.count == 0 );
-
- cf2_glyphpath_pushPrevElem( glyphpath,
- &glyphpath->hintMap,
- &P0,
- P1,
- FALSE );
- }
-
- /* queue the current element with offset points */
- glyphpath->elemIsQueued = TRUE;
- glyphpath->prevElemOp = CF2_PathOpCubeTo;
- glyphpath->prevElemP0 = P0;
- glyphpath->prevElemP1 = P1;
- glyphpath->prevElemP2 = P2;
- glyphpath->prevElemP3 = P3;
-
- /* update current map */
- if ( cf2_hintmask_isNew( glyphpath->hintMask ) )
- cf2_hintmap_build( &glyphpath->hintMap,
- glyphpath->hStemHintArray,
- glyphpath->vStemHintArray,
- glyphpath->hintMask,
- glyphpath->hintOriginY,
- FALSE );
-
- glyphpath->currentCS.x = x3; /* pre-offset current point */
- glyphpath->currentCS.y = y3;
- }
-
-
- FT_LOCAL_DEF( void )
- cf2_glyphpath_closeOpenPath( CF2_GlyphPath glyphpath )
- {
- if ( glyphpath->pathIsOpen )
- {
- /*
- * A closing line in Character Space line is always generated below
- * with `cf2_glyphPath_lineTo'. It may be ignored later if it turns
- * out to be zero length in Device Space.
- */
- glyphpath->pathIsClosing = TRUE;
-
- cf2_glyphpath_lineTo( glyphpath,
- glyphpath->start.x,
- glyphpath->start.y );
-
- /* empty the final element from the queue and close the path */
- if ( glyphpath->elemIsQueued )
- cf2_glyphpath_pushPrevElem( glyphpath,
- &glyphpath->hintMap,
- &glyphpath->offsetStart0,
- glyphpath->offsetStart1,
- TRUE );
-
- /* reset state machine */
- glyphpath->moveIsPending = TRUE;
- glyphpath->pathIsOpen = FALSE;
- glyphpath->pathIsClosing = FALSE;
- glyphpath->elemIsQueued = FALSE;
- }
- }
-
-
-/* END */
diff --git a/thirdparty/freetype/src/cff/cf2hints.h b/thirdparty/freetype/src/cff/cf2hints.h
deleted file mode 100644
index a8984542a0..0000000000
--- a/thirdparty/freetype/src/cff/cf2hints.h
+++ /dev/null
@@ -1,289 +0,0 @@
-/***************************************************************************/
-/* */
-/* cf2hints.h */
-/* */
-/* Adobe's code for handling CFF hints (body). */
-/* */
-/* Copyright 2007-2013 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
-
-
-#ifndef CF2HINTS_H_
-#define CF2HINTS_H_
-
-
-FT_BEGIN_HEADER
-
-
- enum
- {
- CF2_MAX_HINTS = 96 /* maximum # of hints */
- };
-
-
- /*
- * A HintMask object stores a bit mask that specifies which hints in the
- * charstring are active at a given time. Hints in CFF must be declared
- * at the start, before any drawing operators, with horizontal hints
- * preceding vertical hints. The HintMask is ordered the same way, with
- * horizontal hints immediately followed by vertical hints. Clients are
- * responsible for knowing how many of each type are present.
- *
- * The maximum total number of hints is 96, as specified by the CFF
- * specification.
- *
- * A HintMask is built 0 or more times while interpreting a charstring, by
- * the HintMask operator. There is only one HintMask, but it is built or
- * rebuilt each time there is a hint substitution (HintMask operator) in
- * the charstring. A default HintMask with all bits set is built if there
- * has been no HintMask operator prior to the first drawing operator.
- *
- */
-
- typedef struct CF2_HintMaskRec_
- {
- FT_Error* error;
-
- FT_Bool isValid;
- FT_Bool isNew;
-
- size_t bitCount;
- size_t byteCount;
-
- FT_Byte mask[( CF2_MAX_HINTS + 7 ) / 8];
-
- } CF2_HintMaskRec, *CF2_HintMask;
-
-
- typedef struct CF2_StemHintRec_
- {
- FT_Bool used; /* DS positions are valid */
-
- CF2_Fixed min; /* original character space value */
- CF2_Fixed max;
-
- CF2_Fixed minDS; /* DS position after first use */
- CF2_Fixed maxDS;
-
- } CF2_StemHintRec, *CF2_StemHint;
-
-
- /*
- * A HintMap object stores a piecewise linear function for mapping
- * y-coordinates from character space to device space, providing
- * appropriate pixel alignment to stem edges.
- *
- * The map is implemented as an array of `CF2_Hint' elements, each
- * representing an edge. When edges are paired, as from stem hints, the
- * bottom edge must immediately precede the top edge in the array.
- * Element character space AND device space positions must both increase
- * monotonically in the array. `CF2_Hint' elements are also used as
- * parameters to `cf2_blues_capture'.
- *
- * The `cf2_hintmap_build' method must be called before any drawing
- * operation (beginning with a Move operator) and at each hint
- * substitution (HintMask operator).
- *
- * The `cf2_hintmap_map' method is called to transform y-coordinates at
- * each drawing operation (move, line, curve).
- *
- */
-
- /* TODO: make this a CF2_ArrStack and add a deep copy method */
- enum
- {
- CF2_MAX_HINT_EDGES = CF2_MAX_HINTS * 2
- };
-
-
- typedef struct CF2_HintMapRec_
- {
- CF2_Font font;
-
- /* initial map based on blue zones */
- struct CF2_HintMapRec_* initialHintMap;
-
- /* working storage for 2nd pass adjustHints */
- CF2_ArrStack hintMoves;
-
- FT_Bool isValid;
- FT_Bool hinted;
-
- CF2_Fixed scale;
- CF2_UInt count;
-
- /* start search from this index */
- CF2_UInt lastIndex;
-
- CF2_HintRec edge[CF2_MAX_HINT_EDGES]; /* 192 */
-
- } CF2_HintMapRec, *CF2_HintMap;
-
-
- FT_LOCAL( FT_Bool )
- cf2_hint_isValid( const CF2_Hint hint );
- FT_LOCAL( FT_Bool )
- cf2_hint_isTop( const CF2_Hint hint );
- FT_LOCAL( FT_Bool )
- cf2_hint_isBottom( const CF2_Hint hint );
- FT_LOCAL( void )
- cf2_hint_lock( CF2_Hint hint );
-
-
- FT_LOCAL( void )
- cf2_hintmap_init( CF2_HintMap hintmap,
- CF2_Font font,
- CF2_HintMap initialMap,
- CF2_ArrStack hintMoves,
- CF2_Fixed scale );
- FT_LOCAL( void )
- cf2_hintmap_build( CF2_HintMap hintmap,
- CF2_ArrStack hStemHintArray,
- CF2_ArrStack vStemHintArray,
- CF2_HintMask hintMask,
- CF2_Fixed hintOrigin,
- FT_Bool initialMap );
-
-
- /*
- * GlyphPath is a wrapper for drawing operations that scales the
- * coordinates according to the render matrix and HintMap. It also tracks
- * open paths to control ClosePath and to insert MoveTo for broken fonts.
- *
- */
- typedef struct CF2_GlyphPathRec_
- {
- /* TODO: gather some of these into a hinting context */
-
- CF2_Font font; /* font instance */
- CF2_OutlineCallbacks callbacks; /* outline consumer */
-
-
- CF2_HintMapRec hintMap; /* current hint map */
- CF2_HintMapRec firstHintMap; /* saved copy */
- CF2_HintMapRec initialHintMap; /* based on all captured hints */
-
- CF2_ArrStackRec hintMoves; /* list of hint moves for 2nd pass */
-
- CF2_Fixed scaleX; /* matrix a */
- CF2_Fixed scaleC; /* matrix c */
- CF2_Fixed scaleY; /* matrix d */
-
- FT_Vector fractionalTranslation; /* including deviceXScale */
-#if 0
- CF2_Fixed hShift; /* character space horizontal shift */
- /* (for fauxing) */
-#endif
-
- FT_Bool pathIsOpen; /* true after MoveTo */
- FT_Bool pathIsClosing; /* true when synthesizing closepath line */
- FT_Bool darken; /* true if stem darkening */
- FT_Bool moveIsPending; /* true between MoveTo and offset MoveTo */
-
- /* references used to call `cf2_hintmap_build', if necessary */
- CF2_ArrStack hStemHintArray;
- CF2_ArrStack vStemHintArray;
- CF2_HintMask hintMask; /* ptr to the current mask */
- CF2_Fixed hintOriginY; /* copy of current origin */
- const CF2_BluesRec* blues;
-
- CF2_Fixed xOffset; /* character space offsets */
- CF2_Fixed yOffset;
-
- /* character space miter limit threshold */
- CF2_Fixed miterLimit;
- /* vertical/horizontal snap distance in character space */
- CF2_Fixed snapThreshold;
-
- FT_Vector offsetStart0; /* first and second points of first */
- FT_Vector offsetStart1; /* element with offset applied */
-
- /* current point, character space, before offset */
- FT_Vector currentCS;
- /* current point, device space */
- FT_Vector currentDS;
- /* start point of subpath, character space */
- FT_Vector start;
-
- /* the following members constitute the `queue' of one element */
- FT_Bool elemIsQueued;
- CF2_Int prevElemOp;
-
- FT_Vector prevElemP0;
- FT_Vector prevElemP1;
- FT_Vector prevElemP2;
- FT_Vector prevElemP3;
-
- } CF2_GlyphPathRec, *CF2_GlyphPath;
-
-
- FT_LOCAL( void )
- cf2_glyphpath_init( CF2_GlyphPath glyphpath,
- CF2_Font font,
- CF2_OutlineCallbacks callbacks,
- CF2_Fixed scaleY,
- /* CF2_Fixed hShift, */
- CF2_ArrStack hStemHintArray,
- CF2_ArrStack vStemHintArray,
- CF2_HintMask hintMask,
- CF2_Fixed hintOrigin,
- const CF2_Blues blues,
- const FT_Vector* fractionalTranslation );
- FT_LOCAL( void )
- cf2_glyphpath_finalize( CF2_GlyphPath glyphpath );
-
- FT_LOCAL( void )
- cf2_glyphpath_moveTo( CF2_GlyphPath glyphpath,
- CF2_Fixed x,
- CF2_Fixed y );
- FT_LOCAL( void )
- cf2_glyphpath_lineTo( CF2_GlyphPath glyphpath,
- CF2_Fixed x,
- CF2_Fixed y );
- FT_LOCAL( void )
- cf2_glyphpath_curveTo( CF2_GlyphPath glyphpath,
- CF2_Fixed x1,
- CF2_Fixed y1,
- CF2_Fixed x2,
- CF2_Fixed y2,
- CF2_Fixed x3,
- CF2_Fixed y3 );
- FT_LOCAL( void )
- cf2_glyphpath_closeOpenPath( CF2_GlyphPath glyphpath );
-
-
-FT_END_HEADER
-
-
-#endif /* CF2HINTS_H_ */
-
-
-/* END */
diff --git a/thirdparty/freetype/src/cff/cf2intrp.c b/thirdparty/freetype/src/cff/cf2intrp.c
deleted file mode 100644
index a816280748..0000000000
--- a/thirdparty/freetype/src/cff/cf2intrp.c
+++ /dev/null
@@ -1,1959 +0,0 @@
-/***************************************************************************/
-/* */
-/* cf2intrp.c */
-/* */
-/* Adobe's CFF Interpreter (body). */
-/* */
-/* Copyright 2007-2014 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
-
-
-#include "cf2ft.h"
-#include FT_INTERNAL_DEBUG_H
-
-#include "cf2glue.h"
-#include "cf2font.h"
-#include "cf2stack.h"
-#include "cf2hints.h"
-#include "cf2intrp.h"
-
-#include "cf2error.h"
-
-#include "cffload.h"
-
-
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
-#undef FT_COMPONENT
-#define FT_COMPONENT trace_cf2interp
-
-
- FT_LOCAL_DEF( void )
- cf2_hintmask_init( CF2_HintMask hintmask,
- FT_Error* error )
- {
- FT_ZERO( hintmask );
-
- hintmask->error = error;
- }
-
-
- FT_LOCAL_DEF( FT_Bool )
- cf2_hintmask_isValid( const CF2_HintMask hintmask )
- {
- return hintmask->isValid;
- }
-
-
- FT_LOCAL_DEF( FT_Bool )
- cf2_hintmask_isNew( const CF2_HintMask hintmask )
- {
- return hintmask->isNew;
- }
-
-
- FT_LOCAL_DEF( void )
- cf2_hintmask_setNew( CF2_HintMask hintmask,
- FT_Bool val )
- {
- hintmask->isNew = val;
- }
-
-
- /* clients call `getMaskPtr' in order to iterate */
- /* through hint mask */
-
- FT_LOCAL_DEF( FT_Byte* )
- cf2_hintmask_getMaskPtr( CF2_HintMask hintmask )
- {
- return hintmask->mask;
- }
-
-
- static size_t
- cf2_hintmask_setCounts( CF2_HintMask hintmask,
- size_t bitCount )
- {
- if ( bitCount > CF2_MAX_HINTS )
- {
- /* total of h and v stems must be <= 96 */
- CF2_SET_ERROR( hintmask->error, Invalid_Glyph_Format );
- return 0;
- }
-
- hintmask->bitCount = bitCount;
- hintmask->byteCount = ( hintmask->bitCount + 7 ) / 8;
-
- hintmask->isValid = TRUE;
- hintmask->isNew = TRUE;
-
- return bitCount;
- }
-
-
- /* consume the hintmask bytes from the charstring, advancing the src */
- /* pointer */
- static void
- cf2_hintmask_read( CF2_HintMask hintmask,
- CF2_Buffer charstring,
- size_t bitCount )
- {
- size_t i;
-
-#ifndef CF2_NDEBUG
- /* these are the bits in the final mask byte that should be zero */
- /* Note: this variable is only used in an assert expression below */
- /* and then only if CF2_NDEBUG is not defined */
- CF2_UInt mask = ( 1 << ( -(CF2_Int)bitCount & 7 ) ) - 1;
-#endif
-
-
- /* initialize counts and isValid */
- if ( cf2_hintmask_setCounts( hintmask, bitCount ) == 0 )
- return;
-
- FT_ASSERT( hintmask->byteCount > 0 );
-
- FT_TRACE4(( " (maskbytes:" ));
-
- /* set mask and advance interpreter's charstring pointer */
- for ( i = 0; i < hintmask->byteCount; i++ )
- {
- hintmask->mask[i] = (FT_Byte)cf2_buf_readByte( charstring );
- FT_TRACE4(( " 0x%02X", hintmask->mask[i] ));
- }
-
- FT_TRACE4(( ")\n" ));
-
- /* assert any unused bits in last byte are zero unless there's a prior */
- /* error */
- /* bitCount -> mask, 0 -> 0, 1 -> 7f, 2 -> 3f, ... 6 -> 3, 7 -> 1 */
-#ifndef CF2_NDEBUG
- FT_ASSERT( ( hintmask->mask[hintmask->byteCount - 1] & mask ) == 0 ||
- *hintmask->error );
-#endif
- }
-
-
- FT_LOCAL_DEF( void )
- cf2_hintmask_setAll( CF2_HintMask hintmask,
- size_t bitCount )
- {
- size_t i;
- CF2_UInt mask = ( 1 << ( -(CF2_Int)bitCount & 7 ) ) - 1;
-
-
- /* initialize counts and isValid */
- if ( cf2_hintmask_setCounts( hintmask, bitCount ) == 0 )
- return;
-
- FT_ASSERT( hintmask->byteCount > 0 );
- FT_ASSERT( hintmask->byteCount <=
- sizeof ( hintmask->mask ) / sizeof ( hintmask->mask[0] ) );
-
- /* set mask to all ones */
- for ( i = 0; i < hintmask->byteCount; i++ )
- hintmask->mask[i] = 0xFF;
-
- /* clear unused bits */
- /* bitCount -> mask, 0 -> 0, 1 -> 7f, 2 -> 3f, ... 6 -> 3, 7 -> 1 */
- hintmask->mask[hintmask->byteCount - 1] &= ~mask;
- }
-
-
- /* Type2 charstring opcodes */
- enum
- {
- cf2_cmdRESERVED_0, /* 0 */
- cf2_cmdHSTEM, /* 1 */
- cf2_cmdRESERVED_2, /* 2 */
- cf2_cmdVSTEM, /* 3 */
- cf2_cmdVMOVETO, /* 4 */
- cf2_cmdRLINETO, /* 5 */
- cf2_cmdHLINETO, /* 6 */
- cf2_cmdVLINETO, /* 7 */
- cf2_cmdRRCURVETO, /* 8 */
- cf2_cmdRESERVED_9, /* 9 */
- cf2_cmdCALLSUBR, /* 10 */
- cf2_cmdRETURN, /* 11 */
- cf2_cmdESC, /* 12 */
- cf2_cmdRESERVED_13, /* 13 */
- cf2_cmdENDCHAR, /* 14 */
- cf2_cmdVSINDEX, /* 15 */
- cf2_cmdBLEND, /* 16 */
- cf2_cmdRESERVED_17, /* 17 */
- cf2_cmdHSTEMHM, /* 18 */
- cf2_cmdHINTMASK, /* 19 */
- cf2_cmdCNTRMASK, /* 20 */
- cf2_cmdRMOVETO, /* 21 */
- cf2_cmdHMOVETO, /* 22 */
- cf2_cmdVSTEMHM, /* 23 */
- cf2_cmdRCURVELINE, /* 24 */
- cf2_cmdRLINECURVE, /* 25 */
- cf2_cmdVVCURVETO, /* 26 */
- cf2_cmdHHCURVETO, /* 27 */
- cf2_cmdEXTENDEDNMBR, /* 28 */
- cf2_cmdCALLGSUBR, /* 29 */
- cf2_cmdVHCURVETO, /* 30 */
- cf2_cmdHVCURVETO /* 31 */
- };
-
- enum
- {
- cf2_escDOTSECTION, /* 0 */
- cf2_escRESERVED_1, /* 1 */
- cf2_escRESERVED_2, /* 2 */
- cf2_escAND, /* 3 */
- cf2_escOR, /* 4 */
- cf2_escNOT, /* 5 */
- cf2_escRESERVED_6, /* 6 */
- cf2_escRESERVED_7, /* 7 */
- cf2_escRESERVED_8, /* 8 */
- cf2_escABS, /* 9 */
- cf2_escADD, /* 10 like otherADD */
- cf2_escSUB, /* 11 like otherSUB */
- cf2_escDIV, /* 12 */
- cf2_escRESERVED_13, /* 13 */
- cf2_escNEG, /* 14 */
- cf2_escEQ, /* 15 */
- cf2_escRESERVED_16, /* 16 */
- cf2_escRESERVED_17, /* 17 */
- cf2_escDROP, /* 18 */
- cf2_escRESERVED_19, /* 19 */
- cf2_escPUT, /* 20 like otherPUT */
- cf2_escGET, /* 21 like otherGET */
- cf2_escIFELSE, /* 22 like otherIFELSE */
- cf2_escRANDOM, /* 23 like otherRANDOM */
- cf2_escMUL, /* 24 like otherMUL */
- cf2_escRESERVED_25, /* 25 */
- cf2_escSQRT, /* 26 */
- cf2_escDUP, /* 27 like otherDUP */
- cf2_escEXCH, /* 28 like otherEXCH */
- cf2_escINDEX, /* 29 */
- cf2_escROLL, /* 30 */
- cf2_escRESERVED_31, /* 31 */
- cf2_escRESERVED_32, /* 32 */
- cf2_escRESERVED_33, /* 33 */
- cf2_escHFLEX, /* 34 */
- cf2_escFLEX, /* 35 */
- cf2_escHFLEX1, /* 36 */
- cf2_escFLEX1, /* 37 */
- cf2_escRESERVED_38 /* 38 & all higher */
- };
-
-
- /* `stemHintArray' does not change once we start drawing the outline. */
- static void
- cf2_doStems( const CF2_Font font,
- CF2_Stack opStack,
- CF2_ArrStack stemHintArray,
- CF2_Fixed* width,
- FT_Bool* haveWidth,
- CF2_Fixed hintOffset )
- {
- CF2_UInt i;
- CF2_UInt count = cf2_stack_count( opStack );
- FT_Bool hasWidthArg = (FT_Bool)( count & 1 );
-
- /* variable accumulates delta values from operand stack */
- CF2_Fixed position = hintOffset;
-
-
- if ( hasWidthArg && !*haveWidth )
- *width = cf2_stack_getReal( opStack, 0 ) +
- cf2_getNominalWidthX( font->decoder );
-
- if ( font->decoder->width_only )
- goto exit;
-
- for ( i = hasWidthArg ? 1 : 0; i < count; i += 2 )
- {
- /* construct a CF2_StemHint and push it onto the list */
- CF2_StemHintRec stemhint;
-
-
- stemhint.min =
- position = ADD_INT32( position,
- cf2_stack_getReal( opStack, i ) );
- stemhint.max =
- position = ADD_INT32( position,
- cf2_stack_getReal( opStack, i + 1 ) );
-
- stemhint.used = FALSE;
- stemhint.maxDS =
- stemhint.minDS = 0;
-
- cf2_arrstack_push( stemHintArray, &stemhint ); /* defer error check */
- }
-
- cf2_stack_clear( opStack );
-
- exit:
- /* cf2_doStems must define a width (may be default) */
- *haveWidth = TRUE;
- }
-
-
- static void
- cf2_doFlex( CF2_Stack opStack,
- CF2_Fixed* curX,
- CF2_Fixed* curY,
- CF2_GlyphPath glyphPath,
- const FT_Bool* readFromStack,
- FT_Bool doConditionalLastRead )
- {
- CF2_Fixed vals[14];
- CF2_UInt idx;
- FT_Bool isHFlex;
- CF2_Int top, i, j;
-
-
- vals[0] = *curX;
- vals[1] = *curY;
- idx = 0;
- isHFlex = FT_BOOL( readFromStack[9] == FALSE );
- top = isHFlex ? 9 : 10;
-
- for ( i = 0; i < top; i++ )
- {
- vals[i + 2] = vals[i];
- if ( readFromStack[i] )
- vals[i + 2] = ADD_INT32( vals[i + 2], cf2_stack_getReal( opStack,
- idx++ ) );
- }
-
- if ( isHFlex )
- vals[9 + 2] = *curY;
-
- if ( doConditionalLastRead )
- {
- FT_Bool lastIsX = (FT_Bool)(
- cf2_fixedAbs( SUB_INT32( vals[10], *curX ) ) >
- cf2_fixedAbs( SUB_INT32( vals[11], *curY ) ) );
- CF2_Fixed lastVal = cf2_stack_getReal( opStack, idx );
-
-
- if ( lastIsX )
- {
- vals[12] = ADD_INT32( vals[10], lastVal );
- vals[13] = *curY;
- }
- else
- {
- vals[12] = *curX;
- vals[13] = ADD_INT32( vals[11], lastVal );
- }
- }
- else
- {
- if ( readFromStack[10] )
- vals[12] = ADD_INT32( vals[10],
- cf2_stack_getReal( opStack, idx++ ) );
- else
- vals[12] = *curX;
-
- if ( readFromStack[11] )
- vals[13] = ADD_INT32( vals[11],
- cf2_stack_getReal( opStack, idx ) );
- else
- vals[13] = *curY;
- }
-
- for ( j = 0; j < 2; j++ )
- cf2_glyphpath_curveTo( glyphPath, vals[j * 6 + 2],
- vals[j * 6 + 3],
- vals[j * 6 + 4],
- vals[j * 6 + 5],
- vals[j * 6 + 6],
- vals[j * 6 + 7] );
-
- cf2_stack_clear( opStack );
-
- *curX = vals[12];
- *curY = vals[13];
- }
-
-
- /* Blend numOperands on the stack, */
- /* store results into the first numBlends values, */
- /* then pop remaining arguments. */
- static void
- cf2_doBlend( const CFF_Blend blend,
- CF2_Stack opStack,
- CF2_UInt numBlends )
- {
- CF2_UInt delta;
- CF2_UInt base;
- CF2_UInt i, j;
- CF2_UInt numOperands = (CF2_UInt)( numBlends * blend->lenBV );
-
-
- base = cf2_stack_count( opStack ) - numOperands;
- delta = base + numBlends;
-
- for ( i = 0; i < numBlends; i++ )
- {
- const CF2_Fixed* weight = &blend->BV[1];
-
- /* start with first term */
- CF2_Fixed sum = cf2_stack_getReal( opStack, i + base );
-
-
- for ( j = 1; j < blend->lenBV; j++ )
- sum = ADD_INT32( sum,
- FT_MulFix( *weight++,
- cf2_stack_getReal( opStack,
- delta++ ) ) );
-
- /* store blended result */
- cf2_stack_setReal( opStack, i + base, sum );
- }
-
- /* leave only `numBlends' results on stack */
- cf2_stack_pop( opStack, numOperands - numBlends );
- }
-
-
- /*
- * `error' is a shared error code used by many objects in this
- * routine. Before the code continues from an error, it must check and
- * record the error in `*error'. The idea is that this shared
- * error code will record the first error encountered. If testing
- * for an error anyway, the cost of `goto exit' is small, so we do it,
- * even if continuing would be safe. In this case, `lastError' is
- * set, so the testing and storing can be done in one place, at `exit'.
- *
- * Continuing after an error is intended for objects which do their own
- * testing of `*error', e.g., array stack functions. This allows us to
- * avoid an extra test after the call.
- *
- * Unimplemented opcodes are ignored.
- *
- */
- FT_LOCAL_DEF( void )
- cf2_interpT2CharString( CF2_Font font,
- CF2_Buffer buf,
- CF2_OutlineCallbacks callbacks,
- const FT_Vector* translation,
- FT_Bool doingSeac,
- CF2_Fixed curX,
- CF2_Fixed curY,
- CF2_Fixed* width )
- {
- /* lastError is used for errors that are immediately tested */
- FT_Error lastError = FT_Err_Ok;
-
- /* pointer to parsed font object */
- CFF_Decoder* decoder = font->decoder;
-
- FT_Error* error = &font->error;
- FT_Memory memory = font->memory;
-
- CF2_Fixed scaleY = font->innerTransform.d;
- CF2_Fixed nominalWidthX = cf2_getNominalWidthX( decoder );
-
- /* save this for hinting seac accents */
- CF2_Fixed hintOriginY = curY;
-
- CF2_Stack opStack = NULL;
- FT_UInt stackSize;
- FT_Byte op1; /* first opcode byte */
-
- CF2_F16Dot16 storage[CF2_STORAGE_SIZE]; /* for `put' and `get' */
-
- /* instruction limit; 20,000,000 matches Avalon */
- FT_UInt32 instructionLimit = 20000000UL;
-
- CF2_ArrStackRec subrStack;
-
- FT_Bool haveWidth;
- CF2_Buffer charstring = NULL;
-
- CF2_Int charstringIndex = -1; /* initialize to empty */
-
- /* TODO: placeholders for hint structures */
-
- /* objects used for hinting */
- CF2_ArrStackRec hStemHintArray;
- CF2_ArrStackRec vStemHintArray;
-
- CF2_HintMaskRec hintMask;
- CF2_GlyphPathRec glyphPath;
-
-
- FT_ZERO( &storage );
-
- /* initialize the remaining objects */
- cf2_arrstack_init( &subrStack,
- memory,
- error,
- sizeof ( CF2_BufferRec ) );
- cf2_arrstack_init( &hStemHintArray,
- memory,
- error,
- sizeof ( CF2_StemHintRec ) );
- cf2_arrstack_init( &vStemHintArray,
- memory,
- error,
- sizeof ( CF2_StemHintRec ) );
-
- /* initialize CF2_StemHint arrays */
- cf2_hintmask_init( &hintMask, error );
-
- /* initialize path map to manage drawing operations */
-
- /* Note: last 4 params are used to handle `MoveToPermissive', which */
- /* may need to call `hintMap.Build' */
- /* TODO: MoveToPermissive is gone; are these still needed? */
- cf2_glyphpath_init( &glyphPath,
- font,
- callbacks,
- scaleY,
- /* hShift, */
- &hStemHintArray,
- &vStemHintArray,
- &hintMask,
- hintOriginY,
- &font->blues,
- translation );
-
- /*
- * Initialize state for width parsing. From the CFF Spec:
- *
- * The first stack-clearing operator, which must be one of hstem,
- * hstemhm, vstem, vstemhm, cntrmask, hintmask, hmoveto, vmoveto,
- * rmoveto, or endchar, takes an additional argument - the width (as
- * described earlier), which may be expressed as zero or one numeric
- * argument.
- *
- * What we implement here uses the first validly specified width, but
- * does not detect errors for specifying more than one width.
- *
- * If one of the above operators occurs without explicitly specifying
- * a width, we assume the default width.
- *
- * CFF2 charstrings always return the default width (0).
- *
- */
- haveWidth = font->isCFF2 ? TRUE : FALSE;
- *width = cf2_getDefaultWidthX( decoder );
-
- /*
- * Note: At this point, all pointers to resources must be NULL
- * and all local objects must be initialized.
- * There must be no branches to `exit:' above this point.
- *
- */
-
- /* allocate an operand stack */
- stackSize = font->isCFF2 ? cf2_getMaxstack( decoder )
- : CF2_OPERAND_STACK_SIZE;
- opStack = cf2_stack_init( memory, error, stackSize );
-
- if ( !opStack )
- {
- lastError = FT_THROW( Out_Of_Memory );
- goto exit;
- }
-
- /* initialize subroutine stack by placing top level charstring as */
- /* first element (max depth plus one for the charstring) */
- /* Note: Caller owns and must finalize the first charstring. */
- /* Our copy of it does not change that requirement. */
- cf2_arrstack_setCount( &subrStack, CF2_MAX_SUBR + 1 );
-
- charstring = (CF2_Buffer)cf2_arrstack_getBuffer( &subrStack );
- *charstring = *buf; /* structure copy */
-
- charstringIndex = 0; /* entry is valid now */
-
- /* catch errors so far */
- if ( *error )
- goto exit;
-
- /* main interpreter loop */
- while ( 1 )
- {
- if ( cf2_buf_isEnd( charstring ) )
- {
- /* If we've reached the end of the charstring, simulate a */
- /* cf2_cmdRETURN or cf2_cmdENDCHAR. */
- /* We do this for both CFF and CFF2. */
- if ( charstringIndex )
- op1 = cf2_cmdRETURN; /* end of buffer for subroutine */
- else
- op1 = cf2_cmdENDCHAR; /* end of buffer for top level charstring */
- }
- else
- {
- op1 = (FT_Byte)cf2_buf_readByte( charstring );
-
- /* Explicit RETURN and ENDCHAR in CFF2 should be ignored. */
- /* Note: Trace message will report 0 instead of 11 or 14. */
- if ( ( op1 == cf2_cmdRETURN || op1 == cf2_cmdENDCHAR ) &&
- font->isCFF2 )
- op1 = cf2_cmdRESERVED_0;
- }
-
- /* check for errors once per loop */
- if ( *error )
- goto exit;
-
- instructionLimit--;
- if ( instructionLimit == 0 )
- {
- lastError = FT_THROW( Invalid_Glyph_Format );
- goto exit;
- }
-
- switch( op1 )
- {
- case cf2_cmdRESERVED_0:
- case cf2_cmdRESERVED_2:
- case cf2_cmdRESERVED_9:
- case cf2_cmdRESERVED_13:
- case cf2_cmdRESERVED_17:
- /* we may get here if we have a prior error */
- FT_TRACE4(( " unknown op (%d)\n", op1 ));
- break;
-
- case cf2_cmdVSINDEX:
- FT_TRACE4(( " vsindex\n" ));
-
- if ( !font->isCFF2 )
- break; /* clear stack & ignore */
-
- if ( font->blend.usedBV )
- {
- /* vsindex not allowed after blend */
- lastError = FT_THROW( Invalid_Glyph_Format );
- goto exit;
- }
-
- {
- FT_Int temp = cf2_stack_popInt( opStack );
-
-
- if ( temp >= 0 )
- font->vsindex = (FT_UInt)temp;
- }
- break;
-
- case cf2_cmdBLEND:
- {
- FT_UInt numBlends;
-
-
- FT_TRACE4(( " blend\n" ));
-
- if ( !font->isCFF2 )
- break; /* clear stack & ignore */
-
- /* do we have a `blend' op in a non-variant font? */
- if ( !font->blend.font )
- {
- lastError = FT_THROW( Invalid_Glyph_Format );
- goto exit;
- }
-
- /* check cached blend vector */
- if ( cff_blend_check_vector( &font->blend,
- font->vsindex,
- font->lenNDV,
- font->NDV ) )
- {
- lastError = cff_blend_build_vector( &font->blend,
- font->vsindex,
- font->lenNDV,
- font->NDV );
- if ( lastError )
- goto exit;
- }
-
- /* do the blend */
- numBlends = (FT_UInt)cf2_stack_popInt( opStack );
- if ( numBlends > stackSize )
- {
- lastError = FT_THROW( Invalid_Glyph_Format );
- goto exit;
- }
-
- cf2_doBlend( &font->blend, opStack, numBlends );
-
- font->blend.usedBV = TRUE;
- }
- continue; /* do not clear the stack */
-
- case cf2_cmdHSTEMHM:
- case cf2_cmdHSTEM:
- FT_TRACE4(( op1 == cf2_cmdHSTEMHM ? " hstemhm\n" : " hstem\n" ));
-
- /* never add hints after the mask is computed */
- if ( cf2_hintmask_isValid( &hintMask ) )
- {
- FT_TRACE4(( "cf2_interpT2CharString:"
- " invalid horizontal hint mask\n" ));
- break;
- }
-
- cf2_doStems( font,
- opStack,
- &hStemHintArray,
- width,
- &haveWidth,
- 0 );
-
- if ( font->decoder->width_only )
- goto exit;
-
- break;
-
- case cf2_cmdVSTEMHM:
- case cf2_cmdVSTEM:
- FT_TRACE4(( op1 == cf2_cmdVSTEMHM ? " vstemhm\n" : " vstem\n" ));
-
- /* never add hints after the mask is computed */
- if ( cf2_hintmask_isValid( &hintMask ) )
- {
- FT_TRACE4(( "cf2_interpT2CharString:"
- " invalid vertical hint mask\n" ));
- break;
- }
-
- cf2_doStems( font,
- opStack,
- &vStemHintArray,
- width,
- &haveWidth,
- 0 );
-
- if ( font->decoder->width_only )
- goto exit;
-
- break;
-
- case cf2_cmdVMOVETO:
- FT_TRACE4(( " vmoveto\n" ));
-
- if ( cf2_stack_count( opStack ) > 1 && !haveWidth )
- *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ),
- nominalWidthX );
-
- /* width is defined or default after this */
- haveWidth = TRUE;
-
- if ( font->decoder->width_only )
- goto exit;
-
- curY = ADD_INT32( curY, cf2_stack_popFixed( opStack ) );
-
- cf2_glyphpath_moveTo( &glyphPath, curX, curY );
-
- break;
-
- case cf2_cmdRLINETO:
- {
- CF2_UInt idx;
- CF2_UInt count = cf2_stack_count( opStack );
-
-
- FT_TRACE4(( " rlineto\n" ));
-
- for ( idx = 0; idx < count; idx += 2 )
- {
- curX = ADD_INT32( curX, cf2_stack_getReal( opStack,
- idx + 0 ) );
- curY = ADD_INT32( curY, cf2_stack_getReal( opStack,
- idx + 1 ) );
-
- cf2_glyphpath_lineTo( &glyphPath, curX, curY );
- }
-
- cf2_stack_clear( opStack );
- }
- continue; /* no need to clear stack again */
-
- case cf2_cmdHLINETO:
- case cf2_cmdVLINETO:
- {
- CF2_UInt idx;
- CF2_UInt count = cf2_stack_count( opStack );
-
- FT_Bool isX = FT_BOOL( op1 == cf2_cmdHLINETO );
-
-
- FT_TRACE4(( isX ? " hlineto\n" : " vlineto\n" ));
-
- for ( idx = 0; idx < count; idx++ )
- {
- CF2_Fixed v = cf2_stack_getReal( opStack, idx );
-
-
- if ( isX )
- curX = ADD_INT32( curX, v );
- else
- curY = ADD_INT32( curY, v );
-
- isX = !isX;
-
- cf2_glyphpath_lineTo( &glyphPath, curX, curY );
- }
-
- cf2_stack_clear( opStack );
- }
- continue;
-
- case cf2_cmdRCURVELINE:
- case cf2_cmdRRCURVETO:
- {
- CF2_UInt count = cf2_stack_count( opStack );
- CF2_UInt idx = 0;
-
-
- FT_TRACE4(( op1 == cf2_cmdRCURVELINE ? " rcurveline\n"
- : " rrcurveto\n" ));
-
- while ( idx + 6 <= count )
- {
- CF2_Fixed x1, y1, x2, y2, x3, y3;
-
-
- x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX );
- y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), curY );
- x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), x1 );
- y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y1 );
- x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), x2 );
- y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 5 ), y2 );
-
- cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
-
- curX = x3;
- curY = y3;
- idx += 6;
- }
-
- if ( op1 == cf2_cmdRCURVELINE )
- {
- curX = ADD_INT32( curX, cf2_stack_getReal( opStack,
- idx + 0 ) );
- curY = ADD_INT32( curY, cf2_stack_getReal( opStack,
- idx + 1 ) );
-
- cf2_glyphpath_lineTo( &glyphPath, curX, curY );
- }
-
- cf2_stack_clear( opStack );
- }
- continue; /* no need to clear stack again */
-
- case cf2_cmdCALLGSUBR:
- case cf2_cmdCALLSUBR:
- {
- CF2_Int subrNum;
-
-
- FT_TRACE4(( op1 == cf2_cmdCALLGSUBR ? " callgsubr"
- : " callsubr" ));
-
- if ( charstringIndex > CF2_MAX_SUBR )
- {
- /* max subr plus one for charstring */
- lastError = FT_THROW( Invalid_Glyph_Format );
- goto exit; /* overflow of stack */
- }
-
- /* push our current CFF charstring region on subrStack */
- charstring = (CF2_Buffer)
- cf2_arrstack_getPointer(
- &subrStack,
- (size_t)charstringIndex + 1 );
-
- /* set up the new CFF region and pointer */
- subrNum = cf2_stack_popInt( opStack );
-
- switch ( op1 )
- {
- case cf2_cmdCALLGSUBR:
- FT_TRACE4(( " (idx %d, entering level %d)\n",
- subrNum + decoder->globals_bias,
- charstringIndex + 1 ));
-
- if ( cf2_initGlobalRegionBuffer( decoder,
- subrNum,
- charstring ) )
- {
- lastError = FT_THROW( Invalid_Glyph_Format );
- goto exit; /* subroutine lookup or stream error */
- }
- break;
-
- default:
- /* cf2_cmdCALLSUBR */
- FT_TRACE4(( " (idx %d, entering level %d)\n",
- subrNum + decoder->locals_bias,
- charstringIndex + 1 ));
-
- if ( cf2_initLocalRegionBuffer( decoder,
- subrNum,
- charstring ) )
- {
- lastError = FT_THROW( Invalid_Glyph_Format );
- goto exit; /* subroutine lookup or stream error */
- }
- }
-
- charstringIndex += 1; /* entry is valid now */
- }
- continue; /* do not clear the stack */
-
- case cf2_cmdRETURN:
- FT_TRACE4(( " return (leaving level %d)\n", charstringIndex ));
-
- if ( charstringIndex < 1 )
- {
- /* Note: cannot return from top charstring */
- lastError = FT_THROW( Invalid_Glyph_Format );
- goto exit; /* underflow of stack */
- }
-
- /* restore position in previous charstring */
- charstring = (CF2_Buffer)
- cf2_arrstack_getPointer(
- &subrStack,
- (CF2_UInt)--charstringIndex );
- continue; /* do not clear the stack */
-
- case cf2_cmdESC:
- {
- FT_Byte op2 = (FT_Byte)cf2_buf_readByte( charstring );
-
-
- /* first switch for 2-byte operators handles CFF2 */
- /* and opcodes that are reserved for both CFF and CFF2 */
- switch ( op2 )
- {
- case cf2_escHFLEX:
- {
- static const FT_Bool readFromStack[12] =
- {
- TRUE /* dx1 */, FALSE /* dy1 */,
- TRUE /* dx2 */, TRUE /* dy2 */,
- TRUE /* dx3 */, FALSE /* dy3 */,
- TRUE /* dx4 */, FALSE /* dy4 */,
- TRUE /* dx5 */, FALSE /* dy5 */,
- TRUE /* dx6 */, FALSE /* dy6 */
- };
-
-
- FT_TRACE4(( " hflex\n" ));
-
- cf2_doFlex( opStack,
- &curX,
- &curY,
- &glyphPath,
- readFromStack,
- FALSE /* doConditionalLastRead */ );
- }
- continue;
-
- case cf2_escFLEX:
- {
- static const FT_Bool readFromStack[12] =
- {
- TRUE /* dx1 */, TRUE /* dy1 */,
- TRUE /* dx2 */, TRUE /* dy2 */,
- TRUE /* dx3 */, TRUE /* dy3 */,
- TRUE /* dx4 */, TRUE /* dy4 */,
- TRUE /* dx5 */, TRUE /* dy5 */,
- TRUE /* dx6 */, TRUE /* dy6 */
- };
-
-
- FT_TRACE4(( " flex\n" ));
-
- cf2_doFlex( opStack,
- &curX,
- &curY,
- &glyphPath,
- readFromStack,
- FALSE /* doConditionalLastRead */ );
- }
- break; /* TODO: why is this not a continue? */
-
- case cf2_escHFLEX1:
- {
- static const FT_Bool readFromStack[12] =
- {
- TRUE /* dx1 */, TRUE /* dy1 */,
- TRUE /* dx2 */, TRUE /* dy2 */,
- TRUE /* dx3 */, FALSE /* dy3 */,
- TRUE /* dx4 */, FALSE /* dy4 */,
- TRUE /* dx5 */, TRUE /* dy5 */,
- TRUE /* dx6 */, FALSE /* dy6 */
- };
-
-
- FT_TRACE4(( " hflex1\n" ));
-
- cf2_doFlex( opStack,
- &curX,
- &curY,
- &glyphPath,
- readFromStack,
- FALSE /* doConditionalLastRead */ );
- }
- continue;
-
- case cf2_escFLEX1:
- {
- static const FT_Bool readFromStack[12] =
- {
- TRUE /* dx1 */, TRUE /* dy1 */,
- TRUE /* dx2 */, TRUE /* dy2 */,
- TRUE /* dx3 */, TRUE /* dy3 */,
- TRUE /* dx4 */, TRUE /* dy4 */,
- TRUE /* dx5 */, TRUE /* dy5 */,
- FALSE /* dx6 */, FALSE /* dy6 */
- };
-
-
- FT_TRACE4(( " flex1\n" ));
-
- cf2_doFlex( opStack,
- &curX,
- &curY,
- &glyphPath,
- readFromStack,
- TRUE /* doConditionalLastRead */ );
- }
- continue;
-
- /* these opcodes are reserved in both CFF & CFF2 */
- case cf2_escRESERVED_1:
- case cf2_escRESERVED_2:
- case cf2_escRESERVED_6:
- case cf2_escRESERVED_7:
- case cf2_escRESERVED_8:
- case cf2_escRESERVED_13:
- case cf2_escRESERVED_16:
- case cf2_escRESERVED_17:
- case cf2_escRESERVED_19:
- case cf2_escRESERVED_25:
- case cf2_escRESERVED_31:
- case cf2_escRESERVED_32:
- case cf2_escRESERVED_33:
- FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
- break;
-
- default:
- {
- if ( font->isCFF2 || op2 >= cf2_escRESERVED_38 )
- FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
- else
- {
- /* second switch for 2-byte operators handles just CFF */
- switch ( op2 )
- {
-
- case cf2_escDOTSECTION:
- /* something about `flip type of locking' -- ignore it */
- FT_TRACE4(( " dotsection\n" ));
-
- break;
-
- case cf2_escAND:
- {
- CF2_F16Dot16 arg1;
- CF2_F16Dot16 arg2;
-
-
- FT_TRACE4(( " and\n" ));
-
- arg2 = cf2_stack_popFixed( opStack );
- arg1 = cf2_stack_popFixed( opStack );
-
- cf2_stack_pushInt( opStack, arg1 && arg2 );
- }
- continue; /* do not clear the stack */
-
- case cf2_escOR:
- {
- CF2_F16Dot16 arg1;
- CF2_F16Dot16 arg2;
-
-
- FT_TRACE4(( " or\n" ));
-
- arg2 = cf2_stack_popFixed( opStack );
- arg1 = cf2_stack_popFixed( opStack );
-
- cf2_stack_pushInt( opStack, arg1 || arg2 );
- }
- continue; /* do not clear the stack */
-
- case cf2_escNOT:
- {
- CF2_F16Dot16 arg;
-
-
- FT_TRACE4(( " not\n" ));
-
- arg = cf2_stack_popFixed( opStack );
-
- cf2_stack_pushInt( opStack, !arg );
- }
- continue; /* do not clear the stack */
-
- case cf2_escABS:
- {
- CF2_F16Dot16 arg;
-
-
- FT_TRACE4(( " abs\n" ));
-
- arg = cf2_stack_popFixed( opStack );
-
- if ( arg < -CF2_FIXED_MAX )
- cf2_stack_pushFixed( opStack, CF2_FIXED_MAX );
- else
- cf2_stack_pushFixed( opStack, FT_ABS( arg ) );
- }
- continue; /* do not clear the stack */
-
- case cf2_escADD:
- {
- CF2_F16Dot16 summand1;
- CF2_F16Dot16 summand2;
-
-
- FT_TRACE4(( " add\n" ));
-
- summand2 = cf2_stack_popFixed( opStack );
- summand1 = cf2_stack_popFixed( opStack );
-
- cf2_stack_pushFixed( opStack,
- ADD_INT32( summand1,
- summand2 ) );
- }
- continue; /* do not clear the stack */
-
- case cf2_escSUB:
- {
- CF2_F16Dot16 minuend;
- CF2_F16Dot16 subtrahend;
-
-
- FT_TRACE4(( " sub\n" ));
-
- subtrahend = cf2_stack_popFixed( opStack );
- minuend = cf2_stack_popFixed( opStack );
-
- cf2_stack_pushFixed( opStack,
- SUB_INT32( minuend, subtrahend ) );
- }
- continue; /* do not clear the stack */
-
- case cf2_escDIV:
- {
- CF2_F16Dot16 dividend;
- CF2_F16Dot16 divisor;
-
-
- FT_TRACE4(( " div\n" ));
-
- divisor = cf2_stack_popFixed( opStack );
- dividend = cf2_stack_popFixed( opStack );
-
- cf2_stack_pushFixed( opStack,
- FT_DivFix( dividend, divisor ) );
- }
- continue; /* do not clear the stack */
-
- case cf2_escNEG:
- {
- CF2_F16Dot16 arg;
-
-
- FT_TRACE4(( " neg\n" ));
-
- arg = cf2_stack_popFixed( opStack );
-
- if ( arg < -CF2_FIXED_MAX )
- cf2_stack_pushFixed( opStack, CF2_FIXED_MAX );
- else
- cf2_stack_pushFixed( opStack, -arg );
- }
- continue; /* do not clear the stack */
-
- case cf2_escEQ:
- {
- CF2_F16Dot16 arg1;
- CF2_F16Dot16 arg2;
-
-
- FT_TRACE4(( " eq\n" ));
-
- arg2 = cf2_stack_popFixed( opStack );
- arg1 = cf2_stack_popFixed( opStack );
-
- cf2_stack_pushInt( opStack, arg1 == arg2 );
- }
- continue; /* do not clear the stack */
-
- case cf2_escDROP:
- FT_TRACE4(( " drop\n" ));
-
- (void)cf2_stack_popFixed( opStack );
- continue; /* do not clear the stack */
-
- case cf2_escPUT:
- {
- CF2_F16Dot16 val;
- CF2_Int idx;
-
-
- FT_TRACE4(( " put\n" ));
-
- idx = cf2_stack_popInt( opStack );
- val = cf2_stack_popFixed( opStack );
-
- if ( idx >= 0 && idx < CF2_STORAGE_SIZE )
- storage[idx] = val;
- }
- continue; /* do not clear the stack */
-
- case cf2_escGET:
- {
- CF2_Int idx;
-
-
- FT_TRACE4(( " get\n" ));
-
- idx = cf2_stack_popInt( opStack );
-
- if ( idx >= 0 && idx < CF2_STORAGE_SIZE )
- cf2_stack_pushFixed( opStack, storage[idx] );
- }
- continue; /* do not clear the stack */
-
- case cf2_escIFELSE:
- {
- CF2_F16Dot16 arg1;
- CF2_F16Dot16 arg2;
- CF2_F16Dot16 cond1;
- CF2_F16Dot16 cond2;
-
-
- FT_TRACE4(( " ifelse\n" ));
-
- cond2 = cf2_stack_popFixed( opStack );
- cond1 = cf2_stack_popFixed( opStack );
- arg2 = cf2_stack_popFixed( opStack );
- arg1 = cf2_stack_popFixed( opStack );
-
- cf2_stack_pushFixed( opStack,
- cond1 <= cond2 ? arg1 : arg2 );
- }
- continue; /* do not clear the stack */
-
- case cf2_escRANDOM: /* in spec */
- {
- CF2_F16Dot16 r;
-
-
- FT_TRACE4(( " random\n" ));
-
- /* only use the lower 16 bits of `random' */
- /* to generate a number in the range (0;1] */
- r = (CF2_F16Dot16)
- ( ( decoder->current_subfont->random & 0xFFFF ) + 1 );
-
- decoder->current_subfont->random =
- cff_random( decoder->current_subfont->random );
-
- cf2_stack_pushFixed( opStack, r );
- }
- continue; /* do not clear the stack */
-
- case cf2_escMUL:
- {
- CF2_F16Dot16 factor1;
- CF2_F16Dot16 factor2;
-
-
- FT_TRACE4(( " mul\n" ));
-
- factor2 = cf2_stack_popFixed( opStack );
- factor1 = cf2_stack_popFixed( opStack );
-
- cf2_stack_pushFixed( opStack,
- FT_MulFix( factor1, factor2 ) );
- }
- continue; /* do not clear the stack */
-
- case cf2_escSQRT:
- {
- CF2_F16Dot16 arg;
-
-
- FT_TRACE4(( " sqrt\n" ));
-
- arg = cf2_stack_popFixed( opStack );
- if ( arg > 0 )
- {
- /* use a start value that doesn't make */
- /* the algorithm's addition overflow */
- FT_Fixed root = arg < 10 ? arg : arg >> 1;
- FT_Fixed new_root;
-
-
- /* Babylonian method */
- for (;;)
- {
- new_root = ( root + FT_DivFix( arg, root ) + 1 ) >> 1;
- if ( new_root == root )
- break;
- root = new_root;
- }
- arg = new_root;
- }
- else
- arg = 0;
-
- cf2_stack_pushFixed( opStack, arg );
- }
- continue; /* do not clear the stack */
-
- case cf2_escDUP:
- {
- CF2_F16Dot16 arg;
-
-
- FT_TRACE4(( " dup\n" ));
-
- arg = cf2_stack_popFixed( opStack );
-
- cf2_stack_pushFixed( opStack, arg );
- cf2_stack_pushFixed( opStack, arg );
- }
- continue; /* do not clear the stack */
-
- case cf2_escEXCH:
- {
- CF2_F16Dot16 arg1;
- CF2_F16Dot16 arg2;
-
-
- FT_TRACE4(( " exch\n" ));
-
- arg2 = cf2_stack_popFixed( opStack );
- arg1 = cf2_stack_popFixed( opStack );
-
- cf2_stack_pushFixed( opStack, arg2 );
- cf2_stack_pushFixed( opStack, arg1 );
- }
- continue; /* do not clear the stack */
-
- case cf2_escINDEX:
- {
- CF2_Int idx;
- CF2_UInt size;
-
-
- FT_TRACE4(( " index\n" ));
-
- idx = cf2_stack_popInt( opStack );
- size = cf2_stack_count( opStack );
-
- if ( size > 0 )
- {
- /* for `cf2_stack_getReal', */
- /* index 0 is bottom of stack */
- CF2_UInt gr_idx;
-
-
- if ( idx < 0 )
- gr_idx = size - 1;
- else if ( (CF2_UInt)idx >= size )
- gr_idx = 0;
- else
- gr_idx = size - 1 - (CF2_UInt)idx;
-
- cf2_stack_pushFixed( opStack,
- cf2_stack_getReal( opStack,
- gr_idx ) );
- }
- }
- continue; /* do not clear the stack */
-
- case cf2_escROLL:
- {
- CF2_Int idx;
- CF2_Int count;
-
-
- FT_TRACE4(( " roll\n" ));
-
- idx = cf2_stack_popInt( opStack );
- count = cf2_stack_popInt( opStack );
-
- cf2_stack_roll( opStack, count, idx );
- }
- continue; /* do not clear the stack */
-
- } /* end of 2nd switch checking op2 */
- }
- }
- } /* end of 1st switch checking op2 */
- } /* case cf2_cmdESC */
-
- break;
-
- case cf2_cmdENDCHAR:
- FT_TRACE4(( " endchar\n" ));
-
- if ( cf2_stack_count( opStack ) == 1 ||
- cf2_stack_count( opStack ) == 5 )
- {
- if ( !haveWidth )
- *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ),
- nominalWidthX );
- }
-
- /* width is defined or default after this */
- haveWidth = TRUE;
-
- if ( font->decoder->width_only )
- goto exit;
-
- /* close path if still open */
- cf2_glyphpath_closeOpenPath( &glyphPath );
-
- /* disable seac for CFF2 (charstring ending with args on stack) */
- if ( !font->isCFF2 && cf2_stack_count( opStack ) > 1 )
- {
- /* must be either 4 or 5 -- */
- /* this is a (deprecated) implied `seac' operator */
-
- CF2_Int achar;
- CF2_Int bchar;
- CF2_BufferRec component;
- CF2_Fixed dummyWidth; /* ignore component width */
- FT_Error error2;
-
-
- if ( doingSeac )
- {
- lastError = FT_THROW( Invalid_Glyph_Format );
- goto exit; /* nested seac */
- }
-
- achar = cf2_stack_popInt( opStack );
- bchar = cf2_stack_popInt( opStack );
-
- curY = cf2_stack_popFixed( opStack );
- curX = cf2_stack_popFixed( opStack );
-
- error2 = cf2_getSeacComponent( decoder, achar, &component );
- if ( error2 )
- {
- lastError = error2; /* pass FreeType error through */
- goto exit;
- }
- cf2_interpT2CharString( font,
- &component,
- callbacks,
- translation,
- TRUE,
- curX,
- curY,
- &dummyWidth );
- cf2_freeSeacComponent( decoder, &component );
-
- error2 = cf2_getSeacComponent( decoder, bchar, &component );
- if ( error2 )
- {
- lastError = error2; /* pass FreeType error through */
- goto exit;
- }
- cf2_interpT2CharString( font,
- &component,
- callbacks,
- translation,
- TRUE,
- 0,
- 0,
- &dummyWidth );
- cf2_freeSeacComponent( decoder, &component );
- }
- goto exit;
-
- case cf2_cmdCNTRMASK:
- case cf2_cmdHINTMASK:
- /* the final \n in the tracing message gets added in */
- /* `cf2_hintmask_read' (which also traces the mask bytes) */
- FT_TRACE4(( op1 == cf2_cmdCNTRMASK ? " cntrmask" : " hintmask" ));
-
- /* never add hints after the mask is computed */
- if ( cf2_stack_count( opStack ) > 1 &&
- cf2_hintmask_isValid( &hintMask ) )
- {
- FT_TRACE4(( "cf2_interpT2CharString: invalid hint mask\n" ));
- break;
- }
-
- /* if there are arguments on the stack, there this is an */
- /* implied cf2_cmdVSTEMHM */
- cf2_doStems( font,
- opStack,
- &vStemHintArray,
- width,
- &haveWidth,
- 0 );
-
- if ( font->decoder->width_only )
- goto exit;
-
- if ( op1 == cf2_cmdHINTMASK )
- {
- /* consume the hint mask bytes which follow the operator */
- cf2_hintmask_read( &hintMask,
- charstring,
- cf2_arrstack_size( &hStemHintArray ) +
- cf2_arrstack_size( &vStemHintArray ) );
- }
- else
- {
- /*
- * Consume the counter mask bytes which follow the operator:
- * Build a temporary hint map, just to place and lock those
- * stems participating in the counter mask. These are most
- * likely the dominant hstems, and are grouped together in a
- * few counter groups, not necessarily in correspondence
- * with the hint groups. This reduces the chances of
- * conflicts between hstems that are initially placed in
- * separate hint groups and then brought together. The
- * positions are copied back to `hStemHintArray', so we can
- * discard `counterMask' and `counterHintMap'.
- *
- */
- CF2_HintMapRec counterHintMap;
- CF2_HintMaskRec counterMask;
-
-
- cf2_hintmap_init( &counterHintMap,
- font,
- &glyphPath.initialHintMap,
- &glyphPath.hintMoves,
- scaleY );
- cf2_hintmask_init( &counterMask, error );
-
- cf2_hintmask_read( &counterMask,
- charstring,
- cf2_arrstack_size( &hStemHintArray ) +
- cf2_arrstack_size( &vStemHintArray ) );
- cf2_hintmap_build( &counterHintMap,
- &hStemHintArray,
- &vStemHintArray,
- &counterMask,
- 0,
- FALSE );
- }
- break;
-
- case cf2_cmdRMOVETO:
- FT_TRACE4(( " rmoveto\n" ));
-
- if ( cf2_stack_count( opStack ) > 2 && !haveWidth )
- *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ),
- nominalWidthX );
-
- /* width is defined or default after this */
- haveWidth = TRUE;
-
- if ( font->decoder->width_only )
- goto exit;
-
- curY = ADD_INT32( curY, cf2_stack_popFixed( opStack ) );
- curX = ADD_INT32( curX, cf2_stack_popFixed( opStack ) );
-
- cf2_glyphpath_moveTo( &glyphPath, curX, curY );
-
- break;
-
- case cf2_cmdHMOVETO:
- FT_TRACE4(( " hmoveto\n" ));
-
- if ( cf2_stack_count( opStack ) > 1 && !haveWidth )
- *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ),
- nominalWidthX );
-
- /* width is defined or default after this */
- haveWidth = TRUE;
-
- if ( font->decoder->width_only )
- goto exit;
-
- curX = ADD_INT32( curX, cf2_stack_popFixed( opStack ) );
-
- cf2_glyphpath_moveTo( &glyphPath, curX, curY );
-
- break;
-
- case cf2_cmdRLINECURVE:
- {
- CF2_UInt count = cf2_stack_count( opStack );
- CF2_UInt idx = 0;
-
-
- FT_TRACE4(( " rlinecurve\n" ));
-
- while ( idx + 6 < count )
- {
- curX = ADD_INT32( curX, cf2_stack_getReal( opStack,
- idx + 0 ) );
- curY = ADD_INT32( curY, cf2_stack_getReal( opStack,
- idx + 1 ) );
-
- cf2_glyphpath_lineTo( &glyphPath, curX, curY );
- idx += 2;
- }
-
- while ( idx < count )
- {
- CF2_Fixed x1, y1, x2, y2, x3, y3;
-
-
- x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX );
- y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), curY );
- x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), x1 );
- y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y1 );
- x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), x2 );
- y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 5 ), y2 );
-
- cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
-
- curX = x3;
- curY = y3;
- idx += 6;
- }
-
- cf2_stack_clear( opStack );
- }
- continue; /* no need to clear stack again */
-
- case cf2_cmdVVCURVETO:
- {
- CF2_UInt count, count1 = cf2_stack_count( opStack );
- CF2_UInt idx = 0;
-
-
- /* if `cf2_stack_count' isn't of the form 4n or 4n+1, */
- /* we enforce it by clearing the second bit */
- /* (and sorting the stack indexing to suit) */
- count = count1 & ~2U;
- idx += count1 - count;
-
- FT_TRACE4(( " vvcurveto\n" ));
-
- while ( idx < count )
- {
- CF2_Fixed x1, y1, x2, y2, x3, y3;
-
-
- if ( ( count - idx ) & 1 )
- {
- x1 = ADD_INT32( cf2_stack_getReal( opStack, idx ), curX );
-
- idx++;
- }
- else
- x1 = curX;
-
- y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curY );
- x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 );
- y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 );
- x3 = x2;
- y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y2 );
-
- cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
-
- curX = x3;
- curY = y3;
- idx += 4;
- }
-
- cf2_stack_clear( opStack );
- }
- continue; /* no need to clear stack again */
-
- case cf2_cmdHHCURVETO:
- {
- CF2_UInt count, count1 = cf2_stack_count( opStack );
- CF2_UInt idx = 0;
-
-
- /* if `cf2_stack_count' isn't of the form 4n or 4n+1, */
- /* we enforce it by clearing the second bit */
- /* (and sorting the stack indexing to suit) */
- count = count1 & ~2U;
- idx += count1 - count;
-
- FT_TRACE4(( " hhcurveto\n" ));
-
- while ( idx < count )
- {
- CF2_Fixed x1, y1, x2, y2, x3, y3;
-
-
- if ( ( count - idx ) & 1 )
- {
- y1 = ADD_INT32( cf2_stack_getReal( opStack, idx ), curY );
-
- idx++;
- }
- else
- y1 = curY;
-
- x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX );
- x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 );
- y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 );
- x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), x2 );
- y3 = y2;
-
- cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
-
- curX = x3;
- curY = y3;
- idx += 4;
- }
-
- cf2_stack_clear( opStack );
- }
- continue; /* no need to clear stack again */
-
- case cf2_cmdVHCURVETO:
- case cf2_cmdHVCURVETO:
- {
- CF2_UInt count, count1 = cf2_stack_count( opStack );
- CF2_UInt idx = 0;
-
- FT_Bool alternate = FT_BOOL( op1 == cf2_cmdHVCURVETO );
-
-
- /* if `cf2_stack_count' isn't of the form 8n, 8n+1, */
- /* 8n+4, or 8n+5, we enforce it by clearing the */
- /* second bit */
- /* (and sorting the stack indexing to suit) */
- count = count1 & ~2U;
- idx += count1 - count;
-
- FT_TRACE4(( alternate ? " hvcurveto\n" : " vhcurveto\n" ));
-
- while ( idx < count )
- {
- CF2_Fixed x1, x2, x3, y1, y2, y3;
-
-
- if ( alternate )
- {
- x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX );
- y1 = curY;
- x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 );
- y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 );
- y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y2 );
-
- if ( count - idx == 5 )
- {
- x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), x2 );
-
- idx++;
- }
- else
- x3 = x2;
-
- alternate = FALSE;
- }
- else
- {
- x1 = curX;
- y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curY );
- x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 );
- y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 );
- x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), x2 );
-
- if ( count - idx == 5 )
- {
- y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), y2 );
-
- idx++;
- }
- else
- y3 = y2;
-
- alternate = TRUE;
- }
-
- cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
-
- curX = x3;
- curY = y3;
- idx += 4;
- }
-
- cf2_stack_clear( opStack );
- }
- continue; /* no need to clear stack again */
-
- case cf2_cmdEXTENDEDNMBR:
- {
- CF2_Int v;
-
- CF2_Int byte1 = cf2_buf_readByte( charstring );
- CF2_Int byte2 = cf2_buf_readByte( charstring );
-
-
- v = (FT_Short)( ( byte1 << 8 ) |
- byte2 );
-
- FT_TRACE4(( " %d", v ));
-
- cf2_stack_pushInt( opStack, v );
- }
- continue;
-
- default:
- /* numbers */
- {
- if ( /* op1 >= 32 && */ op1 <= 246 )
- {
- CF2_Int v;
-
-
- v = op1 - 139;
-
- FT_TRACE4(( " %d", v ));
-
- /* -107 .. 107 */
- cf2_stack_pushInt( opStack, v );
- }
-
- else if ( /* op1 >= 247 && */ op1 <= 250 )
- {
- CF2_Int v;
-
-
- v = op1;
- v -= 247;
- v *= 256;
- v += cf2_buf_readByte( charstring );
- v += 108;
-
- FT_TRACE4(( " %d", v ));
-
- /* 108 .. 1131 */
- cf2_stack_pushInt( opStack, v );
- }
-
- else if ( /* op1 >= 251 && */ op1 <= 254 )
- {
- CF2_Int v;
-
-
- v = op1;
- v -= 251;
- v *= 256;
- v += cf2_buf_readByte( charstring );
- v = -v - 108;
-
- FT_TRACE4(( " %d", v ));
-
- /* -1131 .. -108 */
- cf2_stack_pushInt( opStack, v );
- }
-
- else /* op1 == 255 */
- {
- CF2_Fixed v;
-
- FT_UInt32 byte1 = (FT_UInt32)cf2_buf_readByte( charstring );
- FT_UInt32 byte2 = (FT_UInt32)cf2_buf_readByte( charstring );
- FT_UInt32 byte3 = (FT_UInt32)cf2_buf_readByte( charstring );
- FT_UInt32 byte4 = (FT_UInt32)cf2_buf_readByte( charstring );
-
-
- v = (CF2_Fixed)( ( byte1 << 24 ) |
- ( byte2 << 16 ) |
- ( byte3 << 8 ) |
- byte4 );
-
- FT_TRACE4(( " %.5f", v / 65536.0 ));
-
- cf2_stack_pushFixed( opStack, v );
- }
- }
- continue; /* don't clear stack */
-
- } /* end of switch statement checking `op1' */
-
- cf2_stack_clear( opStack );
-
- } /* end of main interpreter loop */
-
- /* we get here if the charstring ends without cf2_cmdENDCHAR */
- FT_TRACE4(( "cf2_interpT2CharString:"
- " charstring ends without ENDCHAR\n" ));
-
- exit:
- /* check whether last error seen is also the first one */
- cf2_setError( error, lastError );
-
- if ( *error )
- FT_TRACE4(( "charstring error %d\n", *error ));
-
- /* free resources from objects we've used */
- cf2_glyphpath_finalize( &glyphPath );
- cf2_arrstack_finalize( &vStemHintArray );
- cf2_arrstack_finalize( &hStemHintArray );
- cf2_arrstack_finalize( &subrStack );
- cf2_stack_free( opStack );
-
- FT_TRACE4(( "\n" ));
-
- return;
- }
-
-
-/* END */
diff --git a/thirdparty/freetype/src/cff/cf2intrp.h b/thirdparty/freetype/src/cff/cf2intrp.h
deleted file mode 100644
index ec030e8944..0000000000
--- a/thirdparty/freetype/src/cff/cf2intrp.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/***************************************************************************/
-/* */
-/* cf2font.h */
-/* */
-/* Adobe's CFF Interpreter (specification). */
-/* */
-/* Copyright 2007-2013 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
-
-
-#ifndef CF2INTRP_H_
-#define CF2INTRP_H_
-
-
-#include "cf2ft.h"
-#include "cf2hints.h"
-
-
-FT_BEGIN_HEADER
-
-
- FT_LOCAL( void )
- cf2_hintmask_init( CF2_HintMask hintmask,
- FT_Error* error );
- FT_LOCAL( FT_Bool )
- cf2_hintmask_isValid( const CF2_HintMask hintmask );
- FT_LOCAL( FT_Bool )
- cf2_hintmask_isNew( const CF2_HintMask hintmask );
- FT_LOCAL( void )
- cf2_hintmask_setNew( CF2_HintMask hintmask,
- FT_Bool val );
- FT_LOCAL( FT_Byte* )
- cf2_hintmask_getMaskPtr( CF2_HintMask hintmask );
- FT_LOCAL( void )
- cf2_hintmask_setAll( CF2_HintMask hintmask,
- size_t bitCount );
-
- FT_LOCAL( void )
- cf2_interpT2CharString( CF2_Font font,
- CF2_Buffer charstring,
- CF2_OutlineCallbacks callbacks,
- const FT_Vector* translation,
- FT_Bool doingSeac,
- CF2_Fixed curX,
- CF2_Fixed curY,
- CF2_Fixed* width );
-
-
-FT_END_HEADER
-
-
-#endif /* CF2INTRP_H_ */
-
-
-/* END */
diff --git a/thirdparty/freetype/src/cff/cf2read.c b/thirdparty/freetype/src/cff/cf2read.c
deleted file mode 100644
index 2b429e3eeb..0000000000
--- a/thirdparty/freetype/src/cff/cf2read.c
+++ /dev/null
@@ -1,112 +0,0 @@
-/***************************************************************************/
-/* */
-/* cf2read.c */
-/* */
-/* Adobe's code for stream handling (body). */
-/* */
-/* Copyright 2007-2013 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
-
-
-#include "cf2ft.h"
-#include FT_INTERNAL_DEBUG_H
-
-#include "cf2glue.h"
-
-#include "cf2error.h"
-
-
- /* Define CF2_IO_FAIL as 1 to enable random errors and random */
- /* value errors in I/O. */
-#define CF2_IO_FAIL 0
-
-
-#if CF2_IO_FAIL
-
- /* set the .00 value to a nonzero probability */
- static int
- randomError2( void )
- {
- /* for region buffer ReadByte (interp) function */
- return (double)rand() / RAND_MAX < .00;
- }
-
- /* set the .00 value to a nonzero probability */
- static CF2_Int
- randomValue()
- {
- return (double)rand() / RAND_MAX < .00 ? rand() : 0;
- }
-
-#endif /* CF2_IO_FAIL */
-
-
- /* Region Buffer */
- /* */
- /* Can be constructed from a copied buffer managed by */
- /* `FCM_getDatablock'. */
- /* Reads bytes with check for end of buffer. */
-
- /* reading past the end of the buffer sets error and returns zero */
- FT_LOCAL_DEF( CF2_Int )
- cf2_buf_readByte( CF2_Buffer buf )
- {
- if ( buf->ptr < buf->end )
- {
-#if CF2_IO_FAIL
- if ( randomError2() )
- {
- CF2_SET_ERROR( buf->error, Invalid_Stream_Operation );
- return 0;
- }
-
- return *(buf->ptr)++ + randomValue();
-#else
- return *(buf->ptr)++;
-#endif
- }
- else
- {
- CF2_SET_ERROR( buf->error, Invalid_Stream_Operation );
- return 0;
- }
- }
-
-
- /* note: end condition can occur without error */
- FT_LOCAL_DEF( FT_Bool )
- cf2_buf_isEnd( CF2_Buffer buf )
- {
- return (FT_Bool)( buf->ptr >= buf->end );
- }
-
-
-/* END */
diff --git a/thirdparty/freetype/src/cff/cf2read.h b/thirdparty/freetype/src/cff/cf2read.h
deleted file mode 100644
index b0b0db803a..0000000000
--- a/thirdparty/freetype/src/cff/cf2read.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/***************************************************************************/
-/* */
-/* cf2read.h */
-/* */
-/* Adobe's code for stream handling (specification). */
-/* */
-/* Copyright 2007-2013 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
-
-
-#ifndef CF2READ_H_
-#define CF2READ_H_
-
-
-FT_BEGIN_HEADER
-
-
- typedef struct CF2_BufferRec_
- {
- FT_Error* error;
- const FT_Byte* start;
- const FT_Byte* end;
- const FT_Byte* ptr;
-
- } CF2_BufferRec, *CF2_Buffer;
-
-
- FT_LOCAL( CF2_Int )
- cf2_buf_readByte( CF2_Buffer buf );
- FT_LOCAL( FT_Bool )
- cf2_buf_isEnd( CF2_Buffer buf );
-
-
-FT_END_HEADER
-
-
-#endif /* CF2READ_H_ */
-
-
-/* END */
diff --git a/thirdparty/freetype/src/cff/cf2stack.c b/thirdparty/freetype/src/cff/cf2stack.c
deleted file mode 100644
index 12a026d21d..0000000000
--- a/thirdparty/freetype/src/cff/cf2stack.c
+++ /dev/null
@@ -1,328 +0,0 @@
-/***************************************************************************/
-/* */
-/* cf2stack.c */
-/* */
-/* Adobe's code for emulating a CFF stack (body). */
-/* */
-/* Copyright 2007-2013 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
-
-
-#include "cf2ft.h"
-#include FT_INTERNAL_DEBUG_H
-
-#include "cf2glue.h"
-#include "cf2font.h"
-#include "cf2stack.h"
-
-#include "cf2error.h"
-
-
- /* Allocate and initialize an instance of CF2_Stack. */
- /* Note: This function returns NULL on error (does not set */
- /* `error'). */
- FT_LOCAL_DEF( CF2_Stack )
- cf2_stack_init( FT_Memory memory,
- FT_Error* e,
- FT_UInt stackSize )
- {
- FT_Error error = FT_Err_Ok; /* for FT_NEW */
-
- CF2_Stack stack = NULL;
-
-
- if ( !FT_NEW( stack ) )
- {
- /* initialize the structure; FT_NEW zeroes it */
- stack->memory = memory;
- stack->error = e;
- }
-
- /* allocate the stack buffer */
- if ( FT_NEW_ARRAY( stack->buffer, stackSize ) )
- {
- FT_FREE( stack );
- return NULL;
- }
-
- stack->stackSize = stackSize;
- stack->top = stack->buffer; /* empty stack */
-
- return stack;
- }
-
-
- FT_LOCAL_DEF( void )
- cf2_stack_free( CF2_Stack stack )
- {
- if ( stack )
- {
- FT_Memory memory = stack->memory;
-
- /* free the buffer */
- FT_FREE( stack->buffer );
-
- /* free the main structure */
- FT_FREE( stack );
- }
- }
-
-
- FT_LOCAL_DEF( CF2_UInt )
- cf2_stack_count( CF2_Stack stack )
- {
- return (CF2_UInt)( stack->top - stack->buffer );
- }
-
-
- FT_LOCAL_DEF( void )
- cf2_stack_pushInt( CF2_Stack stack,
- CF2_Int val )
- {
- if ( stack->top == stack->buffer + stack->stackSize )
- {
- CF2_SET_ERROR( stack->error, Stack_Overflow );
- return; /* stack overflow */
- }
-
- stack->top->u.i = val;
- stack->top->type = CF2_NumberInt;
- stack->top++;
- }
-
-
- FT_LOCAL_DEF( void )
- cf2_stack_pushFixed( CF2_Stack stack,
- CF2_Fixed val )
- {
- if ( stack->top == stack->buffer + stack->stackSize )
- {
- CF2_SET_ERROR( stack->error, Stack_Overflow );
- return; /* stack overflow */
- }
-
- stack->top->u.r = val;
- stack->top->type = CF2_NumberFixed;
- stack->top++;
- }
-
-
- /* this function is only allowed to pop an integer type */
- FT_LOCAL_DEF( CF2_Int )
- cf2_stack_popInt( CF2_Stack stack )
- {
- if ( stack->top == stack->buffer )
- {
- CF2_SET_ERROR( stack->error, Stack_Underflow );
- return 0; /* underflow */
- }
- if ( stack->top[-1].type != CF2_NumberInt )
- {
- CF2_SET_ERROR( stack->error, Syntax_Error );
- return 0; /* type mismatch */
- }
-
- stack->top--;
-
- return stack->top->u.i;
- }
-
-
- /* Note: type mismatch is silently cast */
- /* TODO: check this */
- FT_LOCAL_DEF( CF2_Fixed )
- cf2_stack_popFixed( CF2_Stack stack )
- {
- if ( stack->top == stack->buffer )
- {
- CF2_SET_ERROR( stack->error, Stack_Underflow );
- return cf2_intToFixed( 0 ); /* underflow */
- }
-
- stack->top--;
-
- switch ( stack->top->type )
- {
- case CF2_NumberInt:
- return cf2_intToFixed( stack->top->u.i );
- case CF2_NumberFrac:
- return cf2_fracToFixed( stack->top->u.f );
- default:
- return stack->top->u.r;
- }
- }
-
-
- /* Note: type mismatch is silently cast */
- /* TODO: check this */
- FT_LOCAL_DEF( CF2_Fixed )
- cf2_stack_getReal( CF2_Stack stack,
- CF2_UInt idx )
- {
- FT_ASSERT( cf2_stack_count( stack ) <= stack->stackSize );
-
- if ( idx >= cf2_stack_count( stack ) )
- {
- CF2_SET_ERROR( stack->error, Stack_Overflow );
- return cf2_intToFixed( 0 ); /* bounds error */
- }
-
- switch ( stack->buffer[idx].type )
- {
- case CF2_NumberInt:
- return cf2_intToFixed( stack->buffer[idx].u.i );
- case CF2_NumberFrac:
- return cf2_fracToFixed( stack->buffer[idx].u.f );
- default:
- return stack->buffer[idx].u.r;
- }
- }
-
-
- /* provide random access to stack */
- FT_LOCAL_DEF( void )
- cf2_stack_setReal( CF2_Stack stack,
- CF2_UInt idx,
- CF2_Fixed val )
- {
- if ( idx > cf2_stack_count( stack ) )
- {
- CF2_SET_ERROR( stack->error, Stack_Overflow );
- return;
- }
-
- stack->buffer[idx].u.r = val;
- stack->buffer[idx].type = CF2_NumberFixed;
- }
-
-
- /* discard (pop) num values from stack */
- FT_LOCAL_DEF( void )
- cf2_stack_pop( CF2_Stack stack,
- CF2_UInt num )
- {
- if ( num > cf2_stack_count( stack ) )
- {
- CF2_SET_ERROR( stack->error, Stack_Underflow );
- return;
- }
- stack->top -= num;
- }
-
-
- FT_LOCAL_DEF( void )
- cf2_stack_roll( CF2_Stack stack,
- CF2_Int count,
- CF2_Int shift )
- {
- /* we initialize this variable to avoid compiler warnings */
- CF2_StackNumber last = { { 0 }, CF2_NumberInt };
-
- CF2_Int start_idx, idx, i;
-
-
- if ( count < 2 )
- return; /* nothing to do (values 0 and 1), or undefined value */
-
- if ( (CF2_UInt)count > cf2_stack_count( stack ) )
- {
- CF2_SET_ERROR( stack->error, Stack_Overflow );
- return;
- }
-
- if ( shift < 0 )
- shift = -( ( -shift ) % count );
- else
- shift %= count;
-
- if ( shift == 0 )
- return; /* nothing to do */
-
- /* We use the following algorithm to do the rolling, */
- /* which needs two temporary variables only. */
- /* */
- /* Example: */
- /* */
- /* count = 8 */
- /* shift = 2 */
- /* */
- /* stack indices before roll: 7 6 5 4 3 2 1 0 */
- /* stack indices after roll: 1 0 7 6 5 4 3 2 */
- /* */
- /* The value of index 0 gets moved to index 2, while */
- /* the old value of index 2 gets moved to index 4, */
- /* and so on. We thus have the following copying */
- /* chains for shift value 2. */
- /* */
- /* 0 -> 2 -> 4 -> 6 -> 0 */
- /* 1 -> 3 -> 5 -> 7 -> 1 */
- /* */
- /* If `count' and `shift' are incommensurable, we */
- /* have a single chain only. Otherwise, increase */
- /* the start index by 1 after the first chain, then */
- /* do the next chain until all elements in all */
- /* chains are handled. */
-
- start_idx = -1;
- idx = -1;
- for ( i = 0; i < count; i++ )
- {
- CF2_StackNumber tmp;
-
-
- if ( start_idx == idx )
- {
- start_idx++;
- idx = start_idx;
- last = stack->buffer[idx];
- }
-
- idx += shift;
- if ( idx >= count )
- idx -= count;
- else if ( idx < 0 )
- idx += count;
-
- tmp = stack->buffer[idx];
- stack->buffer[idx] = last;
- last = tmp;
- }
- }
-
-
- FT_LOCAL_DEF( void )
- cf2_stack_clear( CF2_Stack stack )
- {
- stack->top = stack->buffer;
- }
-
-
-/* END */
diff --git a/thirdparty/freetype/src/cff/cf2stack.h b/thirdparty/freetype/src/cff/cf2stack.h
deleted file mode 100644
index ef08eefe41..0000000000
--- a/thirdparty/freetype/src/cff/cf2stack.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/***************************************************************************/
-/* */
-/* cf2stack.h */
-/* */
-/* Adobe's code for emulating a CFF stack (specification). */
-/* */
-/* Copyright 2007-2013 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
-
-
-#ifndef CF2STACK_H_
-#define CF2STACK_H_
-
-
-FT_BEGIN_HEADER
-
-
- /* CFF operand stack; specified maximum of 48 or 192 values */
- typedef struct CF2_StackNumber_
- {
- union
- {
- CF2_Fixed r; /* 16.16 fixed point */
- CF2_Frac f; /* 2.30 fixed point (for font matrix) */
- CF2_Int i;
- } u;
-
- CF2_NumberType type;
-
- } CF2_StackNumber;
-
-
- typedef struct CF2_StackRec_
- {
- FT_Memory memory;
- FT_Error* error;
- CF2_StackNumber* buffer;
- CF2_StackNumber* top;
- FT_UInt stackSize;
-
- } CF2_StackRec, *CF2_Stack;
-
-
- FT_LOCAL( CF2_Stack )
- cf2_stack_init( FT_Memory memory,
- FT_Error* error,
- FT_UInt stackSize );
- FT_LOCAL( void )
- cf2_stack_free( CF2_Stack stack );
-
- FT_LOCAL( CF2_UInt )
- cf2_stack_count( CF2_Stack stack );
-
- FT_LOCAL( void )
- cf2_stack_pushInt( CF2_Stack stack,
- CF2_Int val );
- FT_LOCAL( void )
- cf2_stack_pushFixed( CF2_Stack stack,
- CF2_Fixed val );
-
- FT_LOCAL( CF2_Int )
- cf2_stack_popInt( CF2_Stack stack );
- FT_LOCAL( CF2_Fixed )
- cf2_stack_popFixed( CF2_Stack stack );
-
- FT_LOCAL( CF2_Fixed )
- cf2_stack_getReal( CF2_Stack stack,
- CF2_UInt idx );
- FT_LOCAL( void )
- cf2_stack_setReal( CF2_Stack stack,
- CF2_UInt idx,
- CF2_Fixed val );
-
- FT_LOCAL( void )
- cf2_stack_pop( CF2_Stack stack,
- CF2_UInt num );
-
- FT_LOCAL( void )
- cf2_stack_roll( CF2_Stack stack,
- CF2_Int count,
- CF2_Int idx );
-
- FT_LOCAL( void )
- cf2_stack_clear( CF2_Stack stack );
-
-
-FT_END_HEADER
-
-
-#endif /* CF2STACK_H_ */
-
-
-/* END */
diff --git a/thirdparty/freetype/src/cff/cf2types.h b/thirdparty/freetype/src/cff/cf2types.h
deleted file mode 100644
index 5b7e1239af..0000000000
--- a/thirdparty/freetype/src/cff/cf2types.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/***************************************************************************/
-/* */
-/* cf2types.h */
-/* */
-/* Adobe's code for defining data types (specification only). */
-/* */
-/* Copyright 2011-2013 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
-
-
-#ifndef CF2TYPES_H_
-#define CF2TYPES_H_
-
-#include <ft2build.h>
-#include FT_FREETYPE_H
-
-
-FT_BEGIN_HEADER
-
-
- /*
- * The data models that we expect to support are as follows:
- *
- * name char short int long long-long pointer example
- * -----------------------------------------------------
- * ILP32 8 16 32 32 64* 32 32-bit MacOS, x86
- * LLP64 8 16 32 32 64 64 x64
- * LP64 8 16 32 64 64 64 64-bit MacOS
- *
- * *) type may be supported by emulation on a 32-bit architecture
- *
- */
-
-
- /* integers at least 32 bits wide */
-#define CF2_UInt FT_UFast
-#define CF2_Int FT_Fast
-
-
- /* fixed-float numbers */
- typedef FT_Int32 CF2_F16Dot16;
-
-
-FT_END_HEADER
-
-
-#endif /* CF2TYPES_H_ */
-
-
-/* END */
diff --git a/thirdparty/freetype/src/cff/cff.c b/thirdparty/freetype/src/cff/cff.c
index 1a755d5dad..a34ba9b710 100644
--- a/thirdparty/freetype/src/cff/cff.c
+++ b/thirdparty/freetype/src/cff/cff.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* cff.c */
-/* */
-/* FreeType OpenType driver component (body only). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * cff.c
+ *
+ * FreeType OpenType driver component (body only).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#define FT_MAKE_OPTION_SINGLE_OBJECT
@@ -23,7 +23,6 @@
#include "cffdrivr.c"
#include "cffgload.c"
#include "cffparse.c"
-#include "cffpic.c"
#include "cffload.c"
#include "cffobjs.c"
diff --git a/thirdparty/freetype/src/cff/cffcmap.c b/thirdparty/freetype/src/cff/cffcmap.c
index e45ae1127b..15cc94cafb 100644
--- a/thirdparty/freetype/src/cff/cffcmap.c
+++ b/thirdparty/freetype/src/cff/cffcmap.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* cffcmap.c */
-/* */
-/* CFF character mapping table (cmap) support (body). */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * cffcmap.c
+ *
+ * CFF character mapping table (cmap) support (body).
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -161,6 +161,9 @@
if ( !charset->sids )
return FT_THROW( No_Unicode_Glyph_Name );
+ if ( !psnames->unicodes_init )
+ return FT_THROW( Unimplemented_Feature );
+
return psnames->unicodes_init( memory,
unicodes,
cff->num_glyphs,
diff --git a/thirdparty/freetype/src/cff/cffcmap.h b/thirdparty/freetype/src/cff/cffcmap.h
index 856a43dd1b..07366bc748 100644
--- a/thirdparty/freetype/src/cff/cffcmap.h
+++ b/thirdparty/freetype/src/cff/cffcmap.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* cffcmap.h */
-/* */
-/* CFF character mapping table (cmap) support (specification). */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * cffcmap.h
+ *
+ * CFF character mapping table (cmap) support (specification).
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef CFFCMAP_H_
diff --git a/thirdparty/freetype/src/cff/cffdrivr.c b/thirdparty/freetype/src/cff/cffdrivr.c
index df896848da..bbd5c40329 100644
--- a/thirdparty/freetype/src/cff/cffdrivr.c
+++ b/thirdparty/freetype/src/cff/cffdrivr.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* cffdrivr.c */
-/* */
-/* OpenType font driver implementation (body). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * cffdrivr.c
+ *
+ * OpenType font driver implementation (body).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -42,7 +42,6 @@
#endif
#include "cfferrs.h"
-#include "cffpic.h"
#include FT_SERVICE_FONT_FORMAT_H
#include FT_SERVICE_GLYPH_DICT_H
@@ -50,14 +49,14 @@
#include FT_DRIVER_H
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_cffdriver
+#define FT_COMPONENT cffdriver
/*************************************************************************/
@@ -73,38 +72,42 @@
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* <Function> */
- /* cff_get_kerning */
- /* */
- /* <Description> */
- /* A driver method used to return the kerning vector between two */
- /* glyphs of the same face. */
- /* */
- /* <Input> */
- /* face :: A handle to the source face object. */
- /* */
- /* left_glyph :: The index of the left glyph in the kern pair. */
- /* */
- /* right_glyph :: The index of the right glyph in the kern pair. */
- /* */
- /* <Output> */
- /* kerning :: The kerning vector. This is in font units for */
- /* scalable formats, and in pixels for fixed-sizes */
- /* formats. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- /* <Note> */
- /* Only horizontal layouts (left-to-right & right-to-left) are */
- /* supported by this function. Other layouts, or more sophisticated */
- /* kernings, are out of scope of this method (the basic driver */
- /* interface is meant to be simple). */
- /* */
- /* They can be implemented by format-specific interfaces. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * cff_get_kerning
+ *
+ * @Description:
+ * A driver method used to return the kerning vector between two
+ * glyphs of the same face.
+ *
+ * @Input:
+ * face ::
+ * A handle to the source face object.
+ *
+ * left_glyph ::
+ * The index of the left glyph in the kern pair.
+ *
+ * right_glyph ::
+ * The index of the right glyph in the kern pair.
+ *
+ * @Output:
+ * kerning ::
+ * The kerning vector. This is in font units for
+ * scalable formats, and in pixels for fixed-sizes
+ * formats.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ *
+ * @Note:
+ * Only horizontal layouts (left-to-right & right-to-left) are
+ * supported by this function. Other layouts, or more sophisticated
+ * kernings, are out of scope of this method (the basic driver
+ * interface is meant to be simple).
+ *
+ * They can be implemented by format-specific interfaces.
+ */
FT_CALLBACK_DEF( FT_Error )
cff_get_kerning( FT_Face ttface, /* TT_Face */
FT_UInt left_glyph,
@@ -125,32 +128,36 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* cff_glyph_load */
- /* */
- /* <Description> */
- /* A driver method used to load a glyph within a given glyph slot. */
- /* */
- /* <Input> */
- /* slot :: A handle to the target slot object where the glyph */
- /* will be loaded. */
- /* */
- /* size :: A handle to the source face size at which the glyph */
- /* must be scaled, loaded, etc. */
- /* */
- /* glyph_index :: The index of the glyph in the font file. */
- /* */
- /* load_flags :: A flag indicating what to load for this glyph. The */
- /* FT_LOAD_??? constants can be used to control the */
- /* glyph loading process (e.g., whether the outline */
- /* should be scaled, whether to load bitmaps or not, */
- /* whether to hint the outline, etc). */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * cff_glyph_load
+ *
+ * @Description:
+ * A driver method used to load a glyph within a given glyph slot.
+ *
+ * @Input:
+ * slot ::
+ * A handle to the target slot object where the glyph
+ * will be loaded.
+ *
+ * size ::
+ * A handle to the source face size at which the glyph
+ * must be scaled, loaded, etc.
+ *
+ * glyph_index ::
+ * The index of the glyph in the font file.
+ *
+ * load_flags ::
+ * A flag indicating what to load for this glyph. The
+ * FT_LOAD_??? constants can be used to control the
+ * glyph loading process (e.g., whether the outline
+ * should be scaled, whether to load bitmaps or not,
+ * whether to hint the outline, etc).
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_CALLBACK_DEF( FT_Error )
cff_glyph_load( FT_GlyphSlot cffslot, /* CFF_GlyphSlot */
FT_Size cffsize, /* CFF_Size */
@@ -302,7 +309,7 @@
/*
- * GLYPH DICT SERVICE
+ * GLYPH DICT SERVICE
*
*/
@@ -341,7 +348,7 @@
FT_ERROR(( "cff_get_glyph_name:"
" cannot get glyph name from a CFF2 font\n"
" "
- " without the `PSNames' module\n" ));
+ " without the `psnames' module\n" ));
error = FT_THROW( Missing_Module );
goto Exit;
}
@@ -352,7 +359,7 @@
FT_ERROR(( "cff_get_glyph_name:"
" cannot get glyph name from CFF & CEF fonts\n"
" "
- " without the `PSNames' module\n" ));
+ " without the `psnames' module\n" ));
error = FT_THROW( Missing_Module );
goto Exit;
}
@@ -408,7 +415,7 @@
FT_ERROR(( "cff_get_name_index:"
" cannot get glyph index from a CFF2 font\n"
" "
- " without the `PSNames' module\n" ));
+ " without the `psnames' module\n" ));
return 0;
}
}
@@ -446,7 +453,7 @@
/*
- * POSTSCRIPT INFO SERVICE
+ * POSTSCRIPT INFO SERVICE
*
*/
@@ -593,7 +600,7 @@
/*
- * POSTSCRIPT NAME SERVICE
+ * POSTSCRIPT NAME SERVICE
*
*/
@@ -654,8 +661,8 @@
FT_Library library = FT_FACE_LIBRARY( face );
- if ( cmap->clazz != &CFF_CMAP_ENCODING_CLASS_REC_GET &&
- cmap->clazz != &CFF_CMAP_UNICODE_CLASS_REC_GET )
+ if ( cmap->clazz != &cff_cmap_encoding_class_rec &&
+ cmap->clazz != &cff_cmap_unicode_class_rec )
{
FT_Module sfnt = FT_Get_Module( library, "sfnt" );
FT_Service_TTCMaps service =
@@ -682,7 +689,7 @@
/*
- * CID INFO SERVICE
+ * CID INFO SERVICE
*
*/
static FT_Error
@@ -788,7 +795,7 @@
goto Fail;
}
- if ( glyph_index > cff->num_glyphs )
+ if ( glyph_index >= cff->num_glyphs )
{
error = FT_THROW( Invalid_Argument );
goto Fail;
@@ -818,7 +825,7 @@
/*
- * PROPERTY SERVICE
+ * PROPERTY SERVICE
*
*/
@@ -832,7 +839,7 @@
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
/*
- * MULTIPLE MASTER SERVICE
+ * MULTIPLE MASTER SERVICE
*
*/
@@ -861,6 +868,30 @@
static FT_Error
+ cff_set_mm_weightvector( CFF_Face face,
+ FT_UInt len,
+ FT_Fixed* weightvector )
+ {
+ FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm;
+
+
+ return mm->set_mm_weightvector( FT_FACE( face ), len, weightvector );
+ }
+
+
+ static FT_Error
+ cff_get_mm_weightvector( CFF_Face face,
+ FT_UInt* len,
+ FT_Fixed* weightvector )
+ {
+ FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm;
+
+
+ return mm->get_mm_weightvector( FT_FACE( face ), len, weightvector );
+ }
+
+
+ static FT_Error
cff_get_mm_var( CFF_Face face,
FT_MM_Var* *master )
{
@@ -909,22 +940,24 @@
FT_DEFINE_SERVICE_MULTIMASTERSREC(
cff_service_multi_masters,
- (FT_Get_MM_Func) NULL, /* get_mm */
- (FT_Set_MM_Design_Func) NULL, /* set_mm_design */
- (FT_Set_MM_Blend_Func) cff_set_mm_blend, /* set_mm_blend */
- (FT_Get_MM_Blend_Func) cff_get_mm_blend, /* get_mm_blend */
- (FT_Get_MM_Var_Func) cff_get_mm_var, /* get_mm_var */
- (FT_Set_Var_Design_Func)cff_set_var_design, /* set_var_design */
- (FT_Get_Var_Design_Func)cff_get_var_design, /* get_var_design */
- (FT_Set_Instance_Func) cff_set_instance, /* set_instance */
-
- (FT_Get_Var_Blend_Func) cff_get_var_blend, /* get_var_blend */
- (FT_Done_Blend_Func) cff_done_blend /* done_blend */
+ (FT_Get_MM_Func) NULL, /* get_mm */
+ (FT_Set_MM_Design_Func) NULL, /* set_mm_design */
+ (FT_Set_MM_Blend_Func) cff_set_mm_blend, /* set_mm_blend */
+ (FT_Get_MM_Blend_Func) cff_get_mm_blend, /* get_mm_blend */
+ (FT_Get_MM_Var_Func) cff_get_mm_var, /* get_mm_var */
+ (FT_Set_Var_Design_Func) cff_set_var_design, /* set_var_design */
+ (FT_Get_Var_Design_Func) cff_get_var_design, /* get_var_design */
+ (FT_Set_Instance_Func) cff_set_instance, /* set_instance */
+ (FT_Set_MM_WeightVector_Func)cff_set_mm_weightvector, /* set_mm_weightvector */
+ (FT_Get_MM_WeightVector_Func)cff_get_mm_weightvector, /* get_mm_weightvector */
+
+ (FT_Get_Var_Blend_Func) cff_get_var_blend, /* get_var_blend */
+ (FT_Done_Blend_Func) cff_done_blend /* done_blend */
)
/*
- * METRICS VARIATIONS SERVICE
+ * METRICS VARIATIONS SERVICE
*
*/
@@ -968,7 +1001,7 @@
/*
- * CFFLOAD SERVICE
+ * CFFLOAD SERVICE
*
*/
@@ -1001,54 +1034,54 @@
cff_services,
FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_CFF,
- FT_SERVICE_ID_MULTI_MASTERS, &CFF_SERVICE_MULTI_MASTERS_GET,
- FT_SERVICE_ID_METRICS_VARIATIONS, &CFF_SERVICE_METRICS_VAR_GET,
- FT_SERVICE_ID_POSTSCRIPT_INFO, &CFF_SERVICE_PS_INFO_GET,
- FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET,
- FT_SERVICE_ID_GLYPH_DICT, &CFF_SERVICE_GLYPH_DICT_GET,
- FT_SERVICE_ID_TT_CMAP, &CFF_SERVICE_GET_CMAP_INFO_GET,
- FT_SERVICE_ID_CID, &CFF_SERVICE_CID_INFO_GET,
- FT_SERVICE_ID_PROPERTIES, &CFF_SERVICE_PROPERTIES_GET,
- FT_SERVICE_ID_CFF_LOAD, &CFF_SERVICE_CFF_LOAD_GET
+ FT_SERVICE_ID_MULTI_MASTERS, &cff_service_multi_masters,
+ FT_SERVICE_ID_METRICS_VARIATIONS, &cff_service_metrics_variations,
+ FT_SERVICE_ID_POSTSCRIPT_INFO, &cff_service_ps_info,
+ FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &cff_service_ps_name,
+ FT_SERVICE_ID_GLYPH_DICT, &cff_service_glyph_dict,
+ FT_SERVICE_ID_TT_CMAP, &cff_service_get_cmap_info,
+ FT_SERVICE_ID_CID, &cff_service_cid_info,
+ FT_SERVICE_ID_PROPERTIES, &cff_service_properties,
+ FT_SERVICE_ID_CFF_LOAD, &cff_service_cff_load
)
#elif !defined FT_CONFIG_OPTION_NO_GLYPH_NAMES
FT_DEFINE_SERVICEDESCREC8(
cff_services,
FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_CFF,
- FT_SERVICE_ID_POSTSCRIPT_INFO, &CFF_SERVICE_PS_INFO_GET,
- FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET,
- FT_SERVICE_ID_GLYPH_DICT, &CFF_SERVICE_GLYPH_DICT_GET,
- FT_SERVICE_ID_TT_CMAP, &CFF_SERVICE_GET_CMAP_INFO_GET,
- FT_SERVICE_ID_CID, &CFF_SERVICE_CID_INFO_GET,
- FT_SERVICE_ID_PROPERTIES, &CFF_SERVICE_PROPERTIES_GET,
- FT_SERVICE_ID_CFF_LOAD, &CFF_SERVICE_CFF_LOAD_GET
+ FT_SERVICE_ID_POSTSCRIPT_INFO, &cff_service_ps_info,
+ FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &cff_service_ps_name,
+ FT_SERVICE_ID_GLYPH_DICT, &cff_service_glyph_dict,
+ FT_SERVICE_ID_TT_CMAP, &cff_service_get_cmap_info,
+ FT_SERVICE_ID_CID, &cff_service_cid_info,
+ FT_SERVICE_ID_PROPERTIES, &cff_service_properties,
+ FT_SERVICE_ID_CFF_LOAD, &cff_service_cff_load
)
#elif defined TT_CONFIG_OPTION_GX_VAR_SUPPORT
FT_DEFINE_SERVICEDESCREC9(
cff_services,
FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_CFF,
- FT_SERVICE_ID_MULTI_MASTERS, &CFF_SERVICE_MULTI_MASTERS_GET,
- FT_SERVICE_ID_METRICS_VARIATIONS, &CFF_SERVICE_METRICS_VAR_GET,
- FT_SERVICE_ID_POSTSCRIPT_INFO, &CFF_SERVICE_PS_INFO_GET,
- FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET,
- FT_SERVICE_ID_TT_CMAP, &CFF_SERVICE_GET_CMAP_INFO_GET,
- FT_SERVICE_ID_CID, &CFF_SERVICE_CID_INFO_GET,
- FT_SERVICE_ID_PROPERTIES, &CFF_SERVICE_PROPERTIES_GET,
- FT_SERVICE_ID_CFF_LOAD, &CFF_SERVICE_CFF_LOAD_GET
+ FT_SERVICE_ID_MULTI_MASTERS, &cff_service_multi_masters,
+ FT_SERVICE_ID_METRICS_VARIATIONS, &cff_service_metrics_var,
+ FT_SERVICE_ID_POSTSCRIPT_INFO, &cff_service_ps_info,
+ FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &cff_service_ps_name,
+ FT_SERVICE_ID_TT_CMAP, &cff_service_get_cmap_info,
+ FT_SERVICE_ID_CID, &cff_service_cid_info,
+ FT_SERVICE_ID_PROPERTIES, &cff_service_properties,
+ FT_SERVICE_ID_CFF_LOAD, &cff_service_cff_load
)
#else
FT_DEFINE_SERVICEDESCREC7(
cff_services,
FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_CFF,
- FT_SERVICE_ID_POSTSCRIPT_INFO, &CFF_SERVICE_PS_INFO_GET,
- FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET,
- FT_SERVICE_ID_TT_CMAP, &CFF_SERVICE_GET_CMAP_INFO_GET,
- FT_SERVICE_ID_CID, &CFF_SERVICE_CID_INFO_GET,
- FT_SERVICE_ID_PROPERTIES, &CFF_SERVICE_PROPERTIES_GET,
- FT_SERVICE_ID_CFF_LOAD, &CFF_SERVICE_CFF_LOAD_GET
+ FT_SERVICE_ID_POSTSCRIPT_INFO, &cff_service_ps_info,
+ FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &cff_service_ps_name,
+ FT_SERVICE_ID_TT_CMAP, &cff_service_get_cmap_info,
+ FT_SERVICE_ID_CID, &cff_service_cid_info,
+ FT_SERVICE_ID_PROPERTIES, &cff_service_properties,
+ FT_SERVICE_ID_CFF_LOAD, &cff_service_cff_load
)
#endif
@@ -1062,27 +1095,16 @@
FT_Module_Interface result;
- /* CFF_SERVICES_GET dereferences `library' in PIC mode */
-#ifdef FT_CONFIG_OPTION_PIC
- if ( !driver )
- return NULL;
- library = driver->library;
- if ( !library )
- return NULL;
-#endif
-
- result = ft_service_list_lookup( CFF_SERVICES_GET, module_interface );
+ result = ft_service_list_lookup( cff_services, module_interface );
if ( result )
return result;
- /* `driver' is not yet evaluated in non-PIC mode */
-#ifndef FT_CONFIG_OPTION_PIC
+ /* `driver' is not yet evaluated */
if ( !driver )
return NULL;
library = driver->library;
if ( !library )
return NULL;
-#endif
/* we pass our request to the `sfnt' module */
sfnt = FT_Get_Module( library, "sfnt" );
diff --git a/thirdparty/freetype/src/cff/cffdrivr.h b/thirdparty/freetype/src/cff/cffdrivr.h
index ad7c3ad70a..f2bbcfe4f1 100644
--- a/thirdparty/freetype/src/cff/cffdrivr.h
+++ b/thirdparty/freetype/src/cff/cffdrivr.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* cffdrivr.h */
-/* */
-/* High-level OpenType driver interface (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * cffdrivr.h
+ *
+ * High-level OpenType driver interface (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef CFFDRIVER_H_
@@ -26,10 +26,8 @@
FT_BEGIN_HEADER
-
FT_DECLARE_DRIVER( cff_driver_class )
-
FT_END_HEADER
#endif /* CFFDRIVER_H_ */
diff --git a/thirdparty/freetype/src/cff/cfferrs.h b/thirdparty/freetype/src/cff/cfferrs.h
index b2e1bfaf9d..78d47a156d 100644
--- a/thirdparty/freetype/src/cff/cfferrs.h
+++ b/thirdparty/freetype/src/cff/cfferrs.h
@@ -1,26 +1,26 @@
-/***************************************************************************/
-/* */
-/* cfferrs.h */
-/* */
-/* CFF error codes (specification only). */
-/* */
-/* Copyright 2001-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* This file is used to define the CFF error enumeration constants. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * cfferrs.h
+ *
+ * CFF error codes (specification only).
+ *
+ * Copyright (C) 2001-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * This file is used to define the CFF error enumeration constants.
+ *
+ */
#ifndef CFFERRS_H_
#define CFFERRS_H_
diff --git a/thirdparty/freetype/src/cff/cffgload.c b/thirdparty/freetype/src/cff/cffgload.c
index c58471ce86..36aa7d1b9c 100644
--- a/thirdparty/freetype/src/cff/cffgload.c
+++ b/thirdparty/freetype/src/cff/cffgload.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* cffgload.c */
-/* */
-/* OpenType Glyph Loader (body). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * cffgload.c
+ *
+ * OpenType Glyph Loader (body).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -31,14 +31,14 @@
#include "cfferrs.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_cffgload
+#define FT_COMPONENT cffgload
FT_LOCAL_DEF( FT_Error )
@@ -280,16 +280,16 @@
glyph->root.outline.n_points = 0;
glyph->root.outline.n_contours = 0;
- glyph->root.metrics.width = (FT_Pos)metrics.width << 6;
- glyph->root.metrics.height = (FT_Pos)metrics.height << 6;
+ glyph->root.metrics.width = (FT_Pos)metrics.width * 64;
+ glyph->root.metrics.height = (FT_Pos)metrics.height * 64;
- glyph->root.metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;
- glyph->root.metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;
- glyph->root.metrics.horiAdvance = (FT_Pos)metrics.horiAdvance << 6;
+ glyph->root.metrics.horiBearingX = (FT_Pos)metrics.horiBearingX * 64;
+ glyph->root.metrics.horiBearingY = (FT_Pos)metrics.horiBearingY * 64;
+ glyph->root.metrics.horiAdvance = (FT_Pos)metrics.horiAdvance * 64;
- glyph->root.metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6;
- glyph->root.metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6;
- glyph->root.metrics.vertAdvance = (FT_Pos)metrics.vertAdvance << 6;
+ glyph->root.metrics.vertBearingX = (FT_Pos)metrics.vertBearingX * 64;
+ glyph->root.metrics.vertBearingY = (FT_Pos)metrics.vertBearingY * 64;
+ glyph->root.metrics.vertAdvance = (FT_Pos)metrics.vertAdvance * 64;
glyph->root.format = FT_GLYPH_FORMAT_BITMAP;
@@ -414,7 +414,7 @@
decoder.width_only = TRUE;
decoder.builder.no_recurse =
- (FT_Bool)( load_flags & FT_LOAD_NO_RECURSE );
+ FT_BOOL( load_flags & FT_LOAD_NO_RECURSE );
/* now load the unscaled outline */
error = cff_get_glyph_data( face, glyph_index,
diff --git a/thirdparty/freetype/src/cff/cffgload.h b/thirdparty/freetype/src/cff/cffgload.h
index 803f3974fc..754c55acf9 100644
--- a/thirdparty/freetype/src/cff/cffgload.h
+++ b/thirdparty/freetype/src/cff/cffgload.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* cffgload.h */
-/* */
-/* OpenType Glyph Loader (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * cffgload.h
+ *
+ * OpenType Glyph Loader (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef CFFGLOAD_H_
diff --git a/thirdparty/freetype/src/cff/cffload.c b/thirdparty/freetype/src/cff/cffload.c
index 1c6fe51566..12efd18dc4 100644
--- a/thirdparty/freetype/src/cff/cffload.c
+++ b/thirdparty/freetype/src/cff/cffload.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* cffload.c */
-/* */
-/* OpenType and CFF data/program tables loader (body). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * cffload.c
+ *
+ * OpenType and CFF data/program tables loader (body).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -196,14 +196,14 @@
}
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_cffload
+#define FT_COMPONENT cffload
/* read an offset from the index's stream current position */
@@ -1398,7 +1398,14 @@
FT_UInt master;
- FT_ASSERT( lenNDV == 0 || NDV );
+ /* protect against malformed fonts */
+ if ( !( lenNDV == 0 || NDV ) )
+ {
+ FT_TRACE4(( " cff_blend_build_vector:"
+ " Malformed Normalize Design Vector data\n" ));
+ error = FT_THROW( Invalid_File_Format );
+ goto Exit;
+ }
blend->builtBV = FALSE;
@@ -2080,13 +2087,13 @@
/*
* Initialize the random number generator.
*
- * . If we have a face-specific seed, use it.
+ * - If we have a face-specific seed, use it.
* If non-zero, update it to a positive value.
*
- * . Otherwise, use the seed from the CFF driver.
+ * - Otherwise, use the seed from the CFF driver.
* If non-zero, update it to a positive value.
*
- * . If the random value is zero, use the seed given by the subfont's
+ * - If the random value is zero, use the seed given by the subfont's
* `initialRandomSeed' value.
*
*/
diff --git a/thirdparty/freetype/src/cff/cffload.h b/thirdparty/freetype/src/cff/cffload.h
index 14d14e2112..42d2696f33 100644
--- a/thirdparty/freetype/src/cff/cffload.h
+++ b/thirdparty/freetype/src/cff/cffload.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* cffload.h */
-/* */
-/* OpenType & CFF data/program tables loader (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * cffload.h
+ *
+ * OpenType & CFF data/program tables loader (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef CFFLOAD_H_
diff --git a/thirdparty/freetype/src/cff/cffobjs.c b/thirdparty/freetype/src/cff/cffobjs.c
index a2d7aec65e..1a1030c065 100644
--- a/thirdparty/freetype/src/cff/cffobjs.c
+++ b/thirdparty/freetype/src/cff/cffobjs.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* cffobjs.c */
-/* */
-/* OpenType objects manager (body). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * cffobjs.c
+ *
+ * OpenType objects manager (body).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -37,7 +37,6 @@
#include "cffobjs.h"
#include "cffload.h"
#include "cffcmap.h"
-#include "cffpic.h"
#include "cfferrs.h"
@@ -45,21 +44,21 @@
#include FT_SERVICE_CFF_TABLE_LOAD_H
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_cffobjs
+#define FT_COMPONENT cffobjs
- /*************************************************************************/
- /* */
- /* SIZE FUNCTIONS */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * SIZE FUNCTIONS
+ *
+ */
static PSH_Globals_Funcs
@@ -341,11 +340,11 @@
}
- /*************************************************************************/
- /* */
- /* SLOT FUNCTIONS */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * SLOT FUNCTIONS
+ *
+ */
FT_LOCAL_DEF( void )
cff_slot_done( FT_GlyphSlot slot )
@@ -383,11 +382,11 @@
}
- /*************************************************************************/
- /* */
- /* FACE FUNCTIONS */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * FACE FUNCTIONS
+ *
+ */
static FT_String*
cff_strcpy( FT_Memory memory,
@@ -645,14 +644,14 @@
dict = &cff->top_font.font_dict;
- /* we need the `PSNames' module for CFF and CEF formats */
+ /* we need the `psnames' module for CFF and CEF formats */
/* which aren't CID-keyed */
if ( dict->cid_registry == 0xFFFFU && !psnames )
{
FT_ERROR(( "cff_face_init:"
" cannot open CFF & CEF fonts\n"
" "
- " without the `PSNames' module\n" ));
+ " without the `psnames' module\n" ));
error = FT_THROW( Missing_Module );
goto Exit;
}
@@ -965,10 +964,10 @@
/* assume "Regular" style if we don't know better */
cffface->style_name = cff_strcpy( memory, (char *)"Regular" );
- /*******************************************************************/
- /* */
- /* Compute face flags. */
- /* */
+ /********************************************************************
+ *
+ * Compute face flags.
+ */
flags = FT_FACE_FLAG_SCALABLE | /* scalable outlines */
FT_FACE_FLAG_HORIZONTAL | /* horizontal data */
FT_FACE_FLAG_HINTER; /* has native hinter */
@@ -989,10 +988,10 @@
cffface->face_flags |= flags;
- /*******************************************************************/
- /* */
- /* Compute style flags. */
- /* */
+ /********************************************************************
+ *
+ * Compute style flags.
+ */
flags = 0;
if ( dict->italic_angle )
@@ -1028,10 +1027,10 @@
if ( dict->cid_registry != 0xFFFFU && pure_cff )
cffface->face_flags |= FT_FACE_FLAG_CID_KEYED;
- /*******************************************************************/
- /* */
- /* Compute char maps. */
- /* */
+ /********************************************************************
+ *
+ * Compute char maps.
+ */
/* Try to synthesize a Unicode charmap if there is none available */
/* already. If an OpenType font contains a Unicode "cmap", we */
@@ -1070,10 +1069,11 @@
nn = (FT_UInt)cffface->num_charmaps;
- error = FT_CMap_New( &CFF_CMAP_UNICODE_CLASS_REC_GET, NULL,
+ error = FT_CMap_New( &cff_cmap_unicode_class_rec, NULL,
&cmaprec, NULL );
if ( error &&
- FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) )
+ FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) &&
+ FT_ERR_NEQ( error, Unimplemented_Feature ) )
goto Exit;
error = FT_Err_Ok;
@@ -1094,19 +1094,19 @@
{
cmaprec.encoding_id = TT_ADOBE_ID_STANDARD;
cmaprec.encoding = FT_ENCODING_ADOBE_STANDARD;
- clazz = &CFF_CMAP_ENCODING_CLASS_REC_GET;
+ clazz = &cff_cmap_encoding_class_rec;
}
else if ( encoding->offset == 1 )
{
cmaprec.encoding_id = TT_ADOBE_ID_EXPERT;
cmaprec.encoding = FT_ENCODING_ADOBE_EXPERT;
- clazz = &CFF_CMAP_ENCODING_CLASS_REC_GET;
+ clazz = &cff_cmap_encoding_class_rec;
}
else
{
cmaprec.encoding_id = TT_ADOBE_ID_CUSTOM;
cmaprec.encoding = FT_ENCODING_ADOBE_CUSTOM;
- clazz = &CFF_CMAP_ENCODING_CLASS_REC_GET;
+ clazz = &cff_cmap_encoding_class_rec;
}
error = FT_CMap_New( clazz, NULL, &cmaprec, NULL );
diff --git a/thirdparty/freetype/src/cff/cffobjs.h b/thirdparty/freetype/src/cff/cffobjs.h
index 616a25b3b5..03bc78a67f 100644
--- a/thirdparty/freetype/src/cff/cffobjs.h
+++ b/thirdparty/freetype/src/cff/cffobjs.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* cffobjs.h */
-/* */
-/* OpenType objects manager (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * cffobjs.h
+ *
+ * OpenType objects manager (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef CFFOBJS_H_
@@ -51,10 +51,10 @@ FT_BEGIN_HEADER
cff_slot_init( FT_GlyphSlot slot );
- /*************************************************************************/
- /* */
- /* Face functions */
- /* */
+ /**************************************************************************
+ *
+ * Face functions
+ */
FT_LOCAL( FT_Error )
cff_face_init( FT_Stream stream,
FT_Face face, /* CFF_Face */
@@ -66,10 +66,10 @@ FT_BEGIN_HEADER
cff_face_done( FT_Face face ); /* CFF_Face */
- /*************************************************************************/
- /* */
- /* Driver functions */
- /* */
+ /**************************************************************************
+ *
+ * Driver functions
+ */
FT_LOCAL( FT_Error )
cff_driver_init( FT_Module module ); /* PS_Driver */
diff --git a/thirdparty/freetype/src/cff/cffparse.c b/thirdparty/freetype/src/cff/cffparse.c
index b9611cf548..fa806f1a90 100644
--- a/thirdparty/freetype/src/cff/cffparse.c
+++ b/thirdparty/freetype/src/cff/cffparse.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* cffparse.c */
-/* */
-/* CFF token stream parser (body) */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * cffparse.c
+ *
+ * CFF token stream parser (body)
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -22,20 +22,20 @@
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_CALC_H
#include FT_INTERNAL_POSTSCRIPT_AUX_H
+#include FT_LIST_H
#include "cfferrs.h"
-#include "cffpic.h"
#include "cffload.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_cffparse
+#define FT_COMPONENT cffparse
FT_LOCAL_DEF( FT_Error )
@@ -605,7 +605,6 @@
FT_Vector* offset = &dict->font_offset;
FT_ULong* upm = &dict->units_per_em;
FT_Byte** data = parser->stack;
- FT_Error error = FT_ERR( Stack_Underflow );
if ( parser->top >= parser->stack + 6 )
@@ -617,8 +616,6 @@
int i;
- error = FT_Err_Ok;
-
dict->has_font_matrix = TRUE;
/* We expect a well-formed font matrix, this is, the matrix elements */
@@ -647,22 +644,11 @@
( max_scaling - min_scaling ) < 0 ||
( max_scaling - min_scaling ) > 9 )
{
- /* Return default matrix in case of unlikely values. */
-
FT_TRACE1(( "cff_parse_font_matrix:"
" strange scaling values (minimum %d, maximum %d),\n"
" "
" using default matrix\n", min_scaling, max_scaling ));
-
- matrix->xx = 0x10000L;
- matrix->yx = 0;
- matrix->xy = 0;
- matrix->yy = 0x10000L;
- offset->x = 0;
- offset->y = 0;
- *upm = 1;
-
- goto Exit;
+ goto Unlikely;
}
for ( i = 0; i < 6; i++ )
@@ -709,10 +695,31 @@
(double)matrix->yy / *upm / 65536,
(double)offset->x / *upm / 65536,
(double)offset->y / *upm / 65536 ));
+
+ if ( !FT_Matrix_Check( matrix ) )
+ {
+ FT_TRACE1(( "cff_parse_font_matrix:"
+ " degenerate values, using default matrix\n" ));
+ goto Unlikely;
+ }
+
+ return FT_Err_Ok;
}
+ else
+ return FT_THROW( Stack_Underflow );
- Exit:
- return error;
+ Unlikely:
+ /* Return default matrix in case of unlikely values. */
+
+ matrix->xx = 0x10000L;
+ matrix->yx = 0;
+ matrix->xy = 0;
+ matrix->yy = 0x10000L;
+ offset->x = 0;
+ offset->y = 0;
+ *upm = 1;
+
+ return FT_Err_Ok;
}
@@ -802,7 +809,7 @@
#ifdef FT_DEBUG_LEVEL_TRACE
/* beautify tracing message */
- if ( ft_trace_levels[FT_COMPONENT] < 4 )
+ if ( ft_trace_levels[FT_TRACE_COMP( FT_COMPONENT )] < 4 )
FT_TRACE1(( "Multiple Master CFFs not supported yet,"
" handling first master design only\n" ));
else
@@ -1003,9 +1010,6 @@
CFF_FIELD( code, name, id, cff_kind_bool )
-#ifndef FT_CONFIG_OPTION_PIC
-
-
#undef CFF_FIELD
#undef CFF_FIELD_DELTA
@@ -1118,182 +1122,16 @@
#endif /* FT_DEBUG_LEVEL_TRACE */
-#else /* FT_CONFIG_OPTION_PIC */
-
-
- void
- FT_Destroy_Class_cff_field_handlers( FT_Library library,
- CFF_Field_Handler* clazz )
+#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
+ static void
+ destruct_t2s_item( FT_Memory memory,
+ void* data,
+ void* user )
{
- FT_Memory memory = library->memory;
-
-
- if ( clazz )
- FT_FREE( clazz );
+ FT_UNUSED( user );
+ memory->free( memory, data );
}
-
-
- FT_Error
- FT_Create_Class_cff_field_handlers( FT_Library library,
- CFF_Field_Handler** output_class )
- {
- CFF_Field_Handler* clazz = NULL;
- FT_Error error;
- FT_Memory memory = library->memory;
-
- int i = 0;
-
-
-#undef CFF_FIELD
-#define CFF_FIELD( code, name, id, kind ) i++;
-#undef CFF_FIELD_DELTA
-#define CFF_FIELD_DELTA( code, name, max, id ) i++;
-#undef CFF_FIELD_CALLBACK
-#define CFF_FIELD_CALLBACK( code, name, id ) i++;
-#undef CFF_FIELD_BLEND
-#define CFF_FIELD_BLEND( code, id ) i++;
-
-#include "cfftoken.h"
-
- i++; /* { 0, 0, 0, 0, 0, 0, 0 } */
-
- if ( FT_ALLOC( clazz, sizeof ( CFF_Field_Handler ) * i ) )
- return error;
-
- i = 0;
-
-
-#ifndef FT_DEBUG_LEVEL_TRACE
-
-
-#undef CFF_FIELD_CALLBACK
-#define CFF_FIELD_CALLBACK( code_, name_, id_ ) \
- clazz[i].kind = cff_kind_callback; \
- clazz[i].code = code_ | CFFCODE; \
- clazz[i].offset = 0; \
- clazz[i].size = 0; \
- clazz[i].reader = cff_parse_ ## name_; \
- clazz[i].array_max = 0; \
- clazz[i].count_offset = 0; \
- i++;
-
-#undef CFF_FIELD
-#define CFF_FIELD( code_, name_, id_, kind_ ) \
- clazz[i].kind = kind_; \
- clazz[i].code = code_ | CFFCODE; \
- clazz[i].offset = FT_FIELD_OFFSET( name_ ); \
- clazz[i].size = FT_FIELD_SIZE( name_ ); \
- clazz[i].reader = 0; \
- clazz[i].array_max = 0; \
- clazz[i].count_offset = 0; \
- i++; \
-
-#undef CFF_FIELD_DELTA
-#define CFF_FIELD_DELTA( code_, name_, max_, id_ ) \
- clazz[i].kind = cff_kind_delta; \
- clazz[i].code = code_ | CFFCODE; \
- clazz[i].offset = FT_FIELD_OFFSET( name_ ); \
- clazz[i].size = FT_FIELD_SIZE_DELTA( name_ ); \
- clazz[i].reader = 0; \
- clazz[i].array_max = max_; \
- clazz[i].count_offset = FT_FIELD_OFFSET( num_ ## name_ ); \
- i++;
-
-#undef CFF_FIELD_BLEND
-#define CFF_FIELD_BLEND( code_, id_ ) \
- clazz[i].kind = cff_kind_blend; \
- clazz[i].code = code_ | CFFCODE; \
- clazz[i].offset = 0; \
- clazz[i].size = 0; \
- clazz[i].reader = cff_parse_blend; \
- clazz[i].array_max = 0; \
- clazz[i].count_offset = 0; \
- i++;
-
-#include "cfftoken.h"
-
- clazz[i].kind = 0;
- clazz[i].code = 0;
- clazz[i].offset = 0;
- clazz[i].size = 0;
- clazz[i].reader = 0;
- clazz[i].array_max = 0;
- clazz[i].count_offset = 0;
-
-
-#else /* FT_DEBUG_LEVEL_TRACE */
-
-
-#undef CFF_FIELD_CALLBACK
-#define CFF_FIELD_CALLBACK( code_, name_, id_ ) \
- clazz[i].kind = cff_kind_callback; \
- clazz[i].code = code_ | CFFCODE; \
- clazz[i].offset = 0; \
- clazz[i].size = 0; \
- clazz[i].reader = cff_parse_ ## name_; \
- clazz[i].array_max = 0; \
- clazz[i].count_offset = 0; \
- clazz[i].id = id_; \
- i++;
-
-#undef CFF_FIELD
-#define CFF_FIELD( code_, name_, id_, kind_ ) \
- clazz[i].kind = kind_; \
- clazz[i].code = code_ | CFFCODE; \
- clazz[i].offset = FT_FIELD_OFFSET( name_ ); \
- clazz[i].size = FT_FIELD_SIZE( name_ ); \
- clazz[i].reader = 0; \
- clazz[i].array_max = 0; \
- clazz[i].count_offset = 0; \
- clazz[i].id = id_; \
- i++; \
-
-#undef CFF_FIELD_DELTA
-#define CFF_FIELD_DELTA( code_, name_, max_, id_ ) \
- clazz[i].kind = cff_kind_delta; \
- clazz[i].code = code_ | CFFCODE; \
- clazz[i].offset = FT_FIELD_OFFSET( name_ ); \
- clazz[i].size = FT_FIELD_SIZE_DELTA( name_ ); \
- clazz[i].reader = 0; \
- clazz[i].array_max = max_; \
- clazz[i].count_offset = FT_FIELD_OFFSET( num_ ## name_ ); \
- clazz[i].id = id_; \
- i++;
-
-#undef CFF_FIELD_BLEND
-#define CFF_FIELD_BLEND( code_, id_ ) \
- clazz[i].kind = cff_kind_blend; \
- clazz[i].code = code_ | CFFCODE; \
- clazz[i].offset = 0; \
- clazz[i].size = 0; \
- clazz[i].reader = cff_parse_blend; \
- clazz[i].array_max = 0; \
- clazz[i].count_offset = 0; \
- clazz[i].id = id_; \
- i++;
-
-#include "cfftoken.h"
-
- clazz[i].kind = 0;
- clazz[i].code = 0;
- clazz[i].offset = 0;
- clazz[i].size = 0;
- clazz[i].reader = 0;
- clazz[i].array_max = 0;
- clazz[i].count_offset = 0;
- clazz[i].id = 0;
-
-
-#endif /* FT_DEBUG_LEVEL_TRACE */
-
-
- *output_class = clazz;
-
- return FT_Err_Ok;
- }
-
-
-#endif /* FT_CONFIG_OPTION_PIC */
+#endif /* CFF_CONFIG_OPTION_OLD_ENGINE */
FT_LOCAL_DEF( FT_Error )
@@ -1301,17 +1139,21 @@
FT_Byte* start,
FT_Byte* limit )
{
+ FT_Byte* p = start;
+ FT_Error error = FT_Err_Ok;
+
#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
PSAux_Service psaux;
-#endif
- FT_Byte* p = start;
- FT_Error error = FT_Err_Ok;
FT_Library library = parser->library;
+ FT_Memory memory = library->memory;
- FT_UNUSED( library );
+ FT_ListRec t2s;
+ FT_ZERO( &t2s );
+#endif
+
parser->top = parser->stack;
parser->start = start;
parser->limit = limit;
@@ -1321,6 +1163,7 @@
{
FT_UInt v = *p;
+
/* Opcode 31 is legacy MM T2 operator, not a number. */
/* Opcode 255 is reserved and should not appear in fonts; */
/* it is used internally for CFF2 blends. */
@@ -1369,8 +1212,9 @@
FT_Byte* charstring_base;
FT_ULong charstring_len;
- FT_Fixed* stack;
- FT_Byte* q;
+ FT_Fixed* stack;
+ FT_ListNode node;
+ FT_Byte* q;
charstring_base = ++p;
@@ -1405,17 +1249,29 @@
error = psaux->cff_decoder_funcs->parse_charstrings_old(
&decoder, charstring_base, charstring_len, 1 );
+ if ( error )
+ goto Exit;
/* Now copy the stack data in the temporary decoder object, */
/* converting it back to charstring number representations */
/* (this is ugly, I know). */
- /* */
- /* We overwrite the original top DICT charstring under the */
- /* assumption that the charstring representation of the result */
- /* of `cff_decoder_parse_charstrings' is shorter, which should */
- /* be always true. */
- q = charstring_base - 1;
+ node = (FT_ListNode)memory->alloc( memory,
+ sizeof ( FT_ListNodeRec ) );
+ if ( !node )
+ goto Out_Of_Memory_Error;
+
+ /* `5' is the conservative upper bound of required bytes per stack */
+ /* element. */
+ q = (FT_Byte*)memory->alloc( memory,
+ 5 * ( decoder.top - decoder.stack ) );
+ if ( !q )
+ goto Out_Of_Memory_Error;
+
+ node->data = q;
+
+ FT_List_Add( &t2s, node );
+
stack = decoder.stack;
while ( stack < decoder.top )
@@ -1431,7 +1287,7 @@
if ( *stack < 0 )
{
- num = (FT_ULong)-*stack;
+ num = (FT_ULong)NEG_LONG( *stack );
neg = 1;
}
else
@@ -1523,7 +1379,7 @@
}
code = code | parser->object_code;
- for ( field = CFF_FIELD_HANDLERS_GET; field->kind; field++ )
+ for ( field = cff_field_handlers; field->kind; field++ )
{
if ( field->code == (FT_Int)code )
{
@@ -1672,11 +1528,20 @@
parser->top = parser->stack;
}
p++;
- }
+ } /* while ( p < limit ) */
Exit:
+#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
+ FT_List_Finalize( &t2s, destruct_t2s_item, memory, NULL );
+#endif
return error;
+#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
+ Out_Of_Memory_Error:
+ error = FT_THROW( Out_Of_Memory );
+ goto Exit;
+#endif
+
Stack_Overflow:
error = FT_THROW( Invalid_Argument );
goto Exit;
diff --git a/thirdparty/freetype/src/cff/cffparse.h b/thirdparty/freetype/src/cff/cffparse.h
index 8a8caeca44..bac32f9449 100644
--- a/thirdparty/freetype/src/cff/cffparse.h
+++ b/thirdparty/freetype/src/cff/cffparse.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* cffparse.h */
-/* */
-/* CFF token stream parser (specification) */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * cffparse.h
+ *
+ * CFF token stream parser (specification)
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef CFFPARSE_H_
@@ -33,11 +33,11 @@ FT_BEGIN_HEADER
#define CFF_MAX_STACK_DEPTH 96
/*
- * There are plans to remove the `maxstack' operator in a forthcoming
- * revision of the CFF2 specification, increasing the (then static) stack
- * size to 513. By making the default stack size equal to the maximum
- * stack size, the operator is essentially disabled, which has the
- * desired effect in FreeType.
+ * There are plans to remove the `maxstack' operator in a forthcoming
+ * revision of the CFF2 specification, increasing the (then static) stack
+ * size to 513. By making the default stack size equal to the maximum
+ * stack size, the operator is essentially disabled, which has the
+ * desired effect in FreeType.
*/
#define CFF2_MAX_STACK 513
#define CFF2_DEFAULT_STACK 513
diff --git a/thirdparty/freetype/src/cff/cffpic.c b/thirdparty/freetype/src/cff/cffpic.c
deleted file mode 100644
index 08b74c7cf2..0000000000
--- a/thirdparty/freetype/src/cff/cffpic.c
+++ /dev/null
@@ -1,138 +0,0 @@
-/***************************************************************************/
-/* */
-/* cffpic.c */
-/* */
-/* The FreeType position independent code services for cff module. */
-/* */
-/* Copyright 2009-2018 by */
-/* Oran Agra and Mickey Gabel. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#include <ft2build.h>
-#include FT_FREETYPE_H
-#include FT_INTERNAL_OBJECTS_H
-#include "cffcmap.h"
-#include "cffpic.h"
-#include "cfferrs.h"
-
-
-#ifdef FT_CONFIG_OPTION_PIC
-
- /* forward declaration of PIC init functions from cffdrivr.c */
- FT_Error
- FT_Create_Class_cff_services( FT_Library library,
- FT_ServiceDescRec** output_class );
- void
- FT_Destroy_Class_cff_services( FT_Library library,
- FT_ServiceDescRec* clazz );
- void
- FT_Init_Class_cff_service_ps_info( FT_Library library,
- FT_Service_PsInfoRec* clazz );
- void
- FT_Init_Class_cff_service_glyph_dict( FT_Library library,
- FT_Service_GlyphDictRec* clazz );
- void
- FT_Init_Class_cff_service_ps_name( FT_Library library,
- FT_Service_PsFontNameRec* clazz );
- void
- FT_Init_Class_cff_service_get_cmap_info( FT_Library library,
- FT_Service_TTCMapsRec* clazz );
- void
- FT_Init_Class_cff_service_cid_info( FT_Library library,
- FT_Service_CIDRec* clazz );
-
- /* forward declaration of PIC init functions from cffparse.c */
- FT_Error
- FT_Create_Class_cff_field_handlers( FT_Library library,
- CFF_Field_Handler** output_class );
- void
- FT_Destroy_Class_cff_field_handlers( FT_Library library,
- CFF_Field_Handler* clazz );
-
-
- void
- cff_driver_class_pic_free( FT_Library library )
- {
- FT_PIC_Container* pic_container = &library->pic_container;
- FT_Memory memory = library->memory;
-
-
- if ( pic_container->cff )
- {
- CffModulePIC* container = (CffModulePIC*)pic_container->cff;
-
-
- if ( container->cff_services )
- FT_Destroy_Class_cff_services( library,
- container->cff_services );
- container->cff_services = NULL;
- if ( container->cff_field_handlers )
- FT_Destroy_Class_cff_field_handlers(
- library, container->cff_field_handlers );
- container->cff_field_handlers = NULL;
- FT_FREE( container );
- pic_container->cff = NULL;
- }
- }
-
-
- FT_Error
- cff_driver_class_pic_init( FT_Library library )
- {
- FT_PIC_Container* pic_container = &library->pic_container;
- FT_Error error = FT_Err_Ok;
- CffModulePIC* container = NULL;
- FT_Memory memory = library->memory;
-
-
- /* allocate pointer, clear and set global container pointer */
- if ( FT_ALLOC ( container, sizeof ( *container ) ) )
- return error;
- FT_MEM_SET( container, 0, sizeof ( *container ) );
- pic_container->cff = container;
-
- /* initialize pointer table - */
- /* this is how the module usually expects this data */
- error = FT_Create_Class_cff_services( library,
- &container->cff_services );
- if ( error )
- goto Exit;
-
- error = FT_Create_Class_cff_field_handlers(
- library, &container->cff_field_handlers );
- if ( error )
- goto Exit;
-
- FT_Init_Class_cff_service_ps_info(
- library, &container->cff_service_ps_info );
- FT_Init_Class_cff_service_glyph_dict(
- library, &container->cff_service_glyph_dict );
- FT_Init_Class_cff_service_ps_name(
- library, &container->cff_service_ps_name );
- FT_Init_Class_cff_service_get_cmap_info(
- library, &container->cff_service_get_cmap_info );
- FT_Init_Class_cff_service_cid_info(
- library, &container->cff_service_cid_info );
- FT_Init_Class_cff_cmap_encoding_class_rec(
- library, &container->cff_cmap_encoding_class_rec );
- FT_Init_Class_cff_cmap_unicode_class_rec(
- library, &container->cff_cmap_unicode_class_rec );
-
- Exit:
- if ( error )
- cff_driver_class_pic_free( library );
- return error;
- }
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
-
-/* END */
diff --git a/thirdparty/freetype/src/cff/cffpic.h b/thirdparty/freetype/src/cff/cffpic.h
deleted file mode 100644
index 8ba4203a8d..0000000000
--- a/thirdparty/freetype/src/cff/cffpic.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/***************************************************************************/
-/* */
-/* cffpic.h */
-/* */
-/* The FreeType position independent code services for cff module. */
-/* */
-/* Copyright 2009-2018 by */
-/* Oran Agra and Mickey Gabel. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#ifndef CFFPIC_H_
-#define CFFPIC_H_
-
-
-#include FT_INTERNAL_PIC_H
-
-#ifndef FT_CONFIG_OPTION_PIC
-
-#define CFF_SERVICE_PS_INFO_GET cff_service_ps_info
-#define CFF_SERVICE_GLYPH_DICT_GET cff_service_glyph_dict
-#define CFF_SERVICE_PS_NAME_GET cff_service_ps_name
-#define CFF_SERVICE_GET_CMAP_INFO_GET cff_service_get_cmap_info
-#define CFF_SERVICE_CID_INFO_GET cff_service_cid_info
-#define CFF_SERVICE_PROPERTIES_GET cff_service_properties
-#define CFF_SERVICES_GET cff_services
-#define CFF_SERVICE_MULTI_MASTERS_GET cff_service_multi_masters
-#define CFF_SERVICE_METRICS_VAR_GET cff_service_metrics_variations
-#define CFF_SERVICE_CFF_LOAD_GET cff_service_cff_load
-#define CFF_CMAP_ENCODING_CLASS_REC_GET cff_cmap_encoding_class_rec
-#define CFF_CMAP_UNICODE_CLASS_REC_GET cff_cmap_unicode_class_rec
-#define CFF_FIELD_HANDLERS_GET cff_field_handlers
-
-#else /* FT_CONFIG_OPTION_PIC */
-
-#include FT_SERVICE_GLYPH_DICT_H
-#include "cffparse.h"
-#include FT_SERVICE_POSTSCRIPT_INFO_H
-#include FT_SERVICE_POSTSCRIPT_NAME_H
-#include FT_SERVICE_TT_CMAP_H
-#include FT_SERVICE_CID_H
-#include FT_SERVICE_PROPERTIES_H
-#include FT_SERVICE_MULTIPLE_MASTERS_H
-#include FT_SERVICE_METRICS_VARIATIONS_H
-
-
-FT_BEGIN_HEADER
-
- typedef struct CffModulePIC_
- {
- FT_ServiceDescRec* cff_services;
- CFF_Field_Handler* cff_field_handlers;
- FT_Service_PsInfoRec cff_service_ps_info;
- FT_Service_GlyphDictRec cff_service_glyph_dict;
- FT_Service_PsFontNameRec cff_service_ps_name;
- FT_Service_TTCMapsRec cff_service_get_cmap_info;
- FT_Service_CIDRec cff_service_cid_info;
- FT_Service_PropertiesRec cff_service_properties;
- FT_Service_MultiMastersRec cff_service_multi_masters;
- FT_Service_MetricsVariationsRec cff_service_metrics_variations;
- FT_Service_CFFLoadRec cff_service_cff_load;
- FT_CMap_ClassRec cff_cmap_encoding_class_rec;
- FT_CMap_ClassRec cff_cmap_unicode_class_rec;
-
- } CffModulePIC;
-
-
-#define GET_PIC( lib ) \
- ( (CffModulePIC*)( (lib)->pic_container.cff ) )
-
-#define CFF_SERVICE_PS_INFO_GET \
- ( GET_PIC( library )->cff_service_ps_info )
-#define CFF_SERVICE_GLYPH_DICT_GET \
- ( GET_PIC( library )->cff_service_glyph_dict )
-#define CFF_SERVICE_PS_NAME_GET \
- ( GET_PIC( library )->cff_service_ps_name )
-#define CFF_SERVICE_GET_CMAP_INFO_GET \
- ( GET_PIC( library )->cff_service_get_cmap_info )
-#define CFF_SERVICE_CID_INFO_GET \
- ( GET_PIC( library )->cff_service_cid_info )
-#define CFF_SERVICE_PROPERTIES_GET \
- ( GET_PIC( library )->cff_service_properties )
-#define CFF_SERVICES_GET \
- ( GET_PIC( library )->cff_services )
-#define CFF_SERVICE_MULTI_MASTERS_GET \
- ( GET_PIC( library )->cff_service_multi_masters )
-#define CFF_SERVICE_METRICS_VAR_GET \
- ( GET_PIC( library )->cff_service_metrics_variations )
-#define CFF_SERVICE_CFF_LOAD_GET \
- ( GET_PIC( library )->cff_service_cff_load )
-#define CFF_CMAP_ENCODING_CLASS_REC_GET \
- ( GET_PIC( library )->cff_cmap_encoding_class_rec )
-#define CFF_CMAP_UNICODE_CLASS_REC_GET \
- ( GET_PIC( library )->cff_cmap_unicode_class_rec )
-#define CFF_FIELD_HANDLERS_GET \
- ( GET_PIC( library )->cff_field_handlers )
-
- /* see cffpic.c for the implementation */
- void
- cff_driver_class_pic_free( FT_Library library );
-
- FT_Error
- cff_driver_class_pic_init( FT_Library library );
-
-FT_END_HEADER
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
- /* */
-
-#endif /* CFFPIC_H_ */
-
-
-/* END */
diff --git a/thirdparty/freetype/src/cff/cfftoken.h b/thirdparty/freetype/src/cff/cfftoken.h
index fec1ca20bd..063a7b3be0 100644
--- a/thirdparty/freetype/src/cff/cfftoken.h
+++ b/thirdparty/freetype/src/cff/cfftoken.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* cfftoken.h */
-/* */
-/* CFF token definitions (specification only). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * cfftoken.h
+ *
+ * CFF token definitions (specification only).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#undef FT_STRUCTURE
diff --git a/thirdparty/freetype/src/cff/cfftypes.h b/thirdparty/freetype/src/cff/cfftypes.h
deleted file mode 100644
index 74f569f08b..0000000000
--- a/thirdparty/freetype/src/cff/cfftypes.h
+++ /dev/null
@@ -1,405 +0,0 @@
-/***************************************************************************/
-/* */
-/* cfftypes.h */
-/* */
-/* Basic OpenType/CFF type definitions and interface (specification */
-/* only). */
-/* */
-/* Copyright 1996-2017 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#ifndef CFFTYPES_H_
-#define CFFTYPES_H_
-
-
-#include <ft2build.h>
-#include FT_FREETYPE_H
-#include FT_TYPE1_TABLES_H
-#include FT_INTERNAL_SERVICE_H
-#include FT_SERVICE_POSTSCRIPT_CMAPS_H
-#include FT_INTERNAL_POSTSCRIPT_HINTS_H
-
-
-FT_BEGIN_HEADER
-
-
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* CFF_IndexRec */
- /* */
- /* <Description> */
- /* A structure used to model a CFF Index table. */
- /* */
- /* <Fields> */
- /* stream :: The source input stream. */
- /* */
- /* start :: The position of the first index byte in the */
- /* input stream. */
- /* */
- /* count :: The number of elements in the index. */
- /* */
- /* off_size :: The size in bytes of object offsets in index. */
- /* */
- /* data_offset :: The position of first data byte in the index's */
- /* bytes. */
- /* */
- /* data_size :: The size of the data table in this index. */
- /* */
- /* offsets :: A table of element offsets in the index. Must be */
- /* loaded explicitly. */
- /* */
- /* bytes :: If the index is loaded in memory, its bytes. */
- /* */
- typedef struct CFF_IndexRec_
- {
- FT_Stream stream;
- FT_ULong start;
- FT_UInt hdr_size;
- FT_UInt count;
- FT_Byte off_size;
- FT_ULong data_offset;
- FT_ULong data_size;
-
- FT_ULong* offsets;
- FT_Byte* bytes;
-
- } CFF_IndexRec, *CFF_Index;
-
-
- typedef struct CFF_EncodingRec_
- {
- FT_UInt format;
- FT_ULong offset;
-
- FT_UInt count;
- FT_UShort sids [256]; /* avoid dynamic allocations */
- FT_UShort codes[256];
-
- } CFF_EncodingRec, *CFF_Encoding;
-
-
- typedef struct CFF_CharsetRec_
- {
-
- FT_UInt format;
- FT_ULong offset;
-
- FT_UShort* sids;
- FT_UShort* cids; /* the inverse mapping of `sids'; only needed */
- /* for CID-keyed fonts */
- FT_UInt max_cid;
- FT_UInt num_glyphs;
-
- } CFF_CharsetRec, *CFF_Charset;
-
-
- /* cf. similar fields in file `ttgxvar.h' from the `truetype' module */
-
- typedef struct CFF_VarData_
- {
-#if 0
- FT_UInt itemCount; /* not used; always zero */
- FT_UInt shortDeltaCount; /* not used; always zero */
-#endif
-
- FT_UInt regionIdxCount; /* number of region indexes */
- FT_UInt* regionIndices; /* array of `regionIdxCount' indices; */
- /* these index `varRegionList' */
- } CFF_VarData;
-
-
- /* contribution of one axis to a region */
- typedef struct CFF_AxisCoords_
- {
- FT_Fixed startCoord;
- FT_Fixed peakCoord; /* zero peak means no effect (factor = 1) */
- FT_Fixed endCoord;
-
- } CFF_AxisCoords;
-
-
- typedef struct CFF_VarRegion_
- {
- CFF_AxisCoords* axisList; /* array of axisCount records */
-
- } CFF_VarRegion;
-
-
- typedef struct CFF_VStoreRec_
- {
- FT_UInt dataCount;
- CFF_VarData* varData; /* array of dataCount records */
- /* vsindex indexes this array */
- FT_UShort axisCount;
- FT_UInt regionCount; /* total number of regions defined */
- CFF_VarRegion* varRegionList;
-
- } CFF_VStoreRec, *CFF_VStore;
-
-
- /* forward reference */
- typedef struct CFF_FontRec_* CFF_Font;
-
-
- /* This object manages one cached blend vector. */
- /* */
- /* There is a BlendRec for Private DICT parsing in each subfont */
- /* and a BlendRec for charstrings in CF2_Font instance data. */
- /* A cached BV may be used across DICTs or Charstrings if inputs */
- /* have not changed. */
- /* */
- /* `usedBV' is reset at the start of each parse or charstring. */
- /* vsindex cannot be changed after a BV is used. */
- /* */
- /* Note: NDV is long (32/64 bit), while BV is 16.16 (FT_Int32). */
- typedef struct CFF_BlendRec_
- {
- FT_Bool builtBV; /* blendV has been built */
- FT_Bool usedBV; /* blendV has been used */
- CFF_Font font; /* top level font struct */
- FT_UInt lastVsindex; /* last vsindex used */
- FT_UInt lenNDV; /* normDV length (aka numAxes) */
- FT_Fixed* lastNDV; /* last NDV used */
- FT_UInt lenBV; /* BlendV length (aka numMasters) */
- FT_Int32* BV; /* current blendV (per DICT/glyph) */
-
- } CFF_BlendRec, *CFF_Blend;
-
-
- typedef struct CFF_FontRecDictRec_
- {
- FT_UInt version;
- FT_UInt notice;
- FT_UInt copyright;
- FT_UInt full_name;
- FT_UInt family_name;
- FT_UInt weight;
- FT_Bool is_fixed_pitch;
- FT_Fixed italic_angle;
- FT_Fixed underline_position;
- FT_Fixed underline_thickness;
- FT_Int paint_type;
- FT_Int charstring_type;
- FT_Matrix font_matrix;
- FT_Bool has_font_matrix;
- FT_ULong units_per_em; /* temporarily used as scaling value also */
- FT_Vector font_offset;
- FT_ULong unique_id;
- FT_BBox font_bbox;
- FT_Pos stroke_width;
- FT_ULong charset_offset;
- FT_ULong encoding_offset;
- FT_ULong charstrings_offset;
- FT_ULong private_offset;
- FT_ULong private_size;
- FT_Long synthetic_base;
- FT_UInt embedded_postscript;
-
- /* these should only be used for the top-level font dictionary */
- FT_UInt cid_registry;
- FT_UInt cid_ordering;
- FT_Long cid_supplement;
-
- FT_Long cid_font_version;
- FT_Long cid_font_revision;
- FT_Long cid_font_type;
- FT_ULong cid_count;
- FT_ULong cid_uid_base;
- FT_ULong cid_fd_array_offset;
- FT_ULong cid_fd_select_offset;
- FT_UInt cid_font_name;
-
- /* the next fields come from the data of the deprecated */
- /* `MultipleMaster' operator; they are needed to parse the (also */
- /* deprecated) `blend' operator in Type 2 charstrings */
- FT_UShort num_designs;
- FT_UShort num_axes;
-
- /* fields for CFF2 */
- FT_ULong vstore_offset;
- FT_UInt maxstack;
-
- } CFF_FontRecDictRec, *CFF_FontRecDict;
-
-
- /* forward reference */
- typedef struct CFF_SubFontRec_* CFF_SubFont;
-
-
- typedef struct CFF_PrivateRec_
- {
- FT_Byte num_blue_values;
- FT_Byte num_other_blues;
- FT_Byte num_family_blues;
- FT_Byte num_family_other_blues;
-
- FT_Pos blue_values[14];
- FT_Pos other_blues[10];
- FT_Pos family_blues[14];
- FT_Pos family_other_blues[10];
-
- FT_Fixed blue_scale;
- FT_Pos blue_shift;
- FT_Pos blue_fuzz;
- FT_Pos standard_width;
- FT_Pos standard_height;
-
- FT_Byte num_snap_widths;
- FT_Byte num_snap_heights;
- FT_Pos snap_widths[13];
- FT_Pos snap_heights[13];
- FT_Bool force_bold;
- FT_Fixed force_bold_threshold;
- FT_Int lenIV;
- FT_Int language_group;
- FT_Fixed expansion_factor;
- FT_Long initial_random_seed;
- FT_ULong local_subrs_offset;
- FT_Pos default_width;
- FT_Pos nominal_width;
-
- /* fields for CFF2 */
- FT_UInt vsindex;
- CFF_SubFont subfont;
-
- } CFF_PrivateRec, *CFF_Private;
-
-
- typedef struct CFF_FDSelectRec_
- {
- FT_Byte format;
- FT_UInt range_count;
-
- /* that's the table, taken from the file `as is' */
- FT_Byte* data;
- FT_UInt data_size;
-
- /* small cache for format 3 only */
- FT_UInt cache_first;
- FT_UInt cache_count;
- FT_Byte cache_fd;
-
- } CFF_FDSelectRec, *CFF_FDSelect;
-
-
- /* A SubFont packs a font dict and a private dict together. They are */
- /* needed to support CID-keyed CFF fonts. */
- typedef struct CFF_SubFontRec_
- {
- CFF_FontRecDictRec font_dict;
- CFF_PrivateRec private_dict;
-
- /* fields for CFF2 */
- CFF_BlendRec blend; /* current blend vector */
- FT_UInt lenNDV; /* current length NDV or zero */
- FT_Fixed* NDV; /* ptr to current NDV or NULL */
-
- /* `blend_stack' is a writable buffer to hold blend results. */
- /* This buffer is to the side of the normal cff parser stack; */
- /* `cff_parse_blend' and `cff_blend_doBlend' push blend results here. */
- /* The normal stack then points to these values instead of the DICT */
- /* because all other operators in Private DICT clear the stack. */
- /* `blend_stack' could be cleared at each operator other than blend. */
- /* Blended values are stored as 5-byte fixed point values. */
-
- FT_Byte* blend_stack; /* base of stack allocation */
- FT_Byte* blend_top; /* first empty slot */
- FT_UInt blend_used; /* number of bytes in use */
- FT_UInt blend_alloc; /* number of bytes allocated */
-
- CFF_IndexRec local_subrs_index;
- FT_Byte** local_subrs; /* array of pointers */
- /* into Local Subrs INDEX data */
-
- FT_UInt32 random;
-
- } CFF_SubFontRec;
-
-
-#define CFF_MAX_CID_FONTS 256
-
-
- typedef struct CFF_FontRec_
- {
- FT_Library library;
- FT_Stream stream;
- FT_Memory memory; /* TODO: take this from stream->memory? */
- FT_ULong base_offset; /* offset to start of CFF */
- FT_UInt num_faces;
- FT_UInt num_glyphs;
-
- FT_Byte version_major;
- FT_Byte version_minor;
- FT_Byte header_size;
-
- FT_UInt top_dict_length; /* cff2 only */
-
- FT_Bool cff2;
-
- CFF_IndexRec name_index;
- CFF_IndexRec top_dict_index;
- CFF_IndexRec global_subrs_index;
-
- CFF_EncodingRec encoding;
- CFF_CharsetRec charset;
-
- CFF_IndexRec charstrings_index;
- CFF_IndexRec font_dict_index;
- CFF_IndexRec private_index;
- CFF_IndexRec local_subrs_index;
-
- FT_String* font_name;
-
- /* array of pointers into Global Subrs INDEX data */
- FT_Byte** global_subrs;
-
- /* array of pointers into String INDEX data stored at string_pool */
- FT_UInt num_strings;
- FT_Byte** strings;
- FT_Byte* string_pool;
- FT_ULong string_pool_size;
-
- CFF_SubFontRec top_font;
- FT_UInt num_subfonts;
- CFF_SubFont subfonts[CFF_MAX_CID_FONTS];
-
- CFF_FDSelectRec fd_select;
-
- /* interface to PostScript hinter */
- PSHinter_Service pshinter;
-
- /* interface to Postscript Names service */
- FT_Service_PsCMaps psnames;
-
- /* since version 2.3.0 */
- PS_FontInfoRec* font_info; /* font info dictionary */
-
- /* since version 2.3.6 */
- FT_String* registry;
- FT_String* ordering;
-
- /* since version 2.4.12 */
- FT_Generic cf2_instance;
-
- /* since version 2.7.1 */
- CFF_VStoreRec vstore; /* parsed vstore structure */
-
- } CFF_FontRec;
-
-
-FT_END_HEADER
-
-#endif /* CFFTYPES_H_ */
-
-
-/* END */
diff --git a/thirdparty/freetype/src/cff/module.mk b/thirdparty/freetype/src/cff/module.mk
index 8013d5dcab..8c610959d3 100644
--- a/thirdparty/freetype/src/cff/module.mk
+++ b/thirdparty/freetype/src/cff/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2018 by
+# Copyright (C) 1996-2019 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/cff/rules.mk b/thirdparty/freetype/src/cff/rules.mk
index bce672927e..6e2dc476ef 100644
--- a/thirdparty/freetype/src/cff/rules.mk
+++ b/thirdparty/freetype/src/cff/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2018 by
+# Copyright (C) 1996-2019 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
@@ -31,8 +31,7 @@ CFF_DRV_SRC := $(CFF_DIR)/cffcmap.c \
$(CFF_DIR)/cffgload.c \
$(CFF_DIR)/cffload.c \
$(CFF_DIR)/cffobjs.c \
- $(CFF_DIR)/cffparse.c \
- $(CFF_DIR)/cffpic.c
+ $(CFF_DIR)/cffparse.c
# CFF driver headers
diff --git a/thirdparty/freetype/src/cid/ciderrs.h b/thirdparty/freetype/src/cid/ciderrs.h
index a5a86e3fc6..be80bed3be 100644
--- a/thirdparty/freetype/src/cid/ciderrs.h
+++ b/thirdparty/freetype/src/cid/ciderrs.h
@@ -1,26 +1,26 @@
-/***************************************************************************/
-/* */
-/* ciderrs.h */
-/* */
-/* CID error codes (specification only). */
-/* */
-/* Copyright 2001-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* This file is used to define the CID error enumeration constants. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * ciderrs.h
+ *
+ * CID error codes (specification only).
+ *
+ * Copyright (C) 2001-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * This file is used to define the CID error enumeration constants.
+ *
+ */
#ifndef CIDERRS_H_
#define CIDERRS_H_
diff --git a/thirdparty/freetype/src/cid/cidgload.c b/thirdparty/freetype/src/cid/cidgload.c
index d14f9a2cc9..f59f2880f0 100644
--- a/thirdparty/freetype/src/cid/cidgload.c
+++ b/thirdparty/freetype/src/cid/cidgload.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* cidgload.c */
-/* */
-/* CID-keyed Type1 Glyph Loader (body). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * cidgload.c
+ *
+ * CID-keyed Type1 Glyph Loader (body).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -31,14 +31,14 @@
#include "ciderrs.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_cidgload
+#define FT_COMPONENT cidgload
FT_CALLBACK_DEF( FT_Error )
@@ -393,8 +393,7 @@
must_finish_decoder = TRUE;
/* set up the decoder */
- decoder.builder.no_recurse = FT_BOOL(
- ( ( load_flags & FT_LOAD_NO_RECURSE ) != 0 ) );
+ decoder.builder.no_recurse = FT_BOOL( load_flags & FT_LOAD_NO_RECURSE );
error = cid_load_glyph( &decoder, glyph_index );
if ( error )
diff --git a/thirdparty/freetype/src/cid/cidgload.h b/thirdparty/freetype/src/cid/cidgload.h
index 4811852ae4..37eba7ca7b 100644
--- a/thirdparty/freetype/src/cid/cidgload.h
+++ b/thirdparty/freetype/src/cid/cidgload.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* cidgload.h */
-/* */
-/* OpenType Glyph Loader (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * cidgload.h
+ *
+ * OpenType Glyph Loader (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef CIDGLOAD_H_
diff --git a/thirdparty/freetype/src/cid/cidload.c b/thirdparty/freetype/src/cid/cidload.c
index 27cd09b3c3..fce3e37da7 100644
--- a/thirdparty/freetype/src/cid/cidload.c
+++ b/thirdparty/freetype/src/cid/cidload.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* cidload.c */
-/* */
-/* CID-keyed Type1 font loader (body). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * cidload.c
+ *
+ * CID-keyed Type1 font loader (body).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -21,20 +21,21 @@
#include FT_CONFIG_CONFIG_H
#include FT_MULTIPLE_MASTERS_H
#include FT_INTERNAL_TYPE1_TYPES_H
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
#include "cidload.h"
#include "ciderrs.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_cidload
+#define FT_COMPONENT cidload
/* read a single offset */
@@ -81,6 +82,8 @@
/* if the keyword has a dedicated callback, call it */
if ( keyword->type == T1_FIELD_TYPE_CALLBACK )
{
+ FT_TRACE4(( " %s", keyword->ident ));
+
keyword->reader( (FT_Face)face, parser );
error = parser->root.error;
goto Exit;
@@ -131,6 +134,8 @@
}
}
+ FT_TRACE4(( " %s", keyword->ident ));
+
dummy_object = object;
/* now, load the keyword data in the object's field(s) */
@@ -141,12 +146,15 @@
else
error = cid_parser_load_field( &loader->parser,
keyword, &dummy_object );
+
+ FT_TRACE4(( "\n" ));
+
Exit:
return error;
}
- FT_CALLBACK_DEF( FT_Error )
+ FT_CALLBACK_DEF( void )
cid_parse_font_matrix( CID_Face face,
CID_Parser* parser )
{
@@ -171,14 +179,25 @@
result = cid_parser_to_fixed_array( parser, 6, temp, 3 );
if ( result < 6 )
- return FT_THROW( Invalid_File_Format );
+ {
+ FT_ERROR(( "cid_parse_font_matrix: not enough matrix elements\n" ));
+ goto Exit;
+ }
+
+ FT_TRACE4(( " [%f %f %f %f %f %f]\n",
+ (double)temp[0] / 65536 / 1000,
+ (double)temp[1] / 65536 / 1000,
+ (double)temp[2] / 65536 / 1000,
+ (double)temp[3] / 65536 / 1000,
+ (double)temp[4] / 65536 / 1000,
+ (double)temp[5] / 65536 / 1000 ));
temp_scale = FT_ABS( temp[3] );
if ( temp_scale == 0 )
{
FT_ERROR(( "cid_parse_font_matrix: invalid font matrix\n" ));
- return FT_THROW( Invalid_File_Format );
+ goto Exit;
}
/* atypical case */
@@ -200,16 +219,24 @@
matrix->xy = temp[2];
matrix->yy = temp[3];
+ if ( !FT_Matrix_Check( matrix ) )
+ {
+ FT_ERROR(( "t1_parse_font_matrix: invalid font matrix\n" ));
+ parser->root.error = FT_THROW( Invalid_File_Format );
+ goto Exit;
+ }
+
/* note that the font offsets are expressed in integer font units */
offset->x = temp[4] >> 16;
offset->y = temp[5] >> 16;
}
- return FT_Err_Ok;
+ Exit:
+ return;
}
- FT_CALLBACK_DEF( FT_Error )
+ FT_CALLBACK_DEF( void )
parse_fd_array( CID_Face face,
CID_Parser* parser )
{
@@ -224,10 +251,11 @@
if ( num_dicts < 0 )
{
FT_ERROR(( "parse_fd_array: invalid number of dictionaries\n" ));
- error = FT_THROW( Invalid_File_Format );
goto Exit;
}
+ FT_TRACE4(( " %d\n", num_dicts ));
+
/*
* A single entry in the FDArray must (at least) contain the following
* structure elements.
@@ -263,27 +291,31 @@
cid->num_dicts = num_dicts;
- /* don't forget to set a few defaults */
+ /* set some default values (the same as for Type 1 fonts) */
for ( n = 0; n < cid->num_dicts; n++ )
{
CID_FaceDict dict = cid->font_dicts + n;
- /* default value for lenIV */
- dict->private_dict.lenIV = 4;
+ dict->private_dict.blue_shift = 7;
+ dict->private_dict.blue_fuzz = 1;
+ dict->private_dict.lenIV = 4;
+ dict->private_dict.expansion_factor = (FT_Fixed)( 0.06 * 0x10000L );
+ dict->private_dict.blue_scale = (FT_Fixed)(
+ 0.039625 * 0x10000L * 1000 );
}
}
Exit:
- return error;
+ return;
}
- /* by mistake, `expansion_factor' appears both in PS_PrivateRec */
+ /* By mistake, `expansion_factor' appears both in PS_PrivateRec */
/* and CID_FaceDictRec (both are public header files and can't */
- /* changed); we simply copy the value */
+ /* changed). We simply copy the value. */
- FT_CALLBACK_DEF( FT_Error )
+ FT_CALLBACK_DEF( void )
parse_expansion_factor( CID_Face face,
CID_Parser* parser )
{
@@ -296,9 +328,43 @@
dict->expansion_factor = cid_parser_to_fixed( parser, 0 );
dict->private_dict.expansion_factor = dict->expansion_factor;
+
+ FT_TRACE4(( "%d\n", dict->expansion_factor ));
+ }
+
+ return;
+ }
+
+
+ /* By mistake, `CID_FaceDictRec' doesn't contain a field for the */
+ /* `FontName' keyword. FreeType doesn't need it, but it is nice */
+ /* to catch it for producing better trace output. */
+
+ FT_CALLBACK_DEF( void )
+ parse_font_name( CID_Face face,
+ CID_Parser* parser )
+ {
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( parser->num_dict >= 0 && parser->num_dict < face->cid.num_dicts )
+ {
+ T1_TokenRec token;
+ FT_UInt len;
+
+
+ cid_parser_to_token( parser, &token );
+
+ len = (FT_UInt)( token.limit - token.start );
+ if ( len )
+ FT_TRACE4(( " %.*s\n", len, token.start ));
+ else
+ FT_TRACE4(( " <no value>\n" ));
}
+#else
+ FT_UNUSED( face );
+ FT_UNUSED( parser );
+#endif
- return FT_Err_Ok;
+ return;
}
@@ -311,6 +377,7 @@
T1_FIELD_CALLBACK( "FDArray", parse_fd_array, 0 )
T1_FIELD_CALLBACK( "FontMatrix", cid_parse_font_matrix, 0 )
T1_FIELD_CALLBACK( "ExpansionFactor", parse_expansion_factor, 0 )
+ T1_FIELD_CALLBACK( "FontName", parse_font_name, 0 )
{ 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0, 0 }
};
@@ -356,7 +423,16 @@
/* if /FDArray was found, then cid->num_dicts is > 0, and */
/* we can start increasing parser->num_dict */
if ( face->cid.num_dicts > 0 )
+ {
parser->num_dict++;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ FT_TRACE4(( " FontDict %d", parser->num_dict ));
+ if ( parser->num_dict > face->cid.num_dicts )
+ FT_TRACE4(( " (ignored)" ));
+ FT_TRACE4(( "\n" ));
+#endif
+ }
}
}
@@ -757,7 +833,7 @@
if ( cid->fd_bytes < 0 || cid->gd_bytes < 1 )
{
- FT_ERROR(( "cid_parse_dict:"
+ FT_ERROR(( "cid_face_open:"
" Invalid `FDBytes' or `GDBytes' value\n" ));
error = FT_THROW( Invalid_File_Format );
goto Exit;
@@ -766,7 +842,7 @@
/* allow at most 32bit offsets */
if ( cid->fd_bytes > 4 || cid->gd_bytes > 4 )
{
- FT_ERROR(( "cid_parse_dict:"
+ FT_ERROR(( "cid_face_open:"
" Values of `FDBytes' or `GDBytes' larger than 4\n"
" "
" are not supported\n" ));
@@ -782,17 +858,36 @@
CID_FaceDict dict = cid->font_dicts + n;
+ /* the upper limits are ad-hoc values */
+ if ( dict->private_dict.blue_shift > 1000 ||
+ dict->private_dict.blue_shift < 0 )
+ {
+ FT_TRACE2(( "cid_face_open:"
+ " setting unlikely BlueShift value %d to default (7)\n",
+ dict->private_dict.blue_shift ));
+ dict->private_dict.blue_shift = 7;
+ }
+
+ if ( dict->private_dict.blue_fuzz > 1000 ||
+ dict->private_dict.blue_fuzz < 0 )
+ {
+ FT_TRACE2(( "cid_face_open:"
+ " setting unlikely BlueFuzz value %d to default (1)\n",
+ dict->private_dict.blue_fuzz ));
+ dict->private_dict.blue_fuzz = 1;
+ }
+
if ( dict->sd_bytes < 0 ||
( dict->num_subrs && dict->sd_bytes < 1 ) )
{
- FT_ERROR(( "cid_parse_dict: Invalid `SDBytes' value\n" ));
+ FT_ERROR(( "cid_face_open: Invalid `SDBytes' value\n" ));
error = FT_THROW( Invalid_File_Format );
goto Exit;
}
if ( dict->sd_bytes > 4 )
{
- FT_ERROR(( "cid_parse_dict:"
+ FT_ERROR(( "cid_face_open:"
" Values of `SDBytes' larger than 4"
" are not supported\n" ));
error = FT_THROW( Invalid_File_Format );
@@ -801,7 +896,7 @@
if ( dict->subrmap_offset > binary_length )
{
- FT_ERROR(( "cid_parse_dict: Invalid `SubrMapOffset' value\n" ));
+ FT_ERROR(( "cid_face_open: Invalid `SubrMapOffset' value\n" ));
error = FT_THROW( Invalid_File_Format );
goto Exit;
}
@@ -812,7 +907,7 @@
dict->num_subrs > ( binary_length - dict->subrmap_offset ) /
(FT_UInt)dict->sd_bytes ) )
{
- FT_ERROR(( "cid_parse_dict: Invalid `SubrCount' value\n" ));
+ FT_ERROR(( "cid_face_open: Invalid `SubrCount' value\n" ));
error = FT_THROW( Invalid_File_Format );
goto Exit;
}
@@ -820,7 +915,7 @@
if ( cid->cidmap_offset > binary_length )
{
- FT_ERROR(( "cid_parse_dict: Invalid `CIDMapOffset' value\n" ));
+ FT_ERROR(( "cid_face_open: Invalid `CIDMapOffset' value\n" ));
error = FT_THROW( Invalid_File_Format );
goto Exit;
}
@@ -829,7 +924,7 @@
cid->cid_count >
( binary_length - cid->cidmap_offset ) / entry_len )
{
- FT_ERROR(( "cid_parse_dict: Invalid `CIDCount' value\n" ));
+ FT_ERROR(( "cid_face_open: Invalid `CIDCount' value\n" ));
error = FT_THROW( Invalid_File_Format );
goto Exit;
}
diff --git a/thirdparty/freetype/src/cid/cidload.h b/thirdparty/freetype/src/cid/cidload.h
index 3f8bd08620..fb9d46216d 100644
--- a/thirdparty/freetype/src/cid/cidload.h
+++ b/thirdparty/freetype/src/cid/cidload.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* cidload.h */
-/* */
-/* CID-keyed Type1 font loader (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * cidload.h
+ *
+ * CID-keyed Type1 font loader (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef CIDLOAD_H_
diff --git a/thirdparty/freetype/src/cid/cidobjs.c b/thirdparty/freetype/src/cid/cidobjs.c
index 77afe1c875..4e9728719b 100644
--- a/thirdparty/freetype/src/cid/cidobjs.c
+++ b/thirdparty/freetype/src/cid/cidobjs.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* cidobjs.c */
-/* */
-/* CID objects manager (body). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * cidobjs.c
+ *
+ * CID objects manager (body).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -31,21 +31,21 @@
#include "ciderrs.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_cidobjs
+#define FT_COMPONENT cidobjs
- /*************************************************************************/
- /* */
- /* SLOT FUNCTIONS */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * SLOT FUNCTIONS
+ *
+ */
FT_LOCAL_DEF( void )
cid_slot_done( FT_GlyphSlot slot )
@@ -85,11 +85,11 @@
}
- /*************************************************************************/
- /* */
- /* SIZE FUNCTIONS */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * SIZE FUNCTIONS
+ *
+ */
static PSH_Globals_Funcs
@@ -174,23 +174,24 @@
}
- /*************************************************************************/
- /* */
- /* FACE FUNCTIONS */
- /* */
- /*************************************************************************/
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* cid_face_done */
- /* */
- /* <Description> */
- /* Finalizes a given face object. */
- /* */
- /* <Input> */
- /* face :: A pointer to the face object to destroy. */
- /* */
+ /**************************************************************************
+ *
+ * FACE FUNCTIONS
+ *
+ */
+
+ /**************************************************************************
+ *
+ * @Function:
+ * cid_face_done
+ *
+ * @Description:
+ * Finalizes a given face object.
+ *
+ * @Input:
+ * face ::
+ * A pointer to the face object to destroy.
+ */
FT_LOCAL_DEF( void )
cid_face_done( FT_Face cidface ) /* CID_Face */
{
@@ -252,29 +253,34 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* cid_face_init */
- /* */
- /* <Description> */
- /* Initializes a given CID face object. */
- /* */
- /* <Input> */
- /* stream :: The source font stream. */
- /* */
- /* face_index :: The index of the font face in the resource. */
- /* */
- /* num_params :: Number of additional generic parameters. Ignored. */
- /* */
- /* params :: Additional generic parameters. Ignored. */
- /* */
- /* <InOut> */
- /* face :: The newly built face object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * cid_face_init
+ *
+ * @Description:
+ * Initializes a given CID face object.
+ *
+ * @Input:
+ * stream ::
+ * The source font stream.
+ *
+ * face_index ::
+ * The index of the font face in the resource.
+ *
+ * num_params ::
+ * Number of additional generic parameters. Ignored.
+ *
+ * params ::
+ * Additional generic parameters. Ignored.
+ *
+ * @InOut:
+ * face ::
+ * The newly built face object.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
cid_face_init( FT_Stream stream,
FT_Face cidface, /* CID_Face */
@@ -449,20 +455,21 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* cid_driver_init */
- /* */
- /* <Description> */
- /* Initializes a given CID driver object. */
- /* */
- /* <Input> */
- /* driver :: A handle to the target driver object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * cid_driver_init
+ *
+ * @Description:
+ * Initializes a given CID driver object.
+ *
+ * @Input:
+ * driver ::
+ * A handle to the target driver object.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
cid_driver_init( FT_Module module )
{
@@ -505,17 +512,18 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* cid_driver_done */
- /* */
- /* <Description> */
- /* Finalizes a given CID driver. */
- /* */
- /* <Input> */
- /* driver :: A handle to the target CID driver. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * cid_driver_done
+ *
+ * @Description:
+ * Finalizes a given CID driver.
+ *
+ * @Input:
+ * driver ::
+ * A handle to the target CID driver.
+ */
FT_LOCAL_DEF( void )
cid_driver_done( FT_Module driver )
{
diff --git a/thirdparty/freetype/src/cid/cidobjs.h b/thirdparty/freetype/src/cid/cidobjs.h
index 0221f017dd..89c9aa74ab 100644
--- a/thirdparty/freetype/src/cid/cidobjs.h
+++ b/thirdparty/freetype/src/cid/cidobjs.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* cidobjs.h */
-/* */
-/* CID objects manager (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * cidobjs.h
+ *
+ * CID objects manager (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef CIDOBJS_H_
@@ -34,60 +34,60 @@ FT_BEGIN_HEADER
typedef struct CID_Glyph_Hints_ CID_Glyph_Hints;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* CID_Driver */
- /* */
- /* <Description> */
- /* A handle to a Type 1 driver object. */
- /* */
+ /**************************************************************************
+ *
+ * @Type:
+ * CID_Driver
+ *
+ * @Description:
+ * A handle to a Type 1 driver object.
+ */
typedef struct CID_DriverRec_* CID_Driver;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* CID_Size */
- /* */
- /* <Description> */
- /* A handle to a Type 1 size object. */
- /* */
+ /**************************************************************************
+ *
+ * @Type:
+ * CID_Size
+ *
+ * @Description:
+ * A handle to a Type 1 size object.
+ */
typedef struct CID_SizeRec_* CID_Size;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* CID_GlyphSlot */
- /* */
- /* <Description> */
- /* A handle to a Type 1 glyph slot object. */
- /* */
+ /**************************************************************************
+ *
+ * @Type:
+ * CID_GlyphSlot
+ *
+ * @Description:
+ * A handle to a Type 1 glyph slot object.
+ */
typedef struct CID_GlyphSlotRec_* CID_GlyphSlot;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* CID_CharMap */
- /* */
- /* <Description> */
- /* A handle to a Type 1 character mapping object. */
- /* */
- /* <Note> */
- /* The Type 1 format doesn't use a charmap but an encoding table. */
- /* The driver is responsible for making up charmap objects */
- /* corresponding to these tables. */
- /* */
+ /**************************************************************************
+ *
+ * @Type:
+ * CID_CharMap
+ *
+ * @Description:
+ * A handle to a Type 1 character mapping object.
+ *
+ * @Note:
+ * The Type 1 format doesn't use a charmap but an encoding table.
+ * The driver is responsible for making up charmap objects
+ * corresponding to these tables.
+ */
typedef struct CID_CharMapRec_* CID_CharMap;
- /*************************************************************************/
- /* */
- /* HERE BEGINS THE TYPE 1 SPECIFIC STUFF */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * HERE BEGINS THE TYPE 1 SPECIFIC STUFF
+ *
+ */
typedef struct CID_SizeRec_
diff --git a/thirdparty/freetype/src/cid/cidparse.c b/thirdparty/freetype/src/cid/cidparse.c
index b1c7f3cb2c..1be46ec328 100644
--- a/thirdparty/freetype/src/cid/cidparse.c
+++ b/thirdparty/freetype/src/cid/cidparse.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* cidparse.c */
-/* */
-/* CID-keyed Type1 parser (body). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * cidparse.c
+ *
+ * CID-keyed Type1 parser (body).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -26,14 +26,14 @@
#include "ciderrs.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_cidparse
+#define FT_COMPONENT cidparse
/*************************************************************************/
diff --git a/thirdparty/freetype/src/cid/cidparse.h b/thirdparty/freetype/src/cid/cidparse.h
index 61602f7674..ec1f6a346d 100644
--- a/thirdparty/freetype/src/cid/cidparse.h
+++ b/thirdparty/freetype/src/cid/cidparse.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* cidparse.h */
-/* */
-/* CID-keyed Type1 parser (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * cidparse.h
+ *
+ * CID-keyed Type1 parser (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef CIDPARSE_H_
@@ -29,35 +29,43 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* CID_Parser */
- /* */
- /* <Description> */
- /* A CID_Parser is an object used to parse a Type 1 fonts very */
- /* quickly. */
- /* */
- /* <Fields> */
- /* root :: The root PS_ParserRec fields. */
- /* */
- /* stream :: The current input stream. */
- /* */
- /* postscript :: A pointer to the data to be parsed. */
- /* */
- /* postscript_len :: The length of the data to be parsed. */
- /* */
- /* data_offset :: The start position of the binary data (i.e., the */
- /* end of the data to be parsed. */
- /* */
- /* binary_length :: The length of the data after the `StartData' */
- /* command if the data format is hexadecimal. */
- /* */
- /* cid :: A structure which holds the information about */
- /* the current font. */
- /* */
- /* num_dict :: The number of font dictionaries. */
- /* */
+ /**************************************************************************
+ *
+ * @Struct:
+ * CID_Parser
+ *
+ * @Description:
+ * A CID_Parser is an object used to parse a Type 1 fonts very
+ * quickly.
+ *
+ * @Fields:
+ * root ::
+ * The root PS_ParserRec fields.
+ *
+ * stream ::
+ * The current input stream.
+ *
+ * postscript ::
+ * A pointer to the data to be parsed.
+ *
+ * postscript_len ::
+ * The length of the data to be parsed.
+ *
+ * data_offset ::
+ * The start position of the binary data (i.e., the
+ * end of the data to be parsed.
+ *
+ * binary_length ::
+ * The length of the data after the `StartData'
+ * command if the data format is hexadecimal.
+ *
+ * cid ::
+ * A structure which holds the information about
+ * the current font.
+ *
+ * num_dict ::
+ * The number of font dictionaries.
+ */
typedef struct CID_Parser_
{
PS_ParserRec root;
@@ -86,11 +94,11 @@ FT_BEGIN_HEADER
cid_parser_done( CID_Parser* parser );
- /*************************************************************************/
- /* */
- /* PARSING ROUTINES */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * PARSING ROUTINES
+ *
+ */
#define cid_parser_skip_spaces( p ) \
(p)->root.funcs.skip_spaces( &(p)->root )
diff --git a/thirdparty/freetype/src/cid/cidriver.c b/thirdparty/freetype/src/cid/cidriver.c
index d9faf353ea..4d91e87529 100644
--- a/thirdparty/freetype/src/cid/cidriver.c
+++ b/thirdparty/freetype/src/cid/cidriver.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* cidriver.c */
-/* */
-/* CID driver interface (body). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * cidriver.c
+ *
+ * CID driver interface (body).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -34,18 +34,18 @@
#include FT_INTERNAL_POSTSCRIPT_AUX_H
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_ciddriver
+#define FT_COMPONENT ciddriver
/*
- * POSTSCRIPT NAME SERVICE
+ * POSTSCRIPT NAME SERVICE
*
*/
@@ -69,7 +69,7 @@
/*
- * POSTSCRIPT INFO SERVICE
+ * POSTSCRIPT INFO SERVICE
*
*/
@@ -105,7 +105,7 @@
/*
- * CID INFO SERVICE
+ * CID INFO SERVICE
*
*/
static FT_Error
@@ -173,7 +173,7 @@
/*
- * PROPERTY SERVICE
+ * PROPERTY SERVICE
*
*/
@@ -185,7 +185,7 @@
/*
- * SERVICE LIST
+ * SERVICE LIST
*
*/
diff --git a/thirdparty/freetype/src/cid/cidriver.h b/thirdparty/freetype/src/cid/cidriver.h
index 59d9ded901..3402fd7e99 100644
--- a/thirdparty/freetype/src/cid/cidriver.h
+++ b/thirdparty/freetype/src/cid/cidriver.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* cidriver.h */
-/* */
-/* High-level CID driver interface (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * cidriver.h
+ *
+ * High-level CID driver interface (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef CIDRIVER_H_
@@ -26,15 +26,9 @@
FT_BEGIN_HEADER
-#ifdef FT_CONFIG_OPTION_PIC
-#error "this module does not support PIC yet"
-#endif
-
-
FT_CALLBACK_TABLE
const FT_Driver_ClassRec t1cid_driver_class;
-
FT_END_HEADER
#endif /* CIDRIVER_H_ */
diff --git a/thirdparty/freetype/src/cid/cidtoken.h b/thirdparty/freetype/src/cid/cidtoken.h
index b0e2dac6aa..f505c9e166 100644
--- a/thirdparty/freetype/src/cid/cidtoken.h
+++ b/thirdparty/freetype/src/cid/cidtoken.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* cidtoken.h */
-/* */
-/* CID token definitions (specification only). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * cidtoken.h
+ *
+ * CID token definitions (specification only).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#undef FT_STRUCTURE
@@ -21,17 +21,20 @@
#undef T1CODE
#define T1CODE T1_FIELD_LOCATION_CID_INFO
- T1_FIELD_KEY ( "CIDFontName", cid_font_name, 0 )
- T1_FIELD_FIXED ( "CIDFontVersion", cid_version, 0 )
- T1_FIELD_NUM ( "CIDFontType", cid_font_type, 0 )
- T1_FIELD_STRING( "Registry", registry, 0 )
- T1_FIELD_STRING( "Ordering", ordering, 0 )
- T1_FIELD_NUM ( "Supplement", supplement, 0 )
- T1_FIELD_NUM ( "UIDBase", uid_base, 0 )
- T1_FIELD_NUM ( "CIDMapOffset", cidmap_offset, 0 )
- T1_FIELD_NUM ( "FDBytes", fd_bytes, 0 )
- T1_FIELD_NUM ( "GDBytes", gd_bytes, 0 )
- T1_FIELD_NUM ( "CIDCount", cid_count, 0 )
+ T1_FIELD_KEY ( "CIDFontName", cid_font_name, 0 )
+ T1_FIELD_FIXED ( "CIDFontVersion", cid_version, 0 )
+ T1_FIELD_NUM ( "CIDFontType", cid_font_type, 0 )
+ T1_FIELD_STRING ( "Registry", registry, 0 )
+ T1_FIELD_STRING ( "Ordering", ordering, 0 )
+ T1_FIELD_NUM ( "Supplement", supplement, 0 )
+ T1_FIELD_NUM ( "UIDBase", uid_base, 0 )
+
+ T1_FIELD_NUM_TABLE( "XUID", xuid, 16, 0 )
+
+ T1_FIELD_NUM ( "CIDMapOffset", cidmap_offset, 0 )
+ T1_FIELD_NUM ( "FDBytes", fd_bytes, 0 )
+ T1_FIELD_NUM ( "GDBytes", gd_bytes, 0 )
+ T1_FIELD_NUM ( "CIDCount", cid_count, 0 )
#undef FT_STRUCTURE
diff --git a/thirdparty/freetype/src/cid/module.mk b/thirdparty/freetype/src/cid/module.mk
index 9010e339a4..875c683c72 100644
--- a/thirdparty/freetype/src/cid/module.mk
+++ b/thirdparty/freetype/src/cid/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2018 by
+# Copyright (C) 1996-2019 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/cid/rules.mk b/thirdparty/freetype/src/cid/rules.mk
index 94333bda06..2b68dd48a0 100644
--- a/thirdparty/freetype/src/cid/rules.mk
+++ b/thirdparty/freetype/src/cid/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2018 by
+# Copyright (C) 1996-2019 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/cid/type1cid.c b/thirdparty/freetype/src/cid/type1cid.c
index 61770e3f1e..d21801cec1 100644
--- a/thirdparty/freetype/src/cid/type1cid.c
+++ b/thirdparty/freetype/src/cid/type1cid.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* type1cid.c */
-/* */
-/* FreeType OpenType driver component (body only). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * type1cid.c
+ *
+ * FreeType OpenType driver component (body only).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#define FT_MAKE_OPTION_SINGLE_OBJECT
diff --git a/thirdparty/freetype/src/gxvalid/README b/thirdparty/freetype/src/gxvalid/README
index af8128e0e7..d493587842 100644
--- a/thirdparty/freetype/src/gxvalid/README
+++ b/thirdparty/freetype/src/gxvalid/README
@@ -518,7 +518,7 @@ gxvalid: TrueType GX validator
------------------------------------------------------------------------
-Copyright 2004-2018 by
+Copyright (C) 2004-2019 by
suzuki toshiya, Masatake YAMATO, Red hat K.K.,
David Turner, Robert Wilhelm, and Werner Lemberg.
diff --git a/thirdparty/freetype/src/gxvalid/gxvalid.c b/thirdparty/freetype/src/gxvalid/gxvalid.c
index d0577a247e..462e461bf2 100644
--- a/thirdparty/freetype/src/gxvalid/gxvalid.c
+++ b/thirdparty/freetype/src/gxvalid/gxvalid.c
@@ -1,20 +1,20 @@
-/***************************************************************************/
-/* */
-/* gxvalid.c */
-/* */
-/* FreeType validator for TrueTypeGX/AAT tables (body only). */
-/* */
-/* Copyright 2005-2018 by */
-/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * gxvalid.c
+ *
+ * FreeType validator for TrueTypeGX/AAT tables (body only).
+ *
+ * Copyright (C) 2005-2019 by
+ * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#define FT_MAKE_OPTION_SINGLE_OBJECT
diff --git a/thirdparty/freetype/src/gxvalid/gxvalid.h b/thirdparty/freetype/src/gxvalid/gxvalid.h
index 19f0379982..969cd0927a 100644
--- a/thirdparty/freetype/src/gxvalid/gxvalid.h
+++ b/thirdparty/freetype/src/gxvalid/gxvalid.h
@@ -1,28 +1,28 @@
-/***************************************************************************/
-/* */
-/* gxvalid.h */
-/* */
-/* TrueTypeGX/AAT table validation (specification only). */
-/* */
-/* Copyright 2005-2018 by */
-/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-/***************************************************************************/
-/* */
-/* gxvalid is derived from both gxlayout module and otvalid module. */
-/* Development of gxlayout is supported by the Information-technology */
-/* Promotion Agency(IPA), Japan. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * gxvalid.h
+ *
+ * TrueTypeGX/AAT table validation (specification only).
+ *
+ * Copyright (C) 2005-2019 by
+ * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+/****************************************************************************
+ *
+ * gxvalid is derived from both gxlayout module and otvalid module.
+ * Development of gxlayout is supported by the Information-technology
+ * Promotion Agency(IPA), Japan.
+ *
+ */
#ifndef GXVALID_H_
diff --git a/thirdparty/freetype/src/gxvalid/gxvbsln.c b/thirdparty/freetype/src/gxvalid/gxvbsln.c
index c367d38483..f22f2545fa 100644
--- a/thirdparty/freetype/src/gxvalid/gxvbsln.c
+++ b/thirdparty/freetype/src/gxvalid/gxvbsln.c
@@ -1,42 +1,42 @@
-/***************************************************************************/
-/* */
-/* gxvbsln.c */
-/* */
-/* TrueTypeGX/AAT bsln table validation (body). */
-/* */
-/* Copyright 2004-2018 by */
-/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-/***************************************************************************/
-/* */
-/* gxvalid is derived from both gxlayout module and otvalid module. */
-/* Development of gxlayout is supported by the Information-technology */
-/* Promotion Agency(IPA), Japan. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * gxvbsln.c
+ *
+ * TrueTypeGX/AAT bsln table validation (body).
+ *
+ * Copyright (C) 2004-2019 by
+ * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+/****************************************************************************
+ *
+ * gxvalid is derived from both gxlayout module and otvalid module.
+ * Development of gxlayout is supported by the Information-technology
+ * Promotion Agency(IPA), Japan.
+ *
+ */
#include "gxvalid.h"
#include "gxvcommn.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_gxvbsln
+#define FT_COMPONENT gxvbsln
/*************************************************************************/
diff --git a/thirdparty/freetype/src/gxvalid/gxvcommn.c b/thirdparty/freetype/src/gxvalid/gxvcommn.c
index b96601108b..c5cb8ebe8b 100644
--- a/thirdparty/freetype/src/gxvalid/gxvcommn.c
+++ b/thirdparty/freetype/src/gxvalid/gxvcommn.c
@@ -1,41 +1,41 @@
-/***************************************************************************/
-/* */
-/* gxvcommn.c */
-/* */
-/* TrueTypeGX/AAT common tables validation (body). */
-/* */
-/* Copyright 2004-2018 by */
-/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-/***************************************************************************/
-/* */
-/* gxvalid is derived from both gxlayout module and otvalid module. */
-/* Development of gxlayout is supported by the Information-technology */
-/* Promotion Agency(IPA), Japan. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * gxvcommn.c
+ *
+ * TrueTypeGX/AAT common tables validation (body).
+ *
+ * Copyright (C) 2004-2019 by
+ * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+/****************************************************************************
+ *
+ * gxvalid is derived from both gxlayout module and otvalid module.
+ * Development of gxlayout is supported by the Information-technology
+ * Promotion Agency(IPA), Japan.
+ *
+ */
#include "gxvcommn.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_gxvcommon
+#define FT_COMPONENT gxvcommon
/*************************************************************************/
@@ -384,8 +384,8 @@
( P += 2, gxv_lookup_value_load( P - 2, SIGNSPEC ) )
static GXV_LookupValueDesc
- gxv_lookup_value_load( FT_Bytes p,
- int signspec )
+ gxv_lookup_value_load( FT_Bytes p,
+ GXV_LookupValue_SignSpec signspec )
{
GXV_LookupValueDesc v;
diff --git a/thirdparty/freetype/src/gxvalid/gxvcommn.h b/thirdparty/freetype/src/gxvalid/gxvcommn.h
index 8e4ff9cafc..334dc9dfb3 100644
--- a/thirdparty/freetype/src/gxvalid/gxvcommn.h
+++ b/thirdparty/freetype/src/gxvalid/gxvcommn.h
@@ -1,39 +1,39 @@
-/***************************************************************************/
-/* */
-/* gxvcommn.h */
-/* */
-/* TrueTypeGX/AAT common tables validation (specification). */
-/* */
-/* Copyright 2004-2018 by */
-/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-/***************************************************************************/
-/* */
-/* gxvalid is derived from both gxlayout module and otvalid module. */
-/* Development of gxlayout is supported by the Information-technology */
-/* Promotion Agency(IPA), Japan. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * gxvcommn.h
+ *
+ * TrueTypeGX/AAT common tables validation (specification).
+ *
+ * Copyright (C) 2004-2019 by
+ * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+/****************************************************************************
+ *
+ * gxvalid is derived from both gxlayout module and otvalid module.
+ * Development of gxlayout is supported by the Information-technology
+ * Promotion Agency(IPA), Japan.
+ *
+ */
/*
* keywords in variable naming
* ---------------------------
- * table: Of type FT_Bytes, pointing to the start of this table/subtable.
- * limit: Of type FT_Bytes, pointing to the end of this table/subtable,
+ * table: Of type FT_Bytes, pointing to the start of this table/subtable.
+ * limit: Of type FT_Bytes, pointing to the end of this table/subtable,
* including padding for alignment.
- * offset: Of type FT_UInt, the number of octets from the start to target.
- * length: Of type FT_UInt, the number of octets from the start to the
- * end in this table/subtable, including padding for alignment.
+ * offset: Of type FT_UInt, the number of octets from the start to target.
+ * length: Of type FT_UInt, the number of octets from the start to the
+ * end in this table/subtable, including padding for alignment.
*
* _MIN, _MAX: Should be added to the tail of macros, as INT_MIN, etc.
*/
diff --git a/thirdparty/freetype/src/gxvalid/gxverror.h b/thirdparty/freetype/src/gxvalid/gxverror.h
index d1151258a9..da0edb35f9 100644
--- a/thirdparty/freetype/src/gxvalid/gxverror.h
+++ b/thirdparty/freetype/src/gxvalid/gxverror.h
@@ -1,36 +1,36 @@
-/***************************************************************************/
-/* */
-/* gxverror.h */
-/* */
-/* TrueTypeGX/AAT validation module error codes (specification only). */
-/* */
-/* Copyright 2004-2018 by */
-/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-/***************************************************************************/
-/* */
-/* gxvalid is derived from both gxlayout module and otvalid module. */
-/* Development of gxlayout is supported by the Information-technology */
-/* Promotion Agency(IPA), Japan. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* This file is used to define the OpenType validation module error */
- /* enumeration constants. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * gxverror.h
+ *
+ * TrueTypeGX/AAT validation module error codes (specification only).
+ *
+ * Copyright (C) 2004-2019 by
+ * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+/****************************************************************************
+ *
+ * gxvalid is derived from both gxlayout module and otvalid module.
+ * Development of gxlayout is supported by the Information-technology
+ * Promotion Agency(IPA), Japan.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * This file is used to define the OpenType validation module error
+ * enumeration constants.
+ *
+ */
#ifndef GXVERROR_H_
#define GXVERROR_H_
diff --git a/thirdparty/freetype/src/gxvalid/gxvfeat.c b/thirdparty/freetype/src/gxvalid/gxvfeat.c
index 2c805d1d11..e1a12a18ed 100644
--- a/thirdparty/freetype/src/gxvalid/gxvfeat.c
+++ b/thirdparty/freetype/src/gxvalid/gxvfeat.c
@@ -1,28 +1,28 @@
-/***************************************************************************/
-/* */
-/* gxvfeat.c */
-/* */
-/* TrueTypeGX/AAT feat table validation (body). */
-/* */
-/* Copyright 2004-2018 by */
-/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-/***************************************************************************/
-/* */
-/* gxvalid is derived from both gxlayout module and otvalid module. */
-/* Development of gxlayout is supported by the Information-technology */
-/* Promotion Agency(IPA), Japan. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * gxvfeat.c
+ *
+ * TrueTypeGX/AAT feat table validation (body).
+ *
+ * Copyright (C) 2004-2019 by
+ * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+/****************************************************************************
+ *
+ * gxvalid is derived from both gxlayout module and otvalid module.
+ * Development of gxlayout is supported by the Information-technology
+ * Promotion Agency(IPA), Japan.
+ *
+ */
#include "gxvalid.h"
@@ -30,14 +30,14 @@
#include "gxvfeat.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_gxvfeat
+#define FT_COMPONENT gxvfeat
/*************************************************************************/
diff --git a/thirdparty/freetype/src/gxvalid/gxvfeat.h b/thirdparty/freetype/src/gxvalid/gxvfeat.h
index 2d943806c1..6c9892910c 100644
--- a/thirdparty/freetype/src/gxvalid/gxvfeat.h
+++ b/thirdparty/freetype/src/gxvalid/gxvfeat.h
@@ -1,28 +1,28 @@
-/***************************************************************************/
-/* */
-/* gxvfeat.h */
-/* */
-/* TrueTypeGX/AAT feat table validation (specification). */
-/* */
-/* Copyright 2004-2018 by */
-/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-/***************************************************************************/
-/* */
-/* gxvalid is derived from both gxlayout module and otvalid module. */
-/* Development of gxlayout is supported by the Information-technology */
-/* Promotion Agency(IPA), Japan. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * gxvfeat.h
+ *
+ * TrueTypeGX/AAT feat table validation (specification).
+ *
+ * Copyright (C) 2004-2019 by
+ * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+/****************************************************************************
+ *
+ * gxvalid is derived from both gxlayout module and otvalid module.
+ * Development of gxlayout is supported by the Information-technology
+ * Promotion Agency(IPA), Japan.
+ *
+ */
#ifndef GXVFEAT_H_
diff --git a/thirdparty/freetype/src/gxvalid/gxvfgen.c b/thirdparty/freetype/src/gxvalid/gxvfgen.c
index 840c0f3524..5ecb9443c3 100644
--- a/thirdparty/freetype/src/gxvalid/gxvfgen.c
+++ b/thirdparty/freetype/src/gxvalid/gxvfgen.c
@@ -1,62 +1,62 @@
-/***************************************************************************/
-/* */
-/* gxfgen.c */
-/* */
-/* Generate feature registry data for gxv `feat' validator. */
-/* This program is derived from gxfeatreg.c in gxlayout. */
-/* */
-/* Copyright 2004-2018 by */
-/* Masatake YAMATO and Redhat K.K. */
-/* */
-/* This file may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * gxfgen.c
+ *
+ * Generate feature registry data for gxv `feat' validator.
+ * This program is derived from gxfeatreg.c in gxlayout.
+ *
+ * Copyright (C) 2004-2019 by
+ * Masatake YAMATO and Redhat K.K.
+ *
+ * This file may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
-/***************************************************************************/
-/* */
-/* gxfeatreg.c */
-/* */
-/* Database of font features pre-defined by Apple Computer, Inc. */
-/* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html */
-/* (body). */
-/* */
-/* Copyright 2003 by */
-/* Masatake YAMATO and Redhat K.K. */
-/* */
-/* This file may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * gxfeatreg.c
+ *
+ * Database of font features pre-defined by Apple Computer, Inc.
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html
+ * (body).
+ *
+ * Copyright 2003 by
+ * Masatake YAMATO and Redhat K.K.
+ *
+ * This file may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
-/***************************************************************************/
-/* */
-/* Development of gxfeatreg.c is supported by */
-/* Information-technology Promotion Agency, Japan. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * Development of gxfeatreg.c is supported by
+ * Information-technology Promotion Agency, Japan.
+ *
+ */
-/***************************************************************************/
-/* */
-/* This file is compiled as a stand-alone executable. */
-/* This file is never compiled into `libfreetype2'. */
-/* The output of this file is used in `gxvfeat.c'. */
-/* ----------------------------------------------------------------------- */
-/* Compile: gcc `pkg-config --cflags freetype2` gxvfgen.c -o gxvfgen */
-/* Run: ./gxvfgen > tmp.c */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * This file is compiled as a stand-alone executable.
+ * This file is never compiled into `libfreetype2'.
+ * The output of this file is used in `gxvfeat.c'.
+ * -----------------------------------------------------------------------
+ * Compile: gcc `pkg-config --cflags freetype2` gxvfgen.c -o gxvfgen
+ * Run: ./gxvfgen > tmp.c
+ *
+ */
- /*******************************************************************/
- /* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING */
- /*******************************************************************/
+ /********************************************************************
+ * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+ */
/*
* If you add a new setting to a feature, check the number of settings
@@ -65,9 +65,9 @@
*/
#define FEATREG_MAX_SETTING 12
- /*******************************************************************/
- /* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING */
- /*******************************************************************/
+ /********************************************************************
+ * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+ */
#include <stdio.h>
diff --git a/thirdparty/freetype/src/gxvalid/gxvjust.c b/thirdparty/freetype/src/gxvalid/gxvjust.c
index 00c4293195..a582377859 100644
--- a/thirdparty/freetype/src/gxvalid/gxvjust.c
+++ b/thirdparty/freetype/src/gxvalid/gxvjust.c
@@ -1,28 +1,28 @@
-/***************************************************************************/
-/* */
-/* gxvjust.c */
-/* */
-/* TrueTypeGX/AAT just table validation (body). */
-/* */
-/* Copyright 2005-2018 by */
-/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-/***************************************************************************/
-/* */
-/* gxvalid is derived from both gxlayout module and otvalid module. */
-/* Development of gxlayout is supported by the Information-technology */
-/* Promotion Agency(IPA), Japan. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * gxvjust.c
+ *
+ * TrueTypeGX/AAT just table validation (body).
+ *
+ * Copyright (C) 2005-2019 by
+ * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+/****************************************************************************
+ *
+ * gxvalid is derived from both gxlayout module and otvalid module.
+ * Development of gxlayout is supported by the Information-technology
+ * Promotion Agency(IPA), Japan.
+ *
+ */
#include "gxvalid.h"
@@ -31,14 +31,14 @@
#include FT_SFNT_NAMES_H
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_gxvjust
+#define FT_COMPONENT gxvjust
/*
* referred `just' table format specification:
@@ -72,6 +72,8 @@
const FT_String* msg_tag,
GXV_Validator gxvalid )
{
+ FT_UNUSED( msg_tag );
+
if ( gid < gxvalid->face->num_glyphs )
return;
diff --git a/thirdparty/freetype/src/gxvalid/gxvkern.c b/thirdparty/freetype/src/gxvalid/gxvkern.c
index 9c0efd7a4f..a7532335a5 100644
--- a/thirdparty/freetype/src/gxvalid/gxvkern.c
+++ b/thirdparty/freetype/src/gxvalid/gxvkern.c
@@ -1,28 +1,28 @@
-/***************************************************************************/
-/* */
-/* gxvkern.c */
-/* */
-/* TrueTypeGX/AAT kern table validation (body). */
-/* */
-/* Copyright 2004-2018 by */
-/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-/***************************************************************************/
-/* */
-/* gxvalid is derived from both gxlayout module and otvalid module. */
-/* Development of gxlayout is supported by the Information-technology */
-/* Promotion Agency(IPA), Japan. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * gxvkern.c
+ *
+ * TrueTypeGX/AAT kern table validation (body).
+ *
+ * Copyright (C) 2004-2019 by
+ * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+/****************************************************************************
+ *
+ * gxvalid is derived from both gxlayout module and otvalid module.
+ * Development of gxlayout is supported by the Information-technology
+ * Promotion Agency(IPA), Japan.
+ *
+ */
#include "gxvalid.h"
@@ -32,14 +32,14 @@
#include FT_SERVICE_GX_VALIDATE_H
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_gxvkern
+#define FT_COMPONENT gxvkern
/*************************************************************************/
diff --git a/thirdparty/freetype/src/gxvalid/gxvlcar.c b/thirdparty/freetype/src/gxvalid/gxvlcar.c
index 0f261a9ace..13b3de3eaa 100644
--- a/thirdparty/freetype/src/gxvalid/gxvlcar.c
+++ b/thirdparty/freetype/src/gxvalid/gxvlcar.c
@@ -1,42 +1,42 @@
-/***************************************************************************/
-/* */
-/* gxvlcar.c */
-/* */
-/* TrueTypeGX/AAT lcar table validation (body). */
-/* */
-/* Copyright 2004-2018 by */
-/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-/***************************************************************************/
-/* */
-/* gxvalid is derived from both gxlayout module and otvalid module. */
-/* Development of gxlayout is supported by the Information-technology */
-/* Promotion Agency(IPA), Japan. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * gxvlcar.c
+ *
+ * TrueTypeGX/AAT lcar table validation (body).
+ *
+ * Copyright (C) 2004-2019 by
+ * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+/****************************************************************************
+ *
+ * gxvalid is derived from both gxlayout module and otvalid module.
+ * Development of gxlayout is supported by the Information-technology
+ * Promotion Agency(IPA), Japan.
+ *
+ */
#include "gxvalid.h"
#include "gxvcommn.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_gxvlcar
+#define FT_COMPONENT gxvlcar
/*************************************************************************/
diff --git a/thirdparty/freetype/src/gxvalid/gxvmod.c b/thirdparty/freetype/src/gxvalid/gxvmod.c
index 1a3c862927..eeadeb3e1d 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmod.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmod.c
@@ -1,28 +1,28 @@
-/***************************************************************************/
-/* */
-/* gxvmod.c */
-/* */
-/* FreeType's TrueTypeGX/AAT validation module implementation (body). */
-/* */
-/* Copyright 2004-2018 by */
-/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-/***************************************************************************/
-/* */
-/* gxvalid is derived from both gxlayout module and otvalid module. */
-/* Development of gxlayout is supported by the Information-technology */
-/* Promotion Agency(IPA), Japan. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * gxvmod.c
+ *
+ * FreeType's TrueTypeGX/AAT validation module implementation (body).
+ *
+ * Copyright (C) 2004-2019 by
+ * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+/****************************************************************************
+ *
+ * gxvalid is derived from both gxlayout module and otvalid module.
+ * Development of gxlayout is supported by the Information-technology
+ * Promotion Agency(IPA), Japan.
+ *
+ */
#include <ft2build.h>
@@ -37,14 +37,14 @@
#include "gxvcommn.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_gxvmodule
+#define FT_COMPONENT gxvmodule
static FT_Error
diff --git a/thirdparty/freetype/src/gxvalid/gxvmod.h b/thirdparty/freetype/src/gxvalid/gxvmod.h
index 745c62e105..6ecd7312c9 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmod.h
+++ b/thirdparty/freetype/src/gxvalid/gxvmod.h
@@ -1,29 +1,29 @@
-/***************************************************************************/
-/* */
-/* gxvmod.h */
-/* */
-/* FreeType's TrueTypeGX/AAT validation module implementation */
-/* (specification). */
-/* */
-/* Copyright 2004-2018 by */
-/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-/***************************************************************************/
-/* */
-/* gxvalid is derived from both gxlayout module and otvalid module. */
-/* Development of gxlayout is supported by the Information-technology */
-/* Promotion Agency(IPA), Japan. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * gxvmod.h
+ *
+ * FreeType's TrueTypeGX/AAT validation module implementation
+ * (specification).
+ *
+ * Copyright (C) 2004-2019 by
+ * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+/****************************************************************************
+ *
+ * gxvalid is derived from both gxlayout module and otvalid module.
+ * Development of gxlayout is supported by the Information-technology
+ * Promotion Agency(IPA), Japan.
+ *
+ */
#ifndef GXVMOD_H_
@@ -35,10 +35,6 @@
FT_BEGIN_HEADER
-#ifdef FT_CONFIG_OPTION_PIC
-#error "this module does not support PIC yet"
-#endif
-
FT_EXPORT_VAR( const FT_Module_Class ) gxv_module_class;
diff --git a/thirdparty/freetype/src/gxvalid/gxvmort.c b/thirdparty/freetype/src/gxvalid/gxvmort.c
index b361cb2b9d..288ef6988b 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmort.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmort.c
@@ -1,42 +1,42 @@
-/***************************************************************************/
-/* */
-/* gxvmort.c */
-/* */
-/* TrueTypeGX/AAT mort table validation (body). */
-/* */
-/* Copyright 2005-2018 by */
-/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-/***************************************************************************/
-/* */
-/* gxvalid is derived from both gxlayout module and otvalid module. */
-/* Development of gxlayout is supported by the Information-technology */
-/* Promotion Agency(IPA), Japan. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * gxvmort.c
+ *
+ * TrueTypeGX/AAT mort table validation (body).
+ *
+ * Copyright (C) 2005-2019 by
+ * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+/****************************************************************************
+ *
+ * gxvalid is derived from both gxlayout module and otvalid module.
+ * Development of gxlayout is supported by the Information-technology
+ * Promotion Agency(IPA), Japan.
+ *
+ */
#include "gxvmort.h"
#include "gxvfeat.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_gxvmort
+#define FT_COMPONENT gxvmort
static void
@@ -123,6 +123,7 @@
GXV_Validator gxvalid )
{
FT_UNUSED( gxvalid );
+ FT_UNUSED( coverage );
#ifdef FT_DEBUG_LEVEL_TRACE
if ( coverage & 0x8000U )
diff --git a/thirdparty/freetype/src/gxvalid/gxvmort.h b/thirdparty/freetype/src/gxvalid/gxvmort.h
index d8030645e9..0619e24fb9 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmort.h
+++ b/thirdparty/freetype/src/gxvalid/gxvmort.h
@@ -1,28 +1,28 @@
-/***************************************************************************/
-/* */
-/* gxvmort.h */
-/* */
-/* TrueTypeGX/AAT common definition for mort table (specification). */
-/* */
-/* Copyright 2004-2018 by */
-/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-/***************************************************************************/
-/* */
-/* gxvalid is derived from both gxlayout module and otvalid module. */
-/* Development of gxlayout is supported by the Information-technology */
-/* Promotion Agency(IPA), Japan. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * gxvmort.h
+ *
+ * TrueTypeGX/AAT common definition for mort table (specification).
+ *
+ * Copyright (C) 2004-2019 by
+ * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+/****************************************************************************
+ *
+ * gxvalid is derived from both gxlayout module and otvalid module.
+ * Development of gxlayout is supported by the Information-technology
+ * Promotion Agency(IPA), Japan.
+ *
+ */
#ifndef GXVMORT_H_
diff --git a/thirdparty/freetype/src/gxvalid/gxvmort0.c b/thirdparty/freetype/src/gxvalid/gxvmort0.c
index 95cf53d5eb..2c01bf95ec 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmort0.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmort0.c
@@ -1,42 +1,42 @@
-/***************************************************************************/
-/* */
-/* gxvmort0.c */
-/* */
-/* TrueTypeGX/AAT mort table validation */
-/* body for type0 (Indic Script Rearrangement) subtable. */
-/* */
-/* Copyright 2005-2018 by */
-/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-/***************************************************************************/
-/* */
-/* gxvalid is derived from both gxlayout module and otvalid module. */
-/* Development of gxlayout is supported by the Information-technology */
-/* Promotion Agency(IPA), Japan. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * gxvmort0.c
+ *
+ * TrueTypeGX/AAT mort table validation
+ * body for type0 (Indic Script Rearrangement) subtable.
+ *
+ * Copyright (C) 2005-2019 by
+ * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+/****************************************************************************
+ *
+ * gxvalid is derived from both gxlayout module and otvalid module.
+ * Development of gxlayout is supported by the Information-technology
+ * Promotion Agency(IPA), Japan.
+ *
+ */
#include "gxvmort.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_gxvmort
+#define FT_COMPONENT gxvmort
static const char* GXV_Mort_IndicScript_Msg[] =
diff --git a/thirdparty/freetype/src/gxvalid/gxvmort1.c b/thirdparty/freetype/src/gxvalid/gxvmort1.c
index a7683a17b0..c71ba13351 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmort1.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmort1.c
@@ -1,42 +1,42 @@
-/***************************************************************************/
-/* */
-/* gxvmort1.c */
-/* */
-/* TrueTypeGX/AAT mort table validation */
-/* body for type1 (Contextual Substitution) subtable. */
-/* */
-/* Copyright 2005-2018 by */
-/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-/***************************************************************************/
-/* */
-/* gxvalid is derived from both gxlayout module and otvalid module. */
-/* Development of gxlayout is supported by the Information-technology */
-/* Promotion Agency(IPA), Japan. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * gxvmort1.c
+ *
+ * TrueTypeGX/AAT mort table validation
+ * body for type1 (Contextual Substitution) subtable.
+ *
+ * Copyright (C) 2005-2019 by
+ * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+/****************************************************************************
+ *
+ * gxvalid is derived from both gxlayout module and otvalid module.
+ * Development of gxlayout is supported by the Information-technology
+ * Promotion Agency(IPA), Japan.
+ *
+ */
#include "gxvmort.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_gxvmort
+#define FT_COMPONENT gxvmort
typedef struct GXV_mort_subtable_type1_StateOptRec_
diff --git a/thirdparty/freetype/src/gxvalid/gxvmort2.c b/thirdparty/freetype/src/gxvalid/gxvmort2.c
index c23c2775a1..889d3bd582 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmort2.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmort2.c
@@ -1,42 +1,42 @@
-/***************************************************************************/
-/* */
-/* gxvmort2.c */
-/* */
-/* TrueTypeGX/AAT mort table validation */
-/* body for type2 (Ligature Substitution) subtable. */
-/* */
-/* Copyright 2005-2018 by */
-/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-/***************************************************************************/
-/* */
-/* gxvalid is derived from both gxlayout module and otvalid module. */
-/* Development of gxlayout is supported by the Information-technology */
-/* Promotion Agency(IPA), Japan. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * gxvmort2.c
+ *
+ * TrueTypeGX/AAT mort table validation
+ * body for type2 (Ligature Substitution) subtable.
+ *
+ * Copyright (C) 2005-2019 by
+ * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+/****************************************************************************
+ *
+ * gxvalid is derived from both gxlayout module and otvalid module.
+ * Development of gxlayout is supported by the Information-technology
+ * Promotion Agency(IPA), Japan.
+ *
+ */
#include "gxvmort.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_gxvmort
+#define FT_COMPONENT gxvmort
typedef struct GXV_mort_subtable_type2_StateOptRec_
diff --git a/thirdparty/freetype/src/gxvalid/gxvmort4.c b/thirdparty/freetype/src/gxvalid/gxvmort4.c
index 9d21a5fc29..f8ce6cf789 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmort4.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmort4.c
@@ -1,42 +1,42 @@
-/***************************************************************************/
-/* */
-/* gxvmort4.c */
-/* */
-/* TrueTypeGX/AAT mort table validation */
-/* body for type4 (Non-Contextual Glyph Substitution) subtable. */
-/* */
-/* Copyright 2005-2018 by */
-/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-/***************************************************************************/
-/* */
-/* gxvalid is derived from both gxlayout module and otvalid module. */
-/* Development of gxlayout is supported by the Information-technology */
-/* Promotion Agency(IPA), Japan. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * gxvmort4.c
+ *
+ * TrueTypeGX/AAT mort table validation
+ * body for type4 (Non-Contextual Glyph Substitution) subtable.
+ *
+ * Copyright (C) 2005-2019 by
+ * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+/****************************************************************************
+ *
+ * gxvalid is derived from both gxlayout module and otvalid module.
+ * Development of gxlayout is supported by the Information-technology
+ * Promotion Agency(IPA), Japan.
+ *
+ */
#include "gxvmort.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_gxvmort
+#define FT_COMPONENT gxvmort
static void
diff --git a/thirdparty/freetype/src/gxvalid/gxvmort5.c b/thirdparty/freetype/src/gxvalid/gxvmort5.c
index 42cb428aa8..1ba1e5ded0 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmort5.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmort5.c
@@ -1,42 +1,42 @@
-/***************************************************************************/
-/* */
-/* gxvmort5.c */
-/* */
-/* TrueTypeGX/AAT mort table validation */
-/* body for type5 (Contextual Glyph Insertion) subtable. */
-/* */
-/* Copyright 2005-2018 by */
-/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-/***************************************************************************/
-/* */
-/* gxvalid is derived from both gxlayout module and otvalid module. */
-/* Development of gxlayout is supported by the Information-technology */
-/* Promotion Agency(IPA), Japan. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * gxvmort5.c
+ *
+ * TrueTypeGX/AAT mort table validation
+ * body for type5 (Contextual Glyph Insertion) subtable.
+ *
+ * Copyright (C) 2005-2019 by
+ * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+/****************************************************************************
+ *
+ * gxvalid is derived from both gxlayout module and otvalid module.
+ * Development of gxlayout is supported by the Information-technology
+ * Promotion Agency(IPA), Japan.
+ *
+ */
#include "gxvmort.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_gxvmort
+#define FT_COMPONENT gxvmort
/*
diff --git a/thirdparty/freetype/src/gxvalid/gxvmorx.c b/thirdparty/freetype/src/gxvalid/gxvmorx.c
index 9fd6e6b971..8bd45c27e6 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmorx.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmorx.c
@@ -1,41 +1,41 @@
-/***************************************************************************/
-/* */
-/* gxvmorx.c */
-/* */
-/* TrueTypeGX/AAT morx table validation (body). */
-/* */
-/* Copyright 2005-2018 by */
-/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-/***************************************************************************/
-/* */
-/* gxvalid is derived from both gxlayout module and otvalid module. */
-/* Development of gxlayout is supported by the Information-technology */
-/* Promotion Agency(IPA), Japan. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * gxvmorx.c
+ *
+ * TrueTypeGX/AAT morx table validation (body).
+ *
+ * Copyright (C) 2005-2019 by
+ * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+/****************************************************************************
+ *
+ * gxvalid is derived from both gxlayout module and otvalid module.
+ * Development of gxlayout is supported by the Information-technology
+ * Promotion Agency(IPA), Japan.
+ *
+ */
#include "gxvmorx.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_gxvmorx
+#define FT_COMPONENT gxvmorx
static void
diff --git a/thirdparty/freetype/src/gxvalid/gxvmorx.h b/thirdparty/freetype/src/gxvalid/gxvmorx.h
index 6d9925e92b..e257270342 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmorx.h
+++ b/thirdparty/freetype/src/gxvalid/gxvmorx.h
@@ -1,28 +1,28 @@
-/***************************************************************************/
-/* */
-/* gxvmorx.h */
-/* */
-/* TrueTypeGX/AAT common definition for morx table (specification). */
-/* */
-/* Copyright 2005-2018 by */
-/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-/***************************************************************************/
-/* */
-/* gxvalid is derived from both gxlayout module and otvalid module. */
-/* Development of gxlayout is supported by the Information-technology */
-/* Promotion Agency(IPA), Japan. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * gxvmorx.h
+ *
+ * TrueTypeGX/AAT common definition for morx table (specification).
+ *
+ * Copyright (C) 2005-2019 by
+ * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+/****************************************************************************
+ *
+ * gxvalid is derived from both gxlayout module and otvalid module.
+ * Development of gxlayout is supported by the Information-technology
+ * Promotion Agency(IPA), Japan.
+ *
+ */
#ifndef GXVMORX_H_
diff --git a/thirdparty/freetype/src/gxvalid/gxvmorx0.c b/thirdparty/freetype/src/gxvalid/gxvmorx0.c
index 302261b7fa..d7764a0ae8 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmorx0.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmorx0.c
@@ -1,42 +1,42 @@
-/***************************************************************************/
-/* */
-/* gxvmorx0.c */
-/* */
-/* TrueTypeGX/AAT morx table validation */
-/* body for type0 (Indic Script Rearrangement) subtable. */
-/* */
-/* Copyright 2005-2018 by */
-/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-/***************************************************************************/
-/* */
-/* gxvalid is derived from both gxlayout module and otvalid module. */
-/* Development of gxlayout is supported by the Information-technology */
-/* Promotion Agency(IPA), Japan. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * gxvmorx0.c
+ *
+ * TrueTypeGX/AAT morx table validation
+ * body for type0 (Indic Script Rearrangement) subtable.
+ *
+ * Copyright (C) 2005-2019 by
+ * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+/****************************************************************************
+ *
+ * gxvalid is derived from both gxlayout module and otvalid module.
+ * Development of gxlayout is supported by the Information-technology
+ * Promotion Agency(IPA), Japan.
+ *
+ */
#include "gxvmorx.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_gxvmorx
+#define FT_COMPONENT gxvmorx
static void
diff --git a/thirdparty/freetype/src/gxvalid/gxvmorx1.c b/thirdparty/freetype/src/gxvalid/gxvmorx1.c
index 890ca74b1d..5b41b3605f 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmorx1.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmorx1.c
@@ -1,42 +1,42 @@
-/***************************************************************************/
-/* */
-/* gxvmorx1.c */
-/* */
-/* TrueTypeGX/AAT morx table validation */
-/* body for type1 (Contextual Substitution) subtable. */
-/* */
-/* Copyright 2005-2018 by */
-/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-/***************************************************************************/
-/* */
-/* gxvalid is derived from both gxlayout module and otvalid module. */
-/* Development of gxlayout is supported by the Information-technology */
-/* Promotion Agency(IPA), Japan. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * gxvmorx1.c
+ *
+ * TrueTypeGX/AAT morx table validation
+ * body for type1 (Contextual Substitution) subtable.
+ *
+ * Copyright (C) 2005-2019 by
+ * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+/****************************************************************************
+ *
+ * gxvalid is derived from both gxlayout module and otvalid module.
+ * Development of gxlayout is supported by the Information-technology
+ * Promotion Agency(IPA), Japan.
+ *
+ */
#include "gxvmorx.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_gxvmorx
+#define FT_COMPONENT gxvmorx
typedef struct GXV_morx_subtable_type1_StateOptRec_
diff --git a/thirdparty/freetype/src/gxvalid/gxvmorx2.c b/thirdparty/freetype/src/gxvalid/gxvmorx2.c
index 3135031d45..ec4c81299d 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmorx2.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmorx2.c
@@ -1,42 +1,42 @@
-/***************************************************************************/
-/* */
-/* gxvmorx2.c */
-/* */
-/* TrueTypeGX/AAT morx table validation */
-/* body for type2 (Ligature Substitution) subtable. */
-/* */
-/* Copyright 2005-2018 by */
-/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-/***************************************************************************/
-/* */
-/* gxvalid is derived from both gxlayout module and otvalid module. */
-/* Development of gxlayout is supported by the Information-technology */
-/* Promotion Agency(IPA), Japan. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * gxvmorx2.c
+ *
+ * TrueTypeGX/AAT morx table validation
+ * body for type2 (Ligature Substitution) subtable.
+ *
+ * Copyright (C) 2005-2019 by
+ * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+/****************************************************************************
+ *
+ * gxvalid is derived from both gxlayout module and otvalid module.
+ * Development of gxlayout is supported by the Information-technology
+ * Promotion Agency(IPA), Japan.
+ *
+ */
#include "gxvmorx.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_gxvmorx
+#define FT_COMPONENT gxvmorx
typedef struct GXV_morx_subtable_type2_StateOptRec_
diff --git a/thirdparty/freetype/src/gxvalid/gxvmorx4.c b/thirdparty/freetype/src/gxvalid/gxvmorx4.c
index 1e2397b0c5..7b041534c0 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmorx4.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmorx4.c
@@ -1,42 +1,42 @@
-/***************************************************************************/
-/* */
-/* gxvmorx4.c */
-/* */
-/* TrueTypeGX/AAT morx table validation */
-/* body for "morx" type4 (Non-Contextual Glyph Substitution) subtable. */
-/* */
-/* Copyright 2005-2018 by */
-/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-/***************************************************************************/
-/* */
-/* gxvalid is derived from both gxlayout module and otvalid module. */
-/* Development of gxlayout is supported by the Information-technology */
-/* Promotion Agency(IPA), Japan. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * gxvmorx4.c
+ *
+ * TrueTypeGX/AAT morx table validation
+ * body for "morx" type4 (Non-Contextual Glyph Substitution) subtable.
+ *
+ * Copyright (C) 2005-2019 by
+ * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+/****************************************************************************
+ *
+ * gxvalid is derived from both gxlayout module and otvalid module.
+ * Development of gxlayout is supported by the Information-technology
+ * Promotion Agency(IPA), Japan.
+ *
+ */
#include "gxvmorx.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_gxvmorx
+#define FT_COMPONENT gxvmorx
FT_LOCAL_DEF( void )
diff --git a/thirdparty/freetype/src/gxvalid/gxvmorx5.c b/thirdparty/freetype/src/gxvalid/gxvmorx5.c
index db4f9290c8..70a4623656 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmorx5.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmorx5.c
@@ -1,42 +1,42 @@
-/***************************************************************************/
-/* */
-/* gxvmorx5.c */
-/* */
-/* TrueTypeGX/AAT morx table validation */
-/* body for type5 (Contextual Glyph Insertion) subtable. */
-/* */
-/* Copyright 2005-2018 by */
-/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-/***************************************************************************/
-/* */
-/* gxvalid is derived from both gxlayout module and otvalid module. */
-/* Development of gxlayout is supported by the Information-technology */
-/* Promotion Agency(IPA), Japan. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * gxvmorx5.c
+ *
+ * TrueTypeGX/AAT morx table validation
+ * body for type5 (Contextual Glyph Insertion) subtable.
+ *
+ * Copyright (C) 2005-2019 by
+ * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+/****************************************************************************
+ *
+ * gxvalid is derived from both gxlayout module and otvalid module.
+ * Development of gxlayout is supported by the Information-technology
+ * Promotion Agency(IPA), Japan.
+ *
+ */
#include "gxvmorx.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_gxvmorx
+#define FT_COMPONENT gxvmorx
/*
diff --git a/thirdparty/freetype/src/gxvalid/gxvopbd.c b/thirdparty/freetype/src/gxvalid/gxvopbd.c
index e2c167ea59..f055a22054 100644
--- a/thirdparty/freetype/src/gxvalid/gxvopbd.c
+++ b/thirdparty/freetype/src/gxvalid/gxvopbd.c
@@ -1,42 +1,42 @@
-/***************************************************************************/
-/* */
-/* gxvopbd.c */
-/* */
-/* TrueTypeGX/AAT opbd table validation (body). */
-/* */
-/* Copyright 2004-2018 by */
-/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-/***************************************************************************/
-/* */
-/* gxvalid is derived from both gxlayout module and otvalid module. */
-/* Development of gxlayout is supported by the Information-technology */
-/* Promotion Agency(IPA), Japan. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * gxvopbd.c
+ *
+ * TrueTypeGX/AAT opbd table validation (body).
+ *
+ * Copyright (C) 2004-2019 by
+ * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+/****************************************************************************
+ *
+ * gxvalid is derived from both gxlayout module and otvalid module.
+ * Development of gxlayout is supported by the Information-technology
+ * Promotion Agency(IPA), Japan.
+ *
+ */
#include "gxvalid.h"
#include "gxvcommn.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_gxvopbd
+#define FT_COMPONENT gxvopbd
/*************************************************************************/
diff --git a/thirdparty/freetype/src/gxvalid/gxvprop.c b/thirdparty/freetype/src/gxvalid/gxvprop.c
index a67b6bdd00..e1911edd48 100644
--- a/thirdparty/freetype/src/gxvalid/gxvprop.c
+++ b/thirdparty/freetype/src/gxvalid/gxvprop.c
@@ -1,42 +1,42 @@
-/***************************************************************************/
-/* */
-/* gxvprop.c */
-/* */
-/* TrueTypeGX/AAT prop table validation (body). */
-/* */
-/* Copyright 2004-2018 by */
-/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-/***************************************************************************/
-/* */
-/* gxvalid is derived from both gxlayout module and otvalid module. */
-/* Development of gxlayout is supported by the Information-technology */
-/* Promotion Agency(IPA), Japan. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * gxvprop.c
+ *
+ * TrueTypeGX/AAT prop table validation (body).
+ *
+ * Copyright (C) 2004-2019 by
+ * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+/****************************************************************************
+ *
+ * gxvalid is derived from both gxlayout module and otvalid module.
+ * Development of gxlayout is supported by the Information-technology
+ * Promotion Agency(IPA), Japan.
+ *
+ */
#include "gxvalid.h"
#include "gxvcommn.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_gxvprop
+#define FT_COMPONENT gxvprop
/*************************************************************************/
diff --git a/thirdparty/freetype/src/gxvalid/gxvtrak.c b/thirdparty/freetype/src/gxvalid/gxvtrak.c
index d501b5014b..b7794b7af4 100644
--- a/thirdparty/freetype/src/gxvalid/gxvtrak.c
+++ b/thirdparty/freetype/src/gxvalid/gxvtrak.c
@@ -1,42 +1,42 @@
-/***************************************************************************/
-/* */
-/* gxvtrak.c */
-/* */
-/* TrueTypeGX/AAT trak table validation (body). */
-/* */
-/* Copyright 2004-2018 by */
-/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-/***************************************************************************/
-/* */
-/* gxvalid is derived from both gxlayout module and otvalid module. */
-/* Development of gxlayout is supported by the Information-technology */
-/* Promotion Agency(IPA), Japan. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * gxvtrak.c
+ *
+ * TrueTypeGX/AAT trak table validation (body).
+ *
+ * Copyright (C) 2004-2019 by
+ * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+/****************************************************************************
+ *
+ * gxvalid is derived from both gxlayout module and otvalid module.
+ * Development of gxlayout is supported by the Information-technology
+ * Promotion Agency(IPA), Japan.
+ *
+ */
#include "gxvalid.h"
#include "gxvcommn.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_gxvtrak
+#define FT_COMPONENT gxvtrak
/*************************************************************************/
diff --git a/thirdparty/freetype/src/gxvalid/module.mk b/thirdparty/freetype/src/gxvalid/module.mk
index b64879dcee..04067ce617 100644
--- a/thirdparty/freetype/src/gxvalid/module.mk
+++ b/thirdparty/freetype/src/gxvalid/module.mk
@@ -2,7 +2,7 @@
# FreeType 2 gxvalid module definition
#
-# Copyright 2004-2018 by
+# Copyright (C) 2004-2019 by
# suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
diff --git a/thirdparty/freetype/src/gxvalid/rules.mk b/thirdparty/freetype/src/gxvalid/rules.mk
index 3a17c030a6..4ef463bc21 100644
--- a/thirdparty/freetype/src/gxvalid/rules.mk
+++ b/thirdparty/freetype/src/gxvalid/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 2004-2018 by
+# Copyright (C) 2004-2019 by
# suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
diff --git a/thirdparty/freetype/src/gzip/ftgzip.c b/thirdparty/freetype/src/gzip/ftgzip.c
index f8011c2dd8..a5206307f4 100644
--- a/thirdparty/freetype/src/gzip/ftgzip.c
+++ b/thirdparty/freetype/src/gzip/ftgzip.c
@@ -1,23 +1,23 @@
-/***************************************************************************/
-/* */
-/* ftgzip.c */
-/* */
-/* FreeType support for .gz compressed files. */
-/* */
-/* This optional component relies on zlib. It should mainly be used to */
-/* parse compressed PCF fonts, as found with many X11 server */
-/* distributions. */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftgzip.c
+ *
+ * FreeType support for .gz compressed files.
+ *
+ * This optional component relies on zlib. It should mainly be used to
+ * parse compressed PCF fonts, as found with many X11 server
+ * distributions.
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -41,10 +41,6 @@
#ifdef FT_CONFIG_OPTION_USE_ZLIB
-#ifdef FT_CONFIG_OPTION_PIC
-#error "gzip code does not support PIC yet"
-#endif
-
#ifdef FT_CONFIG_OPTION_SYSTEM_ZLIB
#include <zlib.h>
@@ -637,8 +633,8 @@
memory = source->memory;
/*
- * check the header right now; this prevents allocating un-necessary
- * objects when we don't need them
+ * check the header right now; this prevents allocating un-necessary
+ * objects when we don't need them
*/
error = ft_gzip_check_header( source );
if ( error )
@@ -660,12 +656,12 @@
}
/*
- * We use the following trick to try to dramatically improve the
- * performance while dealing with small files. If the original stream
- * size is less than a certain threshold, we try to load the whole font
- * file into memory. This saves us from using the 32KB buffer needed
- * to inflate the file, plus the two 4KB intermediate input/output
- * buffers used in the `FT_GZipFile' structure.
+ * We use the following trick to try to dramatically improve the
+ * performance while dealing with small files. If the original stream
+ * size is less than a certain threshold, we try to load the whole font
+ * file into memory. This saves us from using the 32KB buffer needed
+ * to inflate the file, plus the two 4KB intermediate input/output
+ * buffers used in the `FT_GZipFile' structure.
*/
{
FT_ULong zip_size = ft_gzip_get_uncompressed_size( source );
@@ -735,7 +731,7 @@
/* check for `input' delayed to `inflate' */
- if ( !memory || ! output_len || !output )
+ if ( !memory || !output_len || !output )
return FT_THROW( Invalid_Argument );
/* this function is modeled after zlib's `uncompress' function */
diff --git a/thirdparty/freetype/src/gzip/rules.mk b/thirdparty/freetype/src/gzip/rules.mk
index 1a2e48bebd..44206a1dae 100644
--- a/thirdparty/freetype/src/gzip/rules.mk
+++ b/thirdparty/freetype/src/gzip/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 2002-2018 by
+# Copyright (C) 2002-2019 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/lzw/ftlzw.c b/thirdparty/freetype/src/lzw/ftlzw.c
index cb46f93c68..9805a1e3bd 100644
--- a/thirdparty/freetype/src/lzw/ftlzw.c
+++ b/thirdparty/freetype/src/lzw/ftlzw.c
@@ -1,25 +1,25 @@
-/***************************************************************************/
-/* */
-/* ftlzw.c */
-/* */
-/* FreeType support for .Z compressed files. */
-/* */
-/* This optional component relies on NetBSD's zopen(). It should mainly */
-/* be used to parse compressed PCF fonts, as found with many X11 server */
-/* distributions. */
-/* */
-/* Copyright 2004-2018 by */
-/* Albert Chin-A-Young. */
-/* */
-/* based on code in `src/gzip/ftgzip.c' */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftlzw.c
+ *
+ * FreeType support for .Z compressed files.
+ *
+ * This optional component relies on NetBSD's zopen(). It should mainly
+ * be used to parse compressed PCF fonts, as found with many X11 server
+ * distributions.
+ *
+ * Copyright (C) 2004-2019 by
+ * Albert Chin-A-Young.
+ *
+ * based on code in `src/gzip/ftgzip.c'
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
#include FT_INTERNAL_MEMORY_H
@@ -42,10 +42,6 @@
#ifdef FT_CONFIG_OPTION_USE_LZW
-#ifdef FT_CONFIG_OPTION_PIC
-#error "lzw code does not support PIC yet"
-#endif
-
#include "ftzopen.h"
@@ -361,11 +357,11 @@
memory = source->memory;
/*
- * Check the header right now; this prevents allocation of a huge
- * LZWFile object (400 KByte of heap memory) if not necessary.
+ * Check the header right now; this prevents allocation of a huge
+ * LZWFile object (400 KByte of heap memory) if not necessary.
*
- * Did I mention that you should never use .Z compressed font
- * files?
+ * Did I mention that you should never use .Z compressed font
+ * files?
*/
error = ft_lzw_check_header( source );
if ( error )
diff --git a/thirdparty/freetype/src/lzw/ftzopen.c b/thirdparty/freetype/src/lzw/ftzopen.c
index 2b868ba9f2..67e6760f95 100644
--- a/thirdparty/freetype/src/lzw/ftzopen.c
+++ b/thirdparty/freetype/src/lzw/ftzopen.c
@@ -1,23 +1,23 @@
-/***************************************************************************/
-/* */
-/* ftzopen.c */
-/* */
-/* FreeType support for .Z compressed files. */
-/* */
-/* This optional component relies on NetBSD's zopen(). It should mainly */
-/* be used to parse compressed PCF fonts, as found with many X11 server */
-/* distributions. */
-/* */
-/* Copyright 2005-2018 by */
-/* David Turner. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftzopen.c
+ *
+ * FreeType support for .Z compressed files.
+ *
+ * This optional component relies on NetBSD's zopen(). It should mainly
+ * be used to parse compressed PCF fonts, as found with many X11 server
+ * distributions.
+ *
+ * Copyright (C) 2005-2019 by
+ * David Turner.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include "ftzopen.h"
#include FT_INTERNAL_MEMORY_H
@@ -167,11 +167,11 @@
new_size += new_size >> 2; /* don't grow too fast */
/*
- * Note that the `suffix' array is located in the same memory block
- * pointed to by `prefix'.
+ * Note that the `suffix' array is located in the same memory block
+ * pointed to by `prefix'.
*
- * I know that sizeof(FT_Byte) == 1 by definition, but it is clearer
- * to write it literally.
+ * I know that sizeof(FT_Byte) == 1 by definition, but it is clearer
+ * to write it literally.
*
*/
if ( FT_REALLOC_MULT( state->prefix, old_size, new_size,
diff --git a/thirdparty/freetype/src/lzw/ftzopen.h b/thirdparty/freetype/src/lzw/ftzopen.h
index 4fd267eb90..44fe36d6c5 100644
--- a/thirdparty/freetype/src/lzw/ftzopen.h
+++ b/thirdparty/freetype/src/lzw/ftzopen.h
@@ -1,23 +1,23 @@
-/***************************************************************************/
-/* */
-/* ftzopen.h */
-/* */
-/* FreeType support for .Z compressed files. */
-/* */
-/* This optional component relies on NetBSD's zopen(). It should mainly */
-/* be used to parse compressed PCF fonts, as found with many X11 server */
-/* distributions. */
-/* */
-/* Copyright 2005-2018 by */
-/* David Turner. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftzopen.h
+ *
+ * FreeType support for .Z compressed files.
+ *
+ * This optional component relies on NetBSD's zopen(). It should mainly
+ * be used to parse compressed PCF fonts, as found with many X11 server
+ * distributions.
+ *
+ * Copyright (C) 2005-2019 by
+ * David Turner.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTZOPEN_H_
#define FTZOPEN_H_
@@ -27,9 +27,9 @@
/*
- * This is a complete re-implementation of the LZW file reader,
- * since the old one was incredibly badly written, using
- * 400 KByte of heap memory before decompressing anything.
+ * This is a complete re-implementation of the LZW file reader,
+ * since the old one was incredibly badly written, using
+ * 400 KByte of heap memory before decompressing anything.
*
*/
@@ -58,56 +58,56 @@
/*
- * state of LZW decompressor
+ * state of LZW decompressor
*
- * small technical note
- * --------------------
+ * small technical note
+ * --------------------
*
- * We use a few tricks in this implementation that are explained here to
- * ease debugging and maintenance.
+ * We use a few tricks in this implementation that are explained here to
+ * ease debugging and maintenance.
*
- * - First of all, the `prefix' and `suffix' arrays contain the suffix
- * and prefix for codes over 256; this means that
+ * - First of all, the `prefix' and `suffix' arrays contain the suffix
+ * and prefix for codes over 256; this means that
*
- * prefix_of(code) == state->prefix[code-256]
- * suffix_of(code) == state->suffix[code-256]
+ * prefix_of(code) == state->prefix[code-256]
+ * suffix_of(code) == state->suffix[code-256]
*
- * Each prefix is a 16-bit code, and each suffix an 8-bit byte.
+ * Each prefix is a 16-bit code, and each suffix an 8-bit byte.
*
- * Both arrays are stored in a single memory block, pointed to by
- * `state->prefix'. This means that the following equality is always
- * true:
+ * Both arrays are stored in a single memory block, pointed to by
+ * `state->prefix'. This means that the following equality is always
+ * true:
*
- * state->suffix == (FT_Byte*)(state->prefix + state->prefix_size)
+ * state->suffix == (FT_Byte*)(state->prefix + state->prefix_size)
*
- * Of course, state->prefix_size is the number of prefix/suffix slots
- * in the arrays, corresponding to codes 256..255+prefix_size.
+ * Of course, state->prefix_size is the number of prefix/suffix slots
+ * in the arrays, corresponding to codes 256..255+prefix_size.
*
- * - `free_ent' is the index of the next free entry in the `prefix'
- * and `suffix' arrays. This means that the corresponding `next free
- * code' is really `256+free_ent'.
+ * - `free_ent' is the index of the next free entry in the `prefix'
+ * and `suffix' arrays. This means that the corresponding `next free
+ * code' is really `256+free_ent'.
*
- * Moreover, `max_free' is the maximum value that `free_ent' can reach.
+ * Moreover, `max_free' is the maximum value that `free_ent' can reach.
*
- * `max_free' corresponds to `(1 << max_bits) - 256'. Note that this
- * value is always <= 0xFF00, which means that both `free_ent' and
- * `max_free' can be stored in an FT_UInt variable, even on 16-bit
- * machines.
+ * `max_free' corresponds to `(1 << max_bits) - 256'. Note that this
+ * value is always <= 0xFF00, which means that both `free_ent' and
+ * `max_free' can be stored in an FT_UInt variable, even on 16-bit
+ * machines.
*
- * If `free_ent == max_free', you cannot add new codes to the
- * prefix/suffix table.
+ * If `free_ent == max_free', you cannot add new codes to the
+ * prefix/suffix table.
*
- * - `num_bits' is the current number of code bits, starting at 9 and
- * growing each time `free_ent' reaches the value of `free_bits'. The
- * latter is computed as follows
+ * - `num_bits' is the current number of code bits, starting at 9 and
+ * growing each time `free_ent' reaches the value of `free_bits'. The
+ * latter is computed as follows
*
- * if num_bits < max_bits:
- * free_bits = (1 << num_bits)-256
- * else:
- * free_bits = max_free + 1
+ * if num_bits < max_bits:
+ * free_bits = (1 << num_bits)-256
+ * else:
+ * free_bits = max_free + 1
*
- * Since the value of `max_free + 1' can never be reached by
- * `free_ent', `num_bits' cannot grow larger than `max_bits'.
+ * Since the value of `max_free + 1' can never be reached by
+ * `free_ent', `num_bits' cannot grow larger than `max_bits'.
*/
typedef struct FT_LzwStateRec_
diff --git a/thirdparty/freetype/src/lzw/rules.mk b/thirdparty/freetype/src/lzw/rules.mk
index 18933c41c2..930b32e6b1 100644
--- a/thirdparty/freetype/src/lzw/rules.mk
+++ b/thirdparty/freetype/src/lzw/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 2004-2018 by
+# Copyright (C) 2004-2019 by
# Albert Chin-A-Young.
#
# based on `src/lzw/rules.mk'
diff --git a/thirdparty/freetype/src/otvalid/module.mk b/thirdparty/freetype/src/otvalid/module.mk
index 34f3dab32f..5ea5b7b57b 100644
--- a/thirdparty/freetype/src/otvalid/module.mk
+++ b/thirdparty/freetype/src/otvalid/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright 2004-2018 by
+# Copyright (C) 2004-2019 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/otvalid/otvalid.c b/thirdparty/freetype/src/otvalid/otvalid.c
index 4423ca1012..e3964b99ae 100644
--- a/thirdparty/freetype/src/otvalid/otvalid.c
+++ b/thirdparty/freetype/src/otvalid/otvalid.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* otvalid.c */
-/* */
-/* FreeType validator for OpenType tables (body only). */
-/* */
-/* Copyright 2004-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * otvalid.c
+ *
+ * FreeType validator for OpenType tables (body only).
+ *
+ * Copyright (C) 2004-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#define FT_MAKE_OPTION_SINGLE_OBJECT
diff --git a/thirdparty/freetype/src/otvalid/otvalid.h b/thirdparty/freetype/src/otvalid/otvalid.h
index d7801abae5..5ca819f261 100644
--- a/thirdparty/freetype/src/otvalid/otvalid.h
+++ b/thirdparty/freetype/src/otvalid/otvalid.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* otvalid.h */
-/* */
-/* OpenType table validation (specification only). */
-/* */
-/* Copyright 2004-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * otvalid.h
+ *
+ * OpenType table validation (specification only).
+ *
+ * Copyright (C) 2004-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef OTVALID_H_
diff --git a/thirdparty/freetype/src/otvalid/otvbase.c b/thirdparty/freetype/src/otvalid/otvbase.c
index a01d45c707..be69d7ca31 100644
--- a/thirdparty/freetype/src/otvalid/otvbase.c
+++ b/thirdparty/freetype/src/otvalid/otvbase.c
@@ -1,33 +1,33 @@
-/***************************************************************************/
-/* */
-/* otvbase.c */
-/* */
-/* OpenType BASE table validation (body). */
-/* */
-/* Copyright 2004-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * otvbase.c
+ *
+ * OpenType BASE table validation (body).
+ *
+ * Copyright (C) 2004-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include "otvalid.h"
#include "otvcommn.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_otvbase
+#define FT_COMPONENT otvbase
static void
diff --git a/thirdparty/freetype/src/otvalid/otvcommn.c b/thirdparty/freetype/src/otvalid/otvcommn.c
index 0ccfb03c08..5ed1723506 100644
--- a/thirdparty/freetype/src/otvalid/otvcommn.c
+++ b/thirdparty/freetype/src/otvalid/otvcommn.c
@@ -1,32 +1,32 @@
-/***************************************************************************/
-/* */
-/* otvcommn.c */
-/* */
-/* OpenType common tables validation (body). */
-/* */
-/* Copyright 2004-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * otvcommn.c
+ *
+ * OpenType common tables validation (body).
+ *
+ * Copyright (C) 2004-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include "otvcommn.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_otvcommon
+#define FT_COMPONENT otvcommon
/*************************************************************************/
diff --git a/thirdparty/freetype/src/otvalid/otvcommn.h b/thirdparty/freetype/src/otvalid/otvcommn.h
index a392784cf1..bfcc5b974a 100644
--- a/thirdparty/freetype/src/otvalid/otvcommn.h
+++ b/thirdparty/freetype/src/otvalid/otvcommn.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* otvcommn.h */
-/* */
-/* OpenType common tables validation (specification). */
-/* */
-/* Copyright 2004-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * otvcommn.h
+ *
+ * OpenType common tables validation (specification).
+ *
+ * Copyright (C) 2004-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef OTVCOMMN_H_
diff --git a/thirdparty/freetype/src/otvalid/otverror.h b/thirdparty/freetype/src/otvalid/otverror.h
index 2fcf42e387..a7d35acf1a 100644
--- a/thirdparty/freetype/src/otvalid/otverror.h
+++ b/thirdparty/freetype/src/otvalid/otverror.h
@@ -1,27 +1,27 @@
-/***************************************************************************/
-/* */
-/* otverror.h */
-/* */
-/* OpenType validation module error codes (specification only). */
-/* */
-/* Copyright 2004-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* This file is used to define the OpenType validation module error */
- /* enumeration constants. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * otverror.h
+ *
+ * OpenType validation module error codes (specification only).
+ *
+ * Copyright (C) 2004-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * This file is used to define the OpenType validation module error
+ * enumeration constants.
+ *
+ */
#ifndef OTVERROR_H_
#define OTVERROR_H_
diff --git a/thirdparty/freetype/src/otvalid/otvgdef.c b/thirdparty/freetype/src/otvalid/otvgdef.c
index 08f3171541..2529b544d2 100644
--- a/thirdparty/freetype/src/otvalid/otvgdef.c
+++ b/thirdparty/freetype/src/otvalid/otvgdef.c
@@ -1,33 +1,33 @@
-/***************************************************************************/
-/* */
-/* otvgdef.c */
-/* */
-/* OpenType GDEF table validation (body). */
-/* */
-/* Copyright 2004-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * otvgdef.c
+ *
+ * OpenType GDEF table validation (body).
+ *
+ * Copyright (C) 2004-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include "otvalid.h"
#include "otvcommn.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_otvgdef
+#define FT_COMPONENT otvgdef
/*************************************************************************/
diff --git a/thirdparty/freetype/src/otvalid/otvgpos.c b/thirdparty/freetype/src/otvalid/otvgpos.c
index 696b35cae6..f3bddeac6c 100644
--- a/thirdparty/freetype/src/otvalid/otvgpos.c
+++ b/thirdparty/freetype/src/otvalid/otvgpos.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* otvgpos.c */
-/* */
-/* OpenType GPOS table validation (body). */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * otvgpos.c
+ *
+ * OpenType GPOS table validation (body).
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include "otvalid.h"
@@ -21,14 +21,14 @@
#include "otvgpos.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_otvgpos
+#define FT_COMPONENT otvgpos
static void
diff --git a/thirdparty/freetype/src/otvalid/otvgpos.h b/thirdparty/freetype/src/otvalid/otvgpos.h
index 95f9ac3ee8..b3154312eb 100644
--- a/thirdparty/freetype/src/otvalid/otvgpos.h
+++ b/thirdparty/freetype/src/otvalid/otvgpos.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* otvgpos.h */
-/* */
-/* OpenType GPOS table validator (specification). */
-/* */
-/* Copyright 2004-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * otvgpos.h
+ *
+ * OpenType GPOS table validator (specification).
+ *
+ * Copyright (C) 2004-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef OTVGPOS_H_
diff --git a/thirdparty/freetype/src/otvalid/otvgsub.c b/thirdparty/freetype/src/otvalid/otvgsub.c
index d35ea67f30..97da997d3d 100644
--- a/thirdparty/freetype/src/otvalid/otvgsub.c
+++ b/thirdparty/freetype/src/otvalid/otvgsub.c
@@ -1,33 +1,33 @@
-/***************************************************************************/
-/* */
-/* otvgsub.c */
-/* */
-/* OpenType GSUB table validation (body). */
-/* */
-/* Copyright 2004-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * otvgsub.c
+ *
+ * OpenType GSUB table validation (body).
+ *
+ * Copyright (C) 2004-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include "otvalid.h"
#include "otvcommn.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_otvgsub
+#define FT_COMPONENT otvgsub
/*************************************************************************/
diff --git a/thirdparty/freetype/src/otvalid/otvjstf.c b/thirdparty/freetype/src/otvalid/otvjstf.c
index 94d4af90f6..d4e6d87178 100644
--- a/thirdparty/freetype/src/otvalid/otvjstf.c
+++ b/thirdparty/freetype/src/otvalid/otvjstf.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* otvjstf.c */
-/* */
-/* OpenType JSTF table validation (body). */
-/* */
-/* Copyright 2004-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * otvjstf.c
+ *
+ * OpenType JSTF table validation (body).
+ *
+ * Copyright (C) 2004-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include "otvalid.h"
@@ -21,14 +21,14 @@
#include "otvgpos.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_otvjstf
+#define FT_COMPONENT otvjstf
#define JstfPriorityFunc otv_JstfPriority_validate
diff --git a/thirdparty/freetype/src/otvalid/otvmath.c b/thirdparty/freetype/src/otvalid/otvmath.c
index b9800f60a2..3aaf0ec0ec 100644
--- a/thirdparty/freetype/src/otvalid/otvmath.c
+++ b/thirdparty/freetype/src/otvalid/otvmath.c
@@ -1,21 +1,21 @@
-/***************************************************************************/
-/* */
-/* otvmath.c */
-/* */
-/* OpenType MATH table validation (body). */
-/* */
-/* Copyright 2007-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* Written by George Williams. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * otvmath.c
+ *
+ * OpenType MATH table validation (body).
+ *
+ * Copyright (C) 2007-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Written by George Williams.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include "otvalid.h"
@@ -23,14 +23,14 @@
#include "otvgpos.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_otvmath
+#define FT_COMPONENT otvmath
diff --git a/thirdparty/freetype/src/otvalid/otvmod.c b/thirdparty/freetype/src/otvalid/otvmod.c
index 89ee449d16..f417bd220f 100644
--- a/thirdparty/freetype/src/otvalid/otvmod.c
+++ b/thirdparty/freetype/src/otvalid/otvmod.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* otvmod.c */
-/* */
-/* FreeType's OpenType validation module implementation (body). */
-/* */
-/* Copyright 2004-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * otvmod.c
+ *
+ * FreeType's OpenType validation module implementation (body).
+ *
+ * Copyright (C) 2004-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -28,14 +28,14 @@
#include "otvcommn.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_otvmodule
+#define FT_COMPONENT otvmodule
static FT_Error
diff --git a/thirdparty/freetype/src/otvalid/otvmod.h b/thirdparty/freetype/src/otvalid/otvmod.h
index 6917bccee5..5539de7ec6 100644
--- a/thirdparty/freetype/src/otvalid/otvmod.h
+++ b/thirdparty/freetype/src/otvalid/otvmod.h
@@ -1,20 +1,20 @@
-/***************************************************************************/
-/* */
-/* otvmod.h */
-/* */
-/* FreeType's OpenType validation module implementation */
-/* (specification). */
-/* */
-/* Copyright 2004-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * otvmod.h
+ *
+ * FreeType's OpenType validation module implementation
+ * (specification).
+ *
+ * Copyright (C) 2004-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef OTVMOD_H_
@@ -27,10 +27,6 @@
FT_BEGIN_HEADER
-#ifdef FT_CONFIG_OPTION_PIC
-#error "this module does not support PIC yet"
-#endif
-
FT_EXPORT_VAR( const FT_Module_Class ) otv_module_class;
diff --git a/thirdparty/freetype/src/otvalid/rules.mk b/thirdparty/freetype/src/otvalid/rules.mk
index d4fc723740..3c6ece1c19 100644
--- a/thirdparty/freetype/src/otvalid/rules.mk
+++ b/thirdparty/freetype/src/otvalid/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 2004-2018 by
+# Copyright (C) 2004-2019 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/pcf/pcf.h b/thirdparty/freetype/src/pcf/pcf.h
index f0390cb1eb..529dd3adf8 100644
--- a/thirdparty/freetype/src/pcf/pcf.h
+++ b/thirdparty/freetype/src/pcf/pcf.h
@@ -104,6 +104,19 @@ FT_BEGIN_HEADER
} PCF_MetricRec, *PCF_Metric;
+ typedef struct PCF_EncRec_
+ {
+ FT_UShort firstCol;
+ FT_UShort lastCol;
+ FT_UShort firstRow;
+ FT_UShort lastRow;
+ FT_UShort defaultChar;
+
+ FT_UShort* offset;
+
+ } PCF_EncRec, *PCF_Enc;
+
+
typedef struct PCF_AccelRec_
{
FT_Byte noOverlap;
@@ -124,41 +137,32 @@ FT_BEGIN_HEADER
} PCF_AccelRec, *PCF_Accel;
- typedef struct PCF_EncodingRec_
- {
- FT_Long enc;
- FT_UShort glyph;
-
- } PCF_EncodingRec, *PCF_Encoding;
-
-
+ /*
+ * This file uses X11 terminology for PCF data; an `encoding' in X11 speak
+ * is the same as a `character code' in FreeType speak.
+ */
typedef struct PCF_FaceRec_
{
- FT_FaceRec root;
-
- FT_StreamRec comp_stream;
- FT_Stream comp_source;
+ FT_FaceRec root;
- char* charset_encoding;
- char* charset_registry;
+ FT_StreamRec comp_stream;
+ FT_Stream comp_source;
- PCF_TocRec toc;
- PCF_AccelRec accel;
+ char* charset_encoding;
+ char* charset_registry;
- int nprops;
- PCF_Property properties;
+ PCF_TocRec toc;
+ PCF_AccelRec accel;
- FT_ULong nmetrics;
- PCF_Metric metrics;
- FT_ULong nencodings;
- PCF_Encoding encodings;
+ int nprops;
+ PCF_Property properties;
- FT_Short defaultChar;
+ FT_ULong nmetrics;
+ PCF_Metric metrics;
- FT_ULong bitmapsFormat;
+ PCF_EncRec enc;
- FT_CharMap charmap_handle;
- FT_CharMapRec charmap; /* a single charmap per face */
+ FT_ULong bitmapsFormat;
} PCF_FaceRec, *PCF_Face;
diff --git a/thirdparty/freetype/src/pcf/pcfdrivr.c b/thirdparty/freetype/src/pcf/pcfdrivr.c
index 0119d94853..54bbb9d119 100644
--- a/thirdparty/freetype/src/pcf/pcfdrivr.c
+++ b/thirdparty/freetype/src/pcf/pcfdrivr.c
@@ -45,7 +45,7 @@ THE SOFTWARE.
#include "pcfutil.h"
#undef FT_COMPONENT
-#define FT_COMPONENT trace_pcfread
+#define FT_COMPONENT pcfread
#include FT_SERVICE_BDF_H
#include FT_SERVICE_FONT_FORMAT_H
@@ -53,21 +53,24 @@ THE SOFTWARE.
#include FT_DRIVER_H
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_pcfdriver
+#define FT_COMPONENT pcfdriver
+ /*
+ * This file uses X11 terminology for PCF data; an `encoding' in X11 speak
+ * is the same as a `character code' in FreeType speak.
+ */
typedef struct PCF_CMapRec_
{
- FT_CMapRec root;
- FT_ULong num_encodings;
- PCF_Encoding encodings;
+ FT_CMapRec root;
+ PCF_Enc enc;
} PCF_CMapRec, *PCF_CMap;
@@ -82,8 +85,7 @@ THE SOFTWARE.
FT_UNUSED( init_data );
- cmap->num_encodings = face->nencodings;
- cmap->encodings = face->encodings;
+ cmap->enc = &face->enc;
return FT_Err_Ok;
}
@@ -95,8 +97,7 @@ THE SOFTWARE.
PCF_CMap cmap = (PCF_CMap)pcfcmap;
- cmap->encodings = NULL;
- cmap->num_encodings = 0;
+ cmap->enc = NULL;
}
@@ -104,36 +105,26 @@ THE SOFTWARE.
pcf_cmap_char_index( FT_CMap pcfcmap, /* PCF_CMap */
FT_UInt32 charcode )
{
- PCF_CMap cmap = (PCF_CMap)pcfcmap;
- PCF_Encoding encodings = cmap->encodings;
- FT_ULong min, max, mid;
- FT_UInt result = 0;
+ PCF_CMap cmap = (PCF_CMap)pcfcmap;
+ PCF_Enc enc = cmap->enc;
+ FT_UShort charcodeRow;
+ FT_UShort charcodeCol;
- min = 0;
- max = cmap->num_encodings;
+ if ( charcode > (FT_UInt32)( enc->lastRow * 256 + enc->lastCol ) ||
+ charcode < (FT_UInt32)( enc->firstRow * 256 + enc->firstCol ) )
+ return 0;
- while ( min < max )
- {
- FT_ULong code;
+ charcodeRow = (FT_UShort)( charcode >> 8 );
+ charcodeCol = (FT_UShort)( charcode & 0xFF );
+ if ( charcodeCol < enc->firstCol ||
+ charcodeCol > enc->lastCol )
+ return 0;
- mid = ( min + max ) >> 1;
- code = (FT_ULong)encodings[mid].enc;
-
- if ( charcode == code )
- {
- result = encodings[mid].glyph + 1;
- break;
- }
-
- if ( charcode < code )
- max = mid;
- else
- min = mid + 1;
- }
-
- return result;
+ return (FT_UInt)enc->offset[ ( charcodeRow - enc->firstRow ) *
+ ( enc->lastCol - enc->firstCol + 1 ) +
+ charcodeCol - enc->firstCol ];
}
@@ -141,52 +132,43 @@ THE SOFTWARE.
pcf_cmap_char_next( FT_CMap pcfcmap, /* PCF_CMap */
FT_UInt32 *acharcode )
{
- PCF_CMap cmap = (PCF_CMap)pcfcmap;
- PCF_Encoding encodings = cmap->encodings;
- FT_ULong min, max, mid;
- FT_ULong charcode = *acharcode + 1;
- FT_UInt result = 0;
-
+ PCF_CMap cmap = (PCF_CMap)pcfcmap;
+ PCF_Enc enc = cmap->enc;
+ FT_UInt32 charcode = *acharcode;
+ FT_UShort charcodeRow;
+ FT_UShort charcodeCol;
+ FT_Int result = 0;
- min = 0;
- max = cmap->num_encodings;
- while ( min < max )
+ while ( charcode < (FT_UInt32)( enc->lastRow * 256 + enc->lastCol ) )
{
- FT_ULong code;
+ charcode++;
+ if ( charcode < (FT_UInt32)( enc->firstRow * 256 + enc->firstCol ) )
+ charcode = (FT_UInt32)( enc->firstRow * 256 + enc->firstCol );
- mid = ( min + max ) >> 1;
- code = (FT_ULong)encodings[mid].enc;
+ charcodeRow = (FT_UShort)( charcode >> 8 );
+ charcodeCol = (FT_UShort)( charcode & 0xFF );
- if ( charcode == code )
+ if ( charcodeCol < enc->firstCol )
+ charcodeCol = enc->firstCol;
+ else if ( charcodeCol > enc->lastCol )
{
- result = encodings[mid].glyph + 1;
- goto Exit;
+ charcodeRow++;
+ charcodeCol = enc->firstCol;
}
- if ( charcode < code )
- max = mid;
- else
- min = mid + 1;
- }
+ charcode = (FT_UInt32)( charcodeRow * 256 + charcodeCol );
- charcode = 0;
- if ( min < cmap->num_encodings )
- {
- charcode = (FT_ULong)encodings[min].enc;
- result = encodings[min].glyph + 1;
+ result = (FT_UInt)enc->offset[ ( charcodeRow - enc->firstRow ) *
+ ( enc->lastCol - enc->firstCol + 1 ) +
+ charcodeCol - enc->firstCol ];
+ if ( result != 0xFFFFU )
+ break;
}
- Exit:
- if ( charcode > 0xFFFFFFFFUL )
- {
- FT_TRACE1(( "pcf_cmap_char_next: charcode 0x%x > 32bit API" ));
- *acharcode = 0;
- /* XXX: result should be changed to indicate an overflow error */
- }
- else
- *acharcode = (FT_UInt32)charcode;
+ *acharcode = charcode;
+
return result;
}
@@ -216,8 +198,8 @@ THE SOFTWARE.
memory = FT_FACE_MEMORY( face );
- FT_FREE( face->encodings );
FT_FREE( face->metrics );
+ FT_FREE( face->enc.offset );
/* free properties */
if ( face->properties )
@@ -512,9 +494,6 @@ THE SOFTWARE.
stream = face->root.stream;
- if ( glyph_index > 0 )
- glyph_index--;
-
metric = face->metrics + glyph_index;
bitmap->rows = (unsigned int)( metric->ascent +
@@ -601,11 +580,11 @@ THE SOFTWARE.
}
- /*
- *
- * BDF SERVICE
- *
- */
+ /*
+ *
+ * BDF SERVICE
+ *
+ */
static FT_Error
pcf_get_bdf_property( PCF_Face face,
@@ -633,9 +612,9 @@ THE SOFTWARE.
}
/*
- * The PCF driver loads all properties as signed integers.
- * This really doesn't seem to be a problem, because this is
- * sufficient for any meaningful values.
+ * The PCF driver loads all properties as signed integers.
+ * This really doesn't seem to be a problem, because this is
+ * sufficient for any meaningful values.
*/
aproperty->type = BDF_PROPERTY_TYPE_INTEGER;
aproperty->u.integer = (FT_Int32)prop->value.l;
@@ -668,7 +647,7 @@ THE SOFTWARE.
/*
- * PROPERTY SERVICE
+ * PROPERTY SERVICE
*
*/
static FT_Error
@@ -777,11 +756,11 @@ THE SOFTWARE.
(FT_Properties_GetFunc)pcf_property_get ) /* get_property */
- /*
- *
- * SERVICE LIST
- *
- */
+ /*
+ *
+ * SERVICE LIST
+ *
+ */
static const FT_ServiceDescRec pcf_services[] =
{
diff --git a/thirdparty/freetype/src/pcf/pcfdrivr.h b/thirdparty/freetype/src/pcf/pcfdrivr.h
index 29d30497cd..73db0823d2 100644
--- a/thirdparty/freetype/src/pcf/pcfdrivr.h
+++ b/thirdparty/freetype/src/pcf/pcfdrivr.h
@@ -31,11 +31,8 @@ THE SOFTWARE.
#include <ft2build.h>
#include FT_INTERNAL_DRIVER_H
-FT_BEGIN_HEADER
-#ifdef FT_CONFIG_OPTION_PIC
-#error "this module does not support PIC yet"
-#endif
+FT_BEGIN_HEADER
FT_EXPORT_VAR( const FT_Driver_ClassRec ) pcf_driver_class;
diff --git a/thirdparty/freetype/src/pcf/pcferror.h b/thirdparty/freetype/src/pcf/pcferror.h
index add8ef2230..2e69d1d219 100644
--- a/thirdparty/freetype/src/pcf/pcferror.h
+++ b/thirdparty/freetype/src/pcf/pcferror.h
@@ -1,26 +1,26 @@
-/***************************************************************************/
-/* */
-/* pcferror.h */
-/* */
-/* PCF error codes (specification only). */
-/* */
-/* Copyright 2001, 2012 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* This file is used to define the PCF error enumeration constants. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * pcferror.h
+ *
+ * PCF error codes (specification only).
+ *
+ * Copyright 2001, 2012 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * This file is used to define the PCF error enumeration constants.
+ *
+ */
#ifndef PCFERROR_H_
#define PCFERROR_H_
diff --git a/thirdparty/freetype/src/pcf/pcfread.c b/thirdparty/freetype/src/pcf/pcfread.c
index 537da0dc79..71143ecfb5 100644
--- a/thirdparty/freetype/src/pcf/pcfread.c
+++ b/thirdparty/freetype/src/pcf/pcfread.c
@@ -37,14 +37,14 @@ THE SOFTWARE.
#include "pcferror.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_pcfread
+#define FT_COMPONENT pcfread
#ifdef FT_DEBUG_LEVEL_TRACE
@@ -178,23 +178,23 @@ THE SOFTWARE.
}
/*
- * We now check whether the `size' and `offset' values are reasonable:
- * `offset' + `size' must not exceed the stream size.
+ * We now check whether the `size' and `offset' values are reasonable:
+ * `offset' + `size' must not exceed the stream size.
*
- * Note, however, that X11's `pcfWriteFont' routine (used by the
- * `bdftopcf' program to create PDF font files) has two special
- * features.
+ * Note, however, that X11's `pcfWriteFont' routine (used by the
+ * `bdftopcf' program to create PCF font files) has two special
+ * features.
*
- * - It always assigns the accelerator table a size of 100 bytes in the
- * TOC, regardless of its real size, which can vary between 34 and 72
- * bytes.
+ * - It always assigns the accelerator table a size of 100 bytes in the
+ * TOC, regardless of its real size, which can vary between 34 and 72
+ * bytes.
*
- * - Due to the way the routine is designed, it ships out the last font
- * table with its real size, ignoring the TOC's size value. Since
- * the TOC size values are always rounded up to a multiple of 4, the
- * difference can be up to three bytes for all tables except the
- * accelerator table, for which the difference can be as large as 66
- * bytes.
+ * - Due to the way the routine is designed, it ships out the last font
+ * table with its real size, ignoring the TOC's size value. Since
+ * the TOC size values are always rounded up to a multiple of 4, the
+ * difference can be up to three bytes for all tables except the
+ * accelerator table, for which the difference can be as large as 66
+ * bytes.
*
*/
@@ -810,8 +810,8 @@ THE SOFTWARE.
{
FT_Error error;
FT_Memory memory = FT_FACE( face )->memory;
- FT_Long* offsets = NULL;
- FT_Long bitmapSizes[GLYPHPADOPTIONS];
+ FT_ULong* offsets = NULL;
+ FT_ULong bitmapSizes[GLYPHPADOPTIONS];
FT_ULong format, size;
FT_ULong nbitmaps, orig_nbitmaps, i, sizebitmaps = 0;
@@ -878,11 +878,11 @@ THE SOFTWARE.
for ( i = 0; i < nbitmaps; i++ )
{
if ( PCF_BYTE_ORDER( format ) == MSBFirst )
- (void)FT_READ_LONG( offsets[i] );
+ (void)FT_READ_ULONG( offsets[i] );
else
- (void)FT_READ_LONG_LE( offsets[i] );
+ (void)FT_READ_ULONG_LE( offsets[i] );
- FT_TRACE5(( " bitmap %ld: offset %ld (0x%lX)\n",
+ FT_TRACE5(( " bitmap %lu: offset %lu (0x%lX)\n",
i, offsets[i], offsets[i] ));
}
if ( error )
@@ -891,22 +891,22 @@ THE SOFTWARE.
for ( i = 0; i < GLYPHPADOPTIONS; i++ )
{
if ( PCF_BYTE_ORDER( format ) == MSBFirst )
- (void)FT_READ_LONG( bitmapSizes[i] );
+ (void)FT_READ_ULONG( bitmapSizes[i] );
else
- (void)FT_READ_LONG_LE( bitmapSizes[i] );
+ (void)FT_READ_ULONG_LE( bitmapSizes[i] );
if ( error )
goto Bail;
- sizebitmaps = (FT_ULong)bitmapSizes[PCF_GLYPH_PAD_INDEX( format )];
+ sizebitmaps = bitmapSizes[PCF_GLYPH_PAD_INDEX( format )];
- FT_TRACE4(( " %ld-bit padding implies a size of %ld\n",
+ FT_TRACE4(( " %ld-bit padding implies a size of %lu\n",
8 << i, bitmapSizes[i] ));
}
- FT_TRACE4(( " %ld bitmaps, using %ld-bit padding\n",
+ FT_TRACE4(( " %lu bitmaps, using %ld-bit padding\n",
nbitmaps,
8 << PCF_GLYPH_PAD_INDEX( format ) ));
- FT_TRACE4(( " bitmap size: %ld\n", sizebitmaps ));
+ FT_TRACE4(( " bitmap size: %lu\n", sizebitmaps ));
FT_UNUSED( sizebitmaps ); /* only used for debugging */
@@ -915,14 +915,13 @@ THE SOFTWARE.
for ( i = 0; i < nbitmaps; i++ )
{
/* rough estimate */
- if ( ( offsets[i] < 0 ) ||
- ( (FT_ULong)offsets[i] > size ) )
+ if ( offsets[i] > size )
{
FT_TRACE0(( "pcf_get_bitmaps:"
- " invalid offset to bitmap data of glyph %ld\n", i ));
+ " invalid offset to bitmap data of glyph %lu\n", i ));
}
else
- face->metrics[i].bits = stream->pos + (FT_ULong)offsets[i];
+ face->metrics[i].bits = stream->pos + offsets[i];
}
face->bitmapsFormat = format;
@@ -933,20 +932,58 @@ THE SOFTWARE.
}
+ /*
+ * This file uses X11 terminology for PCF data; an `encoding' in X11 speak
+ * is the same as a character code in FreeType speak.
+ */
+#define PCF_ENC_SIZE 10
+
+ static
+ const FT_Frame_Field pcf_enc_header[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE PCF_EncRec
+
+ FT_FRAME_START( PCF_ENC_SIZE ),
+ FT_FRAME_USHORT_LE( firstCol ),
+ FT_FRAME_USHORT_LE( lastCol ),
+ FT_FRAME_USHORT_LE( firstRow ),
+ FT_FRAME_USHORT_LE( lastRow ),
+ FT_FRAME_USHORT_LE( defaultChar ),
+ FT_FRAME_END
+ };
+
+
+ static
+ const FT_Frame_Field pcf_enc_msb_header[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE PCF_EncRec
+
+ FT_FRAME_START( PCF_ENC_SIZE ),
+ FT_FRAME_USHORT( firstCol ),
+ FT_FRAME_USHORT( lastCol ),
+ FT_FRAME_USHORT( firstRow ),
+ FT_FRAME_USHORT( lastRow ),
+ FT_FRAME_USHORT( defaultChar ),
+ FT_FRAME_END
+ };
+
+
static FT_Error
pcf_get_encodings( FT_Stream stream,
PCF_Face face )
{
- FT_Error error;
- FT_Memory memory = FT_FACE( face )->memory;
- FT_ULong format, size;
- int firstCol, lastCol;
- int firstRow, lastRow;
- FT_ULong nencoding;
- FT_UShort encodingOffset;
- int i, j;
- FT_ULong k;
- PCF_Encoding encoding = NULL;
+ FT_Error error;
+ FT_Memory memory = FT_FACE( face )->memory;
+ FT_ULong format, size;
+ PCF_Enc enc = &face->enc;
+ FT_ULong nencoding;
+ FT_UShort* offset;
+ FT_UShort defaultCharRow, defaultCharCol;
+ FT_UShort encodingOffset, defaultCharEncodingOffset;
+ FT_UShort i, j;
+ FT_Byte* pos;
error = pcf_seek_to_table_type( stream,
@@ -956,75 +993,118 @@ THE SOFTWARE.
&format,
&size );
if ( error )
- return error;
+ goto Bail;
- error = FT_Stream_EnterFrame( stream, 14 );
- if ( error )
- return error;
+ if ( FT_READ_ULONG_LE( format ) )
+ goto Bail;
- format = FT_GET_ULONG_LE();
+ FT_TRACE4(( "pcf_get_encodings:\n"
+ " format: 0x%lX (%s)\n",
+ format,
+ PCF_BYTE_ORDER( format ) == MSBFirst ? "MSB" : "LSB" ));
+
+ if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) &&
+ !PCF_FORMAT_MATCH( format, PCF_BDF_ENCODINGS ) )
+ return FT_THROW( Invalid_File_Format );
if ( PCF_BYTE_ORDER( format ) == MSBFirst )
{
- firstCol = FT_GET_SHORT();
- lastCol = FT_GET_SHORT();
- firstRow = FT_GET_SHORT();
- lastRow = FT_GET_SHORT();
- face->defaultChar = FT_GET_SHORT();
+ if ( FT_STREAM_READ_FIELDS( pcf_enc_msb_header, enc ) )
+ goto Bail;
}
else
{
- firstCol = FT_GET_SHORT_LE();
- lastCol = FT_GET_SHORT_LE();
- firstRow = FT_GET_SHORT_LE();
- lastRow = FT_GET_SHORT_LE();
- face->defaultChar = FT_GET_SHORT_LE();
+ if ( FT_STREAM_READ_FIELDS( pcf_enc_header, enc ) )
+ goto Bail;
}
- FT_Stream_ExitFrame( stream );
-
- FT_TRACE4(( "pcf_get_encodings:\n"
- " format: 0x%lX (%s)\n",
- format,
- PCF_BYTE_ORDER( format ) == MSBFirst ? "MSB" : "LSB" ));
-
- if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
- return FT_THROW( Invalid_File_Format );
-
FT_TRACE4(( " firstCol 0x%X, lastCol 0x%X\n"
- " firstRow 0x%X, lastRow 0x%X\n",
- firstCol, lastCol,
- firstRow, lastRow ));
+ " firstRow 0x%X, lastRow 0x%X\n"
+ " defaultChar 0x%X\n",
+ enc->firstCol, enc->lastCol,
+ enc->firstRow, enc->lastRow,
+ enc->defaultChar ));
/* sanity checks; we limit numbers of rows and columns to 256 */
- if ( firstCol < 0 ||
- firstCol > lastCol ||
- lastCol > 0xFF ||
- firstRow < 0 ||
- firstRow > lastRow ||
- lastRow > 0xFF )
+ if ( enc->firstCol > enc->lastCol ||
+ enc->lastCol > 0xFF ||
+ enc->firstRow > enc->lastRow ||
+ enc->lastRow > 0xFF )
return FT_THROW( Invalid_Table );
- nencoding = (FT_ULong)( lastCol - firstCol + 1 ) *
- (FT_ULong)( lastRow - firstRow + 1 );
+ nencoding = (FT_ULong)( enc->lastCol - enc->firstCol + 1 ) *
+ (FT_ULong)( enc->lastRow - enc->firstRow + 1 );
- if ( FT_NEW_ARRAY( encoding, nencoding ) )
- return error;
+ if ( FT_NEW_ARRAY( enc->offset, nencoding ) )
+ goto Bail;
error = FT_Stream_EnterFrame( stream, 2 * nencoding );
if ( error )
- goto Bail;
+ goto Exit;
FT_TRACE5(( "\n" ));
- k = 0;
- for ( i = firstRow; i <= lastRow; i++ )
+ defaultCharRow = enc->defaultChar >> 8;
+ defaultCharCol = enc->defaultChar & 0xFF;
+
+ /* validate default character */
+ if ( defaultCharRow < enc->firstRow ||
+ defaultCharRow > enc->lastRow ||
+ defaultCharCol < enc->firstCol ||
+ defaultCharCol > enc->lastCol )
+ {
+ enc->defaultChar = enc->firstRow * 256U + enc->firstCol;
+ FT_TRACE0(( "pcf_get_encodings:"
+ " Invalid default character set to %u\n",
+ enc->defaultChar ));
+
+ defaultCharRow = enc->firstRow;
+ defaultCharCol = enc->firstCol;
+ }
+
+ /* FreeType mandates that glyph index 0 is the `undefined glyph', */
+ /* which PCF calls the `default character'. For this reason, we */
+ /* swap the positions of glyph index 0 and the index corresponding */
+ /* to `defaultChar' in case they are different. */
+
+ /* `stream->cursor' still points at the beginning of the frame; */
+ /* we can thus easily get the offset to the default character */
+ pos = stream->cursor +
+ 2 * ( ( defaultCharRow - enc->firstRow ) *
+ ( enc->lastCol - enc->firstCol + 1 ) +
+ defaultCharCol - enc->firstCol );
+
+ if ( PCF_BYTE_ORDER( format ) == MSBFirst )
+ defaultCharEncodingOffset = FT_PEEK_USHORT( pos );
+ else
+ defaultCharEncodingOffset = FT_PEEK_USHORT_LE( pos );
+
+ if ( defaultCharEncodingOffset >= face->nmetrics )
+ {
+ FT_TRACE0(( "pcf_get_encodings:"
+ " Invalid glyph index for default character,"
+ " setting to zero\n" ));
+ defaultCharEncodingOffset = 0;
+ }
+
+ if ( defaultCharEncodingOffset )
+ {
+ /* do the swapping */
+ PCF_MetricRec tmp = face->metrics[defaultCharEncodingOffset];
+
+
+ face->metrics[defaultCharEncodingOffset] = face->metrics[0];
+ face->metrics[0] = tmp;
+ }
+
+ offset = enc->offset;
+ for ( i = enc->firstRow; i <= enc->lastRow; i++ )
{
- for ( j = firstCol; j <= lastCol; j++ )
+ for ( j = enc->firstCol; j <= enc->lastCol; j++ )
{
/* X11's reference implementation uses the equivalent to */
/* `FT_GET_SHORT', however PCF fonts with more than 32768 */
- /* characters (e.g. `unifont.pcf') clearly show that an */
+ /* characters (e.g., `unifont.pcf') clearly show that an */
/* unsigned value is needed. */
if ( PCF_BYTE_ORDER( format ) == MSBFirst )
encodingOffset = FT_GET_USHORT();
@@ -1033,28 +1113,23 @@ THE SOFTWARE.
if ( encodingOffset != 0xFFFFU )
{
- encoding[k].enc = i * 256 + j;
- encoding[k].glyph = encodingOffset;
-
- FT_TRACE5(( " code %d (0x%04X): idx %d\n",
- encoding[k].enc, encoding[k].enc, encoding[k].glyph ));
-
- k++;
+ if ( encodingOffset == defaultCharEncodingOffset )
+ encodingOffset = 0;
+ else if ( encodingOffset == 0 )
+ encodingOffset = defaultCharEncodingOffset;
}
+
+ *offset++ = encodingOffset;
}
}
FT_Stream_ExitFrame( stream );
- if ( FT_RENEW_ARRAY( encoding, nencoding, k ) )
- goto Bail;
-
- face->nencodings = k;
- face->encodings = encoding;
-
return error;
+ Exit:
+ FT_FREE( enc->offset );
+
Bail:
- FT_FREE( encoding );
return error;
}
@@ -1397,8 +1472,7 @@ THE SOFTWARE.
root->face_flags |= FT_FACE_FLAG_FIXED_SIZES |
- FT_FACE_FLAG_HORIZONTAL |
- FT_FACE_FLAG_FAST_GLYPHS;
+ FT_FACE_FLAG_HORIZONTAL;
if ( face->accel.constantWidth )
root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
@@ -1482,14 +1556,7 @@ THE SOFTWARE.
else
root->family_name = NULL;
- /*
- * Note: We shift all glyph indices by +1 since we must
- * respect the convention that glyph 0 always corresponds
- * to the `missing glyph'.
- *
- * This implies bumping the number of `available' glyphs by 1.
- */
- root->num_glyphs = (FT_Long)( face->nmetrics + 1 );
+ root->num_glyphs = (FT_Long)face->nmetrics;
root->num_fixed_sizes = 1;
if ( FT_NEW_ARRAY( root->available_sizes, 1 ) )
diff --git a/thirdparty/freetype/src/pcf/pcfutil.c b/thirdparty/freetype/src/pcf/pcfutil.c
index 0451ee8def..045c42d60f 100644
--- a/thirdparty/freetype/src/pcf/pcfutil.c
+++ b/thirdparty/freetype/src/pcf/pcfutil.c
@@ -37,7 +37,7 @@ in this Software without prior written authorization from The Open Group.
/*
- * Invert bit order within each BYTE of an array.
+ * Invert bit order within each BYTE of an array.
*/
FT_LOCAL_DEF( void )
@@ -59,7 +59,7 @@ in this Software without prior written authorization from The Open Group.
/*
- * Invert byte order within each 16-bits of an array.
+ * Invert byte order within each 16-bits of an array.
*/
FT_LOCAL_DEF( void )
@@ -78,7 +78,7 @@ in this Software without prior written authorization from The Open Group.
}
/*
- * Invert byte order within each 32-bits of an array.
+ * Invert byte order within each 32-bits of an array.
*/
FT_LOCAL_DEF( void )
diff --git a/thirdparty/freetype/src/pfr/module.mk b/thirdparty/freetype/src/pfr/module.mk
index 27fec8e5f6..30d876d4c8 100644
--- a/thirdparty/freetype/src/pfr/module.mk
+++ b/thirdparty/freetype/src/pfr/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright 2002-2018 by
+# Copyright (C) 2002-2019 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/pfr/pfr.c b/thirdparty/freetype/src/pfr/pfr.c
index 1760882fcd..6d885ea47f 100644
--- a/thirdparty/freetype/src/pfr/pfr.c
+++ b/thirdparty/freetype/src/pfr/pfr.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* pfr.c */
-/* */
-/* FreeType PFR driver component. */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * pfr.c
+ *
+ * FreeType PFR driver component.
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#define FT_MAKE_OPTION_SINGLE_OBJECT
diff --git a/thirdparty/freetype/src/pfr/pfrcmap.c b/thirdparty/freetype/src/pfr/pfrcmap.c
index 60643780a1..bfa1b9ea05 100644
--- a/thirdparty/freetype/src/pfr/pfrcmap.c
+++ b/thirdparty/freetype/src/pfr/pfrcmap.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* pfrcmap.c */
-/* */
-/* FreeType PFR cmap handling (body). */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * pfrcmap.c
+ *
+ * FreeType PFR cmap handling (body).
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
diff --git a/thirdparty/freetype/src/pfr/pfrcmap.h b/thirdparty/freetype/src/pfr/pfrcmap.h
index c70a0c83c5..1e203a0514 100644
--- a/thirdparty/freetype/src/pfr/pfrcmap.h
+++ b/thirdparty/freetype/src/pfr/pfrcmap.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* pfrcmap.h */
-/* */
-/* FreeType PFR cmap handling (specification). */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * pfrcmap.h
+ *
+ * FreeType PFR cmap handling (specification).
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef PFRCMAP_H_
diff --git a/thirdparty/freetype/src/pfr/pfrdrivr.c b/thirdparty/freetype/src/pfr/pfrdrivr.c
index 6c7e50128a..f67eebf118 100644
--- a/thirdparty/freetype/src/pfr/pfrdrivr.c
+++ b/thirdparty/freetype/src/pfr/pfrdrivr.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* pfrdrivr.c */
-/* */
-/* FreeType PFR driver interface (body). */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * pfrdrivr.c
+ *
+ * FreeType PFR driver interface (body).
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -57,10 +57,10 @@
}
- /*
- * PFR METRICS SERVICE
- *
- */
+ /*
+ * PFR METRICS SERVICE
+ *
+ */
FT_CALLBACK_DEF( FT_Error )
pfr_get_advance( FT_Face pfrface, /* PFR_Face */
@@ -145,10 +145,10 @@
};
- /*
- * SERVICE LIST
- *
- */
+ /*
+ * SERVICE LIST
+ *
+ */
static const FT_ServiceDescRec pfr_services[] =
{
diff --git a/thirdparty/freetype/src/pfr/pfrdrivr.h b/thirdparty/freetype/src/pfr/pfrdrivr.h
index cab852789b..33b7b9413f 100644
--- a/thirdparty/freetype/src/pfr/pfrdrivr.h
+++ b/thirdparty/freetype/src/pfr/pfrdrivr.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* pfrdrivr.h */
-/* */
-/* High-level Type PFR driver interface (specification). */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * pfrdrivr.h
+ *
+ * High-level Type PFR driver interface (specification).
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef PFRDRIVR_H_
@@ -26,14 +26,8 @@
FT_BEGIN_HEADER
-#ifdef FT_CONFIG_OPTION_PIC
-#error "this module does not support PIC yet"
-#endif
-
-
FT_EXPORT_VAR( const FT_Driver_ClassRec ) pfr_driver_class;
-
FT_END_HEADER
diff --git a/thirdparty/freetype/src/pfr/pfrerror.h b/thirdparty/freetype/src/pfr/pfrerror.h
index 7027c818e8..4829cfc000 100644
--- a/thirdparty/freetype/src/pfr/pfrerror.h
+++ b/thirdparty/freetype/src/pfr/pfrerror.h
@@ -1,26 +1,26 @@
-/***************************************************************************/
-/* */
-/* pfrerror.h */
-/* */
-/* PFR error codes (specification only). */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* This file is used to define the PFR error enumeration constants. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * pfrerror.h
+ *
+ * PFR error codes (specification only).
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * This file is used to define the PFR error enumeration constants.
+ *
+ */
#ifndef PFRERROR_H_
#define PFRERROR_H_
diff --git a/thirdparty/freetype/src/pfr/pfrgload.c b/thirdparty/freetype/src/pfr/pfrgload.c
index b7990196b6..6ef5856a8d 100644
--- a/thirdparty/freetype/src/pfr/pfrgload.c
+++ b/thirdparty/freetype/src/pfr/pfrgload.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* pfrgload.c */
-/* */
-/* FreeType PFR glyph loader (body). */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * pfrgload.c
+ *
+ * FreeType PFR glyph loader (body).
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include "pfrgload.h"
@@ -24,7 +24,7 @@
#include "pfrerror.h"
#undef FT_COMPONENT
-#define FT_COMPONENT trace_pfr
+#define FT_COMPONENT pfr
/*************************************************************************/
@@ -359,9 +359,9 @@
FT_UInt format, format_low, args_format = 0, args_count, n;
- /***************************************************************/
- /* read instruction */
- /* */
+ /****************************************************************
+ * read instruction
+ */
PFR_CHECK( 1 );
format = PFR_NEXT_BYTE( p );
format_low = format & 15;
@@ -426,9 +426,9 @@
args_format = format_low;
}
- /***********************************************************/
- /* now read arguments */
- /* */
+ /************************************************************
+ * now read arguments
+ */
cur = pos;
for ( n = 0; n < args_count; n++ )
{
@@ -513,9 +513,9 @@
FT_TRACE7(( "\n" ));
- /***********************************************************/
- /* finally, execute instruction */
- /* */
+ /************************************************************
+ * finally, execute instruction
+ */
switch ( format >> 4 )
{
case 0: /* end glyph => EXIT */
diff --git a/thirdparty/freetype/src/pfr/pfrgload.h b/thirdparty/freetype/src/pfr/pfrgload.h
index 01f48d7706..d0e1420b67 100644
--- a/thirdparty/freetype/src/pfr/pfrgload.h
+++ b/thirdparty/freetype/src/pfr/pfrgload.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* pfrgload.h */
-/* */
-/* FreeType PFR glyph loader (specification). */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * pfrgload.h
+ *
+ * FreeType PFR glyph loader (specification).
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef PFRGLOAD_H_
diff --git a/thirdparty/freetype/src/pfr/pfrload.c b/thirdparty/freetype/src/pfr/pfrload.c
index 2776da462a..ccf0b7e1f8 100644
--- a/thirdparty/freetype/src/pfr/pfrload.c
+++ b/thirdparty/freetype/src/pfr/pfrload.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* pfrload.c */
-/* */
-/* FreeType PFR loader (body). */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * pfrload.c
+ *
+ * FreeType PFR loader (body).
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include "pfrload.h"
@@ -23,92 +23,92 @@
#include "pfrerror.h"
#undef FT_COMPONENT
-#define FT_COMPONENT trace_pfr
+#define FT_COMPONENT pfr
/*
- * The overall structure of a PFR file is as follows.
+ * The overall structure of a PFR file is as follows.
*
- * PFR header
- * 58 bytes (contains nPhysFonts)
+ * PFR header
+ * 58 bytes (contains nPhysFonts)
*
- * Logical font directory (size at most 2^16 bytes)
- * 2 bytes (nLogFonts)
- * + nLogFonts * 5 bytes
+ * Logical font directory (size at most 2^16 bytes)
+ * 2 bytes (nLogFonts)
+ * + nLogFonts * 5 bytes
*
- * ==> nLogFonts <= 13106
+ * ==> nLogFonts <= 13106
*
- * Logical font section (size at most 2^24 bytes)
- * nLogFonts * logFontRecord
+ * Logical font section (size at most 2^24 bytes)
+ * nLogFonts * logFontRecord
*
- * logFontRecord (size at most 2^16 bytes)
- * 12 bytes (fontMatrix)
- * + 1 byte (flags)
- * + 0-5 bytes (depending on `flags')
- * + 0-(1+255*(2+255)) = 0-65536 (depending on `flags')
- * + 5 bytes (physical font info)
- * + 0-1 bytes (depending on PFR header)
+ * logFontRecord (size at most 2^16 bytes)
+ * 12 bytes (fontMatrix)
+ * + 1 byte (flags)
+ * + 0-5 bytes (depending on `flags')
+ * + 0-(1+255*(2+255)) = 0-65536 (depending on `flags')
+ * + 5 bytes (physical font info)
+ * + 0-1 bytes (depending on PFR header)
*
- * ==> minimum size 18 bytes
+ * ==> minimum size 18 bytes
*
- * Physical font section (size at most 2^24 bytes)
- * nPhysFonts * (physFontRecord
- * + nBitmapSizes * nBmapChars * bmapCharRecord)
+ * Physical font section (size at most 2^24 bytes)
+ * nPhysFonts * (physFontRecord
+ * + nBitmapSizes * nBmapChars * bmapCharRecord)
*
- * physFontRecord (size at most 2^24 bytes)
- * 14 bytes (font info)
- * + 1 byte (flags)
- * + 0-2 (depending on `flags')
- * + 0-? (structure too complicated to be shown here; depending on
- * `flags'; contains `nBitmapSizes' and `nBmapChars')
- * + 3 bytes (nAuxBytes)
- * + nAuxBytes
- * + 1 byte (nBlueValues)
- * + 2 * nBlueValues
- * + 6 bytes (hinting data)
- * + 2 bytes (nCharacters)
- * + nCharacters * (4-10 bytes) (depending on `flags')
+ * physFontRecord (size at most 2^24 bytes)
+ * 14 bytes (font info)
+ * + 1 byte (flags)
+ * + 0-2 (depending on `flags')
+ * + 0-? (structure too complicated to be shown here; depending on
+ * `flags'; contains `nBitmapSizes' and `nBmapChars')
+ * + 3 bytes (nAuxBytes)
+ * + nAuxBytes
+ * + 1 byte (nBlueValues)
+ * + 2 * nBlueValues
+ * + 6 bytes (hinting data)
+ * + 2 bytes (nCharacters)
+ * + nCharacters * (4-10 bytes) (depending on `flags')
*
- * ==> minimum size 27 bytes
+ * ==> minimum size 27 bytes
*
- * bmapCharRecord
- * 4-7 bytes
+ * bmapCharRecord
+ * 4-7 bytes
*
- * Glyph program strings (three possible types: simpleGps, compoundGps,
- * and bitmapGps; size at most 2^24 bytes)
- * simpleGps (size at most 2^16 bytes)
- * 1 byte (flags)
- * 1-2 bytes (n[XY]orus, depending on `flags')
- * 0-(64+512*2) = 0-1088 bytes (depending on `n[XY]orus')
- * 0-? (structure too complicated to be shown here; depending on
- * `flags')
- * 1-? glyph data (faintly resembling PS Type 1 charstrings)
+ * Glyph program strings (three possible types: simpleGps, compoundGps,
+ * and bitmapGps; size at most 2^24 bytes)
+ * simpleGps (size at most 2^16 bytes)
+ * 1 byte (flags)
+ * 1-2 bytes (n[XY]orus, depending on `flags')
+ * 0-(64+512*2) = 0-1088 bytes (depending on `n[XY]orus')
+ * 0-? (structure too complicated to be shown here; depending on
+ * `flags')
+ * 1-? glyph data (faintly resembling PS Type 1 charstrings)
*
- * ==> minimum size 3 bytes
+ * ==> minimum size 3 bytes
*
- * compoundGps (size at most 2^16 bytes)
- * 1 byte (nElements <= 63, flags)
- * + 0-(1+255*(2+255)) = 0-65536 (depending on `flags')
- * + nElements * (6-14 bytes)
+ * compoundGps (size at most 2^16 bytes)
+ * 1 byte (nElements <= 63, flags)
+ * + 0-(1+255*(2+255)) = 0-65536 (depending on `flags')
+ * + nElements * (6-14 bytes)
*
- * bitmapGps (size at most 2^16 bytes)
- * 1 byte (flags)
- * 3-13 bytes (position info, depending on `flags')
- * 0-? bitmap data
+ * bitmapGps (size at most 2^16 bytes)
+ * 1 byte (flags)
+ * 3-13 bytes (position info, depending on `flags')
+ * 0-? bitmap data
*
- * ==> minimum size 4 bytes
+ * ==> minimum size 4 bytes
*
- * PFR trailer
- * 8 bytes
+ * PFR trailer
+ * 8 bytes
*
*
- * ==> minimum size of a valid PFR:
- * 58 (header)
- * + 2 (nLogFonts)
- * + 27 (1 physFontRecord)
- * + 8 (trailer)
- * -----
- * 95 bytes
+ * ==> minimum size of a valid PFR:
+ * 58 (header)
+ * + 2 (nLogFonts)
+ * + 27 (1 physFontRecord)
+ * + 8 (trailer)
+ * -----
+ * 95 bytes
*
*/
diff --git a/thirdparty/freetype/src/pfr/pfrload.h b/thirdparty/freetype/src/pfr/pfrload.h
index 36e809a762..2e7ffd0127 100644
--- a/thirdparty/freetype/src/pfr/pfrload.h
+++ b/thirdparty/freetype/src/pfr/pfrload.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* pfrload.h */
-/* */
-/* FreeType PFR loader (specification). */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * pfrload.h
+ *
+ * FreeType PFR loader (specification).
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef PFRLOAD_H_
diff --git a/thirdparty/freetype/src/pfr/pfrobjs.c b/thirdparty/freetype/src/pfr/pfrobjs.c
index 737b97b5ff..e103a3f6f2 100644
--- a/thirdparty/freetype/src/pfr/pfrobjs.c
+++ b/thirdparty/freetype/src/pfr/pfrobjs.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* pfrobjs.c */
-/* */
-/* FreeType PFR object methods (body). */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * pfrobjs.c
+ *
+ * FreeType PFR object methods (body).
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include "pfrobjs.h"
@@ -29,7 +29,7 @@
#include "pfrerror.h"
#undef FT_COMPONENT
-#define FT_COMPONENT trace_pfr
+#define FT_COMPONENT pfr
/*************************************************************************/
@@ -122,7 +122,7 @@
stream,
(FT_UInt)( face_index & 0xFFFF ),
face->header.log_dir_offset,
- FT_BOOL( face->header.phy_font_max_size_high != 0 ) );
+ FT_BOOL( face->header.phy_font_max_size_high ) );
if ( error )
goto Exit;
@@ -370,7 +370,7 @@
FT_Bool scaling;
- scaling = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 );
+ scaling = FT_BOOL( !( load_flags & FT_LOAD_NO_SCALE ) );
/* copy outline data */
*outline = slot->glyph.loader->base.outline;
diff --git a/thirdparty/freetype/src/pfr/pfrobjs.h b/thirdparty/freetype/src/pfr/pfrobjs.h
index 59c709f58d..39cffd07c5 100644
--- a/thirdparty/freetype/src/pfr/pfrobjs.h
+++ b/thirdparty/freetype/src/pfr/pfrobjs.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* pfrobjs.h */
-/* */
-/* FreeType PFR object methods (specification). */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * pfrobjs.h
+ *
+ * FreeType PFR object methods (specification).
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef PFROBJS_H_
diff --git a/thirdparty/freetype/src/pfr/pfrsbit.c b/thirdparty/freetype/src/pfr/pfrsbit.c
index ba909ddca7..00a9616455 100644
--- a/thirdparty/freetype/src/pfr/pfrsbit.c
+++ b/thirdparty/freetype/src/pfr/pfrsbit.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* pfrsbit.c */
-/* */
-/* FreeType PFR bitmap loader (body). */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * pfrsbit.c
+ *
+ * FreeType PFR bitmap loader (body).
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include "pfrsbit.h"
@@ -24,7 +24,7 @@
#include "pfrerror.h"
#undef FT_COMPONENT
-#define FT_COMPONENT trace_pfr
+#define FT_COMPONENT pfr
/*************************************************************************/
diff --git a/thirdparty/freetype/src/pfr/pfrsbit.h b/thirdparty/freetype/src/pfr/pfrsbit.h
index 07b27bc06c..6568b90943 100644
--- a/thirdparty/freetype/src/pfr/pfrsbit.h
+++ b/thirdparty/freetype/src/pfr/pfrsbit.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* pfrsbit.h */
-/* */
-/* FreeType PFR bitmap loader (specification). */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * pfrsbit.h
+ *
+ * FreeType PFR bitmap loader (specification).
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef PFRSBIT_H_
diff --git a/thirdparty/freetype/src/pfr/pfrtypes.h b/thirdparty/freetype/src/pfr/pfrtypes.h
index 058d6aadc9..6a5f9d571b 100644
--- a/thirdparty/freetype/src/pfr/pfrtypes.h
+++ b/thirdparty/freetype/src/pfr/pfrtypes.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* pfrtypes.h */
-/* */
-/* FreeType PFR data structures (specification only). */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * pfrtypes.h
+ *
+ * FreeType PFR data structures (specification only).
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef PFRTYPES_H_
diff --git a/thirdparty/freetype/src/pfr/rules.mk b/thirdparty/freetype/src/pfr/rules.mk
index 3acb795696..f14ca699e2 100644
--- a/thirdparty/freetype/src/pfr/rules.mk
+++ b/thirdparty/freetype/src/pfr/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 2002-2018 by
+# Copyright (C) 2002-2019 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/psaux/afmparse.c b/thirdparty/freetype/src/psaux/afmparse.c
index 0c33d5949b..49225a9f78 100644
--- a/thirdparty/freetype/src/psaux/afmparse.c
+++ b/thirdparty/freetype/src/psaux/afmparse.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* afmparse.c */
-/* */
-/* AFM parser (body). */
-/* */
-/* Copyright 2006-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * afmparse.c
+ *
+ * AFM parser (body).
+ *
+ * Copyright (C) 2006-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
#include FT_FREETYPE_H
@@ -28,13 +28,13 @@
#include "psauxerr.h"
-/***************************************************************************/
-/* */
-/* AFM_Stream */
-/* */
-/* The use of AFM_Stream is largely inspired by parseAFM.[ch] from t1lib. */
-/* */
-/* */
+ /**************************************************************************
+ *
+ * AFM_Stream
+ *
+ * The use of AFM_Stream is largely inspired by parseAFM.[ch] from t1lib.
+ *
+ */
enum
{
@@ -193,11 +193,11 @@
}
- /*************************************************************************/
- /* */
- /* AFM_Parser */
- /* */
- /* */
+ /**************************************************************************
+ *
+ * AFM_Parser
+ *
+ */
/* all keys defined in Ch. 7-10 of 5004.AFM_Spec.pdf */
typedef enum AFM_Token_
diff --git a/thirdparty/freetype/src/psaux/afmparse.h b/thirdparty/freetype/src/psaux/afmparse.h
index 86f852a247..2ceb77553b 100644
--- a/thirdparty/freetype/src/psaux/afmparse.h
+++ b/thirdparty/freetype/src/psaux/afmparse.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* afmparse.h */
-/* */
-/* AFM parser (specification). */
-/* */
-/* Copyright 2006-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * afmparse.h
+ *
+ * AFM parser (specification).
+ *
+ * Copyright (C) 2006-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef AFMPARSE_H_
diff --git a/thirdparty/freetype/src/psaux/cffdecode.c b/thirdparty/freetype/src/psaux/cffdecode.c
index 80d622c0e1..17cccf818b 100644
--- a/thirdparty/freetype/src/psaux/cffdecode.c
+++ b/thirdparty/freetype/src/psaux/cffdecode.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* cffdecode.c */
-/* */
-/* PostScript CFF (Type 2) decoding routines (body). */
-/* */
-/* Copyright 2017-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * cffdecode.c
+ *
+ * PostScript CFF (Type 2) decoding routines (body).
+ *
+ * Copyright (C) 2017-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -28,14 +28,14 @@
#include "psauxerr.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_cffdecode
+#define FT_COMPONENT cffdecode
#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
@@ -235,8 +235,8 @@
return FT_THROW( Syntax_Error );
}
- adx += decoder->builder.left_bearing.x;
- ady += decoder->builder.left_bearing.y;
+ adx = ADD_LONG( adx, decoder->builder.left_bearing.x );
+ ady = ADD_LONG( ady, decoder->builder.left_bearing.y );
#ifdef FT_CONFIG_OPTION_INCREMENTAL
/* Incremental fonts don't necessarily have valid charsets. */
@@ -378,23 +378,26 @@
/*************************************************************************/
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* <Function> */
- /* cff_compute_bias */
- /* */
- /* <Description> */
- /* Computes the bias value in dependence of the number of glyph */
- /* subroutines. */
- /* */
- /* <Input> */
- /* in_charstring_type :: The `CharstringType' value of the top DICT */
- /* dictionary. */
- /* */
- /* num_subrs :: The number of glyph subroutines. */
- /* */
- /* <Return> */
- /* The bias value. */
+ /**************************************************************************
+ *
+ * @Function:
+ * cff_compute_bias
+ *
+ * @Description:
+ * Computes the bias value in dependence of the number of glyph
+ * subroutines.
+ *
+ * @Input:
+ * in_charstring_type ::
+ * The `CharstringType' value of the top DICT
+ * dictionary.
+ *
+ * num_subrs ::
+ * The number of glyph subroutines.
+ *
+ * @Return:
+ * The bias value.
+ */
static FT_Int
cff_compute_bias( FT_Int in_charstring_type,
FT_UInt num_subrs )
@@ -464,28 +467,32 @@
#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
- /*************************************************************************/
- /* */
- /* <Function> */
- /* cff_decoder_parse_charstrings */
- /* */
- /* <Description> */
- /* Parses a given Type 2 charstrings program. */
- /* */
- /* <InOut> */
- /* decoder :: The current Type 1 decoder. */
- /* */
- /* <Input> */
- /* charstring_base :: The base of the charstring stream. */
- /* */
- /* charstring_len :: The length in bytes of the charstring stream. */
- /* */
- /* in_dict :: Set to 1 if function is called from top or */
- /* private DICT (needed for Multiple Master CFFs). */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * cff_decoder_parse_charstrings
+ *
+ * @Description:
+ * Parses a given Type 2 charstrings program.
+ *
+ * @InOut:
+ * decoder ::
+ * The current Type 1 decoder.
+ *
+ * @Input:
+ * charstring_base ::
+ * The base of the charstring stream.
+ *
+ * charstring_len ::
+ * The length in bytes of the charstring stream.
+ *
+ * in_dict ::
+ * Set to 1 if function is called from top or
+ * private DICT (needed for Multiple Master CFFs).
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
cff_decoder_parse_charstrings( CFF_Decoder* decoder,
FT_Byte* charstring_base,
@@ -543,10 +550,10 @@
FT_Byte v;
- /********************************************************************/
- /* */
- /* Decode operator or operand */
- /* */
+ /*********************************************************************
+ *
+ * Decode operator or operand
+ */
v = *ip++;
if ( v >= 32 || v == 28 )
{
@@ -853,6 +860,15 @@
case cff_op_flex1:
case cff_op_callsubr:
case cff_op_callgsubr:
+ /* deprecated opcodes */
+ case cff_op_dotsection:
+ /* invalid Type 1 opcodes */
+ case cff_op_hsbw:
+ case cff_op_closepath:
+ case cff_op_callothersubr:
+ case cff_op_seac:
+ case cff_op_sbw:
+ case cff_op_setcurrentpoint:
goto MM_Error;
default:
@@ -948,10 +964,10 @@
case cff_op_hstemhm:
case cff_op_vstemhm:
/* the number of arguments is always even here */
- FT_TRACE4((
- op == cff_op_hstem ? " hstem\n" :
- ( op == cff_op_vstem ? " vstem\n" :
- ( op == cff_op_hstemhm ? " hstemhm\n" : " vstemhm\n" ) ) ));
+ FT_TRACE4(( "%s\n",
+ op == cff_op_hstem ? " hstem" :
+ ( op == cff_op_vstem ? " vstem" :
+ ( op == cff_op_hstemhm ? " hstemhm" : " vstemhm" ) ) ));
if ( hinter )
hinter->stems( hinter->hints,
@@ -965,7 +981,8 @@
case cff_op_hintmask:
case cff_op_cntrmask:
- FT_TRACE4(( op == cff_op_hintmask ? " hintmask" : " cntrmask" ));
+ FT_TRACE4(( "%s", op == cff_op_hintmask ? " hintmask"
+ : " cntrmask" ));
/* implement vstem when needed -- */
/* the specification doesn't say it, but this also works */
@@ -1078,8 +1095,8 @@
FT_Int phase = ( op == cff_op_hlineto );
- FT_TRACE4(( op == cff_op_hlineto ? " hlineto\n"
- : " vlineto\n" ));
+ FT_TRACE4(( "%s\n", op == cff_op_hlineto ? " hlineto"
+ : " vlineto" ));
if ( num_args < 0 )
goto Stack_Underflow;
@@ -1250,8 +1267,8 @@
FT_Int nargs;
- FT_TRACE4(( op == cff_op_vhcurveto ? " vhcurveto\n"
- : " hvcurveto\n" ));
+ FT_TRACE4(( "%s\n", op == cff_op_vhcurveto ? " vhcurveto"
+ : " hvcurveto" ));
if ( cff_builder_start_point( builder, x, y ) )
goto Fail;
@@ -1539,9 +1556,9 @@
}
if ( dx < 0 )
- dx = -dx;
+ dx = NEG_LONG( dx );
if ( dy < 0 )
- dy = -dy;
+ dy = NEG_LONG( dy );
/* strange test, but here it is... */
horizontal = ( dx > dy );
@@ -1551,7 +1568,7 @@
x = ADD_LONG( x, args[0] );
y = ADD_LONG( y, args[1] );
cff_builder_add_point( builder, x, y,
- (FT_Bool)( count == 3 ) );
+ FT_BOOL( count == 3 ) );
args += 2;
}
@@ -1589,7 +1606,7 @@
x = ADD_LONG( x, args[0] );
y = ADD_LONG( y, args[1] );
cff_builder_add_point( builder, x, y,
- (FT_Bool)( count == 4 || count == 1 ) );
+ FT_BOOL( count == 4 || count == 1 ) );
args += 2;
}
@@ -1705,16 +1722,20 @@
break;
case cff_op_random:
- FT_TRACE4(( " random\n" ));
+ {
+ FT_UInt32* randval = in_dict ? &decoder->cff->top_font.random
+ : &decoder->current_subfont->random;
- /* only use the lower 16 bits of `random' */
- /* to generate a number in the range (0;1] */
- args[0] = (FT_Fixed)
- ( ( decoder->current_subfont->random & 0xFFFF ) + 1 );
- args++;
- decoder->current_subfont->random =
- cff_random( decoder->current_subfont->random );
+ FT_TRACE4(( " random\n" ));
+
+ /* only use the lower 16 bits of `random' */
+ /* to generate a number in the range (0;1] */
+ args[0] = (FT_Fixed)( ( *randval & 0xFFFF ) + 1 );
+ args++;
+
+ *randval = cff_random( *randval );
+ }
break;
case cff_op_mul:
@@ -1727,7 +1748,10 @@
case cff_op_sqrt:
FT_TRACE4(( " sqrt\n" ));
- if ( args[0] > 0 )
+ /* without upper limit the loop below might not finish */
+ if ( args[0] > 0x7FFFFFFFL )
+ args[0] = 46341;
+ else if ( args[0] > 0 )
{
FT_Fixed root = args[0];
FT_Fixed new_root;
@@ -1800,6 +1824,7 @@
if ( idx >= 0 )
{
+ idx = idx % count;
while ( idx > 0 )
{
FT_Fixed tmp = args[count - 1];
@@ -1814,6 +1839,10 @@
}
else
{
+ /* before C99 it is implementation-defined whether */
+ /* the result of `%' is negative if the first operand */
+ /* is negative */
+ idx = -( NEG_INT( idx ) % count );
while ( idx < 0 )
{
FT_Fixed tmp = args[0];
@@ -1914,6 +1943,7 @@
case cff_op_blend:
/* this operator was removed from the Type2 specification */
/* in version 16-March-2000 */
+ if ( num_designs )
{
FT_Int num_results = (FT_Int)( args[0] >> 16 );
@@ -1923,7 +1953,8 @@
if ( num_results < 0 )
goto Syntax_Error;
- if ( num_results * (FT_Int)num_designs > num_args )
+ if ( num_results > num_args ||
+ num_results * (FT_Int)num_designs > num_args )
goto Stack_Underflow;
/* since we currently don't handle interpolation of multiple */
@@ -1932,6 +1963,8 @@
args -= num_results * ( num_designs - 1 );
num_args -= num_results * ( num_designs - 1 );
}
+ else
+ goto Syntax_Error;
break;
case cff_op_dotsection:
@@ -1998,20 +2031,31 @@
break;
case cff_op_callothersubr:
- /* this is an invalid Type 2 operator; however, there */
- /* exist fonts which are incorrectly converted from probably */
- /* Type 1 to CFF, and some parsers seem to accept it */
+ {
+ FT_Fixed arg;
- FT_TRACE4(( " callothersubr (invalid op)\n" ));
- /* subsequent `pop' operands should add the arguments, */
- /* this is the implementation described for `unknown' other */
- /* subroutines in the Type1 spec. */
- /* */
- /* XXX Fix return arguments (see discussion below). */
- args -= 2 + ( args[-2] >> 16 );
- if ( args < stack )
- goto Stack_Underflow;
+ /* this is an invalid Type 2 operator; however, there */
+ /* exist fonts which are incorrectly converted from */
+ /* probably Type 1 to CFF, and some parsers seem to accept */
+ /* it */
+
+ FT_TRACE4(( " callothersubr (invalid op)\n" ));
+
+ /* subsequent `pop' operands should add the arguments, */
+ /* this is the implementation described for `unknown' */
+ /* other subroutines in the Type1 spec. */
+ /* */
+ /* XXX Fix return arguments (see discussion below). */
+
+ arg = 2 + ( args[-2] >> 16 );
+ if ( arg >= CFF_MAX_OPERANDS )
+ goto Stack_Underflow;
+
+ args -= arg;
+ if ( args < stack )
+ goto Stack_Underflow;
+ }
break;
case cff_op_pop:
@@ -2251,28 +2295,34 @@
#endif /* CFF_CONFIG_OPTION_OLD_ENGINE */
- /*************************************************************************/
- /* */
- /* <Function> */
- /* cff_decoder_init */
- /* */
- /* <Description> */
- /* Initializes a given glyph decoder. */
- /* */
- /* <InOut> */
- /* decoder :: A pointer to the glyph builder to initialize. */
- /* */
- /* <Input> */
- /* face :: The current face object. */
- /* */
- /* size :: The current size object. */
- /* */
- /* slot :: The current glyph object. */
- /* */
- /* hinting :: Whether hinting is active. */
- /* */
- /* hint_mode :: The hinting mode. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * cff_decoder_init
+ *
+ * @Description:
+ * Initializes a given glyph decoder.
+ *
+ * @InOut:
+ * decoder ::
+ * A pointer to the glyph builder to initialize.
+ *
+ * @Input:
+ * face ::
+ * The current face object.
+ *
+ * size ::
+ * The current size object.
+ *
+ * slot ::
+ * The current glyph object.
+ *
+ * hinting ::
+ * Whether hinting is active.
+ *
+ * hint_mode ::
+ * The hinting mode.
+ */
FT_LOCAL_DEF( void )
cff_decoder_init( CFF_Decoder* decoder,
TT_Face face,
diff --git a/thirdparty/freetype/src/psaux/cffdecode.h b/thirdparty/freetype/src/psaux/cffdecode.h
index 0d4f5fef63..a6691979f0 100644
--- a/thirdparty/freetype/src/psaux/cffdecode.h
+++ b/thirdparty/freetype/src/psaux/cffdecode.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* cffdecode.h */
-/* */
-/* PostScript CFF (Type 2) decoding routines (specification). */
-/* */
-/* Copyright 2017-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * cffdecode.h
+ *
+ * PostScript CFF (Type 2) decoding routines (specification).
+ *
+ * Copyright (C) 2017-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef CFFDECODE_H_
diff --git a/thirdparty/freetype/src/psaux/module.mk b/thirdparty/freetype/src/psaux/module.mk
index 6584d075a2..bb0886abdf 100644
--- a/thirdparty/freetype/src/psaux/module.mk
+++ b/thirdparty/freetype/src/psaux/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2018 by
+# Copyright (C) 1996-2019 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/psaux/psarrst.c b/thirdparty/freetype/src/psaux/psarrst.c
index a8780947f9..011803b416 100644
--- a/thirdparty/freetype/src/psaux/psarrst.c
+++ b/thirdparty/freetype/src/psaux/psarrst.c
@@ -1,39 +1,39 @@
-/***************************************************************************/
-/* */
-/* psarrst.c */
-/* */
-/* Adobe's code for Array Stacks (body). */
-/* */
-/* Copyright 2007-2013 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * psarrst.c
+ *
+ * Adobe's code for Array Stacks (body).
+ *
+ * Copyright 2007-2013 Adobe Systems Incorporated.
+ *
+ * This software, and all works of authorship, whether in source or
+ * object code form as indicated by the copyright notice(s) included
+ * herein (collectively, the "Work") is made available, and may only be
+ * used, modified, and distributed under the FreeType Project License,
+ * LICENSE.TXT. Additionally, subject to the terms and conditions of the
+ * FreeType Project License, each contributor to the Work hereby grants
+ * to any individual or legal entity exercising permissions granted by
+ * the FreeType Project License and this section (hereafter, "You" or
+ * "Your") a perpetual, worldwide, non-exclusive, no-charge,
+ * royalty-free, irrevocable (except as stated in this section) patent
+ * license to make, have made, use, offer to sell, sell, import, and
+ * otherwise transfer the Work, where such license applies only to those
+ * patent claims licensable by such contributor that are necessarily
+ * infringed by their contribution(s) alone or by combination of their
+ * contribution(s) with the Work to which such contribution(s) was
+ * submitted. If You institute patent litigation against any entity
+ * (including a cross-claim or counterclaim in a lawsuit) alleging that
+ * the Work or a contribution incorporated within the Work constitutes
+ * direct or contributory patent infringement, then any patent licenses
+ * granted to You under this License for that Work shall terminate as of
+ * the date such litigation is filed.
+ *
+ * By using, modifying, or distributing the Work you indicate that you
+ * have read and understood the terms and conditions of the
+ * FreeType Project License as well as those provided in this section,
+ * and you accept them fully.
+ *
+ */
#include "psft.h"
diff --git a/thirdparty/freetype/src/psaux/psarrst.h b/thirdparty/freetype/src/psaux/psarrst.h
index b3568eb61f..098617b257 100644
--- a/thirdparty/freetype/src/psaux/psarrst.h
+++ b/thirdparty/freetype/src/psaux/psarrst.h
@@ -1,39 +1,39 @@
-/***************************************************************************/
-/* */
-/* psarrst.h */
-/* */
-/* Adobe's code for Array Stacks (specification). */
-/* */
-/* Copyright 2007-2013 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * psarrst.h
+ *
+ * Adobe's code for Array Stacks (specification).
+ *
+ * Copyright 2007-2013 Adobe Systems Incorporated.
+ *
+ * This software, and all works of authorship, whether in source or
+ * object code form as indicated by the copyright notice(s) included
+ * herein (collectively, the "Work") is made available, and may only be
+ * used, modified, and distributed under the FreeType Project License,
+ * LICENSE.TXT. Additionally, subject to the terms and conditions of the
+ * FreeType Project License, each contributor to the Work hereby grants
+ * to any individual or legal entity exercising permissions granted by
+ * the FreeType Project License and this section (hereafter, "You" or
+ * "Your") a perpetual, worldwide, non-exclusive, no-charge,
+ * royalty-free, irrevocable (except as stated in this section) patent
+ * license to make, have made, use, offer to sell, sell, import, and
+ * otherwise transfer the Work, where such license applies only to those
+ * patent claims licensable by such contributor that are necessarily
+ * infringed by their contribution(s) alone or by combination of their
+ * contribution(s) with the Work to which such contribution(s) was
+ * submitted. If You institute patent litigation against any entity
+ * (including a cross-claim or counterclaim in a lawsuit) alleging that
+ * the Work or a contribution incorporated within the Work constitutes
+ * direct or contributory patent infringement, then any patent licenses
+ * granted to You under this License for that Work shall terminate as of
+ * the date such litigation is filed.
+ *
+ * By using, modifying, or distributing the Work you indicate that you
+ * have read and understood the terms and conditions of the
+ * FreeType Project License as well as those provided in this section,
+ * and you accept them fully.
+ *
+ */
#ifndef PSARRST_H_
diff --git a/thirdparty/freetype/src/psaux/psaux.c b/thirdparty/freetype/src/psaux/psaux.c
index fb447fcdbb..1db0462551 100644
--- a/thirdparty/freetype/src/psaux/psaux.c
+++ b/thirdparty/freetype/src/psaux/psaux.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* psaux.c */
-/* */
-/* FreeType auxiliary PostScript driver component (body only). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * psaux.c
+ *
+ * FreeType auxiliary PostScript driver component (body only).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#define FT_MAKE_OPTION_SINGLE_OBJECT
diff --git a/thirdparty/freetype/src/psaux/psauxerr.h b/thirdparty/freetype/src/psaux/psauxerr.h
index cc33fd2eea..523e1886c2 100644
--- a/thirdparty/freetype/src/psaux/psauxerr.h
+++ b/thirdparty/freetype/src/psaux/psauxerr.h
@@ -1,27 +1,27 @@
-/***************************************************************************/
-/* */
-/* psauxerr.h */
-/* */
-/* PS auxiliary module error codes (specification only). */
-/* */
-/* Copyright 2001-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* This file is used to define the PS auxiliary module error enumeration */
- /* constants. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * psauxerr.h
+ *
+ * PS auxiliary module error codes (specification only).
+ *
+ * Copyright (C) 2001-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * This file is used to define the PS auxiliary module error enumeration
+ * constants.
+ *
+ */
#ifndef PSAUXERR_H_
#define PSAUXERR_H_
diff --git a/thirdparty/freetype/src/psaux/psauxmod.c b/thirdparty/freetype/src/psaux/psauxmod.c
index ee497085cc..5df8e69056 100644
--- a/thirdparty/freetype/src/psaux/psauxmod.c
+++ b/thirdparty/freetype/src/psaux/psauxmod.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* psauxmod.c */
-/* */
-/* FreeType auxiliary PostScript module implementation (body). */
-/* */
-/* Copyright 2000-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * psauxmod.c
+ *
+ * FreeType auxiliary PostScript module implementation (body).
+ *
+ * Copyright (C) 2000-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
diff --git a/thirdparty/freetype/src/psaux/psauxmod.h b/thirdparty/freetype/src/psaux/psauxmod.h
index f30978f022..a0eda0bfc0 100644
--- a/thirdparty/freetype/src/psaux/psauxmod.h
+++ b/thirdparty/freetype/src/psaux/psauxmod.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* psauxmod.h */
-/* */
-/* FreeType auxiliary PostScript module implementation (specification). */
-/* */
-/* Copyright 2000-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * psauxmod.h
+ *
+ * FreeType auxiliary PostScript module implementation (specification).
+ *
+ * Copyright (C) 2000-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef PSAUXMOD_H_
@@ -28,10 +28,6 @@
FT_BEGIN_HEADER
-#ifdef FT_CONFIG_OPTION_PIC
-#error "this module does not support PIC yet"
-#endif
-
FT_CALLBACK_TABLE
const CFF_Builder_FuncsRec cff_builder_funcs;
diff --git a/thirdparty/freetype/src/psaux/psblues.c b/thirdparty/freetype/src/psaux/psblues.c
index ae39d03c77..89738ce474 100644
--- a/thirdparty/freetype/src/psaux/psblues.c
+++ b/thirdparty/freetype/src/psaux/psblues.c
@@ -1,39 +1,39 @@
-/***************************************************************************/
-/* */
-/* psblues.c */
-/* */
-/* Adobe's code for handling Blue Zones (body). */
-/* */
-/* Copyright 2009-2014 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * psblues.c
+ *
+ * Adobe's code for handling Blue Zones (body).
+ *
+ * Copyright 2009-2014 Adobe Systems Incorporated.
+ *
+ * This software, and all works of authorship, whether in source or
+ * object code form as indicated by the copyright notice(s) included
+ * herein (collectively, the "Work") is made available, and may only be
+ * used, modified, and distributed under the FreeType Project License,
+ * LICENSE.TXT. Additionally, subject to the terms and conditions of the
+ * FreeType Project License, each contributor to the Work hereby grants
+ * to any individual or legal entity exercising permissions granted by
+ * the FreeType Project License and this section (hereafter, "You" or
+ * "Your") a perpetual, worldwide, non-exclusive, no-charge,
+ * royalty-free, irrevocable (except as stated in this section) patent
+ * license to make, have made, use, offer to sell, sell, import, and
+ * otherwise transfer the Work, where such license applies only to those
+ * patent claims licensable by such contributor that are necessarily
+ * infringed by their contribution(s) alone or by combination of their
+ * contribution(s) with the Work to which such contribution(s) was
+ * submitted. If You institute patent litigation against any entity
+ * (including a cross-claim or counterclaim in a lawsuit) alleging that
+ * the Work or a contribution incorporated within the Work constitutes
+ * direct or contributory patent infringement, then any patent licenses
+ * granted to You under this License for that Work shall terminate as of
+ * the date such litigation is filed.
+ *
+ * By using, modifying, or distributing the Work you indicate that you
+ * have read and understood the terms and conditions of the
+ * FreeType Project License as well as those provided in this section,
+ * and you accept them fully.
+ *
+ */
#include "psft.h"
@@ -44,14 +44,14 @@
#include "psfont.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_cf2blues
+#define FT_COMPONENT cf2blues
/*
@@ -452,13 +452,13 @@
* zones in the same pass (see `BlueLock'). If a hint is captured,
* return true and position the edge(s) in one of 3 ways:
*
- * 1) If `BlueScale' suppresses overshoot, position the captured edge
- * at the flat edge of the zone.
- * 2) If overshoot is not suppressed and `BlueShift' requires
- * overshoot, position the captured edge a minimum of 1 device pixel
- * from the flat edge.
- * 3) If overshoot is not suppressed or required, position the captured
- * edge at the nearest device pixel.
+ * 1) If `BlueScale' suppresses overshoot, position the captured edge
+ * at the flat edge of the zone.
+ * 2) If overshoot is not suppressed and `BlueShift' requires
+ * overshoot, position the captured edge a minimum of 1 device pixel
+ * from the flat edge.
+ * 3) If overshoot is not suppressed or required, position the captured
+ * edge at the nearest device pixel.
*
*/
FT_LOCAL_DEF( FT_Bool )
diff --git a/thirdparty/freetype/src/psaux/psblues.h b/thirdparty/freetype/src/psaux/psblues.h
index 25ef6849c7..55fb88ecdd 100644
--- a/thirdparty/freetype/src/psaux/psblues.h
+++ b/thirdparty/freetype/src/psaux/psblues.h
@@ -1,39 +1,39 @@
-/***************************************************************************/
-/* */
-/* psblues.h */
-/* */
-/* Adobe's code for handling Blue Zones (specification). */
-/* */
-/* Copyright 2009-2013 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * psblues.h
+ *
+ * Adobe's code for handling Blue Zones (specification).
+ *
+ * Copyright 2009-2013 Adobe Systems Incorporated.
+ *
+ * This software, and all works of authorship, whether in source or
+ * object code form as indicated by the copyright notice(s) included
+ * herein (collectively, the "Work") is made available, and may only be
+ * used, modified, and distributed under the FreeType Project License,
+ * LICENSE.TXT. Additionally, subject to the terms and conditions of the
+ * FreeType Project License, each contributor to the Work hereby grants
+ * to any individual or legal entity exercising permissions granted by
+ * the FreeType Project License and this section (hereafter, "You" or
+ * "Your") a perpetual, worldwide, non-exclusive, no-charge,
+ * royalty-free, irrevocable (except as stated in this section) patent
+ * license to make, have made, use, offer to sell, sell, import, and
+ * otherwise transfer the Work, where such license applies only to those
+ * patent claims licensable by such contributor that are necessarily
+ * infringed by their contribution(s) alone or by combination of their
+ * contribution(s) with the Work to which such contribution(s) was
+ * submitted. If You institute patent litigation against any entity
+ * (including a cross-claim or counterclaim in a lawsuit) alleging that
+ * the Work or a contribution incorporated within the Work constitutes
+ * direct or contributory patent infringement, then any patent licenses
+ * granted to You under this License for that Work shall terminate as of
+ * the date such litigation is filed.
+ *
+ * By using, modifying, or distributing the Work you indicate that you
+ * have read and understood the terms and conditions of the
+ * FreeType Project License as well as those provided in this section,
+ * and you accept them fully.
+ *
+ */
/*
diff --git a/thirdparty/freetype/src/psaux/psconv.c b/thirdparty/freetype/src/psaux/psconv.c
index a03385000d..c88761681c 100644
--- a/thirdparty/freetype/src/psaux/psconv.c
+++ b/thirdparty/freetype/src/psaux/psconv.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* psconv.c */
-/* */
-/* Some convenience conversions (body). */
-/* */
-/* Copyright 2006-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * psconv.c
+ *
+ * Some convenience conversions (body).
+ *
+ * Copyright (C) 2006-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -24,14 +24,14 @@
#include "psauxerr.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_psconv
+#define FT_COMPONENT psconv
/* The following array is used by various functions to quickly convert */
diff --git a/thirdparty/freetype/src/psaux/psconv.h b/thirdparty/freetype/src/psaux/psconv.h
index d643ffcfc2..6b24bf6fc9 100644
--- a/thirdparty/freetype/src/psaux/psconv.h
+++ b/thirdparty/freetype/src/psaux/psconv.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* psconv.h */
-/* */
-/* Some convenience conversions (specification). */
-/* */
-/* Copyright 2006-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * psconv.h
+ *
+ * Some convenience conversions (specification).
+ *
+ * Copyright (C) 2006-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef PSCONV_H_
diff --git a/thirdparty/freetype/src/psaux/pserror.c b/thirdparty/freetype/src/psaux/pserror.c
index 9169e5222d..98cebcf74d 100644
--- a/thirdparty/freetype/src/psaux/pserror.c
+++ b/thirdparty/freetype/src/psaux/pserror.c
@@ -1,39 +1,39 @@
-/***************************************************************************/
-/* */
-/* pserror.c */
-/* */
-/* Adobe's code for error handling (body). */
-/* */
-/* Copyright 2006-2013 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * pserror.c
+ *
+ * Adobe's code for error handling (body).
+ *
+ * Copyright 2006-2013 Adobe Systems Incorporated.
+ *
+ * This software, and all works of authorship, whether in source or
+ * object code form as indicated by the copyright notice(s) included
+ * herein (collectively, the "Work") is made available, and may only be
+ * used, modified, and distributed under the FreeType Project License,
+ * LICENSE.TXT. Additionally, subject to the terms and conditions of the
+ * FreeType Project License, each contributor to the Work hereby grants
+ * to any individual or legal entity exercising permissions granted by
+ * the FreeType Project License and this section (hereafter, "You" or
+ * "Your") a perpetual, worldwide, non-exclusive, no-charge,
+ * royalty-free, irrevocable (except as stated in this section) patent
+ * license to make, have made, use, offer to sell, sell, import, and
+ * otherwise transfer the Work, where such license applies only to those
+ * patent claims licensable by such contributor that are necessarily
+ * infringed by their contribution(s) alone or by combination of their
+ * contribution(s) with the Work to which such contribution(s) was
+ * submitted. If You institute patent litigation against any entity
+ * (including a cross-claim or counterclaim in a lawsuit) alleging that
+ * the Work or a contribution incorporated within the Work constitutes
+ * direct or contributory patent infringement, then any patent licenses
+ * granted to You under this License for that Work shall terminate as of
+ * the date such litigation is filed.
+ *
+ * By using, modifying, or distributing the Work you indicate that you
+ * have read and understood the terms and conditions of the
+ * FreeType Project License as well as those provided in this section,
+ * and you accept them fully.
+ *
+ */
#include "psft.h"
diff --git a/thirdparty/freetype/src/psaux/pserror.h b/thirdparty/freetype/src/psaux/pserror.h
index 13d52062bf..b2156b3318 100644
--- a/thirdparty/freetype/src/psaux/pserror.h
+++ b/thirdparty/freetype/src/psaux/pserror.h
@@ -1,39 +1,39 @@
-/***************************************************************************/
-/* */
-/* pserror.h */
-/* */
-/* Adobe's code for error handling (specification). */
-/* */
-/* Copyright 2006-2013 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * pserror.h
+ *
+ * Adobe's code for error handling (specification).
+ *
+ * Copyright 2006-2013 Adobe Systems Incorporated.
+ *
+ * This software, and all works of authorship, whether in source or
+ * object code form as indicated by the copyright notice(s) included
+ * herein (collectively, the "Work") is made available, and may only be
+ * used, modified, and distributed under the FreeType Project License,
+ * LICENSE.TXT. Additionally, subject to the terms and conditions of the
+ * FreeType Project License, each contributor to the Work hereby grants
+ * to any individual or legal entity exercising permissions granted by
+ * the FreeType Project License and this section (hereafter, "You" or
+ * "Your") a perpetual, worldwide, non-exclusive, no-charge,
+ * royalty-free, irrevocable (except as stated in this section) patent
+ * license to make, have made, use, offer to sell, sell, import, and
+ * otherwise transfer the Work, where such license applies only to those
+ * patent claims licensable by such contributor that are necessarily
+ * infringed by their contribution(s) alone or by combination of their
+ * contribution(s) with the Work to which such contribution(s) was
+ * submitted. If You institute patent litigation against any entity
+ * (including a cross-claim or counterclaim in a lawsuit) alleging that
+ * the Work or a contribution incorporated within the Work constitutes
+ * direct or contributory patent infringement, then any patent licenses
+ * granted to You under this License for that Work shall terminate as of
+ * the date such litigation is filed.
+ *
+ * By using, modifying, or distributing the Work you indicate that you
+ * have read and understood the terms and conditions of the
+ * FreeType Project License as well as those provided in this section,
+ * and you accept them fully.
+ *
+ */
#ifndef PSERROR_H_
diff --git a/thirdparty/freetype/src/psaux/psfixed.h b/thirdparty/freetype/src/psaux/psfixed.h
index 219589e7fc..fd3460f34a 100644
--- a/thirdparty/freetype/src/psaux/psfixed.h
+++ b/thirdparty/freetype/src/psaux/psfixed.h
@@ -1,39 +1,39 @@
-/***************************************************************************/
-/* */
-/* psfixed.h */
-/* */
-/* Adobe's code for Fixed Point Mathematics (specification only). */
-/* */
-/* Copyright 2007-2013 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * psfixed.h
+ *
+ * Adobe's code for Fixed Point Mathematics (specification only).
+ *
+ * Copyright 2007-2013 Adobe Systems Incorporated.
+ *
+ * This software, and all works of authorship, whether in source or
+ * object code form as indicated by the copyright notice(s) included
+ * herein (collectively, the "Work") is made available, and may only be
+ * used, modified, and distributed under the FreeType Project License,
+ * LICENSE.TXT. Additionally, subject to the terms and conditions of the
+ * FreeType Project License, each contributor to the Work hereby grants
+ * to any individual or legal entity exercising permissions granted by
+ * the FreeType Project License and this section (hereafter, "You" or
+ * "Your") a perpetual, worldwide, non-exclusive, no-charge,
+ * royalty-free, irrevocable (except as stated in this section) patent
+ * license to make, have made, use, offer to sell, sell, import, and
+ * otherwise transfer the Work, where such license applies only to those
+ * patent claims licensable by such contributor that are necessarily
+ * infringed by their contribution(s) alone or by combination of their
+ * contribution(s) with the Work to which such contribution(s) was
+ * submitted. If You institute patent litigation against any entity
+ * (including a cross-claim or counterclaim in a lawsuit) alleging that
+ * the Work or a contribution incorporated within the Work constitutes
+ * direct or contributory patent infringement, then any patent licenses
+ * granted to You under this License for that Work shall terminate as of
+ * the date such litigation is filed.
+ *
+ * By using, modifying, or distributing the Work you indicate that you
+ * have read and understood the terms and conditions of the
+ * FreeType Project License as well as those provided in this section,
+ * and you accept them fully.
+ *
+ */
#ifndef PSFIXED_H_
diff --git a/thirdparty/freetype/src/psaux/psfont.c b/thirdparty/freetype/src/psaux/psfont.c
index dde67a739d..bb5faa38f5 100644
--- a/thirdparty/freetype/src/psaux/psfont.c
+++ b/thirdparty/freetype/src/psaux/psfont.c
@@ -1,39 +1,39 @@
-/***************************************************************************/
-/* */
-/* psfont.c */
-/* */
-/* Adobe's code for font instances (body). */
-/* */
-/* Copyright 2007-2014 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * psfont.c
+ *
+ * Adobe's code for font instances (body).
+ *
+ * Copyright 2007-2014 Adobe Systems Incorporated.
+ *
+ * This software, and all works of authorship, whether in source or
+ * object code form as indicated by the copyright notice(s) included
+ * herein (collectively, the "Work") is made available, and may only be
+ * used, modified, and distributed under the FreeType Project License,
+ * LICENSE.TXT. Additionally, subject to the terms and conditions of the
+ * FreeType Project License, each contributor to the Work hereby grants
+ * to any individual or legal entity exercising permissions granted by
+ * the FreeType Project License and this section (hereafter, "You" or
+ * "Your") a perpetual, worldwide, non-exclusive, no-charge,
+ * royalty-free, irrevocable (except as stated in this section) patent
+ * license to make, have made, use, offer to sell, sell, import, and
+ * otherwise transfer the Work, where such license applies only to those
+ * patent claims licensable by such contributor that are necessarily
+ * infringed by their contribution(s) alone or by combination of their
+ * contribution(s) with the Work to which such contribution(s) was
+ * submitted. If You institute patent litigation against any entity
+ * (including a cross-claim or counterclaim in a lawsuit) alleging that
+ * the Work or a contribution incorporated within the Work constitutes
+ * direct or contributory patent infringement, then any patent licenses
+ * granted to You under this License for that Work shall terminate as of
+ * the date such litigation is filed.
+ *
+ * By using, modifying, or distributing the Work you indicate that you
+ * have read and understood the terms and conditions of the
+ * FreeType Project License as well as those provided in this section,
+ * and you accept them fully.
+ *
+ */
#include <ft2build.h>
@@ -331,7 +331,7 @@
}
/* copy hinted flag on each call */
- font->hinted = (FT_Bool)( font->renderingFlags & CF2_FlagsHinted );
+ font->hinted = FT_BOOL( font->renderingFlags & CF2_FlagsHinted );
/* determine if transform has changed; */
/* include Fontmatrix but ignore translation */
@@ -366,7 +366,7 @@
if ( font->stemDarkened != ( font->renderingFlags & CF2_FlagsDarkened ) )
{
font->stemDarkened =
- (FT_Bool)( font->renderingFlags & CF2_FlagsDarkened );
+ FT_BOOL( font->renderingFlags & CF2_FlagsDarkened );
/* blue zones depend on darkened flag */
needExtraSetup = TRUE;
diff --git a/thirdparty/freetype/src/psaux/psfont.h b/thirdparty/freetype/src/psaux/psfont.h
index e611ac4bdc..8fbacbb6e3 100644
--- a/thirdparty/freetype/src/psaux/psfont.h
+++ b/thirdparty/freetype/src/psaux/psfont.h
@@ -1,39 +1,39 @@
-/***************************************************************************/
-/* */
-/* psfont.h */
-/* */
-/* Adobe's code for font instances (specification). */
-/* */
-/* Copyright 2007-2013 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * psfont.h
+ *
+ * Adobe's code for font instances (specification).
+ *
+ * Copyright 2007-2013 Adobe Systems Incorporated.
+ *
+ * This software, and all works of authorship, whether in source or
+ * object code form as indicated by the copyright notice(s) included
+ * herein (collectively, the "Work") is made available, and may only be
+ * used, modified, and distributed under the FreeType Project License,
+ * LICENSE.TXT. Additionally, subject to the terms and conditions of the
+ * FreeType Project License, each contributor to the Work hereby grants
+ * to any individual or legal entity exercising permissions granted by
+ * the FreeType Project License and this section (hereafter, "You" or
+ * "Your") a perpetual, worldwide, non-exclusive, no-charge,
+ * royalty-free, irrevocable (except as stated in this section) patent
+ * license to make, have made, use, offer to sell, sell, import, and
+ * otherwise transfer the Work, where such license applies only to those
+ * patent claims licensable by such contributor that are necessarily
+ * infringed by their contribution(s) alone or by combination of their
+ * contribution(s) with the Work to which such contribution(s) was
+ * submitted. If You institute patent litigation against any entity
+ * (including a cross-claim or counterclaim in a lawsuit) alleging that
+ * the Work or a contribution incorporated within the Work constitutes
+ * direct or contributory patent infringement, then any patent licenses
+ * granted to You under this License for that Work shall terminate as of
+ * the date such litigation is filed.
+ *
+ * By using, modifying, or distributing the Work you indicate that you
+ * have read and understood the terms and conditions of the
+ * FreeType Project License as well as those provided in this section,
+ * and you accept them fully.
+ *
+ */
#ifndef PSFONT_H_
diff --git a/thirdparty/freetype/src/psaux/psft.c b/thirdparty/freetype/src/psaux/psft.c
index 1f750174a1..54be468343 100644
--- a/thirdparty/freetype/src/psaux/psft.c
+++ b/thirdparty/freetype/src/psaux/psft.c
@@ -1,39 +1,39 @@
-/***************************************************************************/
-/* */
-/* psft.c */
-/* */
-/* FreeType Glue Component to Adobe's Interpreter (body). */
-/* */
-/* Copyright 2013-2014 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * psft.c
+ *
+ * FreeType Glue Component to Adobe's Interpreter (body).
+ *
+ * Copyright 2013-2014 Adobe Systems Incorporated.
+ *
+ * This software, and all works of authorship, whether in source or
+ * object code form as indicated by the copyright notice(s) included
+ * herein (collectively, the "Work") is made available, and may only be
+ * used, modified, and distributed under the FreeType Project License,
+ * LICENSE.TXT. Additionally, subject to the terms and conditions of the
+ * FreeType Project License, each contributor to the Work hereby grants
+ * to any individual or legal entity exercising permissions granted by
+ * the FreeType Project License and this section (hereafter, "You" or
+ * "Your") a perpetual, worldwide, non-exclusive, no-charge,
+ * royalty-free, irrevocable (except as stated in this section) patent
+ * license to make, have made, use, offer to sell, sell, import, and
+ * otherwise transfer the Work, where such license applies only to those
+ * patent claims licensable by such contributor that are necessarily
+ * infringed by their contribution(s) alone or by combination of their
+ * contribution(s) with the Work to which such contribution(s) was
+ * submitted. If You institute patent litigation against any entity
+ * (including a cross-claim or counterclaim in a lawsuit) alleging that
+ * the Work or a contribution incorporated within the Work constitutes
+ * direct or contributory patent infringement, then any patent licenses
+ * granted to You under this License for that Work shall terminate as of
+ * the date such litigation is filed.
+ *
+ * By using, modifying, or distributing the Work you indicate that you
+ * have read and understood the terms and conditions of the
+ * FreeType Project License as well as those provided in this section,
+ * and you accept them fully.
+ *
+ */
#include "psft.h"
@@ -120,12 +120,12 @@
}
- /********************************************/
- /* */
- /* functions for handling client outline; */
- /* FreeType uses coordinates in 26.6 format */
- /* */
- /********************************************/
+ /*********************************************
+ *
+ * functions for handling client outline;
+ * FreeType uses coordinates in 26.6 format
+ *
+ */
static void
cf2_builder_moveTo( CF2_OutlineCallbacks callbacks,
@@ -767,13 +767,14 @@
cf2_freeT1SeacComponent( PS_Decoder* decoder,
CF2_Buffer buf )
{
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+
T1_Face face;
FT_Data data;
FT_ASSERT( decoder );
-#ifdef FT_CONFIG_OPTION_INCREMENTAL
face = (T1_Face)decoder->builder.face;
data.pointer = buf->start;
@@ -783,7 +784,13 @@
face->root.internal->incremental_interface->funcs->free_glyph_data(
face->root.internal->incremental_interface->object,
&data );
-#endif /* FT_CONFIG_OPTION_INCREMENTAL */
+
+#else /* !FT_CONFIG_OPTION_INCREMENTAL */
+
+ FT_UNUSED( decoder );
+ FT_UNUSED( buf );
+
+#endif /* !FT_CONFIG_OPTION_INCREMENTAL */
}
diff --git a/thirdparty/freetype/src/psaux/psft.h b/thirdparty/freetype/src/psaux/psft.h
index ab172110bb..4c930f0d73 100644
--- a/thirdparty/freetype/src/psaux/psft.h
+++ b/thirdparty/freetype/src/psaux/psft.h
@@ -1,39 +1,39 @@
-/***************************************************************************/
-/* */
-/* psft.h */
-/* */
-/* FreeType Glue Component to Adobe's Interpreter (specification). */
-/* */
-/* Copyright 2013 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * psft.h
+ *
+ * FreeType Glue Component to Adobe's Interpreter (specification).
+ *
+ * Copyright 2013 Adobe Systems Incorporated.
+ *
+ * This software, and all works of authorship, whether in source or
+ * object code form as indicated by the copyright notice(s) included
+ * herein (collectively, the "Work") is made available, and may only be
+ * used, modified, and distributed under the FreeType Project License,
+ * LICENSE.TXT. Additionally, subject to the terms and conditions of the
+ * FreeType Project License, each contributor to the Work hereby grants
+ * to any individual or legal entity exercising permissions granted by
+ * the FreeType Project License and this section (hereafter, "You" or
+ * "Your") a perpetual, worldwide, non-exclusive, no-charge,
+ * royalty-free, irrevocable (except as stated in this section) patent
+ * license to make, have made, use, offer to sell, sell, import, and
+ * otherwise transfer the Work, where such license applies only to those
+ * patent claims licensable by such contributor that are necessarily
+ * infringed by their contribution(s) alone or by combination of their
+ * contribution(s) with the Work to which such contribution(s) was
+ * submitted. If You institute patent litigation against any entity
+ * (including a cross-claim or counterclaim in a lawsuit) alleging that
+ * the Work or a contribution incorporated within the Work constitutes
+ * direct or contributory patent infringement, then any patent licenses
+ * granted to You under this License for that Work shall terminate as of
+ * the date such litigation is filed.
+ *
+ * By using, modifying, or distributing the Work you indicate that you
+ * have read and understood the terms and conditions of the
+ * FreeType Project License as well as those provided in this section,
+ * and you accept them fully.
+ *
+ */
#ifndef PSFT_H_
diff --git a/thirdparty/freetype/src/psaux/psglue.h b/thirdparty/freetype/src/psaux/psglue.h
index 5545e12a5b..022aafbfca 100644
--- a/thirdparty/freetype/src/psaux/psglue.h
+++ b/thirdparty/freetype/src/psaux/psglue.h
@@ -1,39 +1,39 @@
-/***************************************************************************/
-/* */
-/* psglue.h */
-/* */
-/* Adobe's code for shared stuff (specification only). */
-/* */
-/* Copyright 2007-2013 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * psglue.h
+ *
+ * Adobe's code for shared stuff (specification only).
+ *
+ * Copyright 2007-2013 Adobe Systems Incorporated.
+ *
+ * This software, and all works of authorship, whether in source or
+ * object code form as indicated by the copyright notice(s) included
+ * herein (collectively, the "Work") is made available, and may only be
+ * used, modified, and distributed under the FreeType Project License,
+ * LICENSE.TXT. Additionally, subject to the terms and conditions of the
+ * FreeType Project License, each contributor to the Work hereby grants
+ * to any individual or legal entity exercising permissions granted by
+ * the FreeType Project License and this section (hereafter, "You" or
+ * "Your") a perpetual, worldwide, non-exclusive, no-charge,
+ * royalty-free, irrevocable (except as stated in this section) patent
+ * license to make, have made, use, offer to sell, sell, import, and
+ * otherwise transfer the Work, where such license applies only to those
+ * patent claims licensable by such contributor that are necessarily
+ * infringed by their contribution(s) alone or by combination of their
+ * contribution(s) with the Work to which such contribution(s) was
+ * submitted. If You institute patent litigation against any entity
+ * (including a cross-claim or counterclaim in a lawsuit) alleging that
+ * the Work or a contribution incorporated within the Work constitutes
+ * direct or contributory patent infringement, then any patent licenses
+ * granted to You under this License for that Work shall terminate as of
+ * the date such litigation is filed.
+ *
+ * By using, modifying, or distributing the Work you indicate that you
+ * have read and understood the terms and conditions of the
+ * FreeType Project License as well as those provided in this section,
+ * and you accept them fully.
+ *
+ */
#ifndef PSGLUE_H_
diff --git a/thirdparty/freetype/src/psaux/pshints.c b/thirdparty/freetype/src/psaux/pshints.c
index 3615196425..1cbecd2b19 100644
--- a/thirdparty/freetype/src/psaux/pshints.c
+++ b/thirdparty/freetype/src/psaux/pshints.c
@@ -1,39 +1,39 @@
-/***************************************************************************/
-/* */
-/* pshints.c */
-/* */
-/* Adobe's code for handling CFF hints (body). */
-/* */
-/* Copyright 2007-2014 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * pshints.c
+ *
+ * Adobe's code for handling CFF hints (body).
+ *
+ * Copyright 2007-2014 Adobe Systems Incorporated.
+ *
+ * This software, and all works of authorship, whether in source or
+ * object code form as indicated by the copyright notice(s) included
+ * herein (collectively, the "Work") is made available, and may only be
+ * used, modified, and distributed under the FreeType Project License,
+ * LICENSE.TXT. Additionally, subject to the terms and conditions of the
+ * FreeType Project License, each contributor to the Work hereby grants
+ * to any individual or legal entity exercising permissions granted by
+ * the FreeType Project License and this section (hereafter, "You" or
+ * "Your") a perpetual, worldwide, non-exclusive, no-charge,
+ * royalty-free, irrevocable (except as stated in this section) patent
+ * license to make, have made, use, offer to sell, sell, import, and
+ * otherwise transfer the Work, where such license applies only to those
+ * patent claims licensable by such contributor that are necessarily
+ * infringed by their contribution(s) alone or by combination of their
+ * contribution(s) with the Work to which such contribution(s) was
+ * submitted. If You institute patent litigation against any entity
+ * (including a cross-claim or counterclaim in a lawsuit) alleging that
+ * the Work or a contribution incorporated within the Work constitutes
+ * direct or contributory patent infringement, then any patent licenses
+ * granted to You under this License for that Work shall terminate as of
+ * the date such litigation is filed.
+ *
+ * By using, modifying, or distributing the Work you indicate that you
+ * have read and understood the terms and conditions of the
+ * FreeType Project License as well as those provided in this section,
+ * and you accept them fully.
+ *
+ */
#include "psft.h"
@@ -45,14 +45,14 @@
#include "psintrp.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_cf2hints
+#define FT_COMPONENT cf2hints
typedef struct CF2_HintMoveRec_
@@ -217,52 +217,49 @@
FT_LOCAL_DEF( FT_Bool )
cf2_hint_isValid( const CF2_Hint hint )
{
- return (FT_Bool)( hint->flags != 0 );
+ return FT_BOOL( hint->flags );
}
static FT_Bool
cf2_hint_isPair( const CF2_Hint hint )
{
- return (FT_Bool)( ( hint->flags &
- ( CF2_PairBottom | CF2_PairTop ) ) != 0 );
+ return FT_BOOL( hint->flags & ( CF2_PairBottom | CF2_PairTop ) );
}
static FT_Bool
cf2_hint_isPairTop( const CF2_Hint hint )
{
- return (FT_Bool)( ( hint->flags & CF2_PairTop ) != 0 );
+ return FT_BOOL( hint->flags & CF2_PairTop );
}
FT_LOCAL_DEF( FT_Bool )
cf2_hint_isTop( const CF2_Hint hint )
{
- return (FT_Bool)( ( hint->flags &
- ( CF2_PairTop | CF2_GhostTop ) ) != 0 );
+ return FT_BOOL( hint->flags & ( CF2_PairTop | CF2_GhostTop ) );
}
FT_LOCAL_DEF( FT_Bool )
cf2_hint_isBottom( const CF2_Hint hint )
{
- return (FT_Bool)( ( hint->flags &
- ( CF2_PairBottom | CF2_GhostBottom ) ) != 0 );
+ return FT_BOOL( hint->flags & ( CF2_PairBottom | CF2_GhostBottom ) );
}
static FT_Bool
cf2_hint_isLocked( const CF2_Hint hint )
{
- return (FT_Bool)( ( hint->flags & CF2_Locked ) != 0 );
+ return FT_BOOL( hint->flags & CF2_Locked );
}
static FT_Bool
cf2_hint_isSynthetic( const CF2_Hint hint )
{
- return (FT_Bool)( ( hint->flags & CF2_Synthetic ) != 0 );
+ return FT_BOOL( hint->flags & CF2_Synthetic );
}
@@ -334,7 +331,7 @@
cf2_hintmap_map( CF2_HintMap hintmap,
CF2_Fixed csCoord )
{
- if ( hintmap->count == 0 || ! hintmap->hinted )
+ if ( hintmap->count == 0 || !hintmap->hinted )
{
/* there are no hints; use uniform scale and zero offset */
return FT_MulFix( csCoord, hintmap->scale );
@@ -497,7 +494,7 @@
{
move = moveDown;
/* true if non-optimum move */
- saveEdge = (FT_Bool)( moveUp < -moveDown );
+ saveEdge = FT_BOOL( moveUp < -moveDown );
}
else
{
@@ -1025,10 +1022,10 @@
}
}
- FT_TRACE6(( initialMap ? "flags: [p]air [g]host [t]op "
- "[b]ottom [L]ocked [S]ynthetic\n"
- "Initial hintmap\n"
- : "Hints:\n" ));
+ FT_TRACE6(( "%s\n", initialMap ? "flags: [p]air [g]host [t]op"
+ " [b]ottom [L]ocked [S]ynthetic\n"
+ "Initial hintmap"
+ : "Hints:" ));
cf2_hintmap_dump( hintmap );
/*
@@ -1215,7 +1212,7 @@
* (`u').
*
* See notation in
- * http://softsurfer.com/Archive/algorithm_0104/algorithm_0104B.htm.
+ * http://geomalgorithms.com/a05-_intersect-1.html.
* Calculations are done in 16.16, but must handle the squaring of
* line lengths in character space. We scale all vectors by 1/32 to
* avoid overflow. This allows values up to 4095 to be squared. The
diff --git a/thirdparty/freetype/src/psaux/pshints.h b/thirdparty/freetype/src/psaux/pshints.h
index 92e37e98ae..31a8230364 100644
--- a/thirdparty/freetype/src/psaux/pshints.h
+++ b/thirdparty/freetype/src/psaux/pshints.h
@@ -1,39 +1,39 @@
-/***************************************************************************/
-/* */
-/* pshints.h */
-/* */
-/* Adobe's code for handling CFF hints (body). */
-/* */
-/* Copyright 2007-2013 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * pshints.h
+ *
+ * Adobe's code for handling CFF hints (body).
+ *
+ * Copyright 2007-2013 Adobe Systems Incorporated.
+ *
+ * This software, and all works of authorship, whether in source or
+ * object code form as indicated by the copyright notice(s) included
+ * herein (collectively, the "Work") is made available, and may only be
+ * used, modified, and distributed under the FreeType Project License,
+ * LICENSE.TXT. Additionally, subject to the terms and conditions of the
+ * FreeType Project License, each contributor to the Work hereby grants
+ * to any individual or legal entity exercising permissions granted by
+ * the FreeType Project License and this section (hereafter, "You" or
+ * "Your") a perpetual, worldwide, non-exclusive, no-charge,
+ * royalty-free, irrevocable (except as stated in this section) patent
+ * license to make, have made, use, offer to sell, sell, import, and
+ * otherwise transfer the Work, where such license applies only to those
+ * patent claims licensable by such contributor that are necessarily
+ * infringed by their contribution(s) alone or by combination of their
+ * contribution(s) with the Work to which such contribution(s) was
+ * submitted. If You institute patent litigation against any entity
+ * (including a cross-claim or counterclaim in a lawsuit) alleging that
+ * the Work or a contribution incorporated within the Work constitutes
+ * direct or contributory patent infringement, then any patent licenses
+ * granted to You under this License for that Work shall terminate as of
+ * the date such litigation is filed.
+ *
+ * By using, modifying, or distributing the Work you indicate that you
+ * have read and understood the terms and conditions of the
+ * FreeType Project License as well as those provided in this section,
+ * and you accept them fully.
+ *
+ */
#ifndef PSHINT_H_
diff --git a/thirdparty/freetype/src/psaux/psintrp.c b/thirdparty/freetype/src/psaux/psintrp.c
index da5a8dad1d..e2f3accdd5 100644
--- a/thirdparty/freetype/src/psaux/psintrp.c
+++ b/thirdparty/freetype/src/psaux/psintrp.c
@@ -1,39 +1,39 @@
-/***************************************************************************/
-/* */
-/* psintrp.c */
-/* */
-/* Adobe's CFF Interpreter (body). */
-/* */
-/* Copyright 2007-2014 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * psintrp.c
+ *
+ * Adobe's CFF Interpreter (body).
+ *
+ * Copyright 2007-2014 Adobe Systems Incorporated.
+ *
+ * This software, and all works of authorship, whether in source or
+ * object code form as indicated by the copyright notice(s) included
+ * herein (collectively, the "Work") is made available, and may only be
+ * used, modified, and distributed under the FreeType Project License,
+ * LICENSE.TXT. Additionally, subject to the terms and conditions of the
+ * FreeType Project License, each contributor to the Work hereby grants
+ * to any individual or legal entity exercising permissions granted by
+ * the FreeType Project License and this section (hereafter, "You" or
+ * "Your") a perpetual, worldwide, non-exclusive, no-charge,
+ * royalty-free, irrevocable (except as stated in this section) patent
+ * license to make, have made, use, offer to sell, sell, import, and
+ * otherwise transfer the Work, where such license applies only to those
+ * patent claims licensable by such contributor that are necessarily
+ * infringed by their contribution(s) alone or by combination of their
+ * contribution(s) with the Work to which such contribution(s) was
+ * submitted. If You institute patent litigation against any entity
+ * (including a cross-claim or counterclaim in a lawsuit) alleging that
+ * the Work or a contribution incorporated within the Work constitutes
+ * direct or contributory patent infringement, then any patent licenses
+ * granted to You under this License for that Work shall terminate as of
+ * the date such litigation is filed.
+ *
+ * By using, modifying, or distributing the Work you indicate that you
+ * have read and understood the terms and conditions of the
+ * FreeType Project License as well as those provided in this section,
+ * and you accept them fully.
+ *
+ */
#include "psft.h"
@@ -52,14 +52,14 @@
#include "t1decode.h" /* for t1 seac */
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_cf2interp
+#define FT_COMPONENT cf2interp
FT_LOCAL_DEF( void )
@@ -287,7 +287,7 @@
{
CF2_UInt i;
CF2_UInt count = cf2_stack_count( opStack );
- FT_Bool hasWidthArg = (FT_Bool)( count & 1 );
+ FT_Bool hasWidthArg = FT_BOOL( count & 1 );
/* variable accumulates delta values from operand stack */
CF2_Fixed position = hintOffset;
@@ -364,7 +364,7 @@
if ( doConditionalLastRead )
{
- FT_Bool lastIsX = (FT_Bool)(
+ FT_Bool lastIsX = FT_BOOL(
cf2_fixedAbs( SUB_INT32( vals[10], *curX ) ) >
cf2_fixedAbs( SUB_INT32( vals[11], *curY ) ) );
CF2_Fixed lastVal = cf2_stack_getReal( opStack, idx );
@@ -612,14 +612,14 @@
cf2_arrstack_setCount( &subrStack, CF2_MAX_SUBR + 1 );
charstring = (CF2_Buffer)cf2_arrstack_getBuffer( &subrStack );
- *charstring = *buf; /* structure copy */
-
- charstringIndex = 0; /* entry is valid now */
/* catch errors so far */
if ( *error )
goto exit;
+ *charstring = *buf; /* structure copy */
+ charstringIndex = 0; /* entry is valid now */
+
/* main interpreter loop */
while ( 1 )
{
@@ -663,6 +663,7 @@
/* Skip outline commands first time round. */
/* `endchar' will trigger initial hintmap build */
/* and rewind the charstring. */
+ FT_TRACE4(( " <outline command skipped>\n" ));
cf2_stack_clear( opStack );
continue;
}
@@ -775,7 +776,8 @@
case cf2_cmdHSTEMHM:
case cf2_cmdHSTEM:
- FT_TRACE4(( op1 == cf2_cmdHSTEMHM ? " hstemhm\n" : " hstem\n" ));
+ FT_TRACE4(( "%s\n", op1 == cf2_cmdHSTEMHM ? " hstemhm"
+ : " hstem" ));
if ( !font->isT1 )
{
@@ -805,7 +807,8 @@
case cf2_cmdVSTEMHM:
case cf2_cmdVSTEM:
- FT_TRACE4(( op1 == cf2_cmdVSTEMHM ? " vstemhm\n" : " vstem\n" ));
+ FT_TRACE4(( "%s\n", op1 == cf2_cmdVSTEMHM ? " vstemhm"
+ : " vstem" ));
if ( !font->isT1 )
{
@@ -888,7 +891,7 @@
FT_Bool isX = FT_BOOL( op1 == cf2_cmdHLINETO );
- FT_TRACE4(( isX ? " hlineto\n" : " vlineto\n" ));
+ FT_TRACE4(( "%s\n", isX ? " hlineto" : " vlineto" ));
for ( idx = 0; idx < count; idx++ )
{
@@ -916,8 +919,8 @@
CF2_UInt idx = 0;
- FT_TRACE4(( op1 == cf2_cmdRCURVELINE ? " rcurveline\n"
- : " rrcurveto\n" ));
+ FT_TRACE4(( "%s\n", op1 == cf2_cmdRCURVELINE ? " rcurveline"
+ : " rrcurveto" ));
while ( idx + 6 <= count )
{
@@ -957,10 +960,10 @@
FT_TRACE4(( " unknown op (%d)\n", op1 ));
else
{
- FT_TRACE4(( " closepath" ));
+ FT_TRACE4(( " closepath\n" ));
/* if there is no path, `closepath' is a no-op */
- ps_builder_close_contour( &decoder->builder );
+ cf2_glyphpath_closeOpenPath( &glyphPath );
haveWidth = TRUE;
}
@@ -972,8 +975,8 @@
CF2_Int subrNum;
- FT_TRACE4(( op1 == cf2_cmdCALLGSUBR ? " callgsubr"
- : " callsubr" ));
+ FT_TRACE4(( "%s", op1 == cf2_cmdCALLGSUBR ? " callgsubr"
+ : " callsubr" ));
if ( ( !font->isT1 && charstringIndex > CF2_MAX_SUBR ) ||
( font->isT1 && charstringIndex > T1_MAX_SUBRS_CALLS ) )
@@ -1212,8 +1215,8 @@
FT_Bool isV = FT_BOOL( op2 == cf2_escVSTEM3 );
- FT_TRACE4(( isV ? " vstem3\n"
- : " hstem3\n" ));
+ FT_TRACE4(( "%s\n", isV ? " vstem3"
+ : " hstem3" ));
FT_ASSERT( cf2_stack_count( opStack ) == 6 );
@@ -1644,16 +1647,17 @@
subr_no = cf2_stack_popInt( opStack );
arg_cnt = cf2_stack_popInt( opStack );
- /*******************************************************/
- /* */
- /* remove all operands to callothersubr from the stack */
- /* */
- /* for handled othersubrs, where we know the number of */
- /* arguments, we increase the stack by the value of */
- /* known_othersubr_result_cnt */
- /* */
- /* for unhandled othersubrs the following pops adjust */
- /* the stack pointer as necessary */
+ /********************************************************
+ *
+ * remove all operands to callothersubr from the stack
+ *
+ * for handled othersubrs, where we know the number of
+ * arguments, we increase the stack by the value of
+ * known_othersubr_result_cnt
+ *
+ * for unhandled othersubrs the following pops adjust
+ * the stack pointer as necessary
+ */
count = cf2_stack_count( opStack );
FT_ASSERT( (CF2_UInt)arg_cnt <= count );
@@ -2416,7 +2420,7 @@
PS_Builder* builder;
- FT_TRACE4(( " hsbw" ));
+ FT_TRACE4(( " hsbw\n" ));
builder = &decoder->builder;
@@ -2562,7 +2566,7 @@
case cf2_cmdHINTMASK:
/* the final \n in the tracing message gets added in */
/* `cf2_hintmask_read' (which also traces the mask bytes) */
- FT_TRACE4(( op1 == cf2_cmdCNTRMASK ? " cntrmask" : " hintmask" ));
+ FT_TRACE4(( "%s", op1 == cf2_cmdCNTRMASK ? " cntrmask" : " hintmask" ));
/* never add hints after the mask is computed */
if ( cf2_stack_count( opStack ) > 1 &&
@@ -2828,7 +2832,7 @@
count = count1 & ~2U;
idx += count1 - count;
- FT_TRACE4(( alternate ? " hvcurveto\n" : " vhcurveto\n" ));
+ FT_TRACE4(( "%s\n", alternate ? " hvcurveto" : " vhcurveto" ));
while ( idx < count )
{
diff --git a/thirdparty/freetype/src/psaux/psintrp.h b/thirdparty/freetype/src/psaux/psintrp.h
index 4790aaa302..669c09c0ae 100644
--- a/thirdparty/freetype/src/psaux/psintrp.h
+++ b/thirdparty/freetype/src/psaux/psintrp.h
@@ -1,39 +1,39 @@
-/***************************************************************************/
-/* */
-/* psintrp.h */
-/* */
-/* Adobe's CFF Interpreter (specification). */
-/* */
-/* Copyright 2007-2013 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * psintrp.h
+ *
+ * Adobe's CFF Interpreter (specification).
+ *
+ * Copyright 2007-2013 Adobe Systems Incorporated.
+ *
+ * This software, and all works of authorship, whether in source or
+ * object code form as indicated by the copyright notice(s) included
+ * herein (collectively, the "Work") is made available, and may only be
+ * used, modified, and distributed under the FreeType Project License,
+ * LICENSE.TXT. Additionally, subject to the terms and conditions of the
+ * FreeType Project License, each contributor to the Work hereby grants
+ * to any individual or legal entity exercising permissions granted by
+ * the FreeType Project License and this section (hereafter, "You" or
+ * "Your") a perpetual, worldwide, non-exclusive, no-charge,
+ * royalty-free, irrevocable (except as stated in this section) patent
+ * license to make, have made, use, offer to sell, sell, import, and
+ * otherwise transfer the Work, where such license applies only to those
+ * patent claims licensable by such contributor that are necessarily
+ * infringed by their contribution(s) alone or by combination of their
+ * contribution(s) with the Work to which such contribution(s) was
+ * submitted. If You institute patent litigation against any entity
+ * (including a cross-claim or counterclaim in a lawsuit) alleging that
+ * the Work or a contribution incorporated within the Work constitutes
+ * direct or contributory patent infringement, then any patent licenses
+ * granted to You under this License for that Work shall terminate as of
+ * the date such litigation is filed.
+ *
+ * By using, modifying, or distributing the Work you indicate that you
+ * have read and understood the terms and conditions of the
+ * FreeType Project License as well as those provided in this section,
+ * and you accept them fully.
+ *
+ */
#ifndef PSINTRP_H_
diff --git a/thirdparty/freetype/src/psaux/psobjs.c b/thirdparty/freetype/src/psaux/psobjs.c
index f54bc7e416..e2168a3324 100644
--- a/thirdparty/freetype/src/psaux/psobjs.c
+++ b/thirdparty/freetype/src/psaux/psobjs.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* psobjs.c */
-/* */
-/* Auxiliary functions for PostScript fonts (body). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * psobjs.c
+ *
+ * Auxiliary functions for PostScript fonts (body).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -29,14 +29,14 @@
#include "psauxmod.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_psobjs
+#define FT_COMPONENT psobjs
/*************************************************************************/
@@ -47,26 +47,29 @@
/*************************************************************************/
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* <Function> */
- /* ps_table_new */
- /* */
- /* <Description> */
- /* Initializes a PS_Table. */
- /* */
- /* <InOut> */
- /* table :: The address of the target table. */
- /* */
- /* <Input> */
- /* count :: The table size = the maximum number of elements. */
- /* */
- /* memory :: The memory object to use for all subsequent */
- /* reallocations. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * ps_table_new
+ *
+ * @Description:
+ * Initializes a PS_Table.
+ *
+ * @InOut:
+ * table ::
+ * The address of the target table.
+ *
+ * @Input:
+ * count ::
+ * The table size = the maximum number of elements.
+ *
+ * memory ::
+ * The memory object to use for all subsequent
+ * reallocations.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
ps_table_new( PS_Table table,
FT_Int count,
@@ -144,28 +147,32 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* ps_table_add */
- /* */
- /* <Description> */
- /* Adds an object to a PS_Table, possibly growing its memory block. */
- /* */
- /* <InOut> */
- /* table :: The target table. */
- /* */
- /* <Input> */
- /* idx :: The index of the object in the table. */
- /* */
- /* object :: The address of the object to copy in memory. */
- /* */
- /* length :: The length in bytes of the source object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. An error is returned if a */
- /* reallocation fails. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * ps_table_add
+ *
+ * @Description:
+ * Adds an object to a PS_Table, possibly growing its memory block.
+ *
+ * @InOut:
+ * table ::
+ * The target table.
+ *
+ * @Input:
+ * idx ::
+ * The index of the object in the table.
+ *
+ * object ::
+ * The address of the object to copy in memory.
+ *
+ * length ::
+ * The length in bytes of the source object.
+ *
+ * @Return:
+ * FreeType error code. 0 means success. An error is returned if a
+ * reallocation fails.
+ */
FT_LOCAL_DEF( FT_Error )
ps_table_add( PS_Table table,
FT_Int idx,
@@ -216,22 +223,23 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* ps_table_done */
- /* */
- /* <Description> */
- /* Finalizes a PS_TableRec (i.e., reallocate it to its current */
- /* cursor). */
- /* */
- /* <InOut> */
- /* table :: The target table. */
- /* */
- /* <Note> */
- /* This function does NOT release the heap's memory block. It is up */
- /* to the caller to clean it, or reference it in its own structures. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * ps_table_done
+ *
+ * @Description:
+ * Finalizes a PS_TableRec (i.e., reallocate it to its current
+ * cursor).
+ *
+ * @InOut:
+ * table ::
+ * The target table.
+ *
+ * @Note:
+ * This function does NOT release the heap's memory block. It is up
+ * to the caller to clean it, or reference it in its own structures.
+ */
FT_LOCAL_DEF( void )
ps_table_done( PS_Table table )
{
@@ -498,12 +506,12 @@
}
- /***********************************************************************/
- /* */
- /* All exported parsing routines handle leading whitespace and stop at */
- /* the first character which isn't part of the just handled token. */
- /* */
- /***********************************************************************/
+ /************************************************************************
+ *
+ * All exported parsing routines handle leading whitespace and stop at
+ * the first character which isn't part of the just handled token.
+ *
+ */
FT_LOCAL_DEF( void )
@@ -1100,18 +1108,22 @@
{
case T1_FIELD_TYPE_BOOL:
val = ps_tobool( &cur, limit );
+ FT_TRACE4(( " %s", val ? "true" : "false" ));
goto Store_Integer;
case T1_FIELD_TYPE_FIXED:
val = PS_Conv_ToFixed( &cur, limit, 0 );
+ FT_TRACE4(( " %f", (double)val / 65536 ));
goto Store_Integer;
case T1_FIELD_TYPE_FIXED_1000:
val = PS_Conv_ToFixed( &cur, limit, 3 );
+ FT_TRACE4(( " %f", (double)val / 65536 / 1000 ));
goto Store_Integer;
case T1_FIELD_TYPE_INTEGER:
val = PS_Conv_ToInt( &cur, limit );
+ FT_TRACE4(( " %ld", val ));
/* fall through */
Store_Integer:
@@ -1188,6 +1200,13 @@
FT_MEM_COPY( string, cur, len );
string[len] = 0;
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( token.type == T1_TOKEN_TYPE_STRING )
+ FT_TRACE4(( " (%s)", string ));
+ else
+ FT_TRACE4(( " /%s", string ));
+#endif
+
*(FT_String**)q = string;
}
break;
@@ -1213,6 +1232,12 @@
bbox->yMin = FT_RoundFix( temp[1] );
bbox->xMax = FT_RoundFix( temp[2] );
bbox->yMax = FT_RoundFix( temp[3] );
+
+ FT_TRACE4(( " [%d %d %d %d]",
+ bbox->xMin / 65536,
+ bbox->yMin / 65536,
+ bbox->xMax / 65536,
+ bbox->yMax / 65536 ));
}
break;
@@ -1251,6 +1276,7 @@
skip_spaces( &cur, limit );
}
+ FT_TRACE4(( " [" ));
for ( i = 0; i < max_objects; i++ )
{
FT_BBox* bbox = (FT_BBox*)objects[i];
@@ -1260,7 +1286,14 @@
bbox->yMin = FT_RoundFix( temp[i + max_objects] );
bbox->xMax = FT_RoundFix( temp[i + 2 * max_objects] );
bbox->yMax = FT_RoundFix( temp[i + 3 * max_objects] );
+
+ FT_TRACE4(( " [%d %d %d %d]",
+ bbox->xMin / 65536,
+ bbox->yMin / 65536,
+ bbox->xMax / 65536,
+ bbox->yMax / 65536 ));
}
+ FT_TRACE4(( "]" ));
FT_FREE( temp );
}
@@ -1333,6 +1366,8 @@
*(FT_Byte*)( (FT_Byte*)objects[0] + field->count_offset ) =
(FT_Byte)num_elements;
+ FT_TRACE4(( " [" ));
+
/* we now load each element, adjusting the field.offset on each one */
token = elements;
for ( ; num_elements > 0; num_elements--, token++ )
@@ -1351,6 +1386,8 @@
fieldrec.offset += fieldrec.size;
}
+ FT_TRACE4(( "]" ));
+
#if 0 /* obsolete -- keep for reference */
if ( pflags )
*pflags |= 1L << field->flag_bit;
@@ -1410,6 +1447,8 @@
bytes,
max_bytes );
+ parser->cursor = cur;
+
if ( delimiters )
{
if ( cur < parser->limit && *cur != '>' )
@@ -1419,11 +1458,9 @@
goto Exit;
}
- cur++;
+ parser->cursor++;
}
- parser->cursor = cur;
-
Exit:
return error;
}
@@ -1509,26 +1546,31 @@
/*************************************************************************/
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* <Function> */
- /* t1_builder_init */
- /* */
- /* <Description> */
- /* Initializes a given glyph builder. */
- /* */
- /* <InOut> */
- /* builder :: A pointer to the glyph builder to initialize. */
- /* */
- /* <Input> */
- /* face :: The current face object. */
- /* */
- /* size :: The current size object. */
- /* */
- /* glyph :: The current glyph object. */
- /* */
- /* hinting :: Whether hinting should be applied. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * t1_builder_init
+ *
+ * @Description:
+ * Initializes a given glyph builder.
+ *
+ * @InOut:
+ * builder ::
+ * A pointer to the glyph builder to initialize.
+ *
+ * @Input:
+ * face ::
+ * The current face object.
+ *
+ * size ::
+ * The current size object.
+ *
+ * glyph ::
+ * The current glyph object.
+ *
+ * hinting ::
+ * Whether hinting should be applied.
+ */
FT_LOCAL_DEF( void )
t1_builder_init( T1_Builder builder,
FT_Face face,
@@ -1572,19 +1614,20 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* t1_builder_done */
- /* */
- /* <Description> */
- /* Finalizes a given glyph builder. Its contents can still be used */
- /* after the call, but the function saves important information */
- /* within the corresponding glyph slot. */
- /* */
- /* <Input> */
- /* builder :: A pointer to the glyph builder to finalize. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * t1_builder_done
+ *
+ * @Description:
+ * Finalizes a given glyph builder. Its contents can still be used
+ * after the call, but the function saves important information
+ * within the corresponding glyph slot.
+ *
+ * @Input:
+ * builder ::
+ * A pointer to the glyph builder to finalize.
+ */
FT_LOCAL_DEF( void )
t1_builder_done( T1_Builder builder )
{
@@ -1769,26 +1812,31 @@
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* <Function> */
- /* cff_builder_init */
- /* */
- /* <Description> */
- /* Initializes a given glyph builder. */
- /* */
- /* <InOut> */
- /* builder :: A pointer to the glyph builder to initialize. */
- /* */
- /* <Input> */
- /* face :: The current face object. */
- /* */
- /* size :: The current size object. */
- /* */
- /* glyph :: The current glyph object. */
- /* */
- /* hinting :: Whether hinting is active. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * cff_builder_init
+ *
+ * @Description:
+ * Initializes a given glyph builder.
+ *
+ * @InOut:
+ * builder ::
+ * A pointer to the glyph builder to initialize.
+ *
+ * @Input:
+ * face ::
+ * The current face object.
+ *
+ * size ::
+ * The current size object.
+ *
+ * glyph ::
+ * The current glyph object.
+ *
+ * hinting ::
+ * Whether hinting is active.
+ */
FT_LOCAL_DEF( void )
cff_builder_init( CFF_Builder* builder,
TT_Face face,
@@ -1841,19 +1889,20 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* cff_builder_done */
- /* */
- /* <Description> */
- /* Finalizes a given glyph builder. Its contents can still be used */
- /* after the call, but the function saves important information */
- /* within the corresponding glyph slot. */
- /* */
- /* <Input> */
- /* builder :: A pointer to the glyph builder to finalize. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * cff_builder_done
+ *
+ * @Description:
+ * Finalizes a given glyph builder. Its contents can still be used
+ * after the call, but the function saves important information
+ * within the corresponding glyph slot.
+ *
+ * @Input:
+ * builder ::
+ * A pointer to the glyph builder to finalize.
+ */
FT_LOCAL_DEF( void )
cff_builder_done( CFF_Builder* builder )
{
@@ -1993,6 +2042,14 @@
first = outline->n_contours <= 1
? 0 : outline->contours[outline->n_contours - 2] + 1;
+ /* in malformed fonts it can happen that a contour was started */
+ /* but no points were added */
+ if ( outline->n_contours && first == outline->n_points )
+ {
+ outline->n_contours--;
+ return;
+ }
+
/* We must not include the last point in the path if it */
/* is located on the first point. */
if ( outline->n_points > 1 )
@@ -2033,26 +2090,31 @@
/*************************************************************************/
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* <Function> */
- /* ps_builder_init */
- /* */
- /* <Description> */
- /* Initializes a given glyph builder. */
- /* */
- /* <InOut> */
- /* builder :: A pointer to the glyph builder to initialize. */
- /* */
- /* <Input> */
- /* face :: The current face object. */
- /* */
- /* size :: The current size object. */
- /* */
- /* glyph :: The current glyph object. */
- /* */
- /* hinting :: Whether hinting should be applied. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * ps_builder_init
+ *
+ * @Description:
+ * Initializes a given glyph builder.
+ *
+ * @InOut:
+ * builder ::
+ * A pointer to the glyph builder to initialize.
+ *
+ * @Input:
+ * face ::
+ * The current face object.
+ *
+ * size ::
+ * The current size object.
+ *
+ * glyph ::
+ * The current glyph object.
+ *
+ * hinting ::
+ * Whether hinting should be applied.
+ */
FT_LOCAL_DEF( void )
ps_builder_init( PS_Builder* ps_builder,
void* builder,
@@ -2116,19 +2178,20 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* ps_builder_done */
- /* */
- /* <Description> */
- /* Finalizes a given glyph builder. Its contents can still be used */
- /* after the call, but the function saves important information */
- /* within the corresponding glyph slot. */
- /* */
- /* <Input> */
- /* builder :: A pointer to the glyph builder to finalize. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * ps_builder_done
+ *
+ * @Description:
+ * Finalizes a given glyph builder. Its contents can still be used
+ * after the call, but the function saves important information
+ * within the corresponding glyph slot.
+ *
+ * @Input:
+ * builder ::
+ * A pointer to the glyph builder to finalize.
+ */
FT_LOCAL_DEF( void )
ps_builder_done( PS_Builder* builder )
{
@@ -2336,23 +2399,26 @@
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* <Function> */
- /* ps_decoder_init */
- /* */
- /* <Description> */
- /* Creates a wrapper decoder for use in the combined */
- /* Type 1 / CFF interpreter. */
- /* */
- /* <InOut> */
- /* ps_decoder :: A pointer to the decoder to initialize. */
- /* */
- /* <Input> */
- /* decoder :: A pointer to the original decoder. */
- /* */
- /* is_t1 :: Flag indicating Type 1 or CFF */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * ps_decoder_init
+ *
+ * @Description:
+ * Creates a wrapper decoder for use in the combined
+ * Type 1 / CFF interpreter.
+ *
+ * @InOut:
+ * ps_decoder ::
+ * A pointer to the decoder to initialize.
+ *
+ * @Input:
+ * decoder ::
+ * A pointer to the original decoder.
+ *
+ * is_t1 ::
+ * Flag indicating Type 1 or CFF
+ */
FT_LOCAL_DEF( void )
ps_decoder_init( PS_Decoder* ps_decoder,
void* decoder,
diff --git a/thirdparty/freetype/src/psaux/psobjs.h b/thirdparty/freetype/src/psaux/psobjs.h
index 8e0fe5fa4c..9466a1d075 100644
--- a/thirdparty/freetype/src/psaux/psobjs.h
+++ b/thirdparty/freetype/src/psaux/psobjs.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* psobjs.h */
-/* */
-/* Auxiliary functions for PostScript fonts (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * psobjs.h
+ *
+ * Auxiliary functions for PostScript fonts (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef PSOBJS_H_
diff --git a/thirdparty/freetype/src/psaux/psread.c b/thirdparty/freetype/src/psaux/psread.c
index 719863ce17..86bfc03c6e 100644
--- a/thirdparty/freetype/src/psaux/psread.c
+++ b/thirdparty/freetype/src/psaux/psread.c
@@ -1,39 +1,39 @@
-/***************************************************************************/
-/* */
-/* psread.c */
-/* */
-/* Adobe's code for stream handling (body). */
-/* */
-/* Copyright 2007-2013 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * psread.c
+ *
+ * Adobe's code for stream handling (body).
+ *
+ * Copyright 2007-2013 Adobe Systems Incorporated.
+ *
+ * This software, and all works of authorship, whether in source or
+ * object code form as indicated by the copyright notice(s) included
+ * herein (collectively, the "Work") is made available, and may only be
+ * used, modified, and distributed under the FreeType Project License,
+ * LICENSE.TXT. Additionally, subject to the terms and conditions of the
+ * FreeType Project License, each contributor to the Work hereby grants
+ * to any individual or legal entity exercising permissions granted by
+ * the FreeType Project License and this section (hereafter, "You" or
+ * "Your") a perpetual, worldwide, non-exclusive, no-charge,
+ * royalty-free, irrevocable (except as stated in this section) patent
+ * license to make, have made, use, offer to sell, sell, import, and
+ * otherwise transfer the Work, where such license applies only to those
+ * patent claims licensable by such contributor that are necessarily
+ * infringed by their contribution(s) alone or by combination of their
+ * contribution(s) with the Work to which such contribution(s) was
+ * submitted. If You institute patent litigation against any entity
+ * (including a cross-claim or counterclaim in a lawsuit) alleging that
+ * the Work or a contribution incorporated within the Work constitutes
+ * direct or contributory patent infringement, then any patent licenses
+ * granted to You under this License for that Work shall terminate as of
+ * the date such litigation is filed.
+ *
+ * By using, modifying, or distributing the Work you indicate that you
+ * have read and understood the terms and conditions of the
+ * FreeType Project License as well as those provided in this section,
+ * and you accept them fully.
+ *
+ */
#include "psft.h"
@@ -105,7 +105,7 @@
FT_LOCAL_DEF( FT_Bool )
cf2_buf_isEnd( CF2_Buffer buf )
{
- return (FT_Bool)( buf->ptr >= buf->end );
+ return FT_BOOL( buf->ptr >= buf->end );
}
diff --git a/thirdparty/freetype/src/psaux/psread.h b/thirdparty/freetype/src/psaux/psread.h
index 464b29ba74..9e55fe0447 100644
--- a/thirdparty/freetype/src/psaux/psread.h
+++ b/thirdparty/freetype/src/psaux/psread.h
@@ -1,39 +1,39 @@
-/***************************************************************************/
-/* */
-/* psread.h */
-/* */
-/* Adobe's code for stream handling (specification). */
-/* */
-/* Copyright 2007-2013 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * psread.h
+ *
+ * Adobe's code for stream handling (specification).
+ *
+ * Copyright 2007-2013 Adobe Systems Incorporated.
+ *
+ * This software, and all works of authorship, whether in source or
+ * object code form as indicated by the copyright notice(s) included
+ * herein (collectively, the "Work") is made available, and may only be
+ * used, modified, and distributed under the FreeType Project License,
+ * LICENSE.TXT. Additionally, subject to the terms and conditions of the
+ * FreeType Project License, each contributor to the Work hereby grants
+ * to any individual or legal entity exercising permissions granted by
+ * the FreeType Project License and this section (hereafter, "You" or
+ * "Your") a perpetual, worldwide, non-exclusive, no-charge,
+ * royalty-free, irrevocable (except as stated in this section) patent
+ * license to make, have made, use, offer to sell, sell, import, and
+ * otherwise transfer the Work, where such license applies only to those
+ * patent claims licensable by such contributor that are necessarily
+ * infringed by their contribution(s) alone or by combination of their
+ * contribution(s) with the Work to which such contribution(s) was
+ * submitted. If You institute patent litigation against any entity
+ * (including a cross-claim or counterclaim in a lawsuit) alleging that
+ * the Work or a contribution incorporated within the Work constitutes
+ * direct or contributory patent infringement, then any patent licenses
+ * granted to You under this License for that Work shall terminate as of
+ * the date such litigation is filed.
+ *
+ * By using, modifying, or distributing the Work you indicate that you
+ * have read and understood the terms and conditions of the
+ * FreeType Project License as well as those provided in this section,
+ * and you accept them fully.
+ *
+ */
#ifndef PSREAD_H_
diff --git a/thirdparty/freetype/src/psaux/psstack.c b/thirdparty/freetype/src/psaux/psstack.c
index 69d063349a..6659068001 100644
--- a/thirdparty/freetype/src/psaux/psstack.c
+++ b/thirdparty/freetype/src/psaux/psstack.c
@@ -1,39 +1,39 @@
-/***************************************************************************/
-/* */
-/* psstack.c */
-/* */
-/* Adobe's code for emulating a CFF stack (body). */
-/* */
-/* Copyright 2007-2013 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * psstack.c
+ *
+ * Adobe's code for emulating a CFF stack (body).
+ *
+ * Copyright 2007-2013 Adobe Systems Incorporated.
+ *
+ * This software, and all works of authorship, whether in source or
+ * object code form as indicated by the copyright notice(s) included
+ * herein (collectively, the "Work") is made available, and may only be
+ * used, modified, and distributed under the FreeType Project License,
+ * LICENSE.TXT. Additionally, subject to the terms and conditions of the
+ * FreeType Project License, each contributor to the Work hereby grants
+ * to any individual or legal entity exercising permissions granted by
+ * the FreeType Project License and this section (hereafter, "You" or
+ * "Your") a perpetual, worldwide, non-exclusive, no-charge,
+ * royalty-free, irrevocable (except as stated in this section) patent
+ * license to make, have made, use, offer to sell, sell, import, and
+ * otherwise transfer the Work, where such license applies only to those
+ * patent claims licensable by such contributor that are necessarily
+ * infringed by their contribution(s) alone or by combination of their
+ * contribution(s) with the Work to which such contribution(s) was
+ * submitted. If You institute patent litigation against any entity
+ * (including a cross-claim or counterclaim in a lawsuit) alleging that
+ * the Work or a contribution incorporated within the Work constitutes
+ * direct or contributory patent infringement, then any patent licenses
+ * granted to You under this License for that Work shall terminate as of
+ * the date such litigation is filed.
+ *
+ * By using, modifying, or distributing the Work you indicate that you
+ * have read and understood the terms and conditions of the
+ * FreeType Project License as well as those provided in this section,
+ * and you accept them fully.
+ *
+ */
#include "psft.h"
@@ -258,6 +258,9 @@
return;
}
+ /* before C99 it is implementation-defined whether */
+ /* the result of `%' is negative if the first operand */
+ /* is negative */
if ( shift < 0 )
shift = -( ( -shift ) % count );
else
diff --git a/thirdparty/freetype/src/psaux/psstack.h b/thirdparty/freetype/src/psaux/psstack.h
index 38f7b41c68..18cd39bc6a 100644
--- a/thirdparty/freetype/src/psaux/psstack.h
+++ b/thirdparty/freetype/src/psaux/psstack.h
@@ -1,39 +1,39 @@
-/***************************************************************************/
-/* */
-/* psstack.h */
-/* */
-/* Adobe's code for emulating a CFF stack (specification). */
-/* */
-/* Copyright 2007-2013 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * psstack.h
+ *
+ * Adobe's code for emulating a CFF stack (specification).
+ *
+ * Copyright 2007-2013 Adobe Systems Incorporated.
+ *
+ * This software, and all works of authorship, whether in source or
+ * object code form as indicated by the copyright notice(s) included
+ * herein (collectively, the "Work") is made available, and may only be
+ * used, modified, and distributed under the FreeType Project License,
+ * LICENSE.TXT. Additionally, subject to the terms and conditions of the
+ * FreeType Project License, each contributor to the Work hereby grants
+ * to any individual or legal entity exercising permissions granted by
+ * the FreeType Project License and this section (hereafter, "You" or
+ * "Your") a perpetual, worldwide, non-exclusive, no-charge,
+ * royalty-free, irrevocable (except as stated in this section) patent
+ * license to make, have made, use, offer to sell, sell, import, and
+ * otherwise transfer the Work, where such license applies only to those
+ * patent claims licensable by such contributor that are necessarily
+ * infringed by their contribution(s) alone or by combination of their
+ * contribution(s) with the Work to which such contribution(s) was
+ * submitted. If You institute patent litigation against any entity
+ * (including a cross-claim or counterclaim in a lawsuit) alleging that
+ * the Work or a contribution incorporated within the Work constitutes
+ * direct or contributory patent infringement, then any patent licenses
+ * granted to You under this License for that Work shall terminate as of
+ * the date such litigation is filed.
+ *
+ * By using, modifying, or distributing the Work you indicate that you
+ * have read and understood the terms and conditions of the
+ * FreeType Project License as well as those provided in this section,
+ * and you accept them fully.
+ *
+ */
#ifndef PSSTACK_H_
diff --git a/thirdparty/freetype/src/psaux/pstypes.h b/thirdparty/freetype/src/psaux/pstypes.h
index dfbaa3d475..041287e8d5 100644
--- a/thirdparty/freetype/src/psaux/pstypes.h
+++ b/thirdparty/freetype/src/psaux/pstypes.h
@@ -1,39 +1,39 @@
-/***************************************************************************/
-/* */
-/* pstypes.h */
-/* */
-/* Adobe's code for defining data types (specification only). */
-/* */
-/* Copyright 2011-2013 Adobe Systems Incorporated. */
-/* */
-/* This software, and all works of authorship, whether in source or */
-/* object code form as indicated by the copyright notice(s) included */
-/* herein (collectively, the "Work") is made available, and may only be */
-/* used, modified, and distributed under the FreeType Project License, */
-/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
-/* FreeType Project License, each contributor to the Work hereby grants */
-/* to any individual or legal entity exercising permissions granted by */
-/* the FreeType Project License and this section (hereafter, "You" or */
-/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
-/* royalty-free, irrevocable (except as stated in this section) patent */
-/* license to make, have made, use, offer to sell, sell, import, and */
-/* otherwise transfer the Work, where such license applies only to those */
-/* patent claims licensable by such contributor that are necessarily */
-/* infringed by their contribution(s) alone or by combination of their */
-/* contribution(s) with the Work to which such contribution(s) was */
-/* submitted. If You institute patent litigation against any entity */
-/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
-/* the Work or a contribution incorporated within the Work constitutes */
-/* direct or contributory patent infringement, then any patent licenses */
-/* granted to You under this License for that Work shall terminate as of */
-/* the date such litigation is filed. */
-/* */
-/* By using, modifying, or distributing the Work you indicate that you */
-/* have read and understood the terms and conditions of the */
-/* FreeType Project License as well as those provided in this section, */
-/* and you accept them fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * pstypes.h
+ *
+ * Adobe's code for defining data types (specification only).
+ *
+ * Copyright 2011-2013 Adobe Systems Incorporated.
+ *
+ * This software, and all works of authorship, whether in source or
+ * object code form as indicated by the copyright notice(s) included
+ * herein (collectively, the "Work") is made available, and may only be
+ * used, modified, and distributed under the FreeType Project License,
+ * LICENSE.TXT. Additionally, subject to the terms and conditions of the
+ * FreeType Project License, each contributor to the Work hereby grants
+ * to any individual or legal entity exercising permissions granted by
+ * the FreeType Project License and this section (hereafter, "You" or
+ * "Your") a perpetual, worldwide, non-exclusive, no-charge,
+ * royalty-free, irrevocable (except as stated in this section) patent
+ * license to make, have made, use, offer to sell, sell, import, and
+ * otherwise transfer the Work, where such license applies only to those
+ * patent claims licensable by such contributor that are necessarily
+ * infringed by their contribution(s) alone or by combination of their
+ * contribution(s) with the Work to which such contribution(s) was
+ * submitted. If You institute patent litigation against any entity
+ * (including a cross-claim or counterclaim in a lawsuit) alleging that
+ * the Work or a contribution incorporated within the Work constitutes
+ * direct or contributory patent infringement, then any patent licenses
+ * granted to You under this License for that Work shall terminate as of
+ * the date such litigation is filed.
+ *
+ * By using, modifying, or distributing the Work you indicate that you
+ * have read and understood the terms and conditions of the
+ * FreeType Project License as well as those provided in this section,
+ * and you accept them fully.
+ *
+ */
#ifndef PSTYPES_H_
diff --git a/thirdparty/freetype/src/psaux/rules.mk b/thirdparty/freetype/src/psaux/rules.mk
index a87bfe9687..2de734d547 100644
--- a/thirdparty/freetype/src/psaux/rules.mk
+++ b/thirdparty/freetype/src/psaux/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2018 by
+# Copyright (C) 1996-2019 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/psaux/t1cmap.c b/thirdparty/freetype/src/psaux/t1cmap.c
index 112a7892ba..d62d2d5c81 100644
--- a/thirdparty/freetype/src/psaux/t1cmap.c
+++ b/thirdparty/freetype/src/psaux/t1cmap.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* t1cmap.c */
-/* */
-/* Type 1 character map support (body). */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * t1cmap.c
+ *
+ * Type 1 character map support (body).
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include "t1cmap.h"
@@ -305,6 +305,9 @@
FT_UNUSED( pointer );
+ if ( !psnames->unicodes_init )
+ return FT_THROW( Unimplemented_Feature );
+
return psnames->unicodes_init( memory,
unicodes,
(FT_UInt)face->type1.num_glyphs,
diff --git a/thirdparty/freetype/src/psaux/t1cmap.h b/thirdparty/freetype/src/psaux/t1cmap.h
index 4308e31d2d..d325e7b5a6 100644
--- a/thirdparty/freetype/src/psaux/t1cmap.h
+++ b/thirdparty/freetype/src/psaux/t1cmap.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* t1cmap.h */
-/* */
-/* Type 1 character map support (specification). */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * t1cmap.h
+ *
+ * Type 1 character map support (specification).
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef T1CMAP_H_
diff --git a/thirdparty/freetype/src/psaux/t1decode.c b/thirdparty/freetype/src/psaux/t1decode.c
index 6ad145661f..c2b3729b53 100644
--- a/thirdparty/freetype/src/psaux/t1decode.c
+++ b/thirdparty/freetype/src/psaux/t1decode.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* t1decode.c */
-/* */
-/* PostScript Type 1 decoding routines (body). */
-/* */
-/* Copyright 2000-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * t1decode.c
+ *
+ * PostScript Type 1 decoding routines (body).
+ *
+ * Copyright (C) 2000-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -31,14 +31,14 @@
/* ensure proper sign extension */
#define Fix2Int( f ) ( (FT_Int)(FT_Short)( (f) >> 16 ) )
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_t1decode
+#define FT_COMPONENT t1decode
typedef enum T1_Operator_
@@ -109,24 +109,26 @@
};
- /*************************************************************************/
- /* */
- /* <Function> */
- /* t1_lookup_glyph_by_stdcharcode_ps */
- /* */
- /* <Description> */
- /* Looks up a given glyph by its StandardEncoding charcode. Used to */
- /* implement the SEAC Type 1 operator in the Adobe engine */
- /* */
- /* <Input> */
- /* face :: The current face object. */
- /* */
- /* charcode :: The character code to look for. */
- /* */
- /* <Return> */
- /* A glyph index in the font face. Returns -1 if the corresponding */
- /* glyph wasn't found. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * t1_lookup_glyph_by_stdcharcode_ps
+ *
+ * @Description:
+ * Looks up a given glyph by its StandardEncoding charcode. Used to
+ * implement the SEAC Type 1 operator in the Adobe engine
+ *
+ * @Input:
+ * face ::
+ * The current face object.
+ *
+ * charcode ::
+ * The character code to look for.
+ *
+ * @Return:
+ * A glyph index in the font face. Returns -1 if the corresponding
+ * glyph wasn't found.
+ */
FT_LOCAL_DEF( FT_Int )
t1_lookup_glyph_by_stdcharcode_ps( PS_Decoder* decoder,
FT_Int charcode )
@@ -159,24 +161,27 @@
#ifdef T1_CONFIG_OPTION_OLD_ENGINE
- /*************************************************************************/
- /* */
- /* <Function> */
- /* t1_lookup_glyph_by_stdcharcode */
- /* */
- /* <Description> */
- /* Looks up a given glyph by its StandardEncoding charcode. Used to */
- /* implement the SEAC Type 1 operator. */
- /* */
- /* <Input> */
- /* face :: The current face object. */
- /* */
- /* charcode :: The character code to look for. */
- /* */
- /* <Return> */
- /* A glyph index in the font face. Returns -1 if the corresponding */
- /* glyph wasn't found. */
- /* */
+
+ /**************************************************************************
+ *
+ * @Function:
+ * t1_lookup_glyph_by_stdcharcode
+ *
+ * @Description:
+ * Looks up a given glyph by its StandardEncoding charcode. Used to
+ * implement the SEAC Type 1 operator.
+ *
+ * @Input:
+ * face ::
+ * The current face object.
+ *
+ * charcode ::
+ * The character code to look for.
+ *
+ * @Return:
+ * A glyph index in the font face. Returns -1 if the corresponding
+ * glyph wasn't found.
+ */
static FT_Int
t1_lookup_glyph_by_stdcharcode( T1_Decoder decoder,
FT_Int charcode )
@@ -217,30 +222,36 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* t1operator_seac */
- /* */
- /* <Description> */
- /* Implements the `seac' Type 1 operator for a Type 1 decoder. */
- /* */
- /* <Input> */
- /* decoder :: The current CID decoder. */
- /* */
- /* asb :: The accent's side bearing. */
- /* */
- /* adx :: The horizontal offset of the accent. */
- /* */
- /* ady :: The vertical offset of the accent. */
- /* */
- /* bchar :: The base character's StandardEncoding charcode. */
- /* */
- /* achar :: The accent character's StandardEncoding charcode. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * t1operator_seac
+ *
+ * @Description:
+ * Implements the `seac' Type 1 operator for a Type 1 decoder.
+ *
+ * @Input:
+ * decoder ::
+ * The current CID decoder.
+ *
+ * asb ::
+ * The accent's side bearing.
+ *
+ * adx ::
+ * The horizontal offset of the accent.
+ *
+ * ady ::
+ * The vertical offset of the accent.
+ *
+ * bchar ::
+ * The base character's StandardEncoding charcode.
+ *
+ * achar ::
+ * The accent character's StandardEncoding charcode.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
static FT_Error
t1operator_seac( T1_Decoder decoder,
FT_Pos asb,
@@ -399,24 +410,27 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* t1_decoder_parse_charstrings */
- /* */
- /* <Description> */
- /* Parses a given Type 1 charstrings program. */
- /* */
- /* <Input> */
- /* decoder :: The current Type 1 decoder. */
- /* */
- /* charstring_base :: The base address of the charstring stream. */
- /* */
- /* charstring_len :: The length in bytes of the charstring stream. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * t1_decoder_parse_charstrings
+ *
+ * @Description:
+ * Parses a given Type 1 charstrings program.
+ *
+ * @Input:
+ * decoder ::
+ * The current Type 1 decoder.
+ *
+ * charstring_base ::
+ * The base address of the charstring stream.
+ *
+ * charstring_len ::
+ * The length in bytes of the charstring stream.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
t1_decoder_parse_charstrings( T1_Decoder decoder,
FT_Byte* charstring_base,
@@ -466,9 +480,6 @@
if ( decoder->buildchar && decoder->len_buildchar > 0 )
FT_ARRAY_ZERO( decoder->buildchar, decoder->len_buildchar );
- FT_TRACE4(( "\n"
- "Start charstring\n" ));
-
zone->base = charstring_base;
limit = zone->limit = charstring_base + charstring_len;
ip = zone->cursor = zone->base;
@@ -503,11 +514,11 @@
}
#endif
- /*********************************************************************/
- /* */
- /* Decode operator or operand */
- /* */
- /* */
+ /**********************************************************************
+ *
+ * Decode operator or operand
+ *
+ */
/* first of all, decompress operator or value */
switch ( *ip++ )
@@ -710,11 +721,11 @@
large_int = FALSE;
}
- /*********************************************************************/
- /* */
- /* Push value on stack, or process operator */
- /* */
- /* */
+ /**********************************************************************
+ *
+ * Push value on stack, or process operator
+ *
+ */
if ( op == op_none )
{
if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS )
@@ -752,16 +763,17 @@
subr_no = Fix2Int( top[1] );
arg_cnt = Fix2Int( top[0] );
- /***********************************************************/
- /* */
- /* remove all operands to callothersubr from the stack */
- /* */
- /* for handled othersubrs, where we know the number of */
- /* arguments, we increase the stack by the value of */
- /* known_othersubr_result_cnt */
- /* */
- /* for unhandled othersubrs the following pops adjust the */
- /* stack pointer as necessary */
+ /************************************************************
+ *
+ * remove all operands to callothersubr from the stack
+ *
+ * for handled othersubrs, where we know the number of
+ * arguments, we increase the stack by the value of
+ * known_othersubr_result_cnt
+ *
+ * for unhandled othersubrs the following pops adjust the
+ * stack pointer as necessary
+ */
if ( arg_cnt > top - decoder->stack )
goto Stack_Underflow;
@@ -1223,7 +1235,10 @@
/* the glyph's metrics (lsb + advance width), not load the */
/* rest of it; so exit immediately */
if ( builder->metrics_only )
+ {
+ FT_TRACE4(( "\n" ));
return FT_Err_Ok;
+ }
break;
@@ -1255,7 +1270,10 @@
/* the glyph's metrics (lsb + advance width), not load the */
/* rest of it; so exit immediately */
if ( builder->metrics_only )
+ {
+ FT_TRACE4(( "\n" ));
return FT_Err_Ok;
+ }
break;
@@ -1638,26 +1656,31 @@
return FT_THROW( Stack_Underflow );
}
-#else /* T1_CONFIG_OPTION_OLD_ENGINE */
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* t1_decoder_parse_metrics */
- /* */
- /* <Description> */
- /* Parses a given Type 1 charstrings program to extract width */
- /* */
- /* <Input> */
- /* decoder :: The current Type 1 decoder. */
- /* */
- /* charstring_base :: The base address of the charstring stream. */
- /* */
- /* charstring_len :: The length in bytes of the charstring stream. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+
+#else /* !T1_CONFIG_OPTION_OLD_ENGINE */
+
+
+ /**************************************************************************
+ *
+ * @Function:
+ * t1_decoder_parse_metrics
+ *
+ * @Description:
+ * Parses a given Type 1 charstrings program to extract width
+ *
+ * @Input:
+ * decoder ::
+ * The current Type 1 decoder.
+ *
+ * charstring_base ::
+ * The base address of the charstring stream.
+ *
+ * charstring_len ::
+ * The length in bytes of the charstring stream.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
t1_decoder_parse_metrics( T1_Decoder decoder,
FT_Byte* charstring_base,
@@ -1680,9 +1703,6 @@
builder->parse_state = T1_Parse_Start;
- FT_TRACE4(( "\n"
- "Start charstring: get width\n" ));
-
zone->base = charstring_base;
limit = zone->limit = charstring_base + charstring_len;
ip = zone->cursor = zone->base;
@@ -1703,11 +1723,11 @@
}
#endif
- /*********************************************************************/
- /* */
- /* Decode operator or operand */
- /* */
- /* */
+ /**********************************************************************
+ *
+ * Decode operator or operand
+ *
+ */
/* first of all, decompress operator or value */
switch ( *ip++ )
@@ -1817,11 +1837,11 @@
}
}
- /*********************************************************************/
- /* */
- /* Push value on stack, or process operator */
- /* */
- /* */
+ /**********************************************************************
+ *
+ * Push value on stack, or process operator
+ *
+ */
if ( op == op_none )
{
if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS )
@@ -1875,6 +1895,7 @@
/* we only want to compute the glyph's metrics */
/* (lsb + advance width), not load the rest of */
/* it; so exit immediately */
+ FT_TRACE4(( "\n" ));
return FT_Err_Ok;
case op_sbw:
@@ -1893,6 +1914,7 @@
/* we only want to compute the glyph's metrics */
/* (lsb + advance width), not load the rest of */
/* it; so exit immediately */
+ FT_TRACE4(( "\n" ));
return FT_Err_Ok;
default:
@@ -1917,7 +1939,8 @@
Stack_Underflow:
return FT_THROW( Stack_Underflow );
}
-#endif /* T1_CONFIG_OPTION_OLD_ENGINE */
+
+#endif /* !T1_CONFIG_OPTION_OLD_ENGINE */
/* initialize T1 decoder */
@@ -1934,7 +1957,7 @@
{
FT_ZERO( decoder );
- /* retrieve PSNames interface from list of current modules */
+ /* retrieve `psnames' interface from list of current modules */
{
FT_Service_PsCMaps psnames;
diff --git a/thirdparty/freetype/src/psaux/t1decode.h b/thirdparty/freetype/src/psaux/t1decode.h
index 1d9718d678..1b5d6263d3 100644
--- a/thirdparty/freetype/src/psaux/t1decode.h
+++ b/thirdparty/freetype/src/psaux/t1decode.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* t1decode.h */
-/* */
-/* PostScript Type 1 decoding routines (specification). */
-/* */
-/* Copyright 2000-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * t1decode.h
+ *
+ * PostScript Type 1 decoding routines (specification).
+ *
+ * Copyright (C) 2000-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef T1DECODE_H_
diff --git a/thirdparty/freetype/src/pshinter/module.mk b/thirdparty/freetype/src/pshinter/module.mk
index 06707be3b4..0a12a260e1 100644
--- a/thirdparty/freetype/src/pshinter/module.mk
+++ b/thirdparty/freetype/src/pshinter/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2018 by
+# Copyright (C) 1996-2019 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/pshinter/pshalgo.c b/thirdparty/freetype/src/pshinter/pshalgo.c
index b98077c62e..0c5ae62699 100644
--- a/thirdparty/freetype/src/pshinter/pshalgo.c
+++ b/thirdparty/freetype/src/pshinter/pshalgo.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* pshalgo.c */
-/* */
-/* PostScript hinting algorithm (body). */
-/* */
-/* Copyright 2001-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used */
-/* modified and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * pshalgo.c
+ *
+ * PostScript hinting algorithm (body).
+ *
+ * Copyright (C) 2001-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used
+ * modified and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -26,7 +26,7 @@
#undef FT_COMPONENT
-#define FT_COMPONENT trace_pshalgo
+#define FT_COMPONENT pshalgo
#ifdef DEBUG_HINTER
@@ -53,8 +53,8 @@
psh_hint_overlap( PSH_Hint hint1,
PSH_Hint hint2 )
{
- return hint1->org_pos + hint1->org_len >= hint2->org_pos &&
- hint2->org_pos + hint2->org_len >= hint1->org_pos;
+ return ADD_INT( hint1->org_pos, hint1->org_len ) >= hint2->org_pos &&
+ ADD_INT( hint2->org_pos, hint2->org_len ) >= hint1->org_pos;
}
@@ -479,7 +479,7 @@
if ( dimension == 1 )
psh_blues_snap_stem( &globals->blues,
- hint->org_pos + hint->org_len,
+ ADD_INT( hint->org_pos, hint->org_len ),
hint->org_pos,
&align );
@@ -658,8 +658,8 @@
#if 0 /* not used for now, experimental */
/*
- * A variant to perform "light" hinting (i.e. FT_RENDER_MODE_LIGHT)
- * of stems
+ * A variant to perform "light" hinting (i.e. FT_RENDER_MODE_LIGHT)
+ * of stems
*/
static void
psh_hint_align_light( PSH_Hint hint,
@@ -703,7 +703,7 @@
if ( dimension == 1 )
psh_blues_snap_stem( &globals->blues,
- hint->org_pos + hint->org_len,
+ ADD_INT( hint->org_pos, hint->org_len ),
hint->org_pos,
&align );
@@ -1538,8 +1538,8 @@
PSH_Hint hint = sort[nn];
- if ( org_u >= hint->org_pos &&
- org_u <= hint->org_pos + hint->org_len )
+ if ( org_u >= hint->org_pos &&
+ org_u <= ADD_INT( hint->org_pos, hint->org_len ) )
{
point->hint = hint;
break;
diff --git a/thirdparty/freetype/src/pshinter/pshalgo.h b/thirdparty/freetype/src/pshinter/pshalgo.h
index c50683fbec..6859e95cd2 100644
--- a/thirdparty/freetype/src/pshinter/pshalgo.h
+++ b/thirdparty/freetype/src/pshinter/pshalgo.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* pshalgo.h */
-/* */
-/* PostScript hinting algorithm (specification). */
-/* */
-/* Copyright 2001-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * pshalgo.h
+ *
+ * PostScript hinting algorithm (specification).
+ *
+ * Copyright (C) 2001-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef PSHALGO_H_
diff --git a/thirdparty/freetype/src/pshinter/pshglob.c b/thirdparty/freetype/src/pshinter/pshglob.c
index accc04921d..b021e6e42a 100644
--- a/thirdparty/freetype/src/pshinter/pshglob.c
+++ b/thirdparty/freetype/src/pshinter/pshglob.c
@@ -1,25 +1,26 @@
-/***************************************************************************/
-/* */
-/* pshglob.c */
-/* */
-/* PostScript hinter global hinting management (body). */
-/* Inspired by the new auto-hinter module. */
-/* */
-/* Copyright 2001-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used */
-/* modified and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * pshglob.c
+ *
+ * PostScript hinter global hinting management (body).
+ * Inspired by the new auto-hinter module.
+ *
+ * Copyright (C) 2001-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used
+ * modified and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_CALC_H
#include "pshglob.h"
#ifdef DEBUG_HINTER
@@ -568,7 +569,7 @@
for ( ; count > 0; count--, zone++ )
{
- delta = stem_top - zone->org_bottom;
+ delta = SUB_LONG( stem_top, zone->org_bottom );
if ( delta < -blues->blue_fuzz )
break;
@@ -590,7 +591,7 @@
for ( ; count > 0; count--, zone-- )
{
- delta = zone->org_top - stem_bot;
+ delta = SUB_LONG( zone->org_top, stem_bot );
if ( delta < -blues->blue_fuzz )
break;
diff --git a/thirdparty/freetype/src/pshinter/pshglob.h b/thirdparty/freetype/src/pshinter/pshglob.h
index cf80bf40e6..0049d4c0bc 100644
--- a/thirdparty/freetype/src/pshinter/pshglob.h
+++ b/thirdparty/freetype/src/pshinter/pshglob.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* pshglob.h */
-/* */
-/* PostScript hinter global hinting management. */
-/* */
-/* Copyright 2001-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * pshglob.h
+ *
+ * PostScript hinter global hinting management.
+ *
+ * Copyright (C) 2001-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef PSHGLOB_H_
@@ -36,27 +36,27 @@ FT_BEGIN_HEADER
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* @constant: */
- /* PS_GLOBALS_MAX_BLUE_ZONES */
- /* */
- /* @description: */
- /* The maximum number of blue zones in a font global hints structure. */
- /* See @PS_Globals_BluesRec. */
- /* */
+ /**************************************************************************
+ *
+ * @constant:
+ * PS_GLOBALS_MAX_BLUE_ZONES
+ *
+ * @description:
+ * The maximum number of blue zones in a font global hints structure.
+ * See @PS_Globals_BluesRec.
+ */
#define PS_GLOBALS_MAX_BLUE_ZONES 16
- /*************************************************************************/
- /* */
- /* @constant: */
- /* PS_GLOBALS_MAX_STD_WIDTHS */
- /* */
- /* @description: */
- /* The maximum number of standard and snap widths in either the */
- /* horizontal or vertical direction. See @PS_Globals_WidthsRec. */
- /* */
+ /**************************************************************************
+ *
+ * @constant:
+ * PS_GLOBALS_MAX_STD_WIDTHS
+ *
+ * @description:
+ * The maximum number of standard and snap widths in either the
+ * horizontal or vertical direction. See @PS_Globals_WidthsRec.
+ */
#define PS_GLOBALS_MAX_STD_WIDTHS 16
diff --git a/thirdparty/freetype/src/pshinter/pshinter.c b/thirdparty/freetype/src/pshinter/pshinter.c
index 0eedac452d..16c3a0a117 100644
--- a/thirdparty/freetype/src/pshinter/pshinter.c
+++ b/thirdparty/freetype/src/pshinter/pshinter.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* pshinter.c */
-/* */
-/* FreeType PostScript Hinting module */
-/* */
-/* Copyright 2001-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * pshinter.c
+ *
+ * FreeType PostScript Hinting module
+ *
+ * Copyright (C) 2001-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#define FT_MAKE_OPTION_SINGLE_OBJECT
@@ -22,7 +22,6 @@
#include "pshalgo.c"
#include "pshglob.c"
#include "pshmod.c"
-#include "pshpic.c"
#include "pshrec.c"
diff --git a/thirdparty/freetype/src/pshinter/pshmod.c b/thirdparty/freetype/src/pshinter/pshmod.c
index 0b8f6f99b8..2d36ea2a6a 100644
--- a/thirdparty/freetype/src/pshinter/pshmod.c
+++ b/thirdparty/freetype/src/pshinter/pshmod.c
@@ -1,26 +1,25 @@
-/***************************************************************************/
-/* */
-/* pshmod.c */
-/* */
-/* FreeType PostScript hinter module implementation (body). */
-/* */
-/* Copyright 2001-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * pshmod.c
+ *
+ * FreeType PostScript hinter module implementation (body).
+ *
+ * Copyright (C) 2001-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
#include FT_INTERNAL_OBJECTS_H
#include "pshrec.h"
#include "pshalgo.h"
-#include "pshpic.h"
/* the Postscript Hinter module structure */
@@ -111,7 +110,7 @@
0x10000L,
0x20000L,
- &PSHINTER_INTERFACE_GET, /* module-specific interface */
+ &pshinter_interface, /* module-specific interface */
(FT_Module_Constructor)ps_hinter_init, /* module_init */
(FT_Module_Destructor) ps_hinter_done, /* module_done */
diff --git a/thirdparty/freetype/src/pshinter/pshmod.h b/thirdparty/freetype/src/pshinter/pshmod.h
index 556de2fbc0..ea8771308a 100644
--- a/thirdparty/freetype/src/pshinter/pshmod.h
+++ b/thirdparty/freetype/src/pshinter/pshmod.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* pshmod.h */
-/* */
-/* PostScript hinter module interface (specification). */
-/* */
-/* Copyright 2001-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * pshmod.h
+ *
+ * PostScript hinter module interface (specification).
+ *
+ * Copyright (C) 2001-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef PSHMOD_H_
diff --git a/thirdparty/freetype/src/pshinter/pshnterr.h b/thirdparty/freetype/src/pshinter/pshnterr.h
index b9d02d2956..fb9dbca2b1 100644
--- a/thirdparty/freetype/src/pshinter/pshnterr.h
+++ b/thirdparty/freetype/src/pshinter/pshnterr.h
@@ -1,26 +1,26 @@
-/***************************************************************************/
-/* */
-/* pshnterr.h */
-/* */
-/* PS Hinter error codes (specification only). */
-/* */
-/* Copyright 2003-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* This file is used to define the PSHinter error enumeration constants. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * pshnterr.h
+ *
+ * PS Hinter error codes (specification only).
+ *
+ * Copyright (C) 2003-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * This file is used to define the PSHinter error enumeration constants.
+ *
+ */
#ifndef PSHNTERR_H_
#define PSHNTERR_H_
diff --git a/thirdparty/freetype/src/pshinter/pshpic.c b/thirdparty/freetype/src/pshinter/pshpic.c
deleted file mode 100644
index 465ad31885..0000000000
--- a/thirdparty/freetype/src/pshinter/pshpic.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/***************************************************************************/
-/* */
-/* pshpic.c */
-/* */
-/* The FreeType position independent code services for pshinter module. */
-/* */
-/* Copyright 2009-2018 by */
-/* Oran Agra and Mickey Gabel. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#include <ft2build.h>
-#include FT_FREETYPE_H
-#include FT_INTERNAL_OBJECTS_H
-#include "pshpic.h"
-#include "pshnterr.h"
-
-
-#ifdef FT_CONFIG_OPTION_PIC
-
- /* forward declaration of PIC init functions from pshmod.c */
- void
- FT_Init_Class_pshinter_interface( FT_Library library,
- PSHinter_Interface* clazz );
-
- void
- pshinter_module_class_pic_free( FT_Library library )
- {
- FT_PIC_Container* pic_container = &library->pic_container;
- FT_Memory memory = library->memory;
-
-
- if ( pic_container->pshinter )
- {
- FT_FREE( pic_container->pshinter );
- pic_container->pshinter = NULL;
- }
- }
-
-
- FT_Error
- pshinter_module_class_pic_init( FT_Library library )
- {
- FT_PIC_Container* pic_container = &library->pic_container;
- FT_Error error = FT_Err_Ok;
- PSHinterPIC* container = NULL;
- FT_Memory memory = library->memory;
-
-
- /* allocate pointer, clear and set global container pointer */
- if ( FT_ALLOC( container, sizeof ( *container ) ) )
- return error;
- FT_MEM_SET( container, 0, sizeof ( *container ) );
- pic_container->pshinter = container;
-
- /* add call to initialization function when you add new scripts */
- FT_Init_Class_pshinter_interface(
- library, &container->pshinter_interface );
-
- if ( error )
- pshinter_module_class_pic_free( library );
-
- return error;
- }
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
-
-/* END */
diff --git a/thirdparty/freetype/src/pshinter/pshpic.h b/thirdparty/freetype/src/pshinter/pshpic.h
deleted file mode 100644
index 4469ba87c8..0000000000
--- a/thirdparty/freetype/src/pshinter/pshpic.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/***************************************************************************/
-/* */
-/* pshpic.h */
-/* */
-/* The FreeType position independent code services for pshinter module. */
-/* */
-/* Copyright 2009-2018 by */
-/* Oran Agra and Mickey Gabel. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#ifndef PSHPIC_H_
-#define PSHPIC_H_
-
-
-#include FT_INTERNAL_PIC_H
-
-
-#ifndef FT_CONFIG_OPTION_PIC
-
-#define PSHINTER_INTERFACE_GET pshinter_interface
-
-#else /* FT_CONFIG_OPTION_PIC */
-
-#include FT_INTERNAL_POSTSCRIPT_HINTS_H
-
-FT_BEGIN_HEADER
-
- typedef struct PSHinterPIC_
- {
- PSHinter_Interface pshinter_interface;
-
- } PSHinterPIC;
-
-
-#define GET_PIC( lib ) ( (PSHinterPIC*)( (lib)->pic_container.pshinter ) )
-
-#define PSHINTER_INTERFACE_GET ( GET_PIC( library )->pshinter_interface )
-
- /* see pshpic.c for the implementation */
- void
- pshinter_module_class_pic_free( FT_Library library );
-
- FT_Error
- pshinter_module_class_pic_init( FT_Library library );
-
-FT_END_HEADER
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
- /* */
-
-#endif /* PSHPIC_H_ */
-
-
-/* END */
diff --git a/thirdparty/freetype/src/pshinter/pshrec.c b/thirdparty/freetype/src/pshinter/pshrec.c
index 6648d13d60..9dd09efe4c 100644
--- a/thirdparty/freetype/src/pshinter/pshrec.c
+++ b/thirdparty/freetype/src/pshinter/pshrec.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* pshrec.c */
-/* */
-/* FreeType PostScript hints recorder (body). */
-/* */
-/* Copyright 2001-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * pshrec.c
+ *
+ * FreeType PostScript hints recorder (body).
+ *
+ * Copyright (C) 2001-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -28,7 +28,7 @@
#include "pshnterr.h"
#undef FT_COMPONENT
-#define FT_COMPONENT trace_pshrec
+#define FT_COMPONENT pshrec
#ifdef DEBUG_HINTER
PS_Hints ps_debug_hints = NULL;
@@ -666,7 +666,7 @@
if ( len == -21 )
{
flags |= PS_HINT_FLAG_BOTTOM;
- pos += len;
+ pos = ADD_INT( pos, len );
}
len = 0;
}
@@ -1187,7 +1187,7 @@
/* compute integer stem positions in font units */
for ( n = 0; n < count * 2; n++ )
{
- y += coords[n];
+ y = ADD_LONG( y, coords[n] );
stems[n] = FIXED_TO_INT( y );
}
diff --git a/thirdparty/freetype/src/pshinter/pshrec.h b/thirdparty/freetype/src/pshinter/pshrec.h
index 7e3dfe0d53..02cc2102ec 100644
--- a/thirdparty/freetype/src/pshinter/pshrec.h
+++ b/thirdparty/freetype/src/pshinter/pshrec.h
@@ -1,31 +1,31 @@
-/***************************************************************************/
-/* */
-/* pshrec.h */
-/* */
-/* Postscript (Type1/Type2) hints recorder (specification). */
-/* */
-/* Copyright 2001-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /**************************************************************************/
- /* */
- /* The functions defined here are called from the Type 1, CID and CFF */
- /* font drivers to record the hints of a given character/glyph. */
- /* */
- /* The hints are recorded in a unified format, and are later processed */
- /* by the `optimizer' and `fitter' to adjust the outlines to the pixel */
- /* grid. */
- /* */
- /**************************************************************************/
+/****************************************************************************
+ *
+ * pshrec.h
+ *
+ * Postscript (Type1/Type2) hints recorder (specification).
+ *
+ * Copyright (C) 2001-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /***************************************************************************
+ *
+ * The functions defined here are called from the Type 1, CID and CFF
+ * font drivers to record the hints of a given character/glyph.
+ *
+ * The hints are recorded in a unified format, and are later processed
+ * by the `optimizer' and `fitter' to adjust the outlines to the pixel
+ * grid.
+ *
+ */
#ifndef PSHREC_H_
diff --git a/thirdparty/freetype/src/pshinter/rules.mk b/thirdparty/freetype/src/pshinter/rules.mk
index 966690efc2..58227d10f2 100644
--- a/thirdparty/freetype/src/pshinter/rules.mk
+++ b/thirdparty/freetype/src/pshinter/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 2001-2018 by
+# Copyright (C) 2001-2019 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
@@ -31,7 +31,6 @@ PSHINTER_COMPILE := $(CC) $(ANSIFLAGS) \
PSHINTER_DRV_SRC := $(PSHINTER_DIR)/pshalgo.c \
$(PSHINTER_DIR)/pshglob.c \
$(PSHINTER_DIR)/pshmod.c \
- $(PSHINTER_DIR)/pshpic.c \
$(PSHINTER_DIR)/pshrec.c
diff --git a/thirdparty/freetype/src/psnames/module.mk b/thirdparty/freetype/src/psnames/module.mk
index 410f48a191..0806a318a7 100644
--- a/thirdparty/freetype/src/psnames/module.mk
+++ b/thirdparty/freetype/src/psnames/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2018 by
+# Copyright (C) 1996-2019 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/psnames/psmodule.c b/thirdparty/freetype/src/psnames/psmodule.c
index 8929ebe751..0ec440e67b 100644
--- a/thirdparty/freetype/src/psnames/psmodule.c
+++ b/thirdparty/freetype/src/psnames/psmodule.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* psmodule.c */
-/* */
-/* PSNames module implementation (body). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * psmodule.c
+ *
+ * psnames module implementation (body).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -24,16 +24,16 @@
#include "psmodule.h"
/*
- * The file `pstables.h' with its arrays and its function
- * `ft_get_adobe_glyph_index' is useful for other projects also (for
- * example, `pdfium' is using it). However, if used as a C++ header,
- * including it in two different source files makes it necessary to use
- * `extern const' for the declaration of its arrays, otherwise the data
- * would be duplicated as mandated by the C++ standard.
+ * The file `pstables.h' with its arrays and its function
+ * `ft_get_adobe_glyph_index' is useful for other projects also (for
+ * example, `pdfium' is using it). However, if used as a C++ header,
+ * including it in two different source files makes it necessary to use
+ * `extern const' for the declaration of its arrays, otherwise the data
+ * would be duplicated as mandated by the C++ standard.
*
- * For this reason, we use `DEFINE_PS_TABLES' to guard the function
- * definitions, and `DEFINE_PS_TABLES_DATA' to provide both proper array
- * declarations and definitions.
+ * For this reason, we use `DEFINE_PS_TABLES' to guard the function
+ * definitions, and `DEFINE_PS_TABLES_DATA' to provide both proper array
+ * declarations and definitions.
*/
#include "pstables.h"
#define DEFINE_PS_TABLES
@@ -41,7 +41,6 @@
#include "pstables.h"
#include "psnamerr.h"
-#include "pspic.h"
#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
@@ -393,7 +392,9 @@
/* Reallocate if the number of used entries is much smaller. */
if ( count < num_glyphs / 2 )
{
- (void)FT_RENEW_ARRAY( table->maps, num_glyphs, count );
+ (void)FT_RENEW_ARRAY( table->maps,
+ num_glyphs + EXTRA_GLYPH_LIST_SIZE,
+ count );
error = FT_Err_Ok;
}
@@ -577,28 +578,16 @@
FT_DEFINE_SERVICEDESCREC1(
pscmaps_services,
- FT_SERVICE_ID_POSTSCRIPT_CMAPS, &PSCMAPS_INTERFACE_GET )
+ FT_SERVICE_ID_POSTSCRIPT_CMAPS, &pscmaps_interface )
static FT_Pointer
psnames_get_service( FT_Module module,
const char* service_id )
{
- /* PSCMAPS_SERVICES_GET dereferences `library' in PIC mode */
-#ifdef FT_CONFIG_OPTION_PIC
- FT_Library library;
-
-
- if ( !module )
- return NULL;
- library = module->library;
- if ( !library )
- return NULL;
-#else
FT_UNUSED( module );
-#endif
- return ft_service_list_lookup( PSCMAPS_SERVICES_GET, service_id );
+ return ft_service_list_lookup( pscmaps_services, service_id );
}
#endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
@@ -621,7 +610,7 @@
0x20000L, /* driver requires FreeType 2 or above */
PUT_PS_NAMES_SERVICE(
- (void*)&PSCMAPS_INTERFACE_GET ), /* module specific interface */
+ (void*)&pscmaps_interface ), /* module specific interface */
(FT_Module_Constructor)NULL, /* module_init */
(FT_Module_Destructor) NULL, /* module_done */
diff --git a/thirdparty/freetype/src/psnames/psmodule.h b/thirdparty/freetype/src/psnames/psmodule.h
index 3e94f8b437..0df9a7d889 100644
--- a/thirdparty/freetype/src/psnames/psmodule.h
+++ b/thirdparty/freetype/src/psnames/psmodule.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* psmodule.h */
-/* */
-/* High-level PSNames module interface (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * psmodule.h
+ *
+ * High-level psnames module interface (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef PSMODULE_H_
diff --git a/thirdparty/freetype/src/psnames/psnamerr.h b/thirdparty/freetype/src/psnames/psnamerr.h
index 14eb76c99c..67ab1765d3 100644
--- a/thirdparty/freetype/src/psnames/psnamerr.h
+++ b/thirdparty/freetype/src/psnames/psnamerr.h
@@ -1,27 +1,27 @@
-/***************************************************************************/
-/* */
-/* psnamerr.h */
-/* */
-/* PS names module error codes (specification only). */
-/* */
-/* Copyright 2001-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* This file is used to define the PS names module error enumeration */
- /* constants. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * psnamerr.h
+ *
+ * PS names module error codes (specification only).
+ *
+ * Copyright (C) 2001-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * This file is used to define the PS names module error enumeration
+ * constants.
+ *
+ */
#ifndef PSNAMERR_H_
#define PSNAMERR_H_
diff --git a/thirdparty/freetype/src/psnames/psnames.c b/thirdparty/freetype/src/psnames/psnames.c
index febb80d594..4722f98831 100644
--- a/thirdparty/freetype/src/psnames/psnames.c
+++ b/thirdparty/freetype/src/psnames/psnames.c
@@ -1,26 +1,25 @@
-/***************************************************************************/
-/* */
-/* psnames.c */
-/* */
-/* FreeType PSNames module component (body only). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * psnames.c
+ *
+ * FreeType psnames module component (body only).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#define FT_MAKE_OPTION_SINGLE_OBJECT
#include <ft2build.h>
#include "psmodule.c"
-#include "pspic.c"
/* END */
diff --git a/thirdparty/freetype/src/psnames/pspic.c b/thirdparty/freetype/src/psnames/pspic.c
deleted file mode 100644
index 85a06f3603..0000000000
--- a/thirdparty/freetype/src/psnames/pspic.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/***************************************************************************/
-/* */
-/* pspic.c */
-/* */
-/* The FreeType position independent code services for psnames module. */
-/* */
-/* Copyright 2009-2018 by */
-/* Oran Agra and Mickey Gabel. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#include <ft2build.h>
-#include FT_FREETYPE_H
-#include FT_INTERNAL_OBJECTS_H
-#include "pspic.h"
-#include "psnamerr.h"
-
-
-#ifdef FT_CONFIG_OPTION_PIC
-
- /* forward declaration of PIC init functions from psmodule.c */
- FT_Error
- FT_Create_Class_pscmaps_services( FT_Library library,
- FT_ServiceDescRec** output_class );
- void
- FT_Destroy_Class_pscmaps_services( FT_Library library,
- FT_ServiceDescRec* clazz );
-
- void
- FT_Init_Class_pscmaps_interface( FT_Library library,
- FT_Service_PsCMapsRec* clazz );
-
-
- void
- psnames_module_class_pic_free( FT_Library library )
- {
- FT_PIC_Container* pic_container = &library->pic_container;
- FT_Memory memory = library->memory;
-
-
- if ( pic_container->psnames )
- {
- PSModulePIC* container = (PSModulePIC*)pic_container->psnames;
-
-
- if ( container->pscmaps_services )
- FT_Destroy_Class_pscmaps_services( library,
- container->pscmaps_services );
- container->pscmaps_services = NULL;
- FT_FREE( container );
- pic_container->psnames = NULL;
- }
- }
-
-
- FT_Error
- psnames_module_class_pic_init( FT_Library library )
- {
- FT_PIC_Container* pic_container = &library->pic_container;
- FT_Error error = FT_Err_Ok;
- PSModulePIC* container = NULL;
- FT_Memory memory = library->memory;
-
-
- /* allocate pointer, clear and set global container pointer */
- if ( FT_ALLOC( container, sizeof ( *container ) ) )
- return error;
- FT_MEM_SET( container, 0, sizeof ( *container ) );
- pic_container->psnames = container;
-
- /* initialize pointer table - */
- /* this is how the module usually expects this data */
- error = FT_Create_Class_pscmaps_services(
- library, &container->pscmaps_services );
- if ( error )
- goto Exit;
- FT_Init_Class_pscmaps_interface( library,
- &container->pscmaps_interface );
-
- Exit:
- if ( error )
- psnames_module_class_pic_free( library );
- return error;
- }
-
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
-
-/* END */
diff --git a/thirdparty/freetype/src/psnames/pspic.h b/thirdparty/freetype/src/psnames/pspic.h
deleted file mode 100644
index 889780cc03..0000000000
--- a/thirdparty/freetype/src/psnames/pspic.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/***************************************************************************/
-/* */
-/* pspic.h */
-/* */
-/* The FreeType position independent code services for psnames module. */
-/* */
-/* Copyright 2009-2018 by */
-/* Oran Agra and Mickey Gabel. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#ifndef PSPIC_H_
-#define PSPIC_H_
-
-
-#include FT_INTERNAL_PIC_H
-
-
-#ifndef FT_CONFIG_OPTION_PIC
-
-#define PSCMAPS_SERVICES_GET pscmaps_services
-#define PSCMAPS_INTERFACE_GET pscmaps_interface
-
-#else /* FT_CONFIG_OPTION_PIC */
-
-#include FT_SERVICE_POSTSCRIPT_CMAPS_H
-
-
-FT_BEGIN_HEADER
-
- typedef struct PSModulePIC_
- {
- FT_ServiceDescRec* pscmaps_services;
- FT_Service_PsCMapsRec pscmaps_interface;
-
- } PSModulePIC;
-
-
-#define GET_PIC( lib ) \
- ( (PSModulePIC*)((lib)->pic_container.psnames) )
-#define PSCMAPS_SERVICES_GET ( GET_PIC( library )->pscmaps_services )
-#define PSCMAPS_INTERFACE_GET ( GET_PIC( library )->pscmaps_interface )
-
-
- /* see pspic.c for the implementation */
- void
- psnames_module_class_pic_free( FT_Library library );
-
- FT_Error
- psnames_module_class_pic_init( FT_Library library );
-
-FT_END_HEADER
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
- /* */
-
-#endif /* PSPIC_H_ */
-
-
-/* END */
diff --git a/thirdparty/freetype/src/psnames/pstables.h b/thirdparty/freetype/src/psnames/pstables.h
index 79545ee039..c0139bbc60 100644
--- a/thirdparty/freetype/src/psnames/pstables.h
+++ b/thirdparty/freetype/src/psnames/pstables.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* pstables.h */
-/* */
-/* PostScript glyph names. */
-/* */
-/* Copyright 2005-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * pstables.h
+ *
+ * PostScript glyph names.
+ *
+ * Copyright (C) 2005-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
/* This file has been generated automatically -- do not edit! */
@@ -609,12 +609,12 @@
/*
- * This table is a compressed version of the Adobe Glyph List (AGL),
- * optimized for efficient searching. It has been generated by the
- * `glnames.py' python script located in the `src/tools' directory.
+ * This table is a compressed version of the Adobe Glyph List (AGL),
+ * optimized for efficient searching. It has been generated by the
+ * `glnames.py' python script located in the `src/tools' directory.
*
- * The lookup function to get the Unicode value for a given string
- * is defined below the table.
+ * The lookup function to get the Unicode value for a given string
+ * is defined below the table.
*/
#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
@@ -4137,7 +4137,7 @@
#ifdef DEFINE_PS_TABLES
/*
- * This function searches the compressed table efficiently.
+ * This function searches the compressed table efficiently.
*/
static unsigned long
ft_get_adobe_glyph_index( const char* name,
diff --git a/thirdparty/freetype/src/psnames/rules.mk b/thirdparty/freetype/src/psnames/rules.mk
index 4d629d841c..dcc203e391 100644
--- a/thirdparty/freetype/src/psnames/rules.mk
+++ b/thirdparty/freetype/src/psnames/rules.mk
@@ -1,9 +1,9 @@
#
-# FreeType 2 PSNames driver configuration rules
+# FreeType 2 psnames driver configuration rules
#
-# Copyright 1996-2018 by
+# Copyright (C) 1996-2019 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
@@ -13,7 +13,7 @@
# fully.
-# PSNames driver directory
+# psnames driver directory
#
PSNAMES_DIR := $(SRC_DIR)/psnames
@@ -26,20 +26,19 @@ PSNAMES_COMPILE := $(CC) $(ANSIFLAGS) \
$(FT_CFLAGS)
-# PSNames driver sources (i.e., C files)
+# psnames driver sources (i.e., C files)
#
-PSNAMES_DRV_SRC := $(PSNAMES_DIR)/psmodule.c \
- $(PSNAMES_DIR)/pspic.c
+PSNAMES_DRV_SRC := $(PSNAMES_DIR)/psmodule.c
-# PSNames driver headers
+# psnames driver headers
#
PSNAMES_DRV_H := $(PSNAMES_DRV_SRC:%.c=%.h) \
$(PSNAMES_DIR)/psnamerr.h \
$(PSNAMES_DIR)/pstables.h
-# PSNames driver object(s)
+# psnames driver object(s)
#
# PSNAMES_DRV_OBJ_M is used during `multi' builds
# PSNAMES_DRV_OBJ_S is used during `single' builds
@@ -47,19 +46,19 @@ PSNAMES_DRV_H := $(PSNAMES_DRV_SRC:%.c=%.h) \
PSNAMES_DRV_OBJ_M := $(PSNAMES_DRV_SRC:$(PSNAMES_DIR)/%.c=$(OBJ_DIR)/%.$O)
PSNAMES_DRV_OBJ_S := $(OBJ_DIR)/psnames.$O
-# PSNames driver source file for single build
+# psnames driver source file for single build
#
PSNAMES_DRV_SRC_S := $(PSNAMES_DIR)/psnames.c
-# PSNames driver - single object
+# psnames driver - single object
#
$(PSNAMES_DRV_OBJ_S): $(PSNAMES_DRV_SRC_S) $(PSNAMES_DRV_SRC) \
$(FREETYPE_H) $(PSNAMES_DRV_H)
$(PSNAMES_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $(PSNAMES_DRV_SRC_S))
-# PSNames driver - multiple objects
+# psnames driver - multiple objects
#
$(OBJ_DIR)/%.$O: $(PSNAMES_DIR)/%.c $(FREETYPE_H) $(PSNAMES_DRV_H)
$(PSNAMES_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<)
diff --git a/thirdparty/freetype/src/raster/ftmisc.h b/thirdparty/freetype/src/raster/ftmisc.h
index 7e40119071..a246569e3b 100644
--- a/thirdparty/freetype/src/raster/ftmisc.h
+++ b/thirdparty/freetype/src/raster/ftmisc.h
@@ -1,28 +1,28 @@
-/***************************************************************************/
-/* */
-/* ftmisc.h */
-/* */
-/* Miscellaneous macros for stand-alone rasterizer (specification */
-/* only). */
-/* */
-/* Copyright 2005-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used */
-/* modified and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /***************************************************/
- /* */
- /* This file is *not* portable! You have to adapt */
- /* its definitions to your platform. */
- /* */
- /***************************************************/
+/****************************************************************************
+ *
+ * ftmisc.h
+ *
+ * Miscellaneous macros for stand-alone rasterizer (specification
+ * only).
+ *
+ * Copyright (C) 2005-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used
+ * modified and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /****************************************************
+ *
+ * This file is *not* portable! You have to adapt
+ * its definitions to your platform.
+ *
+ */
#ifndef FTMISC_H_
#define FTMISC_H_
diff --git a/thirdparty/freetype/src/raster/ftraster.c b/thirdparty/freetype/src/raster/ftraster.c
index 4354730d54..798a72d02a 100644
--- a/thirdparty/freetype/src/raster/ftraster.c
+++ b/thirdparty/freetype/src/raster/ftraster.c
@@ -1,51 +1,51 @@
-/***************************************************************************/
-/* */
-/* ftraster.c */
-/* */
-/* The FreeType glyph rasterizer (body). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
- /*************************************************************************/
- /* */
- /* This file can be compiled without the rest of the FreeType engine, by */
- /* defining the STANDALONE_ macro when compiling it. You also need to */
- /* put the files `ftimage.h' and `ftmisc.h' into the $(incdir) */
- /* directory. Typically, you should do something like */
- /* */
- /* - copy `src/raster/ftraster.c' (this file) to your current directory */
- /* */
- /* - copy `include/freetype/ftimage.h' and `src/raster/ftmisc.h' to your */
- /* current directory */
- /* */
- /* - compile `ftraster' with the STANDALONE_ macro defined, as in */
- /* */
- /* cc -c -DSTANDALONE_ ftraster.c */
- /* */
- /* The renderer can be initialized with a call to */
- /* `ft_standard_raster.raster_new'; a bitmap can be generated */
- /* with a call to `ft_standard_raster.raster_render'. */
- /* */
- /* See the comments and documentation in the file `ftimage.h' for more */
- /* details on how the raster works. */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* This is a rewrite of the FreeType 1.x scan-line converter */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * ftraster.c
+ *
+ * The FreeType glyph rasterizer (body).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+ /**************************************************************************
+ *
+ * This file can be compiled without the rest of the FreeType engine, by
+ * defining the STANDALONE_ macro when compiling it. You also need to
+ * put the files `ftimage.h' and `ftmisc.h' into the $(incdir)
+ * directory. Typically, you should do something like
+ *
+ * - copy `src/raster/ftraster.c' (this file) to your current directory
+ *
+ * - copy `include/freetype/ftimage.h' and `src/raster/ftmisc.h' to your
+ * current directory
+ *
+ * - compile `ftraster' with the STANDALONE_ macro defined, as in
+ *
+ * cc -c -DSTANDALONE_ ftraster.c
+ *
+ * The renderer can be initialized with a call to
+ * `ft_standard_raster.raster_new'; a bitmap can be generated
+ * with a call to `ft_standard_raster.raster_render'.
+ *
+ * See the comments and documentation in the file `ftimage.h' for more
+ * details on how the raster works.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * This is a rewrite of the FreeType 1.x scan-line converter
+ *
+ */
#ifdef STANDALONE_
@@ -65,82 +65,81 @@
#include <ft2build.h>
#include "ftraster.h"
#include FT_INTERNAL_CALC_H /* for FT_MulDiv and FT_MulDiv_No_Round */
-
-#include "rastpic.h"
+#include FT_OUTLINE_H /* for FT_Outline_Get_CBox */
#endif /* !STANDALONE_ */
- /*************************************************************************/
- /* */
- /* A simple technical note on how the raster works */
- /* ----------------------------------------------- */
- /* */
- /* Converting an outline into a bitmap is achieved in several steps: */
- /* */
- /* 1 - Decomposing the outline into successive `profiles'. Each */
- /* profile is simply an array of scanline intersections on a given */
- /* dimension. A profile's main attributes are */
- /* */
- /* o its scanline position boundaries, i.e. `Ymin' and `Ymax' */
- /* */
- /* o an array of intersection coordinates for each scanline */
- /* between `Ymin' and `Ymax' */
- /* */
- /* o a direction, indicating whether it was built going `up' or */
- /* `down', as this is very important for filling rules */
- /* */
- /* o its drop-out mode */
- /* */
- /* 2 - Sweeping the target map's scanlines in order to compute segment */
- /* `spans' which are then filled. Additionally, this pass */
- /* performs drop-out control. */
- /* */
- /* The outline data is parsed during step 1 only. The profiles are */
- /* built from the bottom of the render pool, used as a stack. The */
- /* following graphics shows the profile list under construction: */
- /* */
- /* __________________________________________________________ _ _ */
- /* | | | | | */
- /* | profile | coordinates for | profile | coordinates for |--> */
- /* | 1 | profile 1 | 2 | profile 2 |--> */
- /* |_________|_________________|_________|_________________|__ _ _ */
- /* */
- /* ^ ^ */
- /* | | */
- /* start of render pool top */
- /* */
- /* The top of the profile stack is kept in the `top' variable. */
- /* */
- /* As you can see, a profile record is pushed on top of the render */
- /* pool, which is then followed by its coordinates/intersections. If */
- /* a change of direction is detected in the outline, a new profile is */
- /* generated until the end of the outline. */
- /* */
- /* Note that when all profiles have been generated, the function */
- /* Finalize_Profile_Table() is used to record, for each profile, its */
- /* bottom-most scanline as well as the scanline above its upmost */
- /* boundary. These positions are called `y-turns' because they (sort */
- /* of) correspond to local extrema. They are stored in a sorted list */
- /* built from the top of the render pool as a downwards stack: */
- /* */
- /* _ _ _______________________________________ */
- /* | | */
- /* <--| sorted list of | */
- /* <--| extrema scanlines | */
- /* _ _ __________________|____________________| */
- /* */
- /* ^ ^ */
- /* | | */
- /* maxBuff sizeBuff = end of pool */
- /* */
- /* This list is later used during the sweep phase in order to */
- /* optimize performance (see technical note on the sweep below). */
- /* */
- /* Of course, the raster detects whether the two stacks collide and */
- /* handles the situation properly. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * A simple technical note on how the raster works
+ * -----------------------------------------------
+ *
+ * Converting an outline into a bitmap is achieved in several steps:
+ *
+ * 1 - Decomposing the outline into successive `profiles'. Each
+ * profile is simply an array of scanline intersections on a given
+ * dimension. A profile's main attributes are
+ *
+ * o its scanline position boundaries, i.e. `Ymin' and `Ymax'
+ *
+ * o an array of intersection coordinates for each scanline
+ * between `Ymin' and `Ymax'
+ *
+ * o a direction, indicating whether it was built going `up' or
+ * `down', as this is very important for filling rules
+ *
+ * o its drop-out mode
+ *
+ * 2 - Sweeping the target map's scanlines in order to compute segment
+ * `spans' which are then filled. Additionally, this pass
+ * performs drop-out control.
+ *
+ * The outline data is parsed during step 1 only. The profiles are
+ * built from the bottom of the render pool, used as a stack. The
+ * following graphics shows the profile list under construction:
+ *
+ * __________________________________________________________ _ _
+ * | | | | |
+ * | profile | coordinates for | profile | coordinates for |-->
+ * | 1 | profile 1 | 2 | profile 2 |-->
+ * |_________|_________________|_________|_________________|__ _ _
+ *
+ * ^ ^
+ * | |
+ * start of render pool top
+ *
+ * The top of the profile stack is kept in the `top' variable.
+ *
+ * As you can see, a profile record is pushed on top of the render
+ * pool, which is then followed by its coordinates/intersections. If
+ * a change of direction is detected in the outline, a new profile is
+ * generated until the end of the outline.
+ *
+ * Note that when all profiles have been generated, the function
+ * Finalize_Profile_Table() is used to record, for each profile, its
+ * bottom-most scanline as well as the scanline above its upmost
+ * boundary. These positions are called `y-turns' because they (sort
+ * of) correspond to local extrema. They are stored in a sorted list
+ * built from the top of the render pool as a downwards stack:
+ *
+ * _ _ _______________________________________
+ * | |
+ * <--| sorted list of |
+ * <--| extrema scanlines |
+ * _ _ __________________|____________________|
+ *
+ * ^ ^
+ * | |
+ * maxBuff sizeBuff = end of pool
+ *
+ * This list is later used during the sweep phase in order to
+ * optimize performance (see technical note on the sweep below).
+ *
+ * Of course, the raster detects whether the two stacks collide and
+ * handles the situation properly.
+ *
+ */
/*************************************************************************/
@@ -163,14 +162,14 @@
/*************************************************************************/
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_raster
+#define FT_COMPONENT raster
#ifdef STANDALONE_
@@ -452,9 +451,9 @@
#define CEILING( x ) ( ( (x) + ras.precision - 1 ) & -ras.precision )
#define TRUNC( x ) ( (Long)(x) >> ras.precision_bits )
#define FRAC( x ) ( (x) & ( ras.precision - 1 ) )
-#define SCALED( x ) ( ( (x) < 0 ? -( -(x) << ras.scale_shift ) \
- : ( (x) << ras.scale_shift ) ) \
- - ras.precision_half )
+
+ /* scale and shift grid to pixel centers */
+#define SCALED( x ) ( (x) * ras.precision_scale - ras.precision_half )
#define IS_BOTTOM_OVERSHOOT( x ) \
(Bool)( CEILING( x ) - x >= ras.precision_half )
@@ -476,13 +475,10 @@
Int precision_bits; /* precision related variables */
Int precision;
Int precision_half;
- Int precision_shift;
+ Int precision_scale;
Int precision_step;
Int precision_jitter;
- Int scale_shift; /* == precision_shift for bitmaps */
- /* == precision_shift+1 for pixmaps */
-
PLong buff; /* The profiles buffer */
PLong sizeBuff; /* Render pool size */
PLong maxBuff; /* Profiles buffer size */
@@ -495,8 +491,7 @@
TPoint* arc; /* current Bezier arc pointer */
UShort bWidth; /* target bitmap width */
- PByte bTarget; /* target bitmap buffer */
- PByte gTarget; /* target pixmap buffer */
+ PByte bOrigin; /* target bitmap bottom-left origin */
Long lastX, lastY;
Long minY, maxY;
@@ -519,8 +514,6 @@
FT_Outline outline;
Long traceOfs; /* current offset in target bitmap */
- Long traceG; /* current offset in target pixmap */
-
Short traceIncr; /* sweep's increment in target bitmap */
/* dispatch variables */
@@ -572,18 +565,19 @@
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Set_High_Precision */
- /* */
- /* <Description> */
- /* Set precision variables according to param flag. */
- /* */
- /* <Input> */
- /* High :: Set to True for high precision (typically for ppem < 24), */
- /* false otherwise. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * Set_High_Precision
+ *
+ * @Description:
+ * Set precision variables according to param flag.
+ *
+ * @Input:
+ * High ::
+ * Set to True for high precision (typically for ppem < 24),
+ * false otherwise.
+ */
static void
Set_High_Precision( RAS_ARGS Int High )
{
@@ -625,29 +619,31 @@
FT_TRACE6(( "Set_High_Precision(%s)\n", High ? "true" : "false" ));
ras.precision = 1 << ras.precision_bits;
- ras.precision_half = ras.precision / 2;
- ras.precision_shift = ras.precision_bits - Pixel_Bits;
+ ras.precision_half = ras.precision >> 1;
+ ras.precision_scale = ras.precision >> Pixel_Bits;
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* New_Profile */
- /* */
- /* <Description> */
- /* Create a new profile in the render pool. */
- /* */
- /* <Input> */
- /* aState :: The state/orientation of the new profile. */
- /* */
- /* overshoot :: Whether the profile's unrounded start position */
- /* differs by at least a half pixel. */
- /* */
- /* <Return> */
- /* SUCCESS on success. FAILURE in case of overflow or of incoherent */
- /* profile. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * New_Profile
+ *
+ * @Description:
+ * Create a new profile in the render pool.
+ *
+ * @Input:
+ * aState ::
+ * The state/orientation of the new profile.
+ *
+ * overshoot ::
+ * Whether the profile's unrounded start position
+ * differs by at least a half pixel.
+ *
+ * @Return:
+ * SUCCESS on success. FAILURE in case of overflow or of incoherent
+ * profile.
+ */
static Bool
New_Profile( RAS_ARGS TStates aState,
Bool overshoot )
@@ -706,21 +702,22 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* End_Profile */
- /* */
- /* <Description> */
- /* Finalize the current profile. */
- /* */
- /* <Input> */
- /* overshoot :: Whether the profile's unrounded end position differs */
- /* by at least a half pixel. */
- /* */
- /* <Return> */
- /* SUCCESS on success. FAILURE in case of overflow or incoherency. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * End_Profile
+ *
+ * @Description:
+ * Finalize the current profile.
+ *
+ * @Input:
+ * overshoot ::
+ * Whether the profile's unrounded end position differs
+ * by at least a half pixel.
+ *
+ * @Return:
+ * SUCCESS on success. FAILURE in case of overflow or incoherency.
+ */
static Bool
End_Profile( RAS_ARGS Bool overshoot )
{
@@ -778,21 +775,21 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Insert_Y_Turn */
- /* */
- /* <Description> */
- /* Insert a salient into the sorted list placed on top of the render */
- /* pool. */
- /* */
- /* <Input> */
- /* New y scanline position. */
- /* */
- /* <Return> */
- /* SUCCESS on success. FAILURE in case of overflow. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * Insert_Y_Turn
+ *
+ * @Description:
+ * Insert a salient into the sorted list placed on top of the render
+ * pool.
+ *
+ * @Input:
+ * New y scanline position.
+ *
+ * @Return:
+ * SUCCESS on success. FAILURE in case of overflow.
+ */
static Bool
Insert_Y_Turn( RAS_ARGS Int y )
{
@@ -834,17 +831,17 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Finalize_Profile_Table */
- /* */
- /* <Description> */
- /* Adjust all links in the profiles list. */
- /* */
- /* <Return> */
- /* SUCCESS on success. FAILURE in case of overflow. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * Finalize_Profile_Table
+ *
+ * @Description:
+ * Adjust all links in the profiles list.
+ *
+ * @Return:
+ * SUCCESS on success. FAILURE in case of overflow.
+ */
static Bool
Finalize_Profile_Table( RAS_ARG )
{
@@ -894,22 +891,22 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Split_Conic */
- /* */
- /* <Description> */
- /* Subdivide one conic Bezier into two joint sub-arcs in the Bezier */
- /* stack. */
- /* */
- /* <Input> */
- /* None (subdivided Bezier is taken from the top of the stack). */
- /* */
- /* <Note> */
- /* This routine is the `beef' of this component. It is _the_ inner */
- /* loop that should be optimized to hell to get the best performance. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * Split_Conic
+ *
+ * @Description:
+ * Subdivide one conic Bezier into two joint sub-arcs in the Bezier
+ * stack.
+ *
+ * @Input:
+ * None (subdivided Bezier is taken from the top of the stack).
+ *
+ * @Note:
+ * This routine is the `beef' of this component. It is _the_ inner
+ * loop that should be optimized to hell to get the best performance.
+ */
static void
Split_Conic( TPoint* base )
{
@@ -933,20 +930,20 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Split_Cubic */
- /* */
- /* <Description> */
- /* Subdivide a third-order Bezier arc into two joint sub-arcs in the */
- /* Bezier stack. */
- /* */
- /* <Note> */
- /* This routine is the `beef' of the component. It is one of _the_ */
- /* inner loops that should be optimized like hell to get the best */
- /* performance. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * Split_Cubic
+ *
+ * @Description:
+ * Subdivide a third-order Bezier arc into two joint sub-arcs in the
+ * Bezier stack.
+ *
+ * @Note:
+ * This routine is the `beef' of the component. It is one of _the_
+ * inner loops that should be optimized like hell to get the best
+ * performance.
+ */
static void
Split_Cubic( TPoint* base )
{
@@ -975,31 +972,37 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Line_Up */
- /* */
- /* <Description> */
- /* Compute the x-coordinates of an ascending line segment and store */
- /* them in the render pool. */
- /* */
- /* <Input> */
- /* x1 :: The x-coordinate of the segment's start point. */
- /* */
- /* y1 :: The y-coordinate of the segment's start point. */
- /* */
- /* x2 :: The x-coordinate of the segment's end point. */
- /* */
- /* y2 :: The y-coordinate of the segment's end point. */
- /* */
- /* miny :: A lower vertical clipping bound value. */
- /* */
- /* maxy :: An upper vertical clipping bound value. */
- /* */
- /* <Return> */
- /* SUCCESS on success, FAILURE on render pool overflow. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * Line_Up
+ *
+ * @Description:
+ * Compute the x-coordinates of an ascending line segment and store
+ * them in the render pool.
+ *
+ * @Input:
+ * x1 ::
+ * The x-coordinate of the segment's start point.
+ *
+ * y1 ::
+ * The y-coordinate of the segment's start point.
+ *
+ * x2 ::
+ * The x-coordinate of the segment's end point.
+ *
+ * y2 ::
+ * The y-coordinate of the segment's end point.
+ *
+ * miny ::
+ * A lower vertical clipping bound value.
+ *
+ * maxy ::
+ * An upper vertical clipping bound value.
+ *
+ * @Return:
+ * SUCCESS on success, FAILURE on render pool overflow.
+ */
static Bool
Line_Up( RAS_ARGS Long x1,
Long y1,
@@ -1114,31 +1117,37 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Line_Down */
- /* */
- /* <Description> */
- /* Compute the x-coordinates of an descending line segment and store */
- /* them in the render pool. */
- /* */
- /* <Input> */
- /* x1 :: The x-coordinate of the segment's start point. */
- /* */
- /* y1 :: The y-coordinate of the segment's start point. */
- /* */
- /* x2 :: The x-coordinate of the segment's end point. */
- /* */
- /* y2 :: The y-coordinate of the segment's end point. */
- /* */
- /* miny :: A lower vertical clipping bound value. */
- /* */
- /* maxy :: An upper vertical clipping bound value. */
- /* */
- /* <Return> */
- /* SUCCESS on success, FAILURE on render pool overflow. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * Line_Down
+ *
+ * @Description:
+ * Compute the x-coordinates of an descending line segment and store
+ * them in the render pool.
+ *
+ * @Input:
+ * x1 ::
+ * The x-coordinate of the segment's start point.
+ *
+ * y1 ::
+ * The y-coordinate of the segment's start point.
+ *
+ * x2 ::
+ * The x-coordinate of the segment's end point.
+ *
+ * y2 ::
+ * The y-coordinate of the segment's end point.
+ *
+ * miny ::
+ * A lower vertical clipping bound value.
+ *
+ * maxy ::
+ * An upper vertical clipping bound value.
+ *
+ * @Return:
+ * SUCCESS on success, FAILURE on render pool overflow.
+ */
static Bool
Line_Down( RAS_ARGS Long x1,
Long y1,
@@ -1165,27 +1174,31 @@
typedef void (*TSplitter)( TPoint* base );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Bezier_Up */
- /* */
- /* <Description> */
- /* Compute the x-coordinates of an ascending Bezier arc and store */
- /* them in the render pool. */
- /* */
- /* <Input> */
- /* degree :: The degree of the Bezier arc (either 2 or 3). */
- /* */
- /* splitter :: The function to split Bezier arcs. */
- /* */
- /* miny :: A lower vertical clipping bound value. */
- /* */
- /* maxy :: An upper vertical clipping bound value. */
- /* */
- /* <Return> */
- /* SUCCESS on success, FAILURE on render pool overflow. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * Bezier_Up
+ *
+ * @Description:
+ * Compute the x-coordinates of an ascending Bezier arc and store
+ * them in the render pool.
+ *
+ * @Input:
+ * degree ::
+ * The degree of the Bezier arc (either 2 or 3).
+ *
+ * splitter ::
+ * The function to split Bezier arcs.
+ *
+ * miny ::
+ * A lower vertical clipping bound value.
+ *
+ * maxy ::
+ * An upper vertical clipping bound value.
+ *
+ * @Return:
+ * SUCCESS on success, FAILURE on render pool overflow.
+ */
static Bool
Bezier_Up( RAS_ARGS Int degree,
TSplitter splitter,
@@ -1298,27 +1311,31 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Bezier_Down */
- /* */
- /* <Description> */
- /* Compute the x-coordinates of an descending Bezier arc and store */
- /* them in the render pool. */
- /* */
- /* <Input> */
- /* degree :: The degree of the Bezier arc (either 2 or 3). */
- /* */
- /* splitter :: The function to split Bezier arcs. */
- /* */
- /* miny :: A lower vertical clipping bound value. */
- /* */
- /* maxy :: An upper vertical clipping bound value. */
- /* */
- /* <Return> */
- /* SUCCESS on success, FAILURE on render pool overflow. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * Bezier_Down
+ *
+ * @Description:
+ * Compute the x-coordinates of an descending Bezier arc and store
+ * them in the render pool.
+ *
+ * @Input:
+ * degree ::
+ * The degree of the Bezier arc (either 2 or 3).
+ *
+ * splitter ::
+ * The function to split Bezier arcs.
+ *
+ * miny ::
+ * A lower vertical clipping bound value.
+ *
+ * maxy ::
+ * An upper vertical clipping bound value.
+ *
+ * @Return:
+ * SUCCESS on success, FAILURE on render pool overflow.
+ */
static Bool
Bezier_Down( RAS_ARGS Int degree,
TSplitter splitter,
@@ -1347,25 +1364,27 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Line_To */
- /* */
- /* <Description> */
- /* Inject a new line segment and adjust the Profiles list. */
- /* */
- /* <Input> */
- /* x :: The x-coordinate of the segment's end point (its start point */
- /* is stored in `lastX'). */
- /* */
- /* y :: The y-coordinate of the segment's end point (its start point */
- /* is stored in `lastY'). */
- /* */
- /* <Return> */
- /* SUCCESS on success, FAILURE on render pool overflow or incorrect */
- /* profile. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * Line_To
+ *
+ * @Description:
+ * Inject a new line segment and adjust the Profiles list.
+ *
+ * @Input:
+ * x ::
+ * The x-coordinate of the segment's end point (its start point
+ * is stored in `lastX').
+ *
+ * y ::
+ * The y-coordinate of the segment's end point (its start point
+ * is stored in `lastY').
+ *
+ * @Return:
+ * SUCCESS on success, FAILURE on render pool overflow or incorrect
+ * profile.
+ */
static Bool
Line_To( RAS_ARGS Long x,
Long y )
@@ -1441,29 +1460,33 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Conic_To */
- /* */
- /* <Description> */
- /* Inject a new conic arc and adjust the profile list. */
- /* */
- /* <Input> */
- /* cx :: The x-coordinate of the arc's new control point. */
- /* */
- /* cy :: The y-coordinate of the arc's new control point. */
- /* */
- /* x :: The x-coordinate of the arc's end point (its start point is */
- /* stored in `lastX'). */
- /* */
- /* y :: The y-coordinate of the arc's end point (its start point is */
- /* stored in `lastY'). */
- /* */
- /* <Return> */
- /* SUCCESS on success, FAILURE on render pool overflow or incorrect */
- /* profile. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * Conic_To
+ *
+ * @Description:
+ * Inject a new conic arc and adjust the profile list.
+ *
+ * @Input:
+ * cx ::
+ * The x-coordinate of the arc's new control point.
+ *
+ * cy ::
+ * The y-coordinate of the arc's new control point.
+ *
+ * x ::
+ * The x-coordinate of the arc's end point (its start point is
+ * stored in `lastX').
+ *
+ * y ::
+ * The y-coordinate of the arc's end point (its start point is
+ * stored in `lastY').
+ *
+ * @Return:
+ * SUCCESS on success, FAILURE on render pool overflow or incorrect
+ * profile.
+ */
static Bool
Conic_To( RAS_ARGS Long cx,
Long cy,
@@ -1558,33 +1581,39 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Cubic_To */
- /* */
- /* <Description> */
- /* Inject a new cubic arc and adjust the profile list. */
- /* */
- /* <Input> */
- /* cx1 :: The x-coordinate of the arc's first new control point. */
- /* */
- /* cy1 :: The y-coordinate of the arc's first new control point. */
- /* */
- /* cx2 :: The x-coordinate of the arc's second new control point. */
- /* */
- /* cy2 :: The y-coordinate of the arc's second new control point. */
- /* */
- /* x :: The x-coordinate of the arc's end point (its start point is */
- /* stored in `lastX'). */
- /* */
- /* y :: The y-coordinate of the arc's end point (its start point is */
- /* stored in `lastY'). */
- /* */
- /* <Return> */
- /* SUCCESS on success, FAILURE on render pool overflow or incorrect */
- /* profile. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * Cubic_To
+ *
+ * @Description:
+ * Inject a new cubic arc and adjust the profile list.
+ *
+ * @Input:
+ * cx1 ::
+ * The x-coordinate of the arc's first new control point.
+ *
+ * cy1 ::
+ * The y-coordinate of the arc's first new control point.
+ *
+ * cx2 ::
+ * The x-coordinate of the arc's second new control point.
+ *
+ * cy2 ::
+ * The y-coordinate of the arc's second new control point.
+ *
+ * x ::
+ * The x-coordinate of the arc's end point (its start point is
+ * stored in `lastX').
+ *
+ * y ::
+ * The y-coordinate of the arc's end point (its start point is
+ * stored in `lastY').
+ *
+ * @Return:
+ * SUCCESS on success, FAILURE on render pool overflow or incorrect
+ * profile.
+ */
static Bool
Cubic_To( RAS_ARGS Long cx1,
Long cy1,
@@ -1705,27 +1734,30 @@
} while ( 0 )
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Decompose_Curve */
- /* */
- /* <Description> */
- /* Scan the outline arrays in order to emit individual segments and */
- /* Beziers by calling Line_To() and Bezier_To(). It handles all */
- /* weird cases, like when the first point is off the curve, or when */
- /* there are simply no `on' points in the contour! */
- /* */
- /* <Input> */
- /* first :: The index of the first point in the contour. */
- /* */
- /* last :: The index of the last point in the contour. */
- /* */
- /* flipped :: If set, flip the direction of the curve. */
- /* */
- /* <Return> */
- /* SUCCESS on success, FAILURE on error. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * Decompose_Curve
+ *
+ * @Description:
+ * Scan the outline arrays in order to emit individual segments and
+ * Beziers by calling Line_To() and Bezier_To(). It handles all
+ * weird cases, like when the first point is off the curve, or when
+ * there are simply no `on' points in the contour!
+ *
+ * @Input:
+ * first ::
+ * The index of the first point in the contour.
+ *
+ * last ::
+ * The index of the last point in the contour.
+ *
+ * flipped ::
+ * If set, flip the direction of the curve.
+ *
+ * @Return:
+ * SUCCESS on success, FAILURE on error.
+ */
static Bool
Decompose_Curve( RAS_ARGS UShort first,
UShort last,
@@ -1934,22 +1966,23 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Convert_Glyph */
- /* */
- /* <Description> */
- /* Convert a glyph into a series of segments and arcs and make a */
- /* profiles list with them. */
- /* */
- /* <Input> */
- /* flipped :: If set, flip the direction of curve. */
- /* */
- /* <Return> */
- /* SUCCESS on success, FAILURE if any error was encountered during */
- /* rendering. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * Convert_Glyph
+ *
+ * @Description:
+ * Convert a glyph into a series of segments and arcs and make a
+ * profiles list with them.
+ *
+ * @Input:
+ * flipped ::
+ * If set, flip the direction of curve.
+ *
+ * @Return:
+ * SUCCESS on success, FAILURE if any error was encountered during
+ * rendering.
+ */
static Bool
Convert_Glyph( RAS_ARGS Int flipped )
{
@@ -2028,12 +2061,12 @@
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* Init_Linked */
- /* */
- /* Initializes an empty linked list. */
- /* */
+ /**************************************************************************
+ *
+ * Init_Linked
+ *
+ * Initializes an empty linked list.
+ */
static void
Init_Linked( TProfileList* l )
{
@@ -2041,12 +2074,12 @@
}
- /*************************************************************************/
- /* */
- /* InsNew */
- /* */
- /* Inserts a new profile in a linked list. */
- /* */
+ /**************************************************************************
+ *
+ * InsNew
+ *
+ * Inserts a new profile in a linked list.
+ */
static void
InsNew( PProfileList list,
PProfile profile )
@@ -2072,12 +2105,12 @@
}
- /*************************************************************************/
- /* */
- /* DelOld */
- /* */
- /* Removes an old profile from a linked list. */
- /* */
+ /**************************************************************************
+ *
+ * DelOld
+ *
+ * Removes an old profile from a linked list.
+ */
static void
DelOld( PProfileList list,
PProfile profile )
@@ -2105,14 +2138,14 @@
}
- /*************************************************************************/
- /* */
- /* Sort */
- /* */
- /* Sorts a trace list. In 95%, the list is already sorted. We need */
- /* an algorithm which is fast in this case. Bubble sort is enough */
- /* and simple. */
- /* */
+ /**************************************************************************
+ *
+ * Sort
+ *
+ * Sorts a trace list. In 95%, the list is already sorted. We need
+ * an algorithm which is fast in this case. Bubble sort is enough
+ * and simple.
+ */
static void
Sort( PProfileList list )
{
@@ -2163,14 +2196,14 @@
}
- /*************************************************************************/
- /* */
- /* Vertical Sweep Procedure Set */
- /* */
- /* These four routines are used during the vertical black/white sweep */
- /* phase by the generic Draw_Sweep() function. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * Vertical Sweep Procedure Set
+ *
+ * These four routines are used during the vertical black/white sweep
+ * phase by the generic Draw_Sweep() function.
+ *
+ */
static void
Vertical_Sweep_Init( RAS_ARGS Short* min,
@@ -2183,8 +2216,6 @@
ras.traceIncr = (Short)-pitch;
ras.traceOfs = -*min * pitch;
- if ( pitch > 0 )
- ras.traceOfs += (Long)( ras.target.rows - 1 ) * pitch;
}
@@ -2215,13 +2246,18 @@
/* Drop-out control */
- e1 = TRUNC( CEILING( x1 ) );
+ e1 = CEILING( x1 );
+ e2 = FLOOR( x2 );
+ /* take care of the special case where both the left */
+ /* and right contour lie exactly on pixel centers */
if ( dropOutControl != 2 &&
- x2 - x1 - ras.precision <= ras.precision_jitter )
+ x2 - x1 - ras.precision <= ras.precision_jitter &&
+ e1 != x1 && e2 != x2 )
e2 = e1;
- else
- e2 = TRUNC( FLOOR( x2 ) );
+
+ e1 = TRUNC( e1 );
+ e2 = TRUNC( e2 );
if ( e2 >= 0 && e1 < ras.bWidth )
{
@@ -2242,7 +2278,7 @@
f1 = (Byte) ( 0xFF >> ( e1 & 7 ) );
f2 = (Byte) ~( 0x7F >> ( e2 & 7 ) );
- target = ras.bTarget + ras.traceOfs + c1;
+ target = ras.bOrigin + ras.traceOfs + c1;
c2 -= c1;
if ( c2 > 0 )
@@ -2252,12 +2288,9 @@
/* memset() is slower than the following code on many platforms. */
/* This is due to the fact that, in the vast majority of cases, */
/* the span length in bytes is relatively small. */
- c2--;
- while ( c2 > 0 )
- {
+ while ( --c2 > 0 )
*(++target) = 0xFF;
- c2--;
- }
+
target[1] |= f2;
}
else
@@ -2400,7 +2433,7 @@
f1 = (Short)( e1 & 7 );
if ( e1 >= 0 && e1 < ras.bWidth &&
- ras.bTarget[ras.traceOfs + c1] & ( 0x80 >> f1 ) )
+ ras.bOrigin[ras.traceOfs + c1] & ( 0x80 >> f1 ) )
goto Exit;
}
else
@@ -2416,7 +2449,7 @@
c1 = (Short)( e1 >> 3 );
f1 = (Short)( e1 & 7 );
- ras.bTarget[ras.traceOfs + c1] |= (char)( 0x80 >> f1 );
+ ras.bOrigin[ras.traceOfs + c1] |= (char)( 0x80 >> f1 );
}
Exit:
@@ -2431,14 +2464,14 @@
}
- /***********************************************************************/
- /* */
- /* Horizontal Sweep Procedure Set */
- /* */
- /* These four routines are used during the horizontal black/white */
- /* sweep phase by the generic Draw_Sweep() function. */
- /* */
- /***********************************************************************/
+ /************************************************************************
+ *
+ * Horizontal Sweep Procedure Set
+ *
+ * These four routines are used during the horizontal black/white
+ * sweep phase by the generic Draw_Sweep() function.
+ *
+ */
static void
Horizontal_Sweep_Init( RAS_ARGS Short* min,
@@ -2483,19 +2516,14 @@
{
Byte f1;
PByte bits;
- PByte p;
FT_TRACE7(( " -> y=%d (drop-out)", e1 ));
- bits = ras.bTarget + ( y >> 3 );
+ bits = ras.bOrigin + ( y >> 3 ) - e1 * ras.target.pitch;
f1 = (Byte)( 0x80 >> ( y & 7 ) );
- p = bits - e1 * ras.target.pitch;
- if ( ras.target.pitch > 0 )
- p += (Long)( ras.target.rows - 1 ) * ras.target.pitch;
-
- p[0] |= f1;
+ bits[0] |= f1;
}
}
@@ -2597,13 +2625,9 @@
e1 = TRUNC( e1 );
- bits = ras.bTarget + ( y >> 3 );
+ bits = ras.bOrigin + ( y >> 3 ) - e1 * ras.target.pitch;
f1 = (Byte)( 0x80 >> ( y & 7 ) );
- bits -= e1 * ras.target.pitch;
- if ( ras.target.pitch > 0 )
- bits += (Long)( ras.target.rows - 1 ) * ras.target.pitch;
-
if ( e1 >= 0 &&
(ULong)e1 < ras.target.rows &&
*bits & f1 )
@@ -2619,12 +2643,8 @@
{
FT_TRACE7(( " -> y=%d (drop-out)", e1 ));
- bits = ras.bTarget + ( y >> 3 );
+ bits = ras.bOrigin + ( y >> 3 ) - e1 * ras.target.pitch;
f1 = (Byte)( 0x80 >> ( y & 7 ) );
- bits -= e1 * ras.target.pitch;
-
- if ( ras.target.pitch > 0 )
- bits += (Long)( ras.target.rows - 1 ) * ras.target.pitch;
bits[0] |= f1;
}
@@ -2642,11 +2662,11 @@
}
- /*************************************************************************/
- /* */
- /* Generic Sweep Drawing routine */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * Generic Sweep Drawing routine
+ *
+ */
static Bool
Draw_Sweep( RAS_ARG )
@@ -2888,20 +2908,109 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Render_Single_Pass */
- /* */
- /* <Description> */
- /* Perform one sweep with sub-banding. */
- /* */
- /* <Input> */
- /* flipped :: If set, flip the direction of the outline. */
- /* */
- /* <Return> */
- /* Renderer error code. */
- /* */
+#ifdef STANDALONE_
+
+ /**************************************************************************
+ *
+ * The following functions should only compile in stand-alone mode,
+ * i.e., when building this component without the rest of FreeType.
+ *
+ */
+
+ /**************************************************************************
+ *
+ * @Function:
+ * FT_Outline_Get_CBox
+ *
+ * @Description:
+ * Return an outline's `control box'. The control box encloses all
+ * the outline's points, including Bézier control points. Though it
+ * coincides with the exact bounding box for most glyphs, it can be
+ * slightly larger in some situations (like when rotating an outline
+ * that contains Bézier outside arcs).
+ *
+ * Computing the control box is very fast, while getting the bounding
+ * box can take much more time as it needs to walk over all segments
+ * and arcs in the outline. To get the latter, you can use the
+ * `ftbbox' component, which is dedicated to this single task.
+ *
+ * @Input:
+ * outline ::
+ * A pointer to the source outline descriptor.
+ *
+ * @Output:
+ * acbox ::
+ * The outline's control box.
+ *
+ * @Note:
+ * See @FT_Glyph_Get_CBox for a discussion of tricky fonts.
+ */
+
+ static void
+ FT_Outline_Get_CBox( const FT_Outline* outline,
+ FT_BBox *acbox )
+ {
+ Long xMin, yMin, xMax, yMax;
+
+
+ if ( outline && acbox )
+ {
+ if ( outline->n_points == 0 )
+ {
+ xMin = 0;
+ yMin = 0;
+ xMax = 0;
+ yMax = 0;
+ }
+ else
+ {
+ FT_Vector* vec = outline->points;
+ FT_Vector* limit = vec + outline->n_points;
+
+
+ xMin = xMax = vec->x;
+ yMin = yMax = vec->y;
+ vec++;
+
+ for ( ; vec < limit; vec++ )
+ {
+ Long x, y;
+
+
+ x = vec->x;
+ if ( x < xMin ) xMin = x;
+ if ( x > xMax ) xMax = x;
+
+ y = vec->y;
+ if ( y < yMin ) yMin = y;
+ if ( y > yMax ) yMax = y;
+ }
+ }
+ acbox->xMin = xMin;
+ acbox->xMax = xMax;
+ acbox->yMin = yMin;
+ acbox->yMax = yMax;
+ }
+ }
+
+#endif /* STANDALONE_ */
+
+
+ /**************************************************************************
+ *
+ * @Function:
+ * Render_Single_Pass
+ *
+ * @Description:
+ * Perform one sweep with sub-banding.
+ *
+ * @Input:
+ * flipped ::
+ * If set, flip the direction of the outline.
+ *
+ * @Return:
+ * Renderer error code.
+ */
static int
Render_Single_Pass( RAS_ARGS Bool flipped )
{
@@ -2963,17 +3072,17 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Render_Glyph */
- /* */
- /* <Description> */
- /* Render a glyph in a bitmap. Sub-banding if needed. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * Render_Glyph
+ *
+ * @Description:
+ * Render a glyph in a bitmap. Sub-banding if needed.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
static FT_Error
Render_Glyph( RAS_ARG )
{
@@ -2982,7 +3091,6 @@
Set_High_Precision( RAS_VARS ras.outline.flags &
FT_OUTLINE_HIGH_PRECISION );
- ras.scale_shift = ras.precision_shift;
if ( ras.outline.flags & FT_OUTLINE_IGNORE_DROPOUTS )
ras.dropOutControl = 2;
@@ -3013,7 +3121,10 @@
ras.band_stack[0].y_max = (Short)( ras.target.rows - 1 );
ras.bWidth = (UShort)ras.target.width;
- ras.bTarget = (Byte*)ras.target.buffer;
+ ras.bOrigin = (Byte*)ras.target.buffer;
+
+ if ( ras.target.pitch > 0 )
+ ras.bOrigin += (Long)( ras.target.rows - 1 ) * ras.target.pitch;
if ( ( error = Render_Single_Pass( RAS_VARS 0 ) ) != 0 )
return error;
@@ -3185,20 +3296,6 @@
if ( !target_map->buffer )
return FT_THROW( Invalid );
- /* reject too large outline coordinates */
- {
- FT_Vector* vec = outline->points;
- FT_Vector* limit = vec + outline->n_points;
-
-
- for ( ; vec < limit; vec++ )
- {
- if ( vec->x < -0x1000000L || vec->x > 0x1000000L ||
- vec->y < -0x1000000L || vec->y > 0x1000000L )
- return FT_THROW( Invalid );
- }
- }
-
ras.outline = *outline;
ras.target = *target_map;
diff --git a/thirdparty/freetype/src/raster/ftraster.h b/thirdparty/freetype/src/raster/ftraster.h
index 40b5d6d321..50d34201a1 100644
--- a/thirdparty/freetype/src/raster/ftraster.h
+++ b/thirdparty/freetype/src/raster/ftraster.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftraster.h */
-/* */
-/* The FreeType glyph rasterizer (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used */
-/* modified and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftraster.h
+ *
+ * The FreeType glyph rasterizer (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used
+ * modified and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTRASTER_H_
@@ -28,11 +28,11 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* Uncomment the following line if you are using ftraster.c as a */
- /* standalone module, fully independent of FreeType. */
- /* */
+ /**************************************************************************
+ *
+ * Uncomment the following line if you are using ftraster.c as a
+ * standalone module, fully independent of FreeType.
+ */
/* #define STANDALONE_ */
FT_EXPORT_VAR( const FT_Raster_Funcs ) ft_standard_raster;
diff --git a/thirdparty/freetype/src/raster/ftrend1.c b/thirdparty/freetype/src/raster/ftrend1.c
index a7ce9731d7..62c727182a 100644
--- a/thirdparty/freetype/src/raster/ftrend1.c
+++ b/thirdparty/freetype/src/raster/ftrend1.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftrend1.c */
-/* */
-/* The FreeType glyph rasterizer interface (body). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftrend1.c
+ *
+ * The FreeType glyph rasterizer interface (body).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -22,7 +22,6 @@
#include FT_OUTLINE_H
#include "ftrend1.h"
#include "ftraster.h"
-#include "rastpic.h"
#include "rasterrs.h"
@@ -128,7 +127,11 @@
slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
}
- ft_glyphslot_preset_bitmap( slot, mode, origin );
+ if ( ft_glyphslot_preset_bitmap( slot, mode, origin ) )
+ {
+ error = FT_THROW( Raster_Overflow );
+ goto Exit;
+ }
/* allocate new one */
if ( FT_ALLOC_MULT( bitmap->buffer, bitmap->rows, bitmap->pitch ) )
@@ -197,7 +200,7 @@
(FT_Renderer_GetCBoxFunc) ft_raster1_get_cbox, /* get_glyph_cbox */
(FT_Renderer_SetModeFunc) ft_raster1_set_mode, /* set_mode */
- (FT_Raster_Funcs*)&FT_STANDARD_RASTER_GET /* raster_class */
+ (FT_Raster_Funcs*)&ft_standard_raster /* raster_class */
)
diff --git a/thirdparty/freetype/src/raster/ftrend1.h b/thirdparty/freetype/src/raster/ftrend1.h
index 2abdf2d703..82ecac686c 100644
--- a/thirdparty/freetype/src/raster/ftrend1.h
+++ b/thirdparty/freetype/src/raster/ftrend1.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftrend1.h */
-/* */
-/* The FreeType glyph rasterizer interface (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftrend1.h
+ *
+ * The FreeType glyph rasterizer interface (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTREND1_H_
diff --git a/thirdparty/freetype/src/raster/module.mk b/thirdparty/freetype/src/raster/module.mk
index b115f416b2..0a6d4b09d9 100644
--- a/thirdparty/freetype/src/raster/module.mk
+++ b/thirdparty/freetype/src/raster/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2018 by
+# Copyright (C) 1996-2019 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/raster/raster.c b/thirdparty/freetype/src/raster/raster.c
index 76edd21e1e..e3ac9e566a 100644
--- a/thirdparty/freetype/src/raster/raster.c
+++ b/thirdparty/freetype/src/raster/raster.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* raster.c */
-/* */
-/* FreeType monochrome rasterer module component (body only). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * raster.c
+ *
+ * FreeType monochrome rasterer module component (body only).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#define FT_MAKE_OPTION_SINGLE_OBJECT
@@ -21,7 +21,6 @@
#include "ftraster.c"
#include "ftrend1.c"
-#include "rastpic.c"
/* END */
diff --git a/thirdparty/freetype/src/raster/rasterrs.h b/thirdparty/freetype/src/raster/rasterrs.h
index 22a3e15340..7266407365 100644
--- a/thirdparty/freetype/src/raster/rasterrs.h
+++ b/thirdparty/freetype/src/raster/rasterrs.h
@@ -1,27 +1,27 @@
-/***************************************************************************/
-/* */
-/* rasterrs.h */
-/* */
-/* monochrome renderer error codes (specification only). */
-/* */
-/* Copyright 2001-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* This file is used to define the monochrome renderer error enumeration */
- /* constants. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * rasterrs.h
+ *
+ * monochrome renderer error codes (specification only).
+ *
+ * Copyright (C) 2001-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * This file is used to define the monochrome renderer error enumeration
+ * constants.
+ *
+ */
#ifndef RASTERRS_H_
#define RASTERRS_H_
diff --git a/thirdparty/freetype/src/raster/rastpic.c b/thirdparty/freetype/src/raster/rastpic.c
deleted file mode 100644
index 1dc8981b8a..0000000000
--- a/thirdparty/freetype/src/raster/rastpic.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/***************************************************************************/
-/* */
-/* rastpic.c */
-/* */
-/* The FreeType position independent code services for raster module. */
-/* */
-/* Copyright 2009-2018 by */
-/* Oran Agra and Mickey Gabel. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#include <ft2build.h>
-#include FT_FREETYPE_H
-#include FT_INTERNAL_OBJECTS_H
-#include "rastpic.h"
-#include "rasterrs.h"
-
-
-#ifdef FT_CONFIG_OPTION_PIC
-
- /* forward declaration of PIC init functions from ftraster.c */
- void
- FT_Init_Class_ft_standard_raster( FT_Raster_Funcs* funcs );
-
-
- void
- ft_raster1_renderer_class_pic_free( FT_Library library )
- {
- FT_PIC_Container* pic_container = &library->pic_container;
- FT_Memory memory = library->memory;
-
-
- if ( pic_container->raster )
- {
- RasterPIC* container = (RasterPIC*)pic_container->raster;
-
-
- if ( --container->ref_count )
- return;
- FT_FREE( container );
- pic_container->raster = NULL;
- }
- }
-
-
- FT_Error
- ft_raster1_renderer_class_pic_init( FT_Library library )
- {
- FT_PIC_Container* pic_container = &library->pic_container;
- FT_Error error = FT_Err_Ok;
- RasterPIC* container = NULL;
- FT_Memory memory = library->memory;
-
-
- /* XXX: since this function also served the no longer available */
- /* raster5 renderer it uses reference counting, which could */
- /* be removed now */
- if ( pic_container->raster )
- {
- ((RasterPIC*)pic_container->raster)->ref_count++;
- return error;
- }
-
- /* allocate pointer, clear and set global container pointer */
- if ( FT_ALLOC( container, sizeof ( *container ) ) )
- return error;
- FT_MEM_SET( container, 0, sizeof ( *container ) );
- pic_container->raster = container;
-
- container->ref_count = 1;
-
- /* initialize pointer table - */
- /* this is how the module usually expects this data */
- FT_Init_Class_ft_standard_raster( &container->ft_standard_raster );
-
- return error;
- }
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
-
-/* END */
diff --git a/thirdparty/freetype/src/raster/rastpic.h b/thirdparty/freetype/src/raster/rastpic.h
deleted file mode 100644
index 6d0877c423..0000000000
--- a/thirdparty/freetype/src/raster/rastpic.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/***************************************************************************/
-/* */
-/* rastpic.h */
-/* */
-/* The FreeType position independent code services for raster module. */
-/* */
-/* Copyright 2009-2018 by */
-/* Oran Agra and Mickey Gabel. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#ifndef RASTPIC_H_
-#define RASTPIC_H_
-
-
-#include FT_INTERNAL_PIC_H
-
-
-FT_BEGIN_HEADER
-
-#ifndef FT_CONFIG_OPTION_PIC
-
-#define FT_STANDARD_RASTER_GET ft_standard_raster
-
-#else /* FT_CONFIG_OPTION_PIC */
-
- typedef struct RasterPIC_
- {
- int ref_count;
- FT_Raster_Funcs ft_standard_raster;
-
- } RasterPIC;
-
-
-#define GET_PIC( lib ) \
- ( (RasterPIC*)( (lib)->pic_container.raster ) )
-#define FT_STANDARD_RASTER_GET ( GET_PIC( library )->ft_standard_raster )
-
-
- /* see rastpic.c for the implementation */
- void
- ft_raster1_renderer_class_pic_free( FT_Library library );
-
- FT_Error
- ft_raster1_renderer_class_pic_init( FT_Library library );
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
- /* */
-
-FT_END_HEADER
-
-#endif /* RASTPIC_H_ */
-
-
-/* END */
diff --git a/thirdparty/freetype/src/raster/rules.mk b/thirdparty/freetype/src/raster/rules.mk
index 9aef1f0bab..7664671e80 100644
--- a/thirdparty/freetype/src/raster/rules.mk
+++ b/thirdparty/freetype/src/raster/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2018 by
+# Copyright (C) 1996-2019 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
@@ -28,8 +28,7 @@ RASTER_COMPILE := $(CC) $(ANSIFLAGS) \
# raster driver sources (i.e., C files)
#
RASTER_DRV_SRC := $(RASTER_DIR)/ftraster.c \
- $(RASTER_DIR)/ftrend1.c \
- $(RASTER_DIR)/rastpic.c
+ $(RASTER_DIR)/ftrend1.c
# raster driver headers
diff --git a/thirdparty/freetype/src/sfnt/module.mk b/thirdparty/freetype/src/sfnt/module.mk
index 51ca67e784..8c3b44fec7 100644
--- a/thirdparty/freetype/src/sfnt/module.mk
+++ b/thirdparty/freetype/src/sfnt/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2018 by
+# Copyright (C) 1996-2019 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/sfnt/pngshim.c b/thirdparty/freetype/src/sfnt/pngshim.c
index 16020266af..ca85d9751f 100644
--- a/thirdparty/freetype/src/sfnt/pngshim.c
+++ b/thirdparty/freetype/src/sfnt/pngshim.c
@@ -1,20 +1,20 @@
-/***************************************************************************/
-/* */
-/* pngshim.c */
-/* */
-/* PNG Bitmap glyph support. */
-/* */
-/* Copyright 2013-2018 by */
-/* Google, Inc. */
-/* Written by Stuart Gill and Behdad Esfahbod. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * pngshim.c
+ *
+ * PNG Bitmap glyph support.
+ *
+ * Copyright (C) 2013-2019 by
+ * Google, Inc.
+ * Written by Stuart Gill and Behdad Esfahbod.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
diff --git a/thirdparty/freetype/src/sfnt/pngshim.h b/thirdparty/freetype/src/sfnt/pngshim.h
index 194238c3a2..06c6f6b20e 100644
--- a/thirdparty/freetype/src/sfnt/pngshim.h
+++ b/thirdparty/freetype/src/sfnt/pngshim.h
@@ -1,20 +1,20 @@
-/***************************************************************************/
-/* */
-/* pngshim.h */
-/* */
-/* PNG Bitmap glyph support. */
-/* */
-/* Copyright 2013-2018 by */
-/* Google, Inc. */
-/* Written by Stuart Gill and Behdad Esfahbod. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * pngshim.h
+ *
+ * PNG Bitmap glyph support.
+ *
+ * Copyright (C) 2013-2019 by
+ * Google, Inc.
+ * Written by Stuart Gill and Behdad Esfahbod.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef PNGSHIM_H_
diff --git a/thirdparty/freetype/src/sfnt/rules.mk b/thirdparty/freetype/src/sfnt/rules.mk
index 83acc66a8f..ff9e7c6117 100644
--- a/thirdparty/freetype/src/sfnt/rules.mk
+++ b/thirdparty/freetype/src/sfnt/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2018 by
+# Copyright (C) 1996-2019 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
@@ -28,17 +28,18 @@ SFNT_COMPILE := $(CC) $(ANSIFLAGS) \
# SFNT driver sources (i.e., C files)
#
-SFNT_DRV_SRC := $(SFNT_DIR)/ttload.c \
- $(SFNT_DIR)/ttmtx.c \
+SFNT_DRV_SRC := $(SFNT_DIR)/pngshim.c \
+ $(SFNT_DIR)/sfdriver.c \
+ $(SFNT_DIR)/sfobjs.c \
+ $(SFNT_DIR)/ttbdf.c \
$(SFNT_DIR)/ttcmap.c \
- $(SFNT_DIR)/ttsbit.c \
- $(SFNT_DIR)/ttpost.c \
+ $(SFNT_DIR)/ttcolr.c \
+ $(SFNT_DIR)/ttcpal.c \
$(SFNT_DIR)/ttkern.c \
- $(SFNT_DIR)/ttbdf.c \
- $(SFNT_DIR)/sfobjs.c \
- $(SFNT_DIR)/sfdriver.c \
- $(SFNT_DIR)/sfntpic.c \
- $(SFNT_DIR)/pngshim.c
+ $(SFNT_DIR)/ttload.c \
+ $(SFNT_DIR)/ttmtx.c \
+ $(SFNT_DIR)/ttpost.c \
+ $(SFNT_DIR)/ttsbit.c
# SFNT driver headers
#
diff --git a/thirdparty/freetype/src/sfnt/sfdriver.c b/thirdparty/freetype/src/sfnt/sfdriver.c
index 303e1ca9f1..c467ff4d37 100644
--- a/thirdparty/freetype/src/sfnt/sfdriver.c
+++ b/thirdparty/freetype/src/sfnt/sfdriver.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* sfdriver.c */
-/* */
-/* High-level SFNT driver interface (body). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * sfdriver.c
+ *
+ * High-level SFNT driver interface (body).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -25,7 +25,6 @@
#include "sfdriver.h"
#include "ttload.h"
#include "sfobjs.h"
-#include "sfntpic.h"
#include "sferrors.h"
@@ -33,6 +32,11 @@
#include "ttsbit.h"
#endif
+#ifdef TT_CONFIG_OPTION_COLOR_LAYERS
+#include "ttcolr.h"
+#include "ttcpal.h"
+#endif
+
#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
#include "ttpost.h"
#endif
@@ -57,18 +61,18 @@
#endif
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_sfdriver
+#define FT_COMPONENT sfdriver
/*
- * SFNT TABLE SERVICE
+ * SFNT TABLE SERVICE
*
*/
@@ -155,7 +159,7 @@
#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
/*
- * GLYPH DICT SERVICE
+ * GLYPH DICT SERVICE
*
*/
@@ -222,7 +226,7 @@
/*
- * POSTSCRIPT NAME SERVICE
+ * POSTSCRIPT NAME SERVICE
*
*/
@@ -460,14 +464,12 @@
typedef int (*char_type_func)( int c );
- /* handling of PID/EID 3/0 and 3/1 is the same */
+ /* Handling of PID/EID 3/0 and 3/1 is the same. */
#define IS_WIN( n ) ( (n)->platformID == 3 && \
- ( (n)->encodingID == 1 || (n)->encodingID == 0 ) && \
- (n)->languageID == 0x409 )
+ ( (n)->encodingID == 1 || (n)->encodingID == 0 ) )
#define IS_APPLE( n ) ( (n)->platformID == 1 && \
- (n)->encodingID == 0 && \
- (n)->languageID == 0 )
+ (n)->encodingID == 0 )
static char*
get_win_string( FT_Memory memory,
@@ -491,42 +493,40 @@
if ( FT_STREAM_SEEK( entry->stringOffset ) ||
FT_FRAME_ENTER( entry->stringLength ) )
- {
- FT_FREE( result );
- entry->stringLength = 0;
- entry->stringOffset = 0;
- FT_FREE( entry->string );
-
- return NULL;
- }
+ goto get_win_string_error;
r = (FT_String*)result;
p = (FT_Char*)stream->cursor;
for ( len = entry->stringLength / 2; len > 0; len--, p += 2 )
{
- if ( p[0] == 0 )
+ if ( p[0] == 0 && char_type( p[1] ) )
+ *r++ = p[1];
+ else
{
- if ( char_type( p[1] ) )
- *r++ = p[1];
- else
- {
- if ( report_invalid_characters )
- {
- FT_TRACE0(( "get_win_string:"
- " Character `%c' (0x%X) invalid in PS name string\n",
- p[1], p[1] ));
- /* it's not the job of FreeType to correct PS names... */
- *r++ = p[1];
- }
- }
+ if ( report_invalid_characters )
+ FT_TRACE0(( "get_win_string:"
+ " Character 0x%X invalid in PS name string\n",
+ ((unsigned)p[0])*256 + (unsigned)p[1] ));
+ break;
}
}
- *r = '\0';
+ if ( !len )
+ *r = '\0';
FT_FRAME_EXIT();
- return result;
+ if ( !len )
+ return result;
+
+ get_win_string_error:
+ FT_FREE( result );
+
+ entry->stringLength = 0;
+ entry->stringOffset = 0;
+ FT_FREE( entry->string );
+
+ return NULL;
}
@@ -552,14 +552,7 @@
if ( FT_STREAM_SEEK( entry->stringOffset ) ||
FT_FRAME_ENTER( entry->stringLength ) )
- {
- FT_FREE( result );
- entry->stringOffset = 0;
- entry->stringLength = 0;
- FT_FREE( entry->string );
-
- return NULL;
- }
+ goto get_apple_string_error;
r = (FT_String*)result;
p = (FT_Char*)stream->cursor;
@@ -571,20 +564,28 @@
else
{
if ( report_invalid_characters )
- {
FT_TRACE0(( "get_apple_string:"
" Character `%c' (0x%X) invalid in PS name string\n",
*p, *p ));
- /* it's not the job of FreeType to correct PS names... */
- *r++ = *p;
- }
+ break;
}
}
- *r = '\0';
+ if ( !len )
+ *r = '\0';
FT_FRAME_EXIT();
- return result;
+ if ( !len )
+ return result;
+
+ get_apple_string_error:
+ FT_FREE( result );
+
+ entry->stringOffset = 0;
+ entry->stringLength = 0;
+ FT_FREE( entry->string );
+
+ return NULL;
}
@@ -607,10 +608,10 @@
if ( name->nameID == id && name->stringLength > 0 )
{
- if ( IS_WIN( name ) )
+ if ( IS_WIN( name ) && ( name->languageID == 0x409 || *win == -1 ) )
*win = n;
- if ( IS_APPLE( name ) )
+ if ( IS_APPLE( name ) && ( name->languageID == 0 || *apple == -1 ) )
*apple = n;
}
}
@@ -643,9 +644,9 @@
/*
- * Find the shortest decimal representation of a 16.16 fixed point
- * number. The function fills `buf' with the result, returning a pointer
- * to the position after the representation's last byte.
+ * Find the shortest decimal representation of a 16.16 fixed point
+ * number. The function fills `buf' with the result, returning a pointer
+ * to the position after the representation's last byte.
*/
static char*
@@ -673,7 +674,7 @@
if ( fixed < 0 )
{
*p++ = '-';
- fixed = -fixed;
+ fixed = NEG_INT( fixed );
}
int_part = ( fixed >> 16 ) & 0xFFFF;
@@ -828,13 +829,20 @@
face->name_table.names + win,
sfnt_is_alphanumeric,
0 );
- else
+ if ( !result && apple != -1 )
result = get_apple_string( face->root.memory,
face->name_table.stream,
face->name_table.names + apple,
sfnt_is_alphanumeric,
0 );
+ if ( !result )
+ {
+ FT_TRACE0(( "sfnt_get_var_ps_name:"
+ " No valid PS name prefix for font instances found\n" ));
+ return NULL;
+ }
+
len = ft_strlen( result );
/* sanitize if necessary; we reserve space for 36 bytes (a 128bit */
@@ -1052,7 +1060,7 @@
face->name_table.names + win,
sfnt_is_postscript,
1 );
- else
+ if ( !result && apple != -1 )
result = get_apple_string( face->root.memory,
face->name_table.stream,
face->name_table.names + apple,
@@ -1073,7 +1081,7 @@
/*
- * TT CMAP INFO
+ * TT CMAP INFO
*/
FT_DEFINE_SERVICE_TTCMAPSREC(
tt_service_get_cmap_info,
@@ -1132,41 +1140,41 @@
/*
- * SERVICE LIST
+ * SERVICE LIST
*/
#if defined TT_CONFIG_OPTION_POSTSCRIPT_NAMES && defined TT_CONFIG_OPTION_BDF
FT_DEFINE_SERVICEDESCREC5(
sfnt_services,
- FT_SERVICE_ID_SFNT_TABLE, &SFNT_SERVICE_SFNT_TABLE_GET,
- FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &SFNT_SERVICE_PS_NAME_GET,
- FT_SERVICE_ID_GLYPH_DICT, &SFNT_SERVICE_GLYPH_DICT_GET,
- FT_SERVICE_ID_BDF, &SFNT_SERVICE_BDF_GET,
- FT_SERVICE_ID_TT_CMAP, &TT_SERVICE_CMAP_INFO_GET )
+ FT_SERVICE_ID_SFNT_TABLE, &sfnt_service_sfnt_table,
+ FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &sfnt_service_ps_name,
+ FT_SERVICE_ID_GLYPH_DICT, &sfnt_service_glyph_dict,
+ FT_SERVICE_ID_BDF, &sfnt_service_bdf,
+ FT_SERVICE_ID_TT_CMAP, &tt_service_get_cmap_info )
#elif defined TT_CONFIG_OPTION_POSTSCRIPT_NAMES
FT_DEFINE_SERVICEDESCREC4(
sfnt_services,
- FT_SERVICE_ID_SFNT_TABLE, &SFNT_SERVICE_SFNT_TABLE_GET,
- FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &SFNT_SERVICE_PS_NAME_GET,
- FT_SERVICE_ID_GLYPH_DICT, &SFNT_SERVICE_GLYPH_DICT_GET,
- FT_SERVICE_ID_TT_CMAP, &TT_SERVICE_CMAP_INFO_GET )
+ FT_SERVICE_ID_SFNT_TABLE, &sfnt_service_sfnt_table,
+ FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &sfnt_service_ps_name,
+ FT_SERVICE_ID_GLYPH_DICT, &sfnt_service_glyph_dict,
+ FT_SERVICE_ID_TT_CMAP, &tt_service_get_cmap_info )
#elif defined TT_CONFIG_OPTION_BDF
FT_DEFINE_SERVICEDESCREC4(
sfnt_services,
- FT_SERVICE_ID_SFNT_TABLE, &SFNT_SERVICE_SFNT_TABLE_GET,
- FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &SFNT_SERVICE_PS_NAME_GET,
- FT_SERVICE_ID_BDF, &SFNT_SERVICE_BDF_GET,
- FT_SERVICE_ID_TT_CMAP, &TT_SERVICE_CMAP_INFO_GET )
+ FT_SERVICE_ID_SFNT_TABLE, &sfnt_service_sfnt_table,
+ FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &sfnt_service_ps_name,
+ FT_SERVICE_ID_BDF, &sfnt_service_bdf,
+ FT_SERVICE_ID_TT_CMAP, &tt_service_get_cmap_info )
#else
FT_DEFINE_SERVICEDESCREC3(
sfnt_services,
- FT_SERVICE_ID_SFNT_TABLE, &SFNT_SERVICE_SFNT_TABLE_GET,
- FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &SFNT_SERVICE_PS_NAME_GET,
- FT_SERVICE_ID_TT_CMAP, &TT_SERVICE_CMAP_INFO_GET )
+ FT_SERVICE_ID_SFNT_TABLE, &sfnt_service_sfnt_table,
+ FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &sfnt_service_ps_name,
+ FT_SERVICE_ID_TT_CMAP, &tt_service_get_cmap_info )
#endif
@@ -1174,21 +1182,9 @@
sfnt_get_interface( FT_Module module,
const char* module_interface )
{
- /* SFNT_SERVICES_GET dereferences `library' in PIC mode */
-#ifdef FT_CONFIG_OPTION_PIC
- FT_Library library;
-
-
- if ( !module )
- return NULL;
- library = module->library;
- if ( !library )
- return NULL;
-#else
FT_UNUSED( module );
-#endif
- return ft_service_list_lookup( SFNT_SERVICES_GET, module_interface );
+ return ft_service_list_lookup( sfnt_services, module_interface );
}
@@ -1198,6 +1194,12 @@
#define PUT_EMBEDDED_BITMAPS( a ) NULL
#endif
+#ifdef TT_CONFIG_OPTION_COLOR_LAYERS
+#define PUT_COLOR_LAYERS( a ) a
+#else
+#define PUT_COLOR_LAYERS( a ) NULL
+#endif
+
#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
#define PUT_PS_NAMES( a ) a
#else
@@ -1256,9 +1258,24 @@
/* TT_Free_Table_Func free_eblc */
PUT_EMBEDDED_BITMAPS( tt_face_set_sbit_strike ),
- /* TT_Set_SBit_Strike_Func set_sbit_strike */
+ /* TT_Set_SBit_Strike_Func set_sbit_strike */
PUT_EMBEDDED_BITMAPS( tt_face_load_strike_metrics ),
- /* TT_Load_Strike_Metrics_Func load_strike_metrics */
+ /* TT_Load_Strike_Metrics_Func load_strike_metrics */
+
+ PUT_COLOR_LAYERS( tt_face_load_cpal ),
+ /* TT_Load_Table_Func load_cpal */
+ PUT_COLOR_LAYERS( tt_face_load_colr ),
+ /* TT_Load_Table_Func load_colr */
+ PUT_COLOR_LAYERS( tt_face_free_cpal ),
+ /* TT_Free_Table_Func free_cpal */
+ PUT_COLOR_LAYERS( tt_face_free_colr ),
+ /* TT_Free_Table_Func free_colr */
+ PUT_COLOR_LAYERS( tt_face_palette_set ),
+ /* TT_Set_Palette_Func set_palette */
+ PUT_COLOR_LAYERS( tt_face_get_colr_layer ),
+ /* TT_Get_Colr_Layer_Func get_colr_layer */
+ PUT_COLOR_LAYERS( tt_face_colr_blend_layer ),
+ /* TT_Blend_Colr_Func colr_blend */
tt_face_get_metrics, /* TT_Get_Metrics_Func get_metrics */
@@ -1277,7 +1294,7 @@
0x10000L, /* driver version 1.0 */
0x20000L, /* driver requires FreeType 2.0 or higher */
- (const void*)&SFNT_INTERFACE_GET, /* module specific interface */
+ (const void*)&sfnt_interface, /* module specific interface */
(FT_Module_Constructor)NULL, /* module_init */
(FT_Module_Destructor) NULL, /* module_done */
diff --git a/thirdparty/freetype/src/sfnt/sfdriver.h b/thirdparty/freetype/src/sfnt/sfdriver.h
index 81c22d2887..8c174634b3 100644
--- a/thirdparty/freetype/src/sfnt/sfdriver.h
+++ b/thirdparty/freetype/src/sfnt/sfdriver.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* sfdriver.h */
-/* */
-/* High-level SFNT driver interface (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * sfdriver.h
+ *
+ * High-level SFNT driver interface (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef SFDRIVER_H_
@@ -26,10 +26,8 @@
FT_BEGIN_HEADER
-
FT_DECLARE_MODULE( sfnt_module_class )
-
FT_END_HEADER
#endif /* SFDRIVER_H_ */
diff --git a/thirdparty/freetype/src/sfnt/sferrors.h b/thirdparty/freetype/src/sfnt/sferrors.h
index 74003d4b38..43e148d295 100644
--- a/thirdparty/freetype/src/sfnt/sferrors.h
+++ b/thirdparty/freetype/src/sfnt/sferrors.h
@@ -1,26 +1,26 @@
-/***************************************************************************/
-/* */
-/* sferrors.h */
-/* */
-/* SFNT error codes (specification only). */
-/* */
-/* Copyright 2001-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* This file is used to define the SFNT error enumeration constants. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * sferrors.h
+ *
+ * SFNT error codes (specification only).
+ *
+ * Copyright (C) 2001-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * This file is used to define the SFNT error enumeration constants.
+ *
+ */
#ifndef SFERRORS_H_
#define SFERRORS_H_
diff --git a/thirdparty/freetype/src/sfnt/sfnt.c b/thirdparty/freetype/src/sfnt/sfnt.c
index 8b9a6b345d..5a503f30c5 100644
--- a/thirdparty/freetype/src/sfnt/sfnt.c
+++ b/thirdparty/freetype/src/sfnt/sfnt.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* sfnt.c */
-/* */
-/* Single object library component. */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * sfnt.c
+ *
+ * Single object library component.
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#define FT_MAKE_OPTION_SINGLE_OBJECT
@@ -21,10 +21,12 @@
#include "pngshim.c"
#include "sfdriver.c"
-#include "sfntpic.c"
#include "sfobjs.c"
#include "ttbdf.c"
#include "ttcmap.c"
+#include "ttcolr.c"
+#include "ttcpal.c"
+
#include "ttkern.c"
#include "ttload.c"
#include "ttmtx.c"
diff --git a/thirdparty/freetype/src/sfnt/sfntpic.c b/thirdparty/freetype/src/sfnt/sfntpic.c
deleted file mode 100644
index db2d816ce6..0000000000
--- a/thirdparty/freetype/src/sfnt/sfntpic.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/***************************************************************************/
-/* */
-/* sfntpic.c */
-/* */
-/* The FreeType position independent code services for sfnt module. */
-/* */
-/* Copyright 2009-2018 by */
-/* Oran Agra and Mickey Gabel. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#include <ft2build.h>
-#include FT_FREETYPE_H
-#include FT_INTERNAL_OBJECTS_H
-#include "sfntpic.h"
-#include "sferrors.h"
-
-
-#ifdef FT_CONFIG_OPTION_PIC
-
- /* forward declaration of PIC init functions from sfdriver.c */
- FT_Error
- FT_Create_Class_sfnt_services( FT_Library library,
- FT_ServiceDescRec** output_class );
- void
- FT_Destroy_Class_sfnt_services( FT_Library library,
- FT_ServiceDescRec* clazz );
- void
- FT_Init_Class_sfnt_service_bdf( FT_Service_BDFRec* clazz );
- void
- FT_Init_Class_sfnt_interface( FT_Library library,
- SFNT_Interface* clazz );
- void
- FT_Init_Class_sfnt_service_glyph_dict(
- FT_Library library,
- FT_Service_GlyphDictRec* clazz );
- void
- FT_Init_Class_sfnt_service_ps_name(
- FT_Library library,
- FT_Service_PsFontNameRec* clazz );
- void
- FT_Init_Class_tt_service_get_cmap_info(
- FT_Library library,
- FT_Service_TTCMapsRec* clazz );
- void
- FT_Init_Class_sfnt_service_sfnt_table(
- FT_Service_SFNT_TableRec* clazz );
-
-
- /* forward declaration of PIC init functions from ttcmap.c */
- FT_Error
- FT_Create_Class_tt_cmap_classes( FT_Library library,
- TT_CMap_Class** output_class );
- void
- FT_Destroy_Class_tt_cmap_classes( FT_Library library,
- TT_CMap_Class* clazz );
-
-
- void
- sfnt_module_class_pic_free( FT_Library library )
- {
- FT_PIC_Container* pic_container = &library->pic_container;
- FT_Memory memory = library->memory;
-
-
- if ( pic_container->sfnt )
- {
- sfntModulePIC* container = (sfntModulePIC*)pic_container->sfnt;
-
-
- if ( container->sfnt_services )
- FT_Destroy_Class_sfnt_services( library,
- container->sfnt_services );
- container->sfnt_services = NULL;
-
- if ( container->tt_cmap_classes )
- FT_Destroy_Class_tt_cmap_classes( library,
- container->tt_cmap_classes );
- container->tt_cmap_classes = NULL;
-
- FT_FREE( container );
- pic_container->sfnt = NULL;
- }
- }
-
-
- FT_Error
- sfnt_module_class_pic_init( FT_Library library )
- {
- FT_PIC_Container* pic_container = &library->pic_container;
- FT_Error error = FT_Err_Ok;
- sfntModulePIC* container = NULL;
- FT_Memory memory = library->memory;
-
-
- /* allocate pointer, clear and set global container pointer */
- if ( FT_ALLOC( container, sizeof ( *container ) ) )
- return error;
- FT_MEM_SET( container, 0, sizeof ( *container ) );
- pic_container->sfnt = container;
-
- /* initialize pointer table - */
- /* this is how the module usually expects this data */
- error = FT_Create_Class_sfnt_services( library,
- &container->sfnt_services );
- if ( error )
- goto Exit;
-
- error = FT_Create_Class_tt_cmap_classes( library,
- &container->tt_cmap_classes );
- if ( error )
- goto Exit;
-
- FT_Init_Class_sfnt_service_glyph_dict(
- library, &container->sfnt_service_glyph_dict );
- FT_Init_Class_sfnt_service_ps_name(
- library, &container->sfnt_service_ps_name );
- FT_Init_Class_tt_service_get_cmap_info(
- library, &container->tt_service_get_cmap_info );
- FT_Init_Class_sfnt_service_sfnt_table(
- &container->sfnt_service_sfnt_table );
-#ifdef TT_CONFIG_OPTION_BDF
- FT_Init_Class_sfnt_service_bdf( &container->sfnt_service_bdf );
-#endif
- FT_Init_Class_sfnt_interface( library, &container->sfnt_interface );
-
- Exit:
- if ( error )
- sfnt_module_class_pic_free( library );
- return error;
- }
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
-
-/* END */
diff --git a/thirdparty/freetype/src/sfnt/sfntpic.h b/thirdparty/freetype/src/sfnt/sfntpic.h
deleted file mode 100644
index 8f43122d81..0000000000
--- a/thirdparty/freetype/src/sfnt/sfntpic.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/***************************************************************************/
-/* */
-/* sfntpic.h */
-/* */
-/* The FreeType position independent code services for sfnt module. */
-/* */
-/* Copyright 2009-2018 by */
-/* Oran Agra and Mickey Gabel. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#ifndef SFNTPIC_H_
-#define SFNTPIC_H_
-
-
-#include FT_INTERNAL_PIC_H
-
-
-#ifndef FT_CONFIG_OPTION_PIC
-
-#define SFNT_SERVICES_GET sfnt_services
-#define SFNT_SERVICE_GLYPH_DICT_GET sfnt_service_glyph_dict
-#define SFNT_SERVICE_PS_NAME_GET sfnt_service_ps_name
-#define TT_SERVICE_CMAP_INFO_GET tt_service_get_cmap_info
-#define TT_CMAP_CLASSES_GET tt_cmap_classes
-#define SFNT_SERVICE_SFNT_TABLE_GET sfnt_service_sfnt_table
-#define SFNT_SERVICE_BDF_GET sfnt_service_bdf
-#define SFNT_INTERFACE_GET sfnt_interface
-
-#else /* FT_CONFIG_OPTION_PIC */
-
- /* some include files required for members of sfntModulePIC */
-#include FT_SERVICE_GLYPH_DICT_H
-#include FT_SERVICE_POSTSCRIPT_NAME_H
-#include FT_SERVICE_SFNT_H
-#include FT_SERVICE_TT_CMAP_H
-
-#ifdef TT_CONFIG_OPTION_BDF
-#include "ttbdf.h"
-#include FT_SERVICE_BDF_H
-#endif
-
-#include FT_INTERNAL_DEBUG_H
-#include FT_INTERNAL_STREAM_H
-#include FT_INTERNAL_SFNT_H
-#include "ttcmap.h"
-
-
-FT_BEGIN_HEADER
-
- typedef struct sfntModulePIC_
- {
- FT_ServiceDescRec* sfnt_services;
- FT_Service_GlyphDictRec sfnt_service_glyph_dict;
- FT_Service_PsFontNameRec sfnt_service_ps_name;
- FT_Service_TTCMapsRec tt_service_get_cmap_info;
- TT_CMap_Class* tt_cmap_classes;
- FT_Service_SFNT_TableRec sfnt_service_sfnt_table;
-#ifdef TT_CONFIG_OPTION_BDF
- FT_Service_BDFRec sfnt_service_bdf;
-#endif
- SFNT_Interface sfnt_interface;
-
- } sfntModulePIC;
-
-
-#define GET_PIC( lib ) \
- ( (sfntModulePIC*)( (lib)->pic_container.sfnt ) )
-
-#define SFNT_SERVICES_GET \
- ( GET_PIC( library )->sfnt_services )
-#define SFNT_SERVICE_GLYPH_DICT_GET \
- ( GET_PIC( library )->sfnt_service_glyph_dict )
-#define SFNT_SERVICE_PS_NAME_GET \
- ( GET_PIC( library )->sfnt_service_ps_name )
-#define TT_SERVICE_CMAP_INFO_GET \
- ( GET_PIC( library )->tt_service_get_cmap_info )
-#define TT_CMAP_CLASSES_GET \
- ( GET_PIC( library )->tt_cmap_classes )
-#define SFNT_SERVICE_SFNT_TABLE_GET \
- ( GET_PIC( library )->sfnt_service_sfnt_table )
-#define SFNT_SERVICE_BDF_GET \
- ( GET_PIC( library )->sfnt_service_bdf )
-#define SFNT_INTERFACE_GET \
- ( GET_PIC( library )->sfnt_interface )
-
-
- /* see sfntpic.c for the implementation */
- void
- sfnt_module_class_pic_free( FT_Library library );
-
- FT_Error
- sfnt_module_class_pic_init( FT_Library library );
-
-
-FT_END_HEADER
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
- /* */
-
-#endif /* SFNTPIC_H_ */
-
-
-/* END */
diff --git a/thirdparty/freetype/src/sfnt/sfobjs.c b/thirdparty/freetype/src/sfnt/sfobjs.c
index 6ba8509f56..0b43d251b8 100644
--- a/thirdparty/freetype/src/sfnt/sfobjs.c
+++ b/thirdparty/freetype/src/sfnt/sfobjs.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* sfobjs.c */
-/* */
-/* SFNT object management (base). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * sfobjs.c
+ *
+ * SFNT object management (base).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -41,14 +41,14 @@
#endif
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_sfobjs
+#define FT_COMPONENT sfobjs
@@ -918,7 +918,9 @@
/* Stream may have changed in sfnt_open_font. */
stream = face->root.stream;
- FT_TRACE2(( "sfnt_init_face: %08p, %d\n", face, face_instance_index ));
+ FT_TRACE2(( "sfnt_init_face: %08p (index %d)\n",
+ face,
+ face_instance_index ));
face_index = FT_ABS( face_instance_index ) & 0xFFFF;
@@ -1001,15 +1003,15 @@
face->variation_support |= TT_FACE_FLAG_VAR_FVAR;
/*
- * As documented in the OpenType specification, an entry for the
- * default instance may be omitted in the named instance table. In
- * particular this means that even if there is no named instance
- * table in the font we actually do have a named instance, namely the
- * default instance.
+ * As documented in the OpenType specification, an entry for the
+ * default instance may be omitted in the named instance table. In
+ * particular this means that even if there is no named instance
+ * table in the font we actually do have a named instance, namely the
+ * default instance.
*
- * For consistency, we always want the default instance in our list
- * of named instances. If it is missing, we try to synthesize it
- * later on. Here, we have to adjust `num_instances' accordingly.
+ * For consistency, we always want the default instance in our list
+ * of named instances. If it is missing, we try to synthesize it
+ * later on. Here, we have to adjust `num_instances' accordingly.
*/
if ( ( face->variation_support & TT_FACE_FLAG_VAR_FVAR ) &&
@@ -1341,6 +1343,13 @@
if ( sfnt->load_eblc )
LOAD_( eblc );
+ /* colored glyph support */
+ if ( sfnt->load_cpal )
+ {
+ LOAD_( cpal );
+ LOAD_( colr );
+ }
+
/* consider the pclt, kerning, and gasp tables as optional */
LOAD_( pclt );
LOAD_( gasp );
@@ -1389,12 +1398,13 @@
FT_Long flags = root->face_flags;
- /*********************************************************************/
- /* */
- /* Compute face flags. */
- /* */
+ /**********************************************************************
+ *
+ * Compute face flags.
+ */
if ( face->sbit_table_type == TT_SBIT_TABLE_TYPE_CBLC ||
- face->sbit_table_type == TT_SBIT_TABLE_TYPE_SBIX )
+ face->sbit_table_type == TT_SBIT_TABLE_TYPE_SBIX ||
+ face->colr )
flags |= FT_FACE_FLAG_COLOR; /* color glyphs */
if ( has_outline == TRUE )
@@ -1438,10 +1448,10 @@
root->face_flags = flags;
- /*********************************************************************/
- /* */
- /* Compute style flags. */
- /* */
+ /**********************************************************************
+ *
+ * Compute style flags.
+ */
flags = 0;
if ( has_outline == TRUE && face->os2.version != 0xFFFFU )
@@ -1471,14 +1481,14 @@
root->style_flags |= flags;
- /*********************************************************************/
- /* */
- /* Polish the charmaps. */
- /* */
- /* Try to set the charmap encoding according to the platform & */
- /* encoding ID of each charmap. Emulate Unicode charmap if one */
- /* is missing. */
- /* */
+ /**********************************************************************
+ *
+ * Polish the charmaps.
+ *
+ * Try to set the charmap encoding according to the platform &
+ * encoding ID of each charmap. Emulate Unicode charmap if one
+ * is missing.
+ */
tt_face_build_cmaps( face ); /* ignore errors */
@@ -1521,7 +1531,8 @@
error = FT_CMap_New( (FT_CMap_Class)&tt_cmap_unicode_class_rec,
NULL, &cmaprec, NULL );
if ( error &&
- FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) )
+ FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) &&
+ FT_ERR_NEQ( error, Unimplemented_Feature ) )
goto Exit;
error = FT_Err_Ok;
@@ -1533,9 +1544,9 @@
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
/*
- * Now allocate the root array of FT_Bitmap_Size records and
- * populate them. Unfortunately, it isn't possible to indicate bit
- * depths in the FT_Bitmap_Size record. This is a design error.
+ * Now allocate the root array of FT_Bitmap_Size records and
+ * populate them. Unfortunately, it isn't possible to indicate bit
+ * depths in the FT_Bitmap_Size record. This is a design error.
*/
{
FT_UInt count;
@@ -1615,10 +1626,10 @@
root->face_flags |= FT_FACE_FLAG_SCALABLE;
- /*********************************************************************/
- /* */
- /* Set up metrics. */
- /* */
+ /**********************************************************************
+ *
+ * Set up metrics.
+ */
if ( FT_IS_SCALABLE( root ) )
{
/* XXX What about if outline header is missing */
@@ -1630,59 +1641,73 @@
root->units_per_EM = face->header.Units_Per_EM;
- /* XXX: Computing the ascender/descender/height is very different */
- /* from what the specification tells you. Apparently, we */
- /* must be careful because */
- /* */
- /* - not all fonts have an OS/2 table; in this case, we take */
- /* the values in the horizontal header. However, these */
- /* values very often are not reliable. */
- /* */
- /* - otherwise, the correct typographic values are in the */
- /* sTypoAscender, sTypoDescender & sTypoLineGap fields. */
- /* */
- /* However, certain fonts have these fields set to 0. */
- /* Rather, they have usWinAscent & usWinDescent correctly */
- /* set (but with different values). */
- /* */
- /* As an example, Arial Narrow is implemented through four */
- /* files ARIALN.TTF, ARIALNI.TTF, ARIALNB.TTF & ARIALNBI.TTF */
- /* */
- /* Strangely, all fonts have the same values in their */
- /* sTypoXXX fields, except ARIALNB which sets them to 0. */
- /* */
- /* On the other hand, they all have different */
- /* usWinAscent/Descent values -- as a conclusion, the OS/2 */
- /* table cannot be used to compute the text height reliably! */
- /* */
-
- /* The ascender and descender are taken from the `hhea' table. */
- /* If zero, they are taken from the `OS/2' table. */
-
- root->ascender = face->horizontal.Ascender;
- root->descender = face->horizontal.Descender;
-
- root->height = root->ascender - root->descender +
- face->horizontal.Line_Gap;
-
- if ( !( root->ascender || root->descender ) )
+ /*
+ * Computing the ascender/descender/height is tricky.
+ *
+ * The OpenType specification v1.8.3 says:
+ *
+ * [OS/2's] sTypoAscender, sTypoDescender and sTypoLineGap fields
+ * are intended to allow applications to lay out documents in a
+ * typographically-correct and portable fashion.
+ *
+ * This is somewhat at odds with the decades of backwards
+ * compatibility, operating systems and applications doing whatever
+ * they want, not to mention broken fonts.
+ *
+ * Not all fonts have an OS/2 table; in this case, we take the values
+ * in the horizontal header, although there is nothing stopping the
+ * values from being unreliable. Even with a OS/2 table, certain fonts
+ * set the sTypoAscender, sTypoDescender and sTypoLineGap fields to 0
+ * and instead correctly set usWinAscent and usWinDescent.
+ *
+ * As an example, Arial Narrow is shipped as four files ARIALN.TTF,
+ * ARIALNI.TTF, ARIALNB.TTF and ARIALNBI.TTF. Strangely, all fonts have
+ * the same values in their sTypo* fields, except ARIALNB.ttf which
+ * sets them to 0. All of them have different usWinAscent/Descent
+ * values. The OS/2 table therefore cannot be trusted for computing the
+ * text height reliably.
+ *
+ * As a compromise, do the following:
+ *
+ * 1. If the OS/2 table exists and the fsSelection bit 7 is set
+ * (USE_TYPO_METRICS), trust the font and use the sTypo* metrics.
+ * 2. Otherwise, use the `hhea' table's metrics.
+ * 3. If they are zero and the OS/2 table exists,
+ * 1. use the OS/2 table's sTypo* metrics if they are non-zero.
+ * 2. Otherwise, use the OS/2 table's usWin* metrics.
+ */
+
+ if ( face->os2.version != 0xFFFFU && face->os2.fsSelection & 128 )
{
- if ( face->os2.version != 0xFFFFU )
- {
- if ( face->os2.sTypoAscender || face->os2.sTypoDescender )
- {
- root->ascender = face->os2.sTypoAscender;
- root->descender = face->os2.sTypoDescender;
+ root->ascender = face->os2.sTypoAscender;
+ root->descender = face->os2.sTypoDescender;
+ root->height = root->ascender - root->descender +
+ face->os2.sTypoLineGap;
+ }
+ else
+ {
+ root->ascender = face->horizontal.Ascender;
+ root->descender = face->horizontal.Descender;
+ root->height = root->ascender - root->descender +
+ face->horizontal.Line_Gap;
- root->height = root->ascender - root->descender +
- face->os2.sTypoLineGap;
- }
- else
+ if ( !( root->ascender || root->descender ) )
+ {
+ if ( face->os2.version != 0xFFFFU )
{
- root->ascender = (FT_Short)face->os2.usWinAscent;
- root->descender = -(FT_Short)face->os2.usWinDescent;
-
- root->height = root->ascender - root->descender;
+ if ( face->os2.sTypoAscender || face->os2.sTypoDescender )
+ {
+ root->ascender = face->os2.sTypoAscender;
+ root->descender = face->os2.sTypoDescender;
+ root->height = root->ascender - root->descender +
+ face->os2.sTypoLineGap;
+ }
+ else
+ {
+ root->ascender = (FT_Short)face->os2.usWinAscent;
+ root->descender = -(FT_Short)face->os2.usWinDescent;
+ root->height = root->ascender - root->descender;
+ }
}
}
}
@@ -1737,6 +1762,13 @@
/* destroy the embedded bitmaps table if it is loaded */
if ( sfnt->free_eblc )
sfnt->free_eblc( face );
+
+ /* destroy color table data if it is loaded */
+ if ( sfnt->free_cpal )
+ {
+ sfnt->free_cpal( face );
+ sfnt->free_colr( face );
+ }
}
#ifdef TT_CONFIG_OPTION_BDF
@@ -1792,11 +1824,18 @@
FT_FREE( face->sbit_strike_map );
face->root.num_fixed_sizes = 0;
-#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
FT_FREE( face->postscript_name );
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
FT_FREE( face->var_postscript_prefix );
#endif
+ /* freeing glyph color palette data */
+ FT_FREE( face->palette_data.palette_name_ids );
+ FT_FREE( face->palette_data.palette_flags );
+ FT_FREE( face->palette_data.palette_entry_name_ids );
+ FT_FREE( face->palette );
+
face->sfnt = NULL;
}
diff --git a/thirdparty/freetype/src/sfnt/sfobjs.h b/thirdparty/freetype/src/sfnt/sfobjs.h
index 1b8d1be5b1..17b0d50105 100644
--- a/thirdparty/freetype/src/sfnt/sfobjs.h
+++ b/thirdparty/freetype/src/sfnt/sfobjs.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* sfobjs.h */
-/* */
-/* SFNT object management (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * sfobjs.h
+ *
+ * SFNT object management (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef SFOBJS_H_
diff --git a/thirdparty/freetype/src/sfnt/ttbdf.c b/thirdparty/freetype/src/sfnt/ttbdf.c
index 534201f229..853599fc43 100644
--- a/thirdparty/freetype/src/sfnt/ttbdf.c
+++ b/thirdparty/freetype/src/sfnt/ttbdf.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ttbdf.c */
-/* */
-/* TrueType and OpenType embedded BDF properties (body). */
-/* */
-/* Copyright 2005-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ttbdf.c
+ *
+ * TrueType and OpenType embedded BDF properties (body).
+ *
+ * Copyright (C) 2005-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -27,14 +27,14 @@
#ifdef TT_CONFIG_OPTION_BDF
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_ttbdf
+#define FT_COMPONENT ttbdf
FT_LOCAL_DEF( void )
@@ -45,7 +45,7 @@
if ( bdf->loaded )
{
- FT_Stream stream = FT_FACE(face)->stream;
+ FT_Stream stream = FT_FACE( face )->stream;
if ( bdf->table )
@@ -111,8 +111,8 @@
FT_UInt num_items = FT_PEEK_USHORT( p + 2 );
/*
- * We don't need to check the value sets themselves, since this
- * is done later.
+ * We don't need to check the value sets themselves, since this
+ * is done later.
*/
strike += 10 * num_items;
@@ -142,7 +142,7 @@
BDF_PropertyRec *aprop )
{
TT_BDF bdf = &face->bdf;
- FT_Size size = FT_FACE(face)->size;
+ FT_Size size = FT_FACE( face )->size;
FT_Error error = FT_Err_Ok;
FT_Byte* p;
FT_UInt count;
diff --git a/thirdparty/freetype/src/sfnt/ttbdf.h b/thirdparty/freetype/src/sfnt/ttbdf.h
index 809a663001..e4164e61fc 100644
--- a/thirdparty/freetype/src/sfnt/ttbdf.h
+++ b/thirdparty/freetype/src/sfnt/ttbdf.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ttbdf.h */
-/* */
-/* TrueType and OpenType embedded BDF properties (specification). */
-/* */
-/* Copyright 2005-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ttbdf.h
+ *
+ * TrueType and OpenType embedded BDF properties (specification).
+ *
+ * Copyright (C) 2005-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef TTBDF_H_
diff --git a/thirdparty/freetype/src/sfnt/ttcmap.c b/thirdparty/freetype/src/sfnt/ttcmap.c
index 996e66485f..8d9737310c 100644
--- a/thirdparty/freetype/src/sfnt/ttcmap.c
+++ b/thirdparty/freetype/src/sfnt/ttcmap.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ttcmap.c */
-/* */
-/* TrueType character mapping table (cmap) support (body). */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ttcmap.c
+ *
+ * TrueType character mapping table (cmap) support (body).
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -27,17 +27,16 @@
#include "ttload.h"
#include "ttcmap.h"
#include "ttpost.h"
-#include "sfntpic.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_ttcmap
+#define FT_COMPONENT ttcmap
#define TT_PEEK_SHORT FT_PEEK_SHORT
@@ -77,19 +76,19 @@
/*************************************************************************/
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* TABLE OVERVIEW */
- /* -------------- */
- /* */
- /* NAME OFFSET TYPE DESCRIPTION */
- /* */
- /* format 0 USHORT must be 0 */
- /* length 2 USHORT table length in bytes */
- /* language 4 USHORT Mac language code */
- /* glyph_ids 6 BYTE[256] array of glyph indices */
- /* 262 */
- /* */
+ /**************************************************************************
+ *
+ * TABLE OVERVIEW
+ * --------------
+ *
+ * NAME OFFSET TYPE DESCRIPTION
+ *
+ * format 0 USHORT must be 0
+ * length 2 USHORT table length in bytes
+ * language 4 USHORT Mac language code
+ * glyph_ids 6 BYTE[256] array of glyph indices
+ * 262
+ */
#ifdef TT_CONFIG_CMAP_FORMAT_0
@@ -238,57 +237,57 @@
/*************************************************************************/
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* TABLE OVERVIEW */
- /* -------------- */
- /* */
- /* NAME OFFSET TYPE DESCRIPTION */
- /* */
- /* format 0 USHORT must be 2 */
- /* length 2 USHORT table length in bytes */
- /* language 4 USHORT Mac language code */
- /* keys 6 USHORT[256] sub-header keys */
- /* subs 518 SUBHEAD[NSUBS] sub-headers array */
- /* glyph_ids 518+NSUB*8 USHORT[] glyph ID array */
- /* */
- /* The `keys' table is used to map charcode high bytes to sub-headers. */
- /* The value of `NSUBS' is the number of sub-headers defined in the */
- /* table and is computed by finding the maximum of the `keys' table. */
- /* */
- /* Note that for any `n', `keys[n]' is a byte offset within the `subs' */
- /* table, i.e., it is the corresponding sub-header index multiplied */
- /* by 8. */
- /* */
- /* Each sub-header has the following format. */
- /* */
- /* NAME OFFSET TYPE DESCRIPTION */
- /* */
- /* first 0 USHORT first valid low-byte */
- /* count 2 USHORT number of valid low-bytes */
- /* delta 4 SHORT see below */
- /* offset 6 USHORT see below */
- /* */
- /* A sub-header defines, for each high byte, the range of valid */
- /* low bytes within the charmap. Note that the range defined by `first' */
- /* and `count' must be completely included in the interval [0..255] */
- /* according to the specification. */
- /* */
- /* If a character code is contained within a given sub-header, then */
- /* mapping it to a glyph index is done as follows. */
- /* */
- /* * The value of `offset' is read. This is a _byte_ distance from the */
- /* location of the `offset' field itself into a slice of the */
- /* `glyph_ids' table. Let's call it `slice' (it is a USHORT[], too). */
- /* */
- /* * The value `slice[char.lo - first]' is read. If it is 0, there is */
- /* no glyph for the charcode. Otherwise, the value of `delta' is */
- /* added to it (modulo 65536) to form a new glyph index. */
- /* */
- /* It is up to the validation routine to check that all offsets fall */
- /* within the glyph IDs table (and not within the `subs' table itself or */
- /* outside of the CMap). */
- /* */
+ /**************************************************************************
+ *
+ * TABLE OVERVIEW
+ * --------------
+ *
+ * NAME OFFSET TYPE DESCRIPTION
+ *
+ * format 0 USHORT must be 2
+ * length 2 USHORT table length in bytes
+ * language 4 USHORT Mac language code
+ * keys 6 USHORT[256] sub-header keys
+ * subs 518 SUBHEAD[NSUBS] sub-headers array
+ * glyph_ids 518+NSUB*8 USHORT[] glyph ID array
+ *
+ * The `keys' table is used to map charcode high bytes to sub-headers.
+ * The value of `NSUBS' is the number of sub-headers defined in the
+ * table and is computed by finding the maximum of the `keys' table.
+ *
+ * Note that for any `n', `keys[n]' is a byte offset within the `subs'
+ * table, i.e., it is the corresponding sub-header index multiplied
+ * by 8.
+ *
+ * Each sub-header has the following format.
+ *
+ * NAME OFFSET TYPE DESCRIPTION
+ *
+ * first 0 USHORT first valid low-byte
+ * count 2 USHORT number of valid low-bytes
+ * delta 4 SHORT see below
+ * offset 6 USHORT see below
+ *
+ * A sub-header defines, for each high byte, the range of valid
+ * low bytes within the charmap. Note that the range defined by `first'
+ * and `count' must be completely included in the interval [0..255]
+ * according to the specification.
+ *
+ * If a character code is contained within a given sub-header, then
+ * mapping it to a glyph index is done as follows.
+ *
+ * - The value of `offset' is read. This is a _byte_ distance from the
+ * location of the `offset' field itself into a slice of the
+ * `glyph_ids' table. Let's call it `slice' (it is a USHORT[], too).
+ *
+ * - The value `slice[char.lo - first]' is read. If it is 0, there is
+ * no glyph for the charcode. Otherwise, the value of `delta' is
+ * added to it (modulo 65536) to form a new glyph index.
+ *
+ * It is up to the validation routine to check that all offsets fall
+ * within the glyph IDs table (and not within the `subs' table itself or
+ * outside of the CMap).
+ */
#ifdef TT_CONFIG_CMAP_FORMAT_2
@@ -626,68 +625,68 @@
/*************************************************************************/
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* TABLE OVERVIEW */
- /* -------------- */
- /* */
- /* NAME OFFSET TYPE DESCRIPTION */
- /* */
- /* format 0 USHORT must be 4 */
- /* length 2 USHORT table length */
- /* in bytes */
- /* language 4 USHORT Mac language code */
- /* */
- /* segCountX2 6 USHORT 2*NUM_SEGS */
- /* searchRange 8 USHORT 2*(1 << LOG_SEGS) */
- /* entrySelector 10 USHORT LOG_SEGS */
- /* rangeShift 12 USHORT segCountX2 - */
- /* searchRange */
- /* */
- /* endCount 14 USHORT[NUM_SEGS] end charcode for */
- /* each segment; last */
- /* is 0xFFFF */
- /* */
- /* pad 14+NUM_SEGS*2 USHORT padding */
- /* */
- /* startCount 16+NUM_SEGS*2 USHORT[NUM_SEGS] first charcode for */
- /* each segment */
- /* */
- /* idDelta 16+NUM_SEGS*4 SHORT[NUM_SEGS] delta for each */
- /* segment */
- /* idOffset 16+NUM_SEGS*6 SHORT[NUM_SEGS] range offset for */
- /* each segment; can be */
- /* zero */
- /* */
- /* glyphIds 16+NUM_SEGS*8 USHORT[] array of glyph ID */
- /* ranges */
- /* */
- /* Character codes are modelled by a series of ordered (increasing) */
- /* intervals called segments. Each segment has start and end codes, */
- /* provided by the `startCount' and `endCount' arrays. Segments must */
- /* not overlap, and the last segment should always contain the value */
- /* 0xFFFF for `endCount'. */
- /* */
- /* The fields `searchRange', `entrySelector' and `rangeShift' are better */
- /* ignored (they are traces of over-engineering in the TrueType */
- /* specification). */
- /* */
- /* Each segment also has a signed `delta', as well as an optional offset */
- /* within the `glyphIds' table. */
- /* */
- /* If a segment's idOffset is 0, the glyph index corresponding to any */
- /* charcode within the segment is obtained by adding the value of */
- /* `idDelta' directly to the charcode, modulo 65536. */
- /* */
- /* Otherwise, a glyph index is taken from the glyph IDs sub-array for */
- /* the segment, and the value of `idDelta' is added to it. */
- /* */
- /* */
- /* Finally, note that a lot of fonts contain an invalid last segment, */
- /* where `start' and `end' are correctly set to 0xFFFF but both `delta' */
- /* and `offset' are incorrect (e.g., `opens___.ttf' which comes with */
- /* OpenOffice.org). We need special code to deal with them correctly. */
- /* */
+ /**************************************************************************
+ *
+ * TABLE OVERVIEW
+ * --------------
+ *
+ * NAME OFFSET TYPE DESCRIPTION
+ *
+ * format 0 USHORT must be 4
+ * length 2 USHORT table length
+ * in bytes
+ * language 4 USHORT Mac language code
+ *
+ * segCountX2 6 USHORT 2*NUM_SEGS
+ * searchRange 8 USHORT 2*(1 << LOG_SEGS)
+ * entrySelector 10 USHORT LOG_SEGS
+ * rangeShift 12 USHORT segCountX2 -
+ * searchRange
+ *
+ * endCount 14 USHORT[NUM_SEGS] end charcode for
+ * each segment; last
+ * is 0xFFFF
+ *
+ * pad 14+NUM_SEGS*2 USHORT padding
+ *
+ * startCount 16+NUM_SEGS*2 USHORT[NUM_SEGS] first charcode for
+ * each segment
+ *
+ * idDelta 16+NUM_SEGS*4 SHORT[NUM_SEGS] delta for each
+ * segment
+ * idOffset 16+NUM_SEGS*6 SHORT[NUM_SEGS] range offset for
+ * each segment; can be
+ * zero
+ *
+ * glyphIds 16+NUM_SEGS*8 USHORT[] array of glyph ID
+ * ranges
+ *
+ * Character codes are modelled by a series of ordered (increasing)
+ * intervals called segments. Each segment has start and end codes,
+ * provided by the `startCount' and `endCount' arrays. Segments must
+ * not overlap, and the last segment should always contain the value
+ * 0xFFFF for `endCount'.
+ *
+ * The fields `searchRange', `entrySelector' and `rangeShift' are better
+ * ignored (they are traces of over-engineering in the TrueType
+ * specification).
+ *
+ * Each segment also has a signed `delta', as well as an optional offset
+ * within the `glyphIds' table.
+ *
+ * If a segment's idOffset is 0, the glyph index corresponding to any
+ * charcode within the segment is obtained by adding the value of
+ * `idDelta' directly to the charcode, modulo 65536.
+ *
+ * Otherwise, a glyph index is taken from the glyph IDs sub-array for
+ * the segment, and the value of `idDelta' is added to it.
+ *
+ *
+ * Finally, note that a lot of fonts contain an invalid last segment,
+ * where `start' and `end' are correctly set to 0xFFFF but both `delta'
+ * and `offset' are incorrect (e.g., `opens___.ttf' which comes with
+ * OpenOffice.org). We need special code to deal with them correctly.
+ */
#ifdef TT_CONFIG_CMAP_FORMAT_4
@@ -1573,23 +1572,23 @@
/*************************************************************************/
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* TABLE OVERVIEW */
- /* -------------- */
- /* */
- /* NAME OFFSET TYPE DESCRIPTION */
- /* */
- /* format 0 USHORT must be 6 */
- /* length 2 USHORT table length in bytes */
- /* language 4 USHORT Mac language code */
- /* */
- /* first 6 USHORT first segment code */
- /* count 8 USHORT segment size in chars */
- /* glyphIds 10 USHORT[count] glyph IDs */
- /* */
- /* A very simplified segment mapping. */
- /* */
+ /**************************************************************************
+ *
+ * TABLE OVERVIEW
+ * --------------
+ *
+ * NAME OFFSET TYPE DESCRIPTION
+ *
+ * format 0 USHORT must be 6
+ * length 2 USHORT table length in bytes
+ * language 4 USHORT Mac language code
+ *
+ * first 6 USHORT first segment code
+ * count 8 USHORT segment size in chars
+ * glyphIds 10 USHORT[count] glyph IDs
+ *
+ * A very simplified segment mapping.
+ */
#ifdef TT_CONFIG_CMAP_FORMAT_6
@@ -1768,26 +1767,26 @@
/*************************************************************************/
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* TABLE OVERVIEW */
- /* -------------- */
- /* */
- /* NAME OFFSET TYPE DESCRIPTION */
- /* */
- /* format 0 USHORT must be 8 */
- /* reserved 2 USHORT reserved */
- /* length 4 ULONG length in bytes */
- /* language 8 ULONG Mac language code */
- /* is32 12 BYTE[8192] 32-bitness bitmap */
- /* count 8204 ULONG number of groups */
- /* */
- /* This header is followed by `count' groups of the following format: */
- /* */
- /* start 0 ULONG first charcode */
- /* end 4 ULONG last charcode */
- /* startId 8 ULONG start glyph ID for the group */
- /* */
+ /**************************************************************************
+ *
+ * TABLE OVERVIEW
+ * --------------
+ *
+ * NAME OFFSET TYPE DESCRIPTION
+ *
+ * format 0 USHORT must be 8
+ * reserved 2 USHORT reserved
+ * length 4 ULONG length in bytes
+ * language 8 ULONG Mac language code
+ * is32 12 BYTE[8192] 32-bitness bitmap
+ * count 8204 ULONG number of groups
+ *
+ * This header is followed by `count' groups of the following format:
+ *
+ * start 0 ULONG first charcode
+ * end 4 ULONG last charcode
+ * startId 8 ULONG start glyph ID for the group
+ */
#ifdef TT_CONFIG_CMAP_FORMAT_8
@@ -2037,22 +2036,22 @@
/*************************************************************************/
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* TABLE OVERVIEW */
- /* -------------- */
- /* */
- /* NAME OFFSET TYPE DESCRIPTION */
- /* */
- /* format 0 USHORT must be 10 */
- /* reserved 2 USHORT reserved */
- /* length 4 ULONG length in bytes */
- /* language 8 ULONG Mac language code */
- /* */
- /* start 12 ULONG first char in range */
- /* count 16 ULONG number of chars in range */
- /* glyphIds 20 USHORT[count] glyph indices covered */
- /* */
+ /**************************************************************************
+ *
+ * TABLE OVERVIEW
+ * --------------
+ *
+ * NAME OFFSET TYPE DESCRIPTION
+ *
+ * format 0 USHORT must be 10
+ * reserved 2 USHORT reserved
+ * length 4 ULONG length in bytes
+ * language 8 ULONG Mac language code
+ *
+ * start 12 ULONG first char in range
+ * count 16 ULONG number of chars in range
+ * glyphIds 20 USHORT[count] glyph indices covered
+ */
#ifdef TT_CONFIG_CMAP_FORMAT_10
@@ -2209,26 +2208,26 @@
/*************************************************************************/
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* TABLE OVERVIEW */
- /* -------------- */
- /* */
- /* NAME OFFSET TYPE DESCRIPTION */
- /* */
- /* format 0 USHORT must be 12 */
- /* reserved 2 USHORT reserved */
- /* length 4 ULONG length in bytes */
- /* language 8 ULONG Mac language code */
- /* count 12 ULONG number of groups */
- /* 16 */
- /* */
- /* This header is followed by `count' groups of the following format: */
- /* */
- /* start 0 ULONG first charcode */
- /* end 4 ULONG last charcode */
- /* startId 8 ULONG start glyph ID for the group */
- /* */
+ /**************************************************************************
+ *
+ * TABLE OVERVIEW
+ * --------------
+ *
+ * NAME OFFSET TYPE DESCRIPTION
+ *
+ * format 0 USHORT must be 12
+ * reserved 2 USHORT reserved
+ * length 4 ULONG length in bytes
+ * language 8 ULONG Mac language code
+ * count 12 ULONG number of groups
+ * 16
+ *
+ * This header is followed by `count' groups of the following format:
+ *
+ * start 0 ULONG first charcode
+ * end 4 ULONG last charcode
+ * startId 8 ULONG start glyph ID for the group
+ */
#ifdef TT_CONFIG_CMAP_FORMAT_12
@@ -2565,26 +2564,26 @@
/*************************************************************************/
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* TABLE OVERVIEW */
- /* -------------- */
- /* */
- /* NAME OFFSET TYPE DESCRIPTION */
- /* */
- /* format 0 USHORT must be 13 */
- /* reserved 2 USHORT reserved */
- /* length 4 ULONG length in bytes */
- /* language 8 ULONG Mac language code */
- /* count 12 ULONG number of groups */
- /* 16 */
- /* */
- /* This header is followed by `count' groups of the following format: */
- /* */
- /* start 0 ULONG first charcode */
- /* end 4 ULONG last charcode */
- /* glyphId 8 ULONG glyph ID for the whole group */
- /* */
+ /**************************************************************************
+ *
+ * TABLE OVERVIEW
+ * --------------
+ *
+ * NAME OFFSET TYPE DESCRIPTION
+ *
+ * format 0 USHORT must be 13
+ * reserved 2 USHORT reserved
+ * length 4 ULONG length in bytes
+ * language 8 ULONG Mac language code
+ * count 12 ULONG number of groups
+ * 16
+ *
+ * This header is followed by `count' groups of the following format:
+ *
+ * start 0 ULONG first charcode
+ * end 4 ULONG last charcode
+ * glyphId 8 ULONG glyph ID for the whole group
+ */
#ifdef TT_CONFIG_CMAP_FORMAT_13
@@ -2891,58 +2890,59 @@
/*************************************************************************/
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* TABLE OVERVIEW */
- /* -------------- */
- /* */
- /* NAME OFFSET TYPE DESCRIPTION */
- /* */
- /* format 0 USHORT must be 14 */
- /* length 2 ULONG table length in bytes */
- /* numSelector 6 ULONG number of variation sel. records */
- /* */
- /* Followed by numSelector records, each of which looks like */
- /* */
- /* varSelector 0 UINT24 Unicode codepoint of sel. */
- /* defaultOff 3 ULONG offset to a default UVS table */
- /* describing any variants to be found in */
- /* the normal Unicode subtable. */
- /* nonDefOff 7 ULONG offset to a non-default UVS table */
- /* describing any variants not in the */
- /* standard cmap, with GIDs here */
- /* (either offset may be 0 NULL) */
- /* */
- /* Selectors are sorted by code point. */
- /* */
- /* A default Unicode Variation Selector (UVS) subtable is just a list of */
- /* ranges of code points which are to be found in the standard cmap. No */
- /* glyph IDs (GIDs) here. */
- /* */
- /* numRanges 0 ULONG number of ranges following */
- /* */
- /* A range looks like */
- /* */
- /* uniStart 0 UINT24 code point of the first character in */
- /* this range */
- /* additionalCnt 3 UBYTE count of additional characters in this */
- /* range (zero means a range of a single */
- /* character) */
- /* */
- /* Ranges are sorted by `uniStart'. */
- /* */
- /* A non-default Unicode Variation Selector (UVS) subtable is a list of */
- /* mappings from codepoint to GID. */
- /* */
- /* numMappings 0 ULONG number of mappings */
- /* */
- /* A range looks like */
- /* */
- /* uniStart 0 UINT24 code point of the first character in */
- /* this range */
- /* GID 3 USHORT and its GID */
- /* */
- /* Ranges are sorted by `uniStart'. */
+ /**************************************************************************
+ *
+ * TABLE OVERVIEW
+ * --------------
+ *
+ * NAME OFFSET TYPE DESCRIPTION
+ *
+ * format 0 USHORT must be 14
+ * length 2 ULONG table length in bytes
+ * numSelector 6 ULONG number of variation sel. records
+ *
+ * Followed by numSelector records, each of which looks like
+ *
+ * varSelector 0 UINT24 Unicode codepoint of sel.
+ * defaultOff 3 ULONG offset to a default UVS table
+ * describing any variants to be found in
+ * the normal Unicode subtable.
+ * nonDefOff 7 ULONG offset to a non-default UVS table
+ * describing any variants not in the
+ * standard cmap, with GIDs here
+ * (either offset may be 0 NULL)
+ *
+ * Selectors are sorted by code point.
+ *
+ * A default Unicode Variation Selector (UVS) subtable is just a list of
+ * ranges of code points which are to be found in the standard cmap. No
+ * glyph IDs (GIDs) here.
+ *
+ * numRanges 0 ULONG number of ranges following
+ *
+ * A range looks like
+ *
+ * uniStart 0 UINT24 code point of the first character in
+ * this range
+ * additionalCnt 3 UBYTE count of additional characters in this
+ * range (zero means a range of a single
+ * character)
+ *
+ * Ranges are sorted by `uniStart'.
+ *
+ * A non-default Unicode Variation Selector (UVS) subtable is a list of
+ * mappings from codepoint to GID.
+ *
+ * numMappings 0 ULONG number of mappings
+ *
+ * A range looks like
+ *
+ * uniStart 0 UINT24 code point of the first character in
+ * this range
+ * GID 3 USHORT and its GID
+ *
+ * Ranges are sorted by `uniStart'.
+ */
#ifdef TT_CONFIG_CMAP_FORMAT_14
@@ -3681,6 +3681,9 @@
FT_UNUSED( pointer );
+ if ( !psnames->unicodes_init )
+ return FT_THROW( Unimplemented_Feature );
+
return psnames->unicodes_init( memory,
unicodes,
face->root.num_glyphs,
@@ -3749,7 +3752,6 @@
#endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
-#ifndef FT_CONFIG_OPTION_PIC
static const TT_CMap_Class tt_cmap_classes[] =
{
@@ -3758,61 +3760,6 @@
NULL,
};
-#else /*FT_CONFIG_OPTION_PIC*/
-
- void
- FT_Destroy_Class_tt_cmap_classes( FT_Library library,
- TT_CMap_Class* clazz )
- {
- FT_Memory memory = library->memory;
-
-
- if ( clazz )
- FT_FREE( clazz );
- }
-
-
- FT_Error
- FT_Create_Class_tt_cmap_classes( FT_Library library,
- TT_CMap_Class** output_class )
- {
- TT_CMap_Class* clazz = NULL;
- TT_CMap_ClassRec* recs;
- FT_Error error;
- FT_Memory memory = library->memory;
-
- int i = 0;
-
-
-#define TTCMAPCITEM( a ) i++;
-#include "ttcmapc.h"
-
- /* allocate enough space for both the pointers */
- /* plus terminator and the class instances */
- if ( FT_ALLOC( clazz, sizeof ( *clazz ) * ( i + 1 ) +
- sizeof ( TT_CMap_ClassRec ) * i ) )
- return error;
-
- /* the location of the class instances follows the array of pointers */
- recs = (TT_CMap_ClassRec*)( (char*)clazz +
- sizeof ( *clazz ) * ( i + 1 ) );
- i = 0;
-
-#undef TTCMAPCITEM
-#define TTCMAPCITEM( a ) \
- FT_Init_Class_ ## a( &recs[i] ); \
- clazz[i] = &recs[i]; \
- i++;
-#include "ttcmapc.h"
-
- clazz[i] = NULL;
-
- *output_class = clazz;
- return FT_Err_Ok;
- }
-
-#endif /*FT_CONFIG_OPTION_PIC*/
-
/* parse the `cmap' table and build the corresponding TT_CMap objects */
/* in the current face */
@@ -3859,7 +3806,7 @@
{
FT_Byte* volatile cmap = table + offset;
volatile FT_UInt format = TT_PEEK_USHORT( cmap );
- const TT_CMap_Class* volatile pclazz = TT_CMAP_CLASSES_GET;
+ const TT_CMap_Class* volatile pclazz = tt_cmap_classes;
TT_CMap_Class volatile clazz;
diff --git a/thirdparty/freetype/src/sfnt/ttcmap.h b/thirdparty/freetype/src/sfnt/ttcmap.h
index d264d99d2c..36801c939e 100644
--- a/thirdparty/freetype/src/sfnt/ttcmap.h
+++ b/thirdparty/freetype/src/sfnt/ttcmap.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ttcmap.h */
-/* */
-/* TrueType character mapping table (cmap) support (specification). */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ttcmap.h
+ *
+ * TrueType character mapping table (cmap) support (specification).
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef TTCMAP_H_
@@ -56,8 +56,6 @@ FT_BEGIN_HEADER
} TT_CMap_ClassRec;
-#ifndef FT_CONFIG_OPTION_PIC
-
#define FT_DEFINE_TT_CMAP( class_, \
size_, \
init_, \
@@ -92,42 +90,6 @@ FT_BEGIN_HEADER
get_cmap_info_ \
};
-#else /* FT_CONFIG_OPTION_PIC */
-
-#define FT_DEFINE_TT_CMAP( class_, \
- size_, \
- init_, \
- done_, \
- char_index_, \
- char_next_, \
- char_var_index_, \
- char_var_default_, \
- variant_list_, \
- charvariant_list_, \
- variantchar_list_, \
- format_, \
- validate_, \
- get_cmap_info_ ) \
- void \
- FT_Init_Class_ ## class_( TT_CMap_ClassRec* clazz ) \
- { \
- clazz->clazz.size = size_; \
- clazz->clazz.init = init_; \
- clazz->clazz.done = done_; \
- clazz->clazz.char_index = char_index_; \
- clazz->clazz.char_next = char_next_; \
- clazz->clazz.char_var_index = char_var_index_; \
- clazz->clazz.char_var_default = char_var_default_; \
- clazz->clazz.variant_list = variant_list_; \
- clazz->clazz.charvariant_list = charvariant_list_; \
- clazz->clazz.variantchar_list = variantchar_list_; \
- clazz->format = format_; \
- clazz->validate = validate_; \
- clazz->get_cmap_info = get_cmap_info_; \
- }
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
typedef struct TT_ValidatorRec_
{
diff --git a/thirdparty/freetype/src/sfnt/ttcmapc.h b/thirdparty/freetype/src/sfnt/ttcmapc.h
index 4980e9dd3d..ace9e69ca8 100644
--- a/thirdparty/freetype/src/sfnt/ttcmapc.h
+++ b/thirdparty/freetype/src/sfnt/ttcmapc.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ttcmapc.h */
-/* */
-/* TT CMAP classes definitions (specification only). */
-/* */
-/* Copyright 2009-2018 by */
-/* Oran Agra and Mickey Gabel. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ttcmapc.h
+ *
+ * TT CMAP classes definitions (specification only).
+ *
+ * Copyright (C) 2009-2019 by
+ * Oran Agra and Mickey Gabel.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifdef TT_CONFIG_CMAP_FORMAT_0
diff --git a/thirdparty/freetype/src/sfnt/ttcolr.c b/thirdparty/freetype/src/sfnt/ttcolr.c
new file mode 100644
index 0000000000..6b537d95b8
--- /dev/null
+++ b/thirdparty/freetype/src/sfnt/ttcolr.c
@@ -0,0 +1,451 @@
+/****************************************************************************
+ *
+ * ttcolr.c
+ *
+ * TrueType and OpenType colored glyph layer support (body).
+ *
+ * Copyright (C) 2018-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Originally written by Shao Yu Zhang <shaozhang@fb.com>.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * `COLR' table specification:
+ *
+ * https://www.microsoft.com/typography/otspec/colr.htm
+ *
+ */
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_TRUETYPE_TAGS_H
+#include FT_COLOR_H
+
+
+#ifdef TT_CONFIG_OPTION_COLOR_LAYERS
+
+#include "ttcolr.h"
+
+
+ /* NOTE: These are the table sizes calculated through the specs. */
+#define BASE_GLYPH_SIZE 6
+#define LAYER_SIZE 4
+#define COLR_HEADER_SIZE 14
+
+
+ typedef struct BaseGlyphRecord_
+ {
+ FT_UShort gid;
+ FT_UShort first_layer_index;
+ FT_UShort num_layers;
+
+ } BaseGlyphRecord;
+
+
+ typedef struct Colr_
+ {
+ FT_UShort version;
+ FT_UShort num_base_glyphs;
+ FT_UShort num_layers;
+
+ FT_Byte* base_glyphs;
+ FT_Byte* layers;
+
+ /* The memory which backs up the `COLR' table. */
+ void* table;
+ FT_ULong table_size;
+
+ } Colr;
+
+
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
+#undef FT_COMPONENT
+#define FT_COMPONENT ttcolr
+
+
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_load_colr( TT_Face face,
+ FT_Stream stream )
+ {
+ FT_Error error;
+ FT_Memory memory = face->root.memory;
+
+ FT_Byte* table = NULL;
+ FT_Byte* p = NULL;
+
+ Colr* colr = NULL;
+
+ FT_ULong base_glyph_offset, layer_offset;
+ FT_ULong table_size;
+
+
+ /* `COLR' always needs `CPAL' */
+ if ( !face->cpal )
+ return FT_THROW( Invalid_File_Format );
+
+ error = face->goto_table( face, TTAG_COLR, stream, &table_size );
+ if ( error )
+ goto NoColr;
+
+ if ( table_size < COLR_HEADER_SIZE )
+ goto InvalidTable;
+
+ if ( FT_FRAME_EXTRACT( table_size, table ) )
+ goto NoColr;
+
+ p = table;
+
+ if ( FT_NEW( colr ) )
+ goto NoColr;
+
+ colr->version = FT_NEXT_USHORT( p );
+ if ( colr->version != 0 )
+ goto InvalidTable;
+
+ colr->num_base_glyphs = FT_NEXT_USHORT( p );
+ base_glyph_offset = FT_NEXT_ULONG( p );
+
+ if ( base_glyph_offset >= table_size )
+ goto InvalidTable;
+ if ( colr->num_base_glyphs * BASE_GLYPH_SIZE >
+ table_size - base_glyph_offset )
+ goto InvalidTable;
+
+ layer_offset = FT_NEXT_ULONG( p );
+ colr->num_layers = FT_NEXT_USHORT( p );
+
+ if ( layer_offset >= table_size )
+ goto InvalidTable;
+ if ( colr->num_layers * LAYER_SIZE > table_size - layer_offset )
+ goto InvalidTable;
+
+ colr->base_glyphs = (FT_Byte*)( table + base_glyph_offset );
+ colr->layers = (FT_Byte*)( table + layer_offset );
+ colr->table = table;
+ colr->table_size = table_size;
+
+ face->colr = colr;
+
+ return FT_Err_Ok;
+
+ InvalidTable:
+ error = FT_THROW( Invalid_Table );
+
+ NoColr:
+ FT_FRAME_RELEASE( table );
+ FT_FREE( colr );
+
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ tt_face_free_colr( TT_Face face )
+ {
+ FT_Stream stream = face->root.stream;
+ FT_Memory memory = face->root.memory;
+
+ Colr* colr = (Colr*)face->colr;
+
+
+ if ( colr )
+ {
+ FT_FRAME_RELEASE( colr->table );
+ FT_FREE( colr );
+ }
+ }
+
+
+ static FT_Bool
+ find_base_glyph_record( FT_Byte* base_glyph_begin,
+ FT_Int num_base_glyph,
+ FT_UInt glyph_id,
+ BaseGlyphRecord* record )
+ {
+ FT_Int min = 0;
+ FT_Int max = num_base_glyph - 1;
+
+
+ while ( min <= max )
+ {
+ FT_Int mid = min + ( max - min ) / 2;
+ FT_Byte* p = base_glyph_begin + mid * BASE_GLYPH_SIZE;
+
+ FT_UShort gid = FT_NEXT_USHORT( p );
+
+
+ if ( gid < glyph_id )
+ min = mid + 1;
+ else if (gid > glyph_id )
+ max = mid - 1;
+ else
+ {
+ record->gid = gid;
+ record->first_layer_index = FT_NEXT_USHORT( p );
+ record->num_layers = FT_NEXT_USHORT( p );
+
+ return 1;
+ }
+ }
+
+ return 0;
+ }
+
+
+ FT_LOCAL_DEF( FT_Bool )
+ tt_face_get_colr_layer( TT_Face face,
+ FT_UInt base_glyph,
+ FT_UInt *aglyph_index,
+ FT_UInt *acolor_index,
+ FT_LayerIterator* iterator )
+ {
+ Colr* colr = (Colr*)face->colr;
+ BaseGlyphRecord glyph_record;
+
+
+ if ( !colr )
+ return 0;
+
+ if ( !iterator->p )
+ {
+ FT_ULong offset;
+
+
+ /* first call to function */
+ iterator->layer = 0;
+
+ if ( !find_base_glyph_record( colr->base_glyphs,
+ colr->num_base_glyphs,
+ base_glyph,
+ &glyph_record ) )
+ return 0;
+
+ if ( glyph_record.num_layers )
+ iterator->num_layers = glyph_record.num_layers;
+ else
+ return 0;
+
+ offset = LAYER_SIZE * glyph_record.first_layer_index;
+ if ( offset + LAYER_SIZE * glyph_record.num_layers > colr->table_size )
+ return 0;
+
+ iterator->p = colr->layers + offset;
+ }
+
+ if ( iterator->layer >= iterator->num_layers )
+ return 0;
+
+ *aglyph_index = FT_NEXT_USHORT( iterator->p );
+ *acolor_index = FT_NEXT_USHORT( iterator->p );
+
+ if ( *aglyph_index >= (FT_UInt)( FT_FACE( face )->num_glyphs ) ||
+ ( *acolor_index != 0xFFFF &&
+ *acolor_index >= face->palette_data.num_palette_entries ) )
+ return 0;
+
+ iterator->layer++;
+
+ return 1;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_colr_blend_layer( TT_Face face,
+ FT_UInt color_index,
+ FT_GlyphSlot dstSlot,
+ FT_GlyphSlot srcSlot )
+ {
+ FT_Error error;
+
+ FT_UInt x, y;
+ FT_Byte b, g, r, alpha;
+
+ FT_ULong size;
+ FT_Byte* src;
+ FT_Byte* dst;
+
+
+ if ( !dstSlot->bitmap.buffer )
+ {
+ /* Initialize destination of color bitmap */
+ /* with the size of first component. */
+ dstSlot->bitmap_left = srcSlot->bitmap_left;
+ dstSlot->bitmap_top = srcSlot->bitmap_top;
+
+ dstSlot->bitmap.width = srcSlot->bitmap.width;
+ dstSlot->bitmap.rows = srcSlot->bitmap.rows;
+ dstSlot->bitmap.pixel_mode = FT_PIXEL_MODE_BGRA;
+ dstSlot->bitmap.pitch = (int)dstSlot->bitmap.width * 4;
+ dstSlot->bitmap.num_grays = 256;
+
+ size = dstSlot->bitmap.rows * (unsigned int)dstSlot->bitmap.pitch;
+
+ error = ft_glyphslot_alloc_bitmap( dstSlot, size );
+ if ( error )
+ return error;
+
+ FT_MEM_ZERO( dstSlot->bitmap.buffer, size );
+ }
+ else
+ {
+ /* Resize destination if needed such that new component fits. */
+ FT_Int x_min, x_max, y_min, y_max;
+
+
+ x_min = FT_MIN( dstSlot->bitmap_left, srcSlot->bitmap_left );
+ x_max = FT_MAX( dstSlot->bitmap_left + (FT_Int)dstSlot->bitmap.width,
+ srcSlot->bitmap_left + (FT_Int)srcSlot->bitmap.width );
+
+ y_min = FT_MIN( dstSlot->bitmap_top - (FT_Int)dstSlot->bitmap.rows,
+ srcSlot->bitmap_top - (FT_Int)srcSlot->bitmap.rows );
+ y_max = FT_MAX( dstSlot->bitmap_top, srcSlot->bitmap_top );
+
+ if ( x_min != dstSlot->bitmap_left ||
+ x_max != dstSlot->bitmap_left + (FT_Int)dstSlot->bitmap.width ||
+ y_min != dstSlot->bitmap_top - (FT_Int)dstSlot->bitmap.rows ||
+ y_max != dstSlot->bitmap_top )
+ {
+ FT_Memory memory = face->root.memory;
+
+ FT_UInt width = (FT_UInt)( x_max - x_min );
+ FT_UInt rows = (FT_UInt)( y_max - y_min );
+ FT_UInt pitch = width * 4;
+
+ FT_Byte* buf = NULL;
+ FT_Byte* p;
+ FT_Byte* q;
+
+
+ size = rows * pitch;
+ if ( FT_ALLOC( buf, size ) )
+ return error;
+
+ p = dstSlot->bitmap.buffer;
+ q = buf +
+ (int)pitch * ( y_max - dstSlot->bitmap_top ) +
+ 4 * ( dstSlot->bitmap_left - x_min );
+
+ for ( y = 0; y < dstSlot->bitmap.rows; y++ )
+ {
+ FT_MEM_COPY( q, p, dstSlot->bitmap.width * 4 );
+
+ p += dstSlot->bitmap.pitch;
+ q += pitch;
+ }
+
+ ft_glyphslot_set_bitmap( dstSlot, buf );
+
+ dstSlot->bitmap_top = y_max;
+ dstSlot->bitmap_left = x_min;
+
+ dstSlot->bitmap.width = width;
+ dstSlot->bitmap.rows = rows;
+ dstSlot->bitmap.pitch = (int)pitch;
+
+ dstSlot->internal->flags |= FT_GLYPH_OWN_BITMAP;
+ dstSlot->format = FT_GLYPH_FORMAT_BITMAP;
+ }
+ }
+
+ if ( color_index == 0xFFFF )
+ {
+ if ( face->have_foreground_color )
+ {
+ b = face->foreground_color.blue;
+ g = face->foreground_color.green;
+ r = face->foreground_color.red;
+ alpha = face->foreground_color.alpha;
+ }
+ else
+ {
+ if ( face->palette_data.palette_flags &&
+ ( face->palette_data.palette_flags[face->palette_index] &
+ FT_PALETTE_FOR_DARK_BACKGROUND ) )
+ {
+ /* white opaque */
+ b = 0xFF;
+ g = 0xFF;
+ r = 0xFF;
+ alpha = 0xFF;
+ }
+ else
+ {
+ /* black opaque */
+ b = 0x00;
+ g = 0x00;
+ r = 0x00;
+ alpha = 0xFF;
+ }
+ }
+ }
+ else
+ {
+ b = face->palette[color_index].blue;
+ g = face->palette[color_index].green;
+ r = face->palette[color_index].red;
+ alpha = face->palette[color_index].alpha;
+ }
+
+ /* XXX Convert if srcSlot.bitmap is not grey? */
+ src = srcSlot->bitmap.buffer;
+ dst = dstSlot->bitmap.buffer +
+ dstSlot->bitmap.pitch * ( dstSlot->bitmap_top - srcSlot->bitmap_top ) +
+ 4 * ( srcSlot->bitmap_left - dstSlot->bitmap_left );
+
+ for ( y = 0; y < srcSlot->bitmap.rows; y++ )
+ {
+ for ( x = 0; x < srcSlot->bitmap.width; x++ )
+ {
+ int aa = src[x];
+ int fa = alpha * aa / 255;
+
+ int fb = b * fa / 255;
+ int fg = g * fa / 255;
+ int fr = r * fa / 255;
+
+ int ba2 = 255 - fa;
+
+ int bb = dst[4 * x + 0];
+ int bg = dst[4 * x + 1];
+ int br = dst[4 * x + 2];
+ int ba = dst[4 * x + 3];
+
+
+ dst[4 * x + 0] = (FT_Byte)( bb * ba2 / 255 + fb );
+ dst[4 * x + 1] = (FT_Byte)( bg * ba2 / 255 + fg );
+ dst[4 * x + 2] = (FT_Byte)( br * ba2 / 255 + fr );
+ dst[4 * x + 3] = (FT_Byte)( ba * ba2 / 255 + fa );
+ }
+
+ src += srcSlot->bitmap.pitch;
+ dst += dstSlot->bitmap.pitch;
+ }
+
+ return FT_Err_Ok;
+ }
+
+#else /* !TT_CONFIG_OPTION_COLOR_LAYERS */
+
+ /* ANSI C doesn't like empty source files */
+ typedef int _tt_colr_dummy;
+
+#endif /* !TT_CONFIG_OPTION_COLOR_LAYERS */
+
+/* EOF */
diff --git a/thirdparty/freetype/src/sfnt/ttcolr.h b/thirdparty/freetype/src/sfnt/ttcolr.h
new file mode 100644
index 0000000000..817489a855
--- /dev/null
+++ b/thirdparty/freetype/src/sfnt/ttcolr.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+ *
+ * ttcolr.h
+ *
+ * TrueType and OpenType colored glyph layer support (specification).
+ *
+ * Copyright (C) 2018-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Originally written by Shao Yu Zhang <shaozhang@fb.com>.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef __TTCOLR_H__
+#define __TTCOLR_H__
+
+
+#include <ft2build.h>
+#include "ttload.h"
+
+
+FT_BEGIN_HEADER
+
+
+ FT_LOCAL( FT_Error )
+ tt_face_load_colr( TT_Face face,
+ FT_Stream stream );
+
+ FT_LOCAL( void )
+ tt_face_free_colr( TT_Face face );
+
+ FT_LOCAL( FT_Bool )
+ tt_face_get_colr_layer( TT_Face face,
+ FT_UInt base_glyph,
+ FT_UInt *aglyph_index,
+ FT_UInt *acolor_index,
+ FT_LayerIterator* iterator );
+
+ FT_LOCAL( FT_Error )
+ tt_face_colr_blend_layer( TT_Face face,
+ FT_UInt color_index,
+ FT_GlyphSlot dstSlot,
+ FT_GlyphSlot srcSlot );
+
+
+FT_END_HEADER
+
+
+#endif /* __TTCOLR_H__ */
+
+/* END */
diff --git a/thirdparty/freetype/src/sfnt/ttcpal.c b/thirdparty/freetype/src/sfnt/ttcpal.c
new file mode 100644
index 0000000000..3482169a89
--- /dev/null
+++ b/thirdparty/freetype/src/sfnt/ttcpal.c
@@ -0,0 +1,311 @@
+/****************************************************************************
+ *
+ * ttcpal.c
+ *
+ * TrueType and OpenType color palette support (body).
+ *
+ * Copyright (C) 2018-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Originally written by Shao Yu Zhang <shaozhang@fb.com>.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * `CPAL' table specification:
+ *
+ * https://www.microsoft.com/typography/otspec/cpal.htm
+ *
+ */
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_TRUETYPE_TAGS_H
+#include FT_COLOR_H
+
+
+#ifdef TT_CONFIG_OPTION_COLOR_LAYERS
+
+#include "ttcpal.h"
+
+
+ /* NOTE: These are the table sizes calculated through the specs. */
+#define CPAL_V0_HEADER_BASE_SIZE 12
+#define COLOR_SIZE 4
+
+
+ /* all data from `CPAL' not covered in FT_Palette_Data */
+ typedef struct Cpal_
+ {
+ FT_UShort version; /* Table version number (0 or 1 supported). */
+ FT_UShort num_colors; /* Total number of color records, */
+ /* combined for all palettes. */
+ FT_Byte* colors; /* RGBA array of colors */
+ FT_Byte* color_indices; /* Index of each palette's first color record */
+ /* in the combined color record array. */
+
+ /* The memory which backs up the `CPAL' table. */
+ void* table;
+ FT_ULong table_size;
+
+ } Cpal;
+
+
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
+#undef FT_COMPONENT
+#define FT_COMPONENT ttcpal
+
+
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_load_cpal( TT_Face face,
+ FT_Stream stream )
+ {
+ FT_Error error;
+ FT_Memory memory = face->root.memory;
+
+ FT_Byte* table = NULL;
+ FT_Byte* p = NULL;
+
+ Cpal* cpal = NULL;
+
+ FT_ULong colors_offset;
+ FT_ULong table_size;
+
+
+ error = face->goto_table( face, TTAG_CPAL, stream, &table_size );
+ if ( error )
+ goto NoCpal;
+
+ if ( table_size < CPAL_V0_HEADER_BASE_SIZE )
+ goto InvalidTable;
+
+ if ( FT_FRAME_EXTRACT( table_size, table ) )
+ goto NoCpal;
+
+ p = table;
+
+ if ( FT_NEW( cpal ) )
+ goto NoCpal;
+
+ cpal->version = FT_NEXT_USHORT( p );
+ if ( cpal->version > 1 )
+ goto InvalidTable;
+
+ face->palette_data.num_palette_entries = FT_NEXT_USHORT( p );
+ face->palette_data.num_palettes = FT_NEXT_USHORT( p );
+
+ cpal->num_colors = FT_NEXT_USHORT( p );
+ colors_offset = FT_NEXT_ULONG( p );
+
+ if ( CPAL_V0_HEADER_BASE_SIZE +
+ face->palette_data.num_palettes * 2U > table_size )
+ goto InvalidTable;
+
+ if ( colors_offset >= table_size )
+ goto InvalidTable;
+ if ( cpal->num_colors * COLOR_SIZE > table_size - colors_offset )
+ goto InvalidTable;
+
+ if ( face->palette_data.num_palette_entries > cpal->num_colors )
+ goto InvalidTable;
+
+ cpal->color_indices = p;
+ cpal->colors = (FT_Byte*)( table + colors_offset );
+
+ if ( cpal->version == 1 )
+ {
+ FT_ULong type_offset, label_offset, entry_label_offset;
+ FT_UShort* array = NULL;
+ FT_UShort* limit;
+ FT_UShort* q;
+
+
+ if ( CPAL_V0_HEADER_BASE_SIZE +
+ face->palette_data.num_palettes * 2U +
+ 3U * 4 > table_size )
+ goto InvalidTable;
+
+ p += face->palette_data.num_palettes * 2;
+
+ type_offset = FT_NEXT_ULONG( p );
+ label_offset = FT_NEXT_ULONG( p );
+ entry_label_offset = FT_NEXT_ULONG( p );
+
+ if ( type_offset )
+ {
+ if ( type_offset >= table_size )
+ goto InvalidTable;
+ if ( face->palette_data.num_palettes * 2 >
+ table_size - type_offset )
+ goto InvalidTable;
+
+ if ( FT_QNEW_ARRAY( array, face->palette_data.num_palettes ) )
+ goto NoCpal;
+
+ p = table + type_offset;
+ q = array;
+ limit = q + face->palette_data.num_palettes;
+
+ while ( q < limit )
+ *q++ = FT_NEXT_USHORT( p );
+
+ face->palette_data.palette_flags = array;
+ }
+
+ if ( label_offset )
+ {
+ if ( label_offset >= table_size )
+ goto InvalidTable;
+ if ( face->palette_data.num_palettes * 2 >
+ table_size - label_offset )
+ goto InvalidTable;
+
+ if ( FT_QNEW_ARRAY( array, face->palette_data.num_palettes ) )
+ goto NoCpal;
+
+ p = table + label_offset;
+ q = array;
+ limit = q + face->palette_data.num_palettes;
+
+ while ( q < limit )
+ *q++ = FT_NEXT_USHORT( p );
+
+ face->palette_data.palette_name_ids = array;
+ }
+
+ if ( entry_label_offset )
+ {
+ if ( entry_label_offset >= table_size )
+ goto InvalidTable;
+ if ( face->palette_data.num_palette_entries * 2 >
+ table_size - entry_label_offset )
+ goto InvalidTable;
+
+ if ( FT_QNEW_ARRAY( array, face->palette_data.num_palette_entries ) )
+ goto NoCpal;
+
+ p = table + entry_label_offset;
+ q = array;
+ limit = q + face->palette_data.num_palette_entries;
+
+ while ( q < limit )
+ *q++ = FT_NEXT_USHORT( p );
+
+ face->palette_data.palette_entry_name_ids = array;
+ }
+ }
+
+ cpal->table = table;
+ cpal->table_size = table_size;
+
+ face->cpal = cpal;
+
+ /* set up default palette */
+ if ( FT_NEW_ARRAY( face->palette,
+ face->palette_data.num_palette_entries ) )
+ goto NoCpal;
+
+ if ( tt_face_palette_set( face, 0 ) )
+ goto InvalidTable;
+
+ return FT_Err_Ok;
+
+ InvalidTable:
+ error = FT_THROW( Invalid_Table );
+
+ NoCpal:
+ FT_FRAME_RELEASE( table );
+ FT_FREE( cpal );
+
+ face->cpal = NULL;
+
+ /* arrays in `face->palette_data' and `face->palette' */
+ /* are freed in `sfnt_done_face' */
+
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ tt_face_free_cpal( TT_Face face )
+ {
+ FT_Stream stream = face->root.stream;
+ FT_Memory memory = face->root.memory;
+
+ Cpal* cpal = (Cpal*)face->cpal;
+
+
+ if ( cpal )
+ {
+ FT_FRAME_RELEASE( cpal->table );
+ FT_FREE( cpal );
+ }
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_palette_set( TT_Face face,
+ FT_UInt palette_index )
+ {
+ Cpal* cpal = (Cpal*)face->cpal;
+
+ FT_Byte* offset;
+ FT_Byte* p;
+
+ FT_Color* q;
+ FT_Color* limit;
+
+ FT_UShort color_index;
+
+
+ if ( !cpal || palette_index >= face->palette_data.num_palettes )
+ return FT_THROW( Invalid_Argument );
+
+ offset = cpal->color_indices + 2 * palette_index;
+ color_index = FT_PEEK_USHORT( offset );
+
+ if ( color_index + face->palette_data.num_palette_entries >
+ cpal->num_colors )
+ return FT_THROW( Invalid_Table );
+
+ p = cpal->colors + COLOR_SIZE * color_index;
+ q = face->palette;
+ limit = q + face->palette_data.num_palette_entries;
+
+ while ( q < limit )
+ {
+ q->blue = FT_NEXT_BYTE( p );
+ q->green = FT_NEXT_BYTE( p );
+ q->red = FT_NEXT_BYTE( p );
+ q->alpha = FT_NEXT_BYTE( p );
+
+ q++;
+ }
+
+ return FT_Err_Ok;
+ }
+
+
+#else /* !TT_CONFIG_OPTION_COLOR_LAYERS */
+
+ /* ANSI C doesn't like empty source files */
+ typedef int _tt_cpal_dummy;
+
+#endif /* !TT_CONFIG_OPTION_COLOR_LAYERS */
+
+/* EOF */
diff --git a/thirdparty/freetype/src/sfnt/ttcpal.h b/thirdparty/freetype/src/sfnt/ttcpal.h
new file mode 100644
index 0000000000..d1b244f3e3
--- /dev/null
+++ b/thirdparty/freetype/src/sfnt/ttcpal.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+ *
+ * ttcpal.h
+ *
+ * TrueType and OpenType color palette support (specification).
+ *
+ * Copyright (C) 2018-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Originally written by Shao Yu Zhang <shaozhang@fb.com>.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef __TTCPAL_H__
+#define __TTCPAL_H__
+
+
+#include <ft2build.h>
+#include "ttload.h"
+
+
+FT_BEGIN_HEADER
+
+
+ FT_LOCAL( FT_Error )
+ tt_face_load_cpal( TT_Face face,
+ FT_Stream stream );
+
+ FT_LOCAL( void )
+ tt_face_free_cpal( TT_Face face );
+
+ FT_LOCAL( FT_Error )
+ tt_face_palette_set( TT_Face face,
+ FT_UInt palette_index );
+
+
+FT_END_HEADER
+
+
+#endif /* __TTCPAL_H__ */
+
+/* END */
diff --git a/thirdparty/freetype/src/sfnt/ttkern.c b/thirdparty/freetype/src/sfnt/ttkern.c
index 68f15a2010..8d1b781090 100644
--- a/thirdparty/freetype/src/sfnt/ttkern.c
+++ b/thirdparty/freetype/src/sfnt/ttkern.c
@@ -1,20 +1,20 @@
-/***************************************************************************/
-/* */
-/* ttkern.c */
-/* */
-/* Load the basic TrueType kerning table. This doesn't handle */
-/* kerning data within the GPOS table at the moment. */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ttkern.c
+ *
+ * Load the basic TrueType kerning table. This doesn't handle
+ * kerning data within the GPOS table at the moment.
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -26,14 +26,14 @@
#include "sferrors.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_ttkern
+#define FT_COMPONENT ttkern
#undef TT_KERN_INDEX
@@ -127,8 +127,8 @@
avail |= mask;
/*
- * Now check whether the pairs in this table are ordered.
- * We then can use binary search.
+ * Now check whether the pairs in this table are ordered.
+ * We then can use binary search.
*/
if ( num_pairs > 0 )
{
@@ -283,8 +283,8 @@
break;
/*
- * We don't support format 2 because we haven't seen a single font
- * using it in real life...
+ * We don't support format 2 because we haven't seen a single font
+ * using it in real life...
*/
default:
diff --git a/thirdparty/freetype/src/sfnt/ttkern.h b/thirdparty/freetype/src/sfnt/ttkern.h
index 4e45d0964b..5f283e5e62 100644
--- a/thirdparty/freetype/src/sfnt/ttkern.h
+++ b/thirdparty/freetype/src/sfnt/ttkern.h
@@ -1,20 +1,20 @@
-/***************************************************************************/
-/* */
-/* ttkern.h */
-/* */
-/* Load the basic TrueType kerning table. This doesn't handle */
-/* kerning data within the GPOS table at the moment. */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ttkern.h
+ *
+ * Load the basic TrueType kerning table. This doesn't handle
+ * kerning data within the GPOS table at the moment.
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef TTKERN_H_
diff --git a/thirdparty/freetype/src/sfnt/ttload.c b/thirdparty/freetype/src/sfnt/ttload.c
index a86a546c3d..5443bf4b69 100644
--- a/thirdparty/freetype/src/sfnt/ttload.c
+++ b/thirdparty/freetype/src/sfnt/ttload.c
@@ -1,20 +1,20 @@
-/***************************************************************************/
-/* */
-/* ttload.c */
-/* */
-/* Load the basic TrueType tables, i.e., tables that can be either in */
-/* TTF or OTF fonts (body). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ttload.c
+ *
+ * Load the basic TrueType tables, i.e., tables that can be either in
+ * TTF or OTF fonts (body).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -26,32 +26,34 @@
#include "sferrors.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_ttload
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_lookup_table */
- /* */
- /* <Description> */
- /* Looks for a TrueType table by name. */
- /* */
- /* <Input> */
- /* face :: A face object handle. */
- /* */
- /* tag :: The searched tag. */
- /* */
- /* <Return> */
- /* A pointer to the table directory entry. 0 if not found. */
- /* */
+#define FT_COMPONENT ttload
+
+
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_face_lookup_table
+ *
+ * @Description:
+ * Looks for a TrueType table by name.
+ *
+ * @Input:
+ * face ::
+ * A face object handle.
+ *
+ * tag ::
+ * The searched tag.
+ *
+ * @Return:
+ * A pointer to the table directory entry. 0 if not found.
+ */
FT_LOCAL_DEF( TT_Table )
tt_face_lookup_table( TT_Face face,
FT_ULong tag )
@@ -101,27 +103,31 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_goto_table */
- /* */
- /* <Description> */
- /* Looks for a TrueType table by name, then seek a stream to it. */
- /* */
- /* <Input> */
- /* face :: A face object handle. */
- /* */
- /* tag :: The searched tag. */
- /* */
- /* stream :: The stream to seek when the table is found. */
- /* */
- /* <Output> */
- /* length :: The length of the table if found, undefined otherwise. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_face_goto_table
+ *
+ * @Description:
+ * Looks for a TrueType table by name, then seek a stream to it.
+ *
+ * @Input:
+ * face ::
+ * A face object handle.
+ *
+ * tag ::
+ * The searched tag.
+ *
+ * stream ::
+ * The stream to seek when the table is found.
+ *
+ * @Output:
+ * length ::
+ * The length of the table if found, undefined otherwise.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
tt_face_goto_table( TT_Face face,
FT_ULong tag,
@@ -309,28 +315,31 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_load_font_dir */
- /* */
- /* <Description> */
- /* Loads the header of a SFNT font file. */
- /* */
- /* <Input> */
- /* face :: A handle to the target face object. */
- /* */
- /* stream :: The input stream. */
- /* */
- /* <Output> */
- /* sfnt :: The SFNT header. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- /* <Note> */
- /* The stream cursor must be at the beginning of the font directory. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_face_load_font_dir
+ *
+ * @Description:
+ * Loads the header of a SFNT font file.
+ *
+ * @Input:
+ * face ::
+ * A handle to the target face object.
+ *
+ * stream ::
+ * The input stream.
+ *
+ * @Output:
+ * sfnt ::
+ * The SFNT header.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ *
+ * @Note:
+ * The stream cursor must be at the beginning of the font directory.
+ */
FT_LOCAL_DEF( FT_Error )
tt_face_load_font_dir( TT_Face face,
FT_Stream stream )
@@ -496,46 +505,51 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_load_any */
- /* */
- /* <Description> */
- /* Loads any font table into client memory. */
- /* */
- /* <Input> */
- /* face :: The face object to look for. */
- /* */
- /* tag :: The tag of table to load. Use the value 0 if you want */
- /* to access the whole font file, else set this parameter */
- /* to a valid TrueType table tag that you can forge with */
- /* the MAKE_TT_TAG macro. */
- /* */
- /* offset :: The starting offset in the table (or the file if */
- /* tag == 0). */
- /* */
- /* length :: The address of the decision variable: */
- /* */
- /* If length == NULL: */
- /* Loads the whole table. Returns an error if */
- /* `offset' == 0! */
- /* */
- /* If *length == 0: */
- /* Exits immediately; returning the length of the given */
- /* table or of the font file, depending on the value of */
- /* `tag'. */
- /* */
- /* If *length != 0: */
- /* Loads the next `length' bytes of table or font, */
- /* starting at offset `offset' (in table or font too). */
- /* */
- /* <Output> */
- /* buffer :: The address of target buffer. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_face_load_any
+ *
+ * @Description:
+ * Loads any font table into client memory.
+ *
+ * @Input:
+ * face ::
+ * The face object to look for.
+ *
+ * tag ::
+ * The tag of table to load. Use the value 0 if you want
+ * to access the whole font file, else set this parameter
+ * to a valid TrueType table tag that you can forge with
+ * the MAKE_TT_TAG macro.
+ *
+ * offset ::
+ * The starting offset in the table (or the file if
+ * tag == 0).
+ *
+ * length ::
+ * The address of the decision variable:
+ *
+ * If length == NULL:
+ * Loads the whole table. Returns an error if
+ * `offset' == 0!
+ *
+ * If *length == 0:
+ * Exits immediately; returning the length of the given
+ * table or of the font file, depending on the value of
+ * `tag'.
+ *
+ * If *length != 0:
+ * Loads the next `length' bytes of table or font,
+ * starting at offset `offset' (in table or font too).
+ *
+ * @Output:
+ * buffer ::
+ * The address of target buffer.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
tt_face_load_any( TT_Face face,
FT_ULong tag,
@@ -586,22 +600,24 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_load_generic_header */
- /* */
- /* <Description> */
- /* Loads the TrueType table `head' or `bhed'. */
- /* */
- /* <Input> */
- /* face :: A handle to the target face object. */
- /* */
- /* stream :: The input stream. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_face_load_generic_header
+ *
+ * @Description:
+ * Loads the TrueType table `head' or `bhed'.
+ *
+ * @Input:
+ * face ::
+ * A handle to the target face object.
+ *
+ * stream ::
+ * The input stream.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
static FT_Error
tt_face_load_generic_header( TT_Face face,
FT_Stream stream,
@@ -622,10 +638,10 @@
FT_FRAME_LONG ( Magic_Number ),
FT_FRAME_USHORT( Flags ),
FT_FRAME_USHORT( Units_Per_EM ),
- FT_FRAME_LONG ( Created[0] ),
- FT_FRAME_LONG ( Created[1] ),
- FT_FRAME_LONG ( Modified[0] ),
- FT_FRAME_LONG ( Modified[1] ),
+ FT_FRAME_ULONG ( Created[0] ),
+ FT_FRAME_ULONG ( Created[1] ),
+ FT_FRAME_ULONG ( Modified[0] ),
+ FT_FRAME_ULONG ( Modified[1] ),
FT_FRAME_SHORT ( xMin ),
FT_FRAME_SHORT ( yMin ),
FT_FRAME_SHORT ( xMax ),
@@ -676,22 +692,24 @@
#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_load_maxp */
- /* */
- /* <Description> */
- /* Loads the maximum profile into a face object. */
- /* */
- /* <Input> */
- /* face :: A handle to the target face object. */
- /* */
- /* stream :: The input stream. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_face_load_maxp
+ *
+ * @Description:
+ * Loads the maximum profile into a face object.
+ *
+ * @Input:
+ * face ::
+ * A handle to the target face object.
+ *
+ * stream ::
+ * The input stream.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
tt_face_load_maxp( TT_Face face,
FT_Stream stream )
@@ -784,22 +802,24 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_load_name */
- /* */
- /* <Description> */
- /* Loads the name records. */
- /* */
- /* <Input> */
- /* face :: A handle to the target face object. */
- /* */
- /* stream :: The input stream. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_face_load_name
+ *
+ * @Description:
+ * Loads the name records.
+ *
+ * @Input:
+ * face ::
+ * A handle to the target face object.
+ *
+ * stream ::
+ * The input stream.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
tt_face_load_name( TT_Face face,
FT_Stream stream )
@@ -981,17 +1001,18 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_free_name */
- /* */
- /* <Description> */
- /* Frees the name records. */
- /* */
- /* <Input> */
- /* face :: A handle to the target face object. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_face_free_name
+ *
+ * @Description:
+ * Frees the name records.
+ *
+ * @Input:
+ * face ::
+ * A handle to the target face object.
+ */
FT_LOCAL_DEF( void )
tt_face_free_name( TT_Face face )
{
@@ -1030,23 +1051,25 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_load_cmap */
- /* */
- /* <Description> */
- /* Loads the cmap directory in a face object. The cmaps themselves */
- /* are loaded on demand in the `ttcmap.c' module. */
- /* */
- /* <Input> */
- /* face :: A handle to the target face object. */
- /* */
- /* stream :: A handle to the input stream. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_face_load_cmap
+ *
+ * @Description:
+ * Loads the cmap directory in a face object. The cmaps themselves
+ * are loaded on demand in the `ttcmap.c' module.
+ *
+ * @Input:
+ * face ::
+ * A handle to the target face object.
+ *
+ * stream ::
+ * A handle to the input stream.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
tt_face_load_cmap( TT_Face face,
@@ -1068,22 +1091,24 @@
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_load_os2 */
- /* */
- /* <Description> */
- /* Loads the OS2 table. */
- /* */
- /* <Input> */
- /* face :: A handle to the target face object. */
- /* */
- /* stream :: A handle to the input stream. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_face_load_os2
+ *
+ * @Description:
+ * Loads the OS2 table.
+ *
+ * @Input:
+ * face ::
+ * A handle to the target face object.
+ *
+ * stream ::
+ * A handle to the input stream.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
tt_face_load_os2( TT_Face face,
FT_Stream stream )
@@ -1228,22 +1253,24 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_load_postscript */
- /* */
- /* <Description> */
- /* Loads the Postscript table. */
- /* */
- /* <Input> */
- /* face :: A handle to the target face object. */
- /* */
- /* stream :: A handle to the input stream. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_face_load_postscript
+ *
+ * @Description:
+ * Loads the Postscript table.
+ *
+ * @Input:
+ * face ::
+ * A handle to the target face object.
+ *
+ * stream ::
+ * A handle to the input stream.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
tt_face_load_post( TT_Face face,
FT_Stream stream )
@@ -1288,22 +1315,24 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_load_pclt */
- /* */
- /* <Description> */
- /* Loads the PCL 5 Table. */
- /* */
- /* <Input> */
- /* face :: A handle to the target face object. */
- /* */
- /* stream :: A handle to the input stream. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_face_load_pclt
+ *
+ * @Description:
+ * Loads the PCL 5 Table.
+ *
+ * @Input:
+ * face ::
+ * A handle to the target face object.
+ *
+ * stream ::
+ * A handle to the input stream.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
tt_face_load_pclt( TT_Face face,
FT_Stream stream )
@@ -1349,22 +1378,24 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_load_gasp */
- /* */
- /* <Description> */
- /* Loads the `gasp' table into a face object. */
- /* */
- /* <Input> */
- /* face :: A handle to the target face object. */
- /* */
- /* stream :: The input stream. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_face_load_gasp
+ *
+ * @Description:
+ * Loads the `gasp' table into a face object.
+ *
+ * @Input:
+ * face ::
+ * A handle to the target face object.
+ *
+ * stream ::
+ * The input stream.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
tt_face_load_gasp( TT_Face face,
FT_Stream stream )
diff --git a/thirdparty/freetype/src/sfnt/ttload.h b/thirdparty/freetype/src/sfnt/ttload.h
index f94be8b7bd..cc18c18694 100644
--- a/thirdparty/freetype/src/sfnt/ttload.h
+++ b/thirdparty/freetype/src/sfnt/ttload.h
@@ -1,20 +1,20 @@
-/***************************************************************************/
-/* */
-/* ttload.h */
-/* */
-/* Load the basic TrueType tables, i.e., tables that can be either in */
-/* TTF or OTF fonts (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ttload.h
+ *
+ * Load the basic TrueType tables, i.e., tables that can be either in
+ * TTF or OTF fonts (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef TTLOAD_H_
diff --git a/thirdparty/freetype/src/sfnt/ttmtx.c b/thirdparty/freetype/src/sfnt/ttmtx.c
index 6ddda95b56..7a4d2be2cb 100644
--- a/thirdparty/freetype/src/sfnt/ttmtx.c
+++ b/thirdparty/freetype/src/sfnt/ttmtx.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ttmtx.c */
-/* */
-/* Load the metrics tables common to TTF and OTF fonts (body). */
-/* */
-/* Copyright 2006-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ttmtx.c
+ *
+ * Load the metrics tables common to TTF and OTF fonts (body).
+ *
+ * Copyright (C) 2006-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -38,34 +38,37 @@
/* both the horizontal and vertical headers. */
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_ttmtx
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_load_hmtx */
- /* */
- /* <Description> */
- /* Load the `hmtx' or `vmtx' table into a face object. */
- /* */
- /* <Input> */
- /* face :: A handle to the target face object. */
- /* */
- /* stream :: The input stream. */
- /* */
- /* vertical :: A boolean flag. If set, load `vmtx'. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+#define FT_COMPONENT ttmtx
+
+
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_face_load_hmtx
+ *
+ * @Description:
+ * Load the `hmtx' or `vmtx' table into a face object.
+ *
+ * @Input:
+ * face ::
+ * A handle to the target face object.
+ *
+ * stream ::
+ * The input stream.
+ *
+ * vertical ::
+ * A boolean flag. If set, load `vmtx'.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
tt_face_load_hmtx( TT_Face face,
FT_Stream stream,
@@ -102,24 +105,27 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_load_hhea */
- /* */
- /* <Description> */
- /* Load the `hhea' or 'vhea' table into a face object. */
- /* */
- /* <Input> */
- /* face :: A handle to the target face object. */
- /* */
- /* stream :: The input stream. */
- /* */
- /* vertical :: A boolean flag. If set, load `vhea'. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_face_load_hhea
+ *
+ * @Description:
+ * Load the `hhea' or 'vhea' table into a face object.
+ *
+ * @Input:
+ * face ::
+ * A handle to the target face object.
+ *
+ * stream ::
+ * The input stream.
+ *
+ * vertical ::
+ * A boolean flag. If set, load `vhea'.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
tt_face_load_hhea( TT_Face face,
FT_Stream stream,
@@ -190,30 +196,35 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_get_metrics */
- /* */
- /* <Description> */
- /* Return the horizontal or vertical metrics in font units for a */
- /* given glyph. The values are the left side bearing (top side */
- /* bearing for vertical metrics) and advance width (advance height */
- /* for vertical metrics). */
- /* */
- /* <Input> */
- /* face :: A pointer to the TrueType face structure. */
- /* */
- /* vertical :: If set to TRUE, get vertical metrics. */
- /* */
- /* gindex :: The glyph index. */
- /* */
- /* <Output> */
- /* abearing :: The bearing, either left side or top side. */
- /* */
- /* aadvance :: The advance width or advance height, depending on */
- /* the `vertical' flag. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_face_get_metrics
+ *
+ * @Description:
+ * Return the horizontal or vertical metrics in font units for a
+ * given glyph. The values are the left side bearing (top side
+ * bearing for vertical metrics) and advance width (advance height
+ * for vertical metrics).
+ *
+ * @Input:
+ * face ::
+ * A pointer to the TrueType face structure.
+ *
+ * vertical ::
+ * If set to TRUE, get vertical metrics.
+ *
+ * gindex ::
+ * The glyph index.
+ *
+ * @Output:
+ * abearing ::
+ * The bearing, either left side or top side.
+ *
+ * aadvance ::
+ * The advance width or advance height, depending on
+ * the `vertical' flag.
+ */
FT_LOCAL_DEF( void )
tt_face_get_metrics( TT_Face face,
FT_Bool vertical,
diff --git a/thirdparty/freetype/src/sfnt/ttmtx.h b/thirdparty/freetype/src/sfnt/ttmtx.h
index ab00acd795..5b0b60b641 100644
--- a/thirdparty/freetype/src/sfnt/ttmtx.h
+++ b/thirdparty/freetype/src/sfnt/ttmtx.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ttmtx.h */
-/* */
-/* Load the metrics tables common to TTF and OTF fonts (specification). */
-/* */
-/* Copyright 2006-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ttmtx.h
+ *
+ * Load the metrics tables common to TTF and OTF fonts (specification).
+ *
+ * Copyright (C) 2006-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef TTMTX_H_
diff --git a/thirdparty/freetype/src/sfnt/ttpost.c b/thirdparty/freetype/src/sfnt/ttpost.c
index 6de99ef977..636a0a004a 100644
--- a/thirdparty/freetype/src/sfnt/ttpost.c
+++ b/thirdparty/freetype/src/sfnt/ttpost.c
@@ -1,28 +1,28 @@
-/***************************************************************************/
-/* */
-/* ttpost.c */
-/* */
-/* PostScript name table processing for TrueType and OpenType fonts */
-/* (body). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
- /*************************************************************************/
- /* */
- /* The post table is not completely loaded by the core engine. This */
- /* file loads the missing PS glyph names and implements an API to access */
- /* them. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * ttpost.c
+ *
+ * PostScript name table processing for TrueType and OpenType fonts
+ * (body).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+ /**************************************************************************
+ *
+ * The post table is not completely loaded by the core engine. This
+ * file loads the missing PS glyph names and implements an API to access
+ * them.
+ *
+ */
#include <ft2build.h>
@@ -38,17 +38,17 @@
#include "sferrors.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_ttpost
+#define FT_COMPONENT ttpost
- /* If this configuration macro is defined, we rely on the `PSNames' */
+ /* If this configuration macro is defined, we rely on the `psnames' */
/* module to grab the glyph names. */
#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
@@ -62,9 +62,9 @@
#else /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
- /* Otherwise, we ignore the `PSNames' module, and provide our own */
+ /* Otherwise, we ignore the `psnames' module, and provide our own */
/* table of Mac names. Thus, it is possible to build a version of */
- /* FreeType without the Type 1 driver & PSNames module. */
+ /* FreeType without the Type 1 driver & psnames module. */
#define MAC_NAME( x ) (FT_String*)tt_post_default_names[x]
@@ -459,28 +459,31 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_get_ps_name */
- /* */
- /* <Description> */
- /* Get the PostScript glyph name of a glyph. */
- /* */
- /* <Input> */
- /* face :: A handle to the parent face. */
- /* */
- /* idx :: The glyph index. */
- /* */
- /* <InOut> */
- /* PSname :: The address of a string pointer. Undefined in case of */
- /* error, otherwise it is a pointer to the glyph name. */
- /* */
- /* You must not modify the returned string! */
- /* */
- /* <Output> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_face_get_ps_name
+ *
+ * @Description:
+ * Get the PostScript glyph name of a glyph.
+ *
+ * @Input:
+ * face ::
+ * A handle to the parent face.
+ *
+ * idx ::
+ * The glyph index.
+ *
+ * @InOut:
+ * PSname ::
+ * The address of a string pointer. Undefined in case of
+ * error, otherwise it is a pointer to the glyph name.
+ *
+ * You must not modify the returned string!
+ *
+ * @Output:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
tt_face_get_ps_name( TT_Face face,
FT_UInt idx,
diff --git a/thirdparty/freetype/src/sfnt/ttpost.h b/thirdparty/freetype/src/sfnt/ttpost.h
index 3bec07e445..812a0fc92d 100644
--- a/thirdparty/freetype/src/sfnt/ttpost.h
+++ b/thirdparty/freetype/src/sfnt/ttpost.h
@@ -1,20 +1,20 @@
-/***************************************************************************/
-/* */
-/* ttpost.h */
-/* */
-/* PostScript name table processing for TrueType and OpenType fonts */
-/* (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ttpost.h
+ *
+ * PostScript name table processing for TrueType and OpenType fonts
+ * (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef TTPOST_H_
diff --git a/thirdparty/freetype/src/sfnt/ttsbit.c b/thirdparty/freetype/src/sfnt/ttsbit.c
index 33b8640bc3..23bd9d7eb0 100644
--- a/thirdparty/freetype/src/sfnt/ttsbit.c
+++ b/thirdparty/freetype/src/sfnt/ttsbit.c
@@ -1,22 +1,22 @@
-/***************************************************************************/
-/* */
-/* ttsbit.c */
-/* */
-/* TrueType and OpenType embedded bitmap support (body). */
-/* */
-/* Copyright 2005-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* Copyright 2013 by Google, Inc. */
-/* Google Author(s): Behdad Esfahbod. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ttsbit.c
+ *
+ * TrueType and OpenType embedded bitmap support (body).
+ *
+ * Copyright (C) 2005-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Copyright 2013 by Google, Inc.
+ * Google Author(s): Behdad Esfahbod.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -36,14 +36,14 @@
#include "pngshim.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_ttsbit
+#define FT_COMPONENT ttsbit
FT_LOCAL_DEF( FT_Error )
@@ -129,8 +129,8 @@
}
/*
- * Count the number of strikes available in the table. We are a bit
- * paranoid there and don't trust the data.
+ * Count the number of strikes available in the table. We are a bit
+ * paranoid there and don't trust the data.
*/
count = (FT_UInt)num_strikes;
if ( 8 + 48UL * count > table_size )
@@ -182,8 +182,8 @@
" expect bad rendering results\n" ));
/*
- * Count the number of strikes available in the table. We are a bit
- * paranoid there and don't trust the data.
+ * Count the number of strikes available in the table. We are a bit
+ * paranoid there and don't trust the data.
*/
count = (FT_UInt)num_strikes;
if ( 8 + 4UL * count > table_size )
@@ -1014,8 +1014,8 @@
for ( nn = 0; nn < num_components; nn++ )
{
FT_UInt gindex = FT_NEXT_USHORT( p );
- FT_Byte dx = FT_NEXT_BYTE( p );
- FT_Byte dy = FT_NEXT_BYTE( p );
+ FT_Char dx = FT_NEXT_CHAR( p );
+ FT_Char dy = FT_NEXT_CHAR( p );
/* NB: a recursive call */
diff --git a/thirdparty/freetype/src/sfnt/ttsbit.h b/thirdparty/freetype/src/sfnt/ttsbit.h
index ce2af3c162..5ab8ff5568 100644
--- a/thirdparty/freetype/src/sfnt/ttsbit.h
+++ b/thirdparty/freetype/src/sfnt/ttsbit.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ttsbit.h */
-/* */
-/* TrueType and OpenType embedded bitmap support (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ttsbit.h
+ *
+ * TrueType and OpenType embedded bitmap support (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef TTSBIT_H_
diff --git a/thirdparty/freetype/src/smooth/ftgrays.c b/thirdparty/freetype/src/smooth/ftgrays.c
index 803a19e415..91293ac946 100644
--- a/thirdparty/freetype/src/smooth/ftgrays.c
+++ b/thirdparty/freetype/src/smooth/ftgrays.c
@@ -1,94 +1,94 @@
-/***************************************************************************/
-/* */
-/* ftgrays.c */
-/* */
-/* A new `perfect' anti-aliasing renderer (body). */
-/* */
-/* Copyright 2000-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
- /*************************************************************************/
- /* */
- /* This file can be compiled without the rest of the FreeType engine, by */
- /* defining the STANDALONE_ macro when compiling it. You also need to */
- /* put the files `ftgrays.h' and `ftimage.h' into the current */
- /* compilation directory. Typically, you could do something like */
- /* */
- /* - copy `src/smooth/ftgrays.c' (this file) to your current directory */
- /* */
- /* - copy `include/freetype/ftimage.h' and `src/smooth/ftgrays.h' to the */
- /* same directory */
- /* */
- /* - compile `ftgrays' with the STANDALONE_ macro defined, as in */
- /* */
- /* cc -c -DSTANDALONE_ ftgrays.c */
- /* */
- /* The renderer can be initialized with a call to */
- /* `ft_gray_raster.raster_new'; an anti-aliased bitmap can be generated */
- /* with a call to `ft_gray_raster.raster_render'. */
- /* */
- /* See the comments and documentation in the file `ftimage.h' for more */
- /* details on how the raster works. */
- /* */
- /*************************************************************************/
-
- /*************************************************************************/
- /* */
- /* This is a new anti-aliasing scan-converter for FreeType 2. The */
- /* algorithm used here is _very_ different from the one in the standard */
- /* `ftraster' module. Actually, `ftgrays' computes the _exact_ */
- /* coverage of the outline on each pixel cell. */
- /* */
- /* It is based on ideas that I initially found in Raph Levien's */
- /* excellent LibArt graphics library (see http://www.levien.com/libart */
- /* for more information, though the web pages do not tell anything */
- /* about the renderer; you'll have to dive into the source code to */
- /* understand how it works). */
- /* */
- /* Note, however, that this is a _very_ different implementation */
- /* compared to Raph's. Coverage information is stored in a very */
- /* different way, and I don't use sorted vector paths. Also, it doesn't */
- /* use floating point values. */
- /* */
- /* This renderer has the following advantages: */
- /* */
- /* - It doesn't need an intermediate bitmap. Instead, one can supply a */
- /* callback function that will be called by the renderer to draw gray */
- /* spans on any target surface. You can thus do direct composition on */
- /* any kind of bitmap, provided that you give the renderer the right */
- /* callback. */
- /* */
- /* - A perfect anti-aliaser, i.e., it computes the _exact_ coverage on */
- /* each pixel cell. */
- /* */
- /* - It performs a single pass on the outline (the `standard' FT2 */
- /* renderer makes two passes). */
- /* */
- /* - It can easily be modified to render to _any_ number of gray levels */
- /* cheaply. */
- /* */
- /* - For small (< 20) pixel sizes, it is faster than the standard */
- /* renderer. */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+/****************************************************************************
+ *
+ * ftgrays.c
+ *
+ * A new `perfect' anti-aliasing renderer (body).
+ *
+ * Copyright (C) 2000-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+ /**************************************************************************
+ *
+ * This file can be compiled without the rest of the FreeType engine, by
+ * defining the STANDALONE_ macro when compiling it. You also need to
+ * put the files `ftgrays.h' and `ftimage.h' into the current
+ * compilation directory. Typically, you could do something like
+ *
+ * - copy `src/smooth/ftgrays.c' (this file) to your current directory
+ *
+ * - copy `include/freetype/ftimage.h' and `src/smooth/ftgrays.h' to the
+ * same directory
+ *
+ * - compile `ftgrays' with the STANDALONE_ macro defined, as in
+ *
+ * cc -c -DSTANDALONE_ ftgrays.c
+ *
+ * The renderer can be initialized with a call to
+ * `ft_gray_raster.raster_new'; an anti-aliased bitmap can be generated
+ * with a call to `ft_gray_raster.raster_render'.
+ *
+ * See the comments and documentation in the file `ftimage.h' for more
+ * details on how the raster works.
+ *
+ */
+
+ /**************************************************************************
+ *
+ * This is a new anti-aliasing scan-converter for FreeType 2. The
+ * algorithm used here is _very_ different from the one in the standard
+ * `ftraster' module. Actually, `ftgrays' computes the _exact_
+ * coverage of the outline on each pixel cell.
+ *
+ * It is based on ideas that I initially found in Raph Levien's
+ * excellent LibArt graphics library (see https://www.levien.com/libart
+ * for more information, though the web pages do not tell anything
+ * about the renderer; you'll have to dive into the source code to
+ * understand how it works).
+ *
+ * Note, however, that this is a _very_ different implementation
+ * compared to Raph's. Coverage information is stored in a very
+ * different way, and I don't use sorted vector paths. Also, it doesn't
+ * use floating point values.
+ *
+ * This renderer has the following advantages:
+ *
+ * - It doesn't need an intermediate bitmap. Instead, one can supply a
+ * callback function that will be called by the renderer to draw gray
+ * spans on any target surface. You can thus do direct composition on
+ * any kind of bitmap, provided that you give the renderer the right
+ * callback.
+ *
+ * - A perfect anti-aliaser, i.e., it computes the _exact_ coverage on
+ * each pixel cell.
+ *
+ * - It performs a single pass on the outline (the `standard' FT2
+ * renderer makes two passes).
+ *
+ * - It can easily be modified to render to _any_ number of gray levels
+ * cheaply.
+ *
+ * - For small (< 20) pixel sizes, it is faster than the standard
+ * renderer.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_smooth
+#define FT_COMPONENT smooth
#ifdef STANDALONE_
@@ -112,9 +112,9 @@
/*
- * Approximate sqrt(x*x+y*y) using the `alpha max plus beta min'
- * algorithm. We use alpha = 1, beta = 3/8, giving us results with a
- * largest error less than 7% compared to the exact value.
+ * Approximate sqrt(x*x+y*y) using the `alpha max plus beta min'
+ * algorithm. We use alpha = 1, beta = 3/8, giving us results with a
+ * largest error less than 7% compared to the exact value.
*/
#define FT_HYPOT( x, y ) \
( x = FT_ABS( x ), \
@@ -222,10 +222,10 @@ typedef ptrdiff_t FT_PtrDist;
#endif
#define FT_THROW( e ) \
- ( FT_Throw( FT_ERR_CAT( ErrRaster, e ), \
+ ( FT_Throw( FT_ERR_CAT( ErrRaster_, e ), \
__LINE__, \
__FILE__ ) | \
- FT_ERR_CAT( ErrRaster, e ) )
+ FT_ERR_CAT( ErrRaster_, e ) )
#else /* !FT_DEBUG_LEVEL_TRACE */
@@ -279,8 +279,6 @@ typedef ptrdiff_t FT_PtrDist;
#include "ftsmerrs.h"
-#include "ftspic.h"
-
#define Smooth_Err_Invalid_Mode Smooth_Err_Cannot_Render_Glyph
#define Smooth_Err_Memory_Overflow Smooth_Err_Out_Of_Memory
#define ErrRaster_Memory_Overflow Smooth_Err_Out_Of_Memory
@@ -395,10 +393,10 @@ typedef ptrdiff_t FT_PtrDist;
( sizeof( long ) * FT_CHAR_BIT - PIXEL_BITS ) )
- /*************************************************************************/
- /* */
- /* TYPE DEFINITIONS */
- /* */
+ /**************************************************************************
+ *
+ * TYPE DEFINITIONS
+ */
/* don't change the following types to FT_Int or FT_Pos, since we might */
/* need to define them to "float" or "double" when experimenting with */
@@ -516,10 +514,10 @@ typedef ptrdiff_t FT_PtrDist;
#endif /* FT_DEBUG_LEVEL_TRACE */
- /*************************************************************************/
- /* */
- /* Record the current cell in the table. */
- /* */
+ /**************************************************************************
+ *
+ * Record the current cell in the table.
+ */
static void
gray_record_cell( RAS_ARG )
{
@@ -561,10 +559,10 @@ typedef ptrdiff_t FT_PtrDist;
}
- /*************************************************************************/
- /* */
- /* Set the current cell to a new position. */
- /* */
+ /**************************************************************************
+ *
+ * Set the current cell to a new position.
+ */
static void
gray_set_cell( RAS_ARG_ TCoord ex,
TCoord ey )
@@ -598,10 +596,10 @@ typedef ptrdiff_t FT_PtrDist;
#ifndef FT_LONG64
- /*************************************************************************/
- /* */
- /* Render a scanline as one or more cells. */
- /* */
+ /**************************************************************************
+ *
+ * Render a scanline as one or more cells.
+ */
static void
gray_render_scanline( RAS_ARG_ TCoord ey,
TPos x1,
@@ -696,10 +694,10 @@ typedef ptrdiff_t FT_PtrDist;
}
- /*************************************************************************/
- /* */
- /* Render a given line as a series of scanlines. */
- /* */
+ /**************************************************************************
+ *
+ * Render a given line as a series of scanlines.
+ */
static void
gray_render_line( RAS_ARG_ TPos to_x,
TPos to_y )
@@ -837,10 +835,10 @@ typedef ptrdiff_t FT_PtrDist;
#else
- /*************************************************************************/
- /* */
- /* Render a straight line across multiple cells in any direction. */
- /* */
+ /**************************************************************************
+ *
+ * Render a straight line across multiple cells in any direction.
+ */
static void
gray_render_line( RAS_ARG_ TPos to_x,
TPos to_y )
@@ -1330,40 +1328,43 @@ typedef ptrdiff_t FT_PtrDist;
#ifdef STANDALONE_
- /*************************************************************************/
- /* */
- /* The following functions should only compile in stand-alone mode, */
- /* i.e., when building this component without the rest of FreeType. */
- /* */
- /*************************************************************************/
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Outline_Decompose */
- /* */
- /* <Description> */
- /* Walk over an outline's structure to decompose it into individual */
- /* segments and Bézier arcs. This function is also able to emit */
- /* `move to' and `close to' operations to indicate the start and end */
- /* of new contours in the outline. */
- /* */
- /* <Input> */
- /* outline :: A pointer to the source target. */
- /* */
- /* func_interface :: A table of `emitters', i.e., function pointers */
- /* called during decomposition to indicate path */
- /* operations. */
- /* */
- /* <InOut> */
- /* user :: A typeless pointer which is passed to each */
- /* emitter during the decomposition. It can be */
- /* used to store the state during the */
- /* decomposition. */
- /* */
- /* <Return> */
- /* Error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * The following functions should only compile in stand-alone mode,
+ * i.e., when building this component without the rest of FreeType.
+ *
+ */
+
+ /**************************************************************************
+ *
+ * @Function:
+ * FT_Outline_Decompose
+ *
+ * @Description:
+ * Walk over an outline's structure to decompose it into individual
+ * segments and Bézier arcs. This function is also able to emit
+ * `move to' and `close to' operations to indicate the start and end
+ * of new contours in the outline.
+ *
+ * @Input:
+ * outline ::
+ * A pointer to the source target.
+ *
+ * func_interface ::
+ * A table of `emitters', i.e., function pointers
+ * called during decomposition to indicate path
+ * operations.
+ *
+ * @InOut:
+ * user ::
+ * A typeless pointer which is passed to each
+ * emitter during the decomposition. It can be
+ * used to store the state during the
+ * decomposition.
+ *
+ * @Return:
+ * Error code. 0 means success.
+ */
static int
FT_Outline_Decompose( const FT_Outline* outline,
const FT_Outline_Funcs* func_interface,
@@ -1610,81 +1611,6 @@ typedef ptrdiff_t FT_PtrDist;
return FT_THROW( Invalid_Outline );
}
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Outline_Get_CBox */
- /* */
- /* <Description> */
- /* Return an outline's `control box'. The control box encloses all */
- /* the outline's points, including Bézier control points. Though it */
- /* coincides with the exact bounding box for most glyphs, it can be */
- /* slightly larger in some situations (like when rotating an outline */
- /* that contains Bézier outside arcs). */
- /* */
- /* Computing the control box is very fast, while getting the bounding */
- /* box can take much more time as it needs to walk over all segments */
- /* and arcs in the outline. To get the latter, you can use the */
- /* `ftbbox' component, which is dedicated to this single task. */
- /* */
- /* <Input> */
- /* outline :: A pointer to the source outline descriptor. */
- /* */
- /* <Output> */
- /* acbox :: The outline's control box. */
- /* */
- /* <Note> */
- /* See @FT_Glyph_Get_CBox for a discussion of tricky fonts. */
- /* */
-
- static void
- FT_Outline_Get_CBox( const FT_Outline* outline,
- FT_BBox *acbox )
- {
- TPos xMin, yMin, xMax, yMax;
-
-
- if ( outline && acbox )
- {
- if ( outline->n_points == 0 )
- {
- xMin = 0;
- yMin = 0;
- xMax = 0;
- yMax = 0;
- }
- else
- {
- FT_Vector* vec = outline->points;
- FT_Vector* limit = vec + outline->n_points;
-
-
- xMin = xMax = vec->x;
- yMin = yMax = vec->y;
- vec++;
-
- for ( ; vec < limit; vec++ )
- {
- TPos x, y;
-
-
- x = vec->x;
- if ( x < xMin ) xMin = x;
- if ( x > xMax ) xMax = x;
-
- y = vec->y;
- if ( y < yMin ) yMin = y;
- if ( y > yMax ) yMax = y;
- }
- }
- acbox->xMin = xMin;
- acbox->xMax = xMax;
- acbox->yMin = yMin;
- acbox->yMax = yMax;
- }
- }
-
#endif /* STANDALONE_ */
@@ -1702,19 +1628,20 @@ typedef ptrdiff_t FT_PtrDist;
static int
- gray_convert_glyph_inner( RAS_ARG )
+ gray_convert_glyph_inner( RAS_ARG,
+ int continued )
{
-
volatile int error = 0;
-#ifdef FT_CONFIG_OPTION_PIC
- FT_Outline_Funcs func_interface;
- Init_Class_func_interface(&func_interface);
-#endif
if ( ft_setjmp( ras.jump_buffer ) == 0 )
{
+ if ( continued )
+ FT_Trace_Disable();
error = FT_Outline_Decompose( &ras.outline, &func_interface, &ras );
+ if ( continued )
+ FT_Trace_Enable();
+
if ( !ras.invalid )
gray_record_cell( RAS_VAR );
@@ -1741,8 +1668,6 @@ typedef ptrdiff_t FT_PtrDist;
{
const TCoord yMin = ras.min_ey;
const TCoord yMax = ras.max_ey;
- const TCoord xMin = ras.min_ex;
- const TCoord xMax = ras.max_ex;
TCell buffer[FT_MAX_GRAY_POOL];
size_t height = (size_t)( yMax - yMin );
@@ -1751,6 +1676,8 @@ typedef ptrdiff_t FT_PtrDist;
TCoord bands[32]; /* enough to accommodate bisections */
TCoord* band;
+ int continued = 0;
+
/* set up vertical bands */
if ( height > n )
@@ -1774,8 +1701,8 @@ typedef ptrdiff_t FT_PtrDist;
ras.max_ey = FT_MIN( y, yMax );
band = bands;
- band[1] = xMin;
- band[0] = xMax;
+ band[1] = ras.min_ey;
+ band[0] = ras.max_ey;
do
{
@@ -1787,10 +1714,11 @@ typedef ptrdiff_t FT_PtrDist;
ras.num_cells = 0;
ras.invalid = 1;
- ras.min_ex = band[1];
- ras.max_ex = band[0];
+ ras.min_ey = band[1];
+ ras.max_ey = band[0];
- error = gray_convert_glyph_inner( RAS_VAR );
+ error = gray_convert_glyph_inner( RAS_VAR, continued );
+ continued = 1;
if ( !error )
{
@@ -1827,7 +1755,7 @@ typedef ptrdiff_t FT_PtrDist;
{
const FT_Outline* outline = (const FT_Outline*)params->source;
const FT_Bitmap* target_map = params->target;
- FT_BBox cbox, clip;
+ FT_BBox clip;
#ifndef FT_STATIC_RASTER
gray_TWorker worker[1];
@@ -1890,21 +1818,11 @@ typedef ptrdiff_t FT_PtrDist;
ras.render_span_data = NULL;
}
- FT_Outline_Get_CBox( outline, &cbox );
-
- /* reject too large outline coordinates */
- if ( cbox.xMin < -0x1000000L || cbox.xMax > 0x1000000L ||
- cbox.yMin < -0x1000000L || cbox.yMax > 0x1000000L )
- return FT_THROW( Invalid_Outline );
-
- /* truncate the bounding box to integer pixels */
- cbox.xMin = cbox.xMin >> 6;
- cbox.yMin = cbox.yMin >> 6;
- cbox.xMax = ( cbox.xMax + 63 ) >> 6;
- cbox.yMax = ( cbox.yMax + 63 ) >> 6;
-
/* compute clipping box */
- if ( !( params->flags & FT_RASTER_FLAG_DIRECT ) )
+ if ( params->flags & FT_RASTER_FLAG_DIRECT &&
+ params->flags & FT_RASTER_FLAG_CLIP )
+ clip = params->clip_box;
+ else
{
/* compute clip box from target pixmap */
clip.xMin = 0;
@@ -1912,21 +1830,12 @@ typedef ptrdiff_t FT_PtrDist;
clip.xMax = (FT_Pos)target_map->width;
clip.yMax = (FT_Pos)target_map->rows;
}
- else if ( params->flags & FT_RASTER_FLAG_CLIP )
- clip = params->clip_box;
- else
- {
- clip.xMin = -32768L;
- clip.yMin = -32768L;
- clip.xMax = 32767L;
- clip.yMax = 32767L;
- }
/* clip to target bitmap, exit if nothing to do */
- ras.min_ex = FT_MAX( cbox.xMin, clip.xMin );
- ras.min_ey = FT_MAX( cbox.yMin, clip.yMin );
- ras.max_ex = FT_MIN( cbox.xMax, clip.xMax );
- ras.max_ey = FT_MIN( cbox.yMax, clip.yMax );
+ ras.min_ex = clip.xMin;
+ ras.min_ey = clip.yMin;
+ ras.max_ex = clip.xMax;
+ ras.max_ey = clip.yMax;
if ( ras.max_ex <= ras.min_ex || ras.max_ey <= ras.min_ey )
return 0;
diff --git a/thirdparty/freetype/src/smooth/ftgrays.h b/thirdparty/freetype/src/smooth/ftgrays.h
index 9e11ca675e..e9f9c7a4ad 100644
--- a/thirdparty/freetype/src/smooth/ftgrays.h
+++ b/thirdparty/freetype/src/smooth/ftgrays.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftgrays.h */
-/* */
-/* FreeType smooth renderer declaration */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftgrays.h
+ *
+ * FreeType smooth renderer declaration
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTGRAYS_H_
@@ -28,19 +28,18 @@
#include "ftimage.h"
#else
#include <ft2build.h>
-#include FT_CONFIG_CONFIG_H /* for FT_CONFIG_OPTION_PIC */
#include FT_IMAGE_H
#endif
- /*************************************************************************/
- /* */
- /* To make ftgrays.h independent from configuration files we check */
- /* whether FT_EXPORT_VAR has been defined already. */
- /* */
- /* On some systems and compilers (Win32 mostly), an extra keyword is */
- /* necessary to compile the library as a DLL. */
- /* */
+ /**************************************************************************
+ *
+ * To make ftgrays.h independent from configuration files we check
+ * whether FT_EXPORT_VAR has been defined already.
+ *
+ * On some systems and compilers (Win32 mostly), an extra keyword is
+ * necessary to compile the library as a DLL.
+ */
#ifndef FT_EXPORT_VAR
#define FT_EXPORT_VAR( x ) extern x
#endif
diff --git a/thirdparty/freetype/src/smooth/ftsmerrs.h b/thirdparty/freetype/src/smooth/ftsmerrs.h
index 226dc1b001..d52c0dd9e2 100644
--- a/thirdparty/freetype/src/smooth/ftsmerrs.h
+++ b/thirdparty/freetype/src/smooth/ftsmerrs.h
@@ -1,27 +1,27 @@
-/***************************************************************************/
-/* */
-/* ftsmerrs.h */
-/* */
-/* smooth renderer error codes (specification only). */
-/* */
-/* Copyright 2001-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* This file is used to define the smooth renderer error enumeration */
- /* constants. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * ftsmerrs.h
+ *
+ * smooth renderer error codes (specification only).
+ *
+ * Copyright (C) 2001-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * This file is used to define the smooth renderer error enumeration
+ * constants.
+ *
+ */
#ifndef FTSMERRS_H_
#define FTSMERRS_H_
diff --git a/thirdparty/freetype/src/smooth/ftsmooth.c b/thirdparty/freetype/src/smooth/ftsmooth.c
index ef176bdf1e..c8b6bb7518 100644
--- a/thirdparty/freetype/src/smooth/ftsmooth.c
+++ b/thirdparty/freetype/src/smooth/ftsmooth.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftsmooth.c */
-/* */
-/* Anti-aliasing renderer interface (body). */
-/* */
-/* Copyright 2000-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftsmooth.c
+ *
+ * Anti-aliasing renderer interface (body).
+ *
+ * Copyright (C) 2000-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -22,7 +22,6 @@
#include FT_OUTLINE_H
#include "ftsmooth.h"
#include "ftgrays.h"
-#include "ftspic.h"
#include "ftsmerrs.h"
@@ -31,6 +30,26 @@
static FT_Error
ft_smooth_init( FT_Renderer render )
{
+
+#ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
+
+ FT_Vector* sub = render->root.library->lcd_geometry;
+
+
+ /* set up default subpixel geometry for striped RGB panels. */
+ sub[0].x = -21;
+ sub[0].y = 0;
+ sub[1].x = 0;
+ sub[1].y = 0;
+ sub[2].x = 21;
+ sub[2].y = 0;
+
+#elif 0 /* or else, once ClearType patents expire */
+
+ FT_Library_SetLcdFilter( render->root.library, FT_LCD_FILTER_DEFAULT );
+
+#endif
+
render->clazz->raster_class->raster_reset( render->raster, NULL, 0 );
return 0;
@@ -130,7 +149,11 @@
slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
}
- ft_glyphslot_preset_bitmap( slot, mode, origin );
+ if ( ft_glyphslot_preset_bitmap( slot, mode, origin ) )
+ {
+ error = FT_THROW( Raster_Overflow );
+ goto Exit;
+ }
/* allocate new one */
if ( FT_ALLOC_MULT( bitmap->buffer, bitmap->rows, bitmap->pitch ) )
@@ -235,33 +258,40 @@
unsigned int width = bitmap->width;
int pitch = bitmap->pitch;
+ FT_Vector* sub = slot->library->lcd_geometry;
- /* Render 3 separate monochrome bitmaps, shifting the outline */
- /* by 1/3 pixel. */
- width /= 3;
- bitmap->buffer += width;
+ /* Render 3 separate monochrome bitmaps, shifting the outline. */
+ width /= 3;
+ FT_Outline_Translate( outline,
+ -sub[0].x,
+ -sub[0].y );
error = render->raster_render( render->raster, &params );
if ( error )
goto Exit;
- FT_Outline_Translate( outline, -21, 0 );
- x_shift -= 21;
bitmap->buffer += width;
-
+ FT_Outline_Translate( outline,
+ sub[0].x - sub[1].x,
+ sub[0].y - sub[1].y );
error = render->raster_render( render->raster, &params );
+ bitmap->buffer -= width;
if ( error )
goto Exit;
- FT_Outline_Translate( outline, 42, 0 );
- x_shift += 42;
- bitmap->buffer -= 2 * width;
-
+ bitmap->buffer += 2 * width;
+ FT_Outline_Translate( outline,
+ sub[1].x - sub[2].x,
+ sub[1].y - sub[2].y );
error = render->raster_render( render->raster, &params );
+ bitmap->buffer -= 2 * width;
if ( error )
goto Exit;
+ x_shift -= sub[2].x;
+ y_shift -= sub[2].y;
+
/* XXX: Rearrange the bytes according to FT_PIXEL_MODE_LCD. */
/* XXX: It is more efficient to render every third byte above. */
@@ -286,34 +316,43 @@
{
int pitch = bitmap->pitch;
+ FT_Vector* sub = slot->library->lcd_geometry;
+
- /* Render 3 separate monochrome bitmaps, shifting the outline */
- /* by 1/3 pixel. Triple the pitch to render on each third row. */
+ /* Render 3 separate monochrome bitmaps, shifting the outline. */
+ /* Notice that the subpixel geometry vectors are rotated. */
+ /* Triple the pitch to render on each third row. */
bitmap->pitch *= 3;
bitmap->rows /= 3;
- bitmap->buffer += pitch;
-
+ FT_Outline_Translate( outline,
+ -sub[0].y,
+ sub[0].x );
error = render->raster_render( render->raster, &params );
if ( error )
goto Exit;
- FT_Outline_Translate( outline, 0, 21 );
- y_shift += 21;
bitmap->buffer += pitch;
-
+ FT_Outline_Translate( outline,
+ sub[0].y - sub[1].y,
+ sub[1].x - sub[0].x );
error = render->raster_render( render->raster, &params );
+ bitmap->buffer -= pitch;
if ( error )
goto Exit;
- FT_Outline_Translate( outline, 0, -42 );
- y_shift -= 42;
- bitmap->buffer -= 2 * pitch;
-
+ bitmap->buffer += 2 * pitch;
+ FT_Outline_Translate( outline,
+ sub[1].y - sub[2].y,
+ sub[2].x - sub[1].x );
error = render->raster_render( render->raster, &params );
+ bitmap->buffer -= 2 * pitch;
if ( error )
goto Exit;
+ x_shift -= sub[2].y;
+ y_shift += sub[2].x;
+
bitmap->pitch /= 3;
bitmap->rows *= 3;
}
@@ -403,7 +442,7 @@
(FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox, /* get_glyph_cbox */
(FT_Renderer_SetModeFunc) ft_smooth_set_mode, /* set_mode */
- (FT_Raster_Funcs*)&FT_GRAYS_RASTER_GET /* raster_class */
+ (FT_Raster_Funcs*)&ft_grays_raster /* raster_class */
)
@@ -430,7 +469,7 @@
(FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox, /* get_glyph_cbox */
(FT_Renderer_SetModeFunc) ft_smooth_set_mode, /* set_mode */
- (FT_Raster_Funcs*)&FT_GRAYS_RASTER_GET /* raster_class */
+ (FT_Raster_Funcs*)&ft_grays_raster /* raster_class */
)
@@ -457,7 +496,7 @@
(FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox, /* get_glyph_cbox */
(FT_Renderer_SetModeFunc) ft_smooth_set_mode, /* set_mode */
- (FT_Raster_Funcs*)&FT_GRAYS_RASTER_GET /* raster_class */
+ (FT_Raster_Funcs*)&ft_grays_raster /* raster_class */
)
diff --git a/thirdparty/freetype/src/smooth/ftsmooth.h b/thirdparty/freetype/src/smooth/ftsmooth.h
index c76ffc5034..fbb21a31d0 100644
--- a/thirdparty/freetype/src/smooth/ftsmooth.h
+++ b/thirdparty/freetype/src/smooth/ftsmooth.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ftsmooth.h */
-/* */
-/* Anti-aliasing renderer interface (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftsmooth.h
+ *
+ * Anti-aliasing renderer interface (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef FTSMOOTH_H_
diff --git a/thirdparty/freetype/src/smooth/ftspic.c b/thirdparty/freetype/src/smooth/ftspic.c
deleted file mode 100644
index 10f04cf4cc..0000000000
--- a/thirdparty/freetype/src/smooth/ftspic.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/***************************************************************************/
-/* */
-/* ftspic.c */
-/* */
-/* The FreeType position independent code services for smooth module. */
-/* */
-/* Copyright 2009-2018 by */
-/* Oran Agra and Mickey Gabel. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#include <ft2build.h>
-#include FT_FREETYPE_H
-#include FT_INTERNAL_OBJECTS_H
-#include "ftspic.h"
-#include "ftsmerrs.h"
-
-
-#ifdef FT_CONFIG_OPTION_PIC
-
- /* forward declaration of PIC init functions from ftgrays.c */
- void
- FT_Init_Class_ft_grays_raster( FT_Raster_Funcs* funcs );
-
-
- void
- ft_smooth_renderer_class_pic_free( FT_Library library )
- {
- FT_PIC_Container* pic_container = &library->pic_container;
- FT_Memory memory = library->memory;
-
-
- if ( pic_container->smooth )
- {
- SmoothPIC* container = (SmoothPIC*)pic_container->smooth;
-
-
- if ( --container->ref_count )
- return;
-
- FT_FREE( container );
- pic_container->smooth = NULL;
- }
- }
-
-
- FT_Error
- ft_smooth_renderer_class_pic_init( FT_Library library )
- {
- FT_PIC_Container* pic_container = &library->pic_container;
- FT_Error error = FT_Err_Ok;
- SmoothPIC* container = NULL;
- FT_Memory memory = library->memory;
-
-
- /* since this function also serve smooth_lcd and smooth_lcdv renderers,
- it implements reference counting */
- if ( pic_container->smooth )
- {
- ((SmoothPIC*)pic_container->smooth)->ref_count++;
- return error;
- }
-
- /* allocate pointer, clear and set global container pointer */
- if ( FT_ALLOC( container, sizeof ( *container ) ) )
- return error;
- FT_MEM_SET( container, 0, sizeof ( *container ) );
- pic_container->smooth = container;
-
- container->ref_count = 1;
-
- /* initialize pointer table - */
- /* this is how the module usually expects this data */
- FT_Init_Class_ft_grays_raster( &container->ft_grays_raster );
-
- return error;
- }
-
-
- /* re-route these init and free functions to the above functions */
- FT_Error
- ft_smooth_lcd_renderer_class_pic_init( FT_Library library )
- {
- return ft_smooth_renderer_class_pic_init( library );
- }
-
-
- void
- ft_smooth_lcd_renderer_class_pic_free( FT_Library library )
- {
- ft_smooth_renderer_class_pic_free( library );
- }
-
-
- FT_Error
- ft_smooth_lcdv_renderer_class_pic_init( FT_Library library )
- {
- return ft_smooth_renderer_class_pic_init( library );
- }
-
-
- void
- ft_smooth_lcdv_renderer_class_pic_free( FT_Library library )
- {
- ft_smooth_renderer_class_pic_free( library );
- }
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
-
-/* END */
diff --git a/thirdparty/freetype/src/smooth/ftspic.h b/thirdparty/freetype/src/smooth/ftspic.h
deleted file mode 100644
index 80fb64cff4..0000000000
--- a/thirdparty/freetype/src/smooth/ftspic.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/***************************************************************************/
-/* */
-/* ftspic.h */
-/* */
-/* The FreeType position independent code services for smooth module. */
-/* */
-/* Copyright 2009-2018 by */
-/* Oran Agra and Mickey Gabel. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#ifndef FTSPIC_H_
-#define FTSPIC_H_
-
-
-#include FT_INTERNAL_PIC_H
-
-
-FT_BEGIN_HEADER
-
-#ifndef FT_CONFIG_OPTION_PIC
-
-#define FT_GRAYS_RASTER_GET ft_grays_raster
-
-#else /* FT_CONFIG_OPTION_PIC */
-
- typedef struct SmoothPIC_
- {
- int ref_count;
- FT_Raster_Funcs ft_grays_raster;
-
- } SmoothPIC;
-
-
-#define GET_PIC( lib ) \
- ( (SmoothPIC*)( (lib)->pic_container.smooth ) )
-#define FT_GRAYS_RASTER_GET ( GET_PIC( library )->ft_grays_raster )
-
-
- /* see ftspic.c for the implementation */
- void
- ft_smooth_renderer_class_pic_free( FT_Library library );
-
- void
- ft_smooth_lcd_renderer_class_pic_free( FT_Library library );
-
- void
- ft_smooth_lcdv_renderer_class_pic_free( FT_Library library );
-
- FT_Error
- ft_smooth_renderer_class_pic_init( FT_Library library );
-
- FT_Error
- ft_smooth_lcd_renderer_class_pic_init( FT_Library library );
-
- FT_Error
- ft_smooth_lcdv_renderer_class_pic_init( FT_Library library );
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
- /* */
-
-FT_END_HEADER
-
-#endif /* FTSPIC_H_ */
-
-
-/* END */
diff --git a/thirdparty/freetype/src/smooth/module.mk b/thirdparty/freetype/src/smooth/module.mk
index 5b8bc3be3b..44b76dfec6 100644
--- a/thirdparty/freetype/src/smooth/module.mk
+++ b/thirdparty/freetype/src/smooth/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2018 by
+# Copyright (C) 1996-2019 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/smooth/rules.mk b/thirdparty/freetype/src/smooth/rules.mk
index f30824a367..0153ac24a4 100644
--- a/thirdparty/freetype/src/smooth/rules.mk
+++ b/thirdparty/freetype/src/smooth/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2018 by
+# Copyright (C) 1996-2019 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
@@ -29,8 +29,7 @@ SMOOTH_COMPILE := $(CC) $(ANSIFLAGS) \
# smooth driver sources (i.e., C files)
#
SMOOTH_DRV_SRC := $(SMOOTH_DIR)/ftgrays.c \
- $(SMOOTH_DIR)/ftsmooth.c \
- $(SMOOTH_DIR)/ftspic.c
+ $(SMOOTH_DIR)/ftsmooth.c
# smooth driver headers
diff --git a/thirdparty/freetype/src/smooth/smooth.c b/thirdparty/freetype/src/smooth/smooth.c
index 5249a8931e..9c543d3360 100644
--- a/thirdparty/freetype/src/smooth/smooth.c
+++ b/thirdparty/freetype/src/smooth/smooth.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* smooth.c */
-/* */
-/* FreeType anti-aliasing rasterer module component (body only). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * smooth.c
+ *
+ * FreeType anti-aliasing rasterer module component (body only).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#define FT_MAKE_OPTION_SINGLE_OBJECT
@@ -21,7 +21,6 @@
#include "ftgrays.c"
#include "ftsmooth.c"
-#include "ftspic.c"
/* END */
diff --git a/thirdparty/freetype/src/truetype/module.mk b/thirdparty/freetype/src/truetype/module.mk
index 16bc9c8b20..8a841cc956 100644
--- a/thirdparty/freetype/src/truetype/module.mk
+++ b/thirdparty/freetype/src/truetype/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2018 by
+# Copyright (C) 1996-2019 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/truetype/rules.mk b/thirdparty/freetype/src/truetype/rules.mk
index e16113f128..df8dcd4a4e 100644
--- a/thirdparty/freetype/src/truetype/rules.mk
+++ b/thirdparty/freetype/src/truetype/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2018 by
+# Copyright (C) 1996-2019 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
@@ -33,7 +33,6 @@ TT_DRV_SRC := $(TT_DIR)/ttdriver.c \
$(TT_DIR)/ttgxvar.c \
$(TT_DIR)/ttinterp.c \
$(TT_DIR)/ttobjs.c \
- $(TT_DIR)/ttpic.c \
$(TT_DIR)/ttpload.c \
$(TT_DIR)/ttsubpix.c
diff --git a/thirdparty/freetype/src/truetype/truetype.c b/thirdparty/freetype/src/truetype/truetype.c
index 484370975c..84928e7321 100644
--- a/thirdparty/freetype/src/truetype/truetype.c
+++ b/thirdparty/freetype/src/truetype/truetype.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* truetype.c */
-/* */
-/* FreeType TrueType driver component (body only). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * truetype.c
+ *
+ * FreeType TrueType driver component (body only).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#define FT_MAKE_OPTION_SINGLE_OBJECT
@@ -24,7 +24,6 @@
#include "ttgxvar.c" /* gx distortable font */
#include "ttinterp.c"
#include "ttobjs.c" /* object manager */
-#include "ttpic.c"
#include "ttpload.c" /* tables loader */
#include "ttsubpix.c"
diff --git a/thirdparty/freetype/src/truetype/ttdriver.c b/thirdparty/freetype/src/truetype/ttdriver.c
index 820cafbb8d..ff626d53ab 100644
--- a/thirdparty/freetype/src/truetype/ttdriver.c
+++ b/thirdparty/freetype/src/truetype/ttdriver.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ttdriver.c */
-/* */
-/* TrueType font driver implementation (body). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ttdriver.c
+ *
+ * TrueType font driver implementation (body).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -43,20 +43,19 @@
#include "tterrors.h"
-#include "ttpic.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_ttdriver
+#define FT_COMPONENT ttdriver
/*
- * PROPERTY SERVICE
+ * PROPERTY SERVICE
*
*/
static FT_Error
@@ -164,38 +163,42 @@
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_get_kerning */
- /* */
- /* <Description> */
- /* A driver method used to return the kerning vector between two */
- /* glyphs of the same face. */
- /* */
- /* <Input> */
- /* face :: A handle to the source face object. */
- /* */
- /* left_glyph :: The index of the left glyph in the kern pair. */
- /* */
- /* right_glyph :: The index of the right glyph in the kern pair. */
- /* */
- /* <Output> */
- /* kerning :: The kerning vector. This is in font units for */
- /* scalable formats, and in pixels for fixed-sizes */
- /* formats. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- /* <Note> */
- /* Only horizontal layouts (left-to-right & right-to-left) are */
- /* supported by this function. Other layouts, or more sophisticated */
- /* kernings, are out of scope of this method (the basic driver */
- /* interface is meant to be simple). */
- /* */
- /* They can be implemented by format-specific interfaces. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_get_kerning
+ *
+ * @Description:
+ * A driver method used to return the kerning vector between two
+ * glyphs of the same face.
+ *
+ * @Input:
+ * face ::
+ * A handle to the source face object.
+ *
+ * left_glyph ::
+ * The index of the left glyph in the kern pair.
+ *
+ * right_glyph ::
+ * The index of the right glyph in the kern pair.
+ *
+ * @Output:
+ * kerning ::
+ * The kerning vector. This is in font units for
+ * scalable formats, and in pixels for fixed-sizes
+ * formats.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ *
+ * @Note:
+ * Only horizontal layouts (left-to-right & right-to-left) are
+ * supported by this function. Other layouts, or more sophisticated
+ * kernings, are out of scope of this method (the basic driver
+ * interface is meant to be simple).
+ *
+ * They can be implemented by format-specific interfaces.
+ */
static FT_Error
tt_get_kerning( FT_Face ttface, /* TT_Face */
FT_UInt left_glyph,
@@ -384,32 +387,36 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_glyph_load */
- /* */
- /* <Description> */
- /* A driver method used to load a glyph within a given glyph slot. */
- /* */
- /* <Input> */
- /* slot :: A handle to the target slot object where the glyph */
- /* will be loaded. */
- /* */
- /* size :: A handle to the source face size at which the glyph */
- /* must be scaled, loaded, etc. */
- /* */
- /* glyph_index :: The index of the glyph in the font file. */
- /* */
- /* load_flags :: A flag indicating what to load for this glyph. The */
- /* FT_LOAD_XXX constants can be used to control the */
- /* glyph loading process (e.g., whether the outline */
- /* should be scaled, whether to load bitmaps or not, */
- /* whether to hint the outline, etc). */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_glyph_load
+ *
+ * @Description:
+ * A driver method used to load a glyph within a given glyph slot.
+ *
+ * @Input:
+ * slot ::
+ * A handle to the target slot object where the glyph
+ * will be loaded.
+ *
+ * size ::
+ * A handle to the source face size at which the glyph
+ * must be scaled, loaded, etc.
+ *
+ * glyph_index ::
+ * The index of the glyph in the font file.
+ *
+ * load_flags ::
+ * A flag indicating what to load for this glyph. The
+ * FT_LOAD_XXX constants can be used to control the
+ * glyph loading process (e.g., whether the outline
+ * should be scaled, whether to load bitmaps or not,
+ * whether to hint the outline, etc).
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
static FT_Error
tt_glyph_load( FT_GlyphSlot ttslot, /* TT_GlyphSlot */
FT_Size ttsize, /* TT_Size */
@@ -464,7 +471,7 @@
? &ttsize->metrics
: &size->hinted_metrics;
- /* now load the glyph outline if necessary */
+ /* now fill in the glyph slot with outline/bitmap/layered */
error = TT_Load_Glyph( size, slot, glyph_index, load_flags );
/* force drop-out mode to 2 - irrelevant now */
@@ -491,17 +498,19 @@
FT_DEFINE_SERVICE_MULTIMASTERSREC(
tt_service_gx_multi_masters,
- (FT_Get_MM_Func) NULL, /* get_mm */
- (FT_Set_MM_Design_Func) NULL, /* set_mm_design */
- (FT_Set_MM_Blend_Func) TT_Set_MM_Blend, /* set_mm_blend */
- (FT_Get_MM_Blend_Func) TT_Get_MM_Blend, /* get_mm_blend */
- (FT_Get_MM_Var_Func) TT_Get_MM_Var, /* get_mm_var */
- (FT_Set_Var_Design_Func)TT_Set_Var_Design, /* set_var_design */
- (FT_Get_Var_Design_Func)TT_Get_Var_Design, /* get_var_design */
- (FT_Set_Instance_Func) TT_Set_Named_Instance, /* set_instance */
-
- (FT_Get_Var_Blend_Func) tt_get_var_blend, /* get_var_blend */
- (FT_Done_Blend_Func) tt_done_blend /* done_blend */
+ (FT_Get_MM_Func) NULL, /* get_mm */
+ (FT_Set_MM_Design_Func) NULL, /* set_mm_design */
+ (FT_Set_MM_Blend_Func) TT_Set_MM_Blend, /* set_mm_blend */
+ (FT_Get_MM_Blend_Func) TT_Get_MM_Blend, /* get_mm_blend */
+ (FT_Get_MM_Var_Func) TT_Get_MM_Var, /* get_mm_var */
+ (FT_Set_Var_Design_Func) TT_Set_Var_Design, /* set_var_design */
+ (FT_Get_Var_Design_Func) TT_Get_Var_Design, /* get_var_design */
+ (FT_Set_Instance_Func) TT_Set_Named_Instance, /* set_instance */
+ (FT_Set_MM_WeightVector_Func)NULL, /* set_mm_weightvector */
+ (FT_Get_MM_WeightVector_Func)NULL, /* get_mm_weightvector */
+
+ (FT_Get_Var_Blend_Func) tt_get_var_blend, /* get_var_blend */
+ (FT_Done_Blend_Func) tt_done_blend /* done_blend */
)
FT_DEFINE_SERVICE_METRICSVARIATIONSREC(
@@ -548,19 +557,19 @@
tt_services,
FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_TRUETYPE,
- FT_SERVICE_ID_MULTI_MASTERS, &TT_SERVICE_GX_MULTI_MASTERS_GET,
- FT_SERVICE_ID_METRICS_VARIATIONS, &TT_SERVICE_METRICS_VARIATIONS_GET,
+ FT_SERVICE_ID_MULTI_MASTERS, &tt_service_gx_multi_masters,
+ FT_SERVICE_ID_METRICS_VARIATIONS, &tt_service_metrics_variations,
FT_SERVICE_ID_TRUETYPE_ENGINE, &tt_service_truetype_engine,
- FT_SERVICE_ID_TT_GLYF, &TT_SERVICE_TRUETYPE_GLYF_GET,
- FT_SERVICE_ID_PROPERTIES, &TT_SERVICE_PROPERTIES_GET )
+ FT_SERVICE_ID_TT_GLYF, &tt_service_truetype_glyf,
+ FT_SERVICE_ID_PROPERTIES, &tt_service_properties )
#else
FT_DEFINE_SERVICEDESCREC4(
tt_services,
FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_TRUETYPE,
FT_SERVICE_ID_TRUETYPE_ENGINE, &tt_service_truetype_engine,
- FT_SERVICE_ID_TT_GLYF, &TT_SERVICE_TRUETYPE_GLYF_GET,
- FT_SERVICE_ID_PROPERTIES, &TT_SERVICE_PROPERTIES_GET )
+ FT_SERVICE_ID_TT_GLYF, &tt_service_truetype_glyf,
+ FT_SERVICE_ID_PROPERTIES, &tt_service_properties )
#endif
@@ -574,26 +583,15 @@
SFNT_Service sfnt;
- /* TT_SERVICES_GET dereferences `library' in PIC mode */
-#ifdef FT_CONFIG_OPTION_PIC
- if ( !driver )
- return NULL;
- library = driver->library;
- if ( !library )
- return NULL;
-#endif
-
- result = ft_service_list_lookup( TT_SERVICES_GET, tt_interface );
+ result = ft_service_list_lookup( tt_services, tt_interface );
if ( result )
return result;
-#ifndef FT_CONFIG_OPTION_PIC
if ( !driver )
return NULL;
library = driver->library;
if ( !library )
return NULL;
-#endif
/* only return the default interface from the SFNT module */
sfntd = FT_Get_Module( library, "sfnt" );
diff --git a/thirdparty/freetype/src/truetype/ttdriver.h b/thirdparty/freetype/src/truetype/ttdriver.h
index 707aa68edf..3936c6a4de 100644
--- a/thirdparty/freetype/src/truetype/ttdriver.h
+++ b/thirdparty/freetype/src/truetype/ttdriver.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ttdriver.h */
-/* */
-/* High-level TrueType driver interface (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ttdriver.h
+ *
+ * High-level TrueType driver interface (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef TTDRIVER_H_
@@ -26,10 +26,8 @@
FT_BEGIN_HEADER
-
FT_DECLARE_DRIVER( tt_driver_class )
-
FT_END_HEADER
#endif /* TTDRIVER_H_ */
diff --git a/thirdparty/freetype/src/truetype/tterrors.h b/thirdparty/freetype/src/truetype/tterrors.h
index 88bca3a04a..5609d28d68 100644
--- a/thirdparty/freetype/src/truetype/tterrors.h
+++ b/thirdparty/freetype/src/truetype/tterrors.h
@@ -1,27 +1,27 @@
-/***************************************************************************/
-/* */
-/* tterrors.h */
-/* */
-/* TrueType error codes (specification only). */
-/* */
-/* Copyright 2001-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* This file is used to define the TrueType error enumeration */
- /* constants. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * tterrors.h
+ *
+ * TrueType error codes (specification only).
+ *
+ * Copyright (C) 2001-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * This file is used to define the TrueType error enumeration
+ * constants.
+ *
+ */
#ifndef TTERRORS_H_
#define TTERRORS_H_
diff --git a/thirdparty/freetype/src/truetype/ttgload.c b/thirdparty/freetype/src/truetype/ttgload.c
index 39d9c3f736..cbee27aa69 100644
--- a/thirdparty/freetype/src/truetype/ttgload.c
+++ b/thirdparty/freetype/src/truetype/ttgload.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ttgload.c */
-/* */
-/* TrueType Glyph Loader (body). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ttgload.c
+ *
+ * TrueType Glyph Loader (body).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -38,20 +38,35 @@
#include "ttsubpix.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_ttgload
+#define FT_COMPONENT ttgload
- /*************************************************************************/
- /* */
- /* Composite glyph flags. */
- /* */
+ /**************************************************************************
+ *
+ * Simple glyph flags.
+ */
+#define ON_CURVE_POINT 0x01 /* same value as FT_CURVE_TAG_ON */
+#define X_SHORT_VECTOR 0x02
+#define Y_SHORT_VECTOR 0x04
+#define REPEAT_FLAG 0x08
+#define X_POSITIVE 0x10 /* two meanings depending on X_SHORT_VECTOR */
+#define SAME_X 0x10
+#define Y_POSITIVE 0x20 /* two meanings depending on Y_SHORT_VECTOR */
+#define SAME_Y 0x20
+#define OVERLAP_SIMPLE 0x40 /* we ignore this value */
+
+
+ /**************************************************************************
+ *
+ * Composite glyph flags.
+ */
#define ARGS_ARE_WORDS 0x0001
#define ARGS_ARE_XY_VALUES 0x0002
#define ROUND_XY_TO_GRID 0x0004
@@ -62,15 +77,15 @@
#define WE_HAVE_A_2X2 0x0080
#define WE_HAVE_INSTR 0x0100
#define USE_MY_METRICS 0x0200
-#define OVERLAP_COMPOUND 0x0400
+#define OVERLAP_COMPOUND 0x0400 /* we ignore this value */
#define SCALED_COMPONENT_OFFSET 0x0800
#define UNSCALED_COMPONENT_OFFSET 0x1000
- /*************************************************************************/
- /* */
- /* Return the horizontal metrics in font units for a given glyph. */
- /* */
+ /**************************************************************************
+ *
+ * Return the horizontal metrics in font units for a given glyph.
+ */
FT_LOCAL_DEF( void )
TT_Get_HMetrics( TT_Face face,
FT_UInt idx,
@@ -84,11 +99,11 @@
}
- /*************************************************************************/
- /* */
- /* Return the vertical metrics in font units for a given glyph. */
- /* See function `tt_loader_set_pp' below for explanations. */
- /* */
+ /**************************************************************************
+ *
+ * Return the vertical metrics in font units for a given glyph.
+ * See function `tt_loader_set_pp' below for explanations.
+ */
FT_LOCAL_DEF( void )
TT_Get_VMetrics( TT_Face face,
FT_UInt idx,
@@ -250,13 +265,13 @@
#endif /* FT_CONFIG_OPTION_INCREMENTAL */
- /*************************************************************************/
- /* */
- /* The following functions are used by default with TrueType fonts. */
- /* However, they can be replaced by alternatives if we need to support */
- /* TrueType-compressed formats (like MicroType) in the future. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * The following functions are used by default with TrueType fonts.
+ * However, they can be replaced by alternatives if we need to support
+ * TrueType-compressed formats (like MicroType) in the future.
+ *
+ */
FT_CALLBACK_DEF( FT_Error )
TT_Access_Glyph_Frame( TT_Loader loader,
@@ -267,12 +282,9 @@
FT_Error error;
FT_Stream stream = loader->stream;
- /* for non-debug mode */
FT_UNUSED( glyph_index );
- FT_TRACE4(( "Glyph %ld\n", glyph_index ));
-
/* the following line sets the `error' variable through macros! */
if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( byte_count ) )
return error;
@@ -337,7 +349,7 @@
FT_Byte *flag, *flag_limit;
FT_Byte c, count;
FT_Vector *vec, *vec_limit;
- FT_Pos x;
+ FT_Pos x, y;
FT_Short *cont, *cont_limit, prev_cont;
FT_Int xy_size = 0;
@@ -382,6 +394,8 @@
goto Invalid_Outline;
}
+ FT_TRACE5(( " # of points: %d\n", n_points ));
+
/* note that we will add four phantom points later */
error = FT_GLYPHLOADER_CHECK_POINTS( gloader, n_points + 4, 0 );
if ( error )
@@ -452,7 +466,7 @@
goto Invalid_Outline;
*flag++ = c = FT_NEXT_BYTE( p );
- if ( c & 8 )
+ if ( c & REPEAT_FLAG )
{
if ( p + 1 > limit )
goto Invalid_Outline;
@@ -478,31 +492,29 @@
for ( ; vec < vec_limit; vec++, flag++ )
{
- FT_Pos y = 0;
- FT_Byte f = *flag;
+ FT_Pos delta = 0;
+ FT_Byte f = *flag;
- if ( f & 2 )
+ if ( f & X_SHORT_VECTOR )
{
if ( p + 1 > limit )
goto Invalid_Outline;
- y = (FT_Pos)FT_NEXT_BYTE( p );
- if ( ( f & 16 ) == 0 )
- y = -y;
+ delta = (FT_Pos)FT_NEXT_BYTE( p );
+ if ( !( f & X_POSITIVE ) )
+ delta = -delta;
}
- else if ( ( f & 16 ) == 0 )
+ else if ( !( f & SAME_X ) )
{
if ( p + 2 > limit )
goto Invalid_Outline;
- y = (FT_Pos)FT_NEXT_SHORT( p );
+ delta = (FT_Pos)FT_NEXT_SHORT( p );
}
- x += y;
+ x += delta;
vec->x = x;
- /* the cast is for stupid compilers */
- *flag = (FT_Byte)( f & ~( 2 | 16 ) );
}
/* reading the Y coordinates */
@@ -510,35 +522,36 @@
vec = gloader->current.outline.points;
vec_limit = vec + n_points;
flag = (FT_Byte*)outline->tags;
- x = 0;
+ y = 0;
for ( ; vec < vec_limit; vec++, flag++ )
{
- FT_Pos y = 0;
- FT_Byte f = *flag;
+ FT_Pos delta = 0;
+ FT_Byte f = *flag;
- if ( f & 4 )
+ if ( f & Y_SHORT_VECTOR )
{
if ( p + 1 > limit )
goto Invalid_Outline;
- y = (FT_Pos)FT_NEXT_BYTE( p );
- if ( ( f & 32 ) == 0 )
- y = -y;
+ delta = (FT_Pos)FT_NEXT_BYTE( p );
+ if ( !( f & Y_POSITIVE ) )
+ delta = -delta;
}
- else if ( ( f & 32 ) == 0 )
+ else if ( !( f & SAME_Y ) )
{
if ( p + 2 > limit )
goto Invalid_Outline;
- y = (FT_Pos)FT_NEXT_SHORT( p );
+ delta = (FT_Pos)FT_NEXT_SHORT( p );
}
- x += y;
- vec->y = x;
+ y += delta;
+ vec->y = y;
+
/* the cast is for stupid compilers */
- *flag = (FT_Byte)( f & FT_CURVE_TAG_ON );
+ *flag = (FT_Byte)( f & ON_CURVE_POINT );
}
outline->n_points = (FT_Short)n_points;
@@ -559,9 +572,10 @@
TT_Load_Composite_Glyph( TT_Loader loader )
{
FT_Error error;
- FT_Byte* p = loader->cursor;
- FT_Byte* limit = loader->limit;
- FT_GlyphLoader gloader = loader->gloader;
+ FT_Byte* p = loader->cursor;
+ FT_Byte* limit = loader->limit;
+ FT_GlyphLoader gloader = loader->gloader;
+ FT_Long num_glyphs = loader->face->root.num_glyphs;
FT_SubGlyph subglyph;
FT_UInt num_subglyphs;
@@ -590,6 +604,11 @@
subglyph->flags = FT_NEXT_USHORT( p );
subglyph->index = FT_NEXT_USHORT( p );
+ /* we reject composites that have components */
+ /* with invalid glyph indices */
+ if ( subglyph->index >= num_glyphs )
+ goto Invalid_Composite;
+
/* check space */
count = 2;
if ( subglyph->flags & ARGS_ARE_WORDS )
@@ -768,15 +787,15 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* TT_Hint_Glyph */
- /* */
- /* <Description> */
- /* Hint the glyph using the zone prepared by the caller. Note that */
- /* the zone is supposed to include four phantom points. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * TT_Hint_Glyph
+ *
+ * @Description:
+ * Hint the glyph using the zone prepared by the caller. Note that
+ * the zone is supposed to include four phantom points.
+ */
static FT_Error
TT_Hint_Glyph( TT_Loader loader,
FT_Bool is_composite )
@@ -797,15 +816,9 @@
#ifdef TT_USE_BYTECODE_INTERPRETER
- if ( loader->glyph->control_len > 0xFFFFL )
- {
- FT_TRACE1(( "TT_Hint_Glyph: too long instructions" ));
- FT_TRACE1(( " (0x%lx byte) is truncated\n",
- loader->glyph->control_len ));
- }
n_ins = loader->glyph->control_len;
- /* save original point position in org */
+ /* save original point positions in `org' array */
if ( n_ins > 0 )
FT_ARRAY_COPY( zone->org, zone->cur, zone->n_points );
@@ -896,16 +909,16 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* TT_Process_Simple_Glyph */
- /* */
- /* <Description> */
- /* Once a simple glyph has been loaded, it needs to be processed. */
- /* Usually, this means scaling and hinting through bytecode */
- /* interpretation. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * TT_Process_Simple_Glyph
+ *
+ * @Description:
+ * Once a simple glyph has been loaded, it needs to be processed.
+ * Usually, this means scaling and hinting through bytecode
+ * interpretation.
+ */
static FT_Error
TT_Process_Simple_Glyph( TT_Loader loader )
{
@@ -1071,15 +1084,15 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* TT_Process_Composite_Component */
- /* */
- /* <Description> */
- /* Once a composite component has been loaded, it needs to be */
- /* processed. Usually, this means transforming and translating. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * TT_Process_Composite_Component
+ *
+ * @Description:
+ * Once a composite component has been loaded, it needs to be
+ * processed. Usually, this means transforming and translating.
+ */
static FT_Error
TT_Process_Composite_Component( TT_Loader loader,
FT_SubGlyph subglyph,
@@ -1153,10 +1166,10 @@
#if 0
- /*******************************************************************/
- /* */
- /* This algorithm is what Apple documents. But it doesn't work. */
- /* */
+ /********************************************************************
+ *
+ * This algorithm is what Apple documents. But it doesn't work.
+ */
int a = subglyph->transform.xx > 0 ? subglyph->transform.xx
: -subglyph->transform.xx;
int b = subglyph->transform.yx > 0 ? subglyph->transform.yx
@@ -1178,10 +1191,10 @@
#else /* 1 */
- /*******************************************************************/
- /* */
- /* This algorithm is a guess and works much better than the above. */
- /* */
+ /********************************************************************
+ *
+ * This algorithm is a guess and works much better than the above.
+ */
FT_Fixed mac_xscale = FT_Hypot( subglyph->transform.xx,
subglyph->transform.xy );
FT_Fixed mac_yscale = FT_Hypot( subglyph->transform.yy,
@@ -1239,16 +1252,16 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* TT_Process_Composite_Glyph */
- /* */
- /* <Description> */
- /* This is slightly different from TT_Process_Simple_Glyph, in that */
- /* its sole purpose is to hint the glyph. Thus this function is */
- /* only available when bytecode interpreter is enabled. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * TT_Process_Composite_Glyph
+ *
+ * @Description:
+ * This is slightly different from TT_Process_Simple_Glyph, in that
+ * its sole purpose is to hint the glyph. Thus this function is
+ * only available when bytecode interpreter is enabled.
+ */
static FT_Error
TT_Process_Composite_Glyph( TT_Loader loader,
FT_UInt start_point,
@@ -1460,7 +1473,7 @@
}
#endif
- use_aw_2 = (FT_Bool)( subpixel_hinting && grayscale );
+ use_aw_2 = FT_BOOL( subpixel_hinting && grayscale );
loader->pp1.x = loader->bbox.xMin - loader->left_bearing;
loader->pp1.y = 0;
@@ -1497,27 +1510,28 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* load_truetype_glyph */
- /* */
- /* <Description> */
- /* Loads a given truetype glyph. Handles composites and uses a */
- /* TT_Loader object. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * load_truetype_glyph
+ *
+ * @Description:
+ * Loads a given truetype glyph. Handles composites and uses a
+ * TT_Loader object.
+ */
static FT_Error
load_truetype_glyph( TT_Loader loader,
FT_UInt glyph_index,
FT_UInt recurse_count,
FT_Bool header_only )
{
- FT_Error error = FT_Err_Ok;
+ FT_Error error = FT_Err_Ok;
FT_Fixed x_scale, y_scale;
FT_ULong offset;
- TT_Face face = loader->face;
- FT_GlyphLoader gloader = loader->gloader;
- FT_Bool opened_frame = 0;
+ TT_Face face = loader->face;
+ FT_GlyphLoader gloader = loader->gloader;
+
+ FT_Bool opened_frame = 0;
#ifdef FT_CONFIG_OPTION_INCREMENTAL
FT_StreamRec inc_stream;
@@ -1550,15 +1564,15 @@
loader->glyph_index = glyph_index;
- if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
+ if ( loader->load_flags & FT_LOAD_NO_SCALE )
{
- x_scale = loader->size->metrics->x_scale;
- y_scale = loader->size->metrics->y_scale;
+ x_scale = 0x10000L;
+ y_scale = 0x10000L;
}
else
{
- x_scale = 0x10000L;
- y_scale = 0x10000L;
+ x_scale = loader->size->metrics->x_scale;
+ y_scale = loader->size->metrics->y_scale;
}
/* Set `offset' to the start of the glyph relative to the start of */
@@ -1617,38 +1631,36 @@
if ( error )
goto Exit;
- opened_frame = 1;
-
/* read glyph header first */
error = face->read_glyph_header( loader );
- if ( error )
- goto Exit;
- /* the metrics must be computed after loading the glyph header */
- /* since we need the glyph's `yMax' value in case the vertical */
- /* metrics must be emulated */
- error = tt_get_metrics( loader, glyph_index );
- if ( error )
- goto Exit;
+ face->forget_glyph_frame( loader );
- if ( header_only )
+ if ( error )
goto Exit;
}
+ /* a space glyph */
if ( loader->byte_len == 0 || loader->n_contours == 0 )
{
loader->bbox.xMin = 0;
loader->bbox.xMax = 0;
loader->bbox.yMin = 0;
loader->bbox.yMax = 0;
+ }
- error = tt_get_metrics( loader, glyph_index );
- if ( error )
- goto Exit;
+ /* the metrics must be computed after loading the glyph header */
+ /* since we need the glyph's `yMax' value in case the vertical */
+ /* metrics must be emulated */
+ error = tt_get_metrics( loader, glyph_index );
+ if ( error )
+ goto Exit;
- if ( header_only )
- goto Exit;
+ if ( header_only )
+ goto Exit;
+ if ( loader->byte_len == 0 || loader->n_contours == 0 )
+ {
/* must initialize points before (possibly) overriding */
/* glyph metrics from the incremental interface */
tt_loader_set_pp( loader );
@@ -1704,7 +1716,6 @@
loader->pp4.x = points[3].x;
loader->pp4.y = points[3].y;
-
/* recalculate linear horizontal and vertical advances */
/* if we don't have HVAR and VVAR, respectively */
if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) )
@@ -1745,6 +1756,16 @@
/***********************************************************************/
/***********************************************************************/
+ /* we now open a frame again, right after the glyph header */
+ /* (which consists of 10 bytes) */
+ error = face->access_glyph_frame( loader, glyph_index,
+ face->glyf_offset + offset + 10,
+ (FT_UInt)loader->byte_len - 10 );
+ if ( error )
+ goto Exit;
+
+ opened_frame = 1;
+
/* if it is a simple glyph, load it */
if ( loader->n_contours > 0 )
@@ -1790,7 +1811,6 @@
* pointers with a width of at least 32 bits.
*/
-
/* clear the nodes filled by sibling chains */
node = ft_list_get_node_at( &loader->composites, recurse_count );
for ( node2 = node; node2; node2 = node2->next )
@@ -2002,7 +2022,7 @@
FT_Int linear_vadvance;
- /* Each time we call load_truetype_glyph in this loop, the */
+ /* Each time we call `load_truetype_glyph' in this loop, the */
/* value of `gloader.base.subglyphs' can change due to table */
/* reallocations. We thus need to recompute the subglyph */
/* pointer on each iteration. */
@@ -2045,12 +2065,14 @@
if ( num_points == num_base_points )
continue;
- /* gloader->base.outline consists of three parts: */
- /* 0 -(1)-> start_point -(2)-> num_base_points -(3)-> n_points. */
- /* */
- /* (1): exists from the beginning */
- /* (2): components that have been loaded so far */
- /* (3): the newly loaded component */
+ /* gloader->base.outline consists of three parts: */
+ /* */
+ /* 0 ----> start_point ----> num_base_points ----> n_points */
+ /* (1) (2) (3) */
+ /* */
+ /* (1) points that exist from the beginning */
+ /* (2) component points that have been loaded so far */
+ /* (3) points of the newly loaded component */
error = TT_Process_Composite_Component( loader,
subglyph,
start_point,
@@ -2132,7 +2154,7 @@
glyph->metrics.horiBearingX = bbox.xMin;
glyph->metrics.horiBearingY = bbox.yMax;
- glyph->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
+ glyph->metrics.horiAdvance = SUB_LONG(loader->pp2.x, loader->pp1.x);
/* Adjust advance width to the value contained in the hdmx table */
/* unless FT_LOAD_COMPUTE_METRICS is set or backward compatibility */
@@ -2276,13 +2298,13 @@
/* XXX: for now, we have no better algorithm for the lsb, but it */
/* should work fine. */
/* */
- glyph->metrics.vertBearingX = glyph->metrics.horiBearingX -
- glyph->metrics.horiAdvance / 2;
+ glyph->metrics.vertBearingX = SUB_LONG( glyph->metrics.horiBearingX,
+ glyph->metrics.horiAdvance / 2 );
glyph->metrics.vertBearingY = top;
glyph->metrics.vertAdvance = advance;
}
- return 0;
+ return FT_Err_Ok;
}
@@ -2656,33 +2678,37 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* TT_Load_Glyph */
- /* */
- /* <Description> */
- /* A function used to load a single glyph within a given glyph slot, */
- /* for a given size. */
- /* */
- /* <Input> */
- /* glyph :: A handle to a target slot object where the glyph */
- /* will be loaded. */
- /* */
- /* size :: A handle to the source face size at which the glyph */
- /* must be scaled/loaded. */
- /* */
- /* glyph_index :: The index of the glyph in the font file. */
- /* */
- /* load_flags :: A flag indicating what to load for this glyph. The */
- /* FT_LOAD_XXX constants can be used to control the */
- /* glyph loading process (e.g., whether the outline */
- /* should be scaled, whether to load bitmaps or not, */
- /* whether to hint the outline, etc). */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * TT_Load_Glyph
+ *
+ * @Description:
+ * A function used to load a single glyph within a given glyph slot,
+ * for a given size.
+ *
+ * @Input:
+ * glyph ::
+ * A handle to a target slot object where the glyph
+ * will be loaded.
+ *
+ * size ::
+ * A handle to the source face size at which the glyph
+ * must be scaled/loaded.
+ *
+ * glyph_index ::
+ * The index of the glyph in the font file.
+ *
+ * load_flags ::
+ * A flag indicating what to load for this glyph. The
+ * FT_LOAD_XXX constants can be used to control the
+ * glyph loading process (e.g., whether the outline
+ * should be scaled, whether to load bitmaps or not,
+ * whether to hint the outline, etc).
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
TT_Load_Glyph( TT_Size size,
TT_GlyphSlot glyph,
diff --git a/thirdparty/freetype/src/truetype/ttgload.h b/thirdparty/freetype/src/truetype/ttgload.h
index d237cfd284..f1324bc862 100644
--- a/thirdparty/freetype/src/truetype/ttgload.h
+++ b/thirdparty/freetype/src/truetype/ttgload.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ttgload.h */
-/* */
-/* TrueType Glyph Loader (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ttgload.h
+ *
+ * TrueType Glyph Loader (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef TTGLOAD_H_
diff --git a/thirdparty/freetype/src/truetype/ttgxvar.c b/thirdparty/freetype/src/truetype/ttgxvar.c
index 29ab2a4efd..020918f533 100644
--- a/thirdparty/freetype/src/truetype/ttgxvar.c
+++ b/thirdparty/freetype/src/truetype/ttgxvar.c
@@ -1,42 +1,42 @@
-/***************************************************************************/
-/* */
-/* ttgxvar.c */
-/* */
-/* TrueType GX Font Variation loader */
-/* */
-/* Copyright 2004-2018 by */
-/* David Turner, Robert Wilhelm, Werner Lemberg, and George Williams. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* Apple documents the `fvar', `gvar', `cvar', and `avar' tables at */
- /* */
- /* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6[fgca]var.html */
- /* */
- /* The documentation for `gvar' is not intelligible; `cvar' refers you */
- /* to `gvar' and is thus also incomprehensible. */
- /* */
- /* The documentation for `avar' appears correct, but Apple has no fonts */
- /* with an `avar' table, so it is hard to test. */
- /* */
- /* Many thanks to John Jenkins (at Apple) in figuring this out. */
- /* */
- /* */
- /* Apple's `kern' table has some references to tuple indices, but as */
- /* there is no indication where these indices are defined, nor how to */
- /* interpolate the kerning values (different tuples have different */
- /* classes) this issue is ignored. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * ttgxvar.c
+ *
+ * TrueType GX Font Variation loader
+ *
+ * Copyright (C) 2004-2019 by
+ * David Turner, Robert Wilhelm, Werner Lemberg, and George Williams.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * Apple documents the `fvar', `gvar', `cvar', and `avar' tables at
+ *
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6[fgca]var.html
+ *
+ * The documentation for `gvar' is not intelligible; `cvar' refers you
+ * to `gvar' and is thus also incomprehensible.
+ *
+ * The documentation for `avar' appears correct, but Apple has no fonts
+ * with an `avar' table, so it is hard to test.
+ *
+ * Many thanks to John Jenkins (at Apple) in figuring this out.
+ *
+ *
+ * Apple's `kern' table has some references to tuple indices, but as
+ * there is no indication where these indices are defined, nor how to
+ * interpolate the kerning values (different tuples have different
+ * classes) this issue is ignored.
+ *
+ */
#include <ft2build.h>
@@ -67,14 +67,23 @@
: (stream)->limit
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /* some macros we need */
+#define FT_fdot14ToFixed( x ) \
+ ( (FT_Fixed)( (FT_ULong)(x) << 2 ) )
+#define FT_intToFixed( i ) \
+ ( (FT_Fixed)( (FT_ULong)(i) << 16 ) )
+#define FT_fixedToInt( x ) \
+ ( (FT_Short)( ( (FT_UInt32)(x) + 0x8000U ) >> 16 ) )
+
+
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_ttgxvar
+#define FT_COMPONENT ttgxvar
/*************************************************************************/
@@ -86,12 +95,12 @@
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* The macro ALL_POINTS is used in `ft_var_readpackedpoints'. It */
- /* indicates that there is a delta for every point without needing to */
- /* enumerate all of them. */
- /* */
+ /**************************************************************************
+ *
+ * The macro ALL_POINTS is used in `ft_var_readpackedpoints'. It
+ * indicates that there is a delta for every point without needing to
+ * enumerate all of them.
+ */
/* ensure that value `0' has the same width as a pointer */
#define ALL_POINTS (FT_UShort*)~(FT_PtrDist)0
@@ -101,29 +110,32 @@
#define GX_PT_POINT_RUN_COUNT_MASK 0x7FU
- /*************************************************************************/
- /* */
- /* <Function> */
- /* ft_var_readpackedpoints */
- /* */
- /* <Description> */
- /* Read a set of points to which the following deltas will apply. */
- /* Points are packed with a run length encoding. */
- /* */
- /* <Input> */
- /* stream :: The data stream. */
- /* */
- /* size :: The size of the table holding the data. */
- /* */
- /* <Output> */
- /* point_cnt :: The number of points read. A zero value means that */
- /* all points in the glyph will be affected, without */
- /* enumerating them individually. */
- /* */
- /* <Return> */
- /* An array of FT_UShort containing the affected points or the */
- /* special value ALL_POINTS. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * ft_var_readpackedpoints
+ *
+ * @Description:
+ * Read a set of points to which the following deltas will apply.
+ * Points are packed with a run length encoding.
+ *
+ * @Input:
+ * stream ::
+ * The data stream.
+ *
+ * size ::
+ * The size of the table holding the data.
+ *
+ * @Output:
+ * point_cnt ::
+ * The number of points read. A zero value means that
+ * all points in the glyph will be affected, without
+ * enumerating them individually.
+ *
+ * @Return:
+ * An array of FT_UShort containing the affected points or the
+ * special value ALL_POINTS.
+ */
static FT_UShort*
ft_var_readpackedpoints( FT_Stream stream,
FT_ULong size,
@@ -211,34 +223,41 @@
#define GX_DT_DELTA_RUN_COUNT_MASK 0x3FU
- /*************************************************************************/
- /* */
- /* <Function> */
- /* ft_var_readpackeddeltas */
- /* */
- /* <Description> */
- /* Read a set of deltas. These are packed slightly differently than */
- /* points. In particular there is no overall count. */
- /* */
- /* <Input> */
- /* stream :: The data stream. */
- /* */
- /* size :: The size of the table holding the data. */
- /* */
- /* delta_cnt :: The number of deltas to be read. */
- /* */
- /* <Return> */
- /* An array of FT_Short containing the deltas for the affected */
- /* points. (This only gets the deltas for one dimension. It will */
- /* generally be called twice, once for x, once for y. When used in */
- /* cvt table, it will only be called once.) */
- /* */
- static FT_Short*
+ /**************************************************************************
+ *
+ * @Function:
+ * ft_var_readpackeddeltas
+ *
+ * @Description:
+ * Read a set of deltas. These are packed slightly differently than
+ * points. In particular there is no overall count.
+ *
+ * @Input:
+ * stream ::
+ * The data stream.
+ *
+ * size ::
+ * The size of the table holding the data.
+ *
+ * delta_cnt ::
+ * The number of deltas to be read.
+ *
+ * @Return:
+ * An array of FT_Fixed containing the deltas for the affected
+ * points. (This only gets the deltas for one dimension. It will
+ * generally be called twice, once for x, once for y. When used in
+ * cvt table, it will only be called once.)
+ *
+ * We use FT_Fixed to avoid accumulation errors while summing up all
+ * deltas (the rounding to integer values happens as the very last
+ * step).
+ */
+ static FT_Fixed*
ft_var_readpackeddeltas( FT_Stream stream,
FT_ULong size,
FT_UInt delta_cnt )
{
- FT_Short *deltas = NULL;
+ FT_Fixed *deltas = NULL;
FT_UInt runcnt, cnt;
FT_UInt i, j;
FT_Memory memory = stream->memory;
@@ -272,13 +291,13 @@
{
/* `runcnt' shorts from the stack */
for ( j = 0; j <= cnt && i < delta_cnt; j++ )
- deltas[i++] = FT_GET_SHORT();
+ deltas[i++] = FT_intToFixed( FT_GET_SHORT() );
}
else
{
/* `runcnt' signed bytes from the stack */
for ( j = 0; j <= cnt && i < delta_cnt; j++ )
- deltas[i++] = FT_GET_CHAR();
+ deltas[i++] = FT_intToFixed( FT_GET_CHAR() );
}
if ( j <= cnt )
@@ -293,18 +312,19 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* ft_var_load_avar */
- /* */
- /* <Description> */
- /* Parse the `avar' table if present. It need not be, so we return */
- /* nothing. */
- /* */
- /* <InOut> */
- /* face :: The font face. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * ft_var_load_avar
+ *
+ * @Description:
+ * Parse the `avar' table if present. It need not be, so we return
+ * nothing.
+ *
+ * @InOut:
+ * face ::
+ * The font face.
+ */
static void
ft_var_load_avar( TT_Face face )
{
@@ -394,17 +414,6 @@
}
- /* some macros we need */
-#define FT_FIXED_ONE ( (FT_Fixed)0x10000 )
-
-#define FT_fdot14ToFixed( x ) \
- ( (FT_Fixed)( (FT_ULong)(x) << 2 ) )
-#define FT_intToFixed( i ) \
- ( (FT_Fixed)( (FT_ULong)(i) << 16 ) )
-#define FT_fixedToInt( x ) \
- ( (FT_Short)( ( (FT_UInt32)(x) + 0x8000U ) >> 16 ) )
-
-
static FT_Error
ft_var_load_item_variation_store( TT_Face face,
FT_ULong offset,
@@ -702,29 +711,30 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* ft_var_load_hvvar */
- /* */
- /* <Description> */
- /* If `vertical' is zero, parse the `HVAR' table and set */
- /* `blend->hvar_loaded' to TRUE. On success, `blend->hvar_checked' */
- /* is set to TRUE. */
- /* */
- /* If `vertical' is not zero, parse the `VVAR' table and set */
- /* `blend->vvar_loaded' to TRUE. On success, `blend->vvar_checked' */
- /* is set to TRUE. */
- /* */
- /* Some memory may remain allocated on error; it is always freed in */
- /* `tt_done_blend', however. */
- /* */
- /* <InOut> */
- /* face :: The font face. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * ft_var_load_hvvar
+ *
+ * @Description:
+ * If `vertical' is zero, parse the `HVAR' table and set
+ * `blend->hvar_loaded' to TRUE. On success, `blend->hvar_checked'
+ * is set to TRUE.
+ *
+ * If `vertical' is not zero, parse the `VVAR' table and set
+ * `blend->vvar_loaded' to TRUE. On success, `blend->vvar_checked'
+ * is set to TRUE.
+ *
+ * Some memory may remain allocated on error; it is always freed in
+ * `tt_done_blend', however.
+ *
+ * @InOut:
+ * face ::
+ * The font face.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
static FT_Error
ft_var_load_hvvar( TT_Face face,
FT_Bool vertical )
@@ -872,7 +882,7 @@
/* outer loop steps through master designs to be blended */
for ( master = 0; master < varData->regionIdxCount; master++ )
{
- FT_Fixed scalar = FT_FIXED_ONE;
+ FT_Fixed scalar = 0x10000L;
FT_UInt regionIndex = varData->regionIndices[master];
GX_AxisCoords axis = itemStore->varRegionList[regionIndex].axisList;
@@ -881,47 +891,43 @@
/* inner loop steps through axes in this region */
for ( j = 0; j < itemStore->axisCount; j++, axis++ )
{
- FT_Fixed axisScalar;
-
-
/* compute the scalar contribution of this axis; */
/* ignore invalid ranges */
if ( axis->startCoord > axis->peakCoord ||
axis->peakCoord > axis->endCoord )
- axisScalar = FT_FIXED_ONE;
+ continue;
else if ( axis->startCoord < 0 &&
axis->endCoord > 0 &&
axis->peakCoord != 0 )
- axisScalar = FT_FIXED_ONE;
+ continue;
/* peak of 0 means ignore this axis */
else if ( axis->peakCoord == 0 )
- axisScalar = FT_FIXED_ONE;
+ continue;
- /* ignore this region if coords are out of range */
- else if ( face->blend->normalizedcoords[j] < axis->startCoord ||
- face->blend->normalizedcoords[j] > axis->endCoord )
- axisScalar = 0;
+ else if ( face->blend->normalizedcoords[j] == axis->peakCoord )
+ continue;
- /* calculate a proportional factor */
- else
+ /* ignore this region if coords are out of range */
+ else if ( face->blend->normalizedcoords[j] <= axis->startCoord ||
+ face->blend->normalizedcoords[j] >= axis->endCoord )
{
- if ( face->blend->normalizedcoords[j] == axis->peakCoord )
- axisScalar = FT_FIXED_ONE;
- else if ( face->blend->normalizedcoords[j] < axis->peakCoord )
- axisScalar =
- FT_DivFix( face->blend->normalizedcoords[j] - axis->startCoord,
- axis->peakCoord - axis->startCoord );
- else
- axisScalar =
- FT_DivFix( axis->endCoord - face->blend->normalizedcoords[j],
- axis->endCoord - axis->peakCoord );
+ scalar = 0;
+ break;
}
- /* take product of all the axis scalars */
- scalar = FT_MulFix( scalar, axisScalar );
-
+ /* cumulative product of all the axis scalars */
+ else if ( face->blend->normalizedcoords[j] < axis->peakCoord )
+ scalar =
+ FT_MulDiv( scalar,
+ face->blend->normalizedcoords[j] - axis->startCoord,
+ axis->peakCoord - axis->startCoord );
+ else
+ scalar =
+ FT_MulDiv( scalar,
+ axis->endCoord - face->blend->normalizedcoords[j],
+ axis->endCoord - axis->peakCoord );
} /* per-axis loop */
/* get the scaled delta for this region */
@@ -937,25 +943,29 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_hvadvance_adjust */
- /* */
- /* <Description> */
- /* Apply `HVAR' advance width or `VVAR' advance height adjustment of */
- /* a given glyph. */
- /* */
- /* <Input> */
- /* gindex :: The glyph index. */
- /* */
- /* vertical :: If set, handle `VVAR' table. */
- /* */
- /* <InOut> */
- /* face :: The font face. */
- /* */
- /* adelta :: Points to width or height value that gets modified. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_hvadvance_adjust
+ *
+ * @Description:
+ * Apply `HVAR' advance width or `VVAR' advance height adjustment of
+ * a given glyph.
+ *
+ * @Input:
+ * gindex ::
+ * The glyph index.
+ *
+ * vertical ::
+ * If set, handle `VVAR' table.
+ *
+ * @InOut:
+ * face ::
+ * The font face.
+ *
+ * adelta ::
+ * Points to width or height value that gets modified.
+ */
static FT_Error
tt_hvadvance_adjust( TT_Face face,
FT_UInt gindex,
@@ -1151,20 +1161,21 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* ft_var_load_mvar */
- /* */
- /* <Description> */
- /* Parse the `MVAR' table. */
- /* */
- /* Some memory may remain allocated on error; it is always freed in */
- /* `tt_done_blend', however. */
- /* */
- /* <InOut> */
- /* face :: The font face. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * ft_var_load_mvar
+ *
+ * @Description:
+ * Parse the `MVAR' table.
+ *
+ * Some memory may remain allocated on error; it is always freed in
+ * `tt_done_blend', however.
+ *
+ * @InOut:
+ * face ::
+ * The font face.
+ */
static void
ft_var_load_mvar( TT_Face face )
{
@@ -1297,22 +1308,26 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_apply_mvar */
- /* */
- /* <Description> */
- /* Apply `MVAR' table adjustments. */
- /* */
- /* <InOut> */
- /* face :: The font face. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_apply_mvar
+ *
+ * @Description:
+ * Apply `MVAR' table adjustments.
+ *
+ * @InOut:
+ * face ::
+ * The font face.
+ */
FT_LOCAL_DEF( void )
tt_apply_mvar( TT_Face face )
{
GX_Blend blend = face->blend;
GX_Value value, limit;
+ FT_Short mvar_hasc_delta = 0;
+ FT_Short mvar_hdsc_delta = 0;
+ FT_Short mvar_hlgp_delta = 0;
if ( !( face->variation_support & TT_FACE_FLAG_VAR_MVAR ) )
@@ -1347,6 +1362,14 @@
/* since we handle both signed and unsigned values as FT_Short, */
/* ensure proper overflow arithmetic */
*p = (FT_Short)( value->unmodified + (FT_Short)delta );
+
+ /* Treat hasc, hdsc and hlgp specially, see below. */
+ if ( value->tag == MVAR_TAG_HASC )
+ mvar_hasc_delta = (FT_Short)delta;
+ else if ( value->tag == MVAR_TAG_HDSC )
+ mvar_hdsc_delta = (FT_Short)delta;
+ else if ( value->tag == MVAR_TAG_HLGP )
+ mvar_hlgp_delta = (FT_Short)delta;
}
}
@@ -1354,25 +1377,40 @@
{
FT_Face root = &face->root;
-
- if ( face->os2.version != 0xFFFFU )
- {
- if ( face->os2.sTypoAscender || face->os2.sTypoDescender )
- {
- root->ascender = face->os2.sTypoAscender;
- root->descender = face->os2.sTypoDescender;
-
- root->height = root->ascender - root->descender +
- face->os2.sTypoLineGap;
- }
- else
- {
- root->ascender = (FT_Short)face->os2.usWinAscent;
- root->descender = -(FT_Short)face->os2.usWinDescent;
-
- root->height = root->ascender - root->descender;
- }
- }
+ /*
+ * Apply the deltas of hasc, hdsc and hlgp to the FT_Face's ascender,
+ * descender and height attributes, no matter how they were originally
+ * computed.
+ *
+ * (Code that ignores those and accesses the font's metrics values
+ * directly is already served by the delta application code above.)
+ *
+ * The MVAR table supports variations for both typo and win metrics.
+ * According to Behdad Esfahbod, the thinking of the working group was
+ * that no one uses win metrics anymore for setting line metrics (the
+ * specification even calls these metrics "horizontal clipping
+ * ascent/descent", probably for their role on the Windows platform in
+ * computing clipping boxes), and new fonts should use typo metrics, so
+ * typo deltas should be applied to whatever sfnt_load_face decided the
+ * line metrics should be.
+ *
+ * Before, the following led to different line metrics between default
+ * outline and instances, visible when e.g. the default outlines were
+ * used as the regular face and instances for everything else:
+ *
+ * 1. sfnt_load_face applied the hhea metrics by default.
+ * 2. This code later applied the typo metrics by default, regardless of
+ * whether they were actually changed or the font had the OS/2 table's
+ * fsSelection's bit 7 (USE_TYPO_METRICS) set.
+ */
+ FT_Short current_line_gap = root->height - root->ascender +
+ root->descender;
+
+
+ root->ascender = root->ascender + mvar_hasc_delta;
+ root->descender = root->descender + mvar_hdsc_delta;
+ root->height = root->ascender - root->descender +
+ current_line_gap + mvar_hlgp_delta;
root->underline_position = face->postscript.underlinePosition -
face->postscript.underlineThickness / 2;
@@ -1400,21 +1438,22 @@
} GX_GVar_Head;
- /*************************************************************************/
- /* */
- /* <Function> */
- /* ft_var_load_gvar */
- /* */
- /* <Description> */
- /* Parse the `gvar' table if present. If `fvar' is there, `gvar' had */
- /* better be there too. */
- /* */
- /* <InOut> */
- /* face :: The font face. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * ft_var_load_gvar
+ *
+ * @Description:
+ * Parse the `gvar' table if present. If `fvar' is there, `gvar' had
+ * better be there too.
+ *
+ * @InOut:
+ * face ::
+ * The font face.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
static FT_Error
ft_var_load_gvar( TT_Face face )
{
@@ -1512,28 +1551,55 @@
if ( gvar_head.flags & 1 )
{
+ FT_ULong limit = gvar_start + table_len;
+
+
/* long offsets (one more offset than glyphs, to mark size of last) */
if ( FT_FRAME_ENTER( ( blend->gv_glyphcnt + 1 ) * 4L ) )
goto Exit;
for ( i = 0; i <= blend->gv_glyphcnt; i++ )
+ {
blend->glyphoffsets[i] = offsetToData + FT_GET_ULONG();
-
- FT_FRAME_EXIT();
+ /* use `>', not `>=' */
+ if ( blend->glyphoffsets[i] > limit )
+ {
+ FT_TRACE2(( "ft_var_load_gvar:"
+ " invalid glyph variation data offset for index %d\n",
+ i ));
+ error = FT_THROW( Invalid_Table );
+ break;
+ }
+ }
}
else
{
+ FT_ULong limit = gvar_start + table_len;
+
+
/* short offsets (one more offset than glyphs, to mark size of last) */
if ( FT_FRAME_ENTER( ( blend->gv_glyphcnt + 1 ) * 2L ) )
goto Exit;
for ( i = 0; i <= blend->gv_glyphcnt; i++ )
+ {
blend->glyphoffsets[i] = offsetToData + FT_GET_USHORT() * 2;
- /* XXX: Undocumented: `*2'! */
-
- FT_FRAME_EXIT();
+ /* use `>', not `>=' */
+ if ( blend->glyphoffsets[i] > limit )
+ {
+ FT_TRACE2(( "ft_var_load_gvar:"
+ " invalid glyph variation data offset for index %d\n",
+ i ));
+ error = FT_THROW( Invalid_Table );
+ break;
+ }
+ }
}
+ FT_FRAME_EXIT();
+ if ( error )
+ goto Exit;
+
if ( blend->tuplecount != 0 )
{
if ( FT_NEW_ARRAY( blend->tuplecoords,
@@ -1567,33 +1633,38 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* ft_var_apply_tuple */
- /* */
- /* <Description> */
- /* Figure out whether a given tuple (design) applies to the current */
- /* blend, and if so, what is the scaling factor. */
- /* */
- /* <Input> */
- /* blend :: The current blend of the font. */
- /* */
- /* tupleIndex :: A flag saying whether this is an intermediate */
- /* tuple or not. */
- /* */
- /* tuple_coords :: The coordinates of the tuple in normalized axis */
- /* units. */
- /* */
- /* im_start_coords :: The initial coordinates where this tuple starts */
- /* to apply (for intermediate coordinates). */
- /* */
- /* im_end_coords :: The final coordinates after which this tuple no */
- /* longer applies (for intermediate coordinates). */
- /* */
- /* <Return> */
- /* An FT_Fixed value containing the scaling factor. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * ft_var_apply_tuple
+ *
+ * @Description:
+ * Figure out whether a given tuple (design) applies to the current
+ * blend, and if so, what is the scaling factor.
+ *
+ * @Input:
+ * blend ::
+ * The current blend of the font.
+ *
+ * tupleIndex ::
+ * A flag saying whether this is an intermediate
+ * tuple or not.
+ *
+ * tuple_coords ::
+ * The coordinates of the tuple in normalized axis
+ * units.
+ *
+ * im_start_coords ::
+ * The initial coordinates where this tuple starts
+ * to apply (for intermediate coordinates).
+ *
+ * im_end_coords ::
+ * The final coordinates after which this tuple no
+ * longer applies (for intermediate coordinates).
+ *
+ * @Return:
+ * An FT_Fixed value containing the scaling factor.
+ */
static FT_Fixed
ft_var_apply_tuple( GX_Blend blend,
FT_UShort tupleIndex,
@@ -1607,13 +1678,8 @@
for ( i = 0; i < blend->num_axis; i++ )
{
- FT_TRACE6(( " axis coordinate %d (%.5f):\n",
+ FT_TRACE6(( " axis %d coordinate %.5f:\n",
i, blend->normalizedcoords[i] / 65536.0 ));
- if ( !( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) )
- FT_TRACE6(( " intermediate coordinates %d (%.5f, %.5f):\n",
- i,
- im_start_coords[i] / 65536.0,
- im_end_coords[i] / 65536.0 ));
/* It's not clear why (for intermediate tuples) we don't need */
/* to check against start/end -- the documentation says we don't. */
@@ -1622,7 +1688,7 @@
if ( tuple_coords[i] == 0 )
{
- FT_TRACE6(( " tuple coordinate is zero, ignored\n", i ));
+ FT_TRACE6(( " tuple coordinate is zero, ignore\n", i ));
continue;
}
@@ -1635,7 +1701,7 @@
if ( blend->normalizedcoords[i] == tuple_coords[i] )
{
- FT_TRACE6(( " tuple coordinate value %.5f fits perfectly\n",
+ FT_TRACE6(( " tuple coordinate %.5f fits perfectly\n",
tuple_coords[i] / 65536.0 ));
/* `apply' does not change */
continue;
@@ -1648,13 +1714,13 @@
if ( blend->normalizedcoords[i] < FT_MIN( 0, tuple_coords[i] ) ||
blend->normalizedcoords[i] > FT_MAX( 0, tuple_coords[i] ) )
{
- FT_TRACE6(( " tuple coordinate value %.5f is exceeded, stop\n",
+ FT_TRACE6(( " tuple coordinate %.5f is exceeded, stop\n",
tuple_coords[i] / 65536.0 ));
apply = 0;
break;
}
- FT_TRACE6(( " tuple coordinate value %.5f fits\n",
+ FT_TRACE6(( " tuple coordinate %.5f fits\n",
tuple_coords[i] / 65536.0 ));
apply = FT_MulDiv( apply,
blend->normalizedcoords[i],
@@ -1664,10 +1730,10 @@
{
/* intermediate tuple */
- if ( blend->normalizedcoords[i] < im_start_coords[i] ||
- blend->normalizedcoords[i] > im_end_coords[i] )
+ if ( blend->normalizedcoords[i] <= im_start_coords[i] ||
+ blend->normalizedcoords[i] >= im_end_coords[i] )
{
- FT_TRACE6(( " intermediate tuple range [%.5f;%.5f] is exceeded,"
+ FT_TRACE6(( " intermediate tuple range ]%.5f;%.5f[ is exceeded,"
" stop\n",
im_start_coords[i] / 65536.0,
im_end_coords[i] / 65536.0 ));
@@ -1675,25 +1741,17 @@
break;
}
- else if ( blend->normalizedcoords[i] < tuple_coords[i] )
- {
- FT_TRACE6(( " intermediate tuple range [%.5f;%.5f] fits\n",
- im_start_coords[i] / 65536.0,
- im_end_coords[i] / 65536.0 ));
+ FT_TRACE6(( " intermediate tuple range ]%.5f;%.5f[ fits\n",
+ im_start_coords[i] / 65536.0,
+ im_end_coords[i] / 65536.0 ));
+ if ( blend->normalizedcoords[i] < tuple_coords[i] )
apply = FT_MulDiv( apply,
blend->normalizedcoords[i] - im_start_coords[i],
tuple_coords[i] - im_start_coords[i] );
- }
-
else
- {
- FT_TRACE6(( " intermediate tuple range [%.5f;%.5f] fits\n",
- im_start_coords[i] / 65536.0,
- im_end_coords[i] / 65536.0 ));
apply = FT_MulDiv( apply,
im_end_coords[i] - blend->normalizedcoords[i],
im_end_coords[i] - tuple_coords[i] );
- }
}
}
@@ -1756,11 +1814,11 @@
}
if ( coord < a->def )
- normalized[i] = -FT_DivFix( coord - a->def,
- a->minimum - a->def );
+ normalized[i] = -FT_DivFix( SUB_LONG( coord, a->def ),
+ SUB_LONG( a->minimum, a->def ) );
else if ( coord > a->def )
- normalized[i] = FT_DivFix( coord - a->def,
- a->maximum - a->def );
+ normalized[i] = FT_DivFix( SUB_LONG( coord, a->def ),
+ SUB_LONG( a->maximum, a->def ) );
else
normalized[i] = 0;
}
@@ -1910,27 +1968,29 @@
} GX_FVar_Axis;
- /*************************************************************************/
- /* */
- /* <Function> */
- /* TT_Get_MM_Var */
- /* */
- /* <Description> */
- /* Check that the font's `fvar' table is valid, parse it, and return */
- /* those data. It also loads (and parses) the `MVAR' table, if */
- /* possible. */
- /* */
- /* <InOut> */
- /* face :: The font face. */
- /* TT_Get_MM_Var initializes the blend structure. */
- /* */
- /* <Output> */
- /* master :: The `fvar' data (must be freed by caller). Can be NULL, */
- /* which makes this function simply load MM support. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * TT_Get_MM_Var
+ *
+ * @Description:
+ * Check that the font's `fvar' table is valid, parse it, and return
+ * those data. It also loads (and parses) the `MVAR' table, if
+ * possible.
+ *
+ * @InOut:
+ * face ::
+ * The font face.
+ * TT_Get_MM_Var initializes the blend structure.
+ *
+ * @Output:
+ * master ::
+ * The `fvar' data (must be freed by caller). Can be NULL,
+ * which makes this function simply load MM support.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
TT_Get_MM_Var( TT_Face face,
FT_MM_Var* *master )
@@ -2507,11 +2567,14 @@
if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) )
{
- FT_UInt idx = (FT_UInt)face->root.face_index >> 16;
+ FT_UInt instance_index = (FT_UInt)face->root.face_index >> 16;
c = blend->normalizedcoords + i;
- n = blend->normalized_stylecoords + idx * mmvar->num_axis + i;
+ n = blend->normalized_stylecoords +
+ ( instance_index - 1 ) * mmvar->num_axis +
+ i;
+
for ( j = i; j < mmvar->num_axis; j++, n++, c++ )
if ( *c != *n )
have_diff = 1;
@@ -2526,7 +2589,11 @@
/* return value -1 indicates `no change' */
if ( !have_diff )
+ {
+ face->doblend = TRUE;
+
return -1;
+ }
for ( ; i < mmvar->num_axis; i++ )
{
@@ -2590,31 +2657,34 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* TT_Set_MM_Blend */
- /* */
- /* <Description> */
- /* Set the blend (normalized) coordinates for this instance of the */
- /* font. Check that the `gvar' table is reasonable and does some */
- /* initial preparation. */
- /* */
- /* <InOut> */
- /* face :: The font. */
- /* Initialize the blend structure with `gvar' data. */
- /* */
- /* <Input> */
- /* num_coords :: The number of available coordinates. If it is */
- /* larger than the number of axes, ignore the excess */
- /* values. If it is smaller than the number of axes, */
- /* use the default value (0) for the remaining axes. */
- /* */
- /* coords :: An array of `num_coords', each between [-1,1]. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * TT_Set_MM_Blend
+ *
+ * @Description:
+ * Set the blend (normalized) coordinates for this instance of the
+ * font. Check that the `gvar' table is reasonable and does some
+ * initial preparation.
+ *
+ * @InOut:
+ * face ::
+ * The font.
+ * Initialize the blend structure with `gvar' data.
+ *
+ * @Input:
+ * num_coords ::
+ * The number of available coordinates. If it is
+ * larger than the number of axes, ignore the excess
+ * values. If it is smaller than the number of axes,
+ * use the default value (0) for the remaining axes.
+ *
+ * coords ::
+ * An array of `num_coords', each between [-1,1].
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
TT_Set_MM_Blend( TT_Face face,
FT_UInt num_coords,
@@ -2636,29 +2706,32 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* TT_Get_MM_Blend */
- /* */
- /* <Description> */
- /* Get the blend (normalized) coordinates for this instance of the */
- /* font. */
- /* */
- /* <InOut> */
- /* face :: The font. */
- /* Initialize the blend structure with `gvar' data. */
- /* */
- /* <Input> */
- /* num_coords :: The number of available coordinates. If it is */
- /* larger than the number of axes, set the excess */
- /* values to 0. */
- /* */
- /* coords :: An array of `num_coords', each between [-1,1]. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * TT_Get_MM_Blend
+ *
+ * @Description:
+ * Get the blend (normalized) coordinates for this instance of the
+ * font.
+ *
+ * @InOut:
+ * face ::
+ * The font.
+ * Initialize the blend structure with `gvar' data.
+ *
+ * @Input:
+ * num_coords ::
+ * The number of available coordinates. If it is
+ * larger than the number of axes, set the excess
+ * values to 0.
+ *
+ * coords ::
+ * An array of `num_coords', each between [-1,1].
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
TT_Get_MM_Blend( TT_Face face,
FT_UInt num_coords,
@@ -2712,31 +2785,34 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* TT_Set_Var_Design */
- /* */
- /* <Description> */
- /* Set the coordinates for the instance, measured in the user */
- /* coordinate system. Parse the `avar' table (if present) to convert */
- /* from user to normalized coordinates. */
- /* */
- /* <InOut> */
- /* face :: The font face. */
- /* Initialize the blend struct with `gvar' data. */
- /* */
- /* <Input> */
- /* num_coords :: The number of available coordinates. If it is */
- /* larger than the number of axes, ignore the excess */
- /* values. If it is smaller than the number of axes, */
- /* use the default values for the remaining axes. */
- /* */
- /* coords :: A coordinate array with `num_coords' elements. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * TT_Set_Var_Design
+ *
+ * @Description:
+ * Set the coordinates for the instance, measured in the user
+ * coordinate system. Parse the `avar' table (if present) to convert
+ * from user to normalized coordinates.
+ *
+ * @InOut:
+ * face ::
+ * The font face.
+ * Initialize the blend struct with `gvar' data.
+ *
+ * @Input:
+ * num_coords ::
+ * The number of available coordinates. If it is
+ * larger than the number of axes, ignore the excess
+ * values. If it is smaller than the number of axes,
+ * use the default values for the remaining axes.
+ *
+ * coords ::
+ * A coordinate array with `num_coords' elements.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
TT_Set_Var_Design( TT_Face face,
FT_UInt num_coords,
@@ -2854,28 +2930,31 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* TT_Get_Var_Design */
- /* */
- /* <Description> */
- /* Get the design coordinates of the currently selected interpolated */
- /* font. */
- /* */
- /* <Input> */
- /* face :: A handle to the source face. */
- /* */
- /* num_coords :: The number of design coordinates to retrieve. If it */
- /* is larger than the number of axes, set the excess */
- /* values to~0. */
- /* */
- /* <Output> */
- /* coords :: The design coordinates array. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * TT_Get_Var_Design
+ *
+ * @Description:
+ * Get the design coordinates of the currently selected interpolated
+ * font.
+ *
+ * @Input:
+ * face ::
+ * A handle to the source face.
+ *
+ * num_coords ::
+ * The number of design coordinates to retrieve. If it
+ * is larger than the number of axes, set the excess
+ * values to~0.
+ *
+ * @Output:
+ * coords ::
+ * The design coordinates array.
+ *
+ * @Return:
+ * FreeType error code. 0~means success.
+ */
FT_LOCAL_DEF( FT_Error )
TT_Get_Var_Design( TT_Face face,
FT_UInt num_coords,
@@ -2929,24 +3008,26 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* TT_Set_Named_Instance */
- /* */
- /* <Description> */
- /* Set the given named instance, also resetting any further */
- /* variation. */
- /* */
- /* <Input> */
- /* face :: A handle to the source face. */
- /* */
- /* instance_index :: The instance index, starting with value 1. */
- /* Value 0 indicates to not use an instance. */
- /* */
- /* <Return> */
- /* FreeType error code. 0~means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * TT_Set_Named_Instance
+ *
+ * @Description:
+ * Set the given named instance, also resetting any further
+ * variation.
+ *
+ * @Input:
+ * face ::
+ * A handle to the source face.
+ *
+ * instance_index ::
+ * The instance index, starting with value 1.
+ * Value 0 indicates to not use an instance.
+ *
+ * @Return:
+ * FreeType error code. 0~means success.
+ */
FT_LOCAL_DEF( FT_Error )
TT_Set_Named_Instance( TT_Face face,
FT_UInt instance_index )
@@ -3022,48 +3103,60 @@
/*************************************************************************/
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_vary_cvt */
- /* */
- /* <Description> */
- /* Modify the loaded cvt table according to the `cvar' table and the */
- /* font's blend. */
- /* */
- /* <InOut> */
- /* face :: A handle to the target face object. */
- /* */
- /* <Input> */
- /* stream :: A handle to the input stream. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- /* Most errors are ignored. It is perfectly valid not to have a */
- /* `cvar' table even if there is a `gvar' and `fvar' table. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_face_vary_cvt
+ *
+ * @Description:
+ * Modify the loaded cvt table according to the `cvar' table and the
+ * font's blend.
+ *
+ * @InOut:
+ * face ::
+ * A handle to the target face object.
+ *
+ * @Input:
+ * stream ::
+ * A handle to the input stream.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ *
+ * Most errors are ignored. It is perfectly valid not to have a
+ * `cvar' table even if there is a `gvar' and `fvar' table.
+ */
FT_LOCAL_DEF( FT_Error )
tt_face_vary_cvt( TT_Face face,
FT_Stream stream )
{
- FT_Error error;
- FT_Memory memory = stream->memory;
- FT_ULong table_start;
- FT_ULong table_len;
- FT_UInt tupleCount;
- FT_ULong offsetToData;
- FT_ULong here;
- FT_UInt i, j;
- FT_Fixed* tuple_coords = NULL;
- FT_Fixed* im_start_coords = NULL;
- FT_Fixed* im_end_coords = NULL;
- GX_Blend blend = face->blend;
- FT_UInt point_count, spoint_count = 0;
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_ULong table_start;
+ FT_ULong table_len;
+
+ FT_UInt tupleCount;
+ FT_ULong offsetToData;
+
+ FT_ULong here;
+ FT_UInt i, j;
+
+ FT_Fixed* tuple_coords = NULL;
+ FT_Fixed* im_start_coords = NULL;
+ FT_Fixed* im_end_coords = NULL;
+
+ GX_Blend blend = face->blend;
+
+ FT_UInt point_count;
+ FT_UInt spoint_count = 0;
+
FT_UShort* sharedpoints = NULL;
FT_UShort* localpoints = NULL;
FT_UShort* points;
- FT_Short* deltas;
+
+ FT_Fixed* deltas = NULL;
+ FT_Fixed* cvt_deltas = NULL;
FT_TRACE2(( "CVAR " ));
@@ -3146,11 +3239,14 @@
}
FT_TRACE5(( "cvar: there %s %d tuple%s:\n",
- ( tupleCount & 0xFFF ) == 1 ? "is" : "are",
- tupleCount & 0xFFF,
- ( tupleCount & 0xFFF ) == 1 ? "" : "s" ));
+ ( tupleCount & GX_TC_TUPLE_COUNT_MASK ) == 1 ? "is" : "are",
+ tupleCount & GX_TC_TUPLE_COUNT_MASK,
+ ( tupleCount & GX_TC_TUPLE_COUNT_MASK ) == 1 ? "" : "s" ));
+
+ if ( FT_NEW_ARRAY( cvt_deltas, face->cvt_size ) )
+ goto FExit;
- for ( i = 0; i < ( tupleCount & 0xFFF ); i++ )
+ for ( i = 0; i < ( tupleCount & GX_TC_TUPLE_COUNT_MASK ); i++ )
{
FT_UInt tupleDataSize;
FT_UInt tupleIndex;
@@ -3174,13 +3270,25 @@
" invalid tuple index\n" ));
error = FT_THROW( Invalid_Table );
- goto Exit;
+ goto FExit;
}
else
+ {
+ if ( !blend->tuplecoords )
+ {
+ FT_TRACE2(( "tt_face_vary_cvt:"
+ " no valid tuple coordinates available\n" ));
+
+ error = FT_THROW( Invalid_Table );
+ goto FExit;
+ }
+
FT_MEM_COPY(
tuple_coords,
- &blend->tuplecoords[( tupleIndex & 0xFFF ) * blend->num_axis],
+ blend->tuplecoords +
+ ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) * blend->num_axis,
blend->num_axis * sizeof ( FT_Fixed ) );
+ }
if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
{
@@ -3241,17 +3349,21 @@
/* this means that there are deltas for every entry in cvt */
for ( j = 0; j < face->cvt_size; j++ )
{
- FT_Long orig_cvt = face->cvt[j];
+ FT_Fixed old_cvt_delta;
- face->cvt[j] = (FT_Short)( orig_cvt +
- FT_MulFix( deltas[j], apply ) );
+ old_cvt_delta = cvt_deltas[j];
+ cvt_deltas[j] = old_cvt_delta + FT_MulFix( deltas[j], apply );
#ifdef FT_DEBUG_LEVEL_TRACE
- if ( orig_cvt != face->cvt[j] )
+ if ( old_cvt_delta != cvt_deltas[j] )
{
- FT_TRACE7(( " %d: %d -> %d\n",
- j, orig_cvt, face->cvt[j] ));
+ FT_TRACE7(( " %d: %f -> %f\n",
+ j,
+ ( FT_intToFixed( face->cvt[j] ) +
+ old_cvt_delta ) / 65536.0,
+ ( FT_intToFixed( face->cvt[j] ) +
+ cvt_deltas[j] ) / 65536.0 ));
count++;
}
#endif
@@ -3274,23 +3386,26 @@
for ( j = 0; j < point_count; j++ )
{
- int pindex;
- FT_Long orig_cvt;
+ int pindex;
+ FT_Fixed old_cvt_delta;
pindex = points[j];
if ( (FT_ULong)pindex >= face->cvt_size )
continue;
- orig_cvt = face->cvt[pindex];
- face->cvt[pindex] = (FT_Short)( orig_cvt +
- FT_MulFix( deltas[j], apply ) );
+ old_cvt_delta = cvt_deltas[pindex];
+ cvt_deltas[pindex] = old_cvt_delta + FT_MulFix( deltas[j], apply );
#ifdef FT_DEBUG_LEVEL_TRACE
- if ( orig_cvt != face->cvt[pindex] )
+ if ( old_cvt_delta != cvt_deltas[pindex] )
{
- FT_TRACE7(( " %d: %d -> %d\n",
- pindex, orig_cvt, face->cvt[pindex] ));
+ FT_TRACE7(( " %d: %f -> %f\n",
+ pindex,
+ ( FT_intToFixed( face->cvt[pindex] ) +
+ old_cvt_delta ) / 65536.0,
+ ( FT_intToFixed( face->cvt[pindex] ) +
+ cvt_deltas[pindex] ) / 65536.0 ));
count++;
}
#endif
@@ -3313,6 +3428,9 @@
FT_TRACE5(( "\n" ));
+ for ( i = 0; i < face->cvt_size; i++ )
+ face->cvt[i] += FT_fixedToInt( cvt_deltas[i] );
+
FExit:
FT_FRAME_EXIT();
@@ -3322,6 +3440,7 @@
FT_FREE( tuple_coords );
FT_FREE( im_start_coords );
FT_FREE( im_end_coords );
+ FT_FREE( cvt_deltas );
return error;
}
@@ -3367,9 +3486,8 @@
/* between `p1' and `p2', using `ref1' and `ref2' as the reference */
/* point indices. */
- /* modeled after `af_iup_interp', `_iup_worker_interpolate', and */
- /* `Ins_IUP' */
-
+ /* modeled after `af_iup_interp', `_iup_worker_interpolate', and */
+ /* `Ins_IUP' with spec differences in handling ill-defined cases. */
static void
tt_delta_interpolate( int p1,
int p2,
@@ -3528,56 +3646,72 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* TT_Vary_Apply_Glyph_Deltas */
- /* */
- /* <Description> */
- /* Apply the appropriate deltas to the current glyph. */
- /* */
- /* <Input> */
- /* face :: A handle to the target face object. */
- /* */
- /* glyph_index :: The index of the glyph being modified. */
- /* */
- /* n_points :: The number of the points in the glyph, including */
- /* phantom points. */
- /* */
- /* <InOut> */
- /* outline :: The outline to change. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * TT_Vary_Apply_Glyph_Deltas
+ *
+ * @Description:
+ * Apply the appropriate deltas to the current glyph.
+ *
+ * @Input:
+ * face ::
+ * A handle to the target face object.
+ *
+ * glyph_index ::
+ * The index of the glyph being modified.
+ *
+ * n_points ::
+ * The number of the points in the glyph, including
+ * phantom points.
+ *
+ * @InOut:
+ * outline ::
+ * The outline to change.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
TT_Vary_Apply_Glyph_Deltas( TT_Face face,
FT_UInt glyph_index,
FT_Outline* outline,
FT_UInt n_points )
{
- FT_Stream stream = face->root.stream;
- FT_Memory memory = stream->memory;
- GX_Blend blend = face->blend;
+ FT_Error error;
+ FT_Stream stream = face->root.stream;
+ FT_Memory memory = stream->memory;
- FT_Vector* points_org = NULL;
- FT_Vector* points_out = NULL;
+ FT_Vector* points_org = NULL; /* coordinates in 16.16 format */
+ FT_Vector* points_out = NULL; /* coordinates in 16.16 format */
FT_Bool* has_delta = NULL;
- FT_Error error;
- FT_ULong glyph_start;
- FT_UInt tupleCount;
- FT_ULong offsetToData;
- FT_ULong here;
- FT_UInt i, j;
- FT_Fixed* tuple_coords = NULL;
- FT_Fixed* im_start_coords = NULL;
- FT_Fixed* im_end_coords = NULL;
- FT_UInt point_count, spoint_count = 0;
+ FT_ULong glyph_start;
+
+ FT_UInt tupleCount;
+ FT_ULong offsetToData;
+ FT_ULong dataSize;
+
+ FT_ULong here;
+ FT_UInt i, j;
+
+ FT_Fixed* tuple_coords = NULL;
+ FT_Fixed* im_start_coords = NULL;
+ FT_Fixed* im_end_coords = NULL;
+
+ GX_Blend blend = face->blend;
+
+ FT_UInt point_count;
+ FT_UInt spoint_count = 0;
+
FT_UShort* sharedpoints = NULL;
FT_UShort* localpoints = NULL;
FT_UShort* points;
- FT_Short *deltas_x, *deltas_y;
+
+ FT_Fixed* deltas_x = NULL;
+ FT_Fixed* deltas_y = NULL;
+ FT_Fixed* point_deltas_x = NULL;
+ FT_Fixed* point_deltas_y = NULL;
if ( !face->doblend || !blend )
@@ -3597,9 +3731,11 @@
FT_NEW_ARRAY( has_delta, n_points ) )
goto Fail1;
- if ( FT_STREAM_SEEK( blend->glyphoffsets[glyph_index] ) ||
- FT_FRAME_ENTER( blend->glyphoffsets[glyph_index + 1] -
- blend->glyphoffsets[glyph_index] ) )
+ dataSize = blend->glyphoffsets[glyph_index + 1] -
+ blend->glyphoffsets[glyph_index];
+
+ if ( FT_STREAM_SEEK( blend->glyphoffsets[glyph_index] ) ||
+ FT_FRAME_ENTER( dataSize ) )
goto Fail1;
glyph_start = FT_Stream_FTell( stream );
@@ -3615,8 +3751,8 @@
offsetToData = FT_GET_USHORT();
/* rough sanity test */
- if ( offsetToData + ( tupleCount & GX_TC_TUPLE_COUNT_MASK ) * 4 >
- blend->gvar_size )
+ if ( offsetToData > dataSize ||
+ ( tupleCount & GX_TC_TUPLE_COUNT_MASK ) * 4 > dataSize )
{
FT_TRACE2(( "TT_Vary_Apply_Glyph_Deltas:"
" invalid glyph variation array header\n" ));
@@ -3646,8 +3782,15 @@
tupleCount & GX_TC_TUPLE_COUNT_MASK,
( tupleCount & GX_TC_TUPLE_COUNT_MASK ) == 1 ? "" : "s" ));
+ if ( FT_NEW_ARRAY( point_deltas_x, n_points ) ||
+ FT_NEW_ARRAY( point_deltas_y, n_points ) )
+ goto Fail3;
+
for ( j = 0; j < n_points; j++ )
- points_org[j] = outline->points[j];
+ {
+ points_org[j].x = FT_intToFixed( outline->points[j].x );
+ points_org[j].y = FT_intToFixed( outline->points[j].y );
+ }
for ( i = 0; i < ( tupleCount & GX_TC_TUPLE_COUNT_MASK ); i++ )
{
@@ -3673,12 +3816,13 @@
" invalid tuple index\n" ));
error = FT_THROW( Invalid_Table );
- goto Fail2;
+ goto Fail3;
}
else
FT_MEM_COPY(
tuple_coords,
- &blend->tuplecoords[( tupleIndex & 0xFFF ) * blend->num_axis],
+ blend->tuplecoords +
+ ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) * blend->num_axis,
blend->num_axis * sizeof ( FT_Fixed ) );
if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
@@ -3742,14 +3886,17 @@
/* this means that there are deltas for every point in the glyph */
for ( j = 0; j < n_points; j++ )
{
- FT_Pos delta_x = FT_MulFix( deltas_x[j], apply );
- FT_Pos delta_y = FT_MulFix( deltas_y[j], apply );
+ FT_Fixed old_point_delta_x = point_deltas_x[j];
+ FT_Fixed old_point_delta_y = point_deltas_y[j];
+
+ FT_Fixed point_delta_x = FT_MulFix( deltas_x[j], apply );
+ FT_Fixed point_delta_y = FT_MulFix( deltas_y[j], apply );
if ( j < n_points - 4 )
{
- outline->points[j].x += delta_x;
- outline->points[j].y += delta_y;
+ point_deltas_x[j] = old_point_delta_x + point_delta_x;
+ point_deltas_y[j] = old_point_delta_y + point_delta_y;
}
else
{
@@ -3759,33 +3906,37 @@
if ( j == ( n_points - 4 ) &&
!( face->variation_support &
TT_FACE_FLAG_VAR_LSB ) )
- outline->points[j].x += delta_x;
+ point_deltas_x[j] = old_point_delta_x + point_delta_x;
else if ( j == ( n_points - 3 ) &&
!( face->variation_support &
TT_FACE_FLAG_VAR_HADVANCE ) )
- outline->points[j].x += delta_x;
+ point_deltas_x[j] = old_point_delta_x + point_delta_x;
else if ( j == ( n_points - 2 ) &&
!( face->variation_support &
TT_FACE_FLAG_VAR_TSB ) )
- outline->points[j].y += delta_y;
+ point_deltas_y[j] = old_point_delta_y + point_delta_y;
else if ( j == ( n_points - 1 ) &&
!( face->variation_support &
TT_FACE_FLAG_VAR_VADVANCE ) )
- outline->points[j].y += delta_y;
+ point_deltas_y[j] = old_point_delta_y + point_delta_y;
}
#ifdef FT_DEBUG_LEVEL_TRACE
- if ( delta_x || delta_y )
+ if ( point_delta_x || point_delta_y )
{
- FT_TRACE7(( " %d: (%d, %d) -> (%d, %d)\n",
+ FT_TRACE7(( " %d: (%f, %f) -> (%f, %f)\n",
j,
- outline->points[j].x - delta_x,
- outline->points[j].y - delta_y,
- outline->points[j].x,
- outline->points[j].y ));
+ ( FT_intToFixed( outline->points[j].x ) +
+ old_point_delta_x ) / 65536.0,
+ ( FT_intToFixed( outline->points[j].y ) +
+ old_point_delta_y ) / 65536.0,
+ ( FT_intToFixed( outline->points[j].x ) +
+ point_deltas_x[j] ) / 65536.0,
+ ( FT_intToFixed( outline->points[j].y ) +
+ point_deltas_y[j] ) / 65536.0 ));
count++;
}
#endif
@@ -3837,14 +3988,17 @@
for ( j = 0; j < n_points; j++ )
{
- FT_Pos delta_x = points_out[j].x - points_org[j].x;
- FT_Pos delta_y = points_out[j].y - points_org[j].y;
+ FT_Fixed old_point_delta_x = point_deltas_x[j];
+ FT_Fixed old_point_delta_y = point_deltas_y[j];
+
+ FT_Pos point_delta_x = points_out[j].x - points_org[j].x;
+ FT_Pos point_delta_y = points_out[j].y - points_org[j].y;
if ( j < n_points - 4 )
{
- outline->points[j].x += delta_x;
- outline->points[j].y += delta_y;
+ point_deltas_x[j] = old_point_delta_x + point_delta_x;
+ point_deltas_y[j] = old_point_delta_y + point_delta_y;
}
else
{
@@ -3854,33 +4008,37 @@
if ( j == ( n_points - 4 ) &&
!( face->variation_support &
TT_FACE_FLAG_VAR_LSB ) )
- outline->points[j].x += delta_x;
+ point_deltas_x[j] = old_point_delta_x + point_delta_x;
else if ( j == ( n_points - 3 ) &&
!( face->variation_support &
TT_FACE_FLAG_VAR_HADVANCE ) )
- outline->points[j].x += delta_x;
+ point_deltas_x[j] = old_point_delta_x + point_delta_x;
else if ( j == ( n_points - 2 ) &&
!( face->variation_support &
TT_FACE_FLAG_VAR_TSB ) )
- outline->points[j].y += delta_y;
+ point_deltas_y[j] = old_point_delta_y + point_delta_y;
else if ( j == ( n_points - 1 ) &&
!( face->variation_support &
TT_FACE_FLAG_VAR_VADVANCE ) )
- outline->points[j].y += delta_y;
+ point_deltas_y[j] = old_point_delta_y + point_delta_y;
}
#ifdef FT_DEBUG_LEVEL_TRACE
- if ( delta_x || delta_y )
+ if ( point_delta_x || point_delta_y )
{
- FT_TRACE7(( " %d: (%d, %d) -> (%d, %d)\n",
+ FT_TRACE7(( " %d: (%f, %f) -> (%f, %f)\n",
j,
- outline->points[j].x - delta_x,
- outline->points[j].y - delta_y,
- outline->points[j].x,
- outline->points[j].y ));
+ ( FT_intToFixed( outline->points[j].x ) +
+ old_point_delta_x ) / 65536.0,
+ ( FT_intToFixed( outline->points[j].y ) +
+ old_point_delta_y ) / 65536.0,
+ ( FT_intToFixed( outline->points[j].x ) +
+ point_deltas_x[j] ) / 65536.0,
+ ( FT_intToFixed( outline->points[j].y ) +
+ point_deltas_y[j] ) / 65536.0 ));
count++;
}
#endif
@@ -3904,6 +4062,16 @@
FT_TRACE5(( "\n" ));
+ for ( i = 0; i < n_points; i++ )
+ {
+ outline->points[i].x += FT_fixedToInt( point_deltas_x[i] );
+ outline->points[i].y += FT_fixedToInt( point_deltas_y[i] );
+ }
+
+ Fail3:
+ FT_FREE( point_deltas_x );
+ FT_FREE( point_deltas_y );
+
Fail2:
if ( sharedpoints != ALL_POINTS )
FT_FREE( sharedpoints );
@@ -3922,16 +4090,16 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_get_var_blend */
- /* */
- /* <Description> */
- /* An extended internal version of `TT_Get_MM_Blend' that returns */
- /* pointers instead of copying data, without any initialization of */
- /* the MM machinery in case it isn't loaded yet. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_get_var_blend
+ *
+ * @Description:
+ * An extended internal version of `TT_Get_MM_Blend' that returns
+ * pointers instead of copying data, without any initialization of
+ * the MM machinery in case it isn't loaded yet.
+ */
FT_LOCAL_DEF( FT_Error )
tt_get_var_blend( TT_Face face,
FT_UInt *num_coords,
@@ -3993,14 +4161,14 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_done_blend */
- /* */
- /* <Description> */
- /* Free the blend internal data structure. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_done_blend
+ *
+ * @Description:
+ * Free the blend internal data structure.
+ */
FT_LOCAL_DEF( void )
tt_done_blend( TT_Face face )
{
diff --git a/thirdparty/freetype/src/truetype/ttgxvar.h b/thirdparty/freetype/src/truetype/ttgxvar.h
index a37bb90266..7e8d9768a7 100644
--- a/thirdparty/freetype/src/truetype/ttgxvar.h
+++ b/thirdparty/freetype/src/truetype/ttgxvar.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ttgxvar.h */
-/* */
-/* TrueType GX Font Variation loader (specification) */
-/* */
-/* Copyright 2004-2018 by */
-/* David Turner, Robert Wilhelm, Werner Lemberg and George Williams. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ttgxvar.h
+ *
+ * TrueType GX Font Variation loader (specification)
+ *
+ * Copyright (C) 2004-2019 by
+ * David Turner, Robert Wilhelm, Werner Lemberg and George Williams.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef TTGXVAR_H_
@@ -29,15 +29,15 @@ FT_BEGIN_HEADER
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* GX_AVarCorrespondenceRec */
- /* */
- /* <Description> */
- /* A data structure representing `shortFracCorrespondence' in `avar' */
- /* table according to the specifications from Apple. */
- /* */
+ /**************************************************************************
+ *
+ * @Struct:
+ * GX_AVarCorrespondenceRec
+ *
+ * @Description:
+ * A data structure representing `shortFracCorrespondence' in `avar'
+ * table according to the specifications from Apple.
+ */
typedef struct GX_AVarCorrespondenceRec_
{
FT_Fixed fromCoord;
@@ -46,15 +46,15 @@ FT_BEGIN_HEADER
} GX_AVarCorrespondenceRec_, *GX_AVarCorrespondence;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* GX_AVarRec */
- /* */
- /* <Description> */
- /* Data from the segment field of `avar' table. */
- /* There is one of these for each axis. */
- /* */
+ /**************************************************************************
+ *
+ * @Struct:
+ * GX_AVarRec
+ *
+ * @Description:
+ * Data from the segment field of `avar' table.
+ * There is one of these for each axis.
+ */
typedef struct GX_AVarSegmentRec_
{
FT_UShort pairCount;
@@ -114,14 +114,14 @@ FT_BEGIN_HEADER
} GX_DeltaSetIdxMapRec, *GX_DeltaSetIdxMap;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* GX_HVVarTableRec */
- /* */
- /* <Description> */
- /* Data from either the `HVAR' or `VVAR' table. */
- /* */
+ /**************************************************************************
+ *
+ * @Struct:
+ * GX_HVVarTableRec
+ *
+ * @Description:
+ * Data from either the `HVAR' or `VVAR' table.
+ */
typedef struct GX_HVVarTableRec_
{
GX_ItemVarStoreRec itemStore; /* Item Variation Store */
@@ -191,14 +191,14 @@ FT_BEGIN_HEADER
} GX_ValueRec, *GX_Value;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* GX_MVarTableRec */
- /* */
- /* <Description> */
- /* Data from the `MVAR' table. */
- /* */
+ /**************************************************************************
+ *
+ * @Struct:
+ * GX_MVarTableRec
+ *
+ * @Description:
+ * Data from the `MVAR' table.
+ */
typedef struct GX_MVarTableRec_
{
FT_UShort valueCount;
@@ -209,95 +209,95 @@ FT_BEGIN_HEADER
} GX_MVarTableRec, *GX_MVarTable;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* GX_BlendRec */
- /* */
- /* <Description> */
- /* Data for interpolating a font from a distortable font specified */
- /* by the GX *var tables ([fgcahvm]var). */
- /* */
- /* <Fields> */
- /* num_axis :: */
- /* The number of axes along which interpolation may happen. */
- /* */
- /* coords :: */
- /* An array of design coordinates (in user space) indicating the */
- /* contribution along each axis to the final interpolated font. */
- /* `normalizedcoords' holds the same values. */
- /* */
- /* normalizedcoords :: */
- /* An array of normalized values (between [-1,1]) indicating the */
- /* contribution along each axis to the final interpolated font. */
- /* `coords' holds the same values. */
- /* */
- /* mmvar :: */
- /* Data from the `fvar' table. */
- /* */
- /* mmvar_len :: */
- /* The length of the `mmvar' structure. */
- /* */
- /* normalized_stylecoords :: */
- /* A two-dimensional array that holds the named instance data from */
- /* `mmvar' as normalized values. */
- /* */
- /* avar_loaded :: */
- /* A Boolean; if set, FreeType tried to load (and parse) the `avar' */
- /* table. */
- /* */
- /* avar_segment :: */
- /* Data from the `avar' table. */
- /* */
- /* hvar_loaded :: */
- /* A Boolean; if set, FreeType tried to load (and parse) the `hvar' */
- /* table. */
- /* */
- /* hvar_checked :: */
- /* A Boolean; if set, FreeType successfully loaded and parsed the */
- /* `hvar' table. */
- /* */
- /* hvar_error :: */
- /* If loading and parsing of the `hvar' table failed, this field */
- /* holds the corresponding error code. */
- /* */
- /* hvar_table :: */
- /* Data from the `hvar' table. */
- /* */
- /* vvar_loaded :: */
- /* A Boolean; if set, FreeType tried to load (and parse) the `vvar' */
- /* table. */
- /* */
- /* vvar_checked :: */
- /* A Boolean; if set, FreeType successfully loaded and parsed the */
- /* `vvar' table. */
- /* */
- /* vvar_error :: */
- /* If loading and parsing of the `vvar' table failed, this field */
- /* holds the corresponding error code. */
- /* */
- /* vvar_table :: */
- /* Data from the `vvar' table. */
- /* */
- /* mvar_table :: */
- /* Data from the `mvar' table. */
- /* */
- /* tuplecount :: */
- /* The number of shared tuples in the `gvar' table. */
- /* */
- /* tuplecoords :: */
- /* A two-dimensional array that holds the shared tuple coordinates */
- /* in the `gvar' table. */
- /* */
- /* gv_glyphcnt :: */
- /* The number of glyphs handled in the `gvar' table. */
- /* */
- /* glyphoffsets :: */
- /* Offsets into the glyph variation data array. */
- /* */
- /* gvar_size :: */
- /* The size of the `gvar' table. */
- /* */
+ /**************************************************************************
+ *
+ * @Struct:
+ * GX_BlendRec
+ *
+ * @Description:
+ * Data for interpolating a font from a distortable font specified
+ * by the GX *var tables ([fgcahvm]var).
+ *
+ * @Fields:
+ * num_axis ::
+ * The number of axes along which interpolation may happen.
+ *
+ * coords ::
+ * An array of design coordinates (in user space) indicating the
+ * contribution along each axis to the final interpolated font.
+ * `normalizedcoords' holds the same values.
+ *
+ * normalizedcoords ::
+ * An array of normalized values (between [-1,1]) indicating the
+ * contribution along each axis to the final interpolated font.
+ * `coords' holds the same values.
+ *
+ * mmvar ::
+ * Data from the `fvar' table.
+ *
+ * mmvar_len ::
+ * The length of the `mmvar' structure.
+ *
+ * normalized_stylecoords ::
+ * A two-dimensional array that holds the named instance data from
+ * `mmvar' as normalized values.
+ *
+ * avar_loaded ::
+ * A Boolean; if set, FreeType tried to load (and parse) the `avar'
+ * table.
+ *
+ * avar_segment ::
+ * Data from the `avar' table.
+ *
+ * hvar_loaded ::
+ * A Boolean; if set, FreeType tried to load (and parse) the `hvar'
+ * table.
+ *
+ * hvar_checked ::
+ * A Boolean; if set, FreeType successfully loaded and parsed the
+ * `hvar' table.
+ *
+ * hvar_error ::
+ * If loading and parsing of the `hvar' table failed, this field
+ * holds the corresponding error code.
+ *
+ * hvar_table ::
+ * Data from the `hvar' table.
+ *
+ * vvar_loaded ::
+ * A Boolean; if set, FreeType tried to load (and parse) the `vvar'
+ * table.
+ *
+ * vvar_checked ::
+ * A Boolean; if set, FreeType successfully loaded and parsed the
+ * `vvar' table.
+ *
+ * vvar_error ::
+ * If loading and parsing of the `vvar' table failed, this field
+ * holds the corresponding error code.
+ *
+ * vvar_table ::
+ * Data from the `vvar' table.
+ *
+ * mvar_table ::
+ * Data from the `mvar' table.
+ *
+ * tuplecount ::
+ * The number of shared tuples in the `gvar' table.
+ *
+ * tuplecoords ::
+ * A two-dimensional array that holds the shared tuple coordinates
+ * in the `gvar' table.
+ *
+ * gv_glyphcnt ::
+ * The number of glyphs handled in the `gvar' table.
+ *
+ * glyphoffsets ::
+ * Offsets into the glyph variation data array.
+ *
+ * gvar_size ::
+ * The size of the `gvar' table.
+ */
typedef struct GX_BlendRec_
{
FT_UInt num_axis;
@@ -336,14 +336,14 @@ FT_BEGIN_HEADER
} GX_BlendRec;
- /*************************************************************************/
- /* */
- /* <enum> */
- /* GX_TupleCountFlags */
- /* */
- /* <Description> */
- /* Flags used within the `TupleCount' field of the `gvar' table. */
- /* */
+ /**************************************************************************
+ *
+ * @enum:
+ * GX_TupleCountFlags
+ *
+ * @Description:
+ * Flags used within the `TupleCount' field of the `gvar' table.
+ */
typedef enum GX_TupleCountFlags_
{
GX_TC_TUPLES_SHARE_POINT_NUMBERS = 0x8000,
@@ -353,15 +353,15 @@ FT_BEGIN_HEADER
} GX_TupleCountFlags;
- /*************************************************************************/
- /* */
- /* <enum> */
- /* GX_TupleIndexFlags */
- /* */
- /* <Description> */
- /* Flags used within the `TupleIndex' field of the `gvar' and `cvar' */
- /* tables. */
- /* */
+ /**************************************************************************
+ *
+ * @enum:
+ * GX_TupleIndexFlags
+ *
+ * @Description:
+ * Flags used within the `TupleIndex' field of the `gvar' and `cvar'
+ * tables.
+ */
typedef enum GX_TupleIndexFlags_
{
GX_TI_EMBEDDED_TUPLE_COORD = 0x8000,
diff --git a/thirdparty/freetype/src/truetype/ttinterp.c b/thirdparty/freetype/src/truetype/ttinterp.c
index da9b595aba..403f3753c7 100644
--- a/thirdparty/freetype/src/truetype/ttinterp.c
+++ b/thirdparty/freetype/src/truetype/ttinterp.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ttinterp.c */
-/* */
-/* TrueType bytecode interpreter (body). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ttinterp.c
+ *
+ * TrueType bytecode interpreter (body).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
/* Greg Hitchcock from Microsoft has helped a lot in resolving unclear */
@@ -39,14 +39,14 @@
#ifdef TT_USE_BYTECODE_INTERPRETER
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_ttinterp
+#define FT_COMPONENT ttinterp
#define NO_SUBPIXEL_HINTING \
@@ -82,10 +82,10 @@
exc->func_dualproj( exc, (v)->x, (v)->y )
- /*************************************************************************/
- /* */
- /* Two simple bounds-checking macros. */
- /* */
+ /**************************************************************************
+ *
+ * Two simple bounds-checking macros.
+ */
#define BOUNDS( x, n ) ( (FT_UInt)(x) >= (FT_UInt)(n) )
#define BOUNDSL( x, n ) ( (FT_ULong)(x) >= (FT_ULong)(n) )
@@ -97,30 +97,33 @@
#define FAILURE 1
- /*************************************************************************/
- /* */
- /* CODERANGE FUNCTIONS */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* TT_Goto_CodeRange */
- /* */
- /* <Description> */
- /* Switches to a new code range (updates the code related elements in */
- /* `exec', and `IP'). */
- /* */
- /* <Input> */
- /* range :: The new execution code range. */
- /* */
- /* IP :: The new IP in the new code range. */
- /* */
- /* <InOut> */
- /* exec :: The target execution context. */
- /* */
+ /**************************************************************************
+ *
+ * CODERANGE FUNCTIONS
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @Function:
+ * TT_Goto_CodeRange
+ *
+ * @Description:
+ * Switches to a new code range (updates the code related elements in
+ * `exec', and `IP').
+ *
+ * @Input:
+ * range ::
+ * The new execution code range.
+ *
+ * IP ::
+ * The new IP in the new code range.
+ *
+ * @InOut:
+ * exec ::
+ * The target execution context.
+ */
FT_LOCAL_DEF( void )
TT_Goto_CodeRange( TT_ExecContext exec,
FT_Int range,
@@ -148,24 +151,28 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* TT_Set_CodeRange */
- /* */
- /* <Description> */
- /* Sets a code range. */
- /* */
- /* <Input> */
- /* range :: The code range index. */
- /* */
- /* base :: The new code base. */
- /* */
- /* length :: The range size in bytes. */
- /* */
- /* <InOut> */
- /* exec :: The target execution context. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * TT_Set_CodeRange
+ *
+ * @Description:
+ * Sets a code range.
+ *
+ * @Input:
+ * range ::
+ * The code range index.
+ *
+ * base ::
+ * The new code base.
+ *
+ * length ::
+ * The range size in bytes.
+ *
+ * @InOut:
+ * exec ::
+ * The target execution context.
+ */
FT_LOCAL_DEF( void )
TT_Set_CodeRange( TT_ExecContext exec,
FT_Int range,
@@ -179,20 +186,22 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* TT_Clear_CodeRange */
- /* */
- /* <Description> */
- /* Clears a code range. */
- /* */
- /* <Input> */
- /* range :: The code range index. */
- /* */
- /* <InOut> */
- /* exec :: The target execution context. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * TT_Clear_CodeRange
+ *
+ * @Description:
+ * Clears a code range.
+ *
+ * @Input:
+ * range ::
+ * The code range index.
+ *
+ * @InOut:
+ * exec ::
+ * The target execution context.
+ */
FT_LOCAL_DEF( void )
TT_Clear_CodeRange( TT_ExecContext exec,
FT_Int range )
@@ -204,29 +213,31 @@
}
- /*************************************************************************/
- /* */
- /* EXECUTION CONTEXT ROUTINES */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* TT_Done_Context */
- /* */
- /* <Description> */
- /* Destroys a given context. */
- /* */
- /* <Input> */
- /* exec :: A handle to the target execution context. */
- /* */
- /* memory :: A handle to the parent memory object. */
- /* */
- /* <Note> */
- /* Only the glyph loader and debugger should call this function. */
- /* */
+ /**************************************************************************
+ *
+ * EXECUTION CONTEXT ROUTINES
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @Function:
+ * TT_Done_Context
+ *
+ * @Description:
+ * Destroys a given context.
+ *
+ * @Input:
+ * exec ::
+ * A handle to the target execution context.
+ *
+ * memory ::
+ * A handle to the parent memory object.
+ *
+ * @Note:
+ * Only the glyph loader and debugger should call this function.
+ */
FT_LOCAL_DEF( void )
TT_Done_Context( TT_ExecContext exec )
{
@@ -257,23 +268,25 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Init_Context */
- /* */
- /* <Description> */
- /* Initializes a context object. */
- /* */
- /* <Input> */
- /* memory :: A handle to the parent memory object. */
- /* */
- /* <InOut> */
- /* exec :: A handle to the target execution context. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * Init_Context
+ *
+ * @Description:
+ * Initializes a context object.
+ *
+ * @Input:
+ * memory ::
+ * A handle to the parent memory object.
+ *
+ * @InOut:
+ * exec ::
+ * A handle to the target execution context.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
static FT_Error
Init_Context( TT_ExecContext exec,
FT_Memory memory )
@@ -313,30 +326,35 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Update_Max */
- /* */
- /* <Description> */
- /* Checks the size of a buffer and reallocates it if necessary. */
- /* */
- /* <Input> */
- /* memory :: A handle to the parent memory object. */
- /* */
- /* multiplier :: The size in bytes of each element in the buffer. */
- /* */
- /* new_max :: The new capacity (size) of the buffer. */
- /* */
- /* <InOut> */
- /* size :: The address of the buffer's current size expressed */
- /* in elements. */
- /* */
- /* buff :: The address of the buffer base pointer. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * Update_Max
+ *
+ * @Description:
+ * Checks the size of a buffer and reallocates it if necessary.
+ *
+ * @Input:
+ * memory ::
+ * A handle to the parent memory object.
+ *
+ * multiplier ::
+ * The size in bytes of each element in the buffer.
+ *
+ * new_max ::
+ * The new capacity (size) of the buffer.
+ *
+ * @InOut:
+ * size ::
+ * The address of the buffer's current size expressed
+ * in elements.
+ *
+ * buff ::
+ * The address of the buffer base pointer.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
Update_Max( FT_Memory memory,
FT_ULong* size,
@@ -359,28 +377,31 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* TT_Load_Context */
- /* */
- /* <Description> */
- /* Prepare an execution context for glyph hinting. */
- /* */
- /* <Input> */
- /* face :: A handle to the source face object. */
- /* */
- /* size :: A handle to the source size object. */
- /* */
- /* <InOut> */
- /* exec :: A handle to the target execution context. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- /* <Note> */
- /* Only the glyph loader and debugger should call this function. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * TT_Load_Context
+ *
+ * @Description:
+ * Prepare an execution context for glyph hinting.
+ *
+ * @Input:
+ * face ::
+ * A handle to the source face object.
+ *
+ * size ::
+ * A handle to the source size object.
+ *
+ * @InOut:
+ * exec ::
+ * A handle to the target execution context.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ *
+ * @Note:
+ * Only the glyph loader and debugger should call this function.
+ */
FT_LOCAL_DEF( FT_Error )
TT_Load_Context( TT_ExecContext exec,
TT_Face face,
@@ -467,23 +488,25 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* TT_Save_Context */
- /* */
- /* <Description> */
- /* Saves the code ranges in a `size' object. */
- /* */
- /* <Input> */
- /* exec :: A handle to the source execution context. */
- /* */
- /* <InOut> */
- /* size :: A handle to the target size object. */
- /* */
- /* <Note> */
- /* Only the glyph loader and debugger should call this function. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * TT_Save_Context
+ *
+ * @Description:
+ * Saves the code ranges in a `size' object.
+ *
+ * @Input:
+ * exec ::
+ * A handle to the source execution context.
+ *
+ * @InOut:
+ * size ::
+ * A handle to the target size object.
+ *
+ * @Note:
+ * Only the glyph loader and debugger should call this function.
+ */
FT_LOCAL_DEF( void )
TT_Save_Context( TT_ExecContext exec,
TT_Size size )
@@ -505,27 +528,21 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* TT_Run_Context */
- /* */
- /* <Description> */
- /* Executes one or more instructions in the execution context. */
- /* */
- /* <Input> */
- /* debug :: A Boolean flag. If set, the function sets some internal */
- /* variables and returns immediately, otherwise TT_RunIns() */
- /* is called. */
- /* */
- /* This is commented out currently. */
- /* */
- /* <Input> */
- /* exec :: A handle to the target execution context. */
- /* */
- /* <Return> */
- /* TrueType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * TT_Run_Context
+ *
+ * @Description:
+ * Executes one or more instructions in the execution context.
+ *
+ * @Input:
+ * exec ::
+ * A handle to the target execution context.
+ *
+ * @Return:
+ * TrueType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
TT_Run_Context( TT_ExecContext exec )
{
@@ -609,22 +626,22 @@
}
- /*************************************************************************/
- /* */
- /* Before an opcode is executed, the interpreter verifies that there are */
- /* enough arguments on the stack, with the help of the `Pop_Push_Count' */
- /* table. */
- /* */
- /* For each opcode, the first column gives the number of arguments that */
- /* are popped from the stack; the second one gives the number of those */
- /* that are pushed in result. */
- /* */
- /* Opcodes which have a varying number of parameters in the data stream */
- /* (NPUSHB, NPUSHW) are handled specially; they have a negative value in */
- /* the `opcode_length' table, and the value in `Pop_Push_Count' is set */
- /* to zero. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * Before an opcode is executed, the interpreter verifies that there are
+ * enough arguments on the stack, with the help of the `Pop_Push_Count'
+ * table.
+ *
+ * For each opcode, the first column gives the number of arguments that
+ * are popped from the stack; the second one gives the number of those
+ * that are pushed in result.
+ *
+ * Opcodes which have a varying number of parameters in the data stream
+ * (NPUSHB, NPUSHW) are handled specially; they have a negative value in
+ * the `opcode_length' table, and the value in `Pop_Push_Count' is set
+ * to zero.
+ *
+ */
#undef PACK
@@ -1129,73 +1146,73 @@
"8 PushW[6]",
"8 PushW[7]",
- "8 MDRP[00]",
- "8 MDRP[01]",
- "8 MDRP[02]",
- "8 MDRP[03]",
- "8 MDRP[04]",
- "8 MDRP[05]",
- "8 MDRP[06]",
- "8 MDRP[07]",
- "8 MDRP[08]",
- "8 MDRP[09]",
- "8 MDRP[10]",
- "8 MDRP[11]",
- "8 MDRP[12]",
- "8 MDRP[13]",
- "8 MDRP[14]",
- "8 MDRP[15]",
-
- "8 MDRP[16]",
- "8 MDRP[17]",
- "8 MDRP[18]",
- "8 MDRP[19]",
- "8 MDRP[20]",
- "8 MDRP[21]",
- "8 MDRP[22]",
- "8 MDRP[23]",
- "8 MDRP[24]",
- "8 MDRP[25]",
- "8 MDRP[26]",
- "8 MDRP[27]",
- "8 MDRP[28]",
- "8 MDRP[29]",
- "8 MDRP[30]",
- "8 MDRP[31]",
-
- "8 MIRP[00]",
- "8 MIRP[01]",
- "8 MIRP[02]",
- "8 MIRP[03]",
- "8 MIRP[04]",
- "8 MIRP[05]",
- "8 MIRP[06]",
- "8 MIRP[07]",
- "8 MIRP[08]",
- "8 MIRP[09]",
- "8 MIRP[10]",
- "8 MIRP[11]",
- "8 MIRP[12]",
- "8 MIRP[13]",
- "8 MIRP[14]",
- "8 MIRP[15]",
-
- "8 MIRP[16]",
- "8 MIRP[17]",
- "8 MIRP[18]",
- "8 MIRP[19]",
- "8 MIRP[20]",
- "8 MIRP[21]",
- "8 MIRP[22]",
- "8 MIRP[23]",
- "8 MIRP[24]",
- "8 MIRP[25]",
- "8 MIRP[26]",
- "8 MIRP[27]",
- "8 MIRP[28]",
- "8 MIRP[29]",
- "8 MIRP[30]",
- "8 MIRP[31]"
+ "7 MDRP[G]",
+ "7 MDRP[B]",
+ "7 MDRP[W]",
+ "7 MDRP[?]",
+ "8 MDRP[rG]",
+ "8 MDRP[rB]",
+ "8 MDRP[rW]",
+ "8 MDRP[r?]",
+ "8 MDRP[mG]",
+ "8 MDRP[mB]",
+ "8 MDRP[mW]",
+ "8 MDRP[m?]",
+ "9 MDRP[mrG]",
+ "9 MDRP[mrB]",
+ "9 MDRP[mrW]",
+ "9 MDRP[mr?]",
+
+ "8 MDRP[pG]",
+ "8 MDRP[pB]",
+ "8 MDRP[pW]",
+ "8 MDRP[p?]",
+ "9 MDRP[prG]",
+ "9 MDRP[prB]",
+ "9 MDRP[prW]",
+ "9 MDRP[pr?]",
+ "9 MDRP[pmG]",
+ "9 MDRP[pmB]",
+ "9 MDRP[pmW]",
+ "9 MDRP[pm?]",
+ "A MDRP[pmrG]",
+ "A MDRP[pmrB]",
+ "A MDRP[pmrW]",
+ "A MDRP[pmr?]",
+
+ "7 MIRP[G]",
+ "7 MIRP[B]",
+ "7 MIRP[W]",
+ "7 MIRP[?]",
+ "8 MIRP[rG]",
+ "8 MIRP[rB]",
+ "8 MIRP[rW]",
+ "8 MIRP[r?]",
+ "8 MIRP[mG]",
+ "8 MIRP[mB]",
+ "8 MIRP[mW]",
+ "8 MIRP[m?]",
+ "9 MIRP[mrG]",
+ "9 MIRP[mrB]",
+ "9 MIRP[mrW]",
+ "9 MIRP[mr?]",
+
+ "8 MIRP[pG]",
+ "8 MIRP[pB]",
+ "8 MIRP[pW]",
+ "8 MIRP[p?]",
+ "9 MIRP[prG]",
+ "9 MIRP[prB]",
+ "9 MIRP[prW]",
+ "9 MIRP[pr?]",
+ "9 MIRP[pmG]",
+ "9 MIRP[pmB]",
+ "9 MIRP[pmW]",
+ "9 MIRP[pm?]",
+ "A MIRP[pmrG]",
+ "A MIRP[pmrB]",
+ "A MIRP[pmrW]",
+ "A MIRP[pmr?]"
};
#endif /* FT_DEBUG_LEVEL_TRACE */
@@ -1448,18 +1465,18 @@
#endif /* TT_DotFix14 */
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Current_Ratio */
- /* */
- /* <Description> */
- /* Returns the current aspect ratio scaling factor depending on the */
- /* projection vector's state and device resolutions. */
- /* */
- /* <Return> */
- /* The aspect ratio in 16.16 format, always <= 1.0 . */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * Current_Ratio
+ *
+ * @Description:
+ * Returns the current aspect ratio scaling factor depending on the
+ * projection vector's state and device resolutions.
+ *
+ * @Return:
+ * The aspect ratio in 16.16 format, always <= 1.0 .
+ */
static FT_Long
Current_Ratio( TT_ExecContext exc )
{
@@ -1501,11 +1518,11 @@
}
- /*************************************************************************/
- /* */
- /* Functions related to the control value table (CVT). */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * Functions related to the control value table (CVT).
+ *
+ */
FT_CALLBACK_DEF( FT_F26Dot6 )
@@ -1547,7 +1564,7 @@
FT_ULong idx,
FT_F26Dot6 value )
{
- exc->cvt[idx] += value;
+ exc->cvt[idx] = ADD_LONG( exc->cvt[idx], value );
}
@@ -1556,25 +1573,26 @@
FT_ULong idx,
FT_F26Dot6 value )
{
- exc->cvt[idx] += FT_DivFix( value, Current_Ratio( exc ) );
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* GetShortIns */
- /* */
- /* <Description> */
- /* Returns a short integer taken from the instruction stream at */
- /* address IP. */
- /* */
- /* <Return> */
- /* Short read at code[IP]. */
- /* */
- /* <Note> */
- /* This one could become a macro. */
- /* */
+ exc->cvt[idx] = ADD_LONG( exc->cvt[idx],
+ FT_DivFix( value, Current_Ratio( exc ) ) );
+ }
+
+
+ /**************************************************************************
+ *
+ * @Function:
+ * GetShortIns
+ *
+ * @Description:
+ * Returns a short integer taken from the instruction stream at
+ * address IP.
+ *
+ * @Return:
+ * Short read at code[IP].
+ *
+ * @Note:
+ * This one could become a macro.
+ */
static FT_Short
GetShortIns( TT_ExecContext exc )
{
@@ -1585,22 +1603,24 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Ins_Goto_CodeRange */
- /* */
- /* <Description> */
- /* Goes to a certain code range in the instruction stream. */
- /* */
- /* <Input> */
- /* aRange :: The index of the code range. */
- /* */
- /* aIP :: The new IP address in the code range. */
- /* */
- /* <Return> */
- /* SUCCESS or FAILURE. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * Ins_Goto_CodeRange
+ *
+ * @Description:
+ * Goes to a certain code range in the instruction stream.
+ *
+ * @Input:
+ * aRange ::
+ * The index of the code range.
+ *
+ * aIP ::
+ * The new IP address in the code range.
+ *
+ * @Return:
+ * SUCCESS or FAILURE.
+ */
static FT_Bool
Ins_Goto_CodeRange( TT_ExecContext exc,
FT_Int aRange,
@@ -1642,27 +1662,30 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Direct_Move */
- /* */
- /* <Description> */
- /* Moves a point by a given distance along the freedom vector. The */
- /* point will be `touched'. */
- /* */
- /* <Input> */
- /* point :: The index of the point to move. */
- /* */
- /* distance :: The distance to apply. */
- /* */
- /* <InOut> */
- /* zone :: The affected glyph zone. */
- /* */
- /* <Note> */
- /* See `ttinterp.h' for details on backward compatibility mode. */
- /* `Touches' the point. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * Direct_Move
+ *
+ * @Description:
+ * Moves a point by a given distance along the freedom vector. The
+ * point will be `touched'.
+ *
+ * @Input:
+ * point ::
+ * The index of the point to move.
+ *
+ * distance ::
+ * The distance to apply.
+ *
+ * @InOut:
+ * zone ::
+ * The affected glyph zone.
+ *
+ * @Note:
+ * See `ttinterp.h' for details on backward compatibility mode.
+ * `Touches' the point.
+ */
static void
Direct_Move( TT_ExecContext exc,
TT_GlyphZone zone,
@@ -1728,23 +1751,26 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Direct_Move_Orig */
- /* */
- /* <Description> */
- /* Moves the *original* position of a point by a given distance along */
- /* the freedom vector. Obviously, the point will not be `touched'. */
- /* */
- /* <Input> */
- /* point :: The index of the point to move. */
- /* */
- /* distance :: The distance to apply. */
- /* */
- /* <InOut> */
- /* zone :: The affected glyph zone. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * Direct_Move_Orig
+ *
+ * @Description:
+ * Moves the *original* position of a point by a given distance along
+ * the freedom vector. Obviously, the point will not be `touched'.
+ *
+ * @Input:
+ * point ::
+ * The index of the point to move.
+ *
+ * distance ::
+ * The distance to apply.
+ *
+ * @InOut:
+ * zone ::
+ * The affected glyph zone.
+ */
static void
Direct_Move_Orig( TT_ExecContext exc,
TT_GlyphZone zone,
@@ -1772,15 +1798,15 @@
}
- /*************************************************************************/
- /* */
- /* Special versions of Direct_Move() */
- /* */
- /* The following versions are used whenever both vectors are both */
- /* along one of the coordinate unit vectors, i.e. in 90% of the cases. */
- /* See `ttinterp.h' for details on backward compatibility mode. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * Special versions of Direct_Move()
+ *
+ * The following versions are used whenever both vectors are both
+ * along one of the coordinate unit vectors, i.e. in 90% of the cases.
+ * See `ttinterp.h' for details on backward compatibility mode.
+ *
+ */
static void
@@ -1827,14 +1853,14 @@
}
- /*************************************************************************/
- /* */
- /* Special versions of Direct_Move_Orig() */
- /* */
- /* The following versions are used whenever both vectors are both */
- /* along one of the coordinate unit vectors, i.e. in 90% of the cases. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * Special versions of Direct_Move_Orig()
+ *
+ * The following versions are used whenever both vectors are both
+ * along one of the coordinate unit vectors, i.e. in 90% of the cases.
+ *
+ */
static void
@@ -1861,28 +1887,30 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Round_None */
- /* */
- /* <Description> */
- /* Does not round, but adds engine compensation. */
- /* */
- /* <Input> */
- /* distance :: The distance (not) to round. */
- /* */
- /* compensation :: The engine compensation. */
- /* */
- /* <Return> */
- /* The compensated distance. */
- /* */
- /* <Note> */
- /* The TrueType specification says very few about the relationship */
- /* between rounding and engine compensation. However, it seems from */
- /* the description of super round that we should add the compensation */
- /* before rounding. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * Round_None
+ *
+ * @Description:
+ * Does not round, but adds engine compensation.
+ *
+ * @Input:
+ * distance ::
+ * The distance (not) to round.
+ *
+ * compensation ::
+ * The engine compensation.
+ *
+ * @Return:
+ * The compensated distance.
+ *
+ * @Note:
+ * The TrueType specification says very few about the relationship
+ * between rounding and engine compensation. However, it seems from
+ * the description of super round that we should add the compensation
+ * before rounding.
+ */
static FT_F26Dot6
Round_None( TT_ExecContext exc,
FT_F26Dot6 distance,
@@ -1909,22 +1937,24 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Round_To_Grid */
- /* */
- /* <Description> */
- /* Rounds value to grid after adding engine compensation. */
- /* */
- /* <Input> */
- /* distance :: The distance to round. */
- /* */
- /* compensation :: The engine compensation. */
- /* */
- /* <Return> */
- /* Rounded distance. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * Round_To_Grid
+ *
+ * @Description:
+ * Rounds value to grid after adding engine compensation.
+ *
+ * @Input:
+ * distance ::
+ * The distance to round.
+ *
+ * compensation ::
+ * The engine compensation.
+ *
+ * @Return:
+ * Rounded distance.
+ */
static FT_F26Dot6
Round_To_Grid( TT_ExecContext exc,
FT_F26Dot6 distance,
@@ -1953,22 +1983,24 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Round_To_Half_Grid */
- /* */
- /* <Description> */
- /* Rounds value to half grid after adding engine compensation. */
- /* */
- /* <Input> */
- /* distance :: The distance to round. */
- /* */
- /* compensation :: The engine compensation. */
- /* */
- /* <Return> */
- /* Rounded distance. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * Round_To_Half_Grid
+ *
+ * @Description:
+ * Rounds value to half grid after adding engine compensation.
+ *
+ * @Input:
+ * distance ::
+ * The distance to round.
+ *
+ * compensation ::
+ * The engine compensation.
+ *
+ * @Return:
+ * Rounded distance.
+ */
static FT_F26Dot6
Round_To_Half_Grid( TT_ExecContext exc,
FT_F26Dot6 distance,
@@ -1999,22 +2031,24 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Round_Down_To_Grid */
- /* */
- /* <Description> */
- /* Rounds value down to grid after adding engine compensation. */
- /* */
- /* <Input> */
- /* distance :: The distance to round. */
- /* */
- /* compensation :: The engine compensation. */
- /* */
- /* <Return> */
- /* Rounded distance. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * Round_Down_To_Grid
+ *
+ * @Description:
+ * Rounds value down to grid after adding engine compensation.
+ *
+ * @Input:
+ * distance ::
+ * The distance to round.
+ *
+ * compensation ::
+ * The engine compensation.
+ *
+ * @Return:
+ * Rounded distance.
+ */
static FT_F26Dot6
Round_Down_To_Grid( TT_ExecContext exc,
FT_F26Dot6 distance,
@@ -2042,22 +2076,24 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Round_Up_To_Grid */
- /* */
- /* <Description> */
- /* Rounds value up to grid after adding engine compensation. */
- /* */
- /* <Input> */
- /* distance :: The distance to round. */
- /* */
- /* compensation :: The engine compensation. */
- /* */
- /* <Return> */
- /* Rounded distance. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * Round_Up_To_Grid
+ *
+ * @Description:
+ * Rounds value up to grid after adding engine compensation.
+ *
+ * @Input:
+ * distance ::
+ * The distance to round.
+ *
+ * compensation ::
+ * The engine compensation.
+ *
+ * @Return:
+ * Rounded distance.
+ */
static FT_F26Dot6
Round_Up_To_Grid( TT_ExecContext exc,
FT_F26Dot6 distance,
@@ -2086,22 +2122,24 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Round_To_Double_Grid */
- /* */
- /* <Description> */
- /* Rounds value to double grid after adding engine compensation. */
- /* */
- /* <Input> */
- /* distance :: The distance to round. */
- /* */
- /* compensation :: The engine compensation. */
- /* */
- /* <Return> */
- /* Rounded distance. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * Round_To_Double_Grid
+ *
+ * @Description:
+ * Rounds value to double grid after adding engine compensation.
+ *
+ * @Input:
+ * distance ::
+ * The distance to round.
+ *
+ * compensation ::
+ * The engine compensation.
+ *
+ * @Return:
+ * Rounded distance.
+ */
static FT_F26Dot6
Round_To_Double_Grid( TT_ExecContext exc,
FT_F26Dot6 distance,
@@ -2130,28 +2168,30 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Round_Super */
- /* */
- /* <Description> */
- /* Super-rounds value to grid after adding engine compensation. */
- /* */
- /* <Input> */
- /* distance :: The distance to round. */
- /* */
- /* compensation :: The engine compensation. */
- /* */
- /* <Return> */
- /* Rounded distance. */
- /* */
- /* <Note> */
- /* The TrueType specification says very little about the relationship */
- /* between rounding and engine compensation. However, it seems from */
- /* the description of super round that we should add the compensation */
- /* before rounding. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * Round_Super
+ *
+ * @Description:
+ * Super-rounds value to grid after adding engine compensation.
+ *
+ * @Input:
+ * distance ::
+ * The distance to round.
+ *
+ * compensation ::
+ * The engine compensation.
+ *
+ * @Return:
+ * Rounded distance.
+ *
+ * @Note:
+ * The TrueType specification says very little about the relationship
+ * between rounding and engine compensation. However, it seems from
+ * the description of super round that we should add the compensation
+ * before rounding.
+ */
static FT_F26Dot6
Round_Super( TT_ExecContext exc,
FT_F26Dot6 distance,
@@ -2183,26 +2223,28 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Round_Super_45 */
- /* */
- /* <Description> */
- /* Super-rounds value to grid after adding engine compensation. */
- /* */
- /* <Input> */
- /* distance :: The distance to round. */
- /* */
- /* compensation :: The engine compensation. */
- /* */
- /* <Return> */
- /* Rounded distance. */
- /* */
- /* <Note> */
- /* There is a separate function for Round_Super_45() as we may need */
- /* greater precision. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * Round_Super_45
+ *
+ * @Description:
+ * Super-rounds value to grid after adding engine compensation.
+ *
+ * @Input:
+ * distance ::
+ * The distance to round.
+ *
+ * compensation ::
+ * The engine compensation.
+ *
+ * @Return:
+ * Rounded distance.
+ *
+ * @Note:
+ * There is a separate function for Round_Super_45() as we may need
+ * greater precision.
+ */
static FT_F26Dot6
Round_Super_45( TT_ExecContext exc,
FT_F26Dot6 distance,
@@ -2234,17 +2276,18 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Compute_Round */
- /* */
- /* <Description> */
- /* Sets the rounding mode. */
- /* */
- /* <Input> */
- /* round_mode :: The rounding mode to be used. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * Compute_Round
+ *
+ * @Description:
+ * Sets the rounding mode.
+ *
+ * @Input:
+ * round_mode ::
+ * The rounding mode to be used.
+ */
static void
Compute_Round( TT_ExecContext exc,
FT_Byte round_mode )
@@ -2286,19 +2329,21 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* SetSuperRound */
- /* */
- /* <Description> */
- /* Sets Super Round parameters. */
- /* */
- /* <Input> */
- /* GridPeriod :: The grid period. */
- /* */
- /* selector :: The SROUND opcode. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * SetSuperRound
+ *
+ * @Description:
+ * Sets Super Round parameters.
+ *
+ * @Input:
+ * GridPeriod ::
+ * The grid period.
+ *
+ * selector ::
+ * The SROUND opcode.
+ */
static void
SetSuperRound( TT_ExecContext exc,
FT_F2Dot14 GridPeriod,
@@ -2355,22 +2400,24 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Project */
- /* */
- /* <Description> */
- /* Computes the projection of vector given by (v2-v1) along the */
- /* current projection vector. */
- /* */
- /* <Input> */
- /* v1 :: First input vector. */
- /* v2 :: Second input vector. */
- /* */
- /* <Return> */
- /* The distance in F26dot6 format. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * Project
+ *
+ * @Description:
+ * Computes the projection of vector given by (v2-v1) along the
+ * current projection vector.
+ *
+ * @Input:
+ * v1 ::
+ * First input vector.
+ * v2 ::
+ * Second input vector.
+ *
+ * @Return:
+ * The distance in F26dot6 format.
+ */
static FT_F26Dot6
Project( TT_ExecContext exc,
FT_Pos dx,
@@ -2382,22 +2429,24 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Dual_Project */
- /* */
- /* <Description> */
- /* Computes the projection of the vector given by (v2-v1) along the */
- /* current dual vector. */
- /* */
- /* <Input> */
- /* v1 :: First input vector. */
- /* v2 :: Second input vector. */
- /* */
- /* <Return> */
- /* The distance in F26dot6 format. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * Dual_Project
+ *
+ * @Description:
+ * Computes the projection of the vector given by (v2-v1) along the
+ * current dual vector.
+ *
+ * @Input:
+ * v1 ::
+ * First input vector.
+ * v2 ::
+ * Second input vector.
+ *
+ * @Return:
+ * The distance in F26dot6 format.
+ */
static FT_F26Dot6
Dual_Project( TT_ExecContext exc,
FT_Pos dx,
@@ -2409,22 +2458,24 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Project_x */
- /* */
- /* <Description> */
- /* Computes the projection of the vector given by (v2-v1) along the */
- /* horizontal axis. */
- /* */
- /* <Input> */
- /* v1 :: First input vector. */
- /* v2 :: Second input vector. */
- /* */
- /* <Return> */
- /* The distance in F26dot6 format. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * Project_x
+ *
+ * @Description:
+ * Computes the projection of the vector given by (v2-v1) along the
+ * horizontal axis.
+ *
+ * @Input:
+ * v1 ::
+ * First input vector.
+ * v2 ::
+ * Second input vector.
+ *
+ * @Return:
+ * The distance in F26dot6 format.
+ */
static FT_F26Dot6
Project_x( TT_ExecContext exc,
FT_Pos dx,
@@ -2437,22 +2488,24 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Project_y */
- /* */
- /* <Description> */
- /* Computes the projection of the vector given by (v2-v1) along the */
- /* vertical axis. */
- /* */
- /* <Input> */
- /* v1 :: First input vector. */
- /* v2 :: Second input vector. */
- /* */
- /* <Return> */
- /* The distance in F26dot6 format. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * Project_y
+ *
+ * @Description:
+ * Computes the projection of the vector given by (v2-v1) along the
+ * vertical axis.
+ *
+ * @Input:
+ * v1 ::
+ * First input vector.
+ * v2 ::
+ * Second input vector.
+ *
+ * @Return:
+ * The distance in F26dot6 format.
+ */
static FT_F26Dot6
Project_y( TT_ExecContext exc,
FT_Pos dx,
@@ -2465,15 +2518,15 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Compute_Funcs */
- /* */
- /* <Description> */
- /* Computes the projection and movement function pointers according */
- /* to the current graphics state. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * Compute_Funcs
+ *
+ * @Description:
+ * Computes the projection and movement function pointers according
+ * to the current graphics state.
+ */
static void
Compute_Funcs( TT_ExecContext exc )
{
@@ -2528,28 +2581,31 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Normalize */
- /* */
- /* <Description> */
- /* Norms a vector. */
- /* */
- /* <Input> */
- /* Vx :: The horizontal input vector coordinate. */
- /* Vy :: The vertical input vector coordinate. */
- /* */
- /* <Output> */
- /* R :: The normed unit vector. */
- /* */
- /* <Return> */
- /* Returns FAILURE if a vector parameter is zero. */
- /* */
- /* <Note> */
- /* In case Vx and Vy are both zero, `Normalize' returns SUCCESS, and */
- /* R is undefined. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * Normalize
+ *
+ * @Description:
+ * Norms a vector.
+ *
+ * @Input:
+ * Vx ::
+ * The horizontal input vector coordinate.
+ * Vy ::
+ * The vertical input vector coordinate.
+ *
+ * @Output:
+ * R ::
+ * The normed unit vector.
+ *
+ * @Return:
+ * Returns FAILURE if a vector parameter is zero.
+ *
+ * @Note:
+ * In case Vx and Vy are both zero, `Normalize' returns SUCCESS, and
+ * R is undefined.
+ */
static FT_Bool
Normalize( FT_F26Dot6 Vx,
FT_F26Dot6 Vy,
@@ -2577,11 +2633,11 @@
}
- /*************************************************************************/
- /* */
- /* Here we start with the implementation of the various opcodes. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * Here we start with the implementation of the various opcodes.
+ *
+ */
#define ARRAY_BOUND_ERROR \
@@ -2592,12 +2648,12 @@
} while (0)
- /*************************************************************************/
- /* */
- /* MPPEM[]: Measure Pixel Per EM */
- /* Opcode range: 0x4B */
- /* Stack: --> Euint16 */
- /* */
+ /**************************************************************************
+ *
+ * MPPEM[]: Measure Pixel Per EM
+ * Opcode range: 0x4B
+ * Stack: --> Euint16
+ */
static void
Ins_MPPEM( TT_ExecContext exc,
FT_Long* args )
@@ -2606,12 +2662,12 @@
}
- /*************************************************************************/
- /* */
- /* MPS[]: Measure Point Size */
- /* Opcode range: 0x4C */
- /* Stack: --> Euint16 */
- /* */
+ /**************************************************************************
+ *
+ * MPS[]: Measure Point Size
+ * Opcode range: 0x4C
+ * Stack: --> Euint16
+ */
static void
Ins_MPS( TT_ExecContext exc,
FT_Long* args )
@@ -2633,12 +2689,12 @@
}
- /*************************************************************************/
- /* */
- /* DUP[]: DUPlicate the stack's top element */
- /* Opcode range: 0x20 */
- /* Stack: StkElt --> StkElt StkElt */
- /* */
+ /**************************************************************************
+ *
+ * DUP[]: DUPlicate the stack's top element
+ * Opcode range: 0x20
+ * Stack: StkElt --> StkElt StkElt
+ */
static void
Ins_DUP( FT_Long* args )
{
@@ -2646,12 +2702,12 @@
}
- /*************************************************************************/
- /* */
- /* POP[]: POP the stack's top element */
- /* Opcode range: 0x21 */
- /* Stack: StkElt --> */
- /* */
+ /**************************************************************************
+ *
+ * POP[]: POP the stack's top element
+ * Opcode range: 0x21
+ * Stack: StkElt -->
+ */
static void
Ins_POP( void )
{
@@ -2659,12 +2715,12 @@
}
- /*************************************************************************/
- /* */
- /* CLEAR[]: CLEAR the entire stack */
- /* Opcode range: 0x22 */
- /* Stack: StkElt... --> */
- /* */
+ /**************************************************************************
+ *
+ * CLEAR[]: CLEAR the entire stack
+ * Opcode range: 0x22
+ * Stack: StkElt... -->
+ */
static void
Ins_CLEAR( TT_ExecContext exc )
{
@@ -2672,12 +2728,12 @@
}
- /*************************************************************************/
- /* */
- /* SWAP[]: SWAP the stack's top two elements */
- /* Opcode range: 0x23 */
- /* Stack: 2 * StkElt --> 2 * StkElt */
- /* */
+ /**************************************************************************
+ *
+ * SWAP[]: SWAP the stack's top two elements
+ * Opcode range: 0x23
+ * Stack: 2 * StkElt --> 2 * StkElt
+ */
static void
Ins_SWAP( FT_Long* args )
{
@@ -2690,12 +2746,12 @@
}
- /*************************************************************************/
- /* */
- /* DEPTH[]: return the stack DEPTH */
- /* Opcode range: 0x24 */
- /* Stack: --> uint32 */
- /* */
+ /**************************************************************************
+ *
+ * DEPTH[]: return the stack DEPTH
+ * Opcode range: 0x24
+ * Stack: --> uint32
+ */
static void
Ins_DEPTH( TT_ExecContext exc,
FT_Long* args )
@@ -2704,12 +2760,12 @@
}
- /*************************************************************************/
- /* */
- /* LT[]: Less Than */
- /* Opcode range: 0x50 */
- /* Stack: int32? int32? --> bool */
- /* */
+ /**************************************************************************
+ *
+ * LT[]: Less Than
+ * Opcode range: 0x50
+ * Stack: int32? int32? --> bool
+ */
static void
Ins_LT( FT_Long* args )
{
@@ -2717,12 +2773,12 @@
}
- /*************************************************************************/
- /* */
- /* LTEQ[]: Less Than or EQual */
- /* Opcode range: 0x51 */
- /* Stack: int32? int32? --> bool */
- /* */
+ /**************************************************************************
+ *
+ * LTEQ[]: Less Than or EQual
+ * Opcode range: 0x51
+ * Stack: int32? int32? --> bool
+ */
static void
Ins_LTEQ( FT_Long* args )
{
@@ -2730,12 +2786,12 @@
}
- /*************************************************************************/
- /* */
- /* GT[]: Greater Than */
- /* Opcode range: 0x52 */
- /* Stack: int32? int32? --> bool */
- /* */
+ /**************************************************************************
+ *
+ * GT[]: Greater Than
+ * Opcode range: 0x52
+ * Stack: int32? int32? --> bool
+ */
static void
Ins_GT( FT_Long* args )
{
@@ -2743,12 +2799,12 @@
}
- /*************************************************************************/
- /* */
- /* GTEQ[]: Greater Than or EQual */
- /* Opcode range: 0x53 */
- /* Stack: int32? int32? --> bool */
- /* */
+ /**************************************************************************
+ *
+ * GTEQ[]: Greater Than or EQual
+ * Opcode range: 0x53
+ * Stack: int32? int32? --> bool
+ */
static void
Ins_GTEQ( FT_Long* args )
{
@@ -2756,12 +2812,12 @@
}
- /*************************************************************************/
- /* */
- /* EQ[]: EQual */
- /* Opcode range: 0x54 */
- /* Stack: StkElt StkElt --> bool */
- /* */
+ /**************************************************************************
+ *
+ * EQ[]: EQual
+ * Opcode range: 0x54
+ * Stack: StkElt StkElt --> bool
+ */
static void
Ins_EQ( FT_Long* args )
{
@@ -2769,12 +2825,12 @@
}
- /*************************************************************************/
- /* */
- /* NEQ[]: Not EQual */
- /* Opcode range: 0x55 */
- /* Stack: StkElt StkElt --> bool */
- /* */
+ /**************************************************************************
+ *
+ * NEQ[]: Not EQual
+ * Opcode range: 0x55
+ * Stack: StkElt StkElt --> bool
+ */
static void
Ins_NEQ( FT_Long* args )
{
@@ -2782,12 +2838,12 @@
}
- /*************************************************************************/
- /* */
- /* ODD[]: Is ODD */
- /* Opcode range: 0x56 */
- /* Stack: f26.6 --> bool */
- /* */
+ /**************************************************************************
+ *
+ * ODD[]: Is ODD
+ * Opcode range: 0x56
+ * Stack: f26.6 --> bool
+ */
static void
Ins_ODD( TT_ExecContext exc,
FT_Long* args )
@@ -2796,12 +2852,12 @@
}
- /*************************************************************************/
- /* */
- /* EVEN[]: Is EVEN */
- /* Opcode range: 0x57 */
- /* Stack: f26.6 --> bool */
- /* */
+ /**************************************************************************
+ *
+ * EVEN[]: Is EVEN
+ * Opcode range: 0x57
+ * Stack: f26.6 --> bool
+ */
static void
Ins_EVEN( TT_ExecContext exc,
FT_Long* args )
@@ -2810,12 +2866,12 @@
}
- /*************************************************************************/
- /* */
- /* AND[]: logical AND */
- /* Opcode range: 0x5A */
- /* Stack: uint32 uint32 --> uint32 */
- /* */
+ /**************************************************************************
+ *
+ * AND[]: logical AND
+ * Opcode range: 0x5A
+ * Stack: uint32 uint32 --> uint32
+ */
static void
Ins_AND( FT_Long* args )
{
@@ -2823,12 +2879,12 @@
}
- /*************************************************************************/
- /* */
- /* OR[]: logical OR */
- /* Opcode range: 0x5B */
- /* Stack: uint32 uint32 --> uint32 */
- /* */
+ /**************************************************************************
+ *
+ * OR[]: logical OR
+ * Opcode range: 0x5B
+ * Stack: uint32 uint32 --> uint32
+ */
static void
Ins_OR( FT_Long* args )
{
@@ -2836,12 +2892,12 @@
}
- /*************************************************************************/
- /* */
- /* NOT[]: logical NOT */
- /* Opcode range: 0x5C */
- /* Stack: StkElt --> uint32 */
- /* */
+ /**************************************************************************
+ *
+ * NOT[]: logical NOT
+ * Opcode range: 0x5C
+ * Stack: StkElt --> uint32
+ */
static void
Ins_NOT( FT_Long* args )
{
@@ -2849,12 +2905,12 @@
}
- /*************************************************************************/
- /* */
- /* ADD[]: ADD */
- /* Opcode range: 0x60 */
- /* Stack: f26.6 f26.6 --> f26.6 */
- /* */
+ /**************************************************************************
+ *
+ * ADD[]: ADD
+ * Opcode range: 0x60
+ * Stack: f26.6 f26.6 --> f26.6
+ */
static void
Ins_ADD( FT_Long* args )
{
@@ -2862,12 +2918,12 @@
}
- /*************************************************************************/
- /* */
- /* SUB[]: SUBtract */
- /* Opcode range: 0x61 */
- /* Stack: f26.6 f26.6 --> f26.6 */
- /* */
+ /**************************************************************************
+ *
+ * SUB[]: SUBtract
+ * Opcode range: 0x61
+ * Stack: f26.6 f26.6 --> f26.6
+ */
static void
Ins_SUB( FT_Long* args )
{
@@ -2875,12 +2931,12 @@
}
- /*************************************************************************/
- /* */
- /* DIV[]: DIVide */
- /* Opcode range: 0x62 */
- /* Stack: f26.6 f26.6 --> f26.6 */
- /* */
+ /**************************************************************************
+ *
+ * DIV[]: DIVide
+ * Opcode range: 0x62
+ * Stack: f26.6 f26.6 --> f26.6
+ */
static void
Ins_DIV( TT_ExecContext exc,
FT_Long* args )
@@ -2892,12 +2948,12 @@
}
- /*************************************************************************/
- /* */
- /* MUL[]: MULtiply */
- /* Opcode range: 0x63 */
- /* Stack: f26.6 f26.6 --> f26.6 */
- /* */
+ /**************************************************************************
+ *
+ * MUL[]: MULtiply
+ * Opcode range: 0x63
+ * Stack: f26.6 f26.6 --> f26.6
+ */
static void
Ins_MUL( FT_Long* args )
{
@@ -2905,12 +2961,12 @@
}
- /*************************************************************************/
- /* */
- /* ABS[]: ABSolute value */
- /* Opcode range: 0x64 */
- /* Stack: f26.6 --> f26.6 */
- /* */
+ /**************************************************************************
+ *
+ * ABS[]: ABSolute value
+ * Opcode range: 0x64
+ * Stack: f26.6 --> f26.6
+ */
static void
Ins_ABS( FT_Long* args )
{
@@ -2919,12 +2975,12 @@
}
- /*************************************************************************/
- /* */
- /* NEG[]: NEGate */
- /* Opcode range: 0x65 */
- /* Stack: f26.6 --> f26.6 */
- /* */
+ /**************************************************************************
+ *
+ * NEG[]: NEGate
+ * Opcode range: 0x65
+ * Stack: f26.6 --> f26.6
+ */
static void
Ins_NEG( FT_Long* args )
{
@@ -2932,12 +2988,12 @@
}
- /*************************************************************************/
- /* */
- /* FLOOR[]: FLOOR */
- /* Opcode range: 0x66 */
- /* Stack: f26.6 --> f26.6 */
- /* */
+ /**************************************************************************
+ *
+ * FLOOR[]: FLOOR
+ * Opcode range: 0x66
+ * Stack: f26.6 --> f26.6
+ */
static void
Ins_FLOOR( FT_Long* args )
{
@@ -2945,12 +3001,12 @@
}
- /*************************************************************************/
- /* */
- /* CEILING[]: CEILING */
- /* Opcode range: 0x67 */
- /* Stack: f26.6 --> f26.6 */
- /* */
+ /**************************************************************************
+ *
+ * CEILING[]: CEILING
+ * Opcode range: 0x67
+ * Stack: f26.6 --> f26.6
+ */
static void
Ins_CEILING( FT_Long* args )
{
@@ -2958,12 +3014,12 @@
}
- /*************************************************************************/
- /* */
- /* RS[]: Read Store */
- /* Opcode range: 0x43 */
- /* Stack: uint32 --> uint32 */
- /* */
+ /**************************************************************************
+ *
+ * RS[]: Read Store
+ * Opcode range: 0x43
+ * Stack: uint32 --> uint32
+ */
static void
Ins_RS( TT_ExecContext exc,
FT_Long* args )
@@ -3004,12 +3060,12 @@
}
- /*************************************************************************/
- /* */
- /* WS[]: Write Store */
- /* Opcode range: 0x42 */
- /* Stack: uint32 uint32 --> */
- /* */
+ /**************************************************************************
+ *
+ * WS[]: Write Store
+ * Opcode range: 0x42
+ * Stack: uint32 uint32 -->
+ */
static void
Ins_WS( TT_ExecContext exc,
FT_Long* args )
@@ -3027,12 +3083,12 @@
}
- /*************************************************************************/
- /* */
- /* WCVTP[]: Write CVT in Pixel units */
- /* Opcode range: 0x44 */
- /* Stack: f26.6 uint32 --> */
- /* */
+ /**************************************************************************
+ *
+ * WCVTP[]: Write CVT in Pixel units
+ * Opcode range: 0x44
+ * Stack: f26.6 uint32 -->
+ */
static void
Ins_WCVTP( TT_ExecContext exc,
FT_Long* args )
@@ -3050,12 +3106,12 @@
}
- /*************************************************************************/
- /* */
- /* WCVTF[]: Write CVT in Funits */
- /* Opcode range: 0x70 */
- /* Stack: uint32 uint32 --> */
- /* */
+ /**************************************************************************
+ *
+ * WCVTF[]: Write CVT in Funits
+ * Opcode range: 0x70
+ * Stack: uint32 uint32 -->
+ */
static void
Ins_WCVTF( TT_ExecContext exc,
FT_Long* args )
@@ -3073,12 +3129,12 @@
}
- /*************************************************************************/
- /* */
- /* RCVT[]: Read CVT */
- /* Opcode range: 0x45 */
- /* Stack: uint32 --> f26.6 */
- /* */
+ /**************************************************************************
+ *
+ * RCVT[]: Read CVT
+ * Opcode range: 0x45
+ * Stack: uint32 --> f26.6
+ */
static void
Ins_RCVT( TT_ExecContext exc,
FT_Long* args )
@@ -3098,12 +3154,12 @@
}
- /*************************************************************************/
- /* */
- /* AA[]: Adjust Angle */
- /* Opcode range: 0x7F */
- /* Stack: uint32 --> */
- /* */
+ /**************************************************************************
+ *
+ * AA[]: Adjust Angle
+ * Opcode range: 0x7F
+ * Stack: uint32 -->
+ */
static void
Ins_AA( void )
{
@@ -3111,14 +3167,14 @@
}
- /*************************************************************************/
- /* */
- /* DEBUG[]: DEBUG. Unsupported. */
- /* Opcode range: 0x4F */
- /* Stack: uint32 --> */
- /* */
- /* Note: The original instruction pops a value from the stack. */
- /* */
+ /**************************************************************************
+ *
+ * DEBUG[]: DEBUG. Unsupported.
+ * Opcode range: 0x4F
+ * Stack: uint32 -->
+ *
+ * Note: The original instruction pops a value from the stack.
+ */
static void
Ins_DEBUG( TT_ExecContext exc )
{
@@ -3126,12 +3182,12 @@
}
- /*************************************************************************/
- /* */
- /* ROUND[ab]: ROUND value */
- /* Opcode range: 0x68-0x6B */
- /* Stack: f26.6 --> f26.6 */
- /* */
+ /**************************************************************************
+ *
+ * ROUND[ab]: ROUND value
+ * Opcode range: 0x68-0x6B
+ * Stack: f26.6 --> f26.6
+ */
static void
Ins_ROUND( TT_ExecContext exc,
FT_Long* args )
@@ -3143,12 +3199,12 @@
}
- /*************************************************************************/
- /* */
- /* NROUND[ab]: No ROUNDing of value */
- /* Opcode range: 0x6C-0x6F */
- /* Stack: f26.6 --> f26.6 */
- /* */
+ /**************************************************************************
+ *
+ * NROUND[ab]: No ROUNDing of value
+ * Opcode range: 0x6C-0x6F
+ * Stack: f26.6 --> f26.6
+ */
static void
Ins_NROUND( TT_ExecContext exc,
FT_Long* args )
@@ -3160,12 +3216,12 @@
}
- /*************************************************************************/
- /* */
- /* MAX[]: MAXimum */
- /* Opcode range: 0x8B */
- /* Stack: int32? int32? --> int32 */
- /* */
+ /**************************************************************************
+ *
+ * MAX[]: MAXimum
+ * Opcode range: 0x8B
+ * Stack: int32? int32? --> int32
+ */
static void
Ins_MAX( FT_Long* args )
{
@@ -3174,12 +3230,12 @@
}
- /*************************************************************************/
- /* */
- /* MIN[]: MINimum */
- /* Opcode range: 0x8C */
- /* Stack: int32? int32? --> int32 */
- /* */
+ /**************************************************************************
+ *
+ * MIN[]: MINimum
+ * Opcode range: 0x8C
+ * Stack: int32? int32? --> int32
+ */
static void
Ins_MIN( FT_Long* args )
{
@@ -3188,12 +3244,12 @@
}
- /*************************************************************************/
- /* */
- /* MINDEX[]: Move INDEXed element */
- /* Opcode range: 0x26 */
- /* Stack: int32? --> StkElt */
- /* */
+ /**************************************************************************
+ *
+ * MINDEX[]: Move INDEXed element
+ * Opcode range: 0x26
+ * Stack: int32? --> StkElt
+ */
static void
Ins_MINDEX( TT_ExecContext exc,
FT_Long* args )
@@ -3221,12 +3277,12 @@
}
- /*************************************************************************/
- /* */
- /* CINDEX[]: Copy INDEXed element */
- /* Opcode range: 0x25 */
- /* Stack: int32 --> StkElt */
- /* */
+ /**************************************************************************
+ *
+ * CINDEX[]: Copy INDEXed element
+ * Opcode range: 0x25
+ * Stack: int32 --> StkElt
+ */
static void
Ins_CINDEX( TT_ExecContext exc,
FT_Long* args )
@@ -3247,12 +3303,12 @@
}
- /*************************************************************************/
- /* */
- /* ROLL[]: ROLL top three elements */
- /* Opcode range: 0x8A */
- /* Stack: 3 * StkElt --> 3 * StkElt */
- /* */
+ /**************************************************************************
+ *
+ * ROLL[]: ROLL top three elements
+ * Opcode range: 0x8A
+ * Stack: 3 * StkElt --> 3 * StkElt
+ */
static void
Ins_ROLL( FT_Long* args )
{
@@ -3269,19 +3325,19 @@
}
- /*************************************************************************/
- /* */
- /* MANAGING THE FLOW OF CONTROL */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * MANAGING THE FLOW OF CONTROL
+ *
+ */
- /*************************************************************************/
- /* */
- /* SLOOP[]: Set LOOP variable */
- /* Opcode range: 0x17 */
- /* Stack: int32? --> */
- /* */
+ /**************************************************************************
+ *
+ * SLOOP[]: Set LOOP variable
+ * Opcode range: 0x17
+ * Stack: int32? -->
+ */
static void
Ins_SLOOP( TT_ExecContext exc,
FT_Long* args )
@@ -3323,12 +3379,12 @@
}
- /*************************************************************************/
- /* */
- /* IF[]: IF test */
- /* Opcode range: 0x58 */
- /* Stack: StkElt --> */
- /* */
+ /**************************************************************************
+ *
+ * IF[]: IF test
+ * Opcode range: 0x58
+ * Stack: StkElt -->
+ */
static void
Ins_IF( TT_ExecContext exc,
FT_Long* args )
@@ -3367,12 +3423,12 @@
}
- /*************************************************************************/
- /* */
- /* ELSE[]: ELSE */
- /* Opcode range: 0x1B */
- /* Stack: --> */
- /* */
+ /**************************************************************************
+ *
+ * ELSE[]: ELSE
+ * Opcode range: 0x1B
+ * Stack: -->
+ */
static void
Ins_ELSE( TT_ExecContext exc )
{
@@ -3400,12 +3456,12 @@
}
- /*************************************************************************/
- /* */
- /* EIF[]: End IF */
- /* Opcode range: 0x59 */
- /* Stack: --> */
- /* */
+ /**************************************************************************
+ *
+ * EIF[]: End IF
+ * Opcode range: 0x59
+ * Stack: -->
+ */
static void
Ins_EIF( void )
{
@@ -3413,12 +3469,12 @@
}
- /*************************************************************************/
- /* */
- /* JMPR[]: JuMP Relative */
- /* Opcode range: 0x1C */
- /* Stack: int32 --> */
- /* */
+ /**************************************************************************
+ *
+ * JMPR[]: JuMP Relative
+ * Opcode range: 0x1C
+ * Stack: int32 -->
+ */
static void
Ins_JMPR( TT_ExecContext exc,
FT_Long* args )
@@ -3448,12 +3504,12 @@
}
- /*************************************************************************/
- /* */
- /* JROT[]: Jump Relative On True */
- /* Opcode range: 0x78 */
- /* Stack: StkElt int32 --> */
- /* */
+ /**************************************************************************
+ *
+ * JROT[]: Jump Relative On True
+ * Opcode range: 0x78
+ * Stack: StkElt int32 -->
+ */
static void
Ins_JROT( TT_ExecContext exc,
FT_Long* args )
@@ -3463,12 +3519,12 @@
}
- /*************************************************************************/
- /* */
- /* JROF[]: Jump Relative On False */
- /* Opcode range: 0x79 */
- /* Stack: StkElt int32 --> */
- /* */
+ /**************************************************************************
+ *
+ * JROF[]: Jump Relative On False
+ * Opcode range: 0x79
+ * Stack: StkElt int32 -->
+ */
static void
Ins_JROF( TT_ExecContext exc,
FT_Long* args )
@@ -3478,19 +3534,19 @@
}
- /*************************************************************************/
- /* */
- /* DEFINING AND USING FUNCTIONS AND INSTRUCTIONS */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * DEFINING AND USING FUNCTIONS AND INSTRUCTIONS
+ *
+ */
- /*************************************************************************/
- /* */
- /* FDEF[]: Function DEFinition */
- /* Opcode range: 0x2C */
- /* Stack: uint32 --> */
- /* */
+ /**************************************************************************
+ *
+ * FDEF[]: Function DEFinition
+ * Opcode range: 0x2C
+ * Stack: uint32 -->
+ */
static void
Ins_FDEF( TT_ExecContext exc,
FT_Long* args )
@@ -3788,12 +3844,12 @@
}
- /*************************************************************************/
- /* */
- /* ENDF[]: END Function definition */
- /* Opcode range: 0x2D */
- /* Stack: --> */
- /* */
+ /**************************************************************************
+ *
+ * ENDF[]: END Function definition
+ * Opcode range: 0x2D
+ * Stack: -->
+ */
static void
Ins_ENDF( TT_ExecContext exc )
{
@@ -3837,12 +3893,12 @@
}
- /*************************************************************************/
- /* */
- /* CALL[]: CALL function */
- /* Opcode range: 0x2B */
- /* Stack: uint32? --> */
- /* */
+ /**************************************************************************
+ *
+ * CALL[]: CALL function
+ * Opcode range: 0x2B
+ * Stack: uint32? -->
+ */
static void
Ins_CALL( TT_ExecContext exc,
FT_Long* args )
@@ -3926,12 +3982,12 @@
}
- /*************************************************************************/
- /* */
- /* LOOPCALL[]: LOOP and CALL function */
- /* Opcode range: 0x2A */
- /* Stack: uint32? Eint16? --> */
- /* */
+ /**************************************************************************
+ *
+ * LOOPCALL[]: LOOP and CALL function
+ * Opcode range: 0x2A
+ * Stack: uint32? Eint16? -->
+ */
static void
Ins_LOOPCALL( TT_ExecContext exc,
FT_Long* args )
@@ -4019,12 +4075,12 @@
}
- /*************************************************************************/
- /* */
- /* IDEF[]: Instruction DEFinition */
- /* Opcode range: 0x89 */
- /* Stack: Eint8 --> */
- /* */
+ /**************************************************************************
+ *
+ * IDEF[]: Instruction DEFinition
+ * Opcode range: 0x89
+ * Stack: Eint8 -->
+ */
static void
Ins_IDEF( TT_ExecContext exc,
FT_Long* args )
@@ -4094,19 +4150,19 @@
}
- /*************************************************************************/
- /* */
- /* PUSHING DATA ONTO THE INTERPRETER STACK */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * PUSHING DATA ONTO THE INTERPRETER STACK
+ *
+ */
- /*************************************************************************/
- /* */
- /* NPUSHB[]: PUSH N Bytes */
- /* Opcode range: 0x40 */
- /* Stack: --> uint32... */
- /* */
+ /**************************************************************************
+ *
+ * NPUSHB[]: PUSH N Bytes
+ * Opcode range: 0x40
+ * Stack: --> uint32...
+ */
static void
Ins_NPUSHB( TT_ExecContext exc,
FT_Long* args )
@@ -4129,12 +4185,12 @@
}
- /*************************************************************************/
- /* */
- /* NPUSHW[]: PUSH N Words */
- /* Opcode range: 0x41 */
- /* Stack: --> int32... */
- /* */
+ /**************************************************************************
+ *
+ * NPUSHW[]: PUSH N Words
+ * Opcode range: 0x41
+ * Stack: --> int32...
+ */
static void
Ins_NPUSHW( TT_ExecContext exc,
FT_Long* args )
@@ -4160,12 +4216,12 @@
}
- /*************************************************************************/
- /* */
- /* PUSHB[abc]: PUSH Bytes */
- /* Opcode range: 0xB0-0xB7 */
- /* Stack: --> uint32... */
- /* */
+ /**************************************************************************
+ *
+ * PUSHB[abc]: PUSH Bytes
+ * Opcode range: 0xB0-0xB7
+ * Stack: --> uint32...
+ */
static void
Ins_PUSHB( TT_ExecContext exc,
FT_Long* args )
@@ -4186,12 +4242,12 @@
}
- /*************************************************************************/
- /* */
- /* PUSHW[abc]: PUSH Words */
- /* Opcode range: 0xB8-0xBF */
- /* Stack: --> int32... */
- /* */
+ /**************************************************************************
+ *
+ * PUSHW[abc]: PUSH Words
+ * Opcode range: 0xB8-0xBF
+ * Stack: --> int32...
+ */
static void
Ins_PUSHW( TT_ExecContext exc,
FT_Long* args )
@@ -4216,11 +4272,11 @@
}
- /*************************************************************************/
- /* */
- /* MANAGING THE GRAPHICS STATE */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * MANAGING THE GRAPHICS STATE
+ *
+ */
static FT_Bool
@@ -4274,20 +4330,20 @@
}
- /*************************************************************************/
- /* */
- /* SVTCA[a]: Set (F and P) Vectors to Coordinate Axis */
- /* Opcode range: 0x00-0x01 */
- /* Stack: --> */
- /* */
- /* SPvTCA[a]: Set PVector to Coordinate Axis */
- /* Opcode range: 0x02-0x03 */
- /* Stack: --> */
- /* */
- /* SFvTCA[a]: Set FVector to Coordinate Axis */
- /* Opcode range: 0x04-0x05 */
- /* Stack: --> */
- /* */
+ /**************************************************************************
+ *
+ * SVTCA[a]: Set (F and P) Vectors to Coordinate Axis
+ * Opcode range: 0x00-0x01
+ * Stack: -->
+ *
+ * SPvTCA[a]: Set PVector to Coordinate Axis
+ * Opcode range: 0x02-0x03
+ * Stack: -->
+ *
+ * SFvTCA[a]: Set FVector to Coordinate Axis
+ * Opcode range: 0x04-0x05
+ * Stack: -->
+ */
static void
Ins_SxyTCA( TT_ExecContext exc )
{
@@ -4318,12 +4374,12 @@
}
- /*************************************************************************/
- /* */
- /* SPvTL[a]: Set PVector To Line */
- /* Opcode range: 0x06-0x07 */
- /* Stack: uint32 uint32 --> */
- /* */
+ /**************************************************************************
+ *
+ * SPvTL[a]: Set PVector To Line
+ * Opcode range: 0x06-0x07
+ * Stack: uint32 uint32 -->
+ */
static void
Ins_SPVTL( TT_ExecContext exc,
FT_Long* args )
@@ -4339,12 +4395,12 @@
}
- /*************************************************************************/
- /* */
- /* SFvTL[a]: Set FVector To Line */
- /* Opcode range: 0x08-0x09 */
- /* Stack: uint32 uint32 --> */
- /* */
+ /**************************************************************************
+ *
+ * SFvTL[a]: Set FVector To Line
+ * Opcode range: 0x08-0x09
+ * Stack: uint32 uint32 -->
+ */
static void
Ins_SFVTL( TT_ExecContext exc,
FT_Long* args )
@@ -4359,12 +4415,12 @@
}
- /*************************************************************************/
- /* */
- /* SFvTPv[]: Set FVector To PVector */
- /* Opcode range: 0x0E */
- /* Stack: --> */
- /* */
+ /**************************************************************************
+ *
+ * SFvTPv[]: Set FVector To PVector
+ * Opcode range: 0x0E
+ * Stack: -->
+ */
static void
Ins_SFVTPV( TT_ExecContext exc )
{
@@ -4373,12 +4429,12 @@
}
- /*************************************************************************/
- /* */
- /* SPvFS[]: Set PVector From Stack */
- /* Opcode range: 0x0A */
- /* Stack: f2.14 f2.14 --> */
- /* */
+ /**************************************************************************
+ *
+ * SPvFS[]: Set PVector From Stack
+ * Opcode range: 0x0A
+ * Stack: f2.14 f2.14 -->
+ */
static void
Ins_SPVFS( TT_ExecContext exc,
FT_Long* args )
@@ -4400,12 +4456,12 @@
}
- /*************************************************************************/
- /* */
- /* SFvFS[]: Set FVector From Stack */
- /* Opcode range: 0x0B */
- /* Stack: f2.14 f2.14 --> */
- /* */
+ /**************************************************************************
+ *
+ * SFvFS[]: Set FVector From Stack
+ * Opcode range: 0x0B
+ * Stack: f2.14 f2.14 -->
+ */
static void
Ins_SFVFS( TT_ExecContext exc,
FT_Long* args )
@@ -4425,12 +4481,12 @@
}
- /*************************************************************************/
- /* */
- /* GPv[]: Get Projection Vector */
- /* Opcode range: 0x0C */
- /* Stack: ef2.14 --> ef2.14 */
- /* */
+ /**************************************************************************
+ *
+ * GPv[]: Get Projection Vector
+ * Opcode range: 0x0C
+ * Stack: ef2.14 --> ef2.14
+ */
static void
Ins_GPV( TT_ExecContext exc,
FT_Long* args )
@@ -4440,12 +4496,12 @@
}
- /*************************************************************************/
- /* */
- /* GFv[]: Get Freedom Vector */
- /* Opcode range: 0x0D */
- /* Stack: ef2.14 --> ef2.14 */
- /* */
+ /**************************************************************************
+ *
+ * GFv[]: Get Freedom Vector
+ * Opcode range: 0x0D
+ * Stack: ef2.14 --> ef2.14
+ */
static void
Ins_GFV( TT_ExecContext exc,
FT_Long* args )
@@ -4455,12 +4511,12 @@
}
- /*************************************************************************/
- /* */
- /* SRP0[]: Set Reference Point 0 */
- /* Opcode range: 0x10 */
- /* Stack: uint32 --> */
- /* */
+ /**************************************************************************
+ *
+ * SRP0[]: Set Reference Point 0
+ * Opcode range: 0x10
+ * Stack: uint32 -->
+ */
static void
Ins_SRP0( TT_ExecContext exc,
FT_Long* args )
@@ -4469,12 +4525,12 @@
}
- /*************************************************************************/
- /* */
- /* SRP1[]: Set Reference Point 1 */
- /* Opcode range: 0x11 */
- /* Stack: uint32 --> */
- /* */
+ /**************************************************************************
+ *
+ * SRP1[]: Set Reference Point 1
+ * Opcode range: 0x11
+ * Stack: uint32 -->
+ */
static void
Ins_SRP1( TT_ExecContext exc,
FT_Long* args )
@@ -4483,12 +4539,12 @@
}
- /*************************************************************************/
- /* */
- /* SRP2[]: Set Reference Point 2 */
- /* Opcode range: 0x12 */
- /* Stack: uint32 --> */
- /* */
+ /**************************************************************************
+ *
+ * SRP2[]: Set Reference Point 2
+ * Opcode range: 0x12
+ * Stack: uint32 -->
+ */
static void
Ins_SRP2( TT_ExecContext exc,
FT_Long* args )
@@ -4497,12 +4553,12 @@
}
- /*************************************************************************/
- /* */
- /* SMD[]: Set Minimum Distance */
- /* Opcode range: 0x1A */
- /* Stack: f26.6 --> */
- /* */
+ /**************************************************************************
+ *
+ * SMD[]: Set Minimum Distance
+ * Opcode range: 0x1A
+ * Stack: f26.6 -->
+ */
static void
Ins_SMD( TT_ExecContext exc,
FT_Long* args )
@@ -4511,12 +4567,12 @@
}
- /*************************************************************************/
- /* */
- /* SCVTCI[]: Set Control Value Table Cut In */
- /* Opcode range: 0x1D */
- /* Stack: f26.6 --> */
- /* */
+ /**************************************************************************
+ *
+ * SCVTCI[]: Set Control Value Table Cut In
+ * Opcode range: 0x1D
+ * Stack: f26.6 -->
+ */
static void
Ins_SCVTCI( TT_ExecContext exc,
FT_Long* args )
@@ -4525,12 +4581,12 @@
}
- /*************************************************************************/
- /* */
- /* SSWCI[]: Set Single Width Cut In */
- /* Opcode range: 0x1E */
- /* Stack: f26.6 --> */
- /* */
+ /**************************************************************************
+ *
+ * SSWCI[]: Set Single Width Cut In
+ * Opcode range: 0x1E
+ * Stack: f26.6 -->
+ */
static void
Ins_SSWCI( TT_ExecContext exc,
FT_Long* args )
@@ -4539,12 +4595,12 @@
}
- /*************************************************************************/
- /* */
- /* SSW[]: Set Single Width */
- /* Opcode range: 0x1F */
- /* Stack: int32? --> */
- /* */
+ /**************************************************************************
+ *
+ * SSW[]: Set Single Width
+ * Opcode range: 0x1F
+ * Stack: int32? -->
+ */
static void
Ins_SSW( TT_ExecContext exc,
FT_Long* args )
@@ -4554,12 +4610,12 @@
}
- /*************************************************************************/
- /* */
- /* FLIPON[]: Set auto-FLIP to ON */
- /* Opcode range: 0x4D */
- /* Stack: --> */
- /* */
+ /**************************************************************************
+ *
+ * FLIPON[]: Set auto-FLIP to ON
+ * Opcode range: 0x4D
+ * Stack: -->
+ */
static void
Ins_FLIPON( TT_ExecContext exc )
{
@@ -4567,12 +4623,12 @@
}
- /*************************************************************************/
- /* */
- /* FLIPOFF[]: Set auto-FLIP to OFF */
- /* Opcode range: 0x4E */
- /* Stack: --> */
- /* */
+ /**************************************************************************
+ *
+ * FLIPOFF[]: Set auto-FLIP to OFF
+ * Opcode range: 0x4E
+ * Stack: -->
+ */
static void
Ins_FLIPOFF( TT_ExecContext exc )
{
@@ -4580,12 +4636,12 @@
}
- /*************************************************************************/
- /* */
- /* SANGW[]: Set ANGle Weight */
- /* Opcode range: 0x7E */
- /* Stack: uint32 --> */
- /* */
+ /**************************************************************************
+ *
+ * SANGW[]: Set ANGle Weight
+ * Opcode range: 0x7E
+ * Stack: uint32 -->
+ */
static void
Ins_SANGW( void )
{
@@ -4593,12 +4649,12 @@
}
- /*************************************************************************/
- /* */
- /* SDB[]: Set Delta Base */
- /* Opcode range: 0x5E */
- /* Stack: uint32 --> */
- /* */
+ /**************************************************************************
+ *
+ * SDB[]: Set Delta Base
+ * Opcode range: 0x5E
+ * Stack: uint32 -->
+ */
static void
Ins_SDB( TT_ExecContext exc,
FT_Long* args )
@@ -4607,12 +4663,12 @@
}
- /*************************************************************************/
- /* */
- /* SDS[]: Set Delta Shift */
- /* Opcode range: 0x5F */
- /* Stack: uint32 --> */
- /* */
+ /**************************************************************************
+ *
+ * SDS[]: Set Delta Shift
+ * Opcode range: 0x5F
+ * Stack: uint32 -->
+ */
static void
Ins_SDS( TT_ExecContext exc,
FT_Long* args )
@@ -4624,12 +4680,12 @@
}
- /*************************************************************************/
- /* */
- /* RTHG[]: Round To Half Grid */
- /* Opcode range: 0x19 */
- /* Stack: --> */
- /* */
+ /**************************************************************************
+ *
+ * RTHG[]: Round To Half Grid
+ * Opcode range: 0x19
+ * Stack: -->
+ */
static void
Ins_RTHG( TT_ExecContext exc )
{
@@ -4638,12 +4694,12 @@
}
- /*************************************************************************/
- /* */
- /* RTG[]: Round To Grid */
- /* Opcode range: 0x18 */
- /* Stack: --> */
- /* */
+ /**************************************************************************
+ *
+ * RTG[]: Round To Grid
+ * Opcode range: 0x18
+ * Stack: -->
+ */
static void
Ins_RTG( TT_ExecContext exc )
{
@@ -4652,11 +4708,11 @@
}
- /*************************************************************************/
- /* RTDG[]: Round To Double Grid */
- /* Opcode range: 0x3D */
- /* Stack: --> */
- /* */
+ /**************************************************************************
+ * RTDG[]: Round To Double Grid
+ * Opcode range: 0x3D
+ * Stack: -->
+ */
static void
Ins_RTDG( TT_ExecContext exc )
{
@@ -4665,11 +4721,11 @@
}
- /*************************************************************************/
- /* RUTG[]: Round Up To Grid */
- /* Opcode range: 0x7C */
- /* Stack: --> */
- /* */
+ /**************************************************************************
+ * RUTG[]: Round Up To Grid
+ * Opcode range: 0x7C
+ * Stack: -->
+ */
static void
Ins_RUTG( TT_ExecContext exc )
{
@@ -4678,12 +4734,12 @@
}
- /*************************************************************************/
- /* */
- /* RDTG[]: Round Down To Grid */
- /* Opcode range: 0x7D */
- /* Stack: --> */
- /* */
+ /**************************************************************************
+ *
+ * RDTG[]: Round Down To Grid
+ * Opcode range: 0x7D
+ * Stack: -->
+ */
static void
Ins_RDTG( TT_ExecContext exc )
{
@@ -4692,12 +4748,12 @@
}
- /*************************************************************************/
- /* */
- /* ROFF[]: Round OFF */
- /* Opcode range: 0x7A */
- /* Stack: --> */
- /* */
+ /**************************************************************************
+ *
+ * ROFF[]: Round OFF
+ * Opcode range: 0x7A
+ * Stack: -->
+ */
static void
Ins_ROFF( TT_ExecContext exc )
{
@@ -4706,12 +4762,12 @@
}
- /*************************************************************************/
- /* */
- /* SROUND[]: Super ROUND */
- /* Opcode range: 0x76 */
- /* Stack: Eint8 --> */
- /* */
+ /**************************************************************************
+ *
+ * SROUND[]: Super ROUND
+ * Opcode range: 0x76
+ * Stack: Eint8 -->
+ */
static void
Ins_SROUND( TT_ExecContext exc,
FT_Long* args )
@@ -4723,12 +4779,12 @@
}
- /*************************************************************************/
- /* */
- /* S45ROUND[]: Super ROUND 45 degrees */
- /* Opcode range: 0x77 */
- /* Stack: uint32 --> */
- /* */
+ /**************************************************************************
+ *
+ * S45ROUND[]: Super ROUND 45 degrees
+ * Opcode range: 0x77
+ * Stack: uint32 -->
+ */
static void
Ins_S45ROUND( TT_ExecContext exc,
FT_Long* args )
@@ -4740,15 +4796,15 @@
}
- /*************************************************************************/
- /* */
- /* GC[a]: Get Coordinate projected onto */
- /* Opcode range: 0x46-0x47 */
- /* Stack: uint32 --> f26.6 */
- /* */
- /* XXX: UNDOCUMENTED: Measures from the original glyph must be taken */
- /* along the dual projection vector! */
- /* */
+ /**************************************************************************
+ *
+ * GC[a]: Get Coordinate projected onto
+ * Opcode range: 0x46-0x47
+ * Stack: uint32 --> f26.6
+ *
+ * XXX: UNDOCUMENTED: Measures from the original glyph must be taken
+ * along the dual projection vector!
+ */
static void
Ins_GC( TT_ExecContext exc,
FT_Long* args )
@@ -4777,16 +4833,16 @@
}
- /*************************************************************************/
- /* */
- /* SCFS[]: Set Coordinate From Stack */
- /* Opcode range: 0x48 */
- /* Stack: f26.6 uint32 --> */
- /* */
- /* Formula: */
- /* */
- /* OA := OA + ( value - OA.p )/( f.p ) * f */
- /* */
+ /**************************************************************************
+ *
+ * SCFS[]: Set Coordinate From Stack
+ * Opcode range: 0x48
+ * Stack: f26.6 uint32 -->
+ *
+ * Formula:
+ *
+ * OA := OA + ( value - OA.p )/( f.p ) * f
+ */
static void
Ins_SCFS( TT_ExecContext exc,
FT_Long* args )
@@ -4815,21 +4871,21 @@
}
- /*************************************************************************/
- /* */
- /* MD[a]: Measure Distance */
- /* Opcode range: 0x49-0x4A */
- /* Stack: uint32 uint32 --> f26.6 */
- /* */
- /* XXX: UNDOCUMENTED: Measure taken in the original glyph must be along */
- /* the dual projection vector. */
- /* */
- /* XXX: UNDOCUMENTED: Flag attributes are inverted! */
- /* 0 => measure distance in original outline */
- /* 1 => measure distance in grid-fitted outline */
- /* */
- /* XXX: UNDOCUMENTED: `zp0 - zp1', and not `zp2 - zp1! */
- /* */
+ /**************************************************************************
+ *
+ * MD[a]: Measure Distance
+ * Opcode range: 0x49-0x4A
+ * Stack: uint32 uint32 --> f26.6
+ *
+ * XXX: UNDOCUMENTED: Measure taken in the original glyph must be along
+ * the dual projection vector.
+ *
+ * XXX: UNDOCUMENTED: Flag attributes are inverted!
+ * 0 => measure distance in original outline
+ * 1 => measure distance in grid-fitted outline
+ *
+ * XXX: UNDOCUMENTED: `zp0 - zp1', and not `zp2 - zp1!
+ */
static void
Ins_MD( TT_ExecContext exc,
FT_Long* args )
@@ -4902,12 +4958,12 @@
}
- /*************************************************************************/
- /* */
- /* SDPvTL[a]: Set Dual PVector to Line */
- /* Opcode range: 0x86-0x87 */
- /* Stack: uint32 uint32 --> */
- /* */
+ /**************************************************************************
+ *
+ * SDPvTL[a]: Set Dual PVector to Line
+ * Opcode range: 0x86-0x87
+ * Stack: uint32 uint32 -->
+ */
static void
Ins_SDPVTL( TT_ExecContext exc,
FT_Long* args )
@@ -4985,12 +5041,12 @@
}
- /*************************************************************************/
- /* */
- /* SZP0[]: Set Zone Pointer 0 */
- /* Opcode range: 0x13 */
- /* Stack: uint32 --> */
- /* */
+ /**************************************************************************
+ *
+ * SZP0[]: Set Zone Pointer 0
+ * Opcode range: 0x13
+ * Stack: uint32 -->
+ */
static void
Ins_SZP0( TT_ExecContext exc,
FT_Long* args )
@@ -5015,12 +5071,12 @@
}
- /*************************************************************************/
- /* */
- /* SZP1[]: Set Zone Pointer 1 */
- /* Opcode range: 0x14 */
- /* Stack: uint32 --> */
- /* */
+ /**************************************************************************
+ *
+ * SZP1[]: Set Zone Pointer 1
+ * Opcode range: 0x14
+ * Stack: uint32 -->
+ */
static void
Ins_SZP1( TT_ExecContext exc,
FT_Long* args )
@@ -5045,12 +5101,12 @@
}
- /*************************************************************************/
- /* */
- /* SZP2[]: Set Zone Pointer 2 */
- /* Opcode range: 0x15 */
- /* Stack: uint32 --> */
- /* */
+ /**************************************************************************
+ *
+ * SZP2[]: Set Zone Pointer 2
+ * Opcode range: 0x15
+ * Stack: uint32 -->
+ */
static void
Ins_SZP2( TT_ExecContext exc,
FT_Long* args )
@@ -5075,12 +5131,12 @@
}
- /*************************************************************************/
- /* */
- /* SZPS[]: Set Zone PointerS */
- /* Opcode range: 0x16 */
- /* Stack: uint32 --> */
- /* */
+ /**************************************************************************
+ *
+ * SZPS[]: Set Zone PointerS
+ * Opcode range: 0x16
+ * Stack: uint32 -->
+ */
static void
Ins_SZPS( TT_ExecContext exc,
FT_Long* args )
@@ -5110,12 +5166,12 @@
}
- /*************************************************************************/
- /* */
- /* INSTCTRL[]: INSTruction ConTRoL */
- /* Opcode range: 0x8E */
- /* Stack: int32 int32 --> */
- /* */
+ /**************************************************************************
+ *
+ * INSTCTRL[]: INSTruction ConTRoL
+ * Opcode range: 0x8E
+ * Stack: int32 int32 -->
+ */
static void
Ins_INSTCTRL( TT_ExecContext exc,
FT_Long* args )
@@ -5172,12 +5228,12 @@
}
- /*************************************************************************/
- /* */
- /* SCANCTRL[]: SCAN ConTRoL */
- /* Opcode range: 0x85 */
- /* Stack: uint32? --> */
- /* */
+ /**************************************************************************
+ *
+ * SCANCTRL[]: SCAN ConTRoL
+ * Opcode range: 0x85
+ * Stack: uint32? -->
+ */
static void
Ins_SCANCTRL( TT_ExecContext exc,
FT_Long* args )
@@ -5219,12 +5275,12 @@
}
- /*************************************************************************/
- /* */
- /* SCANTYPE[]: SCAN TYPE */
- /* Opcode range: 0x8D */
- /* Stack: uint16 --> */
- /* */
+ /**************************************************************************
+ *
+ * SCANTYPE[]: SCAN TYPE
+ * Opcode range: 0x8D
+ * Stack: uint16 -->
+ */
static void
Ins_SCANTYPE( TT_ExecContext exc,
FT_Long* args )
@@ -5234,19 +5290,19 @@
}
- /*************************************************************************/
- /* */
- /* MANAGING OUTLINES */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * MANAGING OUTLINES
+ *
+ */
- /*************************************************************************/
- /* */
- /* FLIPPT[]: FLIP PoinT */
- /* Opcode range: 0x80 */
- /* Stack: uint32... --> */
- /* */
+ /**************************************************************************
+ *
+ * FLIPPT[]: FLIP PoinT
+ * Opcode range: 0x80
+ * Stack: uint32... -->
+ */
static void
Ins_FLIPPT( TT_ExecContext exc )
{
@@ -5295,12 +5351,12 @@
}
- /*************************************************************************/
- /* */
- /* FLIPRGON[]: FLIP RanGe ON */
- /* Opcode range: 0x81 */
- /* Stack: uint32 uint32 --> */
- /* */
+ /**************************************************************************
+ *
+ * FLIPRGON[]: FLIP RanGe ON
+ * Opcode range: 0x81
+ * Stack: uint32 uint32 -->
+ */
static void
Ins_FLIPRGON( TT_ExecContext exc,
FT_Long* args )
@@ -5333,12 +5389,12 @@
}
- /*************************************************************************/
- /* */
- /* FLIPRGOFF: FLIP RanGe OFF */
- /* Opcode range: 0x82 */
- /* Stack: uint32 uint32 --> */
- /* */
+ /**************************************************************************
+ *
+ * FLIPRGOFF: FLIP RanGe OFF
+ * Opcode range: 0x82
+ * Stack: uint32 uint32 -->
+ */
static void
Ins_FLIPRGOFF( TT_ExecContext exc,
FT_Long* args )
@@ -5450,12 +5506,12 @@
}
- /*************************************************************************/
- /* */
- /* SHP[a]: SHift Point by the last point */
- /* Opcode range: 0x32-0x33 */
- /* Stack: uint32... --> */
- /* */
+ /**************************************************************************
+ *
+ * SHP[a]: SHift Point by the last point
+ * Opcode range: 0x32-0x33
+ * Stack: uint32... -->
+ */
static void
Ins_SHP( TT_ExecContext exc )
{
@@ -5507,16 +5563,16 @@
}
- /*************************************************************************/
- /* */
- /* SHC[a]: SHift Contour */
- /* Opcode range: 0x34-35 */
- /* Stack: uint32 --> */
- /* */
- /* UNDOCUMENTED: According to Greg Hitchcock, there is one (virtual) */
- /* contour in the twilight zone, namely contour number */
- /* zero which includes all points of it. */
- /* */
+ /**************************************************************************
+ *
+ * SHC[a]: SHift Contour
+ * Opcode range: 0x34-35
+ * Stack: uint32 -->
+ *
+ * UNDOCUMENTED: According to Greg Hitchcock, there is one (virtual)
+ * contour in the twilight zone, namely contour number
+ * zero which includes all points of it.
+ */
static void
Ins_SHC( TT_ExecContext exc,
FT_Long* args )
@@ -5563,12 +5619,12 @@
}
- /*************************************************************************/
- /* */
- /* SHZ[a]: SHift Zone */
- /* Opcode range: 0x36-37 */
- /* Stack: uint32 --> */
- /* */
+ /**************************************************************************
+ *
+ * SHZ[a]: SHift Zone
+ * Opcode range: 0x36-37
+ * Stack: uint32 -->
+ */
static void
Ins_SHZ( TT_ExecContext exc,
FT_Long* args )
@@ -5611,12 +5667,12 @@
}
- /*************************************************************************/
- /* */
- /* SHPIX[]: SHift points by a PIXel amount */
- /* Opcode range: 0x38 */
- /* Stack: f26.6 uint32... --> */
- /* */
+ /**************************************************************************
+ *
+ * SHPIX[]: SHift points by a PIXel amount
+ * Opcode range: 0x38
+ * Stack: f26.6 uint32... -->
+ */
static void
Ins_SHPIX( TT_ExecContext exc,
FT_Long* args )
@@ -5771,12 +5827,12 @@
}
- /*************************************************************************/
- /* */
- /* MSIRP[a]: Move Stack Indirect Relative Position */
- /* Opcode range: 0x3A-0x3B */
- /* Stack: f26.6 uint32 --> */
- /* */
+ /**************************************************************************
+ *
+ * MSIRP[a]: Move Stack Indirect Relative Position
+ * Opcode range: 0x3A-0x3B
+ * Stack: f26.6 uint32 -->
+ */
static void
Ins_MSIRP( TT_ExecContext exc,
FT_Long* args )
@@ -5846,12 +5902,12 @@
}
- /*************************************************************************/
- /* */
- /* MDAP[a]: Move Direct Absolute Point */
- /* Opcode range: 0x2E-0x2F */
- /* Stack: uint32 --> */
- /* */
+ /**************************************************************************
+ *
+ * MDAP[a]: Move Direct Absolute Point
+ * Opcode range: 0x2E-0x2F
+ * Stack: uint32 -->
+ */
static void
Ins_MDAP( TT_ExecContext exc,
FT_Long* args )
@@ -5900,12 +5956,12 @@
}
- /*************************************************************************/
- /* */
- /* MIAP[a]: Move Indirect Absolute Point */
- /* Opcode range: 0x3E-0x3F */
- /* Stack: uint32 uint32 --> */
- /* */
+ /**************************************************************************
+ *
+ * MIAP[a]: Move Indirect Absolute Point
+ * Opcode range: 0x3E-0x3F
+ * Stack: uint32 uint32 -->
+ */
static void
Ins_MIAP( TT_ExecContext exc,
FT_Long* args )
@@ -6020,12 +6076,12 @@
}
- /*************************************************************************/
- /* */
- /* MDRP[abcde]: Move Direct Relative Point */
- /* Opcode range: 0xC0-0xDF */
- /* Stack: uint32 --> */
- /* */
+ /**************************************************************************
+ *
+ * MDRP[abcde]: Move Direct Relative Point
+ * Opcode range: 0xC0-0xDF
+ * Stack: uint32 -->
+ */
static void
Ins_MDRP( TT_ExecContext exc,
FT_Long* args )
@@ -6164,12 +6220,12 @@
}
- /*************************************************************************/
- /* */
- /* MIRP[abcde]: Move Indirect Relative Point */
- /* Opcode range: 0xE0-0xFF */
- /* Stack: int32? uint32 --> */
- /* */
+ /**************************************************************************
+ *
+ * MIRP[abcde]: Move Indirect Relative Point
+ * Opcode range: 0xE0-0xFF
+ * Stack: int32? uint32 -->
+ */
static void
Ins_MIRP( TT_ExecContext exc,
FT_Long* args )
@@ -6189,6 +6245,8 @@
FT_Bool reverse_move = FALSE;
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
+ FT_F26Dot6 delta;
+
minimum_distance = exc->GS.minimum_distance;
control_value_cutin = exc->GS.control_value_cutin;
@@ -6221,8 +6279,11 @@
/* single width test */
- if ( FT_ABS( cvt_dist - exc->GS.single_width_value ) <
- exc->GS.single_width_cutin )
+ delta = SUB_LONG( cvt_dist, exc->GS.single_width_value );
+ if ( delta < 0 )
+ delta = NEG_LONG( delta );
+
+ if ( delta < exc->GS.single_width_cutin )
{
if ( cvt_dist >= 0 )
cvt_dist = exc->GS.single_width_value;
@@ -6251,7 +6312,7 @@
if ( exc->GS.auto_flip )
{
if ( ( org_dist ^ cvt_dist ) < 0 )
- cvt_dist = -cvt_dist;
+ cvt_dist = NEG_LONG( cvt_dist );
}
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
@@ -6276,9 +6337,6 @@
if ( exc->GS.gep0 == exc->GS.gep1 )
{
- FT_F26Dot6 delta;
-
-
/* XXX: According to Greg Hitchcock, the following wording is */
/* the right one: */
/* */
@@ -6313,9 +6371,6 @@
exc->ignore_x_mode &&
exc->GS.gep0 == exc->GS.gep1 )
{
- FT_F26Dot6 delta;
-
-
delta = SUB_LONG( cvt_dist, org_dist );
if ( delta < 0 )
delta = NEG_LONG( delta );
@@ -6412,12 +6467,12 @@
}
- /*************************************************************************/
- /* */
- /* ALIGNRP[]: ALIGN Relative Point */
- /* Opcode range: 0x3C */
- /* Stack: uint32 uint32... --> */
- /* */
+ /**************************************************************************
+ *
+ * ALIGNRP[]: ALIGN Relative Point
+ * Opcode range: 0x3C
+ * Stack: uint32 uint32... -->
+ */
static void
Ins_ALIGNRP( TT_ExecContext exc )
{
@@ -6475,12 +6530,12 @@
}
- /*************************************************************************/
- /* */
- /* ISECT[]: moves point to InterSECTion */
- /* Opcode range: 0x0F */
- /* Stack: 5 * uint32 --> */
- /* */
+ /**************************************************************************
+ *
+ * ISECT[]: moves point to InterSECTion
+ * Opcode range: 0x0F
+ * Stack: 5 * uint32 -->
+ */
static void
Ins_ISECT( TT_ExecContext exc,
FT_Long* args )
@@ -6571,12 +6626,12 @@
}
- /*************************************************************************/
- /* */
- /* ALIGNPTS[]: ALIGN PoinTS */
- /* Opcode range: 0x27 */
- /* Stack: uint32 uint32 --> */
- /* */
+ /**************************************************************************
+ *
+ * ALIGNPTS[]: ALIGN PoinTS
+ * Opcode range: 0x27
+ * Stack: uint32 uint32 -->
+ */
static void
Ins_ALIGNPTS( TT_ExecContext exc,
FT_Long* args )
@@ -6603,12 +6658,12 @@
}
- /*************************************************************************/
- /* */
- /* IP[]: Interpolate Point */
- /* Opcode range: 0x39 */
- /* Stack: uint32... --> */
- /* */
+ /**************************************************************************
+ *
+ * IP[]: Interpolate Point
+ * Opcode range: 0x39
+ * Stack: uint32... -->
+ */
/* SOMETIMES, DUMBER CODE IS BETTER CODE */
@@ -6763,12 +6818,12 @@
}
- /*************************************************************************/
- /* */
- /* UTP[a]: UnTouch Point */
- /* Opcode range: 0x29 */
- /* Stack: uint32 --> */
- /* */
+ /**************************************************************************
+ *
+ * UTP[a]: UnTouch Point
+ * Opcode range: 0x29
+ * Stack: uint32 -->
+ */
static void
Ins_UTP( TT_ExecContext exc,
FT_Long* args )
@@ -6932,12 +6987,12 @@
}
- /*************************************************************************/
- /* */
- /* IUP[a]: Interpolate Untouched Points */
- /* Opcode range: 0x30-0x31 */
- /* Stack: --> */
- /* */
+ /**************************************************************************
+ *
+ * IUP[a]: Interpolate Untouched Points
+ * Opcode range: 0x30-0x31
+ * Stack: -->
+ */
static void
Ins_IUP( TT_ExecContext exc )
{
@@ -7060,12 +7115,12 @@
}
- /*************************************************************************/
- /* */
- /* DELTAPn[]: DELTA exceptions P1, P2, P3 */
- /* Opcode range: 0x5D,0x71,0x72 */
- /* Stack: uint32 (2 * uint32)... --> */
- /* */
+ /**************************************************************************
+ *
+ * DELTAPn[]: DELTA exceptions P1, P2, P3
+ * Opcode range: 0x5D,0x71,0x72
+ * Stack: uint32 (2 * uint32)... -->
+ */
static void
Ins_DELTAP( TT_ExecContext exc,
FT_Long* args )
@@ -7142,12 +7197,12 @@
if ( SUBPIXEL_HINTING_INFINALITY )
{
/*
- * Allow delta move if
+ * Allow delta move if
*
- * - not using ignore_x_mode rendering,
- * - glyph is specifically set to allow it, or
- * - glyph is composite and freedom vector is not in subpixel
- * direction.
+ * - not using ignore_x_mode rendering,
+ * - glyph is specifically set to allow it, or
+ * - glyph is composite and freedom vector is not in subpixel
+ * direction.
*/
if ( !exc->ignore_x_mode ||
( exc->sph_tweak_flags & SPH_TWEAK_ALWAYS_DO_DELTAP ) ||
@@ -7227,12 +7282,12 @@
}
- /*************************************************************************/
- /* */
- /* DELTACn[]: DELTA exceptions C1, C2, C3 */
- /* Opcode range: 0x73,0x74,0x75 */
- /* Stack: uint32 (2 * uint32)... --> */
- /* */
+ /**************************************************************************
+ *
+ * DELTACn[]: DELTA exceptions C1, C2, C3
+ * Opcode range: 0x73,0x74,0x75
+ * Stack: uint32 (2 * uint32)... -->
+ */
static void
Ins_DELTAC( TT_ExecContext exc,
FT_Long* args )
@@ -7305,27 +7360,27 @@
}
- /*************************************************************************/
- /* */
- /* MISC. INSTRUCTIONS */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * MISC. INSTRUCTIONS
+ *
+ */
- /*************************************************************************/
- /* */
- /* GETINFO[]: GET INFOrmation */
- /* Opcode range: 0x88 */
- /* Stack: uint32 --> uint32 */
- /* */
- /* XXX: UNDOCUMENTED: Selector bits higher than 9 are currently (May */
- /* 2015) not documented in the OpenType specification. */
- /* */
- /* Selector bit 11 is incorrectly described as bit 8, while the */
- /* real meaning of bit 8 (vertical LCD subpixels) stays */
- /* undocumented. The same mistake can be found in Greg Hitchcock's */
- /* whitepaper. */
- /* */
+ /**************************************************************************
+ *
+ * GETINFO[]: GET INFOrmation
+ * Opcode range: 0x88
+ * Stack: uint32 --> uint32
+ *
+ * XXX: UNDOCUMENTED: Selector bits higher than 9 are currently (May
+ * 2015) not documented in the OpenType specification.
+ *
+ * Selector bit 11 is incorrectly described as bit 8, while the
+ * real meaning of bit 8 (vertical LCD subpixels) stays
+ * undocumented. The same mistake can be found in Greg Hitchcock's
+ * whitepaper.
+ */
static void
Ins_GETINFO( TT_ExecContext exc,
FT_Long* args )
@@ -7337,11 +7392,11 @@
K = 0;
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- /********************************/
- /* RASTERIZER VERSION */
- /* Selector Bit: 0 */
- /* Return Bit(s): 0-7 */
- /* */
+ /*********************************
+ * RASTERIZER VERSION
+ * Selector Bit: 0
+ * Return Bit(s): 0-7
+ */
if ( SUBPIXEL_HINTING_INFINALITY &&
( args[0] & 1 ) != 0 &&
exc->subpixel_hinting )
@@ -7362,39 +7417,40 @@
if ( ( args[0] & 1 ) != 0 )
K = driver->interpreter_version;
- /********************************/
- /* GLYPH ROTATED */
- /* Selector Bit: 1 */
- /* Return Bit(s): 8 */
- /* */
+ /*********************************
+ * GLYPH ROTATED
+ * Selector Bit: 1
+ * Return Bit(s): 8
+ */
if ( ( args[0] & 2 ) != 0 && exc->tt_metrics.rotated )
K |= 1 << 8;
- /********************************/
- /* GLYPH STRETCHED */
- /* Selector Bit: 2 */
- /* Return Bit(s): 9 */
- /* */
+ /*********************************
+ * GLYPH STRETCHED
+ * Selector Bit: 2
+ * Return Bit(s): 9
+ */
if ( ( args[0] & 4 ) != 0 && exc->tt_metrics.stretched )
K |= 1 << 9;
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
- /********************************/
- /* VARIATION GLYPH */
- /* Selector Bit: 3 */
- /* Return Bit(s): 10 */
- /* */
- /* XXX: UNDOCUMENTED! */
+ /*********************************
+ * VARIATION GLYPH
+ * Selector Bit: 3
+ * Return Bit(s): 10
+ *
+ * XXX: UNDOCUMENTED!
+ */
if ( (args[0] & 8 ) != 0 && exc->face->blend )
K |= 1 << 10;
#endif
- /********************************/
- /* BI-LEVEL HINTING AND */
- /* GRAYSCALE RENDERING */
- /* Selector Bit: 5 */
- /* Return Bit(s): 12 */
- /* */
+ /*********************************
+ * BI-LEVEL HINTING AND
+ * GRAYSCALE RENDERING
+ * Selector Bit: 5
+ * Return Bit(s): 12
+ */
if ( ( args[0] & 32 ) != 0 && exc->grayscale )
K |= 1 << 12;
@@ -7405,50 +7461,54 @@
/* Bold Italic'. */
if ( SUBPIXEL_HINTING_MINIMAL && exc->subpixel_hinting_lean )
{
- /********************************/
- /* HINTING FOR SUBPIXEL */
- /* Selector Bit: 6 */
- /* Return Bit(s): 13 */
- /* */
- /* v40 does subpixel hinting by default. */
+ /*********************************
+ * HINTING FOR SUBPIXEL
+ * Selector Bit: 6
+ * Return Bit(s): 13
+ *
+ * v40 does subpixel hinting by default.
+ */
if ( ( args[0] & 64 ) != 0 )
K |= 1 << 13;
- /********************************/
- /* VERTICAL LCD SUBPIXELS? */
- /* Selector Bit: 8 */
- /* Return Bit(s): 15 */
- /* */
+ /*********************************
+ * VERTICAL LCD SUBPIXELS?
+ * Selector Bit: 8
+ * Return Bit(s): 15
+ */
if ( ( args[0] & 256 ) != 0 && exc->vertical_lcd_lean )
K |= 1 << 15;
- /********************************/
- /* SUBPIXEL POSITIONED? */
- /* Selector Bit: 10 */
- /* Return Bit(s): 17 */
- /* */
- /* XXX: FreeType supports it, dependent on what client does? */
+ /*********************************
+ * SUBPIXEL POSITIONED?
+ * Selector Bit: 10
+ * Return Bit(s): 17
+ *
+ * XXX: FreeType supports it, dependent on what client does?
+ */
if ( ( args[0] & 1024 ) != 0 )
K |= 1 << 17;
- /********************************/
- /* SYMMETRICAL SMOOTHING */
- /* Selector Bit: 11 */
- /* Return Bit(s): 18 */
- /* */
- /* The only smoothing method FreeType supports unless someone sets */
- /* FT_LOAD_TARGET_MONO. */
+ /*********************************
+ * SYMMETRICAL SMOOTHING
+ * Selector Bit: 11
+ * Return Bit(s): 18
+ *
+ * The only smoothing method FreeType supports unless someone sets
+ * FT_LOAD_TARGET_MONO.
+ */
if ( ( args[0] & 2048 ) != 0 && exc->subpixel_hinting_lean )
K |= 1 << 18;
- /********************************/
- /* CLEARTYPE HINTING AND */
- /* GRAYSCALE RENDERING */
- /* Selector Bit: 12 */
- /* Return Bit(s): 19 */
- /* */
- /* Grayscale rendering is what FreeType does anyway unless someone */
- /* sets FT_LOAD_TARGET_MONO or FT_LOAD_TARGET_LCD(_V) */
+ /*********************************
+ * CLEARTYPE HINTING AND
+ * GRAYSCALE RENDERING
+ * Selector Bit: 12
+ * Return Bit(s): 19
+ *
+ * Grayscale rendering is what FreeType does anyway unless someone
+ * sets FT_LOAD_TARGET_MONO or FT_LOAD_TARGET_LCD(_V)
+ */
if ( ( args[0] & 4096 ) != 0 && exc->grayscale_cleartype )
K |= 1 << 19;
}
@@ -7462,67 +7522,73 @@
if ( exc->rasterizer_version >= 37 )
{
- /********************************/
- /* HINTING FOR SUBPIXEL */
- /* Selector Bit: 6 */
- /* Return Bit(s): 13 */
- /* */
+ /*********************************
+ * HINTING FOR SUBPIXEL
+ * Selector Bit: 6
+ * Return Bit(s): 13
+ */
if ( ( args[0] & 64 ) != 0 && exc->subpixel_hinting )
K |= 1 << 13;
- /********************************/
- /* COMPATIBLE WIDTHS ENABLED */
- /* Selector Bit: 7 */
- /* Return Bit(s): 14 */
- /* */
- /* Functionality still needs to be added */
+ /*********************************
+ * COMPATIBLE WIDTHS ENABLED
+ * Selector Bit: 7
+ * Return Bit(s): 14
+ *
+ * Functionality still needs to be added
+ */
if ( ( args[0] & 128 ) != 0 && exc->compatible_widths )
K |= 1 << 14;
- /********************************/
- /* VERTICAL LCD SUBPIXELS? */
- /* Selector Bit: 8 */
- /* Return Bit(s): 15 */
- /* */
- /* Functionality still needs to be added */
+ /*********************************
+ * VERTICAL LCD SUBPIXELS?
+ * Selector Bit: 8
+ * Return Bit(s): 15
+ *
+ * Functionality still needs to be added
+ */
if ( ( args[0] & 256 ) != 0 && exc->vertical_lcd )
K |= 1 << 15;
- /********************************/
- /* HINTING FOR BGR? */
- /* Selector Bit: 9 */
- /* Return Bit(s): 16 */
- /* */
- /* Functionality still needs to be added */
+ /*********************************
+ * HINTING FOR BGR?
+ * Selector Bit: 9
+ * Return Bit(s): 16
+ *
+ * Functionality still needs to be added
+ */
if ( ( args[0] & 512 ) != 0 && exc->bgr )
K |= 1 << 16;
if ( exc->rasterizer_version >= 38 )
{
- /********************************/
- /* SUBPIXEL POSITIONED? */
- /* Selector Bit: 10 */
- /* Return Bit(s): 17 */
- /* */
- /* Functionality still needs to be added */
+ /*********************************
+ * SUBPIXEL POSITIONED?
+ * Selector Bit: 10
+ * Return Bit(s): 17
+ *
+ * Functionality still needs to be added
+ */
if ( ( args[0] & 1024 ) != 0 && exc->subpixel_positioned )
K |= 1 << 17;
- /********************************/
- /* SYMMETRICAL SMOOTHING */
- /* Selector Bit: 11 */
- /* Return Bit(s): 18 */
- /* */
- /* Functionality still needs to be added */
+ /*********************************
+ * SYMMETRICAL SMOOTHING
+ * Selector Bit: 11
+ * Return Bit(s): 18
+ *
+ * Functionality still needs to be added
+ */
if ( ( args[0] & 2048 ) != 0 && exc->symmetrical_smoothing )
K |= 1 << 18;
- /********************************/
- /* GRAY CLEARTYPE */
- /* Selector Bit: 12 */
- /* Return Bit(s): 19 */
- /* */
- /* Functionality still needs to be added */
+ /*********************************
+ * GRAY CLEARTYPE
+ * Selector Bit: 12
+ * Return Bit(s): 19
+ *
+ * Functionality still needs to be added
+ */
if ( ( args[0] & 4096 ) != 0 && exc->gray_cleartype )
K |= 1 << 19;
}
@@ -7537,16 +7603,16 @@
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
- /*************************************************************************/
- /* */
- /* GETVARIATION[]: get normalized variation (blend) coordinates */
- /* Opcode range: 0x91 */
- /* Stack: --> f2.14... */
- /* */
- /* XXX: UNDOCUMENTED! There is no official documentation from Apple for */
- /* this bytecode instruction. Active only if a font has GX */
- /* variation axes. */
- /* */
+ /**************************************************************************
+ *
+ * GETVARIATION[]: get normalized variation (blend) coordinates
+ * Opcode range: 0x91
+ * Stack: --> f2.14...
+ *
+ * XXX: UNDOCUMENTED! There is no official documentation from Apple for
+ * this bytecode instruction. Active only if a font has GX
+ * variation axes.
+ */
static void
Ins_GETVARIATION( TT_ExecContext exc,
FT_Long* args )
@@ -7576,15 +7642,15 @@
}
- /*************************************************************************/
- /* */
- /* GETDATA[]: no idea what this is good for */
- /* Opcode range: 0x92 */
- /* Stack: --> 17 */
- /* */
- /* XXX: UNDOCUMENTED! There is no documentation from Apple for this */
- /* very weird bytecode instruction. */
- /* */
+ /**************************************************************************
+ *
+ * GETDATA[]: no idea what this is good for
+ * Opcode range: 0x92
+ * Stack: --> 17
+ *
+ * XXX: UNDOCUMENTED! There is no documentation from Apple for this
+ * very weird bytecode instruction.
+ */
static void
Ins_GETDATA( FT_Long* args )
{
@@ -7632,34 +7698,34 @@
}
- /*************************************************************************/
- /* */
- /* RUN */
- /* */
- /* This function executes a run of opcodes. It will exit in the */
- /* following cases: */
- /* */
- /* - Errors (in which case it returns FALSE). */
- /* */
- /* - Reaching the end of the main code range (returns TRUE). */
- /* Reaching the end of a code range within a function call is an */
- /* error. */
- /* */
- /* - After executing one single opcode, if the flag `Instruction_Trap' */
- /* is set to TRUE (returns TRUE). */
- /* */
- /* On exit with TRUE, test IP < CodeSize to know whether it comes from */
- /* an instruction trap or a normal termination. */
- /* */
- /* */
- /* Note: The documented DEBUG opcode pops a value from the stack. This */
- /* behaviour is unsupported; here a DEBUG opcode is always an */
- /* error. */
- /* */
- /* */
- /* THIS IS THE INTERPRETER'S MAIN LOOP. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * RUN
+ *
+ * This function executes a run of opcodes. It will exit in the
+ * following cases:
+ *
+ * - Errors (in which case it returns FALSE).
+ *
+ * - Reaching the end of the main code range (returns TRUE).
+ * Reaching the end of a code range within a function call is an
+ * error.
+ *
+ * - After executing one single opcode, if the flag `Instruction_Trap'
+ * is set to TRUE (returns TRUE).
+ *
+ * On exit with TRUE, test IP < CodeSize to know whether it comes from
+ * an instruction trap or a normal termination.
+ *
+ *
+ * Note: The documented DEBUG opcode pops a value from the stack. This
+ * behaviour is unsupported; here a DEBUG opcode is always an
+ * error.
+ *
+ *
+ * THIS IS THE INTERPRETER'S MAIN LOOP.
+ *
+ */
/* documentation is in ttinterp.h */
@@ -7691,16 +7757,16 @@
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
/*
- * Toggle backward compatibility according to what font wants, except
- * when
+ * Toggle backward compatibility according to what font wants, except
+ * when
*
- * 1) we have a `tricky' font that heavily relies on the interpreter to
- * render glyphs correctly, for example DFKai-SB, or
- * 2) FT_RENDER_MODE_MONO (i.e, monochome rendering) is requested.
+ * 1) we have a `tricky' font that heavily relies on the interpreter to
+ * render glyphs correctly, for example DFKai-SB, or
+ * 2) FT_RENDER_MODE_MONO (i.e, monochome rendering) is requested.
*
- * In those cases, backward compatibility needs to be turned off to get
- * correct rendering. The rendering is then completely up to the
- * font's programming.
+ * In those cases, backward compatibility needs to be turned off to get
+ * correct rendering. The rendering is then completely up to the
+ * font's programming.
*
*/
if ( SUBPIXEL_HINTING_MINIMAL &&
@@ -7801,7 +7867,7 @@
/* and the first few stack elements also */
FT_TRACE6(( " " ));
FT_TRACE7(( "%06d ", exc->IP ));
- FT_TRACE6(( opcode_name[exc->opcode] + 2 ));
+ FT_TRACE6(( "%s", opcode_name[exc->opcode] + 2 ));
FT_TRACE7(( "%*s", *opcode_name[exc->opcode] == 'A'
? 2
: 12 - ( *opcode_name[exc->opcode] - '0' ),
diff --git a/thirdparty/freetype/src/truetype/ttinterp.h b/thirdparty/freetype/src/truetype/ttinterp.h
index 2966439ea2..0cb1e892fb 100644
--- a/thirdparty/freetype/src/truetype/ttinterp.h
+++ b/thirdparty/freetype/src/truetype/ttinterp.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ttinterp.h */
-/* */
-/* TrueType bytecode interpreter (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ttinterp.h
+ *
+ * TrueType bytecode interpreter (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef TTINTERP_H_
@@ -26,10 +26,10 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* Rounding mode constants. */
- /* */
+ /**************************************************************************
+ *
+ * Rounding mode constants.
+ */
#define TT_Round_Off 5
#define TT_Round_To_Half_Grid 0
#define TT_Round_To_Grid 1
@@ -40,13 +40,13 @@ FT_BEGIN_HEADER
#define TT_Round_Super_45 7
- /*************************************************************************/
- /* */
- /* Function types used by the interpreter, depending on various modes */
- /* (e.g. the rounding mode, whether to render a vertical or horizontal */
- /* line etc). */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * Function types used by the interpreter, depending on various modes
+ * (e.g. the rounding mode, whether to render a vertical or horizontal
+ * line etc).
+ *
+ */
/* Rounding function */
typedef FT_F26Dot6
@@ -84,10 +84,10 @@ FT_BEGIN_HEADER
FT_F26Dot6 value );
- /*************************************************************************/
- /* */
- /* This structure defines a call record, used to manage function calls. */
- /* */
+ /**************************************************************************
+ *
+ * This structure defines a call record, used to manage function calls.
+ */
typedef struct TT_CallRec_
{
FT_Int Caller_Range;
@@ -101,11 +101,11 @@ FT_BEGIN_HEADER
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- /*************************************************************************/
- /* */
- /* These structures define rules used to tweak subpixel hinting for */
- /* various fonts. "", 0, "", NULL value indicates to match any value. */
- /* */
+ /**************************************************************************
+ *
+ * These structures define rules used to tweak subpixel hinting for
+ * various fonts. "", 0, "", NULL value indicates to match any value.
+ */
#define SPH_MAX_NAME_SIZE 32
#define SPH_MAX_CLASS_MEMBERS 100
@@ -141,11 +141,11 @@ FT_BEGIN_HEADER
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
- /*************************************************************************/
- /* */
- /* The main structure for the interpreter which collects all necessary */
- /* variables and states. */
- /* */
+ /**************************************************************************
+ *
+ * The main structure for the interpreter which collects all necessary
+ * variables and states.
+ */
typedef struct TT_ExecContextRec_
{
TT_Face face;
@@ -352,7 +352,7 @@ FT_BEGIN_HEADER
* https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx
*
* [3] Beat Stamm describes it in more detail:
- * http://www.beatstamm.com/typography/RTRCh4.htm#Sec12
+ * http://rastertragedy.com/RTRCh4.htm#Sec12.
*
* [4] The list of `native ClearType' fonts is small at the time of this
* writing; I found the following on a Windows 10 Update 1511
@@ -464,26 +464,27 @@ FT_BEGIN_HEADER
#endif /* TT_USE_BYTECODE_INTERPRETER */
- /*************************************************************************/
- /* */
- /* <Function> */
- /* TT_New_Context */
- /* */
- /* <Description> */
- /* Queries the face context for a given font. Note that there is */
- /* now a _single_ execution context in the TrueType driver which is */
- /* shared among faces. */
- /* */
- /* <Input> */
- /* face :: A handle to the source face object. */
- /* */
- /* <Return> */
- /* A handle to the execution context. Initialized for `face'. */
- /* */
- /* <Note> */
- /* Only the glyph loader and debugger should call this function. */
- /* (And right now only the glyph loader uses it.) */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * TT_New_Context
+ *
+ * @Description:
+ * Queries the face context for a given font. Note that there is
+ * now a _single_ execution context in the TrueType driver which is
+ * shared among faces.
+ *
+ * @Input:
+ * face ::
+ * A handle to the source face object.
+ *
+ * @Return:
+ * A handle to the execution context. Initialized for `face'.
+ *
+ * @Note:
+ * Only the glyph loader and debugger should call this function.
+ * (And right now only the glyph loader uses it.)
+ */
FT_EXPORT( TT_ExecContext )
TT_New_Context( TT_Driver driver );
@@ -506,27 +507,28 @@ FT_BEGIN_HEADER
#endif /* TT_USE_BYTECODE_INTERPRETER */
- /*************************************************************************/
- /* */
- /* <Function> */
- /* TT_RunIns */
- /* */
- /* <Description> */
- /* Executes one or more instruction in the execution context. This */
- /* is the main function of the TrueType opcode interpreter. */
- /* */
- /* <Input> */
- /* exec :: A handle to the target execution context. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- /* <Note> */
- /* Only the object manager and debugger should call this function. */
- /* */
- /* This function is publicly exported because it is directly */
- /* invoked by the TrueType debugger. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * TT_RunIns
+ *
+ * @Description:
+ * Executes one or more instruction in the execution context. This
+ * is the main function of the TrueType opcode interpreter.
+ *
+ * @Input:
+ * exec ::
+ * A handle to the target execution context.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ *
+ * @Note:
+ * Only the object manager and debugger should call this function.
+ *
+ * This function is publicly exported because it is directly
+ * invoked by the TrueType debugger.
+ */
FT_EXPORT( FT_Error )
TT_RunIns( TT_ExecContext exec );
diff --git a/thirdparty/freetype/src/truetype/ttobjs.c b/thirdparty/freetype/src/truetype/ttobjs.c
index 6685dc8196..f3a432cedd 100644
--- a/thirdparty/freetype/src/truetype/ttobjs.c
+++ b/thirdparty/freetype/src/truetype/ttobjs.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ttobjs.c */
-/* */
-/* Objects manager (body). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ttobjs.c
+ *
+ * Objects manager (body).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -36,36 +36,37 @@
#include "ttgxvar.h"
#endif
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_ttobjs
+#define FT_COMPONENT ttobjs
#ifdef TT_USE_BYTECODE_INTERPRETER
- /*************************************************************************/
- /* */
- /* GLYPH ZONE FUNCTIONS */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_glyphzone_done */
- /* */
- /* <Description> */
- /* Deallocate a glyph zone. */
- /* */
- /* <Input> */
- /* zone :: A pointer to the target glyph zone. */
- /* */
+ /**************************************************************************
+ *
+ * GLYPH ZONE FUNCTIONS
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_glyphzone_done
+ *
+ * @Description:
+ * Deallocate a glyph zone.
+ *
+ * @Input:
+ * zone ::
+ * A pointer to the target glyph zone.
+ */
FT_LOCAL_DEF( void )
tt_glyphzone_done( TT_GlyphZone zone )
{
@@ -87,27 +88,31 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_glyphzone_new */
- /* */
- /* <Description> */
- /* Allocate a new glyph zone. */
- /* */
- /* <Input> */
- /* memory :: A handle to the current memory object. */
- /* */
- /* maxPoints :: The capacity of glyph zone in points. */
- /* */
- /* maxContours :: The capacity of glyph zone in contours. */
- /* */
- /* <Output> */
- /* zone :: A pointer to the target glyph zone record. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_glyphzone_new
+ *
+ * @Description:
+ * Allocate a new glyph zone.
+ *
+ * @Input:
+ * memory ::
+ * A handle to the current memory object.
+ *
+ * maxPoints ::
+ * The capacity of glyph zone in points.
+ *
+ * maxContours ::
+ * The capacity of glyph zone in contours.
+ *
+ * @Output:
+ * zone ::
+ * A pointer to the target glyph zone record.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
tt_glyphzone_new( FT_Memory memory,
FT_UShort maxPoints,
@@ -566,32 +571,37 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_init */
- /* */
- /* <Description> */
- /* Initialize a given TrueType face object. */
- /* */
- /* <Input> */
- /* stream :: The source font stream. */
- /* */
- /* face_index :: The index of the TrueType font, if we are opening a */
- /* collection, in bits 0-15. The numbered instance */
- /* index~+~1 of a GX (sub)font, if applicable, in bits */
- /* 16-30. */
- /* */
- /* num_params :: Number of additional generic parameters. Ignored. */
- /* */
- /* params :: Additional generic parameters. Ignored. */
- /* */
- /* <InOut> */
- /* face :: The newly built face object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_face_init
+ *
+ * @Description:
+ * Initialize a given TrueType face object.
+ *
+ * @Input:
+ * stream ::
+ * The source font stream.
+ *
+ * face_index ::
+ * The index of the TrueType font, if we are opening a
+ * collection, in bits 0-15. The numbered instance
+ * index~+~1 of a GX (sub)font, if applicable, in bits
+ * 16-30.
+ *
+ * num_params ::
+ * Number of additional generic parameters. Ignored.
+ *
+ * params ::
+ * Additional generic parameters. Ignored.
+ *
+ * @InOut:
+ * face ::
+ * The newly built face object.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
tt_face_init( FT_Stream stream,
FT_Face ttface, /* TT_Face */
@@ -743,17 +753,18 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_done */
- /* */
- /* <Description> */
- /* Finalize a given face object. */
- /* */
- /* <Input> */
- /* face :: A pointer to the face object to destroy. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_face_done
+ *
+ * @Description:
+ * Finalize a given face object.
+ *
+ * @Input:
+ * face ::
+ * A pointer to the face object to destroy.
+ */
FT_LOCAL_DEF( void )
tt_face_done( FT_Face ttface ) /* TT_Face */
{
@@ -799,30 +810,32 @@
}
- /*************************************************************************/
- /* */
- /* SIZE FUNCTIONS */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * SIZE FUNCTIONS
+ *
+ */
#ifdef TT_USE_BYTECODE_INTERPRETER
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_size_run_fpgm */
- /* */
- /* <Description> */
- /* Run the font program. */
- /* */
- /* <Input> */
- /* size :: A handle to the size object. */
- /* */
- /* pedantic :: Set if bytecode execution should be pedantic. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_size_run_fpgm
+ *
+ * @Description:
+ * Run the font program.
+ *
+ * @Input:
+ * size ::
+ * A handle to the size object.
+ *
+ * pedantic ::
+ * Set if bytecode execution should be pedantic.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
tt_size_run_fpgm( TT_Size size,
FT_Bool pedantic )
@@ -899,22 +912,24 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_size_run_prep */
- /* */
- /* <Description> */
- /* Run the control value program. */
- /* */
- /* <Input> */
- /* size :: A handle to the size object. */
- /* */
- /* pedantic :: Set if bytecode execution should be pedantic. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_size_run_prep
+ *
+ * @Description:
+ * Run the control value program.
+ *
+ * @Input:
+ * size ::
+ * A handle to the size object.
+ *
+ * pedantic ::
+ * Set if bytecode execution should be pedantic.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
tt_size_run_prep( TT_Size size,
FT_Bool pedantic )
@@ -1159,10 +1174,16 @@
TT_Face face = (TT_Face)size->root.face;
- /* Scale the cvt values to the new ppem. */
- /* We use by default the y ppem to scale the CVT. */
+ /* Scale the cvt values to the new ppem. */
+ /* By default, we use the y ppem value for scaling. */
+ FT_TRACE6(( "CVT values:\n" ));
for ( i = 0; i < size->cvt_size; i++ )
+ {
size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale );
+ FT_TRACE6(( " %3d: %d (%f)\n",
+ i, face->cvt[i], size->cvt[i] / 64.0 ));
+ }
+ FT_TRACE6(( "\n" ));
/* all twilight points are originally zero */
for ( i = 0; i < (FT_UInt)size->twilight.n_points; i++ )
@@ -1191,20 +1212,21 @@
#endif /* TT_USE_BYTECODE_INTERPRETER */
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_size_init */
- /* */
- /* <Description> */
- /* Initialize a new TrueType size object. */
- /* */
- /* <InOut> */
- /* size :: A handle to the size object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_size_init
+ *
+ * @Description:
+ * Initialize a new TrueType size object.
+ *
+ * @InOut:
+ * size ::
+ * A handle to the size object.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
tt_size_init( FT_Size ttsize ) /* TT_Size */
{
@@ -1224,17 +1246,18 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_size_done */
- /* */
- /* <Description> */
- /* The TrueType size object finalizer. */
- /* */
- /* <Input> */
- /* size :: A handle to the target size object. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_size_done
+ *
+ * @Description:
+ * The TrueType size object finalizer.
+ *
+ * @Input:
+ * size ::
+ * A handle to the target size object.
+ */
FT_LOCAL_DEF( void )
tt_size_done( FT_Size ttsize ) /* TT_Size */
{
@@ -1249,22 +1272,24 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_size_reset */
- /* */
- /* <Description> */
- /* Reset a TrueType size when resolutions and character dimensions */
- /* have been changed. */
- /* */
- /* <Input> */
- /* size :: A handle to the target size object. */
- /* */
- /* only_height :: Only recompute ascender, descender, and height; */
- /* this flag is used for variation fonts where */
- /* `tt_size_reset' is used as an iterator function. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_size_reset
+ *
+ * @Description:
+ * Reset a TrueType size when resolutions and character dimensions
+ * have been changed.
+ *
+ * @Input:
+ * size ::
+ * A handle to the target size object.
+ *
+ * only_height ::
+ * Only recompute ascender, descender, and height;
+ * this flag is used for variation fonts where
+ * `tt_size_reset' is used as an iterator function.
+ */
FT_LOCAL_DEF( FT_Error )
tt_size_reset( TT_Size size,
FT_Bool only_height )
@@ -1358,20 +1383,21 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_driver_init */
- /* */
- /* <Description> */
- /* Initialize a given TrueType driver object. */
- /* */
- /* <Input> */
- /* driver :: A handle to the target driver object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_driver_init
+ *
+ * @Description:
+ * Initialize a given TrueType driver object.
+ *
+ * @Input:
+ * driver ::
+ * A handle to the target driver object.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
tt_driver_init( FT_Module ttdriver ) /* TT_Driver */
{
@@ -1398,17 +1424,18 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_driver_done */
- /* */
- /* <Description> */
- /* Finalize a given TrueType driver. */
- /* */
- /* <Input> */
- /* driver :: A handle to the target TrueType driver. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_driver_done
+ *
+ * @Description:
+ * Finalize a given TrueType driver.
+ *
+ * @Input:
+ * driver ::
+ * A handle to the target TrueType driver.
+ */
FT_LOCAL_DEF( void )
tt_driver_done( FT_Module ttdriver ) /* TT_Driver */
{
@@ -1416,20 +1443,21 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_slot_init */
- /* */
- /* <Description> */
- /* Initialize a new slot object. */
- /* */
- /* <InOut> */
- /* slot :: A handle to the slot object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_slot_init
+ *
+ * @Description:
+ * Initialize a new slot object.
+ *
+ * @InOut:
+ * slot ::
+ * A handle to the slot object.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
tt_slot_init( FT_GlyphSlot slot )
{
diff --git a/thirdparty/freetype/src/truetype/ttobjs.h b/thirdparty/freetype/src/truetype/ttobjs.h
index 38fa30e4e9..9fc654d5d1 100644
--- a/thirdparty/freetype/src/truetype/ttobjs.h
+++ b/thirdparty/freetype/src/truetype/ttobjs.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ttobjs.h */
-/* */
-/* Objects manager (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ttobjs.h
+ *
+ * Objects manager (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef TTOBJS_H_
@@ -28,40 +28,40 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* <Type> */
- /* TT_Driver */
- /* */
- /* <Description> */
- /* A handle to a TrueType driver object. */
- /* */
+ /**************************************************************************
+ *
+ * @Type:
+ * TT_Driver
+ *
+ * @Description:
+ * A handle to a TrueType driver object.
+ */
typedef struct TT_DriverRec_* TT_Driver;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* TT_GlyphSlot */
- /* */
- /* <Description> */
- /* A handle to a TrueType glyph slot object. */
- /* */
- /* <Note> */
- /* This is a direct typedef of FT_GlyphSlot, as there is nothing */
- /* specific about the TrueType glyph slot. */
- /* */
+ /**************************************************************************
+ *
+ * @Type:
+ * TT_GlyphSlot
+ *
+ * @Description:
+ * A handle to a TrueType glyph slot object.
+ *
+ * @Note:
+ * This is a direct typedef of FT_GlyphSlot, as there is nothing
+ * specific about the TrueType glyph slot.
+ */
typedef FT_GlyphSlot TT_GlyphSlot;
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* TT_GraphicsState */
- /* */
- /* <Description> */
- /* The TrueType graphics state used during bytecode interpretation. */
- /* */
+ /**************************************************************************
+ *
+ * @Struct:
+ * TT_GraphicsState
+ *
+ * @Description:
+ * The TrueType graphics state used during bytecode interpretation.
+ */
typedef struct TT_GraphicsState_
{
FT_UShort rp0;
@@ -113,25 +113,25 @@ FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* EXECUTION SUBTABLES */
- /* */
- /* These sub-tables relate to instruction execution. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * EXECUTION SUBTABLES
+ *
+ * These sub-tables relate to instruction execution.
+ *
+ */
#define TT_MAX_CODE_RANGES 3
- /*************************************************************************/
- /* */
- /* There can only be 3 active code ranges at once: */
- /* - the Font Program */
- /* - the CVT Program */
- /* - a glyph's instructions set */
- /* */
+ /**************************************************************************
+ *
+ * There can only be 3 active code ranges at once:
+ * - the Font Program
+ * - the CVT Program
+ * - a glyph's instructions set
+ */
typedef enum TT_CodeRange_Tag_
{
tt_coderange_none = 0,
@@ -152,10 +152,10 @@ FT_BEGIN_HEADER
typedef TT_CodeRange TT_CodeRangeTable[TT_MAX_CODE_RANGES];
- /*************************************************************************/
- /* */
- /* Defines a function/instruction definition record. */
- /* */
+ /**************************************************************************
+ *
+ * Defines a function/instruction definition record.
+ */
typedef struct TT_DefRecord_
{
FT_Int range; /* in which code range is it located? */
@@ -169,10 +169,10 @@ FT_BEGIN_HEADER
} TT_DefRecord, *TT_DefArray;
- /*************************************************************************/
- /* */
- /* Subglyph transformation record. */
- /* */
+ /**************************************************************************
+ *
+ * Subglyph transformation record.
+ */
typedef struct TT_Transform_
{
FT_Fixed xx, xy; /* transformation matrix coefficients */
@@ -182,72 +182,72 @@ FT_BEGIN_HEADER
} TT_Transform;
- /*************************************************************************/
- /* */
- /* A note regarding non-squared pixels: */
- /* */
- /* (This text will probably go into some docs at some time; for now, it */
- /* is kept here to explain some definitions in the TT_Size_Metrics */
- /* record). */
- /* */
- /* The CVT is a one-dimensional array containing values that control */
- /* certain important characteristics in a font, like the height of all */
- /* capitals, all lowercase letter, default spacing or stem width/height. */
- /* */
- /* These values are found in FUnits in the font file, and must be scaled */
- /* to pixel coordinates before being used by the CVT and glyph programs. */
- /* Unfortunately, when using distinct x and y resolutions (or distinct x */
- /* and y pointsizes), there are two possible scalings. */
- /* */
- /* A first try was to implement a `lazy' scheme where all values were */
- /* scaled when first used. However, while some values are always used */
- /* in the same direction, some others are used under many different */
- /* circumstances and orientations. */
- /* */
- /* I have found a simpler way to do the same, and it even seems to work */
- /* in most of the cases: */
- /* */
- /* - All CVT values are scaled to the maximum ppem size. */
- /* */
- /* - When performing a read or write in the CVT, a ratio factor is used */
- /* to perform adequate scaling. Example: */
- /* */
- /* x_ppem = 14 */
- /* y_ppem = 10 */
- /* */
- /* We choose ppem = x_ppem = 14 as the CVT scaling size. All cvt */
- /* entries are scaled to it. */
- /* */
- /* x_ratio = 1.0 */
- /* y_ratio = y_ppem/ppem (< 1.0) */
- /* */
- /* We compute the current ratio like: */
- /* */
- /* - If projVector is horizontal, */
- /* ratio = x_ratio = 1.0 */
- /* */
- /* - if projVector is vertical, */
- /* ratio = y_ratio */
- /* */
- /* - else, */
- /* ratio = sqrt( (proj.x * x_ratio) ^ 2 + (proj.y * y_ratio) ^ 2 ) */
- /* */
- /* Reading a cvt value returns */
- /* ratio * cvt[index] */
- /* */
- /* Writing a cvt value in pixels: */
- /* cvt[index] / ratio */
- /* */
- /* The current ppem is simply */
- /* ratio * ppem */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* Metrics used by the TrueType size and context objects. */
- /* */
+ /**************************************************************************
+ *
+ * A note regarding non-squared pixels:
+ *
+ * (This text will probably go into some docs at some time; for now, it
+ * is kept here to explain some definitions in the TT_Size_Metrics
+ * record).
+ *
+ * The CVT is a one-dimensional array containing values that control
+ * certain important characteristics in a font, like the height of all
+ * capitals, all lowercase letter, default spacing or stem width/height.
+ *
+ * These values are found in FUnits in the font file, and must be scaled
+ * to pixel coordinates before being used by the CVT and glyph programs.
+ * Unfortunately, when using distinct x and y resolutions (or distinct x
+ * and y pointsizes), there are two possible scalings.
+ *
+ * A first try was to implement a `lazy' scheme where all values were
+ * scaled when first used. However, while some values are always used
+ * in the same direction, some others are used under many different
+ * circumstances and orientations.
+ *
+ * I have found a simpler way to do the same, and it even seems to work
+ * in most of the cases:
+ *
+ * - All CVT values are scaled to the maximum ppem size.
+ *
+ * - When performing a read or write in the CVT, a ratio factor is used
+ * to perform adequate scaling. Example:
+ *
+ * x_ppem = 14
+ * y_ppem = 10
+ *
+ * We choose ppem = x_ppem = 14 as the CVT scaling size. All cvt
+ * entries are scaled to it.
+ *
+ * x_ratio = 1.0
+ * y_ratio = y_ppem/ppem (< 1.0)
+ *
+ * We compute the current ratio like:
+ *
+ * - If projVector is horizontal,
+ * ratio = x_ratio = 1.0
+ *
+ * - if projVector is vertical,
+ * ratio = y_ratio
+ *
+ * - else,
+ * ratio = sqrt( (proj.x * x_ratio) ^ 2 + (proj.y * y_ratio) ^ 2 )
+ *
+ * Reading a cvt value returns
+ * ratio * cvt[index]
+ *
+ * Writing a cvt value in pixels:
+ * cvt[index] / ratio
+ *
+ * The current ppem is simply
+ * ratio * ppem
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * Metrics used by the TrueType size and context objects.
+ */
typedef struct TT_Size_Metrics_
{
/* for non-square pixels */
@@ -268,10 +268,10 @@ FT_BEGIN_HEADER
} TT_Size_Metrics;
- /*************************************************************************/
- /* */
- /* TrueType size class. */
- /* */
+ /**************************************************************************
+ *
+ * TrueType size class.
+ */
typedef struct TT_SizeRec_
{
FT_SizeRec root;
@@ -324,10 +324,10 @@ FT_BEGIN_HEADER
} TT_SizeRec;
- /*************************************************************************/
- /* */
- /* TrueType driver class. */
- /* */
+ /**************************************************************************
+ *
+ * TrueType driver class.
+ */
typedef struct TT_DriverRec_
{
FT_DriverRec root;
@@ -348,10 +348,10 @@ FT_BEGIN_HEADER
/* will always use the TT driver to create them. */
- /*************************************************************************/
- /* */
- /* Face functions */
- /* */
+ /**************************************************************************
+ *
+ * Face functions
+ */
FT_LOCAL( FT_Error )
tt_face_init( FT_Stream stream,
FT_Face ttface, /* TT_Face */
@@ -363,10 +363,10 @@ FT_BEGIN_HEADER
tt_face_done( FT_Face ttface ); /* TT_Face */
- /*************************************************************************/
- /* */
- /* Size functions */
- /* */
+ /**************************************************************************
+ *
+ * Size functions
+ */
FT_LOCAL( FT_Error )
tt_size_init( FT_Size ttsize ); /* TT_Size */
@@ -394,10 +394,10 @@ FT_BEGIN_HEADER
FT_Bool only_height );
- /*************************************************************************/
- /* */
- /* Driver functions */
- /* */
+ /**************************************************************************
+ *
+ * Driver functions
+ */
FT_LOCAL( FT_Error )
tt_driver_init( FT_Module ttdriver ); /* TT_Driver */
@@ -405,10 +405,10 @@ FT_BEGIN_HEADER
tt_driver_done( FT_Module ttdriver ); /* TT_Driver */
- /*************************************************************************/
- /* */
- /* Slot functions */
- /* */
+ /**************************************************************************
+ *
+ * Slot functions
+ */
FT_LOCAL( FT_Error )
tt_slot_init( FT_GlyphSlot slot );
diff --git a/thirdparty/freetype/src/truetype/ttpic.c b/thirdparty/freetype/src/truetype/ttpic.c
deleted file mode 100644
index cdbb80639e..0000000000
--- a/thirdparty/freetype/src/truetype/ttpic.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/***************************************************************************/
-/* */
-/* ttpic.c */
-/* */
-/* The FreeType position independent code services for truetype module. */
-/* */
-/* Copyright 2009-2018 by */
-/* Oran Agra and Mickey Gabel. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#include <ft2build.h>
-#include FT_FREETYPE_H
-#include FT_INTERNAL_OBJECTS_H
-#include "ttpic.h"
-#include "tterrors.h"
-
-
-#ifdef FT_CONFIG_OPTION_PIC
-
- /* forward declaration of PIC init functions from ttdriver.c */
- FT_Error
- FT_Create_Class_tt_services( FT_Library library,
- FT_ServiceDescRec** output_class );
- void
- FT_Destroy_Class_tt_services( FT_Library library,
- FT_ServiceDescRec* clazz );
- void
- FT_Init_Class_tt_service_gx_multi_masters(
- FT_Service_MultiMastersRec* sv_mm );
- void
- FT_Init_Class_tt_service_truetype_glyf(
- FT_Service_TTGlyfRec* sv_ttglyf );
-
-
- void
- tt_driver_class_pic_free( FT_Library library )
- {
- FT_PIC_Container* pic_container = &library->pic_container;
- FT_Memory memory = library->memory;
-
-
- if ( pic_container->truetype )
- {
- TTModulePIC* container = (TTModulePIC*)pic_container->truetype;
-
-
- if ( container->tt_services )
- FT_Destroy_Class_tt_services( library, container->tt_services );
- container->tt_services = NULL;
- FT_FREE( container );
- pic_container->truetype = NULL;
- }
- }
-
-
- FT_Error
- tt_driver_class_pic_init( FT_Library library )
- {
- FT_PIC_Container* pic_container = &library->pic_container;
- FT_Error error = FT_Err_Ok;
- TTModulePIC* container = NULL;
- FT_Memory memory = library->memory;
-
-
- /* allocate pointer, clear and set global container pointer */
- if ( FT_ALLOC( container, sizeof ( *container ) ) )
- return error;
- FT_MEM_SET( container, 0, sizeof ( *container ) );
- pic_container->truetype = container;
-
- /* initialize pointer table - this is how the module usually */
- /* expects this data */
- error = FT_Create_Class_tt_services( library,
- &container->tt_services );
- if ( error )
- goto Exit;
-#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
- FT_Init_Class_tt_service_gx_multi_masters(
- &container->tt_service_gx_multi_masters );
-#endif
- FT_Init_Class_tt_service_truetype_glyf(
- &container->tt_service_truetype_glyf );
-
- Exit:
- if ( error )
- tt_driver_class_pic_free( library );
- return error;
- }
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
-
-/* END */
diff --git a/thirdparty/freetype/src/truetype/ttpic.h b/thirdparty/freetype/src/truetype/ttpic.h
deleted file mode 100644
index df878ae6f1..0000000000
--- a/thirdparty/freetype/src/truetype/ttpic.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/***************************************************************************/
-/* */
-/* ttpic.h */
-/* */
-/* The FreeType position independent code services for truetype module. */
-/* */
-/* Copyright 2009-2018 by */
-/* Oran Agra and Mickey Gabel. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#ifndef TTPIC_H_
-#define TTPIC_H_
-
-
-#include FT_INTERNAL_PIC_H
-
-
-#ifndef FT_CONFIG_OPTION_PIC
-
-#define TT_SERVICES_GET tt_services
-#define TT_SERVICE_GX_MULTI_MASTERS_GET tt_service_gx_multi_masters
-#define TT_SERVICE_METRICS_VARIATIONS_GET tt_service_metrics_variations
-#define TT_SERVICE_TRUETYPE_GLYF_GET tt_service_truetype_glyf
-#define TT_SERVICE_PROPERTIES_GET tt_service_properties
-
-#else /* FT_CONFIG_OPTION_PIC */
-
-#include FT_MULTIPLE_MASTERS_H
-#include FT_SERVICE_MULTIPLE_MASTERS_H
-#include FT_SERVICE_METRICS_VARIATIONS_H
-#include FT_SERVICE_TRUETYPE_GLYF_H
-#include FT_SERVICE_PROPERTIES_H
-
-
-FT_BEGIN_HEADER
-
- typedef struct TTModulePIC_
- {
- FT_ServiceDescRec* tt_services;
-#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
- FT_Service_MultiMastersRec tt_service_gx_multi_masters;
- FT_Service_MetricsVariationsRec tt_service_metrics_variations;
-#endif
- FT_Service_TTGlyfRec tt_service_truetype_glyf;
- FT_Service_PropertiesRec tt_service_properties;
-
- } TTModulePIC;
-
-
-#define GET_PIC( lib ) \
- ( (TTModulePIC*)((lib)->pic_container.truetype) )
-#define TT_SERVICES_GET \
- ( GET_PIC( library )->tt_services )
-#define TT_SERVICE_METRICS_VARIATIONS_GET \
- ( GET_PIC( library )->tt_service_metrics_variations )
-#define TT_SERVICE_GX_MULTI_MASTERS_GET \
- ( GET_PIC( library )->tt_service_gx_multi_masters )
-#define TT_SERVICE_TRUETYPE_GLYF_GET \
- ( GET_PIC( library )->tt_service_truetype_glyf )
-#define TT_SERVICE_PROPERTIES_GET \
- ( GET_PIC( library )->tt_service_properties )
-
-
- /* see ttpic.c for the implementation */
- void
- tt_driver_class_pic_free( FT_Library library );
-
- FT_Error
- tt_driver_class_pic_init( FT_Library library );
-
-FT_END_HEADER
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
- /* */
-
-#endif /* TTPIC_H_ */
-
-
-/* END */
diff --git a/thirdparty/freetype/src/truetype/ttpload.c b/thirdparty/freetype/src/truetype/ttpload.c
index d9526ad082..e7718bf9b7 100644
--- a/thirdparty/freetype/src/truetype/ttpload.c
+++ b/thirdparty/freetype/src/truetype/ttpload.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ttpload.c */
-/* */
-/* TrueType-specific tables loader (body). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ttpload.c
+ *
+ * TrueType-specific tables loader (body).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -31,33 +31,35 @@
#include "tterrors.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_ttpload
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_load_loca */
- /* */
- /* <Description> */
- /* Load the locations table. */
- /* */
- /* <InOut> */
- /* face :: A handle to the target face object. */
- /* */
- /* <Input> */
- /* stream :: The input stream. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+#define FT_COMPONENT ttpload
+
+
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_face_load_loca
+ *
+ * @Description:
+ * Load the locations table.
+ *
+ * @InOut:
+ * face ::
+ * A handle to the target face object.
+ *
+ * @Input:
+ * stream ::
+ * The input stream.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
tt_face_load_loca( TT_Face face,
FT_Stream stream )
@@ -297,23 +299,25 @@
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_load_cvt */
- /* */
- /* <Description> */
- /* Load the control value table into a face object. */
- /* */
- /* <InOut> */
- /* face :: A handle to the target face object. */
- /* */
- /* <Input> */
- /* stream :: A handle to the input stream. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_face_load_cvt
+ *
+ * @Description:
+ * Load the control value table into a face object.
+ *
+ * @InOut:
+ * face ::
+ * A handle to the target face object.
+ *
+ * @Input:
+ * stream ::
+ * A handle to the input stream.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
tt_face_load_cvt( TT_Face face,
FT_Stream stream )
@@ -378,23 +382,25 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_load_fpgm */
- /* */
- /* <Description> */
- /* Load the font program. */
- /* */
- /* <InOut> */
- /* face :: A handle to the target face object. */
- /* */
- /* <Input> */
- /* stream :: A handle to the input stream. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_face_load_fpgm
+ *
+ * @Description:
+ * Load the font program.
+ *
+ * @InOut:
+ * face ::
+ * A handle to the target face object.
+ *
+ * @Input:
+ * stream ::
+ * A handle to the input stream.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
tt_face_load_fpgm( TT_Face face,
FT_Stream stream )
@@ -440,23 +446,25 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_load_prep */
- /* */
- /* <Description> */
- /* Load the cvt program. */
- /* */
- /* <InOut> */
- /* face :: A handle to the target face object. */
- /* */
- /* <Input> */
- /* stream :: A handle to the input stream. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_face_load_prep
+ *
+ * @Description:
+ * Load the cvt program.
+ *
+ * @InOut:
+ * face ::
+ * A handle to the target face object.
+ *
+ * @Input:
+ * stream ::
+ * A handle to the input stream.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
tt_face_load_prep( TT_Face face,
FT_Stream stream )
@@ -501,22 +509,24 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_load_hdmx */
- /* */
- /* <Description> */
- /* Load the `hdmx' table into the face object. */
- /* */
- /* <Input> */
- /* face :: A handle to the target face object. */
- /* */
- /* stream :: A handle to the input stream. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_face_load_hdmx
+ *
+ * @Description:
+ * Load the `hdmx' table into the face object.
+ *
+ * @Input:
+ * face ::
+ * A handle to the target face object.
+ *
+ * stream ::
+ * A handle to the input stream.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
tt_face_load_hdmx( TT_Face face,
@@ -610,11 +620,11 @@
}
- /*************************************************************************/
- /* */
- /* Return the advance width table for a given pixel size if it is found */
- /* in the font's `hdmx' table (if any). */
- /* */
+ /**************************************************************************
+ *
+ * Return the advance width table for a given pixel size if it is found
+ * in the font's `hdmx' table (if any).
+ */
FT_LOCAL_DEF( FT_Byte* )
tt_face_get_device_metrics( TT_Face face,
FT_UInt ppem,
diff --git a/thirdparty/freetype/src/truetype/ttpload.h b/thirdparty/freetype/src/truetype/ttpload.h
index fa12527247..022750e324 100644
--- a/thirdparty/freetype/src/truetype/ttpload.h
+++ b/thirdparty/freetype/src/truetype/ttpload.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ttpload.h */
-/* */
-/* TrueType-specific tables loader (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ttpload.h
+ *
+ * TrueType-specific tables loader (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef TTPLOAD_H_
diff --git a/thirdparty/freetype/src/truetype/ttsubpix.c b/thirdparty/freetype/src/truetype/ttsubpix.c
index d94bcc8b50..23a2e5b440 100644
--- a/thirdparty/freetype/src/truetype/ttsubpix.c
+++ b/thirdparty/freetype/src/truetype/ttsubpix.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ttsubpix.c */
-/* */
-/* TrueType Subpixel Hinting. */
-/* */
-/* Copyright 2010-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ttsubpix.c
+ *
+ * TrueType Subpixel Hinting.
+ *
+ * Copyright (C) 2010-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
#include FT_INTERNAL_DEBUG_H
@@ -30,35 +30,35 @@
#if defined( TT_USE_BYTECODE_INTERPRETER ) && \
defined( TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY )
- /*************************************************************************/
- /* */
- /* These rules affect how the TT Interpreter does hinting, with the */
- /* goal of doing subpixel hinting by (in general) ignoring x moves. */
- /* Some of these rules are fixes that go above and beyond the */
- /* stated techniques in the MS whitepaper on Cleartype, due to */
- /* artifacts in many glyphs. So, these rules make some glyphs render */
- /* better than they do in the MS rasterizer. */
- /* */
- /* "" string or 0 int/char indicates to apply to all glyphs. */
- /* "-" used as dummy placeholders, but any non-matching string works. */
- /* */
- /* Some of this could arguably be implemented in fontconfig, however: */
- /* */
- /* - Fontconfig can't set things on a glyph-by-glyph basis. */
- /* - The tweaks that happen here are very low-level, from an average */
- /* user's point of view and are best implemented in the hinter. */
- /* */
- /* The goal is to make the subpixel hinting techniques as generalized */
- /* as possible across all fonts to prevent the need for extra rules such */
- /* as these. */
- /* */
- /* The rule structure is designed so that entirely new rules can easily */
- /* be added when a new compatibility feature is discovered. */
- /* */
- /* The rule structures could also use some enhancement to handle ranges. */
- /* */
- /* ****************** WORK IN PROGRESS ******************* */
- /* */
+ /**************************************************************************
+ *
+ * These rules affect how the TT Interpreter does hinting, with the
+ * goal of doing subpixel hinting by (in general) ignoring x moves.
+ * Some of these rules are fixes that go above and beyond the
+ * stated techniques in the MS whitepaper on Cleartype, due to
+ * artifacts in many glyphs. So, these rules make some glyphs render
+ * better than they do in the MS rasterizer.
+ *
+ * "" string or 0 int/char indicates to apply to all glyphs.
+ * "-" used as dummy placeholders, but any non-matching string works.
+ *
+ * Some of this could arguably be implemented in fontconfig, however:
+ *
+ * - Fontconfig can't set things on a glyph-by-glyph basis.
+ * - The tweaks that happen here are very low-level, from an average
+ * user's point of view and are best implemented in the hinter.
+ *
+ * The goal is to make the subpixel hinting techniques as generalized
+ * as possible across all fonts to prevent the need for extra rules such
+ * as these.
+ *
+ * The rule structure is designed so that entirely new rules can easily
+ * be added when a new compatibility feature is discovered.
+ *
+ * The rule structures could also use some enhancement to handle ranges.
+ *
+ * ****************** WORK IN PROGRESS *******************
+ */
/* These are `classes' of fonts that can be grouped together and used in */
/* rules below. A blank entry "" is required at the end of these! */
diff --git a/thirdparty/freetype/src/truetype/ttsubpix.h b/thirdparty/freetype/src/truetype/ttsubpix.h
index 1070bb016f..4966800c2d 100644
--- a/thirdparty/freetype/src/truetype/ttsubpix.h
+++ b/thirdparty/freetype/src/truetype/ttsubpix.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* ttsubpix.h */
-/* */
-/* TrueType Subpixel Hinting. */
-/* */
-/* Copyright 2010-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ttsubpix.h
+ *
+ * TrueType Subpixel Hinting.
+ *
+ * Copyright (C) 2010-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef TTSUBPIX_H_
@@ -29,11 +29,11 @@ FT_BEGIN_HEADER
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- /*************************************************************************/
- /* */
- /* ID flags to identify special functions at FDEF and runtime. */
- /* */
- /* */
+ /**************************************************************************
+ *
+ * ID flags to identify special functions at FDEF and runtime.
+ *
+ */
#define SPH_FDEF_INLINE_DELTA_1 0x0000001
#define SPH_FDEF_INLINE_DELTA_2 0x0000002
#define SPH_FDEF_DIAGONAL_STROKE 0x0000004
@@ -45,11 +45,11 @@ FT_BEGIN_HEADER
#define SPH_FDEF_TYPEMAN_DIAGENDCTRL 0x0000100
- /*************************************************************************/
- /* */
- /* Tweak flags that are set for each glyph by the below rules. */
- /* */
- /* */
+ /**************************************************************************
+ *
+ * Tweak flags that are set for each glyph by the below rules.
+ *
+ */
#define SPH_TWEAK_ALLOW_X_DMOVE 0x0000001UL
#define SPH_TWEAK_ALWAYS_DO_DELTAP 0x0000002UL
#define SPH_TWEAK_ALWAYS_SKIP_DELTAP 0x0000004UL
diff --git a/thirdparty/freetype/src/type1/module.mk b/thirdparty/freetype/src/type1/module.mk
index 3fea5cc16f..2f48c65821 100644
--- a/thirdparty/freetype/src/type1/module.mk
+++ b/thirdparty/freetype/src/type1/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2018 by
+# Copyright (C) 1996-2019 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/type1/rules.mk b/thirdparty/freetype/src/type1/rules.mk
index cb1a142860..901169c7a5 100644
--- a/thirdparty/freetype/src/type1/rules.mk
+++ b/thirdparty/freetype/src/type1/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2018 by
+# Copyright (C) 1996-2019 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/type1/t1afm.c b/thirdparty/freetype/src/type1/t1afm.c
index 61053d9a64..6841184539 100644
--- a/thirdparty/freetype/src/type1/t1afm.c
+++ b/thirdparty/freetype/src/type1/t1afm.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* t1afm.c */
-/* */
-/* AFM support for Type 1 fonts (body). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * t1afm.c
+ *
+ * AFM support for Type 1 fonts (body).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -26,14 +26,14 @@
#ifndef T1_CONFIG_OPTION_NO_AFM
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_t1afm
+#define FT_COMPONENT t1afm
FT_LOCAL_DEF( void )
diff --git a/thirdparty/freetype/src/type1/t1afm.h b/thirdparty/freetype/src/type1/t1afm.h
index cb8d302b4d..a8e6a5495a 100644
--- a/thirdparty/freetype/src/type1/t1afm.h
+++ b/thirdparty/freetype/src/type1/t1afm.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* t1afm.h */
-/* */
-/* AFM support for Type 1 fonts (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * t1afm.h
+ *
+ * AFM support for Type 1 fonts (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef T1AFM_H_
diff --git a/thirdparty/freetype/src/type1/t1driver.c b/thirdparty/freetype/src/type1/t1driver.c
index 029b410b47..8625db5b01 100644
--- a/thirdparty/freetype/src/type1/t1driver.c
+++ b/thirdparty/freetype/src/type1/t1driver.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* t1driver.c */
-/* */
-/* Type 1 driver interface (body). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * t1driver.c
+ *
+ * Type 1 driver interface (body).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -43,19 +43,19 @@
#include FT_SERVICE_KERNING_H
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_t1driver
+#define FT_COMPONENT t1driver
- /*
- * GLYPH DICT SERVICE
- *
- */
+ /*
+ * GLYPH DICT SERVICE
+ *
+ */
static FT_Error
t1_get_glyph_name( T1_Face face,
@@ -97,7 +97,7 @@
/*
- * POSTSCRIPT NAME SERVICE
+ * POSTSCRIPT NAME SERVICE
*
*/
@@ -115,30 +115,32 @@
/*
- * MULTIPLE MASTERS SERVICE
+ * MULTIPLE MASTERS SERVICE
*
*/
#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
static const FT_Service_MultiMastersRec t1_service_multi_masters =
{
- (FT_Get_MM_Func) T1_Get_Multi_Master, /* get_mm */
- (FT_Set_MM_Design_Func) T1_Set_MM_Design, /* set_mm_design */
- (FT_Set_MM_Blend_Func) T1_Set_MM_Blend, /* set_mm_blend */
- (FT_Get_MM_Blend_Func) T1_Get_MM_Blend, /* get_mm_blend */
- (FT_Get_MM_Var_Func) T1_Get_MM_Var, /* get_mm_var */
- (FT_Set_Var_Design_Func)T1_Set_Var_Design, /* set_var_design */
- (FT_Get_Var_Design_Func)T1_Get_Var_Design, /* get_var_design */
- (FT_Set_Instance_Func) T1_Reset_MM_Blend, /* set_instance */
-
- (FT_Get_Var_Blend_Func) NULL, /* get_var_blend */
- (FT_Done_Blend_Func) T1_Done_Blend /* done_blend */
+ (FT_Get_MM_Func) T1_Get_Multi_Master, /* get_mm */
+ (FT_Set_MM_Design_Func) T1_Set_MM_Design, /* set_mm_design */
+ (FT_Set_MM_Blend_Func) T1_Set_MM_Blend, /* set_mm_blend */
+ (FT_Get_MM_Blend_Func) T1_Get_MM_Blend, /* get_mm_blend */
+ (FT_Get_MM_Var_Func) T1_Get_MM_Var, /* get_mm_var */
+ (FT_Set_Var_Design_Func) T1_Set_Var_Design, /* set_var_design */
+ (FT_Get_Var_Design_Func) T1_Get_Var_Design, /* get_var_design */
+ (FT_Set_Instance_Func) T1_Reset_MM_Blend, /* set_instance */
+ (FT_Set_MM_WeightVector_Func)T1_Set_MM_WeightVector, /* set_mm_weightvector */
+ (FT_Get_MM_WeightVector_Func)T1_Get_MM_WeightVector, /* get_mm_weightvector */
+
+ (FT_Get_Var_Blend_Func) NULL, /* get_var_blend */
+ (FT_Done_Blend_Func) T1_Done_Blend /* done_blend */
};
#endif
/*
- * POSTSCRIPT INFO SERVICE
+ * POSTSCRIPT INFO SERVICE
*
*/
@@ -270,9 +272,12 @@
break;
case PS_DICT_FONT_NAME:
- retval = ft_strlen( type1->font_name ) + 1;
- if ( value && value_len >= retval )
- ft_memcpy( value, (void *)( type1->font_name ), retval );
+ if ( type1->font_name )
+ {
+ retval = ft_strlen( type1->font_name ) + 1;
+ if ( value && value_len >= retval )
+ ft_memcpy( value, (void *)( type1->font_name ), retval );
+ }
break;
case PS_DICT_UNIQUE_ID:
@@ -362,7 +367,7 @@
ok = 1;
}
- if ( ok )
+ if ( ok && type1->subrs )
{
retval = type1->subrs_len[idx] + 1;
if ( value && value_len >= retval )
@@ -559,33 +564,49 @@
break;
case PS_DICT_VERSION:
- retval = ft_strlen( type1->font_info.version ) + 1;
- if ( value && value_len >= retval )
- ft_memcpy( value, (void *)( type1->font_info.version ), retval );
+ if ( type1->font_info.version )
+ {
+ retval = ft_strlen( type1->font_info.version ) + 1;
+ if ( value && value_len >= retval )
+ ft_memcpy( value, (void *)( type1->font_info.version ), retval );
+ }
break;
case PS_DICT_NOTICE:
- retval = ft_strlen( type1->font_info.notice ) + 1;
- if ( value && value_len >= retval )
- ft_memcpy( value, (void *)( type1->font_info.notice ), retval );
+ if ( type1->font_info.notice )
+ {
+ retval = ft_strlen( type1->font_info.notice ) + 1;
+ if ( value && value_len >= retval )
+ ft_memcpy( value, (void *)( type1->font_info.notice ), retval );
+ }
break;
case PS_DICT_FULL_NAME:
- retval = ft_strlen( type1->font_info.full_name ) + 1;
- if ( value && value_len >= retval )
- ft_memcpy( value, (void *)( type1->font_info.full_name ), retval );
+ if ( type1->font_info.full_name )
+ {
+ retval = ft_strlen( type1->font_info.full_name ) + 1;
+ if ( value && value_len >= retval )
+ ft_memcpy( value, (void *)( type1->font_info.full_name ), retval );
+ }
break;
case PS_DICT_FAMILY_NAME:
- retval = ft_strlen( type1->font_info.family_name ) + 1;
- if ( value && value_len >= retval )
- ft_memcpy( value, (void *)( type1->font_info.family_name ), retval );
+ if ( type1->font_info.family_name )
+ {
+ retval = ft_strlen( type1->font_info.family_name ) + 1;
+ if ( value && value_len >= retval )
+ ft_memcpy( value, (void *)( type1->font_info.family_name ),
+ retval );
+ }
break;
case PS_DICT_WEIGHT:
- retval = ft_strlen( type1->font_info.weight ) + 1;
- if ( value && value_len >= retval )
- ft_memcpy( value, (void *)( type1->font_info.weight ), retval );
+ if ( type1->font_info.weight )
+ {
+ retval = ft_strlen( type1->font_info.weight ) + 1;
+ if ( value && value_len >= retval )
+ ft_memcpy( value, (void *)( type1->font_info.weight ), retval );
+ }
break;
case PS_DICT_ITALIC_ANGLE:
@@ -618,7 +639,7 @@
/*
- * PROPERTY SERVICE
+ * PROPERTY SERVICE
*
*/
@@ -630,7 +651,7 @@
/*
- * SERVICE LIST
+ * SERVICE LIST
*
*/
@@ -665,38 +686,42 @@
#ifndef T1_CONFIG_OPTION_NO_AFM
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Get_Kerning */
- /* */
- /* <Description> */
- /* A driver method used to return the kerning vector between two */
- /* glyphs of the same face. */
- /* */
- /* <Input> */
- /* face :: A handle to the source face object. */
- /* */
- /* left_glyph :: The index of the left glyph in the kern pair. */
- /* */
- /* right_glyph :: The index of the right glyph in the kern pair. */
- /* */
- /* <Output> */
- /* kerning :: The kerning vector. This is in font units for */
- /* scalable formats, and in pixels for fixed-sizes */
- /* formats. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- /* <Note> */
- /* Only horizontal layouts (left-to-right & right-to-left) are */
- /* supported by this function. Other layouts, or more sophisticated */
- /* kernings are out of scope of this method (the basic driver */
- /* interface is meant to be simple). */
- /* */
- /* They can be implemented by format-specific interfaces. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * Get_Kerning
+ *
+ * @Description:
+ * A driver method used to return the kerning vector between two
+ * glyphs of the same face.
+ *
+ * @Input:
+ * face ::
+ * A handle to the source face object.
+ *
+ * left_glyph ::
+ * The index of the left glyph in the kern pair.
+ *
+ * right_glyph ::
+ * The index of the right glyph in the kern pair.
+ *
+ * @Output:
+ * kerning ::
+ * The kerning vector. This is in font units for
+ * scalable formats, and in pixels for fixed-sizes
+ * formats.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ *
+ * @Note:
+ * Only horizontal layouts (left-to-right & right-to-left) are
+ * supported by this function. Other layouts, or more sophisticated
+ * kernings are out of scope of this method (the basic driver
+ * interface is meant to be simple).
+ *
+ * They can be implemented by format-specific interfaces.
+ */
static FT_Error
Get_Kerning( FT_Face t1face, /* T1_Face */
FT_UInt left_glyph,
diff --git a/thirdparty/freetype/src/type1/t1driver.h b/thirdparty/freetype/src/type1/t1driver.h
index 2b1507233d..206f64a0bc 100644
--- a/thirdparty/freetype/src/type1/t1driver.h
+++ b/thirdparty/freetype/src/type1/t1driver.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* t1driver.h */
-/* */
-/* High-level Type 1 driver interface (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * t1driver.h
+ *
+ * High-level Type 1 driver interface (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef T1DRIVER_H_
@@ -26,14 +26,8 @@
FT_BEGIN_HEADER
-#ifdef FT_CONFIG_OPTION_PIC
-#error "this module does not support PIC yet"
-#endif
-
-
FT_EXPORT_VAR( const FT_Driver_ClassRec ) t1_driver_class;
-
FT_END_HEADER
#endif /* T1DRIVER_H_ */
diff --git a/thirdparty/freetype/src/type1/t1errors.h b/thirdparty/freetype/src/type1/t1errors.h
index 9e0151b957..b35f67a24c 100644
--- a/thirdparty/freetype/src/type1/t1errors.h
+++ b/thirdparty/freetype/src/type1/t1errors.h
@@ -1,26 +1,26 @@
-/***************************************************************************/
-/* */
-/* t1errors.h */
-/* */
-/* Type 1 error codes (specification only). */
-/* */
-/* Copyright 2001-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* This file is used to define the Type 1 error enumeration constants. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * t1errors.h
+ *
+ * Type 1 error codes (specification only).
+ *
+ * Copyright (C) 2001-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * This file is used to define the Type 1 error enumeration constants.
+ *
+ */
#ifndef T1ERRORS_H_
#define T1ERRORS_H_
diff --git a/thirdparty/freetype/src/type1/t1gload.c b/thirdparty/freetype/src/type1/t1gload.c
index 87d40e7566..f9b115b186 100644
--- a/thirdparty/freetype/src/type1/t1gload.c
+++ b/thirdparty/freetype/src/type1/t1gload.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* t1gload.c */
-/* */
-/* Type 1 Glyph Loader (body). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * t1gload.c
+ *
+ * Type 1 Glyph Loader (body).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -29,14 +29,14 @@
#include "t1errors.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_t1gload
+#define FT_COMPONENT t1gload
static FT_Error
@@ -62,6 +62,7 @@
PS_Driver driver = (PS_Driver)FT_FACE_DRIVER( face );
#endif
+
decoder->font_matrix = type1->font_matrix;
decoder->font_offset = type1->font_offset;
@@ -249,6 +250,8 @@
*max_advance = 0;
+ FT_TRACE6(( "T1_Compute_Max_Advance:\n" ));
+
/* for each glyph, parse the glyph charstring and extract */
/* the advance width */
for ( glyph_index = 0; glyph_index < type1->num_glyphs; glyph_index++ )
@@ -261,6 +264,9 @@
/* ignore the error if one occurred - skip to next glyph */
}
+ FT_TRACE6(( "T1_Compute_Max_Advance: max advance: %f\n",
+ *max_advance / 65536.0 ));
+
psaux->t1_decoder_funcs->done( &decoder );
return FT_Err_Ok;
@@ -282,11 +288,18 @@
FT_Error error;
+ FT_TRACE5(( "T1_Get_Advances:\n" ));
+
if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
{
for ( nn = 0; nn < count; nn++ )
+ {
advances[nn] = 0;
+ FT_TRACE5(( " idx %d: advance height 0 font units\n",
+ first + nn ));
+ }
+
return FT_Err_Ok;
}
@@ -320,6 +333,11 @@
advances[nn] = FIXED_TO_INT( decoder.builder.advance.x );
else
advances[nn] = 0;
+
+ FT_TRACE5(( " idx %d: advance width %d font unit%s\n",
+ first + nn,
+ advances[nn],
+ advances[nn] == 1 ? "" : "s" ));
}
return FT_Err_Ok;
@@ -384,9 +402,9 @@
t1glyph->outline.n_points = 0;
t1glyph->outline.n_contours = 0;
- hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 &&
- ( load_flags & FT_LOAD_NO_HINTING ) == 0 );
- scaled = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 );
+ hinting = FT_BOOL( !( load_flags & FT_LOAD_NO_SCALE ) &&
+ !( load_flags & FT_LOAD_NO_HINTING ) );
+ scaled = FT_BOOL( !( load_flags & FT_LOAD_NO_SCALE ) );
glyph->hint = hinting;
glyph->scaled = scaled;
@@ -398,7 +416,7 @@
t1glyph,
(FT_Byte**)type1->glyph_names,
face->blend,
- FT_BOOL( hinting ),
+ hinting,
FT_LOAD_TARGET_MODE( load_flags ),
T1_Parse_Glyph );
if ( error )
@@ -406,8 +424,7 @@
must_finish_decoder = TRUE;
- decoder.builder.no_recurse = FT_BOOL(
- ( load_flags & FT_LOAD_NO_RECURSE ) != 0 );
+ decoder.builder.no_recurse = FT_BOOL( load_flags & FT_LOAD_NO_RECURSE );
decoder.num_subrs = type1->num_subrs;
decoder.subrs = type1->subrs;
@@ -528,7 +545,7 @@
/* First of all, scale the points, if we are not hinting */
- if ( !hinting || ! decoder.builder.hints_funcs )
+ if ( !hinting || !decoder.builder.hints_funcs )
for ( n = cur->n_points; n > 0; n--, vec++ )
{
vec->x = FT_MulFix( vec->x, x_scale );
diff --git a/thirdparty/freetype/src/type1/t1gload.h b/thirdparty/freetype/src/type1/t1gload.h
index 72ef76f6ae..80440369dc 100644
--- a/thirdparty/freetype/src/type1/t1gload.h
+++ b/thirdparty/freetype/src/type1/t1gload.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* t1gload.h */
-/* */
-/* Type 1 Glyph Loader (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * t1gload.h
+ *
+ * Type 1 Glyph Loader (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef T1GLOAD_H_
diff --git a/thirdparty/freetype/src/type1/t1load.c b/thirdparty/freetype/src/type1/t1load.c
index 9dfa637a69..3896af70ba 100644
--- a/thirdparty/freetype/src/type1/t1load.c
+++ b/thirdparty/freetype/src/type1/t1load.c
@@ -1,63 +1,63 @@
-/***************************************************************************/
-/* */
-/* t1load.c */
-/* */
-/* Type 1 font loader (body). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* This is the new and improved Type 1 data loader for FreeType 2. The */
- /* old loader has several problems: it is slow, complex, difficult to */
- /* maintain, and contains incredible hacks to make it accept some */
- /* ill-formed Type 1 fonts without hiccup-ing. Moreover, about 5% of */
- /* the Type 1 fonts on my machine still aren't loaded correctly by it. */
- /* */
- /* This version is much simpler, much faster and also easier to read and */
- /* maintain by a great order of magnitude. The idea behind it is to */
- /* _not_ try to read the Type 1 token stream with a state machine (i.e. */
- /* a Postscript-like interpreter) but rather to perform simple pattern */
- /* matching. */
- /* */
- /* Indeed, nearly all data definitions follow a simple pattern like */
- /* */
- /* ... /Field <data> ... */
- /* */
- /* where <data> can be a number, a boolean, a string, or an array of */
- /* numbers. There are a few exceptions, namely the encoding, font name, */
- /* charstrings, and subrs; they are handled with a special pattern */
- /* matching routine. */
- /* */
- /* All other common cases are handled very simply. The matching rules */
- /* are defined in the file `t1tokens.h' through the use of several */
- /* macros calls PARSE_XXX. This file is included twice here; the first */
- /* time to generate parsing callback functions, the second time to */
- /* generate a table of keywords (with pointers to the associated */
- /* callback functions). */
- /* */
- /* The function `parse_dict' simply scans *linearly* a given dictionary */
- /* (either the top-level or private one) and calls the appropriate */
- /* callback when it encounters an immediate keyword. */
- /* */
- /* This is by far the fastest way one can find to parse and read all */
- /* data. */
- /* */
- /* This led to tremendous code size reduction. Note that later, the */
- /* glyph loader will also be _greatly_ simplified, and the automatic */
- /* hinter will replace the clumsy `t1hinter'. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * t1load.c
+ *
+ * Type 1 font loader (body).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * This is the new and improved Type 1 data loader for FreeType 2. The
+ * old loader has several problems: it is slow, complex, difficult to
+ * maintain, and contains incredible hacks to make it accept some
+ * ill-formed Type 1 fonts without hiccup-ing. Moreover, about 5% of
+ * the Type 1 fonts on my machine still aren't loaded correctly by it.
+ *
+ * This version is much simpler, much faster and also easier to read and
+ * maintain by a great order of magnitude. The idea behind it is to
+ * _not_ try to read the Type 1 token stream with a state machine (i.e.
+ * a Postscript-like interpreter) but rather to perform simple pattern
+ * matching.
+ *
+ * Indeed, nearly all data definitions follow a simple pattern like
+ *
+ * ... /Field <data> ...
+ *
+ * where <data> can be a number, a boolean, a string, or an array of
+ * numbers. There are a few exceptions, namely the encoding, font name,
+ * charstrings, and subrs; they are handled with a special pattern
+ * matching routine.
+ *
+ * All other common cases are handled very simply. The matching rules
+ * are defined in the file `t1tokens.h' through the use of several
+ * macros calls PARSE_XXX. This file is included twice here; the first
+ * time to generate parsing callback functions, the second time to
+ * generate a table of keywords (with pointers to the associated
+ * callback functions).
+ *
+ * The function `parse_dict' simply scans *linearly* a given dictionary
+ * (either the top-level or private one) and calls the appropriate
+ * callback when it encounters an immediate keyword.
+ *
+ * This is by far the fastest way one can find to parse and read all
+ * data.
+ *
+ * This led to tremendous code size reduction. Note that later, the
+ * glyph loader will also be _greatly_ simplified, and the automatic
+ * hinter will replace the clumsy `t1hinter'.
+ *
+ */
#include <ft2build.h>
@@ -73,20 +73,20 @@
#ifdef FT_CONFIG_OPTION_INCREMENTAL
-#define IS_INCREMENTAL (FT_Bool)( face->root.internal->incremental_interface != 0 )
+#define IS_INCREMENTAL FT_BOOL( face->root.internal->incremental_interface )
#else
#define IS_INCREMENTAL 0
#endif
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_t1load
+#define FT_COMPONENT t1load
#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
@@ -222,11 +222,11 @@
}
- /*************************************************************************/
- /* */
- /* Given a normalized (blend) coordinate, figure out the design */
- /* coordinate appropriate for that value. */
- /* */
+ /**************************************************************************
+ *
+ * Given a normalized (blend) coordinate, figure out the design
+ * coordinate appropriate for that value.
+ */
static FT_Fixed
mm_axis_unmap( PS_DesignMap axismap,
FT_Fixed ncv )
@@ -251,11 +251,11 @@
}
- /*************************************************************************/
- /* */
- /* Given a vector of weights, one for each design, figure out the */
- /* normalized axis coordinates which gave rise to those weights. */
- /* */
+ /**************************************************************************
+ *
+ * Given a vector of weights, one for each design, figure out the
+ * normalized axis coordinates which gave rise to those weights.
+ */
static void
mm_weights_unmap( FT_Fixed* weights,
FT_Fixed* axiscoords,
@@ -293,11 +293,11 @@
}
- /*************************************************************************/
- /* */
- /* Just a wrapper around T1_Get_Multi_Master to support the different */
- /* arguments needed by the GX var distortable fonts. */
- /* */
+ /**************************************************************************
+ *
+ * Just a wrapper around T1_Get_Multi_Master to support the different
+ * arguments needed by the GX var distortable fonts.
+ */
FT_LOCAL_DEF( FT_Error )
T1_Get_MM_Var( T1_Face face,
FT_MM_Var* *master )
@@ -348,16 +348,13 @@
mmvar->axis[i].tag = FT_MAKE_TAG( 'o', 'p', 's', 'z' );
}
- if ( blend->num_designs == ( 1U << blend->num_axis ) )
- {
- mm_weights_unmap( blend->default_weight_vector,
- axiscoords,
- blend->num_axis );
+ mm_weights_unmap( blend->default_weight_vector,
+ axiscoords,
+ blend->num_axis );
- for ( i = 0; i < mmaster.num_axis; i++ )
- mmvar->axis[i].def = mm_axis_unmap( &blend->design_map[i],
- axiscoords[i] );
- }
+ for ( i = 0; i < mmaster.num_axis; i++ )
+ mmvar->axis[i].def = mm_axis_unmap( &blend->design_map[i],
+ axiscoords[i] );
*master = mmvar;
@@ -387,24 +384,31 @@
for ( n = 0; n < blend->num_designs; n++ )
{
FT_Fixed result = 0x10000L; /* 1.0 fixed */
+ FT_Fixed factor;
for ( m = 0; m < blend->num_axis; m++ )
{
- FT_Fixed factor;
-
-
- /* get current blend axis position; */
/* use a default value if we don't have a coordinate */
- factor = m < num_coords ? coords[m] : 0x8000;
- if ( factor < 0 )
- factor = 0;
- if ( factor > 0x10000L )
- factor = 0x10000L;
+ if ( m >= num_coords )
+ {
+ result >>= 1;
+ continue;
+ }
+ /* get current blend axis position */
+ factor = coords[m];
if ( ( n & ( 1 << m ) ) == 0 )
factor = 0x10000L - factor;
+ if ( factor <= 0 )
+ {
+ result = 0;
+ break;
+ }
+ else if ( factor >= 0x10000L )
+ continue;
+
result = FT_MulFix( result, factor );
}
@@ -477,6 +481,75 @@
FT_LOCAL_DEF( FT_Error )
+ T1_Set_MM_WeightVector( T1_Face face,
+ FT_UInt len,
+ FT_Fixed* weightvector )
+ {
+ PS_Blend blend = face->blend;
+ FT_UInt i, n;
+
+
+ if ( !blend )
+ return FT_THROW( Invalid_Argument );
+
+ if ( !len && !weightvector )
+ {
+ for ( i = 0; i < blend->num_designs; i++ )
+ blend->weight_vector[i] = blend->default_weight_vector[i];
+ }
+ else
+ {
+ if ( !weightvector )
+ return FT_THROW( Invalid_Argument );
+
+ n = len < blend->num_designs ? len : blend->num_designs;
+
+ for ( i = 0; i < n; i++ )
+ blend->weight_vector[i] = weightvector[i];
+
+ for ( ; i < blend->num_designs; i++ )
+ blend->weight_vector[i] = (FT_Fixed)0;
+
+ if ( len )
+ face->root.face_flags |= FT_FACE_FLAG_VARIATION;
+ else
+ face->root.face_flags &= ~FT_FACE_FLAG_VARIATION;
+ }
+
+ return FT_Err_Ok;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ T1_Get_MM_WeightVector( T1_Face face,
+ FT_UInt* len,
+ FT_Fixed* weightvector )
+ {
+ PS_Blend blend = face->blend;
+ FT_UInt i;
+
+
+ if ( !blend )
+ return FT_THROW( Invalid_Argument );
+
+ if ( *len < blend->num_designs )
+ {
+ *len = blend->num_designs;
+ return FT_THROW( Invalid_Argument );
+ }
+
+ for ( i = 0; i < blend->num_designs; i++ )
+ weightvector[i] = blend->weight_vector[i];
+ for ( ; i < *len; i++ )
+ weightvector[i] = (FT_Fixed)0;
+
+ *len = blend->num_designs;
+
+ return FT_Err_Ok;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
T1_Set_MM_Design( T1_Face face,
FT_UInt num_coords,
FT_Long* coords )
@@ -573,11 +646,11 @@
}
- /*************************************************************************/
- /* */
- /* Just a wrapper around T1_Set_MM_Design to support the different */
- /* arguments needed by the GX var distortable fonts. */
- /* */
+ /**************************************************************************
+ *
+ * Just a wrapper around T1_Set_MM_Design to support the different
+ * arguments needed by the GX var distortable fonts.
+ */
FT_LOCAL_DEF( FT_Error )
T1_Set_Var_Design( T1_Face face,
FT_UInt num_coords,
@@ -719,6 +792,8 @@
if ( error )
goto Exit;
+ FT_TRACE4(( " [" ));
+
blend = face->blend;
memory = face->root.memory;
@@ -741,11 +816,13 @@
goto Exit;
}
+ FT_TRACE4(( " /%.*s", len, token->start ));
+
name = (FT_Byte*)blend->axis_names[n];
if ( name )
{
FT_TRACE0(( "parse_blend_axis_types:"
- " overwriting axis name `%s' with `%*.s'\n",
+ " overwriting axis name `%s' with `%.*s'\n",
name, len, token->start ));
FT_FREE( name );
}
@@ -758,6 +835,8 @@
name[len] = '\0';
}
+ FT_TRACE4(( "]\n" ));
+
Exit:
loader->parser.root.error = error;
}
@@ -802,6 +881,8 @@
blend = face->blend;
num_axis = 0; /* make compiler happy */
+ FT_TRACE4(( " [" ));
+
for ( n = 0; n < num_designs; n++ )
{
T1_TokenRec axis_tokens[T1_MAX_MM_AXIS];
@@ -842,6 +923,7 @@
}
/* now read each axis token into the design position */
+ FT_TRACE4(( " [" )) ;
for ( axis = 0; axis < n_axis; axis++ )
{
T1_Token token2 = axis_tokens + axis;
@@ -850,9 +932,13 @@
parser->root.cursor = token2->start;
parser->root.limit = token2->limit;
blend->design_pos[n][axis] = T1_ToFixed( parser, 0 );
+ FT_TRACE4(( " %f", (double)blend->design_pos[n][axis] / 65536 ));
}
+ FT_TRACE4(( "]" )) ;
}
+ FT_TRACE4(( "]\n" ));
+
loader->parser.root.cursor = old_cursor;
loader->parser.root.limit = old_limit;
}
@@ -899,6 +985,8 @@
goto Exit;
blend = face->blend;
+ FT_TRACE4(( " [" ));
+
/* now read each axis design map */
for ( n = 0; n < num_axis; n++ )
{
@@ -915,6 +1003,8 @@
T1_ToTokenArray( parser, point_tokens,
T1_MAX_MM_MAP_POINTS, &num_points );
+ FT_TRACE4(( " [" ));
+
if ( num_points <= 0 || num_points > T1_MAX_MM_MAP_POINTS )
{
FT_ERROR(( "parse_blend_design_map: incorrect table\n" ));
@@ -948,9 +1038,17 @@
map->design_points[p] = T1_ToInt( parser );
map->blend_points [p] = T1_ToFixed( parser, 0 );
+
+ FT_TRACE4(( " [%d %f]",
+ map->design_points[p],
+ (double)map->blend_points[p] / 65536 ));
}
+
+ FT_TRACE4(( "]" ));
}
+ FT_TRACE4(( "]\n" ));
+
parser->root.cursor = old_cursor;
parser->root.limit = old_limit;
@@ -1010,6 +1108,8 @@
old_cursor = parser->root.cursor;
old_limit = parser->root.limit;
+ FT_TRACE4(( "[" ));
+
for ( n = 0; n < num_designs; n++ )
{
token = design_tokens + n;
@@ -1018,8 +1118,12 @@
blend->default_weight_vector[n] =
blend->weight_vector[n] = T1_ToFixed( parser, 0 );
+
+ FT_TRACE4(( " %f", (double)blend->weight_vector[n] / 65536 ));
}
+ FT_TRACE4(( "]\n" ));
+
parser->root.cursor = old_cursor;
parser->root.limit = old_limit;
@@ -1036,6 +1140,20 @@
{
face->len_buildchar = (FT_UInt)T1_ToFixedArray( &loader->parser,
0, NULL, 0 );
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ {
+ FT_UInt i;
+
+
+ FT_TRACE4(( " [" ));
+ for ( i = 0; i < face->len_buildchar; i++ )
+ FT_TRACE4(( " 0" ));
+
+ FT_TRACE4(( "]\n" ));
+ }
+#endif
+
return;
}
@@ -1071,6 +1189,8 @@
/* if the keyword has a dedicated callback, call it */
if ( field->type == T1_FIELD_TYPE_CALLBACK )
{
+ FT_TRACE4(( " %s", field->ident ));
+
field->reader( (FT_Face)face, loader );
error = loader->parser.root.error;
goto Exit;
@@ -1148,6 +1268,8 @@
max_objects = 0;
}
+ FT_TRACE4(( " %s", field->ident ));
+
if ( *objects )
{
if ( field->type == T1_FIELD_TYPE_INTEGER_ARRAY ||
@@ -1167,6 +1289,8 @@
error = FT_Err_Ok;
}
+ FT_TRACE4(( "\n" ));
+
Exit:
return error;
}
@@ -1179,6 +1303,8 @@
FT_UNUSED( face );
loader->keywords_encountered |= T1_PRIVATE;
+
+ FT_TRACE4(( "\n" ));
}
@@ -1258,6 +1384,14 @@
return;
}
+ FT_TRACE4(( " [%f %f %f %f %f %f]\n",
+ (double)temp[0] / 65536 / 1000,
+ (double)temp[1] / 65536 / 1000,
+ (double)temp[2] / 65536 / 1000,
+ (double)temp[3] / 65536 / 1000,
+ (double)temp[4] / 65536 / 1000,
+ (double)temp[5] / 65536 / 1000 ));
+
temp_scale = FT_ABS( temp[3] );
if ( temp_scale == 0 )
@@ -1280,12 +1414,18 @@
temp[5] = FT_DivFix( temp[5], temp_scale );
temp[3] = temp[3] < 0 ? -0x10000L : 0x10000L;
}
-
matrix->xx = temp[0];
matrix->yx = temp[1];
matrix->xy = temp[2];
matrix->yy = temp[3];
+ if ( !FT_Matrix_Check( matrix ) )
+ {
+ FT_ERROR(( "t1_parse_font_matrix: invalid font matrix\n" ));
+ parser->root.error = FT_THROW( Invalid_File_Format );
+ return;
+ }
+
/* note that the offsets must be expressed in integer font units */
offset->x = temp[4] >> 16;
offset->y = temp[5] >> 16;
@@ -1494,6 +1634,15 @@
T1_Skip_Spaces( parser );
}
+#ifdef FT_DEBUG_LEVEL_TRACE
+ FT_TRACE4(( " [" ));
+
+ /* XXX show encoding vector */
+ FT_TRACE4(( "..." ));
+
+ FT_TRACE4(( "]\n" ));
+#endif
+
face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY;
parser->root.cursor = cur;
}
@@ -1504,18 +1653,30 @@
{
if ( cur + 17 < limit &&
ft_strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 )
+ {
face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD;
+ FT_TRACE4(( " StandardEncoding\n" ));
+ }
else if ( cur + 15 < limit &&
ft_strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 )
+ {
face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT;
+ FT_TRACE4(( " ExpertEncoding\n" ));
+ }
else if ( cur + 18 < limit &&
ft_strncmp( (const char*)cur, "ISOLatin1Encoding", 17 ) == 0 )
+ {
face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1;
+ FT_TRACE4(( " ISOLatin1Encoding\n" ));
+ }
else
+ {
parser->root.error = FT_ERR( Ignore );
+ FT_TRACE4(( "<unknown>\n" ));
+ }
}
}
@@ -1696,6 +1857,15 @@
if ( !loader->num_subrs )
loader->num_subrs = num_subrs;
+#ifdef FT_DEBUG_LEVEL_TRACE
+ FT_TRACE4(( " <" ));
+
+ /* XXX show subrs? */
+ FT_TRACE4(( "%d elements", num_subrs ));
+
+ FT_TRACE4(( ">\n" ));
+#endif
+
return;
Fail:
@@ -2017,6 +2187,15 @@
loader->num_glyphs += 1;
}
+#ifdef FT_DEBUG_LEVEL_TRACE
+ FT_TRACE4(( " <" ));
+
+ /* XXX show charstrings? */
+ FT_TRACE4(( "%d elements", loader->num_glyphs ));
+
+ FT_TRACE4(( ">\n" ));
+#endif
+
return;
Fail:
@@ -2024,12 +2203,12 @@
}
- /*************************************************************************/
- /* */
- /* Define the token field static variables. This is a set of */
- /* T1_FieldRec variables. */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * Define the token field static variables. This is a set of
+ * T1_FieldRec variables.
+ *
+ */
static
@@ -2216,6 +2395,7 @@
? T1_FIELD_DICT_PRIVATE
: T1_FIELD_DICT_FONTDICT;
+
if ( !( dict & keyword->dict ) )
{
FT_TRACE1(( "parse_dict: found `%s' but ignoring it"
@@ -2330,6 +2510,7 @@
if ( error )
goto Exit;
+ FT_TRACE4(( " top dictionary:\n" ));
error = parse_dict( face, &loader,
parser->base_dict, parser->base_len );
if ( error )
@@ -2339,6 +2520,7 @@
if ( error )
goto Exit;
+ FT_TRACE4(( " private dictionary:\n" ));
error = parse_dict( face, &loader,
parser->private_dict, parser->private_len );
if ( error )
@@ -2349,6 +2531,16 @@
#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
+ /* we don't support Multiple Master fonts with intermediate designs; */
+ /* this implies that `num_designs' must be equal to `2^^num_axis' */
+ if ( face->blend &&
+ face->blend->num_designs != ( 1U << face->blend->num_axis ) )
+ {
+ FT_ERROR(( "T1_Open_Face:"
+ " number-of-designs != 2 ^^ number-of-axes\n" ));
+ T1_Done_Blend( face );
+ }
+
if ( face->blend &&
face->blend->num_default_design_vector != 0 &&
face->blend->num_default_design_vector != face->blend->num_axis )
diff --git a/thirdparty/freetype/src/type1/t1load.h b/thirdparty/freetype/src/type1/t1load.h
index 03be3f7f93..44f835bde2 100644
--- a/thirdparty/freetype/src/type1/t1load.h
+++ b/thirdparty/freetype/src/type1/t1load.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* t1load.h */
-/* */
-/* Type 1 font loader (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * t1load.h
+ *
+ * Type 1 font loader (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef T1LOAD_H_
@@ -106,6 +106,16 @@ FT_BEGIN_HEADER
FT_LOCAL( void )
T1_Done_Blend( T1_Face face );
+ FT_LOCAL( FT_Error )
+ T1_Set_MM_WeightVector( T1_Face face,
+ FT_UInt len,
+ FT_Fixed* weightvector );
+
+ FT_LOCAL( FT_Error )
+ T1_Get_MM_WeightVector( T1_Face face,
+ FT_UInt* len,
+ FT_Fixed* weightvector );
+
#endif /* !T1_CONFIG_OPTION_NO_MM_SUPPORT */
diff --git a/thirdparty/freetype/src/type1/t1objs.c b/thirdparty/freetype/src/type1/t1objs.c
index 7333c4c958..741388a645 100644
--- a/thirdparty/freetype/src/type1/t1objs.c
+++ b/thirdparty/freetype/src/type1/t1objs.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* t1objs.c */
-/* */
-/* Type 1 objects manager (body). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * t1objs.c
+ *
+ * Type 1 objects manager (body).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -36,21 +36,21 @@
#include FT_INTERNAL_POSTSCRIPT_AUX_H
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_t1objs
+#define FT_COMPONENT t1objs
- /*************************************************************************/
- /* */
- /* SIZE FUNCTIONS */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * SIZE FUNCTIONS
+ *
+ */
static PSH_Globals_Funcs
@@ -133,11 +133,11 @@
}
- /*************************************************************************/
- /* */
- /* SLOT FUNCTIONS */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * SLOT FUNCTIONS
+ *
+ */
FT_LOCAL_DEF( void )
T1_GlyphSlot_Done( FT_GlyphSlot slot )
@@ -177,24 +177,25 @@
}
- /*************************************************************************/
- /* */
- /* FACE FUNCTIONS */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* T1_Face_Done */
- /* */
- /* <Description> */
- /* The face object destructor. */
- /* */
- /* <Input> */
- /* face :: A typeless pointer to the face object to destroy. */
- /* */
+ /**************************************************************************
+ *
+ * FACE FUNCTIONS
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @Function:
+ * T1_Face_Done
+ *
+ * @Description:
+ * The face object destructor.
+ *
+ * @Input:
+ * face ::
+ * A typeless pointer to the face object to destroy.
+ */
FT_LOCAL_DEF( void )
T1_Face_Done( FT_Face t1face ) /* T1_Face */
{
@@ -274,29 +275,34 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* T1_Face_Init */
- /* */
- /* <Description> */
- /* The face object constructor. */
- /* */
- /* <Input> */
- /* stream :: input stream where to load font data. */
- /* */
- /* face_index :: The index of the font face in the resource. */
- /* */
- /* num_params :: Number of additional generic parameters. Ignored. */
- /* */
- /* params :: Additional generic parameters. Ignored. */
- /* */
- /* <InOut> */
- /* face :: The face record to build. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * T1_Face_Init
+ *
+ * @Description:
+ * The face object constructor.
+ *
+ * @Input:
+ * stream ::
+ * input stream where to load font data.
+ *
+ * face_index ::
+ * The index of the font face in the resource.
+ *
+ * num_params ::
+ * Number of additional generic parameters. Ignored.
+ *
+ * params ::
+ * Additional generic parameters. Ignored.
+ *
+ * @InOut:
+ * face ::
+ * The face record to build.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
T1_Face_Init( FT_Stream stream,
FT_Face t1face, /* T1_Face */
@@ -341,6 +347,10 @@
if ( error )
goto Exit;
+ FT_TRACE2(( "T1_Face_Init: %08p (index %d)\n",
+ face,
+ face_index ));
+
/* if we just wanted to check the format, leave successfully now */
if ( face_index < 0 )
goto Exit;
@@ -516,7 +526,8 @@
error = FT_CMap_New( cmap_classes->unicode, NULL, &charmap, NULL );
if ( error &&
- FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) )
+ FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) &&
+ FT_ERR_NEQ( error, Unimplemented_Feature ) )
goto Exit;
error = FT_Err_Ok;
@@ -564,20 +575,21 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* T1_Driver_Init */
- /* */
- /* <Description> */
- /* Initializes a given Type 1 driver object. */
- /* */
- /* <Input> */
- /* driver :: A handle to the target driver object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * T1_Driver_Init
+ *
+ * @Description:
+ * Initializes a given Type 1 driver object.
+ *
+ * @Input:
+ * driver ::
+ * A handle to the target driver object.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
T1_Driver_Init( FT_Module module )
{
@@ -620,17 +632,18 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* T1_Driver_Done */
- /* */
- /* <Description> */
- /* Finalizes a given Type 1 driver. */
- /* */
- /* <Input> */
- /* driver :: A handle to the target Type 1 driver. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * T1_Driver_Done
+ *
+ * @Description:
+ * Finalizes a given Type 1 driver.
+ *
+ * @Input:
+ * driver ::
+ * A handle to the target Type 1 driver.
+ */
FT_LOCAL_DEF( void )
T1_Driver_Done( FT_Module driver )
{
diff --git a/thirdparty/freetype/src/type1/t1objs.h b/thirdparty/freetype/src/type1/t1objs.h
index 8298e036f4..2161091f77 100644
--- a/thirdparty/freetype/src/type1/t1objs.h
+++ b/thirdparty/freetype/src/type1/t1objs.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* t1objs.h */
-/* */
-/* Type 1 objects manager (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * t1objs.h
+ *
+ * Type 1 objects manager (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef T1OBJS_H_
@@ -34,59 +34,59 @@ FT_BEGIN_HEADER
typedef struct T1_Glyph_Hints_ T1_Glyph_Hints;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* T1_Size */
- /* */
- /* <Description> */
- /* A handle to a Type 1 size object. */
- /* */
+ /**************************************************************************
+ *
+ * @Type:
+ * T1_Size
+ *
+ * @Description:
+ * A handle to a Type 1 size object.
+ */
typedef struct T1_SizeRec_* T1_Size;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* T1_GlyphSlot */
- /* */
- /* <Description> */
- /* A handle to a Type 1 glyph slot object. */
- /* */
+ /**************************************************************************
+ *
+ * @Type:
+ * T1_GlyphSlot
+ *
+ * @Description:
+ * A handle to a Type 1 glyph slot object.
+ */
typedef struct T1_GlyphSlotRec_* T1_GlyphSlot;
- /*************************************************************************/
- /* */
- /* <Type> */
- /* T1_CharMap */
- /* */
- /* <Description> */
- /* A handle to a Type 1 character mapping object. */
- /* */
- /* <Note> */
- /* The Type 1 format doesn't use a charmap but an encoding table. */
- /* The driver is responsible for making up charmap objects */
- /* corresponding to these tables. */
- /* */
+ /**************************************************************************
+ *
+ * @Type:
+ * T1_CharMap
+ *
+ * @Description:
+ * A handle to a Type 1 character mapping object.
+ *
+ * @Note:
+ * The Type 1 format doesn't use a charmap but an encoding table.
+ * The driver is responsible for making up charmap objects
+ * corresponding to these tables.
+ */
typedef struct T1_CharMapRec_* T1_CharMap;
- /*************************************************************************/
- /* */
- /* HERE BEGINS THE TYPE1 SPECIFIC STUFF */
- /* */
- /*************************************************************************/
+ /**************************************************************************
+ *
+ * HERE BEGINS THE TYPE1 SPECIFIC STUFF
+ *
+ */
- /*************************************************************************/
- /* */
- /* <Type> */
- /* T1_SizeRec */
- /* */
- /* <Description> */
- /* Type 1 size record. */
- /* */
+ /**************************************************************************
+ *
+ * @Type:
+ * T1_SizeRec
+ *
+ * @Description:
+ * Type 1 size record.
+ */
typedef struct T1_SizeRec_
{
FT_SizeRec root;
@@ -105,14 +105,14 @@ FT_BEGIN_HEADER
T1_Size_Init( FT_Size size );
- /*************************************************************************/
- /* */
- /* <Type> */
- /* T1_GlyphSlotRec */
- /* */
- /* <Description> */
- /* Type 1 glyph slot record. */
- /* */
+ /**************************************************************************
+ *
+ * @Type:
+ * T1_GlyphSlotRec
+ *
+ * @Description:
+ * Type 1 glyph slot record.
+ */
typedef struct T1_GlyphSlotRec_
{
FT_GlyphSlotRec root;
diff --git a/thirdparty/freetype/src/type1/t1parse.c b/thirdparty/freetype/src/type1/t1parse.c
index 8e201e5ef5..56caeb9e40 100644
--- a/thirdparty/freetype/src/type1/t1parse.c
+++ b/thirdparty/freetype/src/type1/t1parse.c
@@ -1,36 +1,36 @@
-/***************************************************************************/
-/* */
-/* t1parse.c */
-/* */
-/* Type 1 parser (body). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* The Type 1 parser is in charge of the following: */
- /* */
- /* - provide an implementation of a growing sequence of objects called */
- /* a `T1_Table' (used to build various tables needed by the loader). */
- /* */
- /* - opening .pfb and .pfa files to extract their top-level and private */
- /* dictionaries. */
- /* */
- /* - read numbers, arrays & strings from any dictionary. */
- /* */
- /* See `t1load.c' to see how data is loaded from the font file. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * t1parse.c
+ *
+ * Type 1 parser (body).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * The Type 1 parser is in charge of the following:
+ *
+ * - provide an implementation of a growing sequence of objects called
+ * a `T1_Table' (used to build various tables needed by the loader).
+ *
+ * - opening .pfb and .pfa files to extract their top-level and private
+ * dictionaries.
+ *
+ * - read numbers, arrays & strings from any dictionary.
+ *
+ * See `t1load.c' to see how data is loaded from the font file.
+ *
+ */
#include <ft2build.h>
@@ -43,14 +43,14 @@
#include "t1errors.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_t1parse
+#define FT_COMPONENT t1parse
/*************************************************************************/
@@ -169,21 +169,21 @@
}
}
- /******************************************************************/
- /* */
- /* Here a short summary of what is going on: */
- /* */
- /* When creating a new Type 1 parser, we try to locate and load */
- /* the base dictionary if this is possible (i.e., for PFB */
- /* files). Otherwise, we load the whole font into memory. */
- /* */
- /* When `loading' the base dictionary, we only setup pointers */
- /* in the case of a memory-based stream. Otherwise, we */
- /* allocate and load the base dictionary in it. */
- /* */
- /* parser->in_pfb is set if we are in a binary (`.pfb') font. */
- /* parser->in_memory is set if we have a memory stream. */
- /* */
+ /*******************************************************************
+ *
+ * Here a short summary of what is going on:
+ *
+ * When creating a new Type 1 parser, we try to locate and load
+ * the base dictionary if this is possible (i.e., for PFB
+ * files). Otherwise, we load the whole font into memory.
+ *
+ * When `loading' the base dictionary, we only setup pointers
+ * in the case of a memory-based stream. Otherwise, we
+ * allocate and load the base dictionary in it.
+ *
+ * parser->in_pfb is set if we are in a binary (`.pfb') font.
+ * parser->in_memory is set if we have a memory stream.
+ */
/* try to compute the size of the base dictionary; */
/* look for a Postscript binary file tag, i.e., 0x8001 */
diff --git a/thirdparty/freetype/src/type1/t1parse.h b/thirdparty/freetype/src/type1/t1parse.h
index 4ac82ae913..dab8fddc8b 100644
--- a/thirdparty/freetype/src/type1/t1parse.h
+++ b/thirdparty/freetype/src/type1/t1parse.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* t1parse.h */
-/* */
-/* Type 1 parser (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * t1parse.h
+ *
+ * Type 1 parser (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef T1PARSE_H_
@@ -28,36 +28,45 @@
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* T1_ParserRec */
- /* */
- /* <Description> */
- /* A PS_ParserRec is an object used to parse a Type 1 fonts very */
- /* quickly. */
- /* */
- /* <Fields> */
- /* root :: The root parser. */
- /* */
- /* stream :: The current input stream. */
- /* */
- /* base_dict :: A pointer to the top-level dictionary. */
- /* */
- /* base_len :: The length in bytes of the top dictionary. */
- /* */
- /* private_dict :: A pointer to the private dictionary. */
- /* */
- /* private_len :: The length in bytes of the private dictionary. */
- /* */
- /* in_pfb :: A boolean. Indicates that we are handling a PFB */
- /* file. */
- /* */
- /* in_memory :: A boolean. Indicates a memory-based stream. */
- /* */
- /* single_block :: A boolean. Indicates that the private dictionary */
- /* is stored in lieu of the base dictionary. */
- /* */
+ /**************************************************************************
+ *
+ * @Struct:
+ * T1_ParserRec
+ *
+ * @Description:
+ * A PS_ParserRec is an object used to parse a Type 1 fonts very
+ * quickly.
+ *
+ * @Fields:
+ * root ::
+ * The root parser.
+ *
+ * stream ::
+ * The current input stream.
+ *
+ * base_dict ::
+ * A pointer to the top-level dictionary.
+ *
+ * base_len ::
+ * The length in bytes of the top dictionary.
+ *
+ * private_dict ::
+ * A pointer to the private dictionary.
+ *
+ * private_len ::
+ * The length in bytes of the private dictionary.
+ *
+ * in_pfb ::
+ * A boolean. Indicates that we are handling a PFB
+ * file.
+ *
+ * in_memory ::
+ * A boolean. Indicates a memory-based stream.
+ *
+ * single_block ::
+ * A boolean. Indicates that the private dictionary
+ * is stored in lieu of the base dictionary.
+ */
typedef struct T1_ParserRec_
{
PS_ParserRec root;
diff --git a/thirdparty/freetype/src/type1/t1tokens.h b/thirdparty/freetype/src/type1/t1tokens.h
index 43a65d88ea..97f2dbe0cf 100644
--- a/thirdparty/freetype/src/type1/t1tokens.h
+++ b/thirdparty/freetype/src/type1/t1tokens.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* t1tokens.h */
-/* */
-/* Type 1 tokenizer (specification). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * t1tokens.h
+ *
+ * Type 1 tokenizer (specification).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#undef FT_STRUCTURE
diff --git a/thirdparty/freetype/src/type1/type1.c b/thirdparty/freetype/src/type1/type1.c
index 72eff59bfe..ce8557a5fb 100644
--- a/thirdparty/freetype/src/type1/type1.c
+++ b/thirdparty/freetype/src/type1/type1.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* type1.c */
-/* */
-/* FreeType Type 1 driver component (body only). */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * type1.c
+ *
+ * FreeType Type 1 driver component (body only).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#define FT_MAKE_OPTION_SINGLE_OBJECT
diff --git a/thirdparty/freetype/src/type42/module.mk b/thirdparty/freetype/src/type42/module.mk
index 3d4732bb6f..9e9d15455b 100644
--- a/thirdparty/freetype/src/type42/module.mk
+++ b/thirdparty/freetype/src/type42/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright 2002-2018 by
+# Copyright (C) 2002-2019 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/type42/rules.mk b/thirdparty/freetype/src/type42/rules.mk
index 9325d3898f..9d71f5300e 100644
--- a/thirdparty/freetype/src/type42/rules.mk
+++ b/thirdparty/freetype/src/type42/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 2002-2018 by
+# Copyright (C) 2002-2019 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/type42/t42drivr.c b/thirdparty/freetype/src/type42/t42drivr.c
index f579b2708c..6d4e7a0955 100644
--- a/thirdparty/freetype/src/type42/t42drivr.c
+++ b/thirdparty/freetype/src/type42/t42drivr.c
@@ -1,39 +1,39 @@
-/***************************************************************************/
-/* */
-/* t42drivr.c */
-/* */
-/* High-level Type 42 driver interface (body). */
-/* */
-/* Copyright 2002-2018 by */
-/* Roberto Alameda. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* This driver implements Type42 fonts as described in the */
- /* Technical Note #5012 from Adobe, with these limitations: */
- /* */
- /* 1) CID Fonts are not currently supported. */
- /* 2) Incremental fonts making use of the GlyphDirectory keyword */
- /* will be loaded, but the rendering will be using the TrueType */
- /* tables. */
- /* 3) As for Type1 fonts, CDevProc is not supported. */
- /* 4) The Metrics dictionary is not supported. */
- /* 5) AFM metrics are not supported. */
- /* */
- /* In other words, this driver supports Type42 fonts derived from */
- /* TrueType fonts in a non-CID manner, as done by usual conversion */
- /* programs. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * t42drivr.c
+ *
+ * High-level Type 42 driver interface (body).
+ *
+ * Copyright (C) 2002-2019 by
+ * Roberto Alameda.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * This driver implements Type42 fonts as described in the
+ * Technical Note #5012 from Adobe, with these limitations:
+ *
+ * 1) CID Fonts are not currently supported.
+ * 2) Incremental fonts making use of the GlyphDirectory keyword
+ * will be loaded, but the rendering will be using the TrueType
+ * tables.
+ * 3) As for Type1 fonts, CDevProc is not supported.
+ * 4) The Metrics dictionary is not supported.
+ * 5) AFM metrics are not supported.
+ *
+ * In other words, this driver supports Type42 fonts derived from
+ * TrueType fonts in a non-CID manner, as done by usual conversion
+ * programs.
+ *
+ */
#include "t42drivr.h"
@@ -47,12 +47,12 @@
#include FT_SERVICE_POSTSCRIPT_INFO_H
#undef FT_COMPONENT
-#define FT_COMPONENT trace_t42
+#define FT_COMPONENT t42
/*
*
- * GLYPH DICT SERVICE
+ * GLYPH DICT SERVICE
*
*/
@@ -98,7 +98,7 @@
/*
*
- * POSTSCRIPT NAME SERVICE
+ * POSTSCRIPT NAME SERVICE
*
*/
@@ -117,7 +117,7 @@
/*
*
- * POSTSCRIPT INFO SERVICE
+ * POSTSCRIPT INFO SERVICE
*
*/
@@ -173,7 +173,7 @@
/*
*
- * SERVICE LIST
+ * SERVICE LIST
*
*/
diff --git a/thirdparty/freetype/src/type42/t42drivr.h b/thirdparty/freetype/src/type42/t42drivr.h
index 3667f3e066..a35ca28f84 100644
--- a/thirdparty/freetype/src/type42/t42drivr.h
+++ b/thirdparty/freetype/src/type42/t42drivr.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* t42drivr.h */
-/* */
-/* High-level Type 42 driver interface (specification). */
-/* */
-/* Copyright 2002-2018 by */
-/* Roberto Alameda. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * t42drivr.h
+ *
+ * High-level Type 42 driver interface (specification).
+ *
+ * Copyright (C) 2002-2019 by
+ * Roberto Alameda.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef T42DRIVR_H_
@@ -26,14 +26,8 @@
FT_BEGIN_HEADER
-#ifdef FT_CONFIG_OPTION_PIC
-#error "this module does not support PIC yet"
-#endif
-
-
FT_EXPORT_VAR( const FT_Driver_ClassRec ) t42_driver_class;
-
FT_END_HEADER
diff --git a/thirdparty/freetype/src/type42/t42error.h b/thirdparty/freetype/src/type42/t42error.h
index e3978a7607..5fb2143949 100644
--- a/thirdparty/freetype/src/type42/t42error.h
+++ b/thirdparty/freetype/src/type42/t42error.h
@@ -1,26 +1,26 @@
-/***************************************************************************/
-/* */
-/* t42error.h */
-/* */
-/* Type 42 error codes (specification only). */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* This file is used to define the Type 42 error enumeration constants. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * t42error.h
+ *
+ * Type 42 error codes (specification only).
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * This file is used to define the Type 42 error enumeration constants.
+ *
+ */
#ifndef T42ERROR_H_
#define T42ERROR_H_
diff --git a/thirdparty/freetype/src/type42/t42objs.c b/thirdparty/freetype/src/type42/t42objs.c
index 66e5c40382..234c0a3e97 100644
--- a/thirdparty/freetype/src/type42/t42objs.c
+++ b/thirdparty/freetype/src/type42/t42objs.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* t42objs.c */
-/* */
-/* Type 42 objects manager (body). */
-/* */
-/* Copyright 2002-2018 by */
-/* Roberto Alameda. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * t42objs.c
+ *
+ * Type 42 objects manager (body).
+ *
+ * Copyright (C) 2002-2019 by
+ * Roberto Alameda.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include "t42objs.h"
@@ -25,7 +25,7 @@
#undef FT_COMPONENT
-#define FT_COMPONENT trace_t42
+#define FT_COMPONENT t42
static FT_Error
@@ -354,7 +354,8 @@
error = FT_CMap_New( cmap_classes->unicode, NULL, &charmap, NULL );
if ( error &&
- FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) )
+ FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) &&
+ FT_ERR_NEQ( error, Unimplemented_Feature ) )
goto Exit;
error = FT_Err_Ok;
@@ -457,20 +458,21 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* T42_Driver_Init */
- /* */
- /* <Description> */
- /* Initializes a given Type 42 driver object. */
- /* */
- /* <Input> */
- /* driver :: A handle to the target driver object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /**************************************************************************
+ *
+ * @Function:
+ * T42_Driver_Init
+ *
+ * @Description:
+ * Initializes a given Type 42 driver object.
+ *
+ * @Input:
+ * driver ::
+ * A handle to the target driver object.
+ *
+ * @Return:
+ * FreeType error code. 0 means success.
+ */
FT_LOCAL_DEF( FT_Error )
T42_Driver_Init( FT_Module module ) /* T42_Driver */
{
diff --git a/thirdparty/freetype/src/type42/t42objs.h b/thirdparty/freetype/src/type42/t42objs.h
index 3bad5135e0..98300cf348 100644
--- a/thirdparty/freetype/src/type42/t42objs.h
+++ b/thirdparty/freetype/src/type42/t42objs.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* t42objs.h */
-/* */
-/* Type 42 objects manager (specification). */
-/* */
-/* Copyright 2002-2018 by */
-/* Roberto Alameda. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * t42objs.h
+ *
+ * Type 42 objects manager (specification).
+ *
+ * Copyright (C) 2002-2019 by
+ * Roberto Alameda.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef T42OBJS_H_
diff --git a/thirdparty/freetype/src/type42/t42parse.c b/thirdparty/freetype/src/type42/t42parse.c
index 4813d1f3f9..b653a133a5 100644
--- a/thirdparty/freetype/src/type42/t42parse.c
+++ b/thirdparty/freetype/src/type42/t42parse.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* t42parse.c */
-/* */
-/* Type 42 font parser (body). */
-/* */
-/* Copyright 2002-2018 by */
-/* Roberto Alameda. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * t42parse.c
+ *
+ * Type 42 font parser (body).
+ *
+ * Copyright (C) 2002-2019 by
+ * Roberto Alameda.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include "t42parse.h"
@@ -23,14 +23,14 @@
#include FT_INTERNAL_POSTSCRIPT_AUX_H
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_t42
+#define FT_COMPONENT t42
static void
@@ -149,19 +149,19 @@
parser->base_dict = NULL;
parser->in_memory = 0;
- /*******************************************************************/
- /* */
- /* Here a short summary of what is going on: */
- /* */
- /* When creating a new Type 42 parser, we try to locate and load */
- /* the base dictionary, loading the whole font into memory. */
- /* */
- /* When `loading' the base dictionary, we only set up pointers */
- /* in the case of a memory-based stream. Otherwise, we allocate */
- /* and load the base dictionary in it. */
- /* */
- /* parser->in_memory is set if we have a memory stream. */
- /* */
+ /********************************************************************
+ *
+ * Here a short summary of what is going on:
+ *
+ * When creating a new Type 42 parser, we try to locate and load
+ * the base dictionary, loading the whole font into memory.
+ *
+ * When `loading' the base dictionary, we only set up pointers
+ * in the case of a memory-based stream. Otherwise, we allocate
+ * and load the base dictionary in it.
+ *
+ * parser->in_memory is set if we have a memory stream.
+ */
if ( FT_STREAM_SEEK( 0L ) ||
FT_FRAME_ENTER( 17 ) )
@@ -284,6 +284,13 @@
matrix->xy = temp[2];
matrix->yy = temp[3];
+ if ( !FT_Matrix_Check( matrix ) )
+ {
+ FT_ERROR(( "t42_parse_font_matrix: invalid font matrix\n" ));
+ parser->root.error = FT_THROW( Invalid_File_Format );
+ return;
+ }
+
/* note that the offsets must be expressed in integer font units */
offset->x = temp[4] >> 16;
offset->y = temp[5] >> 16;
@@ -588,6 +595,14 @@
else if ( *cur == '<' )
{
+ if ( string_buf && !allocated )
+ {
+ FT_ERROR(( "t42_parse_sfnts: "
+ "can't handle mixed binary and hex strings\n" ));
+ error = FT_THROW( Invalid_File_Format );
+ goto Fail;
+ }
+
T1_Skip_PS_Token( parser );
if ( parser->root.error )
goto Exit;
diff --git a/thirdparty/freetype/src/type42/t42parse.h b/thirdparty/freetype/src/type42/t42parse.h
index f35d23de63..0c7bb48496 100644
--- a/thirdparty/freetype/src/type42/t42parse.h
+++ b/thirdparty/freetype/src/type42/t42parse.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* t42parse.h */
-/* */
-/* Type 42 font parser (specification). */
-/* */
-/* Copyright 2002-2018 by */
-/* Roberto Alameda. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * t42parse.h
+ *
+ * Type 42 font parser (specification).
+ *
+ * Copyright (C) 2002-2019 by
+ * Roberto Alameda.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef T42PARSE_H_
diff --git a/thirdparty/freetype/src/type42/t42types.h b/thirdparty/freetype/src/type42/t42types.h
index d0aa2de570..a258144ec3 100644
--- a/thirdparty/freetype/src/type42/t42types.h
+++ b/thirdparty/freetype/src/type42/t42types.h
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* t42types.h */
-/* */
-/* Type 42 font data types (specification only). */
-/* */
-/* Copyright 2002-2018 by */
-/* Roberto Alameda. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * t42types.h
+ *
+ * Type 42 font data types (specification only).
+ *
+ * Copyright (C) 2002-2019 by
+ * Roberto Alameda.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef T42TYPES_H_
diff --git a/thirdparty/freetype/src/type42/type42.c b/thirdparty/freetype/src/type42/type42.c
index 6a89cfbed1..0cb7b77eec 100644
--- a/thirdparty/freetype/src/type42/type42.c
+++ b/thirdparty/freetype/src/type42/type42.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/* */
-/* type42.c */
-/* */
-/* FreeType Type 42 driver component. */
-/* */
-/* Copyright 2002-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * type42.c
+ *
+ * FreeType Type 42 driver component.
+ *
+ * Copyright (C) 2002-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#define FT_MAKE_OPTION_SINGLE_OBJECT
diff --git a/thirdparty/freetype/src/winfonts/fnterrs.h b/thirdparty/freetype/src/winfonts/fnterrs.h
index 3a86af5aac..af29307c75 100644
--- a/thirdparty/freetype/src/winfonts/fnterrs.h
+++ b/thirdparty/freetype/src/winfonts/fnterrs.h
@@ -1,27 +1,27 @@
-/***************************************************************************/
-/* */
-/* fnterrs.h */
-/* */
-/* Win FNT/FON error codes (specification only). */
-/* */
-/* Copyright 2001-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* This file is used to define the Windows FNT/FON error enumeration */
- /* constants. */
- /* */
- /*************************************************************************/
+/****************************************************************************
+ *
+ * fnterrs.h
+ *
+ * Win FNT/FON error codes (specification only).
+ *
+ * Copyright (C) 2001-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * This file is used to define the Windows FNT/FON error enumeration
+ * constants.
+ *
+ */
#ifndef FNTERRS_H_
#define FNTERRS_H_
diff --git a/thirdparty/freetype/src/winfonts/module.mk b/thirdparty/freetype/src/winfonts/module.mk
index 13f9077cfc..82fb0151f8 100644
--- a/thirdparty/freetype/src/winfonts/module.mk
+++ b/thirdparty/freetype/src/winfonts/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2018 by
+# Copyright (C) 1996-2019 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/winfonts/rules.mk b/thirdparty/freetype/src/winfonts/rules.mk
index d694d1a771..998d49bc9f 100644
--- a/thirdparty/freetype/src/winfonts/rules.mk
+++ b/thirdparty/freetype/src/winfonts/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2018 by
+# Copyright (C) 1996-2019 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/winfonts/winfnt.c b/thirdparty/freetype/src/winfonts/winfnt.c
index 36bd3148d5..2d771be2cc 100644
--- a/thirdparty/freetype/src/winfonts/winfnt.c
+++ b/thirdparty/freetype/src/winfonts/winfnt.c
@@ -1,21 +1,21 @@
-/***************************************************************************/
-/* */
-/* winfnt.c */
-/* */
-/* FreeType font driver for Windows FNT/FON files */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* Copyright 2003 Huw D M Davies for Codeweavers */
-/* Copyright 2007 Dmitry Timoshkov for Codeweavers */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * winfnt.c
+ *
+ * FreeType font driver for Windows FNT/FON files
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ * Copyright 2003 Huw D M Davies for Codeweavers
+ * Copyright 2007 Dmitry Timoshkov for Codeweavers
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#include <ft2build.h>
@@ -30,14 +30,14 @@
#include FT_SERVICE_WINFNT_H
#include FT_SERVICE_FONT_FORMAT_H
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_winfnt
+#define FT_COMPONENT winfnt
static const FT_Frame_Field winmz_header_fields[] =
@@ -1131,10 +1131,10 @@
winfnt_get_header /* get_header */
};
- /*
- * SERVICE LIST
- *
- */
+ /*
+ * SERVICE LIST
+ *
+ */
static const FT_ServiceDescRec winfnt_services[] =
{
diff --git a/thirdparty/freetype/src/winfonts/winfnt.h b/thirdparty/freetype/src/winfonts/winfnt.h
index 4885c9d745..b628ad4c42 100644
--- a/thirdparty/freetype/src/winfonts/winfnt.h
+++ b/thirdparty/freetype/src/winfonts/winfnt.h
@@ -1,20 +1,20 @@
-/***************************************************************************/
-/* */
-/* winfnt.h */
-/* */
-/* FreeType font driver for Windows FNT/FON files */
-/* */
-/* Copyright 1996-2018 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* Copyright 2007 Dmitry Timoshkov for Codeweavers */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * winfnt.h
+ *
+ * FreeType font driver for Windows FNT/FON files
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ * Copyright 2007 Dmitry Timoshkov for Codeweavers
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
#ifndef WINFNT_H_
@@ -28,9 +28,6 @@
FT_BEGIN_HEADER
-#ifdef FT_CONFIG_OPTION_PIC
-#error "this module does not support PIC yet"
-#endif
typedef struct WinMZ_HeaderRec_
{
@@ -153,9 +150,6 @@ FT_BEGIN_HEADER
FT_FaceRec root;
FNT_Font font;
- FT_CharMap charmap_handle;
- FT_CharMapRec charmap; /* a single charmap per face */
-
} FNT_FaceRec, *FNT_Face;
diff --git a/thirdparty/glad/LICENSE b/thirdparty/glad/LICENSE
new file mode 100644
index 0000000000..b6e2ca25b0
--- /dev/null
+++ b/thirdparty/glad/LICENSE
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2013-2018 David Herberth
+
+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.
diff --git a/thirdparty/glad/glad.c b/thirdparty/glad/glad.c
index 8cc09e46e1..9704c1079f 100644
--- a/thirdparty/glad/glad.c
+++ b/thirdparty/glad/glad.c
@@ -1,6 +1,6 @@
/*
- OpenGL loader generated by glad 0.1.28 on Thu Nov 22 16:50:04 2018.
+ OpenGL loader generated by glad 0.1.29 on Wed May 1 23:16:34 2019.
Language/Generator: C/C++
Specification: gl
@@ -9,6 +9,8 @@
Extensions:
GL_ARB_debug_output,
GL_ARB_framebuffer_object,
+ GL_EXT_framebuffer_blit,
+ GL_EXT_framebuffer_multisample,
GL_EXT_framebuffer_object
Loader: True
Local files: False
@@ -16,9 +18,9 @@
Reproducible: False
Commandline:
- --profile="compatibility" --api="gl=3.3" --generator="c" --spec="gl" --extensions="GL_ARB_debug_output,GL_ARB_framebuffer_object,GL_EXT_framebuffer_object"
+ --profile="compatibility" --api="gl=3.3" --generator="c" --spec="gl" --extensions="GL_ARB_debug_output,GL_ARB_framebuffer_object,GL_EXT_framebuffer_blit,GL_EXT_framebuffer_multisample,GL_EXT_framebuffer_object"
Online:
- https://glad.dav1d.de/#profile=compatibility&language=c&specification=gl&loader=on&api=gl%3D3.3&extensions=GL_ARB_debug_output&extensions=GL_ARB_framebuffer_object&extensions=GL_EXT_framebuffer_object
+ https://glad.dav1d.de/#profile=compatibility&language=c&specification=gl&loader=on&api=gl%3D3.3&extensions=GL_ARB_debug_output&extensions=GL_ARB_framebuffer_object&extensions=GL_EXT_framebuffer_blit&extensions=GL_EXT_framebuffer_multisample&extensions=GL_EXT_framebuffer_object
*/
#include <stdio.h>
@@ -180,11 +182,7 @@ static int get_exts(void) {
num_exts_i = 0;
glGetIntegerv(GL_NUM_EXTENSIONS, &num_exts_i);
if (num_exts_i > 0) {
- char **tmp_exts_i = (char **)realloc((void *)exts_i, (size_t)num_exts_i * (sizeof *exts_i));
- if (tmp_exts_i == NULL) {
- return 0;
- }
- exts_i = tmp_exts_i;
+ exts_i = (char **)malloc((size_t)num_exts_i * (sizeof *exts_i));
}
if (exts_i == NULL) {
@@ -996,11 +994,15 @@ PFNGLWINDOWPOS3SPROC glad_glWindowPos3s = NULL;
PFNGLWINDOWPOS3SVPROC glad_glWindowPos3sv = NULL;
int GLAD_GL_ARB_debug_output = 0;
int GLAD_GL_ARB_framebuffer_object = 0;
+int GLAD_GL_EXT_framebuffer_blit = 0;
+int GLAD_GL_EXT_framebuffer_multisample = 0;
int GLAD_GL_EXT_framebuffer_object = 0;
PFNGLDEBUGMESSAGECONTROLARBPROC glad_glDebugMessageControlARB = NULL;
PFNGLDEBUGMESSAGEINSERTARBPROC glad_glDebugMessageInsertARB = NULL;
PFNGLDEBUGMESSAGECALLBACKARBPROC glad_glDebugMessageCallbackARB = NULL;
PFNGLGETDEBUGMESSAGELOGARBPROC glad_glGetDebugMessageLogARB = NULL;
+PFNGLBLITFRAMEBUFFEREXTPROC glad_glBlitFramebufferEXT = NULL;
+PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glad_glRenderbufferStorageMultisampleEXT = NULL;
PFNGLISRENDERBUFFEREXTPROC glad_glIsRenderbufferEXT = NULL;
PFNGLBINDRENDERBUFFEREXTPROC glad_glBindRenderbufferEXT = NULL;
PFNGLDELETERENDERBUFFERSEXTPROC glad_glDeleteRenderbuffersEXT = NULL;
@@ -1811,6 +1813,14 @@ static void load_GL_ARB_framebuffer_object(GLADloadproc load) {
glad_glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)load("glRenderbufferStorageMultisample");
glad_glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC)load("glFramebufferTextureLayer");
}
+static void load_GL_EXT_framebuffer_blit(GLADloadproc load) {
+ if(!GLAD_GL_EXT_framebuffer_blit) return;
+ glad_glBlitFramebufferEXT = (PFNGLBLITFRAMEBUFFEREXTPROC)load("glBlitFramebufferEXT");
+}
+static void load_GL_EXT_framebuffer_multisample(GLADloadproc load) {
+ if(!GLAD_GL_EXT_framebuffer_multisample) return;
+ glad_glRenderbufferStorageMultisampleEXT = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)load("glRenderbufferStorageMultisampleEXT");
+}
static void load_GL_EXT_framebuffer_object(GLADloadproc load) {
if(!GLAD_GL_EXT_framebuffer_object) return;
glad_glIsRenderbufferEXT = (PFNGLISRENDERBUFFEREXTPROC)load("glIsRenderbufferEXT");
@@ -1835,6 +1845,8 @@ static int find_extensionsGL(void) {
if (!get_exts()) return 0;
GLAD_GL_ARB_debug_output = has_ext("GL_ARB_debug_output");
GLAD_GL_ARB_framebuffer_object = has_ext("GL_ARB_framebuffer_object");
+ GLAD_GL_EXT_framebuffer_blit = has_ext("GL_EXT_framebuffer_blit");
+ GLAD_GL_EXT_framebuffer_multisample = has_ext("GL_EXT_framebuffer_multisample");
GLAD_GL_EXT_framebuffer_object = has_ext("GL_EXT_framebuffer_object");
free_exts();
return 1;
@@ -1916,6 +1928,8 @@ int gladLoadGLLoader(GLADloadproc load) {
if (!find_extensionsGL()) return 0;
load_GL_ARB_debug_output(load);
load_GL_ARB_framebuffer_object(load);
+ load_GL_EXT_framebuffer_blit(load);
+ load_GL_EXT_framebuffer_multisample(load);
load_GL_EXT_framebuffer_object(load);
return GLVersion.major != 0 || GLVersion.minor != 0;
}
diff --git a/thirdparty/glad/glad/glad.h b/thirdparty/glad/glad/glad.h
index 52b05e0ae6..b398faf627 100644
--- a/thirdparty/glad/glad/glad.h
+++ b/thirdparty/glad/glad/glad.h
@@ -1,6 +1,6 @@
/*
- OpenGL loader generated by glad 0.1.28 on Thu Nov 22 16:50:04 2018.
+ OpenGL loader generated by glad 0.1.29 on Wed May 1 23:16:34 2019.
Language/Generator: C/C++
Specification: gl
@@ -9,6 +9,8 @@
Extensions:
GL_ARB_debug_output,
GL_ARB_framebuffer_object,
+ GL_EXT_framebuffer_blit,
+ GL_EXT_framebuffer_multisample,
GL_EXT_framebuffer_object
Loader: True
Local files: False
@@ -16,9 +18,9 @@
Reproducible: False
Commandline:
- --profile="compatibility" --api="gl=3.3" --generator="c" --spec="gl" --extensions="GL_ARB_debug_output,GL_ARB_framebuffer_object,GL_EXT_framebuffer_object"
+ --profile="compatibility" --api="gl=3.3" --generator="c" --spec="gl" --extensions="GL_ARB_debug_output,GL_ARB_framebuffer_object,GL_EXT_framebuffer_blit,GL_EXT_framebuffer_multisample,GL_EXT_framebuffer_object"
Online:
- https://glad.dav1d.de/#profile=compatibility&language=c&specification=gl&loader=on&api=gl%3D3.3&extensions=GL_ARB_debug_output&extensions=GL_ARB_framebuffer_object&extensions=GL_EXT_framebuffer_object
+ https://glad.dav1d.de/#profile=compatibility&language=c&specification=gl&loader=on&api=gl%3D3.3&extensions=GL_ARB_debug_output&extensions=GL_ARB_framebuffer_object&extensions=GL_EXT_framebuffer_blit&extensions=GL_EXT_framebuffer_multisample&extensions=GL_EXT_framebuffer_object
*/
@@ -3633,6 +3635,13 @@ GLAPI PFNGLSECONDARYCOLORP3UIVPROC glad_glSecondaryColorP3uiv;
#define GL_DEBUG_SEVERITY_HIGH_ARB 0x9146
#define GL_DEBUG_SEVERITY_MEDIUM_ARB 0x9147
#define GL_DEBUG_SEVERITY_LOW_ARB 0x9148
+#define GL_READ_FRAMEBUFFER_EXT 0x8CA8
+#define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9
+#define GL_DRAW_FRAMEBUFFER_BINDING_EXT 0x8CA6
+#define GL_READ_FRAMEBUFFER_BINDING_EXT 0x8CAA
+#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56
+#define GL_MAX_SAMPLES_EXT 0x8D57
#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506
#define GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8
#define GL_FRAMEBUFFER_BINDING_EXT 0x8CA6
@@ -3704,6 +3713,20 @@ GLAPI PFNGLGETDEBUGMESSAGELOGARBPROC glad_glGetDebugMessageLogARB;
#define GL_ARB_framebuffer_object 1
GLAPI int GLAD_GL_ARB_framebuffer_object;
#endif
+#ifndef GL_EXT_framebuffer_blit
+#define GL_EXT_framebuffer_blit 1
+GLAPI int GLAD_GL_EXT_framebuffer_blit;
+typedef void (APIENTRYP PFNGLBLITFRAMEBUFFEREXTPROC)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+GLAPI PFNGLBLITFRAMEBUFFEREXTPROC glad_glBlitFramebufferEXT;
+#define glBlitFramebufferEXT glad_glBlitFramebufferEXT
+#endif
+#ifndef GL_EXT_framebuffer_multisample
+#define GL_EXT_framebuffer_multisample 1
+GLAPI int GLAD_GL_EXT_framebuffer_multisample;
+typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glad_glRenderbufferStorageMultisampleEXT;
+#define glRenderbufferStorageMultisampleEXT glad_glRenderbufferStorageMultisampleEXT
+#endif
#ifndef GL_EXT_framebuffer_object
#define GL_EXT_framebuffer_object 1
GLAPI int GLAD_GL_EXT_framebuffer_object;
diff --git a/thirdparty/libpng/LICENSE b/thirdparty/libpng/LICENSE
index 6ee9c8f554..e0c5b531cf 100644
--- a/thirdparty/libpng/LICENSE
+++ b/thirdparty/libpng/LICENSE
@@ -1,53 +1,82 @@
+COPYRIGHT NOTICE, DISCLAIMER, and LICENSE
+=========================================
-This copy of the libpng notices is provided for your convenience. In case of
-any discrepancy between this copy and the notices in the file png.h that is
-included in the libpng distribution, the latter shall prevail.
+PNG Reference Library License version 2
+---------------------------------------
-COPYRIGHT NOTICE, DISCLAIMER, and LICENSE:
+ * Copyright (c) 1995-2019 The PNG Reference Library Authors.
+ * Copyright (c) 2018-2019 Cosmin Truta.
+ * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
+ * Copyright (c) 1996-1997 Andreas Dilger.
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
-If you modify libpng you may insert additional notices immediately following
-this sentence.
+The software is supplied "as is", without warranty of any kind,
+express or implied, including, without limitation, the warranties
+of merchantability, fitness for a particular purpose, title, and
+non-infringement. In no event shall the Copyright owners, or
+anyone distributing the software, be liable for any damages or
+other liability, whether in contract, tort or otherwise, arising
+from, out of, or in connection with the software, or the use or
+other dealings in the software, even if advised of the possibility
+of such damage.
-This code is released under the libpng license.
+Permission is hereby granted to use, copy, modify, and distribute
+this software, or portions hereof, for any purpose, without fee,
+subject to the following restrictions:
-libpng versions 1.0.7, July 1, 2000 through 1.6.35, July 15, 2018 are
+ 1. The origin of this software must not be misrepresented; you
+ must not claim that you wrote the original software. If you
+ use this software in a product, an acknowledgment in the product
+ documentation would be appreciated, but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must
+ not be misrepresented as being the original software.
+
+ 3. This Copyright notice may not be removed or altered from any
+ source or altered source distribution.
+
+
+PNG Reference Library License version 1 (for libpng 0.5 through 1.6.35)
+-----------------------------------------------------------------------
+
+libpng versions 1.0.7, July 1, 2000, through 1.6.35, July 15, 2018 are
Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson, are
derived from libpng-1.0.6, and are distributed according to the same
disclaimer and license as libpng-1.0.6 with the following individuals
added to the list of Contributing Authors:
- Simon-Pierre Cadieux
- Eric S. Raymond
- Mans Rullgard
- Cosmin Truta
- Gilles Vollant
- James Yu
- Mandar Sahastrabuddhe
- Google Inc.
- Vadim Barkov
+ Simon-Pierre Cadieux
+ Eric S. Raymond
+ Mans Rullgard
+ Cosmin Truta
+ Gilles Vollant
+ James Yu
+ Mandar Sahastrabuddhe
+ Google Inc.
+ Vadim Barkov
and with the following additions to the disclaimer:
- There is no warranty against interference with your enjoyment of the
- library or against infringement. There is no warranty that our
- efforts or the library will fulfill any of your particular purposes
- or needs. This library is provided with all faults, and the entire
- risk of satisfactory quality, performance, accuracy, and effort is with
- the user.
+ There is no warranty against interference with your enjoyment of
+ the library or against infringement. There is no warranty that our
+ efforts or the library will fulfill any of your particular purposes
+ or needs. This library is provided with all faults, and the entire
+ risk of satisfactory quality, performance, accuracy, and effort is
+ with the user.
Some files in the "contrib" directory and some configure-generated
-files that are distributed with libpng have other copyright owners and
+files that are distributed with libpng have other copyright owners, and
are released under other open source licenses.
libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from
libpng-0.96, and are distributed according to the same disclaimer and
-license as libpng-0.96, with the following individuals added to the list
-of Contributing Authors:
+license as libpng-0.96, with the following individuals added to the
+list of Contributing Authors:
- Tom Lane
- Glenn Randers-Pehrson
- Willem van Schaik
+ Tom Lane
+ Glenn Randers-Pehrson
+ Willem van Schaik
libpng versions 0.89, June 1996, through 0.96, May 1997, are
Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88,
@@ -55,14 +84,14 @@ and are distributed according to the same disclaimer and license as
libpng-0.88, with the following individuals added to the list of
Contributing Authors:
- John Bowler
- Kevin Bracey
- Sam Bushell
- Magnus Holmgren
- Greg Roelofs
- Tom Tanner
+ John Bowler
+ Kevin Bracey
+ Sam Bushell
+ Magnus Holmgren
+ Greg Roelofs
+ Tom Tanner
-Some files in the "scripts" directory have other copyright owners
+Some files in the "scripts" directory have other copyright owners,
but are released under this license.
libpng versions 0.5, May 1995, through 0.88, January 1996, are
@@ -71,63 +100,35 @@ Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
For the purposes of this copyright and license, "Contributing Authors"
is defined as the following set of individuals:
- Andreas Dilger
- Dave Martindale
- Guy Eric Schalnat
- Paul Schmidt
- Tim Wegner
-
-The PNG Reference Library is supplied "AS IS". The Contributing Authors
-and Group 42, Inc. disclaim all warranties, expressed or implied,
-including, without limitation, the warranties of merchantability and of
-fitness for any purpose. The Contributing Authors and Group 42, Inc.
-assume no liability for direct, indirect, incidental, special, exemplary,
-or consequential damages, which may result from the use of the PNG
-Reference Library, even if advised of the possibility of such damage.
+ Andreas Dilger
+ Dave Martindale
+ Guy Eric Schalnat
+ Paul Schmidt
+ Tim Wegner
+
+The PNG Reference Library is supplied "AS IS". The Contributing
+Authors and Group 42, Inc. disclaim all warranties, expressed or
+implied, including, without limitation, the warranties of
+merchantability and of fitness for any purpose. The Contributing
+Authors and Group 42, Inc. assume no liability for direct, indirect,
+incidental, special, exemplary, or consequential damages, which may
+result from the use of the PNG Reference Library, even if advised of
+the possibility of such damage.
Permission is hereby granted to use, copy, modify, and distribute this
source code, or portions hereof, for any purpose, without fee, subject
to the following restrictions:
- 1. The origin of this source code must not be misrepresented.
-
- 2. Altered versions must be plainly marked as such and must not
- be misrepresented as being the original source.
-
- 3. This Copyright notice may not be removed or altered from any
- source or altered source distribution.
-
-The Contributing Authors and Group 42, Inc. specifically permit, without
-fee, and encourage the use of this source code as a component to
-supporting the PNG file format in commercial products. If you use this
-source code in a product, acknowledgment is not required but would be
-appreciated.
-
-END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE.
-
-TRADEMARK:
-
-The name "libpng" has not been registered by the Copyright owner
-as a trademark in any jurisdiction. However, because libpng has
-been distributed and maintained world-wide, continually since 1995,
-the Copyright owner claims "common-law trademark protection" in any
-jurisdiction where common-law trademark is recognized.
-
-OSI CERTIFICATION:
-
-Libpng is OSI Certified Open Source Software. OSI Certified Open Source is
-a certification mark of the Open Source Initiative. OSI has not addressed
-the additional disclaimers inserted at version 1.0.7.
+ 1. The origin of this source code must not be misrepresented.
-EXPORT CONTROL:
+ 2. Altered versions must be plainly marked as such and must not
+ be misrepresented as being the original source.
-The Copyright owner believes that the Export Control Classification
-Number (ECCN) for libpng is EAR99, which means not subject to export
-controls or International Traffic in Arms Regulations (ITAR) because
-it is open source, publicly available software, that does not contain
-any encryption software. See the EAR, paragraphs 734.3(b)(3) and
-734.7(b).
+ 3. This Copyright notice may not be removed or altered from any
+ source or altered source distribution.
-Glenn Randers-Pehrson
-glennrp at users.sourceforge.net
-July 15, 2018
+The Contributing Authors and Group 42, Inc. specifically permit,
+without fee, and encourage the use of this source code as a component
+to supporting the PNG file format in commercial products. If you use
+this source code in a product, acknowledgment is not required but would
+be appreciated.
diff --git a/thirdparty/libpng/arm/arm_init.c b/thirdparty/libpng/arm/arm_init.c
index 02df812e77..a34ecdbef7 100644
--- a/thirdparty/libpng/arm/arm_init.c
+++ b/thirdparty/libpng/arm/arm_init.c
@@ -1,14 +1,15 @@
/* arm_init.c - NEON optimised filter functions
*
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 2014,2016 Glenn Randers-Pehrson
* Written by Mans Rullgard, 2011.
- * Last changed in libpng 1.6.22 [May 26, 2016]
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*/
+
/* Below, after checking __linux__, various non-C90 POSIX 1003.1 functions are
* called.
*/
diff --git a/thirdparty/libpng/arm/filter_neon.S b/thirdparty/libpng/arm/filter_neon.S
index 000764cd21..2308aad13e 100644
--- a/thirdparty/libpng/arm/filter_neon.S
+++ b/thirdparty/libpng/arm/filter_neon.S
@@ -1,9 +1,9 @@
/* filter_neon.S - NEON optimised filter functions
*
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 2014,2017 Glenn Randers-Pehrson
* Written by Mans Rullgard, 2011.
- * Last changed in libpng 1.6.31 [July 27, 2017]
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
diff --git a/thirdparty/libpng/arm/filter_neon_intrinsics.c b/thirdparty/libpng/arm/filter_neon_intrinsics.c
index ea7e356bcc..553c0be21c 100644
--- a/thirdparty/libpng/arm/filter_neon_intrinsics.c
+++ b/thirdparty/libpng/arm/filter_neon_intrinsics.c
@@ -1,12 +1,11 @@
/* filter_neon_intrinsics.c - NEON optimised filter functions
*
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 2014,2016 Glenn Randers-Pehrson
* Written by James Yu <james.yu at linaro.org>, October 2013.
* Based on filter_neon.S, written by Mans Rullgard, 2011.
*
- * Last changed in libpng 1.6.22 [May 26, 2016]
- *
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
@@ -19,7 +18,11 @@
/* This code requires -mfpu=neon on the command line: */
#if PNG_ARM_NEON_IMPLEMENTATION == 1 /* intrinsics code from pngpriv.h */
-#include <arm_neon.h>
+#if defined(_MSC_VER) && defined(_M_ARM64)
+# include <arm64_neon.h>
+#else
+# include <arm_neon.h>
+#endif
/* libpng row pointers are not necessarily aligned to any particular boundary,
* however this code will only work with appropriate alignment. arm/arm_init.c
@@ -33,6 +36,11 @@
* 'type'. This is written this way just to hide the GCC strict aliasing
* warning; note that the code is safe because there never is an alias between
* the input and output pointers.
+ *
+ * When compiling with MSVC ARM64, the png_ldr macro can't be passed directly
+ * to vst4_lane_u32, because of an internal compiler error inside MSVC.
+ * To avoid this compiler bug, we use a temporary variable (vdest_val) to store
+ * the result of png_ldr.
*/
#define png_ldr(type,pointer)\
(temp_pointer = png_ptr(type,pointer), *temp_pointer)
@@ -125,12 +133,15 @@ png_read_filter_row_sub4_neon(png_row_infop row_info, png_bytep row,
uint8x8x4_t *vrpt = png_ptr(uint8x8x4_t,&vtmp);
uint8x8x4_t vrp = *vrpt;
uint32x2x4_t *temp_pointer;
+ uint32x2x4_t vdest_val;
vdest.val[0] = vadd_u8(vdest.val[3], vrp.val[0]);
vdest.val[1] = vadd_u8(vdest.val[0], vrp.val[1]);
vdest.val[2] = vadd_u8(vdest.val[1], vrp.val[2]);
vdest.val[3] = vadd_u8(vdest.val[2], vrp.val[3]);
- vst4_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2x4_t,&vdest), 0);
+
+ vdest_val = png_ldr(uint32x2x4_t, &vdest);
+ vst4_lane_u32(png_ptr(uint32_t,rp), vdest_val, 0);
}
PNG_UNUSED(prev_row)
@@ -223,6 +234,7 @@ png_read_filter_row_avg4_neon(png_row_infop row_info, png_bytep row,
uint8x8x4_t *vrpt, *vppt;
uint8x8x4_t vrp, vpp;
uint32x2x4_t *temp_pointer;
+ uint32x2x4_t vdest_val;
vtmp = vld4_u32(png_ptr(uint32_t,rp));
vrpt = png_ptr(uint8x8x4_t,&vtmp);
@@ -240,7 +252,8 @@ png_read_filter_row_avg4_neon(png_row_infop row_info, png_bytep row,
vdest.val[3] = vhadd_u8(vdest.val[2], vpp.val[3]);
vdest.val[3] = vadd_u8(vdest.val[3], vrp.val[3]);
- vst4_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2x4_t,&vdest), 0);
+ vdest_val = png_ldr(uint32x2x4_t, &vdest);
+ vst4_lane_u32(png_ptr(uint32_t,rp), vdest_val, 0);
}
}
@@ -359,6 +372,7 @@ png_read_filter_row_paeth4_neon(png_row_infop row_info, png_bytep row,
uint8x8x4_t *vrpt, *vppt;
uint8x8x4_t vrp, vpp;
uint32x2x4_t *temp_pointer;
+ uint32x2x4_t vdest_val;
vtmp = vld4_u32(png_ptr(uint32_t,rp));
vrpt = png_ptr(uint8x8x4_t,&vtmp);
@@ -378,7 +392,8 @@ png_read_filter_row_paeth4_neon(png_row_infop row_info, png_bytep row,
vlast = vpp.val[3];
- vst4_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2x4_t,&vdest), 0);
+ vdest_val = png_ldr(uint32x2x4_t, &vdest);
+ vst4_lane_u32(png_ptr(uint32_t,rp), vdest_val, 0);
}
}
diff --git a/thirdparty/libpng/arm/palette_neon_intrinsics.c b/thirdparty/libpng/arm/palette_neon_intrinsics.c
new file mode 100644
index 0000000000..b4d1fd2abf
--- /dev/null
+++ b/thirdparty/libpng/arm/palette_neon_intrinsics.c
@@ -0,0 +1,149 @@
+
+/* palette_neon_intrinsics.c - NEON optimised palette expansion functions
+ *
+ * Copyright (c) 2018-2019 Cosmin Truta
+ * Copyright (c) 2017-2018 Arm Holdings. All rights reserved.
+ * Written by Richard Townsend <Richard.Townsend@arm.com>, February 2017.
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ */
+
+#include "../pngpriv.h"
+
+#if PNG_ARM_NEON_IMPLEMENTATION == 1
+
+#if defined(_MSC_VER) && defined(_M_ARM64)
+# include <arm64_neon.h>
+#else
+# include <arm_neon.h>
+#endif
+
+/* Build an RGBA8 palette from the separate RGB and alpha palettes. */
+void
+png_riffle_palette_neon(png_structrp png_ptr)
+{
+ png_const_colorp palette = png_ptr->palette;
+ png_bytep riffled_palette = png_ptr->riffled_palette;
+ png_const_bytep trans_alpha = png_ptr->trans_alpha;
+ int num_trans = png_ptr->num_trans;
+ int i;
+
+ png_debug(1, "in png_riffle_palette_neon");
+
+ /* Initially black, opaque. */
+ uint8x16x4_t w = {{
+ vdupq_n_u8(0x00),
+ vdupq_n_u8(0x00),
+ vdupq_n_u8(0x00),
+ vdupq_n_u8(0xff),
+ }};
+
+ /* First, riffle the RGB colours into an RGBA8 palette.
+ * The alpha component is set to opaque for now.
+ */
+ for (i = 0; i < 256; i += 16)
+ {
+ uint8x16x3_t v = vld3q_u8((png_const_bytep)(palette + i));
+ w.val[0] = v.val[0];
+ w.val[1] = v.val[1];
+ w.val[2] = v.val[2];
+ vst4q_u8(riffled_palette + (i << 2), w);
+ }
+
+ /* Fix up the missing transparency values. */
+ for (i = 0; i < num_trans; i++)
+ riffled_palette[(i << 2) + 3] = trans_alpha[i];
+}
+
+/* Expands a palettized row into RGBA8. */
+int
+png_do_expand_palette_rgba8_neon(png_structrp png_ptr, png_row_infop row_info,
+ png_const_bytep row, png_bytepp ssp, png_bytepp ddp)
+{
+ png_uint_32 row_width = row_info->width;
+ const png_uint_32 *riffled_palette =
+ (const png_uint_32 *)png_ptr->riffled_palette;
+ const png_int_32 pixels_per_chunk = 4;
+ int i;
+
+ png_debug(1, "in png_do_expand_palette_rgba8_neon");
+
+ if (row_width < pixels_per_chunk)
+ return 0;
+
+ /* This function originally gets the last byte of the output row.
+ * The NEON part writes forward from a given position, so we have
+ * to seek this back by 4 pixels x 4 bytes.
+ */
+ *ddp = *ddp - ((pixels_per_chunk * sizeof(png_uint_32)) - 1);
+
+ for (i = 0; i < row_width; i += pixels_per_chunk)
+ {
+ uint32x4_t cur;
+ png_bytep sp = *ssp - i, dp = *ddp - (i << 2);
+ cur = vld1q_dup_u32 (riffled_palette + *(sp - 3));
+ cur = vld1q_lane_u32(riffled_palette + *(sp - 2), cur, 1);
+ cur = vld1q_lane_u32(riffled_palette + *(sp - 1), cur, 2);
+ cur = vld1q_lane_u32(riffled_palette + *(sp - 0), cur, 3);
+ vst1q_u32((void *)dp, cur);
+ }
+ if (i != row_width)
+ {
+ /* Remove the amount that wasn't processed. */
+ i -= pixels_per_chunk;
+ }
+
+ /* Decrement output pointers. */
+ *ssp = *ssp - i;
+ *ddp = *ddp - (i << 2);
+ return i;
+}
+
+/* Expands a palettized row into RGB8. */
+int
+png_do_expand_palette_rgb8_neon(png_structrp png_ptr, png_row_infop row_info,
+ png_const_bytep row, png_bytepp ssp, png_bytepp ddp)
+{
+ png_uint_32 row_width = row_info->width;
+ png_const_bytep palette = (png_const_bytep)png_ptr->palette;
+ const png_uint_32 pixels_per_chunk = 8;
+ int i;
+
+ png_debug(1, "in png_do_expand_palette_rgb8_neon");
+
+ if (row_width <= pixels_per_chunk)
+ return 0;
+
+ /* Seeking this back by 8 pixels x 3 bytes. */
+ *ddp = *ddp - ((pixels_per_chunk * sizeof(png_color)) - 1);
+
+ for (i = 0; i < row_width; i += pixels_per_chunk)
+ {
+ uint8x8x3_t cur;
+ png_bytep sp = *ssp - i, dp = *ddp - ((i << 1) + i);
+ cur = vld3_dup_u8(palette + sizeof(png_color) * (*(sp - 7)));
+ cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 6)), cur, 1);
+ cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 5)), cur, 2);
+ cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 4)), cur, 3);
+ cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 3)), cur, 4);
+ cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 2)), cur, 5);
+ cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 1)), cur, 6);
+ cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 0)), cur, 7);
+ vst3_u8((void *)dp, cur);
+ }
+
+ if (i != row_width)
+ {
+ /* Remove the amount that wasn't processed. */
+ i -= pixels_per_chunk;
+ }
+
+ /* Decrement output pointers. */
+ *ssp = *ssp - i;
+ *ddp = *ddp - ((i << 1) + i);
+ return i;
+}
+
+#endif /* PNG_ARM_NEON_IMPLEMENTATION */
diff --git a/thirdparty/libpng/png.c b/thirdparty/libpng/png.c
index a25afebcc8..757c755f97 100644
--- a/thirdparty/libpng/png.c
+++ b/thirdparty/libpng/png.c
@@ -1,10 +1,10 @@
/* png.c - location for general purpose libpng functions
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018-2019 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
@@ -14,7 +14,7 @@
#include "pngpriv.h"
/* Generate a compiler error if there is an old png.h in the search path. */
-typedef png_libpng_version_1_6_35 Your_png_h_is_not_version_1_6_35;
+typedef png_libpng_version_1_6_37 Your_png_h_is_not_version_1_6_37;
#ifdef __GNUC__
/* The version tests may need to be added to, but the problem warning has
@@ -736,7 +736,7 @@ png_save_int_32(png_bytep buf, png_int_32 i)
int PNGAPI
png_convert_to_rfc1123_buffer(char out[29], png_const_timep ptime)
{
- static PNG_CONST char short_months[12][4] =
+ static const char short_months[12][4] =
{"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
@@ -814,20 +814,14 @@ png_get_copyright(png_const_structrp png_ptr)
#ifdef PNG_STRING_COPYRIGHT
return PNG_STRING_COPYRIGHT
#else
-# ifdef __STDC__
return PNG_STRING_NEWLINE \
- "libpng version 1.6.35 - July 15, 2018" PNG_STRING_NEWLINE \
+ "libpng version 1.6.37" PNG_STRING_NEWLINE \
+ "Copyright (c) 2018-2019 Cosmin Truta" PNG_STRING_NEWLINE \
"Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson" \
PNG_STRING_NEWLINE \
"Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
"Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \
PNG_STRING_NEWLINE;
-# else
- return "libpng version 1.6.35 - July 15, 2018\
- Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson\
- Copyright (c) 1996-1997 Andreas Dilger\
- Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.";
-# endif
#endif
}
@@ -1121,7 +1115,7 @@ png_colorspace_set_gamma(png_const_structrp png_ptr,
png_colorspacerp colorspace, png_fixed_point gAMA)
{
/* Changed in libpng-1.5.4 to limit the values to ensure overflow can't
- * occur. Since the fixed point representation is asymetrical it is
+ * occur. Since the fixed point representation is asymmetrical it is
* possible for 1/gamma to overflow the limit of 21474 and this means the
* gamma value must be at least 5/100000 and hence at most 20000.0. For
* safety the limits here are a little narrower. The values are 0.00016 to
@@ -3134,11 +3128,11 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, size_t size,
/* The total output count (max) is now 4+precision */
/* Check for an exponent, if we don't need one we are
- * done and just need to terminate the string. At
- * this point exp_b10==(-1) is effectively a flag - it got
- * to '-1' because of the decrement after outputting
- * the decimal point above (the exponent required is
- * *not* -1!)
+ * done and just need to terminate the string. At this
+ * point, exp_b10==(-1) is effectively a flag: it got
+ * to '-1' because of the decrement, after outputting
+ * the decimal point above. (The exponent required is
+ * *not* -1.)
*/
if (exp_b10 >= (-1) && exp_b10 <= 2)
{
@@ -3976,18 +3970,18 @@ png_gamma_correct(png_structrp png_ptr, unsigned int value,
*/
static void
png_build_16bit_table(png_structrp png_ptr, png_uint_16pp *ptable,
- PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val)
+ unsigned int shift, png_fixed_point gamma_val)
{
/* Various values derived from 'shift': */
- PNG_CONST unsigned int num = 1U << (8U - shift);
+ unsigned int num = 1U << (8U - shift);
#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
/* CSE the division and work round wacky GCC warnings (see the comments
* in png_gamma_8bit_correct for where these come from.)
*/
- PNG_CONST double fmax = 1./(((png_int_32)1 << (16U - shift))-1);
+ double fmax = 1.0 / (((png_int_32)1 << (16U - shift)) - 1);
#endif
- PNG_CONST unsigned int max = (1U << (16U - shift))-1U;
- PNG_CONST unsigned int max_by_2 = 1U << (15U-shift);
+ unsigned int max = (1U << (16U - shift)) - 1U;
+ unsigned int max_by_2 = 1U << (15U - shift);
unsigned int i;
png_uint_16pp table = *ptable =
@@ -4053,10 +4047,10 @@ png_build_16bit_table(png_structrp png_ptr, png_uint_16pp *ptable,
*/
static void
png_build_16to8_table(png_structrp png_ptr, png_uint_16pp *ptable,
- PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val)
+ unsigned int shift, png_fixed_point gamma_val)
{
- PNG_CONST unsigned int num = 1U << (8U - shift);
- PNG_CONST unsigned int max = (1U << (16U - shift))-1U;
+ unsigned int num = 1U << (8U - shift);
+ unsigned int max = (1U << (16U - shift))-1U;
unsigned int i;
png_uint_32 last;
@@ -4121,7 +4115,7 @@ png_build_16to8_table(png_structrp png_ptr, png_uint_16pp *ptable,
*/
static void
png_build_8bit_table(png_structrp png_ptr, png_bytepp ptable,
- PNG_CONST png_fixed_point gamma_val)
+ png_fixed_point gamma_val)
{
unsigned int i;
png_bytep table = *ptable = (png_bytep)png_malloc(png_ptr, 256);
@@ -4594,8 +4588,7 @@ png_image_free(png_imagep image)
if (image != NULL && image->opaque != NULL &&
image->opaque->error_buf == NULL)
{
- /* Ignore errors here: */
- (void)png_safe_execute(image, png_image_free_function, image);
+ png_image_free_function(image);
image->opaque = NULL;
}
}
diff --git a/thirdparty/libpng/png.h b/thirdparty/libpng/png.h
index 19e464cc17..b12174ba35 100644
--- a/thirdparty/libpng/png.h
+++ b/thirdparty/libpng/png.h
@@ -1,68 +1,105 @@
/* png.h - header file for PNG reference library
*
- * libpng version 1.6.35, July 15, 2018
+ * libpng version 1.6.37 - April 14, 2019
*
+ * Copyright (c) 2018-2019 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
- * This code is released under the libpng license (See LICENSE, below)
+ * This code is released under the libpng license. (See LICENSE, below.)
*
* Authors and maintainers:
* libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat
* libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger
- * libpng versions 0.97, January 1998, through 1.6.35, July 15, 2018:
- * Glenn Randers-Pehrson.
+ * libpng versions 0.97, January 1998, through 1.6.35, July 2018:
+ * Glenn Randers-Pehrson
+ * libpng versions 1.6.36, December 2018, through 1.6.37, April 2019:
+ * Cosmin Truta
* See also "Contributing Authors", below.
*/
/*
- * COPYRIGHT NOTICE, DISCLAIMER, and LICENSE:
+ * COPYRIGHT NOTICE, DISCLAIMER, and LICENSE
+ * =========================================
+ *
+ * PNG Reference Library License version 2
+ * ---------------------------------------
+ *
+ * * Copyright (c) 1995-2019 The PNG Reference Library Authors.
+ * * Copyright (c) 2018-2019 Cosmin Truta.
+ * * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
+ * * Copyright (c) 1996-1997 Andreas Dilger.
+ * * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
+ *
+ * The software is supplied "as is", without warranty of any kind,
+ * express or implied, including, without limitation, the warranties
+ * of merchantability, fitness for a particular purpose, title, and
+ * non-infringement. In no event shall the Copyright owners, or
+ * anyone distributing the software, be liable for any damages or
+ * other liability, whether in contract, tort or otherwise, arising
+ * from, out of, or in connection with the software, or the use or
+ * other dealings in the software, even if advised of the possibility
+ * of such damage.
+ *
+ * Permission is hereby granted to use, copy, modify, and distribute
+ * this software, or portions hereof, for any purpose, without fee,
+ * subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you
+ * must not claim that you wrote the original software. If you
+ * use this software in a product, an acknowledgment in the product
+ * documentation would be appreciated, but is not required.
+ *
+ * 2. Altered source versions must be plainly marked as such, and must
+ * not be misrepresented as being the original software.
*
- * If you modify libpng you may insert additional notices immediately following
- * this sentence.
+ * 3. This Copyright notice may not be removed or altered from any
+ * source or altered source distribution.
*
- * This code is released under the libpng license.
*
- * libpng versions 1.0.7, July 1, 2000 through 1.6.35, July 15, 2018 are
+ * PNG Reference Library License version 1 (for libpng 0.5 through 1.6.35)
+ * -----------------------------------------------------------------------
+ *
+ * libpng versions 1.0.7, July 1, 2000, through 1.6.35, July 15, 2018 are
* Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson, are
* derived from libpng-1.0.6, and are distributed according to the same
* disclaimer and license as libpng-1.0.6 with the following individuals
* added to the list of Contributing Authors:
*
- * Simon-Pierre Cadieux
- * Eric S. Raymond
- * Mans Rullgard
- * Cosmin Truta
- * Gilles Vollant
- * James Yu
- * Mandar Sahastrabuddhe
- * Google Inc.
- * Vadim Barkov
+ * Simon-Pierre Cadieux
+ * Eric S. Raymond
+ * Mans Rullgard
+ * Cosmin Truta
+ * Gilles Vollant
+ * James Yu
+ * Mandar Sahastrabuddhe
+ * Google Inc.
+ * Vadim Barkov
*
* and with the following additions to the disclaimer:
*
- * There is no warranty against interference with your enjoyment of the
- * library or against infringement. There is no warranty that our
- * efforts or the library will fulfill any of your particular purposes
- * or needs. This library is provided with all faults, and the entire
- * risk of satisfactory quality, performance, accuracy, and effort is with
- * the user.
+ * There is no warranty against interference with your enjoyment of
+ * the library or against infringement. There is no warranty that our
+ * efforts or the library will fulfill any of your particular purposes
+ * or needs. This library is provided with all faults, and the entire
+ * risk of satisfactory quality, performance, accuracy, and effort is
+ * with the user.
*
* Some files in the "contrib" directory and some configure-generated
- * files that are distributed with libpng have other copyright owners and
+ * files that are distributed with libpng have other copyright owners, and
* are released under other open source licenses.
*
* libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
* Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from
* libpng-0.96, and are distributed according to the same disclaimer and
- * license as libpng-0.96, with the following individuals added to the list
- * of Contributing Authors:
+ * license as libpng-0.96, with the following individuals added to the
+ * list of Contributing Authors:
*
- * Tom Lane
- * Glenn Randers-Pehrson
- * Willem van Schaik
+ * Tom Lane
+ * Glenn Randers-Pehrson
+ * Willem van Schaik
*
* libpng versions 0.89, June 1996, through 0.96, May 1997, are
* Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88,
@@ -70,14 +107,14 @@
* libpng-0.88, with the following individuals added to the list of
* Contributing Authors:
*
- * John Bowler
- * Kevin Bracey
- * Sam Bushell
- * Magnus Holmgren
- * Greg Roelofs
- * Tom Tanner
+ * John Bowler
+ * Kevin Bracey
+ * Sam Bushell
+ * Magnus Holmgren
+ * Greg Roelofs
+ * Tom Tanner
*
- * Some files in the "scripts" directory have other copyright owners
+ * Some files in the "scripts" directory have other copyright owners,
* but are released under this license.
*
* libpng versions 0.5, May 1995, through 0.88, January 1996, are
@@ -86,62 +123,49 @@
* For the purposes of this copyright and license, "Contributing Authors"
* is defined as the following set of individuals:
*
- * Andreas Dilger
- * Dave Martindale
- * Guy Eric Schalnat
- * Paul Schmidt
- * Tim Wegner
- *
- * The PNG Reference Library is supplied "AS IS". The Contributing Authors
- * and Group 42, Inc. disclaim all warranties, expressed or implied,
- * including, without limitation, the warranties of merchantability and of
- * fitness for any purpose. The Contributing Authors and Group 42, Inc.
- * assume no liability for direct, indirect, incidental, special, exemplary,
- * or consequential damages, which may result from the use of the PNG
- * Reference Library, even if advised of the possibility of such damage.
+ * Andreas Dilger
+ * Dave Martindale
+ * Guy Eric Schalnat
+ * Paul Schmidt
+ * Tim Wegner
+ *
+ * The PNG Reference Library is supplied "AS IS". The Contributing
+ * Authors and Group 42, Inc. disclaim all warranties, expressed or
+ * implied, including, without limitation, the warranties of
+ * merchantability and of fitness for any purpose. The Contributing
+ * Authors and Group 42, Inc. assume no liability for direct, indirect,
+ * incidental, special, exemplary, or consequential damages, which may
+ * result from the use of the PNG Reference Library, even if advised of
+ * the possibility of such damage.
*
* Permission is hereby granted to use, copy, modify, and distribute this
* source code, or portions hereof, for any purpose, without fee, subject
* to the following restrictions:
*
- * 1. The origin of this source code must not be misrepresented.
+ * 1. The origin of this source code must not be misrepresented.
*
- * 2. Altered versions must be plainly marked as such and must not
- * be misrepresented as being the original source.
+ * 2. Altered versions must be plainly marked as such and must not
+ * be misrepresented as being the original source.
*
- * 3. This Copyright notice may not be removed or altered from any
- * source or altered source distribution.
+ * 3. This Copyright notice may not be removed or altered from any
+ * source or altered source distribution.
*
- * The Contributing Authors and Group 42, Inc. specifically permit, without
- * fee, and encourage the use of this source code as a component to
- * supporting the PNG file format in commercial products. If you use this
- * source code in a product, acknowledgment is not required but would be
- * appreciated.
+ * The Contributing Authors and Group 42, Inc. specifically permit,
+ * without fee, and encourage the use of this source code as a component
+ * to supporting the PNG file format in commercial products. If you use
+ * this source code in a product, acknowledgment is not required but would
+ * be appreciated.
*
* END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE.
*
- * TRADEMARK:
+ * TRADEMARK
+ * =========
*
- * The name "libpng" has not been registered by the Copyright owner
+ * The name "libpng" has not been registered by the Copyright owners
* as a trademark in any jurisdiction. However, because libpng has
* been distributed and maintained world-wide, continually since 1995,
- * the Copyright owner claims "common-law trademark protection" in any
+ * the Copyright owners claim "common-law trademark protection" in any
* jurisdiction where common-law trademark is recognized.
- *
- * OSI CERTIFICATION:
- *
- * Libpng is OSI Certified Open Source Software. OSI Certified Open Source is
- * a certification mark of the Open Source Initiative. OSI has not addressed
- * the additional disclaimers inserted at version 1.0.7.
- *
- * EXPORT CONTROL:
- *
- * The Copyright owner believes that the Export Control Classification
- * Number (ECCN) for libpng is EAR99, which means not subject to export
- * controls or International Traffic in Arms Regulations (ITAR) because
- * it is open source, publicly available software, that does not contain
- * any encryption software. See the EAR, paragraphs 734.3(b)(3) and
- * 734.7(b).
*/
/*
@@ -207,23 +231,25 @@
* 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible)
* 1.0.7 1 10007 (still compatible)
* ...
- * 1.0.19 10 10019 10.so.0.19[.0]
+ * 1.0.69 10 10069 10.so.0.69[.0]
* ...
- * 1.2.59 13 10257 12.so.0.59[.0]
+ * 1.2.59 13 10259 12.so.0.59[.0]
* ...
- * 1.5.30 15 10527 15.so.15.30[.0]
+ * 1.4.20 14 10420 14.so.0.20[.0]
* ...
- * 1.6.35 16 10635 16.so.16.35[.0]
- *
- * Henceforth the source version will match the shared-library major
- * and minor numbers; the shared-library major version number will be
- * used for changes in backward compatibility, as it is intended. The
- * PNG_LIBPNG_VER macro, which is not used within libpng but is available
- * for applications, is an unsigned integer of the form xyyzz corresponding
- * to the source version x.y.z (leading zeros in y and z). Beta versions
- * were given the previous public release number plus a letter, until
- * version 1.0.6j; from then on they were given the upcoming public
- * release number plus "betaNN" or "rcNN".
+ * 1.5.30 15 10530 15.so.15.30[.0]
+ * ...
+ * 1.6.37 16 10637 16.so.16.37[.0]
+ *
+ * Henceforth the source version will match the shared-library major and
+ * minor numbers; the shared-library major version number will be used for
+ * changes in backward compatibility, as it is intended.
+ * The PNG_LIBPNG_VER macro, which is not used within libpng but is
+ * available for applications, is an unsigned integer of the form XYYZZ
+ * corresponding to the source version X.Y.Z (leading zeros in Y and Z).
+ * Beta versions were given the previous public release number plus a
+ * letter, until version 1.0.6j; from then on they were given the upcoming
+ * public release number plus "betaNN" or "rcNN".
*
* Binary incompatibility exists only when applications make direct access
* to the info_ptr or png_ptr members through png.h, and the compiled
@@ -233,65 +259,8 @@
* in binary compatibility (e.g., when a new feature is added).
*
* See libpng.txt or libpng.3 for more information. The PNG specification
- * is available as a W3C Recommendation and as an ISO Specification,
- * <https://www.w3.org/TR/2003/REC-PNG-20031110/
- */
-
-/*
- * Y2K compliance in libpng:
- * =========================
- *
- * July 15, 2018
- *
- * Since the PNG Development group is an ad-hoc body, we can't make
- * an official declaration.
- *
- * This is your unofficial assurance that libpng from version 0.71 and
- * upward through 1.6.35 are Y2K compliant. It is my belief that
- * earlier versions were also Y2K compliant.
- *
- * Libpng only has two year fields. One is a 2-byte unsigned integer
- * that will hold years up to 65535. The other, which is deprecated,
- * holds the date in text format, and will hold years up to 9999.
- *
- * The integer is
- * "png_uint_16 year" in png_time_struct.
- *
- * The string is
- * "char time_buffer[29]" in png_struct. This is no longer used
- * in libpng-1.6.x and will be removed from libpng-1.7.0.
- *
- * There are seven time-related functions:
- * png.c: png_convert_to_rfc_1123_buffer() in png.c
- * (formerly png_convert_to_rfc_1123() prior to libpng-1.5.x and
- * png_convert_to_rfc_1152() in error prior to libpng-0.98)
- * png_convert_from_struct_tm() in pngwrite.c, called in pngwrite.c
- * png_convert_from_time_t() in pngwrite.c
- * png_get_tIME() in pngget.c
- * png_handle_tIME() in pngrutil.c, called in pngread.c
- * png_set_tIME() in pngset.c
- * png_write_tIME() in pngwutil.c, called in pngwrite.c
- *
- * All handle dates properly in a Y2K environment. The
- * png_convert_from_time_t() function calls gmtime() to convert from system
- * clock time, which returns (year - 1900), which we properly convert to
- * the full 4-digit year. There is a possibility that libpng applications
- * are not passing 4-digit years into the png_convert_to_rfc_1123_buffer()
- * function, or that they are incorrectly passing only a 2-digit year
- * instead of "year - 1900" into the png_convert_from_struct_tm() function,
- * but this is not under our control. The libpng documentation has always
- * stated that it works with 4-digit years, and the APIs have been
- * documented as such.
- *
- * The tIME chunk itself is also Y2K compliant. It uses a 2-byte unsigned
- * integer to hold the year, and can hold years as large as 65535.
- *
- * zlib, upon which libpng depends, is also Y2K compliant. It contains
- * no date-related code.
- *
- * Glenn Randers-Pehrson
- * libpng maintainer
- * PNG Development Group
+ * is available as a W3C Recommendation and as an ISO/IEC Standard; see
+ * <https://www.w3.org/TR/2003/REC-PNG-20031110/>
*/
#ifndef PNG_H
@@ -309,8 +278,8 @@
*/
/* Version information for png.h - this should match the version in png.c */
-#define PNG_LIBPNG_VER_STRING "1.6.35"
-#define PNG_HEADER_VERSION_STRING " libpng version 1.6.35 - July 15, 2018\n"
+#define PNG_LIBPNG_VER_STRING "1.6.37"
+#define PNG_HEADER_VERSION_STRING " libpng version 1.6.37 - April 14, 2019\n"
#define PNG_LIBPNG_VER_SONUM 16
#define PNG_LIBPNG_VER_DLLNUM 16
@@ -318,13 +287,12 @@
/* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */
#define PNG_LIBPNG_VER_MAJOR 1
#define PNG_LIBPNG_VER_MINOR 6
-#define PNG_LIBPNG_VER_RELEASE 35
+#define PNG_LIBPNG_VER_RELEASE 37
-/* This should match the numeric part of the final component of
- * PNG_LIBPNG_VER_STRING, omitting any leading zero:
+/* This should be zero for a public release, or non-zero for a
+ * development version. [Deprecated]
*/
-
-#define PNG_LIBPNG_VER_BUILD 02
+#define PNG_LIBPNG_VER_BUILD 0
/* Release Status */
#define PNG_LIBPNG_BUILD_ALPHA 1
@@ -341,15 +309,16 @@
#define PNG_LIBPNG_BUILD_SPECIAL 32 /* Cannot be OR'ed with
PNG_LIBPNG_BUILD_PRIVATE */
-#define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_BETA
+#define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_STABLE
-/* Careful here. At one time, Guy wanted to use 082, but that would be octal.
- * We must not include leading zeros.
- * Versions 0.7 through 1.0.0 were in the range 0 to 100 here (only
- * version 1.0.0 was mis-numbered 100 instead of 10000). From
- * version 1.0.1 it's xxyyzz, where x=major, y=minor, z=release
+/* Careful here. At one time, Guy wanted to use 082, but that
+ * would be octal. We must not include leading zeros.
+ * Versions 0.7 through 1.0.0 were in the range 0 to 100 here
+ * (only version 1.0.0 was mis-numbered 100 instead of 10000).
+ * From version 1.0.1 it is:
+ * XXYYZZ, where XX=major, YY=minor, ZZ=release
*/
-#define PNG_LIBPNG_VER 10635 /* 1.6.35 */
+#define PNG_LIBPNG_VER 10637 /* 1.6.37 */
/* Library configuration: these options cannot be changed after
* the library has been built.
@@ -361,6 +330,10 @@
# include "pnglibconf.h"
#endif
+#define PNG_APNG_SUPPORTED
+#define PNG_READ_APNG_SUPPORTED
+#define PNG_WRITE_APNG_SUPPORTED
+
#ifndef PNG_VERSION_INFO_ONLY
/* Machine specific configuration. */
# include "pngconf.h"
@@ -456,10 +429,21 @@ extern "C" {
* See pngconf.h for base types that vary by machine/system
*/
+#ifdef PNG_APNG_SUPPORTED
+/* dispose_op flags from inside fcTL */
+#define PNG_DISPOSE_OP_NONE 0x00U
+#define PNG_DISPOSE_OP_BACKGROUND 0x01U
+#define PNG_DISPOSE_OP_PREVIOUS 0x02U
+
+/* blend_op flags from inside fcTL */
+#define PNG_BLEND_OP_SOURCE 0x00U
+#define PNG_BLEND_OP_OVER 0x01U
+#endif /* PNG_APNG_SUPPORTED */
+
/* This triggers a compiler error in png.c, if png.c and png.h
* do not agree upon the version number.
*/
-typedef char* png_libpng_version_1_6_35;
+typedef char* png_libpng_version_1_6_37;
/* Basic control structions. Read libpng-manual.txt or libpng.3 for more info.
*
@@ -777,6 +761,10 @@ typedef png_unknown_chunk * * png_unknown_chunkpp;
#define PNG_INFO_sCAL 0x4000U /* ESR, 1.0.6 */
#define PNG_INFO_IDAT 0x8000U /* ESR, 1.0.6 */
#define PNG_INFO_eXIf 0x10000U /* GR-P, 1.6.31 */
+#ifdef PNG_APNG_SUPPORTED
+#define PNG_INFO_acTL 0x20000U
+#define PNG_INFO_fcTL 0x40000U
+#endif
/* This is used for the transformation routines, as some of them
* change these values for the row. It also should enable using
@@ -814,6 +802,10 @@ typedef PNG_CALLBACK(void, *png_write_status_ptr, (png_structp, png_uint_32,
#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
typedef PNG_CALLBACK(void, *png_progressive_info_ptr, (png_structp, png_infop));
typedef PNG_CALLBACK(void, *png_progressive_end_ptr, (png_structp, png_infop));
+#ifdef PNG_APNG_SUPPORTED
+typedef PNG_CALLBACK(void, *png_progressive_frame_ptr, (png_structp,
+ png_uint_32));
+#endif
/* The following callback receives png_uint_32 row_number, int pass for the
* png_bytep data of the row. When transforming an interlaced image the
@@ -2013,12 +2005,12 @@ PNG_FIXED_EXPORT(233, void, png_set_cHRM_XYZ_fixed, (png_const_structrp png_ptr,
PNG_EXPORT(246, png_uint_32, png_get_eXIf, (png_const_structrp png_ptr,
png_inforp info_ptr, png_bytep *exif));
PNG_EXPORT(247, void, png_set_eXIf, (png_const_structrp png_ptr,
- png_inforp info_ptr, const png_bytep exif));
+ png_inforp info_ptr, png_bytep exif));
PNG_EXPORT(248, png_uint_32, png_get_eXIf_1, (png_const_structrp png_ptr,
png_const_inforp info_ptr, png_uint_32 *num_exif, png_bytep *exif));
PNG_EXPORT(249, void, png_set_eXIf_1, (png_const_structrp png_ptr,
- png_inforp info_ptr, const png_uint_32 num_exif, const png_bytep exif));
+ png_inforp info_ptr, png_uint_32 num_exif, png_bytep exif));
#endif
#ifdef PNG_gAMA_SUPPORTED
@@ -2764,7 +2756,7 @@ typedef struct
*
* When the simplified API needs to convert between sRGB and linear colorspaces,
* the actual sRGB transfer curve defined in the sRGB specification (see the
- * article at https://en.wikipedia.org/wiki/SRGB) is used, not the gamma=1/2.2
+ * article at <https://en.wikipedia.org/wiki/SRGB>) is used, not the gamma=1/2.2
* approximation used elsewhere in libpng.
*
* When an alpha channel is present it is expected to denote pixel coverage
@@ -2967,7 +2959,7 @@ typedef struct
* 'flags' field of png_image.
*/
#define PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB 0x01
- /* This indicates the the RGB values of the in-memory bitmap do not
+ /* This indicates that the RGB values of the in-memory bitmap do not
* correspond to the red, green and blue end-points defined by sRGB.
*/
@@ -3257,6 +3249,74 @@ PNG_EXPORT(244, int, png_set_option, (png_structrp png_ptr, int option,
/*******************************************************************************
* END OF HARDWARE AND SOFTWARE OPTIONS
******************************************************************************/
+#ifdef PNG_APNG_SUPPORTED
+PNG_EXPORT(250, png_uint_32, png_get_acTL, (png_structp png_ptr,
+ png_infop info_ptr, png_uint_32 *num_frames, png_uint_32 *num_plays));
+
+PNG_EXPORT(251, png_uint_32, png_set_acTL, (png_structp png_ptr,
+ png_infop info_ptr, png_uint_32 num_frames, png_uint_32 num_plays));
+
+PNG_EXPORT(252, png_uint_32, png_get_num_frames, (png_structp png_ptr,
+ png_infop info_ptr));
+
+PNG_EXPORT(253, png_uint_32, png_get_num_plays, (png_structp png_ptr,
+ png_infop info_ptr));
+
+PNG_EXPORT(254, png_uint_32, png_get_next_frame_fcTL,
+ (png_structp png_ptr, png_infop info_ptr, png_uint_32 *width,
+ png_uint_32 *height, png_uint_32 *x_offset, png_uint_32 *y_offset,
+ png_uint_16 *delay_num, png_uint_16 *delay_den, png_byte *dispose_op,
+ png_byte *blend_op));
+
+PNG_EXPORT(255, png_uint_32, png_set_next_frame_fcTL,
+ (png_structp png_ptr, png_infop info_ptr, png_uint_32 width,
+ png_uint_32 height, png_uint_32 x_offset, png_uint_32 y_offset,
+ png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op,
+ png_byte blend_op));
+
+PNG_EXPORT(256, png_uint_32, png_get_next_frame_width,
+ (png_structp png_ptr, png_infop info_ptr));
+PNG_EXPORT(257, png_uint_32, png_get_next_frame_height,
+ (png_structp png_ptr, png_infop info_ptr));
+PNG_EXPORT(258, png_uint_32, png_get_next_frame_x_offset,
+ (png_structp png_ptr, png_infop info_ptr));
+PNG_EXPORT(259, png_uint_32, png_get_next_frame_y_offset,
+ (png_structp png_ptr, png_infop info_ptr));
+PNG_EXPORT(260, png_uint_16, png_get_next_frame_delay_num,
+ (png_structp png_ptr, png_infop info_ptr));
+PNG_EXPORT(261, png_uint_16, png_get_next_frame_delay_den,
+ (png_structp png_ptr, png_infop info_ptr));
+PNG_EXPORT(262, png_byte, png_get_next_frame_dispose_op,
+ (png_structp png_ptr, png_infop info_ptr));
+PNG_EXPORT(263, png_byte, png_get_next_frame_blend_op,
+ (png_structp png_ptr, png_infop info_ptr));
+PNG_EXPORT(264, png_byte, png_get_first_frame_is_hidden,
+ (png_structp png_ptr, png_infop info_ptr));
+PNG_EXPORT(265, png_uint_32, png_set_first_frame_is_hidden,
+ (png_structp png_ptr, png_infop info_ptr, png_byte is_hidden));
+
+#ifdef PNG_READ_APNG_SUPPORTED
+PNG_EXPORT(266, void, png_read_frame_head, (png_structp png_ptr,
+ png_infop info_ptr));
+#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
+PNG_EXPORT(267, void, png_set_progressive_frame_fn, (png_structp png_ptr,
+ png_progressive_frame_ptr frame_info_fn,
+ png_progressive_frame_ptr frame_end_fn));
+#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
+#endif /* PNG_READ_APNG_SUPPORTED */
+
+#ifdef PNG_WRITE_APNG_SUPPORTED
+PNG_EXPORT(268, void, png_write_frame_head, (png_structp png_ptr,
+ png_infop info_ptr, png_bytepp row_pointers,
+ png_uint_32 width, png_uint_32 height,
+ png_uint_32 x_offset, png_uint_32 y_offset,
+ png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op,
+ png_byte blend_op));
+
+PNG_EXPORT(269, void, png_write_frame_tail, (png_structp png_ptr,
+ png_infop info_ptr));
+#endif /* PNG_WRITE_APNG_SUPPORTED */
+#endif /* PNG_APNG_SUPPORTED */
/* Maintainer: Put new public prototypes here ^, in libpng.3, in project
* defs, and in scripts/symbols.def.
@@ -3266,7 +3326,11 @@ PNG_EXPORT(244, int, png_set_option, (png_structrp png_ptr, int option,
* one to use is one more than this.)
*/
#ifdef PNG_EXPORT_LAST_ORDINAL
+#ifdef PNG_APNG_SUPPORTED
+ PNG_EXPORT_LAST_ORDINAL(269);
+#else
PNG_EXPORT_LAST_ORDINAL(249);
+#endif /* PNG_APNG_SUPPORTED */
#endif
#ifdef __cplusplus
diff --git a/thirdparty/libpng/pngconf.h b/thirdparty/libpng/pngconf.h
index a4646bab85..927a769dbe 100644
--- a/thirdparty/libpng/pngconf.h
+++ b/thirdparty/libpng/pngconf.h
@@ -1,11 +1,12 @@
-/* pngconf.h - machine configurable file for libpng
+/* pngconf.h - machine-configurable file for libpng
*
- * libpng version 1.6.35, July 15, 2018
+ * libpng version 1.6.37
*
+ * Copyright (c) 2018-2019 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
@@ -57,14 +58,13 @@
#endif /* PNG_BUILDING_SYMBOL_TABLE */
-/* Prior to 1.6.0 it was possible to turn off 'const' in declarations using
- * PNG_NO_CONST; this is no longer supported except for data declarations which
- * apparently still cause problems in 2011 on some compilers.
+/* Prior to 1.6.0, it was possible to turn off 'const' in declarations,
+ * using PNG_NO_CONST. This is no longer supported.
*/
#define PNG_CONST const /* backward compatibility only */
-/* This controls optimization of the reading of 16-bit and 32-bit values
- * from PNG files. It can be set on a per-app-file basis - it
+/* This controls optimization of the reading of 16-bit and 32-bit
+ * values from PNG files. It can be set on a per-app-file basis: it
* just changes whether a macro is used when the function is called.
* The library builder sets the default; if read functions are not
* built into the library the macro implementation is forced on.
diff --git a/thirdparty/libpng/pngdebug.h b/thirdparty/libpng/pngdebug.h
index 15a7ed0c95..00d5a4569e 100644
--- a/thirdparty/libpng/pngdebug.h
+++ b/thirdparty/libpng/pngdebug.h
@@ -1,10 +1,10 @@
/* pngdebug.h - Debugging macros for libpng, also used in pngtest.c
*
- * Last changed in libpng 1.6.8 [December 19, 2013]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2013 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
diff --git a/thirdparty/libpng/pngerror.c b/thirdparty/libpng/pngerror.c
index ad48bfb986..ec3a709b9d 100644
--- a/thirdparty/libpng/pngerror.c
+++ b/thirdparty/libpng/pngerror.c
@@ -1,10 +1,10 @@
/* pngerror.c - stub functions for i/o and memory allocation
*
- * Last changed in libpng 1.6.31 [July 27, 2017]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
@@ -425,7 +425,7 @@ png_app_error(png_const_structrp png_ptr, png_const_charp error_message)
* if the character is invalid.
*/
#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
-static PNG_CONST char png_digit[16] = {
+static const char png_digit[16] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F'
};
@@ -885,7 +885,7 @@ PNG_FUNCTION(void /* PRIVATE */, (PNGCBAPI
png_safe_error),(png_structp png_nonconst_ptr, png_const_charp error_message),
PNG_NORETURN)
{
- const png_const_structrp png_ptr = png_nonconst_ptr;
+ png_const_structrp png_ptr = png_nonconst_ptr;
png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr);
/* An error is always logged here, overwriting anything (typically a warning)
@@ -920,7 +920,7 @@ png_safe_error),(png_structp png_nonconst_ptr, png_const_charp error_message),
void /* PRIVATE */ PNGCBAPI
png_safe_warning(png_structp png_nonconst_ptr, png_const_charp warning_message)
{
- const png_const_structrp png_ptr = png_nonconst_ptr;
+ png_const_structrp png_ptr = png_nonconst_ptr;
png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr);
/* A warning is only logged if there is no prior warning or error. */
diff --git a/thirdparty/libpng/pngget.c b/thirdparty/libpng/pngget.c
index 2325508f1d..9ed101aedc 100644
--- a/thirdparty/libpng/pngget.c
+++ b/thirdparty/libpng/pngget.c
@@ -1,10 +1,10 @@
/* pngget.c - retrieval of values from info struct
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
@@ -1246,4 +1246,166 @@ png_get_palette_max(png_const_structp png_ptr, png_const_infop info_ptr)
# endif
#endif
+#ifdef PNG_APNG_SUPPORTED
+png_uint_32 PNGAPI
+png_get_acTL(png_structp png_ptr, png_infop info_ptr,
+ png_uint_32 *num_frames, png_uint_32 *num_plays)
+{
+ png_debug1(1, "in %s retrieval function", "acTL");
+
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_acTL) &&
+ num_frames != NULL && num_plays != NULL)
+ {
+ *num_frames = info_ptr->num_frames;
+ *num_plays = info_ptr->num_plays;
+ return (1);
+ }
+
+ return (0);
+}
+
+png_uint_32 PNGAPI
+png_get_num_frames(png_structp png_ptr, png_infop info_ptr)
+{
+ png_debug(1, "in png_get_num_frames()");
+
+ if (png_ptr != NULL && info_ptr != NULL)
+ return (info_ptr->num_frames);
+ return (0);
+}
+
+png_uint_32 PNGAPI
+png_get_num_plays(png_structp png_ptr, png_infop info_ptr)
+{
+ png_debug(1, "in png_get_num_plays()");
+
+ if (png_ptr != NULL && info_ptr != NULL)
+ return (info_ptr->num_plays);
+ return (0);
+}
+
+png_uint_32 PNGAPI
+png_get_next_frame_fcTL(png_structp png_ptr, png_infop info_ptr,
+ png_uint_32 *width, png_uint_32 *height,
+ png_uint_32 *x_offset, png_uint_32 *y_offset,
+ png_uint_16 *delay_num, png_uint_16 *delay_den,
+ png_byte *dispose_op, png_byte *blend_op)
+{
+ png_debug1(1, "in %s retrieval function", "fcTL");
+
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_fcTL) &&
+ width != NULL && height != NULL &&
+ x_offset != NULL && y_offset != NULL &&
+ delay_num != NULL && delay_den != NULL &&
+ dispose_op != NULL && blend_op != NULL)
+ {
+ *width = info_ptr->next_frame_width;
+ *height = info_ptr->next_frame_height;
+ *x_offset = info_ptr->next_frame_x_offset;
+ *y_offset = info_ptr->next_frame_y_offset;
+ *delay_num = info_ptr->next_frame_delay_num;
+ *delay_den = info_ptr->next_frame_delay_den;
+ *dispose_op = info_ptr->next_frame_dispose_op;
+ *blend_op = info_ptr->next_frame_blend_op;
+ return (1);
+ }
+
+ return (0);
+}
+
+png_uint_32 PNGAPI
+png_get_next_frame_width(png_structp png_ptr, png_infop info_ptr)
+{
+ png_debug(1, "in png_get_next_frame_width()");
+
+ if (png_ptr != NULL && info_ptr != NULL)
+ return (info_ptr->next_frame_width);
+ return (0);
+}
+
+png_uint_32 PNGAPI
+png_get_next_frame_height(png_structp png_ptr, png_infop info_ptr)
+{
+ png_debug(1, "in png_get_next_frame_height()");
+
+ if (png_ptr != NULL && info_ptr != NULL)
+ return (info_ptr->next_frame_height);
+ return (0);
+}
+
+png_uint_32 PNGAPI
+png_get_next_frame_x_offset(png_structp png_ptr, png_infop info_ptr)
+{
+ png_debug(1, "in png_get_next_frame_x_offset()");
+
+ if (png_ptr != NULL && info_ptr != NULL)
+ return (info_ptr->next_frame_x_offset);
+ return (0);
+}
+
+png_uint_32 PNGAPI
+png_get_next_frame_y_offset(png_structp png_ptr, png_infop info_ptr)
+{
+ png_debug(1, "in png_get_next_frame_y_offset()");
+
+ if (png_ptr != NULL && info_ptr != NULL)
+ return (info_ptr->next_frame_y_offset);
+ return (0);
+}
+
+png_uint_16 PNGAPI
+png_get_next_frame_delay_num(png_structp png_ptr, png_infop info_ptr)
+{
+ png_debug(1, "in png_get_next_frame_delay_num()");
+
+ if (png_ptr != NULL && info_ptr != NULL)
+ return (info_ptr->next_frame_delay_num);
+ return (0);
+}
+
+png_uint_16 PNGAPI
+png_get_next_frame_delay_den(png_structp png_ptr, png_infop info_ptr)
+{
+ png_debug(1, "in png_get_next_frame_delay_den()");
+
+ if (png_ptr != NULL && info_ptr != NULL)
+ return (info_ptr->next_frame_delay_den);
+ return (0);
+}
+
+png_byte PNGAPI
+png_get_next_frame_dispose_op(png_structp png_ptr, png_infop info_ptr)
+{
+ png_debug(1, "in png_get_next_frame_dispose_op()");
+
+ if (png_ptr != NULL && info_ptr != NULL)
+ return (info_ptr->next_frame_dispose_op);
+ return (0);
+}
+
+png_byte PNGAPI
+png_get_next_frame_blend_op(png_structp png_ptr, png_infop info_ptr)
+{
+ png_debug(1, "in png_get_next_frame_blend_op()");
+
+ if (png_ptr != NULL && info_ptr != NULL)
+ return (info_ptr->next_frame_blend_op);
+ return (0);
+}
+
+png_byte PNGAPI
+png_get_first_frame_is_hidden(png_structp png_ptr, png_infop info_ptr)
+{
+ png_debug(1, "in png_first_frame_is_hidden()");
+
+ if (png_ptr != NULL)
+ return (png_byte)(png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN);
+
+ PNG_UNUSED(info_ptr)
+
+ return 0;
+}
+#endif /* PNG_APNG_SUPPORTED */
#endif /* READ || WRITE */
diff --git a/thirdparty/libpng/pnginfo.h b/thirdparty/libpng/pnginfo.h
index 2fcf868dac..ac7b269132 100644
--- a/thirdparty/libpng/pnginfo.h
+++ b/thirdparty/libpng/pnginfo.h
@@ -1,10 +1,10 @@
/* pnginfo.h - header file for PNG reference library
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2013,2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
@@ -263,5 +263,18 @@ defined(PNG_READ_BACKGROUND_SUPPORTED)
png_bytepp row_pointers; /* the image bits */
#endif
+#ifdef PNG_APNG_SUPPORTED
+ png_uint_32 num_frames; /* including default image */
+ png_uint_32 num_plays;
+ png_uint_32 next_frame_width;
+ png_uint_32 next_frame_height;
+ png_uint_32 next_frame_x_offset;
+ png_uint_32 next_frame_y_offset;
+ png_uint_16 next_frame_delay_num;
+ png_uint_16 next_frame_delay_den;
+ png_byte next_frame_dispose_op;
+ png_byte next_frame_blend_op;
+#endif
+
};
#endif /* PNGINFO_H */
diff --git a/thirdparty/libpng/pnglibconf.h b/thirdparty/libpng/pnglibconf.h
index 00acecc69b..e1e27e957e 100644
--- a/thirdparty/libpng/pnglibconf.h
+++ b/thirdparty/libpng/pnglibconf.h
@@ -1,10 +1,9 @@
-/* libpng 1.6.35 STANDARD API DEFINITION */
-
/* pnglibconf.h - library build configuration */
-/* Libpng version 1.6.35 - July 15, 2018 */
+/* libpng version 1.6.37 */
-/* Copyright (c) 1998-2018 Glenn Randers-Pehrson */
+/* Copyright (c) 2018-2019 Cosmin Truta */
+/* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson */
/* This code is released under the libpng license. */
/* For conditions of distribution and use, see the disclaimer */
@@ -20,8 +19,6 @@
#define PNG_ALIGNED_MEMORY_SUPPORTED
/*#undef PNG_ARM_NEON_API_SUPPORTED*/
/*#undef PNG_ARM_NEON_CHECK_SUPPORTED*/
-/*#undef PNG_POWERPC_VSX_API_SUPPORTED*/
-/*#undef PNG_POWERPC_VSX_CHECK_SUPPORTED*/
#define PNG_BENIGN_ERRORS_SUPPORTED
#define PNG_BENIGN_READ_ERRORS_SUPPORTED
/*#undef PNG_BENIGN_WRITE_ERRORS_SUPPORTED*/
@@ -46,6 +43,8 @@
#define PNG_IO_STATE_SUPPORTED
#define PNG_MNG_FEATURES_SUPPORTED
#define PNG_POINTER_INDEXING_SUPPORTED
+/*#undef PNG_POWERPC_VSX_API_SUPPORTED*/
+/*#undef PNG_POWERPC_VSX_CHECK_SUPPORTED*/
#define PNG_PROGRESSIVE_READ_SUPPORTED
#define PNG_READ_16BIT_SUPPORTED
#define PNG_READ_ALPHA_MODE_SUPPORTED
diff --git a/thirdparty/libpng/pngmem.c b/thirdparty/libpng/pngmem.c
index ff3ef7e88c..09ed9c1c99 100644
--- a/thirdparty/libpng/pngmem.c
+++ b/thirdparty/libpng/pngmem.c
@@ -1,10 +1,10 @@
/* pngmem.c - stub functions for memory allocation
*
- * Last changed in libpng 1.6.26 [October 20, 2016]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2014,2016 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
diff --git a/thirdparty/libpng/pngpread.c b/thirdparty/libpng/pngpread.c
index c4ba51c4d4..2eaeca08f7 100644
--- a/thirdparty/libpng/pngpread.c
+++ b/thirdparty/libpng/pngpread.c
@@ -1,10 +1,10 @@
/* pngpread.c - read a png file in push mode
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
@@ -195,6 +195,106 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
chunk_name = png_ptr->chunk_name;
+#ifdef PNG_READ_APNG_SUPPORTED
+ if (png_ptr->num_frames_read > 0 &&
+ png_ptr->num_frames_read < info_ptr->num_frames)
+ {
+ if (chunk_name == png_IDAT)
+ {
+ /* Discard trailing IDATs for the first frame */
+ if (png_ptr->mode & PNG_HAVE_fcTL || png_ptr->num_frames_read > 1)
+ png_error(png_ptr, "out of place IDAT");
+
+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+ {
+ png_push_save_buffer(png_ptr);
+ return;
+ }
+
+ png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
+ return;
+ }
+ else if (chunk_name == png_fdAT)
+ {
+ if (png_ptr->buffer_size < 4)
+ {
+ png_push_save_buffer(png_ptr);
+ return;
+ }
+
+ png_ensure_sequence_number(png_ptr, 4);
+
+ if (!(png_ptr->mode & PNG_HAVE_fcTL))
+ {
+ /* Discard trailing fdATs for frames other than the first */
+ if (png_ptr->num_frames_read < 2)
+ png_error(png_ptr, "out of place fdAT");
+
+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+ {
+ png_push_save_buffer(png_ptr);
+ return;
+ }
+
+ png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
+ return;
+ }
+
+ else
+ {
+ /* frame data follows */
+ png_ptr->idat_size = png_ptr->push_length - 4;
+ png_ptr->mode |= PNG_HAVE_IDAT;
+ png_ptr->process_mode = PNG_READ_IDAT_MODE;
+
+ return;
+ }
+ }
+
+ else if (chunk_name == png_fcTL)
+ {
+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+ {
+ png_push_save_buffer(png_ptr);
+ return;
+ }
+
+ png_read_reset(png_ptr);
+ png_ptr->mode &= ~PNG_HAVE_fcTL;
+
+ png_handle_fcTL(png_ptr, info_ptr, png_ptr->push_length);
+
+ if (!(png_ptr->mode & PNG_HAVE_fcTL))
+ png_error(png_ptr, "missing required fcTL chunk");
+
+ png_read_reinit(png_ptr, info_ptr);
+ png_progressive_read_reset(png_ptr);
+
+ if (png_ptr->frame_info_fn != NULL)
+ (*(png_ptr->frame_info_fn))(png_ptr, png_ptr->num_frames_read);
+
+ png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
+
+ return;
+ }
+
+ else
+ {
+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+ {
+ png_push_save_buffer(png_ptr);
+ return;
+ }
+ png_warning(png_ptr, "Skipped (ignored) a chunk "
+ "between APNG chunks");
+ png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
+ return;
+ }
+
+ return;
+ }
+#endif /* PNG_READ_APNG_SUPPORTED */
+
if (chunk_name == png_IDAT)
{
if ((png_ptr->mode & PNG_AFTER_IDAT) != 0)
@@ -261,6 +361,9 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
else if (chunk_name == png_IDAT)
{
+#ifdef PNG_READ_APNG_SUPPORTED
+ png_have_info(png_ptr, info_ptr);
+#endif
png_ptr->idat_size = png_ptr->push_length;
png_ptr->process_mode = PNG_READ_IDAT_MODE;
png_push_have_info(png_ptr, info_ptr);
@@ -406,6 +509,30 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
png_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length);
}
#endif
+#ifdef PNG_READ_APNG_SUPPORTED
+ else if (chunk_name == png_acTL)
+ {
+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+ {
+ png_push_save_buffer(png_ptr);
+ return;
+ }
+
+ png_handle_acTL(png_ptr, info_ptr, png_ptr->push_length);
+ }
+
+ else if (chunk_name == png_fcTL)
+ {
+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+ {
+ png_push_save_buffer(png_ptr);
+ return;
+ }
+
+ png_handle_fcTL(png_ptr, info_ptr, png_ptr->push_length);
+ }
+
+#endif /* PNG_READ_APNG_SUPPORTED */
else
{
@@ -539,7 +666,11 @@ png_push_read_IDAT(png_structrp png_ptr)
png_byte chunk_tag[4];
/* TODO: this code can be commoned up with the same code in push_read */
+#ifdef PNG_READ_APNG_SUPPORTED
+ PNG_PUSH_SAVE_BUFFER_IF_LT(12)
+#else
PNG_PUSH_SAVE_BUFFER_IF_LT(8)
+#endif
png_push_fill_buffer(png_ptr, chunk_length, 4);
png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
png_reset_crc(png_ptr);
@@ -547,17 +678,64 @@ png_push_read_IDAT(png_structrp png_ptr)
png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag);
png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
+#ifdef PNG_READ_APNG_SUPPORTED
+ if (png_ptr->chunk_name != png_fdAT && png_ptr->num_frames_read > 0)
+ {
+ if (png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED)
+ {
+ png_ptr->process_mode = PNG_READ_CHUNK_MODE;
+ if (png_ptr->frame_end_fn != NULL)
+ (*(png_ptr->frame_end_fn))(png_ptr, png_ptr->num_frames_read);
+ png_ptr->num_frames_read++;
+ return;
+ }
+ else
+ {
+ if (png_ptr->chunk_name == png_IEND)
+ png_error(png_ptr, "Not enough image data");
+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+ {
+ png_push_save_buffer(png_ptr);
+ return;
+ }
+ png_warning(png_ptr, "Skipping (ignoring) a chunk between "
+ "APNG chunks");
+ png_crc_finish(png_ptr, png_ptr->push_length);
+ png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
+ return;
+ }
+ }
+ else
+#endif
+#ifdef PNG_READ_APNG_SUPPORTED
+ if (png_ptr->chunk_name != png_IDAT && png_ptr->num_frames_read == 0)
+#else
if (png_ptr->chunk_name != png_IDAT)
+#endif
{
png_ptr->process_mode = PNG_READ_CHUNK_MODE;
if ((png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) == 0)
png_error(png_ptr, "Not enough compressed data");
+#ifdef PNG_READ_APNG_SUPPORTED
+ if (png_ptr->frame_end_fn != NULL)
+ (*(png_ptr->frame_end_fn))(png_ptr, png_ptr->num_frames_read);
+ png_ptr->num_frames_read++;
+#endif
+
return;
}
png_ptr->idat_size = png_ptr->push_length;
+
+#ifdef PNG_READ_APNG_SUPPORTED
+ if (png_ptr->num_frames_read > 0)
+ {
+ png_ensure_sequence_number(png_ptr, 4);
+ png_ptr->idat_size -= 4;
+ }
+#endif
}
if (png_ptr->idat_size != 0 && png_ptr->save_buffer_size != 0)
@@ -631,6 +809,15 @@ png_process_IDAT_data(png_structrp png_ptr, png_bytep buffer,
if (!(buffer_length > 0) || buffer == NULL)
png_error(png_ptr, "No IDAT data (internal error)");
+#ifdef PNG_READ_APNG_SUPPORTED
+ /* If the app is not APNG-aware, decode only the first frame */
+ if (!(png_ptr->apng_flags & PNG_APNG_APP) && png_ptr->num_frames_read > 0)
+ {
+ png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
+ return;
+ }
+#endif
+
/* This routine must process all the data it has been given
* before returning, calling the row callback as required to
* handle the uncompressed results.
@@ -972,20 +1159,20 @@ png_read_push_finish_row(png_structrp png_ptr)
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Start of interlace block */
- static PNG_CONST png_byte png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
+ static const png_byte png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
/* Offset to next interlace block */
- static PNG_CONST png_byte png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
+ static const png_byte png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
/* Start of interlace block in the y direction */
- static PNG_CONST png_byte png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
+ static const png_byte png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
/* Offset to next interlace block in the y direction */
- static PNG_CONST png_byte png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
+ static const png_byte png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
/* Height of interlace block. This is not currently used - if you need
* it, uncomment it here and in png.h
- static PNG_CONST png_byte png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
+ static const png_byte png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
*/
#endif
@@ -1085,6 +1272,18 @@ png_set_progressive_read_fn(png_structrp png_ptr, png_voidp progressive_ptr,
png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer);
}
+#ifdef PNG_READ_APNG_SUPPORTED
+void PNGAPI
+png_set_progressive_frame_fn(png_structp png_ptr,
+ png_progressive_frame_ptr frame_info_fn,
+ png_progressive_frame_ptr frame_end_fn)
+{
+ png_ptr->frame_info_fn = frame_info_fn;
+ png_ptr->frame_end_fn = frame_end_fn;
+ png_ptr->apng_flags |= PNG_APNG_APP;
+}
+#endif
+
png_voidp PNGAPI
png_get_progressive_ptr(png_const_structrp png_ptr)
{
diff --git a/thirdparty/libpng/pngpriv.h b/thirdparty/libpng/pngpriv.h
index 3581f67919..57e1bf989b 100644
--- a/thirdparty/libpng/pngpriv.h
+++ b/thirdparty/libpng/pngpriv.h
@@ -1,10 +1,10 @@
/* pngpriv.h - private declarations for use inside libpng
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018-2019 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
@@ -174,7 +174,10 @@
# else /* !defined __ARM_NEON__ */
/* The 'intrinsics' code simply won't compile without this -mfpu=neon:
*/
-# define PNG_ARM_NEON_IMPLEMENTATION 2
+# if !defined(__aarch64__)
+ /* The assembler code currently does not work on ARM64 */
+# define PNG_ARM_NEON_IMPLEMENTATION 2
+# endif /* __aarch64__ */
# endif /* __ARM_NEON__ */
# endif /* !PNG_ARM_NEON_IMPLEMENTATION */
@@ -634,6 +637,10 @@
#define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000U /* Have another chunk after IDAT */
/* 0x4000U (unused) */
#define PNG_IS_READ_STRUCT 0x8000U /* Else is a write struct */
+#ifdef PNG_APNG_SUPPORTED
+#define PNG_HAVE_acTL 0x10000U
+#define PNG_HAVE_fcTL 0x20000U
+#endif
/* Flags for the transformations the PNG library does on the image data */
#define PNG_BGR 0x0001U
@@ -870,6 +877,16 @@
#define png_tRNS PNG_U32(116, 82, 78, 83)
#define png_zTXt PNG_U32(122, 84, 88, 116)
+#ifdef PNG_APNG_SUPPORTED
+#define png_acTL PNG_U32( 97, 99, 84, 76)
+#define png_fcTL PNG_U32(102, 99, 84, 76)
+#define png_fdAT PNG_U32(102, 100, 65, 84)
+
+/* For png_struct.apng_flags: */
+#define PNG_FIRST_FRAME_HIDDEN 0x0001U
+#define PNG_APNG_APP 0x0002U
+#endif
+
/* The following will work on (signed char*) strings, whereas the get_uint_32
* macro will fail on top-bit-set values because of the sign extension.
*/
@@ -1534,10 +1551,10 @@ PNG_INTERNAL_FUNCTION(void,png_handle_zTXt,(png_structrp png_ptr,
#endif
PNG_INTERNAL_FUNCTION(void,png_check_chunk_name,(png_const_structrp png_ptr,
- const png_uint_32 chunk_name),PNG_EMPTY);
+ png_uint_32 chunk_name),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_check_chunk_length,(png_const_structrp png_ptr,
- const png_uint_32 chunk_length),PNG_EMPTY);
+ png_uint_32 chunk_length),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_handle_unknown,(png_structrp png_ptr,
png_inforp info_ptr, png_uint_32 length, int keep),PNG_EMPTY);
@@ -1641,6 +1658,47 @@ PNG_INTERNAL_FUNCTION(void,png_colorspace_sync,(png_const_structrp png_ptr,
*/
#endif
+#ifdef PNG_APNG_SUPPORTED
+PNG_INTERNAL_FUNCTION(void,png_ensure_fcTL_is_valid,(png_structp png_ptr,
+ png_uint_32 width, png_uint_32 height,
+ png_uint_32 x_offset, png_uint_32 y_offset,
+ png_uint_16 delay_num, png_uint_16 delay_den,
+ png_byte dispose_op, png_byte blend_op), PNG_EMPTY);
+
+#ifdef PNG_READ_APNG_SUPPORTED
+PNG_INTERNAL_FUNCTION(void,png_handle_acTL,(png_structp png_ptr, png_infop info_ptr,
+ png_uint_32 length),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_handle_fcTL,(png_structp png_ptr, png_infop info_ptr,
+ png_uint_32 length),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_handle_fdAT,(png_structp png_ptr, png_infop info_ptr,
+ png_uint_32 length),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_have_info,(png_structp png_ptr, png_infop info_ptr),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_ensure_sequence_number,(png_structp png_ptr,
+ png_uint_32 length),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_reset,(png_structp png_ptr),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_reinit,(png_structp png_ptr,
+ png_infop info_ptr),PNG_EMPTY);
+#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
+PNG_INTERNAL_FUNCTION(void,png_progressive_read_reset,(png_structp png_ptr),PNG_EMPTY);
+#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
+#endif /* PNG_READ_APNG_SUPPORTED */
+
+#ifdef PNG_WRITE_APNG_SUPPORTED
+PNG_INTERNAL_FUNCTION(void,png_write_acTL,(png_structp png_ptr,
+ png_uint_32 num_frames, png_uint_32 num_plays),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_write_fcTL,(png_structp png_ptr,
+ png_uint_32 width, png_uint_32 height,
+ png_uint_32 x_offset, png_uint_32 y_offset,
+ png_uint_16 delay_num, png_uint_16 delay_den,
+ png_byte dispose_op, png_byte blend_op),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_write_fdAT,(png_structp png_ptr,
+ png_const_bytep data, png_size_t length),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_write_reset,(png_structp png_ptr),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_write_reinit,(png_structp png_ptr,
+ png_infop info_ptr, png_uint_32 width, png_uint_32 height),PNG_EMPTY);
+#endif /* PNG_WRITE_APNG_SUPPORTED */
+#endif /* PNG_APNG_SUPPORTED */
+
/* Added at libpng version 1.4.0 */
#ifdef PNG_COLORSPACE_SUPPORTED
/* These internal functions are for maintaining the colorspace structure within
@@ -2114,6 +2172,29 @@ PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_sse2,
PNG_INTERNAL_FUNCTION(png_uint_32, png_check_keyword, (png_structrp png_ptr,
png_const_charp key, png_bytep new_key), PNG_EMPTY);
+#if PNG_ARM_NEON_IMPLEMENTATION == 1
+PNG_INTERNAL_FUNCTION(void,
+ png_riffle_palette_neon,
+ (png_structrp),
+ PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(int,
+ png_do_expand_palette_rgba8_neon,
+ (png_structrp,
+ png_row_infop,
+ png_const_bytep,
+ const png_bytepp,
+ const png_bytepp),
+ PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(int,
+ png_do_expand_palette_rgb8_neon,
+ (png_structrp,
+ png_row_infop,
+ png_const_bytep,
+ const png_bytepp,
+ const png_bytepp),
+ PNG_EMPTY);
+#endif
+
/* Maintainer: Put new private prototypes here ^ */
#include "pngdebug.h"
diff --git a/thirdparty/libpng/pngread.c b/thirdparty/libpng/pngread.c
index bff7503ee3..fa44d5a8e4 100644
--- a/thirdparty/libpng/pngread.c
+++ b/thirdparty/libpng/pngread.c
@@ -1,10 +1,10 @@
/* pngread.c - read a PNG file
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018-2019 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
@@ -161,6 +161,9 @@ png_read_info(png_structrp png_ptr, png_inforp info_ptr)
else if (chunk_name == png_IDAT)
{
+#ifdef PNG_READ_APNG_SUPPORTED
+ png_have_info(png_ptr, info_ptr);
+#endif
png_ptr->idat_size = length;
break;
}
@@ -255,6 +258,17 @@ png_read_info(png_structrp png_ptr, png_inforp info_ptr)
png_handle_iTXt(png_ptr, info_ptr, length);
#endif
+#ifdef PNG_READ_APNG_SUPPORTED
+ else if (chunk_name == png_acTL)
+ png_handle_acTL(png_ptr, info_ptr, length);
+
+ else if (chunk_name == png_fcTL)
+ png_handle_fcTL(png_ptr, info_ptr, length);
+
+ else if (chunk_name == png_fdAT)
+ png_handle_fdAT(png_ptr, info_ptr, length);
+#endif
+
else
png_handle_unknown(png_ptr, info_ptr, length,
PNG_HANDLE_CHUNK_AS_DEFAULT);
@@ -262,6 +276,72 @@ png_read_info(png_structrp png_ptr, png_inforp info_ptr)
}
#endif /* SEQUENTIAL_READ */
+#ifdef PNG_READ_APNG_SUPPORTED
+void PNGAPI
+png_read_frame_head(png_structp png_ptr, png_infop info_ptr)
+{
+ png_byte have_chunk_after_DAT; /* after IDAT or after fdAT */
+
+ png_debug(0, "Reading frame head");
+
+ if (!(png_ptr->mode & PNG_HAVE_acTL))
+ png_error(png_ptr, "attempt to png_read_frame_head() but "
+ "no acTL present");
+
+ /* do nothing for the main IDAT */
+ if (png_ptr->num_frames_read == 0)
+ return;
+
+ png_read_reset(png_ptr);
+ png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
+ png_ptr->mode &= ~PNG_HAVE_fcTL;
+
+ have_chunk_after_DAT = 0;
+ for (;;)
+ {
+ png_uint_32 length = png_read_chunk_header(png_ptr);
+
+ if (png_ptr->chunk_name == png_IDAT)
+ {
+ /* discard trailing IDATs for the first frame */
+ if (have_chunk_after_DAT || png_ptr->num_frames_read > 1)
+ png_error(png_ptr, "png_read_frame_head(): out of place IDAT");
+ png_crc_finish(png_ptr, length);
+ }
+
+ else if (png_ptr->chunk_name == png_fcTL)
+ {
+ png_handle_fcTL(png_ptr, info_ptr, length);
+ have_chunk_after_DAT = 1;
+ }
+
+ else if (png_ptr->chunk_name == png_fdAT)
+ {
+ png_ensure_sequence_number(png_ptr, length);
+
+ /* discard trailing fdATs for frames other than the first */
+ if (!have_chunk_after_DAT && png_ptr->num_frames_read > 1)
+ png_crc_finish(png_ptr, length - 4);
+ else if(png_ptr->mode & PNG_HAVE_fcTL)
+ {
+ png_ptr->idat_size = length - 4;
+ png_ptr->mode |= PNG_HAVE_IDAT;
+
+ break;
+ }
+ else
+ png_error(png_ptr, "png_read_frame_head(): out of place fdAT");
+ }
+ else
+ {
+ png_warning(png_ptr, "Skipped (ignored) a chunk "
+ "between APNG chunks");
+ png_crc_finish(png_ptr, length);
+ }
+ }
+}
+#endif /* PNG_READ_APNG_SUPPORTED */
+
/* Optional call to update the users info_ptr structure */
void PNGAPI
png_read_update_info(png_structrp png_ptr, png_inforp info_ptr)
@@ -994,6 +1074,12 @@ png_read_destroy(png_structrp png_ptr)
png_ptr->chunk_list = NULL;
#endif
+#if defined(PNG_READ_EXPAND_SUPPORTED) && \
+ defined(PNG_ARM_NEON_IMPLEMENTATION)
+ png_free(png_ptr, png_ptr->riffled_palette);
+ png_ptr->riffled_palette = NULL;
+#endif
+
/* NOTE: the 'setjmp' buffer may still be allocated and the memory and error
* callbacks are still set at this point. They are required to complete the
* destruction of the png_struct itself.
@@ -1621,7 +1707,7 @@ png_image_skip_unused_chunks(png_structrp png_ptr)
* errors (which are unfortunately quite common.)
*/
{
- static PNG_CONST png_byte chunks_to_process[] = {
+ static const png_byte chunks_to_process[] = {
98, 75, 71, 68, '\0', /* bKGD */
99, 72, 82, 77, '\0', /* cHRM */
103, 65, 77, 65, '\0', /* gAMA */
@@ -1758,9 +1844,9 @@ png_create_colormap_entry(png_image_read_control *display,
png_uint_32 alpha, int encoding)
{
png_imagep image = display->image;
- const int output_encoding = (image->format & PNG_FORMAT_FLAG_LINEAR) != 0 ?
+ int output_encoding = (image->format & PNG_FORMAT_FLAG_LINEAR) != 0 ?
P_LINEAR : P_sRGB;
- const int convert_to_Y = (image->format & PNG_FORMAT_FLAG_COLOR) == 0 &&
+ int convert_to_Y = (image->format & PNG_FORMAT_FLAG_COLOR) == 0 &&
(red != green || green != blue);
if (ip > 255)
@@ -1869,13 +1955,13 @@ png_create_colormap_entry(png_image_read_control *display,
/* Store the value. */
{
# ifdef PNG_FORMAT_AFIRST_SUPPORTED
- const int afirst = (image->format & PNG_FORMAT_FLAG_AFIRST) != 0 &&
+ int afirst = (image->format & PNG_FORMAT_FLAG_AFIRST) != 0 &&
(image->format & PNG_FORMAT_FLAG_ALPHA) != 0;
# else
# define afirst 0
# endif
# ifdef PNG_FORMAT_BGR_SUPPORTED
- const int bgr = (image->format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0;
+ int bgr = (image->format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0;
# else
# define bgr 0
# endif
@@ -2085,11 +2171,11 @@ png_image_read_colormap(png_voidp argument)
{
png_image_read_control *display =
png_voidcast(png_image_read_control*, argument);
- const png_imagep image = display->image;
+ png_imagep image = display->image;
- const png_structrp png_ptr = image->opaque->png_ptr;
- const png_uint_32 output_format = image->format;
- const int output_encoding = (output_format & PNG_FORMAT_FLAG_LINEAR) != 0 ?
+ png_structrp png_ptr = image->opaque->png_ptr;
+ png_uint_32 output_format = image->format;
+ int output_encoding = (output_format & PNG_FORMAT_FLAG_LINEAR) != 0 ?
P_LINEAR : P_sRGB;
unsigned int cmap_entries;
@@ -2802,7 +2888,7 @@ png_image_read_colormap(png_voidp argument)
unsigned int num_trans = png_ptr->num_trans;
png_const_bytep trans = num_trans > 0 ? png_ptr->trans_alpha : NULL;
png_const_colorp colormap = png_ptr->palette;
- const int do_background = trans != NULL &&
+ int do_background = trans != NULL &&
(output_format & PNG_FORMAT_FLAG_ALPHA) == 0;
unsigned int i;
@@ -3946,7 +4032,7 @@ png_image_read_direct(png_voidp argument)
*/
if (linear != 0)
{
- PNG_CONST png_uint_16 le = 0x0001;
+ png_uint_16 le = 0x0001;
if ((*(png_const_bytep) & le) != 0)
png_set_swap(png_ptr);
@@ -4108,7 +4194,7 @@ png_image_finish_read(png_imagep image, png_const_colorp background,
* original PNG format because it may not occur in the output PNG format
* and libpng deals with the issues of reading the original.
*/
- const unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format);
+ unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format);
/* The following checks just the 'row_stride' calculation to ensure it
* fits in a signed 32-bit value. Because channels/components can be
@@ -4119,7 +4205,7 @@ png_image_finish_read(png_imagep image, png_const_colorp background,
if (image->width <= 0x7fffffffU/channels) /* no overflow */
{
png_uint_32 check;
- const png_uint_32 png_row_stride = image->width * channels;
+ png_uint_32 png_row_stride = image->width * channels;
if (row_stride == 0)
row_stride = (png_int_32)/*SAFE*/png_row_stride;
diff --git a/thirdparty/libpng/pngrio.c b/thirdparty/libpng/pngrio.c
index 372221483f..7946358101 100644
--- a/thirdparty/libpng/pngrio.c
+++ b/thirdparty/libpng/pngrio.c
@@ -1,10 +1,10 @@
/* pngrio.c - functions for data input
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
diff --git a/thirdparty/libpng/pngrtran.c b/thirdparty/libpng/pngrtran.c
index 67d1f249a6..9a8fad9f4a 100644
--- a/thirdparty/libpng/pngrtran.c
+++ b/thirdparty/libpng/pngrtran.c
@@ -1,10 +1,10 @@
/* pngrtran.c - transforms the data in a row for PNG readers
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018-2019 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
@@ -18,6 +18,17 @@
#include "pngpriv.h"
+#ifdef PNG_ARM_NEON_IMPLEMENTATION
+# if PNG_ARM_NEON_IMPLEMENTATION == 1
+# define PNG_ARM_NEON_INTRINSICS_AVAILABLE
+# if defined(_MSC_VER) && defined(_M_ARM64)
+# include <arm64_neon.h>
+# else
+# include <arm_neon.h>
+# endif
+# endif
+#endif
+
#ifdef PNG_READ_SUPPORTED
/* Set the action on getting a CRC error for an ancillary or critical chunk. */
@@ -1171,20 +1182,20 @@ png_init_palette_transformations(png_structrp png_ptr)
png_ptr->palette[png_ptr->background.index].blue;
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
- if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
- {
- if ((png_ptr->transformations & PNG_EXPAND_tRNS) == 0)
- {
- /* Invert the alpha channel (in tRNS) unless the pixels are
- * going to be expanded, in which case leave it for later
- */
- int i, istop = png_ptr->num_trans;
-
- for (i=0; i<istop; i++)
- png_ptr->trans_alpha[i] = (png_byte)(255 -
- png_ptr->trans_alpha[i]);
- }
- }
+ if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
+ {
+ if ((png_ptr->transformations & PNG_EXPAND_tRNS) == 0)
+ {
+ /* Invert the alpha channel (in tRNS) unless the pixels are
+ * going to be expanded, in which case leave it for later
+ */
+ int i, istop = png_ptr->num_trans;
+
+ for (i = 0; i < istop; i++)
+ png_ptr->trans_alpha[i] =
+ (png_byte)(255 - png_ptr->trans_alpha[i]);
+ }
+ }
#endif /* READ_INVERT_ALPHA */
}
} /* background expand and (therefore) no alpha association. */
@@ -2986,7 +2997,6 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
*/
static int
png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row)
-
{
int rgb_error = 0;
@@ -2995,12 +3005,11 @@ png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row)
if ((row_info->color_type & PNG_COLOR_MASK_PALETTE) == 0 &&
(row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
{
- PNG_CONST png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
- PNG_CONST png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
- PNG_CONST png_uint_32 bc = 32768 - rc - gc;
- PNG_CONST png_uint_32 row_width = row_info->width;
- PNG_CONST int have_alpha =
- (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0;
+ png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
+ png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
+ png_uint_32 bc = 32768 - rc - gc;
+ png_uint_32 row_width = row_info->width;
+ int have_alpha = (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0;
if (row_info->bit_depth == 8)
{
@@ -4143,12 +4152,11 @@ png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
{
if (row_info->bit_depth == 8)
{
- PNG_CONST png_bytep table = png_ptr->gamma_from_1;
+ png_bytep table = png_ptr->gamma_from_1;
if (table != NULL)
{
- PNG_CONST int step =
- (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 4 : 2;
+ int step = (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 4 : 2;
/* The alpha channel is the last component: */
row += step - 1;
@@ -4162,13 +4170,12 @@ png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
else if (row_info->bit_depth == 16)
{
- PNG_CONST png_uint_16pp table = png_ptr->gamma_16_from_1;
- PNG_CONST int gamma_shift = png_ptr->gamma_shift;
+ png_uint_16pp table = png_ptr->gamma_16_from_1;
+ int gamma_shift = png_ptr->gamma_shift;
if (table != NULL)
{
- PNG_CONST int step =
- (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 8 : 4;
+ int step = (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 8 : 4;
/* The alpha channel is the last component: */
row += step - 2;
@@ -4199,8 +4206,9 @@ png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
* upon whether you supply trans and num_trans.
*/
static void
-png_do_expand_palette(png_row_infop row_info, png_bytep row,
- png_const_colorp palette, png_const_bytep trans_alpha, int num_trans)
+png_do_expand_palette(png_structrp png_ptr, png_row_infop row_info,
+ png_bytep row, png_const_colorp palette, png_const_bytep trans_alpha,
+ int num_trans)
{
int shift, value;
png_bytep sp, dp;
@@ -4304,14 +4312,27 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row,
sp = row + (size_t)row_width - 1;
dp = row + ((size_t)row_width << 2) - 1;
- for (i = 0; i < row_width; i++)
+ i = 0;
+#ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE
+ if (png_ptr->riffled_palette != NULL)
+ {
+ /* The RGBA optimization works with png_ptr->bit_depth == 8
+ * but sometimes row_info->bit_depth has been changed to 8.
+ * In these cases, the palette hasn't been riffled.
+ */
+ i = png_do_expand_palette_rgba8_neon(png_ptr, row_info, row,
+ &sp, &dp);
+ }
+#else
+ PNG_UNUSED(png_ptr)
+#endif
+
+ for (; i < row_width; i++)
{
if ((int)(*sp) >= num_trans)
*dp-- = 0xff;
-
else
*dp-- = trans_alpha[*sp];
-
*dp-- = palette[*sp].blue;
*dp-- = palette[*sp].green;
*dp-- = palette[*sp].red;
@@ -4328,8 +4349,15 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row,
{
sp = row + (size_t)row_width - 1;
dp = row + (size_t)(row_width * 3) - 1;
+ i = 0;
+#ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE
+ i = png_do_expand_palette_rgb8_neon(png_ptr, row_info, row,
+ &sp, &dp);
+#else
+ PNG_UNUSED(png_ptr)
+#endif
- for (i = 0; i < row_width; i++)
+ for (; i < row_width; i++)
{
*dp-- = palette[*sp].blue;
*dp-- = palette[*sp].green;
@@ -4743,7 +4771,19 @@ png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info)
{
if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
{
- png_do_expand_palette(row_info, png_ptr->row_buf + 1,
+#ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE
+ if ((png_ptr->num_trans > 0) && (png_ptr->bit_depth == 8))
+ {
+ if (png_ptr->riffled_palette == NULL)
+ {
+ /* Initialize the accelerated palette expansion. */
+ png_ptr->riffled_palette =
+ (png_bytep)png_malloc(png_ptr, 256 * 4);
+ png_riffle_palette_neon(png_ptr);
+ }
+ }
+#endif
+ png_do_expand_palette(png_ptr, row_info, png_ptr->row_buf + 1,
png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans);
}
diff --git a/thirdparty/libpng/pngrutil.c b/thirdparty/libpng/pngrutil.c
index 7001f1976e..ae66a48a83 100644
--- a/thirdparty/libpng/pngrutil.c
+++ b/thirdparty/libpng/pngrutil.c
@@ -1,10 +1,10 @@
/* pngrutil.c - utilities to read a PNG file
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
@@ -865,6 +865,11 @@ png_handle_IHDR(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
filter_type = buf[11];
interlace_type = buf[12];
+#ifdef PNG_READ_APNG_SUPPORTED
+ png_ptr->first_frame_width = width;
+ png_ptr->first_frame_height = height;
+#endif
+
/* Set internal variables */
png_ptr->width = width;
png_ptr->height = height;
@@ -1461,8 +1466,7 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
/* We have the ICC profile header; do the basic header checks.
*/
- const png_uint_32 profile_length =
- png_get_uint_32(profile_header);
+ png_uint_32 profile_length = png_get_uint_32(profile_header);
if (png_icc_check_length(png_ptr, &png_ptr->colorspace,
keyword, profile_length) != 0)
@@ -1479,8 +1483,8 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
* profile. The header check has already validated
* that none of this stuff will overflow.
*/
- const png_uint_32 tag_count = png_get_uint_32(
- profile_header+128);
+ png_uint_32 tag_count =
+ png_get_uint_32(profile_header + 128);
png_bytep profile = png_read_buffer(png_ptr,
profile_length, 2/*silent*/);
@@ -2858,6 +2862,179 @@ png_handle_iTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
}
#endif
+#ifdef PNG_READ_APNG_SUPPORTED
+void /* PRIVATE */
+png_handle_acTL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+ png_byte data[8];
+ png_uint_32 num_frames;
+ png_uint_32 num_plays;
+ png_uint_32 didSet;
+
+ png_debug(1, "in png_handle_acTL");
+
+ if (!(png_ptr->mode & PNG_HAVE_IHDR))
+ {
+ png_error(png_ptr, "Missing IHDR before acTL");
+ }
+ else if (png_ptr->mode & PNG_HAVE_IDAT)
+ {
+ png_warning(png_ptr, "Invalid acTL after IDAT skipped");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+ else if (png_ptr->mode & PNG_HAVE_acTL)
+ {
+ png_warning(png_ptr, "Duplicate acTL skipped");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+ else if (length != 8)
+ {
+ png_warning(png_ptr, "acTL with invalid length skipped");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+
+ png_crc_read(png_ptr, data, 8);
+ png_crc_finish(png_ptr, 0);
+
+ num_frames = png_get_uint_31(png_ptr, data);
+ num_plays = png_get_uint_31(png_ptr, data + 4);
+
+ /* the set function will do error checking on num_frames */
+ didSet = png_set_acTL(png_ptr, info_ptr, num_frames, num_plays);
+ if(didSet)
+ png_ptr->mode |= PNG_HAVE_acTL;
+}
+
+void /* PRIVATE */
+png_handle_fcTL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+ png_byte data[22];
+ png_uint_32 width;
+ png_uint_32 height;
+ png_uint_32 x_offset;
+ png_uint_32 y_offset;
+ png_uint_16 delay_num;
+ png_uint_16 delay_den;
+ png_byte dispose_op;
+ png_byte blend_op;
+
+ png_debug(1, "in png_handle_fcTL");
+
+ png_ensure_sequence_number(png_ptr, length);
+
+ if (!(png_ptr->mode & PNG_HAVE_IHDR))
+ {
+ png_error(png_ptr, "Missing IHDR before fcTL");
+ }
+ else if (png_ptr->mode & PNG_HAVE_IDAT)
+ {
+ /* for any frames other then the first this message may be misleading,
+ * but correct. PNG_HAVE_IDAT is unset before the frame head is read
+ * i can't think of a better message */
+ png_warning(png_ptr, "Invalid fcTL after IDAT skipped");
+ png_crc_finish(png_ptr, length-4);
+ return;
+ }
+ else if (png_ptr->mode & PNG_HAVE_fcTL)
+ {
+ png_warning(png_ptr, "Duplicate fcTL within one frame skipped");
+ png_crc_finish(png_ptr, length-4);
+ return;
+ }
+ else if (length != 26)
+ {
+ png_warning(png_ptr, "fcTL with invalid length skipped");
+ png_crc_finish(png_ptr, length-4);
+ return;
+ }
+
+ png_crc_read(png_ptr, data, 22);
+ png_crc_finish(png_ptr, 0);
+
+ width = png_get_uint_31(png_ptr, data);
+ height = png_get_uint_31(png_ptr, data + 4);
+ x_offset = png_get_uint_31(png_ptr, data + 8);
+ y_offset = png_get_uint_31(png_ptr, data + 12);
+ delay_num = png_get_uint_16(data + 16);
+ delay_den = png_get_uint_16(data + 18);
+ dispose_op = data[20];
+ blend_op = data[21];
+
+ if (png_ptr->num_frames_read == 0 && (x_offset != 0 || y_offset != 0))
+ {
+ png_warning(png_ptr, "fcTL for the first frame must have zero offset");
+ return;
+ }
+
+ if (info_ptr != NULL)
+ {
+ if (png_ptr->num_frames_read == 0 &&
+ (width != info_ptr->width || height != info_ptr->height))
+ {
+ png_warning(png_ptr, "size in first frame's fcTL must match "
+ "the size in IHDR");
+ return;
+ }
+
+ /* The set function will do more error checking */
+ png_set_next_frame_fcTL(png_ptr, info_ptr, width, height,
+ x_offset, y_offset, delay_num, delay_den,
+ dispose_op, blend_op);
+
+ png_read_reinit(png_ptr, info_ptr);
+
+ png_ptr->mode |= PNG_HAVE_fcTL;
+ }
+}
+
+void /* PRIVATE */
+png_have_info(png_structp png_ptr, png_infop info_ptr)
+{
+ if((info_ptr->valid & PNG_INFO_acTL) && !(info_ptr->valid & PNG_INFO_fcTL))
+ {
+ png_ptr->apng_flags |= PNG_FIRST_FRAME_HIDDEN;
+ info_ptr->num_frames++;
+ }
+}
+
+void /* PRIVATE */
+png_handle_fdAT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+ png_ensure_sequence_number(png_ptr, length);
+
+ /* This function is only called from png_read_end(), png_read_info(),
+ * and png_push_read_chunk() which means that:
+ * - the user doesn't want to read this frame
+ * - or this is an out-of-place fdAT
+ * in either case it is safe to ignore the chunk with a warning */
+ png_warning(png_ptr, "ignoring fdAT chunk");
+ png_crc_finish(png_ptr, length - 4);
+ PNG_UNUSED(info_ptr)
+}
+
+void /* PRIVATE */
+png_ensure_sequence_number(png_structp png_ptr, png_uint_32 length)
+{
+ png_byte data[4];
+ png_uint_32 sequence_number;
+
+ if (length < 4)
+ png_error(png_ptr, "invalid fcTL or fdAT chunk found");
+
+ png_crc_read(png_ptr, data, 4);
+ sequence_number = png_get_uint_31(png_ptr, data);
+
+ if (sequence_number != png_ptr->next_seq_num)
+ png_error(png_ptr, "fcTL or fdAT chunk with out-of-order sequence "
+ "number found");
+
+ png_ptr->next_seq_num++;
+}
+#endif /* PNG_READ_APNG_SUPPORTED */
+
#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
/* Utility function for png_handle_unknown; set up png_ptr::unknown_chunk */
static int
@@ -3132,7 +3309,7 @@ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr,
*/
void /* PRIVATE */
-png_check_chunk_name(png_const_structrp png_ptr, const png_uint_32 chunk_name)
+png_check_chunk_name(png_const_structrp png_ptr, png_uint_32 chunk_name)
{
int i;
png_uint_32 cn=chunk_name;
@@ -3151,7 +3328,7 @@ png_check_chunk_name(png_const_structrp png_ptr, const png_uint_32 chunk_name)
}
void /* PRIVATE */
-png_check_chunk_length(png_const_structrp png_ptr, const png_uint_32 length)
+png_check_chunk_length(png_const_structrp png_ptr, png_uint_32 length)
{
png_alloc_size_t limit = PNG_UINT_31_MAX;
@@ -3363,7 +3540,7 @@ png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display)
/* Hence the pre-compiled masks indexed by PACKSWAP (or not), depth and
* then pass:
*/
- static PNG_CONST png_uint_32 row_mask[2/*PACKSWAP*/][3/*depth*/][6] =
+ static const png_uint_32 row_mask[2/*PACKSWAP*/][3/*depth*/][6] =
{
/* Little-endian byte masks for PACKSWAP */
{ S_MASKS(1,0), S_MASKS(2,0), S_MASKS(4,0) },
@@ -3374,7 +3551,7 @@ png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display)
/* display_mask has only three entries for the odd passes, so index by
* pass>>1.
*/
- static PNG_CONST png_uint_32 display_mask[2][3][3] =
+ static const png_uint_32 display_mask[2][3][3] =
{
/* Little-endian byte masks for PACKSWAP */
{ B_MASKS(1,0), B_MASKS(2,0), B_MASKS(4,0) },
@@ -3687,7 +3864,7 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
{
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Offset to next interlace block */
- static PNG_CONST unsigned int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+ static const unsigned int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
png_debug(1, "in png_do_read_interlace");
if (row != NULL && row_info != NULL)
@@ -4166,7 +4343,38 @@ png_read_IDAT_data(png_structrp png_ptr, png_bytep output,
{
uInt avail_in;
png_bytep buffer;
+#ifdef PNG_READ_APNG_SUPPORTED
+ png_uint_32 bytes_to_skip = 0;
+
+ while (png_ptr->idat_size == 0 || bytes_to_skip != 0)
+ {
+ png_crc_finish(png_ptr, bytes_to_skip);
+ bytes_to_skip = 0;
+
+ png_ptr->idat_size = png_read_chunk_header(png_ptr);
+ if (png_ptr->num_frames_read == 0)
+ {
+ if (png_ptr->chunk_name != png_IDAT)
+ png_error(png_ptr, "Not enough image data");
+ }
+ else
+ {
+ if (png_ptr->chunk_name == png_IEND)
+ png_error(png_ptr, "Not enough image data");
+ if (png_ptr->chunk_name != png_fdAT)
+ {
+ png_warning(png_ptr, "Skipped (ignored) a chunk "
+ "between APNG chunks");
+ bytes_to_skip = png_ptr->idat_size;
+ continue;
+ }
+
+ png_ensure_sequence_number(png_ptr, png_ptr->idat_size);
+ png_ptr->idat_size -= 4;
+ }
+ }
+#else
while (png_ptr->idat_size == 0)
{
png_crc_finish(png_ptr, 0);
@@ -4178,7 +4386,7 @@ png_read_IDAT_data(png_structrp png_ptr, png_bytep output,
if (png_ptr->chunk_name != png_IDAT)
png_error(png_ptr, "Not enough image data");
}
-
+#endif /* PNG_READ_APNG_SUPPORTED */
avail_in = png_ptr->IDAT_read_size;
if (avail_in > png_ptr->idat_size)
@@ -4241,6 +4449,9 @@ png_read_IDAT_data(png_structrp png_ptr, png_bytep output,
png_ptr->mode |= PNG_AFTER_IDAT;
png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
+#ifdef PNG_READ_APNG_SUPPORTED
+ png_ptr->num_frames_read++;
+#endif
if (png_ptr->zstream.avail_in > 0 || png_ptr->idat_size > 0)
png_chunk_benign_error(png_ptr, "Extra compressed data");
@@ -4329,16 +4540,16 @@ png_read_finish_row(png_structrp png_ptr)
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Start of interlace block */
- static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
+ static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
/* Offset to next interlace block */
- static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+ static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
/* Start of interlace block in the y direction */
- static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
+ static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
/* Offset to next interlace block in the y direction */
- static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
+ static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
png_debug(1, "in png_read_finish_row");
png_ptr->row_number++;
@@ -4394,16 +4605,16 @@ png_read_start_row(png_structrp png_ptr)
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Start of interlace block */
- static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
+ static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
/* Offset to next interlace block */
- static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+ static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
/* Start of interlace block in the y direction */
- static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
+ static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
/* Offset to next interlace block in the y direction */
- static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
+ static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
unsigned int max_pixel_depth;
size_t row_bytes;
@@ -4679,4 +4890,80 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
png_ptr->flags |= PNG_FLAG_ROW_INIT;
}
+
+#ifdef PNG_READ_APNG_SUPPORTED
+/* This function is to be called after the main IDAT set has been read and
+ * before a new IDAT is read. It resets some parts of png_ptr
+ * to make them usable by the read functions again */
+void /* PRIVATE */
+png_read_reset(png_structp png_ptr)
+{
+ png_ptr->mode &= ~PNG_HAVE_IDAT;
+ png_ptr->mode &= ~PNG_AFTER_IDAT;
+ png_ptr->row_number = 0;
+ png_ptr->pass = 0;
+}
+
+void /* PRIVATE */
+png_read_reinit(png_structp png_ptr, png_infop info_ptr)
+{
+ png_ptr->width = info_ptr->next_frame_width;
+ png_ptr->height = info_ptr->next_frame_height;
+ png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->width);
+ png_ptr->info_rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth,
+ png_ptr->width);
+ if (png_ptr->prev_row)
+ memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
+}
+
+#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
+/* same as png_read_reset() but for the progressive reader */
+void /* PRIVATE */
+png_progressive_read_reset(png_structp png_ptr)
+{
+#ifdef PNG_READ_INTERLACING_SUPPORTED
+ /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
+
+ /* Start of interlace block */
+ const int png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
+
+ /* Offset to next interlace block */
+ const int png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
+
+ /* Start of interlace block in the y direction */
+ const int png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
+
+ /* Offset to next interlace block in the y direction */
+ const int png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
+
+ if (png_ptr->interlaced)
+ {
+ if (!(png_ptr->transformations & PNG_INTERLACE))
+ png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
+ png_pass_ystart[0]) / png_pass_yinc[0];
+ else
+ png_ptr->num_rows = png_ptr->height;
+
+ png_ptr->iwidth = (png_ptr->width +
+ png_pass_inc[png_ptr->pass] - 1 -
+ png_pass_start[png_ptr->pass]) /
+ png_pass_inc[png_ptr->pass];
+ }
+ else
+#endif /* PNG_READ_INTERLACING_SUPPORTED */
+ {
+ png_ptr->num_rows = png_ptr->height;
+ png_ptr->iwidth = png_ptr->width;
+ }
+ png_ptr->flags &= ~PNG_FLAG_ZSTREAM_ENDED;
+ if (inflateReset(&(png_ptr->zstream)) != Z_OK)
+ png_error(png_ptr, "inflateReset failed");
+ png_ptr->zstream.avail_in = 0;
+ png_ptr->zstream.next_in = 0;
+ png_ptr->zstream.next_out = png_ptr->row_buf;
+ png_ptr->zstream.avail_out = (uInt)PNG_ROWBYTES(png_ptr->pixel_depth,
+ png_ptr->iwidth) + 1;
+}
+#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
+#endif /* PNG_READ_APNG_SUPPORTED */
#endif /* READ */
diff --git a/thirdparty/libpng/pngset.c b/thirdparty/libpng/pngset.c
index 7cf54d9248..a281db58ae 100644
--- a/thirdparty/libpng/pngset.c
+++ b/thirdparty/libpng/pngset.c
@@ -1,10 +1,10 @@
/* pngset.c - storage of image information into info struct
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
@@ -137,7 +137,7 @@ png_set_cHRM_XYZ(png_const_structrp png_ptr, png_inforp info_ptr, double red_X,
#ifdef PNG_eXIf_SUPPORTED
void PNGAPI
png_set_eXIf(png_const_structrp png_ptr, png_inforp info_ptr,
- const png_bytep eXIf_buf)
+ png_bytep eXIf_buf)
{
png_warning(png_ptr, "png_set_eXIf does not work; use png_set_eXIf_1");
PNG_UNUSED(info_ptr)
@@ -146,7 +146,7 @@ png_set_eXIf(png_const_structrp png_ptr, png_inforp info_ptr,
void PNGAPI
png_set_eXIf_1(png_const_structrp png_ptr, png_inforp info_ptr,
- const png_uint_32 num_exif, const png_bytep eXIf_buf)
+ png_uint_32 num_exif, png_bytep eXIf_buf)
{
int i;
@@ -288,6 +288,11 @@ png_set_IHDR(png_const_structrp png_ptr, png_inforp info_ptr,
info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth);
info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width);
+
+#ifdef PNG_APNG_SUPPORTED
+ /* for non-animated png. this may be overwritten from an acTL chunk later */
+ info_ptr->num_frames = 1;
+#endif
}
#ifdef PNG_oFFs_SUPPORTED
@@ -1158,6 +1163,147 @@ png_set_sPLT(png_const_structrp png_ptr,
}
#endif /* sPLT */
+#ifdef PNG_APNG_SUPPORTED
+png_uint_32 PNGAPI
+png_set_acTL(png_structp png_ptr, png_infop info_ptr,
+ png_uint_32 num_frames, png_uint_32 num_plays)
+{
+ png_debug1(1, "in %s storage function", "acTL");
+
+ if (png_ptr == NULL || info_ptr == NULL)
+ {
+ png_warning(png_ptr,
+ "Call to png_set_acTL() with NULL png_ptr "
+ "or info_ptr ignored");
+ return (0);
+ }
+ if (num_frames == 0)
+ {
+ png_warning(png_ptr,
+ "Ignoring attempt to set acTL with num_frames zero");
+ return (0);
+ }
+ if (num_frames > PNG_UINT_31_MAX)
+ {
+ png_warning(png_ptr,
+ "Ignoring attempt to set acTL with num_frames > 2^31-1");
+ return (0);
+ }
+ if (num_plays > PNG_UINT_31_MAX)
+ {
+ png_warning(png_ptr,
+ "Ignoring attempt to set acTL with num_plays "
+ "> 2^31-1");
+ return (0);
+ }
+
+ info_ptr->num_frames = num_frames;
+ info_ptr->num_plays = num_plays;
+
+ info_ptr->valid |= PNG_INFO_acTL;
+
+ return (1);
+}
+
+/* delay_num and delay_den can hold any 16-bit values including zero */
+png_uint_32 PNGAPI
+png_set_next_frame_fcTL(png_structp png_ptr, png_infop info_ptr,
+ png_uint_32 width, png_uint_32 height,
+ png_uint_32 x_offset, png_uint_32 y_offset,
+ png_uint_16 delay_num, png_uint_16 delay_den,
+ png_byte dispose_op, png_byte blend_op)
+{
+ png_debug1(1, "in %s storage function", "fcTL");
+
+ if (png_ptr == NULL || info_ptr == NULL)
+ {
+ png_warning(png_ptr,
+ "Call to png_set_fcTL() with NULL png_ptr or info_ptr "
+ "ignored");
+ return (0);
+ }
+
+ png_ensure_fcTL_is_valid(png_ptr, width, height, x_offset, y_offset,
+ delay_num, delay_den, dispose_op, blend_op);
+
+ if (blend_op == PNG_BLEND_OP_OVER)
+ {
+ if (!(png_ptr->color_type & PNG_COLOR_MASK_ALPHA) &&
+ !(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)))
+ {
+ png_warning(png_ptr, "PNG_BLEND_OP_OVER is meaningless "
+ "and wasteful for opaque images, ignored");
+ blend_op = PNG_BLEND_OP_SOURCE;
+ }
+ }
+
+ info_ptr->next_frame_width = width;
+ info_ptr->next_frame_height = height;
+ info_ptr->next_frame_x_offset = x_offset;
+ info_ptr->next_frame_y_offset = y_offset;
+ info_ptr->next_frame_delay_num = delay_num;
+ info_ptr->next_frame_delay_den = delay_den;
+ info_ptr->next_frame_dispose_op = dispose_op;
+ info_ptr->next_frame_blend_op = blend_op;
+
+ info_ptr->valid |= PNG_INFO_fcTL;
+
+ return (1);
+}
+
+void /* PRIVATE */
+png_ensure_fcTL_is_valid(png_structp png_ptr,
+ png_uint_32 width, png_uint_32 height,
+ png_uint_32 x_offset, png_uint_32 y_offset,
+ png_uint_16 delay_num, png_uint_16 delay_den,
+ png_byte dispose_op, png_byte blend_op)
+{
+ if (width == 0 || width > PNG_UINT_31_MAX)
+ png_error(png_ptr, "invalid width in fcTL (> 2^31-1)");
+ if (height == 0 || height > PNG_UINT_31_MAX)
+ png_error(png_ptr, "invalid height in fcTL (> 2^31-1)");
+ if (x_offset > PNG_UINT_31_MAX)
+ png_error(png_ptr, "invalid x_offset in fcTL (> 2^31-1)");
+ if (y_offset > PNG_UINT_31_MAX)
+ png_error(png_ptr, "invalid y_offset in fcTL (> 2^31-1)");
+ if (width + x_offset > png_ptr->first_frame_width ||
+ height + y_offset > png_ptr->first_frame_height)
+ png_error(png_ptr, "dimensions of a frame are greater than"
+ "the ones in IHDR");
+
+ if (dispose_op != PNG_DISPOSE_OP_NONE &&
+ dispose_op != PNG_DISPOSE_OP_BACKGROUND &&
+ dispose_op != PNG_DISPOSE_OP_PREVIOUS)
+ png_error(png_ptr, "invalid dispose_op in fcTL");
+
+ if (blend_op != PNG_BLEND_OP_SOURCE &&
+ blend_op != PNG_BLEND_OP_OVER)
+ png_error(png_ptr, "invalid blend_op in fcTL");
+
+ PNG_UNUSED(delay_num)
+ PNG_UNUSED(delay_den)
+}
+
+png_uint_32 PNGAPI
+png_set_first_frame_is_hidden(png_structp png_ptr, png_infop info_ptr,
+ png_byte is_hidden)
+{
+ png_debug(1, "in png_first_frame_is_hidden()");
+
+ if (png_ptr == NULL)
+ return 0;
+
+ if (is_hidden)
+ png_ptr->apng_flags |= PNG_FIRST_FRAME_HIDDEN;
+ else
+ png_ptr->apng_flags &= ~PNG_FIRST_FRAME_HIDDEN;
+
+ PNG_UNUSED(info_ptr)
+
+ return 1;
+}
+#endif /* PNG_APNG_SUPPORTED */
+
#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
static png_byte
check_location(png_const_structrp png_ptr, int location)
@@ -1399,7 +1545,7 @@ png_set_keep_unknown_chunks(png_structrp png_ptr, int keep,
/* Ignore all unknown chunks and all chunks recognized by
* libpng except for IHDR, PLTE, tRNS, IDAT, and IEND
*/
- static PNG_CONST png_byte chunks_to_ignore[] = {
+ static const png_byte chunks_to_ignore[] = {
98, 75, 71, 68, '\0', /* bKGD */
99, 72, 82, 77, '\0', /* cHRM */
101, 88, 73, 102, '\0', /* eXIf */
diff --git a/thirdparty/libpng/pngstruct.h b/thirdparty/libpng/pngstruct.h
index 699e8ac68a..2a2236f92e 100644
--- a/thirdparty/libpng/pngstruct.h
+++ b/thirdparty/libpng/pngstruct.h
@@ -1,10 +1,10 @@
/* pngstruct.h - header file for PNG reference library
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018-2019 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
@@ -392,6 +392,12 @@ struct png_struct_def
/* deleted in 1.5.5: rgb_to_gray_blue_coeff; */
#endif
+/* New member added in libpng-1.6.36 */
+#if defined(PNG_READ_EXPAND_SUPPORTED) && \
+ defined(PNG_ARM_NEON_IMPLEMENTATION)
+ png_bytep riffled_palette; /* buffer for accelerated palette expansion */
+#endif
+
/* New member added in libpng-1.0.4 (renamed in 1.0.9) */
#if defined(PNG_MNG_FEATURES_SUPPORTED)
/* Changed from png_byte to png_uint_32 at version 1.2.0 */
@@ -403,6 +409,27 @@ struct png_struct_def
png_byte filter_type;
#endif
+#ifdef PNG_APNG_SUPPORTED
+ png_uint_32 apng_flags;
+ png_uint_32 next_seq_num; /* next fcTL/fdAT chunk sequence number */
+ png_uint_32 first_frame_width;
+ png_uint_32 first_frame_height;
+
+#ifdef PNG_READ_APNG_SUPPORTED
+ png_uint_32 num_frames_read; /* incremented after all image data of */
+ /* a frame is read */
+#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
+ png_progressive_frame_ptr frame_info_fn; /* frame info read callback */
+ png_progressive_frame_ptr frame_end_fn; /* frame data read callback */
+#endif
+#endif
+
+#ifdef PNG_WRITE_APNG_SUPPORTED
+ png_uint_32 num_frames_to_write;
+ png_uint_32 num_frames_written;
+#endif
+#endif /* PNG_APNG_SUPPORTED */
+
/* New members added in libpng-1.2.0 */
/* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */
diff --git a/thirdparty/libpng/pngtrans.c b/thirdparty/libpng/pngtrans.c
index de84aa6d6b..1100f46ebe 100644
--- a/thirdparty/libpng/pngtrans.c
+++ b/thirdparty/libpng/pngtrans.c
@@ -1,10 +1,10 @@
/* pngtrans.c - transforms the data in a row (used by both readers and writers)
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
@@ -345,7 +345,7 @@ png_do_swap(png_row_infop row_info, png_bytep row)
#endif
#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
-static PNG_CONST png_byte onebppswaptable[256] = {
+static const png_byte onebppswaptable[256] = {
0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
@@ -380,7 +380,7 @@ static PNG_CONST png_byte onebppswaptable[256] = {
0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
};
-static PNG_CONST png_byte twobppswaptable[256] = {
+static const png_byte twobppswaptable[256] = {
0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0,
0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0,
0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4,
@@ -415,7 +415,7 @@ static PNG_CONST png_byte twobppswaptable[256] = {
0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF
};
-static PNG_CONST png_byte fourbppswaptable[256] = {
+static const png_byte fourbppswaptable[256] = {
0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0,
0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71,
diff --git a/thirdparty/libpng/pngwio.c b/thirdparty/libpng/pngwio.c
index e5391687a2..10e919dd03 100644
--- a/thirdparty/libpng/pngwio.c
+++ b/thirdparty/libpng/pngwio.c
@@ -1,10 +1,10 @@
/* pngwio.c - functions for data output
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2014,2016,2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
diff --git a/thirdparty/libpng/pngwrite.c b/thirdparty/libpng/pngwrite.c
index 5bd87f373e..5e68032378 100644
--- a/thirdparty/libpng/pngwrite.c
+++ b/thirdparty/libpng/pngwrite.c
@@ -1,10 +1,10 @@
/* pngwrite.c - general routines to write a PNG file
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018-2019 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
@@ -128,6 +128,10 @@ png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr)
* the application continues writing the PNG. So check the 'invalid'
* flag here too.
*/
+#ifdef PNG_WRITE_APNG_SUPPORTED
+ if (info_ptr->valid & PNG_INFO_acTL)
+ png_write_acTL(png_ptr, info_ptr->num_frames, info_ptr->num_plays);
+#endif
#ifdef PNG_GAMMA_SUPPORTED
# ifdef PNG_WRITE_gAMA_SUPPORTED
if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
@@ -370,6 +374,11 @@ png_write_end(png_structrp png_ptr, png_inforp info_ptr)
png_benign_error(png_ptr, "Wrote palette index exceeding num_palette");
#endif
+#ifdef PNG_WRITE_APNG_SUPPORTED
+ if (png_ptr->num_frames_written != png_ptr->num_frames_to_write)
+ png_error(png_ptr, "Not enough frames written");
+#endif
+
/* See if user wants us to write information chunks */
if (info_ptr != NULL)
{
@@ -469,7 +478,7 @@ png_write_end(png_structrp png_ptr, png_inforp info_ptr)
#ifdef PNG_CONVERT_tIME_SUPPORTED
void PNGAPI
-png_convert_from_struct_tm(png_timep ptime, PNG_CONST struct tm * ttime)
+png_convert_from_struct_tm(png_timep ptime, const struct tm * ttime)
{
png_debug(1, "in png_convert_from_struct_tm");
@@ -1461,6 +1470,43 @@ png_write_png(png_structrp png_ptr, png_inforp info_ptr,
}
#endif
+#ifdef PNG_WRITE_APNG_SUPPORTED
+void PNGAPI
+png_write_frame_head(png_structp png_ptr, png_infop info_ptr,
+ png_bytepp row_pointers, png_uint_32 width, png_uint_32 height,
+ png_uint_32 x_offset, png_uint_32 y_offset,
+ png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op,
+ png_byte blend_op)
+{
+ png_debug(1, "in png_write_frame_head");
+
+ /* there is a chance this has been set after png_write_info was called,
+ * so it would be set but not written. is there a way to be sure? */
+ if (!(info_ptr->valid & PNG_INFO_acTL))
+ png_error(png_ptr, "png_write_frame_head(): acTL not set");
+
+ png_write_reset(png_ptr);
+
+ png_write_reinit(png_ptr, info_ptr, width, height);
+
+ if ( !(png_ptr->num_frames_written == 0 &&
+ (png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN) ) )
+ png_write_fcTL(png_ptr, width, height, x_offset, y_offset,
+ delay_num, delay_den, dispose_op, blend_op);
+
+ PNG_UNUSED(row_pointers)
+}
+
+void PNGAPI
+png_write_frame_tail(png_structp png_ptr, png_infop info_ptr)
+{
+ png_debug(1, "in png_write_frame_tail");
+
+ png_ptr->num_frames_written++;
+
+ PNG_UNUSED(info_ptr)
+}
+#endif /* PNG_WRITE_APNG_SUPPORTED */
#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
/* Initialize the write structure - general purpose utility. */
@@ -1536,7 +1582,7 @@ png_write_image_16bit(png_voidp argument)
display->first_row);
png_uint_16p output_row = png_voidcast(png_uint_16p, display->local_row);
png_uint_16p row_end;
- const unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ?
+ unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ?
3 : 1;
int aindex = 0;
png_uint_32 y = image->height;
@@ -1573,7 +1619,7 @@ png_write_image_16bit(png_voidp argument)
while (out_ptr < row_end)
{
- const png_uint_16 alpha = in_ptr[aindex];
+ png_uint_16 alpha = in_ptr[aindex];
png_uint_32 reciprocal = 0;
int c;
@@ -1695,7 +1741,7 @@ png_write_image_8bit(png_voidp argument)
display->first_row);
png_bytep output_row = png_voidcast(png_bytep, display->local_row);
png_uint_32 y = image->height;
- const unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ?
+ unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ?
3 : 1;
if ((image->format & PNG_FORMAT_FLAG_ALPHA) != 0)
@@ -1783,25 +1829,25 @@ png_write_image_8bit(png_voidp argument)
static void
png_image_set_PLTE(png_image_write_control *display)
{
- const png_imagep image = display->image;
+ png_imagep image = display->image;
const void *cmap = display->colormap;
- const int entries = image->colormap_entries > 256 ? 256 :
+ int entries = image->colormap_entries > 256 ? 256 :
(int)image->colormap_entries;
/* NOTE: the caller must check for cmap != NULL and entries != 0 */
- const png_uint_32 format = image->format;
- const unsigned int channels = PNG_IMAGE_SAMPLE_CHANNELS(format);
+ png_uint_32 format = image->format;
+ unsigned int channels = PNG_IMAGE_SAMPLE_CHANNELS(format);
# if defined(PNG_FORMAT_BGR_SUPPORTED) &&\
defined(PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED)
- const int afirst = (format & PNG_FORMAT_FLAG_AFIRST) != 0 &&
+ int afirst = (format & PNG_FORMAT_FLAG_AFIRST) != 0 &&
(format & PNG_FORMAT_FLAG_ALPHA) != 0;
# else
# define afirst 0
# endif
# ifdef PNG_FORMAT_BGR_SUPPORTED
- const int bgr = (format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0;
+ int bgr = (format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0;
# else
# define bgr 0
# endif
@@ -1951,12 +1997,12 @@ png_image_write_main(png_voidp argument)
* and total image size to ensure that they are within the system limits.
*/
{
- const unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format);
+ unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format);
if (image->width <= 0x7fffffffU/channels) /* no overflow */
{
png_uint_32 check;
- const png_uint_32 png_row_stride = image->width * channels;
+ png_uint_32 png_row_stride = image->width * channels;
if (display->row_stride == 0)
display->row_stride = (png_int_32)/*SAFE*/png_row_stride;
@@ -2052,7 +2098,7 @@ png_image_write_main(png_voidp argument)
*/
if (write_16bit != 0)
{
- PNG_CONST png_uint_16 le = 0x0001;
+ png_uint_16 le = 0x0001;
if ((*(png_const_bytep) & le) != 0)
png_set_swap(png_ptr);
@@ -2166,7 +2212,7 @@ image_memory_write)(png_structp png_ptr, png_bytep/*const*/ data, size_t size)
{
png_image_write_control *display = png_voidcast(png_image_write_control*,
png_ptr->io_ptr/*backdoor: png_get_io_ptr(png_ptr)*/);
- const png_alloc_size_t ob = display->output_bytes;
+ png_alloc_size_t ob = display->output_bytes;
/* Check for overflow; this should never happen: */
if (size <= ((png_alloc_size_t)-1) - ob)
diff --git a/thirdparty/libpng/pngwtran.c b/thirdparty/libpng/pngwtran.c
index 3a1e0a21d2..49a13c1e98 100644
--- a/thirdparty/libpng/pngwtran.c
+++ b/thirdparty/libpng/pngwtran.c
@@ -1,10 +1,10 @@
/* pngwtran.c - transforms the data in a row for PNG writers
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
@@ -254,8 +254,7 @@ png_do_shift(png_row_infop row_info, png_bytep row,
for (i = 0; i < istop; i++, bp++)
{
-
- const unsigned int c = i%channels;
+ unsigned int c = i%channels;
int j;
unsigned int v, out;
@@ -283,7 +282,7 @@ png_do_shift(png_row_infop row_info, png_bytep row,
for (bp = row, i = 0; i < istop; i++)
{
- const unsigned int c = i%channels;
+ unsigned int c = i%channels;
int j;
unsigned int value, v;
diff --git a/thirdparty/libpng/pngwutil.c b/thirdparty/libpng/pngwutil.c
index ab431e712c..b4809cda6b 100644
--- a/thirdparty/libpng/pngwutil.c
+++ b/thirdparty/libpng/pngwutil.c
@@ -1,10 +1,10 @@
/* pngwutil.c - utilities to write a PNG file
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
@@ -821,6 +821,11 @@ png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height,
/* Write the chunk */
png_write_complete_chunk(png_ptr, png_IHDR, buf, 13);
+#ifdef PNG_WRITE_APNG_SUPPORTED
+ png_ptr->first_frame_width = width;
+ png_ptr->first_frame_height = height;
+#endif
+
if ((png_ptr->do_filter) == PNG_NO_FILTERS)
{
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||
@@ -1002,8 +1007,17 @@ png_compress_IDAT(png_structrp png_ptr, png_const_bytep input,
optimize_cmf(data, png_image_size(png_ptr));
#endif
- if (size > 0)
- png_write_complete_chunk(png_ptr, png_IDAT, data, size);
+ if (size > 0)
+#ifdef PNG_WRITE_APNG_SUPPORTED
+ {
+ if (png_ptr->num_frames_written == 0)
+#endif
+ png_write_complete_chunk(png_ptr, png_IDAT, data, size);
+#ifdef PNG_WRITE_APNG_SUPPORTED
+ else
+ png_write_fdAT(png_ptr, data, size);
+ }
+#endif /* PNG_WRITE_APNG_SUPPORTED */
png_ptr->mode |= PNG_HAVE_IDAT;
png_ptr->zstream.next_out = data;
@@ -1050,7 +1064,17 @@ png_compress_IDAT(png_structrp png_ptr, png_const_bytep input,
#endif
if (size > 0)
+#ifdef PNG_WRITE_APNG_SUPPORTED
+ {
+ if (png_ptr->num_frames_written == 0)
+#endif
png_write_complete_chunk(png_ptr, png_IDAT, data, size);
+#ifdef PNG_WRITE_APNG_SUPPORTED
+ else
+ png_write_fdAT(png_ptr, data, size);
+ }
+#endif /* PNG_WRITE_APNG_SUPPORTED */
+
png_ptr->zstream.avail_out = 0;
png_ptr->zstream.next_out = NULL;
png_ptr->mode |= PNG_HAVE_IDAT | PNG_AFTER_IDAT;
@@ -1885,6 +1909,82 @@ png_write_tIME(png_structrp png_ptr, png_const_timep mod_time)
}
#endif
+#ifdef PNG_WRITE_APNG_SUPPORTED
+void /* PRIVATE */
+png_write_acTL(png_structp png_ptr,
+ png_uint_32 num_frames, png_uint_32 num_plays)
+{
+ png_byte buf[8];
+
+ png_debug(1, "in png_write_acTL");
+
+ png_ptr->num_frames_to_write = num_frames;
+
+ if (png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN)
+ num_frames--;
+
+ png_save_uint_32(buf, num_frames);
+ png_save_uint_32(buf + 4, num_plays);
+
+ png_write_complete_chunk(png_ptr, png_acTL, buf, (png_size_t)8);
+}
+
+void /* PRIVATE */
+png_write_fcTL(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
+ png_uint_32 x_offset, png_uint_32 y_offset,
+ png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op,
+ png_byte blend_op)
+{
+ png_byte buf[26];
+
+ png_debug(1, "in png_write_fcTL");
+
+ if (png_ptr->num_frames_written == 0 && (x_offset != 0 || y_offset != 0))
+ png_error(png_ptr, "x and/or y offset for the first frame aren't 0");
+ if (png_ptr->num_frames_written == 0 &&
+ (width != png_ptr->first_frame_width ||
+ height != png_ptr->first_frame_height))
+ png_error(png_ptr, "width and/or height in the first frame's fcTL "
+ "don't match the ones in IHDR");
+
+ /* more error checking */
+ png_ensure_fcTL_is_valid(png_ptr, width, height, x_offset, y_offset,
+ delay_num, delay_den, dispose_op, blend_op);
+
+ png_save_uint_32(buf, png_ptr->next_seq_num);
+ png_save_uint_32(buf + 4, width);
+ png_save_uint_32(buf + 8, height);
+ png_save_uint_32(buf + 12, x_offset);
+ png_save_uint_32(buf + 16, y_offset);
+ png_save_uint_16(buf + 20, delay_num);
+ png_save_uint_16(buf + 22, delay_den);
+ buf[24] = dispose_op;
+ buf[25] = blend_op;
+
+ png_write_complete_chunk(png_ptr, png_fcTL, buf, (png_size_t)26);
+
+ png_ptr->next_seq_num++;
+}
+
+void /* PRIVATE */
+png_write_fdAT(png_structp png_ptr,
+ png_const_bytep data, png_size_t length)
+{
+ png_byte buf[4];
+
+ png_write_chunk_header(png_ptr, png_fdAT, (png_uint_32)(4 + length));
+
+ png_save_uint_32(buf, png_ptr->next_seq_num);
+ png_write_chunk_data(png_ptr, buf, 4);
+
+ png_write_chunk_data(png_ptr, data, length);
+
+ png_write_chunk_end(png_ptr);
+
+ png_ptr->next_seq_num++;
+}
+#endif /* PNG_WRITE_APNG_SUPPORTED */
+
/* Initializes the row writing capability of libpng */
void /* PRIVATE */
png_write_start_row(png_structrp png_ptr)
@@ -1893,16 +1993,16 @@ png_write_start_row(png_structrp png_ptr)
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Start of interlace block */
- static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
+ static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
/* Offset to next interlace block */
- static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+ static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
/* Start of interlace block in the y direction */
- static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
+ static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
/* Offset to next interlace block in the y direction */
- static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
+ static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
#endif
png_alloc_size_t buf_size;
@@ -2008,16 +2108,16 @@ png_write_finish_row(png_structrp png_ptr)
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Start of interlace block */
- static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
+ static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
/* Offset to next interlace block */
- static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+ static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
/* Start of interlace block in the y direction */
- static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
+ static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
/* Offset to next interlace block in the y direction */
- static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
+ static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
#endif
png_debug(1, "in png_write_finish_row");
@@ -2098,10 +2198,10 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Start of interlace block */
- static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
+ static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
/* Offset to next interlace block */
- static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+ static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
png_debug(1, "in png_do_write_interlace");
@@ -2276,7 +2376,7 @@ png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row,
#ifdef PNG_WRITE_FILTER_SUPPORTED
static size_t /* PRIVATE */
-png_setup_sub_row(png_structrp png_ptr, const png_uint_32 bpp,
+png_setup_sub_row(png_structrp png_ptr, png_uint_32 bpp,
size_t row_bytes, size_t lmins)
{
png_bytep rp, dp, lp;
@@ -2315,7 +2415,7 @@ png_setup_sub_row(png_structrp png_ptr, const png_uint_32 bpp,
}
static void /* PRIVATE */
-png_setup_sub_row_only(png_structrp png_ptr, const png_uint_32 bpp,
+png_setup_sub_row_only(png_structrp png_ptr, png_uint_32 bpp,
size_t row_bytes)
{
png_bytep rp, dp, lp;
@@ -2380,7 +2480,7 @@ png_setup_up_row_only(png_structrp png_ptr, size_t row_bytes)
}
static size_t /* PRIVATE */
-png_setup_avg_row(png_structrp png_ptr, const png_uint_32 bpp,
+png_setup_avg_row(png_structrp png_ptr, png_uint_32 bpp,
size_t row_bytes, size_t lmins)
{
png_bytep rp, dp, pp, lp;
@@ -2420,7 +2520,7 @@ png_setup_avg_row(png_structrp png_ptr, const png_uint_32 bpp,
return (sum);
}
static void /* PRIVATE */
-png_setup_avg_row_only(png_structrp png_ptr, const png_uint_32 bpp,
+png_setup_avg_row_only(png_structrp png_ptr, png_uint_32 bpp,
size_t row_bytes)
{
png_bytep rp, dp, pp, lp;
@@ -2442,7 +2542,7 @@ png_setup_avg_row_only(png_structrp png_ptr, const png_uint_32 bpp,
}
static size_t /* PRIVATE */
-png_setup_paeth_row(png_structrp png_ptr, const png_uint_32 bpp,
+png_setup_paeth_row(png_structrp png_ptr, png_uint_32 bpp,
size_t row_bytes, size_t lmins)
{
png_bytep rp, dp, pp, cp, lp;
@@ -2503,7 +2603,7 @@ png_setup_paeth_row(png_structrp png_ptr, const png_uint_32 bpp,
return (sum);
}
static void /* PRIVATE */
-png_setup_paeth_row_only(png_structrp png_ptr, const png_uint_32 bpp,
+png_setup_paeth_row_only(png_structrp png_ptr, png_uint_32 bpp,
size_t row_bytes)
{
png_bytep rp, dp, pp, cp, lp;
@@ -2778,4 +2878,39 @@ png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row,
}
#endif /* WRITE_FLUSH */
}
+
+#ifdef PNG_WRITE_APNG_SUPPORTED
+void /* PRIVATE */
+png_write_reset(png_structp png_ptr)
+{
+ png_ptr->row_number = 0;
+ png_ptr->pass = 0;
+ png_ptr->mode &= ~PNG_HAVE_IDAT;
+}
+
+void /* PRIVATE */
+png_write_reinit(png_structp png_ptr, png_infop info_ptr,
+ png_uint_32 width, png_uint_32 height)
+{
+ if (png_ptr->num_frames_written == 0 &&
+ (width != png_ptr->first_frame_width ||
+ height != png_ptr->first_frame_height))
+ png_error(png_ptr, "width and/or height in the first frame's fcTL "
+ "don't match the ones in IHDR");
+ if (width > png_ptr->first_frame_width ||
+ height > png_ptr->first_frame_height)
+ png_error(png_ptr, "width and/or height for a frame greater than"
+ "the ones in IHDR");
+
+ png_set_IHDR(png_ptr, info_ptr, width, height,
+ info_ptr->bit_depth, info_ptr->color_type,
+ info_ptr->interlace_type, info_ptr->compression_type,
+ info_ptr->filter_type);
+
+ png_ptr->width = width;
+ png_ptr->height = height;
+ png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width);
+ png_ptr->usr_width = png_ptr->width;
+}
+#endif /* PNG_WRITE_APNG_SUPPORTED */
#endif /* WRITE */
diff --git a/thirdparty/libsimplewebm/OpusVorbisDecoder.cpp b/thirdparty/libsimplewebm/OpusVorbisDecoder.cpp
index c9e71eb733..b5824b17be 100644
--- a/thirdparty/libsimplewebm/OpusVorbisDecoder.cpp
+++ b/thirdparty/libsimplewebm/OpusVorbisDecoder.cpp
@@ -122,6 +122,7 @@ bool OpusVorbisDecoder::getPCMS16(WebMFrame &frame, short *buffer, int &numOutSa
return false;
}
+// -- GODOT begin --
bool OpusVorbisDecoder::getPCMF(WebMFrame &frame, float *buffer, int &numOutSamples) {
if (m_vorbis) {
m_vorbis->op.packet = frame.buffer;
@@ -158,6 +159,7 @@ bool OpusVorbisDecoder::getPCMF(WebMFrame &frame, float *buffer, int &numOutSamp
}
return false;
}
+// -- GODOT end --
bool OpusVorbisDecoder::openVorbis(const WebMDemuxer &demuxer)
{
diff --git a/thirdparty/libsimplewebm/OpusVorbisDecoder.hpp b/thirdparty/libsimplewebm/OpusVorbisDecoder.hpp
index b7619d6a25..f285b3fbd6 100644
--- a/thirdparty/libsimplewebm/OpusVorbisDecoder.hpp
+++ b/thirdparty/libsimplewebm/OpusVorbisDecoder.hpp
@@ -44,8 +44,10 @@ public:
{
return m_numSamples;
}
- bool getPCMF(WebMFrame &frame, float *buffer, int &numOutSamples);
bool getPCMS16(WebMFrame &frame, short *buffer, int &numOutSamples);
+// -- GODOT begin --
+ bool getPCMF(WebMFrame &frame, float *buffer, int &numOutSamples);
+// -- GODOT end --
private:
bool openVorbis(const WebMDemuxer &demuxer);
diff --git a/thirdparty/libsimplewebm/VPXDecoder.cpp b/thirdparty/libsimplewebm/VPXDecoder.cpp
index 3f77b8f5cd..e2606f83ba 100644
--- a/thirdparty/libsimplewebm/VPXDecoder.cpp
+++ b/thirdparty/libsimplewebm/VPXDecoder.cpp
@@ -33,7 +33,8 @@
VPXDecoder::VPXDecoder(const WebMDemuxer &demuxer, unsigned threads) :
m_ctx(NULL),
m_iter(NULL),
- m_delay(0)
+ m_delay(0),
+ m_last_space(VPX_CS_UNKNOWN)
{
if (threads > 8)
threads = 8;
@@ -86,6 +87,11 @@ VPXDecoder::IMAGE_ERROR VPXDecoder::getImage(Image &image)
IMAGE_ERROR err = NO_FRAME;
if (vpx_image_t *img = vpx_codec_get_frame(m_ctx, &m_iter))
{
+ // It seems to be a common problem that UNKNOWN comes up a lot, yet FFMPEG is somehow getting accurate colour-space information.
+ // After checking FFMPEG code, *they're* getting colour-space information, so I'm assuming something like this is going on.
+ // It appears to work, at least.
+ if (img->cs != VPX_CS_UNKNOWN)
+ m_last_space = img->cs;
if ((img->fmt & VPX_IMG_FMT_PLANAR) && !(img->fmt & (VPX_IMG_FMT_HAS_ALPHA | VPX_IMG_FMT_HIGHBITDEPTH)))
{
if (img->stride[0] && img->stride[1] && img->stride[2])
@@ -95,6 +101,7 @@ VPXDecoder::IMAGE_ERROR VPXDecoder::getImage(Image &image)
image.w = img->d_w;
image.h = img->d_h;
+ image.cs = m_last_space;
image.chromaShiftW = img->x_chroma_shift;
image.chromaShiftH = img->y_chroma_shift;
@@ -119,7 +126,9 @@ VPXDecoder::IMAGE_ERROR VPXDecoder::getImage(Image &image)
/**/
+// -- GODOT begin --
#if 0
+// -- GODOT end --
static inline int ceilRshift(int val, int shift)
{
@@ -139,4 +148,7 @@ int VPXDecoder::Image::getHeight(int plane) const
return ceilRshift(h, chromaShiftH);
}
+// -- GODOT begin --
#endif
+// -- GODOT end --
+
diff --git a/thirdparty/libsimplewebm/VPXDecoder.hpp b/thirdparty/libsimplewebm/VPXDecoder.hpp
index 6108395871..5071b069cb 100644
--- a/thirdparty/libsimplewebm/VPXDecoder.hpp
+++ b/thirdparty/libsimplewebm/VPXDecoder.hpp
@@ -37,12 +37,17 @@ public:
class Image
{
public:
+// -- GODOT begin --
#if 0
+// -- GODOT end --
int getWidth(int plane) const;
int getHeight(int plane) const;
+// -- GODOT begin --
#endif
+// -- GODOT end --
int w, h;
+ int cs;
int chromaShiftW, chromaShiftH;
unsigned char *planes[3];
int linesize[3];
@@ -75,6 +80,7 @@ private:
vpx_codec_ctx *m_ctx;
const void *m_iter;
int m_delay;
+ int m_last_space;
};
#endif // VPXDECODER_HPP
diff --git a/thirdparty/libtheora/decode.c b/thirdparty/libtheora/decode.c
index 7be66463d8..bde967b794 100644
--- a/thirdparty/libtheora/decode.c
+++ b/thirdparty/libtheora/decode.c
@@ -397,10 +397,10 @@ static int oc_dec_init(oc_dec_ctx *_dec,const th_info *_info,
int qsum;
qsum=0;
for(qti=0;qti<2;qti++)for(pli=0;pli<3;pli++){
- qsum+=_dec->state.dequant_tables[qti][pli][qi][12]+
- _dec->state.dequant_tables[qti][pli][qi][17]+
- _dec->state.dequant_tables[qti][pli][qi][18]+
- _dec->state.dequant_tables[qti][pli][qi][24]<<(pli==0);
+ qsum+=_dec->state.dequant_tables[qi][pli][qti][12]+
+ _dec->state.dequant_tables[qi][pli][qti][17]+
+ _dec->state.dequant_tables[qi][pli][qti][18]+
+ _dec->state.dequant_tables[qi][pli][qti][24]<<(pli==0);
}
_dec->pp_sharp_mod[qi]=-(qsum>>11);
}
diff --git a/thirdparty/libtheora/patches/theora.git-0ae66d565e6bead8604d312bc1a4e9dccf245c88.patch b/thirdparty/libtheora/patches/theora.git-0ae66d565e6bead8604d312bc1a4e9dccf245c88.patch
new file mode 100644
index 0000000000..1b9c8e20be
--- /dev/null
+++ b/thirdparty/libtheora/patches/theora.git-0ae66d565e6bead8604d312bc1a4e9dccf245c88.patch
@@ -0,0 +1,38 @@
+From 0ae66d565e6bead8604d312bc1a4e9dccf245c88 Mon Sep 17 00:00:00 2001
+From: Tim Terriberry <tterribe@xiph.org>
+Date: Tue, 8 May 2012 02:51:57 +0000
+Subject: [PATCH] Fix pp_sharp_mod calculation.
+
+This was broken when the dequant_tables indexing changed in commit
+ r16102, but it only affected post-processing quality, so we never
+ noticed.
+With gcc 4.8.0, this can now trigger a segfault during decoder
+ initialization.
+
+svn path=/trunk/theora/; revision=18268
+---
+ decode.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/decode.c b/decode.c
+index b803505..9f2516a 100644
+--- a/decode.c
++++ b/decode.c
+@@ -400,10 +400,10 @@ static int oc_dec_init(oc_dec_ctx *_dec,const th_info *_info,
+ int qsum;
+ qsum=0;
+ for(qti=0;qti<2;qti++)for(pli=0;pli<3;pli++){
+- qsum+=_dec->state.dequant_tables[qti][pli][qi][12]+
+- _dec->state.dequant_tables[qti][pli][qi][17]+
+- _dec->state.dequant_tables[qti][pli][qi][18]+
+- _dec->state.dequant_tables[qti][pli][qi][24]<<(pli==0);
++ qsum+=_dec->state.dequant_tables[qi][pli][qti][12]+
++ _dec->state.dequant_tables[qi][pli][qti][17]+
++ _dec->state.dequant_tables[qi][pli][qti][18]+
++ _dec->state.dequant_tables[qi][pli][qti][24]<<(pli==0);
+ }
+ _dec->pp_sharp_mod[qi]=-(qsum>>11);
+ }
+--
+2.11.0
+
diff --git a/thirdparty/libvpx/rtcd/vpx_dsp_rtcd_x86.h b/thirdparty/libvpx/rtcd/vpx_dsp_rtcd_x86.h
index 82574e096c..c2a68330ac 100644
--- a/thirdparty/libvpx/rtcd/vpx_dsp_rtcd_x86.h
+++ b/thirdparty/libvpx/rtcd/vpx_dsp_rtcd_x86.h
@@ -22,7 +22,6 @@ extern "C" {
void vpx_convolve8_c(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h);
void vpx_convolve8_sse2(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h);
void vpx_convolve8_ssse3(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h);
-void vpx_convolve8_avx2(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h);
RTCD_EXTERN void (*vpx_convolve8)(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h);
void vpx_convolve8_avg_c(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h);
@@ -43,13 +42,11 @@ RTCD_EXTERN void (*vpx_convolve8_avg_vert)(const uint8_t *src, ptrdiff_t src_str
void vpx_convolve8_horiz_c(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h);
void vpx_convolve8_horiz_sse2(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h);
void vpx_convolve8_horiz_ssse3(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h);
-void vpx_convolve8_horiz_avx2(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h);
RTCD_EXTERN void (*vpx_convolve8_horiz)(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h);
void vpx_convolve8_vert_c(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h);
void vpx_convolve8_vert_sse2(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h);
void vpx_convolve8_vert_ssse3(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h);
-void vpx_convolve8_vert_avx2(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h);
RTCD_EXTERN void (*vpx_convolve8_vert)(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h);
void vpx_convolve_avg_c(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h);
@@ -343,12 +340,10 @@ RTCD_EXTERN void (*vpx_lpf_horizontal_8_dual)(uint8_t *s, int pitch, const uint8
void vpx_lpf_horizontal_edge_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
void vpx_lpf_horizontal_edge_16_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
-void vpx_lpf_horizontal_edge_16_avx2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
RTCD_EXTERN void (*vpx_lpf_horizontal_edge_16)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
void vpx_lpf_horizontal_edge_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
void vpx_lpf_horizontal_edge_8_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
-void vpx_lpf_horizontal_edge_8_avx2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
RTCD_EXTERN void (*vpx_lpf_horizontal_edge_8)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
void vpx_lpf_vertical_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
@@ -440,7 +435,6 @@ static void setup_rtcd_internal(void)
vpx_convolve8 = vpx_convolve8_c;
if (flags & HAS_SSE2) vpx_convolve8 = vpx_convolve8_sse2;
if (flags & HAS_SSSE3) vpx_convolve8 = vpx_convolve8_ssse3;
- if (flags & HAS_AVX2) vpx_convolve8 = vpx_convolve8_avx2;
vpx_convolve8_avg = vpx_convolve8_avg_c;
if (flags & HAS_SSE2) vpx_convolve8_avg = vpx_convolve8_avg_sse2;
if (flags & HAS_SSSE3) vpx_convolve8_avg = vpx_convolve8_avg_ssse3;
@@ -453,11 +447,9 @@ static void setup_rtcd_internal(void)
vpx_convolve8_horiz = vpx_convolve8_horiz_c;
if (flags & HAS_SSE2) vpx_convolve8_horiz = vpx_convolve8_horiz_sse2;
if (flags & HAS_SSSE3) vpx_convolve8_horiz = vpx_convolve8_horiz_ssse3;
- if (flags & HAS_AVX2) vpx_convolve8_horiz = vpx_convolve8_horiz_avx2;
vpx_convolve8_vert = vpx_convolve8_vert_c;
if (flags & HAS_SSE2) vpx_convolve8_vert = vpx_convolve8_vert_sse2;
if (flags & HAS_SSSE3) vpx_convolve8_vert = vpx_convolve8_vert_ssse3;
- if (flags & HAS_AVX2) vpx_convolve8_vert = vpx_convolve8_vert_avx2;
vpx_convolve_avg = vpx_convolve_avg_c;
if (flags & HAS_SSE2) vpx_convolve_avg = vpx_convolve_avg_sse2;
vpx_convolve_copy = vpx_convolve_copy_c;
@@ -570,10 +562,8 @@ static void setup_rtcd_internal(void)
if (flags & HAS_SSE2) vpx_lpf_horizontal_8_dual = vpx_lpf_horizontal_8_dual_sse2;
vpx_lpf_horizontal_edge_16 = vpx_lpf_horizontal_edge_16_c;
if (flags & HAS_SSE2) vpx_lpf_horizontal_edge_16 = vpx_lpf_horizontal_edge_16_sse2;
- if (flags & HAS_AVX2) vpx_lpf_horizontal_edge_16 = vpx_lpf_horizontal_edge_16_avx2;
vpx_lpf_horizontal_edge_8 = vpx_lpf_horizontal_edge_8_c;
if (flags & HAS_SSE2) vpx_lpf_horizontal_edge_8 = vpx_lpf_horizontal_edge_8_sse2;
- if (flags & HAS_AVX2) vpx_lpf_horizontal_edge_8 = vpx_lpf_horizontal_edge_8_avx2;
vpx_lpf_vertical_16 = vpx_lpf_vertical_16_c;
if (flags & HAS_SSE2) vpx_lpf_vertical_16 = vpx_lpf_vertical_16_sse2;
vpx_lpf_vertical_16_dual = vpx_lpf_vertical_16_dual_c;
diff --git a/thirdparty/libvpx/vpx_config.h b/thirdparty/libvpx/vpx_config.h
index 6caec50c81..e8e91fa6ef 100644
--- a/thirdparty/libvpx/vpx_config.h
+++ b/thirdparty/libvpx/vpx_config.h
@@ -29,7 +29,7 @@
#define HAVE_MMX 1
#define HAVE_SSE2 1
#define HAVE_SSSE3 1
- #define HAVE_AVX2 1
+ #define HAVE_AVX2 0
#elif defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64)
#define ARCH_X86 0
#define ARCH_X86_64 1
@@ -41,7 +41,7 @@
#define HAVE_MMX 1
#define HAVE_SSE2 1
#define HAVE_SSSE3 1
- #define HAVE_AVX2 1
+ #define HAVE_AVX2 0
#elif defined(__arm__) || defined(__TARGET_ARCH_ARM) || defined(_M_ARM)
#define ARCH_X86 0
#define ARCH_X86_64 0
diff --git a/thirdparty/libwebp/AUTHORS b/thirdparty/libwebp/AUTHORS
index 83c7b9c5eb..0d70b7fb2a 100644
--- a/thirdparty/libwebp/AUTHORS
+++ b/thirdparty/libwebp/AUTHORS
@@ -1,4 +1,5 @@
Contributors:
+- Alan Browning (browning at google dot com)
- Charles Munger (clm at google dot com)
- Christian Duvivier (cduvivier at google dot com)
- Djordje Pesut (djordje dot pesut at imgtec dot com)
@@ -6,9 +7,10 @@ Contributors:
- James Zern (jzern at google dot com)
- Jan Engelhardt (jengelh at medozas dot de)
- Jehan (jehan at girinstud dot io)
-- Johann (johann dot koenig at duck dot com)
+- Johann Koenig (johann dot koenig at duck dot com)
- Jovan Zelincevic (jovan dot zelincevic at imgtec dot com)
- Jyrki Alakuijala (jyrki at google dot com)
+- Konstantin Ivlev (tomskside at gmail dot com)
- Lode Vandevenne (lode at google dot com)
- Lou Quillio (louquillio at google dot com)
- Mans Rullgard (mans at mansr dot com)
@@ -37,3 +39,4 @@ Contributors:
- Vincent Rabaud (vrabaud at google dot com)
- Vlad Tsyrklevich (vtsyrklevich at chromium dot org)
- Yang Zhang (yang dot zhang at arm dot com)
+- Yannis Guyon (yguyon at google dot com)
diff --git a/thirdparty/libwebp/src/dec/vp8i_dec.h b/thirdparty/libwebp/src/dec/vp8i_dec.h
index e5e89df57d..2d7900aae1 100644
--- a/thirdparty/libwebp/src/dec/vp8i_dec.h
+++ b/thirdparty/libwebp/src/dec/vp8i_dec.h
@@ -32,7 +32,7 @@ extern "C" {
// version numbers
#define DEC_MAJ_VERSION 1
#define DEC_MIN_VERSION 0
-#define DEC_REV_VERSION 1
+#define DEC_REV_VERSION 2
// YUV-cache parameters. Cache is 32-bytes wide (= one cacheline).
// Constraints are: We need to store one 16x16 block of luma samples (y),
diff --git a/thirdparty/libwebp/src/demux/demux.c b/thirdparty/libwebp/src/demux/demux.c
index a69c65b7cf..d8f7a40a56 100644
--- a/thirdparty/libwebp/src/demux/demux.c
+++ b/thirdparty/libwebp/src/demux/demux.c
@@ -25,7 +25,7 @@
#define DMUX_MAJ_VERSION 1
#define DMUX_MIN_VERSION 0
-#define DMUX_REV_VERSION 1
+#define DMUX_REV_VERSION 2
typedef struct {
size_t start_; // start location of the data
diff --git a/thirdparty/libwebp/src/dsp/cost.c b/thirdparty/libwebp/src/dsp/cost.c
index 634ccc2085..cc681cdd4b 100644
--- a/thirdparty/libwebp/src/dsp/cost.c
+++ b/thirdparty/libwebp/src/dsp/cost.c
@@ -377,6 +377,7 @@ VP8SetResidualCoeffsFunc VP8SetResidualCoeffs;
extern void VP8EncDspCostInitMIPS32(void);
extern void VP8EncDspCostInitMIPSdspR2(void);
extern void VP8EncDspCostInitSSE2(void);
+extern void VP8EncDspCostInitNEON(void);
WEBP_DSP_INIT_FUNC(VP8EncDspCostInit) {
VP8GetResidualCost = GetResidualCost_C;
@@ -399,6 +400,11 @@ WEBP_DSP_INIT_FUNC(VP8EncDspCostInit) {
VP8EncDspCostInitSSE2();
}
#endif
+#if defined(WEBP_USE_NEON)
+ if (VP8GetCPUInfo(kNEON)) {
+ VP8EncDspCostInitNEON();
+ }
+#endif
}
}
diff --git a/thirdparty/libwebp/src/dsp/cost_neon.c b/thirdparty/libwebp/src/dsp/cost_neon.c
new file mode 100644
index 0000000000..8cc8ce58aa
--- /dev/null
+++ b/thirdparty/libwebp/src/dsp/cost_neon.c
@@ -0,0 +1,122 @@
+// Copyright 2018 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// ARM NEON version of cost functions
+
+#include "src/dsp/dsp.h"
+
+#if defined(WEBP_USE_NEON)
+
+#include "src/dsp/neon.h"
+#include "src/enc/cost_enc.h"
+
+static const uint8_t position[16] = { 1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16 };
+
+static void SetResidualCoeffs_NEON(const int16_t* const coeffs,
+ VP8Residual* const res) {
+ const int16x8_t minus_one = vdupq_n_s16(-1);
+ const int16x8_t coeffs_0 = vld1q_s16(coeffs);
+ const int16x8_t coeffs_1 = vld1q_s16(coeffs + 8);
+ const uint16x8_t eob_0 = vtstq_s16(coeffs_0, minus_one);
+ const uint16x8_t eob_1 = vtstq_s16(coeffs_1, minus_one);
+ const uint8x16_t eob = vcombine_u8(vqmovn_u16(eob_0), vqmovn_u16(eob_1));
+ const uint8x16_t masked = vandq_u8(eob, vld1q_u8(position));
+
+#ifdef __aarch64__
+ res->last = vmaxvq_u8(masked) - 1;
+#else
+ const uint8x8_t eob_8x8 = vmax_u8(vget_low_u8(masked), vget_high_u8(masked));
+ const uint16x8_t eob_16x8 = vmovl_u8(eob_8x8);
+ const uint16x4_t eob_16x4 =
+ vmax_u16(vget_low_u16(eob_16x8), vget_high_u16(eob_16x8));
+ const uint32x4_t eob_32x4 = vmovl_u16(eob_16x4);
+ uint32x2_t eob_32x2 =
+ vmax_u32(vget_low_u32(eob_32x4), vget_high_u32(eob_32x4));
+ eob_32x2 = vpmax_u32(eob_32x2, eob_32x2);
+
+ vst1_lane_s32(&res->last, vreinterpret_s32_u32(eob_32x2), 0);
+ --res->last;
+#endif // __aarch64__
+
+ res->coeffs = coeffs;
+}
+
+static int GetResidualCost_NEON(int ctx0, const VP8Residual* const res) {
+ uint8_t levels[16], ctxs[16];
+ uint16_t abs_levels[16];
+ int n = res->first;
+ // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1
+ const int p0 = res->prob[n][ctx0][0];
+ CostArrayPtr const costs = res->costs;
+ const uint16_t* t = costs[n][ctx0];
+ // bit_cost(1, p0) is already incorporated in t[] tables, but only if ctx != 0
+ // (as required by the syntax). For ctx0 == 0, we need to add it here or it'll
+ // be missing during the loop.
+ int cost = (ctx0 == 0) ? VP8BitCost(1, p0) : 0;
+
+ if (res->last < 0) {
+ return VP8BitCost(0, p0);
+ }
+
+ { // precompute clamped levels and contexts, packed to 8b.
+ const uint8x16_t kCst2 = vdupq_n_u8(2);
+ const uint8x16_t kCst67 = vdupq_n_u8(MAX_VARIABLE_LEVEL);
+ const int16x8_t c0 = vld1q_s16(res->coeffs);
+ const int16x8_t c1 = vld1q_s16(res->coeffs + 8);
+ const uint16x8_t E0 = vreinterpretq_u16_s16(vabsq_s16(c0));
+ const uint16x8_t E1 = vreinterpretq_u16_s16(vabsq_s16(c1));
+ const uint8x16_t F = vcombine_u8(vqmovn_u16(E0), vqmovn_u16(E1));
+ const uint8x16_t G = vminq_u8(F, kCst2); // context = 0,1,2
+ const uint8x16_t H = vminq_u8(F, kCst67); // clamp_level in [0..67]
+
+ vst1q_u8(ctxs, G);
+ vst1q_u8(levels, H);
+
+ vst1q_u16(abs_levels, E0);
+ vst1q_u16(abs_levels + 8, E1);
+ }
+ for (; n < res->last; ++n) {
+ const int ctx = ctxs[n];
+ const int level = levels[n];
+ const int flevel = abs_levels[n]; // full level
+ cost += VP8LevelFixedCosts[flevel] + t[level]; // simplified VP8LevelCost()
+ t = costs[n + 1][ctx];
+ }
+ // Last coefficient is always non-zero
+ {
+ const int level = levels[n];
+ const int flevel = abs_levels[n];
+ assert(flevel != 0);
+ cost += VP8LevelFixedCosts[flevel] + t[level];
+ if (n < 15) {
+ const int b = VP8EncBands[n + 1];
+ const int ctx = ctxs[n];
+ const int last_p0 = res->prob[b][ctx][0];
+ cost += VP8BitCost(0, last_p0);
+ }
+ }
+ return cost;
+}
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void VP8EncDspCostInitNEON(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspCostInitNEON(void) {
+ VP8SetResidualCoeffs = SetResidualCoeffs_NEON;
+ VP8GetResidualCost = GetResidualCost_NEON;
+}
+
+#else // !WEBP_USE_NEON
+
+WEBP_DSP_INIT_STUB(VP8EncDspCostInitNEON)
+
+#endif // WEBP_USE_NEON
diff --git a/thirdparty/libwebp/src/dsp/quant.h b/thirdparty/libwebp/src/dsp/quant.h
new file mode 100644
index 0000000000..5ba6f9c377
--- /dev/null
+++ b/thirdparty/libwebp/src/dsp/quant.h
@@ -0,0 +1,70 @@
+// Copyright 2018 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+
+#ifndef WEBP_DSP_QUANT_H_
+#define WEBP_DSP_QUANT_H_
+
+#include "src/dsp/dsp.h"
+#include "src/webp/types.h"
+
+#if defined(WEBP_USE_NEON) && !defined(WEBP_ANDROID_NEON) && \
+ !defined(WEBP_HAVE_NEON_RTCD)
+#include <arm_neon.h>
+
+#define IsFlat IsFlat_NEON
+
+static uint32x2_t horizontal_add_uint32x4(const uint32x4_t a) {
+ const uint64x2_t b = vpaddlq_u32(a);
+ return vadd_u32(vreinterpret_u32_u64(vget_low_u64(b)),
+ vreinterpret_u32_u64(vget_high_u64(b)));
+}
+
+static WEBP_INLINE int IsFlat(const int16_t* levels, int num_blocks,
+ int thresh) {
+ const int16x8_t tst_ones = vdupq_n_s16(-1);
+ uint32x4_t sum = vdupq_n_u32(0);
+
+ for (int i = 0; i < num_blocks; ++i) {
+ // Set DC to zero.
+ const int16x8_t a_0 = vsetq_lane_s16(0, vld1q_s16(levels), 0);
+ const int16x8_t a_1 = vld1q_s16(levels + 8);
+
+ const uint16x8_t b_0 = vshrq_n_u16(vtstq_s16(a_0, tst_ones), 15);
+ const uint16x8_t b_1 = vshrq_n_u16(vtstq_s16(a_1, tst_ones), 15);
+
+ sum = vpadalq_u16(sum, b_0);
+ sum = vpadalq_u16(sum, b_1);
+
+ levels += 16;
+ }
+ return thresh >= (int32_t)vget_lane_u32(horizontal_add_uint32x4(sum), 0);
+}
+
+#else
+
+#define IsFlat IsFlat_C
+
+static WEBP_INLINE int IsFlat(const int16_t* levels, int num_blocks,
+ int thresh) {
+ int score = 0;
+ while (num_blocks-- > 0) { // TODO(skal): refine positional scoring?
+ int i;
+ for (i = 1; i < 16; ++i) { // omit DC, we're only interested in AC
+ score += (levels[i] != 0);
+ if (score > thresh) return 0;
+ }
+ levels += 16;
+ }
+ return 1;
+}
+
+#endif // defined(WEBP_USE_NEON) && !defined(WEBP_ANDROID_NEON) &&
+ // !defined(WEBP_HAVE_NEON_RTCD)
+
+#endif // WEBP_DSP_QUANT_H_
diff --git a/thirdparty/libwebp/src/enc/histogram_enc.c b/thirdparty/libwebp/src/enc/histogram_enc.c
index 4e49e0a201..8ac6fa8e02 100644
--- a/thirdparty/libwebp/src/enc/histogram_enc.c
+++ b/thirdparty/libwebp/src/enc/histogram_enc.c
@@ -165,7 +165,7 @@ VP8LHistogramSet* VP8LAllocateHistogramSet(int size, int cache_bits) {
void VP8LHistogramSetClear(VP8LHistogramSet* const set) {
int i;
const int cache_bits = set->histograms[0]->palette_code_bits_;
- const int size = set->size;
+ const int size = set->max_size;
const size_t total_size = HistogramSetTotalSize(size, cache_bits);
uint8_t* memory = (uint8_t*)set;
@@ -180,6 +180,20 @@ void VP8LHistogramSetClear(VP8LHistogramSet* const set) {
}
}
+// Removes the histogram 'i' from 'set' by setting it to NULL.
+static void HistogramSetRemoveHistogram(VP8LHistogramSet* const set, int i,
+ int* const num_used) {
+ assert(set->histograms[i] != NULL);
+ set->histograms[i] = NULL;
+ --*num_used;
+ // If we remove the last valid one, shrink until the next valid one.
+ if (i == set->size - 1) {
+ while (set->size >= 1 && set->histograms[set->size - 1] == NULL) {
+ --set->size;
+ }
+ }
+}
+
// -----------------------------------------------------------------------------
void VP8LHistogramAddSinglePixOrCopy(VP8LHistogram* const histo,
@@ -447,7 +461,9 @@ static double HistogramAddEval(const VP8LHistogram* const a,
static double HistogramAddThresh(const VP8LHistogram* const a,
const VP8LHistogram* const b,
double cost_threshold) {
- double cost = -a->bit_cost_;
+ double cost;
+ assert(a != NULL && b != NULL);
+ cost = -a->bit_cost_;
GetCombinedHistogramEntropy(a, b, cost_threshold, &cost);
return cost;
}
@@ -561,14 +577,17 @@ static void HistogramBuild(
}
// Copies the histograms and computes its bit_cost.
-static void HistogramCopyAndAnalyze(
- VP8LHistogramSet* const orig_histo, VP8LHistogramSet* const image_histo) {
- int i;
- const int histo_size = orig_histo->size;
+static const uint16_t kInvalidHistogramSymbol = (uint16_t)(-1);
+static void HistogramCopyAndAnalyze(VP8LHistogramSet* const orig_histo,
+ VP8LHistogramSet* const image_histo,
+ int* const num_used,
+ uint16_t* const histogram_symbols) {
+ int i, cluster_id;
+ int num_used_orig = *num_used;
VP8LHistogram** const orig_histograms = orig_histo->histograms;
VP8LHistogram** const histograms = image_histo->histograms;
- image_histo->size = 0;
- for (i = 0; i < histo_size; ++i) {
+ assert(image_histo->max_size == orig_histo->max_size);
+ for (cluster_id = 0, i = 0; i < orig_histo->max_size; ++i) {
VP8LHistogram* const histo = orig_histograms[i];
UpdateHistogramCost(histo);
@@ -576,10 +595,19 @@ static void HistogramCopyAndAnalyze(
// with no information (when they are skipped because of LZ77).
if (!histo->is_used_[0] && !histo->is_used_[1] && !histo->is_used_[2]
&& !histo->is_used_[3] && !histo->is_used_[4]) {
- continue;
+ // The first histogram is always used. If an histogram is empty, we set
+ // its id to be the same as the previous one: this will improve
+ // compressibility for later LZ77.
+ assert(i > 0);
+ HistogramSetRemoveHistogram(image_histo, i, num_used);
+ HistogramSetRemoveHistogram(orig_histo, i, &num_used_orig);
+ histogram_symbols[i] = kInvalidHistogramSymbol;
+ } else {
+ // Copy histograms from orig_histo[] to image_histo[].
+ HistogramCopy(histo, histograms[i]);
+ histogram_symbols[i] = cluster_id++;
+ assert(cluster_id <= image_histo->max_size);
}
- // Copy histograms from orig_histo[] to image_histo[].
- HistogramCopy(histo, histograms[image_histo->size++]);
}
}
@@ -596,29 +624,33 @@ static void HistogramAnalyzeEntropyBin(VP8LHistogramSet* const image_histo,
// Analyze the dominant (literal, red and blue) entropy costs.
for (i = 0; i < histo_size; ++i) {
+ if (histograms[i] == NULL) continue;
UpdateDominantCostRange(histograms[i], &cost_range);
}
// bin-hash histograms on three of the dominant (literal, red and blue)
// symbol costs and store the resulting bin_id for each histogram.
for (i = 0; i < histo_size; ++i) {
+ // bin_map[i] is not set to a special value as its use will later be guarded
+ // by another (histograms[i] == NULL).
+ if (histograms[i] == NULL) continue;
bin_map[i] = GetHistoBinIndex(histograms[i], &cost_range, low_effort);
}
}
-// Compact image_histo[] by merging some histograms with same bin_id together if
-// it's advantageous.
+// Merges some histograms with same bin_id together if it's advantageous.
+// Sets the remaining histograms to NULL.
static void HistogramCombineEntropyBin(VP8LHistogramSet* const image_histo,
+ int *num_used,
+ const uint16_t* const clusters,
+ uint16_t* const cluster_mappings,
VP8LHistogram* cur_combo,
const uint16_t* const bin_map,
- int bin_map_size, int num_bins,
+ int num_bins,
double combine_cost_factor,
int low_effort) {
VP8LHistogram** const histograms = image_histo->histograms;
int idx;
- // Work in-place: processed histograms are put at the beginning of
- // image_histo[]. At the end, we just have to truncate the array.
- int size = 0;
struct {
int16_t first; // position of the histogram that accumulates all
// histograms with the same bin_id
@@ -631,16 +663,19 @@ static void HistogramCombineEntropyBin(VP8LHistogramSet* const image_histo,
bin_info[idx].num_combine_failures = 0;
}
- for (idx = 0; idx < bin_map_size; ++idx) {
- const int bin_id = bin_map[idx];
- const int first = bin_info[bin_id].first;
- assert(size <= idx);
+ // By default, a cluster matches itself.
+ for (idx = 0; idx < *num_used; ++idx) cluster_mappings[idx] = idx;
+ for (idx = 0; idx < image_histo->size; ++idx) {
+ int bin_id, first;
+ if (histograms[idx] == NULL) continue;
+ bin_id = bin_map[idx];
+ first = bin_info[bin_id].first;
if (first == -1) {
- // just move histogram #idx to its final position
- histograms[size] = histograms[idx];
- bin_info[bin_id].first = size++;
+ bin_info[bin_id].first = idx;
} else if (low_effort) {
HistogramAdd(histograms[idx], histograms[first], histograms[first]);
+ HistogramSetRemoveHistogram(image_histo, idx, num_used);
+ cluster_mappings[clusters[idx]] = clusters[first];
} else {
// try to merge #idx into #first (both share the same bin_id)
const double bit_cost = histograms[idx]->bit_cost_;
@@ -663,19 +698,18 @@ static void HistogramCombineEntropyBin(VP8LHistogramSet* const image_histo,
bin_info[bin_id].num_combine_failures >= max_combine_failures) {
// move the (better) merged histogram to its final slot
HistogramSwap(&cur_combo, &histograms[first]);
+ HistogramSetRemoveHistogram(image_histo, idx, num_used);
+ cluster_mappings[clusters[idx]] = clusters[first];
} else {
- histograms[size++] = histograms[idx];
++bin_info[bin_id].num_combine_failures;
}
- } else {
- histograms[size++] = histograms[idx];
}
}
}
- image_histo->size = size;
if (low_effort) {
// for low_effort case, update the final cost when everything is merged
- for (idx = 0; idx < size; ++idx) {
+ for (idx = 0; idx < image_histo->size; ++idx) {
+ if (histograms[idx] == NULL) continue;
UpdateHistogramCost(histograms[idx]);
}
}
@@ -706,16 +740,9 @@ typedef struct {
int max_size;
} HistoQueue;
-static int HistoQueueInit(HistoQueue* const histo_queue, const int max_index) {
+static int HistoQueueInit(HistoQueue* const histo_queue, const int max_size) {
histo_queue->size = 0;
- // max_index^2 for the queue size is safe. If you look at
- // HistogramCombineGreedy, and imagine that UpdateQueueFront always pushes
- // data to the queue, you insert at most:
- // - max_index*(max_index-1)/2 (the first two for loops)
- // - max_index - 1 in the last for loop at the first iteration of the while
- // loop, max_index - 2 at the second iteration ... therefore
- // max_index*(max_index-1)/2 overall too
- histo_queue->max_size = max_index * max_index;
+ histo_queue->max_size = max_size;
// We allocate max_size + 1 because the last element at index "size" is
// used as temporary data (and it could be up to max_size).
histo_queue->queue = (HistogramPair*)WebPSafeMalloc(
@@ -778,6 +805,8 @@ static double HistoQueuePush(HistoQueue* const histo_queue,
const VP8LHistogram* h2;
HistogramPair pair;
+ // Stop here if the queue is full.
+ if (histo_queue->size == histo_queue->max_size) return 0.;
assert(threshold <= 0.);
if (idx1 > idx2) {
const int tmp = idx2;
@@ -794,8 +823,6 @@ static double HistoQueuePush(HistoQueue* const histo_queue,
// Do not even consider the pair if it does not improve the entropy.
if (pair.cost_diff >= threshold) return 0.;
- // We cannot add more elements than the capacity.
- assert(histo_queue->size < histo_queue->max_size);
histo_queue->queue[histo_queue->size++] = pair;
HistoQueueUpdateHead(histo_queue, &histo_queue->queue[histo_queue->size - 1]);
@@ -806,42 +833,43 @@ static double HistoQueuePush(HistoQueue* const histo_queue,
// Combines histograms by continuously choosing the one with the highest cost
// reduction.
-static int HistogramCombineGreedy(VP8LHistogramSet* const image_histo) {
+static int HistogramCombineGreedy(VP8LHistogramSet* const image_histo,
+ int* const num_used) {
int ok = 0;
- int image_histo_size = image_histo->size;
+ const int image_histo_size = image_histo->size;
int i, j;
VP8LHistogram** const histograms = image_histo->histograms;
- // Indexes of remaining histograms.
- int* const clusters =
- (int*)WebPSafeMalloc(image_histo_size, sizeof(*clusters));
// Priority queue of histogram pairs.
HistoQueue histo_queue;
- if (!HistoQueueInit(&histo_queue, image_histo_size) || clusters == NULL) {
+ // image_histo_size^2 for the queue size is safe. If you look at
+ // HistogramCombineGreedy, and imagine that UpdateQueueFront always pushes
+ // data to the queue, you insert at most:
+ // - image_histo_size*(image_histo_size-1)/2 (the first two for loops)
+ // - image_histo_size - 1 in the last for loop at the first iteration of
+ // the while loop, image_histo_size - 2 at the second iteration ...
+ // therefore image_histo_size*(image_histo_size-1)/2 overall too
+ if (!HistoQueueInit(&histo_queue, image_histo_size * image_histo_size)) {
goto End;
}
for (i = 0; i < image_histo_size; ++i) {
- // Initialize clusters indexes.
- clusters[i] = i;
+ if (image_histo->histograms[i] == NULL) continue;
for (j = i + 1; j < image_histo_size; ++j) {
- // Initialize positions array.
+ // Initialize queue.
+ if (image_histo->histograms[j] == NULL) continue;
HistoQueuePush(&histo_queue, histograms, i, j, 0.);
}
}
- while (image_histo_size > 1 && histo_queue.size > 0) {
+ while (histo_queue.size > 0) {
const int idx1 = histo_queue.queue[0].idx1;
const int idx2 = histo_queue.queue[0].idx2;
HistogramAdd(histograms[idx2], histograms[idx1], histograms[idx1]);
histograms[idx1]->bit_cost_ = histo_queue.queue[0].cost_combo;
+
// Remove merged histogram.
- for (i = 0; i + 1 < image_histo_size; ++i) {
- if (clusters[i] >= idx2) {
- clusters[i] = clusters[i + 1];
- }
- }
- --image_histo_size;
+ HistogramSetRemoveHistogram(image_histo, idx2, num_used);
// Remove pairs intersecting the just combined best pair.
for (i = 0; i < histo_queue.size;) {
@@ -856,24 +884,15 @@ static int HistogramCombineGreedy(VP8LHistogramSet* const image_histo) {
}
// Push new pairs formed with combined histogram to the queue.
- for (i = 0; i < image_histo_size; ++i) {
- if (clusters[i] != idx1) {
- HistoQueuePush(&histo_queue, histograms, idx1, clusters[i], 0.);
- }
- }
- }
- // Move remaining histograms to the beginning of the array.
- for (i = 0; i < image_histo_size; ++i) {
- if (i != clusters[i]) { // swap the two histograms
- HistogramSwap(&histograms[i], &histograms[clusters[i]]);
+ for (i = 0; i < image_histo->size; ++i) {
+ if (i == idx1 || image_histo->histograms[i] == NULL) continue;
+ HistoQueuePush(&histo_queue, image_histo->histograms, idx1, i, 0.);
}
}
- image_histo->size = image_histo_size;
ok = 1;
End:
- WebPSafeFree(clusters);
HistoQueueClear(&histo_queue);
return ok;
}
@@ -881,47 +900,69 @@ static int HistogramCombineGreedy(VP8LHistogramSet* const image_histo) {
// Perform histogram aggregation using a stochastic approach.
// 'do_greedy' is set to 1 if a greedy approach needs to be performed
// afterwards, 0 otherwise.
+static int PairComparison(const void* idx1, const void* idx2) {
+ // To be used with bsearch: <0 when *idx1<*idx2, >0 if >, 0 when ==.
+ return (*(int*) idx1 - *(int*) idx2);
+}
static int HistogramCombineStochastic(VP8LHistogramSet* const image_histo,
- int min_cluster_size,
+ int* const num_used, int min_cluster_size,
int* const do_greedy) {
- int iter;
+ int j, iter;
uint32_t seed = 1;
int tries_with_no_success = 0;
- int image_histo_size = image_histo->size;
- const int outer_iters = image_histo_size;
+ const int outer_iters = *num_used;
const int num_tries_no_success = outer_iters / 2;
VP8LHistogram** const histograms = image_histo->histograms;
- // Priority queue of histogram pairs. Its size of "kCostHeapSizeSqrt"^2
+ // Priority queue of histogram pairs. Its size of 'kHistoQueueSize'
// impacts the quality of the compression and the speed: the smaller the
// faster but the worse for the compression.
HistoQueue histo_queue;
- const int kHistoQueueSizeSqrt = 3;
+ const int kHistoQueueSize = 9;
int ok = 0;
+ // mapping from an index in image_histo with no NULL histogram to the full
+ // blown image_histo.
+ int* mappings;
- if (!HistoQueueInit(&histo_queue, kHistoQueueSizeSqrt)) {
+ if (*num_used < min_cluster_size) {
+ *do_greedy = 1;
+ return 1;
+ }
+
+ mappings = (int*) WebPSafeMalloc(*num_used, sizeof(*mappings));
+ if (mappings == NULL || !HistoQueueInit(&histo_queue, kHistoQueueSize)) {
goto End;
}
+ // Fill the initial mapping.
+ for (j = 0, iter = 0; iter < image_histo->size; ++iter) {
+ if (histograms[iter] == NULL) continue;
+ mappings[j++] = iter;
+ }
+ assert(j == *num_used);
+
// Collapse similar histograms in 'image_histo'.
- ++min_cluster_size;
- for (iter = 0; iter < outer_iters && image_histo_size >= min_cluster_size &&
- ++tries_with_no_success < num_tries_no_success;
+ for (iter = 0;
+ iter < outer_iters && *num_used >= min_cluster_size &&
+ ++tries_with_no_success < num_tries_no_success;
++iter) {
+ int* mapping_index;
double best_cost =
(histo_queue.size == 0) ? 0. : histo_queue.queue[0].cost_diff;
int best_idx1 = -1, best_idx2 = 1;
- int j;
- const uint32_t rand_range = (image_histo_size - 1) * image_histo_size;
- // image_histo_size / 2 was chosen empirically. Less means faster but worse
+ const uint32_t rand_range = (*num_used - 1) * (*num_used);
+ // (*num_used) / 2 was chosen empirically. Less means faster but worse
// compression.
- const int num_tries = image_histo_size / 2;
+ const int num_tries = (*num_used) / 2;
- for (j = 0; j < num_tries; ++j) {
+ // Pick random samples.
+ for (j = 0; *num_used >= 2 && j < num_tries; ++j) {
double curr_cost;
// Choose two different histograms at random and try to combine them.
const uint32_t tmp = MyRand(&seed) % rand_range;
- const uint32_t idx1 = tmp / (image_histo_size - 1);
- uint32_t idx2 = tmp % (image_histo_size - 1);
+ uint32_t idx1 = tmp / (*num_used - 1);
+ uint32_t idx2 = tmp % (*num_used - 1);
if (idx2 >= idx1) ++idx2;
+ idx1 = mappings[idx1];
+ idx2 = mappings[idx2];
// Calculate cost reduction on combination.
curr_cost =
@@ -934,18 +975,21 @@ static int HistogramCombineStochastic(VP8LHistogramSet* const image_histo,
}
if (histo_queue.size == 0) continue;
- // Merge the two best histograms.
+ // Get the best histograms.
best_idx1 = histo_queue.queue[0].idx1;
best_idx2 = histo_queue.queue[0].idx2;
assert(best_idx1 < best_idx2);
- HistogramAddEval(histograms[best_idx1], histograms[best_idx2],
- histograms[best_idx1], 0);
- // Swap the best_idx2 histogram with the last one (which is now unused).
- --image_histo_size;
- if (best_idx2 != image_histo_size) {
- HistogramSwap(&histograms[image_histo_size], &histograms[best_idx2]);
- }
- histograms[image_histo_size] = NULL;
+ // Pop best_idx2 from mappings.
+ mapping_index = (int*) bsearch(&best_idx2, mappings, *num_used,
+ sizeof(best_idx2), &PairComparison);
+ assert(mapping_index != NULL);
+ memmove(mapping_index, mapping_index + 1, sizeof(*mapping_index) *
+ ((*num_used) - (mapping_index - mappings) - 1));
+ // Merge the histograms and remove best_idx2 from the queue.
+ HistogramAdd(histograms[best_idx2], histograms[best_idx1],
+ histograms[best_idx1]);
+ histograms[best_idx1]->bit_cost_ = histo_queue.queue[0].cost_combo;
+ HistogramSetRemoveHistogram(image_histo, best_idx2, num_used);
// Parse the queue and update each pair that deals with best_idx1,
// best_idx2 or image_histo_size.
for (j = 0; j < histo_queue.size;) {
@@ -968,12 +1012,6 @@ static int HistogramCombineStochastic(VP8LHistogramSet* const image_histo,
p->idx2 = best_idx1;
do_eval = 1;
}
- if (p->idx2 == image_histo_size) {
- // No need to re-evaluate here as it does not involve a pair
- // containing best_idx1 or best_idx2.
- p->idx2 = best_idx2;
- }
- assert(p->idx2 < image_histo_size);
// Make sure the index order is respected.
if (p->idx1 > p->idx2) {
const int tmp = p->idx2;
@@ -991,15 +1029,14 @@ static int HistogramCombineStochastic(VP8LHistogramSet* const image_histo,
HistoQueueUpdateHead(&histo_queue, p);
++j;
}
-
tries_with_no_success = 0;
}
- image_histo->size = image_histo_size;
- *do_greedy = (image_histo->size <= min_cluster_size);
+ *do_greedy = (*num_used <= min_cluster_size);
ok = 1;
End:
HistoQueueClear(&histo_queue);
+ WebPSafeFree(mappings);
return ok;
}
@@ -1007,23 +1044,29 @@ End:
// Histogram refinement
// Find the best 'out' histogram for each of the 'in' histograms.
+// At call-time, 'out' contains the histograms of the clusters.
// Note: we assume that out[]->bit_cost_ is already up-to-date.
static void HistogramRemap(const VP8LHistogramSet* const in,
- const VP8LHistogramSet* const out,
+ VP8LHistogramSet* const out,
uint16_t* const symbols) {
int i;
VP8LHistogram** const in_histo = in->histograms;
VP8LHistogram** const out_histo = out->histograms;
- const int in_size = in->size;
+ const int in_size = out->max_size;
const int out_size = out->size;
if (out_size > 1) {
for (i = 0; i < in_size; ++i) {
int best_out = 0;
double best_bits = MAX_COST;
int k;
+ if (in_histo[i] == NULL) {
+ // Arbitrarily set to the previous value if unused to help future LZ77.
+ symbols[i] = symbols[i - 1];
+ continue;
+ }
for (k = 0; k < out_size; ++k) {
- const double cur_bits =
- HistogramAddThresh(out_histo[k], in_histo[i], best_bits);
+ double cur_bits;
+ cur_bits = HistogramAddThresh(out_histo[k], in_histo[i], best_bits);
if (k == 0 || cur_bits < best_bits) {
best_bits = cur_bits;
best_out = k;
@@ -1039,12 +1082,13 @@ static void HistogramRemap(const VP8LHistogramSet* const in,
}
// Recompute each out based on raw and symbols.
- for (i = 0; i < out_size; ++i) {
- HistogramClear(out_histo[i]);
- }
+ VP8LHistogramSetClear(out);
+ out->size = out_size;
for (i = 0; i < in_size; ++i) {
- const int idx = symbols[i];
+ int idx;
+ if (in_histo[i] == NULL) continue;
+ idx = symbols[i];
HistogramAdd(in_histo[i], out_histo[idx], out_histo[idx]);
}
}
@@ -1060,6 +1104,70 @@ static double GetCombineCostFactor(int histo_size, int quality) {
return combine_cost_factor;
}
+// Given a HistogramSet 'set', the mapping of clusters 'cluster_mapping' and the
+// current assignment of the cells in 'symbols', merge the clusters and
+// assign the smallest possible clusters values.
+static void OptimizeHistogramSymbols(const VP8LHistogramSet* const set,
+ uint16_t* const cluster_mappings,
+ int num_clusters,
+ uint16_t* const cluster_mappings_tmp,
+ uint16_t* const symbols) {
+ int i, cluster_max;
+ int do_continue = 1;
+ // First, assign the lowest cluster to each pixel.
+ while (do_continue) {
+ do_continue = 0;
+ for (i = 0; i < num_clusters; ++i) {
+ int k;
+ k = cluster_mappings[i];
+ while (k != cluster_mappings[k]) {
+ cluster_mappings[k] = cluster_mappings[cluster_mappings[k]];
+ k = cluster_mappings[k];
+ }
+ if (k != cluster_mappings[i]) {
+ do_continue = 1;
+ cluster_mappings[i] = k;
+ }
+ }
+ }
+ // Create a mapping from a cluster id to its minimal version.
+ cluster_max = 0;
+ memset(cluster_mappings_tmp, 0,
+ set->max_size * sizeof(*cluster_mappings_tmp));
+ assert(cluster_mappings[0] == 0);
+ // Re-map the ids.
+ for (i = 0; i < set->max_size; ++i) {
+ int cluster;
+ if (symbols[i] == kInvalidHistogramSymbol) continue;
+ cluster = cluster_mappings[symbols[i]];
+ assert(symbols[i] < num_clusters);
+ if (cluster > 0 && cluster_mappings_tmp[cluster] == 0) {
+ ++cluster_max;
+ cluster_mappings_tmp[cluster] = cluster_max;
+ }
+ symbols[i] = cluster_mappings_tmp[cluster];
+ }
+
+ // Make sure all cluster values are used.
+ cluster_max = 0;
+ for (i = 0; i < set->max_size; ++i) {
+ if (symbols[i] == kInvalidHistogramSymbol) continue;
+ if (symbols[i] <= cluster_max) continue;
+ ++cluster_max;
+ assert(symbols[i] == cluster_max);
+ }
+}
+
+static void RemoveEmptyHistograms(VP8LHistogramSet* const image_histo) {
+ uint32_t size;
+ int i;
+ for (i = 0, size = 0; i < image_histo->size; ++i) {
+ if (image_histo->histograms[i] == NULL) continue;
+ image_histo->histograms[size++] = image_histo->histograms[i];
+ }
+ image_histo->size = size;
+}
+
int VP8LGetHistoImageSymbols(int xsize, int ysize,
const VP8LBackwardRefs* const refs,
int quality, int low_effort,
@@ -1078,27 +1186,36 @@ int VP8LGetHistoImageSymbols(int xsize, int ysize,
// maximum quality q==100 (to preserve the compression gains at that level).
const int entropy_combine_num_bins = low_effort ? NUM_PARTITIONS : BIN_SIZE;
int entropy_combine;
-
- if (orig_histo == NULL) goto Error;
+ uint16_t* const map_tmp =
+ WebPSafeMalloc(2 * image_histo_raw_size, sizeof(map_tmp));
+ uint16_t* const cluster_mappings = map_tmp + image_histo_raw_size;
+ int num_used = image_histo_raw_size;
+ if (orig_histo == NULL || map_tmp == NULL) goto Error;
// Construct the histograms from backward references.
HistogramBuild(xsize, histo_bits, refs, orig_histo);
// Copies the histograms and computes its bit_cost.
- HistogramCopyAndAnalyze(orig_histo, image_histo);
+ // histogram_symbols is optimized
+ HistogramCopyAndAnalyze(orig_histo, image_histo, &num_used,
+ histogram_symbols);
+
entropy_combine =
- (image_histo->size > entropy_combine_num_bins * 2) && (quality < 100);
+ (num_used > entropy_combine_num_bins * 2) && (quality < 100);
+
if (entropy_combine) {
- const int bin_map_size = image_histo->size;
- // Reuse histogram_symbols storage. By definition, it's guaranteed to be ok.
- uint16_t* const bin_map = histogram_symbols;
+ uint16_t* const bin_map = map_tmp;
const double combine_cost_factor =
GetCombineCostFactor(image_histo_raw_size, quality);
+ const uint32_t num_clusters = num_used;
HistogramAnalyzeEntropyBin(image_histo, bin_map, low_effort);
// Collapse histograms with similar entropy.
- HistogramCombineEntropyBin(image_histo, tmp_histo, bin_map, bin_map_size,
+ HistogramCombineEntropyBin(image_histo, &num_used, histogram_symbols,
+ cluster_mappings, tmp_histo, bin_map,
entropy_combine_num_bins, combine_cost_factor,
low_effort);
+ OptimizeHistogramSymbols(image_histo, cluster_mappings, num_clusters,
+ map_tmp, histogram_symbols);
}
// Don't combine the histograms using stochastic and greedy heuristics for
@@ -1108,21 +1225,26 @@ int VP8LGetHistoImageSymbols(int xsize, int ysize,
// cubic ramp between 1 and MAX_HISTO_GREEDY:
const int threshold_size = (int)(1 + (x * x * x) * (MAX_HISTO_GREEDY - 1));
int do_greedy;
- if (!HistogramCombineStochastic(image_histo, threshold_size, &do_greedy)) {
+ if (!HistogramCombineStochastic(image_histo, &num_used, threshold_size,
+ &do_greedy)) {
goto Error;
}
- if (do_greedy && !HistogramCombineGreedy(image_histo)) {
- goto Error;
+ if (do_greedy) {
+ RemoveEmptyHistograms(image_histo);
+ if (!HistogramCombineGreedy(image_histo, &num_used)) {
+ goto Error;
+ }
}
}
- // TODO(vrabaud): Optimize HistogramRemap for low-effort compression mode.
// Find the optimal map from original histograms to the final ones.
+ RemoveEmptyHistograms(image_histo);
HistogramRemap(orig_histo, image_histo, histogram_symbols);
ok = 1;
Error:
VP8LFreeHistogramSet(orig_histo);
+ WebPSafeFree(map_tmp);
return ok;
}
diff --git a/thirdparty/libwebp/src/enc/predictor_enc.c b/thirdparty/libwebp/src/enc/predictor_enc.c
index f3715f515e..802e89693e 100644
--- a/thirdparty/libwebp/src/enc/predictor_enc.c
+++ b/thirdparty/libwebp/src/enc/predictor_enc.c
@@ -177,12 +177,15 @@ static uint8_t NearLosslessComponent(uint8_t value, uint8_t predict,
}
}
+static WEBP_INLINE uint8_t NearLosslessDiff(uint8_t a, uint8_t b) {
+ return (uint8_t)((((int)(a) - (int)(b))) & 0xff);
+}
+
// Quantize every component of the difference between the actual pixel value and
// its prediction to a multiple of a quantization (a power of 2, not larger than
// max_quantization which is a power of 2, smaller than max_diff). Take care if
// value and predict have undergone subtract green, which means that red and
// blue are represented as offsets from green.
-#define NEAR_LOSSLESS_DIFF(a, b) (uint8_t)((((int)(a) - (int)(b))) & 0xff)
static uint32_t NearLossless(uint32_t value, uint32_t predict,
int max_quantization, int max_diff,
int used_subtract_green) {
@@ -199,7 +202,7 @@ static uint32_t NearLossless(uint32_t value, uint32_t predict,
}
if ((value >> 24) == 0 || (value >> 24) == 0xff) {
// Preserve transparency of fully transparent or fully opaque pixels.
- a = NEAR_LOSSLESS_DIFF(value >> 24, predict >> 24);
+ a = NearLosslessDiff(value >> 24, predict >> 24);
} else {
a = NearLosslessComponent(value >> 24, predict >> 24, 0xff, quantization);
}
@@ -212,16 +215,15 @@ static uint32_t NearLossless(uint32_t value, uint32_t predict,
// The amount by which green has been adjusted during quantization. It is
// subtracted from red and blue for compensation, to avoid accumulating two
// quantization errors in them.
- green_diff = NEAR_LOSSLESS_DIFF(new_green, value >> 8);
+ green_diff = NearLosslessDiff(new_green, value >> 8);
}
- r = NearLosslessComponent(NEAR_LOSSLESS_DIFF(value >> 16, green_diff),
+ r = NearLosslessComponent(NearLosslessDiff(value >> 16, green_diff),
(predict >> 16) & 0xff, 0xff - new_green,
quantization);
- b = NearLosslessComponent(NEAR_LOSSLESS_DIFF(value, green_diff),
+ b = NearLosslessComponent(NearLosslessDiff(value, green_diff),
predict & 0xff, 0xff - new_green, quantization);
return ((uint32_t)a << 24) | ((uint32_t)r << 16) | ((uint32_t)g << 8) | b;
}
-#undef NEAR_LOSSLESS_DIFF
#endif // (WEBP_NEAR_LOSSLESS == 1)
// Stores the difference between the pixel and its prediction in "out".
diff --git a/thirdparty/libwebp/src/enc/quant_enc.c b/thirdparty/libwebp/src/enc/quant_enc.c
index 35bfaf21ef..03c682e3ae 100644
--- a/thirdparty/libwebp/src/enc/quant_enc.c
+++ b/thirdparty/libwebp/src/enc/quant_enc.c
@@ -15,6 +15,7 @@
#include <math.h>
#include <stdlib.h> // for abs()
+#include "src/dsp/quant.h"
#include "src/enc/vp8i_enc.h"
#include "src/enc/cost_enc.h"
@@ -977,19 +978,6 @@ static void SwapOut(VP8EncIterator* const it) {
SwapPtr(&it->yuv_out_, &it->yuv_out2_);
}
-static score_t IsFlat(const int16_t* levels, int num_blocks, score_t thresh) {
- score_t score = 0;
- while (num_blocks-- > 0) { // TODO(skal): refine positional scoring?
- int i;
- for (i = 1; i < 16; ++i) { // omit DC, we're only interested in AC
- score += (levels[i] != 0);
- if (score > thresh) return 0;
- }
- levels += 16;
- }
- return 1;
-}
-
static void PickBestIntra16(VP8EncIterator* const it, VP8ModeScore* rd) {
const int kNumBlocks = 16;
VP8SegmentInfo* const dqm = &it->enc_->dqm_[it->mb_->segment_];
diff --git a/thirdparty/libwebp/src/enc/vp8i_enc.h b/thirdparty/libwebp/src/enc/vp8i_enc.h
index 92439febb8..3a1967da88 100644
--- a/thirdparty/libwebp/src/enc/vp8i_enc.h
+++ b/thirdparty/libwebp/src/enc/vp8i_enc.h
@@ -32,7 +32,7 @@ extern "C" {
// version numbers
#define ENC_MAJ_VERSION 1
#define ENC_MIN_VERSION 0
-#define ENC_REV_VERSION 1
+#define ENC_REV_VERSION 2
enum { MAX_LF_LEVELS = 64, // Maximum loop filter level
MAX_VARIABLE_LEVEL = 67, // last (inclusive) level with variable cost
diff --git a/thirdparty/libwebp/src/enc/vp8l_enc.c b/thirdparty/libwebp/src/enc/vp8l_enc.c
index 2713edcd95..2efd403f77 100644
--- a/thirdparty/libwebp/src/enc/vp8l_enc.c
+++ b/thirdparty/libwebp/src/enc/vp8l_enc.c
@@ -462,6 +462,7 @@ static int GetHuffBitLengthsAndCodes(
for (i = 0; i < histogram_image_size; ++i) {
const VP8LHistogram* const histo = histogram_image->histograms[i];
HuffmanTreeCode* const codes = &huffman_codes[5 * i];
+ assert(histo != NULL);
for (k = 0; k < 5; ++k) {
const int num_symbols =
(k == 0) ? VP8LHistogramNumCodes(histo->palette_code_bits_) :
diff --git a/thirdparty/libwebp/src/mux/muxi.h b/thirdparty/libwebp/src/mux/muxi.h
index df9f74c63c..3e9d8c48d8 100644
--- a/thirdparty/libwebp/src/mux/muxi.h
+++ b/thirdparty/libwebp/src/mux/muxi.h
@@ -29,7 +29,7 @@ extern "C" {
#define MUX_MAJ_VERSION 1
#define MUX_MIN_VERSION 0
-#define MUX_REV_VERSION 1
+#define MUX_REV_VERSION 2
// Chunk object.
typedef struct WebPChunk WebPChunk;
diff --git a/thirdparty/libwebp/src/utils/bit_writer_utils.c b/thirdparty/libwebp/src/utils/bit_writer_utils.c
index f4f476ce3f..7f83b4c8a2 100644
--- a/thirdparty/libwebp/src/utils/bit_writer_utils.c
+++ b/thirdparty/libwebp/src/utils/bit_writer_utils.c
@@ -248,6 +248,7 @@ int VP8LBitWriterClone(const VP8LBitWriter* const src,
dst->bits_ = src->bits_;
dst->used_ = src->used_;
dst->error_ = src->error_;
+ dst->cur_ = dst->buf_ + current_size;
return 1;
}
diff --git a/thirdparty/libwebp/src/utils/utils.h b/thirdparty/libwebp/src/utils/utils.h
index da97b5d38f..c7620f91ec 100644
--- a/thirdparty/libwebp/src/utils/utils.h
+++ b/thirdparty/libwebp/src/utils/utils.h
@@ -107,19 +107,6 @@ static WEBP_INLINE void PutLE32(uint8_t* const data, uint32_t val) {
PutLE16(data + 2, (int)(val >> 16));
}
-// Returns 31 ^ clz(n) = log2(n). This is the default C-implementation, either
-// based on table or not. Can be used as fallback if clz() is not available.
-#define WEBP_NEED_LOG_TABLE_8BIT
-extern const uint8_t WebPLogTable8bit[256];
-static WEBP_INLINE int WebPLog2FloorC(uint32_t n) {
- int log_value = 0;
- while (n >= 256) {
- log_value += 8;
- n >>= 8;
- }
- return log_value + WebPLogTable8bit[n];
-}
-
// Returns (int)floor(log2(n)). n must be > 0.
// use GNU builtins where available.
#if defined(__GNUC__) && \
@@ -138,6 +125,19 @@ static WEBP_INLINE int BitsLog2Floor(uint32_t n) {
return first_set_bit;
}
#else // default: use the C-version.
+// Returns 31 ^ clz(n) = log2(n). This is the default C-implementation, either
+// based on table or not. Can be used as fallback if clz() is not available.
+#define WEBP_NEED_LOG_TABLE_8BIT
+extern const uint8_t WebPLogTable8bit[256];
+static WEBP_INLINE int WebPLog2FloorC(uint32_t n) {
+ int log_value = 0;
+ while (n >= 256) {
+ log_value += 8;
+ n >>= 8;
+ }
+ return log_value + WebPLogTable8bit[n];
+}
+
static WEBP_INLINE int BitsLog2Floor(uint32_t n) { return WebPLog2FloorC(n); }
#endif
diff --git a/thirdparty/libwebp/src/webp/decode.h b/thirdparty/libwebp/src/webp/decode.h
index 95d31e7619..ae8bfe840e 100644
--- a/thirdparty/libwebp/src/webp/decode.h
+++ b/thirdparty/libwebp/src/webp/decode.h
@@ -42,6 +42,12 @@ WEBP_EXTERN int WebPGetDecoderVersion(void);
// This function will also validate the header, returning true on success,
// false otherwise. '*width' and '*height' are only valid on successful return.
// Pointers 'width' and 'height' can be passed NULL if deemed irrelevant.
+// Note: The following chunk sequences (before the raw VP8/VP8L data) are
+// considered valid by this function:
+// RIFF + VP8(L)
+// RIFF + VP8X + (optional chunks) + VP8(L)
+// ALPH + VP8 <-- Not a valid WebP format: only allowed for internal purpose.
+// VP8(L) <-- Not a valid WebP format: only allowed for internal purpose.
WEBP_EXTERN int WebPGetInfo(const uint8_t* data, size_t data_size,
int* width, int* height);
@@ -425,6 +431,12 @@ WEBP_EXTERN VP8StatusCode WebPGetFeaturesInternal(
// Returns VP8_STATUS_OK when the features are successfully retrieved. Returns
// VP8_STATUS_NOT_ENOUGH_DATA when more data is needed to retrieve the
// features from headers. Returns error in other cases.
+// Note: The following chunk sequences (before the raw VP8/VP8L data) are
+// considered valid by this function:
+// RIFF + VP8(L)
+// RIFF + VP8X + (optional chunks) + VP8(L)
+// ALPH + VP8 <-- Not a valid WebP format: only allowed for internal purpose.
+// VP8(L) <-- Not a valid WebP format: only allowed for internal purpose.
static WEBP_INLINE VP8StatusCode WebPGetFeatures(
const uint8_t* data, size_t data_size,
WebPBitstreamFeatures* features) {
diff --git a/thirdparty/libwebsockets/ipv6_fixes.diff b/thirdparty/libwebsockets/ipv6_fixes.diff
new file mode 100644
index 0000000000..fe3e5e4b63
--- /dev/null
+++ b/thirdparty/libwebsockets/ipv6_fixes.diff
@@ -0,0 +1,32 @@
+diff --git a/thirdparty/libwebsockets/plat/lws-plat-unix.c b/thirdparty/libwebsockets/plat/lws-plat-unix.c
+index 7dba3bd82..d1bca8b5d 100644
+--- a/thirdparty/libwebsockets/plat/lws-plat-unix.c
++++ b/thirdparty/libwebsockets/plat/lws-plat-unix.c
+@@ -328,6 +328,11 @@ lws_plat_set_socket_options(struct lws_vhost *vhost, int fd)
+ int optval = 1;
+ socklen_t optlen = sizeof(optval);
+
++#ifdef LWS_WITH_IPV6
++ optval = 0;
++ setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (const void*)&optval, optlen);
++#endif
++
+ #if defined(__APPLE__) || \
+ defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
+ defined(__NetBSD__) || \
+diff --git a/thirdparty/libwebsockets/plat/lws-plat-win.c b/thirdparty/libwebsockets/plat/lws-plat-win.c
+index 1850b6425..26caab2cd 100644
+--- a/thirdparty/libwebsockets/plat/lws-plat-win.c
++++ b/thirdparty/libwebsockets/plat/lws-plat-win.c
+@@ -348,6 +348,11 @@ lws_plat_set_socket_options(struct lws_vhost *vhost, lws_sockfd_type fd)
+ struct protoent *tcp_proto;
+ #endif
+
++#ifdef LWS_WITH_IPV6
++ optval = 0;
++ setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (const void*)&optval, optlen);
++#endif
++
+ if (vhost->ka_time) {
+ /* enable keepalive on this socket */
+ optval = 1;
diff --git a/thirdparty/libwebsockets/lws_config.h b/thirdparty/libwebsockets/lws_config.h
index 86ce9ac38a..fdf02157cc 100644
--- a/thirdparty/libwebsockets/lws_config.h
+++ b/thirdparty/libwebsockets/lws_config.h
@@ -77,7 +77,10 @@
/* #undef LWS_WITH_LIBEVENT */
/* Build with support for ipv6 */
-/* #undef LWS_WITH_IPV6 */
+/* Everywhere, except in OpenBSD which does not support dual stacking */
+#if !defined(__OpenBSD__)
+#define LWS_WITH_IPV6
+#endif
/* Build with support for UNIX domain socket */
/* #undef LWS_WITH_UNIX_SOCK */
diff --git a/thirdparty/libwebsockets/plat/lws-plat-unix.c b/thirdparty/libwebsockets/plat/lws-plat-unix.c
index 7dba3bd82f..d1bca8b5df 100644
--- a/thirdparty/libwebsockets/plat/lws-plat-unix.c
+++ b/thirdparty/libwebsockets/plat/lws-plat-unix.c
@@ -328,6 +328,11 @@ lws_plat_set_socket_options(struct lws_vhost *vhost, int fd)
int optval = 1;
socklen_t optlen = sizeof(optval);
+#ifdef LWS_WITH_IPV6
+ optval = 0;
+ setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (const void*)&optval, optlen);
+#endif
+
#if defined(__APPLE__) || \
defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
defined(__NetBSD__) || \
diff --git a/thirdparty/libwebsockets/plat/lws-plat-win.c b/thirdparty/libwebsockets/plat/lws-plat-win.c
index 1850b64250..26caab2cde 100644
--- a/thirdparty/libwebsockets/plat/lws-plat-win.c
+++ b/thirdparty/libwebsockets/plat/lws-plat-win.c
@@ -348,6 +348,11 @@ lws_plat_set_socket_options(struct lws_vhost *vhost, lws_sockfd_type fd)
struct protoent *tcp_proto;
#endif
+#ifdef LWS_WITH_IPV6
+ optval = 0;
+ setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (const void*)&optval, optlen);
+#endif
+
if (vhost->ka_time) {
/* enable keepalive on this socket */
optval = 1;
diff --git a/thirdparty/mbedtls/1453.diff b/thirdparty/mbedtls/1453.diff
index 6630ad861f..b1c9c43ed2 100644
--- a/thirdparty/mbedtls/1453.diff
+++ b/thirdparty/mbedtls/1453.diff
@@ -1,8 +1,8 @@
diff --git a/library/entropy_poll.c b/library/entropy_poll.c
-index 67900c46c8..cefe882d2a 100644
+index 4556f88a5..ba56b70f7 100644
--- a/library/entropy_poll.c
+++ b/library/entropy_poll.c
-@@ -54,28 +54,43 @@
+@@ -61,28 +61,43 @@
#define _WIN32_WINNT 0x0400
#endif
#include <windows.h>
@@ -54,7 +54,7 @@ index 67900c46c8..cefe882d2a 100644
return( 0 );
diff --git a/library/x509_crt.c b/library/x509_crt.c
-index 290c1eb3d1..3cf1743821 100644
+index 76558342e..35a134950 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -65,6 +65,19 @@
@@ -77,20 +77,20 @@ index 290c1eb3d1..3cf1743821 100644
#else
#include <time.h>
#endif
-@@ -1126,6 +1139,7 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path )
+@@ -1278,6 +1291,7 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path )
char filename[MAX_PATH];
char *p;
size_t len = strlen( path );
-+ int length_as_int = 0;
++ int lengthAsInt = 0;
WIN32_FIND_DATAW file_data;
HANDLE hFind;
-@@ -1140,7 +1154,18 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path )
+@@ -1292,7 +1306,18 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path )
p = filename + len;
filename[len++] = '*';
- w_ret = MultiByteToWideChar( CP_ACP, 0, filename, (int)len, szDir,
-+ if ( FAILED ( SizeTToInt( len, &length_as_int ) ) )
++ if ( FAILED ( SizeTToInt( len, &lengthAsInt ) ) )
+ return( MBEDTLS_ERR_X509_FILE_IO_ERROR );
+
+ /*
@@ -101,20 +101,20 @@ index 290c1eb3d1..3cf1743821 100644
+ * incoming string are less than MAX_PATH to avoid a buffer overrun with
+ * MultiByteToWideChar().
+ */
-+ w_ret = MultiByteToWideChar( CP_ACP, 0, filename, length_as_int, szDir,
++ w_ret = MultiByteToWideChar( CP_ACP, 0, filename, lengthAsInt, szDir,
MAX_PATH - 3 );
if( w_ret == 0 )
return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
-@@ -1157,8 +1182,11 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path )
+@@ -1309,8 +1334,11 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path )
if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
continue;
-+ if ( FAILED( SizeTToInt( wcslen( file_data.cFileName ), &length_as_int ) ) )
++ if ( FAILED( SizeTToInt( wcslen( file_data.cFileName ), &lengthAsInt ) ) )
+ return( MBEDTLS_ERR_X509_FILE_IO_ERROR );
+
w_ret = WideCharToMultiByte( CP_ACP, 0, file_data.cFileName,
- lstrlenW( file_data.cFileName ),
-+ length_as_int,
++ lengthAsInt,
p, (int) len - 1,
NULL, NULL );
if( w_ret == 0 )
diff --git a/thirdparty/mbedtls/include/mbedtls/aes.h b/thirdparty/mbedtls/include/mbedtls/aes.h
index f6603d5962..b42e564efc 100644
--- a/thirdparty/mbedtls/include/mbedtls/aes.h
+++ b/thirdparty/mbedtls/include/mbedtls/aes.h
@@ -60,7 +60,11 @@
/* Error codes in range 0x0021-0x0025 */
#define MBEDTLS_ERR_AES_BAD_INPUT_DATA -0x0021 /**< Invalid input data. */
+
+/* MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE is deprecated and should not be used. */
#define MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE -0x0023 /**< Feature not available. For example, an unsupported AES key size. */
+
+/* MBEDTLS_ERR_AES_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_AES_HW_ACCEL_FAILED -0x0025 /**< AES hardware accelerator failed. */
#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
@@ -79,7 +83,7 @@ extern "C" {
/**
* \brief The AES context-type definition.
*/
-typedef struct
+typedef struct mbedtls_aes_context
{
int nr; /*!< The number of rounds. */
uint32_t *rk; /*!< AES round keys. */
@@ -98,7 +102,7 @@ mbedtls_aes_context;
/**
* \brief The AES XTS context-type definition.
*/
-typedef struct
+typedef struct mbedtls_aes_xts_context
{
mbedtls_aes_context crypt; /*!< The AES context to use for AES block
encryption or decryption. */
@@ -117,7 +121,7 @@ typedef struct
* It must be the first API called before using
* the context.
*
- * \param ctx The AES context to initialize.
+ * \param ctx The AES context to initialize. This must not be \c NULL.
*/
void mbedtls_aes_init( mbedtls_aes_context *ctx );
@@ -125,6 +129,8 @@ void mbedtls_aes_init( mbedtls_aes_context *ctx );
* \brief This function releases and clears the specified AES context.
*
* \param ctx The AES context to clear.
+ * If this is \c NULL, this function does nothing.
+ * Otherwise, the context must have been at least initialized.
*/
void mbedtls_aes_free( mbedtls_aes_context *ctx );
@@ -135,7 +141,7 @@ void mbedtls_aes_free( mbedtls_aes_context *ctx );
* It must be the first API called before using
* the context.
*
- * \param ctx The AES XTS context to initialize.
+ * \param ctx The AES XTS context to initialize. This must not be \c NULL.
*/
void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx );
@@ -143,6 +149,8 @@ void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx );
* \brief This function releases and clears the specified AES XTS context.
*
* \param ctx The AES XTS context to clear.
+ * If this is \c NULL, this function does nothing.
+ * Otherwise, the context must have been at least initialized.
*/
void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx );
#endif /* MBEDTLS_CIPHER_MODE_XTS */
@@ -151,7 +159,9 @@ void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx );
* \brief This function sets the encryption key.
*
* \param ctx The AES context to which the key should be bound.
+ * It must be initialized.
* \param key The encryption key.
+ * This must be a readable buffer of size \p keybits bits.
* \param keybits The size of data passed in bits. Valid options are:
* <ul><li>128 bits</li>
* <li>192 bits</li>
@@ -167,7 +177,9 @@ int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key,
* \brief This function sets the decryption key.
*
* \param ctx The AES context to which the key should be bound.
+ * It must be initialized.
* \param key The decryption key.
+ * This must be a readable buffer of size \p keybits bits.
* \param keybits The size of data passed. Valid options are:
* <ul><li>128 bits</li>
* <li>192 bits</li>
@@ -185,8 +197,10 @@ int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key,
* sets the encryption key.
*
* \param ctx The AES XTS context to which the key should be bound.
+ * It must be initialized.
* \param key The encryption key. This is comprised of the XTS key1
* concatenated with the XTS key2.
+ * This must be a readable buffer of size \p keybits bits.
* \param keybits The size of \p key passed in bits. Valid options are:
* <ul><li>256 bits (each of key1 and key2 is a 128-bit key)</li>
* <li>512 bits (each of key1 and key2 is a 256-bit key)</li></ul>
@@ -203,8 +217,10 @@ int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx,
* sets the decryption key.
*
* \param ctx The AES XTS context to which the key should be bound.
+ * It must be initialized.
* \param key The decryption key. This is comprised of the XTS key1
* concatenated with the XTS key2.
+ * This must be a readable buffer of size \p keybits bits.
* \param keybits The size of \p key passed in bits. Valid options are:
* <ul><li>256 bits (each of key1 and key2 is a 128-bit key)</li>
* <li>512 bits (each of key1 and key2 is a 256-bit key)</li></ul>
@@ -230,10 +246,13 @@ int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx,
* call to this API with the same context.
*
* \param ctx The AES context to use for encryption or decryption.
+ * It must be initialized and bound to a key.
* \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or
* #MBEDTLS_AES_DECRYPT.
- * \param input The 16-Byte buffer holding the input data.
- * \param output The 16-Byte buffer holding the output data.
+ * \param input The buffer holding the input data.
+ * It must be readable and at least \c 16 Bytes long.
+ * \param output The buffer where the output data will be written.
+ * It must be writeable and at least \c 16 Bytes long.
* \return \c 0 on success.
*/
@@ -256,8 +275,8 @@ int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
* mbedtls_aes_setkey_enc() or mbedtls_aes_setkey_dec() must be called
* before the first call to this API with the same context.
*
- * \note This function operates on aligned blocks, that is, the input size
- * must be a multiple of the AES block size of 16 Bytes.
+ * \note This function operates on full blocks, that is, the input size
+ * must be a multiple of the AES block size of \c 16 Bytes.
*
* \note Upon exit, the content of the IV is updated so that you can
* call the same function again on the next
@@ -268,13 +287,17 @@ int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
*
*
* \param ctx The AES context to use for encryption or decryption.
+ * It must be initialized and bound to a key.
* \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or
* #MBEDTLS_AES_DECRYPT.
* \param length The length of the input data in Bytes. This must be a
- * multiple of the block size (16 Bytes).
+ * multiple of the block size (\c 16 Bytes).
* \param iv Initialization vector (updated after use).
+ * It must be a readable and writeable buffer of \c 16 Bytes.
* \param input The buffer holding the input data.
+ * It must be readable and of size \p length Bytes.
* \param output The buffer holding the output data.
+ * It must be writeable and of size \p length Bytes.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH
@@ -302,9 +325,10 @@ int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx,
* returns #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH.
*
* \param ctx The AES XTS context to use for AES XTS operations.
+ * It must be initialized and bound to a key.
* \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or
* #MBEDTLS_AES_DECRYPT.
- * \param length The length of a data unit in bytes. This can be any
+ * \param length The length of a data unit in Bytes. This can be any
* length between 16 bytes and 2^24 bytes inclusive
* (between 1 and 2^20 block cipher blocks).
* \param data_unit The address of the data unit encoded as an array of 16
@@ -312,15 +336,15 @@ int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx,
* is typically the index of the block device sector that
* contains the data.
* \param input The buffer holding the input data (which is an entire
- * data unit). This function reads \p length bytes from \p
+ * data unit). This function reads \p length Bytes from \p
* input.
* \param output The buffer holding the output data (which is an entire
- * data unit). This function writes \p length bytes to \p
+ * data unit). This function writes \p length Bytes to \p
* output.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH if \p length is
- * smaller than an AES block in size (16 bytes) or if \p
+ * smaller than an AES block in size (16 Bytes) or if \p
* length is larger than 2^20 blocks (16 MiB).
*/
int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx,
@@ -356,13 +380,18 @@ int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx,
*
*
* \param ctx The AES context to use for encryption or decryption.
+ * It must be initialized and bound to a key.
* \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or
* #MBEDTLS_AES_DECRYPT.
- * \param length The length of the input data.
+ * \param length The length of the input data in Bytes.
* \param iv_off The offset in IV (updated after use).
+ * It must point to a valid \c size_t.
* \param iv The initialization vector (updated after use).
+ * It must be a readable and writeable buffer of \c 16 Bytes.
* \param input The buffer holding the input data.
+ * It must be readable and of size \p length Bytes.
* \param output The buffer holding the output data.
+ * It must be writeable and of size \p length Bytes.
*
* \return \c 0 on success.
*/
@@ -397,12 +426,16 @@ int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx,
*
*
* \param ctx The AES context to use for encryption or decryption.
+ * It must be initialized and bound to a key.
* \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or
* #MBEDTLS_AES_DECRYPT
* \param length The length of the input data.
* \param iv The initialization vector (updated after use).
+ * It must be a readable and writeable buffer of \c 16 Bytes.
* \param input The buffer holding the input data.
+ * It must be readable and of size \p length Bytes.
* \param output The buffer holding the output data.
+ * It must be writeable and of size \p length Bytes.
*
* \return \c 0 on success.
*/
@@ -447,11 +480,16 @@ int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx,
* will compromise security.
*
* \param ctx The AES context to use for encryption or decryption.
+ * It must be initialized and bound to a key.
* \param length The length of the input data.
* \param iv_off The offset in IV (updated after use).
+ * It must point to a valid \c size_t.
* \param iv The initialization vector (updated after use).
+ * It must be a readable and writeable buffer of \c 16 Bytes.
* \param input The buffer holding the input data.
+ * It must be readable and of size \p length Bytes.
* \param output The buffer holding the output data.
+ * It must be writeable and of size \p length Bytes.
*
* \return \c 0 on success.
*/
@@ -523,15 +561,21 @@ int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx,
* securely discarded as soon as it's no longer needed.
*
* \param ctx The AES context to use for encryption or decryption.
+ * It must be initialized and bound to a key.
* \param length The length of the input data.
* \param nc_off The offset in the current \p stream_block, for
* resuming within the current cipher stream. The
* offset pointer should be 0 at the start of a stream.
+ * It must point to a valid \c size_t.
* \param nonce_counter The 128-bit nonce and counter.
+ * It must be a readable-writeable buffer of \c 16 Bytes.
* \param stream_block The saved stream block for resuming. This is
* overwritten by the function.
+ * It must be a readable-writeable buffer of \c 16 Bytes.
* \param input The buffer holding the input data.
+ * It must be readable and of size \p length Bytes.
* \param output The buffer holding the output data.
+ * It must be writeable and of size \p length Bytes.
*
* \return \c 0 on success.
*/
@@ -584,7 +628,7 @@ int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx,
* \brief Deprecated internal AES block encryption function
* without return value.
*
- * \deprecated Superseded by mbedtls_aes_encrypt_ext() in 2.5.0.
+ * \deprecated Superseded by mbedtls_internal_aes_encrypt()
*
* \param ctx The AES context to use for encryption.
* \param input Plaintext block.
@@ -598,7 +642,7 @@ MBEDTLS_DEPRECATED void mbedtls_aes_encrypt( mbedtls_aes_context *ctx,
* \brief Deprecated internal AES block decryption function
* without return value.
*
- * \deprecated Superseded by mbedtls_aes_decrypt_ext() in 2.5.0.
+ * \deprecated Superseded by mbedtls_internal_aes_decrypt()
*
* \param ctx The AES context to use for decryption.
* \param input Ciphertext block.
diff --git a/thirdparty/mbedtls/include/mbedtls/aesni.h b/thirdparty/mbedtls/include/mbedtls/aesni.h
index 746baa0e17..0196f49b87 100644
--- a/thirdparty/mbedtls/include/mbedtls/aesni.h
+++ b/thirdparty/mbedtls/include/mbedtls/aesni.h
@@ -2,6 +2,9 @@
* \file aesni.h
*
* \brief AES-NI for hardware AES acceleration on some Intel processors
+ *
+ * \warning These functions are only for internal use by other library
+ * functions; you must not call them directly.
*/
/*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
@@ -42,7 +45,10 @@ extern "C" {
#endif
/**
- * \brief AES-NI features detection routine
+ * \brief Internal function to detect the AES-NI feature in CPUs.
+ *
+ * \note This function is only for internal use by other library
+ * functions; you must not call it directly.
*
* \param what The feature to detect
* (MBEDTLS_AESNI_AES or MBEDTLS_AESNI_CLMUL)
@@ -52,7 +58,10 @@ extern "C" {
int mbedtls_aesni_has_support( unsigned int what );
/**
- * \brief AES-NI AES-ECB block en(de)cryption
+ * \brief Internal AES-NI AES-ECB block encryption and decryption
+ *
+ * \note This function is only for internal use by other library
+ * functions; you must not call it directly.
*
* \param ctx AES context
* \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
@@ -62,12 +71,15 @@ int mbedtls_aesni_has_support( unsigned int what );
* \return 0 on success (cannot fail)
*/
int mbedtls_aesni_crypt_ecb( mbedtls_aes_context *ctx,
- int mode,
- const unsigned char input[16],
- unsigned char output[16] );
+ int mode,
+ const unsigned char input[16],
+ unsigned char output[16] );
/**
- * \brief GCM multiplication: c = a * b in GF(2^128)
+ * \brief Internal GCM multiplication: c = a * b in GF(2^128)
+ *
+ * \note This function is only for internal use by other library
+ * functions; you must not call it directly.
*
* \param c Result
* \param a First operand
@@ -77,21 +89,29 @@ int mbedtls_aesni_crypt_ecb( mbedtls_aes_context *ctx,
* elements of GF(2^128) as per the GCM spec.
*/
void mbedtls_aesni_gcm_mult( unsigned char c[16],
- const unsigned char a[16],
- const unsigned char b[16] );
+ const unsigned char a[16],
+ const unsigned char b[16] );
/**
- * \brief Compute decryption round keys from encryption round keys
+ * \brief Internal round key inversion. This function computes
+ * decryption round keys from the encryption round keys.
+ *
+ * \note This function is only for internal use by other library
+ * functions; you must not call it directly.
*
* \param invkey Round keys for the equivalent inverse cipher
* \param fwdkey Original round keys (for encryption)
* \param nr Number of rounds (that is, number of round keys minus one)
*/
void mbedtls_aesni_inverse_key( unsigned char *invkey,
- const unsigned char *fwdkey, int nr );
+ const unsigned char *fwdkey,
+ int nr );
/**
- * \brief Perform key expansion (for encryption)
+ * \brief Internal key expansion for encryption
+ *
+ * \note This function is only for internal use by other library
+ * functions; you must not call it directly.
*
* \param rk Destination buffer where the round keys are written
* \param key Encryption key
@@ -100,8 +120,8 @@ void mbedtls_aesni_inverse_key( unsigned char *invkey,
* \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH
*/
int mbedtls_aesni_setkey_enc( unsigned char *rk,
- const unsigned char *key,
- size_t bits );
+ const unsigned char *key,
+ size_t bits );
#ifdef __cplusplus
}
diff --git a/thirdparty/mbedtls/include/mbedtls/arc4.h b/thirdparty/mbedtls/include/mbedtls/arc4.h
index f11fc5be0a..c43f4065f1 100644
--- a/thirdparty/mbedtls/include/mbedtls/arc4.h
+++ b/thirdparty/mbedtls/include/mbedtls/arc4.h
@@ -36,6 +36,7 @@
#include <stddef.h>
+/* MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED -0x0019 /**< ARC4 hardware accelerator failed. */
#ifdef __cplusplus
@@ -53,7 +54,7 @@ extern "C" {
* security risk. We recommend considering stronger ciphers instead.
*
*/
-typedef struct
+typedef struct mbedtls_arc4_context
{
int x; /*!< permutation index */
int y; /*!< permutation index */
diff --git a/thirdparty/mbedtls/include/mbedtls/aria.h b/thirdparty/mbedtls/include/mbedtls/aria.h
index bae0621b23..1e8956ed13 100644
--- a/thirdparty/mbedtls/include/mbedtls/aria.h
+++ b/thirdparty/mbedtls/include/mbedtls/aria.h
@@ -39,6 +39,8 @@
#include <stddef.h>
#include <stdint.h>
+#include "platform_util.h"
+
#define MBEDTLS_ARIA_ENCRYPT 1 /**< ARIA encryption. */
#define MBEDTLS_ARIA_DECRYPT 0 /**< ARIA decryption. */
@@ -46,9 +48,18 @@
#define MBEDTLS_ARIA_MAX_ROUNDS 16 /**< Maxiumum number of rounds in ARIA. */
#define MBEDTLS_ARIA_MAX_KEYSIZE 32 /**< Maximum size of an ARIA key in bytes. */
-#define MBEDTLS_ERR_ARIA_INVALID_KEY_LENGTH -0x005C /**< Invalid key length. */
-#define MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH -0x005E /**< Invalid data input length. */
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+#define MBEDTLS_ERR_ARIA_INVALID_KEY_LENGTH MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( -0x005C )
+#endif /* !MBEDTLS_DEPRECATED_REMOVED */
+#define MBEDTLS_ERR_ARIA_BAD_INPUT_DATA -0x005C /**< Bad input data. */
+
+#define MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH -0x005E /**< Invalid data input length. */
+
+/* MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE is deprecated and should not be used.
+ */
#define MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE -0x005A /**< Feature not available. For example, an unsupported ARIA key size. */
+
+/* MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED -0x0058 /**< ARIA hardware accelerator failed. */
#if !defined(MBEDTLS_ARIA_ALT)
@@ -62,7 +73,7 @@ extern "C" {
/**
* \brief The ARIA context-type definition.
*/
-typedef struct
+typedef struct mbedtls_aria_context
{
unsigned char nr; /*!< The number of rounds (12, 14 or 16) */
/*! The ARIA round keys. */
@@ -80,14 +91,16 @@ mbedtls_aria_context;
* It must be the first API called before using
* the context.
*
- * \param ctx The ARIA context to initialize.
+ * \param ctx The ARIA context to initialize. This must not be \c NULL.
*/
void mbedtls_aria_init( mbedtls_aria_context *ctx );
/**
* \brief This function releases and clears the specified ARIA context.
*
- * \param ctx The ARIA context to clear.
+ * \param ctx The ARIA context to clear. This may be \c NULL, in which
+ * case this function returns immediately. If it is not \c NULL,
+ * it must point to an initialized ARIA context.
*/
void mbedtls_aria_free( mbedtls_aria_context *ctx );
@@ -95,14 +108,16 @@ void mbedtls_aria_free( mbedtls_aria_context *ctx );
* \brief This function sets the encryption key.
*
* \param ctx The ARIA context to which the key should be bound.
- * \param key The encryption key.
- * \param keybits The size of data passed in bits. Valid options are:
+ * This must be initialized.
+ * \param key The encryption key. This must be a readable buffer
+ * of size \p keybits Bits.
+ * \param keybits The size of \p key in Bits. Valid options are:
* <ul><li>128 bits</li>
* <li>192 bits</li>
* <li>256 bits</li></ul>
*
- * \return \c 0 on success or #MBEDTLS_ERR_ARIA_INVALID_KEY_LENGTH
- * on failure.
+ * \return \c 0 on success.
+ * \return A negative error code on failure.
*/
int mbedtls_aria_setkey_enc( mbedtls_aria_context *ctx,
const unsigned char *key,
@@ -112,13 +127,16 @@ int mbedtls_aria_setkey_enc( mbedtls_aria_context *ctx,
* \brief This function sets the decryption key.
*
* \param ctx The ARIA context to which the key should be bound.
- * \param key The decryption key.
+ * This must be initialized.
+ * \param key The decryption key. This must be a readable buffer
+ * of size \p keybits Bits.
* \param keybits The size of data passed. Valid options are:
* <ul><li>128 bits</li>
* <li>192 bits</li>
* <li>256 bits</li></ul>
*
- * \return \c 0 on success, or #MBEDTLS_ERR_ARIA_INVALID_KEY_LENGTH on failure.
+ * \return \c 0 on success.
+ * \return A negative error code on failure.
*/
int mbedtls_aria_setkey_dec( mbedtls_aria_context *ctx,
const unsigned char *key,
@@ -137,10 +155,12 @@ int mbedtls_aria_setkey_dec( mbedtls_aria_context *ctx,
* call to this API with the same context.
*
* \param ctx The ARIA context to use for encryption or decryption.
+ * This must be initialized and bound to a key.
* \param input The 16-Byte buffer holding the input data.
* \param output The 16-Byte buffer holding the output data.
* \return \c 0 on success.
+ * \return A negative error code on failure.
*/
int mbedtls_aria_crypt_ecb( mbedtls_aria_context *ctx,
const unsigned char input[MBEDTLS_ARIA_BLOCKSIZE],
@@ -172,16 +192,21 @@ int mbedtls_aria_crypt_ecb( mbedtls_aria_context *ctx,
*
*
* \param ctx The ARIA context to use for encryption or decryption.
- * \param mode The ARIA operation: #MBEDTLS_ARIA_ENCRYPT or
- * #MBEDTLS_ARIA_DECRYPT.
+ * This must be initialized and bound to a key.
+ * \param mode The mode of operation. This must be either
+ * #MBEDTLS_ARIA_ENCRYPT for encryption, or
+ * #MBEDTLS_ARIA_DECRYPT for decryption.
* \param length The length of the input data in Bytes. This must be a
* multiple of the block size (16 Bytes).
* \param iv Initialization vector (updated after use).
- * \param input The buffer holding the input data.
- * \param output The buffer holding the output data.
+ * This must be a readable buffer of size 16 Bytes.
+ * \param input The buffer holding the input data. This must
+ * be a readable buffer of length \p length Bytes.
+ * \param output The buffer holding the output data. This must
+ * be a writable buffer of length \p length Bytes.
*
- * \return \c 0 on success, or #MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH
- * on failure.
+ * \return \c 0 on success.
+ * \return A negative error code on failure.
*/
int mbedtls_aria_crypt_cbc( mbedtls_aria_context *ctx,
int mode,
@@ -216,15 +241,22 @@ int mbedtls_aria_crypt_cbc( mbedtls_aria_context *ctx,
*
*
* \param ctx The ARIA context to use for encryption or decryption.
- * \param mode The ARIA operation: #MBEDTLS_ARIA_ENCRYPT or
- * #MBEDTLS_ARIA_DECRYPT.
- * \param length The length of the input data.
+ * This must be initialized and bound to a key.
+ * \param mode The mode of operation. This must be either
+ * #MBEDTLS_ARIA_ENCRYPT for encryption, or
+ * #MBEDTLS_ARIA_DECRYPT for decryption.
+ * \param length The length of the input data \p input in Bytes.
* \param iv_off The offset in IV (updated after use).
+ * This must not be larger than 15.
* \param iv The initialization vector (updated after use).
- * \param input The buffer holding the input data.
- * \param output The buffer holding the output data.
+ * This must be a readable buffer of size 16 Bytes.
+ * \param input The buffer holding the input data. This must
+ * be a readable buffer of length \p length Bytes.
+ * \param output The buffer holding the output data. This must
+ * be a writable buffer of length \p length Bytes.
*
* \return \c 0 on success.
+ * \return A negative error code on failure.
*/
int mbedtls_aria_crypt_cfb128( mbedtls_aria_context *ctx,
int mode,
@@ -294,17 +326,24 @@ int mbedtls_aria_crypt_cfb128( mbedtls_aria_context *ctx,
* securely discarded as soon as it's no longer needed.
*
* \param ctx The ARIA context to use for encryption or decryption.
- * \param length The length of the input data.
- * \param nc_off The offset in the current \p stream_block, for
- * resuming within the current cipher stream. The
- * offset pointer should be 0 at the start of a stream.
- * \param nonce_counter The 128-bit nonce and counter.
- * \param stream_block The saved stream block for resuming. This is
- * overwritten by the function.
- * \param input The buffer holding the input data.
- * \param output The buffer holding the output data.
- *
- * \return \c 0 on success.
+ * This must be initialized and bound to a key.
+ * \param length The length of the input data \p input in Bytes.
+ * \param nc_off The offset in Bytes in the current \p stream_block,
+ * for resuming within the current cipher stream. The
+ * offset pointer should be \c 0 at the start of a
+ * stream. This must not be larger than \c 15 Bytes.
+ * \param nonce_counter The 128-bit nonce and counter. This must point to
+ * a read/write buffer of length \c 16 bytes.
+ * \param stream_block The saved stream block for resuming. This must
+ * point to a read/write buffer of length \c 16 bytes.
+ * This is overwritten by the function.
+ * \param input The buffer holding the input data. This must
+ * be a readable buffer of length \p length Bytes.
+ * \param output The buffer holding the output data. This must
+ * be a writable buffer of length \p length Bytes.
+ *
+ * \return \c 0 on success.
+ * \return A negative error code on failure.
*/
int mbedtls_aria_crypt_ctr( mbedtls_aria_context *ctx,
size_t length,
diff --git a/thirdparty/mbedtls/include/mbedtls/asn1write.h b/thirdparty/mbedtls/include/mbedtls/asn1write.h
index f76fc807d0..76c1780b59 100644
--- a/thirdparty/mbedtls/include/mbedtls/asn1write.h
+++ b/thirdparty/mbedtls/include/mbedtls/asn1write.h
@@ -26,191 +26,272 @@
#include "asn1.h"
-#define MBEDTLS_ASN1_CHK_ADD(g, f) do { if( ( ret = f ) < 0 ) return( ret ); else \
- g += ret; } while( 0 )
+#define MBEDTLS_ASN1_CHK_ADD(g, f) \
+ do { \
+ if( ( ret = f ) < 0 ) \
+ return( ret ); \
+ else \
+ g += ret; \
+ } while( 0 )
#ifdef __cplusplus
extern "C" {
#endif
/**
- * \brief Write a length field in ASN.1 format
- * Note: function works backwards in data buffer
+ * \brief Write a length field in ASN.1 format.
*
- * \param p reference to current position pointer
- * \param start start of the buffer (for bounds-checking)
- * \param len the length to write
+ * \note This function works backwards in data buffer.
*
- * \return the length written or a negative error code
+ * \param p The reference to the current position pointer.
+ * \param start The start of the buffer, for bounds-checking.
+ * \param len The length value to write.
+ *
+ * \return The number of bytes written to \p p on success.
+ * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
*/
-int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len );
-
+int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start,
+ size_t len );
/**
- * \brief Write a ASN.1 tag in ASN.1 format
- * Note: function works backwards in data buffer
+ * \brief Write an ASN.1 tag in ASN.1 format.
+ *
+ * \note This function works backwards in data buffer.
*
- * \param p reference to current position pointer
- * \param start start of the buffer (for bounds-checking)
- * \param tag the tag to write
+ * \param p The reference to the current position pointer.
+ * \param start The start of the buffer, for bounds-checking.
+ * \param tag The tag to write.
*
- * \return the length written or a negative error code
+ * \return The number of bytes written to \p p on success.
+ * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
*/
int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start,
- unsigned char tag );
+ unsigned char tag );
/**
- * \brief Write raw buffer data
- * Note: function works backwards in data buffer
+ * \brief Write raw buffer data.
*
- * \param p reference to current position pointer
- * \param start start of the buffer (for bounds-checking)
- * \param buf data buffer to write
- * \param size length of the data buffer
+ * \note This function works backwards in data buffer.
*
- * \return the length written or a negative error code
+ * \param p The reference to the current position pointer.
+ * \param start The start of the buffer, for bounds-checking.
+ * \param buf The data buffer to write.
+ * \param size The length of the data buffer.
+ *
+ * \return The number of bytes written to \p p on success.
+ * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
*/
int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start,
- const unsigned char *buf, size_t size );
+ const unsigned char *buf, size_t size );
#if defined(MBEDTLS_BIGNUM_C)
/**
- * \brief Write a big number (MBEDTLS_ASN1_INTEGER) in ASN.1 format
- * Note: function works backwards in data buffer
+ * \brief Write a arbitrary-precision number (#MBEDTLS_ASN1_INTEGER)
+ * in ASN.1 format.
+ *
+ * \note This function works backwards in data buffer.
*
- * \param p reference to current position pointer
- * \param start start of the buffer (for bounds-checking)
- * \param X the MPI to write
+ * \param p The reference to the current position pointer.
+ * \param start The start of the buffer, for bounds-checking.
+ * \param X The MPI to write.
*
- * \return the length written or a negative error code
+ * \return The number of bytes written to \p p on success.
+ * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
*/
-int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedtls_mpi *X );
+int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start,
+ const mbedtls_mpi *X );
#endif /* MBEDTLS_BIGNUM_C */
/**
- * \brief Write a NULL tag (MBEDTLS_ASN1_NULL) with zero data in ASN.1 format
- * Note: function works backwards in data buffer
+ * \brief Write a NULL tag (#MBEDTLS_ASN1_NULL) with zero data
+ * in ASN.1 format.
+ *
+ * \note This function works backwards in data buffer.
*
- * \param p reference to current position pointer
- * \param start start of the buffer (for bounds-checking)
+ * \param p The reference to the current position pointer.
+ * \param start The start of the buffer, for bounds-checking.
*
- * \return the length written or a negative error code
+ * \return The number of bytes written to \p p on success.
+ * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
*/
int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start );
/**
- * \brief Write an OID tag (MBEDTLS_ASN1_OID) and data in ASN.1 format
- * Note: function works backwards in data buffer
+ * \brief Write an OID tag (#MBEDTLS_ASN1_OID) and data
+ * in ASN.1 format.
*
- * \param p reference to current position pointer
- * \param start start of the buffer (for bounds-checking)
- * \param oid the OID to write
- * \param oid_len length of the OID
+ * \note This function works backwards in data buffer.
*
- * \return the length written or a negative error code
+ * \param p The reference to the current position pointer.
+ * \param start The start of the buffer, for bounds-checking.
+ * \param oid The OID to write.
+ * \param oid_len The length of the OID.
+ *
+ * \return The number of bytes written to \p p on success.
+ * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
*/
int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start,
- const char *oid, size_t oid_len );
+ const char *oid, size_t oid_len );
/**
- * \brief Write an AlgorithmIdentifier sequence in ASN.1 format
- * Note: function works backwards in data buffer
+ * \brief Write an AlgorithmIdentifier sequence in ASN.1 format.
+ *
+ * \note This function works backwards in data buffer.
*
- * \param p reference to current position pointer
- * \param start start of the buffer (for bounds-checking)
- * \param oid the OID of the algorithm
- * \param oid_len length of the OID
- * \param par_len length of parameters, which must be already written.
+ * \param p The reference to the current position pointer.
+ * \param start The start of the buffer, for bounds-checking.
+ * \param oid The OID of the algorithm to write.
+ * \param oid_len The length of the algorithm's OID.
+ * \param par_len The length of the parameters, which must be already written.
* If 0, NULL parameters are added
*
- * \return the length written or a negative error code
+ * \return The number of bytes written to \p p on success.
+ * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
*/
-int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start,
- const char *oid, size_t oid_len,
- size_t par_len );
+int mbedtls_asn1_write_algorithm_identifier( unsigned char **p,
+ unsigned char *start,
+ const char *oid, size_t oid_len,
+ size_t par_len );
/**
- * \brief Write a boolean tag (MBEDTLS_ASN1_BOOLEAN) and value in ASN.1 format
- * Note: function works backwards in data buffer
+ * \brief Write a boolean tag (#MBEDTLS_ASN1_BOOLEAN) and value
+ * in ASN.1 format.
+ *
+ * \note This function works backwards in data buffer.
*
- * \param p reference to current position pointer
- * \param start start of the buffer (for bounds-checking)
- * \param boolean 0 or 1
+ * \param p The reference to the current position pointer.
+ * \param start The start of the buffer, for bounds-checking.
+ * \param boolean The boolean value to write, either \c 0 or \c 1.
*
- * \return the length written or a negative error code
+ * \return The number of bytes written to \p p on success.
+ * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
*/
-int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, int boolean );
+int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start,
+ int boolean );
/**
- * \brief Write an int tag (MBEDTLS_ASN1_INTEGER) and value in ASN.1 format
- * Note: function works backwards in data buffer
+ * \brief Write an int tag (#MBEDTLS_ASN1_INTEGER) and value
+ * in ASN.1 format.
*
- * \param p reference to current position pointer
- * \param start start of the buffer (for bounds-checking)
- * \param val the integer value
+ * \note This function works backwards in data buffer.
*
- * \return the length written or a negative error code
+ * \param p The reference to the current position pointer.
+ * \param start The start of the buffer, for bounds-checking.
+ * \param val The integer value to write.
+ *
+ * \return The number of bytes written to \p p on success.
+ * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
*/
int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val );
/**
- * \brief Write a printable string tag (MBEDTLS_ASN1_PRINTABLE_STRING) and
- * value in ASN.1 format
- * Note: function works backwards in data buffer
+ * \brief Write a string in ASN.1 format using a specific
+ * string encoding tag.
+
+ * \note This function works backwards in data buffer.
+ *
+ * \param p The reference to the current position pointer.
+ * \param start The start of the buffer, for bounds-checking.
+ * \param tag The string encoding tag to write, e.g.
+ * #MBEDTLS_ASN1_UTF8_STRING.
+ * \param text The string to write.
+ * \param text_len The length of \p text in bytes (which might
+ * be strictly larger than the number of characters).
+ *
+ * \return The number of bytes written to \p p on success.
+ * \return A negative error code on failure.
+ */
+int mbedtls_asn1_write_tagged_string( unsigned char **p, unsigned char *start,
+ int tag, const char *text,
+ size_t text_len );
+
+/**
+ * \brief Write a string in ASN.1 format using the PrintableString
+ * string encoding tag (#MBEDTLS_ASN1_PRINTABLE_STRING).
+ *
+ * \note This function works backwards in data buffer.
+ *
+ * \param p The reference to the current position pointer.
+ * \param start The start of the buffer, for bounds-checking.
+ * \param text The string to write.
+ * \param text_len The length of \p text in bytes (which might
+ * be strictly larger than the number of characters).
+ *
+ * \return The number of bytes written to \p p on success.
+ * \return A negative error code on failure.
+ */
+int mbedtls_asn1_write_printable_string( unsigned char **p,
+ unsigned char *start,
+ const char *text, size_t text_len );
+
+/**
+ * \brief Write a UTF8 string in ASN.1 format using the UTF8String
+ * string encoding tag (#MBEDTLS_ASN1_PRINTABLE_STRING).
+ *
+ * \note This function works backwards in data buffer.
*
- * \param p reference to current position pointer
- * \param start start of the buffer (for bounds-checking)
- * \param text the text to write
- * \param text_len length of the text
+ * \param p The reference to the current position pointer.
+ * \param start The start of the buffer, for bounds-checking.
+ * \param text The string to write.
+ * \param text_len The length of \p text in bytes (which might
+ * be strictly larger than the number of characters).
*
- * \return the length written or a negative error code
+ * \return The number of bytes written to \p p on success.
+ * \return A negative error code on failure.
*/
-int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start,
- const char *text, size_t text_len );
+int mbedtls_asn1_write_utf8_string( unsigned char **p, unsigned char *start,
+ const char *text, size_t text_len );
/**
- * \brief Write an IA5 string tag (MBEDTLS_ASN1_IA5_STRING) and
- * value in ASN.1 format
- * Note: function works backwards in data buffer
+ * \brief Write a string in ASN.1 format using the IA5String
+ * string encoding tag (#MBEDTLS_ASN1_IA5_STRING).
*
- * \param p reference to current position pointer
- * \param start start of the buffer (for bounds-checking)
- * \param text the text to write
- * \param text_len length of the text
+ * \note This function works backwards in data buffer.
*
- * \return the length written or a negative error code
+ * \param p The reference to the current position pointer.
+ * \param start The start of the buffer, for bounds-checking.
+ * \param text The string to write.
+ * \param text_len The length of \p text in bytes (which might
+ * be strictly larger than the number of characters).
+ *
+ * \return The number of bytes written to \p p on success.
+ * \return A negative error code on failure.
*/
int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start,
- const char *text, size_t text_len );
+ const char *text, size_t text_len );
/**
- * \brief Write a bitstring tag (MBEDTLS_ASN1_BIT_STRING) and
- * value in ASN.1 format
- * Note: function works backwards in data buffer
+ * \brief Write a bitstring tag (#MBEDTLS_ASN1_BIT_STRING) and
+ * value in ASN.1 format.
+ *
+ * \note This function works backwards in data buffer.
*
- * \param p reference to current position pointer
- * \param start start of the buffer (for bounds-checking)
- * \param buf the bitstring
- * \param bits the total number of bits in the bitstring
+ * \param p The reference to the current position pointer.
+ * \param start The start of the buffer, for bounds-checking.
+ * \param buf The bitstring to write.
+ * \param bits The total number of bits in the bitstring.
*
- * \return the length written or a negative error code
+ * \return The number of bytes written to \p p on success.
+ * \return A negative error code on failure.
*/
int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start,
- const unsigned char *buf, size_t bits );
+ const unsigned char *buf, size_t bits );
/**
- * \brief Write an octet string tag (MBEDTLS_ASN1_OCTET_STRING) and
- * value in ASN.1 format
- * Note: function works backwards in data buffer
+ * \brief Write an octet string tag (#MBEDTLS_ASN1_OCTET_STRING)
+ * and value in ASN.1 format.
+ *
+ * \note This function works backwards in data buffer.
*
- * \param p reference to current position pointer
- * \param start start of the buffer (for bounds-checking)
- * \param buf data buffer to write
- * \param size length of the data buffer
+ * \param p The reference to the current position pointer.
+ * \param start The start of the buffer, for bounds-checking.
+ * \param buf The buffer holding the data to write.
+ * \param size The length of the data buffer \p buf.
*
- * \return the length written or a negative error code
+ * \return The number of bytes written to \p p on success.
+ * \return A negative error code on failure.
*/
int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start,
- const unsigned char *buf, size_t size );
+ const unsigned char *buf, size_t size );
/**
* \brief Create or find a specific named_data entry for writing in a
@@ -218,15 +299,16 @@ int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start,
* a new entry is added to the head of the list.
* Warning: Destructive behaviour for the val data!
*
- * \param list Pointer to the location of the head of the list to seek
- * through (will be updated in case of a new entry)
- * \param oid The OID to look for
- * \param oid_len Size of the OID
- * \param val Data to store (can be NULL if you want to fill it by hand)
- * \param val_len Minimum length of the data buffer needed
+ * \param list The pointer to the location of the head of the list to seek
+ * through (will be updated in case of a new entry).
+ * \param oid The OID to look for.
+ * \param oid_len The size of the OID.
+ * \param val The data to store (can be \c NULL if you want to fill
+ * it by hand).
+ * \param val_len The minimum length of the data buffer needed.
*
- * \return NULL if if there was a memory allocation error, or a pointer
- * to the new / existing entry.
+ * \return A pointer to the new / existing entry on success.
+ * \return \c NULL if if there was a memory allocation error.
*/
mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( mbedtls_asn1_named_data **list,
const char *oid, size_t oid_len,
diff --git a/thirdparty/mbedtls/include/mbedtls/bignum.h b/thirdparty/mbedtls/include/mbedtls/bignum.h
index 31383b1eb5..141a8e9adf 100644
--- a/thirdparty/mbedtls/include/mbedtls/bignum.h
+++ b/thirdparty/mbedtls/include/mbedtls/bignum.h
@@ -177,7 +177,7 @@ extern "C" {
/**
* \brief MPI structure
*/
-typedef struct
+typedef struct mbedtls_mpi
{
int s; /*!< integer sign */
size_t n; /*!< total # of limbs */
@@ -186,96 +186,115 @@ typedef struct
mbedtls_mpi;
/**
- * \brief Initialize one MPI (make internal references valid)
- * This just makes it ready to be set or freed,
+ * \brief Initialize an MPI context.
+ *
+ * This makes the MPI ready to be set or freed,
* but does not define a value for the MPI.
*
- * \param X One MPI to initialize.
+ * \param X The MPI context to initialize. This must not be \c NULL.
*/
void mbedtls_mpi_init( mbedtls_mpi *X );
/**
- * \brief Unallocate one MPI
+ * \brief This function frees the components of an MPI context.
*
- * \param X One MPI to unallocate.
+ * \param X The MPI context to be cleared. This may be \c NULL,
+ * in which case this function is a no-op. If it is
+ * not \c NULL, it must point to an initialized MPI.
*/
void mbedtls_mpi_free( mbedtls_mpi *X );
/**
- * \brief Enlarge to the specified number of limbs
+ * \brief Enlarge an MPI to the specified number of limbs.
*
- * This function does nothing if the MPI is already large enough.
+ * \note This function does nothing if the MPI is
+ * already large enough.
*
- * \param X MPI to grow
- * \param nblimbs The target number of limbs
+ * \param X The MPI to grow. It must be initialized.
+ * \param nblimbs The target number of limbs.
*
- * \return 0 if successful,
- * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed.
+ * \return Another negative error code on other kinds of failure.
*/
int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs );
/**
- * \brief Resize down, keeping at least the specified number of limbs
+ * \brief This function resizes an MPI downwards, keeping at least the
+ * specified number of limbs.
*
* If \c X is smaller than \c nblimbs, it is resized up
* instead.
*
- * \param X MPI to shrink
- * \param nblimbs The minimum number of limbs to keep
+ * \param X The MPI to shrink. This must point to an initialized MPI.
+ * \param nblimbs The minimum number of limbs to keep.
*
- * \return 0 if successful,
- * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
* (this can only happen when resizing up).
+ * \return Another negative error code on other kinds of failure.
*/
int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs );
/**
- * \brief Copy the contents of Y into X
+ * \brief Make a copy of an MPI.
+ *
+ * \param X The destination MPI. This must point to an initialized MPI.
+ * \param Y The source MPI. This must point to an initialized MPI.
*
- * \param X Destination MPI. It is enlarged if necessary.
- * \param Y Source MPI.
+ * \note The limb-buffer in the destination MPI is enlarged
+ * if necessary to hold the value in the source MPI.
*
- * \return 0 if successful,
- * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed.
+ * \return Another negative error code on other kinds of failure.
*/
int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y );
/**
- * \brief Swap the contents of X and Y
+ * \brief Swap the contents of two MPIs.
*
- * \param X First MPI value
- * \param Y Second MPI value
+ * \param X The first MPI. It must be initialized.
+ * \param Y The second MPI. It must be initialized.
*/
void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y );
/**
- * \brief Safe conditional assignement X = Y if assign is 1
+ * \brief Perform a safe conditional copy of MPI which doesn't
+ * reveal whether the condition was true or not.
*
- * \param X MPI to conditionally assign to
- * \param Y Value to be assigned
- * \param assign 1: perform the assignment, 0: keep X's original value
- *
- * \return 0 if successful,
- * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
+ * \param X The MPI to conditionally assign to. This must point
+ * to an initialized MPI.
+ * \param Y The MPI to be assigned from. This must point to an
+ * initialized MPI.
+ * \param assign The condition deciding whether to perform the
+ * assignment or not. Possible values:
+ * * \c 1: Perform the assignment `X = Y`.
+ * * \c 0: Keep the original value of \p X.
*
* \note This function is equivalent to
- * if( assign ) mbedtls_mpi_copy( X, Y );
+ * `if( assign ) mbedtls_mpi_copy( X, Y );`
* except that it avoids leaking any information about whether
* the assignment was done or not (the above code may leak
* information through branch prediction and/or memory access
* patterns analysis).
+ *
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed.
+ * \return Another negative error code on other kinds of failure.
*/
int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign );
/**
- * \brief Safe conditional swap X <-> Y if swap is 1
+ * \brief Perform a safe conditional swap which doesn't
+ * reveal whether the condition was true or not.
*
- * \param X First mbedtls_mpi value
- * \param Y Second mbedtls_mpi value
- * \param assign 1: perform the swap, 0: keep X and Y's original values
- *
- * \return 0 if successful,
- * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
+ * \param X The first MPI. This must be initialized.
+ * \param Y The second MPI. This must be initialized.
+ * \param assign The condition deciding whether to perform
+ * the swap or not. Possible values:
+ * * \c 1: Swap the values of \p X and \p Y.
+ * * \c 0: Keep the original values of \p X and \p Y.
*
* \note This function is equivalent to
* if( assign ) mbedtls_mpi_swap( X, Y );
@@ -283,415 +302,512 @@ int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned
* the assignment was done or not (the above code may leak
* information through branch prediction and/or memory access
* patterns analysis).
+ *
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed.
+ * \return Another negative error code on other kinds of failure.
+ *
*/
int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char assign );
/**
- * \brief Set value from integer
+ * \brief Store integer value in MPI.
*
- * \param X MPI to set
- * \param z Value to use
+ * \param X The MPI to set. This must be initialized.
+ * \param z The value to use.
*
- * \return 0 if successful,
- * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed.
+ * \return Another negative error code on other kinds of failure.
*/
int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z );
/**
- * \brief Get a specific bit from X
+ * \brief Get a specific bit from an MPI.
*
- * \param X MPI to use
- * \param pos Zero-based index of the bit in X
+ * \param X The MPI to query. This must be initialized.
+ * \param pos Zero-based index of the bit to query.
*
- * \return Either a 0 or a 1
+ * \return \c 0 or \c 1 on success, depending on whether bit \c pos
+ * of \c X is unset or set.
+ * \return A negative error code on failure.
*/
int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos );
/**
- * \brief Set a bit of X to a specific value of 0 or 1
+ * \brief Modify a specific bit in an MPI.
*
- * \note Will grow X if necessary to set a bit to 1 in a not yet
- * existing limb. Will not grow if bit should be set to 0
+ * \note This function will grow the target MPI if necessary to set a
+ * bit to \c 1 in a not yet existing limb. It will not grow if
+ * the bit should be set to \c 0.
*
- * \param X MPI to use
- * \param pos Zero-based index of the bit in X
- * \param val The value to set the bit to (0 or 1)
+ * \param X The MPI to modify. This must be initialized.
+ * \param pos Zero-based index of the bit to modify.
+ * \param val The desired value of bit \c pos: \c 0 or \c 1.
*
- * \return 0 if successful,
- * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
- * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if val is not 0 or 1
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed.
+ * \return Another negative error code on other kinds of failure.
*/
int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val );
/**
- * \brief Return the number of zero-bits before the least significant
- * '1' bit
+ * \brief Return the number of bits of value \c 0 before the
+ * least significant bit of value \c 1.
+ *
+ * \note This is the same as the zero-based index of
+ * the least significant bit of value \c 1.
*
- * Note: Thus also the zero-based index of the least significant '1' bit
+ * \param X The MPI to query.
*
- * \param X MPI to use
+ * \return The number of bits of value \c 0 before the least significant
+ * bit of value \c 1 in \p X.
*/
size_t mbedtls_mpi_lsb( const mbedtls_mpi *X );
/**
* \brief Return the number of bits up to and including the most
- * significant '1' bit'
+ * significant bit of value \c 1.
*
- * Note: Thus also the one-based index of the most significant '1' bit
+ * * \note This is same as the one-based index of the most
+ * significant bit of value \c 1.
*
- * \param X MPI to use
+ * \param X The MPI to query. This must point to an initialized MPI.
+ *
+ * \return The number of bits up to and including the most
+ * significant bit of value \c 1.
*/
size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X );
/**
- * \brief Return the total size in bytes
+ * \brief Return the total size of an MPI value in bytes.
+ *
+ * \param X The MPI to use. This must point to an initialized MPI.
*
- * \param X MPI to use
+ * \note The value returned by this function may be less than
+ * the number of bytes used to store \p X internally.
+ * This happens if and only if there are trailing bytes
+ * of value zero.
+ *
+ * \return The least number of bytes capable of storing
+ * the absolute value of \p X.
*/
size_t mbedtls_mpi_size( const mbedtls_mpi *X );
/**
- * \brief Import from an ASCII string
+ * \brief Import an MPI from an ASCII string.
*
- * \param X Destination MPI
- * \param radix Input numeric base
- * \param s Null-terminated string buffer
+ * \param X The destination MPI. This must point to an initialized MPI.
+ * \param radix The numeric base of the input string.
+ * \param s Null-terminated string buffer.
*
- * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code
+ * \return \c 0 if successful.
+ * \return A negative error code on failure.
*/
int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s );
/**
- * \brief Export into an ASCII string
+ * \brief Export an MPI to an ASCII string.
*
- * \param X Source MPI
- * \param radix Output numeric base
- * \param buf Buffer to write the string to
- * \param buflen Length of buf
- * \param olen Length of the string written, including final NUL byte
+ * \param X The source MPI. This must point to an initialized MPI.
+ * \param radix The numeric base of the output string.
+ * \param buf The buffer to write the string to. This must be writable
+ * buffer of length \p buflen Bytes.
+ * \param buflen The available size in Bytes of \p buf.
+ * \param olen The address at which to store the length of the string
+ * written, including the final \c NULL byte. This must
+ * not be \c NULL.
*
- * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code.
- * *olen is always updated to reflect the amount
- * of data that has (or would have) been written.
+ * \note You can call this function with `buflen == 0` to obtain the
+ * minimum required buffer size in `*olen`.
*
- * \note Call this function with buflen = 0 to obtain the
- * minimum required buffer size in *olen.
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if the target buffer \p buf
+ * is too small to hold the value of \p X in the desired base.
+ * In this case, `*olen` is nonetheless updated to contain the
+ * size of \p buf required for a successful call.
+ * \return Another negative error code on different kinds of failure.
*/
int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
char *buf, size_t buflen, size_t *olen );
#if defined(MBEDTLS_FS_IO)
/**
- * \brief Read MPI from a line in an opened file
- *
- * \param X Destination MPI
- * \param radix Input numeric base
- * \param fin Input file handle
+ * \brief Read an MPI from a line in an opened file.
*
- * \return 0 if successful, MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if
- * the file read buffer is too small or a
- * MBEDTLS_ERR_MPI_XXX error code
+ * \param X The destination MPI. This must point to an initialized MPI.
+ * \param radix The numeric base of the string representation used
+ * in the source line.
+ * \param fin The input file handle to use. This must not be \c NULL.
*
* \note On success, this function advances the file stream
* to the end of the current line or to EOF.
*
- * The function returns 0 on an empty line.
+ * The function returns \c 0 on an empty line.
*
* Leading whitespaces are ignored, as is a
- * '0x' prefix for radix 16.
+ * '0x' prefix for radix \c 16.
*
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if the file read buffer
+ * is too small.
+ * \return Another negative error code on failure.
*/
int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin );
/**
- * \brief Write X into an opened file, or stdout if fout is NULL
+ * \brief Export an MPI into an opened file.
*
- * \param p Prefix, can be NULL
- * \param X Source MPI
- * \param radix Output numeric base
- * \param fout Output file handle (can be NULL)
+ * \param p A string prefix to emit prior to the MPI data.
+ * For example, this might be a label, or "0x" when
+ * printing in base \c 16. This may be \c NULL if no prefix
+ * is needed.
+ * \param X The source MPI. This must point to an initialized MPI.
+ * \param radix The numeric base to be used in the emitted string.
+ * \param fout The output file handle. This may be \c NULL, in which case
+ * the output is written to \c stdout.
*
- * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code
- *
- * \note Set fout == NULL to print X on the console.
+ * \return \c 0 if successful.
+ * \return A negative error code on failure.
*/
-int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout );
+int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X,
+ int radix, FILE *fout );
#endif /* MBEDTLS_FS_IO */
/**
- * \brief Import X from unsigned binary data, big endian
+ * \brief Import an MPI from unsigned big endian binary data.
*
- * \param X Destination MPI
- * \param buf Input buffer
- * \param buflen Input buffer size
+ * \param X The destination MPI. This must point to an initialized MPI.
+ * \param buf The input buffer. This must be a readable buffer of length
+ * \p buflen Bytes.
+ * \param buflen The length of the input buffer \p p in Bytes.
*
- * \return 0 if successful,
- * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed.
+ * \return Another negative error code on different kinds of failure.
*/
-int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen );
+int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf,
+ size_t buflen );
/**
- * \brief Export X into unsigned binary data, big endian.
- * Always fills the whole buffer, which will start with zeros
- * if the number is smaller.
+ * \brief Export an MPI into unsigned big endian binary data
+ * of fixed size.
*
- * \param X Source MPI
- * \param buf Output buffer
- * \param buflen Output buffer size
+ * \param X The source MPI. This must point to an initialized MPI.
+ * \param buf The output buffer. This must be a writable buffer of length
+ * \p buflen Bytes.
+ * \param buflen The size of the output buffer \p buf in Bytes.
*
- * \return 0 if successful,
- * MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p buf isn't
+ * large enough to hold the value of \p X.
+ * \return Another negative error code on different kinds of failure.
*/
-int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen );
+int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf,
+ size_t buflen );
/**
- * \brief Left-shift: X <<= count
+ * \brief Perform a left-shift on an MPI: X <<= count
*
- * \param X MPI to shift
- * \param count Amount to shift
+ * \param X The MPI to shift. This must point to an initialized MPI.
+ * \param count The number of bits to shift by.
*
- * \return 0 if successful,
- * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.
+ * \return Another negative error code on different kinds of failure.
*/
int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count );
/**
- * \brief Right-shift: X >>= count
+ * \brief Perform a right-shift on an MPI: X >>= count
*
- * \param X MPI to shift
- * \param count Amount to shift
+ * \param X The MPI to shift. This must point to an initialized MPI.
+ * \param count The number of bits to shift by.
*
- * \return 0 if successful,
- * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.
+ * \return Another negative error code on different kinds of failure.
*/
int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count );
/**
- * \brief Compare unsigned values
+ * \brief Compare the absolute values of two MPIs.
*
- * \param X Left-hand MPI
- * \param Y Right-hand MPI
+ * \param X The left-hand MPI. This must point to an initialized MPI.
+ * \param Y The right-hand MPI. This must point to an initialized MPI.
*
- * \return 1 if |X| is greater than |Y|,
- * -1 if |X| is lesser than |Y| or
- * 0 if |X| is equal to |Y|
+ * \return \c 1 if `|X|` is greater than `|Y|`.
+ * \return \c -1 if `|X|` is lesser than `|Y|`.
+ * \return \c 0 if `|X|` is equal to `|Y|`.
*/
int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y );
/**
- * \brief Compare signed values
+ * \brief Compare two MPIs.
*
- * \param X Left-hand MPI
- * \param Y Right-hand MPI
+ * \param X The left-hand MPI. This must point to an initialized MPI.
+ * \param Y The right-hand MPI. This must point to an initialized MPI.
*
- * \return 1 if X is greater than Y,
- * -1 if X is lesser than Y or
- * 0 if X is equal to Y
+ * \return \c 1 if \p X is greater than \p Y.
+ * \return \c -1 if \p X is lesser than \p Y.
+ * \return \c 0 if \p X is equal to \p Y.
*/
int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y );
/**
- * \brief Compare signed values
+ * \brief Compare an MPI with an integer.
*
- * \param X Left-hand MPI
- * \param z The integer value to compare to
+ * \param X The left-hand MPI. This must point to an initialized MPI.
+ * \param z The integer value to compare \p X to.
*
- * \return 1 if X is greater than z,
- * -1 if X is lesser than z or
- * 0 if X is equal to z
+ * \return \c 1 if \p X is greater than \p z.
+ * \return \c -1 if \p X is lesser than \p z.
+ * \return \c 0 if \p X is equal to \p z.
*/
int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z );
/**
- * \brief Unsigned addition: X = |A| + |B|
+ * \brief Perform an unsigned addition of MPIs: X = |A| + |B|
*
- * \param X Destination MPI
- * \param A Left-hand MPI
- * \param B Right-hand MPI
+ * \param X The destination MPI. This must point to an initialized MPI.
+ * \param A The first summand. This must point to an initialized MPI.
+ * \param B The second summand. This must point to an initialized MPI.
*
- * \return 0 if successful,
- * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.
+ * \return Another negative error code on different kinds of failure.
*/
-int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B );
+int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A,
+ const mbedtls_mpi *B );
/**
- * \brief Unsigned subtraction: X = |A| - |B|
+ * \brief Perform an unsigned subtraction of MPIs: X = |A| - |B|
+ *
+ * \param X The destination MPI. This must point to an initialized MPI.
+ * \param A The minuend. This must point to an initialized MPI.
+ * \param B The subtrahend. This must point to an initialized MPI.
*
- * \param X Destination MPI
- * \param A Left-hand MPI
- * \param B Right-hand MPI
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p B is greater than \p A.
+ * \return Another negative error code on different kinds of failure.
*
- * \return 0 if successful,
- * MBEDTLS_ERR_MPI_NEGATIVE_VALUE if B is greater than A
*/
-int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B );
+int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A,
+ const mbedtls_mpi *B );
/**
- * \brief Signed addition: X = A + B
+ * \brief Perform a signed addition of MPIs: X = A + B
*
- * \param X Destination MPI
- * \param A Left-hand MPI
- * \param B Right-hand MPI
+ * \param X The destination MPI. This must point to an initialized MPI.
+ * \param A The first summand. This must point to an initialized MPI.
+ * \param B The second summand. This must point to an initialized MPI.
*
- * \return 0 if successful,
- * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.
+ * \return Another negative error code on different kinds of failure.
*/
-int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B );
+int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A,
+ const mbedtls_mpi *B );
/**
- * \brief Signed subtraction: X = A - B
+ * \brief Perform a signed subtraction of MPIs: X = A - B
*
- * \param X Destination MPI
- * \param A Left-hand MPI
- * \param B Right-hand MPI
+ * \param X The destination MPI. This must point to an initialized MPI.
+ * \param A The minuend. This must point to an initialized MPI.
+ * \param B The subtrahend. This must point to an initialized MPI.
*
- * \return 0 if successful,
- * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.
+ * \return Another negative error code on different kinds of failure.
*/
-int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B );
+int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A,
+ const mbedtls_mpi *B );
/**
- * \brief Signed addition: X = A + b
+ * \brief Perform a signed addition of an MPI and an integer: X = A + b
*
- * \param X Destination MPI
- * \param A Left-hand MPI
- * \param b The integer value to add
+ * \param X The destination MPI. This must point to an initialized MPI.
+ * \param A The first summand. This must point to an initialized MPI.
+ * \param b The second summand.
*
- * \return 0 if successful,
- * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.
+ * \return Another negative error code on different kinds of failure.
*/
-int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b );
+int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A,
+ mbedtls_mpi_sint b );
/**
- * \brief Signed subtraction: X = A - b
+ * \brief Perform a signed subtraction of an MPI and an integer:
+ * X = A - b
*
- * \param X Destination MPI
- * \param A Left-hand MPI
- * \param b The integer value to subtract
+ * \param X The destination MPI. This must point to an initialized MPI.
+ * \param A The minuend. This must point to an initialized MPI.
+ * \param b The subtrahend.
*
- * \return 0 if successful,
- * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.
+ * \return Another negative error code on different kinds of failure.
*/
-int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b );
+int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A,
+ mbedtls_mpi_sint b );
/**
- * \brief Baseline multiplication: X = A * B
+ * \brief Perform a multiplication of two MPIs: X = A * B
+ *
+ * \param X The destination MPI. This must point to an initialized MPI.
+ * \param A The first factor. This must point to an initialized MPI.
+ * \param B The second factor. This must point to an initialized MPI.
*
- * \param X Destination MPI
- * \param A Left-hand MPI
- * \param B Right-hand MPI
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.
+ * \return Another negative error code on different kinds of failure.
*
- * \return 0 if successful,
- * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
-int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B );
+int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A,
+ const mbedtls_mpi *B );
/**
- * \brief Baseline multiplication: X = A * b
+ * \brief Perform a multiplication of an MPI with an unsigned integer:
+ * X = A * b
*
- * \param X Destination MPI
- * \param A Left-hand MPI
- * \param b The unsigned integer value to multiply with
+ * \param X The destination MPI. This must point to an initialized MPI.
+ * \param A The first factor. This must point to an initialized MPI.
+ * \param b The second factor.
*
- * \note b is unsigned
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.
+ * \return Another negative error code on different kinds of failure.
*
- * \return 0 if successful,
- * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
-int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b );
+int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A,
+ mbedtls_mpi_uint b );
/**
- * \brief Division by mbedtls_mpi: A = Q * B + R
+ * \brief Perform a division with remainder of two MPIs:
+ * A = Q * B + R
*
- * \param Q Destination MPI for the quotient
- * \param R Destination MPI for the rest value
- * \param A Left-hand MPI
- * \param B Right-hand MPI
+ * \param Q The destination MPI for the quotient.
+ * This may be \c NULL if the value of the
+ * quotient is not needed.
+ * \param R The destination MPI for the remainder value.
+ * This may be \c NULL if the value of the
+ * remainder is not needed.
+ * \param A The dividend. This must point to an initialized MPi.
+ * \param B The divisor. This must point to an initialized MPI.
*
- * \return 0 if successful,
- * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
- * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if B == 0
- *
- * \note Either Q or R can be NULL.
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed.
+ * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p B equals zero.
+ * \return Another negative error code on different kinds of failure.
*/
-int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B );
+int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
+ const mbedtls_mpi *B );
/**
- * \brief Division by int: A = Q * b + R
- *
- * \param Q Destination MPI for the quotient
- * \param R Destination MPI for the rest value
- * \param A Left-hand MPI
- * \param b Integer to divide by
+ * \brief Perform a division with remainder of an MPI by an integer:
+ * A = Q * b + R
*
- * \return 0 if successful,
- * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
- * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if b == 0
+ * \param Q The destination MPI for the quotient.
+ * This may be \c NULL if the value of the
+ * quotient is not needed.
+ * \param R The destination MPI for the remainder value.
+ * This may be \c NULL if the value of the
+ * remainder is not needed.
+ * \param A The dividend. This must point to an initialized MPi.
+ * \param b The divisor.
*
- * \note Either Q or R can be NULL.
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed.
+ * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p b equals zero.
+ * \return Another negative error code on different kinds of failure.
*/
-int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b );
+int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
+ mbedtls_mpi_sint b );
/**
- * \brief Modulo: R = A mod B
+ * \brief Perform a modular reduction. R = A mod B
*
- * \param R Destination MPI for the rest value
- * \param A Left-hand MPI
- * \param B Right-hand MPI
+ * \param R The destination MPI for the residue value.
+ * This must point to an initialized MPI.
+ * \param A The MPI to compute the residue of.
+ * This must point to an initialized MPI.
+ * \param B The base of the modular reduction.
+ * This must point to an initialized MPI.
+ *
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.
+ * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p B equals zero.
+ * \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p B is negative.
+ * \return Another negative error code on different kinds of failure.
*
- * \return 0 if successful,
- * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
- * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if B == 0,
- * MBEDTLS_ERR_MPI_NEGATIVE_VALUE if B < 0
*/
-int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B );
+int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A,
+ const mbedtls_mpi *B );
/**
- * \brief Modulo: r = A mod b
+ * \brief Perform a modular reduction with respect to an integer.
+ * r = A mod b
*
- * \param r Destination mbedtls_mpi_uint
- * \param A Left-hand MPI
- * \param b Integer to divide by
+ * \param r The address at which to store the residue.
+ * This must not be \c NULL.
+ * \param A The MPI to compute the residue of.
+ * This must point to an initialized MPi.
+ * \param b The integer base of the modular reduction.
*
- * \return 0 if successful,
- * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
- * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if b == 0,
- * MBEDTLS_ERR_MPI_NEGATIVE_VALUE if b < 0
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.
+ * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p b equals zero.
+ * \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p b is negative.
+ * \return Another negative error code on different kinds of failure.
*/
-int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b );
+int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A,
+ mbedtls_mpi_sint b );
/**
- * \brief Sliding-window exponentiation: X = A^E mod N
- *
- * \param X Destination MPI
- * \param A Left-hand MPI
- * \param E Exponent MPI
- * \param N Modular MPI
- * \param _RR Speed-up MPI used for recalculations
+ * \brief Perform a sliding-window exponentiation: X = A^E mod N
*
- * \return 0 if successful,
- * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
- * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if N is negative or even or
- * if E is negative
+ * \param X The destination MPI. This must point to an initialized MPI.
+ * \param A The base of the exponentiation.
+ * This must point to an initialized MPI.
+ * \param E The exponent MPI. This must point to an initialized MPI.
+ * \param N The base for the modular reduction. This must point to an
+ * initialized MPI.
+ * \param _RR A helper MPI depending solely on \p N which can be used to
+ * speed-up multiple modular exponentiations for the same value
+ * of \p N. This may be \c NULL. If it is not \c NULL, it must
+ * point to an initialized MPI. If it hasn't been used after
+ * the call to mbedtls_mpi_init(), this function will compute
+ * the helper value and store it in \p _RR for reuse on
+ * subsequent calls to this function. Otherwise, the function
+ * will assume that \p _RR holds the helper value set by a
+ * previous call to mbedtls_mpi_exp_mod(), and reuse it.
+ *
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.
+ * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \c N is negative or
+ * even, or if \c E is negative.
+ * \return Another negative error code on different kinds of failures.
*
- * \note _RR is used to avoid re-computing R*R mod N across
- * multiple calls, which speeds up things a bit. It can
- * be set to NULL if the extra performance is unneeded.
*/
-int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *_RR );
+int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
+ const mbedtls_mpi *E, const mbedtls_mpi *N,
+ mbedtls_mpi *_RR );
/**
- * \brief Fill an MPI X with size bytes of random
+ * \brief Fill an MPI with a number of random bytes.
*
- * \param X Destination MPI
- * \param size Size in bytes
- * \param f_rng RNG function
- * \param p_rng RNG parameter
+ * \param X The destination MPI. This must point to an initialized MPI.
+ * \param size The number of random bytes to generate.
+ * \param f_rng The RNG function to use. This must not be \c NULL.
+ * \param p_rng The RNG parameter to be passed to \p f_rng. This may be
+ * \c NULL if \p f_rng doesn't need a context argument.
*
- * \return 0 if successful,
- * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.
+ * \return Another negative error code on failure.
*
- * \note The bytes obtained from the PRNG are interpreted
+ * \note The bytes obtained from the RNG are interpreted
* as a big-endian representation of an MPI; this can
* be relevant in applications like deterministic ECDSA.
*/
@@ -700,61 +816,130 @@ int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
void *p_rng );
/**
- * \brief Greatest common divisor: G = gcd(A, B)
- *
- * \param G Destination MPI
- * \param A Left-hand MPI
- * \param B Right-hand MPI
- *
- * \return 0 if successful,
- * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
- */
-int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B );
-
-/**
- * \brief Modular inverse: X = A^-1 mod N
+ * \brief Compute the greatest common divisor: G = gcd(A, B)
*
- * \param X Destination MPI
- * \param A Left-hand MPI
- * \param N Right-hand MPI
+ * \param G The destination MPI. This must point to an initialized MPI.
+ * \param A The first operand. This must point to an initialized MPI.
+ * \param B The second operand. This must point to an initialized MPI.
*
- * \return 0 if successful,
- * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
- * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if N is <= 1,
- MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if A has no inverse mod N.
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.
+ * \return Another negative error code on different kinds of failure.
*/
-int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N );
+int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A,
+ const mbedtls_mpi *B );
/**
- * \brief Miller-Rabin primality test
+ * \brief Compute the modular inverse: X = A^-1 mod N
*
- * \param X MPI to check
- * \param f_rng RNG function
- * \param p_rng RNG parameter
+ * \param X The destination MPI. This must point to an initialized MPI.
+ * \param A The MPI to calculate the modular inverse of. This must point
+ * to an initialized MPI.
+ * \param N The base of the modular inversion. This must point to an
+ * initialized MPI.
*
- * \return 0 if successful (probably prime),
- * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
- * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if X is not prime
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.
+ * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p N is less than
+ * or equal to one.
+ * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if \p has no modular inverse
+ * with respect to \p N.
*/
-int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
- int (*f_rng)(void *, unsigned char *, size_t),
- void *p_rng );
+int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
+ const mbedtls_mpi *N );
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+#if defined(MBEDTLS_DEPRECATED_WARNING)
+#define MBEDTLS_DEPRECATED __attribute__((deprecated))
+#else
+#define MBEDTLS_DEPRECATED
+#endif
/**
- * \brief Prime number generation
- *
- * \param X Destination MPI
- * \param nbits Required size of X in bits
- * ( 3 <= nbits <= MBEDTLS_MPI_MAX_BITS )
- * \param dh_flag If 1, then (X-1)/2 will be prime too
- * \param f_rng RNG function
- * \param p_rng RNG parameter
- *
- * \return 0 if successful (probably prime),
- * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
- * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if nbits is < 3
- */
-int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
+ * \brief Perform a Miller-Rabin primality test with error
+ * probability of 2<sup>-80</sup>.
+ *
+ * \deprecated Superseded by mbedtls_mpi_is_prime_ext() which allows
+ * specifying the number of Miller-Rabin rounds.
+ *
+ * \param X The MPI to check for primality.
+ * This must point to an initialized MPI.
+ * \param f_rng The RNG function to use. This must not be \c NULL.
+ * \param p_rng The RNG parameter to be passed to \p f_rng.
+ * This may be \c NULL if \p f_rng doesn't use a
+ * context parameter.
+ *
+ * \return \c 0 if successful, i.e. \p X is probably prime.
+ * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.
+ * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if \p X is not prime.
+ * \return Another negative error code on other kinds of failure.
+ */
+MBEDTLS_DEPRECATED int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng );
+#undef MBEDTLS_DEPRECATED
+#endif /* !MBEDTLS_DEPRECATED_REMOVED */
+
+/**
+ * \brief Miller-Rabin primality test.
+ *
+ * \warning If \p X is potentially generated by an adversary, for example
+ * when validating cryptographic parameters that you didn't
+ * generate yourself and that are supposed to be prime, then
+ * \p rounds should be at least the half of the security
+ * strength of the cryptographic algorithm. On the other hand,
+ * if \p X is chosen uniformly or non-adversially (as is the
+ * case when mbedtls_mpi_gen_prime calls this function), then
+ * \p rounds can be much lower.
+ *
+ * \param X The MPI to check for primality.
+ * This must point to an initialized MPI.
+ * \param rounds The number of bases to perform the Miller-Rabin primality
+ * test for. The probability of returning 0 on a composite is
+ * at most 2<sup>-2*\p rounds</sup>.
+ * \param f_rng The RNG function to use. This must not be \c NULL.
+ * \param p_rng The RNG parameter to be passed to \p f_rng.
+ * This may be \c NULL if \p f_rng doesn't use
+ * a context parameter.
+ *
+ * \return \c 0 if successful, i.e. \p X is probably prime.
+ * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.
+ * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if \p X is not prime.
+ * \return Another negative error code on other kinds of failure.
+ */
+int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng );
+/**
+ * \brief Flags for mbedtls_mpi_gen_prime()
+ *
+ * Each of these flags is a constraint on the result X returned by
+ * mbedtls_mpi_gen_prime().
+ */
+typedef enum {
+ MBEDTLS_MPI_GEN_PRIME_FLAG_DH = 0x0001, /**< (X-1)/2 is prime too */
+ MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR = 0x0002, /**< lower error rate from 2<sup>-80</sup> to 2<sup>-128</sup> */
+} mbedtls_mpi_gen_prime_flag_t;
+
+/**
+ * \brief Generate a prime number.
+ *
+ * \param X The destination MPI to store the generated prime in.
+ * This must point to an initialized MPi.
+ * \param nbits The required size of the destination MPI in bits.
+ * This must be between \c 3 and #MBEDTLS_MPI_MAX_BITS.
+ * \param flags A mask of flags of type #mbedtls_mpi_gen_prime_flag_t.
+ * \param f_rng The RNG function to use. This must not be \c NULL.
+ * \param p_rng The RNG parameter to be passed to \p f_rng.
+ * This may be \c NULL if \p f_rng doesn't use
+ * a context parameter.
+ *
+ * \return \c 0 if successful, in which case \p X holds a
+ * probably prime number.
+ * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.
+ * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if `nbits` is not between
+ * \c 3 and #MBEDTLS_MPI_MAX_BITS.
+ */
+int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
diff --git a/thirdparty/mbedtls/include/mbedtls/blowfish.h b/thirdparty/mbedtls/include/mbedtls/blowfish.h
index 985faa43f0..f01573dcaf 100644
--- a/thirdparty/mbedtls/include/mbedtls/blowfish.h
+++ b/thirdparty/mbedtls/include/mbedtls/blowfish.h
@@ -33,6 +33,8 @@
#include <stddef.h>
#include <stdint.h>
+#include "platform_util.h"
+
#define MBEDTLS_BLOWFISH_ENCRYPT 1
#define MBEDTLS_BLOWFISH_DECRYPT 0
#define MBEDTLS_BLOWFISH_MAX_KEY_BITS 448
@@ -40,9 +42,16 @@
#define MBEDTLS_BLOWFISH_ROUNDS 16 /**< Rounds to use. When increasing this value, make sure to extend the initialisation vectors */
#define MBEDTLS_BLOWFISH_BLOCKSIZE 8 /* Blowfish uses 64 bit blocks */
-#define MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH -0x0016 /**< Invalid key length. */
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+#define MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( -0x0016 )
+#endif /* !MBEDTLS_DEPRECATED_REMOVED */
+#define MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA -0x0016 /**< Bad input data. */
+
+#define MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH -0x0018 /**< Invalid data input length. */
+
+/* MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED is deprecated and should not be used.
+ */
#define MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED -0x0017 /**< Blowfish hardware accelerator failed. */
-#define MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH -0x0018 /**< Invalid data input length. */
#ifdef __cplusplus
extern "C" {
@@ -55,7 +64,7 @@ extern "C" {
/**
* \brief Blowfish context structure
*/
-typedef struct
+typedef struct mbedtls_blowfish_context
{
uint32_t P[MBEDTLS_BLOWFISH_ROUNDS + 2]; /*!< Blowfish round keys */
uint32_t S[4][256]; /*!< key dependent S-boxes */
@@ -67,40 +76,53 @@ mbedtls_blowfish_context;
#endif /* MBEDTLS_BLOWFISH_ALT */
/**
- * \brief Initialize Blowfish context
+ * \brief Initialize a Blowfish context.
*
- * \param ctx Blowfish context to be initialized
+ * \param ctx The Blowfish context to be initialized.
+ * This must not be \c NULL.
*/
void mbedtls_blowfish_init( mbedtls_blowfish_context *ctx );
/**
- * \brief Clear Blowfish context
+ * \brief Clear a Blowfish context.
*
- * \param ctx Blowfish context to be cleared
+ * \param ctx The Blowfish context to be cleared.
+ * This may be \c NULL, in which case this function
+ * returns immediately. If it is not \c NULL, it must
+ * point to an initialized Blowfish context.
*/
void mbedtls_blowfish_free( mbedtls_blowfish_context *ctx );
/**
- * \brief Blowfish key schedule
+ * \brief Perform a Blowfish key schedule operation.
*
- * \param ctx Blowfish context to be initialized
- * \param key encryption key
- * \param keybits must be between 32 and 448 bits
+ * \param ctx The Blowfish context to perform the key schedule on.
+ * \param key The encryption key. This must be a readable buffer of
+ * length \p keybits Bits.
+ * \param keybits The length of \p key in Bits. This must be between
+ * \c 32 and \c 448 and a multiple of \c 8.
*
- * \return 0 if successful, or MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH
+ * \return \c 0 if successful.
+ * \return A negative error code on failure.
*/
int mbedtls_blowfish_setkey( mbedtls_blowfish_context *ctx, const unsigned char *key,
unsigned int keybits );
/**
- * \brief Blowfish-ECB block encryption/decryption
+ * \brief Perform a Blowfish-ECB block encryption/decryption operation.
*
- * \param ctx Blowfish context
- * \param mode MBEDTLS_BLOWFISH_ENCRYPT or MBEDTLS_BLOWFISH_DECRYPT
- * \param input 8-byte input block
- * \param output 8-byte output block
+ * \param ctx The Blowfish context to use. This must be initialized
+ * and bound to a key.
+ * \param mode The mode of operation. Possible values are
+ * #MBEDTLS_BLOWFISH_ENCRYPT for encryption, or
+ * #MBEDTLS_BLOWFISH_DECRYPT for decryption.
+ * \param input The input block. This must be a readable buffer
+ * of size \c 8 Bytes.
+ * \param output The output block. This must be a writable buffer
+ * of size \c 8 Bytes.
*
- * \return 0 if successful
+ * \return \c 0 if successful.
+ * \return A negative error code on failure.
*/
int mbedtls_blowfish_crypt_ecb( mbedtls_blowfish_context *ctx,
int mode,
@@ -109,9 +131,7 @@ int mbedtls_blowfish_crypt_ecb( mbedtls_blowfish_context *ctx,
#if defined(MBEDTLS_CIPHER_MODE_CBC)
/**
- * \brief Blowfish-CBC buffer encryption/decryption
- * Length should be a multiple of the block
- * size (8 bytes)
+ * \brief Perform a Blowfish-CBC buffer encryption/decryption operation.
*
* \note Upon exit, the content of the IV is updated so that you can
* call the function same function again on the following
@@ -121,15 +141,22 @@ int mbedtls_blowfish_crypt_ecb( mbedtls_blowfish_context *ctx,
* IV, you should either save it manually or use the cipher
* module instead.
*
- * \param ctx Blowfish context
- * \param mode MBEDTLS_BLOWFISH_ENCRYPT or MBEDTLS_BLOWFISH_DECRYPT
- * \param length length of the input data
- * \param iv initialization vector (updated after use)
- * \param input buffer holding the input data
- * \param output buffer holding the output data
+ * \param ctx The Blowfish context to use. This must be initialized
+ * and bound to a key.
+ * \param mode The mode of operation. Possible values are
+ * #MBEDTLS_BLOWFISH_ENCRYPT for encryption, or
+ * #MBEDTLS_BLOWFISH_DECRYPT for decryption.
+ * \param length The length of the input data in Bytes. This must be
+ * multiple of \c 8.
+ * \param iv The initialization vector. This must be a read/write buffer
+ * of length \c 8 Bytes. It is updated by this function.
+ * \param input The input data. This must be a readable buffer of length
+ * \p length Bytes.
+ * \param output The output data. This must be a writable buffer of length
+ * \p length Bytes.
*
- * \return 0 if successful, or
- * MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH
+ * \return \c 0 if successful.
+ * \return A negative error code on failure.
*/
int mbedtls_blowfish_crypt_cbc( mbedtls_blowfish_context *ctx,
int mode,
@@ -141,7 +168,7 @@ int mbedtls_blowfish_crypt_cbc( mbedtls_blowfish_context *ctx,
#if defined(MBEDTLS_CIPHER_MODE_CFB)
/**
- * \brief Blowfish CFB buffer encryption/decryption.
+ * \brief Perform a Blowfish CFB buffer encryption/decryption operation.
*
* \note Upon exit, the content of the IV is updated so that you can
* call the function same function again on the following
@@ -151,15 +178,25 @@ int mbedtls_blowfish_crypt_cbc( mbedtls_blowfish_context *ctx,
* IV, you should either save it manually or use the cipher
* module instead.
*
- * \param ctx Blowfish context
- * \param mode MBEDTLS_BLOWFISH_ENCRYPT or MBEDTLS_BLOWFISH_DECRYPT
- * \param length length of the input data
- * \param iv_off offset in IV (updated after use)
- * \param iv initialization vector (updated after use)
- * \param input buffer holding the input data
- * \param output buffer holding the output data
+ * \param ctx The Blowfish context to use. This must be initialized
+ * and bound to a key.
+ * \param mode The mode of operation. Possible values are
+ * #MBEDTLS_BLOWFISH_ENCRYPT for encryption, or
+ * #MBEDTLS_BLOWFISH_DECRYPT for decryption.
+ * \param length The length of the input data in Bytes.
+ * \param iv_off The offset in the initialiation vector.
+ * The value pointed to must be smaller than \c 8 Bytes.
+ * It is updated by this function to support the aforementioned
+ * streaming usage.
+ * \param iv The initialization vector. This must be a read/write buffer
+ * of size \c 8 Bytes. It is updated after use.
+ * \param input The input data. This must be a readable buffer of length
+ * \p length Bytes.
+ * \param output The output data. This must be a writable buffer of length
+ * \p length Bytes.
*
- * \return 0 if successful
+ * \return \c 0 if successful.
+ * \return A negative error code on failure.
*/
int mbedtls_blowfish_crypt_cfb64( mbedtls_blowfish_context *ctx,
int mode,
@@ -172,7 +209,7 @@ int mbedtls_blowfish_crypt_cfb64( mbedtls_blowfish_context *ctx,
#if defined(MBEDTLS_CIPHER_MODE_CTR)
/**
- * \brief Blowfish-CTR buffer encryption/decryption
+ * \brief Perform a Blowfish-CTR buffer encryption/decryption operation.
*
* \warning You must never reuse a nonce value with the same key. Doing so
* would void the encryption for the two messages encrypted with
@@ -215,18 +252,24 @@ int mbedtls_blowfish_crypt_cfb64( mbedtls_blowfish_context *ctx,
* content must not be written to insecure storage and should be
* securely discarded as soon as it's no longer needed.
*
- * \param ctx Blowfish context
- * \param length The length of the data
+ * \param ctx The Blowfish context to use. This must be initialized
+ * and bound to a key.
+ * \param length The length of the input data in Bytes.
* \param nc_off The offset in the current stream_block (for resuming
- * within current cipher stream). The offset pointer to
- * should be 0 at the start of a stream.
- * \param nonce_counter The 64-bit nonce and counter.
- * \param stream_block The saved stream-block for resuming. Is overwritten
- * by the function.
- * \param input The input data stream
- * \param output The output data stream
- *
- * \return 0 if successful
+ * within current cipher stream). The offset pointer
+ * should be \c 0 at the start of a stream and must be
+ * smaller than \c 8. It is updated by this function.
+ * \param nonce_counter The 64-bit nonce and counter. This must point to a
+ * read/write buffer of length \c 8 Bytes.
+ * \param stream_block The saved stream-block for resuming. This must point to
+ * a read/write buffer of length \c 8 Bytes.
+ * \param input The input data. This must be a readable buffer of
+ * length \p length Bytes.
+ * \param output The output data. This must be a writable buffer of
+ * length \p length Bytes.
+ *
+ * \return \c 0 if successful.
+ * \return A negative error code on failure.
*/
int mbedtls_blowfish_crypt_ctr( mbedtls_blowfish_context *ctx,
size_t length,
diff --git a/thirdparty/mbedtls/include/mbedtls/bn_mul.h b/thirdparty/mbedtls/include/mbedtls/bn_mul.h
index b587317d95..2f7b72fe4c 100644
--- a/thirdparty/mbedtls/include/mbedtls/bn_mul.h
+++ b/thirdparty/mbedtls/include/mbedtls/bn_mul.h
@@ -170,19 +170,19 @@
#define MULADDC_INIT \
asm( \
- "xorq %%r8, %%r8 \n\t"
+ "xorq %%r8, %%r8\n"
#define MULADDC_CORE \
- "movq (%%rsi), %%rax \n\t" \
- "mulq %%rbx \n\t" \
- "addq $8, %%rsi \n\t" \
- "addq %%rcx, %%rax \n\t" \
- "movq %%r8, %%rcx \n\t" \
- "adcq $0, %%rdx \n\t" \
- "nop \n\t" \
- "addq %%rax, (%%rdi) \n\t" \
- "adcq %%rdx, %%rcx \n\t" \
- "addq $8, %%rdi \n\t"
+ "movq (%%rsi), %%rax\n" \
+ "mulq %%rbx\n" \
+ "addq $8, %%rsi\n" \
+ "addq %%rcx, %%rax\n" \
+ "movq %%r8, %%rcx\n" \
+ "adcq $0, %%rdx\n" \
+ "nop \n" \
+ "addq %%rax, (%%rdi)\n" \
+ "adcq %%rdx, %%rcx\n" \
+ "addq $8, %%rdi\n"
#define MULADDC_STOP \
: "+c" (c), "+D" (d), "+S" (s) \
@@ -565,9 +565,8 @@
#endif /* TriCore */
/*
- * gcc -O0 by default uses r7 for the frame pointer, so it complains about our
- * use of r7 below, unless -fomit-frame-pointer is passed. Unfortunately,
- * passing that option is not easy when building with yotta.
+ * Note, gcc -O0 by default uses r7 for the frame pointer, so it complains about
+ * our use of r7 below, unless -fomit-frame-pointer is passed.
*
* On the other hand, -fomit-frame-pointer is implied by any -Ox options with
* x !=0, which we can detect using __OPTIMIZE__ (which is also defined by
@@ -637,6 +636,23 @@
"r6", "r7", "r8", "r9", "cc" \
);
+#elif defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)
+
+#define MULADDC_INIT \
+ asm(
+
+#define MULADDC_CORE \
+ "ldr r0, [%0], #4 \n\t" \
+ "ldr r1, [%1] \n\t" \
+ "umaal r1, %2, %3, r0 \n\t" \
+ "str r1, [%1], #4 \n\t"
+
+#define MULADDC_STOP \
+ : "=r" (s), "=r" (d), "=r" (c) \
+ : "r" (b), "0" (s), "1" (d), "2" (c) \
+ : "r0", "r1", "memory" \
+ );
+
#else
#define MULADDC_INIT \
diff --git a/thirdparty/mbedtls/include/mbedtls/camellia.h b/thirdparty/mbedtls/include/mbedtls/camellia.h
index 7e4721af78..0f7c42c92d 100644
--- a/thirdparty/mbedtls/include/mbedtls/camellia.h
+++ b/thirdparty/mbedtls/include/mbedtls/camellia.h
@@ -33,11 +33,20 @@
#include <stddef.h>
#include <stdint.h>
+#include "platform_util.h"
+
#define MBEDTLS_CAMELLIA_ENCRYPT 1
#define MBEDTLS_CAMELLIA_DECRYPT 0
-#define MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH -0x0024 /**< Invalid key length. */
-#define MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH -0x0026 /**< Invalid data input length. */
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+#define MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( -0x0024 )
+#endif /* !MBEDTLS_DEPRECATED_REMOVED */
+#define MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA -0x0024 /**< Bad input data. */
+
+#define MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH -0x0026 /**< Invalid data input length. */
+
+/* MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED is deprecated and should not be used.
+ */
#define MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED -0x0027 /**< Camellia hardware accelerator failed. */
#ifdef __cplusplus
@@ -51,7 +60,7 @@ extern "C" {
/**
* \brief CAMELLIA context structure
*/
-typedef struct
+typedef struct mbedtls_camellia_context
{
int nr; /*!< number of rounds */
uint32_t rk[68]; /*!< CAMELLIA round keys */
@@ -63,52 +72,68 @@ mbedtls_camellia_context;
#endif /* MBEDTLS_CAMELLIA_ALT */
/**
- * \brief Initialize CAMELLIA context
+ * \brief Initialize a CAMELLIA context.
*
- * \param ctx CAMELLIA context to be initialized
+ * \param ctx The CAMELLIA context to be initialized.
+ * This must not be \c NULL.
*/
void mbedtls_camellia_init( mbedtls_camellia_context *ctx );
/**
- * \brief Clear CAMELLIA context
+ * \brief Clear a CAMELLIA context.
*
- * \param ctx CAMELLIA context to be cleared
+ * \param ctx The CAMELLIA context to be cleared. This may be \c NULL,
+ * in which case this function returns immediately. If it is not
+ * \c NULL, it must be initialized.
*/
void mbedtls_camellia_free( mbedtls_camellia_context *ctx );
/**
- * \brief CAMELLIA key schedule (encryption)
+ * \brief Perform a CAMELLIA key schedule operation for encryption.
*
- * \param ctx CAMELLIA context to be initialized
- * \param key encryption key
- * \param keybits must be 128, 192 or 256
+ * \param ctx The CAMELLIA context to use. This must be initialized.
+ * \param key The encryption key to use. This must be a readable buffer
+ * of size \p keybits Bits.
+ * \param keybits The length of \p key in Bits. This must be either \c 128,
+ * \c 192 or \c 256.
*
- * \return 0 if successful, or MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH
+ * \return \c 0 if successful.
+ * \return A negative error code on failure.
*/
-int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx, const unsigned char *key,
- unsigned int keybits );
+int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx,
+ const unsigned char *key,
+ unsigned int keybits );
/**
- * \brief CAMELLIA key schedule (decryption)
+ * \brief Perform a CAMELLIA key schedule operation for decryption.
*
- * \param ctx CAMELLIA context to be initialized
- * \param key decryption key
- * \param keybits must be 128, 192 or 256
+ * \param ctx The CAMELLIA context to use. This must be initialized.
+ * \param key The decryption key. This must be a readable buffer
+ * of size \p keybits Bits.
+ * \param keybits The length of \p key in Bits. This must be either \c 128,
+ * \c 192 or \c 256.
*
- * \return 0 if successful, or MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH
+ * \return \c 0 if successful.
+ * \return A negative error code on failure.
*/
-int mbedtls_camellia_setkey_dec( mbedtls_camellia_context *ctx, const unsigned char *key,
- unsigned int keybits );
+int mbedtls_camellia_setkey_dec( mbedtls_camellia_context *ctx,
+ const unsigned char *key,
+ unsigned int keybits );
/**
- * \brief CAMELLIA-ECB block encryption/decryption
- *
- * \param ctx CAMELLIA context
- * \param mode MBEDTLS_CAMELLIA_ENCRYPT or MBEDTLS_CAMELLIA_DECRYPT
- * \param input 16-byte input block
- * \param output 16-byte output block
- *
- * \return 0 if successful
+ * \brief Perform a CAMELLIA-ECB block encryption/decryption operation.
+ *
+ * \param ctx The CAMELLIA context to use. This must be initialized
+ * and bound to a key.
+ * \param mode The mode of operation. This must be either
+ * #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT.
+ * \param input The input block. This must be a readable buffer
+ * of size \c 16 Bytes.
+ * \param output The output block. This must be a writable buffer
+ * of size \c 16 Bytes.
+ *
+ * \return \c 0 if successful.
+ * \return A negative error code on failure.
*/
int mbedtls_camellia_crypt_ecb( mbedtls_camellia_context *ctx,
int mode,
@@ -117,9 +142,7 @@ int mbedtls_camellia_crypt_ecb( mbedtls_camellia_context *ctx,
#if defined(MBEDTLS_CIPHER_MODE_CBC)
/**
- * \brief CAMELLIA-CBC buffer encryption/decryption
- * Length should be a multiple of the block
- * size (16 bytes)
+ * \brief Perform a CAMELLIA-CBC buffer encryption/decryption operation.
*
* \note Upon exit, the content of the IV is updated so that you can
* call the function same function again on the following
@@ -129,15 +152,22 @@ int mbedtls_camellia_crypt_ecb( mbedtls_camellia_context *ctx,
* IV, you should either save it manually or use the cipher
* module instead.
*
- * \param ctx CAMELLIA context
- * \param mode MBEDTLS_CAMELLIA_ENCRYPT or MBEDTLS_CAMELLIA_DECRYPT
- * \param length length of the input data
- * \param iv initialization vector (updated after use)
- * \param input buffer holding the input data
- * \param output buffer holding the output data
- *
- * \return 0 if successful, or
- * MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH
+ * \param ctx The CAMELLIA context to use. This must be initialized
+ * and bound to a key.
+ * \param mode The mode of operation. This must be either
+ * #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT.
+ * \param length The length in Bytes of the input data \p input.
+ * This must be a multiple of \c 16 Bytes.
+ * \param iv The initialization vector. This must be a read/write buffer
+ * of length \c 16 Bytes. It is updated to allow streaming
+ * use as explained above.
+ * \param input The buffer holding the input data. This must point to a
+ * readable buffer of length \p length Bytes.
+ * \param output The buffer holding the output data. This must point to a
+ * writable buffer of length \p length Bytes.
+ *
+ * \return \c 0 if successful.
+ * \return A negative error code on failure.
*/
int mbedtls_camellia_crypt_cbc( mbedtls_camellia_context *ctx,
int mode,
@@ -149,11 +179,14 @@ int mbedtls_camellia_crypt_cbc( mbedtls_camellia_context *ctx,
#if defined(MBEDTLS_CIPHER_MODE_CFB)
/**
- * \brief CAMELLIA-CFB128 buffer encryption/decryption
+ * \brief Perform a CAMELLIA-CFB128 buffer encryption/decryption
+ * operation.
*
- * Note: Due to the nature of CFB you should use the same key schedule for
- * both encryption and decryption. So a context initialized with
- * mbedtls_camellia_setkey_enc() for both MBEDTLS_CAMELLIA_ENCRYPT and CAMELLIE_DECRYPT.
+ * \note Due to the nature of CFB mode, you should use the same
+ * key for both encryption and decryption. In particular, calls
+ * to this function should be preceded by a key-schedule via
+ * mbedtls_camellia_setkey_enc() regardless of whether \p mode
+ * is #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT.
*
* \note Upon exit, the content of the IV is updated so that you can
* call the function same function again on the following
@@ -163,16 +196,24 @@ int mbedtls_camellia_crypt_cbc( mbedtls_camellia_context *ctx,
* IV, you should either save it manually or use the cipher
* module instead.
*
- * \param ctx CAMELLIA context
- * \param mode MBEDTLS_CAMELLIA_ENCRYPT or MBEDTLS_CAMELLIA_DECRYPT
- * \param length length of the input data
- * \param iv_off offset in IV (updated after use)
- * \param iv initialization vector (updated after use)
- * \param input buffer holding the input data
- * \param output buffer holding the output data
- *
- * \return 0 if successful, or
- * MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH
+ * \param ctx The CAMELLIA context to use. This must be initialized
+ * and bound to a key.
+ * \param mode The mode of operation. This must be either
+ * #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT.
+ * \param length The length of the input data \p input. Any value is allowed.
+ * \param iv_off The current offset in the IV. This must be smaller
+ * than \c 16 Bytes. It is updated after this call to allow
+ * the aforementioned streaming usage.
+ * \param iv The initialization vector. This must be a read/write buffer
+ * of length \c 16 Bytes. It is updated after this call to
+ * allow the aforementioned streaming usage.
+ * \param input The buffer holding the input data. This must be a readable
+ * buffer of size \p length Bytes.
+ * \param output The buffer to hold the output data. This must be a writable
+ * buffer of length \p length Bytes.
+ *
+ * \return \c 0 if successful.
+ * \return A negative error code on failure.
*/
int mbedtls_camellia_crypt_cfb128( mbedtls_camellia_context *ctx,
int mode,
@@ -185,11 +226,13 @@ int mbedtls_camellia_crypt_cfb128( mbedtls_camellia_context *ctx,
#if defined(MBEDTLS_CIPHER_MODE_CTR)
/**
- * \brief CAMELLIA-CTR buffer encryption/decryption
+ * \brief Perform a CAMELLIA-CTR buffer encryption/decryption operation.
*
- * Note: Due to the nature of CTR you should use the same key schedule for
- * both encryption and decryption. So a context initialized with
- * mbedtls_camellia_setkey_enc() for both MBEDTLS_CAMELLIA_ENCRYPT and MBEDTLS_CAMELLIA_DECRYPT.
+ * *note Due to the nature of CTR mode, you should use the same
+ * key for both encryption and decryption. In particular, calls
+ * to this function should be preceded by a key-schedule via
+ * mbedtls_camellia_setkey_enc() regardless of whether \p mode
+ * is #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT.
*
* \warning You must never reuse a nonce value with the same key. Doing so
* would void the encryption for the two messages encrypted with
@@ -212,41 +255,49 @@ int mbedtls_camellia_crypt_cfb128( mbedtls_camellia_context *ctx,
* per-message nonce, handled by yourself, and the second one
* updated by this function internally.
*
- * For example, you might reserve the first 12 bytes for the
- * per-message nonce, and the last 4 bytes for internal use. In that
- * case, before calling this function on a new message you need to
- * set the first 12 bytes of \p nonce_counter to your chosen nonce
- * value, the last 4 to 0, and \p nc_off to 0 (which will cause \p
- * stream_block to be ignored). That way, you can encrypt at most
- * 2**96 messages of up to 2**32 blocks each with the same key.
+ * For example, you might reserve the first \c 12 Bytes for the
+ * per-message nonce, and the last \c 4 Bytes for internal use.
+ * In that case, before calling this function on a new message you
+ * need to set the first \c 12 Bytes of \p nonce_counter to your
+ * chosen nonce value, the last four to \c 0, and \p nc_off to \c 0
+ * (which will cause \p stream_block to be ignored). That way, you
+ * can encrypt at most \c 2**96 messages of up to \c 2**32 blocks
+ * each with the same key.
*
* The per-message nonce (or information sufficient to reconstruct
- * it) needs to be communicated with the ciphertext and must be unique.
- * The recommended way to ensure uniqueness is to use a message
- * counter. An alternative is to generate random nonces, but this
- * limits the number of messages that can be securely encrypted:
- * for example, with 96-bit random nonces, you should not encrypt
- * more than 2**32 messages with the same key.
+ * it) needs to be communicated with the ciphertext and must be
+ * unique. The recommended way to ensure uniqueness is to use a
+ * message counter. An alternative is to generate random nonces,
+ * but this limits the number of messages that can be securely
+ * encrypted: for example, with 96-bit random nonces, you should
+ * not encrypt more than 2**32 messages with the same key.
*
* Note that for both stategies, sizes are measured in blocks and
- * that a CAMELLIA block is 16 bytes.
+ * that a CAMELLIA block is \c 16 Bytes.
*
* \warning Upon return, \p stream_block contains sensitive data. Its
* content must not be written to insecure storage and should be
* securely discarded as soon as it's no longer needed.
*
- * \param ctx CAMELLIA context
- * \param length The length of the data
- * \param nc_off The offset in the current stream_block (for resuming
+ * \param ctx The CAMELLIA context to use. This must be initialized
+ * and bound to a key.
+ * \param length The length of the input data \p input in Bytes.
+ * Any value is allowed.
+ * \param nc_off The offset in the current \p stream_block (for resuming
* within current cipher stream). The offset pointer to
- * should be 0 at the start of a stream.
- * \param nonce_counter The 128-bit nonce and counter.
- * \param stream_block The saved stream-block for resuming. Is overwritten
- * by the function.
- * \param input The input data stream
- * \param output The output data stream
- *
- * \return 0 if successful
+ * should be \c 0 at the start of a stream. It is updated
+ * at the end of this call.
+ * \param nonce_counter The 128-bit nonce and counter. This must be a read/write
+ * buffer of length \c 16 Bytes.
+ * \param stream_block The saved stream-block for resuming. This must be a
+ * read/write buffer of length \c 16 Bytes.
+ * \param input The input data stream. This must be a readable buffer of
+ * size \p length Bytes.
+ * \param output The output data stream. This must be a writable buffer
+ * of size \p length Bytes.
+ *
+ * \return \c 0 if successful.
+ * \return A negative error code on failure.
*/
int mbedtls_camellia_crypt_ctr( mbedtls_camellia_context *ctx,
size_t length,
diff --git a/thirdparty/mbedtls/include/mbedtls/ccm.h b/thirdparty/mbedtls/include/mbedtls/ccm.h
index 5d727e7cca..3f6b8f6709 100644
--- a/thirdparty/mbedtls/include/mbedtls/ccm.h
+++ b/thirdparty/mbedtls/include/mbedtls/ccm.h
@@ -53,8 +53,9 @@
#define MBEDTLS_ERR_CCM_BAD_INPUT -0x000D /**< Bad input parameters to the function. */
#define MBEDTLS_ERR_CCM_AUTH_FAILED -0x000F /**< Authenticated decryption failed. */
-#define MBEDTLS_ERR_CCM_HW_ACCEL_FAILED -0x0011 /**< CCM hardware accelerator failed. */
+/* MBEDTLS_ERR_CCM_HW_ACCEL_FAILED is deprecated and should not be used. */
+#define MBEDTLS_ERR_CCM_HW_ACCEL_FAILED -0x0011 /**< CCM hardware accelerator failed. */
#ifdef __cplusplus
extern "C" {
@@ -68,7 +69,8 @@ extern "C" {
* \brief The CCM context-type definition. The CCM context is passed
* to the APIs called.
*/
-typedef struct {
+typedef struct mbedtls_ccm_context
+{
mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */
}
mbedtls_ccm_context;
@@ -82,7 +84,7 @@ mbedtls_ccm_context;
* to make references valid, and prepare the context
* for mbedtls_ccm_setkey() or mbedtls_ccm_free().
*
- * \param ctx The CCM context to initialize.
+ * \param ctx The CCM context to initialize. This must not be \c NULL.
*/
void mbedtls_ccm_init( mbedtls_ccm_context *ctx );
@@ -90,9 +92,10 @@ void mbedtls_ccm_init( mbedtls_ccm_context *ctx );
* \brief This function initializes the CCM context set in the
* \p ctx parameter and sets the encryption key.
*
- * \param ctx The CCM context to initialize.
+ * \param ctx The CCM context to initialize. This must be an initialized
+ * context.
* \param cipher The 128-bit block cipher to use.
- * \param key The encryption key.
+ * \param key The encryption key. This must not be \c NULL.
* \param keybits The key size in bits. This must be acceptable by the cipher.
*
* \return \c 0 on success.
@@ -107,7 +110,8 @@ int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx,
* \brief This function releases and clears the specified CCM context
* and underlying cipher sub-context.
*
- * \param ctx The CCM context to clear.
+ * \param ctx The CCM context to clear. If this is \c NULL, the function
+ * has no effect. Otherwise, this must be initialized.
*/
void mbedtls_ccm_free( mbedtls_ccm_context *ctx );
@@ -120,19 +124,27 @@ void mbedtls_ccm_free( mbedtls_ccm_context *ctx );
* \p tag = \p output + \p length, and make sure that the
* output buffer is at least \p length + \p tag_len wide.
*
- * \param ctx The CCM context to use for encryption.
+ * \param ctx The CCM context to use for encryption. This must be
+ * initialized and bound to a key.
* \param length The length of the input data in Bytes.
- * \param iv Initialization vector (nonce).
+ * \param iv The initialization vector (nonce). This must be a readable
+ * buffer of at least \p iv_len Bytes.
* \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12,
* or 13. The length L of the message length field is
* 15 - \p iv_len.
- * \param add The additional data field.
+ * \param add The additional data field. If \p add_len is greater than
+ * zero, \p add must be a readable buffer of at least that
+ * length.
* \param add_len The length of additional data in Bytes.
- * Must be less than 2^16 - 2^8.
- * \param input The buffer holding the input data.
- * \param output The buffer holding the output data.
- * Must be at least \p length Bytes wide.
- * \param tag The buffer holding the authentication field.
+ * This must be less than `2^16 - 2^8`.
+ * \param input The buffer holding the input data. If \p length is greater
+ * than zero, \p input must be a readable buffer of at least
+ * that length.
+ * \param output The buffer holding the output data. If \p length is greater
+ * than zero, \p output must be a writable buffer of at least
+ * that length.
+ * \param tag The buffer holding the authentication field. This must be a
+ * readable buffer of at least \p tag_len Bytes.
* \param tag_len The length of the authentication field to generate in Bytes:
* 4, 6, 8, 10, 12, 14 or 16.
*
@@ -158,23 +170,30 @@ int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
* the tag length has to be encoded into the \p iv passed to
* this function.
*
- * \param ctx The CCM context to use for encryption.
+ * \param ctx The CCM context to use for encryption. This must be
+ * initialized and bound to a key.
* \param length The length of the input data in Bytes.
- * \param iv Initialization vector (nonce).
+ * \param iv The initialization vector (nonce). This must be a readable
+ * buffer of at least \p iv_len Bytes.
* \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12,
* or 13. The length L of the message length field is
* 15 - \p iv_len.
- * \param add The additional data field.
+ * \param add The additional data field. This must be a readable buffer of
+ * at least \p add_len Bytes.
* \param add_len The length of additional data in Bytes.
- * Must be less than 2^16 - 2^8.
- * \param input The buffer holding the input data.
- * \param output The buffer holding the output data.
- * Must be at least \p length Bytes wide.
- * \param tag The buffer holding the authentication field.
+ * This must be less than 2^16 - 2^8.
+ * \param input The buffer holding the input data. If \p length is greater
+ * than zero, \p input must be a readable buffer of at least
+ * that length.
+ * \param output The buffer holding the output data. If \p length is greater
+ * than zero, \p output must be a writable buffer of at least
+ * that length.
+ * \param tag The buffer holding the authentication field. This must be a
+ * readable buffer of at least \p tag_len Bytes.
* \param tag_len The length of the authentication field to generate in Bytes:
* 0, 4, 6, 8, 10, 12, 14 or 16.
*
- * \warning Passing 0 as \p tag_len means that the message is no
+ * \warning Passing \c 0 as \p tag_len means that the message is no
* longer authenticated.
*
* \return \c 0 on success.
@@ -190,20 +209,27 @@ int mbedtls_ccm_star_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
* \brief This function performs a CCM authenticated decryption of a
* buffer.
*
- * \param ctx The CCM context to use for decryption.
+ * \param ctx The CCM context to use for decryption. This must be
+ * initialized and bound to a key.
* \param length The length of the input data in Bytes.
- * \param iv Initialization vector (nonce).
+ * \param iv The initialization vector (nonce). This must be a readable
+ * buffer of at least \p iv_len Bytes.
* \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12,
* or 13. The length L of the message length field is
* 15 - \p iv_len.
- * \param add The additional data field.
+ * \param add The additional data field. This must be a readable buffer
+ * of at least that \p add_len Bytes..
* \param add_len The length of additional data in Bytes.
- * Must be less than 2^16 - 2^8.
- * \param input The buffer holding the input data.
- * \param output The buffer holding the output data.
- * Must be at least \p length Bytes wide.
- * \param tag The buffer holding the authentication field.
- * \param tag_len The length of the authentication field in Bytes.
+ * This must be less than 2^16 - 2^8.
+ * \param input The buffer holding the input data. If \p length is greater
+ * than zero, \p input must be a readable buffer of at least
+ * that length.
+ * \param output The buffer holding the output data. If \p length is greater
+ * than zero, \p output must be a writable buffer of at least
+ * that length.
+ * \param tag The buffer holding the authentication field. This must be a
+ * readable buffer of at least \p tag_len Bytes.
+ * \param tag_len The length of the authentication field to generate in Bytes:
* 4, 6, 8, 10, 12, 14 or 16.
*
* \return \c 0 on success. This indicates that the message is authentic.
@@ -225,23 +251,30 @@ int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
* this function as \p tag_len. (\p tag needs to be adjusted
* accordingly.)
*
- * \param ctx The CCM context to use for decryption.
+ * \param ctx The CCM context to use for decryption. This must be
+ * initialized and bound to a key.
* \param length The length of the input data in Bytes.
- * \param iv Initialization vector (nonce).
+ * \param iv The initialization vector (nonce). This must be a readable
+ * buffer of at least \p iv_len Bytes.
* \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12,
* or 13. The length L of the message length field is
* 15 - \p iv_len.
- * \param add The additional data field.
+ * \param add The additional data field. This must be a readable buffer of
+ * at least that \p add_len Bytes.
* \param add_len The length of additional data in Bytes.
- * Must be less than 2^16 - 2^8.
- * \param input The buffer holding the input data.
- * \param output The buffer holding the output data.
- * Must be at least \p length Bytes wide.
- * \param tag The buffer holding the authentication field.
+ * This must be less than 2^16 - 2^8.
+ * \param input The buffer holding the input data. If \p length is greater
+ * than zero, \p input must be a readable buffer of at least
+ * that length.
+ * \param output The buffer holding the output data. If \p length is greater
+ * than zero, \p output must be a writable buffer of at least
+ * that length.
+ * \param tag The buffer holding the authentication field. This must be a
+ * readable buffer of at least \p tag_len Bytes.
* \param tag_len The length of the authentication field in Bytes.
* 0, 4, 6, 8, 10, 12, 14 or 16.
*
- * \warning Passing 0 as \p tag_len means that the message is no
+ * \warning Passing \c 0 as \p tag_len means that the message is nos
* longer authenticated.
*
* \return \c 0 on success.
diff --git a/thirdparty/mbedtls/include/mbedtls/chacha20.h b/thirdparty/mbedtls/include/mbedtls/chacha20.h
index 47bd7d38b9..2ae5e6e5f4 100644
--- a/thirdparty/mbedtls/include/mbedtls/chacha20.h
+++ b/thirdparty/mbedtls/include/mbedtls/chacha20.h
@@ -43,7 +43,13 @@
#include <stddef.h>
#define MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA -0x0051 /**< Invalid input parameter(s). */
+
+/* MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE is deprecated and should not be
+ * used. */
#define MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE -0x0053 /**< Feature not available. For example, s part of the API is not implemented. */
+
+/* MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED is deprecated and should not be used.
+ */
#define MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED -0x0055 /**< Chacha20 hardware accelerator failed. */
#ifdef __cplusplus
@@ -52,7 +58,7 @@ extern "C" {
#if !defined(MBEDTLS_CHACHA20_ALT)
-typedef struct
+typedef struct mbedtls_chacha20_context
{
uint32_t state[16]; /*! The state (before round operations). */
uint8_t keystream8[64]; /*! Leftover keystream bytes. */
@@ -77,13 +83,18 @@ mbedtls_chacha20_context;
* \c mbedtls_chacha20_free().
*
* \param ctx The ChaCha20 context to initialize.
+ * This must not be \c NULL.
*/
void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx );
/**
- * \brief This function releases and clears the specified ChaCha20 context.
+ * \brief This function releases and clears the specified
+ * ChaCha20 context.
+ *
+ * \param ctx The ChaCha20 context to clear. This may be \c NULL,
+ * in which case this function is a no-op. If it is not
+ * \c NULL, it must point to an initialized context.
*
- * \param ctx The ChaCha20 context to clear.
*/
void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx );
@@ -96,7 +107,9 @@ void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx );
* \c mbedtls_chacha_update().
*
* \param ctx The ChaCha20 context to which the key should be bound.
- * \param key The encryption/decryption key. Must be 32 bytes in length.
+ * It must be initialized.
+ * \param key The encryption/decryption key. This must be \c 32 Bytes
+ * in length.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if ctx or key is NULL.
@@ -115,8 +128,9 @@ int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx,
* messages encrypted with the same nonce and key.
*
* \param ctx The ChaCha20 context to which the nonce should be bound.
- * \param nonce The nonce. Must be 12 bytes in size.
- * \param counter The initial counter value. This is usually 0.
+ * It must be initialized and bound to a key.
+ * \param nonce The nonce. This must be \c 12 Bytes in size.
+ * \param counter The initial counter value. This is usually \c 0.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if ctx or nonce is
@@ -144,16 +158,16 @@ int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx,
* key and nonce.
*
* \param ctx The ChaCha20 context to use for encryption or decryption.
- * \param size The length of the input data in bytes.
+ * It must be initialized and bound to a key and nonce.
+ * \param size The length of the input data in Bytes.
* \param input The buffer holding the input data.
- * This pointer can be NULL if size == 0.
+ * This pointer can be \c NULL if `size == 0`.
* \param output The buffer holding the output data.
- * Must be able to hold \p size bytes.
- * This pointer can be NULL if size == 0.
+ * This must be able to hold \p size Bytes.
+ * This pointer can be \c NULL if `size == 0`.
*
* \return \c 0 on success.
- * \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if the ctx, input, or
- * output pointers are NULL.
+ * \return A negative error code on failure.
*/
int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx,
size_t size,
@@ -174,19 +188,19 @@ int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx,
* \note The \p input and \p output pointers must either be equal or
* point to non-overlapping buffers.
*
- * \param key The encryption/decryption key. Must be 32 bytes in length.
- * \param nonce The nonce. Must be 12 bytes in size.
- * \param counter The initial counter value. This is usually 0.
- * \param size The length of the input data in bytes.
+ * \param key The encryption/decryption key.
+ * This must be \c 32 Bytes in length.
+ * \param nonce The nonce. This must be \c 12 Bytes in size.
+ * \param counter The initial counter value. This is usually \c 0.
+ * \param size The length of the input data in Bytes.
* \param input The buffer holding the input data.
- * This pointer can be NULL if size == 0.
+ * This pointer can be \c NULL if `size == 0`.
* \param output The buffer holding the output data.
- * Must be able to hold \p size bytes.
- * This pointer can be NULL if size == 0.
+ * This must be able to hold \p size Bytes.
+ * This pointer can be \c NULL if `size == 0`.
*
* \return \c 0 on success.
- * \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if key, nonce, input,
- * or output is NULL.
+ * \return A negative error code on failure.
*/
int mbedtls_chacha20_crypt( const unsigned char key[32],
const unsigned char nonce[12],
diff --git a/thirdparty/mbedtls/include/mbedtls/chachapoly.h b/thirdparty/mbedtls/include/mbedtls/chachapoly.h
index 42b2b230c5..49e615d278 100644
--- a/thirdparty/mbedtls/include/mbedtls/chachapoly.h
+++ b/thirdparty/mbedtls/include/mbedtls/chachapoly.h
@@ -60,7 +60,7 @@ mbedtls_chachapoly_mode_t;
#include "chacha20.h"
-typedef struct
+typedef struct mbedtls_chachapoly_context
{
mbedtls_chacha20_context chacha20_ctx; /**< The ChaCha20 context. */
mbedtls_poly1305_context poly1305_ctx; /**< The Poly1305 context. */
@@ -115,27 +115,29 @@ mbedtls_chachapoly_context;
* all previous outputs of \c mbedtls_chachapoly_update(),
* otherwise you can now safely use the plaintext.
*
- * \param ctx The ChachaPoly context to initialize.
+ * \param ctx The ChachaPoly context to initialize. Must not be \c NULL.
*/
void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx );
/**
- * \brief This function releases and clears the specified ChaCha20-Poly1305 context.
+ * \brief This function releases and clears the specified
+ * ChaCha20-Poly1305 context.
*
- * \param ctx The ChachaPoly context to clear.
+ * \param ctx The ChachaPoly context to clear. This may be \c NULL, in which
+ * case this function is a no-op.
*/
void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx );
/**
- * \brief This function sets the ChaCha20-Poly1305 symmetric encryption key.
+ * \brief This function sets the ChaCha20-Poly1305
+ * symmetric encryption key.
*
* \param ctx The ChaCha20-Poly1305 context to which the key should be
- * bound.
- * \param key The 256-bit (32 bytes) key.
+ * bound. This must be initialized.
+ * \param key The \c 256 Bit (\c 32 Bytes) key.
*
* \return \c 0 on success.
- * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA
- * if \p ctx or \p key are NULL.
+ * \return A negative error code on failure.
*/
int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx,
const unsigned char key[32] );
@@ -155,14 +157,15 @@ int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx,
* \warning Decryption with the piecewise API is discouraged, see the
* warning on \c mbedtls_chachapoly_init().
*
- * \param ctx The ChaCha20-Poly1305 context.
- * \param nonce The nonce/IV to use for the message. Must be 12 bytes.
+ * \param ctx The ChaCha20-Poly1305 context. This must be initialized
+ * and bound to a key.
+ * \param nonce The nonce/IV to use for the message.
+ * This must be a redable buffer of length \c 12 Bytes.
* \param mode The operation to perform: #MBEDTLS_CHACHAPOLY_ENCRYPT or
* #MBEDTLS_CHACHAPOLY_DECRYPT (discouraged, see warning).
*
* \return \c 0 on success.
- * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA
- * if \p ctx or \p mac are NULL.
+ * \return A negative error code on failure.
*/
int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx,
const unsigned char nonce[12],
@@ -193,11 +196,12 @@ int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx,
* \warning Decryption with the piecewise API is discouraged, see the
* warning on \c mbedtls_chachapoly_init().
*
- * \param ctx The ChaCha20-Poly1305 context to use.
- * \param aad_len The length (in bytes) of the AAD. The length has no
+ * \param ctx The ChaCha20-Poly1305 context. This must be initialized
+ * and bound to a key.
+ * \param aad_len The length in Bytes of the AAD. The length has no
* restrictions.
* \param aad Buffer containing the AAD.
- * This pointer can be NULL if aad_len == 0.
+ * This pointer can be \c NULL if `aad_len == 0`.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA
@@ -227,20 +231,19 @@ int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx,
* \warning Decryption with the piecewise API is discouraged, see the
* warning on \c mbedtls_chachapoly_init().
*
- * \param ctx The ChaCha20-Poly1305 context to use.
+ * \param ctx The ChaCha20-Poly1305 context to use. This must be initialized.
* \param len The length (in bytes) of the data to encrypt or decrypt.
* \param input The buffer containing the data to encrypt or decrypt.
- * This pointer can be NULL if len == 0.
- * \param output The buffer to where the encrypted or decrypted data is written.
- * Must be able to hold \p len bytes.
- * This pointer can be NULL if len == 0.
+ * This pointer can be \c NULL if `len == 0`.
+ * \param output The buffer to where the encrypted or decrypted data is
+ * written. This must be able to hold \p len bytes.
+ * This pointer can be \c NULL if `len == 0`.
*
* \return \c 0 on success.
- * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA
- * if \p ctx, \p input, or \p output are NULL.
* \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE
* if the operation has not been started or has been
* finished.
+ * \return Another negative error code on other kinds of failure.
*/
int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx,
size_t len,
@@ -251,18 +254,17 @@ int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx,
* \brief This function finished the ChaCha20-Poly1305 operation and
* generates the MAC (authentication tag).
*
- * \param ctx The ChaCha20-Poly1305 context to use.
+ * \param ctx The ChaCha20-Poly1305 context to use. This must be initialized.
* \param mac The buffer to where the 128-bit (16 bytes) MAC is written.
*
* \warning Decryption with the piecewise API is discouraged, see the
* warning on \c mbedtls_chachapoly_init().
*
* \return \c 0 on success.
- * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA
- * if \p ctx or \p mac are NULL.
* \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE
* if the operation has not been started or has been
* finished.
+ * \return Another negative error code on other kinds of failure.
*/
int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx,
unsigned char mac[16] );
@@ -280,20 +282,21 @@ int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx,
* and key.
*
* \param ctx The ChaCha20-Poly1305 context to use (holds the key).
+ * This must be initialized.
* \param length The length (in bytes) of the data to encrypt or decrypt.
* \param nonce The 96-bit (12 bytes) nonce/IV to use.
- * \param aad The buffer containing the additional authenticated data (AAD).
- * This pointer can be NULL if aad_len == 0.
+ * \param aad The buffer containing the additional authenticated
+ * data (AAD). This pointer can be \c NULL if `aad_len == 0`.
* \param aad_len The length (in bytes) of the AAD data to process.
* \param input The buffer containing the data to encrypt or decrypt.
- * This pointer can be NULL if ilen == 0.
- * \param output The buffer to where the encrypted or decrypted data is written.
- * This pointer can be NULL if ilen == 0.
- * \param tag The buffer to where the computed 128-bit (16 bytes) MAC is written.
+ * This pointer can be \c NULL if `ilen == 0`.
+ * \param output The buffer to where the encrypted or decrypted data
+ * is written. This pointer can be \c NULL if `ilen == 0`.
+ * \param tag The buffer to where the computed 128-bit (16 bytes) MAC
+ * is written. This must not be \c NULL.
*
* \return \c 0 on success.
- * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA
- * if one or more of the required parameters are NULL.
+ * \return A negative error code on failure.
*/
int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx,
size_t length,
@@ -312,22 +315,22 @@ int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx,
* \c mbedtls_chachapoly_setkey().
*
* \param ctx The ChaCha20-Poly1305 context to use (holds the key).
- * \param length The length (in bytes) of the data to decrypt.
- * \param nonce The 96-bit (12 bytes) nonce/IV to use.
+ * \param length The length (in Bytes) of the data to decrypt.
+ * \param nonce The \c 96 Bit (\c 12 bytes) nonce/IV to use.
* \param aad The buffer containing the additional authenticated data (AAD).
- * This pointer can be NULL if aad_len == 0.
+ * This pointer can be \c NULL if `aad_len == 0`.
* \param aad_len The length (in bytes) of the AAD data to process.
* \param tag The buffer holding the authentication tag.
+ * This must be a readable buffer of length \c 16 Bytes.
* \param input The buffer containing the data to decrypt.
- * This pointer can be NULL if ilen == 0.
+ * This pointer can be \c NULL if `ilen == 0`.
* \param output The buffer to where the decrypted data is written.
- * This pointer can be NULL if ilen == 0.
+ * This pointer can be \c NULL if `ilen == 0`.
*
* \return \c 0 on success.
- * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA
- * if one or more of the required parameters are NULL.
* \return #MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED
* if the data was not authentic.
+ * \return Another negative error code on other kinds of failure.
*/
int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx,
size_t length,
diff --git a/thirdparty/mbedtls/include/mbedtls/check_config.h b/thirdparty/mbedtls/include/mbedtls/check_config.h
index 9e6bb8a46a..b86e5807e0 100644
--- a/thirdparty/mbedtls/include/mbedtls/check_config.h
+++ b/thirdparty/mbedtls/include/mbedtls/check_config.h
@@ -108,6 +108,17 @@
#error "MBEDTLS_ECJPAKE_C defined, but not all prerequisites"
#endif
+#if defined(MBEDTLS_ECP_RESTARTABLE) && \
+ ( defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) || \
+ defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) || \
+ defined(MBEDTLS_ECDSA_SIGN_ALT) || \
+ defined(MBEDTLS_ECDSA_VERIFY_ALT) || \
+ defined(MBEDTLS_ECDSA_GENKEY_ALT) || \
+ defined(MBEDTLS_ECP_INTERNAL_ALT) || \
+ defined(MBEDTLS_ECP_ALT) )
+#error "MBEDTLS_ECP_RESTARTABLE defined, but it cannot coexist with an alternative ECP implementation"
+#endif
+
#if defined(MBEDTLS_ECDSA_DETERMINISTIC) && !defined(MBEDTLS_HMAC_DRBG_C)
#error "MBEDTLS_ECDSA_DETERMINISTIC defined, but not all prerequisites"
#endif
@@ -127,6 +138,10 @@
#error "MBEDTLS_ECP_C defined, but not all prerequisites"
#endif
+#if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_ASN1_PARSE_C)
+#error "MBEDTLS_PK_PARSE_C defined, but not all prerequesites"
+#endif
+
#if defined(MBEDTLS_ENTROPY_C) && (!defined(MBEDTLS_SHA512_C) && \
!defined(MBEDTLS_SHA256_C))
#error "MBEDTLS_ENTROPY_C defined, but not all prerequisites"
diff --git a/thirdparty/mbedtls/include/mbedtls/cipher.h b/thirdparty/mbedtls/include/mbedtls/cipher.h
index ea0ce983f1..922b6c32c6 100644
--- a/thirdparty/mbedtls/include/mbedtls/cipher.h
+++ b/thirdparty/mbedtls/include/mbedtls/cipher.h
@@ -36,6 +36,7 @@
#endif
#include <stddef.h>
+#include "mbedtls/platform_util.h"
#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
#define MBEDTLS_CIPHER_MODE_AEAD
@@ -45,7 +46,8 @@
#define MBEDTLS_CIPHER_MODE_WITH_PADDING
#endif
-#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER)
+#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) || \
+ defined(MBEDTLS_CHACHA20_C)
#define MBEDTLS_CIPHER_MODE_STREAM
#endif
@@ -61,6 +63,8 @@
#define MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED -0x6280 /**< Decryption of block requires a full block. */
#define MBEDTLS_ERR_CIPHER_AUTH_FAILED -0x6300 /**< Authentication failed (for AEAD modes). */
#define MBEDTLS_ERR_CIPHER_INVALID_CONTEXT -0x6380 /**< The context is invalid. For example, because it was freed. */
+
+/* MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED -0x6400 /**< Cipher hardware accelerator failed. */
#define MBEDTLS_CIPHER_VARIABLE_IV_LEN 0x01 /**< Cipher accepts IVs of variable length. */
@@ -235,7 +239,8 @@ typedef struct mbedtls_cmac_context_t mbedtls_cmac_context_t;
* Cipher information. Allows calling cipher functions
* in a generic way.
*/
-typedef struct {
+typedef struct mbedtls_cipher_info_t
+{
/** Full cipher identifier. For example,
* MBEDTLS_CIPHER_AES_256_CBC.
*/
@@ -276,7 +281,8 @@ typedef struct {
/**
* Generic cipher context.
*/
-typedef struct {
+typedef struct mbedtls_cipher_context_t
+{
/** Information about the associated cipher. */
const mbedtls_cipher_info_t *cipher_info;
@@ -331,11 +337,12 @@ const int *mbedtls_cipher_list( void );
* \brief This function retrieves the cipher-information
* structure associated with the given cipher name.
*
- * \param cipher_name Name of the cipher to search for.
+ * \param cipher_name Name of the cipher to search for. This must not be
+ * \c NULL.
*
* \return The cipher information structure associated with the
* given \p cipher_name.
- * \return NULL if the associated cipher information is not found.
+ * \return \c NULL if the associated cipher information is not found.
*/
const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name );
@@ -347,7 +354,7 @@ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher
*
* \return The cipher information structure associated with the
* given \p cipher_type.
- * \return NULL if the associated cipher information is not found.
+ * \return \c NULL if the associated cipher information is not found.
*/
const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type );
@@ -363,7 +370,7 @@ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher
*
* \return The cipher information structure associated with the
* given \p cipher_id.
- * \return NULL if the associated cipher information is not found.
+ * \return \c NULL if the associated cipher information is not found.
*/
const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_cipher_id_t cipher_id,
int key_bitlen,
@@ -371,6 +378,8 @@ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_ciph
/**
* \brief This function initializes a \p cipher_context as NONE.
+ *
+ * \param ctx The context to be initialized. This must not be \c NULL.
*/
void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx );
@@ -378,6 +387,10 @@ void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx );
* \brief This function frees and clears the cipher-specific
* context of \p ctx. Freeing \p ctx itself remains the
* responsibility of the caller.
+ *
+ * \param ctx The context to be freed. If this is \c NULL, the
+ * function has no effect, otherwise this must point to an
+ * initialized context.
*/
void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx );
@@ -387,7 +400,7 @@ void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx );
* structure with the appropriate values. It also clears
* the structure.
*
- * \param ctx The context to initialize. May not be NULL.
+ * \param ctx The context to initialize. This must be initialized.
* \param cipher_info The cipher to use.
*
* \return \c 0 on success.
@@ -400,19 +413,22 @@ void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx );
* In future versions, the caller will be required to call
* mbedtls_cipher_init() on the structure first.
*/
-int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info );
+int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx,
+ const mbedtls_cipher_info_t *cipher_info );
/**
* \brief This function returns the block size of the given cipher.
*
- * \param ctx The context of the cipher. Must be initialized.
+ * \param ctx The context of the cipher. This must be initialized.
*
- * \return The size of the blocks of the cipher.
- * \return 0 if \p ctx has not been initialized.
+ * \return The block size of the underlying cipher.
+ * \return \c 0 if \p ctx has not been initialized.
*/
-static inline unsigned int mbedtls_cipher_get_block_size( const mbedtls_cipher_context_t *ctx )
+static inline unsigned int mbedtls_cipher_get_block_size(
+ const mbedtls_cipher_context_t *ctx )
{
- if( NULL == ctx || NULL == ctx->cipher_info )
+ MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, 0 );
+ if( ctx->cipher_info == NULL )
return 0;
return ctx->cipher_info->block_size;
@@ -422,14 +438,16 @@ static inline unsigned int mbedtls_cipher_get_block_size( const mbedtls_cipher_c
* \brief This function returns the mode of operation for
* the cipher. For example, MBEDTLS_MODE_CBC.
*
- * \param ctx The context of the cipher. Must be initialized.
+ * \param ctx The context of the cipher. This must be initialized.
*
* \return The mode of operation.
* \return #MBEDTLS_MODE_NONE if \p ctx has not been initialized.
*/
-static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode( const mbedtls_cipher_context_t *ctx )
+static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode(
+ const mbedtls_cipher_context_t *ctx )
{
- if( NULL == ctx || NULL == ctx->cipher_info )
+ MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, MBEDTLS_MODE_NONE );
+ if( ctx->cipher_info == NULL )
return MBEDTLS_MODE_NONE;
return ctx->cipher_info->mode;
@@ -439,15 +457,17 @@ static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode( const mbedtl
* \brief This function returns the size of the IV or nonce
* of the cipher, in Bytes.
*
- * \param ctx The context of the cipher. Must be initialized.
+ * \param ctx The context of the cipher. This must be initialized.
*
* \return The recommended IV size if no IV has been set.
* \return \c 0 for ciphers not using an IV or a nonce.
* \return The actual size if an IV has been set.
*/
-static inline int mbedtls_cipher_get_iv_size( const mbedtls_cipher_context_t *ctx )
+static inline int mbedtls_cipher_get_iv_size(
+ const mbedtls_cipher_context_t *ctx )
{
- if( NULL == ctx || NULL == ctx->cipher_info )
+ MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, 0 );
+ if( ctx->cipher_info == NULL )
return 0;
if( ctx->iv_size != 0 )
@@ -459,14 +479,17 @@ static inline int mbedtls_cipher_get_iv_size( const mbedtls_cipher_context_t *ct
/**
* \brief This function returns the type of the given cipher.
*
- * \param ctx The context of the cipher. Must be initialized.
+ * \param ctx The context of the cipher. This must be initialized.
*
* \return The type of the cipher.
* \return #MBEDTLS_CIPHER_NONE if \p ctx has not been initialized.
*/
-static inline mbedtls_cipher_type_t mbedtls_cipher_get_type( const mbedtls_cipher_context_t *ctx )
+static inline mbedtls_cipher_type_t mbedtls_cipher_get_type(
+ const mbedtls_cipher_context_t *ctx )
{
- if( NULL == ctx || NULL == ctx->cipher_info )
+ MBEDTLS_INTERNAL_VALIDATE_RET(
+ ctx != NULL, MBEDTLS_CIPHER_NONE );
+ if( ctx->cipher_info == NULL )
return MBEDTLS_CIPHER_NONE;
return ctx->cipher_info->type;
@@ -476,14 +499,16 @@ static inline mbedtls_cipher_type_t mbedtls_cipher_get_type( const mbedtls_ciphe
* \brief This function returns the name of the given cipher
* as a string.
*
- * \param ctx The context of the cipher. Must be initialized.
+ * \param ctx The context of the cipher. This must be initialized.
*
* \return The name of the cipher.
* \return NULL if \p ctx has not been not initialized.
*/
-static inline const char *mbedtls_cipher_get_name( const mbedtls_cipher_context_t *ctx )
+static inline const char *mbedtls_cipher_get_name(
+ const mbedtls_cipher_context_t *ctx )
{
- if( NULL == ctx || NULL == ctx->cipher_info )
+ MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, 0 );
+ if( ctx->cipher_info == NULL )
return 0;
return ctx->cipher_info->name;
@@ -492,15 +517,18 @@ static inline const char *mbedtls_cipher_get_name( const mbedtls_cipher_context_
/**
* \brief This function returns the key length of the cipher.
*
- * \param ctx The context of the cipher. Must be initialized.
+ * \param ctx The context of the cipher. This must be initialized.
*
* \return The key length of the cipher in bits.
* \return #MBEDTLS_KEY_LENGTH_NONE if ctx \p has not been
* initialized.
*/
-static inline int mbedtls_cipher_get_key_bitlen( const mbedtls_cipher_context_t *ctx )
+static inline int mbedtls_cipher_get_key_bitlen(
+ const mbedtls_cipher_context_t *ctx )
{
- if( NULL == ctx || NULL == ctx->cipher_info )
+ MBEDTLS_INTERNAL_VALIDATE_RET(
+ ctx != NULL, MBEDTLS_KEY_LENGTH_NONE );
+ if( ctx->cipher_info == NULL )
return MBEDTLS_KEY_LENGTH_NONE;
return (int) ctx->cipher_info->key_bitlen;
@@ -509,14 +537,17 @@ static inline int mbedtls_cipher_get_key_bitlen( const mbedtls_cipher_context_t
/**
* \brief This function returns the operation of the given cipher.
*
- * \param ctx The context of the cipher. Must be initialized.
+ * \param ctx The context of the cipher. This must be initialized.
*
* \return The type of operation: #MBEDTLS_ENCRYPT or #MBEDTLS_DECRYPT.
* \return #MBEDTLS_OPERATION_NONE if \p ctx has not been initialized.
*/
-static inline mbedtls_operation_t mbedtls_cipher_get_operation( const mbedtls_cipher_context_t *ctx )
+static inline mbedtls_operation_t mbedtls_cipher_get_operation(
+ const mbedtls_cipher_context_t *ctx )
{
- if( NULL == ctx || NULL == ctx->cipher_info )
+ MBEDTLS_INTERNAL_VALIDATE_RET(
+ ctx != NULL, MBEDTLS_OPERATION_NONE );
+ if( ctx->cipher_info == NULL )
return MBEDTLS_OPERATION_NONE;
return ctx->operation;
@@ -525,11 +556,11 @@ static inline mbedtls_operation_t mbedtls_cipher_get_operation( const mbedtls_ci
/**
* \brief This function sets the key to use with the given context.
*
- * \param ctx The generic cipher context. May not be NULL. Must have
- * been initialized using mbedtls_cipher_info_from_type()
- * or mbedtls_cipher_info_from_string().
- * \param key The key to use.
- * \param key_bitlen The key length to use, in bits.
+ * \param ctx The generic cipher context. This must be initialized and
+ * bound to a cipher information structure.
+ * \param key The key to use. This must be a readable buffer of at
+ * least \p key_bitlen Bits.
+ * \param key_bitlen The key length to use, in Bits.
* \param operation The operation that the key will be used for:
* #MBEDTLS_ENCRYPT or #MBEDTLS_DECRYPT.
*
@@ -538,8 +569,10 @@ static inline mbedtls_operation_t mbedtls_cipher_get_operation( const mbedtls_ci
* parameter-verification failure.
* \return A cipher-specific error code on failure.
*/
-int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *key,
- int key_bitlen, const mbedtls_operation_t operation );
+int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx,
+ const unsigned char *key,
+ int key_bitlen,
+ const mbedtls_operation_t operation );
#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
/**
@@ -548,7 +581,8 @@ int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *k
*
* The default passing mode is PKCS7 padding.
*
- * \param ctx The generic cipher context.
+ * \param ctx The generic cipher context. This must be initialized and
+ * bound to a cipher information structure.
* \param mode The padding mode.
*
* \return \c 0 on success.
@@ -557,7 +591,8 @@ int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *k
* \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if the cipher mode
* does not support padding.
*/
-int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode );
+int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx,
+ mbedtls_cipher_padding_t mode );
#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
/**
@@ -567,8 +602,10 @@ int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_ciph
* \note Some ciphers do not use IVs nor nonce. For these
* ciphers, this function has no effect.
*
- * \param ctx The generic cipher context.
- * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers.
+ * \param ctx The generic cipher context. This must be initialized and
+ * bound to a cipher information structure.
+ * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. This
+ * must be a readable buffer of at least \p iv_len Bytes.
* \param iv_len The IV length for ciphers with variable-size IV.
* This parameter is discarded by ciphers with fixed-size IV.
*
@@ -577,12 +614,13 @@ int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_ciph
* parameter-verification failure.
*/
int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx,
- const unsigned char *iv, size_t iv_len );
+ const unsigned char *iv,
+ size_t iv_len );
/**
* \brief This function resets the cipher state.
*
- * \param ctx The generic cipher context.
+ * \param ctx The generic cipher context. This must be initialized.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on
@@ -594,11 +632,13 @@ int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx );
/**
* \brief This function adds additional data for AEAD ciphers.
* Currently supported with GCM and ChaCha20+Poly1305.
- * Must be called exactly once, after mbedtls_cipher_reset().
+ * This must be called exactly once, after
+ * mbedtls_cipher_reset().
*
- * \param ctx The generic cipher context.
- * \param ad The additional data to use.
- * \param ad_len the Length of \p ad.
+ * \param ctx The generic cipher context. This must be initialized.
+ * \param ad The additional data to use. This must be a readable
+ * buffer of at least \p ad_len Bytes.
+ * \param ad_len the Length of \p ad Bytes.
*
* \return \c 0 on success.
* \return A specific error code on failure.
@@ -622,14 +662,17 @@ int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx,
* mbedtls_cipher_finish(), must have \p ilen as a
* multiple of the block size of the cipher.
*
- * \param ctx The generic cipher context.
- * \param input The buffer holding the input data.
+ * \param ctx The generic cipher context. This must be initialized and
+ * bound to a key.
+ * \param input The buffer holding the input data. This must be a
+ * readable buffer of at least \p ilen Bytes.
* \param ilen The length of the input data.
- * \param output The buffer for the output data. Must be able to hold at
- * least \p ilen + block_size. Must not be the same buffer
- * as input.
+ * \param output The buffer for the output data. This must be able to
+ * hold at least `ilen + block_size`. This must not be the
+ * same buffer as \p input.
* \param olen The length of the output data, to be updated with the
- * actual number of Bytes written.
+ * actual number of Bytes written. This must not be
+ * \c NULL.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on
@@ -647,9 +690,12 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i
* contained in it is padded to the size of
* the last block, and written to the \p output buffer.
*
- * \param ctx The generic cipher context.
- * \param output The buffer to write data to. Needs block_size available.
+ * \param ctx The generic cipher context. This must be initialized and
+ * bound to a key.
+ * \param output The buffer to write data to. This needs to be a writable
+ * buffer of at least \p block_size Bytes.
* \param olen The length of the data written to the \p output buffer.
+ * This may not be \c NULL.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on
@@ -667,10 +713,14 @@ int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx,
/**
* \brief This function writes a tag for AEAD ciphers.
* Currently supported with GCM and ChaCha20+Poly1305.
- * Must be called after mbedtls_cipher_finish().
- *
- * \param ctx The generic cipher context.
- * \param tag The buffer to write the tag to.
+ * This must be called after mbedtls_cipher_finish().
+ *
+ * \param ctx The generic cipher context. This must be initialized,
+ * bound to a key, and have just completed a cipher
+ * operation through mbedtls_cipher_finish() the tag for
+ * which should be written.
+ * \param tag The buffer to write the tag to. This must be a writable
+ * buffer of at least \p tag_len Bytes.
* \param tag_len The length of the tag to write.
*
* \return \c 0 on success.
@@ -682,10 +732,11 @@ int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx,
/**
* \brief This function checks the tag for AEAD ciphers.
* Currently supported with GCM and ChaCha20+Poly1305.
- * Must be called after mbedtls_cipher_finish().
+ * This must be called after mbedtls_cipher_finish().
*
- * \param ctx The generic cipher context.
- * \param tag The buffer holding the tag.
+ * \param ctx The generic cipher context. This must be initialized.
+ * \param tag The buffer holding the tag. This must be a readable
+ * buffer of at least \p tag_len Bytes.
* \param tag_len The length of the tag to check.
*
* \return \c 0 on success.
@@ -699,18 +750,22 @@ int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx,
* \brief The generic all-in-one encryption/decryption function,
* for all ciphers except AEAD constructs.
*
- * \param ctx The generic cipher context.
+ * \param ctx The generic cipher context. This must be initialized.
* \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers.
+ * This must be a readable buffer of at least \p iv_len
+ * Bytes.
* \param iv_len The IV length for ciphers with variable-size IV.
* This parameter is discarded by ciphers with fixed-size
* IV.
- * \param input The buffer holding the input data.
- * \param ilen The length of the input data.
- * \param output The buffer for the output data. Must be able to hold at
- * least \p ilen + block_size. Must not be the same buffer
- * as input.
+ * \param input The buffer holding the input data. This must be a
+ * readable buffer of at least \p ilen Bytes.
+ * \param ilen The length of the input data in Bytes.
+ * \param output The buffer for the output data. This must be able to
+ * hold at least `ilen + block_size`. This must not be the
+ * same buffer as \p input.
* \param olen The length of the output data, to be updated with the
- * actual number of Bytes written.
+ * actual number of Bytes written. This must not be
+ * \c NULL.
*
* \note Some ciphers do not use IVs nor nonce. For these
* ciphers, use \p iv = NULL and \p iv_len = 0.
@@ -733,19 +788,26 @@ int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx,
/**
* \brief The generic autenticated encryption (AEAD) function.
*
- * \param ctx The generic cipher context.
+ * \param ctx The generic cipher context. This must be initialized and
+ * bound to a key.
* \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers.
+ * This must be a readable buffer of at least \p iv_len
+ * Bytes.
* \param iv_len The IV length for ciphers with variable-size IV.
* This parameter is discarded by ciphers with fixed-size IV.
- * \param ad The additional data to authenticate.
+ * \param ad The additional data to authenticate. This must be a
+ * readable buffer of at least \p ad_len Bytes.
* \param ad_len The length of \p ad.
- * \param input The buffer holding the input data.
+ * \param input The buffer holding the input data. This must be a
+ * readable buffer of at least \p ilen Bytes.
* \param ilen The length of the input data.
- * \param output The buffer for the output data.
- * Must be able to hold at least \p ilen.
+ * \param output The buffer for the output data. This must be able to
+ * hold at least \p ilen Bytes.
* \param olen The length of the output data, to be updated with the
- * actual number of Bytes written.
- * \param tag The buffer for the authentication tag.
+ * actual number of Bytes written. This must not be
+ * \c NULL.
+ * \param tag The buffer for the authentication tag. This must be a
+ * writable buffer of at least \p tag_len Bytes.
* \param tag_len The desired length of the authentication tag.
*
* \return \c 0 on success.
@@ -767,19 +829,26 @@ int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx,
* is zeroed out to prevent the unauthentic plaintext being
* used, making this interface safer.
*
- * \param ctx The generic cipher context.
+ * \param ctx The generic cipher context. This must be initialized and
+ * and bound to a key.
* \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers.
+ * This must be a readable buffer of at least \p iv_len
+ * Bytes.
* \param iv_len The IV length for ciphers with variable-size IV.
* This parameter is discarded by ciphers with fixed-size IV.
- * \param ad The additional data to be authenticated.
+ * \param ad The additional data to be authenticated. This must be a
+ * readable buffer of at least \p ad_len Bytes.
* \param ad_len The length of \p ad.
- * \param input The buffer holding the input data.
+ * \param input The buffer holding the input data. This must be a
+ * readable buffer of at least \p ilen Bytes.
* \param ilen The length of the input data.
* \param output The buffer for the output data.
- * Must be able to hold at least \p ilen.
+ * This must be able to hold at least \p ilen Bytes.
* \param olen The length of the output data, to be updated with the
- * actual number of Bytes written.
- * \param tag The buffer holding the authentication tag.
+ * actual number of Bytes written. This must not be
+ * \c NULL.
+ * \param tag The buffer holding the authentication tag. This must be
+ * a readable buffer of at least \p tag_len Bytes.
* \param tag_len The length of the authentication tag.
*
* \return \c 0 on success.
diff --git a/thirdparty/mbedtls/include/mbedtls/cmac.h b/thirdparty/mbedtls/include/mbedtls/cmac.h
index a4fd552565..c196793531 100644
--- a/thirdparty/mbedtls/include/mbedtls/cmac.h
+++ b/thirdparty/mbedtls/include/mbedtls/cmac.h
@@ -34,6 +34,7 @@
extern "C" {
#endif
+/* MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED -0x007A /**< CMAC hardware accelerator failed. */
#define MBEDTLS_AES_BLOCK_SIZE 16
diff --git a/thirdparty/mbedtls/include/mbedtls/config.h b/thirdparty/mbedtls/include/mbedtls/config.h
index 70820be56f..51d66291a5 100644
--- a/thirdparty/mbedtls/include/mbedtls/config.h
+++ b/thirdparty/mbedtls/include/mbedtls/config.h
@@ -137,12 +137,21 @@
/**
* \def MBEDTLS_HAVE_TIME_DATE
*
- * System has time.h and time(), gmtime() and the clock is correct.
+ * System has time.h, time(), and an implementation for
+ * mbedtls_platform_gmtime_r() (see below).
* The time needs to be correct (not necesarily very accurate, but at least
* the date should be correct). This is used to verify the validity period of
* X.509 certificates.
*
* Comment if your system does not have a correct clock.
+ *
+ * \note mbedtls_platform_gmtime_r() is an abstraction in platform_util.h that
+ * behaves similarly to the gmtime_r() function from the C standard. Refer to
+ * the documentation for mbedtls_platform_gmtime_r() for more information.
+ *
+ * \note It is possible to configure an implementation for
+ * mbedtls_platform_gmtime_r() at compile-time by using the macro
+ * MBEDTLS_PLATFORM_GMTIME_R_ALT.
*/
#define MBEDTLS_HAVE_TIME_DATE
@@ -247,6 +256,48 @@
*/
//#define MBEDTLS_DEPRECATED_REMOVED
+/**
+ * \def MBEDTLS_CHECK_PARAMS
+ *
+ * This configuration option controls whether the library validates more of
+ * the parameters passed to it.
+ *
+ * When this flag is not defined, the library only attempts to validate an
+ * input parameter if: (1) they may come from the outside world (such as the
+ * network, the filesystem, etc.) or (2) not validating them could result in
+ * internal memory errors such as overflowing a buffer controlled by the
+ * library. On the other hand, it doesn't attempt to validate parameters whose
+ * values are fully controlled by the application (such as pointers).
+ *
+ * When this flag is defined, the library additionally attempts to validate
+ * parameters that are fully controlled by the application, and should always
+ * be valid if the application code is fully correct and trusted.
+ *
+ * For example, when a function accepts as input a pointer to a buffer that may
+ * contain untrusted data, and its documentation mentions that this pointer
+ * must not be NULL:
+ * - the pointer is checked to be non-NULL only if this option is enabled
+ * - the content of the buffer is always validated
+ *
+ * When this flag is defined, if a library function receives a parameter that
+ * is invalid, it will:
+ * - invoke the macro MBEDTLS_PARAM_FAILED() which by default expands to a
+ * call to the function mbedtls_param_failed()
+ * - immediately return (with a specific error code unless the function
+ * returns void and can't communicate an error).
+ *
+ * When defining this flag, you also need to:
+ * - either provide a definition of the function mbedtls_param_failed() in
+ * your application (see platform_util.h for its prototype) as the library
+ * calls that function, but does not provide a default definition for it,
+ * - or provide a different definition of the macro MBEDTLS_PARAM_FAILED()
+ * below if the above mechanism is not flexible enough to suit your needs.
+ * See the documentation of this macro later in this file.
+ *
+ * Uncomment to enable validation of application-controlled parameters.
+ */
+//#define MBEDTLS_CHECK_PARAMS
+
/* \} name SECTION: System support */
/**
@@ -405,11 +456,11 @@
* unsigned char mbedtls_internal_ecp_grp_capable(
* const mbedtls_ecp_group *grp )
* int mbedtls_internal_ecp_init( const mbedtls_ecp_group *grp )
- * void mbedtls_internal_ecp_deinit( const mbedtls_ecp_group *grp )
+ * void mbedtls_internal_ecp_free( const mbedtls_ecp_group *grp )
* The mbedtls_internal_ecp_grp_capable function should return 1 if the
* replacement functions implement arithmetic for the given group and 0
* otherwise.
- * The functions mbedtls_internal_ecp_init and mbedtls_internal_ecp_deinit are
+ * The functions mbedtls_internal_ecp_init and mbedtls_internal_ecp_free are
* called before and after each point operation and provide an opportunity to
* implement optimized set up and tear down instructions.
*
@@ -669,6 +720,30 @@
#define MBEDTLS_ECP_NIST_OPTIM
/**
+ * \def MBEDTLS_ECP_RESTARTABLE
+ *
+ * Enable "non-blocking" ECC operations that can return early and be resumed.
+ *
+ * This allows various functions to pause by returning
+ * #MBEDTLS_ERR_ECP_IN_PROGRESS (or, for functions in the SSL module,
+ * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) and then be called later again in
+ * order to further progress and eventually complete their operation. This is
+ * controlled through mbedtls_ecp_set_max_ops() which limits the maximum
+ * number of ECC operations a function may perform before pausing; see
+ * mbedtls_ecp_set_max_ops() for more information.
+ *
+ * This is useful in non-threaded environments if you want to avoid blocking
+ * for too long on ECC (and, hence, X.509 or SSL/TLS) operations.
+ *
+ * Uncomment this macro to enable restartable ECC computations.
+ *
+ * \note This option only works with the default software implementation of
+ * elliptic curve functionality. It is incompatible with
+ * MBEDTLS_ECP_ALT, MBEDTLS_ECDH_XXX_ALT and MBEDTLS_ECDSA_XXX_ALT.
+ */
+//#define MBEDTLS_ECP_RESTARTABLE
+
+/**
* \def MBEDTLS_ECDSA_DETERMINISTIC
*
* Enable deterministic ECDSA (RFC 6979).
@@ -1279,7 +1354,7 @@
/**
* \def MBEDTLS_SSL_RENEGOTIATION
*
- * Disable support for TLS renegotiation.
+ * Enable support for TLS renegotiation.
*
* The two main uses of renegotiation are (1) refresh keys on long-lived
* connections and (2) client authentication after the initial handshake.
@@ -2018,14 +2093,16 @@
/**
* \def MBEDTLS_CTR_DRBG_C
*
- * Enable the CTR_DRBG AES-256-based random generator.
+ * Enable the CTR_DRBG AES-based random generator.
+ * The CTR_DRBG generator uses AES-256 by default.
+ * To use AES-128 instead, enable MBEDTLS_CTR_DRBG_USE_128_BIT_KEY below.
*
* Module: library/ctr_drbg.c
* Caller:
*
* Requires: MBEDTLS_AES_C
*
- * This module provides the CTR_DRBG AES-256 random number generator.
+ * This module provides the CTR_DRBG AES random number generator.
*/
#define MBEDTLS_CTR_DRBG_C
@@ -2400,7 +2477,9 @@
*
* This modules adds support for the VIA PadLock on x86.
*/
-#define MBEDTLS_PADLOCK_C
+// -- GODOT start --
+// #define MBEDTLS_PADLOCK_C
+// -- GODOT end --
/**
* \def MBEDTLS_PEM_PARSE_C
@@ -2910,6 +2989,7 @@
//#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */
//#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */
//#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */
+//#define MBEDTLS_CTR_DRBG_USE_128_BIT_KEY /**< Use 128-bit key for CTR_DRBG - may reduce security (see ctr_drbg.h) */
/* HMAC_DRBG options */
//#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */
@@ -2960,6 +3040,36 @@
//#define MBEDTLS_PLATFORM_NV_SEED_READ_MACRO mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */
//#define MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */
+/**
+ * \brief This macro is invoked by the library when an invalid parameter
+ * is detected that is only checked with MBEDTLS_CHECK_PARAMS
+ * (see the documentation of that option for context).
+ *
+ * When you leave this undefined here, a default definition is
+ * provided that invokes the function mbedtls_param_failed(),
+ * which is declared in platform_util.h for the benefit of the
+ * library, but that you need to define in your application.
+ *
+ * When you define this here, this replaces the default
+ * definition in platform_util.h (which no longer declares the
+ * function mbedtls_param_failed()) and it is your responsibility
+ * to make sure this macro expands to something suitable (in
+ * particular, that all the necessary declarations are visible
+ * from within the library - you can ensure that by providing
+ * them in this file next to the macro definition).
+ *
+ * Note that you may define this macro to expand to nothing, in
+ * which case you don't have to worry about declarations or
+ * definitions. However, you will then be notified about invalid
+ * parameters only in non-void functions, and void function will
+ * just silently return early on invalid parameters, which
+ * partially negates the benefits of enabling
+ * #MBEDTLS_CHECK_PARAMS in the first place, so is discouraged.
+ *
+ * \param cond The expression that should evaluate to true, but doesn't.
+ */
+//#define MBEDTLS_PARAM_FAILED( cond ) assert( cond )
+
/* SSL Cache options */
//#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT 86400 /**< 1 day */
//#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */
@@ -2968,31 +3078,65 @@
/** \def MBEDTLS_SSL_MAX_CONTENT_LEN
*
- * Maximum fragment length in bytes.
+ * Maximum length (in bytes) of incoming and outgoing plaintext fragments.
+ *
+ * This determines the size of both the incoming and outgoing TLS I/O buffers
+ * in such a way that both are capable of holding the specified amount of
+ * plaintext data, regardless of the protection mechanism used.
*
- * Determines the size of both the incoming and outgoing TLS I/O buffers.
+ * To configure incoming and outgoing I/O buffers separately, use
+ * #MBEDTLS_SSL_IN_CONTENT_LEN and #MBEDTLS_SSL_OUT_CONTENT_LEN,
+ * which overwrite the value set by this option.
*
- * Uncommenting MBEDTLS_SSL_IN_CONTENT_LEN and/or MBEDTLS_SSL_OUT_CONTENT_LEN
- * will override this length by setting maximum incoming and/or outgoing
- * fragment length, respectively.
+ * \note When using a value less than the default of 16KB on the client, it is
+ * recommended to use the Maximum Fragment Length (MFL) extension to
+ * inform the server about this limitation. On the server, there
+ * is no supported, standardized way of informing the client about
+ * restriction on the maximum size of incoming messages, and unless
+ * the limitation has been communicated by other means, it is recommended
+ * to only change the outgoing buffer size #MBEDTLS_SSL_OUT_CONTENT_LEN
+ * while keeping the default value of 16KB for the incoming buffer.
+ *
+ * Uncomment to set the maximum plaintext size of both
+ * incoming and outgoing I/O buffers.
*/
//#define MBEDTLS_SSL_MAX_CONTENT_LEN 16384
/** \def MBEDTLS_SSL_IN_CONTENT_LEN
*
- * Maximum incoming fragment length in bytes.
+ * Maximum length (in bytes) of incoming plaintext fragments.
+ *
+ * This determines the size of the incoming TLS I/O buffer in such a way
+ * that it is capable of holding the specified amount of plaintext data,
+ * regardless of the protection mechanism used.
+ *
+ * If this option is undefined, it inherits its value from
+ * #MBEDTLS_SSL_MAX_CONTENT_LEN.
*
- * Uncomment to set the size of the inward TLS buffer independently of the
- * outward buffer.
+ * \note When using a value less than the default of 16KB on the client, it is
+ * recommended to use the Maximum Fragment Length (MFL) extension to
+ * inform the server about this limitation. On the server, there
+ * is no supported, standardized way of informing the client about
+ * restriction on the maximum size of incoming messages, and unless
+ * the limitation has been communicated by other means, it is recommended
+ * to only change the outgoing buffer size #MBEDTLS_SSL_OUT_CONTENT_LEN
+ * while keeping the default value of 16KB for the incoming buffer.
+ *
+ * Uncomment to set the maximum plaintext size of the incoming I/O buffer
+ * independently of the outgoing I/O buffer.
*/
//#define MBEDTLS_SSL_IN_CONTENT_LEN 16384
/** \def MBEDTLS_SSL_OUT_CONTENT_LEN
*
- * Maximum outgoing fragment length in bytes.
+ * Maximum length (in bytes) of outgoing plaintext fragments.
+ *
+ * This determines the size of the outgoing TLS I/O buffer in such a way
+ * that it is capable of holding the specified amount of plaintext data,
+ * regardless of the protection mechanism used.
*
- * Uncomment to set the size of the outward TLS buffer independently of the
- * inward buffer.
+ * If this option undefined, it inherits its value from
+ * #MBEDTLS_SSL_MAX_CONTENT_LEN.
*
* It is possible to save RAM by setting a smaller outward buffer, while keeping
* the default inward 16384 byte buffer to conform to the TLS specification.
@@ -3002,14 +3146,28 @@
* The specific size requirement depends on the configured ciphers and any
* certificate data which is sent during the handshake.
*
- * For absolute minimum RAM usage, it's best to enable
- * MBEDTLS_SSL_MAX_FRAGMENT_LENGTH and reduce MBEDTLS_SSL_MAX_CONTENT_LEN. This
- * reduces both incoming and outgoing buffer sizes. However this is only
- * guaranteed if the other end of the connection also supports the TLS
- * max_fragment_len extension. Otherwise the connection may fail.
+ * Uncomment to set the maximum plaintext size of the outgoing I/O buffer
+ * independently of the incoming I/O buffer.
*/
//#define MBEDTLS_SSL_OUT_CONTENT_LEN 16384
+/** \def MBEDTLS_SSL_DTLS_MAX_BUFFERING
+ *
+ * Maximum number of heap-allocated bytes for the purpose of
+ * DTLS handshake message reassembly and future message buffering.
+ *
+ * This should be at least 9/8 * MBEDTLSSL_IN_CONTENT_LEN
+ * to account for a reassembled handshake message of maximum size,
+ * together with its reassembly bitmap.
+ *
+ * A value of 2 * MBEDTLS_SSL_IN_CONTENT_LEN (32768 by default)
+ * should be sufficient for all practical situations as it allows
+ * to reassembly a large handshake message (such as a certificate)
+ * while buffering multiple smaller handshake messages.
+ *
+ */
+//#define MBEDTLS_SSL_DTLS_MAX_BUFFERING 32768
+
//#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */
//#define MBEDTLS_PSK_MAX_LEN 32 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */
//#define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */
@@ -3083,25 +3241,33 @@
*/
//#define MBEDTLS_PLATFORM_ZEROIZE_ALT
-/* \} name SECTION: Customisation configuration options */
-
-/* Target and application specific configurations */
-//#define YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE "target_config.h"
+/**
+ * Uncomment the macro to let Mbed TLS use your alternate implementation of
+ * mbedtls_platform_gmtime_r(). This replaces the default implementation in
+ * platform_util.c.
+ *
+ * gmtime() is not a thread-safe function as defined in the C standard. The
+ * library will try to use safer implementations of this function, such as
+ * gmtime_r() when available. However, if Mbed TLS cannot identify the target
+ * system, the implementation of mbedtls_platform_gmtime_r() will default to
+ * using the standard gmtime(). In this case, calls from the library to
+ * gmtime() will be guarded by the global mutex mbedtls_threading_gmtime_mutex
+ * if MBEDTLS_THREADING_C is enabled. We recommend that calls from outside the
+ * library are also guarded with this mutex to avoid race conditions. However,
+ * if the macro MBEDTLS_PLATFORM_GMTIME_R_ALT is defined, Mbed TLS will
+ * unconditionally use the implementation for mbedtls_platform_gmtime_r()
+ * supplied at compile time.
+ */
+//#define MBEDTLS_PLATFORM_GMTIME_R_ALT
-#if defined(TARGET_LIKE_MBED) && defined(YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE)
-#include YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE
-#endif
+/* \} name SECTION: Customisation configuration options */
-/*
+/* Target and application specific configurations
+ *
* Allow user to override any previous default.
*
- * Use two macro names for that, as:
- * - with yotta the prefix YOTTA_CFG_ is forced
- * - without yotta is looks weird to have a YOTTA prefix.
*/
-#if defined(YOTTA_CFG_MBEDTLS_USER_CONFIG_FILE)
-#include YOTTA_CFG_MBEDTLS_USER_CONFIG_FILE
-#elif defined(MBEDTLS_USER_CONFIG_FILE)
+#if defined(MBEDTLS_USER_CONFIG_FILE)
#include MBEDTLS_USER_CONFIG_FILE
#endif
diff --git a/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h b/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h
index 3835d7299b..10f9389d9f 100644
--- a/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h
+++ b/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h
@@ -8,8 +8,11 @@
* Recommendation for Random Number Generation Using Deterministic Random
* Bit Generators</em>.
*
- * The Mbed TLS implementation of CTR_DRBG uses AES-256 as the underlying
- * block cipher.
+ * The Mbed TLS implementation of CTR_DRBG uses AES-256 (default) or AES-128
+ * as the underlying block cipher.
+ *
+ * \warning Using 128-bit keys for CTR_DRBG limits the security of generated
+ * keys and operations that use random values generated to 128-bit security.
*/
/*
* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved
@@ -45,7 +48,13 @@
#define MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR -0x003A /**< Read or write error in file. */
#define MBEDTLS_CTR_DRBG_BLOCKSIZE 16 /**< The block size used by the cipher. */
-#define MBEDTLS_CTR_DRBG_KEYSIZE 32 /**< The key size used by the cipher. */
+
+#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
+#define MBEDTLS_CTR_DRBG_KEYSIZE 16 /**< The key size used by the cipher (compile-time choice: 128 bits). */
+#else
+#define MBEDTLS_CTR_DRBG_KEYSIZE 32 /**< The key size used by the cipher (compile-time choice: 256 bits). */
+#endif
+
#define MBEDTLS_CTR_DRBG_KEYBITS ( MBEDTLS_CTR_DRBG_KEYSIZE * 8 ) /**< The key size for the DRBG operation, in bits. */
#define MBEDTLS_CTR_DRBG_SEEDLEN ( MBEDTLS_CTR_DRBG_KEYSIZE + MBEDTLS_CTR_DRBG_BLOCKSIZE ) /**< The seed length, calculated as (counter + AES key). */
@@ -108,7 +117,7 @@ extern "C" {
/**
* \brief The CTR_DRBG context structure.
*/
-typedef struct
+typedef struct mbedtls_ctr_drbg_context
{
unsigned char counter[16]; /*!< The counter (V). */
int reseed_counter; /*!< The reseed counter. */
@@ -230,18 +239,20 @@ int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
/**
* \brief This function updates the state of the CTR_DRBG context.
*
- * \note If \p add_len is greater than
- * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT, only the first
- * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT Bytes are used.
- * The remaining Bytes are silently discarded.
- *
* \param ctx The CTR_DRBG context.
* \param additional The data to update the state with.
- * \param add_len Length of \p additional data.
- *
+ * \param add_len Length of \p additional in bytes. This must be at
+ * most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if
+ * \p add_len is more than
+ * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT.
+ * \return An error from the underlying AES cipher on failure.
*/
-void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
- const unsigned char *additional, size_t add_len );
+int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
+ const unsigned char *additional,
+ size_t add_len );
/**
* \brief This function updates a CTR_DRBG instance with additional
@@ -281,6 +292,35 @@ int mbedtls_ctr_drbg_random_with_add( void *p_rng,
int mbedtls_ctr_drbg_random( void *p_rng,
unsigned char *output, size_t output_len );
+
+#if ! defined(MBEDTLS_DEPRECATED_REMOVED)
+#if defined(MBEDTLS_DEPRECATED_WARNING)
+#define MBEDTLS_DEPRECATED __attribute__((deprecated))
+#else
+#define MBEDTLS_DEPRECATED
+#endif
+/**
+ * \brief This function updates the state of the CTR_DRBG context.
+ *
+ * \deprecated Superseded by mbedtls_ctr_drbg_update_ret()
+ * in 2.16.0.
+ *
+ * \note If \p add_len is greater than
+ * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT, only the first
+ * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT Bytes are used.
+ * The remaining Bytes are silently discarded.
+ *
+ * \param ctx The CTR_DRBG context.
+ * \param additional The data to update the state with.
+ * \param add_len Length of \p additional data.
+ */
+MBEDTLS_DEPRECATED void mbedtls_ctr_drbg_update(
+ mbedtls_ctr_drbg_context *ctx,
+ const unsigned char *additional,
+ size_t add_len );
+#undef MBEDTLS_DEPRECATED
+#endif /* !MBEDTLS_DEPRECATED_REMOVED */
+
#if defined(MBEDTLS_FS_IO)
/**
* \brief This function writes a seed file.
diff --git a/thirdparty/mbedtls/include/mbedtls/debug.h b/thirdparty/mbedtls/include/mbedtls/debug.h
index ef8db67ff1..736444bb76 100644
--- a/thirdparty/mbedtls/include/mbedtls/debug.h
+++ b/thirdparty/mbedtls/include/mbedtls/debug.h
@@ -65,6 +65,11 @@
mbedtls_debug_print_crt( ssl, level, __FILE__, __LINE__, text, crt )
#endif
+#if defined(MBEDTLS_ECDH_C)
+#define MBEDTLS_SSL_DEBUG_ECDH( level, ecdh, attr ) \
+ mbedtls_debug_printf_ecdh( ssl, level, __FILE__, __LINE__, ecdh, attr )
+#endif
+
#else /* MBEDTLS_DEBUG_C */
#define MBEDTLS_SSL_DEBUG_MSG( level, args ) do { } while( 0 )
@@ -73,6 +78,7 @@
#define MBEDTLS_SSL_DEBUG_MPI( level, text, X ) do { } while( 0 )
#define MBEDTLS_SSL_DEBUG_ECP( level, text, X ) do { } while( 0 )
#define MBEDTLS_SSL_DEBUG_CRT( level, text, crt ) do { } while( 0 )
+#define MBEDTLS_SSL_DEBUG_ECDH( level, ecdh, attr ) do { } while( 0 )
#endif /* MBEDTLS_DEBUG_C */
@@ -221,6 +227,36 @@ void mbedtls_debug_print_crt( const mbedtls_ssl_context *ssl, int level,
const char *text, const mbedtls_x509_crt *crt );
#endif
+#if defined(MBEDTLS_ECDH_C)
+typedef enum
+{
+ MBEDTLS_DEBUG_ECDH_Q,
+ MBEDTLS_DEBUG_ECDH_QP,
+ MBEDTLS_DEBUG_ECDH_Z,
+} mbedtls_debug_ecdh_attr;
+
+/**
+ * \brief Print a field of the ECDH structure in the SSL context to the debug
+ * output. This function is always used through the
+ * MBEDTLS_SSL_DEBUG_ECDH() macro, which supplies the ssl context, file
+ * and line number parameters.
+ *
+ * \param ssl SSL context
+ * \param level error level of the debug message
+ * \param file file the error has occurred in
+ * \param line line number the error has occurred in
+ * \param ecdh the ECDH context
+ * \param attr the identifier of the attribute being output
+ *
+ * \attention This function is intended for INTERNAL usage within the
+ * library only.
+ */
+void mbedtls_debug_printf_ecdh( const mbedtls_ssl_context *ssl, int level,
+ const char *file, int line,
+ const mbedtls_ecdh_context *ecdh,
+ mbedtls_debug_ecdh_attr attr );
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/thirdparty/mbedtls/include/mbedtls/des.h b/thirdparty/mbedtls/include/mbedtls/des.h
index 6eb7d03bae..d62042d14e 100644
--- a/thirdparty/mbedtls/include/mbedtls/des.h
+++ b/thirdparty/mbedtls/include/mbedtls/des.h
@@ -42,6 +42,8 @@
#define MBEDTLS_DES_DECRYPT 0
#define MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH -0x0032 /**< The data input has an invalid length. */
+
+/* MBEDTLS_ERR_DES_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_DES_HW_ACCEL_FAILED -0x0033 /**< DES hardware accelerator failed. */
#define MBEDTLS_DES_KEY_SIZE 8
@@ -61,7 +63,7 @@ extern "C" {
* security risk. We recommend considering stronger ciphers
* instead.
*/
-typedef struct
+typedef struct mbedtls_des_context
{
uint32_t sk[32]; /*!< DES subkeys */
}
@@ -70,7 +72,7 @@ mbedtls_des_context;
/**
* \brief Triple-DES context structure
*/
-typedef struct
+typedef struct mbedtls_des3_context
{
uint32_t sk[96]; /*!< 3DES subkeys */
}
diff --git a/thirdparty/mbedtls/include/mbedtls/dhm.h b/thirdparty/mbedtls/include/mbedtls/dhm.h
index 75317a8e6d..a5452c199a 100644
--- a/thirdparty/mbedtls/include/mbedtls/dhm.h
+++ b/thirdparty/mbedtls/include/mbedtls/dhm.h
@@ -84,7 +84,10 @@
#define MBEDTLS_ERR_DHM_INVALID_FORMAT -0x3380 /**< The ASN.1 data is not formatted correctly. */
#define MBEDTLS_ERR_DHM_ALLOC_FAILED -0x3400 /**< Allocation of memory failed. */
#define MBEDTLS_ERR_DHM_FILE_IO_ERROR -0x3480 /**< Read or write of file failed. */
+
+/* MBEDTLS_ERR_DHM_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_DHM_HW_ACCEL_FAILED -0x3500 /**< DHM hardware accelerator failed. */
+
#define MBEDTLS_ERR_DHM_SET_GROUP_FAILED -0x3580 /**< Setting the modulus and generator failed. */
#ifdef __cplusplus
@@ -96,7 +99,7 @@ extern "C" {
/**
* \brief The DHM context structure.
*/
-typedef struct
+typedef struct mbedtls_dhm_context
{
size_t len; /*!< The size of \p P in Bytes. */
mbedtls_mpi P; /*!< The prime modulus. */
@@ -124,9 +127,15 @@ mbedtls_dhm_context;
void mbedtls_dhm_init( mbedtls_dhm_context *ctx );
/**
- * \brief This function parses the ServerKeyExchange parameters.
+ * \brief This function parses the DHM parameters in a
+ * TLS ServerKeyExchange handshake message
+ * (DHM modulus, generator, and public key).
*
- * \param ctx The DHM context.
+ * \note In a TLS handshake, this is the how the client
+ * sets up its DHM context from the server's public
+ * DHM key material.
+ *
+ * \param ctx The DHM context to use. This must be initialized.
* \param p On input, *p must be the start of the input buffer.
* On output, *p is updated to point to the end of the data
* that has been read. On success, this is the first byte
@@ -140,31 +149,37 @@ void mbedtls_dhm_init( mbedtls_dhm_context *ctx );
* \return An \c MBEDTLS_ERR_DHM_XXX error code on failure.
*/
int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx,
- unsigned char **p,
- const unsigned char *end );
+ unsigned char **p,
+ const unsigned char *end );
/**
- * \brief This function sets up and writes the ServerKeyExchange
- * parameters.
- *
- * \note The destination buffer must be large enough to hold
- * the reduced binary presentation of the modulus, the generator
- * and the public key, each wrapped with a 2-byte length field.
- * It is the responsibility of the caller to ensure that enough
- * space is available. Refer to \c mbedtls_mpi_size to computing
- * the byte-size of an MPI.
+ * \brief This function generates a DHM key pair and exports its
+ * public part together with the DHM parameters in the format
+ * used in a TLS ServerKeyExchange handshake message.
*
- * \note This function assumes that \c ctx->P and \c ctx->G
- * have already been properly set. For that, use
+ * \note This function assumes that the DHM parameters \c ctx->P
+ * and \c ctx->G have already been properly set. For that, use
* mbedtls_dhm_set_group() below in conjunction with
* mbedtls_mpi_read_binary() and mbedtls_mpi_read_string().
*
- * \param ctx The DHM context.
+ * \note In a TLS handshake, this is the how the server generates
+ * and exports its DHM key material.
+ *
+ * \param ctx The DHM context to use. This must be initialized
+ * and have the DHM parameters set. It may or may not
+ * already have imported the peer's public key.
* \param x_size The private key size in Bytes.
- * \param olen The number of characters written.
- * \param output The destination buffer.
- * \param f_rng The RNG function.
- * \param p_rng The RNG context.
+ * \param olen The address at which to store the number of Bytes
+ * written on success. This must not be \c NULL.
+ * \param output The destination buffer. This must be a writable buffer of
+ * sufficient size to hold the reduced binary presentation of
+ * the modulus, the generator and the public key, each wrapped
+ * with a 2-byte length field. It is the responsibility of the
+ * caller to ensure that enough space is available. Refer to
+ * mbedtls_mpi_size() to computing the byte-size of an MPI.
+ * \param f_rng The RNG function. Must not be \c NULL.
+ * \param p_rng The RNG context to be passed to \p f_rng. This may be
+ * \c NULL if \p f_rng doesn't need a context parameter.
*
* \return \c 0 on success.
* \return An \c MBEDTLS_ERR_DHM_XXX error code on failure.
@@ -177,12 +192,14 @@ int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size,
/**
* \brief This function sets the prime modulus and generator.
*
- * \note This function can be used to set \p P, \p G
+ * \note This function can be used to set \c ctx->P, \c ctx->G
* in preparation for mbedtls_dhm_make_params().
*
- * \param ctx The DHM context.
- * \param P The MPI holding the DHM prime modulus.
- * \param G The MPI holding the DHM generator.
+ * \param ctx The DHM context to configure. This must be initialized.
+ * \param P The MPI holding the DHM prime modulus. This must be
+ * an initialized MPI.
+ * \param G The MPI holding the DHM generator. This must be an
+ * initialized MPI.
*
* \return \c 0 if successful.
* \return An \c MBEDTLS_ERR_DHM_XXX error code on failure.
@@ -192,11 +209,17 @@ int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx,
const mbedtls_mpi *G );
/**
- * \brief This function imports the public value of the peer, G^Y.
+ * \brief This function imports the raw public value of the peer.
+ *
+ * \note In a TLS handshake, this is the how the server imports
+ * the Client's public DHM key.
*
- * \param ctx The DHM context.
- * \param input The input buffer containing the G^Y value of the peer.
- * \param ilen The size of the input buffer.
+ * \param ctx The DHM context to use. This must be initialized and have
+ * its DHM parameters set, e.g. via mbedtls_dhm_set_group().
+ * It may or may not already have generated its own private key.
+ * \param input The input buffer containing the \c G^Y value of the peer.
+ * This must be a readable buffer of size \p ilen Bytes.
+ * \param ilen The size of the input buffer \p input in Bytes.
*
* \return \c 0 on success.
* \return An \c MBEDTLS_ERR_DHM_XXX error code on failure.
@@ -205,21 +228,25 @@ int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx,
const unsigned char *input, size_t ilen );
/**
- * \brief This function creates its own private key, \c X, and
- * exports \c G^X.
+ * \brief This function creates a DHM key pair and exports
+ * the raw public key in big-endian format.
*
* \note The destination buffer is always fully written
* so as to contain a big-endian representation of G^X mod P.
- * If it is larger than ctx->len, it is padded accordingly
+ * If it is larger than \c ctx->len, it is padded accordingly
* with zero-bytes at the beginning.
*
- * \param ctx The DHM context.
+ * \param ctx The DHM context to use. This must be initialized and
+ * have the DHM parameters set. It may or may not already
+ * have imported the peer's public key.
* \param x_size The private key size in Bytes.
- * \param output The destination buffer.
- * \param olen The length of the destination buffer. Must be at least
- * equal to ctx->len (the size of \c P).
- * \param f_rng The RNG function.
- * \param p_rng The RNG context.
+ * \param output The destination buffer. This must be a writable buffer of
+ * size \p olen Bytes.
+ * \param olen The length of the destination buffer. This must be at least
+ * equal to `ctx->len` (the size of \c P).
+ * \param f_rng The RNG function. This must not be \c NULL.
+ * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL
+ * if \p f_rng doesn't need a context argument.
*
* \return \c 0 on success.
* \return An \c MBEDTLS_ERR_DHM_XXX error code on failure.
@@ -230,22 +257,27 @@ int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size,
void *p_rng );
/**
- * \brief This function derives and exports the shared secret
- * \c (G^Y)^X mod \c P.
+ * \brief This function derives and exports the shared secret
+ * \c (G^Y)^X mod \c P.
*
- * \note If \p f_rng is not NULL, it is used to blind the input as
- * a countermeasure against timing attacks. Blinding is used
- * only if our private key \c X is re-used, and not used
- * otherwise. We recommend always passing a non-NULL
- * \p f_rng argument.
+ * \note If \p f_rng is not \c NULL, it is used to blind the input as
+ * a countermeasure against timing attacks. Blinding is used
+ * only if our private key \c X is re-used, and not used
+ * otherwise. We recommend always passing a non-NULL
+ * \p f_rng argument.
*
- * \param ctx The DHM context.
- * \param output The destination buffer.
- * \param output_size The size of the destination buffer. Must be at least
- * the size of ctx->len (the size of \c P).
+ * \param ctx The DHM context to use. This must be initialized
+ * and have its own private key generated and the peer's
+ * public key imported.
+ * \param output The buffer to write the generated shared key to. This
+ * must be a writable buffer of size \p output_size Bytes.
+ * \param output_size The size of the destination buffer. This must be at
+ * least the size of \c ctx->len (the size of \c P).
* \param olen On exit, holds the actual number of Bytes written.
- * \param f_rng The RNG function, for blinding purposes.
- * \param p_rng The RNG context.
+ * \param f_rng The RNG function, for blinding purposes. This may
+ * b \c NULL if blinding isn't needed.
+ * \param p_rng The RNG context. This may be \c NULL if \p f_rng
+ * doesn't need a context argument.
*
* \return \c 0 on success.
* \return An \c MBEDTLS_ERR_DHM_XXX error code on failure.
@@ -256,9 +288,12 @@ int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx,
void *p_rng );
/**
- * \brief This function frees and clears the components of a DHM context.
+ * \brief This function frees and clears the components
+ * of a DHM context.
*
- * \param ctx The DHM context to free and clear.
+ * \param ctx The DHM context to free and clear. This may be \c NULL,
+ * in which case this function is a no-op. If it is not \c NULL,
+ * it must point to an initialized DHM context.
*/
void mbedtls_dhm_free( mbedtls_dhm_context *ctx );
@@ -267,17 +302,19 @@ void mbedtls_dhm_free( mbedtls_dhm_context *ctx );
/**
* \brief This function parses DHM parameters in PEM or DER format.
*
- * \param dhm The DHM context to initialize.
- * \param dhmin The input buffer.
- * \param dhminlen The size of the buffer, including the terminating null
- * Byte for PEM data.
+ * \param dhm The DHM context to import the DHM parameters into.
+ * This must be initialized.
+ * \param dhmin The input buffer. This must be a readable buffer of
+ * length \p dhminlen Bytes.
+ * \param dhminlen The size of the input buffer \p dhmin, including the
+ * terminating \c NULL Byte for PEM data.
*
* \return \c 0 on success.
- * \return An \c MBEDTLS_ERR_DHM_XXX or \c MBEDTLS_ERR_PEM_XXX error code
- * error code on failure.
+ * \return An \c MBEDTLS_ERR_DHM_XXX or \c MBEDTLS_ERR_PEM_XXX error
+ * code on failure.
*/
int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin,
- size_t dhminlen );
+ size_t dhminlen );
#if defined(MBEDTLS_FS_IO)
/** \ingroup x509_module */
@@ -285,11 +322,13 @@ int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin,
* \brief This function loads and parses DHM parameters from a file.
*
* \param dhm The DHM context to load the parameters to.
+ * This must be initialized.
* \param path The filename to read the DHM parameters from.
+ * This must not be \c NULL.
*
* \return \c 0 on success.
- * \return An \c MBEDTLS_ERR_DHM_XXX or \c MBEDTLS_ERR_PEM_XXX error code
- * error code on failure.
+ * \return An \c MBEDTLS_ERR_DHM_XXX or \c MBEDTLS_ERR_PEM_XXX
+ * error code on failure.
*/
int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path );
#endif /* MBEDTLS_FS_IO */
@@ -350,15 +389,6 @@ int mbedtls_dhm_self_test( int verbose );
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-#if defined(MBEDTLS_DEPRECATED_WARNING)
-#define MBEDTLS_DEPRECATED __attribute__((deprecated))
-MBEDTLS_DEPRECATED typedef char const * mbedtls_deprecated_constant_t;
-#define MBEDTLS_DEPRECATED_STRING_CONSTANT( VAL ) \
- ( (mbedtls_deprecated_constant_t) ( VAL ) )
-#else
-#define MBEDTLS_DEPRECATED_STRING_CONSTANT( VAL ) VAL
-#endif /* ! MBEDTLS_DEPRECATED_WARNING */
-
/**
* \warning The origin of the primes in RFC 5114 is not documented and
* their use therefore constitutes a security risk!
diff --git a/thirdparty/mbedtls/include/mbedtls/ecdh.h b/thirdparty/mbedtls/include/mbedtls/ecdh.h
index 5fdf55a88a..05b2b03970 100644
--- a/thirdparty/mbedtls/include/mbedtls/ecdh.h
+++ b/thirdparty/mbedtls/include/mbedtls/ecdh.h
@@ -36,6 +36,18 @@
#include "ecp.h"
+/*
+ * Use a backward compatible ECDH context.
+ *
+ * This flag is always enabled for now and future versions might add a
+ * configuration option that conditionally undefines this flag.
+ * The configuration option in question may have a different name.
+ *
+ * Features undefining this flag, must have a warning in their description in
+ * config.h stating that the feature breaks backward compatibility.
+ */
+#define MBEDTLS_ECDH_LEGACY_CONTEXT
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -49,11 +61,49 @@ typedef enum
MBEDTLS_ECDH_THEIRS, /**< The key of the peer. */
} mbedtls_ecdh_side;
+#if !defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
+/**
+ * Defines the ECDH implementation used.
+ *
+ * Later versions of the library may add new variants, therefore users should
+ * not make any assumptions about them.
+ */
+typedef enum
+{
+ MBEDTLS_ECDH_VARIANT_NONE = 0, /*!< Implementation not defined. */
+ MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0,/*!< The default Mbed TLS implementation */
+} mbedtls_ecdh_variant;
+
+/**
+ * The context used by the default ECDH implementation.
+ *
+ * Later versions might change the structure of this context, therefore users
+ * should not make any assumptions about the structure of
+ * mbedtls_ecdh_context_mbed.
+ */
+typedef struct mbedtls_ecdh_context_mbed
+{
+ mbedtls_ecp_group grp; /*!< The elliptic curve used. */
+ mbedtls_mpi d; /*!< The private key. */
+ mbedtls_ecp_point Q; /*!< The public key. */
+ mbedtls_ecp_point Qp; /*!< The value of the public key of the peer. */
+ mbedtls_mpi z; /*!< The shared secret. */
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ mbedtls_ecp_restart_ctx rs; /*!< The restart context for EC computations. */
+#endif
+} mbedtls_ecdh_context_mbed;
+#endif
+
/**
+ *
+ * \warning Performing multiple operations concurrently on the same
+ * ECDSA context is not supported; objects of this type
+ * should not be shared between multiple threads.
* \brief The ECDH context structure.
*/
-typedef struct
+typedef struct mbedtls_ecdh_context
{
+#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
mbedtls_ecp_group grp; /*!< The elliptic curve used. */
mbedtls_mpi d; /*!< The private key. */
mbedtls_ecp_point Q; /*!< The public key. */
@@ -63,6 +113,29 @@ typedef struct
mbedtls_ecp_point Vi; /*!< The blinding value. */
mbedtls_ecp_point Vf; /*!< The unblinding value. */
mbedtls_mpi _d; /*!< The previous \p d. */
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ int restart_enabled; /*!< The flag for restartable mode. */
+ mbedtls_ecp_restart_ctx rs; /*!< The restart context for EC computations. */
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+#else
+ uint8_t point_format; /*!< The format of point export in TLS messages
+ as defined in RFC 4492. */
+ mbedtls_ecp_group_id grp_id;/*!< The elliptic curve used. */
+ mbedtls_ecdh_variant var; /*!< The ECDH implementation/structure used. */
+ union
+ {
+ mbedtls_ecdh_context_mbed mbed_ecdh;
+ } ctx; /*!< Implementation-specific context. The
+ context in use is specified by the \c var
+ field. */
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ uint8_t restart_enabled; /*!< The flag for restartable mode. Functions of
+ an alternative implementation not supporting
+ restartable mode must return
+ MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED error
+ if this flag is set. */
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+#endif /* MBEDTLS_ECDH_LEGACY_CONTEXT */
}
mbedtls_ecdh_context;
@@ -76,16 +149,20 @@ mbedtls_ecdh_context;
*
* \see ecp.h
*
- * \param grp The ECP group.
+ * \param grp The ECP group to use. This must be initialized and have
+ * domain parameters loaded, for example through
+ * mbedtls_ecp_load() or mbedtls_ecp_tls_read_group().
* \param d The destination MPI (private key).
+ * This must be initialized.
* \param Q The destination point (public key).
- * \param f_rng The RNG function.
- * \param p_rng The RNG context.
+ * This must be initialized.
+ * \param f_rng The RNG function to use. This must not be \c NULL.
+ * \param p_rng The RNG context to be passed to \p f_rng. This may be
+ * \c NULL in case \p f_rng doesn't need a context argument.
*
* \return \c 0 on success.
- * \return An \c MBEDTLS_ERR_ECP_XXX or
+ * \return Another \c MBEDTLS_ERR_ECP_XXX or
* \c MBEDTLS_MPI_XXX error code on failure.
- *
*/
int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q,
int (*f_rng)(void *, unsigned char *, size_t),
@@ -104,15 +181,25 @@ int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp
* countermeasures against side-channel attacks.
* For more information, see mbedtls_ecp_mul().
*
- * \param grp The ECP group.
+ * \param grp The ECP group to use. This must be initialized and have
+ * domain parameters loaded, for example through
+ * mbedtls_ecp_load() or mbedtls_ecp_tls_read_group().
* \param z The destination MPI (shared secret).
+ * This must be initialized.
* \param Q The public key from another party.
+ * This must be initialized.
* \param d Our secret exponent (private key).
- * \param f_rng The RNG function.
- * \param p_rng The RNG context.
+ * This must be initialized.
+ * \param f_rng The RNG function. This may be \c NULL if randomization
+ * of intermediate results during the ECP computations is
+ * not needed (discouraged). See the documentation of
+ * mbedtls_ecp_mul() for more.
+ * \param p_rng The RNG context to be passed to \p f_rng. This may be
+ * \c NULL if \p f_rng is \c NULL or doesn't need a
+ * context argument.
*
* \return \c 0 on success.
- * \return An \c MBEDTLS_ERR_ECP_XXX or
+ * \return Another \c MBEDTLS_ERR_ECP_XXX or
* \c MBEDTLS_MPI_XXX error code on failure.
*/
int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z,
@@ -123,39 +210,62 @@ int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z,
/**
* \brief This function initializes an ECDH context.
*
- * \param ctx The ECDH context to initialize.
+ * \param ctx The ECDH context to initialize. This must not be \c NULL.
*/
void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx );
/**
+ * \brief This function sets up the ECDH context with the information
+ * given.
+ *
+ * This function should be called after mbedtls_ecdh_init() but
+ * before mbedtls_ecdh_make_params(). There is no need to call
+ * this function before mbedtls_ecdh_read_params().
+ *
+ * This is the first function used by a TLS server for ECDHE
+ * ciphersuites.
+ *
+ * \param ctx The ECDH context to set up. This must be initialized.
+ * \param grp_id The group id of the group to set up the context for.
+ *
+ * \return \c 0 on success.
+ */
+int mbedtls_ecdh_setup( mbedtls_ecdh_context *ctx,
+ mbedtls_ecp_group_id grp_id );
+
+/**
* \brief This function frees a context.
*
- * \param ctx The context to free.
+ * \param ctx The context to free. This may be \c NULL, in which
+ * case this function does nothing. If it is not \c NULL,
+ * it must point to an initialized ECDH context.
*/
void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx );
/**
- * \brief This function generates a public key and a TLS
- * ServerKeyExchange payload.
- *
- * This is the first function used by a TLS server for ECDHE
- * ciphersuites.
+ * \brief This function generates an EC key pair and exports its
+ * in the format used in a TLS ServerKeyExchange handshake
+ * message.
*
- * \note This function assumes that the ECP group (grp) of the
- * \p ctx context has already been properly set,
- * for example, using mbedtls_ecp_group_load().
+ * This is the second function used by a TLS server for ECDHE
+ * ciphersuites. (It is called after mbedtls_ecdh_setup().)
*
* \see ecp.h
*
- * \param ctx The ECDH context.
- * \param olen The number of characters written.
- * \param buf The destination buffer.
- * \param blen The length of the destination buffer.
- * \param f_rng The RNG function.
- * \param p_rng The RNG context.
+ * \param ctx The ECDH context to use. This must be initialized
+ * and bound to a group, for example via mbedtls_ecdh_setup().
+ * \param olen The address at which to store the number of Bytes written.
+ * \param buf The destination buffer. This must be a writable buffer of
+ * length \p blen Bytes.
+ * \param blen The length of the destination buffer \p buf in Bytes.
+ * \param f_rng The RNG function to use. This must not be \c NULL.
+ * \param p_rng The RNG context to be passed to \p f_rng. This may be
+ * \c NULL in case \p f_rng doesn't need a context argument.
*
* \return \c 0 on success.
- * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure.
+ * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
+ * operations was reached: see \c mbedtls_ecp_set_max_ops().
+ * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure.
*/
int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen,
unsigned char *buf, size_t blen,
@@ -163,24 +273,32 @@ int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen,
void *p_rng );
/**
- * \brief This function parses and processes a TLS ServerKeyExhange
- * payload.
+ * \brief This function parses the ECDHE parameters in a
+ * TLS ServerKeyExchange handshake message.
*
- * This is the first function used by a TLS client for ECDHE
- * ciphersuites.
+ * \note In a TLS handshake, this is the how the client
+ * sets up its ECDHE context from the server's public
+ * ECDHE key material.
*
* \see ecp.h
*
- * \param ctx The ECDH context.
- * \param buf The pointer to the start of the input buffer.
- * \param end The address for one Byte past the end of the buffer.
+ * \param ctx The ECDHE context to use. This must be initialized.
+ * \param buf On input, \c *buf must be the start of the input buffer.
+ * On output, \c *buf is updated to point to the end of the
+ * data that has been read. On success, this is the first byte
+ * past the end of the ServerKeyExchange parameters.
+ * On error, this is the point at which an error has been
+ * detected, which is usually not useful except to debug
+ * failures.
+ * \param end The end of the input buffer.
*
* \return \c 0 on success.
* \return An \c MBEDTLS_ERR_ECP_XXX error code on failure.
*
*/
int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx,
- const unsigned char **buf, const unsigned char *end );
+ const unsigned char **buf,
+ const unsigned char *end );
/**
* \brief This function sets up an ECDH context from an EC key.
@@ -191,36 +309,45 @@ int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx,
*
* \see ecp.h
*
- * \param ctx The ECDH context to set up.
- * \param key The EC key to use.
- * \param side Defines the source of the key: 1: Our key, or
- * 0: The key of the peer.
+ * \param ctx The ECDH context to set up. This must be initialized.
+ * \param key The EC key to use. This must be initialized.
+ * \param side Defines the source of the key. Possible values are:
+ * - #MBEDTLS_ECDH_OURS: The key is ours.
+ * - #MBEDTLS_ECDH_THEIRS: The key is that of the peer.
*
* \return \c 0 on success.
- * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure.
+ * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure.
*
*/
-int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypair *key,
- mbedtls_ecdh_side side );
+int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx,
+ const mbedtls_ecp_keypair *key,
+ mbedtls_ecdh_side side );
/**
- * \brief This function generates a public key and a TLS
- * ClientKeyExchange payload.
+ * \brief This function generates a public key and exports it
+ * as a TLS ClientKeyExchange payload.
*
* This is the second function used by a TLS client for ECDH(E)
* ciphersuites.
*
* \see ecp.h
*
- * \param ctx The ECDH context.
- * \param olen The number of Bytes written.
- * \param buf The destination buffer.
- * \param blen The size of the destination buffer.
- * \param f_rng The RNG function.
- * \param p_rng The RNG context.
+ * \param ctx The ECDH context to use. This must be initialized
+ * and bound to a group, the latter usually by
+ * mbedtls_ecdh_read_params().
+ * \param olen The address at which to store the number of Bytes written.
+ * This must not be \c NULL.
+ * \param buf The destination buffer. This must be a writable buffer
+ * of length \p blen Bytes.
+ * \param blen The size of the destination buffer \p buf in Bytes.
+ * \param f_rng The RNG function to use. This must not be \c NULL.
+ * \param p_rng The RNG context to be passed to \p f_rng. This may be
+ * \c NULL in case \p f_rng doesn't need a context argument.
*
* \return \c 0 on success.
- * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure.
+ * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
+ * operations was reached: see \c mbedtls_ecp_set_max_ops().
+ * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure.
*/
int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen,
unsigned char *buf, size_t blen,
@@ -228,23 +355,26 @@ int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen,
void *p_rng );
/**
- * \brief This function parses and processes a TLS ClientKeyExchange
- * payload.
+ * \brief This function parses and processes the ECDHE payload of a
+ * TLS ClientKeyExchange message.
*
- * This is the second function used by a TLS server for ECDH(E)
- * ciphersuites.
+ * This is the third function used by a TLS server for ECDH(E)
+ * ciphersuites. (It is called after mbedtls_ecdh_setup() and
+ * mbedtls_ecdh_make_params().)
*
* \see ecp.h
*
- * \param ctx The ECDH context.
- * \param buf The start of the input buffer.
- * \param blen The length of the input buffer.
+ * \param ctx The ECDH context to use. This must be initialized
+ * and bound to a group, for example via mbedtls_ecdh_setup().
+ * \param buf The pointer to the ClientKeyExchange payload. This must
+ * be a readable buffer of length \p blen Bytes.
+ * \param blen The length of the input buffer \p buf in Bytes.
*
* \return \c 0 on success.
* \return An \c MBEDTLS_ERR_ECP_XXX error code on failure.
*/
int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx,
- const unsigned char *buf, size_t blen );
+ const unsigned char *buf, size_t blen );
/**
* \brief This function derives and exports the shared secret.
@@ -257,22 +387,46 @@ int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx,
* For more information, see mbedtls_ecp_mul().
*
* \see ecp.h
- *
- * \param ctx The ECDH context.
- * \param olen The number of Bytes written.
- * \param buf The destination buffer.
- * \param blen The length of the destination buffer.
- * \param f_rng The RNG function.
- * \param p_rng The RNG context.
+
+ * \param ctx The ECDH context to use. This must be initialized
+ * and have its own private key generated and the peer's
+ * public key imported.
+ * \param olen The address at which to store the total number of
+ * Bytes written on success. This must not be \c NULL.
+ * \param buf The buffer to write the generated shared key to. This
+ * must be a writable buffer of size \p blen Bytes.
+ * \param blen The length of the destination buffer \p buf in Bytes.
+ * \param f_rng The RNG function, for blinding purposes. This may
+ * b \c NULL if blinding isn't needed.
+ * \param p_rng The RNG context. This may be \c NULL if \p f_rng
+ * doesn't need a context argument.
*
* \return \c 0 on success.
- * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure.
+ * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
+ * operations was reached: see \c mbedtls_ecp_set_max_ops().
+ * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure.
*/
int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen,
unsigned char *buf, size_t blen,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+/**
+ * \brief This function enables restartable EC computations for this
+ * context. (Default: disabled.)
+ *
+ * \see \c mbedtls_ecp_set_max_ops()
+ *
+ * \note It is not possible to safely disable restartable
+ * computations once enabled, except by free-ing the context,
+ * which cancels possible in-progress operations.
+ *
+ * \param ctx The ECDH context to use. This must be initialized.
+ */
+void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx );
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
#ifdef __cplusplus
}
#endif
diff --git a/thirdparty/mbedtls/include/mbedtls/ecdsa.h b/thirdparty/mbedtls/include/mbedtls/ecdsa.h
index ce1a03d791..40fdab3729 100644
--- a/thirdparty/mbedtls/include/mbedtls/ecdsa.h
+++ b/thirdparty/mbedtls/include/mbedtls/ecdsa.h
@@ -55,20 +55,71 @@
/** The maximal size of an ECDSA signature in Bytes. */
#define MBEDTLS_ECDSA_MAX_LEN ( 3 + 2 * ( 3 + MBEDTLS_ECP_MAX_BYTES ) )
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/**
* \brief The ECDSA context structure.
+ *
+ * \warning Performing multiple operations concurrently on the same
+ * ECDSA context is not supported; objects of this type
+ * should not be shared between multiple threads.
*/
typedef mbedtls_ecp_keypair mbedtls_ecdsa_context;
-#ifdef __cplusplus
-extern "C" {
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+
+/**
+ * \brief Internal restart context for ecdsa_verify()
+ *
+ * \note Opaque struct, defined in ecdsa.c
+ */
+typedef struct mbedtls_ecdsa_restart_ver mbedtls_ecdsa_restart_ver_ctx;
+
+/**
+ * \brief Internal restart context for ecdsa_sign()
+ *
+ * \note Opaque struct, defined in ecdsa.c
+ */
+typedef struct mbedtls_ecdsa_restart_sig mbedtls_ecdsa_restart_sig_ctx;
+
+#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
+/**
+ * \brief Internal restart context for ecdsa_sign_det()
+ *
+ * \note Opaque struct, defined in ecdsa.c
+ */
+typedef struct mbedtls_ecdsa_restart_det mbedtls_ecdsa_restart_det_ctx;
+#endif
+
+/**
+ * \brief General context for resuming ECDSA operations
+ */
+typedef struct
+{
+ mbedtls_ecp_restart_ctx ecp; /*!< base context for ECP restart and
+ shared administrative info */
+ mbedtls_ecdsa_restart_ver_ctx *ver; /*!< ecdsa_verify() sub-context */
+ mbedtls_ecdsa_restart_sig_ctx *sig; /*!< ecdsa_sign() sub-context */
+#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
+ mbedtls_ecdsa_restart_det_ctx *det; /*!< ecdsa_sign_det() sub-context */
#endif
+} mbedtls_ecdsa_restart_ctx;
+
+#else /* MBEDTLS_ECP_RESTARTABLE */
+
+/* Now we can declare functions that take a pointer to that */
+typedef void mbedtls_ecdsa_restart_ctx;
+
+#endif /* MBEDTLS_ECP_RESTARTABLE */
/**
* \brief This function computes the ECDSA signature of a
* previously-hashed message.
*
- * \note The deterministic version is usually preferred.
+ * \note The deterministic version implemented in
+ * mbedtls_ecdsa_sign_det() is usually preferred.
*
* \note If the bitlength of the message hash is larger than the
* bitlength of the group order, then the hash is truncated
@@ -78,14 +129,22 @@ extern "C" {
*
* \see ecp.h
*
- * \param grp The ECP group.
- * \param r The first output integer.
- * \param s The second output integer.
- * \param d The private signing key.
- * \param buf The message hash.
- * \param blen The length of \p buf.
- * \param f_rng The RNG function.
- * \param p_rng The RNG context.
+ * \param grp The context for the elliptic curve to use.
+ * This must be initialized and have group parameters
+ * set, for example through mbedtls_ecp_group_load().
+ * \param r The MPI context in which to store the first part
+ * the signature. This must be initialized.
+ * \param s The MPI context in which to store the second part
+ * the signature. This must be initialized.
+ * \param d The private signing key. This must be initialized.
+ * \param buf The content to be signed. This is usually the hash of
+ * the original data to be signed. This must be a readable
+ * buffer of length \p blen Bytes. It may be \c NULL if
+ * \p blen is zero.
+ * \param blen The length of \p buf in Bytes.
+ * \param f_rng The RNG function. This must not be \c NULL.
+ * \param p_rng The RNG context to be passed to \p f_rng. This may be
+ * \c NULL if \p f_rng doesn't need a context parameter.
*
* \return \c 0 on success.
* \return An \c MBEDTLS_ERR_ECP_XXX
@@ -112,21 +171,29 @@ int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
*
* \see ecp.h
*
- * \param grp The ECP group.
- * \param r The first output integer.
- * \param s The second output integer.
- * \param d The private signing key.
- * \param buf The message hash.
- * \param blen The length of \p buf.
- * \param md_alg The MD algorithm used to hash the message.
+ * \param grp The context for the elliptic curve to use.
+ * This must be initialized and have group parameters
+ * set, for example through mbedtls_ecp_group_load().
+ * \param r The MPI context in which to store the first part
+ * the signature. This must be initialized.
+ * \param s The MPI context in which to store the second part
+ * the signature. This must be initialized.
+ * \param d The private signing key. This must be initialized
+ * and setup, for example through mbedtls_ecp_gen_privkey().
+ * \param buf The hashed content to be signed. This must be a readable
+ * buffer of length \p blen Bytes. It may be \c NULL if
+ * \p blen is zero.
+ * \param blen The length of \p buf in Bytes.
+ * \param md_alg The hash algorithm used to hash the original data.
*
* \return \c 0 on success.
* \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX
* error code on failure.
*/
-int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
- const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
- mbedtls_md_type_t md_alg );
+int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r,
+ mbedtls_mpi *s, const mbedtls_mpi *d,
+ const unsigned char *buf, size_t blen,
+ mbedtls_md_type_t md_alg );
#endif /* MBEDTLS_ECDSA_DETERMINISTIC */
/**
@@ -141,12 +208,19 @@ int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi
*
* \see ecp.h
*
- * \param grp The ECP group.
- * \param buf The message hash.
- * \param blen The length of \p buf.
- * \param Q The public key to use for verification.
+ * \param grp The ECP group to use.
+ * This must be initialized and have group parameters
+ * set, for example through mbedtls_ecp_group_load().
+ * \param buf The hashed content that was signed. This must be a readable
+ * buffer of length \p blen Bytes. It may be \c NULL if
+ * \p blen is zero.
+ * \param blen The length of \p buf in Bytes.
+ * \param Q The public key to use for verification. This must be
+ * initialized and setup.
* \param r The first integer of the signature.
+ * This must be initialized.
* \param s The second integer of the signature.
+ * This must be initialized.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the signature
@@ -155,8 +229,9 @@ int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi
* error code on failure for any other reason.
*/
int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp,
- const unsigned char *buf, size_t blen,
- const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s);
+ const unsigned char *buf, size_t blen,
+ const mbedtls_ecp_point *Q, const mbedtls_mpi *r,
+ const mbedtls_mpi *s);
/**
* \brief This function computes the ECDSA signature and writes it
@@ -173,11 +248,6 @@ int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp,
* of the Digital Signature Algorithm (DSA) and Elliptic
* Curve Digital Signature Algorithm (ECDSA)</em>.
*
- * \note The \p sig buffer must be at least twice as large as the
- * size of the curve used, plus 9. For example, 73 Bytes if
- * a 256-bit curve is used. A buffer length of
- * #MBEDTLS_ECDSA_MAX_LEN is always safe.
- *
* \note If the bitlength of the message hash is larger than the
* bitlength of the group order, then the hash is truncated as
* defined in <em>Standards for Efficient Cryptography Group
@@ -186,25 +256,84 @@ int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp,
*
* \see ecp.h
*
- * \param ctx The ECDSA context.
+ * \param ctx The ECDSA context to use. This must be initialized
+ * and have a group and private key bound to it, for example
+ * via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair().
* \param md_alg The message digest that was used to hash the message.
- * \param hash The message hash.
- * \param hlen The length of the hash.
- * \param sig The buffer that holds the signature.
- * \param slen The length of the signature written.
- * \param f_rng The RNG function.
- * \param p_rng The RNG context.
+ * \param hash The message hash to be signed. This must be a readable
+ * buffer of length \p blen Bytes.
+ * \param hlen The length of the hash \p hash in Bytes.
+ * \param sig The buffer to which to write the signature. This must be a
+ * writable buffer of length at least twice as large as the
+ * size of the curve used, plus 9. For example, 73 Bytes if
+ * a 256-bit curve is used. A buffer length of
+ * #MBEDTLS_ECDSA_MAX_LEN is always safe.
+ * \param slen The address at which to store the actual length of
+ * the signature written. Must not be \c NULL.
+ * \param f_rng The RNG function. This must not be \c NULL if
+ * #MBEDTLS_ECDSA_DETERMINISTIC is unset. Otherwise,
+ * it is unused and may be set to \c NULL.
+ * \param p_rng The RNG context to be passed to \p f_rng. This may be
+ * \c NULL if \p f_rng is \c NULL or doesn't use a context.
*
* \return \c 0 on success.
* \return An \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or
* \c MBEDTLS_ERR_ASN1_XXX error code on failure.
*/
-int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg,
+int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx,
+ mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hlen,
unsigned char *sig, size_t *slen,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
+/**
+ * \brief This function computes the ECDSA signature and writes it
+ * to a buffer, in a restartable way.
+ *
+ * \see \c mbedtls_ecdsa_write_signature()
+ *
+ * \note This function is like \c mbedtls_ecdsa_write_signature()
+ * but it can return early and restart according to the limit
+ * set with \c mbedtls_ecp_set_max_ops() to reduce blocking.
+ *
+ * \param ctx The ECDSA context to use. This must be initialized
+ * and have a group and private key bound to it, for example
+ * via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair().
+ * \param md_alg The message digest that was used to hash the message.
+ * \param hash The message hash to be signed. This must be a readable
+ * buffer of length \p blen Bytes.
+ * \param hlen The length of the hash \p hash in Bytes.
+ * \param sig The buffer to which to write the signature. This must be a
+ * writable buffer of length at least twice as large as the
+ * size of the curve used, plus 9. For example, 73 Bytes if
+ * a 256-bit curve is used. A buffer length of
+ * #MBEDTLS_ECDSA_MAX_LEN is always safe.
+ * \param slen The address at which to store the actual length of
+ * the signature written. Must not be \c NULL.
+ * \param f_rng The RNG function. This must not be \c NULL if
+ * #MBEDTLS_ECDSA_DETERMINISTIC is unset. Otherwise,
+ * it is unused and may be set to \c NULL.
+ * \param p_rng The RNG context to be passed to \p f_rng. This may be
+ * \c NULL if \p f_rng is \c NULL or doesn't use a context.
+ * \param rs_ctx The restart context to use. This may be \c NULL to disable
+ * restarting. If it is not \c NULL, it must point to an
+ * initialized restart context.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
+ * operations was reached: see \c mbedtls_ecp_set_max_ops().
+ * \return Another \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or
+ * \c MBEDTLS_ERR_ASN1_XXX error code on failure.
+ */
+int mbedtls_ecdsa_write_signature_restartable( mbedtls_ecdsa_context *ctx,
+ mbedtls_md_type_t md_alg,
+ const unsigned char *hash, size_t hlen,
+ unsigned char *sig, size_t *slen,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ mbedtls_ecdsa_restart_ctx *rs_ctx );
+
#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
#if ! defined(MBEDTLS_DEPRECATED_REMOVED)
#if defined(MBEDTLS_DEPRECATED_WARNING)
@@ -225,11 +354,6 @@ int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t
* \warning It is not thread-safe to use the same context in
* multiple threads.
*
- * \note The \p sig buffer must be at least twice as large as the
- * size of the curve used, plus 9. For example, 73 Bytes if a
- * 256-bit curve is used. A buffer length of
- * #MBEDTLS_ECDSA_MAX_LEN is always safe.
- *
* \note If the bitlength of the message hash is larger than the
* bitlength of the group order, then the hash is truncated as
* defined in <em>Standards for Efficient Cryptography Group
@@ -241,12 +365,20 @@ int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t
* \deprecated Superseded by mbedtls_ecdsa_write_signature() in
* Mbed TLS version 2.0 and later.
*
- * \param ctx The ECDSA context.
- * \param hash The message hash.
- * \param hlen The length of the hash.
- * \param sig The buffer that holds the signature.
- * \param slen The length of the signature written.
- * \param md_alg The MD algorithm used to hash the message.
+ * \param ctx The ECDSA context to use. This must be initialized
+ * and have a group and private key bound to it, for example
+ * via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair().
+ * \param hash The message hash to be signed. This must be a readable
+ * buffer of length \p blen Bytes.
+ * \param hlen The length of the hash \p hash in Bytes.
+ * \param sig The buffer to which to write the signature. This must be a
+ * writable buffer of length at least twice as large as the
+ * size of the curve used, plus 9. For example, 73 Bytes if
+ * a 256-bit curve is used. A buffer length of
+ * #MBEDTLS_ECDSA_MAX_LEN is always safe.
+ * \param slen The address at which to store the actual length of
+ * the signature written. Must not be \c NULL.
+ * \param md_alg The message digest that was used to hash the message.
*
* \return \c 0 on success.
* \return An \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or
@@ -271,11 +403,14 @@ int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx,
*
* \see ecp.h
*
- * \param ctx The ECDSA context.
- * \param hash The message hash.
- * \param hlen The size of the hash.
- * \param sig The signature to read and verify.
- * \param slen The size of \p sig.
+ * \param ctx The ECDSA context to use. This must be initialized
+ * and have a group and public key bound to it.
+ * \param hash The message hash that was signed. This must be a readable
+ * buffer of length \p size Bytes.
+ * \param hlen The size of the hash \p hash.
+ * \param sig The signature to read and verify. This must be a readable
+ * buffer of length \p slen Bytes.
+ * \param slen The size of \p sig in Bytes.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid.
@@ -289,15 +424,53 @@ int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx,
const unsigned char *sig, size_t slen );
/**
+ * \brief This function reads and verifies an ECDSA signature,
+ * in a restartable way.
+ *
+ * \see \c mbedtls_ecdsa_read_signature()
+ *
+ * \note This function is like \c mbedtls_ecdsa_read_signature()
+ * but it can return early and restart according to the limit
+ * set with \c mbedtls_ecp_set_max_ops() to reduce blocking.
+ *
+ * \param ctx The ECDSA context to use. This must be initialized
+ * and have a group and public key bound to it.
+ * \param hash The message hash that was signed. This must be a readable
+ * buffer of length \p size Bytes.
+ * \param hlen The size of the hash \p hash.
+ * \param sig The signature to read and verify. This must be a readable
+ * buffer of length \p slen Bytes.
+ * \param slen The size of \p sig in Bytes.
+ * \param rs_ctx The restart context to use. This may be \c NULL to disable
+ * restarting. If it is not \c NULL, it must point to an
+ * initialized restart context.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid.
+ * \return #MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH if there is a valid
+ * signature in \p sig, but its length is less than \p siglen.
+ * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
+ * operations was reached: see \c mbedtls_ecp_set_max_ops().
+ * \return Another \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_ERR_MPI_XXX
+ * error code on failure for any other reason.
+ */
+int mbedtls_ecdsa_read_signature_restartable( mbedtls_ecdsa_context *ctx,
+ const unsigned char *hash, size_t hlen,
+ const unsigned char *sig, size_t slen,
+ mbedtls_ecdsa_restart_ctx *rs_ctx );
+
+/**
* \brief This function generates an ECDSA keypair on the given curve.
*
* \see ecp.h
*
* \param ctx The ECDSA context to store the keypair in.
+ * This must be initialized.
* \param gid The elliptic curve to use. One of the various
* \c MBEDTLS_ECP_DP_XXX macros depending on configuration.
- * \param f_rng The RNG function.
- * \param p_rng The RNG context.
+ * \param f_rng The RNG function to use. This must not be \c NULL.
+ * \param p_rng The RNG context to be passed to \p f_rng. This may be
+ * \c NULL if \p f_rng doesn't need a context argument.
*
* \return \c 0 on success.
* \return An \c MBEDTLS_ERR_ECP_XXX code on failure.
@@ -306,32 +479,59 @@ int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
/**
- * \brief This function sets an ECDSA context from an EC key pair.
+ * \brief This function sets up an ECDSA context from an EC key pair.
*
* \see ecp.h
*
- * \param ctx The ECDSA context to set.
- * \param key The EC key to use.
+ * \param ctx The ECDSA context to setup. This must be initialized.
+ * \param key The EC key to use. This must be initialized and hold
+ * a private-public key pair or a public key. In the former
+ * case, the ECDSA context may be used for signature creation
+ * and verification after this call. In the latter case, it
+ * may be used for signature verification.
*
* \return \c 0 on success.
* \return An \c MBEDTLS_ERR_ECP_XXX code on failure.
*/
-int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key );
+int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx,
+ const mbedtls_ecp_keypair *key );
/**
* \brief This function initializes an ECDSA context.
*
* \param ctx The ECDSA context to initialize.
+ * This must not be \c NULL.
*/
void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx );
/**
* \brief This function frees an ECDSA context.
*
- * \param ctx The ECDSA context to free.
+ * \param ctx The ECDSA context to free. This may be \c NULL,
+ * in which case this function does nothing. If it
+ * is not \c NULL, it must be initialized.
*/
void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx );
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+/**
+ * \brief Initialize a restart context.
+ *
+ * \param ctx The restart context to initialize.
+ * This must not be \c NULL.
+ */
+void mbedtls_ecdsa_restart_init( mbedtls_ecdsa_restart_ctx *ctx );
+
+/**
+ * \brief Free the components of a restart context.
+ *
+ * \param ctx The restart context to free. This may be \c NULL,
+ * in which case this function does nothing. If it
+ * is not \c NULL, it must be initialized.
+ */
+void mbedtls_ecdsa_restart_free( mbedtls_ecdsa_restart_ctx *ctx );
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
#ifdef __cplusplus
}
#endif
diff --git a/thirdparty/mbedtls/include/mbedtls/ecjpake.h b/thirdparty/mbedtls/include/mbedtls/ecjpake.h
index cc2b316f5e..b967af8385 100644
--- a/thirdparty/mbedtls/include/mbedtls/ecjpake.h
+++ b/thirdparty/mbedtls/include/mbedtls/ecjpake.h
@@ -68,7 +68,7 @@ typedef enum {
* convetion from the Thread v1.0 spec. Correspondance is indicated in the
* description as a pair C: client name, S: server name
*/
-typedef struct
+typedef struct mbedtls_ecjpake_context
{
const mbedtls_md_info_t *md_info; /**< Hash to use */
mbedtls_ecp_group grp; /**< Elliptic curve */
@@ -92,28 +92,33 @@ typedef struct
#endif /* MBEDTLS_ECJPAKE_ALT */
/**
- * \brief Initialize a context
- * (just makes it ready for setup() or free()).
+ * \brief Initialize an ECJPAKE context.
*
- * \param ctx context to initialize
+ * \param ctx The ECJPAKE context to initialize.
+ * This must not be \c NULL.
*/
void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx );
/**
- * \brief Set up a context for use
+ * \brief Set up an ECJPAKE context for use.
*
* \note Currently the only values for hash/curve allowed by the
- * standard are MBEDTLS_MD_SHA256/MBEDTLS_ECP_DP_SECP256R1.
+ * standard are #MBEDTLS_MD_SHA256/#MBEDTLS_ECP_DP_SECP256R1.
*
- * \param ctx context to set up
- * \param role Our role: client or server
- * \param hash hash function to use (MBEDTLS_MD_XXX)
- * \param curve elliptic curve identifier (MBEDTLS_ECP_DP_XXX)
- * \param secret pre-shared secret (passphrase)
- * \param len length of the shared secret
+ * \param ctx The ECJPAKE context to set up. This must be initialized.
+ * \param role The role of the caller. This must be either
+ * #MBEDTLS_ECJPAKE_CLIENT or #MBEDTLS_ECJPAKE_SERVER.
+ * \param hash The identifier of the hash function to use,
+ * for example #MBEDTLS_MD_SHA256.
+ * \param curve The identifier of the elliptic curve to use,
+ * for example #MBEDTLS_ECP_DP_SECP256R1.
+ * \param secret The pre-shared secret (passphrase). This must be
+ * a readable buffer of length \p len Bytes. It need
+ * only be valid for the duration of this call.
+ * \param len The length of the pre-shared secret \p secret.
*
- * \return 0 if successfull,
- * a negative error code otherwise
+ * \return \c 0 if successful.
+ * \return A negative error code on failure.
*/
int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx,
mbedtls_ecjpake_role role,
@@ -123,29 +128,34 @@ int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx,
size_t len );
/**
- * \brief Check if a context is ready for use
+ * \brief Check if an ECJPAKE context is ready for use.
*
- * \param ctx Context to check
+ * \param ctx The ECJPAKE context to check. This must be
+ * initialized.
*
- * \return 0 if the context is ready for use,
- * MBEDTLS_ERR_ECP_BAD_INPUT_DATA otherwise
+ * \return \c 0 if the context is ready for use.
+ * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA otherwise.
*/
int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx );
/**
* \brief Generate and write the first round message
* (TLS: contents of the Client/ServerHello extension,
- * excluding extension type and length bytes)
+ * excluding extension type and length bytes).
*
- * \param ctx Context to use
- * \param buf Buffer to write the contents to
- * \param len Buffer size
- * \param olen Will be updated with the number of bytes written
- * \param f_rng RNG function
- * \param p_rng RNG parameter
+ * \param ctx The ECJPAKE context to use. This must be
+ * initialized and set up.
+ * \param buf The buffer to write the contents to. This must be a
+ * writable buffer of length \p len Bytes.
+ * \param len The length of \p buf in Bytes.
+ * \param olen The address at which to store the total number
+ * of Bytes written to \p buf. This must not be \c NULL.
+ * \param f_rng The RNG function to use. This must not be \c NULL.
+ * \param p_rng The RNG parameter to be passed to \p f_rng. This
+ * may be \c NULL if \p f_rng doesn't use a context.
*
- * \return 0 if successfull,
- * a negative error code otherwise
+ * \return \c 0 if successful.
+ * \return A negative error code on failure.
*/
int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx,
unsigned char *buf, size_t len, size_t *olen,
@@ -155,14 +165,16 @@ int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx,
/**
* \brief Read and process the first round message
* (TLS: contents of the Client/ServerHello extension,
- * excluding extension type and length bytes)
+ * excluding extension type and length bytes).
*
- * \param ctx Context to use
- * \param buf Pointer to extension contents
- * \param len Extension length
+ * \param ctx The ECJPAKE context to use. This must be initialized
+ * and set up.
+ * \param buf The buffer holding the first round message. This must
+ * be a readable buffer of length \p len Bytes.
+ * \param len The length in Bytes of \p buf.
*
- * \return 0 if successfull,
- * a negative error code otherwise
+ * \return \c 0 if successful.
+ * \return A negative error code on failure.
*/
int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx,
const unsigned char *buf,
@@ -170,17 +182,21 @@ int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx,
/**
* \brief Generate and write the second round message
- * (TLS: contents of the Client/ServerKeyExchange)
+ * (TLS: contents of the Client/ServerKeyExchange).
*
- * \param ctx Context to use
- * \param buf Buffer to write the contents to
- * \param len Buffer size
- * \param olen Will be updated with the number of bytes written
- * \param f_rng RNG function
- * \param p_rng RNG parameter
+ * \param ctx The ECJPAKE context to use. This must be initialized,
+ * set up, and already have performed round one.
+ * \param buf The buffer to write the round two contents to.
+ * This must be a writable buffer of length \p len Bytes.
+ * \param len The size of \p buf in Bytes.
+ * \param olen The address at which to store the total number of Bytes
+ * written to \p buf. This must not be \c NULL.
+ * \param f_rng The RNG function to use. This must not be \c NULL.
+ * \param p_rng The RNG parameter to be passed to \p f_rng. This
+ * may be \c NULL if \p f_rng doesn't use a context.
*
- * \return 0 if successfull,
- * a negative error code otherwise
+ * \return \c 0 if successful.
+ * \return A negative error code on failure.
*/
int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx,
unsigned char *buf, size_t len, size_t *olen,
@@ -189,14 +205,16 @@ int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx,
/**
* \brief Read and process the second round message
- * (TLS: contents of the Client/ServerKeyExchange)
+ * (TLS: contents of the Client/ServerKeyExchange).
*
- * \param ctx Context to use
- * \param buf Pointer to the message
- * \param len Message length
+ * \param ctx The ECJPAKE context to use. This must be initialized
+ * and set up and already have performed round one.
+ * \param buf The buffer holding the second round message. This must
+ * be a readable buffer of length \p len Bytes.
+ * \param len The length in Bytes of \p buf.
*
- * \return 0 if successfull,
- * a negative error code otherwise
+ * \return \c 0 if successful.
+ * \return A negative error code on failure.
*/
int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx,
const unsigned char *buf,
@@ -204,17 +222,21 @@ int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx,
/**
* \brief Derive the shared secret
- * (TLS: Pre-Master Secret)
+ * (TLS: Pre-Master Secret).
*
- * \param ctx Context to use
- * \param buf Buffer to write the contents to
- * \param len Buffer size
- * \param olen Will be updated with the number of bytes written
- * \param f_rng RNG function
- * \param p_rng RNG parameter
+ * \param ctx The ECJPAKE context to use. This must be initialized,
+ * set up and have performed both round one and two.
+ * \param buf The buffer to write the derived secret to. This must
+ * be a writable buffer of length \p len Bytes.
+ * \param len The length of \p buf in Bytes.
+ * \param olen The address at which to store the total number of Bytes
+ * written to \p buf. This must not be \c NULL.
+ * \param f_rng The RNG function to use. This must not be \c NULL.
+ * \param p_rng The RNG parameter to be passed to \p f_rng. This
+ * may be \c NULL if \p f_rng doesn't use a context.
*
- * \return 0 if successfull,
- * a negative error code otherwise
+ * \return \c 0 if successful.
+ * \return A negative error code on failure.
*/
int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx,
unsigned char *buf, size_t len, size_t *olen,
@@ -222,14 +244,15 @@ int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx,
void *p_rng );
/**
- * \brief Free a context's content
+ * \brief This clears an ECJPAKE context and frees any
+ * embedded data structure.
*
- * \param ctx context to free
+ * \param ctx The ECJPAKE context to free. This may be \c NULL,
+ * in which case this function does nothing. If it is not
+ * \c NULL, it must point to an initialized ECJPAKE context.
*/
void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx );
-
-
#if defined(MBEDTLS_SELF_TEST)
/**
diff --git a/thirdparty/mbedtls/include/mbedtls/ecp.h b/thirdparty/mbedtls/include/mbedtls/ecp.h
index 3a407986dd..de3a343cb6 100644
--- a/thirdparty/mbedtls/include/mbedtls/ecp.h
+++ b/thirdparty/mbedtls/include/mbedtls/ecp.h
@@ -49,8 +49,12 @@
#define MBEDTLS_ERR_ECP_RANDOM_FAILED -0x4D00 /**< Generation of random value, such as ephemeral key, failed. */
#define MBEDTLS_ERR_ECP_INVALID_KEY -0x4C80 /**< Invalid private or public key. */
#define MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH -0x4C00 /**< The buffer contains a valid signature followed by more data. */
+
+/* MBEDTLS_ERR_ECP_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_ECP_HW_ACCEL_FAILED -0x4B80 /**< The ECP hardware accelerator failed. */
+#define MBEDTLS_ERR_ECP_IN_PROGRESS -0x4B00 /**< Operation in progress, call again with the same parameters to continue. */
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -92,7 +96,7 @@ typedef enum
/**
* Curve information, for use by other modules.
*/
-typedef struct
+typedef struct mbedtls_ecp_curve_info
{
mbedtls_ecp_group_id grp_id; /*!< An internal identifier. */
uint16_t tls_id; /*!< The TLS NamedCurve identifier. */
@@ -111,7 +115,7 @@ typedef struct
* Otherwise, \p X and \p Y are its standard (affine)
* coordinates.
*/
-typedef struct
+typedef struct mbedtls_ecp_point
{
mbedtls_mpi X; /*!< The X coordinate of the ECP point. */
mbedtls_mpi Y; /*!< The Y coordinate of the ECP point. */
@@ -155,8 +159,12 @@ mbedtls_ecp_point;
* additions or subtractions. Therefore, it is only an approximative modular
* reduction. It must return 0 on success and non-zero on failure.
*
+ * \note Alternative implementations must keep the group IDs distinct. If
+ * two group structures have the same ID, then they must be
+ * identical.
+ *
*/
-typedef struct
+typedef struct mbedtls_ecp_group
{
mbedtls_ecp_group_id id; /*!< An internal group identifier. */
mbedtls_mpi P; /*!< The prime modulus of the base field. */
@@ -181,6 +189,70 @@ typedef struct
}
mbedtls_ecp_group;
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+
+/**
+ * \brief Internal restart context for multiplication
+ *
+ * \note Opaque struct
+ */
+typedef struct mbedtls_ecp_restart_mul mbedtls_ecp_restart_mul_ctx;
+
+/**
+ * \brief Internal restart context for ecp_muladd()
+ *
+ * \note Opaque struct
+ */
+typedef struct mbedtls_ecp_restart_muladd mbedtls_ecp_restart_muladd_ctx;
+
+/**
+ * \brief General context for resuming ECC operations
+ */
+typedef struct
+{
+ unsigned ops_done; /*!< current ops count */
+ unsigned depth; /*!< call depth (0 = top-level) */
+ mbedtls_ecp_restart_mul_ctx *rsm; /*!< ecp_mul_comb() sub-context */
+ mbedtls_ecp_restart_muladd_ctx *ma; /*!< ecp_muladd() sub-context */
+} mbedtls_ecp_restart_ctx;
+
+/*
+ * Operation counts for restartable functions
+ */
+#define MBEDTLS_ECP_OPS_CHK 3 /*!< basic ops count for ecp_check_pubkey() */
+#define MBEDTLS_ECP_OPS_DBL 8 /*!< basic ops count for ecp_double_jac() */
+#define MBEDTLS_ECP_OPS_ADD 11 /*!< basic ops count for see ecp_add_mixed() */
+#define MBEDTLS_ECP_OPS_INV 120 /*!< empirical equivalent for mpi_mod_inv() */
+
+/**
+ * \brief Internal; for restartable functions in other modules.
+ * Check and update basic ops budget.
+ *
+ * \param grp Group structure
+ * \param rs_ctx Restart context
+ * \param ops Number of basic ops to do
+ *
+ * \return \c 0 if doing \p ops basic ops is still allowed,
+ * \return #MBEDTLS_ERR_ECP_IN_PROGRESS otherwise.
+ */
+int mbedtls_ecp_check_budget( const mbedtls_ecp_group *grp,
+ mbedtls_ecp_restart_ctx *rs_ctx,
+ unsigned ops );
+
+/* Utility macro for checking and updating ops budget */
+#define MBEDTLS_ECP_BUDGET( ops ) \
+ MBEDTLS_MPI_CHK( mbedtls_ecp_check_budget( grp, rs_ctx, \
+ (unsigned) (ops) ) );
+
+#else /* MBEDTLS_ECP_RESTARTABLE */
+
+#define MBEDTLS_ECP_BUDGET( ops ) /* no-op; for compatibility */
+
+/* We want to declare restartable versions of existing functions anyway */
+typedef void mbedtls_ecp_restart_ctx;
+
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
/**
* \name SECTION: Module settings
*
@@ -251,7 +323,7 @@ mbedtls_ecp_group;
* \note Members are deliberately in the same order as in the
* ::mbedtls_ecdsa_context structure.
*/
-typedef struct
+typedef struct mbedtls_ecp_keypair
{
mbedtls_ecp_group grp; /*!< Elliptic curve and base point */
mbedtls_mpi d; /*!< our secret value */
@@ -270,6 +342,75 @@ mbedtls_ecp_keypair;
*/
#define MBEDTLS_ECP_TLS_NAMED_CURVE 3 /**< The named_curve of ECCurveType. */
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+/**
+ * \brief Set the maximum number of basic operations done in a row.
+ *
+ * If more operations are needed to complete a computation,
+ * #MBEDTLS_ERR_ECP_IN_PROGRESS will be returned by the
+ * function performing the computation. It is then the
+ * caller's responsibility to either call again with the same
+ * parameters until it returns 0 or an error code; or to free
+ * the restart context if the operation is to be aborted.
+ *
+ * It is strictly required that all input parameters and the
+ * restart context be the same on successive calls for the
+ * same operation, but output parameters need not be the
+ * same; they must not be used until the function finally
+ * returns 0.
+ *
+ * This only applies to functions whose documentation
+ * mentions they may return #MBEDTLS_ERR_ECP_IN_PROGRESS (or
+ * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS for functions in the
+ * SSL module). For functions that accept a "restart context"
+ * argument, passing NULL disables restart and makes the
+ * function equivalent to the function with the same name
+ * with \c _restartable removed. For functions in the ECDH
+ * module, restart is disabled unless the function accepts
+ * an "ECDH context" argument and
+ * mbedtls_ecdh_enable_restart() was previously called on
+ * that context. For function in the SSL module, restart is
+ * only enabled for specific sides and key exchanges
+ * (currently only for clients and ECDHE-ECDSA).
+ *
+ * \param max_ops Maximum number of basic operations done in a row.
+ * Default: 0 (unlimited).
+ * Lower (non-zero) values mean ECC functions will block for
+ * a lesser maximum amount of time.
+ *
+ * \note A "basic operation" is defined as a rough equivalent of a
+ * multiplication in GF(p) for the NIST P-256 curve.
+ * As an indication, with default settings, a scalar
+ * multiplication (full run of \c mbedtls_ecp_mul()) is:
+ * - about 3300 basic operations for P-256
+ * - about 9400 basic operations for P-384
+ *
+ * \note Very low values are not always respected: sometimes
+ * functions need to block for a minimum number of
+ * operations, and will do so even if max_ops is set to a
+ * lower value. That minimum depends on the curve size, and
+ * can be made lower by decreasing the value of
+ * \c MBEDTLS_ECP_WINDOW_SIZE. As an indication, here is the
+ * lowest effective value for various curves and values of
+ * that parameter (w for short):
+ * w=6 w=5 w=4 w=3 w=2
+ * P-256 208 208 160 136 124
+ * P-384 682 416 320 272 248
+ * P-521 1364 832 640 544 496
+ *
+ * \note This setting is currently ignored by Curve25519.
+ */
+void mbedtls_ecp_set_max_ops( unsigned max_ops );
+
+/**
+ * \brief Check if restart is enabled (max_ops != 0)
+ *
+ * \return \c 0 if \c max_ops == 0 (restart disabled)
+ * \return \c 1 otherwise (restart enabled)
+ */
+int mbedtls_ecp_restart_is_enabled( void );
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
/**
* \brief This function retrieves the information defined in
* mbedtls_ecp_curve_info() for all supported curves in order
@@ -356,25 +497,51 @@ void mbedtls_ecp_point_free( mbedtls_ecp_point *pt );
/**
* \brief This function frees the components of an ECP group.
- * \param grp The group to free.
+ *
+ * \param grp The group to free. This may be \c NULL, in which
+ * case this function returns immediately. If it is not
+ * \c NULL, it must point to an initialized ECP group.
*/
void mbedtls_ecp_group_free( mbedtls_ecp_group *grp );
/**
* \brief This function frees the components of a key pair.
- * \param key The key pair to free.
+ *
+ * \param key The key pair to free. This may be \c NULL, in which
+ * case this function returns immediately. If it is not
+ * \c NULL, it must point to an initialized ECP key pair.
*/
void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key );
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+/**
+ * \brief Initialize a restart context.
+ *
+ * \param ctx The restart context to initialize. This must
+ * not be \c NULL.
+ */
+void mbedtls_ecp_restart_init( mbedtls_ecp_restart_ctx *ctx );
+
+/**
+ * \brief Free the components of a restart context.
+ *
+ * \param ctx The restart context to free. This may be \c NULL, in which
+ * case this function returns immediately. If it is not
+ * \c NULL, it must point to an initialized restart context.
+ */
+void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx );
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
/**
* \brief This function copies the contents of point \p Q into
* point \p P.
*
- * \param P The destination point.
- * \param Q The source point.
+ * \param P The destination point. This must be initialized.
+ * \param Q The source point. This must be initialized.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure.
+ * \return Another negative error code for other kinds of failure.
*/
int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q );
@@ -382,31 +549,35 @@ int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q );
* \brief This function copies the contents of group \p src into
* group \p dst.
*
- * \param dst The destination group.
- * \param src The source group.
+ * \param dst The destination group. This must be initialized.
+ * \param src The source group. This must be initialized.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure.
+ * \return Another negative error code on other kinds of failure.
*/
-int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src );
+int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst,
+ const mbedtls_ecp_group *src );
/**
- * \brief This function sets a point to zero.
+ * \brief This function sets a point to the point at infinity.
*
- * \param pt The point to set.
+ * \param pt The point to set. This must be initialized.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure.
+ * \return Another negative error code on other kinds of failure.
*/
int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt );
/**
- * \brief This function checks if a point is zero.
+ * \brief This function checks if a point is the point at infinity.
*
- * \param pt The point to test.
+ * \param pt The point to test. This must be initialized.
*
* \return \c 1 if the point is zero.
* \return \c 0 if the point is non-zero.
+ * \return A negative error code on failure.
*/
int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt );
@@ -416,8 +587,8 @@ int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt );
* \note This assumes that the points are normalized. Otherwise,
* they may compare as "not equal" even if they are.
*
- * \param P The first point to compare.
- * \param Q The second point to compare.
+ * \param P The first point to compare. This must be initialized.
+ * \param Q The second point to compare. This must be initialized.
*
* \return \c 0 if the points are equal.
* \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the points are not equal.
@@ -429,7 +600,7 @@ int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P,
* \brief This function imports a non-zero point from two ASCII
* strings.
*
- * \param P The destination point.
+ * \param P The destination point. This must be initialized.
* \param radix The numeric base of the input.
* \param x The first affine coordinate, as a null-terminated string.
* \param y The second affine coordinate, as a null-terminated string.
@@ -444,15 +615,21 @@ int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix,
* \brief This function exports a point into unsigned binary data.
*
* \param grp The group to which the point should belong.
- * \param P The point to export.
- * \param format The point format. Should be an \c MBEDTLS_ECP_PF_XXX macro.
- * \param olen The length of the output.
- * \param buf The output buffer.
- * \param buflen The length of the output buffer.
+ * This must be initialized and have group parameters
+ * set, for example through mbedtls_ecp_group_load().
+ * \param P The point to export. This must be initialized.
+ * \param format The point format. This must be either
+ * #MBEDTLS_ECP_PF_COMPRESSED or #MBEDTLS_ECP_PF_UNCOMPRESSED.
+ * \param olen The address at which to store the length of
+ * the output in Bytes. This must not be \c NULL.
+ * \param buf The output buffer. This must be a writable buffer
+ * of length \p buflen Bytes.
+ * \param buflen The length of the output buffer \p buf in Bytes.
*
* \return \c 0 on success.
- * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA
- * or #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL on failure.
+ * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the output buffer
+ * is too small to hold the point.
+ * \return Another negative error code on other kinds of failure.
*/
int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P,
int format, size_t *olen,
@@ -466,108 +643,158 @@ int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, const mbedtls_
* for that.
*
* \param grp The group to which the point should belong.
- * \param P The point to import.
- * \param buf The input buffer.
- * \param ilen The length of the input.
+ * This must be initialized and have group parameters
+ * set, for example through mbedtls_ecp_group_load().
+ * \param P The destination context to import the point to.
+ * This must be initialized.
+ * \param buf The input buffer. This must be a readable buffer
+ * of length \p ilen Bytes.
+ * \param ilen The length of the input buffer \p buf in Bytes.
*
* \return \c 0 on success.
- * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid.
+ * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the input is invalid.
* \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure.
* \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the point format
* is not implemented.
- *
*/
-int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P,
- const unsigned char *buf, size_t ilen );
+int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp,
+ mbedtls_ecp_point *P,
+ const unsigned char *buf, size_t ilen );
/**
* \brief This function imports a point from a TLS ECPoint record.
*
- * \note On function return, \p buf is updated to point to immediately
+ * \note On function return, \p *buf is updated to point immediately
* after the ECPoint record.
*
- * \param grp The ECP group used.
+ * \param grp The ECP group to use.
+ * This must be initialized and have group parameters
+ * set, for example through mbedtls_ecp_group_load().
* \param pt The destination point.
* \param buf The address of the pointer to the start of the input buffer.
* \param len The length of the buffer.
*
* \return \c 0 on success.
- * \return An \c MBEDTLS_ERR_MPI_XXX error code on initialization failure.
+ * \return An \c MBEDTLS_ERR_MPI_XXX error code on initialization
+ * failure.
* \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid.
*/
-int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
- const unsigned char **buf, size_t len );
+int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp,
+ mbedtls_ecp_point *pt,
+ const unsigned char **buf, size_t len );
/**
- * \brief This function exports a point as a TLS ECPoint record.
- *
- * \param grp The ECP group used.
- * \param pt The point format to export to. The point format is an
- * \c MBEDTLS_ECP_PF_XXX constant.
- * \param format The export format.
- * \param olen The length of the data written.
- * \param buf The buffer to write to.
- * \param blen The length of the buffer.
+ * \brief This function exports a point as a TLS ECPoint record
+ * defined in RFC 4492, Section 5.4.
+ *
+ * \param grp The ECP group to use.
+ * This must be initialized and have group parameters
+ * set, for example through mbedtls_ecp_group_load().
+ * \param pt The point to be exported. This must be initialized.
+ * \param format The point format to use. This must be either
+ * #MBEDTLS_ECP_PF_COMPRESSED or #MBEDTLS_ECP_PF_UNCOMPRESSED.
+ * \param olen The address at which to store the length in Bytes
+ * of the data written.
+ * \param buf The target buffer. This must be a writable buffer of
+ * length \p blen Bytes.
+ * \param blen The length of the target buffer \p buf in Bytes.
*
* \return \c 0 on success.
- * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA or
- * #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL on failure.
+ * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the input is invalid.
+ * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the target buffer
+ * is too small to hold the exported point.
+ * \return Another negative error code on other kinds of failure.
*/
-int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt,
- int format, size_t *olen,
- unsigned char *buf, size_t blen );
+int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp,
+ const mbedtls_ecp_point *pt,
+ int format, size_t *olen,
+ unsigned char *buf, size_t blen );
/**
- * \brief This function sets a group using standardized domain parameters.
+ * \brief This function sets up an ECP group context
+ * from a standardized set of domain parameters.
*
* \note The index should be a value of the NamedCurve enum,
* as defined in <em>RFC-4492: Elliptic Curve Cryptography
* (ECC) Cipher Suites for Transport Layer Security (TLS)</em>,
* usually in the form of an \c MBEDTLS_ECP_DP_XXX macro.
*
- * \param grp The destination group.
+ * \param grp The group context to setup. This must be initialized.
* \param id The identifier of the domain parameter set to load.
*
- * \return \c 0 on success,
- * \return An \c MBEDTLS_ERR_MPI_XXX error code on initialization failure.
- * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE for unkownn groups.
-
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if \p id doesn't
+ * correspond to a known group.
+ * \return Another negative error code on other kinds of failure.
*/
int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id id );
/**
- * \brief This function sets a group from a TLS ECParameters record.
+ * \brief This function sets up an ECP group context from a TLS
+ * ECParameters record as defined in RFC 4492, Section 5.4.
*
- * \note \p buf is updated to point right after the ECParameters record
- * on exit.
+ * \note The read pointer \p buf is updated to point right after
+ * the ECParameters record on exit.
*
- * \param grp The destination group.
+ * \param grp The group context to setup. This must be initialized.
* \param buf The address of the pointer to the start of the input buffer.
- * \param len The length of the buffer.
+ * \param len The length of the input buffer \c *buf in Bytes.
*
* \return \c 0 on success.
- * \return An \c MBEDTLS_ERR_MPI_XXX error code on initialization failure.
* \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid.
+ * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the group is not
+ * recognized.
+ * \return Another negative error code on other kinds of failure.
*/
-int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, const unsigned char **buf, size_t len );
+int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp,
+ const unsigned char **buf, size_t len );
/**
- * \brief This function writes the TLS ECParameters record for a group.
+ * \brief This function extracts an elliptic curve group ID from a
+ * TLS ECParameters record as defined in RFC 4492, Section 5.4.
+ *
+ * \note The read pointer \p buf is updated to point right after
+ * the ECParameters record on exit.
+ *
+ * \param grp The address at which to store the group id.
+ * This must not be \c NULL.
+ * \param buf The address of the pointer to the start of the input buffer.
+ * \param len The length of the input buffer \c *buf in Bytes.
*
- * \param grp The ECP group used.
- * \param olen The number of Bytes written.
- * \param buf The buffer to write to.
- * \param blen The length of the buffer.
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid.
+ * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the group is not
+ * recognized.
+ * \return Another negative error code on other kinds of failure.
+ */
+int mbedtls_ecp_tls_read_group_id( mbedtls_ecp_group_id *grp,
+ const unsigned char **buf,
+ size_t len );
+/**
+ * \brief This function exports an elliptic curve as a TLS
+ * ECParameters record as defined in RFC 4492, Section 5.4.
+ *
+ * \param grp The ECP group to be exported.
+ * This must be initialized and have group parameters
+ * set, for example through mbedtls_ecp_group_load().
+ * \param olen The address at which to store the number of Bytes written.
+ * This must not be \c NULL.
+ * \param buf The buffer to write to. This must be a writable buffer
+ * of length \p blen Bytes.
+ * \param blen The length of the output buffer \p buf in Bytes.
*
* \return \c 0 on success.
- * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL on failure.
+ * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the output
+ * buffer is too small to hold the exported group.
+ * \return Another negative error code on other kinds of failure.
*/
-int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen,
- unsigned char *buf, size_t blen );
+int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp,
+ size_t *olen,
+ unsigned char *buf, size_t blen );
/**
- * \brief This function performs multiplication of a point by
- * an integer: \p R = \p m * \p P.
+ * \brief This function performs a scalar multiplication of a point
+ * by an integer: \p R = \p m * \p P.
*
* It is not thread-safe to use same group in multiple threads.
*
@@ -581,23 +808,63 @@ int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen,
* targeting these results. We recommend always providing
* a non-NULL \p f_rng. The overhead is negligible.
*
- * \param grp The ECP group.
- * \param R The destination point.
- * \param m The integer by which to multiply.
- * \param P The point to multiply.
- * \param f_rng The RNG function.
- * \param p_rng The RNG context.
+ * \param grp The ECP group to use.
+ * This must be initialized and have group parameters
+ * set, for example through mbedtls_ecp_group_load().
+ * \param R The point in which to store the result of the calculation.
+ * This must be initialized.
+ * \param m The integer by which to multiply. This must be initialized.
+ * \param P The point to multiply. This must be initialized.
+ * \param f_rng The RNG function. This may be \c NULL if randomization
+ * of intermediate results isn't desired (discouraged).
+ * \param p_rng The RNG context to be passed to \p p_rng.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m is not a valid private
* key, or \p P is not a valid public key.
* \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure.
+ * \return Another negative error code on other kinds of failure.
*/
int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
const mbedtls_mpi *m, const mbedtls_ecp_point *P,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
/**
+ * \brief This function performs multiplication of a point by
+ * an integer: \p R = \p m * \p P in a restartable way.
+ *
+ * \see mbedtls_ecp_mul()
+ *
+ * \note This function does the same as \c mbedtls_ecp_mul(), but
+ * it can return early and restart according to the limit set
+ * with \c mbedtls_ecp_set_max_ops() to reduce blocking.
+ *
+ * \param grp The ECP group to use.
+ * This must be initialized and have group parameters
+ * set, for example through mbedtls_ecp_group_load().
+ * \param R The point in which to store the result of the calculation.
+ * This must be initialized.
+ * \param m The integer by which to multiply. This must be initialized.
+ * \param P The point to multiply. This must be initialized.
+ * \param f_rng The RNG function. This may be \c NULL if randomization
+ * of intermediate results isn't desired (discouraged).
+ * \param p_rng The RNG context to be passed to \p p_rng.
+ * \param rs_ctx The restart context (NULL disables restart).
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m is not a valid private
+ * key, or \p P is not a valid public key.
+ * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure.
+ * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
+ * operations was reached: see \c mbedtls_ecp_set_max_ops().
+ * \return Another negative error code on other kinds of failure.
+ */
+int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
+ const mbedtls_mpi *m, const mbedtls_ecp_point *P,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+ mbedtls_ecp_restart_ctx *rs_ctx );
+
+/**
* \brief This function performs multiplication and addition of two
* points by integers: \p R = \p m * \p P + \p n * \p Q
*
@@ -606,24 +873,71 @@ int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
* \note In contrast to mbedtls_ecp_mul(), this function does not
* guarantee a constant execution flow and timing.
*
- * \param grp The ECP group.
- * \param R The destination point.
+ * \param grp The ECP group to use.
+ * This must be initialized and have group parameters
+ * set, for example through mbedtls_ecp_group_load().
+ * \param R The point in which to store the result of the calculation.
+ * This must be initialized.
* \param m The integer by which to multiply \p P.
- * \param P The point to multiply by \p m.
+ * This must be initialized.
+ * \param P The point to multiply by \p m. This must be initialized.
* \param n The integer by which to multiply \p Q.
+ * This must be initialized.
* \param Q The point to be multiplied by \p n.
+ * This must be initialized.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m or \p n are not
* valid private keys, or \p P or \p Q are not valid public
* keys.
* \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure.
+ * \return Another negative error code on other kinds of failure.
*/
int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
const mbedtls_mpi *m, const mbedtls_ecp_point *P,
const mbedtls_mpi *n, const mbedtls_ecp_point *Q );
/**
+ * \brief This function performs multiplication and addition of two
+ * points by integers: \p R = \p m * \p P + \p n * \p Q in a
+ * restartable way.
+ *
+ * \see \c mbedtls_ecp_muladd()
+ *
+ * \note This function works the same as \c mbedtls_ecp_muladd(),
+ * but it can return early and restart according to the limit
+ * set with \c mbedtls_ecp_set_max_ops() to reduce blocking.
+ *
+ * \param grp The ECP group to use.
+ * This must be initialized and have group parameters
+ * set, for example through mbedtls_ecp_group_load().
+ * \param R The point in which to store the result of the calculation.
+ * This must be initialized.
+ * \param m The integer by which to multiply \p P.
+ * This must be initialized.
+ * \param P The point to multiply by \p m. This must be initialized.
+ * \param n The integer by which to multiply \p Q.
+ * This must be initialized.
+ * \param Q The point to be multiplied by \p n.
+ * This must be initialized.
+ * \param rs_ctx The restart context (NULL disables restart).
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m or \p n are not
+ * valid private keys, or \p P or \p Q are not valid public
+ * keys.
+ * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure.
+ * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
+ * operations was reached: see \c mbedtls_ecp_set_max_ops().
+ * \return Another negative error code on other kinds of failure.
+ */
+int mbedtls_ecp_muladd_restartable(
+ mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
+ const mbedtls_mpi *m, const mbedtls_ecp_point *P,
+ const mbedtls_mpi *n, const mbedtls_ecp_point *Q,
+ mbedtls_ecp_restart_ctx *rs_ctx );
+
+/**
* \brief This function checks that a point is a valid public key
* on this curve.
*
@@ -640,30 +954,60 @@ int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
* structures, such as ::mbedtls_ecdh_context or
* ::mbedtls_ecdsa_context.
*
- * \param grp The curve the point should lie on.
- * \param pt The point to check.
+ * \param grp The ECP group the point should belong to.
+ * This must be initialized and have group parameters
+ * set, for example through mbedtls_ecp_group_load().
+ * \param pt The point to check. This must be initialized.
*
* \return \c 0 if the point is a valid public key.
- * \return #MBEDTLS_ERR_ECP_INVALID_KEY on failure.
+ * \return #MBEDTLS_ERR_ECP_INVALID_KEY if the point is not
+ * a valid public key for the given curve.
+ * \return Another negative error code on other kinds of failure.
*/
-int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt );
+int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp,
+ const mbedtls_ecp_point *pt );
/**
- * \brief This function checks that an \p mbedtls_mpi is a valid private
- * key for this curve.
+ * \brief This function checks that an \p mbedtls_mpi is a
+ * valid private key for this curve.
*
* \note This function uses bare components rather than an
* ::mbedtls_ecp_keypair structure to ease use with other
* structures, such as ::mbedtls_ecdh_context or
* ::mbedtls_ecdsa_context.
*
- * \param grp The group used.
- * \param d The integer to check.
+ * \param grp The ECP group the private key should belong to.
+ * This must be initialized and have group parameters
+ * set, for example through mbedtls_ecp_group_load().
+ * \param d The integer to check. This must be initialized.
*
* \return \c 0 if the point is a valid private key.
- * \return #MBEDTLS_ERR_ECP_INVALID_KEY on failure.
+ * \return #MBEDTLS_ERR_ECP_INVALID_KEY if the point is not a valid
+ * private key for the given curve.
+ * \return Another negative error code on other kinds of failure.
+ */
+int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp,
+ const mbedtls_mpi *d );
+
+/**
+ * \brief This function generates a private key.
+ *
+ * \param grp The ECP group to generate a private key for.
+ * This must be initialized and have group parameters
+ * set, for example through mbedtls_ecp_group_load().
+ * \param d The destination MPI (secret part). This must be initialized.
+ * \param f_rng The RNG function. This must not be \c NULL.
+ * \param p_rng The RNG parameter to be passed to \p f_rng. This may be
+ * \c NULL if \p f_rng doesn't need a context argument.
+ *
+ * \return \c 0 on success.
+ * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code
+ * on failure.
*/
-int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *d );
+int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp,
+ mbedtls_mpi *d,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng );
/**
* \brief This function generates a keypair with a configurable base
@@ -674,22 +1018,29 @@ int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *
* structures, such as ::mbedtls_ecdh_context or
* ::mbedtls_ecdsa_context.
*
- * \param grp The ECP group.
- * \param G The chosen base point.
+ * \param grp The ECP group to generate a key pair for.
+ * This must be initialized and have group parameters
+ * set, for example through mbedtls_ecp_group_load().
+ * \param G The base point to use. This must be initialized
+ * and belong to \p grp. It replaces the default base
+ * point \c grp->G used by mbedtls_ecp_gen_keypair().
* \param d The destination MPI (secret part).
+ * This must be initialized.
* \param Q The destination point (public part).
- * \param f_rng The RNG function.
- * \param p_rng The RNG context.
+ * This must be initialized.
+ * \param f_rng The RNG function. This must not be \c NULL.
+ * \param p_rng The RNG context to be passed to \p f_rng. This may
+ * be \c NULL if \p f_rng doesn't need a context argument.
*
* \return \c 0 on success.
* \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code
* on failure.
*/
int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
- const mbedtls_ecp_point *G,
- mbedtls_mpi *d, mbedtls_ecp_point *Q,
- int (*f_rng)(void *, unsigned char *, size_t),
- void *p_rng );
+ const mbedtls_ecp_point *G,
+ mbedtls_mpi *d, mbedtls_ecp_point *Q,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng );
/**
* \brief This function generates an ECP keypair.
@@ -699,34 +1050,42 @@ int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
* structures, such as ::mbedtls_ecdh_context or
* ::mbedtls_ecdsa_context.
*
- * \param grp The ECP group.
+ * \param grp The ECP group to generate a key pair for.
+ * This must be initialized and have group parameters
+ * set, for example through mbedtls_ecp_group_load().
* \param d The destination MPI (secret part).
+ * This must be initialized.
* \param Q The destination point (public part).
- * \param f_rng The RNG function.
- * \param p_rng The RNG context.
+ * This must be initialized.
+ * \param f_rng The RNG function. This must not be \c NULL.
+ * \param p_rng The RNG context to be passed to \p f_rng. This may
+ * be \c NULL if \p f_rng doesn't need a context argument.
*
* \return \c 0 on success.
* \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code
* on failure.
*/
-int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q,
- int (*f_rng)(void *, unsigned char *, size_t),
- void *p_rng );
+int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp, mbedtls_mpi *d,
+ mbedtls_ecp_point *Q,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng );
/**
* \brief This function generates an ECP key.
*
* \param grp_id The ECP group identifier.
- * \param key The destination key.
- * \param f_rng The RNG function.
- * \param p_rng The RNG context.
+ * \param key The destination key. This must be initialized.
+ * \param f_rng The RNG function to use. This must not be \c NULL.
+ * \param p_rng The RNG context to be passed to \p f_rng. This may
+ * be \c NULL if \p f_rng doesn't need a context argument.
*
* \return \c 0 on success.
* \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code
* on failure.
*/
int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
- int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng );
/**
* \brief This function checks that the keypair objects
@@ -734,16 +1093,19 @@ int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
* same public point, and that the private key in
* \p prv is consistent with the public key.
*
- * \param pub The keypair structure holding the public key.
- * If it contains a private key, that part is ignored.
+ * \param pub The keypair structure holding the public key. This
+ * must be initialized. If it contains a private key, that
+ * part is ignored.
* \param prv The keypair structure holding the full keypair.
+ * This must be initialized.
*
* \return \c 0 on success, meaning that the keys are valid and match.
* \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the keys are invalid or do not match.
* \return An \c MBEDTLS_ERR_ECP_XXX or an \c MBEDTLS_ERR_MPI_XXX
* error code on calculation failure.
*/
-int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv );
+int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub,
+ const mbedtls_ecp_keypair *prv );
#if defined(MBEDTLS_SELF_TEST)
diff --git a/thirdparty/mbedtls/include/mbedtls/entropy.h b/thirdparty/mbedtls/include/mbedtls/entropy.h
index a5cb05a584..ca06dc3c58 100644
--- a/thirdparty/mbedtls/include/mbedtls/entropy.h
+++ b/thirdparty/mbedtls/include/mbedtls/entropy.h
@@ -107,7 +107,7 @@ typedef int (*mbedtls_entropy_f_source_ptr)(void *data, unsigned char *output, s
/**
* \brief Entropy source state
*/
-typedef struct
+typedef struct mbedtls_entropy_source_state
{
mbedtls_entropy_f_source_ptr f_source; /**< The entropy source callback */
void * p_source; /**< The callback data pointer */
@@ -120,7 +120,7 @@ mbedtls_entropy_source_state;
/**
* \brief Entropy context structure
*/
-typedef struct
+typedef struct mbedtls_entropy_context
{
int accumulator_started;
#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
diff --git a/thirdparty/mbedtls/include/mbedtls/error.h b/thirdparty/mbedtls/include/mbedtls/error.h
index 6b82d4fbbe..647a11a566 100644
--- a/thirdparty/mbedtls/include/mbedtls/error.h
+++ b/thirdparty/mbedtls/include/mbedtls/error.h
@@ -74,12 +74,13 @@
* MD4 1 0x002D-0x002D
* MD5 1 0x002F-0x002F
* RIPEMD160 1 0x0031-0x0031
- * SHA1 1 0x0035-0x0035
- * SHA256 1 0x0037-0x0037
- * SHA512 1 0x0039-0x0039
+ * SHA1 1 0x0035-0x0035 0x0073-0x0073
+ * SHA256 1 0x0037-0x0037 0x0074-0x0074
+ * SHA512 1 0x0039-0x0039 0x0075-0x0075
* CHACHA20 3 0x0051-0x0055
* POLY1305 3 0x0057-0x005B
* CHACHAPOLY 2 0x0054-0x0056
+ * PLATFORM 1 0x0070-0x0072
*
* High-level module nr (3 bits - 0x0...-0x7...)
* Name ID Nr of Errors
@@ -90,12 +91,12 @@
* DHM 3 11
* PK 3 15 (Started from top)
* RSA 4 11
- * ECP 4 9 (Started from top)
+ * ECP 4 10 (Started from top)
* MD 5 5
* HKDF 5 1 (Started from top)
* CIPHER 6 8
- * SSL 6 22 (Started from top)
- * SSL 7 31
+ * SSL 6 23 (Started from top)
+ * SSL 7 32
*
* Module dependent error code (5 bits 0x.00.-0x.F8.)
*/
diff --git a/thirdparty/mbedtls/include/mbedtls/gcm.h b/thirdparty/mbedtls/include/mbedtls/gcm.h
index 87535ab957..fccabb0d97 100644
--- a/thirdparty/mbedtls/include/mbedtls/gcm.h
+++ b/thirdparty/mbedtls/include/mbedtls/gcm.h
@@ -41,7 +41,10 @@
#define MBEDTLS_GCM_DECRYPT 0
#define MBEDTLS_ERR_GCM_AUTH_FAILED -0x0012 /**< Authenticated decryption failed. */
+
+/* MBEDTLS_ERR_GCM_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_GCM_HW_ACCEL_FAILED -0x0013 /**< GCM hardware accelerator failed. */
+
#define MBEDTLS_ERR_GCM_BAD_INPUT -0x0014 /**< Bad input parameters to function. */
#ifdef __cplusplus
@@ -53,7 +56,8 @@ extern "C" {
/**
* \brief The GCM context structure.
*/
-typedef struct {
+typedef struct mbedtls_gcm_context
+{
mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */
uint64_t HL[16]; /*!< Precalculated HTable low. */
uint64_t HH[16]; /*!< Precalculated HTable high. */
@@ -81,7 +85,7 @@ mbedtls_gcm_context;
* cipher, nor set the key. For this purpose, use
* mbedtls_gcm_setkey().
*
- * \param ctx The GCM context to initialize.
+ * \param ctx The GCM context to initialize. This must not be \c NULL.
*/
void mbedtls_gcm_init( mbedtls_gcm_context *ctx );
@@ -89,9 +93,10 @@ void mbedtls_gcm_init( mbedtls_gcm_context *ctx );
* \brief This function associates a GCM context with a
* cipher algorithm and a key.
*
- * \param ctx The GCM context to initialize.
+ * \param ctx The GCM context. This must be initialized.
* \param cipher The 128-bit block cipher to use.
- * \param key The encryption key.
+ * \param key The encryption key. This must be a readable buffer of at
+ * least \p keybits bits.
* \param keybits The key size in bits. Valid options are:
* <ul><li>128 bits</li>
* <li>192 bits</li>
@@ -118,7 +123,8 @@ int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx,
* authentic. You should use this function to perform encryption
* only. For decryption, use mbedtls_gcm_auth_decrypt() instead.
*
- * \param ctx The GCM context to use for encryption or decryption.
+ * \param ctx The GCM context to use for encryption or decryption. This
+ * must be initialized.
* \param mode The operation to perform:
* - #MBEDTLS_GCM_ENCRYPT to perform authenticated encryption.
* The ciphertext is written to \p output and the
@@ -132,22 +138,28 @@ int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx,
* calling this function in decryption mode.
* \param length The length of the input data, which is equal to the length
* of the output data.
- * \param iv The initialization vector.
+ * \param iv The initialization vector. This must be a readable buffer of
+ * at least \p iv_len Bytes.
* \param iv_len The length of the IV.
- * \param add The buffer holding the additional data.
+ * \param add The buffer holding the additional data. This must be of at
+ * least that size in Bytes.
* \param add_len The length of the additional data.
- * \param input The buffer holding the input data. Its size is \b length.
- * \param output The buffer for holding the output data. It must have room
- * for \b length bytes.
+ * \param input The buffer holding the input data. If \p length is greater
+ * than zero, this must be a readable buffer of at least that
+ * size in Bytes.
+ * \param output The buffer for holding the output data. If \p length is greater
+ * than zero, this must be a writable buffer of at least that
+ * size in Bytes.
* \param tag_len The length of the tag to generate.
- * \param tag The buffer for holding the tag.
+ * \param tag The buffer for holding the tag. This must be a readable
+ * buffer of at least \p tag_len Bytes.
*
* \return \c 0 if the encryption or decryption was performed
* successfully. Note that in #MBEDTLS_GCM_DECRYPT mode,
* this does not indicate that the data is authentic.
- * \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths are not valid.
- * \return #MBEDTLS_ERR_GCM_HW_ACCEL_FAILED or a cipher-specific
- * error code if the encryption or decryption failed.
+ * \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths or pointers are
+ * not valid or a cipher-specific error code if the encryption
+ * or decryption failed.
*/
int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx,
int mode,
@@ -169,24 +181,30 @@ int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx,
* input buffer. If the buffers overlap, the output buffer
* must trail at least 8 Bytes behind the input buffer.
*
- * \param ctx The GCM context.
+ * \param ctx The GCM context. This must be initialized.
* \param length The length of the ciphertext to decrypt, which is also
* the length of the decrypted plaintext.
- * \param iv The initialization vector.
+ * \param iv The initialization vector. This must be a readable buffer
+ * of at least \p iv_len Bytes.
* \param iv_len The length of the IV.
- * \param add The buffer holding the additional data.
+ * \param add The buffer holding the additional data. This must be of at
+ * least that size in Bytes.
* \param add_len The length of the additional data.
- * \param tag The buffer holding the tag to verify.
+ * \param tag The buffer holding the tag to verify. This must be a
+ * readable buffer of at least \p tag_len Bytes.
* \param tag_len The length of the tag to verify.
- * \param input The buffer holding the ciphertext. Its size is \b length.
- * \param output The buffer for holding the decrypted plaintext. It must
- * have room for \b length bytes.
+ * \param input The buffer holding the ciphertext. If \p length is greater
+ * than zero, this must be a readable buffer of at least that
+ * size.
+ * \param output The buffer for holding the decrypted plaintext. If \p length
+ * is greater than zero, this must be a writable buffer of at
+ * least that size.
*
* \return \c 0 if successful and authenticated.
* \return #MBEDTLS_ERR_GCM_AUTH_FAILED if the tag does not match.
- * \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths are not valid.
- * \return #MBEDTLS_ERR_GCM_HW_ACCEL_FAILED or a cipher-specific
- * error code if the decryption failed.
+ * \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths or pointers are
+ * not valid or a cipher-specific error code if the decryption
+ * failed.
*/
int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx,
size_t length,
@@ -203,15 +221,16 @@ int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx,
* \brief This function starts a GCM encryption or decryption
* operation.
*
- * \param ctx The GCM context.
+ * \param ctx The GCM context. This must be initialized.
* \param mode The operation to perform: #MBEDTLS_GCM_ENCRYPT or
* #MBEDTLS_GCM_DECRYPT.
- * \param iv The initialization vector.
+ * \param iv The initialization vector. This must be a readable buffer of
+ * at least \p iv_len Bytes.
* \param iv_len The length of the IV.
- * \param add The buffer holding the additional data, or NULL
- * if \p add_len is 0.
- * \param add_len The length of the additional data. If 0,
- * \p add is NULL.
+ * \param add The buffer holding the additional data, or \c NULL
+ * if \p add_len is \c 0.
+ * \param add_len The length of the additional data. If \c 0,
+ * \p add may be \c NULL.
*
* \return \c 0 on success.
*/
@@ -234,11 +253,15 @@ int mbedtls_gcm_starts( mbedtls_gcm_context *ctx,
* input buffer. If the buffers overlap, the output buffer
* must trail at least 8 Bytes behind the input buffer.
*
- * \param ctx The GCM context.
+ * \param ctx The GCM context. This must be initialized.
* \param length The length of the input data. This must be a multiple of
* 16 except in the last call before mbedtls_gcm_finish().
- * \param input The buffer holding the input data.
- * \param output The buffer for holding the output data.
+ * \param input The buffer holding the input data. If \p length is greater
+ * than zero, this must be a readable buffer of at least that
+ * size in Bytes.
+ * \param output The buffer for holding the output data. If \p length is
+ * greater than zero, this must be a writable buffer of at
+ * least that size in Bytes.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure.
@@ -255,9 +278,11 @@ int mbedtls_gcm_update( mbedtls_gcm_context *ctx,
* It wraps up the GCM stream, and generates the
* tag. The tag can have a maximum length of 16 Bytes.
*
- * \param ctx The GCM context.
- * \param tag The buffer for holding the tag.
- * \param tag_len The length of the tag to generate. Must be at least four.
+ * \param ctx The GCM context. This must be initialized.
+ * \param tag The buffer for holding the tag. This must be a readable
+ * buffer of at least \p tag_len Bytes.
+ * \param tag_len The length of the tag to generate. This must be at least
+ * four.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure.
@@ -270,7 +295,8 @@ int mbedtls_gcm_finish( mbedtls_gcm_context *ctx,
* \brief This function clears a GCM context and the underlying
* cipher sub-context.
*
- * \param ctx The GCM context to clear.
+ * \param ctx The GCM context to clear. If this is \c NULL, the call has
+ * no effect. Otherwise, this must be initialized.
*/
void mbedtls_gcm_free( mbedtls_gcm_context *ctx );
diff --git a/thirdparty/mbedtls/include/mbedtls/havege.h b/thirdparty/mbedtls/include/mbedtls/havege.h
index d4cb3ed38d..57e8c40943 100644
--- a/thirdparty/mbedtls/include/mbedtls/havege.h
+++ b/thirdparty/mbedtls/include/mbedtls/havege.h
@@ -35,7 +35,7 @@ extern "C" {
/**
* \brief HAVEGE state structure
*/
-typedef struct
+typedef struct mbedtls_havege_state
{
int PT1, PT2, offset[2];
int pool[MBEDTLS_HAVEGE_COLLECT_SIZE];
diff --git a/thirdparty/mbedtls/include/mbedtls/hkdf.h b/thirdparty/mbedtls/include/mbedtls/hkdf.h
index 6833e7272e..e6ed7cde97 100644
--- a/thirdparty/mbedtls/include/mbedtls/hkdf.h
+++ b/thirdparty/mbedtls/include/mbedtls/hkdf.h
@@ -73,6 +73,11 @@ int mbedtls_hkdf( const mbedtls_md_info_t *md, const unsigned char *salt,
* \brief Take the input keying material \p ikm and extract from it a
* fixed-length pseudorandom key \p prk.
*
+ * \warning This function should only be used if the security of it has been
+ * studied and established in that particular context (eg. TLS 1.3
+ * key schedule). For standard HKDF security guarantees use
+ * \c mbedtls_hkdf instead.
+ *
* \param md A hash function; md.size denotes the length of the
* hash function output in bytes.
* \param salt An optional salt value (a non-secret random value);
@@ -97,10 +102,15 @@ int mbedtls_hkdf_extract( const mbedtls_md_info_t *md,
* \brief Expand the supplied \p prk into several additional pseudorandom
* keys, which is the output of the HKDF.
*
+ * \warning This function should only be used if the security of it has been
+ * studied and established in that particular context (eg. TLS 1.3
+ * key schedule). For standard HKDF security guarantees use
+ * \c mbedtls_hkdf instead.
+ *
* \param md A hash function; md.size denotes the length of the hash
* function output in bytes.
- * \param prk A pseudorandom key of at least md.size bytes. \p prk is usually,
- * the output from the HKDF extract step.
+ * \param prk A pseudorandom key of at least md.size bytes. \p prk is
+ * usually the output from the HKDF extract step.
* \param prk_len The length in bytes of \p prk.
* \param info An optional context and application specific information
* string. This can be a zero-length string.
diff --git a/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h b/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h
index 2608de8595..146367b9de 100644
--- a/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h
+++ b/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h
@@ -74,7 +74,7 @@ extern "C" {
/**
* HMAC_DRBG context.
*/
-typedef struct
+typedef struct mbedtls_hmac_drbg_context
{
/* Working state: the key K is not stored explicitely,
* but is implied by the HMAC context */
@@ -195,10 +195,13 @@ void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx,
* \param additional Additional data to update state with, or NULL
* \param add_len Length of additional data, or 0
*
+ * \return \c 0 on success, or an error from the underlying
+ * hash calculation.
+ *
* \note Additional data is optional, pass NULL and 0 as second
* third argument if no additional data is being used.
*/
-void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx,
+int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx,
const unsigned char *additional, size_t add_len );
/**
@@ -257,6 +260,31 @@ int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len
*/
void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx );
+#if ! defined(MBEDTLS_DEPRECATED_REMOVED)
+#if defined(MBEDTLS_DEPRECATED_WARNING)
+#define MBEDTLS_DEPRECATED __attribute__((deprecated))
+#else
+#define MBEDTLS_DEPRECATED
+#endif
+/**
+ * \brief HMAC_DRBG update state
+ *
+ * \deprecated Superseded by mbedtls_hmac_drbg_update_ret()
+ * in 2.16.0.
+ *
+ * \param ctx HMAC_DRBG context
+ * \param additional Additional data to update state with, or NULL
+ * \param add_len Length of additional data, or 0
+ *
+ * \note Additional data is optional, pass NULL and 0 as second
+ * third argument if no additional data is being used.
+ */
+MBEDTLS_DEPRECATED void mbedtls_hmac_drbg_update(
+ mbedtls_hmac_drbg_context *ctx,
+ const unsigned char *additional, size_t add_len );
+#undef MBEDTLS_DEPRECATED
+#endif /* !MBEDTLS_DEPRECATED_REMOVED */
+
#if defined(MBEDTLS_FS_IO)
/**
* \brief Write a seed file
diff --git a/thirdparty/mbedtls/include/mbedtls/md.h b/thirdparty/mbedtls/include/mbedtls/md.h
index 6b6f5c53dd..8bcf766a6c 100644
--- a/thirdparty/mbedtls/include/mbedtls/md.h
+++ b/thirdparty/mbedtls/include/mbedtls/md.h
@@ -39,6 +39,8 @@
#define MBEDTLS_ERR_MD_BAD_INPUT_DATA -0x5100 /**< Bad input parameters to function. */
#define MBEDTLS_ERR_MD_ALLOC_FAILED -0x5180 /**< Failed to allocate memory. */
#define MBEDTLS_ERR_MD_FILE_IO_ERROR -0x5200 /**< Opening or reading of file failed. */
+
+/* MBEDTLS_ERR_MD_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_MD_HW_ACCEL_FAILED -0x5280 /**< MD hardware accelerator failed. */
#ifdef __cplusplus
@@ -80,7 +82,8 @@ typedef struct mbedtls_md_info_t mbedtls_md_info_t;
/**
* The generic message-digest context.
*/
-typedef struct {
+typedef struct mbedtls_md_context_t
+{
/** Information about the associated message digest. */
const mbedtls_md_info_t *md_info;
diff --git a/thirdparty/mbedtls/include/mbedtls/md2.h b/thirdparty/mbedtls/include/mbedtls/md2.h
index 08e75b247b..f9bd98f804 100644
--- a/thirdparty/mbedtls/include/mbedtls/md2.h
+++ b/thirdparty/mbedtls/include/mbedtls/md2.h
@@ -37,6 +37,7 @@
#include <stddef.h>
+/* MBEDTLS_ERR_MD2_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_MD2_HW_ACCEL_FAILED -0x002B /**< MD2 hardware accelerator failed */
#ifdef __cplusplus
@@ -55,7 +56,7 @@ extern "C" {
* stronger message digests instead.
*
*/
-typedef struct
+typedef struct mbedtls_md2_context
{
unsigned char cksum[16]; /*!< checksum of the data block */
unsigned char state[48]; /*!< intermediate digest state */
diff --git a/thirdparty/mbedtls/include/mbedtls/md4.h b/thirdparty/mbedtls/include/mbedtls/md4.h
index 8ee4e5cabf..dc3c048949 100644
--- a/thirdparty/mbedtls/include/mbedtls/md4.h
+++ b/thirdparty/mbedtls/include/mbedtls/md4.h
@@ -38,6 +38,7 @@
#include <stddef.h>
#include <stdint.h>
+/* MBEDTLS_ERR_MD4_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_MD4_HW_ACCEL_FAILED -0x002D /**< MD4 hardware accelerator failed */
#ifdef __cplusplus
@@ -56,7 +57,7 @@ extern "C" {
* stronger message digests instead.
*
*/
-typedef struct
+typedef struct mbedtls_md4_context
{
uint32_t total[2]; /*!< number of bytes processed */
uint32_t state[4]; /*!< intermediate digest state */
diff --git a/thirdparty/mbedtls/include/mbedtls/md5.h b/thirdparty/mbedtls/include/mbedtls/md5.h
index 43ead4b747..6c3354fd30 100644
--- a/thirdparty/mbedtls/include/mbedtls/md5.h
+++ b/thirdparty/mbedtls/include/mbedtls/md5.h
@@ -37,6 +37,7 @@
#include <stddef.h>
#include <stdint.h>
+/* MBEDTLS_ERR_MD5_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_MD5_HW_ACCEL_FAILED -0x002F /**< MD5 hardware accelerator failed */
#ifdef __cplusplus
@@ -55,7 +56,7 @@ extern "C" {
* stronger message digests instead.
*
*/
-typedef struct
+typedef struct mbedtls_md5_context
{
uint32_t total[2]; /*!< number of bytes processed */
uint32_t state[4]; /*!< intermediate digest state */
diff --git a/thirdparty/mbedtls/include/mbedtls/net_sockets.h b/thirdparty/mbedtls/include/mbedtls/net_sockets.h
index 9f07eeb4d3..4c7ef00fe6 100644
--- a/thirdparty/mbedtls/include/mbedtls/net_sockets.h
+++ b/thirdparty/mbedtls/include/mbedtls/net_sockets.h
@@ -84,7 +84,7 @@ extern "C" {
* (eg two file descriptors for combined IPv4 + IPv6 support, or additional
* structures for hand-made UDP demultiplexing).
*/
-typedef struct
+typedef struct mbedtls_net_context
{
int fd; /**< The underlying file descriptor */
}
diff --git a/thirdparty/mbedtls/include/mbedtls/oid.h b/thirdparty/mbedtls/include/mbedtls/oid.h
index f82554844c..6fbd018aaa 100644
--- a/thirdparty/mbedtls/include/mbedtls/oid.h
+++ b/thirdparty/mbedtls/include/mbedtls/oid.h
@@ -403,7 +403,8 @@ extern "C" {
/**
* \brief Base OID descriptor structure
*/
-typedef struct {
+typedef struct mbedtls_oid_descriptor_t
+{
const char *asn1; /*!< OID ASN.1 representation */
size_t asn1_len; /*!< length of asn1 */
const char *name; /*!< official name (e.g. from RFC) */
diff --git a/thirdparty/mbedtls/include/mbedtls/padlock.h b/thirdparty/mbedtls/include/mbedtls/padlock.h
index 677936ebf8..7a5d083a95 100644
--- a/thirdparty/mbedtls/include/mbedtls/padlock.h
+++ b/thirdparty/mbedtls/include/mbedtls/padlock.h
@@ -3,6 +3,9 @@
*
* \brief VIA PadLock ACE for HW encryption/decryption supported by some
* processors
+ *
+ * \warning These functions are only for internal use by other library
+ * functions; you must not call them directly.
*/
/*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
@@ -57,7 +60,10 @@ extern "C" {
#endif
/**
- * \brief PadLock detection routine
+ * \brief Internal PadLock detection routine
+ *
+ * \note This function is only for internal use by other library
+ * functions; you must not call it directly.
*
* \param feature The feature to detect
*
@@ -66,7 +72,10 @@ extern "C" {
int mbedtls_padlock_has_support( int feature );
/**
- * \brief PadLock AES-ECB block en(de)cryption
+ * \brief Internal PadLock AES-ECB block en(de)cryption
+ *
+ * \note This function is only for internal use by other library
+ * functions; you must not call it directly.
*
* \param ctx AES context
* \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
@@ -76,12 +85,15 @@ int mbedtls_padlock_has_support( int feature );
* \return 0 if success, 1 if operation failed
*/
int mbedtls_padlock_xcryptecb( mbedtls_aes_context *ctx,
- int mode,
- const unsigned char input[16],
- unsigned char output[16] );
+ int mode,
+ const unsigned char input[16],
+ unsigned char output[16] );
/**
- * \brief PadLock AES-CBC buffer en(de)cryption
+ * \brief Internal PadLock AES-CBC buffer en(de)cryption
+ *
+ * \note This function is only for internal use by other library
+ * functions; you must not call it directly.
*
* \param ctx AES context
* \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
@@ -93,11 +105,11 @@ int mbedtls_padlock_xcryptecb( mbedtls_aes_context *ctx,
* \return 0 if success, 1 if operation failed
*/
int mbedtls_padlock_xcryptcbc( mbedtls_aes_context *ctx,
- int mode,
- size_t length,
- unsigned char iv[16],
- const unsigned char *input,
- unsigned char *output );
+ int mode,
+ size_t length,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output );
#ifdef __cplusplus
}
diff --git a/thirdparty/mbedtls/include/mbedtls/pem.h b/thirdparty/mbedtls/include/mbedtls/pem.h
index 2cf4c0a709..fa82f7bdbd 100644
--- a/thirdparty/mbedtls/include/mbedtls/pem.h
+++ b/thirdparty/mbedtls/include/mbedtls/pem.h
@@ -51,7 +51,7 @@ extern "C" {
/**
* \brief PEM context structure
*/
-typedef struct
+typedef struct mbedtls_pem_context
{
unsigned char *buf; /*!< buffer for decoded data */
size_t buflen; /*!< length of the buffer */
diff --git a/thirdparty/mbedtls/include/mbedtls/pk.h b/thirdparty/mbedtls/include/mbedtls/pk.h
index ee06b2fd20..91950f9407 100644
--- a/thirdparty/mbedtls/include/mbedtls/pk.h
+++ b/thirdparty/mbedtls/include/mbedtls/pk.h
@@ -64,6 +64,8 @@
#define MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE -0x3A00 /**< Elliptic curve is unsupported (only NIST curves are supported). */
#define MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE -0x3980 /**< Unavailable feature, e.g. RSA disabled for RSA key. */
#define MBEDTLS_ERR_PK_SIG_LEN_MISMATCH -0x3900 /**< The buffer contains a valid signature followed by more data. */
+
+/* MBEDTLS_ERR_PK_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_PK_HW_ACCEL_FAILED -0x3880 /**< PK hardware accelerator failed. */
#ifdef __cplusplus
@@ -87,7 +89,7 @@ typedef enum {
* \brief Options for RSASSA-PSS signature verification.
* See \c mbedtls_rsa_rsassa_pss_verify_ext()
*/
-typedef struct
+typedef struct mbedtls_pk_rsassa_pss_options
{
mbedtls_md_type_t mgf1_hash_id;
int expected_salt_len;
@@ -107,7 +109,7 @@ typedef enum
/**
* \brief Item to send to the debug module
*/
-typedef struct
+typedef struct mbedtls_pk_debug_item
{
mbedtls_pk_debug_type type;
const char *name;
@@ -125,12 +127,26 @@ typedef struct mbedtls_pk_info_t mbedtls_pk_info_t;
/**
* \brief Public key container
*/
-typedef struct
+typedef struct mbedtls_pk_context
{
- const mbedtls_pk_info_t * pk_info; /**< Public key informations */
+ const mbedtls_pk_info_t * pk_info; /**< Public key information */
void * pk_ctx; /**< Underlying public key context */
} mbedtls_pk_context;
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+/**
+ * \brief Context for resuming operations
+ */
+typedef struct
+{
+ const mbedtls_pk_info_t * pk_info; /**< Public key information */
+ void * rs_ctx; /**< Underlying restart context */
+} mbedtls_pk_restart_ctx;
+#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+/* Now we can declare functions that take a pointer to that */
+typedef void mbedtls_pk_restart_ctx;
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+
#if defined(MBEDTLS_RSA_C)
/**
* Quick access to an RSA context inside a PK context.
@@ -181,20 +197,45 @@ typedef size_t (*mbedtls_pk_rsa_alt_key_len_func)( void *ctx );
const mbedtls_pk_info_t *mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type );
/**
- * \brief Initialize a mbedtls_pk_context (as NONE)
+ * \brief Initialize a #mbedtls_pk_context (as NONE).
+ *
+ * \param ctx The context to initialize.
+ * This must not be \c NULL.
*/
void mbedtls_pk_init( mbedtls_pk_context *ctx );
/**
- * \brief Free a mbedtls_pk_context
+ * \brief Free the components of a #mbedtls_pk_context.
+ *
+ * \param ctx The context to clear. It must have been initialized.
+ * If this is \c NULL, this function does nothing.
*/
void mbedtls_pk_free( mbedtls_pk_context *ctx );
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+/**
+ * \brief Initialize a restart context
+ *
+ * \param ctx The context to initialize.
+ * This must not be \c NULL.
+ */
+void mbedtls_pk_restart_init( mbedtls_pk_restart_ctx *ctx );
+
+/**
+ * \brief Free the components of a restart context
+ *
+ * \param ctx The context to clear. It must have been initialized.
+ * If this is \c NULL, this function does nothing.
+ */
+void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx );
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+
/**
* \brief Initialize a PK context with the information given
* and allocates the type-specific PK subcontext.
*
- * \param ctx Context to initialize. Must be empty (type NONE).
+ * \param ctx Context to initialize. It must not have been set
+ * up yet (type #MBEDTLS_PK_NONE).
* \param info Information to use
*
* \return 0 on success,
@@ -210,7 +251,8 @@ int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info );
/**
* \brief Initialize an RSA-alt context
*
- * \param ctx Context to initialize. Must be empty (type NONE).
+ * \param ctx Context to initialize. It must not have been set
+ * up yet (type #MBEDTLS_PK_NONE).
* \param key RSA key pointer
* \param decrypt_func Decryption function
* \param sign_func Signing function
@@ -230,7 +272,7 @@ int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key,
/**
* \brief Get the size in bits of the underlying key
*
- * \param ctx Context to use
+ * \param ctx The context to query. It must have been initialized.
*
* \return Key size in bits, or 0 on error
*/
@@ -238,7 +280,8 @@ size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx );
/**
* \brief Get the length in bytes of the underlying key
- * \param ctx Context to use
+ *
+ * \param ctx The context to query. It must have been initialized.
*
* \return Key length in bytes, or 0 on error
*/
@@ -250,18 +293,21 @@ static inline size_t mbedtls_pk_get_len( const mbedtls_pk_context *ctx )
/**
* \brief Tell if a context can do the operation given by type
*
- * \param ctx Context to test
- * \param type Target type
+ * \param ctx The context to query. It must have been initialized.
+ * \param type The desired type.
*
- * \return 0 if context can't do the operations,
- * 1 otherwise.
+ * \return 1 if the context can do operations on the given type.
+ * \return 0 if the context cannot do the operations on the given
+ * type. This is always the case for a context that has
+ * been initialized but not set up, or that has been
+ * cleared with mbedtls_pk_free().
*/
int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type );
/**
* \brief Verify signature (including padding if relevant).
*
- * \param ctx PK context to use
+ * \param ctx The PK context to use. It must have been set up.
* \param md_alg Hash algorithm used (see notes)
* \param hash Hash of the message to sign
* \param hash_len Hash length or 0 (see notes)
@@ -287,12 +333,38 @@ int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
const unsigned char *sig, size_t sig_len );
/**
+ * \brief Restartable version of \c mbedtls_pk_verify()
+ *
+ * \note Performs the same job as \c mbedtls_pk_verify(), but can
+ * return early and restart according to the limit set with
+ * \c mbedtls_ecp_set_max_ops() to reduce blocking for ECC
+ * operations. For RSA, same as \c mbedtls_pk_verify().
+ *
+ * \param ctx The PK context to use. It must have been set up.
+ * \param md_alg Hash algorithm used (see notes)
+ * \param hash Hash of the message to sign
+ * \param hash_len Hash length or 0 (see notes)
+ * \param sig Signature to verify
+ * \param sig_len Signature length
+ * \param rs_ctx Restart context (NULL to disable restart)
+ *
+ * \return See \c mbedtls_pk_verify(), or
+ * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
+ * operations was reached: see \c mbedtls_ecp_set_max_ops().
+ */
+int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx,
+ mbedtls_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ const unsigned char *sig, size_t sig_len,
+ mbedtls_pk_restart_ctx *rs_ctx );
+
+/**
* \brief Verify signature, with options.
* (Includes verification of the padding depending on type.)
*
* \param type Signature type (inc. possible padding type) to verify
* \param options Pointer to type-specific options, or NULL
- * \param ctx PK context to use
+ * \param ctx The PK context to use. It must have been set up.
* \param md_alg Hash algorithm used (see notes)
* \param hash Hash of the message to sign
* \param hash_len Hash length or 0 (see notes)
@@ -323,7 +395,8 @@ int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options,
/**
* \brief Make signature, including padding if relevant.
*
- * \param ctx PK context to use - must hold a private key
+ * \param ctx The PK context to use. It must have been set up
+ * with a private key.
* \param md_alg Hash algorithm used (see notes)
* \param hash Hash of the message to sign
* \param hash_len Hash length or 0 (see notes)
@@ -350,9 +423,40 @@ int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
/**
+ * \brief Restartable version of \c mbedtls_pk_sign()
+ *
+ * \note Performs the same job as \c mbedtls_pk_sign(), but can
+ * return early and restart according to the limit set with
+ * \c mbedtls_ecp_set_max_ops() to reduce blocking for ECC
+ * operations. For RSA, same as \c mbedtls_pk_sign().
+ *
+ * \param ctx The PK context to use. It must have been set up
+ * with a private key.
+ * \param md_alg Hash algorithm used (see notes)
+ * \param hash Hash of the message to sign
+ * \param hash_len Hash length or 0 (see notes)
+ * \param sig Place to write the signature
+ * \param sig_len Number of bytes written
+ * \param f_rng RNG function
+ * \param p_rng RNG parameter
+ * \param rs_ctx Restart context (NULL to disable restart)
+ *
+ * \return See \c mbedtls_pk_sign(), or
+ * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
+ * operations was reached: see \c mbedtls_ecp_set_max_ops().
+ */
+int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx,
+ mbedtls_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ unsigned char *sig, size_t *sig_len,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+ mbedtls_pk_restart_ctx *rs_ctx );
+
+/**
* \brief Decrypt message (including padding if relevant).
*
- * \param ctx PK context to use - must hold a private key
+ * \param ctx The PK context to use. It must have been set up
+ * with a private key.
* \param input Input to decrypt
* \param ilen Input size
* \param output Decrypted output
@@ -373,7 +477,7 @@ int mbedtls_pk_decrypt( mbedtls_pk_context *ctx,
/**
* \brief Encrypt message (including padding if relevant).
*
- * \param ctx PK context to use
+ * \param ctx The PK context to use. It must have been set up.
* \param input Message to encrypt
* \param ilen Message size
* \param output Encrypted output
@@ -404,7 +508,7 @@ int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_conte
/**
* \brief Export debug information
*
- * \param ctx Context to use
+ * \param ctx The PK context to use. It must have been initialized.
* \param items Place to write debug items
*
* \return 0 on success or MBEDTLS_ERR_PK_BAD_INPUT_DATA
@@ -414,7 +518,7 @@ int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *item
/**
* \brief Access the type name
*
- * \param ctx Context to use
+ * \param ctx The PK context to use. It must have been initialized.
*
* \return Type name on success, or "invalid PK"
*/
@@ -423,9 +527,10 @@ const char * mbedtls_pk_get_name( const mbedtls_pk_context *ctx );
/**
* \brief Get the key type
*
- * \param ctx Context to use
+ * \param ctx The PK context to use. It must have been initialized.
*
- * \return Type on success, or MBEDTLS_PK_NONE
+ * \return Type on success.
+ * \return #MBEDTLS_PK_NONE for a context that has not been set up.
*/
mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx );
@@ -434,12 +539,22 @@ mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx );
/**
* \brief Parse a private key in PEM or DER format
*
- * \param ctx key to be initialized
- * \param key input buffer
- * \param keylen size of the buffer
- * (including the terminating null byte for PEM data)
- * \param pwd password for decryption (optional)
- * \param pwdlen size of the password
+ * \param ctx The PK context to fill. It must have been initialized
+ * but not set up.
+ * \param key Input buffer to parse.
+ * The buffer must contain the input exactly, with no
+ * extra trailing material. For PEM, the buffer must
+ * contain a null-terminated string.
+ * \param keylen Size of \b key in bytes.
+ * For PEM data, this includes the terminating null byte,
+ * so \p keylen must be equal to `strlen(key) + 1`.
+ * \param pwd Optional password for decryption.
+ * Pass \c NULL if expecting a non-encrypted key.
+ * Pass a string of \p pwdlen bytes if expecting an encrypted
+ * key; a non-encrypted key will also be accepted.
+ * The empty password is not supported.
+ * \param pwdlen Size of the password in bytes.
+ * Ignored if \p pwd is \c NULL.
*
* \note On entry, ctx must be empty, either freshly initialised
* with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a
@@ -457,10 +572,15 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *ctx,
/**
* \brief Parse a public key in PEM or DER format
*
- * \param ctx key to be initialized
- * \param key input buffer
- * \param keylen size of the buffer
- * (including the terminating null byte for PEM data)
+ * \param ctx The PK context to fill. It must have been initialized
+ * but not set up.
+ * \param key Input buffer to parse.
+ * The buffer must contain the input exactly, with no
+ * extra trailing material. For PEM, the buffer must
+ * contain a null-terminated string.
+ * \param keylen Size of \b key in bytes.
+ * For PEM data, this includes the terminating null byte,
+ * so \p keylen must be equal to `strlen(key) + 1`.
*
* \note On entry, ctx must be empty, either freshly initialised
* with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a
@@ -478,9 +598,14 @@ int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx,
/**
* \brief Load and parse a private key
*
- * \param ctx key to be initialized
+ * \param ctx The PK context to fill. It must have been initialized
+ * but not set up.
* \param path filename to read the private key from
- * \param password password to decrypt the file (can be NULL)
+ * \param password Optional password to decrypt the file.
+ * Pass \c NULL if expecting a non-encrypted key.
+ * Pass a null-terminated string if expecting an encrypted
+ * key; a non-encrypted key will also be accepted.
+ * The empty password is not supported.
*
* \note On entry, ctx must be empty, either freshly initialised
* with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a
@@ -497,7 +622,8 @@ int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx,
/**
* \brief Load and parse a public key
*
- * \param ctx key to be initialized
+ * \param ctx The PK context to fill. It must have been initialized
+ * but not set up.
* \param path filename to read the public key from
*
* \note On entry, ctx must be empty, either freshly initialised
@@ -520,7 +646,7 @@ int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path )
* return value to determine where you should start
* using the buffer
*
- * \param ctx private to write away
+ * \param ctx PK context which must contain a valid private key.
* \param buf buffer to write to
* \param size size of the buffer
*
@@ -535,7 +661,7 @@ int mbedtls_pk_write_key_der( mbedtls_pk_context *ctx, unsigned char *buf, size_
* return value to determine where you should start
* using the buffer
*
- * \param ctx public key to write away
+ * \param ctx PK context which must contain a valid public or private key.
* \param buf buffer to write to
* \param size size of the buffer
*
@@ -548,9 +674,10 @@ int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *ctx, unsigned char *buf, si
/**
* \brief Write a public key to a PEM string
*
- * \param ctx public key to write away
- * \param buf buffer to write to
- * \param size size of the buffer
+ * \param ctx PK context which must contain a valid public or private key.
+ * \param buf Buffer to write to. The output includes a
+ * terminating null byte.
+ * \param size Size of the buffer in bytes.
*
* \return 0 if successful, or a specific error code
*/
@@ -559,9 +686,10 @@ int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *ctx, unsigned char *buf, si
/**
* \brief Write a private key to a PKCS#1 or SEC1 PEM string
*
- * \param ctx private to write away
- * \param buf buffer to write to
- * \param size size of the buffer
+ * \param ctx PK context which must contain a valid private key.
+ * \param buf Buffer to write to. The output includes a
+ * terminating null byte.
+ * \param size Size of the buffer in bytes.
*
* \return 0 if successful, or a specific error code
*/
@@ -580,7 +708,8 @@ int mbedtls_pk_write_key_pem( mbedtls_pk_context *ctx, unsigned char *buf, size_
*
* \param p the position in the ASN.1 data
* \param end end of the buffer
- * \param pk the key to fill
+ * \param pk The PK context to fill. It must have been initialized
+ * but not set up.
*
* \return 0 if successful, or a specific PK error code
*/
@@ -595,7 +724,7 @@ int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end,
*
* \param p reference to current position pointer
* \param start start of the buffer (for bounds-checking)
- * \param key public key to write away
+ * \param key PK context which must contain a valid public or private key.
*
* \return the length written or a negative error code
*/
diff --git a/thirdparty/mbedtls/include/mbedtls/pk_internal.h b/thirdparty/mbedtls/include/mbedtls/pk_internal.h
index 3dae0fc5b2..48b7a5f7bf 100644
--- a/thirdparty/mbedtls/include/mbedtls/pk_internal.h
+++ b/thirdparty/mbedtls/include/mbedtls/pk_internal.h
@@ -59,6 +59,21 @@ struct mbedtls_pk_info_t
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ /** Verify signature (restartable) */
+ int (*verify_rs_func)( void *ctx, mbedtls_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ const unsigned char *sig, size_t sig_len,
+ void *rs_ctx );
+
+ /** Make signature (restartable) */
+ int (*sign_rs_func)( void *ctx, mbedtls_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ unsigned char *sig, size_t *sig_len,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng, void *rs_ctx );
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+
/** Decrypt message */
int (*decrypt_func)( void *ctx, const unsigned char *input, size_t ilen,
unsigned char *output, size_t *olen, size_t osize,
@@ -80,6 +95,14 @@ struct mbedtls_pk_info_t
/** Free the given context */
void (*ctx_free_func)( void *ctx );
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ /** Allocate the restart context */
+ void * (*rs_alloc_func)( void );
+
+ /** Free the restart context */
+ void (*rs_free_func)( void *rs_ctx );
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+
/** Interface with the debug module */
void (*debug_func)( const void *ctx, mbedtls_pk_debug_item *items );
diff --git a/thirdparty/mbedtls/include/mbedtls/pkcs11.h b/thirdparty/mbedtls/include/mbedtls/pkcs11.h
index bf65c55a79..02427ddc1e 100644
--- a/thirdparty/mbedtls/include/mbedtls/pkcs11.h
+++ b/thirdparty/mbedtls/include/mbedtls/pkcs11.h
@@ -50,7 +50,8 @@ extern "C" {
/**
* Context for PKCS #11 private keys.
*/
-typedef struct {
+typedef struct mbedtls_pkcs11_context
+{
pkcs11h_certificate_t pkcs11h_cert;
int len;
} mbedtls_pkcs11_context;
diff --git a/thirdparty/mbedtls/include/mbedtls/pkcs12.h b/thirdparty/mbedtls/include/mbedtls/pkcs12.h
index a621ef5b15..69f04177c8 100644
--- a/thirdparty/mbedtls/include/mbedtls/pkcs12.h
+++ b/thirdparty/mbedtls/include/mbedtls/pkcs12.h
@@ -46,6 +46,8 @@
extern "C" {
#endif
+#if defined(MBEDTLS_ASN1_PARSE_C)
+
/**
* \brief PKCS12 Password Based function (encryption / decryption)
* for pbeWithSHAAnd128BitRC4
@@ -87,6 +89,8 @@ int mbedtls_pkcs12_pbe( mbedtls_asn1_buf *pbe_params, int mode,
const unsigned char *input, size_t len,
unsigned char *output );
+#endif /* MBEDTLS_ASN1_PARSE_C */
+
/**
* \brief The PKCS#12 derivation function uses a password and a salt
* to produce pseudo-random bits for a particular "purpose".
diff --git a/thirdparty/mbedtls/include/mbedtls/pkcs5.h b/thirdparty/mbedtls/include/mbedtls/pkcs5.h
index 9a3c9fddcc..d4bb36dfae 100644
--- a/thirdparty/mbedtls/include/mbedtls/pkcs5.h
+++ b/thirdparty/mbedtls/include/mbedtls/pkcs5.h
@@ -44,6 +44,8 @@
extern "C" {
#endif
+#if defined(MBEDTLS_ASN1_PARSE_C)
+
/**
* \brief PKCS#5 PBES2 function
*
@@ -62,6 +64,8 @@ int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode,
const unsigned char *data, size_t datalen,
unsigned char *output );
+#endif /* MBEDTLS_ASN1_PARSE_C */
+
/**
* \brief PKCS#5 PBKDF2 using HMAC
*
diff --git a/thirdparty/mbedtls/include/mbedtls/platform.h b/thirdparty/mbedtls/include/mbedtls/platform.h
index 624cc642ac..89fe8a7b19 100644
--- a/thirdparty/mbedtls/include/mbedtls/platform.h
+++ b/thirdparty/mbedtls/include/mbedtls/platform.h
@@ -43,6 +43,9 @@
#include "platform_time.h"
#endif
+#define MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED -0x0070 /**< Hardware accelerator failed */
+#define MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED -0x0072 /**< The requested feature is not supported by the platform */
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -315,7 +318,8 @@ int mbedtls_platform_set_nv_seed(
* \note This structure may be used to assist platform-specific
* setup or teardown operations.
*/
-typedef struct {
+typedef struct mbedtls_platform_context
+{
char dummy; /**< A placeholder member, as empty structs are not portable. */
}
mbedtls_platform_context;
diff --git a/thirdparty/mbedtls/include/mbedtls/platform_util.h b/thirdparty/mbedtls/include/mbedtls/platform_util.h
index 84f0732eeb..b0e72ad149 100644
--- a/thirdparty/mbedtls/include/mbedtls/platform_util.h
+++ b/thirdparty/mbedtls/include/mbedtls/platform_util.h
@@ -25,12 +25,104 @@
#ifndef MBEDTLS_PLATFORM_UTIL_H
#define MBEDTLS_PLATFORM_UTIL_H
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
#include <stddef.h>
+#if defined(MBEDTLS_HAVE_TIME_DATE)
+#include "mbedtls/platform_time.h"
+#include <time.h>
+#endif /* MBEDTLS_HAVE_TIME_DATE */
#ifdef __cplusplus
extern "C" {
#endif
+#if defined(MBEDTLS_CHECK_PARAMS)
+
+#if defined(MBEDTLS_PARAM_FAILED)
+/** An alternative definition of MBEDTLS_PARAM_FAILED has been set in config.h.
+ *
+ * This flag can be used to check whether it is safe to assume that
+ * MBEDTLS_PARAM_FAILED() will expand to a call to mbedtls_param_failed().
+ */
+#define MBEDTLS_PARAM_FAILED_ALT
+#else /* MBEDTLS_PARAM_FAILED */
+#define MBEDTLS_PARAM_FAILED( cond ) \
+ mbedtls_param_failed( #cond, __FILE__, __LINE__ )
+
+/**
+ * \brief User supplied callback function for parameter validation failure.
+ * See #MBEDTLS_CHECK_PARAMS for context.
+ *
+ * This function will be called unless an alternative treatement
+ * is defined through the #MBEDTLS_PARAM_FAILED macro.
+ *
+ * This function can return, and the operation will be aborted, or
+ * alternatively, through use of setjmp()/longjmp() can resume
+ * execution in the application code.
+ *
+ * \param failure_condition The assertion that didn't hold.
+ * \param file The file where the assertion failed.
+ * \param line The line in the file where the assertion failed.
+ */
+void mbedtls_param_failed( const char *failure_condition,
+ const char *file,
+ int line );
+#endif /* MBEDTLS_PARAM_FAILED */
+
+/* Internal macro meant to be called only from within the library. */
+#define MBEDTLS_INTERNAL_VALIDATE_RET( cond, ret ) \
+ do { \
+ if( !(cond) ) \
+ { \
+ MBEDTLS_PARAM_FAILED( cond ); \
+ return( ret ); \
+ } \
+ } while( 0 )
+
+/* Internal macro meant to be called only from within the library. */
+#define MBEDTLS_INTERNAL_VALIDATE( cond ) \
+ do { \
+ if( !(cond) ) \
+ { \
+ MBEDTLS_PARAM_FAILED( cond ); \
+ return; \
+ } \
+ } while( 0 )
+
+#else /* MBEDTLS_CHECK_PARAMS */
+
+/* Internal macros meant to be called only from within the library. */
+#define MBEDTLS_INTERNAL_VALIDATE_RET( cond, ret ) do { } while( 0 )
+#define MBEDTLS_INTERNAL_VALIDATE( cond ) do { } while( 0 )
+
+#endif /* MBEDTLS_CHECK_PARAMS */
+
+/* Internal helper macros for deprecating API constants. */
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+#if defined(MBEDTLS_DEPRECATED_WARNING)
+/* Deliberately don't (yet) export MBEDTLS_DEPRECATED here
+ * to avoid conflict with other headers which define and use
+ * it, too. We might want to move all these definitions here at
+ * some point for uniformity. */
+#define MBEDTLS_DEPRECATED __attribute__((deprecated))
+MBEDTLS_DEPRECATED typedef char const * mbedtls_deprecated_string_constant_t;
+#define MBEDTLS_DEPRECATED_STRING_CONSTANT( VAL ) \
+ ( (mbedtls_deprecated_string_constant_t) ( VAL ) )
+MBEDTLS_DEPRECATED typedef int mbedtls_deprecated_numeric_constant_t;
+#define MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( VAL ) \
+ ( (mbedtls_deprecated_numeric_constant_t) ( VAL ) )
+#undef MBEDTLS_DEPRECATED
+#else /* MBEDTLS_DEPRECATED_WARNING */
+#define MBEDTLS_DEPRECATED_STRING_CONSTANT( VAL ) VAL
+#define MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( VAL ) VAL
+#endif /* MBEDTLS_DEPRECATED_WARNING */
+#endif /* MBEDTLS_DEPRECATED_REMOVED */
+
/**
* \brief Securely zeroize a buffer
*
@@ -55,6 +147,37 @@ extern "C" {
*/
void mbedtls_platform_zeroize( void *buf, size_t len );
+#if defined(MBEDTLS_HAVE_TIME_DATE)
+/**
+ * \brief Platform-specific implementation of gmtime_r()
+ *
+ * The function is a thread-safe abstraction that behaves
+ * similarly to the gmtime_r() function from Unix/POSIX.
+ *
+ * Mbed TLS will try to identify the underlying platform and
+ * make use of an appropriate underlying implementation (e.g.
+ * gmtime_r() for POSIX and gmtime_s() for Windows). If this is
+ * not possible, then gmtime() will be used. In this case, calls
+ * from the library to gmtime() will be guarded by the mutex
+ * mbedtls_threading_gmtime_mutex if MBEDTLS_THREADING_C is
+ * enabled. It is recommended that calls from outside the library
+ * are also guarded by this mutex.
+ *
+ * If MBEDTLS_PLATFORM_GMTIME_R_ALT is defined, then Mbed TLS will
+ * unconditionally use the alternative implementation for
+ * mbedtls_platform_gmtime_r() supplied by the user at compile time.
+ *
+ * \param tt Pointer to an object containing time (in seconds) since the
+ * epoch to be converted
+ * \param tm_buf Pointer to an object where the results will be stored
+ *
+ * \return Pointer to an object of type struct tm on success, otherwise
+ * NULL
+ */
+struct tm *mbedtls_platform_gmtime_r( const mbedtls_time_t *tt,
+ struct tm *tm_buf );
+#endif /* MBEDTLS_HAVE_TIME_DATE */
+
#ifdef __cplusplus
}
#endif
diff --git a/thirdparty/mbedtls/include/mbedtls/poly1305.h b/thirdparty/mbedtls/include/mbedtls/poly1305.h
index 54b50abc25..05866a2da6 100644
--- a/thirdparty/mbedtls/include/mbedtls/poly1305.h
+++ b/thirdparty/mbedtls/include/mbedtls/poly1305.h
@@ -43,7 +43,13 @@
#include <stddef.h>
#define MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA -0x0057 /**< Invalid input parameter(s). */
+
+/* MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE is deprecated and should not be
+ * used. */
#define MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE -0x0059 /**< Feature not available. For example, s part of the API is not implemented. */
+
+/* MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED is deprecated and should not be used.
+ */
#define MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED -0x005B /**< Poly1305 hardware accelerator failed. */
#ifdef __cplusplus
@@ -52,7 +58,7 @@ extern "C" {
#if !defined(MBEDTLS_POLY1305_ALT)
-typedef struct
+typedef struct mbedtls_poly1305_context
{
uint32_t r[4]; /** The value for 'r' (low 128 bits of the key). */
uint32_t s[4]; /** The value for 's' (high 128 bits of the key). */
@@ -78,14 +84,18 @@ mbedtls_poly1305_context;
* \c mbedtls_poly1305_finish(), then finally
* \c mbedtls_poly1305_free().
*
- * \param ctx The Poly1305 context to initialize.
+ * \param ctx The Poly1305 context to initialize. This must
+ * not be \c NULL.
*/
void mbedtls_poly1305_init( mbedtls_poly1305_context *ctx );
/**
- * \brief This function releases and clears the specified Poly1305 context.
+ * \brief This function releases and clears the specified
+ * Poly1305 context.
*
- * \param ctx The Poly1305 context to clear.
+ * \param ctx The Poly1305 context to clear. This may be \c NULL, in which
+ * case this function is a no-op. If it is not \c NULL, it must
+ * point to an initialized Poly1305 context.
*/
void mbedtls_poly1305_free( mbedtls_poly1305_context *ctx );
@@ -96,11 +106,11 @@ void mbedtls_poly1305_free( mbedtls_poly1305_context *ctx );
* invocation of Poly1305.
*
* \param ctx The Poly1305 context to which the key should be bound.
- * \param key The buffer containing the 256-bit key.
+ * This must be initialized.
+ * \param key The buffer containing the \c 32 Byte (\c 256 Bit) key.
*
* \return \c 0 on success.
- * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA
- * if ctx or key are NULL.
+ * \return A negative error code on failure.
*/
int mbedtls_poly1305_starts( mbedtls_poly1305_context *ctx,
const unsigned char key[32] );
@@ -114,13 +124,14 @@ int mbedtls_poly1305_starts( mbedtls_poly1305_context *ctx,
* It can be called repeatedly to process a stream of data.
*
* \param ctx The Poly1305 context to use for the Poly1305 operation.
- * \param ilen The length of the input data (in bytes). Any value is accepted.
+ * This must be initialized and bound to a key.
+ * \param ilen The length of the input data in Bytes.
+ * Any value is accepted.
* \param input The buffer holding the input data.
- * This pointer can be NULL if ilen == 0.
+ * This pointer can be \c NULL if `ilen == 0`.
*
* \return \c 0 on success.
- * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA
- * if ctx or input are NULL.
+ * \return A negative error code on failure.
*/
int mbedtls_poly1305_update( mbedtls_poly1305_context *ctx,
const unsigned char *input,
@@ -131,12 +142,12 @@ int mbedtls_poly1305_update( mbedtls_poly1305_context *ctx,
* Authentication Code (MAC).
*
* \param ctx The Poly1305 context to use for the Poly1305 operation.
- * \param mac The buffer to where the MAC is written. Must be big enough
- * to hold the 16-byte MAC.
+ * This must be initialized and bound to a key.
+ * \param mac The buffer to where the MAC is written. This must
+ * be a writable buffer of length \c 16 Bytes.
*
* \return \c 0 on success.
- * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA
- * if ctx or mac are NULL.
+ * \return A negative error code on failure.
*/
int mbedtls_poly1305_finish( mbedtls_poly1305_context *ctx,
unsigned char mac[16] );
@@ -148,16 +159,16 @@ int mbedtls_poly1305_finish( mbedtls_poly1305_context *ctx,
* \warning The key must be unique and unpredictable for each
* invocation of Poly1305.
*
- * \param key The buffer containing the 256-bit key.
- * \param ilen The length of the input data (in bytes). Any value is accepted.
+ * \param key The buffer containing the \c 32 Byte (\c 256 Bit) key.
+ * \param ilen The length of the input data in Bytes.
+ * Any value is accepted.
* \param input The buffer holding the input data.
- * This pointer can be NULL if ilen == 0.
- * \param mac The buffer to where the MAC is written. Must be big enough
- * to hold the 16-byte MAC.
+ * This pointer can be \c NULL if `ilen == 0`.
+ * \param mac The buffer to where the MAC is written. This must be
+ * a writable buffer of length \c 16 Bytes.
*
* \return \c 0 on success.
- * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA
- * if key, input, or mac are NULL.
+ * \return A negative error code on failure.
*/
int mbedtls_poly1305_mac( const unsigned char key[32],
const unsigned char *input,
diff --git a/thirdparty/mbedtls/include/mbedtls/ripemd160.h b/thirdparty/mbedtls/include/mbedtls/ripemd160.h
index a0dac0c360..c74b7d2c6c 100644
--- a/thirdparty/mbedtls/include/mbedtls/ripemd160.h
+++ b/thirdparty/mbedtls/include/mbedtls/ripemd160.h
@@ -33,6 +33,8 @@
#include <stddef.h>
#include <stdint.h>
+/* MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED is deprecated and should not be used.
+ */
#define MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED -0x0031 /**< RIPEMD160 hardware accelerator failed */
#ifdef __cplusplus
@@ -46,7 +48,7 @@ extern "C" {
/**
* \brief RIPEMD-160 context structure
*/
-typedef struct
+typedef struct mbedtls_ripemd160_context
{
uint32_t total[2]; /*!< number of bytes processed */
uint32_t state[5]; /*!< intermediate digest state */
diff --git a/thirdparty/mbedtls/include/mbedtls/rsa.h b/thirdparty/mbedtls/include/mbedtls/rsa.h
index 19eb2ee74c..ed65a34452 100644
--- a/thirdparty/mbedtls/include/mbedtls/rsa.h
+++ b/thirdparty/mbedtls/include/mbedtls/rsa.h
@@ -55,7 +55,12 @@
#define MBEDTLS_ERR_RSA_VERIFY_FAILED -0x4380 /**< The PKCS#1 verification failed. */
#define MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE -0x4400 /**< The output buffer for decryption is not large enough. */
#define MBEDTLS_ERR_RSA_RNG_FAILED -0x4480 /**< The random generator failed to generate non-zeros. */
+
+/* MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION is deprecated and should not be used.
+ */
#define MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION -0x4500 /**< The implementation does not offer the requested operation, for example, because of security violations or lack of functionality. */
+
+/* MBEDTLS_ERR_RSA_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_RSA_HW_ACCEL_FAILED -0x4580 /**< RSA hardware accelerator failed. */
/*
@@ -92,7 +97,7 @@ extern "C" {
* is deprecated. All manipulation should instead be done through
* the public interface functions.
*/
-typedef struct
+typedef struct mbedtls_rsa_context
{
int ver; /*!< Always 0.*/
size_t len; /*!< The size of \p N in Bytes. */
@@ -153,15 +158,16 @@ mbedtls_rsa_context;
* making signatures, but can be overriden for verifying them.
* If set to #MBEDTLS_MD_NONE, it is always overriden.
*
- * \param ctx The RSA context to initialize.
- * \param padding Selects padding mode: #MBEDTLS_RSA_PKCS_V15 or
- * #MBEDTLS_RSA_PKCS_V21.
- * \param hash_id The hash identifier of #mbedtls_md_type_t type, if
- * \p padding is #MBEDTLS_RSA_PKCS_V21.
+ * \param ctx The RSA context to initialize. This must not be \c NULL.
+ * \param padding The padding mode to use. This must be either
+ * #MBEDTLS_RSA_PKCS_V15 or #MBEDTLS_RSA_PKCS_V21.
+ * \param hash_id The hash identifier of ::mbedtls_md_type_t type, if
+ * \p padding is #MBEDTLS_RSA_PKCS_V21. It is unused
+ * otherwise.
*/
void mbedtls_rsa_init( mbedtls_rsa_context *ctx,
int padding,
- int hash_id);
+ int hash_id );
/**
* \brief This function imports a set of core parameters into an
@@ -183,11 +189,11 @@ void mbedtls_rsa_init( mbedtls_rsa_context *ctx,
* for the lifetime of the RSA context being set up.
*
* \param ctx The initialized RSA context to store the parameters in.
- * \param N The RSA modulus, or NULL.
- * \param P The first prime factor of \p N, or NULL.
- * \param Q The second prime factor of \p N, or NULL.
- * \param D The private exponent, or NULL.
- * \param E The public exponent, or NULL.
+ * \param N The RSA modulus. This may be \c NULL.
+ * \param P The first prime factor of \p N. This may be \c NULL.
+ * \param Q The second prime factor of \p N. This may be \c NULL.
+ * \param D The private exponent. This may be \c NULL.
+ * \param E The public exponent. This may be \c NULL.
*
* \return \c 0 on success.
* \return A non-zero error code on failure.
@@ -217,16 +223,16 @@ int mbedtls_rsa_import( mbedtls_rsa_context *ctx,
* for the lifetime of the RSA context being set up.
*
* \param ctx The initialized RSA context to store the parameters in.
- * \param N The RSA modulus, or NULL.
- * \param N_len The Byte length of \p N, ignored if \p N == NULL.
- * \param P The first prime factor of \p N, or NULL.
- * \param P_len The Byte length of \p P, ignored if \p P == NULL.
- * \param Q The second prime factor of \p N, or NULL.
- * \param Q_len The Byte length of \p Q, ignored if \p Q == NULL.
- * \param D The private exponent, or NULL.
- * \param D_len The Byte length of \p D, ignored if \p D == NULL.
- * \param E The public exponent, or NULL.
- * \param E_len The Byte length of \p E, ignored if \p E == NULL.
+ * \param N The RSA modulus. This may be \c NULL.
+ * \param N_len The Byte length of \p N; it is ignored if \p N == NULL.
+ * \param P The first prime factor of \p N. This may be \c NULL.
+ * \param P_len The Byte length of \p P; it ns ignored if \p P == NULL.
+ * \param Q The second prime factor of \p N. This may be \c NULL.
+ * \param Q_len The Byte length of \p Q; it is ignored if \p Q == NULL.
+ * \param D The private exponent. This may be \c NULL.
+ * \param D_len The Byte length of \p D; it is ignored if \p D == NULL.
+ * \param E The public exponent. This may be \c NULL.
+ * \param E_len The Byte length of \p E; it is ignored if \p E == NULL.
*
* \return \c 0 on success.
* \return A non-zero error code on failure.
@@ -281,7 +287,7 @@ int mbedtls_rsa_complete( mbedtls_rsa_context *ctx );
* zero Bytes.
*
* Possible reasons for returning
- * #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION:<ul>
+ * #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED:<ul>
* <li>An alternative RSA implementation is in use, which
* stores the key externally, and either cannot or should
* not export it into RAM.</li>
@@ -294,14 +300,19 @@ int mbedtls_rsa_complete( mbedtls_rsa_context *ctx );
* the RSA context stays intact and remains usable.
*
* \param ctx The initialized RSA context.
- * \param N The MPI to hold the RSA modulus, or NULL.
- * \param P The MPI to hold the first prime factor of \p N, or NULL.
- * \param Q The MPI to hold the second prime factor of \p N, or NULL.
- * \param D The MPI to hold the private exponent, or NULL.
- * \param E The MPI to hold the public exponent, or NULL.
+ * \param N The MPI to hold the RSA modulus.
+ * This may be \c NULL if this field need not be exported.
+ * \param P The MPI to hold the first prime factor of \p N.
+ * This may be \c NULL if this field need not be exported.
+ * \param Q The MPI to hold the second prime factor of \p N.
+ * This may be \c NULL if this field need not be exported.
+ * \param D The MPI to hold the private exponent.
+ * This may be \c NULL if this field need not be exported.
+ * \param E The MPI to hold the public exponent.
+ * This may be \c NULL if this field need not be exported.
*
* \return \c 0 on success.
- * \return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION if exporting the
+ * \return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED if exporting the
* requested parameters cannot be done due to missing
* functionality or because of security policies.
* \return A non-zero return code on any other failure.
@@ -321,7 +332,7 @@ int mbedtls_rsa_export( const mbedtls_rsa_context *ctx,
* zero Bytes.
*
* Possible reasons for returning
- * #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION:<ul>
+ * #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED:<ul>
* <li>An alternative RSA implementation is in use, which
* stores the key externally, and either cannot or should
* not export it into RAM.</li>
@@ -336,21 +347,24 @@ int mbedtls_rsa_export( const mbedtls_rsa_context *ctx,
* buffer pointers are NULL.
*
* \param ctx The initialized RSA context.
- * \param N The Byte array to store the RSA modulus, or NULL.
+ * \param N The Byte array to store the RSA modulus,
+ * or \c NULL if this field need not be exported.
* \param N_len The size of the buffer for the modulus.
- * \param P The Byte array to hold the first prime factor of \p N, or
- * NULL.
+ * \param P The Byte array to hold the first prime factor of \p N,
+ * or \c NULL if this field need not be exported.
* \param P_len The size of the buffer for the first prime factor.
- * \param Q The Byte array to hold the second prime factor of \p N, or
- * NULL.
+ * \param Q The Byte array to hold the second prime factor of \p N,
+ * or \c NULL if this field need not be exported.
* \param Q_len The size of the buffer for the second prime factor.
- * \param D The Byte array to hold the private exponent, or NULL.
+ * \param D The Byte array to hold the private exponent,
+ * or \c NULL if this field need not be exported.
* \param D_len The size of the buffer for the private exponent.
- * \param E The Byte array to hold the public exponent, or NULL.
+ * \param E The Byte array to hold the public exponent,
+ * or \c NULL if this field need not be exported.
* \param E_len The size of the buffer for the public exponent.
*
* \return \c 0 on success.
- * \return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION if exporting the
+ * \return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED if exporting the
* requested parameters cannot be done due to missing
* functionality or because of security policies.
* \return A non-zero return code on any other failure.
@@ -370,9 +384,12 @@ int mbedtls_rsa_export_raw( const mbedtls_rsa_context *ctx,
* mbedtls_rsa_deduce_opt().
*
* \param ctx The initialized RSA context.
- * \param DP The MPI to hold D modulo P-1, or NULL.
- * \param DQ The MPI to hold D modulo Q-1, or NULL.
- * \param QP The MPI to hold modular inverse of Q modulo P, or NULL.
+ * \param DP The MPI to hold \c D modulo `P-1`,
+ * or \c NULL if it need not be exported.
+ * \param DQ The MPI to hold \c D modulo `Q-1`,
+ * or \c NULL if it need not be exported.
+ * \param QP The MPI to hold modular inverse of \c Q modulo \c P,
+ * or \c NULL if it need not be exported.
*
* \return \c 0 on success.
* \return A non-zero error code on failure.
@@ -385,13 +402,13 @@ int mbedtls_rsa_export_crt( const mbedtls_rsa_context *ctx,
* \brief This function sets padding for an already initialized RSA
* context. See mbedtls_rsa_init() for details.
*
- * \param ctx The RSA context to be set.
- * \param padding Selects padding mode: #MBEDTLS_RSA_PKCS_V15 or
- * #MBEDTLS_RSA_PKCS_V21.
+ * \param ctx The initialized RSA context to be configured.
+ * \param padding The padding mode to use. This must be either
+ * #MBEDTLS_RSA_PKCS_V15 or #MBEDTLS_RSA_PKCS_V21.
* \param hash_id The #MBEDTLS_RSA_PKCS_V21 hash identifier.
*/
void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding,
- int hash_id);
+ int hash_id );
/**
* \brief This function retrieves the length of RSA modulus in Bytes.
@@ -409,11 +426,14 @@ size_t mbedtls_rsa_get_len( const mbedtls_rsa_context *ctx );
* \note mbedtls_rsa_init() must be called before this function,
* to set up the RSA context.
*
- * \param ctx The RSA context used to hold the key.
- * \param f_rng The RNG function.
- * \param p_rng The RNG context.
+ * \param ctx The initialized RSA context used to hold the key.
+ * \param f_rng The RNG function to be used for key generation.
+ * This must not be \c NULL.
+ * \param p_rng The RNG context to be passed to \p f_rng.
+ * This may be \c NULL if \p f_rng doesn't need a context.
* \param nbits The size of the public key in bits.
- * \param exponent The public exponent. For example, 65537.
+ * \param exponent The public exponent to use. For example, \c 65537.
+ * This must be odd and greater than \c 1.
*
* \return \c 0 on success.
* \return An \c MBEDTLS_ERR_RSA_XXX error code on failure.
@@ -431,7 +451,7 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx,
* enough information is present to perform an RSA public key
* operation using mbedtls_rsa_public().
*
- * \param ctx The RSA context to check.
+ * \param ctx The initialized RSA context to check.
*
* \return \c 0 on success.
* \return An \c MBEDTLS_ERR_RSA_XXX error code on failure.
@@ -470,7 +490,7 @@ int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx );
* parameters, which goes beyond what is effectively checkable
* by the library.</li></ul>
*
- * \param ctx The RSA context to check.
+ * \param ctx The initialized RSA context to check.
*
* \return \c 0 on success.
* \return An \c MBEDTLS_ERR_RSA_XXX error code on failure.
@@ -482,8 +502,8 @@ int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx );
*
* It checks each of the contexts, and makes sure they match.
*
- * \param pub The RSA context holding the public key.
- * \param prv The RSA context holding the private key.
+ * \param pub The initialized RSA context holding the public key.
+ * \param prv The initialized RSA context holding the private key.
*
* \return \c 0 on success.
* \return An \c MBEDTLS_ERR_RSA_XXX error code on failure.
@@ -494,18 +514,19 @@ int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub,
/**
* \brief This function performs an RSA public key operation.
*
+ * \param ctx The initialized RSA context to use.
+ * \param input The input buffer. This must be a readable buffer
+ * of length \c ctx->len Bytes. For example, \c 256 Bytes
+ * for an 2048-bit RSA modulus.
+ * \param output The output buffer. This must be a writable buffer
+ * of length \c ctx->len Bytes. For example, \c 256 Bytes
+ * for an 2048-bit RSA modulus.
+ *
* \note This function does not handle message padding.
*
* \note Make sure to set \p input[0] = 0 or ensure that
* input is smaller than \p N.
*
- * \note The input and output buffers must be large
- * enough. For example, 128 Bytes if RSA-1024 is used.
- *
- * \param ctx The RSA context.
- * \param input The input buffer.
- * \param output The output buffer.
- *
* \return \c 0 on success.
* \return An \c MBEDTLS_ERR_RSA_XXX error code on failure.
*/
@@ -516,9 +537,6 @@ int mbedtls_rsa_public( mbedtls_rsa_context *ctx,
/**
* \brief This function performs an RSA private key operation.
*
- * \note The input and output buffers must be large
- * enough. For example, 128 Bytes if RSA-1024 is used.
- *
* \note Blinding is used if and only if a PRNG is provided.
*
* \note If blinding is used, both the base of exponentation
@@ -530,11 +548,18 @@ int mbedtls_rsa_public( mbedtls_rsa_context *ctx,
* Future versions of the library may enforce the presence
* of a PRNG.
*
- * \param ctx The RSA context.
- * \param f_rng The RNG function. Needed for blinding.
- * \param p_rng The RNG context.
- * \param input The input buffer.
- * \param output The output buffer.
+ * \param ctx The initialized RSA context to use.
+ * \param f_rng The RNG function, used for blinding. It is discouraged
+ * and deprecated to pass \c NULL here, in which case
+ * blinding will be omitted.
+ * \param p_rng The RNG context to pass to \p f_rng. This may be \c NULL
+ * if \p f_rng is \c NULL or if \p f_rng doesn't need a context.
+ * \param input The input buffer. This must be a readable buffer
+ * of length \c ctx->len Bytes. For example, \c 256 Bytes
+ * for an 2048-bit RSA modulus.
+ * \param output The output buffer. This must be a writable buffer
+ * of length \c ctx->len Bytes. For example, \c 256 Bytes
+ * for an 2048-bit RSA modulus.
*
* \return \c 0 on success.
* \return An \c MBEDTLS_ERR_RSA_XXX error code on failure.
@@ -553,9 +578,6 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx,
* It is the generic wrapper for performing a PKCS#1 encryption
* operation using the \p mode from the context.
*
- * \note The input and output buffers must be as large as the size
- * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used.
- *
* \deprecated It is deprecated and discouraged to call this function
* in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library
* are likely to remove the \p mode argument and have it
@@ -563,16 +585,26 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx,
*
* \note Alternative implementations of RSA need not support
* mode being set to #MBEDTLS_RSA_PRIVATE and might instead
- * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION.
- *
- * \param ctx The RSA context.
- * \param f_rng The RNG function. Needed for padding, PKCS#1 v2.1
- * encoding, and #MBEDTLS_RSA_PRIVATE.
- * \param p_rng The RNG context.
- * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE.
- * \param ilen The length of the plaintext.
- * \param input The buffer holding the data to encrypt.
- * \param output The buffer used to hold the ciphertext.
+ * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED.
+ *
+ * \param ctx The initialized RSA context to use.
+ * \param f_rng The RNG to use. It is mandatory for PKCS#1 v2.1 padding
+ * encoding, and for PKCS#1 v1.5 padding encoding when used
+ * with \p mode set to #MBEDTLS_RSA_PUBLIC. For PKCS#1 v1.5
+ * padding encoding and \p mode set to #MBEDTLS_RSA_PRIVATE,
+ * it is used for blinding and should be provided in this
+ * case; see mbedtls_rsa_private() for more.
+ * \param p_rng The RNG context to be passed to \p f_rng. May be
+ * \c NULL if \p f_rng is \c NULL or if \p f_rng doesn't
+ * need a context argument.
+ * \param mode The mode of operation. This must be either
+ * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated).
+ * \param ilen The length of the plaintext in Bytes.
+ * \param input The input data to encrypt. This must be a readable
+ * buffer of size \p ilen Bytes. This must not be \c NULL.
+ * \param output The output buffer. This must be a writable buffer
+ * of length \c ctx->len Bytes. For example, \c 256 Bytes
+ * for an 2048-bit RSA modulus.
*
* \return \c 0 on success.
* \return An \c MBEDTLS_ERR_RSA_XXX error code on failure.
@@ -588,9 +620,6 @@ int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx,
* \brief This function performs a PKCS#1 v1.5 encryption operation
* (RSAES-PKCS1-v1_5-ENCRYPT).
*
- * \note The output buffer must be as large as the size
- * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used.
- *
* \deprecated It is deprecated and discouraged to call this function
* in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library
* are likely to remove the \p mode argument and have it
@@ -598,16 +627,24 @@ int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx,
*
* \note Alternative implementations of RSA need not support
* mode being set to #MBEDTLS_RSA_PRIVATE and might instead
- * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION.
- *
- * \param ctx The RSA context.
- * \param f_rng The RNG function. Needed for padding and
- * #MBEDTLS_RSA_PRIVATE.
- * \param p_rng The RNG context.
- * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE.
- * \param ilen The length of the plaintext.
- * \param input The buffer holding the data to encrypt.
- * \param output The buffer used to hold the ciphertext.
+ * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED.
+ *
+ * \param ctx The initialized RSA context to use.
+ * \param f_rng The RNG function to use. It is needed for padding generation
+ * if \p mode is #MBEDTLS_RSA_PUBLIC. If \p mode is
+ * #MBEDTLS_RSA_PRIVATE (discouraged), it is used for
+ * blinding and should be provided; see mbedtls_rsa_private().
+ * \param p_rng The RNG context to be passed to \p f_rng. This may
+ * be \c NULL if \p f_rng is \c NULL or if \p f_rng
+ * doesn't need a context argument.
+ * \param mode The mode of operation. This must be either
+ * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated).
+ * \param ilen The length of the plaintext in Bytes.
+ * \param input The input data to encrypt. This must be a readable
+ * buffer of size \p ilen Bytes. This must not be \c NULL.
+ * \param output The output buffer. This must be a writable buffer
+ * of length \c ctx->len Bytes. For example, \c 256 Bytes
+ * for an 2048-bit RSA modulus.
*
* \return \c 0 on success.
* \return An \c MBEDTLS_ERR_RSA_XXX error code on failure.
@@ -633,18 +670,25 @@ int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx,
*
* \note Alternative implementations of RSA need not support
* mode being set to #MBEDTLS_RSA_PRIVATE and might instead
- * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION.
- *
- * \param ctx The RSA context.
- * \param f_rng The RNG function. Needed for padding and PKCS#1 v2.1
- * encoding and #MBEDTLS_RSA_PRIVATE.
- * \param p_rng The RNG context.
- * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE.
+ * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED.
+ *
+ * \param ctx The initnialized RSA context to use.
+ * \param f_rng The RNG function to use. This is needed for padding
+ * generation and must be provided.
+ * \param p_rng The RNG context to be passed to \p f_rng. This may
+ * be \c NULL if \p f_rng doesn't need a context argument.
+ * \param mode The mode of operation. This must be either
+ * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated).
* \param label The buffer holding the custom label to use.
- * \param label_len The length of the label.
- * \param ilen The length of the plaintext.
- * \param input The buffer holding the data to encrypt.
- * \param output The buffer used to hold the ciphertext.
+ * This must be a readable buffer of length \p label_len
+ * Bytes. It may be \c NULL if \p label_len is \c 0.
+ * \param label_len The length of the label in Bytes.
+ * \param ilen The length of the plaintext buffer \p input in Bytes.
+ * \param input The input data to encrypt. This must be a readable
+ * buffer of size \p ilen Bytes. This must not be \c NULL.
+ * \param output The output buffer. This must be a writable buffer
+ * of length \c ctx->len Bytes. For example, \c 256 Bytes
+ * for an 2048-bit RSA modulus.
*
* \return \c 0 on success.
* \return An \c MBEDTLS_ERR_RSA_XXX error code on failure.
@@ -672,9 +716,6 @@ int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx,
* hold the decryption of the particular ciphertext provided,
* the function returns \c MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE.
*
- * \note The input buffer must be as large as the size
- * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used.
- *
* \deprecated It is deprecated and discouraged to call this function
* in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library
* are likely to remove the \p mode argument and have it
@@ -682,16 +723,25 @@ int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx,
*
* \note Alternative implementations of RSA need not support
* mode being set to #MBEDTLS_RSA_PUBLIC and might instead
- * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION.
- *
- * \param ctx The RSA context.
- * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE.
- * \param p_rng The RNG context.
- * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE.
- * \param olen The length of the plaintext.
- * \param input The buffer holding the encrypted data.
- * \param output The buffer used to hold the plaintext.
- * \param output_max_len The maximum length of the output buffer.
+ * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED.
+ *
+ * \param ctx The initialized RSA context to use.
+ * \param f_rng The RNG function. If \p mode is #MBEDTLS_RSA_PRIVATE,
+ * this is used for blinding and should be provided; see
+ * mbedtls_rsa_private() for more. If \p mode is
+ * #MBEDTLS_RSA_PUBLIC, it is ignored.
+ * \param p_rng The RNG context to be passed to \p f_rng. This may be
+ * \c NULL if \p f_rng is \c NULL or doesn't need a context.
+ * \param mode The mode of operation. This must be either
+ * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated).
+ * \param olen The address at which to store the length of
+ * the plaintext. This must not be \c NULL.
+ * \param input The ciphertext buffer. This must be a readable buffer
+ * of length \c ctx->len Bytes. For example, \c 256 Bytes
+ * for an 2048-bit RSA modulus.
+ * \param output The buffer used to hold the plaintext. This must
+ * be a writable buffer of length \p output_max_len Bytes.
+ * \param output_max_len The length in Bytes of the output buffer \p output.
*
* \return \c 0 on success.
* \return An \c MBEDTLS_ERR_RSA_XXX error code on failure.
@@ -715,9 +765,6 @@ int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx,
* hold the decryption of the particular ciphertext provided,
* the function returns #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE.
*
- * \note The input buffer must be as large as the size
- * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used.
- *
* \deprecated It is deprecated and discouraged to call this function
* in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library
* are likely to remove the \p mode argument and have it
@@ -725,16 +772,25 @@ int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx,
*
* \note Alternative implementations of RSA need not support
* mode being set to #MBEDTLS_RSA_PUBLIC and might instead
- * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION.
- *
- * \param ctx The RSA context.
- * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE.
- * \param p_rng The RNG context.
- * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE.
- * \param olen The length of the plaintext.
- * \param input The buffer holding the encrypted data.
- * \param output The buffer to hold the plaintext.
- * \param output_max_len The maximum length of the output buffer.
+ * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED.
+ *
+ * \param ctx The initialized RSA context to use.
+ * \param f_rng The RNG function. If \p mode is #MBEDTLS_RSA_PRIVATE,
+ * this is used for blinding and should be provided; see
+ * mbedtls_rsa_private() for more. If \p mode is
+ * #MBEDTLS_RSA_PUBLIC, it is ignored.
+ * \param p_rng The RNG context to be passed to \p f_rng. This may be
+ * \c NULL if \p f_rng is \c NULL or doesn't need a context.
+ * \param mode The mode of operation. This must be either
+ * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated).
+ * \param olen The address at which to store the length of
+ * the plaintext. This must not be \c NULL.
+ * \param input The ciphertext buffer. This must be a readable buffer
+ * of length \c ctx->len Bytes. For example, \c 256 Bytes
+ * for an 2048-bit RSA modulus.
+ * \param output The buffer used to hold the plaintext. This must
+ * be a writable buffer of length \p output_max_len Bytes.
+ * \param output_max_len The length in Bytes of the output buffer \p output.
*
* \return \c 0 on success.
* \return An \c MBEDTLS_ERR_RSA_XXX error code on failure.
@@ -760,9 +816,6 @@ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx,
* ciphertext provided, the function returns
* #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE.
*
- * \note The input buffer must be as large as the size
- * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used.
- *
* \deprecated It is deprecated and discouraged to call this function
* in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library
* are likely to remove the \p mode argument and have it
@@ -770,18 +823,29 @@ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx,
*
* \note Alternative implementations of RSA need not support
* mode being set to #MBEDTLS_RSA_PUBLIC and might instead
- * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION.
- *
- * \param ctx The RSA context.
- * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE.
- * \param p_rng The RNG context.
- * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE.
+ * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED.
+ *
+ * \param ctx The initialized RSA context to use.
+ * \param f_rng The RNG function. If \p mode is #MBEDTLS_RSA_PRIVATE,
+ * this is used for blinding and should be provided; see
+ * mbedtls_rsa_private() for more. If \p mode is
+ * #MBEDTLS_RSA_PUBLIC, it is ignored.
+ * \param p_rng The RNG context to be passed to \p f_rng. This may be
+ * \c NULL if \p f_rng is \c NULL or doesn't need a context.
+ * \param mode The mode of operation. This must be either
+ * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated).
* \param label The buffer holding the custom label to use.
- * \param label_len The length of the label.
- * \param olen The length of the plaintext.
- * \param input The buffer holding the encrypted data.
- * \param output The buffer to hold the plaintext.
- * \param output_max_len The maximum length of the output buffer.
+ * This must be a readable buffer of length \p label_len
+ * Bytes. It may be \c NULL if \p label_len is \c 0.
+ * \param label_len The length of the label in Bytes.
+ * \param olen The address at which to store the length of
+ * the plaintext. This must not be \c NULL.
+ * \param input The ciphertext buffer. This must be a readable buffer
+ * of length \c ctx->len Bytes. For example, \c 256 Bytes
+ * for an 2048-bit RSA modulus.
+ * \param output The buffer used to hold the plaintext. This must
+ * be a writable buffer of length \p output_max_len Bytes.
+ * \param output_max_len The length in Bytes of the output buffer \p output.
*
* \return \c 0 on success.
* \return An \c MBEDTLS_ERR_RSA_XXX error code on failure.
@@ -817,18 +881,30 @@ int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx,
*
* \note Alternative implementations of RSA need not support
* mode being set to #MBEDTLS_RSA_PUBLIC and might instead
- * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION.
- *
- * \param ctx The RSA context.
- * \param f_rng The RNG function. Needed for PKCS#1 v2.1 encoding and for
- * #MBEDTLS_RSA_PRIVATE.
- * \param p_rng The RNG context.
- * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE.
+ * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED.
+ *
+ * \param ctx The initialized RSA context to use.
+ * \param f_rng The RNG function to use. If the padding mode is PKCS#1 v2.1,
+ * this must be provided. If the padding mode is PKCS#1 v1.5 and
+ * \p mode is #MBEDTLS_RSA_PRIVATE, it is used for blinding
+ * and should be provided; see mbedtls_rsa_private() for more
+ * more. It is ignored otherwise.
+ * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL
+ * if \p f_rng is \c NULL or doesn't need a context argument.
+ * \param mode The mode of operation. This must be either
+ * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated).
* \param md_alg The message-digest algorithm used to hash the original data.
* Use #MBEDTLS_MD_NONE for signing raw data.
- * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE.
- * \param hash The buffer holding the message digest.
- * \param sig The buffer to hold the ciphertext.
+ * \param hashlen The length of the message digest.
+ * Ths is only used if \p md_alg is #MBEDTLS_MD_NONE.
+ * \param hash The buffer holding the message digest or raw data.
+ * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable
+ * buffer of length \p hashlen Bytes. If \p md_alg is not
+ * #MBEDTLS_MD_NONE, it must be a readable buffer of length
+ * the size of the hash corresponding to \p md_alg.
+ * \param sig The buffer to hold the signature. This must be a writable
+ * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes
+ * for an 2048-bit RSA modulus.
*
* \return \c 0 if the signing operation was successful.
* \return An \c MBEDTLS_ERR_RSA_XXX error code on failure.
@@ -846,9 +922,6 @@ int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx,
* \brief This function performs a PKCS#1 v1.5 signature
* operation (RSASSA-PKCS1-v1_5-SIGN).
*
- * \note The \p sig buffer must be as large as the size
- * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used.
- *
* \deprecated It is deprecated and discouraged to call this function
* in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library
* are likely to remove the \p mode argument and have it
@@ -856,17 +929,29 @@ int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx,
*
* \note Alternative implementations of RSA need not support
* mode being set to #MBEDTLS_RSA_PUBLIC and might instead
- * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION.
- *
- * \param ctx The RSA context.
- * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE.
- * \param p_rng The RNG context.
- * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE.
+ * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED.
+ *
+ * \param ctx The initialized RSA context to use.
+ * \param f_rng The RNG function. If \p mode is #MBEDTLS_RSA_PRIVATE,
+ * this is used for blinding and should be provided; see
+ * mbedtls_rsa_private() for more. If \p mode is
+ * #MBEDTLS_RSA_PUBLIC, it is ignored.
+ * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL
+ * if \p f_rng is \c NULL or doesn't need a context argument.
+ * \param mode The mode of operation. This must be either
+ * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated).
* \param md_alg The message-digest algorithm used to hash the original data.
* Use #MBEDTLS_MD_NONE for signing raw data.
- * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE.
- * \param hash The buffer holding the message digest.
- * \param sig The buffer to hold the ciphertext.
+ * \param hashlen The length of the message digest.
+ * Ths is only used if \p md_alg is #MBEDTLS_MD_NONE.
+ * \param hash The buffer holding the message digest or raw data.
+ * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable
+ * buffer of length \p hashlen Bytes. If \p md_alg is not
+ * #MBEDTLS_MD_NONE, it must be a readable buffer of length
+ * the size of the hash corresponding to \p md_alg.
+ * \param sig The buffer to hold the signature. This must be a writable
+ * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes
+ * for an 2048-bit RSA modulus.
*
* \return \c 0 if the signing operation was successful.
* \return An \c MBEDTLS_ERR_RSA_XXX error code on failure.
@@ -884,9 +969,6 @@ int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx,
* \brief This function performs a PKCS#1 v2.1 PSS signature
* operation (RSASSA-PSS-SIGN).
*
- * \note The \p sig buffer must be as large as the size
- * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used.
- *
* \note The \p hash_id in the RSA context is the one used for the
* encoding. \p md_alg in the function call is the type of hash
* that is encoded. According to <em>RFC-3447: Public-Key
@@ -894,6 +976,16 @@ int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx,
* Specifications</em> it is advised to keep both hashes the
* same.
*
+ * \note This function always uses the maximum possible salt size,
+ * up to the length of the payload hash. This choice of salt
+ * size complies with FIPS 186-4 §5.5 (e) and RFC 8017 (PKCS#1
+ * v2.2) §9.1.1 step 3. Furthermore this function enforces a
+ * minimum salt size which is the hash size minus 2 bytes. If
+ * this minimum size is too large given the key size (the salt
+ * size, plus the hash size, plus 2 bytes must be no more than
+ * the key size in bytes), this function returns
+ * #MBEDTLS_ERR_RSA_BAD_INPUT_DATA.
+ *
* \deprecated It is deprecated and discouraged to call this function
* in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library
* are likely to remove the \p mode argument and have it
@@ -901,18 +993,26 @@ int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx,
*
* \note Alternative implementations of RSA need not support
* mode being set to #MBEDTLS_RSA_PUBLIC and might instead
- * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION.
- *
- * \param ctx The RSA context.
- * \param f_rng The RNG function. Needed for PKCS#1 v2.1 encoding and for
- * #MBEDTLS_RSA_PRIVATE.
- * \param p_rng The RNG context.
- * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE.
+ * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED.
+ *
+ * \param ctx The initialized RSA context to use.
+ * \param f_rng The RNG function. It must not be \c NULL.
+ * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL
+ * if \p f_rng doesn't need a context argument.
+ * \param mode The mode of operation. This must be either
+ * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated).
* \param md_alg The message-digest algorithm used to hash the original data.
* Use #MBEDTLS_MD_NONE for signing raw data.
- * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE.
- * \param hash The buffer holding the message digest.
- * \param sig The buffer to hold the ciphertext.
+ * \param hashlen The length of the message digest.
+ * Ths is only used if \p md_alg is #MBEDTLS_MD_NONE.
+ * \param hash The buffer holding the message digest or raw data.
+ * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable
+ * buffer of length \p hashlen Bytes. If \p md_alg is not
+ * #MBEDTLS_MD_NONE, it must be a readable buffer of length
+ * the size of the hash corresponding to \p md_alg.
+ * \param sig The buffer to hold the signature. This must be a writable
+ * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes
+ * for an 2048-bit RSA modulus.
*
* \return \c 0 if the signing operation was successful.
* \return An \c MBEDTLS_ERR_RSA_XXX error code on failure.
@@ -933,9 +1033,6 @@ int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx,
* This is the generic wrapper for performing a PKCS#1
* verification using the mode from the context.
*
- * \note The \p sig buffer must be as large as the size
- * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used.
- *
* \note For PKCS#1 v2.1 encoding, see comments on
* mbedtls_rsa_rsassa_pss_verify() about \p md_alg and
* \p hash_id.
@@ -947,17 +1044,28 @@ int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx,
*
* \note Alternative implementations of RSA need not support
* mode being set to #MBEDTLS_RSA_PRIVATE and might instead
- * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION.
- *
- * \param ctx The RSA public key context.
- * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE.
- * \param p_rng The RNG context.
- * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE.
+ * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED.
+ *
+ * \param ctx The initialized RSA public key context to use.
+ * \param f_rng The RNG function to use. If \p mode is #MBEDTLS_RSA_PRIVATE,
+ * this is used for blinding and should be provided; see
+ * mbedtls_rsa_private() for more. Otherwise, it is ignored.
+ * \param p_rng The RNG context to be passed to \p f_rng. This may be
+ * \c NULL if \p f_rng is \c NULL or doesn't need a context.
+ * \param mode The mode of operation. This must be either
+ * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated).
* \param md_alg The message-digest algorithm used to hash the original data.
* Use #MBEDTLS_MD_NONE for signing raw data.
- * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE.
- * \param hash The buffer holding the message digest.
- * \param sig The buffer holding the ciphertext.
+ * \param hashlen The length of the message digest.
+ * This is only used if \p md_alg is #MBEDTLS_MD_NONE.
+ * \param hash The buffer holding the message digest or raw data.
+ * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable
+ * buffer of length \p hashlen Bytes. If \p md_alg is not
+ * #MBEDTLS_MD_NONE, it must be a readable buffer of length
+ * the size of the hash corresponding to \p md_alg.
+ * \param sig The buffer holding the signature. This must be a readable
+ * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes
+ * for an 2048-bit RSA modulus.
*
* \return \c 0 if the verify operation was successful.
* \return An \c MBEDTLS_ERR_RSA_XXX error code on failure.
@@ -975,9 +1083,6 @@ int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx,
* \brief This function performs a PKCS#1 v1.5 verification
* operation (RSASSA-PKCS1-v1_5-VERIFY).
*
- * \note The \p sig buffer must be as large as the size
- * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used.
- *
* \deprecated It is deprecated and discouraged to call this function
* in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library
* are likely to remove the \p mode argument and have it
@@ -985,17 +1090,28 @@ int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx,
*
* \note Alternative implementations of RSA need not support
* mode being set to #MBEDTLS_RSA_PRIVATE and might instead
- * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION.
- *
- * \param ctx The RSA public key context.
- * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE.
- * \param p_rng The RNG context.
- * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE.
+ * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED.
+ *
+ * \param ctx The initialized RSA public key context to use.
+ * \param f_rng The RNG function to use. If \p mode is #MBEDTLS_RSA_PRIVATE,
+ * this is used for blinding and should be provided; see
+ * mbedtls_rsa_private() for more. Otherwise, it is ignored.
+ * \param p_rng The RNG context to be passed to \p f_rng. This may be
+ * \c NULL if \p f_rng is \c NULL or doesn't need a context.
+ * \param mode The mode of operation. This must be either
+ * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated).
* \param md_alg The message-digest algorithm used to hash the original data.
* Use #MBEDTLS_MD_NONE for signing raw data.
- * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE.
- * \param hash The buffer holding the message digest.
- * \param sig The buffer holding the ciphertext.
+ * \param hashlen The length of the message digest.
+ * This is only used if \p md_alg is #MBEDTLS_MD_NONE.
+ * \param hash The buffer holding the message digest or raw data.
+ * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable
+ * buffer of length \p hashlen Bytes. If \p md_alg is not
+ * #MBEDTLS_MD_NONE, it must be a readable buffer of length
+ * the size of the hash corresponding to \p md_alg.
+ * \param sig The buffer holding the signature. This must be a readable
+ * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes
+ * for an 2048-bit RSA modulus.
*
* \return \c 0 if the verify operation was successful.
* \return An \c MBEDTLS_ERR_RSA_XXX error code on failure.
@@ -1016,9 +1132,6 @@ int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx,
* The hash function for the MGF mask generating function
* is that specified in the RSA context.
*
- * \note The \p sig buffer must be as large as the size
- * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used.
- *
* \note The \p hash_id in the RSA context is the one used for the
* verification. \p md_alg in the function call is the type of
* hash that is verified. According to <em>RFC-3447: Public-Key
@@ -1034,17 +1147,28 @@ int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx,
*
* \note Alternative implementations of RSA need not support
* mode being set to #MBEDTLS_RSA_PRIVATE and might instead
- * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION.
- *
- * \param ctx The RSA public key context.
- * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE.
- * \param p_rng The RNG context.
- * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE.
+ * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED.
+ *
+ * \param ctx The initialized RSA public key context to use.
+ * \param f_rng The RNG function to use. If \p mode is #MBEDTLS_RSA_PRIVATE,
+ * this is used for blinding and should be provided; see
+ * mbedtls_rsa_private() for more. Otherwise, it is ignored.
+ * \param p_rng The RNG context to be passed to \p f_rng. This may be
+ * \c NULL if \p f_rng is \c NULL or doesn't need a context.
+ * \param mode The mode of operation. This must be either
+ * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated).
* \param md_alg The message-digest algorithm used to hash the original data.
* Use #MBEDTLS_MD_NONE for signing raw data.
- * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE.
- * \param hash The buffer holding the message digest.
- * \param sig The buffer holding the ciphertext.
+ * \param hashlen The length of the message digest.
+ * This is only used if \p md_alg is #MBEDTLS_MD_NONE.
+ * \param hash The buffer holding the message digest or raw data.
+ * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable
+ * buffer of length \p hashlen Bytes. If \p md_alg is not
+ * #MBEDTLS_MD_NONE, it must be a readable buffer of length
+ * the size of the hash corresponding to \p md_alg.
+ * \param sig The buffer holding the signature. This must be a readable
+ * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes
+ * for an 2048-bit RSA modulus.
*
* \return \c 0 if the verify operation was successful.
* \return An \c MBEDTLS_ERR_RSA_XXX error code on failure.
@@ -1070,19 +1194,29 @@ int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx,
*
* \note The \p hash_id in the RSA context is ignored.
*
- * \param ctx The RSA public key context.
- * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE.
- * \param p_rng The RNG context.
- * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE.
+ * \param ctx The initialized RSA public key context to use.
+ * \param f_rng The RNG function to use. If \p mode is #MBEDTLS_RSA_PRIVATE,
+ * this is used for blinding and should be provided; see
+ * mbedtls_rsa_private() for more. Otherwise, it is ignored.
+ * \param p_rng The RNG context to be passed to \p f_rng. This may be
+ * \c NULL if \p f_rng is \c NULL or doesn't need a context.
+ * \param mode The mode of operation. This must be either
+ * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE.
* \param md_alg The message-digest algorithm used to hash the original data.
* Use #MBEDTLS_MD_NONE for signing raw data.
- * \param hashlen The length of the message digest. Only used if \p md_alg is
- * #MBEDTLS_MD_NONE.
- * \param hash The buffer holding the message digest.
- * \param mgf1_hash_id The message digest used for mask generation.
- * \param expected_salt_len The length of the salt used in padding. Use
- * #MBEDTLS_RSA_SALT_LEN_ANY to accept any salt length.
- * \param sig The buffer holding the ciphertext.
+ * \param hashlen The length of the message digest.
+ * This is only used if \p md_alg is #MBEDTLS_MD_NONE.
+ * \param hash The buffer holding the message digest or raw data.
+ * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable
+ * buffer of length \p hashlen Bytes. If \p md_alg is not
+ * #MBEDTLS_MD_NONE, it must be a readable buffer of length
+ * the size of the hash corresponding to \p md_alg.
+ * \param mgf1_hash_id The message digest used for mask generation.
+ * \param expected_salt_len The length of the salt used in padding. Use
+ * #MBEDTLS_RSA_SALT_LEN_ANY to accept any salt length.
+ * \param sig The buffer holding the signature. This must be a readable
+ * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes
+ * for an 2048-bit RSA modulus.
*
* \return \c 0 if the verify operation was successful.
* \return An \c MBEDTLS_ERR_RSA_XXX error code on failure.
@@ -1101,8 +1235,8 @@ int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx,
/**
* \brief This function copies the components of an RSA context.
*
- * \param dst The destination context.
- * \param src The source context.
+ * \param dst The destination context. This must be initialized.
+ * \param src The source context. This must be initialized.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory allocation failure.
@@ -1112,7 +1246,9 @@ int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src )
/**
* \brief This function frees the components of an RSA key.
*
- * \param ctx The RSA Context to free.
+ * \param ctx The RSA context to free. May be \c NULL, in which case
+ * this function is a no-op. If it is not \c NULL, it must
+ * point to an initialized RSA context.
*/
void mbedtls_rsa_free( mbedtls_rsa_context *ctx );
diff --git a/thirdparty/mbedtls/include/mbedtls/sha1.h b/thirdparty/mbedtls/include/mbedtls/sha1.h
index 65a124c94b..38ea10b137 100644
--- a/thirdparty/mbedtls/include/mbedtls/sha1.h
+++ b/thirdparty/mbedtls/include/mbedtls/sha1.h
@@ -40,7 +40,9 @@
#include <stddef.h>
#include <stdint.h>
+/* MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED -0x0035 /**< SHA-1 hardware accelerator failed */
+#define MBEDTLS_ERR_SHA1_BAD_INPUT_DATA -0x0073 /**< SHA-1 input data was malformed. */
#ifdef __cplusplus
extern "C" {
@@ -58,7 +60,7 @@ extern "C" {
* stronger message digests instead.
*
*/
-typedef struct
+typedef struct mbedtls_sha1_context
{
uint32_t total[2]; /*!< The number of Bytes processed. */
uint32_t state[5]; /*!< The intermediate digest state. */
@@ -78,6 +80,7 @@ mbedtls_sha1_context;
* stronger message digests instead.
*
* \param ctx The SHA-1 context to initialize.
+ * This must not be \c NULL.
*
*/
void mbedtls_sha1_init( mbedtls_sha1_context *ctx );
@@ -89,7 +92,10 @@ void mbedtls_sha1_init( mbedtls_sha1_context *ctx );
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*
- * \param ctx The SHA-1 context to clear.
+ * \param ctx The SHA-1 context to clear. This may be \c NULL,
+ * in which case this function does nothing. If it is
+ * not \c NULL, it must point to an initialized
+ * SHA-1 context.
*
*/
void mbedtls_sha1_free( mbedtls_sha1_context *ctx );
@@ -101,8 +107,8 @@ void mbedtls_sha1_free( mbedtls_sha1_context *ctx );
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*
- * \param dst The SHA-1 context to clone to.
- * \param src The SHA-1 context to clone from.
+ * \param dst The SHA-1 context to clone to. This must be initialized.
+ * \param src The SHA-1 context to clone from. This must be initialized.
*
*/
void mbedtls_sha1_clone( mbedtls_sha1_context *dst,
@@ -115,9 +121,10 @@ void mbedtls_sha1_clone( mbedtls_sha1_context *dst,
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*
- * \param ctx The SHA-1 context to initialize.
+ * \param ctx The SHA-1 context to initialize. This must be initialized.
*
* \return \c 0 on success.
+ * \return A negative error code on failure.
*
*/
int mbedtls_sha1_starts_ret( mbedtls_sha1_context *ctx );
@@ -130,11 +137,14 @@ int mbedtls_sha1_starts_ret( mbedtls_sha1_context *ctx );
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*
- * \param ctx The SHA-1 context.
+ * \param ctx The SHA-1 context. This must be initialized
+ * and have a hash operation started.
* \param input The buffer holding the input data.
- * \param ilen The length of the input data.
+ * This must be a readable buffer of length \p ilen Bytes.
+ * \param ilen The length of the input data \p input in Bytes.
*
* \return \c 0 on success.
+ * \return A negative error code on failure.
*/
int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx,
const unsigned char *input,
@@ -148,10 +158,13 @@ int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx,
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*
- * \param ctx The SHA-1 context.
- * \param output The SHA-1 checksum result.
+ * \param ctx The SHA-1 context to use. This must be initialized and
+ * have a hash operation started.
+ * \param output The SHA-1 checksum result. This must be a writable
+ * buffer of length \c 20 Bytes.
*
* \return \c 0 on success.
+ * \return A negative error code on failure.
*/
int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx,
unsigned char output[20] );
@@ -163,10 +176,12 @@ int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx,
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*
- * \param ctx The SHA-1 context.
- * \param data The data block being processed.
+ * \param ctx The SHA-1 context to use. This must be initialized.
+ * \param data The data block being processed. This must be a
+ * readable buffer of length \c 64 Bytes.
*
* \return \c 0 on success.
+ * \return A negative error code on failure.
*
*/
int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx,
@@ -187,7 +202,7 @@ int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx,
*
* \deprecated Superseded by mbedtls_sha1_starts_ret() in 2.7.0.
*
- * \param ctx The SHA-1 context to initialize.
+ * \param ctx The SHA-1 context to initialize. This must be initialized.
*
*/
MBEDTLS_DEPRECATED void mbedtls_sha1_starts( mbedtls_sha1_context *ctx );
@@ -202,9 +217,11 @@ MBEDTLS_DEPRECATED void mbedtls_sha1_starts( mbedtls_sha1_context *ctx );
*
* \deprecated Superseded by mbedtls_sha1_update_ret() in 2.7.0.
*
- * \param ctx The SHA-1 context.
+ * \param ctx The SHA-1 context. This must be initialized and
+ * have a hash operation started.
* \param input The buffer holding the input data.
- * \param ilen The length of the input data.
+ * This must be a readable buffer of length \p ilen Bytes.
+ * \param ilen The length of the input data \p input in Bytes.
*
*/
MBEDTLS_DEPRECATED void mbedtls_sha1_update( mbedtls_sha1_context *ctx,
@@ -221,9 +238,10 @@ MBEDTLS_DEPRECATED void mbedtls_sha1_update( mbedtls_sha1_context *ctx,
*
* \deprecated Superseded by mbedtls_sha1_finish_ret() in 2.7.0.
*
- * \param ctx The SHA-1 context.
+ * \param ctx The SHA-1 context. This must be initialized and
+ * have a hash operation started.
* \param output The SHA-1 checksum result.
- *
+ * This must be a writable buffer of length \c 20 Bytes.
*/
MBEDTLS_DEPRECATED void mbedtls_sha1_finish( mbedtls_sha1_context *ctx,
unsigned char output[20] );
@@ -237,8 +255,9 @@ MBEDTLS_DEPRECATED void mbedtls_sha1_finish( mbedtls_sha1_context *ctx,
*
* \deprecated Superseded by mbedtls_internal_sha1_process() in 2.7.0.
*
- * \param ctx The SHA-1 context.
+ * \param ctx The SHA-1 context. This must be initialized.
* \param data The data block being processed.
+ * This must be a readable buffer of length \c 64 bytes.
*
*/
MBEDTLS_DEPRECATED void mbedtls_sha1_process( mbedtls_sha1_context *ctx,
@@ -261,10 +280,13 @@ MBEDTLS_DEPRECATED void mbedtls_sha1_process( mbedtls_sha1_context *ctx,
* stronger message digests instead.
*
* \param input The buffer holding the input data.
- * \param ilen The length of the input data.
+ * This must be a readable buffer of length \p ilen Bytes.
+ * \param ilen The length of the input data \p input in Bytes.
* \param output The SHA-1 checksum result.
+ * This must be a writable buffer of length \c 20 Bytes.
*
* \return \c 0 on success.
+ * \return A negative error code on failure.
*
*/
int mbedtls_sha1_ret( const unsigned char *input,
@@ -293,8 +315,10 @@ int mbedtls_sha1_ret( const unsigned char *input,
* \deprecated Superseded by mbedtls_sha1_ret() in 2.7.0
*
* \param input The buffer holding the input data.
- * \param ilen The length of the input data.
- * \param output The SHA-1 checksum result.
+ * This must be a readable buffer of length \p ilen Bytes.
+ * \param ilen The length of the input data \p input in Bytes.
+ * \param output The SHA-1 checksum result. This must be a writable
+ * buffer of size \c 20 Bytes.
*
*/
MBEDTLS_DEPRECATED void mbedtls_sha1( const unsigned char *input,
diff --git a/thirdparty/mbedtls/include/mbedtls/sha256.h b/thirdparty/mbedtls/include/mbedtls/sha256.h
index adf31a82ed..0e42f0abba 100644
--- a/thirdparty/mbedtls/include/mbedtls/sha256.h
+++ b/thirdparty/mbedtls/include/mbedtls/sha256.h
@@ -36,7 +36,9 @@
#include <stddef.h>
#include <stdint.h>
+/* MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED -0x0037 /**< SHA-256 hardware accelerator failed */
+#define MBEDTLS_ERR_SHA256_BAD_INPUT_DATA -0x0074 /**< SHA-256 input data was malformed. */
#ifdef __cplusplus
extern "C" {
@@ -53,7 +55,7 @@ extern "C" {
* checksum calculations. The choice between these two is
* made in the call to mbedtls_sha256_starts_ret().
*/
-typedef struct
+typedef struct mbedtls_sha256_context
{
uint32_t total[2]; /*!< The number of Bytes processed. */
uint32_t state[8]; /*!< The intermediate digest state. */
@@ -70,22 +72,24 @@ mbedtls_sha256_context;
/**
* \brief This function initializes a SHA-256 context.
*
- * \param ctx The SHA-256 context to initialize.
+ * \param ctx The SHA-256 context to initialize. This must not be \c NULL.
*/
void mbedtls_sha256_init( mbedtls_sha256_context *ctx );
/**
* \brief This function clears a SHA-256 context.
*
- * \param ctx The SHA-256 context to clear.
+ * \param ctx The SHA-256 context to clear. This may be \c NULL, in which
+ * case this function returns immediately. If it is not \c NULL,
+ * it must point to an initialized SHA-256 context.
*/
void mbedtls_sha256_free( mbedtls_sha256_context *ctx );
/**
* \brief This function clones the state of a SHA-256 context.
*
- * \param dst The destination context.
- * \param src The context to clone.
+ * \param dst The destination context. This must be initialized.
+ * \param src The context to clone. This must be initialized.
*/
void mbedtls_sha256_clone( mbedtls_sha256_context *dst,
const mbedtls_sha256_context *src );
@@ -94,11 +98,12 @@ void mbedtls_sha256_clone( mbedtls_sha256_context *dst,
* \brief This function starts a SHA-224 or SHA-256 checksum
* calculation.
*
- * \param ctx The context to initialize.
- * \param is224 Determines which function to use:
- * 0: Use SHA-256, or 1: Use SHA-224.
+ * \param ctx The context to use. This must be initialized.
+ * \param is224 This determines which function to use. This must be
+ * either \c 0 for SHA-256, or \c 1 for SHA-224.
*
* \return \c 0 on success.
+ * \return A negative error code on failure.
*/
int mbedtls_sha256_starts_ret( mbedtls_sha256_context *ctx, int is224 );
@@ -106,11 +111,14 @@ int mbedtls_sha256_starts_ret( mbedtls_sha256_context *ctx, int is224 );
* \brief This function feeds an input buffer into an ongoing
* SHA-256 checksum calculation.
*
- * \param ctx The SHA-256 context.
- * \param input The buffer holding the data.
- * \param ilen The length of the input data.
+ * \param ctx The SHA-256 context. This must be initialized
+ * and have a hash operation started.
+ * \param input The buffer holding the data. This must be a readable
+ * buffer of length \p ilen Bytes.
+ * \param ilen The length of the input data in Bytes.
*
* \return \c 0 on success.
+ * \return A negative error code on failure.
*/
int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx,
const unsigned char *input,
@@ -120,10 +128,13 @@ int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx,
* \brief This function finishes the SHA-256 operation, and writes
* the result to the output buffer.
*
- * \param ctx The SHA-256 context.
+ * \param ctx The SHA-256 context. This must be initialized
+ * and have a hash operation started.
* \param output The SHA-224 or SHA-256 checksum result.
+ * This must be a writable buffer of length \c 32 Bytes.
*
* \return \c 0 on success.
+ * \return A negative error code on failure.
*/
int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx,
unsigned char output[32] );
@@ -133,10 +144,12 @@ int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx,
* the ongoing SHA-256 computation. This function is for
* internal use only.
*
- * \param ctx The SHA-256 context.
- * \param data The buffer holding one block of data.
+ * \param ctx The SHA-256 context. This must be initialized.
+ * \param data The buffer holding one block of data. This must
+ * be a readable buffer of length \c 64 Bytes.
*
* \return \c 0 on success.
+ * \return A negative error code on failure.
*/
int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx,
const unsigned char data[64] );
@@ -151,12 +164,11 @@ int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx,
* \brief This function starts a SHA-224 or SHA-256 checksum
* calculation.
*
- *
* \deprecated Superseded by mbedtls_sha256_starts_ret() in 2.7.0.
*
- * \param ctx The context to initialize.
- * \param is224 Determines which function to use:
- * 0: Use SHA-256, or 1: Use SHA-224.
+ * \param ctx The context to use. This must be initialized.
+ * \param is224 Determines which function to use. This must be
+ * either \c 0 for SHA-256, or \c 1 for SHA-224.
*/
MBEDTLS_DEPRECATED void mbedtls_sha256_starts( mbedtls_sha256_context *ctx,
int is224 );
@@ -167,9 +179,11 @@ MBEDTLS_DEPRECATED void mbedtls_sha256_starts( mbedtls_sha256_context *ctx,
*
* \deprecated Superseded by mbedtls_sha256_update_ret() in 2.7.0.
*
- * \param ctx The SHA-256 context to initialize.
- * \param input The buffer holding the data.
- * \param ilen The length of the input data.
+ * \param ctx The SHA-256 context to use. This must be
+ * initialized and have a hash operation started.
+ * \param input The buffer holding the data. This must be a readable
+ * buffer of length \p ilen Bytes.
+ * \param ilen The length of the input data in Bytes.
*/
MBEDTLS_DEPRECATED void mbedtls_sha256_update( mbedtls_sha256_context *ctx,
const unsigned char *input,
@@ -181,8 +195,10 @@ MBEDTLS_DEPRECATED void mbedtls_sha256_update( mbedtls_sha256_context *ctx,
*
* \deprecated Superseded by mbedtls_sha256_finish_ret() in 2.7.0.
*
- * \param ctx The SHA-256 context.
- * \param output The SHA-224 or SHA-256 checksum result.
+ * \param ctx The SHA-256 context. This must be initialized and
+ * have a hash operation started.
+ * \param output The SHA-224 or SHA-256 checksum result. This must be
+ * a writable buffer of length \c 32 Bytes.
*/
MBEDTLS_DEPRECATED void mbedtls_sha256_finish( mbedtls_sha256_context *ctx,
unsigned char output[32] );
@@ -194,8 +210,9 @@ MBEDTLS_DEPRECATED void mbedtls_sha256_finish( mbedtls_sha256_context *ctx,
*
* \deprecated Superseded by mbedtls_internal_sha256_process() in 2.7.0.
*
- * \param ctx The SHA-256 context.
- * \param data The buffer holding one block of data.
+ * \param ctx The SHA-256 context. This must be initialized.
+ * \param data The buffer holding one block of data. This must be
+ * a readable buffer of size \c 64 Bytes.
*/
MBEDTLS_DEPRECATED void mbedtls_sha256_process( mbedtls_sha256_context *ctx,
const unsigned char data[64] );
@@ -213,11 +230,13 @@ MBEDTLS_DEPRECATED void mbedtls_sha256_process( mbedtls_sha256_context *ctx,
* The SHA-256 result is calculated as
* output = SHA-256(input buffer).
*
- * \param input The buffer holding the input data.
- * \param ilen The length of the input data.
- * \param output The SHA-224 or SHA-256 checksum result.
- * \param is224 Determines which function to use:
- * 0: Use SHA-256, or 1: Use SHA-224.
+ * \param input The buffer holding the data. This must be a readable
+ * buffer of length \p ilen Bytes.
+ * \param ilen The length of the input data in Bytes.
+ * \param output The SHA-224 or SHA-256 checksum result. This must
+ * be a writable buffer of length \c 32 Bytes.
+ * \param is224 Determines which function to use. This must be
+ * either \c 0 for SHA-256, or \c 1 for SHA-224.
*/
int mbedtls_sha256_ret( const unsigned char *input,
size_t ilen,
@@ -243,11 +262,13 @@ int mbedtls_sha256_ret( const unsigned char *input,
*
* \deprecated Superseded by mbedtls_sha256_ret() in 2.7.0.
*
- * \param input The buffer holding the data.
- * \param ilen The length of the input data.
- * \param output The SHA-224 or SHA-256 checksum result.
- * \param is224 Determines which function to use:
- * 0: Use SHA-256, or 1: Use SHA-224.
+ * \param input The buffer holding the data. This must be a readable
+ * buffer of length \p ilen Bytes.
+ * \param ilen The length of the input data in Bytes.
+ * \param output The SHA-224 or SHA-256 checksum result. This must be
+ * a writable buffer of length \c 32 Bytes.
+ * \param is224 Determines which function to use. This must be either
+ * \c 0 for SHA-256, or \c 1 for SHA-224.
*/
MBEDTLS_DEPRECATED void mbedtls_sha256( const unsigned char *input,
size_t ilen,
diff --git a/thirdparty/mbedtls/include/mbedtls/sha512.h b/thirdparty/mbedtls/include/mbedtls/sha512.h
index 5bb83f43bd..7b26cf5cc3 100644
--- a/thirdparty/mbedtls/include/mbedtls/sha512.h
+++ b/thirdparty/mbedtls/include/mbedtls/sha512.h
@@ -35,7 +35,9 @@
#include <stddef.h>
#include <stdint.h>
+/* MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED -0x0039 /**< SHA-512 hardware accelerator failed */
+#define MBEDTLS_ERR_SHA512_BAD_INPUT_DATA -0x0075 /**< SHA-512 input data was malformed. */
#ifdef __cplusplus
extern "C" {
@@ -52,7 +54,7 @@ extern "C" {
* checksum calculations. The choice between these two is
* made in the call to mbedtls_sha512_starts_ret().
*/
-typedef struct
+typedef struct mbedtls_sha512_context
{
uint64_t total[2]; /*!< The number of Bytes processed. */
uint64_t state[8]; /*!< The intermediate digest state. */
@@ -69,22 +71,26 @@ mbedtls_sha512_context;
/**
* \brief This function initializes a SHA-512 context.
*
- * \param ctx The SHA-512 context to initialize.
+ * \param ctx The SHA-512 context to initialize. This must
+ * not be \c NULL.
*/
void mbedtls_sha512_init( mbedtls_sha512_context *ctx );
/**
* \brief This function clears a SHA-512 context.
*
- * \param ctx The SHA-512 context to clear.
+ * \param ctx The SHA-512 context to clear. This may be \c NULL,
+ * in which case this function does nothing. If it
+ * is not \c NULL, it must point to an initialized
+ * SHA-512 context.
*/
void mbedtls_sha512_free( mbedtls_sha512_context *ctx );
/**
* \brief This function clones the state of a SHA-512 context.
*
- * \param dst The destination context.
- * \param src The context to clone.
+ * \param dst The destination context. This must be initialized.
+ * \param src The context to clone. This must be initialized.
*/
void mbedtls_sha512_clone( mbedtls_sha512_context *dst,
const mbedtls_sha512_context *src );
@@ -93,11 +99,12 @@ void mbedtls_sha512_clone( mbedtls_sha512_context *dst,
* \brief This function starts a SHA-384 or SHA-512 checksum
* calculation.
*
- * \param ctx The SHA-512 context to initialize.
- * \param is384 Determines which function to use:
- * 0: Use SHA-512, or 1: Use SHA-384.
+ * \param ctx The SHA-512 context to use. This must be initialized.
+ * \param is384 Determines which function to use. This must be
+ * either \c for SHA-512, or \c 1 for SHA-384.
*
* \return \c 0 on success.
+ * \return A negative error code on failure.
*/
int mbedtls_sha512_starts_ret( mbedtls_sha512_context *ctx, int is384 );
@@ -105,11 +112,14 @@ int mbedtls_sha512_starts_ret( mbedtls_sha512_context *ctx, int is384 );
* \brief This function feeds an input buffer into an ongoing
* SHA-512 checksum calculation.
*
- * \param ctx The SHA-512 context.
- * \param input The buffer holding the input data.
- * \param ilen The length of the input data.
+ * \param ctx The SHA-512 context. This must be initialized
+ * and have a hash operation started.
+ * \param input The buffer holding the input data. This must
+ * be a readable buffer of length \p ilen Bytes.
+ * \param ilen The length of the input data in Bytes.
*
* \return \c 0 on success.
+ * \return A negative error code on failure.
*/
int mbedtls_sha512_update_ret( mbedtls_sha512_context *ctx,
const unsigned char *input,
@@ -120,10 +130,13 @@ int mbedtls_sha512_update_ret( mbedtls_sha512_context *ctx,
* the result to the output buffer. This function is for
* internal use only.
*
- * \param ctx The SHA-512 context.
+ * \param ctx The SHA-512 context. This must be initialized
+ * and have a hash operation started.
* \param output The SHA-384 or SHA-512 checksum result.
+ * This must be a writable buffer of length \c 64 Bytes.
*
* \return \c 0 on success.
+ * \return A negative error code on failure.
*/
int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx,
unsigned char output[64] );
@@ -132,10 +145,12 @@ int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx,
* \brief This function processes a single data block within
* the ongoing SHA-512 computation.
*
- * \param ctx The SHA-512 context.
- * \param data The buffer holding one block of data.
+ * \param ctx The SHA-512 context. This must be initialized.
+ * \param data The buffer holding one block of data. This
+ * must be a readable buffer of length \c 128 Bytes.
*
* \return \c 0 on success.
+ * \return A negative error code on failure.
*/
int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx,
const unsigned char data[128] );
@@ -151,9 +166,9 @@ int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx,
*
* \deprecated Superseded by mbedtls_sha512_starts_ret() in 2.7.0
*
- * \param ctx The SHA-512 context to initialize.
- * \param is384 Determines which function to use:
- * 0: Use SHA-512, or 1: Use SHA-384.
+ * \param ctx The SHA-512 context to use. This must be initialized.
+ * \param is384 Determines which function to use. This must be either
+ * \c 0 for SHA-512 or \c 1 for SHA-384.
*/
MBEDTLS_DEPRECATED void mbedtls_sha512_starts( mbedtls_sha512_context *ctx,
int is384 );
@@ -164,9 +179,11 @@ MBEDTLS_DEPRECATED void mbedtls_sha512_starts( mbedtls_sha512_context *ctx,
*
* \deprecated Superseded by mbedtls_sha512_update_ret() in 2.7.0.
*
- * \param ctx The SHA-512 context.
- * \param input The buffer holding the data.
- * \param ilen The length of the input data.
+ * \param ctx The SHA-512 context. This must be initialized
+ * and have a hash operation started.
+ * \param input The buffer holding the data. This must be a readable
+ * buffer of length \p ilen Bytes.
+ * \param ilen The length of the input data in Bytes.
*/
MBEDTLS_DEPRECATED void mbedtls_sha512_update( mbedtls_sha512_context *ctx,
const unsigned char *input,
@@ -178,8 +195,10 @@ MBEDTLS_DEPRECATED void mbedtls_sha512_update( mbedtls_sha512_context *ctx,
*
* \deprecated Superseded by mbedtls_sha512_finish_ret() in 2.7.0.
*
- * \param ctx The SHA-512 context.
- * \param output The SHA-384 or SHA-512 checksum result.
+ * \param ctx The SHA-512 context. This must be initialized
+ * and have a hash operation started.
+ * \param output The SHA-384 or SHA-512 checksum result. This must
+ * be a writable buffer of size \c 64 Bytes.
*/
MBEDTLS_DEPRECATED void mbedtls_sha512_finish( mbedtls_sha512_context *ctx,
unsigned char output[64] );
@@ -191,8 +210,9 @@ MBEDTLS_DEPRECATED void mbedtls_sha512_finish( mbedtls_sha512_context *ctx,
*
* \deprecated Superseded by mbedtls_internal_sha512_process() in 2.7.0.
*
- * \param ctx The SHA-512 context.
- * \param data The buffer holding one block of data.
+ * \param ctx The SHA-512 context. This must be initialized.
+ * \param data The buffer holding one block of data. This must be
+ * a readable buffer of length \c 128 Bytes.
*/
MBEDTLS_DEPRECATED void mbedtls_sha512_process(
mbedtls_sha512_context *ctx,
@@ -211,13 +231,16 @@ MBEDTLS_DEPRECATED void mbedtls_sha512_process(
* The SHA-512 result is calculated as
* output = SHA-512(input buffer).
*
- * \param input The buffer holding the input data.
- * \param ilen The length of the input data.
+ * \param input The buffer holding the input data. This must be
+ * a readable buffer of length \p ilen Bytes.
+ * \param ilen The length of the input data in Bytes.
* \param output The SHA-384 or SHA-512 checksum result.
- * \param is384 Determines which function to use:
- * 0: Use SHA-512, or 1: Use SHA-384.
+ * This must be a writable buffer of length \c 64 Bytes.
+ * \param is384 Determines which function to use. This must be either
+ * \c 0 for SHA-512, or \c 1 for SHA-384.
*
* \return \c 0 on success.
+ * \return A negative error code on failure.
*/
int mbedtls_sha512_ret( const unsigned char *input,
size_t ilen,
@@ -242,11 +265,13 @@ int mbedtls_sha512_ret( const unsigned char *input,
*
* \deprecated Superseded by mbedtls_sha512_ret() in 2.7.0
*
- * \param input The buffer holding the data.
- * \param ilen The length of the input data.
- * \param output The SHA-384 or SHA-512 checksum result.
- * \param is384 Determines which function to use:
- * 0: Use SHA-512, or 1: Use SHA-384.
+ * \param input The buffer holding the data. This must be a
+ * readable buffer of length \p ilen Bytes.
+ * \param ilen The length of the input data in Bytes.
+ * \param output The SHA-384 or SHA-512 checksum result. This must
+ * be a writable buffer of length \c 64 Bytes.
+ * \param is384 Determines which function to use. This must be either
+ * \c 0 for SHA-512, or \c 1 for SHA-384.
*/
MBEDTLS_DEPRECATED void mbedtls_sha512( const unsigned char *input,
size_t ilen,
diff --git a/thirdparty/mbedtls/include/mbedtls/ssl.h b/thirdparty/mbedtls/include/mbedtls/ssl.h
index 2d511a8ea1..8106bb4ab0 100644
--- a/thirdparty/mbedtls/include/mbedtls/ssl.h
+++ b/thirdparty/mbedtls/include/mbedtls/ssl.h
@@ -121,6 +121,8 @@
#define MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH -0x6600 /**< Couldn't set the hash for verifying CertificateVerify */
#define MBEDTLS_ERR_SSL_CONTINUE_PROCESSING -0x6580 /**< Internal-only message signaling that further message-processing should be done */
#define MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS -0x6500 /**< The asynchronous operation is not completed yet. */
+#define MBEDTLS_ERR_SSL_EARLY_MESSAGE -0x6480 /**< Internal-only message signaling that a message arrived early. */
+#define MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS -0x7000 /**< A cryptographic operation is in progress. Try again later. */
/*
* Various constants
@@ -242,6 +244,14 @@
#define MBEDTLS_SSL_OUT_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN
#endif
+/*
+ * Maximum number of heap-allocated bytes for the purpose of
+ * DTLS handshake message reassembly and future message buffering.
+ */
+#if !defined(MBEDTLS_SSL_DTLS_MAX_BUFFERING)
+#define MBEDTLS_SSL_DTLS_MAX_BUFFERING 32768
+#endif
+
/* \} name SECTION: Module settings */
/*
@@ -1022,14 +1032,14 @@ struct mbedtls_ssl_context
int renego_records_seen; /*!< Records since renego request, or with DTLS,
number of retransmissions of request if
renego_max_records is < 0 */
-#endif
+#endif /* MBEDTLS_SSL_RENEGOTIATION */
int major_ver; /*!< equal to MBEDTLS_SSL_MAJOR_VERSION_3 */
int minor_ver; /*!< either 0 (SSL3) or 1 (TLS1.0) */
#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT)
unsigned badmac_seen; /*!< records with a bad MAC received */
-#endif
+#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */
mbedtls_ssl_send_t *f_send; /*!< Callback for network send */
mbedtls_ssl_recv_t *f_recv; /*!< Callback for network receive */
@@ -1085,11 +1095,11 @@ struct mbedtls_ssl_context
uint16_t in_epoch; /*!< DTLS epoch for incoming records */
size_t next_record_offset; /*!< offset of the next record in datagram
(equal to in_left if none) */
-#endif
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
uint64_t in_window_top; /*!< last validated record seq_num */
uint64_t in_window; /*!< bitmask for replay detection */
-#endif
+#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */
size_t in_hslen; /*!< current handshake message length,
including the handshake header */
@@ -1098,6 +1108,11 @@ struct mbedtls_ssl_context
int keep_current_message; /*!< drop or reuse current message
on next call to record layer? */
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ uint8_t disable_datagram_packing; /*!< Disable packing multiple records
+ * within a single datagram. */
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
/*
* Record layer (outgoing data)
*/
@@ -1112,12 +1127,18 @@ struct mbedtls_ssl_context
size_t out_msglen; /*!< record header: message length */
size_t out_left; /*!< amount of data not yet written */
+ unsigned char cur_out_ctr[8]; /*!< Outgoing record sequence number. */
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ uint16_t mtu; /*!< path mtu, used to fragment outgoing messages */
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
#if defined(MBEDTLS_ZLIB_SUPPORT)
unsigned char *compress_buf; /*!< zlib data buffer */
-#endif
+#endif /* MBEDTLS_ZLIB_SUPPORT */
#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING)
signed char split_done; /*!< current record already splitted? */
-#endif
+#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */
/*
* PKI layer
@@ -1130,11 +1151,11 @@ struct mbedtls_ssl_context
#if defined(MBEDTLS_X509_CRT_PARSE_C)
char *hostname; /*!< expected peer CN for verification
(and SNI if available) */
-#endif
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
#if defined(MBEDTLS_SSL_ALPN)
const char *alpn_chosen; /*!< negotiated protocol */
-#endif
+#endif /* MBEDTLS_SSL_ALPN */
/*
* Information for DTLS hello verify
@@ -1142,7 +1163,7 @@ struct mbedtls_ssl_context
#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)
unsigned char *cli_id; /*!< transport-level ID of the client */
size_t cli_id_len; /*!< length of cli_id */
-#endif
+#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */
/*
* Secure renegotiation
@@ -1154,7 +1175,7 @@ struct mbedtls_ssl_context
size_t verify_data_len; /*!< length of verify data stored */
char own_verify_data[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */
char peer_verify_data[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */
-#endif
+#endif /* MBEDTLS_SSL_RENEGOTIATION */
};
#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
@@ -1374,6 +1395,52 @@ void mbedtls_ssl_set_bio( mbedtls_ssl_context *ssl,
mbedtls_ssl_recv_t *f_recv,
mbedtls_ssl_recv_timeout_t *f_recv_timeout );
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+/**
+ * \brief Set the Maximum Tranport Unit (MTU).
+ * Special value: 0 means unset (no limit).
+ * This represents the maximum size of a datagram payload
+ * handled by the transport layer (usually UDP) as determined
+ * by the network link and stack. In practice, this controls
+ * the maximum size datagram the DTLS layer will pass to the
+ * \c f_send() callback set using \c mbedtls_ssl_set_bio().
+ *
+ * \note The limit on datagram size is converted to a limit on
+ * record payload by subtracting the current overhead of
+ * encapsulation and encryption/authentication if any.
+ *
+ * \note This can be called at any point during the connection, for
+ * example when a Path Maximum Transfer Unit (PMTU)
+ * estimate becomes available from other sources,
+ * such as lower (or higher) protocol layers.
+ *
+ * \note This setting only controls the size of the packets we send,
+ * and does not restrict the size of the datagrams we're
+ * willing to receive. Client-side, you can request the
+ * server to use smaller records with \c
+ * mbedtls_ssl_conf_max_frag_len().
+ *
+ * \note If both a MTU and a maximum fragment length have been
+ * configured (or negotiated with the peer), the resulting
+ * lower limit on record payload (see first note) is used.
+ *
+ * \note This can only be used to decrease the maximum size
+ * of datagrams (hence records, see first note) sent. It
+ * cannot be used to increase the maximum size of records over
+ * the limit set by #MBEDTLS_SSL_OUT_CONTENT_LEN.
+ *
+ * \note Values lower than the current record layer expansion will
+ * result in an error when trying to send data.
+ *
+ * \note Using record compression together with a non-zero MTU value
+ * will result in an error when trying to send data.
+ *
+ * \param ssl SSL context
+ * \param mtu Value of the path MTU in bytes
+ */
+void mbedtls_ssl_set_mtu( mbedtls_ssl_context *ssl, uint16_t mtu );
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
/**
* \brief Set the timeout period for mbedtls_ssl_read()
* (Default: no timeout.)
@@ -1757,6 +1824,38 @@ void mbedtls_ssl_conf_dtls_badmac_limit( mbedtls_ssl_config *conf, unsigned limi
#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */
#if defined(MBEDTLS_SSL_PROTO_DTLS)
+
+/**
+ * \brief Allow or disallow packing of multiple handshake records
+ * within a single datagram.
+ *
+ * \param ssl The SSL context to configure.
+ * \param allow_packing This determines whether datagram packing may
+ * be used or not. A value of \c 0 means that every
+ * record will be sent in a separate datagram; a
+ * value of \c 1 means that, if space permits,
+ * multiple handshake messages (including CCS) belonging to
+ * a single flight may be packed within a single datagram.
+ *
+ * \note This is enabled by default and should only be disabled
+ * for test purposes, or if datagram packing causes
+ * interoperability issues with peers that don't support it.
+ *
+ * \note Allowing datagram packing reduces the network load since
+ * there's less overhead if multiple messages share the same
+ * datagram. Also, it increases the handshake efficiency
+ * since messages belonging to a single datagram will not
+ * be reordered in transit, and so future message buffering
+ * or flight retransmission (if no buffering is used) as
+ * means to deal with reordering are needed less frequently.
+ *
+ * \note Application records are not affected by this option and
+ * are currently always sent in separate datagrams.
+ *
+ */
+void mbedtls_ssl_set_datagram_packing( mbedtls_ssl_context *ssl,
+ unsigned allow_packing );
+
/**
* \brief Set retransmit timeout values for the DTLS handshake.
* (DTLS only, no effect on TLS.)
@@ -1945,6 +2044,14 @@ void mbedtls_ssl_conf_ca_chain( mbedtls_ssl_config *conf,
* whether it matches those preferences - the server can then
* decide what it wants to do with it.
*
+ * \note The provided \p pk_key needs to match the public key in the
+ * first certificate in \p own_cert, or all handshakes using
+ * that certificate will fail. It is your responsibility
+ * to ensure that; this function will not perform any check.
+ * You may use mbedtls_pk_check_pair() in order to perform
+ * this check yourself, but be aware that this function can
+ * be computationally expensive on some key types.
+ *
* \param conf SSL configuration
* \param own_cert own public certificate chain
* \param pk_key own private key
@@ -2433,6 +2540,18 @@ void mbedtls_ssl_conf_cert_req_ca_list( mbedtls_ssl_config *conf,
* (Client: set maximum fragment length to emit *and*
* negotiate with the server during handshake)
*
+ * \note With TLS, this currently only affects ApplicationData (sent
+ * with \c mbedtls_ssl_read()), not handshake messages.
+ * With DTLS, this affects both ApplicationData and handshake.
+ *
+ * \note This sets the maximum length for a record's payload,
+ * excluding record overhead that will be added to it, see
+ * \c mbedtls_ssl_get_record_expansion().
+ *
+ * \note For DTLS, it is also possible to set a limit for the total
+ * size of daragrams passed to the transport layer, including
+ * record overhead, see \c mbedtls_ssl_set_mtu().
+ *
* \param conf SSL configuration
* \param mfl_code Code for maximum fragment length (allowed values:
* MBEDTLS_SSL_MAX_FRAG_LEN_512, MBEDTLS_SSL_MAX_FRAG_LEN_1024,
@@ -2663,13 +2782,14 @@ size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl );
/**
* \brief Return the result of the certificate verification
*
- * \param ssl SSL context
+ * \param ssl The SSL context to use.
*
- * \return 0 if successful,
- * -1 if result is not available (eg because the handshake was
- * aborted too early), or
- * a combination of BADCERT_xxx and BADCRL_xxx flags, see
- * x509.h
+ * \return \c 0 if the certificate verification was successful.
+ * \return \c -1u if the result is not available. This may happen
+ * e.g. if the handshake aborts early, or a verification
+ * callback returned a fatal error.
+ * \return A bitwise combination of \c MBEDTLS_X509_BADCERT_XXX
+ * and \c MBEDTLS_X509_BADCRL_XXX failure flags; see x509.h.
*/
uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *ssl );
@@ -2695,6 +2815,9 @@ const char *mbedtls_ssl_get_version( const mbedtls_ssl_context *ssl );
* \brief Return the (maximum) number of bytes added by the record
* layer: header + encryption/MAC overhead (inc. padding)
*
+ * \note This function is not available (always returns an error)
+ * when record compression is enabled.
+ *
* \param ssl SSL context
*
* \return Current maximum record expansion in bytes, or
@@ -2709,6 +2832,23 @@ int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl );
* This is the value negotiated with peer if any,
* or the locally configured value.
*
+ * \sa mbedtls_ssl_conf_max_frag_len()
+ * \sa mbedtls_ssl_get_max_record_payload()
+ *
+ * \param ssl SSL context
+ *
+ * \return Current maximum fragment length.
+ */
+size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl );
+#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
+
+/**
+ * \brief Return the current maximum outgoing record payload in bytes.
+ * This takes into account the config.h setting \c
+ * MBEDTLS_SSL_OUT_CONTENT_LEN, the configured and negotiated
+ * max fragment length extension if used, and for DTLS the
+ * path MTU as configured and current record expansion.
+ *
* \note With DTLS, \c mbedtls_ssl_write() will return an error if
* called with a larger length value.
* With TLS, \c mbedtls_ssl_write() will fragment the input if
@@ -2716,12 +2856,19 @@ int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl );
* to the caller to call \c mbedtls_ssl_write() again in
* order to send the remaining bytes if any.
*
+ * \note This function is not available (always returns an error)
+ * when record compression is enabled.
+ *
+ * \sa mbedtls_ssl_set_mtu()
+ * \sa mbedtls_ssl_get_max_frag_len()
+ * \sa mbedtls_ssl_get_record_expansion()
+ *
* \param ssl SSL context
*
- * \return Current maximum fragment length.
+ * \return Current maximum payload for an outgoing record,
+ * or a negative error code.
*/
-size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl );
-#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
+int mbedtls_ssl_get_max_out_record_payload( const mbedtls_ssl_context *ssl );
#if defined(MBEDTLS_X509_CRT_PARSE_C)
/**
@@ -2776,35 +2923,50 @@ int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, mbedtls_ssl_session
*
* \param ssl SSL context
*
- * \return 0 if successful, or
- * MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or
- * MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED (see below), or
- * a specific SSL error code.
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE
+ * if the handshake is incomplete and waiting for data to
+ * be available for reading from or writing to the underlying
+ * transport - in this case you must call this function again
+ * when the underlying transport is ready for the operation.
+ * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous
+ * operation is in progress (see
+ * mbedtls_ssl_conf_async_private_cb()) - in this case you
+ * must call this function again when the operation is ready.
+ * \return #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic
+ * operation is in progress (see mbedtls_ecp_set_max_ops()) -
+ * in this case you must call this function again to complete
+ * the handshake when you're done attending other tasks.
+ * \return #MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED if DTLS is in use
+ * and the client did not demonstrate reachability yet - in
+ * this case you must stop using the context (see below).
+ * \return Another SSL error code - in this case you must stop using
+ * the context (see below).
+ *
+ * \warning If this function returns something other than
+ * \c 0,
+ * #MBEDTLS_ERR_SSL_WANT_READ,
+ * #MBEDTLS_ERR_SSL_WANT_WRITE,
+ * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or
+ * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS,
+ * you must stop using the SSL context for reading or writing,
+ * and either free it or call \c mbedtls_ssl_session_reset()
+ * on it before re-using it for a new connection; the current
+ * connection must be closed.
*
- * If this function returns MBEDTLS_ERR_SSL_WANT_READ, the
- * handshake is unfinished and no further data is available
- * from the underlying transport. In this case, you must call
- * the function again at some later stage.
+ * \note If DTLS is in use, then you may choose to handle
+ * #MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED specially for logging
+ * purposes, as it is an expected return value rather than an
+ * actual error, but you still need to reset/free the context.
*
* \note Remarks regarding event-driven DTLS:
- * If the function returns MBEDTLS_ERR_SSL_WANT_READ, no datagram
+ * If the function returns #MBEDTLS_ERR_SSL_WANT_READ, no datagram
* from the underlying transport layer is currently being processed,
* and it is safe to idle until the timer or the underlying transport
* signal a new event. This is not true for a successful handshake,
* in which case the datagram of the underlying transport that is
* currently being processed might or might not contain further
* DTLS records.
- *
- * \note If this function returns something other than 0 or
- * MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using
- * the SSL context for reading or writing, and either free it or
- * call \c mbedtls_ssl_session_reset() on it before re-using it
- * for a new connection; the current connection must be closed.
- *
- * \note If DTLS is in use, then you may choose to handle
- * MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED specially for logging
- * purposes, as it is an expected return value rather than an
- * actual error, but you still need to reset/free the context.
*/
int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl );
@@ -2812,20 +2974,21 @@ int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl );
* \brief Perform a single step of the SSL handshake
*
* \note The state of the context (ssl->state) will be at
- * the next state after execution of this function. Do not
+ * the next state after this function returns \c 0. Do not
* call this function if state is MBEDTLS_SSL_HANDSHAKE_OVER.
*
- * \note If this function returns something other than 0 or
- * MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using
- * the SSL context for reading or writing, and either free it or
- * call \c mbedtls_ssl_session_reset() on it before re-using it
- * for a new connection; the current connection must be closed.
- *
* \param ssl SSL context
*
- * \return 0 if successful, or
- * MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or
- * a specific SSL error code.
+ * \return See mbedtls_ssl_handshake().
+ *
+ * \warning If this function returns something other than \c 0,
+ * #MBEDTLS_ERR_SSL_WANT_READ, #MBEDTLS_ERR_SSL_WANT_WRITE,
+ * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or
+ * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, you must stop using
+ * the SSL context for reading or writing, and either free it
+ * or call \c mbedtls_ssl_session_reset() on it before
+ * re-using it for a new connection; the current connection
+ * must be closed.
*/
int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl );
@@ -2840,13 +3003,18 @@ int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl );
* \param ssl SSL context
*
* \return 0 if successful, or any mbedtls_ssl_handshake() return
- * value.
+ * value except #MBEDTLS_ERR_SSL_CLIENT_RECONNECT that can't
+ * happen during a renegotiation.
+ *
+ * \warning If this function returns something other than \c 0,
+ * #MBEDTLS_ERR_SSL_WANT_READ, #MBEDTLS_ERR_SSL_WANT_WRITE,
+ * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or
+ * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, you must stop using
+ * the SSL context for reading or writing, and either free it
+ * or call \c mbedtls_ssl_session_reset() on it before
+ * re-using it for a new connection; the current connection
+ * must be closed.
*
- * \note If this function returns something other than 0 or
- * MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using
- * the SSL context for reading or writing, and either free it or
- * call \c mbedtls_ssl_session_reset() on it before re-using it
- * for a new connection; the current connection must be closed.
*/
int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl );
#endif /* MBEDTLS_SSL_RENEGOTIATION */
@@ -2858,42 +3026,56 @@ int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl );
* \param buf buffer that will hold the data
* \param len maximum number of bytes to read
*
- * \return One of the following:
- * - 0 if the read end of the underlying transport was closed,
- * - the (positive) number of bytes read, or
- * - a negative error code on failure.
- *
- * If MBEDTLS_ERR_SSL_WANT_READ is returned, no application data
- * is available from the underlying transport. In this case,
- * the function needs to be called again at some later stage.
- *
- * If MBEDTLS_ERR_SSL_WANT_WRITE is returned, a write is pending
- * but the underlying transport isn't available for writing. In this
- * case, the function needs to be called again at some later stage.
+ * \return The (positive) number of bytes read if successful.
+ * \return \c 0 if the read end of the underlying transport was closed
+ * - in this case you must stop using the context (see below).
+ * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE
+ * if the handshake is incomplete and waiting for data to
+ * be available for reading from or writing to the underlying
+ * transport - in this case you must call this function again
+ * when the underlying transport is ready for the operation.
+ * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous
+ * operation is in progress (see
+ * mbedtls_ssl_conf_async_private_cb()) - in this case you
+ * must call this function again when the operation is ready.
+ * \return #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic
+ * operation is in progress (see mbedtls_ecp_set_max_ops()) -
+ * in this case you must call this function again to complete
+ * the handshake when you're done attending other tasks.
+ * \return #MBEDTLS_ERR_SSL_CLIENT_RECONNECT if we're at the server
+ * side of a DTLS connection and the client is initiating a
+ * new connection using the same source port. See below.
+ * \return Another SSL error code - in this case you must stop using
+ * the context (see below).
+ *
+ * \warning If this function returns something other than
+ * a positive value,
+ * #MBEDTLS_ERR_SSL_WANT_READ,
+ * #MBEDTLS_ERR_SSL_WANT_WRITE,
+ * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS,
+ * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS or
+ * #MBEDTLS_ERR_SSL_CLIENT_RECONNECT,
+ * you must stop using the SSL context for reading or writing,
+ * and either free it or call \c mbedtls_ssl_session_reset()
+ * on it before re-using it for a new connection; the current
+ * connection must be closed.
*
- * When this function return MBEDTLS_ERR_SSL_CLIENT_RECONNECT
+ * \note When this function returns #MBEDTLS_ERR_SSL_CLIENT_RECONNECT
* (which can only happen server-side), it means that a client
* is initiating a new connection using the same source port.
* You can either treat that as a connection close and wait
* for the client to resend a ClientHello, or directly
* continue with \c mbedtls_ssl_handshake() with the same
- * context (as it has beeen reset internally). Either way, you
- * should make sure this is seen by the application as a new
+ * context (as it has been reset internally). Either way, you
+ * must make sure this is seen by the application as a new
* connection: application state, if any, should be reset, and
* most importantly the identity of the client must be checked
* again. WARNING: not validating the identity of the client
* again, or not transmitting the new identity to the
* application layer, would allow authentication bypass!
*
- * \note If this function returns something other than a positive value
- * or MBEDTLS_ERR_SSL_WANT_READ/WRITE or MBEDTLS_ERR_SSL_CLIENT_RECONNECT,
- * you must stop using the SSL context for reading or writing,
- * and either free it or call \c mbedtls_ssl_session_reset() on it
- * before re-using it for a new connection; the current connection
- * must be closed.
- *
* \note Remarks regarding event-driven DTLS:
- * - If the function returns MBEDTLS_ERR_SSL_WANT_READ, no datagram
+ * - If the function returns #MBEDTLS_ERR_SSL_WANT_READ, no datagram
* from the underlying transport layer is currently being processed,
* and it is safe to idle until the timer or the underlying transport
* signal a new event.
@@ -2922,21 +3104,39 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
* \param buf buffer holding the data
* \param len how many bytes must be written
*
- * \return the number of bytes actually written (may be less than len),
- * or MBEDTLS_ERR_SSL_WANT_WRITE or MBEDTLS_ERR_SSL_WANT_READ,
- * or another negative error code.
- *
- * \note If this function returns something other than 0, a positive
- * value or MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop
- * using the SSL context for reading or writing, and either
- * free it or call \c mbedtls_ssl_session_reset() on it before
- * re-using it for a new connection; the current connection
- * must be closed.
+ * \return The (non-negative) number of bytes actually written if
+ * successful (may be less than \p len).
+ * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE
+ * if the handshake is incomplete and waiting for data to
+ * be available for reading from or writing to the underlying
+ * transport - in this case you must call this function again
+ * when the underlying transport is ready for the operation.
+ * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous
+ * operation is in progress (see
+ * mbedtls_ssl_conf_async_private_cb()) - in this case you
+ * must call this function again when the operation is ready.
+ * \return #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic
+ * operation is in progress (see mbedtls_ecp_set_max_ops()) -
+ * in this case you must call this function again to complete
+ * the handshake when you're done attending other tasks.
+ * \return Another SSL error code - in this case you must stop using
+ * the context (see below).
+ *
+ * \warning If this function returns something other than
+ * a non-negative value,
+ * #MBEDTLS_ERR_SSL_WANT_READ,
+ * #MBEDTLS_ERR_SSL_WANT_WRITE,
+ * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or
+ * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS,
+ * you must stop using the SSL context for reading or writing,
+ * and either free it or call \c mbedtls_ssl_session_reset()
+ * on it before re-using it for a new connection; the current
+ * connection must be closed.
*
- * \note When this function returns MBEDTLS_ERR_SSL_WANT_WRITE/READ,
+ * \note When this function returns #MBEDTLS_ERR_SSL_WANT_WRITE/READ,
* it must be called later with the *same* arguments,
* until it returns a value greater that or equal to 0. When
- * the function returns MBEDTLS_ERR_SSL_WANT_WRITE there may be
+ * the function returns #MBEDTLS_ERR_SSL_WANT_WRITE there may be
* some partial data in the output buffer, however this is not
* yet sent.
*
diff --git a/thirdparty/mbedtls/include/mbedtls/ssl_cookie.h b/thirdparty/mbedtls/include/mbedtls/ssl_cookie.h
index 80b65bbbb9..6a0ad4fa96 100644
--- a/thirdparty/mbedtls/include/mbedtls/ssl_cookie.h
+++ b/thirdparty/mbedtls/include/mbedtls/ssl_cookie.h
@@ -50,7 +50,7 @@ extern "C" {
/**
* \brief Context for the default cookie functions.
*/
-typedef struct
+typedef struct mbedtls_ssl_cookie_ctx
{
mbedtls_md_context_t hmac_ctx; /*!< context for the HMAC portion */
#if !defined(MBEDTLS_HAVE_TIME)
diff --git a/thirdparty/mbedtls/include/mbedtls/ssl_internal.h b/thirdparty/mbedtls/include/mbedtls/ssl_internal.h
index d214703d77..97abb9f90b 100644
--- a/thirdparty/mbedtls/include/mbedtls/ssl_internal.h
+++ b/thirdparty/mbedtls/include/mbedtls/ssl_internal.h
@@ -93,6 +93,14 @@
#endif /* MBEDTLS_SSL_PROTO_TLS1_1 */
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+/* Shorthand for restartable ECC */
+#if defined(MBEDTLS_ECP_RESTARTABLE) && \
+ defined(MBEDTLS_SSL_CLI_C) && \
+ defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
+ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+#define MBEDTLS_SSL__ECP_RESTARTABLE
+#endif
+
#define MBEDTLS_SSL_INITIAL_HANDSHAKE 0
#define MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS 1 /* In progress */
#define MBEDTLS_SSL_RENEGOTIATION_DONE 2 /* Done or aborted */
@@ -155,6 +163,9 @@
#define MBEDTLS_SSL_OUT_PAYLOAD_LEN ( MBEDTLS_SSL_PAYLOAD_OVERHEAD + \
( MBEDTLS_SSL_OUT_CONTENT_LEN ) )
+/* The maximum number of buffered handshake messages. */
+#define MBEDTLS_SSL_MAX_BUFFERED_HS 4
+
/* Maximum length we can advertise as our max content length for
RFC 6066 max_fragment_length extension negotiation purposes
(the lesser of both sizes, if they are unequal.)
@@ -284,7 +295,18 @@ struct mbedtls_ssl_handshake_params
mbedtls_x509_crl *sni_ca_crl; /*!< trusted CAs CRLs from SNI */
#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
#endif /* MBEDTLS_X509_CRT_PARSE_C */
-
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ int ecrs_enabled; /*!< Handshake supports EC restart? */
+ mbedtls_x509_crt_restart_ctx ecrs_ctx; /*!< restart context */
+ enum { /* this complements ssl->state with info on intra-state operations */
+ ssl_ecrs_none = 0, /*!< nothing going on (yet) */
+ ssl_ecrs_crt_verify, /*!< Certificate: crt_verify() */
+ ssl_ecrs_ske_start_processing, /*!< ServerKeyExchange: pk_verify() */
+ ssl_ecrs_cke_ecdh_calc_secret, /*!< ClientKeyExchange: ECDH step 2 */
+ ssl_ecrs_crt_vrfy_sign, /*!< CertificateVerify: pk_sign() */
+ } ecrs_state; /*!< current (or last) operation */
+ size_t ecrs_n; /*!< place for saving a length */
+#endif
#if defined(MBEDTLS_SSL_PROTO_DTLS)
unsigned int out_msg_seq; /*!< Outgoing handshake sequence number */
unsigned int in_msg_seq; /*!< Incoming handshake sequence number */
@@ -294,18 +316,45 @@ struct mbedtls_ssl_handshake_params
unsigned char verify_cookie_len; /*!< Cli: cookie length
Srv: flag for sending a cookie */
- unsigned char *hs_msg; /*!< Reassembled handshake message */
-
uint32_t retransmit_timeout; /*!< Current value of timeout */
unsigned char retransmit_state; /*!< Retransmission state */
- mbedtls_ssl_flight_item *flight; /*!< Current outgoing flight */
- mbedtls_ssl_flight_item *cur_msg; /*!< Current message in flight */
+ mbedtls_ssl_flight_item *flight; /*!< Current outgoing flight */
+ mbedtls_ssl_flight_item *cur_msg; /*!< Current message in flight */
+ unsigned char *cur_msg_p; /*!< Position in current message */
unsigned int in_flight_start_seq; /*!< Minimum message sequence in the
flight being received */
mbedtls_ssl_transform *alt_transform_out; /*!< Alternative transform for
resending messages */
unsigned char alt_out_ctr[8]; /*!< Alternative record epoch/counter
for resending messages */
+
+ struct
+ {
+ size_t total_bytes_buffered; /*!< Cumulative size of heap allocated
+ * buffers used for message buffering. */
+
+ uint8_t seen_ccs; /*!< Indicates if a CCS message has
+ * been seen in the current flight. */
+
+ struct mbedtls_ssl_hs_buffer
+ {
+ unsigned is_valid : 1;
+ unsigned is_fragmented : 1;
+ unsigned is_complete : 1;
+ unsigned char *data;
+ size_t data_len;
+ } hs[MBEDTLS_SSL_MAX_BUFFERED_HS];
+
+ struct
+ {
+ unsigned char *data;
+ size_t len;
+ unsigned epoch;
+ } future_record;
+
+ } buffering;
+
+ uint16_t mtu; /*!< Handshake mtu, used to fragment outgoing messages */
#endif /* MBEDTLS_SSL_PROTO_DTLS */
/*
@@ -364,6 +413,8 @@ struct mbedtls_ssl_handshake_params
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
};
+typedef struct mbedtls_ssl_hs_buffer mbedtls_ssl_hs_buffer;
+
/*
* This structure contains a full set of runtime transform parameters
* either in negotiation or active.
@@ -478,7 +529,6 @@ int mbedtls_ssl_send_fatal_handshake_failure( mbedtls_ssl_context *ssl );
void mbedtls_ssl_reset_checksum( mbedtls_ssl_context *ssl );
int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl );
-int mbedtls_ssl_read_record_layer( mbedtls_ssl_context *ssl );
int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl );
int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl );
void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl );
@@ -490,7 +540,10 @@ void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl );
* of the logic of (D)TLS from the implementation
* of the secure transport.
*
- * \param ssl SSL context to use
+ * \param ssl The SSL context to use.
+ * \param update_hs_digest This indicates if the handshake digest
+ * should be automatically updated in case
+ * a handshake message is found.
*
* \return 0 or non-zero error code.
*
@@ -556,10 +609,12 @@ void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl );
* following the above definition.
*
*/
-int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl );
+int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl,
+ unsigned update_hs_digest );
int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want );
-int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl );
+int mbedtls_ssl_write_handshake_msg( mbedtls_ssl_context *ssl );
+int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl, uint8_t force_flush );
int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl );
int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl );
@@ -668,6 +723,7 @@ static inline size_t mbedtls_ssl_hs_hdr_len( const mbedtls_ssl_context *ssl )
void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl );
void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl );
int mbedtls_ssl_resend( mbedtls_ssl_context *ssl );
+int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl );
#endif
/* Visible for testing purposes only */
diff --git a/thirdparty/mbedtls/include/mbedtls/ssl_ticket.h b/thirdparty/mbedtls/include/mbedtls/ssl_ticket.h
index 93ad46ac9c..b2686df09f 100644
--- a/thirdparty/mbedtls/include/mbedtls/ssl_ticket.h
+++ b/thirdparty/mbedtls/include/mbedtls/ssl_ticket.h
@@ -44,7 +44,7 @@ extern "C" {
/**
* \brief Information for session ticket protection
*/
-typedef struct
+typedef struct mbedtls_ssl_ticket_key
{
unsigned char name[4]; /*!< random key identifier */
uint32_t generation_time; /*!< key generation timestamp (seconds) */
@@ -55,7 +55,7 @@ mbedtls_ssl_ticket_key;
/**
* \brief Context for session ticket handling functions
*/
-typedef struct
+typedef struct mbedtls_ssl_ticket_context
{
mbedtls_ssl_ticket_key keys[2]; /*!< ticket protection keys */
unsigned char active; /*!< index of the currently active key */
diff --git a/thirdparty/mbedtls/include/mbedtls/threading.h b/thirdparty/mbedtls/include/mbedtls/threading.h
index c25daa5cdf..92e6e6b987 100644
--- a/thirdparty/mbedtls/include/mbedtls/threading.h
+++ b/thirdparty/mbedtls/include/mbedtls/threading.h
@@ -36,13 +36,16 @@
extern "C" {
#endif
+/* MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE is deprecated and should not be
+ * used. */
#define MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE -0x001A /**< The selected feature is not available. */
+
#define MBEDTLS_ERR_THREADING_BAD_INPUT_DATA -0x001C /**< Bad input parameters to function. */
#define MBEDTLS_ERR_THREADING_MUTEX_ERROR -0x001E /**< Locking / unlocking / free failed with error code. */
#if defined(MBEDTLS_THREADING_PTHREAD)
#include <pthread.h>
-typedef struct
+typedef struct mbedtls_threading_mutex_t
{
pthread_mutex_t mutex;
char is_valid;
@@ -99,6 +102,17 @@ extern int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t *mutex );
#if defined(MBEDTLS_FS_IO)
extern mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex;
#endif
+
+#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT)
+/* This mutex may or may not be used in the default definition of
+ * mbedtls_platform_gmtime_r(), but in order to determine that,
+ * we need to check POSIX features, hence modify _POSIX_C_SOURCE.
+ * With the current approach, this declaration is orphaned, lacking
+ * an accompanying definition, in case mbedtls_platform_gmtime_r()
+ * doesn't need it, but that's not a problem. */
+extern mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex;
+#endif /* MBEDTLS_HAVE_TIME_DATE && !MBEDTLS_PLATFORM_GMTIME_R_ALT */
+
#endif /* MBEDTLS_THREADING_C */
#ifdef __cplusplus
diff --git a/thirdparty/mbedtls/include/mbedtls/timing.h b/thirdparty/mbedtls/include/mbedtls/timing.h
index bbcb90688a..a965fe0d35 100644
--- a/thirdparty/mbedtls/include/mbedtls/timing.h
+++ b/thirdparty/mbedtls/include/mbedtls/timing.h
@@ -51,7 +51,7 @@ struct mbedtls_timing_hr_time
/**
* \brief Context for mbedtls_timing_set/get_delay()
*/
-typedef struct
+typedef struct mbedtls_timing_delay_context
{
struct mbedtls_timing_hr_time timer;
uint32_t int_ms;
diff --git a/thirdparty/mbedtls/include/mbedtls/version.h b/thirdparty/mbedtls/include/mbedtls/version.h
index eaf25d908c..56e7398a2a 100644
--- a/thirdparty/mbedtls/include/mbedtls/version.h
+++ b/thirdparty/mbedtls/include/mbedtls/version.h
@@ -39,7 +39,7 @@
* Major, Minor, Patchlevel
*/
#define MBEDTLS_VERSION_MAJOR 2
-#define MBEDTLS_VERSION_MINOR 12
+#define MBEDTLS_VERSION_MINOR 16
#define MBEDTLS_VERSION_PATCH 0
/**
@@ -47,9 +47,9 @@
* MMNNPP00
* Major version | Minor version | Patch version
*/
-#define MBEDTLS_VERSION_NUMBER 0x020C0000
-#define MBEDTLS_VERSION_STRING "2.12.0"
-#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.12.0"
+#define MBEDTLS_VERSION_NUMBER 0x02100000
+#define MBEDTLS_VERSION_STRING "2.16.0"
+#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.16.0"
#if defined(MBEDTLS_VERSION_C)
diff --git a/thirdparty/mbedtls/include/mbedtls/x509_crt.h b/thirdparty/mbedtls/include/mbedtls/x509_crt.h
index ac23cffe84..3dd5922486 100644
--- a/thirdparty/mbedtls/include/mbedtls/x509_crt.h
+++ b/thirdparty/mbedtls/include/mbedtls/x509_crt.h
@@ -105,7 +105,7 @@ mbedtls_x509_crt;
*
* All lists are bitfields, built by ORing flags from MBEDTLS_X509_ID_FLAG().
*/
-typedef struct
+typedef struct mbedtls_x509_crt_profile
{
uint32_t allowed_mds; /**< MDs for signatures */
uint32_t allowed_pks; /**< PK algs for signatures */
@@ -143,6 +143,63 @@ typedef struct mbedtls_x509write_cert
}
mbedtls_x509write_cert;
+/**
+ * Item in a verification chain: cert and flags for it
+ */
+typedef struct {
+ mbedtls_x509_crt *crt;
+ uint32_t flags;
+} mbedtls_x509_crt_verify_chain_item;
+
+/**
+ * Max size of verification chain: end-entity + intermediates + trusted root
+ */
+#define MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE ( MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2 )
+
+/**
+ * Verification chain as built by \c mbedtls_crt_verify_chain()
+ */
+typedef struct
+{
+ mbedtls_x509_crt_verify_chain_item items[MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE];
+ unsigned len;
+} mbedtls_x509_crt_verify_chain;
+
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+
+/**
+ * \brief Context for resuming X.509 verify operations
+ */
+typedef struct
+{
+ /* for check_signature() */
+ mbedtls_pk_restart_ctx pk;
+
+ /* for find_parent_in() */
+ mbedtls_x509_crt *parent; /* non-null iff parent_in in progress */
+ mbedtls_x509_crt *fallback_parent;
+ int fallback_signature_is_good;
+
+ /* for find_parent() */
+ int parent_is_trusted; /* -1 if find_parent is not in progress */
+
+ /* for verify_chain() */
+ enum {
+ x509_crt_rs_none,
+ x509_crt_rs_find_parent,
+ } in_progress; /* none if no operation is in progress */
+ int self_cnt;
+ mbedtls_x509_crt_verify_chain ver_chain;
+
+} mbedtls_x509_crt_restart_ctx;
+
+#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+
+/* Now we can declare functions that take a pointer to that */
+typedef void mbedtls_x509_crt_restart_ctx;
+
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+
#if defined(MBEDTLS_X509_CRT_PARSE_C)
/**
* Default security profile. Should provide a good balance between security
@@ -175,19 +232,34 @@ int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, const unsigned char *bu
size_t buflen );
/**
- * \brief Parse one or more certificates and add them
- * to the chained list. Parses permissively. If some
- * certificates can be parsed, the result is the number
- * of failed certificates it encountered. If none complete
- * correctly, the first error is returned.
+ * \brief Parse one DER-encoded or one or more concatenated PEM-encoded
+ * certificates and add them to the chained list.
*
- * \param chain points to the start of the chain
- * \param buf buffer holding the certificate data in PEM or DER format
- * \param buflen size of the buffer
- * (including the terminating null byte for PEM data)
+ * For CRTs in PEM encoding, the function parses permissively:
+ * if at least one certificate can be parsed, the function
+ * returns the number of certificates for which parsing failed
+ * (hence \c 0 if all certificates were parsed successfully).
+ * If no certificate could be parsed, the function returns
+ * the first (negative) error encountered during parsing.
+ *
+ * PEM encoded certificates may be interleaved by other data
+ * such as human readable descriptions of their content, as
+ * long as the certificates are enclosed in the PEM specific
+ * '-----{BEGIN/END} CERTIFICATE-----' delimiters.
+ *
+ * \param chain The chain to which to add the parsed certificates.
+ * \param buf The buffer holding the certificate data in PEM or DER format.
+ * For certificates in PEM encoding, this may be a concatenation
+ * of multiple certificates; for DER encoding, the buffer must
+ * comprise exactly one certificate.
+ * \param buflen The size of \p buf, including the terminating \c NULL byte
+ * in case of PEM encoded data.
+ *
+ * \return \c 0 if all certificates were parsed successfully.
+ * \return The (positive) number of certificates that couldn't
+ * be parsed if parsing was partly successful (see above).
+ * \return A negative X509 or PEM error code otherwise.
*
- * \return 0 if all certificates parsed successfully, a positive number
- * if partly successful or a specific X509 or PEM error code
*/
int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen );
@@ -353,6 +425,37 @@ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt,
int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
void *p_vrfy );
+/**
+ * \brief Restartable version of \c mbedtls_crt_verify_with_profile()
+ *
+ * \note Performs the same job as \c mbedtls_crt_verify_with_profile()
+ * but can return early and restart according to the limit
+ * set with \c mbedtls_ecp_set_max_ops() to reduce blocking.
+ *
+ * \param crt a certificate (chain) to be verified
+ * \param trust_ca the list of trusted CAs
+ * \param ca_crl the list of CRLs for trusted CAs
+ * \param profile security profile for verification
+ * \param cn expected Common Name (can be set to
+ * NULL if the CN must not be verified)
+ * \param flags result of the verification
+ * \param f_vrfy verification function
+ * \param p_vrfy verification parameter
+ * \param rs_ctx restart context (NULL to disable restart)
+ *
+ * \return See \c mbedtls_crt_verify_with_profile(), or
+ * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
+ * operations was reached: see \c mbedtls_ecp_set_max_ops().
+ */
+int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt,
+ mbedtls_x509_crt *trust_ca,
+ mbedtls_x509_crl *ca_crl,
+ const mbedtls_x509_crt_profile *profile,
+ const char *cn, uint32_t *flags,
+ int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
+ void *p_vrfy,
+ mbedtls_x509_crt_restart_ctx *rs_ctx );
+
#if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
/**
* \brief Check usage of certificate against keyUsage extension.
@@ -424,6 +527,18 @@ void mbedtls_x509_crt_init( mbedtls_x509_crt *crt );
* \param crt Certificate chain to free
*/
void mbedtls_x509_crt_free( mbedtls_x509_crt *crt );
+
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+/**
+ * \brief Initialize a restart context
+ */
+void mbedtls_x509_crt_restart_init( mbedtls_x509_crt_restart_ctx *ctx );
+
+/**
+ * \brief Free the components of a restart context
+ */
+void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx );
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
#endif /* MBEDTLS_X509_CRT_PARSE_C */
/* \} name */
diff --git a/thirdparty/mbedtls/include/mbedtls/xtea.h b/thirdparty/mbedtls/include/mbedtls/xtea.h
index 8df708a3a5..6430c1318a 100644
--- a/thirdparty/mbedtls/include/mbedtls/xtea.h
+++ b/thirdparty/mbedtls/include/mbedtls/xtea.h
@@ -37,6 +37,8 @@
#define MBEDTLS_XTEA_DECRYPT 0
#define MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH -0x0028 /**< The data input has an invalid length. */
+
+/* MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED -0x0029 /**< XTEA hardware accelerator failed. */
#ifdef __cplusplus
@@ -50,7 +52,7 @@ extern "C" {
/**
* \brief XTEA context structure
*/
-typedef struct
+typedef struct mbedtls_xtea_context
{
uint32_t k[4]; /*!< key */
}
diff --git a/thirdparty/mbedtls/library/aes.c b/thirdparty/mbedtls/library/aes.c
index 5c939bba47..0543cd7817 100644
--- a/thirdparty/mbedtls/library/aes.c
+++ b/thirdparty/mbedtls/library/aes.c
@@ -36,6 +36,7 @@
#include <string.h>
#include "mbedtls/aes.h"
+#include "mbedtls/platform.h"
#include "mbedtls/platform_util.h"
#if defined(MBEDTLS_PADLOCK_C)
#include "mbedtls/padlock.h"
@@ -55,6 +56,12 @@
#if !defined(MBEDTLS_AES_ALT)
+/* Parameter validation macros based on platform_util.h */
+#define AES_VALIDATE_RET( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_AES_BAD_INPUT_DATA )
+#define AES_VALIDATE( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE( cond )
+
/*
* 32-bit integer manipulation macros (little endian)
*/
@@ -510,6 +517,8 @@ static void aes_gen_tables( void )
void mbedtls_aes_init( mbedtls_aes_context *ctx )
{
+ AES_VALIDATE( ctx != NULL );
+
memset( ctx, 0, sizeof( mbedtls_aes_context ) );
}
@@ -524,12 +533,17 @@ void mbedtls_aes_free( mbedtls_aes_context *ctx )
#if defined(MBEDTLS_CIPHER_MODE_XTS)
void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx )
{
+ AES_VALIDATE( ctx != NULL );
+
mbedtls_aes_init( &ctx->crypt );
mbedtls_aes_init( &ctx->tweak );
}
void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx )
{
+ if( ctx == NULL )
+ return;
+
mbedtls_aes_free( &ctx->crypt );
mbedtls_aes_free( &ctx->tweak );
}
@@ -545,14 +559,8 @@ int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key,
unsigned int i;
uint32_t *RK;
-#if !defined(MBEDTLS_AES_ROM_TABLES)
- if( aes_init_done == 0 )
- {
- aes_gen_tables();
- aes_init_done = 1;
-
- }
-#endif
+ AES_VALIDATE_RET( ctx != NULL );
+ AES_VALIDATE_RET( key != NULL );
switch( keybits )
{
@@ -562,6 +570,14 @@ int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key,
default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
}
+#if !defined(MBEDTLS_AES_ROM_TABLES)
+ if( aes_init_done == 0 )
+ {
+ aes_gen_tables();
+ aes_init_done = 1;
+ }
+#endif
+
#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16)
if( aes_padlock_ace == -1 )
aes_padlock_ace = mbedtls_padlock_has_support( MBEDTLS_PADLOCK_ACE );
@@ -661,6 +677,9 @@ int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key,
uint32_t *RK;
uint32_t *SK;
+ AES_VALIDATE_RET( ctx != NULL );
+ AES_VALIDATE_RET( key != NULL );
+
mbedtls_aes_init( &cty );
#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16)
@@ -751,6 +770,9 @@ int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx,
const unsigned char *key1, *key2;
unsigned int key1bits, key2bits;
+ AES_VALIDATE_RET( ctx != NULL );
+ AES_VALIDATE_RET( key != NULL );
+
ret = mbedtls_aes_xts_decode_keys( key, keybits, &key1, &key1bits,
&key2, &key2bits );
if( ret != 0 )
@@ -773,6 +795,9 @@ int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx,
const unsigned char *key1, *key2;
unsigned int key1bits, key2bits;
+ AES_VALIDATE_RET( ctx != NULL );
+ AES_VALIDATE_RET( key != NULL );
+
ret = mbedtls_aes_xts_decode_keys( key, keybits, &key1, &key1bits,
&key2, &key2bits );
if( ret != 0 )
@@ -976,10 +1001,16 @@ void mbedtls_aes_decrypt( mbedtls_aes_context *ctx,
* AES-ECB block encryption/decryption
*/
int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
- int mode,
- const unsigned char input[16],
- unsigned char output[16] )
+ int mode,
+ const unsigned char input[16],
+ unsigned char output[16] )
{
+ AES_VALIDATE_RET( ctx != NULL );
+ AES_VALIDATE_RET( input != NULL );
+ AES_VALIDATE_RET( output != NULL );
+ AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT ||
+ mode == MBEDTLS_AES_DECRYPT );
+
#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) )
return( mbedtls_aesni_crypt_ecb( ctx, mode, input, output ) );
@@ -1017,6 +1048,13 @@ int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx,
int i;
unsigned char temp[16];
+ AES_VALIDATE_RET( ctx != NULL );
+ AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT ||
+ mode == MBEDTLS_AES_DECRYPT );
+ AES_VALIDATE_RET( iv != NULL );
+ AES_VALIDATE_RET( input != NULL );
+ AES_VALIDATE_RET( output != NULL );
+
if( length % 16 )
return( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH );
@@ -1142,11 +1180,18 @@ int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx,
unsigned char prev_tweak[16];
unsigned char tmp[16];
- /* Sectors must be at least 16 bytes. */
+ AES_VALIDATE_RET( ctx != NULL );
+ AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT ||
+ mode == MBEDTLS_AES_DECRYPT );
+ AES_VALIDATE_RET( data_unit != NULL );
+ AES_VALIDATE_RET( input != NULL );
+ AES_VALIDATE_RET( output != NULL );
+
+ /* Data units must be at least 16 bytes long. */
if( length < 16 )
return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
- /* NIST SP 80-38E disallows data units larger than 2**20 blocks. */
+ /* NIST SP 800-38E disallows data units larger than 2**20 blocks. */
if( length > ( 1 << 20 ) * 16 )
return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
@@ -1241,7 +1286,20 @@ int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx,
unsigned char *output )
{
int c;
- size_t n = *iv_off;
+ size_t n;
+
+ AES_VALIDATE_RET( ctx != NULL );
+ AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT ||
+ mode == MBEDTLS_AES_DECRYPT );
+ AES_VALIDATE_RET( iv_off != NULL );
+ AES_VALIDATE_RET( iv != NULL );
+ AES_VALIDATE_RET( input != NULL );
+ AES_VALIDATE_RET( output != NULL );
+
+ n = *iv_off;
+
+ if( n > 15 )
+ return( MBEDTLS_ERR_AES_BAD_INPUT_DATA );
if( mode == MBEDTLS_AES_DECRYPT )
{
@@ -1279,15 +1337,21 @@ int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx,
* AES-CFB8 buffer encryption/decryption
*/
int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx,
- int mode,
- size_t length,
- unsigned char iv[16],
- const unsigned char *input,
- unsigned char *output )
+ int mode,
+ size_t length,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output )
{
unsigned char c;
unsigned char ov[17];
+ AES_VALIDATE_RET( ctx != NULL );
+ AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT ||
+ mode == MBEDTLS_AES_DECRYPT );
+ AES_VALIDATE_RET( iv != NULL );
+ AES_VALIDATE_RET( input != NULL );
+ AES_VALIDATE_RET( output != NULL );
while( length-- )
{
memcpy( ov, iv, 16 );
@@ -1320,7 +1384,18 @@ int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx,
unsigned char *output )
{
int ret = 0;
- size_t n = *iv_off;
+ size_t n;
+
+ AES_VALIDATE_RET( ctx != NULL );
+ AES_VALIDATE_RET( iv_off != NULL );
+ AES_VALIDATE_RET( iv != NULL );
+ AES_VALIDATE_RET( input != NULL );
+ AES_VALIDATE_RET( output != NULL );
+
+ n = *iv_off;
+
+ if( n > 15 )
+ return( MBEDTLS_ERR_AES_BAD_INPUT_DATA );
while( length-- )
{
@@ -1355,7 +1430,16 @@ int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx,
unsigned char *output )
{
int c, i;
- size_t n = *nc_off;
+ size_t n;
+
+ AES_VALIDATE_RET( ctx != NULL );
+ AES_VALIDATE_RET( nc_off != NULL );
+ AES_VALIDATE_RET( nonce_counter != NULL );
+ AES_VALIDATE_RET( stream_block != NULL );
+ AES_VALIDATE_RET( input != NULL );
+ AES_VALIDATE_RET( output != NULL );
+
+ n = *nc_off;
if ( n > 0x0F )
return( MBEDTLS_ERR_AES_BAD_INPUT_DATA );
@@ -1757,7 +1841,7 @@ int mbedtls_aes_self_test( int verbose )
* there is an alternative underlying implementation i.e. when
* MBEDTLS_AES_ALT is defined.
*/
- if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 )
+ if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 )
{
mbedtls_printf( "skipped\n" );
continue;
@@ -1821,7 +1905,7 @@ int mbedtls_aes_self_test( int verbose )
* there is an alternative underlying implementation i.e. when
* MBEDTLS_AES_ALT is defined.
*/
- if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 )
+ if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 )
{
mbedtls_printf( "skipped\n" );
continue;
@@ -1886,7 +1970,7 @@ int mbedtls_aes_self_test( int verbose )
* there is an alternative underlying implementation i.e. when
* MBEDTLS_AES_ALT is defined.
*/
- if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 )
+ if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 )
{
mbedtls_printf( "skipped\n" );
continue;
@@ -1949,7 +2033,7 @@ int mbedtls_aes_self_test( int verbose )
* there is an alternative underlying implementation i.e. when
* MBEDTLS_AES_ALT is defined.
*/
- if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 )
+ if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 )
{
mbedtls_printf( "skipped\n" );
continue;
diff --git a/thirdparty/mbedtls/library/aria.c b/thirdparty/mbedtls/library/aria.c
index e9bcd6d135..aff66d667f 100644
--- a/thirdparty/mbedtls/library/aria.c
+++ b/thirdparty/mbedtls/library/aria.c
@@ -55,6 +55,12 @@
#define inline __inline
#endif
+/* Parameter validation macros */
+#define ARIA_VALIDATE_RET( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ARIA_BAD_INPUT_DATA )
+#define ARIA_VALIDATE( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE( cond )
+
/*
* 32-bit integer manipulation macros (little endian)
*/
@@ -449,9 +455,11 @@ int mbedtls_aria_setkey_enc( mbedtls_aria_context *ctx,
int i;
uint32_t w[4][4], *w2;
+ ARIA_VALIDATE_RET( ctx != NULL );
+ ARIA_VALIDATE_RET( key != NULL );
if( keybits != 128 && keybits != 192 && keybits != 256 )
- return( MBEDTLS_ERR_ARIA_INVALID_KEY_LENGTH );
+ return( MBEDTLS_ERR_ARIA_BAD_INPUT_DATA );
/* Copy key to W0 (and potential remainder to W1) */
GET_UINT32_LE( w[0][0], key, 0 );
@@ -503,6 +511,8 @@ int mbedtls_aria_setkey_dec( mbedtls_aria_context *ctx,
const unsigned char *key, unsigned int keybits )
{
int i, j, k, ret;
+ ARIA_VALIDATE_RET( ctx != NULL );
+ ARIA_VALIDATE_RET( key != NULL );
ret = mbedtls_aria_setkey_enc( ctx, key, keybits );
if( ret != 0 )
@@ -539,6 +549,9 @@ int mbedtls_aria_crypt_ecb( mbedtls_aria_context *ctx,
int i;
uint32_t a, b, c, d;
+ ARIA_VALIDATE_RET( ctx != NULL );
+ ARIA_VALIDATE_RET( input != NULL );
+ ARIA_VALIDATE_RET( output != NULL );
GET_UINT32_LE( a, input, 0 );
GET_UINT32_LE( b, input, 4 );
@@ -586,6 +599,7 @@ int mbedtls_aria_crypt_ecb( mbedtls_aria_context *ctx,
/* Initialize context */
void mbedtls_aria_init( mbedtls_aria_context *ctx )
{
+ ARIA_VALIDATE( ctx != NULL );
memset( ctx, 0, sizeof( mbedtls_aria_context ) );
}
@@ -612,6 +626,13 @@ int mbedtls_aria_crypt_cbc( mbedtls_aria_context *ctx,
int i;
unsigned char temp[MBEDTLS_ARIA_BLOCKSIZE];
+ ARIA_VALIDATE_RET( ctx != NULL );
+ ARIA_VALIDATE_RET( mode == MBEDTLS_ARIA_ENCRYPT ||
+ mode == MBEDTLS_ARIA_DECRYPT );
+ ARIA_VALIDATE_RET( length == 0 || input != NULL );
+ ARIA_VALIDATE_RET( length == 0 || output != NULL );
+ ARIA_VALIDATE_RET( iv != NULL );
+
if( length % MBEDTLS_ARIA_BLOCKSIZE )
return( MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH );
@@ -665,7 +686,23 @@ int mbedtls_aria_crypt_cfb128( mbedtls_aria_context *ctx,
unsigned char *output )
{
unsigned char c;
- size_t n = *iv_off;
+ size_t n;
+
+ ARIA_VALIDATE_RET( ctx != NULL );
+ ARIA_VALIDATE_RET( mode == MBEDTLS_ARIA_ENCRYPT ||
+ mode == MBEDTLS_ARIA_DECRYPT );
+ ARIA_VALIDATE_RET( length == 0 || input != NULL );
+ ARIA_VALIDATE_RET( length == 0 || output != NULL );
+ ARIA_VALIDATE_RET( iv != NULL );
+ ARIA_VALIDATE_RET( iv_off != NULL );
+
+ n = *iv_off;
+
+ /* An overly large value of n can lead to an unlimited
+ * buffer overflow. Therefore, guard against this
+ * outside of parameter validation. */
+ if( n >= MBEDTLS_ARIA_BLOCKSIZE )
+ return( MBEDTLS_ERR_ARIA_BAD_INPUT_DATA );
if( mode == MBEDTLS_ARIA_DECRYPT )
{
@@ -713,7 +750,21 @@ int mbedtls_aria_crypt_ctr( mbedtls_aria_context *ctx,
unsigned char *output )
{
int c, i;
- size_t n = *nc_off;
+ size_t n;
+
+ ARIA_VALIDATE_RET( ctx != NULL );
+ ARIA_VALIDATE_RET( length == 0 || input != NULL );
+ ARIA_VALIDATE_RET( length == 0 || output != NULL );
+ ARIA_VALIDATE_RET( nonce_counter != NULL );
+ ARIA_VALIDATE_RET( stream_block != NULL );
+ ARIA_VALIDATE_RET( nc_off != NULL );
+
+ n = *nc_off;
+ /* An overly large value of n can lead to an unlimited
+ * buffer overflow. Therefore, guard against this
+ * outside of parameter validation. */
+ if( n >= MBEDTLS_ARIA_BLOCKSIZE )
+ return( MBEDTLS_ERR_ARIA_BAD_INPUT_DATA );
while( length-- )
{
@@ -875,11 +926,11 @@ static const uint8_t aria_test2_ctr_ct[3][48] = // CTR ciphertext
#define ARIA_SELF_TEST_IF_FAIL \
{ \
if( verbose ) \
- printf( "failed\n" ); \
+ mbedtls_printf( "failed\n" ); \
return( 1 ); \
} else { \
if( verbose ) \
- printf( "passed\n" ); \
+ mbedtls_printf( "passed\n" ); \
}
/*
@@ -908,7 +959,7 @@ int mbedtls_aria_self_test( int verbose )
{
/* test ECB encryption */
if( verbose )
- printf( " ARIA-ECB-%d (enc): ", 128 + 64 * i );
+ mbedtls_printf( " ARIA-ECB-%d (enc): ", 128 + 64 * i );
mbedtls_aria_setkey_enc( &ctx, aria_test1_ecb_key, 128 + 64 * i );
mbedtls_aria_crypt_ecb( &ctx, aria_test1_ecb_pt, blk );
if( memcmp( blk, aria_test1_ecb_ct[i], MBEDTLS_ARIA_BLOCKSIZE ) != 0 )
@@ -916,14 +967,14 @@ int mbedtls_aria_self_test( int verbose )
/* test ECB decryption */
if( verbose )
- printf( " ARIA-ECB-%d (dec): ", 128 + 64 * i );
+ mbedtls_printf( " ARIA-ECB-%d (dec): ", 128 + 64 * i );
mbedtls_aria_setkey_dec( &ctx, aria_test1_ecb_key, 128 + 64 * i );
mbedtls_aria_crypt_ecb( &ctx, aria_test1_ecb_ct[i], blk );
if( memcmp( blk, aria_test1_ecb_pt, MBEDTLS_ARIA_BLOCKSIZE ) != 0 )
ARIA_SELF_TEST_IF_FAIL;
}
if( verbose )
- printf( "\n" );
+ mbedtls_printf( "\n" );
/*
* Test set 2
@@ -933,7 +984,7 @@ int mbedtls_aria_self_test( int verbose )
{
/* Test CBC encryption */
if( verbose )
- printf( " ARIA-CBC-%d (enc): ", 128 + 64 * i );
+ mbedtls_printf( " ARIA-CBC-%d (enc): ", 128 + 64 * i );
mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i );
memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE );
memset( buf, 0x55, sizeof( buf ) );
@@ -944,7 +995,7 @@ int mbedtls_aria_self_test( int verbose )
/* Test CBC decryption */
if( verbose )
- printf( " ARIA-CBC-%d (dec): ", 128 + 64 * i );
+ mbedtls_printf( " ARIA-CBC-%d (dec): ", 128 + 64 * i );
mbedtls_aria_setkey_dec( &ctx, aria_test2_key, 128 + 64 * i );
memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE );
memset( buf, 0xAA, sizeof( buf ) );
@@ -954,7 +1005,7 @@ int mbedtls_aria_self_test( int verbose )
ARIA_SELF_TEST_IF_FAIL;
}
if( verbose )
- printf( "\n" );
+ mbedtls_printf( "\n" );
#endif /* MBEDTLS_CIPHER_MODE_CBC */
@@ -963,7 +1014,7 @@ int mbedtls_aria_self_test( int verbose )
{
/* Test CFB encryption */
if( verbose )
- printf( " ARIA-CFB-%d (enc): ", 128 + 64 * i );
+ mbedtls_printf( " ARIA-CFB-%d (enc): ", 128 + 64 * i );
mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i );
memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE );
memset( buf, 0x55, sizeof( buf ) );
@@ -975,7 +1026,7 @@ int mbedtls_aria_self_test( int verbose )
/* Test CFB decryption */
if( verbose )
- printf( " ARIA-CFB-%d (dec): ", 128 + 64 * i );
+ mbedtls_printf( " ARIA-CFB-%d (dec): ", 128 + 64 * i );
mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i );
memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE );
memset( buf, 0xAA, sizeof( buf ) );
@@ -986,7 +1037,7 @@ int mbedtls_aria_self_test( int verbose )
ARIA_SELF_TEST_IF_FAIL;
}
if( verbose )
- printf( "\n" );
+ mbedtls_printf( "\n" );
#endif /* MBEDTLS_CIPHER_MODE_CFB */
#if defined(MBEDTLS_CIPHER_MODE_CTR)
@@ -994,7 +1045,7 @@ int mbedtls_aria_self_test( int verbose )
{
/* Test CTR encryption */
if( verbose )
- printf( " ARIA-CTR-%d (enc): ", 128 + 64 * i );
+ mbedtls_printf( " ARIA-CTR-%d (enc): ", 128 + 64 * i );
mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i );
memset( iv, 0, MBEDTLS_ARIA_BLOCKSIZE ); // IV = 0
memset( buf, 0x55, sizeof( buf ) );
@@ -1006,7 +1057,7 @@ int mbedtls_aria_self_test( int verbose )
/* Test CTR decryption */
if( verbose )
- printf( " ARIA-CTR-%d (dec): ", 128 + 64 * i );
+ mbedtls_printf( " ARIA-CTR-%d (dec): ", 128 + 64 * i );
mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i );
memset( iv, 0, MBEDTLS_ARIA_BLOCKSIZE ); // IV = 0
memset( buf, 0xAA, sizeof( buf ) );
@@ -1017,7 +1068,7 @@ int mbedtls_aria_self_test( int verbose )
ARIA_SELF_TEST_IF_FAIL;
}
if( verbose )
- printf( "\n" );
+ mbedtls_printf( "\n" );
#endif /* MBEDTLS_CIPHER_MODE_CTR */
return( 0 );
diff --git a/thirdparty/mbedtls/library/asn1write.c b/thirdparty/mbedtls/library/asn1write.c
index 72acdf3012..a4d23f6196 100644
--- a/thirdparty/mbedtls/library/asn1write.c
+++ b/thirdparty/mbedtls/library/asn1write.c
@@ -257,34 +257,37 @@ int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val )
return( (int) len );
}
-int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start,
- const char *text, size_t text_len )
+int mbedtls_asn1_write_tagged_string( unsigned char **p, unsigned char *start, int tag,
+ const char *text, size_t text_len )
{
int ret;
size_t len = 0;
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
- (const unsigned char *) text, text_len ) );
+ (const unsigned char *) text, text_len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_PRINTABLE_STRING ) );
+ MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, tag ) );
return( (int) len );
}
-int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start,
- const char *text, size_t text_len )
+int mbedtls_asn1_write_utf8_string( unsigned char **p, unsigned char *start,
+ const char *text, size_t text_len )
{
- int ret;
- size_t len = 0;
-
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
- (const unsigned char *) text, text_len ) );
+ return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_UTF8_STRING, text, text_len) );
+}
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_IA5_STRING ) );
+int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start,
+ const char *text, size_t text_len )
+{
+ return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_PRINTABLE_STRING, text, text_len) );
+}
- return( (int) len );
+int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start,
+ const char *text, size_t text_len )
+{
+ return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_IA5_STRING, text, text_len) );
}
int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start,
@@ -328,14 +331,36 @@ int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start,
return( (int) len );
}
-mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( mbedtls_asn1_named_data **head,
+
+/* This is a copy of the ASN.1 parsing function mbedtls_asn1_find_named_data(),
+ * which is replicated to avoid a dependency ASN1_WRITE_C on ASN1_PARSE_C. */
+static mbedtls_asn1_named_data *asn1_find_named_data(
+ mbedtls_asn1_named_data *list,
+ const char *oid, size_t len )
+{
+ while( list != NULL )
+ {
+ if( list->oid.len == len &&
+ memcmp( list->oid.p, oid, len ) == 0 )
+ {
+ break;
+ }
+
+ list = list->next;
+ }
+
+ return( list );
+}
+
+mbedtls_asn1_named_data *mbedtls_asn1_store_named_data(
+ mbedtls_asn1_named_data **head,
const char *oid, size_t oid_len,
const unsigned char *val,
size_t val_len )
{
mbedtls_asn1_named_data *cur;
- if( ( cur = mbedtls_asn1_find_named_data( *head, oid, oid_len ) ) == NULL )
+ if( ( cur = asn1_find_named_data( *head, oid, oid_len ) ) == NULL )
{
// Add new entry if not present yet based on OID
//
diff --git a/thirdparty/mbedtls/library/bignum.c b/thirdparty/mbedtls/library/bignum.c
index 423e375fd1..f968a0ad7d 100644
--- a/thirdparty/mbedtls/library/bignum.c
+++ b/thirdparty/mbedtls/library/bignum.c
@@ -59,6 +59,11 @@
#define mbedtls_free free
#endif
+#define MPI_VALIDATE_RET( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA )
+#define MPI_VALIDATE( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE( cond )
+
#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
#define biL (ciL << 3) /* bits in limb */
#define biH (ciL << 2) /* half limb size */
@@ -83,8 +88,7 @@ static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n )
*/
void mbedtls_mpi_init( mbedtls_mpi *X )
{
- if( X == NULL )
- return;
+ MPI_VALIDATE( X != NULL );
X->s = 1;
X->n = 0;
@@ -116,6 +120,7 @@ void mbedtls_mpi_free( mbedtls_mpi *X )
int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
{
mbedtls_mpi_uint *p;
+ MPI_VALIDATE_RET( X != NULL );
if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
@@ -147,6 +152,10 @@ int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
{
mbedtls_mpi_uint *p;
size_t i;
+ MPI_VALIDATE_RET( X != NULL );
+
+ if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
+ return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
/* Actually resize up in this case */
if( X->n <= nblimbs )
@@ -183,6 +192,8 @@ int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
{
int ret = 0;
size_t i;
+ MPI_VALIDATE_RET( X != NULL );
+ MPI_VALIDATE_RET( Y != NULL );
if( X == Y )
return( 0 );
@@ -222,6 +233,8 @@ cleanup:
void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
{
mbedtls_mpi T;
+ MPI_VALIDATE( X != NULL );
+ MPI_VALIDATE( Y != NULL );
memcpy( &T, X, sizeof( mbedtls_mpi ) );
memcpy( X, Y, sizeof( mbedtls_mpi ) );
@@ -237,6 +250,8 @@ int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned
{
int ret = 0;
size_t i;
+ MPI_VALIDATE_RET( X != NULL );
+ MPI_VALIDATE_RET( Y != NULL );
/* make sure assign is 0 or 1 in a time-constant manner */
assign = (assign | (unsigned char)-assign) >> 7;
@@ -266,6 +281,8 @@ int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char sw
int ret, s;
size_t i;
mbedtls_mpi_uint tmp;
+ MPI_VALIDATE_RET( X != NULL );
+ MPI_VALIDATE_RET( Y != NULL );
if( X == Y )
return( 0 );
@@ -298,6 +315,7 @@ cleanup:
int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
{
int ret;
+ MPI_VALIDATE_RET( X != NULL );
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
memset( X->p, 0, X->n * ciL );
@@ -315,12 +333,18 @@ cleanup:
*/
int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
{
+ MPI_VALIDATE_RET( X != NULL );
+
if( X->n * biL <= pos )
return( 0 );
return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
}
+/* Get a specific byte, without range checks. */
+#define GET_BYTE( X, i ) \
+ ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
+
/*
* Set a bit to a specific value of 0 or 1
*/
@@ -329,6 +353,7 @@ int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
int ret = 0;
size_t off = pos / biL;
size_t idx = pos % biL;
+ MPI_VALIDATE_RET( X != NULL );
if( val != 0 && val != 1 )
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
@@ -355,6 +380,7 @@ cleanup:
size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
{
size_t i, j, count = 0;
+ MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 );
for( i = 0; i < X->n; i++ )
for( j = 0; j < biL; j++, count++ )
@@ -435,6 +461,8 @@ int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
size_t i, j, slen, n;
mbedtls_mpi_uint d;
mbedtls_mpi T;
+ MPI_VALIDATE_RET( X != NULL );
+ MPI_VALIDATE_RET( s != NULL );
if( radix < 2 || radix > 16 )
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
@@ -535,6 +563,9 @@ int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
size_t n;
char *p;
mbedtls_mpi T;
+ MPI_VALIDATE_RET( X != NULL );
+ MPI_VALIDATE_RET( olen != NULL );
+ MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
if( radix < 2 || radix > 16 )
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
@@ -616,6 +647,12 @@ int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
*/
char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
+ MPI_VALIDATE_RET( X != NULL );
+ MPI_VALIDATE_RET( fin != NULL );
+
+ if( radix < 2 || radix > 16 )
+ return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+
memset( s, 0, sizeof( s ) );
if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
@@ -647,6 +684,10 @@ int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE
* newline characters and '\0'
*/
char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
+ MPI_VALIDATE_RET( X != NULL );
+
+ if( radix < 2 || radix > 16 )
+ return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
memset( s, 0, sizeof( s ) );
@@ -683,6 +724,9 @@ int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t bu
size_t i, j;
size_t const limbs = CHARS_TO_LIMBS( buflen );
+ MPI_VALIDATE_RET( X != NULL );
+ MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
+
/* Ensure that target MPI has exactly the necessary number of limbs */
if( X->n != limbs )
{
@@ -704,19 +748,45 @@ cleanup:
/*
* Export X into unsigned binary data, big endian
*/
-int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen )
+int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
+ unsigned char *buf, size_t buflen )
{
- size_t i, j, n;
+ size_t stored_bytes;
+ size_t bytes_to_copy;
+ unsigned char *p;
+ size_t i;
- n = mbedtls_mpi_size( X );
+ MPI_VALIDATE_RET( X != NULL );
+ MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
- if( buflen < n )
- return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
+ stored_bytes = X->n * ciL;
- memset( buf, 0, buflen );
+ if( stored_bytes < buflen )
+ {
+ /* There is enough space in the output buffer. Write initial
+ * null bytes and record the position at which to start
+ * writing the significant bytes. In this case, the execution
+ * trace of this function does not depend on the value of the
+ * number. */
+ bytes_to_copy = stored_bytes;
+ p = buf + buflen - stored_bytes;
+ memset( buf, 0, buflen - stored_bytes );
+ }
+ else
+ {
+ /* The output buffer is smaller than the allocated size of X.
+ * However X may fit if its leading bytes are zero. */
+ bytes_to_copy = buflen;
+ p = buf;
+ for( i = bytes_to_copy; i < stored_bytes; i++ )
+ {
+ if( GET_BYTE( X, i ) != 0 )
+ return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
+ }
+ }
- for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
- buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
+ for( i = 0; i < bytes_to_copy; i++ )
+ p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
return( 0 );
}
@@ -729,6 +799,7 @@ int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
int ret;
size_t i, v0, t1;
mbedtls_mpi_uint r0 = 0, r1;
+ MPI_VALIDATE_RET( X != NULL );
v0 = count / (biL );
t1 = count & (biL - 1);
@@ -778,6 +849,7 @@ int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
{
size_t i, v0, v1;
mbedtls_mpi_uint r0 = 0, r1;
+ MPI_VALIDATE_RET( X != NULL );
v0 = count / biL;
v1 = count & (biL - 1);
@@ -820,6 +892,8 @@ int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
{
size_t i, j;
+ MPI_VALIDATE_RET( X != NULL );
+ MPI_VALIDATE_RET( Y != NULL );
for( i = X->n; i > 0; i-- )
if( X->p[i - 1] != 0 )
@@ -850,6 +924,8 @@ int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
{
size_t i, j;
+ MPI_VALIDATE_RET( X != NULL );
+ MPI_VALIDATE_RET( Y != NULL );
for( i = X->n; i > 0; i-- )
if( X->p[i - 1] != 0 )
@@ -884,6 +960,7 @@ int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
{
mbedtls_mpi Y;
mbedtls_mpi_uint p[1];
+ MPI_VALIDATE_RET( X != NULL );
*p = ( z < 0 ) ? -z : z;
Y.s = ( z < 0 ) ? -1 : 1;
@@ -901,6 +978,9 @@ int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi
int ret;
size_t i, j;
mbedtls_mpi_uint *o, *p, c, tmp;
+ MPI_VALIDATE_RET( X != NULL );
+ MPI_VALIDATE_RET( A != NULL );
+ MPI_VALIDATE_RET( B != NULL );
if( X == B )
{
@@ -978,6 +1058,9 @@ int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi
mbedtls_mpi TB;
int ret;
size_t n;
+ MPI_VALIDATE_RET( X != NULL );
+ MPI_VALIDATE_RET( A != NULL );
+ MPI_VALIDATE_RET( B != NULL );
if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
@@ -1018,8 +1101,12 @@ cleanup:
*/
int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
{
- int ret, s = A->s;
+ int ret, s;
+ MPI_VALIDATE_RET( X != NULL );
+ MPI_VALIDATE_RET( A != NULL );
+ MPI_VALIDATE_RET( B != NULL );
+ s = A->s;
if( A->s * B->s < 0 )
{
if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
@@ -1049,8 +1136,12 @@ cleanup:
*/
int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
{
- int ret, s = A->s;
+ int ret, s;
+ MPI_VALIDATE_RET( X != NULL );
+ MPI_VALIDATE_RET( A != NULL );
+ MPI_VALIDATE_RET( B != NULL );
+ s = A->s;
if( A->s * B->s > 0 )
{
if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
@@ -1082,6 +1173,8 @@ int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint
{
mbedtls_mpi _B;
mbedtls_mpi_uint p[1];
+ MPI_VALIDATE_RET( X != NULL );
+ MPI_VALIDATE_RET( A != NULL );
p[0] = ( b < 0 ) ? -b : b;
_B.s = ( b < 0 ) ? -1 : 1;
@@ -1098,6 +1191,8 @@ int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint
{
mbedtls_mpi _B;
mbedtls_mpi_uint p[1];
+ MPI_VALIDATE_RET( X != NULL );
+ MPI_VALIDATE_RET( A != NULL );
p[0] = ( b < 0 ) ? -b : b;
_B.s = ( b < 0 ) ? -1 : 1;
@@ -1187,6 +1282,9 @@ int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi
int ret;
size_t i, j;
mbedtls_mpi TA, TB;
+ MPI_VALIDATE_RET( X != NULL );
+ MPI_VALIDATE_RET( A != NULL );
+ MPI_VALIDATE_RET( B != NULL );
mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
@@ -1223,6 +1321,8 @@ int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint
{
mbedtls_mpi _B;
mbedtls_mpi_uint p[1];
+ MPI_VALIDATE_RET( X != NULL );
+ MPI_VALIDATE_RET( A != NULL );
_B.s = 1;
_B.n = 1;
@@ -1331,11 +1431,14 @@ static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
/*
* Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
*/
-int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
+int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
+ const mbedtls_mpi *B )
{
int ret;
size_t i, n, t, k;
mbedtls_mpi X, Y, Z, T1, T2;
+ MPI_VALIDATE_RET( A != NULL );
+ MPI_VALIDATE_RET( B != NULL );
if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
@@ -1446,10 +1549,13 @@ cleanup:
/*
* Division by int: A = Q * b + R
*/
-int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b )
+int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
+ const mbedtls_mpi *A,
+ mbedtls_mpi_sint b )
{
mbedtls_mpi _B;
mbedtls_mpi_uint p[1];
+ MPI_VALIDATE_RET( A != NULL );
p[0] = ( b < 0 ) ? -b : b;
_B.s = ( b < 0 ) ? -1 : 1;
@@ -1465,6 +1571,9 @@ int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, m
int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
{
int ret;
+ MPI_VALIDATE_RET( R != NULL );
+ MPI_VALIDATE_RET( A != NULL );
+ MPI_VALIDATE_RET( B != NULL );
if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
@@ -1489,6 +1598,8 @@ int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_
{
size_t i;
mbedtls_mpi_uint x, y, z;
+ MPI_VALIDATE_RET( r != NULL );
+ MPI_VALIDATE_RET( A != NULL );
if( b == 0 )
return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
@@ -1602,7 +1713,8 @@ static int mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi
/*
* Montgomery reduction: A = A * R^-1 mod N
*/
-static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, mbedtls_mpi_uint mm, const mbedtls_mpi *T )
+static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
+ mbedtls_mpi_uint mm, const mbedtls_mpi *T )
{
mbedtls_mpi_uint z = 1;
mbedtls_mpi U;
@@ -1616,7 +1728,9 @@ static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, mbedtls_mpi_uint m
/*
* Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
*/
-int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *_RR )
+int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
+ const mbedtls_mpi *E, const mbedtls_mpi *N,
+ mbedtls_mpi *_RR )
{
int ret;
size_t wbits, wsize, one = 1;
@@ -1626,6 +1740,11 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi
mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
int neg;
+ MPI_VALIDATE_RET( X != NULL );
+ MPI_VALIDATE_RET( A != NULL );
+ MPI_VALIDATE_RET( E != NULL );
+ MPI_VALIDATE_RET( N != NULL );
+
if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
@@ -1830,6 +1949,10 @@ int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B
size_t lz, lzt;
mbedtls_mpi TG, TA, TB;
+ MPI_VALIDATE_RET( G != NULL );
+ MPI_VALIDATE_RET( A != NULL );
+ MPI_VALIDATE_RET( B != NULL );
+
mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
@@ -1886,6 +2009,8 @@ int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
{
int ret;
unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
+ MPI_VALIDATE_RET( X != NULL );
+ MPI_VALIDATE_RET( f_rng != NULL );
if( size > MBEDTLS_MPI_MAX_SIZE )
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
@@ -1905,6 +2030,9 @@ int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi
{
int ret;
mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
+ MPI_VALIDATE_RET( X != NULL );
+ MPI_VALIDATE_RET( A != NULL );
+ MPI_VALIDATE_RET( N != NULL );
if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
@@ -2056,15 +2184,19 @@ cleanup:
/*
* Miller-Rabin pseudo-primality test (HAC 4.24)
*/
-static int mpi_miller_rabin( const mbedtls_mpi *X,
+static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
int ret, count;
- size_t i, j, k, n, s;
+ size_t i, j, k, s;
mbedtls_mpi W, R, T, A, RR;
- mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
+ MPI_VALIDATE_RET( X != NULL );
+ MPI_VALIDATE_RET( f_rng != NULL );
+
+ mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
+ mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
mbedtls_mpi_init( &RR );
/*
@@ -2077,27 +2209,12 @@ static int mpi_miller_rabin( const mbedtls_mpi *X,
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
i = mbedtls_mpi_bitlen( X );
- /*
- * HAC, table 4.4
- */
- n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
- ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
- ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
- for( i = 0; i < n; i++ )
+ for( i = 0; i < rounds; i++ )
{
/*
* pick a random A, 1 < A < |X| - 1
*/
- MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
-
- if( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 )
- {
- j = mbedtls_mpi_bitlen( &A ) - mbedtls_mpi_bitlen( &W );
- MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j + 1 ) );
- }
- A.p[0] |= 3;
-
count = 0;
do {
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
@@ -2105,7 +2222,7 @@ static int mpi_miller_rabin( const mbedtls_mpi *X,
j = mbedtls_mpi_bitlen( &A );
k = mbedtls_mpi_bitlen( &W );
if (j > k) {
- MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j - k ) );
+ A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
}
if (count++ > 30) {
@@ -2151,7 +2268,8 @@ static int mpi_miller_rabin( const mbedtls_mpi *X,
}
cleanup:
- mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
+ mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
+ mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
mbedtls_mpi_free( &RR );
return( ret );
@@ -2160,12 +2278,14 @@ cleanup:
/*
* Pseudo-primality test: small factors, then Miller-Rabin
*/
-int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
- int (*f_rng)(void *, unsigned char *, size_t),
- void *p_rng )
+int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
{
int ret;
mbedtls_mpi XX;
+ MPI_VALIDATE_RET( X != NULL );
+ MPI_VALIDATE_RET( f_rng != NULL );
XX.s = 1;
XX.n = X->n;
@@ -2186,17 +2306,37 @@ int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
return( ret );
}
- return( mpi_miller_rabin( &XX, f_rng, p_rng ) );
+ return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
+}
+
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+/*
+ * Pseudo-primality test, error probability 2^-80
+ */
+int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ MPI_VALIDATE_RET( X != NULL );
+ MPI_VALIDATE_RET( f_rng != NULL );
+
+ /*
+ * In the past our key generation aimed for an error rate of at most
+ * 2^-80. Since this function is deprecated, aim for the same certainty
+ * here as well.
+ */
+ return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
}
+#endif
/*
* Prime number generation
*
- * If dh_flag is 0 and nbits is at least 1024, then the procedure
- * follows the RSA probably-prime generation method of FIPS 186-4.
- * NB. FIPS 186-4 only allows the specific bit lengths of 1024 and 1536.
+ * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
+ * be either 1024 bits or 1536 bits long, and flags must contain
+ * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
*/
-int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
+int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
@@ -2209,9 +2349,13 @@ int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
#endif
int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
size_t k, n;
+ int rounds;
mbedtls_mpi_uint r;
mbedtls_mpi Y;
+ MPI_VALIDATE_RET( X != NULL );
+ MPI_VALIDATE_RET( f_rng != NULL );
+
if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
@@ -2219,6 +2363,27 @@ int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
n = BITS_TO_LIMBS( nbits );
+ if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
+ {
+ /*
+ * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
+ */
+ rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
+ ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
+ ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
+ }
+ else
+ {
+ /*
+ * 2^-100 error probability, number of rounds computed based on HAC,
+ * fact 4.48
+ */
+ rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
+ ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
+ ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
+ ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
+ }
+
while( 1 )
{
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
@@ -2229,9 +2394,9 @@ int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
X->p[0] |= 1;
- if( dh_flag == 0 )
+ if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
{
- ret = mbedtls_mpi_is_prime( X, f_rng, p_rng );
+ ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
goto cleanup;
@@ -2264,8 +2429,10 @@ int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
*/
if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
( ret = mpi_check_small_factors( &Y ) ) == 0 &&
- ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 &&
- ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 )
+ ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
+ == 0 &&
+ ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
+ == 0 )
goto cleanup;
if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
diff --git a/thirdparty/mbedtls/library/blowfish.c b/thirdparty/mbedtls/library/blowfish.c
index 5b6bb9885f..cbf9238246 100644
--- a/thirdparty/mbedtls/library/blowfish.c
+++ b/thirdparty/mbedtls/library/blowfish.c
@@ -40,6 +40,12 @@
#if !defined(MBEDTLS_BLOWFISH_ALT)
+/* Parameter validation macros */
+#define BLOWFISH_VALIDATE_RET( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA )
+#define BLOWFISH_VALIDATE( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE( cond )
+
/*
* 32-bit integer manipulation macros (big endian)
*/
@@ -153,6 +159,7 @@ static void blowfish_dec( mbedtls_blowfish_context *ctx, uint32_t *xl, uint32_t
void mbedtls_blowfish_init( mbedtls_blowfish_context *ctx )
{
+ BLOWFISH_VALIDATE( ctx != NULL );
memset( ctx, 0, sizeof( mbedtls_blowfish_context ) );
}
@@ -167,16 +174,20 @@ void mbedtls_blowfish_free( mbedtls_blowfish_context *ctx )
/*
* Blowfish key schedule
*/
-int mbedtls_blowfish_setkey( mbedtls_blowfish_context *ctx, const unsigned char *key,
- unsigned int keybits )
+int mbedtls_blowfish_setkey( mbedtls_blowfish_context *ctx,
+ const unsigned char *key,
+ unsigned int keybits )
{
unsigned int i, j, k;
uint32_t data, datal, datar;
+ BLOWFISH_VALIDATE_RET( ctx != NULL );
+ BLOWFISH_VALIDATE_RET( key != NULL );
- if( keybits < MBEDTLS_BLOWFISH_MIN_KEY_BITS || keybits > MBEDTLS_BLOWFISH_MAX_KEY_BITS ||
- ( keybits % 8 ) )
+ if( keybits < MBEDTLS_BLOWFISH_MIN_KEY_BITS ||
+ keybits > MBEDTLS_BLOWFISH_MAX_KEY_BITS ||
+ keybits % 8 != 0 )
{
- return( MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH );
+ return( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA );
}
keybits >>= 3;
@@ -231,6 +242,11 @@ int mbedtls_blowfish_crypt_ecb( mbedtls_blowfish_context *ctx,
unsigned char output[MBEDTLS_BLOWFISH_BLOCKSIZE] )
{
uint32_t X0, X1;
+ BLOWFISH_VALIDATE_RET( ctx != NULL );
+ BLOWFISH_VALIDATE_RET( mode == MBEDTLS_BLOWFISH_ENCRYPT ||
+ mode == MBEDTLS_BLOWFISH_DECRYPT );
+ BLOWFISH_VALIDATE_RET( input != NULL );
+ BLOWFISH_VALIDATE_RET( output != NULL );
GET_UINT32_BE( X0, input, 0 );
GET_UINT32_BE( X1, input, 4 );
@@ -263,6 +279,12 @@ int mbedtls_blowfish_crypt_cbc( mbedtls_blowfish_context *ctx,
{
int i;
unsigned char temp[MBEDTLS_BLOWFISH_BLOCKSIZE];
+ BLOWFISH_VALIDATE_RET( ctx != NULL );
+ BLOWFISH_VALIDATE_RET( mode == MBEDTLS_BLOWFISH_ENCRYPT ||
+ mode == MBEDTLS_BLOWFISH_DECRYPT );
+ BLOWFISH_VALIDATE_RET( iv != NULL );
+ BLOWFISH_VALIDATE_RET( length == 0 || input != NULL );
+ BLOWFISH_VALIDATE_RET( length == 0 || output != NULL );
if( length % MBEDTLS_BLOWFISH_BLOCKSIZE )
return( MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH );
@@ -317,7 +339,19 @@ int mbedtls_blowfish_crypt_cfb64( mbedtls_blowfish_context *ctx,
unsigned char *output )
{
int c;
- size_t n = *iv_off;
+ size_t n;
+
+ BLOWFISH_VALIDATE_RET( ctx != NULL );
+ BLOWFISH_VALIDATE_RET( mode == MBEDTLS_BLOWFISH_ENCRYPT ||
+ mode == MBEDTLS_BLOWFISH_DECRYPT );
+ BLOWFISH_VALIDATE_RET( iv != NULL );
+ BLOWFISH_VALIDATE_RET( iv_off != NULL );
+ BLOWFISH_VALIDATE_RET( length == 0 || input != NULL );
+ BLOWFISH_VALIDATE_RET( length == 0 || output != NULL );
+
+ n = *iv_off;
+ if( n >= 8 )
+ return( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA );
if( mode == MBEDTLS_BLOWFISH_DECRYPT )
{
@@ -365,7 +399,17 @@ int mbedtls_blowfish_crypt_ctr( mbedtls_blowfish_context *ctx,
unsigned char *output )
{
int c, i;
- size_t n = *nc_off;
+ size_t n;
+ BLOWFISH_VALIDATE_RET( ctx != NULL );
+ BLOWFISH_VALIDATE_RET( nonce_counter != NULL );
+ BLOWFISH_VALIDATE_RET( stream_block != NULL );
+ BLOWFISH_VALIDATE_RET( nc_off != NULL );
+ BLOWFISH_VALIDATE_RET( length == 0 || input != NULL );
+ BLOWFISH_VALIDATE_RET( length == 0 || output != NULL );
+
+ n = *nc_off;
+ if( n >= 8 )
+ return( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA );
while( length-- )
{
diff --git a/thirdparty/mbedtls/library/camellia.c b/thirdparty/mbedtls/library/camellia.c
index 41b7da0fae..22262b89a8 100644
--- a/thirdparty/mbedtls/library/camellia.c
+++ b/thirdparty/mbedtls/library/camellia.c
@@ -49,6 +49,12 @@
#if !defined(MBEDTLS_CAMELLIA_ALT)
+/* Parameter validation macros */
+#define CAMELLIA_VALIDATE_RET( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA )
+#define CAMELLIA_VALIDATE( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE( cond )
+
/*
* 32-bit integer manipulation macros (big endian)
*/
@@ -321,6 +327,7 @@ static void camellia_feistel( const uint32_t x[2], const uint32_t k[2],
void mbedtls_camellia_init( mbedtls_camellia_context *ctx )
{
+ CAMELLIA_VALIDATE( ctx != NULL );
memset( ctx, 0, sizeof( mbedtls_camellia_context ) );
}
@@ -335,8 +342,9 @@ void mbedtls_camellia_free( mbedtls_camellia_context *ctx )
/*
* Camellia key schedule (encryption)
*/
-int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx, const unsigned char *key,
- unsigned int keybits )
+int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx,
+ const unsigned char *key,
+ unsigned int keybits )
{
int idx;
size_t i;
@@ -346,6 +354,9 @@ int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx, const unsigned c
uint32_t KC[16];
uint32_t TK[20];
+ CAMELLIA_VALIDATE_RET( ctx != NULL );
+ CAMELLIA_VALIDATE_RET( key != NULL );
+
RK = ctx->rk;
memset( t, 0, 64 );
@@ -356,7 +367,7 @@ int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx, const unsigned c
case 128: ctx->nr = 3; idx = 0; break;
case 192:
case 256: ctx->nr = 4; idx = 1; break;
- default : return( MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH );
+ default : return( MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA );
}
for( i = 0; i < keybits / 8; ++i )
@@ -440,14 +451,17 @@ int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx, const unsigned c
/*
* Camellia key schedule (decryption)
*/
-int mbedtls_camellia_setkey_dec( mbedtls_camellia_context *ctx, const unsigned char *key,
- unsigned int keybits )
+int mbedtls_camellia_setkey_dec( mbedtls_camellia_context *ctx,
+ const unsigned char *key,
+ unsigned int keybits )
{
int idx, ret;
size_t i;
mbedtls_camellia_context cty;
uint32_t *RK;
uint32_t *SK;
+ CAMELLIA_VALIDATE_RET( ctx != NULL );
+ CAMELLIA_VALIDATE_RET( key != NULL );
mbedtls_camellia_init( &cty );
@@ -495,6 +509,11 @@ int mbedtls_camellia_crypt_ecb( mbedtls_camellia_context *ctx,
{
int NR;
uint32_t *RK, X[4];
+ CAMELLIA_VALIDATE_RET( ctx != NULL );
+ CAMELLIA_VALIDATE_RET( mode == MBEDTLS_CAMELLIA_ENCRYPT ||
+ mode == MBEDTLS_CAMELLIA_DECRYPT );
+ CAMELLIA_VALIDATE_RET( input != NULL );
+ CAMELLIA_VALIDATE_RET( output != NULL );
( (void) mode );
@@ -552,14 +571,20 @@ int mbedtls_camellia_crypt_ecb( mbedtls_camellia_context *ctx,
* Camellia-CBC buffer encryption/decryption
*/
int mbedtls_camellia_crypt_cbc( mbedtls_camellia_context *ctx,
- int mode,
- size_t length,
- unsigned char iv[16],
- const unsigned char *input,
- unsigned char *output )
+ int mode,
+ size_t length,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output )
{
int i;
unsigned char temp[16];
+ CAMELLIA_VALIDATE_RET( ctx != NULL );
+ CAMELLIA_VALIDATE_RET( mode == MBEDTLS_CAMELLIA_ENCRYPT ||
+ mode == MBEDTLS_CAMELLIA_DECRYPT );
+ CAMELLIA_VALIDATE_RET( iv != NULL );
+ CAMELLIA_VALIDATE_RET( length == 0 || input != NULL );
+ CAMELLIA_VALIDATE_RET( length == 0 || output != NULL );
if( length % 16 )
return( MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH );
@@ -614,7 +639,18 @@ int mbedtls_camellia_crypt_cfb128( mbedtls_camellia_context *ctx,
unsigned char *output )
{
int c;
- size_t n = *iv_off;
+ size_t n;
+ CAMELLIA_VALIDATE_RET( ctx != NULL );
+ CAMELLIA_VALIDATE_RET( mode == MBEDTLS_CAMELLIA_ENCRYPT ||
+ mode == MBEDTLS_CAMELLIA_DECRYPT );
+ CAMELLIA_VALIDATE_RET( iv != NULL );
+ CAMELLIA_VALIDATE_RET( iv_off != NULL );
+ CAMELLIA_VALIDATE_RET( length == 0 || input != NULL );
+ CAMELLIA_VALIDATE_RET( length == 0 || output != NULL );
+
+ n = *iv_off;
+ if( n >= 16 )
+ return( MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA );
if( mode == MBEDTLS_CAMELLIA_DECRYPT )
{
@@ -662,7 +698,17 @@ int mbedtls_camellia_crypt_ctr( mbedtls_camellia_context *ctx,
unsigned char *output )
{
int c, i;
- size_t n = *nc_off;
+ size_t n;
+ CAMELLIA_VALIDATE_RET( ctx != NULL );
+ CAMELLIA_VALIDATE_RET( nonce_counter != NULL );
+ CAMELLIA_VALIDATE_RET( stream_block != NULL );
+ CAMELLIA_VALIDATE_RET( nc_off != NULL );
+ CAMELLIA_VALIDATE_RET( length == 0 || input != NULL );
+ CAMELLIA_VALIDATE_RET( length == 0 || output != NULL );
+
+ n = *nc_off;
+ if( n >= 16 )
+ return( MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA );
while( length-- )
{
diff --git a/thirdparty/mbedtls/library/ccm.c b/thirdparty/mbedtls/library/ccm.c
index 804eaf80f1..01e58b0436 100644
--- a/thirdparty/mbedtls/library/ccm.c
+++ b/thirdparty/mbedtls/library/ccm.c
@@ -52,6 +52,11 @@
#if !defined(MBEDTLS_CCM_ALT)
+#define CCM_VALIDATE_RET( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CCM_BAD_INPUT )
+#define CCM_VALIDATE( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE( cond )
+
#define CCM_ENCRYPT 0
#define CCM_DECRYPT 1
@@ -60,6 +65,7 @@
*/
void mbedtls_ccm_init( mbedtls_ccm_context *ctx )
{
+ CCM_VALIDATE( ctx != NULL );
memset( ctx, 0, sizeof( mbedtls_ccm_context ) );
}
@@ -71,6 +77,9 @@ int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx,
int ret;
const mbedtls_cipher_info_t *cipher_info;
+ CCM_VALIDATE_RET( ctx != NULL );
+ CCM_VALIDATE_RET( key != NULL );
+
cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, MBEDTLS_MODE_ECB );
if( cipher_info == NULL )
return( MBEDTLS_ERR_CCM_BAD_INPUT );
@@ -97,6 +106,8 @@ int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx,
*/
void mbedtls_ccm_free( mbedtls_ccm_context *ctx )
{
+ if( ctx == NULL )
+ return;
mbedtls_cipher_free( &ctx->cipher_ctx );
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ccm_context ) );
}
@@ -310,6 +321,12 @@ int mbedtls_ccm_star_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *input, unsigned char *output,
unsigned char *tag, size_t tag_len )
{
+ CCM_VALIDATE_RET( ctx != NULL );
+ CCM_VALIDATE_RET( iv != NULL );
+ CCM_VALIDATE_RET( add_len == 0 || add != NULL );
+ CCM_VALIDATE_RET( length == 0 || input != NULL );
+ CCM_VALIDATE_RET( length == 0 || output != NULL );
+ CCM_VALIDATE_RET( tag_len == 0 || tag != NULL );
return( ccm_auth_crypt( ctx, CCM_ENCRYPT, length, iv, iv_len,
add, add_len, input, output, tag, tag_len ) );
}
@@ -320,6 +337,12 @@ int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *input, unsigned char *output,
unsigned char *tag, size_t tag_len )
{
+ CCM_VALIDATE_RET( ctx != NULL );
+ CCM_VALIDATE_RET( iv != NULL );
+ CCM_VALIDATE_RET( add_len == 0 || add != NULL );
+ CCM_VALIDATE_RET( length == 0 || input != NULL );
+ CCM_VALIDATE_RET( length == 0 || output != NULL );
+ CCM_VALIDATE_RET( tag_len == 0 || tag != NULL );
if( tag_len == 0 )
return( MBEDTLS_ERR_CCM_BAD_INPUT );
@@ -341,6 +364,13 @@ int mbedtls_ccm_star_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
unsigned char i;
int diff;
+ CCM_VALIDATE_RET( ctx != NULL );
+ CCM_VALIDATE_RET( iv != NULL );
+ CCM_VALIDATE_RET( add_len == 0 || add != NULL );
+ CCM_VALIDATE_RET( length == 0 || input != NULL );
+ CCM_VALIDATE_RET( length == 0 || output != NULL );
+ CCM_VALIDATE_RET( tag_len == 0 || tag != NULL );
+
if( ( ret = ccm_auth_crypt( ctx, CCM_DECRYPT, length,
iv, iv_len, add, add_len,
input, output, check_tag, tag_len ) ) != 0 )
@@ -367,6 +397,13 @@ int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *input, unsigned char *output,
const unsigned char *tag, size_t tag_len )
{
+ CCM_VALIDATE_RET( ctx != NULL );
+ CCM_VALIDATE_RET( iv != NULL );
+ CCM_VALIDATE_RET( add_len == 0 || add != NULL );
+ CCM_VALIDATE_RET( length == 0 || input != NULL );
+ CCM_VALIDATE_RET( length == 0 || output != NULL );
+ CCM_VALIDATE_RET( tag_len == 0 || tag != NULL );
+
if( tag_len == 0 )
return( MBEDTLS_ERR_CCM_BAD_INPUT );
@@ -381,7 +418,8 @@ int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
*/
#define NB_TESTS 3
-
+#define CCM_SELFTEST_PT_MAX_LEN 24
+#define CCM_SELFTEST_CT_MAX_LEN 32
/*
* The data is the same for all tests, only the used length changes
*/
@@ -401,7 +439,7 @@ static const unsigned char ad[] = {
0x10, 0x11, 0x12, 0x13
};
-static const unsigned char msg[] = {
+static const unsigned char msg[CCM_SELFTEST_PT_MAX_LEN] = {
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
@@ -412,7 +450,7 @@ static const size_t add_len[NB_TESTS] = { 8, 16, 20 };
static const size_t msg_len[NB_TESTS] = { 4, 16, 24 };
static const size_t tag_len[NB_TESTS] = { 4, 6, 8 };
-static const unsigned char res[NB_TESTS][32] = {
+static const unsigned char res[NB_TESTS][CCM_SELFTEST_CT_MAX_LEN] = {
{ 0x71, 0x62, 0x01, 0x5b, 0x4d, 0xac, 0x25, 0x5d },
{ 0xd2, 0xa1, 0xf0, 0xe0, 0x51, 0xea, 0x5f, 0x62,
0x08, 0x1a, 0x77, 0x92, 0x07, 0x3d, 0x59, 0x3d,
@@ -426,7 +464,13 @@ static const unsigned char res[NB_TESTS][32] = {
int mbedtls_ccm_self_test( int verbose )
{
mbedtls_ccm_context ctx;
- unsigned char out[32];
+ /*
+ * Some hardware accelerators require the input and output buffers
+ * would be in RAM, because the flash is not accessible.
+ * Use buffers on the stack to hold the test vectors data.
+ */
+ unsigned char plaintext[CCM_SELFTEST_PT_MAX_LEN];
+ unsigned char ciphertext[CCM_SELFTEST_CT_MAX_LEN];
size_t i;
int ret;
@@ -445,27 +489,32 @@ int mbedtls_ccm_self_test( int verbose )
if( verbose != 0 )
mbedtls_printf( " CCM-AES #%u: ", (unsigned int) i + 1 );
+ memset( plaintext, 0, CCM_SELFTEST_PT_MAX_LEN );
+ memset( ciphertext, 0, CCM_SELFTEST_CT_MAX_LEN );
+ memcpy( plaintext, msg, msg_len[i] );
+
ret = mbedtls_ccm_encrypt_and_tag( &ctx, msg_len[i],
- iv, iv_len[i], ad, add_len[i],
- msg, out,
- out + msg_len[i], tag_len[i] );
+ iv, iv_len[i], ad, add_len[i],
+ plaintext, ciphertext,
+ ciphertext + msg_len[i], tag_len[i] );
if( ret != 0 ||
- memcmp( out, res[i], msg_len[i] + tag_len[i] ) != 0 )
+ memcmp( ciphertext, res[i], msg_len[i] + tag_len[i] ) != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
return( 1 );
}
+ memset( plaintext, 0, CCM_SELFTEST_PT_MAX_LEN );
ret = mbedtls_ccm_auth_decrypt( &ctx, msg_len[i],
- iv, iv_len[i], ad, add_len[i],
- res[i], out,
- res[i] + msg_len[i], tag_len[i] );
+ iv, iv_len[i], ad, add_len[i],
+ ciphertext, plaintext,
+ ciphertext + msg_len[i], tag_len[i] );
if( ret != 0 ||
- memcmp( out, msg, msg_len[i] ) != 0 )
+ memcmp( plaintext, msg, msg_len[i] ) != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
diff --git a/thirdparty/mbedtls/library/certs.c b/thirdparty/mbedtls/library/certs.c
index f1379b8cb1..ff0f11e923 100644
--- a/thirdparty/mbedtls/library/certs.c
+++ b/thirdparty/mbedtls/library/certs.c
@@ -218,12 +218,13 @@ const size_t mbedtls_test_ca_key_rsa_len = sizeof( mbedtls_test_ca_key_rsa );
const char mbedtls_test_ca_pwd_rsa[] = "PolarSSLTest";
const size_t mbedtls_test_ca_pwd_rsa_len = sizeof( mbedtls_test_ca_pwd_rsa ) - 1;
+/* tests/data_files/server2.crt */
const char mbedtls_test_srv_crt_rsa[] =
"-----BEGIN CERTIFICATE-----\r\n"
"MIIDNzCCAh+gAwIBAgIBAjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n"
-"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n"
+"MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n"
"MTEwMjEyMTQ0NDA2WhcNMjEwMjEyMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n"
-"A1UEChMIUG9sYXJTU0wxEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN\r\n"
+"A1UECgwIUG9sYXJTU0wxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN\r\n"
"AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN\r\n"
"owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz\r\n"
"NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM\r\n"
@@ -231,16 +232,17 @@ const char mbedtls_test_srv_crt_rsa[] =
"hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya\r\n"
"HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNNMEswCQYD\r\n"
"VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw\r\n"
-"FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDQYJKoZIhvcNAQEFBQADggEBAJxnXClY\r\n"
-"oHkbp70cqBrsGXLybA74czbO5RdLEgFs7rHVS9r+c293luS/KdliLScZqAzYVylw\r\n"
-"UfRWvKMoWhHYKp3dEIS4xTXk6/5zXxhv9Rw8SGc8qn6vITHk1S1mPevtekgasY5Y\r\n"
-"iWQuM3h4YVlRH3HHEMAD1TnAexfXHHDFQGe+Bd1iAbz1/sH9H8l4StwX6egvTK3M\r\n"
-"wXRwkKkvjKaEDA9ATbZx0mI8LGsxSuCqe9r9dyjmttd47J1p1Rulz3CLzaRcVIuS\r\n"
-"RRQfaD8neM9c1S/iJ/amTVqJxA1KOdOS5780WhPfSArA+g4qAmSjelc3p4wWpha8\r\n"
-"zhuYwjVuX6JHG0c=\r\n"
+"FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDQYJKoZIhvcNAQEFBQADggEBAAFzC0rF\r\n"
+"y6De8WMcdgQrEw3AhBHFjzqnxZw1ene4IBSC7lTw8rBSy3jOWQdPUWn+0y/pCeeF\r\n"
+"kti6sevFdl1hLemGtd4q+T9TKEKGg3ND4ARfB5AUZZ9uEHq8WBkiwus5clGS17Qd\r\n"
+"dS/TOisB59tQruLx1E1bPLtBKyqk4koC5WAULJwfpswGSyWJTpYwIpxcWE3D2tBu\r\n"
+"UB6MZfXZFzWmWEOyKbeoXjXe8GBCGgHLywvYDsGQ36HSGtEsAvR2QaTLSxWYcfk1\r\n"
+"fbDn4jSWkb4yZy1r01UEigFQtONieGwRFaUqEcFJHJvEEGVgh9keaVlOj2vrwf5r\r\n"
+"4mN4lW7gLdenN6g=\r\n"
"-----END CERTIFICATE-----\r\n";
const size_t mbedtls_test_srv_crt_rsa_len = sizeof( mbedtls_test_srv_crt_rsa );
+/* tests/data_files/server2.key */
const char mbedtls_test_srv_key_rsa[] =
"-----BEGIN RSA PRIVATE KEY-----\r\n"
"MIIEpAIBAAKCAQEAwU2j3efNHdEE10lyuJmsDnjkOjxKzzoTFtBa5M2jAIin7h5r\r\n"
@@ -271,11 +273,12 @@ const char mbedtls_test_srv_key_rsa[] =
"-----END RSA PRIVATE KEY-----\r\n";
const size_t mbedtls_test_srv_key_rsa_len = sizeof( mbedtls_test_srv_key_rsa );
+/* tests/data_files/cli-rsa-sha256.crt */
const char mbedtls_test_cli_crt_rsa[] =
"-----BEGIN CERTIFICATE-----\r\n"
-"MIIDhTCCAm2gAwIBAgIBBDANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\r\n"
+"MIIDPzCCAiegAwIBAgIBBDANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\r\n"
"MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n"
-"MTcwNTA1MTMwNzU5WhcNMjcwNTA2MTMwNzU5WjA8MQswCQYDVQQGEwJOTDERMA8G\r\n"
+"MTEwMjEyMTQ0NDA2WhcNMjEwMjEyMTQ0NDA2WjA8MQswCQYDVQQGEwJOTDERMA8G\r\n"
"A1UECgwIUG9sYXJTU0wxGjAYBgNVBAMMEVBvbGFyU1NMIENsaWVudCAyMIIBIjAN\r\n"
"BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6f\r\n"
"M60Nj4o8VmXl3ETZzGaFB9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu\r\n"
@@ -283,18 +286,18 @@ const char mbedtls_test_cli_crt_rsa[] =
"MjDV0/YI0FZPRo7yX/k9Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v\r\n"
"4Jv4EFbMs44TFeY0BGbH7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx/\r\n"
"/DZrtenNLQNiTrM9AM+vdqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQAB\r\n"
-"o4GSMIGPMB0GA1UdDgQWBBRxoQBzckAvVHZeM/xSj7zx3WtGITBjBgNVHSMEXDBa\r\n"
-"gBS0WuSls97SUva51aaVD+s+vMf9/6E/pD0wOzELMAkGA1UEBhMCTkwxETAPBgNV\r\n"
-"BAoMCFBvbGFyU1NMMRkwFwYDVQQDDBBQb2xhclNTTCBUZXN0IENBggEAMAkGA1Ud\r\n"
-"EwQCMAAwDQYJKoZIhvcNAQELBQADggEBAC7yO786NvcHpK8UovKIG9cB32oSQQom\r\n"
-"LoR0eHDRzdqEkoq7yGZufHFiRAAzbMqJfogRtxlrWAeB4y/jGaMBV25IbFOIcH2W\r\n"
-"iCEaMMbG+VQLKNvuC63kmw/Zewc9ThM6Pa1Hcy0axT0faf1B/U01j0FIcw/6mTfK\r\n"
-"D8w48OIwc1yr0JtutCVjig5DC0yznGMt32RyseOLcUe+lfq005v2PAiCozr5X8rE\r\n"
-"ofGZpiM2NqRPePgYy+Vc75Zk28xkRQq1ncprgQb3S4vTsZdScpM9hLf+eMlrgqlj\r\n"
-"c5PLSkXBeLE5+fedkyfTaLxxQlgCpuoOhKBm04/R1pWNzUHyqagjO9Q=\r\n"
+"o00wSzAJBgNVHRMEAjAAMB0GA1UdDgQWBBRxoQBzckAvVHZeM/xSj7zx3WtGITAf\r\n"
+"BgNVHSMEGDAWgBS0WuSls97SUva51aaVD+s+vMf9/zANBgkqhkiG9w0BAQsFAAOC\r\n"
+"AQEAlHabem2Tu69VUN7EipwnQn1dIHdgvT5i+iQHpSxY1crPnBbAeSdAXwsVEqLQ\r\n"
+"gOOIAQD5VIITNuoGgo4i+4OpNh9u7ZkpRHla+/swsfrFWRRbBNP5Bcu74AGLstwU\r\n"
+"zM8gIkBiyfM1Q1qDQISV9trlCG6O8vh8dp/rbI3rfzo99BOHXgFCrzXjCuW4vDsF\r\n"
+"r+Dao26bX3sJ6UnEWg1H3o2x6PpUcvQ36h71/bz4TEbbUUEpe02V4QWuL+wrhHJL\r\n"
+"U7o3SVE3Og7jPF8sat0a50YUWhwEFI256m02KAXLg89ueUyYKEr6rNwhcvXJpvU9\r\n"
+"giIVvd0Sbjjnn7NC4VDbcXV8vw==\r\n"
"-----END CERTIFICATE-----\r\n";
const size_t mbedtls_test_cli_crt_rsa_len = sizeof( mbedtls_test_cli_crt_rsa );
+/* tests/data_files/cli-rsa.key */
const char mbedtls_test_cli_key_rsa[] =
"-----BEGIN RSA PRIVATE KEY-----\r\n"
"MIIEpAIBAAKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6fM60Nj4o8VmXl3ETZzGaF\r\n"
diff --git a/thirdparty/mbedtls/library/chacha20.c b/thirdparty/mbedtls/library/chacha20.c
index d14a51e044..0757163e2f 100644
--- a/thirdparty/mbedtls/library/chacha20.c
+++ b/thirdparty/mbedtls/library/chacha20.c
@@ -53,6 +53,12 @@
#define inline __inline
#endif
+/* Parameter validation macros */
+#define CHACHA20_VALIDATE_RET( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA )
+#define CHACHA20_VALIDATE( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE( cond )
+
#define BYTES_TO_U32_LE( data, offset ) \
( (uint32_t) data[offset] \
| (uint32_t) ( (uint32_t) data[( offset ) + 1] << 8 ) \
@@ -181,14 +187,13 @@ static void chacha20_block( const uint32_t initial_state[16],
void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx )
{
- if( ctx != NULL )
- {
- mbedtls_platform_zeroize( ctx->state, sizeof( ctx->state ) );
- mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
+ CHACHA20_VALIDATE( ctx != NULL );
- /* Initially, there's no keystream bytes available */
- ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
- }
+ mbedtls_platform_zeroize( ctx->state, sizeof( ctx->state ) );
+ mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
+
+ /* Initially, there's no keystream bytes available */
+ ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
}
void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx )
@@ -202,10 +207,8 @@ void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx )
int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx,
const unsigned char key[32] )
{
- if( ( ctx == NULL ) || ( key == NULL ) )
- {
- return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
- }
+ CHACHA20_VALIDATE_RET( ctx != NULL );
+ CHACHA20_VALIDATE_RET( key != NULL );
/* ChaCha20 constants - the string "expand 32-byte k" */
ctx->state[0] = 0x61707865;
@@ -230,10 +233,8 @@ int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx,
const unsigned char nonce[12],
uint32_t counter )
{
- if( ( ctx == NULL ) || ( nonce == NULL ) )
- {
- return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
- }
+ CHACHA20_VALIDATE_RET( ctx != NULL );
+ CHACHA20_VALIDATE_RET( nonce != NULL );
/* Counter */
ctx->state[12] = counter;
@@ -259,15 +260,9 @@ int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx,
size_t offset = 0U;
size_t i;
- if( ctx == NULL )
- {
- return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
- }
- else if( ( size > 0U ) && ( ( input == NULL ) || ( output == NULL ) ) )
- {
- /* input and output pointers are allowed to be NULL only if size == 0 */
- return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
- }
+ CHACHA20_VALIDATE_RET( ctx != NULL );
+ CHACHA20_VALIDATE_RET( size == 0 || input != NULL );
+ CHACHA20_VALIDATE_RET( size == 0 || output != NULL );
/* Use leftover keystream bytes, if available */
while( size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES )
@@ -332,6 +327,11 @@ int mbedtls_chacha20_crypt( const unsigned char key[32],
mbedtls_chacha20_context ctx;
int ret;
+ CHACHA20_VALIDATE_RET( key != NULL );
+ CHACHA20_VALIDATE_RET( nonce != NULL );
+ CHACHA20_VALIDATE_RET( data_len == 0 || input != NULL );
+ CHACHA20_VALIDATE_RET( data_len == 0 || output != NULL );
+
mbedtls_chacha20_init( &ctx );
ret = mbedtls_chacha20_setkey( &ctx, key );
diff --git a/thirdparty/mbedtls/library/chachapoly.c b/thirdparty/mbedtls/library/chachapoly.c
index 860f877653..dc643dd618 100644
--- a/thirdparty/mbedtls/library/chachapoly.c
+++ b/thirdparty/mbedtls/library/chachapoly.c
@@ -44,6 +44,12 @@
#if !defined(MBEDTLS_CHACHAPOLY_ALT)
+/* Parameter validation macros */
+#define CHACHAPOLY_VALIDATE_RET( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA )
+#define CHACHAPOLY_VALIDATE( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE( cond )
+
#define CHACHAPOLY_STATE_INIT ( 0 )
#define CHACHAPOLY_STATE_AAD ( 1 )
#define CHACHAPOLY_STATE_CIPHERTEXT ( 2 ) /* Encrypting or decrypting */
@@ -90,39 +96,35 @@ static int chachapoly_pad_ciphertext( mbedtls_chachapoly_context *ctx )
void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx )
{
- if( ctx != NULL )
- {
- mbedtls_chacha20_init( &ctx->chacha20_ctx );
- mbedtls_poly1305_init( &ctx->poly1305_ctx );
- ctx->aad_len = 0U;
- ctx->ciphertext_len = 0U;
- ctx->state = CHACHAPOLY_STATE_INIT;
- ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
- }
+ CHACHAPOLY_VALIDATE( ctx != NULL );
+
+ mbedtls_chacha20_init( &ctx->chacha20_ctx );
+ mbedtls_poly1305_init( &ctx->poly1305_ctx );
+ ctx->aad_len = 0U;
+ ctx->ciphertext_len = 0U;
+ ctx->state = CHACHAPOLY_STATE_INIT;
+ ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
}
void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx )
{
- if( ctx != NULL )
- {
- mbedtls_chacha20_free( &ctx->chacha20_ctx );
- mbedtls_poly1305_free( &ctx->poly1305_ctx );
- ctx->aad_len = 0U;
- ctx->ciphertext_len = 0U;
- ctx->state = CHACHAPOLY_STATE_INIT;
- ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
- }
+ if( ctx == NULL )
+ return;
+
+ mbedtls_chacha20_free( &ctx->chacha20_ctx );
+ mbedtls_poly1305_free( &ctx->poly1305_ctx );
+ ctx->aad_len = 0U;
+ ctx->ciphertext_len = 0U;
+ ctx->state = CHACHAPOLY_STATE_INIT;
+ ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
}
int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx,
const unsigned char key[32] )
{
int ret;
-
- if( ( ctx == NULL ) || ( key == NULL ) )
- {
- return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
- }
+ CHACHAPOLY_VALIDATE_RET( ctx != NULL );
+ CHACHAPOLY_VALIDATE_RET( key != NULL );
ret = mbedtls_chacha20_setkey( &ctx->chacha20_ctx, key );
@@ -135,11 +137,8 @@ int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx,
{
int ret;
unsigned char poly1305_key[64];
-
- if( ( ctx == NULL ) || ( nonce == NULL ) )
- {
- return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
- }
+ CHACHAPOLY_VALIDATE_RET( ctx != NULL );
+ CHACHAPOLY_VALIDATE_RET( nonce != NULL );
/* Set counter = 0, will be update to 1 when generating Poly1305 key */
ret = mbedtls_chacha20_starts( &ctx->chacha20_ctx, nonce, 0U );
@@ -176,19 +175,11 @@ int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx,
const unsigned char *aad,
size_t aad_len )
{
- if( ctx == NULL )
- {
- return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
- }
- else if( ( aad_len > 0U ) && ( aad == NULL ) )
- {
- /* aad pointer is allowed to be NULL if aad_len == 0 */
- return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
- }
- else if( ctx->state != CHACHAPOLY_STATE_AAD )
- {
+ CHACHAPOLY_VALIDATE_RET( ctx != NULL );
+ CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL );
+
+ if( ctx->state != CHACHAPOLY_STATE_AAD )
return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
- }
ctx->aad_len += aad_len;
@@ -201,18 +192,12 @@ int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx,
unsigned char *output )
{
int ret;
+ CHACHAPOLY_VALIDATE_RET( ctx != NULL );
+ CHACHAPOLY_VALIDATE_RET( len == 0 || input != NULL );
+ CHACHAPOLY_VALIDATE_RET( len == 0 || output != NULL );
- if( ctx == NULL )
- {
- return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
- }
- else if( ( len > 0U ) && ( ( input == NULL ) || ( output == NULL ) ) )
- {
- /* input and output pointers are allowed to be NULL if len == 0 */
- return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
- }
- else if( ( ctx->state != CHACHAPOLY_STATE_AAD ) &&
- ( ctx->state != CHACHAPOLY_STATE_CIPHERTEXT ) )
+ if( ( ctx->state != CHACHAPOLY_STATE_AAD ) &&
+ ( ctx->state != CHACHAPOLY_STATE_CIPHERTEXT ) )
{
return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
}
@@ -257,12 +242,10 @@ int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx,
{
int ret;
unsigned char len_block[16];
+ CHACHAPOLY_VALIDATE_RET( ctx != NULL );
+ CHACHAPOLY_VALIDATE_RET( mac != NULL );
- if( ( ctx == NULL ) || ( mac == NULL ) )
- {
- return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
- }
- else if( ctx->state == CHACHAPOLY_STATE_INIT )
+ if( ctx->state == CHACHAPOLY_STATE_INIT )
{
return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
}
@@ -350,6 +333,13 @@ int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx,
unsigned char *output,
unsigned char tag[16] )
{
+ CHACHAPOLY_VALIDATE_RET( ctx != NULL );
+ CHACHAPOLY_VALIDATE_RET( nonce != NULL );
+ CHACHAPOLY_VALIDATE_RET( tag != NULL );
+ CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL );
+ CHACHAPOLY_VALIDATE_RET( length == 0 || input != NULL );
+ CHACHAPOLY_VALIDATE_RET( length == 0 || output != NULL );
+
return( chachapoly_crypt_and_tag( ctx, MBEDTLS_CHACHAPOLY_ENCRYPT,
length, nonce, aad, aad_len,
input, output, tag ) );
@@ -368,9 +358,12 @@ int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx,
unsigned char check_tag[16];
size_t i;
int diff;
-
- if( tag == NULL )
- return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+ CHACHAPOLY_VALIDATE_RET( ctx != NULL );
+ CHACHAPOLY_VALIDATE_RET( nonce != NULL );
+ CHACHAPOLY_VALIDATE_RET( tag != NULL );
+ CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL );
+ CHACHAPOLY_VALIDATE_RET( length == 0 || input != NULL );
+ CHACHAPOLY_VALIDATE_RET( length == 0 || output != NULL );
if( ( ret = chachapoly_crypt_and_tag( ctx,
MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce,
diff --git a/thirdparty/mbedtls/library/cipher.c b/thirdparty/mbedtls/library/cipher.c
index 7ae6c4ac5d..273997577b 100644
--- a/thirdparty/mbedtls/library/cipher.c
+++ b/thirdparty/mbedtls/library/cipher.c
@@ -65,6 +65,11 @@
#define mbedtls_free free
#endif
+#define CIPHER_VALIDATE_RET( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA )
+#define CIPHER_VALIDATE( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE( cond )
+
#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
/* Compare the contents of two buffers in constant time.
* Returns 0 if the contents are bitwise identical, otherwise returns
@@ -81,7 +86,7 @@ static int mbedtls_constant_time_memcmp( const void *v1, const void *v2, size_t
for( diff = 0, i = 0; i < len; i++ )
diff |= p1[i] ^ p2[i];
- return (int)diff;
+ return( (int)diff );
}
#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */
@@ -150,6 +155,7 @@ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_ciph
void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx )
{
+ CIPHER_VALIDATE( ctx != NULL );
memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) );
}
@@ -175,7 +181,8 @@ void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx )
int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info )
{
- if( NULL == cipher_info || NULL == ctx )
+ CIPHER_VALIDATE_RET( ctx != NULL );
+ if( cipher_info == NULL )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) );
@@ -199,10 +206,16 @@ int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_in
return( 0 );
}
-int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *key,
- int key_bitlen, const mbedtls_operation_t operation )
+int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx,
+ const unsigned char *key,
+ int key_bitlen,
+ const mbedtls_operation_t operation )
{
- if( NULL == ctx || NULL == ctx->cipher_info )
+ CIPHER_VALIDATE_RET( ctx != NULL );
+ CIPHER_VALIDATE_RET( key != NULL );
+ CIPHER_VALIDATE_RET( operation == MBEDTLS_ENCRYPT ||
+ operation == MBEDTLS_DECRYPT );
+ if( ctx->cipher_info == NULL )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_KEY_LEN ) == 0 &&
@@ -222,23 +235,26 @@ int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *k
MBEDTLS_MODE_OFB == ctx->cipher_info->mode ||
MBEDTLS_MODE_CTR == ctx->cipher_info->mode )
{
- return ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key,
- ctx->key_bitlen );
+ return( ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key,
+ ctx->key_bitlen ) );
}
if( MBEDTLS_DECRYPT == operation )
- return ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key,
- ctx->key_bitlen );
+ return( ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key,
+ ctx->key_bitlen ) );
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
}
int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx,
- const unsigned char *iv, size_t iv_len )
+ const unsigned char *iv,
+ size_t iv_len )
{
size_t actual_iv_size;
- if( NULL == ctx || NULL == ctx->cipher_info || NULL == iv )
+ CIPHER_VALIDATE_RET( ctx != NULL );
+ CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL );
+ if( ctx->cipher_info == NULL )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
/* avoid buffer overflow in ctx->iv */
@@ -268,15 +284,19 @@ int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx,
}
#endif
- memcpy( ctx->iv, iv, actual_iv_size );
- ctx->iv_size = actual_iv_size;
+ if ( actual_iv_size != 0 )
+ {
+ memcpy( ctx->iv, iv, actual_iv_size );
+ ctx->iv_size = actual_iv_size;
+ }
return( 0 );
}
int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx )
{
- if( NULL == ctx || NULL == ctx->cipher_info )
+ CIPHER_VALIDATE_RET( ctx != NULL );
+ if( ctx->cipher_info == NULL )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
ctx->unprocessed_len = 0;
@@ -288,14 +308,16 @@ int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx )
int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx,
const unsigned char *ad, size_t ad_len )
{
- if( NULL == ctx || NULL == ctx->cipher_info )
+ CIPHER_VALIDATE_RET( ctx != NULL );
+ CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL );
+ if( ctx->cipher_info == NULL )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
#if defined(MBEDTLS_GCM_C)
if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
{
- return mbedtls_gcm_starts( (mbedtls_gcm_context *) ctx->cipher_ctx, ctx->operation,
- ctx->iv, ctx->iv_size, ad, ad_len );
+ return( mbedtls_gcm_starts( (mbedtls_gcm_context *) ctx->cipher_ctx, ctx->operation,
+ ctx->iv, ctx->iv_size, ad, ad_len ) );
}
#endif
@@ -315,8 +337,8 @@ int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx,
if ( result != 0 )
return( result );
- return mbedtls_chachapoly_update_aad( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
- ad, ad_len );
+ return( mbedtls_chachapoly_update_aad( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
+ ad, ad_len ) );
}
#endif
@@ -328,12 +350,14 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i
size_t ilen, unsigned char *output, size_t *olen )
{
int ret;
- size_t block_size = 0;
+ size_t block_size;
- if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen )
- {
+ CIPHER_VALIDATE_RET( ctx != NULL );
+ CIPHER_VALIDATE_RET( ilen == 0 || input != NULL );
+ CIPHER_VALIDATE_RET( output != NULL );
+ CIPHER_VALIDATE_RET( olen != NULL );
+ if( ctx->cipher_info == NULL )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
- }
*olen = 0;
block_size = mbedtls_cipher_get_block_size( ctx );
@@ -358,8 +382,8 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i
if( ctx->cipher_info->mode == MBEDTLS_MODE_GCM )
{
*olen = ilen;
- return mbedtls_gcm_update( (mbedtls_gcm_context *) ctx->cipher_ctx, ilen, input,
- output );
+ return( mbedtls_gcm_update( (mbedtls_gcm_context *) ctx->cipher_ctx, ilen, input,
+ output ) );
}
#endif
@@ -367,14 +391,14 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i
if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 )
{
*olen = ilen;
- return mbedtls_chachapoly_update( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
- ilen, input, output );
+ return( mbedtls_chachapoly_update( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
+ ilen, input, output ) );
}
#endif
if ( 0 == block_size )
{
- return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT;
+ return( MBEDTLS_ERR_CIPHER_INVALID_CONTEXT );
}
if( input == output &&
@@ -437,7 +461,7 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i
{
if( 0 == block_size )
{
- return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT;
+ return( MBEDTLS_ERR_CIPHER_INVALID_CONTEXT );
}
/* Encryption: only cache partial blocks
@@ -738,7 +762,10 @@ static int get_no_padding( unsigned char *input, size_t input_len,
int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx,
unsigned char *output, size_t *olen )
{
- if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen )
+ CIPHER_VALIDATE_RET( ctx != NULL );
+ CIPHER_VALIDATE_RET( output != NULL );
+ CIPHER_VALIDATE_RET( olen != NULL );
+ if( ctx->cipher_info == NULL )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
*olen = 0;
@@ -808,8 +835,8 @@ int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx,
/* Set output size for decryption */
if( MBEDTLS_DECRYPT == ctx->operation )
- return ctx->get_padding( output, mbedtls_cipher_get_block_size( ctx ),
- olen );
+ return( ctx->get_padding( output, mbedtls_cipher_get_block_size( ctx ),
+ olen ) );
/* Set output size for encryption */
*olen = mbedtls_cipher_get_block_size( ctx );
@@ -823,10 +850,12 @@ int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx,
}
#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
-int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode )
+int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx,
+ mbedtls_cipher_padding_t mode )
{
- if( NULL == ctx ||
- MBEDTLS_MODE_CBC != ctx->cipher_info->mode )
+ CIPHER_VALIDATE_RET( ctx != NULL );
+
+ if( NULL == ctx->cipher_info || MBEDTLS_MODE_CBC != ctx->cipher_info->mode )
{
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
}
@@ -874,7 +903,9 @@ int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_ciph
int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx,
unsigned char *tag, size_t tag_len )
{
- if( NULL == ctx || NULL == ctx->cipher_info || NULL == tag )
+ CIPHER_VALIDATE_RET( ctx != NULL );
+ CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL );
+ if( ctx->cipher_info == NULL )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
if( MBEDTLS_ENCRYPT != ctx->operation )
@@ -882,7 +913,8 @@ int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx,
#if defined(MBEDTLS_GCM_C)
if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
- return mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, tag, tag_len );
+ return( mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx,
+ tag, tag_len ) );
#endif
#if defined(MBEDTLS_CHACHAPOLY_C)
@@ -892,8 +924,8 @@ int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx,
if ( tag_len != 16U )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
- return mbedtls_chachapoly_finish( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
- tag );
+ return( mbedtls_chachapoly_finish( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
+ tag ) );
}
#endif
@@ -906,8 +938,12 @@ int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx,
unsigned char check_tag[16];
int ret;
- if( NULL == ctx || NULL == ctx->cipher_info ||
- MBEDTLS_DECRYPT != ctx->operation )
+ CIPHER_VALIDATE_RET( ctx != NULL );
+ CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL );
+ if( ctx->cipher_info == NULL )
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+ if( MBEDTLS_DECRYPT != ctx->operation )
{
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
}
@@ -969,6 +1005,12 @@ int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx,
int ret;
size_t finish_olen;
+ CIPHER_VALIDATE_RET( ctx != NULL );
+ CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL );
+ CIPHER_VALIDATE_RET( ilen == 0 || input != NULL );
+ CIPHER_VALIDATE_RET( output != NULL );
+ CIPHER_VALIDATE_RET( olen != NULL );
+
if( ( ret = mbedtls_cipher_set_iv( ctx, iv, iv_len ) ) != 0 )
return( ret );
@@ -997,6 +1039,14 @@ int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx,
unsigned char *output, size_t *olen,
unsigned char *tag, size_t tag_len )
{
+ CIPHER_VALIDATE_RET( ctx != NULL );
+ CIPHER_VALIDATE_RET( iv != NULL );
+ CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL );
+ CIPHER_VALIDATE_RET( ilen == 0 || input != NULL );
+ CIPHER_VALIDATE_RET( output != NULL );
+ CIPHER_VALIDATE_RET( olen != NULL );
+ CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL );
+
#if defined(MBEDTLS_GCM_C)
if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
{
@@ -1044,6 +1094,14 @@ int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx,
unsigned char *output, size_t *olen,
const unsigned char *tag, size_t tag_len )
{
+ CIPHER_VALIDATE_RET( ctx != NULL );
+ CIPHER_VALIDATE_RET( iv != NULL );
+ CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL );
+ CIPHER_VALIDATE_RET( ilen == 0 || input != NULL );
+ CIPHER_VALIDATE_RET( output != NULL );
+ CIPHER_VALIDATE_RET( olen != NULL );
+ CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL );
+
#if defined(MBEDTLS_GCM_C)
if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
{
diff --git a/thirdparty/mbedtls/library/cipher_wrap.c b/thirdparty/mbedtls/library/cipher_wrap.c
index 893490acc8..6dd8c5d3a9 100644
--- a/thirdparty/mbedtls/library/cipher_wrap.c
+++ b/thirdparty/mbedtls/library/cipher_wrap.c
@@ -258,7 +258,7 @@ static const mbedtls_cipher_info_t aes_128_ecb_info = {
MBEDTLS_MODE_ECB,
128,
"AES-128-ECB",
- 16,
+ 0,
0,
16,
&aes_info
@@ -269,7 +269,7 @@ static const mbedtls_cipher_info_t aes_192_ecb_info = {
MBEDTLS_MODE_ECB,
192,
"AES-192-ECB",
- 16,
+ 0,
0,
16,
&aes_info
@@ -280,7 +280,7 @@ static const mbedtls_cipher_info_t aes_256_ecb_info = {
MBEDTLS_MODE_ECB,
256,
"AES-256-ECB",
- 16,
+ 0,
0,
16,
&aes_info
diff --git a/thirdparty/mbedtls/library/ctr_drbg.c b/thirdparty/mbedtls/library/ctr_drbg.c
index d0e5ba862d..fb121575bb 100644
--- a/thirdparty/mbedtls/library/ctr_drbg.c
+++ b/thirdparty/mbedtls/library/ctr_drbg.c
@@ -66,6 +66,18 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
* Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow
* NIST tests to succeed (which require known length fixed entropy)
*/
+/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
+ * mbedtls_ctr_drbg_seed_entropy_len(ctx, f_entropy, p_entropy,
+ * custom, len, entropy_len)
+ * implements
+ * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
+ * security_strength) -> initial_working_state
+ * with inputs
+ * custom[:len] = nonce || personalization_string
+ * where entropy_input comes from f_entropy for entropy_len bytes
+ * and with outputs
+ * ctx = initial_working_state
+ */
int mbedtls_ctr_drbg_seed_entropy_len(
mbedtls_ctr_drbg_context *ctx,
int (*f_entropy)(void *, unsigned char *, size_t),
@@ -256,6 +268,14 @@ exit:
return( ret );
}
+/* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
+ * ctr_drbg_update_internal(ctx, provided_data)
+ * implements
+ * CTR_DRBG_Update(provided_data, Key, V)
+ * with inputs and outputs
+ * ctx->aes_ctx = Key
+ * ctx->counter = V
+ */
static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
{
@@ -279,9 +299,7 @@ static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
* Crypt counter block
*/
if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ) ) != 0 )
- {
- return( ret );
- }
+ goto exit;
p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
}
@@ -293,31 +311,71 @@ static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
* Update key and counter
*/
if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
- {
- return( ret );
- }
+ goto exit;
memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE );
- return( 0 );
+exit:
+ mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
+ return( ret );
}
-void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
- const unsigned char *additional, size_t add_len )
+/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
+ * mbedtls_ctr_drbg_update(ctx, additional, add_len)
+ * implements
+ * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
+ * security_strength) -> initial_working_state
+ * with inputs
+ * ctx->counter = all-bits-0
+ * ctx->aes_ctx = context from all-bits-0 key
+ * additional[:add_len] = entropy_input || nonce || personalization_string
+ * and with outputs
+ * ctx = initial_working_state
+ */
+int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
+ const unsigned char *additional,
+ size_t add_len )
{
unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
+ int ret;
- if( add_len > 0 )
- {
- /* MAX_INPUT would be more logical here, but we have to match
- * block_cipher_df()'s limits since we can't propagate errors */
- if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
- add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
+ if( add_len == 0 )
+ return( 0 );
- block_cipher_df( add_input, additional, add_len );
- ctr_drbg_update_internal( ctx, add_input );
- }
+ if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
+ goto exit;
+ if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
+ goto exit;
+
+exit:
+ mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
+ return( ret );
}
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
+ const unsigned char *additional,
+ size_t add_len )
+{
+ /* MAX_INPUT would be more logical here, but we have to match
+ * block_cipher_df()'s limits since we can't propagate errors */
+ if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
+ add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
+ (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
+}
+#endif /* MBEDTLS_DEPRECATED_REMOVED */
+
+/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
+ * mbedtls_ctr_drbg_reseed(ctx, additional, len)
+ * implements
+ * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
+ * -> new_working_state
+ * with inputs
+ * ctx contains working_state
+ * additional[:len] = additional_input
+ * and entropy_input comes from calling ctx->f_entropy
+ * and with output
+ * ctx contains new_working_state
+ */
int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
const unsigned char *additional, size_t len )
{
@@ -355,22 +413,39 @@ int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
* Reduce to 384 bits
*/
if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
- {
- return( ret );
- }
+ goto exit;
/*
* Update state
*/
if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
- {
- return( ret );
- }
+ goto exit;
ctx->reseed_counter = 1;
- return( 0 );
+exit:
+ mbedtls_platform_zeroize( seed, sizeof( seed ) );
+ return( ret );
}
+/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
+ * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
+ * implements
+ * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
+ * -> working_state_after_reseed
+ * if required, then
+ * CTR_DRBG_Generate(working_state_after_reseed,
+ * requested_number_of_bits, additional_input)
+ * -> status, returned_bits, new_working_state
+ * with inputs
+ * ctx contains working_state
+ * requested_number_of_bits = 8 * output_len
+ * additional[:add_len] = additional_input
+ * and entropy_input comes from calling ctx->f_entropy
+ * and with outputs
+ * status = SUCCESS (this function does the reseed internally)
+ * returned_bits = output[:output_len]
+ * ctx contains new_working_state
+ */
int mbedtls_ctr_drbg_random_with_add( void *p_rng,
unsigned char *output, size_t output_len,
const unsigned char *additional, size_t add_len )
@@ -404,13 +479,9 @@ int mbedtls_ctr_drbg_random_with_add( void *p_rng,
if( add_len > 0 )
{
if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
- {
- return( ret );
- }
+ goto exit;
if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
- {
- return( ret );
- }
+ goto exit;
}
while( output_len > 0 )
@@ -426,9 +497,7 @@ int mbedtls_ctr_drbg_random_with_add( void *p_rng,
* Crypt counter block
*/
if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 )
- {
- return( ret );
- }
+ goto exit;
use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
output_len;
@@ -441,12 +510,13 @@ int mbedtls_ctr_drbg_random_with_add( void *p_rng,
}
if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
- {
- return( ret );
- }
+ goto exit;
ctx->reseed_counter++;
+exit:
+ mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
+ mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
return( 0 );
}
@@ -498,35 +568,36 @@ exit:
int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
{
int ret = 0;
- FILE *f;
+ FILE *f = NULL;
size_t n;
unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
+ unsigned char c;
if( ( f = fopen( path, "rb" ) ) == NULL )
return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
- fseek( f, 0, SEEK_END );
- n = (size_t) ftell( f );
- fseek( f, 0, SEEK_SET );
-
- if( n > MBEDTLS_CTR_DRBG_MAX_INPUT )
+ n = fread( buf, 1, sizeof( buf ), f );
+ if( fread( &c, 1, 1, f ) != 0 )
{
- fclose( f );
- return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
+ ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
+ goto exit;
}
-
- if( fread( buf, 1, n, f ) != n )
+ if( n == 0 || ferror( f ) )
+ {
ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
- else
- mbedtls_ctr_drbg_update( ctx, buf, n );
-
+ goto exit;
+ }
fclose( f );
+ f = NULL;
- mbedtls_platform_zeroize( buf, sizeof( buf ) );
+ ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
+exit:
+ mbedtls_platform_zeroize( buf, sizeof( buf ) );
+ if( f != NULL )
+ fclose( f );
if( ret != 0 )
return( ret );
-
return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
}
#endif /* MBEDTLS_FS_IO */
diff --git a/thirdparty/mbedtls/library/debug.c b/thirdparty/mbedtls/library/debug.c
index db3924ac54..824cd0236e 100644
--- a/thirdparty/mbedtls/library/debug.c
+++ b/thirdparty/mbedtls/library/debug.c
@@ -365,4 +365,54 @@ void mbedtls_debug_print_crt( const mbedtls_ssl_context *ssl, int level,
}
#endif /* MBEDTLS_X509_CRT_PARSE_C */
+#if defined(MBEDTLS_ECDH_C)
+static void mbedtls_debug_printf_ecdh_internal( const mbedtls_ssl_context *ssl,
+ int level, const char *file,
+ int line,
+ const mbedtls_ecdh_context *ecdh,
+ mbedtls_debug_ecdh_attr attr )
+{
+#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
+ const mbedtls_ecdh_context* ctx = ecdh;
+#else
+ const mbedtls_ecdh_context_mbed* ctx = &ecdh->ctx.mbed_ecdh;
+#endif
+
+ switch( attr )
+ {
+ case MBEDTLS_DEBUG_ECDH_Q:
+ mbedtls_debug_print_ecp( ssl, level, file, line, "ECDH: Q",
+ &ctx->Q );
+ break;
+ case MBEDTLS_DEBUG_ECDH_QP:
+ mbedtls_debug_print_ecp( ssl, level, file, line, "ECDH: Qp",
+ &ctx->Qp );
+ break;
+ case MBEDTLS_DEBUG_ECDH_Z:
+ mbedtls_debug_print_mpi( ssl, level, file, line, "ECDH: z",
+ &ctx->z );
+ break;
+ default:
+ break;
+ }
+}
+
+void mbedtls_debug_printf_ecdh( const mbedtls_ssl_context *ssl, int level,
+ const char *file, int line,
+ const mbedtls_ecdh_context *ecdh,
+ mbedtls_debug_ecdh_attr attr )
+{
+#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
+ mbedtls_debug_printf_ecdh_internal( ssl, level, file, line, ecdh, attr );
+#else
+ switch( ecdh->var )
+ {
+ default:
+ mbedtls_debug_printf_ecdh_internal( ssl, level, file, line, ecdh,
+ attr );
+ }
+#endif
+}
+#endif /* MBEDTLS_ECDH_C */
+
#endif /* MBEDTLS_DEBUG_C */
diff --git a/thirdparty/mbedtls/library/dhm.c b/thirdparty/mbedtls/library/dhm.c
index 82cbb0ce88..fb6937e854 100644
--- a/thirdparty/mbedtls/library/dhm.c
+++ b/thirdparty/mbedtls/library/dhm.c
@@ -60,6 +60,11 @@
#if !defined(MBEDTLS_DHM_ALT)
+#define DHM_VALIDATE_RET( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_DHM_BAD_INPUT_DATA )
+#define DHM_VALIDATE( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE( cond )
+
/*
* helper to validate the mbedtls_mpi size and import it
*/
@@ -121,6 +126,7 @@ cleanup:
void mbedtls_dhm_init( mbedtls_dhm_context *ctx )
{
+ DHM_VALIDATE( ctx != NULL );
memset( ctx, 0, sizeof( mbedtls_dhm_context ) );
}
@@ -132,6 +138,9 @@ int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx,
const unsigned char *end )
{
int ret;
+ DHM_VALIDATE_RET( ctx != NULL );
+ DHM_VALIDATE_RET( p != NULL && *p != NULL );
+ DHM_VALIDATE_RET( end != NULL );
if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 ||
( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 ||
@@ -157,6 +166,10 @@ int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size,
int ret, count = 0;
size_t n1, n2, n3;
unsigned char *p;
+ DHM_VALIDATE_RET( ctx != NULL );
+ DHM_VALIDATE_RET( output != NULL );
+ DHM_VALIDATE_RET( olen != NULL );
+ DHM_VALIDATE_RET( f_rng != NULL );
if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
@@ -227,9 +240,9 @@ int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx,
const mbedtls_mpi *G )
{
int ret;
-
- if( ctx == NULL || P == NULL || G == NULL )
- return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
+ DHM_VALIDATE_RET( ctx != NULL );
+ DHM_VALIDATE_RET( P != NULL );
+ DHM_VALIDATE_RET( G != NULL );
if( ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ||
( ret = mbedtls_mpi_copy( &ctx->G, G ) ) != 0 )
@@ -248,8 +261,10 @@ int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx,
const unsigned char *input, size_t ilen )
{
int ret;
+ DHM_VALIDATE_RET( ctx != NULL );
+ DHM_VALIDATE_RET( input != NULL );
- if( ctx == NULL || ilen < 1 || ilen > ctx->len )
+ if( ilen < 1 || ilen > ctx->len )
return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
if( ( ret = mbedtls_mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 )
@@ -267,8 +282,11 @@ int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size,
void *p_rng )
{
int ret, count = 0;
+ DHM_VALIDATE_RET( ctx != NULL );
+ DHM_VALIDATE_RET( output != NULL );
+ DHM_VALIDATE_RET( f_rng != NULL );
- if( ctx == NULL || olen < 1 || olen > ctx->len )
+ if( olen < 1 || olen > ctx->len )
return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
@@ -380,8 +398,11 @@ int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx,
{
int ret;
mbedtls_mpi GYb;
+ DHM_VALIDATE_RET( ctx != NULL );
+ DHM_VALIDATE_RET( output != NULL );
+ DHM_VALIDATE_RET( olen != NULL );
- if( ctx == NULL || output_size < ctx->len )
+ if( output_size < ctx->len )
return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
@@ -428,11 +449,19 @@ cleanup:
*/
void mbedtls_dhm_free( mbedtls_dhm_context *ctx )
{
- mbedtls_mpi_free( &ctx->pX ); mbedtls_mpi_free( &ctx->Vf );
- mbedtls_mpi_free( &ctx->Vi ); mbedtls_mpi_free( &ctx->RP );
- mbedtls_mpi_free( &ctx->K ); mbedtls_mpi_free( &ctx->GY );
- mbedtls_mpi_free( &ctx->GX ); mbedtls_mpi_free( &ctx->X );
- mbedtls_mpi_free( &ctx->G ); mbedtls_mpi_free( &ctx->P );
+ if( ctx == NULL )
+ return;
+
+ mbedtls_mpi_free( &ctx->pX );
+ mbedtls_mpi_free( &ctx->Vf );
+ mbedtls_mpi_free( &ctx->Vi );
+ mbedtls_mpi_free( &ctx->RP );
+ mbedtls_mpi_free( &ctx->K );
+ mbedtls_mpi_free( &ctx->GY );
+ mbedtls_mpi_free( &ctx->GX );
+ mbedtls_mpi_free( &ctx->X );
+ mbedtls_mpi_free( &ctx->G );
+ mbedtls_mpi_free( &ctx->P );
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_dhm_context ) );
}
@@ -449,7 +478,12 @@ int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin,
unsigned char *p, *end;
#if defined(MBEDTLS_PEM_PARSE_C)
mbedtls_pem_context pem;
+#endif /* MBEDTLS_PEM_PARSE_C */
+
+ DHM_VALIDATE_RET( dhm != NULL );
+ DHM_VALIDATE_RET( dhmin != NULL );
+#if defined(MBEDTLS_PEM_PARSE_C)
mbedtls_pem_init( &pem );
/* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
@@ -596,6 +630,8 @@ int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path )
int ret;
size_t n;
unsigned char *buf;
+ DHM_VALIDATE_RET( dhm != NULL );
+ DHM_VALIDATE_RET( path != NULL );
if( ( ret = load_file( path, &buf, &n ) ) != 0 )
return( ret );
diff --git a/thirdparty/mbedtls/library/ecdh.c b/thirdparty/mbedtls/library/ecdh.c
index 61380b6936..da95c60dad 100644
--- a/thirdparty/mbedtls/library/ecdh.c
+++ b/thirdparty/mbedtls/library/ecdh.c
@@ -35,41 +35,82 @@
#if defined(MBEDTLS_ECDH_C)
#include "mbedtls/ecdh.h"
+#include "mbedtls/platform_util.h"
#include <string.h>
+/* Parameter validation macros based on platform_util.h */
+#define ECDH_VALIDATE_RET( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
+#define ECDH_VALIDATE( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE( cond )
+
+#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
+typedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed;
+#endif
+
#if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT)
/*
- * Generate public key: simple wrapper around mbedtls_ecp_gen_keypair
+ * Generate public key (restartable version)
+ *
+ * Note: this internal function relies on its caller preserving the value of
+ * the output parameter 'd' across continuation calls. This would not be
+ * acceptable for a public function but is OK here as we control call sites.
+ */
+static int ecdh_gen_public_restartable( mbedtls_ecp_group *grp,
+ mbedtls_mpi *d, mbedtls_ecp_point *Q,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ mbedtls_ecp_restart_ctx *rs_ctx )
+{
+ int ret;
+
+ /* If multiplication is in progress, we already generated a privkey */
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx == NULL || rs_ctx->rsm == NULL )
+#endif
+ MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
+
+ MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, Q, d, &grp->G,
+ f_rng, p_rng, rs_ctx ) );
+
+cleanup:
+ return( ret );
+}
+
+/*
+ * Generate public key
*/
int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
- return mbedtls_ecp_gen_keypair( grp, d, Q, f_rng, p_rng );
+ ECDH_VALIDATE_RET( grp != NULL );
+ ECDH_VALIDATE_RET( d != NULL );
+ ECDH_VALIDATE_RET( Q != NULL );
+ ECDH_VALIDATE_RET( f_rng != NULL );
+ return( ecdh_gen_public_restartable( grp, d, Q, f_rng, p_rng, NULL ) );
}
-#endif /* MBEDTLS_ECDH_GEN_PUBLIC_ALT */
+#endif /* !MBEDTLS_ECDH_GEN_PUBLIC_ALT */
#if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT)
/*
* Compute shared secret (SEC1 3.3.1)
*/
-int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z,
+static int ecdh_compute_shared_restartable( mbedtls_ecp_group *grp,
+ mbedtls_mpi *z,
const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
int (*f_rng)(void *, unsigned char *, size_t),
- void *p_rng )
+ void *p_rng,
+ mbedtls_ecp_restart_ctx *rs_ctx )
{
int ret;
mbedtls_ecp_point P;
mbedtls_ecp_point_init( &P );
- /*
- * Make sure Q is a valid pubkey before using it
- */
- MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, Q ) );
-
- MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, &P, d, Q, f_rng, p_rng ) );
+ MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &P, d, Q,
+ f_rng, p_rng, rs_ctx ) );
if( mbedtls_ecp_is_zero( &P ) )
{
@@ -84,65 +125,195 @@ cleanup:
return( ret );
}
-#endif /* MBEDTLS_ECDH_COMPUTE_SHARED_ALT */
+
+/*
+ * Compute shared secret (SEC1 3.3.1)
+ */
+int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z,
+ const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ ECDH_VALIDATE_RET( grp != NULL );
+ ECDH_VALIDATE_RET( Q != NULL );
+ ECDH_VALIDATE_RET( d != NULL );
+ ECDH_VALIDATE_RET( z != NULL );
+ return( ecdh_compute_shared_restartable( grp, z, Q, d,
+ f_rng, p_rng, NULL ) );
+}
+#endif /* !MBEDTLS_ECDH_COMPUTE_SHARED_ALT */
+
+static void ecdh_init_internal( mbedtls_ecdh_context_mbed *ctx )
+{
+ mbedtls_ecp_group_init( &ctx->grp );
+ mbedtls_mpi_init( &ctx->d );
+ mbedtls_ecp_point_init( &ctx->Q );
+ mbedtls_ecp_point_init( &ctx->Qp );
+ mbedtls_mpi_init( &ctx->z );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ mbedtls_ecp_restart_init( &ctx->rs );
+#endif
+}
/*
* Initialize context
*/
void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx )
{
+ ECDH_VALIDATE( ctx != NULL );
+
+#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
+ ecdh_init_internal( ctx );
+ mbedtls_ecp_point_init( &ctx->Vi );
+ mbedtls_ecp_point_init( &ctx->Vf );
+ mbedtls_mpi_init( &ctx->_d );
+#else
memset( ctx, 0, sizeof( mbedtls_ecdh_context ) );
+
+ ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
+#endif
+ ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ ctx->restart_enabled = 0;
+#endif
+}
+
+static int ecdh_setup_internal( mbedtls_ecdh_context_mbed *ctx,
+ mbedtls_ecp_group_id grp_id )
+{
+ int ret;
+
+ ret = mbedtls_ecp_group_load( &ctx->grp, grp_id );
+ if( ret != 0 )
+ {
+ return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+ }
+
+ return( 0 );
}
/*
- * Free context
+ * Setup context
*/
-void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx )
+int mbedtls_ecdh_setup( mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id )
{
- if( ctx == NULL )
- return;
+ ECDH_VALIDATE_RET( ctx != NULL );
+#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
+ return( ecdh_setup_internal( ctx, grp_id ) );
+#else
+ switch( grp_id )
+ {
+ default:
+ ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
+ ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0;
+ ctx->grp_id = grp_id;
+ ecdh_init_internal( &ctx->ctx.mbed_ecdh );
+ return( ecdh_setup_internal( &ctx->ctx.mbed_ecdh, grp_id ) );
+ }
+#endif
+}
+
+static void ecdh_free_internal( mbedtls_ecdh_context_mbed *ctx )
+{
mbedtls_ecp_group_free( &ctx->grp );
+ mbedtls_mpi_free( &ctx->d );
mbedtls_ecp_point_free( &ctx->Q );
mbedtls_ecp_point_free( &ctx->Qp );
- mbedtls_ecp_point_free( &ctx->Vi );
- mbedtls_ecp_point_free( &ctx->Vf );
- mbedtls_mpi_free( &ctx->d );
mbedtls_mpi_free( &ctx->z );
- mbedtls_mpi_free( &ctx->_d );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ mbedtls_ecp_restart_free( &ctx->rs );
+#endif
}
+#if defined(MBEDTLS_ECP_RESTARTABLE)
/*
- * Setup and write the ServerKeyExhange parameters (RFC 4492)
- * struct {
- * ECParameters curve_params;
- * ECPoint public;
- * } ServerECDHParams;
+ * Enable restartable operations for context
*/
-int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen,
- unsigned char *buf, size_t blen,
- int (*f_rng)(void *, unsigned char *, size_t),
- void *p_rng )
+void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx )
+{
+ ECDH_VALIDATE( ctx != NULL );
+
+ ctx->restart_enabled = 1;
+}
+#endif
+
+/*
+ * Free context
+ */
+void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx )
+{
+ if( ctx == NULL )
+ return;
+
+#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
+ mbedtls_ecp_point_free( &ctx->Vi );
+ mbedtls_ecp_point_free( &ctx->Vf );
+ mbedtls_mpi_free( &ctx->_d );
+ ecdh_free_internal( ctx );
+#else
+ switch( ctx->var )
+ {
+ case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
+ ecdh_free_internal( &ctx->ctx.mbed_ecdh );
+ break;
+ default:
+ break;
+ }
+
+ ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
+ ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
+ ctx->grp_id = MBEDTLS_ECP_DP_NONE;
+#endif
+}
+
+static int ecdh_make_params_internal( mbedtls_ecdh_context_mbed *ctx,
+ size_t *olen, int point_format,
+ unsigned char *buf, size_t blen,
+ int (*f_rng)(void *,
+ unsigned char *,
+ size_t),
+ void *p_rng,
+ int restart_enabled )
{
int ret;
size_t grp_len, pt_len;
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ mbedtls_ecp_restart_ctx *rs_ctx = NULL;
+#endif
- if( ctx == NULL || ctx->grp.pbits == 0 )
+ if( ctx->grp.pbits == 0 )
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
- if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) )
- != 0 )
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( restart_enabled )
+ rs_ctx = &ctx->rs;
+#else
+ (void) restart_enabled;
+#endif
+
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q,
+ f_rng, p_rng, rs_ctx ) ) != 0 )
return( ret );
+#else
+ if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q,
+ f_rng, p_rng ) ) != 0 )
+ return( ret );
+#endif /* MBEDTLS_ECP_RESTARTABLE */
- if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp, &grp_len, buf, blen ) )
- != 0 )
+ if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp, &grp_len, buf,
+ blen ) ) != 0 )
return( ret );
buf += grp_len;
blen -= grp_len;
- if( ( ret = mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format,
- &pt_len, buf, blen ) ) != 0 )
+ if( ( ret = mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, point_format,
+ &pt_len, buf, blen ) ) != 0 )
return( ret );
*olen = grp_len + pt_len;
@@ -150,6 +321,55 @@ int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen,
}
/*
+ * Setup and write the ServerKeyExhange parameters (RFC 4492)
+ * struct {
+ * ECParameters curve_params;
+ * ECPoint public;
+ * } ServerECDHParams;
+ */
+int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen,
+ unsigned char *buf, size_t blen,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ int restart_enabled = 0;
+ ECDH_VALIDATE_RET( ctx != NULL );
+ ECDH_VALIDATE_RET( olen != NULL );
+ ECDH_VALIDATE_RET( buf != NULL );
+ ECDH_VALIDATE_RET( f_rng != NULL );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ restart_enabled = ctx->restart_enabled;
+#else
+ (void) restart_enabled;
+#endif
+
+#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
+ return( ecdh_make_params_internal( ctx, olen, ctx->point_format, buf, blen,
+ f_rng, p_rng, restart_enabled ) );
+#else
+ switch( ctx->var )
+ {
+ case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
+ return( ecdh_make_params_internal( &ctx->ctx.mbed_ecdh, olen,
+ ctx->point_format, buf, blen,
+ f_rng, p_rng,
+ restart_enabled ) );
+ default:
+ return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+ }
+#endif
+}
+
+static int ecdh_read_params_internal( mbedtls_ecdh_context_mbed *ctx,
+ const unsigned char **buf,
+ const unsigned char *end )
+{
+ return( mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, buf,
+ end - *buf ) );
+}
+
+/*
* Read the ServerKeyExhange parameters (RFC 4492)
* struct {
* ECParameters curve_params;
@@ -157,31 +377,43 @@ int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen,
* } ServerECDHParams;
*/
int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx,
- const unsigned char **buf, const unsigned char *end )
+ const unsigned char **buf,
+ const unsigned char *end )
{
int ret;
-
- if( ( ret = mbedtls_ecp_tls_read_group( &ctx->grp, buf, end - *buf ) ) != 0 )
+ mbedtls_ecp_group_id grp_id;
+ ECDH_VALIDATE_RET( ctx != NULL );
+ ECDH_VALIDATE_RET( buf != NULL );
+ ECDH_VALIDATE_RET( *buf != NULL );
+ ECDH_VALIDATE_RET( end != NULL );
+
+ if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, end - *buf ) )
+ != 0 )
return( ret );
- if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, buf, end - *buf ) )
- != 0 )
+ if( ( ret = mbedtls_ecdh_setup( ctx, grp_id ) ) != 0 )
return( ret );
- return( 0 );
+#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
+ return( ecdh_read_params_internal( ctx, buf, end ) );
+#else
+ switch( ctx->var )
+ {
+ case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
+ return( ecdh_read_params_internal( &ctx->ctx.mbed_ecdh,
+ buf, end ) );
+ default:
+ return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+ }
+#endif
}
-/*
- * Get parameters from a keypair
- */
-int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypair *key,
- mbedtls_ecdh_side side )
+static int ecdh_get_params_internal( mbedtls_ecdh_context_mbed *ctx,
+ const mbedtls_ecp_keypair *key,
+ mbedtls_ecdh_side side )
{
int ret;
- if( ( ret = mbedtls_ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 )
- return( ret );
-
/* If it's not our key, just import the public part as Qp */
if( side == MBEDTLS_ECDH_THEIRS )
return( mbedtls_ecp_copy( &ctx->Qp, &key->Q ) );
@@ -198,39 +430,116 @@ int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypai
}
/*
- * Setup and export the client public value
+ * Get parameters from a keypair
*/
-int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen,
- unsigned char *buf, size_t blen,
- int (*f_rng)(void *, unsigned char *, size_t),
- void *p_rng )
+int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx,
+ const mbedtls_ecp_keypair *key,
+ mbedtls_ecdh_side side )
{
int ret;
+ ECDH_VALIDATE_RET( ctx != NULL );
+ ECDH_VALIDATE_RET( key != NULL );
+ ECDH_VALIDATE_RET( side == MBEDTLS_ECDH_OURS ||
+ side == MBEDTLS_ECDH_THEIRS );
- if( ctx == NULL || ctx->grp.pbits == 0 )
+ if( ( ret = mbedtls_ecdh_setup( ctx, key->grp.id ) ) != 0 )
+ return( ret );
+
+#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
+ return( ecdh_get_params_internal( ctx, key, side ) );
+#else
+ switch( ctx->var )
+ {
+ case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
+ return( ecdh_get_params_internal( &ctx->ctx.mbed_ecdh,
+ key, side ) );
+ default:
+ return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+ }
+#endif
+}
+
+static int ecdh_make_public_internal( mbedtls_ecdh_context_mbed *ctx,
+ size_t *olen, int point_format,
+ unsigned char *buf, size_t blen,
+ int (*f_rng)(void *,
+ unsigned char *,
+ size_t),
+ void *p_rng,
+ int restart_enabled )
+{
+ int ret;
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ mbedtls_ecp_restart_ctx *rs_ctx = NULL;
+#endif
+
+ if( ctx->grp.pbits == 0 )
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
- if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) )
- != 0 )
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( restart_enabled )
+ rs_ctx = &ctx->rs;
+#else
+ (void) restart_enabled;
+#endif
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q,
+ f_rng, p_rng, rs_ctx ) ) != 0 )
+ return( ret );
+#else
+ if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q,
+ f_rng, p_rng ) ) != 0 )
return( ret );
+#endif /* MBEDTLS_ECP_RESTARTABLE */
- return mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format,
- olen, buf, blen );
+ return mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, point_format, olen,
+ buf, blen );
}
/*
- * Parse and import the client's public value
+ * Setup and export the client public value
*/
-int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx,
- const unsigned char *buf, size_t blen )
+int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen,
+ unsigned char *buf, size_t blen,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ int restart_enabled = 0;
+ ECDH_VALIDATE_RET( ctx != NULL );
+ ECDH_VALIDATE_RET( olen != NULL );
+ ECDH_VALIDATE_RET( buf != NULL );
+ ECDH_VALIDATE_RET( f_rng != NULL );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ restart_enabled = ctx->restart_enabled;
+#endif
+
+#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
+ return( ecdh_make_public_internal( ctx, olen, ctx->point_format, buf, blen,
+ f_rng, p_rng, restart_enabled ) );
+#else
+ switch( ctx->var )
+ {
+ case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
+ return( ecdh_make_public_internal( &ctx->ctx.mbed_ecdh, olen,
+ ctx->point_format, buf, blen,
+ f_rng, p_rng,
+ restart_enabled ) );
+ default:
+ return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+ }
+#endif
+}
+
+static int ecdh_read_public_internal( mbedtls_ecdh_context_mbed *ctx,
+ const unsigned char *buf, size_t blen )
{
int ret;
const unsigned char *p = buf;
- if( ctx == NULL )
- return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
-
- if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, &p, blen ) ) != 0 )
+ if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, &p,
+ blen ) ) != 0 )
return( ret );
if( (size_t)( p - buf ) != blen )
@@ -240,23 +549,66 @@ int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx,
}
/*
- * Derive and export the shared secret
+ * Parse and import the client's public value
*/
-int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen,
- unsigned char *buf, size_t blen,
- int (*f_rng)(void *, unsigned char *, size_t),
- void *p_rng )
+int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx,
+ const unsigned char *buf, size_t blen )
+{
+ ECDH_VALIDATE_RET( ctx != NULL );
+ ECDH_VALIDATE_RET( buf != NULL );
+
+#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
+ return( ecdh_read_public_internal( ctx, buf, blen ) );
+#else
+ switch( ctx->var )
+ {
+ case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
+ return( ecdh_read_public_internal( &ctx->ctx.mbed_ecdh,
+ buf, blen ) );
+ default:
+ return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+ }
+#endif
+}
+
+static int ecdh_calc_secret_internal( mbedtls_ecdh_context_mbed *ctx,
+ size_t *olen, unsigned char *buf,
+ size_t blen,
+ int (*f_rng)(void *,
+ unsigned char *,
+ size_t),
+ void *p_rng,
+ int restart_enabled )
{
int ret;
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ mbedtls_ecp_restart_ctx *rs_ctx = NULL;
+#endif
- if( ctx == NULL )
+ if( ctx == NULL || ctx->grp.pbits == 0 )
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
- if( ( ret = mbedtls_ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp, &ctx->d,
- f_rng, p_rng ) ) != 0 )
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( restart_enabled )
+ rs_ctx = &ctx->rs;
+#else
+ (void) restart_enabled;
+#endif
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( ( ret = ecdh_compute_shared_restartable( &ctx->grp, &ctx->z, &ctx->Qp,
+ &ctx->d, f_rng, p_rng,
+ rs_ctx ) ) != 0 )
{
return( ret );
}
+#else
+ if( ( ret = mbedtls_ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp,
+ &ctx->d, f_rng, p_rng ) ) != 0 )
+ {
+ return( ret );
+ }
+#endif /* MBEDTLS_ECP_RESTARTABLE */
if( mbedtls_mpi_size( &ctx->z ) > blen )
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
@@ -265,4 +617,37 @@ int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen,
return mbedtls_mpi_write_binary( &ctx->z, buf, *olen );
}
+/*
+ * Derive and export the shared secret
+ */
+int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen,
+ unsigned char *buf, size_t blen,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ int restart_enabled = 0;
+ ECDH_VALIDATE_RET( ctx != NULL );
+ ECDH_VALIDATE_RET( olen != NULL );
+ ECDH_VALIDATE_RET( buf != NULL );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ restart_enabled = ctx->restart_enabled;
+#endif
+
+#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
+ return( ecdh_calc_secret_internal( ctx, olen, buf, blen, f_rng, p_rng,
+ restart_enabled ) );
+#else
+ switch( ctx->var )
+ {
+ case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
+ return( ecdh_calc_secret_internal( &ctx->ctx.mbed_ecdh, olen, buf,
+ blen, f_rng, p_rng,
+ restart_enabled ) );
+ default:
+ return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+ }
+#endif
+}
+
#endif /* MBEDTLS_ECDH_C */
diff --git a/thirdparty/mbedtls/library/ecdsa.c b/thirdparty/mbedtls/library/ecdsa.c
index 17a88bdd29..1204ef9949 100644
--- a/thirdparty/mbedtls/library/ecdsa.c
+++ b/thirdparty/mbedtls/library/ecdsa.c
@@ -42,6 +42,186 @@
#include "mbedtls/hmac_drbg.h"
#endif
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include <stdlib.h>
+#define mbedtls_calloc calloc
+#define mbedtls_free free
+#endif
+
+#include "mbedtls/platform_util.h"
+
+/* Parameter validation macros based on platform_util.h */
+#define ECDSA_VALIDATE_RET( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
+#define ECDSA_VALIDATE( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE( cond )
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+
+/*
+ * Sub-context for ecdsa_verify()
+ */
+struct mbedtls_ecdsa_restart_ver
+{
+ mbedtls_mpi u1, u2; /* intermediate values */
+ enum { /* what to do next? */
+ ecdsa_ver_init = 0, /* getting started */
+ ecdsa_ver_muladd, /* muladd step */
+ } state;
+};
+
+/*
+ * Init verify restart sub-context
+ */
+static void ecdsa_restart_ver_init( mbedtls_ecdsa_restart_ver_ctx *ctx )
+{
+ mbedtls_mpi_init( &ctx->u1 );
+ mbedtls_mpi_init( &ctx->u2 );
+ ctx->state = ecdsa_ver_init;
+}
+
+/*
+ * Free the components of a verify restart sub-context
+ */
+static void ecdsa_restart_ver_free( mbedtls_ecdsa_restart_ver_ctx *ctx )
+{
+ if( ctx == NULL )
+ return;
+
+ mbedtls_mpi_free( &ctx->u1 );
+ mbedtls_mpi_free( &ctx->u2 );
+
+ ecdsa_restart_ver_init( ctx );
+}
+
+/*
+ * Sub-context for ecdsa_sign()
+ */
+struct mbedtls_ecdsa_restart_sig
+{
+ int sign_tries;
+ int key_tries;
+ mbedtls_mpi k; /* per-signature random */
+ mbedtls_mpi r; /* r value */
+ enum { /* what to do next? */
+ ecdsa_sig_init = 0, /* getting started */
+ ecdsa_sig_mul, /* doing ecp_mul() */
+ ecdsa_sig_modn, /* mod N computations */
+ } state;
+};
+
+/*
+ * Init verify sign sub-context
+ */
+static void ecdsa_restart_sig_init( mbedtls_ecdsa_restart_sig_ctx *ctx )
+{
+ ctx->sign_tries = 0;
+ ctx->key_tries = 0;
+ mbedtls_mpi_init( &ctx->k );
+ mbedtls_mpi_init( &ctx->r );
+ ctx->state = ecdsa_sig_init;
+}
+
+/*
+ * Free the components of a sign restart sub-context
+ */
+static void ecdsa_restart_sig_free( mbedtls_ecdsa_restart_sig_ctx *ctx )
+{
+ if( ctx == NULL )
+ return;
+
+ mbedtls_mpi_free( &ctx->k );
+ mbedtls_mpi_free( &ctx->r );
+}
+
+#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
+/*
+ * Sub-context for ecdsa_sign_det()
+ */
+struct mbedtls_ecdsa_restart_det
+{
+ mbedtls_hmac_drbg_context rng_ctx; /* DRBG state */
+ enum { /* what to do next? */
+ ecdsa_det_init = 0, /* getting started */
+ ecdsa_det_sign, /* make signature */
+ } state;
+};
+
+/*
+ * Init verify sign_det sub-context
+ */
+static void ecdsa_restart_det_init( mbedtls_ecdsa_restart_det_ctx *ctx )
+{
+ mbedtls_hmac_drbg_init( &ctx->rng_ctx );
+ ctx->state = ecdsa_det_init;
+}
+
+/*
+ * Free the components of a sign_det restart sub-context
+ */
+static void ecdsa_restart_det_free( mbedtls_ecdsa_restart_det_ctx *ctx )
+{
+ if( ctx == NULL )
+ return;
+
+ mbedtls_hmac_drbg_free( &ctx->rng_ctx );
+
+ ecdsa_restart_det_init( ctx );
+}
+#endif /* MBEDTLS_ECDSA_DETERMINISTIC */
+
+#define ECDSA_RS_ECP &rs_ctx->ecp
+
+/* Utility macro for checking and updating ops budget */
+#define ECDSA_BUDGET( ops ) \
+ MBEDTLS_MPI_CHK( mbedtls_ecp_check_budget( grp, &rs_ctx->ecp, ops ) );
+
+/* Call this when entering a function that needs its own sub-context */
+#define ECDSA_RS_ENTER( SUB ) do { \
+ /* reset ops count for this call if top-level */ \
+ if( rs_ctx != NULL && rs_ctx->ecp.depth++ == 0 ) \
+ rs_ctx->ecp.ops_done = 0; \
+ \
+ /* set up our own sub-context if needed */ \
+ if( mbedtls_ecp_restart_is_enabled() && \
+ rs_ctx != NULL && rs_ctx->SUB == NULL ) \
+ { \
+ rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) ); \
+ if( rs_ctx->SUB == NULL ) \
+ return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); \
+ \
+ ecdsa_restart_## SUB ##_init( rs_ctx->SUB ); \
+ } \
+} while( 0 )
+
+/* Call this when leaving a function that needs its own sub-context */
+#define ECDSA_RS_LEAVE( SUB ) do { \
+ /* clear our sub-context when not in progress (done or error) */ \
+ if( rs_ctx != NULL && rs_ctx->SUB != NULL && \
+ ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) \
+ { \
+ ecdsa_restart_## SUB ##_free( rs_ctx->SUB ); \
+ mbedtls_free( rs_ctx->SUB ); \
+ rs_ctx->SUB = NULL; \
+ } \
+ \
+ if( rs_ctx != NULL ) \
+ rs_ctx->ecp.depth--; \
+} while( 0 )
+
+#else /* MBEDTLS_ECP_RESTARTABLE */
+
+#define ECDSA_RS_ECP NULL
+
+#define ECDSA_BUDGET( ops ) /* no-op; for compatibility */
+
+#define ECDSA_RS_ENTER( SUB ) (void) rs_ctx
+#define ECDSA_RS_LEAVE( SUB ) (void) rs_ctx
+
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
/*
* Derive a suitable integer for group grp from a buffer of length len
* SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3
@@ -70,13 +250,17 @@ cleanup:
* Compute ECDSA signature of a hashed message (SEC1 4.1.3)
* Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message)
*/
-int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
+static int ecdsa_sign_restartable( mbedtls_ecp_group *grp,
+ mbedtls_mpi *r, mbedtls_mpi *s,
const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
- int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+ mbedtls_ecdsa_restart_ctx *rs_ctx )
{
- int ret, key_tries, sign_tries, blind_tries;
+ int ret, key_tries, sign_tries;
+ int *p_sign_tries = &sign_tries, *p_key_tries = &key_tries;
mbedtls_ecp_point R;
mbedtls_mpi k, e, t;
+ mbedtls_mpi *pk = &k, *pr = r;
/* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
if( grp->N.p == NULL )
@@ -89,26 +273,72 @@ int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
mbedtls_ecp_point_init( &R );
mbedtls_mpi_init( &k ); mbedtls_mpi_init( &e ); mbedtls_mpi_init( &t );
- sign_tries = 0;
+ ECDSA_RS_ENTER( sig );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->sig != NULL )
+ {
+ /* redirect to our context */
+ p_sign_tries = &rs_ctx->sig->sign_tries;
+ p_key_tries = &rs_ctx->sig->key_tries;
+ pk = &rs_ctx->sig->k;
+ pr = &rs_ctx->sig->r;
+
+ /* jump to current step */
+ if( rs_ctx->sig->state == ecdsa_sig_mul )
+ goto mul;
+ if( rs_ctx->sig->state == ecdsa_sig_modn )
+ goto modn;
+ }
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
+ *p_sign_tries = 0;
do
{
+ if( *p_sign_tries++ > 10 )
+ {
+ ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
+ goto cleanup;
+ }
+
/*
* Steps 1-3: generate a suitable ephemeral keypair
* and set r = xR mod n
*/
- key_tries = 0;
+ *p_key_tries = 0;
do
{
- MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair( grp, &k, &R, f_rng, p_rng ) );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( r, &R.X, &grp->N ) );
-
- if( key_tries++ > 10 )
+ if( *p_key_tries++ > 10 )
{
ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
goto cleanup;
}
+
+ MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, pk, f_rng, p_rng ) );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->sig != NULL )
+ rs_ctx->sig->state = ecdsa_sig_mul;
+
+mul:
+#endif
+ MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &R, pk, &grp->G,
+ f_rng, p_rng, ECDSA_RS_ECP ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pr, &R.X, &grp->N ) );
}
- while( mbedtls_mpi_cmp_int( r, 0 ) == 0 );
+ while( mbedtls_mpi_cmp_int( pr, 0 ) == 0 );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->sig != NULL )
+ rs_ctx->sig->state = ecdsa_sig_modn;
+
+modn:
+#endif
+ /*
+ * Accounting for everything up to the end of the loop
+ * (step 6, but checking now avoids saving e and t)
+ */
+ ECDSA_BUDGET( MBEDTLS_ECP_OPS_INV + 4 );
/*
* Step 5: derive MPI from hashed message
@@ -119,57 +349,67 @@ int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
* Generate a random value to blind inv_mod in next step,
* avoiding a potential timing leak.
*/
- blind_tries = 0;
- do
- {
- size_t n_size = ( grp->nbits + 7 ) / 8;
- MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &t, n_size, f_rng, p_rng ) );
- MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &t, 8 * n_size - grp->nbits ) );
-
- /* See mbedtls_ecp_gen_keypair() */
- if( ++blind_tries > 30 )
- return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
- }
- while( mbedtls_mpi_cmp_int( &t, 1 ) < 0 ||
- mbedtls_mpi_cmp_mpi( &t, &grp->N ) >= 0 );
+ MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, &t, f_rng, p_rng ) );
/*
* Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n
*/
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, r, d ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, pr, d ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &e, &e, s ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &e, &e, &t ) );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &k, &k, &t ) );
- MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, &k, &grp->N ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pk, pk, &t ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, pk, &grp->N ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, s, &e ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( s, s, &grp->N ) );
-
- if( sign_tries++ > 10 )
- {
- ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
- goto cleanup;
- }
}
while( mbedtls_mpi_cmp_int( s, 0 ) == 0 );
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->sig != NULL )
+ mbedtls_mpi_copy( r, pr );
+#endif
+
cleanup:
mbedtls_ecp_point_free( &R );
mbedtls_mpi_free( &k ); mbedtls_mpi_free( &e ); mbedtls_mpi_free( &t );
+ ECDSA_RS_LEAVE( sig );
+
return( ret );
}
-#endif /* MBEDTLS_ECDSA_SIGN_ALT */
+
+/*
+ * Compute ECDSA signature of a hashed message
+ */
+int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
+ const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+ ECDSA_VALIDATE_RET( grp != NULL );
+ ECDSA_VALIDATE_RET( r != NULL );
+ ECDSA_VALIDATE_RET( s != NULL );
+ ECDSA_VALIDATE_RET( d != NULL );
+ ECDSA_VALIDATE_RET( f_rng != NULL );
+ ECDSA_VALIDATE_RET( buf != NULL || blen == 0 );
+
+ return( ecdsa_sign_restartable( grp, r, s, d, buf, blen,
+ f_rng, p_rng, NULL ) );
+}
+#endif /* !MBEDTLS_ECDSA_SIGN_ALT */
#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
/*
* Deterministic signature wrapper
*/
-int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
+static int ecdsa_sign_det_restartable( mbedtls_ecp_group *grp,
+ mbedtls_mpi *r, mbedtls_mpi *s,
const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
- mbedtls_md_type_t md_alg )
+ mbedtls_md_type_t md_alg,
+ mbedtls_ecdsa_restart_ctx *rs_ctx )
{
int ret;
mbedtls_hmac_drbg_context rng_ctx;
+ mbedtls_hmac_drbg_context *p_rng = &rng_ctx;
unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES];
size_t grp_len = ( grp->nbits + 7 ) / 8;
const mbedtls_md_info_t *md_info;
@@ -181,21 +421,64 @@ int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi
mbedtls_mpi_init( &h );
mbedtls_hmac_drbg_init( &rng_ctx );
+ ECDSA_RS_ENTER( det );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->det != NULL )
+ {
+ /* redirect to our context */
+ p_rng = &rs_ctx->det->rng_ctx;
+
+ /* jump to current step */
+ if( rs_ctx->det->state == ecdsa_det_sign )
+ goto sign;
+ }
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
/* Use private key and message hash (reduced) to initialize HMAC_DRBG */
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( d, data, grp_len ) );
MBEDTLS_MPI_CHK( derive_mpi( grp, &h, buf, blen ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, data + grp_len, grp_len ) );
- mbedtls_hmac_drbg_seed_buf( &rng_ctx, md_info, data, 2 * grp_len );
+ mbedtls_hmac_drbg_seed_buf( p_rng, md_info, data, 2 * grp_len );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->det != NULL )
+ rs_ctx->det->state = ecdsa_det_sign;
+sign:
+#endif
+#if defined(MBEDTLS_ECDSA_SIGN_ALT)
ret = mbedtls_ecdsa_sign( grp, r, s, d, buf, blen,
- mbedtls_hmac_drbg_random, &rng_ctx );
+ mbedtls_hmac_drbg_random, p_rng );
+#else
+ ret = ecdsa_sign_restartable( grp, r, s, d, buf, blen,
+ mbedtls_hmac_drbg_random, p_rng, rs_ctx );
+#endif /* MBEDTLS_ECDSA_SIGN_ALT */
cleanup:
mbedtls_hmac_drbg_free( &rng_ctx );
mbedtls_mpi_free( &h );
+ ECDSA_RS_LEAVE( det );
+
return( ret );
}
+
+/*
+ * Deterministic signature wrapper
+ */
+int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
+ const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
+ mbedtls_md_type_t md_alg )
+{
+ ECDSA_VALIDATE_RET( grp != NULL );
+ ECDSA_VALIDATE_RET( r != NULL );
+ ECDSA_VALIDATE_RET( s != NULL );
+ ECDSA_VALIDATE_RET( d != NULL );
+ ECDSA_VALIDATE_RET( buf != NULL || blen == 0 );
+
+ return( ecdsa_sign_det_restartable( grp, r, s, d, buf, blen, md_alg, NULL ) );
+}
#endif /* MBEDTLS_ECDSA_DETERMINISTIC */
#if !defined(MBEDTLS_ECDSA_VERIFY_ALT)
@@ -203,21 +486,40 @@ cleanup:
* Verify ECDSA signature of hashed message (SEC1 4.1.4)
* Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message)
*/
-int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp,
- const unsigned char *buf, size_t blen,
- const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s)
+static int ecdsa_verify_restartable( mbedtls_ecp_group *grp,
+ const unsigned char *buf, size_t blen,
+ const mbedtls_ecp_point *Q,
+ const mbedtls_mpi *r, const mbedtls_mpi *s,
+ mbedtls_ecdsa_restart_ctx *rs_ctx )
{
int ret;
mbedtls_mpi e, s_inv, u1, u2;
mbedtls_ecp_point R;
+ mbedtls_mpi *pu1 = &u1, *pu2 = &u2;
mbedtls_ecp_point_init( &R );
- mbedtls_mpi_init( &e ); mbedtls_mpi_init( &s_inv ); mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 );
+ mbedtls_mpi_init( &e ); mbedtls_mpi_init( &s_inv );
+ mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 );
/* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
if( grp->N.p == NULL )
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+ ECDSA_RS_ENTER( ver );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->ver != NULL )
+ {
+ /* redirect to our context */
+ pu1 = &rs_ctx->ver->u1;
+ pu2 = &rs_ctx->ver->u2;
+
+ /* jump to current step */
+ if( rs_ctx->ver->state == ecdsa_ver_muladd )
+ goto muladd;
+ }
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
/*
* Step 1: make sure r and s are in range 1..n-1
*/
@@ -229,11 +531,6 @@ int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp,
}
/*
- * Additional precaution: make sure Q is valid
- */
- MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, Q ) );
-
- /*
* Step 3: derive MPI from hashed message
*/
MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) );
@@ -241,21 +538,27 @@ int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp,
/*
* Step 4: u1 = e / s mod n, u2 = r / s mod n
*/
+ ECDSA_BUDGET( MBEDTLS_ECP_OPS_CHK + MBEDTLS_ECP_OPS_INV + 2 );
+
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &s_inv, s, &grp->N ) );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u1, &e, &s_inv ) );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &u1, &u1, &grp->N ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pu1, &e, &s_inv ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pu1, pu1, &grp->N ) );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u2, r, &s_inv ) );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &u2, &u2, &grp->N ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pu2, r, &s_inv ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pu2, pu2, &grp->N ) );
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->ver != NULL )
+ rs_ctx->ver->state = ecdsa_ver_muladd;
+
+muladd:
+#endif
/*
* Step 5: R = u1 G + u2 Q
- *
- * Since we're not using any secret data, no need to pass a RNG to
- * mbedtls_ecp_mul() for countermesures.
*/
- MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, &R, &u1, &grp->G, &u2, Q ) );
+ MBEDTLS_MPI_CHK( mbedtls_ecp_muladd_restartable( grp,
+ &R, pu1, &grp->G, pu2, Q, ECDSA_RS_ECP ) );
if( mbedtls_ecp_is_zero( &R ) )
{
@@ -280,11 +583,32 @@ int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp,
cleanup:
mbedtls_ecp_point_free( &R );
- mbedtls_mpi_free( &e ); mbedtls_mpi_free( &s_inv ); mbedtls_mpi_free( &u1 ); mbedtls_mpi_free( &u2 );
+ mbedtls_mpi_free( &e ); mbedtls_mpi_free( &s_inv );
+ mbedtls_mpi_free( &u1 ); mbedtls_mpi_free( &u2 );
+
+ ECDSA_RS_LEAVE( ver );
return( ret );
}
-#endif /* MBEDTLS_ECDSA_VERIFY_ALT */
+
+/*
+ * Verify ECDSA signature of hashed message
+ */
+int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp,
+ const unsigned char *buf, size_t blen,
+ const mbedtls_ecp_point *Q,
+ const mbedtls_mpi *r,
+ const mbedtls_mpi *s)
+{
+ ECDSA_VALIDATE_RET( grp != NULL );
+ ECDSA_VALIDATE_RET( Q != NULL );
+ ECDSA_VALIDATE_RET( r != NULL );
+ ECDSA_VALIDATE_RET( s != NULL );
+ ECDSA_VALIDATE_RET( buf != NULL || blen == 0 );
+
+ return( ecdsa_verify_restartable( grp, buf, blen, Q, r, s, NULL ) );
+}
+#endif /* !MBEDTLS_ECDSA_VERIFY_ALT */
/*
* Convert a signature (given by context) to ASN.1
@@ -313,14 +637,20 @@ static int ecdsa_signature_to_asn1( const mbedtls_mpi *r, const mbedtls_mpi *s,
/*
* Compute and write signature
*/
-int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg,
+int mbedtls_ecdsa_write_signature_restartable( mbedtls_ecdsa_context *ctx,
+ mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hlen,
unsigned char *sig, size_t *slen,
int (*f_rng)(void *, unsigned char *, size_t),
- void *p_rng )
+ void *p_rng,
+ mbedtls_ecdsa_restart_ctx *rs_ctx )
{
int ret;
mbedtls_mpi r, s;
+ ECDSA_VALIDATE_RET( ctx != NULL );
+ ECDSA_VALIDATE_RET( hash != NULL );
+ ECDSA_VALIDATE_RET( sig != NULL );
+ ECDSA_VALIDATE_RET( slen != NULL );
mbedtls_mpi_init( &r );
mbedtls_mpi_init( &s );
@@ -329,14 +659,19 @@ int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t
(void) f_rng;
(void) p_rng;
- MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign_det( &ctx->grp, &r, &s, &ctx->d,
- hash, hlen, md_alg ) );
+ MBEDTLS_MPI_CHK( ecdsa_sign_det_restartable( &ctx->grp, &r, &s, &ctx->d,
+ hash, hlen, md_alg, rs_ctx ) );
#else
(void) md_alg;
+#if defined(MBEDTLS_ECDSA_SIGN_ALT)
MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d,
hash, hlen, f_rng, p_rng ) );
-#endif
+#else
+ MBEDTLS_MPI_CHK( ecdsa_sign_restartable( &ctx->grp, &r, &s, &ctx->d,
+ hash, hlen, f_rng, p_rng, rs_ctx ) );
+#endif /* MBEDTLS_ECDSA_SIGN_ALT */
+#endif /* MBEDTLS_ECDSA_DETERMINISTIC */
MBEDTLS_MPI_CHK( ecdsa_signature_to_asn1( &r, &s, sig, slen ) );
@@ -347,13 +682,35 @@ cleanup:
return( ret );
}
-#if ! defined(MBEDTLS_DEPRECATED_REMOVED) && \
+/*
+ * Compute and write signature
+ */
+int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx,
+ mbedtls_md_type_t md_alg,
+ const unsigned char *hash, size_t hlen,
+ unsigned char *sig, size_t *slen,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ ECDSA_VALIDATE_RET( ctx != NULL );
+ ECDSA_VALIDATE_RET( hash != NULL );
+ ECDSA_VALIDATE_RET( sig != NULL );
+ ECDSA_VALIDATE_RET( slen != NULL );
+ return( mbedtls_ecdsa_write_signature_restartable(
+ ctx, md_alg, hash, hlen, sig, slen, f_rng, p_rng, NULL ) );
+}
+
+#if !defined(MBEDTLS_DEPRECATED_REMOVED) && \
defined(MBEDTLS_ECDSA_DETERMINISTIC)
int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx,
const unsigned char *hash, size_t hlen,
unsigned char *sig, size_t *slen,
mbedtls_md_type_t md_alg )
{
+ ECDSA_VALIDATE_RET( ctx != NULL );
+ ECDSA_VALIDATE_RET( hash != NULL );
+ ECDSA_VALIDATE_RET( sig != NULL );
+ ECDSA_VALIDATE_RET( slen != NULL );
return( mbedtls_ecdsa_write_signature( ctx, md_alg, hash, hlen, sig, slen,
NULL, NULL ) );
}
@@ -366,11 +723,29 @@ int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx,
const unsigned char *hash, size_t hlen,
const unsigned char *sig, size_t slen )
{
+ ECDSA_VALIDATE_RET( ctx != NULL );
+ ECDSA_VALIDATE_RET( hash != NULL );
+ ECDSA_VALIDATE_RET( sig != NULL );
+ return( mbedtls_ecdsa_read_signature_restartable(
+ ctx, hash, hlen, sig, slen, NULL ) );
+}
+
+/*
+ * Restartable read and check signature
+ */
+int mbedtls_ecdsa_read_signature_restartable( mbedtls_ecdsa_context *ctx,
+ const unsigned char *hash, size_t hlen,
+ const unsigned char *sig, size_t slen,
+ mbedtls_ecdsa_restart_ctx *rs_ctx )
+{
int ret;
unsigned char *p = (unsigned char *) sig;
const unsigned char *end = sig + slen;
size_t len;
mbedtls_mpi r, s;
+ ECDSA_VALIDATE_RET( ctx != NULL );
+ ECDSA_VALIDATE_RET( hash != NULL );
+ ECDSA_VALIDATE_RET( sig != NULL );
mbedtls_mpi_init( &r );
mbedtls_mpi_init( &s );
@@ -395,10 +770,15 @@ int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx,
ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
goto cleanup;
}
-
+#if defined(MBEDTLS_ECDSA_VERIFY_ALT)
if( ( ret = mbedtls_ecdsa_verify( &ctx->grp, hash, hlen,
- &ctx->Q, &r, &s ) ) != 0 )
+ &ctx->Q, &r, &s ) ) != 0 )
goto cleanup;
+#else
+ if( ( ret = ecdsa_verify_restartable( &ctx->grp, hash, hlen,
+ &ctx->Q, &r, &s, rs_ctx ) ) != 0 )
+ goto cleanup;
+#endif /* MBEDTLS_ECDSA_VERIFY_ALT */
/* At this point we know that the buffer starts with a valid signature.
* Return 0 if the buffer just contains the signature, and a specific
@@ -420,10 +800,13 @@ cleanup:
int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
{
+ ECDSA_VALIDATE_RET( ctx != NULL );
+ ECDSA_VALIDATE_RET( f_rng != NULL );
+
return( mbedtls_ecp_group_load( &ctx->grp, gid ) ||
mbedtls_ecp_gen_keypair( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) );
}
-#endif /* MBEDTLS_ECDSA_GENKEY_ALT */
+#endif /* !MBEDTLS_ECDSA_GENKEY_ALT */
/*
* Set context from an mbedtls_ecp_keypair
@@ -431,6 +814,8 @@ int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid,
int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key )
{
int ret;
+ ECDSA_VALIDATE_RET( ctx != NULL );
+ ECDSA_VALIDATE_RET( key != NULL );
if( ( ret = mbedtls_ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 ||
( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 ||
@@ -447,6 +832,8 @@ int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_ke
*/
void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx )
{
+ ECDSA_VALIDATE( ctx != NULL );
+
mbedtls_ecp_keypair_init( ctx );
}
@@ -455,7 +842,53 @@ void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx )
*/
void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx )
{
+ if( ctx == NULL )
+ return;
+
mbedtls_ecp_keypair_free( ctx );
}
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+/*
+ * Initialize a restart context
+ */
+void mbedtls_ecdsa_restart_init( mbedtls_ecdsa_restart_ctx *ctx )
+{
+ ECDSA_VALIDATE( ctx != NULL );
+
+ mbedtls_ecp_restart_init( &ctx->ecp );
+
+ ctx->ver = NULL;
+ ctx->sig = NULL;
+#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
+ ctx->det = NULL;
+#endif
+}
+
+/*
+ * Free the components of a restart context
+ */
+void mbedtls_ecdsa_restart_free( mbedtls_ecdsa_restart_ctx *ctx )
+{
+ if( ctx == NULL )
+ return;
+
+ mbedtls_ecp_restart_free( &ctx->ecp );
+
+ ecdsa_restart_ver_free( ctx->ver );
+ mbedtls_free( ctx->ver );
+ ctx->ver = NULL;
+
+ ecdsa_restart_sig_free( ctx->sig );
+ mbedtls_free( ctx->sig );
+ ctx->sig = NULL;
+
+#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
+ ecdsa_restart_det_free( ctx->det );
+ mbedtls_free( ctx->det );
+ ctx->det = NULL;
+#endif
+}
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
#endif /* MBEDTLS_ECDSA_C */
diff --git a/thirdparty/mbedtls/library/ecjpake.c b/thirdparty/mbedtls/library/ecjpake.c
index ec5a4007db..be941b14b1 100644
--- a/thirdparty/mbedtls/library/ecjpake.c
+++ b/thirdparty/mbedtls/library/ecjpake.c
@@ -33,11 +33,18 @@
#if defined(MBEDTLS_ECJPAKE_C)
#include "mbedtls/ecjpake.h"
+#include "mbedtls/platform_util.h"
#include <string.h>
#if !defined(MBEDTLS_ECJPAKE_ALT)
+/* Parameter validation macros based on platform_util.h */
+#define ECJPAKE_VALIDATE_RET( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
+#define ECJPAKE_VALIDATE( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE( cond )
+
/*
* Convert a mbedtls_ecjpake_role to identifier string
*/
@@ -54,8 +61,7 @@ static const char * const ecjpake_id[] = {
*/
void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx )
{
- if( ctx == NULL )
- return;
+ ECJPAKE_VALIDATE( ctx != NULL );
ctx->md_info = NULL;
mbedtls_ecp_group_init( &ctx->grp );
@@ -106,6 +112,11 @@ int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx,
{
int ret;
+ ECJPAKE_VALIDATE_RET( ctx != NULL );
+ ECJPAKE_VALIDATE_RET( role == MBEDTLS_ECJPAKE_CLIENT ||
+ role == MBEDTLS_ECJPAKE_SERVER );
+ ECJPAKE_VALIDATE_RET( secret != NULL || len == 0 );
+
ctx->role = role;
if( ( ctx->md_info = mbedtls_md_info_from_type( hash ) ) == NULL )
@@ -127,6 +138,8 @@ cleanup:
*/
int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx )
{
+ ECJPAKE_VALIDATE_RET( ctx != NULL );
+
if( ctx->md_info == NULL ||
ctx->grp.id == MBEDTLS_ECP_DP_NONE ||
ctx->s.p == NULL )
@@ -504,6 +517,9 @@ int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx,
const unsigned char *buf,
size_t len )
{
+ ECJPAKE_VALIDATE_RET( ctx != NULL );
+ ECJPAKE_VALIDATE_RET( buf != NULL );
+
return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, ctx->point_format,
&ctx->grp.G,
&ctx->Xp1, &ctx->Xp2, ID_PEER,
@@ -518,6 +534,11 @@ int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
+ ECJPAKE_VALIDATE_RET( ctx != NULL );
+ ECJPAKE_VALIDATE_RET( buf != NULL );
+ ECJPAKE_VALIDATE_RET( olen != NULL );
+ ECJPAKE_VALIDATE_RET( f_rng != NULL );
+
return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, ctx->point_format,
&ctx->grp.G,
&ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
@@ -560,6 +581,9 @@ int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx,
mbedtls_ecp_group grp;
mbedtls_ecp_point G; /* C: GB, S: GA */
+ ECJPAKE_VALIDATE_RET( ctx != NULL );
+ ECJPAKE_VALIDATE_RET( buf != NULL );
+
mbedtls_ecp_group_init( &grp );
mbedtls_ecp_point_init( &G );
@@ -652,6 +676,11 @@ int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx,
const unsigned char *end = buf + len;
size_t ec_len;
+ ECJPAKE_VALIDATE_RET( ctx != NULL );
+ ECJPAKE_VALIDATE_RET( buf != NULL );
+ ECJPAKE_VALIDATE_RET( olen != NULL );
+ ECJPAKE_VALIDATE_RET( f_rng != NULL );
+
mbedtls_ecp_point_init( &G );
mbedtls_ecp_point_init( &Xm );
mbedtls_mpi_init( &xm );
@@ -727,6 +756,11 @@ int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx,
unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
size_t x_bytes;
+ ECJPAKE_VALIDATE_RET( ctx != NULL );
+ ECJPAKE_VALIDATE_RET( buf != NULL );
+ ECJPAKE_VALIDATE_RET( olen != NULL );
+ ECJPAKE_VALIDATE_RET( f_rng != NULL );
+
*olen = mbedtls_md_get_size( ctx->md_info );
if( len < *olen )
return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
diff --git a/thirdparty/mbedtls/library/ecp.c b/thirdparty/mbedtls/library/ecp.c
index 41db3fbe5b..ecea5910e0 100644
--- a/thirdparty/mbedtls/library/ecp.c
+++ b/thirdparty/mbedtls/library/ecp.c
@@ -47,6 +47,35 @@
#include MBEDTLS_CONFIG_FILE
#endif
+/**
+ * \brief Function level alternative implementation.
+ *
+ * The MBEDTLS_ECP_INTERNAL_ALT macro enables alternative implementations to
+ * replace certain functions in this module. The alternative implementations are
+ * typically hardware accelerators and need to activate the hardware before the
+ * computation starts and deactivate it after it finishes. The
+ * mbedtls_internal_ecp_init() and mbedtls_internal_ecp_free() functions serve
+ * this purpose.
+ *
+ * To preserve the correct functionality the following conditions must hold:
+ *
+ * - The alternative implementation must be activated by
+ * mbedtls_internal_ecp_init() before any of the replaceable functions is
+ * called.
+ * - mbedtls_internal_ecp_free() must \b only be called when the alternative
+ * implementation is activated.
+ * - mbedtls_internal_ecp_init() must \b not be called when the alternative
+ * implementation is activated.
+ * - Public functions must not return while the alternative implementation is
+ * activated.
+ * - Replaceable functions are guarded by \c MBEDTLS_ECP_XXX_ALT macros and
+ * before calling them an \code if( mbedtls_internal_ecp_grp_capable( grp ) )
+ * \endcode ensures that the alternative implementation supports the current
+ * group.
+ */
+#if defined(MBEDTLS_ECP_INTERNAL_ALT)
+#endif
+
#if defined(MBEDTLS_ECP_C)
#include "mbedtls/ecp.h"
@@ -57,6 +86,12 @@
#if !defined(MBEDTLS_ECP_ALT)
+/* Parameter validation macros based on platform_util.h */
+#define ECP_VALIDATE_RET( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
+#define ECP_VALIDATE( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE( cond )
+
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
@@ -82,6 +117,233 @@
static unsigned long add_count, dbl_count, mul_count;
#endif
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+/*
+ * Maximum number of "basic operations" to be done in a row.
+ *
+ * Default value 0 means that ECC operations will not yield.
+ * Note that regardless of the value of ecp_max_ops, always at
+ * least one step is performed before yielding.
+ *
+ * Setting ecp_max_ops=1 can be suitable for testing purposes
+ * as it will interrupt computation at all possible points.
+ */
+static unsigned ecp_max_ops = 0;
+
+/*
+ * Set ecp_max_ops
+ */
+void mbedtls_ecp_set_max_ops( unsigned max_ops )
+{
+ ecp_max_ops = max_ops;
+}
+
+/*
+ * Check if restart is enabled
+ */
+int mbedtls_ecp_restart_is_enabled( void )
+{
+ return( ecp_max_ops != 0 );
+}
+
+/*
+ * Restart sub-context for ecp_mul_comb()
+ */
+struct mbedtls_ecp_restart_mul
+{
+ mbedtls_ecp_point R; /* current intermediate result */
+ size_t i; /* current index in various loops, 0 outside */
+ mbedtls_ecp_point *T; /* table for precomputed points */
+ unsigned char T_size; /* number of points in table T */
+ enum { /* what were we doing last time we returned? */
+ ecp_rsm_init = 0, /* nothing so far, dummy initial state */
+ ecp_rsm_pre_dbl, /* precompute 2^n multiples */
+ ecp_rsm_pre_norm_dbl, /* normalize precomputed 2^n multiples */
+ ecp_rsm_pre_add, /* precompute remaining points by adding */
+ ecp_rsm_pre_norm_add, /* normalize all precomputed points */
+ ecp_rsm_comb_core, /* ecp_mul_comb_core() */
+ ecp_rsm_final_norm, /* do the final normalization */
+ } state;
+};
+
+/*
+ * Init restart_mul sub-context
+ */
+static void ecp_restart_rsm_init( mbedtls_ecp_restart_mul_ctx *ctx )
+{
+ mbedtls_ecp_point_init( &ctx->R );
+ ctx->i = 0;
+ ctx->T = NULL;
+ ctx->T_size = 0;
+ ctx->state = ecp_rsm_init;
+}
+
+/*
+ * Free the components of a restart_mul sub-context
+ */
+static void ecp_restart_rsm_free( mbedtls_ecp_restart_mul_ctx *ctx )
+{
+ unsigned char i;
+
+ if( ctx == NULL )
+ return;
+
+ mbedtls_ecp_point_free( &ctx->R );
+
+ if( ctx->T != NULL )
+ {
+ for( i = 0; i < ctx->T_size; i++ )
+ mbedtls_ecp_point_free( ctx->T + i );
+ mbedtls_free( ctx->T );
+ }
+
+ ecp_restart_rsm_init( ctx );
+}
+
+/*
+ * Restart context for ecp_muladd()
+ */
+struct mbedtls_ecp_restart_muladd
+{
+ mbedtls_ecp_point mP; /* mP value */
+ mbedtls_ecp_point R; /* R intermediate result */
+ enum { /* what should we do next? */
+ ecp_rsma_mul1 = 0, /* first multiplication */
+ ecp_rsma_mul2, /* second multiplication */
+ ecp_rsma_add, /* addition */
+ ecp_rsma_norm, /* normalization */
+ } state;
+};
+
+/*
+ * Init restart_muladd sub-context
+ */
+static void ecp_restart_ma_init( mbedtls_ecp_restart_muladd_ctx *ctx )
+{
+ mbedtls_ecp_point_init( &ctx->mP );
+ mbedtls_ecp_point_init( &ctx->R );
+ ctx->state = ecp_rsma_mul1;
+}
+
+/*
+ * Free the components of a restart_muladd sub-context
+ */
+static void ecp_restart_ma_free( mbedtls_ecp_restart_muladd_ctx *ctx )
+{
+ if( ctx == NULL )
+ return;
+
+ mbedtls_ecp_point_free( &ctx->mP );
+ mbedtls_ecp_point_free( &ctx->R );
+
+ ecp_restart_ma_init( ctx );
+}
+
+/*
+ * Initialize a restart context
+ */
+void mbedtls_ecp_restart_init( mbedtls_ecp_restart_ctx *ctx )
+{
+ ECP_VALIDATE( ctx != NULL );
+ ctx->ops_done = 0;
+ ctx->depth = 0;
+ ctx->rsm = NULL;
+ ctx->ma = NULL;
+}
+
+/*
+ * Free the components of a restart context
+ */
+void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx )
+{
+ if( ctx == NULL )
+ return;
+
+ ecp_restart_rsm_free( ctx->rsm );
+ mbedtls_free( ctx->rsm );
+
+ ecp_restart_ma_free( ctx->ma );
+ mbedtls_free( ctx->ma );
+
+ mbedtls_ecp_restart_init( ctx );
+}
+
+/*
+ * Check if we can do the next step
+ */
+int mbedtls_ecp_check_budget( const mbedtls_ecp_group *grp,
+ mbedtls_ecp_restart_ctx *rs_ctx,
+ unsigned ops )
+{
+ ECP_VALIDATE_RET( grp != NULL );
+
+ if( rs_ctx != NULL && ecp_max_ops != 0 )
+ {
+ /* scale depending on curve size: the chosen reference is 256-bit,
+ * and multiplication is quadratic. Round to the closest integer. */
+ if( grp->pbits >= 512 )
+ ops *= 4;
+ else if( grp->pbits >= 384 )
+ ops *= 2;
+
+ /* Avoid infinite loops: always allow first step.
+ * Because of that, however, it's not generally true
+ * that ops_done <= ecp_max_ops, so the check
+ * ops_done > ecp_max_ops below is mandatory. */
+ if( ( rs_ctx->ops_done != 0 ) &&
+ ( rs_ctx->ops_done > ecp_max_ops ||
+ ops > ecp_max_ops - rs_ctx->ops_done ) )
+ {
+ return( MBEDTLS_ERR_ECP_IN_PROGRESS );
+ }
+
+ /* update running count */
+ rs_ctx->ops_done += ops;
+ }
+
+ return( 0 );
+}
+
+/* Call this when entering a function that needs its own sub-context */
+#define ECP_RS_ENTER( SUB ) do { \
+ /* reset ops count for this call if top-level */ \
+ if( rs_ctx != NULL && rs_ctx->depth++ == 0 ) \
+ rs_ctx->ops_done = 0; \
+ \
+ /* set up our own sub-context if needed */ \
+ if( mbedtls_ecp_restart_is_enabled() && \
+ rs_ctx != NULL && rs_ctx->SUB == NULL ) \
+ { \
+ rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) ); \
+ if( rs_ctx->SUB == NULL ) \
+ return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); \
+ \
+ ecp_restart_## SUB ##_init( rs_ctx->SUB ); \
+ } \
+} while( 0 )
+
+/* Call this when leaving a function that needs its own sub-context */
+#define ECP_RS_LEAVE( SUB ) do { \
+ /* clear our sub-context when not in progress (done or error) */ \
+ if( rs_ctx != NULL && rs_ctx->SUB != NULL && \
+ ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) \
+ { \
+ ecp_restart_## SUB ##_free( rs_ctx->SUB ); \
+ mbedtls_free( rs_ctx->SUB ); \
+ rs_ctx->SUB = NULL; \
+ } \
+ \
+ if( rs_ctx != NULL ) \
+ rs_ctx->depth--; \
+} while( 0 )
+
+#else /* MBEDTLS_ECP_RESTARTABLE */
+
+#define ECP_RS_ENTER( sub ) (void) rs_ctx;
+#define ECP_RS_LEAVE( sub ) (void) rs_ctx;
+
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \
defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \
defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
@@ -243,6 +505,9 @@ const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name
{
const mbedtls_ecp_curve_info *curve_info;
+ if( name == NULL )
+ return( NULL );
+
for( curve_info = mbedtls_ecp_curve_list();
curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
curve_info++ )
@@ -273,8 +538,7 @@ static inline ecp_curve_type ecp_get_type( const mbedtls_ecp_group *grp )
*/
void mbedtls_ecp_point_init( mbedtls_ecp_point *pt )
{
- if( pt == NULL )
- return;
+ ECP_VALIDATE( pt != NULL );
mbedtls_mpi_init( &pt->X );
mbedtls_mpi_init( &pt->Y );
@@ -286,10 +550,23 @@ void mbedtls_ecp_point_init( mbedtls_ecp_point *pt )
*/
void mbedtls_ecp_group_init( mbedtls_ecp_group *grp )
{
- if( grp == NULL )
- return;
-
- memset( grp, 0, sizeof( mbedtls_ecp_group ) );
+ ECP_VALIDATE( grp != NULL );
+
+ grp->id = MBEDTLS_ECP_DP_NONE;
+ mbedtls_mpi_init( &grp->P );
+ mbedtls_mpi_init( &grp->A );
+ mbedtls_mpi_init( &grp->B );
+ mbedtls_ecp_point_init( &grp->G );
+ mbedtls_mpi_init( &grp->N );
+ grp->pbits = 0;
+ grp->nbits = 0;
+ grp->h = 0;
+ grp->modp = NULL;
+ grp->t_pre = NULL;
+ grp->t_post = NULL;
+ grp->t_data = NULL;
+ grp->T = NULL;
+ grp->T_size = 0;
}
/*
@@ -297,8 +574,7 @@ void mbedtls_ecp_group_init( mbedtls_ecp_group *grp )
*/
void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key )
{
- if( key == NULL )
- return;
+ ECP_VALIDATE( key != NULL );
mbedtls_ecp_group_init( &key->grp );
mbedtls_mpi_init( &key->d );
@@ -366,6 +642,8 @@ void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key )
int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
{
int ret;
+ ECP_VALIDATE_RET( P != NULL );
+ ECP_VALIDATE_RET( Q != NULL );
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->X, &Q->X ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Y, &Q->Y ) );
@@ -380,7 +658,10 @@ cleanup:
*/
int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src )
{
- return mbedtls_ecp_group_load( dst, src->id );
+ ECP_VALIDATE_RET( dst != NULL );
+ ECP_VALIDATE_RET( src != NULL );
+
+ return( mbedtls_ecp_group_load( dst, src->id ) );
}
/*
@@ -389,6 +670,7 @@ int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src
int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt )
{
int ret;
+ ECP_VALIDATE_RET( pt != NULL );
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->X , 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Y , 1 ) );
@@ -403,15 +685,20 @@ cleanup:
*/
int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt )
{
+ ECP_VALIDATE_RET( pt != NULL );
+
return( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 );
}
/*
- * Compare two points lazyly
+ * Compare two points lazily
*/
int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P,
const mbedtls_ecp_point *Q )
{
+ ECP_VALIDATE_RET( P != NULL );
+ ECP_VALIDATE_RET( Q != NULL );
+
if( mbedtls_mpi_cmp_mpi( &P->X, &Q->X ) == 0 &&
mbedtls_mpi_cmp_mpi( &P->Y, &Q->Y ) == 0 &&
mbedtls_mpi_cmp_mpi( &P->Z, &Q->Z ) == 0 )
@@ -429,6 +716,9 @@ int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix,
const char *x, const char *y )
{
int ret;
+ ECP_VALIDATE_RET( P != NULL );
+ ECP_VALIDATE_RET( x != NULL );
+ ECP_VALIDATE_RET( y != NULL );
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->X, radix, x ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->Y, radix, y ) );
@@ -441,16 +731,19 @@ cleanup:
/*
* Export a point into unsigned binary data (SEC1 2.3.3)
*/
-int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P,
- int format, size_t *olen,
- unsigned char *buf, size_t buflen )
+int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp,
+ const mbedtls_ecp_point *P,
+ int format, size_t *olen,
+ unsigned char *buf, size_t buflen )
{
int ret = 0;
size_t plen;
-
- if( format != MBEDTLS_ECP_PF_UNCOMPRESSED &&
- format != MBEDTLS_ECP_PF_COMPRESSED )
- return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+ ECP_VALIDATE_RET( grp != NULL );
+ ECP_VALIDATE_RET( P != NULL );
+ ECP_VALIDATE_RET( olen != NULL );
+ ECP_VALIDATE_RET( buf != NULL );
+ ECP_VALIDATE_RET( format == MBEDTLS_ECP_PF_UNCOMPRESSED ||
+ format == MBEDTLS_ECP_PF_COMPRESSED );
/*
* Common case: P == 0
@@ -497,11 +790,15 @@ cleanup:
/*
* Import a point from unsigned binary data (SEC1 2.3.4)
*/
-int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
- const unsigned char *buf, size_t ilen )
+int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp,
+ mbedtls_ecp_point *pt,
+ const unsigned char *buf, size_t ilen )
{
int ret;
size_t plen;
+ ECP_VALIDATE_RET( grp != NULL );
+ ECP_VALIDATE_RET( pt != NULL );
+ ECP_VALIDATE_RET( buf != NULL );
if( ilen < 1 )
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
@@ -536,11 +833,16 @@ cleanup:
* opaque point <1..2^8-1>;
* } ECPoint;
*/
-int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
- const unsigned char **buf, size_t buf_len )
+int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp,
+ mbedtls_ecp_point *pt,
+ const unsigned char **buf, size_t buf_len )
{
unsigned char data_len;
const unsigned char *buf_start;
+ ECP_VALIDATE_RET( grp != NULL );
+ ECP_VALIDATE_RET( pt != NULL );
+ ECP_VALIDATE_RET( buf != NULL );
+ ECP_VALIDATE_RET( *buf != NULL );
/*
* We must have at least two bytes (1 for length, at least one for data)
@@ -558,7 +860,7 @@ int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, mbedtls_ecp_point
buf_start = *buf;
*buf += data_len;
- return mbedtls_ecp_point_read_binary( grp, pt, buf_start, data_len );
+ return( mbedtls_ecp_point_read_binary( grp, pt, buf_start, data_len ) );
}
/*
@@ -572,6 +874,12 @@ int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp
unsigned char *buf, size_t blen )
{
int ret;
+ ECP_VALIDATE_RET( grp != NULL );
+ ECP_VALIDATE_RET( pt != NULL );
+ ECP_VALIDATE_RET( olen != NULL );
+ ECP_VALIDATE_RET( buf != NULL );
+ ECP_VALIDATE_RET( format == MBEDTLS_ECP_PF_UNCOMPRESSED ||
+ format == MBEDTLS_ECP_PF_COMPRESSED );
/*
* buffer length must be at least one, for our length byte
@@ -595,10 +903,33 @@ int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp
/*
* Set a group from an ECParameters record (RFC 4492)
*/
-int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, const unsigned char **buf, size_t len )
+int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp,
+ const unsigned char **buf, size_t len )
+{
+ int ret;
+ mbedtls_ecp_group_id grp_id;
+ ECP_VALIDATE_RET( grp != NULL );
+ ECP_VALIDATE_RET( buf != NULL );
+ ECP_VALIDATE_RET( *buf != NULL );
+
+ if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, len ) ) != 0 )
+ return( ret );
+
+ return( mbedtls_ecp_group_load( grp, grp_id ) );
+}
+
+/*
+ * Read a group id from an ECParameters record (RFC 4492) and convert it to
+ * mbedtls_ecp_group_id.
+ */
+int mbedtls_ecp_tls_read_group_id( mbedtls_ecp_group_id *grp,
+ const unsigned char **buf, size_t len )
{
uint16_t tls_id;
const mbedtls_ecp_curve_info *curve_info;
+ ECP_VALIDATE_RET( grp != NULL );
+ ECP_VALIDATE_RET( buf != NULL );
+ ECP_VALIDATE_RET( *buf != NULL );
/*
* We expect at least three bytes (see below)
@@ -622,7 +953,9 @@ int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, const unsigned char **bu
if( ( curve_info = mbedtls_ecp_curve_info_from_tls_id( tls_id ) ) == NULL )
return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
- return mbedtls_ecp_group_load( grp, curve_info->grp_id );
+ *grp = curve_info->grp_id;
+
+ return( 0 );
}
/*
@@ -632,6 +965,9 @@ int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen,
unsigned char *buf, size_t blen )
{
const mbedtls_ecp_curve_info *curve_info;
+ ECP_VALIDATE_RET( grp != NULL );
+ ECP_VALIDATE_RET( buf != NULL );
+ ECP_VALIDATE_RET( olen != NULL );
if( ( curve_info = mbedtls_ecp_curve_info_from_grp_id( grp->id ) ) == NULL )
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
@@ -752,11 +1088,10 @@ static int ecp_normalize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *p
return( 0 );
#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT)
- if ( mbedtls_internal_ecp_grp_capable( grp ) )
- {
- return mbedtls_internal_ecp_normalize_jac( grp, pt );
- }
+ if( mbedtls_internal_ecp_grp_capable( grp ) )
+ return( mbedtls_internal_ecp_normalize_jac( grp, pt ) );
#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */
+
mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
/*
@@ -796,32 +1131,33 @@ cleanup:
* Cost: 1N(t) := 1I + (6t - 3)M + 1S
*/
static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp,
- mbedtls_ecp_point *T[], size_t t_len )
+ mbedtls_ecp_point *T[], size_t T_size )
{
int ret;
size_t i;
mbedtls_mpi *c, u, Zi, ZZi;
- if( t_len < 2 )
+ if( T_size < 2 )
return( ecp_normalize_jac( grp, *T ) );
#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT)
- if ( mbedtls_internal_ecp_grp_capable( grp ) )
- {
- return mbedtls_internal_ecp_normalize_jac_many(grp, T, t_len);
- }
+ if( mbedtls_internal_ecp_grp_capable( grp ) )
+ return( mbedtls_internal_ecp_normalize_jac_many( grp, T, T_size ) );
#endif
- if( ( c = mbedtls_calloc( t_len, sizeof( mbedtls_mpi ) ) ) == NULL )
+ if( ( c = mbedtls_calloc( T_size, sizeof( mbedtls_mpi ) ) ) == NULL )
return( MBEDTLS_ERR_ECP_ALLOC_FAILED );
+ for( i = 0; i < T_size; i++ )
+ mbedtls_mpi_init( &c[i] );
+
mbedtls_mpi_init( &u ); mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
/*
* c[i] = Z_0 * ... * Z_i
*/
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &c[0], &T[0]->Z ) );
- for( i = 1; i < t_len; i++ )
+ for( i = 1; i < T_size; i++ )
{
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &c[i], &c[i-1], &T[i]->Z ) );
MOD_MUL( c[i] );
@@ -830,9 +1166,9 @@ static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp,
/*
* u = 1 / (Z_0 * ... * Z_n) mod P
*/
- MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[t_len-1], &grp->P ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[T_size-1], &grp->P ) );
- for( i = t_len - 1; ; i-- )
+ for( i = T_size - 1; ; i-- )
{
/*
* Zi = 1 / Z_i mod p
@@ -872,7 +1208,7 @@ static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp,
cleanup:
mbedtls_mpi_free( &u ); mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi );
- for( i = 0; i < t_len; i++ )
+ for( i = 0; i < T_size; i++ )
mbedtls_mpi_free( &c[i] );
mbedtls_free( c );
@@ -929,10 +1265,8 @@ static int ecp_double_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
#endif
#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT)
- if ( mbedtls_internal_ecp_grp_capable( grp ) )
- {
- return mbedtls_internal_ecp_double_jac( grp, R, P );
- }
+ if( mbedtls_internal_ecp_grp_capable( grp ) )
+ return( mbedtls_internal_ecp_double_jac( grp, R, P ) );
#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */
mbedtls_mpi_init( &M ); mbedtls_mpi_init( &S ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &U );
@@ -1027,10 +1361,8 @@ static int ecp_add_mixed( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
#endif
#if defined(MBEDTLS_ECP_ADD_MIXED_ALT)
- if ( mbedtls_internal_ecp_grp_capable( grp ) )
- {
- return mbedtls_internal_ecp_add_mixed( grp, R, P, Q );
- }
+ if( mbedtls_internal_ecp_grp_capable( grp ) )
+ return( mbedtls_internal_ecp_add_mixed( grp, R, P, Q ) );
#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */
/*
@@ -1114,10 +1446,8 @@ static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *p
int count = 0;
#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT)
- if ( mbedtls_internal_ecp_grp_capable( grp ) )
- {
- return mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng );
- }
+ if( mbedtls_internal_ecp_grp_capable( grp ) )
+ return( mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng ) );
#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */
p_size = ( grp->pbits + 7 ) / 8;
@@ -1173,11 +1503,38 @@ cleanup:
* modified version that provides resistance to SPA by avoiding zero
* digits in the representation as in [3]. We modify the method further by
* requiring that all K_i be odd, which has the small cost that our
- * representation uses one more K_i, due to carries.
+ * representation uses one more K_i, due to carries, but saves on the size of
+ * the precomputed table.
*
- * Also, for the sake of compactness, only the seven low-order bits of x[i]
- * are used to represent K_i, and the msb of x[i] encodes the the sign (s_i in
- * the paper): it is set if and only if if s_i == -1;
+ * Summary of the comb method and its modifications:
+ *
+ * - The goal is to compute m*P for some w*d-bit integer m.
+ *
+ * - The basic comb method splits m into the w-bit integers
+ * x[0] .. x[d-1] where x[i] consists of the bits in m whose
+ * index has residue i modulo d, and computes m * P as
+ * S[x[0]] + 2 * S[x[1]] + .. + 2^(d-1) S[x[d-1]], where
+ * S[i_{w-1} .. i_0] := i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + i_0 P.
+ *
+ * - If it happens that, say, x[i+1]=0 (=> S[x[i+1]]=0), one can replace the sum by
+ * .. + 2^{i-1} S[x[i-1]] - 2^i S[x[i]] + 2^{i+1} S[x[i]] + 2^{i+2} S[x[i+2]] ..,
+ * thereby successively converting it into a form where all summands
+ * are nonzero, at the cost of negative summands. This is the basic idea of [3].
+ *
+ * - More generally, even if x[i+1] != 0, we can first transform the sum as
+ * .. - 2^i S[x[i]] + 2^{i+1} ( S[x[i]] + S[x[i+1]] ) + 2^{i+2} S[x[i+2]] ..,
+ * and then replace S[x[i]] + S[x[i+1]] = S[x[i] ^ x[i+1]] + 2 S[x[i] & x[i+1]].
+ * Performing and iterating this procedure for those x[i] that are even
+ * (keeping track of carry), we can transform the original sum into one of the form
+ * S[x'[0]] +- 2 S[x'[1]] +- .. +- 2^{d-1} S[x'[d-1]] + 2^d S[x'[d]]
+ * with all x'[i] odd. It is therefore only necessary to know S at odd indices,
+ * which is why we are only computing half of it in the first place in
+ * ecp_precompute_comb and accessing it with index abs(i) / 2 in ecp_select_comb.
+ *
+ * - For the sake of compactness, only the seven low-order bits of x[i]
+ * are used to represent its absolute value (K_i in the paper), and the msb
+ * of x[i] encodes the sign (s_i in the paper): it is set if and only if
+ * if s_i == -1;
*
* Calling conventions:
* - x is an array of size d + 1
@@ -1186,8 +1543,8 @@ cleanup:
* - m is the MPI, expected to be odd and such that bitlength(m) <= w * d
* (the result will be incorrect if these assumptions are not satisfied)
*/
-static void ecp_comb_fixed( unsigned char x[], size_t d,
- unsigned char w, const mbedtls_mpi *m )
+static void ecp_comb_recode_core( unsigned char x[], size_t d,
+ unsigned char w, const mbedtls_mpi *m )
{
size_t i, j;
unsigned char c, cc, adjust;
@@ -1217,70 +1574,178 @@ static void ecp_comb_fixed( unsigned char x[], size_t d,
}
/*
- * Precompute points for the comb method
+ * Precompute points for the adapted comb method
*
- * If i = i_{w-1} ... i_1 is the binary representation of i, then
- * T[i] = i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + P
+ * Assumption: T must be able to hold 2^{w - 1} elements.
*
- * T must be able to hold 2^{w - 1} elements
+ * Operation: If i = i_{w-1} ... i_1 is the binary representation of i,
+ * sets T[i] = i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + P.
*
* Cost: d(w-1) D + (2^{w-1} - 1) A + 1 N(w-1) + 1 N(2^{w-1} - 1)
+ *
+ * Note: Even comb values (those where P would be omitted from the
+ * sum defining T[i] above) are not needed in our adaption
+ * the comb method. See ecp_comb_recode_core().
+ *
+ * This function currently works in four steps:
+ * (1) [dbl] Computation of intermediate T[i] for 2-power values of i
+ * (2) [norm_dbl] Normalization of coordinates of these T[i]
+ * (3) [add] Computation of all T[i]
+ * (4) [norm_add] Normalization of all T[i]
+ *
+ * Step 1 can be interrupted but not the others; together with the final
+ * coordinate normalization they are the largest steps done at once, depending
+ * on the window size. Here are operation counts for P-256:
+ *
+ * step (2) (3) (4)
+ * w = 5 142 165 208
+ * w = 4 136 77 160
+ * w = 3 130 33 136
+ * w = 2 124 11 124
+ *
+ * So if ECC operations are blocking for too long even with a low max_ops
+ * value, it's useful to set MBEDTLS_ECP_WINDOW_SIZE to a lower value in order
+ * to minimize maximum blocking time.
*/
static int ecp_precompute_comb( const mbedtls_ecp_group *grp,
mbedtls_ecp_point T[], const mbedtls_ecp_point *P,
- unsigned char w, size_t d )
+ unsigned char w, size_t d,
+ mbedtls_ecp_restart_ctx *rs_ctx )
{
int ret;
- unsigned char i, k;
- size_t j;
+ unsigned char i;
+ size_t j = 0;
+ const unsigned char T_size = 1U << ( w - 1 );
mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1];
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->rsm != NULL )
+ {
+ if( rs_ctx->rsm->state == ecp_rsm_pre_dbl )
+ goto dbl;
+ if( rs_ctx->rsm->state == ecp_rsm_pre_norm_dbl )
+ goto norm_dbl;
+ if( rs_ctx->rsm->state == ecp_rsm_pre_add )
+ goto add;
+ if( rs_ctx->rsm->state == ecp_rsm_pre_norm_add )
+ goto norm_add;
+ }
+#else
+ (void) rs_ctx;
+#endif
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->rsm != NULL )
+ {
+ rs_ctx->rsm->state = ecp_rsm_pre_dbl;
+
+ /* initial state for the loop */
+ rs_ctx->rsm->i = 0;
+ }
+
+dbl:
+#endif
/*
* Set T[0] = P and
* T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value)
*/
MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) );
- k = 0;
- for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 )
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 )
+ j = rs_ctx->rsm->i;
+ else
+#endif
+ j = 0;
+
+ for( ; j < d * ( w - 1 ); j++ )
{
+ MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL );
+
+ i = 1U << ( j / d );
cur = T + i;
- MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) );
- for( j = 0; j < d; j++ )
- MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) );
- TT[k++] = cur;
+ if( j % d == 0 )
+ MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) );
+
+ MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) );
}
- MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) );
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->rsm != NULL )
+ rs_ctx->rsm->state = ecp_rsm_pre_norm_dbl;
+norm_dbl:
+#endif
+ /*
+ * Normalize current elements in T. As T has holes,
+ * use an auxiliary array of pointers to elements in T.
+ */
+ j = 0;
+ for( i = 1; i < T_size; i <<= 1 )
+ TT[j++] = T + i;
+
+ MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 );
+
+ MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->rsm != NULL )
+ rs_ctx->rsm->state = ecp_rsm_pre_add;
+
+add:
+#endif
/*
* Compute the remaining ones using the minimal number of additions
* Be careful to update T[2^l] only after using it!
*/
- k = 0;
- for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 )
+ MBEDTLS_ECP_BUDGET( ( T_size - 1 ) * MBEDTLS_ECP_OPS_ADD );
+
+ for( i = 1; i < T_size; i <<= 1 )
{
j = i;
while( j-- )
- {
MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) );
- TT[k++] = &T[i + j];
- }
}
- MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) );
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->rsm != NULL )
+ rs_ctx->rsm->state = ecp_rsm_pre_norm_add;
+
+norm_add:
+#endif
+ /*
+ * Normalize final elements in T. Even though there are no holes now, we
+ * still need the auxiliary array for homogeneity with the previous
+ * call. Also, skip T[0] which is already normalised, being a copy of P.
+ */
+ for( j = 0; j + 1 < T_size; j++ )
+ TT[j] = T + j + 1;
+
+ MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 );
+
+ MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) );
cleanup:
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->rsm != NULL &&
+ ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
+ {
+ if( rs_ctx->rsm->state == ecp_rsm_pre_dbl )
+ rs_ctx->rsm->i = j;
+ }
+#endif
return( ret );
}
/*
* Select precomputed point: R = sign(i) * T[ abs(i) / 2 ]
+ *
+ * See ecp_comb_recode_core() for background
*/
static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
- const mbedtls_ecp_point T[], unsigned char t_len,
+ const mbedtls_ecp_point T[], unsigned char T_size,
unsigned char i )
{
int ret;
@@ -1290,7 +1755,7 @@ static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
ii = ( i & 0x7Fu ) >> 1;
/* Read the whole table to thwart cache-based timing attacks */
- for( j = 0; j < t_len; j++ )
+ for( j = 0; j < T_size; j++ )
{
MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) );
@@ -1310,10 +1775,11 @@ cleanup:
* Cost: d A + d D + 1 R
*/
static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
- const mbedtls_ecp_point T[], unsigned char t_len,
+ const mbedtls_ecp_point T[], unsigned char T_size,
const unsigned char x[], size_t d,
int (*f_rng)(void *, unsigned char *, size_t),
- void *p_rng )
+ void *p_rng,
+ mbedtls_ecp_restart_ctx *rs_ctx )
{
int ret;
mbedtls_ecp_point Txi;
@@ -1321,17 +1787,42 @@ static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R
mbedtls_ecp_point_init( &Txi );
- /* Start with a non-zero point and randomize its coordinates */
- i = d;
- MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, t_len, x[i] ) );
- MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) );
- if( f_rng != 0 )
- MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) );
+#if !defined(MBEDTLS_ECP_RESTARTABLE)
+ (void) rs_ctx;
+#endif
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->rsm != NULL &&
+ rs_ctx->rsm->state != ecp_rsm_comb_core )
+ {
+ rs_ctx->rsm->i = 0;
+ rs_ctx->rsm->state = ecp_rsm_comb_core;
+ }
+
+ /* new 'if' instead of nested for the sake of the 'else' branch */
+ if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 )
+ {
+ /* restore current index (R already pointing to rs_ctx->rsm->R) */
+ i = rs_ctx->rsm->i;
+ }
+ else
+#endif
+ {
+ /* Start with a non-zero point and randomize its coordinates */
+ i = d;
+ MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, T_size, x[i] ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) );
+ if( f_rng != 0 )
+ MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) );
+ }
- while( i-- != 0 )
+ while( i != 0 )
{
+ MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL + MBEDTLS_ECP_OPS_ADD );
+ --i;
+
MBEDTLS_MPI_CHK( ecp_double_jac( grp, R, R ) );
- MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, t_len, x[i] ) );
+ MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, T_size, x[i] ) );
MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) );
}
@@ -1339,32 +1830,130 @@ cleanup:
mbedtls_ecp_point_free( &Txi );
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->rsm != NULL &&
+ ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
+ {
+ rs_ctx->rsm->i = i;
+ /* no need to save R, already pointing to rs_ctx->rsm->R */
+ }
+#endif
+
return( ret );
}
/*
- * Multiplication using the comb method,
- * for curves in short Weierstrass form
- */
-static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
- const mbedtls_mpi *m, const mbedtls_ecp_point *P,
- int (*f_rng)(void *, unsigned char *, size_t),
- void *p_rng )
+ * Recode the scalar to get constant-time comb multiplication
+ *
+ * As the actual scalar recoding needs an odd scalar as a starting point,
+ * this wrapper ensures that by replacing m by N - m if necessary, and
+ * informs the caller that the result of multiplication will be negated.
+ *
+ * This works because we only support large prime order for Short Weierstrass
+ * curves, so N is always odd hence either m or N - m is.
+ *
+ * See ecp_comb_recode_core() for background.
+ */
+static int ecp_comb_recode_scalar( const mbedtls_ecp_group *grp,
+ const mbedtls_mpi *m,
+ unsigned char k[COMB_MAX_D + 1],
+ size_t d,
+ unsigned char w,
+ unsigned char *parity_trick )
{
int ret;
- unsigned char w, m_is_odd, p_eq_g, pre_len, i;
- size_t d;
- unsigned char k[COMB_MAX_D + 1];
- mbedtls_ecp_point *T;
mbedtls_mpi M, mm;
mbedtls_mpi_init( &M );
mbedtls_mpi_init( &mm );
- /* we need N to be odd to trnaform m in an odd number, check now */
+ /* N is always odd (see above), just make extra sure */
if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 )
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+ /* do we need the parity trick? */
+ *parity_trick = ( mbedtls_mpi_get_bit( m, 0 ) == 0 );
+
+ /* execute parity fix in constant time */
+ MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, *parity_trick ) );
+
+ /* actual scalar recoding */
+ ecp_comb_recode_core( k, d, w, &M );
+
+cleanup:
+ mbedtls_mpi_free( &mm );
+ mbedtls_mpi_free( &M );
+
+ return( ret );
+}
+
+/*
+ * Perform comb multiplication (for short Weierstrass curves)
+ * once the auxiliary table has been pre-computed.
+ *
+ * Scalar recoding may use a parity trick that makes us compute -m * P,
+ * if that is the case we'll need to recover m * P at the end.
+ */
+static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp,
+ mbedtls_ecp_point *R,
+ const mbedtls_mpi *m,
+ const mbedtls_ecp_point *T,
+ unsigned char T_size,
+ unsigned char w,
+ size_t d,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ mbedtls_ecp_restart_ctx *rs_ctx )
+{
+ int ret;
+ unsigned char parity_trick;
+ unsigned char k[COMB_MAX_D + 1];
+ mbedtls_ecp_point *RR = R;
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->rsm != NULL )
+ {
+ RR = &rs_ctx->rsm->R;
+
+ if( rs_ctx->rsm->state == ecp_rsm_final_norm )
+ goto final_norm;
+ }
+#endif
+
+ MBEDTLS_MPI_CHK( ecp_comb_recode_scalar( grp, m, k, d, w,
+ &parity_trick ) );
+ MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, RR, T, T_size, k, d,
+ f_rng, p_rng, rs_ctx ) );
+ MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, RR, parity_trick ) );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->rsm != NULL )
+ rs_ctx->rsm->state = ecp_rsm_final_norm;
+
+final_norm:
+#endif
+ MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV );
+ MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, RR ) );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->rsm != NULL )
+ MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, RR ) );
+#endif
+
+cleanup:
+ return( ret );
+}
+
+/*
+ * Pick window size based on curve size and whether we optimize for base point
+ */
+static unsigned char ecp_pick_window_size( const mbedtls_ecp_group *grp,
+ unsigned char p_eq_g )
+{
+ unsigned char w;
+
/*
* Minimize the number of multiplications, that is minimize
* 10 * d * w + 18 * 2^(w-1) + 11 * d + 7 * w, with d = ceil( nbits / w )
@@ -1377,14 +1966,8 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
* Just adding one avoids upping the cost of the first mul too much,
* and the memory cost too.
*/
-#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
- p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 &&
- mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 );
if( p_eq_g )
w++;
-#else
- p_eq_g = 0;
-#endif
/*
* Make sure w is within bounds.
@@ -1395,70 +1978,140 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
if( w >= grp->nbits )
w = 2;
- /* Other sizes that depend on w */
- pre_len = 1U << ( w - 1 );
+ return( w );
+}
+
+/*
+ * Multiplication using the comb method - for curves in short Weierstrass form
+ *
+ * This function is mainly responsible for administrative work:
+ * - managing the restart context if enabled
+ * - managing the table of precomputed points (passed between the below two
+ * functions): allocation, computation, ownership tranfer, freeing.
+ *
+ * It delegates the actual arithmetic work to:
+ * ecp_precompute_comb() and ecp_mul_comb_with_precomp()
+ *
+ * See comments on ecp_comb_recode_core() regarding the computation strategy.
+ */
+static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
+ const mbedtls_mpi *m, const mbedtls_ecp_point *P,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ mbedtls_ecp_restart_ctx *rs_ctx )
+{
+ int ret;
+ unsigned char w, p_eq_g, i;
+ size_t d;
+ unsigned char T_size, T_ok;
+ mbedtls_ecp_point *T;
+
+ ECP_RS_ENTER( rsm );
+
+ /* Is P the base point ? */
+#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
+ p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 &&
+ mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 );
+#else
+ p_eq_g = 0;
+#endif
+
+ /* Pick window size and deduce related sizes */
+ w = ecp_pick_window_size( grp, p_eq_g );
+ T_size = 1U << ( w - 1 );
d = ( grp->nbits + w - 1 ) / w;
- /*
- * Prepare precomputed points: if P == G we want to
- * use grp->T if already initialized, or initialize it.
- */
- T = p_eq_g ? grp->T : NULL;
+ /* Pre-computed table: do we have it already for the base point? */
+ if( p_eq_g && grp->T != NULL )
+ {
+ /* second pointer to the same table, will be deleted on exit */
+ T = grp->T;
+ T_ok = 1;
+ }
+ else
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ /* Pre-computed table: do we have one in progress? complete? */
+ if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->T != NULL )
+ {
+ /* transfer ownership of T from rsm to local function */
+ T = rs_ctx->rsm->T;
+ rs_ctx->rsm->T = NULL;
+ rs_ctx->rsm->T_size = 0;
- if( T == NULL )
+ /* This effectively jumps to the call to mul_comb_after_precomp() */
+ T_ok = rs_ctx->rsm->state >= ecp_rsm_comb_core;
+ }
+ else
+#endif
+ /* Allocate table if we didn't have any */
{
- T = mbedtls_calloc( pre_len, sizeof( mbedtls_ecp_point ) );
+ T = mbedtls_calloc( T_size, sizeof( mbedtls_ecp_point ) );
if( T == NULL )
{
ret = MBEDTLS_ERR_ECP_ALLOC_FAILED;
goto cleanup;
}
- MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d ) );
+ for( i = 0; i < T_size; i++ )
+ mbedtls_ecp_point_init( &T[i] );
+
+ T_ok = 0;
+ }
+
+ /* Compute table (or finish computing it) if not done already */
+ if( !T_ok )
+ {
+ MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d, rs_ctx ) );
if( p_eq_g )
{
+ /* almost transfer ownership of T to the group, but keep a copy of
+ * the pointer to use for calling the next function more easily */
grp->T = T;
- grp->T_size = pre_len;
+ grp->T_size = T_size;
}
}
- /*
- * Make sure M is odd (M = m or M = N - m, since N is odd)
- * using the fact that m * P = - (N - m) * P
- */
- m_is_odd = ( mbedtls_mpi_get_bit( m, 0 ) == 1 );
- MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) );
- MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) );
- MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, ! m_is_odd ) );
+ /* Actual comb multiplication using precomputed points */
+ MBEDTLS_MPI_CHK( ecp_mul_comb_after_precomp( grp, R, m,
+ T, T_size, w, d,
+ f_rng, p_rng, rs_ctx ) );
- /*
- * Go for comb multiplication, R = M * P
- */
- ecp_comb_fixed( k, d, w, &M );
- MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, R, T, pre_len, k, d, f_rng, p_rng ) );
+cleanup:
- /*
- * Now get m * P from M * P and normalize it
- */
- MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, ! m_is_odd ) );
- MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) );
+ /* does T belong to the group? */
+ if( T == grp->T )
+ T = NULL;
-cleanup:
+ /* does T belong to the restart context? */
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->rsm != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS && T != NULL )
+ {
+ /* transfer ownership of T from local function to rsm */
+ rs_ctx->rsm->T_size = T_size;
+ rs_ctx->rsm->T = T;
+ T = NULL;
+ }
+#endif
- if( T != NULL && ! p_eq_g )
+ /* did T belong to us? then let's destroy it! */
+ if( T != NULL )
{
- for( i = 0; i < pre_len; i++ )
+ for( i = 0; i < T_size; i++ )
mbedtls_ecp_point_free( &T[i] );
mbedtls_free( T );
}
- mbedtls_mpi_free( &M );
- mbedtls_mpi_free( &mm );
-
+ /* don't free R while in progress in case R == P */
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
+#endif
+ /* prevent caller from using invalid value */
if( ret != 0 )
mbedtls_ecp_point_free( R );
+ ECP_RS_LEAVE( rsm );
+
return( ret );
}
@@ -1482,10 +2135,8 @@ static int ecp_normalize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P
int ret;
#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT)
- if ( mbedtls_internal_ecp_grp_capable( grp ) )
- {
- return mbedtls_internal_ecp_normalize_mxz( grp, P );
- }
+ if( mbedtls_internal_ecp_grp_capable( grp ) )
+ return( mbedtls_internal_ecp_normalize_mxz( grp, P ) );
#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &P->Z, &P->Z, &grp->P ) );
@@ -1513,10 +2164,8 @@ static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P
int count = 0;
#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT)
- if ( mbedtls_internal_ecp_grp_capable( grp ) )
- {
- return mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng );
- }
+ if( mbedtls_internal_ecp_grp_capable( grp ) )
+ return( mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng );
#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */
p_size = ( grp->pbits + 7 ) / 8;
@@ -1568,10 +2217,8 @@ static int ecp_double_add_mxz( const mbedtls_ecp_group *grp,
mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB;
#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT)
- if ( mbedtls_internal_ecp_grp_capable( grp ) )
- {
- return mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d );
- }
+ if( mbedtls_internal_ecp_grp_capable( grp ) )
+ return( mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d ) );
#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */
mbedtls_mpi_init( &A ); mbedtls_mpi_init( &AA ); mbedtls_mpi_init( &B );
@@ -1668,54 +2315,85 @@ cleanup:
#endif /* ECP_MONTGOMERY */
/*
- * Multiplication R = m * P
+ * Restartable multiplication R = m * P
*/
-int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
+int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
const mbedtls_mpi *m, const mbedtls_ecp_point *P,
- int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+ mbedtls_ecp_restart_ctx *rs_ctx )
{
int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
#if defined(MBEDTLS_ECP_INTERNAL_ALT)
char is_grp_capable = 0;
#endif
-
- /* Common sanity checks */
- if( mbedtls_mpi_cmp_int( &P->Z, 1 ) != 0 )
- return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
-
- if( ( ret = mbedtls_ecp_check_privkey( grp, m ) ) != 0 ||
- ( ret = mbedtls_ecp_check_pubkey( grp, P ) ) != 0 )
- return( ret );
+ ECP_VALIDATE_RET( grp != NULL );
+ ECP_VALIDATE_RET( R != NULL );
+ ECP_VALIDATE_RET( m != NULL );
+ ECP_VALIDATE_RET( P != NULL );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ /* reset ops count for this call if top-level */
+ if( rs_ctx != NULL && rs_ctx->depth++ == 0 )
+ rs_ctx->ops_done = 0;
+#endif
#if defined(MBEDTLS_ECP_INTERNAL_ALT)
- if ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) )
- {
+ if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) )
MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
+#endif /* MBEDTLS_ECP_INTERNAL_ALT */
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ /* skip argument check when restarting */
+ if( rs_ctx == NULL || rs_ctx->rsm == NULL )
+#endif
+ {
+ /* check_privkey is free */
+ MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_CHK );
+
+ /* Common sanity checks */
+ MBEDTLS_MPI_CHK( mbedtls_ecp_check_privkey( grp, m ) );
+ MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, P ) );
}
-#endif /* MBEDTLS_ECP_INTERNAL_ALT */
+ ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
#if defined(ECP_MONTGOMERY)
if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
- ret = ecp_mul_mxz( grp, R, m, P, f_rng, p_rng );
-
+ MBEDTLS_MPI_CHK( ecp_mul_mxz( grp, R, m, P, f_rng, p_rng ) );
#endif
#if defined(ECP_SHORTWEIERSTRASS)
if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
- ret = ecp_mul_comb( grp, R, m, P, f_rng, p_rng );
-
+ MBEDTLS_MPI_CHK( ecp_mul_comb( grp, R, m, P, f_rng, p_rng, rs_ctx ) );
#endif
-#if defined(MBEDTLS_ECP_INTERNAL_ALT)
+
cleanup:
- if ( is_grp_capable )
- {
+#if defined(MBEDTLS_ECP_INTERNAL_ALT)
+ if( is_grp_capable )
mbedtls_internal_ecp_free( grp );
- }
-
#endif /* MBEDTLS_ECP_INTERNAL_ALT */
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL )
+ rs_ctx->depth--;
+#endif
+
return( ret );
}
+/*
+ * Multiplication R = m * P
+ */
+int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
+ const mbedtls_mpi *m, const mbedtls_ecp_point *P,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+ ECP_VALIDATE_RET( grp != NULL );
+ ECP_VALIDATE_RET( R != NULL );
+ ECP_VALIDATE_RET( m != NULL );
+ ECP_VALIDATE_RET( P != NULL );
+ return( mbedtls_ecp_mul_restartable( grp, R, m, P, f_rng, p_rng, NULL ) );
+}
+
#if defined(ECP_SHORTWEIERSTRASS)
/*
* Check that an affine point is valid as a public key,
@@ -1773,7 +2451,8 @@ cleanup:
static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp,
mbedtls_ecp_point *R,
const mbedtls_mpi *m,
- const mbedtls_ecp_point *P )
+ const mbedtls_ecp_point *P,
+ mbedtls_ecp_restart_ctx *rs_ctx )
{
int ret;
@@ -1789,7 +2468,8 @@ static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp,
}
else
{
- MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, R, m, P, NULL, NULL ) );
+ MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, R, m, P,
+ NULL, NULL, rs_ctx ) );
}
cleanup:
@@ -1797,51 +2477,118 @@ cleanup:
}
/*
- * Linear combination
+ * Restartable linear combination
* NOT constant-time
*/
-int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
+int mbedtls_ecp_muladd_restartable(
+ mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
const mbedtls_mpi *m, const mbedtls_ecp_point *P,
- const mbedtls_mpi *n, const mbedtls_ecp_point *Q )
+ const mbedtls_mpi *n, const mbedtls_ecp_point *Q,
+ mbedtls_ecp_restart_ctx *rs_ctx )
{
int ret;
mbedtls_ecp_point mP;
+ mbedtls_ecp_point *pmP = &mP;
+ mbedtls_ecp_point *pR = R;
#if defined(MBEDTLS_ECP_INTERNAL_ALT)
char is_grp_capable = 0;
#endif
+ ECP_VALIDATE_RET( grp != NULL );
+ ECP_VALIDATE_RET( R != NULL );
+ ECP_VALIDATE_RET( m != NULL );
+ ECP_VALIDATE_RET( P != NULL );
+ ECP_VALIDATE_RET( n != NULL );
+ ECP_VALIDATE_RET( Q != NULL );
if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS )
return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
mbedtls_ecp_point_init( &mP );
- MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, &mP, m, P ) );
- MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, R, n, Q ) );
+ ECP_RS_ENTER( ma );
-#if defined(MBEDTLS_ECP_INTERNAL_ALT)
- if ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) )
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->ma != NULL )
{
- MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
+ /* redirect intermediate results to restart context */
+ pmP = &rs_ctx->ma->mP;
+ pR = &rs_ctx->ma->R;
+
+ /* jump to next operation */
+ if( rs_ctx->ma->state == ecp_rsma_mul2 )
+ goto mul2;
+ if( rs_ctx->ma->state == ecp_rsma_add )
+ goto add;
+ if( rs_ctx->ma->state == ecp_rsma_norm )
+ goto norm;
}
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+ MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pmP, m, P, rs_ctx ) );
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->ma != NULL )
+ rs_ctx->ma->state = ecp_rsma_mul2;
+
+mul2:
+#endif
+ MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pR, n, Q, rs_ctx ) );
+
+#if defined(MBEDTLS_ECP_INTERNAL_ALT)
+ if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) )
+ MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
#endif /* MBEDTLS_ECP_INTERNAL_ALT */
- MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, &mP, R ) );
- MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) );
-cleanup:
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->ma != NULL )
+ rs_ctx->ma->state = ecp_rsma_add;
+
+add:
+#endif
+ MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_ADD );
+ MBEDTLS_MPI_CHK( ecp_add_mixed( grp, pR, pmP, pR ) );
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->ma != NULL )
+ rs_ctx->ma->state = ecp_rsma_norm;
+
+norm:
+#endif
+ MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV );
+ MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, pR ) );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->ma != NULL )
+ MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, pR ) );
+#endif
+cleanup:
#if defined(MBEDTLS_ECP_INTERNAL_ALT)
- if ( is_grp_capable )
- {
+ if( is_grp_capable )
mbedtls_internal_ecp_free( grp );
- }
-
#endif /* MBEDTLS_ECP_INTERNAL_ALT */
+
mbedtls_ecp_point_free( &mP );
+ ECP_RS_LEAVE( ma );
+
return( ret );
}
+/*
+ * Linear combination
+ * NOT constant-time
+ */
+int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
+ const mbedtls_mpi *m, const mbedtls_ecp_point *P,
+ const mbedtls_mpi *n, const mbedtls_ecp_point *Q )
+{
+ ECP_VALIDATE_RET( grp != NULL );
+ ECP_VALIDATE_RET( R != NULL );
+ ECP_VALIDATE_RET( m != NULL );
+ ECP_VALIDATE_RET( P != NULL );
+ ECP_VALIDATE_RET( n != NULL );
+ ECP_VALIDATE_RET( Q != NULL );
+ return( mbedtls_ecp_muladd_restartable( grp, R, m, P, n, Q, NULL ) );
+}
#if defined(ECP_MONTGOMERY)
/*
@@ -1862,8 +2609,12 @@ static int ecp_check_pubkey_mx( const mbedtls_ecp_group *grp, const mbedtls_ecp_
/*
* Check that a point is valid as a public key
*/
-int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
+int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp,
+ const mbedtls_ecp_point *pt )
{
+ ECP_VALIDATE_RET( grp != NULL );
+ ECP_VALIDATE_RET( pt != NULL );
+
/* Must use affine coordinates */
if( mbedtls_mpi_cmp_int( &pt->Z, 1 ) != 0 )
return( MBEDTLS_ERR_ECP_INVALID_KEY );
@@ -1882,8 +2633,12 @@ int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_po
/*
* Check that an mbedtls_mpi is valid as a private key
*/
-int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *d )
+int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp,
+ const mbedtls_mpi *d )
{
+ ECP_VALIDATE_RET( grp != NULL );
+ ECP_VALIDATE_RET( d != NULL );
+
#if defined(ECP_MONTGOMERY)
if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
{
@@ -1892,7 +2647,6 @@ int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *
mbedtls_mpi_get_bit( d, 1 ) != 0 ||
mbedtls_mpi_bitlen( d ) - 1 != grp->nbits ) /* mbedtls_mpi_bitlen is one-based! */
return( MBEDTLS_ERR_ECP_INVALID_KEY );
- else
/* see [Curve25519] page 5 */
if( grp->nbits == 254 && mbedtls_mpi_get_bit( d, 2 ) != 0 )
@@ -1917,16 +2671,21 @@ int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *
}
/*
- * Generate a keypair with configurable base point
+ * Generate a private key
*/
-int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
- const mbedtls_ecp_point *G,
- mbedtls_mpi *d, mbedtls_ecp_point *Q,
+int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp,
+ mbedtls_mpi *d,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
- int ret;
- size_t n_size = ( grp->nbits + 7 ) / 8;
+ int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+ size_t n_size;
+
+ ECP_VALIDATE_RET( grp != NULL );
+ ECP_VALIDATE_RET( d != NULL );
+ ECP_VALIDATE_RET( f_rng != NULL );
+
+ n_size = ( grp->nbits + 7 ) / 8;
#if defined(ECP_MONTGOMERY)
if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
@@ -1954,8 +2713,8 @@ int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) );
}
}
- else
#endif /* ECP_MONTGOMERY */
+
#if defined(ECP_SHORTWEIERSTRASS)
if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
{
@@ -1989,15 +2748,33 @@ int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
while( mbedtls_mpi_cmp_int( d, 1 ) < 0 ||
mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 );
}
- else
#endif /* ECP_SHORTWEIERSTRASS */
- return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
cleanup:
- if( ret != 0 )
- return( ret );
+ return( ret );
+}
- return( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) );
+/*
+ * Generate a keypair with configurable base point
+ */
+int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
+ const mbedtls_ecp_point *G,
+ mbedtls_mpi *d, mbedtls_ecp_point *Q,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ int ret;
+ ECP_VALIDATE_RET( grp != NULL );
+ ECP_VALIDATE_RET( d != NULL );
+ ECP_VALIDATE_RET( G != NULL );
+ ECP_VALIDATE_RET( Q != NULL );
+ ECP_VALIDATE_RET( f_rng != NULL );
+
+ MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
+ MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) );
+
+cleanup:
+ return( ret );
}
/*
@@ -2008,6 +2785,11 @@ int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
+ ECP_VALIDATE_RET( grp != NULL );
+ ECP_VALIDATE_RET( d != NULL );
+ ECP_VALIDATE_RET( Q != NULL );
+ ECP_VALIDATE_RET( f_rng != NULL );
+
return( mbedtls_ecp_gen_keypair_base( grp, &grp->G, d, Q, f_rng, p_rng ) );
}
@@ -2018,6 +2800,8 @@ int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
{
int ret;
+ ECP_VALIDATE_RET( key != NULL );
+ ECP_VALIDATE_RET( f_rng != NULL );
if( ( ret = mbedtls_ecp_group_load( &key->grp, grp_id ) ) != 0 )
return( ret );
@@ -2033,6 +2817,8 @@ int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ec
int ret;
mbedtls_ecp_point Q;
mbedtls_ecp_group grp;
+ ECP_VALIDATE_RET( pub != NULL );
+ ECP_VALIDATE_RET( prv != NULL );
if( pub->grp.id == MBEDTLS_ECP_DP_NONE ||
pub->grp.id != prv->grp.id ||
diff --git a/thirdparty/mbedtls/library/ecp_curves.c b/thirdparty/mbedtls/library/ecp_curves.c
index 68e2441ae8..731621dc3c 100644
--- a/thirdparty/mbedtls/library/ecp_curves.c
+++ b/thirdparty/mbedtls/library/ecp_curves.c
@@ -28,11 +28,18 @@
#if defined(MBEDTLS_ECP_C)
#include "mbedtls/ecp.h"
+#include "mbedtls/platform_util.h"
#include <string.h>
#if !defined(MBEDTLS_ECP_ALT)
+/* Parameter validation macros based on platform_util.h */
+#define ECP_VALIDATE_RET( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
+#define ECP_VALIDATE( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE( cond )
+
#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
!defined(inline) && !defined(__cplusplus)
#define inline __inline
@@ -746,6 +753,7 @@ cleanup:
*/
int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id id )
{
+ ECP_VALIDATE_RET( grp != NULL );
mbedtls_ecp_group_free( grp );
grp->id = id;
diff --git a/thirdparty/mbedtls/library/entropy_poll.c b/thirdparty/mbedtls/library/entropy_poll.c
index f44a753f4d..ba56b70f77 100644
--- a/thirdparty/mbedtls/library/entropy_poll.c
+++ b/thirdparty/mbedtls/library/entropy_poll.c
@@ -114,6 +114,7 @@ int mbedtls_platform_entropy_poll( void *data, unsigned char *output, size_t len
#include <sys/syscall.h>
#if defined(SYS_getrandom)
#define HAVE_GETRANDOM
+#include <errno.h>
static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags )
{
@@ -123,47 +124,8 @@ static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags )
memset( buf, 0, buflen );
#endif
#endif
-
return( syscall( SYS_getrandom, buf, buflen, flags ) );
}
-
-#include <sys/utsname.h>
-/* Check if version is at least 3.17.0 */
-static int check_version_3_17_plus( void )
-{
- int minor;
- struct utsname un;
- const char *ver;
-
- /* Get version information */
- uname(&un);
- ver = un.release;
-
- /* Check major version; assume a single digit */
- if( ver[0] < '3' || ver[0] > '9' || ver [1] != '.' )
- return( -1 );
-
- if( ver[0] - '0' > 3 )
- return( 0 );
-
- /* Ok, so now we know major == 3, check minor.
- * Assume 1 or 2 digits. */
- if( ver[2] < '0' || ver[2] > '9' )
- return( -1 );
-
- minor = ver[2] - '0';
-
- if( ver[3] >= '0' && ver[3] <= '9' )
- minor = 10 * minor + ver[3] - '0';
- else if( ver [3] != '.' )
- return( -1 );
-
- if( minor < 17 )
- return( -1 );
-
- return( 0 );
-}
-static int has_getrandom = -1;
#endif /* SYS_getrandom */
#endif /* __linux__ */
@@ -174,22 +136,21 @@ int mbedtls_platform_entropy_poll( void *data,
{
FILE *file;
size_t read_len;
+ int ret;
((void) data);
#if defined(HAVE_GETRANDOM)
- if( has_getrandom == -1 )
- has_getrandom = ( check_version_3_17_plus() == 0 );
-
- if( has_getrandom )
+ ret = getrandom_wrapper( output, len, 0 );
+ if( ret >= 0 )
{
- int ret;
-
- if( ( ret = getrandom_wrapper( output, len, 0 ) ) < 0 )
- return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
-
*olen = ret;
return( 0 );
}
+ else if( errno != ENOSYS )
+ return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
+ /* Fall through if the system call isn't known. */
+#else
+ ((void) ret);
#endif /* HAVE_GETRANDOM */
*olen = 0;
diff --git a/thirdparty/mbedtls/library/entropy_poll.c.orig b/thirdparty/mbedtls/library/entropy_poll.c.orig
deleted file mode 100644
index 040aa117dc..0000000000
--- a/thirdparty/mbedtls/library/entropy_poll.c.orig
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * Platform-specific and custom entropy polling functions
- *
- * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
- * SPDX-License-Identifier: Apache-2.0
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * This file is part of mbed TLS (https://tls.mbed.org)
- */
-
-#if defined(__linux__)
-/* Ensure that syscall() is available even when compiling with -std=c99 */
-#define _GNU_SOURCE
-#endif
-
-#if !defined(MBEDTLS_CONFIG_FILE)
-#include "mbedtls/config.h"
-#else
-#include MBEDTLS_CONFIG_FILE
-#endif
-
-#include <string.h>
-
-#if defined(MBEDTLS_ENTROPY_C)
-
-#include "mbedtls/entropy.h"
-#include "mbedtls/entropy_poll.h"
-
-#if defined(MBEDTLS_TIMING_C)
-#include "mbedtls/timing.h"
-#endif
-#if defined(MBEDTLS_HAVEGE_C)
-#include "mbedtls/havege.h"
-#endif
-#if defined(MBEDTLS_ENTROPY_NV_SEED)
-#include "mbedtls/platform.h"
-#endif
-
-#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY)
-
-#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \
- !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \
- !defined(__HAIKU__)
-#error "Platform entropy sources only work on Unix and Windows, see MBEDTLS_NO_PLATFORM_ENTROPY in config.h"
-#endif
-
-#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
-
-#if !defined(_WIN32_WINNT)
-#define _WIN32_WINNT 0x0400
-#endif
-#include <windows.h>
-#include <wincrypt.h>
-
-int mbedtls_platform_entropy_poll( void *data, unsigned char *output, size_t len,
- size_t *olen )
-{
- HCRYPTPROV provider;
- ((void) data);
- *olen = 0;
-
- if( CryptAcquireContext( &provider, NULL, NULL,
- PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) == FALSE )
- {
- return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
- }
-
- if( CryptGenRandom( provider, (DWORD) len, output ) == FALSE )
- {
- CryptReleaseContext( provider, 0 );
- return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
- }
-
- CryptReleaseContext( provider, 0 );
- *olen = len;
-
- return( 0 );
-}
-#else /* _WIN32 && !EFIX64 && !EFI32 */
-
-/*
- * Test for Linux getrandom() support.
- * Since there is no wrapper in the libc yet, use the generic syscall wrapper
- * available in GNU libc and compatible libc's (eg uClibc).
- */
-#if defined(__linux__) && defined(__GLIBC__)
-#include <unistd.h>
-#include <sys/syscall.h>
-#if defined(SYS_getrandom)
-#define HAVE_GETRANDOM
-
-static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags )
-{
- /* MemSan cannot understand that the syscall writes to the buffer */
-#if defined(__has_feature)
-#if __has_feature(memory_sanitizer)
- memset( buf, 0, buflen );
-#endif
-#endif
-
- return( syscall( SYS_getrandom, buf, buflen, flags ) );
-}
-
-#include <sys/utsname.h>
-/* Check if version is at least 3.17.0 */
-static int check_version_3_17_plus( void )
-{
- int minor;
- struct utsname un;
- const char *ver;
-
- /* Get version information */
- uname(&un);
- ver = un.release;
-
- /* Check major version; assume a single digit */
- if( ver[0] < '3' || ver[0] > '9' || ver [1] != '.' )
- return( -1 );
-
- if( ver[0] - '0' > 3 )
- return( 0 );
-
- /* Ok, so now we know major == 3, check minor.
- * Assume 1 or 2 digits. */
- if( ver[2] < '0' || ver[2] > '9' )
- return( -1 );
-
- minor = ver[2] - '0';
-
- if( ver[3] >= '0' && ver[3] <= '9' )
- minor = 10 * minor + ver[3] - '0';
- else if( ver [3] != '.' )
- return( -1 );
-
- if( minor < 17 )
- return( -1 );
-
- return( 0 );
-}
-static int has_getrandom = -1;
-#endif /* SYS_getrandom */
-#endif /* __linux__ */
-
-#include <stdio.h>
-
-int mbedtls_platform_entropy_poll( void *data,
- unsigned char *output, size_t len, size_t *olen )
-{
- FILE *file;
- size_t read_len;
- ((void) data);
-
-#if defined(HAVE_GETRANDOM)
- if( has_getrandom == -1 )
- has_getrandom = ( check_version_3_17_plus() == 0 );
-
- if( has_getrandom )
- {
- int ret;
-
- if( ( ret = getrandom_wrapper( output, len, 0 ) ) < 0 )
- return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
-
- *olen = ret;
- return( 0 );
- }
-#endif /* HAVE_GETRANDOM */
-
- *olen = 0;
-
- file = fopen( "/dev/urandom", "rb" );
- if( file == NULL )
- return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
-
- read_len = fread( output, 1, len, file );
- if( read_len != len )
- {
- fclose( file );
- return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
- }
-
- fclose( file );
- *olen = len;
-
- return( 0 );
-}
-#endif /* _WIN32 && !EFIX64 && !EFI32 */
-#endif /* !MBEDTLS_NO_PLATFORM_ENTROPY */
-
-#if defined(MBEDTLS_TEST_NULL_ENTROPY)
-int mbedtls_null_entropy_poll( void *data,
- unsigned char *output, size_t len, size_t *olen )
-{
- ((void) data);
- ((void) output);
- *olen = 0;
-
- if( len < sizeof(unsigned char) )
- return( 0 );
-
- *olen = sizeof(unsigned char);
-
- return( 0 );
-}
-#endif
-
-#if defined(MBEDTLS_TIMING_C)
-int mbedtls_hardclock_poll( void *data,
- unsigned char *output, size_t len, size_t *olen )
-{
- unsigned long timer = mbedtls_timing_hardclock();
- ((void) data);
- *olen = 0;
-
- if( len < sizeof(unsigned long) )
- return( 0 );
-
- memcpy( output, &timer, sizeof(unsigned long) );
- *olen = sizeof(unsigned long);
-
- return( 0 );
-}
-#endif /* MBEDTLS_TIMING_C */
-
-#if defined(MBEDTLS_HAVEGE_C)
-int mbedtls_havege_poll( void *data,
- unsigned char *output, size_t len, size_t *olen )
-{
- mbedtls_havege_state *hs = (mbedtls_havege_state *) data;
- *olen = 0;
-
- if( mbedtls_havege_random( hs, output, len ) != 0 )
- return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
-
- *olen = len;
-
- return( 0 );
-}
-#endif /* MBEDTLS_HAVEGE_C */
-
-#if defined(MBEDTLS_ENTROPY_NV_SEED)
-int mbedtls_nv_seed_poll( void *data,
- unsigned char *output, size_t len, size_t *olen )
-{
- unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
- size_t use_len = MBEDTLS_ENTROPY_BLOCK_SIZE;
- ((void) data);
-
- memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
-
- if( mbedtls_nv_seed_read( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 )
- return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
-
- if( len < use_len )
- use_len = len;
-
- memcpy( output, buf, use_len );
- *olen = use_len;
-
- return( 0 );
-}
-#endif /* MBEDTLS_ENTROPY_NV_SEED */
-
-#endif /* MBEDTLS_ENTROPY_C */
diff --git a/thirdparty/mbedtls/library/error.c b/thirdparty/mbedtls/library/error.c
index 774244b454..12312a0562 100644
--- a/thirdparty/mbedtls/library/error.c
+++ b/thirdparty/mbedtls/library/error.c
@@ -165,6 +165,10 @@
#include "mbedtls/pkcs5.h"
#endif
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#endif
+
#if defined(MBEDTLS_POLY1305_C)
#include "mbedtls/poly1305.h"
#endif
@@ -289,6 +293,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
mbedtls_snprintf( buf, buflen, "ECP - The buffer contains a valid signature followed by more data" );
if( use_ret == -(MBEDTLS_ERR_ECP_HW_ACCEL_FAILED) )
mbedtls_snprintf( buf, buflen, "ECP - The ECP hardware accelerator failed" );
+ if( use_ret == -(MBEDTLS_ERR_ECP_IN_PROGRESS) )
+ mbedtls_snprintf( buf, buflen, "ECP - Operation in progress, call again with the same parameters to continue" );
#endif /* MBEDTLS_ECP_C */
#if defined(MBEDTLS_MD_C)
@@ -515,6 +521,10 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
mbedtls_snprintf( buf, buflen, "SSL - Internal-only message signaling that further message-processing should be done" );
if( use_ret == -(MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) )
mbedtls_snprintf( buf, buflen, "SSL - The asynchronous operation is not completed yet" );
+ if( use_ret == -(MBEDTLS_ERR_SSL_EARLY_MESSAGE) )
+ mbedtls_snprintf( buf, buflen, "SSL - Internal-only message signaling that a message arrived early" );
+ if( use_ret == -(MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) )
+ mbedtls_snprintf( buf, buflen, "SSL - A cryptographic operation is in progress. Try again later" );
#endif /* MBEDTLS_SSL_TLS_C */
#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C)
@@ -608,8 +618,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
#endif /* MBEDTLS_ARC4_C */
#if defined(MBEDTLS_ARIA_C)
- if( use_ret == -(MBEDTLS_ERR_ARIA_INVALID_KEY_LENGTH) )
- mbedtls_snprintf( buf, buflen, "ARIA - Invalid key length" );
+ if( use_ret == -(MBEDTLS_ERR_ARIA_BAD_INPUT_DATA) )
+ mbedtls_snprintf( buf, buflen, "ARIA - Bad input data" );
if( use_ret == -(MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH) )
mbedtls_snprintf( buf, buflen, "ARIA - Invalid data input length" );
if( use_ret == -(MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE) )
@@ -662,17 +672,17 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
#endif /* MBEDTLS_BIGNUM_C */
#if defined(MBEDTLS_BLOWFISH_C)
- if( use_ret == -(MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH) )
- mbedtls_snprintf( buf, buflen, "BLOWFISH - Invalid key length" );
- if( use_ret == -(MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED) )
- mbedtls_snprintf( buf, buflen, "BLOWFISH - Blowfish hardware accelerator failed" );
+ if( use_ret == -(MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA) )
+ mbedtls_snprintf( buf, buflen, "BLOWFISH - Bad input data" );
if( use_ret == -(MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH) )
mbedtls_snprintf( buf, buflen, "BLOWFISH - Invalid data input length" );
+ if( use_ret == -(MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED) )
+ mbedtls_snprintf( buf, buflen, "BLOWFISH - Blowfish hardware accelerator failed" );
#endif /* MBEDTLS_BLOWFISH_C */
#if defined(MBEDTLS_CAMELLIA_C)
- if( use_ret == -(MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH) )
- mbedtls_snprintf( buf, buflen, "CAMELLIA - Invalid key length" );
+ if( use_ret == -(MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA) )
+ mbedtls_snprintf( buf, buflen, "CAMELLIA - Bad input data" );
if( use_ret == -(MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH) )
mbedtls_snprintf( buf, buflen, "CAMELLIA - Invalid data input length" );
if( use_ret == -(MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED) )
@@ -821,6 +831,13 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
mbedtls_snprintf( buf, buflen, "PADLOCK - Input data should be aligned" );
#endif /* MBEDTLS_PADLOCK_C */
+#if defined(MBEDTLS_PLATFORM_C)
+ if( use_ret == -(MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED) )
+ mbedtls_snprintf( buf, buflen, "PLATFORM - Hardware accelerator failed" );
+ if( use_ret == -(MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED) )
+ mbedtls_snprintf( buf, buflen, "PLATFORM - The requested feature is not supported by the platform" );
+#endif /* MBEDTLS_PLATFORM_C */
+
#if defined(MBEDTLS_POLY1305_C)
if( use_ret == -(MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA) )
mbedtls_snprintf( buf, buflen, "POLY1305 - Invalid input parameter(s)" );
@@ -838,16 +855,22 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
#if defined(MBEDTLS_SHA1_C)
if( use_ret == -(MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED) )
mbedtls_snprintf( buf, buflen, "SHA1 - SHA-1 hardware accelerator failed" );
+ if( use_ret == -(MBEDTLS_ERR_SHA1_BAD_INPUT_DATA) )
+ mbedtls_snprintf( buf, buflen, "SHA1 - SHA-1 input data was malformed" );
#endif /* MBEDTLS_SHA1_C */
#if defined(MBEDTLS_SHA256_C)
if( use_ret == -(MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED) )
mbedtls_snprintf( buf, buflen, "SHA256 - SHA-256 hardware accelerator failed" );
+ if( use_ret == -(MBEDTLS_ERR_SHA256_BAD_INPUT_DATA) )
+ mbedtls_snprintf( buf, buflen, "SHA256 - SHA-256 input data was malformed" );
#endif /* MBEDTLS_SHA256_C */
#if defined(MBEDTLS_SHA512_C)
if( use_ret == -(MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED) )
mbedtls_snprintf( buf, buflen, "SHA512 - SHA-512 hardware accelerator failed" );
+ if( use_ret == -(MBEDTLS_ERR_SHA512_BAD_INPUT_DATA) )
+ mbedtls_snprintf( buf, buflen, "SHA512 - SHA-512 input data was malformed" );
#endif /* MBEDTLS_SHA512_C */
#if defined(MBEDTLS_THREADING_C)
diff --git a/thirdparty/mbedtls/library/gcm.c b/thirdparty/mbedtls/library/gcm.c
index 57b027933d..675926a518 100644
--- a/thirdparty/mbedtls/library/gcm.c
+++ b/thirdparty/mbedtls/library/gcm.c
@@ -48,9 +48,8 @@
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
#include "mbedtls/aes.h"
-#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
-#else
+#if !defined(MBEDTLS_PLATFORM_C)
#include <stdio.h>
#define mbedtls_printf printf
#endif /* MBEDTLS_PLATFORM_C */
@@ -58,6 +57,12 @@
#if !defined(MBEDTLS_GCM_ALT)
+/* Parameter validation macros */
+#define GCM_VALIDATE_RET( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_GCM_BAD_INPUT )
+#define GCM_VALIDATE( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE( cond )
+
/*
* 32-bit integer manipulation macros (big endian)
*/
@@ -86,6 +91,7 @@
*/
void mbedtls_gcm_init( mbedtls_gcm_context *ctx )
{
+ GCM_VALIDATE( ctx != NULL );
memset( ctx, 0, sizeof( mbedtls_gcm_context ) );
}
@@ -165,6 +171,10 @@ int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx,
int ret;
const mbedtls_cipher_info_t *cipher_info;
+ GCM_VALIDATE_RET( ctx != NULL );
+ GCM_VALIDATE_RET( key != NULL );
+ GCM_VALIDATE_RET( keybits == 128 || keybits == 192 || keybits == 256 );
+
cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, MBEDTLS_MODE_ECB );
if( cipher_info == NULL )
return( MBEDTLS_ERR_GCM_BAD_INPUT );
@@ -275,6 +285,10 @@ int mbedtls_gcm_starts( mbedtls_gcm_context *ctx,
const unsigned char *p;
size_t use_len, olen = 0;
+ GCM_VALIDATE_RET( ctx != NULL );
+ GCM_VALIDATE_RET( iv != NULL );
+ GCM_VALIDATE_RET( add_len == 0 || add != NULL );
+
/* IV and AD are limited to 2^64 bits, so 2^61 bytes */
/* IV is not allowed to be zero length */
if( iv_len == 0 ||
@@ -357,6 +371,10 @@ int mbedtls_gcm_update( mbedtls_gcm_context *ctx,
unsigned char *out_p = output;
size_t use_len, olen = 0;
+ GCM_VALIDATE_RET( ctx != NULL );
+ GCM_VALIDATE_RET( length == 0 || input != NULL );
+ GCM_VALIDATE_RET( length == 0 || output != NULL );
+
if( output > input && (size_t) ( output - input ) < length )
return( MBEDTLS_ERR_GCM_BAD_INPUT );
@@ -410,8 +428,14 @@ int mbedtls_gcm_finish( mbedtls_gcm_context *ctx,
{
unsigned char work_buf[16];
size_t i;
- uint64_t orig_len = ctx->len * 8;
- uint64_t orig_add_len = ctx->add_len * 8;
+ uint64_t orig_len;
+ uint64_t orig_add_len;
+
+ GCM_VALIDATE_RET( ctx != NULL );
+ GCM_VALIDATE_RET( tag != NULL );
+
+ orig_len = ctx->len * 8;
+ orig_add_len = ctx->add_len * 8;
if( tag_len > 16 || tag_len < 4 )
return( MBEDTLS_ERR_GCM_BAD_INPUT );
@@ -453,6 +477,13 @@ int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx,
{
int ret;
+ GCM_VALIDATE_RET( ctx != NULL );
+ GCM_VALIDATE_RET( iv != NULL );
+ GCM_VALIDATE_RET( add_len == 0 || add != NULL );
+ GCM_VALIDATE_RET( length == 0 || input != NULL );
+ GCM_VALIDATE_RET( length == 0 || output != NULL );
+ GCM_VALIDATE_RET( tag != NULL );
+
if( ( ret = mbedtls_gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 )
return( ret );
@@ -481,6 +512,13 @@ int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx,
size_t i;
int diff;
+ GCM_VALIDATE_RET( ctx != NULL );
+ GCM_VALIDATE_RET( iv != NULL );
+ GCM_VALIDATE_RET( add_len == 0 || add != NULL );
+ GCM_VALIDATE_RET( tag != NULL );
+ GCM_VALIDATE_RET( length == 0 || input != NULL );
+ GCM_VALIDATE_RET( length == 0 || output != NULL );
+
if( ( ret = mbedtls_gcm_crypt_and_tag( ctx, MBEDTLS_GCM_DECRYPT, length,
iv, iv_len, add, add_len,
input, output, tag_len, check_tag ) ) != 0 )
@@ -503,6 +541,8 @@ int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx,
void mbedtls_gcm_free( mbedtls_gcm_context *ctx )
{
+ if( ctx == NULL )
+ return;
mbedtls_cipher_free( &ctx->cipher_ctx );
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_gcm_context ) );
}
@@ -764,7 +804,7 @@ int mbedtls_gcm_self_test( int verbose )
* there is an alternative underlying implementation i.e. when
* MBEDTLS_AES_ALT is defined.
*/
- if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && key_len == 192 )
+ if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192 )
{
mbedtls_printf( "skipped\n" );
break;
diff --git a/thirdparty/mbedtls/library/hmac_drbg.c b/thirdparty/mbedtls/library/hmac_drbg.c
index dad55ff861..c50330e7d8 100644
--- a/thirdparty/mbedtls/library/hmac_drbg.c
+++ b/thirdparty/mbedtls/library/hmac_drbg.c
@@ -66,31 +66,60 @@ void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx )
/*
* HMAC_DRBG update, using optional additional data (10.1.2.2)
*/
-void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx,
- const unsigned char *additional, size_t add_len )
+int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx,
+ const unsigned char *additional,
+ size_t add_len )
{
size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
unsigned char sep[1];
unsigned char K[MBEDTLS_MD_MAX_SIZE];
+ int ret;
for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
{
/* Step 1 or 4 */
- mbedtls_md_hmac_reset( &ctx->md_ctx );
- mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
- mbedtls_md_hmac_update( &ctx->md_ctx, sep, 1 );
+ if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
+ goto exit;
+ if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
+ ctx->V, md_len ) ) != 0 )
+ goto exit;
+ if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
+ sep, 1 ) ) != 0 )
+ goto exit;
if( rounds == 2 )
- mbedtls_md_hmac_update( &ctx->md_ctx, additional, add_len );
- mbedtls_md_hmac_finish( &ctx->md_ctx, K );
+ {
+ if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
+ additional, add_len ) ) != 0 )
+ goto exit;
+ }
+ if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, K ) ) != 0 )
+ goto exit;
/* Step 2 or 5 */
- mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len );
- mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
- mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V );
+ if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ) ) != 0 )
+ goto exit;
+ if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
+ ctx->V, md_len ) ) != 0 )
+ goto exit;
+ if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
+ goto exit;
}
+
+exit:
+ mbedtls_platform_zeroize( K, sizeof( K ) );
+ return( ret );
}
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx,
+ const unsigned char *additional,
+ size_t add_len )
+{
+ (void) mbedtls_hmac_drbg_update_ret( ctx, additional, add_len );
+}
+#endif /* MBEDTLS_DEPRECATED_REMOVED */
+
/*
* Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
*/
@@ -108,10 +137,13 @@ int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
* Use the V memory location, which is currently all 0, to initialize the
* MD context with an all-zero key. Then set V to its initial value.
*/
- mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, mbedtls_md_get_size( md_info ) );
+ if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V,
+ mbedtls_md_get_size( md_info ) ) ) != 0 )
+ return( ret );
memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) );
- mbedtls_hmac_drbg_update( ctx, data, data_len );
+ if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, data, data_len ) ) != 0 )
+ return( ret );
return( 0 );
}
@@ -124,6 +156,7 @@ int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
{
unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
size_t seedlen;
+ int ret;
/* III. Check input length */
if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
@@ -135,7 +168,8 @@ int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT );
/* IV. Gather entropy_len bytes of entropy for the seed */
- if( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 )
+ if( ( ret = ctx->f_entropy( ctx->p_entropy,
+ seed, ctx->entropy_len ) ) != 0 )
return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
seedlen = ctx->entropy_len;
@@ -148,13 +182,16 @@ int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
}
/* 2. Update state */
- mbedtls_hmac_drbg_update( ctx, seed, seedlen );
+ if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, seed, seedlen ) ) != 0 )
+ goto exit;
/* 3. Reset reseed_counter */
ctx->reseed_counter = 1;
+exit:
/* 4. Done */
- return( 0 );
+ mbedtls_platform_zeroize( seed, seedlen );
+ return( ret );
}
/*
@@ -180,7 +217,8 @@ int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
* Use the V memory location, which is currently all 0, to initialize the
* MD context with an all-zero key. Then set V to its initial value.
*/
- mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size );
+ if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ) ) != 0 )
+ return( ret );
memset( ctx->V, 0x01, md_size );
ctx->f_entropy = f_entropy;
@@ -273,16 +311,24 @@ int mbedtls_hmac_drbg_random_with_add( void *p_rng,
/* 2. Use additional data if any */
if( additional != NULL && add_len != 0 )
- mbedtls_hmac_drbg_update( ctx, additional, add_len );
+ {
+ if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
+ additional, add_len ) ) != 0 )
+ goto exit;
+ }
/* 3, 4, 5. Generate bytes */
while( left != 0 )
{
size_t use_len = left > md_len ? md_len : left;
- mbedtls_md_hmac_reset( &ctx->md_ctx );
- mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
- mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V );
+ if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
+ goto exit;
+ if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
+ ctx->V, md_len ) ) != 0 )
+ goto exit;
+ if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
+ goto exit;
memcpy( out, ctx->V, use_len );
out += use_len;
@@ -290,13 +336,16 @@ int mbedtls_hmac_drbg_random_with_add( void *p_rng,
}
/* 6. Update */
- mbedtls_hmac_drbg_update( ctx, additional, add_len );
+ if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
+ additional, add_len ) ) != 0 )
+ goto exit;
/* 7. Update reseed counter */
ctx->reseed_counter++;
+exit:
/* 8. Done */
- return( 0 );
+ return( ret );
}
/*
@@ -368,35 +417,36 @@ exit:
int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
{
int ret = 0;
- FILE *f;
+ FILE *f = NULL;
size_t n;
unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
+ unsigned char c;
if( ( f = fopen( path, "rb" ) ) == NULL )
return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
- fseek( f, 0, SEEK_END );
- n = (size_t) ftell( f );
- fseek( f, 0, SEEK_SET );
-
- if( n > MBEDTLS_HMAC_DRBG_MAX_INPUT )
+ n = fread( buf, 1, sizeof( buf ), f );
+ if( fread( &c, 1, 1, f ) != 0 )
{
- fclose( f );
- return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
+ ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
+ goto exit;
}
-
- if( fread( buf, 1, n, f ) != n )
+ if( n == 0 || ferror( f ) )
+ {
ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
- else
- mbedtls_hmac_drbg_update( ctx, buf, n );
-
+ goto exit;
+ }
fclose( f );
+ f = NULL;
- mbedtls_platform_zeroize( buf, sizeof( buf ) );
+ ret = mbedtls_hmac_drbg_update_ret( ctx, buf, n );
+exit:
+ mbedtls_platform_zeroize( buf, sizeof( buf ) );
+ if( f != NULL )
+ fclose( f );
if( ret != 0 )
return( ret );
-
return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) );
}
#endif /* MBEDTLS_FS_IO */
diff --git a/thirdparty/mbedtls/library/nist_kw.c b/thirdparty/mbedtls/library/nist_kw.c
index 176af9fe08..317a2426ae 100644
--- a/thirdparty/mbedtls/library/nist_kw.c
+++ b/thirdparty/mbedtls/library/nist_kw.c
@@ -311,7 +311,7 @@ cleanup:
}
mbedtls_platform_zeroize( inbuff, KW_SEMIBLOCK_LENGTH * 2 );
mbedtls_platform_zeroize( outbuff, KW_SEMIBLOCK_LENGTH * 2 );
- mbedtls_cipher_finish( &ctx->cipher_ctx, NULL, &olen );
+
return( ret );
}
@@ -528,7 +528,7 @@ cleanup:
mbedtls_platform_zeroize( &bad_padding, sizeof( bad_padding) );
mbedtls_platform_zeroize( &diff, sizeof( diff ) );
mbedtls_platform_zeroize( A, sizeof( A ) );
- mbedtls_cipher_finish( &ctx->cipher_ctx, NULL, &olen );
+
return( ret );
}
diff --git a/thirdparty/mbedtls/library/pem.c b/thirdparty/mbedtls/library/pem.c
index 6069a23dec..897c8a0d6f 100644
--- a/thirdparty/mbedtls/library/pem.c
+++ b/thirdparty/mbedtls/library/pem.c
@@ -423,9 +423,11 @@ int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const
void mbedtls_pem_free( mbedtls_pem_context *ctx )
{
- if( ctx->buf != NULL )
+ if ( ctx->buf != NULL )
+ {
mbedtls_platform_zeroize( ctx->buf, ctx->buflen );
- mbedtls_free( ctx->buf );
+ mbedtls_free( ctx->buf );
+ }
mbedtls_free( ctx->info );
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pem_context ) );
diff --git a/thirdparty/mbedtls/library/pk.c b/thirdparty/mbedtls/library/pk.c
index f05b139e3f..bac685dc19 100644
--- a/thirdparty/mbedtls/library/pk.c
+++ b/thirdparty/mbedtls/library/pk.c
@@ -44,13 +44,18 @@
#include <limits.h>
#include <stdint.h>
+/* Parameter validation macros based on platform_util.h */
+#define PK_VALIDATE_RET( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA )
+#define PK_VALIDATE( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE( cond )
+
/*
* Initialise a mbedtls_pk_context
*/
void mbedtls_pk_init( mbedtls_pk_context *ctx )
{
- if( ctx == NULL )
- return;
+ PK_VALIDATE( ctx != NULL );
ctx->pk_info = NULL;
ctx->pk_ctx = NULL;
@@ -61,14 +66,44 @@ void mbedtls_pk_init( mbedtls_pk_context *ctx )
*/
void mbedtls_pk_free( mbedtls_pk_context *ctx )
{
- if( ctx == NULL || ctx->pk_info == NULL )
+ if( ctx == NULL )
return;
- ctx->pk_info->ctx_free_func( ctx->pk_ctx );
+ if ( ctx->pk_info != NULL )
+ ctx->pk_info->ctx_free_func( ctx->pk_ctx );
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pk_context ) );
}
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+/*
+ * Initialize a restart context
+ */
+void mbedtls_pk_restart_init( mbedtls_pk_restart_ctx *ctx )
+{
+ PK_VALIDATE( ctx != NULL );
+ ctx->pk_info = NULL;
+ ctx->rs_ctx = NULL;
+}
+
+/*
+ * Free the components of a restart context
+ */
+void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx )
+{
+ if( ctx == NULL || ctx->pk_info == NULL ||
+ ctx->pk_info->rs_free_func == NULL )
+ {
+ return;
+ }
+
+ ctx->pk_info->rs_free_func( ctx->rs_ctx );
+
+ ctx->pk_info = NULL;
+ ctx->rs_ctx = NULL;
+}
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+
/*
* Get pk_info structure from type
*/
@@ -100,7 +135,8 @@ const mbedtls_pk_info_t * mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type )
*/
int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info )
{
- if( ctx == NULL || info == NULL || ctx->pk_info != NULL )
+ PK_VALIDATE_RET( ctx != NULL );
+ if( info == NULL || ctx->pk_info != NULL )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL )
@@ -123,7 +159,8 @@ int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key,
mbedtls_rsa_alt_context *rsa_alt;
const mbedtls_pk_info_t *info = &mbedtls_rsa_alt_info;
- if( ctx == NULL || ctx->pk_info != NULL )
+ PK_VALIDATE_RET( ctx != NULL );
+ if( ctx->pk_info != NULL )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL )
@@ -147,7 +184,9 @@ int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key,
*/
int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type )
{
- /* null or NONE context can't do anything */
+ /* A context with null pk_info is not set up yet and can't do anything.
+ * For backward compatibility, also accept NULL instead of a context
+ * pointer. */
if( ctx == NULL || ctx->pk_info == NULL )
return( 0 );
@@ -171,17 +210,71 @@ static inline int pk_hashlen_helper( mbedtls_md_type_t md_alg, size_t *hash_len
return( 0 );
}
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
/*
- * Verify a signature
+ * Helper to set up a restart context if needed
*/
-int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
+static int pk_restart_setup( mbedtls_pk_restart_ctx *ctx,
+ const mbedtls_pk_info_t *info )
+{
+ /* Don't do anything if already set up or invalid */
+ if( ctx == NULL || ctx->pk_info != NULL )
+ return( 0 );
+
+ /* Should never happen when we're called */
+ if( info->rs_alloc_func == NULL || info->rs_free_func == NULL )
+ return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+
+ if( ( ctx->rs_ctx = info->rs_alloc_func() ) == NULL )
+ return( MBEDTLS_ERR_PK_ALLOC_FAILED );
+
+ ctx->pk_info = info;
+
+ return( 0 );
+}
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+
+/*
+ * Verify a signature (restartable)
+ */
+int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx,
+ mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
- const unsigned char *sig, size_t sig_len )
+ const unsigned char *sig, size_t sig_len,
+ mbedtls_pk_restart_ctx *rs_ctx )
{
- if( ctx == NULL || ctx->pk_info == NULL ||
+ PK_VALIDATE_RET( ctx != NULL );
+ PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) ||
+ hash != NULL );
+ PK_VALIDATE_RET( sig != NULL );
+
+ if( ctx->pk_info == NULL ||
pk_hashlen_helper( md_alg, &hash_len ) != 0 )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ /* optimization: use non-restartable version if restart disabled */
+ if( rs_ctx != NULL &&
+ mbedtls_ecp_restart_is_enabled() &&
+ ctx->pk_info->verify_rs_func != NULL )
+ {
+ int ret;
+
+ if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 )
+ return( ret );
+
+ ret = ctx->pk_info->verify_rs_func( ctx->pk_ctx,
+ md_alg, hash, hash_len, sig, sig_len, rs_ctx->rs_ctx );
+
+ if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
+ mbedtls_pk_restart_free( rs_ctx );
+
+ return( ret );
+ }
+#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+ (void) rs_ctx;
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+
if( ctx->pk_info->verify_func == NULL )
return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
@@ -190,6 +283,17 @@ int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
}
/*
+ * Verify a signature
+ */
+int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ const unsigned char *sig, size_t sig_len )
+{
+ return( mbedtls_pk_verify_restartable( ctx, md_alg, hash, hash_len,
+ sig, sig_len, NULL ) );
+}
+
+/*
* Verify a signature with options
*/
int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options,
@@ -197,7 +301,12 @@ int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options,
const unsigned char *hash, size_t hash_len,
const unsigned char *sig, size_t sig_len )
{
- if( ctx == NULL || ctx->pk_info == NULL )
+ PK_VALIDATE_RET( ctx != NULL );
+ PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) ||
+ hash != NULL );
+ PK_VALIDATE_RET( sig != NULL );
+
+ if( ctx->pk_info == NULL )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
if( ! mbedtls_pk_can_do( ctx, type ) )
@@ -248,17 +357,47 @@ int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options,
}
/*
- * Make a signature
+ * Make a signature (restartable)
*/
-int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
+int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx,
+ mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
unsigned char *sig, size_t *sig_len,
- int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+ mbedtls_pk_restart_ctx *rs_ctx )
{
- if( ctx == NULL || ctx->pk_info == NULL ||
+ PK_VALIDATE_RET( ctx != NULL );
+ PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) ||
+ hash != NULL );
+ PK_VALIDATE_RET( sig != NULL );
+
+ if( ctx->pk_info == NULL ||
pk_hashlen_helper( md_alg, &hash_len ) != 0 )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ /* optimization: use non-restartable version if restart disabled */
+ if( rs_ctx != NULL &&
+ mbedtls_ecp_restart_is_enabled() &&
+ ctx->pk_info->sign_rs_func != NULL )
+ {
+ int ret;
+
+ if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 )
+ return( ret );
+
+ ret = ctx->pk_info->sign_rs_func( ctx->pk_ctx, md_alg,
+ hash, hash_len, sig, sig_len, f_rng, p_rng, rs_ctx->rs_ctx );
+
+ if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
+ mbedtls_pk_restart_free( rs_ctx );
+
+ return( ret );
+ }
+#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+ (void) rs_ctx;
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+
if( ctx->pk_info->sign_func == NULL )
return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
@@ -267,6 +406,18 @@ int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
}
/*
+ * Make a signature
+ */
+int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ unsigned char *sig, size_t *sig_len,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+ return( mbedtls_pk_sign_restartable( ctx, md_alg, hash, hash_len,
+ sig, sig_len, f_rng, p_rng, NULL ) );
+}
+
+/*
* Decrypt message
*/
int mbedtls_pk_decrypt( mbedtls_pk_context *ctx,
@@ -274,7 +425,12 @@ int mbedtls_pk_decrypt( mbedtls_pk_context *ctx,
unsigned char *output, size_t *olen, size_t osize,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
{
- if( ctx == NULL || ctx->pk_info == NULL )
+ PK_VALIDATE_RET( ctx != NULL );
+ PK_VALIDATE_RET( input != NULL || ilen == 0 );
+ PK_VALIDATE_RET( output != NULL || osize == 0 );
+ PK_VALIDATE_RET( olen != NULL );
+
+ if( ctx->pk_info == NULL )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
if( ctx->pk_info->decrypt_func == NULL )
@@ -292,7 +448,12 @@ int mbedtls_pk_encrypt( mbedtls_pk_context *ctx,
unsigned char *output, size_t *olen, size_t osize,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
{
- if( ctx == NULL || ctx->pk_info == NULL )
+ PK_VALIDATE_RET( ctx != NULL );
+ PK_VALIDATE_RET( input != NULL || ilen == 0 );
+ PK_VALIDATE_RET( output != NULL || osize == 0 );
+ PK_VALIDATE_RET( olen != NULL );
+
+ if( ctx->pk_info == NULL )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
if( ctx->pk_info->encrypt_func == NULL )
@@ -307,8 +468,11 @@ int mbedtls_pk_encrypt( mbedtls_pk_context *ctx,
*/
int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_context *prv )
{
- if( pub == NULL || pub->pk_info == NULL ||
- prv == NULL || prv->pk_info == NULL ||
+ PK_VALIDATE_RET( pub != NULL );
+ PK_VALIDATE_RET( prv != NULL );
+
+ if( pub->pk_info == NULL ||
+ prv->pk_info == NULL ||
prv->pk_info->check_pair_func == NULL )
{
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
@@ -333,6 +497,8 @@ int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_conte
*/
size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx )
{
+ /* For backward compatibility, accept NULL or a context that
+ * isn't set up yet, and return a fake value that should be safe. */
if( ctx == NULL || ctx->pk_info == NULL )
return( 0 );
@@ -344,7 +510,8 @@ size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx )
*/
int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items )
{
- if( ctx == NULL || ctx->pk_info == NULL )
+ PK_VALIDATE_RET( ctx != NULL );
+ if( ctx->pk_info == NULL )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
if( ctx->pk_info->debug_func == NULL )
diff --git a/thirdparty/mbedtls/library/pk_wrap.c b/thirdparty/mbedtls/library/pk_wrap.c
index 2c7d2d79b8..87806be337 100644
--- a/thirdparty/mbedtls/library/pk_wrap.c
+++ b/thirdparty/mbedtls/library/pk_wrap.c
@@ -190,11 +190,19 @@ const mbedtls_pk_info_t mbedtls_rsa_info = {
rsa_can_do,
rsa_verify_wrap,
rsa_sign_wrap,
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ NULL,
+ NULL,
+#endif
rsa_decrypt_wrap,
rsa_encrypt_wrap,
rsa_check_pair_wrap,
rsa_alloc_wrap,
rsa_free_wrap,
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ NULL,
+ NULL,
+#endif
rsa_debug,
};
#endif /* MBEDTLS_RSA_C */
@@ -262,6 +270,110 @@ static int eckey_sign_wrap( void *ctx, mbedtls_md_type_t md_alg,
return( ret );
}
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+/* Forward declarations */
+static int ecdsa_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ const unsigned char *sig, size_t sig_len,
+ void *rs_ctx );
+
+static int ecdsa_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ unsigned char *sig, size_t *sig_len,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+ void *rs_ctx );
+
+/*
+ * Restart context for ECDSA operations with ECKEY context
+ *
+ * We need to store an actual ECDSA context, as we need to pass the same to
+ * the underlying ecdsa function, so we can't create it on the fly every time.
+ */
+typedef struct
+{
+ mbedtls_ecdsa_restart_ctx ecdsa_rs;
+ mbedtls_ecdsa_context ecdsa_ctx;
+} eckey_restart_ctx;
+
+static void *eckey_rs_alloc( void )
+{
+ eckey_restart_ctx *rs_ctx;
+
+ void *ctx = mbedtls_calloc( 1, sizeof( eckey_restart_ctx ) );
+
+ if( ctx != NULL )
+ {
+ rs_ctx = ctx;
+ mbedtls_ecdsa_restart_init( &rs_ctx->ecdsa_rs );
+ mbedtls_ecdsa_init( &rs_ctx->ecdsa_ctx );
+ }
+
+ return( ctx );
+}
+
+static void eckey_rs_free( void *ctx )
+{
+ eckey_restart_ctx *rs_ctx;
+
+ if( ctx == NULL)
+ return;
+
+ rs_ctx = ctx;
+ mbedtls_ecdsa_restart_free( &rs_ctx->ecdsa_rs );
+ mbedtls_ecdsa_free( &rs_ctx->ecdsa_ctx );
+
+ mbedtls_free( ctx );
+}
+
+static int eckey_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ const unsigned char *sig, size_t sig_len,
+ void *rs_ctx )
+{
+ int ret;
+ eckey_restart_ctx *rs = rs_ctx;
+
+ /* Should never happen */
+ if( rs == NULL )
+ return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+
+ /* set up our own sub-context if needed (that is, on first run) */
+ if( rs->ecdsa_ctx.grp.pbits == 0 )
+ MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( &rs->ecdsa_ctx, ctx ) );
+
+ MBEDTLS_MPI_CHK( ecdsa_verify_rs_wrap( &rs->ecdsa_ctx,
+ md_alg, hash, hash_len,
+ sig, sig_len, &rs->ecdsa_rs ) );
+
+cleanup:
+ return( ret );
+}
+
+static int eckey_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ unsigned char *sig, size_t *sig_len,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+ void *rs_ctx )
+{
+ int ret;
+ eckey_restart_ctx *rs = rs_ctx;
+
+ /* Should never happen */
+ if( rs == NULL )
+ return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+
+ /* set up our own sub-context if needed (that is, on first run) */
+ if( rs->ecdsa_ctx.grp.pbits == 0 )
+ MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( &rs->ecdsa_ctx, ctx ) );
+
+ MBEDTLS_MPI_CHK( ecdsa_sign_rs_wrap( &rs->ecdsa_ctx, md_alg,
+ hash, hash_len, sig, sig_len,
+ f_rng, p_rng, &rs->ecdsa_rs ) );
+
+cleanup:
+ return( ret );
+}
+#endif /* MBEDTLS_ECP_RESTARTABLE */
#endif /* MBEDTLS_ECDSA_C */
static int eckey_check_pair( const void *pub, const void *prv )
@@ -301,15 +413,23 @@ const mbedtls_pk_info_t mbedtls_eckey_info = {
#if defined(MBEDTLS_ECDSA_C)
eckey_verify_wrap,
eckey_sign_wrap,
-#else
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ eckey_verify_rs_wrap,
+ eckey_sign_rs_wrap,
+#endif
+#else /* MBEDTLS_ECDSA_C */
NULL,
NULL,
-#endif
+#endif /* MBEDTLS_ECDSA_C */
NULL,
NULL,
eckey_check_pair,
eckey_alloc_wrap,
eckey_free_wrap,
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ eckey_rs_alloc,
+ eckey_rs_free,
+#endif
eckey_debug,
};
@@ -329,11 +449,19 @@ const mbedtls_pk_info_t mbedtls_eckeydh_info = {
eckeydh_can_do,
NULL,
NULL,
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ NULL,
+ NULL,
+#endif
NULL,
NULL,
eckey_check_pair,
eckey_alloc_wrap, /* Same underlying key structure */
eckey_free_wrap, /* Same underlying key structure */
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ NULL,
+ NULL,
+#endif
eckey_debug, /* Same underlying key structure */
};
#endif /* MBEDTLS_ECP_C */
@@ -369,6 +497,40 @@ static int ecdsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg,
md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng ) );
}
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+static int ecdsa_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ const unsigned char *sig, size_t sig_len,
+ void *rs_ctx )
+{
+ int ret;
+ ((void) md_alg);
+
+ ret = mbedtls_ecdsa_read_signature_restartable(
+ (mbedtls_ecdsa_context *) ctx,
+ hash, hash_len, sig, sig_len,
+ (mbedtls_ecdsa_restart_ctx *) rs_ctx );
+
+ if( ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH )
+ return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH );
+
+ return( ret );
+}
+
+static int ecdsa_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ unsigned char *sig, size_t *sig_len,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+ void *rs_ctx )
+{
+ return( mbedtls_ecdsa_write_signature_restartable(
+ (mbedtls_ecdsa_context *) ctx,
+ md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng,
+ (mbedtls_ecdsa_restart_ctx *) rs_ctx ) );
+
+}
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
static void *ecdsa_alloc_wrap( void )
{
void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_context ) );
@@ -385,6 +547,24 @@ static void ecdsa_free_wrap( void *ctx )
mbedtls_free( ctx );
}
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+static void *ecdsa_rs_alloc( void )
+{
+ void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_restart_ctx ) );
+
+ if( ctx != NULL )
+ mbedtls_ecdsa_restart_init( ctx );
+
+ return( ctx );
+}
+
+static void ecdsa_rs_free( void *ctx )
+{
+ mbedtls_ecdsa_restart_free( ctx );
+ mbedtls_free( ctx );
+}
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
const mbedtls_pk_info_t mbedtls_ecdsa_info = {
MBEDTLS_PK_ECDSA,
"ECDSA",
@@ -392,11 +572,19 @@ const mbedtls_pk_info_t mbedtls_ecdsa_info = {
ecdsa_can_do,
ecdsa_verify_wrap,
ecdsa_sign_wrap,
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ ecdsa_verify_rs_wrap,
+ ecdsa_sign_rs_wrap,
+#endif
NULL,
NULL,
eckey_check_pair, /* Compatible key structures */
ecdsa_alloc_wrap,
ecdsa_free_wrap,
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ ecdsa_rs_alloc,
+ ecdsa_rs_free,
+#endif
eckey_debug, /* Compatible key structures */
};
#endif /* MBEDTLS_ECDSA_C */
@@ -506,6 +694,10 @@ const mbedtls_pk_info_t mbedtls_rsa_alt_info = {
rsa_alt_can_do,
NULL,
rsa_alt_sign_wrap,
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ NULL,
+ NULL,
+#endif
rsa_alt_decrypt_wrap,
NULL,
#if defined(MBEDTLS_RSA_C)
@@ -515,6 +707,10 @@ const mbedtls_pk_info_t mbedtls_rsa_alt_info = {
#endif
rsa_alt_alloc_wrap,
rsa_alt_free_wrap,
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ NULL,
+ NULL,
+#endif
NULL,
};
diff --git a/thirdparty/mbedtls/library/pkcs12.c b/thirdparty/mbedtls/library/pkcs12.c
index 16a15cb63e..7edf064c13 100644
--- a/thirdparty/mbedtls/library/pkcs12.c
+++ b/thirdparty/mbedtls/library/pkcs12.c
@@ -48,6 +48,8 @@
#include "mbedtls/des.h"
#endif
+#if defined(MBEDTLS_ASN1_PARSE_C)
+
static int pkcs12_parse_pbe_params( mbedtls_asn1_buf *params,
mbedtls_asn1_buf *salt, int *iterations )
{
@@ -226,6 +228,8 @@ exit:
return( ret );
}
+#endif /* MBEDTLS_ASN1_PARSE_C */
+
static void pkcs12_fill_buffer( unsigned char *data, size_t data_len,
const unsigned char *filler, size_t fill_len )
{
diff --git a/thirdparty/mbedtls/library/pkcs5.c b/thirdparty/mbedtls/library/pkcs5.c
index f04f0ab25e..50133435ce 100644
--- a/thirdparty/mbedtls/library/pkcs5.c
+++ b/thirdparty/mbedtls/library/pkcs5.c
@@ -54,22 +54,7 @@
#define mbedtls_printf printf
#endif
-#if !defined(MBEDTLS_ASN1_PARSE_C)
-int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode,
- const unsigned char *pwd, size_t pwdlen,
- const unsigned char *data, size_t datalen,
- unsigned char *output )
-{
- ((void) pbe_params);
- ((void) mode);
- ((void) pwd);
- ((void) pwdlen);
- ((void) data);
- ((void) datalen);
- ((void) output);
- return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE );
-}
-#else
+#if defined(MBEDTLS_ASN1_PARSE_C)
static int pkcs5_parse_pbkdf2_params( const mbedtls_asn1_buf *params,
mbedtls_asn1_buf *salt, int *iterations,
int *keylen, mbedtls_md_type_t *md_type )
diff --git a/thirdparty/mbedtls/library/pkparse.c b/thirdparty/mbedtls/library/pkparse.c
index d6ac987e23..ae210bca6a 100644
--- a/thirdparty/mbedtls/library/pkparse.c
+++ b/thirdparty/mbedtls/library/pkparse.c
@@ -61,6 +61,12 @@
#define mbedtls_free free
#endif
+/* Parameter validation macros based on platform_util.h */
+#define PK_VALIDATE_RET( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA )
+#define PK_VALIDATE( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE( cond )
+
#if defined(MBEDTLS_FS_IO)
/*
* Load all data from a file into a given buffer.
@@ -74,6 +80,10 @@ int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n )
FILE *f;
long size;
+ PK_VALIDATE_RET( path != NULL );
+ PK_VALIDATE_RET( buf != NULL );
+ PK_VALIDATE_RET( n != NULL );
+
if( ( f = fopen( path, "rb" ) ) == NULL )
return( MBEDTLS_ERR_PK_FILE_IO_ERROR );
@@ -124,6 +134,9 @@ int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx,
size_t n;
unsigned char *buf;
+ PK_VALIDATE_RET( ctx != NULL );
+ PK_VALIDATE_RET( path != NULL );
+
if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 )
return( ret );
@@ -148,6 +161,9 @@ int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path )
size_t n;
unsigned char *buf;
+ PK_VALIDATE_RET( ctx != NULL );
+ PK_VALIDATE_RET( path != NULL );
+
if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 )
return( ret );
@@ -605,6 +621,11 @@ int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end,
mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;
const mbedtls_pk_info_t *pk_info;
+ PK_VALIDATE_RET( p != NULL );
+ PK_VALIDATE_RET( *p != NULL );
+ PK_VALIDATE_RET( end != NULL );
+ PK_VALIDATE_RET( pk != NULL );
+
if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
{
@@ -1145,16 +1166,22 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk,
{
int ret;
const mbedtls_pk_info_t *pk_info;
-
#if defined(MBEDTLS_PEM_PARSE_C)
size_t len;
mbedtls_pem_context pem;
+#endif
- mbedtls_pem_init( &pem );
+ PK_VALIDATE_RET( pk != NULL );
+ if( keylen == 0 )
+ return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
+ PK_VALIDATE_RET( key != NULL );
+
+#if defined(MBEDTLS_PEM_PARSE_C)
+ mbedtls_pem_init( &pem );
#if defined(MBEDTLS_RSA_C)
/* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
- if( keylen == 0 || key[keylen - 1] != '\0' )
+ if( key[keylen - 1] != '\0' )
ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
else
ret = mbedtls_pem_read_buffer( &pem,
@@ -1185,7 +1212,7 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk,
#if defined(MBEDTLS_ECP_C)
/* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
- if( keylen == 0 || key[keylen - 1] != '\0' )
+ if( key[keylen - 1] != '\0' )
ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
else
ret = mbedtls_pem_read_buffer( &pem,
@@ -1215,7 +1242,7 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk,
#endif /* MBEDTLS_ECP_C */
/* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
- if( keylen == 0 || key[keylen - 1] != '\0' )
+ if( key[keylen - 1] != '\0' )
ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
else
ret = mbedtls_pem_read_buffer( &pem,
@@ -1238,7 +1265,7 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk,
#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
/* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
- if( keylen == 0 || key[keylen - 1] != '\0' )
+ if( key[keylen - 1] != '\0' )
ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
else
ret = mbedtls_pem_read_buffer( &pem,
@@ -1276,9 +1303,6 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk,
{
unsigned char *key_copy;
- if( keylen == 0 )
- return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
-
if( ( key_copy = mbedtls_calloc( 1, keylen ) ) == NULL )
return( MBEDTLS_ERR_PK_ALLOC_FAILED );
@@ -1295,6 +1319,7 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk,
return( 0 );
mbedtls_pk_free( pk );
+ mbedtls_pk_init( pk );
if( ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH )
{
@@ -1306,39 +1331,42 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk,
return( 0 );
mbedtls_pk_free( pk );
+ mbedtls_pk_init( pk );
#if defined(MBEDTLS_RSA_C)
pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA );
- if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ||
- ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ),
- key, keylen ) ) != 0 )
- {
- mbedtls_pk_free( pk );
- }
- else
+ if( mbedtls_pk_setup( pk, pk_info ) == 0 &&
+ pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), key, keylen ) == 0 )
{
return( 0 );
}
+ mbedtls_pk_free( pk );
+ mbedtls_pk_init( pk );
#endif /* MBEDTLS_RSA_C */
#if defined(MBEDTLS_ECP_C)
-
pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY );
- if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ||
- ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ),
- key, keylen ) ) != 0 )
- {
- mbedtls_pk_free( pk );
- }
- else
+ if( mbedtls_pk_setup( pk, pk_info ) == 0 &&
+ pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ),
+ key, keylen ) == 0 )
{
return( 0 );
}
-
+ mbedtls_pk_free( pk );
#endif /* MBEDTLS_ECP_C */
+ /* If MBEDTLS_RSA_C is defined but MBEDTLS_ECP_C isn't,
+ * it is ok to leave the PK context initialized but not
+ * freed: It is the caller's responsibility to call pk_init()
+ * before calling this function, and to call pk_free()
+ * when it fails. If MBEDTLS_ECP_C is defined but MBEDTLS_RSA_C
+ * isn't, this leads to mbedtls_pk_free() being called
+ * twice, once here and once by the caller, but this is
+ * also ok and in line with the mbedtls_pk_free() calls
+ * on failed PEM parsing attempts. */
+
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
}
@@ -1356,11 +1384,18 @@ int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx,
#if defined(MBEDTLS_PEM_PARSE_C)
size_t len;
mbedtls_pem_context pem;
+#endif
+ PK_VALIDATE_RET( ctx != NULL );
+ if( keylen == 0 )
+ return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
+ PK_VALIDATE_RET( key != NULL || keylen == 0 );
+
+#if defined(MBEDTLS_PEM_PARSE_C)
mbedtls_pem_init( &pem );
#if defined(MBEDTLS_RSA_C)
/* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
- if( keylen == 0 || key[keylen - 1] != '\0' )
+ if( key[keylen - 1] != '\0' )
ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
else
ret = mbedtls_pem_read_buffer( &pem,
@@ -1391,7 +1426,7 @@ int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx,
#endif /* MBEDTLS_RSA_C */
/* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
- if( keylen == 0 || key[keylen - 1] != '\0' )
+ if( key[keylen - 1] != '\0' )
ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
else
ret = mbedtls_pem_read_buffer( &pem,
diff --git a/thirdparty/mbedtls/library/pkwrite.c b/thirdparty/mbedtls/library/pkwrite.c
index 8eabd889b5..8d1da2f757 100644
--- a/thirdparty/mbedtls/library/pkwrite.c
+++ b/thirdparty/mbedtls/library/pkwrite.c
@@ -30,6 +30,7 @@
#include "mbedtls/pk.h"
#include "mbedtls/asn1write.h"
#include "mbedtls/oid.h"
+#include "mbedtls/platform_util.h"
#include <string.h>
@@ -54,6 +55,12 @@
#define mbedtls_free free
#endif
+/* Parameter validation macros based on platform_util.h */
+#define PK_VALIDATE_RET( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA )
+#define PK_VALIDATE( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE( cond )
+
#if defined(MBEDTLS_RSA_C)
/*
* RSAPublicKey ::= SEQUENCE {
@@ -151,6 +158,11 @@ int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start,
int ret;
size_t len = 0;
+ PK_VALIDATE_RET( p != NULL );
+ PK_VALIDATE_RET( *p != NULL );
+ PK_VALIDATE_RET( start != NULL );
+ PK_VALIDATE_RET( key != NULL );
+
#if defined(MBEDTLS_RSA_C)
if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA )
MBEDTLS_ASN1_CHK_ADD( len, pk_write_rsa_pubkey( p, start, mbedtls_pk_rsa( *key ) ) );
@@ -173,6 +185,11 @@ int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *key, unsigned char *buf, si
size_t len = 0, par_len = 0, oid_len;
const char *oid;
+ PK_VALIDATE_RET( key != NULL );
+ if( size == 0 )
+ return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+ PK_VALIDATE_RET( buf != NULL );
+
c = buf + size;
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, key ) );
@@ -217,9 +234,16 @@ int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *key, unsigned char *buf, si
int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_t size )
{
int ret;
- unsigned char *c = buf + size;
+ unsigned char *c;
size_t len = 0;
+ PK_VALIDATE_RET( key != NULL );
+ if( size == 0 )
+ return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+ PK_VALIDATE_RET( buf != NULL );
+
+ c = buf + size;
+
#if defined(MBEDTLS_RSA_C)
if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA )
{
@@ -457,6 +481,9 @@ int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *key, unsigned char *buf, si
unsigned char output_buf[PUB_DER_MAX_BYTES];
size_t olen = 0;
+ PK_VALIDATE_RET( key != NULL );
+ PK_VALIDATE_RET( buf != NULL || size == 0 );
+
if( ( ret = mbedtls_pk_write_pubkey_der( key, output_buf,
sizeof(output_buf) ) ) < 0 )
{
@@ -480,6 +507,9 @@ int mbedtls_pk_write_key_pem( mbedtls_pk_context *key, unsigned char *buf, size_
const char *begin, *end;
size_t olen = 0;
+ PK_VALIDATE_RET( key != NULL );
+ PK_VALIDATE_RET( buf != NULL || size == 0 );
+
if( ( ret = mbedtls_pk_write_key_der( key, output_buf, sizeof(output_buf) ) ) < 0 )
return( ret );
diff --git a/thirdparty/mbedtls/library/platform.c b/thirdparty/mbedtls/library/platform.c
index b24b2fa652..73a6db9ebe 100644
--- a/thirdparty/mbedtls/library/platform.c
+++ b/thirdparty/mbedtls/library/platform.c
@@ -30,7 +30,14 @@
#include "mbedtls/platform.h"
#include "mbedtls/platform_util.h"
-#if defined(MBEDTLS_PLATFORM_MEMORY)
+/* The compile time configuration of memory allocation via the macros
+ * MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO takes precedence over the runtime
+ * configuration via mbedtls_platform_set_calloc_free(). So, omit everything
+ * related to the latter if MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO are defined. */
+#if defined(MBEDTLS_PLATFORM_MEMORY) && \
+ !( defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && \
+ defined(MBEDTLS_PLATFORM_FREE_MACRO) )
+
#if !defined(MBEDTLS_PLATFORM_STD_CALLOC)
static void *platform_calloc_uninit( size_t n, size_t size )
{
@@ -71,7 +78,9 @@ int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ),
mbedtls_free_func = free_func;
return( 0 );
}
-#endif /* MBEDTLS_PLATFORM_MEMORY */
+#endif /* MBEDTLS_PLATFORM_MEMORY &&
+ !( defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&
+ defined(MBEDTLS_PLATFORM_FREE_MACRO) ) */
#if defined(_WIN32)
#include <stdarg.h>
diff --git a/thirdparty/mbedtls/library/platform_util.c b/thirdparty/mbedtls/library/platform_util.c
index 1a57de9393..756e22679a 100644
--- a/thirdparty/mbedtls/library/platform_util.c
+++ b/thirdparty/mbedtls/library/platform_util.c
@@ -20,6 +20,14 @@
* This file is part of Mbed TLS (https://tls.mbed.org)
*/
+/*
+ * Ensure gmtime_r is available even with -std=c99; must be defined before
+ * config.h, which pulls in glibc's features.h. Harmless on other platforms.
+ */
+#if !defined(_POSIX_C_SOURCE)
+#define _POSIX_C_SOURCE 200112L
+#endif
+
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
@@ -27,6 +35,8 @@
#endif
#include "mbedtls/platform_util.h"
+#include "mbedtls/platform.h"
+#include "mbedtls/threading.h"
#include <stddef.h>
#include <string.h>
@@ -65,3 +75,62 @@ void mbedtls_platform_zeroize( void *buf, size_t len )
memset_func( buf, 0, len );
}
#endif /* MBEDTLS_PLATFORM_ZEROIZE_ALT */
+
+#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT)
+#include <time.h>
+#if !defined(_WIN32) && (defined(unix) || \
+ defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \
+ defined(__MACH__)))
+#include <unistd.h>
+#endif /* !_WIN32 && (unix || __unix || __unix__ ||
+ * (__APPLE__ && __MACH__)) */
+
+#if !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \
+ ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \
+ _POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) )
+/*
+ * This is a convenience shorthand macro to avoid checking the long
+ * preprocessor conditions above. Ideally, we could expose this macro in
+ * platform_util.h and simply use it in platform_util.c, threading.c and
+ * threading.h. However, this macro is not part of the Mbed TLS public API, so
+ * we keep it private by only defining it in this file
+ */
+#if ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) )
+#define PLATFORM_UTIL_USE_GMTIME
+#endif /* ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) */
+
+#endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \
+ ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \
+ _POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) ) */
+
+struct tm *mbedtls_platform_gmtime_r( const mbedtls_time_t *tt,
+ struct tm *tm_buf )
+{
+#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
+ return( ( gmtime_s( tm_buf, tt ) == 0 ) ? tm_buf : NULL );
+#elif !defined(PLATFORM_UTIL_USE_GMTIME)
+ return( gmtime_r( tt, tm_buf ) );
+#else
+ struct tm *lt;
+
+#if defined(MBEDTLS_THREADING_C)
+ if( mbedtls_mutex_lock( &mbedtls_threading_gmtime_mutex ) != 0 )
+ return( NULL );
+#endif /* MBEDTLS_THREADING_C */
+
+ lt = gmtime( tt );
+
+ if( lt != NULL )
+ {
+ memcpy( tm_buf, lt, sizeof( struct tm ) );
+ }
+
+#if defined(MBEDTLS_THREADING_C)
+ if( mbedtls_mutex_unlock( &mbedtls_threading_gmtime_mutex ) != 0 )
+ return( NULL );
+#endif /* MBEDTLS_THREADING_C */
+
+ return( ( lt == NULL ) ? NULL : tm_buf );
+#endif /* _WIN32 && !EFIX64 && !EFI32 */
+}
+#endif /* MBEDTLS_HAVE_TIME_DATE && MBEDTLS_PLATFORM_GMTIME_R_ALT */
diff --git a/thirdparty/mbedtls/library/poly1305.c b/thirdparty/mbedtls/library/poly1305.c
index e22d3afb68..b274119181 100644
--- a/thirdparty/mbedtls/library/poly1305.c
+++ b/thirdparty/mbedtls/library/poly1305.c
@@ -49,6 +49,12 @@
#define inline __inline
#endif
+/* Parameter validation macros */
+#define POLY1305_VALIDATE_RET( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA )
+#define POLY1305_VALIDATE( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE( cond )
+
#define POLY1305_BLOCK_SIZE_BYTES ( 16U )
#define BYTES_TO_U32_LE( data, offset ) \
@@ -276,27 +282,24 @@ static void poly1305_compute_mac( const mbedtls_poly1305_context *ctx,
void mbedtls_poly1305_init( mbedtls_poly1305_context *ctx )
{
- if( ctx != NULL )
- {
- mbedtls_platform_zeroize( ctx, sizeof( mbedtls_poly1305_context ) );
- }
+ POLY1305_VALIDATE( ctx != NULL );
+
+ mbedtls_platform_zeroize( ctx, sizeof( mbedtls_poly1305_context ) );
}
void mbedtls_poly1305_free( mbedtls_poly1305_context *ctx )
{
- if( ctx != NULL )
- {
- mbedtls_platform_zeroize( ctx, sizeof( mbedtls_poly1305_context ) );
- }
+ if( ctx == NULL )
+ return;
+
+ mbedtls_platform_zeroize( ctx, sizeof( mbedtls_poly1305_context ) );
}
int mbedtls_poly1305_starts( mbedtls_poly1305_context *ctx,
const unsigned char key[32] )
{
- if( ctx == NULL || key == NULL )
- {
- return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
- }
+ POLY1305_VALIDATE_RET( ctx != NULL );
+ POLY1305_VALIDATE_RET( key != NULL );
/* r &= 0x0ffffffc0ffffffc0ffffffc0fffffff */
ctx->r[0] = BYTES_TO_U32_LE( key, 0 ) & 0x0FFFFFFFU;
@@ -331,16 +334,8 @@ int mbedtls_poly1305_update( mbedtls_poly1305_context *ctx,
size_t remaining = ilen;
size_t queue_free_len;
size_t nblocks;
-
- if( ctx == NULL )
- {
- return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
- }
- else if( ( ilen > 0U ) && ( input == NULL ) )
- {
- /* input pointer is allowed to be NULL only if ilen == 0 */
- return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
- }
+ POLY1305_VALIDATE_RET( ctx != NULL );
+ POLY1305_VALIDATE_RET( ilen == 0 || input != NULL );
if( ( remaining > 0U ) && ( ctx->queue_len > 0U ) )
{
@@ -398,10 +393,8 @@ int mbedtls_poly1305_update( mbedtls_poly1305_context *ctx,
int mbedtls_poly1305_finish( mbedtls_poly1305_context *ctx,
unsigned char mac[16] )
{
- if( ( ctx == NULL ) || ( mac == NULL ) )
- {
- return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
- }
+ POLY1305_VALIDATE_RET( ctx != NULL );
+ POLY1305_VALIDATE_RET( mac != NULL );
/* Process any leftover data */
if( ctx->queue_len > 0U )
@@ -431,6 +424,9 @@ int mbedtls_poly1305_mac( const unsigned char key[32],
{
mbedtls_poly1305_context ctx;
int ret;
+ POLY1305_VALIDATE_RET( key != NULL );
+ POLY1305_VALIDATE_RET( mac != NULL );
+ POLY1305_VALIDATE_RET( ilen == 0 || input != NULL );
mbedtls_poly1305_init( &ctx );
diff --git a/thirdparty/mbedtls/library/rsa.c b/thirdparty/mbedtls/library/rsa.c
index 88c1cf1007..af1a878599 100644
--- a/thirdparty/mbedtls/library/rsa.c
+++ b/thirdparty/mbedtls/library/rsa.c
@@ -71,6 +71,12 @@
#if !defined(MBEDTLS_RSA_ALT)
+/* Parameter validation macros */
+#define RSA_VALIDATE_RET( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_RSA_BAD_INPUT_DATA )
+#define RSA_VALIDATE( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE( cond )
+
#if defined(MBEDTLS_PKCS1_V15)
/* constant-time buffer comparison */
static inline int mbedtls_safer_memcmp( const void *a, const void *b, size_t n )
@@ -93,6 +99,7 @@ int mbedtls_rsa_import( mbedtls_rsa_context *ctx,
const mbedtls_mpi *D, const mbedtls_mpi *E )
{
int ret;
+ RSA_VALIDATE_RET( ctx != NULL );
if( ( N != NULL && ( ret = mbedtls_mpi_copy( &ctx->N, N ) ) != 0 ) ||
( P != NULL && ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ) ||
@@ -117,6 +124,7 @@ int mbedtls_rsa_import_raw( mbedtls_rsa_context *ctx,
unsigned char const *E, size_t E_len )
{
int ret = 0;
+ RSA_VALIDATE_RET( ctx != NULL );
if( N != NULL )
{
@@ -240,12 +248,16 @@ static int rsa_check_context( mbedtls_rsa_context const *ctx, int is_priv,
int mbedtls_rsa_complete( mbedtls_rsa_context *ctx )
{
int ret = 0;
+ int have_N, have_P, have_Q, have_D, have_E;
+ int n_missing, pq_missing, d_missing, is_pub, is_priv;
+
+ RSA_VALIDATE_RET( ctx != NULL );
- const int have_N = ( mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 );
- const int have_P = ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 );
- const int have_Q = ( mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 );
- const int have_D = ( mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 );
- const int have_E = ( mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0 );
+ have_N = ( mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 );
+ have_P = ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 );
+ have_Q = ( mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 );
+ have_D = ( mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 );
+ have_E = ( mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0 );
/*
* Check whether provided parameters are enough
@@ -257,13 +269,13 @@ int mbedtls_rsa_complete( mbedtls_rsa_context *ctx )
*
*/
- const int n_missing = have_P && have_Q && have_D && have_E;
- const int pq_missing = have_N && !have_P && !have_Q && have_D && have_E;
- const int d_missing = have_P && have_Q && !have_D && have_E;
- const int is_pub = have_N && !have_P && !have_Q && !have_D && have_E;
+ n_missing = have_P && have_Q && have_D && have_E;
+ pq_missing = have_N && !have_P && !have_Q && have_D && have_E;
+ d_missing = have_P && have_Q && !have_D && have_E;
+ is_pub = have_N && !have_P && !have_Q && !have_D && have_E;
/* These three alternatives are mutually exclusive */
- const int is_priv = n_missing || pq_missing || d_missing;
+ is_priv = n_missing || pq_missing || d_missing;
if( !is_priv && !is_pub )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
@@ -336,9 +348,11 @@ int mbedtls_rsa_export_raw( const mbedtls_rsa_context *ctx,
unsigned char *E, size_t E_len )
{
int ret = 0;
+ int is_priv;
+ RSA_VALIDATE_RET( ctx != NULL );
/* Check if key is private or public */
- const int is_priv =
+ is_priv =
mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 &&
mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 &&
mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 &&
@@ -379,9 +393,11 @@ int mbedtls_rsa_export( const mbedtls_rsa_context *ctx,
mbedtls_mpi *D, mbedtls_mpi *E )
{
int ret;
+ int is_priv;
+ RSA_VALIDATE_RET( ctx != NULL );
/* Check if key is private or public */
- int is_priv =
+ is_priv =
mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 &&
mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 &&
mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 &&
@@ -421,9 +437,11 @@ int mbedtls_rsa_export_crt( const mbedtls_rsa_context *ctx,
mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP )
{
int ret;
+ int is_priv;
+ RSA_VALIDATE_RET( ctx != NULL );
/* Check if key is private or public */
- int is_priv =
+ is_priv =
mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 &&
mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 &&
mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 &&
@@ -459,6 +477,10 @@ void mbedtls_rsa_init( mbedtls_rsa_context *ctx,
int padding,
int hash_id )
{
+ RSA_VALIDATE( ctx != NULL );
+ RSA_VALIDATE( padding == MBEDTLS_RSA_PKCS_V15 ||
+ padding == MBEDTLS_RSA_PKCS_V21 );
+
memset( ctx, 0, sizeof( mbedtls_rsa_context ) );
mbedtls_rsa_set_padding( ctx, padding, hash_id );
@@ -471,8 +493,13 @@ void mbedtls_rsa_init( mbedtls_rsa_context *ctx,
/*
* Set padding for an existing RSA context
*/
-void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, int hash_id )
+void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding,
+ int hash_id )
{
+ RSA_VALIDATE( ctx != NULL );
+ RSA_VALIDATE( padding == MBEDTLS_RSA_PKCS_V15 ||
+ padding == MBEDTLS_RSA_PKCS_V21 );
+
ctx->padding = padding;
ctx->hash_id = hash_id;
}
@@ -502,12 +529,20 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx,
{
int ret;
mbedtls_mpi H, G, L;
+ int prime_quality = 0;
+ RSA_VALIDATE_RET( ctx != NULL );
+ RSA_VALIDATE_RET( f_rng != NULL );
- if( f_rng == NULL || nbits < 128 || exponent < 3 )
+ if( nbits < 128 || exponent < 3 || nbits % 2 != 0 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
- if( nbits % 2 )
- return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+ /*
+ * If the modulus is 1024 bit long or shorter, then the security strength of
+ * the RSA algorithm is less than or equal to 80 bits and therefore an error
+ * rate of 2^-80 is sufficient.
+ */
+ if( nbits > 1024 )
+ prime_quality = MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR;
mbedtls_mpi_init( &H );
mbedtls_mpi_init( &G );
@@ -523,11 +558,11 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx,
do
{
- MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->P, nbits >> 1, 0,
- f_rng, p_rng ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->P, nbits >> 1,
+ prime_quality, f_rng, p_rng ) );
- MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->Q, nbits >> 1, 0,
- f_rng, p_rng ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->Q, nbits >> 1,
+ prime_quality, f_rng, p_rng ) );
/* make sure the difference between p and q is not too small (FIPS 186-4 §B.3.3 step 5.4) */
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &H, &ctx->P, &ctx->Q ) );
@@ -603,6 +638,8 @@ cleanup:
*/
int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx )
{
+ RSA_VALIDATE_RET( ctx != NULL );
+
if( rsa_check_context( ctx, 0 /* public */, 0 /* no blinding */ ) != 0 )
return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
@@ -626,6 +663,8 @@ int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx )
*/
int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx )
{
+ RSA_VALIDATE_RET( ctx != NULL );
+
if( mbedtls_rsa_check_pubkey( ctx ) != 0 ||
rsa_check_context( ctx, 1 /* private */, 1 /* blinding */ ) != 0 )
{
@@ -655,6 +694,9 @@ int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx )
int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub,
const mbedtls_rsa_context *prv )
{
+ RSA_VALIDATE_RET( pub != NULL );
+ RSA_VALIDATE_RET( prv != NULL );
+
if( mbedtls_rsa_check_pubkey( pub ) != 0 ||
mbedtls_rsa_check_privkey( prv ) != 0 )
{
@@ -680,6 +722,9 @@ int mbedtls_rsa_public( mbedtls_rsa_context *ctx,
int ret;
size_t olen;
mbedtls_mpi T;
+ RSA_VALIDATE_RET( ctx != NULL );
+ RSA_VALIDATE_RET( input != NULL );
+ RSA_VALIDATE_RET( output != NULL );
if( rsa_check_context( ctx, 0 /* public */, 0 /* no blinding */ ) )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
@@ -822,6 +867,10 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx,
* checked result; should be the same in the end. */
mbedtls_mpi I, C;
+ RSA_VALIDATE_RET( ctx != NULL );
+ RSA_VALIDATE_RET( input != NULL );
+ RSA_VALIDATE_RET( output != NULL );
+
if( rsa_check_context( ctx, 1 /* private key checks */,
f_rng != NULL /* blinding y/n */ ) != 0 )
{
@@ -1082,6 +1131,13 @@ int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx,
const mbedtls_md_info_t *md_info;
mbedtls_md_context_t md_ctx;
+ RSA_VALIDATE_RET( ctx != NULL );
+ RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
+ mode == MBEDTLS_RSA_PUBLIC );
+ RSA_VALIDATE_RET( output != NULL );
+ RSA_VALIDATE_RET( input != NULL );
+ RSA_VALIDATE_RET( label_len == 0 || label != NULL );
+
if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
@@ -1158,11 +1214,13 @@ int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx,
int ret;
unsigned char *p = output;
- if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 )
- return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+ RSA_VALIDATE_RET( ctx != NULL );
+ RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
+ mode == MBEDTLS_RSA_PUBLIC );
+ RSA_VALIDATE_RET( output != NULL );
+ RSA_VALIDATE_RET( input != NULL );
- // We don't check p_rng because it won't be dereferenced here
- if( f_rng == NULL || input == NULL || output == NULL )
+ if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
olen = ctx->len;
@@ -1176,6 +1234,9 @@ int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx,
*p++ = 0;
if( mode == MBEDTLS_RSA_PUBLIC )
{
+ if( f_rng == NULL )
+ return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+
*p++ = MBEDTLS_RSA_CRYPT;
while( nb_pad-- > 0 )
@@ -1220,6 +1281,12 @@ int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx,
const unsigned char *input,
unsigned char *output )
{
+ RSA_VALIDATE_RET( ctx != NULL );
+ RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
+ mode == MBEDTLS_RSA_PUBLIC );
+ RSA_VALIDATE_RET( output != NULL );
+ RSA_VALIDATE_RET( input != NULL );
+
switch( ctx->padding )
{
#if defined(MBEDTLS_PKCS1_V15)
@@ -1262,6 +1329,14 @@ int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx,
const mbedtls_md_info_t *md_info;
mbedtls_md_context_t md_ctx;
+ RSA_VALIDATE_RET( ctx != NULL );
+ RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
+ mode == MBEDTLS_RSA_PUBLIC );
+ RSA_VALIDATE_RET( output_max_len == 0 || output != NULL );
+ RSA_VALIDATE_RET( label_len == 0 || label != NULL );
+ RSA_VALIDATE_RET( input != NULL );
+ RSA_VALIDATE_RET( olen != NULL );
+
/*
* Parameters sanity checks
*/
@@ -1378,6 +1453,97 @@ cleanup:
#endif /* MBEDTLS_PKCS1_V21 */
#if defined(MBEDTLS_PKCS1_V15)
+/** Turn zero-or-nonzero into zero-or-all-bits-one, without branches.
+ *
+ * \param value The value to analyze.
+ * \return Zero if \p value is zero, otherwise all-bits-one.
+ */
+static unsigned all_or_nothing_int( unsigned value )
+{
+ /* MSVC has a warning about unary minus on unsigned, but this is
+ * well-defined and precisely what we want to do here */
+#if defined(_MSC_VER)
+#pragma warning( push )
+#pragma warning( disable : 4146 )
+#endif
+ return( - ( ( value | - value ) >> ( sizeof( value ) * 8 - 1 ) ) );
+#if defined(_MSC_VER)
+#pragma warning( pop )
+#endif
+}
+
+/** Check whether a size is out of bounds, without branches.
+ *
+ * This is equivalent to `size > max`, but is likely to be compiled to
+ * to code using bitwise operation rather than a branch.
+ *
+ * \param size Size to check.
+ * \param max Maximum desired value for \p size.
+ * \return \c 0 if `size <= max`.
+ * \return \c 1 if `size > max`.
+ */
+static unsigned size_greater_than( size_t size, size_t max )
+{
+ /* Return the sign bit (1 for negative) of (max - size). */
+ return( ( max - size ) >> ( sizeof( size_t ) * 8 - 1 ) );
+}
+
+/** Choose between two integer values, without branches.
+ *
+ * This is equivalent to `cond ? if1 : if0`, but is likely to be compiled
+ * to code using bitwise operation rather than a branch.
+ *
+ * \param cond Condition to test.
+ * \param if1 Value to use if \p cond is nonzero.
+ * \param if0 Value to use if \p cond is zero.
+ * \return \c if1 if \p cond is nonzero, otherwise \c if0.
+ */
+static unsigned if_int( unsigned cond, unsigned if1, unsigned if0 )
+{
+ unsigned mask = all_or_nothing_int( cond );
+ return( ( mask & if1 ) | (~mask & if0 ) );
+}
+
+/** Shift some data towards the left inside a buffer without leaking
+ * the length of the data through side channels.
+ *
+ * `mem_move_to_left(start, total, offset)` is functionally equivalent to
+ * ```
+ * memmove(start, start + offset, total - offset);
+ * memset(start + offset, 0, total - offset);
+ * ```
+ * but it strives to use a memory access pattern (and thus total timing)
+ * that does not depend on \p offset. This timing independence comes at
+ * the expense of performance.
+ *
+ * \param start Pointer to the start of the buffer.
+ * \param total Total size of the buffer.
+ * \param offset Offset from which to copy \p total - \p offset bytes.
+ */
+static void mem_move_to_left( void *start,
+ size_t total,
+ size_t offset )
+{
+ volatile unsigned char *buf = start;
+ size_t i, n;
+ if( total == 0 )
+ return;
+ for( i = 0; i < total; i++ )
+ {
+ unsigned no_op = size_greater_than( total - offset, i );
+ /* The first `total - offset` passes are a no-op. The last
+ * `offset` passes shift the data one byte to the left and
+ * zero out the last byte. */
+ for( n = 0; n < total - 1; n++ )
+ {
+ unsigned char current = buf[n];
+ unsigned char next = buf[n+1];
+ buf[n] = if_int( no_op, current, next );
+ }
+ buf[total-1] = if_int( no_op, buf[total-1], 0 );
+ }
+}
+
/*
* Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function
*/
@@ -1387,18 +1553,42 @@ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx,
int mode, size_t *olen,
const unsigned char *input,
unsigned char *output,
- size_t output_max_len)
+ size_t output_max_len )
{
int ret;
- size_t ilen, pad_count = 0, i;
- unsigned char *p, bad, pad_done = 0;
+ size_t ilen, i, plaintext_max_size;
unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
+ /* The following variables take sensitive values: their value must
+ * not leak into the observable behavior of the function other than
+ * the designated outputs (output, olen, return value). Otherwise
+ * this would open the execution of the function to
+ * side-channel-based variants of the Bleichenbacher padding oracle
+ * attack. Potential side channels include overall timing, memory
+ * access patterns (especially visible to an adversary who has access
+ * to a shared memory cache), and branches (especially visible to
+ * an adversary who has access to a shared code cache or to a shared
+ * branch predictor). */
+ size_t pad_count = 0;
+ unsigned bad = 0;
+ unsigned char pad_done = 0;
+ size_t plaintext_size = 0;
+ unsigned output_too_large;
+
+ RSA_VALIDATE_RET( ctx != NULL );
+ RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
+ mode == MBEDTLS_RSA_PUBLIC );
+ RSA_VALIDATE_RET( output_max_len == 0 || output != NULL );
+ RSA_VALIDATE_RET( input != NULL );
+ RSA_VALIDATE_RET( olen != NULL );
+
+ ilen = ctx->len;
+ plaintext_max_size = ( output_max_len > ilen - 11 ?
+ ilen - 11 :
+ output_max_len );
if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
- ilen = ctx->len;
-
if( ilen < 16 || ilen > sizeof( buf ) )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
@@ -1409,63 +1599,109 @@ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx,
if( ret != 0 )
goto cleanup;
- p = buf;
- bad = 0;
-
- /*
- * Check and get padding len in "constant-time"
- */
- bad |= *p++; /* First byte must be 0 */
+ /* Check and get padding length in constant time and constant
+ * memory trace. The first byte must be 0. */
+ bad |= buf[0];
- /* This test does not depend on secret data */
if( mode == MBEDTLS_RSA_PRIVATE )
{
- bad |= *p++ ^ MBEDTLS_RSA_CRYPT;
+ /* Decode EME-PKCS1-v1_5 padding: 0x00 || 0x02 || PS || 0x00
+ * where PS must be at least 8 nonzero bytes. */
+ bad |= buf[1] ^ MBEDTLS_RSA_CRYPT;
- /* Get padding len, but always read till end of buffer
- * (minus one, for the 00 byte) */
- for( i = 0; i < ilen - 3; i++ )
+ /* Read the whole buffer. Set pad_done to nonzero if we find
+ * the 0x00 byte and remember the padding length in pad_count. */
+ for( i = 2; i < ilen; i++ )
{
- pad_done |= ((p[i] | (unsigned char)-p[i]) >> 7) ^ 1;
+ pad_done |= ((buf[i] | (unsigned char)-buf[i]) >> 7) ^ 1;
pad_count += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1;
}
-
- p += pad_count;
- bad |= *p++; /* Must be zero */
}
else
{
- bad |= *p++ ^ MBEDTLS_RSA_SIGN;
+ /* Decode EMSA-PKCS1-v1_5 padding: 0x00 || 0x01 || PS || 0x00
+ * where PS must be at least 8 bytes with the value 0xFF. */
+ bad |= buf[1] ^ MBEDTLS_RSA_SIGN;
- /* Get padding len, but always read till end of buffer
- * (minus one, for the 00 byte) */
- for( i = 0; i < ilen - 3; i++ )
+ /* Read the whole buffer. Set pad_done to nonzero if we find
+ * the 0x00 byte and remember the padding length in pad_count.
+ * If there's a non-0xff byte in the padding, the padding is bad. */
+ for( i = 2; i < ilen; i++ )
{
- pad_done |= ( p[i] != 0xFF );
- pad_count += ( pad_done == 0 );
+ pad_done |= if_int( buf[i], 0, 1 );
+ pad_count += if_int( pad_done, 0, 1 );
+ bad |= if_int( pad_done, 0, buf[i] ^ 0xFF );
}
-
- p += pad_count;
- bad |= *p++; /* Must be zero */
}
- bad |= ( pad_count < 8 );
-
- if( bad )
- {
- ret = MBEDTLS_ERR_RSA_INVALID_PADDING;
- goto cleanup;
- }
-
- if( ilen - ( p - buf ) > output_max_len )
- {
- ret = MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE;
- goto cleanup;
- }
-
- *olen = ilen - (p - buf);
- memcpy( output, p, *olen );
- ret = 0;
+ /* If pad_done is still zero, there's no data, only unfinished padding. */
+ bad |= if_int( pad_done, 0, 1 );
+
+ /* There must be at least 8 bytes of padding. */
+ bad |= size_greater_than( 8, pad_count );
+
+ /* If the padding is valid, set plaintext_size to the number of
+ * remaining bytes after stripping the padding. If the padding
+ * is invalid, avoid leaking this fact through the size of the
+ * output: use the maximum message size that fits in the output
+ * buffer. Do it without branches to avoid leaking the padding
+ * validity through timing. RSA keys are small enough that all the
+ * size_t values involved fit in unsigned int. */
+ plaintext_size = if_int( bad,
+ (unsigned) plaintext_max_size,
+ (unsigned) ( ilen - pad_count - 3 ) );
+
+ /* Set output_too_large to 0 if the plaintext fits in the output
+ * buffer and to 1 otherwise. */
+ output_too_large = size_greater_than( plaintext_size,
+ plaintext_max_size );
+
+ /* Set ret without branches to avoid timing attacks. Return:
+ * - INVALID_PADDING if the padding is bad (bad != 0).
+ * - OUTPUT_TOO_LARGE if the padding is good but the decrypted
+ * plaintext does not fit in the output buffer.
+ * - 0 if the padding is correct. */
+ ret = - (int) if_int( bad, - MBEDTLS_ERR_RSA_INVALID_PADDING,
+ if_int( output_too_large, - MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE,
+ 0 ) );
+
+ /* If the padding is bad or the plaintext is too large, zero the
+ * data that we're about to copy to the output buffer.
+ * We need to copy the same amount of data
+ * from the same buffer whether the padding is good or not to
+ * avoid leaking the padding validity through overall timing or
+ * through memory or cache access patterns. */
+ bad = all_or_nothing_int( bad | output_too_large );
+ for( i = 11; i < ilen; i++ )
+ buf[i] &= ~bad;
+
+ /* If the plaintext is too large, truncate it to the buffer size.
+ * Copy anyway to avoid revealing the length through timing, because
+ * revealing the length is as bad as revealing the padding validity
+ * for a Bleichenbacher attack. */
+ plaintext_size = if_int( output_too_large,
+ (unsigned) plaintext_max_size,
+ (unsigned) plaintext_size );
+
+ /* Move the plaintext to the leftmost position where it can start in
+ * the working buffer, i.e. make it start plaintext_max_size from
+ * the end of the buffer. Do this with a memory access trace that
+ * does not depend on the plaintext size. After this move, the
+ * starting location of the plaintext is no longer sensitive
+ * information. */
+ mem_move_to_left( buf + ilen - plaintext_max_size,
+ plaintext_max_size,
+ plaintext_max_size - plaintext_size );
+
+ /* Finally copy the decrypted plaintext plus trailing zeros
+ * into the output buffer. */
+ memcpy( output, buf + ilen - plaintext_max_size, plaintext_max_size );
+
+ /* Report the amount of data we copied to the output buffer. In case
+ * of errors (bad padding or output too large), the value of *olen
+ * when this function returns is not specified. Making it equivalent
+ * to the good case limits the risks of leaking the padding validity. */
+ *olen = plaintext_size;
cleanup:
mbedtls_platform_zeroize( buf, sizeof( buf ) );
@@ -1485,6 +1721,13 @@ int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx,
unsigned char *output,
size_t output_max_len)
{
+ RSA_VALIDATE_RET( ctx != NULL );
+ RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
+ mode == MBEDTLS_RSA_PUBLIC );
+ RSA_VALIDATE_RET( output_max_len == 0 || output != NULL );
+ RSA_VALIDATE_RET( input != NULL );
+ RSA_VALIDATE_RET( olen != NULL );
+
switch( ctx->padding )
{
#if defined(MBEDTLS_PKCS1_V15)
@@ -1521,11 +1764,18 @@ int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx,
size_t olen;
unsigned char *p = sig;
unsigned char salt[MBEDTLS_MD_MAX_SIZE];
- unsigned int slen, hlen, offset = 0;
+ size_t slen, min_slen, hlen, offset = 0;
int ret;
size_t msb;
const mbedtls_md_info_t *md_info;
mbedtls_md_context_t md_ctx;
+ RSA_VALIDATE_RET( ctx != NULL );
+ RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
+ mode == MBEDTLS_RSA_PUBLIC );
+ RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE &&
+ hashlen == 0 ) ||
+ hash != NULL );
+ RSA_VALIDATE_RET( sig != NULL );
if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
@@ -1550,10 +1800,20 @@ int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx,
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
hlen = mbedtls_md_get_size( md_info );
- slen = hlen;
- if( olen < hlen + slen + 2 )
+ /* Calculate the largest possible salt length. Normally this is the hash
+ * length, which is the maximum length the salt can have. If there is not
+ * enough room, use the maximum salt length that fits. The constraint is
+ * that the hash length plus the salt length plus 2 bytes must be at most
+ * the key length. This complies with FIPS 186-4 §5.5 (e) and RFC 8017
+ * (PKCS#1 v2.2) §9.1.1 step 3. */
+ min_slen = hlen - 2;
+ if( olen < hlen + min_slen + 2 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+ else if( olen >= hlen + hlen + 2 )
+ slen = hlen;
+ else
+ slen = olen - hlen - 2;
memset( sig, 0, olen );
@@ -1563,7 +1823,7 @@ int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx,
/* Note: EMSA-PSS encoding is over the length of N - 1 bits */
msb = mbedtls_mpi_bitlen( &ctx->N ) - 1;
- p += olen - hlen * 2 - 2;
+ p += olen - hlen - slen - 2;
*p++ = 0x01;
memcpy( p, salt, slen );
p += slen;
@@ -1763,6 +2023,14 @@ int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx,
int ret;
unsigned char *sig_try = NULL, *verif = NULL;
+ RSA_VALIDATE_RET( ctx != NULL );
+ RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
+ mode == MBEDTLS_RSA_PUBLIC );
+ RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE &&
+ hashlen == 0 ) ||
+ hash != NULL );
+ RSA_VALIDATE_RET( sig != NULL );
+
if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
@@ -1832,6 +2100,14 @@ int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx,
const unsigned char *hash,
unsigned char *sig )
{
+ RSA_VALIDATE_RET( ctx != NULL );
+ RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
+ mode == MBEDTLS_RSA_PUBLIC );
+ RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE &&
+ hashlen == 0 ) ||
+ hash != NULL );
+ RSA_VALIDATE_RET( sig != NULL );
+
switch( ctx->padding )
{
#if defined(MBEDTLS_PKCS1_V15)
@@ -1878,6 +2154,14 @@ int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx,
mbedtls_md_context_t md_ctx;
unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
+ RSA_VALIDATE_RET( ctx != NULL );
+ RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
+ mode == MBEDTLS_RSA_PUBLIC );
+ RSA_VALIDATE_RET( sig != NULL );
+ RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE &&
+ hashlen == 0 ) ||
+ hash != NULL );
+
if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
@@ -2006,7 +2290,16 @@ int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx,
const unsigned char *hash,
const unsigned char *sig )
{
- mbedtls_md_type_t mgf1_hash_id = ( ctx->hash_id != MBEDTLS_MD_NONE )
+ mbedtls_md_type_t mgf1_hash_id;
+ RSA_VALIDATE_RET( ctx != NULL );
+ RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
+ mode == MBEDTLS_RSA_PUBLIC );
+ RSA_VALIDATE_RET( sig != NULL );
+ RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE &&
+ hashlen == 0 ) ||
+ hash != NULL );
+
+ mgf1_hash_id = ( ctx->hash_id != MBEDTLS_MD_NONE )
? (mbedtls_md_type_t) ctx->hash_id
: md_alg;
@@ -2032,9 +2325,19 @@ int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx,
const unsigned char *sig )
{
int ret = 0;
- const size_t sig_len = ctx->len;
+ size_t sig_len;
unsigned char *encoded = NULL, *encoded_expected = NULL;
+ RSA_VALIDATE_RET( ctx != NULL );
+ RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
+ mode == MBEDTLS_RSA_PUBLIC );
+ RSA_VALIDATE_RET( sig != NULL );
+ RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE &&
+ hashlen == 0 ) ||
+ hash != NULL );
+
+ sig_len = ctx->len;
+
if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
@@ -2104,6 +2407,14 @@ int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx,
const unsigned char *hash,
const unsigned char *sig )
{
+ RSA_VALIDATE_RET( ctx != NULL );
+ RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
+ mode == MBEDTLS_RSA_PUBLIC );
+ RSA_VALIDATE_RET( sig != NULL );
+ RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE &&
+ hashlen == 0 ) ||
+ hash != NULL );
+
switch( ctx->padding )
{
#if defined(MBEDTLS_PKCS1_V15)
@@ -2129,6 +2440,8 @@ int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx,
int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src )
{
int ret;
+ RSA_VALIDATE_RET( dst != NULL );
+ RSA_VALIDATE_RET( src != NULL );
dst->ver = src->ver;
dst->len = src->len;
@@ -2168,14 +2481,23 @@ cleanup:
*/
void mbedtls_rsa_free( mbedtls_rsa_context *ctx )
{
- mbedtls_mpi_free( &ctx->Vi ); mbedtls_mpi_free( &ctx->Vf );
- mbedtls_mpi_free( &ctx->RN ); mbedtls_mpi_free( &ctx->D );
- mbedtls_mpi_free( &ctx->Q ); mbedtls_mpi_free( &ctx->P );
- mbedtls_mpi_free( &ctx->E ); mbedtls_mpi_free( &ctx->N );
+ if( ctx == NULL )
+ return;
+
+ mbedtls_mpi_free( &ctx->Vi );
+ mbedtls_mpi_free( &ctx->Vf );
+ mbedtls_mpi_free( &ctx->RN );
+ mbedtls_mpi_free( &ctx->D );
+ mbedtls_mpi_free( &ctx->Q );
+ mbedtls_mpi_free( &ctx->P );
+ mbedtls_mpi_free( &ctx->E );
+ mbedtls_mpi_free( &ctx->N );
#if !defined(MBEDTLS_RSA_NO_CRT)
- mbedtls_mpi_free( &ctx->RQ ); mbedtls_mpi_free( &ctx->RP );
- mbedtls_mpi_free( &ctx->QP ); mbedtls_mpi_free( &ctx->DQ );
+ mbedtls_mpi_free( &ctx->RQ );
+ mbedtls_mpi_free( &ctx->RP );
+ mbedtls_mpi_free( &ctx->QP );
+ mbedtls_mpi_free( &ctx->DQ );
mbedtls_mpi_free( &ctx->DP );
#endif /* MBEDTLS_RSA_NO_CRT */
diff --git a/thirdparty/mbedtls/library/rsa_internal.c b/thirdparty/mbedtls/library/rsa_internal.c
index 507009f131..9a42d47ceb 100644
--- a/thirdparty/mbedtls/library/rsa_internal.c
+++ b/thirdparty/mbedtls/library/rsa_internal.c
@@ -351,15 +351,20 @@ int mbedtls_rsa_validate_params( const mbedtls_mpi *N, const mbedtls_mpi *P,
*/
#if defined(MBEDTLS_GENPRIME)
+ /*
+ * When generating keys, the strongest security we support aims for an error
+ * rate of at most 2^-100 and we are aiming for the same certainty here as
+ * well.
+ */
if( f_rng != NULL && P != NULL &&
- ( ret = mbedtls_mpi_is_prime( P, f_rng, p_rng ) ) != 0 )
+ ( ret = mbedtls_mpi_is_prime_ext( P, 50, f_rng, p_rng ) ) != 0 )
{
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup;
}
if( f_rng != NULL && Q != NULL &&
- ( ret = mbedtls_mpi_is_prime( Q, f_rng, p_rng ) ) != 0 )
+ ( ret = mbedtls_mpi_is_prime_ext( Q, 50, f_rng, p_rng ) ) != 0 )
{
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup;
diff --git a/thirdparty/mbedtls/library/sha1.c b/thirdparty/mbedtls/library/sha1.c
index bab6087c4e..e8d4096fbb 100644
--- a/thirdparty/mbedtls/library/sha1.c
+++ b/thirdparty/mbedtls/library/sha1.c
@@ -46,6 +46,11 @@
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST */
+#define SHA1_VALIDATE_RET(cond) \
+ MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA1_BAD_INPUT_DATA )
+
+#define SHA1_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond )
+
#if !defined(MBEDTLS_SHA1_ALT)
/*
@@ -73,6 +78,8 @@
void mbedtls_sha1_init( mbedtls_sha1_context *ctx )
{
+ SHA1_VALIDATE( ctx != NULL );
+
memset( ctx, 0, sizeof( mbedtls_sha1_context ) );
}
@@ -87,6 +94,9 @@ void mbedtls_sha1_free( mbedtls_sha1_context *ctx )
void mbedtls_sha1_clone( mbedtls_sha1_context *dst,
const mbedtls_sha1_context *src )
{
+ SHA1_VALIDATE( dst != NULL );
+ SHA1_VALIDATE( src != NULL );
+
*dst = *src;
}
@@ -95,6 +105,8 @@ void mbedtls_sha1_clone( mbedtls_sha1_context *dst,
*/
int mbedtls_sha1_starts_ret( mbedtls_sha1_context *ctx )
{
+ SHA1_VALIDATE_RET( ctx != NULL );
+
ctx->total[0] = 0;
ctx->total[1] = 0;
@@ -120,6 +132,9 @@ int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx,
{
uint32_t temp, W[16], A, B, C, D, E;
+ SHA1_VALIDATE_RET( ctx != NULL );
+ SHA1_VALIDATE_RET( (const unsigned char *)data != NULL );
+
GET_UINT32_BE( W[ 0], data, 0 );
GET_UINT32_BE( W[ 1], data, 4 );
GET_UINT32_BE( W[ 2], data, 8 );
@@ -294,6 +309,9 @@ int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx,
size_t fill;
uint32_t left;
+ SHA1_VALIDATE_RET( ctx != NULL );
+ SHA1_VALIDATE_RET( ilen == 0 || input != NULL );
+
if( ilen == 0 )
return( 0 );
@@ -352,6 +370,9 @@ int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx,
uint32_t used;
uint32_t high, low;
+ SHA1_VALIDATE_RET( ctx != NULL );
+ SHA1_VALIDATE_RET( (unsigned char *)output != NULL );
+
/*
* Add padding: 0x80 then 0x00 until 8 bytes remain for the length
*/
@@ -420,6 +441,9 @@ int mbedtls_sha1_ret( const unsigned char *input,
int ret;
mbedtls_sha1_context ctx;
+ SHA1_VALIDATE_RET( ilen == 0 || input != NULL );
+ SHA1_VALIDATE_RET( (unsigned char *)output != NULL );
+
mbedtls_sha1_init( &ctx );
if( ( ret = mbedtls_sha1_starts_ret( &ctx ) ) != 0 )
diff --git a/thirdparty/mbedtls/library/sha256.c b/thirdparty/mbedtls/library/sha256.c
index dbb4a89861..8a540adfbe 100644
--- a/thirdparty/mbedtls/library/sha256.c
+++ b/thirdparty/mbedtls/library/sha256.c
@@ -49,6 +49,10 @@
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST */
+#define SHA256_VALIDATE_RET(cond) \
+ MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA256_BAD_INPUT_DATA )
+#define SHA256_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond )
+
#if !defined(MBEDTLS_SHA256_ALT)
/*
@@ -76,6 +80,8 @@ do { \
void mbedtls_sha256_init( mbedtls_sha256_context *ctx )
{
+ SHA256_VALIDATE( ctx != NULL );
+
memset( ctx, 0, sizeof( mbedtls_sha256_context ) );
}
@@ -90,6 +96,9 @@ void mbedtls_sha256_free( mbedtls_sha256_context *ctx )
void mbedtls_sha256_clone( mbedtls_sha256_context *dst,
const mbedtls_sha256_context *src )
{
+ SHA256_VALIDATE( dst != NULL );
+ SHA256_VALIDATE( src != NULL );
+
*dst = *src;
}
@@ -98,6 +107,9 @@ void mbedtls_sha256_clone( mbedtls_sha256_context *dst,
*/
int mbedtls_sha256_starts_ret( mbedtls_sha256_context *ctx, int is224 )
{
+ SHA256_VALIDATE_RET( ctx != NULL );
+ SHA256_VALIDATE_RET( is224 == 0 || is224 == 1 );
+
ctx->total[0] = 0;
ctx->total[1] = 0;
@@ -192,6 +204,9 @@ int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx,
uint32_t A[8];
unsigned int i;
+ SHA256_VALIDATE_RET( ctx != NULL );
+ SHA256_VALIDATE_RET( (const unsigned char *)data != NULL );
+
for( i = 0; i < 8; i++ )
A[i] = ctx->state[i];
@@ -263,6 +278,9 @@ int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx,
size_t fill;
uint32_t left;
+ SHA256_VALIDATE_RET( ctx != NULL );
+ SHA256_VALIDATE_RET( ilen == 0 || input != NULL );
+
if( ilen == 0 )
return( 0 );
@@ -321,6 +339,9 @@ int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx,
uint32_t used;
uint32_t high, low;
+ SHA256_VALIDATE_RET( ctx != NULL );
+ SHA256_VALIDATE_RET( (unsigned char *)output != NULL );
+
/*
* Add padding: 0x80 then 0x00 until 8 bytes remain for the length
*/
@@ -395,6 +416,10 @@ int mbedtls_sha256_ret( const unsigned char *input,
int ret;
mbedtls_sha256_context ctx;
+ SHA256_VALIDATE_RET( is224 == 0 || is224 == 1 );
+ SHA256_VALIDATE_RET( ilen == 0 || input != NULL );
+ SHA256_VALIDATE_RET( (unsigned char *)output != NULL );
+
mbedtls_sha256_init( &ctx );
if( ( ret = mbedtls_sha256_starts_ret( &ctx, is224 ) ) != 0 )
diff --git a/thirdparty/mbedtls/library/sha512.c b/thirdparty/mbedtls/library/sha512.c
index a9440e8af5..941ecda762 100644
--- a/thirdparty/mbedtls/library/sha512.c
+++ b/thirdparty/mbedtls/library/sha512.c
@@ -55,6 +55,10 @@
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST */
+#define SHA512_VALIDATE_RET(cond) \
+ MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA512_BAD_INPUT_DATA )
+#define SHA512_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond )
+
#if !defined(MBEDTLS_SHA512_ALT)
/*
@@ -90,6 +94,8 @@
void mbedtls_sha512_init( mbedtls_sha512_context *ctx )
{
+ SHA512_VALIDATE( ctx != NULL );
+
memset( ctx, 0, sizeof( mbedtls_sha512_context ) );
}
@@ -104,6 +110,9 @@ void mbedtls_sha512_free( mbedtls_sha512_context *ctx )
void mbedtls_sha512_clone( mbedtls_sha512_context *dst,
const mbedtls_sha512_context *src )
{
+ SHA512_VALIDATE( dst != NULL );
+ SHA512_VALIDATE( src != NULL );
+
*dst = *src;
}
@@ -112,6 +121,9 @@ void mbedtls_sha512_clone( mbedtls_sha512_context *dst,
*/
int mbedtls_sha512_starts_ret( mbedtls_sha512_context *ctx, int is384 )
{
+ SHA512_VALIDATE_RET( ctx != NULL );
+ SHA512_VALIDATE_RET( is384 == 0 || is384 == 1 );
+
ctx->total[0] = 0;
ctx->total[1] = 0;
@@ -209,6 +221,9 @@ int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx,
uint64_t temp1, temp2, W[80];
uint64_t A, B, C, D, E, F, G, H;
+ SHA512_VALIDATE_RET( ctx != NULL );
+ SHA512_VALIDATE_RET( (const unsigned char *)data != NULL );
+
#define SHR(x,n) (x >> n)
#define ROTR(x,n) (SHR(x,n) | (x << (64 - n)))
@@ -294,6 +309,9 @@ int mbedtls_sha512_update_ret( mbedtls_sha512_context *ctx,
size_t fill;
unsigned int left;
+ SHA512_VALIDATE_RET( ctx != NULL );
+ SHA512_VALIDATE_RET( ilen == 0 || input != NULL );
+
if( ilen == 0 )
return( 0 );
@@ -351,6 +369,9 @@ int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx,
unsigned used;
uint64_t high, low;
+ SHA512_VALIDATE_RET( ctx != NULL );
+ SHA512_VALIDATE_RET( (unsigned char *)output != NULL );
+
/*
* Add padding: 0x80 then 0x00 until 16 bytes remain for the length
*/
@@ -427,6 +448,10 @@ int mbedtls_sha512_ret( const unsigned char *input,
int ret;
mbedtls_sha512_context ctx;
+ SHA512_VALIDATE_RET( is384 == 0 || is384 == 1 );
+ SHA512_VALIDATE_RET( ilen == 0 || input != NULL );
+ SHA512_VALIDATE_RET( (unsigned char *)output != NULL );
+
mbedtls_sha512_init( &ctx );
if( ( ret = mbedtls_sha512_starts_ret( &ctx, is384 ) ) != 0 )
diff --git a/thirdparty/mbedtls/library/ssl_ciphersuites.c b/thirdparty/mbedtls/library/ssl_ciphersuites.c
index 59cdc7a806..745474effe 100644
--- a/thirdparty/mbedtls/library/ssl_ciphersuites.c
+++ b/thirdparty/mbedtls/library/ssl_ciphersuites.c
@@ -2320,7 +2320,8 @@ mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg( const mbedtls_ssl_ciphers
#endif /* MBEDTLS_PK_C */
-#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C)
+#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
+ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info )
{
switch( info->key_exchange )
@@ -2330,13 +2331,14 @@ int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info )
case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK:
case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:
case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:
+ case MBEDTLS_KEY_EXCHANGE_ECJPAKE:
return( 1 );
default:
return( 0 );
}
}
-#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C */
+#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED*/
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
int mbedtls_ssl_ciphersuite_uses_psk( const mbedtls_ssl_ciphersuite_t *info )
diff --git a/thirdparty/mbedtls/library/ssl_cli.c b/thirdparty/mbedtls/library/ssl_cli.c
index ba59c48989..afced7a99c 100644
--- a/thirdparty/mbedtls/library/ssl_cli.c
+++ b/thirdparty/mbedtls/library/ssl_cli.c
@@ -766,6 +766,10 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
unsigned char offer_compress;
const int *ciphersuites;
const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
+#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
+ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+ int uses_ec = 0;
+#endif
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client hello" ) );
@@ -917,6 +921,11 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %04x",
ciphersuites[i] ) );
+#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
+ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+ uses_ec |= mbedtls_ssl_ciphersuite_uses_ec( ciphersuite_info );
+#endif
+
n++;
*p++ = (unsigned char)( ciphersuites[i] >> 8 );
*p++ = (unsigned char)( ciphersuites[i] );
@@ -1010,11 +1019,14 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
- ssl_write_supported_elliptic_curves_ext( ssl, p + 2 + ext_len, &olen );
- ext_len += olen;
+ if( uses_ec )
+ {
+ ssl_write_supported_elliptic_curves_ext( ssl, p + 2 + ext_len, &olen );
+ ext_len += olen;
- ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen );
- ext_len += olen;
+ ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen );
+ ext_len += olen;
+ }
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
@@ -1076,11 +1088,20 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
mbedtls_ssl_send_flight_completed( ssl );
#endif
- if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
+ return( ret );
+ }
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+ ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
{
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret );
return( ret );
}
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write client hello" ) );
@@ -1479,7 +1500,7 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
buf = ssl->in_msg;
- if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
{
/* No alert on a read error. */
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
@@ -1742,6 +1763,14 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", suite_info->name ) );
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA &&
+ ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
+ {
+ ssl->handshake->ecrs_enabled = 1;
+ }
+#endif
+
if( comp != MBEDTLS_SSL_COMPRESS_NULL
#if defined(MBEDTLS_ZLIB_SUPPORT)
&& comp != MBEDTLS_SSL_COMPRESS_DEFLATE
@@ -1998,8 +2027,14 @@ static int ssl_parse_server_dh_params( mbedtls_ssl_context *ssl, unsigned char *
static int ssl_check_server_ecdh_params( const mbedtls_ssl_context *ssl )
{
const mbedtls_ecp_curve_info *curve_info;
+ mbedtls_ecp_group_id grp_id;
+#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
+ grp_id = ssl->handshake->ecdh_ctx.grp.id;
+#else
+ grp_id = ssl->handshake->ecdh_ctx.grp_id;
+#endif
- curve_info = mbedtls_ecp_curve_info_from_grp_id( ssl->handshake->ecdh_ctx.grp.id );
+ curve_info = mbedtls_ecp_curve_info_from_grp_id( grp_id );
if( curve_info == NULL )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
@@ -2009,14 +2044,15 @@ static int ssl_check_server_ecdh_params( const mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDH curve: %s", curve_info->name ) );
#if defined(MBEDTLS_ECP_C)
- if( mbedtls_ssl_check_curve( ssl, ssl->handshake->ecdh_ctx.grp.id ) != 0 )
+ if( mbedtls_ssl_check_curve( ssl, grp_id ) != 0 )
#else
if( ssl->handshake->ecdh_ctx.grp.nbits < 163 ||
ssl->handshake->ecdh_ctx.grp.nbits > 521 )
#endif
return( -1 );
- MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Qp", &ssl->handshake->ecdh_ctx.Qp );
+ MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx,
+ MBEDTLS_DEBUG_ECDH_QP );
return( 0 );
}
@@ -2047,6 +2083,10 @@ static int ssl_parse_server_ecdh_params( mbedtls_ssl_context *ssl,
(const unsigned char **) p, end ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_read_params" ), ret );
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
+ ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
+#endif
return( ret );
}
@@ -2076,7 +2116,7 @@ static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl,
*
* opaque psk_identity_hint<0..2^16-1>;
*/
- if( (*p) > end - 2 )
+ if( end - (*p) < 2 )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message "
"(psk_identity_hint length)" ) );
@@ -2085,7 +2125,7 @@ static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl,
len = (*p)[0] << 8 | (*p)[1];
*p += 2;
- if( (*p) > end - len )
+ if( end - (*p) < (int) len )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message "
"(psk_identity_hint length)" ) );
@@ -2328,7 +2368,15 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED ||
MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
- if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ if( ssl->handshake->ecrs_enabled &&
+ ssl->handshake->ecrs_state == ssl_ecrs_ske_start_processing )
+ {
+ goto start_processing;
+ }
+#endif
+
+ if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
return( ret );
@@ -2365,6 +2413,12 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
}
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ if( ssl->handshake->ecrs_enabled )
+ ssl->handshake->ecrs_state = ssl_ecrs_ske_start_processing;
+
+start_processing:
+#endif
p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl );
end = ssl->in_msg + ssl->in_hslen;
MBEDTLS_SSL_DEBUG_BUF( 3, "server key exchange", p, end - p );
@@ -2457,6 +2511,7 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;
unsigned char *params = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl );
size_t params_len = p - params;
+ void *rs_ctx = NULL;
/*
* Handle the digitally-signed structure
@@ -2579,12 +2634,25 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH );
}
- if( ( ret = mbedtls_pk_verify( &ssl->session_negotiate->peer_cert->pk,
- md_alg, hash, hashlen, p, sig_len ) ) != 0 )
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ if( ssl->handshake->ecrs_enabled )
+ rs_ctx = &ssl->handshake->ecrs_ctx.pk;
+#endif
+
+ if( ( ret = mbedtls_pk_verify_restartable(
+ &ssl->session_negotiate->peer_cert->pk,
+ md_alg, hash, hashlen, p, sig_len, rs_ctx ) ) != 0 )
{
- mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
- MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR );
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
+#endif
+ mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+ MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR );
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret );
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
+ ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
+#endif
return( ret );
}
}
@@ -2635,7 +2703,7 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl )
return( 0 );
}
- if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
return( ret );
@@ -2709,7 +2777,7 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl )
* therefore the buffer length at this point must be greater than that
* regardless of the actual code path.
*/
- if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n )
+ if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
@@ -2787,7 +2855,7 @@ static int ssl_parse_server_hello_done( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello done" ) );
- if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
return( ret );
@@ -2882,6 +2950,16 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
*/
i = 4;
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ if( ssl->handshake->ecrs_enabled )
+ {
+ if( ssl->handshake->ecrs_state == ssl_ecrs_cke_ecdh_calc_secret )
+ goto ecdh_calc_secret;
+
+ mbedtls_ecdh_enable_restart( &ssl->handshake->ecdh_ctx );
+ }
+#endif
+
ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx,
&n,
&ssl->out_msg[i], 1000,
@@ -2889,11 +2967,27 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
if( ret != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_public", ret );
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
+ ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
+#endif
return( ret );
}
- MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q", &ssl->handshake->ecdh_ctx.Q );
+ MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx,
+ MBEDTLS_DEBUG_ECDH_Q );
+
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ if( ssl->handshake->ecrs_enabled )
+ {
+ ssl->handshake->ecrs_n = n;
+ ssl->handshake->ecrs_state = ssl_ecrs_cke_ecdh_calc_secret;
+ }
+ecdh_calc_secret:
+ if( ssl->handshake->ecrs_enabled )
+ n = ssl->handshake->ecrs_n;
+#endif
if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx,
&ssl->handshake->pmslen,
ssl->handshake->premaster,
@@ -2901,10 +2995,15 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret );
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
+ ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
+#endif
return( ret );
}
- MBEDTLS_SSL_DEBUG_MPI( 3, "ECDH: z", &ssl->handshake->ecdh_ctx.z );
+ MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx,
+ MBEDTLS_DEBUG_ECDH_Z );
}
else
#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
@@ -2999,7 +3098,8 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
return( ret );
}
- MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q", &ssl->handshake->ecdh_ctx.Q );
+ MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx,
+ MBEDTLS_DEBUG_ECDH_Q );
}
else
#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
@@ -3063,9 +3163,9 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
ssl->state++;
- if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
{
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
return( ret );
}
@@ -3119,9 +3219,18 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
unsigned char *hash_start = hash;
mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE;
unsigned int hashlen;
+ void *rs_ctx = NULL;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) );
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ if( ssl->handshake->ecrs_enabled &&
+ ssl->handshake->ecrs_state == ssl_ecrs_crt_vrfy_sign )
+ {
+ goto sign;
+ }
+#endif
+
if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret );
@@ -3153,8 +3262,15 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
}
/*
- * Make an RSA signature of the handshake digests
+ * Make a signature of the handshake digests
*/
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ if( ssl->handshake->ecrs_enabled )
+ ssl->handshake->ecrs_state = ssl_ecrs_crt_vrfy_sign;
+
+sign:
+#endif
+
ssl->handshake->calc_verify( ssl, hash );
#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
@@ -3231,11 +3347,21 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
- if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), md_alg, hash_start, hashlen,
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ if( ssl->handshake->ecrs_enabled )
+ rs_ctx = &ssl->handshake->ecrs_ctx.pk;
+#endif
+
+ if( ( ret = mbedtls_pk_sign_restartable( mbedtls_ssl_own_key( ssl ),
+ md_alg, hash_start, hashlen,
ssl->out_msg + 6 + offset, &n,
- ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
+ ssl->conf->f_rng, ssl->conf->p_rng, rs_ctx ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret );
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
+ ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
+#endif
return( ret );
}
@@ -3248,9 +3374,9 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
ssl->state++;
- if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
{
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
return( ret );
}
@@ -3276,7 +3402,7 @@ static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse new session ticket" ) );
- if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
return( ret );
@@ -3311,8 +3437,8 @@ static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl )
msg = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl );
- lifetime = ( msg[0] << 24 ) | ( msg[1] << 16 ) |
- ( msg[2] << 8 ) | ( msg[3] );
+ lifetime = ( ((uint32_t) msg[0]) << 24 ) | ( msg[1] << 16 ) |
+ ( msg[2] << 8 ) | ( msg[3] );
ticket_len = ( msg[4] << 8 ) | ( msg[5] );
@@ -3390,10 +3516,10 @@ int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl )
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING )
{
- if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
return( ret );
}
-#endif
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
/* Change state now, so that it is right in mbedtls_ssl_read_record(), used
* by DTLS for dropping out-of-sequence ChangeCipherSpec records */
diff --git a/thirdparty/mbedtls/library/ssl_srv.c b/thirdparty/mbedtls/library/ssl_srv.c
index 52087ae6e1..bc77f80203 100644
--- a/thirdparty/mbedtls/library/ssl_srv.c
+++ b/thirdparty/mbedtls/library/ssl_srv.c
@@ -1294,7 +1294,7 @@ read_record_header:
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
- memcpy( ssl->out_ctr + 2, ssl->in_ctr + 2, 6 );
+ memcpy( ssl->cur_out_ctr + 2, ssl->in_ctr + 2, 6 );
#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
if( mbedtls_ssl_dtls_replay_check( ssl ) != 0 )
@@ -2384,12 +2384,21 @@ static int ssl_write_hello_verify_request( mbedtls_ssl_context *ssl )
ssl->state = MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT;
- if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
{
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
return( ret );
}
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+ ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret );
+ return( ret );
+ }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write hello verify request" ) );
return( 0 );
@@ -2589,8 +2598,12 @@ static int ssl_write_server_hello( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
- ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen );
- ext_len += olen;
+ if ( mbedtls_ssl_ciphersuite_uses_ec(
+ mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite ) ) )
+ {
+ ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen );
+ ext_len += olen;
+ }
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
@@ -2620,7 +2633,7 @@ static int ssl_write_server_hello( mbedtls_ssl_context *ssl )
ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_HELLO;
- ret = mbedtls_ssl_write_record( ssl );
+ ret = mbedtls_ssl_write_handshake_msg( ssl );
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello" ) );
@@ -2815,7 +2828,7 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl )
ssl->out_msg[4 + ct_len + sa_len] = (unsigned char)( total_dn_size >> 8 );
ssl->out_msg[5 + ct_len + sa_len] = (unsigned char)( total_dn_size );
- ret = mbedtls_ssl_write_record( ssl );
+ ret = mbedtls_ssl_write_handshake_msg( ssl );
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate request" ) );
@@ -3035,8 +3048,8 @@ curve_matching_done:
MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDHE curve: %s", (*curve)->name ) );
- if( ( ret = mbedtls_ecp_group_load( &ssl->handshake->ecdh_ctx.grp,
- (*curve)->grp_id ) ) != 0 )
+ if( ( ret = mbedtls_ecdh_setup( &ssl->handshake->ecdh_ctx,
+ (*curve)->grp_id ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecp_group_load", ret );
return( ret );
@@ -3058,7 +3071,8 @@ curve_matching_done:
ssl->out_msglen += len;
- MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q ", &ssl->handshake->ecdh_ctx.Q );
+ MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx,
+ MBEDTLS_DEBUG_ECDH_Q );
}
#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED */
@@ -3332,9 +3346,9 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
ssl->state++;
- if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
{
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
return( ret );
}
@@ -3359,11 +3373,20 @@ static int ssl_write_server_hello_done( mbedtls_ssl_context *ssl )
mbedtls_ssl_send_flight_completed( ssl );
#endif
- if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
+ return( ret );
+ }
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+ ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
{
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret );
return( ret );
}
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello done" ) );
@@ -3706,7 +3729,7 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
}
else
#endif
- if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
return( ret );
@@ -3772,7 +3795,8 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP );
}
- MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Qp ", &ssl->handshake->ecdh_ctx.Qp );
+ MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx,
+ MBEDTLS_DEBUG_ECDH_QP );
if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx,
&ssl->handshake->pmslen,
@@ -3784,7 +3808,8 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS );
}
- MBEDTLS_SSL_DEBUG_MPI( 3, "ECDH: z ", &ssl->handshake->ecdh_ctx.z );
+ MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx,
+ MBEDTLS_DEBUG_ECDH_Z );
}
else
#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
@@ -3897,7 +3922,8 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP );
}
- MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Qp ", &ssl->handshake->ecdh_ctx.Qp );
+ MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx,
+ MBEDTLS_DEBUG_ECDH_QP );
if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl,
ciphersuite_info->key_exchange ) ) != 0 )
@@ -4016,25 +4042,10 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
}
/* Read the message without adding it to the checksum */
- do {
-
- do ret = mbedtls_ssl_read_record_layer( ssl );
- while( ret == MBEDTLS_ERR_SSL_CONTINUE_PROCESSING );
-
- if( ret != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret );
- return( ret );
- }
-
- ret = mbedtls_ssl_handle_message_type( ssl );
-
- } while( MBEDTLS_ERR_SSL_NON_FATAL == ret ||
- MBEDTLS_ERR_SSL_CONTINUE_PROCESSING == ret );
-
+ ret = mbedtls_ssl_read_record( ssl, 0 /* no checksum update */ );
if( 0 != ret )
{
- MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_handle_message_type" ), ret );
+ MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record" ), ret );
return( ret );
}
@@ -4223,9 +4234,9 @@ static int ssl_write_new_session_ticket( mbedtls_ssl_context *ssl )
*/
ssl->handshake->new_session_ticket = 0;
- if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
{
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
return( ret );
}
@@ -4254,10 +4265,10 @@ int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl )
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING )
{
- if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
return( ret );
}
-#endif
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
switch( ssl->state )
{
diff --git a/thirdparty/mbedtls/library/ssl_ticket.c b/thirdparty/mbedtls/library/ssl_ticket.c
index a2b304869e..8492c19a8c 100644
--- a/thirdparty/mbedtls/library/ssl_ticket.c
+++ b/thirdparty/mbedtls/library/ssl_ticket.c
@@ -97,7 +97,7 @@ static int ssl_ticket_update_keys( mbedtls_ssl_ticket_context *ctx )
uint32_t current_time = (uint32_t) mbedtls_time( NULL );
uint32_t key_time = ctx->keys[ctx->active].generation_time;
- if( current_time > key_time &&
+ if( current_time >= key_time &&
current_time - key_time < ctx->ticket_lifetime )
{
return( 0 );
@@ -188,9 +188,9 @@ static int ssl_save_session( const mbedtls_ssl_session *session,
if( left < 3 + cert_len )
return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
- *p++ = (unsigned char)( cert_len >> 16 & 0xFF );
- *p++ = (unsigned char)( cert_len >> 8 & 0xFF );
- *p++ = (unsigned char)( cert_len & 0xFF );
+ *p++ = (unsigned char)( ( cert_len >> 16 ) & 0xFF );
+ *p++ = (unsigned char)( ( cert_len >> 8 ) & 0xFF );
+ *p++ = (unsigned char)( ( cert_len ) & 0xFF );
if( session->peer_cert != NULL )
memcpy( p, session->peer_cert->raw.p, cert_len );
@@ -215,14 +215,14 @@ static int ssl_load_session( mbedtls_ssl_session *session,
size_t cert_len;
#endif /* MBEDTLS_X509_CRT_PARSE_C */
- if( p + sizeof( mbedtls_ssl_session ) > end )
+ if( sizeof( mbedtls_ssl_session ) > (size_t)( end - p ) )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
memcpy( session, p, sizeof( mbedtls_ssl_session ) );
p += sizeof( mbedtls_ssl_session );
#if defined(MBEDTLS_X509_CRT_PARSE_C)
- if( p + 3 > end )
+ if( 3 > (size_t)( end - p ) )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
cert_len = ( p[0] << 16 ) | ( p[1] << 8 ) | p[2];
@@ -236,7 +236,7 @@ static int ssl_load_session( mbedtls_ssl_session *session,
{
int ret;
- if( p + cert_len > end )
+ if( cert_len > (size_t)( end - p ) )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
session->peer_cert = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) );
@@ -247,7 +247,7 @@ static int ssl_load_session( mbedtls_ssl_session *session,
mbedtls_x509_crt_init( session->peer_cert );
if( ( ret = mbedtls_x509_crt_parse_der( session->peer_cert,
- p, cert_len ) ) != 0 )
+ p, cert_len ) ) != 0 )
{
mbedtls_x509_crt_free( session->peer_cert );
mbedtls_free( session->peer_cert );
diff --git a/thirdparty/mbedtls/library/ssl_tls.c b/thirdparty/mbedtls/library/ssl_tls.c
index 91f96c8ab6..38690fa664 100644
--- a/thirdparty/mbedtls/library/ssl_tls.c
+++ b/thirdparty/mbedtls/library/ssl_tls.c
@@ -54,6 +54,9 @@
#include "mbedtls/oid.h"
#endif
+static void ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl );
+static uint32_t ssl_get_hs_total_len( mbedtls_ssl_context const *ssl );
+
/* Length of the "epoch" field in the record header */
static inline size_t ssl_ep_len( const mbedtls_ssl_context *ssl )
{
@@ -96,7 +99,101 @@ static int ssl_check_timer( mbedtls_ssl_context *ssl )
return( 0 );
}
+static void ssl_update_out_pointers( mbedtls_ssl_context *ssl,
+ mbedtls_ssl_transform *transform );
+static void ssl_update_in_pointers( mbedtls_ssl_context *ssl,
+ mbedtls_ssl_transform *transform );
+
+#define SSL_DONT_FORCE_FLUSH 0
+#define SSL_FORCE_FLUSH 1
+
#if defined(MBEDTLS_SSL_PROTO_DTLS)
+
+/* Forward declarations for functions related to message buffering. */
+static void ssl_buffering_free( mbedtls_ssl_context *ssl );
+static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl,
+ uint8_t slot );
+static void ssl_free_buffered_record( mbedtls_ssl_context *ssl );
+static int ssl_load_buffered_message( mbedtls_ssl_context *ssl );
+static int ssl_load_buffered_record( mbedtls_ssl_context *ssl );
+static int ssl_buffer_message( mbedtls_ssl_context *ssl );
+static int ssl_buffer_future_record( mbedtls_ssl_context *ssl );
+static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl );
+
+static size_t ssl_get_current_mtu( const mbedtls_ssl_context *ssl );
+static size_t ssl_get_maximum_datagram_size( mbedtls_ssl_context const *ssl )
+{
+ size_t mtu = ssl_get_current_mtu( ssl );
+
+ if( mtu != 0 && mtu < MBEDTLS_SSL_OUT_BUFFER_LEN )
+ return( mtu );
+
+ return( MBEDTLS_SSL_OUT_BUFFER_LEN );
+}
+
+static int ssl_get_remaining_space_in_datagram( mbedtls_ssl_context const *ssl )
+{
+ size_t const bytes_written = ssl->out_left;
+ size_t const mtu = ssl_get_maximum_datagram_size( ssl );
+
+ /* Double-check that the write-index hasn't gone
+ * past what we can transmit in a single datagram. */
+ if( bytes_written > mtu )
+ {
+ /* Should never happen... */
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+ return( (int) ( mtu - bytes_written ) );
+}
+
+static int ssl_get_remaining_payload_in_datagram( mbedtls_ssl_context const *ssl )
+{
+ int ret;
+ size_t remaining, expansion;
+ size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN;
+
+#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+ const size_t mfl = mbedtls_ssl_get_max_frag_len( ssl );
+
+ if( max_len > mfl )
+ max_len = mfl;
+
+ /* By the standard (RFC 6066 Sect. 4), the MFL extension
+ * only limits the maximum record payload size, so in theory
+ * we would be allowed to pack multiple records of payload size
+ * MFL into a single datagram. However, this would mean that there's
+ * no way to explicitly communicate MTU restrictions to the peer.
+ *
+ * The following reduction of max_len makes sure that we never
+ * write datagrams larger than MFL + Record Expansion Overhead.
+ */
+ if( max_len <= ssl->out_left )
+ return( 0 );
+
+ max_len -= ssl->out_left;
+#endif
+
+ ret = ssl_get_remaining_space_in_datagram( ssl );
+ if( ret < 0 )
+ return( ret );
+ remaining = (size_t) ret;
+
+ ret = mbedtls_ssl_get_record_expansion( ssl );
+ if( ret < 0 )
+ return( ret );
+ expansion = (size_t) ret;
+
+ if( remaining <= expansion )
+ return( 0 );
+
+ remaining -= expansion;
+ if( remaining >= max_len )
+ remaining = max_len;
+
+ return( (int) remaining );
+}
+
/*
* Double the retransmit timeout value, within the allowed range,
* returning -1 if the maximum value has already been reached.
@@ -108,6 +205,18 @@ static int ssl_double_retransmit_timeout( mbedtls_ssl_context *ssl )
if( ssl->handshake->retransmit_timeout >= ssl->conf->hs_timeout_max )
return( -1 );
+ /* Implement the final paragraph of RFC 6347 section 4.1.1.1
+ * in the following way: after the initial transmission and a first
+ * retransmission, back off to a temporary estimated MTU of 508 bytes.
+ * This value is guaranteed to be deliverable (if not guaranteed to be
+ * delivered) of any compliant IPv4 (and IPv6) network, and should work
+ * on most non-IP stacks too. */
+ if( ssl->handshake->retransmit_timeout != ssl->conf->hs_timeout_min )
+ {
+ ssl->handshake->mtu = 508;
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "mtu autoreduction to %d bytes", ssl->handshake->mtu ) );
+ }
+
new_timeout = 2 * ssl->handshake->retransmit_timeout;
/* Avoid arithmetic overflow and range overflow */
@@ -1224,7 +1333,8 @@ int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exch
*(p++) = (unsigned char)( zlen );
p += zlen;
- MBEDTLS_SSL_DEBUG_MPI( 3, "ECDH: z", &ssl->handshake->ecdh_ctx.z );
+ MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx,
+ MBEDTLS_DEBUG_ECDH_Z );
}
else
#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
@@ -1345,14 +1455,6 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_BUF( 4, "before encrypt: output payload",
ssl->out_msg, ssl->out_msglen );
- if( ssl->out_msglen > MBEDTLS_SSL_OUT_CONTENT_LEN )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record content %u too large, maximum %d",
- (unsigned) ssl->out_msglen,
- MBEDTLS_SSL_OUT_CONTENT_LEN ) );
- return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
- }
-
/*
* Add MAC before if needed
*/
@@ -1626,6 +1728,8 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
if( auth_done == 0 )
{
+ unsigned char mac[MBEDTLS_SSL_MAC_ADD];
+
/*
* MAC(MAC_write_key, seq_num +
* TLSCipherText.type +
@@ -1648,10 +1752,12 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl )
mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, pseudo_hdr, 13 );
mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc,
ssl->out_iv, ssl->out_msglen );
- mbedtls_md_hmac_finish( &ssl->transform_out->md_ctx_enc,
- ssl->out_iv + ssl->out_msglen );
+ mbedtls_md_hmac_finish( &ssl->transform_out->md_ctx_enc, mac );
mbedtls_md_hmac_reset( &ssl->transform_out->md_ctx_enc );
+ memcpy( ssl->out_iv + ssl->out_msglen, mac,
+ ssl->transform_out->maclen );
+
ssl->out_msglen += ssl->transform_out->maclen;
auth_done++;
}
@@ -2202,13 +2308,13 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl )
correct = 0;
}
auth_done++;
-
- /*
- * Finally check the correct flag
- */
- if( correct == 0 )
- return( MBEDTLS_ERR_SSL_INVALID_MAC );
}
+
+ /*
+ * Finally check the correct flag
+ */
+ if( correct == 0 )
+ return( MBEDTLS_ERR_SSL_INVALID_MAC );
#endif /* SSL_SOME_MODES_USE_MAC */
/* Make extra sure authentication was performed, exactly once */
@@ -2644,7 +2750,7 @@ int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want )
int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl )
{
int ret;
- unsigned char *buf, i;
+ unsigned char *buf;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> flush output" ) );
@@ -2667,8 +2773,7 @@ int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 2, ( "message length: %d, out_left: %d",
mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen, ssl->out_left ) );
- buf = ssl->out_hdr + mbedtls_ssl_hdr_len( ssl ) +
- ssl->out_msglen - ssl->out_left;
+ buf = ssl->out_hdr - ssl->out_left;
ret = ssl->f_send( ssl->p_bio, buf, ssl->out_left );
MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_send", ret );
@@ -2687,16 +2792,17 @@ int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl )
ssl->out_left -= ret;
}
- for( i = 8; i > ssl_ep_len( ssl ); i-- )
- if( ++ssl->out_ctr[i - 1] != 0 )
- break;
-
- /* The loop goes to its end iff the counter is wrapping */
- if( i == ssl_ep_len( ssl ) )
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ {
+ ssl->out_hdr = ssl->out_buf;
+ }
+ else
+#endif
{
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "outgoing message counter would wrap" ) );
- return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING );
+ ssl->out_hdr = ssl->out_buf + 8;
}
+ ssl_update_out_pointers( ssl, ssl->transform_out );
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) );
@@ -2713,6 +2819,9 @@ int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl )
static int ssl_flight_append( mbedtls_ssl_context *ssl )
{
mbedtls_ssl_flight_item *msg;
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_flight_append" ) );
+ MBEDTLS_SSL_DEBUG_BUF( 4, "message appended to flight",
+ ssl->out_msg, ssl->out_msglen );
/* Allocate space for current message */
if( ( msg = mbedtls_calloc( 1, sizeof( mbedtls_ssl_flight_item ) ) ) == NULL )
@@ -2746,6 +2855,7 @@ static int ssl_flight_append( mbedtls_ssl_context *ssl )
cur->next = msg;
}
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_flight_append" ) );
return( 0 );
}
@@ -2794,19 +2904,12 @@ static void ssl_swap_epochs( mbedtls_ssl_context *ssl )
ssl->handshake->alt_transform_out = tmp_transform;
/* Swap epoch + sequence_number */
- memcpy( tmp_out_ctr, ssl->out_ctr, 8 );
- memcpy( ssl->out_ctr, ssl->handshake->alt_out_ctr, 8 );
+ memcpy( tmp_out_ctr, ssl->cur_out_ctr, 8 );
+ memcpy( ssl->cur_out_ctr, ssl->handshake->alt_out_ctr, 8 );
memcpy( ssl->handshake->alt_out_ctr, tmp_out_ctr, 8 );
/* Adjust to the newly activated transform */
- if( ssl->transform_out != NULL &&
- ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
- {
- ssl->out_msg = ssl->out_iv + ssl->transform_out->ivlen -
- ssl->transform_out->fixed_ivlen;
- }
- else
- ssl->out_msg = ssl->out_iv;
+ ssl_update_out_pointers( ssl, ssl->transform_out );
#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
if( mbedtls_ssl_hw_record_activate != NULL )
@@ -2822,20 +2925,38 @@ static void ssl_swap_epochs( mbedtls_ssl_context *ssl )
/*
* Retransmit the current flight of messages.
+ */
+int mbedtls_ssl_resend( mbedtls_ssl_context *ssl )
+{
+ int ret = 0;
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_resend" ) );
+
+ ret = mbedtls_ssl_flight_transmit( ssl );
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_resend" ) );
+
+ return( ret );
+}
+
+/*
+ * Transmit or retransmit the current flight of messages.
*
* Need to remember the current message in case flush_output returns
* WANT_WRITE, causing us to exit this function and come back later.
* This function must be called until state is no longer SENDING.
*/
-int mbedtls_ssl_resend( mbedtls_ssl_context *ssl )
+int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl )
{
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_resend" ) );
+ int ret;
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_flight_transmit" ) );
if( ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING )
{
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialise resending" ) );
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialise flight transmission" ) );
ssl->handshake->cur_msg = ssl->handshake->flight;
+ ssl->handshake->cur_msg_p = ssl->handshake->flight->p + 12;
ssl_swap_epochs( ssl );
ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_SENDING;
@@ -2843,33 +2964,129 @@ int mbedtls_ssl_resend( mbedtls_ssl_context *ssl )
while( ssl->handshake->cur_msg != NULL )
{
- int ret;
- mbedtls_ssl_flight_item *cur = ssl->handshake->cur_msg;
+ size_t max_frag_len;
+ const mbedtls_ssl_flight_item * const cur = ssl->handshake->cur_msg;
+
+ int const is_finished =
+ ( cur->type == MBEDTLS_SSL_MSG_HANDSHAKE &&
+ cur->p[0] == MBEDTLS_SSL_HS_FINISHED );
+
+ uint8_t const force_flush = ssl->disable_datagram_packing == 1 ?
+ SSL_FORCE_FLUSH : SSL_DONT_FORCE_FLUSH;
/* Swap epochs before sending Finished: we can't do it after
* sending ChangeCipherSpec, in case write returns WANT_READ.
* Must be done before copying, may change out_msg pointer */
- if( cur->type == MBEDTLS_SSL_MSG_HANDSHAKE &&
- cur->p[0] == MBEDTLS_SSL_HS_FINISHED )
+ if( is_finished && ssl->handshake->cur_msg_p == ( cur->p + 12 ) )
{
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "swap epochs to send finished message" ) );
ssl_swap_epochs( ssl );
}
- memcpy( ssl->out_msg, cur->p, cur->len );
- ssl->out_msglen = cur->len;
- ssl->out_msgtype = cur->type;
+ ret = ssl_get_remaining_payload_in_datagram( ssl );
+ if( ret < 0 )
+ return( ret );
+ max_frag_len = (size_t) ret;
+
+ /* CCS is copied as is, while HS messages may need fragmentation */
+ if( cur->type == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC )
+ {
+ if( max_frag_len == 0 )
+ {
+ if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
+ return( ret );
+
+ continue;
+ }
+
+ memcpy( ssl->out_msg, cur->p, cur->len );
+ ssl->out_msglen = cur->len;
+ ssl->out_msgtype = cur->type;
+
+ /* Update position inside current message */
+ ssl->handshake->cur_msg_p += cur->len;
+ }
+ else
+ {
+ const unsigned char * const p = ssl->handshake->cur_msg_p;
+ const size_t hs_len = cur->len - 12;
+ const size_t frag_off = p - ( cur->p + 12 );
+ const size_t rem_len = hs_len - frag_off;
+ size_t cur_hs_frag_len, max_hs_frag_len;
- ssl->handshake->cur_msg = cur->next;
+ if( ( max_frag_len < 12 ) || ( max_frag_len == 12 && hs_len != 0 ) )
+ {
+ if( is_finished )
+ ssl_swap_epochs( ssl );
- MBEDTLS_SSL_DEBUG_BUF( 3, "resent handshake message header", ssl->out_msg, 12 );
+ if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
+ return( ret );
+
+ continue;
+ }
+ max_hs_frag_len = max_frag_len - 12;
+
+ cur_hs_frag_len = rem_len > max_hs_frag_len ?
+ max_hs_frag_len : rem_len;
+
+ if( frag_off == 0 && cur_hs_frag_len != hs_len )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "fragmenting handshake message (%u > %u)",
+ (unsigned) cur_hs_frag_len,
+ (unsigned) max_hs_frag_len ) );
+ }
+
+ /* Messages are stored with handshake headers as if not fragmented,
+ * copy beginning of headers then fill fragmentation fields.
+ * Handshake headers: type(1) len(3) seq(2) f_off(3) f_len(3) */
+ memcpy( ssl->out_msg, cur->p, 6 );
+
+ ssl->out_msg[6] = ( ( frag_off >> 16 ) & 0xff );
+ ssl->out_msg[7] = ( ( frag_off >> 8 ) & 0xff );
+ ssl->out_msg[8] = ( ( frag_off ) & 0xff );
+
+ ssl->out_msg[ 9] = ( ( cur_hs_frag_len >> 16 ) & 0xff );
+ ssl->out_msg[10] = ( ( cur_hs_frag_len >> 8 ) & 0xff );
+ ssl->out_msg[11] = ( ( cur_hs_frag_len ) & 0xff );
+
+ MBEDTLS_SSL_DEBUG_BUF( 3, "handshake header", ssl->out_msg, 12 );
+
+ /* Copy the handshake message content and set records fields */
+ memcpy( ssl->out_msg + 12, p, cur_hs_frag_len );
+ ssl->out_msglen = cur_hs_frag_len + 12;
+ ssl->out_msgtype = cur->type;
+
+ /* Update position inside current message */
+ ssl->handshake->cur_msg_p += cur_hs_frag_len;
+ }
+
+ /* If done with the current message move to the next one if any */
+ if( ssl->handshake->cur_msg_p >= cur->p + cur->len )
+ {
+ if( cur->next != NULL )
+ {
+ ssl->handshake->cur_msg = cur->next;
+ ssl->handshake->cur_msg_p = cur->next->p + 12;
+ }
+ else
+ {
+ ssl->handshake->cur_msg = NULL;
+ ssl->handshake->cur_msg_p = NULL;
+ }
+ }
- if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+ /* Actually send the message out */
+ if( ( ret = mbedtls_ssl_write_record( ssl, force_flush ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
return( ret );
}
}
+ if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
+ return( ret );
+
+ /* Update state and set timer */
if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER )
ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED;
else
@@ -2878,7 +3095,7 @@ int mbedtls_ssl_resend( mbedtls_ssl_context *ssl )
ssl_set_timer( ssl, ssl->handshake->retransmit_timeout );
}
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_resend" ) );
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_flight_transmit" ) );
return( 0 );
}
@@ -2896,6 +3113,12 @@ void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl )
/* The next incoming flight will start with this msg_seq */
ssl->handshake->in_flight_start_seq = ssl->handshake->in_msg_seq;
+ /* We don't want to remember CCS's across flight boundaries. */
+ ssl->handshake->buffering.seen_ccs = 0;
+
+ /* Clear future message buffering structure. */
+ ssl_buffering_free( ssl );
+
/* Cancel timer */
ssl_set_timer( ssl, 0 );
@@ -2927,43 +3150,102 @@ void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl )
#endif /* MBEDTLS_SSL_PROTO_DTLS */
/*
- * Record layer functions
+ * Handshake layer functions
*/
/*
- * Write current record.
- * Uses ssl->out_msgtype, ssl->out_msglen and bytes at ssl->out_msg.
+ * Write (DTLS: or queue) current handshake (including CCS) message.
+ *
+ * - fill in handshake headers
+ * - update handshake checksum
+ * - DTLS: save message for resending
+ * - then pass to the record layer
+ *
+ * DTLS: except for HelloRequest, messages are only queued, and will only be
+ * actually sent when calling flight_transmit() or resend().
+ *
+ * Inputs:
+ * - ssl->out_msglen: 4 + actual handshake message len
+ * (4 is the size of handshake headers for TLS)
+ * - ssl->out_msg[0]: the handshake type (ClientHello, ServerHello, etc)
+ * - ssl->out_msg + 4: the handshake message body
+ *
+ * Outputs, ie state before passing to flight_append() or write_record():
+ * - ssl->out_msglen: the length of the record contents
+ * (including handshake headers but excluding record headers)
+ * - ssl->out_msg: the record contents (handshake headers + content)
*/
-int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl )
+int mbedtls_ssl_write_handshake_msg( mbedtls_ssl_context *ssl )
{
- int ret, done = 0, out_msg_type;
- size_t len = ssl->out_msglen;
+ int ret;
+ const size_t hs_len = ssl->out_msglen - 4;
+ const unsigned char hs_type = ssl->out_msg[0];
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write record" ) );
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write handshake message" ) );
+
+ /*
+ * Sanity checks
+ */
+ if( ssl->out_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE &&
+ ssl->out_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC )
+ {
+ /* In SSLv3, the client might send a NoCertificate alert. */
+#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_CLI_C)
+ if( ! ( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 &&
+ ssl->out_msgtype == MBEDTLS_SSL_MSG_ALERT &&
+ ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) )
+#endif /* MBEDTLS_SSL_PROTO_SSL3 && MBEDTLS_SSL_SRV_C */
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+ }
+
+ /* Whenever we send anything different from a
+ * HelloRequest we should be in a handshake - double check. */
+ if( ! ( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
+ hs_type == MBEDTLS_SSL_HS_HELLO_REQUEST ) &&
+ ssl->handshake == NULL )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
#if defined(MBEDTLS_SSL_PROTO_DTLS)
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
ssl->handshake != NULL &&
ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING )
{
- ; /* Skip special handshake treatment when resending */
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
- else
#endif
- if( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE )
- {
- out_msg_type = ssl->out_msg[0];
- if( out_msg_type != MBEDTLS_SSL_HS_HELLO_REQUEST &&
- ssl->handshake == NULL )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
+ /* Double-check that we did not exceed the bounds
+ * of the outgoing record buffer.
+ * This should never fail as the various message
+ * writing functions must obey the bounds of the
+ * outgoing record buffer, but better be safe.
+ *
+ * Note: We deliberately do not check for the MTU or MFL here.
+ */
+ if( ssl->out_msglen > MBEDTLS_SSL_OUT_CONTENT_LEN )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record too large: "
+ "size %u, maximum %u",
+ (unsigned) ssl->out_msglen,
+ (unsigned) MBEDTLS_SSL_OUT_CONTENT_LEN ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
- ssl->out_msg[1] = (unsigned char)( ( len - 4 ) >> 16 );
- ssl->out_msg[2] = (unsigned char)( ( len - 4 ) >> 8 );
- ssl->out_msg[3] = (unsigned char)( ( len - 4 ) );
+ /*
+ * Fill handshake headers
+ */
+ if( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE )
+ {
+ ssl->out_msg[1] = (unsigned char)( hs_len >> 16 );
+ ssl->out_msg[2] = (unsigned char)( hs_len >> 8 );
+ ssl->out_msg[3] = (unsigned char)( hs_len );
/*
* DTLS has additional fields in the Handshake layer,
@@ -2980,17 +3262,16 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS handshake message too large: "
"size %u, maximum %u",
- (unsigned) ( ssl->in_hslen - 4 ),
+ (unsigned) ( hs_len ),
(unsigned) ( MBEDTLS_SSL_OUT_CONTENT_LEN - 12 ) ) );
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
}
- memmove( ssl->out_msg + 12, ssl->out_msg + 4, len - 4 );
+ memmove( ssl->out_msg + 12, ssl->out_msg + 4, hs_len );
ssl->out_msglen += 8;
- len += 8;
/* Write message_seq and update it, except for HelloRequest */
- if( out_msg_type != MBEDTLS_SSL_HS_HELLO_REQUEST )
+ if( hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST )
{
ssl->out_msg[4] = ( ssl->handshake->out_msg_seq >> 8 ) & 0xFF;
ssl->out_msg[5] = ( ssl->handshake->out_msg_seq ) & 0xFF;
@@ -3002,23 +3283,23 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl )
ssl->out_msg[5] = 0;
}
- /* We don't fragment, so frag_offset = 0 and frag_len = len */
+ /* Handshake hashes are computed without fragmentation,
+ * so set frag_offset = 0 and frag_len = hs_len for now */
memset( ssl->out_msg + 6, 0x00, 3 );
memcpy( ssl->out_msg + 9, ssl->out_msg + 1, 3 );
}
#endif /* MBEDTLS_SSL_PROTO_DTLS */
- if( out_msg_type != MBEDTLS_SSL_HS_HELLO_REQUEST )
- ssl->handshake->update_checksum( ssl, ssl->out_msg, len );
+ /* Update running hashes of handshake messages seen */
+ if( hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST )
+ ssl->handshake->update_checksum( ssl, ssl->out_msg, ssl->out_msglen );
}
- /* Save handshake and CCS messages for resending */
+ /* Either send now, or just save to be sent (and resent) later */
#if defined(MBEDTLS_SSL_PROTO_DTLS)
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
- ssl->handshake != NULL &&
- ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING &&
- ( ssl->out_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ||
- ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) )
+ ! ( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
+ hs_type == MBEDTLS_SSL_HS_HELLO_REQUEST ) )
{
if( ( ret = ssl_flight_append( ssl ) ) != 0 )
{
@@ -3026,7 +3307,40 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl )
return( ret );
}
}
+ else
#endif
+ {
+ if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+ return( ret );
+ }
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write handshake message" ) );
+
+ return( 0 );
+}
+
+/*
+ * Record layer functions
+ */
+
+/*
+ * Write current record.
+ *
+ * Uses:
+ * - ssl->out_msgtype: type of the message (AppData, Handshake, Alert, CCS)
+ * - ssl->out_msglen: length of the record content (excl headers)
+ * - ssl->out_msg: record content
+ */
+int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl, uint8_t force_flush )
+{
+ int ret, done = 0;
+ size_t len = ssl->out_msglen;
+ uint8_t flush = force_flush;
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write record" ) );
#if defined(MBEDTLS_ZLIB_SUPPORT)
if( ssl->transform_out != NULL &&
@@ -3060,10 +3374,14 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl )
#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */
if( !done )
{
+ unsigned i;
+ size_t protected_record_size;
+
ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype;
mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver,
ssl->conf->transport, ssl->out_hdr + 1 );
+ memcpy( ssl->out_ctr, ssl->cur_out_ctr, 8 );
ssl->out_len[0] = (unsigned char)( len >> 8 );
ssl->out_len[1] = (unsigned char)( len );
@@ -3080,18 +3398,76 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl )
ssl->out_len[1] = (unsigned char)( len );
}
- ssl->out_left = mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen;
+ protected_record_size = len + mbedtls_ssl_hdr_len( ssl );
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ /* In case of DTLS, double-check that we don't exceed
+ * the remaining space in the datagram. */
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ {
+ ret = ssl_get_remaining_space_in_datagram( ssl );
+ if( ret < 0 )
+ return( ret );
+
+ if( protected_record_size > (size_t) ret )
+ {
+ /* Should never happen */
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+ }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
MBEDTLS_SSL_DEBUG_MSG( 3, ( "output record: msgtype = %d, "
- "version = [%d:%d], msglen = %d",
- ssl->out_hdr[0], ssl->out_hdr[1], ssl->out_hdr[2],
- ( ssl->out_len[0] << 8 ) | ssl->out_len[1] ) );
+ "version = [%d:%d], msglen = %d",
+ ssl->out_hdr[0], ssl->out_hdr[1],
+ ssl->out_hdr[2], len ) );
MBEDTLS_SSL_DEBUG_BUF( 4, "output record sent to network",
- ssl->out_hdr, mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen );
+ ssl->out_hdr, protected_record_size );
+
+ ssl->out_left += protected_record_size;
+ ssl->out_hdr += protected_record_size;
+ ssl_update_out_pointers( ssl, ssl->transform_out );
+
+ for( i = 8; i > ssl_ep_len( ssl ); i-- )
+ if( ++ssl->cur_out_ctr[i - 1] != 0 )
+ break;
+
+ /* The loop goes to its end iff the counter is wrapping */
+ if( i == ssl_ep_len( ssl ) )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "outgoing message counter would wrap" ) );
+ return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING );
+ }
}
- if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+ flush == SSL_DONT_FORCE_FLUSH )
+ {
+ size_t remaining;
+ ret = ssl_get_remaining_payload_in_datagram( ssl );
+ if( ret < 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_remaining_payload_in_datagram",
+ ret );
+ return( ret );
+ }
+
+ remaining = (size_t) ret;
+ if( remaining == 0 )
+ {
+ flush = SSL_FORCE_FLUSH;
+ }
+ else
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Still %u bytes available in current datagram", (unsigned) remaining ) );
+ }
+ }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+ if( ( flush == SSL_FORCE_FLUSH ) &&
+ ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret );
return( ret );
@@ -3103,6 +3479,52 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl )
}
#if defined(MBEDTLS_SSL_PROTO_DTLS)
+
+static int ssl_hs_is_proper_fragment( mbedtls_ssl_context *ssl )
+{
+ if( ssl->in_msglen < ssl->in_hslen ||
+ memcmp( ssl->in_msg + 6, "\0\0\0", 3 ) != 0 ||
+ memcmp( ssl->in_msg + 9, ssl->in_msg + 1, 3 ) != 0 )
+ {
+ return( 1 );
+ }
+ return( 0 );
+}
+
+static uint32_t ssl_get_hs_frag_len( mbedtls_ssl_context const *ssl )
+{
+ return( ( ssl->in_msg[9] << 16 ) |
+ ( ssl->in_msg[10] << 8 ) |
+ ssl->in_msg[11] );
+}
+
+static uint32_t ssl_get_hs_frag_off( mbedtls_ssl_context const *ssl )
+{
+ return( ( ssl->in_msg[6] << 16 ) |
+ ( ssl->in_msg[7] << 8 ) |
+ ssl->in_msg[8] );
+}
+
+static int ssl_check_hs_header( mbedtls_ssl_context const *ssl )
+{
+ uint32_t msg_len, frag_off, frag_len;
+
+ msg_len = ssl_get_hs_total_len( ssl );
+ frag_off = ssl_get_hs_frag_off( ssl );
+ frag_len = ssl_get_hs_frag_len( ssl );
+
+ if( frag_off > msg_len )
+ return( -1 );
+
+ if( frag_len > msg_len - frag_off )
+ return( -1 );
+
+ if( frag_len + 12 > ssl->in_msglen )
+ return( -1 );
+
+ return( 0 );
+}
+
/*
* Mark bits in bitmask (used for DTLS HS reassembly)
*/
@@ -3164,161 +3586,29 @@ static int ssl_bitmask_check( unsigned char *mask, size_t len )
return( 0 );
}
-/*
- * Reassemble fragmented DTLS handshake messages.
- *
- * Use a temporary buffer for reassembly, divided in two parts:
- * - the first holds the reassembled message (including handshake header),
- * - the second holds a bitmask indicating which parts of the message
- * (excluding headers) have been received so far.
- */
-static int ssl_reassemble_dtls_handshake( mbedtls_ssl_context *ssl )
+/* msg_len does not include the handshake header */
+static size_t ssl_get_reassembly_buffer_size( size_t msg_len,
+ unsigned add_bitmap )
{
- unsigned char *msg, *bitmask;
- size_t frag_len, frag_off;
- size_t msg_len = ssl->in_hslen - 12; /* Without headers */
-
- if( ssl->handshake == NULL )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "not supported outside handshake (for now)" ) );
- return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
- }
-
- /*
- * For first fragment, check size and allocate buffer
- */
- if( ssl->handshake->hs_msg == NULL )
- {
- size_t alloc_len;
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialize reassembly, total length = %d",
- msg_len ) );
-
- if( ssl->in_hslen > MBEDTLS_SSL_IN_CONTENT_LEN )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake message too large" ) );
- return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
- }
-
- /* The bitmask needs one bit per byte of message excluding header */
- alloc_len = 12 + msg_len + msg_len / 8 + ( msg_len % 8 != 0 );
-
- ssl->handshake->hs_msg = mbedtls_calloc( 1, alloc_len );
- if( ssl->handshake->hs_msg == NULL )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc failed (%d bytes)", alloc_len ) );
- return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
- }
-
- /* Prepare final header: copy msg_type, length and message_seq,
- * then add standardised fragment_offset and fragment_length */
- memcpy( ssl->handshake->hs_msg, ssl->in_msg, 6 );
- memset( ssl->handshake->hs_msg + 6, 0, 3 );
- memcpy( ssl->handshake->hs_msg + 9,
- ssl->handshake->hs_msg + 1, 3 );
- }
- else
- {
- /* Make sure msg_type and length are consistent */
- if( memcmp( ssl->handshake->hs_msg, ssl->in_msg, 4 ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "fragment header mismatch" ) );
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
- }
- }
-
- msg = ssl->handshake->hs_msg + 12;
- bitmask = msg + msg_len;
-
- /*
- * Check and copy current fragment
- */
- frag_off = ( ssl->in_msg[6] << 16 ) |
- ( ssl->in_msg[7] << 8 ) |
- ssl->in_msg[8];
- frag_len = ( ssl->in_msg[9] << 16 ) |
- ( ssl->in_msg[10] << 8 ) |
- ssl->in_msg[11];
-
- if( frag_off + frag_len > msg_len )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid fragment offset/len: %d + %d > %d",
- frag_off, frag_len, msg_len ) );
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
- }
-
- if( frag_len + 12 > ssl->in_msglen )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid fragment length: %d + 12 > %d",
- frag_len, ssl->in_msglen ) );
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
- }
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "adding fragment, offset = %d, length = %d",
- frag_off, frag_len ) );
-
- memcpy( msg + frag_off, ssl->in_msg + 12, frag_len );
- ssl_bitmask_set( bitmask, frag_off, frag_len );
-
- /*
- * Do we have the complete message by now?
- * If yes, finalize it, else ask to read the next record.
- */
- if( ssl_bitmask_check( bitmask, msg_len ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "message is not complete yet" ) );
- return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING );
- }
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake message completed" ) );
-
- if( frag_len + 12 < ssl->in_msglen )
- {
- /*
- * We'got more handshake messages in the same record.
- * This case is not handled now because no know implementation does
- * that and it's hard to test, so we prefer to fail cleanly for now.
- */
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "last fragment not alone in its record" ) );
- return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
- }
-
- if( ssl->in_left > ssl->next_record_offset )
- {
- /*
- * We've got more data in the buffer after the current record,
- * that we don't want to overwrite. Move it before writing the
- * reassembled message, and adjust in_left and next_record_offset.
- */
- unsigned char *cur_remain = ssl->in_hdr + ssl->next_record_offset;
- unsigned char *new_remain = ssl->in_msg + ssl->in_hslen;
- size_t remain_len = ssl->in_left - ssl->next_record_offset;
-
- /* First compute and check new lengths */
- ssl->next_record_offset = new_remain - ssl->in_hdr;
- ssl->in_left = ssl->next_record_offset + remain_len;
-
- if( ssl->in_left > MBEDTLS_SSL_IN_BUFFER_LEN -
- (size_t)( ssl->in_hdr - ssl->in_buf ) )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "reassembled message too large for buffer" ) );
- return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
- }
+ size_t alloc_len;
- memmove( new_remain, cur_remain, remain_len );
- }
+ alloc_len = 12; /* Handshake header */
+ alloc_len += msg_len; /* Content buffer */
- memcpy( ssl->in_msg, ssl->handshake->hs_msg, ssl->in_hslen );
+ if( add_bitmap )
+ alloc_len += msg_len / 8 + ( msg_len % 8 != 0 ); /* Bitmap */
- mbedtls_free( ssl->handshake->hs_msg );
- ssl->handshake->hs_msg = NULL;
+ return( alloc_len );
+}
- MBEDTLS_SSL_DEBUG_BUF( 3, "reassembled handshake message",
- ssl->in_msg, ssl->in_hslen );
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
- return( 0 );
+static uint32_t ssl_get_hs_total_len( mbedtls_ssl_context const *ssl )
+{
+ return( ( ssl->in_msg[1] << 16 ) |
+ ( ssl->in_msg[2] << 8 ) |
+ ssl->in_msg[3] );
}
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl )
{
@@ -3329,10 +3619,7 @@ int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
}
- ssl->in_hslen = mbedtls_ssl_hs_hdr_len( ssl ) + (
- ( ssl->in_msg[1] << 16 ) |
- ( ssl->in_msg[2] << 8 ) |
- ssl->in_msg[3] );
+ ssl->in_hslen = mbedtls_ssl_hs_hdr_len( ssl ) + ssl_get_hs_total_len( ssl );
MBEDTLS_SSL_DEBUG_MSG( 3, ( "handshake message: msglen ="
" %d, type = %d, hslen = %d",
@@ -3344,12 +3631,26 @@ int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl )
int ret;
unsigned int recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5];
+ if( ssl_check_hs_header( ssl ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid handshake header" ) );
+ return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ }
+
if( ssl->handshake != NULL &&
( ( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER &&
recv_msg_seq != ssl->handshake->in_msg_seq ) ||
( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER &&
ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) ) )
{
+ if( recv_msg_seq > ssl->handshake->in_msg_seq )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "received future handshake message of sequence number %u (next %u)",
+ recv_msg_seq,
+ ssl->handshake->in_msg_seq ) );
+ return( MBEDTLS_ERR_SSL_EARLY_MESSAGE );
+ }
+
/* Retransmit only on last message from previous flight, to avoid
* too many retransmissions.
* Besides, No sane server ever retransmits HelloVerifyRequest */
@@ -3379,20 +3680,14 @@ int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl )
}
/* Wait until message completion to increment in_msg_seq */
- /* Reassemble if current message is fragmented or reassembly is
- * already in progress */
- if( ssl->in_msglen < ssl->in_hslen ||
- memcmp( ssl->in_msg + 6, "\0\0\0", 3 ) != 0 ||
- memcmp( ssl->in_msg + 9, ssl->in_msg + 1, 3 ) != 0 ||
- ( ssl->handshake != NULL && ssl->handshake->hs_msg != NULL ) )
+ /* Message reassembly is handled alongside buffering of future
+ * messages; the commonality is that both handshake fragments and
+ * future messages cannot be forwarded immediately to the
+ * handshake logic layer. */
+ if( ssl_hs_is_proper_fragment( ssl ) == 1 )
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "found fragmented DTLS handshake message" ) );
-
- if( ( ret = ssl_reassemble_dtls_handshake( ssl ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "ssl_reassemble_dtls_handshake", ret );
- return( ret );
- }
+ return( MBEDTLS_ERR_SSL_EARLY_MESSAGE );
}
}
else
@@ -3409,9 +3704,9 @@ int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl )
void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl )
{
+ mbedtls_ssl_handshake_params * const hs = ssl->handshake;
- if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER &&
- ssl->handshake != NULL )
+ if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && hs != NULL )
{
ssl->handshake->update_checksum( ssl, ssl->in_msg, ssl->in_hslen );
}
@@ -3421,7 +3716,29 @@ void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl )
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
ssl->handshake != NULL )
{
- ssl->handshake->in_msg_seq++;
+ unsigned offset;
+ mbedtls_ssl_hs_buffer *hs_buf;
+
+ /* Increment handshake sequence number */
+ hs->in_msg_seq++;
+
+ /*
+ * Clear up handshake buffering and reassembly structure.
+ */
+
+ /* Free first entry */
+ ssl_buffering_free_slot( ssl, 0 );
+
+ /* Shift all other entries */
+ for( offset = 0, hs_buf = &hs->buffering.hs[0];
+ offset + 1 < MBEDTLS_SSL_MAX_BUFFERED_HS;
+ offset++, hs_buf++ )
+ {
+ *hs_buf = *(hs_buf + 1);
+ }
+
+ /* Create a fresh last entry */
+ memset( hs_buf, 0, sizeof( mbedtls_ssl_hs_buffer ) );
}
#endif
}
@@ -3822,7 +4139,16 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl )
}
else
#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */
+ {
+ /* Consider buffering the record. */
+ if( rec_epoch == (unsigned int) ssl->in_epoch + 1 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Consider record for buffering" ) );
+ return( MBEDTLS_ERR_SSL_EARLY_MESSAGE );
+ }
+
return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
+ }
}
#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
@@ -3835,15 +4161,6 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl )
}
#endif
- /* Drop unexpected ChangeCipherSpec messages */
- if( ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC &&
- ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC &&
- ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ChangeCipherSpec" ) );
- return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
- }
-
/* Drop unexpected ApplicationData records,
* except at the beginning of renegotiations */
if( ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA &&
@@ -3980,7 +4297,14 @@ static void ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl );
* RFC 6347 4.1.2.7) and continue reading until a valid record is found.
*
*/
-int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl )
+
+/* Helper functions for mbedtls_ssl_read_record(). */
+static int ssl_consume_current_message( mbedtls_ssl_context *ssl );
+static int ssl_get_next_record( mbedtls_ssl_context *ssl );
+static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl );
+
+int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl,
+ unsigned update_hs_digest )
{
int ret;
@@ -3990,17 +4314,53 @@ int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl )
{
do {
- do ret = mbedtls_ssl_read_record_layer( ssl );
- while( ret == MBEDTLS_ERR_SSL_CONTINUE_PROCESSING );
-
+ ret = ssl_consume_current_message( ssl );
if( ret != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret );
return( ret );
+
+ if( ssl_record_is_in_progress( ssl ) == 0 )
+ {
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ int have_buffered = 0;
+
+ /* We only check for buffered messages if the
+ * current datagram is fully consumed. */
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+ ssl_next_record_is_in_datagram( ssl ) == 0 )
+ {
+ if( ssl_load_buffered_message( ssl ) == 0 )
+ have_buffered = 1;
+ }
+
+ if( have_buffered == 0 )
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+ {
+ ret = ssl_get_next_record( ssl );
+ if( ret == MBEDTLS_ERR_SSL_CONTINUE_PROCESSING )
+ continue;
+
+ if( ret != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_get_next_record" ), ret );
+ return( ret );
+ }
+ }
}
ret = mbedtls_ssl_handle_message_type( ssl );
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE )
+ {
+ /* Buffer future message */
+ ret = ssl_buffer_message( ssl );
+ if( ret != 0 )
+ return( ret );
+
+ ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING;
+ }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
} while( MBEDTLS_ERR_SSL_NON_FATAL == ret ||
MBEDTLS_ERR_SSL_CONTINUE_PROCESSING == ret );
@@ -4010,14 +4370,15 @@ int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl )
return( ret );
}
- if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE )
+ if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
+ update_hs_digest == 1 )
{
mbedtls_ssl_update_handshake_status( ssl );
}
}
else
{
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= reuse previously read message" ) );
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "reuse previously read message" ) );
ssl->keep_current_message = 0;
}
@@ -4026,13 +4387,350 @@ int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl )
return( 0 );
}
-int mbedtls_ssl_read_record_layer( mbedtls_ssl_context *ssl )
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl )
{
- int ret;
+ if( ssl->in_left > ssl->next_record_offset )
+ return( 1 );
+
+ return( 0 );
+}
+
+static int ssl_load_buffered_message( mbedtls_ssl_context *ssl )
+{
+ mbedtls_ssl_handshake_params * const hs = ssl->handshake;
+ mbedtls_ssl_hs_buffer * hs_buf;
+ int ret = 0;
+
+ if( hs == NULL )
+ return( -1 );
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_messsage" ) );
+
+ if( ssl->state == MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC ||
+ ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC )
+ {
+ /* Check if we have seen a ChangeCipherSpec before.
+ * If yes, synthesize a CCS record. */
+ if( !hs->buffering.seen_ccs )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "CCS not seen in the current flight" ) );
+ ret = -1;
+ goto exit;
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Injecting buffered CCS message" ) );
+ ssl->in_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC;
+ ssl->in_msglen = 1;
+ ssl->in_msg[0] = 1;
+
+ /* As long as they are equal, the exact value doesn't matter. */
+ ssl->in_left = 0;
+ ssl->next_record_offset = 0;
+
+ hs->buffering.seen_ccs = 0;
+ goto exit;
+ }
+
+#if defined(MBEDTLS_DEBUG_C)
+ /* Debug only */
+ {
+ unsigned offset;
+ for( offset = 1; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++ )
+ {
+ hs_buf = &hs->buffering.hs[offset];
+ if( hs_buf->is_valid == 1 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Future message with sequence number %u %s buffered.",
+ hs->in_msg_seq + offset,
+ hs_buf->is_complete ? "fully" : "partially" ) );
+ }
+ }
+ }
+#endif /* MBEDTLS_DEBUG_C */
+
+ /* Check if we have buffered and/or fully reassembled the
+ * next handshake message. */
+ hs_buf = &hs->buffering.hs[0];
+ if( ( hs_buf->is_valid == 1 ) && ( hs_buf->is_complete == 1 ) )
+ {
+ /* Synthesize a record containing the buffered HS message. */
+ size_t msg_len = ( hs_buf->data[1] << 16 ) |
+ ( hs_buf->data[2] << 8 ) |
+ hs_buf->data[3];
+
+ /* Double-check that we haven't accidentally buffered
+ * a message that doesn't fit into the input buffer. */
+ if( msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Next handshake message has been buffered - load" ) );
+ MBEDTLS_SSL_DEBUG_BUF( 3, "Buffered handshake message (incl. header)",
+ hs_buf->data, msg_len + 12 );
+
+ ssl->in_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
+ ssl->in_hslen = msg_len + 12;
+ ssl->in_msglen = msg_len + 12;
+ memcpy( ssl->in_msg, hs_buf->data, ssl->in_hslen );
+
+ ret = 0;
+ goto exit;
+ }
+ else
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Next handshake message %u not or only partially bufffered",
+ hs->in_msg_seq ) );
+ }
+
+ ret = -1;
+
+exit:
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_load_buffered_message" ) );
+ return( ret );
+}
+
+static int ssl_buffer_make_space( mbedtls_ssl_context *ssl,
+ size_t desired )
+{
+ int offset;
+ mbedtls_ssl_handshake_params * const hs = ssl->handshake;
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Attempt to free buffered messages to have %u bytes available",
+ (unsigned) desired ) );
+
+ /* Get rid of future records epoch first, if such exist. */
+ ssl_free_buffered_record( ssl );
+
+ /* Check if we have enough space available now. */
+ if( desired <= ( MBEDTLS_SSL_DTLS_MAX_BUFFERING -
+ hs->buffering.total_bytes_buffered ) )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Enough space available after freeing future epoch record" ) );
+ return( 0 );
+ }
+
+ /* We don't have enough space to buffer the next expected handshake
+ * message. Remove buffers used for future messages to gain space,
+ * starting with the most distant one. */
+ for( offset = MBEDTLS_SSL_MAX_BUFFERED_HS - 1;
+ offset >= 0; offset-- )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Free buffering slot %d to make space for reassembly of next handshake message",
+ offset ) );
+
+ ssl_buffering_free_slot( ssl, (uint8_t) offset );
+
+ /* Check if we have enough space available now. */
+ if( desired <= ( MBEDTLS_SSL_DTLS_MAX_BUFFERING -
+ hs->buffering.total_bytes_buffered ) )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Enough space available after freeing buffered HS messages" ) );
+ return( 0 );
+ }
+ }
+
+ return( -1 );
+}
+
+static int ssl_buffer_message( mbedtls_ssl_context *ssl )
+{
+ int ret = 0;
+ mbedtls_ssl_handshake_params * const hs = ssl->handshake;
+
+ if( hs == NULL )
+ return( 0 );
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_buffer_message" ) );
+
+ switch( ssl->in_msgtype )
+ {
+ case MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC:
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Remember CCS message" ) );
+
+ hs->buffering.seen_ccs = 1;
+ break;
+
+ case MBEDTLS_SSL_MSG_HANDSHAKE:
+ {
+ unsigned recv_msg_seq_offset;
+ unsigned recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5];
+ mbedtls_ssl_hs_buffer *hs_buf;
+ size_t msg_len = ssl->in_hslen - 12;
+
+ /* We should never receive an old handshake
+ * message - double-check nonetheless. */
+ if( recv_msg_seq < ssl->handshake->in_msg_seq )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+ recv_msg_seq_offset = recv_msg_seq - ssl->handshake->in_msg_seq;
+ if( recv_msg_seq_offset >= MBEDTLS_SSL_MAX_BUFFERED_HS )
+ {
+ /* Silently ignore -- message too far in the future */
+ MBEDTLS_SSL_DEBUG_MSG( 2,
+ ( "Ignore future HS message with sequence number %u, "
+ "buffering window %u - %u",
+ recv_msg_seq, ssl->handshake->in_msg_seq,
+ ssl->handshake->in_msg_seq + MBEDTLS_SSL_MAX_BUFFERED_HS - 1 ) );
+
+ goto exit;
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering HS message with sequence number %u, offset %u ",
+ recv_msg_seq, recv_msg_seq_offset ) );
+
+ hs_buf = &hs->buffering.hs[ recv_msg_seq_offset ];
+
+ /* Check if the buffering for this seq nr has already commenced. */
+ if( !hs_buf->is_valid )
+ {
+ size_t reassembly_buf_sz;
+
+ hs_buf->is_fragmented =
+ ( ssl_hs_is_proper_fragment( ssl ) == 1 );
+
+ /* We copy the message back into the input buffer
+ * after reassembly, so check that it's not too large.
+ * This is an implementation-specific limitation
+ * and not one from the standard, hence it is not
+ * checked in ssl_check_hs_header(). */
+ if( msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN )
+ {
+ /* Ignore message */
+ goto exit;
+ }
+ /* Check if we have enough space to buffer the message. */
+ if( hs->buffering.total_bytes_buffered >
+ MBEDTLS_SSL_DTLS_MAX_BUFFERING )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+ reassembly_buf_sz = ssl_get_reassembly_buffer_size( msg_len,
+ hs_buf->is_fragmented );
+
+ if( reassembly_buf_sz > ( MBEDTLS_SSL_DTLS_MAX_BUFFERING -
+ hs->buffering.total_bytes_buffered ) )
+ {
+ if( recv_msg_seq_offset > 0 )
+ {
+ /* If we can't buffer a future message because
+ * of space limitations -- ignore. */
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- ignore\n",
+ (unsigned) msg_len, MBEDTLS_SSL_DTLS_MAX_BUFFERING,
+ (unsigned) hs->buffering.total_bytes_buffered ) );
+ goto exit;
+ }
+ else
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- attempt to make space by freeing buffered future messages\n",
+ (unsigned) msg_len, MBEDTLS_SSL_DTLS_MAX_BUFFERING,
+ (unsigned) hs->buffering.total_bytes_buffered ) );
+ }
+
+ if( ssl_buffer_make_space( ssl, reassembly_buf_sz ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reassembly of next message of size %u (%u with bitmap) would exceed the compile-time limit %u (already %u bytes buffered) -- fail\n",
+ (unsigned) msg_len,
+ (unsigned) reassembly_buf_sz,
+ MBEDTLS_SSL_DTLS_MAX_BUFFERING,
+ (unsigned) hs->buffering.total_bytes_buffered ) );
+ ret = MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
+ goto exit;
+ }
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialize reassembly, total length = %d",
+ msg_len ) );
+
+ hs_buf->data = mbedtls_calloc( 1, reassembly_buf_sz );
+ if( hs_buf->data == NULL )
+ {
+ ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
+ goto exit;
+ }
+ hs_buf->data_len = reassembly_buf_sz;
+
+ /* Prepare final header: copy msg_type, length and message_seq,
+ * then add standardised fragment_offset and fragment_length */
+ memcpy( hs_buf->data, ssl->in_msg, 6 );
+ memset( hs_buf->data + 6, 0, 3 );
+ memcpy( hs_buf->data + 9, hs_buf->data + 1, 3 );
+
+ hs_buf->is_valid = 1;
+
+ hs->buffering.total_bytes_buffered += reassembly_buf_sz;
+ }
+ else
+ {
+ /* Make sure msg_type and length are consistent */
+ if( memcmp( hs_buf->data, ssl->in_msg, 4 ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "Fragment header mismatch - ignore" ) );
+ /* Ignore */
+ goto exit;
+ }
+ }
+
+ if( !hs_buf->is_complete )
+ {
+ size_t frag_len, frag_off;
+ unsigned char * const msg = hs_buf->data + 12;
+
+ /*
+ * Check and copy current fragment
+ */
+
+ /* Validation of header fields already done in
+ * mbedtls_ssl_prepare_handshake_record(). */
+ frag_off = ssl_get_hs_frag_off( ssl );
+ frag_len = ssl_get_hs_frag_len( ssl );
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "adding fragment, offset = %d, length = %d",
+ frag_off, frag_len ) );
+ memcpy( msg + frag_off, ssl->in_msg + 12, frag_len );
+
+ if( hs_buf->is_fragmented )
+ {
+ unsigned char * const bitmask = msg + msg_len;
+ ssl_bitmask_set( bitmask, frag_off, frag_len );
+ hs_buf->is_complete = ( ssl_bitmask_check( bitmask,
+ msg_len ) == 0 );
+ }
+ else
+ {
+ hs_buf->is_complete = 1;
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "message %scomplete",
+ hs_buf->is_complete ? "" : "not yet " ) );
+ }
+
+ break;
+ }
+
+ default:
+ /* We don't buffer other types of messages. */
+ break;
+ }
+
+exit:
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_buffer_message" ) );
+ return( ret );
+}
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+static int ssl_consume_current_message( mbedtls_ssl_context *ssl )
+{
/*
- * Step A
- *
* Consume last content-layer message and potentially
* update in_msglen which keeps track of the contents'
* consumption state.
@@ -4114,20 +4812,161 @@ int mbedtls_ssl_read_record_layer( mbedtls_ssl_context *ssl )
ssl->in_msglen = 0;
}
- /*
- * Step B
- *
- * Fetch and decode new record if current one is fully consumed.
- *
- */
+ return( 0 );
+}
+static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl )
+{
if( ssl->in_msglen > 0 )
+ return( 1 );
+
+ return( 0 );
+}
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+
+static void ssl_free_buffered_record( mbedtls_ssl_context *ssl )
+{
+ mbedtls_ssl_handshake_params * const hs = ssl->handshake;
+ if( hs == NULL )
+ return;
+
+ if( hs->buffering.future_record.data != NULL )
{
- /* There's something left to be processed in the current record. */
+ hs->buffering.total_bytes_buffered -=
+ hs->buffering.future_record.len;
+
+ mbedtls_free( hs->buffering.future_record.data );
+ hs->buffering.future_record.data = NULL;
+ }
+}
+
+static int ssl_load_buffered_record( mbedtls_ssl_context *ssl )
+{
+ mbedtls_ssl_handshake_params * const hs = ssl->handshake;
+ unsigned char * rec;
+ size_t rec_len;
+ unsigned rec_epoch;
+
+ if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ return( 0 );
+
+ if( hs == NULL )
+ return( 0 );
+
+ rec = hs->buffering.future_record.data;
+ rec_len = hs->buffering.future_record.len;
+ rec_epoch = hs->buffering.future_record.epoch;
+
+ if( rec == NULL )
return( 0 );
+
+ /* Only consider loading future records if the
+ * input buffer is empty. */
+ if( ssl_next_record_is_in_datagram( ssl ) == 1 )
+ return( 0 );
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_record" ) );
+
+ if( rec_epoch != ssl->in_epoch )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffered record not from current epoch." ) );
+ goto exit;
}
- /* Current record either fully processed or to be discarded. */
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Found buffered record from current epoch - load" ) );
+
+ /* Double-check that the record is not too large */
+ if( rec_len > MBEDTLS_SSL_IN_BUFFER_LEN -
+ (size_t)( ssl->in_hdr - ssl->in_buf ) )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+ memcpy( ssl->in_hdr, rec, rec_len );
+ ssl->in_left = rec_len;
+ ssl->next_record_offset = 0;
+
+ ssl_free_buffered_record( ssl );
+
+exit:
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_load_buffered_record" ) );
+ return( 0 );
+}
+
+static int ssl_buffer_future_record( mbedtls_ssl_context *ssl )
+{
+ mbedtls_ssl_handshake_params * const hs = ssl->handshake;
+ size_t const rec_hdr_len = 13;
+ size_t const total_buf_sz = rec_hdr_len + ssl->in_msglen;
+
+ /* Don't buffer future records outside handshakes. */
+ if( hs == NULL )
+ return( 0 );
+
+ /* Only buffer handshake records (we are only interested
+ * in Finished messages). */
+ if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE )
+ return( 0 );
+
+ /* Don't buffer more than one future epoch record. */
+ if( hs->buffering.future_record.data != NULL )
+ return( 0 );
+
+ /* Don't buffer record if there's not enough buffering space remaining. */
+ if( total_buf_sz > ( MBEDTLS_SSL_DTLS_MAX_BUFFERING -
+ hs->buffering.total_bytes_buffered ) )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future epoch record of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- ignore\n",
+ (unsigned) total_buf_sz, MBEDTLS_SSL_DTLS_MAX_BUFFERING,
+ (unsigned) hs->buffering.total_bytes_buffered ) );
+ return( 0 );
+ }
+
+ /* Buffer record */
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffer record from epoch %u",
+ ssl->in_epoch + 1 ) );
+ MBEDTLS_SSL_DEBUG_BUF( 3, "Buffered record", ssl->in_hdr,
+ rec_hdr_len + ssl->in_msglen );
+
+ /* ssl_parse_record_header() only considers records
+ * of the next epoch as candidates for buffering. */
+ hs->buffering.future_record.epoch = ssl->in_epoch + 1;
+ hs->buffering.future_record.len = total_buf_sz;
+
+ hs->buffering.future_record.data =
+ mbedtls_calloc( 1, hs->buffering.future_record.len );
+ if( hs->buffering.future_record.data == NULL )
+ {
+ /* If we run out of RAM trying to buffer a
+ * record from the next epoch, just ignore. */
+ return( 0 );
+ }
+
+ memcpy( hs->buffering.future_record.data, ssl->in_hdr, total_buf_sz );
+
+ hs->buffering.total_bytes_buffered += total_buf_sz;
+ return( 0 );
+}
+
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+static int ssl_get_next_record( mbedtls_ssl_context *ssl )
+{
+ int ret;
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ /* We might have buffered a future record; if so,
+ * and if the epoch matches now, load it.
+ * On success, this call will set ssl->in_left to
+ * the length of the buffered record, so that
+ * the calls to ssl_fetch_input() below will
+ * essentially be no-ops. */
+ ret = ssl_load_buffered_record( ssl );
+ if( ret != 0 )
+ return( ret );
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
if( ( ret = mbedtls_ssl_fetch_input( ssl, mbedtls_ssl_hdr_len( ssl ) ) ) != 0 )
{
@@ -4141,6 +4980,16 @@ int mbedtls_ssl_read_record_layer( mbedtls_ssl_context *ssl )
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
ret != MBEDTLS_ERR_SSL_CLIENT_RECONNECT )
{
+ if( ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE )
+ {
+ ret = ssl_buffer_future_record( ssl );
+ if( ret != 0 )
+ return( ret );
+
+ /* Fall through to handling of unexpected records */
+ ret = MBEDTLS_ERR_SSL_UNEXPECTED_RECORD;
+ }
+
if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_RECORD )
{
/* Skip unexpected record (but not whole datagram) */
@@ -4272,6 +5121,39 @@ int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl )
}
}
+ if( ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC )
+ {
+ if( ssl->in_msglen != 1 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid CCS message, len: %d",
+ ssl->in_msglen ) );
+ return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ }
+
+ if( ssl->in_msg[0] != 1 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid CCS message, content: %02x",
+ ssl->in_msg[0] ) );
+ return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ }
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+ ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC &&
+ ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC )
+ {
+ if( ssl->handshake == NULL )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping ChangeCipherSpec outside handshake" ) );
+ return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "received out-of-order ChangeCipherSpec - remember" ) );
+ return( MBEDTLS_ERR_SSL_EARLY_MESSAGE );
+ }
+#endif
+ }
+
if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT )
{
if( ssl->in_msglen != 2 )
@@ -4373,7 +5255,7 @@ int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl,
ssl->out_msg[0] = level;
ssl->out_msg[1] = message;
- if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
return( ret );
@@ -4542,9 +5424,9 @@ write_msg:
ssl->state++;
- if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
{
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
return( ret );
}
@@ -4553,60 +5435,16 @@ write_msg:
return( ret );
}
-int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
+/*
+ * Once the certificate message is read, parse it into a cert chain and
+ * perform basic checks, but leave actual verification to the caller
+ */
+static int ssl_parse_certificate_chain( mbedtls_ssl_context *ssl )
{
- int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+ int ret;
size_t i, n;
- const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
- int authmode = ssl->conf->authmode;
uint8_t alert;
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) );
-
- if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
- ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
- ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
- ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
- ssl->state++;
- return( 0 );
- }
-
-#if defined(MBEDTLS_SSL_SRV_C)
- if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
- ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK )
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
- ssl->state++;
- return( 0 );
- }
-
-#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
- if( ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET )
- authmode = ssl->handshake->sni_authmode;
-#endif
-
- if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
- authmode == MBEDTLS_SSL_VERIFY_NONE )
- {
- ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_SKIP_VERIFY;
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
- ssl->state++;
- return( 0 );
- }
-#endif
-
- if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
- {
- /* mbedtls_ssl_read_record may have sent an alert already. We
- let it decide whether to alert. */
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
- return( ret );
- }
-
- ssl->state++;
-
#if defined(MBEDTLS_SSL_SRV_C)
#if defined(MBEDTLS_SSL_PROTO_SSL3)
/*
@@ -4626,10 +5464,7 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
one. The client should know what's going on, so we
don't send an alert. */
ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING;
- if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL )
- return( 0 );
- else
- return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE );
+ return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE );
}
}
#endif /* MBEDTLS_SSL_PROTO_SSL3 */
@@ -4650,10 +5485,7 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
one. The client should know what's going on, so we
don't send an alert. */
ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING;
- if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL )
- return( 0 );
- else
- return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE );
+ return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE );
}
}
#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
@@ -4803,6 +5635,94 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
}
#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */
+ return( 0 );
+}
+
+int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
+{
+ int ret;
+ const mbedtls_ssl_ciphersuite_t * const ciphersuite_info =
+ ssl->transform_negotiate->ciphersuite_info;
+#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+ const int authmode = ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET
+ ? ssl->handshake->sni_authmode
+ : ssl->conf->authmode;
+#else
+ const int authmode = ssl->conf->authmode;
+#endif
+ void *rs_ctx = NULL;
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) );
+
+ if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
+ ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
+ ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
+ ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
+ ssl->state++;
+ return( 0 );
+ }
+
+#if defined(MBEDTLS_SSL_SRV_C)
+ if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
+ ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
+ ssl->state++;
+ return( 0 );
+ }
+
+ if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
+ authmode == MBEDTLS_SSL_VERIFY_NONE )
+ {
+ ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_SKIP_VERIFY;
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
+
+ ssl->state++;
+ return( 0 );
+ }
+#endif
+
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ if( ssl->handshake->ecrs_enabled &&
+ ssl->handshake->ecrs_state == ssl_ecrs_crt_verify )
+ {
+ goto crt_verify;
+ }
+#endif
+
+ if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
+ {
+ /* mbedtls_ssl_read_record may have sent an alert already. We
+ let it decide whether to alert. */
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
+ return( ret );
+ }
+
+ if( ( ret = ssl_parse_certificate_chain( ssl ) ) != 0 )
+ {
+#if defined(MBEDTLS_SSL_SRV_C)
+ if( ret == MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE &&
+ authmode == MBEDTLS_SSL_VERIFY_OPTIONAL )
+ {
+ ret = 0;
+ }
+#endif
+
+ ssl->state++;
+ return( ret );
+ }
+
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ if( ssl->handshake->ecrs_enabled)
+ ssl->handshake->ecrs_state = ssl_ecrs_crt_verify;
+
+crt_verify:
+ if( ssl->handshake->ecrs_enabled)
+ rs_ctx = &ssl->handshake->ecrs_ctx;
+#endif
+
if( authmode != MBEDTLS_SSL_VERIFY_NONE )
{
mbedtls_x509_crt *ca_chain;
@@ -4824,19 +5744,24 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
/*
* Main check: verify certificate
*/
- ret = mbedtls_x509_crt_verify_with_profile(
+ ret = mbedtls_x509_crt_verify_restartable(
ssl->session_negotiate->peer_cert,
ca_chain, ca_crl,
ssl->conf->cert_profile,
ssl->hostname,
&ssl->session_negotiate->verify_result,
- ssl->conf->f_vrfy, ssl->conf->p_vrfy );
+ ssl->conf->f_vrfy, ssl->conf->p_vrfy, rs_ctx );
if( ret != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "x509_verify_cert", ret );
}
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
+ return( MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS );
+#endif
+
/*
* Secondary checks: always done, but change 'ret' only if it was 0
*/
@@ -4889,6 +5814,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
if( ret != 0 )
{
+ uint8_t alert;
+
/* The certificate may have been rejected for several reasons.
Pick one and send the corresponding alert. Which alert to send
may be a subject of debate in some cases. */
@@ -4931,6 +5858,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
#endif /* MBEDTLS_DEBUG_C */
}
+ ssl->state++;
+
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) );
return( ret );
@@ -4955,9 +5884,9 @@ int mbedtls_ssl_write_change_cipher_spec( mbedtls_ssl_context *ssl )
ssl->state++;
- if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
{
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
return( ret );
}
@@ -4972,7 +5901,7 @@ int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse change cipher spec" ) );
- if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
return( ret );
@@ -4986,13 +5915,8 @@ int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
}
- if( ssl->in_msglen != 1 || ssl->in_msg[0] != 1 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) );
- mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
- MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
- return( MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC );
- }
+ /* CCS records are only accepted if they have length 1 and content '1',
+ * so we don't need to check this here. */
/*
* Switch to our negotiated transform and session parameters for inbound
@@ -5022,16 +5946,7 @@ int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl )
#endif /* MBEDTLS_SSL_PROTO_DTLS */
memset( ssl->in_ctr, 0, 8 );
- /*
- * Set the in_msg pointer to the correct location based on IV length
- */
- if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
- {
- ssl->in_msg = ssl->in_iv + ssl->transform_negotiate->ivlen -
- ssl->transform_negotiate->fixed_ivlen;
- }
- else
- ssl->in_msg = ssl->in_iv;
+ ssl_update_in_pointers( ssl, ssl->transform_negotiate );
#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
if( mbedtls_ssl_hw_record_activate != NULL )
@@ -5482,16 +6397,7 @@ int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write finished" ) );
- /*
- * Set the out_msg pointer to the correct location based on IV length
- */
- if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
- {
- ssl->out_msg = ssl->out_iv + ssl->transform_negotiate->ivlen -
- ssl->transform_negotiate->fixed_ivlen;
- }
- else
- ssl->out_msg = ssl->out_iv;
+ ssl_update_out_pointers( ssl, ssl->transform_negotiate );
ssl->handshake->calc_finished( ssl, ssl->out_msg + 4, ssl->conf->endpoint );
@@ -5543,14 +6449,14 @@ int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl )
/* Remember current epoch settings for resending */
ssl->handshake->alt_transform_out = ssl->transform_out;
- memcpy( ssl->handshake->alt_out_ctr, ssl->out_ctr, 8 );
+ memcpy( ssl->handshake->alt_out_ctr, ssl->cur_out_ctr, 8 );
/* Set sequence_number to zero */
- memset( ssl->out_ctr + 2, 0, 6 );
+ memset( ssl->cur_out_ctr + 2, 0, 6 );
/* Increment epoch */
for( i = 2; i > 0; i-- )
- if( ++ssl->out_ctr[i - 1] != 0 )
+ if( ++ssl->cur_out_ctr[i - 1] != 0 )
break;
/* The loop goes to its end iff the counter is wrapping */
@@ -5562,7 +6468,7 @@ int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl )
}
else
#endif /* MBEDTLS_SSL_PROTO_DTLS */
- memset( ssl->out_ctr, 0, 8 );
+ memset( ssl->cur_out_ctr, 0, 8 );
ssl->transform_out = ssl->transform_negotiate;
ssl->session_out = ssl->session_negotiate;
@@ -5583,11 +6489,20 @@ int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl )
mbedtls_ssl_send_flight_completed( ssl );
#endif
- if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
{
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
+ return( ret );
+ }
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+ ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret );
return( ret );
}
+#endif
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write finished" ) );
@@ -5610,7 +6525,7 @@ int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl )
ssl->handshake->calc_finished( ssl, buf, ssl->conf->endpoint ^ 1 );
- if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
return( ret );
@@ -5722,6 +6637,10 @@ static void ssl_handshake_params_init( mbedtls_ssl_handshake_params *handshake )
#endif
#endif
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ mbedtls_x509_crt_restart_init( &handshake->ecrs_ctx );
+#endif
+
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
handshake->sni_authmode = MBEDTLS_SSL_VERIFY_UNSET;
#endif
@@ -5841,6 +6760,78 @@ static int ssl_cookie_check_dummy( void *ctx,
}
#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */
+/* Once ssl->out_hdr as the address of the beginning of the
+ * next outgoing record is set, deduce the other pointers.
+ *
+ * Note: For TLS, we save the implicit record sequence number
+ * (entering MAC computation) in the 8 bytes before ssl->out_hdr,
+ * and the caller has to make sure there's space for this.
+ */
+
+static void ssl_update_out_pointers( mbedtls_ssl_context *ssl,
+ mbedtls_ssl_transform *transform )
+{
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ {
+ ssl->out_ctr = ssl->out_hdr + 3;
+ ssl->out_len = ssl->out_hdr + 11;
+ ssl->out_iv = ssl->out_hdr + 13;
+ }
+ else
+#endif
+ {
+ ssl->out_ctr = ssl->out_hdr - 8;
+ ssl->out_len = ssl->out_hdr + 3;
+ ssl->out_iv = ssl->out_hdr + 5;
+ }
+
+ /* Adjust out_msg to make space for explicit IV, if used. */
+ if( transform != NULL &&
+ ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
+ {
+ ssl->out_msg = ssl->out_iv + transform->ivlen - transform->fixed_ivlen;
+ }
+ else
+ ssl->out_msg = ssl->out_iv;
+}
+
+/* Once ssl->in_hdr as the address of the beginning of the
+ * next incoming record is set, deduce the other pointers.
+ *
+ * Note: For TLS, we save the implicit record sequence number
+ * (entering MAC computation) in the 8 bytes before ssl->in_hdr,
+ * and the caller has to make sure there's space for this.
+ */
+
+static void ssl_update_in_pointers( mbedtls_ssl_context *ssl,
+ mbedtls_ssl_transform *transform )
+{
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ {
+ ssl->in_ctr = ssl->in_hdr + 3;
+ ssl->in_len = ssl->in_hdr + 11;
+ ssl->in_iv = ssl->in_hdr + 13;
+ }
+ else
+#endif
+ {
+ ssl->in_ctr = ssl->in_hdr - 8;
+ ssl->in_len = ssl->in_hdr + 3;
+ ssl->in_iv = ssl->in_hdr + 5;
+ }
+
+ /* Offset in_msg from in_iv to allow space for explicit IV, if used. */
+ if( transform != NULL &&
+ ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
+ {
+ ssl->in_msg = ssl->in_iv + transform->ivlen - transform->fixed_ivlen;
+ }
+ else
+ ssl->in_msg = ssl->in_iv;
+}
+
/*
* Initialize an SSL context
*/
@@ -5852,6 +6843,28 @@ void mbedtls_ssl_init( mbedtls_ssl_context *ssl )
/*
* Setup an SSL context
*/
+
+static void ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl )
+{
+ /* Set the incoming and outgoing record pointers. */
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ {
+ ssl->out_hdr = ssl->out_buf;
+ ssl->in_hdr = ssl->in_buf;
+ }
+ else
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+ {
+ ssl->out_hdr = ssl->out_buf + 8;
+ ssl->in_hdr = ssl->in_buf + 8;
+ }
+
+ /* Derive other internal pointers. */
+ ssl_update_out_pointers( ssl, NULL /* no transform enabled */ );
+ ssl_update_in_pointers ( ssl, NULL /* no transform enabled */ );
+}
+
int mbedtls_ssl_setup( mbedtls_ssl_context *ssl,
const mbedtls_ssl_config *conf )
{
@@ -5862,57 +6875,55 @@ int mbedtls_ssl_setup( mbedtls_ssl_context *ssl,
/*
* Prepare base structures
*/
+
+ /* Set to NULL in case of an error condition */
+ ssl->out_buf = NULL;
+
ssl->in_buf = mbedtls_calloc( 1, MBEDTLS_SSL_IN_BUFFER_LEN );
if( ssl->in_buf == NULL )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", MBEDTLS_SSL_IN_BUFFER_LEN) );
- return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
+ ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
+ goto error;
}
ssl->out_buf = mbedtls_calloc( 1, MBEDTLS_SSL_OUT_BUFFER_LEN );
if( ssl->out_buf == NULL )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", MBEDTLS_SSL_OUT_BUFFER_LEN) );
- mbedtls_free( ssl->in_buf );
- ssl->in_buf = NULL;
- return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
- }
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
- {
- ssl->out_hdr = ssl->out_buf;
- ssl->out_ctr = ssl->out_buf + 3;
- ssl->out_len = ssl->out_buf + 11;
- ssl->out_iv = ssl->out_buf + 13;
- ssl->out_msg = ssl->out_buf + 13;
-
- ssl->in_hdr = ssl->in_buf;
- ssl->in_ctr = ssl->in_buf + 3;
- ssl->in_len = ssl->in_buf + 11;
- ssl->in_iv = ssl->in_buf + 13;
- ssl->in_msg = ssl->in_buf + 13;
+ ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
+ goto error;
}
- else
-#endif
- {
- ssl->out_ctr = ssl->out_buf;
- ssl->out_hdr = ssl->out_buf + 8;
- ssl->out_len = ssl->out_buf + 11;
- ssl->out_iv = ssl->out_buf + 13;
- ssl->out_msg = ssl->out_buf + 13;
- ssl->in_ctr = ssl->in_buf;
- ssl->in_hdr = ssl->in_buf + 8;
- ssl->in_len = ssl->in_buf + 11;
- ssl->in_iv = ssl->in_buf + 13;
- ssl->in_msg = ssl->in_buf + 13;
- }
+ ssl_reset_in_out_pointers( ssl );
if( ( ret = ssl_handshake_init( ssl ) ) != 0 )
- return( ret );
+ goto error;
return( 0 );
+
+error:
+ mbedtls_free( ssl->in_buf );
+ mbedtls_free( ssl->out_buf );
+
+ ssl->conf = NULL;
+
+ ssl->in_buf = NULL;
+ ssl->out_buf = NULL;
+
+ ssl->in_hdr = NULL;
+ ssl->in_ctr = NULL;
+ ssl->in_len = NULL;
+ ssl->in_iv = NULL;
+ ssl->in_msg = NULL;
+
+ ssl->out_hdr = NULL;
+ ssl->out_ctr = NULL;
+ ssl->out_len = NULL;
+ ssl->out_iv = NULL;
+ ssl->out_msg = NULL;
+
+ return( ret );
}
/*
@@ -5926,6 +6937,11 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial )
{
int ret;
+#if !defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) || \
+ !defined(MBEDTLS_SSL_SRV_C)
+ ((void) partial);
+#endif
+
ssl->state = MBEDTLS_SSL_HELLO_REQUEST;
/* Cancel any possibly running timer */
@@ -5942,12 +6958,10 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial )
ssl->secure_renegotiation = MBEDTLS_SSL_LEGACY_RENEGOTIATION;
ssl->in_offt = NULL;
+ ssl_reset_in_out_pointers( ssl );
- ssl->in_msg = ssl->in_buf + 13;
ssl->in_msgtype = 0;
ssl->in_msglen = 0;
- if( partial == 0 )
- ssl->in_left = 0;
#if defined(MBEDTLS_SSL_PROTO_DTLS)
ssl->next_record_offset = 0;
ssl->in_epoch = 0;
@@ -5961,7 +6975,6 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial )
ssl->keep_current_message = 0;
- ssl->out_msg = ssl->out_buf + 13;
ssl->out_msgtype = 0;
ssl->out_msglen = 0;
ssl->out_left = 0;
@@ -5970,12 +6983,23 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial )
ssl->split_done = 0;
#endif
+ memset( ssl->cur_out_ctr, 0, sizeof( ssl->cur_out_ctr ) );
+
ssl->transform_in = NULL;
ssl->transform_out = NULL;
+ ssl->session_in = NULL;
+ ssl->session_out = NULL;
+
memset( ssl->out_buf, 0, MBEDTLS_SSL_OUT_BUFFER_LEN );
+
+#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C)
if( partial == 0 )
+#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */
+ {
+ ssl->in_left = 0;
memset( ssl->in_buf, 0, MBEDTLS_SSL_IN_BUFFER_LEN );
+ }
#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
if( mbedtls_ssl_hw_record_reset != NULL )
@@ -6008,7 +7032,9 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial )
#endif
#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)
+#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE)
if( partial == 0 )
+#endif
{
mbedtls_free( ssl->cli_id );
ssl->cli_id = NULL;
@@ -6059,7 +7085,15 @@ void mbedtls_ssl_conf_dtls_badmac_limit( mbedtls_ssl_config *conf, unsigned limi
#endif
#if defined(MBEDTLS_SSL_PROTO_DTLS)
-void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf, uint32_t min, uint32_t max )
+
+void mbedtls_ssl_set_datagram_packing( mbedtls_ssl_context *ssl,
+ unsigned allow_packing )
+{
+ ssl->disable_datagram_packing = !allow_packing;
+}
+
+void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf,
+ uint32_t min, uint32_t max )
{
conf->hs_timeout_min = min;
conf->hs_timeout_max = max;
@@ -6109,6 +7143,13 @@ void mbedtls_ssl_set_bio( mbedtls_ssl_context *ssl,
ssl->f_recv_timeout = f_recv_timeout;
}
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+void mbedtls_ssl_set_mtu( mbedtls_ssl_context *ssl, uint16_t mtu )
+{
+ ssl->mtu = mtu;
+}
+#endif
+
void mbedtls_ssl_conf_read_timeout( mbedtls_ssl_config *conf, uint32_t timeout )
{
conf->read_timeout = timeout;
@@ -6772,7 +7813,7 @@ int mbedtls_ssl_check_pending( const mbedtls_ssl_context *ssl )
/*
* In all other cases, the rest of the message can be dropped.
- * As in ssl_read_record_layer, this needs to be adapted if
+ * As in ssl_get_next_record, this needs to be adapted if
* we implement support for multiple alerts in single records.
*/
@@ -6839,28 +7880,47 @@ const char *mbedtls_ssl_get_version( const mbedtls_ssl_context *ssl )
int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl )
{
- size_t transform_expansion;
+ size_t transform_expansion = 0;
const mbedtls_ssl_transform *transform = ssl->transform_out;
+ unsigned block_size;
+
+ if( transform == NULL )
+ return( (int) mbedtls_ssl_hdr_len( ssl ) );
#if defined(MBEDTLS_ZLIB_SUPPORT)
if( ssl->session_out->compression != MBEDTLS_SSL_COMPRESS_NULL )
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
#endif
- if( transform == NULL )
- return( (int) mbedtls_ssl_hdr_len( ssl ) );
-
switch( mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_enc ) )
{
case MBEDTLS_MODE_GCM:
case MBEDTLS_MODE_CCM:
+ case MBEDTLS_MODE_CHACHAPOLY:
case MBEDTLS_MODE_STREAM:
transform_expansion = transform->minlen;
break;
case MBEDTLS_MODE_CBC:
- transform_expansion = transform->maclen
- + mbedtls_cipher_get_block_size( &transform->cipher_ctx_enc );
+
+ block_size = mbedtls_cipher_get_block_size(
+ &transform->cipher_ctx_enc );
+
+ /* Expansion due to the addition of the MAC. */
+ transform_expansion += transform->maclen;
+
+ /* Expansion due to the addition of CBC padding;
+ * Theoretically up to 256 bytes, but we never use
+ * more than the block size of the underlying cipher. */
+ transform_expansion += block_size;
+
+ /* For TLS 1.1 or higher, an explicit IV is added
+ * after the record header. */
+#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2)
+ if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
+ transform_expansion += block_size;
+#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */
+
break;
default:
@@ -6881,19 +7941,89 @@ size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl )
*/
max_len = ssl_mfl_code_to_length( ssl->conf->mfl_code );
- /*
- * Check if a smaller max length was negotiated
- */
+ /* Check if a smaller max length was negotiated */
if( ssl->session_out != NULL &&
ssl_mfl_code_to_length( ssl->session_out->mfl_code ) < max_len )
{
max_len = ssl_mfl_code_to_length( ssl->session_out->mfl_code );
}
- return max_len;
+ /* During a handshake, use the value being negotiated */
+ if( ssl->session_negotiate != NULL &&
+ ssl_mfl_code_to_length( ssl->session_negotiate->mfl_code ) < max_len )
+ {
+ max_len = ssl_mfl_code_to_length( ssl->session_negotiate->mfl_code );
+ }
+
+ return( max_len );
}
#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+static size_t ssl_get_current_mtu( const mbedtls_ssl_context *ssl )
+{
+ /* Return unlimited mtu for client hello messages to avoid fragmentation. */
+ if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
+ ( ssl->state == MBEDTLS_SSL_CLIENT_HELLO ||
+ ssl->state == MBEDTLS_SSL_SERVER_HELLO ) )
+ return ( 0 );
+
+ if( ssl->handshake == NULL || ssl->handshake->mtu == 0 )
+ return( ssl->mtu );
+
+ if( ssl->mtu == 0 )
+ return( ssl->handshake->mtu );
+
+ return( ssl->mtu < ssl->handshake->mtu ?
+ ssl->mtu : ssl->handshake->mtu );
+}
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+int mbedtls_ssl_get_max_out_record_payload( const mbedtls_ssl_context *ssl )
+{
+ size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN;
+
+#if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) && \
+ !defined(MBEDTLS_SSL_PROTO_DTLS)
+ (void) ssl;
+#endif
+
+#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+ const size_t mfl = mbedtls_ssl_get_max_frag_len( ssl );
+
+ if( max_len > mfl )
+ max_len = mfl;
+#endif
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl_get_current_mtu( ssl ) != 0 )
+ {
+ const size_t mtu = ssl_get_current_mtu( ssl );
+ const int ret = mbedtls_ssl_get_record_expansion( ssl );
+ const size_t overhead = (size_t) ret;
+
+ if( ret < 0 )
+ return( ret );
+
+ if( mtu <= overhead )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "MTU too low for record expansion" ) );
+ return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+ }
+
+ if( max_len > mtu - overhead )
+ max_len = mtu - overhead;
+ }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+#if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) && \
+ !defined(MBEDTLS_SSL_PROTO_DTLS)
+ ((void) ssl);
+#endif
+
+ return( (int) max_len );
+}
+
#if defined(MBEDTLS_X509_CRT_PARSE_C)
const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ssl )
{
@@ -6981,9 +8111,9 @@ static int ssl_write_hello_request( mbedtls_ssl_context *ssl )
ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
ssl->out_msg[0] = MBEDTLS_SSL_HS_HELLO_REQUEST;
- if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
{
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
return( ret );
}
@@ -7113,7 +8243,7 @@ static int ssl_check_ctr_renegotiate( mbedtls_ssl_context *ssl )
in_ctr_cmp = memcmp( ssl->in_ctr + ep_len,
ssl->conf->renego_period + ep_len, 8 - ep_len );
- out_ctr_cmp = memcmp( ssl->out_ctr + ep_len,
+ out_ctr_cmp = memcmp( ssl->cur_out_ctr + ep_len,
ssl->conf->renego_period + ep_len, 8 - ep_len );
if( in_ctr_cmp <= 0 && out_ctr_cmp <= 0 )
@@ -7148,7 +8278,7 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
if( ssl->handshake != NULL &&
ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING )
{
- if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
return( ret );
}
}
@@ -7197,7 +8327,7 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
ssl_set_timer( ssl, ssl->conf->read_timeout );
}
- if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
{
if( ret == MBEDTLS_ERR_SSL_CONN_EOF )
return( 0 );
@@ -7212,7 +8342,7 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
/*
* OpenSSL sends empty messages to randomize the IV
*/
- if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
{
if( ret == MBEDTLS_ERR_SSL_CONN_EOF )
return( 0 );
@@ -7445,12 +8575,15 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
static int ssl_write_real( mbedtls_ssl_context *ssl,
const unsigned char *buf, size_t len )
{
- int ret;
-#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
- size_t max_len = mbedtls_ssl_get_max_frag_len( ssl );
-#else
- size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN;
-#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
+ int ret = mbedtls_ssl_get_max_out_record_payload( ssl );
+ const size_t max_len = (size_t) ret;
+
+ if( ret < 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_get_max_out_record_payload", ret );
+ return( ret );
+ }
+
if( len > max_len )
{
#if defined(MBEDTLS_SSL_PROTO_DTLS)
@@ -7491,7 +8624,7 @@ static int ssl_write_real( mbedtls_ssl_context *ssl,
ssl->out_msgtype = MBEDTLS_SSL_MSG_APPLICATION_DATA;
memcpy( ssl->out_msg, buf, len );
- if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
return( ret );
@@ -7643,6 +8776,42 @@ static void ssl_key_cert_free( mbedtls_ssl_key_cert *key_cert )
}
#endif /* MBEDTLS_X509_CRT_PARSE_C */
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+
+static void ssl_buffering_free( mbedtls_ssl_context *ssl )
+{
+ unsigned offset;
+ mbedtls_ssl_handshake_params * const hs = ssl->handshake;
+
+ if( hs == NULL )
+ return;
+
+ ssl_free_buffered_record( ssl );
+
+ for( offset = 0; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++ )
+ ssl_buffering_free_slot( ssl, offset );
+}
+
+static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl,
+ uint8_t slot )
+{
+ mbedtls_ssl_handshake_params * const hs = ssl->handshake;
+ mbedtls_ssl_hs_buffer * const hs_buf = &hs->buffering.hs[slot];
+
+ if( slot >= MBEDTLS_SSL_MAX_BUFFERED_HS )
+ return;
+
+ if( hs_buf->is_valid == 1 )
+ {
+ hs->buffering.total_bytes_buffered -= hs_buf->data_len;
+ mbedtls_platform_zeroize( hs_buf->data, hs_buf->data_len );
+ mbedtls_free( hs_buf->data );
+ memset( hs_buf, 0, sizeof( mbedtls_ssl_hs_buffer ) );
+ }
+}
+
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl )
{
mbedtls_ssl_handshake_params *handshake = ssl->handshake;
@@ -7720,10 +8889,14 @@ void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl )
}
#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_SERVER_NAME_INDICATION */
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ mbedtls_x509_crt_restart_free( &handshake->ecrs_ctx );
+#endif
+
#if defined(MBEDTLS_SSL_PROTO_DTLS)
mbedtls_free( handshake->verify_cookie );
- mbedtls_free( handshake->hs_msg );
ssl_flight_free( handshake->flight );
+ ssl_buffering_free( ssl );
#endif
mbedtls_platform_zeroize( handshake,
diff --git a/thirdparty/mbedtls/library/threading.c b/thirdparty/mbedtls/library/threading.c
index 7a32e672c7..7c90c7c595 100644
--- a/thirdparty/mbedtls/library/threading.c
+++ b/thirdparty/mbedtls/library/threading.c
@@ -19,6 +19,14 @@
* This file is part of mbed TLS (https://tls.mbed.org)
*/
+/*
+ * Ensure gmtime_r is available even with -std=c99; must be defined before
+ * config.h, which pulls in glibc's features.h. Harmless on other platforms.
+ */
+#if !defined(_POSIX_C_SOURCE)
+#define _POSIX_C_SOURCE 200112L
+#endif
+
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
@@ -29,6 +37,36 @@
#include "mbedtls/threading.h"
+#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT)
+
+#if !defined(_WIN32) && (defined(unix) || \
+ defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \
+ defined(__MACH__)))
+#include <unistd.h>
+#endif /* !_WIN32 && (unix || __unix || __unix__ ||
+ * (__APPLE__ && __MACH__)) */
+
+#if !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \
+ ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \
+ _POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) )
+/*
+ * This is a convenience shorthand macro to avoid checking the long
+ * preprocessor conditions above. Ideally, we could expose this macro in
+ * platform_util.h and simply use it in platform_util.c, threading.c and
+ * threading.h. However, this macro is not part of the Mbed TLS public API, so
+ * we keep it private by only defining it in this file
+ */
+
+#if ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) )
+#define THREADING_USE_GMTIME
+#endif /* ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) */
+
+#endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \
+ ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \
+ _POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) ) */
+
+#endif /* MBEDTLS_HAVE_TIME_DATE && !MBEDTLS_PLATFORM_GMTIME_R_ALT */
+
#if defined(MBEDTLS_THREADING_PTHREAD)
static void threading_mutex_init_pthread( mbedtls_threading_mutex_t *mutex )
{
@@ -114,6 +152,9 @@ void mbedtls_threading_set_alt( void (*mutex_init)( mbedtls_threading_mutex_t *
#if defined(MBEDTLS_FS_IO)
mbedtls_mutex_init( &mbedtls_threading_readdir_mutex );
#endif
+#if defined(THREADING_USE_GMTIME)
+ mbedtls_mutex_init( &mbedtls_threading_gmtime_mutex );
+#endif
}
/*
@@ -124,6 +165,9 @@ void mbedtls_threading_free_alt( void )
#if defined(MBEDTLS_FS_IO)
mbedtls_mutex_free( &mbedtls_threading_readdir_mutex );
#endif
+#if defined(THREADING_USE_GMTIME)
+ mbedtls_mutex_free( &mbedtls_threading_gmtime_mutex );
+#endif
}
#endif /* MBEDTLS_THREADING_ALT */
@@ -136,5 +180,8 @@ void mbedtls_threading_free_alt( void )
#if defined(MBEDTLS_FS_IO)
mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex MUTEX_INIT;
#endif
+#if defined(THREADING_USE_GMTIME)
+mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex MUTEX_INIT;
+#endif
#endif /* MBEDTLS_THREADING_C */
diff --git a/thirdparty/mbedtls/library/timing.c b/thirdparty/mbedtls/library/timing.c
index 3e8139f1f9..413d133fb6 100644
--- a/thirdparty/mbedtls/library/timing.c
+++ b/thirdparty/mbedtls/library/timing.c
@@ -52,6 +52,7 @@
#include <windows.h>
#include <winbase.h>
+#include <process.h>
struct _hr_time
{
@@ -267,18 +268,17 @@ unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int
/* It's OK to use a global because alarm() is supposed to be global anyway */
static DWORD alarmMs;
-static DWORD WINAPI TimerProc( LPVOID TimerContext )
+static void TimerProc( void *TimerContext )
{
- ((void) TimerContext);
+ (void) TimerContext;
Sleep( alarmMs );
mbedtls_timing_alarmed = 1;
- return( TRUE );
+ /* _endthread will be called implicitly on return
+ * That ensures execution of thread funcition's epilogue */
}
void mbedtls_set_alarm( int seconds )
{
- DWORD ThreadId;
-
if( seconds == 0 )
{
/* No need to create a thread for this simple case.
@@ -289,7 +289,7 @@ void mbedtls_set_alarm( int seconds )
mbedtls_timing_alarmed = 0;
alarmMs = seconds * 1000;
- CloseHandle( CreateThread( NULL, 0, TimerProc, NULL, 0, &ThreadId ) );
+ (void) _beginthread( TimerProc, 0, NULL );
}
#else /* _WIN32 && !EFIX64 && !EFI32 */
diff --git a/thirdparty/mbedtls/library/version_features.c b/thirdparty/mbedtls/library/version_features.c
index 777b6034c4..4c36d3caaa 100644
--- a/thirdparty/mbedtls/library/version_features.c
+++ b/thirdparty/mbedtls/library/version_features.c
@@ -84,6 +84,9 @@ static const char *features[] = {
#if defined(MBEDTLS_DEPRECATED_REMOVED)
"MBEDTLS_DEPRECATED_REMOVED",
#endif /* MBEDTLS_DEPRECATED_REMOVED */
+#if defined(MBEDTLS_CHECK_PARAMS)
+ "MBEDTLS_CHECK_PARAMS",
+#endif /* MBEDTLS_CHECK_PARAMS */
#if defined(MBEDTLS_TIMING_ALT)
"MBEDTLS_TIMING_ALT",
#endif /* MBEDTLS_TIMING_ALT */
@@ -339,6 +342,9 @@ static const char *features[] = {
#if defined(MBEDTLS_ECP_NIST_OPTIM)
"MBEDTLS_ECP_NIST_OPTIM",
#endif /* MBEDTLS_ECP_NIST_OPTIM */
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ "MBEDTLS_ECP_RESTARTABLE",
+#endif /* MBEDTLS_ECP_RESTARTABLE */
#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
"MBEDTLS_ECDSA_DETERMINISTIC",
#endif /* MBEDTLS_ECDSA_DETERMINISTIC */
diff --git a/thirdparty/mbedtls/library/x509.c b/thirdparty/mbedtls/library/x509.c
index 2e6795f750..52b5b649f7 100644
--- a/thirdparty/mbedtls/library/x509.c
+++ b/thirdparty/mbedtls/library/x509.c
@@ -29,10 +29,6 @@
* http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
*/
-/* Ensure gmtime_r is available even with -std=c99; must be included before
- * config.h, which pulls in glibc's features.h. Harmless on other platforms. */
-#define _POSIX_C_SOURCE 200112L
-
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
@@ -67,6 +63,7 @@
#include "mbedtls/platform_time.h"
#endif
#if defined(MBEDTLS_HAVE_TIME_DATE)
+#include "mbedtls/platform_util.h"
#include <time.h>
#endif
@@ -901,11 +898,7 @@ static int x509_get_current_time( mbedtls_x509_time *now )
int ret = 0;
tt = mbedtls_time( NULL );
-#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
- lt = gmtime_s( &tm_buf, &tt ) == 0 ? &tm_buf : NULL;
-#else
- lt = gmtime_r( &tt, &tm_buf );
-#endif
+ lt = mbedtls_platform_gmtime_r( &tt, &tm_buf );
if( lt == NULL )
ret = -1;
diff --git a/thirdparty/mbedtls/library/x509_create.c b/thirdparty/mbedtls/library/x509_create.c
index df20ec8ebd..546e8fa1a9 100644
--- a/thirdparty/mbedtls/library/x509_create.c
+++ b/thirdparty/mbedtls/library/x509_create.c
@@ -33,48 +33,84 @@
#include <string.h>
+/* Structure linking OIDs for X.509 DN AttributeTypes to their
+ * string representations and default string encodings used by Mbed TLS. */
typedef struct {
- const char *name;
- size_t name_len;
- const char*oid;
+ const char *name; /* String representation of AttributeType, e.g.
+ * "CN" or "emailAddress". */
+ size_t name_len; /* Length of 'name', without trailing 0 byte. */
+ const char *oid; /* String representation of OID of AttributeType,
+ * as per RFC 5280, Appendix A.1. */
+ int default_tag; /* The default character encoding used for the
+ * given attribute type, e.g.
+ * MBEDTLS_ASN1_UTF8_STRING for UTF-8. */
} x509_attr_descriptor_t;
#define ADD_STRLEN( s ) s, sizeof( s ) - 1
+/* X.509 DN attributes from RFC 5280, Appendix A.1. */
static const x509_attr_descriptor_t x509_attrs[] =
{
- { ADD_STRLEN( "CN" ), MBEDTLS_OID_AT_CN },
- { ADD_STRLEN( "commonName" ), MBEDTLS_OID_AT_CN },
- { ADD_STRLEN( "C" ), MBEDTLS_OID_AT_COUNTRY },
- { ADD_STRLEN( "countryName" ), MBEDTLS_OID_AT_COUNTRY },
- { ADD_STRLEN( "O" ), MBEDTLS_OID_AT_ORGANIZATION },
- { ADD_STRLEN( "organizationName" ), MBEDTLS_OID_AT_ORGANIZATION },
- { ADD_STRLEN( "L" ), MBEDTLS_OID_AT_LOCALITY },
- { ADD_STRLEN( "locality" ), MBEDTLS_OID_AT_LOCALITY },
- { ADD_STRLEN( "R" ), MBEDTLS_OID_PKCS9_EMAIL },
- { ADD_STRLEN( "OU" ), MBEDTLS_OID_AT_ORG_UNIT },
- { ADD_STRLEN( "organizationalUnitName" ), MBEDTLS_OID_AT_ORG_UNIT },
- { ADD_STRLEN( "ST" ), MBEDTLS_OID_AT_STATE },
- { ADD_STRLEN( "stateOrProvinceName" ), MBEDTLS_OID_AT_STATE },
- { ADD_STRLEN( "emailAddress" ), MBEDTLS_OID_PKCS9_EMAIL },
- { ADD_STRLEN( "serialNumber" ), MBEDTLS_OID_AT_SERIAL_NUMBER },
- { ADD_STRLEN( "postalAddress" ), MBEDTLS_OID_AT_POSTAL_ADDRESS },
- { ADD_STRLEN( "postalCode" ), MBEDTLS_OID_AT_POSTAL_CODE },
- { ADD_STRLEN( "dnQualifier" ), MBEDTLS_OID_AT_DN_QUALIFIER },
- { ADD_STRLEN( "title" ), MBEDTLS_OID_AT_TITLE },
- { ADD_STRLEN( "surName" ), MBEDTLS_OID_AT_SUR_NAME },
- { ADD_STRLEN( "SN" ), MBEDTLS_OID_AT_SUR_NAME },
- { ADD_STRLEN( "givenName" ), MBEDTLS_OID_AT_GIVEN_NAME },
- { ADD_STRLEN( "GN" ), MBEDTLS_OID_AT_GIVEN_NAME },
- { ADD_STRLEN( "initials" ), MBEDTLS_OID_AT_INITIALS },
- { ADD_STRLEN( "pseudonym" ), MBEDTLS_OID_AT_PSEUDONYM },
- { ADD_STRLEN( "generationQualifier" ), MBEDTLS_OID_AT_GENERATION_QUALIFIER },
- { ADD_STRLEN( "domainComponent" ), MBEDTLS_OID_DOMAIN_COMPONENT },
- { ADD_STRLEN( "DC" ), MBEDTLS_OID_DOMAIN_COMPONENT },
- { NULL, 0, NULL }
+ { ADD_STRLEN( "CN" ),
+ MBEDTLS_OID_AT_CN, MBEDTLS_ASN1_UTF8_STRING },
+ { ADD_STRLEN( "commonName" ),
+ MBEDTLS_OID_AT_CN, MBEDTLS_ASN1_UTF8_STRING },
+ { ADD_STRLEN( "C" ),
+ MBEDTLS_OID_AT_COUNTRY, MBEDTLS_ASN1_PRINTABLE_STRING },
+ { ADD_STRLEN( "countryName" ),
+ MBEDTLS_OID_AT_COUNTRY, MBEDTLS_ASN1_PRINTABLE_STRING },
+ { ADD_STRLEN( "O" ),
+ MBEDTLS_OID_AT_ORGANIZATION, MBEDTLS_ASN1_UTF8_STRING },
+ { ADD_STRLEN( "organizationName" ),
+ MBEDTLS_OID_AT_ORGANIZATION, MBEDTLS_ASN1_UTF8_STRING },
+ { ADD_STRLEN( "L" ),
+ MBEDTLS_OID_AT_LOCALITY, MBEDTLS_ASN1_UTF8_STRING },
+ { ADD_STRLEN( "locality" ),
+ MBEDTLS_OID_AT_LOCALITY, MBEDTLS_ASN1_UTF8_STRING },
+ { ADD_STRLEN( "R" ),
+ MBEDTLS_OID_PKCS9_EMAIL, MBEDTLS_ASN1_IA5_STRING },
+ { ADD_STRLEN( "OU" ),
+ MBEDTLS_OID_AT_ORG_UNIT, MBEDTLS_ASN1_UTF8_STRING },
+ { ADD_STRLEN( "organizationalUnitName" ),
+ MBEDTLS_OID_AT_ORG_UNIT, MBEDTLS_ASN1_UTF8_STRING },
+ { ADD_STRLEN( "ST" ),
+ MBEDTLS_OID_AT_STATE, MBEDTLS_ASN1_UTF8_STRING },
+ { ADD_STRLEN( "stateOrProvinceName" ),
+ MBEDTLS_OID_AT_STATE, MBEDTLS_ASN1_UTF8_STRING },
+ { ADD_STRLEN( "emailAddress" ),
+ MBEDTLS_OID_PKCS9_EMAIL, MBEDTLS_ASN1_IA5_STRING },
+ { ADD_STRLEN( "serialNumber" ),
+ MBEDTLS_OID_AT_SERIAL_NUMBER, MBEDTLS_ASN1_PRINTABLE_STRING },
+ { ADD_STRLEN( "postalAddress" ),
+ MBEDTLS_OID_AT_POSTAL_ADDRESS, MBEDTLS_ASN1_PRINTABLE_STRING },
+ { ADD_STRLEN( "postalCode" ),
+ MBEDTLS_OID_AT_POSTAL_CODE, MBEDTLS_ASN1_PRINTABLE_STRING },
+ { ADD_STRLEN( "dnQualifier" ),
+ MBEDTLS_OID_AT_DN_QUALIFIER, MBEDTLS_ASN1_PRINTABLE_STRING },
+ { ADD_STRLEN( "title" ),
+ MBEDTLS_OID_AT_TITLE, MBEDTLS_ASN1_UTF8_STRING },
+ { ADD_STRLEN( "surName" ),
+ MBEDTLS_OID_AT_SUR_NAME, MBEDTLS_ASN1_UTF8_STRING },
+ { ADD_STRLEN( "SN" ),
+ MBEDTLS_OID_AT_SUR_NAME, MBEDTLS_ASN1_UTF8_STRING },
+ { ADD_STRLEN( "givenName" ),
+ MBEDTLS_OID_AT_GIVEN_NAME, MBEDTLS_ASN1_UTF8_STRING },
+ { ADD_STRLEN( "GN" ),
+ MBEDTLS_OID_AT_GIVEN_NAME, MBEDTLS_ASN1_UTF8_STRING },
+ { ADD_STRLEN( "initials" ),
+ MBEDTLS_OID_AT_INITIALS, MBEDTLS_ASN1_UTF8_STRING },
+ { ADD_STRLEN( "pseudonym" ),
+ MBEDTLS_OID_AT_PSEUDONYM, MBEDTLS_ASN1_UTF8_STRING },
+ { ADD_STRLEN( "generationQualifier" ),
+ MBEDTLS_OID_AT_GENERATION_QUALIFIER, MBEDTLS_ASN1_UTF8_STRING },
+ { ADD_STRLEN( "domainComponent" ),
+ MBEDTLS_OID_DOMAIN_COMPONENT, MBEDTLS_ASN1_IA5_STRING },
+ { ADD_STRLEN( "DC" ),
+ MBEDTLS_OID_DOMAIN_COMPONENT, MBEDTLS_ASN1_IA5_STRING },
+ { NULL, 0, NULL, MBEDTLS_ASN1_NULL }
};
-static const char *x509_at_oid_from_name( const char *name, size_t name_len )
+static const x509_attr_descriptor_t *x509_attr_descr_from_name( const char *name, size_t name_len )
{
const x509_attr_descriptor_t *cur;
@@ -83,7 +119,10 @@ static const char *x509_at_oid_from_name( const char *name, size_t name_len )
strncmp( cur->name, name, name_len ) == 0 )
break;
- return( cur->oid );
+ if ( cur->name == NULL )
+ return( NULL );
+
+ return( cur );
}
int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *name )
@@ -92,6 +131,7 @@ int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *na
const char *s = name, *c = s;
const char *end = s + strlen( s );
const char *oid = NULL;
+ const x509_attr_descriptor_t* attr_descr = NULL;
int in_tag = 1;
char data[MBEDTLS_X509_MAX_DN_NAME_SIZE];
char *d = data;
@@ -103,12 +143,13 @@ int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *na
{
if( in_tag && *c == '=' )
{
- if( ( oid = x509_at_oid_from_name( s, c - s ) ) == NULL )
+ if( ( attr_descr = x509_attr_descr_from_name( s, c - s ) ) == NULL )
{
ret = MBEDTLS_ERR_X509_UNKNOWN_OID;
goto exit;
}
+ oid = attr_descr->oid;
s = c + 1;
in_tag = 0;
d = data;
@@ -127,13 +168,19 @@ int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *na
}
else if( !in_tag && ( *c == ',' || c == end ) )
{
- if( mbedtls_asn1_store_named_data( head, oid, strlen( oid ),
- (unsigned char *) data,
- d - data ) == NULL )
+ mbedtls_asn1_named_data* cur =
+ mbedtls_asn1_store_named_data( head, oid, strlen( oid ),
+ (unsigned char *) data,
+ d - data );
+
+ if(cur == NULL )
{
return( MBEDTLS_ERR_X509_ALLOC_FAILED );
}
+ // set tagType
+ cur->val.tag = attr_descr->default_tag;
+
while( c < end && *(c + 1) == ' ' )
c++;
@@ -192,46 +239,40 @@ int mbedtls_x509_set_extension( mbedtls_asn1_named_data **head, const char *oid,
*
* AttributeValue ::= ANY DEFINED BY AttributeType
*/
-static int x509_write_name( unsigned char **p, unsigned char *start,
- const char *oid, size_t oid_len,
- const unsigned char *name, size_t name_len )
+static int x509_write_name( unsigned char **p, unsigned char *start, mbedtls_asn1_named_data* cur_name)
{
int ret;
size_t len = 0;
-
- // Write PrintableString for all except MBEDTLS_OID_PKCS9_EMAIL
- //
- if( MBEDTLS_OID_SIZE( MBEDTLS_OID_PKCS9_EMAIL ) == oid_len &&
- memcmp( oid, MBEDTLS_OID_PKCS9_EMAIL, oid_len ) == 0 )
- {
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_ia5_string( p, start,
- (const char *) name,
- name_len ) );
- }
- else
- {
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_printable_string( p, start,
- (const char *) name,
- name_len ) );
- }
-
+ const char *oid = (const char*)cur_name->oid.p;
+ size_t oid_len = cur_name->oid.len;
+ const unsigned char *name = cur_name->val.p;
+ size_t name_len = cur_name->val.len;
+
+ // Write correct string tag and value
+ MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tagged_string( p, start,
+ cur_name->val.tag,
+ (const char *) name,
+ name_len ) );
// Write OID
//
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) );
+ MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid,
+ oid_len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED |
- MBEDTLS_ASN1_SEQUENCE ) );
+ MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start,
+ MBEDTLS_ASN1_CONSTRUCTED |
+ MBEDTLS_ASN1_SEQUENCE ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED |
+ MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start,
+ MBEDTLS_ASN1_CONSTRUCTED |
MBEDTLS_ASN1_SET ) );
return( (int) len );
}
int mbedtls_x509_write_names( unsigned char **p, unsigned char *start,
- mbedtls_asn1_named_data *first )
+ mbedtls_asn1_named_data *first )
{
int ret;
size_t len = 0;
@@ -239,9 +280,7 @@ int mbedtls_x509_write_names( unsigned char **p, unsigned char *start,
while( cur != NULL )
{
- MBEDTLS_ASN1_CHK_ADD( len, x509_write_name( p, start, (char *) cur->oid.p,
- cur->oid.len,
- cur->val.p, cur->val.len ) );
+ MBEDTLS_ASN1_CHK_ADD( len, x509_write_name( p, start, cur ) );
cur = cur->next;
}
diff --git a/thirdparty/mbedtls/library/x509_crt.c b/thirdparty/mbedtls/library/x509_crt.c
index 3cf1743821..35a134950e 100644
--- a/thirdparty/mbedtls/library/x509_crt.c
+++ b/thirdparty/mbedtls/library/x509_crt.c
@@ -43,7 +43,6 @@
#include "mbedtls/oid.h"
#include "mbedtls/platform_util.h"
-#include <stdio.h>
#include <string.h>
#if defined(MBEDTLS_PEM_PARSE_C)
@@ -53,6 +52,7 @@
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
+#include <stdio.h>
#include <stdlib.h>
#define mbedtls_free free
#define mbedtls_calloc calloc
@@ -176,6 +176,9 @@ const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb =
static int x509_profile_check_md_alg( const mbedtls_x509_crt_profile *profile,
mbedtls_md_type_t md_alg )
{
+ if( md_alg == MBEDTLS_MD_NONE )
+ return( -1 );
+
if( ( profile->allowed_mds & MBEDTLS_X509_ID_FLAG( md_alg ) ) != 0 )
return( 0 );
@@ -189,6 +192,9 @@ static int x509_profile_check_md_alg( const mbedtls_x509_crt_profile *profile,
static int x509_profile_check_pk_alg( const mbedtls_x509_crt_profile *profile,
mbedtls_pk_type_t pk_alg )
{
+ if( pk_alg == MBEDTLS_PK_NONE )
+ return( -1 );
+
if( ( profile->allowed_pks & MBEDTLS_X509_ID_FLAG( pk_alg ) ) != 0 )
return( 0 );
@@ -221,6 +227,9 @@ static int x509_profile_check_key( const mbedtls_x509_crt_profile *profile,
{
const mbedtls_ecp_group_id gid = mbedtls_pk_ec( *pk )->grp.id;
+ if( gid == MBEDTLS_ECP_DP_NONE )
+ return( -1 );
+
if( ( profile->allowed_curves & MBEDTLS_X509_ID_FLAG( gid ) ) != 0 )
return( 0 );
@@ -232,6 +241,153 @@ static int x509_profile_check_key( const mbedtls_x509_crt_profile *profile,
}
/*
+ * Like memcmp, but case-insensitive and always returns -1 if different
+ */
+static int x509_memcasecmp( const void *s1, const void *s2, size_t len )
+{
+ size_t i;
+ unsigned char diff;
+ const unsigned char *n1 = s1, *n2 = s2;
+
+ for( i = 0; i < len; i++ )
+ {
+ diff = n1[i] ^ n2[i];
+
+ if( diff == 0 )
+ continue;
+
+ if( diff == 32 &&
+ ( ( n1[i] >= 'a' && n1[i] <= 'z' ) ||
+ ( n1[i] >= 'A' && n1[i] <= 'Z' ) ) )
+ {
+ continue;
+ }
+
+ return( -1 );
+ }
+
+ return( 0 );
+}
+
+/*
+ * Return 0 if name matches wildcard, -1 otherwise
+ */
+static int x509_check_wildcard( const char *cn, const mbedtls_x509_buf *name )
+{
+ size_t i;
+ size_t cn_idx = 0, cn_len = strlen( cn );
+
+ /* We can't have a match if there is no wildcard to match */
+ if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' )
+ return( -1 );
+
+ for( i = 0; i < cn_len; ++i )
+ {
+ if( cn[i] == '.' )
+ {
+ cn_idx = i;
+ break;
+ }
+ }
+
+ if( cn_idx == 0 )
+ return( -1 );
+
+ if( cn_len - cn_idx == name->len - 1 &&
+ x509_memcasecmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 )
+ {
+ return( 0 );
+ }
+
+ return( -1 );
+}
+
+/*
+ * Compare two X.509 strings, case-insensitive, and allowing for some encoding
+ * variations (but not all).
+ *
+ * Return 0 if equal, -1 otherwise.
+ */
+static int x509_string_cmp( const mbedtls_x509_buf *a, const mbedtls_x509_buf *b )
+{
+ if( a->tag == b->tag &&
+ a->len == b->len &&
+ memcmp( a->p, b->p, b->len ) == 0 )
+ {
+ return( 0 );
+ }
+
+ if( ( a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) &&
+ ( b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) &&
+ a->len == b->len &&
+ x509_memcasecmp( a->p, b->p, b->len ) == 0 )
+ {
+ return( 0 );
+ }
+
+ return( -1 );
+}
+
+/*
+ * Compare two X.509 Names (aka rdnSequence).
+ *
+ * See RFC 5280 section 7.1, though we don't implement the whole algorithm:
+ * we sometimes return unequal when the full algorithm would return equal,
+ * but never the other way. (In particular, we don't do Unicode normalisation
+ * or space folding.)
+ *
+ * Return 0 if equal, -1 otherwise.
+ */
+static int x509_name_cmp( const mbedtls_x509_name *a, const mbedtls_x509_name *b )
+{
+ /* Avoid recursion, it might not be optimised by the compiler */
+ while( a != NULL || b != NULL )
+ {
+ if( a == NULL || b == NULL )
+ return( -1 );
+
+ /* type */
+ if( a->oid.tag != b->oid.tag ||
+ a->oid.len != b->oid.len ||
+ memcmp( a->oid.p, b->oid.p, b->oid.len ) != 0 )
+ {
+ return( -1 );
+ }
+
+ /* value */
+ if( x509_string_cmp( &a->val, &b->val ) != 0 )
+ return( -1 );
+
+ /* structure of the list of sets */
+ if( a->next_merged != b->next_merged )
+ return( -1 );
+
+ a = a->next;
+ b = b->next;
+ }
+
+ /* a == NULL == b */
+ return( 0 );
+}
+
+/*
+ * Reset (init or clear) a verify_chain
+ */
+static void x509_crt_verify_chain_reset(
+ mbedtls_x509_crt_verify_chain *ver_chain )
+{
+ size_t i;
+
+ for( i = 0; i < MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE; i++ )
+ {
+ ver_chain->items[i].crt = NULL;
+ ver_chain->items[i].flags = -1;
+ }
+
+ ver_chain->len = 0;
+}
+
+/*
* Version ::= INTEGER { v1(0), v2(1), v3(2) }
*/
static int x509_get_version( unsigned char **p,
@@ -583,18 +739,14 @@ static int x509_get_crt_ext( unsigned char **p,
end_ext_data = *p + len;
/* Get extension ID */
- extn_oid.tag = **p;
-
- if( ( ret = mbedtls_asn1_get_tag( p, end, &extn_oid.len, MBEDTLS_ASN1_OID ) ) != 0 )
+ if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &extn_oid.len,
+ MBEDTLS_ASN1_OID ) ) != 0 )
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+ extn_oid.tag = MBEDTLS_ASN1_OID;
extn_oid.p = *p;
*p += extn_oid.len;
- if( ( end - *p ) < 1 )
- return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
- MBEDTLS_ERR_ASN1_OUT_OF_DATA );
-
/* Get optional critical */
if( ( ret = mbedtls_asn1_get_bool( p, end_ext_data, &is_critical ) ) != 0 &&
( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) )
@@ -1139,7 +1291,7 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path )
char filename[MAX_PATH];
char *p;
size_t len = strlen( path );
- int length_as_int = 0;
+ int lengthAsInt = 0;
WIN32_FIND_DATAW file_data;
HANDLE hFind;
@@ -1154,7 +1306,7 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path )
p = filename + len;
filename[len++] = '*';
- if ( FAILED ( SizeTToInt( len, &length_as_int ) ) )
+ if ( FAILED ( SizeTToInt( len, &lengthAsInt ) ) )
return( MBEDTLS_ERR_X509_FILE_IO_ERROR );
/*
@@ -1165,7 +1317,7 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path )
* incoming string are less than MAX_PATH to avoid a buffer overrun with
* MultiByteToWideChar().
*/
- w_ret = MultiByteToWideChar( CP_ACP, 0, filename, length_as_int, szDir,
+ w_ret = MultiByteToWideChar( CP_ACP, 0, filename, lengthAsInt, szDir,
MAX_PATH - 3 );
if( w_ret == 0 )
return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
@@ -1182,11 +1334,11 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path )
if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
continue;
- if ( FAILED( SizeTToInt( wcslen( file_data.cFileName ), &length_as_int ) ) )
+ if ( FAILED( SizeTToInt( wcslen( file_data.cFileName ), &lengthAsInt ) ) )
return( MBEDTLS_ERR_X509_FILE_IO_ERROR );
w_ret = WideCharToMultiByte( CP_ACP, 0, file_data.cFileName,
- length_as_int,
+ lengthAsInt,
p, (int) len - 1,
NULL, NULL );
if( w_ret == 0 )
@@ -1690,9 +1842,7 @@ static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca,
while( crl_list != NULL )
{
if( crl_list->version == 0 ||
- crl_list->issuer_raw.len != ca->subject_raw.len ||
- memcmp( crl_list->issuer_raw.p, ca->subject_raw.p,
- crl_list->issuer_raw.len ) != 0 )
+ x509_name_cmp( &crl_list->issuer, &ca->subject ) != 0 )
{
crl_list = crl_list->next;
continue;
@@ -1702,7 +1852,8 @@ static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca,
* Check if the CA is configured to sign CRLs
*/
#if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
- if( mbedtls_x509_crt_check_key_usage( ca, MBEDTLS_X509_KU_CRL_SIGN ) != 0 )
+ if( mbedtls_x509_crt_check_key_usage( ca,
+ MBEDTLS_X509_KU_CRL_SIGN ) != 0 )
{
flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
break;
@@ -1763,140 +1914,11 @@ static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca,
#endif /* MBEDTLS_X509_CRL_PARSE_C */
/*
- * Like memcmp, but case-insensitive and always returns -1 if different
- */
-static int x509_memcasecmp( const void *s1, const void *s2, size_t len )
-{
- size_t i;
- unsigned char diff;
- const unsigned char *n1 = s1, *n2 = s2;
-
- for( i = 0; i < len; i++ )
- {
- diff = n1[i] ^ n2[i];
-
- if( diff == 0 )
- continue;
-
- if( diff == 32 &&
- ( ( n1[i] >= 'a' && n1[i] <= 'z' ) ||
- ( n1[i] >= 'A' && n1[i] <= 'Z' ) ) )
- {
- continue;
- }
-
- return( -1 );
- }
-
- return( 0 );
-}
-
-/*
- * Return 0 if name matches wildcard, -1 otherwise
- */
-static int x509_check_wildcard( const char *cn, const mbedtls_x509_buf *name )
-{
- size_t i;
- size_t cn_idx = 0, cn_len = strlen( cn );
-
- /* We can't have a match if there is no wildcard to match */
- if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' )
- return( -1 );
-
- for( i = 0; i < cn_len; ++i )
- {
- if( cn[i] == '.' )
- {
- cn_idx = i;
- break;
- }
- }
-
- if( cn_idx == 0 )
- return( -1 );
-
- if( cn_len - cn_idx == name->len - 1 &&
- x509_memcasecmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 )
- {
- return( 0 );
- }
-
- return( -1 );
-}
-
-/*
- * Compare two X.509 strings, case-insensitive, and allowing for some encoding
- * variations (but not all).
- *
- * Return 0 if equal, -1 otherwise.
- */
-static int x509_string_cmp( const mbedtls_x509_buf *a, const mbedtls_x509_buf *b )
-{
- if( a->tag == b->tag &&
- a->len == b->len &&
- memcmp( a->p, b->p, b->len ) == 0 )
- {
- return( 0 );
- }
-
- if( ( a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) &&
- ( b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) &&
- a->len == b->len &&
- x509_memcasecmp( a->p, b->p, b->len ) == 0 )
- {
- return( 0 );
- }
-
- return( -1 );
-}
-
-/*
- * Compare two X.509 Names (aka rdnSequence).
- *
- * See RFC 5280 section 7.1, though we don't implement the whole algorithm:
- * we sometimes return unequal when the full algorithm would return equal,
- * but never the other way. (In particular, we don't do Unicode normalisation
- * or space folding.)
- *
- * Return 0 if equal, -1 otherwise.
- */
-static int x509_name_cmp( const mbedtls_x509_name *a, const mbedtls_x509_name *b )
-{
- /* Avoid recursion, it might not be optimised by the compiler */
- while( a != NULL || b != NULL )
- {
- if( a == NULL || b == NULL )
- return( -1 );
-
- /* type */
- if( a->oid.tag != b->oid.tag ||
- a->oid.len != b->oid.len ||
- memcmp( a->oid.p, b->oid.p, b->oid.len ) != 0 )
- {
- return( -1 );
- }
-
- /* value */
- if( x509_string_cmp( &a->val, &b->val ) != 0 )
- return( -1 );
-
- /* structure of the list of sets */
- if( a->next_merged != b->next_merged )
- return( -1 );
-
- a = a->next;
- b = b->next;
- }
-
- /* a == NULL == b */
- return( 0 );
-}
-
-/*
* Check the signature of a certificate by its parent
*/
static int x509_crt_check_signature( const mbedtls_x509_crt *child,
- mbedtls_x509_crt *parent )
+ mbedtls_x509_crt *parent,
+ mbedtls_x509_crt_restart_ctx *rs_ctx )
{
const mbedtls_md_info_t *md_info;
unsigned char hash[MBEDTLS_MD_MAX_SIZE];
@@ -1908,14 +1930,24 @@ static int x509_crt_check_signature( const mbedtls_x509_crt *child,
return( -1 );
}
- if( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk,
- child->sig_md, hash, mbedtls_md_get_size( md_info ),
- child->sig.p, child->sig.len ) != 0 )
- {
+ /* Skip expensive computation on obvious mismatch */
+ if( ! mbedtls_pk_can_do( &parent->pk, child->sig_pk ) )
return( -1 );
+
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && child->sig_pk == MBEDTLS_PK_ECDSA )
+ {
+ return( mbedtls_pk_verify_restartable( &parent->pk,
+ child->sig_md, hash, mbedtls_md_get_size( md_info ),
+ child->sig.p, child->sig.len, &rs_ctx->pk ) );
}
+#else
+ (void) rs_ctx;
+#endif
- return( 0 );
+ return( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk,
+ child->sig_md, hash, mbedtls_md_get_size( md_info ),
+ child->sig.p, child->sig.len ) );
}
/*
@@ -1962,6 +1994,7 @@ static int x509_crt_check_parent( const mbedtls_x509_crt *child,
* 1. subject name matches child's issuer
* 2. if necessary, the CA bit is set and key usage allows signing certs
* 3. for trusted roots, the signature is correct
+ * (for intermediates, the signature is checked and the result reported)
* 4. pathlen constraints are satisfied
*
* If there's a suitable candidate which is also time-valid, return the first
@@ -1984,23 +2017,54 @@ static int x509_crt_check_parent( const mbedtls_x509_crt *child,
* Arguments:
* - [in] child: certificate for which we're looking for a parent
* - [in] candidates: chained list of potential parents
+ * - [out] r_parent: parent found (or NULL)
+ * - [out] r_signature_is_good: 1 if child signature by parent is valid, or 0
* - [in] top: 1 if candidates consists of trusted roots, ie we're at the top
* of the chain, 0 otherwise
* - [in] path_cnt: number of intermediates seen so far
* - [in] self_cnt: number of self-signed intermediates seen so far
* (will never be greater than path_cnt)
+ * - [in-out] rs_ctx: context for restarting operations
*
* Return value:
- * - the first suitable parent found (see above regarding time-validity)
- * - NULL if no suitable parent was found
+ * - 0 on success
+ * - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise
*/
-static mbedtls_x509_crt *x509_crt_find_parent_in( mbedtls_x509_crt *child,
- mbedtls_x509_crt *candidates,
- int top,
- size_t path_cnt,
- size_t self_cnt )
+static int x509_crt_find_parent_in(
+ mbedtls_x509_crt *child,
+ mbedtls_x509_crt *candidates,
+ mbedtls_x509_crt **r_parent,
+ int *r_signature_is_good,
+ int top,
+ unsigned path_cnt,
+ unsigned self_cnt,
+ mbedtls_x509_crt_restart_ctx *rs_ctx )
{
- mbedtls_x509_crt *parent, *badtime_parent = NULL;
+ int ret;
+ mbedtls_x509_crt *parent, *fallback_parent;
+ int signature_is_good, fallback_signature_is_good;
+
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ /* did we have something in progress? */
+ if( rs_ctx != NULL && rs_ctx->parent != NULL )
+ {
+ /* restore saved state */
+ parent = rs_ctx->parent;
+ fallback_parent = rs_ctx->fallback_parent;
+ fallback_signature_is_good = rs_ctx->fallback_signature_is_good;
+
+ /* clear saved state */
+ rs_ctx->parent = NULL;
+ rs_ctx->fallback_parent = NULL;
+ rs_ctx->fallback_signature_is_good = 0;
+
+ /* resume where we left */
+ goto check_signature;
+ }
+#endif
+
+ fallback_parent = NULL;
+ fallback_signature_is_good = 0;
for( parent = candidates; parent != NULL; parent = parent->next )
{
@@ -2016,17 +2080,38 @@ static mbedtls_x509_crt *x509_crt_find_parent_in( mbedtls_x509_crt *child,
}
/* Signature */
- if( top && x509_crt_check_signature( child, parent ) != 0 )
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+check_signature:
+#endif
+ ret = x509_crt_check_signature( child, parent, rs_ctx );
+
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
{
- continue;
+ /* save state */
+ rs_ctx->parent = parent;
+ rs_ctx->fallback_parent = fallback_parent;
+ rs_ctx->fallback_signature_is_good = fallback_signature_is_good;
+
+ return( ret );
}
+#else
+ (void) ret;
+#endif
+
+ signature_is_good = ret == 0;
+ if( top && ! signature_is_good )
+ continue;
/* optional time check */
if( mbedtls_x509_time_is_past( &parent->valid_to ) ||
mbedtls_x509_time_is_future( &parent->valid_from ) )
{
- if( badtime_parent == NULL )
- badtime_parent = parent;
+ if( fallback_parent == NULL )
+ {
+ fallback_parent = parent;
+ fallback_signature_is_good = signature_is_good;
+ }
continue;
}
@@ -2034,10 +2119,18 @@ static mbedtls_x509_crt *x509_crt_find_parent_in( mbedtls_x509_crt *child,
break;
}
- if( parent == NULL )
- parent = badtime_parent;
+ if( parent != NULL )
+ {
+ *r_parent = parent;
+ *r_signature_is_good = signature_is_good;
+ }
+ else
+ {
+ *r_parent = fallback_parent;
+ *r_signature_is_good = fallback_signature_is_good;
+ }
- return( parent );
+ return( 0 );
}
/*
@@ -2049,34 +2142,78 @@ static mbedtls_x509_crt *x509_crt_find_parent_in( mbedtls_x509_crt *child,
* Arguments:
* - [in] child: certificate for which we're looking for a parent, followed
* by a chain of possible intermediates
- * - [in] trust_ca: locally trusted CAs
- * - [out] 1 if parent was found in trust_ca, 0 if found in provided chain
- * - [in] path_cnt: number of intermediates seen so far
- * - [in] self_cnt: number of self-signed intermediates seen so far
+ * - [in] trust_ca: list of locally trusted certificates
+ * - [out] parent: parent found (or NULL)
+ * - [out] parent_is_trusted: 1 if returned `parent` is trusted, or 0
+ * - [out] signature_is_good: 1 if child signature by parent is valid, or 0
+ * - [in] path_cnt: number of links in the chain so far (EE -> ... -> child)
+ * - [in] self_cnt: number of self-signed certs in the chain so far
* (will always be no greater than path_cnt)
+ * - [in-out] rs_ctx: context for restarting operations
*
* Return value:
- * - the first suitable parent found (see find_parent_in() for "suitable")
- * - NULL if no suitable parent was found
+ * - 0 on success
+ * - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise
*/
-static mbedtls_x509_crt *x509_crt_find_parent( mbedtls_x509_crt *child,
- mbedtls_x509_crt *trust_ca,
- int *parent_is_trusted,
- size_t path_cnt,
- size_t self_cnt )
+static int x509_crt_find_parent(
+ mbedtls_x509_crt *child,
+ mbedtls_x509_crt *trust_ca,
+ mbedtls_x509_crt **parent,
+ int *parent_is_trusted,
+ int *signature_is_good,
+ unsigned path_cnt,
+ unsigned self_cnt,
+ mbedtls_x509_crt_restart_ctx *rs_ctx )
{
- mbedtls_x509_crt *parent;
+ int ret;
+ mbedtls_x509_crt *search_list;
- /* Look for a parent in trusted CAs */
*parent_is_trusted = 1;
- parent = x509_crt_find_parent_in( child, trust_ca, 1, path_cnt, self_cnt );
- if( parent != NULL )
- return( parent );
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ /* restore then clear saved state if we have some stored */
+ if( rs_ctx != NULL && rs_ctx->parent_is_trusted != -1 )
+ {
+ *parent_is_trusted = rs_ctx->parent_is_trusted;
+ rs_ctx->parent_is_trusted = -1;
+ }
+#endif
+
+ while( 1 ) {
+ search_list = *parent_is_trusted ? trust_ca : child->next;
+
+ ret = x509_crt_find_parent_in( child, search_list,
+ parent, signature_is_good,
+ *parent_is_trusted,
+ path_cnt, self_cnt, rs_ctx );
+
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
+ {
+ /* save state */
+ rs_ctx->parent_is_trusted = *parent_is_trusted;
+ return( ret );
+ }
+#else
+ (void) ret;
+#endif
+
+ /* stop here if found or already in second iteration */
+ if( *parent != NULL || *parent_is_trusted == 0 )
+ break;
+
+ /* prepare second iteration */
+ *parent_is_trusted = 0;
+ }
+
+ /* extra precaution against mistakes in the caller */
+ if( *parent == NULL )
+ {
+ *parent_is_trusted = 0;
+ *signature_is_good = 0;
+ }
- /* Look for a parent upwards the chain */
- *parent_is_trusted = 0;
- return( x509_crt_find_parent_in( child, child->next, 0, path_cnt, self_cnt ) );
+ return( 0 );
}
/*
@@ -2125,11 +2262,24 @@ static int x509_crt_check_ee_locally_trusted(
* - EE, Ci1, ..., Ciq cannot be continued with a trusted root
* -> return that chain with NOT_TRUSTED set on Ciq
*
+ * Tests for (aspects of) this function should include at least:
+ * - trusted EE
+ * - EE -> trusted root
+ * - EE -> intermedate CA -> trusted root
+ * - if relevant: EE untrusted
+ * - if relevant: EE -> intermediate, untrusted
+ * with the aspect under test checked at each relevant level (EE, int, root).
+ * For some aspects longer chains are required, but usually length 2 is
+ * enough (but length 1 is not in general).
+ *
* Arguments:
* - [in] crt: the cert list EE, C1, ..., Cn
* - [in] trust_ca: the trusted list R1, ..., Rp
* - [in] ca_crl, profile: as in verify_with_profile()
- * - [out] ver_chain, chain_len: the built and verified chain
+ * - [out] ver_chain: the built and verified chain
+ * Only valid when return value is 0, may contain garbage otherwise!
+ * Restart note: need not be the same when calling again to resume.
+ * - [in-out] rs_ctx: context for restarting operations
*
* Return value:
* - non-zero if the chain could not be fully built and examined
@@ -2141,24 +2291,50 @@ static int x509_crt_verify_chain(
mbedtls_x509_crt *trust_ca,
mbedtls_x509_crl *ca_crl,
const mbedtls_x509_crt_profile *profile,
- x509_crt_verify_chain_item ver_chain[X509_MAX_VERIFY_CHAIN_SIZE],
- size_t *chain_len )
+ mbedtls_x509_crt_verify_chain *ver_chain,
+ mbedtls_x509_crt_restart_ctx *rs_ctx )
{
+ /* Don't initialize any of those variables here, so that the compiler can
+ * catch potential issues with jumping ahead when restarting */
+ int ret;
uint32_t *flags;
+ mbedtls_x509_crt_verify_chain_item *cur;
mbedtls_x509_crt *child;
mbedtls_x509_crt *parent;
- int parent_is_trusted = 0;
- int child_is_trusted = 0;
- size_t self_cnt = 0;
+ int parent_is_trusted;
+ int child_is_trusted;
+ int signature_is_good;
+ unsigned self_cnt;
+
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ /* resume if we had an operation in progress */
+ if( rs_ctx != NULL && rs_ctx->in_progress == x509_crt_rs_find_parent )
+ {
+ /* restore saved state */
+ *ver_chain = rs_ctx->ver_chain; /* struct copy */
+ self_cnt = rs_ctx->self_cnt;
+
+ /* restore derived state */
+ cur = &ver_chain->items[ver_chain->len - 1];
+ child = cur->crt;
+ flags = &cur->flags;
+
+ goto find_parent;
+ }
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
child = crt;
- *chain_len = 0;
+ self_cnt = 0;
+ parent_is_trusted = 0;
+ child_is_trusted = 0;
while( 1 ) {
/* Add certificate to the verification chain */
- ver_chain[*chain_len].crt = child;
- flags = &ver_chain[*chain_len].flags;
- ++*chain_len;
+ cur = &ver_chain->items[ver_chain->len];
+ cur->crt = child;
+ cur->flags = 0;
+ ver_chain->len++;
+ flags = &cur->flags;
/* Check time-validity (all certificates) */
if( mbedtls_x509_time_is_past( &child->valid_to ) )
@@ -2179,15 +2355,33 @@ static int x509_crt_verify_chain(
*flags |= MBEDTLS_X509_BADCERT_BAD_PK;
/* Special case: EE certs that are locally trusted */
- if( *chain_len == 1 &&
+ if( ver_chain->len == 1 &&
x509_crt_check_ee_locally_trusted( child, trust_ca ) == 0 )
{
return( 0 );
}
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+find_parent:
+#endif
/* Look for a parent in trusted CAs or up the chain */
- parent = x509_crt_find_parent( child, trust_ca, &parent_is_trusted,
- *chain_len - 1, self_cnt );
+ ret = x509_crt_find_parent( child, trust_ca, &parent,
+ &parent_is_trusted, &signature_is_good,
+ ver_chain->len - 1, self_cnt, rs_ctx );
+
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
+ {
+ /* save state */
+ rs_ctx->in_progress = x509_crt_rs_find_parent;
+ rs_ctx->self_cnt = self_cnt;
+ rs_ctx->ver_chain = *ver_chain; /* struct copy */
+
+ return( ret );
+ }
+#else
+ (void) ret;
+#endif
/* No parent? We're done here */
if( parent == NULL )
@@ -2199,7 +2393,7 @@ static int x509_crt_verify_chain(
/* Count intermediate self-issued (not necessarily self-signed) certs.
* These can occur with some strategies for key rollover, see [SIRO],
* and should be excluded from max_pathlen checks. */
- if( *chain_len != 1 &&
+ if( ver_chain->len != 1 &&
x509_name_cmp( &child->issuer, &child->subject ) == 0 )
{
self_cnt++;
@@ -2208,14 +2402,14 @@ static int x509_crt_verify_chain(
/* path_cnt is 0 for the first intermediate CA,
* and if parent is trusted it's not an intermediate CA */
if( ! parent_is_trusted &&
- *chain_len > MBEDTLS_X509_MAX_INTERMEDIATE_CA )
+ ver_chain->len > MBEDTLS_X509_MAX_INTERMEDIATE_CA )
{
/* return immediately to avoid overflow the chain array */
return( MBEDTLS_ERR_X509_FATAL_ERROR );
}
- /* if parent is trusted, the signature was checked by find_parent() */
- if( ! parent_is_trusted && x509_crt_check_signature( child, parent ) != 0 )
+ /* signature was checked while searching parent */
+ if( ! signature_is_good )
*flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED;
/* check size of signing key */
@@ -2233,6 +2427,7 @@ static int x509_crt_verify_chain(
child = parent;
parent = NULL;
child_is_trusted = parent_is_trusted;
+ signature_is_good = 0;
}
}
@@ -2301,21 +2496,22 @@ static void x509_crt_verify_name( const mbedtls_x509_crt *crt,
*/
static int x509_crt_merge_flags_with_cb(
uint32_t *flags,
- x509_crt_verify_chain_item ver_chain[X509_MAX_VERIFY_CHAIN_SIZE],
- size_t chain_len,
+ const mbedtls_x509_crt_verify_chain *ver_chain,
int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
void *p_vrfy )
{
int ret;
- size_t i;
+ unsigned i;
uint32_t cur_flags;
+ const mbedtls_x509_crt_verify_chain_item *cur;
- for( i = chain_len; i != 0; --i )
+ for( i = ver_chain->len; i != 0; --i )
{
- cur_flags = ver_chain[i-1].flags;
+ cur = &ver_chain->items[i-1];
+ cur_flags = cur->flags;
if( NULL != f_vrfy )
- if( ( ret = f_vrfy( p_vrfy, ver_chain[i-1].crt, (int) i-1, &cur_flags ) ) != 0 )
+ if( ( ret = f_vrfy( p_vrfy, cur->crt, (int) i-1, &cur_flags ) ) != 0 )
return( ret );
*flags |= cur_flags;
@@ -2325,7 +2521,7 @@ static int x509_crt_merge_flags_with_cb(
}
/*
- * Verify the certificate validity
+ * Verify the certificate validity (default profile, not restartable)
*/
int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt,
mbedtls_x509_crt *trust_ca,
@@ -2334,12 +2530,28 @@ int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt,
int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
void *p_vrfy )
{
- return( mbedtls_x509_crt_verify_with_profile( crt, trust_ca, ca_crl,
- &mbedtls_x509_crt_profile_default, cn, flags, f_vrfy, p_vrfy ) );
+ return( mbedtls_x509_crt_verify_restartable( crt, trust_ca, ca_crl,
+ &mbedtls_x509_crt_profile_default, cn, flags,
+ f_vrfy, p_vrfy, NULL ) );
+}
+
+/*
+ * Verify the certificate validity (user-chosen profile, not restartable)
+ */
+int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt,
+ mbedtls_x509_crt *trust_ca,
+ mbedtls_x509_crl *ca_crl,
+ const mbedtls_x509_crt_profile *profile,
+ const char *cn, uint32_t *flags,
+ int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
+ void *p_vrfy )
+{
+ return( mbedtls_x509_crt_verify_restartable( crt, trust_ca, ca_crl,
+ profile, cn, flags, f_vrfy, p_vrfy, NULL ) );
}
/*
- * Verify the certificate validity, with profile
+ * Verify the certificate validity, with profile, restartable version
*
* This function:
* - checks the requested CN (if any)
@@ -2348,23 +2560,23 @@ int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt,
* - builds and verifies the chain
* - then calls the callback and merges the flags
*/
-int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt,
+int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt,
mbedtls_x509_crt *trust_ca,
mbedtls_x509_crl *ca_crl,
const mbedtls_x509_crt_profile *profile,
const char *cn, uint32_t *flags,
int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
- void *p_vrfy )
+ void *p_vrfy,
+ mbedtls_x509_crt_restart_ctx *rs_ctx )
{
int ret;
mbedtls_pk_type_t pk_type;
- x509_crt_verify_chain_item ver_chain[X509_MAX_VERIFY_CHAIN_SIZE];
- size_t chain_len;
- uint32_t *ee_flags = &ver_chain[0].flags;
+ mbedtls_x509_crt_verify_chain ver_chain;
+ uint32_t ee_flags;
*flags = 0;
- memset( ver_chain, 0, sizeof( ver_chain ) );
- chain_len = 0;
+ ee_flags = 0;
+ x509_crt_verify_chain_reset( &ver_chain );
if( profile == NULL )
{
@@ -2374,28 +2586,36 @@ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt,
/* check name if requested */
if( cn != NULL )
- x509_crt_verify_name( crt, cn, ee_flags );
+ x509_crt_verify_name( crt, cn, &ee_flags );
/* Check the type and size of the key */
pk_type = mbedtls_pk_get_type( &crt->pk );
if( x509_profile_check_pk_alg( profile, pk_type ) != 0 )
- *ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK;
+ ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK;
if( x509_profile_check_key( profile, &crt->pk ) != 0 )
- *ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
+ ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
/* Check the chain */
ret = x509_crt_verify_chain( crt, trust_ca, ca_crl, profile,
- ver_chain, &chain_len );
+ &ver_chain, rs_ctx );
+
if( ret != 0 )
goto exit;
+ /* Merge end-entity flags */
+ ver_chain.items[0].flags |= ee_flags;
+
/* Build final flags, calling callback on the way if any */
- ret = x509_crt_merge_flags_with_cb( flags,
- ver_chain, chain_len, f_vrfy, p_vrfy );
+ ret = x509_crt_merge_flags_with_cb( flags, &ver_chain, f_vrfy, p_vrfy );
exit:
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
+ mbedtls_x509_crt_restart_free( rs_ctx );
+#endif
+
/* prevent misuse of the vrfy callback - VERIFY_FAILED would be ignored by
* the SSL module for authmode optional, but non-zero return from the
* callback means a fatal error so it shouldn't be ignored */
@@ -2506,4 +2726,36 @@ void mbedtls_x509_crt_free( mbedtls_x509_crt *crt )
while( cert_cur != NULL );
}
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+/*
+ * Initialize a restart context
+ */
+void mbedtls_x509_crt_restart_init( mbedtls_x509_crt_restart_ctx *ctx )
+{
+ mbedtls_pk_restart_init( &ctx->pk );
+
+ ctx->parent = NULL;
+ ctx->fallback_parent = NULL;
+ ctx->fallback_signature_is_good = 0;
+
+ ctx->parent_is_trusted = -1;
+
+ ctx->in_progress = x509_crt_rs_none;
+ ctx->self_cnt = 0;
+ x509_crt_verify_chain_reset( &ctx->ver_chain );
+}
+
+/*
+ * Free the components of a restart context
+ */
+void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx )
+{
+ if( ctx == NULL )
+ return;
+
+ mbedtls_pk_restart_free( &ctx->pk );
+ mbedtls_x509_crt_restart_init( ctx );
+}
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+
#endif /* MBEDTLS_X509_CRT_PARSE_C */
diff --git a/thirdparty/mbedtls/padlock.diff b/thirdparty/mbedtls/padlock.diff
new file mode 100644
index 0000000000..6ace48891c
--- /dev/null
+++ b/thirdparty/mbedtls/padlock.diff
@@ -0,0 +1,13 @@
+--- a/thirdparty/mbedtls/include/mbedtls/config.h
++++ b/thirdparty/mbedtls/include/mbedtls/config.h
+@@ -2477,7 +2477,9 @@
+ *
+ * This modules adds support for the VIA PadLock on x86.
+ */
+-#define MBEDTLS_PADLOCK_C
++// -- GODOT start --
++// #define MBEDTLS_PADLOCK_C
++// -- GODOT end --
+
+ /**
+ * \def MBEDTLS_PEM_PARSE_C
diff --git a/thirdparty/misc/base64.h b/thirdparty/misc/base64.h
index 4c300382c1..ffcd0af973 100644
--- a/thirdparty/misc/base64.h
+++ b/thirdparty/misc/base64.h
@@ -11,8 +11,8 @@
extern "C" {
-uint32_t base64_encode(char *to, char *from, uint32_t len);
-uint32_t base64_decode(char *to, char *from, uint32_t len);
+long base64_encode(char *to, char *from, unsigned int len);
+long base64_decode(char *to, char *from, unsigned int len);
};
#endif /* BASE64_H */
diff --git a/thirdparty/misc/clipper-exceptions.patch b/thirdparty/misc/clipper-exceptions.patch
new file mode 100644
index 0000000000..537afd59b3
--- /dev/null
+++ b/thirdparty/misc/clipper-exceptions.patch
@@ -0,0 +1,154 @@
+diff --git a/thirdparty/misc/clipper.cpp b/thirdparty/misc/clipper.cpp
+index 8c3a59c4ca..c67045d113 100644
+--- a/thirdparty/misc/clipper.cpp
++++ b/thirdparty/misc/clipper.cpp
+@@ -48,6 +48,38 @@
+ #include <ostream>
+ #include <functional>
+
++//Explicitly disables exceptions handling for target platform
++//#define CLIPPER_NOEXCEPTION
++
++#define CLIPPER_THROW(exception) std::abort()
++#define CLIPPER_TRY if(true)
++#define CLIPPER_CATCH(exception) if(false)
++
++#if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)
++ #ifndef CLIPPER_NOEXCEPTION
++ #undef CLIPPER_THROW
++ #define CLIPPER_THROW(exception) throw exception
++ #undef CLIPPER_TRY
++ #define CLIPPER_TRY try
++ #undef CLIPPER_CATCH
++ #define CLIPPER_CATCH(exception) catch(exception)
++ #endif
++#endif
++
++//Optionally allows to override exception macros
++#if defined(CLIPPER_THROW_USER)
++ #undef CLIPPER_THROW
++ #define CLIPPER_THROW CLIPPER_THROW_USER
++#endif
++#if defined(CLIPPER_TRY_USER)
++ #undef CLIPPER_TRY
++ #define CLIPPER_TRY CLIPPER_TRY_USER
++#endif
++#if defined(CLIPPER_CATCH_USER)
++ #undef CLIPPER_CATCH
++ #define CLIPPER_CATCH CLIPPER_CATCH_USER
++#endif
++
+ namespace ClipperLib {
+
+ static double const pi = 3.141592653589793238;
+@@ -898,7 +930,7 @@ void RangeTest(const IntPoint& Pt, bool& useFullRange)
+ if (useFullRange)
+ {
+ if (Pt.X > hiRange || Pt.Y > hiRange || -Pt.X > hiRange || -Pt.Y > hiRange)
+- throw clipperException("Coordinate outside allowed range");
++ CLIPPER_THROW(clipperException("Coordinate outside allowed range"));
+ }
+ else if (Pt.X > loRange|| Pt.Y > loRange || -Pt.X > loRange || -Pt.Y > loRange)
+ {
+@@ -1046,10 +1078,10 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed)
+ {
+ #ifdef use_lines
+ if (!Closed && PolyTyp == ptClip)
+- throw clipperException("AddPath: Open paths must be subject.");
++ CLIPPER_THROW(clipperException("AddPath: Open paths must be subject."));
+ #else
+ if (!Closed)
+- throw clipperException("AddPath: Open paths have been disabled.");
++ CLIPPER_THROW(clipperException("AddPath: Open paths have been disabled."));
+ #endif
+
+ int highI = (int)pg.size() -1;
+@@ -1062,7 +1094,7 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed)
+
+ bool IsFlat = true;
+ //1. Basic (first) edge initialization ...
+- try
++ CLIPPER_TRY
+ {
+ edges[1].Curr = pg[1];
+ RangeTest(pg[0], m_UseFullRange);
+@@ -1075,10 +1107,10 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed)
+ InitEdge(&edges[i], &edges[i+1], &edges[i-1], pg[i]);
+ }
+ }
+- catch(...)
++ CLIPPER_CATCH(...)
+ {
+ delete [] edges;
+- throw; //range test fails
++ CLIPPER_THROW(); //range test fails
+ }
+ TEdge *eStart = &edges[0];
+
+@@ -1442,7 +1474,7 @@ void ClipperBase::SwapPositionsInAEL(TEdge *Edge1, TEdge *Edge2)
+ void ClipperBase::UpdateEdgeIntoAEL(TEdge *&e)
+ {
+ if (!e->NextInLML)
+- throw clipperException("UpdateEdgeIntoAEL: invalid call");
++ CLIPPER_THROW(clipperException("UpdateEdgeIntoAEL: invalid call"));
+
+ e->NextInLML->OutIdx = e->OutIdx;
+ TEdge* AelPrev = e->PrevInAEL;
+@@ -1510,7 +1542,7 @@ bool Clipper::Execute(ClipType clipType, Paths &solution,
+ {
+ if( m_ExecuteLocked ) return false;
+ if (m_HasOpenPaths)
+- throw clipperException("Error: PolyTree struct is needed for open path clipping.");
++ CLIPPER_THROW(clipperException("Error: PolyTree struct is needed for open path clipping."));
+ m_ExecuteLocked = true;
+ solution.resize(0);
+ m_SubjFillType = subjFillType;
+@@ -1560,7 +1592,7 @@ void Clipper::FixHoleLinkage(OutRec &outrec)
+ bool Clipper::ExecuteInternal()
+ {
+ bool succeeded = true;
+- try {
++ CLIPPER_TRY {
+ Reset();
+ m_Maxima = MaximaList();
+ m_SortedEdges = 0;
+@@ -1583,7 +1615,7 @@ bool Clipper::ExecuteInternal()
+ InsertLocalMinimaIntoAEL(botY);
+ }
+ }
+- catch(...)
++ CLIPPER_CATCH(...)
+ {
+ succeeded = false;
+ }
+@@ -2827,18 +2859,18 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge)
+ bool Clipper::ProcessIntersections(const cInt topY)
+ {
+ if( !m_ActiveEdges ) return true;
+- try {
++ CLIPPER_TRY {
+ BuildIntersectList(topY);
+ size_t IlSize = m_IntersectList.size();
+ if (IlSize == 0) return true;
+ if (IlSize == 1 || FixupIntersectionOrder()) ProcessIntersectList();
+ else return false;
+ }
+- catch(...)
++ CLIPPER_CATCH(...)
+ {
+ m_SortedEdges = 0;
+ DisposeIntersectNodes();
+- throw clipperException("ProcessIntersections error");
++ CLIPPER_THROW(clipperException("ProcessIntersections error"));
+ }
+ m_SortedEdges = 0;
+ return true;
+@@ -3002,7 +3034,7 @@ void Clipper::DoMaxima(TEdge *e)
+ DeleteFromAEL(eMaxPair);
+ }
+ #endif
+- else throw clipperException("DoMaxima error");
++ else CLIPPER_THROW(clipperException("DoMaxima error"));
+ }
+ //------------------------------------------------------------------------------
+
diff --git a/thirdparty/misc/clipper.cpp b/thirdparty/misc/clipper.cpp
index d3143fe5ab..c67045d113 100644
--- a/thirdparty/misc/clipper.cpp
+++ b/thirdparty/misc/clipper.cpp
@@ -48,6 +48,38 @@
#include <ostream>
#include <functional>
+//Explicitly disables exceptions handling for target platform
+//#define CLIPPER_NOEXCEPTION
+
+#define CLIPPER_THROW(exception) std::abort()
+#define CLIPPER_TRY if(true)
+#define CLIPPER_CATCH(exception) if(false)
+
+#if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)
+ #ifndef CLIPPER_NOEXCEPTION
+ #undef CLIPPER_THROW
+ #define CLIPPER_THROW(exception) throw exception
+ #undef CLIPPER_TRY
+ #define CLIPPER_TRY try
+ #undef CLIPPER_CATCH
+ #define CLIPPER_CATCH(exception) catch(exception)
+ #endif
+#endif
+
+//Optionally allows to override exception macros
+#if defined(CLIPPER_THROW_USER)
+ #undef CLIPPER_THROW
+ #define CLIPPER_THROW CLIPPER_THROW_USER
+#endif
+#if defined(CLIPPER_TRY_USER)
+ #undef CLIPPER_TRY
+ #define CLIPPER_TRY CLIPPER_TRY_USER
+#endif
+#if defined(CLIPPER_CATCH_USER)
+ #undef CLIPPER_CATCH
+ #define CLIPPER_CATCH CLIPPER_CATCH_USER
+#endif
+
namespace ClipperLib {
static double const pi = 3.141592653589793238;
@@ -898,7 +930,7 @@ void RangeTest(const IntPoint& Pt, bool& useFullRange)
if (useFullRange)
{
if (Pt.X > hiRange || Pt.Y > hiRange || -Pt.X > hiRange || -Pt.Y > hiRange)
- throw clipperException("Coordinate outside allowed range");
+ CLIPPER_THROW(clipperException("Coordinate outside allowed range"));
}
else if (Pt.X > loRange|| Pt.Y > loRange || -Pt.X > loRange || -Pt.Y > loRange)
{
@@ -1046,10 +1078,10 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed)
{
#ifdef use_lines
if (!Closed && PolyTyp == ptClip)
- throw clipperException("AddPath: Open paths must be subject.");
+ CLIPPER_THROW(clipperException("AddPath: Open paths must be subject."));
#else
if (!Closed)
- throw clipperException("AddPath: Open paths have been disabled.");
+ CLIPPER_THROW(clipperException("AddPath: Open paths have been disabled."));
#endif
int highI = (int)pg.size() -1;
@@ -1062,7 +1094,7 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed)
bool IsFlat = true;
//1. Basic (first) edge initialization ...
- try
+ CLIPPER_TRY
{
edges[1].Curr = pg[1];
RangeTest(pg[0], m_UseFullRange);
@@ -1075,10 +1107,10 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed)
InitEdge(&edges[i], &edges[i+1], &edges[i-1], pg[i]);
}
}
- catch(...)
+ CLIPPER_CATCH(...)
{
delete [] edges;
- throw; //range test fails
+ CLIPPER_THROW(); //range test fails
}
TEdge *eStart = &edges[0];
@@ -1442,7 +1474,7 @@ void ClipperBase::SwapPositionsInAEL(TEdge *Edge1, TEdge *Edge2)
void ClipperBase::UpdateEdgeIntoAEL(TEdge *&e)
{
if (!e->NextInLML)
- throw clipperException("UpdateEdgeIntoAEL: invalid call");
+ CLIPPER_THROW(clipperException("UpdateEdgeIntoAEL: invalid call"));
e->NextInLML->OutIdx = e->OutIdx;
TEdge* AelPrev = e->PrevInAEL;
@@ -1510,7 +1542,7 @@ bool Clipper::Execute(ClipType clipType, Paths &solution,
{
if( m_ExecuteLocked ) return false;
if (m_HasOpenPaths)
- throw clipperException("Error: PolyTree struct is needed for open path clipping.");
+ CLIPPER_THROW(clipperException("Error: PolyTree struct is needed for open path clipping."));
m_ExecuteLocked = true;
solution.resize(0);
m_SubjFillType = subjFillType;
@@ -1560,7 +1592,7 @@ void Clipper::FixHoleLinkage(OutRec &outrec)
bool Clipper::ExecuteInternal()
{
bool succeeded = true;
- try {
+ CLIPPER_TRY {
Reset();
m_Maxima = MaximaList();
m_SortedEdges = 0;
@@ -1583,7 +1615,7 @@ bool Clipper::ExecuteInternal()
InsertLocalMinimaIntoAEL(botY);
}
}
- catch(...)
+ CLIPPER_CATCH(...)
{
succeeded = false;
}
@@ -2827,18 +2859,18 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge)
bool Clipper::ProcessIntersections(const cInt topY)
{
if( !m_ActiveEdges ) return true;
- try {
+ CLIPPER_TRY {
BuildIntersectList(topY);
size_t IlSize = m_IntersectList.size();
if (IlSize == 0) return true;
if (IlSize == 1 || FixupIntersectionOrder()) ProcessIntersectList();
else return false;
}
- catch(...)
+ CLIPPER_CATCH(...)
{
m_SortedEdges = 0;
DisposeIntersectNodes();
- throw clipperException("ProcessIntersections error");
+ CLIPPER_THROW(clipperException("ProcessIntersections error"));
}
m_SortedEdges = 0;
return true;
@@ -3002,7 +3034,7 @@ void Clipper::DoMaxima(TEdge *e)
DeleteFromAEL(eMaxPair);
}
#endif
- else throw clipperException("DoMaxima error");
+ else CLIPPER_THROW(clipperException("DoMaxima error"));
}
//------------------------------------------------------------------------------
@@ -4329,10 +4361,10 @@ double DistanceFromLineSqrd(
const IntPoint& pt, const IntPoint& ln1, const IntPoint& ln2)
{
//The equation of a line in general form (Ax + By + C = 0)
- //given 2 points (x¹,y¹) & (x²,y²) is ...
- //(y¹ - y²)x + (x² - x¹)y + (y² - y¹)x¹ - (x² - x¹)y¹ = 0
- //A = (y¹ - y²); B = (x² - x¹); C = (y² - y¹)x¹ - (x² - x¹)y¹
- //perpendicular distance of point (x³,y³) = (Ax³ + By³ + C)/Sqrt(A² + B²)
+ //given 2 points (x¹,y¹) & (x²,y²) is ...
+ //(y¹ - y²)x + (x² - x¹)y + (y² - y¹)x¹ - (x² - x¹)y¹ = 0
+ //A = (y¹ - y²); B = (x² - x¹); C = (y² - y¹)x¹ - (x² - x¹)y¹
+ //perpendicular distance of point (x³,y³) = (Ax³ + By³ + C)/Sqrt(A² + B²)
//see http://en.wikipedia.org/wiki/Perpendicular_distance
double A = double(ln1.Y - ln2.Y);
double B = double(ln2.X - ln1.X);
diff --git a/thirdparty/misc/pcg.cpp b/thirdparty/misc/pcg.cpp
index eac3b36d36..c421e16f89 100644
--- a/thirdparty/misc/pcg.cpp
+++ b/thirdparty/misc/pcg.cpp
@@ -13,3 +13,13 @@ uint32_t pcg32_random_r(pcg32_random_t* rng)
uint32_t rot = oldstate >> 59u;
return (xorshifted >> rot) | (xorshifted << ((-rot) & 31));
}
+
+// Source from http://www.pcg-random.org/downloads/pcg-c-basic-0.9.zip
+void pcg32_srandom_r(pcg32_random_t* rng, uint64_t initstate, uint64_t initseq)
+{
+ rng->state = 0U;
+ rng->inc = (initseq << 1u) | 1u;
+ pcg32_random_r(rng);
+ rng->state += initstate;
+ pcg32_random_r(rng);
+}
diff --git a/thirdparty/misc/pcg.h b/thirdparty/misc/pcg.h
index e2d66d51d5..6f42b3b094 100644
--- a/thirdparty/misc/pcg.h
+++ b/thirdparty/misc/pcg.h
@@ -10,5 +10,6 @@
typedef struct { uint64_t state; uint64_t inc; } pcg32_random_t;
uint32_t pcg32_random_r(pcg32_random_t* rng);
+void pcg32_srandom_r(pcg32_random_t* rng, uint64_t initstate, uint64_t initseq);
#endif // RANDOM_H
diff --git a/thirdparty/misc/stb_truetype.h b/thirdparty/misc/stb_truetype.h
index e2efae2285..72299ea86d 100644
--- a/thirdparty/misc/stb_truetype.h
+++ b/thirdparty/misc/stb_truetype.h
@@ -1,4 +1,4 @@
-// stb_truetype.h - v1.19 - public domain
+// stb_truetype.h - v1.21 - public domain
// authored from 2009-2016 by Sean Barrett / RAD Game Tools
//
// This library processes TrueType files:
@@ -49,6 +49,8 @@
//
// VERSION HISTORY
//
+// 1.21 (2019-02-25) fix warning
+// 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics()
// 1.19 (2018-02-11) GPOS kerning, STBTT_fmod
// 1.18 (2018-01-29) add missing function
// 1.17 (2017-07-23) make more arguments const; doc fix
@@ -75,7 +77,7 @@
//
// USAGE
//
-// Include this file in whatever places neeed to refer to it. In ONE C/C++
+// Include this file in whatever places need to refer to it. In ONE C/C++
// file, write:
// #define STB_TRUETYPE_IMPLEMENTATION
// before the #include of this file. This expands out the actual
@@ -242,19 +244,6 @@
// recommend it.
//
//
-// SOURCE STATISTICS (based on v0.6c, 2050 LOC)
-//
-// Documentation & header file 520 LOC \___ 660 LOC documentation
-// Sample code 140 LOC /
-// Truetype parsing 620 LOC ---- 620 LOC TrueType
-// Software rasterization 240 LOC \ .
-// Curve tesselation 120 LOC \__ 550 LOC Bitmap creation
-// Bitmap management 100 LOC /
-// Baked bitmap interface 70 LOC /
-// Font name matching & access 150 LOC ---- 150
-// C runtime library abstraction 60 LOC ---- 60
-//
-//
// PERFORMANCE MEASUREMENTS FOR 1.06:
//
// 32-bit 64-bit
@@ -556,6 +545,8 @@ STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int p
//
// It's inefficient; you might want to c&p it and optimize it.
+STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap);
+// Query the font vertical metrics without having to create a font first.
//////////////////////////////////////////////////////////////////////////////
@@ -641,6 +632,12 @@ STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h
// To use with PackFontRangesGather etc., you must set it before calls
// call to PackFontRangesGatherRects.
+STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip);
+// If skip != 0, this tells stb_truetype to skip any codepoints for which
+// there is no corresponding glyph. If skip=0, which is the default, then
+// codepoints without a glyph recived the font's "missing character" glyph,
+// typically an empty box by convention.
+
STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above
int char_index, // character to display
float *xpos, float *ypos, // pointers to current position in screen pixel space
@@ -669,6 +666,7 @@ struct stbtt_pack_context {
int height;
int stride_in_bytes;
int padding;
+ int skip_missing;
unsigned int h_oversample, v_oversample;
unsigned char *pixels;
void *nodes;
@@ -694,7 +692,7 @@ STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index);
// file will only define one font and it always be at offset 0, so it will
// return '0' for index 0, and -1 for all other indices.
-// The following structure is defined publically so you can declare one on
+// The following structure is defined publicly so you can declare one on
// the stack or as a global or etc, but you should treat it as opaque.
struct stbtt_fontinfo
{
@@ -733,6 +731,7 @@ STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codep
// and you want a speed-up, call this function with the character you're
// going to process, then use glyph-based functions instead of the
// codepoint-based functions.
+// Returns 0 if the character codepoint is not defined in the font.
//////////////////////////////////////////////////////////////////////////////
@@ -820,7 +819,7 @@ STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, s
// returns # of vertices and fills *vertices with the pointer to them
// these are expressed in "unscaled" coordinates
//
-// The shape is a series of countours. Each one starts with
+// The shape is a series of contours. Each one starts with
// a STBTT_moveto, then consists of a series of mixed
// STBTT_lineto and STBTT_curveto segments. A lineto
// draws a line from previous endpoint to its x,y; a curveto
@@ -916,7 +915,7 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff);
// These functions compute a discretized SDF field for a single character, suitable for storing
// in a single-channel texture, sampling with bilinear filtering, and testing against
-// larger than some threshhold to produce scalable fonts.
+// larger than some threshold to produce scalable fonts.
// info -- the font
// scale -- controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap
// glyph/codepoint -- the character to generate the SDF for
@@ -2463,6 +2462,7 @@ static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, i
if (valueFormat2 != 0) return 0;
STBTT_assert(coverageIndex < pairSetCount);
+ STBTT__NOTUSED(pairSetCount);
needle=glyph2;
r=pairValueCount-1;
@@ -3160,7 +3160,13 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e,
if (e->y0 != e->y1) {
stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata);
if (z != NULL) {
- STBTT_assert(z->ey >= scan_y_top);
+ if (j == 0 && off_y != 0) {
+ if (z->ey < scan_y_top) {
+ // this can happen due to subpixel positioning and some kind of fp rounding error i think
+ z->ey = scan_y_top;
+ }
+ }
+ STBTT_assert(z->ey >= scan_y_top); // if we get really unlucky a tiny bit of an edge can be out of bounds
// insert at front
z->next = active;
active = z;
@@ -3229,7 +3235,7 @@ static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n)
static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n)
{
- /* threshhold for transitioning to insertion sort */
+ /* threshold for transitioning to insertion sort */
while (n > 12) {
stbtt__edge t;
int c01,c12,c,m,i,j;
@@ -3364,7 +3370,7 @@ static void stbtt__add_point(stbtt__point *points, int n, float x, float y)
points[n].y = y;
}
-// tesselate until threshhold p is happy... @TODO warped to compensate for non-linear stretching
+// tessellate until threshold p is happy... @TODO warped to compensate for non-linear stretching
static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n)
{
// midpoint
@@ -3789,6 +3795,7 @@ STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, in
spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw;
spc->h_oversample = 1;
spc->v_oversample = 1;
+ spc->skip_missing = 0;
stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes);
@@ -3814,6 +3821,11 @@ STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h
spc->v_oversample = v_oversample;
}
+STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip)
+{
+ spc->skip_missing = skip;
+}
+
#define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1)
static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width)
@@ -3967,13 +3979,17 @@ STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stb
int x0,y0,x1,y1;
int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
int glyph = stbtt_FindGlyphIndex(info, codepoint);
- stbtt_GetGlyphBitmapBoxSubpixel(info,glyph,
- scale * spc->h_oversample,
- scale * spc->v_oversample,
- 0,0,
- &x0,&y0,&x1,&y1);
- rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1);
- rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1);
+ if (glyph == 0 && spc->skip_missing) {
+ rects[k].w = rects[k].h = 0;
+ } else {
+ stbtt_GetGlyphBitmapBoxSubpixel(info,glyph,
+ scale * spc->h_oversample,
+ scale * spc->v_oversample,
+ 0,0,
+ &x0,&y0,&x1,&y1);
+ rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1);
+ rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1);
+ }
++k;
}
}
@@ -4026,7 +4042,7 @@ STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const
sub_y = stbtt__oversample_shift(spc->v_oversample);
for (j=0; j < ranges[i].num_chars; ++j) {
stbrp_rect *r = &rects[k];
- if (r->was_packed) {
+ if (r->was_packed && r->w != 0 && r->h != 0) {
stbtt_packedchar *bc = &ranges[i].chardata_for_range[j];
int advance, lsb, x0,y0,x1,y1;
int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
@@ -4140,6 +4156,19 @@ STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *
return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1);
}
+STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap)
+{
+ int i_ascent, i_descent, i_lineGap;
+ float scale;
+ stbtt_fontinfo info;
+ stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata, index));
+ scale = size > 0 ? stbtt_ScaleForPixelHeight(&info, size) : stbtt_ScaleForMappingEmToPixels(&info, -size);
+ stbtt_GetFontVMetrics(&info, &i_ascent, &i_descent, &i_lineGap);
+ *ascent = (float) i_ascent * scale;
+ *descent = (float) i_descent * scale;
+ *lineGap = (float) i_lineGap * scale;
+}
+
STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer)
{
float ipw = 1.0f / pw, iph = 1.0f / ph;
diff --git a/thirdparty/misc/stb_vorbis.c b/thirdparty/misc/stb_vorbis.c
index 8edcf0f38a..88276026ef 100644
--- a/thirdparty/misc/stb_vorbis.c
+++ b/thirdparty/misc/stb_vorbis.c
@@ -1,4 +1,4 @@
-// Ogg Vorbis audio decoder - v1.14 - public domain
+// Ogg Vorbis audio decoder - v1.15 - public domain
// http://nothings.org/stb_vorbis/
//
// Original version written by Sean Barrett in 2007.
@@ -33,6 +33,7 @@
// Timur Gagiev
//
// Partial history:
+// 1.15 - 2019-02-07 - explicit failure if Ogg Skeleton data is found
// 1.14 - 2018-02-11 - delete bogus dealloca usage
// 1.13 - 2018-01-29 - fix truncation of last frame (hopefully)
// 1.12 - 2017-11-21 - limit residue begin/end to blocksize/2 to avoid large temp allocs in bad/corrupt files
@@ -253,7 +254,7 @@ extern stb_vorbis * stb_vorbis_open_file(FILE *f, int close_handle_on_close,
// create an ogg vorbis decoder from an open FILE *, looking for a stream at
// the _current_ seek point (ftell). on failure, returns NULL and sets *error.
// note that stb_vorbis must "own" this stream; if you seek it in between
-// calls to stb_vorbis, it will become confused. Morever, if you attempt to
+// calls to stb_vorbis, it will become confused. Moreover, if you attempt to
// perform stb_vorbis_seek_*() operations on this file, it will assume it
// owns the _entire_ rest of the file after the start point. Use the next
// function, stb_vorbis_open_file_section(), to limit it.
@@ -374,7 +375,8 @@ enum STBVorbisError
VORBIS_invalid_first_page,
VORBIS_bad_packet_type,
VORBIS_cant_find_last_page,
- VORBIS_seek_failed
+ VORBIS_seek_failed,
+ VORBIS_ogg_skeleton_not_supported
};
@@ -1073,7 +1075,7 @@ static int compute_codewords(Codebook *c, uint8 *len, int n, uint32 *values)
assert(z >= 0 && z < 32);
available[z] = 0;
add_entry(c, bit_reverse(res), i, m++, len[i], values);
- // propogate availability up the tree
+ // propagate availability up the tree
if (z != len[i]) {
assert(len[i] >= 0 && len[i] < 32);
for (y=len[i]; y > z; --y) {
@@ -2637,7 +2639,7 @@ static void inverse_mdct(float *buffer, int n, vorb *f, int blocktype)
// once I combined the passes.
// so there's a missing 'times 2' here (for adding X to itself).
- // this propogates through linearly to the end, where the numbers
+ // this propagates through linearly to the end, where the numbers
// are 1/2 too small, and need to be compensated for.
{
@@ -3578,7 +3580,22 @@ static int start_decoder(vorb *f)
if (f->page_flag & PAGEFLAG_continued_packet) return error(f, VORBIS_invalid_first_page);
// check for expected packet length
if (f->segment_count != 1) return error(f, VORBIS_invalid_first_page);
- if (f->segments[0] != 30) return error(f, VORBIS_invalid_first_page);
+ if (f->segments[0] != 30) {
+ // check for the Ogg skeleton fishead identifying header to refine our error
+ if (f->segments[0] == 64 &&
+ getn(f, header, 6) &&
+ header[0] == 'f' &&
+ header[1] == 'i' &&
+ header[2] == 's' &&
+ header[3] == 'h' &&
+ header[4] == 'e' &&
+ header[5] == 'a' &&
+ get8(f) == 'd' &&
+ get8(f) == '\0') return error(f, VORBIS_ogg_skeleton_not_supported);
+ else
+ return error(f, VORBIS_invalid_first_page);
+ }
+
// read packet
// check packet header
if (get8(f) != VORBIS_packet_id) return error(f, VORBIS_invalid_first_page);
@@ -4566,7 +4583,7 @@ static int get_seek_page_info(stb_vorbis *f, ProbedPage *z)
return 1;
}
-// rarely used function to seek back to the preceeding page while finding the
+// rarely used function to seek back to the preceding page while finding the
// start of a packet
static int go_to_page_before(stb_vorbis *f, unsigned int limit_offset)
{
diff --git a/thirdparty/misc/yuv2rgb.h b/thirdparty/misc/yuv2rgb.h
index 3ec8388246..d8f7fd6de2 100644
--- a/thirdparty/misc/yuv2rgb.h
+++ b/thirdparty/misc/yuv2rgb.h
@@ -24,6 +24,14 @@ does not infringe any patents that apply in your area before you
ship it.
*/
+/*
+ * Please note that this version has been modified for various reasons:
+ * 1. Using the Godot core typedefs
+ * 2. At some point or another the code relied on the byte order of a uint32_t, this has been fixed
+ * 3. Output has been reordered to struct { uint8_t r, g, b, a; } precisely in accordance with the function names
+ * 4. Removing unused 'dither' parameter
+ */
+
#ifndef YUV2RGB_H
#define YUV2RGB_H
@@ -803,6 +811,8 @@ static const uint32_t tables[256*3] = {
0xE6365800U
};
+/* -- Common -- */
+
#define FLAGS 0x40080100
#define READUV(U,V) (tables[256 + (U)] + tables[512 + (V)])
#define READY(Y) tables[Y]
@@ -820,12 +830,14 @@ do { \
#define STORE(Y,DSTPTR) \
do { \
- *(DSTPTR)++ = (Y); \
- *(DSTPTR)++ = (Y)>>22; \
*(DSTPTR)++ = (Y)>>11; \
- *(DSTPTR)++ = 255; \
+ *(DSTPTR)++ = (Y)>>22; \
+ *(DSTPTR)++ = (Y); \
+ *(DSTPTR)++ = 255; \
} while (0 == 1)
+/* -- End Common -- */
+
static void yuv422_2_rgb8888(uint8_t *dst_ptr,
const uint8_t *y_ptr,
const uint8_t *u_ptr,
@@ -834,8 +846,7 @@ static void yuv422_2_rgb8888(uint8_t *dst_ptr,
int32_t height,
int32_t y_span,
int32_t uv_span,
- int32_t dst_span,
- int32_t dither)
+ int32_t dst_span)
{
height -= 1;
while (height > 0)
@@ -909,35 +920,7 @@ static void yuv422_2_rgb8888(uint8_t *dst_ptr,
}
}
-
-#undef FLAGS
-#undef READUV
-#undef READY
-#undef FIXUP
-#undef STORE
-
-
-#define FLAGS 0x40080100
-#define READUV(U,V) (tables[256 + (U)] + tables[512 + (V)])
-#define READY(Y) tables[Y]
-#define FIXUP(Y) \
-do { \
- int tmp = (Y) & FLAGS; \
- if (tmp != 0) \
- { \
- tmp -= tmp>>8; \
- (Y) |= tmp; \
- tmp = FLAGS & ~(Y>>1); \
- (Y) += tmp>>8; \
- } \
-} while (0 == 1)
-
-#define STORE(Y,DSTPTR) \
-do { \
- (DSTPTR) = 0xFF000000 | (Y & 0xFF) | (0xFF00 & (Y>>14)) | (0xFF0000 & (Y<<5));\
-} while (0 == 1)
-
-static void yuv420_2_rgb8888(uint8_t *dst_ptr_,
+static void yuv420_2_rgb8888(uint8_t *dst_ptr,
const uint8_t *y_ptr,
const uint8_t *u_ptr,
const uint8_t *v_ptr,
@@ -945,12 +928,9 @@ static void yuv420_2_rgb8888(uint8_t *dst_ptr_,
int32_t height,
int32_t y_span,
int32_t uv_span,
- int32_t dst_span,
- int32_t dither)
+ int32_t dst_span)
{
- uint32_t *dst_ptr = (uint32_t *)(void *)dst_ptr_;
- dst_span >>= 2;
-
+ /* The 'dst_ptr as uint32_t' thing is not endianness-aware, so that's been removed. */
height -= 1;
while (height > 0)
{
@@ -960,36 +940,38 @@ static void yuv420_2_rgb8888(uint8_t *dst_ptr_,
{
/* Do 2 column pairs */
uint32_t uv, y0, y1;
+ uint8_t * dst_ptr_1span = dst_ptr + dst_span;
uv = READUV(*u_ptr++,*v_ptr++);
y1 = uv + READY(y_ptr[y_span]);
y0 = uv + READY(*y_ptr++);
FIXUP(y1);
FIXUP(y0);
- STORE(y1, dst_ptr[dst_span]);
- STORE(y0, *dst_ptr++);
+ STORE(y1, dst_ptr_1span);
+ STORE(y0, dst_ptr);
y1 = uv + READY(y_ptr[y_span]);
y0 = uv + READY(*y_ptr++);
FIXUP(y1);
FIXUP(y0);
- STORE(y1, dst_ptr[dst_span]);
- STORE(y0, *dst_ptr++);
+ STORE(y1, dst_ptr_1span);
+ STORE(y0, dst_ptr);
height += (2<<16);
}
if ((height>>16) == 0)
{
/* Trailing column pair */
uint32_t uv, y0, y1;
+ uint8_t * dst_ptr_1span = dst_ptr + dst_span;
uv = READUV(*u_ptr,*v_ptr);
y1 = uv + READY(y_ptr[y_span]);
y0 = uv + READY(*y_ptr++);
FIXUP(y1);
FIXUP(y0);
- STORE(y0, dst_ptr[dst_span]);
- STORE(y1, *dst_ptr++);
+ STORE(y0, dst_ptr_1span);
+ STORE(y1, dst_ptr);
}
- dst_ptr += dst_span*2-width;
+ dst_ptr += (dst_span * 2) - (width * 4);
y_ptr += y_span*2-width;
u_ptr += uv_span-(width>>1);
v_ptr += uv_span-(width>>1);
@@ -1011,8 +993,8 @@ static void yuv420_2_rgb8888(uint8_t *dst_ptr_,
y0 = uv + READY(*y_ptr++);
FIXUP(y1);
FIXUP(y0);
- STORE(y1, *dst_ptr++);
- STORE(y0, *dst_ptr++);
+ STORE(y1, dst_ptr);
+ STORE(y0, dst_ptr);
height += (2<<16);
}
if ((height>>16) == 0)
@@ -1023,42 +1005,11 @@ static void yuv420_2_rgb8888(uint8_t *dst_ptr_,
uv = READUV(*u_ptr++,*v_ptr++);
y0 = uv + READY(*y_ptr++);
FIXUP(y0);
- STORE(y0, *dst_ptr++);
+ STORE(y0, dst_ptr);
}
}
}
-
-
-#undef FLAGS
-#undef READUV
-#undef READY
-#undef FIXUP
-#undef STORE
-
-#define FLAGS 0x40080100
-#define READUV(U,V) (tables[256 + (U)] + tables[512 + (V)])
-#define READY(Y) tables[Y]
-#define FIXUP(Y) \
-do { \
- int tmp = (Y) & FLAGS; \
- if (tmp != 0) \
- { \
- tmp -= tmp>>8; \
- (Y) |= tmp; \
- tmp = FLAGS & ~(Y>>1); \
- (Y) += tmp>>8; \
- } \
-} while (0 == 1)
-
-#define STORE(Y,DSTPTR) \
-do { \
- *(DSTPTR)++ = (Y); \
- *(DSTPTR)++ = (Y)>>22; \
- *(DSTPTR)++ = (Y)>>11; \
- *(DSTPTR)++ = 255; \
-} while (0 == 1)
-
static void yuv444_2_rgb8888(uint8_t *dst_ptr,
const uint8_t *y_ptr,
const uint8_t *u_ptr,
@@ -1067,8 +1018,7 @@ static void yuv444_2_rgb8888(uint8_t *dst_ptr,
int32_t height,
int32_t y_span,
int32_t uv_span,
- int32_t dst_span,
- int32_t dither)
+ int32_t dst_span)
{
height -= 1;
while (height > 0)
@@ -1143,4 +1093,11 @@ static void yuv444_2_rgb8888(uint8_t *dst_ptr,
height -= 1;
}
}
+
+#undef FLAGS
+#undef READUV
+#undef READY
+#undef FIXUP
+#undef STORE
+
#endif // YUV2RGB_H
diff --git a/thirdparty/nanosvg/nanosvg.h b/thirdparty/nanosvg/nanosvg.h
index 2321c56fd2..8c8b061cd1 100644
--- a/thirdparty/nanosvg/nanosvg.h
+++ b/thirdparty/nanosvg/nanosvg.h
@@ -29,9 +29,11 @@
#ifndef NANOSVG_H
#define NANOSVG_H
+#ifndef NANOSVG_CPLUSPLUS
#ifdef __cplusplus
extern "C" {
#endif
+#endif
// NanoSVG is a simple stupid single-header-file SVG parse. The output of the parser is a list of cubic bezier shapes.
//
@@ -45,15 +47,15 @@ extern "C" {
// NanoSVG can return the paths in few different units. For example if you want to render an image, you may choose
// to get the paths in pixels, or if you are feeding the data into a CNC-cutter, you may want to use millimeters.
//
-// The units passed to NanoVG should be one of: 'px', 'pt', 'pc' 'mm', 'cm', or 'in'.
+// The units passed to NanoSVG should be one of: 'px', 'pt', 'pc' 'mm', 'cm', or 'in'.
// DPI (dots-per-inch) controls how the unit conversion is done.
//
// If you don't know or care about the units stuff, "px" and 96 should get you going.
/* Example Usage:
- // Load
- NSVGImage* image;
+ // Load SVG
+ NSVGimage* image;
image = nsvgParseFromFile("test.svg", "px", 96);
printf("size: %f x %f\n", image->width, image->height);
// Use...
@@ -167,12 +169,17 @@ NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi)
// Important note: changes the string.
NSVGimage* nsvgParse(char* input, const char* units, float dpi);
-// Deletes list of paths.
+// Duplicates a path.
+NSVGpath* nsvgDuplicatePath(NSVGpath* p);
+
+// Deletes an image.
void nsvgDelete(NSVGimage* image);
+#ifndef NANOSVG_CPLUSPLUS
#ifdef __cplusplus
}
#endif
+#endif
#endif // NANOSVG_H
@@ -1415,8 +1422,7 @@ static unsigned int nsvg__parseColor(const char* str)
static float nsvg__parseOpacity(const char* str)
{
- float val = 0;
- sscanf(str, "%f", &val);
+ float val = nsvg__atof(str);
if (val < 0.0f) val = 0.0f;
if (val > 1.0f) val = 1.0f;
return val;
@@ -1424,8 +1430,7 @@ static float nsvg__parseOpacity(const char* str)
static float nsvg__parseMiterLimit(const char* str)
{
- float val = 0;
- sscanf(str, "%f", &val);
+ float val = nsvg__atof(str);
if (val < 0.0f) val = 0.0f;
return val;
}
@@ -1456,9 +1461,9 @@ static int nsvg__parseUnits(const char* units)
static NSVGcoordinate nsvg__parseCoordinateRaw(const char* str)
{
NSVGcoordinate coord = {0, NSVG_UNITS_USER};
- char units[32]="";
- sscanf(str, "%f%31s", &coord.value, units);
- coord.units = nsvg__parseUnits(units);
+ char buf[64];
+ coord.units = nsvg__parseUnits(nsvg__parseNumber(str, buf, 64));
+ coord.value = nsvg__atof(buf);
return coord;
}
@@ -1650,7 +1655,7 @@ static char nsvg__parseLineJoin(const char* str)
else if (strcmp(str, "bevel") == 0)
return NSVG_JOIN_BEVEL;
// TODO: handle inherit.
- return NSVG_CAP_BUTT;
+ return NSVG_JOIN_MITER;
}
static char nsvg__parseFillRule(const char* str)
@@ -2494,11 +2499,26 @@ static void nsvg__parseSVG(NSVGparser* p, const char** attr)
for (i = 0; attr[i]; i += 2) {
if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
if (strcmp(attr[i], "width") == 0) {
- p->image->width = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 1.0f);
+ p->image->width = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 0.0f);
} else if (strcmp(attr[i], "height") == 0) {
- p->image->height = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 1.0f);
+ p->image->height = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 0.0f);
} else if (strcmp(attr[i], "viewBox") == 0) {
- sscanf(attr[i + 1], "%f%*[%%, \t]%f%*[%%, \t]%f%*[%%, \t]%f", &p->viewMinx, &p->viewMiny, &p->viewWidth, &p->viewHeight);
+ const char *s = attr[i + 1];
+ char buf[64];
+ s = nsvg__parseNumber(s, buf, 64);
+ p->viewMinx = nsvg__atof(buf);
+ while (*s && (nsvg__isspace(*s) || *s == '%' || *s == ',')) s++;
+ if (!*s) return;
+ s = nsvg__parseNumber(s, buf, 64);
+ p->viewMiny = nsvg__atof(buf);
+ while (*s && (nsvg__isspace(*s) || *s == '%' || *s == ',')) s++;
+ if (!*s) return;
+ s = nsvg__parseNumber(s, buf, 64);
+ p->viewWidth = nsvg__atof(buf);
+ while (*s && (nsvg__isspace(*s) || *s == '%' || *s == ',')) s++;
+ if (!*s) return;
+ s = nsvg__parseNumber(s, buf, 64);
+ p->viewHeight = nsvg__atof(buf);
} else if (strcmp(attr[i], "preserveAspectRatio") == 0) {
if (strstr(attr[i + 1], "none") != 0) {
// No uniform scaling
@@ -2906,6 +2926,36 @@ error:
return NULL;
}
+NSVGpath* nsvgDuplicatePath(NSVGpath* p)
+{
+ NSVGpath* res = NULL;
+
+ if (p == NULL)
+ return NULL;
+
+ res = (NSVGpath*)malloc(sizeof(NSVGpath));
+ if (res == NULL) goto error;
+ memset(res, 0, sizeof(NSVGpath));
+
+ res->pts = (float*)malloc(p->npts*2*sizeof(float));
+ if (res->pts == NULL) goto error;
+ memcpy(res->pts, p->pts, p->npts * sizeof(float) * 2);
+ res->npts = p->npts;
+
+ memcpy(res->bounds, p->bounds, sizeof(p->bounds));
+
+ res->closed = p->closed;
+
+ return res;
+
+error:
+ if (res != NULL) {
+ free(res->pts);
+ free(res);
+ }
+ return NULL;
+}
+
void nsvgDelete(NSVGimage* image)
{
NSVGshape *snext, *shape;
diff --git a/thirdparty/nanosvg/nanosvgrast.h b/thirdparty/nanosvg/nanosvgrast.h
index 2940c1f916..b740c316ca 100644
--- a/thirdparty/nanosvg/nanosvgrast.h
+++ b/thirdparty/nanosvg/nanosvgrast.h
@@ -25,15 +25,18 @@
#ifndef NANOSVGRAST_H
#define NANOSVGRAST_H
+#ifndef NANOSVGRAST_CPLUSPLUS
#ifdef __cplusplus
extern "C" {
#endif
+#endif
typedef struct NSVGrasterizer NSVGrasterizer;
/* Example Usage:
// Load SVG
- struct SNVGImage* image = nsvgParseFromFile("test.svg.");
+ NSVGimage* image;
+ image = nsvgParseFromFile("test.svg", "px", 96);
// Create rasterizer (can be used to render multiple images).
struct NSVGrasterizer* rast = nsvgCreateRasterizer();
@@ -63,9 +66,11 @@ void nsvgRasterize(NSVGrasterizer* r,
void nsvgDeleteRasterizer(NSVGrasterizer*);
+#ifndef NANOSVGRAST_CPLUSPLUS
#ifdef __cplusplus
}
#endif
+#endif
#endif // NANOSVGRAST_H
diff --git a/thirdparty/opus/http.c b/thirdparty/opus/http.c
deleted file mode 100644
index 99fa8c08e0..0000000000
--- a/thirdparty/opus/http.c
+++ /dev/null
@@ -1,3465 +0,0 @@
-/********************************************************************
- * *
- * THIS FILE IS PART OF THE libopusfile SOFTWARE CODEC SOURCE CODE. *
- * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
- * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
- * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
- * *
- * THE libopusfile SOURCE CODE IS (C) COPYRIGHT 2012 *
- * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
- * *
- ********************************************************************/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "internal.h"
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <string.h>
-
-/*RFCs referenced in this file:
- RFC 761: DOD Standard Transmission Control Protocol
- RFC 1535: A Security Problem and Proposed Correction With Widely Deployed DNS
- Software
- RFC 1738: Uniform Resource Locators (URL)
- RFC 1945: Hypertext Transfer Protocol -- HTTP/1.0
- RFC 2068: Hypertext Transfer Protocol -- HTTP/1.1
- RFC 2145: Use and Interpretation of HTTP Version Numbers
- RFC 2246: The TLS Protocol Version 1.0
- RFC 2459: Internet X.509 Public Key Infrastructure Certificate and
- Certificate Revocation List (CRL) Profile
- RFC 2616: Hypertext Transfer Protocol -- HTTP/1.1
- RFC 2617: HTTP Authentication: Basic and Digest Access Authentication
- RFC 2817: Upgrading to TLS Within HTTP/1.1
- RFC 2818: HTTP Over TLS
- RFC 3492: Punycode: A Bootstring encoding of Unicode for Internationalized
- Domain Names in Applications (IDNA)
- RFC 3986: Uniform Resource Identifier (URI): Generic Syntax
- RFC 3987: Internationalized Resource Identifiers (IRIs)
- RFC 4343: Domain Name System (DNS) Case Insensitivity Clarification
- RFC 5894: Internationalized Domain Names for Applications (IDNA):
- Background, Explanation, and Rationale
- RFC 6066: Transport Layer Security (TLS) Extensions: Extension Definitions
- RFC 6125: Representation and Verification of Domain-Based Application Service
- Identity within Internet Public Key Infrastructure Using X.509 (PKIX)
- Certificates in the Context of Transport Layer Security (TLS)
- RFC 6555: Happy Eyeballs: Success with Dual-Stack Hosts*/
-
-typedef struct OpusParsedURL OpusParsedURL;
-typedef struct OpusStringBuf OpusStringBuf;
-typedef struct OpusHTTPConn OpusHTTPConn;
-typedef struct OpusHTTPStream OpusHTTPStream;
-
-static char *op_string_range_dup(const char *_start,const char *_end){
- size_t len;
- char *ret;
- OP_ASSERT(_start<=_end);
- len=_end-_start;
- /*This is to help avoid overflow elsewhere, later.*/
- if(OP_UNLIKELY(len>=INT_MAX))return NULL;
- ret=(char *)_ogg_malloc(sizeof(*ret)*(len+1));
- if(OP_LIKELY(ret!=NULL)){
- ret=(char *)memcpy(ret,_start,sizeof(*ret)*(len));
- ret[len]='\0';
- }
- return ret;
-}
-
-static char *op_string_dup(const char *_s){
- return op_string_range_dup(_s,_s+strlen(_s));
-}
-
-static char *op_string_tolower(char *_s){
- int i;
- for(i=0;_s[i]!='\0';i++){
- int c;
- c=_s[i];
- if(c>='A'&&c<='Z')c+='a'-'A';
- _s[i]=(char)c;
- }
- return _s;
-}
-
-/*URI character classes (from RFC 3986).*/
-#define OP_URL_ALPHA \
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
-#define OP_URL_DIGIT "0123456789"
-#define OP_URL_HEXDIGIT "0123456789ABCDEFabcdef"
-/*Not a character class, but the characters allowed in <scheme>.*/
-#define OP_URL_SCHEME OP_URL_ALPHA OP_URL_DIGIT "+-."
-#define OP_URL_GEN_DELIMS "#/:?@[]"
-#define OP_URL_SUB_DELIMS "!$&'()*+,;="
-#define OP_URL_RESERVED OP_URL_GEN_DELIMS OP_URL_SUB_DELIMS
-#define OP_URL_UNRESERVED OP_URL_ALPHA OP_URL_DIGIT "-._~"
-/*Not a character class, but the characters allowed in <pct-encoded>.*/
-#define OP_URL_PCT_ENCODED "%"
-/*Not a character class or production rule, but for convenience.*/
-#define OP_URL_PCHAR_BASE \
- OP_URL_UNRESERVED OP_URL_PCT_ENCODED OP_URL_SUB_DELIMS
-#define OP_URL_PCHAR OP_URL_PCHAR_BASE ":@"
-/*Not a character class, but the characters allowed in <userinfo> and
- <IP-literal>.*/
-#define OP_URL_PCHAR_NA OP_URL_PCHAR_BASE ":"
-/*Not a character class, but the characters allowed in <segment-nz-nc>.*/
-#define OP_URL_PCHAR_NC OP_URL_PCHAR_BASE "@"
-/*Not a character clsss, but the characters allowed in <path>.*/
-#define OP_URL_PATH OP_URL_PCHAR "/"
-/*Not a character class, but the characters allowed in <query> / <fragment>.*/
-#define OP_URL_QUERY_FRAG OP_URL_PCHAR "/?"
-
-/*Check the <% HEXDIG HEXDIG> escapes of a URL for validity.
- Return: 0 if valid, or a negative value on failure.*/
-static int op_validate_url_escapes(const char *_s){
- int i;
- for(i=0;_s[i];i++){
- if(_s[i]=='%'){
- if(OP_UNLIKELY(!isxdigit(_s[i+1]))
- ||OP_UNLIKELY(!isxdigit(_s[i+2]))
- /*RFC 3986 says %00 "should be rejected if the application is not
- expecting to receive raw data within a component."*/
- ||OP_UNLIKELY(_s[i+1]=='0'&&_s[i+2]=='0')){
- return OP_FALSE;
- }
- i+=2;
- }
- }
- return 0;
-}
-
-/*Convert a hex digit to its actual value.
- _c: The hex digit to convert.
- Presumed to be valid ('0'...'9', 'A'...'F', or 'a'...'f').
- Return: The value of the digit, in the range [0,15].*/
-static int op_hex_value(int _c){
- return _c>='a'?_c-'a'+10:_c>='A'?_c-'A'+10:_c-'0';
-}
-
-/*Unescape all the <% HEXDIG HEXDIG> sequences in a string in-place.
- This does no validity checking.*/
-static char *op_unescape_url_component(char *_s){
- int i;
- int j;
- for(i=j=0;_s[i];i++,j++){
- if(_s[i]=='%'){
- _s[i]=(char)(op_hex_value(_s[i+1])<<4|op_hex_value(_s[i+2]));
- i+=2;
- }
- }
- return _s;
-}
-
-/*Parse a file: URL.
- This code is not meant to be fast: strspn() with large sets is likely to be
- slow, but it is very convenient.
- It is meant to be RFC 1738-compliant (as updated by RFC 3986).*/
-static const char *op_parse_file_url(const char *_src){
- const char *scheme_end;
- const char *path;
- const char *path_end;
- scheme_end=_src+strspn(_src,OP_URL_SCHEME);
- if(OP_UNLIKELY(*scheme_end!=':')
- ||scheme_end-_src!=4||op_strncasecmp(_src,"file",4)!=0){
- /*Unsupported protocol.*/
- return NULL;
- }
- /*Make sure all escape sequences are valid to simplify unescaping later.*/
- if(OP_UNLIKELY(op_validate_url_escapes(scheme_end+1)<0))return NULL;
- if(scheme_end[1]=='/'&&scheme_end[2]=='/'){
- const char *host;
- /*file: URLs can have a host!
- Yeah, I was surprised, too, but that's what RFC 1738 says.
- It also says, "The file URL scheme is unusual in that it does not specify
- an Internet protocol or access method for such files; as such, its
- utility in network protocols between hosts is limited," which is a mild
- understatement.*/
- host=scheme_end+3;
- /*The empty host is what we expect.*/
- if(OP_LIKELY(*host=='/'))path=host;
- else{
- const char *host_end;
- char host_buf[28];
- /*RFC 1738 says localhost "is interpreted as `the machine from which the
- URL is being interpreted,'" so let's check for it.*/
- host_end=host+strspn(host,OP_URL_PCHAR_BASE);
- /*No <port> allowed.
- This also rejects IP-Literals.*/
- if(*host_end!='/')return NULL;
- /*An escaped "localhost" can take at most 27 characters.*/
- if(OP_UNLIKELY(host_end-host>27))return NULL;
- memcpy(host_buf,host,sizeof(*host_buf)*(host_end-host));
- host_buf[host_end-host]='\0';
- op_unescape_url_component(host_buf);
- op_string_tolower(host_buf);
- /*Some other host: give up.*/
- if(OP_UNLIKELY(strcmp(host_buf,"localhost")!=0))return NULL;
- path=host_end;
- }
- }
- else path=scheme_end+1;
- path_end=path+strspn(path,OP_URL_PATH);
- /*This will reject a <query> or <fragment> component, too.
- I don't know what to do with queries, but a temporal fragment would at
- least make sense.
- RFC 1738 pretty clearly defines a <searchpart> that's equivalent to the
- RFC 3986 <query> component for other schemes, but not the file: scheme,
- so I'm going to just reject it.*/
- if(*path_end!='\0')return NULL;
- return path;
-}
-
-#if defined(OP_ENABLE_HTTP)
-# if defined(_WIN32)
-# include <winsock2.h>
-# include <ws2tcpip.h>
-# include <openssl/ssl.h>
-# include "winerrno.h"
-
-typedef SOCKET op_sock;
-
-# define OP_INVALID_SOCKET (INVALID_SOCKET)
-
-/*Vista and later support WSAPoll(), but we don't want to rely on that.
- Instead we re-implement it badly using select().
- Unfortunately, they define a conflicting struct pollfd, so we only define our
- own if it looks like that one has not already been defined.*/
-# if !defined(POLLIN)
-/*Equivalent to POLLIN.*/
-# define POLLRDNORM (0x0100)
-/*Priority band data can be read.*/
-# define POLLRDBAND (0x0200)
-/*There is data to read.*/
-# define POLLIN (POLLRDNORM|POLLRDBAND)
-/*There is urgent data to read.*/
-# define POLLPRI (0x0400)
-/*Equivalent to POLLOUT.*/
-# define POLLWRNORM (0x0010)
-/*Writing now will not block.*/
-# define POLLOUT (POLLWRNORM)
-/*Priority data may be written.*/
-# define POLLWRBAND (0x0020)
-/*Error condition (output only).*/
-# define POLLERR (0x0001)
-/*Hang up (output only).*/
-# define POLLHUP (0x0002)
-/*Invalid request: fd not open (output only).*/
-# define POLLNVAL (0x0004)
-
-struct pollfd{
- /*File descriptor.*/
- op_sock fd;
- /*Requested events.*/
- short events;
- /*Returned events.*/
- short revents;
-};
-# endif
-
-/*But Winsock never defines nfds_t (it's simply hard-coded to ULONG).*/
-typedef unsigned long nfds_t;
-
-/*The usage of FD_SET() below is O(N^2).
- This is okay because select() is limited to 64 sockets in Winsock, anyway.
- In practice, we only ever call it with one or two sockets.*/
-static int op_poll_win32(struct pollfd *_fds,nfds_t _nfds,int _timeout){
- struct timeval tv;
- fd_set ifds;
- fd_set ofds;
- fd_set efds;
- nfds_t i;
- int ret;
- FD_ZERO(&ifds);
- FD_ZERO(&ofds);
- FD_ZERO(&efds);
- for(i=0;i<_nfds;i++){
- _fds[i].revents=0;
- if(_fds[i].events&POLLIN)FD_SET(_fds[i].fd,&ifds);
- if(_fds[i].events&POLLOUT)FD_SET(_fds[i].fd,&ofds);
- FD_SET(_fds[i].fd,&efds);
- }
- if(_timeout>=0){
- tv.tv_sec=_timeout/1000;
- tv.tv_usec=(_timeout%1000)*1000;
- }
- ret=select(-1,&ifds,&ofds,&efds,_timeout<0?NULL:&tv);
- if(ret>0){
- for(i=0;i<_nfds;i++){
- if(FD_ISSET(_fds[i].fd,&ifds))_fds[i].revents|=POLLIN;
- if(FD_ISSET(_fds[i].fd,&ofds))_fds[i].revents|=POLLOUT;
- /*This isn't correct: there are several different things that might have
- happened to a fd in efds, but I don't know a good way to distinguish
- them without more context from the caller.
- It's okay, because we don't actually check any of these bits, we just
- need _some_ bit set.*/
- if(FD_ISSET(_fds[i].fd,&efds))_fds[i].revents|=POLLHUP;
- }
- }
- return ret;
-}
-
-/*We define op_errno() to make it clear that it's not an l-value like normal
- errno is.*/
-# define op_errno() (WSAGetLastError()?WSAGetLastError()-WSABASEERR:0)
-# define op_reset_errno() (WSASetLastError(0))
-
-/*The remaining functions don't get an op_ prefix even though they only
- operate on sockets, because we don't use non-socket I/O here, and this
- minimizes the changes needed to deal with Winsock.*/
-# define close(_fd) closesocket(_fd)
-/*This relies on sizeof(u_long)==sizeof(int), which is always true on both
- Win32 and Win64.*/
-# define ioctl(_fd,_req,_arg) ioctlsocket(_fd,_req,(u_long *)(_arg))
-# define getsockopt(_fd,_level,_name,_val,_len) \
- getsockopt(_fd,_level,_name,(char *)(_val),_len)
-# define setsockopt(_fd,_level,_name,_val,_len) \
- setsockopt(_fd,_level,_name,(const char *)(_val),_len)
-# define poll(_fds,_nfds,_timeout) op_poll_win32(_fds,_nfds,_timeout)
-
-# if defined(_MSC_VER)
-typedef ptrdiff_t ssize_t;
-# endif
-
-/*Load certificates from the built-in certificate store.*/
-int SSL_CTX_set_default_verify_paths_win32(SSL_CTX *_ssl_ctx);
-# define SSL_CTX_set_default_verify_paths \
- SSL_CTX_set_default_verify_paths_win32
-
-# else
-/*Normal Berkeley sockets.*/
-# include <sys/ioctl.h>
-# include <sys/types.h>
-# include <sys/socket.h>
-# include <arpa/inet.h>
-# include <netinet/in.h>
-# include <netinet/tcp.h>
-# include <fcntl.h>
-# include <netdb.h>
-# include <poll.h>
-# include <unistd.h>
-# include <openssl/ssl.h>
-
-typedef int op_sock;
-
-# define OP_INVALID_SOCKET (-1)
-
-# define op_errno() (errno)
-# define op_reset_errno() (errno=0)
-
-# endif
-# include <sys/timeb.h>
-# include <openssl/x509v3.h>
-
-/*The maximum number of simultaneous connections.
- RFC 2616 says this SHOULD NOT be more than 2, but everyone on the modern web
- ignores that (e.g., IE 8 bumped theirs up from 2 to 6, Firefox uses 15).
- If it makes you feel better, we'll only ever actively read from one of these
- at a time.
- The others are kept around mainly to avoid slow-starting a new connection
- when seeking, and time out rapidly.*/
-# define OP_NCONNS_MAX (4)
-
-/*The amount of time before we attempt to re-resolve the host.
- This is 10 minutes, as recommended in RFC 6555 for expiring cached connection
- results for dual-stack hosts.*/
-# define OP_RESOLVE_CACHE_TIMEOUT_MS (10*60*(opus_int32)1000)
-
-/*The number of redirections at which we give up.
- The value here is the current default in Firefox.
- RFC 2068 mandated a maximum of 5, but RFC 2616 relaxed that to "a client
- SHOULD detect infinite redirection loops."
- Fortunately, 20 is less than infinity.*/
-# define OP_REDIRECT_LIMIT (20)
-
-/*The initial size of the buffer used to read a response message (before the
- body).*/
-# define OP_RESPONSE_SIZE_MIN (510)
-/*The maximum size of a response message (before the body).
- Responses larger than this will be discarded.
- I've seen a real server return 20 kB of data for a 302 Found response.
- Increasing this beyond 32kB will cause problems on platforms with a 16-bit
- int.*/
-# define OP_RESPONSE_SIZE_MAX (32766)
-
-/*The number of milliseconds we will allow a connection to sit idle before we
- refuse to resurrect it.
- Apache as of 2.2 has reduced its default timeout to 5 seconds (from 15), so
- that's what we'll use here.*/
-# define OP_CONNECTION_IDLE_TIMEOUT_MS (5*1000)
-
-/*The number of milliseconds we will wait to send or receive data before giving
- up.*/
-# define OP_POLL_TIMEOUT_MS (30*1000)
-
-/*We will always attempt to read ahead at least this much in preference to
- opening a new connection.*/
-# define OP_READAHEAD_THRESH_MIN (32*(opus_int32)1024)
-
-/*The amount of data to request after a seek.
- This is a trade-off between read throughput after a seek vs. the the ability
- to quickly perform another seek with the same connection.*/
-# define OP_PIPELINE_CHUNK_SIZE (32*(opus_int32)1024)
-/*Subsequent chunks are requested with larger and larger sizes until they pass
- this threshold, after which we just ask for the rest of the resource.*/
-# define OP_PIPELINE_CHUNK_SIZE_MAX (1024*(opus_int32)1024)
-/*This is the maximum number of requests we'll make with a single connection.
- Many servers will simply disconnect after we attempt some number of requests,
- possibly without sending a Connection: close header, meaning we won't
- discover it until we try to read beyond the end of the current chunk.
- We can reconnect when that happens, but this is slow.
- Instead, we impose a limit ourselves (set to the default for Apache
- installations and thus likely the most common value in use).*/
-# define OP_PIPELINE_MAX_REQUESTS (100)
-/*This should be the number of requests, starting from a chunk size of
- OP_PIPELINE_CHUNK_SIZE and doubling each time, until we exceed
- OP_PIPELINE_CHUNK_SIZE_MAX and just request the rest of the file.
- We won't reuse a connection when seeking unless it has at least this many
- requests left, to reduce the chances we'll have to open a new connection
- while reading forward afterwards.*/
-# define OP_PIPELINE_MIN_REQUESTS (7)
-
-/*Is this an https URL?
- For now we can simply check the last letter of the scheme.*/
-# define OP_URL_IS_SSL(_url) ((_url)->scheme[4]=='s')
-
-/*Does this URL use the default port for its scheme?*/
-# define OP_URL_IS_DEFAULT_PORT(_url) \
- (!OP_URL_IS_SSL(_url)&&(_url)->port==80 \
- ||OP_URL_IS_SSL(_url)&&(_url)->port==443)
-
-struct OpusParsedURL{
- /*Either "http" or "https".*/
- char *scheme;
- /*The user name from the <userinfo> component, or NULL.*/
- char *user;
- /*The password from the <userinfo> component, or NULL.*/
- char *pass;
- /*The <host> component.
- This may not be NULL.*/
- char *host;
- /*The <path> and <query> components.
- This may not be NULL.*/
- char *path;
- /*The <port> component.
- This is set to the default port if the URL did not contain one.*/
- unsigned port;
-};
-
-/*Parse a URL.
- This code is not meant to be fast: strspn() with large sets is likely to be
- slow, but it is very convenient.
- It is meant to be RFC 3986-compliant.
- We currently do not support IRIs (Internationalized Resource Identifiers,
- RFC 3987).
- Callers should translate them to URIs first.*/
-static int op_parse_url_impl(OpusParsedURL *_dst,const char *_src){
- const char *scheme_end;
- const char *authority;
- const char *userinfo_end;
- const char *user;
- const char *user_end;
- const char *pass;
- const char *hostport;
- const char *hostport_end;
- const char *host_end;
- const char *port;
- opus_int32 port_num;
- const char *port_end;
- const char *path;
- const char *path_end;
- const char *uri_end;
- scheme_end=_src+strspn(_src,OP_URL_SCHEME);
- if(OP_UNLIKELY(*scheme_end!=':')
- ||OP_UNLIKELY(scheme_end-_src<4)||OP_UNLIKELY(scheme_end-_src>5)
- ||OP_UNLIKELY(op_strncasecmp(_src,"https",scheme_end-_src)!=0)){
- /*Unsupported protocol.*/
- return OP_EIMPL;
- }
- if(OP_UNLIKELY(scheme_end[1]!='/')||OP_UNLIKELY(scheme_end[2]!='/')){
- /*We require an <authority> component.*/
- return OP_EINVAL;
- }
- authority=scheme_end+3;
- /*Make sure all escape sequences are valid to simplify unescaping later.*/
- if(OP_UNLIKELY(op_validate_url_escapes(authority)<0))return OP_EINVAL;
- /*Look for a <userinfo> component.*/
- userinfo_end=authority+strspn(authority,OP_URL_PCHAR_NA);
- if(*userinfo_end=='@'){
- /*Found one.*/
- user=authority;
- /*Look for a password (yes, clear-text passwords are deprecated, I know,
- but what else are people supposed to use? use SSL if you care).*/
- user_end=authority+strspn(authority,OP_URL_PCHAR_BASE);
- if(*user_end==':')pass=user_end+1;
- else pass=NULL;
- hostport=userinfo_end+1;
- }
- else{
- /*We shouldn't have to initialize user_end, but gcc is too dumb to figure
- out that user!=NULL below means we didn't take this else branch.*/
- user=user_end=NULL;
- pass=NULL;
- hostport=authority;
- }
- /*Try to figure out where the <host> component ends.*/
- if(hostport[0]=='['){
- hostport++;
- /*We have an <IP-literal>, which can contain colons.*/
- hostport_end=host_end=hostport+strspn(hostport,OP_URL_PCHAR_NA);
- if(OP_UNLIKELY(*hostport_end++!=']'))return OP_EINVAL;
- }
- /*Currently we don't support IDNA (RFC 5894), because I don't want to deal
- with the policy about which domains should not be internationalized to
- avoid confusing similarities.
- Give this API Punycode (RFC 3492) domain names instead.*/
- else hostport_end=host_end=hostport+strspn(hostport,OP_URL_PCHAR_BASE);
- /*TODO: Validate host.*/
- /*Is there a port number?*/
- port_num=-1;
- if(*hostport_end==':'){
- int i;
- port=hostport_end+1;
- port_end=port+strspn(port,OP_URL_DIGIT);
- path=port_end;
- /*Not part of RFC 3986, but require port numbers in the range 0...65535.*/
- if(OP_LIKELY(port_end-port>0)){
- while(*port=='0')port++;
- if(OP_UNLIKELY(port_end-port>5))return OP_EINVAL;
- port_num=0;
- for(i=0;i<port_end-port;i++)port_num=port_num*10+port[i]-'0';
- if(OP_UNLIKELY(port_num>65535))return OP_EINVAL;
- }
- }
- else path=hostport_end;
- path_end=path+strspn(path,OP_URL_PATH);
- /*If the path is not empty, it must begin with a '/'.*/
- if(OP_LIKELY(path_end>path)&&OP_UNLIKELY(path[0]!='/'))return OP_EINVAL;
- /*Consume the <query> component, if any (right now we don't split this out
- from the <path> component).*/
- if(*path_end=='?')path_end=path_end+strspn(path_end,OP_URL_QUERY_FRAG);
- /*Discard the <fragment> component, if any.
- This doesn't get sent to the server.
- Some day we should add support for Media Fragment URIs
- <http://www.w3.org/TR/media-frags/>.*/
- if(*path_end=='#')uri_end=path_end+1+strspn(path_end+1,OP_URL_QUERY_FRAG);
- else uri_end=path_end;
- /*If there's anything left, this was not a valid URL.*/
- if(OP_UNLIKELY(*uri_end!='\0'))return OP_EINVAL;
- _dst->scheme=op_string_range_dup(_src,scheme_end);
- if(OP_UNLIKELY(_dst->scheme==NULL))return OP_EFAULT;
- op_string_tolower(_dst->scheme);
- if(user!=NULL){
- _dst->user=op_string_range_dup(user,user_end);
- if(OP_UNLIKELY(_dst->user==NULL))return OP_EFAULT;
- op_unescape_url_component(_dst->user);
- /*Unescaping might have created a ':' in the username.
- That's not allowed by RFC 2617's Basic Authentication Scheme.*/
- if(OP_UNLIKELY(strchr(_dst->user,':')!=NULL))return OP_EINVAL;
- }
- else _dst->user=NULL;
- if(pass!=NULL){
- _dst->pass=op_string_range_dup(pass,userinfo_end);
- if(OP_UNLIKELY(_dst->pass==NULL))return OP_EFAULT;
- op_unescape_url_component(_dst->pass);
- }
- else _dst->pass=NULL;
- _dst->host=op_string_range_dup(hostport,host_end);
- if(OP_UNLIKELY(_dst->host==NULL))return OP_EFAULT;
- if(port_num<0){
- if(_src[4]=='s')port_num=443;
- else port_num=80;
- }
- _dst->port=(unsigned)port_num;
- /*RFC 2616 says an empty <abs-path> component is equivalent to "/", and we
- MUST use the latter in the Request-URI.
- Reserve space for the slash here.*/
- if(path==path_end||path[0]=='?')path--;
- _dst->path=op_string_range_dup(path,path_end);
- if(OP_UNLIKELY(_dst->path==NULL))return OP_EFAULT;
- /*And force-set it here.*/
- _dst->path[0]='/';
- return 0;
-}
-
-static void op_parsed_url_init(OpusParsedURL *_url){
- memset(_url,0,sizeof(*_url));
-}
-
-static void op_parsed_url_clear(OpusParsedURL *_url){
- _ogg_free(_url->scheme);
- _ogg_free(_url->user);
- _ogg_free(_url->pass);
- _ogg_free(_url->host);
- _ogg_free(_url->path);
-}
-
-static int op_parse_url(OpusParsedURL *_dst,const char *_src){
- OpusParsedURL url;
- int ret;
- op_parsed_url_init(&url);
- ret=op_parse_url_impl(&url,_src);
- if(OP_UNLIKELY(ret<0))op_parsed_url_clear(&url);
- else *_dst=*&url;
- return ret;
-}
-
-/*A buffer to hold growing strings.
- The main purpose of this is to consolidate allocation checks and simplify
- cleanup on a failed allocation.*/
-struct OpusStringBuf{
- char *buf;
- int nbuf;
- int cbuf;
-};
-
-static void op_sb_init(OpusStringBuf *_sb){
- _sb->buf=NULL;
- _sb->nbuf=0;
- _sb->cbuf=0;
-}
-
-static void op_sb_clear(OpusStringBuf *_sb){
- _ogg_free(_sb->buf);
-}
-
-/*Make sure we have room for at least _capacity characters (plus 1 more for the
- terminating NUL).*/
-static int op_sb_ensure_capacity(OpusStringBuf *_sb,int _capacity){
- char *buf;
- int cbuf;
- buf=_sb->buf;
- cbuf=_sb->cbuf;
- if(_capacity>=cbuf-1){
- if(OP_UNLIKELY(cbuf>INT_MAX-1>>1))return OP_EFAULT;
- if(OP_UNLIKELY(_capacity>=INT_MAX-1))return OP_EFAULT;
- cbuf=OP_MAX(2*cbuf+1,_capacity+1);
- buf=_ogg_realloc(buf,sizeof(*buf)*cbuf);
- if(OP_UNLIKELY(buf==NULL))return OP_EFAULT;
- _sb->buf=buf;
- _sb->cbuf=cbuf;
- }
- return 0;
-}
-
-/*Increase the capacity of the buffer, but not to more than _max_size
- characters (plus 1 more for the terminating NUL).*/
-static int op_sb_grow(OpusStringBuf *_sb,int _max_size){
- char *buf;
- int cbuf;
- buf=_sb->buf;
- cbuf=_sb->cbuf;
- OP_ASSERT(_max_size<=INT_MAX-1);
- cbuf=cbuf<=_max_size-1>>1?2*cbuf+1:_max_size+1;
- buf=_ogg_realloc(buf,sizeof(*buf)*cbuf);
- if(OP_UNLIKELY(buf==NULL))return OP_EFAULT;
- _sb->buf=buf;
- _sb->cbuf=cbuf;
- return 0;
-}
-
-static int op_sb_append(OpusStringBuf *_sb,const char *_s,int _len){
- char *buf;
- int nbuf;
- int ret;
- nbuf=_sb->nbuf;
- if(OP_UNLIKELY(nbuf>INT_MAX-_len))return OP_EFAULT;
- ret=op_sb_ensure_capacity(_sb,nbuf+_len);
- if(OP_UNLIKELY(ret<0))return ret;
- buf=_sb->buf;
- memcpy(buf+nbuf,_s,sizeof(*buf)*_len);
- nbuf+=_len;
- buf[nbuf]='\0';
- _sb->nbuf=nbuf;
- return 0;
-}
-
-static int op_sb_append_string(OpusStringBuf *_sb,const char *_s){
- return op_sb_append(_sb,_s,strlen(_s));
-}
-
-static int op_sb_append_port(OpusStringBuf *_sb,unsigned _port){
- char port_buf[7];
- OP_ASSERT(_port<=65535U);
- sprintf(port_buf,":%u",_port);
- return op_sb_append_string(_sb,port_buf);
-}
-
-static int op_sb_append_nonnegative_int64(OpusStringBuf *_sb,opus_int64 _i){
- char digit;
- int nbuf_start;
- int ret;
- OP_ASSERT(_i>=0);
- nbuf_start=_sb->nbuf;
- ret=0;
- do{
- digit='0'+_i%10;
- ret|=op_sb_append(_sb,&digit,1);
- _i/=10;
- }
- while(_i>0);
- if(OP_LIKELY(ret>=0)){
- char *buf;
- int nbuf_end;
- buf=_sb->buf;
- nbuf_end=_sb->nbuf-1;
- /*We've added the digits backwards.
- Reverse them.*/
- while(nbuf_start<nbuf_end){
- digit=buf[nbuf_start];
- buf[nbuf_start]=buf[nbuf_end];
- buf[nbuf_end]=digit;
- nbuf_start++;
- nbuf_end--;
- }
- }
- return ret;
-}
-
-static struct addrinfo *op_resolve(const char *_host,unsigned _port){
- struct addrinfo *addrs;
- struct addrinfo hints;
- char service[6];
- memset(&hints,0,sizeof(hints));
- hints.ai_socktype=SOCK_STREAM;
-#if defined(AI_NUMERICSERV)
- hints.ai_flags=AI_NUMERICSERV;
-#endif
- OP_ASSERT(_port<=65535U);
- sprintf(service,"%u",_port);
- if(OP_LIKELY(!getaddrinfo(_host,service,&hints,&addrs)))return addrs;
- return NULL;
-}
-
-static int op_sock_set_nonblocking(op_sock _fd,int _nonblocking){
-#if !defined(_WIN32)
- int flags;
- flags=fcntl(_fd,F_GETFL);
- if(OP_UNLIKELY(flags<0))return flags;
- if(_nonblocking)flags|=O_NONBLOCK;
- else flags&=~O_NONBLOCK;
- return fcntl(_fd,F_SETFL,flags);
-#else
- return ioctl(_fd,FIONBIO,&_nonblocking);
-#endif
-}
-
-/*Disable/enable write coalescing if we can.
- We always send whole requests at once and always parse the response headers
- before sending another one, so normally write coalescing just causes added
- delay.*/
-static void op_sock_set_tcp_nodelay(op_sock _fd,int _nodelay){
-# if defined(TCP_NODELAY)&&(defined(IPPROTO_TCP)||defined(SOL_TCP))
-# if defined(IPPROTO_TCP)
-# define OP_SO_LEVEL IPPROTO_TCP
-# else
-# define OP_SO_LEVEL SOL_TCP
-# endif
- /*It doesn't really matter if this call fails, but it would be interesting
- to hit a case where it does.*/
- OP_ALWAYS_TRUE(!setsockopt(_fd,OP_SO_LEVEL,TCP_NODELAY,
- &_nodelay,sizeof(_nodelay)));
-# endif
-}
-
-#if defined(_WIN32)
-static void op_init_winsock(){
- static LONG count;
- static WSADATA wsadata;
- if(InterlockedIncrement(&count)==1)WSAStartup(0x0202,&wsadata);
-}
-#endif
-
-/*A single physical connection to an HTTP server.
- We may have several of these open at once.*/
-struct OpusHTTPConn{
- /*The current position indicator for this connection.*/
- opus_int64 pos;
- /*The position where the current request will end, or -1 if we're reading
- until EOF (an unseekable stream or the initial HTTP/1.0 request).*/
- opus_int64 end_pos;
- /*The position where next request we've sent will start, or -1 if we haven't
- sent the next request yet.*/
- opus_int64 next_pos;
- /*The end of the next request or -1 if we requested the rest of the resource.
- This is only set to a meaningful value if next_pos is not -1.*/
- opus_int64 next_end;
- /*The SSL connection, if this is https.*/
- SSL *ssl_conn;
- /*The next connection in either the LRU or free list.*/
- OpusHTTPConn *next;
- /*The last time we blocked for reading from this connection.*/
- struct timeb read_time;
- /*The number of bytes we've read since the last time we blocked.*/
- opus_int64 read_bytes;
- /*The estimated throughput of this connection, in bytes/s.*/
- opus_int64 read_rate;
- /*The socket we're reading from.*/
- op_sock fd;
- /*The number of remaining requests we are allowed on this connection.*/
- int nrequests_left;
- /*The chunk size to use for pipelining requests.*/
- opus_int32 chunk_size;
-};
-
-static void op_http_conn_init(OpusHTTPConn *_conn){
- _conn->next_pos=-1;
- _conn->ssl_conn=NULL;
- _conn->next=NULL;
- _conn->fd=OP_INVALID_SOCKET;
-}
-
-static void op_http_conn_clear(OpusHTTPConn *_conn){
- if(_conn->ssl_conn!=NULL)SSL_free(_conn->ssl_conn);
- /*SSL frees the BIO for us.*/
- if(_conn->fd!=OP_INVALID_SOCKET)close(_conn->fd);
-}
-
-/*The global stream state.*/
-struct OpusHTTPStream{
- /*The list of connections.*/
- OpusHTTPConn conns[OP_NCONNS_MAX];
- /*The context object used as a framework for TLS/SSL functions.*/
- SSL_CTX *ssl_ctx;
- /*The cached session to reuse for future connections.*/
- SSL_SESSION *ssl_session;
- /*The LRU list (ordered from MRU to LRU) of currently connected
- connections.*/
- OpusHTTPConn *lru_head;
- /*The free list.*/
- OpusHTTPConn *free_head;
- /*The URL to connect to.*/
- OpusParsedURL url;
- /*Information about the address we connected to.*/
- struct addrinfo addr_info;
- /*The address we connected to.*/
- union{
- struct sockaddr s;
- struct sockaddr_in v4;
- struct sockaddr_in6 v6;
- } addr;
- /*The last time we re-resolved the host.*/
- struct timeb resolve_time;
- /*A buffer used to build HTTP requests.*/
- OpusStringBuf request;
- /*A buffer used to build proxy CONNECT requests.*/
- OpusStringBuf proxy_connect;
- /*A buffer used to receive the response headers.*/
- OpusStringBuf response;
- /*The Content-Length, if specified, or -1 otherwise.
- This will always be specified for seekable streams.*/
- opus_int64 content_length;
- /*The position indicator used when no connection is active.*/
- opus_int64 pos;
- /*The host we actually connected to.*/
- char *connect_host;
- /*The port we actually connected to.*/
- unsigned connect_port;
- /*The connection we're currently reading from.
- This can be -1 if no connection is active.*/
- int cur_conni;
- /*Whether or not the server supports range requests.*/
- int seekable;
- /*Whether or not the server supports HTTP/1.1 with persistent connections.*/
- int pipeline;
- /*Whether or not we should skip certificate checks.*/
- int skip_certificate_check;
- /*The offset of the tail of the request.
- Only the offset in the Range: header appears after this, allowing us to
- quickly edit the request to ask for a new range.*/
- int request_tail;
- /*The estimated time required to open a new connection, in milliseconds.*/
- opus_int32 connect_rate;
-};
-
-static void op_http_stream_init(OpusHTTPStream *_stream){
- OpusHTTPConn **pnext;
- int ci;
- pnext=&_stream->free_head;
- for(ci=0;ci<OP_NCONNS_MAX;ci++){
- op_http_conn_init(_stream->conns+ci);
- *pnext=_stream->conns+ci;
- pnext=&_stream->conns[ci].next;
- }
- _stream->ssl_ctx=NULL;
- _stream->ssl_session=NULL;
- _stream->lru_head=NULL;
- op_parsed_url_init(&_stream->url);
- op_sb_init(&_stream->request);
- op_sb_init(&_stream->proxy_connect);
- op_sb_init(&_stream->response);
- _stream->connect_host=NULL;
- _stream->seekable=0;
-}
-
-/*Close the connection and move it to the free list.
- _stream: The stream containing the free list.
- _conn: The connection to close.
- _pnext: The linked-list pointer currently pointing to this connection.
- _gracefully: Whether or not to shut down cleanly.*/
-static void op_http_conn_close(OpusHTTPStream *_stream,OpusHTTPConn *_conn,
- OpusHTTPConn **_pnext,int _gracefully){
- /*If we don't shut down gracefully, the server MUST NOT re-use our session
- according to RFC 2246, because it can't tell the difference between an
- abrupt close and a truncation attack.
- So we shut down gracefully if we can.
- However, we will not wait if this would block (it's not worth the savings
- from session resumption to do so).
- Clients (that's us) MAY resume a TLS session that ended with an incomplete
- close, according to RFC 2818, so there's no reason to make sure the server
- shut things down gracefully.*/
- if(_gracefully&&_conn->ssl_conn!=NULL)SSL_shutdown(_conn->ssl_conn);
- op_http_conn_clear(_conn);
- _conn->next_pos=-1;
- _conn->ssl_conn=NULL;
- _conn->fd=OP_INVALID_SOCKET;
- OP_ASSERT(*_pnext==_conn);
- *_pnext=_conn->next;
- _conn->next=_stream->free_head;
- _stream->free_head=_conn;
-}
-
-static void op_http_stream_clear(OpusHTTPStream *_stream){
- while(_stream->lru_head!=NULL){
- op_http_conn_close(_stream,_stream->lru_head,&_stream->lru_head,0);
- }
- if(_stream->ssl_session!=NULL)SSL_SESSION_free(_stream->ssl_session);
- if(_stream->ssl_ctx!=NULL)SSL_CTX_free(_stream->ssl_ctx);
- op_sb_clear(&_stream->response);
- op_sb_clear(&_stream->proxy_connect);
- op_sb_clear(&_stream->request);
- if(_stream->connect_host!=_stream->url.host)_ogg_free(_stream->connect_host);
- op_parsed_url_clear(&_stream->url);
-}
-
-static int op_http_conn_write_fully(OpusHTTPConn *_conn,
- const char *_buf,int _buf_size){
- struct pollfd fd;
- SSL *ssl_conn;
- fd.fd=_conn->fd;
- ssl_conn=_conn->ssl_conn;
- while(_buf_size>0){
- int err;
- if(ssl_conn!=NULL){
- int ret;
- ret=SSL_write(ssl_conn,_buf,_buf_size);
- if(ret>0){
- /*Wrote some data.*/
- _buf+=ret;
- _buf_size-=ret;
- continue;
- }
- /*Connection closed.*/
- else if(ret==0)return OP_FALSE;
- err=SSL_get_error(ssl_conn,ret);
- /*Yes, renegotiations can cause SSL_write() to block for reading.*/
- if(err==SSL_ERROR_WANT_READ)fd.events=POLLIN;
- else if(err==SSL_ERROR_WANT_WRITE)fd.events=POLLOUT;
- else return OP_FALSE;
- }
- else{
- ssize_t ret;
- op_reset_errno();
- ret=send(fd.fd,_buf,_buf_size,0);
- if(ret>0){
- _buf+=ret;
- _buf_size-=ret;
- continue;
- }
- err=op_errno();
- if(err!=EAGAIN&&err!=EWOULDBLOCK)return OP_FALSE;
- fd.events=POLLOUT;
- }
- if(poll(&fd,1,OP_POLL_TIMEOUT_MS)<=0)return OP_FALSE;
- }
- return 0;
-}
-
-static int op_http_conn_estimate_available(OpusHTTPConn *_conn){
- int available;
- int ret;
- ret=ioctl(_conn->fd,FIONREAD,&available);
- if(ret<0)available=0;
- /*This requires the SSL read_ahead flag to be unset to work.
- We ignore partial records as well as the protocol overhead for any pending
- bytes.
- This means we might return somewhat less than can truly be read without
- blocking (if there's a partial record).
- This is okay, because we're using this value to estimate network transfer
- time, and we _have_ already received those bytes.
- We also might return slightly more (due to protocol overhead), but that's
- small enough that it probably doesn't matter.*/
- if(_conn->ssl_conn!=NULL)available+=SSL_pending(_conn->ssl_conn);
- return available;
-}
-
-static opus_int32 op_time_diff_ms(const struct timeb *_end,
- const struct timeb *_start){
- opus_int64 dtime;
- dtime=_end->time-(opus_int64)_start->time;
- OP_ASSERT(_end->millitm<1000);
- OP_ASSERT(_start->millitm<1000);
- if(OP_UNLIKELY(dtime>(OP_INT32_MAX-1000)/1000))return OP_INT32_MAX;
- if(OP_UNLIKELY(dtime<(OP_INT32_MIN+1000)/1000))return OP_INT32_MIN;
- return (opus_int32)dtime*1000+_end->millitm-_start->millitm;
-}
-
-/*Update the read rate estimate for this connection.*/
-static void op_http_conn_read_rate_update(OpusHTTPConn *_conn){
- struct timeb read_time;
- opus_int32 read_delta_ms;
- opus_int64 read_delta_bytes;
- opus_int64 read_rate;
- read_delta_bytes=_conn->read_bytes;
- if(read_delta_bytes<=0)return;
- ftime(&read_time);
- read_delta_ms=op_time_diff_ms(&read_time,&_conn->read_time);
- read_rate=_conn->read_rate;
- read_delta_ms=OP_MAX(read_delta_ms,1);
- read_rate+=read_delta_bytes*1000/read_delta_ms-read_rate+4>>3;
- *&_conn->read_time=*&read_time;
- _conn->read_bytes=0;
- _conn->read_rate=read_rate;
-}
-
-/*Tries to read from the given connection.
- [out] _buf: Returns the data read.
- _buf_size: The size of the buffer.
- _blocking: Whether or not to block until some data is retrieved.
- Return: A positive number of bytes read on success.
- 0: The read would block, or the connection was closed.
- OP_EREAD: There was a fatal read error.*/
-static int op_http_conn_read(OpusHTTPConn *_conn,
- char *_buf,int _buf_size,int _blocking){
- struct pollfd fd;
- SSL *ssl_conn;
- int nread;
- int nread_unblocked;
- fd.fd=_conn->fd;
- ssl_conn=_conn->ssl_conn;
- nread=nread_unblocked=0;
- /*RFC 2818 says "client implementations MUST treat any premature closes as
- errors and the data received as potentially truncated," so we make very
- sure to report read errors upwards.*/
- do{
- int err;
- if(ssl_conn!=NULL){
- int ret;
- ret=SSL_read(ssl_conn,_buf+nread,_buf_size-nread);
- OP_ASSERT(ret<=_buf_size-nread);
- if(ret>0){
- /*Read some data.
- Keep going to see if there's more.*/
- nread+=ret;
- nread_unblocked+=ret;
- continue;
- }
- /*If we already read some data, return it right now.*/
- if(nread>0)break;
- err=SSL_get_error(ssl_conn,ret);
- if(ret==0){
- /*Connection close.
- Check for a clean shutdown to prevent truncation attacks.
- This check always succeeds for SSLv2, as it has no "close notify"
- message and thus can't verify an orderly shutdown.*/
- return err==SSL_ERROR_ZERO_RETURN?0:OP_EREAD;
- }
- if(err==SSL_ERROR_WANT_READ)fd.events=POLLIN;
- /*Yes, renegotiations can cause SSL_read() to block for writing.*/
- else if(err==SSL_ERROR_WANT_WRITE)fd.events=POLLOUT;
- /*Some other error.*/
- else return OP_EREAD;
- }
- else{
- ssize_t ret;
- op_reset_errno();
- ret=recv(fd.fd,_buf+nread,_buf_size-nread,0);
- OP_ASSERT(ret<=_buf_size-nread);
- if(ret>0){
- /*Read some data.
- Keep going to see if there's more.*/
- nread+=ret;
- nread_unblocked+=ret;
- continue;
- }
- /*If we already read some data or the connection was closed, return
- right now.*/
- if(ret==0||nread>0)break;
- err=op_errno();
- if(err!=EAGAIN&&err!=EWOULDBLOCK)return OP_EREAD;
- fd.events=POLLIN;
- }
- _conn->read_bytes+=nread_unblocked;
- op_http_conn_read_rate_update(_conn);
- nread_unblocked=0;
- if(!_blocking)break;
- /*Need to wait to get any data at all.*/
- if(poll(&fd,1,OP_POLL_TIMEOUT_MS)<=0)return OP_EREAD;
- }
- while(nread<_buf_size);
- _conn->read_bytes+=nread_unblocked;
- return nread;
-}
-
-/*Tries to look at the pending data for a connection without consuming it.
- [out] _buf: Returns the data at which we're peeking.
- _buf_size: The size of the buffer.*/
-static int op_http_conn_peek(OpusHTTPConn *_conn,char *_buf,int _buf_size){
- struct pollfd fd;
- SSL *ssl_conn;
- int ret;
- fd.fd=_conn->fd;
- ssl_conn=_conn->ssl_conn;
- for(;;){
- int err;
- if(ssl_conn!=NULL){
- ret=SSL_peek(ssl_conn,_buf,_buf_size);
- /*Either saw some data or the connection was closed.*/
- if(ret>=0)return ret;
- err=SSL_get_error(ssl_conn,ret);
- if(err==SSL_ERROR_WANT_READ)fd.events=POLLIN;
- /*Yes, renegotiations can cause SSL_peek() to block for writing.*/
- else if(err==SSL_ERROR_WANT_WRITE)fd.events=POLLOUT;
- else return 0;
- }
- else{
- op_reset_errno();
- ret=(int)recv(fd.fd,_buf,_buf_size,MSG_PEEK);
- /*Either saw some data or the connection was closed.*/
- if(ret>=0)return ret;
- err=op_errno();
- if(err!=EAGAIN&&err!=EWOULDBLOCK)return 0;
- fd.events=POLLIN;
- }
- /*Need to wait to get any data at all.*/
- if(poll(&fd,1,OP_POLL_TIMEOUT_MS)<=0)return 0;
- }
-}
-
-/*When parsing response headers, RFC 2616 mandates that all lines end in CR LF.
- However, even in the year 2012, I have seen broken servers use just a LF.
- This is the evil that Postel's advice from RFC 761 breeds.*/
-
-/*Reads the entirety of a response to an HTTP request into the response buffer.
- Actual parsing and validation is done later.
- Return: The number of bytes in the response on success, OP_EREAD if the
- connection was closed before reading any data, or another negative
- value on any other error.*/
-static int op_http_conn_read_response(OpusHTTPConn *_conn,
- OpusStringBuf *_response){
- int ret;
- _response->nbuf=0;
- ret=op_sb_ensure_capacity(_response,OP_RESPONSE_SIZE_MIN);
- if(OP_UNLIKELY(ret<0))return ret;
- for(;;){
- char *buf;
- int size;
- int capacity;
- int read_limit;
- int terminated;
- size=_response->nbuf;
- capacity=_response->cbuf-1;
- if(OP_UNLIKELY(size>=capacity)){
- ret=op_sb_grow(_response,OP_RESPONSE_SIZE_MAX);
- if(OP_UNLIKELY(ret<0))return ret;
- capacity=_response->cbuf-1;
- /*The response was too large.
- This prevents a bad server from running us out of memory.*/
- if(OP_UNLIKELY(size>=capacity))return OP_EIMPL;
- }
- buf=_response->buf;
- ret=op_http_conn_peek(_conn,buf+size,capacity-size);
- if(OP_UNLIKELY(ret<=0))return size<=0?OP_EREAD:OP_FALSE;
- /*We read some data.*/
- /*Make sure the starting characters are "HTTP".
- Otherwise we could wind up waiting forever for a response from
- something that is not an HTTP server.*/
- if(size<4&&op_strncasecmp(buf,"HTTP",OP_MIN(size+ret,4))!=0){
- return OP_FALSE;
- }
- /*How far can we read without passing the "\r\n\r\n" terminator?*/
- buf[size+ret]='\0';
- terminated=0;
- for(read_limit=OP_MAX(size-3,0);read_limit<size+ret;read_limit++){
- /*We don't look for the leading '\r' thanks to broken servers.*/
- if(buf[read_limit]=='\n'){
- if(buf[read_limit+1]=='\r'&&OP_LIKELY(buf[read_limit+2]=='\n')){
- terminated=3;
- break;
- }
- /*This case is for broken servers.*/
- else if(OP_UNLIKELY(buf[read_limit+1]=='\n')){
- terminated=2;
- break;
- }
- }
- }
- read_limit+=terminated;
- OP_ASSERT(size<=read_limit);
- OP_ASSERT(read_limit<=size+ret);
- /*Actually consume that data.*/
- ret=op_http_conn_read(_conn,buf+size,read_limit-size,1);
- if(OP_UNLIKELY(ret<=0))return OP_FALSE;
- size+=ret;
- buf[size]='\0';
- _response->nbuf=size;
- /*We found the terminator and read all the data up to and including it.*/
- if(terminated&&OP_LIKELY(size>=read_limit))return size;
- }
- return OP_EIMPL;
-}
-
-# define OP_HTTP_DIGIT "0123456789"
-
-/*The Reason-Phrase is not allowed to contain control characters, except
- horizontal tab (HT: \011).*/
-# define OP_HTTP_CREASON_PHRASE \
- "\001\002\003\004\005\006\007\010\012\013\014\015\016\017\020\021" \
- "\022\023\024\025\026\027\030\031\032\033\034\035\036\037\177"
-
-# define OP_HTTP_CTLS \
- "\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\177"
-
-/*This also includes '\t', but we get that from OP_HTTP_CTLS.*/
-# define OP_HTTP_SEPARATORS " \"(),/:;<=>?@[\\]{}"
-
-/*TEXT can also include LWS, but that has structure, so we parse it
- separately.*/
-# define OP_HTTP_CTOKEN OP_HTTP_CTLS OP_HTTP_SEPARATORS
-
-/*Return: The amount of linear white space (LWS) at the start of _s.*/
-static int op_http_lwsspn(const char *_s){
- int i;
- for(i=0;;){
- if(_s[0]=='\r'&&_s[1]=='\n'&&(_s[2]=='\t'||_s[2]==' '))i+=3;
- /*This case is for broken servers.*/
- else if(_s[0]=='\n'&&(_s[1]=='\t'||_s[1]==' '))i+=2;
- else if(_s[i]=='\t'||_s[i]==' ')i++;
- else return i;
- }
-}
-
-static char *op_http_parse_status_line(int *_v1_1_compat,
- char **_status_code,char *_response){
- char *next;
- char *status_code;
- int v1_1_compat;
- size_t d;
- /*RFC 2616 Section 6.1 does not say that the tokens in the Status-Line cannot
- be separated by optional LWS, but since it specifically calls out where
- spaces are to be placed and that CR and LF are not allowed except at the
- end, I am assuming this to be true.*/
- /*We already validated that this starts with "HTTP"*/
- OP_ASSERT(op_strncasecmp(_response,"HTTP",4)==0);
- next=_response+4;
- if(OP_UNLIKELY(*next++!='/'))return NULL;
- d=strspn(next,OP_HTTP_DIGIT);
- /*"Leading zeros MUST be ignored by recipients."*/
- while(*next=='0'){
- next++;
- OP_ASSERT(d>0);
- d--;
- }
- /*We only support version 1.x*/
- if(OP_UNLIKELY(d!=1)||OP_UNLIKELY(*next++!='1'))return NULL;
- if(OP_UNLIKELY(*next++!='.'))return NULL;
- d=strspn(next,OP_HTTP_DIGIT);
- if(OP_UNLIKELY(d<=0))return NULL;
- /*"Leading zeros MUST be ignored by recipients."*/
- while(*next=='0'){
- next++;
- OP_ASSERT(d>0);
- d--;
- }
- /*We don't need to parse the version number.
- Any non-zero digit means it's greater than 1.*/
- v1_1_compat=d>0;
- next+=d;
- if(OP_UNLIKELY(*next++!=' '))return NULL;
- status_code=next;
- d=strspn(next,OP_HTTP_DIGIT);
- if(OP_UNLIKELY(d!=3))return NULL;
- next+=d;
- /*The Reason-Phrase can be empty, but the space must be here.*/
- if(OP_UNLIKELY(*next++!=' '))return NULL;
- next+=strcspn(next,OP_HTTP_CREASON_PHRASE);
- /*We are not mandating this be present thanks to broken servers.*/
- if(OP_LIKELY(*next=='\r'))next++;
- if(OP_UNLIKELY(*next++!='\n'))return NULL;
- if(_v1_1_compat!=NULL)*_v1_1_compat=v1_1_compat;
- *_status_code=status_code;
- return next;
-}
-
-/*Get the next response header.
- [out] _header: The header token, NUL-terminated, with leading and trailing
- whitespace stripped, and converted to lower case (to simplify
- case-insensitive comparisons), or NULL if there are no more
- response headers.
- [out] _cdr: The remaining contents of the header, excluding the initial
- colon (':') and the terminating CRLF ("\r\n"),
- NUL-terminated, and with leading and trailing whitespace
- stripped, or NULL if there are no more response headers.
- [inout] _s: On input, this points to the start of the current line of the
- response headers.
- On output, it points to the start of the first line following
- this header, or NULL if there are no more response headers.
- Return: 0 on success, or a negative value on failure.*/
-static int op_http_get_next_header(char **_header,char **_cdr,char **_s){
- char *header;
- char *header_end;
- char *cdr;
- char *cdr_end;
- char *next;
- size_t d;
- next=*_s;
- /*The second case is for broken servers.*/
- if(next[0]=='\r'&&next[1]=='\n'||OP_UNLIKELY(next[0]=='\n')){
- /*No more headers.*/
- *_header=NULL;
- *_cdr=NULL;
- *_s=NULL;
- return 0;
- }
- header=next+op_http_lwsspn(next);
- d=strcspn(header,OP_HTTP_CTOKEN);
- if(OP_UNLIKELY(d<=0))return OP_FALSE;
- header_end=header+d;
- next=header_end+op_http_lwsspn(header_end);
- if(OP_UNLIKELY(*next++!=':'))return OP_FALSE;
- next+=op_http_lwsspn(next);
- cdr=next;
- do{
- cdr_end=next+strcspn(next,OP_HTTP_CTLS);
- next=cdr_end+op_http_lwsspn(cdr_end);
- }
- while(next>cdr_end);
- /*We are not mandating this be present thanks to broken servers.*/
- if(OP_LIKELY(*next=='\r'))next++;
- if(OP_UNLIKELY(*next++!='\n'))return OP_FALSE;
- *header_end='\0';
- *cdr_end='\0';
- /*Field names are case-insensitive.*/
- op_string_tolower(header);
- *_header=header;
- *_cdr=cdr;
- *_s=next;
- return 0;
-}
-
-static opus_int64 op_http_parse_nonnegative_int64(const char **_next,
- const char *_cdr){
- const char *next;
- opus_int64 ret;
- int i;
- next=_cdr+strspn(_cdr,OP_HTTP_DIGIT);
- *_next=next;
- if(OP_UNLIKELY(next<=_cdr))return OP_FALSE;
- while(*_cdr=='0')_cdr++;
- if(OP_UNLIKELY(next-_cdr>19))return OP_EIMPL;
- ret=0;
- for(i=0;i<next-_cdr;i++){
- int digit;
- digit=_cdr[i]-'0';
- /*Check for overflow.*/
- if(OP_UNLIKELY(ret>(OP_INT64_MAX-9)/10+(digit<=7)))return OP_EIMPL;
- ret=ret*10+digit;
- }
- return ret;
-}
-
-static opus_int64 op_http_parse_content_length(const char *_cdr){
- const char *next;
- opus_int64 content_length;
- content_length=op_http_parse_nonnegative_int64(&next,_cdr);
- if(OP_UNLIKELY(*next!='\0'))return OP_FALSE;
- return content_length;
-}
-
-static int op_http_parse_content_range(opus_int64 *_first,opus_int64 *_last,
- opus_int64 *_length,const char *_cdr){
- opus_int64 first;
- opus_int64 last;
- opus_int64 length;
- size_t d;
- if(OP_UNLIKELY(op_strncasecmp(_cdr,"bytes",5)!=0))return OP_FALSE;
- _cdr+=5;
- d=op_http_lwsspn(_cdr);
- if(OP_UNLIKELY(d<=0))return OP_FALSE;
- _cdr+=d;
- if(*_cdr!='*'){
- first=op_http_parse_nonnegative_int64(&_cdr,_cdr);
- if(OP_UNLIKELY(first<0))return (int)first;
- _cdr+=op_http_lwsspn(_cdr);
- if(*_cdr++!='-')return OP_FALSE;
- _cdr+=op_http_lwsspn(_cdr);
- last=op_http_parse_nonnegative_int64(&_cdr,_cdr);
- if(OP_UNLIKELY(last<0))return (int)last;
- _cdr+=op_http_lwsspn(_cdr);
- }
- else{
- /*This is for a 416 response (Requested range not satisfiable).*/
- first=last=-1;
- _cdr++;
- }
- if(OP_UNLIKELY(*_cdr++!='/'))return OP_FALSE;
- if(*_cdr!='*'){
- length=op_http_parse_nonnegative_int64(&_cdr,_cdr);
- if(OP_UNLIKELY(length<0))return (int)length;
- }
- else{
- /*The total length is unspecified.*/
- _cdr++;
- length=-1;
- }
- if(OP_UNLIKELY(*_cdr!='\0'))return OP_FALSE;
- if(OP_UNLIKELY(last<first))return OP_FALSE;
- if(length>=0&&OP_UNLIKELY(last>=length))return OP_FALSE;
- *_first=first;
- *_last=last;
- *_length=length;
- return 0;
-}
-
-/*Parse the Connection response header and look for a "close" token.
- Return: 1 if a "close" token is found, 0 if it's not found, and a negative
- value on error.*/
-static int op_http_parse_connection(char *_cdr){
- size_t d;
- int ret;
- ret=0;
- for(;;){
- d=strcspn(_cdr,OP_HTTP_CTOKEN);
- if(OP_UNLIKELY(d<=0))return OP_FALSE;
- if(op_strncasecmp(_cdr,"close",(int)d)==0)ret=1;
- /*We're supposed to strip and ignore any headers mentioned in the
- Connection header if this response is from an HTTP/1.0 server (to
- work around forwarding of hop-by-hop headers by old proxies), but the
- only hop-by-hop header we look at is Connection itself.
- Everything else is a well-defined end-to-end header, and going back and
- undoing the things we did based on already-examined headers would be
- hard (since we only scan them once, in a destructive manner).
- Therefore we just ignore all the other tokens.*/
- _cdr+=d;
- d=op_http_lwsspn(_cdr);
- if(d<=0)break;
- _cdr+=d;
- }
- return OP_UNLIKELY(*_cdr!='\0')?OP_FALSE:ret;
-}
-
-typedef int (*op_ssl_step_func)(SSL *_ssl_conn);
-
-/*Try to run an SSL function to completion (blocking if necessary).*/
-static int op_do_ssl_step(SSL *_ssl_conn,op_sock _fd,op_ssl_step_func _step){
- struct pollfd fd;
- fd.fd=_fd;
- for(;;){
- int ret;
- int err;
- ret=(*_step)(_ssl_conn);
- if(ret>=0)return ret;
- err=SSL_get_error(_ssl_conn,ret);
- if(err==SSL_ERROR_WANT_READ)fd.events=POLLIN;
- else if(err==SSL_ERROR_WANT_WRITE)fd.events=POLLOUT;
- else return OP_FALSE;
- if(poll(&fd,1,OP_POLL_TIMEOUT_MS)<=0)return OP_FALSE;
- }
-}
-
-/*Implement a BIO type that just indicates every operation should be retried.
- We use this when initializing an SSL connection via a proxy to allow the
- initial handshake to proceed all the way up to the first read attempt, and
- then return.
- This allows the TLS client hello message to be pipelined with the HTTP
- CONNECT request.*/
-
-static int op_bio_retry_write(BIO *_b,const char *_buf,int _num){
- (void)_buf;
- (void)_num;
- BIO_clear_retry_flags(_b);
- BIO_set_retry_write(_b);
- return -1;
-}
-
-static int op_bio_retry_read(BIO *_b,char *_buf,int _num){
- (void)_buf;
- (void)_num;
- BIO_clear_retry_flags(_b);
- BIO_set_retry_read(_b);
- return -1;
-}
-
-static int op_bio_retry_puts(BIO *_b,const char *_str){
- return op_bio_retry_write(_b,_str,0);
-}
-
-static long op_bio_retry_ctrl(BIO *_b,int _cmd,long _num,void *_ptr){
- long ret;
- (void)_b;
- (void)_num;
- (void)_ptr;
- ret=0;
- switch(_cmd){
- case BIO_CTRL_RESET:
- case BIO_C_RESET_READ_REQUEST:{
- BIO_clear_retry_flags(_b);
- /*Fall through.*/
- }
- case BIO_CTRL_EOF:
- case BIO_CTRL_SET:
- case BIO_CTRL_SET_CLOSE:
- case BIO_CTRL_FLUSH:
- case BIO_CTRL_DUP:{
- ret=1;
- }break;
- }
- return ret;
-}
-
-# if OPENSSL_VERSION_NUMBER<0x10100000L
-# define BIO_set_data(_b,_ptr) ((_b)->ptr=(_ptr))
-# define BIO_set_init(_b,_init) ((_b)->init=(_init))
-# endif
-
-static int op_bio_retry_new(BIO *_b){
- BIO_set_init(_b,1);
-# if OPENSSL_VERSION_NUMBER<0x10100000L
- _b->num=0;
-# endif
- BIO_set_data(_b,NULL);
- return 1;
-}
-
-static int op_bio_retry_free(BIO *_b){
- return _b!=NULL;
-}
-
-# if OPENSSL_VERSION_NUMBER<0x10100000L
-/*This is not const because OpenSSL doesn't allow it, even though it won't
- write to it.*/
-static BIO_METHOD op_bio_retry_method={
- BIO_TYPE_NULL,
- "retry",
- op_bio_retry_write,
- op_bio_retry_read,
- op_bio_retry_puts,
- NULL,
- op_bio_retry_ctrl,
- op_bio_retry_new,
- op_bio_retry_free,
- NULL
-};
-# endif
-
-/*Establish a CONNECT tunnel and pipeline the start of the TLS handshake for
- proxying https URL requests.*/
-static int op_http_conn_establish_tunnel(OpusHTTPStream *_stream,
- OpusHTTPConn *_conn,op_sock _fd,SSL *_ssl_conn,BIO *_ssl_bio){
-# if OPENSSL_VERSION_NUMBER>=0x10100000L
- BIO_METHOD *bio_retry_method;
-# endif
- BIO *retry_bio;
- char *status_code;
- char *next;
- int ret;
- _conn->ssl_conn=NULL;
- _conn->fd=_fd;
- OP_ASSERT(_stream->proxy_connect.nbuf>0);
- ret=op_http_conn_write_fully(_conn,
- _stream->proxy_connect.buf,_stream->proxy_connect.nbuf);
- if(OP_UNLIKELY(ret<0))return ret;
-# if OPENSSL_VERSION_NUMBER>=0x10100000L
- bio_retry_method=BIO_meth_new(BIO_TYPE_NULL,"retry");
- if(bio_retry_method==NULL)return OP_EFAULT;
- BIO_meth_set_write(bio_retry_method,op_bio_retry_write);
- BIO_meth_set_read(bio_retry_method,op_bio_retry_read);
- BIO_meth_set_puts(bio_retry_method,op_bio_retry_puts);
- BIO_meth_set_ctrl(bio_retry_method,op_bio_retry_ctrl);
- BIO_meth_set_create(bio_retry_method,op_bio_retry_new);
- BIO_meth_set_destroy(bio_retry_method,op_bio_retry_free);
- retry_bio=BIO_new(bio_retry_method);
- if(OP_UNLIKELY(retry_bio==NULL)){
- BIO_meth_free(bio_retry_method);
- return OP_EFAULT;
- }
-# else
- retry_bio=BIO_new(&op_bio_retry_method);
- if(OP_UNLIKELY(retry_bio==NULL))return OP_EFAULT;
-# endif
- SSL_set_bio(_ssl_conn,retry_bio,_ssl_bio);
- SSL_set_connect_state(_ssl_conn);
- /*This shouldn't succeed, since we can't read yet.*/
- OP_ALWAYS_TRUE(SSL_connect(_ssl_conn)<0);
- SSL_set_bio(_ssl_conn,_ssl_bio,_ssl_bio);
-# if OPENSSL_VERSION_NUMBER>=0x10100000L
- BIO_meth_free(bio_retry_method);
-# endif
- /*Only now do we disable write coalescing, to allow the CONNECT
- request and the start of the TLS handshake to be combined.*/
- op_sock_set_tcp_nodelay(_fd,1);
- ret=op_http_conn_read_response(_conn,&_stream->response);
- if(OP_UNLIKELY(ret<0))return ret;
- next=op_http_parse_status_line(NULL,&status_code,_stream->response.buf);
- /*According to RFC 2817, "Any successful (2xx) response to a
- CONNECT request indicates that the proxy has established a
- connection to the requested host and port.*/
- if(OP_UNLIKELY(next==NULL)||OP_UNLIKELY(status_code[0]!='2'))return OP_FALSE;
- return 0;
-}
-
-/*Match a host name against a host with a possible wildcard pattern according
- to the rules of RFC 6125 Section 6.4.3.
- Return: 0 if the pattern doesn't match, and a non-zero value if it does.*/
-static int op_http_hostname_match(const char *_host,size_t _host_len,
- ASN1_STRING *_pattern){
- const char *pattern;
- size_t host_label_len;
- size_t host_suffix_len;
- size_t pattern_len;
- size_t pattern_label_len;
- size_t pattern_prefix_len;
- size_t pattern_suffix_len;
- pattern=(const char *)ASN1_STRING_data(_pattern);
- pattern_len=strlen(pattern);
- /*Check the pattern for embedded NULs.*/
- if(OP_UNLIKELY(pattern_len!=(size_t)ASN1_STRING_length(_pattern)))return 0;
- pattern_label_len=strcspn(pattern,".");
- OP_ASSERT(pattern_label_len<=pattern_len);
- pattern_prefix_len=strcspn(pattern,"*");
- if(pattern_prefix_len>=pattern_label_len){
- /*"The client SHOULD NOT attempt to match a presented identifier in which
- the wildcard character comprises a label other than the left-most label
- (e.g., do not match bar.*.example.net)." [RFC 6125 Section 6.4.3]*/
- if(pattern_prefix_len<pattern_len)return 0;
- /*If the pattern does not contain a wildcard in the first element, do an
- exact match.
- Don't use the system strcasecmp here, as that uses the locale and
- RFC 4343 makes clear that DNS's case-insensitivity only applies to
- the ASCII range.*/
- return _host_len==pattern_len&&op_strncasecmp(_host,pattern,_host_len)==0;
- }
- /*"However, the client SHOULD NOT attempt to match a presented identifier
- where the wildcard character is embedded within an A-label or U-label of
- an internationalized domain name." [RFC 6125 Section 6.4.3]*/
- if(op_strncasecmp(pattern,"xn--",4)==0)return 0;
- host_label_len=strcspn(_host,".");
- /*Make sure the host has at least two dots, to prevent the wildcard match
- from being ridiculously wide.
- We should have already checked to ensure it had at least one.*/
- if(OP_UNLIKELY(_host[host_label_len]!='.')
- ||strchr(_host+host_label_len+1,'.')==NULL){
- return 0;
- }
- OP_ASSERT(host_label_len<_host_len);
- /*"If the wildcard character is the only character of the left-most label in
- the presented identifier, the client SHOULD NOT compare against anything
- but the left-most label of the reference identifier (e.g., *.example.com
- would match foo.example.com but not bar.foo.example.com)." [RFC 6125
- Section 6.4.3]
- This is really confusingly worded, as we check this by actually comparing
- the rest of the pattern for an exact match.
- We also use the fact that the wildcard must match at least one character,
- so the left-most label of the hostname must be at least as large as the
- left-most label of the pattern.*/
- if(host_label_len<pattern_label_len)return 0;
- OP_ASSERT(pattern[pattern_prefix_len]=='*');
- /*"The client MAY match a presented identifier in which the wildcard
- character is not the only character of the label (e.g., baz*.example.net
- and *baz.example.net and b*z.example.net would be taken to match
- baz1.example.net and foobaz.example.net and buzz.example.net,
- respectively)." [RFC 6125 Section 6.4.3]*/
- pattern_suffix_len=pattern_len-pattern_prefix_len-1;
- host_suffix_len=_host_len-host_label_len
- +pattern_label_len-pattern_prefix_len-1;
- return pattern_suffix_len==host_suffix_len
- &&op_strncasecmp(_host,pattern,pattern_prefix_len)==0
- &&op_strncasecmp(_host+_host_len-host_suffix_len,
- pattern+pattern_prefix_len+1,host_suffix_len)==0;
-}
-
-/*Convert a host to a numeric address, if possible.
- Return: A struct addrinfo containing the address, if it was numeric, and NULL
- otherise.*/
-static struct addrinfo *op_inet_pton(const char *_host){
- struct addrinfo *addrs;
- struct addrinfo hints;
- memset(&hints,0,sizeof(hints));
- hints.ai_socktype=SOCK_STREAM;
- hints.ai_flags=AI_NUMERICHOST;
- if(!getaddrinfo(_host,NULL,&hints,&addrs))return addrs;
- return NULL;
-}
-
-/*Verify the server's hostname matches the certificate they presented using
- the procedure from Section 6 of RFC 6125.
- Return: 0 if the certificate doesn't match, and a non-zero value if it does.*/
-static int op_http_verify_hostname(OpusHTTPStream *_stream,SSL *_ssl_conn){
- X509 *peer_cert;
- STACK_OF(GENERAL_NAME) *san_names;
- char *host;
- size_t host_len;
- int ret;
- host=_stream->url.host;
- host_len=strlen(host);
- peer_cert=SSL_get_peer_certificate(_ssl_conn);
- /*We set VERIFY_PEER, so we shouldn't get here without a certificate.*/
- if(OP_UNLIKELY(peer_cert==NULL))return 0;
- ret=0;
- OP_ASSERT(host_len<INT_MAX);
- /*RFC 2818 says (after correcting for Eratta 1077): "If a subjectAltName
- extension of type dNSName is present, that MUST be used as the identity.
- Otherwise, the (most specific) Common Name field in the Subject field of
- the certificate MUST be used.
- Although the use of the Common Name is existing practice, it is deprecated
- and Certification Authorities are encouraged to use the dNSName
- instead."
- "Matching is performed using the matching rules specified by RFC 2459.
- If more than one identity of a given type is present in the certificate
- (e.g., more than one dNSName name), a match in any one of the set is
- considered acceptable.
- Names may contain the wildcard character * which is condered to match any
- single domain name component or component fragment.
- E.g., *.a.com matches foo.a.com but not bar.foo.a.com.
- f*.com matches foo.com but not bar.com."
- "In some cases, the URI is specified as an IP address rather than a
- hostname.
- In this case, the iPAddress subjectAltName must be present in the
- certificate and must exactly match the IP in the URI."*/
- san_names=X509_get_ext_d2i(peer_cert,NID_subject_alt_name,NULL,NULL);
- if(san_names!=NULL){
- struct addrinfo *addr;
- unsigned char *ip;
- int ip_len;
- int nsan_names;
- int sni;
- /*Check to see if the host was specified as a simple IP address.*/
- addr=op_inet_pton(host);
- ip=NULL;
- ip_len=0;
- if(addr!=NULL){
- switch(addr->ai_family){
- case AF_INET:{
- struct sockaddr_in *s;
- s=(struct sockaddr_in *)addr->ai_addr;
- OP_ASSERT(addr->ai_addrlen>=sizeof(*s));
- ip=(unsigned char *)&s->sin_addr;
- ip_len=sizeof(s->sin_addr);
- }break;
- case AF_INET6:{
- struct sockaddr_in6 *s;
- s=(struct sockaddr_in6 *)addr->ai_addr;
- OP_ASSERT(addr->ai_addrlen>=sizeof(*s));
- ip=(unsigned char *)&s->sin6_addr;
- ip_len=sizeof(s->sin6_addr);
- }break;
- }
- }
- /*We can only verify fully-qualified domain names.
- To quote RFC 6125: "The extracted data MUST include only information that
- can be securely parsed out of the inputs (e.g., parsing the fully
- qualified DNS domain name out of the "host" component (or its
- equivalent) of a URI or deriving the application service type from the
- scheme of a URI) ..."
- We don't have a way to check (without relying on DNS records, which might
- be subverted) if this address is fully-qualified.
- This is particularly problematic when using a CONNECT tunnel, as it is
- the server that does DNS lookup, not us.
- However, we are certain that if the hostname has no '.', it is definitely
- not a fully-qualified domain name (with the exception of crazy TLDs that
- actually resolve, like "uz", but I am willing to ignore those).
- RFC 1535 says "...in any event where a '.' exists in a specified name it
- should be assumed to be a fully qualified domain name (FQDN) and SHOULD
- be tried as a rooted name first."
- That doesn't give us any security guarantees, of course (a subverted DNS
- could fail the original query and our resolver might still retry with a
- local domain appended).
- If we don't have a FQDN, just set the number of names to 0, so we'll fail
- and clean up any resources we allocated.*/
- if(ip==NULL&&strchr(host,'.')==NULL)nsan_names=0;
- /*RFC 2459 says there MUST be at least one, but we don't depend on it.*/
- else nsan_names=sk_GENERAL_NAME_num(san_names);
- for(sni=0;sni<nsan_names;sni++){
- const GENERAL_NAME *name;
- name=sk_GENERAL_NAME_value(san_names,sni);
- if(ip==NULL){
- if(name->type==GEN_DNS
- &&op_http_hostname_match(host,host_len,name->d.dNSName)){
- ret=1;
- break;
- }
- }
- else if(name->type==GEN_IPADD){
- unsigned char *cert_ip;
- /*If we do have an IP address, compare it directly.
- RFC 6125: "When the reference identity is an IP address, the identity
- MUST be converted to the 'network byte order' octet string
- representation.
- For IP Version 4, as specified in RFC 791, the octet string will
- contain exactly four octets.
- For IP Version 6, as specified in RFC 2460, the octet string will
- contain exactly sixteen octets.
- This octet string is then compared against subjectAltName values of
- type iPAddress.
- A match occurs if the reference identity octet string and the value
- octet strings are identical."*/
- cert_ip=ASN1_STRING_data(name->d.iPAddress);
- if(ip_len==ASN1_STRING_length(name->d.iPAddress)
- &&memcmp(ip,cert_ip,ip_len)==0){
- ret=1;
- break;
- }
- }
- }
- sk_GENERAL_NAME_pop_free(san_names,GENERAL_NAME_free);
- if(addr!=NULL)freeaddrinfo(addr);
- }
- /*Do the same FQDN check we did above.
- We don't do this once in advance for both cases, because in the
- subjectAltName case we might have an IPv6 address without a dot.*/
- else if(strchr(host,'.')!=NULL){
- int last_cn_loc;
- int cn_loc;
- /*If there is no subjectAltName, match against commonName.
- RFC 6125 says that at least one significant CA is known to issue certs
- with multiple CNs, although it SHOULD NOT.
- It also says: "The server's identity may also be verified by comparing
- the reference identity to the Common Name (CN) value in the last
- Relative Distinguished Name (RDN) of the subject field of the server's
- certificate (where "last" refers to the DER-encoded order...)."
- So find the last one and check it.*/
- cn_loc=-1;
- do{
- last_cn_loc=cn_loc;
- cn_loc=X509_NAME_get_index_by_NID(X509_get_subject_name(peer_cert),
- NID_commonName,last_cn_loc);
- }
- while(cn_loc>=0);
- ret=last_cn_loc>=0
- &&op_http_hostname_match(host,host_len,
- X509_NAME_ENTRY_get_data(
- X509_NAME_get_entry(X509_get_subject_name(peer_cert),last_cn_loc)));
- }
- X509_free(peer_cert);
- return ret;
-}
-
-/*Perform the TLS handshake on a new connection.*/
-static int op_http_conn_start_tls(OpusHTTPStream *_stream,OpusHTTPConn *_conn,
- op_sock _fd,SSL *_ssl_conn){
- SSL_SESSION *ssl_session;
- BIO *ssl_bio;
- int skip_certificate_check;
- int ret;
- ssl_bio=BIO_new_socket(_fd,BIO_NOCLOSE);
- if(OP_LIKELY(ssl_bio==NULL))return OP_FALSE;
-# if !defined(OPENSSL_NO_TLSEXT)
- /*Support for RFC 6066 Server Name Indication.*/
- SSL_set_tlsext_host_name(_ssl_conn,_stream->url.host);
-# endif
- /*Resume a previous session if available.*/
- if(_stream->ssl_session!=NULL){
- SSL_set_session(_ssl_conn,_stream->ssl_session);
- }
- /*If we're proxying, establish the CONNECT tunnel.*/
- if(_stream->proxy_connect.nbuf>0){
- ret=op_http_conn_establish_tunnel(_stream,_conn,
- _fd,_ssl_conn,ssl_bio);
- if(OP_UNLIKELY(ret<0))return ret;
- }
- else{
- /*Otherwise, just use this socket directly.*/
- op_sock_set_tcp_nodelay(_fd,1);
- SSL_set_bio(_ssl_conn,ssl_bio,ssl_bio);
- SSL_set_connect_state(_ssl_conn);
- }
- ret=op_do_ssl_step(_ssl_conn,_fd,SSL_connect);
- if(OP_UNLIKELY(ret<=0))return OP_FALSE;
- ssl_session=_stream->ssl_session;
- skip_certificate_check=_stream->skip_certificate_check;
- if(ssl_session==NULL||!skip_certificate_check){
- ret=op_do_ssl_step(_ssl_conn,_fd,SSL_do_handshake);
- if(OP_UNLIKELY(ret<=0))return OP_FALSE;
- /*OpenSSL does not do hostname verification, despite the fact that we just
- passed it the hostname above in the call to SSL_set_tlsext_host_name(),
- because they are morons.
- Do it for them.*/
- if(!skip_certificate_check&&!op_http_verify_hostname(_stream,_ssl_conn)){
- return OP_FALSE;
- }
- if(ssl_session==NULL){
- /*Save the session for later resumption.*/
- _stream->ssl_session=SSL_get1_session(_ssl_conn);
- }
- }
- _conn->ssl_conn=_ssl_conn;
- _conn->fd=_fd;
- _conn->nrequests_left=OP_PIPELINE_MAX_REQUESTS;
- return 0;
-}
-
-/*Try to start a connection to the next address in the given list of a given
- type.
- _fd: The socket to connect with.
- [inout] _addr: A pointer to the list of addresses.
- This will be advanced to the first one that matches the given
- address family (possibly the current one).
- _ai_family: The address family to connect to.
- Return: 1 If the connection was successful.
- 0 If the connection is in progress.
- OP_FALSE If the connection failed and there were no more addresses
- left to try.
- *_addr will be set to NULL in this case.*/
-static int op_sock_connect_next(op_sock _fd,
- const struct addrinfo **_addr,int _ai_family){
- const struct addrinfo *addr;
- int err;
- addr=*_addr;
- for(;;){
- /*Move to the next address of the requested type.*/
- for(;addr!=NULL&&addr->ai_family!=_ai_family;addr=addr->ai_next);
- *_addr=addr;
- /*No more: failure.*/
- if(addr==NULL)return OP_FALSE;
- if(connect(_fd,addr->ai_addr,addr->ai_addrlen)>=0)return 1;
- err=op_errno();
- /*Winsock will set WSAEWOULDBLOCK.*/
- if(OP_LIKELY(err==EINPROGRESS||err==EWOULDBLOCK))return 0;
- addr=addr->ai_next;
- }
-}
-
-/*The number of address families to try connecting to simultaneously.*/
-# define OP_NPROTOS (2)
-
-static int op_http_connect_impl(OpusHTTPStream *_stream,OpusHTTPConn *_conn,
- const struct addrinfo *_addrs,struct timeb *_start_time){
- const struct addrinfo *addr;
- const struct addrinfo *addrs[OP_NPROTOS];
- struct pollfd fds[OP_NPROTOS];
- int ai_family;
- int nprotos;
- int ret;
- int pi;
- int pj;
- for(pi=0;pi<OP_NPROTOS;pi++)addrs[pi]=NULL;
- /*Try connecting via both IPv4 and IPv6 simultaneously, and keep the first
- one that succeeds.
- Start by finding the first address from each family.
- We order the first connection attempts in the same order the address
- families were returned in the DNS records in accordance with RFC 6555.*/
- for(addr=_addrs,nprotos=0;addr!=NULL&&nprotos<OP_NPROTOS;addr=addr->ai_next){
- if(addr->ai_family==AF_INET6||addr->ai_family==AF_INET){
- OP_ASSERT(addr->ai_addrlen<=sizeof(struct sockaddr_in6));
- OP_ASSERT(addr->ai_addrlen<=sizeof(struct sockaddr_in));
- /*If we've seen this address family before, skip this address for now.*/
- for(pi=0;pi<nprotos;pi++)if(addrs[pi]->ai_family==addr->ai_family)break;
- if(pi<nprotos)continue;
- addrs[nprotos++]=addr;
- }
- }
- /*Pop the connection off the free list and put it on the LRU list.*/
- OP_ASSERT(_stream->free_head==_conn);
- _stream->free_head=_conn->next;
- _conn->next=_stream->lru_head;
- _stream->lru_head=_conn;
- ftime(_start_time);
- *&_conn->read_time=*_start_time;
- _conn->read_bytes=0;
- _conn->read_rate=0;
- /*Try to start a connection to each protocol.
- RFC 6555 says it is RECOMMENDED that connection attempts be paced
- 150...250 ms apart "to balance human factors against network load", but
- that "stateful algorithms" (that's us) "are expected to be more
- aggressive".
- We are definitely more aggressive: we don't pace at all.*/
- for(pi=0;pi<nprotos;pi++){
- ai_family=addrs[pi]->ai_family;
- fds[pi].fd=socket(ai_family,SOCK_STREAM,addrs[pi]->ai_protocol);
- fds[pi].events=POLLOUT;
- if(OP_LIKELY(fds[pi].fd!=OP_INVALID_SOCKET)){
- if(OP_LIKELY(op_sock_set_nonblocking(fds[pi].fd,1)>=0)){
- ret=op_sock_connect_next(fds[pi].fd,addrs+pi,ai_family);
- if(OP_UNLIKELY(ret>0)){
- /*It succeeded right away (technically possible), so stop.*/
- nprotos=pi+1;
- break;
- }
- /*Otherwise go on to the next protocol, and skip the clean-up below.*/
- else if(ret==0)continue;
- /*Tried all the addresses for this protocol.*/
- }
- /*Clean up the socket.*/
- close(fds[pi].fd);
- }
- /*Remove this protocol from the list.*/
- memmove(addrs+pi,addrs+pi+1,sizeof(*addrs)*(nprotos-pi-1));
- nprotos--;
- pi--;
- }
- /*Wait for one of the connections to finish.*/
- while(pi>=nprotos&&nprotos>0&&poll(fds,nprotos,OP_POLL_TIMEOUT_MS)>0){
- for(pi=0;pi<nprotos;pi++){
- socklen_t errlen;
- int err;
- /*Still waiting...*/
- if(!fds[pi].revents)continue;
- errlen=sizeof(err);
- /*Some platforms will return the pending error in &err and return 0.
- Others will put it in errno and return -1.*/
- ret=getsockopt(fds[pi].fd,SOL_SOCKET,SO_ERROR,&err,&errlen);
- if(ret<0)err=op_errno();
- /*Success!*/
- if(err==0||err==EISCONN)break;
- /*Move on to the next address for this protocol.*/
- ai_family=addrs[pi]->ai_family;
- addrs[pi]=addrs[pi]->ai_next;
- ret=op_sock_connect_next(fds[pi].fd,addrs+pi,ai_family);
- /*It succeeded right away, so stop.*/
- if(ret>0)break;
- /*Otherwise go on to the next protocol, and skip the clean-up below.*/
- else if(ret==0)continue;
- /*Tried all the addresses for this protocol.
- Remove it from the list.*/
- close(fds[pi].fd);
- memmove(fds+pi,fds+pi+1,sizeof(*fds)*(nprotos-pi-1));
- memmove(addrs+pi,addrs+pi+1,sizeof(*addrs)*(nprotos-pi-1));
- nprotos--;
- pi--;
- }
- }
- /*Close all the other sockets.*/
- for(pj=0;pj<nprotos;pj++)if(pi!=pj)close(fds[pj].fd);
- /*If none of them succeeded, we're done.*/
- if(pi>=nprotos)return OP_FALSE;
- /*Save this address for future connection attempts.*/
- if(addrs[pi]!=&_stream->addr_info){
- memcpy(&_stream->addr_info,addrs[pi],sizeof(_stream->addr_info));
- _stream->addr_info.ai_addr=&_stream->addr.s;
- _stream->addr_info.ai_next=NULL;
- memcpy(&_stream->addr,addrs[pi]->ai_addr,addrs[pi]->ai_addrlen);
- }
- if(OP_URL_IS_SSL(&_stream->url)){
- SSL *ssl_conn;
- /*Start the SSL connection.*/
- OP_ASSERT(_stream->ssl_ctx!=NULL);
- ssl_conn=SSL_new(_stream->ssl_ctx);
- if(OP_LIKELY(ssl_conn!=NULL)){
- ret=op_http_conn_start_tls(_stream,_conn,fds[pi].fd,ssl_conn);
- if(OP_LIKELY(ret>=0))return ret;
- SSL_free(ssl_conn);
- }
- close(fds[pi].fd);
- _conn->fd=OP_INVALID_SOCKET;
- return OP_FALSE;
- }
- /*Just a normal non-SSL connection.*/
- _conn->ssl_conn=NULL;
- _conn->fd=fds[pi].fd;
- _conn->nrequests_left=OP_PIPELINE_MAX_REQUESTS;
- /*Disable write coalescing.
- We always send whole requests at once and always parse the response headers
- before sending another one.*/
- op_sock_set_tcp_nodelay(fds[pi].fd,1);
- return 0;
-}
-
-static int op_http_connect(OpusHTTPStream *_stream,OpusHTTPConn *_conn,
- const struct addrinfo *_addrs,struct timeb *_start_time){
- struct timeb resolve_time;
- struct addrinfo *new_addrs;
- int ret;
- /*Re-resolve the host if we need to (RFC 6555 says we MUST do so
- occasionally).*/
- new_addrs=NULL;
- ftime(&resolve_time);
- if(_addrs!=&_stream->addr_info||op_time_diff_ms(&resolve_time,
- &_stream->resolve_time)>=OP_RESOLVE_CACHE_TIMEOUT_MS){
- new_addrs=op_resolve(_stream->connect_host,_stream->connect_port);
- if(OP_LIKELY(new_addrs!=NULL)){
- _addrs=new_addrs;
- *&_stream->resolve_time=*&resolve_time;
- }
- else if(OP_LIKELY(_addrs==NULL))return OP_FALSE;
- }
- ret=op_http_connect_impl(_stream,_conn,_addrs,_start_time);
- if(new_addrs!=NULL)freeaddrinfo(new_addrs);
- return ret;
-}
-
-# define OP_BASE64_LENGTH(_len) (((_len)+2)/3*4)
-
-static const char BASE64_TABLE[64]={
- 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
- 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
- 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
- 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
-};
-
-static char *op_base64_encode(char *_dst,const char *_src,int _len){
- unsigned s0;
- unsigned s1;
- unsigned s2;
- int ngroups;
- int i;
- ngroups=_len/3;
- for(i=0;i<ngroups;i++){
- s0=_src[3*i+0];
- s1=_src[3*i+1];
- s2=_src[3*i+2];
- _dst[4*i+0]=BASE64_TABLE[s0>>2];
- _dst[4*i+1]=BASE64_TABLE[(s0&3)<<4|s1>>4];
- _dst[4*i+2]=BASE64_TABLE[(s1&15)<<2|s2>>6];
- _dst[4*i+3]=BASE64_TABLE[s2&63];
- }
- _len-=3*i;
- if(_len==1){
- s0=_src[3*i+0];
- _dst[4*i+0]=BASE64_TABLE[s0>>2];
- _dst[4*i+1]=BASE64_TABLE[(s0&3)<<4];
- _dst[4*i+2]='=';
- _dst[4*i+3]='=';
- i++;
- }
- else if(_len==2){
- s0=_src[3*i+0];
- s1=_src[3*i+1];
- _dst[4*i+0]=BASE64_TABLE[s0>>2];
- _dst[4*i+1]=BASE64_TABLE[(s0&3)<<4|s1>>4];
- _dst[4*i+2]=BASE64_TABLE[(s1&15)<<2];
- _dst[4*i+3]='=';
- i++;
- }
- _dst[4*i]='\0';
- return _dst+4*i;
-}
-
-/*Construct an HTTP authorization header using RFC 2617's Basic Authentication
- Scheme and append it to the given string buffer.*/
-static int op_sb_append_basic_auth_header(OpusStringBuf *_sb,
- const char *_header,const char *_user,const char *_pass){
- int user_len;
- int pass_len;
- int user_pass_len;
- int base64_len;
- int nbuf_total;
- int ret;
- ret=op_sb_append_string(_sb,_header);
- ret|=op_sb_append(_sb,": Basic ",8);
- user_len=strlen(_user);
- pass_len=strlen(_pass);
- if(OP_UNLIKELY(pass_len>INT_MAX-user_len))return OP_EFAULT;
- if(OP_UNLIKELY(user_len+pass_len>(INT_MAX>>2)*3-3))return OP_EFAULT;
- user_pass_len=user_len+1+pass_len;
- base64_len=OP_BASE64_LENGTH(user_pass_len);
- /*Stick "user:pass" at the end of the buffer so we can Base64 encode it
- in-place.*/
- nbuf_total=_sb->nbuf;
- if(OP_UNLIKELY(base64_len>INT_MAX-nbuf_total))return OP_EFAULT;
- nbuf_total+=base64_len;
- ret|=op_sb_ensure_capacity(_sb,nbuf_total);
- if(OP_UNLIKELY(ret<0))return ret;
- _sb->nbuf=nbuf_total-user_pass_len;
- OP_ALWAYS_TRUE(!op_sb_append(_sb,_user,user_len));
- OP_ALWAYS_TRUE(!op_sb_append(_sb,":",1));
- OP_ALWAYS_TRUE(!op_sb_append(_sb,_pass,pass_len));
- op_base64_encode(_sb->buf+nbuf_total-base64_len,
- _sb->buf+nbuf_total-user_pass_len,user_pass_len);
- return op_sb_append(_sb,"\r\n",2);
-}
-
-static int op_http_allow_pipelining(const char *_server){
- /*Servers known to do bad things with pipelined requests.
- This list is taken from Gecko's nsHttpConnection::SupportsPipelining() (in
- netwerk/protocol/http/nsHttpConnection.cpp).*/
- static const char *BAD_SERVERS[]={
- "EFAServer/",
- "Microsoft-IIS/4.",
- "Microsoft-IIS/5.",
- "Netscape-Enterprise/3.",
- "Netscape-Enterprise/4.",
- "Netscape-Enterprise/5.",
- "Netscape-Enterprise/6.",
- "WebLogic 3.",
- "WebLogic 4.",
- "WebLogic 5.",
- "WebLogic 6.",
- "Winstone Servlet Engine v0."
- };
-# define NBAD_SERVERS ((int)(sizeof(BAD_SERVERS)/sizeof(*BAD_SERVERS)))
- if(*_server>='E'&&*_server<='W'){
- int si;
- for(si=0;si<NBAD_SERVERS;si++){
- if(strncmp(_server,BAD_SERVERS[si],strlen(BAD_SERVERS[si]))==0){
- return 0;
- }
- }
- }
- return 1;
-# undef NBAD_SERVERS
-}
-
-static int op_http_stream_open(OpusHTTPStream *_stream,const char *_url,
- int _skip_certificate_check,const char *_proxy_host,unsigned _proxy_port,
- const char *_proxy_user,const char *_proxy_pass,OpusServerInfo *_info){
- struct addrinfo *addrs;
- int nredirs;
- int ret;
-#if defined(_WIN32)
- op_init_winsock();
-#endif
- ret=op_parse_url(&_stream->url,_url);
- if(OP_UNLIKELY(ret<0))return ret;
- if(_proxy_host!=NULL){
- if(OP_UNLIKELY(_proxy_port>65535U))return OP_EINVAL;
- _stream->connect_host=op_string_dup(_proxy_host);
- _stream->connect_port=_proxy_port;
- }
- else{
- _stream->connect_host=_stream->url.host;
- _stream->connect_port=_stream->url.port;
- }
- addrs=NULL;
- for(nredirs=0;nredirs<OP_REDIRECT_LIMIT;nredirs++){
- OpusParsedURL next_url;
- struct timeb start_time;
- struct timeb end_time;
- char *next;
- char *status_code;
- int minor_version_pos;
- int v1_1_compat;
- /*Initialize the SSL library if necessary.*/
- if(OP_URL_IS_SSL(&_stream->url)&&_stream->ssl_ctx==NULL){
- SSL_CTX *ssl_ctx;
-# if OPENSSL_VERSION_NUMBER<0x10100000L
-# if !defined(OPENSSL_NO_LOCKING)
- /*The documentation says SSL_library_init() is not reentrant.
- We don't want to add our own depenencies on a threading library, and it
- appears that it's safe to call OpenSSL's locking functions before the
- library is initialized, so that's what we'll do (really OpenSSL should
- do this for us).
- This doesn't guarantee that _other_ threads in the application aren't
- calling SSL_library_init() at the same time, but there's not much we
- can do about that.*/
- CRYPTO_w_lock(CRYPTO_LOCK_SSL);
-# endif
- SSL_library_init();
- /*Needed to get SHA2 algorithms with old OpenSSL versions.*/
- OpenSSL_add_ssl_algorithms();
-# if !defined(OPENSSL_NO_LOCKING)
- CRYPTO_w_unlock(CRYPTO_LOCK_SSL);
-# endif
-# else
- /*Finally, OpenSSL does this for us, but as penance, it can now fail.*/
- if(!OPENSSL_init_ssl(0,NULL))return OP_EFAULT;
-# endif
- ssl_ctx=SSL_CTX_new(SSLv23_client_method());
- if(ssl_ctx==NULL)return OP_EFAULT;
- if(!_skip_certificate_check){
- /*We don't do anything if this fails, since it just means we won't load
- any certificates (and thus all checks will fail).
- However, as that is probably the result of a system
- mis-configuration, assert here to make it easier to identify.*/
- OP_ALWAYS_TRUE(SSL_CTX_set_default_verify_paths(ssl_ctx));
- SSL_CTX_set_verify(ssl_ctx,SSL_VERIFY_PEER,NULL);
- }
- _stream->ssl_ctx=ssl_ctx;
- _stream->skip_certificate_check=_skip_certificate_check;
- if(_proxy_host!=NULL){
- /*We need to establish a CONNECT tunnel to handle https proxying.
- Build the request we'll send to do so.*/
- _stream->proxy_connect.nbuf=0;
- ret=op_sb_append(&_stream->proxy_connect,"CONNECT ",8);
- ret|=op_sb_append_string(&_stream->proxy_connect,_stream->url.host);
- ret|=op_sb_append_port(&_stream->proxy_connect,_stream->url.port);
- /*CONNECT requires at least HTTP 1.1.*/
- ret|=op_sb_append(&_stream->proxy_connect," HTTP/1.1\r\n",11);
- ret|=op_sb_append(&_stream->proxy_connect,"Host: ",6);
- ret|=op_sb_append_string(&_stream->proxy_connect,_stream->url.host);
- /*The example in RFC 2817 Section 5.2 specifies an explicit port even
- when connecting to the default port.
- Given that the proxy doesn't know whether we're trying to connect to
- an http or an https URL except by the port number, this seems like a
- good idea.*/
- ret|=op_sb_append_port(&_stream->proxy_connect,_stream->url.port);
- ret|=op_sb_append(&_stream->proxy_connect,"\r\n",2);
- ret|=op_sb_append(&_stream->proxy_connect,"User-Agent: .\r\n",15);
- if(_proxy_user!=NULL&&_proxy_pass!=NULL){
- ret|=op_sb_append_basic_auth_header(&_stream->proxy_connect,
- "Proxy-Authorization",_proxy_user,_proxy_pass);
- }
- /*For backwards compatibility.*/
- ret|=op_sb_append(&_stream->proxy_connect,
- "Proxy-Connection: keep-alive\r\n",30);
- ret|=op_sb_append(&_stream->proxy_connect,"\r\n",2);
- if(OP_UNLIKELY(ret<0))return ret;
- }
- }
- /*Actually make the connection.*/
- ret=op_http_connect(_stream,_stream->conns+0,addrs,&start_time);
- if(OP_UNLIKELY(ret<0))return ret;
- /*Build the request to send.*/
- _stream->request.nbuf=0;
- ret=op_sb_append(&_stream->request,"GET ",4);
- ret|=op_sb_append_string(&_stream->request,
- _proxy_host!=NULL?_url:_stream->url.path);
- /*Send HTTP/1.0 by default for maximum compatibility (so we don't have to
- re-try if HTTP/1.1 fails, though it shouldn't, even for a 1.0 server).
- This means we aren't conditionally compliant with RFC 2145, because we
- violate the requirement that "An HTTP client SHOULD send a request
- version equal to the highest version for which the client is at least
- conditionally compliant...".
- According to RFC 2145, that means we can't claim any compliance with any
- IETF HTTP specification.*/
- ret|=op_sb_append(&_stream->request," HTTP/1.0\r\n",11);
- /*Remember where this is so we can upgrade to HTTP/1.1 if the server
- supports it.*/
- minor_version_pos=_stream->request.nbuf-3;
- ret|=op_sb_append(&_stream->request,"Host: ",6);
- ret|=op_sb_append_string(&_stream->request,_stream->url.host);
- if(!OP_URL_IS_DEFAULT_PORT(&_stream->url)){
- ret|=op_sb_append_port(&_stream->request,_stream->url.port);
- }
- ret|=op_sb_append(&_stream->request,"\r\n",2);
- /*User-Agents have been a bad idea, so send as little as possible.
- RFC 2616 requires at least one token in the User-Agent, which must have
- at least one character.*/
- ret|=op_sb_append(&_stream->request,"User-Agent: .\r\n",15);
- if(_proxy_host!=NULL&&!OP_URL_IS_SSL(&_stream->url)
- &&_proxy_user!=NULL&&_proxy_pass!=NULL){
- ret|=op_sb_append_basic_auth_header(&_stream->request,
- "Proxy-Authorization",_proxy_user,_proxy_pass);
- }
- if(_stream->url.user!=NULL&&_stream->url.pass!=NULL){
- ret|=op_sb_append_basic_auth_header(&_stream->request,
- "Authorization",_stream->url.user,_stream->url.pass);
- }
- /*Always send a Referer [sic] header.
- It's common to refuse to serve a resource unless one is present.
- We just use the relative "/" URI to suggest we came from the same domain,
- as this is the most common check.
- This might violate RFC 2616's mandate that the field "MUST NOT be sent if
- the Request-URI was obtained from a source that does not have its own
- URI, such as input from the user keyboard," but we don't really have any
- way to know.*/
- /*TODO: Should we update this on redirects?*/
- ret|=op_sb_append(&_stream->request,"Referer: /\r\n",12);
- /*Always send a Range request header to find out if we're seekable.
- This requires an HTTP/1.1 server to succeed, but we'll still get what we
- want with an HTTP/1.0 server that ignores this request header.*/
- ret|=op_sb_append(&_stream->request,"Range: bytes=0-\r\n",17);
- /*Remember where this is so we can append offsets to it later.*/
- _stream->request_tail=_stream->request.nbuf-4;
- ret|=op_sb_append(&_stream->request,"\r\n",2);
- if(OP_UNLIKELY(ret<0))return ret;
- ret=op_http_conn_write_fully(_stream->conns+0,
- _stream->request.buf,_stream->request.nbuf);
- if(OP_UNLIKELY(ret<0))return ret;
- ret=op_http_conn_read_response(_stream->conns+0,&_stream->response);
- if(OP_UNLIKELY(ret<0))return ret;
- ftime(&end_time);
- next=op_http_parse_status_line(&v1_1_compat,&status_code,
- _stream->response.buf);
- if(OP_UNLIKELY(next==NULL))return OP_FALSE;
- if(status_code[0]=='2'){
- opus_int64 content_length;
- opus_int64 range_length;
- int pipeline_supported;
- int pipeline_disabled;
- /*We only understand 20x codes.*/
- if(status_code[1]!='0')return OP_FALSE;
- content_length=-1;
- range_length=-1;
- /*Pipelining must be explicitly enabled.*/
- pipeline_supported=0;
- pipeline_disabled=0;
- for(;;){
- char *header;
- char *cdr;
- ret=op_http_get_next_header(&header,&cdr,&next);
- if(OP_UNLIKELY(ret<0))return ret;
- if(header==NULL)break;
- if(strcmp(header,"content-length")==0){
- /*Two Content-Length headers?*/
- if(OP_UNLIKELY(content_length>=0))return OP_FALSE;
- content_length=op_http_parse_content_length(cdr);
- if(OP_UNLIKELY(content_length<0))return (int)content_length;
- /*Make sure the Content-Length and Content-Range headers match.*/
- if(range_length>=0&&OP_UNLIKELY(content_length!=range_length)){
- return OP_FALSE;
- }
- }
- else if(strcmp(header,"content-range")==0){
- opus_int64 range_first;
- opus_int64 range_last;
- /*Two Content-Range headers?*/
- if(OP_UNLIKELY(range_length>=0))return OP_FALSE;
- ret=op_http_parse_content_range(&range_first,&range_last,
- &range_length,cdr);
- if(OP_UNLIKELY(ret<0))return ret;
- /*"A response with satus code 206 (Partial Content) MUST NOT
- include a Content-Range field with a byte-range-resp-spec of
- '*'."*/
- if(status_code[2]=='6'
- &&(OP_UNLIKELY(range_first<0)||OP_UNLIKELY(range_last<0))){
- return OP_FALSE;
- }
- /*We asked for the entire resource.*/
- if(range_length>=0){
- /*Quit if we didn't get it.*/
- if(range_last>=0&&OP_UNLIKELY(range_last!=range_length-1)){
- return OP_FALSE;
- }
- }
- /*If there was no length, use the end of the range.*/
- else if(range_last>=0)range_length=range_last+1;
- /*Make sure the Content-Length and Content-Range headers match.*/
- if(content_length>=0&&OP_UNLIKELY(content_length!=range_length)){
- return OP_FALSE;
- }
- }
- else if(strcmp(header,"connection")==0){
- /*According to RFC 2616, if an HTTP/1.1 application does not support
- pipelining, it "MUST include the 'close' connection option in
- every message."
- Therefore, if we receive one in the initial response, disable
- pipelining entirely.
- The server still might support it (e.g., we might just have hit the
- request limit for a temporary child process), but if it doesn't
- and we assume it does, every time we cross a chunk boundary we'll
- error out and reconnect, adding lots of latency.*/
- ret=op_http_parse_connection(cdr);
- if(OP_UNLIKELY(ret<0))return ret;
- pipeline_disabled|=ret;
- }
- else if(strcmp(header,"server")==0){
- /*If we got a Server response header, and it wasn't from a known-bad
- server, enable pipelining, as long as it's at least HTTP/1.1.
- According to RFC 2145, the server is supposed to respond with the
- highest minor version number it supports unless it is known or
- suspected that we incorrectly implement the HTTP specification.
- So it should send back at least HTTP/1.1, despite our HTTP/1.0
- request.*/
- pipeline_supported=v1_1_compat;
- if(v1_1_compat)pipeline_disabled|=!op_http_allow_pipelining(cdr);
- if(_info!=NULL&&_info->server==NULL)_info->server=op_string_dup(cdr);
- }
- /*Collect station information headers if the caller requested it.
- If there's more than one copy of a header, the first one wins.*/
- else if(_info!=NULL){
- if(strcmp(header,"content-type")==0){
- if(_info->content_type==NULL){
- _info->content_type=op_string_dup(cdr);
- }
- }
- else if(header[0]=='i'&&header[1]=='c'
- &&(header[2]=='e'||header[2]=='y')&&header[3]=='-'){
- if(strcmp(header+4,"name")==0){
- if(_info->name==NULL)_info->name=op_string_dup(cdr);
- }
- else if(strcmp(header+4,"description")==0){
- if(_info->description==NULL)_info->description=op_string_dup(cdr);
- }
- else if(strcmp(header+4,"genre")==0){
- if(_info->genre==NULL)_info->genre=op_string_dup(cdr);
- }
- else if(strcmp(header+4,"url")==0){
- if(_info->url==NULL)_info->url=op_string_dup(cdr);
- }
- else if(strcmp(header,"icy-br")==0
- ||strcmp(header,"ice-bitrate")==0){
- if(_info->bitrate_kbps<0){
- opus_int64 bitrate_kbps;
- /*Just re-using this function to parse a random unsigned
- integer field.*/
- bitrate_kbps=op_http_parse_content_length(cdr);
- if(bitrate_kbps>=0&&bitrate_kbps<=OP_INT32_MAX){
- _info->bitrate_kbps=(opus_int32)bitrate_kbps;
- }
- }
- }
- else if(strcmp(header,"icy-pub")==0
- ||strcmp(header,"ice-public")==0){
- if(_info->is_public<0&&(cdr[0]=='0'||cdr[0]=='1')&&cdr[1]=='\0'){
- _info->is_public=cdr[0]-'0';
- }
- }
- }
- }
- }
- switch(status_code[2]){
- /*200 OK*/
- case '0':break;
- /*203 Non-Authoritative Information*/
- case '3':break;
- /*204 No Content*/
- case '4':{
- if(content_length>=0&&OP_UNLIKELY(content_length!=0)){
- return OP_FALSE;
- }
- }break;
- /*206 Partial Content*/
- case '6':{
- /*No Content-Range header.*/
- if(OP_UNLIKELY(range_length<0))return OP_FALSE;
- content_length=range_length;
- /*The server supports range requests for this resource.
- We can seek.*/
- _stream->seekable=1;
- }break;
- /*201 Created: the response "SHOULD include an entity containing a list
- of resource characteristics and location(s)," but not an Opus file.
- 202 Accepted: the response "SHOULD include an indication of request's
- current status and either a pointer to a status monitor or some
- estimate of when the user can expect the request to be fulfilled,"
- but not an Opus file.
- 205 Reset Content: this "MUST NOT include an entity," meaning no Opus
- file.
- 207...209 are not yet defined, so we don't know how to handle them.*/
- default:return OP_FALSE;
- }
- _stream->content_length=content_length;
- _stream->pipeline=pipeline_supported&&!pipeline_disabled;
- /*Pipelining requires HTTP/1.1 persistent connections.*/
- if(_stream->pipeline)_stream->request.buf[minor_version_pos]='1';
- _stream->conns[0].pos=0;
- _stream->conns[0].end_pos=_stream->seekable?content_length:-1;
- _stream->conns[0].chunk_size=-1;
- _stream->cur_conni=0;
- _stream->connect_rate=op_time_diff_ms(&end_time,&start_time);
- _stream->connect_rate=OP_MAX(_stream->connect_rate,1);
- if(_info!=NULL)_info->is_ssl=OP_URL_IS_SSL(&_stream->url);
- /*The URL has been successfully opened.*/
- return 0;
- }
- /*Shouldn't get 1xx; 4xx and 5xx are both failures (and we don't retry).
- Everything else is undefined.*/
- else if(status_code[0]!='3')return OP_FALSE;
- /*We have some form of redirect request.*/
- /*We only understand 30x codes.*/
- if(status_code[1]!='0')return OP_FALSE;
- switch(status_code[2]){
- /*300 Multiple Choices: "If the server has a preferred choice of
- representation, it SHOULD include the specific URI for that
- representation in the Location field," otherwise we'll fail.*/
- case '0':
- /*301 Moved Permanently*/
- case '1':
- /*302 Found*/
- case '2':
- /*307 Temporary Redirect*/
- case '7':
- /*308 Permanent Redirect (defined by draft-reschke-http-status-308-07).*/
- case '8':break;
- /*305 Use Proxy: "The Location field gives the URI of the proxy."
- TODO: This shouldn't actually be that hard to do.*/
- case '5':return OP_EIMPL;
- /*303 See Other: "The new URI is not a substitute reference for the
- originally requested resource."
- 304 Not Modified: "The 304 response MUST NOT contain a message-body."
- 306 (Unused)
- 309 is not yet defined, so we don't know how to handle it.*/
- default:return OP_FALSE;
- }
- _url=NULL;
- for(;;){
- char *header;
- char *cdr;
- ret=op_http_get_next_header(&header,&cdr,&next);
- if(OP_UNLIKELY(ret<0))return ret;
- if(header==NULL)break;
- if(strcmp(header,"location")==0&&OP_LIKELY(_url==NULL))_url=cdr;
- }
- if(OP_UNLIKELY(_url==NULL))return OP_FALSE;
- ret=op_parse_url(&next_url,_url);
- if(OP_UNLIKELY(ret<0))return ret;
- if(_proxy_host==NULL||_stream->ssl_session!=NULL){
- if(strcmp(_stream->url.host,next_url.host)==0
- &&_stream->url.port==next_url.port){
- /*Try to skip re-resolve when connecting to the same host.*/
- addrs=&_stream->addr_info;
- }
- else{
- if(_stream->ssl_session!=NULL){
- /*Forget any cached SSL session from the last host.*/
- SSL_SESSION_free(_stream->ssl_session);
- _stream->ssl_session=NULL;
- }
- }
- }
- if(_proxy_host==NULL){
- OP_ASSERT(_stream->connect_host==_stream->url.host);
- _stream->connect_host=next_url.host;
- _stream->connect_port=next_url.port;
- }
- /*Always try to skip re-resolve for proxy connections.*/
- else addrs=&_stream->addr_info;
- op_parsed_url_clear(&_stream->url);
- *&_stream->url=*&next_url;
- /*TODO: On servers/proxies that support pipelining, we might be able to
- re-use this connection.*/
- op_http_conn_close(_stream,_stream->conns+0,&_stream->lru_head,1);
- }
- /*Redirection limit reached.*/
- return OP_FALSE;
-}
-
-static int op_http_conn_send_request(OpusHTTPStream *_stream,
- OpusHTTPConn *_conn,opus_int64 _pos,opus_int32 _chunk_size,
- int _try_not_to_block){
- opus_int64 next_end;
- int ret;
- /*We shouldn't have another request outstanding.*/
- OP_ASSERT(_conn->next_pos<0);
- /*Build the request to send.*/
- OP_ASSERT(_stream->request.nbuf>=_stream->request_tail);
- _stream->request.nbuf=_stream->request_tail;
- ret=op_sb_append_nonnegative_int64(&_stream->request,_pos);
- ret|=op_sb_append(&_stream->request,"-",1);
- if(_chunk_size>0&&OP_ADV_OFFSET(_pos,2*_chunk_size)<_stream->content_length){
- /*We shouldn't be pipelining requests with non-HTTP/1.1 servers.*/
- OP_ASSERT(_stream->pipeline);
- next_end=_pos+_chunk_size;
- ret|=op_sb_append_nonnegative_int64(&_stream->request,next_end-1);
- /*Use a larger chunk size for our next request.*/
- _chunk_size<<=1;
- /*But after a while, just request the rest of the resource.*/
- if(_chunk_size>OP_PIPELINE_CHUNK_SIZE_MAX)_chunk_size=-1;
- }
- else{
- /*Either this was a non-pipelined request or we were close enough to the
- end to just ask for the rest.*/
- next_end=-1;
- _chunk_size=-1;
- }
- ret|=op_sb_append(&_stream->request,"\r\n\r\n",4);
- if(OP_UNLIKELY(ret<0))return ret;
- /*If we don't want to block, check to see if there's enough space in the send
- queue.
- There's still a chance we might block, even if there is enough space, but
- it's a much slimmer one.
- Blocking at all is pretty unlikely, as we won't have any requests queued
- when _try_not_to_block is set, so if FIONSPACE isn't available (e.g., on
- Linux), just skip the test.*/
- if(_try_not_to_block){
-# if defined(FIONSPACE)
- int available;
- ret=ioctl(_conn->fd,FIONSPACE,&available);
- if(ret<0||available<_stream->request.nbuf)return 1;
-# endif
- }
- ret=op_http_conn_write_fully(_conn,
- _stream->request.buf,_stream->request.nbuf);
- if(OP_UNLIKELY(ret<0))return ret;
- _conn->next_pos=_pos;
- _conn->next_end=next_end;
- /*Save the chunk size to use for the next request.*/
- _conn->chunk_size=_chunk_size;
- _conn->nrequests_left--;
- return ret;
-}
-
-/*Handles the response to all requests after the first one.
- Return: 1 if the connection was closed or timed out, 0 on success, or a
- negative value on any other error.*/
-static int op_http_conn_handle_response(OpusHTTPStream *_stream,
- OpusHTTPConn *_conn){
- char *next;
- char *status_code;
- opus_int64 range_length;
- opus_int64 next_pos;
- opus_int64 next_end;
- int ret;
- ret=op_http_conn_read_response(_conn,&_stream->response);
- /*If the server just closed the connection on us, we may have just hit a
- connection re-use limit, so we might want to retry.*/
- if(OP_UNLIKELY(ret<0))return ret==OP_EREAD?1:ret;
- next=op_http_parse_status_line(NULL,&status_code,_stream->response.buf);
- if(OP_UNLIKELY(next==NULL))return OP_FALSE;
- /*We _need_ a 206 Partial Content response.
- Nothing else will do.*/
- if(strncmp(status_code,"206",3)!=0){
- /*But on a 408 Request Timeout, we might want to re-try.*/
- return strncmp(status_code,"408",3)==0?1:OP_FALSE;
- }
- next_pos=_conn->next_pos;
- next_end=_conn->next_end;
- range_length=-1;
- for(;;){
- char *header;
- char *cdr;
- ret=op_http_get_next_header(&header,&cdr,&next);
- if(OP_UNLIKELY(ret<0))return ret;
- if(header==NULL)break;
- if(strcmp(header,"content-range")==0){
- opus_int64 range_first;
- opus_int64 range_last;
- /*Two Content-Range headers?*/
- if(OP_UNLIKELY(range_length>=0))return OP_FALSE;
- ret=op_http_parse_content_range(&range_first,&range_last,
- &range_length,cdr);
- if(OP_UNLIKELY(ret<0))return ret;
- /*"A response with satus code 206 (Partial Content) MUST NOT
- include a Content-Range field with a byte-range-resp-spec of
- '*'."*/
- if(OP_UNLIKELY(range_first<0)||OP_UNLIKELY(range_last<0))return OP_FALSE;
- /*We also don't want range_last to overflow.*/
- if(OP_UNLIKELY(range_last>=OP_INT64_MAX))return OP_FALSE;
- range_last++;
- /*Quit if we didn't get the offset we asked for.*/
- if(range_first!=next_pos)return OP_FALSE;
- if(next_end<0){
- /*We asked for the rest of the resource.*/
- if(range_length>=0){
- /*Quit if we didn't get it.*/
- if(OP_UNLIKELY(range_last!=range_length))return OP_FALSE;
- }
- /*If there was no length, use the end of the range.*/
- else range_length=range_last;
- next_end=range_last;
- }
- else{
- if(range_last!=next_end)return OP_FALSE;
- /*If there was no length, use the larger of the content length or the
- end of this chunk.*/
- if(range_length<0){
- range_length=OP_MAX(range_last,_stream->content_length);
- }
- }
- }
- else if(strcmp(header,"content-length")==0){
- opus_int64 content_length;
- /*Validate the Content-Length header, if present, against the request we
- made.*/
- content_length=op_http_parse_content_length(cdr);
- if(OP_UNLIKELY(content_length<0))return (int)content_length;
- if(next_end<0){
- /*If we haven't seen the Content-Range header yet and we asked for the
- rest of the resource, set next_end, so we can make sure they match
- when we do find the Content-Range header.*/
- if(OP_UNLIKELY(next_pos>OP_INT64_MAX-content_length))return OP_FALSE;
- next_end=next_pos+content_length;
- }
- /*Otherwise, make sure they match now.*/
- else if(OP_UNLIKELY(next_end-next_pos!=content_length))return OP_FALSE;
- }
- else if(strcmp(header,"connection")==0){
- ret=op_http_parse_connection(cdr);
- if(OP_UNLIKELY(ret<0))return ret;
- /*If the server told us it was going to close the connection, don't make
- any more requests.*/
- if(OP_UNLIKELY(ret>0))_conn->nrequests_left=0;
- }
- }
- /*No Content-Range header.*/
- if(OP_UNLIKELY(range_length<0))return OP_FALSE;
- /*Update the content_length if necessary.*/
- _stream->content_length=range_length;
- _conn->pos=next_pos;
- _conn->end_pos=next_end;
- _conn->next_pos=-1;
- return 0;
-}
-
-/*Open a new connection that will start reading at byte offset _pos.
- _pos: The byte offset to start reading from.
- _chunk_size: The number of bytes to ask for in the initial request, or -1 to
- request the rest of the resource.
- This may be more bytes than remain, in which case it will be
- converted into a request for the rest.*/
-static int op_http_conn_open_pos(OpusHTTPStream *_stream,
- OpusHTTPConn *_conn,opus_int64 _pos,opus_int32 _chunk_size){
- struct timeb start_time;
- struct timeb end_time;
- opus_int32 connect_rate;
- opus_int32 connect_time;
- int ret;
- ret=op_http_connect(_stream,_conn,&_stream->addr_info,&start_time);
- if(OP_UNLIKELY(ret<0))return ret;
- ret=op_http_conn_send_request(_stream,_conn,_pos,_chunk_size,0);
- if(OP_UNLIKELY(ret<0))return ret;
- ret=op_http_conn_handle_response(_stream,_conn);
- if(OP_UNLIKELY(ret!=0))return OP_FALSE;
- ftime(&end_time);
- _stream->cur_conni=_conn-_stream->conns;
- OP_ASSERT(_stream->cur_conni>=0&&_stream->cur_conni<OP_NCONNS_MAX);
- /*The connection has been successfully opened.
- Update the connection time estimate.*/
- connect_time=op_time_diff_ms(&end_time,&start_time);
- connect_rate=_stream->connect_rate;
- connect_rate+=OP_MAX(connect_time,1)-connect_rate+8>>4;
- _stream->connect_rate=connect_rate;
- return 0;
-}
-
-/*Read data from the current response body.
- If we're pipelining and we get close to the end of this response, queue
- another request.
- If we've reached the end of this response body, parse the next response and
- keep going.
- [out] _buf: Returns the data read.
- _buf_size: The size of the buffer.
- Return: A positive number of bytes read on success.
- 0: The connection was closed.
- OP_EREAD: There was a fatal read error.*/
-static int op_http_conn_read_body(OpusHTTPStream *_stream,
- OpusHTTPConn *_conn,unsigned char *_buf,int _buf_size){
- opus_int64 pos;
- opus_int64 end_pos;
- opus_int64 next_pos;
- opus_int64 content_length;
- int nread;
- int pipeline;
- int ret;
- /*Currently this function can only be called on the LRU head.
- Otherwise, we'd need a _pnext pointer if we needed to close the connection,
- and re-opening it would re-organize the lists.*/
- OP_ASSERT(_stream->lru_head==_conn);
- /*We should have filtered out empty reads by this point.*/
- OP_ASSERT(_buf_size>0);
- pos=_conn->pos;
- end_pos=_conn->end_pos;
- next_pos=_conn->next_pos;
- pipeline=_stream->pipeline;
- content_length=_stream->content_length;
- if(end_pos>=0){
- /*Have we reached the end of the current response body?*/
- if(pos>=end_pos){
- OP_ASSERT(content_length>=0);
- /*If this was the end of the stream, we're done.
- Also return early if a non-blocking read was requested (regardless of
- whether we might be able to parse the next response without
- blocking).*/
- if(content_length<=end_pos)return 0;
- /*Otherwise, start on the next response.*/
- if(next_pos<0){
- /*We haven't issued another request yet.*/
- if(!pipeline||_conn->nrequests_left<=0){
- /*There are two ways to get here: either the server told us it was
- going to close the connection after the last request, or we
- thought we were reading the whole resource, but it grew while we
- were reading it.
- The only way the latter could have happened is if content_length
- changed while seeking.
- Open a new request to read the rest.*/
- OP_ASSERT(_stream->seekable);
- /*Try to open a new connection to read another chunk.*/
- op_http_conn_close(_stream,_conn,&_stream->lru_head,1);
- /*If we're not pipelining, we should be requesting the rest.*/
- OP_ASSERT(pipeline||_conn->chunk_size==-1);
- ret=op_http_conn_open_pos(_stream,_conn,end_pos,_conn->chunk_size);
- if(OP_UNLIKELY(ret<0))return OP_EREAD;
- }
- else{
- /*Issue the request now (better late than never).*/
- ret=op_http_conn_send_request(_stream,_conn,pos,_conn->chunk_size,0);
- if(OP_UNLIKELY(ret<0))return OP_EREAD;
- next_pos=_conn->next_pos;
- OP_ASSERT(next_pos>=0);
- }
- }
- if(next_pos>=0){
- /*We shouldn't be trying to read past the current request body if we're
- seeking somewhere else.*/
- OP_ASSERT(next_pos==end_pos);
- ret=op_http_conn_handle_response(_stream,_conn);
- if(OP_UNLIKELY(ret<0))return OP_EREAD;
- if(OP_UNLIKELY(ret>0)&&pipeline){
- opus_int64 next_end;
- next_end=_conn->next_end;
- /*Our request timed out or the server closed the connection.
- Try re-connecting.*/
- op_http_conn_close(_stream,_conn,&_stream->lru_head,1);
- /*Unless there's a bug, we should be able to convert
- (next_pos,next_end) into valid (_pos,_chunk_size) parameters.*/
- OP_ASSERT(next_end<0
- ||next_end-next_pos>=0&&next_end-next_pos<=OP_INT32_MAX);
- ret=op_http_conn_open_pos(_stream,_conn,next_pos,
- next_end<0?-1:(opus_int32)(next_end-next_pos));
- if(OP_UNLIKELY(ret<0))return OP_EREAD;
- }
- else if(OP_UNLIKELY(ret!=0))return OP_EREAD;
- }
- pos=_conn->pos;
- end_pos=_conn->end_pos;
- content_length=_stream->content_length;
- }
- OP_ASSERT(end_pos>pos);
- _buf_size=OP_MIN(_buf_size,end_pos-pos);
- }
- nread=op_http_conn_read(_conn,(char *)_buf,_buf_size,1);
- if(OP_UNLIKELY(nread<0))return nread;
- pos+=nread;
- _conn->pos=pos;
- OP_ASSERT(end_pos<0||content_length>=0);
- /*TODO: If nrequests_left<=0, we can't make a new request, and there will be
- a big pause after we hit the end of the chunk while we open a new
- connection.
- It would be nice to be able to start that process now, but we have no way
- to do it in the background without blocking (even if we could start it, we
- have no guarantee the application will return control to us in a
- sufficiently timely manner to allow us to complete it, and this is
- uncommon enough that it's not worth using threads just for this).*/
- if(end_pos>=0&&end_pos<content_length&&next_pos<0
- &&pipeline&&OP_LIKELY(_conn->nrequests_left>0)){
- opus_int64 request_thresh;
- opus_int32 chunk_size;
- /*Are we getting close to the end of the current response body?
- If so, we should request more data.*/
- request_thresh=_stream->connect_rate*_conn->read_rate>>12;
- /*But don't commit ourselves too quickly.*/
- chunk_size=_conn->chunk_size;
- if(chunk_size>=0)request_thresh=OP_MIN(chunk_size>>2,request_thresh);
- if(end_pos-pos<request_thresh){
- ret=op_http_conn_send_request(_stream,_conn,end_pos,_conn->chunk_size,1);
- if(OP_UNLIKELY(ret<0))return OP_EREAD;
- }
- }
- return nread;
-}
-
-static int op_http_stream_read(void *_stream,
- unsigned char *_ptr,int _buf_size){
- OpusHTTPStream *stream;
- ptrdiff_t nread;
- opus_int64 size;
- opus_int64 pos;
- int ci;
- stream=(OpusHTTPStream *)_stream;
- /*Check for an empty read.*/
- if(_buf_size<=0)return 0;
- ci=stream->cur_conni;
- /*No current connection => EOF.*/
- if(ci<0)return 0;
- pos=stream->conns[ci].pos;
- size=stream->content_length;
- /*Check for EOF.*/
- if(size>=0){
- if(pos>=size)return 0;
- /*Check for a short read.*/
- if(_buf_size>size-pos)_buf_size=(int)(size-pos);
- }
- nread=op_http_conn_read_body(stream,stream->conns+ci,_ptr,_buf_size);
- if(OP_UNLIKELY(nread<=0)){
- /*We hit an error or EOF.
- Either way, we're done with this connection.*/
- op_http_conn_close(stream,stream->conns+ci,&stream->lru_head,1);
- stream->cur_conni=-1;
- stream->pos=pos;
- }
- return nread;
-}
-
-/*Discard data until we reach the _target position.
- This destroys the contents of _stream->response.buf, as we need somewhere to
- read this data, and that is a convenient place.
- _just_read_ahead: Whether or not this is a plain fast-forward.
- If 0, we need to issue a new request for a chunk at _target
- and discard all the data from our current request(s).
- Otherwise, we should be able to reach _target without
- issuing any new requests.
- _target: The stream position to which to read ahead.*/
-static int op_http_conn_read_ahead(OpusHTTPStream *_stream,
- OpusHTTPConn *_conn,int _just_read_ahead,opus_int64 _target){
- opus_int64 pos;
- opus_int64 end_pos;
- opus_int64 next_pos;
- opus_int64 next_end;
- ptrdiff_t nread;
- int ret;
- pos=_conn->pos;
- end_pos=_conn->end_pos;
- next_pos=_conn->next_pos;
- next_end=_conn->next_end;
- if(!_just_read_ahead){
- /*We need to issue a new pipelined request.
- This is the only case where we allow more than one outstanding request
- at a time, so we need to reset next_pos (we'll restore it below if we
- did have an outstanding request).*/
- OP_ASSERT(_stream->pipeline);
- _conn->next_pos=-1;
- ret=op_http_conn_send_request(_stream,_conn,_target,
- OP_PIPELINE_CHUNK_SIZE,0);
- if(OP_UNLIKELY(ret<0))return ret;
- }
- /*We can reach the target position by reading forward in the current chunk.*/
- if(_just_read_ahead&&(end_pos<0||_target<end_pos))end_pos=_target;
- else if(next_pos>=0){
- opus_int64 next_next_pos;
- opus_int64 next_next_end;
- /*We already have a request outstanding.
- Finish off the current chunk.*/
- while(pos<end_pos){
- nread=op_http_conn_read(_conn,_stream->response.buf,
- (int)OP_MIN(end_pos-pos,_stream->response.cbuf),1);
- /*We failed to read ahead.*/
- if(nread<=0)return OP_FALSE;
- pos+=nread;
- }
- OP_ASSERT(pos==end_pos);
- if(_just_read_ahead){
- next_next_pos=next_next_end=-1;
- end_pos=_target;
- }
- else{
- OP_ASSERT(_conn->next_pos==_target);
- next_next_pos=_target;
- next_next_end=_conn->next_end;
- _conn->next_pos=next_pos;
- _conn->next_end=next_end;
- end_pos=next_end;
- }
- ret=op_http_conn_handle_response(_stream,_conn);
- if(OP_UNLIKELY(ret!=0))return OP_FALSE;
- _conn->next_pos=next_next_pos;
- _conn->next_end=next_next_end;
- }
- while(pos<end_pos){
- nread=op_http_conn_read(_conn,_stream->response.buf,
- (int)OP_MIN(end_pos-pos,_stream->response.cbuf),1);
- /*We failed to read ahead.*/
- if(nread<=0)return OP_FALSE;
- pos+=nread;
- }
- OP_ASSERT(pos==end_pos);
- if(!_just_read_ahead){
- ret=op_http_conn_handle_response(_stream,_conn);
- if(OP_UNLIKELY(ret!=0))return OP_FALSE;
- }
- else _conn->pos=end_pos;
- OP_ASSERT(_conn->pos==_target);
- return 0;
-}
-
-static int op_http_stream_seek(void *_stream,opus_int64 _offset,int _whence){
- struct timeb seek_time;
- OpusHTTPStream *stream;
- OpusHTTPConn *conn;
- OpusHTTPConn **pnext;
- OpusHTTPConn *close_conn;
- OpusHTTPConn **close_pnext;
- opus_int64 content_length;
- opus_int64 pos;
- int pipeline;
- int ci;
- int ret;
- stream=(OpusHTTPStream *)_stream;
- if(!stream->seekable)return -1;
- content_length=stream->content_length;
- /*If we're seekable, we should have gotten a Content-Length.*/
- OP_ASSERT(content_length>=0);
- ci=stream->cur_conni;
- pos=ci<0?content_length:stream->conns[ci].pos;
- switch(_whence){
- case SEEK_SET:{
- /*Check for overflow:*/
- if(_offset<0)return -1;
- pos=_offset;
- }break;
- case SEEK_CUR:{
- /*Check for overflow:*/
- if(_offset<-pos||_offset>OP_INT64_MAX-pos)return -1;
- pos+=_offset;
- }break;
- case SEEK_END:{
- /*Check for overflow:*/
- if(_offset>content_length||_offset<content_length-OP_INT64_MAX)return -1;
- pos=content_length-_offset;
- }break;
- default:return -1;
- }
- /*Mark when we deactivated the active connection.*/
- if(ci>=0){
- op_http_conn_read_rate_update(stream->conns+ci);
- *&seek_time=*&stream->conns[ci].read_time;
- }
- else ftime(&seek_time);
- /*If we seeked past the end of the stream, just disable the active
- connection.*/
- if(pos>=content_length){
- stream->cur_conni=-1;
- stream->pos=pos;
- return 0;
- }
- /*First try to find a connection we can use without waiting.*/
- pnext=&stream->lru_head;
- conn=stream->lru_head;
- while(conn!=NULL){
- opus_int64 conn_pos;
- opus_int64 end_pos;
- int available;
- /*If this connection has been dormant too long or has made too many
- requests, close it.
- This is to prevent us from hitting server limits/firewall timeouts.*/
- if(op_time_diff_ms(&seek_time,&conn->read_time)>
- OP_CONNECTION_IDLE_TIMEOUT_MS
- ||conn->nrequests_left<OP_PIPELINE_MIN_REQUESTS){
- op_http_conn_close(stream,conn,pnext,1);
- conn=*pnext;
- continue;
- }
- available=op_http_conn_estimate_available(conn);
- conn_pos=conn->pos;
- end_pos=conn->end_pos;
- if(conn->next_pos>=0){
- OP_ASSERT(end_pos>=0);
- OP_ASSERT(conn->next_pos==end_pos);
- end_pos=conn->next_end;
- }
- OP_ASSERT(end_pos<0||conn_pos<=end_pos);
- /*Can we quickly read ahead without issuing a new request or waiting for
- any more data?
- If we have an oustanding request, we'll over-estimate the amount of data
- it has available (because we'll count the response headers, too), but
- that probably doesn't matter.*/
- if(conn_pos<=pos&&pos-conn_pos<=available&&(end_pos<0||pos<end_pos)){
- /*Found a suitable connection to re-use.*/
- ret=op_http_conn_read_ahead(stream,conn,1,pos);
- if(OP_UNLIKELY(ret<0)){
- /*The connection might have become stale, so close it and keep going.*/
- op_http_conn_close(stream,conn,pnext,1);
- conn=*pnext;
- continue;
- }
- /*Sucessfully resurrected this connection.*/
- *pnext=conn->next;
- conn->next=stream->lru_head;
- stream->lru_head=conn;
- stream->cur_conni=conn-stream->conns;
- return 0;
- }
- pnext=&conn->next;
- conn=conn->next;
- }
- /*Chances are that didn't work, so now try to find one we can use by reading
- ahead a reasonable amount and/or by issuing a new request.*/
- close_pnext=NULL;
- close_conn=NULL;
- pnext=&stream->lru_head;
- conn=stream->lru_head;
- pipeline=stream->pipeline;
- while(conn!=NULL){
- opus_int64 conn_pos;
- opus_int64 end_pos;
- opus_int64 read_ahead_thresh;
- int available;
- int just_read_ahead;
- /*Dividing by 2048 instead of 1000 scales this by nearly 1/2, biasing away
- from connection re-use (and roughly compensating for the lag required to
- reopen the TCP window of a connection that's been idle).
- There's no overflow checking here, because it's vanishingly unlikely, and
- all it would do is cause us to make poor decisions.*/
- read_ahead_thresh=OP_MAX(OP_READAHEAD_THRESH_MIN,
- stream->connect_rate*conn->read_rate>>11);
- available=op_http_conn_estimate_available(conn);
- conn_pos=conn->pos;
- end_pos=conn->end_pos;
- if(conn->next_pos>=0){
- OP_ASSERT(end_pos>=0);
- OP_ASSERT(conn->next_pos==end_pos);
- end_pos=conn->next_end;
- }
- OP_ASSERT(end_pos<0||conn_pos<=end_pos);
- /*Can we quickly read ahead without issuing a new request?*/
- just_read_ahead=conn_pos<=pos&&pos-conn_pos-available<=read_ahead_thresh
- &&(end_pos<0||pos<end_pos);
- if(just_read_ahead||pipeline&&end_pos>=0
- &&end_pos-conn_pos-available<=read_ahead_thresh){
- /*Found a suitable connection to re-use.*/
- ret=op_http_conn_read_ahead(stream,conn,just_read_ahead,pos);
- if(OP_UNLIKELY(ret<0)){
- /*The connection might have become stale, so close it and keep going.*/
- op_http_conn_close(stream,conn,pnext,1);
- conn=*pnext;
- continue;
- }
- /*Sucessfully resurrected this connection.*/
- *pnext=conn->next;
- conn->next=stream->lru_head;
- stream->lru_head=conn;
- stream->cur_conni=conn-stream->conns;
- return 0;
- }
- close_pnext=pnext;
- close_conn=conn;
- pnext=&conn->next;
- conn=conn->next;
- }
- /*No suitable connections.
- Open a new one.*/
- if(stream->free_head==NULL){
- /*All connections in use.
- Expire one of them (we should have already picked which one when scanning
- the list).*/
- OP_ASSERT(close_conn!=NULL);
- OP_ASSERT(close_pnext!=NULL);
- op_http_conn_close(stream,close_conn,close_pnext,1);
- }
- OP_ASSERT(stream->free_head!=NULL);
- conn=stream->free_head;
- /*If we can pipeline, only request a chunk of data.
- If we're seeking now, there's a good chance we will want to seek again
- soon, and this avoids committing this connection to reading the rest of
- the stream.
- Particularly with SSL or proxies, issuing a new request on the same
- connection can be substantially faster than opening a new one.
- This also limits the amount of data the server will blast at us on this
- connection if we later seek elsewhere and start reading from a different
- connection.*/
- ret=op_http_conn_open_pos(stream,conn,pos,
- pipeline?OP_PIPELINE_CHUNK_SIZE:-1);
- if(OP_UNLIKELY(ret<0)){
- op_http_conn_close(stream,conn,&stream->lru_head,1);
- return -1;
- }
- return 0;
-}
-
-static opus_int64 op_http_stream_tell(void *_stream){
- OpusHTTPStream *stream;
- int ci;
- stream=(OpusHTTPStream *)_stream;
- ci=stream->cur_conni;
- return ci<0?stream->pos:stream->conns[ci].pos;
-}
-
-static int op_http_stream_close(void *_stream){
- OpusHTTPStream *stream;
- stream=(OpusHTTPStream *)_stream;
- if(OP_LIKELY(stream!=NULL)){
- op_http_stream_clear(stream);
- _ogg_free(stream);
- }
- return 0;
-}
-
-static const OpusFileCallbacks OP_HTTP_CALLBACKS={
- op_http_stream_read,
- op_http_stream_seek,
- op_http_stream_tell,
- op_http_stream_close
-};
-#endif
-
-void opus_server_info_init(OpusServerInfo *_info){
- _info->name=NULL;
- _info->description=NULL;
- _info->genre=NULL;
- _info->url=NULL;
- _info->server=NULL;
- _info->content_type=NULL;
- _info->bitrate_kbps=-1;
- _info->is_public=-1;
- _info->is_ssl=0;
-}
-
-void opus_server_info_clear(OpusServerInfo *_info){
- _ogg_free(_info->content_type);
- _ogg_free(_info->server);
- _ogg_free(_info->url);
- _ogg_free(_info->genre);
- _ogg_free(_info->description);
- _ogg_free(_info->name);
-}
-
-/*The actual URL stream creation function.
- This one isn't extensible like the application-level interface, but because
- it isn't public, we're free to change it in the future.*/
-static void *op_url_stream_create_impl(OpusFileCallbacks *_cb,const char *_url,
- int _skip_certificate_check,const char *_proxy_host,unsigned _proxy_port,
- const char *_proxy_user,const char *_proxy_pass,OpusServerInfo *_info){
- const char *path;
- /*Check to see if this is a valid file: URL.*/
- path=op_parse_file_url(_url);
- if(path!=NULL){
- char *unescaped_path;
- void *ret;
- unescaped_path=op_string_dup(path);
- if(OP_UNLIKELY(unescaped_path==NULL))return NULL;
- ret=op_fopen(_cb,op_unescape_url_component(unescaped_path),"rb");
- _ogg_free(unescaped_path);
- return ret;
- }
-#if defined(OP_ENABLE_HTTP)
- /*If not, try http/https.*/
- else{
- OpusHTTPStream *stream;
- int ret;
- stream=(OpusHTTPStream *)_ogg_malloc(sizeof(*stream));
- if(OP_UNLIKELY(stream==NULL))return NULL;
- op_http_stream_init(stream);
- ret=op_http_stream_open(stream,_url,_skip_certificate_check,
- _proxy_host,_proxy_port,_proxy_user,_proxy_pass,_info);
- if(OP_UNLIKELY(ret<0)){
- op_http_stream_clear(stream);
- _ogg_free(stream);
- return NULL;
- }
- *_cb=*&OP_HTTP_CALLBACKS;
- return stream;
- }
-#else
- (void)_skip_certificate_check;
- (void)_proxy_host;
- (void)_proxy_port;
- (void)_proxy_user;
- (void)_proxy_pass;
- (void)_info;
- return NULL;
-#endif
-}
-
-/*The actual implementation of op_url_stream_vcreate().
- We have to do a careful dance here to avoid potential memory leaks if
- OpusServerInfo is requested, since this function is also used by
- op_vopen_url() and op_vtest_url().
- Even if this function succeeds, those functions might ultimately fail.
- If they do, they should return without having touched the OpusServerInfo
- passed by the application.
- Therefore, if this function succeeds and OpusServerInfo is requested, the
- actual info will be stored in *_info and a pointer to the application's
- storage will be placed in *_pinfo.
- If this function fails or if the application did not request OpusServerInfo,
- *_pinfo will be NULL.
- Our caller is responsible for copying *_info to **_pinfo if it ultimately
- succeeds, or for clearing *_info if it ultimately fails.*/
-void *op_url_stream_vcreate_impl(OpusFileCallbacks *_cb,
- const char *_url,OpusServerInfo *_info,OpusServerInfo **_pinfo,va_list _ap){
- int skip_certificate_check;
- const char *proxy_host;
- opus_int32 proxy_port;
- const char *proxy_user;
- const char *proxy_pass;
- OpusServerInfo *pinfo;
- skip_certificate_check=0;
- proxy_host=NULL;
- proxy_port=8080;
- proxy_user=NULL;
- proxy_pass=NULL;
- pinfo=NULL;
- for(;;){
- ptrdiff_t request;
- request=va_arg(_ap,char *)-(char *)NULL;
- /*If we hit NULL, we're done processing options.*/
- if(!request)break;
- switch(request){
- case OP_SSL_SKIP_CERTIFICATE_CHECK_REQUEST:{
- skip_certificate_check=!!va_arg(_ap,opus_int32);
- }break;
- case OP_HTTP_PROXY_HOST_REQUEST:{
- proxy_host=va_arg(_ap,const char *);
- }break;
- case OP_HTTP_PROXY_PORT_REQUEST:{
- proxy_port=va_arg(_ap,opus_int32);
- if(proxy_port<0||proxy_port>(opus_int32)65535)return NULL;
- }break;
- case OP_HTTP_PROXY_USER_REQUEST:{
- proxy_user=va_arg(_ap,const char *);
- }break;
- case OP_HTTP_PROXY_PASS_REQUEST:{
- proxy_pass=va_arg(_ap,const char *);
- }break;
- case OP_GET_SERVER_INFO_REQUEST:{
- pinfo=va_arg(_ap,OpusServerInfo *);
- }break;
- /*Some unknown option.*/
- default:return NULL;
- }
- }
- /*If the caller has requested server information, proxy it to a local copy to
- simplify error handling.*/
- *_pinfo=NULL;
- if(pinfo!=NULL){
- void *ret;
- opus_server_info_init(_info);
- ret=op_url_stream_create_impl(_cb,_url,skip_certificate_check,
- proxy_host,proxy_port,proxy_user,proxy_pass,_info);
- if(ret!=NULL)*_pinfo=pinfo;
- else opus_server_info_clear(_info);
- return ret;
- }
- return op_url_stream_create_impl(_cb,_url,skip_certificate_check,
- proxy_host,proxy_port,proxy_user,proxy_pass,NULL);
-}
-
-void *op_url_stream_vcreate(OpusFileCallbacks *_cb,
- const char *_url,va_list _ap){
- OpusServerInfo info;
- OpusServerInfo *pinfo;
- void *ret;
- ret=op_url_stream_vcreate_impl(_cb,_url,&info,&pinfo,_ap);
- if(pinfo!=NULL)*pinfo=*&info;
- return ret;
-}
-
-void *op_url_stream_create(OpusFileCallbacks *_cb,
- const char *_url,...){
- va_list ap;
- void *ret;
- va_start(ap,_url);
- ret=op_url_stream_vcreate(_cb,_url,ap);
- va_end(ap);
- return ret;
-}
-
-/*Convenience routines to open/test URLs in a single step.*/
-
-OggOpusFile *op_vopen_url(const char *_url,int *_error,va_list _ap){
- OpusFileCallbacks cb;
- OggOpusFile *of;
- OpusServerInfo info;
- OpusServerInfo *pinfo;
- void *source;
- source=op_url_stream_vcreate_impl(&cb,_url,&info,&pinfo,_ap);
- if(OP_UNLIKELY(source==NULL)){
- OP_ASSERT(pinfo==NULL);
- if(_error!=NULL)*_error=OP_EFAULT;
- return NULL;
- }
- of=op_open_callbacks(source,&cb,NULL,0,_error);
- if(OP_UNLIKELY(of==NULL)){
- if(pinfo!=NULL)opus_server_info_clear(&info);
- (*cb.close)(source);
- }
- else if(pinfo!=NULL)*pinfo=*&info;
- return of;
-}
-
-OggOpusFile *op_open_url(const char *_url,int *_error,...){
- OggOpusFile *ret;
- va_list ap;
- va_start(ap,_error);
- ret=op_vopen_url(_url,_error,ap);
- va_end(ap);
- return ret;
-}
-
-OggOpusFile *op_vtest_url(const char *_url,int *_error,va_list _ap){
- OpusFileCallbacks cb;
- OggOpusFile *of;
- OpusServerInfo info;
- OpusServerInfo *pinfo;
- void *source;
- source=op_url_stream_vcreate_impl(&cb,_url,&info,&pinfo,_ap);
- if(OP_UNLIKELY(source==NULL)){
- OP_ASSERT(pinfo==NULL);
- if(_error!=NULL)*_error=OP_EFAULT;
- return NULL;
- }
- of=op_test_callbacks(source,&cb,NULL,0,_error);
- if(OP_UNLIKELY(of==NULL)){
- if(pinfo!=NULL)opus_server_info_clear(&info);
- (*cb.close)(source);
- }
- else if(pinfo!=NULL)*pinfo=*&info;
- return of;
-}
-
-OggOpusFile *op_test_url(const char *_url,int *_error,...){
- OggOpusFile *ret;
- va_list ap;
- va_start(ap,_error);
- ret=op_vtest_url(_url,_error,ap);
- va_end(ap);
- return ret;
-}
diff --git a/thirdparty/opus/wincerts.c b/thirdparty/opus/wincerts.c
deleted file mode 100644
index b0e35aa352..0000000000
--- a/thirdparty/opus/wincerts.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/********************************************************************
- * *
- * THIS FILE IS PART OF THE libopusfile SOFTWARE CODEC SOURCE CODE. *
- * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
- * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
- * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
- * *
- * THE libopusfile SOURCE CODE IS (C) COPYRIGHT 2013 *
- * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
- * *
- ********************************************************************/
-
-/*This should really be part of OpenSSL, but there's been a patch [1] sitting
- in their bugtracker for over two years that implements this, without any
- action, so I'm giving up and re-implementing it locally.
-
- [1] <http://rt.openssl.org/Ticket/Display.html?id=2158>*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "internal.h"
-#if defined(OP_ENABLE_HTTP)&&defined(_WIN32)
-/*You must include windows.h before wincrypt.h and x509.h.*/
-# define WIN32_LEAN_AND_MEAN
-# define WIN32_EXTRA_LEAN
-# include <windows.h>
-/*You must include wincrypt.h before x509.h, too, or X509_NAME doesn't get
- defined properly.*/
-# include <wincrypt.h>
-# include <openssl/ssl.h>
-# include <openssl/err.h>
-# include <openssl/x509.h>
-
-static int op_capi_new(X509_LOOKUP *_lu){
- HCERTSTORE h_store;
- h_store=CertOpenStore(CERT_STORE_PROV_SYSTEM_A,0,0,
- CERT_STORE_OPEN_EXISTING_FLAG|CERT_STORE_READONLY_FLAG|
- CERT_SYSTEM_STORE_CURRENT_USER|CERT_STORE_SHARE_CONTEXT_FLAG,"ROOT");
- if(h_store!=NULL){
- _lu->method_data=(char *)h_store;
- return 1;
- }
- return 0;
-}
-
-static void op_capi_free(X509_LOOKUP *_lu){
- HCERTSTORE h_store;
- h_store=(HCERTSTORE)_lu->method_data;
-# if defined(OP_ENABLE_ASSERTIONS)
- OP_ALWAYS_TRUE(CertCloseStore(h_store,CERT_CLOSE_STORE_CHECK_FLAG));
-# else
- CertCloseStore(h_store,0);
-# endif
-}
-
-static int op_capi_retrieve_by_subject(X509_LOOKUP *_lu,int _type,
- X509_NAME *_name,X509_OBJECT *_ret){
- X509_OBJECT *obj;
- CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
- obj=X509_OBJECT_retrieve_by_subject(_lu->store_ctx->objs,_type,_name);
- CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
- if(obj!=NULL){
- _ret->type=obj->type;
- memcpy(&_ret->data,&obj->data,sizeof(_ret->data));
- return 1;
- }
- return 0;
-}
-
-static int op_capi_get_by_subject(X509_LOOKUP *_lu,int _type,X509_NAME *_name,
- X509_OBJECT *_ret){
- HCERTSTORE h_store;
- if(_name==NULL)return 0;
- if(_name->bytes==NULL||_name->bytes->length<=0||_name->modified){
- if(i2d_X509_NAME(_name,NULL)<0)return 0;
- OP_ASSERT(_name->bytes->length>0);
- }
- h_store=(HCERTSTORE)_lu->method_data;
- switch(_type){
- case X509_LU_X509:{
- CERT_NAME_BLOB find_para;
- PCCERT_CONTEXT cert;
- X509 *x;
- int ret;
- /*Although X509_NAME contains a canon_enc field, that "canonical" [1]
- encoding was just made up by OpenSSL.
- It doesn't correspond to any actual standard, and since it drops the
- initial sequence header, won't be recognized by the Crypto API.
- The assumption here is that CertFindCertificateInStore() will allow any
- appropriate variations in the encoding when it does its comparison.
- This is, however, emphatically not true under Wine, which just compares
- the encodings with memcmp().
- Most of the time things work anyway, though, and there isn't really
- anything we can do to make the situation better.
-
- [1] A "canonical form" is defined as the one where, if you locked 10
- mathematicians in a room and asked them to come up with a
- representation for something, it's the answer that 9 of them would
- give you back.
- I don't think OpenSSL's encoding qualifies.*/
- find_para.cbData=_name->bytes->length;
- find_para.pbData=(unsigned char *)_name->bytes->data;
- cert=CertFindCertificateInStore(h_store,X509_ASN_ENCODING,0,
- CERT_FIND_SUBJECT_NAME,&find_para,NULL);
- if(cert==NULL)return 0;
- x=d2i_X509(NULL,(const unsigned char **)&cert->pbCertEncoded,
- cert->cbCertEncoded);
- CertFreeCertificateContext(cert);
- if(x==NULL)return 0;
- ret=X509_STORE_add_cert(_lu->store_ctx,x);
- X509_free(x);
- if(ret)return op_capi_retrieve_by_subject(_lu,_type,_name,_ret);
- }break;
- case X509_LU_CRL:{
- CERT_INFO cert_info;
- CERT_CONTEXT find_para;
- PCCRL_CONTEXT crl;
- X509_CRL *x;
- int ret;
- ret=op_capi_retrieve_by_subject(_lu,_type,_name,_ret);
- if(ret>0)return ret;
- memset(&cert_info,0,sizeof(cert_info));
- cert_info.Issuer.cbData=_name->bytes->length;
- cert_info.Issuer.pbData=(unsigned char *)_name->bytes->data;
- memset(&find_para,0,sizeof(find_para));
- find_para.pCertInfo=&cert_info;
- crl=CertFindCRLInStore(h_store,0,0,CRL_FIND_ISSUED_BY,&find_para,NULL);
- if(crl==NULL)return 0;
- x=d2i_X509_CRL(NULL,(const unsigned char **)&crl->pbCrlEncoded,
- crl->cbCrlEncoded);
- CertFreeCRLContext(crl);
- if(x==NULL)return 0;
- ret=X509_STORE_add_crl(_lu->store_ctx,x);
- X509_CRL_free(x);
- if(ret)return op_capi_retrieve_by_subject(_lu,_type,_name,_ret);
- }break;
- }
- return 0;
-}
-
-/*This is not const because OpenSSL doesn't allow it, even though it won't
- write to it.*/
-static X509_LOOKUP_METHOD X509_LOOKUP_CAPI={
- "Load Crypto API store into cache",
- op_capi_new,
- op_capi_free,
- NULL,
- NULL,
- NULL,
- op_capi_get_by_subject,
- NULL,
- NULL,
- NULL
-};
-
-int SSL_CTX_set_default_verify_paths_win32(SSL_CTX *_ssl_ctx){
- X509_STORE *store;
- X509_LOOKUP *lu;
- /*We intentionally do not add the normal default paths, as they are usually
- wrong, and are just asking to be used as an exploit vector.*/
- store=SSL_CTX_get_cert_store(_ssl_ctx);
- OP_ASSERT(store!=NULL);
- lu=X509_STORE_add_lookup(store,&X509_LOOKUP_CAPI);
- if(lu==NULL)return 0;
- ERR_clear_error();
- return 1;
-}
-
-#endif
diff --git a/thirdparty/opus/winerrno.h b/thirdparty/opus/winerrno.h
deleted file mode 100644
index 32a90b4ee1..0000000000
--- a/thirdparty/opus/winerrno.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/********************************************************************
- * *
- * THIS FILE IS PART OF THE libopusfile SOFTWARE CODEC SOURCE CODE. *
- * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
- * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
- * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
- * *
- * THE libopusfile SOURCE CODE IS (C) COPYRIGHT 2012 *
- * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
- * *
- ********************************************************************/
-#if !defined(_opusfile_winerrno_h)
-# define _opusfile_winerrno_h (1)
-
-# include <errno.h>
-# include <winerror.h>
-
-/*These conflict with the MSVC errno.h definitions, but we don't need to use
- the original ones in any file that deals with sockets.
- We could map the WSA errors to the errno.h ones (most of which are only
- available on sufficiently new versions of MSVC), but they aren't ordered the
- same, and given how rarely we actually look at the values, I don't think
- it's worth a lookup table.*/
-# undef EWOULDBLOCK
-# undef EINPROGRESS
-# undef EALREADY
-# undef ENOTSOCK
-# undef EDESTADDRREQ
-# undef EMSGSIZE
-# undef EPROTOTYPE
-# undef ENOPROTOOPT
-# undef EPROTONOSUPPORT
-# undef EOPNOTSUPP
-# undef EAFNOSUPPORT
-# undef EADDRINUSE
-# undef EADDRNOTAVAIL
-# undef ENETDOWN
-# undef ENETUNREACH
-# undef ENETRESET
-# undef ECONNABORTED
-# undef ECONNRESET
-# undef ENOBUFS
-# undef EISCONN
-# undef ENOTCONN
-# undef ETIMEDOUT
-# undef ECONNREFUSED
-# undef ELOOP
-# undef ENAMETOOLONG
-# undef EHOSTUNREACH
-# undef ENOTEMPTY
-
-# define EWOULDBLOCK (WSAEWOULDBLOCK-WSABASEERR)
-# define EINPROGRESS (WSAEINPROGRESS-WSABASEERR)
-# define EALREADY (WSAEALREADY-WSABASEERR)
-# define ENOTSOCK (WSAENOTSOCK-WSABASEERR)
-# define EDESTADDRREQ (WSAEDESTADDRREQ-WSABASEERR)
-# define EMSGSIZE (WSAEMSGSIZE-WSABASEERR)
-# define EPROTOTYPE (WSAEPROTOTYPE-WSABASEERR)
-# define ENOPROTOOPT (WSAENOPROTOOPT-WSABASEERR)
-# define EPROTONOSUPPORT (WSAEPROTONOSUPPORT-WSABASEERR)
-# define ESOCKTNOSUPPORT (WSAESOCKTNOSUPPORT-WSABASEERR)
-# define EOPNOTSUPP (WSAEOPNOTSUPP-WSABASEERR)
-# define EPFNOSUPPORT (WSAEPFNOSUPPORT-WSABASEERR)
-# define EAFNOSUPPORT (WSAEAFNOSUPPORT-WSABASEERR)
-# define EADDRINUSE (WSAEADDRINUSE-WSABASEERR)
-# define EADDRNOTAVAIL (WSAEADDRNOTAVAIL-WSABASEERR)
-# define ENETDOWN (WSAENETDOWN-WSABASEERR)
-# define ENETUNREACH (WSAENETUNREACH-WSABASEERR)
-# define ENETRESET (WSAENETRESET-WSABASEERR)
-# define ECONNABORTED (WSAECONNABORTED-WSABASEERR)
-# define ECONNRESET (WSAECONNRESET-WSABASEERR)
-# define ENOBUFS (WSAENOBUFS-WSABASEERR)
-# define EISCONN (WSAEISCONN-WSABASEERR)
-# define ENOTCONN (WSAENOTCONN-WSABASEERR)
-# define ESHUTDOWN (WSAESHUTDOWN-WSABASEERR)
-# define ETOOMANYREFS (WSAETOOMANYREFS-WSABASEERR)
-# define ETIMEDOUT (WSAETIMEDOUT-WSABASEERR)
-# define ECONNREFUSED (WSAECONNREFUSED-WSABASEERR)
-# define ELOOP (WSAELOOP-WSABASEERR)
-# define ENAMETOOLONG (WSAENAMETOOLONG-WSABASEERR)
-# define EHOSTDOWN (WSAEHOSTDOWN-WSABASEERR)
-# define EHOSTUNREACH (WSAEHOSTUNREACH-WSABASEERR)
-# define ENOTEMPTY (WSAENOTEMPTY-WSABASEERR)
-# define EPROCLIM (WSAEPROCLIM-WSABASEERR)
-# define EUSERS (WSAEUSERS-WSABASEERR)
-# define EDQUOT (WSAEDQUOT-WSABASEERR)
-# define ESTALE (WSAESTALE-WSABASEERR)
-# define EREMOTE (WSAEREMOTE-WSABASEERR)
-
-#endif
diff --git a/thirdparty/pcre2/LICENCE b/thirdparty/pcre2/LICENCE
index bfe3c8d528..b0f8804fff 100644
--- a/thirdparty/pcre2/LICENCE
+++ b/thirdparty/pcre2/LICENCE
@@ -4,11 +4,11 @@ PCRE2 LICENCE
PCRE2 is a library of functions to support regular expressions whose syntax
and semantics are as close as possible to those of the Perl 5 language.
-Release 10 of PCRE2 is distributed under the terms of the "BSD" licence, as
-specified below, with one exemption for certain binary redistributions. The
-documentation for PCRE2, supplied in the "doc" directory, is distributed under
-the same terms as the software itself. The data in the testdata directory is
-not copyrighted and is in the public domain.
+Releases 10.00 and above of PCRE2 are distributed under the terms of the "BSD"
+licence, as specified below, with one exemption for certain binary
+redistributions. The documentation for PCRE2, supplied in the "doc" directory,
+is distributed under the same terms as the software itself. The data in the
+testdata directory is not copyrighted and is in the public domain.
The basic library functions are written in C and are freestanding. Also
included in the distribution is a just-in-time compiler that can be used to
@@ -35,7 +35,7 @@ PCRE2 JUST-IN-TIME COMPILATION SUPPORT
Written by: Zoltan Herczeg
Email local part: hzmester
-Emain domain: freemail.hu
+Email domain: freemail.hu
Copyright(c) 2010-2018 Zoltan Herczeg
All rights reserved.
@@ -46,7 +46,7 @@ STACK-LESS JUST-IN-TIME COMPILER
Written by: Zoltan Herczeg
Email local part: hzmester
-Emain domain: freemail.hu
+Email domain: freemail.hu
Copyright(c) 2009-2018 Zoltan Herczeg
All rights reserved.
diff --git a/thirdparty/pcre2/src/config.h b/thirdparty/pcre2/src/config.h
index f738616714..89a52ef848 100644
--- a/thirdparty/pcre2/src/config.h
+++ b/thirdparty/pcre2/src/config.h
@@ -18,10 +18,10 @@ to set the macro values. In this case, you do not have to set -DHAVE_CONFIG_H,
but if you do, default values will be taken from config.h for non-boolean
macros that are not defined on the command line.
-Boolean macros such as HAVE_STDLIB_H and SUPPORT_PCRE2_8 should either be defined
-(conventionally to 1) for TRUE, and not defined at all for FALSE. All such
-macros are listed as a commented #undef in config.h.generic. Macros such as
-MATCH_LIMIT, whose actual value is relevant, have defaults defined, but are
+Boolean macros such as HAVE_STDLIB_H and SUPPORT_PCRE2_8 should either be
+defined (conventionally to 1) for TRUE, and not defined at all for FALSE. All
+such macros are listed as a commented #undef in config.h.generic. Macros such
+as MATCH_LIMIT, whose actual value is relevant, have defaults defined, but are
surrounded by #ifndef/#endif lines so that the value can be overridden by -D.
PCRE2 uses memmove() if HAVE_MEMMOVE is defined; otherwise it uses bcopy() if
@@ -132,17 +132,18 @@ sure both macros are undefined; an emulation function will then be used. */
/* Define to 1 if you have the <zlib.h> header file. */
/* #undef HAVE_ZLIB_H */
-/* This limits the amount of memory that pcre2_match() may use while matching
- a pattern. The value is in kilobytes. */
+/* This limits the amount of memory that may be used while matching a pattern.
+ It applies to both pcre2_match() and pcre2_dfa_match(). It does not apply
+ to JIT matching. The value is in kibibytes (units of 1024 bytes). */
#ifndef HEAP_LIMIT
#define HEAP_LIMIT 20000000
#endif
/* The value of LINK_SIZE determines the number of bytes used to store links
as offsets within the compiled regex. The default is 2, which allows for
- compiled patterns up to 64K long. This covers the vast majority of cases.
- However, PCRE2 can also be compiled to use 3 or 4 bytes instead. This
- allows for longer patterns in extreme cases. */
+ compiled patterns up to 65535 code units long. This covers the vast
+ majority of cases. However, PCRE2 can also be compiled to use 3 or 4 bytes
+ instead. This allows for longer patterns in extreme cases. */
#ifndef LINK_SIZE
#define LINK_SIZE 2
#endif
@@ -155,7 +156,8 @@ sure both macros are undefined; an emulation function will then be used. */
/* The value of MATCH_LIMIT determines the default number of times the
pcre2_match() function can record a backtrack position during a single
- matching attempt. There is a runtime interface for setting a different
+ matching attempt. The value is also used to limit a loop counter in
+ pcre2_dfa_match(). There is a runtime interface for setting a different
limit. The limit exists in order to catch runaway regular expressions that
take for ever to determine that they do not match. The default is set very
large so that it does not accidentally catch legitimate cases. */
@@ -170,7 +172,9 @@ sure both macros are undefined; an emulation function will then be used. */
MATCH_LIMIT_DEPTH provides this facility. To have any useful effect, it
must be less than the value of MATCH_LIMIT. The default is to use the same
value as MATCH_LIMIT. There is a runtime method for setting a different
- limit. */
+ limit. In the case of pcre2_dfa_match(), this limit controls the depth of
+ the internal nested function calls that are used for pattern recursions,
+ lookarounds, and atomic groups. */
#ifndef MATCH_LIMIT_DEPTH
#define MATCH_LIMIT_DEPTH MATCH_LIMIT
#endif
@@ -210,7 +214,7 @@ sure both macros are undefined; an emulation function will then be used. */
#define PACKAGE_NAME "PCRE2"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "PCRE2 10.31"
+#define PACKAGE_STRING "PCRE2 10.32"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "pcre2"
@@ -219,7 +223,7 @@ sure both macros are undefined; an emulation function will then be used. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
-#define PACKAGE_VERSION "10.31"
+#define PACKAGE_VERSION "10.32"
/* The value of PARENS_NEST_LIMIT specifies the maximum depth of nested
parentheses (of any kind) in a pattern. This limits the amount of system
@@ -339,7 +343,7 @@ sure both macros are undefined; an emulation function will then be used. */
#endif
/* Version number of package */
-#define VERSION "10.31"
+#define VERSION "10.32"
/* Define to 1 if on MINIX. */
/* #undef _MINIX */
diff --git a/thirdparty/pcre2/src/pcre2.h b/thirdparty/pcre2/src/pcre2.h
index fffcc307d0..3d2feb7a6b 100644
--- a/thirdparty/pcre2/src/pcre2.h
+++ b/thirdparty/pcre2/src/pcre2.h
@@ -5,7 +5,7 @@
/* This is the public header file for the PCRE library, second API, to be
#included by applications that call PCRE2 functions.
- Copyright (c) 2016-2017 University of Cambridge
+ Copyright (c) 2016-2018 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -41,10 +41,16 @@ POSSIBILITY OF SUCH DAMAGE.
/* The current PCRE version information. */
-#define PCRE2_MAJOR 10
-#define PCRE2_MINOR 31
-#define PCRE2_PRERELEASE
-#define PCRE2_DATE 2018-02-12
+#define PCRE2_MAJOR 10
+#define PCRE2_MINOR 32
+#define PCRE2_PRERELEASE
+#define PCRE2_DATE 2018-09-10
+
+/* For the benefit of systems without stdint.h, an alternative is to use
+inttypes.h. The existence of these headers is checked by configure or CMake. */
+
+#define PCRE2_HAVE_STDINT_H 1
+#define PCRE2_HAVE_INTTYPES_H 1
/* When an application links to a PCRE DLL in Windows, the symbols that are
imported have to be identified as such. When building PCRE2, the appropriate
@@ -81,12 +87,18 @@ set, we ensure here that it has no effect. */
#define PCRE2_CALL_CONVENTION
#endif
-/* Have to include limits.h, stdlib.h and stdint.h to ensure that size_t and
-uint8_t, UCHAR_MAX, etc are defined. */
+/* Have to include limits.h, stdlib.h and stdint.h (or inttypes.h) to ensure
+that size_t and uint8_t, UCHAR_MAX, etc are defined. If the system has neither
+header, the relevant values must be provided by some other means. */
#include <limits.h>
#include <stdlib.h>
+
+#if PCRE2_HAVE_STDINT_H
#include <stdint.h>
+#elif PCRE2_HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
/* Allow for C++ users compiling this directly. */
@@ -269,6 +281,7 @@ pcre2_pattern_convert(). */
#define PCRE2_ERROR_INTERNAL_UNKNOWN_NEWLINE 156
#define PCRE2_ERROR_BACKSLASH_G_SYNTAX 157
#define PCRE2_ERROR_PARENS_QUERY_R_MISSING_CLOSING 158
+/* Error 159 is obsolete and should now never occur */
#define PCRE2_ERROR_VERB_ARGUMENT_NOT_ALLOWED 159
#define PCRE2_ERROR_VERB_UNKNOWN 160
#define PCRE2_ERROR_SUBPATTERN_NUMBER_TOO_BIG 161
@@ -303,6 +316,8 @@ pcre2_pattern_convert(). */
#define PCRE2_ERROR_INTERNAL_BAD_CODE_IN_SKIP 190
#define PCRE2_ERROR_NO_SURROGATES_IN_UTF16 191
#define PCRE2_ERROR_BAD_LITERAL_OPTIONS 192
+#define PCRE2_ERROR_SUPPORTED_ONLY_IN_UNICODE 193
+#define PCRE2_ERROR_INVALID_HYPHEN_IN_OPTIONS 194
/* "Expected" matching error codes: no match and partial match. */
@@ -387,6 +402,7 @@ released, the numbers must not be changed. */
#define PCRE2_ERROR_BADSERIALIZEDDATA (-62)
#define PCRE2_ERROR_HEAPLIMIT (-63)
#define PCRE2_ERROR_CONVERT_SYNTAX (-64)
+#define PCRE2_ERROR_INTERNAL_DUPMATCH (-65)
/* Request types for pcre2_pattern_info() */
diff --git a/thirdparty/pcre2/src/pcre2_auto_possess.c b/thirdparty/pcre2/src/pcre2_auto_possess.c
index 23275a2e39..2ce152e952 100644
--- a/thirdparty/pcre2/src/pcre2_auto_possess.c
+++ b/thirdparty/pcre2/src/pcre2_auto_possess.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2017 University of Cambridge
+ New API code Copyright (c) 2016-2018 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -505,7 +505,7 @@ Arguments:
utf TRUE in UTF mode
cb compile data block
base_list the data list of the base opcode
- base_end the end of the data list
+ base_end the end of the base opcode
rec_limit points to recursion depth counter
Returns: TRUE if the auto-possessification is possible
@@ -730,7 +730,7 @@ for(;;)
if ((*xclass_flags & XCL_MAP) == 0)
{
/* No bits are set for characters < 256. */
- if (list[1] == 0) return TRUE;
+ if (list[1] == 0) return (*xclass_flags & XCL_NOT) == 0;
/* Might be an empty repeat. */
continue;
}
@@ -1235,6 +1235,7 @@ for (;;)
#endif
case OP_MARK:
+ case OP_COMMIT_ARG:
case OP_PRUNE_ARG:
case OP_SKIP_ARG:
case OP_THEN_ARG:
diff --git a/thirdparty/pcre2/src/pcre2_chartables.c b/thirdparty/pcre2/src/pcre2_chartables.c
index 203cb1a4ab..4046500c00 100644
--- a/thirdparty/pcre2/src/pcre2_chartables.c
+++ b/thirdparty/pcre2/src/pcre2_chartables.c
@@ -2,23 +2,24 @@
* Perl-Compatible Regular Expressions *
*************************************************/
-/* This file contains character tables that are used when no external tables
-are passed to PCRE2 by the application that calls it. The tables are used only
-for characters whose code values are less than 256.
-
-This is a default version of the tables that assumes ASCII encoding. A program
-called dftables (which is distributed with PCRE2) can be used to build
-alternative versions of this file. This is necessary if you are running in an
-EBCDIC environment, or if you want to default to a different encoding, for
-example ISO-8859-1. When dftables is run, it creates these tables in the
-current locale. If PCRE2 is configured with --enable-rebuild-chartables, this
-happens automatically.
-
-The following #includes are present because without them gcc 4.x may remove the
-array definition from the final binary if PCRE2 is built into a static library
-and dead code stripping is activated. This leads to link errors. Pulling in the
-header ensures that the array gets flagged as "someone outside this compilation
-unit might reference this" and so it will always be supplied to the linker. */
+/* This file was automatically written by the dftables auxiliary
+program. It contains character tables that are used when no external
+tables are passed to PCRE2 by the application that calls it. The tables
+are used only for characters whose code values are less than 256. */
+
+/*The dftables program (which is distributed with PCRE2) can be used to
+build alternative versions of this file. This is necessary if you are
+running in an EBCDIC environment, or if you want to default to a different
+encoding, for example ISO-8859-1. When dftables is run, it creates these
+tables in the current locale. This happens automatically if PCRE2 is
+configured with --enable-rebuild-chartables. */
+
+/* The following #include is present because without it gcc 4.x may remove
+the array definition from the final binary if PCRE2 is built into a static
+library and dead code stripping is activated. This leads to link errors.
+Pulling in the header ensures that the array gets flagged as "someone
+outside this compilation unit might reference this" and so it will always
+be supplied to the linker. */
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -101,7 +102,7 @@ const uint8_t PRIV(default_tables)[] = {
/* This table contains bit maps for various character classes. Each map is 32
bytes long and the bits run from the least significant end of each byte. The
classes that have their own maps are: space, xdigit, digit, upper, lower, word,
-graph, print, punct, and cntrl. Other classes are built from combinations. */
+graph print, punct, and cntrl. Other classes are built from combinations. */
0x00,0x3e,0x00,0x00,0x01,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
@@ -159,25 +160,24 @@ graph, print, punct, and cntrl. Other classes are built from combinations. */
0x04 decimal digit
0x08 hexadecimal digit
0x10 alphanumeric or '_'
- 0x80 regular expression metacharacter or binary zero
*/
- 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 */
0x00,0x01,0x01,0x01,0x01,0x01,0x00,0x00, /* 8- 15 */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 16- 23 */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */
- 0x01,0x00,0x00,0x00,0x80,0x00,0x00,0x00, /* - ' */
- 0x80,0x80,0x80,0x80,0x00,0x00,0x80,0x00, /* ( - / */
+ 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - ' */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* ( - / */
0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, /* 0 - 7 */
- 0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x80, /* 8 - ? */
+ 0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x00, /* 8 - ? */
0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* @ - G */
0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* H - O */
0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* P - W */
- 0x12,0x12,0x12,0x80,0x80,0x00,0x80,0x10, /* X - _ */
+ 0x12,0x12,0x12,0x00,0x00,0x00,0x00,0x10, /* X - _ */
0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* ` - g */
0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* h - o */
0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* p - w */
- 0x12,0x12,0x12,0x80,0x80,0x00,0x00,0x00, /* x -127 */
+ 0x12,0x12,0x12,0x00,0x00,0x00,0x00,0x00, /* x -127 */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 128-135 */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 136-143 */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144-151 */
diff --git a/thirdparty/pcre2/src/pcre2_compile.c b/thirdparty/pcre2/src/pcre2_compile.c
index 87530fb584..6bb1de3610 100644
--- a/thirdparty/pcre2/src/pcre2_compile.c
+++ b/thirdparty/pcre2/src/pcre2_compile.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2017 University of Cambridge
+ New API code Copyright (c) 2016-2018 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -63,8 +63,8 @@ POSSIBILITY OF SUCH DAMAGE.
/* Other debugging code can be enabled by these defines. */
-// #define DEBUG_SHOW_CAPTURES
-// #define DEBUG_SHOW_PARSED
+/* #define DEBUG_SHOW_CAPTURES */
+/* #define DEBUG_SHOW_PARSED */
/* There are a few things that vary with different code unit sizes. Handle them
by defining macros in order to minimize #if usage. */
@@ -250,34 +250,35 @@ is present where expected in a conditional group. */
#define META_LOOKBEHINDNOT 0x80250000u /* (?<! */
/* These must be kept in this order, with consecutive values, and the _ARG
-versions of PRUNE, SKIP, and THEN immediately after their non-argument
+versions of COMMIT, PRUNE, SKIP, and THEN immediately after their non-argument
versions. */
#define META_MARK 0x80260000u /* (*MARK) */
#define META_ACCEPT 0x80270000u /* (*ACCEPT) */
-#define META_COMMIT 0x80280000u /* (*COMMIT) */
-#define META_FAIL 0x80290000u /* (*FAIL) */
-#define META_PRUNE 0x802a0000u /* These pairs must */
-#define META_PRUNE_ARG 0x802b0000u /* be */
-#define META_SKIP 0x802c0000u /* kept */
-#define META_SKIP_ARG 0x802d0000u /* in */
-#define META_THEN 0x802e0000u /* this */
-#define META_THEN_ARG 0x802f0000u /* order */
+#define META_FAIL 0x80280000u /* (*FAIL) */
+#define META_COMMIT 0x80290000u /* These */
+#define META_COMMIT_ARG 0x802a0000u /* pairs */
+#define META_PRUNE 0x802b0000u /* must */
+#define META_PRUNE_ARG 0x802c0000u /* be */
+#define META_SKIP 0x802d0000u /* kept */
+#define META_SKIP_ARG 0x802e0000u /* in */
+#define META_THEN 0x802f0000u /* this */
+#define META_THEN_ARG 0x80300000u /* order */
/* These must be kept in groups of adjacent 3 values, and all together. */
-#define META_ASTERISK 0x80300000u /* * */
-#define META_ASTERISK_PLUS 0x80310000u /* *+ */
-#define META_ASTERISK_QUERY 0x80320000u /* *? */
-#define META_PLUS 0x80330000u /* + */
-#define META_PLUS_PLUS 0x80340000u /* ++ */
-#define META_PLUS_QUERY 0x80350000u /* +? */
-#define META_QUERY 0x80360000u /* ? */
-#define META_QUERY_PLUS 0x80370000u /* ?+ */
-#define META_QUERY_QUERY 0x80380000u /* ?? */
-#define META_MINMAX 0x80390000u /* {n,m} repeat */
-#define META_MINMAX_PLUS 0x803a0000u /* {n,m}+ repeat */
-#define META_MINMAX_QUERY 0x803b0000u /* {n,m}? repeat */
+#define META_ASTERISK 0x80310000u /* * */
+#define META_ASTERISK_PLUS 0x80320000u /* *+ */
+#define META_ASTERISK_QUERY 0x80330000u /* *? */
+#define META_PLUS 0x80340000u /* + */
+#define META_PLUS_PLUS 0x80350000u /* ++ */
+#define META_PLUS_QUERY 0x80360000u /* +? */
+#define META_QUERY 0x80370000u /* ? */
+#define META_QUERY_PLUS 0x80380000u /* ?+ */
+#define META_QUERY_QUERY 0x80390000u /* ?? */
+#define META_MINMAX 0x803a0000u /* {n,m} repeat */
+#define META_MINMAX_PLUS 0x803b0000u /* {n,m}+ repeat */
+#define META_MINMAX_QUERY 0x803c0000u /* {n,m}? repeat */
#define META_FIRST_QUANTIFIER META_ASTERISK
#define META_LAST_QUANTIFIER META_MINMAX_QUERY
@@ -327,8 +328,9 @@ static unsigned char meta_extra_lengths[] = {
SIZEOFFSET, /* META_LOOKBEHINDNOT */
1, /* META_MARK - plus the string length */
0, /* META_ACCEPT */
- 0, /* META_COMMIT */
0, /* META_FAIL */
+ 0, /* META_COMMIT */
+ 1, /* META_COMMIT_ARG - plus the string length */
0, /* META_PRUNE */
1, /* META_PRUNE_ARG - plus the string length */
0, /* META_SKIP */
@@ -510,17 +512,17 @@ static const short int escapes[] = {
-ESC_Z, CHAR_LEFT_SQUARE_BRACKET,
CHAR_BACKSLASH, CHAR_RIGHT_SQUARE_BRACKET,
CHAR_CIRCUMFLEX_ACCENT, CHAR_UNDERSCORE,
- CHAR_GRAVE_ACCENT, ESC_a,
+ CHAR_GRAVE_ACCENT, CHAR_BEL,
-ESC_b, 0,
- -ESC_d, ESC_e,
- ESC_f, 0,
+ -ESC_d, CHAR_ESC,
+ CHAR_FF, 0,
-ESC_h, 0,
0, -ESC_k,
0, 0,
- ESC_n, 0,
+ CHAR_LF, 0,
-ESC_p, 0,
- ESC_r, -ESC_s,
- ESC_tee, 0,
+ CHAR_CR, -ESC_s,
+ CHAR_HT, 0,
-ESC_v, -ESC_w,
0, 0,
-ESC_z
@@ -544,22 +546,22 @@ because it is defined as 'a', which of course picks up the ASCII value. */
#endif
static const short int escapes[] = {
-/* 80 */ ESC_a, -ESC_b, 0, -ESC_d, ESC_e, ESC_f, 0,
-/* 88 */-ESC_h, 0, 0, '{', 0, 0, 0, 0,
-/* 90 */ 0, 0, -ESC_k, 0, 0, ESC_n, 0, -ESC_p,
-/* 98 */ 0, ESC_r, 0, '}', 0, 0, 0, 0,
-/* A0 */ 0, '~', -ESC_s, ESC_tee, 0,-ESC_v, -ESC_w, 0,
-/* A8 */ 0,-ESC_z, 0, 0, 0, '[', 0, 0,
-/* B0 */ 0, 0, 0, 0, 0, 0, 0, 0,
-/* B8 */ 0, 0, 0, 0, 0, ']', '=', '-',
-/* C0 */ '{',-ESC_A, -ESC_B, -ESC_C, -ESC_D,-ESC_E, 0, -ESC_G,
-/* C8 */-ESC_H, 0, 0, 0, 0, 0, 0, 0,
-/* D0 */ '}', 0, -ESC_K, 0, 0,-ESC_N, 0, -ESC_P,
-/* D8 */-ESC_Q,-ESC_R, 0, 0, 0, 0, 0, 0,
-/* E0 */ '\\', 0, -ESC_S, 0, 0,-ESC_V, -ESC_W, -ESC_X,
-/* E8 */ 0,-ESC_Z, 0, 0, 0, 0, 0, 0,
-/* F0 */ 0, 0, 0, 0, 0, 0, 0, 0,
-/* F8 */ 0, 0
+/* 80 */ CHAR_BEL, -ESC_b, 0, -ESC_d, CHAR_ESC, CHAR_FF, 0,
+/* 88 */ -ESC_h, 0, 0, '{', 0, 0, 0, 0,
+/* 90 */ 0, 0, -ESC_k, 0, 0, CHAR_LF, 0, -ESC_p,
+/* 98 */ 0, CHAR_CR, 0, '}', 0, 0, 0, 0,
+/* A0 */ 0, '~', -ESC_s, CHAR_HT, 0, -ESC_v, -ESC_w, 0,
+/* A8 */ 0, -ESC_z, 0, 0, 0, '[', 0, 0,
+/* B0 */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* B8 */ 0, 0, 0, 0, 0, ']', '=', '-',
+/* C0 */ '{', -ESC_A, -ESC_B, -ESC_C, -ESC_D, -ESC_E, 0, -ESC_G,
+/* C8 */ -ESC_H, 0, 0, 0, 0, 0, 0, 0,
+/* D0 */ '}', 0, -ESC_K, 0, 0, -ESC_N, 0, -ESC_P,
+/* D8 */ -ESC_Q, -ESC_R, 0, 0, 0, 0, 0, 0,
+/* E0 */ '\\', 0, -ESC_S, 0, 0, -ESC_V, -ESC_W, -ESC_X,
+/* E8 */ 0, -ESC_Z, 0, 0, 0, 0, 0, 0,
+/* F0 */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* F8 */ 0, 0
};
/* We also need a table of characters that may follow \c in an EBCDIC
@@ -586,9 +588,9 @@ static const char verbnames[] =
"\0" /* Empty name is a shorthand for MARK */
STRING_MARK0
STRING_ACCEPT0
- STRING_COMMIT0
STRING_F0
STRING_FAIL0
+ STRING_COMMIT0
STRING_PRUNE0
STRING_SKIP0
STRING_THEN;
@@ -596,11 +598,11 @@ static const char verbnames[] =
static const verbitem verbs[] = {
{ 0, META_MARK, +1 }, /* > 0 => must have an argument */
{ 4, META_MARK, +1 },
- { 6, META_ACCEPT, -1 }, /* < 0 => must not have an argument */
- { 6, META_COMMIT, -1 },
+ { 6, META_ACCEPT, -1 }, /* < 0 => Optional argument, convert to pre-MARK */
{ 1, META_FAIL, -1 },
{ 4, META_FAIL, -1 },
- { 5, META_PRUNE, 0 }, /* Argument is optional; bump META code if found */
+ { 6, META_COMMIT, 0 },
+ { 5, META_PRUNE, 0 }, /* Optional argument; bump META code if found */
{ 4, META_SKIP, 0 },
{ 4, META_THEN, 0 }
};
@@ -610,8 +612,8 @@ static const int verbcount = sizeof(verbs)/sizeof(verbitem);
/* Verb opcodes, indexed by their META code offset from META_MARK. */
static const uint32_t verbops[] = {
- OP_MARK, OP_ACCEPT, OP_COMMIT, OP_FAIL, OP_PRUNE, OP_PRUNE_ARG, OP_SKIP,
- OP_SKIP_ARG, OP_THEN, OP_THEN_ARG };
+ OP_MARK, OP_ACCEPT, OP_FAIL, OP_COMMIT, OP_COMMIT_ARG, OP_PRUNE,
+ OP_PRUNE_ARG, OP_SKIP, OP_SKIP_ARG, OP_THEN, OP_THEN_ARG };
/* Offsets from OP_STAR for case-independent and negative repeat opcodes. */
@@ -729,7 +731,7 @@ enum { ERR0 = COMPILE_ERROR_BASE,
ERR61, ERR62, ERR63, ERR64, ERR65, ERR66, ERR67, ERR68, ERR69, ERR70,
ERR71, ERR72, ERR73, ERR74, ERR75, ERR76, ERR77, ERR78, ERR79, ERR80,
ERR81, ERR82, ERR83, ERR84, ERR85, ERR86, ERR87, ERR88, ERR89, ERR90,
- ERR91, ERR92};
+ ERR91, ERR92, ERR93, ERR94 };
/* This is a table of start-of-pattern options such as (*UTF) and settings such
as (*LIMIT_MATCH=nnnn) and (*CRLF). For completeness and backward
@@ -976,8 +978,8 @@ for (;;)
case META_POSIX_NEG: fprintf(stderr, "META_POSIX_NEG %d", *pptr++); break;
case META_ACCEPT: fprintf(stderr, "META (*ACCEPT)"); break;
- case META_COMMIT: fprintf(stderr, "META (*COMMIT)"); break;
case META_FAIL: fprintf(stderr, "META (*FAIL)"); break;
+ case META_COMMIT: fprintf(stderr, "META (*COMMIT)"); break;
case META_PRUNE: fprintf(stderr, "META (*PRUNE)"); break;
case META_SKIP: fprintf(stderr, "META (*SKIP)"); break;
case META_THEN: fprintf(stderr, "META (*THEN)"); break;
@@ -1067,6 +1069,10 @@ for (;;)
fprintf(stderr, "META (*MARK:");
goto SHOWARG;
+ case META_COMMIT_ARG:
+ fprintf(stderr, "META (*COMMIT:");
+ goto SHOWARG;
+
case META_PRUNE_ARG:
fprintf(stderr, "META (*PRUNE:");
goto SHOWARG;
@@ -1435,6 +1441,48 @@ else if ((i = escapes[c - ESCAPES_FIRST]) != 0)
escape = -i; /* Else return a special escape */
if (cb != NULL && (escape == ESC_P || escape == ESC_p || escape == ESC_X))
cb->external_flags |= PCRE2_HASBKPORX; /* Note \P, \p, or \X */
+
+ /* Perl supports \N{name} for character names and \N{U+dddd} for numerical
+ Unicode code points, as well as plain \N for "not newline". PCRE does not
+ support \N{name}. However, it does support quantification such as \N{2,3},
+ so if \N{ is not followed by U+dddd we check for a quantifier. */
+
+ if (escape == ESC_N && ptr < ptrend && *ptr == CHAR_LEFT_CURLY_BRACKET)
+ {
+ PCRE2_SPTR p = ptr + 1;
+
+ /* \N{U+ can be handled by the \x{ code. However, this construction is
+ not valid in EBCDIC environments because it specifies a Unicode
+ character, not a codepoint in the local code. For example \N{U+0041}
+ must be "A" in all environments. Also, in Perl, \N{U+ forces Unicode
+ casing semantics for the entire pattern, so allow it only in UTF (i.e.
+ Unicode) mode. */
+
+ if (ptrend - p > 1 && *p == CHAR_U && p[1] == CHAR_PLUS)
+ {
+#ifdef EBCDIC
+ *errorcodeptr = ERR93;
+#else
+ if (utf)
+ {
+ ptr = p + 1;
+ escape = 0; /* Not a fancy escape after all */
+ goto COME_FROM_NU;
+ }
+ else *errorcodeptr = ERR93;
+#endif
+ }
+
+ /* Give an error if what follows is not a quantifier, but don't override
+ an error set by the quantifier reader (e.g. number overflow). */
+
+ else
+ {
+ if (!read_repeat_counts(&p, ptrend, NULL, NULL, errorcodeptr) &&
+ *errorcodeptr == 0)
+ *errorcodeptr = ERR37;
+ }
+ }
}
}
@@ -1462,6 +1510,7 @@ else
/* A number of Perl escapes are not handled by PCRE. We give an explicit
error. */
+ case CHAR_F:
case CHAR_l:
case CHAR_L:
*errorcodeptr = ERR37;
@@ -1719,6 +1768,9 @@ else
{
if (ptr < ptrend && *ptr == CHAR_LEFT_CURLY_BRACKET)
{
+#ifndef EBCDIC
+ COME_FROM_NU:
+#endif
if (++ptr >= ptrend || *ptr == CHAR_RIGHT_CURLY_BRACKET)
{
*errorcodeptr = ERR78;
@@ -1852,19 +1904,6 @@ else
}
}
-/* Perl supports \N{name} for character names, as well as plain \N for "not
-newline". PCRE does not support \N{name}. However, it does support
-quantification such as \N{2,3}. */
-
-if (escape == ESC_N && ptr < ptrend && *ptr == CHAR_LEFT_CURLY_BRACKET &&
- ptrend - ptr > 2)
- {
- PCRE2_SPTR p = ptr + 1;
- if (!read_repeat_counts(&p, ptrend, NULL, NULL, errorcodeptr) &&
- *errorcodeptr == 0)
- *errorcodeptr = ERR37;
- }
-
/* Set the pointer to the next character before returning. */
*ptrptr = ptr;
@@ -2251,11 +2290,14 @@ typedef struct nest_save {
#define NSF_RESET 0x0001u
#define NSF_CONDASSERT 0x0002u
-/* Of the options that are changeable within the pattern, these are tracked
-during parsing. The rest are used from META_OPTIONS items when compiling. */
+/* Options that are changeable within the pattern must be tracked during
+parsing. Some (e.g. PCRE2_EXTENDED) are implemented entirely during parsing,
+but all must be tracked so that META_OPTIONS items set the correct values for
+the main compiling phase. */
-#define PARSE_TRACKED_OPTIONS \
- (PCRE2_DUPNAMES|PCRE2_EXTENDED|PCRE2_EXTENDED_MORE|PCRE2_NO_AUTO_CAPTURE)
+#define PARSE_TRACKED_OPTIONS (PCRE2_CASELESS|PCRE2_DOTALL|PCRE2_DUPNAMES| \
+ PCRE2_EXTENDED|PCRE2_EXTENDED_MORE|PCRE2_MULTILINE|PCRE2_NO_AUTO_CAPTURE| \
+ PCRE2_UNGREEDY)
/* States used for analyzing ranges in character classes. The two OK values
must be last. */
@@ -2290,6 +2332,7 @@ uint32_t *previous_callout = NULL;
uint32_t *parsed_pattern = cb->parsed_pattern;
uint32_t *parsed_pattern_end = cb->parsed_pattern_end;
uint32_t meta_quantifier = 0;
+uint32_t add_after_mark = 0;
uint16_t nest_depth = 0;
int after_manual_callout = 0;
int expect_cond_assert = 0;
@@ -2434,11 +2477,17 @@ while (ptr < ptrend)
/* EITHER: not both options set */
((options & (PCRE2_EXTENDED | PCRE2_ALT_VERBNAMES)) !=
(PCRE2_EXTENDED | PCRE2_ALT_VERBNAMES)) ||
- /* OR: character > 255 */
- c > 255 ||
- /* OR: not a # comment or white space */
- (c != CHAR_NUMBER_SIGN && (cb->ctypes[c] & ctype_space) == 0)
- ))
+#ifdef SUPPORT_UNICODE
+ /* OR: character > 255 AND not Unicode Pattern White Space */
+ (c > 255 && (c|1) != 0x200f && (c|1) != 0x2029) ||
+#endif
+ /* OR: not a # comment or isspace() white space */
+ (c < 256 && c != CHAR_NUMBER_SIGN && (cb->ctypes[c] & ctype_space) == 0
+#ifdef SUPPORT_UNICODE
+ /* and not CHAR_NEL when Unicode is supported */
+ && c != CHAR_NEL
+#endif
+ )))
{
PCRE2_SIZE verbnamelength;
@@ -2461,6 +2510,16 @@ while (ptr < ptrend)
goto FAILED;
}
*verblengthptr = (uint32_t)verbnamelength;
+
+ /* If this name was on a verb such as (*ACCEPT) which does not continue,
+ a (*MARK) was generated for the name. We now add the original verb as the
+ next item. */
+
+ if (add_after_mark != 0)
+ {
+ *parsed_pattern++ = add_after_mark;
+ add_after_mark = 0;
+ }
break;
case CHAR_BACKSLASH:
@@ -2510,11 +2569,18 @@ while (ptr < ptrend)
/* Skip over whitespace and # comments in extended mode. Note that c is a
character, not a code unit, so we must not use MAX_255 to test its size
- because MAX_255 tests code units and is assumed TRUE in 8-bit mode. */
+ because MAX_255 tests code units and is assumed TRUE in 8-bit mode. The
+ whitespace characters are those designated as "Pattern White Space" by
+ Unicode, which are the isspace() characters plus CHAR_NEL (newline), which is
+ U+0085 in Unicode, plus U+200E, U+200F, U+2028, and U+2029. These are a
+ subset of space characters that match \h and \v. */
if ((options & PCRE2_EXTENDED) != 0)
{
if (c < 256 && (cb->ctypes[c] & ctype_space) != 0) continue;
+#ifdef SUPPORT_UNICODE
+ if (c == CHAR_NEL || (c|1) == 0x200f || (c|1) == 0x2029) continue;
+#endif
if (c == CHAR_NUMBER_SIGN)
{
while (ptr < ptrend)
@@ -3206,7 +3272,6 @@ while (ptr < ptrend)
tempptr = ptr;
escape = PRIV(check_escape)(&ptr, ptrend, &c, &errorcode,
options, TRUE, cb);
-
if (errorcode != 0)
{
CLASS_ESCAPE_FAILED:
@@ -3454,13 +3519,25 @@ while (ptr < ptrend)
if (*ptr++ == CHAR_COLON) /* Skip past : or ) */
{
- if (verbs[i].has_arg < 0) /* Argument is forbidden */
+ /* Some optional arguments can be treated as a preceding (*MARK) */
+
+ if (verbs[i].has_arg < 0)
{
- errorcode = ERR59;
- goto FAILED;
+ add_after_mark = verbs[i].meta;
+ *parsed_pattern++ = META_MARK;
}
- *parsed_pattern++ = verbs[i].meta +
- ((verbs[i].meta != META_MARK)? 0x00010000u:0);
+
+ /* The remaining verbs with arguments (except *MARK) need a different
+ opcode. */
+
+ else
+ {
+ *parsed_pattern++ = verbs[i].meta +
+ ((verbs[i].meta != META_MARK)? 0x00010000u:0);
+ }
+
+ /* Set up for reading the name in the main loop. */
+
verblengthptr = parsed_pattern++;
verbnamestart = ptr;
inverbname = TRUE;
@@ -3521,17 +3598,39 @@ while (ptr < ptrend)
else
{
+ BOOL hyphenok = TRUE;
+ uint32_t oldoptions = options;
+
top_nest->reset_group = 0;
top_nest->max_group = 0;
set = unset = 0;
optset = &set;
+ /* ^ at the start unsets imnsx and disables the subsequent use of - */
+
+ if (ptr < ptrend && *ptr == CHAR_CIRCUMFLEX_ACCENT)
+ {
+ options &= ~(PCRE2_CASELESS|PCRE2_MULTILINE|PCRE2_NO_AUTO_CAPTURE|
+ PCRE2_DOTALL|PCRE2_EXTENDED|PCRE2_EXTENDED_MORE);
+ hyphenok = FALSE;
+ ptr++;
+ }
+
while (ptr < ptrend && *ptr != CHAR_RIGHT_PARENTHESIS &&
*ptr != CHAR_COLON)
{
switch (*ptr++)
{
- case CHAR_MINUS: optset = &unset; break;
+ case CHAR_MINUS:
+ if (!hyphenok)
+ {
+ errorcode = ERR94;
+ ptr--; /* Correct the offset */
+ goto FAILED;
+ }
+ optset = &unset;
+ hyphenok = FALSE;
+ break;
case CHAR_J: /* Record that it changed in the external options */
*optset |= PCRE2_DUPNAMES;
@@ -3591,7 +3690,7 @@ while (ptr < ptrend)
/* If nothing changed, no need to record. */
- if (set != 0 || unset != 0)
+ if (options != oldoptions)
{
*parsed_pattern++ = META_OPTIONS;
*parsed_pattern++ = options;
@@ -3896,9 +3995,8 @@ while (ptr < ptrend)
if (*ptr == CHAR_DOT)
{
if (++ptr >= ptrend || !IS_DIGIT(*ptr)) goto BAD_VERSION_CONDITION;
- if (!read_number(&ptr, ptrend, -1, 99 , ERR79, &minor, &errorcode))
- goto FAILED;
- if (minor < 10) minor *= 10;
+ minor = (*ptr++ - CHAR_0) * 10;
+ if (IS_DIGIT(*ptr)) minor += *ptr++ - CHAR_0;
if (ptr >= ptrend || *ptr != CHAR_RIGHT_PARENTHESIS)
goto BAD_VERSION_CONDITION;
}
@@ -4261,11 +4359,11 @@ goto FAILED;
/*************************************************
-* Find first significant op code *
+* Find first significant opcode *
*************************************************/
/* This is called by several functions that scan a compiled expression looking
-for a fixed first character, or an anchoring op code etc. It skips over things
+for a fixed first character, or an anchoring opcode etc. It skips over things
that do not influence this. For some calls, it makes sense to skip negative
forward and all backward assertions, and also the \b assertion; for others it
does not.
@@ -5472,7 +5570,7 @@ for (;; pptr++)
set xclass = TRUE. Then, in the pre-compile phase, accumulate the length
of the extra data and reset the pointer. This is so that very large
classes that contain a zillion wide characters or Unicode property tests
- do not overwrite the work space (which is on the stack). */
+ do not overwrite the workspace (which is on the stack). */
if (class_uchardata > class_uchardata_base)
{
@@ -5563,7 +5661,7 @@ for (;; pptr++)
if (class_has_8bitchar > 0)
{
*code++ |= XCL_MAP;
- memmove(code + (32 / sizeof(PCRE2_UCHAR)), code,
+ (void)memmove(code + (32 / sizeof(PCRE2_UCHAR)), code,
CU2BYTES(class_uchardata - code));
if (negate_class && !xclass_has_prop)
for (i = 0; i < 32; i++) classbits[i] = ~classbits[i];
@@ -5655,6 +5753,7 @@ for (;; pptr++)
cb->had_pruneorskip = TRUE;
/* Fall through */
case META_MARK:
+ case META_COMMIT_ARG:
VERB_ARG:
*code++ = verbops[(meta - META_MARK) >> 16];
/* The length is in characters. */
@@ -6509,7 +6608,7 @@ for (;; pptr++)
/* Wrap the recursion call in OP_BRA brackets. */
- memmove(previous + 1 + LINK_SIZE, previous, CU2BYTES(1 + LINK_SIZE));
+ (void)memmove(previous + 1 + LINK_SIZE, previous, CU2BYTES(1 + LINK_SIZE));
op_previous = *previous = OP_BRA;
PUT(previous, 1, 2 + 2*LINK_SIZE);
previous[2 + 2*LINK_SIZE] = OP_KET;
@@ -6589,7 +6688,7 @@ for (;; pptr++)
if (repeat_max <= 1 || repeat_max == REPEAT_UNLIMITED)
{
- memmove(previous + 1, previous, CU2BYTES(len));
+ (void)memmove(previous + 1, previous, CU2BYTES(len));
code++;
if (repeat_max == 0)
{
@@ -6610,7 +6709,7 @@ for (;; pptr++)
else
{
int linkoffset;
- memmove(previous + 2 + LINK_SIZE, previous, CU2BYTES(len));
+ (void)memmove(previous + 2 + LINK_SIZE, previous, CU2BYTES(len));
code += 2 + LINK_SIZE;
*previous++ = OP_BRAZERO + repeat_type;
*previous++ = OP_BRA;
@@ -6811,7 +6910,7 @@ for (;; pptr++)
if (*bracode == OP_COND || *bracode == OP_SCOND)
{
int nlen = (int)(code - bracode);
- memmove(bracode + 1 + LINK_SIZE, bracode, CU2BYTES(nlen));
+ (void)memmove(bracode + 1 + LINK_SIZE, bracode, CU2BYTES(nlen));
code += 1 + LINK_SIZE;
nlen += 1 + LINK_SIZE;
*bracode = (*bracode == OP_COND)? OP_BRAPOS : OP_SBRAPOS;
@@ -7082,7 +7181,7 @@ for (;; pptr++)
else
{
- memmove(tempcode + 1 + LINK_SIZE, tempcode, CU2BYTES(len));
+ (void)memmove(tempcode + 1 + LINK_SIZE, tempcode, CU2BYTES(len));
code += 1 + LINK_SIZE;
len += 1 + LINK_SIZE;
tempcode[0] = OP_ONCE;
@@ -7460,7 +7559,7 @@ length of the BRA and KET and any extra code units that are required at the
beginning. We accumulate in a local variable to save frequent testing of
lengthptr for NULL. We cannot do this by looking at the value of 'code' at the
start and end of each alternative, because compiled items are discarded during
-the pre-compile phase so that the work space is not exceeded. */
+the pre-compile phase so that the workspace is not exceeded. */
length = 2 + 2*LINK_SIZE + skipunits;
@@ -7622,7 +7721,7 @@ for (;;)
{
if (cb->open_caps->flag)
{
- memmove(start_bracket + 1 + LINK_SIZE, start_bracket,
+ (void)memmove(start_bracket + 1 + LINK_SIZE, start_bracket,
CU2BYTES(code - start_bracket));
*start_bracket = OP_ONCE;
code += 1 + LINK_SIZE;
@@ -7765,10 +7864,11 @@ do {
if (!is_anchored(scode, bracket_map, cb, atomcount, TRUE)) return FALSE;
}
- /* Condition */
+ /* Condition. If there is no second branch, it can't be anchored. */
- else if (op == OP_COND)
+ else if (op == OP_COND || op == OP_SCOND)
{
+ if (scode[GET(scode,1)] != OP_ALT) return FALSE;
if (!is_anchored(scode, bracket_map, cb, atomcount, inassert))
return FALSE;
}
@@ -8003,6 +8103,7 @@ for (;;)
break;
case OP_MARK:
+ case OP_COMMIT_ARG:
case OP_PRUNE_ARG:
case OP_SKIP_ARG:
case OP_THEN_ARG:
@@ -8221,7 +8322,7 @@ for (i = 0; i < tablecount; i++)
if (crc < 0)
{
- memmove(slot + cb->name_entry_size, slot,
+ (void)memmove(slot + cb->name_entry_size, slot,
CU2BYTES((tablecount - i) * cb->name_entry_size));
break;
}
@@ -8311,6 +8412,7 @@ for (;; pptr++)
break;
case META_MARK: /* Add the length of the name. */
+ case META_COMMIT_ARG:
case META_PRUNE_ARG:
case META_SKIP_ARG:
case META_THEN_ARG:
@@ -8501,6 +8603,7 @@ for (;; pptr++)
goto EXIT;
case META_MARK:
+ case META_COMMIT_ARG:
case META_PRUNE_ARG:
case META_SKIP_ARG:
case META_THEN_ARG:
@@ -8572,6 +8675,32 @@ for (;; pptr++)
case META_LOOKAHEADNOT:
pptr = parsed_skip(pptr + 1, PSKIP_KET);
if (pptr == NULL) goto PARSED_SKIP_FAILED;
+
+ /* Also ignore any qualifiers that follow a lookahead assertion. */
+
+ switch (pptr[1])
+ {
+ case META_ASTERISK:
+ case META_ASTERISK_PLUS:
+ case META_ASTERISK_QUERY:
+ case META_PLUS:
+ case META_PLUS_PLUS:
+ case META_PLUS_QUERY:
+ case META_QUERY:
+ case META_QUERY_PLUS:
+ case META_QUERY_QUERY:
+ pptr++;
+ break;
+
+ case META_MINMAX:
+ case META_MINMAX_PLUS:
+ case META_MINMAX_QUERY:
+ pptr += 3;
+ break;
+
+ default:
+ break;
+ }
break;
/* Lookbehinds can be ignored, but must themselves be checked. */
@@ -8942,6 +9071,7 @@ for (pptr = cb->parsed_pattern; *pptr != META_END; pptr++)
break;
case META_MARK:
+ case META_COMMIT_ARG:
case META_PRUNE_ARG:
case META_SKIP_ARG:
case META_THEN_ARG:
diff --git a/thirdparty/pcre2/src/pcre2_convert.c b/thirdparty/pcre2/src/pcre2_convert.c
index bdf9b86df6..1dd5c337dc 100644
--- a/thirdparty/pcre2/src/pcre2_convert.c
+++ b/thirdparty/pcre2/src/pcre2_convert.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2017 University of Cambridge
+ New API code Copyright (c) 2016-2018 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -1066,11 +1066,12 @@ BOOL utf = (options & PCRE2_CONVERT_UTF) != 0;
uint32_t pattype = options & TYPE_OPTIONS;
if (pattern == NULL || bufflenptr == NULL) return PCRE2_ERROR_NULL;
+
if ((options & ~ALL_OPTIONS) != 0 || /* Undefined bit set */
(pattype & (~pattype+1)) != pattype || /* More than one type set */
pattype == 0) /* No type set */
{
- *bufflenptr = 0; /* Error offset */
+ *bufflenptr = 0; /* Error offset */
return PCRE2_ERROR_BADOPTION;
}
@@ -1081,7 +1082,11 @@ if (ccontext == NULL) ccontext =
/* Check UTF if required. */
#ifndef SUPPORT_UNICODE
-if (utf) return PCRE2_ERROR_UNICODE_NOT_SUPPORTED;
+if (utf)
+ {
+ *bufflenptr = 0; /* Error offset */
+ return PCRE2_ERROR_UNICODE_NOT_SUPPORTED;
+ }
#else
if (utf && (options & PCRE2_CONVERT_NO_UTF_CHECK) == 0)
{
@@ -1126,6 +1131,7 @@ for (i = 0; i < 2; i++)
break;
default:
+ *bufflenptr = 0; /* Error offset */
return PCRE2_ERROR_INTERNAL;
}
diff --git a/thirdparty/pcre2/src/pcre2_dfa_match.c b/thirdparty/pcre2/src/pcre2_dfa_match.c
index c6184ff5e9..9b43237da7 100644
--- a/thirdparty/pcre2/src/pcre2_dfa_match.c
+++ b/thirdparty/pcre2/src/pcre2_dfa_match.c
@@ -181,7 +181,8 @@ static const uint8_t coptable[] = {
0, 0, 0, /* BRAZERO, BRAMINZERO, BRAPOSZERO */
0, 0, 0, /* MARK, PRUNE, PRUNE_ARG */
0, 0, 0, 0, /* SKIP, SKIP_ARG, THEN, THEN_ARG */
- 0, 0, 0, 0, /* COMMIT, FAIL, ACCEPT, ASSERT_ACCEPT */
+ 0, 0, /* COMMIT, COMMIT_ARG */
+ 0, 0, 0, /* FAIL, ACCEPT, ASSERT_ACCEPT */
0, 0, 0 /* CLOSE, SKIPZERO, DEFINE */
};
@@ -254,7 +255,8 @@ static const uint8_t poptable[] = {
0, 0, 0, /* BRAZERO, BRAMINZERO, BRAPOSZERO */
0, 0, 0, /* MARK, PRUNE, PRUNE_ARG */
0, 0, 0, 0, /* SKIP, SKIP_ARG, THEN, THEN_ARG */
- 0, 0, 0, 0, /* COMMIT, FAIL, ACCEPT, ASSERT_ACCEPT */
+ 0, 0, /* COMMIT, COMMIT_ARG */
+ 0, 0, 0, /* FAIL, ACCEPT, ASSERT_ACCEPT */
0, 0, 0 /* CLOSE, SKIPZERO, DEFINE */
};
@@ -292,6 +294,35 @@ typedef struct stateblock {
#define INTS_PER_STATEBLOCK (int)(sizeof(stateblock)/sizeof(int))
+/* Before version 10.32 the recursive calls of internal_dfa_match() were passed
+local working space and output vectors that were created on the stack. This has
+caused issues for some patterns, especially in small-stack environments such as
+Windows. A new scheme is now in use which sets up a vector on the stack, but if
+this is too small, heap memory is used, up to the heap_limit. The main
+parameters are all numbers of ints because the workspace is a vector of ints.
+
+The size of the starting stack vector, DFA_START_RWS_SIZE, is in bytes, and is
+defined in pcre2_internal.h so as to be available to pcre2test when it is
+finding the minimum heap requirement for a match. */
+
+#define OVEC_UNIT (sizeof(PCRE2_SIZE)/sizeof(int))
+
+#define RWS_BASE_SIZE (DFA_START_RWS_SIZE/sizeof(int)) /* Stack vector */
+#define RWS_RSIZE 1000 /* Work size for recursion */
+#define RWS_OVEC_RSIZE (1000*OVEC_UNIT) /* Ovector for recursion */
+#define RWS_OVEC_OSIZE (2*OVEC_UNIT) /* Ovector in other cases */
+
+/* This structure is at the start of each workspace block. */
+
+typedef struct RWS_anchor {
+ struct RWS_anchor *next;
+ unsigned int size; /* Number of ints */
+ unsigned int free; /* Number of ints */
+} RWS_anchor;
+
+#define RWS_ANCHOR_SIZE (sizeof(RWS_anchor)/sizeof(int))
+
+
/*************************************************
* Process a callout *
@@ -354,6 +385,61 @@ return (mb->callout)(cb, mb->callout_data);
/*************************************************
+* Expand local workspace memory *
+*************************************************/
+
+/* This function is called when internal_dfa_match() is about to be called
+recursively and there is insufficient working space left in the current
+workspace block. If there's an existing next block, use it; otherwise get a new
+block unless the heap limit is reached.
+
+Arguments:
+ rwsptr pointer to block pointer (updated)
+ ovecsize space needed for an ovector
+ mb the match block
+
+Returns: 0 rwsptr has been updated
+ !0 an error code
+*/
+
+static int
+more_workspace(RWS_anchor **rwsptr, unsigned int ovecsize, dfa_match_block *mb)
+{
+RWS_anchor *rws = *rwsptr;
+RWS_anchor *new;
+
+if (rws->next != NULL)
+ {
+ new = rws->next;
+ }
+
+/* All sizes are in units of sizeof(int), except for mb->heaplimit, which is in
+kibibytes. */
+
+else
+ {
+ unsigned int newsize = rws->size * 2;
+ unsigned int heapleft = (unsigned int)
+ (((1024/sizeof(int))*mb->heap_limit - mb->heap_used));
+ if (newsize > heapleft) newsize = heapleft;
+ if (newsize < RWS_RSIZE + ovecsize + RWS_ANCHOR_SIZE)
+ return PCRE2_ERROR_HEAPLIMIT;
+ new = mb->memctl.malloc(newsize*sizeof(int), mb->memctl.memory_data);
+ if (new == NULL) return PCRE2_ERROR_NOMEMORY;
+ mb->heap_used += newsize;
+ new->next = NULL;
+ new->size = newsize;
+ rws->next = new;
+ }
+
+new->free = new->size - RWS_ANCHOR_SIZE;
+*rwsptr = new;
+return 0;
+}
+
+
+
+/*************************************************
* Match a Regular Expression - DFA engine *
*************************************************/
@@ -431,7 +517,8 @@ internal_dfa_match(
uint32_t offsetcount,
int *workspace,
int wscount,
- uint32_t rlevel)
+ uint32_t rlevel,
+ int *RWS)
{
stateblock *active_states, *new_states, *temp_states;
stateblock *next_active_state, *next_new_state;
@@ -788,7 +875,7 @@ for (;;)
else if (match_count > 0 && ++match_count * 2 > (int)offsetcount)
match_count = 0;
count = ((match_count == 0)? (int)offsetcount : match_count * 2) - 2;
- if (count > 0) memmove(offsets + 2, offsets,
+ if (count > 0) (void)memmove(offsets + 2, offsets,
(size_t)count * sizeof(PCRE2_SIZE));
if (offsetcount >= 2)
{
@@ -2587,10 +2674,22 @@ for (;;)
case OP_ASSERTBACK:
case OP_ASSERTBACK_NOT:
{
- PCRE2_SPTR endasscode = code + GET(code, 1);
- PCRE2_SIZE local_offsets[2];
int rc;
- int local_workspace[1000];
+ int *local_workspace;
+ PCRE2_SIZE *local_offsets;
+ PCRE2_SPTR endasscode = code + GET(code, 1);
+ RWS_anchor *rws = (RWS_anchor *)RWS;
+
+ if (rws->free < RWS_RSIZE + RWS_OVEC_OSIZE)
+ {
+ rc = more_workspace(&rws, RWS_OVEC_OSIZE, mb);
+ if (rc != 0) return rc;
+ RWS = (int *)rws;
+ }
+
+ local_offsets = (PCRE2_SIZE *)(RWS + rws->size - rws->free);
+ local_workspace = ((int *)local_offsets) + RWS_OVEC_OSIZE;
+ rws->free -= RWS_RSIZE + RWS_OVEC_OSIZE;
while (*endasscode == OP_ALT) endasscode += GET(endasscode, 1);
@@ -2600,10 +2699,13 @@ for (;;)
ptr, /* where we currently are */
(PCRE2_SIZE)(ptr - start_subject), /* start offset */
local_offsets, /* offset vector */
- sizeof(local_offsets)/sizeof(PCRE2_SIZE), /* size of same */
+ RWS_OVEC_OSIZE/OVEC_UNIT, /* size of same */
local_workspace, /* workspace vector */
- sizeof(local_workspace)/sizeof(int), /* size of same */
- rlevel); /* function recursion level */
+ RWS_RSIZE, /* size of same */
+ rlevel, /* function recursion level */
+ RWS); /* recursion workspace */
+
+ rws->free += RWS_RSIZE + RWS_OVEC_OSIZE;
if (rc < 0 && rc != PCRE2_ERROR_NOMATCH) return rc;
if ((rc >= 0) == (codevalue == OP_ASSERT || codevalue == OP_ASSERTBACK))
@@ -2615,8 +2717,6 @@ for (;;)
case OP_COND:
case OP_SCOND:
{
- PCRE2_SIZE local_offsets[1000];
- int local_workspace[1000];
int codelink = (int)GET(code, 1);
PCRE2_UCHAR condcode;
@@ -2673,8 +2773,22 @@ for (;;)
else
{
int rc;
+ int *local_workspace;
+ PCRE2_SIZE *local_offsets;
PCRE2_SPTR asscode = code + LINK_SIZE + 1;
PCRE2_SPTR endasscode = asscode + GET(asscode, 1);
+ RWS_anchor *rws = (RWS_anchor *)RWS;
+
+ if (rws->free < RWS_RSIZE + RWS_OVEC_OSIZE)
+ {
+ rc = more_workspace(&rws, RWS_OVEC_OSIZE, mb);
+ if (rc != 0) return rc;
+ RWS = (int *)rws;
+ }
+
+ local_offsets = (PCRE2_SIZE *)(RWS + rws->size - rws->free);
+ local_workspace = ((int *)local_offsets) + RWS_OVEC_OSIZE;
+ rws->free -= RWS_RSIZE + RWS_OVEC_OSIZE;
while (*endasscode == OP_ALT) endasscode += GET(endasscode, 1);
@@ -2684,10 +2798,13 @@ for (;;)
ptr, /* where we currently are */
(PCRE2_SIZE)(ptr - start_subject), /* start offset */
local_offsets, /* offset vector */
- sizeof(local_offsets)/sizeof(PCRE2_SIZE), /* size of same */
+ RWS_OVEC_OSIZE/OVEC_UNIT, /* size of same */
local_workspace, /* workspace vector */
- sizeof(local_workspace)/sizeof(int), /* size of same */
- rlevel); /* function recursion level */
+ RWS_RSIZE, /* size of same */
+ rlevel, /* function recursion level */
+ RWS); /* recursion workspace */
+
+ rws->free += RWS_RSIZE + RWS_OVEC_OSIZE;
if (rc < 0 && rc != PCRE2_ERROR_NOMATCH) return rc;
if ((rc >= 0) ==
@@ -2702,13 +2819,25 @@ for (;;)
/*-----------------------------------------------------------------*/
case OP_RECURSE:
{
+ int rc;
+ int *local_workspace;
+ PCRE2_SIZE *local_offsets;
+ RWS_anchor *rws = (RWS_anchor *)RWS;
dfa_recursion_info *ri;
- PCRE2_SIZE local_offsets[1000];
- int local_workspace[1000];
PCRE2_SPTR callpat = start_code + GET(code, 1);
uint32_t recno = (callpat == mb->start_code)? 0 :
GET2(callpat, 1 + LINK_SIZE);
- int rc;
+
+ if (rws->free < RWS_RSIZE + RWS_OVEC_RSIZE)
+ {
+ rc = more_workspace(&rws, RWS_OVEC_RSIZE, mb);
+ if (rc != 0) return rc;
+ RWS = (int *)rws;
+ }
+
+ local_offsets = (PCRE2_SIZE *)(RWS + rws->size - rws->free);
+ local_workspace = ((int *)local_offsets) + RWS_OVEC_RSIZE;
+ rws->free -= RWS_RSIZE + RWS_OVEC_RSIZE;
/* Check for repeating a recursion without advancing the subject
pointer. This should catch convoluted mutual recursions. (Some simple
@@ -2732,11 +2861,13 @@ for (;;)
ptr, /* where we currently are */
(PCRE2_SIZE)(ptr - start_subject), /* start offset */
local_offsets, /* offset vector */
- sizeof(local_offsets)/sizeof(PCRE2_SIZE), /* size of same */
+ RWS_OVEC_RSIZE/OVEC_UNIT, /* size of same */
local_workspace, /* workspace vector */
- sizeof(local_workspace)/sizeof(int), /* size of same */
- rlevel); /* function recursion level */
+ RWS_RSIZE, /* size of same */
+ rlevel, /* function recursion level */
+ RWS); /* recursion workspace */
+ rws->free += RWS_RSIZE + RWS_OVEC_RSIZE;
mb->recursive = new_recursive.prevrec; /* Done this recursion */
/* Ran out of internal offsets */
@@ -2782,10 +2913,25 @@ for (;;)
case OP_SCBRAPOS:
case OP_BRAPOSZERO:
{
+ int rc;
+ int *local_workspace;
+ PCRE2_SIZE *local_offsets;
PCRE2_SIZE charcount, matched_count;
PCRE2_SPTR local_ptr = ptr;
+ RWS_anchor *rws = (RWS_anchor *)RWS;
BOOL allow_zero;
+ if (rws->free < RWS_RSIZE + RWS_OVEC_OSIZE)
+ {
+ rc = more_workspace(&rws, RWS_OVEC_OSIZE, mb);
+ if (rc != 0) return rc;
+ RWS = (int *)rws;
+ }
+
+ local_offsets = (PCRE2_SIZE *)(RWS + rws->size - rws->free);
+ local_workspace = ((int *)local_offsets) + RWS_OVEC_OSIZE;
+ rws->free -= RWS_RSIZE + RWS_OVEC_OSIZE;
+
if (codevalue == OP_BRAPOSZERO)
{
allow_zero = TRUE;
@@ -2798,19 +2944,17 @@ for (;;)
for (matched_count = 0;; matched_count++)
{
- PCRE2_SIZE local_offsets[2];
- int local_workspace[1000];
-
- int rc = internal_dfa_match(
+ rc = internal_dfa_match(
mb, /* fixed match data */
code, /* this subexpression's code */
local_ptr, /* where we currently are */
(PCRE2_SIZE)(ptr - start_subject), /* start offset */
local_offsets, /* offset vector */
- sizeof(local_offsets)/sizeof(PCRE2_SIZE), /* size of same */
+ RWS_OVEC_OSIZE/OVEC_UNIT, /* size of same */
local_workspace, /* workspace vector */
- sizeof(local_workspace)/sizeof(int), /* size of same */
- rlevel); /* function recursion level */
+ RWS_RSIZE, /* size of same */
+ rlevel, /* function recursion level */
+ RWS); /* recursion workspace */
/* Failed to match */
@@ -2827,6 +2971,8 @@ for (;;)
local_ptr += charcount; /* Advance temporary position ptr */
}
+ rws->free += RWS_RSIZE + RWS_OVEC_OSIZE;
+
/* At this point we have matched the subpattern matched_count
times, and local_ptr is pointing to the character after the end of the
last match. */
@@ -2869,19 +3015,35 @@ for (;;)
/*-----------------------------------------------------------------*/
case OP_ONCE:
{
- PCRE2_SIZE local_offsets[2];
- int local_workspace[1000];
+ int rc;
+ int *local_workspace;
+ PCRE2_SIZE *local_offsets;
+ RWS_anchor *rws = (RWS_anchor *)RWS;
- int rc = internal_dfa_match(
+ if (rws->free < RWS_RSIZE + RWS_OVEC_OSIZE)
+ {
+ rc = more_workspace(&rws, RWS_OVEC_OSIZE, mb);
+ if (rc != 0) return rc;
+ RWS = (int *)rws;
+ }
+
+ local_offsets = (PCRE2_SIZE *)(RWS + rws->size - rws->free);
+ local_workspace = ((int *)local_offsets) + RWS_OVEC_OSIZE;
+ rws->free -= RWS_RSIZE + RWS_OVEC_OSIZE;
+
+ rc = internal_dfa_match(
mb, /* fixed match data */
code, /* this subexpression's code */
ptr, /* where we currently are */
(PCRE2_SIZE)(ptr - start_subject), /* start offset */
local_offsets, /* offset vector */
- sizeof(local_offsets)/sizeof(PCRE2_SIZE), /* size of same */
+ RWS_OVEC_OSIZE/OVEC_UNIT, /* size of same */
local_workspace, /* workspace vector */
- sizeof(local_workspace)/sizeof(int), /* size of same */
- rlevel); /* function recursion level */
+ RWS_RSIZE, /* size of same */
+ rlevel, /* function recursion level */
+ RWS); /* recursion workspace */
+
+ rws->free += RWS_RSIZE + RWS_OVEC_OSIZE;
if (rc >= 0)
{
@@ -3063,6 +3225,7 @@ pcre2_dfa_match(const pcre2_code *code, PCRE2_SPTR subject, PCRE2_SIZE length,
PCRE2_SIZE start_offset, uint32_t options, pcre2_match_data *match_data,
pcre2_match_context *mcontext, int *workspace, PCRE2_SIZE wscount)
{
+int rc;
const pcre2_real_code *re = (const pcre2_real_code *)code;
PCRE2_SPTR start_match;
@@ -3071,9 +3234,9 @@ PCRE2_SPTR bumpalong_limit;
PCRE2_SPTR req_cu_ptr;
BOOL utf, anchored, startline, firstline;
-
BOOL has_first_cu = FALSE;
BOOL has_req_cu = FALSE;
+
PCRE2_UCHAR first_cu = 0;
PCRE2_UCHAR first_cu2 = 0;
PCRE2_UCHAR req_cu = 0;
@@ -3088,6 +3251,17 @@ pcre2_callout_block cb;
dfa_match_block actual_match_block;
dfa_match_block *mb = &actual_match_block;
+/* Set up a starting block of memory for use during recursive calls to
+internal_dfa_match(). By putting this on the stack, it minimizes resource use
+in the case when it is not needed. If this is too small, more memory is
+obtained from the heap. At the start of each block is an anchor structure.*/
+
+int base_recursion_workspace[RWS_BASE_SIZE];
+RWS_anchor *rws = (RWS_anchor *)base_recursion_workspace;
+rws->next = NULL;
+rws->size = RWS_BASE_SIZE;
+rws->free = RWS_BASE_SIZE - RWS_ANCHOR_SIZE;
+
/* A length equal to PCRE2_ZERO_TERMINATED implies a zero-terminated
subject string. */
@@ -3184,6 +3358,7 @@ if (mcontext == NULL)
mb->memctl = re->memctl;
mb->match_limit = PRIV(default_match_context).match_limit;
mb->match_limit_depth = PRIV(default_match_context).depth_limit;
+ mb->heap_limit = PRIV(default_match_context).heap_limit;
}
else
{
@@ -3198,6 +3373,7 @@ else
mb->memctl = mcontext->memctl;
mb->match_limit = mcontext->match_limit;
mb->match_limit_depth = mcontext->depth_limit;
+ mb->heap_limit = mcontext->heap_limit;
}
if (mb->match_limit > re->limit_match)
@@ -3206,6 +3382,9 @@ if (mb->match_limit > re->limit_match)
if (mb->match_limit_depth > re->limit_depth)
mb->match_limit_depth = re->limit_depth;
+if (mb->heap_limit > re->limit_heap)
+ mb->heap_limit = re->limit_heap;
+
mb->start_code = (PCRE2_UCHAR *)((uint8_t *)re + sizeof(pcre2_real_code)) +
re->name_count * re->name_entry_size;
mb->tables = re->tables;
@@ -3215,6 +3394,7 @@ mb->start_offset = start_offset;
mb->moptions = options;
mb->poptions = re->overall_options;
mb->match_call_count = 0;
+mb->heap_used = 0;
/* Process the \R and newline settings. */
@@ -3351,8 +3531,6 @@ a match. */
for (;;)
{
- int rc;
-
/* ----------------- Start of match optimizations ---------------- */
/* There are some optimizations that avoid running the match if a known
@@ -3544,7 +3722,7 @@ for (;;)
in characters, we treat it as code units to avoid spending too much time
in this optimization. */
- if (end_subject - start_match < re->minlength) return PCRE2_ERROR_NOMATCH;
+ if (end_subject - start_match < re->minlength) goto NOMATCH_EXIT;
/* If req_cu is set, we know that that code unit must appear in the
subject for the match to succeed. If the first code unit is set, req_cu
@@ -3621,7 +3799,8 @@ for (;;)
(uint32_t)match_data->oveccount * 2, /* actual size of same */
workspace, /* workspace vector */
(int)wscount, /* size of same */
- 0); /* function recurse level */
+ 0, /* function recurse level */
+ base_recursion_workspace); /* initial workspace for recursion */
/* Anything other than "no match" means we are done, always; otherwise, carry
on only if not anchored. */
@@ -3637,7 +3816,7 @@ for (;;)
match_data->rightchar = (PCRE2_SIZE)( mb->last_used_ptr - subject);
match_data->startchar = (PCRE2_SIZE)(start_match - subject);
match_data->rc = rc;
- return rc;
+ goto EXIT;
}
/* Advance to the next subject character unless we are at the end of a line
@@ -3668,8 +3847,18 @@ for (;;)
} /* "Bumpalong" loop */
+NOMATCH_EXIT:
+rc = PCRE2_ERROR_NOMATCH;
+
+EXIT:
+while (rws->next != NULL)
+ {
+ RWS_anchor *next = rws->next;
+ rws->next = next->next;
+ mb->memctl.free(next, mb->memctl.memory_data);
+ }
-return PCRE2_ERROR_NOMATCH;
+return rc;
}
/* End of pcre2_dfa_match.c */
diff --git a/thirdparty/pcre2/src/pcre2_error.c b/thirdparty/pcre2/src/pcre2_error.c
index d98cae9963..4b3b3f1bc0 100644
--- a/thirdparty/pcre2/src/pcre2_error.c
+++ b/thirdparty/pcre2/src/pcre2_error.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2017 University of Cambridge
+ New API code Copyright (c) 2016-2018 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -107,7 +107,7 @@ static const unsigned char compile_error_texts[] =
/* 35 */
"lookbehind is too complicated\0"
"\\C is not allowed in a lookbehind assertion in UTF-" XSTRING(PCRE2_CODE_UNIT_WIDTH) " mode\0"
- "PCRE does not support \\L, \\l, \\N{name}, \\U, or \\u\0"
+ "PCRE2 does not support \\F, \\L, \\l, \\N{name}, \\U, or \\u\0"
"number after (?C is greater than 255\0"
"closing parenthesis for (?C expected\0"
/* 40 */
@@ -133,7 +133,8 @@ static const unsigned char compile_error_texts[] =
"internal error: unknown newline setting\0"
"\\g is not followed by a braced, angle-bracketed, or quoted name/number or by a plain number\0"
"(?R (recursive pattern call) must be followed by a closing parenthesis\0"
- "an argument is not allowed for (*ACCEPT), (*FAIL), or (*COMMIT)\0"
+ /* "an argument is not allowed for (*ACCEPT), (*FAIL), or (*COMMIT)\0" */
+ "obsolete error (should not occur)\0" /* Was the above */
/* 60 */
"(*VERB) not recognized or malformed\0"
"group number is too big\0"
@@ -160,7 +161,7 @@ static const unsigned char compile_error_texts[] =
"using UCP is disabled by the application\0"
"name is too long in (*MARK), (*PRUNE), (*SKIP), or (*THEN)\0"
"character code point value in \\u.... sequence is too large\0"
- "digits missing in \\x{} or \\o{}\0"
+ "digits missing in \\x{} or \\o{} or \\N{U+}\0"
"syntax error or number too big in (?(VERSION condition\0"
/* 80 */
"internal error: unknown opcode in auto_possessify()\0"
@@ -178,6 +179,8 @@ static const unsigned char compile_error_texts[] =
"internal error: bad code value in parsed_skip()\0"
"PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES is not allowed in UTF-16 mode\0"
"invalid option bits with PCRE2_LITERAL\0"
+ "\\N{U+dddd} is supported only in Unicode (UTF) mode\0"
+ "invalid hyphen in option setting\0"
;
/* Match-time and UTF error texts are in the same format. */
@@ -255,11 +258,13 @@ static const unsigned char match_error_texts[] =
"expected closing curly bracket in replacement string\0"
"bad substitution in replacement string\0"
/* 60 */
- "match with end before start is not supported\0"
+ "match with end before start or start moved backwards is not supported\0"
"too many replacements (more than INT_MAX)\0"
"bad serialized data\0"
"heap limit exceeded\0"
"invalid syntax\0"
+ /* 65 */
+ "internal error - duplicate substitution match\0"
;
diff --git a/thirdparty/pcre2/src/pcre2_extuni.c b/thirdparty/pcre2/src/pcre2_extuni.c
index 11a0bfbdd6..237211abf7 100644
--- a/thirdparty/pcre2/src/pcre2_extuni.c
+++ b/thirdparty/pcre2/src/pcre2_extuni.c
@@ -129,11 +129,11 @@ while (eptr < end_subject)
if ((ricount & 1) != 0) break; /* Grapheme break required */
}
- /* If Extend follows E_Base[_GAZ] do not update lgb; this allows
- any number of Extend before a following E_Modifier. */
+ /* If Extend or ZWJ follows Extended_Pictographic, do not update lgb; this
+ allows any number of them before a following Extended_Pictographic. */
- if (rgb != ucp_gbExtend ||
- (lgb != ucp_gbE_Base && lgb != ucp_gbE_Base_GAZ))
+ if ((rgb != ucp_gbExtend && rgb != ucp_gbZWJ) ||
+ lgb != ucp_gbExtended_Pictographic)
lgb = rgb;
eptr += len;
diff --git a/thirdparty/pcre2/src/pcre2_find_bracket.c b/thirdparty/pcre2/src/pcre2_find_bracket.c
index 357385a11c..70baa1394f 100644
--- a/thirdparty/pcre2/src/pcre2_find_bracket.c
+++ b/thirdparty/pcre2/src/pcre2_find_bracket.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016 University of Cambridge
+ New API code Copyright (c) 2016-2018 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -131,6 +131,7 @@ for (;;)
break;
case OP_MARK:
+ case OP_COMMIT_ARG:
case OP_PRUNE_ARG:
case OP_SKIP_ARG:
case OP_THEN_ARG:
diff --git a/thirdparty/pcre2/src/pcre2_internal.h b/thirdparty/pcre2/src/pcre2_internal.h
index 3db9d604f4..8750f2f174 100644
--- a/thirdparty/pcre2/src/pcre2_internal.h
+++ b/thirdparty/pcre2/src/pcre2_internal.h
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2017 University of Cambridge
+ New API code Copyright (c) 2016-2018 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -165,6 +165,16 @@ by "configure". */
#define INT64_OR_DOUBLE double
#endif
+/* External (in the C sense) functions and tables that are private to the
+libraries are always referenced using the PRIV macro. This makes it possible
+for pcre2test.c to include some of the source files from the libraries using a
+different PRIV definition to avoid name clashes. It also makes it clear in the
+code that a non-static object is being referenced. */
+
+#ifndef PRIV
+#define PRIV(name) _pcre2_##name
+#endif
+
/* When compiling for use with the Virtual Pascal compiler, these functions
need to have their names changed. PCRE2 must be compiled with the -DVPCOMPAT
option on the command line. */
@@ -178,50 +188,15 @@ option on the command line. */
#define memset(s,c,n) _memset(s,c,n)
#else /* VPCOMPAT */
-/* To cope with SunOS4 and other systems that lack memmove() but have bcopy(),
-define a macro for memmove() if HAVE_MEMMOVE is false, provided that HAVE_BCOPY
-is set. Otherwise, include an emulating function for those systems that have
-neither (there some non-Unix environments where this is the case). */
+/* Otherwise, to cope with SunOS4 and other systems that lack memmove(), define
+a macro that calls an emulating function. */
#ifndef HAVE_MEMMOVE
-#undef memmove /* some systems may have a macro */
-#ifdef HAVE_BCOPY
-#define memmove(a, b, c) bcopy(b, a, c)
-#else /* HAVE_BCOPY */
-static void *
-pcre2_memmove(void *d, const void *s, size_t n)
-{
-size_t i;
-unsigned char *dest = (unsigned char *)d;
-const unsigned char *src = (const unsigned char *)s;
-if (dest > src)
- {
- dest += n;
- src += n;
- for (i = 0; i < n; ++i) *(--dest) = *(--src);
- return (void *)dest;
- }
-else
- {
- for (i = 0; i < n; ++i) *dest++ = *src++;
- return (void *)(dest - n);
- }
-}
-#define memmove(a, b, c) pcre2_memmove(a, b, c)
-#endif /* not HAVE_BCOPY */
+#undef memmove /* Some systems may have a macro */
+#define memmove(a, b, c) PRIV(memmove)(a, b, c)
#endif /* not HAVE_MEMMOVE */
#endif /* not VPCOMPAT */
-/* External (in the C sense) functions and tables that are private to the
-libraries are always referenced using the PRIV macro. This makes it possible
-for pcre2test.c to include some of the source files from the libraries using a
-different PRIV definition to avoid name clashes. It also makes it clear in the
-code that a non-static object is being referenced. */
-
-#ifndef PRIV
-#define PRIV(name) _pcre2_##name
-#endif
-
/* This is an unsigned int value that no UTF character can ever have, as
Unicode doesn't go beyond 0x0010ffff. */
@@ -247,12 +222,17 @@ not rely on this. */
pcre2_match() is allocated on the system stack, of this size (bytes). The size
must be a multiple of sizeof(PCRE2_SPTR) in all environments, so making it a
multiple of 8 is best. Typical frame sizes are a few hundred bytes (it depends
-on the number of capturing parentheses) so 20K handles quite a few frames. A
+on the number of capturing parentheses) so 20KiB handles quite a few frames. A
larger vector on the heap is obtained for patterns that need more frames. The
maximum size of this can be limited. */
#define START_FRAMES_SIZE 20480
+/* Similarly, for DFA matching, an initial internal workspace vector is
+allocated on the stack. */
+
+#define DFA_START_RWS_SIZE 30720
+
/* Define the default BSR convention. */
#ifdef BSR_ANYCRLF
@@ -585,14 +565,15 @@ these tables. */
#define cbit_cntrl 288 /* [:cntrl:] */
#define cbit_length 320 /* Length of the cbits table */
-/* Bit definitions for entries in the ctypes table. */
+/* Bit definitions for entries in the ctypes table. Do not change these values
+without checking pcre2_jit_compile.c, which has an assertion to ensure that
+ctype_word has the value 16. */
#define ctype_space 0x01
#define ctype_letter 0x02
#define ctype_digit 0x04
-#define ctype_xdigit 0x08
+#define ctype_xdigit 0x08 /* not actually used any more */
#define ctype_word 0x10 /* alphanumeric or '_' */
-#define ctype_meta 0x80 /* regexp meta char or zero (end pattern) */
/* Offsets of the various tables from the base tables pointer, and
total length of the tables. */
@@ -1267,36 +1248,6 @@ contain characters with values greater than 255. */
#define XCL_PROP 3 /* Unicode property (2-byte property code follows) */
#define XCL_NOTPROP 4 /* Unicode inverted property (ditto) */
-/* Escape items that are just an encoding of a particular data value. These
-appear in the escapes[] table in pcre2_compile.c as positive numbers. */
-
-#ifndef ESC_a
-#define ESC_a CHAR_BEL
-#endif
-
-#ifndef ESC_e
-#define ESC_e CHAR_ESC
-#endif
-
-#ifndef ESC_f
-#define ESC_f CHAR_FF
-#endif
-
-#ifndef ESC_n
-#define ESC_n CHAR_LF
-#endif
-
-#ifndef ESC_r
-#define ESC_r CHAR_CR
-#endif
-
-/* We can't officially use ESC_t because it is a POSIX reserved identifier
-(presumably because of all the others like size_t). */
-
-#ifndef ESC_tee
-#define ESC_tee CHAR_HT
-#endif
-
/* These are escaped items that aren't just an encoding of a particular data
value such as \n. They must have non-zero values, as check_escape() returns 0
for a data character. In the escapes[] table in pcre2_compile.c their values
@@ -1578,23 +1529,26 @@ enum {
OP_THEN, /* 155 */
OP_THEN_ARG, /* 156 same, but with argument */
OP_COMMIT, /* 157 */
+ OP_COMMIT_ARG, /* 158 same, but with argument */
- /* These are forced failure and success verbs */
+ /* These are forced failure and success verbs. FAIL and ACCEPT do accept an
+ argument, but these cases can be compiled as, for example, (*MARK:X)(*FAIL)
+ without the need for a special opcode. */
- OP_FAIL, /* 158 */
- OP_ACCEPT, /* 159 */
- OP_ASSERT_ACCEPT, /* 160 Used inside assertions */
- OP_CLOSE, /* 161 Used before OP_ACCEPT to close open captures */
+ OP_FAIL, /* 159 */
+ OP_ACCEPT, /* 160 */
+ OP_ASSERT_ACCEPT, /* 161 Used inside assertions */
+ OP_CLOSE, /* 162 Used before OP_ACCEPT to close open captures */
/* This is used to skip a subpattern with a {0} quantifier */
- OP_SKIPZERO, /* 162 */
+ OP_SKIPZERO, /* 163 */
/* This is used to identify a DEFINE group during compilation so that it can
be checked for having only one branch. It is changed to OP_FALSE before
compilation finishes. */
- OP_DEFINE, /* 163 */
+ OP_DEFINE, /* 164 */
/* This is not an opcode, but is used to check that tables indexed by opcode
are the correct length, in order to catch updating errors - there have been
@@ -1650,7 +1604,7 @@ some cases doesn't actually use these names at all). */
"Cond false", "Cond true", \
"Brazero", "Braminzero", "Braposzero", \
"*MARK", "*PRUNE", "*PRUNE", "*SKIP", "*SKIP", \
- "*THEN", "*THEN", "*COMMIT", "*FAIL", \
+ "*THEN", "*THEN", "*COMMIT", "*COMMIT", "*FAIL", \
"*ACCEPT", "*ASSERT_ACCEPT", \
"Close", "Skip zero", "Define"
@@ -1742,7 +1696,8 @@ in UTF-8 mode. The code that uses this table must know about such things. */
3, 1, 3, /* MARK, PRUNE, PRUNE_ARG */ \
1, 3, /* SKIP, SKIP_ARG */ \
1, 3, /* THEN, THEN_ARG */ \
- 1, 1, 1, 1, /* COMMIT, FAIL, ACCEPT, ASSERT_ACCEPT */ \
+ 1, 3, /* COMMIT, COMMIT_ARG */ \
+ 1, 1, 1, /* FAIL, ACCEPT, ASSERT_ACCEPT */ \
1+IMM2_SIZE, 1, /* CLOSE, SKIPZERO */ \
1 /* DEFINE */
@@ -1896,7 +1851,7 @@ extern const ucd_record PRIV(ucd_records)[];
#if PCRE2_CODE_UNIT_WIDTH == 32
extern const ucd_record PRIV(dummy_ucd_record)[];
#endif
-extern const uint8_t PRIV(ucd_stage1)[];
+extern const uint16_t PRIV(ucd_stage1)[];
extern const uint16_t PRIV(ucd_stage2)[];
extern const uint32_t PRIV(ucp_gbtable)[];
extern const uint32_t PRIV(ucp_gentype)[];
@@ -1976,6 +1931,14 @@ extern int _pcre2_valid_utf(PCRE2_SPTR, PCRE2_SIZE, PCRE2_SIZE *);
extern BOOL _pcre2_was_newline(PCRE2_SPTR, uint32_t, PCRE2_SPTR,
uint32_t *, BOOL);
extern BOOL _pcre2_xclass(uint32_t, PCRE2_SPTR, BOOL);
+
+/* This function is needed only when memmove() is not available. */
+
+#if !defined(VPCOMPAT) && !defined(HAVE_MEMMOVE)
+#define _pcre2_memmove PCRE2_SUFFIX(_pcre2_memmove)
+extern void * _pcre2_memmove(void *, const void *, size_t);
+#endif
+
#endif /* PCRE2_CODE_UNIT_WIDTH */
#endif /* PCRE2_INTERNAL_H_IDEMPOTENT_GUARD */
diff --git a/thirdparty/pcre2/src/pcre2_intmodedep.h b/thirdparty/pcre2/src/pcre2_intmodedep.h
index c4c4c3adb9..62626d0a8a 100644
--- a/thirdparty/pcre2/src/pcre2_intmodedep.h
+++ b/thirdparty/pcre2/src/pcre2_intmodedep.h
@@ -793,11 +793,23 @@ typedef struct heapframe {
uint8_t return_id; /* Where to go on in internal "return" */
uint8_t op; /* Processing opcode */
+ /* At this point, the structure is 16-bit aligned. On most architectures
+ the alignment requirement for a pointer will ensure that the eptr field below
+ is 32-bit or 64-bit aligned. However, on m68k it is fine to have a pointer
+ that is 16-bit aligned. We must therefore ensure that what comes between here
+ and eptr is an odd multiple of 16 bits so as to get back into 32-bit
+ alignment. This happens naturally when PCRE2_UCHAR is 8 bits wide, but needs
+ fudges in the other cases. In the 32-bit case the padding comes first so that
+ the occu field itself is 32-bit aligned. Without the padding, this structure
+ is no longer a multiple of PCRE2_SIZE on m68k, and the check below fails. */
+
#if PCRE2_CODE_UNIT_WIDTH == 8
PCRE2_UCHAR occu[6]; /* Used for other case code units */
#elif PCRE2_CODE_UNIT_WIDTH == 16
PCRE2_UCHAR occu[2]; /* Used for other case code units */
+ uint8_t unused[2]; /* Ensure 32-bit alignment (see above) */
#else
+ uint8_t unused[2]; /* Ensure 32-bit alignment (see above) */
PCRE2_UCHAR occu[1]; /* Used for other case code units */
#endif
@@ -818,6 +830,9 @@ typedef struct heapframe {
PCRE2_SIZE ovector[131072]; /* Must be last in the structure */
} heapframe;
+/* This typedef is a check that the size of the heapframe structure is a
+multiple of PCRE2_SIZE. See various comments above. */
+
typedef char check_heapframe_size[
((sizeof(heapframe) % sizeof(PCRE2_SIZE)) == 0)? (+1):(-1)];
@@ -881,6 +896,8 @@ typedef struct dfa_match_block {
PCRE2_SPTR last_used_ptr; /* Latest consulted character */
const uint8_t *tables; /* Character tables */
PCRE2_SIZE start_offset; /* The start offset value */
+ PCRE2_SIZE heap_limit; /* As it says */
+ PCRE2_SIZE heap_used; /* As it says */
uint32_t match_limit; /* As it says */
uint32_t match_limit_depth; /* As it says */
uint32_t match_call_count; /* Number of calls of internal function */
diff --git a/thirdparty/pcre2/src/pcre2_jit_compile.c b/thirdparty/pcre2/src/pcre2_jit_compile.c
index 80ed1c4ca6..32e985b793 100644
--- a/thirdparty/pcre2/src/pcre2_jit_compile.c
+++ b/thirdparty/pcre2/src/pcre2_jit_compile.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2017 University of Cambridge
+ New API code Copyright (c) 2016-2018 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -839,6 +839,7 @@ switch(*cc)
#endif
case OP_MARK:
+ case OP_COMMIT_ARG:
case OP_PRUNE_ARG:
case OP_SKIP_ARG:
case OP_THEN_ARG:
@@ -939,6 +940,7 @@ while (cc < ccend)
common->control_head_ptr = 1;
/* Fall through. */
+ case OP_COMMIT_ARG:
case OP_PRUNE_ARG:
case OP_MARK:
if (common->mark_ptr == 0)
@@ -1553,6 +1555,7 @@ while (cc < ccend)
break;
case OP_MARK:
+ case OP_COMMIT_ARG:
case OP_PRUNE_ARG:
case OP_THEN_ARG:
SLJIT_ASSERT(common->mark_ptr != 0);
@@ -1733,6 +1736,7 @@ while (cc < ccend)
break;
case OP_MARK:
+ case OP_COMMIT_ARG:
case OP_PRUNE_ARG:
case OP_THEN_ARG:
SLJIT_ASSERT(common->mark_ptr != 0);
@@ -2041,6 +2045,7 @@ while (cc < ccend)
break;
case OP_MARK:
+ case OP_COMMIT_ARG:
case OP_PRUNE_ARG:
case OP_THEN_ARG:
SLJIT_ASSERT(common->mark_ptr != 0);
@@ -2428,6 +2433,7 @@ while (cc < ccend)
break;
case OP_MARK:
+ case OP_COMMIT_ARG:
case OP_PRUNE_ARG:
case OP_THEN_ARG:
SLJIT_ASSERT(common->mark_ptr != 0);
@@ -3666,7 +3672,8 @@ if (!common->utf)
#endif
OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
-OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_stage1));
+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
+OP1(SLJIT_MOV_U16, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_stage1));
OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK);
OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);
@@ -5894,6 +5901,8 @@ for (i = 0; i < 32; i++)
}
}
+if (len == 0) return FALSE; /* Should never occur, but stops analyzers complaining. */
+
i = 0;
j = 0;
@@ -6627,7 +6636,8 @@ if (needstype || needsscript)
#endif
OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
- OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_stage1));
+ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
+ OP1(SLJIT_MOV_U16, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_stage1));
OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK);
OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);
@@ -7254,10 +7264,11 @@ while (cc < end_subject)
if ((ricount & 1) != 0) break; /* Grapheme break required */
}
- /* If Extend follows E_Base[_GAZ] do not update lgb; this allows
- any number of Extend before a following E_Modifier. */
+ /* If Extend or ZWJ follows Extended_Pictographic, do not update lgb; this
+ allows any number of them before a following Extended_Pictographic. */
- if (rgb != ucp_gbExtend || (lgb != ucp_gbE_Base && lgb != ucp_gbE_Base_GAZ))
+ if ((rgb != ucp_gbExtend && rgb != ucp_gbZWJ) ||
+ lgb != ucp_gbExtended_Pictographic)
lgb = rgb;
prevcc = cc;
@@ -7309,10 +7320,11 @@ while (cc < end_subject)
if ((ricount & 1) != 0) break; /* Grapheme break required */
}
- /* If Extend follows E_Base[_GAZ] do not update lgb; this allows
- any number of Extend before a following E_Modifier. */
+ /* If Extend or ZWJ follows Extended_Pictographic, do not update lgb; this
+ allows any number of them before a following Extended_Pictographic. */
- if (rgb != ucp_gbExtend || (lgb != ucp_gbE_Base && lgb != ucp_gbE_Base_GAZ))
+ if ((rgb != ucp_gbExtend && rgb != ucp_gbZWJ) ||
+ lgb != ucp_gbExtended_Pictographic)
lgb = rgb;
cc++;
@@ -10346,7 +10358,8 @@ backtrack_common *backtrack;
PCRE2_UCHAR opcode = *cc;
PCRE2_SPTR ccend = cc + 1;
-if (opcode == OP_PRUNE_ARG || opcode == OP_SKIP_ARG || opcode == OP_THEN_ARG)
+if (opcode == OP_COMMIT_ARG || opcode == OP_PRUNE_ARG ||
+ opcode == OP_SKIP_ARG || opcode == OP_THEN_ARG)
ccend += 2 + cc[1];
PUSH_BACKTRACK(sizeof(backtrack_common), cc, NULL);
@@ -10358,7 +10371,7 @@ if (opcode == OP_SKIP)
return ccend;
}
-if (opcode == OP_PRUNE_ARG || opcode == OP_THEN_ARG)
+if (opcode == OP_COMMIT_ARG || opcode == OP_PRUNE_ARG || opcode == OP_THEN_ARG)
{
OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)(cc + 2));
@@ -10677,6 +10690,7 @@ while (cc < ccend)
case OP_THEN:
case OP_THEN_ARG:
case OP_COMMIT:
+ case OP_COMMIT_ARG:
cc = compile_control_verb_matchingpath(common, cc, parent);
break;
@@ -11751,6 +11765,7 @@ while (current)
break;
case OP_COMMIT:
+ case OP_COMMIT_ARG:
if (!common->local_quit_available)
OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_NOMATCH);
if (common->quit_label == NULL)
diff --git a/thirdparty/pcre2/src/pcre2_maketables.c b/thirdparty/pcre2/src/pcre2_maketables.c
index 2c7ae84d86..537edba8c3 100644
--- a/thirdparty/pcre2/src/pcre2_maketables.c
+++ b/thirdparty/pcre2/src/pcre2_maketables.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016 University of Cambridge
+ New API code Copyright (c) 2016-2018 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -141,13 +141,6 @@ for (i = 0; i < 256; i++)
if (isdigit(i)) x += ctype_digit;
if (isxdigit(i)) x += ctype_xdigit;
if (isalnum(i) || i == '_') x += ctype_word;
-
- /* Note: strchr includes the terminating zero in the characters it considers.
- In this instance, that is ok because we want binary zero to be flagged as a
- meta-character, which in this sense is any character that terminates a run
- of data characters. */
-
- if (strchr("\\*+?{^.$|()[", i) != 0) x += ctype_meta;
*p++ = x;
}
diff --git a/thirdparty/pcre2/src/pcre2_match.c b/thirdparty/pcre2/src/pcre2_match.c
index 79cc93f918..8741e1432d 100644
--- a/thirdparty/pcre2/src/pcre2_match.c
+++ b/thirdparty/pcre2/src/pcre2_match.c
@@ -43,11 +43,11 @@ POSSIBILITY OF SUCH DAMAGE.
#include "config.h"
#endif
-/* These defines enables debugging code */
+/* These defines enable debugging code */
-//#define DEBUG_FRAMES_DISPLAY
-//#define DEBUG_SHOW_OPS
-//#define DEBUG_SHOW_RMATCH
+/* #define DEBUG_FRAMES_DISPLAY */
+/* #define DEBUG_SHOW_OPS */
+/* #define DEBUG_SHOW_RMATCH */
#ifdef DEBUG_FRAME_DISPLAY
#include <stdarg.h>
@@ -149,7 +149,7 @@ changed, the code at RETURN_SWITCH below must be updated in sync. */
enum { RM1=1, RM2, RM3, RM4, RM5, RM6, RM7, RM8, RM9, RM10,
RM11, RM12, RM13, RM14, RM15, RM16, RM17, RM18, RM19, RM20,
RM21, RM22, RM23, RM24, RM25, RM26, RM27, RM28, RM29, RM30,
- RM31, RM32, RM33, RM34, RM35 };
+ RM31, RM32, RM33, RM34, RM35, RM36 };
#ifdef SUPPORT_WIDE_CHARS
enum { RM100=100, RM101 };
@@ -770,7 +770,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
/* ===================================================================== */
/* Real or forced end of the pattern, assertion, or recursion. In an
assertion ACCEPT, update the last used pointer and remember the current
- frame so that the captures can be fished out of it. */
+ frame so that the captures and mark can be fished out of it. */
case OP_ASSERT_ACCEPT:
if (Feptr > mb->last_used_ptr) mb->last_used_ptr = Feptr;
@@ -1776,7 +1776,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
/* ===================================================================== */
- /* Match a bit-mapped character class, possibly repeatedly. These op codes
+ /* Match a bit-mapped character class, possibly repeatedly. These opcodes
are used when all the characters in the class have values in the range
0-255, and either the matching is caseful, or the characters are in the
range 0-127 when UTF processing is enabled. The only difference between
@@ -1962,11 +1962,15 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
if (reptype == REPTYPE_POS) continue; /* No backtracking */
+ /* After \C in UTF mode, Lstart_eptr might be in the middle of a
+ Unicode character. Use <= Lstart_eptr to ensure backtracking doesn't
+ go too far. */
+
for (;;)
{
RMATCH(Fecode, RM201);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- if (Feptr-- == Lstart_eptr) break; /* Tried at original position */
+ if (Feptr-- <= Lstart_eptr) break; /* Tried at original position */
BACKCHAR(Feptr);
}
}
@@ -2126,11 +2130,15 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
if (reptype == REPTYPE_POS) continue; /* No backtracking */
+ /* After \C in UTF mode, Lstart_eptr might be in the middle of a
+ Unicode character. Use <= Lstart_eptr to ensure backtracking doesn't
+ go too far. */
+
for(;;)
{
RMATCH(Fecode, RM101);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- if (Feptr-- == Lstart_eptr) break; /* Tried at original position */
+ if (Feptr-- <= Lstart_eptr) break; /* Tried at original position */
#ifdef SUPPORT_UNICODE
if (utf) BACKCHAR(Feptr);
#endif
@@ -2456,7 +2464,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
/* ===================================================================== */
/* Match a single character type repeatedly. Note that the property type
- does not need to be in a stack frame as it not used within an RMATCH()
+ does not need to be in a stack frame as it is not used within an RMATCH()
loop. */
#define Lstart_eptr F->temp_sptr[0]
@@ -4002,8 +4010,8 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
if (reptype == REPTYPE_POS) continue; /* No backtracking */
/* After \C in UTF mode, Lstart_eptr might be in the middle of a
- Unicode character. Use <= pp to ensure backtracking doesn't go too far.
- */
+ Unicode character. Use <= Lstart_eptr to ensure backtracking doesn't
+ go too far. */
for(;;)
{
@@ -4135,7 +4143,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
}
break;
- /* The "byte" (i.e. "code unit") case is the same as non-UTF */
+ /* The "byte" (i.e. "code unit") case is the same as non-UTF */
case OP_ANYBYTE:
fc = Lmax - Lmin;
@@ -5111,7 +5119,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
/* Positive assertions are like other groups except that PCRE doesn't allow
the effect of (*THEN) to escape beyond an assertion; it is therefore
treated as NOMATCH. (*ACCEPT) is treated as successful assertion, with its
- captures retained. Any other return is an error. */
+ captures and mark retained. Any other return is an error. */
#define Lframe_type F->temp_32[0]
@@ -5128,6 +5136,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
(char *)assert_accept_frame + offsetof(heapframe, ovector),
assert_accept_frame->offset_top * sizeof(PCRE2_SIZE));
Foffset_top = assert_accept_frame->offset_top;
+ Fmark = assert_accept_frame->mark;
break;
}
if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc);
@@ -5416,7 +5425,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
Feptr -= number;
}
- /* Save the earliest consulted character, then skip to next op code */
+ /* Save the earliest consulted character, then skip to next opcode */
if (Feptr < mb->start_used_ptr) mb->start_used_ptr = Feptr;
Fecode += 1 + LINK_SIZE;
@@ -5501,7 +5510,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
frame so that it points to the final branch. */
case OP_ONCE:
- Fback_frame = ((char *)F - (char *)P) + frame_size;
+ Fback_frame = ((char *)F - (char *)P);
for (;;)
{
uint32_t y = GET(P->ecode,1);
@@ -5829,6 +5838,13 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
mb->verb_current_recurse = Fcurrent_recurse;
RRETURN(MATCH_COMMIT);
+ case OP_COMMIT_ARG:
+ Fmark = mb->nomatch_mark = Fecode + 2;
+ RMATCH(Fecode + PRIV(OP_lengths)[*Fecode] + Fecode[1], RM36);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ mb->verb_current_recurse = Fcurrent_recurse;
+ RRETURN(MATCH_COMMIT);
+
case OP_PRUNE:
RMATCH(Fecode + PRIV(OP_lengths)[*Fecode], RM14);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
@@ -5921,7 +5937,7 @@ in rrc. */
RETURN_SWITCH:
if (Frdepth == 0) return rrc; /* Exit from the top level */
-F = (heapframe *)((char *)F - Fback_frame); /* Back track */
+F = (heapframe *)((char *)F - Fback_frame); /* Backtrack */
mb->cb->callout_flags |= PCRE2_CALLOUT_BACKTRACK; /* Note for callouts */
#ifdef DEBUG_SHOW_RMATCH
@@ -5934,7 +5950,7 @@ switch (Freturn_id)
LBL( 9) LBL(10) LBL(11) LBL(12) LBL(13) LBL(14) LBL(15) LBL(16)
LBL(17) LBL(18) LBL(19) LBL(20) LBL(21) LBL(22) LBL(23) LBL(24)
LBL(25) LBL(26) LBL(27) LBL(28) LBL(29) LBL(30) LBL(31) LBL(32)
- LBL(33) LBL(34) LBL(35)
+ LBL(33) LBL(34) LBL(35) LBL(36)
#ifdef SUPPORT_WIDE_CHARS
LBL(100) LBL(101)
@@ -6275,7 +6291,7 @@ mb->match_limit_depth = (mcontext->depth_limit < re->limit_depth)?
/* If a pattern has very many capturing parentheses, the frame size may be very
large. Ensure that there are at least 10 available frames by getting an initial
vector on the heap if necessary, except when the heap limit prevents this. Get
-fewer if possible. (The heap limit is in kilobytes.) */
+fewer if possible. (The heap limit is in kibibytes.) */
if (frame_size <= START_FRAMES_SIZE/10)
{
diff --git a/thirdparty/pcre2/src/pcre2_pattern_info.c b/thirdparty/pcre2/src/pcre2_pattern_info.c
index 906e9198f5..a29f5eff67 100644
--- a/thirdparty/pcre2/src/pcre2_pattern_info.c
+++ b/thirdparty/pcre2/src/pcre2_pattern_info.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2017 University of Cambridge
+ New API code Copyright (c) 2016-2018 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -390,6 +390,7 @@ while (TRUE)
#endif
case OP_MARK:
+ case OP_COMMIT_ARG:
case OP_PRUNE_ARG:
case OP_SKIP_ARG:
case OP_THEN_ARG:
diff --git a/thirdparty/pcre2/src/pcre2_serialize.c b/thirdparty/pcre2/src/pcre2_serialize.c
index d2cc603cbb..cec1a035d1 100644
--- a/thirdparty/pcre2/src/pcre2_serialize.c
+++ b/thirdparty/pcre2/src/pcre2_serialize.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2017 University of Cambridge
+ New API code Copyright (c) 2016-2018 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -127,7 +127,25 @@ dst_bytes += tables_length;
for (i = 0; i < number_of_codes; i++)
{
re = (const pcre2_real_code *)(codes[i]);
- memcpy(dst_bytes, (char *)re, re->blocksize);
+ (void)memcpy(dst_bytes, (char *)re, re->blocksize);
+
+ /* Certain fields in the compiled code block are re-set during
+ deserialization. In order to ensure that the serialized data stream is always
+ the same for the same pattern, set them to zero here. We can't assume the
+ copy of the pattern is correctly aligned for accessing the fields as part of
+ a structure. Note the use of sizeof(void *) in the second of these, to
+ specify the size of a pointer. If sizeof(uint8_t *) is used (tables is a
+ pointer to uint8_t), gcc gives a warning because the first argument is also a
+ pointer to uint8_t. Casting the first argument to (void *) can stop this, but
+ it didn't stop Coverity giving the same complaint. */
+
+ (void)memset(dst_bytes + offsetof(pcre2_real_code, memctl), 0,
+ sizeof(pcre2_memctl));
+ (void)memset(dst_bytes + offsetof(pcre2_real_code, tables), 0,
+ sizeof(void *));
+ (void)memset(dst_bytes + offsetof(pcre2_real_code, executable_jit), 0,
+ sizeof(void *));
+
dst_bytes += re->blocksize;
}
diff --git a/thirdparty/pcre2/src/pcre2_string_utils.c b/thirdparty/pcre2/src/pcre2_string_utils.c
index 2a1f282629..d6be01acf5 100644
--- a/thirdparty/pcre2/src/pcre2_string_utils.c
+++ b/thirdparty/pcre2/src/pcre2_string_utils.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016 University of Cambridge
+ New API code Copyright (c) 2018 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -51,6 +51,42 @@ functions work only on 8-bit data. */
/*************************************************
+* Emulated memmove() for systems without it *
+*************************************************/
+
+/* This function can make use of bcopy() if it is available. Otherwise do it by
+steam, as there some non-Unix environments that lack both memmove() and
+bcopy(). */
+
+#if !defined(VPCOMPAT) && !defined(HAVE_MEMMOVE)
+void *
+PRIV(memmove)(void *d, const void *s, size_t n)
+{
+#ifdef HAVE_BCOPY
+bcopy(s, d, n);
+return d;
+#else
+size_t i;
+unsigned char *dest = (unsigned char *)d;
+const unsigned char *src = (const unsigned char *)s;
+if (dest > src)
+ {
+ dest += n;
+ src += n;
+ for (i = 0; i < n; ++i) *(--dest) = *(--src);
+ return (void *)dest;
+ }
+else
+ {
+ for (i = 0; i < n; ++i) *dest++ = *src++;
+ return (void *)(dest - n);
+ }
+#endif /* not HAVE_BCOPY */
+}
+#endif /* not VPCOMPAT && not HAVE_MEMMOVE */
+
+
+/*************************************************
* Compare two zero-terminated PCRE2 strings *
*************************************************/
diff --git a/thirdparty/pcre2/src/pcre2_study.c b/thirdparty/pcre2/src/pcre2_study.c
index b92686759d..acbf98b41b 100644
--- a/thirdparty/pcre2/src/pcre2_study.c
+++ b/thirdparty/pcre2/src/pcre2_study.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2017 University of Cambridge
+ New API code Copyright (c) 2016-2018 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -707,6 +707,7 @@ for (;;)
/* Skip these, but we need to add in the name length. */
case OP_MARK:
+ case OP_COMMIT_ARG:
case OP_PRUNE_ARG:
case OP_SKIP_ARG:
case OP_THEN_ARG:
@@ -956,6 +957,7 @@ do
case OP_CIRCM:
case OP_CLOSE:
case OP_COMMIT:
+ case OP_COMMIT_ARG:
case OP_COND:
case OP_CREF:
case OP_FALSE:
@@ -1274,7 +1276,7 @@ do
break;
/* Single character types set the bits and stop. Note that if PCRE2_UCP
- is set, we do not see these op codes because \d etc are converted to
+ is set, we do not see these opcodes because \d etc are converted to
properties. Therefore, these apply in the case when only characters less
than 256 are recognized to match the types. */
diff --git a/thirdparty/pcre2/src/pcre2_substitute.c b/thirdparty/pcre2/src/pcre2_substitute.c
index 8da951fc6e..ab8d10908a 100644
--- a/thirdparty/pcre2/src/pcre2_substitute.c
+++ b/thirdparty/pcre2/src/pcre2_substitute.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016 University of Cambridge
+ New API code Copyright (c) 2016-2018 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -238,10 +238,12 @@ PCRE2_SPTR repend;
PCRE2_SIZE extra_needed = 0;
PCRE2_SIZE buff_offset, buff_length, lengthleft, fraglength;
PCRE2_SIZE *ovector;
+PCRE2_SIZE ovecsave[3];
buff_offset = 0;
lengthleft = buff_length = *blength;
*blength = PCRE2_UNSET;
+ovecsave[0] = ovecsave[1] = ovecsave[2] = PCRE2_UNSET;
/* Partial matching is not valid. */
@@ -361,13 +363,33 @@ do
}
/* Handle a successful match. Matches that use \K to end before they start
- are not supported. */
-
- if (ovector[1] < ovector[0])
+ or start before the current point in the subject are not supported. */
+
+ if (ovector[1] < ovector[0] || ovector[0] < start_offset)
{
rc = PCRE2_ERROR_BADSUBSPATTERN;
goto EXIT;
}
+
+ /* Check for the same match as previous. This is legitimate after matching an
+ empty string that starts after the initial match offset. We have tried again
+ at the match point in case the pattern is one like /(?<=\G.)/ which can never
+ match at its starting point, so running the match achieves the bumpalong. If
+ we do get the same (null) match at the original match point, it isn't such a
+ pattern, so we now do the empty string magic. In all other cases, a repeat
+ match should never occur. */
+
+ if (ovecsave[0] == ovector[0] && ovecsave[1] == ovector[1])
+ {
+ if (ovector[0] == ovector[1] && ovecsave[2] != start_offset)
+ {
+ goptions = PCRE2_NOTEMPTY_ATSTART | PCRE2_ANCHORED;
+ ovecsave[2] = start_offset;
+ continue; /* Back to the top of the loop */
+ }
+ rc = PCRE2_ERROR_INTERNAL_DUPMATCH;
+ goto EXIT;
+ }
/* Count substitutions with a paranoid check for integer overflow; surely no
real call to this function would ever hit this! */
@@ -799,13 +821,18 @@ do
} /* End handling a literal code unit */
} /* End of loop for scanning the replacement. */
- /* The replacement has been copied to the output. Update the start offset to
- point to the rest of the subject string. If we matched an empty string,
- do the magic for global matches. */
-
- start_offset = ovector[1];
- goptions = (ovector[0] != ovector[1])? 0 :
+ /* The replacement has been copied to the output. Save the details of this
+ match. See above for how this data is used. If we matched an empty string, do
+ the magic for global matches. Finally, update the start offset to point to
+ the rest of the subject string. */
+
+ ovecsave[0] = ovector[0];
+ ovecsave[1] = ovector[1];
+ ovecsave[2] = start_offset;
+
+ goptions = (ovector[0] != ovector[1] || ovector[0] > start_offset)? 0 :
PCRE2_ANCHORED|PCRE2_NOTEMPTY_ATSTART;
+ start_offset = ovector[1];
} while ((suboptions & PCRE2_SUBSTITUTE_GLOBAL) != 0); /* Repeat "do" loop */
/* Copy the rest of the subject. */
diff --git a/thirdparty/pcre2/src/pcre2_tables.c b/thirdparty/pcre2/src/pcre2_tables.c
index 9f8dc293aa..83d6f9de55 100644
--- a/thirdparty/pcre2/src/pcre2_tables.c
+++ b/thirdparty/pcre2/src/pcre2_tables.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2017 University of Cambridge
+ New API code Copyright (c) 2016-2018 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -137,9 +137,10 @@ const uint32_t PRIV(ucp_gentype)[] = {
/* This table encodes the rules for finding the end of an extended grapheme
cluster. Every code point has a grapheme break property which is one of the
-ucp_gbXX values defined in pcre2_ucp.h. The 2-dimensional table is indexed by
-the properties of two adjacent code points. The left property selects a word
-from the table, and the right property selects a bit from that word like this:
+ucp_gbXX values defined in pcre2_ucp.h. These changed between Unicode versions
+10 and 11. The 2-dimensional table is indexed by the properties of two adjacent
+code points. The left property selects a word from the table, and the right
+property selects a bit from that word like this:
PRIV(ucp_gbtable)[left-property] & (1 << right-property)
@@ -166,49 +167,41 @@ are implementing).
6. Do not break after Prepend characters.
-7. Do not break within emoji modifier sequences (E_Base or E_Base_GAZ followed
- by E_Modifier). Extend characters are allowed before the modifier; this
- cannot be represented in this table, the code has to deal with it.
+7. Do not break within emoji modifier sequences or emoji zwj sequences. That
+ is, do not break between characters with the Extended_Pictographic property.
+ Extend and ZWJ characters are allowed between the characters; this cannot be
+ represented in this table, the code has to deal with it.
-8. Do not break within emoji zwj sequences (ZWJ followed by Glue_After_Zwj or
- E_Base_GAZ).
-
-9. Do not break within emoji flag sequences. That is, do not break between
+8. Do not break within emoji flag sequences. That is, do not break between
regional indicator (RI) symbols if there are an odd number of RI characters
before the break point. This table encodes "join RI characters"; the code
has to deal with checking for previous adjoining RIs.
-10. Otherwise, break everywhere.
+9. Otherwise, break everywhere.
*/
#define ESZ (1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark)|(1<<ucp_gbZWJ)
const uint32_t PRIV(ucp_gbtable)[] = {
- (1<<ucp_gbLF), /* 0 CR */
- 0, /* 1 LF */
- 0, /* 2 Control */
- ESZ, /* 3 Extend */
- ESZ|(1<<ucp_gbPrepend)| /* 4 Prepend */
+ (1<<ucp_gbLF), /* 0 CR */
+ 0, /* 1 LF */
+ 0, /* 2 Control */
+ ESZ, /* 3 Extend */
+ ESZ|(1<<ucp_gbPrepend)| /* 4 Prepend */
(1<<ucp_gbL)|(1<<ucp_gbV)|(1<<ucp_gbT)|
(1<<ucp_gbLV)|(1<<ucp_gbLVT)|(1<<ucp_gbOther)|
- (1<<ucp_gbRegionalIndicator)|
- (1<<ucp_gbE_Base)|(1<<ucp_gbE_Modifier)|
- (1<<ucp_gbE_Base_GAZ)|
- (1<<ucp_gbZWJ)|(1<<ucp_gbGlue_After_Zwj),
- ESZ, /* 5 SpacingMark */
- ESZ|(1<<ucp_gbL)|(1<<ucp_gbV)|(1<<ucp_gbLV)| /* 6 L */
+ (1<<ucp_gbRegionalIndicator),
+ ESZ, /* 5 SpacingMark */
+ ESZ|(1<<ucp_gbL)|(1<<ucp_gbV)|(1<<ucp_gbLV)| /* 6 L */
(1<<ucp_gbLVT),
- ESZ|(1<<ucp_gbV)|(1<<ucp_gbT), /* 7 V */
- ESZ|(1<<ucp_gbT), /* 8 T */
- ESZ|(1<<ucp_gbV)|(1<<ucp_gbT), /* 9 LV */
- ESZ|(1<<ucp_gbT), /* 10 LVT */
- (1<<ucp_gbRegionalIndicator), /* 11 RegionalIndicator */
- ESZ, /* 12 Other */
- ESZ|(1<<ucp_gbE_Modifier), /* 13 E_Base */
- ESZ, /* 14 E_Modifier */
- ESZ|(1<<ucp_gbE_Modifier), /* 15 E_Base_GAZ */
- ESZ|(1<<ucp_gbGlue_After_Zwj)|(1<<ucp_gbE_Base_GAZ), /* 16 ZWJ */
- ESZ /* 12 Glue_After_Zwj */
+ ESZ|(1<<ucp_gbV)|(1<<ucp_gbT), /* 7 V */
+ ESZ|(1<<ucp_gbT), /* 8 T */
+ ESZ|(1<<ucp_gbV)|(1<<ucp_gbT), /* 9 LV */
+ ESZ|(1<<ucp_gbT), /* 10 LVT */
+ (1<<ucp_gbRegionalIndicator), /* 11 RegionalIndicator */
+ ESZ, /* 12 Other */
+ ESZ, /* 13 ZWJ */
+ ESZ|(1<<ucp_gbExtended_Pictographic) /* 14 Extended Pictographic */
};
#undef ESZ
@@ -282,6 +275,7 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */
#define STRING_Cyrillic0 STR_C STR_y STR_r STR_i STR_l STR_l STR_i STR_c "\0"
#define STRING_Deseret0 STR_D STR_e STR_s STR_e STR_r STR_e STR_t "\0"
#define STRING_Devanagari0 STR_D STR_e STR_v STR_a STR_n STR_a STR_g STR_a STR_r STR_i "\0"
+#define STRING_Dogra0 STR_D STR_o STR_g STR_r STR_a "\0"
#define STRING_Duployan0 STR_D STR_u STR_p STR_l STR_o STR_y STR_a STR_n "\0"
#define STRING_Egyptian_Hieroglyphs0 STR_E STR_g STR_y STR_p STR_t STR_i STR_a STR_n STR_UNDERSCORE STR_H STR_i STR_e STR_r STR_o STR_g STR_l STR_y STR_p STR_h STR_s "\0"
#define STRING_Elbasan0 STR_E STR_l STR_b STR_a STR_s STR_a STR_n "\0"
@@ -292,9 +286,11 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */
#define STRING_Grantha0 STR_G STR_r STR_a STR_n STR_t STR_h STR_a "\0"
#define STRING_Greek0 STR_G STR_r STR_e STR_e STR_k "\0"
#define STRING_Gujarati0 STR_G STR_u STR_j STR_a STR_r STR_a STR_t STR_i "\0"
+#define STRING_Gunjala_Gondi0 STR_G STR_u STR_n STR_j STR_a STR_l STR_a STR_UNDERSCORE STR_G STR_o STR_n STR_d STR_i "\0"
#define STRING_Gurmukhi0 STR_G STR_u STR_r STR_m STR_u STR_k STR_h STR_i "\0"
#define STRING_Han0 STR_H STR_a STR_n "\0"
#define STRING_Hangul0 STR_H STR_a STR_n STR_g STR_u STR_l "\0"
+#define STRING_Hanifi_Rohingya0 STR_H STR_a STR_n STR_i STR_f STR_i STR_UNDERSCORE STR_R STR_o STR_h STR_i STR_n STR_g STR_y STR_a "\0"
#define STRING_Hanunoo0 STR_H STR_a STR_n STR_u STR_n STR_o STR_o "\0"
#define STRING_Hatran0 STR_H STR_a STR_t STR_r STR_a STR_n "\0"
#define STRING_Hebrew0 STR_H STR_e STR_b STR_r STR_e STR_w "\0"
@@ -330,6 +326,7 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */
#define STRING_Lydian0 STR_L STR_y STR_d STR_i STR_a STR_n "\0"
#define STRING_M0 STR_M "\0"
#define STRING_Mahajani0 STR_M STR_a STR_h STR_a STR_j STR_a STR_n STR_i "\0"
+#define STRING_Makasar0 STR_M STR_a STR_k STR_a STR_s STR_a STR_r "\0"
#define STRING_Malayalam0 STR_M STR_a STR_l STR_a STR_y STR_a STR_l STR_a STR_m "\0"
#define STRING_Mandaic0 STR_M STR_a STR_n STR_d STR_a STR_i STR_c "\0"
#define STRING_Manichaean0 STR_M STR_a STR_n STR_i STR_c STR_h STR_a STR_e STR_a STR_n "\0"
@@ -337,6 +334,7 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */
#define STRING_Masaram_Gondi0 STR_M STR_a STR_s STR_a STR_r STR_a STR_m STR_UNDERSCORE STR_G STR_o STR_n STR_d STR_i "\0"
#define STRING_Mc0 STR_M STR_c "\0"
#define STRING_Me0 STR_M STR_e "\0"
+#define STRING_Medefaidrin0 STR_M STR_e STR_d STR_e STR_f STR_a STR_i STR_d STR_r STR_i STR_n "\0"
#define STRING_Meetei_Mayek0 STR_M STR_e STR_e STR_t STR_e STR_i STR_UNDERSCORE STR_M STR_a STR_y STR_e STR_k "\0"
#define STRING_Mende_Kikakui0 STR_M STR_e STR_n STR_d STR_e STR_UNDERSCORE STR_K STR_i STR_k STR_a STR_k STR_u STR_i "\0"
#define STRING_Meroitic_Cursive0 STR_M STR_e STR_r STR_o STR_i STR_t STR_i STR_c STR_UNDERSCORE STR_C STR_u STR_r STR_s STR_i STR_v STR_e "\0"
@@ -364,6 +362,7 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */
#define STRING_Old_North_Arabian0 STR_O STR_l STR_d STR_UNDERSCORE STR_N STR_o STR_r STR_t STR_h STR_UNDERSCORE STR_A STR_r STR_a STR_b STR_i STR_a STR_n "\0"
#define STRING_Old_Permic0 STR_O STR_l STR_d STR_UNDERSCORE STR_P STR_e STR_r STR_m STR_i STR_c "\0"
#define STRING_Old_Persian0 STR_O STR_l STR_d STR_UNDERSCORE STR_P STR_e STR_r STR_s STR_i STR_a STR_n "\0"
+#define STRING_Old_Sogdian0 STR_O STR_l STR_d STR_UNDERSCORE STR_S STR_o STR_g STR_d STR_i STR_a STR_n "\0"
#define STRING_Old_South_Arabian0 STR_O STR_l STR_d STR_UNDERSCORE STR_S STR_o STR_u STR_t STR_h STR_UNDERSCORE STR_A STR_r STR_a STR_b STR_i STR_a STR_n "\0"
#define STRING_Old_Turkic0 STR_O STR_l STR_d STR_UNDERSCORE STR_T STR_u STR_r STR_k STR_i STR_c "\0"
#define STRING_Oriya0 STR_O STR_r STR_i STR_y STR_a "\0"
@@ -397,6 +396,7 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */
#define STRING_Sk0 STR_S STR_k "\0"
#define STRING_Sm0 STR_S STR_m "\0"
#define STRING_So0 STR_S STR_o "\0"
+#define STRING_Sogdian0 STR_S STR_o STR_g STR_d STR_i STR_a STR_n "\0"
#define STRING_Sora_Sompeng0 STR_S STR_o STR_r STR_a STR_UNDERSCORE STR_S STR_o STR_m STR_p STR_e STR_n STR_g "\0"
#define STRING_Soyombo0 STR_S STR_o STR_y STR_o STR_m STR_b STR_o "\0"
#define STRING_Sundanese0 STR_S STR_u STR_n STR_d STR_a STR_n STR_e STR_s STR_e "\0"
@@ -469,6 +469,7 @@ const char PRIV(utt_names)[] =
STRING_Cyrillic0
STRING_Deseret0
STRING_Devanagari0
+ STRING_Dogra0
STRING_Duployan0
STRING_Egyptian_Hieroglyphs0
STRING_Elbasan0
@@ -479,9 +480,11 @@ const char PRIV(utt_names)[] =
STRING_Grantha0
STRING_Greek0
STRING_Gujarati0
+ STRING_Gunjala_Gondi0
STRING_Gurmukhi0
STRING_Han0
STRING_Hangul0
+ STRING_Hanifi_Rohingya0
STRING_Hanunoo0
STRING_Hatran0
STRING_Hebrew0
@@ -517,6 +520,7 @@ const char PRIV(utt_names)[] =
STRING_Lydian0
STRING_M0
STRING_Mahajani0
+ STRING_Makasar0
STRING_Malayalam0
STRING_Mandaic0
STRING_Manichaean0
@@ -524,6 +528,7 @@ const char PRIV(utt_names)[] =
STRING_Masaram_Gondi0
STRING_Mc0
STRING_Me0
+ STRING_Medefaidrin0
STRING_Meetei_Mayek0
STRING_Mende_Kikakui0
STRING_Meroitic_Cursive0
@@ -551,6 +556,7 @@ const char PRIV(utt_names)[] =
STRING_Old_North_Arabian0
STRING_Old_Permic0
STRING_Old_Persian0
+ STRING_Old_Sogdian0
STRING_Old_South_Arabian0
STRING_Old_Turkic0
STRING_Oriya0
@@ -584,6 +590,7 @@ const char PRIV(utt_names)[] =
STRING_Sk0
STRING_Sm0
STRING_So0
+ STRING_Sogdian0
STRING_Sora_Sompeng0
STRING_Soyombo0
STRING_Sundanese0
@@ -656,154 +663,161 @@ const ucp_type_table PRIV(utt)[] = {
{ 265, PT_SC, ucp_Cyrillic },
{ 274, PT_SC, ucp_Deseret },
{ 282, PT_SC, ucp_Devanagari },
- { 293, PT_SC, ucp_Duployan },
- { 302, PT_SC, ucp_Egyptian_Hieroglyphs },
- { 323, PT_SC, ucp_Elbasan },
- { 331, PT_SC, ucp_Ethiopic },
- { 340, PT_SC, ucp_Georgian },
- { 349, PT_SC, ucp_Glagolitic },
- { 360, PT_SC, ucp_Gothic },
- { 367, PT_SC, ucp_Grantha },
- { 375, PT_SC, ucp_Greek },
- { 381, PT_SC, ucp_Gujarati },
- { 390, PT_SC, ucp_Gurmukhi },
- { 399, PT_SC, ucp_Han },
- { 403, PT_SC, ucp_Hangul },
- { 410, PT_SC, ucp_Hanunoo },
- { 418, PT_SC, ucp_Hatran },
- { 425, PT_SC, ucp_Hebrew },
- { 432, PT_SC, ucp_Hiragana },
- { 441, PT_SC, ucp_Imperial_Aramaic },
- { 458, PT_SC, ucp_Inherited },
- { 468, PT_SC, ucp_Inscriptional_Pahlavi },
- { 490, PT_SC, ucp_Inscriptional_Parthian },
- { 513, PT_SC, ucp_Javanese },
- { 522, PT_SC, ucp_Kaithi },
- { 529, PT_SC, ucp_Kannada },
- { 537, PT_SC, ucp_Katakana },
- { 546, PT_SC, ucp_Kayah_Li },
- { 555, PT_SC, ucp_Kharoshthi },
- { 566, PT_SC, ucp_Khmer },
- { 572, PT_SC, ucp_Khojki },
- { 579, PT_SC, ucp_Khudawadi },
- { 589, PT_GC, ucp_L },
- { 591, PT_LAMP, 0 },
- { 594, PT_SC, ucp_Lao },
- { 598, PT_SC, ucp_Latin },
- { 604, PT_SC, ucp_Lepcha },
- { 611, PT_SC, ucp_Limbu },
- { 617, PT_SC, ucp_Linear_A },
- { 626, PT_SC, ucp_Linear_B },
- { 635, PT_SC, ucp_Lisu },
- { 640, PT_PC, ucp_Ll },
- { 643, PT_PC, ucp_Lm },
- { 646, PT_PC, ucp_Lo },
- { 649, PT_PC, ucp_Lt },
- { 652, PT_PC, ucp_Lu },
- { 655, PT_SC, ucp_Lycian },
- { 662, PT_SC, ucp_Lydian },
- { 669, PT_GC, ucp_M },
- { 671, PT_SC, ucp_Mahajani },
- { 680, PT_SC, ucp_Malayalam },
- { 690, PT_SC, ucp_Mandaic },
- { 698, PT_SC, ucp_Manichaean },
- { 709, PT_SC, ucp_Marchen },
- { 717, PT_SC, ucp_Masaram_Gondi },
- { 731, PT_PC, ucp_Mc },
- { 734, PT_PC, ucp_Me },
- { 737, PT_SC, ucp_Meetei_Mayek },
- { 750, PT_SC, ucp_Mende_Kikakui },
- { 764, PT_SC, ucp_Meroitic_Cursive },
- { 781, PT_SC, ucp_Meroitic_Hieroglyphs },
- { 802, PT_SC, ucp_Miao },
- { 807, PT_PC, ucp_Mn },
- { 810, PT_SC, ucp_Modi },
- { 815, PT_SC, ucp_Mongolian },
- { 825, PT_SC, ucp_Mro },
- { 829, PT_SC, ucp_Multani },
- { 837, PT_SC, ucp_Myanmar },
- { 845, PT_GC, ucp_N },
- { 847, PT_SC, ucp_Nabataean },
- { 857, PT_PC, ucp_Nd },
- { 860, PT_SC, ucp_New_Tai_Lue },
- { 872, PT_SC, ucp_Newa },
- { 877, PT_SC, ucp_Nko },
- { 881, PT_PC, ucp_Nl },
- { 884, PT_PC, ucp_No },
- { 887, PT_SC, ucp_Nushu },
- { 893, PT_SC, ucp_Ogham },
- { 899, PT_SC, ucp_Ol_Chiki },
- { 908, PT_SC, ucp_Old_Hungarian },
- { 922, PT_SC, ucp_Old_Italic },
- { 933, PT_SC, ucp_Old_North_Arabian },
- { 951, PT_SC, ucp_Old_Permic },
- { 962, PT_SC, ucp_Old_Persian },
- { 974, PT_SC, ucp_Old_South_Arabian },
- { 992, PT_SC, ucp_Old_Turkic },
- { 1003, PT_SC, ucp_Oriya },
- { 1009, PT_SC, ucp_Osage },
- { 1015, PT_SC, ucp_Osmanya },
- { 1023, PT_GC, ucp_P },
- { 1025, PT_SC, ucp_Pahawh_Hmong },
- { 1038, PT_SC, ucp_Palmyrene },
- { 1048, PT_SC, ucp_Pau_Cin_Hau },
- { 1060, PT_PC, ucp_Pc },
- { 1063, PT_PC, ucp_Pd },
- { 1066, PT_PC, ucp_Pe },
- { 1069, PT_PC, ucp_Pf },
- { 1072, PT_SC, ucp_Phags_Pa },
- { 1081, PT_SC, ucp_Phoenician },
- { 1092, PT_PC, ucp_Pi },
- { 1095, PT_PC, ucp_Po },
- { 1098, PT_PC, ucp_Ps },
- { 1101, PT_SC, ucp_Psalter_Pahlavi },
- { 1117, PT_SC, ucp_Rejang },
- { 1124, PT_SC, ucp_Runic },
- { 1130, PT_GC, ucp_S },
- { 1132, PT_SC, ucp_Samaritan },
- { 1142, PT_SC, ucp_Saurashtra },
- { 1153, PT_PC, ucp_Sc },
- { 1156, PT_SC, ucp_Sharada },
- { 1164, PT_SC, ucp_Shavian },
- { 1172, PT_SC, ucp_Siddham },
- { 1180, PT_SC, ucp_SignWriting },
- { 1192, PT_SC, ucp_Sinhala },
- { 1200, PT_PC, ucp_Sk },
- { 1203, PT_PC, ucp_Sm },
- { 1206, PT_PC, ucp_So },
- { 1209, PT_SC, ucp_Sora_Sompeng },
- { 1222, PT_SC, ucp_Soyombo },
- { 1230, PT_SC, ucp_Sundanese },
- { 1240, PT_SC, ucp_Syloti_Nagri },
- { 1253, PT_SC, ucp_Syriac },
- { 1260, PT_SC, ucp_Tagalog },
- { 1268, PT_SC, ucp_Tagbanwa },
- { 1277, PT_SC, ucp_Tai_Le },
- { 1284, PT_SC, ucp_Tai_Tham },
- { 1293, PT_SC, ucp_Tai_Viet },
- { 1302, PT_SC, ucp_Takri },
- { 1308, PT_SC, ucp_Tamil },
- { 1314, PT_SC, ucp_Tangut },
- { 1321, PT_SC, ucp_Telugu },
- { 1328, PT_SC, ucp_Thaana },
- { 1335, PT_SC, ucp_Thai },
- { 1340, PT_SC, ucp_Tibetan },
- { 1348, PT_SC, ucp_Tifinagh },
- { 1357, PT_SC, ucp_Tirhuta },
- { 1365, PT_SC, ucp_Ugaritic },
- { 1374, PT_SC, ucp_Vai },
- { 1378, PT_SC, ucp_Warang_Citi },
- { 1390, PT_ALNUM, 0 },
- { 1394, PT_PXSPACE, 0 },
- { 1398, PT_SPACE, 0 },
- { 1402, PT_UCNC, 0 },
- { 1406, PT_WORD, 0 },
- { 1410, PT_SC, ucp_Yi },
- { 1413, PT_GC, ucp_Z },
- { 1415, PT_SC, ucp_Zanabazar_Square },
- { 1432, PT_PC, ucp_Zl },
- { 1435, PT_PC, ucp_Zp },
- { 1438, PT_PC, ucp_Zs }
+ { 293, PT_SC, ucp_Dogra },
+ { 299, PT_SC, ucp_Duployan },
+ { 308, PT_SC, ucp_Egyptian_Hieroglyphs },
+ { 329, PT_SC, ucp_Elbasan },
+ { 337, PT_SC, ucp_Ethiopic },
+ { 346, PT_SC, ucp_Georgian },
+ { 355, PT_SC, ucp_Glagolitic },
+ { 366, PT_SC, ucp_Gothic },
+ { 373, PT_SC, ucp_Grantha },
+ { 381, PT_SC, ucp_Greek },
+ { 387, PT_SC, ucp_Gujarati },
+ { 396, PT_SC, ucp_Gunjala_Gondi },
+ { 410, PT_SC, ucp_Gurmukhi },
+ { 419, PT_SC, ucp_Han },
+ { 423, PT_SC, ucp_Hangul },
+ { 430, PT_SC, ucp_Hanifi_Rohingya },
+ { 446, PT_SC, ucp_Hanunoo },
+ { 454, PT_SC, ucp_Hatran },
+ { 461, PT_SC, ucp_Hebrew },
+ { 468, PT_SC, ucp_Hiragana },
+ { 477, PT_SC, ucp_Imperial_Aramaic },
+ { 494, PT_SC, ucp_Inherited },
+ { 504, PT_SC, ucp_Inscriptional_Pahlavi },
+ { 526, PT_SC, ucp_Inscriptional_Parthian },
+ { 549, PT_SC, ucp_Javanese },
+ { 558, PT_SC, ucp_Kaithi },
+ { 565, PT_SC, ucp_Kannada },
+ { 573, PT_SC, ucp_Katakana },
+ { 582, PT_SC, ucp_Kayah_Li },
+ { 591, PT_SC, ucp_Kharoshthi },
+ { 602, PT_SC, ucp_Khmer },
+ { 608, PT_SC, ucp_Khojki },
+ { 615, PT_SC, ucp_Khudawadi },
+ { 625, PT_GC, ucp_L },
+ { 627, PT_LAMP, 0 },
+ { 630, PT_SC, ucp_Lao },
+ { 634, PT_SC, ucp_Latin },
+ { 640, PT_SC, ucp_Lepcha },
+ { 647, PT_SC, ucp_Limbu },
+ { 653, PT_SC, ucp_Linear_A },
+ { 662, PT_SC, ucp_Linear_B },
+ { 671, PT_SC, ucp_Lisu },
+ { 676, PT_PC, ucp_Ll },
+ { 679, PT_PC, ucp_Lm },
+ { 682, PT_PC, ucp_Lo },
+ { 685, PT_PC, ucp_Lt },
+ { 688, PT_PC, ucp_Lu },
+ { 691, PT_SC, ucp_Lycian },
+ { 698, PT_SC, ucp_Lydian },
+ { 705, PT_GC, ucp_M },
+ { 707, PT_SC, ucp_Mahajani },
+ { 716, PT_SC, ucp_Makasar },
+ { 724, PT_SC, ucp_Malayalam },
+ { 734, PT_SC, ucp_Mandaic },
+ { 742, PT_SC, ucp_Manichaean },
+ { 753, PT_SC, ucp_Marchen },
+ { 761, PT_SC, ucp_Masaram_Gondi },
+ { 775, PT_PC, ucp_Mc },
+ { 778, PT_PC, ucp_Me },
+ { 781, PT_SC, ucp_Medefaidrin },
+ { 793, PT_SC, ucp_Meetei_Mayek },
+ { 806, PT_SC, ucp_Mende_Kikakui },
+ { 820, PT_SC, ucp_Meroitic_Cursive },
+ { 837, PT_SC, ucp_Meroitic_Hieroglyphs },
+ { 858, PT_SC, ucp_Miao },
+ { 863, PT_PC, ucp_Mn },
+ { 866, PT_SC, ucp_Modi },
+ { 871, PT_SC, ucp_Mongolian },
+ { 881, PT_SC, ucp_Mro },
+ { 885, PT_SC, ucp_Multani },
+ { 893, PT_SC, ucp_Myanmar },
+ { 901, PT_GC, ucp_N },
+ { 903, PT_SC, ucp_Nabataean },
+ { 913, PT_PC, ucp_Nd },
+ { 916, PT_SC, ucp_New_Tai_Lue },
+ { 928, PT_SC, ucp_Newa },
+ { 933, PT_SC, ucp_Nko },
+ { 937, PT_PC, ucp_Nl },
+ { 940, PT_PC, ucp_No },
+ { 943, PT_SC, ucp_Nushu },
+ { 949, PT_SC, ucp_Ogham },
+ { 955, PT_SC, ucp_Ol_Chiki },
+ { 964, PT_SC, ucp_Old_Hungarian },
+ { 978, PT_SC, ucp_Old_Italic },
+ { 989, PT_SC, ucp_Old_North_Arabian },
+ { 1007, PT_SC, ucp_Old_Permic },
+ { 1018, PT_SC, ucp_Old_Persian },
+ { 1030, PT_SC, ucp_Old_Sogdian },
+ { 1042, PT_SC, ucp_Old_South_Arabian },
+ { 1060, PT_SC, ucp_Old_Turkic },
+ { 1071, PT_SC, ucp_Oriya },
+ { 1077, PT_SC, ucp_Osage },
+ { 1083, PT_SC, ucp_Osmanya },
+ { 1091, PT_GC, ucp_P },
+ { 1093, PT_SC, ucp_Pahawh_Hmong },
+ { 1106, PT_SC, ucp_Palmyrene },
+ { 1116, PT_SC, ucp_Pau_Cin_Hau },
+ { 1128, PT_PC, ucp_Pc },
+ { 1131, PT_PC, ucp_Pd },
+ { 1134, PT_PC, ucp_Pe },
+ { 1137, PT_PC, ucp_Pf },
+ { 1140, PT_SC, ucp_Phags_Pa },
+ { 1149, PT_SC, ucp_Phoenician },
+ { 1160, PT_PC, ucp_Pi },
+ { 1163, PT_PC, ucp_Po },
+ { 1166, PT_PC, ucp_Ps },
+ { 1169, PT_SC, ucp_Psalter_Pahlavi },
+ { 1185, PT_SC, ucp_Rejang },
+ { 1192, PT_SC, ucp_Runic },
+ { 1198, PT_GC, ucp_S },
+ { 1200, PT_SC, ucp_Samaritan },
+ { 1210, PT_SC, ucp_Saurashtra },
+ { 1221, PT_PC, ucp_Sc },
+ { 1224, PT_SC, ucp_Sharada },
+ { 1232, PT_SC, ucp_Shavian },
+ { 1240, PT_SC, ucp_Siddham },
+ { 1248, PT_SC, ucp_SignWriting },
+ { 1260, PT_SC, ucp_Sinhala },
+ { 1268, PT_PC, ucp_Sk },
+ { 1271, PT_PC, ucp_Sm },
+ { 1274, PT_PC, ucp_So },
+ { 1277, PT_SC, ucp_Sogdian },
+ { 1285, PT_SC, ucp_Sora_Sompeng },
+ { 1298, PT_SC, ucp_Soyombo },
+ { 1306, PT_SC, ucp_Sundanese },
+ { 1316, PT_SC, ucp_Syloti_Nagri },
+ { 1329, PT_SC, ucp_Syriac },
+ { 1336, PT_SC, ucp_Tagalog },
+ { 1344, PT_SC, ucp_Tagbanwa },
+ { 1353, PT_SC, ucp_Tai_Le },
+ { 1360, PT_SC, ucp_Tai_Tham },
+ { 1369, PT_SC, ucp_Tai_Viet },
+ { 1378, PT_SC, ucp_Takri },
+ { 1384, PT_SC, ucp_Tamil },
+ { 1390, PT_SC, ucp_Tangut },
+ { 1397, PT_SC, ucp_Telugu },
+ { 1404, PT_SC, ucp_Thaana },
+ { 1411, PT_SC, ucp_Thai },
+ { 1416, PT_SC, ucp_Tibetan },
+ { 1424, PT_SC, ucp_Tifinagh },
+ { 1433, PT_SC, ucp_Tirhuta },
+ { 1441, PT_SC, ucp_Ugaritic },
+ { 1450, PT_SC, ucp_Vai },
+ { 1454, PT_SC, ucp_Warang_Citi },
+ { 1466, PT_ALNUM, 0 },
+ { 1470, PT_PXSPACE, 0 },
+ { 1474, PT_SPACE, 0 },
+ { 1478, PT_UCNC, 0 },
+ { 1482, PT_WORD, 0 },
+ { 1486, PT_SC, ucp_Yi },
+ { 1489, PT_GC, ucp_Z },
+ { 1491, PT_SC, ucp_Zanabazar_Square },
+ { 1508, PT_PC, ucp_Zl },
+ { 1511, PT_PC, ucp_Zp },
+ { 1514, PT_PC, ucp_Zs }
};
const size_t PRIV(utt_size) = sizeof(PRIV(utt)) / sizeof(ucp_type_table);
diff --git a/thirdparty/pcre2/src/pcre2_ucd.c b/thirdparty/pcre2/src/pcre2_ucd.c
index ac7649b99e..275a4be2fe 100644
--- a/thirdparty/pcre2/src/pcre2_ucd.c
+++ b/thirdparty/pcre2/src/pcre2_ucd.c
@@ -20,7 +20,7 @@ needed. */
/* Unicode character database. */
/* This file was autogenerated by the MultiStage2.py script. */
-/* Total size: 80808 bytes, block size: 128. */
+/* Total size: 92592 bytes, block size: 128. */
/* The tables herein are needed only when UCP support is built,
and in PCRE2 that happens automatically with UTF support.
@@ -34,12 +34,12 @@ Instead, just supply small dummy tables. */
#ifndef SUPPORT_UNICODE
const ucd_record PRIV(ucd_records)[] = {{0,0,0,0,0 }};
-const uint8_t PRIV(ucd_stage1)[] = {0};
+const uint16_t PRIV(ucd_stage1)[] = {0};
const uint16_t PRIV(ucd_stage2)[] = {0};
const uint32_t PRIV(ucd_caseless_sets)[] = {0};
#else
-const char *PRIV(unicode_version) = "10.0.0";
+const char *PRIV(unicode_version) = "11.0.0";
/* If the 32-bit library is run in non-32-bit mode, character values
greater than 0x10ffff may be encountered. For these we set up a
@@ -104,7 +104,7 @@ const uint32_t PRIV(ucd_caseless_sets)[] = {
#ifndef PCRE2_PCRE2TEST
-const ucd_record PRIV(ucd_records)[] = { /* 6568 bytes, record size 8 */
+const ucd_record PRIV(ucd_records)[] = { /* 6832 bytes, record size 8 */
{ 9, 0, 2, 0, 0, }, /* 0 */
{ 9, 0, 1, 0, 0, }, /* 1 */
{ 9, 0, 0, 0, 0, }, /* 2 */
@@ -125,1357 +125,1390 @@ const ucd_record PRIV(ucd_records)[] = { /* 6568 bytes, record size 8 */
{ 33, 5, 12, 100, -32, }, /* 17 */
{ 33, 5, 12, 1, -32, }, /* 18 */
{ 9, 26, 12, 0, 0, }, /* 19 */
- { 33, 7, 12, 0, 0, }, /* 20 */
- { 9, 20, 12, 0, 0, }, /* 21 */
- { 9, 1, 2, 0, 0, }, /* 22 */
- { 9, 15, 12, 0, 0, }, /* 23 */
- { 9, 5, 12, 26, 775, }, /* 24 */
- { 9, 19, 12, 0, 0, }, /* 25 */
- { 33, 9, 12, 104, 32, }, /* 26 */
- { 33, 5, 12, 0, 7615, }, /* 27 */
- { 33, 5, 12, 104, -32, }, /* 28 */
- { 33, 5, 12, 0, 121, }, /* 29 */
- { 33, 9, 12, 0, 1, }, /* 30 */
- { 33, 5, 12, 0, -1, }, /* 31 */
- { 33, 9, 12, 0, 0, }, /* 32 */
- { 33, 5, 12, 0, 0, }, /* 33 */
- { 33, 9, 12, 0, -121, }, /* 34 */
- { 33, 5, 12, 1, -268, }, /* 35 */
- { 33, 5, 12, 0, 195, }, /* 36 */
- { 33, 9, 12, 0, 210, }, /* 37 */
- { 33, 9, 12, 0, 206, }, /* 38 */
- { 33, 9, 12, 0, 205, }, /* 39 */
- { 33, 9, 12, 0, 79, }, /* 40 */
- { 33, 9, 12, 0, 202, }, /* 41 */
- { 33, 9, 12, 0, 203, }, /* 42 */
- { 33, 9, 12, 0, 207, }, /* 43 */
- { 33, 5, 12, 0, 97, }, /* 44 */
- { 33, 9, 12, 0, 211, }, /* 45 */
- { 33, 9, 12, 0, 209, }, /* 46 */
- { 33, 5, 12, 0, 163, }, /* 47 */
- { 33, 9, 12, 0, 213, }, /* 48 */
- { 33, 5, 12, 0, 130, }, /* 49 */
- { 33, 9, 12, 0, 214, }, /* 50 */
- { 33, 9, 12, 0, 218, }, /* 51 */
- { 33, 9, 12, 0, 217, }, /* 52 */
- { 33, 9, 12, 0, 219, }, /* 53 */
- { 33, 5, 12, 0, 56, }, /* 54 */
- { 33, 9, 12, 5, 2, }, /* 55 */
- { 33, 8, 12, 5, 1, }, /* 56 */
- { 33, 5, 12, 5, -2, }, /* 57 */
- { 33, 9, 12, 9, 2, }, /* 58 */
- { 33, 8, 12, 9, 1, }, /* 59 */
- { 33, 5, 12, 9, -2, }, /* 60 */
- { 33, 9, 12, 13, 2, }, /* 61 */
- { 33, 8, 12, 13, 1, }, /* 62 */
- { 33, 5, 12, 13, -2, }, /* 63 */
- { 33, 5, 12, 0, -79, }, /* 64 */
- { 33, 9, 12, 17, 2, }, /* 65 */
- { 33, 8, 12, 17, 1, }, /* 66 */
- { 33, 5, 12, 17, -2, }, /* 67 */
- { 33, 9, 12, 0, -97, }, /* 68 */
- { 33, 9, 12, 0, -56, }, /* 69 */
- { 33, 9, 12, 0, -130, }, /* 70 */
- { 33, 9, 12, 0, 10795, }, /* 71 */
- { 33, 9, 12, 0, -163, }, /* 72 */
- { 33, 9, 12, 0, 10792, }, /* 73 */
- { 33, 5, 12, 0, 10815, }, /* 74 */
- { 33, 9, 12, 0, -195, }, /* 75 */
- { 33, 9, 12, 0, 69, }, /* 76 */
- { 33, 9, 12, 0, 71, }, /* 77 */
- { 33, 5, 12, 0, 10783, }, /* 78 */
- { 33, 5, 12, 0, 10780, }, /* 79 */
- { 33, 5, 12, 0, 10782, }, /* 80 */
- { 33, 5, 12, 0, -210, }, /* 81 */
- { 33, 5, 12, 0, -206, }, /* 82 */
- { 33, 5, 12, 0, -205, }, /* 83 */
- { 33, 5, 12, 0, -202, }, /* 84 */
- { 33, 5, 12, 0, -203, }, /* 85 */
- { 33, 5, 12, 0, 42319, }, /* 86 */
- { 33, 5, 12, 0, 42315, }, /* 87 */
- { 33, 5, 12, 0, -207, }, /* 88 */
- { 33, 5, 12, 0, 42280, }, /* 89 */
- { 33, 5, 12, 0, 42308, }, /* 90 */
- { 33, 5, 12, 0, -209, }, /* 91 */
- { 33, 5, 12, 0, -211, }, /* 92 */
- { 33, 5, 12, 0, 10743, }, /* 93 */
- { 33, 5, 12, 0, 42305, }, /* 94 */
- { 33, 5, 12, 0, 10749, }, /* 95 */
- { 33, 5, 12, 0, -213, }, /* 96 */
- { 33, 5, 12, 0, -214, }, /* 97 */
- { 33, 5, 12, 0, 10727, }, /* 98 */
- { 33, 5, 12, 0, -218, }, /* 99 */
- { 33, 5, 12, 0, 42282, }, /* 100 */
- { 33, 5, 12, 0, -69, }, /* 101 */
- { 33, 5, 12, 0, -217, }, /* 102 */
- { 33, 5, 12, 0, -71, }, /* 103 */
- { 33, 5, 12, 0, -219, }, /* 104 */
- { 33, 5, 12, 0, 42261, }, /* 105 */
- { 33, 5, 12, 0, 42258, }, /* 106 */
- { 33, 6, 12, 0, 0, }, /* 107 */
- { 9, 6, 12, 0, 0, }, /* 108 */
- { 3, 24, 12, 0, 0, }, /* 109 */
- { 27, 12, 3, 0, 0, }, /* 110 */
- { 27, 12, 3, 21, 116, }, /* 111 */
- { 19, 9, 12, 0, 1, }, /* 112 */
- { 19, 5, 12, 0, -1, }, /* 113 */
- { 19, 24, 12, 0, 0, }, /* 114 */
- { 9, 2, 12, 0, 0, }, /* 115 */
- { 19, 6, 12, 0, 0, }, /* 116 */
- { 19, 5, 12, 0, 130, }, /* 117 */
- { 19, 9, 12, 0, 116, }, /* 118 */
- { 19, 9, 12, 0, 38, }, /* 119 */
- { 19, 9, 12, 0, 37, }, /* 120 */
- { 19, 9, 12, 0, 64, }, /* 121 */
- { 19, 9, 12, 0, 63, }, /* 122 */
- { 19, 5, 12, 0, 0, }, /* 123 */
- { 19, 9, 12, 0, 32, }, /* 124 */
- { 19, 9, 12, 34, 32, }, /* 125 */
- { 19, 9, 12, 59, 32, }, /* 126 */
- { 19, 9, 12, 38, 32, }, /* 127 */
- { 19, 9, 12, 21, 32, }, /* 128 */
- { 19, 9, 12, 51, 32, }, /* 129 */
- { 19, 9, 12, 26, 32, }, /* 130 */
- { 19, 9, 12, 47, 32, }, /* 131 */
- { 19, 9, 12, 55, 32, }, /* 132 */
- { 19, 9, 12, 30, 32, }, /* 133 */
- { 19, 9, 12, 43, 32, }, /* 134 */
- { 19, 9, 12, 96, 32, }, /* 135 */
- { 19, 5, 12, 0, -38, }, /* 136 */
- { 19, 5, 12, 0, -37, }, /* 137 */
- { 19, 5, 12, 0, -32, }, /* 138 */
- { 19, 5, 12, 34, -32, }, /* 139 */
- { 19, 5, 12, 59, -32, }, /* 140 */
- { 19, 5, 12, 38, -32, }, /* 141 */
- { 19, 5, 12, 21, -116, }, /* 142 */
- { 19, 5, 12, 51, -32, }, /* 143 */
- { 19, 5, 12, 26, -775, }, /* 144 */
- { 19, 5, 12, 47, -32, }, /* 145 */
- { 19, 5, 12, 55, -32, }, /* 146 */
- { 19, 5, 12, 30, 1, }, /* 147 */
- { 19, 5, 12, 30, -32, }, /* 148 */
- { 19, 5, 12, 43, -32, }, /* 149 */
- { 19, 5, 12, 96, -32, }, /* 150 */
- { 19, 5, 12, 0, -64, }, /* 151 */
- { 19, 5, 12, 0, -63, }, /* 152 */
- { 19, 9, 12, 0, 8, }, /* 153 */
- { 19, 5, 12, 34, -30, }, /* 154 */
- { 19, 5, 12, 38, -25, }, /* 155 */
- { 19, 9, 12, 0, 0, }, /* 156 */
- { 19, 5, 12, 43, -15, }, /* 157 */
- { 19, 5, 12, 47, -22, }, /* 158 */
- { 19, 5, 12, 0, -8, }, /* 159 */
- { 10, 9, 12, 0, 1, }, /* 160 */
- { 10, 5, 12, 0, -1, }, /* 161 */
- { 19, 5, 12, 51, -54, }, /* 162 */
- { 19, 5, 12, 55, -48, }, /* 163 */
- { 19, 5, 12, 0, 7, }, /* 164 */
- { 19, 5, 12, 0, -116, }, /* 165 */
- { 19, 9, 12, 38, -60, }, /* 166 */
- { 19, 5, 12, 59, -64, }, /* 167 */
- { 19, 25, 12, 0, 0, }, /* 168 */
- { 19, 9, 12, 0, -7, }, /* 169 */
- { 19, 9, 12, 0, -130, }, /* 170 */
- { 12, 9, 12, 0, 80, }, /* 171 */
- { 12, 9, 12, 0, 32, }, /* 172 */
- { 12, 9, 12, 63, 32, }, /* 173 */
- { 12, 9, 12, 67, 32, }, /* 174 */
- { 12, 9, 12, 71, 32, }, /* 175 */
- { 12, 9, 12, 75, 32, }, /* 176 */
- { 12, 9, 12, 79, 32, }, /* 177 */
- { 12, 9, 12, 84, 32, }, /* 178 */
- { 12, 5, 12, 0, -32, }, /* 179 */
- { 12, 5, 12, 63, -32, }, /* 180 */
- { 12, 5, 12, 67, -32, }, /* 181 */
- { 12, 5, 12, 71, -32, }, /* 182 */
- { 12, 5, 12, 75, -32, }, /* 183 */
- { 12, 5, 12, 79, -32, }, /* 184 */
- { 12, 5, 12, 84, -32, }, /* 185 */
- { 12, 5, 12, 0, -80, }, /* 186 */
- { 12, 9, 12, 0, 1, }, /* 187 */
- { 12, 5, 12, 0, -1, }, /* 188 */
- { 12, 9, 12, 88, 1, }, /* 189 */
- { 12, 5, 12, 88, -1, }, /* 190 */
- { 12, 26, 12, 0, 0, }, /* 191 */
- { 12, 12, 3, 0, 0, }, /* 192 */
- { 12, 11, 3, 0, 0, }, /* 193 */
- { 12, 9, 12, 0, 15, }, /* 194 */
- { 12, 5, 12, 0, -15, }, /* 195 */
- { 1, 9, 12, 0, 48, }, /* 196 */
- { 1, 6, 12, 0, 0, }, /* 197 */
- { 1, 21, 12, 0, 0, }, /* 198 */
- { 1, 5, 12, 0, -48, }, /* 199 */
+ { 9, 26, 14, 0, 0, }, /* 20 */
+ { 33, 7, 12, 0, 0, }, /* 21 */
+ { 9, 20, 12, 0, 0, }, /* 22 */
+ { 9, 1, 2, 0, 0, }, /* 23 */
+ { 9, 15, 12, 0, 0, }, /* 24 */
+ { 9, 5, 12, 26, 775, }, /* 25 */
+ { 9, 19, 12, 0, 0, }, /* 26 */
+ { 33, 9, 12, 104, 32, }, /* 27 */
+ { 33, 5, 12, 0, 7615, }, /* 28 */
+ { 33, 5, 12, 104, -32, }, /* 29 */
+ { 33, 5, 12, 0, 121, }, /* 30 */
+ { 33, 9, 12, 0, 1, }, /* 31 */
+ { 33, 5, 12, 0, -1, }, /* 32 */
+ { 33, 9, 12, 0, 0, }, /* 33 */
+ { 33, 5, 12, 0, 0, }, /* 34 */
+ { 33, 9, 12, 0, -121, }, /* 35 */
+ { 33, 5, 12, 1, -268, }, /* 36 */
+ { 33, 5, 12, 0, 195, }, /* 37 */
+ { 33, 9, 12, 0, 210, }, /* 38 */
+ { 33, 9, 12, 0, 206, }, /* 39 */
+ { 33, 9, 12, 0, 205, }, /* 40 */
+ { 33, 9, 12, 0, 79, }, /* 41 */
+ { 33, 9, 12, 0, 202, }, /* 42 */
+ { 33, 9, 12, 0, 203, }, /* 43 */
+ { 33, 9, 12, 0, 207, }, /* 44 */
+ { 33, 5, 12, 0, 97, }, /* 45 */
+ { 33, 9, 12, 0, 211, }, /* 46 */
+ { 33, 9, 12, 0, 209, }, /* 47 */
+ { 33, 5, 12, 0, 163, }, /* 48 */
+ { 33, 9, 12, 0, 213, }, /* 49 */
+ { 33, 5, 12, 0, 130, }, /* 50 */
+ { 33, 9, 12, 0, 214, }, /* 51 */
+ { 33, 9, 12, 0, 218, }, /* 52 */
+ { 33, 9, 12, 0, 217, }, /* 53 */
+ { 33, 9, 12, 0, 219, }, /* 54 */
+ { 33, 5, 12, 0, 56, }, /* 55 */
+ { 33, 9, 12, 5, 2, }, /* 56 */
+ { 33, 8, 12, 5, 1, }, /* 57 */
+ { 33, 5, 12, 5, -2, }, /* 58 */
+ { 33, 9, 12, 9, 2, }, /* 59 */
+ { 33, 8, 12, 9, 1, }, /* 60 */
+ { 33, 5, 12, 9, -2, }, /* 61 */
+ { 33, 9, 12, 13, 2, }, /* 62 */
+ { 33, 8, 12, 13, 1, }, /* 63 */
+ { 33, 5, 12, 13, -2, }, /* 64 */
+ { 33, 5, 12, 0, -79, }, /* 65 */
+ { 33, 9, 12, 17, 2, }, /* 66 */
+ { 33, 8, 12, 17, 1, }, /* 67 */
+ { 33, 5, 12, 17, -2, }, /* 68 */
+ { 33, 9, 12, 0, -97, }, /* 69 */
+ { 33, 9, 12, 0, -56, }, /* 70 */
+ { 33, 9, 12, 0, -130, }, /* 71 */
+ { 33, 9, 12, 0, 10795, }, /* 72 */
+ { 33, 9, 12, 0, -163, }, /* 73 */
+ { 33, 9, 12, 0, 10792, }, /* 74 */
+ { 33, 5, 12, 0, 10815, }, /* 75 */
+ { 33, 9, 12, 0, -195, }, /* 76 */
+ { 33, 9, 12, 0, 69, }, /* 77 */
+ { 33, 9, 12, 0, 71, }, /* 78 */
+ { 33, 5, 12, 0, 10783, }, /* 79 */
+ { 33, 5, 12, 0, 10780, }, /* 80 */
+ { 33, 5, 12, 0, 10782, }, /* 81 */
+ { 33, 5, 12, 0, -210, }, /* 82 */
+ { 33, 5, 12, 0, -206, }, /* 83 */
+ { 33, 5, 12, 0, -205, }, /* 84 */
+ { 33, 5, 12, 0, -202, }, /* 85 */
+ { 33, 5, 12, 0, -203, }, /* 86 */
+ { 33, 5, 12, 0, 42319, }, /* 87 */
+ { 33, 5, 12, 0, 42315, }, /* 88 */
+ { 33, 5, 12, 0, -207, }, /* 89 */
+ { 33, 5, 12, 0, 42280, }, /* 90 */
+ { 33, 5, 12, 0, 42308, }, /* 91 */
+ { 33, 5, 12, 0, -209, }, /* 92 */
+ { 33, 5, 12, 0, -211, }, /* 93 */
+ { 33, 5, 12, 0, 10743, }, /* 94 */
+ { 33, 5, 12, 0, 42305, }, /* 95 */
+ { 33, 5, 12, 0, 10749, }, /* 96 */
+ { 33, 5, 12, 0, -213, }, /* 97 */
+ { 33, 5, 12, 0, -214, }, /* 98 */
+ { 33, 5, 12, 0, 10727, }, /* 99 */
+ { 33, 5, 12, 0, -218, }, /* 100 */
+ { 33, 5, 12, 0, 42282, }, /* 101 */
+ { 33, 5, 12, 0, -69, }, /* 102 */
+ { 33, 5, 12, 0, -217, }, /* 103 */
+ { 33, 5, 12, 0, -71, }, /* 104 */
+ { 33, 5, 12, 0, -219, }, /* 105 */
+ { 33, 5, 12, 0, 42261, }, /* 106 */
+ { 33, 5, 12, 0, 42258, }, /* 107 */
+ { 33, 6, 12, 0, 0, }, /* 108 */
+ { 9, 6, 12, 0, 0, }, /* 109 */
+ { 3, 24, 12, 0, 0, }, /* 110 */
+ { 27, 12, 3, 0, 0, }, /* 111 */
+ { 27, 12, 3, 21, 116, }, /* 112 */
+ { 19, 9, 12, 0, 1, }, /* 113 */
+ { 19, 5, 12, 0, -1, }, /* 114 */
+ { 19, 24, 12, 0, 0, }, /* 115 */
+ { 9, 2, 12, 0, 0, }, /* 116 */
+ { 19, 6, 12, 0, 0, }, /* 117 */
+ { 19, 5, 12, 0, 130, }, /* 118 */
+ { 19, 9, 12, 0, 116, }, /* 119 */
+ { 19, 9, 12, 0, 38, }, /* 120 */
+ { 19, 9, 12, 0, 37, }, /* 121 */
+ { 19, 9, 12, 0, 64, }, /* 122 */
+ { 19, 9, 12, 0, 63, }, /* 123 */
+ { 19, 5, 12, 0, 0, }, /* 124 */
+ { 19, 9, 12, 0, 32, }, /* 125 */
+ { 19, 9, 12, 34, 32, }, /* 126 */
+ { 19, 9, 12, 59, 32, }, /* 127 */
+ { 19, 9, 12, 38, 32, }, /* 128 */
+ { 19, 9, 12, 21, 32, }, /* 129 */
+ { 19, 9, 12, 51, 32, }, /* 130 */
+ { 19, 9, 12, 26, 32, }, /* 131 */
+ { 19, 9, 12, 47, 32, }, /* 132 */
+ { 19, 9, 12, 55, 32, }, /* 133 */
+ { 19, 9, 12, 30, 32, }, /* 134 */
+ { 19, 9, 12, 43, 32, }, /* 135 */
+ { 19, 9, 12, 96, 32, }, /* 136 */
+ { 19, 5, 12, 0, -38, }, /* 137 */
+ { 19, 5, 12, 0, -37, }, /* 138 */
+ { 19, 5, 12, 0, -32, }, /* 139 */
+ { 19, 5, 12, 34, -32, }, /* 140 */
+ { 19, 5, 12, 59, -32, }, /* 141 */
+ { 19, 5, 12, 38, -32, }, /* 142 */
+ { 19, 5, 12, 21, -116, }, /* 143 */
+ { 19, 5, 12, 51, -32, }, /* 144 */
+ { 19, 5, 12, 26, -775, }, /* 145 */
+ { 19, 5, 12, 47, -32, }, /* 146 */
+ { 19, 5, 12, 55, -32, }, /* 147 */
+ { 19, 5, 12, 30, 1, }, /* 148 */
+ { 19, 5, 12, 30, -32, }, /* 149 */
+ { 19, 5, 12, 43, -32, }, /* 150 */
+ { 19, 5, 12, 96, -32, }, /* 151 */
+ { 19, 5, 12, 0, -64, }, /* 152 */
+ { 19, 5, 12, 0, -63, }, /* 153 */
+ { 19, 9, 12, 0, 8, }, /* 154 */
+ { 19, 5, 12, 34, -30, }, /* 155 */
+ { 19, 5, 12, 38, -25, }, /* 156 */
+ { 19, 9, 12, 0, 0, }, /* 157 */
+ { 19, 5, 12, 43, -15, }, /* 158 */
+ { 19, 5, 12, 47, -22, }, /* 159 */
+ { 19, 5, 12, 0, -8, }, /* 160 */
+ { 10, 9, 12, 0, 1, }, /* 161 */
+ { 10, 5, 12, 0, -1, }, /* 162 */
+ { 19, 5, 12, 51, -54, }, /* 163 */
+ { 19, 5, 12, 55, -48, }, /* 164 */
+ { 19, 5, 12, 0, 7, }, /* 165 */
+ { 19, 5, 12, 0, -116, }, /* 166 */
+ { 19, 9, 12, 38, -60, }, /* 167 */
+ { 19, 5, 12, 59, -64, }, /* 168 */
+ { 19, 25, 12, 0, 0, }, /* 169 */
+ { 19, 9, 12, 0, -7, }, /* 170 */
+ { 19, 9, 12, 0, -130, }, /* 171 */
+ { 12, 9, 12, 0, 80, }, /* 172 */
+ { 12, 9, 12, 0, 32, }, /* 173 */
+ { 12, 9, 12, 63, 32, }, /* 174 */
+ { 12, 9, 12, 67, 32, }, /* 175 */
+ { 12, 9, 12, 71, 32, }, /* 176 */
+ { 12, 9, 12, 75, 32, }, /* 177 */
+ { 12, 9, 12, 79, 32, }, /* 178 */
+ { 12, 9, 12, 84, 32, }, /* 179 */
+ { 12, 5, 12, 0, -32, }, /* 180 */
+ { 12, 5, 12, 63, -32, }, /* 181 */
+ { 12, 5, 12, 67, -32, }, /* 182 */
+ { 12, 5, 12, 71, -32, }, /* 183 */
+ { 12, 5, 12, 75, -32, }, /* 184 */
+ { 12, 5, 12, 79, -32, }, /* 185 */
+ { 12, 5, 12, 84, -32, }, /* 186 */
+ { 12, 5, 12, 0, -80, }, /* 187 */
+ { 12, 9, 12, 0, 1, }, /* 188 */
+ { 12, 5, 12, 0, -1, }, /* 189 */
+ { 12, 9, 12, 88, 1, }, /* 190 */
+ { 12, 5, 12, 88, -1, }, /* 191 */
+ { 12, 26, 12, 0, 0, }, /* 192 */
+ { 12, 12, 3, 0, 0, }, /* 193 */
+ { 12, 11, 3, 0, 0, }, /* 194 */
+ { 12, 9, 12, 0, 15, }, /* 195 */
+ { 12, 5, 12, 0, -15, }, /* 196 */
+ { 1, 9, 12, 0, 48, }, /* 197 */
+ { 1, 6, 12, 0, 0, }, /* 198 */
+ { 1, 21, 12, 0, 0, }, /* 199 */
{ 1, 5, 12, 0, 0, }, /* 200 */
- { 1, 17, 12, 0, 0, }, /* 201 */
- { 1, 26, 12, 0, 0, }, /* 202 */
- { 1, 23, 12, 0, 0, }, /* 203 */
- { 25, 12, 3, 0, 0, }, /* 204 */
- { 25, 17, 12, 0, 0, }, /* 205 */
- { 25, 21, 12, 0, 0, }, /* 206 */
- { 25, 7, 12, 0, 0, }, /* 207 */
- { 0, 1, 4, 0, 0, }, /* 208 */
- { 9, 1, 4, 0, 0, }, /* 209 */
- { 0, 25, 12, 0, 0, }, /* 210 */
- { 0, 21, 12, 0, 0, }, /* 211 */
- { 0, 23, 12, 0, 0, }, /* 212 */
- { 0, 26, 12, 0, 0, }, /* 213 */
- { 0, 12, 3, 0, 0, }, /* 214 */
- { 0, 1, 2, 0, 0, }, /* 215 */
- { 0, 7, 12, 0, 0, }, /* 216 */
- { 0, 13, 12, 0, 0, }, /* 217 */
- { 0, 6, 12, 0, 0, }, /* 218 */
- { 49, 21, 12, 0, 0, }, /* 219 */
- { 49, 1, 4, 0, 0, }, /* 220 */
- { 49, 7, 12, 0, 0, }, /* 221 */
- { 49, 12, 3, 0, 0, }, /* 222 */
- { 55, 7, 12, 0, 0, }, /* 223 */
- { 55, 12, 3, 0, 0, }, /* 224 */
- { 63, 13, 12, 0, 0, }, /* 225 */
- { 63, 7, 12, 0, 0, }, /* 226 */
- { 63, 12, 3, 0, 0, }, /* 227 */
- { 63, 6, 12, 0, 0, }, /* 228 */
- { 63, 26, 12, 0, 0, }, /* 229 */
- { 63, 21, 12, 0, 0, }, /* 230 */
- { 89, 7, 12, 0, 0, }, /* 231 */
- { 89, 12, 3, 0, 0, }, /* 232 */
- { 89, 6, 12, 0, 0, }, /* 233 */
- { 89, 21, 12, 0, 0, }, /* 234 */
- { 94, 7, 12, 0, 0, }, /* 235 */
- { 94, 12, 3, 0, 0, }, /* 236 */
- { 94, 21, 12, 0, 0, }, /* 237 */
- { 14, 12, 3, 0, 0, }, /* 238 */
- { 14, 10, 5, 0, 0, }, /* 239 */
- { 14, 7, 12, 0, 0, }, /* 240 */
- { 14, 13, 12, 0, 0, }, /* 241 */
- { 14, 21, 12, 0, 0, }, /* 242 */
- { 14, 6, 12, 0, 0, }, /* 243 */
- { 2, 7, 12, 0, 0, }, /* 244 */
- { 2, 12, 3, 0, 0, }, /* 245 */
- { 2, 10, 5, 0, 0, }, /* 246 */
- { 2, 10, 3, 0, 0, }, /* 247 */
- { 2, 13, 12, 0, 0, }, /* 248 */
- { 2, 23, 12, 0, 0, }, /* 249 */
- { 2, 15, 12, 0, 0, }, /* 250 */
- { 2, 26, 12, 0, 0, }, /* 251 */
- { 2, 21, 12, 0, 0, }, /* 252 */
- { 21, 12, 3, 0, 0, }, /* 253 */
- { 21, 10, 5, 0, 0, }, /* 254 */
- { 21, 7, 12, 0, 0, }, /* 255 */
- { 21, 13, 12, 0, 0, }, /* 256 */
- { 20, 12, 3, 0, 0, }, /* 257 */
- { 20, 10, 5, 0, 0, }, /* 258 */
- { 20, 7, 12, 0, 0, }, /* 259 */
- { 20, 13, 12, 0, 0, }, /* 260 */
- { 20, 21, 12, 0, 0, }, /* 261 */
- { 20, 23, 12, 0, 0, }, /* 262 */
- { 43, 12, 3, 0, 0, }, /* 263 */
- { 43, 10, 5, 0, 0, }, /* 264 */
- { 43, 7, 12, 0, 0, }, /* 265 */
- { 43, 10, 3, 0, 0, }, /* 266 */
- { 43, 13, 12, 0, 0, }, /* 267 */
- { 43, 26, 12, 0, 0, }, /* 268 */
- { 43, 15, 12, 0, 0, }, /* 269 */
- { 53, 12, 3, 0, 0, }, /* 270 */
- { 53, 7, 12, 0, 0, }, /* 271 */
- { 53, 10, 3, 0, 0, }, /* 272 */
- { 53, 10, 5, 0, 0, }, /* 273 */
- { 53, 13, 12, 0, 0, }, /* 274 */
- { 53, 15, 12, 0, 0, }, /* 275 */
- { 53, 26, 12, 0, 0, }, /* 276 */
- { 53, 23, 12, 0, 0, }, /* 277 */
- { 54, 12, 3, 0, 0, }, /* 278 */
- { 54, 10, 5, 0, 0, }, /* 279 */
- { 54, 7, 12, 0, 0, }, /* 280 */
- { 54, 13, 12, 0, 0, }, /* 281 */
- { 54, 15, 12, 0, 0, }, /* 282 */
- { 54, 26, 12, 0, 0, }, /* 283 */
- { 28, 7, 12, 0, 0, }, /* 284 */
- { 28, 12, 3, 0, 0, }, /* 285 */
- { 28, 10, 5, 0, 0, }, /* 286 */
- { 28, 10, 3, 0, 0, }, /* 287 */
- { 28, 13, 12, 0, 0, }, /* 288 */
- { 36, 12, 3, 0, 0, }, /* 289 */
- { 36, 10, 5, 0, 0, }, /* 290 */
- { 36, 7, 12, 0, 0, }, /* 291 */
- { 36, 10, 3, 0, 0, }, /* 292 */
- { 36, 7, 4, 0, 0, }, /* 293 */
- { 36, 26, 12, 0, 0, }, /* 294 */
- { 36, 15, 12, 0, 0, }, /* 295 */
- { 36, 13, 12, 0, 0, }, /* 296 */
- { 47, 10, 5, 0, 0, }, /* 297 */
- { 47, 7, 12, 0, 0, }, /* 298 */
- { 47, 12, 3, 0, 0, }, /* 299 */
- { 47, 10, 3, 0, 0, }, /* 300 */
- { 47, 13, 12, 0, 0, }, /* 301 */
- { 47, 21, 12, 0, 0, }, /* 302 */
- { 56, 7, 12, 0, 0, }, /* 303 */
- { 56, 12, 3, 0, 0, }, /* 304 */
- { 56, 7, 5, 0, 0, }, /* 305 */
- { 56, 6, 12, 0, 0, }, /* 306 */
- { 56, 21, 12, 0, 0, }, /* 307 */
- { 56, 13, 12, 0, 0, }, /* 308 */
- { 32, 7, 12, 0, 0, }, /* 309 */
- { 32, 12, 3, 0, 0, }, /* 310 */
- { 32, 7, 5, 0, 0, }, /* 311 */
- { 32, 6, 12, 0, 0, }, /* 312 */
- { 32, 13, 12, 0, 0, }, /* 313 */
- { 57, 7, 12, 0, 0, }, /* 314 */
- { 57, 26, 12, 0, 0, }, /* 315 */
- { 57, 21, 12, 0, 0, }, /* 316 */
- { 57, 12, 3, 0, 0, }, /* 317 */
- { 57, 13, 12, 0, 0, }, /* 318 */
- { 57, 15, 12, 0, 0, }, /* 319 */
- { 57, 22, 12, 0, 0, }, /* 320 */
- { 57, 18, 12, 0, 0, }, /* 321 */
- { 57, 10, 5, 0, 0, }, /* 322 */
- { 38, 7, 12, 0, 0, }, /* 323 */
- { 38, 10, 12, 0, 0, }, /* 324 */
- { 38, 12, 3, 0, 0, }, /* 325 */
- { 38, 10, 5, 0, 0, }, /* 326 */
- { 38, 13, 12, 0, 0, }, /* 327 */
- { 38, 21, 12, 0, 0, }, /* 328 */
- { 38, 26, 12, 0, 0, }, /* 329 */
- { 16, 9, 12, 0, 7264, }, /* 330 */
- { 16, 7, 12, 0, 0, }, /* 331 */
- { 16, 6, 12, 0, 0, }, /* 332 */
- { 23, 7, 6, 0, 0, }, /* 333 */
- { 23, 7, 7, 0, 0, }, /* 334 */
- { 23, 7, 8, 0, 0, }, /* 335 */
- { 15, 7, 12, 0, 0, }, /* 336 */
- { 15, 12, 3, 0, 0, }, /* 337 */
- { 15, 21, 12, 0, 0, }, /* 338 */
- { 15, 15, 12, 0, 0, }, /* 339 */
- { 15, 26, 12, 0, 0, }, /* 340 */
- { 8, 9, 12, 0, 38864, }, /* 341 */
- { 8, 9, 12, 0, 8, }, /* 342 */
- { 8, 5, 12, 0, -8, }, /* 343 */
- { 7, 17, 12, 0, 0, }, /* 344 */
- { 7, 7, 12, 0, 0, }, /* 345 */
- { 7, 21, 12, 0, 0, }, /* 346 */
- { 40, 29, 12, 0, 0, }, /* 347 */
- { 40, 7, 12, 0, 0, }, /* 348 */
- { 40, 22, 12, 0, 0, }, /* 349 */
- { 40, 18, 12, 0, 0, }, /* 350 */
- { 45, 7, 12, 0, 0, }, /* 351 */
- { 45, 14, 12, 0, 0, }, /* 352 */
- { 50, 7, 12, 0, 0, }, /* 353 */
- { 50, 12, 3, 0, 0, }, /* 354 */
- { 24, 7, 12, 0, 0, }, /* 355 */
- { 24, 12, 3, 0, 0, }, /* 356 */
- { 6, 7, 12, 0, 0, }, /* 357 */
- { 6, 12, 3, 0, 0, }, /* 358 */
- { 51, 7, 12, 0, 0, }, /* 359 */
- { 51, 12, 3, 0, 0, }, /* 360 */
- { 31, 7, 12, 0, 0, }, /* 361 */
- { 31, 12, 3, 0, 0, }, /* 362 */
- { 31, 10, 5, 0, 0, }, /* 363 */
- { 31, 21, 12, 0, 0, }, /* 364 */
- { 31, 6, 12, 0, 0, }, /* 365 */
- { 31, 23, 12, 0, 0, }, /* 366 */
- { 31, 13, 12, 0, 0, }, /* 367 */
- { 31, 15, 12, 0, 0, }, /* 368 */
- { 37, 21, 12, 0, 0, }, /* 369 */
- { 37, 17, 12, 0, 0, }, /* 370 */
- { 37, 12, 3, 0, 0, }, /* 371 */
- { 37, 1, 2, 0, 0, }, /* 372 */
- { 37, 13, 12, 0, 0, }, /* 373 */
- { 37, 7, 12, 0, 0, }, /* 374 */
- { 37, 6, 12, 0, 0, }, /* 375 */
- { 34, 7, 12, 0, 0, }, /* 376 */
- { 34, 12, 3, 0, 0, }, /* 377 */
- { 34, 10, 5, 0, 0, }, /* 378 */
- { 34, 26, 12, 0, 0, }, /* 379 */
- { 34, 21, 12, 0, 0, }, /* 380 */
- { 34, 13, 12, 0, 0, }, /* 381 */
- { 52, 7, 12, 0, 0, }, /* 382 */
- { 39, 7, 12, 0, 0, }, /* 383 */
- { 39, 13, 12, 0, 0, }, /* 384 */
- { 39, 15, 12, 0, 0, }, /* 385 */
- { 39, 26, 12, 0, 0, }, /* 386 */
- { 31, 26, 12, 0, 0, }, /* 387 */
- { 5, 7, 12, 0, 0, }, /* 388 */
- { 5, 12, 3, 0, 0, }, /* 389 */
- { 5, 10, 5, 0, 0, }, /* 390 */
- { 5, 21, 12, 0, 0, }, /* 391 */
- { 90, 7, 12, 0, 0, }, /* 392 */
- { 90, 10, 5, 0, 0, }, /* 393 */
- { 90, 12, 3, 0, 0, }, /* 394 */
- { 90, 10, 12, 0, 0, }, /* 395 */
- { 90, 13, 12, 0, 0, }, /* 396 */
- { 90, 21, 12, 0, 0, }, /* 397 */
- { 90, 6, 12, 0, 0, }, /* 398 */
- { 27, 11, 3, 0, 0, }, /* 399 */
- { 61, 12, 3, 0, 0, }, /* 400 */
- { 61, 10, 5, 0, 0, }, /* 401 */
- { 61, 7, 12, 0, 0, }, /* 402 */
- { 61, 13, 12, 0, 0, }, /* 403 */
- { 61, 21, 12, 0, 0, }, /* 404 */
- { 61, 26, 12, 0, 0, }, /* 405 */
- { 75, 12, 3, 0, 0, }, /* 406 */
- { 75, 10, 5, 0, 0, }, /* 407 */
- { 75, 7, 12, 0, 0, }, /* 408 */
- { 75, 13, 12, 0, 0, }, /* 409 */
- { 92, 7, 12, 0, 0, }, /* 410 */
- { 92, 12, 3, 0, 0, }, /* 411 */
- { 92, 10, 5, 0, 0, }, /* 412 */
- { 92, 21, 12, 0, 0, }, /* 413 */
- { 69, 7, 12, 0, 0, }, /* 414 */
- { 69, 10, 5, 0, 0, }, /* 415 */
- { 69, 12, 3, 0, 0, }, /* 416 */
- { 69, 21, 12, 0, 0, }, /* 417 */
- { 69, 13, 12, 0, 0, }, /* 418 */
- { 72, 13, 12, 0, 0, }, /* 419 */
- { 72, 7, 12, 0, 0, }, /* 420 */
- { 72, 6, 12, 0, 0, }, /* 421 */
- { 72, 21, 12, 0, 0, }, /* 422 */
- { 12, 5, 12, 63, -6222, }, /* 423 */
- { 12, 5, 12, 67, -6221, }, /* 424 */
- { 12, 5, 12, 71, -6212, }, /* 425 */
- { 12, 5, 12, 75, -6210, }, /* 426 */
- { 12, 5, 12, 79, -6210, }, /* 427 */
- { 12, 5, 12, 79, -6211, }, /* 428 */
- { 12, 5, 12, 84, -6204, }, /* 429 */
- { 12, 5, 12, 88, -6180, }, /* 430 */
- { 12, 5, 12, 108, 35267, }, /* 431 */
- { 75, 21, 12, 0, 0, }, /* 432 */
- { 9, 10, 5, 0, 0, }, /* 433 */
- { 9, 7, 12, 0, 0, }, /* 434 */
- { 12, 5, 12, 0, 0, }, /* 435 */
- { 12, 6, 12, 0, 0, }, /* 436 */
- { 33, 5, 12, 0, 35332, }, /* 437 */
- { 33, 5, 12, 0, 3814, }, /* 438 */
- { 33, 9, 12, 92, 1, }, /* 439 */
- { 33, 5, 12, 92, -1, }, /* 440 */
- { 33, 5, 12, 92, -58, }, /* 441 */
- { 33, 9, 12, 0, -7615, }, /* 442 */
- { 19, 5, 12, 0, 8, }, /* 443 */
- { 19, 9, 12, 0, -8, }, /* 444 */
- { 19, 5, 12, 0, 74, }, /* 445 */
- { 19, 5, 12, 0, 86, }, /* 446 */
- { 19, 5, 12, 0, 100, }, /* 447 */
- { 19, 5, 12, 0, 128, }, /* 448 */
- { 19, 5, 12, 0, 112, }, /* 449 */
- { 19, 5, 12, 0, 126, }, /* 450 */
- { 19, 8, 12, 0, -8, }, /* 451 */
- { 19, 5, 12, 0, 9, }, /* 452 */
- { 19, 9, 12, 0, -74, }, /* 453 */
- { 19, 8, 12, 0, -9, }, /* 454 */
- { 19, 5, 12, 21, -7173, }, /* 455 */
- { 19, 9, 12, 0, -86, }, /* 456 */
- { 19, 9, 12, 0, -100, }, /* 457 */
- { 19, 9, 12, 0, -112, }, /* 458 */
- { 19, 9, 12, 0, -128, }, /* 459 */
- { 19, 9, 12, 0, -126, }, /* 460 */
- { 27, 1, 3, 0, 0, }, /* 461 */
- { 27, 1, 16, 0, 0, }, /* 462 */
- { 9, 27, 2, 0, 0, }, /* 463 */
- { 9, 28, 2, 0, 0, }, /* 464 */
- { 9, 2, 2, 0, 0, }, /* 465 */
- { 9, 9, 12, 0, 0, }, /* 466 */
- { 9, 5, 12, 0, 0, }, /* 467 */
- { 19, 9, 12, 96, -7517, }, /* 468 */
- { 33, 9, 12, 100, -8383, }, /* 469 */
- { 33, 9, 12, 104, -8262, }, /* 470 */
- { 33, 9, 12, 0, 28, }, /* 471 */
- { 33, 5, 12, 0, -28, }, /* 472 */
- { 33, 14, 12, 0, 16, }, /* 473 */
- { 33, 14, 12, 0, -16, }, /* 474 */
- { 33, 14, 12, 0, 0, }, /* 475 */
- { 9, 26, 12, 0, 26, }, /* 476 */
- { 9, 26, 12, 0, -26, }, /* 477 */
- { 9, 26, 13, 0, 0, }, /* 478 */
- { 9, 26, 17, 0, 0, }, /* 479 */
- { 4, 26, 12, 0, 0, }, /* 480 */
- { 17, 9, 12, 0, 48, }, /* 481 */
- { 17, 5, 12, 0, -48, }, /* 482 */
- { 33, 9, 12, 0, -10743, }, /* 483 */
- { 33, 9, 12, 0, -3814, }, /* 484 */
- { 33, 9, 12, 0, -10727, }, /* 485 */
- { 33, 5, 12, 0, -10795, }, /* 486 */
- { 33, 5, 12, 0, -10792, }, /* 487 */
- { 33, 9, 12, 0, -10780, }, /* 488 */
- { 33, 9, 12, 0, -10749, }, /* 489 */
- { 33, 9, 12, 0, -10783, }, /* 490 */
- { 33, 9, 12, 0, -10782, }, /* 491 */
- { 33, 9, 12, 0, -10815, }, /* 492 */
- { 10, 5, 12, 0, 0, }, /* 493 */
- { 10, 26, 12, 0, 0, }, /* 494 */
- { 10, 12, 3, 0, 0, }, /* 495 */
- { 10, 21, 12, 0, 0, }, /* 496 */
- { 10, 15, 12, 0, 0, }, /* 497 */
- { 16, 5, 12, 0, -7264, }, /* 498 */
- { 58, 7, 12, 0, 0, }, /* 499 */
- { 58, 6, 12, 0, 0, }, /* 500 */
- { 58, 21, 12, 0, 0, }, /* 501 */
- { 58, 12, 3, 0, 0, }, /* 502 */
- { 22, 26, 12, 0, 0, }, /* 503 */
- { 22, 6, 12, 0, 0, }, /* 504 */
- { 22, 14, 12, 0, 0, }, /* 505 */
- { 23, 10, 3, 0, 0, }, /* 506 */
- { 26, 7, 12, 0, 0, }, /* 507 */
- { 26, 6, 12, 0, 0, }, /* 508 */
- { 29, 7, 12, 0, 0, }, /* 509 */
- { 29, 6, 12, 0, 0, }, /* 510 */
- { 3, 7, 12, 0, 0, }, /* 511 */
- { 23, 7, 12, 0, 0, }, /* 512 */
- { 23, 26, 12, 0, 0, }, /* 513 */
- { 29, 26, 12, 0, 0, }, /* 514 */
- { 22, 7, 12, 0, 0, }, /* 515 */
- { 60, 7, 12, 0, 0, }, /* 516 */
- { 60, 6, 12, 0, 0, }, /* 517 */
- { 60, 26, 12, 0, 0, }, /* 518 */
- { 85, 7, 12, 0, 0, }, /* 519 */
- { 85, 6, 12, 0, 0, }, /* 520 */
- { 85, 21, 12, 0, 0, }, /* 521 */
- { 76, 7, 12, 0, 0, }, /* 522 */
- { 76, 6, 12, 0, 0, }, /* 523 */
- { 76, 21, 12, 0, 0, }, /* 524 */
- { 76, 13, 12, 0, 0, }, /* 525 */
- { 12, 9, 12, 108, 1, }, /* 526 */
- { 12, 5, 12, 108, -35267, }, /* 527 */
- { 12, 7, 12, 0, 0, }, /* 528 */
- { 12, 21, 12, 0, 0, }, /* 529 */
- { 78, 7, 12, 0, 0, }, /* 530 */
- { 78, 14, 12, 0, 0, }, /* 531 */
- { 78, 12, 3, 0, 0, }, /* 532 */
- { 78, 21, 12, 0, 0, }, /* 533 */
- { 33, 9, 12, 0, -35332, }, /* 534 */
- { 33, 9, 12, 0, -42280, }, /* 535 */
- { 33, 9, 12, 0, -42308, }, /* 536 */
- { 33, 9, 12, 0, -42319, }, /* 537 */
- { 33, 9, 12, 0, -42315, }, /* 538 */
- { 33, 9, 12, 0, -42305, }, /* 539 */
- { 33, 9, 12, 0, -42258, }, /* 540 */
- { 33, 9, 12, 0, -42282, }, /* 541 */
- { 33, 9, 12, 0, -42261, }, /* 542 */
- { 33, 9, 12, 0, 928, }, /* 543 */
- { 48, 7, 12, 0, 0, }, /* 544 */
- { 48, 12, 3, 0, 0, }, /* 545 */
- { 48, 10, 5, 0, 0, }, /* 546 */
- { 48, 26, 12, 0, 0, }, /* 547 */
- { 64, 7, 12, 0, 0, }, /* 548 */
- { 64, 21, 12, 0, 0, }, /* 549 */
- { 74, 10, 5, 0, 0, }, /* 550 */
- { 74, 7, 12, 0, 0, }, /* 551 */
- { 74, 12, 3, 0, 0, }, /* 552 */
- { 74, 21, 12, 0, 0, }, /* 553 */
- { 74, 13, 12, 0, 0, }, /* 554 */
- { 68, 13, 12, 0, 0, }, /* 555 */
- { 68, 7, 12, 0, 0, }, /* 556 */
- { 68, 12, 3, 0, 0, }, /* 557 */
- { 68, 21, 12, 0, 0, }, /* 558 */
- { 73, 7, 12, 0, 0, }, /* 559 */
- { 73, 12, 3, 0, 0, }, /* 560 */
- { 73, 10, 5, 0, 0, }, /* 561 */
- { 73, 21, 12, 0, 0, }, /* 562 */
- { 83, 12, 3, 0, 0, }, /* 563 */
- { 83, 10, 5, 0, 0, }, /* 564 */
- { 83, 7, 12, 0, 0, }, /* 565 */
- { 83, 21, 12, 0, 0, }, /* 566 */
- { 83, 13, 12, 0, 0, }, /* 567 */
- { 38, 6, 12, 0, 0, }, /* 568 */
- { 67, 7, 12, 0, 0, }, /* 569 */
- { 67, 12, 3, 0, 0, }, /* 570 */
- { 67, 10, 5, 0, 0, }, /* 571 */
- { 67, 13, 12, 0, 0, }, /* 572 */
- { 67, 21, 12, 0, 0, }, /* 573 */
- { 91, 7, 12, 0, 0, }, /* 574 */
- { 91, 12, 3, 0, 0, }, /* 575 */
- { 91, 6, 12, 0, 0, }, /* 576 */
- { 91, 21, 12, 0, 0, }, /* 577 */
- { 86, 7, 12, 0, 0, }, /* 578 */
- { 86, 10, 5, 0, 0, }, /* 579 */
- { 86, 12, 3, 0, 0, }, /* 580 */
- { 86, 21, 12, 0, 0, }, /* 581 */
- { 86, 6, 12, 0, 0, }, /* 582 */
- { 33, 5, 12, 0, -928, }, /* 583 */
- { 8, 5, 12, 0, -38864, }, /* 584 */
- { 86, 13, 12, 0, 0, }, /* 585 */
- { 23, 7, 9, 0, 0, }, /* 586 */
- { 23, 7, 10, 0, 0, }, /* 587 */
- { 9, 4, 2, 0, 0, }, /* 588 */
- { 9, 3, 12, 0, 0, }, /* 589 */
- { 25, 25, 12, 0, 0, }, /* 590 */
- { 0, 24, 12, 0, 0, }, /* 591 */
- { 9, 6, 3, 0, 0, }, /* 592 */
- { 35, 7, 12, 0, 0, }, /* 593 */
- { 19, 14, 12, 0, 0, }, /* 594 */
- { 19, 15, 12, 0, 0, }, /* 595 */
- { 19, 26, 12, 0, 0, }, /* 596 */
- { 70, 7, 12, 0, 0, }, /* 597 */
- { 66, 7, 12, 0, 0, }, /* 598 */
- { 41, 7, 12, 0, 0, }, /* 599 */
- { 41, 15, 12, 0, 0, }, /* 600 */
- { 18, 7, 12, 0, 0, }, /* 601 */
- { 18, 14, 12, 0, 0, }, /* 602 */
- { 117, 7, 12, 0, 0, }, /* 603 */
- { 117, 12, 3, 0, 0, }, /* 604 */
- { 59, 7, 12, 0, 0, }, /* 605 */
- { 59, 21, 12, 0, 0, }, /* 606 */
- { 42, 7, 12, 0, 0, }, /* 607 */
- { 42, 21, 12, 0, 0, }, /* 608 */
- { 42, 14, 12, 0, 0, }, /* 609 */
- { 13, 9, 12, 0, 40, }, /* 610 */
- { 13, 5, 12, 0, -40, }, /* 611 */
- { 46, 7, 12, 0, 0, }, /* 612 */
- { 44, 7, 12, 0, 0, }, /* 613 */
- { 44, 13, 12, 0, 0, }, /* 614 */
- { 135, 9, 12, 0, 40, }, /* 615 */
- { 135, 5, 12, 0, -40, }, /* 616 */
- { 105, 7, 12, 0, 0, }, /* 617 */
- { 103, 7, 12, 0, 0, }, /* 618 */
- { 103, 21, 12, 0, 0, }, /* 619 */
- { 109, 7, 12, 0, 0, }, /* 620 */
- { 11, 7, 12, 0, 0, }, /* 621 */
- { 80, 7, 12, 0, 0, }, /* 622 */
- { 80, 21, 12, 0, 0, }, /* 623 */
- { 80, 15, 12, 0, 0, }, /* 624 */
- { 119, 7, 12, 0, 0, }, /* 625 */
- { 119, 26, 12, 0, 0, }, /* 626 */
- { 119, 15, 12, 0, 0, }, /* 627 */
- { 115, 7, 12, 0, 0, }, /* 628 */
- { 115, 15, 12, 0, 0, }, /* 629 */
- { 127, 7, 12, 0, 0, }, /* 630 */
- { 127, 15, 12, 0, 0, }, /* 631 */
- { 65, 7, 12, 0, 0, }, /* 632 */
- { 65, 15, 12, 0, 0, }, /* 633 */
- { 65, 21, 12, 0, 0, }, /* 634 */
- { 71, 7, 12, 0, 0, }, /* 635 */
- { 71, 21, 12, 0, 0, }, /* 636 */
- { 97, 7, 12, 0, 0, }, /* 637 */
- { 96, 7, 12, 0, 0, }, /* 638 */
- { 96, 15, 12, 0, 0, }, /* 639 */
- { 30, 7, 12, 0, 0, }, /* 640 */
- { 30, 12, 3, 0, 0, }, /* 641 */
- { 30, 15, 12, 0, 0, }, /* 642 */
- { 30, 21, 12, 0, 0, }, /* 643 */
- { 87, 7, 12, 0, 0, }, /* 644 */
- { 87, 15, 12, 0, 0, }, /* 645 */
- { 87, 21, 12, 0, 0, }, /* 646 */
- { 116, 7, 12, 0, 0, }, /* 647 */
- { 116, 15, 12, 0, 0, }, /* 648 */
- { 111, 7, 12, 0, 0, }, /* 649 */
- { 111, 26, 12, 0, 0, }, /* 650 */
- { 111, 12, 3, 0, 0, }, /* 651 */
- { 111, 15, 12, 0, 0, }, /* 652 */
- { 111, 21, 12, 0, 0, }, /* 653 */
- { 77, 7, 12, 0, 0, }, /* 654 */
- { 77, 21, 12, 0, 0, }, /* 655 */
- { 82, 7, 12, 0, 0, }, /* 656 */
- { 82, 15, 12, 0, 0, }, /* 657 */
- { 81, 7, 12, 0, 0, }, /* 658 */
- { 81, 15, 12, 0, 0, }, /* 659 */
- { 120, 7, 12, 0, 0, }, /* 660 */
- { 120, 21, 12, 0, 0, }, /* 661 */
- { 120, 15, 12, 0, 0, }, /* 662 */
- { 88, 7, 12, 0, 0, }, /* 663 */
- { 129, 9, 12, 0, 64, }, /* 664 */
- { 129, 5, 12, 0, -64, }, /* 665 */
- { 129, 15, 12, 0, 0, }, /* 666 */
- { 0, 15, 12, 0, 0, }, /* 667 */
- { 93, 10, 5, 0, 0, }, /* 668 */
- { 93, 12, 3, 0, 0, }, /* 669 */
- { 93, 7, 12, 0, 0, }, /* 670 */
- { 93, 21, 12, 0, 0, }, /* 671 */
- { 93, 15, 12, 0, 0, }, /* 672 */
- { 93, 13, 12, 0, 0, }, /* 673 */
- { 84, 12, 3, 0, 0, }, /* 674 */
- { 84, 10, 5, 0, 0, }, /* 675 */
- { 84, 7, 12, 0, 0, }, /* 676 */
- { 84, 21, 12, 0, 0, }, /* 677 */
- { 84, 1, 4, 0, 0, }, /* 678 */
- { 100, 7, 12, 0, 0, }, /* 679 */
- { 100, 13, 12, 0, 0, }, /* 680 */
- { 95, 12, 3, 0, 0, }, /* 681 */
- { 95, 7, 12, 0, 0, }, /* 682 */
- { 95, 10, 5, 0, 0, }, /* 683 */
- { 95, 13, 12, 0, 0, }, /* 684 */
- { 95, 21, 12, 0, 0, }, /* 685 */
- { 110, 7, 12, 0, 0, }, /* 686 */
- { 110, 12, 3, 0, 0, }, /* 687 */
- { 110, 21, 12, 0, 0, }, /* 688 */
- { 99, 12, 3, 0, 0, }, /* 689 */
- { 99, 10, 5, 0, 0, }, /* 690 */
- { 99, 7, 12, 0, 0, }, /* 691 */
- { 99, 7, 4, 0, 0, }, /* 692 */
- { 99, 21, 12, 0, 0, }, /* 693 */
- { 99, 13, 12, 0, 0, }, /* 694 */
- { 47, 15, 12, 0, 0, }, /* 695 */
- { 107, 7, 12, 0, 0, }, /* 696 */
- { 107, 10, 5, 0, 0, }, /* 697 */
- { 107, 12, 3, 0, 0, }, /* 698 */
- { 107, 21, 12, 0, 0, }, /* 699 */
- { 128, 7, 12, 0, 0, }, /* 700 */
- { 128, 21, 12, 0, 0, }, /* 701 */
- { 108, 7, 12, 0, 0, }, /* 702 */
- { 108, 12, 3, 0, 0, }, /* 703 */
- { 108, 10, 5, 0, 0, }, /* 704 */
- { 108, 13, 12, 0, 0, }, /* 705 */
- { 106, 12, 3, 0, 0, }, /* 706 */
- { 106, 10, 5, 0, 0, }, /* 707 */
- { 106, 7, 12, 0, 0, }, /* 708 */
- { 106, 10, 3, 0, 0, }, /* 709 */
- { 134, 7, 12, 0, 0, }, /* 710 */
- { 134, 10, 5, 0, 0, }, /* 711 */
- { 134, 12, 3, 0, 0, }, /* 712 */
- { 134, 21, 12, 0, 0, }, /* 713 */
- { 134, 13, 12, 0, 0, }, /* 714 */
- { 123, 7, 12, 0, 0, }, /* 715 */
- { 123, 10, 3, 0, 0, }, /* 716 */
- { 123, 10, 5, 0, 0, }, /* 717 */
- { 123, 12, 3, 0, 0, }, /* 718 */
- { 123, 21, 12, 0, 0, }, /* 719 */
- { 123, 13, 12, 0, 0, }, /* 720 */
- { 122, 7, 12, 0, 0, }, /* 721 */
- { 122, 10, 3, 0, 0, }, /* 722 */
- { 122, 10, 5, 0, 0, }, /* 723 */
- { 122, 12, 3, 0, 0, }, /* 724 */
- { 122, 21, 12, 0, 0, }, /* 725 */
- { 113, 7, 12, 0, 0, }, /* 726 */
- { 113, 10, 5, 0, 0, }, /* 727 */
- { 113, 12, 3, 0, 0, }, /* 728 */
- { 113, 21, 12, 0, 0, }, /* 729 */
- { 113, 13, 12, 0, 0, }, /* 730 */
- { 101, 7, 12, 0, 0, }, /* 731 */
- { 101, 12, 3, 0, 0, }, /* 732 */
- { 101, 10, 5, 0, 0, }, /* 733 */
- { 101, 13, 12, 0, 0, }, /* 734 */
- { 125, 7, 12, 0, 0, }, /* 735 */
- { 125, 12, 3, 0, 0, }, /* 736 */
- { 125, 10, 5, 0, 0, }, /* 737 */
- { 125, 13, 12, 0, 0, }, /* 738 */
- { 125, 15, 12, 0, 0, }, /* 739 */
- { 125, 21, 12, 0, 0, }, /* 740 */
- { 125, 26, 12, 0, 0, }, /* 741 */
- { 124, 9, 12, 0, 32, }, /* 742 */
- { 124, 5, 12, 0, -32, }, /* 743 */
- { 124, 13, 12, 0, 0, }, /* 744 */
- { 124, 15, 12, 0, 0, }, /* 745 */
- { 124, 7, 12, 0, 0, }, /* 746 */
- { 140, 7, 12, 0, 0, }, /* 747 */
- { 140, 12, 3, 0, 0, }, /* 748 */
- { 140, 10, 5, 0, 0, }, /* 749 */
- { 140, 7, 4, 0, 0, }, /* 750 */
- { 140, 21, 12, 0, 0, }, /* 751 */
- { 139, 7, 12, 0, 0, }, /* 752 */
- { 139, 12, 3, 0, 0, }, /* 753 */
- { 139, 10, 5, 0, 0, }, /* 754 */
- { 139, 7, 4, 0, 0, }, /* 755 */
- { 139, 21, 12, 0, 0, }, /* 756 */
- { 121, 7, 12, 0, 0, }, /* 757 */
- { 132, 7, 12, 0, 0, }, /* 758 */
- { 132, 10, 5, 0, 0, }, /* 759 */
- { 132, 12, 3, 0, 0, }, /* 760 */
- { 132, 21, 12, 0, 0, }, /* 761 */
- { 132, 13, 12, 0, 0, }, /* 762 */
- { 132, 15, 12, 0, 0, }, /* 763 */
- { 133, 21, 12, 0, 0, }, /* 764 */
- { 133, 7, 12, 0, 0, }, /* 765 */
- { 133, 12, 3, 0, 0, }, /* 766 */
- { 133, 10, 5, 0, 0, }, /* 767 */
- { 137, 7, 12, 0, 0, }, /* 768 */
- { 137, 12, 3, 0, 0, }, /* 769 */
- { 137, 7, 4, 0, 0, }, /* 770 */
- { 137, 13, 12, 0, 0, }, /* 771 */
- { 62, 7, 12, 0, 0, }, /* 772 */
- { 62, 14, 12, 0, 0, }, /* 773 */
- { 62, 21, 12, 0, 0, }, /* 774 */
- { 79, 7, 12, 0, 0, }, /* 775 */
- { 126, 7, 12, 0, 0, }, /* 776 */
- { 114, 7, 12, 0, 0, }, /* 777 */
- { 114, 13, 12, 0, 0, }, /* 778 */
- { 114, 21, 12, 0, 0, }, /* 779 */
- { 102, 7, 12, 0, 0, }, /* 780 */
- { 102, 12, 3, 0, 0, }, /* 781 */
- { 102, 21, 12, 0, 0, }, /* 782 */
- { 118, 7, 12, 0, 0, }, /* 783 */
- { 118, 12, 3, 0, 0, }, /* 784 */
- { 118, 21, 12, 0, 0, }, /* 785 */
- { 118, 26, 12, 0, 0, }, /* 786 */
- { 118, 6, 12, 0, 0, }, /* 787 */
- { 118, 13, 12, 0, 0, }, /* 788 */
- { 118, 15, 12, 0, 0, }, /* 789 */
- { 98, 7, 12, 0, 0, }, /* 790 */
- { 98, 10, 5, 0, 0, }, /* 791 */
- { 98, 12, 3, 0, 0, }, /* 792 */
- { 98, 6, 12, 0, 0, }, /* 793 */
- { 136, 6, 12, 0, 0, }, /* 794 */
- { 138, 6, 12, 0, 0, }, /* 795 */
- { 136, 7, 12, 0, 0, }, /* 796 */
- { 138, 7, 12, 0, 0, }, /* 797 */
- { 104, 7, 12, 0, 0, }, /* 798 */
- { 104, 26, 12, 0, 0, }, /* 799 */
- { 104, 12, 3, 0, 0, }, /* 800 */
- { 104, 21, 12, 0, 0, }, /* 801 */
- { 9, 10, 3, 0, 0, }, /* 802 */
- { 19, 12, 3, 0, 0, }, /* 803 */
- { 130, 26, 12, 0, 0, }, /* 804 */
- { 130, 12, 3, 0, 0, }, /* 805 */
- { 130, 21, 12, 0, 0, }, /* 806 */
- { 17, 12, 3, 0, 0, }, /* 807 */
- { 112, 7, 12, 0, 0, }, /* 808 */
- { 112, 15, 12, 0, 0, }, /* 809 */
- { 112, 12, 3, 0, 0, }, /* 810 */
- { 131, 9, 12, 0, 34, }, /* 811 */
- { 131, 5, 12, 0, -34, }, /* 812 */
- { 131, 12, 3, 0, 0, }, /* 813 */
- { 131, 13, 12, 0, 0, }, /* 814 */
- { 131, 21, 12, 0, 0, }, /* 815 */
- { 9, 26, 11, 0, 0, }, /* 816 */
- { 26, 26, 12, 0, 0, }, /* 817 */
- { 9, 24, 14, 0, 0, }, /* 818 */
- { 9, 26, 15, 0, 0, }, /* 819 */
- { 9, 1, 3, 0, 0, }, /* 820 */
+ { 1, 5, 12, 0, -48, }, /* 201 */
+ { 1, 17, 12, 0, 0, }, /* 202 */
+ { 1, 26, 12, 0, 0, }, /* 203 */
+ { 1, 23, 12, 0, 0, }, /* 204 */
+ { 25, 12, 3, 0, 0, }, /* 205 */
+ { 25, 17, 12, 0, 0, }, /* 206 */
+ { 25, 21, 12, 0, 0, }, /* 207 */
+ { 25, 7, 12, 0, 0, }, /* 208 */
+ { 0, 1, 4, 0, 0, }, /* 209 */
+ { 9, 1, 4, 0, 0, }, /* 210 */
+ { 0, 25, 12, 0, 0, }, /* 211 */
+ { 0, 21, 12, 0, 0, }, /* 212 */
+ { 0, 23, 12, 0, 0, }, /* 213 */
+ { 0, 26, 12, 0, 0, }, /* 214 */
+ { 0, 12, 3, 0, 0, }, /* 215 */
+ { 0, 1, 2, 0, 0, }, /* 216 */
+ { 0, 7, 12, 0, 0, }, /* 217 */
+ { 0, 13, 12, 0, 0, }, /* 218 */
+ { 0, 6, 12, 0, 0, }, /* 219 */
+ { 49, 21, 12, 0, 0, }, /* 220 */
+ { 49, 1, 4, 0, 0, }, /* 221 */
+ { 49, 7, 12, 0, 0, }, /* 222 */
+ { 49, 12, 3, 0, 0, }, /* 223 */
+ { 55, 7, 12, 0, 0, }, /* 224 */
+ { 55, 12, 3, 0, 0, }, /* 225 */
+ { 63, 13, 12, 0, 0, }, /* 226 */
+ { 63, 7, 12, 0, 0, }, /* 227 */
+ { 63, 12, 3, 0, 0, }, /* 228 */
+ { 63, 6, 12, 0, 0, }, /* 229 */
+ { 63, 26, 12, 0, 0, }, /* 230 */
+ { 63, 21, 12, 0, 0, }, /* 231 */
+ { 63, 23, 12, 0, 0, }, /* 232 */
+ { 89, 7, 12, 0, 0, }, /* 233 */
+ { 89, 12, 3, 0, 0, }, /* 234 */
+ { 89, 6, 12, 0, 0, }, /* 235 */
+ { 89, 21, 12, 0, 0, }, /* 236 */
+ { 94, 7, 12, 0, 0, }, /* 237 */
+ { 94, 12, 3, 0, 0, }, /* 238 */
+ { 94, 21, 12, 0, 0, }, /* 239 */
+ { 14, 12, 3, 0, 0, }, /* 240 */
+ { 14, 10, 5, 0, 0, }, /* 241 */
+ { 14, 7, 12, 0, 0, }, /* 242 */
+ { 14, 13, 12, 0, 0, }, /* 243 */
+ { 14, 21, 12, 0, 0, }, /* 244 */
+ { 14, 6, 12, 0, 0, }, /* 245 */
+ { 2, 7, 12, 0, 0, }, /* 246 */
+ { 2, 12, 3, 0, 0, }, /* 247 */
+ { 2, 10, 5, 0, 0, }, /* 248 */
+ { 2, 10, 3, 0, 0, }, /* 249 */
+ { 2, 13, 12, 0, 0, }, /* 250 */
+ { 2, 23, 12, 0, 0, }, /* 251 */
+ { 2, 15, 12, 0, 0, }, /* 252 */
+ { 2, 26, 12, 0, 0, }, /* 253 */
+ { 2, 21, 12, 0, 0, }, /* 254 */
+ { 21, 12, 3, 0, 0, }, /* 255 */
+ { 21, 10, 5, 0, 0, }, /* 256 */
+ { 21, 7, 12, 0, 0, }, /* 257 */
+ { 21, 13, 12, 0, 0, }, /* 258 */
+ { 21, 21, 12, 0, 0, }, /* 259 */
+ { 20, 12, 3, 0, 0, }, /* 260 */
+ { 20, 10, 5, 0, 0, }, /* 261 */
+ { 20, 7, 12, 0, 0, }, /* 262 */
+ { 20, 13, 12, 0, 0, }, /* 263 */
+ { 20, 21, 12, 0, 0, }, /* 264 */
+ { 20, 23, 12, 0, 0, }, /* 265 */
+ { 43, 12, 3, 0, 0, }, /* 266 */
+ { 43, 10, 5, 0, 0, }, /* 267 */
+ { 43, 7, 12, 0, 0, }, /* 268 */
+ { 43, 10, 3, 0, 0, }, /* 269 */
+ { 43, 13, 12, 0, 0, }, /* 270 */
+ { 43, 26, 12, 0, 0, }, /* 271 */
+ { 43, 15, 12, 0, 0, }, /* 272 */
+ { 53, 12, 3, 0, 0, }, /* 273 */
+ { 53, 7, 12, 0, 0, }, /* 274 */
+ { 53, 10, 3, 0, 0, }, /* 275 */
+ { 53, 10, 5, 0, 0, }, /* 276 */
+ { 53, 13, 12, 0, 0, }, /* 277 */
+ { 53, 15, 12, 0, 0, }, /* 278 */
+ { 53, 26, 12, 0, 0, }, /* 279 */
+ { 53, 23, 12, 0, 0, }, /* 280 */
+ { 54, 12, 3, 0, 0, }, /* 281 */
+ { 54, 10, 5, 0, 0, }, /* 282 */
+ { 54, 7, 12, 0, 0, }, /* 283 */
+ { 54, 13, 12, 0, 0, }, /* 284 */
+ { 54, 15, 12, 0, 0, }, /* 285 */
+ { 54, 26, 12, 0, 0, }, /* 286 */
+ { 28, 7, 12, 0, 0, }, /* 287 */
+ { 28, 12, 3, 0, 0, }, /* 288 */
+ { 28, 10, 5, 0, 0, }, /* 289 */
+ { 28, 21, 12, 0, 0, }, /* 290 */
+ { 28, 10, 3, 0, 0, }, /* 291 */
+ { 28, 13, 12, 0, 0, }, /* 292 */
+ { 36, 12, 3, 0, 0, }, /* 293 */
+ { 36, 10, 5, 0, 0, }, /* 294 */
+ { 36, 7, 12, 0, 0, }, /* 295 */
+ { 36, 10, 3, 0, 0, }, /* 296 */
+ { 36, 7, 4, 0, 0, }, /* 297 */
+ { 36, 26, 12, 0, 0, }, /* 298 */
+ { 36, 15, 12, 0, 0, }, /* 299 */
+ { 36, 13, 12, 0, 0, }, /* 300 */
+ { 47, 10, 5, 0, 0, }, /* 301 */
+ { 47, 7, 12, 0, 0, }, /* 302 */
+ { 47, 12, 3, 0, 0, }, /* 303 */
+ { 47, 10, 3, 0, 0, }, /* 304 */
+ { 47, 13, 12, 0, 0, }, /* 305 */
+ { 47, 21, 12, 0, 0, }, /* 306 */
+ { 56, 7, 12, 0, 0, }, /* 307 */
+ { 56, 12, 3, 0, 0, }, /* 308 */
+ { 56, 7, 5, 0, 0, }, /* 309 */
+ { 56, 6, 12, 0, 0, }, /* 310 */
+ { 56, 21, 12, 0, 0, }, /* 311 */
+ { 56, 13, 12, 0, 0, }, /* 312 */
+ { 32, 7, 12, 0, 0, }, /* 313 */
+ { 32, 12, 3, 0, 0, }, /* 314 */
+ { 32, 7, 5, 0, 0, }, /* 315 */
+ { 32, 6, 12, 0, 0, }, /* 316 */
+ { 32, 13, 12, 0, 0, }, /* 317 */
+ { 57, 7, 12, 0, 0, }, /* 318 */
+ { 57, 26, 12, 0, 0, }, /* 319 */
+ { 57, 21, 12, 0, 0, }, /* 320 */
+ { 57, 12, 3, 0, 0, }, /* 321 */
+ { 57, 13, 12, 0, 0, }, /* 322 */
+ { 57, 15, 12, 0, 0, }, /* 323 */
+ { 57, 22, 12, 0, 0, }, /* 324 */
+ { 57, 18, 12, 0, 0, }, /* 325 */
+ { 57, 10, 5, 0, 0, }, /* 326 */
+ { 38, 7, 12, 0, 0, }, /* 327 */
+ { 38, 10, 12, 0, 0, }, /* 328 */
+ { 38, 12, 3, 0, 0, }, /* 329 */
+ { 38, 10, 5, 0, 0, }, /* 330 */
+ { 38, 13, 12, 0, 0, }, /* 331 */
+ { 38, 21, 12, 0, 0, }, /* 332 */
+ { 38, 26, 12, 0, 0, }, /* 333 */
+ { 16, 9, 12, 0, 7264, }, /* 334 */
+ { 16, 5, 12, 0, 3008, }, /* 335 */
+ { 16, 6, 12, 0, 0, }, /* 336 */
+ { 23, 7, 6, 0, 0, }, /* 337 */
+ { 23, 7, 7, 0, 0, }, /* 338 */
+ { 23, 7, 8, 0, 0, }, /* 339 */
+ { 15, 7, 12, 0, 0, }, /* 340 */
+ { 15, 12, 3, 0, 0, }, /* 341 */
+ { 15, 21, 12, 0, 0, }, /* 342 */
+ { 15, 15, 12, 0, 0, }, /* 343 */
+ { 15, 26, 12, 0, 0, }, /* 344 */
+ { 8, 9, 12, 0, 38864, }, /* 345 */
+ { 8, 9, 12, 0, 8, }, /* 346 */
+ { 8, 5, 12, 0, -8, }, /* 347 */
+ { 7, 17, 12, 0, 0, }, /* 348 */
+ { 7, 7, 12, 0, 0, }, /* 349 */
+ { 7, 21, 12, 0, 0, }, /* 350 */
+ { 40, 29, 12, 0, 0, }, /* 351 */
+ { 40, 7, 12, 0, 0, }, /* 352 */
+ { 40, 22, 12, 0, 0, }, /* 353 */
+ { 40, 18, 12, 0, 0, }, /* 354 */
+ { 45, 7, 12, 0, 0, }, /* 355 */
+ { 45, 14, 12, 0, 0, }, /* 356 */
+ { 50, 7, 12, 0, 0, }, /* 357 */
+ { 50, 12, 3, 0, 0, }, /* 358 */
+ { 24, 7, 12, 0, 0, }, /* 359 */
+ { 24, 12, 3, 0, 0, }, /* 360 */
+ { 6, 7, 12, 0, 0, }, /* 361 */
+ { 6, 12, 3, 0, 0, }, /* 362 */
+ { 51, 7, 12, 0, 0, }, /* 363 */
+ { 51, 12, 3, 0, 0, }, /* 364 */
+ { 31, 7, 12, 0, 0, }, /* 365 */
+ { 31, 12, 3, 0, 0, }, /* 366 */
+ { 31, 10, 5, 0, 0, }, /* 367 */
+ { 31, 21, 12, 0, 0, }, /* 368 */
+ { 31, 6, 12, 0, 0, }, /* 369 */
+ { 31, 23, 12, 0, 0, }, /* 370 */
+ { 31, 13, 12, 0, 0, }, /* 371 */
+ { 31, 15, 12, 0, 0, }, /* 372 */
+ { 37, 21, 12, 0, 0, }, /* 373 */
+ { 37, 17, 12, 0, 0, }, /* 374 */
+ { 37, 12, 3, 0, 0, }, /* 375 */
+ { 37, 1, 2, 0, 0, }, /* 376 */
+ { 37, 13, 12, 0, 0, }, /* 377 */
+ { 37, 7, 12, 0, 0, }, /* 378 */
+ { 37, 6, 12, 0, 0, }, /* 379 */
+ { 34, 7, 12, 0, 0, }, /* 380 */
+ { 34, 12, 3, 0, 0, }, /* 381 */
+ { 34, 10, 5, 0, 0, }, /* 382 */
+ { 34, 26, 12, 0, 0, }, /* 383 */
+ { 34, 21, 12, 0, 0, }, /* 384 */
+ { 34, 13, 12, 0, 0, }, /* 385 */
+ { 52, 7, 12, 0, 0, }, /* 386 */
+ { 39, 7, 12, 0, 0, }, /* 387 */
+ { 39, 13, 12, 0, 0, }, /* 388 */
+ { 39, 15, 12, 0, 0, }, /* 389 */
+ { 39, 26, 12, 0, 0, }, /* 390 */
+ { 31, 26, 12, 0, 0, }, /* 391 */
+ { 5, 7, 12, 0, 0, }, /* 392 */
+ { 5, 12, 3, 0, 0, }, /* 393 */
+ { 5, 10, 5, 0, 0, }, /* 394 */
+ { 5, 21, 12, 0, 0, }, /* 395 */
+ { 90, 7, 12, 0, 0, }, /* 396 */
+ { 90, 10, 5, 0, 0, }, /* 397 */
+ { 90, 12, 3, 0, 0, }, /* 398 */
+ { 90, 10, 12, 0, 0, }, /* 399 */
+ { 90, 13, 12, 0, 0, }, /* 400 */
+ { 90, 21, 12, 0, 0, }, /* 401 */
+ { 90, 6, 12, 0, 0, }, /* 402 */
+ { 27, 11, 3, 0, 0, }, /* 403 */
+ { 61, 12, 3, 0, 0, }, /* 404 */
+ { 61, 10, 5, 0, 0, }, /* 405 */
+ { 61, 7, 12, 0, 0, }, /* 406 */
+ { 61, 13, 12, 0, 0, }, /* 407 */
+ { 61, 21, 12, 0, 0, }, /* 408 */
+ { 61, 26, 12, 0, 0, }, /* 409 */
+ { 75, 12, 3, 0, 0, }, /* 410 */
+ { 75, 10, 5, 0, 0, }, /* 411 */
+ { 75, 7, 12, 0, 0, }, /* 412 */
+ { 75, 13, 12, 0, 0, }, /* 413 */
+ { 92, 7, 12, 0, 0, }, /* 414 */
+ { 92, 12, 3, 0, 0, }, /* 415 */
+ { 92, 10, 5, 0, 0, }, /* 416 */
+ { 92, 21, 12, 0, 0, }, /* 417 */
+ { 69, 7, 12, 0, 0, }, /* 418 */
+ { 69, 10, 5, 0, 0, }, /* 419 */
+ { 69, 12, 3, 0, 0, }, /* 420 */
+ { 69, 21, 12, 0, 0, }, /* 421 */
+ { 69, 13, 12, 0, 0, }, /* 422 */
+ { 72, 13, 12, 0, 0, }, /* 423 */
+ { 72, 7, 12, 0, 0, }, /* 424 */
+ { 72, 6, 12, 0, 0, }, /* 425 */
+ { 72, 21, 12, 0, 0, }, /* 426 */
+ { 12, 5, 12, 63, -6222, }, /* 427 */
+ { 12, 5, 12, 67, -6221, }, /* 428 */
+ { 12, 5, 12, 71, -6212, }, /* 429 */
+ { 12, 5, 12, 75, -6210, }, /* 430 */
+ { 12, 5, 12, 79, -6210, }, /* 431 */
+ { 12, 5, 12, 79, -6211, }, /* 432 */
+ { 12, 5, 12, 84, -6204, }, /* 433 */
+ { 12, 5, 12, 88, -6180, }, /* 434 */
+ { 12, 5, 12, 108, 35267, }, /* 435 */
+ { 16, 9, 12, 0, -3008, }, /* 436 */
+ { 75, 21, 12, 0, 0, }, /* 437 */
+ { 9, 10, 5, 0, 0, }, /* 438 */
+ { 9, 7, 12, 0, 0, }, /* 439 */
+ { 12, 5, 12, 0, 0, }, /* 440 */
+ { 12, 6, 12, 0, 0, }, /* 441 */
+ { 33, 5, 12, 0, 35332, }, /* 442 */
+ { 33, 5, 12, 0, 3814, }, /* 443 */
+ { 33, 9, 12, 92, 1, }, /* 444 */
+ { 33, 5, 12, 92, -1, }, /* 445 */
+ { 33, 5, 12, 92, -58, }, /* 446 */
+ { 33, 9, 12, 0, -7615, }, /* 447 */
+ { 19, 5, 12, 0, 8, }, /* 448 */
+ { 19, 9, 12, 0, -8, }, /* 449 */
+ { 19, 5, 12, 0, 74, }, /* 450 */
+ { 19, 5, 12, 0, 86, }, /* 451 */
+ { 19, 5, 12, 0, 100, }, /* 452 */
+ { 19, 5, 12, 0, 128, }, /* 453 */
+ { 19, 5, 12, 0, 112, }, /* 454 */
+ { 19, 5, 12, 0, 126, }, /* 455 */
+ { 19, 8, 12, 0, -8, }, /* 456 */
+ { 19, 5, 12, 0, 9, }, /* 457 */
+ { 19, 9, 12, 0, -74, }, /* 458 */
+ { 19, 8, 12, 0, -9, }, /* 459 */
+ { 19, 5, 12, 21, -7173, }, /* 460 */
+ { 19, 9, 12, 0, -86, }, /* 461 */
+ { 19, 9, 12, 0, -100, }, /* 462 */
+ { 19, 9, 12, 0, -112, }, /* 463 */
+ { 19, 9, 12, 0, -128, }, /* 464 */
+ { 19, 9, 12, 0, -126, }, /* 465 */
+ { 27, 1, 3, 0, 0, }, /* 466 */
+ { 27, 1, 13, 0, 0, }, /* 467 */
+ { 9, 27, 2, 0, 0, }, /* 468 */
+ { 9, 28, 2, 0, 0, }, /* 469 */
+ { 9, 21, 14, 0, 0, }, /* 470 */
+ { 9, 2, 2, 0, 0, }, /* 471 */
+ { 9, 9, 12, 0, 0, }, /* 472 */
+ { 9, 5, 12, 0, 0, }, /* 473 */
+ { 19, 9, 12, 96, -7517, }, /* 474 */
+ { 33, 9, 12, 100, -8383, }, /* 475 */
+ { 33, 9, 12, 104, -8262, }, /* 476 */
+ { 33, 9, 12, 0, 28, }, /* 477 */
+ { 9, 5, 14, 0, 0, }, /* 478 */
+ { 33, 5, 12, 0, -28, }, /* 479 */
+ { 33, 14, 12, 0, 16, }, /* 480 */
+ { 33, 14, 12, 0, -16, }, /* 481 */
+ { 33, 14, 12, 0, 0, }, /* 482 */
+ { 9, 25, 14, 0, 0, }, /* 483 */
+ { 9, 26, 12, 0, 26, }, /* 484 */
+ { 9, 26, 14, 0, 26, }, /* 485 */
+ { 9, 26, 12, 0, -26, }, /* 486 */
+ { 4, 26, 12, 0, 0, }, /* 487 */
+ { 17, 9, 12, 0, 48, }, /* 488 */
+ { 17, 5, 12, 0, -48, }, /* 489 */
+ { 33, 9, 12, 0, -10743, }, /* 490 */
+ { 33, 9, 12, 0, -3814, }, /* 491 */
+ { 33, 9, 12, 0, -10727, }, /* 492 */
+ { 33, 5, 12, 0, -10795, }, /* 493 */
+ { 33, 5, 12, 0, -10792, }, /* 494 */
+ { 33, 9, 12, 0, -10780, }, /* 495 */
+ { 33, 9, 12, 0, -10749, }, /* 496 */
+ { 33, 9, 12, 0, -10783, }, /* 497 */
+ { 33, 9, 12, 0, -10782, }, /* 498 */
+ { 33, 9, 12, 0, -10815, }, /* 499 */
+ { 10, 5, 12, 0, 0, }, /* 500 */
+ { 10, 26, 12, 0, 0, }, /* 501 */
+ { 10, 12, 3, 0, 0, }, /* 502 */
+ { 10, 21, 12, 0, 0, }, /* 503 */
+ { 10, 15, 12, 0, 0, }, /* 504 */
+ { 16, 5, 12, 0, -7264, }, /* 505 */
+ { 58, 7, 12, 0, 0, }, /* 506 */
+ { 58, 6, 12, 0, 0, }, /* 507 */
+ { 58, 21, 12, 0, 0, }, /* 508 */
+ { 58, 12, 3, 0, 0, }, /* 509 */
+ { 22, 26, 12, 0, 0, }, /* 510 */
+ { 22, 6, 12, 0, 0, }, /* 511 */
+ { 22, 14, 12, 0, 0, }, /* 512 */
+ { 23, 10, 3, 0, 0, }, /* 513 */
+ { 9, 17, 14, 0, 0, }, /* 514 */
+ { 26, 7, 12, 0, 0, }, /* 515 */
+ { 26, 6, 12, 0, 0, }, /* 516 */
+ { 29, 7, 12, 0, 0, }, /* 517 */
+ { 29, 6, 12, 0, 0, }, /* 518 */
+ { 3, 7, 12, 0, 0, }, /* 519 */
+ { 23, 7, 12, 0, 0, }, /* 520 */
+ { 23, 26, 12, 0, 0, }, /* 521 */
+ { 29, 26, 12, 0, 0, }, /* 522 */
+ { 22, 7, 12, 0, 0, }, /* 523 */
+ { 60, 7, 12, 0, 0, }, /* 524 */
+ { 60, 6, 12, 0, 0, }, /* 525 */
+ { 60, 26, 12, 0, 0, }, /* 526 */
+ { 85, 7, 12, 0, 0, }, /* 527 */
+ { 85, 6, 12, 0, 0, }, /* 528 */
+ { 85, 21, 12, 0, 0, }, /* 529 */
+ { 76, 7, 12, 0, 0, }, /* 530 */
+ { 76, 6, 12, 0, 0, }, /* 531 */
+ { 76, 21, 12, 0, 0, }, /* 532 */
+ { 76, 13, 12, 0, 0, }, /* 533 */
+ { 12, 9, 12, 108, 1, }, /* 534 */
+ { 12, 5, 12, 108, -35267, }, /* 535 */
+ { 12, 7, 12, 0, 0, }, /* 536 */
+ { 12, 21, 12, 0, 0, }, /* 537 */
+ { 78, 7, 12, 0, 0, }, /* 538 */
+ { 78, 14, 12, 0, 0, }, /* 539 */
+ { 78, 12, 3, 0, 0, }, /* 540 */
+ { 78, 21, 12, 0, 0, }, /* 541 */
+ { 33, 9, 12, 0, -35332, }, /* 542 */
+ { 33, 9, 12, 0, -42280, }, /* 543 */
+ { 33, 9, 12, 0, -42308, }, /* 544 */
+ { 33, 9, 12, 0, -42319, }, /* 545 */
+ { 33, 9, 12, 0, -42315, }, /* 546 */
+ { 33, 9, 12, 0, -42305, }, /* 547 */
+ { 33, 9, 12, 0, -42258, }, /* 548 */
+ { 33, 9, 12, 0, -42282, }, /* 549 */
+ { 33, 9, 12, 0, -42261, }, /* 550 */
+ { 33, 9, 12, 0, 928, }, /* 551 */
+ { 48, 7, 12, 0, 0, }, /* 552 */
+ { 48, 12, 3, 0, 0, }, /* 553 */
+ { 48, 10, 5, 0, 0, }, /* 554 */
+ { 48, 26, 12, 0, 0, }, /* 555 */
+ { 64, 7, 12, 0, 0, }, /* 556 */
+ { 64, 21, 12, 0, 0, }, /* 557 */
+ { 74, 10, 5, 0, 0, }, /* 558 */
+ { 74, 7, 12, 0, 0, }, /* 559 */
+ { 74, 12, 3, 0, 0, }, /* 560 */
+ { 74, 21, 12, 0, 0, }, /* 561 */
+ { 74, 13, 12, 0, 0, }, /* 562 */
+ { 68, 13, 12, 0, 0, }, /* 563 */
+ { 68, 7, 12, 0, 0, }, /* 564 */
+ { 68, 12, 3, 0, 0, }, /* 565 */
+ { 68, 21, 12, 0, 0, }, /* 566 */
+ { 73, 7, 12, 0, 0, }, /* 567 */
+ { 73, 12, 3, 0, 0, }, /* 568 */
+ { 73, 10, 5, 0, 0, }, /* 569 */
+ { 73, 21, 12, 0, 0, }, /* 570 */
+ { 83, 12, 3, 0, 0, }, /* 571 */
+ { 83, 10, 5, 0, 0, }, /* 572 */
+ { 83, 7, 12, 0, 0, }, /* 573 */
+ { 83, 21, 12, 0, 0, }, /* 574 */
+ { 83, 13, 12, 0, 0, }, /* 575 */
+ { 38, 6, 12, 0, 0, }, /* 576 */
+ { 67, 7, 12, 0, 0, }, /* 577 */
+ { 67, 12, 3, 0, 0, }, /* 578 */
+ { 67, 10, 5, 0, 0, }, /* 579 */
+ { 67, 13, 12, 0, 0, }, /* 580 */
+ { 67, 21, 12, 0, 0, }, /* 581 */
+ { 91, 7, 12, 0, 0, }, /* 582 */
+ { 91, 12, 3, 0, 0, }, /* 583 */
+ { 91, 6, 12, 0, 0, }, /* 584 */
+ { 91, 21, 12, 0, 0, }, /* 585 */
+ { 86, 7, 12, 0, 0, }, /* 586 */
+ { 86, 10, 5, 0, 0, }, /* 587 */
+ { 86, 12, 3, 0, 0, }, /* 588 */
+ { 86, 21, 12, 0, 0, }, /* 589 */
+ { 86, 6, 12, 0, 0, }, /* 590 */
+ { 33, 5, 12, 0, -928, }, /* 591 */
+ { 8, 5, 12, 0, -38864, }, /* 592 */
+ { 86, 13, 12, 0, 0, }, /* 593 */
+ { 23, 7, 9, 0, 0, }, /* 594 */
+ { 23, 7, 10, 0, 0, }, /* 595 */
+ { 9, 4, 2, 0, 0, }, /* 596 */
+ { 9, 3, 12, 0, 0, }, /* 597 */
+ { 25, 25, 12, 0, 0, }, /* 598 */
+ { 0, 24, 12, 0, 0, }, /* 599 */
+ { 9, 6, 3, 0, 0, }, /* 600 */
+ { 35, 7, 12, 0, 0, }, /* 601 */
+ { 19, 14, 12, 0, 0, }, /* 602 */
+ { 19, 15, 12, 0, 0, }, /* 603 */
+ { 19, 26, 12, 0, 0, }, /* 604 */
+ { 70, 7, 12, 0, 0, }, /* 605 */
+ { 66, 7, 12, 0, 0, }, /* 606 */
+ { 41, 7, 12, 0, 0, }, /* 607 */
+ { 41, 15, 12, 0, 0, }, /* 608 */
+ { 18, 7, 12, 0, 0, }, /* 609 */
+ { 18, 14, 12, 0, 0, }, /* 610 */
+ { 117, 7, 12, 0, 0, }, /* 611 */
+ { 117, 12, 3, 0, 0, }, /* 612 */
+ { 59, 7, 12, 0, 0, }, /* 613 */
+ { 59, 21, 12, 0, 0, }, /* 614 */
+ { 42, 7, 12, 0, 0, }, /* 615 */
+ { 42, 21, 12, 0, 0, }, /* 616 */
+ { 42, 14, 12, 0, 0, }, /* 617 */
+ { 13, 9, 12, 0, 40, }, /* 618 */
+ { 13, 5, 12, 0, -40, }, /* 619 */
+ { 46, 7, 12, 0, 0, }, /* 620 */
+ { 44, 7, 12, 0, 0, }, /* 621 */
+ { 44, 13, 12, 0, 0, }, /* 622 */
+ { 135, 9, 12, 0, 40, }, /* 623 */
+ { 135, 5, 12, 0, -40, }, /* 624 */
+ { 105, 7, 12, 0, 0, }, /* 625 */
+ { 103, 7, 12, 0, 0, }, /* 626 */
+ { 103, 21, 12, 0, 0, }, /* 627 */
+ { 109, 7, 12, 0, 0, }, /* 628 */
+ { 11, 7, 12, 0, 0, }, /* 629 */
+ { 80, 7, 12, 0, 0, }, /* 630 */
+ { 80, 21, 12, 0, 0, }, /* 631 */
+ { 80, 15, 12, 0, 0, }, /* 632 */
+ { 119, 7, 12, 0, 0, }, /* 633 */
+ { 119, 26, 12, 0, 0, }, /* 634 */
+ { 119, 15, 12, 0, 0, }, /* 635 */
+ { 115, 7, 12, 0, 0, }, /* 636 */
+ { 115, 15, 12, 0, 0, }, /* 637 */
+ { 127, 7, 12, 0, 0, }, /* 638 */
+ { 127, 15, 12, 0, 0, }, /* 639 */
+ { 65, 7, 12, 0, 0, }, /* 640 */
+ { 65, 15, 12, 0, 0, }, /* 641 */
+ { 65, 21, 12, 0, 0, }, /* 642 */
+ { 71, 7, 12, 0, 0, }, /* 643 */
+ { 71, 21, 12, 0, 0, }, /* 644 */
+ { 97, 7, 12, 0, 0, }, /* 645 */
+ { 96, 7, 12, 0, 0, }, /* 646 */
+ { 96, 15, 12, 0, 0, }, /* 647 */
+ { 30, 7, 12, 0, 0, }, /* 648 */
+ { 30, 12, 3, 0, 0, }, /* 649 */
+ { 30, 15, 12, 0, 0, }, /* 650 */
+ { 30, 21, 12, 0, 0, }, /* 651 */
+ { 87, 7, 12, 0, 0, }, /* 652 */
+ { 87, 15, 12, 0, 0, }, /* 653 */
+ { 87, 21, 12, 0, 0, }, /* 654 */
+ { 116, 7, 12, 0, 0, }, /* 655 */
+ { 116, 15, 12, 0, 0, }, /* 656 */
+ { 111, 7, 12, 0, 0, }, /* 657 */
+ { 111, 26, 12, 0, 0, }, /* 658 */
+ { 111, 12, 3, 0, 0, }, /* 659 */
+ { 111, 15, 12, 0, 0, }, /* 660 */
+ { 111, 21, 12, 0, 0, }, /* 661 */
+ { 77, 7, 12, 0, 0, }, /* 662 */
+ { 77, 21, 12, 0, 0, }, /* 663 */
+ { 82, 7, 12, 0, 0, }, /* 664 */
+ { 82, 15, 12, 0, 0, }, /* 665 */
+ { 81, 7, 12, 0, 0, }, /* 666 */
+ { 81, 15, 12, 0, 0, }, /* 667 */
+ { 120, 7, 12, 0, 0, }, /* 668 */
+ { 120, 21, 12, 0, 0, }, /* 669 */
+ { 120, 15, 12, 0, 0, }, /* 670 */
+ { 88, 7, 12, 0, 0, }, /* 671 */
+ { 129, 9, 12, 0, 64, }, /* 672 */
+ { 129, 5, 12, 0, -64, }, /* 673 */
+ { 129, 15, 12, 0, 0, }, /* 674 */
+ { 143, 7, 12, 0, 0, }, /* 675 */
+ { 143, 12, 3, 0, 0, }, /* 676 */
+ { 143, 13, 12, 0, 0, }, /* 677 */
+ { 0, 15, 12, 0, 0, }, /* 678 */
+ { 146, 7, 12, 0, 0, }, /* 679 */
+ { 146, 15, 12, 0, 0, }, /* 680 */
+ { 147, 7, 12, 0, 0, }, /* 681 */
+ { 147, 12, 3, 0, 0, }, /* 682 */
+ { 147, 15, 12, 0, 0, }, /* 683 */
+ { 147, 21, 12, 0, 0, }, /* 684 */
+ { 93, 10, 5, 0, 0, }, /* 685 */
+ { 93, 12, 3, 0, 0, }, /* 686 */
+ { 93, 7, 12, 0, 0, }, /* 687 */
+ { 93, 21, 12, 0, 0, }, /* 688 */
+ { 93, 15, 12, 0, 0, }, /* 689 */
+ { 93, 13, 12, 0, 0, }, /* 690 */
+ { 84, 12, 3, 0, 0, }, /* 691 */
+ { 84, 10, 5, 0, 0, }, /* 692 */
+ { 84, 7, 12, 0, 0, }, /* 693 */
+ { 84, 21, 12, 0, 0, }, /* 694 */
+ { 84, 1, 4, 0, 0, }, /* 695 */
+ { 100, 7, 12, 0, 0, }, /* 696 */
+ { 100, 13, 12, 0, 0, }, /* 697 */
+ { 95, 12, 3, 0, 0, }, /* 698 */
+ { 95, 7, 12, 0, 0, }, /* 699 */
+ { 95, 10, 5, 0, 0, }, /* 700 */
+ { 95, 13, 12, 0, 0, }, /* 701 */
+ { 95, 21, 12, 0, 0, }, /* 702 */
+ { 110, 7, 12, 0, 0, }, /* 703 */
+ { 110, 12, 3, 0, 0, }, /* 704 */
+ { 110, 21, 12, 0, 0, }, /* 705 */
+ { 99, 12, 3, 0, 0, }, /* 706 */
+ { 99, 10, 5, 0, 0, }, /* 707 */
+ { 99, 7, 12, 0, 0, }, /* 708 */
+ { 99, 7, 4, 0, 0, }, /* 709 */
+ { 99, 21, 12, 0, 0, }, /* 710 */
+ { 99, 13, 12, 0, 0, }, /* 711 */
+ { 47, 15, 12, 0, 0, }, /* 712 */
+ { 107, 7, 12, 0, 0, }, /* 713 */
+ { 107, 10, 5, 0, 0, }, /* 714 */
+ { 107, 12, 3, 0, 0, }, /* 715 */
+ { 107, 21, 12, 0, 0, }, /* 716 */
+ { 128, 7, 12, 0, 0, }, /* 717 */
+ { 128, 21, 12, 0, 0, }, /* 718 */
+ { 108, 7, 12, 0, 0, }, /* 719 */
+ { 108, 12, 3, 0, 0, }, /* 720 */
+ { 108, 10, 5, 0, 0, }, /* 721 */
+ { 108, 13, 12, 0, 0, }, /* 722 */
+ { 106, 12, 3, 0, 0, }, /* 723 */
+ { 106, 10, 5, 0, 0, }, /* 724 */
+ { 106, 7, 12, 0, 0, }, /* 725 */
+ { 106, 10, 3, 0, 0, }, /* 726 */
+ { 134, 7, 12, 0, 0, }, /* 727 */
+ { 134, 10, 5, 0, 0, }, /* 728 */
+ { 134, 12, 3, 0, 0, }, /* 729 */
+ { 134, 21, 12, 0, 0, }, /* 730 */
+ { 134, 13, 12, 0, 0, }, /* 731 */
+ { 123, 7, 12, 0, 0, }, /* 732 */
+ { 123, 10, 3, 0, 0, }, /* 733 */
+ { 123, 10, 5, 0, 0, }, /* 734 */
+ { 123, 12, 3, 0, 0, }, /* 735 */
+ { 123, 21, 12, 0, 0, }, /* 736 */
+ { 123, 13, 12, 0, 0, }, /* 737 */
+ { 122, 7, 12, 0, 0, }, /* 738 */
+ { 122, 10, 3, 0, 0, }, /* 739 */
+ { 122, 10, 5, 0, 0, }, /* 740 */
+ { 122, 12, 3, 0, 0, }, /* 741 */
+ { 122, 21, 12, 0, 0, }, /* 742 */
+ { 113, 7, 12, 0, 0, }, /* 743 */
+ { 113, 10, 5, 0, 0, }, /* 744 */
+ { 113, 12, 3, 0, 0, }, /* 745 */
+ { 113, 21, 12, 0, 0, }, /* 746 */
+ { 113, 13, 12, 0, 0, }, /* 747 */
+ { 101, 7, 12, 0, 0, }, /* 748 */
+ { 101, 12, 3, 0, 0, }, /* 749 */
+ { 101, 10, 5, 0, 0, }, /* 750 */
+ { 101, 13, 12, 0, 0, }, /* 751 */
+ { 125, 7, 12, 0, 0, }, /* 752 */
+ { 125, 12, 3, 0, 0, }, /* 753 */
+ { 125, 10, 5, 0, 0, }, /* 754 */
+ { 125, 13, 12, 0, 0, }, /* 755 */
+ { 125, 15, 12, 0, 0, }, /* 756 */
+ { 125, 21, 12, 0, 0, }, /* 757 */
+ { 125, 26, 12, 0, 0, }, /* 758 */
+ { 141, 7, 12, 0, 0, }, /* 759 */
+ { 141, 10, 5, 0, 0, }, /* 760 */
+ { 141, 12, 3, 0, 0, }, /* 761 */
+ { 141, 21, 12, 0, 0, }, /* 762 */
+ { 124, 9, 12, 0, 32, }, /* 763 */
+ { 124, 5, 12, 0, -32, }, /* 764 */
+ { 124, 13, 12, 0, 0, }, /* 765 */
+ { 124, 15, 12, 0, 0, }, /* 766 */
+ { 124, 7, 12, 0, 0, }, /* 767 */
+ { 140, 7, 12, 0, 0, }, /* 768 */
+ { 140, 12, 3, 0, 0, }, /* 769 */
+ { 140, 10, 5, 0, 0, }, /* 770 */
+ { 140, 7, 4, 0, 0, }, /* 771 */
+ { 140, 21, 12, 0, 0, }, /* 772 */
+ { 139, 7, 12, 0, 0, }, /* 773 */
+ { 139, 12, 3, 0, 0, }, /* 774 */
+ { 139, 10, 5, 0, 0, }, /* 775 */
+ { 139, 7, 4, 0, 0, }, /* 776 */
+ { 139, 21, 12, 0, 0, }, /* 777 */
+ { 121, 7, 12, 0, 0, }, /* 778 */
+ { 132, 7, 12, 0, 0, }, /* 779 */
+ { 132, 10, 5, 0, 0, }, /* 780 */
+ { 132, 12, 3, 0, 0, }, /* 781 */
+ { 132, 21, 12, 0, 0, }, /* 782 */
+ { 132, 13, 12, 0, 0, }, /* 783 */
+ { 132, 15, 12, 0, 0, }, /* 784 */
+ { 133, 21, 12, 0, 0, }, /* 785 */
+ { 133, 7, 12, 0, 0, }, /* 786 */
+ { 133, 12, 3, 0, 0, }, /* 787 */
+ { 133, 10, 5, 0, 0, }, /* 788 */
+ { 137, 7, 12, 0, 0, }, /* 789 */
+ { 137, 12, 3, 0, 0, }, /* 790 */
+ { 137, 7, 4, 0, 0, }, /* 791 */
+ { 137, 13, 12, 0, 0, }, /* 792 */
+ { 142, 7, 12, 0, 0, }, /* 793 */
+ { 142, 10, 5, 0, 0, }, /* 794 */
+ { 142, 12, 3, 0, 0, }, /* 795 */
+ { 142, 13, 12, 0, 0, }, /* 796 */
+ { 144, 7, 12, 0, 0, }, /* 797 */
+ { 144, 12, 3, 0, 0, }, /* 798 */
+ { 144, 10, 5, 0, 0, }, /* 799 */
+ { 144, 21, 12, 0, 0, }, /* 800 */
+ { 62, 7, 12, 0, 0, }, /* 801 */
+ { 62, 14, 12, 0, 0, }, /* 802 */
+ { 62, 21, 12, 0, 0, }, /* 803 */
+ { 79, 7, 12, 0, 0, }, /* 804 */
+ { 126, 7, 12, 0, 0, }, /* 805 */
+ { 114, 7, 12, 0, 0, }, /* 806 */
+ { 114, 13, 12, 0, 0, }, /* 807 */
+ { 114, 21, 12, 0, 0, }, /* 808 */
+ { 102, 7, 12, 0, 0, }, /* 809 */
+ { 102, 12, 3, 0, 0, }, /* 810 */
+ { 102, 21, 12, 0, 0, }, /* 811 */
+ { 118, 7, 12, 0, 0, }, /* 812 */
+ { 118, 12, 3, 0, 0, }, /* 813 */
+ { 118, 21, 12, 0, 0, }, /* 814 */
+ { 118, 26, 12, 0, 0, }, /* 815 */
+ { 118, 6, 12, 0, 0, }, /* 816 */
+ { 118, 13, 12, 0, 0, }, /* 817 */
+ { 118, 15, 12, 0, 0, }, /* 818 */
+ { 145, 9, 12, 0, 32, }, /* 819 */
+ { 145, 5, 12, 0, -32, }, /* 820 */
+ { 145, 15, 12, 0, 0, }, /* 821 */
+ { 145, 21, 12, 0, 0, }, /* 822 */
+ { 98, 7, 12, 0, 0, }, /* 823 */
+ { 98, 10, 5, 0, 0, }, /* 824 */
+ { 98, 12, 3, 0, 0, }, /* 825 */
+ { 98, 6, 12, 0, 0, }, /* 826 */
+ { 136, 6, 12, 0, 0, }, /* 827 */
+ { 138, 6, 12, 0, 0, }, /* 828 */
+ { 136, 7, 12, 0, 0, }, /* 829 */
+ { 138, 7, 12, 0, 0, }, /* 830 */
+ { 104, 7, 12, 0, 0, }, /* 831 */
+ { 104, 26, 12, 0, 0, }, /* 832 */
+ { 104, 12, 3, 0, 0, }, /* 833 */
+ { 104, 21, 12, 0, 0, }, /* 834 */
+ { 9, 10, 3, 0, 0, }, /* 835 */
+ { 19, 12, 3, 0, 0, }, /* 836 */
+ { 130, 26, 12, 0, 0, }, /* 837 */
+ { 130, 12, 3, 0, 0, }, /* 838 */
+ { 130, 21, 12, 0, 0, }, /* 839 */
+ { 17, 12, 3, 0, 0, }, /* 840 */
+ { 112, 7, 12, 0, 0, }, /* 841 */
+ { 112, 15, 12, 0, 0, }, /* 842 */
+ { 112, 12, 3, 0, 0, }, /* 843 */
+ { 131, 9, 12, 0, 34, }, /* 844 */
+ { 131, 5, 12, 0, -34, }, /* 845 */
+ { 131, 12, 3, 0, 0, }, /* 846 */
+ { 131, 13, 12, 0, 0, }, /* 847 */
+ { 131, 21, 12, 0, 0, }, /* 848 */
+ { 9, 2, 14, 0, 0, }, /* 849 */
+ { 9, 26, 11, 0, 0, }, /* 850 */
+ { 26, 26, 12, 0, 0, }, /* 851 */
+ { 9, 24, 3, 0, 0, }, /* 852 */
+ { 9, 1, 3, 0, 0, }, /* 853 */
};
-const uint8_t PRIV(ucd_stage1)[] = { /* 8704 bytes */
+const uint16_t PRIV(ucd_stage1)[] = { /* 17408 bytes */
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* U+0000 */
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* U+0800 */
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 41, 41, 42, 43, 44, 45, /* U+1000 */
46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, /* U+1800 */
62, 63, 64, 65, 66, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, /* U+2000 */
- 77, 77, 66, 78, 66, 66, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, /* U+2800 */
- 89, 90, 91, 92, 93, 94, 95, 71, 96, 96, 96, 96, 96, 96, 96, 96, /* U+3000 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+3800 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+4000 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 97, 96, 96, 96, 96, /* U+4800 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+5000 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+5800 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+6000 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+6800 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+7000 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+7800 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+8000 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+8800 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+9000 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 98, /* U+9800 */
- 99,100,100,100,100,100,100,100,100,101,102,102,103,104,105,106, /* U+A000 */
-107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,115, /* U+A800 */
-116,117,118,119,120,121,115,116,117,118,119,120,121,115,116,117, /* U+B000 */
-118,119,120,121,115,116,117,118,119,120,121,115,116,117,118,119, /* U+B800 */
-120,121,115,116,117,118,119,120,121,115,116,117,118,119,120,121, /* U+C000 */
-115,116,117,118,119,120,121,115,116,117,118,119,120,121,115,116, /* U+C800 */
-117,118,119,120,121,115,116,117,118,119,120,121,115,116,117,122, /* U+D000 */
-123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+D800 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+E000 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+E800 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F000 */
-124,124, 96, 96,125,126,127,128,129,129,130,131,132,133,134,135, /* U+F800 */
-136,137,138,139,140,141,142,143,144,145,146,140,147,147,148,140, /* U+10000 */
-149,150,151,152,153,154,155,156,157,158,140,140,159,140,140,140, /* U+10800 */
-160,161,162,163,164,165,166,140,167,168,140,169,170,171,172,140, /* U+11000 */
-140,173,140,140,174,175,140,140,176,177,178,140,140,140,140,140, /* U+11800 */
-179,179,179,179,179,179,179,180,181,179,182,140,140,140,140,140, /* U+12000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+12800 */
-183,183,183,183,183,183,183,183,184,140,140,140,140,140,140,140, /* U+13000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+13800 */
-140,140,140,140,140,140,140,140,185,185,185,185,186,140,140,140, /* U+14000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+14800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+15000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+15800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+16000 */
-187,187,187,187,188,189,190,191,140,140,140,140,140,140,192,193, /* U+16800 */
-194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194, /* U+17000 */
-194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194, /* U+17800 */
-194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,195, /* U+18000 */
-194,194,194,194,194,196,140,140,140,140,140,140,140,140,140,140, /* U+18800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+19000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+19800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+1A000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+1A800 */
-197,198,199,200,200,201,140,140,140,140,140,140,140,140,140,140, /* U+1B000 */
-140,140,140,140,140,140,140,140,202,203,140,140,140,140,140,140, /* U+1B800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+1C000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+1C800 */
- 71,204,205,206,207,140,208,140,209,210,211,212,213,214,215,216, /* U+1D000 */
-217,217,217,217,218,219,140,140,140,140,140,140,140,140,140,140, /* U+1D800 */
-220,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+1E000 */
-221,222,223,140,140,140,140,140,140,140,140,140,224,225,140,140, /* U+1E800 */
-226,227,228,229,230,140,231,232,233,234,235,236,237,238,239,240, /* U+1F000 */
-241,242,243,244,140,140,140,140,140,140,140,140,140,140,140,140, /* U+1F800 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+20000 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+20800 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+21000 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+21800 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+22000 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+22800 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+23000 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+23800 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+24000 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+24800 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+25000 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+25800 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+26000 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+26800 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+27000 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+27800 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+28000 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+28800 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+29000 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+29800 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,245, 96, 96, /* U+2A000 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+2A800 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,246, 96, /* U+2B000 */
-247, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+2B800 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+2C000 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,248, 96, 96, /* U+2C800 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+2D000 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+2D800 */
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+2E000 */
- 96, 96, 96, 96, 96, 96, 96,249,140,140,140,140,140,140,140,140, /* U+2E800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+2F000 */
- 96, 96, 96, 96,250,140,140,140,140,140,140,140,140,140,140,140, /* U+2F800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+30000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+30800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+31000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+31800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+32000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+32800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+33000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+33800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+34000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+34800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+35000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+35800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+36000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+36800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+37000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+37800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+38000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+38800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+39000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+39800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+3A000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+3A800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+3B000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+3B800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+3C000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+3C800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+3D000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+3D800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+3E000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+3E800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+3F000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+3F800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+40000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+40800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+41000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+41800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+42000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+42800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+43000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+43800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+44000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+44800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+45000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+45800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+46000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+46800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+47000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+47800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+48000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+48800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+49000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+49800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+4A000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+4A800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+4B000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+4B800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+4C000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+4C800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+4D000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+4D800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+4E000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+4E800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+4F000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+4F800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+50000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+50800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+51000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+51800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+52000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+52800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+53000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+53800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+54000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+54800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+55000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+55800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+56000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+56800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+57000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+57800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+58000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+58800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+59000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+59800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+5A000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+5A800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+5B000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+5B800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+5C000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+5C800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+5D000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+5D800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+5E000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+5E800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+5F000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+5F800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+60000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+60800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+61000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+61800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+62000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+62800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+63000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+63800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+64000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+64800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+65000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+65800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+66000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+66800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+67000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+67800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+68000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+68800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+69000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+69800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+6A000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+6A800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+6B000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+6B800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+6C000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+6C800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+6D000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+6D800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+6E000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+6E800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+6F000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+6F800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+70000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+70800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+71000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+71800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+72000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+72800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+73000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+73800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+74000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+74800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+75000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+75800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+76000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+76800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+77000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+77800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+78000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+78800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+79000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+79800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+7A000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+7A800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+7B000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+7B800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+7C000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+7C800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+7D000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+7D800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+7E000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+7E800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+7F000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+7F800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+80000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+80800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+81000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+81800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+82000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+82800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+83000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+83800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+84000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+84800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+85000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+85800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+86000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+86800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+87000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+87800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+88000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+88800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+89000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+89800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+8A000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+8A800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+8B000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+8B800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+8C000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+8C800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+8D000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+8D800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+8E000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+8E800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+8F000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+8F800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+90000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+90800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+91000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+91800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+92000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+92800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+93000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+93800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+94000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+94800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+95000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+95800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+96000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+96800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+97000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+97800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+98000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+98800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+99000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+99800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+9A000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+9A800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+9B000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+9B800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+9C000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+9C800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+9D000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+9D800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+9E000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+9E800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+9F000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+9F800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A0000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A0800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A1000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A1800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A2000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A2800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A3000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A3800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A4000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A4800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A5000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A5800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A6000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A6800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A7000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A7800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A8000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A8800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A9000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A9800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+AA000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+AA800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+AB000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+AB800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+AC000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+AC800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+AD000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+AD800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+AE000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+AE800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+AF000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+AF800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B0000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B0800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B1000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B1800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B2000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B2800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B3000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B3800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B4000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B4800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B5000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B5800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B6000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B6800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B7000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B7800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B8000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B8800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B9000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B9800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+BA000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+BA800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+BB000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+BB800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+BC000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+BC800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+BD000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+BD800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+BE000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+BE800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+BF000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+BF800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C0000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C0800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C1000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C1800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C2000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C2800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C3000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C3800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C4000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C4800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C5000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C5800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C6000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C6800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C7000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C7800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C8000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C8800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C9000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C9800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+CA000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+CA800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+CB000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+CB800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+CC000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+CC800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+CD000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+CD800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+CE000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+CE800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+CF000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+CF800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D0000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D0800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D1000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D1800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D2000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D2800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D3000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D3800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D4000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D4800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D5000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D5800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D6000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D6800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D7000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D7800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D8000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D8800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D9000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D9800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+DA000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+DA800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+DB000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+DB800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+DC000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+DC800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+DD000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+DD800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+DE000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+DE800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+DF000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+DF800 */
-251,252,253,254,252,252,252,252,252,252,252,252,252,252,252,252, /* U+E0000 */
-252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252, /* U+E0800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+E1000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+E1800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+E2000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+E2800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+E3000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+E3800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+E4000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+E4800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+E5000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+E5800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+E6000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+E6800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+E7000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+E7800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+E8000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+E8800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+E9000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+E9800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+EA000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+EA800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+EB000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+EB800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+EC000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+EC800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+ED000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+ED800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+EE000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+EE800 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+EF000 */
-140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+EF800 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F0000 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F0800 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F1000 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F1800 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F2000 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F2800 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F3000 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F3800 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F4000 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F4800 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F5000 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F5800 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F6000 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F6800 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F7000 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F7800 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F8000 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F8800 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F9000 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F9800 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+FA000 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+FA800 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+FB000 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+FB800 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+FC000 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+FC800 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+FD000 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+FD800 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+FE000 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+FE800 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+FF000 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,255, /* U+FF800 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+100000 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+100800 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+101000 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+101800 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+102000 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+102800 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+103000 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+103800 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+104000 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+104800 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+105000 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+105800 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+106000 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+106800 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+107000 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+107800 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+108000 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+108800 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+109000 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+109800 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+10A000 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+10A800 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+10B000 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+10B800 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+10C000 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+10C800 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+10D000 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+10D800 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+10E000 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+10E800 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+10F000 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,255, /* U+10F800 */
+ 77, 77, 78, 79, 66, 66, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, /* U+2800 */
+ 90, 91, 92, 93, 94, 95, 96, 71, 97, 97, 97, 97, 97, 97, 97, 97, /* U+3000 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, /* U+3800 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, /* U+4000 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 98, 97, 97, 97, 97, /* U+4800 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, /* U+5000 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, /* U+5800 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, /* U+6000 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, /* U+6800 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, /* U+7000 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, /* U+7800 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, /* U+8000 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, /* U+8800 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, /* U+9000 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 99, /* U+9800 */
+100,101,101,101,101,101,101,101,101,102,103,103,104,105,106,107, /* U+A000 */
+108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,116, /* U+A800 */
+117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118, /* U+B000 */
+119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120, /* U+B800 */
+121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122, /* U+C000 */
+116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117, /* U+C800 */
+118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,123, /* U+D000 */
+124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+D800 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+E000 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+E800 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F000 */
+125,125, 97, 97,126,127,128,129,130,130,131,132,133,134,135,136, /* U+F800 */
+137,138,139,140,141,142,143,144,145,146,147,141,148,148,149,141, /* U+10000 */
+150,151,152,153,154,155,156,157,158,159,160,141,161,141,162,141, /* U+10800 */
+163,164,165,166,167,168,169,141,170,171,141,172,173,174,175,141, /* U+11000 */
+176,177,141,141,178,179,141,141,180,181,182,183,141,184,141,141, /* U+11800 */
+185,185,185,185,185,185,185,186,187,185,188,141,141,141,141,141, /* U+12000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+12800 */
+189,189,189,189,189,189,189,189,190,141,141,141,141,141,141,141, /* U+13000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+13800 */
+141,141,141,141,141,141,141,141,191,191,191,191,192,141,141,141, /* U+14000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+14800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+15000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+15800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+16000 */
+193,193,193,193,194,195,196,197,141,141,141,141,198,199,200,201, /* U+16800 */
+202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202, /* U+17000 */
+202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202, /* U+17800 */
+202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,203, /* U+18000 */
+202,202,202,202,202,204,141,141,141,141,141,141,141,141,141,141, /* U+18800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+19000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+19800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+1A000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+1A800 */
+205,206,207,208,208,209,141,141,141,141,141,141,141,141,141,141, /* U+1B000 */
+141,141,141,141,141,141,141,141,210,211,141,141,141,141,141,141, /* U+1B800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+1C000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+1C800 */
+ 71,212,213,214,215,216,217,141,218,219,220,221,222,223,224,225, /* U+1D000 */
+226,226,226,226,227,228,141,141,141,141,141,141,141,141,141,141, /* U+1D800 */
+229,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+1E000 */
+230,231,232,141,141,141,141,141,233,234,141,141,235,236,141,141, /* U+1E800 */
+237,238,239,240,241,242,243,244,243,243,245,243,246,247,248,249, /* U+1F000 */
+250,251,252,253,254,242,242,242,242,242,242,242,242,242,242,255, /* U+1F800 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, /* U+20000 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, /* U+20800 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, /* U+21000 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, /* U+21800 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, /* U+22000 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, /* U+22800 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, /* U+23000 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, /* U+23800 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, /* U+24000 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, /* U+24800 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, /* U+25000 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, /* U+25800 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, /* U+26000 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, /* U+26800 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, /* U+27000 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, /* U+27800 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, /* U+28000 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, /* U+28800 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, /* U+29000 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, /* U+29800 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,256, 97, 97, /* U+2A000 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, /* U+2A800 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,257, 97, /* U+2B000 */
+258, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, /* U+2B800 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, /* U+2C000 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,259, 97, 97, /* U+2C800 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, /* U+2D000 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, /* U+2D800 */
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, /* U+2E000 */
+ 97, 97, 97, 97, 97, 97, 97,260,141,141,141,141,141,141,141,141, /* U+2E800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+2F000 */
+ 97, 97, 97, 97,261,141,141,141,141,141,141,141,141,141,141,141, /* U+2F800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+30000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+30800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+31000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+31800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+32000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+32800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+33000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+33800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+34000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+34800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+35000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+35800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+36000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+36800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+37000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+37800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+38000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+38800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+39000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+39800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+3A000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+3A800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+3B000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+3B800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+3C000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+3C800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+3D000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+3D800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+3E000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+3E800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+3F000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+3F800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+40000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+40800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+41000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+41800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+42000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+42800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+43000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+43800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+44000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+44800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+45000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+45800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+46000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+46800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+47000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+47800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+48000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+48800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+49000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+49800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+4A000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+4A800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+4B000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+4B800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+4C000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+4C800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+4D000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+4D800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+4E000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+4E800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+4F000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+4F800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+50000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+50800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+51000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+51800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+52000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+52800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+53000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+53800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+54000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+54800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+55000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+55800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+56000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+56800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+57000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+57800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+58000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+58800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+59000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+59800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+5A000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+5A800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+5B000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+5B800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+5C000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+5C800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+5D000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+5D800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+5E000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+5E800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+5F000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+5F800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+60000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+60800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+61000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+61800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+62000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+62800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+63000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+63800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+64000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+64800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+65000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+65800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+66000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+66800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+67000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+67800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+68000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+68800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+69000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+69800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+6A000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+6A800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+6B000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+6B800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+6C000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+6C800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+6D000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+6D800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+6E000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+6E800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+6F000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+6F800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+70000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+70800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+71000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+71800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+72000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+72800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+73000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+73800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+74000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+74800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+75000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+75800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+76000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+76800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+77000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+77800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+78000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+78800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+79000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+79800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+7A000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+7A800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+7B000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+7B800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+7C000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+7C800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+7D000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+7D800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+7E000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+7E800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+7F000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+7F800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+80000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+80800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+81000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+81800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+82000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+82800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+83000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+83800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+84000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+84800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+85000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+85800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+86000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+86800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+87000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+87800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+88000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+88800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+89000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+89800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+8A000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+8A800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+8B000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+8B800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+8C000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+8C800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+8D000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+8D800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+8E000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+8E800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+8F000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+8F800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+90000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+90800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+91000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+91800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+92000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+92800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+93000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+93800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+94000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+94800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+95000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+95800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+96000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+96800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+97000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+97800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+98000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+98800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+99000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+99800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+9A000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+9A800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+9B000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+9B800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+9C000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+9C800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+9D000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+9D800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+9E000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+9E800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+9F000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+9F800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A0000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A0800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A1000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A1800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A2000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A2800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A3000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A3800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A4000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A4800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A5000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A5800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A6000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A6800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A7000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A7800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A8000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A8800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A9000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A9800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+AA000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+AA800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+AB000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+AB800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+AC000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+AC800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+AD000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+AD800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+AE000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+AE800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+AF000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+AF800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B0000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B0800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B1000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B1800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B2000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B2800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B3000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B3800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B4000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B4800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B5000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B5800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B6000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B6800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B7000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B7800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B8000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B8800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B9000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B9800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+BA000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+BA800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+BB000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+BB800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+BC000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+BC800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+BD000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+BD800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+BE000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+BE800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+BF000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+BF800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C0000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C0800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C1000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C1800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C2000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C2800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C3000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C3800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C4000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C4800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C5000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C5800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C6000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C6800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C7000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C7800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C8000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C8800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C9000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C9800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+CA000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+CA800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+CB000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+CB800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+CC000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+CC800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+CD000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+CD800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+CE000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+CE800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+CF000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+CF800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D0000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D0800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D1000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D1800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D2000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D2800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D3000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D3800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D4000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D4800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D5000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D5800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D6000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D6800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D7000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D7800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D8000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D8800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D9000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D9800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+DA000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+DA800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+DB000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+DB800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+DC000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+DC800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+DD000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+DD800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+DE000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+DE800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+DF000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+DF800 */
+262,263,264,265,263,263,263,263,263,263,263,263,263,263,263,263, /* U+E0000 */
+263,263,263,263,263,263,263,263,263,263,263,263,263,263,263,263, /* U+E0800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+E1000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+E1800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+E2000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+E2800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+E3000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+E3800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+E4000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+E4800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+E5000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+E5800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+E6000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+E6800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+E7000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+E7800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+E8000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+E8800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+E9000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+E9800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+EA000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+EA800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+EB000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+EB800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+EC000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+EC800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+ED000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+ED800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+EE000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+EE800 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+EF000 */
+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+EF800 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F0000 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F0800 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F1000 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F1800 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F2000 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F2800 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F3000 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F3800 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F4000 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F4800 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F5000 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F5800 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F6000 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F6800 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F7000 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F7800 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F8000 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F8800 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F9000 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F9800 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+FA000 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+FA800 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+FB000 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+FB800 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+FC000 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+FC800 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+FD000 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+FD800 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+FE000 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+FE800 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+FF000 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,266, /* U+FF800 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+100000 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+100800 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+101000 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+101800 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+102000 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+102800 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+103000 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+103800 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+104000 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+104800 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+105000 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+105800 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+106000 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+106800 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+107000 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+107800 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+108000 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+108800 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+109000 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+109800 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+10A000 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+10A800 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+10B000 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+10B800 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+10C000 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+10C800 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+10D000 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+10D800 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+10E000 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+10E800 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+10F000 */
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,266, /* U+10F800 */
};
-const uint16_t PRIV(ucd_stage2)[] = { /* 65536 bytes, block = 128 */
+const uint16_t PRIV(ucd_stage2)[] = { /* 68352 bytes, block = 128 */
/* block 0 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -1489,647 +1522,647 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 65536 bytes, block = 128 */
/* block 1 */
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,
- 3, 4, 5, 5, 5, 5, 19, 4, 14, 19, 20, 21, 8, 22, 19, 14,
- 19, 8, 23, 23, 14, 24, 4, 4, 14, 23, 20, 25, 23, 23, 23, 4,
- 11, 11, 11, 11, 11, 26, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
- 11, 11, 11, 11, 11, 11, 11, 8, 11, 11, 11, 11, 11, 11, 11, 27,
- 16, 16, 16, 16, 16, 28, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 8, 16, 16, 16, 16, 16, 16, 16, 29,
+ 3, 4, 5, 5, 5, 5, 19, 4, 14, 20, 21, 22, 8, 23, 20, 14,
+ 19, 8, 24, 24, 14, 25, 4, 4, 14, 24, 21, 26, 24, 24, 24, 4,
+ 11, 11, 11, 11, 11, 27, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 8, 11, 11, 11, 11, 11, 11, 11, 28,
+ 16, 16, 16, 16, 16, 29, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 8, 16, 16, 16, 16, 16, 16, 16, 30,
/* block 2 */
- 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
- 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
- 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
- 32, 33, 30, 31, 30, 31, 30, 31, 33, 30, 31, 30, 31, 30, 31, 30,
- 31, 30, 31, 30, 31, 30, 31, 30, 31, 33, 30, 31, 30, 31, 30, 31,
- 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
- 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
- 30, 31, 30, 31, 30, 31, 30, 31, 34, 30, 31, 30, 31, 30, 31, 35,
+ 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32,
+ 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32,
+ 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32,
+ 33, 34, 31, 32, 31, 32, 31, 32, 34, 31, 32, 31, 32, 31, 32, 31,
+ 32, 31, 32, 31, 32, 31, 32, 31, 32, 34, 31, 32, 31, 32, 31, 32,
+ 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32,
+ 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32,
+ 31, 32, 31, 32, 31, 32, 31, 32, 35, 31, 32, 31, 32, 31, 32, 36,
/* block 3 */
- 36, 37, 30, 31, 30, 31, 38, 30, 31, 39, 39, 30, 31, 33, 40, 41,
- 42, 30, 31, 39, 43, 44, 45, 46, 30, 31, 47, 33, 45, 48, 49, 50,
- 30, 31, 30, 31, 30, 31, 51, 30, 31, 51, 33, 33, 30, 31, 51, 30,
- 31, 52, 52, 30, 31, 30, 31, 53, 30, 31, 33, 20, 30, 31, 33, 54,
- 20, 20, 20, 20, 55, 56, 57, 58, 59, 60, 61, 62, 63, 30, 31, 30,
- 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 64, 30, 31,
- 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
- 33, 65, 66, 67, 30, 31, 68, 69, 30, 31, 30, 31, 30, 31, 30, 31,
+ 37, 38, 31, 32, 31, 32, 39, 31, 32, 40, 40, 31, 32, 34, 41, 42,
+ 43, 31, 32, 40, 44, 45, 46, 47, 31, 32, 48, 34, 46, 49, 50, 51,
+ 31, 32, 31, 32, 31, 32, 52, 31, 32, 52, 34, 34, 31, 32, 52, 31,
+ 32, 53, 53, 31, 32, 31, 32, 54, 31, 32, 34, 21, 31, 32, 34, 55,
+ 21, 21, 21, 21, 56, 57, 58, 59, 60, 61, 62, 63, 64, 31, 32, 31,
+ 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 65, 31, 32,
+ 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32,
+ 34, 66, 67, 68, 31, 32, 69, 70, 31, 32, 31, 32, 31, 32, 31, 32,
/* block 4 */
- 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
- 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
- 70, 33, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
- 30, 31, 30, 31, 33, 33, 33, 33, 33, 33, 71, 30, 31, 72, 73, 74,
- 74, 30, 31, 75, 76, 77, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
- 78, 79, 80, 81, 82, 33, 83, 83, 33, 84, 33, 85, 86, 33, 33, 33,
- 83, 87, 33, 88, 33, 89, 90, 33, 91, 92, 90, 93, 94, 33, 33, 92,
- 33, 95, 96, 33, 33, 97, 33, 33, 33, 33, 33, 33, 33, 98, 33, 33,
+ 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32,
+ 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32,
+ 71, 34, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32,
+ 31, 32, 31, 32, 34, 34, 34, 34, 34, 34, 72, 31, 32, 73, 74, 75,
+ 75, 31, 32, 76, 77, 78, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32,
+ 79, 80, 81, 82, 83, 34, 84, 84, 34, 85, 34, 86, 87, 34, 34, 34,
+ 84, 88, 34, 89, 34, 90, 91, 34, 92, 93, 91, 94, 95, 34, 34, 93,
+ 34, 96, 97, 34, 34, 98, 34, 34, 34, 34, 34, 34, 34, 99, 34, 34,
/* block 5 */
- 99, 33, 33, 99, 33, 33, 33,100, 99,101,102,102,103, 33, 33, 33,
- 33, 33,104, 33, 20, 33, 33, 33, 33, 33, 33, 33, 33,105,106, 33,
- 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
-107,107,107,107,107,107,107,107,107,108,108,108,108,108,108,108,
-108,108, 14, 14, 14, 14,108,108,108,108,108,108,108,108,108,108,
-108,108, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-107,107,107,107,107, 14, 14, 14, 14, 14,109,109,108, 14,108, 14,
+100, 34, 34,100, 34, 34, 34,101,100,102,103,103,104, 34, 34, 34,
+ 34, 34,105, 34, 21, 34, 34, 34, 34, 34, 34, 34, 34,106,107, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+108,108,108,108,108,108,108,108,108,109,109,109,109,109,109,109,
+109,109, 14, 14, 14, 14,109,109,109,109,109,109,109,109,109,109,
+109,109, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+108,108,108,108,108, 14, 14, 14, 14, 14,110,110,109, 14,109, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
/* block 6 */
-110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
-110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
-110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
-110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
-110,110,110,110,110,111,110,110,110,110,110,110,110,110,110,110,
-110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
-110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
-112,113,112,113,108,114,112,113,115,115,116,117,117,117, 4,118,
+111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
+111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
+111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
+111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
+111,111,111,111,111,112,111,111,111,111,111,111,111,111,111,111,
+111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
+111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
+113,114,113,114,109,115,113,114,116,116,117,118,118,118, 4,119,
/* block 7 */
-115,115,115,115,114, 14,119, 4,120,120,120,115,121,115,122,122,
-123,124,125,124,124,126,124,124,127,128,129,124,130,124,124,124,
-131,132,115,133,124,124,134,124,124,135,124,124,136,137,137,137,
-123,138,139,138,138,140,138,138,141,142,143,138,144,138,138,138,
-145,146,147,148,138,138,149,138,138,150,138,138,151,152,152,153,
-154,155,156,156,156,157,158,159,112,113,112,113,112,113,112,113,
-112,113,160,161,160,161,160,161,160,161,160,161,160,161,160,161,
-162,163,164,165,166,167,168,112,113,169,112,113,123,170,170,170,
+116,116,116,116,115, 14,120, 4,121,121,121,116,122,116,123,123,
+124,125,126,125,125,127,125,125,128,129,130,125,131,125,125,125,
+132,133,116,134,125,125,135,125,125,136,125,125,137,138,138,138,
+124,139,140,139,139,141,139,139,142,143,144,139,145,139,139,139,
+146,147,148,149,139,139,150,139,139,151,139,139,152,153,153,154,
+155,156,157,157,157,158,159,160,113,114,113,114,113,114,113,114,
+113,114,161,162,161,162,161,162,161,162,161,162,161,162,161,162,
+163,164,165,166,167,168,169,113,114,170,113,114,124,171,171,171,
/* block 8 */
-171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,
-172,172,173,172,174,172,172,172,172,172,172,172,172,172,175,172,
-172,176,177,172,172,172,172,172,172,172,178,172,172,172,172,172,
-179,179,180,179,181,179,179,179,179,179,179,179,179,179,182,179,
-179,183,184,179,179,179,179,179,179,179,185,179,179,179,179,179,
-186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,
-187,188,189,190,187,188,187,188,187,188,187,188,187,188,187,188,
-187,188,187,188,187,188,187,188,187,188,187,188,187,188,187,188,
+172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,
+173,173,174,173,175,173,173,173,173,173,173,173,173,173,176,173,
+173,177,178,173,173,173,173,173,173,173,179,173,173,173,173,173,
+180,180,181,180,182,180,180,180,180,180,180,180,180,180,183,180,
+180,184,185,180,180,180,180,180,180,180,186,180,180,180,180,180,
+187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,
+188,189,190,191,188,189,188,189,188,189,188,189,188,189,188,189,
+188,189,188,189,188,189,188,189,188,189,188,189,188,189,188,189,
/* block 9 */
-187,188,191,192,192,110,110,192,193,193,187,188,187,188,187,188,
-187,188,187,188,187,188,187,188,187,188,187,188,187,188,187,188,
-187,188,187,188,187,188,187,188,187,188,187,188,187,188,187,188,
-187,188,187,188,187,188,187,188,187,188,187,188,187,188,187,188,
-194,187,188,187,188,187,188,187,188,187,188,187,188,187,188,195,
-187,188,187,188,187,188,187,188,187,188,187,188,187,188,187,188,
-187,188,187,188,187,188,187,188,187,188,187,188,187,188,187,188,
-187,188,187,188,187,188,187,188,187,188,187,188,187,188,187,188,
+188,189,192,193,193,111,111,193,194,194,188,189,188,189,188,189,
+188,189,188,189,188,189,188,189,188,189,188,189,188,189,188,189,
+188,189,188,189,188,189,188,189,188,189,188,189,188,189,188,189,
+188,189,188,189,188,189,188,189,188,189,188,189,188,189,188,189,
+195,188,189,188,189,188,189,188,189,188,189,188,189,188,189,196,
+188,189,188,189,188,189,188,189,188,189,188,189,188,189,188,189,
+188,189,188,189,188,189,188,189,188,189,188,189,188,189,188,189,
+188,189,188,189,188,189,188,189,188,189,188,189,188,189,188,189,
/* block 10 */
-187,188,187,188,187,188,187,188,187,188,187,188,187,188,187,188,
-187,188,187,188,187,188,187,188,187,188,187,188,187,188,187,188,
-187,188,187,188,187,188,187,188,187,188,187,188,187,188,187,188,
-115,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
-196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
-196,196,196,196,196,196,196,115,115,197,198,198,198,198,198,198,
-115,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
+188,189,188,189,188,189,188,189,188,189,188,189,188,189,188,189,
+188,189,188,189,188,189,188,189,188,189,188,189,188,189,188,189,
+188,189,188,189,188,189,188,189,188,189,188,189,188,189,188,189,
+116,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
+197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
+197,197,197,197,197,197,197,116,116,198,199,199,199,199,199,199,
+200,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,
+201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,
/* block 11 */
-199,199,199,199,199,199,199,200,115, 4,201,115,115,202,202,203,
-115,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,
-204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,
-204,204,204,204,204,204,204,204,204,204,204,204,204,204,205,204,
-206,204,204,206,204,204,206,204,115,115,115,115,115,115,115,115,
-207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,
-207,207,207,207,207,207,207,207,207,207,207,115,115,115,115,115,
-207,207,207,206,206,115,115,115,115,115,115,115,115,115,115,115,
+201,201,201,201,201,201,201,200,200, 4,202,116,116,203,203,204,
+116,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,
+205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,
+205,205,205,205,205,205,205,205,205,205,205,205,205,205,206,205,
+207,205,205,207,205,205,207,205,116,116,116,116,116,116,116,116,
+208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
+208,208,208,208,208,208,208,208,208,208,208,116,116,116,116,208,
+208,208,208,207,207,116,116,116,116,116,116,116,116,116,116,116,
/* block 12 */
-208,208,208,208,208,209,210,210,210,211,211,212, 4,211,213,213,
-214,214,214,214,214,214,214,214,214,214,214, 4,215,115,211, 4,
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-108,216,216,216,216,216,216,216,216,216,216,110,110,110,110,110,
-110,110,110,110,110,110,214,214,214,214,214,214,214,214,214,214,
-217,217,217,217,217,217,217,217,217,217,211,211,211,211,216,216,
-110,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
+209,209,209,209,209,210,211,211,211,212,212,213, 4,212,214,214,
+215,215,215,215,215,215,215,215,215,215,215, 4,216,116,212, 4,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+109,217,217,217,217,217,217,217,217,217,217,111,111,111,111,111,
+111,111,111,111,111,111,215,215,215,215,215,215,215,215,215,215,
+218,218,218,218,218,218,218,218,218,218,212,212,212,212,217,217,
+111,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
/* block 13 */
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-216,216,216,216,211,216,214,214,214,214,214,214,214,209,213,214,
-214,214,214,214,214,218,218,214,214,213,214,214,214,214,216,216,
-217,217,217,217,217,217,217,217,217,217,216,216,216,213,213,216,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,212,217,215,215,215,215,215,215,215,210,214,215,
+215,215,215,215,215,219,219,215,215,214,215,215,215,215,217,217,
+218,218,218,218,218,218,218,218,218,218,217,217,217,214,214,217,
/* block 14 */
-219,219,219,219,219,219,219,219,219,219,219,219,219,219,115,220,
-221,222,221,221,221,221,221,221,221,221,221,221,221,221,221,221,
-221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,
+220,220,220,220,220,220,220,220,220,220,220,220,220,220,116,221,
+222,223,222,222,222,222,222,222,222,222,222,222,222,222,222,222,
222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,
-222,222,222,222,222,222,222,222,222,222,222,115,115,221,221,221,
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
+223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,
+223,223,223,223,223,223,223,223,223,223,223,116,116,222,222,222,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
/* block 15 */
-223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,
-223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,
-223,223,223,223,223,223,224,224,224,224,224,224,224,224,224,224,
-224,223,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-225,225,225,225,225,225,225,225,225,225,226,226,226,226,226,226,
-226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,
-226,226,226,226,226,226,226,226,226,226,226,227,227,227,227,227,
-227,227,227,227,228,228,229,230,230,230,228,115,115,115,115,115,
+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
+224,224,224,224,224,224,225,225,225,225,225,225,225,225,225,225,
+225,224,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+226,226,226,226,226,226,226,226,226,226,227,227,227,227,227,227,
+227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,
+227,227,227,227,227,227,227,227,227,227,227,228,228,228,228,228,
+228,228,228,228,229,229,230,231,231,231,229,116,116,228,232,232,
/* block 16 */
-231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,
-231,231,231,231,231,231,232,232,232,232,233,232,232,232,232,232,
-232,232,232,232,233,232,232,232,233,232,232,232,232,232,115,115,
-234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,115,
-235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
-235,235,235,235,235,235,235,235,235,236,236,236,115,115,237,115,
-221,221,221,221,221,221,221,221,221,221,221,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,
+233,233,233,233,233,233,234,234,234,234,235,234,234,234,234,234,
+234,234,234,234,235,234,234,234,235,234,234,234,234,234,116,116,
+236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,116,
+237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,
+237,237,237,237,237,237,237,237,237,238,238,238,116,116,239,116,
+222,222,222,222,222,222,222,222,222,222,222,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 17 */
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-216,216,216,216,216,115,216,216,216,216,216,216,216,216,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,214,214,214,214,214,214,214,214,214,214,214,214,
-214,214,209,214,214,214,214,214,214,214,214,214,214,214,214,214,
-214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,116,217,217,217,217,217,217,217,217,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,215,215,215,215,215,215,215,215,215,215,215,215,215,
+215,215,210,215,215,215,215,215,215,215,215,215,215,215,215,215,
+215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,
/* block 18 */
-238,238,238,239,240,240,240,240,240,240,240,240,240,240,240,240,
-240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
-240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
-240,240,240,240,240,240,240,240,240,240,238,239,238,240,239,239,
-239,238,238,238,238,238,238,238,238,239,239,239,239,238,239,239,
-240,110,110,238,238,238,238,238,240,240,240,240,240,240,240,240,
-240,240,238,238, 4, 4,241,241,241,241,241,241,241,241,241,241,
-242,243,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
+240,240,240,241,242,242,242,242,242,242,242,242,242,242,242,242,
+242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,
+242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,
+242,242,242,242,242,242,242,242,242,242,240,241,240,242,241,241,
+241,240,240,240,240,240,240,240,240,241,241,241,241,240,241,241,
+242,111,111,240,240,240,240,240,242,242,242,242,242,242,242,242,
+242,242,240,240, 4, 4,243,243,243,243,243,243,243,243,243,243,
+244,245,242,242,242,242,242,242,242,242,242,242,242,242,242,242,
/* block 19 */
-244,245,246,246,115,244,244,244,244,244,244,244,244,115,115,244,
-244,115,115,244,244,244,244,244,244,244,244,244,244,244,244,244,
-244,244,244,244,244,244,244,244,244,115,244,244,244,244,244,244,
-244,115,244,115,115,115,244,244,244,244,115,115,245,244,247,246,
-246,245,245,245,245,115,115,246,246,115,115,246,246,245,244,115,
-115,115,115,115,115,115,115,247,115,115,115,115,244,244,115,244,
-244,244,245,245,115,115,248,248,248,248,248,248,248,248,248,248,
-244,244,249,249,250,250,250,250,250,250,251,249,244,252,115,115,
+246,247,248,248,116,246,246,246,246,246,246,246,246,116,116,246,
+246,116,116,246,246,246,246,246,246,246,246,246,246,246,246,246,
+246,246,246,246,246,246,246,246,246,116,246,246,246,246,246,246,
+246,116,246,116,116,116,246,246,246,246,116,116,247,246,249,248,
+248,247,247,247,247,116,116,248,248,116,116,248,248,247,246,116,
+116,116,116,116,116,116,116,249,116,116,116,116,246,246,116,246,
+246,246,247,247,116,116,250,250,250,250,250,250,250,250,250,250,
+246,246,251,251,252,252,252,252,252,252,253,251,246,254,247,116,
/* block 20 */
-115,253,253,254,115,255,255,255,255,255,255,115,115,115,115,255,
-255,115,115,255,255,255,255,255,255,255,255,255,255,255,255,255,
-255,255,255,255,255,255,255,255,255,115,255,255,255,255,255,255,
-255,115,255,255,115,255,255,115,255,255,115,115,253,115,254,254,
-254,253,253,115,115,115,115,253,253,115,115,253,253,253,115,115,
-115,253,115,115,115,115,115,115,115,255,255,255,255,115,255,115,
-115,115,115,115,115,115,256,256,256,256,256,256,256,256,256,256,
-253,253,255,255,255,253,115,115,115,115,115,115,115,115,115,115,
+116,255,255,256,116,257,257,257,257,257,257,116,116,116,116,257,
+257,116,116,257,257,257,257,257,257,257,257,257,257,257,257,257,
+257,257,257,257,257,257,257,257,257,116,257,257,257,257,257,257,
+257,116,257,257,116,257,257,116,257,257,116,116,255,116,256,256,
+256,255,255,116,116,116,116,255,255,116,116,255,255,255,116,116,
+116,255,116,116,116,116,116,116,116,257,257,257,257,116,257,116,
+116,116,116,116,116,116,258,258,258,258,258,258,258,258,258,258,
+255,255,257,257,257,255,259,116,116,116,116,116,116,116,116,116,
/* block 21 */
-115,257,257,258,115,259,259,259,259,259,259,259,259,259,115,259,
-259,259,115,259,259,259,259,259,259,259,259,259,259,259,259,259,
-259,259,259,259,259,259,259,259,259,115,259,259,259,259,259,259,
-259,115,259,259,115,259,259,259,259,259,115,115,257,259,258,258,
-258,257,257,257,257,257,115,257,257,258,115,258,258,257,115,115,
-259,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-259,259,257,257,115,115,260,260,260,260,260,260,260,260,260,260,
-261,262,115,115,115,115,115,115,115,259,257,257,257,257,257,257,
+116,260,260,261,116,262,262,262,262,262,262,262,262,262,116,262,
+262,262,116,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,116,262,262,262,262,262,262,
+262,116,262,262,116,262,262,262,262,262,116,116,260,262,261,261,
+261,260,260,260,260,260,116,260,260,261,116,261,261,260,116,116,
+262,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+262,262,260,260,116,116,263,263,263,263,263,263,263,263,263,263,
+264,265,116,116,116,116,116,116,116,262,260,260,260,260,260,260,
/* block 22 */
-115,263,264,264,115,265,265,265,265,265,265,265,265,115,115,265,
-265,115,115,265,265,265,265,265,265,265,265,265,265,265,265,265,
-265,265,265,265,265,265,265,265,265,115,265,265,265,265,265,265,
-265,115,265,265,115,265,265,265,265,265,115,115,263,265,266,263,
-264,263,263,263,263,115,115,264,264,115,115,264,264,263,115,115,
-115,115,115,115,115,115,263,266,115,115,115,115,265,265,115,265,
-265,265,263,263,115,115,267,267,267,267,267,267,267,267,267,267,
-268,265,269,269,269,269,269,269,115,115,115,115,115,115,115,115,
+116,266,267,267,116,268,268,268,268,268,268,268,268,116,116,268,
+268,116,116,268,268,268,268,268,268,268,268,268,268,268,268,268,
+268,268,268,268,268,268,268,268,268,116,268,268,268,268,268,268,
+268,116,268,268,116,268,268,268,268,268,116,116,266,268,269,266,
+267,266,266,266,266,116,116,267,267,116,116,267,267,266,116,116,
+116,116,116,116,116,116,266,269,116,116,116,116,268,268,116,268,
+268,268,266,266,116,116,270,270,270,270,270,270,270,270,270,270,
+271,268,272,272,272,272,272,272,116,116,116,116,116,116,116,116,
/* block 23 */
-115,115,270,271,115,271,271,271,271,271,271,115,115,115,271,271,
-271,115,271,271,271,271,115,115,115,271,271,115,271,115,271,271,
-115,115,115,271,271,115,115,115,271,271,271,115,115,115,271,271,
-271,271,271,271,271,271,271,271,271,271,115,115,115,115,272,273,
-270,273,273,115,115,115,273,273,273,115,273,273,273,270,115,115,
-271,115,115,115,115,115,115,272,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,274,274,274,274,274,274,274,274,274,274,
-275,275,275,276,276,276,276,276,276,277,276,115,115,115,115,115,
+116,116,273,274,116,274,274,274,274,274,274,116,116,116,274,274,
+274,116,274,274,274,274,116,116,116,274,274,116,274,116,274,274,
+116,116,116,274,274,116,116,116,274,274,274,116,116,116,274,274,
+274,274,274,274,274,274,274,274,274,274,116,116,116,116,275,276,
+273,276,276,116,116,116,276,276,276,116,276,276,276,273,116,116,
+274,116,116,116,116,116,116,275,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,277,277,277,277,277,277,277,277,277,277,
+278,278,278,279,279,279,279,279,279,280,279,116,116,116,116,116,
/* block 24 */
-278,279,279,279,115,280,280,280,280,280,280,280,280,115,280,280,
-280,115,280,280,280,280,280,280,280,280,280,280,280,280,280,280,
-280,280,280,280,280,280,280,280,280,115,280,280,280,280,280,280,
-280,280,280,280,280,280,280,280,280,280,115,115,115,280,278,278,
-278,279,279,279,279,115,278,278,278,115,278,278,278,278,115,115,
-115,115,115,115,115,278,278,115,280,280,280,115,115,115,115,115,
-280,280,278,278,115,115,281,281,281,281,281,281,281,281,281,281,
-115,115,115,115,115,115,115,115,282,282,282,282,282,282,282,283,
+281,282,282,282,281,283,283,283,283,283,283,283,283,116,283,283,
+283,116,283,283,283,283,283,283,283,283,283,283,283,283,283,283,
+283,283,283,283,283,283,283,283,283,116,283,283,283,283,283,283,
+283,283,283,283,283,283,283,283,283,283,116,116,116,283,281,281,
+281,282,282,282,282,116,281,281,281,116,281,281,281,281,116,116,
+116,116,116,116,116,281,281,116,283,283,283,116,116,116,116,116,
+283,283,281,281,116,116,284,284,284,284,284,284,284,284,284,284,
+116,116,116,116,116,116,116,116,285,285,285,285,285,285,285,286,
/* block 25 */
-284,285,286,286,115,284,284,284,284,284,284,284,284,115,284,284,
-284,115,284,284,284,284,284,284,284,284,284,284,284,284,284,284,
-284,284,284,284,284,284,284,284,284,115,284,284,284,284,284,284,
-284,284,284,284,115,284,284,284,284,284,115,115,285,284,286,285,
-286,286,287,286,286,115,285,286,286,115,286,286,285,285,115,115,
-115,115,115,115,115,287,287,115,115,115,115,115,115,115,284,115,
-284,284,285,285,115,115,288,288,288,288,288,288,288,288,288,288,
-115,284,284,115,115,115,115,115,115,115,115,115,115,115,115,115,
+287,288,289,289,290,287,287,287,287,287,287,287,287,116,287,287,
+287,116,287,287,287,287,287,287,287,287,287,287,287,287,287,287,
+287,287,287,287,287,287,287,287,287,116,287,287,287,287,287,287,
+287,287,287,287,116,287,287,287,287,287,116,116,288,287,289,288,
+289,289,291,289,289,116,288,289,289,116,289,289,288,288,116,116,
+116,116,116,116,116,291,291,116,116,116,116,116,116,116,287,116,
+287,287,288,288,116,116,292,292,292,292,292,292,292,292,292,292,
+116,287,287,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 26 */
-289,289,290,290,115,291,291,291,291,291,291,291,291,115,291,291,
-291,115,291,291,291,291,291,291,291,291,291,291,291,291,291,291,
-291,291,291,291,291,291,291,291,291,291,291,291,291,291,291,291,
-291,291,291,291,291,291,291,291,291,291,291,289,289,291,292,290,
-290,289,289,289,289,115,290,290,290,115,290,290,290,289,293,294,
-115,115,115,115,291,291,291,292,295,295,295,295,295,295,295,291,
-291,291,289,289,115,115,296,296,296,296,296,296,296,296,296,296,
-295,295,295,295,295,295,295,295,295,294,291,291,291,291,291,291,
+293,293,294,294,116,295,295,295,295,295,295,295,295,116,295,295,
+295,116,295,295,295,295,295,295,295,295,295,295,295,295,295,295,
+295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,
+295,295,295,295,295,295,295,295,295,295,295,293,293,295,296,294,
+294,293,293,293,293,116,294,294,294,116,294,294,294,293,297,298,
+116,116,116,116,295,295,295,296,299,299,299,299,299,299,299,295,
+295,295,293,293,116,116,300,300,300,300,300,300,300,300,300,300,
+299,299,299,299,299,299,299,299,299,298,295,295,295,295,295,295,
/* block 27 */
-115,115,297,297,115,298,298,298,298,298,298,298,298,298,298,298,
-298,298,298,298,298,298,298,115,115,115,298,298,298,298,298,298,
-298,298,298,298,298,298,298,298,298,298,298,298,298,298,298,298,
-298,298,115,298,298,298,298,298,298,298,298,298,115,298,115,115,
-298,298,298,298,298,298,298,115,115,115,299,115,115,115,115,300,
-297,297,299,299,299,115,299,115,297,297,297,297,297,297,297,300,
-115,115,115,115,115,115,301,301,301,301,301,301,301,301,301,301,
-115,115,297,297,302,115,115,115,115,115,115,115,115,115,115,115,
+116,116,301,301,116,302,302,302,302,302,302,302,302,302,302,302,
+302,302,302,302,302,302,302,116,116,116,302,302,302,302,302,302,
+302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,
+302,302,116,302,302,302,302,302,302,302,302,302,116,302,116,116,
+302,302,302,302,302,302,302,116,116,116,303,116,116,116,116,304,
+301,301,303,303,303,116,303,116,301,301,301,301,301,301,301,304,
+116,116,116,116,116,116,305,305,305,305,305,305,305,305,305,305,
+116,116,301,301,306,116,116,116,116,116,116,116,116,116,116,116,
/* block 28 */
-115,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,
-303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,
-303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,
-303,304,303,305,304,304,304,304,304,304,304,115,115,115,115, 5,
-303,303,303,303,303,303,306,304,304,304,304,304,304,304,304,307,
-308,308,308,308,308,308,308,308,308,308,307,307,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+116,307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,
+307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,
+307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,
+307,308,307,309,308,308,308,308,308,308,308,116,116,116,116, 5,
+307,307,307,307,307,307,310,308,308,308,308,308,308,308,308,311,
+312,312,312,312,312,312,312,312,312,312,311,311,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 29 */
-115,309,309,115,309,115,115,309,309,115,309,115,115,309,115,115,
-115,115,115,115,309,309,309,309,115,309,309,309,309,309,309,309,
-115,309,309,309,115,309,115,309,115,115,309,309,115,309,309,309,
-309,310,309,311,310,310,310,310,310,310,115,310,310,309,115,115,
-309,309,309,309,309,115,312,115,310,310,310,310,310,310,115,115,
-313,313,313,313,313,313,313,313,313,313,115,115,309,309,309,309,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+116,313,313,116,313,116,116,313,313,116,313,116,116,313,116,116,
+116,116,116,116,313,313,313,313,116,313,313,313,313,313,313,313,
+116,313,313,313,116,313,116,313,116,116,313,313,116,313,313,313,
+313,314,313,315,314,314,314,314,314,314,116,314,314,313,116,116,
+313,313,313,313,313,116,316,116,314,314,314,314,314,314,116,116,
+317,317,317,317,317,317,317,317,317,317,116,116,313,313,313,313,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 30 */
-314,315,315,315,316,316,316,316,316,316,316,316,316,316,316,316,
-316,316,316,315,316,315,315,315,317,317,315,315,315,315,315,315,
-318,318,318,318,318,318,318,318,318,318,319,319,319,319,319,319,
-319,319,319,319,315,317,315,317,315,317,320,321,320,321,322,322,
-314,314,314,314,314,314,314,314,115,314,314,314,314,314,314,314,
-314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
-314,314,314,314,314,314,314,314,314,314,314,314,314,115,115,115,
-115,317,317,317,317,317,317,317,317,317,317,317,317,317,317,322,
+318,319,319,319,320,320,320,320,320,320,320,320,320,320,320,320,
+320,320,320,319,320,319,319,319,321,321,319,319,319,319,319,319,
+322,322,322,322,322,322,322,322,322,322,323,323,323,323,323,323,
+323,323,323,323,319,321,319,321,319,321,324,325,324,325,326,326,
+318,318,318,318,318,318,318,318,116,318,318,318,318,318,318,318,
+318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,
+318,318,318,318,318,318,318,318,318,318,318,318,318,116,116,116,
+116,321,321,321,321,321,321,321,321,321,321,321,321,321,321,326,
/* block 31 */
-317,317,317,317,317,316,317,317,314,314,314,314,314,317,317,317,
-317,317,317,317,317,317,317,317,115,317,317,317,317,317,317,317,
-317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,
-317,317,317,317,317,317,317,317,317,317,317,317,317,115,315,315,
-315,315,315,315,315,315,317,315,315,315,315,315,315,115,315,315,
-316,316,316,316,316, 19, 19, 19, 19,316,316,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+321,321,321,321,321,320,321,321,318,318,318,318,318,321,321,321,
+321,321,321,321,321,321,321,321,116,321,321,321,321,321,321,321,
+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,
+321,321,321,321,321,321,321,321,321,321,321,321,321,116,319,319,
+319,319,319,319,319,319,321,319,319,319,319,319,319,116,319,319,
+320,320,320,320,320, 19, 19, 19, 19,320,320,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 32 */
-323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,
-323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,
-323,323,323,323,323,323,323,323,323,323,323,324,324,325,325,325,
-325,326,325,325,325,325,325,325,324,325,325,326,326,325,325,323,
-327,327,327,327,327,327,327,327,327,327,328,328,328,328,328,328,
-323,323,323,323,323,323,326,326,325,325,323,323,323,323,325,325,
-325,323,324,324,324,323,323,324,324,324,324,324,324,324,323,323,
-323,325,325,325,325,323,323,323,323,323,323,323,323,323,323,323,
+327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,
+327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,
+327,327,327,327,327,327,327,327,327,327,327,328,328,329,329,329,
+329,330,329,329,329,329,329,329,328,329,329,330,330,329,329,327,
+331,331,331,331,331,331,331,331,331,331,332,332,332,332,332,332,
+327,327,327,327,327,327,330,330,329,329,327,327,327,327,329,329,
+329,327,328,328,328,327,327,328,328,328,328,328,328,328,327,327,
+327,329,329,329,329,327,327,327,327,327,327,327,327,327,327,327,
/* block 33 */
-323,323,325,324,326,325,325,324,324,324,324,324,324,325,323,324,
-327,327,327,327,327,327,327,327,327,327,324,324,324,325,329,329,
-330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,
-330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,
-330,330,330,330,330,330,115,330,115,115,115,115,115,330,115,115,
-331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,
-331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,
-331,331,331,331,331,331,331,331,331,331,331, 4,332,331,331,331,
-
-/* block 34 */
-333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,
-333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,
-333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,
-333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,
-333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,
-333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,
-334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,
+327,327,329,328,330,329,329,328,328,328,328,328,328,329,327,328,
+331,331,331,331,331,331,331,331,331,331,328,328,328,329,333,333,
334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,
-
-/* block 35 */
334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,
-334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,
-334,334,334,334,334,334,334,334,335,335,335,335,335,335,335,335,
-335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,
-335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,
-335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,
+334,334,334,334,334,334,116,334,116,116,116,116,116,334,116,116,
335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,
335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,
+335,335,335,335,335,335,335,335,335,335,335, 4,336,335,335,335,
+
+/* block 34 */
+337,337,337,337,337,337,337,337,337,337,337,337,337,337,337,337,
+337,337,337,337,337,337,337,337,337,337,337,337,337,337,337,337,
+337,337,337,337,337,337,337,337,337,337,337,337,337,337,337,337,
+337,337,337,337,337,337,337,337,337,337,337,337,337,337,337,337,
+337,337,337,337,337,337,337,337,337,337,337,337,337,337,337,337,
+337,337,337,337,337,337,337,337,337,337,337,337,337,337,337,337,
+338,338,338,338,338,338,338,338,338,338,338,338,338,338,338,338,
+338,338,338,338,338,338,338,338,338,338,338,338,338,338,338,338,
+
+/* block 35 */
+338,338,338,338,338,338,338,338,338,338,338,338,338,338,338,338,
+338,338,338,338,338,338,338,338,338,338,338,338,338,338,338,338,
+338,338,338,338,338,338,338,338,339,339,339,339,339,339,339,339,
+339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,
+339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,
+339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,
+339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,
+339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,
/* block 36 */
-336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,
-336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,
-336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,
-336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,
-336,336,336,336,336,336,336,336,336,115,336,336,336,336,115,115,
-336,336,336,336,336,336,336,115,336,115,336,336,336,336,115,115,
-336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,
-336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,
+340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,
+340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,
+340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,
+340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,
+340,340,340,340,340,340,340,340,340,116,340,340,340,340,116,116,
+340,340,340,340,340,340,340,116,340,116,340,340,340,340,116,116,
+340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,
+340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,
/* block 37 */
-336,336,336,336,336,336,336,336,336,115,336,336,336,336,115,115,
-336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,
-336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,
-336,115,336,336,336,336,115,115,336,336,336,336,336,336,336,115,
-336,115,336,336,336,336,115,115,336,336,336,336,336,336,336,336,
-336,336,336,336,336,336,336,115,336,336,336,336,336,336,336,336,
-336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,
-336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,
+340,340,340,340,340,340,340,340,340,116,340,340,340,340,116,116,
+340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,
+340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,
+340,116,340,340,340,340,116,116,340,340,340,340,340,340,340,116,
+340,116,340,340,340,340,116,116,340,340,340,340,340,340,340,340,
+340,340,340,340,340,340,340,116,340,340,340,340,340,340,340,340,
+340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,
+340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,
/* block 38 */
-336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,
-336,115,336,336,336,336,115,115,336,336,336,336,336,336,336,336,
-336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,
-336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,
-336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,
-336,336,336,336,336,336,336,336,336,336,336,115,115,337,337,337,
-338,338,338,338,338,338,338,338,338,339,339,339,339,339,339,339,
-339,339,339,339,339,339,339,339,339,339,339,339,339,115,115,115,
+340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,
+340,116,340,340,340,340,116,116,340,340,340,340,340,340,340,340,
+340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,
+340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,
+340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,
+340,340,340,340,340,340,340,340,340,340,340,116,116,341,341,341,
+342,342,342,342,342,342,342,342,342,343,343,343,343,343,343,343,
+343,343,343,343,343,343,343,343,343,343,343,343,343,116,116,116,
/* block 39 */
-336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,
-340,340,340,340,340,340,340,340,340,340,115,115,115,115,115,115,
-341,341,341,341,341,341,341,341,341,341,341,341,341,341,341,341,
-341,341,341,341,341,341,341,341,341,341,341,341,341,341,341,341,
-341,341,341,341,341,341,341,341,341,341,341,341,341,341,341,341,
-341,341,341,341,341,341,341,341,341,341,341,341,341,341,341,341,
-341,341,341,341,341,341,341,341,341,341,341,341,341,341,341,341,
-342,342,342,342,342,342,115,115,343,343,343,343,343,343,115,115,
-
-/* block 40 */
-344,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,
-345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,
-345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,
+340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,
+344,344,344,344,344,344,344,344,344,344,116,116,116,116,116,116,
345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,
345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,
345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,
345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,
345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,
+346,346,346,346,346,346,116,116,347,347,347,347,347,347,116,116,
+
+/* block 40 */
+348,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,
+349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,
+349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,
+349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,
+349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,
+349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,
+349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,
+349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,
/* block 41 */
-345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,
-345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,
-345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,
-345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,
-345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,
-345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,
-345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,
-345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,
+349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,
+349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,
+349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,
+349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,
+349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,
+349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,
+349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,
+349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,
/* block 42 */
-345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,
-345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,
-345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,
-345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,
-345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,
-345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,
-345,345,345,345,345,345,345,345,345,345,345,345,345,346,346,345,
-345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,
+349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,
+349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,
+349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,
+349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,
+349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,
+349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,
+349,349,349,349,349,349,349,349,349,349,349,349,349,350,350,349,
+349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,
/* block 43 */
-347,348,348,348,348,348,348,348,348,348,348,348,348,348,348,348,
-348,348,348,348,348,348,348,348,348,348,348,349,350,115,115,115,
-351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,
-351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,
-351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,
-351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,
-351,351,351,351,351,351,351,351,351,351,351, 4, 4, 4,352,352,
-352,351,351,351,351,351,351,351,351,115,115,115,115,115,115,115,
+351,352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,
+352,352,352,352,352,352,352,352,352,352,352,353,354,116,116,116,
+355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,
+355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,
+355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,
+355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,
+355,355,355,355,355,355,355,355,355,355,355, 4, 4, 4,356,356,
+356,355,355,355,355,355,355,355,355,116,116,116,116,116,116,116,
/* block 44 */
-353,353,353,353,353,353,353,353,353,353,353,353,353,115,353,353,
-353,353,354,354,354,115,115,115,115,115,115,115,115,115,115,115,
-355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,
-355,355,356,356,356, 4, 4,115,115,115,115,115,115,115,115,115,
-357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,
-357,357,358,358,115,115,115,115,115,115,115,115,115,115,115,115,
-359,359,359,359,359,359,359,359,359,359,359,359,359,115,359,359,
-359,115,360,360,115,115,115,115,115,115,115,115,115,115,115,115,
+357,357,357,357,357,357,357,357,357,357,357,357,357,116,357,357,
+357,357,358,358,358,116,116,116,116,116,116,116,116,116,116,116,
+359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,
+359,359,360,360,360, 4, 4,116,116,116,116,116,116,116,116,116,
+361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,
+361,361,362,362,116,116,116,116,116,116,116,116,116,116,116,116,
+363,363,363,363,363,363,363,363,363,363,363,363,363,116,363,363,
+363,116,364,364,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 45 */
-361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,
-361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,
-361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,
-361,361,361,361,362,362,363,362,362,362,362,362,362,362,363,363,
-363,363,363,363,363,363,362,363,363,362,362,362,362,362,362,362,
-362,362,362,362,364,364,364,365,364,364,364,366,361,362,115,115,
-367,367,367,367,367,367,367,367,367,367,115,115,115,115,115,115,
-368,368,368,368,368,368,368,368,368,368,115,115,115,115,115,115,
+365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,
+365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,
+365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,
+365,365,365,365,366,366,367,366,366,366,366,366,366,366,367,367,
+367,367,367,367,367,367,366,367,367,366,366,366,366,366,366,366,
+366,366,366,366,368,368,368,369,368,368,368,370,365,366,116,116,
+371,371,371,371,371,371,371,371,371,371,116,116,116,116,116,116,
+372,372,372,372,372,372,372,372,372,372,116,116,116,116,116,116,
/* block 46 */
-369,369, 4, 4,369, 4,370,369,369,369,369,371,371,371,372,115,
-373,373,373,373,373,373,373,373,373,373,115,115,115,115,115,115,
-374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,
-374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,
-374,374,374,375,374,374,374,374,374,374,374,374,374,374,374,374,
-374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,
-374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,
-374,374,374,374,374,374,374,374,115,115,115,115,115,115,115,115,
+373,373, 4, 4,373, 4,374,373,373,373,373,375,375,375,376,116,
+377,377,377,377,377,377,377,377,377,377,116,116,116,116,116,116,
+378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,
+378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,
+378,378,378,379,378,378,378,378,378,378,378,378,378,378,378,378,
+378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,
+378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,
+378,378,378,378,378,378,378,378,378,116,116,116,116,116,116,116,
/* block 47 */
-374,374,374,374,374,371,371,374,374,374,374,374,374,374,374,374,
-374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,
-374,374,374,374,374,374,374,374,374,371,374,115,115,115,115,115,
-345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,
-345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,
-345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,
-345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,
-345,345,345,345,345,345,115,115,115,115,115,115,115,115,115,115,
+378,378,378,378,378,375,375,378,378,378,378,378,378,378,378,378,
+378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,
+378,378,378,378,378,378,378,378,378,375,378,116,116,116,116,116,
+349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,
+349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,
+349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,
+349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,
+349,349,349,349,349,349,116,116,116,116,116,116,116,116,116,116,
/* block 48 */
-376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,
-376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,115,
-377,377,377,378,378,378,378,377,377,378,378,378,115,115,115,115,
-378,378,377,378,378,378,378,378,378,377,377,377,115,115,115,115,
-379,115,115,115,380,380,381,381,381,381,381,381,381,381,381,381,
-382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,
-382,382,382,382,382,382,382,382,382,382,382,382,382,382,115,115,
-382,382,382,382,382,115,115,115,115,115,115,115,115,115,115,115,
+380,380,380,380,380,380,380,380,380,380,380,380,380,380,380,380,
+380,380,380,380,380,380,380,380,380,380,380,380,380,380,380,116,
+381,381,381,382,382,382,382,381,381,382,382,382,116,116,116,116,
+382,382,381,382,382,382,382,382,382,381,381,381,116,116,116,116,
+383,116,116,116,384,384,385,385,385,385,385,385,385,385,385,385,
+386,386,386,386,386,386,386,386,386,386,386,386,386,386,386,386,
+386,386,386,386,386,386,386,386,386,386,386,386,386,386,116,116,
+386,386,386,386,386,116,116,116,116,116,116,116,116,116,116,116,
/* block 49 */
-383,383,383,383,383,383,383,383,383,383,383,383,383,383,383,383,
-383,383,383,383,383,383,383,383,383,383,383,383,383,383,383,383,
-383,383,383,383,383,383,383,383,383,383,383,383,115,115,115,115,
-383,383,383,383,383,383,383,383,383,383,383,383,383,383,383,383,
-383,383,383,383,383,383,383,383,383,383,115,115,115,115,115,115,
-384,384,384,384,384,384,384,384,384,384,385,115,115,115,386,386,
387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,
387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,
+387,387,387,387,387,387,387,387,387,387,387,387,116,116,116,116,
+387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,
+387,387,387,387,387,387,387,387,387,387,116,116,116,116,116,116,
+388,388,388,388,388,388,388,388,388,388,389,116,116,116,390,390,
+391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,
+391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,
/* block 50 */
-388,388,388,388,388,388,388,388,388,388,388,388,388,388,388,388,
-388,388,388,388,388,388,388,389,389,390,390,389,115,115,391,391,
392,392,392,392,392,392,392,392,392,392,392,392,392,392,392,392,
-392,392,392,392,392,392,392,392,392,392,392,392,392,392,392,392,
-392,392,392,392,392,392,392,392,392,392,392,392,392,392,392,392,
-392,392,392,392,392,393,394,393,394,394,394,394,394,394,394,115,
-394,395,394,395,395,394,394,394,394,394,394,394,394,393,393,393,
-393,393,393,394,394,394,394,394,394,394,394,394,394,115,115,394,
+392,392,392,392,392,392,392,393,393,394,394,393,116,116,395,395,
+396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,
+396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,
+396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,
+396,396,396,396,396,397,398,397,398,398,398,398,398,398,398,116,
+398,399,398,399,399,398,398,398,398,398,398,398,398,397,397,397,
+397,397,397,398,398,398,398,398,398,398,398,398,398,116,116,398,
/* block 51 */
-396,396,396,396,396,396,396,396,396,396,115,115,115,115,115,115,
-396,396,396,396,396,396,396,396,396,396,115,115,115,115,115,115,
-397,397,397,397,397,397,397,398,397,397,397,397,397,397,115,115,
-110,110,110,110,110,110,110,110,110,110,110,110,110,110,399,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+400,400,400,400,400,400,400,400,400,400,116,116,116,116,116,116,
+400,400,400,400,400,400,400,400,400,400,116,116,116,116,116,116,
+401,401,401,401,401,401,401,402,401,401,401,401,401,401,116,116,
+111,111,111,111,111,111,111,111,111,111,111,111,111,111,403,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 52 */
-400,400,400,400,401,402,402,402,402,402,402,402,402,402,402,402,
-402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,
-402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,
-402,402,402,402,400,401,400,400,400,400,400,401,400,401,401,401,
-401,401,400,401,401,402,402,402,402,402,402,402,115,115,115,115,
-403,403,403,403,403,403,403,403,403,403,404,404,404,404,404,404,
-404,405,405,405,405,405,405,405,405,405,405,400,400,400,400,400,
-400,400,400,400,405,405,405,405,405,405,405,405,405,115,115,115,
+404,404,404,404,405,406,406,406,406,406,406,406,406,406,406,406,
+406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,
+406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,
+406,406,406,406,404,405,404,404,404,404,404,405,404,405,405,405,
+405,405,404,405,405,406,406,406,406,406,406,406,116,116,116,116,
+407,407,407,407,407,407,407,407,407,407,408,408,408,408,408,408,
+408,409,409,409,409,409,409,409,409,409,409,404,404,404,404,404,
+404,404,404,404,409,409,409,409,409,409,409,409,409,116,116,116,
/* block 53 */
-406,406,407,408,408,408,408,408,408,408,408,408,408,408,408,408,
-408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,
-408,407,406,406,406,406,407,407,406,406,407,406,406,406,408,408,
-409,409,409,409,409,409,409,409,409,409,408,408,408,408,408,408,
-410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,
-410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,
-410,410,410,410,410,410,411,412,411,411,412,412,412,411,412,411,
-411,411,412,412,115,115,115,115,115,115,115,115,413,413,413,413,
-
-/* block 54 */
+410,410,411,412,412,412,412,412,412,412,412,412,412,412,412,412,
+412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,
+412,411,410,410,410,410,411,411,410,410,411,410,410,410,412,412,
+413,413,413,413,413,413,413,413,413,413,412,412,412,412,412,412,
414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,
414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,
-414,414,414,414,415,415,415,415,415,415,415,415,416,416,416,416,
-416,416,416,416,415,415,416,416,115,115,115,417,417,417,417,417,
-418,418,418,418,418,418,418,418,418,418,115,115,115,414,414,414,
-419,419,419,419,419,419,419,419,419,419,420,420,420,420,420,420,
-420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,
-420,420,420,420,420,420,420,420,421,421,421,421,421,421,422,422,
+414,414,414,414,414,414,415,416,415,415,416,416,416,415,416,415,
+415,415,416,416,116,116,116,116,116,116,116,116,417,417,417,417,
+
+/* block 54 */
+418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,
+418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,
+418,418,418,418,419,419,419,419,419,419,419,419,420,420,420,420,
+420,420,420,420,419,419,420,420,116,116,116,421,421,421,421,421,
+422,422,422,422,422,422,422,422,422,422,116,116,116,418,418,418,
+423,423,423,423,423,423,423,423,423,423,424,424,424,424,424,424,
+424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,
+424,424,424,424,424,424,424,424,425,425,425,425,425,425,426,426,
/* block 55 */
-423,424,425,426,427,428,429,430,431,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-432,432,432,432,432,432,432,432,115,115,115,115,115,115,115,115,
-110,110,110, 4,110,110,110,110,110,110,110,110,110,110,110,110,
-110,433,110,110,110,110,110,110,110,434,434,434,434,110,434,434,
-434,434,433,433,110,434,434,433,110,110,115,115,115,115,115,115,
+427,428,429,430,431,432,433,434,435,116,116,116,116,116,116,116,
+436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,
+436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,
+436,436,436,436,436,436,436,436,436,436,436,116,116,436,436,436,
+437,437,437,437,437,437,437,437,116,116,116,116,116,116,116,116,
+111,111,111, 4,111,111,111,111,111,111,111,111,111,111,111,111,
+111,438,111,111,111,111,111,111,111,439,439,439,439,111,439,439,
+439,439,438,438,111,439,439,438,111,111,116,116,116,116,116,116,
/* block 56 */
- 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
- 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
- 33, 33, 33, 33, 33, 33,123,123,123,123,123,435,107,107,107,107,
-107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,
-107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,
-107,107,107,107,107,107,107,107,107,107,107,107,107,116,116,116,
-116,116,107,107,107,107,116,116,116,116,116, 33, 33, 33, 33, 33,
- 33, 33, 33, 33, 33, 33, 33, 33,436,437, 33, 33, 33,438, 33, 33,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+ 34, 34, 34, 34, 34, 34,124,124,124,124,124,440,108,108,108,108,
+108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,
+108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,
+108,108,108,108,108,108,108,108,108,108,108,108,108,117,117,117,
+117,117,108,108,108,108,117,117,117,117,117, 34, 34, 34, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34,441,442, 34, 34, 34,443, 34, 34,
/* block 57 */
- 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
- 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,107,107,107,107,107,
-107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,
-107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,116,
-110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
-110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
-110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
-110,110,110,110,110,110,110,110,110,110,115,110,110,110,110,110,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,108,108,108,108,108,
+108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,
+108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,117,
+111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
+111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
+111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
+111,111,111,111,111,111,111,111,111,111,116,111,111,111,111,111,
/* block 58 */
- 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
- 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
- 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
- 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
- 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
- 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
-439,440, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
- 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
+ 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32,
+ 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32,
+ 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32,
+ 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32,
+ 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32,
+ 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32,
+444,445, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32,
+ 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32,
/* block 59 */
- 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
- 30, 31, 30, 31, 30, 31, 33, 33, 33, 33, 33,441, 33, 33,442, 33,
- 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
- 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
- 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
- 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
- 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
- 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
+ 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32,
+ 31, 32, 31, 32, 31, 32, 34, 34, 34, 34, 34,446, 34, 34,447, 34,
+ 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32,
+ 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32,
+ 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32,
+ 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32,
+ 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32,
+ 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32,
/* block 60 */
-443,443,443,443,443,443,443,443,444,444,444,444,444,444,444,444,
-443,443,443,443,443,443,115,115,444,444,444,444,444,444,115,115,
-443,443,443,443,443,443,443,443,444,444,444,444,444,444,444,444,
-443,443,443,443,443,443,443,443,444,444,444,444,444,444,444,444,
-443,443,443,443,443,443,115,115,444,444,444,444,444,444,115,115,
-123,443,123,443,123,443,123,443,115,444,115,444,115,444,115,444,
-443,443,443,443,443,443,443,443,444,444,444,444,444,444,444,444,
-445,445,446,446,446,446,447,447,448,448,449,449,450,450,115,115,
+448,448,448,448,448,448,448,448,449,449,449,449,449,449,449,449,
+448,448,448,448,448,448,116,116,449,449,449,449,449,449,116,116,
+448,448,448,448,448,448,448,448,449,449,449,449,449,449,449,449,
+448,448,448,448,448,448,448,448,449,449,449,449,449,449,449,449,
+448,448,448,448,448,448,116,116,449,449,449,449,449,449,116,116,
+124,448,124,448,124,448,124,448,116,449,116,449,116,449,116,449,
+448,448,448,448,448,448,448,448,449,449,449,449,449,449,449,449,
+450,450,451,451,451,451,452,452,453,453,454,454,455,455,116,116,
/* block 61 */
-443,443,443,443,443,443,443,443,451,451,451,451,451,451,451,451,
-443,443,443,443,443,443,443,443,451,451,451,451,451,451,451,451,
-443,443,443,443,443,443,443,443,451,451,451,451,451,451,451,451,
-443,443,123,452,123,115,123,123,444,444,453,453,454,114,455,114,
-114,114,123,452,123,115,123,123,456,456,456,456,454,114,114,114,
-443,443,123,123,115,115,123,123,444,444,457,457,115,114,114,114,
-443,443,123,123,123,164,123,123,444,444,458,458,169,114,114,114,
-115,115,123,452,123,115,123,123,459,459,460,460,454,114,114,115,
+448,448,448,448,448,448,448,448,456,456,456,456,456,456,456,456,
+448,448,448,448,448,448,448,448,456,456,456,456,456,456,456,456,
+448,448,448,448,448,448,448,448,456,456,456,456,456,456,456,456,
+448,448,124,457,124,116,124,124,449,449,458,458,459,115,460,115,
+115,115,124,457,124,116,124,124,461,461,461,461,459,115,115,115,
+448,448,124,124,116,116,124,124,449,449,462,462,116,115,115,115,
+448,448,124,124,124,165,124,124,449,449,463,463,170,115,115,115,
+116,116,124,457,124,116,124,124,464,464,465,465,459,115,115,116,
/* block 62 */
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 22,461,462, 22, 22,
- 9, 9, 9, 9, 9, 9, 4, 4, 21, 25, 6, 21, 21, 25, 6, 21,
- 4, 4, 4, 4, 4, 4, 4, 4,463,464, 22, 22, 22, 22, 22, 3,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 21, 25, 4, 4, 4, 4, 15,
- 15, 4, 4, 4, 8, 6, 7, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 23,466,467, 23, 23,
+ 9, 9, 9, 9, 9, 9, 4, 4, 22, 26, 6, 22, 22, 26, 6, 22,
+ 4, 4, 4, 4, 4, 4, 4, 4,468,469, 23, 23, 23, 23, 23, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 22, 26, 4,470, 4, 4, 15,
+ 15, 4, 4, 4, 8, 6, 7, 4, 4,470, 4, 4, 4, 4, 4, 4,
4, 4, 8, 4, 15, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3,
- 22, 22, 22, 22, 22,465, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
- 23,107,115,115, 23, 23, 23, 23, 23, 23, 8, 8, 8, 6, 7,107,
+ 23, 23, 23, 23, 23,471, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+ 24,108,116,116, 24, 24, 24, 24, 24, 24, 8, 8, 8, 6, 7,108,
/* block 63 */
- 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 8, 8, 8, 6, 7,115,
-107,107,107,107,107,107,107,107,107,107,107,107,107,115,115,115,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 8, 8, 8, 6, 7,116,
+108,108,108,108,108,108,108,108,108,108,108,108,108,116,116,116,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-110,110,110,110,110,110,110,110,110,110,110,110,110,399,399,399,
-399,110,399,399,399,110,110,110,110,110,110,110,110,110,110,110,
-110,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+111,111,111,111,111,111,111,111,111,111,111,111,111,403,403,403,
+403,111,403,403,403,111,111,111,111,111,111,111,111,111,111,111,
+111,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 64 */
- 19, 19,466, 19, 19, 19, 19,466, 19, 19,467,466,466,466,467,467,
-466,466,466,467, 19,466, 19, 19, 8,466,466,466,466,466, 19, 19,
- 19, 19, 19, 19,466, 19,468, 19,466, 19,469,470,466,466, 19,467,
-466,466,471,466,467,434,434,434,434,467, 19, 19,467,467,466,466,
- 8, 8, 8, 8, 8,466,467,467,467,467, 19, 8, 19, 19,472, 19,
- 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
-473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,
-474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,
+ 19, 19,472, 19, 19, 19, 19,472, 19, 19,473,472,472,472,473,473,
+472,472,472,473, 19,472, 19, 19, 8,472,472,472,472,472, 19, 19,
+ 19, 19, 20, 19,472, 19,474, 19,472, 19,475,476,472,472, 19,473,
+472,472,477,472,473,439,439,439,439,478, 19, 19,473,473,472,472,
+ 8, 8, 8, 8, 8,472,473,473,473,473, 19, 8, 19, 19,479, 19,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,
+481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,
/* block 65 */
-475,475,475, 30, 31,475,475,475,475, 23, 19, 19,115,115,115,115,
- 8, 8, 8, 8, 8, 19, 19, 19, 19, 19, 8, 8, 19, 19, 19, 19,
- 8, 19, 19, 8, 19, 19, 8, 19, 19, 19, 19, 19, 19, 19, 8, 19,
+482,482,482, 31, 32,482,482,482,482, 24, 19, 19,116,116,116,116,
+ 8, 8, 8, 8,483, 20, 20, 20, 20, 20, 8, 8, 19, 19, 19, 19,
+ 8, 19, 19, 8, 19, 19, 8, 19, 19, 20, 20, 19, 19, 19, 8, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 8, 8,
19, 19, 8, 19, 8, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
@@ -2148,8 +2181,8 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 65536 bytes, block = 128 */
/* block 67 */
19, 19, 19, 19, 19, 19, 19, 19, 6, 7, 6, 7, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 8, 8, 19, 19, 19, 19, 19, 19, 19, 6, 7, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 19, 19, 19, 19,
+ 8, 8, 19, 19, 19, 19, 19, 19, 20, 6, 7, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
@@ -2157,34 +2190,34 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 65536 bytes, block = 128 */
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 8, 19, 19, 19,
/* block 68 */
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 20, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 8, 8, 8, 8,
- 8, 8, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 8, 8, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 19, 19, 19, 19, 20, 20, 20, 19, 19, 19, 19, 19,
/* block 69 */
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
- 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
- 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+ 19, 19, 19, 19, 19, 19, 19,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
/* block 70 */
- 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
- 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 19, 19, 19, 19,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19,476,476,476,476,476,476,476,476,476,476,
-476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,
-477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,
-477,477,477,477,477,477,477,477,477,477, 23, 23, 23, 23, 23, 23,
- 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+ 19, 19, 19, 19, 19, 19,484,484,484,484,484,484,484,484,484,484,
+484,484,485,484,484,484,484,484,484,484,484,484,484,484,484,484,
+486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,
+486,486,486,486,486,486,486,486,486,486, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
/* block 71 */
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
@@ -2199,64 +2232,74 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 65536 bytes, block = 128 */
/* block 72 */
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 20, 8, 19, 19, 19, 19, 19, 19, 19, 19,
+ 20, 8, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 8, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 8, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 8, 8, 8, 8, 8, 8, 8, 8,
+ 19, 19, 19, 19, 19, 19, 19, 19, 8, 8, 8,483,483,483,483, 8,
/* block 73 */
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,478, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
-479, 19,479, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 8,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 20, 20, 20, 20, 20, 20, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,483,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
/* block 74 */
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19,479,479, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19,478, 19, 19, 19, 19, 19, 19,
+ 20, 20, 20, 20, 20, 20, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
/* block 75 */
- 19, 19, 19, 19, 19, 19, 19, 19,479, 19,478,478,478,478, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19,479, 19, 19, 19, 6, 7, 6, 7, 6, 7, 6, 7,
- 6, 7, 6, 7, 6, 7, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+ 20, 20, 20, 20, 20, 20, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 19, 20, 19, 20, 19, 19, 19, 19, 19, 19, 20, 19, 19,
+ 19, 20, 19, 19, 19, 19, 19, 19, 20, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 20, 20, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 20, 19, 19, 20, 19, 19, 19, 19, 20, 19, 20, 19,
+ 19, 19, 19, 20, 20, 20, 19, 20, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 20, 20, 20, 20, 20, 6, 7, 6, 7, 6, 7, 6, 7,
+ 6, 7, 6, 7, 6, 7, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
/* block 76 */
- 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
- 23, 23, 23, 23, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 19, 20, 20, 20, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 20, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 20, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20,
8, 8, 8, 8, 8, 6, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
/* block 77 */
-480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,
-480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,
-480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,
-480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,
-480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,
-480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,
-480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,
-480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,
+487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,
+487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,
+487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,
+487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,
+487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,
+487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,
+487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,
+487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,
/* block 78 */
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8,483,483, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+
+/* block 79 */
8, 8, 8, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6,
7, 6, 7, 6, 7, 6, 7, 6, 7, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
@@ -2266,1775 +2309,1875 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 65536 bytes, block = 128 */
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 6, 7, 8, 8,
-/* block 79 */
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+/* block 80 */
+ 19, 19, 19, 19, 19, 20, 20, 20, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 19, 19, 8, 8, 8, 8, 8, 8, 19, 19, 19,
+ 20, 19, 19, 19, 19, 20, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19,115,115, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19,116,116, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
-/* block 80 */
+/* block 81 */
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19,115,115, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19,116,116, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19,115, 19, 19, 19, 19, 19, 19,
- 19, 19, 19,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115, 19, 19, 19, 19,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-
-/* block 81 */
-481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,
-481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,
-481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,115,
-482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,
-482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,
-482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,115,
- 30, 31,483,484,485,486,487, 30, 31, 30, 31, 30, 31,488,489,490,
-491, 33, 30, 31, 33, 30, 31, 33, 33, 33, 33, 33,107,107,492,492,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19,116, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,116,
/* block 82 */
-160,161,160,161,160,161,160,161,160,161,160,161,160,161,160,161,
-160,161,160,161,160,161,160,161,160,161,160,161,160,161,160,161,
-160,161,160,161,160,161,160,161,160,161,160,161,160,161,160,161,
-160,161,160,161,160,161,160,161,160,161,160,161,160,161,160,161,
-160,161,160,161,160,161,160,161,160,161,160,161,160,161,160,161,
-160,161,160,161,160,161,160,161,160,161,160,161,160,161,160,161,
-160,161,160,161,493,494,494,494,494,494,494,160,161,160,161,495,
-495,495,160,161,115,115,115,115,115,496,496,496,496,497,496,496,
+488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,
+488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,
+488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,116,
+489,489,489,489,489,489,489,489,489,489,489,489,489,489,489,489,
+489,489,489,489,489,489,489,489,489,489,489,489,489,489,489,489,
+489,489,489,489,489,489,489,489,489,489,489,489,489,489,489,116,
+ 31, 32,490,491,492,493,494, 31, 32, 31, 32, 31, 32,495,496,497,
+498, 34, 31, 32, 34, 31, 32, 34, 34, 34, 34, 34,108,108,499,499,
/* block 83 */
-498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,
-498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,
-498,498,498,498,498,498,115,498,115,115,115,115,115,498,115,115,
-499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,
-499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,
-499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,
-499,499,499,499,499,499,499,499,115,115,115,115,115,115,115,500,
-501,115,115,115,115,115,115,115,115,115,115,115,115,115,115,502,
+161,162,161,162,161,162,161,162,161,162,161,162,161,162,161,162,
+161,162,161,162,161,162,161,162,161,162,161,162,161,162,161,162,
+161,162,161,162,161,162,161,162,161,162,161,162,161,162,161,162,
+161,162,161,162,161,162,161,162,161,162,161,162,161,162,161,162,
+161,162,161,162,161,162,161,162,161,162,161,162,161,162,161,162,
+161,162,161,162,161,162,161,162,161,162,161,162,161,162,161,162,
+161,162,161,162,500,501,501,501,501,501,501,161,162,161,162,502,
+502,502,161,162,116,116,116,116,116,503,503,503,503,504,503,503,
/* block 84 */
-336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,
-336,336,336,336,336,336,336,115,115,115,115,115,115,115,115,115,
-336,336,336,336,336,336,336,115,336,336,336,336,336,336,336,115,
-336,336,336,336,336,336,336,115,336,336,336,336,336,336,336,115,
-336,336,336,336,336,336,336,115,336,336,336,336,336,336,336,115,
-336,336,336,336,336,336,336,115,336,336,336,336,336,336,336,115,
-192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
-192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
+505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,
+505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,
+505,505,505,505,505,505,116,505,116,116,116,116,116,505,116,116,
+506,506,506,506,506,506,506,506,506,506,506,506,506,506,506,506,
+506,506,506,506,506,506,506,506,506,506,506,506,506,506,506,506,
+506,506,506,506,506,506,506,506,506,506,506,506,506,506,506,506,
+506,506,506,506,506,506,506,506,116,116,116,116,116,116,116,507,
+508,116,116,116,116,116,116,116,116,116,116,116,116,116,116,509,
/* block 85 */
- 4, 4, 21, 25, 21, 25, 4, 4, 4, 21, 25, 4, 21, 25, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 9, 4, 4, 9, 4, 21, 25, 4, 4,
- 21, 25, 6, 7, 6, 7, 6, 7, 6, 7, 4, 4, 4, 4, 4,108,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 9, 9, 4, 4, 4, 4,
- 9, 4, 6, 4, 4, 4, 4, 4, 4, 4,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,
+340,340,340,340,340,340,340,116,116,116,116,116,116,116,116,116,
+340,340,340,340,340,340,340,116,340,340,340,340,340,340,340,116,
+340,340,340,340,340,340,340,116,340,340,340,340,340,340,340,116,
+340,340,340,340,340,340,340,116,340,340,340,340,340,340,340,116,
+340,340,340,340,340,340,340,116,340,340,340,340,340,340,340,116,
+193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
+193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
/* block 86 */
-503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,
-503,503,503,503,503,503,503,503,503,503,115,503,503,503,503,503,
-503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,
-503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,
-503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,
-503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,
-503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,
-503,503,503,503,115,115,115,115,115,115,115,115,115,115,115,115,
+ 4, 4, 22, 26, 22, 26, 4, 4, 4, 22, 26, 4, 22, 26, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 9, 4, 4, 9, 4, 22, 26, 4, 4,
+ 22, 26, 6, 7, 6, 7, 6, 7, 6, 7, 4, 4, 4, 4, 4,109,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 9, 9, 4, 4, 4, 4,
+ 9, 4, 6, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 87 */
-503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,
-503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,
-503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,
-503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,
-503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,
-503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,
-503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,
-503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,
+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,
+510,510,510,510,510,510,510,510,510,510,116,510,510,510,510,510,
+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,
+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,
+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,
+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,
+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,
+510,510,510,510,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 88 */
-503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,
-503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,
-503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,
-503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,
-503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,
-503,503,503,503,503,503,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,
+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,
+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,
+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,
+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,
+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,
+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,
+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,
+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,
/* block 89 */
- 3, 4, 4, 4, 19,504,434,505, 6, 7, 6, 7, 6, 7, 6, 7,
- 6, 7, 19, 19, 6, 7, 6, 7, 6, 7, 6, 7, 9, 6, 7, 7,
- 19,505,505,505,505,505,505,505,505,505,110,110,110,110,506,506,
- 9,108,108,108,108,108, 19, 19,505,505,505,504,434, 4, 19, 19,
-115,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,
-507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,
-507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,
-507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,
+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,
+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,
+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,
+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,
+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,
+510,510,510,510,510,510,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,116,116,116,116,
/* block 90 */
-507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,
-507,507,507,507,507,507,507,115,115,110,110, 14, 14,508,508,507,
- 9,509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,
-509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,
-509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,
-509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,
-509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,
-509,509,509,509,509,509,509,509,509,509,509, 4,108,510,510,509,
+ 3, 4, 4, 4, 19,511,439,512, 6, 7, 6, 7, 6, 7, 6, 7,
+ 6, 7, 19, 19, 6, 7, 6, 7, 6, 7, 6, 7, 9, 6, 7, 7,
+ 19,512,512,512,512,512,512,512,512,512,111,111,111,111,513,513,
+514,109,109,109,109,109, 19, 19,512,512,512,511,439,470, 19, 19,
+116,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
+515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
+515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
+515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
/* block 91 */
-115,115,115,115,115,511,511,511,511,511,511,511,511,511,511,511,
-511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,
-511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,115,
-115,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,
-512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,
-512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,
-512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,
-512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,
+515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
+515,515,515,515,515,515,515,116,116,111,111, 14, 14,516,516,515,
+ 9,517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,
+517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,
+517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,
+517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,
+517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,
+517,517,517,517,517,517,517,517,517,517,517, 4,109,518,518,517,
/* block 92 */
-512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,115,
- 19, 19, 23, 23, 23, 23, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
-511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,
-511,511,511,511,511,511,511,511,511,511,511,115,115,115,115,115,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19,115,115,115,115,115,115,115,115,115,115,115,115,
-509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,
+116,116,116,116,116,519,519,519,519,519,519,519,519,519,519,519,
+519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,
+519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,
+116,520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,
+520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,
+520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,
+520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,
+520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,
/* block 93 */
-513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,
-513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,115,
- 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 19, 19, 19, 19, 19, 19,
+520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,116,
+ 19, 19, 24, 24, 24, 24, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,
+519,519,519,519,519,519,519,519,519,519,519,116,116,116,116,116,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 23, 23, 23, 23, 23, 23, 23, 23,
- 19, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
-513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,
-513,513,513,513,513,513,513,513,513,513,513,513,513,513,513, 19,
+ 19, 19, 19, 19,116,116,116,116,116,116,116,116,116,116,116,116,
+517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,
/* block 94 */
- 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+521,521,521,521,521,521,521,521,521,521,521,521,521,521,521,521,
+521,521,521,521,521,521,521,521,521,521,521,521,521,521,521,116,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
-514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,
-514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,
-514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,115,
+ 19, 19, 19, 19, 19, 19, 19, 19, 24, 24, 24, 24, 24, 24, 24, 24,
+ 19, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+521,521,521,521,521,521,521,521,521,521,521,521,521,521,521,521,
+521,521,521,521,521,521,521,521,521,521,521,521,521,521,521, 19,
/* block 95 */
-514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,
-514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,
-514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,
-514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,
-514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,
-514,514,514,514,514,514,514,514, 19, 19, 19, 19, 19, 19, 19, 19,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 20, 19, 20, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,
+522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,
+522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,116,
/* block 96 */
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
+522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,
+522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,
+522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,
+522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,
+522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,
+522,522,522,522,522,522,522,522, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
/* block 97 */
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,115,115,115,115,115,115,115,115,115,115,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+
+/* block 98 */
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,116,116,116,116,116,116,116,116,116,116,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
-/* block 98 */
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-
/* block 99 */
-516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,
-516,516,516,516,516,517,516,516,516,516,516,516,516,516,516,516,
-516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,
-516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,
-516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,
-516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,
-516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,
-516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 100 */
-516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,
-516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,
-516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,
-516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,
-516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,
-516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,
-516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,
-516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,
+524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,
+524,524,524,524,524,525,524,524,524,524,524,524,524,524,524,524,
+524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,
+524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,
+524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,
+524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,
+524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,
+524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,
/* block 101 */
-516,516,516,516,516,516,516,516,516,516,516,516,516,115,115,115,
-518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,
-518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,
-518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,
-518,518,518,518,518,518,518,115,115,115,115,115,115,115,115,115,
-519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,
-519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,
-519,519,519,519,519,519,519,519,520,520,520,520,520,520,521,521,
+524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,
+524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,
+524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,
+524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,
+524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,
+524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,
+524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,
+524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,
/* block 102 */
-522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,
-522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,
-522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,
-522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,
-522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,
-522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,
-522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,
-522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,
+524,524,524,524,524,524,524,524,524,524,524,524,524,116,116,116,
+526,526,526,526,526,526,526,526,526,526,526,526,526,526,526,526,
+526,526,526,526,526,526,526,526,526,526,526,526,526,526,526,526,
+526,526,526,526,526,526,526,526,526,526,526,526,526,526,526,526,
+526,526,526,526,526,526,526,116,116,116,116,116,116,116,116,116,
+527,527,527,527,527,527,527,527,527,527,527,527,527,527,527,527,
+527,527,527,527,527,527,527,527,527,527,527,527,527,527,527,527,
+527,527,527,527,527,527,527,527,528,528,528,528,528,528,529,529,
/* block 103 */
-522,522,522,522,522,522,522,522,522,522,522,522,523,524,524,524,
-522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,
-525,525,525,525,525,525,525,525,525,525,522,522,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-187,188,187,188,187,188,187,188,187,188,526,527,187,188,187,188,
-187,188,187,188,187,188,187,188,187,188,187,188,187,188,187,188,
-187,188,187,188,187,188,187,188,187,188,187,188,187,188,528,192,
-193,193,193,529,192,192,192,192,192,192,192,192,192,192,529,436,
-
-/* block 104 */
-187,188,187,188,187,188,187,188,187,188,187,188,187,188,187,188,
-187,188,187,188,187,188,187,188,187,188,187,188,436,436,192,192,
530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,
530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,
530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,
530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,
-530,530,530,530,530,530,531,531,531,531,531,531,531,531,531,531,
-532,532,533,533,533,533,533,533,115,115,115,115,115,115,115,115,
+530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,
+530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,
+530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,
+530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,
+
+/* block 104 */
+530,530,530,530,530,530,530,530,530,530,530,530,531,532,532,532,
+530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,
+533,533,533,533,533,533,533,533,533,533,530,530,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+188,189,188,189,188,189,188,189,188,189,534,535,188,189,188,189,
+188,189,188,189,188,189,188,189,188,189,188,189,188,189,188,189,
+188,189,188,189,188,189,188,189,188,189,188,189,188,189,536,193,
+194,194,194,537,193,193,193,193,193,193,193,193,193,193,537,441,
/* block 105 */
- 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14,108,108,108,108,108,108,108,108,108,
- 14, 14, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
- 33, 33, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
- 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
- 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
- 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
-107, 33, 33, 33, 33, 33, 33, 33, 33, 30, 31, 30, 31,534, 30, 31,
+188,189,188,189,188,189,188,189,188,189,188,189,188,189,188,189,
+188,189,188,189,188,189,188,189,188,189,188,189,441,441,193,193,
+538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,
+538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,
+538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,
+538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,
+538,538,538,538,538,538,539,539,539,539,539,539,539,539,539,539,
+540,540,541,541,541,541,541,541,116,116,116,116,116,116,116,116,
/* block 106 */
- 30, 31, 30, 31, 30, 31, 30, 31,108, 14, 14, 30, 31,535, 33, 20,
- 30, 31, 30, 31, 33, 33, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
- 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,536,537,538,539,536,115,
-540,541,542,543, 30, 31, 30, 31,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115, 20,107,107, 33, 20, 20, 20, 20, 20,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14,109,109,109,109,109,109,109,109,109,
+ 14, 14, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32,
+ 34, 34, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32,
+ 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32,
+ 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32,
+ 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32,
+108, 34, 34, 34, 34, 34, 34, 34, 34, 31, 32, 31, 32,542, 31, 32,
/* block 107 */
-544,544,545,544,544,544,545,544,544,544,544,545,544,544,544,544,
-544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,
-544,544,544,546,546,545,545,546,547,547,547,547,115,115,115,115,
- 23, 23, 23, 23, 23, 23, 19, 19, 5, 19,115,115,115,115,115,115,
-548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,
-548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,
-548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,
-548,548,548,548,549,549,549,549,115,115,115,115,115,115,115,115,
+ 31, 32, 31, 32, 31, 32, 31, 32,109, 14, 14, 31, 32,543, 34, 21,
+ 31, 32, 31, 32, 34, 34, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32,
+ 31, 32, 31, 32, 31, 32, 31, 32, 31, 32,544,545,546,547,544, 34,
+548,549,550,551, 31, 32, 31, 32, 31, 32,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116, 21,108,108, 34, 21, 21, 21, 21, 21,
/* block 108 */
-550,550,551,551,551,551,551,551,551,551,551,551,551,551,551,551,
-551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,
-551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,
-551,551,551,551,550,550,550,550,550,550,550,550,550,550,550,550,
-550,550,550,550,552,552,115,115,115,115,115,115,115,115,553,553,
-554,554,554,554,554,554,554,554,554,554,115,115,115,115,115,115,
-238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,
-238,238,240,240,240,240,240,240,242,242,242,240,242,240,115,115,
+552,552,553,552,552,552,553,552,552,552,552,553,552,552,552,552,
+552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,
+552,552,552,554,554,553,553,554,555,555,555,555,116,116,116,116,
+ 24, 24, 24, 24, 24, 24, 19, 19, 5, 19,116,116,116,116,116,116,
+556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,
+556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,
+556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,
+556,556,556,556,557,557,557,557,116,116,116,116,116,116,116,116,
/* block 109 */
-555,555,555,555,555,555,555,555,555,555,556,556,556,556,556,556,
-556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,
-556,556,556,556,556,556,557,557,557,557,557,557,557,557, 4,558,
+558,558,559,559,559,559,559,559,559,559,559,559,559,559,559,559,
559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,
-559,559,559,559,559,559,559,560,560,560,560,560,560,560,560,560,
-560,560,561,561,115,115,115,115,115,115,115,115,115,115,115,562,
-333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,
-333,333,333,333,333,333,333,333,333,333,333,333,333,115,115,115,
+559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,
+559,559,559,559,558,558,558,558,558,558,558,558,558,558,558,558,
+558,558,558,558,560,560,116,116,116,116,116,116,116,116,561,561,
+562,562,562,562,562,562,562,562,562,562,116,116,116,116,116,116,
+240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
+240,240,242,242,242,242,242,242,244,244,244,242,244,242,242,240,
/* block 110 */
-563,563,563,564,565,565,565,565,565,565,565,565,565,565,565,565,
-565,565,565,565,565,565,565,565,565,565,565,565,565,565,565,565,
-565,565,565,565,565,565,565,565,565,565,565,565,565,565,565,565,
-565,565,565,563,564,564,563,563,563,563,564,564,563,564,564,564,
-564,566,566,566,566,566,566,566,566,566,566,566,566,566,115,108,
-567,567,567,567,567,567,567,567,567,567,115,115,115,115,566,566,
-323,323,323,323,323,325,568,323,323,323,323,323,323,323,323,323,
-327,327,327,327,327,327,327,327,327,327,323,323,323,323,323,115,
+563,563,563,563,563,563,563,563,563,563,564,564,564,564,564,564,
+564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,
+564,564,564,564,564,564,565,565,565,565,565,565,565,565, 4,566,
+567,567,567,567,567,567,567,567,567,567,567,567,567,567,567,567,
+567,567,567,567,567,567,567,568,568,568,568,568,568,568,568,568,
+568,568,569,569,116,116,116,116,116,116,116,116,116,116,116,570,
+337,337,337,337,337,337,337,337,337,337,337,337,337,337,337,337,
+337,337,337,337,337,337,337,337,337,337,337,337,337,116,116,116,
/* block 111 */
-569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,
-569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,
-569,569,569,569,569,569,569,569,569,570,570,570,570,570,570,571,
-571,570,570,571,571,570,570,115,115,115,115,115,115,115,115,115,
-569,569,569,570,569,569,569,569,569,569,569,569,570,571,115,115,
-572,572,572,572,572,572,572,572,572,572,115,115,573,573,573,573,
-323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,
-568,323,323,323,323,323,323,329,329,329,323,324,325,324,323,323,
+571,571,571,572,573,573,573,573,573,573,573,573,573,573,573,573,
+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,
+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,
+573,573,573,571,572,572,571,571,571,571,572,572,571,572,572,572,
+572,574,574,574,574,574,574,574,574,574,574,574,574,574,116,109,
+575,575,575,575,575,575,575,575,575,575,116,116,116,116,574,574,
+327,327,327,327,327,329,576,327,327,327,327,327,327,327,327,327,
+331,331,331,331,331,331,331,331,331,331,327,327,327,327,327,116,
/* block 112 */
-574,574,574,574,574,574,574,574,574,574,574,574,574,574,574,574,
-574,574,574,574,574,574,574,574,574,574,574,574,574,574,574,574,
-574,574,574,574,574,574,574,574,574,574,574,574,574,574,574,574,
-575,574,575,575,575,574,574,575,575,574,574,574,574,574,575,575,
-574,575,574,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,574,574,576,577,577,
-578,578,578,578,578,578,578,578,578,578,578,579,580,580,579,579,
-581,581,578,582,582,579,580,115,115,115,115,115,115,115,115,115,
+577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
+577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
+577,577,577,577,577,577,577,577,577,578,578,578,578,578,578,579,
+579,578,578,579,579,578,578,116,116,116,116,116,116,116,116,116,
+577,577,577,578,577,577,577,577,577,577,577,577,578,579,116,116,
+580,580,580,580,580,580,580,580,580,580,116,116,581,581,581,581,
+327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,
+576,327,327,327,327,327,327,333,333,333,327,328,329,328,327,327,
/* block 113 */
-115,336,336,336,336,336,336,115,115,336,336,336,336,336,336,115,
-115,336,336,336,336,336,336,115,115,115,115,115,115,115,115,115,
-336,336,336,336,336,336,336,115,336,336,336,336,336,336,336,115,
- 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
- 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
- 33, 33, 33,583, 33, 33, 33, 33, 33, 33, 33, 14,107,107,107,107,
- 33, 33, 33, 33, 33,123,115,115,115,115,115,115,115,115,115,115,
-584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,
+582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,
+582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,
+582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,
+583,582,583,583,583,582,582,583,583,582,582,582,582,582,583,583,
+582,583,582,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,582,582,584,585,585,
+586,586,586,586,586,586,586,586,586,586,586,587,588,588,587,587,
+589,589,586,590,590,587,588,116,116,116,116,116,116,116,116,116,
/* block 114 */
-584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,
-584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,
-584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,
-584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,
-578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
-578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
-578,578,578,579,579,580,579,579,580,579,579,581,579,580,115,115,
-585,585,585,585,585,585,585,585,585,585,115,115,115,115,115,115,
+116,340,340,340,340,340,340,116,116,340,340,340,340,340,340,116,
+116,340,340,340,340,340,340,116,116,116,116,116,116,116,116,116,
+340,340,340,340,340,340,340,116,340,340,340,340,340,340,340,116,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+ 34, 34, 34,591, 34, 34, 34, 34, 34, 34, 34, 14,108,108,108,108,
+ 34, 34, 34, 34, 34,124,116,116,116,116,116,116,116,116,116,116,
+592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,
/* block 115 */
-586,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
-587,587,587,587,587,587,587,587,587,587,587,587,586,587,587,587,
-587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
-587,587,587,587,587,587,587,587,586,587,587,587,587,587,587,587,
-587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
-587,587,587,587,586,587,587,587,587,587,587,587,587,587,587,587,
-587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
-586,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
+592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,
+592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,
+592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,
+592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,587,587,588,587,587,588,587,587,589,587,588,116,116,
+593,593,593,593,593,593,593,593,593,593,116,116,116,116,116,116,
/* block 116 */
-587,587,587,587,587,587,587,587,587,587,587,587,586,587,587,587,
-587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
-587,587,587,587,587,587,587,587,586,587,587,587,587,587,587,587,
-587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
-587,587,587,587,586,587,587,587,587,587,587,587,587,587,587,587,
-587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
-586,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
-587,587,587,587,587,587,587,587,587,587,587,587,586,587,587,587,
+594,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,
+595,595,595,595,595,595,595,595,595,595,595,595,594,595,595,595,
+595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,
+595,595,595,595,595,595,595,595,594,595,595,595,595,595,595,595,
+595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,
+595,595,595,595,594,595,595,595,595,595,595,595,595,595,595,595,
+595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,
+594,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,
/* block 117 */
-587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
-587,587,587,587,587,587,587,587,586,587,587,587,587,587,587,587,
-587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
-587,587,587,587,586,587,587,587,587,587,587,587,587,587,587,587,
-587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
-586,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
-587,587,587,587,587,587,587,587,587,587,587,587,586,587,587,587,
-587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
+595,595,595,595,595,595,595,595,595,595,595,595,594,595,595,595,
+595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,
+595,595,595,595,595,595,595,595,594,595,595,595,595,595,595,595,
+595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,
+595,595,595,595,594,595,595,595,595,595,595,595,595,595,595,595,
+595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,
+594,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,
+595,595,595,595,595,595,595,595,595,595,595,595,594,595,595,595,
/* block 118 */
-587,587,587,587,587,587,587,587,586,587,587,587,587,587,587,587,
-587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
-587,587,587,587,586,587,587,587,587,587,587,587,587,587,587,587,
-587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
-586,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
-587,587,587,587,587,587,587,587,587,587,587,587,586,587,587,587,
-587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
-587,587,587,587,587,587,587,587,586,587,587,587,587,587,587,587,
+595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,
+595,595,595,595,595,595,595,595,594,595,595,595,595,595,595,595,
+595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,
+595,595,595,595,594,595,595,595,595,595,595,595,595,595,595,595,
+595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,
+594,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,
+595,595,595,595,595,595,595,595,595,595,595,595,594,595,595,595,
+595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,
/* block 119 */
-587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
-587,587,587,587,586,587,587,587,587,587,587,587,587,587,587,587,
-587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
-586,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
-587,587,587,587,587,587,587,587,587,587,587,587,586,587,587,587,
-587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
-587,587,587,587,587,587,587,587,586,587,587,587,587,587,587,587,
-587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
+595,595,595,595,595,595,595,595,594,595,595,595,595,595,595,595,
+595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,
+595,595,595,595,594,595,595,595,595,595,595,595,595,595,595,595,
+595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,
+594,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,
+595,595,595,595,595,595,595,595,595,595,595,595,594,595,595,595,
+595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,
+595,595,595,595,595,595,595,595,594,595,595,595,595,595,595,595,
/* block 120 */
-587,587,587,587,586,587,587,587,587,587,587,587,587,587,587,587,
-587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
-586,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
-587,587,587,587,587,587,587,587,587,587,587,587,586,587,587,587,
-587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
-587,587,587,587,587,587,587,587,586,587,587,587,587,587,587,587,
-587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
-587,587,587,587,586,587,587,587,587,587,587,587,587,587,587,587,
+595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,
+595,595,595,595,594,595,595,595,595,595,595,595,595,595,595,595,
+595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,
+594,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,
+595,595,595,595,595,595,595,595,595,595,595,595,594,595,595,595,
+595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,
+595,595,595,595,595,595,595,595,594,595,595,595,595,595,595,595,
+595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,
/* block 121 */
-587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
-586,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
-587,587,587,587,587,587,587,587,587,587,587,587,586,587,587,587,
-587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
-587,587,587,587,587,587,587,587,586,587,587,587,587,587,587,587,
-587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
-587,587,587,587,586,587,587,587,587,587,587,587,587,587,587,587,
-587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
+595,595,595,595,594,595,595,595,595,595,595,595,595,595,595,595,
+595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,
+594,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,
+595,595,595,595,595,595,595,595,595,595,595,595,594,595,595,595,
+595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,
+595,595,595,595,595,595,595,595,594,595,595,595,595,595,595,595,
+595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,
+595,595,595,595,594,595,595,595,595,595,595,595,595,595,595,595,
/* block 122 */
-587,587,587,587,587,587,587,587,586,587,587,587,587,587,587,587,
-587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
-587,587,587,587,115,115,115,115,115,115,115,115,115,115,115,115,
-334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,
-334,334,334,334,334,334,334,115,115,115,115,335,335,335,335,335,
-335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,
-335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,
-335,335,335,335,335,335,335,335,335,335,335,335,115,115,115,115,
+595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,
+594,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,
+595,595,595,595,595,595,595,595,595,595,595,595,594,595,595,595,
+595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,
+595,595,595,595,595,595,595,595,594,595,595,595,595,595,595,595,
+595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,
+595,595,595,595,594,595,595,595,595,595,595,595,595,595,595,595,
+595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,
/* block 123 */
-588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,
-588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,
-588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,
-588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,
-588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,
-588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,
-588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,
-588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,
+595,595,595,595,595,595,595,595,594,595,595,595,595,595,595,595,
+595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,
+595,595,595,595,116,116,116,116,116,116,116,116,116,116,116,116,
+338,338,338,338,338,338,338,338,338,338,338,338,338,338,338,338,
+338,338,338,338,338,338,338,116,116,116,116,339,339,339,339,339,
+339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,
+339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,
+339,339,339,339,339,339,339,339,339,339,339,339,116,116,116,116,
/* block 124 */
-589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,
-589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,
-589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,
-589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,
-589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,
-589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,
-589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,
-589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,
+596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,
+596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,
+596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,
+596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,
+596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,
+596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,
+596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,
+596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,
/* block 125 */
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,115,115,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
+597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,
+597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,
+597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,
+597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,
+597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,
+597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,
+597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,
+597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,
/* block 126 */
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,116,116,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
/* block 127 */
- 33, 33, 33, 33, 33, 33, 33,115,115,115,115,115,115,115,115,115,
-115,115,115,200,200,200,200,200,115,115,115,115,115,207,204,207,
-207,207,207,207,207,207,207,207,207,590,207,207,207,207,207,207,
-207,207,207,207,207,207,207,115,207,207,207,207,207,115,207,115,
-207,207,115,207,207,115,207,207,207,207,207,207,207,207,207,207,
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 128 */
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-216,216,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,216,216,216,216,216,216,216,216,216,216,216,216,216,
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
+ 34, 34, 34, 34, 34, 34, 34,116,116,116,116,116,116,116,116,116,
+116,116,116,200,200,200,200,200,116,116,116,116,116,208,205,208,
+208,208,208,208,208,208,208,208,208,598,208,208,208,208,208,208,
+208,208,208,208,208,208,208,116,208,208,208,208,208,116,208,116,
+208,208,116,208,208,116,208,208,208,208,208,208,208,208,208,208,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
/* block 129 */
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,599,599,599,599,599,599,599,599,599,599,599,599,599,599,
+599,599,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
/* block 130 */
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-216,216,216,216,216,216,216,216,216,216,216,216,216,216, 7, 6,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
/* block 131 */
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-115,115,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-216,216,216,216,216,216,216,216,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-216,216,216,216,216,216,216,216,216,216,216,216,212,213,115,115,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217, 7, 6,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
/* block 132 */
-110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
- 4, 4, 4, 4, 4, 4, 4, 6, 7, 4,115,115,115,115,115,115,
-110,110,110,110,110,110,110,110,110,110,110,110,110,110,192,192,
- 4, 9, 9, 15, 15, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6,
- 7, 6, 7, 6, 7, 4, 4, 6, 7, 4, 4, 4, 4, 15, 15, 15,
- 4, 4, 4,115, 4, 4, 4, 4, 9, 6, 7, 6, 7, 6, 7, 4,
- 4, 4, 8, 9, 8, 8, 8,115, 4, 5, 4, 4,115,115,115,115,
-216,216,216,216,216,115,216,216,216,216,216,216,216,216,216,216,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+116,116,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,217,217,217,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+217,217,217,217,217,217,217,217,217,217,217,217,213,214,116,116,
/* block 133 */
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-216,216,216,216,216,216,216,216,216,216,216,216,216,115,115, 22,
+111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
+ 4, 4, 4, 4, 4, 4, 4, 6, 7, 4,116,116,116,116,116,116,
+111,111,111,111,111,111,111,111,111,111,111,111,111,111,193,193,
+ 4, 9, 9, 15, 15, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6,
+ 7, 6, 7, 6, 7, 4, 4, 6, 7, 4, 4, 4, 4, 15, 15, 15,
+ 4, 4, 4,116, 4, 4, 4, 4, 9, 6, 7, 6, 7, 6, 7, 4,
+ 4, 4, 8, 9, 8, 8, 8,116, 4, 5, 4, 4,116,116,116,116,
+217,217,217,217,217,116,217,217,217,217,217,217,217,217,217,217,
/* block 134 */
-115, 4, 4, 4, 5, 4, 4, 4, 6, 7, 4, 8, 4, 9, 4, 4,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217,217,217,116,116, 23,
+
+/* block 135 */
+116, 4, 4, 4, 5, 4, 4, 4, 6, 7, 4, 8, 4, 9, 4, 4,
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 4, 4, 8, 8, 8, 4,
4, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 6, 4, 7, 14, 15,
14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 6, 8, 7, 8, 6,
- 7, 4, 6, 7, 4, 4,509,509,509,509,509,509,509,509,509,509,
-108,509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,
-
-/* block 135 */
-509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,
-509,509,509,509,509,509,509,509,509,509,509,509,509,509,592,592,
-512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,
-512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,115,
-115,115,512,512,512,512,512,512,115,115,512,512,512,512,512,512,
-115,115,512,512,512,512,512,512,115,115,512,512,512,115,115,115,
- 5, 5, 8, 14, 19, 5, 5,115, 19, 8, 8, 8, 8, 19, 19,115,
-465,465,465,465,465,465,465,465,465, 22, 22, 22, 19, 19,115,115,
+ 7, 4, 6, 7, 4, 4,517,517,517,517,517,517,517,517,517,517,
+109,517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,
/* block 136 */
-593,593,593,593,593,593,593,593,593,593,593,593,115,593,593,593,
-593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,
-593,593,593,593,593,593,593,115,593,593,593,593,593,593,593,593,
-593,593,593,593,593,593,593,593,593,593,593,115,593,593,115,593,
-593,593,593,593,593,593,593,593,593,593,593,593,593,593,115,115,
-593,593,593,593,593,593,593,593,593,593,593,593,593,593,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,
+517,517,517,517,517,517,517,517,517,517,517,517,517,517,600,600,
+520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,
+520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,116,
+116,116,520,520,520,520,520,520,116,116,520,520,520,520,520,520,
+116,116,520,520,520,520,520,520,116,116,520,520,520,116,116,116,
+ 5, 5, 8, 14, 19, 5, 5,116, 19, 8, 8, 8, 8, 19, 19,116,
+471,471,471,471,471,471,471,471,471, 23, 23, 23, 19, 19,116,116,
/* block 137 */
-593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,
-593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,
-593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,
-593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,
-593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,
-593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,
-593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,
-593,593,593,593,593,593,593,593,593,593,593,115,115,115,115,115,
+601,601,601,601,601,601,601,601,601,601,601,601,116,601,601,601,
+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,
+601,601,601,601,601,601,601,116,601,601,601,601,601,601,601,601,
+601,601,601,601,601,601,601,601,601,601,601,116,601,601,116,601,
+601,601,601,601,601,601,601,601,601,601,601,601,601,601,116,116,
+601,601,601,601,601,601,601,601,601,601,601,601,601,601,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 138 */
- 4, 4, 4,115,115,115,115, 23, 23, 23, 23, 23, 23, 23, 23, 23,
- 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
- 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
- 23, 23, 23, 23,115,115,115, 19, 19, 19, 19, 19, 19, 19, 19, 19,
-594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,
-594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,
-594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,
-594,594,594,594,594,595,595,595,595,596,596,596,596,596,596,596,
+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,
+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,
+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,
+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,
+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,
+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,
+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,
+601,601,601,601,601,601,601,601,601,601,601,116,116,116,116,116,
/* block 139 */
-596,596,596,596,596,596,596,596,596,596,595,595,596,596,596,115,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,
-596,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,110,115,115,
+ 4, 4, 4,116,116,116,116, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24,116,116,116, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,
+602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,
+602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,
+602,602,602,602,602,603,603,603,603,604,604,604,604,604,604,604,
/* block 140 */
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+604,604,604,604,604,604,604,604,604,604,603,603,604,604,604,116,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,116,116,116,116,
+604,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,111,116,116,
/* block 141 */
-597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,
-597,597,597,597,597,597,597,597,597,597,597,597,597,115,115,115,
-598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,
-598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,
-598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,
-598,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-110, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
- 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,115,115,115,115,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 142 */
-599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,
-599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,
-600,600,600,600,115,115,115,115,115,115,115,115,115,599,599,599,
-601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,
-601,602,601,601,601,601,601,601,601,601,602,115,115,115,115,115,
-603,603,603,603,603,603,603,603,603,603,603,603,603,603,603,603,
-603,603,603,603,603,603,603,603,603,603,603,603,603,603,603,603,
-603,603,603,603,603,603,604,604,604,604,604,115,115,115,115,115,
+605,605,605,605,605,605,605,605,605,605,605,605,605,605,605,605,
+605,605,605,605,605,605,605,605,605,605,605,605,605,116,116,116,
+606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,
+606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,
+606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,
+606,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+111, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,116,116,116,116,
/* block 143 */
-605,605,605,605,605,605,605,605,605,605,605,605,605,605,605,605,
-605,605,605,605,605,605,605,605,605,605,605,605,605,605,115,606,
607,607,607,607,607,607,607,607,607,607,607,607,607,607,607,607,
607,607,607,607,607,607,607,607,607,607,607,607,607,607,607,607,
-607,607,607,607,115,115,115,115,607,607,607,607,607,607,607,607,
-608,609,609,609,609,609,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-
-/* block 144 */
-610,610,610,610,610,610,610,610,610,610,610,610,610,610,610,610,
-610,610,610,610,610,610,610,610,610,610,610,610,610,610,610,610,
-610,610,610,610,610,610,610,610,611,611,611,611,611,611,611,611,
+608,608,608,608,116,116,116,116,116,116,116,116,116,607,607,607,
+609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,
+609,610,609,609,609,609,609,609,609,609,610,116,116,116,116,116,
611,611,611,611,611,611,611,611,611,611,611,611,611,611,611,611,
611,611,611,611,611,611,611,611,611,611,611,611,611,611,611,611,
-612,612,612,612,612,612,612,612,612,612,612,612,612,612,612,612,
-612,612,612,612,612,612,612,612,612,612,612,612,612,612,612,612,
-612,612,612,612,612,612,612,612,612,612,612,612,612,612,612,612,
+611,611,611,611,611,611,612,612,612,612,612,116,116,116,116,116,
-/* block 145 */
+/* block 144 */
613,613,613,613,613,613,613,613,613,613,613,613,613,613,613,613,
-613,613,613,613,613,613,613,613,613,613,613,613,613,613,115,115,
-614,614,614,614,614,614,614,614,614,614,115,115,115,115,115,115,
+613,613,613,613,613,613,613,613,613,613,613,613,613,613,116,614,
615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,
615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,
-615,615,615,615,115,115,115,115,616,616,616,616,616,616,616,616,
-616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,
-616,616,616,616,616,616,616,616,616,616,616,616,115,115,115,115,
+615,615,615,615,116,116,116,116,615,615,615,615,615,615,615,615,
+616,617,617,617,617,617,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
-/* block 146 */
-617,617,617,617,617,617,617,617,617,617,617,617,617,617,617,617,
-617,617,617,617,617,617,617,617,617,617,617,617,617,617,617,617,
-617,617,617,617,617,617,617,617,115,115,115,115,115,115,115,115,
-618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,
+/* block 145 */
618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,
618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,
-618,618,618,618,115,115,115,115,115,115,115,115,115,115,115,619,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-
-/* block 147 */
-620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,
-620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,
-620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,
-620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,
-620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,
+618,618,618,618,618,618,618,618,619,619,619,619,619,619,619,619,
+619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,
+619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,
620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,
620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,
620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,
+/* block 146 */
+621,621,621,621,621,621,621,621,621,621,621,621,621,621,621,621,
+621,621,621,621,621,621,621,621,621,621,621,621,621,621,116,116,
+622,622,622,622,622,622,622,622,622,622,116,116,116,116,116,116,
+623,623,623,623,623,623,623,623,623,623,623,623,623,623,623,623,
+623,623,623,623,623,623,623,623,623,623,623,623,623,623,623,623,
+623,623,623,623,116,116,116,116,624,624,624,624,624,624,624,624,
+624,624,624,624,624,624,624,624,624,624,624,624,624,624,624,624,
+624,624,624,624,624,624,624,624,624,624,624,624,116,116,116,116,
+
+/* block 147 */
+625,625,625,625,625,625,625,625,625,625,625,625,625,625,625,625,
+625,625,625,625,625,625,625,625,625,625,625,625,625,625,625,625,
+625,625,625,625,625,625,625,625,116,116,116,116,116,116,116,116,
+626,626,626,626,626,626,626,626,626,626,626,626,626,626,626,626,
+626,626,626,626,626,626,626,626,626,626,626,626,626,626,626,626,
+626,626,626,626,626,626,626,626,626,626,626,626,626,626,626,626,
+626,626,626,626,116,116,116,116,116,116,116,116,116,116,116,627,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+
/* block 148 */
-620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,
-620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,
-620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,
-620,620,620,620,620,620,620,115,115,115,115,115,115,115,115,115,
-620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,
-620,620,620,620,620,620,115,115,115,115,115,115,115,115,115,115,
-620,620,620,620,620,620,620,620,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,
+628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,
+628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,
+628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,
+628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,
+628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,
+628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,
+628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,
/* block 149 */
-621,621,621,621,621,621,115,115,621,115,621,621,621,621,621,621,
-621,621,621,621,621,621,621,621,621,621,621,621,621,621,621,621,
-621,621,621,621,621,621,621,621,621,621,621,621,621,621,621,621,
-621,621,621,621,621,621,115,621,621,115,115,115,621,115,115,621,
-622,622,622,622,622,622,622,622,622,622,622,622,622,622,622,622,
-622,622,622,622,622,622,115,623,624,624,624,624,624,624,624,624,
-625,625,625,625,625,625,625,625,625,625,625,625,625,625,625,625,
-625,625,625,625,625,625,625,626,626,627,627,627,627,627,627,627,
+628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,
+628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,
+628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,
+628,628,628,628,628,628,628,116,116,116,116,116,116,116,116,116,
+628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,
+628,628,628,628,628,628,116,116,116,116,116,116,116,116,116,116,
+628,628,628,628,628,628,628,628,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 150 */
-628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,
-628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,115,
-115,115,115,115,115,115,115,629,629,629,629,629,629,629,629,629,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+629,629,629,629,629,629,116,116,629,116,629,629,629,629,629,629,
+629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,
+629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,
+629,629,629,629,629,629,116,629,629,116,116,116,629,116,116,629,
630,630,630,630,630,630,630,630,630,630,630,630,630,630,630,630,
-630,630,630,115,630,630,115,115,115,115,115,631,631,631,631,631,
+630,630,630,630,630,630,116,631,632,632,632,632,632,632,632,632,
+633,633,633,633,633,633,633,633,633,633,633,633,633,633,633,633,
+633,633,633,633,633,633,633,634,634,635,635,635,635,635,635,635,
/* block 151 */
-632,632,632,632,632,632,632,632,632,632,632,632,632,632,632,632,
-632,632,632,632,632,632,633,633,633,633,633,633,115,115,115,634,
-635,635,635,635,635,635,635,635,635,635,635,635,635,635,635,635,
-635,635,635,635,635,635,635,635,635,635,115,115,115,115,115,636,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+636,636,636,636,636,636,636,636,636,636,636,636,636,636,636,636,
+636,636,636,636,636,636,636,636,636,636,636,636,636,636,636,116,
+116,116,116,116,116,116,116,637,637,637,637,637,637,637,637,637,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,
+638,638,638,116,638,638,116,116,116,116,116,639,639,639,639,639,
/* block 152 */
-637,637,637,637,637,637,637,637,637,637,637,637,637,637,637,637,
-637,637,637,637,637,637,637,637,637,637,637,637,637,637,637,637,
-638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,
-638,638,638,638,638,638,638,638,115,115,115,115,639,639,638,638,
-639,639,639,639,639,639,639,639,639,639,639,639,639,639,639,639,
-115,115,639,639,639,639,639,639,639,639,639,639,639,639,639,639,
-639,639,639,639,639,639,639,639,639,639,639,639,639,639,639,639,
-639,639,639,639,639,639,639,639,639,639,639,639,639,639,639,639,
+640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,
+640,640,640,640,640,640,641,641,641,641,641,641,116,116,116,642,
+643,643,643,643,643,643,643,643,643,643,643,643,643,643,643,643,
+643,643,643,643,643,643,643,643,643,643,116,116,116,116,116,644,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 153 */
-640,641,641,641,115,641,641,115,115,115,115,115,641,641,641,641,
-640,640,640,640,115,640,640,640,115,640,640,640,640,640,640,640,
-640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,
-640,640,640,640,115,115,115,115,641,641,641,115,115,115,115,641,
-642,642,642,642,642,642,642,642,115,115,115,115,115,115,115,115,
-643,643,643,643,643,643,643,643,643,115,115,115,115,115,115,115,
-644,644,644,644,644,644,644,644,644,644,644,644,644,644,644,644,
-644,644,644,644,644,644,644,644,644,644,644,644,644,645,645,646,
+645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,
+645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,
+646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,
+646,646,646,646,646,646,646,646,116,116,116,116,647,647,646,646,
+647,647,647,647,647,647,647,647,647,647,647,647,647,647,647,647,
+116,116,647,647,647,647,647,647,647,647,647,647,647,647,647,647,
+647,647,647,647,647,647,647,647,647,647,647,647,647,647,647,647,
+647,647,647,647,647,647,647,647,647,647,647,647,647,647,647,647,
/* block 154 */
-647,647,647,647,647,647,647,647,647,647,647,647,647,647,647,647,
-647,647,647,647,647,647,647,647,647,647,647,647,647,648,648,648,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-649,649,649,649,649,649,649,649,650,649,649,649,649,649,649,649,
-649,649,649,649,649,649,649,649,649,649,649,649,649,649,649,649,
-649,649,649,649,649,651,651,115,115,115,115,652,652,652,652,652,
-653,653,653,653,653,653,653,115,115,115,115,115,115,115,115,115,
+648,649,649,649,116,649,649,116,116,116,116,116,649,649,649,649,
+648,648,648,648,116,648,648,648,116,648,648,648,648,648,648,648,
+648,648,648,648,648,648,648,648,648,648,648,648,648,648,648,648,
+648,648,648,648,648,648,116,116,649,649,649,116,116,116,116,649,
+650,650,650,650,650,650,650,650,650,116,116,116,116,116,116,116,
+651,651,651,651,651,651,651,651,651,116,116,116,116,116,116,116,
+652,652,652,652,652,652,652,652,652,652,652,652,652,652,652,652,
+652,652,652,652,652,652,652,652,652,652,652,652,652,653,653,654,
/* block 155 */
-654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,
-654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,
-654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,
-654,654,654,654,654,654,115,115,115,655,655,655,655,655,655,655,
-656,656,656,656,656,656,656,656,656,656,656,656,656,656,656,656,
-656,656,656,656,656,656,115,115,657,657,657,657,657,657,657,657,
-658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,
-658,658,658,115,115,115,115,115,659,659,659,659,659,659,659,659,
+655,655,655,655,655,655,655,655,655,655,655,655,655,655,655,655,
+655,655,655,655,655,655,655,655,655,655,655,655,655,656,656,656,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+657,657,657,657,657,657,657,657,658,657,657,657,657,657,657,657,
+657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
+657,657,657,657,657,659,659,116,116,116,116,660,660,660,660,660,
+661,661,661,661,661,661,661,116,116,116,116,116,116,116,116,116,
/* block 156 */
-660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,
-660,660,115,115,115,115,115,115,115,661,661,661,661,115,115,115,
-115,115,115,115,115,115,115,115,115,662,662,662,662,662,662,662,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,
+662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,
+662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,
+662,662,662,662,662,662,116,116,116,663,663,663,663,663,663,663,
+664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,
+664,664,664,664,664,664,116,116,665,665,665,665,665,665,665,665,
+666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,
+666,666,666,116,116,116,116,116,667,667,667,667,667,667,667,667,
/* block 157 */
-663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,
-663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,
-663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,
-663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,
-663,663,663,663,663,663,663,663,663,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,
+668,668,116,116,116,116,116,116,116,669,669,669,669,116,116,116,
+116,116,116,116,116,116,116,116,116,670,670,670,670,670,670,670,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 158 */
-664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,
-664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,
-664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,
-664,664,664,115,115,115,115,115,115,115,115,115,115,115,115,115,
-665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,
-665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,
-665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,
-665,665,665,115,115,115,115,115,115,115,666,666,666,666,666,666,
+671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,
+671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,
+671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,
+671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,
+671,671,671,671,671,671,671,671,671,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 159 */
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,
-667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,115,
+672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,
+672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,
+672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,
+672,672,672,116,116,116,116,116,116,116,116,116,116,116,116,116,
+673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,
+673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,
+673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,
+673,673,673,116,116,116,116,116,116,116,674,674,674,674,674,674,
/* block 160 */
-668,669,668,670,670,670,670,670,670,670,670,670,670,670,670,670,
-670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,
-670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,
-670,670,670,670,670,670,670,670,669,669,669,669,669,669,669,669,
-669,669,669,669,669,669,669,671,671,671,671,671,671,671,115,115,
-115,115,672,672,672,672,672,672,672,672,672,672,672,672,672,672,
-672,672,672,672,672,672,673,673,673,673,673,673,673,673,673,673,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,669,
+675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,
+675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,
+675,675,675,675,676,676,676,676,116,116,116,116,116,116,116,116,
+677,677,677,677,677,677,677,677,677,677,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 161 */
-674,674,675,676,676,676,676,676,676,676,676,676,676,676,676,676,
-676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,
-676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,
-675,675,675,674,674,674,674,675,675,674,674,677,677,678,677,677,
-677,677,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,
-679,679,679,679,679,679,679,679,679,115,115,115,115,115,115,115,
-680,680,680,680,680,680,680,680,680,680,115,115,115,115,115,115,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,
+678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,116,
/* block 162 */
-681,681,681,682,682,682,682,682,682,682,682,682,682,682,682,682,
-682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,
-682,682,682,682,682,682,682,681,681,681,681,681,683,681,681,681,
-681,681,681,681,681,115,684,684,684,684,684,684,684,684,684,684,
-685,685,685,685,115,115,115,115,115,115,115,115,115,115,115,115,
-686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,
-686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,
-686,686,686,687,688,688,686,115,115,115,115,115,115,115,115,115,
+679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,
+679,679,679,679,679,679,679,679,679,679,679,679,679,680,680,680,
+680,680,680,680,680,680,680,679,116,116,116,116,116,116,116,116,
+681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,
+681,681,681,681,681,681,682,682,682,682,682,682,682,682,682,682,
+682,683,683,683,683,684,684,684,684,684,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 163 */
-689,689,690,691,691,691,691,691,691,691,691,691,691,691,691,691,
-691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,
-691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,
-691,691,691,690,690,690,689,689,689,689,689,689,689,689,689,690,
-690,691,692,692,691,693,693,693,693,693,689,689,689,693,115,115,
-694,694,694,694,694,694,694,694,694,694,691,693,691,693,693,693,
-115,695,695,695,695,695,695,695,695,695,695,695,695,695,695,695,
-695,695,695,695,695,115,115,115,115,115,115,115,115,115,115,115,
+685,686,685,687,687,687,687,687,687,687,687,687,687,687,687,687,
+687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,
+687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,
+687,687,687,687,687,687,687,687,686,686,686,686,686,686,686,686,
+686,686,686,686,686,686,686,688,688,688,688,688,688,688,116,116,
+116,116,689,689,689,689,689,689,689,689,689,689,689,689,689,689,
+689,689,689,689,689,689,690,690,690,690,690,690,690,690,690,690,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,686,
/* block 164 */
+691,691,692,693,693,693,693,693,693,693,693,693,693,693,693,693,
+693,693,693,693,693,693,693,693,693,693,693,693,693,693,693,693,
+693,693,693,693,693,693,693,693,693,693,693,693,693,693,693,693,
+692,692,692,691,691,691,691,692,692,691,691,694,694,695,694,694,
+694,694,116,116,116,116,116,116,116,116,116,116,116,695,116,116,
696,696,696,696,696,696,696,696,696,696,696,696,696,696,696,696,
-696,696,115,696,696,696,696,696,696,696,696,696,696,696,696,696,
-696,696,696,696,696,696,696,696,696,696,696,696,697,697,697,698,
-698,698,697,697,698,697,698,698,699,699,699,699,699,699,698,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+696,696,696,696,696,696,696,696,696,116,116,116,116,116,116,116,
+697,697,697,697,697,697,697,697,697,697,116,116,116,116,116,116,
/* block 165 */
-700,700,700,700,700,700,700,115,700,115,700,700,700,700,115,700,
-700,700,700,700,700,700,700,700,700,700,700,700,700,700,115,700,
-700,700,700,700,700,700,700,700,700,701,115,115,115,115,115,115,
-702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,
-702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,
-702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,703,
-704,704,704,703,703,703,703,703,703,703,703,115,115,115,115,115,
-705,705,705,705,705,705,705,705,705,705,115,115,115,115,115,115,
+698,698,698,699,699,699,699,699,699,699,699,699,699,699,699,699,
+699,699,699,699,699,699,699,699,699,699,699,699,699,699,699,699,
+699,699,699,699,699,699,699,698,698,698,698,698,700,698,698,698,
+698,698,698,698,698,116,701,701,701,701,701,701,701,701,701,701,
+702,702,702,702,699,700,700,116,116,116,116,116,116,116,116,116,
+703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,
+703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,
+703,703,703,704,705,705,703,116,116,116,116,116,116,116,116,116,
/* block 166 */
-706,706,707,707,115,708,708,708,708,708,708,708,708,115,115,708,
-708,115,115,708,708,708,708,708,708,708,708,708,708,708,708,708,
-708,708,708,708,708,708,708,708,708,115,708,708,708,708,708,708,
-708,115,708,708,115,708,708,708,708,708,115,115,706,708,709,707,
-706,707,707,707,707,115,115,707,707,115,115,707,707,707,115,115,
-708,115,115,115,115,115,115,709,115,115,115,115,115,708,708,708,
-708,708,707,707,115,115,706,706,706,706,706,706,706,115,115,115,
-706,706,706,706,706,115,115,115,115,115,115,115,115,115,115,115,
+706,706,707,708,708,708,708,708,708,708,708,708,708,708,708,708,
+708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,
+708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,
+708,708,708,707,707,707,706,706,706,706,706,706,706,706,706,707,
+707,708,709,709,708,710,710,710,710,706,706,706,706,710,116,116,
+711,711,711,711,711,711,711,711,711,711,708,710,708,710,710,710,
+116,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,
+712,712,712,712,712,116,116,116,116,116,116,116,116,116,116,116,
/* block 167 */
-710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,
-710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,
-710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,
-710,710,710,710,710,711,711,711,712,712,712,712,712,712,712,712,
-711,711,712,712,712,711,712,710,710,710,710,713,713,713,713,713,
-714,714,714,714,714,714,714,714,714,714,115,713,115,713,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,
+713,713,116,713,713,713,713,713,713,713,713,713,713,713,713,713,
+713,713,713,713,713,713,713,713,713,713,713,713,714,714,714,715,
+715,715,714,714,715,714,715,715,716,716,716,716,716,716,715,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 168 */
-715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,
-715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,
-715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,
-716,717,717,718,718,718,718,718,718,717,718,717,717,716,717,718,
-718,717,718,718,715,715,719,715,115,115,115,115,115,115,115,115,
-720,720,720,720,720,720,720,720,720,720,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+717,717,717,717,717,717,717,116,717,116,717,717,717,717,116,717,
+717,717,717,717,717,717,717,717,717,717,717,717,717,717,116,717,
+717,717,717,717,717,717,717,717,717,718,116,116,116,116,116,116,
+719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,
+719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,
+719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,720,
+721,721,721,720,720,720,720,720,720,720,720,116,116,116,116,116,
+722,722,722,722,722,722,722,722,722,722,116,116,116,116,116,116,
/* block 169 */
-721,721,721,721,721,721,721,721,721,721,721,721,721,721,721,721,
-721,721,721,721,721,721,721,721,721,721,721,721,721,721,721,721,
-721,721,721,721,721,721,721,721,721,721,721,721,721,721,721,722,
-723,723,724,724,724,724,115,115,723,723,723,723,724,724,723,724,
-724,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,
-725,725,725,725,725,725,725,725,721,721,721,721,724,724,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+723,723,724,724,116,725,725,725,725,725,725,725,725,116,116,725,
+725,116,116,725,725,725,725,725,725,725,725,725,725,725,725,725,
+725,725,725,725,725,725,725,725,725,116,725,725,725,725,725,725,
+725,116,725,725,116,725,725,725,725,725,116,111,723,725,726,724,
+723,724,724,724,724,116,116,724,724,116,116,724,724,724,116,116,
+725,116,116,116,116,116,116,726,116,116,116,116,116,725,725,725,
+725,725,724,724,116,116,723,723,723,723,723,723,723,116,116,116,
+723,723,723,723,723,116,116,116,116,116,116,116,116,116,116,116,
/* block 170 */
-726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,
-726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,
-726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,
-727,727,727,728,728,728,728,728,728,728,728,727,727,728,727,728,
-728,729,729,729,726,115,115,115,115,115,115,115,115,115,115,115,
-730,730,730,730,730,730,730,730,730,730,115,115,115,115,115,115,
-369,369,369,369,369,369,369,369,369,369,369,369,369,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,
+727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,
+727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,
+727,727,727,727,727,728,728,728,729,729,729,729,729,729,729,729,
+728,728,729,729,729,728,729,727,727,727,727,730,730,730,730,730,
+731,731,731,731,731,731,731,731,731,731,116,730,116,730,729,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 171 */
-731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,
-731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,
-731,731,731,731,731,731,731,731,731,731,731,732,733,732,733,733,
-732,732,732,732,732,732,733,732,115,115,115,115,115,115,115,115,
-734,734,734,734,734,734,734,734,734,734,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+732,732,732,732,732,732,732,732,732,732,732,732,732,732,732,732,
+732,732,732,732,732,732,732,732,732,732,732,732,732,732,732,732,
+732,732,732,732,732,732,732,732,732,732,732,732,732,732,732,732,
+733,734,734,735,735,735,735,735,735,734,735,734,734,733,734,735,
+735,734,735,735,732,732,736,732,116,116,116,116,116,116,116,116,
+737,737,737,737,737,737,737,737,737,737,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 172 */
-735,735,735,735,735,735,735,735,735,735,735,735,735,735,735,735,
-735,735,735,735,735,735,735,735,735,735,115,115,115,736,736,736,
-737,737,736,736,736,736,737,736,736,736,736,736,115,115,115,115,
-738,738,738,738,738,738,738,738,738,738,739,739,740,740,740,741,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,
+738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,
+738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,739,
+740,740,741,741,741,741,116,116,740,740,740,740,741,741,740,741,
+741,742,742,742,742,742,742,742,742,742,742,742,742,742,742,742,
+742,742,742,742,742,742,742,742,738,738,738,738,741,741,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 173 */
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-742,742,742,742,742,742,742,742,742,742,742,742,742,742,742,742,
-742,742,742,742,742,742,742,742,742,742,742,742,742,742,742,742,
743,743,743,743,743,743,743,743,743,743,743,743,743,743,743,743,
743,743,743,743,743,743,743,743,743,743,743,743,743,743,743,743,
-744,744,744,744,744,744,744,744,744,744,745,745,745,745,745,745,
-745,745,745,115,115,115,115,115,115,115,115,115,115,115,115,746,
+743,743,743,743,743,743,743,743,743,743,743,743,743,743,743,743,
+744,744,744,745,745,745,745,745,745,745,745,744,744,745,744,745,
+745,746,746,746,743,116,116,116,116,116,116,116,116,116,116,116,
+747,747,747,747,747,747,747,747,747,747,116,116,116,116,116,116,
+373,373,373,373,373,373,373,373,373,373,373,373,373,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 174 */
-747,748,748,748,748,748,748,749,749,748,748,747,747,747,747,747,
-747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,
-747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,
-747,747,747,748,748,748,748,748,748,749,750,748,748,748,748,751,
-751,751,751,751,751,751,751,748,115,115,115,115,115,115,115,115,
-752,753,753,753,753,753,753,754,754,753,753,753,752,752,752,752,
-752,752,752,752,752,752,752,752,752,752,752,752,752,752,752,752,
-752,752,752,752,752,752,752,752,752,752,752,752,752,752,752,752,
+748,748,748,748,748,748,748,748,748,748,748,748,748,748,748,748,
+748,748,748,748,748,748,748,748,748,748,748,748,748,748,748,748,
+748,748,748,748,748,748,748,748,748,748,748,749,750,749,750,750,
+749,749,749,749,749,749,750,749,116,116,116,116,116,116,116,116,
+751,751,751,751,751,751,751,751,751,751,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 175 */
-752,752,752,752,115,115,755,755,755,755,753,753,753,753,753,753,
-753,753,753,753,753,753,753,754,753,753,756,756,756,115,756,756,
-756,756,756,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-757,757,757,757,757,757,757,757,757,757,757,757,757,757,757,757,
-757,757,757,757,757,757,757,757,757,757,757,757,757,757,757,757,
-757,757,757,757,757,757,757,757,757,757,757,757,757,757,757,757,
-757,757,757,757,757,757,757,757,757,115,115,115,115,115,115,115,
+752,752,752,752,752,752,752,752,752,752,752,752,752,752,752,752,
+752,752,752,752,752,752,752,752,752,752,752,116,116,753,753,753,
+754,754,753,753,753,753,754,753,753,753,753,753,116,116,116,116,
+755,755,755,755,755,755,755,755,755,755,756,756,757,757,757,758,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 176 */
-758,758,758,758,758,758,758,758,758,115,758,758,758,758,758,758,
-758,758,758,758,758,758,758,758,758,758,758,758,758,758,758,758,
-758,758,758,758,758,758,758,758,758,758,758,758,758,758,758,759,
-760,760,760,760,760,760,760,115,760,760,760,760,760,760,759,760,
-758,761,761,761,761,761,115,115,115,115,115,115,115,115,115,115,
-762,762,762,762,762,762,762,762,762,762,763,763,763,763,763,763,
-763,763,763,763,763,763,763,763,763,763,763,763,763,115,115,115,
-764,764,765,765,765,765,765,765,765,765,765,765,765,765,765,765,
+759,759,759,759,759,759,759,759,759,759,759,759,759,759,759,759,
+759,759,759,759,759,759,759,759,759,759,759,759,759,759,759,759,
+759,759,759,759,759,759,759,759,759,759,759,759,760,760,760,761,
+761,761,761,761,761,761,761,761,760,761,761,762,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 177 */
-765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,
-115,115,766,766,766,766,766,766,766,766,766,766,766,766,766,766,
-766,766,766,766,766,766,766,766,115,767,766,766,766,766,766,766,
-766,767,766,766,767,766,766,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,
+763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,
+764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,
+764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,
+765,765,765,765,765,765,765,765,765,765,766,766,766,766,766,766,
+766,766,766,116,116,116,116,116,116,116,116,116,116,116,116,767,
/* block 178 */
-768,768,768,768,768,768,768,115,768,768,115,768,768,768,768,768,
+768,769,769,769,769,769,769,769,769,769,769,768,768,768,768,768,
768,768,768,768,768,768,768,768,768,768,768,768,768,768,768,768,
768,768,768,768,768,768,768,768,768,768,768,768,768,768,768,768,
-768,769,769,769,769,769,769,115,115,115,769,115,769,769,115,769,
-769,769,769,769,769,769,770,769,115,115,115,115,115,115,115,115,
-771,771,771,771,771,771,771,771,771,771,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+768,768,768,769,769,769,769,769,769,770,771,769,769,769,769,772,
+772,772,772,772,772,772,772,769,116,116,116,116,116,116,116,116,
+773,774,774,774,774,774,774,775,775,774,774,774,773,773,773,773,
+773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,
+773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,
/* block 179 */
-772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,
-772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,
-772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,
-772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,
-772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,
-772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,
-772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,
-772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,
+773,773,773,773,116,116,776,776,776,776,774,774,774,774,774,774,
+774,774,774,774,774,774,774,775,774,774,777,777,777,773,777,777,
+777,777,777,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+778,778,778,778,778,778,778,778,778,778,778,778,778,778,778,778,
+778,778,778,778,778,778,778,778,778,778,778,778,778,778,778,778,
+778,778,778,778,778,778,778,778,778,778,778,778,778,778,778,778,
+778,778,778,778,778,778,778,778,778,116,116,116,116,116,116,116,
/* block 180 */
-772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,
-772,772,772,772,772,772,772,772,772,772,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+779,779,779,779,779,779,779,779,779,116,779,779,779,779,779,779,
+779,779,779,779,779,779,779,779,779,779,779,779,779,779,779,779,
+779,779,779,779,779,779,779,779,779,779,779,779,779,779,779,780,
+781,781,781,781,781,781,781,116,781,781,781,781,781,781,780,781,
+779,782,782,782,782,782,116,116,116,116,116,116,116,116,116,116,
+783,783,783,783,783,783,783,783,783,783,784,784,784,784,784,784,
+784,784,784,784,784,784,784,784,784,784,784,784,784,116,116,116,
+785,785,786,786,786,786,786,786,786,786,786,786,786,786,786,786,
/* block 181 */
-773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,
-773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,
-773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,
-773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,
-773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,
-773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,
-773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,115,
-774,774,774,774,774,115,115,115,115,115,115,115,115,115,115,115,
+786,786,786,786,786,786,786,786,786,786,786,786,786,786,786,786,
+116,116,787,787,787,787,787,787,787,787,787,787,787,787,787,787,
+787,787,787,787,787,787,787,787,116,788,787,787,787,787,787,787,
+787,788,787,787,788,787,787,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 182 */
-772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,
-772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,
-772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,
-772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,
-772,772,772,772,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+789,789,789,789,789,789,789,116,789,789,116,789,789,789,789,789,
+789,789,789,789,789,789,789,789,789,789,789,789,789,789,789,789,
+789,789,789,789,789,789,789,789,789,789,789,789,789,789,789,789,
+789,790,790,790,790,790,790,116,116,116,790,116,790,790,116,790,
+790,790,790,790,790,790,791,790,116,116,116,116,116,116,116,116,
+792,792,792,792,792,792,792,792,792,792,116,116,116,116,116,116,
+793,793,793,793,793,793,116,793,793,116,793,793,793,793,793,793,
+793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,
/* block 183 */
-775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,
-775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,
-775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,
-775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,
-775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,
-775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,
-775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,
-775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,
+793,793,793,793,793,793,793,793,793,793,794,794,794,794,794,116,
+795,795,116,794,794,795,794,795,793,116,116,116,116,116,116,116,
+796,796,796,796,796,796,796,796,796,796,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 184 */
-775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,
-775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,
-775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,
+797,797,797,798,798,799,799,800,800,116,116,116,116,116,116,116,
/* block 185 */
-776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,
-776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,
-776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,
-776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,
-776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,
-776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,
-776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,
-776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,
+801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,
+801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,
+801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,
+801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,
+801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,
+801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,
+801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,
+801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,
/* block 186 */
-776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,
-776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,
-776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,
-776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,
-776,776,776,776,776,776,776,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,
+801,801,801,801,801,801,801,801,801,801,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 187 */
-530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,
-530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,
-530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,
-530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,
-530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,
-530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,
-530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,
-530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,
+802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,
+802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,
+802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,
+802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,
+802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,
+802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,
+802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,116,
+803,803,803,803,803,116,116,116,116,116,116,116,116,116,116,116,
/* block 188 */
-530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,
-530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,
-530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,
-530,530,530,530,530,530,530,530,530,115,115,115,115,115,115,115,
-777,777,777,777,777,777,777,777,777,777,777,777,777,777,777,777,
-777,777,777,777,777,777,777,777,777,777,777,777,777,777,777,115,
-778,778,778,778,778,778,778,778,778,778,115,115,115,115,779,779,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,
+801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,
+801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,
+801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,
+801,801,801,801,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 189 */
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-780,780,780,780,780,780,780,780,780,780,780,780,780,780,780,780,
-780,780,780,780,780,780,780,780,780,780,780,780,780,780,115,115,
-781,781,781,781,781,782,115,115,115,115,115,115,115,115,115,115,
+804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,
+804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,
+804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,
+804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,
+804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,
+804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,
+804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,
+804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,
/* block 190 */
-783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,
-783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,
-783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,
-784,784,784,784,784,784,784,785,785,785,785,785,786,786,786,786,
-787,787,787,787,785,786,115,115,115,115,115,115,115,115,115,115,
-788,788,788,788,788,788,788,788,788,788,115,789,789,789,789,789,
-789,789,115,783,783,783,783,783,783,783,783,783,783,783,783,783,
-783,783,783,783,783,783,783,783,115,115,115,115,115,783,783,783,
+804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,
+804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,
+804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 191 */
-783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,
+805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,
+805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,
+805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,
+805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,
+805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,
+805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,
+805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,
/* block 192 */
-790,790,790,790,790,790,790,790,790,790,790,790,790,790,790,790,
-790,790,790,790,790,790,790,790,790,790,790,790,790,790,790,790,
-790,790,790,790,790,790,790,790,790,790,790,790,790,790,790,790,
-790,790,790,790,790,790,790,790,790,790,790,790,790,790,790,790,
-790,790,790,790,790,115,115,115,115,115,115,115,115,115,115,115,
-790,791,791,791,791,791,791,791,791,791,791,791,791,791,791,791,
-791,791,791,791,791,791,791,791,791,791,791,791,791,791,791,791,
-791,791,791,791,791,791,791,791,791,791,791,791,791,791,791,115,
+805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,
+805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,
+805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,
+805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,
+805,805,805,805,805,805,805,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 193 */
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,792,
-792,792,792,793,793,793,793,793,793,793,793,793,793,793,793,793,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-794,795,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,
+538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,
+538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,
+538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,
+538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,
+538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,
+538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,
+538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,
/* block 194 */
-796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,
-796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,
-796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,
-796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,
-796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,
-796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,
-796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,
-796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,
+538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,
+538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,
+538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,
+538,538,538,538,538,538,538,538,538,116,116,116,116,116,116,116,
+806,806,806,806,806,806,806,806,806,806,806,806,806,806,806,806,
+806,806,806,806,806,806,806,806,806,806,806,806,806,806,806,116,
+807,807,807,807,807,807,807,807,807,807,116,116,116,116,808,808,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 195 */
-796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,
-796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,
-796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,
-796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,
-796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,
-796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,
-796,796,796,796,796,796,796,796,796,796,796,796,796,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+809,809,809,809,809,809,809,809,809,809,809,809,809,809,809,809,
+809,809,809,809,809,809,809,809,809,809,809,809,809,809,116,116,
+810,810,810,810,810,811,116,116,116,116,116,116,116,116,116,116,
/* block 196 */
-796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,
-796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,
-796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,
-796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,
-796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,
-796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,
-796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,
-796,796,796,115,115,115,115,115,115,115,115,115,115,115,115,115,
+812,812,812,812,812,812,812,812,812,812,812,812,812,812,812,812,
+812,812,812,812,812,812,812,812,812,812,812,812,812,812,812,812,
+812,812,812,812,812,812,812,812,812,812,812,812,812,812,812,812,
+813,813,813,813,813,813,813,814,814,814,814,814,815,815,815,815,
+816,816,816,816,814,815,116,116,116,116,116,116,116,116,116,116,
+817,817,817,817,817,817,817,817,817,817,116,818,818,818,818,818,
+818,818,116,812,812,812,812,812,812,812,812,812,812,812,812,812,
+812,812,812,812,812,812,812,812,116,116,116,116,116,812,812,812,
/* block 197 */
-509,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,
-507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,
-507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,
-507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,
-507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,
-507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,
-507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,
-507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,
+812,812,812,812,812,812,812,812,812,812,812,812,812,812,812,812,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 198 */
-507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,
-507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,
-507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,
-507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,
-507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,
-507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,
-507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,
-507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,
+819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,
+820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,
+820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,
/* block 199 */
-507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,
-507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,
+821,821,821,821,821,821,821,821,821,821,821,821,821,821,821,821,
+821,821,821,821,821,821,821,822,822,822,822,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 200 */
-797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,
-797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,
-797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,
-797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,
-797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,
-797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,
-797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,
-797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,
+823,823,823,823,823,823,823,823,823,823,823,823,823,823,823,823,
+823,823,823,823,823,823,823,823,823,823,823,823,823,823,823,823,
+823,823,823,823,823,823,823,823,823,823,823,823,823,823,823,823,
+823,823,823,823,823,823,823,823,823,823,823,823,823,823,823,823,
+823,823,823,823,823,116,116,116,116,116,116,116,116,116,116,116,
+823,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,
+824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,
+824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,116,
/* block 201 */
-797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,
-797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,
-797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,
-797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,
-797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,
-797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,
-797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,
-797,797,797,797,797,797,797,797,797,797,797,797,115,115,115,115,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,825,
+825,825,825,826,826,826,826,826,826,826,826,826,826,826,826,826,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+827,828,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 202 */
-798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,
-798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,
-798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,
-798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,
-798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,
-798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,
-798,798,798,798,798,798,798,798,798,798,798,115,115,115,115,115,
-798,798,798,798,798,798,798,798,798,798,798,798,798,115,115,115,
+829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,
+829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,
+829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,
+829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,
+829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,
+829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,
+829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,
+829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,
/* block 203 */
-798,798,798,798,798,798,798,798,798,115,115,115,115,115,115,115,
-798,798,798,798,798,798,798,798,798,798,115,115,799,800,800,801,
- 22, 22, 22, 22,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,
+829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,
+829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,
+829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,
+829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,
+829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,
+829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,
+829,829,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 204 */
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19,115,115,115,115,115,115,115,115,115,115,
+829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,
+829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,
+829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,
+829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,
+829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,
+829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,
+829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,
+829,829,829,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 205 */
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19,115,115, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19,802,433,110,110,110, 19, 19, 19,433,802,802,
-802,802,802, 22, 22, 22, 22, 22, 22, 22, 22,110,110,110,110,110,
+517,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
+515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
+515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
+515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
+515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
+515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
+515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
+515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
/* block 206 */
-110,110,110, 19, 19,110,110,110,110,110,110,110, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,110,110,110,110, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
+515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
+515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
+515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
+515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
+515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
+515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
+515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
/* block 207 */
-596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,
-596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,
-596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,
-596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,
-596,596,803,803,803,596,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
+515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,
/* block 208 */
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19,115,115,115,115,115,115,115,115,115,
- 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
- 23, 23,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,
+830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,
+830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,
+830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,
+830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,
+830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,
+830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,
+830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,
/* block 209 */
-466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,
-466,466,466,466,466,466,466,466,466,466,467,467,467,467,467,467,
-467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,
-467,467,467,467,466,466,466,466,466,466,466,466,466,466,466,466,
-466,466,466,466,466,466,466,466,466,466,466,466,466,466,467,467,
-467,467,467,467,467,115,467,467,467,467,467,467,467,467,467,467,
-467,467,467,467,467,467,467,467,466,466,466,466,466,466,466,466,
-466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,
+830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,
+830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,
+830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,
+830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,
+830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,
+830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,
+830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,
+830,830,830,830,830,830,830,830,830,830,830,830,116,116,116,116,
/* block 210 */
-466,466,467,467,467,467,467,467,467,467,467,467,467,467,467,467,
-467,467,467,467,467,467,467,467,467,467,467,467,466,115,466,466,
-115,115,466,115,115,466,466,115,115,466,466,466,466,115,466,466,
-466,466,466,466,466,466,467,467,467,467,115,467,115,467,467,467,
-467,467,467,467,115,467,467,467,467,467,467,467,467,467,467,467,
-466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,
-466,466,466,466,466,466,466,466,466,466,467,467,467,467,467,467,
-467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,
+831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,
+831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,
+831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,
+831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,
+831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,
+831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,
+831,831,831,831,831,831,831,831,831,831,831,116,116,116,116,116,
+831,831,831,831,831,831,831,831,831,831,831,831,831,116,116,116,
/* block 211 */
-467,467,467,467,466,466,115,466,466,466,466,115,115,466,466,466,
-466,466,466,466,466,115,466,466,466,466,466,466,466,115,467,467,
-467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,
-467,467,467,467,467,467,467,467,466,466,115,466,466,466,466,115,
-466,466,466,466,466,115,466,115,115,115,466,466,466,466,466,466,
-466,115,467,467,467,467,467,467,467,467,467,467,467,467,467,467,
-467,467,467,467,467,467,467,467,467,467,467,467,466,466,466,466,
-466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,
+831,831,831,831,831,831,831,831,831,116,116,116,116,116,116,116,
+831,831,831,831,831,831,831,831,831,831,116,116,832,833,833,834,
+ 23, 23, 23, 23,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 212 */
-466,466,466,466,466,466,467,467,467,467,467,467,467,467,467,467,
-467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,
-466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,
-466,466,466,466,466,466,466,466,466,466,467,467,467,467,467,467,
-467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,
-467,467,467,467,466,466,466,466,466,466,466,466,466,466,466,466,
-466,466,466,466,466,466,466,466,466,466,466,466,466,466,467,467,
-467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19,116,116,116,116,116,116,116,116,116,116,
/* block 213 */
-467,467,467,467,467,467,467,467,466,466,466,466,466,466,466,466,
-466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,
-466,466,467,467,467,467,467,467,467,467,467,467,467,467,467,467,
-467,467,467,467,467,467,467,467,467,467,467,467,466,466,466,466,
-466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,
-466,466,466,466,466,466,467,467,467,467,467,467,467,467,467,467,
-467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,
-466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19,116,116, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19,835,438,111,111,111, 19, 19, 19,438,835,835,
+835,835,835, 23, 23, 23, 23, 23, 23, 23, 23,111,111,111,111,111,
/* block 214 */
-466,466,466,466,466,466,466,466,466,466,467,467,467,467,467,467,
-467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,
-467,467,467,467,467,467,115,115,466,466,466,466,466,466,466,466,
-466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,
-466, 8,467,467,467,467,467,467,467,467,467,467,467,467,467,467,
-467,467,467,467,467,467,467,467,467,467,467, 8,467,467,467,467,
-467,467,466,466,466,466,466,466,466,466,466,466,466,466,466,466,
-466,466,466,466,466,466,466,466,466,466,466, 8,467,467,467,467,
+111,111,111, 19, 19,111,111,111,111,111,111,111, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,111,111,111,111, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 215 */
-467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,
-467,467,467,467,467, 8,467,467,467,467,467,467,466,466,466,466,
-466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,
-466,466,466,466,466, 8,467,467,467,467,467,467,467,467,467,467,
-467,467,467,467,467,467,467,467,467,467,467,467,467,467,467, 8,
-467,467,467,467,467,467,466,466,466,466,466,466,466,466,466,466,
-466,466,466,466,466,466,466,466,466,466,466,466,466,466,466, 8,
-467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,
+604,604,604,604,604,604,604,604,604,604,604,604,604,604,604,604,
+604,604,604,604,604,604,604,604,604,604,604,604,604,604,604,604,
+604,604,604,604,604,604,604,604,604,604,604,604,604,604,604,604,
+604,604,604,604,604,604,604,604,604,604,604,604,604,604,604,604,
+604,604,836,836,836,604,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 216 */
-467,467,467,467,467,467,467,467,467, 8,467,467,467,467,467,467,
-466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,
-466,466,466,466,466,466,466,466,466, 8,467,467,467,467,467,467,
-467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,
-467,467,467, 8,467,467,467,467,467,467,466,467,115,115, 10, 10,
- 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
- 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
- 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 217 */
-804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,
-804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,
-804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,
-804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,
-804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,
-804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,
-804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,
-804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19,116,116,116,116,116,116,116,116,116,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24,116,116,116,116,116,116,116,
/* block 218 */
-805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,
-805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,
-805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,
-805,805,805,805,805,805,805,804,804,804,804,805,805,805,805,805,
-805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,
-805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,
-805,805,805,805,805,805,805,805,805,805,805,805,805,804,804,804,
-804,804,804,804,804,805,804,804,804,804,804,804,804,804,804,804,
+472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,
+472,472,472,472,472,472,472,472,472,472,473,473,473,473,473,473,
+473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,
+473,473,473,473,472,472,472,472,472,472,472,472,472,472,472,472,
+472,472,472,472,472,472,472,472,472,472,472,472,472,472,473,473,
+473,473,473,473,473,116,473,473,473,473,473,473,473,473,473,473,
+473,473,473,473,473,473,473,473,472,472,472,472,472,472,472,472,
+472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,
/* block 219 */
-804,804,804,804,805,804,804,806,806,806,806,806,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,805,805,805,805,805,
-115,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+472,472,473,473,473,473,473,473,473,473,473,473,473,473,473,473,
+473,473,473,473,473,473,473,473,473,473,473,473,472,116,472,472,
+116,116,472,116,116,472,472,116,116,472,472,472,472,116,472,472,
+472,472,472,472,472,472,473,473,473,473,116,473,116,473,473,473,
+473,473,473,473,116,473,473,473,473,473,473,473,473,473,473,473,
+472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,
+472,472,472,472,472,472,472,472,472,472,473,473,473,473,473,473,
+473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,
/* block 220 */
-807,807,807,807,807,807,807,115,807,807,807,807,807,807,807,807,
-807,807,807,807,807,807,807,807,807,115,115,807,807,807,807,807,
-807,807,115,807,807,115,807,807,807,807,807,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+473,473,473,473,472,472,116,472,472,472,472,116,116,472,472,472,
+472,472,472,472,472,116,472,472,472,472,472,472,472,116,473,473,
+473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,
+473,473,473,473,473,473,473,473,472,472,116,472,472,472,472,116,
+472,472,472,472,472,116,472,116,116,116,472,472,472,472,472,472,
+472,116,473,473,473,473,473,473,473,473,473,473,473,473,473,473,
+473,473,473,473,473,473,473,473,473,473,473,473,472,472,472,472,
+472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,
/* block 221 */
-808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,
-808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,
-808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,
-808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,
-808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,
-808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,
-808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,
-808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,
+472,472,472,472,472,472,473,473,473,473,473,473,473,473,473,473,
+473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,
+472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,
+472,472,472,472,472,472,472,472,472,472,473,473,473,473,473,473,
+473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,
+473,473,473,473,472,472,472,472,472,472,472,472,472,472,472,472,
+472,472,472,472,472,472,472,472,472,472,472,472,472,472,473,473,
+473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,
/* block 222 */
-808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,
-808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,
-808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,
-808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,
-808,808,808,808,808,115,115,809,809,809,809,809,809,809,809,809,
-810,810,810,810,810,810,810,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+473,473,473,473,473,473,473,473,472,472,472,472,472,472,472,472,
+472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,
+472,472,473,473,473,473,473,473,473,473,473,473,473,473,473,473,
+473,473,473,473,473,473,473,473,473,473,473,473,472,472,472,472,
+472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,
+472,472,472,472,472,472,473,473,473,473,473,473,473,473,473,473,
+473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,
+472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,
/* block 223 */
-811,811,811,811,811,811,811,811,811,811,811,811,811,811,811,811,
-811,811,811,811,811,811,811,811,811,811,811,811,811,811,811,811,
-811,811,812,812,812,812,812,812,812,812,812,812,812,812,812,812,
-812,812,812,812,812,812,812,812,812,812,812,812,812,812,812,812,
-812,812,812,812,813,813,813,813,813,813,813,115,115,115,115,115,
-814,814,814,814,814,814,814,814,814,814,115,115,115,115,815,815,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+472,472,472,472,472,472,472,472,472,472,473,473,473,473,473,473,
+473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,
+473,473,473,473,473,473,116,116,472,472,472,472,472,472,472,472,
+472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,
+472, 8,473,473,473,473,473,473,473,473,473,473,473,473,473,473,
+473,473,473,473,473,473,473,473,473,473,473, 8,473,473,473,473,
+473,473,472,472,472,472,472,472,472,472,472,472,472,472,472,472,
+472,472,472,472,472,472,472,472,472,472,472, 8,473,473,473,473,
/* block 224 */
-216,216,216,216,115,216,216,216,216,216,216,216,216,216,216,216,
-216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-115,216,216,115,216,115,115,216,115,216,216,216,216,216,216,216,
-216,216,216,115,216,216,216,216,115,216,115,216,115,115,115,115,
-115,115,216,115,115,115,115,216,115,216,115,216,115,216,216,216,
-115,216,216,115,216,115,115,216,115,216,115,216,115,216,115,216,
-115,216,216,115,216,115,115,216,216,216,216,115,216,216,216,216,
-216,216,216,115,216,216,216,216,115,216,216,216,216,115,216,115,
+473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,
+473,473,473,473,473, 8,473,473,473,473,473,473,472,472,472,472,
+472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,
+472,472,472,472,472, 8,473,473,473,473,473,473,473,473,473,473,
+473,473,473,473,473,473,473,473,473,473,473,473,473,473,473, 8,
+473,473,473,473,473,473,472,472,472,472,472,472,472,472,472,472,
+472,472,472,472,472,472,472,472,472,472,472,472,472,472,472, 8,
+473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,
/* block 225 */
-216,216,216,216,216,216,216,216,216,216,115,216,216,216,216,216,
-216,216,216,216,216,216,216,216,216,216,216,216,115,115,115,115,
-115,216,216,216,115,216,216,216,216,216,115,216,216,216,216,216,
-216,216,216,216,216,216,216,216,216,216,216,216,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-210,210,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+473,473,473,473,473,473,473,473,473, 8,473,473,473,473,473,473,
+472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,
+472,472,472,472,472,472,472,472,472, 8,473,473,473,473,473,473,
+473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,
+473,473,473, 8,473,473,473,473,473,473,472,473,116,116, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
/* block 226 */
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,
+837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,
+837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,
+837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,
+837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,
+837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,
+837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,
+837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,
/* block 227 */
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19,115,115,115,115,115,115,115,115,115,115,115,115,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,
-115, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
-115, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
-115, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19,115,115,115,115,115,115,115,115,115,115,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,837,837,837,837,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,837,837,837,
+837,837,837,837,837,838,837,837,837,837,837,837,837,837,837,837,
/* block 228 */
- 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,115,115,115,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+837,837,837,837,838,837,837,839,839,839,839,839,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,838,838,838,838,838,
+116,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 229 */
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,816,816,816,816,816,816,816,816,816,816,
-816,816,816,816,816,816,816,816,816,816,816,816,816,816,816,816,
+840,840,840,840,840,840,840,116,840,840,840,840,840,840,840,840,
+840,840,840,840,840,840,840,840,840,116,116,840,840,840,840,840,
+840,840,116,840,840,116,840,840,840,840,840,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 230 */
-817, 19, 19,115,115,115,115,115,115,115,115,115,115,115,115,115,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,
- 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,115,115,115,
- 19, 19,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
- 19, 19, 19, 19, 19, 19,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,
+841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,
+841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,
+841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,
+841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,
+841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,
+841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,
+841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,
/* block 231 */
- 19, 19, 19, 19, 19, 19, 19, 19,479, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,479, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19,479, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,
+841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,
+841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,
+841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,
+841,841,841,841,841,116,116,842,842,842,842,842,842,842,842,842,
+843,843,843,843,843,843,843,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 232 */
- 19, 19, 19, 19, 19,478, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19,479, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19,479, 19, 19, 19,479, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19,478,478,478, 19, 19,478, 19, 19,478,478,478, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,479, 19,479, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,818,818,818,818,818,
+844,844,844,844,844,844,844,844,844,844,844,844,844,844,844,844,
+844,844,844,844,844,844,844,844,844,844,844,844,844,844,844,844,
+844,844,845,845,845,845,845,845,845,845,845,845,845,845,845,845,
+845,845,845,845,845,845,845,845,845,845,845,845,845,845,845,845,
+845,845,845,845,846,846,846,846,846,846,846,116,116,116,116,116,
+847,847,847,847,847,847,847,847,847,847,116,116,116,116,848,848,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 233 */
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19,478,478, 19, 19,478,478,478,478,478,478,478,478,478,478,
-478, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19,819,819,819,819, 19, 19, 19, 19,478, 19,
-478,478,478,478,478,478,478,478,478, 19, 19, 19,478, 19, 19, 19,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
/* block 234 */
- 19,478,478,478, 19,478,478,478, 19, 19, 19,479, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,478, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,479,479, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 19, 24, 24, 24,
+ 5, 24, 24, 24, 24,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 235 */
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19,479, 19, 19, 19, 19,479, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19,478,478, 19, 19, 19, 19,478, 19, 19, 19, 19, 19,
+217,217,217,217,116,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+116,217,217,116,217,116,116,217,116,217,217,217,217,217,217,217,
+217,217,217,116,217,217,217,217,116,217,116,217,116,116,116,116,
+116,116,217,116,116,116,116,217,116,217,116,217,116,217,217,217,
+116,217,217,116,217,116,116,217,116,217,116,217,116,217,116,217,
+116,217,217,116,217,116,116,217,217,217,217,116,217,217,217,217,
+217,217,217,116,217,217,217,217,116,217,217,217,217,116,217,116,
/* block 236 */
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
-478, 19, 19, 19, 19,478,478, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19,479, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+217,217,217,217,217,217,217,217,217,217,116,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217,217,116,116,116,116,
+116,217,217,217,116,217,217,217,217,217,116,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217,217,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+211,211,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
/* block 237 */
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19,478,478,478, 19, 19, 19,478,478,478,478,478,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,849,849,849,849,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
/* block 238 */
-479, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19,479, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19,478, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19,478,478,478, 19, 19, 19, 19, 19, 19, 19, 19, 19,
-478, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,478, 19, 19, 19,
- 19, 19, 19, 19, 19,115,115,115,115,115,115,115,115,115,115,115,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,
- 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,115,115,115,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20,849,849,849,849,849,849,849,849,849,849,849,849,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,849,
+849, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+849, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+849, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20,849,849,849,849,849,849,849,849,849,849,
/* block 239 */
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,849,849,849,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19,115,115,115,115,115,115,115,115,115,115,115,115,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,849,849,849,849,
+ 20, 20, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20,
/* block 240 */
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 19,
+ 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,849,849,849,
+849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,
+849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,
+849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,
+849,849,849,849,849,849,850,850,850,850,850,850,850,850,850,850,
+850,850,850,850,850,850,850,850,850,850,850,850,850,850,850,850,
/* block 241 */
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,115,115,115,115,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,115,115,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+851, 20, 20,849,849,849,849,849,849,849,849,849,849,849,849,849,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20,
+ 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 19,849,849,849,849,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19,849,849,849,849,849,849,849,
+ 20, 20,849,849,849,849,849,849,849,849,849,849,849,849,849,849,
+ 20, 20, 20, 20, 20, 20,849,849,849,849,849,849,849,849,849,849,
+849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,
/* block 242 */
- 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,115,115,115,115,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,
+849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,
+849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,
+849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,
+849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,
+849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,
+849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,
+849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,
/* block 243 */
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,
- 19, 19, 19, 19, 19, 19, 19, 19,478,478,478,478,478, 19,478,478,
- 19, 19, 19, 19, 19, 19,478, 19, 19, 19, 19, 19, 19, 19, 19, 19,
-478,478,478,478,478,478,478,478,478,478, 19, 19, 19,478,478,115,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
/* block 244 */
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
- 19,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
- 19,478,478,478,478,478,478,478,478,478,478,478,478,478, 19, 19,
- 19, 19, 19, 19, 19, 19, 19,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,852,852,852,852,852,
/* block 245 */
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 19, 19,
+ 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
/* block 246 */
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,115,115,115,115,115,115,115,115,115,115,115,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
/* block 247 */
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,115,115,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20,849,849,849,849,849,849,849,849,849,849,849,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,849,849,849,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,849,849,849,849,849,849,
/* block 248 */
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19,849,849,849,849,849,849,849,849,849,849,849,849,
/* block 249 */
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 20, 20, 20, 20,849,849,849,849,849,849,849,
+849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,
+849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,
/* block 250 */
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,515,515,515,515,515,515,515,515,515,515,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,849,849,849,849,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19,849,849,849,849,849,849,849,849,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,849,849,849,849,849,849,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
/* block 251 */
-465, 22,465,465,465,465,465,465,465,465,465,465,465,465,465,465,
-465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,
-820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,
-820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,
-820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,
-820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,
-820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,
-820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,
+ 19, 19, 19, 19, 19, 19, 19, 19,849,849,849,849,849,849,849,849,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,849,849,
+849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,
+849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,
+849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,
+849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,
+849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,
/* block 252 */
-465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,
-465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,
-465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,
-465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,
-465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,
-465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,
-465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,
-465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,849,849,849,849,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 19, 20, 20, 20,849,
+ 20, 20, 20, 20, 20, 20, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20,849,849, 20, 20, 20, 20,849,849,849, 20,849, 20, 20, 20, 20,
/* block 253 */
-110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
-110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
-110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
-110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
-110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
-110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
-110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
-110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20,849,849,849,849,849,849,849,849,849,849,849,849,849,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,849,849,849,849,849,849,
+ 20, 20, 20,849,849,849,849,849,849,849,849,849,849,849,849,849,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
/* block 254 */
-110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
-110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
-110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
-110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
-110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
-110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
-110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
-465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,
+849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,
+849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,
+849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,
+849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,
+849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,
+849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,849,849,
+849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,
/* block 255 */
-589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,
-589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,
-589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,
-589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,
-589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,
-589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,
-589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,
-589,589,589,589,589,589,589,589,589,589,589,589,589,589,115,115,
+849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,
+849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,
+849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,
+849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,
+849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,
+849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,
+849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,
+849,849,849,849,849,849,849,849,849,849,849,849,849,849,116,116,
+
+/* block 256 */
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+
+/* block 257 */
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,116,116,116,116,116,116,116,116,116,116,116,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+
+/* block 258 */
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,116,116,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+
+/* block 259 */
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+
+/* block 260 */
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+
+/* block 261 */
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+
+/* block 262 */
+471, 23,471,471,471,471,471,471,471,471,471,471,471,471,471,471,
+471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,
+853,853,853,853,853,853,853,853,853,853,853,853,853,853,853,853,
+853,853,853,853,853,853,853,853,853,853,853,853,853,853,853,853,
+853,853,853,853,853,853,853,853,853,853,853,853,853,853,853,853,
+853,853,853,853,853,853,853,853,853,853,853,853,853,853,853,853,
+853,853,853,853,853,853,853,853,853,853,853,853,853,853,853,853,
+853,853,853,853,853,853,853,853,853,853,853,853,853,853,853,853,
+
+/* block 263 */
+471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,
+471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,
+471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,
+471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,
+471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,
+471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,
+471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,
+471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,
+
+/* block 264 */
+111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
+111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
+111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
+111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
+111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
+111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
+111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
+111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
+
+/* block 265 */
+111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
+111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
+111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
+111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
+111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
+111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
+111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
+471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,
+
+/* block 266 */
+597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,
+597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,
+597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,
+597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,
+597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,
+597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,
+597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,
+597,597,597,597,597,597,597,597,597,597,597,597,597,597,116,116,
};
diff --git a/thirdparty/pcre2/src/pcre2_ucp.h b/thirdparty/pcre2/src/pcre2_ucp.h
index defba4c10e..0c330edcb2 100644
--- a/thirdparty/pcre2/src/pcre2_ucp.h
+++ b/thirdparty/pcre2/src/pcre2_ucp.h
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016 University of Cambridge
+ New API code Copyright (c) 2016-2018 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -100,27 +100,25 @@ enum {
ucp_Zs /* Space separator */
};
-/* These are grapheme break properties. */
+/* These are grapheme break properties. The Extended Pictographic property
+comes from the emoji-data.txt file. */
enum {
- ucp_gbCR, /* 0 */
- ucp_gbLF, /* 1 */
- ucp_gbControl, /* 2 */
- ucp_gbExtend, /* 3 */
- ucp_gbPrepend, /* 4 */
- ucp_gbSpacingMark, /* 5 */
- ucp_gbL, /* 6 Hangul syllable type L */
- ucp_gbV, /* 7 Hangul syllable type V */
- ucp_gbT, /* 8 Hangul syllable type T */
- ucp_gbLV, /* 9 Hangul syllable type LV */
- ucp_gbLVT, /* 10 Hangul syllable type LVT */
- ucp_gbRegionalIndicator, /* 11 */
- ucp_gbOther, /* 12 */
- ucp_gbE_Base, /* 13 */
- ucp_gbE_Modifier, /* 14 */
- ucp_gbE_Base_GAZ, /* 15 */
- ucp_gbZWJ, /* 16 */
- ucp_gbGlue_After_Zwj /* 17 */
+ ucp_gbCR, /* 0 */
+ ucp_gbLF, /* 1 */
+ ucp_gbControl, /* 2 */
+ ucp_gbExtend, /* 3 */
+ ucp_gbPrepend, /* 4 */
+ ucp_gbSpacingMark, /* 5 */
+ ucp_gbL, /* 6 Hangul syllable type L */
+ ucp_gbV, /* 7 Hangul syllable type V */
+ ucp_gbT, /* 8 Hangul syllable type T */
+ ucp_gbLV, /* 9 Hangul syllable type LV */
+ ucp_gbLVT, /* 10 Hangul syllable type LVT */
+ ucp_gbRegionalIndicator, /* 11 */
+ ucp_gbOther, /* 12 */
+ ucp_gbZWJ, /* 13 */
+ ucp_gbExtended_Pictographic /* 14 */
};
/* These are the script identifications. */
@@ -274,7 +272,15 @@ enum {
ucp_Masaram_Gondi,
ucp_Nushu,
ucp_Soyombo,
- ucp_Zanabazar_Square
+ ucp_Zanabazar_Square,
+ /* New for Unicode 11.0.0 */
+ ucp_Dogra,
+ ucp_Gunjala_Gondi,
+ ucp_Hanifi_Rohingya,
+ ucp_Makasar,
+ ucp_Medefaidrin,
+ ucp_Old_Sogdian,
+ ucp_Sogdian
};
#endif /* PCRE2_UCP_H_IDEMPOTENT_GUARD */
diff --git a/thirdparty/pcre2/src/sljit/sljitConfigInternal.h b/thirdparty/pcre2/src/sljit/sljitConfigInternal.h
index e13282c842..f5703e8e7f 100644
--- a/thirdparty/pcre2/src/sljit/sljitConfigInternal.h
+++ b/thirdparty/pcre2/src/sljit/sljitConfigInternal.h
@@ -66,7 +66,7 @@
SLJIT_RETURN_ADDRESS_OFFSET : a return instruction always adds this offset to the return address
Other macros:
- SLJIT_FUNC : calling convention attribute for both calling JIT form C and C calling back from JIT
+ SLJIT_FUNC : calling convention attribute for both calling JIT from C and C calling back from JIT
SLJIT_W(number) : defining 64 bit constants on 64 bit architectures (compiler independent helper)
*/
@@ -147,17 +147,23 @@
#define SLJIT_CONFIG_UNSUPPORTED 1
#endif
-#else /* !_WIN32 */
+#else /* _WIN32 */
#if defined(_M_X64) || defined(__x86_64__)
#define SLJIT_CONFIG_X86_64 1
+#elif (defined(_M_ARM) && _M_ARM >= 7 && defined(_M_ARMT)) || defined(__thumb2__)
+#define SLJIT_CONFIG_ARM_THUMB2 1
+#elif (defined(_M_ARM) && _M_ARM >= 7)
+#define SLJIT_CONFIG_ARM_V7 1
#elif defined(_ARM_)
#define SLJIT_CONFIG_ARM_V5 1
+#elif defined(_M_ARM64) || defined(__aarch64__)
+#define SLJIT_CONFIG_ARM_64 1
#else
#define SLJIT_CONFIG_X86_32 1
#endif
-#endif /* !WIN32 */
+#endif /* !_WIN32 */
#endif /* SLJIT_CONFIG_AUTO */
#if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
@@ -324,6 +330,11 @@
sparc_cache_flush((from), (to))
#define SLJIT_CACHE_FLUSH_OWN_IMPL 1
+#elif defined _WIN32
+
+#define SLJIT_CACHE_FLUSH(from, to) \
+ FlushInstructionCache(GetCurrentProcess(), (char*)(from), (char*)(to) - (char*)(from))
+
#else
/* Calls __ARM_NR_cacheflush on ARM-Linux. */
@@ -371,12 +382,18 @@ typedef int sljit_sw;
#define SLJIT_64BIT_ARCHITECTURE 1
#define SLJIT_WORD_SHIFT 3
#ifdef _WIN32
+#ifdef __GNUC__
+/* These types do not require windows.h */
+typedef unsigned long long sljit_uw;
+typedef long long sljit_sw;
+#else
typedef unsigned __int64 sljit_uw;
typedef __int64 sljit_sw;
-#else
+#endif
+#else /* !_WIN32 */
typedef unsigned long int sljit_uw;
typedef long int sljit_sw;
-#endif
+#endif /* _WIN32 */
#endif
typedef sljit_uw sljit_p;
@@ -590,7 +607,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr);
#define SLJIT_NUMBER_OF_REGISTERS 26
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 10
-#define SLJIT_LOCALS_OFFSET_BASE (2 * sizeof(sljit_sw))
+#define SLJIT_LOCALS_OFFSET_BASE 0
#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
diff --git a/thirdparty/pcre2/src/sljit/sljitExecAllocator.c b/thirdparty/pcre2/src/sljit/sljitExecAllocator.c
index f5009788f6..7c18578618 100644
--- a/thirdparty/pcre2/src/sljit/sljitExecAllocator.c
+++ b/thirdparty/pcre2/src/sljit/sljitExecAllocator.c
@@ -99,7 +99,14 @@ static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
void *retval;
#ifdef MAP_ANON
- retval = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, -1, 0);
+
+ int flags = MAP_PRIVATE | MAP_ANON;
+
+#ifdef MAP_JIT
+ flags |= MAP_JIT;
+#endif
+
+ retval = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, flags, -1, 0);
#else
if (dev_zero < 0) {
if (open_dev_zero())
diff --git a/thirdparty/pcre2/src/sljit/sljitLir.c b/thirdparty/pcre2/src/sljit/sljitLir.c
index 5e435f0154..5bdddc10cf 100644
--- a/thirdparty/pcre2/src/sljit/sljitLir.c
+++ b/thirdparty/pcre2/src/sljit/sljitLir.c
@@ -26,6 +26,13 @@
#include "sljitLir.h"
+#ifdef _WIN32
+
+/* For SLJIT_CACHE_FLUSH, which can expand to FlushInstructionCache. */
+#include <windows.h>
+
+#endif /* _WIN32 */
+
#if !(defined SLJIT_STD_MACROS_DEFINED && SLJIT_STD_MACROS_DEFINED)
/* These libraries are needed for the macros below. */
@@ -2178,7 +2185,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil
#endif
-#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
+#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \
+ && !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset)
{
diff --git a/thirdparty/pcre2/src/sljit/sljitLir.h b/thirdparty/pcre2/src/sljit/sljitLir.h
index 920f6d4f78..e71890cf7b 100644
--- a/thirdparty/pcre2/src/sljit/sljitLir.h
+++ b/thirdparty/pcre2/src/sljit/sljitLir.h
@@ -138,7 +138,7 @@ of sljitConfigInternal.h */
be specified as scratch registers and the fifth one as saved register
on the CPU above and any user code which requires four scratch
registers can run unmodified. The SLJIT compiler automatically saves
- the content of the two extra scrath register on the stack. Scratch
+ the content of the two extra scratch register on the stack. Scratch
registers can also be preserved by saving their value on the stack
but this needs to be done manually.
@@ -746,7 +746,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler
be mixed. The only exception is SLJIT_MOV32 and SLJIT_MOVU32 whose source
register can hold any 32 or 64 bit value, and it is converted to a 32 bit
compatible format first. This conversion is free (no instructions are
- emitted) on most CPUs. A 32 bit value can also be coverted to a 64 bit
+ emitted) on most CPUs. A 32 bit value can also be converted to a 64 bit
value by SLJIT_MOV_S32 (sign extension) or SLJIT_MOV_U32 (zero extension).
Note: memory addressing always uses 64 bit values on 64 bit systems so
@@ -773,8 +773,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler
*/
#define SLJIT_F32_OP SLJIT_I32_OP
-/* Many CPUs (x86, ARM, PPC) has status flags which can be set according
- to the result of an operation. Other CPUs (MIPS) does not have status
+/* Many CPUs (x86, ARM, PPC) have status flags which can be set according
+ to the result of an operation. Other CPUs (MIPS) do not have status
flags, and results must be stored in registers. To cover both architecture
types efficiently only two flags are defined by SLJIT:
@@ -810,14 +810,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler
Using these flags can reduce the number of emitted instructions. E.g. a
fast loop can be implemented by decreasing a counter register and set the
- zero flag to jump back if the counter register is not reached zero.
+ zero flag to jump back if the counter register has not reached zero.
Motivation: although CPUs can set a large number of flags, usually their
values are ignored or only one of them is used. Emulating a large number
of flags on systems without flag register is complicated so SLJIT
instructions must specify the flag they want to use and only that flag
will be emulated. The last arithmetic instruction can be repeated if
- multiple flags needs to be checked.
+ multiple flags need to be checked.
*/
/* Set Zero status flag. */
@@ -884,7 +884,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
/* Starting index of opcodes for sljit_emit_op1. */
#define SLJIT_OP1_BASE 32
-/* The MOV instruction transfer data from source to destination.
+/* The MOV instruction transfers data from source to destination.
MOV instruction suffixes:
@@ -1156,7 +1156,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
#define SLJIT_FAST_CALL 25
/* Called function must be declared with the SLJIT_FUNC attribute. */
#define SLJIT_CALL 26
- /* Called function must be decalred with cdecl attribute.
+ /* Called function must be declared with cdecl attribute.
This is the default attribute for C functions. */
#define SLJIT_CALL_CDECL 27
@@ -1210,7 +1210,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sl
/* Set the destination address of the jump to this label. */
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw target);
-/* Emit an indirect jump or fast call. Both direct and indirect form
+/* Emit an indirect jump or fast call.
Direct form: set src to SLJIT_IMM() and srcw to the address
Indirect form: any other valid addressing mode
type must be between SLJIT_JUMP and SLJIT_FAST_CALL
@@ -1274,7 +1274,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
#define SLJIT_MEM_POST 0x1000
/* Emit a single memory load or store with update instruction. When the
- requested instruction from is not supported by the CPU, it returns
+ requested instruction form is not supported by the CPU, it returns
with SLJIT_ERR_UNSUPPORTED instead of emulating the instruction. This
allows specializing tight loops based on the supported instruction
forms (see SLJIT_MEM_SUPP flag).
diff --git a/thirdparty/pcre2/src/sljit/sljitNativeARM_64.c b/thirdparty/pcre2/src/sljit/sljitNativeARM_64.c
index 8a437bd6a0..27af741487 100644
--- a/thirdparty/pcre2/src/sljit/sljitNativeARM_64.c
+++ b/thirdparty/pcre2/src/sljit/sljitNativeARM_64.c
@@ -37,14 +37,14 @@ typedef sljit_u32 sljit_ins;
#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)
#define TMP_LR (SLJIT_NUMBER_OF_REGISTERS + 4)
-#define TMP_SP (SLJIT_NUMBER_OF_REGISTERS + 5)
+#define TMP_FP (SLJIT_NUMBER_OF_REGISTERS + 5)
#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)
/* r18 - platform register, currently not used */
static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 8] = {
- 31, 0, 1, 2, 3, 4, 5, 6, 7, 11, 12, 13, 14, 15, 16, 17, 8, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 29, 9, 10, 30, 31
+ 31, 0, 1, 2, 3, 4, 5, 6, 7, 11, 12, 13, 14, 15, 16, 17, 8, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 31, 9, 10, 30, 29
};
static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
@@ -68,6 +68,7 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
#define ADC 0x9a000000
#define ADD 0x8b000000
+#define ADDE 0x8b200000
#define ADDI 0x91000000
#define AND 0x8a000000
#define ANDI 0x92000000
@@ -96,7 +97,8 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
#define FSUB 0x1e603800
#define LDRI 0xf9400000
#define LDP 0xa9400000
-#define LDP_PST 0xa8c00000
+#define LDP_PRE 0xa9c00000
+#define LDR_PRE 0xf8400c00
#define LSLV 0x9ac02000
#define LSRV 0x9ac02400
#define MADD 0x9b000000
@@ -873,73 +875,51 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
- saved_regs_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 0);
- local_size += saved_regs_size + SLJIT_LOCALS_OFFSET;
+ saved_regs_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 2);
+ if (saved_regs_size & 0x8)
+ saved_regs_size += sizeof(sljit_sw);
+
local_size = (local_size + 15) & ~0xf;
- compiler->local_size = local_size;
-
- if (local_size <= (63 * sizeof(sljit_sw))) {
- FAIL_IF(push_inst(compiler, STP_PRE | 29 | RT2(TMP_LR)
- | RN(TMP_SP) | ((-(local_size >> 3) & 0x7f) << 15)));
- FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(TMP_SP) | (0 << 10)));
- offs = (local_size - saved_regs_size) << (15 - 3);
- } else {
- offs = 0 << 15;
- if (saved_regs_size & 0x8) {
- offs = 1 << 15;
- saved_regs_size += sizeof(sljit_sw);
- }
- local_size -= saved_regs_size + SLJIT_LOCALS_OFFSET;
- if (saved_regs_size > 0)
- FAIL_IF(push_inst(compiler, SUBI | RD(TMP_SP) | RN(TMP_SP) | (saved_regs_size << 10)));
- }
+ compiler->local_size = local_size + saved_regs_size;
+
+ FAIL_IF(push_inst(compiler, STP_PRE | RT(TMP_FP) | RT2(TMP_LR)
+ | RN(SLJIT_SP) | ((-(saved_regs_size >> 3) & 0x7f) << 15)));
+
+#ifdef _WIN32
+ if (local_size >= 4096)
+ FAIL_IF(push_inst(compiler, SUBI | RD(TMP_REG1) | RN(SLJIT_SP) | (1 << 10) | (1 << 22)));
+ else if (local_size > 256)
+ FAIL_IF(push_inst(compiler, SUBI | RD(TMP_REG1) | RN(SLJIT_SP) | (local_size << 10)));
+#endif
tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;
prev = -1;
+ offs = 2 << 15;
for (i = SLJIT_S0; i >= tmp; i--) {
if (prev == -1) {
- if (!(offs & (1 << 15))) {
- prev = i;
- continue;
- }
- FAIL_IF(push_inst(compiler, STRI | RT(i) | RN(TMP_SP) | (offs >> 5)));
- offs += 1 << 15;
+ prev = i;
continue;
}
- FAIL_IF(push_inst(compiler, STP | RT(prev) | RT2(i) | RN(TMP_SP) | offs));
+ FAIL_IF(push_inst(compiler, STP | RT(prev) | RT2(i) | RN(SLJIT_SP) | offs));
offs += 2 << 15;
prev = -1;
}
for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
if (prev == -1) {
- if (!(offs & (1 << 15))) {
- prev = i;
- continue;
- }
- FAIL_IF(push_inst(compiler, STRI | RT(i) | RN(TMP_SP) | (offs >> 5)));
- offs += 1 << 15;
+ prev = i;
continue;
}
- FAIL_IF(push_inst(compiler, STP | RT(prev) | RT2(i) | RN(TMP_SP) | offs));
+ FAIL_IF(push_inst(compiler, STP | RT(prev) | RT2(i) | RN(SLJIT_SP) | offs));
offs += 2 << 15;
prev = -1;
}
- SLJIT_ASSERT(prev == -1);
+ if (prev != -1)
+ FAIL_IF(push_inst(compiler, STRI | RT(prev) | RN(SLJIT_SP) | (offs >> 5)));
- if (compiler->local_size > (63 * sizeof(sljit_sw))) {
- /* The local_size is already adjusted by the saved registers. */
- if (local_size > 0xfff) {
- FAIL_IF(push_inst(compiler, SUBI | RD(TMP_SP) | RN(TMP_SP) | ((local_size >> 12) << 10) | (1 << 22)));
- local_size &= 0xfff;
- }
- if (local_size)
- FAIL_IF(push_inst(compiler, SUBI | RD(TMP_SP) | RN(TMP_SP) | (local_size << 10)));
- FAIL_IF(push_inst(compiler, STP_PRE | 29 | RT2(TMP_LR)
- | RN(TMP_SP) | ((-(16 >> 3) & 0x7f) << 15)));
- FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(TMP_SP) | (0 << 10)));
- }
+
+ FAIL_IF(push_inst(compiler, ADDI | RD(TMP_FP) | RN(SLJIT_SP) | (0 << 10)));
args = get_arg_count(arg_types);
@@ -950,6 +930,64 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
if (args >= 3)
FAIL_IF(push_inst(compiler, ORR | RD(SLJIT_S2) | RN(TMP_ZERO) | RM(SLJIT_R2)));
+#ifdef _WIN32
+ if (local_size >= 4096) {
+ if (local_size < 4 * 4096) {
+ /* No need for a loop. */
+ if (local_size >= 2 * 4096) {
+ FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, SUBI | RD(TMP_REG1) | RN(TMP_REG1) | (1 << 10) | (1 << 22)));
+ local_size -= 4096;
+ }
+
+ if (local_size >= 2 * 4096) {
+ FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, SUBI | RD(TMP_REG1) | RN(TMP_REG1) | (1 << 10) | (1 << 22)));
+ local_size -= 4096;
+ }
+
+ FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(TMP_REG1)));
+ local_size -= 4096;
+ }
+ else {
+ FAIL_IF(push_inst(compiler, MOVZ | RD(TMP_REG2) | (((local_size >> 12) - 1) << 5)));
+ FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, SUBI | RD(TMP_REG1) | RN(TMP_REG1) | (1 << 10) | (1 << 22)));
+ FAIL_IF(push_inst(compiler, SUBI | (1 << 29) | RD(TMP_REG2) | RN(TMP_REG2) | (1 << 10)));
+ FAIL_IF(push_inst(compiler, B_CC | ((((sljit_ins) -3) & 0x7ffff) << 5) | 0x1 /* not-equal */));
+ FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(TMP_REG1)));
+
+ local_size &= 0xfff;
+ }
+
+ if (local_size > 256) {
+ FAIL_IF(push_inst(compiler, SUBI | RD(TMP_REG1) | RN(TMP_REG1) | (local_size << 10)));
+ FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(TMP_REG1)));
+ }
+ else if (local_size > 0)
+ FAIL_IF(push_inst(compiler, LDR_PRE | RT(TMP_ZERO) | RN(TMP_REG1) | ((-local_size & 0x1ff) << 12)));
+
+ FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(TMP_REG1) | (0 << 10)));
+ }
+ else if (local_size > 256) {
+ FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(TMP_REG1) | (0 << 10)));
+ }
+ else if (local_size > 0)
+ FAIL_IF(push_inst(compiler, LDR_PRE | RT(TMP_ZERO) | RN(SLJIT_SP) | ((-local_size & 0x1ff) << 12)));
+
+#else /* !_WIN32 */
+
+ /* The local_size does not include saved registers size. */
+ if (local_size > 0xfff) {
+ FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | ((local_size >> 12) << 10) | (1 << 22)));
+ local_size &= 0xfff;
+ }
+ if (local_size != 0)
+ FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | (local_size << 10)));
+
+#endif /* _WIN32 */
+
return SLJIT_SUCCESS;
}
@@ -957,13 +995,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp
sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
{
+ sljit_s32 saved_regs_size;
+
CHECK_ERROR();
CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
- local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 0) + SLJIT_LOCALS_OFFSET;
- local_size = (local_size + 15) & ~0xf;
- compiler->local_size = local_size;
+ saved_regs_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 2);
+ if (saved_regs_size & 0x8)
+ saved_regs_size += sizeof(sljit_sw);
+
+ compiler->local_size = saved_regs_size + ((local_size + 15) & ~0xf);
return SLJIT_SUCCESS;
}
@@ -977,71 +1019,59 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp
FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
- local_size = compiler->local_size;
+ saved_regs_size = GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 2);
+ if (saved_regs_size & 0x8)
+ saved_regs_size += sizeof(sljit_sw);
- saved_regs_size = GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 0);
- if (local_size <= (63 * sizeof(sljit_sw)))
- offs = (local_size - saved_regs_size) << (15 - 3);
+ local_size = compiler->local_size - saved_regs_size;
+
+ /* Load LR as early as possible. */
+ if (local_size == 0)
+ FAIL_IF(push_inst(compiler, LDP | RT(TMP_FP) | RT2(TMP_LR) | RN(SLJIT_SP)));
+ else if (local_size < 63 * sizeof(sljit_sw)) {
+ FAIL_IF(push_inst(compiler, LDP_PRE | RT(TMP_FP) | RT2(TMP_LR)
+ | RN(SLJIT_SP) | (local_size << (15 - 3))));
+ }
else {
- FAIL_IF(push_inst(compiler, LDP_PST | 29 | RT2(TMP_LR)
- | RN(TMP_SP) | (((16 >> 3) & 0x7f) << 15)));
- offs = 0 << 15;
- if (saved_regs_size & 0x8) {
- offs = 1 << 15;
- saved_regs_size += sizeof(sljit_sw);
- }
- local_size -= saved_regs_size + SLJIT_LOCALS_OFFSET;
if (local_size > 0xfff) {
- FAIL_IF(push_inst(compiler, ADDI | RD(TMP_SP) | RN(TMP_SP) | ((local_size >> 12) << 10) | (1 << 22)));
+ FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(SLJIT_SP) | ((local_size >> 12) << 10) | (1 << 22)));
local_size &= 0xfff;
}
if (local_size)
- FAIL_IF(push_inst(compiler, ADDI | RD(TMP_SP) | RN(TMP_SP) | (local_size << 10)));
+ FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(SLJIT_SP) | (local_size << 10)));
+
+ FAIL_IF(push_inst(compiler, LDP | RT(TMP_FP) | RT2(TMP_LR) | RN(SLJIT_SP)));
}
tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG;
prev = -1;
+ offs = 2 << 15;
for (i = SLJIT_S0; i >= tmp; i--) {
if (prev == -1) {
- if (!(offs & (1 << 15))) {
- prev = i;
- continue;
- }
- FAIL_IF(push_inst(compiler, LDRI | RT(i) | RN(TMP_SP) | (offs >> 5)));
- offs += 1 << 15;
+ prev = i;
continue;
}
- FAIL_IF(push_inst(compiler, LDP | RT(prev) | RT2(i) | RN(TMP_SP) | offs));
+ FAIL_IF(push_inst(compiler, LDP | RT(prev) | RT2(i) | RN(SLJIT_SP) | offs));
offs += 2 << 15;
prev = -1;
}
for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
if (prev == -1) {
- if (!(offs & (1 << 15))) {
- prev = i;
- continue;
- }
- FAIL_IF(push_inst(compiler, LDRI | RT(i) | RN(TMP_SP) | (offs >> 5)));
- offs += 1 << 15;
+ prev = i;
continue;
}
- FAIL_IF(push_inst(compiler, LDP | RT(prev) | RT2(i) | RN(TMP_SP) | offs));
+ FAIL_IF(push_inst(compiler, LDP | RT(prev) | RT2(i) | RN(SLJIT_SP) | offs));
offs += 2 << 15;
prev = -1;
}
- SLJIT_ASSERT(prev == -1);
+ if (prev != -1)
+ FAIL_IF(push_inst(compiler, LDRI | RT(prev) | RN(SLJIT_SP) | (offs >> 5)));
- if (compiler->local_size <= (63 * sizeof(sljit_sw))) {
- FAIL_IF(push_inst(compiler, LDP_PST | 29 | RT2(TMP_LR)
- | RN(TMP_SP) | (((local_size >> 3) & 0x7f) << 15)));
- } else if (saved_regs_size > 0) {
- FAIL_IF(push_inst(compiler, ADDI | RD(TMP_SP) | RN(TMP_SP) | (saved_regs_size << 10)));
- }
-
- FAIL_IF(push_inst(compiler, RET | RN(TMP_LR)));
- return SLJIT_SUCCESS;
+ /* These two can be executed in parallel. */
+ FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(SLJIT_SP) | (saved_regs_size << 10)));
+ return push_inst(compiler, RET | RN(TMP_LR));
}
/* --------------------------------------------------------------------- */
@@ -1856,6 +1886,46 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil
return push_inst(compiler, inst | VT(freg) | RN(mem & REG_MASK) | ((memw & 0x1ff) << 12));
}
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset)
+{
+ sljit_s32 dst_reg;
+ sljit_ins ins;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_get_local_base(compiler, dst, dstw, offset));
+
+ SLJIT_ASSERT (SLJIT_LOCALS_OFFSET_BASE == 0);
+
+ dst_reg = FAST_IS_REG(dst) ? dst : TMP_REG1;
+
+ if (offset <= 0xffffff && offset >= -0xffffff) {
+ ins = ADDI;
+ if (offset < 0) {
+ offset = -offset;
+ ins = SUBI;
+ }
+
+ if (offset <= 0xfff)
+ FAIL_IF(push_inst(compiler, ins | RD(dst_reg) | RN(SLJIT_SP) | (offset << 10)));
+ else {
+ FAIL_IF(push_inst(compiler, ins | RD(dst_reg) | RN(SLJIT_SP) | ((offset & 0xfff000) >> (12 - 10)) | (1 << 22)));
+
+ offset &= 0xfff;
+ if (offset != 0)
+ FAIL_IF(push_inst(compiler, ins | RD(dst_reg) | RN(dst_reg) | (offset << 10)));
+ }
+ }
+ else {
+ FAIL_IF(load_immediate (compiler, dst_reg, offset));
+ /* Add extended register form. */
+ FAIL_IF(push_inst(compiler, ADDE | (0x3 << 13) | RD(dst_reg) | RN(SLJIT_SP) | RM(dst_reg)));
+ }
+
+ if (SLJIT_UNLIKELY(dst & SLJIT_MEM))
+ return emit_op_mem(compiler, WORD_SIZE | STORE, dst_reg, dst, dstw, TMP_REG1);
+ return SLJIT_SUCCESS;
+}
+
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
{
struct sljit_const *const_;
diff --git a/thirdparty/pcre2/src/sljit/sljitNativeARM_T2_32.c b/thirdparty/pcre2/src/sljit/sljitNativeARM_T2_32.c
index 75e7a38b5f..d7024b6d7d 100644
--- a/thirdparty/pcre2/src/sljit/sljitNativeARM_T2_32.c
+++ b/thirdparty/pcre2/src/sljit/sljitNativeARM_T2_32.c
@@ -110,6 +110,7 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
#define ASRSI 0x1000
#define ASR_W 0xfa40f000
#define ASR_WI 0xea4f0020
+#define BCC 0xd000
#define BICI 0xf0200000
#define BKPT 0xbe00
#define BLX 0x4780
@@ -125,6 +126,7 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
#define EORS 0x4040
#define EOR_W 0xea800000
#define IT 0xbf00
+#define LDRI 0xf8500800
#define LSLS 0x4080
#define LSLSI 0x0000
#define LSL_W 0xfa00f000
@@ -158,6 +160,7 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
#define SBCI 0xf1600000
#define SBCS 0x4180
#define SBC_W 0xeb600000
+#define SDIV 0xfb90f0f0
#define SMULL 0xfb800000
#define STR_SP 0x9000
#define SUBS 0x1a00
@@ -172,6 +175,7 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
#define SXTH 0xb200
#define SXTH_W 0xfa0ff080
#define TST 0x4200
+#define UDIV 0xfbb0f0f0
#define UMULL 0xfba00000
#define UXTB 0xb2c0
#define UXTB_W 0xfa5ff080
@@ -339,8 +343,8 @@ static SLJIT_INLINE void set_jump_instruction(struct sljit_jump *jump, sljit_sw
/* Really complex instruction form for branches. */
s = (diff >> 23) & 0x1;
- j1 = (~(diff >> 21) ^ s) & 0x1;
- j2 = (~(diff >> 22) ^ s) & 0x1;
+ j1 = (~(diff >> 22) ^ s) & 0x1;
+ j2 = (~(diff >> 21) ^ s) & 0x1;
jump_inst[0] = 0xf000 | (s << 10) | COPY_BITS(diff, 11, 0, 10);
jump_inst[1] = (j1 << 13) | (j2 << 11) | (diff & 0x7ff);
@@ -520,6 +524,8 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst,
{
sljit_uw tmp;
+ /* MOVS cannot be used since it destroy flags. */
+
if (imm >= 0x10000) {
tmp = get_imm(imm);
if (tmp != INVALID_IMM)
@@ -1032,6 +1038,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
{
sljit_s32 args, size, i, tmp;
sljit_ins push = 0;
+#ifdef _WIN32
+ sljit_uw imm;
+#endif
CHECK_ERROR();
CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
@@ -1052,12 +1061,25 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);
local_size = ((size + local_size + 7) & ~7) - size;
compiler->local_size = local_size;
+
+#ifdef _WIN32
+ if (local_size >= 256) {
+ if (local_size > 4096)
+ imm = get_imm(4096);
+ else
+ imm = get_imm(local_size & ~0xff);
+
+ SLJIT_ASSERT(imm != INVALID_IMM);
+ FAIL_IF(push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(SLJIT_SP) | imm));
+ }
+#else
if (local_size > 0) {
if (local_size <= (127 << 2))
FAIL_IF(push_inst16(compiler, SUB_SP | (local_size >> 2)));
else
FAIL_IF(emit_op_imm(compiler, SLJIT_SUB | ARG2_IMM, SLJIT_SP, SLJIT_SP, local_size));
}
+#endif
args = get_arg_count(arg_types);
@@ -1068,6 +1090,61 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
if (args >= 3)
FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_S2, SLJIT_R2)));
+#ifdef _WIN32
+ if (local_size >= 256) {
+ if (local_size > 4096) {
+ imm = get_imm(4096);
+ SLJIT_ASSERT(imm != INVALID_IMM);
+
+ if (local_size < 4 * 4096) {
+ if (local_size > 2 * 4096) {
+ FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG2) | RN4(TMP_REG1)));
+ FAIL_IF(push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(TMP_REG1) | imm));
+ local_size -= 4096;
+ }
+
+ if (local_size > 2 * 4096) {
+ FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG2) | RN4(TMP_REG1)));
+ FAIL_IF(push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(TMP_REG1) | imm));
+ local_size -= 4096;
+ }
+
+ FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG2) | RN4(TMP_REG1)));
+ local_size -= 4096;
+
+ SLJIT_ASSERT(local_size > 0);
+ }
+ else {
+ FAIL_IF(load_immediate(compiler, SLJIT_R3, (local_size >> 12) - 1));
+ FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG2) | RN4(TMP_REG1)));
+ FAIL_IF(push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(TMP_REG1) | imm));
+ SLJIT_ASSERT(reg_map[SLJIT_R3] < 7);
+ FAIL_IF(push_inst16(compiler, SUBSI8 | RDN3(SLJIT_R3) | 1));
+ FAIL_IF(push_inst16(compiler, BCC | (0x1 << 8) /* not-equal */ | (-7 & 0xff)));
+
+ local_size &= 0xfff;
+
+ if (local_size != 0)
+ FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG2) | RN4(TMP_REG1)));
+ }
+
+ if (local_size >= 256) {
+ imm = get_imm(local_size & ~0xff);
+ SLJIT_ASSERT(imm != INVALID_IMM);
+
+ FAIL_IF(push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(TMP_REG1) | imm));
+ }
+ }
+
+ local_size &= 0xff;
+ FAIL_IF(push_inst32(compiler, LDRI | 0x400 | (local_size > 0 ? 0x100 : 0) | RT4(TMP_REG2) | RN4(TMP_REG1) | local_size));
+
+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_SP, TMP_REG1)));
+ }
+ else if (local_size > 0)
+ FAIL_IF(push_inst32(compiler, LDRI | 0x500 | RT4(TMP_REG1) | RN4(SLJIT_SP) | local_size));
+#endif
+
return SLJIT_SUCCESS;
}
@@ -1119,11 +1196,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp
/* Operators */
/* --------------------------------------------------------------------- */
+#if !(defined __ARM_FEATURE_IDIV) && !(defined __ARM_ARCH_EXT_IDIV__)
+
#ifdef __cplusplus
extern "C" {
#endif
-#if defined(__GNUC__)
+#ifdef _WIN32
+extern unsigned long long __rt_udiv(unsigned int denominator, unsigned int numerator);
+extern long long __rt_sdiv(int denominator, int numerator);
+#elif defined(__GNUC__)
extern unsigned int __aeabi_uidivmod(unsigned int numerator, int unsigned denominator);
extern int __aeabi_idivmod(int numerator, int denominator);
#else
@@ -1134,10 +1216,14 @@ extern int __aeabi_idivmod(int numerator, int denominator);
}
#endif
+#endif /* !__ARM_FEATURE_IDIV && !__ARM_ARCH_EXT_IDIV__ */
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
{
+#if !(defined __ARM_FEATURE_IDIV) && !(defined __ARM_ARCH_EXT_IDIV__)
sljit_sw saved_reg_list[3];
sljit_sw saved_reg_count;
+#endif
CHECK_ERROR();
CHECK(check_sljit_emit_op0(compiler, op));
@@ -1155,6 +1241,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
| (reg_map[SLJIT_R0] << 12)
| (reg_map[SLJIT_R0] << 16)
| reg_map[SLJIT_R1]);
+#if (defined __ARM_FEATURE_IDIV) || (defined __ARM_ARCH_EXT_IDIV__)
+ case SLJIT_DIVMOD_UW:
+ case SLJIT_DIVMOD_SW:
+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG1, SLJIT_R0)));
+ FAIL_IF(push_inst32(compiler, (op == SLJIT_DIVMOD_UW ? UDIV : SDIV) | RD4(SLJIT_R0) | RN4(SLJIT_R0) | RM4(SLJIT_R1)));
+ FAIL_IF(push_inst32(compiler, MUL | RD4(SLJIT_R1) | RN4(SLJIT_R0) | RM4(SLJIT_R1)));
+ return push_inst32(compiler, SUB_W | RD4(SLJIT_R1) | RN4(TMP_REG1) | RM4(SLJIT_R1));
+ case SLJIT_DIV_UW:
+ case SLJIT_DIV_SW:
+ return push_inst32(compiler, (op == SLJIT_DIV_UW ? UDIV : SDIV) | RD4(SLJIT_R0) | RN4(SLJIT_R0) | RM4(SLJIT_R1));
+#else /* !__ARM_FEATURE_IDIV && !__ARM_ARCH_EXT_IDIV__ */
case SLJIT_DIVMOD_UW:
case SLJIT_DIVMOD_SW:
case SLJIT_DIV_UW:
@@ -1183,7 +1280,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
}
}
-#if defined(__GNUC__)
+#ifdef _WIN32
+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG1, SLJIT_R0)));
+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_R0, SLJIT_R1)));
+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_R1, TMP_REG1)));
+ FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM,
+ ((op | 0x2) == SLJIT_DIV_UW ? SLJIT_FUNC_OFFSET(__rt_udiv) : SLJIT_FUNC_OFFSET(__rt_sdiv))));
+#elif defined(__GNUC__)
FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM,
((op | 0x2) == SLJIT_DIV_UW ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod))));
#else
@@ -1203,6 +1306,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
| (saved_reg_list[0] << 12) /* ldr rX, [sp], #8/16 */);
}
return SLJIT_SUCCESS;
+#endif /* __ARM_FEATURE_IDIV || __ARM_ARCH_EXT_IDIV__ */
}
return SLJIT_SUCCESS;
diff --git a/thirdparty/pcre2/src/sljit/sljitNativeMIPS_32.c b/thirdparty/pcre2/src/sljit/sljitNativeMIPS_32.c
index 9f9e157a05..094c9923bc 100644
--- a/thirdparty/pcre2/src/sljit/sljitNativeMIPS_32.c
+++ b/thirdparty/pcre2/src/sljit/sljitNativeMIPS_32.c
@@ -448,7 +448,7 @@ static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_t
sljit_ins ins = NOP;
sljit_u8 offsets[4];
- SLJIT_ASSERT(reg_map[TMP_REG3] == 4 && freg_map[TMP_FREG1] == 12);
+ SLJIT_ASSERT(reg_map[TMP_REG1] == 4 && freg_map[TMP_FREG1] == 12);
arg_types >>= SLJIT_DEF_SHIFT;
@@ -516,7 +516,7 @@ static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_t
else if (arg_count != word_arg_count)
ins = ADDU | S(word_arg_count) | TA(0) | DA(4 + (offsets[arg_count - 1] >> 2));
else if (arg_count == 1)
- ins = ADDU | S(SLJIT_R0) | TA(0) | D(TMP_REG3);
+ ins = ADDU | S(SLJIT_R0) | TA(0) | DA(4);
arg_count--;
word_arg_count--;
diff --git a/thirdparty/pcre2/src/sljit/sljitNativeMIPS_64.c b/thirdparty/pcre2/src/sljit/sljitNativeMIPS_64.c
index ff6f048659..f841aef5dd 100644
--- a/thirdparty/pcre2/src/sljit/sljitNativeMIPS_64.c
+++ b/thirdparty/pcre2/src/sljit/sljitNativeMIPS_64.c
@@ -547,7 +547,7 @@ static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_t
sljit_ins prev_ins = NOP;
sljit_ins ins = NOP;
- SLJIT_ASSERT(reg_map[TMP_REG3] == 4 && freg_map[TMP_FREG1] == 12);
+ SLJIT_ASSERT(reg_map[TMP_REG1] == 4 && freg_map[TMP_FREG1] == 12);
arg_types >>= SLJIT_DEF_SHIFT;
@@ -591,7 +591,7 @@ static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_t
if (arg_count != word_arg_count)
ins = DADDU | S(word_arg_count) | TA(0) | D(arg_count);
else if (arg_count == 1)
- ins = DADDU | S(SLJIT_R0) | TA(0) | D(TMP_REG3);
+ ins = DADDU | S(SLJIT_R0) | TA(0) | DA(4);
arg_count--;
word_arg_count--;
break;
diff --git a/thirdparty/pcre2/src/sljit/sljitNativeMIPS_common.c b/thirdparty/pcre2/src/sljit/sljitNativeMIPS_common.c
index e108433f70..894e21304b 100644
--- a/thirdparty/pcre2/src/sljit/sljitNativeMIPS_common.c
+++ b/thirdparty/pcre2/src/sljit/sljitNativeMIPS_common.c
@@ -57,14 +57,14 @@ typedef sljit_u32 sljit_ins;
#define RETURN_ADDR_REG 31
/* Flags are kept in volatile registers. */
-#define EQUAL_FLAG 31
+#define EQUAL_FLAG 3
#define OTHER_FLAG 1
#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)
static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {
- 0, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 24, 23, 22, 21, 20, 19, 18, 17, 16, 29, 3, 25, 4
+ 0, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 24, 23, 22, 21, 20, 19, 18, 17, 16, 29, 4, 25, 31
};
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
@@ -612,16 +612,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
/* Frequent case. */
FAIL_IF(push_inst(compiler, ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(-local_size), DR(SLJIT_SP)));
base = S(SLJIT_SP);
+ offs = local_size - (sljit_sw)sizeof(sljit_sw);
}
else {
- FAIL_IF(load_immediate(compiler, DR(TMP_REG1), local_size));
+ FAIL_IF(load_immediate(compiler, DR(OTHER_FLAG), local_size));
FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_SP) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));
- FAIL_IF(push_inst(compiler, SUBU_W | S(SLJIT_SP) | T(TMP_REG1) | D(SLJIT_SP), DR(SLJIT_SP)));
+ FAIL_IF(push_inst(compiler, SUBU_W | S(SLJIT_SP) | T(OTHER_FLAG) | D(SLJIT_SP), DR(SLJIT_SP)));
base = S(TMP_REG2);
local_size = 0;
+ offs = -(sljit_sw)sizeof(sljit_sw);
}
- offs = local_size - (sljit_sw)(sizeof(sljit_sw));
FAIL_IF(push_inst(compiler, STACK_STORE | base | TA(RETURN_ADDR_REG) | IMM(offs), MOVABLE_INS));
tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;
@@ -805,7 +806,8 @@ static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sl
if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) {
tmp_ar = reg_ar;
delay_slot = reg_ar;
- } else {
+ }
+ else {
tmp_ar = DR(TMP_REG1);
delay_slot = MOVABLE_INS;
}
@@ -881,11 +883,39 @@ static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sl
static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw)
{
+ sljit_s32 tmp_ar, base, delay_slot;
+
if (getput_arg_fast(compiler, flags, reg_ar, arg, argw))
return compiler->error;
- compiler->cache_arg = 0;
- compiler->cache_argw = 0;
- return getput_arg(compiler, flags, reg_ar, arg, argw, 0, 0);
+
+ if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) {
+ tmp_ar = reg_ar;
+ delay_slot = reg_ar;
+ }
+ else {
+ tmp_ar = DR(TMP_REG1);
+ delay_slot = MOVABLE_INS;
+ }
+ base = arg & REG_MASK;
+
+ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
+ argw &= 0x3;
+
+ if (SLJIT_UNLIKELY(argw)) {
+ FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | DA(tmp_ar) | SH_IMM(argw), tmp_ar));
+ FAIL_IF(push_inst(compiler, ADDU_W | S(base) | TA(tmp_ar) | DA(tmp_ar), tmp_ar));
+ }
+ else
+ FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(OFFS_REG(arg)) | DA(tmp_ar), tmp_ar));
+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
+ }
+
+ FAIL_IF(load_immediate(compiler, tmp_ar, argw));
+
+ if (base != 0)
+ FAIL_IF(push_inst(compiler, ADDU_W | S(base) | TA(tmp_ar) | DA(tmp_ar), tmp_ar));
+
+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
}
static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg1, sljit_sw arg1w, sljit_s32 arg2, sljit_sw arg2w)
diff --git a/thirdparty/pcre2/src/sljit/sljitNativeX86_32.c b/thirdparty/pcre2/src/sljit/sljitNativeX86_32.c
index 8a83e273a4..074e64b9f2 100644
--- a/thirdparty/pcre2/src/sljit/sljitNativeX86_32.c
+++ b/thirdparty/pcre2/src/sljit/sljitNativeX86_32.c
@@ -123,34 +123,38 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
if (args > 0) {
- *inst++ = MOV_r_rm;
- *inst++ = MOD_REG | (reg_map[SLJIT_S0] << 3) | reg_map[SLJIT_R2];
+ inst[0] = MOV_r_rm;
+ inst[1] = MOD_REG | (reg_map[SLJIT_S0] << 3) | reg_map[SLJIT_R2];
+ inst += 2;
}
if (args > 1) {
- *inst++ = MOV_r_rm;
- *inst++ = MOD_REG | (reg_map[SLJIT_S1] << 3) | reg_map[SLJIT_R1];
+ inst[0] = MOV_r_rm;
+ inst[1] = MOD_REG | (reg_map[SLJIT_S1] << 3) | reg_map[SLJIT_R1];
+ inst += 2;
}
if (args > 2) {
- *inst++ = MOV_r_rm;
- *inst++ = MOD_DISP8 | (reg_map[SLJIT_S2] << 3) | 0x4 /* esp */;
- *inst++ = 0x24;
- *inst++ = sizeof(sljit_sw) * (3 + 2); /* saveds >= 3 as well. */
+ inst[0] = MOV_r_rm;
+ inst[1] = MOD_DISP8 | (reg_map[SLJIT_S2] << 3) | 0x4 /* esp */;
+ inst[2] = 0x24;
+ inst[3] = sizeof(sljit_sw) * (3 + 2); /* saveds >= 3 as well. */
}
#else
if (args > 0) {
- *inst++ = MOV_r_rm;
- *inst++ = MOD_DISP8 | (reg_map[SLJIT_S0] << 3) | reg_map[TMP_REG1];
- *inst++ = sizeof(sljit_sw) * 2;
+ inst[0] = MOV_r_rm;
+ inst[1] = MOD_DISP8 | (reg_map[SLJIT_S0] << 3) | reg_map[TMP_REG1];
+ inst[2] = sizeof(sljit_sw) * 2;
+ inst += 3;
}
if (args > 1) {
- *inst++ = MOV_r_rm;
- *inst++ = MOD_DISP8 | (reg_map[SLJIT_S1] << 3) | reg_map[TMP_REG1];
- *inst++ = sizeof(sljit_sw) * 3;
+ inst[0] = MOV_r_rm;
+ inst[1] = MOD_DISP8 | (reg_map[SLJIT_S1] << 3) | reg_map[TMP_REG1];
+ inst[2] = sizeof(sljit_sw) * 3;
+ inst += 3;
}
if (args > 2) {
- *inst++ = MOV_r_rm;
- *inst++ = MOD_DISP8 | (reg_map[SLJIT_S2] << 3) | reg_map[TMP_REG1];
- *inst++ = sizeof(sljit_sw) * 4;
+ inst[0] = MOV_r_rm;
+ inst[1] = MOD_DISP8 | (reg_map[SLJIT_S2] << 3) | reg_map[TMP_REG1];
+ inst[2] = sizeof(sljit_sw) * 4;
}
#endif
@@ -170,17 +174,36 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
compiler->local_size = local_size;
#ifdef _WIN32
- if (local_size > 1024) {
-#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
- FAIL_IF(emit_do_imm(compiler, MOV_r_i32 + reg_map[SLJIT_R0], local_size));
-#else
- /* Space for a single argument. This amount is excluded when the stack is allocated below. */
- local_size -= sizeof(sljit_sw);
- FAIL_IF(emit_do_imm(compiler, MOV_r_i32 + reg_map[SLJIT_R0], local_size));
- FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB),
- SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, sizeof(sljit_sw)));
-#endif
- FAIL_IF(sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARG1(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_grow_stack)));
+ if (local_size > 0) {
+ if (local_size <= 4 * 4096) {
+ if (local_size > 4096)
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -4096);
+ if (local_size > 2 * 4096)
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -4096 * 2);
+ if (local_size > 3 * 4096)
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -4096 * 3);
+ }
+ else {
+ EMIT_MOV(compiler, SLJIT_R0, 0, SLJIT_SP, 0);
+ EMIT_MOV(compiler, SLJIT_R1, 0, SLJIT_IMM, (local_size - 1) >> 12);
+
+ SLJIT_ASSERT (reg_map[SLJIT_R0] == 0);
+
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_R0), -4096);
+ FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB),
+ SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 4096));
+ FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB),
+ SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1));
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);
+ FAIL_IF(!inst);
+
+ INC_SIZE(2);
+ inst[0] = JNE_i8;
+ inst[1] = (sljit_s8) -16;
+ }
+
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -local_size);
}
#endif
diff --git a/thirdparty/pcre2/src/sljit/sljitNativeX86_64.c b/thirdparty/pcre2/src/sljit/sljitNativeX86_64.c
index 635ebd087c..8506565614 100644
--- a/thirdparty/pcre2/src/sljit/sljitNativeX86_64.c
+++ b/thirdparty/pcre2/src/sljit/sljitNativeX86_64.c
@@ -83,6 +83,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
+ compiler->mode32 = 0;
+
#ifdef _WIN64
/* Two/four register slots for parameters plus space for xmm6 register if needed. */
if (fscratches >= 6 || fsaveds >= 1)
@@ -126,35 +128,39 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
#ifndef _WIN64
if (args > 0) {
- *inst++ = REX_W;
- *inst++ = MOV_r_rm;
- *inst++ = MOD_REG | (reg_map[SLJIT_S0] << 3) | 0x7 /* rdi */;
+ inst[0] = REX_W;
+ inst[1] = MOV_r_rm;
+ inst[2] = MOD_REG | (reg_map[SLJIT_S0] << 3) | 0x7 /* rdi */;
+ inst += 3;
}
if (args > 1) {
- *inst++ = REX_W | REX_R;
- *inst++ = MOV_r_rm;
- *inst++ = MOD_REG | (reg_lmap[SLJIT_S1] << 3) | 0x6 /* rsi */;
+ inst[0] = REX_W | REX_R;
+ inst[1] = MOV_r_rm;
+ inst[2] = MOD_REG | (reg_lmap[SLJIT_S1] << 3) | 0x6 /* rsi */;
+ inst += 3;
}
if (args > 2) {
- *inst++ = REX_W | REX_R;
- *inst++ = MOV_r_rm;
- *inst++ = MOD_REG | (reg_lmap[SLJIT_S2] << 3) | 0x2 /* rdx */;
+ inst[0] = REX_W | REX_R;
+ inst[1] = MOV_r_rm;
+ inst[2] = MOD_REG | (reg_lmap[SLJIT_S2] << 3) | 0x2 /* rdx */;
}
#else
if (args > 0) {
- *inst++ = REX_W;
- *inst++ = MOV_r_rm;
- *inst++ = MOD_REG | (reg_map[SLJIT_S0] << 3) | 0x1 /* rcx */;
+ inst[0] = REX_W;
+ inst[1] = MOV_r_rm;
+ inst[2] = MOD_REG | (reg_map[SLJIT_S0] << 3) | 0x1 /* rcx */;
+ inst += 3;
}
if (args > 1) {
- *inst++ = REX_W;
- *inst++ = MOV_r_rm;
- *inst++ = MOD_REG | (reg_map[SLJIT_S1] << 3) | 0x2 /* rdx */;
+ inst[0] = REX_W;
+ inst[1] = MOV_r_rm;
+ inst[2] = MOD_REG | (reg_map[SLJIT_S1] << 3) | 0x2 /* rdx */;
+ inst += 3;
}
if (args > 2) {
- *inst++ = REX_W | REX_B;
- *inst++ = MOV_r_rm;
- *inst++ = MOD_REG | (reg_map[SLJIT_S2] << 3) | 0x0 /* r8 */;
+ inst[0] = REX_W | REX_B;
+ inst[1] = MOV_r_rm;
+ inst[2] = MOD_REG | (reg_map[SLJIT_S2] << 3) | 0x0 /* r8 */;
}
#endif
}
@@ -163,58 +169,42 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
compiler->local_size = local_size;
#ifdef _WIN64
- if (local_size > 1024) {
- /* Allocate stack for the callback, which grows the stack. */
- inst = (sljit_u8*)ensure_buf(compiler, 1 + 4 + (3 + sizeof(sljit_s32)));
- FAIL_IF(!inst);
- INC_SIZE(4 + (3 + sizeof(sljit_s32)));
- *inst++ = REX_W;
- *inst++ = GROUP_BINARY_83;
- *inst++ = MOD_REG | SUB | reg_map[SLJIT_SP];
- /* Allocated size for registers must be divisible by 8. */
- SLJIT_ASSERT(!(saved_register_size & 0x7));
- /* Aligned to 16 byte. */
- if (saved_register_size & 0x8) {
- *inst++ = 5 * sizeof(sljit_sw);
- local_size -= 5 * sizeof(sljit_sw);
- } else {
- *inst++ = 4 * sizeof(sljit_sw);
- local_size -= 4 * sizeof(sljit_sw);
- }
- /* Second instruction */
- SLJIT_ASSERT(reg_map[SLJIT_R0] < 8);
- *inst++ = REX_W;
- *inst++ = MOV_rm_i32;
- *inst++ = MOD_REG | reg_lmap[SLJIT_R0];
- sljit_unaligned_store_s32(inst, local_size);
-#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
- || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
- compiler->skip_checks = 1;
-#endif
- FAIL_IF(sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARG1(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_grow_stack)));
- }
-#endif
-
if (local_size > 0) {
- if (local_size <= 127) {
- inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);
- FAIL_IF(!inst);
- INC_SIZE(4);
- *inst++ = REX_W;
- *inst++ = GROUP_BINARY_83;
- *inst++ = MOD_REG | SUB | reg_map[SLJIT_SP];
- *inst++ = local_size;
+ if (local_size <= 4 * 4096) {
+ if (local_size > 4096)
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -4096);
+ if (local_size > 2 * 4096)
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -4096 * 2);
+ if (local_size > 3 * 4096)
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -4096 * 3);
}
else {
- inst = (sljit_u8*)ensure_buf(compiler, 1 + 7);
+ EMIT_MOV(compiler, SLJIT_R0, 0, SLJIT_SP, 0);
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, (local_size - 1) >> 12);
+
+ SLJIT_ASSERT (reg_map[SLJIT_R0] == 0);
+
+ EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_MEM1(SLJIT_R0), -4096);
+ FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB),
+ SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 4096));
+ FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB),
+ TMP_REG1, 0, TMP_REG1, 0, SLJIT_IMM, 1));
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);
FAIL_IF(!inst);
- INC_SIZE(7);
- *inst++ = REX_W;
- *inst++ = GROUP_BINARY_81;
- *inst++ = MOD_REG | SUB | reg_map[SLJIT_SP];
- sljit_unaligned_store_s32(inst, local_size);
- inst += sizeof(sljit_s32);
+
+ INC_SIZE(2);
+ inst[0] = JNE_i8;
+ inst[1] = (sljit_s8) -19;
}
+
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -local_size);
+ }
+#endif
+
+ if (local_size > 0) {
+ FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB),
+ SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, local_size));
}
#ifdef _WIN64
diff --git a/thirdparty/pcre2/src/sljit/sljitNativeX86_common.c b/thirdparty/pcre2/src/sljit/sljitNativeX86_common.c
index ab7b36adb2..6f02ee3e8b 100644
--- a/thirdparty/pcre2/src/sljit/sljitNativeX86_common.c
+++ b/thirdparty/pcre2/src/sljit/sljitNativeX86_common.c
@@ -669,23 +669,6 @@ static SLJIT_INLINE sljit_s32 emit_sse2_store(struct sljit_compiler *compiler,
static SLJIT_INLINE sljit_s32 emit_sse2_load(struct sljit_compiler *compiler,
sljit_s32 single, sljit_s32 dst, sljit_s32 src, sljit_sw srcw);
-#ifdef _WIN32
-#include <malloc.h>
-
-static void SLJIT_FUNC sljit_grow_stack(sljit_sw local_size)
-{
- /* Workaround for calling the internal _chkstk() function on Windows.
- This function touches all 4k pages belongs to the requested stack space,
- which size is passed in local_size. This is necessary on Windows where
- the stack can only grow in 4k steps. However, this function just burn
- CPU cycles if the stack is large enough. However, you don't know it in
- advance, so it must always be called. I think this is a bad design in
- general even if it has some reasons. */
- *(volatile sljit_s32*)alloca(local_size) = 0;
-}
-
-#endif
-
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
#include "sljitNativeX86_32.c"
#else
diff --git a/thirdparty/rtaudio/RtAudio.cpp b/thirdparty/rtaudio/RtAudio.cpp
deleted file mode 100644
index 04159776f7..0000000000
--- a/thirdparty/rtaudio/RtAudio.cpp
+++ /dev/null
@@ -1,10232 +0,0 @@
-#ifdef RTAUDIO_ENABLED // -GODOT-
-
-/************************************************************************/
-/*! \class RtAudio
- \brief Realtime audio i/o C++ classes.
-
- RtAudio provides a common API (Application Programming Interface)
- for realtime audio input/output across Linux (native ALSA, Jack,
- and OSS), Macintosh OS X (CoreAudio and Jack), and Windows
- (DirectSound, ASIO and WASAPI) operating systems.
-
- RtAudio WWW site: http://www.music.mcgill.ca/~gary/rtaudio/
-
- RtAudio: realtime audio i/o C++ classes
- Copyright (c) 2001-2016 Gary P. Scavone
-
- 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.
-
- Any person wishing to distribute modifications to the Software is
- asked to send the modifications to the original developer so that
- they can be incorporated into the canonical version. This is,
- however, not a binding provision of this license.
-
- 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.
-*/
-/************************************************************************/
-
-// RtAudio: Version 4.1.2
-
-#include "RtAudio.h"
-#include <iostream>
-#include <cstdlib>
-#include <cstring>
-#include <climits>
-#include <algorithm>
-
-// Static variable definitions.
-const unsigned int RtApi::MAX_SAMPLE_RATES = 14;
-const unsigned int RtApi::SAMPLE_RATES[] = {
- 4000, 5512, 8000, 9600, 11025, 16000, 22050,
- 32000, 44100, 48000, 88200, 96000, 176400, 192000
-};
-
-#if defined(__WINDOWS_DS__) || defined(__WINDOWS_ASIO__) || defined(__WINDOWS_WASAPI__)
- #define MUTEX_INITIALIZE(A) InitializeCriticalSection(A)
- #define MUTEX_DESTROY(A) DeleteCriticalSection(A)
- #define MUTEX_LOCK(A) EnterCriticalSection(A)
- #define MUTEX_UNLOCK(A) LeaveCriticalSection(A)
-
- #include "tchar.h"
-
- static std::string convertCharPointerToStdString(const char *text)
- {
- return std::string(text);
- }
-
- static std::string convertCharPointerToStdString(const wchar_t *text)
- {
- int length = WideCharToMultiByte(CP_UTF8, 0, text, -1, NULL, 0, NULL, NULL);
- std::string s( length-1, '\0' );
- WideCharToMultiByte(CP_UTF8, 0, text, -1, &s[0], length, NULL, NULL);
- return s;
- }
-
-#elif defined(__LINUX_ALSA__) || defined(__LINUX_PULSE__) || defined(__UNIX_JACK__) || defined(__LINUX_OSS__) || defined(__MACOSX_CORE__)
- // pthread API
- #define MUTEX_INITIALIZE(A) pthread_mutex_init(A, NULL)
- #define MUTEX_DESTROY(A) pthread_mutex_destroy(A)
- #define MUTEX_LOCK(A) pthread_mutex_lock(A)
- #define MUTEX_UNLOCK(A) pthread_mutex_unlock(A)
-#else
- #define MUTEX_INITIALIZE(A) abs(*A) // dummy definitions
- #define MUTEX_DESTROY(A) abs(*A) // dummy definitions
-#endif
-
-// *************************************************** //
-//
-// RtAudio definitions.
-//
-// *************************************************** //
-
-std::string RtAudio :: getVersion( void ) throw()
-{
- return RTAUDIO_VERSION;
-}
-
-void RtAudio :: getCompiledApi( std::vector<RtAudio::Api> &apis ) throw()
-{
- apis.clear();
-
- // The order here will control the order of RtAudio's API search in
- // the constructor.
-#if defined(__UNIX_JACK__)
- apis.push_back( UNIX_JACK );
-#endif
-#if defined(__LINUX_ALSA__)
- apis.push_back( LINUX_ALSA );
-#endif
-#if defined(__LINUX_PULSE__)
- apis.push_back( LINUX_PULSE );
-#endif
-#if defined(__LINUX_OSS__)
- apis.push_back( LINUX_OSS );
-#endif
-#if defined(__WINDOWS_ASIO__)
- apis.push_back( WINDOWS_ASIO );
-#endif
-#if defined(__WINDOWS_WASAPI__)
- apis.push_back( WINDOWS_WASAPI );
-#endif
-#if defined(__WINDOWS_DS__)
- apis.push_back( WINDOWS_DS );
-#endif
-#if defined(__MACOSX_CORE__)
- apis.push_back( MACOSX_CORE );
-#endif
-#if defined(__RTAUDIO_DUMMY__)
- apis.push_back( RTAUDIO_DUMMY );
-#endif
-}
-
-void RtAudio :: openRtApi( RtAudio::Api api )
-{
- if ( rtapi_ )
- delete rtapi_;
- rtapi_ = 0;
-
-#if defined(__UNIX_JACK__)
- if ( api == UNIX_JACK )
- rtapi_ = new RtApiJack();
-#endif
-#if defined(__LINUX_ALSA__)
- if ( api == LINUX_ALSA )
- rtapi_ = new RtApiAlsa();
-#endif
-#if defined(__LINUX_PULSE__)
- if ( api == LINUX_PULSE )
- rtapi_ = new RtApiPulse();
-#endif
-#if defined(__LINUX_OSS__)
- if ( api == LINUX_OSS )
- rtapi_ = new RtApiOss();
-#endif
-#if defined(__WINDOWS_ASIO__)
- if ( api == WINDOWS_ASIO )
- rtapi_ = new RtApiAsio();
-#endif
-#if defined(__WINDOWS_WASAPI__)
- if ( api == WINDOWS_WASAPI )
- rtapi_ = new RtApiWasapi();
-#endif
-#if defined(__WINDOWS_DS__)
- if ( api == WINDOWS_DS )
- rtapi_ = new RtApiDs();
-#endif
-#if defined(__MACOSX_CORE__)
- if ( api == MACOSX_CORE )
- rtapi_ = new RtApiCore();
-#endif
-#if defined(__RTAUDIO_DUMMY__)
- if ( api == RTAUDIO_DUMMY )
- rtapi_ = new RtApiDummy();
-#endif
-}
-
-RtAudio :: RtAudio( RtAudio::Api api )
-{
- rtapi_ = 0;
-
- if ( api != UNSPECIFIED ) {
- // Attempt to open the specified API.
- openRtApi( api );
- if ( rtapi_ ) return;
-
- // No compiled support for specified API value. Issue a debug
- // warning and continue as if no API was specified.
- std::cerr << "\nRtAudio: no compiled support for specified API argument!\n" << std::endl;
- }
-
- // Iterate through the compiled APIs and return as soon as we find
- // one with at least one device or we reach the end of the list.
- std::vector< RtAudio::Api > apis;
- getCompiledApi( apis );
- for ( unsigned int i=0; i<apis.size(); i++ ) {
- openRtApi( apis[i] );
- if ( rtapi_ && rtapi_->getDeviceCount() ) break;
- }
-
- if ( rtapi_ ) return;
-
- // It should not be possible to get here because the preprocessor
- // definition __RTAUDIO_DUMMY__ is automatically defined if no
- // API-specific definitions are passed to the compiler. But just in
- // case something weird happens, we'll thow an error.
- std::string errorText = "\nRtAudio: no compiled API support found ... critical error!!\n\n";
- throw( RtAudioError( errorText, RtAudioError::UNSPECIFIED ) );
-}
-
-RtAudio :: ~RtAudio() throw()
-{
- if ( rtapi_ )
- delete rtapi_;
-}
-
-void RtAudio :: openStream( RtAudio::StreamParameters *outputParameters,
- RtAudio::StreamParameters *inputParameters,
- RtAudioFormat format, unsigned int sampleRate,
- unsigned int *bufferFrames,
- RtAudioCallback callback, void *userData,
- RtAudio::StreamOptions *options,
- RtAudioErrorCallback errorCallback )
-{
- return rtapi_->openStream( outputParameters, inputParameters, format,
- sampleRate, bufferFrames, callback,
- userData, options, errorCallback );
-}
-
-// *************************************************** //
-//
-// Public RtApi definitions (see end of file for
-// private or protected utility functions).
-//
-// *************************************************** //
-
-RtApi :: RtApi()
-{
- stream_.state = STREAM_CLOSED;
- stream_.mode = UNINITIALIZED;
- stream_.apiHandle = 0;
- stream_.userBuffer[0] = 0;
- stream_.userBuffer[1] = 0;
- MUTEX_INITIALIZE( &stream_.mutex );
- showWarnings_ = true;
- firstErrorOccurred_ = false;
-}
-
-RtApi :: ~RtApi()
-{
- MUTEX_DESTROY( &stream_.mutex );
-}
-
-void RtApi :: openStream( RtAudio::StreamParameters *oParams,
- RtAudio::StreamParameters *iParams,
- RtAudioFormat format, unsigned int sampleRate,
- unsigned int *bufferFrames,
- RtAudioCallback callback, void *userData,
- RtAudio::StreamOptions *options,
- RtAudioErrorCallback errorCallback )
-{
- if ( stream_.state != STREAM_CLOSED ) {
- errorText_ = "RtApi::openStream: a stream is already open!";
- error( RtAudioError::INVALID_USE );
- return;
- }
-
- // Clear stream information potentially left from a previously open stream.
- clearStreamInfo();
-
- if ( oParams && oParams->nChannels < 1 ) {
- errorText_ = "RtApi::openStream: a non-NULL output StreamParameters structure cannot have an nChannels value less than one.";
- error( RtAudioError::INVALID_USE );
- return;
- }
-
- if ( iParams && iParams->nChannels < 1 ) {
- errorText_ = "RtApi::openStream: a non-NULL input StreamParameters structure cannot have an nChannels value less than one.";
- error( RtAudioError::INVALID_USE );
- return;
- }
-
- if ( oParams == NULL && iParams == NULL ) {
- errorText_ = "RtApi::openStream: input and output StreamParameters structures are both NULL!";
- error( RtAudioError::INVALID_USE );
- return;
- }
-
- if ( formatBytes(format) == 0 ) {
- errorText_ = "RtApi::openStream: 'format' parameter value is undefined.";
- error( RtAudioError::INVALID_USE );
- return;
- }
-
- unsigned int nDevices = getDeviceCount();
- unsigned int oChannels = 0;
- if ( oParams ) {
- oChannels = oParams->nChannels;
- if ( oParams->deviceId >= nDevices ) {
- errorText_ = "RtApi::openStream: output device parameter value is invalid.";
- error( RtAudioError::INVALID_USE );
- return;
- }
- }
-
- unsigned int iChannels = 0;
- if ( iParams ) {
- iChannels = iParams->nChannels;
- if ( iParams->deviceId >= nDevices ) {
- errorText_ = "RtApi::openStream: input device parameter value is invalid.";
- error( RtAudioError::INVALID_USE );
- return;
- }
- }
-
- bool result;
-
- if ( oChannels > 0 ) {
-
- result = probeDeviceOpen( oParams->deviceId, OUTPUT, oChannels, oParams->firstChannel,
- sampleRate, format, bufferFrames, options );
- if ( result == false ) {
- error( RtAudioError::SYSTEM_ERROR );
- return;
- }
- }
-
- if ( iChannels > 0 ) {
-
- result = probeDeviceOpen( iParams->deviceId, INPUT, iChannels, iParams->firstChannel,
- sampleRate, format, bufferFrames, options );
- if ( result == false ) {
- if ( oChannels > 0 ) closeStream();
- error( RtAudioError::SYSTEM_ERROR );
- return;
- }
- }
-
- stream_.callbackInfo.callback = (void *) callback;
- stream_.callbackInfo.userData = userData;
- stream_.callbackInfo.errorCallback = (void *) errorCallback;
-
- if ( options ) options->numberOfBuffers = stream_.nBuffers;
- stream_.state = STREAM_STOPPED;
-}
-
-unsigned int RtApi :: getDefaultInputDevice( void )
-{
- // Should be implemented in subclasses if possible.
- return 0;
-}
-
-unsigned int RtApi :: getDefaultOutputDevice( void )
-{
- // Should be implemented in subclasses if possible.
- return 0;
-}
-
-void RtApi :: closeStream( void )
-{
- // MUST be implemented in subclasses!
- return;
-}
-
-bool RtApi :: probeDeviceOpen( unsigned int /*device*/, StreamMode /*mode*/, unsigned int /*channels*/,
- unsigned int /*firstChannel*/, unsigned int /*sampleRate*/,
- RtAudioFormat /*format*/, unsigned int * /*bufferSize*/,
- RtAudio::StreamOptions * /*options*/ )
-{
- // MUST be implemented in subclasses!
- return FAILURE;
-}
-
-void RtApi :: tickStreamTime( void )
-{
- // Subclasses that do not provide their own implementation of
- // getStreamTime should call this function once per buffer I/O to
- // provide basic stream time support.
-
- stream_.streamTime += ( stream_.bufferSize * 1.0 / stream_.sampleRate );
-
-#if defined( HAVE_GETTIMEOFDAY )
- gettimeofday( &stream_.lastTickTimestamp, NULL );
-#endif
-}
-
-long RtApi :: getStreamLatency( void )
-{
- verifyStream();
-
- long totalLatency = 0;
- if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX )
- totalLatency = stream_.latency[0];
- if ( stream_.mode == INPUT || stream_.mode == DUPLEX )
- totalLatency += stream_.latency[1];
-
- return totalLatency;
-}
-
-double RtApi :: getStreamTime( void )
-{
- verifyStream();
-
-#if defined( HAVE_GETTIMEOFDAY )
- // Return a very accurate estimate of the stream time by
- // adding in the elapsed time since the last tick.
- struct timeval then;
- struct timeval now;
-
- if ( stream_.state != STREAM_RUNNING || stream_.streamTime == 0.0 )
- return stream_.streamTime;
-
- gettimeofday( &now, NULL );
- then = stream_.lastTickTimestamp;
- return stream_.streamTime +
- ((now.tv_sec + 0.000001 * now.tv_usec) -
- (then.tv_sec + 0.000001 * then.tv_usec));
-#else
- return stream_.streamTime;
-#endif
-}
-
-void RtApi :: setStreamTime( double time )
-{
- verifyStream();
-
- if ( time >= 0.0 )
- stream_.streamTime = time;
-}
-
-unsigned int RtApi :: getStreamSampleRate( void )
-{
- verifyStream();
-
- return stream_.sampleRate;
-}
-
-
-// *************************************************** //
-//
-// OS/API-specific methods.
-//
-// *************************************************** //
-
-#if defined(__MACOSX_CORE__)
-
-// The OS X CoreAudio API is designed to use a separate callback
-// procedure for each of its audio devices. A single RtAudio duplex
-// stream using two different devices is supported here, though it
-// cannot be guaranteed to always behave correctly because we cannot
-// synchronize these two callbacks.
-//
-// A property listener is installed for over/underrun information.
-// However, no functionality is currently provided to allow property
-// listeners to trigger user handlers because it is unclear what could
-// be done if a critical stream parameter (buffer size, sample rate,
-// device disconnect) notification arrived. The listeners entail
-// quite a bit of extra code and most likely, a user program wouldn't
-// be prepared for the result anyway. However, we do provide a flag
-// to the client callback function to inform of an over/underrun.
-
-// A structure to hold various information related to the CoreAudio API
-// implementation.
-struct CoreHandle {
- AudioDeviceID id[2]; // device ids
-#if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 )
- AudioDeviceIOProcID procId[2];
-#endif
- UInt32 iStream[2]; // device stream index (or first if using multiple)
- UInt32 nStreams[2]; // number of streams to use
- bool xrun[2];
- char *deviceBuffer;
- pthread_cond_t condition;
- int drainCounter; // Tracks callback counts when draining
- bool internalDrain; // Indicates if stop is initiated from callback or not.
-
- CoreHandle()
- :deviceBuffer(0), drainCounter(0), internalDrain(false) { nStreams[0] = 1; nStreams[1] = 1; id[0] = 0; id[1] = 0; xrun[0] = false; xrun[1] = false; }
-};
-
-RtApiCore:: RtApiCore()
-{
-#if defined( AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER )
- // This is a largely undocumented but absolutely necessary
- // requirement starting with OS-X 10.6. If not called, queries and
- // updates to various audio device properties are not handled
- // correctly.
- CFRunLoopRef theRunLoop = NULL;
- AudioObjectPropertyAddress property = { kAudioHardwarePropertyRunLoop,
- kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster };
- OSStatus result = AudioObjectSetPropertyData( kAudioObjectSystemObject, &property, 0, NULL, sizeof(CFRunLoopRef), &theRunLoop);
- if ( result != noErr ) {
- errorText_ = "RtApiCore::RtApiCore: error setting run loop property!";
- error( RtAudioError::WARNING );
- }
-#endif
-}
-
-RtApiCore :: ~RtApiCore()
-{
- // The subclass destructor gets called before the base class
- // destructor, so close an existing stream before deallocating
- // apiDeviceId memory.
- if ( stream_.state != STREAM_CLOSED ) closeStream();
-}
-
-unsigned int RtApiCore :: getDeviceCount( void )
-{
- // Find out how many audio devices there are, if any.
- UInt32 dataSize;
- AudioObjectPropertyAddress propertyAddress = { kAudioHardwarePropertyDevices, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
- OSStatus result = AudioObjectGetPropertyDataSize( kAudioObjectSystemObject, &propertyAddress, 0, NULL, &dataSize );
- if ( result != noErr ) {
- errorText_ = "RtApiCore::getDeviceCount: OS-X error getting device info!";
- error( RtAudioError::WARNING );
- return 0;
- }
-
- return dataSize / sizeof( AudioDeviceID );
-}
-
-unsigned int RtApiCore :: getDefaultInputDevice( void )
-{
- unsigned int nDevices = getDeviceCount();
- if ( nDevices <= 1 ) return 0;
-
- AudioDeviceID id;
- UInt32 dataSize = sizeof( AudioDeviceID );
- AudioObjectPropertyAddress property = { kAudioHardwarePropertyDefaultInputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
- OSStatus result = AudioObjectGetPropertyData( kAudioObjectSystemObject, &property, 0, NULL, &dataSize, &id );
- if ( result != noErr ) {
- errorText_ = "RtApiCore::getDefaultInputDevice: OS-X system error getting device.";
- error( RtAudioError::WARNING );
- return 0;
- }
-
- dataSize *= nDevices;
- AudioDeviceID deviceList[ nDevices ];
- property.mSelector = kAudioHardwarePropertyDevices;
- result = AudioObjectGetPropertyData( kAudioObjectSystemObject, &property, 0, NULL, &dataSize, (void *) &deviceList );
- if ( result != noErr ) {
- errorText_ = "RtApiCore::getDefaultInputDevice: OS-X system error getting device IDs.";
- error( RtAudioError::WARNING );
- return 0;
- }
-
- for ( unsigned int i=0; i<nDevices; i++ )
- if ( id == deviceList[i] ) return i;
-
- errorText_ = "RtApiCore::getDefaultInputDevice: No default device found!";
- error( RtAudioError::WARNING );
- return 0;
-}
-
-unsigned int RtApiCore :: getDefaultOutputDevice( void )
-{
- unsigned int nDevices = getDeviceCount();
- if ( nDevices <= 1 ) return 0;
-
- AudioDeviceID id;
- UInt32 dataSize = sizeof( AudioDeviceID );
- AudioObjectPropertyAddress property = { kAudioHardwarePropertyDefaultOutputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
- OSStatus result = AudioObjectGetPropertyData( kAudioObjectSystemObject, &property, 0, NULL, &dataSize, &id );
- if ( result != noErr ) {
- errorText_ = "RtApiCore::getDefaultOutputDevice: OS-X system error getting device.";
- error( RtAudioError::WARNING );
- return 0;
- }
-
- dataSize = sizeof( AudioDeviceID ) * nDevices;
- AudioDeviceID deviceList[ nDevices ];
- property.mSelector = kAudioHardwarePropertyDevices;
- result = AudioObjectGetPropertyData( kAudioObjectSystemObject, &property, 0, NULL, &dataSize, (void *) &deviceList );
- if ( result != noErr ) {
- errorText_ = "RtApiCore::getDefaultOutputDevice: OS-X system error getting device IDs.";
- error( RtAudioError::WARNING );
- return 0;
- }
-
- for ( unsigned int i=0; i<nDevices; i++ )
- if ( id == deviceList[i] ) return i;
-
- errorText_ = "RtApiCore::getDefaultOutputDevice: No default device found!";
- error( RtAudioError::WARNING );
- return 0;
-}
-
-RtAudio::DeviceInfo RtApiCore :: getDeviceInfo( unsigned int device )
-{
- RtAudio::DeviceInfo info;
- info.probed = false;
-
- // Get device ID
- unsigned int nDevices = getDeviceCount();
- if ( nDevices == 0 ) {
- errorText_ = "RtApiCore::getDeviceInfo: no devices found!";
- error( RtAudioError::INVALID_USE );
- return info;
- }
-
- if ( device >= nDevices ) {
- errorText_ = "RtApiCore::getDeviceInfo: device ID is invalid!";
- error( RtAudioError::INVALID_USE );
- return info;
- }
-
- AudioDeviceID deviceList[ nDevices ];
- UInt32 dataSize = sizeof( AudioDeviceID ) * nDevices;
- AudioObjectPropertyAddress property = { kAudioHardwarePropertyDevices,
- kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster };
- OSStatus result = AudioObjectGetPropertyData( kAudioObjectSystemObject, &property,
- 0, NULL, &dataSize, (void *) &deviceList );
- if ( result != noErr ) {
- errorText_ = "RtApiCore::getDeviceInfo: OS-X system error getting device IDs.";
- error( RtAudioError::WARNING );
- return info;
- }
-
- AudioDeviceID id = deviceList[ device ];
-
- // Get the device name.
- info.name.erase();
- CFStringRef cfname;
- dataSize = sizeof( CFStringRef );
- property.mSelector = kAudioObjectPropertyManufacturer;
- result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &cfname );
- if ( result != noErr ) {
- errorStream_ << "RtApiCore::probeDeviceInfo: system error (" << getErrorCode( result ) << ") getting device manufacturer.";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- return info;
- }
-
- //const char *mname = CFStringGetCStringPtr( cfname, CFStringGetSystemEncoding() );
- int length = CFStringGetLength(cfname);
- char *mname = (char *)malloc(length * 3 + 1);
-#if defined( UNICODE ) || defined( _UNICODE )
- CFStringGetCString(cfname, mname, length * 3 + 1, kCFStringEncodingUTF8);
-#else
- CFStringGetCString(cfname, mname, length * 3 + 1, CFStringGetSystemEncoding());
-#endif
- info.name.append( (const char *)mname, strlen(mname) );
- info.name.append( ": " );
- CFRelease( cfname );
- free(mname);
-
- property.mSelector = kAudioObjectPropertyName;
- result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &cfname );
- if ( result != noErr ) {
- errorStream_ << "RtApiCore::probeDeviceInfo: system error (" << getErrorCode( result ) << ") getting device name.";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- return info;
- }
-
- //const char *name = CFStringGetCStringPtr( cfname, CFStringGetSystemEncoding() );
- length = CFStringGetLength(cfname);
- char *name = (char *)malloc(length * 3 + 1);
-#if defined( UNICODE ) || defined( _UNICODE )
- CFStringGetCString(cfname, name, length * 3 + 1, kCFStringEncodingUTF8);
-#else
- CFStringGetCString(cfname, name, length * 3 + 1, CFStringGetSystemEncoding());
-#endif
- info.name.append( (const char *)name, strlen(name) );
- CFRelease( cfname );
- free(name);
-
- // Get the output stream "configuration".
- AudioBufferList *bufferList = nil;
- property.mSelector = kAudioDevicePropertyStreamConfiguration;
- property.mScope = kAudioDevicePropertyScopeOutput;
- // property.mElement = kAudioObjectPropertyElementWildcard;
- dataSize = 0;
- result = AudioObjectGetPropertyDataSize( id, &property, 0, NULL, &dataSize );
- if ( result != noErr || dataSize == 0 ) {
- errorStream_ << "RtApiCore::getDeviceInfo: system error (" << getErrorCode( result ) << ") getting output stream configuration info for device (" << device << ").";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- return info;
- }
-
- // Allocate the AudioBufferList.
- bufferList = (AudioBufferList *) malloc( dataSize );
- if ( bufferList == NULL ) {
- errorText_ = "RtApiCore::getDeviceInfo: memory error allocating output AudioBufferList.";
- error( RtAudioError::WARNING );
- return info;
- }
-
- result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, bufferList );
- if ( result != noErr || dataSize == 0 ) {
- free( bufferList );
- errorStream_ << "RtApiCore::getDeviceInfo: system error (" << getErrorCode( result ) << ") getting output stream configuration for device (" << device << ").";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- return info;
- }
-
- // Get output channel information.
- unsigned int i, nStreams = bufferList->mNumberBuffers;
- for ( i=0; i<nStreams; i++ )
- info.outputChannels += bufferList->mBuffers[i].mNumberChannels;
- free( bufferList );
-
- // Get the input stream "configuration".
- property.mScope = kAudioDevicePropertyScopeInput;
- result = AudioObjectGetPropertyDataSize( id, &property, 0, NULL, &dataSize );
- if ( result != noErr || dataSize == 0 ) {
- errorStream_ << "RtApiCore::getDeviceInfo: system error (" << getErrorCode( result ) << ") getting input stream configuration info for device (" << device << ").";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- return info;
- }
-
- // Allocate the AudioBufferList.
- bufferList = (AudioBufferList *) malloc( dataSize );
- if ( bufferList == NULL ) {
- errorText_ = "RtApiCore::getDeviceInfo: memory error allocating input AudioBufferList.";
- error( RtAudioError::WARNING );
- return info;
- }
-
- result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, bufferList );
- if (result != noErr || dataSize == 0) {
- free( bufferList );
- errorStream_ << "RtApiCore::getDeviceInfo: system error (" << getErrorCode( result ) << ") getting input stream configuration for device (" << device << ").";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- return info;
- }
-
- // Get input channel information.
- nStreams = bufferList->mNumberBuffers;
- for ( i=0; i<nStreams; i++ )
- info.inputChannels += bufferList->mBuffers[i].mNumberChannels;
- free( bufferList );
-
- // If device opens for both playback and capture, we determine the channels.
- if ( info.outputChannels > 0 && info.inputChannels > 0 )
- info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels;
-
- // Probe the device sample rates.
- bool isInput = false;
- if ( info.outputChannels == 0 ) isInput = true;
-
- // Determine the supported sample rates.
- property.mSelector = kAudioDevicePropertyAvailableNominalSampleRates;
- if ( isInput == false ) property.mScope = kAudioDevicePropertyScopeOutput;
- result = AudioObjectGetPropertyDataSize( id, &property, 0, NULL, &dataSize );
- if ( result != kAudioHardwareNoError || dataSize == 0 ) {
- errorStream_ << "RtApiCore::getDeviceInfo: system error (" << getErrorCode( result ) << ") getting sample rate info.";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- return info;
- }
-
- UInt32 nRanges = dataSize / sizeof( AudioValueRange );
- AudioValueRange rangeList[ nRanges ];
- result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &rangeList );
- if ( result != kAudioHardwareNoError ) {
- errorStream_ << "RtApiCore::getDeviceInfo: system error (" << getErrorCode( result ) << ") getting sample rates.";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- return info;
- }
-
- // The sample rate reporting mechanism is a bit of a mystery. It
- // seems that it can either return individual rates or a range of
- // rates. I assume that if the min / max range values are the same,
- // then that represents a single supported rate and if the min / max
- // range values are different, the device supports an arbitrary
- // range of values (though there might be multiple ranges, so we'll
- // use the most conservative range).
- Float64 minimumRate = 1.0, maximumRate = 10000000000.0;
- bool haveValueRange = false;
- info.sampleRates.clear();
- for ( UInt32 i=0; i<nRanges; i++ ) {
- if ( rangeList[i].mMinimum == rangeList[i].mMaximum ) {
- unsigned int tmpSr = (unsigned int) rangeList[i].mMinimum;
- info.sampleRates.push_back( tmpSr );
-
- if ( !info.preferredSampleRate || ( tmpSr <= 48000 && tmpSr > info.preferredSampleRate ) )
- info.preferredSampleRate = tmpSr;
-
- } else {
- haveValueRange = true;
- if ( rangeList[i].mMinimum > minimumRate ) minimumRate = rangeList[i].mMinimum;
- if ( rangeList[i].mMaximum < maximumRate ) maximumRate = rangeList[i].mMaximum;
- }
- }
-
- if ( haveValueRange ) {
- for ( unsigned int k=0; k<MAX_SAMPLE_RATES; k++ ) {
- if ( SAMPLE_RATES[k] >= (unsigned int) minimumRate && SAMPLE_RATES[k] <= (unsigned int) maximumRate ) {
- info.sampleRates.push_back( SAMPLE_RATES[k] );
-
- if ( !info.preferredSampleRate || ( SAMPLE_RATES[k] <= 48000 && SAMPLE_RATES[k] > info.preferredSampleRate ) )
- info.preferredSampleRate = SAMPLE_RATES[k];
- }
- }
- }
-
- // Sort and remove any redundant values
- std::sort( info.sampleRates.begin(), info.sampleRates.end() );
- info.sampleRates.erase( unique( info.sampleRates.begin(), info.sampleRates.end() ), info.sampleRates.end() );
-
- if ( info.sampleRates.size() == 0 ) {
- errorStream_ << "RtApiCore::probeDeviceInfo: No supported sample rates found for device (" << device << ").";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- return info;
- }
-
- // CoreAudio always uses 32-bit floating point data for PCM streams.
- // Thus, any other "physical" formats supported by the device are of
- // no interest to the client.
- info.nativeFormats = RTAUDIO_FLOAT32;
-
- if ( info.outputChannels > 0 )
- if ( getDefaultOutputDevice() == device ) info.isDefaultOutput = true;
- if ( info.inputChannels > 0 )
- if ( getDefaultInputDevice() == device ) info.isDefaultInput = true;
-
- info.probed = true;
- return info;
-}
-
-static OSStatus callbackHandler( AudioDeviceID inDevice,
- const AudioTimeStamp* /*inNow*/,
- const AudioBufferList* inInputData,
- const AudioTimeStamp* /*inInputTime*/,
- AudioBufferList* outOutputData,
- const AudioTimeStamp* /*inOutputTime*/,
- void* infoPointer )
-{
- CallbackInfo *info = (CallbackInfo *) infoPointer;
-
- RtApiCore *object = (RtApiCore *) info->object;
- if ( object->callbackEvent( inDevice, inInputData, outOutputData ) == false )
- return kAudioHardwareUnspecifiedError;
- else
- return kAudioHardwareNoError;
-}
-
-static OSStatus xrunListener( AudioObjectID /*inDevice*/,
- UInt32 nAddresses,
- const AudioObjectPropertyAddress properties[],
- void* handlePointer )
-{
- CoreHandle *handle = (CoreHandle *) handlePointer;
- for ( UInt32 i=0; i<nAddresses; i++ ) {
- if ( properties[i].mSelector == kAudioDeviceProcessorOverload ) {
- if ( properties[i].mScope == kAudioDevicePropertyScopeInput )
- handle->xrun[1] = true;
- else
- handle->xrun[0] = true;
- }
- }
-
- return kAudioHardwareNoError;
-}
-
-static OSStatus rateListener( AudioObjectID inDevice,
- UInt32 /*nAddresses*/,
- const AudioObjectPropertyAddress /*properties*/[],
- void* ratePointer )
-{
- Float64 *rate = (Float64 *) ratePointer;
- UInt32 dataSize = sizeof( Float64 );
- AudioObjectPropertyAddress property = { kAudioDevicePropertyNominalSampleRate,
- kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster };
- AudioObjectGetPropertyData( inDevice, &property, 0, NULL, &dataSize, rate );
- return kAudioHardwareNoError;
-}
-
-bool RtApiCore :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,
- unsigned int firstChannel, unsigned int sampleRate,
- RtAudioFormat format, unsigned int *bufferSize,
- RtAudio::StreamOptions *options )
-{
- // Get device ID
- unsigned int nDevices = getDeviceCount();
- if ( nDevices == 0 ) {
- // This should not happen because a check is made before this function is called.
- errorText_ = "RtApiCore::probeDeviceOpen: no devices found!";
- return FAILURE;
- }
-
- if ( device >= nDevices ) {
- // This should not happen because a check is made before this function is called.
- errorText_ = "RtApiCore::probeDeviceOpen: device ID is invalid!";
- return FAILURE;
- }
-
- AudioDeviceID deviceList[ nDevices ];
- UInt32 dataSize = sizeof( AudioDeviceID ) * nDevices;
- AudioObjectPropertyAddress property = { kAudioHardwarePropertyDevices,
- kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster };
- OSStatus result = AudioObjectGetPropertyData( kAudioObjectSystemObject, &property,
- 0, NULL, &dataSize, (void *) &deviceList );
- if ( result != noErr ) {
- errorText_ = "RtApiCore::probeDeviceOpen: OS-X system error getting device IDs.";
- return FAILURE;
- }
-
- AudioDeviceID id = deviceList[ device ];
-
- // Setup for stream mode.
- bool isInput = false;
- if ( mode == INPUT ) {
- isInput = true;
- property.mScope = kAudioDevicePropertyScopeInput;
- }
- else
- property.mScope = kAudioDevicePropertyScopeOutput;
-
- // Get the stream "configuration".
- AudioBufferList *bufferList = nil;
- dataSize = 0;
- property.mSelector = kAudioDevicePropertyStreamConfiguration;
- result = AudioObjectGetPropertyDataSize( id, &property, 0, NULL, &dataSize );
- if ( result != noErr || dataSize == 0 ) {
- errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting stream configuration info for device (" << device << ").";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- // Allocate the AudioBufferList.
- bufferList = (AudioBufferList *) malloc( dataSize );
- if ( bufferList == NULL ) {
- errorText_ = "RtApiCore::probeDeviceOpen: memory error allocating AudioBufferList.";
- return FAILURE;
- }
-
- result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, bufferList );
- if (result != noErr || dataSize == 0) {
- free( bufferList );
- errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting stream configuration for device (" << device << ").";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- // Search for one or more streams that contain the desired number of
- // channels. CoreAudio devices can have an arbitrary number of
- // streams and each stream can have an arbitrary number of channels.
- // For each stream, a single buffer of interleaved samples is
- // provided. RtAudio prefers the use of one stream of interleaved
- // data or multiple consecutive single-channel streams. However, we
- // now support multiple consecutive multi-channel streams of
- // interleaved data as well.
- UInt32 iStream, offsetCounter = firstChannel;
- UInt32 nStreams = bufferList->mNumberBuffers;
- bool monoMode = false;
- bool foundStream = false;
-
- // First check that the device supports the requested number of
- // channels.
- UInt32 deviceChannels = 0;
- for ( iStream=0; iStream<nStreams; iStream++ )
- deviceChannels += bufferList->mBuffers[iStream].mNumberChannels;
-
- if ( deviceChannels < ( channels + firstChannel ) ) {
- free( bufferList );
- errorStream_ << "RtApiCore::probeDeviceOpen: the device (" << device << ") does not support the requested channel count.";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- // Look for a single stream meeting our needs.
- UInt32 firstStream, streamCount = 1, streamChannels = 0, channelOffset = 0;
- for ( iStream=0; iStream<nStreams; iStream++ ) {
- streamChannels = bufferList->mBuffers[iStream].mNumberChannels;
- if ( streamChannels >= channels + offsetCounter ) {
- firstStream = iStream;
- channelOffset = offsetCounter;
- foundStream = true;
- break;
- }
- if ( streamChannels > offsetCounter ) break;
- offsetCounter -= streamChannels;
- }
-
- // If we didn't find a single stream above, then we should be able
- // to meet the channel specification with multiple streams.
- if ( foundStream == false ) {
- monoMode = true;
- offsetCounter = firstChannel;
- for ( iStream=0; iStream<nStreams; iStream++ ) {
- streamChannels = bufferList->mBuffers[iStream].mNumberChannels;
- if ( streamChannels > offsetCounter ) break;
- offsetCounter -= streamChannels;
- }
-
- firstStream = iStream;
- channelOffset = offsetCounter;
- Int32 channelCounter = channels + offsetCounter - streamChannels;
-
- if ( streamChannels > 1 ) monoMode = false;
- while ( channelCounter > 0 ) {
- streamChannels = bufferList->mBuffers[++iStream].mNumberChannels;
- if ( streamChannels > 1 ) monoMode = false;
- channelCounter -= streamChannels;
- streamCount++;
- }
- }
-
- free( bufferList );
-
- // Determine the buffer size.
- AudioValueRange bufferRange;
- dataSize = sizeof( AudioValueRange );
- property.mSelector = kAudioDevicePropertyBufferFrameSizeRange;
- result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &bufferRange );
-
- if ( result != noErr ) {
- errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting buffer size range for device (" << device << ").";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- if ( bufferRange.mMinimum > *bufferSize ) *bufferSize = (unsigned long) bufferRange.mMinimum;
- else if ( bufferRange.mMaximum < *bufferSize ) *bufferSize = (unsigned long) bufferRange.mMaximum;
- if ( options && options->flags & RTAUDIO_MINIMIZE_LATENCY ) *bufferSize = (unsigned long) bufferRange.mMinimum;
-
- // Set the buffer size. For multiple streams, I'm assuming we only
- // need to make this setting for the master channel.
- UInt32 theSize = (UInt32) *bufferSize;
- dataSize = sizeof( UInt32 );
- property.mSelector = kAudioDevicePropertyBufferFrameSize;
- result = AudioObjectSetPropertyData( id, &property, 0, NULL, dataSize, &theSize );
-
- if ( result != noErr ) {
- errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") setting the buffer size for device (" << device << ").";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- // If attempting to setup a duplex stream, the bufferSize parameter
- // MUST be the same in both directions!
- *bufferSize = theSize;
- if ( stream_.mode == OUTPUT && mode == INPUT && *bufferSize != stream_.bufferSize ) {
- errorStream_ << "RtApiCore::probeDeviceOpen: system error setting buffer size for duplex stream on device (" << device << ").";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- stream_.bufferSize = *bufferSize;
- stream_.nBuffers = 1;
-
- // Try to set "hog" mode ... it's not clear to me this is working.
- if ( options && options->flags & RTAUDIO_HOG_DEVICE ) {
- pid_t hog_pid;
- dataSize = sizeof( hog_pid );
- property.mSelector = kAudioDevicePropertyHogMode;
- result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &hog_pid );
- if ( result != noErr ) {
- errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting 'hog' state!";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- if ( hog_pid != getpid() ) {
- hog_pid = getpid();
- result = AudioObjectSetPropertyData( id, &property, 0, NULL, dataSize, &hog_pid );
- if ( result != noErr ) {
- errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") setting 'hog' state!";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
- }
- }
-
- // Check and if necessary, change the sample rate for the device.
- Float64 nominalRate;
- dataSize = sizeof( Float64 );
- property.mSelector = kAudioDevicePropertyNominalSampleRate;
- result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &nominalRate );
- if ( result != noErr ) {
- errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting current sample rate.";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- // Only change the sample rate if off by more than 1 Hz.
- if ( fabs( nominalRate - (double)sampleRate ) > 1.0 ) {
-
- // Set a property listener for the sample rate change
- Float64 reportedRate = 0.0;
- AudioObjectPropertyAddress tmp = { kAudioDevicePropertyNominalSampleRate, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
- result = AudioObjectAddPropertyListener( id, &tmp, rateListener, (void *) &reportedRate );
- if ( result != noErr ) {
- errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") setting sample rate property listener for device (" << device << ").";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- nominalRate = (Float64) sampleRate;
- result = AudioObjectSetPropertyData( id, &property, 0, NULL, dataSize, &nominalRate );
- if ( result != noErr ) {
- AudioObjectRemovePropertyListener( id, &tmp, rateListener, (void *) &reportedRate );
- errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") setting sample rate for device (" << device << ").";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- // Now wait until the reported nominal rate is what we just set.
- UInt32 microCounter = 0;
- while ( reportedRate != nominalRate ) {
- microCounter += 5000;
- if ( microCounter > 5000000 ) break;
- usleep( 5000 );
- }
-
- // Remove the property listener.
- AudioObjectRemovePropertyListener( id, &tmp, rateListener, (void *) &reportedRate );
-
- if ( microCounter > 5000000 ) {
- errorStream_ << "RtApiCore::probeDeviceOpen: timeout waiting for sample rate update for device (" << device << ").";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
- }
-
- // Now set the stream format for all streams. Also, check the
- // physical format of the device and change that if necessary.
- AudioStreamBasicDescription description;
- dataSize = sizeof( AudioStreamBasicDescription );
- property.mSelector = kAudioStreamPropertyVirtualFormat;
- result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &description );
- if ( result != noErr ) {
- errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting stream format for device (" << device << ").";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- // Set the sample rate and data format id. However, only make the
- // change if the sample rate is not within 1.0 of the desired
- // rate and the format is not linear pcm.
- bool updateFormat = false;
- if ( fabs( description.mSampleRate - (Float64)sampleRate ) > 1.0 ) {
- description.mSampleRate = (Float64) sampleRate;
- updateFormat = true;
- }
-
- if ( description.mFormatID != kAudioFormatLinearPCM ) {
- description.mFormatID = kAudioFormatLinearPCM;
- updateFormat = true;
- }
-
- if ( updateFormat ) {
- result = AudioObjectSetPropertyData( id, &property, 0, NULL, dataSize, &description );
- if ( result != noErr ) {
- errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") setting sample rate or data format for device (" << device << ").";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
- }
-
- // Now check the physical format.
- property.mSelector = kAudioStreamPropertyPhysicalFormat;
- result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &description );
- if ( result != noErr ) {
- errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting stream physical format for device (" << device << ").";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- //std::cout << "Current physical stream format:" << std::endl;
- //std::cout << " mBitsPerChan = " << description.mBitsPerChannel << std::endl;
- //std::cout << " aligned high = " << (description.mFormatFlags & kAudioFormatFlagIsAlignedHigh) << ", isPacked = " << (description.mFormatFlags & kAudioFormatFlagIsPacked) << std::endl;
- //std::cout << " bytesPerFrame = " << description.mBytesPerFrame << std::endl;
- //std::cout << " sample rate = " << description.mSampleRate << std::endl;
-
- if ( description.mFormatID != kAudioFormatLinearPCM || description.mBitsPerChannel < 16 ) {
- description.mFormatID = kAudioFormatLinearPCM;
- //description.mSampleRate = (Float64) sampleRate;
- AudioStreamBasicDescription testDescription = description;
- UInt32 formatFlags;
-
- // We'll try higher bit rates first and then work our way down.
- std::vector< std::pair<UInt32, UInt32> > physicalFormats;
- formatFlags = (description.mFormatFlags | kLinearPCMFormatFlagIsFloat) & ~kLinearPCMFormatFlagIsSignedInteger;
- physicalFormats.push_back( std::pair<Float32, UInt32>( 32, formatFlags ) );
- formatFlags = (description.mFormatFlags | kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked) & ~kLinearPCMFormatFlagIsFloat;
- physicalFormats.push_back( std::pair<Float32, UInt32>( 32, formatFlags ) );
- physicalFormats.push_back( std::pair<Float32, UInt32>( 24, formatFlags ) ); // 24-bit packed
- formatFlags &= ~( kAudioFormatFlagIsPacked | kAudioFormatFlagIsAlignedHigh );
- physicalFormats.push_back( std::pair<Float32, UInt32>( 24.2, formatFlags ) ); // 24-bit in 4 bytes, aligned low
- formatFlags |= kAudioFormatFlagIsAlignedHigh;
- physicalFormats.push_back( std::pair<Float32, UInt32>( 24.4, formatFlags ) ); // 24-bit in 4 bytes, aligned high
- formatFlags = (description.mFormatFlags | kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked) & ~kLinearPCMFormatFlagIsFloat;
- physicalFormats.push_back( std::pair<Float32, UInt32>( 16, formatFlags ) );
- physicalFormats.push_back( std::pair<Float32, UInt32>( 8, formatFlags ) );
-
- bool setPhysicalFormat = false;
- for( unsigned int i=0; i<physicalFormats.size(); i++ ) {
- testDescription = description;
- testDescription.mBitsPerChannel = (UInt32) physicalFormats[i].first;
- testDescription.mFormatFlags = physicalFormats[i].second;
- if ( (24 == (UInt32)physicalFormats[i].first) && ~( physicalFormats[i].second & kAudioFormatFlagIsPacked ) )
- testDescription.mBytesPerFrame = 4 * testDescription.mChannelsPerFrame;
- else
- testDescription.mBytesPerFrame = testDescription.mBitsPerChannel/8 * testDescription.mChannelsPerFrame;
- testDescription.mBytesPerPacket = testDescription.mBytesPerFrame * testDescription.mFramesPerPacket;
- result = AudioObjectSetPropertyData( id, &property, 0, NULL, dataSize, &testDescription );
- if ( result == noErr ) {
- setPhysicalFormat = true;
- //std::cout << "Updated physical stream format:" << std::endl;
- //std::cout << " mBitsPerChan = " << testDescription.mBitsPerChannel << std::endl;
- //std::cout << " aligned high = " << (testDescription.mFormatFlags & kAudioFormatFlagIsAlignedHigh) << ", isPacked = " << (testDescription.mFormatFlags & kAudioFormatFlagIsPacked) << std::endl;
- //std::cout << " bytesPerFrame = " << testDescription.mBytesPerFrame << std::endl;
- //std::cout << " sample rate = " << testDescription.mSampleRate << std::endl;
- break;
- }
- }
-
- if ( !setPhysicalFormat ) {
- errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") setting physical data format for device (" << device << ").";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
- } // done setting virtual/physical formats.
-
- // Get the stream / device latency.
- UInt32 latency;
- dataSize = sizeof( UInt32 );
- property.mSelector = kAudioDevicePropertyLatency;
- if ( AudioObjectHasProperty( id, &property ) == true ) {
- result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &latency );
- if ( result == kAudioHardwareNoError ) stream_.latency[ mode ] = latency;
- else {
- errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting device latency for device (" << device << ").";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- }
- }
-
- // Byte-swapping: According to AudioHardware.h, the stream data will
- // always be presented in native-endian format, so we should never
- // need to byte swap.
- stream_.doByteSwap[mode] = false;
-
- // From the CoreAudio documentation, PCM data must be supplied as
- // 32-bit floats.
- stream_.userFormat = format;
- stream_.deviceFormat[mode] = RTAUDIO_FLOAT32;
-
- if ( streamCount == 1 )
- stream_.nDeviceChannels[mode] = description.mChannelsPerFrame;
- else // multiple streams
- stream_.nDeviceChannels[mode] = channels;
- stream_.nUserChannels[mode] = channels;
- stream_.channelOffset[mode] = channelOffset; // offset within a CoreAudio stream
- if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) stream_.userInterleaved = false;
- else stream_.userInterleaved = true;
- stream_.deviceInterleaved[mode] = true;
- if ( monoMode == true ) stream_.deviceInterleaved[mode] = false;
-
- // Set flags for buffer conversion.
- stream_.doConvertBuffer[mode] = false;
- if ( stream_.userFormat != stream_.deviceFormat[mode] )
- stream_.doConvertBuffer[mode] = true;
- if ( stream_.nUserChannels[mode] < stream_.nDeviceChannels[mode] )
- stream_.doConvertBuffer[mode] = true;
- if ( streamCount == 1 ) {
- if ( stream_.nUserChannels[mode] > 1 &&
- stream_.userInterleaved != stream_.deviceInterleaved[mode] )
- stream_.doConvertBuffer[mode] = true;
- }
- else if ( monoMode && stream_.userInterleaved )
- stream_.doConvertBuffer[mode] = true;
-
- // Allocate our CoreHandle structure for the stream.
- CoreHandle *handle = 0;
- if ( stream_.apiHandle == 0 ) {
- try {
- handle = new CoreHandle;
- }
- catch ( std::bad_alloc& ) {
- errorText_ = "RtApiCore::probeDeviceOpen: error allocating CoreHandle memory.";
- goto error;
- }
-
- if ( pthread_cond_init( &handle->condition, NULL ) ) {
- errorText_ = "RtApiCore::probeDeviceOpen: error initializing pthread condition variable.";
- goto error;
- }
- stream_.apiHandle = (void *) handle;
- }
- else
- handle = (CoreHandle *) stream_.apiHandle;
- handle->iStream[mode] = firstStream;
- handle->nStreams[mode] = streamCount;
- handle->id[mode] = id;
-
- // Allocate necessary internal buffers.
- unsigned long bufferBytes;
- bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat );
- // stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 );
- stream_.userBuffer[mode] = (char *) malloc( bufferBytes * sizeof(char) );
- memset( stream_.userBuffer[mode], 0, bufferBytes * sizeof(char) );
- if ( stream_.userBuffer[mode] == NULL ) {
- errorText_ = "RtApiCore::probeDeviceOpen: error allocating user buffer memory.";
- goto error;
- }
-
- // If possible, we will make use of the CoreAudio stream buffers as
- // "device buffers". However, we can't do this if using multiple
- // streams.
- if ( stream_.doConvertBuffer[mode] && handle->nStreams[mode] > 1 ) {
-
- bool makeBuffer = true;
- bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] );
- if ( mode == INPUT ) {
- if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) {
- unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] );
- if ( bufferBytes <= bytesOut ) makeBuffer = false;
- }
- }
-
- if ( makeBuffer ) {
- bufferBytes *= *bufferSize;
- if ( stream_.deviceBuffer ) free( stream_.deviceBuffer );
- stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 );
- if ( stream_.deviceBuffer == NULL ) {
- errorText_ = "RtApiCore::probeDeviceOpen: error allocating device buffer memory.";
- goto error;
- }
- }
- }
-
- stream_.sampleRate = sampleRate;
- stream_.device[mode] = device;
- stream_.state = STREAM_STOPPED;
- stream_.callbackInfo.object = (void *) this;
-
- // Setup the buffer conversion information structure.
- if ( stream_.doConvertBuffer[mode] ) {
- if ( streamCount > 1 ) setConvertInfo( mode, 0 );
- else setConvertInfo( mode, channelOffset );
- }
-
- if ( mode == INPUT && stream_.mode == OUTPUT && stream_.device[0] == device )
- // Only one callback procedure per device.
- stream_.mode = DUPLEX;
- else {
-#if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 )
- result = AudioDeviceCreateIOProcID( id, callbackHandler, (void *) &stream_.callbackInfo, &handle->procId[mode] );
-#else
- // deprecated in favor of AudioDeviceCreateIOProcID()
- result = AudioDeviceAddIOProc( id, callbackHandler, (void *) &stream_.callbackInfo );
-#endif
- if ( result != noErr ) {
- errorStream_ << "RtApiCore::probeDeviceOpen: system error setting callback for device (" << device << ").";
- errorText_ = errorStream_.str();
- goto error;
- }
- if ( stream_.mode == OUTPUT && mode == INPUT )
- stream_.mode = DUPLEX;
- else
- stream_.mode = mode;
- }
-
- // Setup the device property listener for over/underload.
- property.mSelector = kAudioDeviceProcessorOverload;
- property.mScope = kAudioObjectPropertyScopeGlobal;
- result = AudioObjectAddPropertyListener( id, &property, xrunListener, (void *) handle );
-
- return SUCCESS;
-
- error:
- if ( handle ) {
- pthread_cond_destroy( &handle->condition );
- delete handle;
- stream_.apiHandle = 0;
- }
-
- for ( int i=0; i<2; i++ ) {
- if ( stream_.userBuffer[i] ) {
- free( stream_.userBuffer[i] );
- stream_.userBuffer[i] = 0;
- }
- }
-
- if ( stream_.deviceBuffer ) {
- free( stream_.deviceBuffer );
- stream_.deviceBuffer = 0;
- }
-
- stream_.state = STREAM_CLOSED;
- return FAILURE;
-}
-
-void RtApiCore :: closeStream( void )
-{
- if ( stream_.state == STREAM_CLOSED ) {
- errorText_ = "RtApiCore::closeStream(): no open stream to close!";
- error( RtAudioError::WARNING );
- return;
- }
-
- CoreHandle *handle = (CoreHandle *) stream_.apiHandle;
- if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
- if (handle) {
- AudioObjectPropertyAddress property = { kAudioHardwarePropertyDevices,
- kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster };
-
- property.mSelector = kAudioDeviceProcessorOverload;
- property.mScope = kAudioObjectPropertyScopeGlobal;
- if (AudioObjectRemovePropertyListener( handle->id[0], &property, xrunListener, (void *) handle ) != noErr) {
- errorText_ = "RtApiCore::closeStream(): error removing property listener!";
- error( RtAudioError::WARNING );
- }
- }
- if ( stream_.state == STREAM_RUNNING )
- AudioDeviceStop( handle->id[0], callbackHandler );
-#if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 )
- AudioDeviceDestroyIOProcID( handle->id[0], handle->procId[0] );
-#else
- // deprecated in favor of AudioDeviceDestroyIOProcID()
- AudioDeviceRemoveIOProc( handle->id[0], callbackHandler );
-#endif
- }
-
- if ( stream_.mode == INPUT || ( stream_.mode == DUPLEX && stream_.device[0] != stream_.device[1] ) ) {
- if (handle) {
- AudioObjectPropertyAddress property = { kAudioHardwarePropertyDevices,
- kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster };
-
- property.mSelector = kAudioDeviceProcessorOverload;
- property.mScope = kAudioObjectPropertyScopeGlobal;
- if (AudioObjectRemovePropertyListener( handle->id[1], &property, xrunListener, (void *) handle ) != noErr) {
- errorText_ = "RtApiCore::closeStream(): error removing property listener!";
- error( RtAudioError::WARNING );
- }
- }
- if ( stream_.state == STREAM_RUNNING )
- AudioDeviceStop( handle->id[1], callbackHandler );
-#if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 )
- AudioDeviceDestroyIOProcID( handle->id[1], handle->procId[1] );
-#else
- // deprecated in favor of AudioDeviceDestroyIOProcID()
- AudioDeviceRemoveIOProc( handle->id[1], callbackHandler );
-#endif
- }
-
- for ( int i=0; i<2; i++ ) {
- if ( stream_.userBuffer[i] ) {
- free( stream_.userBuffer[i] );
- stream_.userBuffer[i] = 0;
- }
- }
-
- if ( stream_.deviceBuffer ) {
- free( stream_.deviceBuffer );
- stream_.deviceBuffer = 0;
- }
-
- // Destroy pthread condition variable.
- pthread_cond_destroy( &handle->condition );
- delete handle;
- stream_.apiHandle = 0;
-
- stream_.mode = UNINITIALIZED;
- stream_.state = STREAM_CLOSED;
-}
-
-void RtApiCore :: startStream( void )
-{
- verifyStream();
- if ( stream_.state == STREAM_RUNNING ) {
- errorText_ = "RtApiCore::startStream(): the stream is already running!";
- error( RtAudioError::WARNING );
- return;
- }
-
- OSStatus result = noErr;
- CoreHandle *handle = (CoreHandle *) stream_.apiHandle;
- if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
-
- result = AudioDeviceStart( handle->id[0], callbackHandler );
- if ( result != noErr ) {
- errorStream_ << "RtApiCore::startStream: system error (" << getErrorCode( result ) << ") starting callback procedure on device (" << stream_.device[0] << ").";
- errorText_ = errorStream_.str();
- goto unlock;
- }
- }
-
- if ( stream_.mode == INPUT ||
- ( stream_.mode == DUPLEX && stream_.device[0] != stream_.device[1] ) ) {
-
- result = AudioDeviceStart( handle->id[1], callbackHandler );
- if ( result != noErr ) {
- errorStream_ << "RtApiCore::startStream: system error starting input callback procedure on device (" << stream_.device[1] << ").";
- errorText_ = errorStream_.str();
- goto unlock;
- }
- }
-
- handle->drainCounter = 0;
- handle->internalDrain = false;
- stream_.state = STREAM_RUNNING;
-
- unlock:
- if ( result == noErr ) return;
- error( RtAudioError::SYSTEM_ERROR );
-}
-
-void RtApiCore :: stopStream( void )
-{
- verifyStream();
- if ( stream_.state == STREAM_STOPPED ) {
- errorText_ = "RtApiCore::stopStream(): the stream is already stopped!";
- error( RtAudioError::WARNING );
- return;
- }
-
- OSStatus result = noErr;
- CoreHandle *handle = (CoreHandle *) stream_.apiHandle;
- if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
-
- if ( handle->drainCounter == 0 ) {
- handle->drainCounter = 2;
- pthread_cond_wait( &handle->condition, &stream_.mutex ); // block until signaled
- }
-
- result = AudioDeviceStop( handle->id[0], callbackHandler );
- if ( result != noErr ) {
- errorStream_ << "RtApiCore::stopStream: system error (" << getErrorCode( result ) << ") stopping callback procedure on device (" << stream_.device[0] << ").";
- errorText_ = errorStream_.str();
- goto unlock;
- }
- }
-
- if ( stream_.mode == INPUT || ( stream_.mode == DUPLEX && stream_.device[0] != stream_.device[1] ) ) {
-
- result = AudioDeviceStop( handle->id[1], callbackHandler );
- if ( result != noErr ) {
- errorStream_ << "RtApiCore::stopStream: system error (" << getErrorCode( result ) << ") stopping input callback procedure on device (" << stream_.device[1] << ").";
- errorText_ = errorStream_.str();
- goto unlock;
- }
- }
-
- stream_.state = STREAM_STOPPED;
-
- unlock:
- if ( result == noErr ) return;
- error( RtAudioError::SYSTEM_ERROR );
-}
-
-void RtApiCore :: abortStream( void )
-{
- verifyStream();
- if ( stream_.state == STREAM_STOPPED ) {
- errorText_ = "RtApiCore::abortStream(): the stream is already stopped!";
- error( RtAudioError::WARNING );
- return;
- }
-
- CoreHandle *handle = (CoreHandle *) stream_.apiHandle;
- handle->drainCounter = 2;
-
- stopStream();
-}
-
-// This function will be called by a spawned thread when the user
-// callback function signals that the stream should be stopped or
-// aborted. It is better to handle it this way because the
-// callbackEvent() function probably should return before the AudioDeviceStop()
-// function is called.
-static void *coreStopStream( void *ptr )
-{
- CallbackInfo *info = (CallbackInfo *) ptr;
- RtApiCore *object = (RtApiCore *) info->object;
-
- object->stopStream();
- pthread_exit( NULL );
-}
-
-bool RtApiCore :: callbackEvent( AudioDeviceID deviceId,
- const AudioBufferList *inBufferList,
- const AudioBufferList *outBufferList )
-{
- if ( stream_.state == STREAM_STOPPED || stream_.state == STREAM_STOPPING ) return SUCCESS;
- if ( stream_.state == STREAM_CLOSED ) {
- errorText_ = "RtApiCore::callbackEvent(): the stream is closed ... this shouldn't happen!";
- error( RtAudioError::WARNING );
- return FAILURE;
- }
-
- CallbackInfo *info = (CallbackInfo *) &stream_.callbackInfo;
- CoreHandle *handle = (CoreHandle *) stream_.apiHandle;
-
- // Check if we were draining the stream and signal is finished.
- if ( handle->drainCounter > 3 ) {
- ThreadHandle threadId;
-
- stream_.state = STREAM_STOPPING;
- if ( handle->internalDrain == true )
- pthread_create( &threadId, NULL, coreStopStream, info );
- else // external call to stopStream()
- pthread_cond_signal( &handle->condition );
- return SUCCESS;
- }
-
- AudioDeviceID outputDevice = handle->id[0];
-
- // Invoke user callback to get fresh output data UNLESS we are
- // draining stream or duplex mode AND the input/output devices are
- // different AND this function is called for the input device.
- if ( handle->drainCounter == 0 && ( stream_.mode != DUPLEX || deviceId == outputDevice ) ) {
- RtAudioCallback callback = (RtAudioCallback) info->callback;
- double streamTime = getStreamTime();
- RtAudioStreamStatus status = 0;
- if ( stream_.mode != INPUT && handle->xrun[0] == true ) {
- status |= RTAUDIO_OUTPUT_UNDERFLOW;
- handle->xrun[0] = false;
- }
- if ( stream_.mode != OUTPUT && handle->xrun[1] == true ) {
- status |= RTAUDIO_INPUT_OVERFLOW;
- handle->xrun[1] = false;
- }
-
- int cbReturnValue = callback( stream_.userBuffer[0], stream_.userBuffer[1],
- stream_.bufferSize, streamTime, status, info->userData );
- if ( cbReturnValue == 2 ) {
- stream_.state = STREAM_STOPPING;
- handle->drainCounter = 2;
- abortStream();
- return SUCCESS;
- }
- else if ( cbReturnValue == 1 ) {
- handle->drainCounter = 1;
- handle->internalDrain = true;
- }
- }
-
- if ( stream_.mode == OUTPUT || ( stream_.mode == DUPLEX && deviceId == outputDevice ) ) {
-
- if ( handle->drainCounter > 1 ) { // write zeros to the output stream
-
- if ( handle->nStreams[0] == 1 ) {
- memset( outBufferList->mBuffers[handle->iStream[0]].mData,
- 0,
- outBufferList->mBuffers[handle->iStream[0]].mDataByteSize );
- }
- else { // fill multiple streams with zeros
- for ( unsigned int i=0; i<handle->nStreams[0]; i++ ) {
- memset( outBufferList->mBuffers[handle->iStream[0]+i].mData,
- 0,
- outBufferList->mBuffers[handle->iStream[0]+i].mDataByteSize );
- }
- }
- }
- else if ( handle->nStreams[0] == 1 ) {
- if ( stream_.doConvertBuffer[0] ) { // convert directly to CoreAudio stream buffer
- convertBuffer( (char *) outBufferList->mBuffers[handle->iStream[0]].mData,
- stream_.userBuffer[0], stream_.convertInfo[0] );
- }
- else { // copy from user buffer
- memcpy( outBufferList->mBuffers[handle->iStream[0]].mData,
- stream_.userBuffer[0],
- outBufferList->mBuffers[handle->iStream[0]].mDataByteSize );
- }
- }
- else { // fill multiple streams
- Float32 *inBuffer = (Float32 *) stream_.userBuffer[0];
- if ( stream_.doConvertBuffer[0] ) {
- convertBuffer( stream_.deviceBuffer, stream_.userBuffer[0], stream_.convertInfo[0] );
- inBuffer = (Float32 *) stream_.deviceBuffer;
- }
-
- if ( stream_.deviceInterleaved[0] == false ) { // mono mode
- UInt32 bufferBytes = outBufferList->mBuffers[handle->iStream[0]].mDataByteSize;
- for ( unsigned int i=0; i<stream_.nUserChannels[0]; i++ ) {
- memcpy( outBufferList->mBuffers[handle->iStream[0]+i].mData,
- (void *)&inBuffer[i*stream_.bufferSize], bufferBytes );
- }
- }
- else { // fill multiple multi-channel streams with interleaved data
- UInt32 streamChannels, channelsLeft, inJump, outJump, inOffset;
- Float32 *out, *in;
-
- bool inInterleaved = ( stream_.userInterleaved ) ? true : false;
- UInt32 inChannels = stream_.nUserChannels[0];
- if ( stream_.doConvertBuffer[0] ) {
- inInterleaved = true; // device buffer will always be interleaved for nStreams > 1 and not mono mode
- inChannels = stream_.nDeviceChannels[0];
- }
-
- if ( inInterleaved ) inOffset = 1;
- else inOffset = stream_.bufferSize;
-
- channelsLeft = inChannels;
- for ( unsigned int i=0; i<handle->nStreams[0]; i++ ) {
- in = inBuffer;
- out = (Float32 *) outBufferList->mBuffers[handle->iStream[0]+i].mData;
- streamChannels = outBufferList->mBuffers[handle->iStream[0]+i].mNumberChannels;
-
- outJump = 0;
- // Account for possible channel offset in first stream
- if ( i == 0 && stream_.channelOffset[0] > 0 ) {
- streamChannels -= stream_.channelOffset[0];
- outJump = stream_.channelOffset[0];
- out += outJump;
- }
-
- // Account for possible unfilled channels at end of the last stream
- if ( streamChannels > channelsLeft ) {
- outJump = streamChannels - channelsLeft;
- streamChannels = channelsLeft;
- }
-
- // Determine input buffer offsets and skips
- if ( inInterleaved ) {
- inJump = inChannels;
- in += inChannels - channelsLeft;
- }
- else {
- inJump = 1;
- in += (inChannels - channelsLeft) * inOffset;
- }
-
- for ( unsigned int i=0; i<stream_.bufferSize; i++ ) {
- for ( unsigned int j=0; j<streamChannels; j++ ) {
- *out++ = in[j*inOffset];
- }
- out += outJump;
- in += inJump;
- }
- channelsLeft -= streamChannels;
- }
- }
- }
- }
-
- // Don't bother draining input
- if ( handle->drainCounter ) {
- handle->drainCounter++;
- goto unlock;
- }
-
- AudioDeviceID inputDevice;
- inputDevice = handle->id[1];
- if ( stream_.mode == INPUT || ( stream_.mode == DUPLEX && deviceId == inputDevice ) ) {
-
- if ( handle->nStreams[1] == 1 ) {
- if ( stream_.doConvertBuffer[1] ) { // convert directly from CoreAudio stream buffer
- convertBuffer( stream_.userBuffer[1],
- (char *) inBufferList->mBuffers[handle->iStream[1]].mData,
- stream_.convertInfo[1] );
- }
- else { // copy to user buffer
- memcpy( stream_.userBuffer[1],
- inBufferList->mBuffers[handle->iStream[1]].mData,
- inBufferList->mBuffers[handle->iStream[1]].mDataByteSize );
- }
- }
- else { // read from multiple streams
- Float32 *outBuffer = (Float32 *) stream_.userBuffer[1];
- if ( stream_.doConvertBuffer[1] ) outBuffer = (Float32 *) stream_.deviceBuffer;
-
- if ( stream_.deviceInterleaved[1] == false ) { // mono mode
- UInt32 bufferBytes = inBufferList->mBuffers[handle->iStream[1]].mDataByteSize;
- for ( unsigned int i=0; i<stream_.nUserChannels[1]; i++ ) {
- memcpy( (void *)&outBuffer[i*stream_.bufferSize],
- inBufferList->mBuffers[handle->iStream[1]+i].mData, bufferBytes );
- }
- }
- else { // read from multiple multi-channel streams
- UInt32 streamChannels, channelsLeft, inJump, outJump, outOffset;
- Float32 *out, *in;
-
- bool outInterleaved = ( stream_.userInterleaved ) ? true : false;
- UInt32 outChannels = stream_.nUserChannels[1];
- if ( stream_.doConvertBuffer[1] ) {
- outInterleaved = true; // device buffer will always be interleaved for nStreams > 1 and not mono mode
- outChannels = stream_.nDeviceChannels[1];
- }
-
- if ( outInterleaved ) outOffset = 1;
- else outOffset = stream_.bufferSize;
-
- channelsLeft = outChannels;
- for ( unsigned int i=0; i<handle->nStreams[1]; i++ ) {
- out = outBuffer;
- in = (Float32 *) inBufferList->mBuffers[handle->iStream[1]+i].mData;
- streamChannels = inBufferList->mBuffers[handle->iStream[1]+i].mNumberChannels;
-
- inJump = 0;
- // Account for possible channel offset in first stream
- if ( i == 0 && stream_.channelOffset[1] > 0 ) {
- streamChannels -= stream_.channelOffset[1];
- inJump = stream_.channelOffset[1];
- in += inJump;
- }
-
- // Account for possible unread channels at end of the last stream
- if ( streamChannels > channelsLeft ) {
- inJump = streamChannels - channelsLeft;
- streamChannels = channelsLeft;
- }
-
- // Determine output buffer offsets and skips
- if ( outInterleaved ) {
- outJump = outChannels;
- out += outChannels - channelsLeft;
- }
- else {
- outJump = 1;
- out += (outChannels - channelsLeft) * outOffset;
- }
-
- for ( unsigned int i=0; i<stream_.bufferSize; i++ ) {
- for ( unsigned int j=0; j<streamChannels; j++ ) {
- out[j*outOffset] = *in++;
- }
- out += outJump;
- in += inJump;
- }
- channelsLeft -= streamChannels;
- }
- }
-
- if ( stream_.doConvertBuffer[1] ) { // convert from our internal "device" buffer
- convertBuffer( stream_.userBuffer[1],
- stream_.deviceBuffer,
- stream_.convertInfo[1] );
- }
- }
- }
-
- unlock:
- //MUTEX_UNLOCK( &stream_.mutex );
-
- RtApi::tickStreamTime();
- return SUCCESS;
-}
-
-const char* RtApiCore :: getErrorCode( OSStatus code )
-{
- switch( code ) {
-
- case kAudioHardwareNotRunningError:
- return "kAudioHardwareNotRunningError";
-
- case kAudioHardwareUnspecifiedError:
- return "kAudioHardwareUnspecifiedError";
-
- case kAudioHardwareUnknownPropertyError:
- return "kAudioHardwareUnknownPropertyError";
-
- case kAudioHardwareBadPropertySizeError:
- return "kAudioHardwareBadPropertySizeError";
-
- case kAudioHardwareIllegalOperationError:
- return "kAudioHardwareIllegalOperationError";
-
- case kAudioHardwareBadObjectError:
- return "kAudioHardwareBadObjectError";
-
- case kAudioHardwareBadDeviceError:
- return "kAudioHardwareBadDeviceError";
-
- case kAudioHardwareBadStreamError:
- return "kAudioHardwareBadStreamError";
-
- case kAudioHardwareUnsupportedOperationError:
- return "kAudioHardwareUnsupportedOperationError";
-
- case kAudioDeviceUnsupportedFormatError:
- return "kAudioDeviceUnsupportedFormatError";
-
- case kAudioDevicePermissionsError:
- return "kAudioDevicePermissionsError";
-
- default:
- return "CoreAudio unknown error";
- }
-}
-
- //******************** End of __MACOSX_CORE__ *********************//
-#endif
-
-#if defined(__UNIX_JACK__)
-
-// JACK is a low-latency audio server, originally written for the
-// GNU/Linux operating system and now also ported to OS-X. It can
-// connect a number of different applications to an audio device, as
-// well as allowing them to share audio between themselves.
-//
-// When using JACK with RtAudio, "devices" refer to JACK clients that
-// have ports connected to the server. The JACK server is typically
-// started in a terminal as follows:
-//
-// .jackd -d alsa -d hw:0
-//
-// or through an interface program such as qjackctl. Many of the
-// parameters normally set for a stream are fixed by the JACK server
-// and can be specified when the JACK server is started. In
-// particular,
-//
-// .jackd -d alsa -d hw:0 -r 44100 -p 512 -n 4
-//
-// specifies a sample rate of 44100 Hz, a buffer size of 512 sample
-// frames, and number of buffers = 4. Once the server is running, it
-// is not possible to override these values. If the values are not
-// specified in the command-line, the JACK server uses default values.
-//
-// The JACK server does not have to be running when an instance of
-// RtApiJack is created, though the function getDeviceCount() will
-// report 0 devices found until JACK has been started. When no
-// devices are available (i.e., the JACK server is not running), a
-// stream cannot be opened.
-
-#include <jack/jack.h>
-#include <unistd.h>
-#include <cstdio>
-
-// A structure to hold various information related to the Jack API
-// implementation.
-struct JackHandle {
- jack_client_t *client;
- jack_port_t **ports[2];
- std::string deviceName[2];
- bool xrun[2];
- pthread_cond_t condition;
- int drainCounter; // Tracks callback counts when draining
- bool internalDrain; // Indicates if stop is initiated from callback or not.
-
- JackHandle()
- :client(0), drainCounter(0), internalDrain(false) { ports[0] = 0; ports[1] = 0; xrun[0] = false; xrun[1] = false; }
-};
-
-static void jackSilentError( const char * ) {};
-
-RtApiJack :: RtApiJack()
-{
- // Nothing to do here.
-#if !defined(__RTAUDIO_DEBUG__)
- // Turn off Jack's internal error reporting.
- jack_set_error_function( &jackSilentError );
-#endif
-}
-
-RtApiJack :: ~RtApiJack()
-{
- if ( stream_.state != STREAM_CLOSED ) closeStream();
-}
-
-unsigned int RtApiJack :: getDeviceCount( void )
-{
- // See if we can become a jack client.
- jack_options_t options = (jack_options_t) ( JackNoStartServer ); //JackNullOption;
- jack_status_t *status = NULL;
- jack_client_t *client = jack_client_open( "RtApiJackCount", options, status );
- if ( client == 0 ) return 0;
-
- const char **ports;
- std::string port, previousPort;
- unsigned int nChannels = 0, nDevices = 0;
- ports = jack_get_ports( client, NULL, NULL, 0 );
- if ( ports ) {
- // Parse the port names up to the first colon (:).
- size_t iColon = 0;
- do {
- port = (char *) ports[ nChannels ];
- iColon = port.find(":");
- if ( iColon != std::string::npos ) {
- port = port.substr( 0, iColon + 1 );
- if ( port != previousPort ) {
- nDevices++;
- previousPort = port;
- }
- }
- } while ( ports[++nChannels] );
- free( ports );
- }
-
- jack_client_close( client );
- return nDevices;
-}
-
-RtAudio::DeviceInfo RtApiJack :: getDeviceInfo( unsigned int device )
-{
- RtAudio::DeviceInfo info;
- info.probed = false;
-
- jack_options_t options = (jack_options_t) ( JackNoStartServer ); //JackNullOption
- jack_status_t *status = NULL;
- jack_client_t *client = jack_client_open( "RtApiJackInfo", options, status );
- if ( client == 0 ) {
- errorText_ = "RtApiJack::getDeviceInfo: Jack server not found or connection error!";
- error( RtAudioError::WARNING );
- return info;
- }
-
- const char **ports;
- std::string port, previousPort;
- unsigned int nPorts = 0, nDevices = 0;
- ports = jack_get_ports( client, NULL, NULL, 0 );
- if ( ports ) {
- // Parse the port names up to the first colon (:).
- size_t iColon = 0;
- do {
- port = (char *) ports[ nPorts ];
- iColon = port.find(":");
- if ( iColon != std::string::npos ) {
- port = port.substr( 0, iColon );
- if ( port != previousPort ) {
- if ( nDevices == device ) info.name = port;
- nDevices++;
- previousPort = port;
- }
- }
- } while ( ports[++nPorts] );
- free( ports );
- }
-
- if ( device >= nDevices ) {
- jack_client_close( client );
- errorText_ = "RtApiJack::getDeviceInfo: device ID is invalid!";
- error( RtAudioError::INVALID_USE );
- return info;
- }
-
- // Get the current jack server sample rate.
- info.sampleRates.clear();
-
- info.preferredSampleRate = jack_get_sample_rate( client );
- info.sampleRates.push_back( info.preferredSampleRate );
-
- // Count the available ports containing the client name as device
- // channels. Jack "input ports" equal RtAudio output channels.
- unsigned int nChannels = 0;
- ports = jack_get_ports( client, info.name.c_str(), NULL, JackPortIsInput );
- if ( ports ) {
- while ( ports[ nChannels ] ) nChannels++;
- free( ports );
- info.outputChannels = nChannels;
- }
-
- // Jack "output ports" equal RtAudio input channels.
- nChannels = 0;
- ports = jack_get_ports( client, info.name.c_str(), NULL, JackPortIsOutput );
- if ( ports ) {
- while ( ports[ nChannels ] ) nChannels++;
- free( ports );
- info.inputChannels = nChannels;
- }
-
- if ( info.outputChannels == 0 && info.inputChannels == 0 ) {
- jack_client_close(client);
- errorText_ = "RtApiJack::getDeviceInfo: error determining Jack input/output channels!";
- error( RtAudioError::WARNING );
- return info;
- }
-
- // If device opens for both playback and capture, we determine the channels.
- if ( info.outputChannels > 0 && info.inputChannels > 0 )
- info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels;
-
- // Jack always uses 32-bit floats.
- info.nativeFormats = RTAUDIO_FLOAT32;
-
- // Jack doesn't provide default devices so we'll use the first available one.
- if ( device == 0 && info.outputChannels > 0 )
- info.isDefaultOutput = true;
- if ( device == 0 && info.inputChannels > 0 )
- info.isDefaultInput = true;
-
- jack_client_close(client);
- info.probed = true;
- return info;
-}
-
-static int jackCallbackHandler( jack_nframes_t nframes, void *infoPointer )
-{
- CallbackInfo *info = (CallbackInfo *) infoPointer;
-
- RtApiJack *object = (RtApiJack *) info->object;
- if ( object->callbackEvent( (unsigned long) nframes ) == false ) return 1;
-
- return 0;
-}
-
-// This function will be called by a spawned thread when the Jack
-// server signals that it is shutting down. It is necessary to handle
-// it this way because the jackShutdown() function must return before
-// the jack_deactivate() function (in closeStream()) will return.
-static void *jackCloseStream( void *ptr )
-{
- CallbackInfo *info = (CallbackInfo *) ptr;
- RtApiJack *object = (RtApiJack *) info->object;
-
- object->closeStream();
-
- pthread_exit( NULL );
-}
-static void jackShutdown( void *infoPointer )
-{
- CallbackInfo *info = (CallbackInfo *) infoPointer;
- RtApiJack *object = (RtApiJack *) info->object;
-
- // Check current stream state. If stopped, then we'll assume this
- // was called as a result of a call to RtApiJack::stopStream (the
- // deactivation of a client handle causes this function to be called).
- // If not, we'll assume the Jack server is shutting down or some
- // other problem occurred and we should close the stream.
- if ( object->isStreamRunning() == false ) return;
-
- ThreadHandle threadId;
- pthread_create( &threadId, NULL, jackCloseStream, info );
- std::cerr << "\nRtApiJack: the Jack server is shutting down this client ... stream stopped and closed!!\n" << std::endl;
-}
-
-static int jackXrun( void *infoPointer )
-{
- JackHandle *handle = (JackHandle *) infoPointer;
-
- if ( handle->ports[0] ) handle->xrun[0] = true;
- if ( handle->ports[1] ) handle->xrun[1] = true;
-
- return 0;
-}
-
-bool RtApiJack :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,
- unsigned int firstChannel, unsigned int sampleRate,
- RtAudioFormat format, unsigned int *bufferSize,
- RtAudio::StreamOptions *options )
-{
- JackHandle *handle = (JackHandle *) stream_.apiHandle;
-
- // Look for jack server and try to become a client (only do once per stream).
- jack_client_t *client = 0;
- if ( mode == OUTPUT || ( mode == INPUT && stream_.mode != OUTPUT ) ) {
- jack_options_t jackoptions = (jack_options_t) ( JackNoStartServer ); //JackNullOption;
- jack_status_t *status = NULL;
- if ( options && !options->streamName.empty() )
- client = jack_client_open( options->streamName.c_str(), jackoptions, status );
- else
- client = jack_client_open( "RtApiJack", jackoptions, status );
- if ( client == 0 ) {
- errorText_ = "RtApiJack::probeDeviceOpen: Jack server not found or connection error!";
- error( RtAudioError::WARNING );
- return FAILURE;
- }
- }
- else {
- // The handle must have been created on an earlier pass.
- client = handle->client;
- }
-
- const char **ports;
- std::string port, previousPort, deviceName;
- unsigned int nPorts = 0, nDevices = 0;
- ports = jack_get_ports( client, NULL, NULL, 0 );
- if ( ports ) {
- // Parse the port names up to the first colon (:).
- size_t iColon = 0;
- do {
- port = (char *) ports[ nPorts ];
- iColon = port.find(":");
- if ( iColon != std::string::npos ) {
- port = port.substr( 0, iColon );
- if ( port != previousPort ) {
- if ( nDevices == device ) deviceName = port;
- nDevices++;
- previousPort = port;
- }
- }
- } while ( ports[++nPorts] );
- free( ports );
- }
-
- if ( device >= nDevices ) {
- errorText_ = "RtApiJack::probeDeviceOpen: device ID is invalid!";
- return FAILURE;
- }
-
- // Count the available ports containing the client name as device
- // channels. Jack "input ports" equal RtAudio output channels.
- unsigned int nChannels = 0;
- unsigned long flag = JackPortIsInput;
- if ( mode == INPUT ) flag = JackPortIsOutput;
- ports = jack_get_ports( client, deviceName.c_str(), NULL, flag );
- if ( ports ) {
- while ( ports[ nChannels ] ) nChannels++;
- free( ports );
- }
-
- // Compare the jack ports for specified client to the requested number of channels.
- if ( nChannels < (channels + firstChannel) ) {
- errorStream_ << "RtApiJack::probeDeviceOpen: requested number of channels (" << channels << ") + offset (" << firstChannel << ") not found for specified device (" << device << ":" << deviceName << ").";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- // Check the jack server sample rate.
- unsigned int jackRate = jack_get_sample_rate( client );
- if ( sampleRate != jackRate ) {
- jack_client_close( client );
- errorStream_ << "RtApiJack::probeDeviceOpen: the requested sample rate (" << sampleRate << ") is different than the JACK server rate (" << jackRate << ").";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
- stream_.sampleRate = jackRate;
-
- // Get the latency of the JACK port.
- ports = jack_get_ports( client, deviceName.c_str(), NULL, flag );
- if ( ports[ firstChannel ] ) {
- // Added by Ge Wang
- jack_latency_callback_mode_t cbmode = (mode == INPUT ? JackCaptureLatency : JackPlaybackLatency);
- // the range (usually the min and max are equal)
- jack_latency_range_t latrange; latrange.min = latrange.max = 0;
- // get the latency range
- jack_port_get_latency_range( jack_port_by_name( client, ports[firstChannel] ), cbmode, &latrange );
- // be optimistic, use the min!
- stream_.latency[mode] = latrange.min;
- //stream_.latency[mode] = jack_port_get_latency( jack_port_by_name( client, ports[ firstChannel ] ) );
- }
- free( ports );
-
- // The jack server always uses 32-bit floating-point data.
- stream_.deviceFormat[mode] = RTAUDIO_FLOAT32;
- stream_.userFormat = format;
-
- if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) stream_.userInterleaved = false;
- else stream_.userInterleaved = true;
-
- // Jack always uses non-interleaved buffers.
- stream_.deviceInterleaved[mode] = false;
-
- // Jack always provides host byte-ordered data.
- stream_.doByteSwap[mode] = false;
-
- // Get the buffer size. The buffer size and number of buffers
- // (periods) is set when the jack server is started.
- stream_.bufferSize = (int) jack_get_buffer_size( client );
- *bufferSize = stream_.bufferSize;
-
- stream_.nDeviceChannels[mode] = channels;
- stream_.nUserChannels[mode] = channels;
-
- // Set flags for buffer conversion.
- stream_.doConvertBuffer[mode] = false;
- if ( stream_.userFormat != stream_.deviceFormat[mode] )
- stream_.doConvertBuffer[mode] = true;
- if ( stream_.userInterleaved != stream_.deviceInterleaved[mode] &&
- stream_.nUserChannels[mode] > 1 )
- stream_.doConvertBuffer[mode] = true;
-
- // Allocate our JackHandle structure for the stream.
- if ( handle == 0 ) {
- try {
- handle = new JackHandle;
- }
- catch ( std::bad_alloc& ) {
- errorText_ = "RtApiJack::probeDeviceOpen: error allocating JackHandle memory.";
- goto error;
- }
-
- if ( pthread_cond_init(&handle->condition, NULL) ) {
- errorText_ = "RtApiJack::probeDeviceOpen: error initializing pthread condition variable.";
- goto error;
- }
- stream_.apiHandle = (void *) handle;
- handle->client = client;
- }
- handle->deviceName[mode] = deviceName;
-
- // Allocate necessary internal buffers.
- unsigned long bufferBytes;
- bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat );
- stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 );
- if ( stream_.userBuffer[mode] == NULL ) {
- errorText_ = "RtApiJack::probeDeviceOpen: error allocating user buffer memory.";
- goto error;
- }
-
- if ( stream_.doConvertBuffer[mode] ) {
-
- bool makeBuffer = true;
- if ( mode == OUTPUT )
- bufferBytes = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] );
- else { // mode == INPUT
- bufferBytes = stream_.nDeviceChannels[1] * formatBytes( stream_.deviceFormat[1] );
- if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) {
- unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes(stream_.deviceFormat[0]);
- if ( bufferBytes < bytesOut ) makeBuffer = false;
- }
- }
-
- if ( makeBuffer ) {
- bufferBytes *= *bufferSize;
- if ( stream_.deviceBuffer ) free( stream_.deviceBuffer );
- stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 );
- if ( stream_.deviceBuffer == NULL ) {
- errorText_ = "RtApiJack::probeDeviceOpen: error allocating device buffer memory.";
- goto error;
- }
- }
- }
-
- // Allocate memory for the Jack ports (channels) identifiers.
- handle->ports[mode] = (jack_port_t **) malloc ( sizeof (jack_port_t *) * channels );
- if ( handle->ports[mode] == NULL ) {
- errorText_ = "RtApiJack::probeDeviceOpen: error allocating port memory.";
- goto error;
- }
-
- stream_.device[mode] = device;
- stream_.channelOffset[mode] = firstChannel;
- stream_.state = STREAM_STOPPED;
- stream_.callbackInfo.object = (void *) this;
-
- if ( stream_.mode == OUTPUT && mode == INPUT )
- // We had already set up the stream for output.
- stream_.mode = DUPLEX;
- else {
- stream_.mode = mode;
- jack_set_process_callback( handle->client, jackCallbackHandler, (void *) &stream_.callbackInfo );
- jack_set_xrun_callback( handle->client, jackXrun, (void *) &handle );
- jack_on_shutdown( handle->client, jackShutdown, (void *) &stream_.callbackInfo );
- }
-
- // Register our ports.
- char label[64];
- if ( mode == OUTPUT ) {
- for ( unsigned int i=0; i<stream_.nUserChannels[0]; i++ ) {
- snprintf( label, 64, "outport %d", i );
- handle->ports[0][i] = jack_port_register( handle->client, (const char *)label,
- JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0 );
- }
- }
- else {
- for ( unsigned int i=0; i<stream_.nUserChannels[1]; i++ ) {
- snprintf( label, 64, "inport %d", i );
- handle->ports[1][i] = jack_port_register( handle->client, (const char *)label,
- JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0 );
- }
- }
-
- // Setup the buffer conversion information structure. We don't use
- // buffers to do channel offsets, so we override that parameter
- // here.
- if ( stream_.doConvertBuffer[mode] ) setConvertInfo( mode, 0 );
-
- return SUCCESS;
-
- error:
- if ( handle ) {
- pthread_cond_destroy( &handle->condition );
- jack_client_close( handle->client );
-
- if ( handle->ports[0] ) free( handle->ports[0] );
- if ( handle->ports[1] ) free( handle->ports[1] );
-
- delete handle;
- stream_.apiHandle = 0;
- }
-
- for ( int i=0; i<2; i++ ) {
- if ( stream_.userBuffer[i] ) {
- free( stream_.userBuffer[i] );
- stream_.userBuffer[i] = 0;
- }
- }
-
- if ( stream_.deviceBuffer ) {
- free( stream_.deviceBuffer );
- stream_.deviceBuffer = 0;
- }
-
- return FAILURE;
-}
-
-void RtApiJack :: closeStream( void )
-{
- if ( stream_.state == STREAM_CLOSED ) {
- errorText_ = "RtApiJack::closeStream(): no open stream to close!";
- error( RtAudioError::WARNING );
- return;
- }
-
- JackHandle *handle = (JackHandle *) stream_.apiHandle;
- if ( handle ) {
-
- if ( stream_.state == STREAM_RUNNING )
- jack_deactivate( handle->client );
-
- jack_client_close( handle->client );
- }
-
- if ( handle ) {
- if ( handle->ports[0] ) free( handle->ports[0] );
- if ( handle->ports[1] ) free( handle->ports[1] );
- pthread_cond_destroy( &handle->condition );
- delete handle;
- stream_.apiHandle = 0;
- }
-
- for ( int i=0; i<2; i++ ) {
- if ( stream_.userBuffer[i] ) {
- free( stream_.userBuffer[i] );
- stream_.userBuffer[i] = 0;
- }
- }
-
- if ( stream_.deviceBuffer ) {
- free( stream_.deviceBuffer );
- stream_.deviceBuffer = 0;
- }
-
- stream_.mode = UNINITIALIZED;
- stream_.state = STREAM_CLOSED;
-}
-
-void RtApiJack :: startStream( void )
-{
- verifyStream();
- if ( stream_.state == STREAM_RUNNING ) {
- errorText_ = "RtApiJack::startStream(): the stream is already running!";
- error( RtAudioError::WARNING );
- return;
- }
-
- JackHandle *handle = (JackHandle *) stream_.apiHandle;
- int result = jack_activate( handle->client );
- if ( result ) {
- errorText_ = "RtApiJack::startStream(): unable to activate JACK client!";
- goto unlock;
- }
-
- const char **ports;
-
- // Get the list of available ports.
- if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
- result = 1;
- ports = jack_get_ports( handle->client, handle->deviceName[0].c_str(), NULL, JackPortIsInput);
- if ( ports == NULL) {
- errorText_ = "RtApiJack::startStream(): error determining available JACK input ports!";
- goto unlock;
- }
-
- // Now make the port connections. Since RtAudio wasn't designed to
- // allow the user to select particular channels of a device, we'll
- // just open the first "nChannels" ports with offset.
- for ( unsigned int i=0; i<stream_.nUserChannels[0]; i++ ) {
- result = 1;
- if ( ports[ stream_.channelOffset[0] + i ] )
- result = jack_connect( handle->client, jack_port_name( handle->ports[0][i] ), ports[ stream_.channelOffset[0] + i ] );
- if ( result ) {
- free( ports );
- errorText_ = "RtApiJack::startStream(): error connecting output ports!";
- goto unlock;
- }
- }
- free(ports);
- }
-
- if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) {
- result = 1;
- ports = jack_get_ports( handle->client, handle->deviceName[1].c_str(), NULL, JackPortIsOutput );
- if ( ports == NULL) {
- errorText_ = "RtApiJack::startStream(): error determining available JACK output ports!";
- goto unlock;
- }
-
- // Now make the port connections. See note above.
- for ( unsigned int i=0; i<stream_.nUserChannels[1]; i++ ) {
- result = 1;
- if ( ports[ stream_.channelOffset[1] + i ] )
- result = jack_connect( handle->client, ports[ stream_.channelOffset[1] + i ], jack_port_name( handle->ports[1][i] ) );
- if ( result ) {
- free( ports );
- errorText_ = "RtApiJack::startStream(): error connecting input ports!";
- goto unlock;
- }
- }
- free(ports);
- }
-
- handle->drainCounter = 0;
- handle->internalDrain = false;
- stream_.state = STREAM_RUNNING;
-
- unlock:
- if ( result == 0 ) return;
- error( RtAudioError::SYSTEM_ERROR );
-}
-
-void RtApiJack :: stopStream( void )
-{
- verifyStream();
- if ( stream_.state == STREAM_STOPPED ) {
- errorText_ = "RtApiJack::stopStream(): the stream is already stopped!";
- error( RtAudioError::WARNING );
- return;
- }
-
- JackHandle *handle = (JackHandle *) stream_.apiHandle;
- if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
-
- if ( handle->drainCounter == 0 ) {
- handle->drainCounter = 2;
- pthread_cond_wait( &handle->condition, &stream_.mutex ); // block until signaled
- }
- }
-
- jack_deactivate( handle->client );
- stream_.state = STREAM_STOPPED;
-}
-
-void RtApiJack :: abortStream( void )
-{
- verifyStream();
- if ( stream_.state == STREAM_STOPPED ) {
- errorText_ = "RtApiJack::abortStream(): the stream is already stopped!";
- error( RtAudioError::WARNING );
- return;
- }
-
- JackHandle *handle = (JackHandle *) stream_.apiHandle;
- handle->drainCounter = 2;
-
- stopStream();
-}
-
-// This function will be called by a spawned thread when the user
-// callback function signals that the stream should be stopped or
-// aborted. It is necessary to handle it this way because the
-// callbackEvent() function must return before the jack_deactivate()
-// function will return.
-static void *jackStopStream( void *ptr )
-{
- CallbackInfo *info = (CallbackInfo *) ptr;
- RtApiJack *object = (RtApiJack *) info->object;
-
- object->stopStream();
- pthread_exit( NULL );
-}
-
-bool RtApiJack :: callbackEvent( unsigned long nframes )
-{
- if ( stream_.state == STREAM_STOPPED || stream_.state == STREAM_STOPPING ) return SUCCESS;
- if ( stream_.state == STREAM_CLOSED ) {
- errorText_ = "RtApiCore::callbackEvent(): the stream is closed ... this shouldn't happen!";
- error( RtAudioError::WARNING );
- return FAILURE;
- }
- if ( stream_.bufferSize != nframes ) {
- errorText_ = "RtApiCore::callbackEvent(): the JACK buffer size has changed ... cannot process!";
- error( RtAudioError::WARNING );
- return FAILURE;
- }
-
- CallbackInfo *info = (CallbackInfo *) &stream_.callbackInfo;
- JackHandle *handle = (JackHandle *) stream_.apiHandle;
-
- // Check if we were draining the stream and signal is finished.
- if ( handle->drainCounter > 3 ) {
- ThreadHandle threadId;
-
- stream_.state = STREAM_STOPPING;
- if ( handle->internalDrain == true )
- pthread_create( &threadId, NULL, jackStopStream, info );
- else
- pthread_cond_signal( &handle->condition );
- return SUCCESS;
- }
-
- // Invoke user callback first, to get fresh output data.
- if ( handle->drainCounter == 0 ) {
- RtAudioCallback callback = (RtAudioCallback) info->callback;
- double streamTime = getStreamTime();
- RtAudioStreamStatus status = 0;
- if ( stream_.mode != INPUT && handle->xrun[0] == true ) {
- status |= RTAUDIO_OUTPUT_UNDERFLOW;
- handle->xrun[0] = false;
- }
- if ( stream_.mode != OUTPUT && handle->xrun[1] == true ) {
- status |= RTAUDIO_INPUT_OVERFLOW;
- handle->xrun[1] = false;
- }
- int cbReturnValue = callback( stream_.userBuffer[0], stream_.userBuffer[1],
- stream_.bufferSize, streamTime, status, info->userData );
- if ( cbReturnValue == 2 ) {
- stream_.state = STREAM_STOPPING;
- handle->drainCounter = 2;
- ThreadHandle id;
- pthread_create( &id, NULL, jackStopStream, info );
- return SUCCESS;
- }
- else if ( cbReturnValue == 1 ) {
- handle->drainCounter = 1;
- handle->internalDrain = true;
- }
- }
-
- jack_default_audio_sample_t *jackbuffer;
- unsigned long bufferBytes = nframes * sizeof( jack_default_audio_sample_t );
- if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
-
- if ( handle->drainCounter > 1 ) { // write zeros to the output stream
-
- for ( unsigned int i=0; i<stream_.nDeviceChannels[0]; i++ ) {
- jackbuffer = (jack_default_audio_sample_t *) jack_port_get_buffer( handle->ports[0][i], (jack_nframes_t) nframes );
- memset( jackbuffer, 0, bufferBytes );
- }
-
- }
- else if ( stream_.doConvertBuffer[0] ) {
-
- convertBuffer( stream_.deviceBuffer, stream_.userBuffer[0], stream_.convertInfo[0] );
-
- for ( unsigned int i=0; i<stream_.nDeviceChannels[0]; i++ ) {
- jackbuffer = (jack_default_audio_sample_t *) jack_port_get_buffer( handle->ports[0][i], (jack_nframes_t) nframes );
- memcpy( jackbuffer, &stream_.deviceBuffer[i*bufferBytes], bufferBytes );
- }
- }
- else { // no buffer conversion
- for ( unsigned int i=0; i<stream_.nUserChannels[0]; i++ ) {
- jackbuffer = (jack_default_audio_sample_t *) jack_port_get_buffer( handle->ports[0][i], (jack_nframes_t) nframes );
- memcpy( jackbuffer, &stream_.userBuffer[0][i*bufferBytes], bufferBytes );
- }
- }
- }
-
- // Don't bother draining input
- if ( handle->drainCounter ) {
- handle->drainCounter++;
- goto unlock;
- }
-
- if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) {
-
- if ( stream_.doConvertBuffer[1] ) {
- for ( unsigned int i=0; i<stream_.nDeviceChannels[1]; i++ ) {
- jackbuffer = (jack_default_audio_sample_t *) jack_port_get_buffer( handle->ports[1][i], (jack_nframes_t) nframes );
- memcpy( &stream_.deviceBuffer[i*bufferBytes], jackbuffer, bufferBytes );
- }
- convertBuffer( stream_.userBuffer[1], stream_.deviceBuffer, stream_.convertInfo[1] );
- }
- else { // no buffer conversion
- for ( unsigned int i=0; i<stream_.nUserChannels[1]; i++ ) {
- jackbuffer = (jack_default_audio_sample_t *) jack_port_get_buffer( handle->ports[1][i], (jack_nframes_t) nframes );
- memcpy( &stream_.userBuffer[1][i*bufferBytes], jackbuffer, bufferBytes );
- }
- }
- }
-
- unlock:
- RtApi::tickStreamTime();
- return SUCCESS;
-}
- //******************** End of __UNIX_JACK__ *********************//
-#endif
-
-#if defined(__WINDOWS_ASIO__) // ASIO API on Windows
-
-// The ASIO API is designed around a callback scheme, so this
-// implementation is similar to that used for OS-X CoreAudio and Linux
-// Jack. The primary constraint with ASIO is that it only allows
-// access to a single driver at a time. Thus, it is not possible to
-// have more than one simultaneous RtAudio stream.
-//
-// This implementation also requires a number of external ASIO files
-// and a few global variables. The ASIO callback scheme does not
-// allow for the passing of user data, so we must create a global
-// pointer to our callbackInfo structure.
-//
-// On unix systems, we make use of a pthread condition variable.
-// Since there is no equivalent in Windows, I hacked something based
-// on information found in
-// http://www.cs.wustl.edu/~schmidt/win32-cv-1.html.
-
-#include "asiosys.h"
-#include "asio.h"
-#include "iasiothiscallresolver.h"
-#include "asiodrivers.h"
-#include <cmath>
-
-static AsioDrivers drivers;
-static ASIOCallbacks asioCallbacks;
-static ASIODriverInfo driverInfo;
-static CallbackInfo *asioCallbackInfo;
-static bool asioXRun;
-
-struct AsioHandle {
- int drainCounter; // Tracks callback counts when draining
- bool internalDrain; // Indicates if stop is initiated from callback or not.
- ASIOBufferInfo *bufferInfos;
- HANDLE condition;
-
- AsioHandle()
- :drainCounter(0), internalDrain(false), bufferInfos(0) {}
-};
-
-// Function declarations (definitions at end of section)
-static const char* getAsioErrorString( ASIOError result );
-static void sampleRateChanged( ASIOSampleRate sRate );
-static long asioMessages( long selector, long value, void* message, double* opt );
-
-RtApiAsio :: RtApiAsio()
-{
- // ASIO cannot run on a multi-threaded appartment. You can call
- // CoInitialize beforehand, but it must be for appartment threading
- // (in which case, CoInitilialize will return S_FALSE here).
- coInitialized_ = false;
- HRESULT hr = CoInitialize( NULL );
- if ( FAILED(hr) ) {
- errorText_ = "RtApiAsio::ASIO requires a single-threaded appartment. Call CoInitializeEx(0,COINIT_APARTMENTTHREADED)";
- error( RtAudioError::WARNING );
- }
- coInitialized_ = true;
-
- drivers.removeCurrentDriver();
- driverInfo.asioVersion = 2;
-
- // See note in DirectSound implementation about GetDesktopWindow().
- driverInfo.sysRef = GetForegroundWindow();
-}
-
-RtApiAsio :: ~RtApiAsio()
-{
- if ( stream_.state != STREAM_CLOSED ) closeStream();
- if ( coInitialized_ ) CoUninitialize();
-}
-
-unsigned int RtApiAsio :: getDeviceCount( void )
-{
- return (unsigned int) drivers.asioGetNumDev();
-}
-
-RtAudio::DeviceInfo RtApiAsio :: getDeviceInfo( unsigned int device )
-{
- RtAudio::DeviceInfo info;
- info.probed = false;
-
- // Get device ID
- unsigned int nDevices = getDeviceCount();
- if ( nDevices == 0 ) {
- errorText_ = "RtApiAsio::getDeviceInfo: no devices found!";
- error( RtAudioError::INVALID_USE );
- return info;
- }
-
- if ( device >= nDevices ) {
- errorText_ = "RtApiAsio::getDeviceInfo: device ID is invalid!";
- error( RtAudioError::INVALID_USE );
- return info;
- }
-
- // If a stream is already open, we cannot probe other devices. Thus, use the saved results.
- if ( stream_.state != STREAM_CLOSED ) {
- if ( device >= devices_.size() ) {
- errorText_ = "RtApiAsio::getDeviceInfo: device ID was not present before stream was opened.";
- error( RtAudioError::WARNING );
- return info;
- }
- return devices_[ device ];
- }
-
- char driverName[32];
- ASIOError result = drivers.asioGetDriverName( (int) device, driverName, 32 );
- if ( result != ASE_OK ) {
- errorStream_ << "RtApiAsio::getDeviceInfo: unable to get driver name (" << getAsioErrorString( result ) << ").";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- return info;
- }
-
- info.name = driverName;
-
- if ( !drivers.loadDriver( driverName ) ) {
- errorStream_ << "RtApiAsio::getDeviceInfo: unable to load driver (" << driverName << ").";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- return info;
- }
-
- result = ASIOInit( &driverInfo );
- if ( result != ASE_OK ) {
- errorStream_ << "RtApiAsio::getDeviceInfo: error (" << getAsioErrorString( result ) << ") initializing driver (" << driverName << ").";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- return info;
- }
-
- // Determine the device channel information.
- long inputChannels, outputChannels;
- result = ASIOGetChannels( &inputChannels, &outputChannels );
- if ( result != ASE_OK ) {
- drivers.removeCurrentDriver();
- errorStream_ << "RtApiAsio::getDeviceInfo: error (" << getAsioErrorString( result ) << ") getting channel count (" << driverName << ").";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- return info;
- }
-
- info.outputChannels = outputChannels;
- info.inputChannels = inputChannels;
- if ( info.outputChannels > 0 && info.inputChannels > 0 )
- info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels;
-
- // Determine the supported sample rates.
- info.sampleRates.clear();
- for ( unsigned int i=0; i<MAX_SAMPLE_RATES; i++ ) {
- result = ASIOCanSampleRate( (ASIOSampleRate) SAMPLE_RATES[i] );
- if ( result == ASE_OK ) {
- info.sampleRates.push_back( SAMPLE_RATES[i] );
-
- if ( !info.preferredSampleRate || ( SAMPLE_RATES[i] <= 48000 && SAMPLE_RATES[i] > info.preferredSampleRate ) )
- info.preferredSampleRate = SAMPLE_RATES[i];
- }
- }
-
- // Determine supported data types ... just check first channel and assume rest are the same.
- ASIOChannelInfo channelInfo;
- channelInfo.channel = 0;
- channelInfo.isInput = true;
- if ( info.inputChannels <= 0 ) channelInfo.isInput = false;
- result = ASIOGetChannelInfo( &channelInfo );
- if ( result != ASE_OK ) {
- drivers.removeCurrentDriver();
- errorStream_ << "RtApiAsio::getDeviceInfo: error (" << getAsioErrorString( result ) << ") getting driver channel info (" << driverName << ").";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- return info;
- }
-
- info.nativeFormats = 0;
- if ( channelInfo.type == ASIOSTInt16MSB || channelInfo.type == ASIOSTInt16LSB )
- info.nativeFormats |= RTAUDIO_SINT16;
- else if ( channelInfo.type == ASIOSTInt32MSB || channelInfo.type == ASIOSTInt32LSB )
- info.nativeFormats |= RTAUDIO_SINT32;
- else if ( channelInfo.type == ASIOSTFloat32MSB || channelInfo.type == ASIOSTFloat32LSB )
- info.nativeFormats |= RTAUDIO_FLOAT32;
- else if ( channelInfo.type == ASIOSTFloat64MSB || channelInfo.type == ASIOSTFloat64LSB )
- info.nativeFormats |= RTAUDIO_FLOAT64;
- else if ( channelInfo.type == ASIOSTInt24MSB || channelInfo.type == ASIOSTInt24LSB )
- info.nativeFormats |= RTAUDIO_SINT24;
-
- if ( info.outputChannels > 0 )
- if ( getDefaultOutputDevice() == device ) info.isDefaultOutput = true;
- if ( info.inputChannels > 0 )
- if ( getDefaultInputDevice() == device ) info.isDefaultInput = true;
-
- info.probed = true;
- drivers.removeCurrentDriver();
- return info;
-}
-
-static void bufferSwitch( long index, ASIOBool /*processNow*/ )
-{
- RtApiAsio *object = (RtApiAsio *) asioCallbackInfo->object;
- object->callbackEvent( index );
-}
-
-void RtApiAsio :: saveDeviceInfo( void )
-{
- devices_.clear();
-
- unsigned int nDevices = getDeviceCount();
- devices_.resize( nDevices );
- for ( unsigned int i=0; i<nDevices; i++ )
- devices_[i] = getDeviceInfo( i );
-}
-
-bool RtApiAsio :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,
- unsigned int firstChannel, unsigned int sampleRate,
- RtAudioFormat format, unsigned int *bufferSize,
- RtAudio::StreamOptions *options )
-{////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
- bool isDuplexInput = mode == INPUT && stream_.mode == OUTPUT;
-
- // For ASIO, a duplex stream MUST use the same driver.
- if ( isDuplexInput && stream_.device[0] != device ) {
- errorText_ = "RtApiAsio::probeDeviceOpen: an ASIO duplex stream must use the same device for input and output!";
- return FAILURE;
- }
-
- char driverName[32];
- ASIOError result = drivers.asioGetDriverName( (int) device, driverName, 32 );
- if ( result != ASE_OK ) {
- errorStream_ << "RtApiAsio::probeDeviceOpen: unable to get driver name (" << getAsioErrorString( result ) << ").";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- // Only load the driver once for duplex stream.
- if ( !isDuplexInput ) {
- // The getDeviceInfo() function will not work when a stream is open
- // because ASIO does not allow multiple devices to run at the same
- // time. Thus, we'll probe the system before opening a stream and
- // save the results for use by getDeviceInfo().
- this->saveDeviceInfo();
-
- if ( !drivers.loadDriver( driverName ) ) {
- errorStream_ << "RtApiAsio::probeDeviceOpen: unable to load driver (" << driverName << ").";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- result = ASIOInit( &driverInfo );
- if ( result != ASE_OK ) {
- errorStream_ << "RtApiAsio::probeDeviceOpen: error (" << getAsioErrorString( result ) << ") initializing driver (" << driverName << ").";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
- }
-
- // keep them before any "goto error", they are used for error cleanup + goto device boundary checks
- bool buffersAllocated = false;
- AsioHandle *handle = (AsioHandle *) stream_.apiHandle;
- unsigned int nChannels;
-
-
- // Check the device channel count.
- long inputChannels, outputChannels;
- result = ASIOGetChannels( &inputChannels, &outputChannels );
- if ( result != ASE_OK ) {
- errorStream_ << "RtApiAsio::probeDeviceOpen: error (" << getAsioErrorString( result ) << ") getting channel count (" << driverName << ").";
- errorText_ = errorStream_.str();
- goto error;
- }
-
- if ( ( mode == OUTPUT && (channels+firstChannel) > (unsigned int) outputChannels) ||
- ( mode == INPUT && (channels+firstChannel) > (unsigned int) inputChannels) ) {
- errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") does not support requested channel count (" << channels << ") + offset (" << firstChannel << ").";
- errorText_ = errorStream_.str();
- goto error;
- }
- stream_.nDeviceChannels[mode] = channels;
- stream_.nUserChannels[mode] = channels;
- stream_.channelOffset[mode] = firstChannel;
-
- // Verify the sample rate is supported.
- result = ASIOCanSampleRate( (ASIOSampleRate) sampleRate );
- if ( result != ASE_OK ) {
- errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") does not support requested sample rate (" << sampleRate << ").";
- errorText_ = errorStream_.str();
- goto error;
- }
-
- // Get the current sample rate
- ASIOSampleRate currentRate;
- result = ASIOGetSampleRate( &currentRate );
- if ( result != ASE_OK ) {
- errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error getting sample rate.";
- errorText_ = errorStream_.str();
- goto error;
- }
-
- // Set the sample rate only if necessary
- if ( currentRate != sampleRate ) {
- result = ASIOSetSampleRate( (ASIOSampleRate) sampleRate );
- if ( result != ASE_OK ) {
- errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error setting sample rate (" << sampleRate << ").";
- errorText_ = errorStream_.str();
- goto error;
- }
- }
-
- // Determine the driver data type.
- ASIOChannelInfo channelInfo;
- channelInfo.channel = 0;
- if ( mode == OUTPUT ) channelInfo.isInput = false;
- else channelInfo.isInput = true;
- result = ASIOGetChannelInfo( &channelInfo );
- if ( result != ASE_OK ) {
- errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error (" << getAsioErrorString( result ) << ") getting data format.";
- errorText_ = errorStream_.str();
- goto error;
- }
-
- // Assuming WINDOWS host is always little-endian.
- stream_.doByteSwap[mode] = false;
- stream_.userFormat = format;
- stream_.deviceFormat[mode] = 0;
- if ( channelInfo.type == ASIOSTInt16MSB || channelInfo.type == ASIOSTInt16LSB ) {
- stream_.deviceFormat[mode] = RTAUDIO_SINT16;
- if ( channelInfo.type == ASIOSTInt16MSB ) stream_.doByteSwap[mode] = true;
- }
- else if ( channelInfo.type == ASIOSTInt32MSB || channelInfo.type == ASIOSTInt32LSB ) {
- stream_.deviceFormat[mode] = RTAUDIO_SINT32;
- if ( channelInfo.type == ASIOSTInt32MSB ) stream_.doByteSwap[mode] = true;
- }
- else if ( channelInfo.type == ASIOSTFloat32MSB || channelInfo.type == ASIOSTFloat32LSB ) {
- stream_.deviceFormat[mode] = RTAUDIO_FLOAT32;
- if ( channelInfo.type == ASIOSTFloat32MSB ) stream_.doByteSwap[mode] = true;
- }
- else if ( channelInfo.type == ASIOSTFloat64MSB || channelInfo.type == ASIOSTFloat64LSB ) {
- stream_.deviceFormat[mode] = RTAUDIO_FLOAT64;
- if ( channelInfo.type == ASIOSTFloat64MSB ) stream_.doByteSwap[mode] = true;
- }
- else if ( channelInfo.type == ASIOSTInt24MSB || channelInfo.type == ASIOSTInt24LSB ) {
- stream_.deviceFormat[mode] = RTAUDIO_SINT24;
- if ( channelInfo.type == ASIOSTInt24MSB ) stream_.doByteSwap[mode] = true;
- }
-
- if ( stream_.deviceFormat[mode] == 0 ) {
- errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") data format not supported by RtAudio.";
- errorText_ = errorStream_.str();
- goto error;
- }
-
- // Set the buffer size. For a duplex stream, this will end up
- // setting the buffer size based on the input constraints, which
- // should be ok.
- long minSize, maxSize, preferSize, granularity;
- result = ASIOGetBufferSize( &minSize, &maxSize, &preferSize, &granularity );
- if ( result != ASE_OK ) {
- errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error (" << getAsioErrorString( result ) << ") getting buffer size.";
- errorText_ = errorStream_.str();
- goto error;
- }
-
- if ( isDuplexInput ) {
- // When this is the duplex input (output was opened before), then we have to use the same
- // buffersize as the output, because it might use the preferred buffer size, which most
- // likely wasn't passed as input to this. The buffer sizes have to be identically anyway,
- // So instead of throwing an error, make them equal. The caller uses the reference
- // to the "bufferSize" param as usual to set up processing buffers.
-
- *bufferSize = stream_.bufferSize;
-
- } else {
- if ( *bufferSize == 0 ) *bufferSize = preferSize;
- else if ( *bufferSize < (unsigned int) minSize ) *bufferSize = (unsigned int) minSize;
- else if ( *bufferSize > (unsigned int) maxSize ) *bufferSize = (unsigned int) maxSize;
- else if ( granularity == -1 ) {
- // Make sure bufferSize is a power of two.
- int log2_of_min_size = 0;
- int log2_of_max_size = 0;
-
- for ( unsigned int i = 0; i < sizeof(long) * 8; i++ ) {
- if ( minSize & ((long)1 << i) ) log2_of_min_size = i;
- if ( maxSize & ((long)1 << i) ) log2_of_max_size = i;
- }
-
- long min_delta = std::abs( (long)*bufferSize - ((long)1 << log2_of_min_size) );
- int min_delta_num = log2_of_min_size;
-
- for (int i = log2_of_min_size + 1; i <= log2_of_max_size; i++) {
- long current_delta = std::abs( (long)*bufferSize - ((long)1 << i) );
- if (current_delta < min_delta) {
- min_delta = current_delta;
- min_delta_num = i;
- }
- }
-
- *bufferSize = ( (unsigned int)1 << min_delta_num );
- if ( *bufferSize < (unsigned int) minSize ) *bufferSize = (unsigned int) minSize;
- else if ( *bufferSize > (unsigned int) maxSize ) *bufferSize = (unsigned int) maxSize;
- }
- else if ( granularity != 0 ) {
- // Set to an even multiple of granularity, rounding up.
- *bufferSize = (*bufferSize + granularity-1) / granularity * granularity;
- }
- }
-
- /*
- // we don't use it anymore, see above!
- // Just left it here for the case...
- if ( isDuplexInput && stream_.bufferSize != *bufferSize ) {
- errorText_ = "RtApiAsio::probeDeviceOpen: input/output buffersize discrepancy!";
- goto error;
- }
- */
-
- stream_.bufferSize = *bufferSize;
- stream_.nBuffers = 2;
-
- if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) stream_.userInterleaved = false;
- else stream_.userInterleaved = true;
-
- // ASIO always uses non-interleaved buffers.
- stream_.deviceInterleaved[mode] = false;
-
- // Allocate, if necessary, our AsioHandle structure for the stream.
- if ( handle == 0 ) {
- try {
- handle = new AsioHandle;
- }
- catch ( std::bad_alloc& ) {
- errorText_ = "RtApiAsio::probeDeviceOpen: error allocating AsioHandle memory.";
- goto error;
- }
- handle->bufferInfos = 0;
-
- // Create a manual-reset event.
- handle->condition = CreateEvent( NULL, // no security
- TRUE, // manual-reset
- FALSE, // non-signaled initially
- NULL ); // unnamed
- stream_.apiHandle = (void *) handle;
- }
-
- // Create the ASIO internal buffers. Since RtAudio sets up input
- // and output separately, we'll have to dispose of previously
- // created output buffers for a duplex stream.
- if ( mode == INPUT && stream_.mode == OUTPUT ) {
- ASIODisposeBuffers();
- if ( handle->bufferInfos ) free( handle->bufferInfos );
- }
-
- // Allocate, initialize, and save the bufferInfos in our stream callbackInfo structure.
- unsigned int i;
- nChannels = stream_.nDeviceChannels[0] + stream_.nDeviceChannels[1];
- handle->bufferInfos = (ASIOBufferInfo *) malloc( nChannels * sizeof(ASIOBufferInfo) );
- if ( handle->bufferInfos == NULL ) {
- errorStream_ << "RtApiAsio::probeDeviceOpen: error allocating bufferInfo memory for driver (" << driverName << ").";
- errorText_ = errorStream_.str();
- goto error;
- }
-
- ASIOBufferInfo *infos;
- infos = handle->bufferInfos;
- for ( i=0; i<stream_.nDeviceChannels[0]; i++, infos++ ) {
- infos->isInput = ASIOFalse;
- infos->channelNum = i + stream_.channelOffset[0];
- infos->buffers[0] = infos->buffers[1] = 0;
- }
- for ( i=0; i<stream_.nDeviceChannels[1]; i++, infos++ ) {
- infos->isInput = ASIOTrue;
- infos->channelNum = i + stream_.channelOffset[1];
- infos->buffers[0] = infos->buffers[1] = 0;
- }
-
- // prepare for callbacks
- stream_.sampleRate = sampleRate;
- stream_.device[mode] = device;
- stream_.mode = isDuplexInput ? DUPLEX : mode;
-
- // store this class instance before registering callbacks, that are going to use it
- asioCallbackInfo = &stream_.callbackInfo;
- stream_.callbackInfo.object = (void *) this;
-
- // Set up the ASIO callback structure and create the ASIO data buffers.
- asioCallbacks.bufferSwitch = &bufferSwitch;
- asioCallbacks.sampleRateDidChange = &sampleRateChanged;
- asioCallbacks.asioMessage = &asioMessages;
- asioCallbacks.bufferSwitchTimeInfo = NULL;
- result = ASIOCreateBuffers( handle->bufferInfos, nChannels, stream_.bufferSize, &asioCallbacks );
- if ( result != ASE_OK ) {
- // Standard method failed. This can happen with strict/misbehaving drivers that return valid buffer size ranges
- // but only accept the preferred buffer size as parameter for ASIOCreateBuffers. eg. Creatives ASIO driver
- // in that case, let's be naïve and try that instead
- *bufferSize = preferSize;
- stream_.bufferSize = *bufferSize;
- result = ASIOCreateBuffers( handle->bufferInfos, nChannels, stream_.bufferSize, &asioCallbacks );
- }
-
- if ( result != ASE_OK ) {
- errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error (" << getAsioErrorString( result ) << ") creating buffers.";
- errorText_ = errorStream_.str();
- goto error;
- }
- buffersAllocated = true;
- stream_.state = STREAM_STOPPED;
-
- // Set flags for buffer conversion.
- stream_.doConvertBuffer[mode] = false;
- if ( stream_.userFormat != stream_.deviceFormat[mode] )
- stream_.doConvertBuffer[mode] = true;
- if ( stream_.userInterleaved != stream_.deviceInterleaved[mode] &&
- stream_.nUserChannels[mode] > 1 )
- stream_.doConvertBuffer[mode] = true;
-
- // Allocate necessary internal buffers
- unsigned long bufferBytes;
- bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat );
- stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 );
- if ( stream_.userBuffer[mode] == NULL ) {
- errorText_ = "RtApiAsio::probeDeviceOpen: error allocating user buffer memory.";
- goto error;
- }
-
- if ( stream_.doConvertBuffer[mode] ) {
-
- bool makeBuffer = true;
- bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] );
- if ( isDuplexInput && stream_.deviceBuffer ) {
- unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] );
- if ( bufferBytes <= bytesOut ) makeBuffer = false;
- }
-
- if ( makeBuffer ) {
- bufferBytes *= *bufferSize;
- if ( stream_.deviceBuffer ) free( stream_.deviceBuffer );
- stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 );
- if ( stream_.deviceBuffer == NULL ) {
- errorText_ = "RtApiAsio::probeDeviceOpen: error allocating device buffer memory.";
- goto error;
- }
- }
- }
-
- // Determine device latencies
- long inputLatency, outputLatency;
- result = ASIOGetLatencies( &inputLatency, &outputLatency );
- if ( result != ASE_OK ) {
- errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error (" << getAsioErrorString( result ) << ") getting latency.";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING); // warn but don't fail
- }
- else {
- stream_.latency[0] = outputLatency;
- stream_.latency[1] = inputLatency;
- }
-
- // Setup the buffer conversion information structure. We don't use
- // buffers to do channel offsets, so we override that parameter
- // here.
- if ( stream_.doConvertBuffer[mode] ) setConvertInfo( mode, 0 );
-
- return SUCCESS;
-
- error:
- if ( !isDuplexInput ) {
- // the cleanup for error in the duplex input, is done by RtApi::openStream
- // So we clean up for single channel only
-
- if ( buffersAllocated )
- ASIODisposeBuffers();
-
- drivers.removeCurrentDriver();
-
- if ( handle ) {
- CloseHandle( handle->condition );
- if ( handle->bufferInfos )
- free( handle->bufferInfos );
-
- delete handle;
- stream_.apiHandle = 0;
- }
-
-
- if ( stream_.userBuffer[mode] ) {
- free( stream_.userBuffer[mode] );
- stream_.userBuffer[mode] = 0;
- }
-
- if ( stream_.deviceBuffer ) {
- free( stream_.deviceBuffer );
- stream_.deviceBuffer = 0;
- }
- }
-
- return FAILURE;
-}////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-void RtApiAsio :: closeStream()
-{
- if ( stream_.state == STREAM_CLOSED ) {
- errorText_ = "RtApiAsio::closeStream(): no open stream to close!";
- error( RtAudioError::WARNING );
- return;
- }
-
- if ( stream_.state == STREAM_RUNNING ) {
- stream_.state = STREAM_STOPPED;
- ASIOStop();
- }
- ASIODisposeBuffers();
- drivers.removeCurrentDriver();
-
- AsioHandle *handle = (AsioHandle *) stream_.apiHandle;
- if ( handle ) {
- CloseHandle( handle->condition );
- if ( handle->bufferInfos )
- free( handle->bufferInfos );
- delete handle;
- stream_.apiHandle = 0;
- }
-
- for ( int i=0; i<2; i++ ) {
- if ( stream_.userBuffer[i] ) {
- free( stream_.userBuffer[i] );
- stream_.userBuffer[i] = 0;
- }
- }
-
- if ( stream_.deviceBuffer ) {
- free( stream_.deviceBuffer );
- stream_.deviceBuffer = 0;
- }
-
- stream_.mode = UNINITIALIZED;
- stream_.state = STREAM_CLOSED;
-}
-
-bool stopThreadCalled = false;
-
-void RtApiAsio :: startStream()
-{
- verifyStream();
- if ( stream_.state == STREAM_RUNNING ) {
- errorText_ = "RtApiAsio::startStream(): the stream is already running!";
- error( RtAudioError::WARNING );
- return;
- }
-
- AsioHandle *handle = (AsioHandle *) stream_.apiHandle;
- ASIOError result = ASIOStart();
- if ( result != ASE_OK ) {
- errorStream_ << "RtApiAsio::startStream: error (" << getAsioErrorString( result ) << ") starting device.";
- errorText_ = errorStream_.str();
- goto unlock;
- }
-
- handle->drainCounter = 0;
- handle->internalDrain = false;
- ResetEvent( handle->condition );
- stream_.state = STREAM_RUNNING;
- asioXRun = false;
-
- unlock:
- stopThreadCalled = false;
-
- if ( result == ASE_OK ) return;
- error( RtAudioError::SYSTEM_ERROR );
-}
-
-void RtApiAsio :: stopStream()
-{
- verifyStream();
- if ( stream_.state == STREAM_STOPPED ) {
- errorText_ = "RtApiAsio::stopStream(): the stream is already stopped!";
- error( RtAudioError::WARNING );
- return;
- }
-
- AsioHandle *handle = (AsioHandle *) stream_.apiHandle;
- if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
- if ( handle->drainCounter == 0 ) {
- handle->drainCounter = 2;
- WaitForSingleObject( handle->condition, INFINITE ); // block until signaled
- }
- }
-
- stream_.state = STREAM_STOPPED;
-
- ASIOError result = ASIOStop();
- if ( result != ASE_OK ) {
- errorStream_ << "RtApiAsio::stopStream: error (" << getAsioErrorString( result ) << ") stopping device.";
- errorText_ = errorStream_.str();
- }
-
- if ( result == ASE_OK ) return;
- error( RtAudioError::SYSTEM_ERROR );
-}
-
-void RtApiAsio :: abortStream()
-{
- verifyStream();
- if ( stream_.state == STREAM_STOPPED ) {
- errorText_ = "RtApiAsio::abortStream(): the stream is already stopped!";
- error( RtAudioError::WARNING );
- return;
- }
-
- // The following lines were commented-out because some behavior was
- // noted where the device buffers need to be zeroed to avoid
- // continuing sound, even when the device buffers are completely
- // disposed. So now, calling abort is the same as calling stop.
- // AsioHandle *handle = (AsioHandle *) stream_.apiHandle;
- // handle->drainCounter = 2;
- stopStream();
-}
-
-// This function will be called by a spawned thread when the user
-// callback function signals that the stream should be stopped or
-// aborted. It is necessary to handle it this way because the
-// callbackEvent() function must return before the ASIOStop()
-// function will return.
-static unsigned __stdcall asioStopStream( void *ptr )
-{
- CallbackInfo *info = (CallbackInfo *) ptr;
- RtApiAsio *object = (RtApiAsio *) info->object;
-
- object->stopStream();
- _endthreadex( 0 );
- return 0;
-}
-
-bool RtApiAsio :: callbackEvent( long bufferIndex )
-{
- if ( stream_.state == STREAM_STOPPED || stream_.state == STREAM_STOPPING ) return SUCCESS;
- if ( stream_.state == STREAM_CLOSED ) {
- errorText_ = "RtApiAsio::callbackEvent(): the stream is closed ... this shouldn't happen!";
- error( RtAudioError::WARNING );
- return FAILURE;
- }
-
- CallbackInfo *info = (CallbackInfo *) &stream_.callbackInfo;
- AsioHandle *handle = (AsioHandle *) stream_.apiHandle;
-
- // Check if we were draining the stream and signal if finished.
- if ( handle->drainCounter > 3 ) {
-
- stream_.state = STREAM_STOPPING;
- if ( handle->internalDrain == false )
- SetEvent( handle->condition );
- else { // spawn a thread to stop the stream
- unsigned threadId;
- stream_.callbackInfo.thread = _beginthreadex( NULL, 0, &asioStopStream,
- &stream_.callbackInfo, 0, &threadId );
- }
- return SUCCESS;
- }
-
- // Invoke user callback to get fresh output data UNLESS we are
- // draining stream.
- if ( handle->drainCounter == 0 ) {
- RtAudioCallback callback = (RtAudioCallback) info->callback;
- double streamTime = getStreamTime();
- RtAudioStreamStatus status = 0;
- if ( stream_.mode != INPUT && asioXRun == true ) {
- status |= RTAUDIO_OUTPUT_UNDERFLOW;
- asioXRun = false;
- }
- if ( stream_.mode != OUTPUT && asioXRun == true ) {
- status |= RTAUDIO_INPUT_OVERFLOW;
- asioXRun = false;
- }
- int cbReturnValue = callback( stream_.userBuffer[0], stream_.userBuffer[1],
- stream_.bufferSize, streamTime, status, info->userData );
- if ( cbReturnValue == 2 ) {
- stream_.state = STREAM_STOPPING;
- handle->drainCounter = 2;
- unsigned threadId;
- stream_.callbackInfo.thread = _beginthreadex( NULL, 0, &asioStopStream,
- &stream_.callbackInfo, 0, &threadId );
- return SUCCESS;
- }
- else if ( cbReturnValue == 1 ) {
- handle->drainCounter = 1;
- handle->internalDrain = true;
- }
- }
-
- unsigned int nChannels, bufferBytes, i, j;
- nChannels = stream_.nDeviceChannels[0] + stream_.nDeviceChannels[1];
- if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
-
- bufferBytes = stream_.bufferSize * formatBytes( stream_.deviceFormat[0] );
-
- if ( handle->drainCounter > 1 ) { // write zeros to the output stream
-
- for ( i=0, j=0; i<nChannels; i++ ) {
- if ( handle->bufferInfos[i].isInput != ASIOTrue )
- memset( handle->bufferInfos[i].buffers[bufferIndex], 0, bufferBytes );
- }
-
- }
- else if ( stream_.doConvertBuffer[0] ) {
-
- convertBuffer( stream_.deviceBuffer, stream_.userBuffer[0], stream_.convertInfo[0] );
- if ( stream_.doByteSwap[0] )
- byteSwapBuffer( stream_.deviceBuffer,
- stream_.bufferSize * stream_.nDeviceChannels[0],
- stream_.deviceFormat[0] );
-
- for ( i=0, j=0; i<nChannels; i++ ) {
- if ( handle->bufferInfos[i].isInput != ASIOTrue )
- memcpy( handle->bufferInfos[i].buffers[bufferIndex],
- &stream_.deviceBuffer[j++*bufferBytes], bufferBytes );
- }
-
- }
- else {
-
- if ( stream_.doByteSwap[0] )
- byteSwapBuffer( stream_.userBuffer[0],
- stream_.bufferSize * stream_.nUserChannels[0],
- stream_.userFormat );
-
- for ( i=0, j=0; i<nChannels; i++ ) {
- if ( handle->bufferInfos[i].isInput != ASIOTrue )
- memcpy( handle->bufferInfos[i].buffers[bufferIndex],
- &stream_.userBuffer[0][bufferBytes*j++], bufferBytes );
- }
-
- }
- }
-
- // Don't bother draining input
- if ( handle->drainCounter ) {
- handle->drainCounter++;
- goto unlock;
- }
-
- if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) {
-
- bufferBytes = stream_.bufferSize * formatBytes(stream_.deviceFormat[1]);
-
- if (stream_.doConvertBuffer[1]) {
-
- // Always interleave ASIO input data.
- for ( i=0, j=0; i<nChannels; i++ ) {
- if ( handle->bufferInfos[i].isInput == ASIOTrue )
- memcpy( &stream_.deviceBuffer[j++*bufferBytes],
- handle->bufferInfos[i].buffers[bufferIndex],
- bufferBytes );
- }
-
- if ( stream_.doByteSwap[1] )
- byteSwapBuffer( stream_.deviceBuffer,
- stream_.bufferSize * stream_.nDeviceChannels[1],
- stream_.deviceFormat[1] );
- convertBuffer( stream_.userBuffer[1], stream_.deviceBuffer, stream_.convertInfo[1] );
-
- }
- else {
- for ( i=0, j=0; i<nChannels; i++ ) {
- if ( handle->bufferInfos[i].isInput == ASIOTrue ) {
- memcpy( &stream_.userBuffer[1][bufferBytes*j++],
- handle->bufferInfos[i].buffers[bufferIndex],
- bufferBytes );
- }
- }
-
- if ( stream_.doByteSwap[1] )
- byteSwapBuffer( stream_.userBuffer[1],
- stream_.bufferSize * stream_.nUserChannels[1],
- stream_.userFormat );
- }
- }
-
- unlock:
- // The following call was suggested by Malte Clasen. While the API
- // documentation indicates it should not be required, some device
- // drivers apparently do not function correctly without it.
- ASIOOutputReady();
-
- RtApi::tickStreamTime();
- return SUCCESS;
-}
-
-static void sampleRateChanged( ASIOSampleRate sRate )
-{
- // The ASIO documentation says that this usually only happens during
- // external sync. Audio processing is not stopped by the driver,
- // actual sample rate might not have even changed, maybe only the
- // sample rate status of an AES/EBU or S/PDIF digital input at the
- // audio device.
-
- RtApi *object = (RtApi *) asioCallbackInfo->object;
- try {
- object->stopStream();
- }
- catch ( RtAudioError &exception ) {
- std::cerr << "\nRtApiAsio: sampleRateChanged() error (" << exception.getMessage() << ")!\n" << std::endl;
- return;
- }
-
- std::cerr << "\nRtApiAsio: driver reports sample rate changed to " << sRate << " ... stream stopped!!!\n" << std::endl;
-}
-
-static long asioMessages( long selector, long value, void* /*message*/, double* /*opt*/ )
-{
- long ret = 0;
-
- switch( selector ) {
- case kAsioSelectorSupported:
- if ( value == kAsioResetRequest
- || value == kAsioEngineVersion
- || value == kAsioResyncRequest
- || value == kAsioLatenciesChanged
- // The following three were added for ASIO 2.0, you don't
- // necessarily have to support them.
- || value == kAsioSupportsTimeInfo
- || value == kAsioSupportsTimeCode
- || value == kAsioSupportsInputMonitor)
- ret = 1L;
- break;
- case kAsioResetRequest:
- // Defer the task and perform the reset of the driver during the
- // next "safe" situation. You cannot reset the driver right now,
- // as this code is called from the driver. Reset the driver is
- // done by completely destruct is. I.e. ASIOStop(),
- // ASIODisposeBuffers(), Destruction Afterwards you initialize the
- // driver again.
- std::cerr << "\nRtApiAsio: driver reset requested!!!" << std::endl;
- ret = 1L;
- break;
- case kAsioResyncRequest:
- // This informs the application that the driver encountered some
- // non-fatal data loss. It is used for synchronization purposes
- // of different media. Added mainly to work around the Win16Mutex
- // problems in Windows 95/98 with the Windows Multimedia system,
- // which could lose data because the Mutex was held too long by
- // another thread. However a driver can issue it in other
- // situations, too.
- // std::cerr << "\nRtApiAsio: driver resync requested!!!" << std::endl;
- asioXRun = true;
- ret = 1L;
- break;
- case kAsioLatenciesChanged:
- // This will inform the host application that the drivers were
- // latencies changed. Beware, it this does not mean that the
- // buffer sizes have changed! You might need to update internal
- // delay data.
- std::cerr << "\nRtApiAsio: driver latency may have changed!!!" << std::endl;
- ret = 1L;
- break;
- case kAsioEngineVersion:
- // Return the supported ASIO version of the host application. If
- // a host application does not implement this selector, ASIO 1.0
- // is assumed by the driver.
- ret = 2L;
- break;
- case kAsioSupportsTimeInfo:
- // Informs the driver whether the
- // asioCallbacks.bufferSwitchTimeInfo() callback is supported.
- // For compatibility with ASIO 1.0 drivers the host application
- // should always support the "old" bufferSwitch method, too.
- ret = 0;
- break;
- case kAsioSupportsTimeCode:
- // Informs the driver whether application is interested in time
- // code info. If an application does not need to know about time
- // code, the driver has less work to do.
- ret = 0;
- break;
- }
- return ret;
-}
-
-static const char* getAsioErrorString( ASIOError result )
-{
- struct Messages
- {
- ASIOError value;
- const char*message;
- };
-
- static const Messages m[] =
- {
- { ASE_NotPresent, "Hardware input or output is not present or available." },
- { ASE_HWMalfunction, "Hardware is malfunctioning." },
- { ASE_InvalidParameter, "Invalid input parameter." },
- { ASE_InvalidMode, "Invalid mode." },
- { ASE_SPNotAdvancing, "Sample position not advancing." },
- { ASE_NoClock, "Sample clock or rate cannot be determined or is not present." },
- { ASE_NoMemory, "Not enough memory to complete the request." }
- };
-
- for ( unsigned int i = 0; i < sizeof(m)/sizeof(m[0]); ++i )
- if ( m[i].value == result ) return m[i].message;
-
- return "Unknown error.";
-}
-
-//******************** End of __WINDOWS_ASIO__ *********************//
-#endif
-
-
-#if defined(__WINDOWS_WASAPI__) // Windows WASAPI API
-
-// Authored by Marcus Tomlinson <themarcustomlinson@gmail.com>, April 2014
-// - Introduces support for the Windows WASAPI API
-// - Aims to deliver bit streams to and from hardware at the lowest possible latency, via the absolute minimum buffer sizes required
-// - Provides flexible stream configuration to an otherwise strict and inflexible WASAPI interface
-// - Includes automatic internal conversion of sample rate and buffer size between hardware and the user
-
-#ifndef INITGUID
- #define INITGUID
-#endif
-#include <audioclient.h>
-#include <avrt.h>
-#include <mmdeviceapi.h>
-#include <functiondiscoverykeys_devpkey.h>
-
-//=============================================================================
-
-#define SAFE_RELEASE( objectPtr )\
-if ( objectPtr )\
-{\
- objectPtr->Release();\
- objectPtr = NULL;\
-}
-
-typedef HANDLE ( __stdcall *TAvSetMmThreadCharacteristicsPtr )( LPCWSTR TaskName, LPDWORD TaskIndex );
-
-//-----------------------------------------------------------------------------
-
-// WASAPI dictates stream sample rate, format, channel count, and in some cases, buffer size.
-// Therefore we must perform all necessary conversions to user buffers in order to satisfy these
-// requirements. WasapiBuffer ring buffers are used between HwIn->UserIn and UserOut->HwOut to
-// provide intermediate storage for read / write synchronization.
-class WasapiBuffer
-{
-public:
- WasapiBuffer()
- : buffer_( NULL ),
- bufferSize_( 0 ),
- inIndex_( 0 ),
- outIndex_( 0 ) {}
-
- ~WasapiBuffer() {
- free( buffer_ );
- }
-
- // sets the length of the internal ring buffer
- void setBufferSize( unsigned int bufferSize, unsigned int formatBytes ) {
- free( buffer_ );
-
- buffer_ = ( char* ) calloc( bufferSize, formatBytes );
-
- bufferSize_ = bufferSize;
- inIndex_ = 0;
- outIndex_ = 0;
- }
-
- // attempt to push a buffer into the ring buffer at the current "in" index
- bool pushBuffer( char* buffer, unsigned int bufferSize, RtAudioFormat format )
- {
- if ( !buffer || // incoming buffer is NULL
- bufferSize == 0 || // incoming buffer has no data
- bufferSize > bufferSize_ ) // incoming buffer too large
- {
- return false;
- }
-
- unsigned int relOutIndex = outIndex_;
- unsigned int inIndexEnd = inIndex_ + bufferSize;
- if ( relOutIndex < inIndex_ && inIndexEnd >= bufferSize_ ) {
- relOutIndex += bufferSize_;
- }
-
- // "in" index can end on the "out" index but cannot begin at it
- if ( inIndex_ <= relOutIndex && inIndexEnd > relOutIndex ) {
- return false; // not enough space between "in" index and "out" index
- }
-
- // copy buffer from external to internal
- int fromZeroSize = inIndex_ + bufferSize - bufferSize_;
- fromZeroSize = fromZeroSize < 0 ? 0 : fromZeroSize;
- int fromInSize = bufferSize - fromZeroSize;
-
- switch( format )
- {
- case RTAUDIO_SINT8:
- memcpy( &( ( char* ) buffer_ )[inIndex_], buffer, fromInSize * sizeof( char ) );
- memcpy( buffer_, &( ( char* ) buffer )[fromInSize], fromZeroSize * sizeof( char ) );
- break;
- case RTAUDIO_SINT16:
- memcpy( &( ( short* ) buffer_ )[inIndex_], buffer, fromInSize * sizeof( short ) );
- memcpy( buffer_, &( ( short* ) buffer )[fromInSize], fromZeroSize * sizeof( short ) );
- break;
- case RTAUDIO_SINT24:
- memcpy( &( ( S24* ) buffer_ )[inIndex_], buffer, fromInSize * sizeof( S24 ) );
- memcpy( buffer_, &( ( S24* ) buffer )[fromInSize], fromZeroSize * sizeof( S24 ) );
- break;
- case RTAUDIO_SINT32:
- memcpy( &( ( int* ) buffer_ )[inIndex_], buffer, fromInSize * sizeof( int ) );
- memcpy( buffer_, &( ( int* ) buffer )[fromInSize], fromZeroSize * sizeof( int ) );
- break;
- case RTAUDIO_FLOAT32:
- memcpy( &( ( float* ) buffer_ )[inIndex_], buffer, fromInSize * sizeof( float ) );
- memcpy( buffer_, &( ( float* ) buffer )[fromInSize], fromZeroSize * sizeof( float ) );
- break;
- case RTAUDIO_FLOAT64:
- memcpy( &( ( double* ) buffer_ )[inIndex_], buffer, fromInSize * sizeof( double ) );
- memcpy( buffer_, &( ( double* ) buffer )[fromInSize], fromZeroSize * sizeof( double ) );
- break;
- }
-
- // update "in" index
- inIndex_ += bufferSize;
- inIndex_ %= bufferSize_;
-
- return true;
- }
-
- // attempt to pull a buffer from the ring buffer from the current "out" index
- bool pullBuffer( char* buffer, unsigned int bufferSize, RtAudioFormat format )
- {
- if ( !buffer || // incoming buffer is NULL
- bufferSize == 0 || // incoming buffer has no data
- bufferSize > bufferSize_ ) // incoming buffer too large
- {
- return false;
- }
-
- unsigned int relInIndex = inIndex_;
- unsigned int outIndexEnd = outIndex_ + bufferSize;
- if ( relInIndex < outIndex_ && outIndexEnd >= bufferSize_ ) {
- relInIndex += bufferSize_;
- }
-
- // "out" index can begin at and end on the "in" index
- if ( outIndex_ < relInIndex && outIndexEnd > relInIndex ) {
- return false; // not enough space between "out" index and "in" index
- }
-
- // copy buffer from internal to external
- int fromZeroSize = outIndex_ + bufferSize - bufferSize_;
- fromZeroSize = fromZeroSize < 0 ? 0 : fromZeroSize;
- int fromOutSize = bufferSize - fromZeroSize;
-
- switch( format )
- {
- case RTAUDIO_SINT8:
- memcpy( buffer, &( ( char* ) buffer_ )[outIndex_], fromOutSize * sizeof( char ) );
- memcpy( &( ( char* ) buffer )[fromOutSize], buffer_, fromZeroSize * sizeof( char ) );
- break;
- case RTAUDIO_SINT16:
- memcpy( buffer, &( ( short* ) buffer_ )[outIndex_], fromOutSize * sizeof( short ) );
- memcpy( &( ( short* ) buffer )[fromOutSize], buffer_, fromZeroSize * sizeof( short ) );
- break;
- case RTAUDIO_SINT24:
- memcpy( buffer, &( ( S24* ) buffer_ )[outIndex_], fromOutSize * sizeof( S24 ) );
- memcpy( &( ( S24* ) buffer )[fromOutSize], buffer_, fromZeroSize * sizeof( S24 ) );
- break;
- case RTAUDIO_SINT32:
- memcpy( buffer, &( ( int* ) buffer_ )[outIndex_], fromOutSize * sizeof( int ) );
- memcpy( &( ( int* ) buffer )[fromOutSize], buffer_, fromZeroSize * sizeof( int ) );
- break;
- case RTAUDIO_FLOAT32:
- memcpy( buffer, &( ( float* ) buffer_ )[outIndex_], fromOutSize * sizeof( float ) );
- memcpy( &( ( float* ) buffer )[fromOutSize], buffer_, fromZeroSize * sizeof( float ) );
- break;
- case RTAUDIO_FLOAT64:
- memcpy( buffer, &( ( double* ) buffer_ )[outIndex_], fromOutSize * sizeof( double ) );
- memcpy( &( ( double* ) buffer )[fromOutSize], buffer_, fromZeroSize * sizeof( double ) );
- break;
- }
-
- // update "out" index
- outIndex_ += bufferSize;
- outIndex_ %= bufferSize_;
-
- return true;
- }
-
-private:
- char* buffer_;
- unsigned int bufferSize_;
- unsigned int inIndex_;
- unsigned int outIndex_;
-};
-
-//-----------------------------------------------------------------------------
-
-// In order to satisfy WASAPI's buffer requirements, we need a means of converting sample rate
-// between HW and the user. The convertBufferWasapi function is used to perform this conversion
-// between HwIn->UserIn and UserOut->HwOut during the stream callback loop.
-// This sample rate converter favors speed over quality, and works best with conversions between
-// one rate and its multiple.
-void convertBufferWasapi( char* outBuffer,
- const char* inBuffer,
- const unsigned int& channelCount,
- const unsigned int& inSampleRate,
- const unsigned int& outSampleRate,
- const unsigned int& inSampleCount,
- unsigned int& outSampleCount,
- const RtAudioFormat& format )
-{
- // calculate the new outSampleCount and relative sampleStep
- float sampleRatio = ( float ) outSampleRate / inSampleRate;
- float sampleStep = 1.0f / sampleRatio;
- float inSampleFraction = 0.0f;
-
- outSampleCount = ( unsigned int ) roundf( inSampleCount * sampleRatio );
-
- // frame-by-frame, copy each relative input sample into it's corresponding output sample
- for ( unsigned int outSample = 0; outSample < outSampleCount; outSample++ )
- {
- unsigned int inSample = ( unsigned int ) inSampleFraction;
-
- switch ( format )
- {
- case RTAUDIO_SINT8:
- memcpy( &( ( char* ) outBuffer )[ outSample * channelCount ], &( ( char* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( char ) );
- break;
- case RTAUDIO_SINT16:
- memcpy( &( ( short* ) outBuffer )[ outSample * channelCount ], &( ( short* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( short ) );
- break;
- case RTAUDIO_SINT24:
- memcpy( &( ( S24* ) outBuffer )[ outSample * channelCount ], &( ( S24* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( S24 ) );
- break;
- case RTAUDIO_SINT32:
- memcpy( &( ( int* ) outBuffer )[ outSample * channelCount ], &( ( int* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( int ) );
- break;
- case RTAUDIO_FLOAT32:
- memcpy( &( ( float* ) outBuffer )[ outSample * channelCount ], &( ( float* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( float ) );
- break;
- case RTAUDIO_FLOAT64:
- memcpy( &( ( double* ) outBuffer )[ outSample * channelCount ], &( ( double* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( double ) );
- break;
- }
-
- // jump to next in sample
- inSampleFraction += sampleStep;
- }
-}
-
-//-----------------------------------------------------------------------------
-
-// A structure to hold various information related to the WASAPI implementation.
-struct WasapiHandle
-{
- IAudioClient* captureAudioClient;
- IAudioClient* renderAudioClient;
- IAudioCaptureClient* captureClient;
- IAudioRenderClient* renderClient;
- HANDLE captureEvent;
- HANDLE renderEvent;
-
- WasapiHandle()
- : captureAudioClient( NULL ),
- renderAudioClient( NULL ),
- captureClient( NULL ),
- renderClient( NULL ),
- captureEvent( NULL ),
- renderEvent( NULL ) {}
-};
-
-//=============================================================================
-
-RtApiWasapi::RtApiWasapi()
- : coInitialized_( false ), deviceEnumerator_( NULL )
-{
- // WASAPI can run either apartment or multi-threaded
- HRESULT hr = CoInitialize( NULL );
- if ( !FAILED( hr ) )
- coInitialized_ = true;
-
- // Instantiate device enumerator
- hr = CoCreateInstance( __uuidof( MMDeviceEnumerator ), NULL,
- CLSCTX_ALL, __uuidof( IMMDeviceEnumerator ),
- ( void** ) &deviceEnumerator_ );
-
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::RtApiWasapi: Unable to instantiate device enumerator";
- error( RtAudioError::DRIVER_ERROR );
- }
-}
-
-//-----------------------------------------------------------------------------
-
-RtApiWasapi::~RtApiWasapi()
-{
- if ( stream_.state != STREAM_CLOSED )
- closeStream();
-
- SAFE_RELEASE( deviceEnumerator_ );
-
- // If this object previously called CoInitialize()
- if ( coInitialized_ )
- CoUninitialize();
-}
-
-//=============================================================================
-
-unsigned int RtApiWasapi::getDeviceCount( void )
-{
- unsigned int captureDeviceCount = 0;
- unsigned int renderDeviceCount = 0;
-
- IMMDeviceCollection* captureDevices = NULL;
- IMMDeviceCollection* renderDevices = NULL;
-
- // Count capture devices
- errorText_.clear();
- HRESULT hr = deviceEnumerator_->EnumAudioEndpoints( eCapture, DEVICE_STATE_ACTIVE, &captureDevices );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::getDeviceCount: Unable to retrieve capture device collection.";
- goto Exit;
- }
-
- hr = captureDevices->GetCount( &captureDeviceCount );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::getDeviceCount: Unable to retrieve capture device count.";
- goto Exit;
- }
-
- // Count render devices
- hr = deviceEnumerator_->EnumAudioEndpoints( eRender, DEVICE_STATE_ACTIVE, &renderDevices );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::getDeviceCount: Unable to retrieve render device collection.";
- goto Exit;
- }
-
- hr = renderDevices->GetCount( &renderDeviceCount );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::getDeviceCount: Unable to retrieve render device count.";
- goto Exit;
- }
-
-Exit:
- // release all references
- SAFE_RELEASE( captureDevices );
- SAFE_RELEASE( renderDevices );
-
- if ( errorText_.empty() )
- return captureDeviceCount + renderDeviceCount;
-
- error( RtAudioError::DRIVER_ERROR );
- return 0;
-}
-
-//-----------------------------------------------------------------------------
-
-RtAudio::DeviceInfo RtApiWasapi::getDeviceInfo( unsigned int device )
-{
- RtAudio::DeviceInfo info;
- unsigned int captureDeviceCount = 0;
- unsigned int renderDeviceCount = 0;
- std::string defaultDeviceName;
- bool isCaptureDevice = false;
-
- PROPVARIANT deviceNameProp;
- PROPVARIANT defaultDeviceNameProp;
-
- IMMDeviceCollection* captureDevices = NULL;
- IMMDeviceCollection* renderDevices = NULL;
- IMMDevice* devicePtr = NULL;
- IMMDevice* defaultDevicePtr = NULL;
- IAudioClient* audioClient = NULL;
- IPropertyStore* devicePropStore = NULL;
- IPropertyStore* defaultDevicePropStore = NULL;
-
- WAVEFORMATEX* deviceFormat = NULL;
- WAVEFORMATEX* closestMatchFormat = NULL;
-
- // probed
- info.probed = false;
-
- // Count capture devices
- errorText_.clear();
- RtAudioError::Type errorType = RtAudioError::DRIVER_ERROR;
- HRESULT hr = deviceEnumerator_->EnumAudioEndpoints( eCapture, DEVICE_STATE_ACTIVE, &captureDevices );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve capture device collection.";
- goto Exit;
- }
-
- hr = captureDevices->GetCount( &captureDeviceCount );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve capture device count.";
- goto Exit;
- }
-
- // Count render devices
- hr = deviceEnumerator_->EnumAudioEndpoints( eRender, DEVICE_STATE_ACTIVE, &renderDevices );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve render device collection.";
- goto Exit;
- }
-
- hr = renderDevices->GetCount( &renderDeviceCount );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve render device count.";
- goto Exit;
- }
-
- // validate device index
- if ( device >= captureDeviceCount + renderDeviceCount ) {
- errorText_ = "RtApiWasapi::getDeviceInfo: Invalid device index.";
- errorType = RtAudioError::INVALID_USE;
- goto Exit;
- }
-
- // determine whether index falls within capture or render devices
- if ( device >= renderDeviceCount ) {
- hr = captureDevices->Item( device - renderDeviceCount, &devicePtr );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve capture device handle.";
- goto Exit;
- }
- isCaptureDevice = true;
- }
- else {
- hr = renderDevices->Item( device, &devicePtr );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve render device handle.";
- goto Exit;
- }
- isCaptureDevice = false;
- }
-
- // get default device name
- if ( isCaptureDevice ) {
- hr = deviceEnumerator_->GetDefaultAudioEndpoint( eCapture, eConsole, &defaultDevicePtr );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve default capture device handle.";
- goto Exit;
- }
- }
- else {
- hr = deviceEnumerator_->GetDefaultAudioEndpoint( eRender, eConsole, &defaultDevicePtr );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve default render device handle.";
- goto Exit;
- }
- }
-
- hr = defaultDevicePtr->OpenPropertyStore( STGM_READ, &defaultDevicePropStore );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::getDeviceInfo: Unable to open default device property store.";
- goto Exit;
- }
- PropVariantInit( &defaultDeviceNameProp );
-
- hr = defaultDevicePropStore->GetValue( PKEY_Device_FriendlyName, &defaultDeviceNameProp );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve default device property: PKEY_Device_FriendlyName.";
- goto Exit;
- }
-
- defaultDeviceName = convertCharPointerToStdString(defaultDeviceNameProp.pwszVal);
-
- // name
- hr = devicePtr->OpenPropertyStore( STGM_READ, &devicePropStore );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::getDeviceInfo: Unable to open device property store.";
- goto Exit;
- }
-
- PropVariantInit( &deviceNameProp );
-
- hr = devicePropStore->GetValue( PKEY_Device_FriendlyName, &deviceNameProp );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve device property: PKEY_Device_FriendlyName.";
- goto Exit;
- }
-
- info.name =convertCharPointerToStdString(deviceNameProp.pwszVal);
-
- // is default
- if ( isCaptureDevice ) {
- info.isDefaultInput = info.name == defaultDeviceName;
- info.isDefaultOutput = false;
- }
- else {
- info.isDefaultInput = false;
- info.isDefaultOutput = info.name == defaultDeviceName;
- }
-
- // channel count
- hr = devicePtr->Activate( __uuidof( IAudioClient ), CLSCTX_ALL, NULL, ( void** ) &audioClient );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve device audio client.";
- goto Exit;
- }
-
- hr = audioClient->GetMixFormat( &deviceFormat );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve device mix format.";
- goto Exit;
- }
-
- if ( isCaptureDevice ) {
- info.inputChannels = deviceFormat->nChannels;
- info.outputChannels = 0;
- info.duplexChannels = 0;
- }
- else {
- info.inputChannels = 0;
- info.outputChannels = deviceFormat->nChannels;
- info.duplexChannels = 0;
- }
-
- // sample rates
- info.sampleRates.clear();
-
- // allow support for all sample rates as we have a built-in sample rate converter
- for ( unsigned int i = 0; i < MAX_SAMPLE_RATES; i++ ) {
- info.sampleRates.push_back( SAMPLE_RATES[i] );
- }
- info.preferredSampleRate = deviceFormat->nSamplesPerSec;
-
- // native format
- info.nativeFormats = 0;
-
- if ( deviceFormat->wFormatTag == WAVE_FORMAT_IEEE_FLOAT ||
- ( deviceFormat->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
- ( ( WAVEFORMATEXTENSIBLE* ) deviceFormat )->SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT ) )
- {
- if ( deviceFormat->wBitsPerSample == 32 ) {
- info.nativeFormats |= RTAUDIO_FLOAT32;
- }
- else if ( deviceFormat->wBitsPerSample == 64 ) {
- info.nativeFormats |= RTAUDIO_FLOAT64;
- }
- }
- else if ( deviceFormat->wFormatTag == WAVE_FORMAT_PCM ||
- ( deviceFormat->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
- ( ( WAVEFORMATEXTENSIBLE* ) deviceFormat )->SubFormat == KSDATAFORMAT_SUBTYPE_PCM ) )
- {
- if ( deviceFormat->wBitsPerSample == 8 ) {
- info.nativeFormats |= RTAUDIO_SINT8;
- }
- else if ( deviceFormat->wBitsPerSample == 16 ) {
- info.nativeFormats |= RTAUDIO_SINT16;
- }
- else if ( deviceFormat->wBitsPerSample == 24 ) {
- info.nativeFormats |= RTAUDIO_SINT24;
- }
- else if ( deviceFormat->wBitsPerSample == 32 ) {
- info.nativeFormats |= RTAUDIO_SINT32;
- }
- }
-
- // probed
- info.probed = true;
-
-Exit:
- // release all references
- PropVariantClear( &deviceNameProp );
- PropVariantClear( &defaultDeviceNameProp );
-
- SAFE_RELEASE( captureDevices );
- SAFE_RELEASE( renderDevices );
- SAFE_RELEASE( devicePtr );
- SAFE_RELEASE( defaultDevicePtr );
- SAFE_RELEASE( audioClient );
- SAFE_RELEASE( devicePropStore );
- SAFE_RELEASE( defaultDevicePropStore );
-
- CoTaskMemFree( deviceFormat );
- CoTaskMemFree( closestMatchFormat );
-
- if ( !errorText_.empty() )
- error( errorType );
- return info;
-}
-
-//-----------------------------------------------------------------------------
-
-unsigned int RtApiWasapi::getDefaultOutputDevice( void )
-{
- for ( unsigned int i = 0; i < getDeviceCount(); i++ ) {
- if ( getDeviceInfo( i ).isDefaultOutput ) {
- return i;
- }
- }
-
- return 0;
-}
-
-//-----------------------------------------------------------------------------
-
-unsigned int RtApiWasapi::getDefaultInputDevice( void )
-{
- for ( unsigned int i = 0; i < getDeviceCount(); i++ ) {
- if ( getDeviceInfo( i ).isDefaultInput ) {
- return i;
- }
- }
-
- return 0;
-}
-
-//-----------------------------------------------------------------------------
-
-void RtApiWasapi::closeStream( void )
-{
- if ( stream_.state == STREAM_CLOSED ) {
- errorText_ = "RtApiWasapi::closeStream: No open stream to close.";
- error( RtAudioError::WARNING );
- return;
- }
-
- if ( stream_.state != STREAM_STOPPED )
- stopStream();
-
- // clean up stream memory
- SAFE_RELEASE( ( ( WasapiHandle* ) stream_.apiHandle )->captureAudioClient )
- SAFE_RELEASE( ( ( WasapiHandle* ) stream_.apiHandle )->renderAudioClient )
-
- SAFE_RELEASE( ( ( WasapiHandle* ) stream_.apiHandle )->captureClient )
- SAFE_RELEASE( ( ( WasapiHandle* ) stream_.apiHandle )->renderClient )
-
- if ( ( ( WasapiHandle* ) stream_.apiHandle )->captureEvent )
- CloseHandle( ( ( WasapiHandle* ) stream_.apiHandle )->captureEvent );
-
- if ( ( ( WasapiHandle* ) stream_.apiHandle )->renderEvent )
- CloseHandle( ( ( WasapiHandle* ) stream_.apiHandle )->renderEvent );
-
- delete ( WasapiHandle* ) stream_.apiHandle;
- stream_.apiHandle = NULL;
-
- for ( int i = 0; i < 2; i++ ) {
- if ( stream_.userBuffer[i] ) {
- free( stream_.userBuffer[i] );
- stream_.userBuffer[i] = 0;
- }
- }
-
- if ( stream_.deviceBuffer ) {
- free( stream_.deviceBuffer );
- stream_.deviceBuffer = 0;
- }
-
- // update stream state
- stream_.state = STREAM_CLOSED;
-}
-
-//-----------------------------------------------------------------------------
-
-void RtApiWasapi::startStream( void )
-{
- verifyStream();
-
- if ( stream_.state == STREAM_RUNNING ) {
- errorText_ = "RtApiWasapi::startStream: The stream is already running.";
- error( RtAudioError::WARNING );
- return;
- }
-
- // update stream state
- stream_.state = STREAM_RUNNING;
-
- // create WASAPI stream thread
- stream_.callbackInfo.thread = ( ThreadHandle ) CreateThread( NULL, 0, runWasapiThread, this, CREATE_SUSPENDED, NULL );
-
- if ( !stream_.callbackInfo.thread ) {
- errorText_ = "RtApiWasapi::startStream: Unable to instantiate callback thread.";
- error( RtAudioError::THREAD_ERROR );
- }
- else {
- SetThreadPriority( ( void* ) stream_.callbackInfo.thread, stream_.callbackInfo.priority );
- ResumeThread( ( void* ) stream_.callbackInfo.thread );
- }
-}
-
-//-----------------------------------------------------------------------------
-
-void RtApiWasapi::stopStream( void )
-{
- verifyStream();
-
- if ( stream_.state == STREAM_STOPPED ) {
- errorText_ = "RtApiWasapi::stopStream: The stream is already stopped.";
- error( RtAudioError::WARNING );
- return;
- }
-
- // inform stream thread by setting stream state to STREAM_STOPPING
- stream_.state = STREAM_STOPPING;
-
- // wait until stream thread is stopped
- while( stream_.state != STREAM_STOPPED ) {
- Sleep( 1 );
- }
-
- // Wait for the last buffer to play before stopping.
- Sleep( 1000 * stream_.bufferSize / stream_.sampleRate );
-
- // stop capture client if applicable
- if ( ( ( WasapiHandle* ) stream_.apiHandle )->captureAudioClient ) {
- HRESULT hr = ( ( WasapiHandle* ) stream_.apiHandle )->captureAudioClient->Stop();
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::stopStream: Unable to stop capture stream.";
- error( RtAudioError::DRIVER_ERROR );
- return;
- }
- }
-
- // stop render client if applicable
- if ( ( ( WasapiHandle* ) stream_.apiHandle )->renderAudioClient ) {
- HRESULT hr = ( ( WasapiHandle* ) stream_.apiHandle )->renderAudioClient->Stop();
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::stopStream: Unable to stop render stream.";
- error( RtAudioError::DRIVER_ERROR );
- return;
- }
- }
-
- // close thread handle
- if ( stream_.callbackInfo.thread && !CloseHandle( ( void* ) stream_.callbackInfo.thread ) ) {
- errorText_ = "RtApiWasapi::stopStream: Unable to close callback thread.";
- error( RtAudioError::THREAD_ERROR );
- return;
- }
-
- stream_.callbackInfo.thread = (ThreadHandle) NULL;
-}
-
-//-----------------------------------------------------------------------------
-
-void RtApiWasapi::abortStream( void )
-{
- verifyStream();
-
- if ( stream_.state == STREAM_STOPPED ) {
- errorText_ = "RtApiWasapi::abortStream: The stream is already stopped.";
- error( RtAudioError::WARNING );
- return;
- }
-
- // inform stream thread by setting stream state to STREAM_STOPPING
- stream_.state = STREAM_STOPPING;
-
- // wait until stream thread is stopped
- while ( stream_.state != STREAM_STOPPED ) {
- Sleep( 1 );
- }
-
- // stop capture client if applicable
- if ( ( ( WasapiHandle* ) stream_.apiHandle )->captureAudioClient ) {
- HRESULT hr = ( ( WasapiHandle* ) stream_.apiHandle )->captureAudioClient->Stop();
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::abortStream: Unable to stop capture stream.";
- error( RtAudioError::DRIVER_ERROR );
- return;
- }
- }
-
- // stop render client if applicable
- if ( ( ( WasapiHandle* ) stream_.apiHandle )->renderAudioClient ) {
- HRESULT hr = ( ( WasapiHandle* ) stream_.apiHandle )->renderAudioClient->Stop();
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::abortStream: Unable to stop render stream.";
- error( RtAudioError::DRIVER_ERROR );
- return;
- }
- }
-
- // close thread handle
- if ( stream_.callbackInfo.thread && !CloseHandle( ( void* ) stream_.callbackInfo.thread ) ) {
- errorText_ = "RtApiWasapi::abortStream: Unable to close callback thread.";
- error( RtAudioError::THREAD_ERROR );
- return;
- }
-
- stream_.callbackInfo.thread = (ThreadHandle) NULL;
-}
-
-//-----------------------------------------------------------------------------
-
-bool RtApiWasapi::probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,
- unsigned int firstChannel, unsigned int sampleRate,
- RtAudioFormat format, unsigned int* bufferSize,
- RtAudio::StreamOptions* options )
-{
- bool methodResult = FAILURE;
- unsigned int captureDeviceCount = 0;
- unsigned int renderDeviceCount = 0;
-
- IMMDeviceCollection* captureDevices = NULL;
- IMMDeviceCollection* renderDevices = NULL;
- IMMDevice* devicePtr = NULL;
- WAVEFORMATEX* deviceFormat = NULL;
- unsigned int bufferBytes;
- stream_.state = STREAM_STOPPED;
-
- // create API Handle if not already created
- if ( !stream_.apiHandle )
- stream_.apiHandle = ( void* ) new WasapiHandle();
-
- // Count capture devices
- errorText_.clear();
- RtAudioError::Type errorType = RtAudioError::DRIVER_ERROR;
- HRESULT hr = deviceEnumerator_->EnumAudioEndpoints( eCapture, DEVICE_STATE_ACTIVE, &captureDevices );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve capture device collection.";
- goto Exit;
- }
-
- hr = captureDevices->GetCount( &captureDeviceCount );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve capture device count.";
- goto Exit;
- }
-
- // Count render devices
- hr = deviceEnumerator_->EnumAudioEndpoints( eRender, DEVICE_STATE_ACTIVE, &renderDevices );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve render device collection.";
- goto Exit;
- }
-
- hr = renderDevices->GetCount( &renderDeviceCount );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve render device count.";
- goto Exit;
- }
-
- // validate device index
- if ( device >= captureDeviceCount + renderDeviceCount ) {
- errorType = RtAudioError::INVALID_USE;
- errorText_ = "RtApiWasapi::probeDeviceOpen: Invalid device index.";
- goto Exit;
- }
-
- // determine whether index falls within capture or render devices
- if ( device >= renderDeviceCount ) {
- if ( mode != INPUT ) {
- errorType = RtAudioError::INVALID_USE;
- errorText_ = "RtApiWasapi::probeDeviceOpen: Capture device selected as output device.";
- goto Exit;
- }
-
- // retrieve captureAudioClient from devicePtr
- IAudioClient*& captureAudioClient = ( ( WasapiHandle* ) stream_.apiHandle )->captureAudioClient;
-
- hr = captureDevices->Item( device - renderDeviceCount, &devicePtr );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve capture device handle.";
- goto Exit;
- }
-
- hr = devicePtr->Activate( __uuidof( IAudioClient ), CLSCTX_ALL,
- NULL, ( void** ) &captureAudioClient );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve device audio client.";
- goto Exit;
- }
-
- hr = captureAudioClient->GetMixFormat( &deviceFormat );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve device mix format.";
- goto Exit;
- }
-
- stream_.nDeviceChannels[mode] = deviceFormat->nChannels;
- captureAudioClient->GetStreamLatency( ( long long* ) &stream_.latency[mode] );
- }
- else {
- if ( mode != OUTPUT ) {
- errorType = RtAudioError::INVALID_USE;
- errorText_ = "RtApiWasapi::probeDeviceOpen: Render device selected as input device.";
- goto Exit;
- }
-
- // retrieve renderAudioClient from devicePtr
- IAudioClient*& renderAudioClient = ( ( WasapiHandle* ) stream_.apiHandle )->renderAudioClient;
-
- hr = renderDevices->Item( device, &devicePtr );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve render device handle.";
- goto Exit;
- }
-
- hr = devicePtr->Activate( __uuidof( IAudioClient ), CLSCTX_ALL,
- NULL, ( void** ) &renderAudioClient );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve device audio client.";
- goto Exit;
- }
-
- hr = renderAudioClient->GetMixFormat( &deviceFormat );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve device mix format.";
- goto Exit;
- }
-
- stream_.nDeviceChannels[mode] = deviceFormat->nChannels;
- renderAudioClient->GetStreamLatency( ( long long* ) &stream_.latency[mode] );
- }
-
- // fill stream data
- if ( ( stream_.mode == OUTPUT && mode == INPUT ) ||
- ( stream_.mode == INPUT && mode == OUTPUT ) ) {
- stream_.mode = DUPLEX;
- }
- else {
- stream_.mode = mode;
- }
-
- stream_.device[mode] = device;
- stream_.doByteSwap[mode] = false;
- stream_.sampleRate = sampleRate;
- stream_.bufferSize = *bufferSize;
- stream_.nBuffers = 1;
- stream_.nUserChannels[mode] = channels;
- stream_.channelOffset[mode] = firstChannel;
- stream_.userFormat = format;
- stream_.deviceFormat[mode] = getDeviceInfo( device ).nativeFormats;
-
- if ( options && options->flags & RTAUDIO_NONINTERLEAVED )
- stream_.userInterleaved = false;
- else
- stream_.userInterleaved = true;
- stream_.deviceInterleaved[mode] = true;
-
- // Set flags for buffer conversion.
- stream_.doConvertBuffer[mode] = false;
- if ( stream_.userFormat != stream_.deviceFormat[mode] ||
- stream_.nUserChannels != stream_.nDeviceChannels )
- stream_.doConvertBuffer[mode] = true;
- else if ( stream_.userInterleaved != stream_.deviceInterleaved[mode] &&
- stream_.nUserChannels[mode] > 1 )
- stream_.doConvertBuffer[mode] = true;
-
- if ( stream_.doConvertBuffer[mode] )
- setConvertInfo( mode, 0 );
-
- // Allocate necessary internal buffers
- bufferBytes = stream_.nUserChannels[mode] * stream_.bufferSize * formatBytes( stream_.userFormat );
-
- stream_.userBuffer[mode] = ( char* ) calloc( bufferBytes, 1 );
- if ( !stream_.userBuffer[mode] ) {
- errorType = RtAudioError::MEMORY_ERROR;
- errorText_ = "RtApiWasapi::probeDeviceOpen: Error allocating user buffer memory.";
- goto Exit;
- }
-
- if ( options && options->flags & RTAUDIO_SCHEDULE_REALTIME )
- stream_.callbackInfo.priority = 15;
- else
- stream_.callbackInfo.priority = 0;
-
- ///! TODO: RTAUDIO_MINIMIZE_LATENCY // Provide stream buffers directly to callback
- ///! TODO: RTAUDIO_HOG_DEVICE // Exclusive mode
-
- methodResult = SUCCESS;
-
-Exit:
- //clean up
- SAFE_RELEASE( captureDevices );
- SAFE_RELEASE( renderDevices );
- SAFE_RELEASE( devicePtr );
- CoTaskMemFree( deviceFormat );
-
- // if method failed, close the stream
- if ( methodResult == FAILURE )
- closeStream();
-
- if ( !errorText_.empty() )
- error( errorType );
- return methodResult;
-}
-
-//=============================================================================
-
-DWORD WINAPI RtApiWasapi::runWasapiThread( void* wasapiPtr )
-{
- if ( wasapiPtr )
- ( ( RtApiWasapi* ) wasapiPtr )->wasapiThread();
-
- return 0;
-}
-
-DWORD WINAPI RtApiWasapi::stopWasapiThread( void* wasapiPtr )
-{
- if ( wasapiPtr )
- ( ( RtApiWasapi* ) wasapiPtr )->stopStream();
-
- return 0;
-}
-
-DWORD WINAPI RtApiWasapi::abortWasapiThread( void* wasapiPtr )
-{
- if ( wasapiPtr )
- ( ( RtApiWasapi* ) wasapiPtr )->abortStream();
-
- return 0;
-}
-
-//-----------------------------------------------------------------------------
-
-void RtApiWasapi::wasapiThread()
-{
- // as this is a new thread, we must CoInitialize it
- CoInitialize( NULL );
-
- HRESULT hr;
-
- IAudioClient* captureAudioClient = ( ( WasapiHandle* ) stream_.apiHandle )->captureAudioClient;
- IAudioClient* renderAudioClient = ( ( WasapiHandle* ) stream_.apiHandle )->renderAudioClient;
- IAudioCaptureClient* captureClient = ( ( WasapiHandle* ) stream_.apiHandle )->captureClient;
- IAudioRenderClient* renderClient = ( ( WasapiHandle* ) stream_.apiHandle )->renderClient;
- HANDLE captureEvent = ( ( WasapiHandle* ) stream_.apiHandle )->captureEvent;
- HANDLE renderEvent = ( ( WasapiHandle* ) stream_.apiHandle )->renderEvent;
-
- WAVEFORMATEX* captureFormat = NULL;
- WAVEFORMATEX* renderFormat = NULL;
- float captureSrRatio = 0.0f;
- float renderSrRatio = 0.0f;
- WasapiBuffer captureBuffer;
- WasapiBuffer renderBuffer;
-
- // declare local stream variables
- RtAudioCallback callback = ( RtAudioCallback ) stream_.callbackInfo.callback;
- BYTE* streamBuffer = NULL;
- unsigned long captureFlags = 0;
- unsigned int bufferFrameCount = 0;
- unsigned int numFramesPadding = 0;
- unsigned int convBufferSize = 0;
- bool callbackPushed = false;
- bool callbackPulled = false;
- bool callbackStopped = false;
- int callbackResult = 0;
-
- // convBuffer is used to store converted buffers between WASAPI and the user
- char* convBuffer = NULL;
- unsigned int convBuffSize = 0;
- unsigned int deviceBuffSize = 0;
-
- errorText_.clear();
- RtAudioError::Type errorType = RtAudioError::DRIVER_ERROR;
-
- // Attempt to assign "Pro Audio" characteristic to thread
- HMODULE AvrtDll = LoadLibrary( (LPCTSTR) "AVRT.dll" );
- if ( AvrtDll ) {
- DWORD taskIndex = 0;
- TAvSetMmThreadCharacteristicsPtr AvSetMmThreadCharacteristicsPtr = ( TAvSetMmThreadCharacteristicsPtr ) GetProcAddress( AvrtDll, "AvSetMmThreadCharacteristicsW" );
- AvSetMmThreadCharacteristicsPtr( L"Pro Audio", &taskIndex );
- FreeLibrary( AvrtDll );
- }
-
- // start capture stream if applicable
- if ( captureAudioClient ) {
- hr = captureAudioClient->GetMixFormat( &captureFormat );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::wasapiThread: Unable to retrieve device mix format.";
- goto Exit;
- }
-
- captureSrRatio = ( ( float ) captureFormat->nSamplesPerSec / stream_.sampleRate );
-
- // initialize capture stream according to desire buffer size
- float desiredBufferSize = stream_.bufferSize * captureSrRatio;
- REFERENCE_TIME desiredBufferPeriod = ( REFERENCE_TIME ) ( ( float ) desiredBufferSize * 10000000 / captureFormat->nSamplesPerSec );
-
- if ( !captureClient ) {
- hr = captureAudioClient->Initialize( AUDCLNT_SHAREMODE_SHARED,
- AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
- desiredBufferPeriod,
- desiredBufferPeriod,
- captureFormat,
- NULL );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::wasapiThread: Unable to initialize capture audio client.";
- goto Exit;
- }
-
- hr = captureAudioClient->GetService( __uuidof( IAudioCaptureClient ),
- ( void** ) &captureClient );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::wasapiThread: Unable to retrieve capture client handle.";
- goto Exit;
- }
-
- // configure captureEvent to trigger on every available capture buffer
- captureEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
- if ( !captureEvent ) {
- errorType = RtAudioError::SYSTEM_ERROR;
- errorText_ = "RtApiWasapi::wasapiThread: Unable to create capture event.";
- goto Exit;
- }
-
- hr = captureAudioClient->SetEventHandle( captureEvent );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::wasapiThread: Unable to set capture event handle.";
- goto Exit;
- }
-
- ( ( WasapiHandle* ) stream_.apiHandle )->captureClient = captureClient;
- ( ( WasapiHandle* ) stream_.apiHandle )->captureEvent = captureEvent;
- }
-
- unsigned int inBufferSize = 0;
- hr = captureAudioClient->GetBufferSize( &inBufferSize );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::wasapiThread: Unable to get capture buffer size.";
- goto Exit;
- }
-
- // scale outBufferSize according to stream->user sample rate ratio
- unsigned int outBufferSize = ( unsigned int ) ( stream_.bufferSize * captureSrRatio ) * stream_.nDeviceChannels[INPUT];
- inBufferSize *= stream_.nDeviceChannels[INPUT];
-
- // set captureBuffer size
- captureBuffer.setBufferSize( inBufferSize + outBufferSize, formatBytes( stream_.deviceFormat[INPUT] ) );
-
- // reset the capture stream
- hr = captureAudioClient->Reset();
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::wasapiThread: Unable to reset capture stream.";
- goto Exit;
- }
-
- // start the capture stream
- hr = captureAudioClient->Start();
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::wasapiThread: Unable to start capture stream.";
- goto Exit;
- }
- }
-
- // start render stream if applicable
- if ( renderAudioClient ) {
- hr = renderAudioClient->GetMixFormat( &renderFormat );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::wasapiThread: Unable to retrieve device mix format.";
- goto Exit;
- }
-
- renderSrRatio = ( ( float ) renderFormat->nSamplesPerSec / stream_.sampleRate );
-
- // initialize render stream according to desire buffer size
- float desiredBufferSize = stream_.bufferSize * renderSrRatio;
- REFERENCE_TIME desiredBufferPeriod = ( REFERENCE_TIME ) ( ( float ) desiredBufferSize * 10000000 / renderFormat->nSamplesPerSec );
-
- if ( !renderClient ) {
- hr = renderAudioClient->Initialize( AUDCLNT_SHAREMODE_SHARED,
- AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
- desiredBufferPeriod,
- desiredBufferPeriod,
- renderFormat,
- NULL );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::wasapiThread: Unable to initialize render audio client.";
- goto Exit;
- }
-
- hr = renderAudioClient->GetService( __uuidof( IAudioRenderClient ),
- ( void** ) &renderClient );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::wasapiThread: Unable to retrieve render client handle.";
- goto Exit;
- }
-
- // configure renderEvent to trigger on every available render buffer
- renderEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
- if ( !renderEvent ) {
- errorType = RtAudioError::SYSTEM_ERROR;
- errorText_ = "RtApiWasapi::wasapiThread: Unable to create render event.";
- goto Exit;
- }
-
- hr = renderAudioClient->SetEventHandle( renderEvent );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::wasapiThread: Unable to set render event handle.";
- goto Exit;
- }
-
- ( ( WasapiHandle* ) stream_.apiHandle )->renderClient = renderClient;
- ( ( WasapiHandle* ) stream_.apiHandle )->renderEvent = renderEvent;
- }
-
- unsigned int outBufferSize = 0;
- hr = renderAudioClient->GetBufferSize( &outBufferSize );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::wasapiThread: Unable to get render buffer size.";
- goto Exit;
- }
-
- // scale inBufferSize according to user->stream sample rate ratio
- unsigned int inBufferSize = ( unsigned int ) ( stream_.bufferSize * renderSrRatio ) * stream_.nDeviceChannels[OUTPUT];
- outBufferSize *= stream_.nDeviceChannels[OUTPUT];
-
- // set renderBuffer size
- renderBuffer.setBufferSize( inBufferSize + outBufferSize, formatBytes( stream_.deviceFormat[OUTPUT] ) );
-
- // reset the render stream
- hr = renderAudioClient->Reset();
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::wasapiThread: Unable to reset render stream.";
- goto Exit;
- }
-
- // start the render stream
- hr = renderAudioClient->Start();
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::wasapiThread: Unable to start render stream.";
- goto Exit;
- }
- }
-
- if ( stream_.mode == INPUT ) {
- convBuffSize = ( size_t ) ( stream_.bufferSize * captureSrRatio ) * stream_.nDeviceChannels[INPUT] * formatBytes( stream_.deviceFormat[INPUT] );
- deviceBuffSize = stream_.bufferSize * stream_.nDeviceChannels[INPUT] * formatBytes( stream_.deviceFormat[INPUT] );
- }
- else if ( stream_.mode == OUTPUT ) {
- convBuffSize = ( size_t ) ( stream_.bufferSize * renderSrRatio ) * stream_.nDeviceChannels[OUTPUT] * formatBytes( stream_.deviceFormat[OUTPUT] );
- deviceBuffSize = stream_.bufferSize * stream_.nDeviceChannels[OUTPUT] * formatBytes( stream_.deviceFormat[OUTPUT] );
- }
- else if ( stream_.mode == DUPLEX ) {
- convBuffSize = std::max( ( size_t ) ( stream_.bufferSize * captureSrRatio ) * stream_.nDeviceChannels[INPUT] * formatBytes( stream_.deviceFormat[INPUT] ),
- ( size_t ) ( stream_.bufferSize * renderSrRatio ) * stream_.nDeviceChannels[OUTPUT] * formatBytes( stream_.deviceFormat[OUTPUT] ) );
- deviceBuffSize = std::max( stream_.bufferSize * stream_.nDeviceChannels[INPUT] * formatBytes( stream_.deviceFormat[INPUT] ),
- stream_.bufferSize * stream_.nDeviceChannels[OUTPUT] * formatBytes( stream_.deviceFormat[OUTPUT] ) );
- }
-
- convBuffer = ( char* ) malloc( convBuffSize );
- stream_.deviceBuffer = ( char* ) malloc( deviceBuffSize );
- if ( !convBuffer || !stream_.deviceBuffer ) {
- errorType = RtAudioError::MEMORY_ERROR;
- errorText_ = "RtApiWasapi::wasapiThread: Error allocating device buffer memory.";
- goto Exit;
- }
-
- // stream process loop
- while ( stream_.state != STREAM_STOPPING ) {
- if ( !callbackPulled ) {
- // Callback Input
- // ==============
- // 1. Pull callback buffer from inputBuffer
- // 2. If 1. was successful: Convert callback buffer to user sample rate and channel count
- // Convert callback buffer to user format
-
- if ( captureAudioClient ) {
- // Pull callback buffer from inputBuffer
- callbackPulled = captureBuffer.pullBuffer( convBuffer,
- ( unsigned int ) ( stream_.bufferSize * captureSrRatio ) * stream_.nDeviceChannels[INPUT],
- stream_.deviceFormat[INPUT] );
-
- if ( callbackPulled ) {
- // Convert callback buffer to user sample rate
- convertBufferWasapi( stream_.deviceBuffer,
- convBuffer,
- stream_.nDeviceChannels[INPUT],
- captureFormat->nSamplesPerSec,
- stream_.sampleRate,
- ( unsigned int ) ( stream_.bufferSize * captureSrRatio ),
- convBufferSize,
- stream_.deviceFormat[INPUT] );
-
- if ( stream_.doConvertBuffer[INPUT] ) {
- // Convert callback buffer to user format
- convertBuffer( stream_.userBuffer[INPUT],
- stream_.deviceBuffer,
- stream_.convertInfo[INPUT] );
- }
- else {
- // no further conversion, simple copy deviceBuffer to userBuffer
- memcpy( stream_.userBuffer[INPUT],
- stream_.deviceBuffer,
- stream_.bufferSize * stream_.nUserChannels[INPUT] * formatBytes( stream_.userFormat ) );
- }
- }
- }
- else {
- // if there is no capture stream, set callbackPulled flag
- callbackPulled = true;
- }
-
- // Execute Callback
- // ================
- // 1. Execute user callback method
- // 2. Handle return value from callback
-
- // if callback has not requested the stream to stop
- if ( callbackPulled && !callbackStopped ) {
- // Execute user callback method
- callbackResult = callback( stream_.userBuffer[OUTPUT],
- stream_.userBuffer[INPUT],
- stream_.bufferSize,
- getStreamTime(),
- captureFlags & AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY ? RTAUDIO_INPUT_OVERFLOW : 0,
- stream_.callbackInfo.userData );
-
- // Handle return value from callback
- if ( callbackResult == 1 ) {
- // instantiate a thread to stop this thread
- HANDLE threadHandle = CreateThread( NULL, 0, stopWasapiThread, this, 0, NULL );
- if ( !threadHandle ) {
- errorType = RtAudioError::THREAD_ERROR;
- errorText_ = "RtApiWasapi::wasapiThread: Unable to instantiate stream stop thread.";
- goto Exit;
- }
- else if ( !CloseHandle( threadHandle ) ) {
- errorType = RtAudioError::THREAD_ERROR;
- errorText_ = "RtApiWasapi::wasapiThread: Unable to close stream stop thread handle.";
- goto Exit;
- }
-
- callbackStopped = true;
- }
- else if ( callbackResult == 2 ) {
- // instantiate a thread to stop this thread
- HANDLE threadHandle = CreateThread( NULL, 0, abortWasapiThread, this, 0, NULL );
- if ( !threadHandle ) {
- errorType = RtAudioError::THREAD_ERROR;
- errorText_ = "RtApiWasapi::wasapiThread: Unable to instantiate stream abort thread.";
- goto Exit;
- }
- else if ( !CloseHandle( threadHandle ) ) {
- errorType = RtAudioError::THREAD_ERROR;
- errorText_ = "RtApiWasapi::wasapiThread: Unable to close stream abort thread handle.";
- goto Exit;
- }
-
- callbackStopped = true;
- }
- }
- }
-
- // Callback Output
- // ===============
- // 1. Convert callback buffer to stream format
- // 2. Convert callback buffer to stream sample rate and channel count
- // 3. Push callback buffer into outputBuffer
-
- if ( renderAudioClient && callbackPulled ) {
- if ( stream_.doConvertBuffer[OUTPUT] ) {
- // Convert callback buffer to stream format
- convertBuffer( stream_.deviceBuffer,
- stream_.userBuffer[OUTPUT],
- stream_.convertInfo[OUTPUT] );
-
- }
-
- // Convert callback buffer to stream sample rate
- convertBufferWasapi( convBuffer,
- stream_.deviceBuffer,
- stream_.nDeviceChannels[OUTPUT],
- stream_.sampleRate,
- renderFormat->nSamplesPerSec,
- stream_.bufferSize,
- convBufferSize,
- stream_.deviceFormat[OUTPUT] );
-
- // Push callback buffer into outputBuffer
- callbackPushed = renderBuffer.pushBuffer( convBuffer,
- convBufferSize * stream_.nDeviceChannels[OUTPUT],
- stream_.deviceFormat[OUTPUT] );
- }
- else {
- // if there is no render stream, set callbackPushed flag
- callbackPushed = true;
- }
-
- // Stream Capture
- // ==============
- // 1. Get capture buffer from stream
- // 2. Push capture buffer into inputBuffer
- // 3. If 2. was successful: Release capture buffer
-
- if ( captureAudioClient ) {
- // if the callback input buffer was not pulled from captureBuffer, wait for next capture event
- if ( !callbackPulled ) {
- WaitForSingleObject( captureEvent, INFINITE );
- }
-
- // Get capture buffer from stream
- hr = captureClient->GetBuffer( &streamBuffer,
- &bufferFrameCount,
- &captureFlags, NULL, NULL );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::wasapiThread: Unable to retrieve capture buffer.";
- goto Exit;
- }
-
- if ( bufferFrameCount != 0 ) {
- // Push capture buffer into inputBuffer
- if ( captureBuffer.pushBuffer( ( char* ) streamBuffer,
- bufferFrameCount * stream_.nDeviceChannels[INPUT],
- stream_.deviceFormat[INPUT] ) )
- {
- // Release capture buffer
- hr = captureClient->ReleaseBuffer( bufferFrameCount );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::wasapiThread: Unable to release capture buffer.";
- goto Exit;
- }
- }
- else
- {
- // Inform WASAPI that capture was unsuccessful
- hr = captureClient->ReleaseBuffer( 0 );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::wasapiThread: Unable to release capture buffer.";
- goto Exit;
- }
- }
- }
- else
- {
- // Inform WASAPI that capture was unsuccessful
- hr = captureClient->ReleaseBuffer( 0 );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::wasapiThread: Unable to release capture buffer.";
- goto Exit;
- }
- }
- }
-
- // Stream Render
- // =============
- // 1. Get render buffer from stream
- // 2. Pull next buffer from outputBuffer
- // 3. If 2. was successful: Fill render buffer with next buffer
- // Release render buffer
-
- if ( renderAudioClient ) {
- // if the callback output buffer was not pushed to renderBuffer, wait for next render event
- if ( callbackPulled && !callbackPushed ) {
- WaitForSingleObject( renderEvent, INFINITE );
- }
-
- // Get render buffer from stream
- hr = renderAudioClient->GetBufferSize( &bufferFrameCount );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::wasapiThread: Unable to retrieve render buffer size.";
- goto Exit;
- }
-
- hr = renderAudioClient->GetCurrentPadding( &numFramesPadding );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::wasapiThread: Unable to retrieve render buffer padding.";
- goto Exit;
- }
-
- bufferFrameCount -= numFramesPadding;
-
- if ( bufferFrameCount != 0 ) {
- hr = renderClient->GetBuffer( bufferFrameCount, &streamBuffer );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::wasapiThread: Unable to retrieve render buffer.";
- goto Exit;
- }
-
- // Pull next buffer from outputBuffer
- // Fill render buffer with next buffer
- if ( renderBuffer.pullBuffer( ( char* ) streamBuffer,
- bufferFrameCount * stream_.nDeviceChannels[OUTPUT],
- stream_.deviceFormat[OUTPUT] ) )
- {
- // Release render buffer
- hr = renderClient->ReleaseBuffer( bufferFrameCount, 0 );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::wasapiThread: Unable to release render buffer.";
- goto Exit;
- }
- }
- else
- {
- // Inform WASAPI that render was unsuccessful
- hr = renderClient->ReleaseBuffer( 0, 0 );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::wasapiThread: Unable to release render buffer.";
- goto Exit;
- }
- }
- }
- else
- {
- // Inform WASAPI that render was unsuccessful
- hr = renderClient->ReleaseBuffer( 0, 0 );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::wasapiThread: Unable to release render buffer.";
- goto Exit;
- }
- }
- }
-
- // if the callback buffer was pushed renderBuffer reset callbackPulled flag
- if ( callbackPushed ) {
- callbackPulled = false;
- // tick stream time
- RtApi::tickStreamTime();
- }
-
- }
-
-Exit:
- // clean up
- CoTaskMemFree( captureFormat );
- CoTaskMemFree( renderFormat );
-
- free ( convBuffer );
-
- CoUninitialize();
-
- // update stream state
- stream_.state = STREAM_STOPPED;
-
- if ( errorText_.empty() )
- return;
- else
- error( errorType );
-}
-
-//******************** End of __WINDOWS_WASAPI__ *********************//
-#endif
-
-
-#if defined(__WINDOWS_DS__) // Windows DirectSound API
-
-// Modified by Robin Davies, October 2005
-// - Improvements to DirectX pointer chasing.
-// - Bug fix for non-power-of-two Asio granularity used by Edirol PCR-A30.
-// - Auto-call CoInitialize for DSOUND and ASIO platforms.
-// Various revisions for RtAudio 4.0 by Gary Scavone, April 2007
-// Changed device query structure for RtAudio 4.0.7, January 2010
-
-#include <dsound.h>
-#include <assert.h>
-#include <algorithm>
-
-#if defined(__MINGW32__)
- // missing from latest mingw winapi
-#define WAVE_FORMAT_96M08 0x00010000 /* 96 kHz, Mono, 8-bit */
-#define WAVE_FORMAT_96S08 0x00020000 /* 96 kHz, Stereo, 8-bit */
-#define WAVE_FORMAT_96M16 0x00040000 /* 96 kHz, Mono, 16-bit */
-#define WAVE_FORMAT_96S16 0x00080000 /* 96 kHz, Stereo, 16-bit */
-#endif
-
-#define MINIMUM_DEVICE_BUFFER_SIZE 32768
-
-#ifdef _MSC_VER // if Microsoft Visual C++
-#pragma comment( lib, "winmm.lib" ) // then, auto-link winmm.lib. Otherwise, it has to be added manually.
-#endif
-
-static inline DWORD dsPointerBetween( DWORD pointer, DWORD laterPointer, DWORD earlierPointer, DWORD bufferSize )
-{
- if ( pointer > bufferSize ) pointer -= bufferSize;
- if ( laterPointer < earlierPointer ) laterPointer += bufferSize;
- if ( pointer < earlierPointer ) pointer += bufferSize;
- return pointer >= earlierPointer && pointer < laterPointer;
-}
-
-// A structure to hold various information related to the DirectSound
-// API implementation.
-struct DsHandle {
- unsigned int drainCounter; // Tracks callback counts when draining
- bool internalDrain; // Indicates if stop is initiated from callback or not.
- void *id[2];
- void *buffer[2];
- bool xrun[2];
- UINT bufferPointer[2];
- DWORD dsBufferSize[2];
- DWORD dsPointerLeadTime[2]; // the number of bytes ahead of the safe pointer to lead by.
- HANDLE condition;
-
- DsHandle()
- :drainCounter(0), internalDrain(false) { id[0] = 0; id[1] = 0; buffer[0] = 0; buffer[1] = 0; xrun[0] = false; xrun[1] = false; bufferPointer[0] = 0; bufferPointer[1] = 0; }
-};
-
-// Declarations for utility functions, callbacks, and structures
-// specific to the DirectSound implementation.
-static BOOL CALLBACK deviceQueryCallback( LPGUID lpguid,
- LPCTSTR description,
- LPCTSTR module,
- LPVOID lpContext );
-
-static const char* getErrorString( int code );
-
-static unsigned __stdcall callbackHandler( void *ptr );
-
-struct DsDevice {
- LPGUID id[2];
- bool validId[2];
- bool found;
- std::string name;
-
- DsDevice()
- : found(false) { validId[0] = false; validId[1] = false; }
-};
-
-struct DsProbeData {
- bool isInput;
- std::vector<struct DsDevice>* dsDevices;
-};
-
-RtApiDs :: RtApiDs()
-{
- // Dsound will run both-threaded. If CoInitialize fails, then just
- // accept whatever the mainline chose for a threading model.
- coInitialized_ = false;
- HRESULT hr = CoInitialize( NULL );
- if ( !FAILED( hr ) ) coInitialized_ = true;
-}
-
-RtApiDs :: ~RtApiDs()
-{
- if ( coInitialized_ ) CoUninitialize(); // balanced call.
- if ( stream_.state != STREAM_CLOSED ) closeStream();
-}
-
-// The DirectSound default output is always the first device.
-unsigned int RtApiDs :: getDefaultOutputDevice( void )
-{
- return 0;
-}
-
-// The DirectSound default input is always the first input device,
-// which is the first capture device enumerated.
-unsigned int RtApiDs :: getDefaultInputDevice( void )
-{
- return 0;
-}
-
-unsigned int RtApiDs :: getDeviceCount( void )
-{
- // Set query flag for previously found devices to false, so that we
- // can check for any devices that have disappeared.
- for ( unsigned int i=0; i<dsDevices.size(); i++ )
- dsDevices[i].found = false;
-
- // Query DirectSound devices.
- struct DsProbeData probeInfo;
- probeInfo.isInput = false;
- probeInfo.dsDevices = &dsDevices;
- HRESULT result = DirectSoundEnumerate( (LPDSENUMCALLBACK) deviceQueryCallback, &probeInfo );
- if ( FAILED( result ) ) {
- errorStream_ << "RtApiDs::getDeviceCount: error (" << getErrorString( result ) << ") enumerating output devices!";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- }
-
- // Query DirectSoundCapture devices.
- probeInfo.isInput = true;
- result = DirectSoundCaptureEnumerate( (LPDSENUMCALLBACK) deviceQueryCallback, &probeInfo );
- if ( FAILED( result ) ) {
- errorStream_ << "RtApiDs::getDeviceCount: error (" << getErrorString( result ) << ") enumerating input devices!";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- }
-
- // Clean out any devices that may have disappeared (code update submitted by Eli Zehngut).
- for ( unsigned int i=0; i<dsDevices.size(); ) {
- if ( dsDevices[i].found == false ) dsDevices.erase( dsDevices.begin() + i );
- else i++;
- }
-
- return static_cast<unsigned int>(dsDevices.size());
-}
-
-RtAudio::DeviceInfo RtApiDs :: getDeviceInfo( unsigned int device )
-{
- RtAudio::DeviceInfo info;
- info.probed = false;
-
- if ( dsDevices.size() == 0 ) {
- // Force a query of all devices
- getDeviceCount();
- if ( dsDevices.size() == 0 ) {
- errorText_ = "RtApiDs::getDeviceInfo: no devices found!";
- error( RtAudioError::INVALID_USE );
- return info;
- }
- }
-
- if ( device >= dsDevices.size() ) {
- errorText_ = "RtApiDs::getDeviceInfo: device ID is invalid!";
- error( RtAudioError::INVALID_USE );
- return info;
- }
-
- HRESULT result;
- if ( dsDevices[ device ].validId[0] == false ) goto probeInput;
-
- LPDIRECTSOUND output;
- DSCAPS outCaps;
- result = DirectSoundCreate( dsDevices[ device ].id[0], &output, NULL );
- if ( FAILED( result ) ) {
- errorStream_ << "RtApiDs::getDeviceInfo: error (" << getErrorString( result ) << ") opening output device (" << dsDevices[ device ].name << ")!";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- goto probeInput;
- }
-
- outCaps.dwSize = sizeof( outCaps );
- result = output->GetCaps( &outCaps );
- if ( FAILED( result ) ) {
- output->Release();
- errorStream_ << "RtApiDs::getDeviceInfo: error (" << getErrorString( result ) << ") getting capabilities!";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- goto probeInput;
- }
-
- // Get output channel information.
- info.outputChannels = ( outCaps.dwFlags & DSCAPS_PRIMARYSTEREO ) ? 2 : 1;
-
- // Get sample rate information.
- info.sampleRates.clear();
- for ( unsigned int k=0; k<MAX_SAMPLE_RATES; k++ ) {
- if ( SAMPLE_RATES[k] >= (unsigned int) outCaps.dwMinSecondarySampleRate &&
- SAMPLE_RATES[k] <= (unsigned int) outCaps.dwMaxSecondarySampleRate ) {
- info.sampleRates.push_back( SAMPLE_RATES[k] );
-
- if ( !info.preferredSampleRate || ( SAMPLE_RATES[k] <= 48000 && SAMPLE_RATES[k] > info.preferredSampleRate ) )
- info.preferredSampleRate = SAMPLE_RATES[k];
- }
- }
-
- // Get format information.
- if ( outCaps.dwFlags & DSCAPS_PRIMARY16BIT ) info.nativeFormats |= RTAUDIO_SINT16;
- if ( outCaps.dwFlags & DSCAPS_PRIMARY8BIT ) info.nativeFormats |= RTAUDIO_SINT8;
-
- output->Release();
-
- if ( getDefaultOutputDevice() == device )
- info.isDefaultOutput = true;
-
- if ( dsDevices[ device ].validId[1] == false ) {
- info.name = dsDevices[ device ].name;
- info.probed = true;
- return info;
- }
-
- probeInput:
-
- LPDIRECTSOUNDCAPTURE input;
- result = DirectSoundCaptureCreate( dsDevices[ device ].id[1], &input, NULL );
- if ( FAILED( result ) ) {
- errorStream_ << "RtApiDs::getDeviceInfo: error (" << getErrorString( result ) << ") opening input device (" << dsDevices[ device ].name << ")!";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- return info;
- }
-
- DSCCAPS inCaps;
- inCaps.dwSize = sizeof( inCaps );
- result = input->GetCaps( &inCaps );
- if ( FAILED( result ) ) {
- input->Release();
- errorStream_ << "RtApiDs::getDeviceInfo: error (" << getErrorString( result ) << ") getting object capabilities (" << dsDevices[ device ].name << ")!";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- return info;
- }
-
- // Get input channel information.
- info.inputChannels = inCaps.dwChannels;
-
- // Get sample rate and format information.
- std::vector<unsigned int> rates;
- if ( inCaps.dwChannels >= 2 ) {
- if ( inCaps.dwFormats & WAVE_FORMAT_1S16 ) info.nativeFormats |= RTAUDIO_SINT16;
- if ( inCaps.dwFormats & WAVE_FORMAT_2S16 ) info.nativeFormats |= RTAUDIO_SINT16;
- if ( inCaps.dwFormats & WAVE_FORMAT_4S16 ) info.nativeFormats |= RTAUDIO_SINT16;
- if ( inCaps.dwFormats & WAVE_FORMAT_96S16 ) info.nativeFormats |= RTAUDIO_SINT16;
- if ( inCaps.dwFormats & WAVE_FORMAT_1S08 ) info.nativeFormats |= RTAUDIO_SINT8;
- if ( inCaps.dwFormats & WAVE_FORMAT_2S08 ) info.nativeFormats |= RTAUDIO_SINT8;
- if ( inCaps.dwFormats & WAVE_FORMAT_4S08 ) info.nativeFormats |= RTAUDIO_SINT8;
- if ( inCaps.dwFormats & WAVE_FORMAT_96S08 ) info.nativeFormats |= RTAUDIO_SINT8;
-
- if ( info.nativeFormats & RTAUDIO_SINT16 ) {
- if ( inCaps.dwFormats & WAVE_FORMAT_1S16 ) rates.push_back( 11025 );
- if ( inCaps.dwFormats & WAVE_FORMAT_2S16 ) rates.push_back( 22050 );
- if ( inCaps.dwFormats & WAVE_FORMAT_4S16 ) rates.push_back( 44100 );
- if ( inCaps.dwFormats & WAVE_FORMAT_96S16 ) rates.push_back( 96000 );
- }
- else if ( info.nativeFormats & RTAUDIO_SINT8 ) {
- if ( inCaps.dwFormats & WAVE_FORMAT_1S08 ) rates.push_back( 11025 );
- if ( inCaps.dwFormats & WAVE_FORMAT_2S08 ) rates.push_back( 22050 );
- if ( inCaps.dwFormats & WAVE_FORMAT_4S08 ) rates.push_back( 44100 );
- if ( inCaps.dwFormats & WAVE_FORMAT_96S08 ) rates.push_back( 96000 );
- }
- }
- else if ( inCaps.dwChannels == 1 ) {
- if ( inCaps.dwFormats & WAVE_FORMAT_1M16 ) info.nativeFormats |= RTAUDIO_SINT16;
- if ( inCaps.dwFormats & WAVE_FORMAT_2M16 ) info.nativeFormats |= RTAUDIO_SINT16;
- if ( inCaps.dwFormats & WAVE_FORMAT_4M16 ) info.nativeFormats |= RTAUDIO_SINT16;
- if ( inCaps.dwFormats & WAVE_FORMAT_96M16 ) info.nativeFormats |= RTAUDIO_SINT16;
- if ( inCaps.dwFormats & WAVE_FORMAT_1M08 ) info.nativeFormats |= RTAUDIO_SINT8;
- if ( inCaps.dwFormats & WAVE_FORMAT_2M08 ) info.nativeFormats |= RTAUDIO_SINT8;
- if ( inCaps.dwFormats & WAVE_FORMAT_4M08 ) info.nativeFormats |= RTAUDIO_SINT8;
- if ( inCaps.dwFormats & WAVE_FORMAT_96M08 ) info.nativeFormats |= RTAUDIO_SINT8;
-
- if ( info.nativeFormats & RTAUDIO_SINT16 ) {
- if ( inCaps.dwFormats & WAVE_FORMAT_1M16 ) rates.push_back( 11025 );
- if ( inCaps.dwFormats & WAVE_FORMAT_2M16 ) rates.push_back( 22050 );
- if ( inCaps.dwFormats & WAVE_FORMAT_4M16 ) rates.push_back( 44100 );
- if ( inCaps.dwFormats & WAVE_FORMAT_96M16 ) rates.push_back( 96000 );
- }
- else if ( info.nativeFormats & RTAUDIO_SINT8 ) {
- if ( inCaps.dwFormats & WAVE_FORMAT_1M08 ) rates.push_back( 11025 );
- if ( inCaps.dwFormats & WAVE_FORMAT_2M08 ) rates.push_back( 22050 );
- if ( inCaps.dwFormats & WAVE_FORMAT_4M08 ) rates.push_back( 44100 );
- if ( inCaps.dwFormats & WAVE_FORMAT_96M08 ) rates.push_back( 96000 );
- }
- }
- else info.inputChannels = 0; // technically, this would be an error
-
- input->Release();
-
- if ( info.inputChannels == 0 ) return info;
-
- // Copy the supported rates to the info structure but avoid duplication.
- bool found;
- for ( unsigned int i=0; i<rates.size(); i++ ) {
- found = false;
- for ( unsigned int j=0; j<info.sampleRates.size(); j++ ) {
- if ( rates[i] == info.sampleRates[j] ) {
- found = true;
- break;
- }
- }
- if ( found == false ) info.sampleRates.push_back( rates[i] );
- }
- std::sort( info.sampleRates.begin(), info.sampleRates.end() );
-
- // If device opens for both playback and capture, we determine the channels.
- if ( info.outputChannels > 0 && info.inputChannels > 0 )
- info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels;
-
- if ( device == 0 ) info.isDefaultInput = true;
-
- // Copy name and return.
- info.name = dsDevices[ device ].name;
- info.probed = true;
- return info;
-}
-
-bool RtApiDs :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,
- unsigned int firstChannel, unsigned int sampleRate,
- RtAudioFormat format, unsigned int *bufferSize,
- RtAudio::StreamOptions *options )
-{
- if ( channels + firstChannel > 2 ) {
- errorText_ = "RtApiDs::probeDeviceOpen: DirectSound does not support more than 2 channels per device.";
- return FAILURE;
- }
-
- size_t nDevices = dsDevices.size();
- if ( nDevices == 0 ) {
- // This should not happen because a check is made before this function is called.
- errorText_ = "RtApiDs::probeDeviceOpen: no devices found!";
- return FAILURE;
- }
-
- if ( device >= nDevices ) {
- // This should not happen because a check is made before this function is called.
- errorText_ = "RtApiDs::probeDeviceOpen: device ID is invalid!";
- return FAILURE;
- }
-
- if ( mode == OUTPUT ) {
- if ( dsDevices[ device ].validId[0] == false ) {
- errorStream_ << "RtApiDs::probeDeviceOpen: device (" << device << ") does not support output!";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
- }
- else { // mode == INPUT
- if ( dsDevices[ device ].validId[1] == false ) {
- errorStream_ << "RtApiDs::probeDeviceOpen: device (" << device << ") does not support input!";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
- }
-
- // According to a note in PortAudio, using GetDesktopWindow()
- // instead of GetForegroundWindow() is supposed to avoid problems
- // that occur when the application's window is not the foreground
- // window. Also, if the application window closes before the
- // DirectSound buffer, DirectSound can crash. In the past, I had
- // problems when using GetDesktopWindow() but it seems fine now
- // (January 2010). I'll leave it commented here.
- // HWND hWnd = GetForegroundWindow();
- HWND hWnd = GetDesktopWindow();
-
- // Check the numberOfBuffers parameter and limit the lowest value to
- // two. This is a judgement call and a value of two is probably too
- // low for capture, but it should work for playback.
- int nBuffers = 0;
- if ( options ) nBuffers = options->numberOfBuffers;
- if ( options && options->flags & RTAUDIO_MINIMIZE_LATENCY ) nBuffers = 2;
- if ( nBuffers < 2 ) nBuffers = 3;
-
- // Check the lower range of the user-specified buffer size and set
- // (arbitrarily) to a lower bound of 32.
- if ( *bufferSize < 32 ) *bufferSize = 32;
-
- // Create the wave format structure. The data format setting will
- // be determined later.
- WAVEFORMATEX waveFormat;
- ZeroMemory( &waveFormat, sizeof(WAVEFORMATEX) );
- waveFormat.wFormatTag = WAVE_FORMAT_PCM;
- waveFormat.nChannels = channels + firstChannel;
- waveFormat.nSamplesPerSec = (unsigned long) sampleRate;
-
- // Determine the device buffer size. By default, we'll use the value
- // defined above (32K), but we will grow it to make allowances for
- // very large software buffer sizes.
- DWORD dsBufferSize = MINIMUM_DEVICE_BUFFER_SIZE;
- DWORD dsPointerLeadTime = 0;
-
- void *ohandle = 0, *bhandle = 0;
- HRESULT result;
- if ( mode == OUTPUT ) {
-
- LPDIRECTSOUND output;
- result = DirectSoundCreate( dsDevices[ device ].id[0], &output, NULL );
- if ( FAILED( result ) ) {
- errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") opening output device (" << dsDevices[ device ].name << ")!";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- DSCAPS outCaps;
- outCaps.dwSize = sizeof( outCaps );
- result = output->GetCaps( &outCaps );
- if ( FAILED( result ) ) {
- output->Release();
- errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") getting capabilities (" << dsDevices[ device ].name << ")!";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- // Check channel information.
- if ( channels + firstChannel == 2 && !( outCaps.dwFlags & DSCAPS_PRIMARYSTEREO ) ) {
- errorStream_ << "RtApiDs::getDeviceInfo: the output device (" << dsDevices[ device ].name << ") does not support stereo playback.";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- // Check format information. Use 16-bit format unless not
- // supported or user requests 8-bit.
- if ( outCaps.dwFlags & DSCAPS_PRIMARY16BIT &&
- !( format == RTAUDIO_SINT8 && outCaps.dwFlags & DSCAPS_PRIMARY8BIT ) ) {
- waveFormat.wBitsPerSample = 16;
- stream_.deviceFormat[mode] = RTAUDIO_SINT16;
- }
- else {
- waveFormat.wBitsPerSample = 8;
- stream_.deviceFormat[mode] = RTAUDIO_SINT8;
- }
- stream_.userFormat = format;
-
- // Update wave format structure and buffer information.
- waveFormat.nBlockAlign = waveFormat.nChannels * waveFormat.wBitsPerSample / 8;
- waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;
- dsPointerLeadTime = nBuffers * (*bufferSize) * (waveFormat.wBitsPerSample / 8) * channels;
-
- // If the user wants an even bigger buffer, increase the device buffer size accordingly.
- while ( dsPointerLeadTime * 2U > dsBufferSize )
- dsBufferSize *= 2;
-
- // Set cooperative level to DSSCL_EXCLUSIVE ... sound stops when window focus changes.
- // result = output->SetCooperativeLevel( hWnd, DSSCL_EXCLUSIVE );
- // Set cooperative level to DSSCL_PRIORITY ... sound remains when window focus changes.
- result = output->SetCooperativeLevel( hWnd, DSSCL_PRIORITY );
- if ( FAILED( result ) ) {
- output->Release();
- errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") setting cooperative level (" << dsDevices[ device ].name << ")!";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- // Even though we will write to the secondary buffer, we need to
- // access the primary buffer to set the correct output format
- // (since the default is 8-bit, 22 kHz!). Setup the DS primary
- // buffer description.
- DSBUFFERDESC bufferDescription;
- ZeroMemory( &bufferDescription, sizeof( DSBUFFERDESC ) );
- bufferDescription.dwSize = sizeof( DSBUFFERDESC );
- bufferDescription.dwFlags = DSBCAPS_PRIMARYBUFFER;
-
- // Obtain the primary buffer
- LPDIRECTSOUNDBUFFER buffer;
- result = output->CreateSoundBuffer( &bufferDescription, &buffer, NULL );
- if ( FAILED( result ) ) {
- output->Release();
- errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") accessing primary buffer (" << dsDevices[ device ].name << ")!";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- // Set the primary DS buffer sound format.
- result = buffer->SetFormat( &waveFormat );
- if ( FAILED( result ) ) {
- output->Release();
- errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") setting primary buffer format (" << dsDevices[ device ].name << ")!";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- // Setup the secondary DS buffer description.
- ZeroMemory( &bufferDescription, sizeof( DSBUFFERDESC ) );
- bufferDescription.dwSize = sizeof( DSBUFFERDESC );
- bufferDescription.dwFlags = ( DSBCAPS_STICKYFOCUS |
- DSBCAPS_GLOBALFOCUS |
- DSBCAPS_GETCURRENTPOSITION2 |
- DSBCAPS_LOCHARDWARE ); // Force hardware mixing
- bufferDescription.dwBufferBytes = dsBufferSize;
- bufferDescription.lpwfxFormat = &waveFormat;
-
- // Try to create the secondary DS buffer. If that doesn't work,
- // try to use software mixing. Otherwise, there's a problem.
- result = output->CreateSoundBuffer( &bufferDescription, &buffer, NULL );
- if ( FAILED( result ) ) {
- bufferDescription.dwFlags = ( DSBCAPS_STICKYFOCUS |
- DSBCAPS_GLOBALFOCUS |
- DSBCAPS_GETCURRENTPOSITION2 |
- DSBCAPS_LOCSOFTWARE ); // Force software mixing
- result = output->CreateSoundBuffer( &bufferDescription, &buffer, NULL );
- if ( FAILED( result ) ) {
- output->Release();
- errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") creating secondary buffer (" << dsDevices[ device ].name << ")!";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
- }
-
- // Get the buffer size ... might be different from what we specified.
- DSBCAPS dsbcaps;
- dsbcaps.dwSize = sizeof( DSBCAPS );
- result = buffer->GetCaps( &dsbcaps );
- if ( FAILED( result ) ) {
- output->Release();
- buffer->Release();
- errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") getting buffer settings (" << dsDevices[ device ].name << ")!";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- dsBufferSize = dsbcaps.dwBufferBytes;
-
- // Lock the DS buffer
- LPVOID audioPtr;
- DWORD dataLen;
- result = buffer->Lock( 0, dsBufferSize, &audioPtr, &dataLen, NULL, NULL, 0 );
- if ( FAILED( result ) ) {
- output->Release();
- buffer->Release();
- errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") locking buffer (" << dsDevices[ device ].name << ")!";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- // Zero the DS buffer
- ZeroMemory( audioPtr, dataLen );
-
- // Unlock the DS buffer
- result = buffer->Unlock( audioPtr, dataLen, NULL, 0 );
- if ( FAILED( result ) ) {
- output->Release();
- buffer->Release();
- errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") unlocking buffer (" << dsDevices[ device ].name << ")!";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- ohandle = (void *) output;
- bhandle = (void *) buffer;
- }
-
- if ( mode == INPUT ) {
-
- LPDIRECTSOUNDCAPTURE input;
- result = DirectSoundCaptureCreate( dsDevices[ device ].id[1], &input, NULL );
- if ( FAILED( result ) ) {
- errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") opening input device (" << dsDevices[ device ].name << ")!";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- DSCCAPS inCaps;
- inCaps.dwSize = sizeof( inCaps );
- result = input->GetCaps( &inCaps );
- if ( FAILED( result ) ) {
- input->Release();
- errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") getting input capabilities (" << dsDevices[ device ].name << ")!";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- // Check channel information.
- if ( inCaps.dwChannels < channels + firstChannel ) {
- errorText_ = "RtApiDs::getDeviceInfo: the input device does not support requested input channels.";
- return FAILURE;
- }
-
- // Check format information. Use 16-bit format unless user
- // requests 8-bit.
- DWORD deviceFormats;
- if ( channels + firstChannel == 2 ) {
- deviceFormats = WAVE_FORMAT_1S08 | WAVE_FORMAT_2S08 | WAVE_FORMAT_4S08 | WAVE_FORMAT_96S08;
- if ( format == RTAUDIO_SINT8 && inCaps.dwFormats & deviceFormats ) {
- waveFormat.wBitsPerSample = 8;
- stream_.deviceFormat[mode] = RTAUDIO_SINT8;
- }
- else { // assume 16-bit is supported
- waveFormat.wBitsPerSample = 16;
- stream_.deviceFormat[mode] = RTAUDIO_SINT16;
- }
- }
- else { // channel == 1
- deviceFormats = WAVE_FORMAT_1M08 | WAVE_FORMAT_2M08 | WAVE_FORMAT_4M08 | WAVE_FORMAT_96M08;
- if ( format == RTAUDIO_SINT8 && inCaps.dwFormats & deviceFormats ) {
- waveFormat.wBitsPerSample = 8;
- stream_.deviceFormat[mode] = RTAUDIO_SINT8;
- }
- else { // assume 16-bit is supported
- waveFormat.wBitsPerSample = 16;
- stream_.deviceFormat[mode] = RTAUDIO_SINT16;
- }
- }
- stream_.userFormat = format;
-
- // Update wave format structure and buffer information.
- waveFormat.nBlockAlign = waveFormat.nChannels * waveFormat.wBitsPerSample / 8;
- waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;
- dsPointerLeadTime = nBuffers * (*bufferSize) * (waveFormat.wBitsPerSample / 8) * channels;
-
- // If the user wants an even bigger buffer, increase the device buffer size accordingly.
- while ( dsPointerLeadTime * 2U > dsBufferSize )
- dsBufferSize *= 2;
-
- // Setup the secondary DS buffer description.
- DSCBUFFERDESC bufferDescription;
- ZeroMemory( &bufferDescription, sizeof( DSCBUFFERDESC ) );
- bufferDescription.dwSize = sizeof( DSCBUFFERDESC );
- bufferDescription.dwFlags = 0;
- bufferDescription.dwReserved = 0;
- bufferDescription.dwBufferBytes = dsBufferSize;
- bufferDescription.lpwfxFormat = &waveFormat;
-
- // Create the capture buffer.
- LPDIRECTSOUNDCAPTUREBUFFER buffer;
- result = input->CreateCaptureBuffer( &bufferDescription, &buffer, NULL );
- if ( FAILED( result ) ) {
- input->Release();
- errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") creating input buffer (" << dsDevices[ device ].name << ")!";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- // Get the buffer size ... might be different from what we specified.
- DSCBCAPS dscbcaps;
- dscbcaps.dwSize = sizeof( DSCBCAPS );
- result = buffer->GetCaps( &dscbcaps );
- if ( FAILED( result ) ) {
- input->Release();
- buffer->Release();
- errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") getting buffer settings (" << dsDevices[ device ].name << ")!";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- dsBufferSize = dscbcaps.dwBufferBytes;
-
- // NOTE: We could have a problem here if this is a duplex stream
- // and the play and capture hardware buffer sizes are different
- // (I'm actually not sure if that is a problem or not).
- // Currently, we are not verifying that.
-
- // Lock the capture buffer
- LPVOID audioPtr;
- DWORD dataLen;
- result = buffer->Lock( 0, dsBufferSize, &audioPtr, &dataLen, NULL, NULL, 0 );
- if ( FAILED( result ) ) {
- input->Release();
- buffer->Release();
- errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") locking input buffer (" << dsDevices[ device ].name << ")!";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- // Zero the buffer
- ZeroMemory( audioPtr, dataLen );
-
- // Unlock the buffer
- result = buffer->Unlock( audioPtr, dataLen, NULL, 0 );
- if ( FAILED( result ) ) {
- input->Release();
- buffer->Release();
- errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") unlocking input buffer (" << dsDevices[ device ].name << ")!";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- ohandle = (void *) input;
- bhandle = (void *) buffer;
- }
-
- // Set various stream parameters
- DsHandle *handle = 0;
- stream_.nDeviceChannels[mode] = channels + firstChannel;
- stream_.nUserChannels[mode] = channels;
- stream_.bufferSize = *bufferSize;
- stream_.channelOffset[mode] = firstChannel;
- stream_.deviceInterleaved[mode] = true;
- if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) stream_.userInterleaved = false;
- else stream_.userInterleaved = true;
-
- // Set flag for buffer conversion
- stream_.doConvertBuffer[mode] = false;
- if (stream_.nUserChannels[mode] != stream_.nDeviceChannels[mode])
- stream_.doConvertBuffer[mode] = true;
- if (stream_.userFormat != stream_.deviceFormat[mode])
- stream_.doConvertBuffer[mode] = true;
- if ( stream_.userInterleaved != stream_.deviceInterleaved[mode] &&
- stream_.nUserChannels[mode] > 1 )
- stream_.doConvertBuffer[mode] = true;
-
- // Allocate necessary internal buffers
- long bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat );
- stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 );
- if ( stream_.userBuffer[mode] == NULL ) {
- errorText_ = "RtApiDs::probeDeviceOpen: error allocating user buffer memory.";
- goto error;
- }
-
- if ( stream_.doConvertBuffer[mode] ) {
-
- bool makeBuffer = true;
- bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] );
- if ( mode == INPUT ) {
- if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) {
- unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] );
- if ( bufferBytes <= (long) bytesOut ) makeBuffer = false;
- }
- }
-
- if ( makeBuffer ) {
- bufferBytes *= *bufferSize;
- if ( stream_.deviceBuffer ) free( stream_.deviceBuffer );
- stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 );
- if ( stream_.deviceBuffer == NULL ) {
- errorText_ = "RtApiDs::probeDeviceOpen: error allocating device buffer memory.";
- goto error;
- }
- }
- }
-
- // Allocate our DsHandle structures for the stream.
- if ( stream_.apiHandle == 0 ) {
- try {
- handle = new DsHandle;
- }
- catch ( std::bad_alloc& ) {
- errorText_ = "RtApiDs::probeDeviceOpen: error allocating AsioHandle memory.";
- goto error;
- }
-
- // Create a manual-reset event.
- handle->condition = CreateEvent( NULL, // no security
- TRUE, // manual-reset
- FALSE, // non-signaled initially
- NULL ); // unnamed
- stream_.apiHandle = (void *) handle;
- }
- else
- handle = (DsHandle *) stream_.apiHandle;
- handle->id[mode] = ohandle;
- handle->buffer[mode] = bhandle;
- handle->dsBufferSize[mode] = dsBufferSize;
- handle->dsPointerLeadTime[mode] = dsPointerLeadTime;
-
- stream_.device[mode] = device;
- stream_.state = STREAM_STOPPED;
- if ( stream_.mode == OUTPUT && mode == INPUT )
- // We had already set up an output stream.
- stream_.mode = DUPLEX;
- else
- stream_.mode = mode;
- stream_.nBuffers = nBuffers;
- stream_.sampleRate = sampleRate;
-
- // Setup the buffer conversion information structure.
- if ( stream_.doConvertBuffer[mode] ) setConvertInfo( mode, firstChannel );
-
- // Setup the callback thread.
- if ( stream_.callbackInfo.isRunning == false ) {
- unsigned threadId;
- stream_.callbackInfo.isRunning = true;
- stream_.callbackInfo.object = (void *) this;
- stream_.callbackInfo.thread = _beginthreadex( NULL, 0, &callbackHandler,
- &stream_.callbackInfo, 0, &threadId );
- if ( stream_.callbackInfo.thread == 0 ) {
- errorText_ = "RtApiDs::probeDeviceOpen: error creating callback thread!";
- goto error;
- }
-
- // Boost DS thread priority
- SetThreadPriority( (HANDLE) stream_.callbackInfo.thread, THREAD_PRIORITY_HIGHEST );
- }
- return SUCCESS;
-
- error:
- if ( handle ) {
- if ( handle->buffer[0] ) { // the object pointer can be NULL and valid
- LPDIRECTSOUND object = (LPDIRECTSOUND) handle->id[0];
- LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0];
- if ( buffer ) buffer->Release();
- object->Release();
- }
- if ( handle->buffer[1] ) {
- LPDIRECTSOUNDCAPTURE object = (LPDIRECTSOUNDCAPTURE) handle->id[1];
- LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) handle->buffer[1];
- if ( buffer ) buffer->Release();
- object->Release();
- }
- CloseHandle( handle->condition );
- delete handle;
- stream_.apiHandle = 0;
- }
-
- for ( int i=0; i<2; i++ ) {
- if ( stream_.userBuffer[i] ) {
- free( stream_.userBuffer[i] );
- stream_.userBuffer[i] = 0;
- }
- }
-
- if ( stream_.deviceBuffer ) {
- free( stream_.deviceBuffer );
- stream_.deviceBuffer = 0;
- }
-
- stream_.state = STREAM_CLOSED;
- return FAILURE;
-}
-
-void RtApiDs :: closeStream()
-{
- if ( stream_.state == STREAM_CLOSED ) {
- errorText_ = "RtApiDs::closeStream(): no open stream to close!";
- error( RtAudioError::WARNING );
- return;
- }
-
- // Stop the callback thread.
- stream_.callbackInfo.isRunning = false;
- WaitForSingleObject( (HANDLE) stream_.callbackInfo.thread, INFINITE );
- CloseHandle( (HANDLE) stream_.callbackInfo.thread );
-
- DsHandle *handle = (DsHandle *) stream_.apiHandle;
- if ( handle ) {
- if ( handle->buffer[0] ) { // the object pointer can be NULL and valid
- LPDIRECTSOUND object = (LPDIRECTSOUND) handle->id[0];
- LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0];
- if ( buffer ) {
- buffer->Stop();
- buffer->Release();
- }
- object->Release();
- }
- if ( handle->buffer[1] ) {
- LPDIRECTSOUNDCAPTURE object = (LPDIRECTSOUNDCAPTURE) handle->id[1];
- LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) handle->buffer[1];
- if ( buffer ) {
- buffer->Stop();
- buffer->Release();
- }
- object->Release();
- }
- CloseHandle( handle->condition );
- delete handle;
- stream_.apiHandle = 0;
- }
-
- for ( int i=0; i<2; i++ ) {
- if ( stream_.userBuffer[i] ) {
- free( stream_.userBuffer[i] );
- stream_.userBuffer[i] = 0;
- }
- }
-
- if ( stream_.deviceBuffer ) {
- free( stream_.deviceBuffer );
- stream_.deviceBuffer = 0;
- }
-
- stream_.mode = UNINITIALIZED;
- stream_.state = STREAM_CLOSED;
-}
-
-void RtApiDs :: startStream()
-{
- verifyStream();
- if ( stream_.state == STREAM_RUNNING ) {
- errorText_ = "RtApiDs::startStream(): the stream is already running!";
- error( RtAudioError::WARNING );
- return;
- }
-
- DsHandle *handle = (DsHandle *) stream_.apiHandle;
-
- // Increase scheduler frequency on lesser windows (a side-effect of
- // increasing timer accuracy). On greater windows (Win2K or later),
- // this is already in effect.
- timeBeginPeriod( 1 );
-
- buffersRolling = false;
- duplexPrerollBytes = 0;
-
- if ( stream_.mode == DUPLEX ) {
- // 0.5 seconds of silence in DUPLEX mode while the devices spin up and synchronize.
- duplexPrerollBytes = (int) ( 0.5 * stream_.sampleRate * formatBytes( stream_.deviceFormat[1] ) * stream_.nDeviceChannels[1] );
- }
-
- HRESULT result = 0;
- if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
-
- LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0];
- result = buffer->Play( 0, 0, DSBPLAY_LOOPING );
- if ( FAILED( result ) ) {
- errorStream_ << "RtApiDs::startStream: error (" << getErrorString( result ) << ") starting output buffer!";
- errorText_ = errorStream_.str();
- goto unlock;
- }
- }
-
- if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) {
-
- LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) handle->buffer[1];
- result = buffer->Start( DSCBSTART_LOOPING );
- if ( FAILED( result ) ) {
- errorStream_ << "RtApiDs::startStream: error (" << getErrorString( result ) << ") starting input buffer!";
- errorText_ = errorStream_.str();
- goto unlock;
- }
- }
-
- handle->drainCounter = 0;
- handle->internalDrain = false;
- ResetEvent( handle->condition );
- stream_.state = STREAM_RUNNING;
-
- unlock:
- if ( FAILED( result ) ) error( RtAudioError::SYSTEM_ERROR );
-}
-
-void RtApiDs :: stopStream()
-{
- verifyStream();
- if ( stream_.state == STREAM_STOPPED ) {
- errorText_ = "RtApiDs::stopStream(): the stream is already stopped!";
- error( RtAudioError::WARNING );
- return;
- }
-
- HRESULT result = 0;
- LPVOID audioPtr;
- DWORD dataLen;
- DsHandle *handle = (DsHandle *) stream_.apiHandle;
- if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
- if ( handle->drainCounter == 0 ) {
- handle->drainCounter = 2;
- WaitForSingleObject( handle->condition, INFINITE ); // block until signaled
- }
-
- stream_.state = STREAM_STOPPED;
-
- MUTEX_LOCK( &stream_.mutex );
-
- // Stop the buffer and clear memory
- LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0];
- result = buffer->Stop();
- if ( FAILED( result ) ) {
- errorStream_ << "RtApiDs::stopStream: error (" << getErrorString( result ) << ") stopping output buffer!";
- errorText_ = errorStream_.str();
- goto unlock;
- }
-
- // Lock the buffer and clear it so that if we start to play again,
- // we won't have old data playing.
- result = buffer->Lock( 0, handle->dsBufferSize[0], &audioPtr, &dataLen, NULL, NULL, 0 );
- if ( FAILED( result ) ) {
- errorStream_ << "RtApiDs::stopStream: error (" << getErrorString( result ) << ") locking output buffer!";
- errorText_ = errorStream_.str();
- goto unlock;
- }
-
- // Zero the DS buffer
- ZeroMemory( audioPtr, dataLen );
-
- // Unlock the DS buffer
- result = buffer->Unlock( audioPtr, dataLen, NULL, 0 );
- if ( FAILED( result ) ) {
- errorStream_ << "RtApiDs::stopStream: error (" << getErrorString( result ) << ") unlocking output buffer!";
- errorText_ = errorStream_.str();
- goto unlock;
- }
-
- // If we start playing again, we must begin at beginning of buffer.
- handle->bufferPointer[0] = 0;
- }
-
- if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) {
- LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) handle->buffer[1];
- audioPtr = NULL;
- dataLen = 0;
-
- stream_.state = STREAM_STOPPED;
-
- if ( stream_.mode != DUPLEX )
- MUTEX_LOCK( &stream_.mutex );
-
- result = buffer->Stop();
- if ( FAILED( result ) ) {
- errorStream_ << "RtApiDs::stopStream: error (" << getErrorString( result ) << ") stopping input buffer!";
- errorText_ = errorStream_.str();
- goto unlock;
- }
-
- // Lock the buffer and clear it so that if we start to play again,
- // we won't have old data playing.
- result = buffer->Lock( 0, handle->dsBufferSize[1], &audioPtr, &dataLen, NULL, NULL, 0 );
- if ( FAILED( result ) ) {
- errorStream_ << "RtApiDs::stopStream: error (" << getErrorString( result ) << ") locking input buffer!";
- errorText_ = errorStream_.str();
- goto unlock;
- }
-
- // Zero the DS buffer
- ZeroMemory( audioPtr, dataLen );
-
- // Unlock the DS buffer
- result = buffer->Unlock( audioPtr, dataLen, NULL, 0 );
- if ( FAILED( result ) ) {
- errorStream_ << "RtApiDs::stopStream: error (" << getErrorString( result ) << ") unlocking input buffer!";
- errorText_ = errorStream_.str();
- goto unlock;
- }
-
- // If we start recording again, we must begin at beginning of buffer.
- handle->bufferPointer[1] = 0;
- }
-
- unlock:
- timeEndPeriod( 1 ); // revert to normal scheduler frequency on lesser windows.
- MUTEX_UNLOCK( &stream_.mutex );
-
- if ( FAILED( result ) ) error( RtAudioError::SYSTEM_ERROR );
-}
-
-void RtApiDs :: abortStream()
-{
- verifyStream();
- if ( stream_.state == STREAM_STOPPED ) {
- errorText_ = "RtApiDs::abortStream(): the stream is already stopped!";
- error( RtAudioError::WARNING );
- return;
- }
-
- DsHandle *handle = (DsHandle *) stream_.apiHandle;
- handle->drainCounter = 2;
-
- stopStream();
-}
-
-void RtApiDs :: callbackEvent()
-{
- if ( stream_.state == STREAM_STOPPED || stream_.state == STREAM_STOPPING ) {
- Sleep( 50 ); // sleep 50 milliseconds
- return;
- }
-
- if ( stream_.state == STREAM_CLOSED ) {
- errorText_ = "RtApiDs::callbackEvent(): the stream is closed ... this shouldn't happen!";
- error( RtAudioError::WARNING );
- return;
- }
-
- CallbackInfo *info = (CallbackInfo *) &stream_.callbackInfo;
- DsHandle *handle = (DsHandle *) stream_.apiHandle;
-
- // Check if we were draining the stream and signal is finished.
- if ( handle->drainCounter > stream_.nBuffers + 2 ) {
-
- stream_.state = STREAM_STOPPING;
- if ( handle->internalDrain == false )
- SetEvent( handle->condition );
- else
- stopStream();
- return;
- }
-
- // Invoke user callback to get fresh output data UNLESS we are
- // draining stream.
- if ( handle->drainCounter == 0 ) {
- RtAudioCallback callback = (RtAudioCallback) info->callback;
- double streamTime = getStreamTime();
- RtAudioStreamStatus status = 0;
- if ( stream_.mode != INPUT && handle->xrun[0] == true ) {
- status |= RTAUDIO_OUTPUT_UNDERFLOW;
- handle->xrun[0] = false;
- }
- if ( stream_.mode != OUTPUT && handle->xrun[1] == true ) {
- status |= RTAUDIO_INPUT_OVERFLOW;
- handle->xrun[1] = false;
- }
- int cbReturnValue = callback( stream_.userBuffer[0], stream_.userBuffer[1],
- stream_.bufferSize, streamTime, status, info->userData );
- if ( cbReturnValue == 2 ) {
- stream_.state = STREAM_STOPPING;
- handle->drainCounter = 2;
- abortStream();
- return;
- }
- else if ( cbReturnValue == 1 ) {
- handle->drainCounter = 1;
- handle->internalDrain = true;
- }
- }
-
- HRESULT result;
- DWORD currentWritePointer, safeWritePointer;
- DWORD currentReadPointer, safeReadPointer;
- UINT nextWritePointer;
-
- LPVOID buffer1 = NULL;
- LPVOID buffer2 = NULL;
- DWORD bufferSize1 = 0;
- DWORD bufferSize2 = 0;
-
- char *buffer;
- long bufferBytes;
-
- MUTEX_LOCK( &stream_.mutex );
- if ( stream_.state == STREAM_STOPPED ) {
- MUTEX_UNLOCK( &stream_.mutex );
- return;
- }
-
- if ( buffersRolling == false ) {
- if ( stream_.mode == DUPLEX ) {
- //assert( handle->dsBufferSize[0] == handle->dsBufferSize[1] );
-
- // It takes a while for the devices to get rolling. As a result,
- // there's no guarantee that the capture and write device pointers
- // will move in lockstep. Wait here for both devices to start
- // rolling, and then set our buffer pointers accordingly.
- // e.g. Crystal Drivers: the capture buffer starts up 5700 to 9600
- // bytes later than the write buffer.
-
- // Stub: a serious risk of having a pre-emptive scheduling round
- // take place between the two GetCurrentPosition calls... but I'm
- // really not sure how to solve the problem. Temporarily boost to
- // Realtime priority, maybe; but I'm not sure what priority the
- // DirectSound service threads run at. We *should* be roughly
- // within a ms or so of correct.
-
- LPDIRECTSOUNDBUFFER dsWriteBuffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0];
- LPDIRECTSOUNDCAPTUREBUFFER dsCaptureBuffer = (LPDIRECTSOUNDCAPTUREBUFFER) handle->buffer[1];
-
- DWORD startSafeWritePointer, startSafeReadPointer;
-
- result = dsWriteBuffer->GetCurrentPosition( NULL, &startSafeWritePointer );
- if ( FAILED( result ) ) {
- errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current write position!";
- errorText_ = errorStream_.str();
- MUTEX_UNLOCK( &stream_.mutex );
- error( RtAudioError::SYSTEM_ERROR );
- return;
- }
- result = dsCaptureBuffer->GetCurrentPosition( NULL, &startSafeReadPointer );
- if ( FAILED( result ) ) {
- errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current read position!";
- errorText_ = errorStream_.str();
- MUTEX_UNLOCK( &stream_.mutex );
- error( RtAudioError::SYSTEM_ERROR );
- return;
- }
- while ( true ) {
- result = dsWriteBuffer->GetCurrentPosition( NULL, &safeWritePointer );
- if ( FAILED( result ) ) {
- errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current write position!";
- errorText_ = errorStream_.str();
- MUTEX_UNLOCK( &stream_.mutex );
- error( RtAudioError::SYSTEM_ERROR );
- return;
- }
- result = dsCaptureBuffer->GetCurrentPosition( NULL, &safeReadPointer );
- if ( FAILED( result ) ) {
- errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current read position!";
- errorText_ = errorStream_.str();
- MUTEX_UNLOCK( &stream_.mutex );
- error( RtAudioError::SYSTEM_ERROR );
- return;
- }
- if ( safeWritePointer != startSafeWritePointer && safeReadPointer != startSafeReadPointer ) break;
- Sleep( 1 );
- }
-
- //assert( handle->dsBufferSize[0] == handle->dsBufferSize[1] );
-
- handle->bufferPointer[0] = safeWritePointer + handle->dsPointerLeadTime[0];
- if ( handle->bufferPointer[0] >= handle->dsBufferSize[0] ) handle->bufferPointer[0] -= handle->dsBufferSize[0];
- handle->bufferPointer[1] = safeReadPointer;
- }
- else if ( stream_.mode == OUTPUT ) {
-
- // Set the proper nextWritePosition after initial startup.
- LPDIRECTSOUNDBUFFER dsWriteBuffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0];
- result = dsWriteBuffer->GetCurrentPosition( &currentWritePointer, &safeWritePointer );
- if ( FAILED( result ) ) {
- errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current write position!";
- errorText_ = errorStream_.str();
- MUTEX_UNLOCK( &stream_.mutex );
- error( RtAudioError::SYSTEM_ERROR );
- return;
- }
- handle->bufferPointer[0] = safeWritePointer + handle->dsPointerLeadTime[0];
- if ( handle->bufferPointer[0] >= handle->dsBufferSize[0] ) handle->bufferPointer[0] -= handle->dsBufferSize[0];
- }
-
- buffersRolling = true;
- }
-
- if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
-
- LPDIRECTSOUNDBUFFER dsBuffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0];
-
- if ( handle->drainCounter > 1 ) { // write zeros to the output stream
- bufferBytes = stream_.bufferSize * stream_.nUserChannels[0];
- bufferBytes *= formatBytes( stream_.userFormat );
- memset( stream_.userBuffer[0], 0, bufferBytes );
- }
-
- // Setup parameters and do buffer conversion if necessary.
- if ( stream_.doConvertBuffer[0] ) {
- buffer = stream_.deviceBuffer;
- convertBuffer( buffer, stream_.userBuffer[0], stream_.convertInfo[0] );
- bufferBytes = stream_.bufferSize * stream_.nDeviceChannels[0];
- bufferBytes *= formatBytes( stream_.deviceFormat[0] );
- }
- else {
- buffer = stream_.userBuffer[0];
- bufferBytes = stream_.bufferSize * stream_.nUserChannels[0];
- bufferBytes *= formatBytes( stream_.userFormat );
- }
-
- // No byte swapping necessary in DirectSound implementation.
-
- // Ahhh ... windoze. 16-bit data is signed but 8-bit data is
- // unsigned. So, we need to convert our signed 8-bit data here to
- // unsigned.
- if ( stream_.deviceFormat[0] == RTAUDIO_SINT8 )
- for ( int i=0; i<bufferBytes; i++ ) buffer[i] = (unsigned char) ( buffer[i] + 128 );
-
- DWORD dsBufferSize = handle->dsBufferSize[0];
- nextWritePointer = handle->bufferPointer[0];
-
- DWORD endWrite, leadPointer;
- while ( true ) {
- // Find out where the read and "safe write" pointers are.
- result = dsBuffer->GetCurrentPosition( &currentWritePointer, &safeWritePointer );
- if ( FAILED( result ) ) {
- errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current write position!";
- errorText_ = errorStream_.str();
- MUTEX_UNLOCK( &stream_.mutex );
- error( RtAudioError::SYSTEM_ERROR );
- return;
- }
-
- // We will copy our output buffer into the region between
- // safeWritePointer and leadPointer. If leadPointer is not
- // beyond the next endWrite position, wait until it is.
- leadPointer = safeWritePointer + handle->dsPointerLeadTime[0];
- //std::cout << "safeWritePointer = " << safeWritePointer << ", leadPointer = " << leadPointer << ", nextWritePointer = " << nextWritePointer << std::endl;
- if ( leadPointer > dsBufferSize ) leadPointer -= dsBufferSize;
- if ( leadPointer < nextWritePointer ) leadPointer += dsBufferSize; // unwrap offset
- endWrite = nextWritePointer + bufferBytes;
-
- // Check whether the entire write region is behind the play pointer.
- if ( leadPointer >= endWrite ) break;
-
- // If we are here, then we must wait until the leadPointer advances
- // beyond the end of our next write region. We use the
- // Sleep() function to suspend operation until that happens.
- double millis = ( endWrite - leadPointer ) * 1000.0;
- millis /= ( formatBytes( stream_.deviceFormat[0]) * stream_.nDeviceChannels[0] * stream_.sampleRate);
- if ( millis < 1.0 ) millis = 1.0;
- Sleep( (DWORD) millis );
- }
-
- if ( dsPointerBetween( nextWritePointer, safeWritePointer, currentWritePointer, dsBufferSize )
- || dsPointerBetween( endWrite, safeWritePointer, currentWritePointer, dsBufferSize ) ) {
- // We've strayed into the forbidden zone ... resync the read pointer.
- handle->xrun[0] = true;
- nextWritePointer = safeWritePointer + handle->dsPointerLeadTime[0] - bufferBytes;
- if ( nextWritePointer >= dsBufferSize ) nextWritePointer -= dsBufferSize;
- handle->bufferPointer[0] = nextWritePointer;
- endWrite = nextWritePointer + bufferBytes;
- }
-
- // Lock free space in the buffer
- result = dsBuffer->Lock( nextWritePointer, bufferBytes, &buffer1,
- &bufferSize1, &buffer2, &bufferSize2, 0 );
- if ( FAILED( result ) ) {
- errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") locking buffer during playback!";
- errorText_ = errorStream_.str();
- MUTEX_UNLOCK( &stream_.mutex );
- error( RtAudioError::SYSTEM_ERROR );
- return;
- }
-
- // Copy our buffer into the DS buffer
- CopyMemory( buffer1, buffer, bufferSize1 );
- if ( buffer2 != NULL ) CopyMemory( buffer2, buffer+bufferSize1, bufferSize2 );
-
- // Update our buffer offset and unlock sound buffer
- dsBuffer->Unlock( buffer1, bufferSize1, buffer2, bufferSize2 );
- if ( FAILED( result ) ) {
- errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") unlocking buffer during playback!";
- errorText_ = errorStream_.str();
- MUTEX_UNLOCK( &stream_.mutex );
- error( RtAudioError::SYSTEM_ERROR );
- return;
- }
- nextWritePointer = ( nextWritePointer + bufferSize1 + bufferSize2 ) % dsBufferSize;
- handle->bufferPointer[0] = nextWritePointer;
- }
-
- // Don't bother draining input
- if ( handle->drainCounter ) {
- handle->drainCounter++;
- goto unlock;
- }
-
- if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) {
-
- // Setup parameters.
- if ( stream_.doConvertBuffer[1] ) {
- buffer = stream_.deviceBuffer;
- bufferBytes = stream_.bufferSize * stream_.nDeviceChannels[1];
- bufferBytes *= formatBytes( stream_.deviceFormat[1] );
- }
- else {
- buffer = stream_.userBuffer[1];
- bufferBytes = stream_.bufferSize * stream_.nUserChannels[1];
- bufferBytes *= formatBytes( stream_.userFormat );
- }
-
- LPDIRECTSOUNDCAPTUREBUFFER dsBuffer = (LPDIRECTSOUNDCAPTUREBUFFER) handle->buffer[1];
- long nextReadPointer = handle->bufferPointer[1];
- DWORD dsBufferSize = handle->dsBufferSize[1];
-
- // Find out where the write and "safe read" pointers are.
- result = dsBuffer->GetCurrentPosition( &currentReadPointer, &safeReadPointer );
- if ( FAILED( result ) ) {
- errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current read position!";
- errorText_ = errorStream_.str();
- MUTEX_UNLOCK( &stream_.mutex );
- error( RtAudioError::SYSTEM_ERROR );
- return;
- }
-
- if ( safeReadPointer < (DWORD)nextReadPointer ) safeReadPointer += dsBufferSize; // unwrap offset
- DWORD endRead = nextReadPointer + bufferBytes;
-
- // Handling depends on whether we are INPUT or DUPLEX.
- // If we're in INPUT mode then waiting is a good thing. If we're in DUPLEX mode,
- // then a wait here will drag the write pointers into the forbidden zone.
- //
- // In DUPLEX mode, rather than wait, we will back off the read pointer until
- // it's in a safe position. This causes dropouts, but it seems to be the only
- // practical way to sync up the read and write pointers reliably, given the
- // the very complex relationship between phase and increment of the read and write
- // pointers.
- //
- // In order to minimize audible dropouts in DUPLEX mode, we will
- // provide a pre-roll period of 0.5 seconds in which we return
- // zeros from the read buffer while the pointers sync up.
-
- if ( stream_.mode == DUPLEX ) {
- if ( safeReadPointer < endRead ) {
- if ( duplexPrerollBytes <= 0 ) {
- // Pre-roll time over. Be more agressive.
- int adjustment = endRead-safeReadPointer;
-
- handle->xrun[1] = true;
- // Two cases:
- // - large adjustments: we've probably run out of CPU cycles, so just resync exactly,
- // and perform fine adjustments later.
- // - small adjustments: back off by twice as much.
- if ( adjustment >= 2*bufferBytes )
- nextReadPointer = safeReadPointer-2*bufferBytes;
- else
- nextReadPointer = safeReadPointer-bufferBytes-adjustment;
-
- if ( nextReadPointer < 0 ) nextReadPointer += dsBufferSize;
-
- }
- else {
- // In pre=roll time. Just do it.
- nextReadPointer = safeReadPointer - bufferBytes;
- while ( nextReadPointer < 0 ) nextReadPointer += dsBufferSize;
- }
- endRead = nextReadPointer + bufferBytes;
- }
- }
- else { // mode == INPUT
- while ( safeReadPointer < endRead && stream_.callbackInfo.isRunning ) {
- // See comments for playback.
- double millis = (endRead - safeReadPointer) * 1000.0;
- millis /= ( formatBytes(stream_.deviceFormat[1]) * stream_.nDeviceChannels[1] * stream_.sampleRate);
- if ( millis < 1.0 ) millis = 1.0;
- Sleep( (DWORD) millis );
-
- // Wake up and find out where we are now.
- result = dsBuffer->GetCurrentPosition( &currentReadPointer, &safeReadPointer );
- if ( FAILED( result ) ) {
- errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current read position!";
- errorText_ = errorStream_.str();
- MUTEX_UNLOCK( &stream_.mutex );
- error( RtAudioError::SYSTEM_ERROR );
- return;
- }
-
- if ( safeReadPointer < (DWORD)nextReadPointer ) safeReadPointer += dsBufferSize; // unwrap offset
- }
- }
-
- // Lock free space in the buffer
- result = dsBuffer->Lock( nextReadPointer, bufferBytes, &buffer1,
- &bufferSize1, &buffer2, &bufferSize2, 0 );
- if ( FAILED( result ) ) {
- errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") locking capture buffer!";
- errorText_ = errorStream_.str();
- MUTEX_UNLOCK( &stream_.mutex );
- error( RtAudioError::SYSTEM_ERROR );
- return;
- }
-
- if ( duplexPrerollBytes <= 0 ) {
- // Copy our buffer into the DS buffer
- CopyMemory( buffer, buffer1, bufferSize1 );
- if ( buffer2 != NULL ) CopyMemory( buffer+bufferSize1, buffer2, bufferSize2 );
- }
- else {
- memset( buffer, 0, bufferSize1 );
- if ( buffer2 != NULL ) memset( buffer + bufferSize1, 0, bufferSize2 );
- duplexPrerollBytes -= bufferSize1 + bufferSize2;
- }
-
- // Update our buffer offset and unlock sound buffer
- nextReadPointer = ( nextReadPointer + bufferSize1 + bufferSize2 ) % dsBufferSize;
- dsBuffer->Unlock( buffer1, bufferSize1, buffer2, bufferSize2 );
- if ( FAILED( result ) ) {
- errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") unlocking capture buffer!";
- errorText_ = errorStream_.str();
- MUTEX_UNLOCK( &stream_.mutex );
- error( RtAudioError::SYSTEM_ERROR );
- return;
- }
- handle->bufferPointer[1] = nextReadPointer;
-
- // No byte swapping necessary in DirectSound implementation.
-
- // If necessary, convert 8-bit data from unsigned to signed.
- if ( stream_.deviceFormat[1] == RTAUDIO_SINT8 )
- for ( int j=0; j<bufferBytes; j++ ) buffer[j] = (signed char) ( buffer[j] - 128 );
-
- // Do buffer conversion if necessary.
- if ( stream_.doConvertBuffer[1] )
- convertBuffer( stream_.userBuffer[1], stream_.deviceBuffer, stream_.convertInfo[1] );
- }
-
- unlock:
- MUTEX_UNLOCK( &stream_.mutex );
- RtApi::tickStreamTime();
-}
-
-// Definitions for utility functions and callbacks
-// specific to the DirectSound implementation.
-
-static unsigned __stdcall callbackHandler( void *ptr )
-{
- CallbackInfo *info = (CallbackInfo *) ptr;
- RtApiDs *object = (RtApiDs *) info->object;
- bool* isRunning = &info->isRunning;
-
- while ( *isRunning == true ) {
- object->callbackEvent();
- }
-
- _endthreadex( 0 );
- return 0;
-}
-
-static BOOL CALLBACK deviceQueryCallback( LPGUID lpguid,
- LPCTSTR description,
- LPCTSTR /*module*/,
- LPVOID lpContext )
-{
- struct DsProbeData& probeInfo = *(struct DsProbeData*) lpContext;
- std::vector<struct DsDevice>& dsDevices = *probeInfo.dsDevices;
-
- HRESULT hr;
- bool validDevice = false;
- if ( probeInfo.isInput == true ) {
- DSCCAPS caps;
- LPDIRECTSOUNDCAPTURE object;
-
- hr = DirectSoundCaptureCreate( lpguid, &object, NULL );
- if ( hr != DS_OK ) return TRUE;
-
- caps.dwSize = sizeof(caps);
- hr = object->GetCaps( &caps );
- if ( hr == DS_OK ) {
- if ( caps.dwChannels > 0 && caps.dwFormats > 0 )
- validDevice = true;
- }
- object->Release();
- }
- else {
- DSCAPS caps;
- LPDIRECTSOUND object;
- hr = DirectSoundCreate( lpguid, &object, NULL );
- if ( hr != DS_OK ) return TRUE;
-
- caps.dwSize = sizeof(caps);
- hr = object->GetCaps( &caps );
- if ( hr == DS_OK ) {
- if ( caps.dwFlags & DSCAPS_PRIMARYMONO || caps.dwFlags & DSCAPS_PRIMARYSTEREO )
- validDevice = true;
- }
- object->Release();
- }
-
- // If good device, then save its name and guid.
- std::string name = convertCharPointerToStdString( description );
- //if ( name == "Primary Sound Driver" || name == "Primary Sound Capture Driver" )
- if ( lpguid == NULL )
- name = "Default Device";
- if ( validDevice ) {
- for ( unsigned int i=0; i<dsDevices.size(); i++ ) {
- if ( dsDevices[i].name == name ) {
- dsDevices[i].found = true;
- if ( probeInfo.isInput ) {
- dsDevices[i].id[1] = lpguid;
- dsDevices[i].validId[1] = true;
- }
- else {
- dsDevices[i].id[0] = lpguid;
- dsDevices[i].validId[0] = true;
- }
- return TRUE;
- }
- }
-
- DsDevice device;
- device.name = name;
- device.found = true;
- if ( probeInfo.isInput ) {
- device.id[1] = lpguid;
- device.validId[1] = true;
- }
- else {
- device.id[0] = lpguid;
- device.validId[0] = true;
- }
- dsDevices.push_back( device );
- }
-
- return TRUE;
-}
-
-static const char* getErrorString( int code )
-{
- switch ( code ) {
-
- case DSERR_ALLOCATED:
- return "Already allocated";
-
- case DSERR_CONTROLUNAVAIL:
- return "Control unavailable";
-
- case DSERR_INVALIDPARAM:
- return "Invalid parameter";
-
- case DSERR_INVALIDCALL:
- return "Invalid call";
-
- case DSERR_GENERIC:
- return "Generic error";
-
- case DSERR_PRIOLEVELNEEDED:
- return "Priority level needed";
-
- case DSERR_OUTOFMEMORY:
- return "Out of memory";
-
- case DSERR_BADFORMAT:
- return "The sample rate or the channel format is not supported";
-
- case DSERR_UNSUPPORTED:
- return "Not supported";
-
- case DSERR_NODRIVER:
- return "No driver";
-
- case DSERR_ALREADYINITIALIZED:
- return "Already initialized";
-
- case DSERR_NOAGGREGATION:
- return "No aggregation";
-
- case DSERR_BUFFERLOST:
- return "Buffer lost";
-
- case DSERR_OTHERAPPHASPRIO:
- return "Another application already has priority";
-
- case DSERR_UNINITIALIZED:
- return "Uninitialized";
-
- default:
- return "DirectSound unknown error";
- }
-}
-//******************** End of __WINDOWS_DS__ *********************//
-#endif
-
-
-#if defined(__LINUX_ALSA__)
-
-#include <alsa/asoundlib.h>
-#include <unistd.h>
-
- // A structure to hold various information related to the ALSA API
- // implementation.
-struct AlsaHandle {
- snd_pcm_t *handles[2];
- bool synchronized;
- bool xrun[2];
- pthread_cond_t runnable_cv;
- bool runnable;
-
- AlsaHandle()
- :synchronized(false), runnable(false) { xrun[0] = false; xrun[1] = false; }
-};
-
-static void *alsaCallbackHandler( void * ptr );
-
-RtApiAlsa :: RtApiAlsa()
-{
- // Nothing to do here.
-}
-
-RtApiAlsa :: ~RtApiAlsa()
-{
- if ( stream_.state != STREAM_CLOSED ) closeStream();
-}
-
-unsigned int RtApiAlsa :: getDeviceCount( void )
-{
- unsigned nDevices = 0;
- int result, subdevice, card;
- char name[64];
- snd_ctl_t *handle;
-
- // Count cards and devices
- card = -1;
- snd_card_next( &card );
- while ( card >= 0 ) {
- sprintf( name, "hw:%d", card );
- result = snd_ctl_open( &handle, name, 0 );
- if ( result < 0 ) {
- errorStream_ << "RtApiAlsa::getDeviceCount: control open, card = " << card << ", " << snd_strerror( result ) << ".";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- goto nextcard;
- }
- subdevice = -1;
- while( 1 ) {
- result = snd_ctl_pcm_next_device( handle, &subdevice );
- if ( result < 0 ) {
- errorStream_ << "RtApiAlsa::getDeviceCount: control next device, card = " << card << ", " << snd_strerror( result ) << ".";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- break;
- }
- if ( subdevice < 0 )
- break;
- nDevices++;
- }
- nextcard:
- snd_ctl_close( handle );
- snd_card_next( &card );
- }
-
- result = snd_ctl_open( &handle, "default", 0 );
- if (result == 0) {
- nDevices++;
- snd_ctl_close( handle );
- }
-
- return nDevices;
-}
-
-RtAudio::DeviceInfo RtApiAlsa :: getDeviceInfo( unsigned int device )
-{
- RtAudio::DeviceInfo info;
- info.probed = false;
-
- unsigned nDevices = 0;
- int result, subdevice, card;
- char name[64];
- snd_ctl_t *chandle;
-
- // Count cards and devices
- card = -1;
- subdevice = -1;
- snd_card_next( &card );
- while ( card >= 0 ) {
- sprintf( name, "hw:%d", card );
- result = snd_ctl_open( &chandle, name, SND_CTL_NONBLOCK );
- if ( result < 0 ) {
- errorStream_ << "RtApiAlsa::getDeviceInfo: control open, card = " << card << ", " << snd_strerror( result ) << ".";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- goto nextcard;
- }
- subdevice = -1;
- while( 1 ) {
- result = snd_ctl_pcm_next_device( chandle, &subdevice );
- if ( result < 0 ) {
- errorStream_ << "RtApiAlsa::getDeviceInfo: control next device, card = " << card << ", " << snd_strerror( result ) << ".";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- break;
- }
- if ( subdevice < 0 ) break;
- if ( nDevices == device ) {
- sprintf( name, "hw:%d,%d", card, subdevice );
- goto foundDevice;
- }
- nDevices++;
- }
- nextcard:
- snd_ctl_close( chandle );
- snd_card_next( &card );
- }
-
- result = snd_ctl_open( &chandle, "default", SND_CTL_NONBLOCK );
- if ( result == 0 ) {
- if ( nDevices == device ) {
- strcpy( name, "default" );
- goto foundDevice;
- }
- nDevices++;
- }
-
- if ( nDevices == 0 ) {
- errorText_ = "RtApiAlsa::getDeviceInfo: no devices found!";
- error( RtAudioError::INVALID_USE );
- return info;
- }
-
- if ( device >= nDevices ) {
- errorText_ = "RtApiAlsa::getDeviceInfo: device ID is invalid!";
- error( RtAudioError::INVALID_USE );
- return info;
- }
-
- foundDevice:
-
- // If a stream is already open, we cannot probe the stream devices.
- // Thus, use the saved results.
- if ( stream_.state != STREAM_CLOSED &&
- ( stream_.device[0] == device || stream_.device[1] == device ) ) {
- snd_ctl_close( chandle );
- if ( device >= devices_.size() ) {
- errorText_ = "RtApiAlsa::getDeviceInfo: device ID was not present before stream was opened.";
- error( RtAudioError::WARNING );
- return info;
- }
- return devices_[ device ];
- }
-
- int openMode = SND_PCM_ASYNC;
- snd_pcm_stream_t stream;
- snd_pcm_info_t *pcminfo;
- snd_pcm_info_alloca( &pcminfo );
- snd_pcm_t *phandle;
- snd_pcm_hw_params_t *params;
- snd_pcm_hw_params_alloca( &params );
-
- // First try for playback unless default device (which has subdev -1)
- stream = SND_PCM_STREAM_PLAYBACK;
- snd_pcm_info_set_stream( pcminfo, stream );
- if ( subdevice != -1 ) {
- snd_pcm_info_set_device( pcminfo, subdevice );
- snd_pcm_info_set_subdevice( pcminfo, 0 );
-
- result = snd_ctl_pcm_info( chandle, pcminfo );
- if ( result < 0 ) {
- // Device probably doesn't support playback.
- goto captureProbe;
- }
- }
-
- result = snd_pcm_open( &phandle, name, stream, openMode | SND_PCM_NONBLOCK );
- if ( result < 0 ) {
- errorStream_ << "RtApiAlsa::getDeviceInfo: snd_pcm_open error for device (" << name << "), " << snd_strerror( result ) << ".";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- goto captureProbe;
- }
-
- // The device is open ... fill the parameter structure.
- result = snd_pcm_hw_params_any( phandle, params );
- if ( result < 0 ) {
- snd_pcm_close( phandle );
- errorStream_ << "RtApiAlsa::getDeviceInfo: snd_pcm_hw_params error for device (" << name << "), " << snd_strerror( result ) << ".";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- goto captureProbe;
- }
-
- // Get output channel information.
- unsigned int value;
- result = snd_pcm_hw_params_get_channels_max( params, &value );
- if ( result < 0 ) {
- snd_pcm_close( phandle );
- errorStream_ << "RtApiAlsa::getDeviceInfo: error getting device (" << name << ") output channels, " << snd_strerror( result ) << ".";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- goto captureProbe;
- }
- info.outputChannels = value;
- snd_pcm_close( phandle );
-
- captureProbe:
- stream = SND_PCM_STREAM_CAPTURE;
- snd_pcm_info_set_stream( pcminfo, stream );
-
- // Now try for capture unless default device (with subdev = -1)
- if ( subdevice != -1 ) {
- result = snd_ctl_pcm_info( chandle, pcminfo );
- snd_ctl_close( chandle );
- if ( result < 0 ) {
- // Device probably doesn't support capture.
- if ( info.outputChannels == 0 ) return info;
- goto probeParameters;
- }
- }
- else
- snd_ctl_close( chandle );
-
- result = snd_pcm_open( &phandle, name, stream, openMode | SND_PCM_NONBLOCK);
- if ( result < 0 ) {
- errorStream_ << "RtApiAlsa::getDeviceInfo: snd_pcm_open error for device (" << name << "), " << snd_strerror( result ) << ".";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- if ( info.outputChannels == 0 ) return info;
- goto probeParameters;
- }
-
- // The device is open ... fill the parameter structure.
- result = snd_pcm_hw_params_any( phandle, params );
- if ( result < 0 ) {
- snd_pcm_close( phandle );
- errorStream_ << "RtApiAlsa::getDeviceInfo: snd_pcm_hw_params error for device (" << name << "), " << snd_strerror( result ) << ".";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- if ( info.outputChannels == 0 ) return info;
- goto probeParameters;
- }
-
- result = snd_pcm_hw_params_get_channels_max( params, &value );
- if ( result < 0 ) {
- snd_pcm_close( phandle );
- errorStream_ << "RtApiAlsa::getDeviceInfo: error getting device (" << name << ") input channels, " << snd_strerror( result ) << ".";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- if ( info.outputChannels == 0 ) return info;
- goto probeParameters;
- }
- info.inputChannels = value;
- snd_pcm_close( phandle );
-
- // If device opens for both playback and capture, we determine the channels.
- if ( info.outputChannels > 0 && info.inputChannels > 0 )
- info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels;
-
- // ALSA doesn't provide default devices so we'll use the first available one.
- if ( device == 0 && info.outputChannels > 0 )
- info.isDefaultOutput = true;
- if ( device == 0 && info.inputChannels > 0 )
- info.isDefaultInput = true;
-
- probeParameters:
- // At this point, we just need to figure out the supported data
- // formats and sample rates. We'll proceed by opening the device in
- // the direction with the maximum number of channels, or playback if
- // they are equal. This might limit our sample rate options, but so
- // be it.
-
- if ( info.outputChannels >= info.inputChannels )
- stream = SND_PCM_STREAM_PLAYBACK;
- else
- stream = SND_PCM_STREAM_CAPTURE;
- snd_pcm_info_set_stream( pcminfo, stream );
-
- result = snd_pcm_open( &phandle, name, stream, openMode | SND_PCM_NONBLOCK);
- if ( result < 0 ) {
- errorStream_ << "RtApiAlsa::getDeviceInfo: snd_pcm_open error for device (" << name << "), " << snd_strerror( result ) << ".";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- return info;
- }
-
- // The device is open ... fill the parameter structure.
- result = snd_pcm_hw_params_any( phandle, params );
- if ( result < 0 ) {
- snd_pcm_close( phandle );
- errorStream_ << "RtApiAlsa::getDeviceInfo: snd_pcm_hw_params error for device (" << name << "), " << snd_strerror( result ) << ".";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- return info;
- }
-
- // Test our discrete set of sample rate values.
- info.sampleRates.clear();
- for ( unsigned int i=0; i<MAX_SAMPLE_RATES; i++ ) {
- if ( snd_pcm_hw_params_test_rate( phandle, params, SAMPLE_RATES[i], 0 ) == 0 ) {
- info.sampleRates.push_back( SAMPLE_RATES[i] );
-
- if ( !info.preferredSampleRate || ( SAMPLE_RATES[i] <= 48000 && SAMPLE_RATES[i] > info.preferredSampleRate ) )
- info.preferredSampleRate = SAMPLE_RATES[i];
- }
- }
- if ( info.sampleRates.size() == 0 ) {
- snd_pcm_close( phandle );
- errorStream_ << "RtApiAlsa::getDeviceInfo: no supported sample rates found for device (" << name << ").";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- return info;
- }
-
- // Probe the supported data formats ... we don't care about endian-ness just yet
- snd_pcm_format_t format;
- info.nativeFormats = 0;
- format = SND_PCM_FORMAT_S8;
- if ( snd_pcm_hw_params_test_format( phandle, params, format ) == 0 )
- info.nativeFormats |= RTAUDIO_SINT8;
- format = SND_PCM_FORMAT_S16;
- if ( snd_pcm_hw_params_test_format( phandle, params, format ) == 0 )
- info.nativeFormats |= RTAUDIO_SINT16;
- format = SND_PCM_FORMAT_S24;
- if ( snd_pcm_hw_params_test_format( phandle, params, format ) == 0 )
- info.nativeFormats |= RTAUDIO_SINT24;
- format = SND_PCM_FORMAT_S32;
- if ( snd_pcm_hw_params_test_format( phandle, params, format ) == 0 )
- info.nativeFormats |= RTAUDIO_SINT32;
- format = SND_PCM_FORMAT_FLOAT;
- if ( snd_pcm_hw_params_test_format( phandle, params, format ) == 0 )
- info.nativeFormats |= RTAUDIO_FLOAT32;
- format = SND_PCM_FORMAT_FLOAT64;
- if ( snd_pcm_hw_params_test_format( phandle, params, format ) == 0 )
- info.nativeFormats |= RTAUDIO_FLOAT64;
-
- // Check that we have at least one supported format
- if ( info.nativeFormats == 0 ) {
- snd_pcm_close( phandle );
- errorStream_ << "RtApiAlsa::getDeviceInfo: pcm device (" << name << ") data format not supported by RtAudio.";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- return info;
- }
-
- // Get the device name
- char *cardname;
- result = snd_card_get_name( card, &cardname );
- if ( result >= 0 ) {
- sprintf( name, "hw:%s,%d", cardname, subdevice );
- free( cardname );
- }
- info.name = name;
-
- // That's all ... close the device and return
- snd_pcm_close( phandle );
- info.probed = true;
- return info;
-}
-
-void RtApiAlsa :: saveDeviceInfo( void )
-{
- devices_.clear();
-
- unsigned int nDevices = getDeviceCount();
- devices_.resize( nDevices );
- for ( unsigned int i=0; i<nDevices; i++ )
- devices_[i] = getDeviceInfo( i );
-}
-
-bool RtApiAlsa :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,
- unsigned int firstChannel, unsigned int sampleRate,
- RtAudioFormat format, unsigned int *bufferSize,
- RtAudio::StreamOptions *options )
-
-{
-#if defined(__RTAUDIO_DEBUG__)
- snd_output_t *out;
- snd_output_stdio_attach(&out, stderr, 0);
-#endif
-
- // I'm not using the "plug" interface ... too much inconsistent behavior.
-
- unsigned nDevices = 0;
- int result, subdevice, card;
- char name[64];
- snd_ctl_t *chandle;
-
- if ( options && options->flags & RTAUDIO_ALSA_USE_DEFAULT )
- snprintf(name, sizeof(name), "%s", "default");
- else {
- // Count cards and devices
- card = -1;
- snd_card_next( &card );
- while ( card >= 0 ) {
- sprintf( name, "hw:%d", card );
- result = snd_ctl_open( &chandle, name, SND_CTL_NONBLOCK );
- if ( result < 0 ) {
- errorStream_ << "RtApiAlsa::probeDeviceOpen: control open, card = " << card << ", " << snd_strerror( result ) << ".";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
- subdevice = -1;
- while( 1 ) {
- result = snd_ctl_pcm_next_device( chandle, &subdevice );
- if ( result < 0 ) break;
- if ( subdevice < 0 ) break;
- if ( nDevices == device ) {
- sprintf( name, "hw:%d,%d", card, subdevice );
- snd_ctl_close( chandle );
- goto foundDevice;
- }
- nDevices++;
- }
- snd_ctl_close( chandle );
- snd_card_next( &card );
- }
-
- result = snd_ctl_open( &chandle, "default", SND_CTL_NONBLOCK );
- if ( result == 0 ) {
- if ( nDevices == device ) {
- strcpy( name, "default" );
- goto foundDevice;
- }
- nDevices++;
- }
-
- if ( nDevices == 0 ) {
- // This should not happen because a check is made before this function is called.
- errorText_ = "RtApiAlsa::probeDeviceOpen: no devices found!";
- return FAILURE;
- }
-
- if ( device >= nDevices ) {
- // This should not happen because a check is made before this function is called.
- errorText_ = "RtApiAlsa::probeDeviceOpen: device ID is invalid!";
- return FAILURE;
- }
- }
-
- foundDevice:
-
- // The getDeviceInfo() function will not work for a device that is
- // already open. Thus, we'll probe the system before opening a
- // stream and save the results for use by getDeviceInfo().
- if ( mode == OUTPUT || ( mode == INPUT && stream_.mode != OUTPUT ) ) // only do once
- this->saveDeviceInfo();
-
- snd_pcm_stream_t stream;
- if ( mode == OUTPUT )
- stream = SND_PCM_STREAM_PLAYBACK;
- else
- stream = SND_PCM_STREAM_CAPTURE;
-
- snd_pcm_t *phandle;
- int openMode = SND_PCM_ASYNC;
- result = snd_pcm_open( &phandle, name, stream, openMode );
- if ( result < 0 ) {
- if ( mode == OUTPUT )
- errorStream_ << "RtApiAlsa::probeDeviceOpen: pcm device (" << name << ") won't open for output.";
- else
- errorStream_ << "RtApiAlsa::probeDeviceOpen: pcm device (" << name << ") won't open for input.";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- // Fill the parameter structure.
- snd_pcm_hw_params_t *hw_params;
- snd_pcm_hw_params_alloca( &hw_params );
- result = snd_pcm_hw_params_any( phandle, hw_params );
- if ( result < 0 ) {
- snd_pcm_close( phandle );
- errorStream_ << "RtApiAlsa::probeDeviceOpen: error getting pcm device (" << name << ") parameters, " << snd_strerror( result ) << ".";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
-#if defined(__RTAUDIO_DEBUG__)
- fprintf( stderr, "\nRtApiAlsa: dump hardware params just after device open:\n\n" );
- snd_pcm_hw_params_dump( hw_params, out );
-#endif
-
- // Set access ... check user preference.
- if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) {
- stream_.userInterleaved = false;
- result = snd_pcm_hw_params_set_access( phandle, hw_params, SND_PCM_ACCESS_RW_NONINTERLEAVED );
- if ( result < 0 ) {
- result = snd_pcm_hw_params_set_access( phandle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED );
- stream_.deviceInterleaved[mode] = true;
- }
- else
- stream_.deviceInterleaved[mode] = false;
- }
- else {
- stream_.userInterleaved = true;
- result = snd_pcm_hw_params_set_access( phandle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED );
- if ( result < 0 ) {
- result = snd_pcm_hw_params_set_access( phandle, hw_params, SND_PCM_ACCESS_RW_NONINTERLEAVED );
- stream_.deviceInterleaved[mode] = false;
- }
- else
- stream_.deviceInterleaved[mode] = true;
- }
-
- if ( result < 0 ) {
- snd_pcm_close( phandle );
- errorStream_ << "RtApiAlsa::probeDeviceOpen: error setting pcm device (" << name << ") access, " << snd_strerror( result ) << ".";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- // Determine how to set the device format.
- stream_.userFormat = format;
- snd_pcm_format_t deviceFormat = SND_PCM_FORMAT_UNKNOWN;
-
- if ( format == RTAUDIO_SINT8 )
- deviceFormat = SND_PCM_FORMAT_S8;
- else if ( format == RTAUDIO_SINT16 )
- deviceFormat = SND_PCM_FORMAT_S16;
- else if ( format == RTAUDIO_SINT24 )
- deviceFormat = SND_PCM_FORMAT_S24;
- else if ( format == RTAUDIO_SINT32 )
- deviceFormat = SND_PCM_FORMAT_S32;
- else if ( format == RTAUDIO_FLOAT32 )
- deviceFormat = SND_PCM_FORMAT_FLOAT;
- else if ( format == RTAUDIO_FLOAT64 )
- deviceFormat = SND_PCM_FORMAT_FLOAT64;
-
- if ( snd_pcm_hw_params_test_format(phandle, hw_params, deviceFormat) == 0) {
- stream_.deviceFormat[mode] = format;
- goto setFormat;
- }
-
- // The user requested format is not natively supported by the device.
- deviceFormat = SND_PCM_FORMAT_FLOAT64;
- if ( snd_pcm_hw_params_test_format( phandle, hw_params, deviceFormat ) == 0 ) {
- stream_.deviceFormat[mode] = RTAUDIO_FLOAT64;
- goto setFormat;
- }
-
- deviceFormat = SND_PCM_FORMAT_FLOAT;
- if ( snd_pcm_hw_params_test_format(phandle, hw_params, deviceFormat ) == 0 ) {
- stream_.deviceFormat[mode] = RTAUDIO_FLOAT32;
- goto setFormat;
- }
-
- deviceFormat = SND_PCM_FORMAT_S32;
- if ( snd_pcm_hw_params_test_format(phandle, hw_params, deviceFormat ) == 0 ) {
- stream_.deviceFormat[mode] = RTAUDIO_SINT32;
- goto setFormat;
- }
-
- deviceFormat = SND_PCM_FORMAT_S24;
- if ( snd_pcm_hw_params_test_format(phandle, hw_params, deviceFormat ) == 0 ) {
- stream_.deviceFormat[mode] = RTAUDIO_SINT24;
- goto setFormat;
- }
-
- deviceFormat = SND_PCM_FORMAT_S16;
- if ( snd_pcm_hw_params_test_format(phandle, hw_params, deviceFormat ) == 0 ) {
- stream_.deviceFormat[mode] = RTAUDIO_SINT16;
- goto setFormat;
- }
-
- deviceFormat = SND_PCM_FORMAT_S8;
- if ( snd_pcm_hw_params_test_format(phandle, hw_params, deviceFormat ) == 0 ) {
- stream_.deviceFormat[mode] = RTAUDIO_SINT8;
- goto setFormat;
- }
-
- // If we get here, no supported format was found.
- snd_pcm_close( phandle );
- errorStream_ << "RtApiAlsa::probeDeviceOpen: pcm device " << device << " data format not supported by RtAudio.";
- errorText_ = errorStream_.str();
- return FAILURE;
-
- setFormat:
- result = snd_pcm_hw_params_set_format( phandle, hw_params, deviceFormat );
- if ( result < 0 ) {
- snd_pcm_close( phandle );
- errorStream_ << "RtApiAlsa::probeDeviceOpen: error setting pcm device (" << name << ") data format, " << snd_strerror( result ) << ".";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- // Determine whether byte-swaping is necessary.
- stream_.doByteSwap[mode] = false;
- if ( deviceFormat != SND_PCM_FORMAT_S8 ) {
- result = snd_pcm_format_cpu_endian( deviceFormat );
- if ( result == 0 )
- stream_.doByteSwap[mode] = true;
- else if (result < 0) {
- snd_pcm_close( phandle );
- errorStream_ << "RtApiAlsa::probeDeviceOpen: error getting pcm device (" << name << ") endian-ness, " << snd_strerror( result ) << ".";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
- }
-
- // Set the sample rate.
- result = snd_pcm_hw_params_set_rate_near( phandle, hw_params, (unsigned int*) &sampleRate, 0 );
- if ( result < 0 ) {
- snd_pcm_close( phandle );
- errorStream_ << "RtApiAlsa::probeDeviceOpen: error setting sample rate on device (" << name << "), " << snd_strerror( result ) << ".";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- // Determine the number of channels for this device. We support a possible
- // minimum device channel number > than the value requested by the user.
- stream_.nUserChannels[mode] = channels;
- unsigned int value;
- result = snd_pcm_hw_params_get_channels_max( hw_params, &value );
- unsigned int deviceChannels = value;
- if ( result < 0 || deviceChannels < channels + firstChannel ) {
- snd_pcm_close( phandle );
- errorStream_ << "RtApiAlsa::probeDeviceOpen: requested channel parameters not supported by device (" << name << "), " << snd_strerror( result ) << ".";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- result = snd_pcm_hw_params_get_channels_min( hw_params, &value );
- if ( result < 0 ) {
- snd_pcm_close( phandle );
- errorStream_ << "RtApiAlsa::probeDeviceOpen: error getting minimum channels for device (" << name << "), " << snd_strerror( result ) << ".";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
- deviceChannels = value;
- if ( deviceChannels < channels + firstChannel ) deviceChannels = channels + firstChannel;
- stream_.nDeviceChannels[mode] = deviceChannels;
-
- // Set the device channels.
- result = snd_pcm_hw_params_set_channels( phandle, hw_params, deviceChannels );
- if ( result < 0 ) {
- snd_pcm_close( phandle );
- errorStream_ << "RtApiAlsa::probeDeviceOpen: error setting channels for device (" << name << "), " << snd_strerror( result ) << ".";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- // Set the buffer (or period) size.
- int dir = 0;
- snd_pcm_uframes_t periodSize = *bufferSize;
- result = snd_pcm_hw_params_set_period_size_near( phandle, hw_params, &periodSize, &dir );
- if ( result < 0 ) {
- snd_pcm_close( phandle );
- errorStream_ << "RtApiAlsa::probeDeviceOpen: error setting period size for device (" << name << "), " << snd_strerror( result ) << ".";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
- *bufferSize = periodSize;
-
- // Set the buffer number, which in ALSA is referred to as the "period".
- unsigned int periods = 0;
- if ( options && options->flags & RTAUDIO_MINIMIZE_LATENCY ) periods = 2;
- if ( options && options->numberOfBuffers > 0 ) periods = options->numberOfBuffers;
- if ( periods < 2 ) periods = 4; // a fairly safe default value
- result = snd_pcm_hw_params_set_periods_near( phandle, hw_params, &periods, &dir );
- if ( result < 0 ) {
- snd_pcm_close( phandle );
- errorStream_ << "RtApiAlsa::probeDeviceOpen: error setting periods for device (" << name << "), " << snd_strerror( result ) << ".";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- // If attempting to setup a duplex stream, the bufferSize parameter
- // MUST be the same in both directions!
- if ( stream_.mode == OUTPUT && mode == INPUT && *bufferSize != stream_.bufferSize ) {
- snd_pcm_close( phandle );
- errorStream_ << "RtApiAlsa::probeDeviceOpen: system error setting buffer size for duplex stream on device (" << name << ").";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- stream_.bufferSize = *bufferSize;
-
- // Install the hardware configuration
- result = snd_pcm_hw_params( phandle, hw_params );
- if ( result < 0 ) {
- snd_pcm_close( phandle );
- errorStream_ << "RtApiAlsa::probeDeviceOpen: error installing hardware configuration on device (" << name << "), " << snd_strerror( result ) << ".";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
-#if defined(__RTAUDIO_DEBUG__)
- fprintf(stderr, "\nRtApiAlsa: dump hardware params after installation:\n\n");
- snd_pcm_hw_params_dump( hw_params, out );
-#endif
-
- // Set the software configuration to fill buffers with zeros and prevent device stopping on xruns.
- snd_pcm_sw_params_t *sw_params = NULL;
- snd_pcm_sw_params_alloca( &sw_params );
- snd_pcm_sw_params_current( phandle, sw_params );
- snd_pcm_sw_params_set_start_threshold( phandle, sw_params, *bufferSize );
- snd_pcm_sw_params_set_stop_threshold( phandle, sw_params, ULONG_MAX );
- snd_pcm_sw_params_set_silence_threshold( phandle, sw_params, 0 );
-
- // The following two settings were suggested by Theo Veenker
- //snd_pcm_sw_params_set_avail_min( phandle, sw_params, *bufferSize );
- //snd_pcm_sw_params_set_xfer_align( phandle, sw_params, 1 );
-
- // here are two options for a fix
- //snd_pcm_sw_params_set_silence_size( phandle, sw_params, ULONG_MAX );
- snd_pcm_uframes_t val;
- snd_pcm_sw_params_get_boundary( sw_params, &val );
- snd_pcm_sw_params_set_silence_size( phandle, sw_params, val );
-
- result = snd_pcm_sw_params( phandle, sw_params );
- if ( result < 0 ) {
- snd_pcm_close( phandle );
- errorStream_ << "RtApiAlsa::probeDeviceOpen: error installing software configuration on device (" << name << "), " << snd_strerror( result ) << ".";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
-#if defined(__RTAUDIO_DEBUG__)
- fprintf(stderr, "\nRtApiAlsa: dump software params after installation:\n\n");
- snd_pcm_sw_params_dump( sw_params, out );
-#endif
-
- // Set flags for buffer conversion
- stream_.doConvertBuffer[mode] = false;
- if ( stream_.userFormat != stream_.deviceFormat[mode] )
- stream_.doConvertBuffer[mode] = true;
- if ( stream_.nUserChannels[mode] < stream_.nDeviceChannels[mode] )
- stream_.doConvertBuffer[mode] = true;
- if ( stream_.userInterleaved != stream_.deviceInterleaved[mode] &&
- stream_.nUserChannels[mode] > 1 )
- stream_.doConvertBuffer[mode] = true;
-
- // Allocate the ApiHandle if necessary and then save.
- AlsaHandle *apiInfo = 0;
- if ( stream_.apiHandle == 0 ) {
- try {
- apiInfo = (AlsaHandle *) new AlsaHandle;
- }
- catch ( std::bad_alloc& ) {
- errorText_ = "RtApiAlsa::probeDeviceOpen: error allocating AlsaHandle memory.";
- goto error;
- }
-
- if ( pthread_cond_init( &apiInfo->runnable_cv, NULL ) ) {
- errorText_ = "RtApiAlsa::probeDeviceOpen: error initializing pthread condition variable.";
- goto error;
- }
-
- stream_.apiHandle = (void *) apiInfo;
- apiInfo->handles[0] = 0;
- apiInfo->handles[1] = 0;
- }
- else {
- apiInfo = (AlsaHandle *) stream_.apiHandle;
- }
- apiInfo->handles[mode] = phandle;
- phandle = 0;
-
- // Allocate necessary internal buffers.
- unsigned long bufferBytes;
- bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat );
- stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 );
- if ( stream_.userBuffer[mode] == NULL ) {
- errorText_ = "RtApiAlsa::probeDeviceOpen: error allocating user buffer memory.";
- goto error;
- }
-
- if ( stream_.doConvertBuffer[mode] ) {
-
- bool makeBuffer = true;
- bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] );
- if ( mode == INPUT ) {
- if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) {
- unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] );
- if ( bufferBytes <= bytesOut ) makeBuffer = false;
- }
- }
-
- if ( makeBuffer ) {
- bufferBytes *= *bufferSize;
- if ( stream_.deviceBuffer ) free( stream_.deviceBuffer );
- stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 );
- if ( stream_.deviceBuffer == NULL ) {
- errorText_ = "RtApiAlsa::probeDeviceOpen: error allocating device buffer memory.";
- goto error;
- }
- }
- }
-
- stream_.sampleRate = sampleRate;
- stream_.nBuffers = periods;
- stream_.device[mode] = device;
- stream_.state = STREAM_STOPPED;
-
- // Setup the buffer conversion information structure.
- if ( stream_.doConvertBuffer[mode] ) setConvertInfo( mode, firstChannel );
-
- // Setup thread if necessary.
- if ( stream_.mode == OUTPUT && mode == INPUT ) {
- // We had already set up an output stream.
- stream_.mode = DUPLEX;
- // Link the streams if possible.
- apiInfo->synchronized = false;
- if ( snd_pcm_link( apiInfo->handles[0], apiInfo->handles[1] ) == 0 )
- apiInfo->synchronized = true;
- else {
- errorText_ = "RtApiAlsa::probeDeviceOpen: unable to synchronize input and output devices.";
- error( RtAudioError::WARNING );
- }
- }
- else {
- stream_.mode = mode;
-
- // Setup callback thread.
- stream_.callbackInfo.object = (void *) this;
-
- // Set the thread attributes for joinable and realtime scheduling
- // priority (optional). The higher priority will only take affect
- // if the program is run as root or suid. Note, under Linux
- // processes with CAP_SYS_NICE privilege, a user can change
- // scheduling policy and priority (thus need not be root). See
- // POSIX "capabilities".
- pthread_attr_t attr;
- pthread_attr_init( &attr );
- pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE );
-
-#ifdef SCHED_RR // Undefined with some OSes (eg: NetBSD 1.6.x with GNU Pthread)
- if ( options && options->flags & RTAUDIO_SCHEDULE_REALTIME ) {
- // We previously attempted to increase the audio callback priority
- // to SCHED_RR here via the attributes. However, while no errors
- // were reported in doing so, it did not work. So, now this is
- // done in the alsaCallbackHandler function.
- stream_.callbackInfo.doRealtime = true;
- int priority = options->priority;
- int min = sched_get_priority_min( SCHED_RR );
- int max = sched_get_priority_max( SCHED_RR );
- if ( priority < min ) priority = min;
- else if ( priority > max ) priority = max;
- stream_.callbackInfo.priority = priority;
- }
-#endif
-
- stream_.callbackInfo.isRunning = true;
- result = pthread_create( &stream_.callbackInfo.thread, &attr, alsaCallbackHandler, &stream_.callbackInfo );
- pthread_attr_destroy( &attr );
- if ( result ) {
- stream_.callbackInfo.isRunning = false;
- errorText_ = "RtApiAlsa::error creating callback thread!";
- goto error;
- }
- }
-
- return SUCCESS;
-
- error:
- if ( apiInfo ) {
- pthread_cond_destroy( &apiInfo->runnable_cv );
- if ( apiInfo->handles[0] ) snd_pcm_close( apiInfo->handles[0] );
- if ( apiInfo->handles[1] ) snd_pcm_close( apiInfo->handles[1] );
- delete apiInfo;
- stream_.apiHandle = 0;
- }
-
- if ( phandle) snd_pcm_close( phandle );
-
- for ( int i=0; i<2; i++ ) {
- if ( stream_.userBuffer[i] ) {
- free( stream_.userBuffer[i] );
- stream_.userBuffer[i] = 0;
- }
- }
-
- if ( stream_.deviceBuffer ) {
- free( stream_.deviceBuffer );
- stream_.deviceBuffer = 0;
- }
-
- stream_.state = STREAM_CLOSED;
- return FAILURE;
-}
-
-void RtApiAlsa :: closeStream()
-{
- if ( stream_.state == STREAM_CLOSED ) {
- errorText_ = "RtApiAlsa::closeStream(): no open stream to close!";
- error( RtAudioError::WARNING );
- return;
- }
-
- AlsaHandle *apiInfo = (AlsaHandle *) stream_.apiHandle;
- stream_.callbackInfo.isRunning = false;
- MUTEX_LOCK( &stream_.mutex );
- if ( stream_.state == STREAM_STOPPED ) {
- apiInfo->runnable = true;
- pthread_cond_signal( &apiInfo->runnable_cv );
- }
- MUTEX_UNLOCK( &stream_.mutex );
- pthread_join( stream_.callbackInfo.thread, NULL );
-
- if ( stream_.state == STREAM_RUNNING ) {
- stream_.state = STREAM_STOPPED;
- if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX )
- snd_pcm_drop( apiInfo->handles[0] );
- if ( stream_.mode == INPUT || stream_.mode == DUPLEX )
- snd_pcm_drop( apiInfo->handles[1] );
- }
-
- if ( apiInfo ) {
- pthread_cond_destroy( &apiInfo->runnable_cv );
- if ( apiInfo->handles[0] ) snd_pcm_close( apiInfo->handles[0] );
- if ( apiInfo->handles[1] ) snd_pcm_close( apiInfo->handles[1] );
- delete apiInfo;
- stream_.apiHandle = 0;
- }
-
- for ( int i=0; i<2; i++ ) {
- if ( stream_.userBuffer[i] ) {
- free( stream_.userBuffer[i] );
- stream_.userBuffer[i] = 0;
- }
- }
-
- if ( stream_.deviceBuffer ) {
- free( stream_.deviceBuffer );
- stream_.deviceBuffer = 0;
- }
-
- stream_.mode = UNINITIALIZED;
- stream_.state = STREAM_CLOSED;
-}
-
-void RtApiAlsa :: startStream()
-{
- // This method calls snd_pcm_prepare if the device isn't already in that state.
-
- verifyStream();
- if ( stream_.state == STREAM_RUNNING ) {
- errorText_ = "RtApiAlsa::startStream(): the stream is already running!";
- error( RtAudioError::WARNING );
- return;
- }
-
- MUTEX_LOCK( &stream_.mutex );
-
- int result = 0;
- snd_pcm_state_t state;
- AlsaHandle *apiInfo = (AlsaHandle *) stream_.apiHandle;
- snd_pcm_t **handle = (snd_pcm_t **) apiInfo->handles;
- if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
- state = snd_pcm_state( handle[0] );
- if ( state != SND_PCM_STATE_PREPARED ) {
- result = snd_pcm_prepare( handle[0] );
- if ( result < 0 ) {
- errorStream_ << "RtApiAlsa::startStream: error preparing output pcm device, " << snd_strerror( result ) << ".";
- errorText_ = errorStream_.str();
- goto unlock;
- }
- }
- }
-
- if ( ( stream_.mode == INPUT || stream_.mode == DUPLEX ) && !apiInfo->synchronized ) {
- result = snd_pcm_drop(handle[1]); // fix to remove stale data received since device has been open
- state = snd_pcm_state( handle[1] );
- if ( state != SND_PCM_STATE_PREPARED ) {
- result = snd_pcm_prepare( handle[1] );
- if ( result < 0 ) {
- errorStream_ << "RtApiAlsa::startStream: error preparing input pcm device, " << snd_strerror( result ) << ".";
- errorText_ = errorStream_.str();
- goto unlock;
- }
- }
- }
-
- stream_.state = STREAM_RUNNING;
-
- unlock:
- apiInfo->runnable = true;
- pthread_cond_signal( &apiInfo->runnable_cv );
- MUTEX_UNLOCK( &stream_.mutex );
-
- if ( result >= 0 ) return;
- error( RtAudioError::SYSTEM_ERROR );
-}
-
-void RtApiAlsa :: stopStream()
-{
- verifyStream();
- if ( stream_.state == STREAM_STOPPED ) {
- errorText_ = "RtApiAlsa::stopStream(): the stream is already stopped!";
- error( RtAudioError::WARNING );
- return;
- }
-
- stream_.state = STREAM_STOPPED;
- MUTEX_LOCK( &stream_.mutex );
-
- int result = 0;
- AlsaHandle *apiInfo = (AlsaHandle *) stream_.apiHandle;
- snd_pcm_t **handle = (snd_pcm_t **) apiInfo->handles;
- if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
- if ( apiInfo->synchronized )
- result = snd_pcm_drop( handle[0] );
- else
- result = snd_pcm_drain( handle[0] );
- if ( result < 0 ) {
- errorStream_ << "RtApiAlsa::stopStream: error draining output pcm device, " << snd_strerror( result ) << ".";
- errorText_ = errorStream_.str();
- goto unlock;
- }
- }
-
- if ( ( stream_.mode == INPUT || stream_.mode == DUPLEX ) && !apiInfo->synchronized ) {
- result = snd_pcm_drop( handle[1] );
- if ( result < 0 ) {
- errorStream_ << "RtApiAlsa::stopStream: error stopping input pcm device, " << snd_strerror( result ) << ".";
- errorText_ = errorStream_.str();
- goto unlock;
- }
- }
-
- unlock:
- apiInfo->runnable = false; // fixes high CPU usage when stopped
- MUTEX_UNLOCK( &stream_.mutex );
-
- if ( result >= 0 ) return;
- error( RtAudioError::SYSTEM_ERROR );
-}
-
-void RtApiAlsa :: abortStream()
-{
- verifyStream();
- if ( stream_.state == STREAM_STOPPED ) {
- errorText_ = "RtApiAlsa::abortStream(): the stream is already stopped!";
- error( RtAudioError::WARNING );
- return;
- }
-
- stream_.state = STREAM_STOPPED;
- MUTEX_LOCK( &stream_.mutex );
-
- int result = 0;
- AlsaHandle *apiInfo = (AlsaHandle *) stream_.apiHandle;
- snd_pcm_t **handle = (snd_pcm_t **) apiInfo->handles;
- if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
- result = snd_pcm_drop( handle[0] );
- if ( result < 0 ) {
- errorStream_ << "RtApiAlsa::abortStream: error aborting output pcm device, " << snd_strerror( result ) << ".";
- errorText_ = errorStream_.str();
- goto unlock;
- }
- }
-
- if ( ( stream_.mode == INPUT || stream_.mode == DUPLEX ) && !apiInfo->synchronized ) {
- result = snd_pcm_drop( handle[1] );
- if ( result < 0 ) {
- errorStream_ << "RtApiAlsa::abortStream: error aborting input pcm device, " << snd_strerror( result ) << ".";
- errorText_ = errorStream_.str();
- goto unlock;
- }
- }
-
- unlock:
- apiInfo->runnable = false; // fixes high CPU usage when stopped
- MUTEX_UNLOCK( &stream_.mutex );
-
- if ( result >= 0 ) return;
- error( RtAudioError::SYSTEM_ERROR );
-}
-
-void RtApiAlsa :: callbackEvent()
-{
- AlsaHandle *apiInfo = (AlsaHandle *) stream_.apiHandle;
- if ( stream_.state == STREAM_STOPPED ) {
- MUTEX_LOCK( &stream_.mutex );
- while ( !apiInfo->runnable )
- pthread_cond_wait( &apiInfo->runnable_cv, &stream_.mutex );
-
- if ( stream_.state != STREAM_RUNNING ) {
- MUTEX_UNLOCK( &stream_.mutex );
- return;
- }
- MUTEX_UNLOCK( &stream_.mutex );
- }
-
- if ( stream_.state == STREAM_CLOSED ) {
- errorText_ = "RtApiAlsa::callbackEvent(): the stream is closed ... this shouldn't happen!";
- error( RtAudioError::WARNING );
- return;
- }
-
- int doStopStream = 0;
- RtAudioCallback callback = (RtAudioCallback) stream_.callbackInfo.callback;
- double streamTime = getStreamTime();
- RtAudioStreamStatus status = 0;
- if ( stream_.mode != INPUT && apiInfo->xrun[0] == true ) {
- status |= RTAUDIO_OUTPUT_UNDERFLOW;
- apiInfo->xrun[0] = false;
- }
- if ( stream_.mode != OUTPUT && apiInfo->xrun[1] == true ) {
- status |= RTAUDIO_INPUT_OVERFLOW;
- apiInfo->xrun[1] = false;
- }
- doStopStream = callback( stream_.userBuffer[0], stream_.userBuffer[1],
- stream_.bufferSize, streamTime, status, stream_.callbackInfo.userData );
-
- if ( doStopStream == 2 ) {
- abortStream();
- return;
- }
-
- MUTEX_LOCK( &stream_.mutex );
-
- // The state might change while waiting on a mutex.
- if ( stream_.state == STREAM_STOPPED ) goto unlock;
-
- int result;
- char *buffer;
- int channels;
- snd_pcm_t **handle;
- snd_pcm_sframes_t frames;
- RtAudioFormat format;
- handle = (snd_pcm_t **) apiInfo->handles;
-
- if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) {
-
- // Setup parameters.
- if ( stream_.doConvertBuffer[1] ) {
- buffer = stream_.deviceBuffer;
- channels = stream_.nDeviceChannels[1];
- format = stream_.deviceFormat[1];
- }
- else {
- buffer = stream_.userBuffer[1];
- channels = stream_.nUserChannels[1];
- format = stream_.userFormat;
- }
-
- // Read samples from device in interleaved/non-interleaved format.
- if ( stream_.deviceInterleaved[1] )
- result = snd_pcm_readi( handle[1], buffer, stream_.bufferSize );
- else {
- void *bufs[channels];
- size_t offset = stream_.bufferSize * formatBytes( format );
- for ( int i=0; i<channels; i++ )
- bufs[i] = (void *) (buffer + (i * offset));
- result = snd_pcm_readn( handle[1], bufs, stream_.bufferSize );
- }
-
- if ( result < (int) stream_.bufferSize ) {
- // Either an error or overrun occured.
- if ( result == -EPIPE ) {
- snd_pcm_state_t state = snd_pcm_state( handle[1] );
- if ( state == SND_PCM_STATE_XRUN ) {
- apiInfo->xrun[1] = true;
- result = snd_pcm_prepare( handle[1] );
- if ( result < 0 ) {
- errorStream_ << "RtApiAlsa::callbackEvent: error preparing device after overrun, " << snd_strerror( result ) << ".";
- errorText_ = errorStream_.str();
- }
- }
- else {
- errorStream_ << "RtApiAlsa::callbackEvent: error, current state is " << snd_pcm_state_name( state ) << ", " << snd_strerror( result ) << ".";
- errorText_ = errorStream_.str();
- }
- }
- else {
- errorStream_ << "RtApiAlsa::callbackEvent: audio read error, " << snd_strerror( result ) << ".";
- errorText_ = errorStream_.str();
- }
- error( RtAudioError::WARNING );
- goto tryOutput;
- }
-
- // Do byte swapping if necessary.
- if ( stream_.doByteSwap[1] )
- byteSwapBuffer( buffer, stream_.bufferSize * channels, format );
-
- // Do buffer conversion if necessary.
- if ( stream_.doConvertBuffer[1] )
- convertBuffer( stream_.userBuffer[1], stream_.deviceBuffer, stream_.convertInfo[1] );
-
- // Check stream latency
- result = snd_pcm_delay( handle[1], &frames );
- if ( result == 0 && frames > 0 ) stream_.latency[1] = frames;
- }
-
- tryOutput:
-
- if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
-
- // Setup parameters and do buffer conversion if necessary.
- if ( stream_.doConvertBuffer[0] ) {
- buffer = stream_.deviceBuffer;
- convertBuffer( buffer, stream_.userBuffer[0], stream_.convertInfo[0] );
- channels = stream_.nDeviceChannels[0];
- format = stream_.deviceFormat[0];
- }
- else {
- buffer = stream_.userBuffer[0];
- channels = stream_.nUserChannels[0];
- format = stream_.userFormat;
- }
-
- // Do byte swapping if necessary.
- if ( stream_.doByteSwap[0] )
- byteSwapBuffer(buffer, stream_.bufferSize * channels, format);
-
- // Write samples to device in interleaved/non-interleaved format.
- if ( stream_.deviceInterleaved[0] )
- result = snd_pcm_writei( handle[0], buffer, stream_.bufferSize );
- else {
- void *bufs[channels];
- size_t offset = stream_.bufferSize * formatBytes( format );
- for ( int i=0; i<channels; i++ )
- bufs[i] = (void *) (buffer + (i * offset));
- result = snd_pcm_writen( handle[0], bufs, stream_.bufferSize );
- }
-
- if ( result < (int) stream_.bufferSize ) {
- // Either an error or underrun occured.
- if ( result == -EPIPE ) {
- snd_pcm_state_t state = snd_pcm_state( handle[0] );
- if ( state == SND_PCM_STATE_XRUN ) {
- apiInfo->xrun[0] = true;
- result = snd_pcm_prepare( handle[0] );
- if ( result < 0 ) {
- errorStream_ << "RtApiAlsa::callbackEvent: error preparing device after underrun, " << snd_strerror( result ) << ".";
- errorText_ = errorStream_.str();
- }
- else
- errorText_ = "RtApiAlsa::callbackEvent: audio write error, underrun.";
- }
- else {
- errorStream_ << "RtApiAlsa::callbackEvent: error, current state is " << snd_pcm_state_name( state ) << ", " << snd_strerror( result ) << ".";
- errorText_ = errorStream_.str();
- }
- }
- else {
- errorStream_ << "RtApiAlsa::callbackEvent: audio write error, " << snd_strerror( result ) << ".";
- errorText_ = errorStream_.str();
- }
- error( RtAudioError::WARNING );
- goto unlock;
- }
-
- // Check stream latency
- result = snd_pcm_delay( handle[0], &frames );
- if ( result == 0 && frames > 0 ) stream_.latency[0] = frames;
- }
-
- unlock:
- MUTEX_UNLOCK( &stream_.mutex );
-
- RtApi::tickStreamTime();
- if ( doStopStream == 1 ) this->stopStream();
-}
-
-static void *alsaCallbackHandler( void *ptr )
-{
- CallbackInfo *info = (CallbackInfo *) ptr;
- RtApiAlsa *object = (RtApiAlsa *) info->object;
- bool *isRunning = &info->isRunning;
-
-#ifdef SCHED_RR // Undefined with some OSes (eg: NetBSD 1.6.x with GNU Pthread)
- if ( info->doRealtime ) {
- pthread_t tID = pthread_self(); // ID of this thread
- sched_param prio = { info->priority }; // scheduling priority of thread
- pthread_setschedparam( tID, SCHED_RR, &prio );
- }
-#endif
-
- while ( *isRunning == true ) {
- pthread_testcancel();
- object->callbackEvent();
- }
-
- pthread_exit( NULL );
-}
-
-//******************** End of __LINUX_ALSA__ *********************//
-#endif
-
-#if defined(__LINUX_PULSE__)
-
-// Code written by Peter Meerwald, pmeerw@pmeerw.net
-// and Tristan Matthews.
-
-#include <pulse/error.h>
-#include <pulse/simple.h>
-#include <cstdio>
-
-static const unsigned int SUPPORTED_SAMPLERATES[] = { 8000, 16000, 22050, 32000,
- 44100, 48000, 96000, 0};
-
-struct rtaudio_pa_format_mapping_t {
- RtAudioFormat rtaudio_format;
- pa_sample_format_t pa_format;
-};
-
-static const rtaudio_pa_format_mapping_t supported_sampleformats[] = {
- {RTAUDIO_SINT16, PA_SAMPLE_S16LE},
- {RTAUDIO_SINT32, PA_SAMPLE_S32LE},
- {RTAUDIO_FLOAT32, PA_SAMPLE_FLOAT32LE},
- {0, PA_SAMPLE_INVALID}};
-
-struct PulseAudioHandle {
- pa_simple *s_play;
- pa_simple *s_rec;
- pthread_t thread;
- pthread_cond_t runnable_cv;
- bool runnable;
- PulseAudioHandle() : s_play(0), s_rec(0), runnable(false) { }
-};
-
-RtApiPulse::~RtApiPulse()
-{
- if ( stream_.state != STREAM_CLOSED )
- closeStream();
-}
-
-unsigned int RtApiPulse::getDeviceCount( void )
-{
- return 1;
-}
-
-RtAudio::DeviceInfo RtApiPulse::getDeviceInfo( unsigned int /*device*/ )
-{
- RtAudio::DeviceInfo info;
- info.probed = true;
- info.name = "PulseAudio";
- info.outputChannels = 2;
- info.inputChannels = 2;
- info.duplexChannels = 2;
- info.isDefaultOutput = true;
- info.isDefaultInput = true;
-
- for ( const unsigned int *sr = SUPPORTED_SAMPLERATES; *sr; ++sr )
- info.sampleRates.push_back( *sr );
-
- info.preferredSampleRate = 48000;
- info.nativeFormats = RTAUDIO_SINT16 | RTAUDIO_SINT32 | RTAUDIO_FLOAT32;
-
- return info;
-}
-
-static void *pulseaudio_callback( void * user )
-{
- CallbackInfo *cbi = static_cast<CallbackInfo *>( user );
- RtApiPulse *context = static_cast<RtApiPulse *>( cbi->object );
- volatile bool *isRunning = &cbi->isRunning;
-
- while ( *isRunning ) {
- pthread_testcancel();
- context->callbackEvent();
- }
-
- pthread_exit( NULL );
-}
-
-void RtApiPulse::closeStream( void )
-{
- PulseAudioHandle *pah = static_cast<PulseAudioHandle *>( stream_.apiHandle );
-
- stream_.callbackInfo.isRunning = false;
- if ( pah ) {
- MUTEX_LOCK( &stream_.mutex );
- if ( stream_.state == STREAM_STOPPED ) {
- pah->runnable = true;
- pthread_cond_signal( &pah->runnable_cv );
- }
- MUTEX_UNLOCK( &stream_.mutex );
-
- pthread_join( pah->thread, 0 );
- if ( pah->s_play ) {
- pa_simple_flush( pah->s_play, NULL );
- pa_simple_free( pah->s_play );
- }
- if ( pah->s_rec )
- pa_simple_free( pah->s_rec );
-
- pthread_cond_destroy( &pah->runnable_cv );
- delete pah;
- stream_.apiHandle = 0;
- }
-
- if ( stream_.userBuffer[0] ) {
- free( stream_.userBuffer[0] );
- stream_.userBuffer[0] = 0;
- }
- if ( stream_.userBuffer[1] ) {
- free( stream_.userBuffer[1] );
- stream_.userBuffer[1] = 0;
- }
-
- stream_.state = STREAM_CLOSED;
- stream_.mode = UNINITIALIZED;
-}
-
-void RtApiPulse::callbackEvent( void )
-{
- PulseAudioHandle *pah = static_cast<PulseAudioHandle *>( stream_.apiHandle );
-
- if ( stream_.state == STREAM_STOPPED ) {
- MUTEX_LOCK( &stream_.mutex );
- while ( !pah->runnable )
- pthread_cond_wait( &pah->runnable_cv, &stream_.mutex );
-
- if ( stream_.state != STREAM_RUNNING ) {
- MUTEX_UNLOCK( &stream_.mutex );
- return;
- }
- MUTEX_UNLOCK( &stream_.mutex );
- }
-
- if ( stream_.state == STREAM_CLOSED ) {
- errorText_ = "RtApiPulse::callbackEvent(): the stream is closed ... "
- "this shouldn't happen!";
- error( RtAudioError::WARNING );
- return;
- }
-
- RtAudioCallback callback = (RtAudioCallback) stream_.callbackInfo.callback;
- double streamTime = getStreamTime();
- RtAudioStreamStatus status = 0;
- int doStopStream = callback( stream_.userBuffer[OUTPUT], stream_.userBuffer[INPUT],
- stream_.bufferSize, streamTime, status,
- stream_.callbackInfo.userData );
-
- if ( doStopStream == 2 ) {
- abortStream();
- return;
- }
-
- MUTEX_LOCK( &stream_.mutex );
- void *pulse_in = stream_.doConvertBuffer[INPUT] ? stream_.deviceBuffer : stream_.userBuffer[INPUT];
- void *pulse_out = stream_.doConvertBuffer[OUTPUT] ? stream_.deviceBuffer : stream_.userBuffer[OUTPUT];
-
- if ( stream_.state != STREAM_RUNNING )
- goto unlock;
-
- int pa_error;
- size_t bytes;
- if (stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
- if ( stream_.doConvertBuffer[OUTPUT] ) {
- convertBuffer( stream_.deviceBuffer,
- stream_.userBuffer[OUTPUT],
- stream_.convertInfo[OUTPUT] );
- bytes = stream_.nDeviceChannels[OUTPUT] * stream_.bufferSize *
- formatBytes( stream_.deviceFormat[OUTPUT] );
- } else
- bytes = stream_.nUserChannels[OUTPUT] * stream_.bufferSize *
- formatBytes( stream_.userFormat );
-
- if ( pa_simple_write( pah->s_play, pulse_out, bytes, &pa_error ) < 0 ) {
- errorStream_ << "RtApiPulse::callbackEvent: audio write error, " <<
- pa_strerror( pa_error ) << ".";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- }
- }
-
- if ( stream_.mode == INPUT || stream_.mode == DUPLEX) {
- if ( stream_.doConvertBuffer[INPUT] )
- bytes = stream_.nDeviceChannels[INPUT] * stream_.bufferSize *
- formatBytes( stream_.deviceFormat[INPUT] );
- else
- bytes = stream_.nUserChannels[INPUT] * stream_.bufferSize *
- formatBytes( stream_.userFormat );
-
- if ( pa_simple_read( pah->s_rec, pulse_in, bytes, &pa_error ) < 0 ) {
- errorStream_ << "RtApiPulse::callbackEvent: audio read error, " <<
- pa_strerror( pa_error ) << ".";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- }
- if ( stream_.doConvertBuffer[INPUT] ) {
- convertBuffer( stream_.userBuffer[INPUT],
- stream_.deviceBuffer,
- stream_.convertInfo[INPUT] );
- }
- }
-
- unlock:
- MUTEX_UNLOCK( &stream_.mutex );
- RtApi::tickStreamTime();
-
- if ( doStopStream == 1 )
- stopStream();
-}
-
-void RtApiPulse::startStream( void )
-{
- PulseAudioHandle *pah = static_cast<PulseAudioHandle *>( stream_.apiHandle );
-
- if ( stream_.state == STREAM_CLOSED ) {
- errorText_ = "RtApiPulse::startStream(): the stream is not open!";
- error( RtAudioError::INVALID_USE );
- return;
- }
- if ( stream_.state == STREAM_RUNNING ) {
- errorText_ = "RtApiPulse::startStream(): the stream is already running!";
- error( RtAudioError::WARNING );
- return;
- }
-
- MUTEX_LOCK( &stream_.mutex );
-
- stream_.state = STREAM_RUNNING;
-
- pah->runnable = true;
- pthread_cond_signal( &pah->runnable_cv );
- MUTEX_UNLOCK( &stream_.mutex );
-}
-
-void RtApiPulse::stopStream( void )
-{
- PulseAudioHandle *pah = static_cast<PulseAudioHandle *>( stream_.apiHandle );
-
- if ( stream_.state == STREAM_CLOSED ) {
- errorText_ = "RtApiPulse::stopStream(): the stream is not open!";
- error( RtAudioError::INVALID_USE );
- return;
- }
- if ( stream_.state == STREAM_STOPPED ) {
- errorText_ = "RtApiPulse::stopStream(): the stream is already stopped!";
- error( RtAudioError::WARNING );
- return;
- }
-
- stream_.state = STREAM_STOPPED;
- MUTEX_LOCK( &stream_.mutex );
-
- if ( pah && pah->s_play ) {
- int pa_error;
- if ( pa_simple_drain( pah->s_play, &pa_error ) < 0 ) {
- errorStream_ << "RtApiPulse::stopStream: error draining output device, " <<
- pa_strerror( pa_error ) << ".";
- errorText_ = errorStream_.str();
- MUTEX_UNLOCK( &stream_.mutex );
- error( RtAudioError::SYSTEM_ERROR );
- return;
- }
- }
-
- stream_.state = STREAM_STOPPED;
- MUTEX_UNLOCK( &stream_.mutex );
-}
-
-void RtApiPulse::abortStream( void )
-{
- PulseAudioHandle *pah = static_cast<PulseAudioHandle*>( stream_.apiHandle );
-
- if ( stream_.state == STREAM_CLOSED ) {
- errorText_ = "RtApiPulse::abortStream(): the stream is not open!";
- error( RtAudioError::INVALID_USE );
- return;
- }
- if ( stream_.state == STREAM_STOPPED ) {
- errorText_ = "RtApiPulse::abortStream(): the stream is already stopped!";
- error( RtAudioError::WARNING );
- return;
- }
-
- stream_.state = STREAM_STOPPED;
- MUTEX_LOCK( &stream_.mutex );
-
- if ( pah && pah->s_play ) {
- int pa_error;
- if ( pa_simple_flush( pah->s_play, &pa_error ) < 0 ) {
- errorStream_ << "RtApiPulse::abortStream: error flushing output device, " <<
- pa_strerror( pa_error ) << ".";
- errorText_ = errorStream_.str();
- MUTEX_UNLOCK( &stream_.mutex );
- error( RtAudioError::SYSTEM_ERROR );
- return;
- }
- }
-
- stream_.state = STREAM_STOPPED;
- MUTEX_UNLOCK( &stream_.mutex );
-}
-
-bool RtApiPulse::probeDeviceOpen( unsigned int device, StreamMode mode,
- unsigned int channels, unsigned int firstChannel,
- unsigned int sampleRate, RtAudioFormat format,
- unsigned int *bufferSize, RtAudio::StreamOptions *options )
-{
- PulseAudioHandle *pah = 0;
- unsigned long bufferBytes = 0;
- pa_sample_spec ss;
-
- if ( device != 0 ) return false;
- if ( mode != INPUT && mode != OUTPUT ) return false;
- if ( channels != 1 && channels != 2 ) {
- errorText_ = "RtApiPulse::probeDeviceOpen: unsupported number of channels.";
- return false;
- }
- ss.channels = channels;
-
- if ( firstChannel != 0 ) return false;
-
- bool sr_found = false;
- for ( const unsigned int *sr = SUPPORTED_SAMPLERATES; *sr; ++sr ) {
- if ( sampleRate == *sr ) {
- sr_found = true;
- stream_.sampleRate = sampleRate;
- ss.rate = sampleRate;
- break;
- }
- }
- if ( !sr_found ) {
- errorText_ = "RtApiPulse::probeDeviceOpen: unsupported sample rate.";
- return false;
- }
-
- bool sf_found = 0;
- for ( const rtaudio_pa_format_mapping_t *sf = supported_sampleformats;
- sf->rtaudio_format && sf->pa_format != PA_SAMPLE_INVALID; ++sf ) {
- if ( format == sf->rtaudio_format ) {
- sf_found = true;
- stream_.userFormat = sf->rtaudio_format;
- stream_.deviceFormat[mode] = stream_.userFormat;
- ss.format = sf->pa_format;
- break;
- }
- }
- if ( !sf_found ) { // Use internal data format conversion.
- stream_.userFormat = format;
- stream_.deviceFormat[mode] = RTAUDIO_FLOAT32;
- ss.format = PA_SAMPLE_FLOAT32LE;
- }
-
- // Set other stream parameters.
- if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) stream_.userInterleaved = false;
- else stream_.userInterleaved = true;
- stream_.deviceInterleaved[mode] = true;
- stream_.nBuffers = 1;
- stream_.doByteSwap[mode] = false;
- stream_.nUserChannels[mode] = channels;
- stream_.nDeviceChannels[mode] = channels + firstChannel;
- stream_.channelOffset[mode] = 0;
- std::string streamName = "RtAudio";
-
- // Set flags for buffer conversion.
- stream_.doConvertBuffer[mode] = false;
- if ( stream_.userFormat != stream_.deviceFormat[mode] )
- stream_.doConvertBuffer[mode] = true;
- if ( stream_.nUserChannels[mode] < stream_.nDeviceChannels[mode] )
- stream_.doConvertBuffer[mode] = true;
-
- // Allocate necessary internal buffers.
- bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat );
- stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 );
- if ( stream_.userBuffer[mode] == NULL ) {
- errorText_ = "RtApiPulse::probeDeviceOpen: error allocating user buffer memory.";
- goto error;
- }
- stream_.bufferSize = *bufferSize;
-
- if ( stream_.doConvertBuffer[mode] ) {
-
- bool makeBuffer = true;
- bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] );
- if ( mode == INPUT ) {
- if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) {
- unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] );
- if ( bufferBytes <= bytesOut ) makeBuffer = false;
- }
- }
-
- if ( makeBuffer ) {
- bufferBytes *= *bufferSize;
- if ( stream_.deviceBuffer ) free( stream_.deviceBuffer );
- stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 );
- if ( stream_.deviceBuffer == NULL ) {
- errorText_ = "RtApiPulse::probeDeviceOpen: error allocating device buffer memory.";
- goto error;
- }
- }
- }
-
- stream_.device[mode] = device;
-
- // Setup the buffer conversion information structure.
- if ( stream_.doConvertBuffer[mode] ) setConvertInfo( mode, firstChannel );
-
- if ( !stream_.apiHandle ) {
- PulseAudioHandle *pah = new PulseAudioHandle;
- if ( !pah ) {
- errorText_ = "RtApiPulse::probeDeviceOpen: error allocating memory for handle.";
- goto error;
- }
-
- stream_.apiHandle = pah;
- if ( pthread_cond_init( &pah->runnable_cv, NULL ) != 0 ) {
- errorText_ = "RtApiPulse::probeDeviceOpen: error creating condition variable.";
- goto error;
- }
- }
- pah = static_cast<PulseAudioHandle *>( stream_.apiHandle );
-
- int error;
- if ( options && !options->streamName.empty() ) streamName = options->streamName;
- switch ( mode ) {
- case INPUT:
- pa_buffer_attr buffer_attr;
- buffer_attr.fragsize = bufferBytes;
- buffer_attr.maxlength = -1;
-
- pah->s_rec = pa_simple_new( NULL, streamName.c_str(), PA_STREAM_RECORD, NULL, "Record", &ss, NULL, &buffer_attr, &error );
- if ( !pah->s_rec ) {
- errorText_ = "RtApiPulse::probeDeviceOpen: error connecting input to PulseAudio server.";
- goto error;
- }
- break;
- case OUTPUT:
- pah->s_play = pa_simple_new( NULL, streamName.c_str(), PA_STREAM_PLAYBACK, NULL, "Playback", &ss, NULL, NULL, &error );
- if ( !pah->s_play ) {
- errorText_ = "RtApiPulse::probeDeviceOpen: error connecting output to PulseAudio server.";
- goto error;
- }
- break;
- default:
- goto error;
- }
-
- if ( stream_.mode == UNINITIALIZED )
- stream_.mode = mode;
- else if ( stream_.mode == mode )
- goto error;
- else
- stream_.mode = DUPLEX;
-
- if ( !stream_.callbackInfo.isRunning ) {
- stream_.callbackInfo.object = this;
- stream_.callbackInfo.isRunning = true;
- if ( pthread_create( &pah->thread, NULL, pulseaudio_callback, (void *)&stream_.callbackInfo) != 0 ) {
- errorText_ = "RtApiPulse::probeDeviceOpen: error creating thread.";
- goto error;
- }
- }
-
- stream_.state = STREAM_STOPPED;
- return true;
-
- error:
- if ( pah && stream_.callbackInfo.isRunning ) {
- pthread_cond_destroy( &pah->runnable_cv );
- delete pah;
- stream_.apiHandle = 0;
- }
-
- for ( int i=0; i<2; i++ ) {
- if ( stream_.userBuffer[i] ) {
- free( stream_.userBuffer[i] );
- stream_.userBuffer[i] = 0;
- }
- }
-
- if ( stream_.deviceBuffer ) {
- free( stream_.deviceBuffer );
- stream_.deviceBuffer = 0;
- }
-
- return FAILURE;
-}
-
-//******************** End of __LINUX_PULSE__ *********************//
-#endif
-
-#if defined(__LINUX_OSS__)
-
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/soundcard.h>
-#include <errno.h>
-#include <math.h>
-
-static void *ossCallbackHandler(void * ptr);
-
-// A structure to hold various information related to the OSS API
-// implementation.
-struct OssHandle {
- int id[2]; // device ids
- bool xrun[2];
- bool triggered;
- pthread_cond_t runnable;
-
- OssHandle()
- :triggered(false) { id[0] = 0; id[1] = 0; xrun[0] = false; xrun[1] = false; }
-};
-
-RtApiOss :: RtApiOss()
-{
- // Nothing to do here.
-}
-
-RtApiOss :: ~RtApiOss()
-{
- if ( stream_.state != STREAM_CLOSED ) closeStream();
-}
-
-unsigned int RtApiOss :: getDeviceCount( void )
-{
- int mixerfd = open( "/dev/mixer", O_RDWR, 0 );
- if ( mixerfd == -1 ) {
- errorText_ = "RtApiOss::getDeviceCount: error opening '/dev/mixer'.";
- error( RtAudioError::WARNING );
- return 0;
- }
-
- oss_sysinfo sysinfo;
- if ( ioctl( mixerfd, SNDCTL_SYSINFO, &sysinfo ) == -1 ) {
- close( mixerfd );
- errorText_ = "RtApiOss::getDeviceCount: error getting sysinfo, OSS version >= 4.0 is required.";
- error( RtAudioError::WARNING );
- return 0;
- }
-
- close( mixerfd );
- return sysinfo.numaudios;
-}
-
-RtAudio::DeviceInfo RtApiOss :: getDeviceInfo( unsigned int device )
-{
- RtAudio::DeviceInfo info;
- info.probed = false;
-
- int mixerfd = open( "/dev/mixer", O_RDWR, 0 );
- if ( mixerfd == -1 ) {
- errorText_ = "RtApiOss::getDeviceInfo: error opening '/dev/mixer'.";
- error( RtAudioError::WARNING );
- return info;
- }
-
- oss_sysinfo sysinfo;
- int result = ioctl( mixerfd, SNDCTL_SYSINFO, &sysinfo );
- if ( result == -1 ) {
- close( mixerfd );
- errorText_ = "RtApiOss::getDeviceInfo: error getting sysinfo, OSS version >= 4.0 is required.";
- error( RtAudioError::WARNING );
- return info;
- }
-
- unsigned nDevices = sysinfo.numaudios;
- if ( nDevices == 0 ) {
- close( mixerfd );
- errorText_ = "RtApiOss::getDeviceInfo: no devices found!";
- error( RtAudioError::INVALID_USE );
- return info;
- }
-
- if ( device >= nDevices ) {
- close( mixerfd );
- errorText_ = "RtApiOss::getDeviceInfo: device ID is invalid!";
- error( RtAudioError::INVALID_USE );
- return info;
- }
-
- oss_audioinfo ainfo;
- ainfo.dev = device;
- result = ioctl( mixerfd, SNDCTL_AUDIOINFO, &ainfo );
- close( mixerfd );
- if ( result == -1 ) {
- errorStream_ << "RtApiOss::getDeviceInfo: error getting device (" << ainfo.name << ") info.";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- return info;
- }
-
- // Probe channels
- if ( ainfo.caps & PCM_CAP_OUTPUT ) info.outputChannels = ainfo.max_channels;
- if ( ainfo.caps & PCM_CAP_INPUT ) info.inputChannels = ainfo.max_channels;
- if ( ainfo.caps & PCM_CAP_DUPLEX ) {
- if ( info.outputChannels > 0 && info.inputChannels > 0 && ainfo.caps & PCM_CAP_DUPLEX )
- info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels;
- }
-
- // Probe data formats ... do for input
- unsigned long mask = ainfo.iformats;
- if ( mask & AFMT_S16_LE || mask & AFMT_S16_BE )
- info.nativeFormats |= RTAUDIO_SINT16;
- if ( mask & AFMT_S8 )
- info.nativeFormats |= RTAUDIO_SINT8;
- if ( mask & AFMT_S32_LE || mask & AFMT_S32_BE )
- info.nativeFormats |= RTAUDIO_SINT32;
- if ( mask & AFMT_FLOAT )
- info.nativeFormats |= RTAUDIO_FLOAT32;
- if ( mask & AFMT_S24_LE || mask & AFMT_S24_BE )
- info.nativeFormats |= RTAUDIO_SINT24;
-
- // Check that we have at least one supported format
- if ( info.nativeFormats == 0 ) {
- errorStream_ << "RtApiOss::getDeviceInfo: device (" << ainfo.name << ") data format not supported by RtAudio.";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- return info;
- }
-
- // Probe the supported sample rates.
- info.sampleRates.clear();
- if ( ainfo.nrates ) {
- for ( unsigned int i=0; i<ainfo.nrates; i++ ) {
- for ( unsigned int k=0; k<MAX_SAMPLE_RATES; k++ ) {
- if ( ainfo.rates[i] == SAMPLE_RATES[k] ) {
- info.sampleRates.push_back( SAMPLE_RATES[k] );
-
- if ( !info.preferredSampleRate || ( SAMPLE_RATES[k] <= 48000 && SAMPLE_RATES[k] > info.preferredSampleRate ) )
- info.preferredSampleRate = SAMPLE_RATES[k];
-
- break;
- }
- }
- }
- }
- else {
- // Check min and max rate values;
- for ( unsigned int k=0; k<MAX_SAMPLE_RATES; k++ ) {
- if ( ainfo.min_rate <= (int) SAMPLE_RATES[k] && ainfo.max_rate >= (int) SAMPLE_RATES[k] ) {
- info.sampleRates.push_back( SAMPLE_RATES[k] );
-
- if ( !info.preferredSampleRate || ( SAMPLE_RATES[k] <= 48000 && SAMPLE_RATES[k] > info.preferredSampleRate ) )
- info.preferredSampleRate = SAMPLE_RATES[k];
- }
- }
- }
-
- if ( info.sampleRates.size() == 0 ) {
- errorStream_ << "RtApiOss::getDeviceInfo: no supported sample rates found for device (" << ainfo.name << ").";
- errorText_ = errorStream_.str();
- error( RtAudioError::WARNING );
- }
- else {
- info.probed = true;
- info.name = ainfo.name;
- }
-
- return info;
-}
-
-
-bool RtApiOss :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,
- unsigned int firstChannel, unsigned int sampleRate,
- RtAudioFormat format, unsigned int *bufferSize,
- RtAudio::StreamOptions *options )
-{
- int mixerfd = open( "/dev/mixer", O_RDWR, 0 );
- if ( mixerfd == -1 ) {
- errorText_ = "RtApiOss::probeDeviceOpen: error opening '/dev/mixer'.";
- return FAILURE;
- }
-
- oss_sysinfo sysinfo;
- int result = ioctl( mixerfd, SNDCTL_SYSINFO, &sysinfo );
- if ( result == -1 ) {
- close( mixerfd );
- errorText_ = "RtApiOss::probeDeviceOpen: error getting sysinfo, OSS version >= 4.0 is required.";
- return FAILURE;
- }
-
- unsigned nDevices = sysinfo.numaudios;
- if ( nDevices == 0 ) {
- // This should not happen because a check is made before this function is called.
- close( mixerfd );
- errorText_ = "RtApiOss::probeDeviceOpen: no devices found!";
- return FAILURE;
- }
-
- if ( device >= nDevices ) {
- // This should not happen because a check is made before this function is called.
- close( mixerfd );
- errorText_ = "RtApiOss::probeDeviceOpen: device ID is invalid!";
- return FAILURE;
- }
-
- oss_audioinfo ainfo;
- ainfo.dev = device;
- result = ioctl( mixerfd, SNDCTL_AUDIOINFO, &ainfo );
- close( mixerfd );
- if ( result == -1 ) {
- errorStream_ << "RtApiOss::getDeviceInfo: error getting device (" << ainfo.name << ") info.";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- // Check if device supports input or output
- if ( ( mode == OUTPUT && !( ainfo.caps & PCM_CAP_OUTPUT ) ) ||
- ( mode == INPUT && !( ainfo.caps & PCM_CAP_INPUT ) ) ) {
- if ( mode == OUTPUT )
- errorStream_ << "RtApiOss::probeDeviceOpen: device (" << ainfo.name << ") does not support output.";
- else
- errorStream_ << "RtApiOss::probeDeviceOpen: device (" << ainfo.name << ") does not support input.";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- int flags = 0;
- OssHandle *handle = (OssHandle *) stream_.apiHandle;
- if ( mode == OUTPUT )
- flags |= O_WRONLY;
- else { // mode == INPUT
- if (stream_.mode == OUTPUT && stream_.device[0] == device) {
- // We just set the same device for playback ... close and reopen for duplex (OSS only).
- close( handle->id[0] );
- handle->id[0] = 0;
- if ( !( ainfo.caps & PCM_CAP_DUPLEX ) ) {
- errorStream_ << "RtApiOss::probeDeviceOpen: device (" << ainfo.name << ") does not support duplex mode.";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
- // Check that the number previously set channels is the same.
- if ( stream_.nUserChannels[0] != channels ) {
- errorStream_ << "RtApiOss::probeDeviceOpen: input/output channels must be equal for OSS duplex device (" << ainfo.name << ").";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
- flags |= O_RDWR;
- }
- else
- flags |= O_RDONLY;
- }
-
- // Set exclusive access if specified.
- if ( options && options->flags & RTAUDIO_HOG_DEVICE ) flags |= O_EXCL;
-
- // Try to open the device.
- int fd;
- fd = open( ainfo.devnode, flags, 0 );
- if ( fd == -1 ) {
- if ( errno == EBUSY )
- errorStream_ << "RtApiOss::probeDeviceOpen: device (" << ainfo.name << ") is busy.";
- else
- errorStream_ << "RtApiOss::probeDeviceOpen: error opening device (" << ainfo.name << ").";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- // For duplex operation, specifically set this mode (this doesn't seem to work).
- /*
- if ( flags | O_RDWR ) {
- result = ioctl( fd, SNDCTL_DSP_SETDUPLEX, NULL );
- if ( result == -1) {
- errorStream_ << "RtApiOss::probeDeviceOpen: error setting duplex mode for device (" << ainfo.name << ").";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
- }
- */
-
- // Check the device channel support.
- stream_.nUserChannels[mode] = channels;
- if ( ainfo.max_channels < (int)(channels + firstChannel) ) {
- close( fd );
- errorStream_ << "RtApiOss::probeDeviceOpen: the device (" << ainfo.name << ") does not support requested channel parameters.";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- // Set the number of channels.
- int deviceChannels = channels + firstChannel;
- result = ioctl( fd, SNDCTL_DSP_CHANNELS, &deviceChannels );
- if ( result == -1 || deviceChannels < (int)(channels + firstChannel) ) {
- close( fd );
- errorStream_ << "RtApiOss::probeDeviceOpen: error setting channel parameters on device (" << ainfo.name << ").";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
- stream_.nDeviceChannels[mode] = deviceChannels;
-
- // Get the data format mask
- int mask;
- result = ioctl( fd, SNDCTL_DSP_GETFMTS, &mask );
- if ( result == -1 ) {
- close( fd );
- errorStream_ << "RtApiOss::probeDeviceOpen: error getting device (" << ainfo.name << ") data formats.";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- // Determine how to set the device format.
- stream_.userFormat = format;
- int deviceFormat = -1;
- stream_.doByteSwap[mode] = false;
- if ( format == RTAUDIO_SINT8 ) {
- if ( mask & AFMT_S8 ) {
- deviceFormat = AFMT_S8;
- stream_.deviceFormat[mode] = RTAUDIO_SINT8;
- }
- }
- else if ( format == RTAUDIO_SINT16 ) {
- if ( mask & AFMT_S16_NE ) {
- deviceFormat = AFMT_S16_NE;
- stream_.deviceFormat[mode] = RTAUDIO_SINT16;
- }
- else if ( mask & AFMT_S16_OE ) {
- deviceFormat = AFMT_S16_OE;
- stream_.deviceFormat[mode] = RTAUDIO_SINT16;
- stream_.doByteSwap[mode] = true;
- }
- }
- else if ( format == RTAUDIO_SINT24 ) {
- if ( mask & AFMT_S24_NE ) {
- deviceFormat = AFMT_S24_NE;
- stream_.deviceFormat[mode] = RTAUDIO_SINT24;
- }
- else if ( mask & AFMT_S24_OE ) {
- deviceFormat = AFMT_S24_OE;
- stream_.deviceFormat[mode] = RTAUDIO_SINT24;
- stream_.doByteSwap[mode] = true;
- }
- }
- else if ( format == RTAUDIO_SINT32 ) {
- if ( mask & AFMT_S32_NE ) {
- deviceFormat = AFMT_S32_NE;
- stream_.deviceFormat[mode] = RTAUDIO_SINT32;
- }
- else if ( mask & AFMT_S32_OE ) {
- deviceFormat = AFMT_S32_OE;
- stream_.deviceFormat[mode] = RTAUDIO_SINT32;
- stream_.doByteSwap[mode] = true;
- }
- }
-
- if ( deviceFormat == -1 ) {
- // The user requested format is not natively supported by the device.
- if ( mask & AFMT_S16_NE ) {
- deviceFormat = AFMT_S16_NE;
- stream_.deviceFormat[mode] = RTAUDIO_SINT16;
- }
- else if ( mask & AFMT_S32_NE ) {
- deviceFormat = AFMT_S32_NE;
- stream_.deviceFormat[mode] = RTAUDIO_SINT32;
- }
- else if ( mask & AFMT_S24_NE ) {
- deviceFormat = AFMT_S24_NE;
- stream_.deviceFormat[mode] = RTAUDIO_SINT24;
- }
- else if ( mask & AFMT_S16_OE ) {
- deviceFormat = AFMT_S16_OE;
- stream_.deviceFormat[mode] = RTAUDIO_SINT16;
- stream_.doByteSwap[mode] = true;
- }
- else if ( mask & AFMT_S32_OE ) {
- deviceFormat = AFMT_S32_OE;
- stream_.deviceFormat[mode] = RTAUDIO_SINT32;
- stream_.doByteSwap[mode] = true;
- }
- else if ( mask & AFMT_S24_OE ) {
- deviceFormat = AFMT_S24_OE;
- stream_.deviceFormat[mode] = RTAUDIO_SINT24;
- stream_.doByteSwap[mode] = true;
- }
- else if ( mask & AFMT_S8) {
- deviceFormat = AFMT_S8;
- stream_.deviceFormat[mode] = RTAUDIO_SINT8;
- }
- }
-
- if ( stream_.deviceFormat[mode] == 0 ) {
- // This really shouldn't happen ...
- close( fd );
- errorStream_ << "RtApiOss::probeDeviceOpen: device (" << ainfo.name << ") data format not supported by RtAudio.";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- // Set the data format.
- int temp = deviceFormat;
- result = ioctl( fd, SNDCTL_DSP_SETFMT, &deviceFormat );
- if ( result == -1 || deviceFormat != temp ) {
- close( fd );
- errorStream_ << "RtApiOss::probeDeviceOpen: error setting data format on device (" << ainfo.name << ").";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- // Attempt to set the buffer size. According to OSS, the minimum
- // number of buffers is two. The supposed minimum buffer size is 16
- // bytes, so that will be our lower bound. The argument to this
- // call is in the form 0xMMMMSSSS (hex), where the buffer size (in
- // bytes) is given as 2^SSSS and the number of buffers as 2^MMMM.
- // We'll check the actual value used near the end of the setup
- // procedure.
- int ossBufferBytes = *bufferSize * formatBytes( stream_.deviceFormat[mode] ) * deviceChannels;
- if ( ossBufferBytes < 16 ) ossBufferBytes = 16;
- int buffers = 0;
- if ( options ) buffers = options->numberOfBuffers;
- if ( options && options->flags & RTAUDIO_MINIMIZE_LATENCY ) buffers = 2;
- if ( buffers < 2 ) buffers = 3;
- temp = ((int) buffers << 16) + (int)( log10( (double)ossBufferBytes ) / log10( 2.0 ) );
- result = ioctl( fd, SNDCTL_DSP_SETFRAGMENT, &temp );
- if ( result == -1 ) {
- close( fd );
- errorStream_ << "RtApiOss::probeDeviceOpen: error setting buffer size on device (" << ainfo.name << ").";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
- stream_.nBuffers = buffers;
-
- // Save buffer size (in sample frames).
- *bufferSize = ossBufferBytes / ( formatBytes(stream_.deviceFormat[mode]) * deviceChannels );
- stream_.bufferSize = *bufferSize;
-
- // Set the sample rate.
- int srate = sampleRate;
- result = ioctl( fd, SNDCTL_DSP_SPEED, &srate );
- if ( result == -1 ) {
- close( fd );
- errorStream_ << "RtApiOss::probeDeviceOpen: error setting sample rate (" << sampleRate << ") on device (" << ainfo.name << ").";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
-
- // Verify the sample rate setup worked.
- if ( abs( srate - sampleRate ) > 100 ) {
- close( fd );
- errorStream_ << "RtApiOss::probeDeviceOpen: device (" << ainfo.name << ") does not support sample rate (" << sampleRate << ").";
- errorText_ = errorStream_.str();
- return FAILURE;
- }
- stream_.sampleRate = sampleRate;
-
- if ( mode == INPUT && stream_.mode == OUTPUT && stream_.device[0] == device) {
- // We're doing duplex setup here.
- stream_.deviceFormat[0] = stream_.deviceFormat[1];
- stream_.nDeviceChannels[0] = deviceChannels;
- }
-
- // Set interleaving parameters.
- stream_.userInterleaved = true;
- stream_.deviceInterleaved[mode] = true;
- if ( options && options->flags & RTAUDIO_NONINTERLEAVED )
- stream_.userInterleaved = false;
-
- // Set flags for buffer conversion
- stream_.doConvertBuffer[mode] = false;
- if ( stream_.userFormat != stream_.deviceFormat[mode] )
- stream_.doConvertBuffer[mode] = true;
- if ( stream_.nUserChannels[mode] < stream_.nDeviceChannels[mode] )
- stream_.doConvertBuffer[mode] = true;
- if ( stream_.userInterleaved != stream_.deviceInterleaved[mode] &&
- stream_.nUserChannels[mode] > 1 )
- stream_.doConvertBuffer[mode] = true;
-
- // Allocate the stream handles if necessary and then save.
- if ( stream_.apiHandle == 0 ) {
- try {
- handle = new OssHandle;
- }
- catch ( std::bad_alloc& ) {
- errorText_ = "RtApiOss::probeDeviceOpen: error allocating OssHandle memory.";
- goto error;
- }
-
- if ( pthread_cond_init( &handle->runnable, NULL ) ) {
- errorText_ = "RtApiOss::probeDeviceOpen: error initializing pthread condition variable.";
- goto error;
- }
-
- stream_.apiHandle = (void *) handle;
- }
- else {
- handle = (OssHandle *) stream_.apiHandle;
- }
- handle->id[mode] = fd;
-
- // Allocate necessary internal buffers.
- unsigned long bufferBytes;
- bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat );
- stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 );
- if ( stream_.userBuffer[mode] == NULL ) {
- errorText_ = "RtApiOss::probeDeviceOpen: error allocating user buffer memory.";
- goto error;
- }
-
- if ( stream_.doConvertBuffer[mode] ) {
-
- bool makeBuffer = true;
- bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] );
- if ( mode == INPUT ) {
- if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) {
- unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] );
- if ( bufferBytes <= bytesOut ) makeBuffer = false;
- }
- }
-
- if ( makeBuffer ) {
- bufferBytes *= *bufferSize;
- if ( stream_.deviceBuffer ) free( stream_.deviceBuffer );
- stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 );
- if ( stream_.deviceBuffer == NULL ) {
- errorText_ = "RtApiOss::probeDeviceOpen: error allocating device buffer memory.";
- goto error;
- }
- }
- }
-
- stream_.device[mode] = device;
- stream_.state = STREAM_STOPPED;
-
- // Setup the buffer conversion information structure.
- if ( stream_.doConvertBuffer[mode] ) setConvertInfo( mode, firstChannel );
-
- // Setup thread if necessary.
- if ( stream_.mode == OUTPUT && mode == INPUT ) {
- // We had already set up an output stream.
- stream_.mode = DUPLEX;
- if ( stream_.device[0] == device ) handle->id[0] = fd;
- }
- else {
- stream_.mode = mode;
-
- // Setup callback thread.
- stream_.callbackInfo.object = (void *) this;
-
- // Set the thread attributes for joinable and realtime scheduling
- // priority. The higher priority will only take affect if the
- // program is run as root or suid.
- pthread_attr_t attr;
- pthread_attr_init( &attr );
- pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE );
-#ifdef SCHED_RR // Undefined with some OSes (eg: NetBSD 1.6.x with GNU Pthread)
- if ( options && options->flags & RTAUDIO_SCHEDULE_REALTIME ) {
- struct sched_param param;
- int priority = options->priority;
- int min = sched_get_priority_min( SCHED_RR );
- int max = sched_get_priority_max( SCHED_RR );
- if ( priority < min ) priority = min;
- else if ( priority > max ) priority = max;
- param.sched_priority = priority;
- pthread_attr_setschedparam( &attr, &param );
- pthread_attr_setschedpolicy( &attr, SCHED_RR );
- }
- else
- pthread_attr_setschedpolicy( &attr, SCHED_OTHER );
-#else
- pthread_attr_setschedpolicy( &attr, SCHED_OTHER );
-#endif
-
- stream_.callbackInfo.isRunning = true;
- result = pthread_create( &stream_.callbackInfo.thread, &attr, ossCallbackHandler, &stream_.callbackInfo );
- pthread_attr_destroy( &attr );
- if ( result ) {
- stream_.callbackInfo.isRunning = false;
- errorText_ = "RtApiOss::error creating callback thread!";
- goto error;
- }
- }
-
- return SUCCESS;
-
- error:
- if ( handle ) {
- pthread_cond_destroy( &handle->runnable );
- if ( handle->id[0] ) close( handle->id[0] );
- if ( handle->id[1] ) close( handle->id[1] );
- delete handle;
- stream_.apiHandle = 0;
- }
-
- for ( int i=0; i<2; i++ ) {
- if ( stream_.userBuffer[i] ) {
- free( stream_.userBuffer[i] );
- stream_.userBuffer[i] = 0;
- }
- }
-
- if ( stream_.deviceBuffer ) {
- free( stream_.deviceBuffer );
- stream_.deviceBuffer = 0;
- }
-
- return FAILURE;
-}
-
-void RtApiOss :: closeStream()
-{
- if ( stream_.state == STREAM_CLOSED ) {
- errorText_ = "RtApiOss::closeStream(): no open stream to close!";
- error( RtAudioError::WARNING );
- return;
- }
-
- OssHandle *handle = (OssHandle *) stream_.apiHandle;
- stream_.callbackInfo.isRunning = false;
- MUTEX_LOCK( &stream_.mutex );
- if ( stream_.state == STREAM_STOPPED )
- pthread_cond_signal( &handle->runnable );
- MUTEX_UNLOCK( &stream_.mutex );
- pthread_join( stream_.callbackInfo.thread, NULL );
-
- if ( stream_.state == STREAM_RUNNING ) {
- if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX )
- ioctl( handle->id[0], SNDCTL_DSP_HALT, 0 );
- else
- ioctl( handle->id[1], SNDCTL_DSP_HALT, 0 );
- stream_.state = STREAM_STOPPED;
- }
-
- if ( handle ) {
- pthread_cond_destroy( &handle->runnable );
- if ( handle->id[0] ) close( handle->id[0] );
- if ( handle->id[1] ) close( handle->id[1] );
- delete handle;
- stream_.apiHandle = 0;
- }
-
- for ( int i=0; i<2; i++ ) {
- if ( stream_.userBuffer[i] ) {
- free( stream_.userBuffer[i] );
- stream_.userBuffer[i] = 0;
- }
- }
-
- if ( stream_.deviceBuffer ) {
- free( stream_.deviceBuffer );
- stream_.deviceBuffer = 0;
- }
-
- stream_.mode = UNINITIALIZED;
- stream_.state = STREAM_CLOSED;
-}
-
-void RtApiOss :: startStream()
-{
- verifyStream();
- if ( stream_.state == STREAM_RUNNING ) {
- errorText_ = "RtApiOss::startStream(): the stream is already running!";
- error( RtAudioError::WARNING );
- return;
- }
-
- MUTEX_LOCK( &stream_.mutex );
-
- stream_.state = STREAM_RUNNING;
-
- // No need to do anything else here ... OSS automatically starts
- // when fed samples.
-
- MUTEX_UNLOCK( &stream_.mutex );
-
- OssHandle *handle = (OssHandle *) stream_.apiHandle;
- pthread_cond_signal( &handle->runnable );
-}
-
-void RtApiOss :: stopStream()
-{
- verifyStream();
- if ( stream_.state == STREAM_STOPPED ) {
- errorText_ = "RtApiOss::stopStream(): the stream is already stopped!";
- error( RtAudioError::WARNING );
- return;
- }
-
- MUTEX_LOCK( &stream_.mutex );
-
- // The state might change while waiting on a mutex.
- if ( stream_.state == STREAM_STOPPED ) {
- MUTEX_UNLOCK( &stream_.mutex );
- return;
- }
-
- int result = 0;
- OssHandle *handle = (OssHandle *) stream_.apiHandle;
- if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
-
- // Flush the output with zeros a few times.
- char *buffer;
- int samples;
- RtAudioFormat format;
-
- if ( stream_.doConvertBuffer[0] ) {
- buffer = stream_.deviceBuffer;
- samples = stream_.bufferSize * stream_.nDeviceChannels[0];
- format = stream_.deviceFormat[0];
- }
- else {
- buffer = stream_.userBuffer[0];
- samples = stream_.bufferSize * stream_.nUserChannels[0];
- format = stream_.userFormat;
- }
-
- memset( buffer, 0, samples * formatBytes(format) );
- for ( unsigned int i=0; i<stream_.nBuffers+1; i++ ) {
- result = write( handle->id[0], buffer, samples * formatBytes(format) );
- if ( result == -1 ) {
- errorText_ = "RtApiOss::stopStream: audio write error.";
- error( RtAudioError::WARNING );
- }
- }
-
- result = ioctl( handle->id[0], SNDCTL_DSP_HALT, 0 );
- if ( result == -1 ) {
- errorStream_ << "RtApiOss::stopStream: system error stopping callback procedure on device (" << stream_.device[0] << ").";
- errorText_ = errorStream_.str();
- goto unlock;
- }
- handle->triggered = false;
- }
-
- if ( stream_.mode == INPUT || ( stream_.mode == DUPLEX && handle->id[0] != handle->id[1] ) ) {
- result = ioctl( handle->id[1], SNDCTL_DSP_HALT, 0 );
- if ( result == -1 ) {
- errorStream_ << "RtApiOss::stopStream: system error stopping input callback procedure on device (" << stream_.device[0] << ").";
- errorText_ = errorStream_.str();
- goto unlock;
- }
- }
-
- unlock:
- stream_.state = STREAM_STOPPED;
- MUTEX_UNLOCK( &stream_.mutex );
-
- if ( result != -1 ) return;
- error( RtAudioError::SYSTEM_ERROR );
-}
-
-void RtApiOss :: abortStream()
-{
- verifyStream();
- if ( stream_.state == STREAM_STOPPED ) {
- errorText_ = "RtApiOss::abortStream(): the stream is already stopped!";
- error( RtAudioError::WARNING );
- return;
- }
-
- MUTEX_LOCK( &stream_.mutex );
-
- // The state might change while waiting on a mutex.
- if ( stream_.state == STREAM_STOPPED ) {
- MUTEX_UNLOCK( &stream_.mutex );
- return;
- }
-
- int result = 0;
- OssHandle *handle = (OssHandle *) stream_.apiHandle;
- if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
- result = ioctl( handle->id[0], SNDCTL_DSP_HALT, 0 );
- if ( result == -1 ) {
- errorStream_ << "RtApiOss::abortStream: system error stopping callback procedure on device (" << stream_.device[0] << ").";
- errorText_ = errorStream_.str();
- goto unlock;
- }
- handle->triggered = false;
- }
-
- if ( stream_.mode == INPUT || ( stream_.mode == DUPLEX && handle->id[0] != handle->id[1] ) ) {
- result = ioctl( handle->id[1], SNDCTL_DSP_HALT, 0 );
- if ( result == -1 ) {
- errorStream_ << "RtApiOss::abortStream: system error stopping input callback procedure on device (" << stream_.device[0] << ").";
- errorText_ = errorStream_.str();
- goto unlock;
- }
- }
-
- unlock:
- stream_.state = STREAM_STOPPED;
- MUTEX_UNLOCK( &stream_.mutex );
-
- if ( result != -1 ) return;
- error( RtAudioError::SYSTEM_ERROR );
-}
-
-void RtApiOss :: callbackEvent()
-{
- OssHandle *handle = (OssHandle *) stream_.apiHandle;
- if ( stream_.state == STREAM_STOPPED ) {
- MUTEX_LOCK( &stream_.mutex );
- pthread_cond_wait( &handle->runnable, &stream_.mutex );
- if ( stream_.state != STREAM_RUNNING ) {
- MUTEX_UNLOCK( &stream_.mutex );
- return;
- }
- MUTEX_UNLOCK( &stream_.mutex );
- }
-
- if ( stream_.state == STREAM_CLOSED ) {
- errorText_ = "RtApiOss::callbackEvent(): the stream is closed ... this shouldn't happen!";
- error( RtAudioError::WARNING );
- return;
- }
-
- // Invoke user callback to get fresh output data.
- int doStopStream = 0;
- RtAudioCallback callback = (RtAudioCallback) stream_.callbackInfo.callback;
- double streamTime = getStreamTime();
- RtAudioStreamStatus status = 0;
- if ( stream_.mode != INPUT && handle->xrun[0] == true ) {
- status |= RTAUDIO_OUTPUT_UNDERFLOW;
- handle->xrun[0] = false;
- }
- if ( stream_.mode != OUTPUT && handle->xrun[1] == true ) {
- status |= RTAUDIO_INPUT_OVERFLOW;
- handle->xrun[1] = false;
- }
- doStopStream = callback( stream_.userBuffer[0], stream_.userBuffer[1],
- stream_.bufferSize, streamTime, status, stream_.callbackInfo.userData );
- if ( doStopStream == 2 ) {
- this->abortStream();
- return;
- }
-
- MUTEX_LOCK( &stream_.mutex );
-
- // The state might change while waiting on a mutex.
- if ( stream_.state == STREAM_STOPPED ) goto unlock;
-
- int result;
- char *buffer;
- int samples;
- RtAudioFormat format;
-
- if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
-
- // Setup parameters and do buffer conversion if necessary.
- if ( stream_.doConvertBuffer[0] ) {
- buffer = stream_.deviceBuffer;
- convertBuffer( buffer, stream_.userBuffer[0], stream_.convertInfo[0] );
- samples = stream_.bufferSize * stream_.nDeviceChannels[0];
- format = stream_.deviceFormat[0];
- }
- else {
- buffer = stream_.userBuffer[0];
- samples = stream_.bufferSize * stream_.nUserChannels[0];
- format = stream_.userFormat;
- }
-
- // Do byte swapping if necessary.
- if ( stream_.doByteSwap[0] )
- byteSwapBuffer( buffer, samples, format );
-
- if ( stream_.mode == DUPLEX && handle->triggered == false ) {
- int trig = 0;
- ioctl( handle->id[0], SNDCTL_DSP_SETTRIGGER, &trig );
- result = write( handle->id[0], buffer, samples * formatBytes(format) );
- trig = PCM_ENABLE_INPUT|PCM_ENABLE_OUTPUT;
- ioctl( handle->id[0], SNDCTL_DSP_SETTRIGGER, &trig );
- handle->triggered = true;
- }
- else
- // Write samples to device.
- result = write( handle->id[0], buffer, samples * formatBytes(format) );
-
- if ( result == -1 ) {
- // We'll assume this is an underrun, though there isn't a
- // specific means for determining that.
- handle->xrun[0] = true;
- errorText_ = "RtApiOss::callbackEvent: audio write error.";
- error( RtAudioError::WARNING );
- // Continue on to input section.
- }
- }
-
- if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) {
-
- // Setup parameters.
- if ( stream_.doConvertBuffer[1] ) {
- buffer = stream_.deviceBuffer;
- samples = stream_.bufferSize * stream_.nDeviceChannels[1];
- format = stream_.deviceFormat[1];
- }
- else {
- buffer = stream_.userBuffer[1];
- samples = stream_.bufferSize * stream_.nUserChannels[1];
- format = stream_.userFormat;
- }
-
- // Read samples from device.
- result = read( handle->id[1], buffer, samples * formatBytes(format) );
-
- if ( result == -1 ) {
- // We'll assume this is an overrun, though there isn't a
- // specific means for determining that.
- handle->xrun[1] = true;
- errorText_ = "RtApiOss::callbackEvent: audio read error.";
- error( RtAudioError::WARNING );
- goto unlock;
- }
-
- // Do byte swapping if necessary.
- if ( stream_.doByteSwap[1] )
- byteSwapBuffer( buffer, samples, format );
-
- // Do buffer conversion if necessary.
- if ( stream_.doConvertBuffer[1] )
- convertBuffer( stream_.userBuffer[1], stream_.deviceBuffer, stream_.convertInfo[1] );
- }
-
- unlock:
- MUTEX_UNLOCK( &stream_.mutex );
-
- RtApi::tickStreamTime();
- if ( doStopStream == 1 ) this->stopStream();
-}
-
-static void *ossCallbackHandler( void *ptr )
-{
- CallbackInfo *info = (CallbackInfo *) ptr;
- RtApiOss *object = (RtApiOss *) info->object;
- bool *isRunning = &info->isRunning;
-
- while ( *isRunning == true ) {
- pthread_testcancel();
- object->callbackEvent();
- }
-
- pthread_exit( NULL );
-}
-
-//******************** End of __LINUX_OSS__ *********************//
-#endif
-
-
-// *************************************************** //
-//
-// Protected common (OS-independent) RtAudio methods.
-//
-// *************************************************** //
-
-// This method can be modified to control the behavior of error
-// message printing.
-void RtApi :: error( RtAudioError::Type type )
-{
- errorStream_.str(""); // clear the ostringstream
-
- RtAudioErrorCallback errorCallback = (RtAudioErrorCallback) stream_.callbackInfo.errorCallback;
- if ( errorCallback ) {
- // abortStream() can generate new error messages. Ignore them. Just keep original one.
-
- if ( firstErrorOccurred_ )
- return;
-
- firstErrorOccurred_ = true;
- const std::string errorMessage = errorText_;
-
- if ( type != RtAudioError::WARNING && stream_.state != STREAM_STOPPED) {
- stream_.callbackInfo.isRunning = false; // exit from the thread
- abortStream();
- }
-
- errorCallback( type, errorMessage );
- firstErrorOccurred_ = false;
- return;
- }
-
- if ( type == RtAudioError::WARNING && showWarnings_ == true )
- std::cerr << '\n' << errorText_ << "\n\n";
- else if ( type != RtAudioError::WARNING )
- throw( RtAudioError( errorText_, type ) );
-}
-
-void RtApi :: verifyStream()
-{
- if ( stream_.state == STREAM_CLOSED ) {
- errorText_ = "RtApi:: a stream is not open!";
- error( RtAudioError::INVALID_USE );
- }
-}
-
-void RtApi :: clearStreamInfo()
-{
- stream_.mode = UNINITIALIZED;
- stream_.state = STREAM_CLOSED;
- stream_.sampleRate = 0;
- stream_.bufferSize = 0;
- stream_.nBuffers = 0;
- stream_.userFormat = 0;
- stream_.userInterleaved = true;
- stream_.streamTime = 0.0;
- stream_.apiHandle = 0;
- stream_.deviceBuffer = 0;
- stream_.callbackInfo.callback = 0;
- stream_.callbackInfo.userData = 0;
- stream_.callbackInfo.isRunning = false;
- stream_.callbackInfo.errorCallback = 0;
- for ( int i=0; i<2; i++ ) {
- stream_.device[i] = 11111;
- stream_.doConvertBuffer[i] = false;
- stream_.deviceInterleaved[i] = true;
- stream_.doByteSwap[i] = false;
- stream_.nUserChannels[i] = 0;
- stream_.nDeviceChannels[i] = 0;
- stream_.channelOffset[i] = 0;
- stream_.deviceFormat[i] = 0;
- stream_.latency[i] = 0;
- stream_.userBuffer[i] = 0;
- stream_.convertInfo[i].channels = 0;
- stream_.convertInfo[i].inJump = 0;
- stream_.convertInfo[i].outJump = 0;
- stream_.convertInfo[i].inFormat = 0;
- stream_.convertInfo[i].outFormat = 0;
- stream_.convertInfo[i].inOffset.clear();
- stream_.convertInfo[i].outOffset.clear();
- }
-}
-
-unsigned int RtApi :: formatBytes( RtAudioFormat format )
-{
- if ( format == RTAUDIO_SINT16 )
- return 2;
- else if ( format == RTAUDIO_SINT32 || format == RTAUDIO_FLOAT32 )
- return 4;
- else if ( format == RTAUDIO_FLOAT64 )
- return 8;
- else if ( format == RTAUDIO_SINT24 )
- return 3;
- else if ( format == RTAUDIO_SINT8 )
- return 1;
-
- errorText_ = "RtApi::formatBytes: undefined format.";
- error( RtAudioError::WARNING );
-
- return 0;
-}
-
-void RtApi :: setConvertInfo( StreamMode mode, unsigned int firstChannel )
-{
- if ( mode == INPUT ) { // convert device to user buffer
- stream_.convertInfo[mode].inJump = stream_.nDeviceChannels[1];
- stream_.convertInfo[mode].outJump = stream_.nUserChannels[1];
- stream_.convertInfo[mode].inFormat = stream_.deviceFormat[1];
- stream_.convertInfo[mode].outFormat = stream_.userFormat;
- }
- else { // convert user to device buffer
- stream_.convertInfo[mode].inJump = stream_.nUserChannels[0];
- stream_.convertInfo[mode].outJump = stream_.nDeviceChannels[0];
- stream_.convertInfo[mode].inFormat = stream_.userFormat;
- stream_.convertInfo[mode].outFormat = stream_.deviceFormat[0];
- }
-
- if ( stream_.convertInfo[mode].inJump < stream_.convertInfo[mode].outJump )
- stream_.convertInfo[mode].channels = stream_.convertInfo[mode].inJump;
- else
- stream_.convertInfo[mode].channels = stream_.convertInfo[mode].outJump;
-
- // Set up the interleave/deinterleave offsets.
- if ( stream_.deviceInterleaved[mode] != stream_.userInterleaved ) {
- if ( ( mode == OUTPUT && stream_.deviceInterleaved[mode] ) ||
- ( mode == INPUT && stream_.userInterleaved ) ) {
- for ( int k=0; k<stream_.convertInfo[mode].channels; k++ ) {
- stream_.convertInfo[mode].inOffset.push_back( k * stream_.bufferSize );
- stream_.convertInfo[mode].outOffset.push_back( k );
- stream_.convertInfo[mode].inJump = 1;
- }
- }
- else {
- for ( int k=0; k<stream_.convertInfo[mode].channels; k++ ) {
- stream_.convertInfo[mode].inOffset.push_back( k );
- stream_.convertInfo[mode].outOffset.push_back( k * stream_.bufferSize );
- stream_.convertInfo[mode].outJump = 1;
- }
- }
- }
- else { // no (de)interleaving
- if ( stream_.userInterleaved ) {
- for ( int k=0; k<stream_.convertInfo[mode].channels; k++ ) {
- stream_.convertInfo[mode].inOffset.push_back( k );
- stream_.convertInfo[mode].outOffset.push_back( k );
- }
- }
- else {
- for ( int k=0; k<stream_.convertInfo[mode].channels; k++ ) {
- stream_.convertInfo[mode].inOffset.push_back( k * stream_.bufferSize );
- stream_.convertInfo[mode].outOffset.push_back( k * stream_.bufferSize );
- stream_.convertInfo[mode].inJump = 1;
- stream_.convertInfo[mode].outJump = 1;
- }
- }
- }
-
- // Add channel offset.
- if ( firstChannel > 0 ) {
- if ( stream_.deviceInterleaved[mode] ) {
- if ( mode == OUTPUT ) {
- for ( int k=0; k<stream_.convertInfo[mode].channels; k++ )
- stream_.convertInfo[mode].outOffset[k] += firstChannel;
- }
- else {
- for ( int k=0; k<stream_.convertInfo[mode].channels; k++ )
- stream_.convertInfo[mode].inOffset[k] += firstChannel;
- }
- }
- else {
- if ( mode == OUTPUT ) {
- for ( int k=0; k<stream_.convertInfo[mode].channels; k++ )
- stream_.convertInfo[mode].outOffset[k] += ( firstChannel * stream_.bufferSize );
- }
- else {
- for ( int k=0; k<stream_.convertInfo[mode].channels; k++ )
- stream_.convertInfo[mode].inOffset[k] += ( firstChannel * stream_.bufferSize );
- }
- }
- }
-}
-
-void RtApi :: convertBuffer( char *outBuffer, char *inBuffer, ConvertInfo &info )
-{
- // This function does format conversion, input/output channel compensation, and
- // data interleaving/deinterleaving. 24-bit integers are assumed to occupy
- // the lower three bytes of a 32-bit integer.
-
- // Clear our device buffer when in/out duplex device channels are different
- if ( outBuffer == stream_.deviceBuffer && stream_.mode == DUPLEX &&
- ( stream_.nDeviceChannels[0] < stream_.nDeviceChannels[1] ) )
- memset( outBuffer, 0, stream_.bufferSize * info.outJump * formatBytes( info.outFormat ) );
-
- int j;
- if (info.outFormat == RTAUDIO_FLOAT64) {
- Float64 scale;
- Float64 *out = (Float64 *)outBuffer;
-
- if (info.inFormat == RTAUDIO_SINT8) {
- signed char *in = (signed char *)inBuffer;
- scale = 1.0 / 127.5;
- for (unsigned int i=0; i<stream_.bufferSize; i++) {
- for (j=0; j<info.channels; j++) {
- out[info.outOffset[j]] = (Float64) in[info.inOffset[j]];
- out[info.outOffset[j]] += 0.5;
- out[info.outOffset[j]] *= scale;
- }
- in += info.inJump;
- out += info.outJump;
- }
- }
- else if (info.inFormat == RTAUDIO_SINT16) {
- Int16 *in = (Int16 *)inBuffer;
- scale = 1.0 / 32767.5;
- for (unsigned int i=0; i<stream_.bufferSize; i++) {
- for (j=0; j<info.channels; j++) {
- out[info.outOffset[j]] = (Float64) in[info.inOffset[j]];
- out[info.outOffset[j]] += 0.5;
- out[info.outOffset[j]] *= scale;
- }
- in += info.inJump;
- out += info.outJump;
- }
- }
- else if (info.inFormat == RTAUDIO_SINT24) {
- Int24 *in = (Int24 *)inBuffer;
- scale = 1.0 / 8388607.5;
- for (unsigned int i=0; i<stream_.bufferSize; i++) {
- for (j=0; j<info.channels; j++) {
- out[info.outOffset[j]] = (Float64) (in[info.inOffset[j]].asInt());
- out[info.outOffset[j]] += 0.5;
- out[info.outOffset[j]] *= scale;
- }
- in += info.inJump;
- out += info.outJump;
- }
- }
- else if (info.inFormat == RTAUDIO_SINT32) {
- Int32 *in = (Int32 *)inBuffer;
- scale = 1.0 / 2147483647.5;
- for (unsigned int i=0; i<stream_.bufferSize; i++) {
- for (j=0; j<info.channels; j++) {
- out[info.outOffset[j]] = (Float64) in[info.inOffset[j]];
- out[info.outOffset[j]] += 0.5;
- out[info.outOffset[j]] *= scale;
- }
- in += info.inJump;
- out += info.outJump;
- }
- }
- else if (info.inFormat == RTAUDIO_FLOAT32) {
- Float32 *in = (Float32 *)inBuffer;
- for (unsigned int i=0; i<stream_.bufferSize; i++) {
- for (j=0; j<info.channels; j++) {
- out[info.outOffset[j]] = (Float64) in[info.inOffset[j]];
- }
- in += info.inJump;
- out += info.outJump;
- }
- }
- else if (info.inFormat == RTAUDIO_FLOAT64) {
- // Channel compensation and/or (de)interleaving only.
- Float64 *in = (Float64 *)inBuffer;
- for (unsigned int i=0; i<stream_.bufferSize; i++) {
- for (j=0; j<info.channels; j++) {
- out[info.outOffset[j]] = in[info.inOffset[j]];
- }
- in += info.inJump;
- out += info.outJump;
- }
- }
- }
- else if (info.outFormat == RTAUDIO_FLOAT32) {
- Float32 scale;
- Float32 *out = (Float32 *)outBuffer;
-
- if (info.inFormat == RTAUDIO_SINT8) {
- signed char *in = (signed char *)inBuffer;
- scale = (Float32) ( 1.0 / 127.5 );
- for (unsigned int i=0; i<stream_.bufferSize; i++) {
- for (j=0; j<info.channels; j++) {
- out[info.outOffset[j]] = (Float32) in[info.inOffset[j]];
- out[info.outOffset[j]] += 0.5;
- out[info.outOffset[j]] *= scale;
- }
- in += info.inJump;
- out += info.outJump;
- }
- }
- else if (info.inFormat == RTAUDIO_SINT16) {
- Int16 *in = (Int16 *)inBuffer;
- scale = (Float32) ( 1.0 / 32767.5 );
- for (unsigned int i=0; i<stream_.bufferSize; i++) {
- for (j=0; j<info.channels; j++) {
- out[info.outOffset[j]] = (Float32) in[info.inOffset[j]];
- out[info.outOffset[j]] += 0.5;
- out[info.outOffset[j]] *= scale;
- }
- in += info.inJump;
- out += info.outJump;
- }
- }
- else if (info.inFormat == RTAUDIO_SINT24) {
- Int24 *in = (Int24 *)inBuffer;
- scale = (Float32) ( 1.0 / 8388607.5 );
- for (unsigned int i=0; i<stream_.bufferSize; i++) {
- for (j=0; j<info.channels; j++) {
- out[info.outOffset[j]] = (Float32) (in[info.inOffset[j]].asInt());
- out[info.outOffset[j]] += 0.5;
- out[info.outOffset[j]] *= scale;
- }
- in += info.inJump;
- out += info.outJump;
- }
- }
- else if (info.inFormat == RTAUDIO_SINT32) {
- Int32 *in = (Int32 *)inBuffer;
- scale = (Float32) ( 1.0 / 2147483647.5 );
- for (unsigned int i=0; i<stream_.bufferSize; i++) {
- for (j=0; j<info.channels; j++) {
- out[info.outOffset[j]] = (Float32) in[info.inOffset[j]];
- out[info.outOffset[j]] += 0.5;
- out[info.outOffset[j]] *= scale;
- }
- in += info.inJump;
- out += info.outJump;
- }
- }
- else if (info.inFormat == RTAUDIO_FLOAT32) {
- // Channel compensation and/or (de)interleaving only.
- Float32 *in = (Float32 *)inBuffer;
- for (unsigned int i=0; i<stream_.bufferSize; i++) {
- for (j=0; j<info.channels; j++) {
- out[info.outOffset[j]] = in[info.inOffset[j]];
- }
- in += info.inJump;
- out += info.outJump;
- }
- }
- else if (info.inFormat == RTAUDIO_FLOAT64) {
- Float64 *in = (Float64 *)inBuffer;
- for (unsigned int i=0; i<stream_.bufferSize; i++) {
- for (j=0; j<info.channels; j++) {
- out[info.outOffset[j]] = (Float32) in[info.inOffset[j]];
- }
- in += info.inJump;
- out += info.outJump;
- }
- }
- }
- else if (info.outFormat == RTAUDIO_SINT32) {
- Int32 *out = (Int32 *)outBuffer;
- if (info.inFormat == RTAUDIO_SINT8) {
- signed char *in = (signed char *)inBuffer;
- for (unsigned int i=0; i<stream_.bufferSize; i++) {
- for (j=0; j<info.channels; j++) {
- out[info.outOffset[j]] = (Int32) in[info.inOffset[j]];
- out[info.outOffset[j]] <<= 24;
- }
- in += info.inJump;
- out += info.outJump;
- }
- }
- else if (info.inFormat == RTAUDIO_SINT16) {
- Int16 *in = (Int16 *)inBuffer;
- for (unsigned int i=0; i<stream_.bufferSize; i++) {
- for (j=0; j<info.channels; j++) {
- out[info.outOffset[j]] = (Int32) in[info.inOffset[j]];
- out[info.outOffset[j]] <<= 16;
- }
- in += info.inJump;
- out += info.outJump;
- }
- }
- else if (info.inFormat == RTAUDIO_SINT24) {
- Int24 *in = (Int24 *)inBuffer;
- for (unsigned int i=0; i<stream_.bufferSize; i++) {
- for (j=0; j<info.channels; j++) {
- out[info.outOffset[j]] = (Int32) in[info.inOffset[j]].asInt();
- out[info.outOffset[j]] <<= 8;
- }
- in += info.inJump;
- out += info.outJump;
- }
- }
- else if (info.inFormat == RTAUDIO_SINT32) {
- // Channel compensation and/or (de)interleaving only.
- Int32 *in = (Int32 *)inBuffer;
- for (unsigned int i=0; i<stream_.bufferSize; i++) {
- for (j=0; j<info.channels; j++) {
- out[info.outOffset[j]] = in[info.inOffset[j]];
- }
- in += info.inJump;
- out += info.outJump;
- }
- }
- else if (info.inFormat == RTAUDIO_FLOAT32) {
- Float32 *in = (Float32 *)inBuffer;
- for (unsigned int i=0; i<stream_.bufferSize; i++) {
- for (j=0; j<info.channels; j++) {
- out[info.outOffset[j]] = (Int32) (in[info.inOffset[j]] * 2147483647.5 - 0.5);
- }
- in += info.inJump;
- out += info.outJump;
- }
- }
- else if (info.inFormat == RTAUDIO_FLOAT64) {
- Float64 *in = (Float64 *)inBuffer;
- for (unsigned int i=0; i<stream_.bufferSize; i++) {
- for (j=0; j<info.channels; j++) {
- out[info.outOffset[j]] = (Int32) (in[info.inOffset[j]] * 2147483647.5 - 0.5);
- }
- in += info.inJump;
- out += info.outJump;
- }
- }
- }
- else if (info.outFormat == RTAUDIO_SINT24) {
- Int24 *out = (Int24 *)outBuffer;
- if (info.inFormat == RTAUDIO_SINT8) {
- signed char *in = (signed char *)inBuffer;
- for (unsigned int i=0; i<stream_.bufferSize; i++) {
- for (j=0; j<info.channels; j++) {
- out[info.outOffset[j]] = (Int32) (in[info.inOffset[j]] << 16);
- //out[info.outOffset[j]] <<= 16;
- }
- in += info.inJump;
- out += info.outJump;
- }
- }
- else if (info.inFormat == RTAUDIO_SINT16) {
- Int16 *in = (Int16 *)inBuffer;
- for (unsigned int i=0; i<stream_.bufferSize; i++) {
- for (j=0; j<info.channels; j++) {
- out[info.outOffset[j]] = (Int32) (in[info.inOffset[j]] << 8);
- //out[info.outOffset[j]] <<= 8;
- }
- in += info.inJump;
- out += info.outJump;
- }
- }
- else if (info.inFormat == RTAUDIO_SINT24) {
- // Channel compensation and/or (de)interleaving only.
- Int24 *in = (Int24 *)inBuffer;
- for (unsigned int i=0; i<stream_.bufferSize; i++) {
- for (j=0; j<info.channels; j++) {
- out[info.outOffset[j]] = in[info.inOffset[j]];
- }
- in += info.inJump;
- out += info.outJump;
- }
- }
- else if (info.inFormat == RTAUDIO_SINT32) {
- Int32 *in = (Int32 *)inBuffer;
- for (unsigned int i=0; i<stream_.bufferSize; i++) {
- for (j=0; j<info.channels; j++) {
- out[info.outOffset[j]] = (Int32) (in[info.inOffset[j]] >> 8);
- //out[info.outOffset[j]] >>= 8;
- }
- in += info.inJump;
- out += info.outJump;
- }
- }
- else if (info.inFormat == RTAUDIO_FLOAT32) {
- Float32 *in = (Float32 *)inBuffer;
- for (unsigned int i=0; i<stream_.bufferSize; i++) {
- for (j=0; j<info.channels; j++) {
- out[info.outOffset[j]] = (Int32) (in[info.inOffset[j]] * 8388607.5 - 0.5);
- }
- in += info.inJump;
- out += info.outJump;
- }
- }
- else if (info.inFormat == RTAUDIO_FLOAT64) {
- Float64 *in = (Float64 *)inBuffer;
- for (unsigned int i=0; i<stream_.bufferSize; i++) {
- for (j=0; j<info.channels; j++) {
- out[info.outOffset[j]] = (Int32) (in[info.inOffset[j]] * 8388607.5 - 0.5);
- }
- in += info.inJump;
- out += info.outJump;
- }
- }
- }
- else if (info.outFormat == RTAUDIO_SINT16) {
- Int16 *out = (Int16 *)outBuffer;
- if (info.inFormat == RTAUDIO_SINT8) {
- signed char *in = (signed char *)inBuffer;
- for (unsigned int i=0; i<stream_.bufferSize; i++) {
- for (j=0; j<info.channels; j++) {
- out[info.outOffset[j]] = (Int16) in[info.inOffset[j]];
- out[info.outOffset[j]] <<= 8;
- }
- in += info.inJump;
- out += info.outJump;
- }
- }
- else if (info.inFormat == RTAUDIO_SINT16) {
- // Channel compensation and/or (de)interleaving only.
- Int16 *in = (Int16 *)inBuffer;
- for (unsigned int i=0; i<stream_.bufferSize; i++) {
- for (j=0; j<info.channels; j++) {
- out[info.outOffset[j]] = in[info.inOffset[j]];
- }
- in += info.inJump;
- out += info.outJump;
- }
- }
- else if (info.inFormat == RTAUDIO_SINT24) {
- Int24 *in = (Int24 *)inBuffer;
- for (unsigned int i=0; i<stream_.bufferSize; i++) {
- for (j=0; j<info.channels; j++) {
- out[info.outOffset[j]] = (Int16) (in[info.inOffset[j]].asInt() >> 8);
- }
- in += info.inJump;
- out += info.outJump;
- }
- }
- else if (info.inFormat == RTAUDIO_SINT32) {
- Int32 *in = (Int32 *)inBuffer;
- for (unsigned int i=0; i<stream_.bufferSize; i++) {
- for (j=0; j<info.channels; j++) {
- out[info.outOffset[j]] = (Int16) ((in[info.inOffset[j]] >> 16) & 0x0000ffff);
- }
- in += info.inJump;
- out += info.outJump;
- }
- }
- else if (info.inFormat == RTAUDIO_FLOAT32) {
- Float32 *in = (Float32 *)inBuffer;
- for (unsigned int i=0; i<stream_.bufferSize; i++) {
- for (j=0; j<info.channels; j++) {
- out[info.outOffset[j]] = (Int16) (in[info.inOffset[j]] * 32767.5 - 0.5);
- }
- in += info.inJump;
- out += info.outJump;
- }
- }
- else if (info.inFormat == RTAUDIO_FLOAT64) {
- Float64 *in = (Float64 *)inBuffer;
- for (unsigned int i=0; i<stream_.bufferSize; i++) {
- for (j=0; j<info.channels; j++) {
- out[info.outOffset[j]] = (Int16) (in[info.inOffset[j]] * 32767.5 - 0.5);
- }
- in += info.inJump;
- out += info.outJump;
- }
- }
- }
- else if (info.outFormat == RTAUDIO_SINT8) {
- signed char *out = (signed char *)outBuffer;
- if (info.inFormat == RTAUDIO_SINT8) {
- // Channel compensation and/or (de)interleaving only.
- signed char *in = (signed char *)inBuffer;
- for (unsigned int i=0; i<stream_.bufferSize; i++) {
- for (j=0; j<info.channels; j++) {
- out[info.outOffset[j]] = in[info.inOffset[j]];
- }
- in += info.inJump;
- out += info.outJump;
- }
- }
- if (info.inFormat == RTAUDIO_SINT16) {
- Int16 *in = (Int16 *)inBuffer;
- for (unsigned int i=0; i<stream_.bufferSize; i++) {
- for (j=0; j<info.channels; j++) {
- out[info.outOffset[j]] = (signed char) ((in[info.inOffset[j]] >> 8) & 0x00ff);
- }
- in += info.inJump;
- out += info.outJump;
- }
- }
- else if (info.inFormat == RTAUDIO_SINT24) {
- Int24 *in = (Int24 *)inBuffer;
- for (unsigned int i=0; i<stream_.bufferSize; i++) {
- for (j=0; j<info.channels; j++) {
- out[info.outOffset[j]] = (signed char) (in[info.inOffset[j]].asInt() >> 16);
- }
- in += info.inJump;
- out += info.outJump;
- }
- }
- else if (info.inFormat == RTAUDIO_SINT32) {
- Int32 *in = (Int32 *)inBuffer;
- for (unsigned int i=0; i<stream_.bufferSize; i++) {
- for (j=0; j<info.channels; j++) {
- out[info.outOffset[j]] = (signed char) ((in[info.inOffset[j]] >> 24) & 0x000000ff);
- }
- in += info.inJump;
- out += info.outJump;
- }
- }
- else if (info.inFormat == RTAUDIO_FLOAT32) {
- Float32 *in = (Float32 *)inBuffer;
- for (unsigned int i=0; i<stream_.bufferSize; i++) {
- for (j=0; j<info.channels; j++) {
- out[info.outOffset[j]] = (signed char) (in[info.inOffset[j]] * 127.5 - 0.5);
- }
- in += info.inJump;
- out += info.outJump;
- }
- }
- else if (info.inFormat == RTAUDIO_FLOAT64) {
- Float64 *in = (Float64 *)inBuffer;
- for (unsigned int i=0; i<stream_.bufferSize; i++) {
- for (j=0; j<info.channels; j++) {
- out[info.outOffset[j]] = (signed char) (in[info.inOffset[j]] * 127.5 - 0.5);
- }
- in += info.inJump;
- out += info.outJump;
- }
- }
- }
-}
-
-//static inline uint16_t bswap_16(uint16_t x) { return (x>>8) | (x<<8); }
-//static inline uint32_t bswap_32(uint32_t x) { return (bswap_16(x&0xffff)<<16) | (bswap_16(x>>16)); }
-//static inline uint64_t bswap_64(uint64_t x) { return (((unsigned long long)bswap_32(x&0xffffffffull))<<32) | (bswap_32(x>>32)); }
-
-void RtApi :: byteSwapBuffer( char *buffer, unsigned int samples, RtAudioFormat format )
-{
- char val;
- char *ptr;
-
- ptr = buffer;
- if ( format == RTAUDIO_SINT16 ) {
- for ( unsigned int i=0; i<samples; i++ ) {
- // Swap 1st and 2nd bytes.
- val = *(ptr);
- *(ptr) = *(ptr+1);
- *(ptr+1) = val;
-
- // Increment 2 bytes.
- ptr += 2;
- }
- }
- else if ( format == RTAUDIO_SINT32 ||
- format == RTAUDIO_FLOAT32 ) {
- for ( unsigned int i=0; i<samples; i++ ) {
- // Swap 1st and 4th bytes.
- val = *(ptr);
- *(ptr) = *(ptr+3);
- *(ptr+3) = val;
-
- // Swap 2nd and 3rd bytes.
- ptr += 1;
- val = *(ptr);
- *(ptr) = *(ptr+1);
- *(ptr+1) = val;
-
- // Increment 3 more bytes.
- ptr += 3;
- }
- }
- else if ( format == RTAUDIO_SINT24 ) {
- for ( unsigned int i=0; i<samples; i++ ) {
- // Swap 1st and 3rd bytes.
- val = *(ptr);
- *(ptr) = *(ptr+2);
- *(ptr+2) = val;
-
- // Increment 2 more bytes.
- ptr += 2;
- }
- }
- else if ( format == RTAUDIO_FLOAT64 ) {
- for ( unsigned int i=0; i<samples; i++ ) {
- // Swap 1st and 8th bytes
- val = *(ptr);
- *(ptr) = *(ptr+7);
- *(ptr+7) = val;
-
- // Swap 2nd and 7th bytes
- ptr += 1;
- val = *(ptr);
- *(ptr) = *(ptr+5);
- *(ptr+5) = val;
-
- // Swap 3rd and 6th bytes
- ptr += 1;
- val = *(ptr);
- *(ptr) = *(ptr+3);
- *(ptr+3) = val;
-
- // Swap 4th and 5th bytes
- ptr += 1;
- val = *(ptr);
- *(ptr) = *(ptr+1);
- *(ptr+1) = val;
-
- // Increment 5 more bytes.
- ptr += 5;
- }
- }
-}
-
- // Indentation settings for Vim and Emacs
- //
- // Local Variables:
- // c-basic-offset: 2
- // indent-tabs-mode: nil
- // End:
- //
- // vim: et sts=2 sw=2
-
-#endif // RTAUDIO_ENABLED -GODOT-
diff --git a/thirdparty/rtaudio/RtAudio.h b/thirdparty/rtaudio/RtAudio.h
deleted file mode 100644
index aab109d907..0000000000
--- a/thirdparty/rtaudio/RtAudio.h
+++ /dev/null
@@ -1,1183 +0,0 @@
-// -GODOT- Start
-
-#ifdef RTAUDIO_ENABLED
-
-#if defined(OSX_ENABLED)
- #define __MACOSX_CORE__
-#elif defined(UNIX_ENABLED)
- #define __LINUX_ALSA__
-#elif defined(WINDOWS_ENABLED)
- #if defined(UWP_ENABLED)
- #define __RTAUDIO_DUMMY__
- #else
- #define __WINDOWS_DS__
- #endif
-#endif
-
-// -GODOT- End
-
-/************************************************************************/
-/*! \class RtAudio
- \brief Realtime audio i/o C++ classes.
-
- RtAudio provides a common API (Application Programming Interface)
- for realtime audio input/output across Linux (native ALSA, Jack,
- and OSS), Macintosh OS X (CoreAudio and Jack), and Windows
- (DirectSound, ASIO and WASAPI) operating systems.
-
- RtAudio WWW site: http://www.music.mcgill.ca/~gary/rtaudio/
-
- RtAudio: realtime audio i/o C++ classes
- Copyright (c) 2001-2016 Gary P. Scavone
-
- 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.
-
- Any person wishing to distribute modifications to the Software is
- asked to send the modifications to the original developer so that
- they can be incorporated into the canonical version. This is,
- however, not a binding provision of this license.
-
- 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.
-*/
-/************************************************************************/
-
-/*!
- \file RtAudio.h
- */
-
-#ifndef __RTAUDIO_H
-#define __RTAUDIO_H
-
-#define RTAUDIO_VERSION "4.1.2"
-
-#include <string>
-#include <vector>
-#include <exception>
-#include <iostream>
-
-/*! \typedef typedef unsigned long RtAudioFormat;
- \brief RtAudio data format type.
-
- Support for signed integers and floats. Audio data fed to/from an
- RtAudio stream is assumed to ALWAYS be in host byte order. The
- internal routines will automatically take care of any necessary
- byte-swapping between the host format and the soundcard. Thus,
- endian-ness is not a concern in the following format definitions.
-
- - \e RTAUDIO_SINT8: 8-bit signed integer.
- - \e RTAUDIO_SINT16: 16-bit signed integer.
- - \e RTAUDIO_SINT24: 24-bit signed integer.
- - \e RTAUDIO_SINT32: 32-bit signed integer.
- - \e RTAUDIO_FLOAT32: Normalized between plus/minus 1.0.
- - \e RTAUDIO_FLOAT64: Normalized between plus/minus 1.0.
-*/
-typedef unsigned long RtAudioFormat;
-static const RtAudioFormat RTAUDIO_SINT8 = 0x1; // 8-bit signed integer.
-static const RtAudioFormat RTAUDIO_SINT16 = 0x2; // 16-bit signed integer.
-static const RtAudioFormat RTAUDIO_SINT24 = 0x4; // 24-bit signed integer.
-static const RtAudioFormat RTAUDIO_SINT32 = 0x8; // 32-bit signed integer.
-static const RtAudioFormat RTAUDIO_FLOAT32 = 0x10; // Normalized between plus/minus 1.0.
-static const RtAudioFormat RTAUDIO_FLOAT64 = 0x20; // Normalized between plus/minus 1.0.
-
-/*! \typedef typedef unsigned long RtAudioStreamFlags;
- \brief RtAudio stream option flags.
-
- The following flags can be OR'ed together to allow a client to
- make changes to the default stream behavior:
-
- - \e RTAUDIO_NONINTERLEAVED: Use non-interleaved buffers (default = interleaved).
- - \e RTAUDIO_MINIMIZE_LATENCY: Attempt to set stream parameters for lowest possible latency.
- - \e RTAUDIO_HOG_DEVICE: Attempt grab device for exclusive use.
- - \e RTAUDIO_ALSA_USE_DEFAULT: Use the "default" PCM device (ALSA only).
-
- By default, RtAudio streams pass and receive audio data from the
- client in an interleaved format. By passing the
- RTAUDIO_NONINTERLEAVED flag to the openStream() function, audio
- data will instead be presented in non-interleaved buffers. In
- this case, each buffer argument in the RtAudioCallback function
- will point to a single array of data, with \c nFrames samples for
- each channel concatenated back-to-back. For example, the first
- sample of data for the second channel would be located at index \c
- nFrames (assuming the \c buffer pointer was recast to the correct
- data type for the stream).
-
- Certain audio APIs offer a number of parameters that influence the
- I/O latency of a stream. By default, RtAudio will attempt to set
- these parameters internally for robust (glitch-free) performance
- (though some APIs, like Windows Direct Sound, make this difficult).
- By passing the RTAUDIO_MINIMIZE_LATENCY flag to the openStream()
- function, internal stream settings will be influenced in an attempt
- to minimize stream latency, though possibly at the expense of stream
- performance.
-
- If the RTAUDIO_HOG_DEVICE flag is set, RtAudio will attempt to
- open the input and/or output stream device(s) for exclusive use.
- Note that this is not possible with all supported audio APIs.
-
- If the RTAUDIO_SCHEDULE_REALTIME flag is set, RtAudio will attempt
- to select realtime scheduling (round-robin) for the callback thread.
-
- If the RTAUDIO_ALSA_USE_DEFAULT flag is set, RtAudio will attempt to
- open the "default" PCM device when using the ALSA API. Note that this
- will override any specified input or output device id.
-*/
-typedef unsigned int RtAudioStreamFlags;
-static const RtAudioStreamFlags RTAUDIO_NONINTERLEAVED = 0x1; // Use non-interleaved buffers (default = interleaved).
-static const RtAudioStreamFlags RTAUDIO_MINIMIZE_LATENCY = 0x2; // Attempt to set stream parameters for lowest possible latency.
-static const RtAudioStreamFlags RTAUDIO_HOG_DEVICE = 0x4; // Attempt grab device and prevent use by others.
-static const RtAudioStreamFlags RTAUDIO_SCHEDULE_REALTIME = 0x8; // Try to select realtime scheduling for callback thread.
-static const RtAudioStreamFlags RTAUDIO_ALSA_USE_DEFAULT = 0x10; // Use the "default" PCM device (ALSA only).
-
-/*! \typedef typedef unsigned long RtAudioStreamStatus;
- \brief RtAudio stream status (over- or underflow) flags.
-
- Notification of a stream over- or underflow is indicated by a
- non-zero stream \c status argument in the RtAudioCallback function.
- The stream status can be one of the following two options,
- depending on whether the stream is open for output and/or input:
-
- - \e RTAUDIO_INPUT_OVERFLOW: Input data was discarded because of an overflow condition at the driver.
- - \e RTAUDIO_OUTPUT_UNDERFLOW: The output buffer ran low, likely producing a break in the output sound.
-*/
-typedef unsigned int RtAudioStreamStatus;
-static const RtAudioStreamStatus RTAUDIO_INPUT_OVERFLOW = 0x1; // Input data was discarded because of an overflow condition at the driver.
-static const RtAudioStreamStatus RTAUDIO_OUTPUT_UNDERFLOW = 0x2; // The output buffer ran low, likely causing a gap in the output sound.
-
-//! RtAudio callback function prototype.
-/*!
- All RtAudio clients must create a function of type RtAudioCallback
- to read and/or write data from/to the audio stream. When the
- underlying audio system is ready for new input or output data, this
- function will be invoked.
-
- \param outputBuffer For output (or duplex) streams, the client
- should write \c nFrames of audio sample frames into this
- buffer. This argument should be recast to the datatype
- specified when the stream was opened. For input-only
- streams, this argument will be NULL.
-
- \param inputBuffer For input (or duplex) streams, this buffer will
- hold \c nFrames of input audio sample frames. This
- argument should be recast to the datatype specified when the
- stream was opened. For output-only streams, this argument
- will be NULL.
-
- \param nFrames The number of sample frames of input or output
- data in the buffers. The actual buffer size in bytes is
- dependent on the data type and number of channels in use.
-
- \param streamTime The number of seconds that have elapsed since the
- stream was started.
-
- \param status If non-zero, this argument indicates a data overflow
- or underflow condition for the stream. The particular
- condition can be determined by comparison with the
- RtAudioStreamStatus flags.
-
- \param userData A pointer to optional data provided by the client
- when opening the stream (default = NULL).
-
- To continue normal stream operation, the RtAudioCallback function
- should return a value of zero. To stop the stream and drain the
- output buffer, the function should return a value of one. To abort
- the stream immediately, the client should return a value of two.
- */
-typedef int (*RtAudioCallback)( void *outputBuffer, void *inputBuffer,
- unsigned int nFrames,
- double streamTime,
- RtAudioStreamStatus status,
- void *userData );
-
-/************************************************************************/
-/*! \class RtAudioError
- \brief Exception handling class for RtAudio.
-
- The RtAudioError class is quite simple but it does allow errors to be
- "caught" by RtAudioError::Type. See the RtAudio documentation to know
- which methods can throw an RtAudioError.
-*/
-/************************************************************************/
-
-class RtAudioError : public std::exception
-{
- public:
- //! Defined RtAudioError types.
- enum Type {
- WARNING, /*!< A non-critical error. */
- DEBUG_WARNING, /*!< A non-critical error which might be useful for debugging. */
- UNSPECIFIED, /*!< The default, unspecified error type. */
- NO_DEVICES_FOUND, /*!< No devices found on system. */
- INVALID_DEVICE, /*!< An invalid device ID was specified. */
- MEMORY_ERROR, /*!< An error occured during memory allocation. */
- INVALID_PARAMETER, /*!< An invalid parameter was specified to a function. */
- INVALID_USE, /*!< The function was called incorrectly. */
- DRIVER_ERROR, /*!< A system driver error occured. */
- SYSTEM_ERROR, /*!< A system error occured. */
- THREAD_ERROR /*!< A thread error occured. */
- };
-
- //! The constructor.
- RtAudioError( const std::string& message, Type type = RtAudioError::UNSPECIFIED ) throw() : message_(message), type_(type) {}
-
- //! The destructor.
- virtual ~RtAudioError( void ) throw() {}
-
- //! Prints thrown error message to stderr.
- virtual void printMessage( void ) const throw() { std::cerr << '\n' << message_ << "\n\n"; }
-
- //! Returns the thrown error message type.
- virtual const Type& getType(void) const throw() { return type_; }
-
- //! Returns the thrown error message string.
- virtual const std::string& getMessage(void) const throw() { return message_; }
-
- //! Returns the thrown error message as a c-style string.
- virtual const char* what( void ) const throw() { return message_.c_str(); }
-
- protected:
- std::string message_;
- Type type_;
-};
-
-//! RtAudio error callback function prototype.
-/*!
- \param type Type of error.
- \param errorText Error description.
- */
-typedef void (*RtAudioErrorCallback)( RtAudioError::Type type, const std::string &errorText );
-
-// **************************************************************** //
-//
-// RtAudio class declaration.
-//
-// RtAudio is a "controller" used to select an available audio i/o
-// interface. It presents a common API for the user to call but all
-// functionality is implemented by the class RtApi and its
-// subclasses. RtAudio creates an instance of an RtApi subclass
-// based on the user's API choice. If no choice is made, RtAudio
-// attempts to make a "logical" API selection.
-//
-// **************************************************************** //
-
-class RtApi;
-
-class RtAudio
-{
- public:
-
- //! Audio API specifier arguments.
- enum Api {
- UNSPECIFIED, /*!< Search for a working compiled API. */
- LINUX_ALSA, /*!< The Advanced Linux Sound Architecture API. */
- LINUX_PULSE, /*!< The Linux PulseAudio API. */
- LINUX_OSS, /*!< The Linux Open Sound System API. */
- UNIX_JACK, /*!< The Jack Low-Latency Audio Server API. */
- MACOSX_CORE, /*!< Macintosh OS-X Core Audio API. */
- WINDOWS_WASAPI, /*!< The Microsoft WASAPI API. */
- WINDOWS_ASIO, /*!< The Steinberg Audio Stream I/O API. */
- WINDOWS_DS, /*!< The Microsoft Direct Sound API. */
- RTAUDIO_DUMMY /*!< A compilable but non-functional API. */
- };
-
- //! The public device information structure for returning queried values.
- struct DeviceInfo {
- bool probed; /*!< true if the device capabilities were successfully probed. */
- std::string name; /*!< Character string device identifier. */
- unsigned int outputChannels; /*!< Maximum output channels supported by device. */
- unsigned int inputChannels; /*!< Maximum input channels supported by device. */
- unsigned int duplexChannels; /*!< Maximum simultaneous input/output channels supported by device. */
- bool isDefaultOutput; /*!< true if this is the default output device. */
- bool isDefaultInput; /*!< true if this is the default input device. */
- std::vector<unsigned int> sampleRates; /*!< Supported sample rates (queried from list of standard rates). */
- unsigned int preferredSampleRate; /*!< Preferred sample rate, eg. for WASAPI the system sample rate. */
- RtAudioFormat nativeFormats; /*!< Bit mask of supported data formats. */
-
- // Default constructor.
- DeviceInfo()
- :probed(false), outputChannels(0), inputChannels(0), duplexChannels(0),
- isDefaultOutput(false), isDefaultInput(false), preferredSampleRate(0), nativeFormats(0) {}
- };
-
- //! The structure for specifying input or ouput stream parameters.
- struct StreamParameters {
- unsigned int deviceId; /*!< Device index (0 to getDeviceCount() - 1). */
- unsigned int nChannels; /*!< Number of channels. */
- unsigned int firstChannel; /*!< First channel index on device (default = 0). */
-
- // Default constructor.
- StreamParameters()
- : deviceId(0), nChannels(0), firstChannel(0) {}
- };
-
- //! The structure for specifying stream options.
- /*!
- The following flags can be OR'ed together to allow a client to
- make changes to the default stream behavior:
-
- - \e RTAUDIO_NONINTERLEAVED: Use non-interleaved buffers (default = interleaved).
- - \e RTAUDIO_MINIMIZE_LATENCY: Attempt to set stream parameters for lowest possible latency.
- - \e RTAUDIO_HOG_DEVICE: Attempt grab device for exclusive use.
- - \e RTAUDIO_SCHEDULE_REALTIME: Attempt to select realtime scheduling for callback thread.
- - \e RTAUDIO_ALSA_USE_DEFAULT: Use the "default" PCM device (ALSA only).
-
- By default, RtAudio streams pass and receive audio data from the
- client in an interleaved format. By passing the
- RTAUDIO_NONINTERLEAVED flag to the openStream() function, audio
- data will instead be presented in non-interleaved buffers. In
- this case, each buffer argument in the RtAudioCallback function
- will point to a single array of data, with \c nFrames samples for
- each channel concatenated back-to-back. For example, the first
- sample of data for the second channel would be located at index \c
- nFrames (assuming the \c buffer pointer was recast to the correct
- data type for the stream).
-
- Certain audio APIs offer a number of parameters that influence the
- I/O latency of a stream. By default, RtAudio will attempt to set
- these parameters internally for robust (glitch-free) performance
- (though some APIs, like Windows Direct Sound, make this difficult).
- By passing the RTAUDIO_MINIMIZE_LATENCY flag to the openStream()
- function, internal stream settings will be influenced in an attempt
- to minimize stream latency, though possibly at the expense of stream
- performance.
-
- If the RTAUDIO_HOG_DEVICE flag is set, RtAudio will attempt to
- open the input and/or output stream device(s) for exclusive use.
- Note that this is not possible with all supported audio APIs.
-
- If the RTAUDIO_SCHEDULE_REALTIME flag is set, RtAudio will attempt
- to select realtime scheduling (round-robin) for the callback thread.
- The \c priority parameter will only be used if the RTAUDIO_SCHEDULE_REALTIME
- flag is set. It defines the thread's realtime priority.
-
- If the RTAUDIO_ALSA_USE_DEFAULT flag is set, RtAudio will attempt to
- open the "default" PCM device when using the ALSA API. Note that this
- will override any specified input or output device id.
-
- The \c numberOfBuffers parameter can be used to control stream
- latency in the Windows DirectSound, Linux OSS, and Linux Alsa APIs
- only. A value of two is usually the smallest allowed. Larger
- numbers can potentially result in more robust stream performance,
- though likely at the cost of stream latency. The value set by the
- user is replaced during execution of the RtAudio::openStream()
- function by the value actually used by the system.
-
- The \c streamName parameter can be used to set the client name
- when using the Jack API. By default, the client name is set to
- RtApiJack. However, if you wish to create multiple instances of
- RtAudio with Jack, each instance must have a unique client name.
- */
- struct StreamOptions {
- RtAudioStreamFlags flags; /*!< A bit-mask of stream flags (RTAUDIO_NONINTERLEAVED, RTAUDIO_MINIMIZE_LATENCY, RTAUDIO_HOG_DEVICE, RTAUDIO_ALSA_USE_DEFAULT). */
- unsigned int numberOfBuffers; /*!< Number of stream buffers. */
- std::string streamName; /*!< A stream name (currently used only in Jack). */
- int priority; /*!< Scheduling priority of callback thread (only used with flag RTAUDIO_SCHEDULE_REALTIME). */
-
- // Default constructor.
- StreamOptions()
- : flags(0), numberOfBuffers(0), priority(0) {}
- };
-
- //! A static function to determine the current RtAudio version.
- static std::string getVersion( void ) throw();
-
- //! A static function to determine the available compiled audio APIs.
- /*!
- The values returned in the std::vector can be compared against
- the enumerated list values. Note that there can be more than one
- API compiled for certain operating systems.
- */
- static void getCompiledApi( std::vector<RtAudio::Api> &apis ) throw();
-
- //! The class constructor.
- /*!
- The constructor performs minor initialization tasks. An exception
- can be thrown if no API support is compiled.
-
- If no API argument is specified and multiple API support has been
- compiled, the default order of use is JACK, ALSA, OSS (Linux
- systems) and ASIO, DS (Windows systems).
- */
- RtAudio( RtAudio::Api api=UNSPECIFIED );
-
- //! The destructor.
- /*!
- If a stream is running or open, it will be stopped and closed
- automatically.
- */
- ~RtAudio() throw();
-
- //! Returns the audio API specifier for the current instance of RtAudio.
- RtAudio::Api getCurrentApi( void ) throw();
-
- //! A public function that queries for the number of audio devices available.
- /*!
- This function performs a system query of available devices each time it
- is called, thus supporting devices connected \e after instantiation. If
- a system error occurs during processing, a warning will be issued.
- */
- unsigned int getDeviceCount( void ) throw();
-
- //! Return an RtAudio::DeviceInfo structure for a specified device number.
- /*!
-
- Any device integer between 0 and getDeviceCount() - 1 is valid.
- If an invalid argument is provided, an RtAudioError (type = INVALID_USE)
- will be thrown. If a device is busy or otherwise unavailable, the
- structure member "probed" will have a value of "false" and all
- other members are undefined. If the specified device is the
- current default input or output device, the corresponding
- "isDefault" member will have a value of "true".
- */
- RtAudio::DeviceInfo getDeviceInfo( unsigned int device );
-
- //! A function that returns the index of the default output device.
- /*!
- If the underlying audio API does not provide a "default
- device", or if no devices are available, the return value will be
- 0. Note that this is a valid device identifier and it is the
- client's responsibility to verify that a device is available
- before attempting to open a stream.
- */
- unsigned int getDefaultOutputDevice( void ) throw();
-
- //! A function that returns the index of the default input device.
- /*!
- If the underlying audio API does not provide a "default
- device", or if no devices are available, the return value will be
- 0. Note that this is a valid device identifier and it is the
- client's responsibility to verify that a device is available
- before attempting to open a stream.
- */
- unsigned int getDefaultInputDevice( void ) throw();
-
- //! A public function for opening a stream with the specified parameters.
- /*!
- An RtAudioError (type = SYSTEM_ERROR) is thrown if a stream cannot be
- opened with the specified parameters or an error occurs during
- processing. An RtAudioError (type = INVALID_USE) is thrown if any
- invalid device ID or channel number parameters are specified.
-
- \param outputParameters Specifies output stream parameters to use
- when opening a stream, including a device ID, number of channels,
- and starting channel number. For input-only streams, this
- argument should be NULL. The device ID is an index value between
- 0 and getDeviceCount() - 1.
- \param inputParameters Specifies input stream parameters to use
- when opening a stream, including a device ID, number of channels,
- and starting channel number. For output-only streams, this
- argument should be NULL. The device ID is an index value between
- 0 and getDeviceCount() - 1.
- \param format An RtAudioFormat specifying the desired sample data format.
- \param sampleRate The desired sample rate (sample frames per second).
- \param *bufferFrames A pointer to a value indicating the desired
- internal buffer size in sample frames. The actual value
- used by the device is returned via the same pointer. A
- value of zero can be specified, in which case the lowest
- allowable value is determined.
- \param callback A client-defined function that will be invoked
- when input data is available and/or output data is needed.
- \param userData An optional pointer to data that can be accessed
- from within the callback function.
- \param options An optional pointer to a structure containing various
- global stream options, including a list of OR'ed RtAudioStreamFlags
- and a suggested number of stream buffers that can be used to
- control stream latency. More buffers typically result in more
- robust performance, though at a cost of greater latency. If a
- value of zero is specified, a system-specific median value is
- chosen. If the RTAUDIO_MINIMIZE_LATENCY flag bit is set, the
- lowest allowable value is used. The actual value used is
- returned via the structure argument. The parameter is API dependent.
- \param errorCallback A client-defined function that will be invoked
- when an error has occured.
- */
- void openStream( RtAudio::StreamParameters *outputParameters,
- RtAudio::StreamParameters *inputParameters,
- RtAudioFormat format, unsigned int sampleRate,
- unsigned int *bufferFrames, RtAudioCallback callback,
- void *userData = NULL, RtAudio::StreamOptions *options = NULL, RtAudioErrorCallback errorCallback = NULL );
-
- //! A function that closes a stream and frees any associated stream memory.
- /*!
- If a stream is not open, this function issues a warning and
- returns (no exception is thrown).
- */
- void closeStream( void ) throw();
-
- //! A function that starts a stream.
- /*!
- An RtAudioError (type = SYSTEM_ERROR) is thrown if an error occurs
- during processing. An RtAudioError (type = INVALID_USE) is thrown if a
- stream is not open. A warning is issued if the stream is already
- running.
- */
- void startStream( void );
-
- //! Stop a stream, allowing any samples remaining in the output queue to be played.
- /*!
- An RtAudioError (type = SYSTEM_ERROR) is thrown if an error occurs
- during processing. An RtAudioError (type = INVALID_USE) is thrown if a
- stream is not open. A warning is issued if the stream is already
- stopped.
- */
- void stopStream( void );
-
- //! Stop a stream, discarding any samples remaining in the input/output queue.
- /*!
- An RtAudioError (type = SYSTEM_ERROR) is thrown if an error occurs
- during processing. An RtAudioError (type = INVALID_USE) is thrown if a
- stream is not open. A warning is issued if the stream is already
- stopped.
- */
- void abortStream( void );
-
- //! Returns true if a stream is open and false if not.
- bool isStreamOpen( void ) const throw();
-
- //! Returns true if the stream is running and false if it is stopped or not open.
- bool isStreamRunning( void ) const throw();
-
- //! Returns the number of elapsed seconds since the stream was started.
- /*!
- If a stream is not open, an RtAudioError (type = INVALID_USE) will be thrown.
- */
- double getStreamTime( void );
-
- //! Set the stream time to a time in seconds greater than or equal to 0.0.
- /*!
- If a stream is not open, an RtAudioError (type = INVALID_USE) will be thrown.
- */
- void setStreamTime( double time );
-
- //! Returns the internal stream latency in sample frames.
- /*!
- The stream latency refers to delay in audio input and/or output
- caused by internal buffering by the audio system and/or hardware.
- For duplex streams, the returned value will represent the sum of
- the input and output latencies. If a stream is not open, an
- RtAudioError (type = INVALID_USE) will be thrown. If the API does not
- report latency, the return value will be zero.
- */
- long getStreamLatency( void );
-
- //! Returns actual sample rate in use by the stream.
- /*!
- On some systems, the sample rate used may be slightly different
- than that specified in the stream parameters. If a stream is not
- open, an RtAudioError (type = INVALID_USE) will be thrown.
- */
- unsigned int getStreamSampleRate( void );
-
- //! Specify whether warning messages should be printed to stderr.
- void showWarnings( bool value = true ) throw();
-
- protected:
-
- void openRtApi( RtAudio::Api api );
- RtApi *rtapi_;
-};
-
-// Operating system dependent thread functionality.
-#if defined(__WINDOWS_DS__) || defined(__WINDOWS_ASIO__) || defined(__WINDOWS_WASAPI__)
-
- #ifndef NOMINMAX
- #define NOMINMAX
- #endif
- #include <windows.h>
- #include <process.h>
-
- typedef uintptr_t ThreadHandle;
- typedef CRITICAL_SECTION StreamMutex;
-
-#elif defined(__LINUX_ALSA__) || defined(__LINUX_PULSE__) || defined(__UNIX_JACK__) || defined(__LINUX_OSS__) || defined(__MACOSX_CORE__)
- // Using pthread library for various flavors of unix.
- #include <pthread.h>
-
- typedef pthread_t ThreadHandle;
- typedef pthread_mutex_t StreamMutex;
-
-#else // Setup for "dummy" behavior
-
- #define __RTAUDIO_DUMMY__
- typedef int ThreadHandle;
- typedef int StreamMutex;
-
-#endif
-
-// This global structure type is used to pass callback information
-// between the private RtAudio stream structure and global callback
-// handling functions.
-struct CallbackInfo {
- void *object; // Used as a "this" pointer.
- ThreadHandle thread;
- void *callback;
- void *userData;
- void *errorCallback;
- void *apiInfo; // void pointer for API specific callback information
- bool isRunning;
- bool doRealtime;
- int priority;
-
- // Default constructor.
- CallbackInfo()
- :object(0), callback(0), userData(0), errorCallback(0), apiInfo(0), isRunning(false), doRealtime(false) {}
-};
-
-// **************************************************************** //
-//
-// RtApi class declaration.
-//
-// Subclasses of RtApi contain all API- and OS-specific code necessary
-// to fully implement the RtAudio API.
-//
-// Note that RtApi is an abstract base class and cannot be
-// explicitly instantiated. The class RtAudio will create an
-// instance of an RtApi subclass (RtApiOss, RtApiAlsa,
-// RtApiJack, RtApiCore, RtApiDs, or RtApiAsio).
-//
-// **************************************************************** //
-
-#pragma pack(push, 1)
-class S24 {
-
- protected:
- unsigned char c3[3];
-
- public:
- S24() {}
-
- S24& operator = ( const int& i ) {
- c3[0] = (i & 0x000000ff);
- c3[1] = (i & 0x0000ff00) >> 8;
- c3[2] = (i & 0x00ff0000) >> 16;
- return *this;
- }
-
- S24( const S24& v ) { *this = v; }
- S24( const double& d ) { *this = (int) d; }
- S24( const float& f ) { *this = (int) f; }
- S24( const signed short& s ) { *this = (int) s; }
- S24( const char& c ) { *this = (int) c; }
-
- int asInt() {
- int i = c3[0] | (c3[1] << 8) | (c3[2] << 16);
- if (i & 0x800000) i |= ~0xffffff;
- return i;
- }
-};
-#pragma pack(pop)
-
-#if defined( HAVE_GETTIMEOFDAY )
- #include <sys/time.h>
-#endif
-
-#include <sstream>
-
-class RtApi
-{
-public:
-
- RtApi();
- virtual ~RtApi();
- virtual RtAudio::Api getCurrentApi( void ) = 0;
- virtual unsigned int getDeviceCount( void ) = 0;
- virtual RtAudio::DeviceInfo getDeviceInfo( unsigned int device ) = 0;
- virtual unsigned int getDefaultInputDevice( void );
- virtual unsigned int getDefaultOutputDevice( void );
- void openStream( RtAudio::StreamParameters *outputParameters,
- RtAudio::StreamParameters *inputParameters,
- RtAudioFormat format, unsigned int sampleRate,
- unsigned int *bufferFrames, RtAudioCallback callback,
- void *userData, RtAudio::StreamOptions *options,
- RtAudioErrorCallback errorCallback );
- virtual void closeStream( void );
- virtual void startStream( void ) = 0;
- virtual void stopStream( void ) = 0;
- virtual void abortStream( void ) = 0;
- long getStreamLatency( void );
- unsigned int getStreamSampleRate( void );
- virtual double getStreamTime( void );
- virtual void setStreamTime( double time );
- bool isStreamOpen( void ) const { return stream_.state != STREAM_CLOSED; }
- bool isStreamRunning( void ) const { return stream_.state == STREAM_RUNNING; }
- void showWarnings( bool value ) { showWarnings_ = value; }
-
-
-protected:
-
- static const unsigned int MAX_SAMPLE_RATES;
- static const unsigned int SAMPLE_RATES[];
-
- enum { FAILURE, SUCCESS };
-
- enum StreamState {
- STREAM_STOPPED,
- STREAM_STOPPING,
- STREAM_RUNNING,
- STREAM_CLOSED = -50
- };
-
- enum StreamMode {
- OUTPUT,
- INPUT,
- DUPLEX,
- UNINITIALIZED = -75
- };
-
- // A protected structure used for buffer conversion.
- struct ConvertInfo {
- int channels;
- int inJump, outJump;
- RtAudioFormat inFormat, outFormat;
- std::vector<int> inOffset;
- std::vector<int> outOffset;
- };
-
- // A protected structure for audio streams.
- struct RtApiStream {
- unsigned int device[2]; // Playback and record, respectively.
- void *apiHandle; // void pointer for API specific stream handle information
- StreamMode mode; // OUTPUT, INPUT, or DUPLEX.
- StreamState state; // STOPPED, RUNNING, or CLOSED
- char *userBuffer[2]; // Playback and record, respectively.
- char *deviceBuffer;
- bool doConvertBuffer[2]; // Playback and record, respectively.
- bool userInterleaved;
- bool deviceInterleaved[2]; // Playback and record, respectively.
- bool doByteSwap[2]; // Playback and record, respectively.
- unsigned int sampleRate;
- unsigned int bufferSize;
- unsigned int nBuffers;
- unsigned int nUserChannels[2]; // Playback and record, respectively.
- unsigned int nDeviceChannels[2]; // Playback and record channels, respectively.
- unsigned int channelOffset[2]; // Playback and record, respectively.
- unsigned long latency[2]; // Playback and record, respectively.
- RtAudioFormat userFormat;
- RtAudioFormat deviceFormat[2]; // Playback and record, respectively.
- StreamMutex mutex;
- CallbackInfo callbackInfo;
- ConvertInfo convertInfo[2];
- double streamTime; // Number of elapsed seconds since the stream started.
-
-#if defined(HAVE_GETTIMEOFDAY)
- struct timeval lastTickTimestamp;
-#endif
-
- RtApiStream()
- :apiHandle(0), deviceBuffer(0) { device[0] = 11111; device[1] = 11111; }
- };
-
- typedef S24 Int24;
- typedef signed short Int16;
- typedef signed int Int32;
- typedef float Float32;
- typedef double Float64;
-
- std::ostringstream errorStream_;
- std::string errorText_;
- bool showWarnings_;
- RtApiStream stream_;
- bool firstErrorOccurred_;
-
- /*!
- Protected, api-specific method that attempts to open a device
- with the given parameters. This function MUST be implemented by
- all subclasses. If an error is encountered during the probe, a
- "warning" message is reported and FAILURE is returned. A
- successful probe is indicated by a return value of SUCCESS.
- */
- virtual bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,
- unsigned int firstChannel, unsigned int sampleRate,
- RtAudioFormat format, unsigned int *bufferSize,
- RtAudio::StreamOptions *options );
-
- //! A protected function used to increment the stream time.
- void tickStreamTime( void );
-
- //! Protected common method to clear an RtApiStream structure.
- void clearStreamInfo();
-
- /*!
- Protected common method that throws an RtAudioError (type =
- INVALID_USE) if a stream is not open.
- */
- void verifyStream( void );
-
- //! Protected common error method to allow global control over error handling.
- void error( RtAudioError::Type type );
-
- /*!
- Protected method used to perform format, channel number, and/or interleaving
- conversions between the user and device buffers.
- */
- void convertBuffer( char *outBuffer, char *inBuffer, ConvertInfo &info );
-
- //! Protected common method used to perform byte-swapping on buffers.
- void byteSwapBuffer( char *buffer, unsigned int samples, RtAudioFormat format );
-
- //! Protected common method that returns the number of bytes for a given format.
- unsigned int formatBytes( RtAudioFormat format );
-
- //! Protected common method that sets up the parameters for buffer conversion.
- void setConvertInfo( StreamMode mode, unsigned int firstChannel );
-};
-
-// **************************************************************** //
-//
-// Inline RtAudio definitions.
-//
-// **************************************************************** //
-
-inline RtAudio::Api RtAudio :: getCurrentApi( void ) throw() { return rtapi_->getCurrentApi(); }
-inline unsigned int RtAudio :: getDeviceCount( void ) throw() { return rtapi_->getDeviceCount(); }
-inline RtAudio::DeviceInfo RtAudio :: getDeviceInfo( unsigned int device ) { return rtapi_->getDeviceInfo( device ); }
-inline unsigned int RtAudio :: getDefaultInputDevice( void ) throw() { return rtapi_->getDefaultInputDevice(); }
-inline unsigned int RtAudio :: getDefaultOutputDevice( void ) throw() { return rtapi_->getDefaultOutputDevice(); }
-inline void RtAudio :: closeStream( void ) throw() { return rtapi_->closeStream(); }
-inline void RtAudio :: startStream( void ) { return rtapi_->startStream(); }
-inline void RtAudio :: stopStream( void ) { return rtapi_->stopStream(); }
-inline void RtAudio :: abortStream( void ) { return rtapi_->abortStream(); }
-inline bool RtAudio :: isStreamOpen( void ) const throw() { return rtapi_->isStreamOpen(); }
-inline bool RtAudio :: isStreamRunning( void ) const throw() { return rtapi_->isStreamRunning(); }
-inline long RtAudio :: getStreamLatency( void ) { return rtapi_->getStreamLatency(); }
-inline unsigned int RtAudio :: getStreamSampleRate( void ) { return rtapi_->getStreamSampleRate(); }
-inline double RtAudio :: getStreamTime( void ) { return rtapi_->getStreamTime(); }
-inline void RtAudio :: setStreamTime( double time ) { return rtapi_->setStreamTime( time ); }
-inline void RtAudio :: showWarnings( bool value ) throw() { rtapi_->showWarnings( value ); }
-
-// RtApi Subclass prototypes.
-
-#if defined(__MACOSX_CORE__)
-
-#include <CoreAudio/AudioHardware.h>
-
-class RtApiCore: public RtApi
-{
-public:
-
- RtApiCore();
- ~RtApiCore();
- RtAudio::Api getCurrentApi( void ) { return RtAudio::MACOSX_CORE; }
- unsigned int getDeviceCount( void );
- RtAudio::DeviceInfo getDeviceInfo( unsigned int device );
- unsigned int getDefaultOutputDevice( void );
- unsigned int getDefaultInputDevice( void );
- void closeStream( void );
- void startStream( void );
- void stopStream( void );
- void abortStream( void );
- long getStreamLatency( void );
-
- // This function is intended for internal use only. It must be
- // public because it is called by the internal callback handler,
- // which is not a member of RtAudio. External use of this function
- // will most likely produce highly undesireable results!
- bool callbackEvent( AudioDeviceID deviceId,
- const AudioBufferList *inBufferList,
- const AudioBufferList *outBufferList );
-
- private:
-
- bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,
- unsigned int firstChannel, unsigned int sampleRate,
- RtAudioFormat format, unsigned int *bufferSize,
- RtAudio::StreamOptions *options );
- static const char* getErrorCode( OSStatus code );
-};
-
-#endif
-
-#if defined(__UNIX_JACK__)
-
-class RtApiJack: public RtApi
-{
-public:
-
- RtApiJack();
- ~RtApiJack();
- RtAudio::Api getCurrentApi( void ) { return RtAudio::UNIX_JACK; }
- unsigned int getDeviceCount( void );
- RtAudio::DeviceInfo getDeviceInfo( unsigned int device );
- void closeStream( void );
- void startStream( void );
- void stopStream( void );
- void abortStream( void );
- long getStreamLatency( void );
-
- // This function is intended for internal use only. It must be
- // public because it is called by the internal callback handler,
- // which is not a member of RtAudio. External use of this function
- // will most likely produce highly undesireable results!
- bool callbackEvent( unsigned long nframes );
-
- private:
-
- bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,
- unsigned int firstChannel, unsigned int sampleRate,
- RtAudioFormat format, unsigned int *bufferSize,
- RtAudio::StreamOptions *options );
-};
-
-#endif
-
-#if defined(__WINDOWS_ASIO__)
-
-class RtApiAsio: public RtApi
-{
-public:
-
- RtApiAsio();
- ~RtApiAsio();
- RtAudio::Api getCurrentApi( void ) { return RtAudio::WINDOWS_ASIO; }
- unsigned int getDeviceCount( void );
- RtAudio::DeviceInfo getDeviceInfo( unsigned int device );
- void closeStream( void );
- void startStream( void );
- void stopStream( void );
- void abortStream( void );
- long getStreamLatency( void );
-
- // This function is intended for internal use only. It must be
- // public because it is called by the internal callback handler,
- // which is not a member of RtAudio. External use of this function
- // will most likely produce highly undesireable results!
- bool callbackEvent( long bufferIndex );
-
- private:
-
- std::vector<RtAudio::DeviceInfo> devices_;
- void saveDeviceInfo( void );
- bool coInitialized_;
- bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,
- unsigned int firstChannel, unsigned int sampleRate,
- RtAudioFormat format, unsigned int *bufferSize,
- RtAudio::StreamOptions *options );
-};
-
-#endif
-
-#if defined(__WINDOWS_DS__)
-
-class RtApiDs: public RtApi
-{
-public:
-
- RtApiDs();
- ~RtApiDs();
- RtAudio::Api getCurrentApi( void ) { return RtAudio::WINDOWS_DS; }
- unsigned int getDeviceCount( void );
- unsigned int getDefaultOutputDevice( void );
- unsigned int getDefaultInputDevice( void );
- RtAudio::DeviceInfo getDeviceInfo( unsigned int device );
- void closeStream( void );
- void startStream( void );
- void stopStream( void );
- void abortStream( void );
- long getStreamLatency( void );
-
- // This function is intended for internal use only. It must be
- // public because it is called by the internal callback handler,
- // which is not a member of RtAudio. External use of this function
- // will most likely produce highly undesireable results!
- void callbackEvent( void );
-
- private:
-
- bool coInitialized_;
- bool buffersRolling;
- long duplexPrerollBytes;
- std::vector<struct DsDevice> dsDevices;
- bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,
- unsigned int firstChannel, unsigned int sampleRate,
- RtAudioFormat format, unsigned int *bufferSize,
- RtAudio::StreamOptions *options );
-};
-
-#endif
-
-#if defined(__WINDOWS_WASAPI__)
-
-struct IMMDeviceEnumerator;
-
-class RtApiWasapi : public RtApi
-{
-public:
- RtApiWasapi();
- ~RtApiWasapi();
-
- RtAudio::Api getCurrentApi( void ) { return RtAudio::WINDOWS_WASAPI; }
- unsigned int getDeviceCount( void );
- RtAudio::DeviceInfo getDeviceInfo( unsigned int device );
- unsigned int getDefaultOutputDevice( void );
- unsigned int getDefaultInputDevice( void );
- void closeStream( void );
- void startStream( void );
- void stopStream( void );
- void abortStream( void );
-
-private:
- bool coInitialized_;
- IMMDeviceEnumerator* deviceEnumerator_;
-
- bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,
- unsigned int firstChannel, unsigned int sampleRate,
- RtAudioFormat format, unsigned int* bufferSize,
- RtAudio::StreamOptions* options );
-
- static DWORD WINAPI runWasapiThread( void* wasapiPtr );
- static DWORD WINAPI stopWasapiThread( void* wasapiPtr );
- static DWORD WINAPI abortWasapiThread( void* wasapiPtr );
- void wasapiThread();
-};
-
-#endif
-
-#if defined(__LINUX_ALSA__)
-
-class RtApiAlsa: public RtApi
-{
-public:
-
- RtApiAlsa();
- ~RtApiAlsa();
- RtAudio::Api getCurrentApi() { return RtAudio::LINUX_ALSA; }
- unsigned int getDeviceCount( void );
- RtAudio::DeviceInfo getDeviceInfo( unsigned int device );
- void closeStream( void );
- void startStream( void );
- void stopStream( void );
- void abortStream( void );
-
- // This function is intended for internal use only. It must be
- // public because it is called by the internal callback handler,
- // which is not a member of RtAudio. External use of this function
- // will most likely produce highly undesireable results!
- void callbackEvent( void );
-
- private:
-
- std::vector<RtAudio::DeviceInfo> devices_;
- void saveDeviceInfo( void );
- bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,
- unsigned int firstChannel, unsigned int sampleRate,
- RtAudioFormat format, unsigned int *bufferSize,
- RtAudio::StreamOptions *options );
-};
-
-#endif
-
-#if defined(__LINUX_PULSE__)
-
-class RtApiPulse: public RtApi
-{
-public:
- ~RtApiPulse();
- RtAudio::Api getCurrentApi() { return RtAudio::LINUX_PULSE; }
- unsigned int getDeviceCount( void );
- RtAudio::DeviceInfo getDeviceInfo( unsigned int device );
- void closeStream( void );
- void startStream( void );
- void stopStream( void );
- void abortStream( void );
-
- // This function is intended for internal use only. It must be
- // public because it is called by the internal callback handler,
- // which is not a member of RtAudio. External use of this function
- // will most likely produce highly undesireable results!
- void callbackEvent( void );
-
- private:
-
- std::vector<RtAudio::DeviceInfo> devices_;
- void saveDeviceInfo( void );
- bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,
- unsigned int firstChannel, unsigned int sampleRate,
- RtAudioFormat format, unsigned int *bufferSize,
- RtAudio::StreamOptions *options );
-};
-
-#endif
-
-#if defined(__LINUX_OSS__)
-
-class RtApiOss: public RtApi
-{
-public:
-
- RtApiOss();
- ~RtApiOss();
- RtAudio::Api getCurrentApi() { return RtAudio::LINUX_OSS; }
- unsigned int getDeviceCount( void );
- RtAudio::DeviceInfo getDeviceInfo( unsigned int device );
- void closeStream( void );
- void startStream( void );
- void stopStream( void );
- void abortStream( void );
-
- // This function is intended for internal use only. It must be
- // public because it is called by the internal callback handler,
- // which is not a member of RtAudio. External use of this function
- // will most likely produce highly undesireable results!
- void callbackEvent( void );
-
- private:
-
- bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,
- unsigned int firstChannel, unsigned int sampleRate,
- RtAudioFormat format, unsigned int *bufferSize,
- RtAudio::StreamOptions *options );
-};
-
-#endif
-
-#if defined(__RTAUDIO_DUMMY__)
-
-class RtApiDummy: public RtApi
-{
-public:
-
- RtApiDummy() { errorText_ = "RtApiDummy: This class provides no functionality."; error( RtAudioError::WARNING ); }
- RtAudio::Api getCurrentApi( void ) { return RtAudio::RTAUDIO_DUMMY; }
- unsigned int getDeviceCount( void ) { return 0; }
- RtAudio::DeviceInfo getDeviceInfo( unsigned int /*device*/ ) { RtAudio::DeviceInfo info; return info; }
- void closeStream( void ) {}
- void startStream( void ) {}
- void stopStream( void ) {}
- void abortStream( void ) {}
-
- private:
-
- bool probeDeviceOpen( unsigned int /*device*/, StreamMode /*mode*/, unsigned int /*channels*/,
- unsigned int /*firstChannel*/, unsigned int /*sampleRate*/,
- RtAudioFormat /*format*/, unsigned int * /*bufferSize*/,
- RtAudio::StreamOptions * /*options*/ ) { return false; }
-};
-
-#endif
-
-#endif
-
-// Indentation settings for Vim and Emacs
-//
-// Local Variables:
-// c-basic-offset: 2
-// indent-tabs-mode: nil
-// End:
-//
-// vim: et sts=2 sw=2
-
-#endif // RTAUDIO_ENABLED -GODOT-
diff --git a/thirdparty/thekla_atlas/godot-changes.patch b/thirdparty/thekla_atlas/godot-changes.patch
deleted file mode 100644
index 0e56403336..0000000000
--- a/thirdparty/thekla_atlas/godot-changes.patch
+++ /dev/null
@@ -1,154 +0,0 @@
-diff --git a/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.cpp b/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.cpp
-index 5ce452c..11e635d 100644
---- a/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.cpp
-+++ b/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.cpp
-@@ -142,9 +142,11 @@ AtlasPacker::AtlasPacker(Atlas * atlas) : m_atlas(atlas), m_bitmap(256, 256)
- {
- m_width = 0;
- m_height = 0;
--
-- m_debug_bitmap.allocate(256, 256);
-- m_debug_bitmap.fill(Color32(0,0,0,0));
-+
-+ // -- GODOT start --
-+ //m_debug_bitmap.allocate(256, 256);
-+ //m_debug_bitmap.fill(Color32(0,0,0,0));
-+ // -- GODOT end --
- }
-
- AtlasPacker::~AtlasPacker()
-@@ -465,7 +467,11 @@ void AtlasPacker::packCharts(int quality, float texelsPerUnit, bool blockAligned
- nvDebug("origin: %f %f\n", origin.x, origin.y);
- nvDebug("majorAxis: %f %f\n", majorAxis.x, majorAxis.y);
- nvDebug("minorAxis: %f %f\n", minorAxis.x, minorAxis.y);
-- nvDebugBreak();
-+ // -- GODOT start --
-+ //nvDebugBreak();
-+ m_atlas->setFailed();
-+ return;
-+ // -- GODOT end --
- }
- //nvCheck(tmp.x >= 0 && tmp.y >= 0);
-
-@@ -597,8 +603,10 @@ void AtlasPacker::packCharts(int quality, float texelsPerUnit, bool blockAligned
- m_bitmap.clearAll();
- if (approximateExtent > m_bitmap.width()) {
- m_bitmap.resize(approximateExtent, approximateExtent, false);
-- m_debug_bitmap.resize(approximateExtent, approximateExtent);
-- m_debug_bitmap.fill(Color32(0,0,0,0));
-+ // -- GODOT start --
-+ //m_debug_bitmap.resize(approximateExtent, approximateExtent);
-+ //m_debug_bitmap.fill(Color32(0,0,0,0));
-+ // -- GODOT end --
- }
-
-
-@@ -680,20 +688,24 @@ void AtlasPacker::packCharts(int quality, float texelsPerUnit, bool blockAligned
- {
- //nvDebug("Resize bitmap (%d, %d).\n", nextPowerOfTwo(w), nextPowerOfTwo(h));
- m_bitmap.resize(nextPowerOfTwo(U32(w)), nextPowerOfTwo(U32(h)), false);
-- m_debug_bitmap.resize(nextPowerOfTwo(U32(w)), nextPowerOfTwo(U32(h)));
-+ // -- GODOT start --
-+ //m_debug_bitmap.resize(nextPowerOfTwo(U32(w)), nextPowerOfTwo(U32(h)));
-+ // -- GODOT end --
- }
-
- //nvDebug("Add chart at (%d, %d).\n", best_x, best_y);
-
- addChart(&chart_bitmap, w, h, best_x, best_y, best_r, /*debugOutput=*/NULL);
-
-+ // -- GODOT start --
- // IC: Output chart again to debug bitmap.
-- if (chart->isVertexMapped()) {
-+ /*if (chart->isVertexMapped()) {
- addChart(&chart_bitmap, w, h, best_x, best_y, best_r, &m_debug_bitmap);
- }
- else {
- addChart(chart, w, h, best_x, best_y, best_r, &m_debug_bitmap);
-- }
-+ }*/
-+ // -- GODOT end --
-
- //float best_angle = 2 * PI * best_r;
-
-@@ -842,8 +854,10 @@ void AtlasPacker::packCharts(int quality, float texelsPerUnit, bool blockAligned
- nvCheck(isAligned(m_width, 4));
- nvCheck(isAligned(m_height, 4));
-
-- m_debug_bitmap.resize(m_width, m_height);
-- m_debug_bitmap.setFormat(Image::Format_ARGB);
-+ // -- GODOT start --
-+ //m_debug_bitmap.resize(m_width, m_height);
-+ //m_debug_bitmap.setFormat(Image::Format_ARGB);
-+ // -- GODOT end --
-
- #if DEBUG_OUTPUT
- //outputDebugBitmap("debug_packer_final.tga", m_bitmap, w, h);
-diff --git a/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.h b/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.h
-index 2d305f3..845dbfb 100644
---- a/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.h
-+++ b/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.h
-@@ -48,7 +48,9 @@ namespace nv
-
- Atlas * m_atlas;
- BitMap m_bitmap;
-- Image m_debug_bitmap;
-+ // -- GODOT start --
-+ //Image m_debug_bitmap;
-+ // -- GODOT end --
- RadixSort m_radix;
-
- uint m_width;
-diff --git a/thirdparty/thekla_atlas/thekla/thekla_atlas.cpp b/thirdparty/thekla_atlas/thekla/thekla_atlas.cpp
-index d6f0acc..de1953d 100644
---- a/thirdparty/thekla_atlas/thekla/thekla_atlas.cpp
-+++ b/thirdparty/thekla_atlas/thekla/thekla_atlas.cpp
-@@ -2,6 +2,9 @@
- #include "thekla_atlas.h"
-
- #include <cfloat>
-+// -- GODOT start --
-+#include <stdio.h>
-+// -- GODOT end --
-
- #include "nvmesh/halfedge/Edge.h"
- #include "nvmesh/halfedge/Mesh.h"
-@@ -112,6 +115,8 @@ static Atlas_Output_Mesh * mesh_atlas_to_output(const HalfEdge::Mesh * mesh, con
- output->index_count = face_count * 3;
- output->index_array = new int[face_count * 3];
-
-+ // -- GODOT start --
-+ int face_ofs = 0;
- // Set face indices.
- for (int f = 0; f < face_count; f++) {
- uint c = charts->faceChartAt(f);
-@@ -121,14 +126,26 @@ static Atlas_Output_Mesh * mesh_atlas_to_output(const HalfEdge::Mesh * mesh, con
- const Chart * chart = charts->chartAt(c);
- nvDebugCheck(chart->faceAt(i) == f);
-
-+ if (i >= chart->chartMesh()->faceCount()) {
-+ printf("WARNING: Faces may be missing in the final vertex, which could not be packed\n");
-+ continue;
-+ }
-+
- const HalfEdge::Face * face = chart->chartMesh()->faceAt(i);
- const HalfEdge::Edge * edge = face->edge;
-
-- output->index_array[3*f+0] = vertexOffset + edge->vertex->id;
-- output->index_array[3*f+1] = vertexOffset + edge->next->vertex->id;
-- output->index_array[3*f+2] = vertexOffset + edge->next->next->vertex->id;
-+ //output->index_array[3*f+0] = vertexOffset + edge->vertex->id;
-+ //output->index_array[3*f+1] = vertexOffset + edge->next->vertex->id;
-+ //output->index_array[3*f+2] = vertexOffset + edge->next->next->vertex->id;
-+ output->index_array[3 * face_ofs + 0] = vertexOffset + edge->vertex->id;
-+ output->index_array[3 * face_ofs + 1] = vertexOffset + edge->next->vertex->id;
-+ output->index_array[3 * face_ofs + 2] = vertexOffset + edge->next->next->vertex->id;
-+ face_ofs++;
- }
-
-+ output->index_count = face_ofs * 3;
-+ // -- GODOT end --
-+
- *error = Atlas_Error_Success;
- output->atlas_width = w;
- output->atlas_height = h;
diff --git a/thirdparty/thekla_atlas/nvconfig.h b/thirdparty/thekla_atlas/nvconfig.h
deleted file mode 100644
index 815bc3ec75..0000000000
--- a/thirdparty/thekla_atlas/nvconfig.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef NV_CONFIG
-#define NV_CONFIG
-
-#if NV_OS_DARWIN
-
-// Hardcoded.
-
-#define NV_HAVE_UNISTD_H
-#define NV_HAVE_STDARG_H
-#define NV_HAVE_SIGNAL_H
-#define NV_HAVE_EXECINFO_H
-//#define NV_HAVE_MALLOC_H
-
-#else
-
-//#define HAVE_UNISTD_H
-#define NV_HAVE_STDARG_H
-//#define HAVE_SIGNAL_H
-//#define HAVE_EXECINFO_H
-//#define HAVE_MALLOC_H
-
-#endif
-
-//#define HAVE_OPENMP // Only in MSVC pro edition.
-
-//#cmakedefine HAVE_PNG
-//#cmakedefine HAVE_JPEG
-//#cmakedefine HAVE_TIFF
-//#cmakedefine HAVE_OPENEXR
-//#cmakedefine HAVE_FREEIMAGE
-#if !NV_OS_IOS
-#define NV_HAVE_STBIMAGE
-#endif
-
-//#cmakedefine HAVE_MAYA
-
-#endif // NV_CONFIG
diff --git a/thirdparty/thekla_atlas/nvcore/Array.h b/thirdparty/thekla_atlas/nvcore/Array.h
deleted file mode 100644
index b295cb2b0c..0000000000
--- a/thirdparty/thekla_atlas/nvcore/Array.h
+++ /dev/null
@@ -1,182 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#pragma once
-#ifndef NV_CORE_ARRAY_H
-#define NV_CORE_ARRAY_H
-
-/*
-This array class requires the elements to be relocable; it uses memmove and realloc. Ideally I should be
-using swap, but I honestly don't care. The only thing that you should be aware of is that internal pointers
-are not supported.
-
-Note also that push_back and resize does not support inserting arguments elements that are in the same
-container. This is forbidden to prevent an extra copy.
-*/
-
-
-#include "Memory.h"
-#include "Debug.h"
-#include "ForEach.h" // PseudoIndex
-
-
-namespace nv
-{
- class Stream;
-
- /**
- * Replacement for std::vector that is easier to debug and provides
- * some nice foreach enumerators.
- */
- template<typename T>
- class NVCORE_CLASS Array {
- public:
- typedef uint size_type;
-
- // Default constructor.
- NV_FORCEINLINE Array() : m_buffer(NULL), m_capacity(0), m_size(0) {}
-
- // Copy constructor.
- NV_FORCEINLINE Array(const Array & a) : m_buffer(NULL), m_capacity(0), m_size(0) {
- copy(a.m_buffer, a.m_size);
- }
-
- // Constructor that initializes the vector with the given elements.
- NV_FORCEINLINE Array(const T * ptr, uint num) : m_buffer(NULL), m_capacity(0), m_size(0) {
- copy(ptr, num);
- }
-
- // Allocate array.
- NV_FORCEINLINE explicit Array(uint capacity) : m_buffer(NULL), m_capacity(0), m_size(0) {
- setArrayCapacity(capacity);
- }
-
- // Destructor.
- NV_FORCEINLINE ~Array() {
- clear();
- free<T>(m_buffer);
- }
-
-
- /// Const element access.
- NV_FORCEINLINE const T & operator[]( uint index ) const
- {
- nvDebugCheck(index < m_size);
- return m_buffer[index];
- }
- NV_FORCEINLINE const T & at( uint index ) const
- {
- nvDebugCheck(index < m_size);
- return m_buffer[index];
- }
-
- /// Element access.
- NV_FORCEINLINE T & operator[] ( uint index )
- {
- nvDebugCheck(index < m_size);
- return m_buffer[index];
- }
- NV_FORCEINLINE T & at( uint index )
- {
- nvDebugCheck(index < m_size);
- return m_buffer[index];
- }
-
- /// Get vector size.
- NV_FORCEINLINE uint size() const { return m_size; }
-
- /// Get vector size.
- NV_FORCEINLINE uint count() const { return m_size; }
-
- /// Get vector capacity.
- NV_FORCEINLINE uint capacity() const { return m_capacity; }
-
- /// Get const vector pointer.
- NV_FORCEINLINE const T * buffer() const { return m_buffer; }
-
- /// Get vector pointer.
- NV_FORCEINLINE T * buffer() { return m_buffer; }
-
- /// Provide begin/end pointers for C++11 range-based for loops.
- NV_FORCEINLINE T * begin() { return m_buffer; }
- NV_FORCEINLINE T * end() { return m_buffer + m_size; }
- NV_FORCEINLINE const T * begin() const { return m_buffer; }
- NV_FORCEINLINE const T * end() const { return m_buffer + m_size; }
-
- /// Is vector empty.
- NV_FORCEINLINE bool isEmpty() const { return m_size == 0; }
-
- /// Is a null vector.
- NV_FORCEINLINE bool isNull() const { return m_buffer == NULL; }
-
-
- T & append();
- void push_back( const T & val );
- void pushBack( const T & val );
- Array<T> & append( const T & val );
- Array<T> & operator<< ( T & t );
- void pop_back();
- void popBack(uint count = 1);
- void popFront(uint count = 1);
- const T & back() const;
- T & back();
- const T & front() const;
- T & front();
- bool contains(const T & e) const;
- bool find(const T & element, uint * indexPtr) const;
- bool find(const T & element, uint begin, uint end, uint * indexPtr) const;
- void removeAt(uint index);
- bool remove(const T & element);
- void insertAt(uint index, const T & val = T());
- void append(const Array<T> & other);
- void append(const T other[], uint count);
- void replaceWithLast(uint index);
- void resize(uint new_size);
- void resize(uint new_size, const T & elem);
- void fill(const T & elem);
- void clear();
- void shrink();
- void reserve(uint desired_size);
- void copy(const T * data, uint count);
- Array<T> & operator=( const Array<T> & a );
- T * release();
-
-
- // Array enumerator.
- typedef uint PseudoIndex;
-
- NV_FORCEINLINE PseudoIndex start() const { return 0; }
- NV_FORCEINLINE bool isDone(const PseudoIndex & i) const { nvDebugCheck(i <= this->m_size); return i == this->m_size; }
- NV_FORCEINLINE void advance(PseudoIndex & i) const { nvDebugCheck(i <= this->m_size); i++; }
-
-#if NV_NEED_PSEUDOINDEX_WRAPPER
- NV_FORCEINLINE T & operator[]( const PseudoIndexWrapper & i ) {
- return m_buffer[i(this)];
- }
- NV_FORCEINLINE const T & operator[]( const PseudoIndexWrapper & i ) const {
- return m_buffer[i(this)];
- }
-#endif
-
- // Friends.
- template <typename Typ>
- friend Stream & operator<< ( Stream & s, Array<Typ> & p );
-
- template <typename Typ>
- friend void swap(Array<Typ> & a, Array<Typ> & b);
-
-
- protected:
-
- void setArraySize(uint new_size);
- void setArrayCapacity(uint new_capacity);
-
- T * m_buffer;
- uint m_capacity;
- uint m_size;
-
- };
-
-
-} // nv namespace
-
-#endif // NV_CORE_ARRAY_H
diff --git a/thirdparty/thekla_atlas/nvcore/Array.inl b/thirdparty/thekla_atlas/nvcore/Array.inl
deleted file mode 100644
index 0b4de28ba9..0000000000
--- a/thirdparty/thekla_atlas/nvcore/Array.inl
+++ /dev/null
@@ -1,452 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#pragma once
-#ifndef NV_CORE_ARRAY_INL
-#define NV_CORE_ARRAY_INL
-
-#include "Array.h"
-
-#include "Stream.h"
-#include "Utils.h" // swap
-
-#include <string.h> // memmove
-#include <new> // for placement new
-
-
-
-namespace nv
-{
- template <typename T>
- NV_FORCEINLINE T & Array<T>::append()
- {
- uint old_size = m_size;
- uint new_size = m_size + 1;
-
- setArraySize(new_size);
-
- construct_range(m_buffer, new_size, old_size);
-
- return m_buffer[old_size]; // Return reference to last element.
- }
-
- // Push an element at the end of the vector.
- template <typename T>
- NV_FORCEINLINE void Array<T>::push_back( const T & val )
- {
-#if 1
- nvDebugCheck(&val < m_buffer || &val >= m_buffer+m_size);
-
- uint old_size = m_size;
- uint new_size = m_size + 1;
-
- setArraySize(new_size);
-
- construct_range(m_buffer, new_size, old_size, val);
-#else
- uint new_size = m_size + 1;
-
- if (new_size > m_capacity)
- {
- // @@ Is there any way to avoid this copy?
- // @@ Can we create a copy without side effects? Ie. without calls to constructor/destructor. Use alloca + memcpy?
- // @@ Assert instead of copy?
- const T copy(val); // create a copy in case value is inside of this array.
-
- setArraySize(new_size);
-
- new (m_buffer+new_size-1) T(copy);
- }
- else
- {
- m_size = new_size;
- new(m_buffer+new_size-1) T(val);
- }
-#endif // 0/1
- }
- template <typename T>
- NV_FORCEINLINE void Array<T>::pushBack( const T & val )
- {
- push_back(val);
- }
- template <typename T>
- NV_FORCEINLINE Array<T> & Array<T>::append( const T & val )
- {
- push_back(val);
- return *this;
- }
-
- // Qt like push operator.
- template <typename T>
- NV_FORCEINLINE Array<T> & Array<T>::operator<< ( T & t )
- {
- push_back(t);
- return *this;
- }
-
- // Pop the element at the end of the vector.
- template <typename T>
- NV_FORCEINLINE void Array<T>::pop_back()
- {
- nvDebugCheck( m_size > 0 );
- resize( m_size - 1 );
- }
- template <typename T>
- NV_FORCEINLINE void Array<T>::popBack(uint count)
- {
- nvDebugCheck(m_size >= count);
- resize(m_size - count);
- }
-
- template <typename T>
- NV_FORCEINLINE void Array<T>::popFront(uint count)
- {
- nvDebugCheck(m_size >= count);
- //resize(m_size - count);
-
- if (m_size == count) {
- clear();
- }
- else {
- destroy_range(m_buffer, 0, count);
-
- memmove(m_buffer, m_buffer + count, sizeof(T) * (m_size - count));
-
- m_size -= count;
- }
-
- }
-
-
- // Get back element.
- template <typename T>
- NV_FORCEINLINE const T & Array<T>::back() const
- {
- nvDebugCheck( m_size > 0 );
- return m_buffer[m_size-1];
- }
-
- // Get back element.
- template <typename T>
- NV_FORCEINLINE T & Array<T>::back()
- {
- nvDebugCheck( m_size > 0 );
- return m_buffer[m_size-1];
- }
-
- // Get front element.
- template <typename T>
- NV_FORCEINLINE const T & Array<T>::front() const
- {
- nvDebugCheck( m_size > 0 );
- return m_buffer[0];
- }
-
- // Get front element.
- template <typename T>
- NV_FORCEINLINE T & Array<T>::front()
- {
- nvDebugCheck( m_size > 0 );
- return m_buffer[0];
- }
-
- // Check if the given element is contained in the array.
- template <typename T>
- NV_FORCEINLINE bool Array<T>::contains(const T & e) const
- {
- return find(e, NULL);
- }
-
- // Return true if element found.
- template <typename T>
- NV_FORCEINLINE bool Array<T>::find(const T & element, uint * indexPtr) const
- {
- return find(element, 0, m_size, indexPtr);
- }
-
- // Return true if element found within the given range.
- template <typename T>
- NV_FORCEINLINE bool Array<T>::find(const T & element, uint begin, uint end, uint * indexPtr) const
- {
- return ::nv::find(element, m_buffer, begin, end, indexPtr);
- }
-
-
- // Remove the element at the given index. This is an expensive operation!
- template <typename T>
- void Array<T>::removeAt(uint index)
- {
- nvDebugCheck(index >= 0 && index < m_size);
-
- if (m_size == 1) {
- clear();
- }
- else {
- m_buffer[index].~T();
-
- memmove(m_buffer+index, m_buffer+index+1, sizeof(T) * (m_size - 1 - index));
- m_size--;
- }
- }
-
- // Remove the first instance of the given element.
- template <typename T>
- bool Array<T>::remove(const T & element)
- {
- uint index;
- if (find(element, &index)) {
- removeAt(index);
- return true;
- }
- return false;
- }
-
- // Insert the given element at the given index shifting all the elements up.
- template <typename T>
- void Array<T>::insertAt(uint index, const T & val/*=T()*/)
- {
- nvDebugCheck( index >= 0 && index <= m_size );
-
- setArraySize(m_size + 1);
-
- if (index < m_size - 1) {
- memmove(m_buffer+index+1, m_buffer+index, sizeof(T) * (m_size - 1 - index));
- }
-
- // Copy-construct into the newly opened slot.
- new(m_buffer+index) T(val);
- }
-
- // Append the given data to our vector.
- template <typename T>
- NV_FORCEINLINE void Array<T>::append(const Array<T> & other)
- {
- append(other.m_buffer, other.m_size);
- }
-
- // Append the given data to our vector.
- template <typename T>
- void Array<T>::append(const T other[], uint count)
- {
- if (count > 0) {
- const uint old_size = m_size;
-
- setArraySize(m_size + count);
-
- for (uint i = 0; i < count; i++ ) {
- new(m_buffer + old_size + i) T(other[i]);
- }
- }
- }
-
-
- // Remove the given element by replacing it with the last one.
- template <typename T>
- void Array<T>::replaceWithLast(uint index)
- {
- nvDebugCheck( index < m_size );
- nv::swap(m_buffer[index], back()); // @@ Is this OK when index == size-1?
- (m_buffer+m_size-1)->~T();
- m_size--;
- }
-
- // Resize the vector preserving existing elements.
- template <typename T>
- void Array<T>::resize(uint new_size)
- {
- uint old_size = m_size;
-
- // Destruct old elements (if we're shrinking).
- destroy_range(m_buffer, new_size, old_size);
-
- setArraySize(new_size);
-
- // Call default constructors
- construct_range(m_buffer, new_size, old_size);
- }
-
-
- // Resize the vector preserving existing elements and initializing the
- // new ones with the given value.
- template <typename T>
- void Array<T>::resize(uint new_size, const T & elem)
- {
- nvDebugCheck(&elem < m_buffer || &elem > m_buffer+m_size);
-
- uint old_size = m_size;
-
- // Destruct old elements (if we're shrinking).
- destroy_range(m_buffer, new_size, old_size);
-
- setArraySize(new_size);
-
- // Call copy constructors
- construct_range(m_buffer, new_size, old_size, elem);
- }
-
- // Fill array with the given value.
- template <typename T>
- void Array<T>::fill(const T & elem)
- {
- fill(m_buffer, m_size, elem);
- }
-
- // Clear the buffer.
- template <typename T>
- NV_FORCEINLINE void Array<T>::clear()
- {
- nvDebugCheck(isValidPtr(m_buffer));
-
- // Destruct old elements
- destroy_range(m_buffer, 0, m_size);
-
- m_size = 0;
- }
-
- // Shrink the allocated vector.
- template <typename T>
- NV_FORCEINLINE void Array<T>::shrink()
- {
- if (m_size < m_capacity) {
- setArrayCapacity(m_size);
- }
- }
-
- // Preallocate space.
- template <typename T>
- NV_FORCEINLINE void Array<T>::reserve(uint desired_size)
- {
- if (desired_size > m_capacity) {
- setArrayCapacity(desired_size);
- }
- }
-
- // Copy elements to this array. Resizes it if needed.
- template <typename T>
- NV_FORCEINLINE void Array<T>::copy(const T * data, uint count)
- {
-#if 1 // More simple, but maybe not be as efficient?
- destroy_range(m_buffer, 0, m_size);
-
- setArraySize(count);
-
- construct_range(m_buffer, count, 0, data);
-#else
- const uint old_size = m_size;
-
- destroy_range(m_buffer, count, old_size);
-
- setArraySize(count);
-
- copy_range(m_buffer, data, old_size);
-
- construct_range(m_buffer, count, old_size, data);
-#endif
- }
-
- // Assignment operator.
- template <typename T>
- NV_FORCEINLINE Array<T> & Array<T>::operator=( const Array<T> & a )
- {
- copy(a.m_buffer, a.m_size);
- return *this;
- }
-
- // Release ownership of allocated memory and returns pointer to it.
- template <typename T>
- T * Array<T>::release() {
- T * tmp = m_buffer;
- m_buffer = NULL;
- m_capacity = 0;
- m_size = 0;
- return tmp;
- }
-
-
-
- // Change array size.
- template <typename T>
- inline void Array<T>::setArraySize(uint new_size) {
- m_size = new_size;
-
- if (new_size > m_capacity) {
- uint new_buffer_size;
- if (m_capacity == 0) {
- // first allocation is exact
- new_buffer_size = new_size;
- }
- else {
- // following allocations grow array by 25%
- new_buffer_size = new_size + (new_size >> 2);
- }
-
- setArrayCapacity( new_buffer_size );
- }
- }
-
- // Change array capacity.
- template <typename T>
- inline void Array<T>::setArrayCapacity(uint new_capacity) {
- nvDebugCheck(new_capacity >= m_size);
-
- if (new_capacity == 0) {
- // free the buffer.
- if (m_buffer != NULL) {
- free<T>(m_buffer);
- m_buffer = NULL;
- }
- }
- else {
- // realloc the buffer
- m_buffer = realloc<T>(m_buffer, new_capacity);
- }
-
- m_capacity = new_capacity;
- }
-
- // Array serialization.
- template <typename Typ>
- inline Stream & operator<< ( Stream & s, Array<Typ> & p )
- {
- if (s.isLoading()) {
- uint size;
- s << size;
- p.resize( size );
- }
- else {
- s << p.m_size;
- }
-
- for (uint i = 0; i < p.m_size; i++) {
- s << p.m_buffer[i];
- }
-
- return s;
- }
-
- // Swap the members of the two given vectors.
- template <typename Typ>
- inline void swap(Array<Typ> & a, Array<Typ> & b)
- {
- nv::swap(a.m_buffer, b.m_buffer);
- nv::swap(a.m_capacity, b.m_capacity);
- nv::swap(a.m_size, b.m_size);
- }
-
-
-} // nv namespace
-
-// IC: These functions are for compatibility with the Foreach macro in The Witness.
-template <typename T> inline int item_count(const nv::Array<T> & array) { return array.count(); }
-template <typename T> inline const T & item_at(const nv::Array<T> & array, int i) { return array.at(i); }
-template <typename T> inline T & item_at(nv::Array<T> & array, int i) { return array.at(i); }
-template <typename T> inline int item_advance(const nv::Array<T> & array, int i) { return ++i; }
-template <typename T> inline int item_remove(nv::Array<T> & array, int i) { array.replaceWithLast(i); return i - 1; }
-
-template <typename T> inline int item_count(const nv::Array<T> * array) { return array->count(); }
-template <typename T> inline const T & item_at(const nv::Array<T> * array, int i) { return array->at(i); }
-template <typename T> inline T & item_at(nv::Array<T> * array, int i) { return array->at(i); }
-template <typename T> inline int item_advance(const nv::Array<T> * array, int i) { return ++i; }
-template <typename T> inline int item_remove(nv::Array<T> * array, int i) { array->replaceWithLast(i); return i - 1; }
-
-
-#endif // NV_CORE_ARRAY_INL
diff --git a/thirdparty/thekla_atlas/nvcore/BitArray.h b/thirdparty/thekla_atlas/nvcore/BitArray.h
deleted file mode 100644
index 23cf880694..0000000000
--- a/thirdparty/thekla_atlas/nvcore/BitArray.h
+++ /dev/null
@@ -1,250 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#pragma once
-#ifndef NV_CORE_BITARRAY_H
-#define NV_CORE_BITARRAY_H
-
-#include "nvcore.h"
-#include "Array.inl"
-
-namespace nv
-{
-
- // @@ Uh, this could be much faster.
- inline uint countSetBits(uint32 x) {
- uint count = 0;
- for(; x != 0; x >>= 1) {
- count += (x & 1);
- }
- return count;
- }
-
- // @@ This is even more lame. What was I thinking?
- inline uint countSetBits(uint32 x, int bits) {
- uint count = 0;
- for(; x != 0 && bits != 0; x >>= 1, bits--) {
- count += (x & 1);
- }
- return count;
- }
-
- // See "Conditionally set or clear bits without branching" at http://graphics.stanford.edu/~seander/bithacks.html
- inline uint setBits(uint w, uint m, bool b) {
- return (w & ~m) | (-int(b) & m);
- }
-
-
-
- // Simple bit array.
- class BitArray
- {
- public:
-
- BitArray() {}
- BitArray(uint sz) {
- resize(sz);
- }
-
- uint size() const { return m_size; }
- void clear() { resize(0); }
-
- void resize(uint new_size)
- {
- m_size = new_size;
- m_wordArray.resize( (m_size + 31) >> 5 );
- }
-
- void resize(uint new_size, bool init)
- {
- //if (new_size == m_size) return;
-
- uint old_size = m_size;
- uint size_mod_32 = old_size & 31;
- uint last_word_index = ((old_size + 31) >> 5) - 1;
- uint mask = (1 << size_mod_32) - 1;
-
- uint init_dword;
- if (init) {
- if (size_mod_32) m_wordArray[last_word_index] |= ~mask;
- init_dword = ~0;
- }
- else {
- if (size_mod_32) m_wordArray[last_word_index] &= mask;
- init_dword = 0;
- }
-
- m_size = new_size;
- m_wordArray.resize((new_size + 31) >> 5, init_dword);
-
- // Make sure new bits are initialized correctly.
- /*for (uint i = old_size; i < new_size; i++) {
- nvCheck(bitAt(i) == init);
- }*/
- }
-
-
- /// Get bit.
- bool bitAt(uint b) const
- {
- nvDebugCheck( b < m_size );
- return (m_wordArray[b >> 5] & (1 << (b & 31))) != 0;
- }
-
- // It may be useful to pack mulitple bit arrays together interleaving their bits.
- uint bitsAt(uint idx, uint count) const
- {
- //nvDebugCheck(count == 2 || count == 4 || count == 8 || count == 16 || count == 32);
- nvDebugCheck(count == 2); // @@ Hardcoded for two.
- uint b = idx * count;
- nvDebugCheck(b < m_size);
- return (m_wordArray[b >> 5] & (0x3 << (b & 31))) >> (b & 31);
- }
-
- // It would be useful to have a function to set two bits simultaneously.
- /*void setBitsAt(uint idx, uint count, uint bits) const
- {
- //nvDebugCheck(count == 2 || count == 4 || count == 8 || count == 16 || count == 32);
- nvDebugCheck(count == 2); // @@ Hardcoded for two.
- uint b = idx * count;
- nvDebugCheck(b < m_size);
- return (m_wordArray[b >> 5] & (0x3 << (b & 31))) >> (b & 31);
- }*/
-
-
-
- // Set a bit.
- void setBitAt(uint idx)
- {
- nvDebugCheck(idx < m_size);
- m_wordArray[idx >> 5] |= (1 << (idx & 31));
- }
-
- // Clear a bit.
- void clearBitAt(uint idx)
- {
- nvDebugCheck(idx < m_size);
- m_wordArray[idx >> 5] &= ~(1 << (idx & 31));
- }
-
- // Toggle a bit.
- void toggleBitAt(uint idx)
- {
- nvDebugCheck(idx < m_size);
- m_wordArray[idx >> 5] ^= (1 << (idx & 31));
- }
-
- // Set a bit to the given value. @@ Rename modifyBitAt?
- void setBitAt(uint idx, bool b)
- {
- nvDebugCheck(idx < m_size);
- m_wordArray[idx >> 5] = setBits(m_wordArray[idx >> 5], 1 << (idx & 31), b);
- nvDebugCheck(bitAt(idx) == b);
- }
-
- void append(bool value)
- {
- resize(m_size + 1);
- setBitAt(m_size - 1, value);
- }
-
-
- // Clear all the bits.
- void clearAll()
- {
- memset(m_wordArray.buffer(), 0, m_wordArray.size() * sizeof(uint));
- }
-
- // Set all the bits.
- void setAll()
- {
- memset(m_wordArray.buffer(), 0xFF, m_wordArray.size() * sizeof(uint));
- }
-
- // Toggle all the bits.
- void toggleAll()
- {
- const uint wordCount = m_wordArray.count();
- for(uint b = 0; b < wordCount; b++) {
- m_wordArray[b] ^= 0xFFFFFFFF;
- }
- }
-
- // Count the number of bits set.
- uint countSetBits() const
- {
- const uint num = m_wordArray.size();
- if( num == 0 ) {
- return 0;
- }
-
- uint count = 0;
- for(uint i = 0; i < num - 1; i++) {
- count += nv::countSetBits(m_wordArray[i]);
- }
- count += nv::countSetBits(m_wordArray[num - 1], m_size & 31);
-
- //piDebugCheck(count + countClearBits() == m_size);
- return count;
- }
-
- // Count the number of bits clear.
- uint countClearBits() const {
-
- const uint num = m_wordArray.size();
- if( num == 0 ) {
- return 0;
- }
-
- uint count = 0;
- for(uint i = 0; i < num - 1; i++) {
- count += nv::countSetBits(~m_wordArray[i]);
- }
- count += nv::countSetBits(~m_wordArray[num - 1], m_size & 31);
-
- //piDebugCheck(count + countSetBits() == m_size);
- return count;
- }
-
- friend void swap(BitArray & a, BitArray & b)
- {
- swap(a.m_size, b.m_size);
- swap(a.m_wordArray, b.m_wordArray);
- }
-
- void operator &= (const BitArray & other) {
- if (other.m_size != m_size) {
- resize(other.m_size);
- }
-
- const uint wordCount = m_wordArray.count();
- for (uint i = 0; i < wordCount; i++) {
- m_wordArray[i] &= other.m_wordArray[i];
- }
- }
-
- void operator |= (const BitArray & other) {
- if (other.m_size != m_size) {
- resize(other.m_size);
- }
-
- const uint wordCount = m_wordArray.count();
- for (uint i = 0; i < wordCount; i++) {
- m_wordArray[i] |= other.m_wordArray[i];
- }
- }
-
-
- private:
-
- // Number of bits stored.
- uint m_size;
-
- // Array of bits.
- Array<uint> m_wordArray;
-
- };
-
-} // nv namespace
-
-#endif // NV_CORE_BITARRAY_H
-
diff --git a/thirdparty/thekla_atlas/nvcore/Debug.cpp b/thirdparty/thekla_atlas/nvcore/Debug.cpp
deleted file mode 100644
index 4980ffa916..0000000000
--- a/thirdparty/thekla_atlas/nvcore/Debug.cpp
+++ /dev/null
@@ -1,1357 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#include "Debug.h"
-#include "Array.inl"
-#include "StrLib.h" // StringBuilder
-
-#include "StdStream.h" // fileOpen
-
-#include <stdlib.h>
-
-// Extern
-#if NV_OS_WIN32 //&& NV_CC_MSVC
-# define WIN32_LEAN_AND_MEAN
-# define VC_EXTRALEAN
-# include <windows.h>
-# include <direct.h>
-// -- GODOT start -
-# include <crtdbg.h>
-# if _MSC_VER < 1300
-# define DECLSPEC_DEPRECATED
-// VC6: change this path to your Platform SDK headers
-# include <dbghelp.h> // must be XP version of file
-// include "M:\\dev7\\vs\\devtools\\common\\win32sdk\\include\\dbghelp.h"
-# else
-// VC7: ships with updated headers
-# include <dbghelp.h>
-# endif
-// -- GODOT end -
-# pragma comment(lib,"dbghelp.lib")
-#endif
-
-#if NV_OS_XBOX
-# include <Xtl.h>
-# ifdef _DEBUG
-# include <xbdm.h>
-# endif //_DEBUG
-#endif //NV_OS_XBOX
-
-#if !NV_OS_WIN32 && defined(NV_HAVE_SIGNAL_H)
-# include <signal.h>
-#endif
-
-#if NV_OS_UNIX
-# include <unistd.h> // getpid
-#endif
-
-#if NV_OS_LINUX && defined(NV_HAVE_EXECINFO_H)
-# include <execinfo.h> // backtrace
-# if NV_CC_GNUC // defined(NV_HAVE_CXXABI_H)
-# include <cxxabi.h>
-# endif
-#endif
-
-#if NV_OS_DARWIN || NV_OS_FREEBSD || NV_OS_OPENBSD
-# include <sys/types.h>
-# include <sys/param.h>
-# include <sys/sysctl.h> // sysctl
-# if !defined(NV_OS_OPENBSD)
-# include <sys/ucontext.h>
-# endif
-# if defined(NV_HAVE_EXECINFO_H) // only after OSX 10.5
-# include <execinfo.h> // backtrace
-# if NV_CC_GNUC // defined(NV_HAVE_CXXABI_H)
-# include <cxxabi.h>
-# endif
-# endif
-#endif
-
-#if NV_OS_ORBIS
-#include <libdbg.h>
-#endif
-
-#if NV_OS_DURANGO
-#include "Windows.h"
-#include <winnt.h>
-#include <crtdbg.h>
-#include <dbghelp.h>
-#include <errhandlingapi.h>
-#define NV_USE_SEPARATE_THREAD 0
-#else
-#define NV_USE_SEPARATE_THREAD 1
-#endif
-
-
-
-using namespace nv;
-
-namespace
-{
-
- static MessageHandler * s_message_handler = NULL;
- static AssertHandler * s_assert_handler = NULL;
-
- static bool s_sig_handler_enabled = false;
- static bool s_interactive = true;
-
-#if (NV_OS_WIN32 && NV_CC_MSVC) || NV_OS_DURANGO
-
- // Old exception filter.
- static LPTOP_LEVEL_EXCEPTION_FILTER s_old_exception_filter = NULL;
-
-#elif !NV_OS_WIN32 && defined(NV_HAVE_SIGNAL_H)
-
- // Old signal handlers.
- struct sigaction s_old_sigsegv;
- struct sigaction s_old_sigtrap;
- struct sigaction s_old_sigfpe;
- struct sigaction s_old_sigbus;
-
-#endif
-
-// -- GODOT start -
-#if NV_OS_WIN32 || NV_OS_DURANGO
-// -- GODOT end -
-
- // We should try to simplify the top level filter as much as possible.
- // http://www.nynaeve.net/?p=128
-
- // The critical section enforcing the requirement that only one exception be
- // handled by a handler at a time.
- static CRITICAL_SECTION s_handler_critical_section;
-
-#if NV_USE_SEPARATE_THREAD
- // Semaphores used to move exception handling between the exception thread
- // and the handler thread. handler_start_semaphore_ is signalled by the
- // exception thread to wake up the handler thread when an exception occurs.
- // handler_finish_semaphore_ is signalled by the handler thread to wake up
- // the exception thread when handling is complete.
- static HANDLE s_handler_start_semaphore = NULL;
- static HANDLE s_handler_finish_semaphore = NULL;
-
- // The exception handler thread.
- static HANDLE s_handler_thread = NULL;
-
- static DWORD s_requesting_thread_id = 0;
- static EXCEPTION_POINTERS * s_exception_info = NULL;
-
-#endif // NV_USE_SEPARATE_THREAD
-
-
- struct MinidumpCallbackContext {
- ULONG64 memory_base;
- ULONG memory_size;
- bool finished;
- };
-
-#if NV_OS_WIN32
- // static
- static BOOL CALLBACK miniDumpWriteDumpCallback(PVOID context, const PMINIDUMP_CALLBACK_INPUT callback_input, PMINIDUMP_CALLBACK_OUTPUT callback_output)
- {
- switch (callback_input->CallbackType)
- {
- case MemoryCallback: {
- MinidumpCallbackContext* callback_context = reinterpret_cast<MinidumpCallbackContext*>(context);
- if (callback_context->finished)
- return FALSE;
-
- // Include the specified memory region.
- callback_output->MemoryBase = callback_context->memory_base;
- callback_output->MemorySize = callback_context->memory_size;
- callback_context->finished = true;
- return TRUE;
- }
-
- // Include all modules.
- case IncludeModuleCallback:
- case ModuleCallback:
- return TRUE;
-
- // Include all threads.
- case IncludeThreadCallback:
- case ThreadCallback:
- return TRUE;
-
- // Stop receiving cancel callbacks.
- case CancelCallback:
- callback_output->CheckCancel = FALSE;
- callback_output->Cancel = FALSE;
- return TRUE;
- }
-
- // Ignore other callback types.
- return FALSE;
- }
-#endif
-
- static bool writeMiniDump(EXCEPTION_POINTERS * pExceptionInfo)
- {
-#if NV_OS_DURANGO
- // Get a handle to the minidump method.
- typedef BOOL(WINAPI* MiniDumpWriteDumpPfn) (
- _In_ HANDLE hProcess,
- _In_ DWORD ProcessId,
- _In_ HANDLE hFile,
- _In_ MINIDUMP_TYPE DumpType,
- _In_opt_ PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
- _In_opt_ PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
- _Reserved_ PVOID CallbackParam
- );
- MiniDumpWriteDumpPfn MiniDumpWriteDump = NULL;
- HMODULE hToolHelpModule = ::LoadLibraryW(L"toolhelpx.dll");
- if (hToolHelpModule != INVALID_HANDLE_VALUE) {
- MiniDumpWriteDump = reinterpret_cast<MiniDumpWriteDumpPfn>(::GetProcAddress(hToolHelpModule, "MiniDumpWriteDump"));
- if (!MiniDumpWriteDump) {
- FreeLibrary(hToolHelpModule);
- return false;
- }
- }
- else
- return false;
-
- // Generate a decent filename.
- nv::Path application_path(256);
- HINSTANCE hinstance = GetModuleHandle(NULL);
- GetModuleFileName(hinstance, application_path.str(), 256);
- application_path.stripExtension();
- const char * application_name = application_path.fileName();
-
- SYSTEMTIME local_time;
- GetLocalTime(&local_time);
-
- char dump_filename[MAX_PATH] = {};
- sprintf_s(dump_filename, "d:\\%s-%04d%02d%02d-%02d%02d%02d.dmp",
- application_name,
- local_time.wYear, local_time.wMonth, local_time.wDay,
- local_time.wHour, local_time.wMinute, local_time.wSecond );
-#else
- const char* dump_filename = "crash.dmp";
-#endif
-
- // create the file
- HANDLE hFile = CreateFileA(dump_filename, GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
- if (hFile == INVALID_HANDLE_VALUE) {
- //nvDebug("*** Failed to create dump file.\n");
-#if NV_OS_DURANGO
- FreeLibrary(hToolHelpModule);
-#endif
- return false;
- }
-
- MINIDUMP_EXCEPTION_INFORMATION * pExInfo = NULL;
-#if NV_OS_WIN32
- MINIDUMP_CALLBACK_INFORMATION * pCallback = NULL;
-#else
- void * pCallback = NULL;
-#endif
-
- MINIDUMP_EXCEPTION_INFORMATION ExInfo;
- if (pExceptionInfo != NULL) {
- ExInfo.ThreadId = ::GetCurrentThreadId();
- ExInfo.ExceptionPointers = pExceptionInfo;
- ExInfo.ClientPointers = NULL;
- pExInfo = &ExInfo;
-
-#if NV_OS_WIN32
- MINIDUMP_CALLBACK_INFORMATION callback;
- MinidumpCallbackContext context;
-
- // Find a memory region of 256 bytes centered on the
- // faulting instruction pointer.
- const ULONG64 instruction_pointer =
- #if defined(_M_IX86)
- pExceptionInfo->ContextRecord->Eip;
- #elif defined(_M_AMD64)
- pExceptionInfo->ContextRecord->Rip;
- #else
- #error Unsupported platform
- #endif
-
- MEMORY_BASIC_INFORMATION info;
-
- if (VirtualQuery(reinterpret_cast<LPCVOID>(instruction_pointer), &info, sizeof(MEMORY_BASIC_INFORMATION)) != 0 && info.State == MEM_COMMIT)
- {
- // Attempt to get 128 bytes before and after the instruction
- // pointer, but settle for whatever's available up to the
- // boundaries of the memory region.
- const ULONG64 kIPMemorySize = 256;
- context.memory_base = max(reinterpret_cast<ULONG64>(info.BaseAddress), instruction_pointer - (kIPMemorySize / 2));
- ULONG64 end_of_range = min(instruction_pointer + (kIPMemorySize / 2), reinterpret_cast<ULONG64>(info.BaseAddress) + info.RegionSize);
- context.memory_size = static_cast<ULONG>(end_of_range - context.memory_base);
- context.finished = false;
-
- callback.CallbackRoutine = miniDumpWriteDumpCallback;
- callback.CallbackParam = reinterpret_cast<void*>(&context);
- pCallback = &callback;
- }
-#endif
- }
-
- MINIDUMP_TYPE miniDumpType = (MINIDUMP_TYPE)(MiniDumpNormal|MiniDumpWithHandleData|MiniDumpWithThreadInfo);
-
- // write the dump
- BOOL ok = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, miniDumpType, pExInfo, NULL, pCallback) != 0;
- CloseHandle(hFile);
-#if NV_OS_DURANGO
- FreeLibrary(hToolHelpModule);
-#endif
-
- if (ok == FALSE) {
- //nvDebug("*** Failed to save dump file.\n");
- return false;
- }
-
- //nvDebug("\nDump file saved.\n");
-
- return true;
- }
-
-#if NV_USE_SEPARATE_THREAD
-
- static DWORD WINAPI ExceptionHandlerThreadMain(void* lpParameter) {
- nvDebugCheck(s_handler_start_semaphore != NULL);
- nvDebugCheck(s_handler_finish_semaphore != NULL);
-
- while (true) {
- if (WaitForSingleObject(s_handler_start_semaphore, INFINITE) == WAIT_OBJECT_0) {
- writeMiniDump(s_exception_info);
-
- // Allow the requesting thread to proceed.
- ReleaseSemaphore(s_handler_finish_semaphore, 1, NULL);
- }
- }
-
- // This statement is not reached when the thread is unconditionally
- // terminated by the ExceptionHandler destructor.
- return 0;
- }
-
-#endif // NV_USE_SEPARATE_THREAD
-
- static bool hasStackTrace() {
- return true;
- }
-
- /*static NV_NOINLINE int backtrace(void * trace[], int maxcount) {
-
- // In Windows XP and Windows Server 2003, the sum of the FramesToSkip and FramesToCapture parameters must be less than 63.
- int xp_maxcount = min(63-1, maxcount);
-
- int count = RtlCaptureStackBackTrace(1, xp_maxcount, trace, NULL);
- nvDebugCheck(count <= maxcount);
-
- return count;
- }*/
-
-#if NV_OS_WIN32
- static NV_NOINLINE int backtraceWithSymbols(CONTEXT * ctx, void * trace[], int maxcount, int skip = 0) {
-
- // Init the stack frame for this function
- STACKFRAME64 stackFrame = { 0 };
-
- #if NV_CPU_X86_64
- DWORD dwMachineType = IMAGE_FILE_MACHINE_AMD64;
- stackFrame.AddrPC.Offset = ctx->Rip;
- stackFrame.AddrFrame.Offset = ctx->Rbp;
- stackFrame.AddrStack.Offset = ctx->Rsp;
- #elif NV_CPU_X86
- DWORD dwMachineType = IMAGE_FILE_MACHINE_I386;
- stackFrame.AddrPC.Offset = ctx->Eip;
- stackFrame.AddrFrame.Offset = ctx->Ebp;
- stackFrame.AddrStack.Offset = ctx->Esp;
- #else
- #error "Platform not supported!"
- #endif
- stackFrame.AddrPC.Mode = AddrModeFlat;
- stackFrame.AddrFrame.Mode = AddrModeFlat;
- stackFrame.AddrStack.Mode = AddrModeFlat;
-
- // Walk up the stack
- const HANDLE hThread = GetCurrentThread();
- const HANDLE hProcess = GetCurrentProcess();
- int i;
- for (i = 0; i < maxcount; i++)
- {
- // walking once first makes us skip self
- if (!StackWalk64(dwMachineType, hProcess, hThread, &stackFrame, ctx, NULL, &SymFunctionTableAccess64, &SymGetModuleBase64, NULL)) {
- break;
- }
-
- /*if (stackFrame.AddrPC.Offset == stackFrame.AddrReturn.Offset || stackFrame.AddrPC.Offset == 0) {
- break;
- }*/
-
- if (i >= skip) {
- trace[i - skip] = (PVOID)stackFrame.AddrPC.Offset;
- }
- }
-
- return i - skip;
- }
-
-#pragma warning(push)
-#pragma warning(disable:4748)
- static NV_NOINLINE int backtrace(void * trace[], int maxcount) {
- CONTEXT ctx = { 0 };
-// -- GODOT start --
-#if NV_CPU_X86 && !NV_CPU_X86_64
- ctx.ContextFlags = CONTEXT_CONTROL;
-#if NV_CC_MSVC
- _asm {
- call x
- x: pop eax
- mov ctx.Eip, eax
- mov ctx.Ebp, ebp
- mov ctx.Esp, esp
- }
-#else
- register long unsigned int ebp asm("ebp");
- ctx.Eip = (DWORD) __builtin_return_address(0);
- ctx.Ebp = ebp;
- ctx.Esp = (DWORD) __builtin_frame_address(0);
-#endif
-// -- GODOT end --
-#else
- RtlCaptureContext(&ctx); // Not implemented correctly in x86.
-#endif
-
- return backtraceWithSymbols(&ctx, trace, maxcount, 1);
- }
-#pragma warning(pop)
-
- static NV_NOINLINE void writeStackTrace(void * trace[], int size, int start, Array<const char *> & lines)
- {
- StringBuilder builder(512);
-
- HANDLE hProcess = GetCurrentProcess();
-
- // Resolve PC to function names
- for (int i = start; i < size; i++)
- {
- // Check for end of stack walk
- DWORD64 ip = (DWORD64)trace[i];
- if (ip == NULL)
- break;
-
- // Get function name
- #define MAX_STRING_LEN (512)
- unsigned char byBuffer[sizeof(IMAGEHLP_SYMBOL64) + MAX_STRING_LEN] = { 0 };
- IMAGEHLP_SYMBOL64 * pSymbol = (IMAGEHLP_SYMBOL64*)byBuffer;
- pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
- pSymbol->MaxNameLength = MAX_STRING_LEN;
-
- DWORD64 dwDisplacement;
-
- if (SymGetSymFromAddr64(hProcess, ip, &dwDisplacement, pSymbol))
- {
- pSymbol->Name[MAX_STRING_LEN-1] = 0;
-
- /*
- // Make the symbol readable for humans
- UnDecorateSymbolName( pSym->Name, lpszNonUnicodeUnDSymbol, BUFFERSIZE,
- UNDNAME_COMPLETE |
- UNDNAME_NO_THISTYPE |
- UNDNAME_NO_SPECIAL_SYMS |
- UNDNAME_NO_MEMBER_TYPE |
- UNDNAME_NO_MS_KEYWORDS |
- UNDNAME_NO_ACCESS_SPECIFIERS );
- */
-
- // pSymbol->Name
- const char * pFunc = pSymbol->Name;
-
- // Get file/line number
- IMAGEHLP_LINE64 theLine = { 0 };
- theLine.SizeOfStruct = sizeof(theLine);
-
- DWORD dwDisplacement;
- if (!SymGetLineFromAddr64(hProcess, ip, &dwDisplacement, &theLine))
- {
- // Do not print unknown symbols anymore.
- //break;
- builder.format("unknown(%08X) : %s\n", (uint32)ip, pFunc);
- }
- else
- {
- /*
- const char* pFile = strrchr(theLine.FileName, '\\');
- if ( pFile == NULL ) pFile = theLine.FileName;
- else pFile++;
- */
- const char * pFile = theLine.FileName;
-
- int line = theLine.LineNumber;
-
- builder.format("%s(%d) : %s\n", pFile, line, pFunc);
- }
-
- lines.append(builder.release());
-
- if (pFunc != NULL && strcmp(pFunc, "WinMain") == 0) {
- break;
- }
- }
- }
- }
-#endif
-
- // Write mini dump and print stack trace.
- static LONG WINAPI handleException(EXCEPTION_POINTERS * pExceptionInfo)
- {
- EnterCriticalSection(&s_handler_critical_section);
-#if NV_USE_SEPARATE_THREAD
- s_requesting_thread_id = GetCurrentThreadId();
- s_exception_info = pExceptionInfo;
-
- // This causes the handler thread to call writeMiniDump.
- ReleaseSemaphore(s_handler_start_semaphore, 1, NULL);
-
- // Wait until WriteMinidumpWithException is done and collect its return value.
- WaitForSingleObject(s_handler_finish_semaphore, INFINITE);
- //bool status = s_handler_return_value;
-
- // Clean up.
- s_requesting_thread_id = 0;
- s_exception_info = NULL;
-#else
- // First of all, write mini dump.
- writeMiniDump(pExceptionInfo);
-#endif
- LeaveCriticalSection(&s_handler_critical_section);
-
- nvDebug("\nDump file saved.\n");
-
- // Try to attach to debugger.
- if (s_interactive && debug::attachToDebugger()) {
- nvDebugBreak();
- return EXCEPTION_CONTINUE_EXECUTION;
- }
-
-#if NV_OS_WIN32
- // If that fails, then try to pretty print a stack trace and terminate.
- void * trace[64];
-
- int size = backtraceWithSymbols(pExceptionInfo->ContextRecord, trace, 64);
-
- // @@ Use win32's CreateFile?
- FILE * fp = fileOpen("crash.txt", "wb");
- if (fp != NULL) {
- Array<const char *> lines;
- writeStackTrace(trace, size, 0, lines);
-
- for (uint i = 0; i < lines.count(); i++) {
- fputs(lines[i], fp);
- delete lines[i];
- }
-
- // @@ Add more info to crash.txt?
-
- fclose(fp);
- }
-#endif
-
- // This should terminate the process and set the error exit code.
- TerminateProcess(GetCurrentProcess(), EXIT_FAILURE + 2);
-
- return EXCEPTION_EXECUTE_HANDLER; // Terminate app. In case terminate process did not succeed.
- }
-
- static void handlePureVirtualCall() {
- nvDebugBreak();
- TerminateProcess(GetCurrentProcess(), EXIT_FAILURE + 8);
- }
-
- static void handleInvalidParameter(const wchar_t * wexpresion, const wchar_t * wfunction, const wchar_t * wfile, unsigned int line, uintptr_t reserved) {
-
- size_t convertedCharCount = 0;
-
- StringBuilder expresion;
- if (wexpresion != NULL) {
- uint size = U32(wcslen(wexpresion) + 1);
- expresion.reserve(size);
- wcstombs_s(&convertedCharCount, expresion.str(), size, wexpresion, _TRUNCATE);
- }
-
- StringBuilder file;
- if (wfile != NULL) {
- uint size = U32(wcslen(wfile) + 1);
- file.reserve(size);
- wcstombs_s(&convertedCharCount, file.str(), size, wfile, _TRUNCATE);
- }
-
- StringBuilder function;
- if (wfunction != NULL) {
- uint size = U32(wcslen(wfunction) + 1);
- function.reserve(size);
- wcstombs_s(&convertedCharCount, function.str(), size, wfunction, _TRUNCATE);
- }
-
- int result = nvAbort(expresion.str(), file.str(), line, function.str());
- if (result == NV_ABORT_DEBUG) {
- nvDebugBreak();
- }
- }
-
-#elif !NV_OS_WIN32 && defined(NV_HAVE_SIGNAL_H) // NV_OS_LINUX || NV_OS_DARWIN
-
-#if defined(NV_HAVE_EXECINFO_H)
-
- static bool hasStackTrace() {
- return true;
- }
-
-
- static void writeStackTrace(void * trace[], int size, int start, Array<const char *> & lines) {
- StringBuilder builder(512);
- char ** string_array = backtrace_symbols(trace, size);
-
- for(int i = start; i < size-1; i++ ) {
- // IC: Just in case.
- if (string_array[i] == NULL || string_array[i][0] == '\0') break;
-
-# if NV_CC_GNUC // defined(NV_HAVE_CXXABI_H)
- // @@ Write a better parser for the possible formats.
- char * begin = strchr(string_array[i], '(');
- char * end = strrchr(string_array[i], '+');
- char * module = string_array[i];
-
- if (begin == 0 && end != 0) {
- *(end - 1) = '\0';
- begin = strrchr(string_array[i], ' ');
- module = NULL; // Ignore module.
- }
-
- if (begin != 0 && begin < end) {
- int stat;
- *end = '\0';
- *begin = '\0';
- char * name = abi::__cxa_demangle(begin+1, 0, 0, &stat);
- if (module == NULL) {
- if (name == NULL || stat != 0) {
- builder.format(" In: '%s'\n", begin+1);
- }
- else {
- builder.format(" In: '%s'\n", name);
- }
- }
- else {
- if (name == NULL || stat != 0) {
- builder.format(" In: [%s] '%s'\n", module, begin+1);
- }
- else {
- builder.format(" In: [%s] '%s'\n", module, name);
- }
- }
- free(name);
- }
- else {
- builder.format(" In: '%s'\n", string_array[i]);
- }
-# else
- builder.format(" In: '%s'\n", string_array[i]);
-# endif
- lines.append(builder.release());
- }
-
- free(string_array);
- }
-
- static void printStackTrace(void * trace[], int size, int start=0) {
- nvDebug( "\nDumping stacktrace:\n" );
-
- Array<const char *> lines;
- writeStackTrace(trace, size, 1, lines);
-
- for (uint i = 0; i < lines.count(); i++) {
- nvDebug("%s", lines[i]);
- delete lines[i];
- }
-
- nvDebug("\n");
- }
-
-#endif // defined(NV_HAVE_EXECINFO_H)
-
- static void * callerAddress(void * secret)
- {
-#if NV_OS_DARWIN
-# if defined(_STRUCT_MCONTEXT)
-# if NV_CPU_PPC
- ucontext_t * ucp = (ucontext_t *)secret;
- return (void *) ucp->uc_mcontext->__ss.__srr0;
-# elif NV_CPU_X86_64
- ucontext_t * ucp = (ucontext_t *)secret;
- return (void *) ucp->uc_mcontext->__ss.__rip;
-# elif NV_CPU_X86
- ucontext_t * ucp = (ucontext_t *)secret;
- return (void *) ucp->uc_mcontext->__ss.__eip;
-# elif NV_CPU_ARM
- ucontext_t * ucp = (ucontext_t *)secret;
- return (void *) ucp->uc_mcontext->__ss.__pc;
-# else
-# error "Unknown CPU"
-# endif
-# else
-# if NV_CPU_PPC
- ucontext_t * ucp = (ucontext_t *)secret;
- return (void *) ucp->uc_mcontext->ss.srr0;
-# elif NV_CPU_X86
- ucontext_t * ucp = (ucontext_t *)secret;
- return (void *) ucp->uc_mcontext->ss.eip;
-# else
-# error "Unknown CPU"
-# endif
-# endif
-#elif NV_OS_FREEBSD
-# if NV_CPU_X86_64
- ucontext_t * ucp = (ucontext_t *)secret;
- return (void *)ucp->uc_mcontext.mc_rip;
-# elif NV_CPU_X86
- ucontext_t * ucp = (ucontext_t *)secret;
- return (void *)ucp->uc_mcontext.mc_eip;
-# else
-# error "Unknown CPU"
-# endif
-#elif NV_OS_OPENBSD
-# if NV_CPU_X86_64
- ucontext_t * ucp = (ucontext_t *)secret;
- return (void *)ucp->sc_rip;
-# elif NV_CPU_X86
- ucontext_t * ucp = (ucontext_t *)secret;
- return (void *)ucp->sc_eip;
-# else
-# error "Unknown CPU"
-# endif
-#else
-# if NV_CPU_X86_64
- // #define REG_RIP REG_INDEX(rip) // seems to be 16
- ucontext_t * ucp = (ucontext_t *)secret;
- return (void *)ucp->uc_mcontext.gregs[REG_RIP];
-# elif NV_CPU_X86
- ucontext_t * ucp = (ucontext_t *)secret;
- return (void *)ucp->uc_mcontext.gregs[14/*REG_EIP*/];
-# elif NV_CPU_PPC
- ucontext_t * ucp = (ucontext_t *)secret;
- return (void *) ucp->uc_mcontext.regs->nip;
-# else
-# error "Unknown CPU"
-# endif
-#endif
-
- // How to obtain the instruction pointers in different platforms, from mlton's source code.
- // http://mlton.org/
- // OpenBSD && NetBSD
- // ucp->sc_eip
- // FreeBSD:
- // ucp->uc_mcontext.mc_eip
- // HPUX:
- // ucp->uc_link
- // Solaris:
- // ucp->uc_mcontext.gregs[REG_PC]
- // Linux hppa:
- // uc->uc_mcontext.sc_iaoq[0] & ~0x3UL
- // Linux sparc:
- // ((struct sigcontext*) secret)->sigc_regs.tpc
- // Linux sparc64:
- // ((struct sigcontext*) secret)->si_regs.pc
-
- // potentially correct for other archs:
- // Linux alpha: ucp->m_context.sc_pc
- // Linux arm: ucp->m_context.ctx.arm_pc
- // Linux ia64: ucp->m_context.sc_ip & ~0x3UL
- // Linux mips: ucp->m_context.sc_pc
- // Linux s390: ucp->m_context.sregs->regs.psw.addr
- }
-
- static void nvSigHandler(int sig, siginfo_t *info, void *secret)
- {
- void * pnt = callerAddress(secret);
-
- // Do something useful with siginfo_t
- if (sig == SIGSEGV) {
- if (pnt != NULL) nvDebug("Got signal %d, faulty address is %p, from %p\n", sig, info->si_addr, pnt);
- else nvDebug("Got signal %d, faulty address is %p\n", sig, info->si_addr);
- }
- else if(sig == SIGTRAP) {
- nvDebug("Breakpoint hit.\n");
- }
- else {
- nvDebug("Got signal %d\n", sig);
- }
-
-#if defined(NV_HAVE_EXECINFO_H)
- if (hasStackTrace()) // in case of weak linking
- {
- void * trace[64];
- int size = backtrace(trace, 64);
-
- if (pnt != NULL) {
- // Overwrite sigaction with caller's address.
- trace[1] = pnt;
- }
-
- printStackTrace(trace, size, 1);
- }
-#endif // defined(NV_HAVE_EXECINFO_H)
-
- exit(0);
- }
-
-#endif // defined(NV_HAVE_SIGNAL_H)
-
-
-
-#if NV_OS_WIN32 //&& NV_CC_MSVC
-
- /** Win32 assert handler. */
- struct Win32AssertHandler : public AssertHandler
- {
- // Flush the message queue. This is necessary for the message box to show up.
- static void flushMessageQueue()
- {
- MSG msg;
- while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) {
- //if( msg.message == WM_QUIT ) break;
- TranslateMessage( &msg );
- DispatchMessage( &msg );
- }
- }
-
- // Assert handler method.
- virtual int assertion(const char * exp, const char * file, int line, const char * func, const char * msg, va_list arg)
- {
- int ret = NV_ABORT_EXIT;
-
- StringBuilder error_string;
- error_string.format("*** Assertion failed: %s\n On file: %s\n On line: %d\n", exp, file, line );
- if (func != NULL) {
- error_string.appendFormat(" On function: %s\n", func);
- }
- if (msg != NULL) {
- error_string.append(" Message: ");
- va_list tmp;
- va_copy(tmp, arg);
- error_string.appendFormatList(msg, tmp);
- va_end(tmp);
- error_string.append("\n");
- }
- nvDebug( error_string.str() );
-
- // Print stack trace:
- debug::dumpInfo();
-
- if (debug::isDebuggerPresent()) {
- return NV_ABORT_DEBUG;
- }
-
- if (s_interactive) {
- flushMessageQueue();
- int action = MessageBoxA(NULL, error_string.str(), "Assertion failed", MB_ABORTRETRYIGNORE | MB_ICONERROR | MB_TOPMOST);
- switch( action ) {
- case IDRETRY:
- ret = NV_ABORT_DEBUG;
- break;
- case IDIGNORE:
- ret = NV_ABORT_IGNORE;
- break;
- case IDABORT:
- default:
- ret = NV_ABORT_EXIT;
- break;
- }
- /*if( _CrtDbgReport( _CRT_ASSERT, file, line, module, exp ) == 1 ) {
- return NV_ABORT_DEBUG;
- }*/
- }
-
- if (ret == NV_ABORT_EXIT) {
- // Exit cleanly.
- exit(EXIT_FAILURE + 1);
- }
-
- return ret;
- }
- };
-#elif NV_OS_XBOX
-
- /** Xbox360 assert handler. */
- struct Xbox360AssertHandler : public AssertHandler
- {
- // Assert handler method.
- virtual int assertion(const char * exp, const char * file, int line, const char * func, const char * msg, va_list arg)
- {
- int ret = NV_ABORT_EXIT;
-
- StringBuilder error_string;
- if( func != NULL ) {
- error_string.format( "*** Assertion failed: %s\n On file: %s\n On function: %s\n On line: %d\n ", exp, file, func, line );
- nvDebug( error_string.str() );
- }
- else {
- error_string.format( "*** Assertion failed: %s\n On file: %s\n On line: %d\n ", exp, file, line );
- nvDebug( error_string.str() );
- }
-
- if (debug::isDebuggerPresent()) {
- return NV_ABORT_DEBUG;
- }
-
- if( ret == NV_ABORT_EXIT ) {
- // Exit cleanly.
- exit(EXIT_FAILURE + 1);
- }
-
- return ret;
- }
- };
-#elif NV_OS_ORBIS || NV_OS_DURANGO
-
- /** Console assert handler. */
- struct ConsoleAssertHandler : public AssertHandler
- {
- // Assert handler method.
- virtual int assertion(const char * exp, const char * file, int line, const char * func, const char * msg, va_list arg)
- {
- if( func != NULL ) {
- nvDebug( "*** Assertion failed: %s\n On file: %s\n On function: %s\n On line: %d\n ", exp, file, func, line );
- }
- else {
- nvDebug( "*** Assertion failed: %s\n On file: %s\n On line: %d\n ", exp, file, line );
- }
-
- //SBtodoORBIS print stack trace
- /*if (hasStackTrace())
- {
- void * trace[64];
- int size = backtrace(trace, 64);
- printStackTrace(trace, size, 2);
- }*/
-
- if (debug::isDebuggerPresent())
- return NV_ABORT_DEBUG;
-
- return NV_ABORT_IGNORE;
- }
- };
-
-#else
-
- /** Unix assert handler. */
- struct UnixAssertHandler : public AssertHandler
- {
- // Assert handler method.
- virtual int assertion(const char * exp, const char * file, int line, const char * func, const char * msg, va_list arg)
- {
- int ret = NV_ABORT_EXIT;
-
- if( func != NULL ) {
- nvDebug( "*** Assertion failed: %s\n On file: %s\n On function: %s\n On line: %d\n ", exp, file, func, line );
- }
- else {
- nvDebug( "*** Assertion failed: %s\n On file: %s\n On line: %d\n ", exp, file, line );
- }
-
-#if _DEBUG
- if (debug::isDebuggerPresent()) {
- return NV_ABORT_DEBUG;
- }
-#endif
-
-#if defined(NV_HAVE_EXECINFO_H)
- if (hasStackTrace())
- {
- void * trace[64];
- int size = backtrace(trace, 64);
- printStackTrace(trace, size, 2);
- }
-#endif
-
- if( ret == NV_ABORT_EXIT ) {
- // Exit cleanly.
- exit(EXIT_FAILURE + 1);
- }
-
- return ret;
- }
- };
-
-#endif
-
-} // namespace
-
-
-/// Handle assertion through the assert handler.
-int nvAbort(const char * exp, const char * file, int line, const char * func/*=NULL*/, const char * msg/*= NULL*/, ...)
-{
-#if NV_OS_WIN32 //&& NV_CC_MSVC
- static Win32AssertHandler s_default_assert_handler;
-#elif NV_OS_XBOX
- static Xbox360AssertHandler s_default_assert_handler;
-#elif NV_OS_ORBIS || NV_OS_DURANGO
- static ConsoleAssertHandler s_default_assert_handler;
-#else
- static UnixAssertHandler s_default_assert_handler;
-#endif
-
- va_list arg;
- va_start(arg,msg);
-
- AssertHandler * handler = s_assert_handler != NULL ? s_assert_handler : &s_default_assert_handler;
- int result = handler->assertion(exp, file, line, func, msg, arg);
-
- va_end(arg);
-
- return result;
-}
-
-// Abnormal termination. Create mini dump and output call stack.
-void debug::terminate(int code)
-{
-#if NV_OS_WIN32 || NV_OS_DURANGO
- EnterCriticalSection(&s_handler_critical_section);
-
- writeMiniDump(NULL);
-
-#if NV_OS_WIN32
- const int max_stack_size = 64;
- void * trace[max_stack_size];
- int size = backtrace(trace, max_stack_size);
-
- // @@ Use win32's CreateFile?
- FILE * fp = fileOpen("crash.txt", "wb");
- if (fp != NULL) {
- Array<const char *> lines;
- writeStackTrace(trace, size, 0, lines);
-
- for (uint i = 0; i < lines.count(); i++) {
- fputs(lines[i], fp);
- delete lines[i];
- }
-
- // @@ Add more info to crash.txt?
-
- fclose(fp);
- }
-#endif
-
- LeaveCriticalSection(&s_handler_critical_section);
-#endif
-
- exit(code);
-}
-
-
-/// Shows a message through the message handler.
-void NV_CDECL nvDebugPrint(const char *msg, ...)
-{
- va_list arg;
- va_start(arg,msg);
- if (s_message_handler != NULL) {
- s_message_handler->log( msg, arg );
- }
- else {
- vprintf(msg, arg);
- }
- va_end(arg);
-}
-
-
-/// Dump debug info.
-void debug::dumpInfo()
-{
-#if (NV_OS_WIN32 && NV_CC_MSVC) || (defined(NV_HAVE_SIGNAL_H) && defined(NV_HAVE_EXECINFO_H))
- if (hasStackTrace())
- {
- void * trace[64];
- int size = backtrace(trace, 64);
-
- nvDebug( "\nDumping stacktrace:\n" );
-
- Array<const char *> lines;
- writeStackTrace(trace, size, 1, lines);
-
- for (uint i = 0; i < lines.count(); i++) {
- nvDebug("%s", lines[i]);
- delete lines[i];
- }
- }
-#endif
-}
-
-/// Dump callstack using the specified handler.
-void debug::dumpCallstack(MessageHandler *messageHandler, int callstackLevelsToSkip /*= 0*/)
-{
-#if (NV_OS_WIN32 && NV_CC_MSVC) || (defined(NV_HAVE_SIGNAL_H) && defined(NV_HAVE_EXECINFO_H))
- if (hasStackTrace())
- {
- void * trace[64];
- int size = backtrace(trace, 64);
-
- Array<const char *> lines;
- writeStackTrace(trace, size, callstackLevelsToSkip + 1, lines); // + 1 to skip the call to dumpCallstack
-
- for (uint i = 0; i < lines.count(); i++) {
- messageHandler->log(lines[i], NULL);
- delete lines[i];
- }
- }
-#endif
-}
-
-
-/// Set the debug message handler.
-void debug::setMessageHandler(MessageHandler * message_handler)
-{
- s_message_handler = message_handler;
-}
-
-/// Reset the debug message handler.
-void debug::resetMessageHandler()
-{
- s_message_handler = NULL;
-}
-
-/// Set the assert handler.
-void debug::setAssertHandler(AssertHandler * assert_handler)
-{
- s_assert_handler = assert_handler;
-}
-
-/// Reset the assert handler.
-void debug::resetAssertHandler()
-{
- s_assert_handler = NULL;
-}
-
-#if NV_OS_WIN32 || NV_OS_DURANGO
-#if NV_USE_SEPARATE_THREAD
-
-static void initHandlerThread()
-{
- static const int kExceptionHandlerThreadInitialStackSize = 64 * 1024;
-
- // Set synchronization primitives and the handler thread. Each
- // ExceptionHandler object gets its own handler thread because that's the
- // only way to reliably guarantee sufficient stack space in an exception,
- // and it allows an easy way to get a snapshot of the requesting thread's
- // context outside of an exception.
- InitializeCriticalSection(&s_handler_critical_section);
-
- s_handler_start_semaphore = CreateSemaphoreExW(NULL, 0, 1, NULL, 0,
- SEMAPHORE_MODIFY_STATE | DELETE | SYNCHRONIZE);
- nvDebugCheck(s_handler_start_semaphore != NULL);
-
- s_handler_finish_semaphore = CreateSemaphoreExW(NULL, 0, 1, NULL, 0,
- SEMAPHORE_MODIFY_STATE | DELETE | SYNCHRONIZE);
- nvDebugCheck(s_handler_finish_semaphore != NULL);
-
- // Don't attempt to create the thread if we could not create the semaphores.
- if (s_handler_finish_semaphore != NULL && s_handler_start_semaphore != NULL) {
- DWORD thread_id;
- s_handler_thread = CreateThread(NULL, // lpThreadAttributes
- kExceptionHandlerThreadInitialStackSize,
- ExceptionHandlerThreadMain,
- NULL, // lpParameter
- 0, // dwCreationFlags
- &thread_id);
- nvDebugCheck(s_handler_thread != NULL);
- }
-
- /* @@ We should avoid loading modules in the exception handler!
- dbghelp_module_ = LoadLibrary(L"dbghelp.dll");
- if (dbghelp_module_) {
- minidump_write_dump_ = reinterpret_cast<MiniDumpWriteDump_type>(GetProcAddress(dbghelp_module_, "MiniDumpWriteDump"));
- }
- */
-}
-
-static void shutHandlerThread() {
- // @@ Free stuff. Terminate thread.
-}
-
-#endif // NV_USE_SEPARATE_THREAD
-#endif // NV_OS_WIN32
-
-
-// Enable signal handler.
-void debug::enableSigHandler(bool interactive)
-{
- if (s_sig_handler_enabled) return;
-
- s_sig_handler_enabled = true;
- s_interactive = interactive;
-
-#if (NV_OS_WIN32 && NV_CC_MSVC) || NV_OS_DURANGO
- if (interactive) {
-#if NV_OS_WIN32
- // Do not display message boxes on error.
- // http://msdn.microsoft.com/en-us/library/windows/desktop/ms680621(v=vs.85).aspx
- SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOGPFAULTERRORBOX|SEM_NOOPENFILEERRORBOX);
-#endif
-
- // CRT reports errors to debug output only.
- // http://msdn.microsoft.com/en-us/library/1y71x448(v=vs.80).aspx
- _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG);
- _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
- _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
- }
-
-
-#if NV_USE_SEPARATE_THREAD
- initHandlerThread();
-#else
- InitializeCriticalSection(&s_handler_critical_section);
-#endif
-
- s_old_exception_filter = ::SetUnhandledExceptionFilter( handleException );
-
-#if _MSC_VER >= 1400 // MSVC 2005/8
- _set_invalid_parameter_handler(handleInvalidParameter);
-#endif // _MSC_VER >= 1400
-
- _set_purecall_handler(handlePureVirtualCall);
-
-#if NV_OS_WIN32
- // SYMOPT_DEFERRED_LOADS make us not take a ton of time unless we actual log traces
- SymSetOptions(SYMOPT_DEFERRED_LOADS|SYMOPT_FAIL_CRITICAL_ERRORS|SYMOPT_LOAD_LINES|SYMOPT_UNDNAME);
-
- if (!SymInitialize(GetCurrentProcess(), NULL, TRUE)) {
- DWORD error = GetLastError();
- nvDebug("SymInitialize returned error : %d\n", error);
- }
-#endif
-
-#elif !NV_OS_WIN32 && defined(NV_HAVE_SIGNAL_H)
-
- // Install our signal handler
- struct sigaction sa;
- sa.sa_sigaction = nvSigHandler;
- sigemptyset (&sa.sa_mask);
- sa.sa_flags = SA_ONSTACK | SA_RESTART | SA_SIGINFO;
-
- sigaction(SIGSEGV, &sa, &s_old_sigsegv);
- sigaction(SIGTRAP, &sa, &s_old_sigtrap);
- sigaction(SIGFPE, &sa, &s_old_sigfpe);
- sigaction(SIGBUS, &sa, &s_old_sigbus);
-
-#endif
-}
-
-/// Disable signal handler.
-void debug::disableSigHandler()
-{
- nvCheck(s_sig_handler_enabled == true);
- s_sig_handler_enabled = false;
-
-#if (NV_OS_WIN32 && NV_CC_MSVC) || NV_OS_DURANGO
-
- ::SetUnhandledExceptionFilter( s_old_exception_filter );
- s_old_exception_filter = NULL;
-
-#if NV_OS_WIN32
- SymCleanup(GetCurrentProcess());
-#endif
-
-#elif !NV_OS_WIN32 && defined(NV_HAVE_SIGNAL_H)
-
- sigaction(SIGSEGV, &s_old_sigsegv, NULL);
- sigaction(SIGTRAP, &s_old_sigtrap, NULL);
- sigaction(SIGFPE, &s_old_sigfpe, NULL);
- sigaction(SIGBUS, &s_old_sigbus, NULL);
-
-#endif
-}
-
-
-bool debug::isDebuggerPresent()
-{
-#if NV_OS_WIN32
- HINSTANCE kernel32 = GetModuleHandleA("kernel32.dll");
- if (kernel32) {
- FARPROC IsDebuggerPresent = GetProcAddress(kernel32, "IsDebuggerPresent");
- if (IsDebuggerPresent != NULL && IsDebuggerPresent()) {
- return true;
- }
- }
- return false;
-#elif NV_OS_XBOX
-#ifdef _DEBUG
- return DmIsDebuggerPresent() == TRUE;
-#else
- return false;
-#endif
-#elif NV_OS_ORBIS
- #if PS4_FINAL_REQUIREMENTS
- return false;
- #else
- return sceDbgIsDebuggerAttached() == 1;
- #endif
-#elif NV_OS_DURANGO
- #if XB1_FINAL_REQUIREMENTS
- return false;
- #else
- return IsDebuggerPresent() == TRUE;
- #endif
-#elif NV_OS_DARWIN
- int mib[4];
- struct kinfo_proc info;
- size_t size;
- mib[0] = CTL_KERN;
- mib[1] = KERN_PROC;
- mib[2] = KERN_PROC_PID;
- mib[3] = getpid();
- size = sizeof(info);
- info.kp_proc.p_flag = 0;
- sysctl(mib,4,&info,&size,NULL,0);
- return ((info.kp_proc.p_flag & P_TRACED) == P_TRACED);
-#else
- // if ppid != sid, some process spawned our app, probably a debugger.
- return getsid(getpid()) != getppid();
-#endif
-}
-
-bool debug::attachToDebugger()
-{
-#if NV_OS_WIN32
- if (isDebuggerPresent() == FALSE) {
- Path process(1024);
- process.copy("\"");
- GetSystemDirectoryA(process.str() + 1, 1024 - 1);
-
- process.appendSeparator();
-
- process.appendFormat("VSJitDebugger.exe\" -p %lu", ::GetCurrentProcessId());
-
- STARTUPINFOA sSi;
- memset(&sSi, 0, sizeof(sSi));
-
- PROCESS_INFORMATION sPi;
- memset(&sPi, 0, sizeof(sPi));
-
- BOOL b = CreateProcessA(NULL, process.str(), NULL, NULL, FALSE, 0, NULL, NULL, &sSi, &sPi);
- if (b != FALSE) {
- ::WaitForSingleObject(sPi.hProcess, INFINITE);
-
- DWORD dwExitCode;
- ::GetExitCodeProcess(sPi.hProcess, &dwExitCode);
- if (dwExitCode != 0) //if exit code is zero, a debugger was selected
- b = FALSE;
- }
-
- if (sPi.hThread != NULL) ::CloseHandle(sPi.hThread);
- if (sPi.hProcess != NULL) ::CloseHandle(sPi.hProcess);
-
- if (b == FALSE)
- return false;
-
- for (int i = 0; i < 5*60; i++) {
- if (isDebuggerPresent())
- break;
- ::Sleep(200);
- }
- }
-#endif // NV_OS_WIN32
-
- return true;
-}
diff --git a/thirdparty/thekla_atlas/nvcore/Debug.h b/thirdparty/thekla_atlas/nvcore/Debug.h
deleted file mode 100644
index 3804ed4763..0000000000
--- a/thirdparty/thekla_atlas/nvcore/Debug.h
+++ /dev/null
@@ -1,246 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#pragma once
-#ifndef NV_CORE_DEBUG_H
-#define NV_CORE_DEBUG_H
-
-#include "nvcore.h"
-
-#include <stdarg.h> // va_list
-
-#if NV_OS_IOS //ACS: maybe we want this for OSX too?
-# ifdef __APPLE__
-# include <TargetConditionals.h>
-# include <signal.h>
-# endif
-#endif
-
-// Make sure we are using our assert.
-#undef assert
-
-#define NV_ABORT_DEBUG 1
-#define NV_ABORT_IGNORE 2
-#define NV_ABORT_EXIT 3
-
-#define nvNoAssert(exp) \
- NV_MULTI_LINE_MACRO_BEGIN \
- (void)sizeof(exp); \
- NV_MULTI_LINE_MACRO_END
-
-#if NV_NO_ASSERT
-
-# define nvAssert(exp) nvNoAssert(exp)
-# define nvCheck(exp) nvNoAssert(exp)
-# define nvDebugAssert(exp) nvNoAssert(exp)
-# define nvDebugCheck(exp) nvNoAssert(exp)
-# define nvDebugBreak() nvNoAssert(0)
-
-#else // NV_NO_ASSERT
-
-# if NV_CC_MSVC
- // @@ Does this work in msvc-6 and earlier?
-# define nvDebugBreak() __debugbreak()
-//# define nvDebugBreak() __asm { int 3 }
-# elif NV_OS_ORBIS
-# define nvDebugBreak() __debugbreak()
-# elif NV_OS_IOS && TARGET_OS_IPHONE
-# define nvDebugBreak() raise(SIGINT)
-# elif NV_CC_CLANG
-# define nvDebugBreak() __builtin_debugtrap()
-# elif NV_CC_GNUC
-//# define nvDebugBreak() __builtin_debugtrap() // Does GCC have debugtrap?
-# define nvDebugBreak() __builtin_trap()
-/*
-# elif NV_CC_GNUC && NV_CPU_PPC && NV_OS_DARWIN
-// @@ Use __builtin_trap() on GCC
-# define nvDebugBreak() __asm__ volatile ("trap")
-# elif NV_CC_GNUC && NV_CPU_X86 && NV_OS_DARWIN
-# define nvDebugBreak() __asm__ volatile ("int3")
-# elif NV_CC_GNUC && NV_CPU_X86
-# define nvDebugBreak() __asm__ ( "int %0" : :"I"(3) )
-# elif NV_OS_ORBIS
-# define nvDebugBreak() __asm volatile ("int $0x41")
-# else
-# include <signal.h>
-# define nvDebugBreak() raise(SIGTRAP);
-// define nvDebugBreak() *((int *)(0)) = 0
-*/
-# endif
-
-# if NV_CC_MSVC
-# define nvExpect(expr) (expr)
-#else
-# define nvExpect(expr) __builtin_expect((expr) != 0, true)
-#endif
-
-#if NV_CC_CLANG
-# if __has_feature(attribute_analyzer_noreturn)
-# define NV_ANALYZER_NORETURN __attribute__((analyzer_noreturn))
-# else
-# define NV_ANALYZER_NORETURN
-# endif
-#else
-# define NV_ANALYZER_NORETURN
-#endif
-
-#define nvDebugBreakOnce() \
- NV_MULTI_LINE_MACRO_BEGIN \
- static bool firstTime = true; \
- if (firstTime) { firstTime = false; nvDebugBreak(); } \
- NV_MULTI_LINE_MACRO_END
-
-#define nvAssertMacro(exp) \
- NV_MULTI_LINE_MACRO_BEGIN \
- if (!nvExpect(exp)) { \
- if (nvAbort(#exp, __FILE__, __LINE__, __FUNC__) == NV_ABORT_DEBUG) { \
- nvDebugBreak(); \
- } \
- } \
- NV_MULTI_LINE_MACRO_END
-
-// GCC, LLVM need "##" before the __VA_ARGS__, MSVC doesn't care
-#define nvAssertMacroWithIgnoreAll(exp,...) \
- NV_MULTI_LINE_MACRO_BEGIN \
- static bool ignoreAll = false; \
- if (!ignoreAll && !nvExpect(exp)) { \
- int _result = nvAbort(#exp, __FILE__, __LINE__, __FUNC__, ##__VA_ARGS__); \
- if (_result == NV_ABORT_DEBUG) { \
- nvDebugBreak(); \
- } else if (_result == NV_ABORT_IGNORE) { \
- ignoreAll = true; \
- } \
- } \
- NV_MULTI_LINE_MACRO_END
-
-// Interesting assert macro from Insomniac:
-// http://www.gdcvault.com/play/1015319/Developing-Imperfect-Software-How-to
-// Used as follows:
-// if (nvCheck(i < count)) {
-// normal path
-// } else {
-// fixup code.
-// }
-// This style of macro could be combined with __builtin_expect to let the compiler know failure is unlikely.
-#define nvCheckMacro(exp) \
- (\
- (exp) ? true : ( \
- (nvAbort(#exp, __FILE__, __LINE__, __FUNC__) == NV_ABORT_DEBUG) ? (nvDebugBreak(), true) : ( false ) \
- ) \
- )
-
-
-#define nvAssert(exp) nvAssertMacro(exp)
-#define nvCheck(exp) nvAssertMacro(exp)
-
-#if defined(_DEBUG)
-# define nvDebugAssert(exp) nvAssertMacro(exp)
-# define nvDebugCheck(exp) nvAssertMacro(exp)
-#else // _DEBUG
-# define nvDebugAssert(exp) nvNoAssert(exp)
-# define nvDebugCheck(exp) nvNoAssert(exp)
-#endif // _DEBUG
-
-#endif // NV_NO_ASSERT
-
-// Use nvAssume for very simple expresions only: nvAssume(0), nvAssume(value == true), etc.
-/*#if !defined(_DEBUG)
-# if NV_CC_MSVC
-# define nvAssume(exp) __assume(exp)
-# else
-# define nvAssume(exp) nvCheck(exp)
-# endif
-#else
-# define nvAssume(exp) nvCheck(exp)
-#endif*/
-
-#if defined(_DEBUG)
-# if NV_CC_MSVC
-# define nvUnreachable() nvAssert(0 && "unreachable"); __assume(0)
-# else
-# define nvUnreachable() nvAssert(0 && "unreachable"); __builtin_unreachable()
-# endif
-#else
-# if NV_CC_MSVC
-# define nvUnreachable() __assume(0)
-# else
-# define nvUnreachable() __builtin_unreachable()
-# endif
-#endif
-
-#define nvError(x) nvAbort(x, __FILE__, __LINE__, __FUNC__)
-#define nvWarning(x) nvDebugPrint("*** Warning %s/%d: %s\n", __FILE__, __LINE__, (x))
-
-#ifndef NV_DEBUG_PRINT
-#define NV_DEBUG_PRINT 1 //defined(_DEBUG)
-#endif
-
-#if NV_DEBUG_PRINT
-#define nvDebug(...) nvDebugPrint(__VA_ARGS__)
-#else
-#if NV_CC_MSVC
-#define nvDebug(...) __noop(__VA_ARGS__)
-#else
-#define nvDebug(...) ((void)0) // Non-msvc platforms do not evaluate arguments?
-#endif
-#endif
-
-
-NVCORE_API int nvAbort(const char *exp, const char *file, int line, const char * func = NULL, const char * msg = NULL, ...) __attribute__((format (printf, 5, 6))) NV_ANALYZER_NORETURN;
-NVCORE_API void NV_CDECL nvDebugPrint( const char *msg, ... ) __attribute__((format (printf, 1, 2)));
-
-namespace nv
-{
- inline bool isValidPtr(const void * ptr) {
- #if NV_OS_DARWIN
- return true; // IC: Not sure what ranges are OK on OSX.
- #endif
-
- #if NV_CPU_X86_64
- if (ptr == NULL) return true;
- if (reinterpret_cast<uint64>(ptr) < 0x10000ULL) return false;
- if (reinterpret_cast<uint64>(ptr) >= 0x000007FFFFFEFFFFULL) return false;
- #else
- if (reinterpret_cast<uintptr_t>(ptr) == 0xcccccccc) return false;
- if (reinterpret_cast<uintptr_t>(ptr) == 0xcdcdcdcd) return false;
- if (reinterpret_cast<uintptr_t>(ptr) == 0xdddddddd) return false;
- if (reinterpret_cast<uintptr_t>(ptr) == 0xffffffff) return false;
- #endif
- return true;
- }
-
- // Message handler interface.
- struct MessageHandler {
- virtual void log(const char * str, va_list arg) = 0;
- virtual ~MessageHandler() {}
- };
-
- // Assert handler interface.
- struct AssertHandler {
- virtual int assertion(const char *exp, const char *file, int line, const char *func, const char *msg, va_list arg) = 0;
- virtual ~AssertHandler() {}
- };
-
-
- namespace debug
- {
- NVCORE_API void dumpInfo();
- NVCORE_API void dumpCallstack( MessageHandler *messageHandler, int callstackLevelsToSkip = 0 );
-
- NVCORE_API void setMessageHandler( MessageHandler * messageHandler );
- NVCORE_API void resetMessageHandler();
-
- NVCORE_API void setAssertHandler( AssertHandler * assertHanlder );
- NVCORE_API void resetAssertHandler();
-
- NVCORE_API void enableSigHandler(bool interactive);
- NVCORE_API void disableSigHandler();
-
- NVCORE_API bool isDebuggerPresent();
- NVCORE_API bool attachToDebugger();
-
- NVCORE_API void terminate(int code);
- }
-
-} // nv namespace
-
-#endif // NV_CORE_DEBUG_H
diff --git a/thirdparty/thekla_atlas/nvcore/DefsGnucDarwin.h b/thirdparty/thekla_atlas/nvcore/DefsGnucDarwin.h
deleted file mode 100644
index afb21c3d25..0000000000
--- a/thirdparty/thekla_atlas/nvcore/DefsGnucDarwin.h
+++ /dev/null
@@ -1,57 +0,0 @@
-#ifndef NV_CORE_H
-#error "Do not include this file directly."
-#endif
-
-#include <stdint.h> // uint8_t, int8_t, ... uintptr_t
-#include <stddef.h> // operator new, size_t, NULL
-
-// Function linkage
-#define DLL_IMPORT
-#if __GNUC__ >= 4
-# define DLL_EXPORT __attribute__((visibility("default")))
-# define DLL_EXPORT_CLASS DLL_EXPORT
-#else
-# define DLL_EXPORT
-# define DLL_EXPORT_CLASS
-#endif
-
-// Function calling modes
-#if NV_CPU_X86
-# define NV_CDECL __attribute__((cdecl))
-# define NV_STDCALL __attribute__((stdcall))
-#else
-# define NV_CDECL
-# define NV_STDCALL
-#endif
-
-#define NV_FASTCALL __attribute__((fastcall))
-#define NV_FORCEINLINE __attribute__((always_inline)) inline
-#define NV_DEPRECATED __attribute__((deprecated))
-#if NV_OS_IOS
-#define NV_THREAD_LOCAL // @@ IC: Looks like iOS does not have support for TLS declarations.
-#else
-#define NV_THREAD_LOCAL __thread
-#endif
-
-#if __GNUC__ > 2
-#define NV_PURE __attribute__((pure))
-#define NV_CONST __attribute__((const))
-#else
-#define NV_PURE
-#define NV_CONST
-#endif
-
-#define NV_NOINLINE __attribute__((noinline))
-
-// Define __FUNC__ properly.
-#if __STDC_VERSION__ < 199901L
-# if __GNUC__ >= 2
-# define __FUNC__ __PRETTY_FUNCTION__ // __FUNCTION__
-# else
-# define __FUNC__ "<unknown>"
-# endif
-#else
-# define __FUNC__ __PRETTY_FUNCTION__
-#endif
-
-#define restrict __restrict__
diff --git a/thirdparty/thekla_atlas/nvcore/DefsGnucLinux.h b/thirdparty/thekla_atlas/nvcore/DefsGnucLinux.h
deleted file mode 100644
index 2126d866f5..0000000000
--- a/thirdparty/thekla_atlas/nvcore/DefsGnucLinux.h
+++ /dev/null
@@ -1,59 +0,0 @@
-#ifndef NV_CORE_H
-#error "Do not include this file directly."
-#endif
-
-#include <stdint.h> // uint8_t, int8_t, ... uintptr_t
-#include <stddef.h> // operator new, size_t, NULL
-
-// Function linkage
-#define DLL_IMPORT
-#if __GNUC__ >= 4
-# define DLL_EXPORT __attribute__((visibility("default")))
-# define DLL_EXPORT_CLASS DLL_EXPORT
-#else
-# define DLL_EXPORT
-# define DLL_EXPORT_CLASS
-#endif
-
-// Function calling modes
-#if NV_CPU_X86
-# define NV_CDECL __attribute__((cdecl))
-# define NV_STDCALL __attribute__((stdcall))
-#else
-# define NV_CDECL
-# define NV_STDCALL
-#endif
-
-#define NV_FASTCALL __attribute__((fastcall))
-//#if __GNUC__ > 3
-// It seems that GCC does not assume always_inline implies inline. I think this depends on the GCC version :(
-#define NV_FORCEINLINE inline __attribute__((always_inline))
-//#else
-// Some compilers complain that inline and always_inline are redundant.
-//#define NV_FORCEINLINE __attribute__((always_inline))
-//#endif
-#define NV_DEPRECATED __attribute__((deprecated))
-#define NV_THREAD_LOCAL __thread
-
-#if __GNUC__ > 2
-#define NV_PURE __attribute__((pure))
-#define NV_CONST __attribute__((const))
-#else
-#define NV_PURE
-#define NV_CONST
-#endif
-
-#define NV_NOINLINE __attribute__((noinline))
-
-// Define __FUNC__ properly.
-#if __STDC_VERSION__ < 199901L
-# if __GNUC__ >= 2
-# define __FUNC__ __PRETTY_FUNCTION__ // __FUNCTION__
-# else
-# define __FUNC__ "<unknown>"
-# endif
-#else
-# define __FUNC__ __PRETTY_FUNCTION__
-#endif
-
-#define restrict __restrict__
diff --git a/thirdparty/thekla_atlas/nvcore/DefsGnucWin32.h b/thirdparty/thekla_atlas/nvcore/DefsGnucWin32.h
deleted file mode 100644
index e1c8d6e4f8..0000000000
--- a/thirdparty/thekla_atlas/nvcore/DefsGnucWin32.h
+++ /dev/null
@@ -1,67 +0,0 @@
-#ifndef NV_CORE_H
-#error "Do not include this file directly."
-#endif
-
-//#include <cstddef> // size_t, NULL
-
-// Function linkage
-#define DLL_IMPORT __declspec(dllimport)
-#define DLL_EXPORT __declspec(dllexport)
-#define DLL_EXPORT_CLASS DLL_EXPORT
-
-// Function calling modes
-#if NV_CPU_X86
-# define NV_CDECL __attribute__((cdecl))
-# define NV_STDCALL __attribute__((stdcall))
-#else
-# define NV_CDECL
-# define NV_STDCALL
-#endif
-
-#define NV_FASTCALL __attribute__((fastcall))
-// -- GODOT start -
-#define NV_FORCEINLINE __attribute__((always_inline)) inline
-// -- GODOT end -
-#define NV_DEPRECATED __attribute__((deprecated))
-
-#if __GNUC__ > 2
-#define NV_PURE __attribute__((pure))
-#define NV_CONST __attribute__((const))
-#else
-#define NV_PURE
-#define NV_CONST
-#endif
-
-#define NV_NOINLINE __attribute__((noinline))
-
-// Define __FUNC__ properly.
-#if __STDC_VERSION__ < 199901L
-# if __GNUC__ >= 2
-# define __FUNC__ __PRETTY_FUNCTION__ // __FUNCTION__
-# else
-# define __FUNC__ "<unknown>"
-# endif
-#else
-# define __FUNC__ __PRETTY_FUNCTION__
-#endif
-
-#define restrict __restrict__
-
-/*
-// Type definitions
-typedef unsigned char uint8;
-typedef signed char int8;
-
-typedef unsigned short uint16;
-typedef signed short int16;
-
-typedef unsigned int uint32;
-typedef signed int int32;
-
-typedef unsigned long long uint64;
-typedef signed long long int64;
-
-// Aliases
-typedef uint32 uint;
-*/
-
diff --git a/thirdparty/thekla_atlas/nvcore/DefsVcWin32.h b/thirdparty/thekla_atlas/nvcore/DefsVcWin32.h
deleted file mode 100644
index a915f3791a..0000000000
--- a/thirdparty/thekla_atlas/nvcore/DefsVcWin32.h
+++ /dev/null
@@ -1,94 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#ifndef NV_CORE_H
-#error "Do not include this file directly."
-#endif
-
-// Function linkage
-#define DLL_IMPORT __declspec(dllimport)
-#define DLL_EXPORT __declspec(dllexport)
-#define DLL_EXPORT_CLASS DLL_EXPORT
-
-// Function calling modes
-#define NV_CDECL __cdecl
-#define NV_STDCALL __stdcall
-#define NV_FASTCALL __fastcall
-#define NV_DEPRECATED
-
-#define NV_PURE
-#define NV_CONST
-
-// Set standard function names.
-#if _MSC_VER < 1900
-# define snprintf _snprintf
-#endif
-#if _MSC_VER < 1500
-# define vsnprintf _vsnprintf
-#endif
-#if _MSC_VER < 1700
-# define strtoll _strtoi64
-# define strtoull _strtoui64
-#endif
-//#define chdir _chdir
-#define getcwd _getcwd
-
-#if _MSC_VER <= 1600
-#define va_copy(a, b) (a) = (b)
-#endif
-
-#if !defined restrict
-#define restrict
-#endif
-
-// Ignore gcc attributes.
-#define __attribute__(X)
-
-#if !defined __FUNC__
-#define __FUNC__ __FUNCTION__
-#endif
-
-#define NV_NOINLINE __declspec(noinline)
-#define NV_FORCEINLINE __forceinline
-
-#define NV_THREAD_LOCAL __declspec(thread)
-
-/*
-// Type definitions
-typedef unsigned char uint8;
-typedef signed char int8;
-
-typedef unsigned short uint16;
-typedef signed short int16;
-
-typedef unsigned int uint32;
-typedef signed int int32;
-
-typedef unsigned __int64 uint64;
-typedef signed __int64 int64;
-
-// Aliases
-typedef uint32 uint;
-*/
-
-// Unwanted VC++ warnings to disable.
-/*
-#pragma warning(disable : 4244) // conversion to float, possible loss of data
-#pragma warning(disable : 4245) // conversion from 'enum ' to 'unsigned long', signed/unsigned mismatch
-#pragma warning(disable : 4100) // unreferenced formal parameter
-#pragma warning(disable : 4514) // unreferenced inline function has been removed
-#pragma warning(disable : 4710) // inline function not expanded
-#pragma warning(disable : 4127) // Conditional expression is constant
-#pragma warning(disable : 4305) // truncation from 'const double' to 'float'
-#pragma warning(disable : 4505) // unreferenced local function has been removed
-
-#pragma warning(disable : 4702) // unreachable code in inline expanded function
-#pragma warning(disable : 4711) // function selected for automatic inlining
-#pragma warning(disable : 4725) // Pentium fdiv bug
-
-#pragma warning(disable : 4786) // Identifier was truncated and cannot be debugged.
-
-#pragma warning(disable : 4675) // resolved overload was found by argument-dependent lookup
-*/
-
-#pragma warning(1 : 4705) // Report unused local variables.
-#pragma warning(1 : 4555) // Expression has no effect.
diff --git a/thirdparty/thekla_atlas/nvcore/FileSystem.cpp b/thirdparty/thekla_atlas/nvcore/FileSystem.cpp
deleted file mode 100644
index 5ed0ca074f..0000000000
--- a/thirdparty/thekla_atlas/nvcore/FileSystem.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-// This code is in the public domain -- castano@gmail.com
-
-#include "FileSystem.h"
-
-#if NV_OS_WIN32
-#define _CRT_NONSTDC_NO_WARNINGS // _chdir is defined deprecated, but that's a bug, chdir is deprecated, _chdir is *not*.
-//#include <shlwapi.h> // PathFileExists
-#include <windows.h> // GetFileAttributes
-#include <direct.h> // _mkdir
-#elif NV_OS_XBOX
-#include <Xtl.h>
-#elif NV_OS_DURANGO
-#include <Windows.h>
-#else
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-#endif
-#include <stdio.h> // remove, unlink
-
-using namespace nv;
-
-
-bool FileSystem::exists(const char * path)
-{
-#if NV_OS_UNIX
- return access(path, F_OK|R_OK) == 0;
- //struct stat buf;
- //return stat(path, &buf) == 0;
-#elif NV_OS_WIN32 || NV_OS_XBOX || NV_OS_DURANGO
- // PathFileExists requires linking to shlwapi.lib
- //return PathFileExists(path) != 0;
- return GetFileAttributesA(path) != INVALID_FILE_ATTRIBUTES;
-#else
- if (FILE * fp = fopen(path, "r"))
- {
- fclose(fp);
- return true;
- }
- return false;
-#endif
-}
-
-bool FileSystem::createDirectory(const char * path)
-{
-#if NV_OS_WIN32 || NV_OS_XBOX || NV_OS_DURANGO
- return CreateDirectoryA(path, NULL) != 0;
-#elif NV_OS_ORBIS
- // not implemented
- return false;
-#else
- return mkdir(path, 0777) != -1;
-#endif
-}
-
-bool FileSystem::changeDirectory(const char * path)
-{
-#if NV_OS_WIN32
- return _chdir(path) != -1;
-#elif NV_OS_XBOX || NV_OS_DURANGO
- // Xbox doesn't support Current Working Directory!
- return false;
-#elif NV_OS_ORBIS
- // Orbis doesn't support Current Working Directory!
- return false;
-#else
- return chdir(path) != -1;
-#endif
-}
-
-bool FileSystem::removeFile(const char * path)
-{
- // @@ Use unlink or remove?
- return remove(path) == 0;
-}
diff --git a/thirdparty/thekla_atlas/nvcore/FileSystem.h b/thirdparty/thekla_atlas/nvcore/FileSystem.h
deleted file mode 100644
index afd0f449d3..0000000000
--- a/thirdparty/thekla_atlas/nvcore/FileSystem.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// This code is in the public domain -- castano@gmail.com
-
-#pragma once
-#ifndef NV_CORE_FILESYSTEM_H
-#define NV_CORE_FILESYSTEM_H
-
-#include "nvcore.h"
-
-namespace nv
-{
-
- namespace FileSystem
- {
- NVCORE_API bool exists(const char * path);
- NVCORE_API bool createDirectory(const char * path);
- NVCORE_API bool changeDirectory(const char * path);
- NVCORE_API bool removeFile(const char * path);
-
- } // FileSystem namespace
-
-} // nv namespace
-
-
-#endif // NV_CORE_FILESYSTEM_H
diff --git a/thirdparty/thekla_atlas/nvcore/ForEach.h b/thirdparty/thekla_atlas/nvcore/ForEach.h
deleted file mode 100644
index bc66f424ef..0000000000
--- a/thirdparty/thekla_atlas/nvcore/ForEach.h
+++ /dev/null
@@ -1,71 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#pragma once
-#ifndef NV_CORE_FOREACH_H
-#define NV_CORE_FOREACH_H
-
-/*
-These foreach macros are very non-standard and somewhat confusing, but I like them.
-*/
-
-#include "nvcore.h"
-
-
-#if NV_CC_CPP11
-
-#define NV_FOREACH(i, container) \
- for (auto i = (container).start(); !(container).isDone(i); (container).advance(i))
-
-#elif NV_CC_GNUC // If typeof is available:
-
-/*
-Ideally we would like to write this:
-
-#define NV_FOREACH(i, container) \
- for(decltype(container)::PseudoIndex i((container).start()); !(container).isDone(i); (container).advance(i))
-
-But gcc versions prior to 4.7 required an intermediate type. See:
-https://gcc.gnu.org/bugzilla/show_bug.cgi?id=6709
-*/
-
-#define NV_FOREACH(i, container) \
- typedef typeof(container) NV_STRING_JOIN2(cont,__LINE__); \
- for(NV_STRING_JOIN2(cont,__LINE__)::PseudoIndex i((container).start()); !(container).isDone(i); (container).advance(i))
-
-#else // If typeof not available:
-
-#define NV_NEED_PSEUDOINDEX_WRAPPER 1
-
-#include <new> // placement new
-
-struct PseudoIndexWrapper {
- template <typename T>
- PseudoIndexWrapper(const T & container) {
- nvStaticCheck(sizeof(typename T::PseudoIndex) <= sizeof(memory));
- new (memory) typename T::PseudoIndex(container.start());
- }
- // PseudoIndex cannot have a dtor!
-
- template <typename T> typename T::PseudoIndex & operator()(const T * /*container*/) {
- return *reinterpret_cast<typename T::PseudoIndex *>(memory);
- }
- template <typename T> const typename T::PseudoIndex & operator()(const T * /*container*/) const {
- return *reinterpret_cast<const typename T::PseudoIndex *>(memory);
- }
-
- uint8 memory[4]; // Increase the size if we have bigger enumerators.
-};
-
-#define NV_FOREACH(i, container) \
- for(PseudoIndexWrapper i(container); !(container).isDone(i(&(container))); (container).advance(i(&(container))))
-
-#endif
-
-// Declare foreach keyword.
-#if !defined NV_NO_USE_KEYWORDS
-# define foreach NV_FOREACH
-# define foreach_index NV_FOREACH
-#endif
-
-
-#endif // NV_CORE_FOREACH_H
diff --git a/thirdparty/thekla_atlas/nvcore/Hash.h b/thirdparty/thekla_atlas/nvcore/Hash.h
deleted file mode 100644
index a8b0b2c63b..0000000000
--- a/thirdparty/thekla_atlas/nvcore/Hash.h
+++ /dev/null
@@ -1,83 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#pragma once
-#ifndef NV_CORE_HASH_H
-#define NV_CORE_HASH_H
-
-#include "nvcore.h"
-
-namespace nv
-{
- inline uint sdbmHash(const void * data_in, uint size, uint h = 5381)
- {
- const uint8 * data = (const uint8 *) data_in;
- uint i = 0;
- while (i < size) {
- h = (h << 16) + (h << 6) - h + (uint) data[i++];
- }
- return h;
- }
-
- // Note that this hash does not handle NaN properly.
- inline uint sdbmFloatHash(const float * f, uint count, uint h = 5381)
- {
- for (uint i = 0; i < count; i++) {
- //nvDebugCheck(nv::isFinite(*f));
- union { float f; uint32 i; } x = { f[i] };
- if (x.i == 0x80000000) x.i = 0;
- h = sdbmHash(&x, 4, h);
- }
- return h;
- }
-
-
- template <typename T>
- inline uint hash(const T & t, uint h = 5381)
- {
- return sdbmHash(&t, sizeof(T), h);
- }
-
- template <>
- inline uint hash(const float & f, uint h)
- {
- return sdbmFloatHash(&f, 1, h);
- }
-
-
- // Functors for hash table:
- template <typename Key> struct Hash
- {
- uint operator()(const Key & k) const {
- return hash(k);
- }
- };
-
- template <typename Key> struct Equal
- {
- bool operator()(const Key & k0, const Key & k1) const {
- return k0 == k1;
- }
- };
-
-
- // @@ Move to Utils.h?
- template <typename T1, typename T2>
- struct Pair {
- T1 first;
- T2 second;
- };
-
- template <typename T1, typename T2>
- bool operator==(const Pair<T1,T2> & p0, const Pair<T1,T2> & p1) {
- return p0.first == p1.first && p0.second == p1.second;
- }
-
- template <typename T1, typename T2>
- uint hash(const Pair<T1,T2> & p, uint h = 5381) {
- return hash(p.second, hash(p.first));
- }
-
-
-} // nv namespace
-
-#endif // NV_CORE_HASH_H
diff --git a/thirdparty/thekla_atlas/nvcore/HashMap.h b/thirdparty/thekla_atlas/nvcore/HashMap.h
deleted file mode 100644
index 7856d6a8c9..0000000000
--- a/thirdparty/thekla_atlas/nvcore/HashMap.h
+++ /dev/null
@@ -1,174 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#pragma once
-#ifndef NV_CORE_HASHMAP_H
-#define NV_CORE_HASHMAP_H
-
-/*
-HashMap based on Thatcher Ulrich <tu@tulrich.com> container, donated to the Public Domain.
-
-I'd like to do something to reduce the amount of code generated with this template. The type of
-U is largely irrelevant to the generated code, except for calls to constructors and destructors,
-but the combination of all T and U pairs, generate a large amounts of code.
-
-HashMap is not used in NVTT, so it could be removed from the repository.
-*/
-
-
-#include "Memory.h"
-#include "Debug.h"
-#include "ForEach.h"
-#include "Hash.h"
-
-namespace nv
-{
- class Stream;
-
- /** Thatcher Ulrich's hash table.
- *
- * Hash table, linear probing, internal chaining. One
- * interesting/nice thing about this implementation is that the table
- * itself is a flat chunk of memory containing no pointers, only
- * relative indices. If the key and value types of the hash contain
- * no pointers, then the hash can be serialized using raw IO. Could
- * come in handy.
- *
- * Never shrinks, unless you explicitly clear() it. Expands on
- * demand, though. For best results, if you know roughly how big your
- * table will be, default it to that size when you create it.
- */
- template<typename T, typename U, typename H = Hash<T>, typename E = Equal<T> >
- class NVCORE_CLASS HashMap
- {
- NV_FORBID_COPY(HashMap);
- public:
-
- /// Default ctor.
- HashMap() : entry_count(0), size_mask(-1), table(NULL) { }
-
- /// Ctor with size hint.
- explicit HashMap(int size_hint) : entry_count(0), size_mask(-1), table(NULL) { setCapacity(size_hint); }
-
- /// Dtor.
- ~HashMap() { clear(); }
-
-
- void set(const T& key, const U& value);
- void add(const T& key, const U& value);
- bool remove(const T& key);
- void clear();
- bool isEmpty() const;
- bool get(const T& key, U* value = NULL, T* other_key = NULL) const;
- bool contains(const T & key) const;
- int size() const;
- int count() const;
- int capacity() const;
- void checkExpand();
- void resize(int n);
-
- void setCapacity(int new_size);
-
- // Behaves much like std::pair.
- struct Entry
- {
- int next_in_chain; // internal chaining for collisions
- uint hash_value; // avoids recomputing. Worthwhile?
- T key;
- U value;
-
- Entry() : next_in_chain(-2) {}
- Entry(const Entry& e) : next_in_chain(e.next_in_chain), hash_value(e.hash_value), key(e.key), value(e.value) {}
- Entry(const T& k, const U& v, int next, int hash) : next_in_chain(next), hash_value(hash), key(k), value(v) {}
-
- bool isEmpty() const { return next_in_chain == -2; }
- bool isEndOfChain() const { return next_in_chain == -1; }
- bool isTombstone() const { return hash_value == TOMBSTONE_HASH; }
-
- void clear() {
- key.~T(); // placement delete
- value.~U(); // placement delete
- next_in_chain = -2;
- hash_value = ~TOMBSTONE_HASH;
- }
-
- void makeTombstone() {
- key.~T();
- value.~U();
- hash_value = TOMBSTONE_HASH;
- }
- };
-
-
- // HashMap enumerator.
- typedef int PseudoIndex;
- PseudoIndex start() const { PseudoIndex i = 0; findNext(i); return i; }
- bool isDone(const PseudoIndex & i) const { nvDebugCheck(i <= size_mask+1); return i == size_mask+1; };
- void advance(PseudoIndex & i) const { nvDebugCheck(i <= size_mask+1); i++; findNext(i); }
-
-#if NV_NEED_PSEUDOINDEX_WRAPPER
- Entry & operator[]( const PseudoIndexWrapper & i ) {
- Entry & e = entry(i(this));
- nvDebugCheck(e.isTombstone() == false);
- return e;
- }
- const Entry & operator[]( const PseudoIndexWrapper & i ) const {
- const Entry & e = entry(i(this));
- nvDebugCheck(e.isTombstone() == false);
- return e;
- }
-#else
- Entry & operator[](const PseudoIndex & i) {
- Entry & e = entry(i);
- nvDebugCheck(e.isTombstone() == false);
- return e;
- }
- const Entry & operator[](const PseudoIndex & i) const {
- const Entry & e = entry(i);
- nvDebugCheck(e.isTombstone() == false);
- return e;
- }
-#endif
-
-
- // By default we serialize the key-value pairs compactl y.
- template<typename _T, typename _U, typename _H, typename _E>
- friend Stream & operator<< (Stream & s, HashMap<_T, _U, _H, _E> & map);
-
- // This requires more storage, but saves us from rehashing the elements.
- template<typename _T, typename _U, typename _H, typename _E>
- friend Stream & rawSerialize(Stream & s, HashMap<_T, _U, _H, _E> & map);
-
- /// Swap the members of this vector and the given vector.
- template<typename _T, typename _U, typename _H, typename _E>
- friend void swap(HashMap<_T, _U, _H, _E> & a, HashMap<_T, _U, _H, _E> & b);
-
- private:
- static const uint TOMBSTONE_HASH = (uint) -1;
-
- uint compute_hash(const T& key) const;
-
- // Find the index of the matching entry. If no match, then return -1.
- int findIndex(const T& key) const;
-
- // Return the index of the newly cleared element.
- int removeTombstone(int index);
-
- // Helpers.
- Entry & entry(int index);
- const Entry & entry(int index) const;
-
- void setRawCapacity(int new_size);
-
- // Move the enumerator to the next valid element.
- void findNext(PseudoIndex & i) const;
-
-
- int entry_count;
- int size_mask;
- Entry * table;
-
- };
-
-} // nv namespace
-
-#endif // NV_CORE_HASHMAP_H
diff --git a/thirdparty/thekla_atlas/nvcore/HashMap.inl b/thirdparty/thekla_atlas/nvcore/HashMap.inl
deleted file mode 100644
index f0b6bfea62..0000000000
--- a/thirdparty/thekla_atlas/nvcore/HashMap.inl
+++ /dev/null
@@ -1,550 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#pragma once
-#ifndef NV_CORE_HASHMAP_INL
-#define NV_CORE_HASHMAP_INL
-
-#include "HashMap.h"
-
-#include "Stream.h"
-#include "Utils.h" // swap
-
-#include <new> // for placement new
-
-
-namespace nv
-{
-
- // Set a new or existing value under the key, to the value.
- template<typename T, typename U, typename H, typename E>
- void HashMap<T, U, H, E>::set(const T& key, const U& value)
- {
- int index = findIndex(key);
- if (index >= 0)
- {
- entry(index).value = value;
- return;
- }
-
- // Entry under key doesn't exist.
- add(key, value);
- }
-
-
- // Add a new value to the hash table, under the specified key.
- template<typename T, typename U, typename H, typename E>
- void HashMap<T, U, H, E>::add(const T& key, const U& value)
- {
- nvCheck(findIndex(key) == -1);
-
- checkExpand();
- nvCheck(table != NULL);
- entry_count++;
-
- const uint hash_value = compute_hash(key);
- const int index = hash_value & size_mask;
-
- Entry * natural_entry = &(entry(index));
-
- if (natural_entry->isEmpty())
- {
- // Put the new entry in.
- new (natural_entry) Entry(key, value, -1, hash_value);
- }
- else if (natural_entry->isTombstone()) {
- // Put the new entry in, without disturbing the rest of the chain.
- int next_in_chain = natural_entry->next_in_chain;
- new (natural_entry) Entry(key, value, next_in_chain, hash_value);
- }
- else
- {
- // Find a blank spot.
- int blank_index = index;
- for (int search_count = 0; ; search_count++)
- {
- blank_index = (blank_index + 1) & size_mask;
- if (entry(blank_index).isEmpty()) break; // found it
- if (entry(blank_index).isTombstone()) {
- blank_index = removeTombstone(blank_index);
- break;
- }
- nvCheck(search_count < this->size_mask);
- }
- Entry * blank_entry = &entry(blank_index);
-
- if (int(natural_entry->hash_value & size_mask) == index)
- {
- // Collision. Link into this chain.
-
- // Move existing list head.
- new (blank_entry) Entry(*natural_entry); // placement new, copy ctor
-
- // Put the new info in the natural entry.
- natural_entry->key = key;
- natural_entry->value = value;
- natural_entry->next_in_chain = blank_index;
- natural_entry->hash_value = hash_value;
- }
- else
- {
- // Existing entry does not naturally
- // belong in this slot. Existing
- // entry must be moved.
-
- // Find natural location of collided element (i.e. root of chain)
- int collided_index = natural_entry->hash_value & size_mask;
- for (int search_count = 0; ; search_count++)
- {
- Entry * e = &entry(collided_index);
- if (e->next_in_chain == index)
- {
- // Here's where we need to splice.
- new (blank_entry) Entry(*natural_entry);
- e->next_in_chain = blank_index;
- break;
- }
- collided_index = e->next_in_chain;
- nvCheck(collided_index >= 0 && collided_index <= size_mask);
- nvCheck(search_count <= size_mask);
- }
-
- // Put the new data in the natural entry.
- natural_entry->key = key;
- natural_entry->value = value;
- natural_entry->hash_value = hash_value;
- natural_entry->next_in_chain = -1;
- }
- }
- }
-
-
- // Remove the first value under the specified key.
- template<typename T, typename U, typename H, typename E>
- bool HashMap<T, U, H, E>::remove(const T& key)
- {
- if (table == NULL)
- {
- return false;
- }
-
- int index = findIndex(key);
- if (index < 0)
- {
- return false;
- }
-
- Entry * pos = &entry(index);
-
- int natural_index = (int) (pos->hash_value & size_mask);
-
- if (index != natural_index) {
- // We're not the head of our chain, so we can
- // be spliced out of it.
-
- // Iterate up the chain, and splice out when
- // we get to m_index.
- Entry* e = &entry(natural_index);
- while (e->next_in_chain != index) {
- nvDebugCheck(e->isEndOfChain() == false);
- e = &entry(e->next_in_chain);
- }
-
- if (e->isTombstone() && pos->isEndOfChain()) {
- // Tombstone has nothing else to point
- // to, so mark it empty.
- e->next_in_chain = -2;
- } else {
- e->next_in_chain = pos->next_in_chain;
- }
-
- pos->clear();
- }
- else if (pos->isEndOfChain() == false) {
- // We're the head of our chain, and there are
- // additional elements.
- //
- // We need to put a tombstone here.
- //
- // We can't clear the element, because the
- // rest of the elements in the chain must be
- // linked to this position.
- //
- // We can't move any of the succeeding
- // elements in the chain (i.e. to fill this
- // entry), because we don't want to invalidate
- // any other existing iterators.
- pos->makeTombstone();
- } else {
- // We're the head of the chain, but we're the
- // only member of the chain.
- pos->clear();
- }
-
- entry_count--;
-
- return true;
- }
-
-
- // Remove all entries from the hash table.
- template<typename T, typename U, typename H, typename E>
- void HashMap<T, U, H, E>::clear()
- {
- if (table != NULL)
- {
- // Delete the entries.
- for (int i = 0, n = size_mask; i <= n; i++)
- {
- Entry * e = &entry(i);
- if (e->isEmpty() == false && e->isTombstone() == false)
- {
- e->clear();
- }
- }
- free(table);
- table = NULL;
- entry_count = 0;
- size_mask = -1;
- }
- }
-
-
- // Returns true if the hash is empty.
- template<typename T, typename U, typename H, typename E>
- bool HashMap<T, U, H, E>::isEmpty() const
- {
- return table == NULL || entry_count == 0;
- }
-
-
- // Retrieve the value under the given key.
- // - If there's no value under the key, then return false and leave *value alone.
- // - If there is a value, return true, and set *value to the entry's value.
- // - If value == NULL, return true or false according to the presence of the key, but don't touch *value.
- template<typename T, typename U, typename H, typename E>
- bool HashMap<T, U, H, E>::get(const T& key, U* value/*= NULL*/, T* other_key/*= NULL*/) const
- {
- int index = findIndex(key);
- if (index >= 0)
- {
- if (value != NULL) {
- *value = entry(index).value; // take care with side-effects!
- }
- if (other_key != NULL) {
- *other_key = entry(index).key;
- }
- return true;
- }
- return false;
- }
-
- // Determine if the given key is contained in the hash.
- template<typename T, typename U, typename H, typename E>
- bool HashMap<T, U, H, E>::contains(const T & key) const
- {
- return get(key);
- }
-
- // Number of entries in the hash.
- template<typename T, typename U, typename H, typename E>
- int HashMap<T, U, H, E>::size() const
- {
- return entry_count;
- }
-
- // Number of entries in the hash.
- template<typename T, typename U, typename H, typename E>
- int HashMap<T, U, H, E>::count() const
- {
- return size();
- }
-
- template<typename T, typename U, typename H, typename E>
- int HashMap<T, U, H, E>::capacity() const
- {
- return size_mask+1;
- }
-
-
- // Resize the hash table to fit one more entry. Often this doesn't involve any action.
- template<typename T, typename U, typename H, typename E>
- void HashMap<T, U, H, E>::checkExpand()
- {
- if (table == NULL) {
- // Initial creation of table. Make a minimum-sized table.
- setRawCapacity(16);
- }
- else if (entry_count * 3 > (size_mask + 1) * 2) {
- // Table is more than 2/3rds full. Expand.
- setRawCapacity(entry_count * 2);
- }
- }
-
-
- // Hint the bucket count to >= n.
- template<typename T, typename U, typename H, typename E>
- void HashMap<T, U, H, E>::resize(int n)
- {
- // Not really sure what this means in relation to
- // STLport's hash_map... they say they "increase the
- // bucket count to at least n" -- but does that mean
- // their real capacity after resize(n) is more like
- // n*2 (since they do linked-list chaining within
- // buckets?).
- setCapacity(n);
- }
-
-
- // Size the hash so that it can comfortably contain the given number of elements. If the hash already contains more
- // elements than new_size, then this may be a no-op.
- template<typename T, typename U, typename H, typename E>
- void HashMap<T, U, H, E>::setCapacity(int new_size)
- {
- int new_raw_size = (new_size * 3) / 2;
- if (new_raw_size < size()) { return; }
-
- setRawCapacity(new_raw_size);
- }
-
-
- // By default we serialize the key-value pairs compactly.
- template<typename _T, typename _U, typename _H, typename _E>
- Stream & operator<< (Stream & s, HashMap<_T, _U, _H, _E> & map)
- {
- typedef typename HashMap<_T, _U, _H, _E>::Entry HashMapEntry;
-
- int entry_count = map.entry_count;
- s << entry_count;
-
- if (s.isLoading()) {
- map.clear();
- if(entry_count == 0) {
- return s;
- }
- map.entry_count = entry_count;
- map.size_mask = nextPowerOfTwo(U32(entry_count)) - 1;
- map.table = malloc<HashMapEntry>(map.size_mask + 1);
-
- for (int i = 0; i <= map.size_mask; i++) {
- map.table[i].next_in_chain = -2; // mark empty
- }
-
- _T key;
- _U value;
- for (int i = 0; i < entry_count; i++) {
- s << key << value;
- map.add(key, value);
- }
- }
- else {
- int i = 0;
- map.findNext(i);
- while (i != map.size_mask+1) {
- HashMapEntry & e = map.entry(i);
-
- s << e.key << e.value;
-
- i++;
- map.findNext(i);
- }
- //for(HashMap<_T, _U, _H, _E>::PseudoIndex i((map).start()); !(map).isDone(i); (map).advance(i)) {
- //foreach(i, map) {
- // s << map[i].key << map[i].value;
- //}
- }
-
- return s;
- }
-
- // This requires more storage, but saves us from rehashing the elements.
- template<typename _T, typename _U, typename _H, typename _E>
- Stream & rawSerialize(Stream & s, HashMap<_T, _U, _H, _E> & map)
- {
- typedef typename HashMap<_T, _U, _H, _E>::Entry HashMapEntry;
-
- if (s.isLoading()) {
- map.clear();
- }
-
- s << map.size_mask;
-
- if (map.size_mask != -1) {
- s << map.entry_count;
-
- if (s.isLoading()) {
- map.table = new HashMapEntry[map.size_mask+1];
- }
-
- for (int i = 0; i <= map.size_mask; i++) {
- HashMapEntry & e = map.table[i];
- s << e.next_in_chain << e.hash_value;
- s << e.key;
- s << e.value;
- }
- }
-
- return s;
- }
-
- // Swap the members of this vector and the given vector.
- template<typename _T, typename _U, typename _H, typename _E>
- void swap(HashMap<_T, _U, _H, _E> & a, HashMap<_T, _U, _H, _E> & b)
- {
- swap(a.entry_count, b.entry_count);
- swap(a.size_mask, b.size_mask);
- swap(a.table, b.table);
- }
-
-
- template<typename T, typename U, typename H, typename E>
- uint HashMap<T, U, H, E>::compute_hash(const T& key) const
- {
- H hash;
- uint hash_value = hash(key);
- if (hash_value == TOMBSTONE_HASH) {
- hash_value ^= 0x8000;
- }
- return hash_value;
- }
-
- // Find the index of the matching entry. If no match, then return -1.
- template<typename T, typename U, typename H, typename E>
- int HashMap<T, U, H, E>::findIndex(const T& key) const
- {
- if (table == NULL) return -1;
-
- E equal;
-
- uint hash_value = compute_hash(key);
- int index = hash_value & size_mask;
-
- const Entry * e = &entry(index);
- if (e->isEmpty()) return -1;
- if (e->isTombstone() == false && int(e->hash_value & size_mask) != index) {
- // occupied by a collider
- return -1;
- }
-
- for (;;)
- {
- nvCheck(e->isTombstone() || (e->hash_value & size_mask) == (hash_value & size_mask));
-
- if (e->hash_value == hash_value && equal(e->key, key))
- {
- // Found it.
- return index;
- }
- nvDebugCheck(e->isTombstone() || !equal(e->key, key)); // keys are equal, but hash differs!
-
- // Keep looking through the chain.
- index = e->next_in_chain;
- if (index == -1) break; // end of chain
-
- nvCheck(index >= 0 && index <= size_mask);
- e = &entry(index);
-
- nvCheck(e->isEmpty() == false || e->isTombstone());
- }
- return -1;
- }
-
- // Return the index of the newly cleared element.
- template<typename T, typename U, typename H, typename E>
- int HashMap<T, U, H, E>::removeTombstone(int index) {
- Entry* e = &entry(index);
- nvCheck(e->isTombstone());
- nvCheck(!e->isEndOfChain());
-
- // Move the next element of the chain into the
- // tombstone slot, and return the vacated element.
- int new_blank_index = e->next_in_chain;
- Entry* new_blank = &entry(new_blank_index);
- new (e) Entry(*new_blank);
- new_blank->clear();
- return new_blank_index;
- }
-
- // Helpers.
- template<typename T, typename U, typename H, typename E>
- typename HashMap<T, U, H, E>::Entry & HashMap<T, U, H, E>::entry(int index)
- {
- nvDebugCheck(table != NULL);
- nvDebugCheck(index >= 0 && index <= size_mask);
- return table[index];
- }
- template<typename T, typename U, typename H, typename E>
- const typename HashMap<T, U, H, E>::Entry & HashMap<T, U, H, E>::entry(int index) const
- {
- nvDebugCheck(table != NULL);
- nvDebugCheck(index >= 0 && index <= size_mask);
- return table[index];
- }
-
-
- // Resize the hash table to the given size (Rehash the contents of the current table). The arg is the number of
- // hash table entries, not the number of elements we should actually contain (which will be less than this).
- template<typename T, typename U, typename H, typename E>
- void HashMap<T, U, H, E>::setRawCapacity(int new_size)
- {
- if (new_size <= 0) {
- // Special case.
- clear();
- return;
- }
-
- // Force new_size to be a power of two.
- new_size = nextPowerOfTwo(U32(new_size));
-
- HashMap<T, U, H, E> new_hash;
- new_hash.table = malloc<Entry>(new_size);
- nvDebugCheck(new_hash.table != NULL);
-
- new_hash.entry_count = 0;
- new_hash.size_mask = new_size - 1;
- for (int i = 0; i < new_size; i++)
- {
- new_hash.entry(i).next_in_chain = -2; // mark empty
- }
-
- // Copy stuff to new_hash
- if (table != NULL)
- {
- for (int i = 0, n = size_mask; i <= n; i++)
- {
- Entry * e = &entry(i);
- if (e->isEmpty() == false && e->isTombstone() == false)
- {
- // Insert old entry into new hash.
- new_hash.add(e->key, e->value);
- e->clear(); // placement delete of old element
- }
- }
-
- // Delete our old data buffer.
- free(table);
- }
-
- // Steal new_hash's data.
- entry_count = new_hash.entry_count;
- size_mask = new_hash.size_mask;
- table = new_hash.table;
- new_hash.entry_count = 0;
- new_hash.size_mask = -1;
- new_hash.table = NULL;
- }
-
- // Move the enumerator to the next valid element.
- template<typename T, typename U, typename H, typename E>
- void HashMap<T, U, H, E>::findNext(PseudoIndex & i) const {
- while (i <= size_mask) {
- const Entry & e = entry(i);
- if (e.isEmpty() == false && e.isTombstone() == false) {
- break;
- }
- i++;
- }
- }
-
-} // nv namespace
-
-#endif // NV_CORE_HASHMAP_INL
diff --git a/thirdparty/thekla_atlas/nvcore/Memory.cpp b/thirdparty/thekla_atlas/nvcore/Memory.cpp
deleted file mode 100644
index 302a2d84cb..0000000000
--- a/thirdparty/thekla_atlas/nvcore/Memory.cpp
+++ /dev/null
@@ -1,153 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#include "Memory.h"
-#include "Debug.h"
-#include "Utils.h"
-
-#include <stdlib.h>
-
-#ifdef NV_OS_LINUX
-#include <malloc.h>
-#endif
-
-#define USE_EFENCE 0
-
-#if USE_EFENCE
-extern "C" void *EF_malloc(size_t size);
-extern "C" void *EF_realloc(void * oldBuffer, size_t newSize);
-extern "C" void EF_free(void * address);
-#endif
-
-using namespace nv;
-
-#if NV_OVERRIDE_ALLOC
-
-void * malloc(size_t size)
-{
-#if USE_EFENCE
- return EF_malloc(size);
-#else
- return ::malloc(size);
-#endif
-}
-
-void * debug_malloc(size_t size, const char * file, int line)
-{
- NV_UNUSED(file);
- NV_UNUSED(line);
-#if USE_EFENCE
- return EF_malloc(size);
-#else
- return ::malloc(size);
-#endif
-}
-
-void free(void * ptr)
-{
-#if USE_EFENCE
- return EF_free(const_cast<void *>(ptr));
-#else
- ::free(const_cast<void *>(ptr));
-#endif
-}
-
-void * realloc(void * ptr, size_t size)
-{
- nvDebugCheck(ptr != NULL || size != 0); // undefined realloc behavior.
-#if USE_EFENCE
- return EF_realloc(ptr, size);
-#else
- return ::realloc(ptr, size);
-#endif
-}
-
-
-/* No need to override this unless we want line info.
-void * operator new (size_t size) throw()
-{
- return malloc(size);
-}
-
-void operator delete (void *p) throw()
-{
- free(p);
-}
-
-void * operator new [] (size_t size) throw()
-{
- return malloc(size);
-}
-
-void operator delete [] (void * p) throw()
-{
- free(p);
-}
-*/
-
-#if 0 // Code from Apple:
-void* operator new(std::size_t sz) throw (std::bad_alloc)
-{
- void *result = std::malloc (sz == 0 ? 1 : sz);
- if (result == NULL)
- throw std::bad_alloc();
- gNewCounter++;
- return result;
-}
-void operator delete(void* p) throw()
-{
- if (p == NULL)
- return;
- std::free (p);
- gDeleteCounter++;
-}
-
-/* These are the 'nothrow' versions of the above operators.
- The system version will try to call a std::new_handler if they
- fail, but your overriding versions are not required to do this. */
-void* operator new(std::size_t sz, const std::nothrow_t&) throw()
-{
- try {
- void * result = ::operator new (sz); // calls our overridden operator new
- return result;
- } catch (std::bad_alloc &) {
- return NULL;
- }
-}
-void operator delete(void* p, const std::nothrow_t&) throw()
-{
- ::operator delete (p);
-}
-
-#endif // 0
-
-#endif // NV_OVERRIDE_ALLOC
-
-void * nv::aligned_malloc(size_t size, size_t alignment)
-{
- // alignment must be a power of two, multiple of sizeof(void*)
- nvDebugCheck(isPowerOfTwo(alignment));
- nvDebugCheck((alignment & (sizeof(void*) - 1)) == 0);
-
-#if NV_OS_WIN32 || NV_OS_DURANGO
- return _aligned_malloc(size, alignment);
-#elif NV_OS_DARWIN && !NV_OS_IOS
- void * ptr = NULL;
- posix_memalign(&ptr, alignment, size);
- return ptr;
-#elif NV_OS_LINUX
- return memalign(alignment, size);
-#else // NV_OS_ORBIS || NV_OS_IOS
- // @@ IC: iOS appears to be 16 byte aligned, should we check alignment and assert if we request a higher alignment factor?
- return ::malloc(size);
-#endif
-}
-
-void nv::aligned_free(void * ptr)
-{
-#if NV_OS_WIN32 || NV_OS_DURANGO
- _aligned_free(ptr);
-#else
- ::free(ptr);
-#endif
-}
-
diff --git a/thirdparty/thekla_atlas/nvcore/Memory.h b/thirdparty/thekla_atlas/nvcore/Memory.h
deleted file mode 100644
index 1f71b60947..0000000000
--- a/thirdparty/thekla_atlas/nvcore/Memory.h
+++ /dev/null
@@ -1,72 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#pragma once
-#ifndef NV_CORE_MEMORY_H
-#define NV_CORE_MEMORY_H
-
-#include "nvcore.h"
-
-#include <stdlib.h> // malloc(), realloc() and free()
-#include <string.h> // memset
-//#include <stddef.h> // size_t
-
-//#include <new> // new and delete
-
-#define TRACK_MEMORY_LEAKS 0
-#if TRACK_MEMORY_LEAKS
-#include <vld.h>
-#endif
-
-
-#if NV_CC_GNUC
-# define NV_ALIGN_16 __attribute__ ((__aligned__ (16)))
-#else
-# define NV_ALIGN_16 __declspec(align(16))
-#endif
-
-
-#define NV_OVERRIDE_ALLOC 0
-
-#if NV_OVERRIDE_ALLOC
-
-// Custom memory allocator
-extern "C" {
- NVCORE_API void * malloc(size_t size);
- NVCORE_API void * debug_malloc(size_t size, const char * file, int line);
- NVCORE_API void free(void * ptr);
- NVCORE_API void * realloc(void * ptr, size_t size);
-}
-
-/*
-#ifdef _DEBUG
-#define new new(__FILE__, __LINE__)
-#define malloc(i) debug_malloc(i, __FILE__, __LINE__)
-#endif
-*/
-
-#endif
-
-namespace nv {
- NVCORE_API void * aligned_malloc(size_t size, size_t alignment);
- NVCORE_API void aligned_free(void * );
-
- // C++ helpers.
- template <typename T> NV_FORCEINLINE T * malloc(size_t count) {
- return (T *)::malloc(sizeof(T) * count);
- }
-
- template <typename T> NV_FORCEINLINE T * realloc(T * ptr, size_t count) {
- return (T *)::realloc(ptr, sizeof(T) * count);
- }
-
- template <typename T> NV_FORCEINLINE void free(const T * ptr) {
- ::free((void *)ptr);
- }
-
- template <typename T> NV_FORCEINLINE void zero(T & data) {
- memset(&data, 0, sizeof(T));
- }
-
-} // nv namespace
-
-#endif // NV_CORE_MEMORY_H
diff --git a/thirdparty/thekla_atlas/nvcore/Ptr.h b/thirdparty/thekla_atlas/nvcore/Ptr.h
deleted file mode 100644
index b43039274b..0000000000
--- a/thirdparty/thekla_atlas/nvcore/Ptr.h
+++ /dev/null
@@ -1,322 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#ifndef NV_CORE_PTR_H
-#define NV_CORE_PTR_H
-
-#include "nvcore.h"
-#include "Debug.h"
-
-#include "RefCounted.h"
-
-namespace nv
-{
- class WeakProxy;
-
- /** Simple auto pointer template class.
- *
- * This is very similar to the standard auto_ptr class, but with some
- * additional limitations to make its use less error prone:
- * - Copy constructor and assignment operator are disabled.
- * - reset method is removed.
- *
- * The semantics of the standard auto_ptr are not clear and change depending
- * on the std implementation. For a discussion of the problems of auto_ptr read:
- * http://www.awprofessional.com/content/images/020163371X/autoptrupdate\auto_ptr_update.html
- */
- template <class T>
- class AutoPtr
- {
- NV_FORBID_COPY(AutoPtr);
- NV_FORBID_HEAPALLOC();
- public:
-
- /// Ctor.
- AutoPtr(T * p = NULL) : m_ptr(p) { }
-
- template <class Q>
- AutoPtr(Q * p) : m_ptr(static_cast<T *>(p)) { }
-
- /// Dtor. Deletes owned pointer.
- ~AutoPtr() {
- delete m_ptr;
- m_ptr = NULL;
- }
-
- /// Delete owned pointer and assign new one.
- void operator=( T * p ) {
- if (p != m_ptr)
- {
- delete m_ptr;
- m_ptr = p;
- }
- }
-
- template <class Q>
- void operator=( Q * p ) {
- if (p != m_ptr)
- {
- delete m_ptr;
- m_ptr = static_cast<T *>(p);
- }
- }
-
- /// Member access.
- T * operator -> () const {
- nvDebugCheck(m_ptr != NULL);
- return m_ptr;
- }
-
- /// Get reference.
- T & operator*() const {
- nvDebugCheck(m_ptr != NULL);
- return *m_ptr;
- }
-
- /// Get pointer.
- T * ptr() const { return m_ptr; }
-
- /// Relinquish ownership of the underlying pointer and returns that pointer.
- T * release() {
- T * tmp = m_ptr;
- m_ptr = NULL;
- return tmp;
- }
-
- /// Const pointer equal comparation.
- friend bool operator == (const AutoPtr<T> & ap, const T * const p) {
- return (ap.ptr() == p);
- }
-
- /// Const pointer nequal comparation.
- friend bool operator != (const AutoPtr<T> & ap, const T * const p) {
- return (ap.ptr() != p);
- }
-
- /// Const pointer equal comparation.
- friend bool operator == (const T * const p, const AutoPtr<T> & ap) {
- return (ap.ptr() == p);
- }
-
- /// Const pointer nequal comparation.
- friend bool operator != (const T * const p, const AutoPtr<T> & ap) {
- return (ap.ptr() != p);
- }
-
- private:
- T * m_ptr;
- };
-
-
- /// Smart pointer template class.
- template <class BaseClass>
- class SmartPtr {
- public:
-
- // BaseClass must implement addRef() and release().
- typedef SmartPtr<BaseClass> ThisType;
-
- /// Default ctor.
- SmartPtr() : m_ptr(NULL)
- {
- }
-
- /// Other type assignment.
- template <class OtherBase>
- SmartPtr( const SmartPtr<OtherBase> & tc )
- {
- m_ptr = static_cast<BaseClass *>( tc.ptr() );
- if (m_ptr) {
- m_ptr->addRef();
- }
- }
-
- /// Copy ctor.
- SmartPtr( const ThisType & bc )
- {
- m_ptr = bc.ptr();
- if (m_ptr) {
- m_ptr->addRef();
- }
- }
-
- /// Copy cast ctor. SmartPtr(NULL) is valid.
- explicit SmartPtr( BaseClass * bc )
- {
- m_ptr = bc;
- if (m_ptr) {
- m_ptr->addRef();
- }
- }
-
- /// Dtor.
- ~SmartPtr()
- {
- set(NULL);
- }
-
-
- /// -> operator.
- BaseClass * operator -> () const
- {
- nvCheck( m_ptr != NULL );
- return m_ptr;
- }
-
- /// * operator.
- BaseClass & operator*() const
- {
- nvCheck( m_ptr != NULL );
- return *m_ptr;
- }
-
- /// Get pointer.
- BaseClass * ptr() const
- {
- return m_ptr;
- }
-
- /// Other type assignment.
- template <class OtherBase>
- void operator = ( const SmartPtr<OtherBase> & tc )
- {
- set( static_cast<BaseClass *>(tc.ptr()) );
- }
-
- /// This type assignment.
- void operator = ( const ThisType & bc )
- {
- set( bc.ptr() );
- }
-
- /// Pointer assignment.
- void operator = ( BaseClass * bc )
- {
- set( bc );
- }
-
-
- /// Other type equal comparation.
- template <class OtherBase>
- bool operator == ( const SmartPtr<OtherBase> & other ) const
- {
- return m_ptr == other.ptr();
- }
-
- /// This type equal comparation.
- bool operator == ( const ThisType & bc ) const
- {
- return m_ptr == bc.ptr();
- }
-
- /// Const pointer equal comparation.
- bool operator == ( const BaseClass * const bc ) const
- {
- return m_ptr == bc;
- }
-
- /// Other type not equal comparation.
- template <class OtherBase>
- bool operator != ( const SmartPtr<OtherBase> & other ) const
- {
- return m_ptr != other.ptr();
- }
-
- /// Other type not equal comparation.
- bool operator != ( const ThisType & bc ) const
- {
- return m_ptr != bc.ptr();
- }
-
- /// Const pointer not equal comparation.
- bool operator != (const BaseClass * const bc) const
- {
- return m_ptr != bc;
- }
-
- /// This type lower than comparation.
- bool operator < (const ThisType & p) const
- {
- return m_ptr < p.ptr();
- }
-
- bool isValid() const {
- return isValidPtr(m_ptr);
- }
-
- private:
-
- // Set this pointer.
- void set( BaseClass * p )
- {
- if (p) p->addRef();
- if (m_ptr) m_ptr->release();
- m_ptr = p;
- }
-
- private:
-
- BaseClass * m_ptr;
-
- };
-
-
- /// Smart pointer template class.
- template <class T>
- class WeakPtr {
- public:
-
- WeakPtr() {}
-
- WeakPtr(T * p) { operator=(p); }
- WeakPtr(const SmartPtr<T> & p) { operator=(p.ptr()); }
-
- // Default constructor and assignment from weak_ptr<T> are OK.
-
- void operator=(T * p)
- {
- if (p) {
- m_proxy = p->getWeakProxy();
- nvDebugCheck(m_proxy != NULL);
- nvDebugCheck(m_proxy->ptr() == p);
- }
- else {
- m_proxy = NULL;
- }
- }
-
- void operator=(const SmartPtr<T> & ptr) { operator=(ptr.ptr()); }
-
- bool operator==(const SmartPtr<T> & p) const { return ptr() == p.ptr(); }
- bool operator!=(const SmartPtr<T> & p) const { return ptr() != p.ptr(); }
-
- bool operator==(const WeakPtr<T> & p) const { return ptr() == p.ptr(); }
- bool operator!=(const WeakPtr<T> & p) const { return ptr() != p.ptr(); }
-
- bool operator==(T * p) const { return ptr() == p; }
- bool operator!=(T * p) const { return ptr() != p; }
-
- T * operator->() const
- {
- T * p = ptr();
- nvDebugCheck(p != NULL);
- return p;
- }
-
- T * ptr() const
- {
- if (m_proxy != NULL) {
- return static_cast<T *>(m_proxy->ptr());
- }
- return NULL;
- }
-
- private:
-
- mutable SmartPtr<WeakProxy> m_proxy;
-
- };
-
-
-} // nv namespace
-
-#endif // NV_CORE_PTR_H
diff --git a/thirdparty/thekla_atlas/nvcore/RadixSort.cpp b/thirdparty/thekla_atlas/nvcore/RadixSort.cpp
deleted file mode 100644
index 3f44620c99..0000000000
--- a/thirdparty/thekla_atlas/nvcore/RadixSort.cpp
+++ /dev/null
@@ -1,285 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#include "RadixSort.h"
-
-#include "Utils.h"
-
-#include <string.h> // memset
-
-using namespace nv;
-
-static inline void FloatFlip(uint32 & f) {
- //uint32 mask = -int32(f >> 31) | 0x80000000; // Michael Herf.
- int32 mask = (int32(f) >> 31) | 0x80000000; // Warren Hunt, Manchor Ko.
- f ^= mask;
-}
-
-static inline void IFloatFlip(uint32 & f) {
- uint32 mask = ((f >> 31) - 1) | 0x80000000; // Michael Herf.
- //uint32 mask = (int32(f ^ 0x80000000) >> 31) | 0x80000000; // Warren Hunt, Manchor Ko. @@ Correct, but fails in release on gcc-4.2.1
- f ^= mask;
-}
-
-
-template<typename T>
-void createHistograms(const T * buffer, uint count, uint * histogram)
-{
- const uint bucketCount = sizeof(T); // (8 * sizeof(T)) / log2(radix)
-
- // Init bucket pointers.
- uint * h[bucketCount];
- for (uint i = 0; i < bucketCount; i++) {
-#if NV_BIG_ENDIAN
- h[sizeof(T)-1-i] = histogram + 256 * i;
-#else
- h[i] = histogram + 256 * i;
-#endif
- }
-
- // Clear histograms.
- memset(histogram, 0, 256 * bucketCount * sizeof(uint));
-
- // @@ Add support for signed integers.
-
- // Build histograms.
- const uint8 * p = (const uint8 *)buffer; // @@ Does this break aliasing rules?
- const uint8 * pe = p + count * sizeof(T);
-
- while (p != pe) {
- h[0][*p++]++, h[1][*p++]++, h[2][*p++]++, h[3][*p++]++;
- if (bucketCount == 8) h[4][*p++]++, h[5][*p++]++, h[6][*p++]++, h[7][*p++]++;
- }
-}
-
-/*
-template <>
-void createHistograms<float>(const float * buffer, uint count, uint * histogram)
-{
- // Init bucket pointers.
- uint32 * h[4];
- for (uint i = 0; i < 4; i++) {
-#if NV_BIG_ENDIAN
- h[3-i] = histogram + 256 * i;
-#else
- h[i] = histogram + 256 * i;
-#endif
- }
-
- // Clear histograms.
- memset(histogram, 0, 256 * 4 * sizeof(uint32));
-
- // Build histograms.
- for (uint i = 0; i < count; i++) {
- uint32 fi = FloatFlip(buffer[i]);
-
- h[0][fi & 0xFF]++;
- h[1][(fi >> 8) & 0xFF]++;
- h[2][(fi >> 16) & 0xFF]++;
- h[3][fi >> 24]++;
- }
-}
-*/
-
-RadixSort::RadixSort() : m_size(0), m_ranks(NULL), m_ranks2(NULL), m_validRanks(false)
-{
-}
-
-RadixSort::RadixSort(uint reserve_count) : m_size(0), m_ranks(NULL), m_ranks2(NULL), m_validRanks(false)
-{
- checkResize(reserve_count);
-}
-
-RadixSort::~RadixSort()
-{
- // Release everything
- free(m_ranks2);
- free(m_ranks);
-}
-
-
-void RadixSort::resize(uint count)
-{
- m_ranks2 = realloc<uint>(m_ranks2, count);
- m_ranks = realloc<uint>(m_ranks, count);
-}
-
-inline void RadixSort::checkResize(uint count)
-{
- if (count != m_size)
- {
- if (count > m_size) resize(count);
- m_size = count;
- m_validRanks = false;
- }
-}
-
-template <typename T> inline void RadixSort::insertionSort(const T * input, uint count)
-{
- if (!m_validRanks) {
- /*for (uint i = 0; i < count; i++) {
- m_ranks[i] = i;
- }*/
-
- m_ranks[0] = 0;
- for (uint i = 1; i != count; ++i)
- {
- int rank = m_ranks[i] = i;
-
- uint j = i;
- while (j != 0 && input[rank] < input[m_ranks[j-1]])
- {
- m_ranks[j] = m_ranks[j-1];
- --j;
- }
- if (i != j)
- {
- m_ranks[j] = rank;
- }
- }
-
- m_validRanks = true;
- }
- else {
- for (uint i = 1; i != count; ++i)
- {
- int rank = m_ranks[i];
-
- uint j = i;
- while (j != 0 && input[rank] < input[m_ranks[j-1]])
- {
- m_ranks[j] = m_ranks[j-1];
- --j;
- }
- if (i != j)
- {
- m_ranks[j] = rank;
- }
- }
- }
-}
-
-template <typename T> inline void RadixSort::radixSort(const T * input, uint count)
-{
- const uint P = sizeof(T); // pass count
-
- // Allocate histograms & offsets on the stack
- uint histogram[256 * P];
- uint * link[256];
-
- createHistograms(input, count, histogram);
-
- // Radix sort, j is the pass number (0=LSB, P=MSB)
- for (uint j = 0; j < P; j++)
- {
- // Pointer to this bucket.
- const uint * h = &histogram[j * 256];
-
- const uint8 * inputBytes = (const uint8*)input; // @@ Is this aliasing legal?
-
-#if NV_BIG_ENDIAN
- inputBytes += P - 1 - j;
-#else
- inputBytes += j;
-#endif
-
- if (h[inputBytes[0]] == count) {
- // Skip this pass, all values are the same.
- continue;
- }
-
- // Create offsets
- link[0] = m_ranks2;
- for (uint i = 1; i < 256; i++) link[i] = link[i-1] + h[i-1];
-
- // Perform Radix Sort
- if (!m_validRanks)
- {
- for (uint i = 0; i < count; i++)
- {
- *link[inputBytes[i*P]]++ = i;
- }
- m_validRanks = true;
- }
- else
- {
- for (uint i = 0; i < count; i++)
- {
- const uint idx = m_ranks[i];
- *link[inputBytes[idx*P]]++ = idx;
- }
- }
-
- // Swap pointers for next pass. Valid indices - the most recent ones - are in m_ranks after the swap.
- swap(m_ranks, m_ranks2);
- }
-
- // All values were equal, generate linear ranks.
- if (!m_validRanks)
- {
- for (uint i = 0; i < count; i++)
- {
- m_ranks[i] = i;
- }
- m_validRanks = true;
- }
-}
-
-
-RadixSort & RadixSort::sort(const uint32 * input, uint count)
-{
- if (input == NULL || count == 0) return *this;
-
- // Resize lists if needed
- checkResize(count);
-
- if (count < 32) {
- insertionSort(input, count);
- }
- else {
- radixSort<uint32>(input, count);
- }
- return *this;
-}
-
-
-RadixSort & RadixSort::sort(const uint64 * input, uint count)
-{
- if (input == NULL || count == 0) return *this;
-
- // Resize lists if needed
- checkResize(count);
-
- if (count < 64) {
- insertionSort(input, count);
- }
- else {
- radixSort(input, count);
- }
- return *this;
-}
-
-RadixSort& RadixSort::sort(const float * input, uint count)
-{
- if (input == NULL || count == 0) return *this;
-
- // Resize lists if needed
- checkResize(count);
-
- if (count < 32) {
- insertionSort(input, count);
- }
- else {
- // @@ Avoid touching the input multiple times.
- for (uint i = 0; i < count; i++) {
- FloatFlip((uint32 &)input[i]);
- }
-
- radixSort<uint32>((const uint32 *)input, count);
-
- for (uint i = 0; i < count; i++) {
- IFloatFlip((uint32 &)input[i]);
- }
- }
-
- return *this;
-}
diff --git a/thirdparty/thekla_atlas/nvcore/RadixSort.h b/thirdparty/thekla_atlas/nvcore/RadixSort.h
deleted file mode 100644
index 82325ebb24..0000000000
--- a/thirdparty/thekla_atlas/nvcore/RadixSort.h
+++ /dev/null
@@ -1,75 +0,0 @@
-#pragma once
-#ifndef NV_CORE_RADIXSORT_H
-#define NV_CORE_RADIXSORT_H
-
-// Based on Pierre Terdiman's and Michael Herf's source code.
-// http://www.codercorner.com/RadixSortRevisited.htm
-// http://www.stereopsis.com/radix.html
-
-#include "nvcore.h"
-#include "Array.h"
-
-namespace nv
-{
-
- class NVCORE_CLASS RadixSort
- {
- NV_FORBID_COPY(RadixSort);
- public:
- // Constructor/Destructor
- RadixSort();
- RadixSort(uint reserve_count);
- ~RadixSort();
-
- // Invalidate ranks.
- RadixSort & reset() { m_validRanks = false; return *this; }
-
- // Sorting methods.
- RadixSort & sort(const uint32 * input, uint count);
- RadixSort & sort(const uint64 * input, uint count);
- RadixSort & sort(const float * input, uint count);
-
- // Helpers.
- RadixSort & sort(const Array<uint32> & input);
- RadixSort & sort(const Array<uint64> & input);
- RadixSort & sort(const Array<float> & input);
-
- // Access to results. m_ranks is a list of indices in sorted order, i.e. in the order you may further process your data
- inline const uint * ranks() const { nvDebugCheck(m_validRanks); return m_ranks; }
- inline uint * ranks() { nvDebugCheck(m_validRanks); return m_ranks; }
- inline uint rank(uint i) const { nvDebugCheck(m_validRanks); return m_ranks[i]; }
-
- // query whether the sort has been performed
- inline bool valid() const { return m_validRanks; }
-
- private:
- uint m_size;
- uint * m_ranks;
- uint * m_ranks2;
- bool m_validRanks;
-
- // Internal methods
- template <typename T> void insertionSort(const T * input, uint count);
- template <typename T> void radixSort(const T * input, uint count);
-
- void checkResize(uint nb);
- void resize(uint nb);
- };
-
- inline RadixSort & RadixSort::sort(const Array<uint32> & input) {
- return sort(input.buffer(), input.count());
- }
-
- inline RadixSort & RadixSort::sort(const Array<uint64> & input) {
- return sort(input.buffer(), input.count());
- }
-
- inline RadixSort & RadixSort::sort(const Array<float> & input) {
- return sort(input.buffer(), input.count());
- }
-
-} // nv namespace
-
-
-
-#endif // NV_CORE_RADIXSORT_H
diff --git a/thirdparty/thekla_atlas/nvcore/RefCounted.h b/thirdparty/thekla_atlas/nvcore/RefCounted.h
deleted file mode 100644
index b8d68edee3..0000000000
--- a/thirdparty/thekla_atlas/nvcore/RefCounted.h
+++ /dev/null
@@ -1,149 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#ifndef NV_CORE_REFCOUNTED_H
-#define NV_CORE_REFCOUNTED_H
-
-#include "nvcore.h"
-#include "Debug.h"
-
-#define NV_DECLARE_PTR(Class) \
- template <class T> class SmartPtr; \
- typedef SmartPtr<class Class> Class ## Ptr; \
- typedef SmartPtr<const class Class> Class ## ConstPtr
-
-
-namespace nv
-{
- /// Weak proxy.
- class WeakProxy
- {
- NV_FORBID_COPY(WeakProxy);
- public:
- /// Ctor.
- WeakProxy(void * ptr) : m_count(0), m_ptr(ptr) { }
-
- /// Dtor.
- ~WeakProxy()
- {
- nvCheck( m_count == 0 );
- }
-
- /// Increase reference count.
- uint addRef() const
- {
- m_count++;
- return m_count;
- }
-
- /// Decrease reference count and remove when 0.
- uint release() const
- {
- nvCheck( m_count > 0 );
-
- m_count--;
- if( m_count == 0 ) {
- delete this;
- return 0;
- }
- return m_count;
- }
-
- /// WeakPtr's call this to determine if their pointer is valid or not.
- bool isAlive() const {
- return m_ptr != NULL;
- }
-
- /// Only the actual object should call this.
- void notifyObjectDied() {
- m_ptr = NULL;
- }
-
- /// Return proxy pointer.
- void * ptr() const {
- return m_ptr;
- }
-
- private:
- mutable int m_count;
- void * m_ptr;
- };
-
-
- /// Reference counted base class to be used with SmartPtr and WeakPtr.
- class RefCounted
- {
- NV_FORBID_COPY(RefCounted);
- public:
-
- /// Ctor.
- RefCounted() : m_count(0), m_weak_proxy(NULL)
- {
- }
-
- /// Virtual dtor.
- virtual ~RefCounted()
- {
- nvCheck( m_count == 0 );
- releaseWeakProxy();
- }
-
-
- /// Increase reference count.
- uint addRef() const
- {
- m_count++;
- return m_count;
- }
-
-
- /// Decrease reference count and remove when 0.
- uint release() const
- {
- nvCheck( m_count > 0 );
-
- m_count--;
- if( m_count == 0 ) {
- delete this;
- return 0;
- }
- return m_count;
- }
-
- /// Get weak proxy.
- WeakProxy * getWeakProxy() const
- {
- if (m_weak_proxy == NULL) {
- m_weak_proxy = new WeakProxy((void *)this);
- m_weak_proxy->addRef();
- }
- return m_weak_proxy;
- }
-
- /// Release the weak proxy.
- void releaseWeakProxy() const
- {
- if (m_weak_proxy != NULL) {
- m_weak_proxy->notifyObjectDied();
- m_weak_proxy->release();
- m_weak_proxy = NULL;
- }
- }
-
- /// Get reference count.
- int refCount() const
- {
- return m_count;
- }
-
-
- private:
-
- mutable int m_count;
- mutable WeakProxy * m_weak_proxy;
-
- };
-
-} // nv namespace
-
-
-#endif // NV_CORE_REFCOUNTED_H
diff --git a/thirdparty/thekla_atlas/nvcore/StdStream.h b/thirdparty/thekla_atlas/nvcore/StdStream.h
deleted file mode 100644
index f65d6dab59..0000000000
--- a/thirdparty/thekla_atlas/nvcore/StdStream.h
+++ /dev/null
@@ -1,474 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-//#pragma once
-//#ifndef NV_CORE_STDSTREAM_H
-//#define NV_CORE_STDSTREAM_H
-
-#include "nvcore.h"
-#include "Stream.h"
-#include "Array.h"
-
-#include <stdio.h> // fopen
-#include <string.h> // memcpy
-
-namespace nv
-{
-
- // Portable version of fopen.
- inline FILE * fileOpen(const char * fileName, const char * mode)
- {
- nvCheck(fileName != NULL);
-#if NV_CC_MSVC && _MSC_VER >= 1400
- FILE * fp;
- if (fopen_s(&fp, fileName, mode) == 0) {
- return fp;
- }
- return NULL;
-#else
- return fopen(fileName, mode);
-#endif
- }
-
-
- /// Base stdio stream.
- class NVCORE_CLASS StdStream : public Stream
- {
- NV_FORBID_COPY(StdStream);
- public:
-
- /// Ctor.
- StdStream( FILE * fp, bool autoclose ) : m_fp(fp), m_autoclose(autoclose) { }
-
- /// Dtor.
- virtual ~StdStream()
- {
- if( m_fp != NULL && m_autoclose ) {
-#if NV_OS_WIN32
- _fclose_nolock( m_fp );
-#else
- fclose( m_fp );
-#endif
- }
- }
-
-
- /** @name Stream implementation. */
- //@{
- virtual void seek( uint pos )
- {
- nvDebugCheck(m_fp != NULL);
- nvDebugCheck(pos <= size());
-#if NV_OS_WIN32
- _fseek_nolock(m_fp, pos, SEEK_SET);
-#else
- fseek(m_fp, pos, SEEK_SET);
-#endif
- }
-
- virtual uint tell() const
- {
- nvDebugCheck(m_fp != NULL);
-#if NV_OS_WIN32
- return _ftell_nolock(m_fp);
-#else
- return (uint)ftell(m_fp);
-#endif
- }
-
- virtual uint size() const
- {
- nvDebugCheck(m_fp != NULL);
-#if NV_OS_WIN32
- uint pos = _ftell_nolock(m_fp);
- _fseek_nolock(m_fp, 0, SEEK_END);
- uint end = _ftell_nolock(m_fp);
- _fseek_nolock(m_fp, pos, SEEK_SET);
-#else
- uint pos = (uint)ftell(m_fp);
- fseek(m_fp, 0, SEEK_END);
- uint end = (uint)ftell(m_fp);
- fseek(m_fp, pos, SEEK_SET);
-#endif
- return end;
- }
-
- virtual bool isError() const
- {
- return m_fp == NULL || ferror( m_fp ) != 0;
- }
-
- virtual void clearError()
- {
- nvDebugCheck(m_fp != NULL);
- clearerr(m_fp);
- }
-
- // @@ The original implementation uses feof, which only returns true when we attempt to read *past* the end of the stream.
- // That is, if we read the last byte of a file, then isAtEnd would still return false, even though the stream pointer is at the file end. This is not the intent and was inconsistent with the implementation of the MemoryStream, a better
- // implementation uses use ftell and fseek to determine our location within the file.
- virtual bool isAtEnd() const
- {
- if (m_fp == NULL) return true;
- //nvDebugCheck(m_fp != NULL);
- //return feof( m_fp ) != 0;
-#if NV_OS_WIN32
- uint pos = _ftell_nolock(m_fp);
- _fseek_nolock(m_fp, 0, SEEK_END);
- uint end = _ftell_nolock(m_fp);
- _fseek_nolock(m_fp, pos, SEEK_SET);
-#else
- uint pos = (uint)ftell(m_fp);
- fseek(m_fp, 0, SEEK_END);
- uint end = (uint)ftell(m_fp);
- fseek(m_fp, pos, SEEK_SET);
-#endif
- return pos == end;
- }
-
- /// Always true.
- virtual bool isSeekable() const { return true; }
- //@}
-
- protected:
-
- FILE * m_fp;
- bool m_autoclose;
-
- };
-
-
- /// Standard output stream.
- class NVCORE_CLASS StdOutputStream : public StdStream
- {
- NV_FORBID_COPY(StdOutputStream);
- public:
-
- /// Construct stream by file name.
- StdOutputStream( const char * name ) : StdStream(fileOpen(name, "wb"), /*autoclose=*/true) { }
-
- /// Construct stream by file handle.
- StdOutputStream( FILE * fp, bool autoclose ) : StdStream(fp, autoclose)
- {
- }
-
- /** @name Stream implementation. */
- //@{
- /// Write data.
- virtual uint serialize( void * data, uint len )
- {
- nvDebugCheck(data != NULL);
- nvDebugCheck(m_fp != NULL);
-#if NV_OS_WIN32
- return (uint)_fwrite_nolock(data, 1, len, m_fp);
-#elif NV_OS_LINUX
- return (uint)fwrite_unlocked(data, 1, len, m_fp);
-#elif NV_OS_DARWIN
- // @@ No error checking, always returns len.
- for (uint i = 0; i < len; i++) {
- putc_unlocked(((char *)data)[i], m_fp);
- }
- return len;
-#else
- return (uint)fwrite(data, 1, len, m_fp);
-#endif
- }
-
- virtual bool isLoading() const
- {
- return false;
- }
-
- virtual bool isSaving() const
- {
- return true;
- }
- //@}
-
- };
-
-
- /// Standard input stream.
- class NVCORE_CLASS StdInputStream : public StdStream
- {
- NV_FORBID_COPY(StdInputStream);
- public:
-
- /// Construct stream by file name.
- StdInputStream( const char * name ) : StdStream(fileOpen(name, "rb"), /*autoclose=*/true) { }
-
- /// Construct stream by file handle.
- StdInputStream( FILE * fp, bool autoclose=true ) : StdStream(fp, autoclose)
- {
- }
-
- /** @name Stream implementation. */
- //@{
- /// Read data.
- virtual uint serialize( void * data, uint len )
- {
- nvDebugCheck(data != NULL);
- nvDebugCheck(m_fp != NULL);
-#if NV_OS_WIN32
- return (uint)_fread_nolock(data, 1, len, m_fp);
-#elif NV_OS_LINUX
- return (uint)fread_unlocked(data, 1, len, m_fp);
-#elif NV_OS_DARWIN
- // This is rather lame. Not sure if it's faster than the locked version.
- for (uint i = 0; i < len; i++) {
- ((char *)data)[i] = getc_unlocked(m_fp);
- if (feof_unlocked(m_fp) != 0) {
- return i;
- }
- }
- return len;
-#else
- return (uint)fread(data, 1, len, m_fp);
-#endif
-
- }
-
- virtual bool isLoading() const
- {
- return true;
- }
-
- virtual bool isSaving() const
- {
- return false;
- }
- //@}
- };
-
-
-
- /// Memory input stream.
- class NVCORE_CLASS MemoryInputStream : public Stream
- {
- NV_FORBID_COPY(MemoryInputStream);
- public:
-
- /// Ctor.
- MemoryInputStream( const uint8 * mem, uint size ) : m_mem(mem), m_ptr(mem), m_size(size) { }
-
- /** @name Stream implementation. */
- //@{
- /// Read data.
- virtual uint serialize( void * data, uint len )
- {
- nvDebugCheck(data != NULL);
- nvDebugCheck(!isError());
-
- uint left = m_size - tell();
- if (len > left) len = left;
-
- memcpy( data, m_ptr, len );
- m_ptr += len;
-
- return len;
- }
-
- virtual void seek( uint pos )
- {
- nvDebugCheck(!isError());
- m_ptr = m_mem + pos;
- nvDebugCheck(!isError());
- }
-
- virtual uint tell() const
- {
- nvDebugCheck(m_ptr >= m_mem);
- return uint(m_ptr - m_mem);
- }
-
- virtual uint size() const
- {
- return m_size;
- }
-
- virtual bool isError() const
- {
- return m_mem == NULL || m_ptr > m_mem + m_size || m_ptr < m_mem;
- }
-
- virtual void clearError()
- {
- // Nothing to do.
- }
-
- virtual bool isAtEnd() const
- {
- return m_ptr == m_mem + m_size;
- }
-
- /// Always true.
- virtual bool isSeekable() const
- {
- return true;
- }
-
- virtual bool isLoading() const
- {
- return true;
- }
-
- virtual bool isSaving() const
- {
- return false;
- }
- //@}
-
- const uint8 * ptr() const { return m_ptr; }
-
-
- private:
-
- const uint8 * m_mem;
- const uint8 * m_ptr;
- uint m_size;
-
- };
-
-
- /// Buffer output stream.
- class NVCORE_CLASS BufferOutputStream : public Stream
- {
- NV_FORBID_COPY(BufferOutputStream);
- public:
-
- BufferOutputStream(Array<uint8> & buffer) : m_buffer(buffer) { }
-
- virtual uint serialize( void * data, uint len )
- {
- nvDebugCheck(data != NULL);
- m_buffer.append((uint8 *)data, len);
- return len;
- }
-
- virtual void seek( uint /*pos*/ ) { /*Not implemented*/ }
- virtual uint tell() const { return m_buffer.size(); }
- virtual uint size() const { return m_buffer.size(); }
-
- virtual bool isError() const { return false; }
- virtual void clearError() {}
-
- virtual bool isAtEnd() const { return true; }
- virtual bool isSeekable() const { return false; }
- virtual bool isLoading() const { return false; }
- virtual bool isSaving() const { return true; }
-
- private:
- Array<uint8> & m_buffer;
- };
-
-
- /// Protected input stream.
- class NVCORE_CLASS ProtectedStream : public Stream
- {
- NV_FORBID_COPY(ProtectedStream);
- public:
-
- /// Ctor.
- ProtectedStream( Stream & s ) : m_s(&s), m_autodelete(false)
- {
- }
-
- /// Ctor.
- ProtectedStream( Stream * s, bool autodelete = true ) :
- m_s(s), m_autodelete(autodelete)
- {
- nvDebugCheck(m_s != NULL);
- }
-
- /// Dtor.
- virtual ~ProtectedStream()
- {
- if( m_autodelete ) {
- delete m_s;
- }
- }
-
- /** @name Stream implementation. */
- //@{
- /// Read data.
- virtual uint serialize( void * data, uint len )
- {
- nvDebugCheck(data != NULL);
- len = m_s->serialize( data, len );
-
- if( m_s->isError() ) {
-#if NV_OS_ORBIS
- //SBtodoORBIS disabled (no exceptions)
-#else
- throw;
-#endif
- }
-
- return len;
- }
-
- virtual void seek( uint pos )
- {
- m_s->seek( pos );
-
- if( m_s->isError() ) {
-#if NV_OS_ORBIS
- //SBtodoORBIS disabled (no exceptions)
-#else
- throw;
-#endif
- }
- }
-
- virtual uint tell() const
- {
- return m_s->tell();
- }
-
- virtual uint size() const
- {
- return m_s->size();
- }
-
- virtual bool isError() const
- {
- return m_s->isError();
- }
-
- virtual void clearError()
- {
- m_s->clearError();
- }
-
- virtual bool isAtEnd() const
- {
- return m_s->isAtEnd();
- }
-
- virtual bool isSeekable() const
- {
- return m_s->isSeekable();
- }
-
- virtual bool isLoading() const
- {
- return m_s->isLoading();
- }
-
- virtual bool isSaving() const
- {
- return m_s->isSaving();
- }
- //@}
-
-
- private:
-
- Stream * const m_s;
- bool const m_autodelete;
-
- };
-
-} // nv namespace
-
-
-//#endif // NV_CORE_STDSTREAM_H
diff --git a/thirdparty/thekla_atlas/nvcore/StrLib.cpp b/thirdparty/thekla_atlas/nvcore/StrLib.cpp
deleted file mode 100644
index 7ec6c70136..0000000000
--- a/thirdparty/thekla_atlas/nvcore/StrLib.cpp
+++ /dev/null
@@ -1,796 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#include "StrLib.h"
-
-#include "Memory.h"
-#include "Utils.h" // swap
-
-#include <math.h> // log
-#include <stdio.h> // vsnprintf
-#include <string.h> // strlen, strcmp, etc.
-
-#if NV_CC_MSVC
-#include <stdarg.h> // vsnprintf
-#endif
-
-using namespace nv;
-
-namespace
-{
- static char * strAlloc(uint size)
- {
- return malloc<char>(size);
- }
-
- static char * strReAlloc(char * str, uint size)
- {
- return realloc<char>(str, size);
- }
-
- static void strFree(const char * str)
- {
- return free<char>(str);
- }
-
- /*static char * strDup( const char * str )
- {
- nvDebugCheck( str != NULL );
- uint len = uint(strlen( str ) + 1);
- char * dup = strAlloc( len );
- memcpy( dup, str, len );
- return dup;
- }*/
-
- // helper function for integer to string conversion.
- static char * i2a( uint i, char *a, uint r )
- {
- if( i / r > 0 ) {
- a = i2a( i / r, a, r );
- }
- *a = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[i % r];
- return a + 1;
- }
-
- // Locale independent functions.
- static inline char toUpper( char c ) {
- return (c<'a' || c>'z') ? (c) : (c+'A'-'a');
- }
- static inline char toLower( char c ) {
- return (c<'A' || c>'Z') ? (c) : (c+'a'-'A');
- }
- static inline bool isAlpha( char c ) {
- return (c>='a' && c<='z') || (c>='A' && c<='Z');
- }
- static inline bool isDigit( char c ) {
- return c>='0' && c<='9';
- }
- static inline bool isAlnum( char c ) {
- return (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9');
- }
-
-}
-
-uint nv::strLen(const char * str)
-{
- nvDebugCheck(str != NULL);
- return U32(strlen(str));
-}
-
-int nv::strDiff(const char * s1, const char * s2)
-{
- nvDebugCheck(s1 != NULL);
- nvDebugCheck(s2 != NULL);
- return strcmp(s1, s2);
-}
-
-int nv::strCaseDiff(const char * s1, const char * s2)
-{
- nvDebugCheck(s1 != NULL);
- nvDebugCheck(s1 != NULL);
-#if NV_CC_MSVC
- return _stricmp(s1, s2);
-#else
- return strcasecmp(s1, s2);
-#endif
-}
-
-bool nv::strEqual(const char * s1, const char * s2)
-{
- if (s1 == s2) return true;
- if (s1 == NULL || s2 == NULL) return false;
- return strcmp(s1, s2) == 0;
-}
-
-bool nv::strCaseEqual(const char * s1, const char * s2)
-{
- if (s1 == s2) return true;
- if (s1 == NULL || s2 == NULL) return false;
- return strCaseDiff(s1, s2) == 0;
-}
-
-bool nv::strBeginsWith(const char * str, const char * prefix)
-{
- //return strstr(str, prefix) == dst;
- return strncmp(str, prefix, strlen(prefix)) == 0;
-}
-
-bool nv::strEndsWith(const char * str, const char * suffix)
-{
- uint ml = strLen(str);
- uint sl = strLen(suffix);
- if (ml < sl) return false;
- return strncmp(str + ml - sl, suffix, sl) == 0;
-}
-
-// @@ Add asserts to detect overlap between dst and src?
-void nv::strCpy(char * dst, uint size, const char * src)
-{
- nvDebugCheck(dst != NULL);
- nvDebugCheck(src != NULL);
-#if NV_CC_MSVC && _MSC_VER >= 1400
- strcpy_s(dst, size, src);
-#else
- NV_UNUSED(size);
- strcpy(dst, src);
-#endif
-}
-
-void nv::strCpy(char * dst, uint size, const char * src, uint len)
-{
- nvDebugCheck(dst != NULL);
- nvDebugCheck(src != NULL);
-#if NV_CC_MSVC && _MSC_VER >= 1400
- strncpy_s(dst, size, src, len);
-#else
- int n = min(len+1, size);
- strncpy(dst, src, n);
- dst[n-1] = '\0';
-#endif
-}
-
-void nv::strCat(char * dst, uint size, const char * src)
-{
- nvDebugCheck(dst != NULL);
- nvDebugCheck(src != NULL);
-#if NV_CC_MSVC && _MSC_VER >= 1400
- strcat_s(dst, size, src);
-#else
- NV_UNUSED(size);
- strcat(dst, src);
-#endif
-}
-
-NVCORE_API const char * nv::strSkipWhiteSpace(const char * str)
-{
- nvDebugCheck(str != NULL);
- while (*str == ' ') str++;
- return str;
-}
-
-NVCORE_API char * nv::strSkipWhiteSpace(char * str)
-{
- nvDebugCheck(str != NULL);
- while (*str == ' ') str++;
- return str;
-}
-
-
-/** Pattern matching routine. I don't remember where did I get this. */
-bool nv::strMatch(const char * str, const char * pat)
-{
- nvDebugCheck(str != NULL);
- nvDebugCheck(pat != NULL);
-
- char c2;
-
- while (true) {
- if (*pat==0) {
- if (*str==0) return true;
- else return false;
- }
- if ((*str==0) && (*pat!='*')) return false;
- if (*pat=='*') {
- pat++;
- if (*pat==0) return true;
- while (true) {
- if (strMatch(str, pat)) return true;
- if (*str==0) return false;
- str++;
- }
- }
- if (*pat=='?') goto match;
- if (*pat=='[') {
- pat++;
- while (true) {
- if ((*pat==']') || (*pat==0)) return false;
- if (*pat==*str) break;
- if (pat[1] == '-') {
- c2 = pat[2];
- if (c2==0) return false;
- if ((*pat<=*str) && (c2>=*str)) break;
- if ((*pat>=*str) && (c2<=*str)) break;
- pat+=2;
- }
- pat++;
- }
- while (*pat!=']') {
- if (*pat==0) {
- pat--;
- break;
- }
- pat++;
- }
- goto match;
- }
-
- if (*pat == NV_PATH_SEPARATOR) {
- pat++;
- if (*pat==0) return false;
- }
- if (*pat!=*str) return false;
-
-match:
- pat++;
- str++;
- }
-}
-
-bool nv::isNumber(const char * str) {
- while(*str != '\0') {
- if (!isDigit(*str)) return false;
- str++;
- }
- return true;
-}
-
-
-/** Empty string. */
-StringBuilder::StringBuilder() : m_size(0), m_str(NULL)
-{
-}
-
-/** Preallocate space. */
-StringBuilder::StringBuilder( uint size_hint ) : m_size(size_hint)
-{
- nvDebugCheck(m_size > 0);
- m_str = strAlloc(m_size);
- *m_str = '\0';
-}
-
-/** Copy ctor. */
-StringBuilder::StringBuilder( const StringBuilder & s ) : m_size(0), m_str(NULL)
-{
- copy(s);
-}
-
-/** Copy string. */
-StringBuilder::StringBuilder(const char * s) : m_size(0), m_str(NULL)
-{
- if (s != NULL) {
- copy(s);
- }
-}
-
-/** Copy string. */
-StringBuilder::StringBuilder(const char * s, uint len) : m_size(0), m_str(NULL)
-{
- copy(s, len);
-}
-
-/** Delete the string. */
-StringBuilder::~StringBuilder()
-{
- strFree(m_str);
-}
-
-
-/** Format a string safely. */
-StringBuilder & StringBuilder::format( const char * fmt, ... )
-{
- nvDebugCheck(fmt != NULL);
- va_list arg;
- va_start( arg, fmt );
-
- formatList( fmt, arg );
-
- va_end( arg );
-
- return *this;
-}
-
-
-/** Format a string safely. */
-StringBuilder & StringBuilder::formatList( const char * fmt, va_list arg )
-{
- nvDebugCheck(fmt != NULL);
-
- if (m_size == 0) {
- m_size = 64;
- m_str = strAlloc( m_size );
- }
-
- va_list tmp;
- va_copy(tmp, arg);
-#if NV_CC_MSVC && _MSC_VER >= 1400
- int n = vsnprintf_s(m_str, m_size, _TRUNCATE, fmt, tmp);
-#else
- int n = vsnprintf(m_str, m_size, fmt, tmp);
-#endif
- va_end(tmp);
-
- while( n < 0 || n >= int(m_size) ) {
- if( n > -1 ) {
- m_size = n + 1;
- }
- else {
- m_size *= 2;
- }
-
- m_str = strReAlloc(m_str, m_size);
-
- va_copy(tmp, arg);
-#if NV_CC_MSVC && _MSC_VER >= 1400
- n = vsnprintf_s(m_str, m_size, _TRUNCATE, fmt, tmp);
-#else
- n = vsnprintf(m_str, m_size, fmt, tmp);
-#endif
- va_end(tmp);
- }
-
- nvDebugCheck(n < int(m_size));
-
- // Make sure it's null terminated.
- nvDebugCheck(m_str[n] == '\0');
- //str[n] = '\0';
-
- return *this;
-}
-
-
-// Append a character.
-StringBuilder & StringBuilder::append( char c )
-{
- return append(&c, 1);
-}
-
-// Append a string.
-StringBuilder & StringBuilder::append( const char * s )
-{
- return append(s, U32(strlen( s )));
-}
-
-// Append a string.
-StringBuilder & StringBuilder::append(const char * s, uint len)
-{
- nvDebugCheck(s != NULL);
-
- uint offset = length();
- const uint size = offset + len + 1;
- reserve(size);
- strCpy(m_str + offset, len + 1, s, len);
-
- return *this;
-}
-
-StringBuilder & StringBuilder::append(const StringBuilder & str)
-{
- return append(str.m_str, str.length());
-}
-
-
-/** Append a formatted string. */
-StringBuilder & StringBuilder::appendFormat( const char * fmt, ... )
-{
- nvDebugCheck( fmt != NULL );
-
- va_list arg;
- va_start( arg, fmt );
-
- appendFormatList( fmt, arg );
-
- va_end( arg );
-
- return *this;
-}
-
-
-/** Append a formatted string. */
-StringBuilder & StringBuilder::appendFormatList( const char * fmt, va_list arg )
-{
- nvDebugCheck( fmt != NULL );
-
- va_list tmp;
- va_copy(tmp, arg);
-
- if (m_size == 0) {
- formatList(fmt, arg);
- }
- else {
- StringBuilder tmp_str;
- tmp_str.formatList( fmt, tmp );
- append( tmp_str.str() );
- }
-
- va_end(tmp);
-
- return *this;
-}
-
-// Append n spaces.
-StringBuilder & StringBuilder::appendSpace(uint n)
-{
- if (m_str == NULL) {
- m_size = n + 1;
- m_str = strAlloc(m_size);
- memset(m_str, ' ', m_size);
- m_str[n] = '\0';
- }
- else {
- const uint len = strLen(m_str);
- if (m_size < len + n + 1) {
- m_size = len + n + 1;
- m_str = strReAlloc(m_str, m_size);
- }
- memset(m_str + len, ' ', n);
- m_str[len+n] = '\0';
- }
-
- return *this;
-}
-
-
-/** Convert number to string in the given base. */
-StringBuilder & StringBuilder::number( int i, int base )
-{
- nvCheck( base >= 2 );
- nvCheck( base <= 36 );
-
- // @@ This needs to be done correctly.
- // length = floor(log(i, base));
- uint len = uint(log(float(i)) / log(float(base)) + 2); // one more if negative
- reserve(len);
-
- if( i < 0 ) {
- *m_str = '-';
- *i2a(uint(-i), m_str+1, base) = 0;
- }
- else {
- *i2a(i, m_str, base) = 0;
- }
-
- return *this;
-}
-
-
-/** Convert number to string in the given base. */
-StringBuilder & StringBuilder::number( uint i, int base )
-{
- nvCheck( base >= 2 );
- nvCheck( base <= 36 );
-
- // @@ This needs to be done correctly.
- // length = floor(log(i, base));
- uint len = uint(log(float(i)) / log(float(base)) - 0.5f + 1);
- reserve(len);
-
- *i2a(i, m_str, base) = 0;
-
- return *this;
-}
-
-
-/** Resize the string preserving the contents. */
-StringBuilder & StringBuilder::reserve( uint size_hint )
-{
- nvCheck(size_hint != 0);
- if (size_hint > m_size) {
- m_str = strReAlloc(m_str, size_hint);
- m_size = size_hint;
- }
- return *this;
-}
-
-
-/** Copy a string safely. */
-StringBuilder & StringBuilder::copy(const char * s)
-{
- nvCheck( s != NULL );
- const uint str_size = uint(strlen( s )) + 1;
- reserve(str_size);
- memcpy(m_str, s, str_size);
- return *this;
-}
-
-/** Copy a string safely. */
-StringBuilder & StringBuilder::copy(const char * s, uint len)
-{
- nvCheck( s != NULL );
- const uint str_size = len + 1;
- reserve(str_size);
- strCpy(m_str, str_size, s, len);
- return *this;
-}
-
-
-/** Copy an StringBuilder. */
-StringBuilder & StringBuilder::copy( const StringBuilder & s )
-{
- if (s.m_str == NULL) {
- nvCheck( s.m_size == 0 );
- reset();
- }
- else {
- reserve( s.m_size );
- strCpy( m_str, s.m_size, s.m_str );
- }
- return *this;
-}
-
-bool StringBuilder::endsWith(const char * str) const
-{
- uint l = uint(strlen(str));
- uint ml = uint(strlen(m_str));
- if (ml < l) return false;
- return strncmp(m_str + ml - l, str, l) == 0;
-}
-
-bool StringBuilder::beginsWith(const char * str) const
-{
- size_t l = strlen(str);
- return strncmp(m_str, str, l) == 0;
-}
-
-// Find given char starting from the end.
-char * StringBuilder::reverseFind(char c)
-{
- int length = (int)strlen(m_str) - 1;
- while (length >= 0 && m_str[length] != c) {
- length--;
- }
- if (length >= 0) {
- return m_str + length;
- }
- else {
- return NULL;
- }
-}
-
-
-/** Reset the string. */
-void StringBuilder::reset()
-{
- m_size = 0;
- strFree( m_str );
- m_str = NULL;
-}
-
-/** Release the allocated string. */
-char * StringBuilder::release()
-{
- char * str = m_str;
- m_size = 0;
- m_str = NULL;
- return str;
-}
-
-// Take ownership of string.
-void StringBuilder::acquire(char * str)
-{
- if (str) {
- m_size = strLen(str) + 1;
- m_str = str;
- }
- else {
- m_size = 0;
- m_str = NULL;
- }
-}
-
-// Swap strings.
-void nv::swap(StringBuilder & a, StringBuilder & b) {
- swap(a.m_size, b.m_size);
- swap(a.m_str, b.m_str);
-}
-
-
-/// Get the file name from a path.
-const char * Path::fileName() const
-{
- return fileName(m_str);
-}
-
-
-/// Get the extension from a file path.
-const char * Path::extension() const
-{
- return extension(m_str);
-}
-
-
-/*static */void Path::translatePath(char * path, char pathSeparator/*= NV_PATH_SEPARATOR*/) {
- if (path != NULL) {
- for (int i = 0;; i++) {
- if (path[i] == '\0') break;
- if (path[i] == '\\' || path[i] == '/') path[i] = pathSeparator;
- }
- }
-}
-
-/// Toggles path separators (ie. \\ into /).
-void Path::translatePath(char pathSeparator/*=NV_PATH_SEPARATOR*/)
-{
- if (!isNull()) {
- translatePath(m_str, pathSeparator);
- }
-}
-
-void Path::appendSeparator(char pathSeparator/*=NV_PATH_SEPARATOR*/)
-{
- nvCheck(!isNull());
-
- const uint l = length();
-
- if (m_str[l] != '\\' && m_str[l] != '/') {
- char separatorString[] = { pathSeparator, '\0' };
- append(separatorString);
- }
-}
-
-
-/**
-* Strip the file name from a path.
-* @warning path cannot end with '/' o '\\', can't it?
-*/
-void Path::stripFileName()
-{
- nvCheck( m_str != NULL );
-
- int length = (int)strlen(m_str) - 1;
- while (length > 0 && m_str[length] != '/' && m_str[length] != '\\'){
- length--;
- }
- if( length ) {
- m_str[length+1] = 0;
- }
- else {
- m_str[0] = 0;
- }
-}
-
-
-/// Strip the extension from a path name.
-void Path::stripExtension()
-{
- nvCheck( m_str != NULL );
-
- int length = (int)strlen(m_str) - 1;
- while (length > 0 && m_str[length] != '.') {
- length--;
- if( m_str[length] == NV_PATH_SEPARATOR ) {
- return; // no extension
- }
- }
- if (length > 0) {
- m_str[length] = 0;
- }
-}
-
-
-/// Get the path separator.
-// static
-char Path::separator()
-{
- return NV_PATH_SEPARATOR;
-}
-
-// static
-const char * Path::fileName(const char * str)
-{
- nvCheck( str != NULL );
-
- int length = (int)strlen(str) - 1;
- while (length >= 0 && str[length] != '\\' && str[length] != '/') {
- length--;
- }
-
- return &str[length+1];
-}
-
-// static
-const char * Path::extension(const char * str)
-{
- nvCheck( str != NULL );
-
- int length, l;
- l = length = (int)strlen( str );
- while (length > 0 && str[length] != '.') {
- length--;
- if (str[length] == '\\' || str[length] == '/') {
- return &str[l]; // no extension
- }
- }
- if (length == 0) {
- return &str[l];
- }
- return &str[length];
-}
-
-
-
-/// Clone this string
-String String::clone() const
-{
- String str(data);
- return str;
-}
-
-void String::setString(const char * str)
-{
- if (str == NULL) {
- data = NULL;
- }
- else {
- allocString( str );
- addRef();
- }
-}
-
-void String::setString(const char * str, uint length)
-{
- nvDebugCheck(str != NULL);
-
- allocString(str, length);
- addRef();
-}
-
-void String::setString(const StringBuilder & str)
-{
- if (str.str() == NULL) {
- data = NULL;
- }
- else {
- allocString(str.str());
- addRef();
- }
-}
-
-// Add reference count.
-void String::addRef()
-{
- if (data != NULL)
- {
- setRefCount(getRefCount() + 1);
- }
-}
-
-// Decrease reference count.
-void String::release()
-{
- if (data != NULL)
- {
- const uint16 count = getRefCount();
- setRefCount(count - 1);
- if (count - 1 == 0) {
- free(data - 2);
- data = NULL;
- }
- }
-}
-
-void String::allocString(const char * str, uint len)
-{
- const char * ptr = malloc<char>(2 + len + 1);
-
- setData( ptr );
- setRefCount( 0 );
-
- // Copy string.
- strCpy(const_cast<char *>(data), len+1, str, len);
-
- // Add terminating character.
- const_cast<char *>(data)[len] = '\0';
-}
-
-void nv::swap(String & a, String & b) {
- swap(a.data, b.data);
-}
diff --git a/thirdparty/thekla_atlas/nvcore/StrLib.h b/thirdparty/thekla_atlas/nvcore/StrLib.h
deleted file mode 100644
index ae4b5d12a0..0000000000
--- a/thirdparty/thekla_atlas/nvcore/StrLib.h
+++ /dev/null
@@ -1,433 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#pragma once
-#ifndef NV_CORE_STRING_H
-#define NV_CORE_STRING_H
-
-#include "Debug.h"
-#include "Hash.h" // hash
-
-//#include <string.h> // strlen, etc.
-
-#if NV_OS_WIN32
-#define NV_PATH_SEPARATOR '\\'
-#else
-#define NV_PATH_SEPARATOR '/'
-#endif
-
-namespace nv
-{
-
- NVCORE_API uint strHash(const char * str, uint h) NV_PURE;
-
- /// String hash based on Bernstein's hash.
- inline uint strHash(const char * data, uint h = 5381)
- {
- uint i = 0;
- while(data[i] != 0) {
- h = (33 * h) ^ uint(data[i]);
- i++;
- }
- return h;
- }
-
- template <> struct Hash<const char *> {
- uint operator()(const char * str) const { return strHash(str); }
- };
-
- NVCORE_API uint strLen(const char * str) NV_PURE; // Asserts on NULL strings.
-
- NVCORE_API int strDiff(const char * s1, const char * s2) NV_PURE; // Asserts on NULL strings.
- NVCORE_API int strCaseDiff(const char * s1, const char * s2) NV_PURE; // Asserts on NULL strings.
- NVCORE_API bool strEqual(const char * s1, const char * s2) NV_PURE; // Accepts NULL strings.
- NVCORE_API bool strCaseEqual(const char * s1, const char * s2) NV_PURE; // Accepts NULL strings.
-
- template <> struct Equal<const char *> {
- bool operator()(const char * a, const char * b) const { return strEqual(a, b); }
- };
-
- NVCORE_API bool strBeginsWith(const char * dst, const char * prefix) NV_PURE;
- NVCORE_API bool strEndsWith(const char * dst, const char * suffix) NV_PURE;
-
-
- NVCORE_API void strCpy(char * dst, uint size, const char * src);
- NVCORE_API void strCpy(char * dst, uint size, const char * src, uint len);
- NVCORE_API void strCat(char * dst, uint size, const char * src);
-
- NVCORE_API const char * strSkipWhiteSpace(const char * str);
- NVCORE_API char * strSkipWhiteSpace(char * str);
-
- NVCORE_API bool strMatch(const char * str, const char * pat) NV_PURE;
-
- NVCORE_API bool isNumber(const char * str) NV_PURE;
-
- /* @@ Implement these two functions and modify StringBuilder to use them?
- NVCORE_API void strFormat(const char * dst, const char * fmt, ...);
- NVCORE_API void strFormatList(const char * dst, const char * fmt, va_list arg);
-
- template <size_t count> void strFormatSafe(char (&buffer)[count], const char *fmt, ...) __attribute__((format (printf, 2, 3)));
- template <size_t count> void strFormatSafe(char (&buffer)[count], const char *fmt, ...) {
- va_list args;
- va_start(args, fmt);
- strFormatList(buffer, count, fmt, args);
- va_end(args);
- }
- template <size_t count> void strFormatListSafe(char (&buffer)[count], const char *fmt, va_list arg) {
- va_list tmp;
- va_copy(tmp, args);
- strFormatList(buffer, count, fmt, tmp);
- va_end(tmp);
- }*/
-
- template <int count> void strCpySafe(char (&buffer)[count], const char *src) {
- strCpy(buffer, count, src);
- }
-
- template <int count> void strCatSafe(char (&buffer)[count], const char * src) {
- strCat(buffer, count, src);
- }
-
-
-
- /// String builder.
- class NVCORE_CLASS StringBuilder
- {
- public:
-
- StringBuilder();
- explicit StringBuilder( uint size_hint );
- StringBuilder(const char * str);
- StringBuilder(const char * str, uint len);
- StringBuilder(const StringBuilder & other);
-
- ~StringBuilder();
-
- StringBuilder & format( const char * format, ... ) __attribute__((format (printf, 2, 3)));
- StringBuilder & formatList( const char * format, va_list arg );
-
- StringBuilder & append(char c);
- StringBuilder & append(const char * str);
- StringBuilder & append(const char * str, uint len);
- StringBuilder & append(const StringBuilder & str);
- StringBuilder & appendFormat(const char * format, ...) __attribute__((format (printf, 2, 3)));
- StringBuilder & appendFormatList(const char * format, va_list arg);
-
- StringBuilder & appendSpace(uint n);
-
- StringBuilder & number( int i, int base = 10 );
- StringBuilder & number( uint i, int base = 10 );
-
- StringBuilder & reserve(uint size_hint);
- StringBuilder & copy(const char * str);
- StringBuilder & copy(const char * str, uint len);
- StringBuilder & copy(const StringBuilder & str);
-
- StringBuilder & toLower();
- StringBuilder & toUpper();
-
- bool endsWith(const char * str) const;
- bool beginsWith(const char * str) const;
-
- char * reverseFind(char c);
-
- void reset();
- bool isNull() const { return m_size == 0; }
-
- // const char * accessors
- //operator const char * () const { return m_str; }
- //operator char * () { return m_str; }
- const char * str() const { return m_str; }
- char * str() { return m_str; }
-
- char * release(); // Release ownership of string.
- void acquire(char *); // Take ownership of string.
-
- /// Implement value semantics.
- StringBuilder & operator=( const StringBuilder & s ) {
- return copy(s);
- }
-
- /// Implement value semantics.
- StringBuilder & operator=( const char * s ) {
- return copy(s);
- }
-
- /// Equal operator.
- bool operator==( const StringBuilder & s ) const {
- return strMatch(s.m_str, m_str);
- }
-
- /// Return the exact length.
- uint length() const { return isNull() ? 0 : strLen(m_str); }
-
- /// Return the size of the string container.
- uint capacity() const { return m_size; }
-
- /// Return the hash of the string.
- uint hash() const { return isNull() ? 0 : strHash(m_str); }
-
- // Swap strings.
- friend void swap(StringBuilder & a, StringBuilder & b);
-
- protected:
-
- /// Size of the string container.
- uint m_size;
-
- /// String.
- char * m_str;
-
- };
-
-
- /// Path string. @@ This should be called PathBuilder.
- class NVCORE_CLASS Path : public StringBuilder
- {
- public:
- Path() : StringBuilder() {}
- explicit Path(int size_hint) : StringBuilder(size_hint) {}
- Path(const char * str) : StringBuilder(str) {}
- Path(const Path & path) : StringBuilder(path) {}
-
- const char * fileName() const;
- const char * extension() const;
-
- void translatePath(char pathSeparator = NV_PATH_SEPARATOR);
-
- void appendSeparator(char pathSeparator = NV_PATH_SEPARATOR);
-
- void stripFileName();
- void stripExtension();
-
- // statics
- NVCORE_API static char separator();
- NVCORE_API static const char * fileName(const char *);
- NVCORE_API static const char * extension(const char *);
-
- NVCORE_API static void translatePath(char * path, char pathSeparator = NV_PATH_SEPARATOR);
- };
-
-
- /// String class.
- class NVCORE_CLASS String
- {
- public:
-
- /// Constructs a null string. @sa isNull()
- String()
- {
- data = NULL;
- }
-
- /// Constructs a shared copy of str.
- String(const String & str)
- {
- data = str.data;
- if (data != NULL) addRef();
- }
-
- /// Constructs a shared string from a standard string.
- String(const char * str)
- {
- setString(str);
- }
-
- /// Constructs a shared string from a standard string.
- String(const char * str, int length)
- {
- setString(str, length);
- }
-
- /// Constructs a shared string from a StringBuilder.
- String(const StringBuilder & str)
- {
- setString(str);
- }
-
- /// Dtor.
- ~String()
- {
- release();
- }
-
- String clone() const;
-
- /// Release the current string and allocate a new one.
- const String & operator=( const char * str )
- {
- release();
- setString( str );
- return *this;
- }
-
- /// Release the current string and allocate a new one.
- const String & operator=( const StringBuilder & str )
- {
- release();
- setString( str );
- return *this;
- }
-
- /// Implement value semantics.
- String & operator=( const String & str )
- {
- if (str.data != data)
- {
- release();
- data = str.data;
- addRef();
- }
- return *this;
- }
-
- /// Equal operator.
- bool operator==( const String & str ) const
- {
- return strMatch(str.data, data);
- }
-
- /// Equal operator.
- bool operator==( const char * str ) const
- {
- return strMatch(str, data);
- }
-
- /// Not equal operator.
- bool operator!=( const String & str ) const
- {
- return !strMatch(str.data, data);
- }
-
- /// Not equal operator.
- bool operator!=( const char * str ) const
- {
- return !strMatch(str, data);
- }
-
- /// Returns true if this string is the null string.
- bool isNull() const { return data == NULL; }
-
- /// Return the exact length.
- uint length() const { nvDebugCheck(data != NULL); return strLen(data); }
-
- /// Return the hash of the string.
- uint hash() const { nvDebugCheck(data != NULL); return strHash(data); }
-
- /// const char * cast operator.
- operator const char * () const { return data; }
-
- /// Get string pointer.
- const char * str() const { return data; }
-
-
- private:
-
- // Add reference count.
- void addRef();
-
- // Decrease reference count.
- void release();
-
- uint16 getRefCount() const
- {
- nvDebugCheck(data != NULL);
- return *reinterpret_cast<const uint16 *>(data - 2);
- }
-
- void setRefCount(uint16 count) {
- nvDebugCheck(data != NULL);
- nvCheck(count < 0xFFFF);
- *reinterpret_cast<uint16 *>(const_cast<char *>(data - 2)) = uint16(count);
- }
-
- void setData(const char * str) {
- data = str + 2;
- }
-
- void allocString(const char * str)
- {
- allocString(str, strLen(str));
- }
-
- void allocString(const char * str, uint length);
-
- void setString(const char * str);
- void setString(const char * str, uint length);
- void setString(const StringBuilder & str);
-
- // Swap strings.
- friend void swap(String & a, String & b);
-
- private:
-
- const char * data;
-
- };
-
- template <> struct Hash<String> {
- uint operator()(const String & str) const { return str.hash(); }
- };
-
-
- // Like AutoPtr, but for const char strings.
- class AutoString
- {
- NV_FORBID_COPY(AutoString);
- NV_FORBID_HEAPALLOC();
- public:
-
- // Ctor.
- AutoString(const char * p = NULL) : m_ptr(p) { }
-
-#if NV_CC_CPP11
- // Move ctor.
- AutoString(AutoString && ap) : m_ptr(ap.m_ptr) { ap.m_ptr = NULL; }
-#endif
-
- // Dtor. Deletes owned pointer.
- ~AutoString() {
- delete [] m_ptr;
- m_ptr = NULL;
- }
-
- // Delete owned pointer and assign new one.
- void operator=(const char * p) {
- if (p != m_ptr)
- {
- delete [] m_ptr;
- m_ptr = p;
- }
- }
-
- // Get pointer.
- const char * ptr() const { return m_ptr; }
- operator const char *() const { return m_ptr; }
-
- // Relinquish ownership of the underlying pointer and returns that pointer.
- const char * release() {
- const char * tmp = m_ptr;
- m_ptr = NULL;
- return tmp;
- }
-
- // comparison operators.
- friend bool operator == (const AutoString & ap, const char * const p) {
- return (ap.ptr() == p);
- }
- friend bool operator != (const AutoString & ap, const char * const p) {
- return (ap.ptr() != p);
- }
- friend bool operator == (const char * const p, const AutoString & ap) {
- return (ap.ptr() == p);
- }
- friend bool operator != (const char * const p, const AutoString & ap) {
- return (ap.ptr() != p);
- }
-
- private:
- const char * m_ptr;
- };
-
-} // nv namespace
-
-#endif // NV_CORE_STRING_H
diff --git a/thirdparty/thekla_atlas/nvcore/Stream.h b/thirdparty/thekla_atlas/nvcore/Stream.h
deleted file mode 100644
index c35c0d0c78..0000000000
--- a/thirdparty/thekla_atlas/nvcore/Stream.h
+++ /dev/null
@@ -1,164 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#pragma once
-#ifndef NV_CORE_STREAM_H
-#define NV_CORE_STREAM_H
-
-#include "nvcore.h"
-#include "Debug.h"
-
-namespace nv
-{
-
- /// Base stream class.
- class NVCORE_CLASS Stream {
- public:
-
- enum ByteOrder {
- LittleEndian = false,
- BigEndian = true,
- };
-
- /// Get the byte order of the system.
- static ByteOrder getSystemByteOrder() {
-#if NV_LITTLE_ENDIAN
- return LittleEndian;
-#else
- return BigEndian;
-#endif
- }
-
-
- /// Ctor.
- Stream() : m_byteOrder(LittleEndian) { }
-
- /// Virtual destructor.
- virtual ~Stream() {}
-
- /// Set byte order.
- void setByteOrder(ByteOrder bo) { m_byteOrder = bo; }
-
- /// Get byte order.
- ByteOrder byteOrder() const { return m_byteOrder; }
-
-
- /// Serialize the given data.
- virtual uint serialize( void * data, uint len ) = 0;
-
- /// Move to the given position in the archive.
- virtual void seek( uint pos ) = 0;
-
- /// Return the current position in the archive.
- virtual uint tell() const = 0;
-
- /// Return the current size of the archive.
- virtual uint size() const = 0;
-
- /// Determine if there has been any error.
- virtual bool isError() const = 0;
-
- /// Clear errors.
- virtual void clearError() = 0;
-
- /// Return true if the stream is at the end.
- virtual bool isAtEnd() const = 0;
-
- /// Return true if the stream is seekable.
- virtual bool isSeekable() const = 0;
-
- /// Return true if this is an input stream.
- virtual bool isLoading() const = 0;
-
- /// Return true if this is an output stream.
- virtual bool isSaving() const = 0;
-
-
- void advance(uint offset) { seek(tell() + offset); }
-
-
- // friends
- friend Stream & operator<<( Stream & s, bool & c ) {
-#if NV_OS_DARWIN && !NV_CC_CPP11
- nvStaticCheck(sizeof(bool) == 4);
- uint8 b = c ? 1 : 0;
- s.serialize( &b, 1 );
- c = (b != 0);
-#else
- nvStaticCheck(sizeof(bool) == 1);
- s.serialize( &c, 1 );
-#endif
- return s;
- }
- friend Stream & operator<<( Stream & s, char & c ) {
- nvStaticCheck(sizeof(char) == 1);
- s.serialize( &c, 1 );
- return s;
- }
- friend Stream & operator<<( Stream & s, uint8 & c ) {
- nvStaticCheck(sizeof(uint8) == 1);
- s.serialize( &c, 1 );
- return s;
- }
- friend Stream & operator<<( Stream & s, int8 & c ) {
- nvStaticCheck(sizeof(int8) == 1);
- s.serialize( &c, 1 );
- return s;
- }
- friend Stream & operator<<( Stream & s, uint16 & c ) {
- nvStaticCheck(sizeof(uint16) == 2);
- return s.byteOrderSerialize( &c, 2 );
- }
- friend Stream & operator<<( Stream & s, int16 & c ) {
- nvStaticCheck(sizeof(int16) == 2);
- return s.byteOrderSerialize( &c, 2 );
- }
- friend Stream & operator<<( Stream & s, uint32 & c ) {
- nvStaticCheck(sizeof(uint32) == 4);
- return s.byteOrderSerialize( &c, 4 );
- }
- friend Stream & operator<<( Stream & s, int32 & c ) {
- nvStaticCheck(sizeof(int32) == 4);
- return s.byteOrderSerialize( &c, 4 );
- }
- friend Stream & operator<<( Stream & s, uint64 & c ) {
- nvStaticCheck(sizeof(uint64) == 8);
- return s.byteOrderSerialize( &c, 8 );
- }
- friend Stream & operator<<( Stream & s, int64 & c ) {
- nvStaticCheck(sizeof(int64) == 8);
- return s.byteOrderSerialize( &c, 8 );
- }
- friend Stream & operator<<( Stream & s, float & c ) {
- nvStaticCheck(sizeof(float) == 4);
- return s.byteOrderSerialize( &c, 4 );
- }
- friend Stream & operator<<( Stream & s, double & c ) {
- nvStaticCheck(sizeof(double) == 8);
- return s.byteOrderSerialize( &c, 8 );
- }
-
- protected:
-
- /// Serialize in the stream byte order.
- Stream & byteOrderSerialize( void * v, uint len ) {
- if( m_byteOrder == getSystemByteOrder() ) {
- serialize( v, len );
- }
- else {
- for( uint i = len; i > 0; i-- ) {
- serialize( (uint8 *)v + i - 1, 1 );
- }
- }
- return *this;
- }
-
-
- private:
-
- ByteOrder m_byteOrder;
-
- };
-
-} // nv namespace
-
-#endif // NV_CORE_STREAM_H
diff --git a/thirdparty/thekla_atlas/nvcore/Utils.h b/thirdparty/thekla_atlas/nvcore/Utils.h
deleted file mode 100644
index f20e42cda8..0000000000
--- a/thirdparty/thekla_atlas/nvcore/Utils.h
+++ /dev/null
@@ -1,315 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#pragma once
-#ifndef NV_CORE_UTILS_H
-#define NV_CORE_UTILS_H
-
-#include "Debug.h" // nvDebugCheck
-
-#include <new> // for placement new
-
-
-// Just in case. Grrr.
-#undef min
-#undef max
-
-#define NV_INT8_MIN (-128)
-#define NV_INT8_MAX 127
-#define NV_UINT8_MAX 255
-#define NV_INT16_MIN (-32767-1)
-#define NV_INT16_MAX 32767
-#define NV_UINT16_MAX 0xffff
-#define NV_INT32_MIN (-2147483647-1)
-#define NV_INT32_MAX 2147483647
-#define NV_UINT32_MAX 0xffffffff
-#define NV_INT64_MAX POSH_I64(9223372036854775807)
-#define NV_INT64_MIN (-POSH_I64(9223372036854775807)-1)
-#define NV_UINT64_MAX POSH_U64(0xffffffffffffffff)
-
-#define NV_HALF_MAX 65504.0F
-#define NV_FLOAT_MAX 3.402823466e+38F
-
-#define NV_INTEGER_TO_FLOAT_MAX 16777217 // Largest integer such that it and all smaller integers can be stored in a 32bit float.
-
-
-namespace nv
-{
- // Less error prone than casting. From CB:
- // http://cbloomrants.blogspot.com/2011/06/06-17-11-c-casting-is-devil.html
-
- // These intentionally look like casts.
-
- // uint64 casts:
- template <typename T> inline uint64 U64(T x) { return x; }
- //template <> inline uint64 U64<uint64>(uint64 x) { return x; }
- template <> inline uint64 U64<int64>(int64 x) { nvDebugCheck(x >= 0); return (uint64)x; }
- //template <> inline uint64 U32<uint32>(uint32 x) { return x; }
- template <> inline uint64 U64<int32>(int32 x) { nvDebugCheck(x >= 0); return (uint64)x; }
- //template <> inline uint64 U64<uint16>(uint16 x) { return x; }
- template <> inline uint64 U64<int16>(int16 x) { nvDebugCheck(x >= 0); return (uint64)x; }
- //template <> inline uint64 U64<uint8>(uint8 x) { return x; }
- template <> inline uint64 U64<int8>(int8 x) { nvDebugCheck(x >= 0); return (uint64)x; }
-
- // int64 casts:
- template <typename T> inline int64 I64(T x) { return x; }
- template <> inline int64 I64<uint64>(uint64 x) { nvDebugCheck(x <= NV_INT64_MAX); return (int64)x; }
- //template <> inline uint64 U64<int64>(int64 x) { return x; }
- //template <> inline uint64 U32<uint32>(uint32 x) { return x; }
- //template <> inline uint64 U64<int32>(int32 x) { return x; }
- //template <> inline uint64 U64<uint16>(uint16 x) { return x; }
- //template <> inline uint64 U64<int16>(int16 x) { return x; }
- //template <> inline uint64 U64<uint8>(uint8 x) { return x; }
- //template <> inline uint64 U64<int8>(int8 x) { return x; }
-
- // uint32 casts:
- template <typename T> inline uint32 U32(T x) { return x; }
- template <> inline uint32 U32<uint64>(uint64 x) { nvDebugCheck(x <= NV_UINT32_MAX); return (uint32)x; }
- template <> inline uint32 U32<int64>(int64 x) { nvDebugCheck(x >= 0 && x <= NV_UINT32_MAX); return (uint32)x; }
- //template <> inline uint32 U32<uint32>(uint32 x) { return x; }
- template <> inline uint32 U32<int32>(int32 x) { nvDebugCheck(x >= 0); return (uint32)x; }
- //template <> inline uint32 U32<uint16>(uint16 x) { return x; }
- template <> inline uint32 U32<int16>(int16 x) { nvDebugCheck(x >= 0); return (uint32)x; }
- //template <> inline uint32 U32<uint8>(uint8 x) { return x; }
- template <> inline uint32 U32<int8>(int8 x) { nvDebugCheck(x >= 0); return (uint32)x; }
-
- // int32 casts:
- template <typename T> inline int32 I32(T x) { return x; }
- template <> inline int32 I32<uint64>(uint64 x) { nvDebugCheck(x <= NV_INT32_MAX); return (int32)x; }
- template <> inline int32 I32<int64>(int64 x) { nvDebugCheck(x >= NV_INT32_MIN && x <= NV_UINT32_MAX); return (int32)x; }
- template <> inline int32 I32<uint32>(uint32 x) { nvDebugCheck(x <= NV_INT32_MAX); return (int32)x; }
- //template <> inline int32 I32<int32>(int32 x) { return x; }
- //template <> inline int32 I32<uint16>(uint16 x) { return x; }
- //template <> inline int32 I32<int16>(int16 x) { return x; }
- //template <> inline int32 I32<uint8>(uint8 x) { return x; }
- //template <> inline int32 I32<int8>(int8 x) { return x; }
-
- // uint16 casts:
- template <typename T> inline uint16 U16(T x) { return x; }
- template <> inline uint16 U16<uint64>(uint64 x) { nvDebugCheck(x <= NV_UINT16_MAX); return (uint16)x; }
- template <> inline uint16 U16<int64>(int64 x) { nvDebugCheck(x >= 0 && x <= NV_UINT16_MAX); return (uint16)x; }
- template <> inline uint16 U16<uint32>(uint32 x) { nvDebugCheck(x <= NV_UINT16_MAX); return (uint16)x; }
- template <> inline uint16 U16<int32>(int32 x) { nvDebugCheck(x >= 0 && x <= NV_UINT16_MAX); return (uint16)x; }
- //template <> inline uint16 U16<uint16>(uint16 x) { return x; }
- template <> inline uint16 U16<int16>(int16 x) { nvDebugCheck(x >= 0); return (uint16)x; }
- //template <> inline uint16 U16<uint8>(uint8 x) { return x; }
- template <> inline uint16 U16<int8>(int8 x) { nvDebugCheck(x >= 0); return (uint16)x; }
-
- // int16 casts:
- template <typename T> inline int16 I16(T x) { return x; }
- template <> inline int16 I16<uint64>(uint64 x) { nvDebugCheck(x <= NV_INT16_MAX); return (int16)x; }
- template <> inline int16 I16<int64>(int64 x) { nvDebugCheck(x >= NV_INT16_MIN && x <= NV_UINT16_MAX); return (int16)x; }
- template <> inline int16 I16<uint32>(uint32 x) { nvDebugCheck(x <= NV_INT16_MAX); return (int16)x; }
- template <> inline int16 I16<int32>(int32 x) { nvDebugCheck(x >= NV_INT16_MIN && x <= NV_UINT16_MAX); return (int16)x; }
- template <> inline int16 I16<uint16>(uint16 x) { nvDebugCheck(x <= NV_INT16_MAX); return (int16)x; }
- //template <> inline int16 I16<int16>(int16 x) { return x; }
- //template <> inline int16 I16<uint8>(uint8 x) { return x; }
- //template <> inline int16 I16<int8>(int8 x) { return x; }
-
- // uint8 casts:
- template <typename T> inline uint8 U8(T x) { return x; }
- template <> inline uint8 U8<uint64>(uint64 x) { nvDebugCheck(x <= NV_UINT8_MAX); return (uint8)x; }
- template <> inline uint8 U8<int64>(int64 x) { nvDebugCheck(x >= 0 && x <= NV_UINT8_MAX); return (uint8)x; }
- template <> inline uint8 U8<uint32>(uint32 x) { nvDebugCheck(x <= NV_UINT8_MAX); return (uint8)x; }
- template <> inline uint8 U8<int32>(int32 x) { nvDebugCheck(x >= 0 && x <= NV_UINT8_MAX); return (uint8)x; }
- template <> inline uint8 U8<uint16>(uint16 x) { nvDebugCheck(x <= NV_UINT8_MAX); return (uint8)x; }
- template <> inline uint8 U8<int16>(int16 x) { nvDebugCheck(x >= 0 && x <= NV_UINT8_MAX); return (uint8)x; }
- //template <> inline uint8 U8<uint8>(uint8 x) { return x; }
- template <> inline uint8 U8<int8>(int8 x) { nvDebugCheck(x >= 0); return (uint8)x; }
- //template <> inline uint8 U8<float>(int8 x) { nvDebugCheck(x >= 0.0f && x <= 255.0f); return (uint8)x; }
-
- // int8 casts:
- template <typename T> inline int8 I8(T x) { return x; }
- template <> inline int8 I8<uint64>(uint64 x) { nvDebugCheck(x <= NV_INT8_MAX); return (int8)x; }
- template <> inline int8 I8<int64>(int64 x) { nvDebugCheck(x >= NV_INT8_MIN && x <= NV_UINT8_MAX); return (int8)x; }
- template <> inline int8 I8<uint32>(uint32 x) { nvDebugCheck(x <= NV_INT8_MAX); return (int8)x; }
- template <> inline int8 I8<int32>(int32 x) { nvDebugCheck(x >= NV_INT8_MIN && x <= NV_UINT8_MAX); return (int8)x; }
- template <> inline int8 I8<uint16>(uint16 x) { nvDebugCheck(x <= NV_INT8_MAX); return (int8)x; }
- template <> inline int8 I8<int16>(int16 x) { nvDebugCheck(x >= NV_INT8_MIN && x <= NV_UINT8_MAX); return (int8)x; }
- template <> inline int8 I8<uint8>(uint8 x) { nvDebugCheck(x <= NV_INT8_MAX); return (int8)x; }
- //template <> inline int8 I8<int8>(int8 x) { return x; }
-
- // float casts:
- template <typename T> inline float F32(T x) { return x; }
- template <> inline float F32<uint64>(uint64 x) { nvDebugCheck(x <= NV_INTEGER_TO_FLOAT_MAX); return (float)x; }
- template <> inline float F32<int64>(int64 x) { nvDebugCheck(x >= -NV_INTEGER_TO_FLOAT_MAX && x <= NV_INTEGER_TO_FLOAT_MAX); return (float)x; }
- template <> inline float F32<uint32>(uint32 x) { nvDebugCheck(x <= NV_INTEGER_TO_FLOAT_MAX); return (float)x; }
- template <> inline float F32<int32>(int32 x) { nvDebugCheck(x >= -NV_INTEGER_TO_FLOAT_MAX && x <= NV_INTEGER_TO_FLOAT_MAX); return (float)x; }
- // The compiler should not complain about these conversions:
- //template <> inline float F32<uint16>(uint16 x) { nvDebugCheck(return (float)x; }
- //template <> inline float F32<int16>(int16 x) { nvDebugCheck(return (float)x; }
- //template <> inline float F32<uint8>(uint8 x) { nvDebugCheck(return (float)x; }
- //template <> inline float F32<int8>(int8 x) { nvDebugCheck(return (float)x; }
-
-
- /// Swap two values.
- template <typename T>
- inline void swap(T & a, T & b)
- {
- T temp(a);
- a = b;
- b = temp;
- }
-
- /// Return the maximum of the two arguments. For floating point values, it returns the second value if the first is NaN.
- template <typename T>
- //inline const T & max(const T & a, const T & b)
- inline T max(const T & a, const T & b)
- {
- return (b < a) ? a : b;
- }
-
- /// Return the maximum of the four arguments.
- template <typename T>
- //inline const T & max4(const T & a, const T & b, const T & c)
- inline T max4(const T & a, const T & b, const T & c, const T & d)
- {
- return max(max(a, b), max(c, d));
- }
-
- /// Return the maximum of the three arguments.
- template <typename T>
- //inline const T & max3(const T & a, const T & b, const T & c)
- inline T max3(const T & a, const T & b, const T & c)
- {
- return max(a, max(b, c));
- }
-
- /// Return the minimum of two values.
- template <typename T>
- //inline const T & min(const T & a, const T & b)
- inline T min(const T & a, const T & b)
- {
- return (a < b) ? a : b;
- }
-
- /// Return the maximum of the three arguments.
- template <typename T>
- //inline const T & min3(const T & a, const T & b, const T & c)
- inline T min3(const T & a, const T & b, const T & c)
- {
- return min(a, min(b, c));
- }
-
- /// Clamp between two values.
- template <typename T>
- //inline const T & clamp(const T & x, const T & a, const T & b)
- inline T clamp(const T & x, const T & a, const T & b)
- {
- return min(max(x, a), b);
- }
-
- /** Return the next power of two.
- * @see http://graphics.stanford.edu/~seander/bithacks.html
- * @warning Behaviour for 0 is undefined.
- * @note isPowerOfTwo(x) == true -> nextPowerOfTwo(x) == x
- * @note nextPowerOfTwo(x) = 2 << log2(x-1)
- */
- inline uint32 nextPowerOfTwo(uint32 x)
- {
- nvDebugCheck( x != 0 );
-#if 1 // On modern CPUs this is supposed to be as fast as using the bsr instruction.
- x--;
- x |= x >> 1;
- x |= x >> 2;
- x |= x >> 4;
- x |= x >> 8;
- x |= x >> 16;
- return x+1;
-#else
- uint p = 1;
- while( x > p ) {
- p += p;
- }
- return p;
-#endif
- }
-
- inline uint64 nextPowerOfTwo(uint64 x)
- {
- nvDebugCheck(x != 0);
- uint p = 1;
- while (x > p) {
- p += p;
- }
- return p;
- }
-
- // @@ Should I just use a macro instead?
- template <typename T>
- inline bool isPowerOfTwo(T n)
- {
- return (n & (n-1)) == 0;
- }
-
-
- // @@ Move this to utils?
- /// Delete all the elements of a container.
- template <typename T>
- void deleteAll(T & container)
- {
- for (typename T::PseudoIndex i = container.start(); !container.isDone(i); container.advance(i))
- {
- delete container[i];
- }
- }
-
-
-
- // @@ Specialize these methods for numeric, pointer, and pod types.
-
- template <typename T>
- void construct_range(T * restrict ptr, uint new_size, uint old_size) {
- for (uint i = old_size; i < new_size; i++) {
- new(ptr+i) T; // placement new
- }
- }
-
- template <typename T>
- void construct_range(T * restrict ptr, uint new_size, uint old_size, const T & elem) {
- for (uint i = old_size; i < new_size; i++) {
- new(ptr+i) T(elem); // placement new
- }
- }
-
- template <typename T>
- void construct_range(T * restrict ptr, uint new_size, uint old_size, const T * src) {
- for (uint i = old_size; i < new_size; i++) {
- new(ptr+i) T(src[i]); // placement new
- }
- }
-
- template <typename T>
- void destroy_range(T * restrict ptr, uint new_size, uint old_size) {
- for (uint i = new_size; i < old_size; i++) {
- (ptr+i)->~T(); // Explicit call to the destructor
- }
- }
-
- template <typename T>
- void fill(T * restrict dst, uint count, const T & value) {
- for (uint i = 0; i < count; i++) {
- dst[i] = value;
- }
- }
-
- template <typename T>
- void copy_range(T * restrict dst, const T * restrict src, uint count) {
- for (uint i = 0; i < count; i++) {
- dst[i] = src[i];
- }
- }
-
- template <typename T>
- bool find(const T & element, const T * restrict ptr, uint begin, uint end, uint * index) {
- for (uint i = begin; i < end; i++) {
- if (ptr[i] == element) {
- if (index != NULL) *index = i;
- return true;
- }
- }
- return false;
- }
-
-} // nv namespace
-
-#endif // NV_CORE_UTILS_H
diff --git a/thirdparty/thekla_atlas/nvcore/nvcore.h b/thirdparty/thekla_atlas/nvcore/nvcore.h
deleted file mode 100644
index 5ef69668d9..0000000000
--- a/thirdparty/thekla_atlas/nvcore/nvcore.h
+++ /dev/null
@@ -1,360 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#pragma once
-#ifndef NV_CORE_H
-#define NV_CORE_H
-
-// Function linkage
-#if NVCORE_SHARED
-#ifdef NVCORE_EXPORTS
-#define NVCORE_API DLL_EXPORT
-#define NVCORE_CLASS DLL_EXPORT_CLASS
-#else
-#define NVCORE_API DLL_IMPORT
-#define NVCORE_CLASS DLL_IMPORT
-#endif
-#else // NVCORE_SHARED
-#define NVCORE_API
-#define NVCORE_CLASS
-#endif // NVCORE_SHARED
-
-
-// Platform definitions
-#include <posh.h>
-
-// OS:
-// NV_OS_WIN32
-// NV_OS_WIN64
-// NV_OS_MINGW
-// NV_OS_CYGWIN
-// NV_OS_LINUX
-// NV_OS_UNIX
-// NV_OS_DARWIN
-// NV_OS_XBOX
-// NV_OS_ORBIS
-// NV_OS_IOS
-
-#define NV_OS_STRING POSH_OS_STRING
-
-#if defined POSH_OS_LINUX
-# define NV_OS_LINUX 1
-# define NV_OS_UNIX 1
-#elif defined POSH_OS_ORBIS
-# define NV_OS_ORBIS 1
-#elif defined POSH_OS_FREEBSD
-# define NV_OS_FREEBSD 1
-# define NV_OS_UNIX 1
-#elif defined POSH_OS_HAIKU
-# define NV_OS_HAIKU 1
-# define NV_OS_UNIX 1
-#elif defined POSH_OS_OPENBSD
-# define NV_OS_OPENBSD 1
-# define NV_OS_UNIX 1
-#elif defined POSH_OS_CYGWIN32
-# define NV_OS_CYGWIN 1
-#elif defined POSH_OS_MINGW
-# define NV_OS_MINGW 1
-# define NV_OS_WIN32 1
-#elif defined POSH_OS_OSX
-# define NV_OS_OSX 1 // IC: Adding this, because iOS defines NV_OS_DARWIN too.
-# define NV_OS_DARWIN 1
-# define NV_OS_UNIX 1
-#elif defined POSH_OS_IOS
-# define NV_OS_DARWIN 1 //ACS should we keep this on IOS?
-# define NV_OS_UNIX 1
-# define NV_OS_IOS 1
-#elif defined POSH_OS_UNIX
-# define NV_OS_UNIX 1
-#elif defined POSH_OS_WIN64
-# define NV_OS_WIN32 1
-# define NV_OS_WIN64 1
-#elif defined POSH_OS_WIN32
-# define NV_OS_WIN32 1
-#elif defined POSH_OS_XBOX
-# define NV_OS_XBOX 1
-#elif defined POSH_OS_DURANGO
-# define NV_OS_DURANGO 1
-#else
-# error "Unsupported OS"
-#endif
-
-
-// Is this a console OS? (i.e. connected to a TV)
-#if NV_OS_ORBIS || NV_OS_XBOX || NV_OS_DURANGO
-# define NV_OS_CONSOLE 1
-#endif
-
-
-// Threading:
-// some platforms don't implement __thread or similar for thread-local-storage
-#if NV_OS_UNIX || NV_OS_ORBIS || NV_OS_IOS //ACStodoIOS darwin instead of ios?
-# define NV_OS_USE_PTHREAD 1
-# if NV_OS_IOS
-# define NV_OS_HAS_TLS_QUALIFIER 0
-# else
-# define NV_OS_HAS_TLS_QUALIFIER 1
-# endif
-#else
-# define NV_OS_USE_PTHREAD 0
-# define NV_OS_HAS_TLS_QUALIFIER 1
-#endif
-
-
-// CPUs:
-// NV_CPU_X86
-// NV_CPU_X86_64
-// NV_CPU_PPC
-// NV_CPU_ARM
-
-#define NV_CPU_STRING POSH_CPU_STRING
-
-#if defined POSH_CPU_X86_64
-//# define NV_CPU_X86 1
-# define NV_CPU_X86_64 1
-#elif defined POSH_CPU_X86
-# define NV_CPU_X86 1
-#elif defined POSH_CPU_PPC
-# define NV_CPU_PPC 1
-#elif defined POSH_CPU_STRONGARM
-# define NV_CPU_ARM 1
-#else
-# error "Unsupported CPU"
-#endif
-
-
-// Compiler:
-// NV_CC_GNUC
-// NV_CC_MSVC
-// NV_CC_CLANG
-
-#if defined POSH_COMPILER_CLANG
-# define NV_CC_CLANG 1
-# define NV_CC_GNUC 1 // Clang is compatible with GCC.
-# define NV_CC_STRING "clang"
-#elif defined POSH_COMPILER_GCC
-# define NV_CC_GNUC 1
-# define NV_CC_STRING "gcc"
-#elif defined POSH_COMPILER_MSVC
-# define NV_CC_MSVC 1
-# define NV_CC_STRING "msvc"
-#else
-# error "Unsupported compiler"
-#endif
-
-#if NV_CC_MSVC
-#define NV_CC_CPP11 (__cplusplus > 199711L || _MSC_VER >= 1800) // Visual Studio 2013 has all the features we use, but doesn't advertise full C++11 support yet.
-#else
-// @@ IC: This works in CLANG, about GCC?
-// @@ ES: Doesn't work in gcc. These 3 features are available in GCC >= 4.4.
-#ifdef __clang__
-#define NV_CC_CPP11 (__has_feature(cxx_deleted_functions) && __has_feature(cxx_rvalue_references) && __has_feature(cxx_static_assert))
-#elif defined __GNUC__
-#define NV_CC_CPP11 ( __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
-#endif
-#endif
-
-// Endiannes:
-#define NV_LITTLE_ENDIAN POSH_LITTLE_ENDIAN
-#define NV_BIG_ENDIAN POSH_BIG_ENDIAN
-#define NV_ENDIAN_STRING POSH_ENDIAN_STRING
-
-
-// Define the right printf prefix for size_t arguments:
-#if POSH_64BIT_POINTER
-# define NV_SIZET_PRINTF_PREFIX POSH_I64_PRINTF_PREFIX
-#else
-# define NV_SIZET_PRINTF_PREFIX
-#endif
-
-
-// cmake config
-#include "nvconfig.h"
-
-#if NV_OS_DARWIN
-#include <stdint.h>
-//#include <inttypes.h>
-
-// Type definitions:
-typedef uint8_t uint8;
-typedef int8_t int8;
-
-typedef uint16_t uint16;
-typedef int16_t int16;
-
-typedef uint32_t uint32;
-typedef int32_t int32;
-
-typedef uint64_t uint64;
-typedef int64_t int64;
-
-// POSH gets this wrong due to __LP64__
-#undef POSH_I64_PRINTF_PREFIX
-#define POSH_I64_PRINTF_PREFIX "ll"
-
-#else
-
-// Type definitions:
-typedef posh_u8_t uint8;
-typedef posh_i8_t int8;
-
-typedef posh_u16_t uint16;
-typedef posh_i16_t int16;
-
-typedef posh_u32_t uint32;
-typedef posh_i32_t int32;
-
-//#if NV_OS_DARWIN
-// OSX-64 is supposed to be LP64 (longs and pointers are 64 bits), thus uint64 is defined as
-// unsigned long. However, some OSX headers define it as unsigned long long, producing errors,
-// even though both types are 64 bit. Ideally posh should handle that, but it has not been
-// updated in ages, so here I'm just falling back to the standard C99 types defined in inttypes.h
-//#include <inttypes.h>
-//typedef posh_u64_t uint64_t;
-//typedef posh_i64_t int64_t;
-//#else
-typedef posh_u64_t uint64;
-typedef posh_i64_t int64;
-//#endif
-#if NV_OS_DARWIN
-// To avoid duplicate definitions.
-#define _UINT64
-#endif
-#endif
-
-// Aliases
-typedef uint32 uint;
-
-
-// Version string:
-#define NV_VERSION_STRING \
- NV_OS_STRING "/" NV_CC_STRING "/" NV_CPU_STRING"/" \
- NV_ENDIAN_STRING"-endian - " __DATE__ "-" __TIME__
-
-
-// Disable copy constructor and assignment operator.
-#if NV_CC_CPP11
-#define NV_FORBID_COPY(C) \
- C( const C & ) = delete; \
- C &operator=( const C & ) = delete
-#else
-#define NV_FORBID_COPY(C) \
- private: \
- C( const C & ); \
- C &operator=( const C & )
-#endif
-
-// Disable dynamic allocation on the heap.
-// See Prohibiting Heap-Based Objects in More Effective C++.
-#define NV_FORBID_HEAPALLOC() \
- private: \
- void *operator new(size_t size); \
- void *operator new[](size_t size)
- //static void *operator new(size_t size); \
- //static void *operator new[](size_t size);
-
-// String concatenation macros.
-#define NV_STRING_JOIN2(arg1, arg2) NV_DO_STRING_JOIN2(arg1, arg2)
-#define NV_DO_STRING_JOIN2(arg1, arg2) arg1 ## arg2
-#define NV_STRING_JOIN3(arg1, arg2, arg3) NV_DO_STRING_JOIN3(arg1, arg2, arg3)
-#define NV_DO_STRING_JOIN3(arg1, arg2, arg3) arg1 ## arg2 ## arg3
-#define NV_STRING2(x) #x
-#define NV_STRING(x) NV_STRING2(x)
-
-#if NV_CC_MSVC
-#define NV_MULTI_LINE_MACRO_BEGIN do {
-#define NV_MULTI_LINE_MACRO_END \
- __pragma(warning(push)) \
- __pragma(warning(disable:4127)) \
- } while(false) \
- __pragma(warning(pop))
-#else
-#define NV_MULTI_LINE_MACRO_BEGIN do {
-#define NV_MULTI_LINE_MACRO_END } while(false)
-#endif
-
-#if NV_CC_CPP11
-#define nvStaticCheck(x) static_assert((x), "Static assert "#x" failed")
-#else
-#define nvStaticCheck(x) typedef char NV_STRING_JOIN2(__static_assert_,__LINE__)[(x)]
-#endif
-#define NV_COMPILER_CHECK(x) nvStaticCheck(x) // I like this name best.
-
-// Make sure type definitions are fine.
-NV_COMPILER_CHECK(sizeof(int8) == 1);
-NV_COMPILER_CHECK(sizeof(uint8) == 1);
-NV_COMPILER_CHECK(sizeof(int16) == 2);
-NV_COMPILER_CHECK(sizeof(uint16) == 2);
-NV_COMPILER_CHECK(sizeof(int32) == 4);
-NV_COMPILER_CHECK(sizeof(uint32) == 4);
-NV_COMPILER_CHECK(sizeof(int32) == 4);
-NV_COMPILER_CHECK(sizeof(uint32) == 4);
-
-#include <stddef.h> // for size_t
-template <typename T, size_t N> char (&ArraySizeHelper(T (&array)[N]))[N];
-#define NV_ARRAY_SIZE(x) sizeof(ArraySizeHelper(x))
-//#define NV_ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
-
-#if 0 // Disabled in The Witness.
-#if NV_CC_MSVC
-#define NV_MESSAGE(x) message(__FILE__ "(" NV_STRING(__LINE__) ") : " x)
-#else
-#define NV_MESSAGE(x) message(x)
-#endif
-#else
-#define NV_MESSAGE(x)
-#endif
-
-
-// Startup initialization macro.
-#define NV_AT_STARTUP(some_code) \
- namespace { \
- static struct NV_STRING_JOIN2(AtStartup_, __LINE__) { \
- NV_STRING_JOIN2(AtStartup_, __LINE__)() { some_code; } \
- } \
- NV_STRING_JOIN3(AtStartup_, __LINE__, Instance); \
- }
-
-// Indicate the compiler that the parameter is not used to suppress compier warnings.
-#if NV_CC_MSVC
-#define NV_UNUSED(a) ((a)=(a))
-#else
-#define NV_UNUSED(a) _Pragma(NV_STRING(unused(a)))
-#endif
-
-// Null index. @@ Move this somewhere else... it's only used by nvmesh.
-//const unsigned int NIL = unsigned int(~0);
-#define NIL uint(~0)
-
-// Null pointer.
-#ifndef NULL
-#define NULL 0
-#endif
-
-// Platform includes
-#if NV_CC_MSVC
-# if NV_OS_WIN32
-# include "DefsVcWin32.h"
-# elif NV_OS_XBOX
-# include "DefsVcXBox.h"
-# elif NV_OS_DURANGO
-# include "DefsVcDurango.h"
-# else
-# error "MSVC: Platform not supported"
-# endif
-#elif NV_CC_GNUC
-# if NV_OS_LINUX
-# include "DefsGnucLinux.h"
-# elif NV_OS_DARWIN || NV_OS_FREEBSD || NV_OS_OPENBSD || NV_OS_HAIKU
-# include "DefsGnucDarwin.h"
-# elif NV_OS_ORBIS
-# include "DefsOrbis.h"
-# elif NV_OS_MINGW
-# include "DefsGnucWin32.h"
-# elif NV_OS_CYGWIN
-# error "GCC: Cygwin not supported"
-# else
-# error "GCC: Platform not supported"
-# endif
-#endif
-
-#endif // NV_CORE_H
diff --git a/thirdparty/thekla_atlas/nvcore/scanf.c b/thirdparty/thekla_atlas/nvcore/scanf.c
deleted file mode 100644
index bf9d293154..0000000000
--- a/thirdparty/thekla_atlas/nvcore/scanf.c
+++ /dev/null
@@ -1,641 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Chris Torek.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- * 4. 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 REGENTS 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 REGENTS 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.
- *
- * From: Id: vfscanf.c,v 1.13 1998/09/25 12:20:27 obrien Exp
- * From: static char sccsid[] = "@(#)strtol.c 8.1 (Berkeley) 6/4/93";
- * From: static char sccsid[] = "@(#)strtoul.c 8.1 (Berkeley) 6/4/93";
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <ctype.h>
-#include <string.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#pragma warning(disable : 4244) // conversion from '*' to '*', possible loss of data
-#pragma warning(disable : 4018) // signed/unsigned mismatch
-#pragma warning(disable : 4267) // '=' : conversion from 'size_t' to 'int', possible loss of data
-
-#define strtoq _strtoi64
-#define strtouq _strtoui64
-#define bcopy(b1,b2,len) (memmove((b2), (b1), (len)), (void) 0)
-
-typedef int long long quad_t;
-typedef unsigned long long u_quad_t;
-typedef unsigned char u_char;
-
-#define BUF 32 /* Maximum length of numeric string. */
-
-/*
- * Flags used during conversion.
- */
-#define LONG 0x01 /* l: long or double */
-#define SHORT 0x04 /* h: short */
-#define SUPPRESS 0x08 /* suppress assignment */
-#define POINTER 0x10 /* weird %p pointer (`fake hex') */
-#define NOSKIP 0x20 /* do not skip blanks */
-#define QUAD 0x400
-
-/*
- * The following are used in numeric conversions only:
- * SIGNOK, NDIGITS, DPTOK, and EXPOK are for floating point;
- * SIGNOK, NDIGITS, PFXOK, and NZDIGITS are for integral.
- */
-#define SIGNOK 0x40 /* +/- is (still) legal */
-#define NDIGITS 0x80 /* no digits detected */
-
-#define DPTOK 0x100 /* (float) decimal point is still legal */
-#define EXPOK 0x200 /* (float) exponent (e+3, etc) still legal */
-
-#define PFXOK 0x100 /* 0x prefix is (still) legal */
-#define NZDIGITS 0x200 /* no zero digits detected */
-
-/*
- * Conversion types.
- */
-#define CT_CHAR 0 /* %c conversion */
-#define CT_CCL 1 /* %[...] conversion */
-#define CT_STRING 2 /* %s conversion */
-#define CT_INT 3 /* integer, i.e., strtoq or strtouq */
-typedef u_quad_t (*ccfntype)(const char *, char **, int);
-
-static const u_char *__sccl(char *, const u_char *);
-
-int
-vsscanf(const char *inp, char const *fmt0, va_list ap)
-{
- int inr;
- const u_char *fmt = (const u_char *)fmt0;
- int c; /* character from format, or conversion */
- size_t width; /* field width, or 0 */
- char *p; /* points into all kinds of strings */
- int n; /* handy integer */
- int flags; /* flags as defined above */
- char *p0; /* saves original value of p when necessary */
- int nassigned; /* number of fields assigned */
- int nconversions; /* number of conversions */
- int nread; /* number of characters consumed from fp */
- int base; /* base argument to strtoq/strtouq */
- ccfntype ccfn; /* conversion function (strtoq/strtouq) */
- char ccltab[256]; /* character class table for %[...] */
- char buf[BUF]; /* buffer for numeric conversions */
-
- /* `basefix' is used to avoid `if' tests in the integer scanner */
- static short basefix[17] =
- { 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
-
- inr = strlen(inp);
-
- nassigned = 0;
- nconversions = 0;
- nread = 0;
- base = 0; /* XXX just to keep gcc happy */
- ccfn = NULL; /* XXX just to keep gcc happy */
- for (;;) {
- c = *fmt++;
- if (c == 0)
- return (nassigned);
- if (isspace(c)) {
- while (inr > 0 && isspace(*inp))
- nread++, inr--, inp++;
- continue;
- }
- if (c != '%')
- goto literal;
- width = 0;
- flags = 0;
- /*
- * switch on the format. continue if done;
- * break once format type is derived.
- */
-again: c = *fmt++;
- switch (c) {
- case '%':
-literal:
- if (inr <= 0)
- goto input_failure;
- if (*inp != c)
- goto match_failure;
- inr--, inp++;
- nread++;
- continue;
-
- case '*':
- flags |= SUPPRESS;
- goto again;
- case 'l':
- flags |= LONG;
- goto again;
- case 'q':
- flags |= QUAD;
- goto again;
- case 'h':
- flags |= SHORT;
- goto again;
-
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- width = width * 10 + c - '0';
- goto again;
-
- /*
- * Conversions.
- *
- */
- case 'd':
- c = CT_INT;
- ccfn = (ccfntype)strtoq;
- base = 10;
- break;
-
- case 'i':
- c = CT_INT;
- ccfn = (ccfntype)strtoq;
- base = 0;
- break;
-
- case 'o':
- c = CT_INT;
- ccfn = strtouq;
- base = 8;
- break;
-
- case 'u':
- c = CT_INT;
- ccfn = strtouq;
- base = 10;
- break;
-
- case 'x':
- flags |= PFXOK; /* enable 0x prefixing */
- c = CT_INT;
- ccfn = strtouq;
- base = 16;
- break;
-
- case 's':
- c = CT_STRING;
- break;
-
- case '[':
- fmt = __sccl(ccltab, fmt);
- flags |= NOSKIP;
- c = CT_CCL;
- break;
-
- case 'c':
- flags |= NOSKIP;
- c = CT_CHAR;
- break;
-
- case 'p': /* pointer format is like hex */
- flags |= POINTER | PFXOK;
- c = CT_INT;
- ccfn = strtouq;
- base = 16;
- break;
-
- case 'n':
- nconversions++;
- if (flags & SUPPRESS) /* ??? */
- continue;
- if (flags & SHORT)
- *va_arg(ap, short *) = nread;
- else if (flags & LONG)
- *va_arg(ap, long *) = nread;
- else if (flags & QUAD)
- *va_arg(ap, quad_t *) = nread;
- else
- *va_arg(ap, int *) = nread;
- continue;
- }
-
- /*
- * We have a conversion that requires input.
- */
- if (inr <= 0)
- goto input_failure;
-
- /*
- * Consume leading white space, except for formats
- * that suppress this.
- */
- if ((flags & NOSKIP) == 0) {
- while (isspace(*inp)) {
- nread++;
- if (--inr > 0)
- inp++;
- else
- goto input_failure;
- }
- /*
- * Note that there is at least one character in
- * the buffer, so conversions that do not set NOSKIP
- * can no longer result in an input failure.
- */
- }
-
- /*
- * Do the conversion.
- */
- switch (c) {
-
- case CT_CHAR:
- /* scan arbitrary characters (sets NOSKIP) */
- if (width == 0)
- width = 1;
- if (flags & SUPPRESS) {
- size_t sum = 0;
- for (;;) {
- if ((n = inr) < width) {
- sum += n;
- width -= n;
- inp += n;
- if (sum == 0)
- goto input_failure;
- break;
- } else {
- sum += width;
- inr -= width;
- inp += width;
- break;
- }
- }
- nread += sum;
- } else {
- bcopy(inp, va_arg(ap, char *), width);
- inr -= width;
- inp += width;
- nread += width;
- nassigned++;
- }
- nconversions++;
- break;
-
- case CT_CCL:
- /* scan a (nonempty) character class (sets NOSKIP) */
- if (width == 0)
- width = (size_t)~0; /* `infinity' */
- /* take only those things in the class */
- if (flags & SUPPRESS) {
- n = 0;
- while (ccltab[(unsigned char)*inp]) {
- n++, inr--, inp++;
- if (--width == 0)
- break;
- if (inr <= 0) {
- if (n == 0)
- goto input_failure;
- break;
- }
- }
- if (n == 0)
- goto match_failure;
- } else {
- p0 = p = va_arg(ap, char *);
- while (ccltab[(unsigned char)*inp]) {
- inr--;
- *p++ = *inp++;
- if (--width == 0)
- break;
- if (inr <= 0) {
- if (p == p0)
- goto input_failure;
- break;
- }
- }
- n = p - p0;
- if (n == 0)
- goto match_failure;
- *p = 0;
- nassigned++;
- }
- nread += n;
- nconversions++;
- break;
-
- case CT_STRING:
- /* like CCL, but zero-length string OK, & no NOSKIP */
- if (width == 0)
- width = (size_t)~0;
- if (flags & SUPPRESS) {
- n = 0;
- while (!isspace(*inp)) {
- n++, inr--, inp++;
- if (--width == 0)
- break;
- if (inr <= 0)
- break;
- }
- nread += n;
- } else {
- p0 = p = va_arg(ap, char *);
- while (!isspace(*inp)) {
- inr--;
- *p++ = *inp++;
- if (--width == 0)
- break;
- if (inr <= 0)
- break;
- }
- *p = 0;
- nread += p - p0;
- nassigned++;
- }
- nconversions++;
- continue;
-
- case CT_INT:
- /* scan an integer as if by strtoq/strtouq */
-#ifdef hardway
- if (width == 0 || width > sizeof(buf) - 1)
- width = sizeof(buf) - 1;
-#else
- /* size_t is unsigned, hence this optimisation */
- if (--width > sizeof(buf) - 2)
- width = sizeof(buf) - 2;
- width++;
-#endif
- flags |= SIGNOK | NDIGITS | NZDIGITS;
- for (p = buf; width; width--) {
- c = *inp;
- /*
- * Switch on the character; `goto ok'
- * if we accept it as a part of number.
- */
- switch (c) {
-
- /*
- * The digit 0 is always legal, but is
- * special. For %i conversions, if no
- * digits (zero or nonzero) have been
- * scanned (only signs), we will have
- * base==0. In that case, we should set
- * it to 8 and enable 0x prefixing.
- * Also, if we have not scanned zero digits
- * before this, do not turn off prefixing
- * (someone else will turn it off if we
- * have scanned any nonzero digits).
- */
- case '0':
- if (base == 0) {
- base = 8;
- flags |= PFXOK;
- }
- if (flags & NZDIGITS)
- flags &= ~(SIGNOK|NZDIGITS|NDIGITS);
- else
- flags &= ~(SIGNOK|PFXOK|NDIGITS);
- goto ok;
-
- /* 1 through 7 always legal */
- case '1': case '2': case '3':
- case '4': case '5': case '6': case '7':
- base = basefix[base];
- flags &= ~(SIGNOK | PFXOK | NDIGITS);
- goto ok;
-
- /* digits 8 and 9 ok iff decimal or hex */
- case '8': case '9':
- base = basefix[base];
- if (base <= 8)
- break; /* not legal here */
- flags &= ~(SIGNOK | PFXOK | NDIGITS);
- goto ok;
-
- /* letters ok iff hex */
- case 'A': case 'B': case 'C':
- case 'D': case 'E': case 'F':
- case 'a': case 'b': case 'c':
- case 'd': case 'e': case 'f':
- /* no need to fix base here */
- if (base <= 10)
- break; /* not legal here */
- flags &= ~(SIGNOK | PFXOK | NDIGITS);
- goto ok;
-
- /* sign ok only as first character */
- case '+': case '-':
- if (flags & SIGNOK) {
- flags &= ~SIGNOK;
- goto ok;
- }
- break;
-
- /* x ok iff flag still set & 2nd char */
- case 'x': case 'X':
- if (flags & PFXOK && p == buf + 1) {
- base = 16; /* if %i */
- flags &= ~PFXOK;
- goto ok;
- }
- break;
- }
-
- /*
- * If we got here, c is not a legal character
- * for a number. Stop accumulating digits.
- */
- break;
- ok:
- /*
- * c is legal: store it and look at the next.
- */
- *p++ = c;
- if (--inr > 0)
- inp++;
- else
- break; /* end of input */
- }
- /*
- * If we had only a sign, it is no good; push
- * back the sign. If the number ends in `x',
- * it was [sign] '0' 'x', so push back the x
- * and treat it as [sign] '0'.
- */
- if (flags & NDIGITS) {
- if (p > buf) {
- inp--;
- inr++;
- }
- goto match_failure;
- }
- c = ((u_char *)p)[-1];
- if (c == 'x' || c == 'X') {
- --p;
- inp--;
- inr++;
- }
- if ((flags & SUPPRESS) == 0) {
- u_quad_t res;
-
- *p = 0;
- res = (*ccfn)(buf, (char **)NULL, base);
- if (flags & POINTER)
- *va_arg(ap, void **) =
- (void *)(uintptr_t)res;
- else if (flags & SHORT)
- *va_arg(ap, short *) = res;
- else if (flags & LONG)
- *va_arg(ap, long *) = res;
- else if (flags & QUAD)
- *va_arg(ap, quad_t *) = res;
- else
- *va_arg(ap, int *) = res;
- nassigned++;
- }
- nread += p - buf;
- nconversions++;
- break;
-
- }
- }
-input_failure:
- return (nconversions != 0 ? nassigned : -1);
-match_failure:
- return (nassigned);
-}
-
-
-/*
- * Fill in the given table from the scanset at the given format
- * (just after `['). Return a pointer to the character past the
- * closing `]'. The table has a 1 wherever characters should be
- * considered part of the scanset.
- */
-static const u_char *
-__sccl(char *tab, const u_char *fmt)
-{
- int c, n, v;
-
- /* first `clear' the whole table */
- c = *fmt++; /* first char hat => negated scanset */
- if (c == '^') {
- v = 1; /* default => accept */
- c = *fmt++; /* get new first char */
- } else
- v = 0; /* default => reject */
-
- /* XXX: Will not work if sizeof(tab*) > sizeof(char) */
- for (n = 0; n < 256; n++)
- tab[n] = v; /* memset(tab, v, 256) */
-
- if (c == 0)
- return (fmt - 1);/* format ended before closing ] */
-
- /*
- * Now set the entries corresponding to the actual scanset
- * to the opposite of the above.
- *
- * The first character may be ']' (or '-') without being special;
- * the last character may be '-'.
- */
- v = 1 - v;
- for (;;) {
- tab[c] = v; /* take character c */
-doswitch:
- n = *fmt++; /* and examine the next */
- switch (n) {
-
- case 0: /* format ended too soon */
- return (fmt - 1);
-
- case '-':
- /*
- * A scanset of the form
- * [01+-]
- * is defined as `the digit 0, the digit 1,
- * the character +, the character -', but
- * the effect of a scanset such as
- * [a-zA-Z0-9]
- * is implementation defined. The V7 Unix
- * scanf treats `a-z' as `the letters a through
- * z', but treats `a-a' as `the letter a, the
- * character -, and the letter a'.
- *
- * For compatibility, the `-' is not considerd
- * to define a range if the character following
- * it is either a close bracket (required by ANSI)
- * or is not numerically greater than the character
- * we just stored in the table (c).
- */
- n = *fmt;
- if (n == ']' || n < c) {
- c = '-';
- break; /* resume the for(;;) */
- }
- fmt++;
- /* fill in the range */
- do {
- tab[++c] = v;
- } while (c < n);
- c = n;
- /*
- * Alas, the V7 Unix scanf also treats formats
- * such as [a-c-e] as `the letters a through e'.
- * This too is permitted by the standard....
- */
- goto doswitch;
- break;
-
- case ']': /* end of scanset */
- return (fmt);
-
- default: /* just another character */
- c = n;
- break;
- }
- }
- /* NOTREACHED */
-}
-
-/*
-int
-sscanf(const char *ibuf, const char *fmt, ...)
-{
- va_list ap;
- int ret;
-
- va_start(ap, fmt);
- ret = vsscanf(ibuf, fmt, ap);
- va_end(ap);
-
- return(ret);
-}
-*/
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/thirdparty/thekla_atlas/nvimage/BitMap.cpp b/thirdparty/thekla_atlas/nvimage/BitMap.cpp
deleted file mode 100644
index 8cc49644ea..0000000000
--- a/thirdparty/thekla_atlas/nvimage/BitMap.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-// This code is in the public domain -- castanyo@yahoo.es
-
-#include "BitMap.h"
-
-using namespace nv;
-
-void BitMap::resize(uint w, uint h, bool initValue)
-{
- BitArray tmp(w*h);
-
- if (initValue) tmp.setAll();
- else tmp.clearAll();
-
- // @@ Copying one bit at a time. This could be much faster.
- for (uint y = 0; y < m_height; y++)
- {
- for (uint x = 0; x < m_width; x++)
- {
- //tmp.setBitAt(y*w + x, bitAt(x, y));
- if (bitAt(x, y) != initValue) tmp.toggleBitAt(y*w + x);
- }
- }
-
- swap(m_bitArray, tmp);
- m_width = w;
- m_height = h;
-}
diff --git a/thirdparty/thekla_atlas/nvimage/BitMap.h b/thirdparty/thekla_atlas/nvimage/BitMap.h
deleted file mode 100644
index a285321176..0000000000
--- a/thirdparty/thekla_atlas/nvimage/BitMap.h
+++ /dev/null
@@ -1,87 +0,0 @@
-// This code is in the public domain -- castanyo@yahoo.es
-
-#pragma once
-#ifndef NV_IMAGE_BITMAP_H
-#define NV_IMAGE_BITMAP_H
-
-#include "nvimage.h"
-
-#include "nvcore/BitArray.h"
-
-namespace nv
-{
- /// Bit map. This should probably be called BitImage.
- class NVIMAGE_CLASS BitMap
- {
- public:
- BitMap() : m_width(0), m_height(0) {}
- BitMap(uint w, uint h) : m_width(w), m_height(h), m_bitArray(w*h) {}
-
- uint width() const { return m_width; }
- uint height() const { return m_height; }
-
- void resize(uint w, uint h, bool initValue);
-
- bool bitAt(uint x, uint y) const
- {
- nvDebugCheck(x < m_width && y < m_height);
- return m_bitArray.bitAt(y * m_width + x);
- }
- bool bitAt(uint idx) const
- {
- return m_bitArray.bitAt(idx);
- }
-
- void setBitAt(uint x, uint y)
- {
- nvDebugCheck(x < m_width && y < m_height);
- m_bitArray.setBitAt(y * m_width + x);
- }
- void setBitAt(uint idx)
- {
- m_bitArray.setBitAt(idx);
- }
-
- void clearBitAt(uint x, uint y)
- {
- nvDebugCheck(x < m_width && y < m_height);
- m_bitArray.clearBitAt(y * m_width + x);
- }
- void clearBitAt(uint idx)
- {
- m_bitArray.clearBitAt(idx);
- }
-
- void clearAll()
- {
- m_bitArray.clearAll();
- }
-
- void setAll()
- {
- m_bitArray.setAll();
- }
-
- void toggleAll()
- {
- m_bitArray.toggleAll();
- }
-
- friend void swap(BitMap & a, BitMap & b)
- {
- nvCheck(a.m_width == b.m_width);
- nvCheck(a.m_height == b.m_height);
- swap(a.m_bitArray, b.m_bitArray);
- }
-
- private:
-
- uint m_width;
- uint m_height;
- BitArray m_bitArray;
-
- };
-
-} // nv namespace
-
-#endif // NV_IMAGE_BITMAP_H
diff --git a/thirdparty/thekla_atlas/nvimage/Image.cpp b/thirdparty/thekla_atlas/nvimage/Image.cpp
deleted file mode 100644
index 8c0cbcf4e3..0000000000
--- a/thirdparty/thekla_atlas/nvimage/Image.cpp
+++ /dev/null
@@ -1,210 +0,0 @@
-// This code is in the public domain -- castanyo@yahoo.es
-
-#include "Image.h"
-//#include "ImageIO.h"
-
-#include "nvmath/Color.h"
-
-#include "nvcore/Debug.h"
-#include "nvcore/Ptr.h"
-#include "nvcore/Utils.h" // swap
-#include "nvcore/Memory.h" // realloc, free
-
-#include <string.h> // memcpy
-
-
-using namespace nv;
-
-Image::Image() : m_width(0), m_height(0), m_format(Format_RGB), m_data(NULL)
-{
-}
-
-Image::Image(const Image & img) : m_data(NULL)
-{
- allocate(img.m_width, img.m_height, img.m_depth);
- m_format = img.m_format;
- memcpy(m_data, img.m_data, sizeof(Color32) * m_width * m_height * m_depth);
-}
-
-Image::~Image()
-{
- free();
-}
-
-const Image & Image::operator=(const Image & img)
-{
- allocate(img.m_width, img.m_height, m_depth);
- m_format = img.m_format;
- memcpy(m_data, img.m_data, sizeof(Color32) * m_width * m_height * m_depth);
- return *this;
-}
-
-
-void Image::allocate(uint w, uint h, uint d/*= 1*/)
-{
- m_width = w;
- m_height = h;
- m_depth = d;
- m_data = realloc<Color32>(m_data, w * h * d);
-}
-
-void Image::acquire(Color32 * data, uint w, uint h, uint d/*= 1*/)
-{
- free();
- m_width = w;
- m_height = h;
- m_depth = d;
- m_data = data;
-}
-
-void Image::resize(uint w, uint h, uint d/*= 1*/) {
-
- Image img;
- img.allocate(w, h, d);
-
- Color32 background(0,0,0,0);
-
- // Copy image.
- uint x, y, z;
- for(z = 0; z < min(d, m_depth); z++) {
- for(y = 0; y < min(h, m_height); y++) {
- for(x = 0; x < min(w, m_width); x++) {
- img.pixel(x, y, z) = pixel(x, y, z);
- }
- for(; x < w; x++) {
- img.pixel(x, y, z) = background;
- }
- }
- for(; y < h; y++) {
- for(x = 0; x < w; x++) {
- img.pixel(x, y, z) = background;
- }
- }
- }
- for(; z < d; z++) {
- for(y = 0; y < h; y++) {
- for(x = 0; x < w; x++) {
- img.pixel(x, y, z) = background;
- }
- }
- }
-
- swap(m_width, img.m_width);
- swap(m_height, img.m_height);
- swap(m_depth, img.m_depth);
- swap(m_format, img.m_format);
- swap(m_data, img.m_data);
-}
-
-/*bool Image::load(const char * name)
-{
- free();
-
- AutoPtr<Image> img(ImageIO::load(name));
- if (img == NULL) {
- return false;
- }
-
- swap(m_width, img->m_width);
- swap(m_height, img->m_height);
- swap(m_depth, img->m_depth);
- swap(m_format, img->m_format);
- swap(m_data, img->m_data);
-
- return true;
-}*/
-
-void Image::wrap(void * data, uint w, uint h, uint d)
-{
- free();
- m_data = (Color32 *)data;
- m_width = w;
- m_height = h;
- m_depth = d;
-}
-
-void Image::unwrap()
-{
- m_data = NULL;
- m_width = 0;
- m_height = 0;
- m_depth = 0;
-}
-
-
-void Image::free()
-{
- ::free(m_data);
- m_data = NULL;
-}
-
-
-uint Image::width() const
-{
- return m_width;
-}
-
-uint Image::height() const
-{
- return m_height;
-}
-
-uint Image::depth() const
-{
- return m_depth;
-}
-
-const Color32 * Image::scanline(uint h) const
-{
- nvDebugCheck(h < m_height);
- return m_data + h * m_width;
-}
-
-Color32 * Image::scanline(uint h)
-{
- nvDebugCheck(h < m_height);
- return m_data + h * m_width;
-}
-
-const Color32 * Image::pixels() const
-{
- return m_data;
-}
-
-Color32 * Image::pixels()
-{
- return m_data;
-}
-
-const Color32 & Image::pixel(uint idx) const
-{
- nvDebugCheck(idx < m_width * m_height * m_depth);
- return m_data[idx];
-}
-
-Color32 & Image::pixel(uint idx)
-{
- nvDebugCheck(idx < m_width * m_height * m_depth);
- return m_data[idx];
-}
-
-
-Image::Format Image::format() const
-{
- return m_format;
-}
-
-void Image::setFormat(Image::Format f)
-{
- m_format = f;
-}
-
-void Image::fill(Color32 c)
-{
- const uint size = m_width * m_height * m_depth;
- for (uint i = 0; i < size; ++i)
- {
- m_data[i] = c;
- }
-}
-
diff --git a/thirdparty/thekla_atlas/nvimage/Image.h b/thirdparty/thekla_atlas/nvimage/Image.h
deleted file mode 100644
index 4c5748cb00..0000000000
--- a/thirdparty/thekla_atlas/nvimage/Image.h
+++ /dev/null
@@ -1,89 +0,0 @@
-// This code is in the public domain -- castanyo@yahoo.es
-
-#pragma once
-#ifndef NV_IMAGE_IMAGE_H
-#define NV_IMAGE_IMAGE_H
-
-#include "nvimage.h"
-#include "nvcore/Debug.h"
-
-namespace nv
-{
- class Color32;
-
- /// 32 bit RGBA image.
- class NVIMAGE_CLASS Image
- {
- public:
-
- enum Format
- {
- Format_RGB,
- Format_ARGB,
- };
-
- Image();
- Image(const Image & img);
- ~Image();
-
- const Image & operator=(const Image & img);
-
-
- void allocate(uint w, uint h, uint d = 1);
- void acquire(Color32 * data, uint w, uint h, uint d = 1);
- //bool load(const char * name);
-
- void resize(uint w, uint h, uint d = 1);
-
- void wrap(void * data, uint w, uint h, uint d = 1);
- void unwrap();
-
- uint width() const;
- uint height() const;
- uint depth() const;
-
- const Color32 * scanline(uint h) const;
- Color32 * scanline(uint h);
-
- const Color32 * pixels() const;
- Color32 * pixels();
-
- const Color32 & pixel(uint idx) const;
- Color32 & pixel(uint idx);
-
- const Color32 & pixel(uint x, uint y, uint z = 0) const;
- Color32 & pixel(uint x, uint y, uint z = 0);
-
- Format format() const;
- void setFormat(Format f);
-
- void fill(Color32 c);
-
- private:
- void free();
-
- private:
- uint m_width;
- uint m_height;
- uint m_depth;
- Format m_format;
- Color32 * m_data;
- };
-
-
- inline const Color32 & Image::pixel(uint x, uint y, uint z) const
- {
- nvDebugCheck(x < m_width && y < m_height && z < m_depth);
- return pixel((z * m_height + y) * m_width + x);
- }
-
- inline Color32 & Image::pixel(uint x, uint y, uint z)
- {
- nvDebugCheck(x < m_width && y < m_height && z < m_depth);
- return pixel((z * m_height + y) * m_width + x);
- }
-
-} // nv namespace
-
-
-#endif // NV_IMAGE_IMAGE_H
diff --git a/thirdparty/thekla_atlas/nvimage/nvimage.h b/thirdparty/thekla_atlas/nvimage/nvimage.h
deleted file mode 100644
index 5c89bd4726..0000000000
--- a/thirdparty/thekla_atlas/nvimage/nvimage.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// This code is in the public domain -- castanyo@yahoo.es
-
-#pragma once
-#ifndef NV_IMAGE_H
-#define NV_IMAGE_H
-
-#include "nvcore/nvcore.h"
-#include "nvcore/Debug.h" // nvDebugCheck
-#include "nvcore/Utils.h" // isPowerOfTwo
-
-// Function linkage
-#if NVIMAGE_SHARED
-#ifdef NVIMAGE_EXPORTS
-#define NVIMAGE_API DLL_EXPORT
-#define NVIMAGE_CLASS DLL_EXPORT_CLASS
-#else
-#define NVIMAGE_API DLL_IMPORT
-#define NVIMAGE_CLASS DLL_IMPORT
-#endif
-#else
-#define NVIMAGE_API
-#define NVIMAGE_CLASS
-#endif
-
-
-namespace nv {
-
- // Some utility functions:
-
- inline uint computeBitPitch(uint w, uint bitsize, uint alignmentInBits)
- {
- nvDebugCheck(isPowerOfTwo(alignmentInBits));
-
- return ((w * bitsize + alignmentInBits - 1) / alignmentInBits) * alignmentInBits;
- }
-
- inline uint computeBytePitch(uint w, uint bitsize, uint alignmentInBytes)
- {
- uint pitch = computeBitPitch(w, bitsize, 8*alignmentInBytes);
- nvDebugCheck((pitch & 7) == 0);
-
- return (pitch + 7) / 8;
- }
-
-
-} // nv namespace
-
-#endif // NV_IMAGE_H
diff --git a/thirdparty/thekla_atlas/nvmath/Basis.cpp b/thirdparty/thekla_atlas/nvmath/Basis.cpp
deleted file mode 100644
index 0824179633..0000000000
--- a/thirdparty/thekla_atlas/nvmath/Basis.cpp
+++ /dev/null
@@ -1,270 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#include "Basis.h"
-
-using namespace nv;
-
-
-/// Normalize basis vectors.
-void Basis::normalize(float epsilon /*= NV_EPSILON*/)
-{
- normal = ::normalizeSafe(normal, Vector3(0.0f), epsilon);
- tangent = ::normalizeSafe(tangent, Vector3(0.0f), epsilon);
- bitangent = ::normalizeSafe(bitangent, Vector3(0.0f), epsilon);
-}
-
-
-/// Gram-Schmidt orthogonalization.
-/// @note Works only if the vectors are close to orthogonal.
-void Basis::orthonormalize(float epsilon /*= NV_EPSILON*/)
-{
- // N' = |N|
- // T' = |T - (N' dot T) N'|
- // B' = |B - (N' dot B) N' - (T' dot B) T'|
-
- normal = ::normalize(normal, epsilon);
-
- tangent -= normal * dot(normal, tangent);
- tangent = ::normalize(tangent, epsilon);
-
- bitangent -= normal * dot(normal, bitangent);
- bitangent -= tangent * dot(tangent, bitangent);
- bitangent = ::normalize(bitangent, epsilon);
-}
-
-
-
-
-/// Robust orthonormalization.
-/// Returns an orthonormal basis even when the original is degenerate.
-void Basis::robustOrthonormalize(float epsilon /*= NV_EPSILON*/)
-{
- // Normalize all vectors.
- normalize(epsilon);
-
- if (lengthSquared(normal) < epsilon*epsilon)
- {
- // Build normal from tangent and bitangent.
- normal = cross(tangent, bitangent);
-
- if (lengthSquared(normal) < epsilon*epsilon)
- {
- // Arbitrary basis.
- tangent = Vector3(1, 0, 0);
- bitangent = Vector3(0, 1, 0);
- normal = Vector3(0, 0, 1);
- return;
- }
-
- normal = nv::normalize(normal, epsilon);
- }
-
- // Project tangents to normal plane.
- tangent -= normal * dot(normal, tangent);
- bitangent -= normal * dot(normal, bitangent);
-
- if (lengthSquared(tangent) < epsilon*epsilon)
- {
- if (lengthSquared(bitangent) < epsilon*epsilon)
- {
- // Arbitrary basis.
- buildFrameForDirection(normal);
- }
- else
- {
- // Build tangent from bitangent.
- bitangent = nv::normalize(bitangent, epsilon);
-
- tangent = cross(bitangent, normal);
- nvDebugCheck(isNormalized(tangent, epsilon));
- }
- }
- else
- {
- tangent = nv::normalize(tangent, epsilon);
-#if 0
- bitangent -= tangent * dot(tangent, bitangent);
-
- if (lengthSquared(bitangent) < epsilon*epsilon)
- {
- bitangent = cross(tangent, normal);
- nvDebugCheck(isNormalized(bitangent, epsilon));
- }
- else
- {
- bitangent = nv::normalize(bitangent, epsilon);
- }
-#else
- if (lengthSquared(bitangent) < epsilon*epsilon)
- {
- // Build bitangent from tangent.
- bitangent = cross(tangent, normal);
- nvDebugCheck(isNormalized(bitangent, epsilon));
- }
- else
- {
- bitangent = nv::normalize(bitangent, epsilon);
-
- // At this point tangent and bitangent are orthogonal to normal, but we don't know whether their orientation.
-
- Vector3 bisector;
- if (lengthSquared(tangent + bitangent) < epsilon*epsilon)
- {
- bisector = tangent;
- }
- else
- {
- bisector = nv::normalize(tangent + bitangent);
- }
- Vector3 axis = nv::normalize(cross(bisector, normal));
-
- //nvDebugCheck(isNormalized(axis, epsilon));
- nvDebugCheck(equal(dot(axis, tangent), -dot(axis, bitangent), epsilon));
-
- if (dot(axis, tangent) > 0)
- {
- tangent = bisector + axis;
- bitangent = bisector - axis;
- }
- else
- {
- tangent = bisector - axis;
- bitangent = bisector + axis;
- }
-
- // Make sure the resulting tangents are still perpendicular to the normal.
- tangent -= normal * dot(normal, tangent);
- bitangent -= normal * dot(normal, bitangent);
-
- // Double check.
- nvDebugCheck(equal(dot(normal, tangent), 0.0f, epsilon));
- nvDebugCheck(equal(dot(normal, bitangent), 0.0f, epsilon));
-
- // Normalize.
- tangent = nv::normalize(tangent);
- bitangent = nv::normalize(bitangent);
-
- // If tangent and bitangent are not orthogonal, then derive bitangent from tangent, just in case...
- if (!equal(dot(tangent, bitangent), 0.0f, epsilon)) {
- bitangent = cross(tangent, normal);
- bitangent = nv::normalize(bitangent);
- }
- }
-#endif
- }
-
- /*// Check vector lengths.
- if (!isNormalized(normal, epsilon))
- {
- nvDebug("%f %f %f\n", normal.x, normal.y, normal.z);
- nvDebug("%f %f %f\n", tangent.x, tangent.y, tangent.z);
- nvDebug("%f %f %f\n", bitangent.x, bitangent.y, bitangent.z);
- }*/
-
- nvDebugCheck(isNormalized(normal, epsilon));
- nvDebugCheck(isNormalized(tangent, epsilon));
- nvDebugCheck(isNormalized(bitangent, epsilon));
-
- // Check vector angles.
- nvDebugCheck(equal(dot(normal, tangent), 0.0f, epsilon));
- nvDebugCheck(equal(dot(normal, bitangent), 0.0f, epsilon));
- nvDebugCheck(equal(dot(tangent, bitangent), 0.0f, epsilon));
-
- // Check vector orientation.
- const float det = dot(cross(normal, tangent), bitangent);
- nvDebugCheck(equal(det, 1.0f, epsilon) || equal(det, -1.0f, epsilon));
-}
-
-
-/// Build an arbitrary frame for the given direction.
-void Basis::buildFrameForDirection(Vector3::Arg d, float angle/*= 0*/)
-{
- nvCheck(isNormalized(d));
- normal = d;
-
- // Choose minimum axis.
- if (fabsf(normal.x) < fabsf(normal.y) && fabsf(normal.x) < fabsf(normal.z))
- {
- tangent = Vector3(1, 0, 0);
- }
- else if (fabsf(normal.y) < fabsf(normal.z))
- {
- tangent = Vector3(0, 1, 0);
- }
- else
- {
- tangent = Vector3(0, 0, 1);
- }
-
- // Ortogonalize
- tangent -= normal * dot(normal, tangent);
- tangent = ::normalize(tangent);
-
- bitangent = cross(normal, tangent);
-
- // Rotate frame around normal according to angle.
- if (angle != 0.0f) {
- float c = cosf(angle);
- float s = sinf(angle);
- Vector3 tmp = c * tangent - s * bitangent;
- bitangent = s * tangent + c * bitangent;
- tangent = tmp;
- }
-}
-
-bool Basis::isValid() const
-{
- if (equal(normal, Vector3(0.0f))) return false;
- if (equal(tangent, Vector3(0.0f))) return false;
- if (equal(bitangent, Vector3(0.0f))) return false;
-
- if (equal(determinant(), 0.0f)) return false;
-
- return true;
-}
-
-
-/// Transform by this basis. (From this basis to object space).
-Vector3 Basis::transform(Vector3::Arg v) const
-{
- Vector3 o = tangent * v.x;
- o += bitangent * v.y;
- o += normal * v.z;
- return o;
-}
-
-/// Transform by the transpose. (From object space to this basis).
-Vector3 Basis::transformT(Vector3::Arg v)
-{
- return Vector3(dot(tangent, v), dot(bitangent, v), dot(normal, v));
-}
-
-/// Transform by the inverse. (From object space to this basis).
-/// @note Uses Cramer's rule so the inverse is not accurate if the basis is ill-conditioned.
-Vector3 Basis::transformI(Vector3::Arg v) const
-{
- const float det = determinant();
- nvDebugCheck(!equal(det, 0.0f, 0.0f));
-
- const float idet = 1.0f / det;
-
- // Rows of the inverse matrix.
- Vector3 r0(
- (bitangent.y * normal.z - bitangent.z * normal.y),
- -(bitangent.x * normal.z - bitangent.z * normal.x),
- (bitangent.x * normal.y - bitangent.y * normal.x));
-
- Vector3 r1(
- -(tangent.y * normal.z - tangent.z * normal.y),
- (tangent.x * normal.z - tangent.z * normal.x),
- -(tangent.x * normal.y - tangent.y * normal.x));
-
- Vector3 r2(
- (tangent.y * bitangent.z - tangent.z * bitangent.y),
- -(tangent.x * bitangent.z - tangent.z * bitangent.x),
- (tangent.x * bitangent.y - tangent.y * bitangent.x));
-
- return Vector3(dot(v, r0), dot(v, r1), dot(v, r2)) * idet;
-}
-
-
diff --git a/thirdparty/thekla_atlas/nvmath/Basis.h b/thirdparty/thekla_atlas/nvmath/Basis.h
deleted file mode 100644
index e8146afdbe..0000000000
--- a/thirdparty/thekla_atlas/nvmath/Basis.h
+++ /dev/null
@@ -1,82 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#pragma once
-#ifndef NV_MATH_BASIS_H
-#define NV_MATH_BASIS_H
-
-#include "nvmath.h"
-#include "Vector.inl"
-#include "Matrix.h"
-
-namespace nv
-{
-
- /// Basis class to compute tangent space basis, ortogonalizations and to
- /// transform vectors from one space to another.
- class Basis
- {
- public:
-
- /// Create a null basis.
- Basis() : tangent(0, 0, 0), bitangent(0, 0, 0), normal(0, 0, 0) {}
-
- /// Create a basis given three vectors.
- Basis(Vector3::Arg n, Vector3::Arg t, Vector3::Arg b) : tangent(t), bitangent(b), normal(n) {}
-
- /// Create a basis with the given tangent vectors and the handness.
- Basis(Vector3::Arg n, Vector3::Arg t, float sign)
- {
- build(n, t, sign);
- }
-
- NVMATH_API void normalize(float epsilon = NV_EPSILON);
- NVMATH_API void orthonormalize(float epsilon = NV_EPSILON);
- NVMATH_API void robustOrthonormalize(float epsilon = NV_EPSILON);
- NVMATH_API void buildFrameForDirection(Vector3::Arg d, float angle = 0);
-
- /// Calculate the determinant [ F G N ] to obtain the handness of the basis.
- float handness() const
- {
- return determinant() > 0.0f ? 1.0f : -1.0f;
- }
-
- /// Build a basis from 2 vectors and a handness flag.
- void build(Vector3::Arg n, Vector3::Arg t, float sign)
- {
- normal = n;
- tangent = t;
- bitangent = sign * cross(t, n);
- }
-
- /// Compute the determinant of this basis.
- float determinant() const
- {
- return
- tangent.x * bitangent.y * normal.z - tangent.z * bitangent.y * normal.x +
- tangent.y * bitangent.z * normal.x - tangent.y * bitangent.x * normal.z +
- tangent.z * bitangent.x * normal.y - tangent.x * bitangent.z * normal.y;
- }
-
- bool isValid() const;
-
- // Get transform matrix for this basis.
- NVMATH_API Matrix matrix() const;
-
- // Transform by this basis. (From this basis to object space).
- NVMATH_API Vector3 transform(Vector3::Arg v) const;
-
- // Transform by the transpose. (From object space to this basis).
- NVMATH_API Vector3 transformT(Vector3::Arg v);
-
- // Transform by the inverse. (From object space to this basis).
- NVMATH_API Vector3 transformI(Vector3::Arg v) const;
-
-
- Vector3 tangent;
- Vector3 bitangent;
- Vector3 normal;
- };
-
-} // nv namespace
-
-#endif // NV_MATH_BASIS_H
diff --git a/thirdparty/thekla_atlas/nvmath/Box.cpp b/thirdparty/thekla_atlas/nvmath/Box.cpp
deleted file mode 100644
index 8f2014a077..0000000000
--- a/thirdparty/thekla_atlas/nvmath/Box.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-// This code is in the public domain -- castanyo@yahoo.es
-
-#include "Box.h"
-#include "Box.inl"
-#include "Sphere.h"
-
-using namespace nv;
-
-
-
-
-// Clip the given segment against this box.
-bool Box::clipSegment(const Vector3 & origin, const Vector3 & dir, float * t_near, float * t_far) const {
-
- // Avoid aliasing.
- float tnear = *t_near;
- float tfar = *t_far;
-
- // clip ray segment to box
- for (int i = 0; i < 3; i++)
- {
- const float pos = origin.component[i] + tfar * dir.component[i];
- const float dt = tfar - tnear;
-
- if (dir.component[i] < 0) {
-
- // clip end point
- if (pos < minCorner.component[i]) {
- tfar = tnear + dt * (origin.component[i] - minCorner.component[i]) / (origin.component[i] - pos);
- }
-
- // clip start point
- if (origin.component[i] > maxCorner.component[i]) {
- tnear = tnear + dt * (origin.component[i] - maxCorner.component[i]) / (tfar * dir.component[i]);
- }
- }
- else {
-
- // clip end point
- if (pos > maxCorner.component[i]) {
- tfar = tnear + dt * (maxCorner.component[i] - origin.component[i]) / (pos - origin.component[i]);
- }
-
- // clip start point
- if (origin.component[i] < minCorner.component[i]) {
- tnear = tnear + dt * (minCorner.component[i] - origin.component[i]) / (tfar * dir.component[i]);
- }
- }
-
- if (tnear > tfar) {
- // Clipped away.
- return false;
- }
- }
-
- // Return result.
- *t_near = tnear;
- *t_far = tfar;
- return true;
-}
-
-
-float nv::distanceSquared(const Box &box, const Vector3 &point) {
- Vector3 closest;
-
- if (point.x < box.minCorner.x) closest.x = box.minCorner.x;
- else if (point.x > box.maxCorner.x) closest.x = box.maxCorner.x;
- else closest.x = point.x;
-
- if (point.y < box.minCorner.y) closest.y = box.minCorner.y;
- else if (point.y > box.maxCorner.y) closest.y = box.maxCorner.y;
- else closest.y = point.y;
-
- if (point.z < box.minCorner.z) closest.z = box.minCorner.z;
- else if (point.z > box.maxCorner.z) closest.z = box.maxCorner.z;
- else closest.z = point.z;
-
- return lengthSquared(point - closest);
-}
-
-bool nv::overlap(const Box &box, const Sphere &sphere) {
- return distanceSquared(box, sphere.center) < sphere.radius * sphere.radius;
-}
-
-
-bool nv::intersect(const Box & box, const Vector3 & p, const Vector3 & id, float * t /*= NULL*/) {
- // Precompute these in ray structure?
- int sdx = (id.x < 0);
- int sdy = (id.y < 0);
- int sdz = (id.z < 0);
-
- float tmin = (box.corner( sdx).x - p.x) * id.x;
- float tmax = (box.corner(1-sdx).x - p.x) * id.x;
- float tymin = (box.corner( sdy).y - p.y) * id.y;
- float tymax = (box.corner(1-sdy).y - p.y) * id.y;
-
- if ((tmin > tymax) || (tymin > tmax))
- return false;
-
- if (tymin > tmin) tmin = tymin;
- if (tymax < tmax) tmax = tymax;
-
- float tzmin = (box.corner( sdz).z - p.z) * id.z;
- float tzmax = (box.corner(1-sdz).z - p.z) * id.z;
-
- if ((tmin > tzmax) || (tzmin > tmax))
- return false;
-
- if (tzmin > tmin) tmin = tzmin;
- if (tzmax < tmax) tmax = tzmax;
-
- if (tmax < 0)
- return false;
-
- if (t != NULL) *t = tmin;
-
- return true;
-}
-
diff --git a/thirdparty/thekla_atlas/nvmath/Box.h b/thirdparty/thekla_atlas/nvmath/Box.h
deleted file mode 100644
index 19b5f2a3a5..0000000000
--- a/thirdparty/thekla_atlas/nvmath/Box.h
+++ /dev/null
@@ -1,103 +0,0 @@
-// This code is in the public domain -- castanyo@yahoo.es
-
-#pragma once
-#ifndef NV_MATH_BOX_H
-#define NV_MATH_BOX_H
-
-#include "Vector.h"
-
-#include <float.h> // FLT_MAX
-
-namespace nv
-{
- class Vector;
- class Stream;
- class Sphere;
-
- // Axis Aligned Bounding Box.
- class Box
- {
- public:
-
- inline Box() {}
- inline Box(const Box & b) : minCorner(b.minCorner), maxCorner(b.maxCorner) {}
- inline Box(const Vector3 & mins, const Vector3 & maxs) : minCorner(mins), maxCorner(maxs) {}
-
- Box & operator=(const Box & b);
-
- operator const float * () const { return reinterpret_cast<const float *>(this); }
-
- // Clear the bounds.
- void clearBounds();
-
- // min < max
- bool isValid() const;
-
- // Build a cube centered on center and with edge = 2*dist
- void cube(const Vector3 & center, float dist);
-
- // Build a box, given center and extents.
- void setCenterExtents(const Vector3 & center, const Vector3 & extents);
-
- // Get box center.
- Vector3 center() const;
-
- // Return extents of the box.
- Vector3 extents() const;
-
- // Return extents of the box.
- float extents(uint axis) const;
-
- // Add a point to this box.
- void addPointToBounds(const Vector3 & p);
-
- // Add a box to this box.
- void addBoxToBounds(const Box & b);
-
- // Add sphere to this box.
- void addSphereToBounds(const Vector3 & p, float r);
-
- // Translate box.
- void translate(const Vector3 & v);
-
- // Scale the box.
- void scale(float s);
-
- // Expand the box by a fixed amount.
- void expand(float r);
-
- // Get the area of the box.
- float area() const;
-
- // Get the volume of the box.
- float volume() const;
-
- // Return true if the box contains the given point.
- bool contains(const Vector3 & p) const;
-
- // Split the given box in 8 octants and assign the ith one to this box.
- void setOctant(const Box & box, const Vector3 & center, int i);
-
-
- // Clip the given segment against this box.
- bool clipSegment(const Vector3 & origin, const Vector3 & dir, float * t_near, float * t_far) const;
-
-
- friend Stream & operator<< (Stream & s, Box & box);
-
- const Vector3 & corner(int i) const { return (&minCorner)[i]; }
-
- Vector3 minCorner;
- Vector3 maxCorner;
- };
-
- float distanceSquared(const Box &box, const Vector3 &point);
- bool overlap(const Box &box, const Sphere &sphere);
-
- // p is ray origin, id is inverse ray direction.
- bool intersect(const Box & box, const Vector3 & p, const Vector3 & id, float * t);
-
-} // nv namespace
-
-
-#endif // NV_MATH_BOX_H
diff --git a/thirdparty/thekla_atlas/nvmath/Box.inl b/thirdparty/thekla_atlas/nvmath/Box.inl
deleted file mode 100644
index dcfa70ff96..0000000000
--- a/thirdparty/thekla_atlas/nvmath/Box.inl
+++ /dev/null
@@ -1,154 +0,0 @@
-// This code is in the public domain -- castanyo@yahoo.es
-
-#pragma once
-#ifndef NV_MATH_BOX_INL
-#define NV_MATH_BOX_INL
-
-#include "Box.h"
-#include "Vector.inl"
-
-#include <float.h> // FLT_MAX
-
-namespace nv
-{
- // Default ctor.
- //inline Box::Box() { };
-
- // Copy ctor.
- //inline Box::Box(const Box & b) : minCorner(b.minCorner), maxCorner(b.maxCorner) { }
-
- // Init ctor.
- //inline Box::Box(const Vector3 & mins, const Vector3 & maxs) : minCorner(mins), maxCorner(maxs) { }
-
- // Assignment operator.
- inline Box & Box::operator=(const Box & b) { minCorner = b.minCorner; maxCorner = b.maxCorner; return *this; }
-
- // Clear the bounds.
- inline void Box::clearBounds()
- {
- minCorner.set(FLT_MAX, FLT_MAX, FLT_MAX);
- maxCorner.set(-FLT_MAX, -FLT_MAX, -FLT_MAX);
- }
-
- // min < max
- inline bool Box::isValid() const
- {
- return minCorner.x <= maxCorner.x && minCorner.y <= maxCorner.y && minCorner.z <= maxCorner.z;
- }
-
- // Build a cube centered on center and with edge = 2*dist
- inline void Box::cube(const Vector3 & center, float dist)
- {
- setCenterExtents(center, Vector3(dist));
- }
-
- // Build a box, given center and extents.
- inline void Box::setCenterExtents(const Vector3 & center, const Vector3 & extents)
- {
- minCorner = center - extents;
- maxCorner = center + extents;
- }
-
- // Get box center.
- inline Vector3 Box::center() const
- {
- return (minCorner + maxCorner) * 0.5f;
- }
-
- // Return extents of the box.
- inline Vector3 Box::extents() const
- {
- return (maxCorner - minCorner) * 0.5f;
- }
-
- // Return extents of the box.
- inline float Box::extents(uint axis) const
- {
- nvDebugCheck(axis < 3);
- if (axis == 0) return (maxCorner.x - minCorner.x) * 0.5f;
- if (axis == 1) return (maxCorner.y - minCorner.y) * 0.5f;
- if (axis == 2) return (maxCorner.z - minCorner.z) * 0.5f;
- nvUnreachable();
- return 0.0f;
- }
-
- // Add a point to this box.
- inline void Box::addPointToBounds(const Vector3 & p)
- {
- minCorner = min(minCorner, p);
- maxCorner = max(maxCorner, p);
- }
-
- // Add a box to this box.
- inline void Box::addBoxToBounds(const Box & b)
- {
- minCorner = min(minCorner, b.minCorner);
- maxCorner = max(maxCorner, b.maxCorner);
- }
-
- // Add sphere to this box.
- inline void Box::addSphereToBounds(const Vector3 & p, float r) {
- minCorner = min(minCorner, p - Vector3(r));
- maxCorner = min(maxCorner, p + Vector3(r));
- }
-
- // Translate box.
- inline void Box::translate(const Vector3 & v)
- {
- minCorner += v;
- maxCorner += v;
- }
-
- // Scale the box.
- inline void Box::scale(float s)
- {
- minCorner *= s;
- maxCorner *= s;
- }
-
- // Expand the box by a fixed amount.
- inline void Box::expand(float r) {
- minCorner -= Vector3(r,r,r);
- maxCorner += Vector3(r,r,r);
- }
-
- // Get the area of the box.
- inline float Box::area() const
- {
- const Vector3 d = extents();
- return 8.0f * (d.x*d.y + d.x*d.z + d.y*d.z);
- }
-
- // Get the volume of the box.
- inline float Box::volume() const
- {
- Vector3 d = extents();
- return 8.0f * (d.x * d.y * d.z);
- }
-
- // Return true if the box contains the given point.
- inline bool Box::contains(const Vector3 & p) const
- {
- return
- minCorner.x < p.x && minCorner.y < p.y && minCorner.z < p.z &&
- maxCorner.x > p.x && maxCorner.y > p.y && maxCorner.z > p.z;
- }
-
- // Split the given box in 8 octants and assign the ith one to this box.
- inline void Box::setOctant(const Box & box, const Vector3 & center, int i)
- {
- minCorner = box.minCorner;
- maxCorner = box.maxCorner;
-
- if (i & 4) minCorner.x = center.x;
- else maxCorner.x = center.x;
- if (i & 2) minCorner.y = center.y;
- else maxCorner.y = center.y;
- if (i & 1) minCorner.z = center.z;
- else maxCorner.z = center.z;
- }
-
-} // nv namespace
-
-
-#endif // NV_MATH_BOX_INL
diff --git a/thirdparty/thekla_atlas/nvmath/Color.h b/thirdparty/thekla_atlas/nvmath/Color.h
deleted file mode 100644
index 5cdc374bd9..0000000000
--- a/thirdparty/thekla_atlas/nvmath/Color.h
+++ /dev/null
@@ -1,150 +0,0 @@
-// This code is in the public domain -- castanyo@yahoo.es
-
-#pragma once
-#ifndef NV_MATH_COLOR_H
-#define NV_MATH_COLOR_H
-
-#include "nvmath.h"
-
-namespace nv
-{
-
- /// 64 bit color stored as BGRA.
- class NVMATH_CLASS Color64
- {
- public:
- Color64() { }
- Color64(const Color64 & c) : u(c.u) { }
- Color64(uint16 R, uint16 G, uint16 B, uint16 A) { setRGBA(R, G, B, A); }
- explicit Color64(uint64 U) : u(U) { }
-
- void setRGBA(uint16 R, uint16 G, uint16 B, uint16 A)
- {
- r = R;
- g = G;
- b = B;
- a = A;
- }
-
- operator uint64 () const {
- return u;
- }
-
- union {
- struct {
-#if NV_LITTLE_ENDIAN
- uint16 r, a, b, g;
-#else
- uint16 a: 16;
- uint16 r: 16;
- uint16 g: 16;
- uint16 b: 16;
-#endif
- };
- uint64 u;
- };
- };
-
- /// 32 bit color stored as BGRA.
- class NVMATH_CLASS Color32
- {
- public:
- Color32() { }
- Color32(const Color32 & c) : u(c.u) { }
- Color32(uint8 R, uint8 G, uint8 B) { setRGBA(R, G, B, 0xFF); }
- Color32(uint8 R, uint8 G, uint8 B, uint8 A) { setRGBA( R, G, B, A); }
- //Color32(uint8 c[4]) { setRGBA(c[0], c[1], c[2], c[3]); }
- //Color32(float R, float G, float B) { setRGBA(uint(R*255), uint(G*255), uint(B*255), 0xFF); }
- //Color32(float R, float G, float B, float A) { setRGBA(uint(R*255), uint(G*255), uint(B*255), uint(A*255)); }
- explicit Color32(uint32 U) : u(U) { }
-
- void setRGBA(uint8 R, uint8 G, uint8 B, uint8 A)
- {
- r = R;
- g = G;
- b = B;
- a = A;
- }
-
- void setBGRA(uint8 B, uint8 G, uint8 R, uint8 A = 0xFF)
- {
- r = R;
- g = G;
- b = B;
- a = A;
- }
-
- operator uint32 () const {
- return u;
- }
-
- union {
- struct {
-#if NV_LITTLE_ENDIAN
- uint8 b, g, r, a;
-#else
- uint8 a: 8;
- uint8 r: 8;
- uint8 g: 8;
- uint8 b: 8;
-#endif
- };
- uint8 component[4];
- uint32 u;
- };
- };
-
-
- /// 16 bit 565 BGR color.
- class NVMATH_CLASS Color16
- {
- public:
- Color16() { }
- Color16(const Color16 & c) : u(c.u) { }
- explicit Color16(uint16 U) : u(U) { }
-
- union {
- struct {
-#if NV_LITTLE_ENDIAN
- uint16 b : 5;
- uint16 g : 6;
- uint16 r : 5;
-#else
- uint16 r : 5;
- uint16 g : 6;
- uint16 b : 5;
-#endif
- };
- uint16 u;
- };
- };
-
- /// 16 bit 4444 BGRA color.
- class NVMATH_CLASS Color16_4444
- {
- public:
- Color16_4444() { }
- Color16_4444(const Color16_4444 & c) : u(c.u) { }
- explicit Color16_4444(uint16 U) : u(U) { }
-
- union {
- struct {
-#if NV_LITTLE_ENDIAN
- uint16 b : 4;
- uint16 g : 4;
- uint16 r : 4;
- uint16 a : 4;
-#else
- uint16 a : 4;
- uint16 r : 4;
- uint16 g : 4;
- uint16 b : 4;
-#endif
- };
- uint16 u;
- };
- };
-
-} // nv namespace
-
-#endif // NV_MATH_COLOR_H
diff --git a/thirdparty/thekla_atlas/nvmath/ConvexHull.cpp b/thirdparty/thekla_atlas/nvmath/ConvexHull.cpp
deleted file mode 100644
index a4a95dace4..0000000000
--- a/thirdparty/thekla_atlas/nvmath/ConvexHull.cpp
+++ /dev/null
@@ -1,120 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#include "ConvexHull.h"
-
-#include "Vector.inl"
-
-#include "nvcore/RadixSort.h"
-#include "nvcore/Array.inl"
-
-using namespace nv;
-
-inline static float triangleArea(Vector2::Arg v1, Vector2::Arg v2, Vector2::Arg v3)
-{
- return 0.5f * (v3.x * v1.y + v1.x * v2.y + v2.x * v3.y - v2.x * v1.y - v3.x * v2.y - v1.x * v3.y);
-}
-
-
-// Compute the convex hull using Graham Scan.
-void nv::convexHull(const Array<Vector2> & input, Array<Vector2> & output, float epsilon/*=0*/)
-{
- const uint inputCount = input.count();
-
- Array<float> coords;
- coords.resize(inputCount);
-
- for (uint i = 0; i < inputCount; i++) {
- coords[i] = input[i].x;
- }
-
- RadixSort radix;
- radix.sort(coords);
-
- const uint * ranks = radix.ranks();
-
- Array<Vector2> top(inputCount);
- Array<Vector2> bottom(inputCount);
-
- Vector2 P = input[ranks[0]];
- Vector2 Q = input[ranks[inputCount-1]];
-
- float topy = max(P.y, Q.y);
- float boty = min(P.y, Q.y);
-
- for (uint i = 0; i < inputCount; i++) {
- Vector2 p = input[ranks[i]];
- if (p.y >= boty) top.append(p);
- }
-
- for (uint i = 0; i < inputCount; i++) {
- Vector2 p = input[ranks[inputCount-1-i]];
- if (p.y <= topy) bottom.append(p);
- }
-
- // Filter top list.
- output.clear();
- output.append(top[0]);
- output.append(top[1]);
-
- for (uint i = 2; i < top.count(); ) {
- Vector2 a = output[output.count()-2];
- Vector2 b = output[output.count()-1];
- Vector2 c = top[i];
-
- float area = triangleArea(a, b, c);
-
- if (area >= -epsilon) {
- output.popBack();
- }
-
- if (area < -epsilon || output.count() == 1) {
- output.append(c);
- i++;
- }
- }
-
- uint top_count = output.count();
- output.append(bottom[1]);
-
- // Filter bottom list.
- for (uint i = 2; i < bottom.count(); ) {
- Vector2 a = output[output.count()-2];
- Vector2 b = output[output.count()-1];
- Vector2 c = bottom[i];
-
- float area = triangleArea(a, b, c);
-
- if (area >= -epsilon) {
- output.popBack();
- }
-
- if (area < -epsilon || output.count() == top_count) {
- output.append(c);
- i++;
- }
- }
-
- // Remove duplicate element.
- nvDebugCheck(output.front() == output.back());
- output.popBack();
-}
-
-/*
-void testConvexHull() {
-
- Array<Vector2> points;
- points.append(Vector2(1.00, 1.00));
- points.append(Vector2(0.00, 0.00));
- points.append(Vector2(1.00, 1.00));
- points.append(Vector2(1.00, -1.00));
- points.append(Vector2(2.00, 5.00));
- points.append(Vector2(-5.00, 3.00));
- points.append(Vector2(-4.00, -3.00));
- points.append(Vector2(7.00, -4.00));
-
- Array<Vector2> hull;
- convexHull(points, hull);
-
-}
-*/
-
diff --git a/thirdparty/thekla_atlas/nvmath/ConvexHull.h b/thirdparty/thekla_atlas/nvmath/ConvexHull.h
deleted file mode 100644
index 6c2db5d73f..0000000000
--- a/thirdparty/thekla_atlas/nvmath/ConvexHull.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#pragma once
-#ifndef NV_MATH_CONVEXHULL_H
-#define NV_MATH_CONVEXHULL_H
-
-#include "nvmath.h"
-#include "nvcore/Array.h"
-
-namespace nv {
- class Vector2;
-
- void convexHull(const Array<Vector2> & input, Array<Vector2> & output, float epsilon = 0);
-
-} // namespace nv
-
-#endif // NV_MATH_CONVEXHULL_H
diff --git a/thirdparty/thekla_atlas/nvmath/Fitting.cpp b/thirdparty/thekla_atlas/nvmath/Fitting.cpp
deleted file mode 100644
index 6cd5cb0f32..0000000000
--- a/thirdparty/thekla_atlas/nvmath/Fitting.cpp
+++ /dev/null
@@ -1,1205 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#include "Fitting.h"
-#include "Vector.inl"
-#include "Plane.inl"
-
-#include "nvcore/Array.inl"
-#include "nvcore/Utils.h" // max, swap
-
-#include <float.h> // FLT_MAX
-//#include <vector>
-#include <string.h>
-
-using namespace nv;
-
-// @@ Move to EigenSolver.h
-
-// @@ We should be able to do something cheaper...
-static Vector3 estimatePrincipalComponent(const float * __restrict matrix)
-{
- const Vector3 row0(matrix[0], matrix[1], matrix[2]);
- const Vector3 row1(matrix[1], matrix[3], matrix[4]);
- const Vector3 row2(matrix[2], matrix[4], matrix[5]);
-
- float r0 = lengthSquared(row0);
- float r1 = lengthSquared(row1);
- float r2 = lengthSquared(row2);
-
- if (r0 > r1 && r0 > r2) return row0;
- if (r1 > r2) return row1;
- return row2;
-}
-
-
-static inline Vector3 firstEigenVector_PowerMethod(const float *__restrict matrix)
-{
- if (matrix[0] == 0 && matrix[3] == 0 && matrix[5] == 0)
- {
- return Vector3(0.0f);
- }
-
- Vector3 v = estimatePrincipalComponent(matrix);
-
- const int NUM = 8;
- for (int i = 0; i < NUM; i++)
- {
- float x = v.x * matrix[0] + v.y * matrix[1] + v.z * matrix[2];
- float y = v.x * matrix[1] + v.y * matrix[3] + v.z * matrix[4];
- float z = v.x * matrix[2] + v.y * matrix[4] + v.z * matrix[5];
-
- float norm = max(max(x, y), z);
-
- v = Vector3(x, y, z) / norm;
- }
-
- return v;
-}
-
-
-Vector3 nv::Fit::computeCentroid(int n, const Vector3 *__restrict points)
-{
- Vector3 centroid(0.0f);
-
- for (int i = 0; i < n; i++)
- {
- centroid += points[i];
- }
- centroid /= float(n);
-
- return centroid;
-}
-
-Vector3 nv::Fit::computeCentroid(int n, const Vector3 *__restrict points, const float *__restrict weights, Vector3::Arg metric)
-{
- Vector3 centroid(0.0f);
- float total = 0.0f;
-
- for (int i = 0; i < n; i++)
- {
- total += weights[i];
- centroid += weights[i]*points[i];
- }
- centroid /= total;
-
- return centroid;
-}
-
-Vector4 nv::Fit::computeCentroid(int n, const Vector4 *__restrict points)
-{
- Vector4 centroid(0.0f);
-
- for (int i = 0; i < n; i++)
- {
- centroid += points[i];
- }
- centroid /= float(n);
-
- return centroid;
-}
-
-Vector4 nv::Fit::computeCentroid(int n, const Vector4 *__restrict points, const float *__restrict weights, Vector4::Arg metric)
-{
- Vector4 centroid(0.0f);
- float total = 0.0f;
-
- for (int i = 0; i < n; i++)
- {
- total += weights[i];
- centroid += weights[i]*points[i];
- }
- centroid /= total;
-
- return centroid;
-}
-
-
-
-Vector3 nv::Fit::computeCovariance(int n, const Vector3 *__restrict points, float *__restrict covariance)
-{
- // compute the centroid
- Vector3 centroid = computeCentroid(n, points);
-
- // compute covariance matrix
- for (int i = 0; i < 6; i++)
- {
- covariance[i] = 0.0f;
- }
-
- for (int i = 0; i < n; i++)
- {
- Vector3 v = points[i] - centroid;
-
- covariance[0] += v.x * v.x;
- covariance[1] += v.x * v.y;
- covariance[2] += v.x * v.z;
- covariance[3] += v.y * v.y;
- covariance[4] += v.y * v.z;
- covariance[5] += v.z * v.z;
- }
-
- return centroid;
-}
-
-Vector3 nv::Fit::computeCovariance(int n, const Vector3 *__restrict points, const float *__restrict weights, Vector3::Arg metric, float *__restrict covariance)
-{
- // compute the centroid
- Vector3 centroid = computeCentroid(n, points, weights, metric);
-
- // compute covariance matrix
- for (int i = 0; i < 6; i++)
- {
- covariance[i] = 0.0f;
- }
-
- for (int i = 0; i < n; i++)
- {
- Vector3 a = (points[i] - centroid) * metric;
- Vector3 b = weights[i]*a;
-
- covariance[0] += a.x * b.x;
- covariance[1] += a.x * b.y;
- covariance[2] += a.x * b.z;
- covariance[3] += a.y * b.y;
- covariance[4] += a.y * b.z;
- covariance[5] += a.z * b.z;
- }
-
- return centroid;
-}
-
-Vector4 nv::Fit::computeCovariance(int n, const Vector4 *__restrict points, float *__restrict covariance)
-{
- // compute the centroid
- Vector4 centroid = computeCentroid(n, points);
-
- // compute covariance matrix
- for (int i = 0; i < 10; i++)
- {
- covariance[i] = 0.0f;
- }
-
- for (int i = 0; i < n; i++)
- {
- Vector4 v = points[i] - centroid;
-
- covariance[0] += v.x * v.x;
- covariance[1] += v.x * v.y;
- covariance[2] += v.x * v.z;
- covariance[3] += v.x * v.w;
-
- covariance[4] += v.y * v.y;
- covariance[5] += v.y * v.z;
- covariance[6] += v.y * v.w;
-
- covariance[7] += v.z * v.z;
- covariance[8] += v.z * v.w;
-
- covariance[9] += v.w * v.w;
- }
-
- return centroid;
-}
-
-Vector4 nv::Fit::computeCovariance(int n, const Vector4 *__restrict points, const float *__restrict weights, Vector4::Arg metric, float *__restrict covariance)
-{
- // compute the centroid
- Vector4 centroid = computeCentroid(n, points, weights, metric);
-
- // compute covariance matrix
- for (int i = 0; i < 10; i++)
- {
- covariance[i] = 0.0f;
- }
-
- for (int i = 0; i < n; i++)
- {
- Vector4 a = (points[i] - centroid) * metric;
- Vector4 b = weights[i]*a;
-
- covariance[0] += a.x * b.x;
- covariance[1] += a.x * b.y;
- covariance[2] += a.x * b.z;
- covariance[3] += a.x * b.w;
-
- covariance[4] += a.y * b.y;
- covariance[5] += a.y * b.z;
- covariance[6] += a.y * b.w;
-
- covariance[7] += a.z * b.z;
- covariance[8] += a.z * b.w;
-
- covariance[9] += a.w * b.w;
- }
-
- return centroid;
-}
-
-
-
-Vector3 nv::Fit::computePrincipalComponent_PowerMethod(int n, const Vector3 *__restrict points)
-{
- float matrix[6];
- computeCovariance(n, points, matrix);
-
- return firstEigenVector_PowerMethod(matrix);
-}
-
-Vector3 nv::Fit::computePrincipalComponent_PowerMethod(int n, const Vector3 *__restrict points, const float *__restrict weights, Vector3::Arg metric)
-{
- float matrix[6];
- computeCovariance(n, points, weights, metric, matrix);
-
- return firstEigenVector_PowerMethod(matrix);
-}
-
-
-
-static inline Vector3 firstEigenVector_EigenSolver3(const float *__restrict matrix)
-{
- if (matrix[0] == 0 && matrix[3] == 0 && matrix[5] == 0)
- {
- return Vector3(0.0f);
- }
-
- float eigenValues[3];
- Vector3 eigenVectors[3];
- if (!nv::Fit::eigenSolveSymmetric3(matrix, eigenValues, eigenVectors))
- {
- return Vector3(0.0f);
- }
-
- return eigenVectors[0];
-}
-
-Vector3 nv::Fit::computePrincipalComponent_EigenSolver(int n, const Vector3 *__restrict points)
-{
- float matrix[6];
- computeCovariance(n, points, matrix);
-
- return firstEigenVector_EigenSolver3(matrix);
-}
-
-Vector3 nv::Fit::computePrincipalComponent_EigenSolver(int n, const Vector3 *__restrict points, const float *__restrict weights, Vector3::Arg metric)
-{
- float matrix[6];
- computeCovariance(n, points, weights, metric, matrix);
-
- return firstEigenVector_EigenSolver3(matrix);
-}
-
-
-
-static inline Vector4 firstEigenVector_EigenSolver4(const float *__restrict matrix)
-{
- if (matrix[0] == 0 && matrix[4] == 0 && matrix[7] == 0&& matrix[9] == 0)
- {
- return Vector4(0.0f);
- }
-
- float eigenValues[4];
- Vector4 eigenVectors[4];
- if (!nv::Fit::eigenSolveSymmetric4(matrix, eigenValues, eigenVectors))
- {
- return Vector4(0.0f);
- }
-
- return eigenVectors[0];
-}
-
-Vector4 nv::Fit::computePrincipalComponent_EigenSolver(int n, const Vector4 *__restrict points)
-{
- float matrix[10];
- computeCovariance(n, points, matrix);
-
- return firstEigenVector_EigenSolver4(matrix);
-}
-
-Vector4 nv::Fit::computePrincipalComponent_EigenSolver(int n, const Vector4 *__restrict points, const float *__restrict weights, Vector4::Arg metric)
-{
- float matrix[10];
- computeCovariance(n, points, weights, metric, matrix);
-
- return firstEigenVector_EigenSolver4(matrix);
-}
-
-
-
-void ArvoSVD(int rows, int cols, float * Q, float * diag, float * R);
-
-Vector3 nv::Fit::computePrincipalComponent_SVD(int n, const Vector3 *__restrict points)
-{
- // Store the points in an n x n matrix
- Array<float> Q; Q.resize(n*n, 0.0f);
- for (int i = 0; i < n; ++i)
- {
- Q[i*n+0] = points[i].x;
- Q[i*n+1] = points[i].y;
- Q[i*n+2] = points[i].z;
- }
-
- // Alloc space for the SVD outputs
- Array<float> diag; diag.resize(n, 0.0f);
- Array<float> R; R.resize(n*n, 0.0f);
-
- ArvoSVD(n, n, &Q[0], &diag[0], &R[0]);
-
- // Get the principal component
- return Vector3(R[0], R[1], R[2]);
-}
-
-Vector4 nv::Fit::computePrincipalComponent_SVD(int n, const Vector4 *__restrict points)
-{
- // Store the points in an n x n matrix
- Array<float> Q; Q.resize(n*n, 0.0f);
- for (int i = 0; i < n; ++i)
- {
- Q[i*n+0] = points[i].x;
- Q[i*n+1] = points[i].y;
- Q[i*n+2] = points[i].z;
- Q[i*n+3] = points[i].w;
- }
-
- // Alloc space for the SVD outputs
- Array<float> diag; diag.resize(n, 0.0f);
- Array<float> R; R.resize(n*n, 0.0f);
-
- ArvoSVD(n, n, &Q[0], &diag[0], &R[0]);
-
- // Get the principal component
- return Vector4(R[0], R[1], R[2], R[3]);
-}
-
-
-
-Plane nv::Fit::bestPlane(int n, const Vector3 *__restrict points)
-{
- // compute the centroid and covariance
- float matrix[6];
- Vector3 centroid = computeCovariance(n, points, matrix);
-
- if (matrix[0] == 0 && matrix[3] == 0 && matrix[5] == 0)
- {
- // If no plane defined, then return a horizontal plane.
- return Plane(Vector3(0, 0, 1), centroid);
- }
-
- float eigenValues[3];
- Vector3 eigenVectors[3];
- if (!eigenSolveSymmetric3(matrix, eigenValues, eigenVectors)) {
- // If no plane defined, then return a horizontal plane.
- return Plane(Vector3(0, 0, 1), centroid);
- }
-
- return Plane(eigenVectors[2], centroid);
-}
-
-bool nv::Fit::isPlanar(int n, const Vector3 * points, float epsilon/*=NV_EPSILON*/)
-{
- // compute the centroid and covariance
- float matrix[6];
- computeCovariance(n, points, matrix);
-
- float eigenValues[3];
- Vector3 eigenVectors[3];
- if (!eigenSolveSymmetric3(matrix, eigenValues, eigenVectors)) {
- return false;
- }
-
- return eigenValues[2] < epsilon;
-}
-
-
-
-// Tridiagonal solver from Charles Bloom.
-// Householder transforms followed by QL decomposition.
-// Seems to be based on the code from Numerical Recipes in C.
-
-static void EigenSolver3_Tridiagonal(float mat[3][3], float * diag, float * subd);
-static bool EigenSolver3_QLAlgorithm(float mat[3][3], float * diag, float * subd);
-
-bool nv::Fit::eigenSolveSymmetric3(const float matrix[6], float eigenValues[3], Vector3 eigenVectors[3])
-{
- nvDebugCheck(matrix != NULL && eigenValues != NULL && eigenVectors != NULL);
-
- float subd[3];
- float diag[3];
- float work[3][3];
-
- work[0][0] = matrix[0];
- work[0][1] = work[1][0] = matrix[1];
- work[0][2] = work[2][0] = matrix[2];
- work[1][1] = matrix[3];
- work[1][2] = work[2][1] = matrix[4];
- work[2][2] = matrix[5];
-
- EigenSolver3_Tridiagonal(work, diag, subd);
- if (!EigenSolver3_QLAlgorithm(work, diag, subd))
- {
- for (int i = 0; i < 3; i++) {
- eigenValues[i] = 0;
- eigenVectors[i] = Vector3(0);
- }
- return false;
- }
-
- for (int i = 0; i < 3; i++) {
- eigenValues[i] = (float)diag[i];
- }
-
- // eigenvectors are the columns; make them the rows :
-
- for (int i=0; i < 3; i++)
- {
- for (int j = 0; j < 3; j++)
- {
- eigenVectors[j].component[i] = (float) work[i][j];
- }
- }
-
- // shuffle to sort by singular value :
- if (eigenValues[2] > eigenValues[0] && eigenValues[2] > eigenValues[1])
- {
- swap(eigenValues[0], eigenValues[2]);
- swap(eigenVectors[0], eigenVectors[2]);
- }
- if (eigenValues[1] > eigenValues[0])
- {
- swap(eigenValues[0], eigenValues[1]);
- swap(eigenVectors[0], eigenVectors[1]);
- }
- if (eigenValues[2] > eigenValues[1])
- {
- swap(eigenValues[1], eigenValues[2]);
- swap(eigenVectors[1], eigenVectors[2]);
- }
-
- nvDebugCheck(eigenValues[0] >= eigenValues[1] && eigenValues[0] >= eigenValues[2]);
- nvDebugCheck(eigenValues[1] >= eigenValues[2]);
-
- return true;
-}
-
-static void EigenSolver3_Tridiagonal(float mat[3][3], float * diag, float * subd)
-{
- // Householder reduction T = Q^t M Q
- // Input:
- // mat, symmetric 3x3 matrix M
- // Output:
- // mat, orthogonal matrix Q
- // diag, diagonal entries of T
- // subd, subdiagonal entries of T (T is symmetric)
- const float epsilon = 1e-08f;
-
- float a = mat[0][0];
- float b = mat[0][1];
- float c = mat[0][2];
- float d = mat[1][1];
- float e = mat[1][2];
- float f = mat[2][2];
-
- diag[0] = a;
- subd[2] = 0.f;
- if (fabsf(c) >= epsilon)
- {
- const float ell = sqrtf(b*b+c*c);
- b /= ell;
- c /= ell;
- const float q = 2*b*e+c*(f-d);
- diag[1] = d+c*q;
- diag[2] = f-c*q;
- subd[0] = ell;
- subd[1] = e-b*q;
- mat[0][0] = 1; mat[0][1] = 0; mat[0][2] = 0;
- mat[1][0] = 0; mat[1][1] = b; mat[1][2] = c;
- mat[2][0] = 0; mat[2][1] = c; mat[2][2] = -b;
- }
- else
- {
- diag[1] = d;
- diag[2] = f;
- subd[0] = b;
- subd[1] = e;
- mat[0][0] = 1; mat[0][1] = 0; mat[0][2] = 0;
- mat[1][0] = 0; mat[1][1] = 1; mat[1][2] = 0;
- mat[2][0] = 0; mat[2][1] = 0; mat[2][2] = 1;
- }
-}
-
-static bool EigenSolver3_QLAlgorithm(float mat[3][3], float * diag, float * subd)
-{
- // QL iteration with implicit shifting to reduce matrix from tridiagonal
- // to diagonal
- const int maxiter = 32;
-
- for (int ell = 0; ell < 3; ell++)
- {
- int iter;
- for (iter = 0; iter < maxiter; iter++)
- {
- int m;
- for (m = ell; m <= 1; m++)
- {
- float dd = fabsf(diag[m]) + fabsf(diag[m+1]);
- if ( fabsf(subd[m]) + dd == dd )
- break;
- }
- if ( m == ell )
- break;
-
- float g = (diag[ell+1]-diag[ell])/(2*subd[ell]);
- float r = sqrtf(g*g+1);
- if ( g < 0 )
- g = diag[m]-diag[ell]+subd[ell]/(g-r);
- else
- g = diag[m]-diag[ell]+subd[ell]/(g+r);
- float s = 1, c = 1, p = 0;
- for (int i = m-1; i >= ell; i--)
- {
- float f = s*subd[i], b = c*subd[i];
- if ( fabsf(f) >= fabsf(g) )
- {
- c = g/f;
- r = sqrtf(c*c+1);
- subd[i+1] = f*r;
- c *= (s = 1/r);
- }
- else
- {
- s = f/g;
- r = sqrtf(s*s+1);
- subd[i+1] = g*r;
- s *= (c = 1/r);
- }
- g = diag[i+1]-p;
- r = (diag[i]-g)*s+2*b*c;
- p = s*r;
- diag[i+1] = g+p;
- g = c*r-b;
-
- for (int k = 0; k < 3; k++)
- {
- f = mat[k][i+1];
- mat[k][i+1] = s*mat[k][i]+c*f;
- mat[k][i] = c*mat[k][i]-s*f;
- }
- }
- diag[ell] -= p;
- subd[ell] = g;
- subd[m] = 0;
- }
-
- if ( iter == maxiter )
- // should not get here under normal circumstances
- return false;
- }
-
- return true;
-}
-
-
-
-// Tridiagonal solver for 4x4 symmetric matrices.
-
-static void EigenSolver4_Tridiagonal(float mat[4][4], float * diag, float * subd);
-static bool EigenSolver4_QLAlgorithm(float mat[4][4], float * diag, float * subd);
-
-bool nv::Fit::eigenSolveSymmetric4(const float matrix[10], float eigenValues[4], Vector4 eigenVectors[4])
-{
- nvDebugCheck(matrix != NULL && eigenValues != NULL && eigenVectors != NULL);
-
- float subd[4];
- float diag[4];
- float work[4][4];
-
- work[0][0] = matrix[0];
- work[0][1] = work[1][0] = matrix[1];
- work[0][2] = work[2][0] = matrix[2];
- work[0][3] = work[3][0] = matrix[3];
- work[1][1] = matrix[4];
- work[1][2] = work[2][1] = matrix[5];
- work[1][3] = work[3][1] = matrix[6];
- work[2][2] = matrix[7];
- work[2][3] = work[3][2] = matrix[8];
- work[3][3] = matrix[9];
-
- EigenSolver4_Tridiagonal(work, diag, subd);
- if (!EigenSolver4_QLAlgorithm(work, diag, subd))
- {
- for (int i = 0; i < 4; i++) {
- eigenValues[i] = 0;
- eigenVectors[i] = Vector4(0);
- }
- return false;
- }
-
- for (int i = 0; i < 4; i++) {
- eigenValues[i] = (float)diag[i];
- }
-
- // eigenvectors are the columns; make them the rows
-
- for (int i = 0; i < 4; i++)
- {
- for (int j = 0; j < 4; j++)
- {
- eigenVectors[j].component[i] = (float) work[i][j];
- }
- }
-
- // sort by singular value
-
- for (int i = 0; i < 3; ++i)
- {
- for (int j = i+1; j < 4; ++j)
- {
- if (eigenValues[j] > eigenValues[i])
- {
- swap(eigenValues[i], eigenValues[j]);
- swap(eigenVectors[i], eigenVectors[j]);
- }
- }
- }
-
- nvDebugCheck(eigenValues[0] >= eigenValues[1] && eigenValues[0] >= eigenValues[2] && eigenValues[0] >= eigenValues[3]);
- nvDebugCheck(eigenValues[1] >= eigenValues[2] && eigenValues[1] >= eigenValues[3]);
- nvDebugCheck(eigenValues[2] >= eigenValues[2]);
-
- return true;
-}
-
-#include "nvmath/Matrix.inl"
-
-inline float signNonzero(float x)
-{
- return (x >= 0.0f) ? 1.0f : -1.0f;
-}
-
-static void EigenSolver4_Tridiagonal(float mat[4][4], float * diag, float * subd)
-{
- // Householder reduction T = Q^t M Q
- // Input:
- // mat, symmetric 3x3 matrix M
- // Output:
- // mat, orthogonal matrix Q
- // diag, diagonal entries of T
- // subd, subdiagonal entries of T (T is symmetric)
-
- static const int n = 4;
-
- // Set epsilon relative to size of elements in matrix
- static const float relEpsilon = 1e-6f;
- float maxElement = FLT_MAX;
- for (int i = 0; i < n; ++i)
- for (int j = 0; j < n; ++j)
- maxElement = max(maxElement, fabsf(mat[i][j]));
- float epsilon = relEpsilon * maxElement;
-
- // Iterative algorithm, works for any size of matrix but might be slower than
- // a closed-form solution for symmetric 4x4 matrices. Based on this article:
- // http://en.wikipedia.org/wiki/Householder_transformation#Tridiagonalization
-
- Matrix A, Q(identity);
- memcpy(&A, mat, sizeof(float)*n*n);
-
- // We proceed from left to right, making the off-tridiagonal entries zero in
- // one column of the matrix at a time.
- for (int k = 0; k < n - 2; ++k)
- {
- float sum = 0.0f;
- for (int j = k+1; j < n; ++j)
- sum += A(j,k)*A(j,k);
- float alpha = -signNonzero(A(k+1,k)) * sqrtf(sum);
- float r = sqrtf(0.5f * (alpha*alpha - A(k+1,k)*alpha));
-
- // If r is zero, skip this column - already in tridiagonal form
- if (fabsf(r) < epsilon)
- continue;
-
- float v[n] = {};
- v[k+1] = 0.5f * (A(k+1,k) - alpha) / r;
- for (int j = k+2; j < n; ++j)
- v[j] = 0.5f * A(j,k) / r;
-
- Matrix P(identity);
- for (int i = 0; i < n; ++i)
- for (int j = 0; j < n; ++j)
- P(i,j) -= 2.0f * v[i] * v[j];
-
- A = mul(mul(P, A), P);
- Q = mul(Q, P);
- }
-
- nvDebugCheck(fabsf(A(2,0)) < epsilon);
- nvDebugCheck(fabsf(A(0,2)) < epsilon);
- nvDebugCheck(fabsf(A(3,0)) < epsilon);
- nvDebugCheck(fabsf(A(0,3)) < epsilon);
- nvDebugCheck(fabsf(A(3,1)) < epsilon);
- nvDebugCheck(fabsf(A(1,3)) < epsilon);
-
- for (int i = 0; i < n; ++i)
- diag[i] = A(i,i);
- for (int i = 0; i < n - 1; ++i)
- subd[i] = A(i+1,i);
- subd[n-1] = 0.0f;
-
- memcpy(mat, &Q, sizeof(float)*n*n);
-}
-
-static bool EigenSolver4_QLAlgorithm(float mat[4][4], float * diag, float * subd)
-{
- // QL iteration with implicit shifting to reduce matrix from tridiagonal
- // to diagonal
- const int maxiter = 32;
-
- for (int ell = 0; ell < 4; ell++)
- {
- int iter;
- for (iter = 0; iter < maxiter; iter++)
- {
- int m;
- for (m = ell; m < 3; m++)
- {
- float dd = fabsf(diag[m]) + fabsf(diag[m+1]);
- if ( fabsf(subd[m]) + dd == dd )
- break;
- }
- if ( m == ell )
- break;
-
- float g = (diag[ell+1]-diag[ell])/(2*subd[ell]);
- float r = sqrtf(g*g+1);
- if ( g < 0 )
- g = diag[m]-diag[ell]+subd[ell]/(g-r);
- else
- g = diag[m]-diag[ell]+subd[ell]/(g+r);
- float s = 1, c = 1, p = 0;
- for (int i = m-1; i >= ell; i--)
- {
- float f = s*subd[i], b = c*subd[i];
- if ( fabsf(f) >= fabsf(g) )
- {
- c = g/f;
- r = sqrtf(c*c+1);
- subd[i+1] = f*r;
- c *= (s = 1/r);
- }
- else
- {
- s = f/g;
- r = sqrtf(s*s+1);
- subd[i+1] = g*r;
- s *= (c = 1/r);
- }
- g = diag[i+1]-p;
- r = (diag[i]-g)*s+2*b*c;
- p = s*r;
- diag[i+1] = g+p;
- g = c*r-b;
-
- for (int k = 0; k < 4; k++)
- {
- f = mat[k][i+1];
- mat[k][i+1] = s*mat[k][i]+c*f;
- mat[k][i] = c*mat[k][i]-s*f;
- }
- }
- diag[ell] -= p;
- subd[ell] = g;
- subd[m] = 0;
- }
-
- if ( iter == maxiter )
- // should not get here under normal circumstances
- return false;
- }
-
- return true;
-}
-
-
-
-int nv::Fit::compute4Means(int n, const Vector3 *__restrict points, const float *__restrict weights, Vector3::Arg metric, Vector3 *__restrict cluster)
-{
- // Compute principal component.
- float matrix[6];
- Vector3 centroid = computeCovariance(n, points, weights, metric, matrix);
- Vector3 principal = firstEigenVector_PowerMethod(matrix);
-
- // Pick initial solution.
- int mini, maxi;
- mini = maxi = 0;
-
- float mindps, maxdps;
- mindps = maxdps = dot(points[0] - centroid, principal);
-
- for (int i = 1; i < n; ++i)
- {
- float dps = dot(points[i] - centroid, principal);
-
- if (dps < mindps) {
- mindps = dps;
- mini = i;
- }
- else {
- maxdps = dps;
- maxi = i;
- }
- }
-
- cluster[0] = centroid + mindps * principal;
- cluster[1] = centroid + maxdps * principal;
- cluster[2] = (2.0f * cluster[0] + cluster[1]) / 3.0f;
- cluster[3] = (2.0f * cluster[1] + cluster[0]) / 3.0f;
-
- // Now we have to iteratively refine the clusters.
- while (true)
- {
- Vector3 newCluster[4] = { Vector3(0.0f), Vector3(0.0f), Vector3(0.0f), Vector3(0.0f) };
- float total[4] = {0, 0, 0, 0};
-
- for (int i = 0; i < n; ++i)
- {
- // Find nearest cluster.
- int nearest = 0;
- float mindist = FLT_MAX;
- for (int j = 0; j < 4; j++)
- {
- float dist = lengthSquared((cluster[j] - points[i]) * metric);
- if (dist < mindist)
- {
- mindist = dist;
- nearest = j;
- }
- }
-
- newCluster[nearest] += weights[i] * points[i];
- total[nearest] += weights[i];
- }
-
- for (int j = 0; j < 4; j++)
- {
- if (total[j] != 0)
- newCluster[j] /= total[j];
- }
-
- if (equal(cluster[0], newCluster[0]) && equal(cluster[1], newCluster[1]) &&
- equal(cluster[2], newCluster[2]) && equal(cluster[3], newCluster[3]))
- {
- return (total[0] != 0) + (total[1] != 0) + (total[2] != 0) + (total[3] != 0);
- }
-
- cluster[0] = newCluster[0];
- cluster[1] = newCluster[1];
- cluster[2] = newCluster[2];
- cluster[3] = newCluster[3];
-
- // Sort clusters by weight.
- for (int i = 0; i < 4; i++)
- {
- for (int j = i; j > 0 && total[j] > total[j - 1]; j--)
- {
- swap( total[j], total[j - 1] );
- swap( cluster[j], cluster[j - 1] );
- }
- }
- }
-}
-
-
-
-// Adaptation of James Arvo's SVD code, as found in ZOH.
-
-inline float Sqr(float x) { return x*x; }
-
-inline float svd_pythag( float a, float b )
-{
- float at = fabsf(a);
- float bt = fabsf(b);
- if( at > bt )
- return at * sqrtf( 1.0f + Sqr( bt / at ) );
- else if( bt > 0.0f )
- return bt * sqrtf( 1.0f + Sqr( at / bt ) );
- else return 0.0f;
-}
-
-inline float SameSign( float a, float b )
-{
- float t;
- if( b >= 0.0f ) t = fabsf( a );
- else t = -fabsf( a );
- return t;
-}
-
-void ArvoSVD(int rows, int cols, float * Q, float * diag, float * R)
-{
- static const int MaxIterations = 30;
-
- int i, j, k, l, p, q, iter;
- float c, f, h, s, x, y, z;
- float norm = 0.0f;
- float g = 0.0f;
- float scale = 0.0f;
-
- Array<float> temp; temp.resize(cols, 0.0f);
-
- for( i = 0; i < cols; i++ )
- {
- temp[i] = scale * g;
- scale = 0.0f;
- g = 0.0f;
- s = 0.0f;
- l = i + 1;
-
- if( i < rows )
- {
- for( k = i; k < rows; k++ ) scale += fabsf( Q[k*cols+i] );
- if( scale != 0.0f )
- {
- for( k = i; k < rows; k++ )
- {
- Q[k*cols+i] /= scale;
- s += Sqr( Q[k*cols+i] );
- }
- f = Q[i*cols+i];
- g = -SameSign( sqrtf(s), f );
- h = f * g - s;
- Q[i*cols+i] = f - g;
- if( i != cols - 1 )
- {
- for( j = l; j < cols; j++ )
- {
- s = 0.0f;
- for( k = i; k < rows; k++ ) s += Q[k*cols+i] * Q[k*cols+j];
- f = s / h;
- for( k = i; k < rows; k++ ) Q[k*cols+j] += f * Q[k*cols+i];
- }
- }
- for( k = i; k < rows; k++ ) Q[k*cols+i] *= scale;
- }
- }
-
- diag[i] = scale * g;
- g = 0.0f;
- s = 0.0f;
- scale = 0.0f;
-
- if( i < rows && i != cols - 1 )
- {
- for( k = l; k < cols; k++ ) scale += fabsf( Q[i*cols+k] );
- if( scale != 0.0f )
- {
- for( k = l; k < cols; k++ )
- {
- Q[i*cols+k] /= scale;
- s += Sqr( Q[i*cols+k] );
- }
- f = Q[i*cols+l];
- g = -SameSign( sqrtf(s), f );
- h = f * g - s;
- Q[i*cols+l] = f - g;
- for( k = l; k < cols; k++ ) temp[k] = Q[i*cols+k] / h;
- if( i != rows - 1 )
- {
- for( j = l; j < rows; j++ )
- {
- s = 0.0f;
- for( k = l; k < cols; k++ ) s += Q[j*cols+k] * Q[i*cols+k];
- for( k = l; k < cols; k++ ) Q[j*cols+k] += s * temp[k];
- }
- }
- for( k = l; k < cols; k++ ) Q[i*cols+k] *= scale;
- }
- }
- norm = max( norm, fabsf( diag[i] ) + fabsf( temp[i] ) );
- }
-
-
- for( i = cols - 1; i >= 0; i-- )
- {
- if( i < cols - 1 )
- {
- if( g != 0.0f )
- {
- for( j = l; j < cols; j++ ) R[i*cols+j] = ( Q[i*cols+j] / Q[i*cols+l] ) / g;
- for( j = l; j < cols; j++ )
- {
- s = 0.0f;
- for( k = l; k < cols; k++ ) s += Q[i*cols+k] * R[j*cols+k];
- for( k = l; k < cols; k++ ) R[j*cols+k] += s * R[i*cols+k];
- }
- }
- for( j = l; j < cols; j++ )
- {
- R[i*cols+j] = 0.0f;
- R[j*cols+i] = 0.0f;
- }
- }
- R[i*cols+i] = 1.0f;
- g = temp[i];
- l = i;
- }
-
-
- for( i = cols - 1; i >= 0; i-- )
- {
- l = i + 1;
- g = diag[i];
- if( i < cols - 1 ) for( j = l; j < cols; j++ ) Q[i*cols+j] = 0.0f;
- if( g != 0.0f )
- {
- g = 1.0f / g;
- if( i != cols - 1 )
- {
- for( j = l; j < cols; j++ )
- {
- s = 0.0f;
- for( k = l; k < rows; k++ ) s += Q[k*cols+i] * Q[k*cols+j];
- f = ( s / Q[i*cols+i] ) * g;
- for( k = i; k < rows; k++ ) Q[k*cols+j] += f * Q[k*cols+i];
- }
- }
- for( j = i; j < rows; j++ ) Q[j*cols+i] *= g;
- }
- else
- {
- for( j = i; j < rows; j++ ) Q[j*cols+i] = 0.0f;
- }
- Q[i*cols+i] += 1.0f;
- }
-
-
- for( k = cols - 1; k >= 0; k-- )
- {
- for( iter = 1; iter <= MaxIterations; iter++ )
- {
- int jump = 0;
-
- for( l = k; l >= 0; l-- )
- {
- q = l - 1;
- if( fabsf( temp[l] ) + norm == norm ) { jump = 1; break; }
- if( fabsf( diag[q] ) + norm == norm ) { jump = 0; break; }
- }
-
- if( !jump )
- {
- c = 0.0f;
- s = 1.0f;
- for( i = l; i <= k; i++ )
- {
- f = s * temp[i];
- temp[i] *= c;
- if( fabsf( f ) + norm == norm ) break;
- g = diag[i];
- h = svd_pythag( f, g );
- diag[i] = h;
- h = 1.0f / h;
- c = g * h;
- s = -f * h;
- for( j = 0; j < rows; j++ )
- {
- y = Q[j*cols+q];
- z = Q[j*cols+i];
- Q[j*cols+q] = y * c + z * s;
- Q[j*cols+i] = z * c - y * s;
- }
- }
- }
-
- z = diag[k];
- if( l == k )
- {
- if( z < 0.0f )
- {
- diag[k] = -z;
- for( j = 0; j < cols; j++ ) R[k*cols+j] *= -1.0f;
- }
- break;
- }
- if( iter >= MaxIterations ) return;
- x = diag[l];
- q = k - 1;
- y = diag[q];
- g = temp[q];
- h = temp[k];
- f = ( ( y - z ) * ( y + z ) + ( g - h ) * ( g + h ) ) / ( 2.0f * h * y );
- g = svd_pythag( f, 1.0f );
- f = ( ( x - z ) * ( x + z ) + h * ( ( y / ( f + SameSign( g, f ) ) ) - h ) ) / x;
- c = 1.0f;
- s = 1.0f;
- for( j = l; j <= q; j++ )
- {
- i = j + 1;
- g = temp[i];
- y = diag[i];
- h = s * g;
- g = c * g;
- z = svd_pythag( f, h );
- temp[j] = z;
- c = f / z;
- s = h / z;
- f = x * c + g * s;
- g = g * c - x * s;
- h = y * s;
- y = y * c;
- for( p = 0; p < cols; p++ )
- {
- x = R[j*cols+p];
- z = R[i*cols+p];
- R[j*cols+p] = x * c + z * s;
- R[i*cols+p] = z * c - x * s;
- }
- z = svd_pythag( f, h );
- diag[j] = z;
- if( z != 0.0f )
- {
- z = 1.0f / z;
- c = f * z;
- s = h * z;
- }
- f = c * g + s * y;
- x = c * y - s * g;
- for( p = 0; p < rows; p++ )
- {
- y = Q[p*cols+j];
- z = Q[p*cols+i];
- Q[p*cols+j] = y * c + z * s;
- Q[p*cols+i] = z * c - y * s;
- }
- }
- temp[l] = 0.0f;
- temp[k] = f;
- diag[k] = x;
- }
- }
-
- // Sort the singular values into descending order.
-
- for( i = 0; i < cols - 1; i++ )
- {
- float biggest = diag[i]; // Biggest singular value so far.
- int bindex = i; // The row/col it occurred in.
- for( j = i + 1; j < cols; j++ )
- {
- if( diag[j] > biggest )
- {
- biggest = diag[j];
- bindex = j;
- }
- }
- if( bindex != i ) // Need to swap rows and columns.
- {
- // Swap columns in Q.
- for (int j = 0; j < rows; ++j)
- swap(Q[j*cols+i], Q[j*cols+bindex]);
-
- // Swap rows in R.
- for (int j = 0; j < rows; ++j)
- swap(R[i*cols+j], R[bindex*cols+j]);
-
- // Swap elements in diag.
- swap(diag[i], diag[bindex]);
- }
- }
-}
diff --git a/thirdparty/thekla_atlas/nvmath/Fitting.h b/thirdparty/thekla_atlas/nvmath/Fitting.h
deleted file mode 100644
index 7a88cd28fd..0000000000
--- a/thirdparty/thekla_atlas/nvmath/Fitting.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#pragma once
-#ifndef NV_MATH_FITTING_H
-#define NV_MATH_FITTING_H
-
-#include "Vector.h"
-#include "Plane.h"
-
-namespace nv
-{
- namespace Fit
- {
- Vector3 computeCentroid(int n, const Vector3 * points);
- Vector3 computeCentroid(int n, const Vector3 * points, const float * weights, const Vector3 & metric);
-
- Vector4 computeCentroid(int n, const Vector4 * points);
- Vector4 computeCentroid(int n, const Vector4 * points, const float * weights, const Vector4 & metric);
-
- Vector3 computeCovariance(int n, const Vector3 * points, float * covariance);
- Vector3 computeCovariance(int n, const Vector3 * points, const float * weights, const Vector3 & metric, float * covariance);
-
- Vector4 computeCovariance(int n, const Vector4 * points, float * covariance);
- Vector4 computeCovariance(int n, const Vector4 * points, const float * weights, const Vector4 & metric, float * covariance);
-
- Vector3 computePrincipalComponent_PowerMethod(int n, const Vector3 * points);
- Vector3 computePrincipalComponent_PowerMethod(int n, const Vector3 * points, const float * weights, const Vector3 & metric);
-
- Vector3 computePrincipalComponent_EigenSolver(int n, const Vector3 * points);
- Vector3 computePrincipalComponent_EigenSolver(int n, const Vector3 * points, const float * weights, const Vector3 & metric);
-
- Vector4 computePrincipalComponent_EigenSolver(int n, const Vector4 * points);
- Vector4 computePrincipalComponent_EigenSolver(int n, const Vector4 * points, const float * weights, const Vector4 & metric);
-
- Vector3 computePrincipalComponent_SVD(int n, const Vector3 * points);
- Vector4 computePrincipalComponent_SVD(int n, const Vector4 * points);
-
- Plane bestPlane(int n, const Vector3 * points);
- bool isPlanar(int n, const Vector3 * points, float epsilon = NV_EPSILON);
-
- bool eigenSolveSymmetric3(const float matrix[6], float eigenValues[3], Vector3 eigenVectors[3]);
- bool eigenSolveSymmetric4(const float matrix[10], float eigenValues[4], Vector4 eigenVectors[4]);
-
- // Returns number of clusters [1-4].
- int compute4Means(int n, const Vector3 * points, const float * weights, const Vector3 & metric, Vector3 * cluster);
- }
-
-} // nv namespace
-
-#endif // NV_MATH_FITTING_H
diff --git a/thirdparty/thekla_atlas/nvmath/KahanSum.h b/thirdparty/thekla_atlas/nvmath/KahanSum.h
deleted file mode 100644
index 18d475e7cb..0000000000
--- a/thirdparty/thekla_atlas/nvmath/KahanSum.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#pragma once
-#ifndef NV_MATH_KAHANSUM_H
-#define NV_MATH_KAHANSUM_H
-
-#include "nvmath.h"
-
-namespace nv
-{
-
- class KahanSum
- {
- public:
- KahanSum() : accum(0.0f), err(0) {};
-
- void add(float f)
- {
- float compensated = f + err;
- float tmp = accum + compensated;
- err = accum - tmp;
- err += compensated;
- accum = tmp;
- }
-
- float sum() const
- {
- return accum;
- }
-
- private:
- float accum;
- float err;
- };
-
-} // nv namespace
-
-
-#endif // NV_MATH_KAHANSUM_H
diff --git a/thirdparty/thekla_atlas/nvmath/Matrix.cpp b/thirdparty/thekla_atlas/nvmath/Matrix.cpp
deleted file mode 100644
index 29bd19f5f8..0000000000
--- a/thirdparty/thekla_atlas/nvmath/Matrix.cpp
+++ /dev/null
@@ -1,441 +0,0 @@
-// This code is in the public domain -- castanyo@yahoo.es
-
-#include "Matrix.inl"
-#include "Vector.inl"
-
-#include "nvcore/Array.inl"
-
-#include <float.h>
-
-#if !NV_CC_MSVC && !NV_OS_ORBIS
-#include <alloca.h>
-#endif
-
-using namespace nv;
-
-
-// Given a matrix a[1..n][1..n], this routine replaces it by the LU decomposition of a rowwise
-// permutation of itself. a and n are input. a is output, arranged as in equation (2.3.14) above;
-// indx[1..n] is an output vector that records the row permutation effected by the partial
-// pivoting; d is output as -1 depending on whether the number of row interchanges was even
-// or odd, respectively. This routine is used in combination with lubksb to solve linear equations
-// or invert a matrix.
-static bool ludcmp(float **a, int n, int *indx, float *d)
-{
- const float TINY = 1.0e-20f;
-
- float * vv = (float*)alloca(sizeof(float) * n); // vv stores the implicit scaling of each row.
-
- *d = 1.0; // No row interchanges yet.
- for (int i = 0; i < n; i++) { // Loop over rows to get the implicit scaling information.
-
- float big = 0.0;
- for (int j = 0; j < n; j++) {
- big = max(big, fabsf(a[i][j]));
- }
- if (big == 0) {
- return false; // Singular matrix
- }
-
- // No nonzero largest element.
- vv[i] = 1.0f / big; // Save the scaling.
- }
-
- for (int j = 0; j < n; j++) { // This is the loop over columns of Crout's method.
- for (int i = 0; i < j; i++) { // This is equation (2.3.12) except for i = j.
- float sum = a[i][j];
- for (int k = 0; k < i; k++) sum -= a[i][k]*a[k][j];
- a[i][j] = sum;
- }
-
- int imax = -1;
- float big = 0.0; // Initialize for the search for largest pivot element.
- for (int i = j; i < n; i++) { // This is i = j of equation (2.3.12) and i = j+ 1 : : : N
- float sum = a[i][j]; // of equation (2.3.13).
- for (int k = 0; k < j; k++) {
- sum -= a[i][k]*a[k][j];
- }
- a[i][j]=sum;
-
- float dum = vv[i]*fabs(sum);
- if (dum >= big) {
- // Is the figure of merit for the pivot better than the best so far?
- big = dum;
- imax = i;
- }
- }
- nvDebugCheck(imax != -1);
-
- if (j != imax) { // Do we need to interchange rows?
- for (int k = 0; k < n; k++) { // Yes, do so...
- swap(a[imax][k], a[j][k]);
- }
- *d = -(*d); // ...and change the parity of d.
- vv[imax]=vv[j]; // Also interchange the scale factor.
- }
-
- indx[j]=imax;
- if (a[j][j] == 0.0) a[j][j] = TINY;
-
- // If the pivot element is zero the matrix is singular (at least to the precision of the
- // algorithm). For some applications on singular matrices, it is desirable to substitute
- // TINY for zero.
- if (j != n-1) { // Now, finally, divide by the pivot element.
- float dum = 1.0f / a[j][j];
- for (int i = j+1; i < n; i++) a[i][j] *= dum;
- }
- } // Go back for the next column in the reduction.
-
- return true;
-}
-
-
-// Solves the set of n linear equations Ax = b. Here a[1..n][1..n] is input, not as the matrix
-// A but rather as its LU decomposition, determined by the routine ludcmp. indx[1..n] is input
-// as the permutation vector returned by ludcmp. b[1..n] is input as the right-hand side vector
-// B, and returns with the solution vector X. a, n, and indx are not modified by this routine
-// and can be left in place for successive calls with different right-hand sides b. This routine takes
-// into account the possibility that b will begin with many zero elements, so it is efficient for use
-// in matrix inversion.
-static void lubksb(float **a, int n, int *indx, float b[])
-{
- int ii = 0;
- for (int i=0; i<n; i++) { // When ii is set to a positive value, it will become
- int ip = indx[i]; // the index of the first nonvanishing element of b. We now
- float sum = b[ip]; // do the forward substitution, equation (2.3.6). The
- b[ip] = b[i]; // only new wrinkle is to unscramble the permutation as we go.
- if (ii != 0) {
- for (int j = ii-1; j < i; j++) sum -= a[i][j]*b[j];
- }
- else if (sum != 0.0f) {
- ii = i+1; // A nonzero element was encountered, so from now on we
- }
- b[i] = sum; // will have to do the sums in the loop above.
- }
- for (int i=n-1; i>=0; i--) { // Now we do the backsubstitution, equation (2.3.7).
- float sum = b[i];
- for (int j = i+1; j < n; j++) {
- sum -= a[i][j]*b[j];
- }
- b[i] = sum/a[i][i]; // Store a component of the solution vector X.
- } // All done!
-}
-
-
-bool nv::solveLU(const Matrix & A, const Vector4 & b, Vector4 * x)
-{
- nvDebugCheck(x != NULL);
-
- float m[4][4];
- float *a[4] = {m[0], m[1], m[2], m[3]};
- int idx[4];
- float d;
-
- for (int y = 0; y < 4; y++) {
- for (int x = 0; x < 4; x++) {
- a[x][y] = A(x, y);
- }
- }
-
- // Create LU decomposition.
- if (!ludcmp(a, 4, idx, &d)) {
- // Singular matrix.
- return false;
- }
-
- // Init solution.
- *x = b;
-
- // Do back substitution.
- lubksb(a, 4, idx, x->component);
-
- return true;
-}
-
-// @@ Not tested.
-Matrix nv::inverseLU(const Matrix & A)
-{
- Vector4 Ai[4];
-
- solveLU(A, Vector4(1, 0, 0, 0), &Ai[0]);
- solveLU(A, Vector4(0, 1, 0, 0), &Ai[1]);
- solveLU(A, Vector4(0, 0, 1, 0), &Ai[2]);
- solveLU(A, Vector4(0, 0, 0, 1), &Ai[3]);
-
- return Matrix(Ai[0], Ai[1], Ai[2], Ai[3]);
-}
-
-
-
-bool nv::solveLU(const Matrix3 & A, const Vector3 & b, Vector3 * x)
-{
- nvDebugCheck(x != NULL);
-
- float m[3][3];
- float *a[3] = {m[0], m[1], m[2]};
- int idx[3];
- float d;
-
- for (int y = 0; y < 3; y++) {
- for (int x = 0; x < 3; x++) {
- a[x][y] = A(x, y);
- }
- }
-
- // Create LU decomposition.
- if (!ludcmp(a, 3, idx, &d)) {
- // Singular matrix.
- return false;
- }
-
- // Init solution.
- *x = b;
-
- // Do back substitution.
- lubksb(a, 3, idx, x->component);
-
- return true;
-}
-
-
-bool nv::solveCramer(const Matrix & A, const Vector4 & b, Vector4 * x)
-{
- nvDebugCheck(x != NULL);
-
- *x = transform(inverseCramer(A), b);
-
- return true; // @@ Return false if determinant(A) == 0 !
-}
-
-bool nv::solveCramer(const Matrix3 & A, const Vector3 & b, Vector3 * x)
-{
- nvDebugCheck(x != NULL);
-
- const float det = A.determinant();
- if (equal(det, 0.0f)) { // @@ Use input epsilon.
- return false;
- }
-
- Matrix3 Ai = inverseCramer(A);
-
- *x = transform(Ai, b);
-
- return true;
-}
-
-
-
-// Inverse using gaussian elimination. From Jon's code.
-Matrix nv::inverse(const Matrix & m) {
-
- Matrix A = m;
- Matrix B(identity);
-
- int i, j, k;
- float max, t, det, pivot;
-
- det = 1.0;
- for (i=0; i<4; i++) { /* eliminate in column i, below diag */
- max = -1.;
- for (k=i; k<4; k++) /* find pivot for column i */
- if (fabs(A(k, i)) > max) {
- max = fabs(A(k, i));
- j = k;
- }
- if (max<=0.) return B; /* if no nonzero pivot, PUNT */
- if (j!=i) { /* swap rows i and j */
- for (k=i; k<4; k++)
- swap(A(i, k), A(j, k));
- for (k=0; k<4; k++)
- swap(B(i, k), B(j, k));
- det = -det;
- }
- pivot = A(i, i);
- det *= pivot;
- for (k=i+1; k<4; k++) /* only do elems to right of pivot */
- A(i, k) /= pivot;
- for (k=0; k<4; k++)
- B(i, k) /= pivot;
- /* we know that A(i, i) will be set to 1, so don't bother to do it */
-
- for (j=i+1; j<4; j++) { /* eliminate in rows below i */
- t = A(j, i); /* we're gonna zero this guy */
- for (k=i+1; k<4; k++) /* subtract scaled row i from row j */
- A(j, k) -= A(i, k)*t; /* (ignore k<=i, we know they're 0) */
- for (k=0; k<4; k++)
- B(j, k) -= B(i, k)*t;
- }
- }
-
- /*---------- backward elimination ----------*/
-
- for (i=4-1; i>0; i--) { /* eliminate in column i, above diag */
- for (j=0; j<i; j++) { /* eliminate in rows above i */
- t = A(j, i); /* we're gonna zero this guy */
- for (k=0; k<4; k++) /* subtract scaled row i from row j */
- B(j, k) -= B(i, k)*t;
- }
- }
-
- return B;
-}
-
-
-Matrix3 nv::inverse(const Matrix3 & m) {
-
- Matrix3 A = m;
- Matrix3 B(identity);
-
- int i, j, k;
- float max, t, det, pivot;
-
- det = 1.0;
- for (i=0; i<3; i++) { /* eliminate in column i, below diag */
- max = -1.;
- for (k=i; k<3; k++) /* find pivot for column i */
- if (fabs(A(k, i)) > max) {
- max = fabs(A(k, i));
- j = k;
- }
- if (max<=0.) return B; /* if no nonzero pivot, PUNT */
- if (j!=i) { /* swap rows i and j */
- for (k=i; k<3; k++)
- swap(A(i, k), A(j, k));
- for (k=0; k<3; k++)
- swap(B(i, k), B(j, k));
- det = -det;
- }
- pivot = A(i, i);
- det *= pivot;
- for (k=i+1; k<3; k++) /* only do elems to right of pivot */
- A(i, k) /= pivot;
- for (k=0; k<3; k++)
- B(i, k) /= pivot;
- /* we know that A(i, i) will be set to 1, so don't bother to do it */
-
- for (j=i+1; j<3; j++) { /* eliminate in rows below i */
- t = A(j, i); /* we're gonna zero this guy */
- for (k=i+1; k<3; k++) /* subtract scaled row i from row j */
- A(j, k) -= A(i, k)*t; /* (ignore k<=i, we know they're 0) */
- for (k=0; k<3; k++)
- B(j, k) -= B(i, k)*t;
- }
- }
-
- /*---------- backward elimination ----------*/
-
- for (i=3-1; i>0; i--) { /* eliminate in column i, above diag */
- for (j=0; j<i; j++) { /* eliminate in rows above i */
- t = A(j, i); /* we're gonna zero this guy */
- for (k=0; k<3; k++) /* subtract scaled row i from row j */
- B(j, k) -= B(i, k)*t;
- }
- }
-
- return B;
-}
-
-
-
-
-
-#if 0
-
-// Copyright (C) 1999-2004 Michael Garland.
-//
-// 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, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, provided that the above
-// copyright notice(s) and this permission notice appear in all copies of
-// the Software and that both the above copyright notice(s) and this
-// permission notice appear in supporting documentation.
-//
-// 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
-// OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
-// HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
-// INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
-// FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
-// NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
-// WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-//
-// Except as contained in this notice, the name of a copyright holder
-// shall not be used in advertising or otherwise to promote the sale, use
-// or other dealings in this Software without prior written authorization
-// of the copyright holder.
-
-
-// Matrix inversion code for 4x4 matrices using Gaussian elimination
-// with partial pivoting. This is a specialized version of a
-// procedure originally due to Paul Heckbert <ph@cs.cmu.edu>.
-//
-// Returns determinant of A, and B=inverse(A)
-// If matrix A is singular, returns 0 and leaves trash in B.
-//
-#define SWAP(a, b, t) {t = a; a = b; b = t;}
-double invert(Mat4& B, const Mat4& m)
-{
- Mat4 A = m;
- int i, j, k;
- double max, t, det, pivot;
-
- /*---------- forward elimination ----------*/
-
- for (i=0; i<4; i++) /* put identity matrix in B */
- for (j=0; j<4; j++)
- B(i, j) = (double)(i==j);
-
- det = 1.0;
- for (i=0; i<4; i++) { /* eliminate in column i, below diag */
- max = -1.;
- for (k=i; k<4; k++) /* find pivot for column i */
- if (fabs(A(k, i)) > max) {
- max = fabs(A(k, i));
- j = k;
- }
- if (max<=0.) return 0.; /* if no nonzero pivot, PUNT */
- if (j!=i) { /* swap rows i and j */
- for (k=i; k<4; k++)
- SWAP(A(i, k), A(j, k), t);
- for (k=0; k<4; k++)
- SWAP(B(i, k), B(j, k), t);
- det = -det;
- }
- pivot = A(i, i);
- det *= pivot;
- for (k=i+1; k<4; k++) /* only do elems to right of pivot */
- A(i, k) /= pivot;
- for (k=0; k<4; k++)
- B(i, k) /= pivot;
- /* we know that A(i, i) will be set to 1, so don't bother to do it */
-
- for (j=i+1; j<4; j++) { /* eliminate in rows below i */
- t = A(j, i); /* we're gonna zero this guy */
- for (k=i+1; k<4; k++) /* subtract scaled row i from row j */
- A(j, k) -= A(i, k)*t; /* (ignore k<=i, we know they're 0) */
- for (k=0; k<4; k++)
- B(j, k) -= B(i, k)*t;
- }
- }
-
- /*---------- backward elimination ----------*/
-
- for (i=4-1; i>0; i--) { /* eliminate in column i, above diag */
- for (j=0; j<i; j++) { /* eliminate in rows above i */
- t = A(j, i); /* we're gonna zero this guy */
- for (k=0; k<4; k++) /* subtract scaled row i from row j */
- B(j, k) -= B(i, k)*t;
- }
- }
-
- return det;
-}
-
-#endif // 0
-
-
-
diff --git a/thirdparty/thekla_atlas/nvmath/Matrix.h b/thirdparty/thekla_atlas/nvmath/Matrix.h
deleted file mode 100644
index 506bdad1ca..0000000000
--- a/thirdparty/thekla_atlas/nvmath/Matrix.h
+++ /dev/null
@@ -1,113 +0,0 @@
-// This code is in the public domain -- castanyo@yahoo.es
-
-#pragma once
-#ifndef NV_MATH_MATRIX_H
-#define NV_MATH_MATRIX_H
-
-#include "Vector.h"
-
-// - Matrices are stored in memory in *column major* order.
-// - Points are to be though of as column vectors.
-// - Transformation of a point p by a matrix M is: p' = M * p
-
-namespace nv
-{
- enum identity_t { identity };
-
- // 3x3 matrix.
- class NVMATH_CLASS Matrix3
- {
- public:
- Matrix3();
- explicit Matrix3(float f);
- explicit Matrix3(identity_t);
- Matrix3(const Matrix3 & m);
- Matrix3(Vector3::Arg v0, Vector3::Arg v1, Vector3::Arg v2);
-
- float data(uint idx) const;
- float & data(uint idx);
- float get(uint row, uint col) const;
- float operator()(uint row, uint col) const;
- float & operator()(uint row, uint col);
-
- Vector3 row(uint i) const;
- Vector3 column(uint i) const;
-
- void operator*=(float s);
- void operator/=(float s);
- void operator+=(const Matrix3 & m);
- void operator-=(const Matrix3 & m);
-
- void scale(float s);
- void scale(Vector3::Arg s);
- float determinant() const;
-
- private:
- float m_data[9];
- };
-
- // Solve equation system using LU decomposition and back-substitution.
- extern bool solveLU(const Matrix3 & m, const Vector3 & b, Vector3 * x);
-
- // Solve equation system using Cramer's inverse.
- extern bool solveCramer(const Matrix3 & A, const Vector3 & b, Vector3 * x);
-
-
- // 4x4 matrix.
- class NVMATH_CLASS Matrix
- {
- public:
- typedef Matrix const & Arg;
-
- Matrix();
- explicit Matrix(float f);
- explicit Matrix(identity_t);
- Matrix(const Matrix3 & m);
- Matrix(const Matrix & m);
- Matrix(Vector4::Arg v0, Vector4::Arg v1, Vector4::Arg v2, Vector4::Arg v3);
- //explicit Matrix(const float m[]); // m is assumed to contain 16 elements
-
- float data(uint idx) const;
- float & data(uint idx);
- float get(uint row, uint col) const;
- float operator()(uint row, uint col) const;
- float & operator()(uint row, uint col);
- const float * ptr() const;
-
- Vector4 row(uint i) const;
- Vector4 column(uint i) const;
-
- void zero();
- void identity();
-
- void scale(float s);
- void scale(Vector3::Arg s);
- void translate(Vector3::Arg t);
- void rotate(float theta, float v0, float v1, float v2);
- float determinant() const;
-
- void operator+=(const Matrix & m);
- void operator-=(const Matrix & m);
-
- void apply(Matrix::Arg m);
-
- private:
- float m_data[16];
- };
-
- // Solve equation system using LU decomposition and back-substitution.
- extern bool solveLU(const Matrix & A, const Vector4 & b, Vector4 * x);
-
- // Solve equation system using Cramer's inverse.
- extern bool solveCramer(const Matrix & A, const Vector4 & b, Vector4 * x);
-
- // Compute inverse using LU decomposition.
- extern Matrix inverseLU(const Matrix & m);
-
- // Compute inverse using Gaussian elimination and partial pivoting.
- extern Matrix inverse(const Matrix & m);
- extern Matrix3 inverse(const Matrix3 & m);
-
-} // nv namespace
-
-#endif // NV_MATH_MATRIX_H
diff --git a/thirdparty/thekla_atlas/nvmath/Matrix.inl b/thirdparty/thekla_atlas/nvmath/Matrix.inl
deleted file mode 100644
index c0d99d9fe0..0000000000
--- a/thirdparty/thekla_atlas/nvmath/Matrix.inl
+++ /dev/null
@@ -1,1274 +0,0 @@
-// This code is in the public domain -- castanyo@yahoo.es
-
-#pragma once
-#ifndef NV_MATH_MATRIX_INL
-#define NV_MATH_MATRIX_INL
-
-#include "Matrix.h"
-
-namespace nv
-{
- inline Matrix3::Matrix3() {}
-
- inline Matrix3::Matrix3(float f)
- {
- for(int i = 0; i < 9; i++) {
- m_data[i] = f;
- }
- }
-
- inline Matrix3::Matrix3(identity_t)
- {
- for(int i = 0; i < 3; i++) {
- for(int j = 0; j < 3; j++) {
- m_data[3*j+i] = (i == j) ? 1.0f : 0.0f;
- }
- }
- }
-
- inline Matrix3::Matrix3(const Matrix3 & m)
- {
- for(int i = 0; i < 9; i++) {
- m_data[i] = m.m_data[i];
- }
- }
-
- inline Matrix3::Matrix3(Vector3::Arg v0, Vector3::Arg v1, Vector3::Arg v2)
- {
- m_data[0] = v0.x; m_data[1] = v0.y; m_data[2] = v0.z;
- m_data[3] = v1.x; m_data[4] = v1.y; m_data[5] = v1.z;
- m_data[6] = v2.x; m_data[7] = v2.y; m_data[8] = v2.z;
- }
-
- inline float Matrix3::data(uint idx) const
- {
- nvDebugCheck(idx < 9);
- return m_data[idx];
- }
- inline float & Matrix3::data(uint idx)
- {
- nvDebugCheck(idx < 9);
- return m_data[idx];
- }
- inline float Matrix3::get(uint row, uint col) const
- {
- nvDebugCheck(row < 3 && col < 3);
- return m_data[col * 3 + row];
- }
- inline float Matrix3::operator()(uint row, uint col) const
- {
- nvDebugCheck(row < 3 && col < 3);
- return m_data[col * 3 + row];
- }
- inline float & Matrix3::operator()(uint row, uint col)
- {
- nvDebugCheck(row < 3 && col < 3);
- return m_data[col * 3 + row];
- }
-
- inline Vector3 Matrix3::row(uint i) const
- {
- nvDebugCheck(i < 3);
- return Vector3(get(i, 0), get(i, 1), get(i, 2));
- }
- inline Vector3 Matrix3::column(uint i) const
- {
- nvDebugCheck(i < 3);
- return Vector3(get(0, i), get(1, i), get(2, i));
- }
-
- inline void Matrix3::operator*=(float s)
- {
- for(int i = 0; i < 9; i++) {
- m_data[i] *= s;
- }
- }
-
- inline void Matrix3::operator/=(float s)
- {
- float is = 1.0f /s;
- for(int i = 0; i < 9; i++) {
- m_data[i] *= is;
- }
- }
-
- inline void Matrix3::operator+=(const Matrix3 & m)
- {
- for(int i = 0; i < 9; i++) {
- m_data[i] += m.m_data[i];
- }
- }
-
- inline void Matrix3::operator-=(const Matrix3 & m)
- {
- for(int i = 0; i < 9; i++) {
- m_data[i] -= m.m_data[i];
- }
- }
-
- inline Matrix3 operator+(const Matrix3 & a, const Matrix3 & b)
- {
- Matrix3 m = a;
- m += b;
- return m;
- }
-
- inline Matrix3 operator-(const Matrix3 & a, const Matrix3 & b)
- {
- Matrix3 m = a;
- m -= b;
- return m;
- }
-
- inline Matrix3 operator*(const Matrix3 & a, float s)
- {
- Matrix3 m = a;
- m *= s;
- return m;
- }
-
- inline Matrix3 operator*(float s, const Matrix3 & a)
- {
- Matrix3 m = a;
- m *= s;
- return m;
- }
-
- inline Matrix3 operator/(const Matrix3 & a, float s)
- {
- Matrix3 m = a;
- m /= s;
- return m;
- }
-
- inline Matrix3 mul(const Matrix3 & a, const Matrix3 & b)
- {
- Matrix3 m;
-
- for(int i = 0; i < 3; i++) {
- const float ai0 = a(i,0), ai1 = a(i,1), ai2 = a(i,2);
- m(i, 0) = ai0 * b(0,0) + ai1 * b(1,0) + ai2 * b(2,0);
- m(i, 1) = ai0 * b(0,1) + ai1 * b(1,1) + ai2 * b(2,1);
- m(i, 2) = ai0 * b(0,2) + ai1 * b(1,2) + ai2 * b(2,2);
- }
-
- return m;
- }
-
- inline Matrix3 operator*(const Matrix3 & a, const Matrix3 & b)
- {
- return mul(a, b);
- }
-
- // Transform the given 3d vector with the given matrix.
- inline Vector3 transform(const Matrix3 & m, const Vector3 & p)
- {
- return Vector3(
- p.x * m(0,0) + p.y * m(0,1) + p.z * m(0,2),
- p.x * m(1,0) + p.y * m(1,1) + p.z * m(1,2),
- p.x * m(2,0) + p.y * m(2,1) + p.z * m(2,2));
- }
-
- inline void Matrix3::scale(float s)
- {
- for (int i = 0; i < 9; i++) {
- m_data[i] *= s;
- }
- }
-
- inline void Matrix3::scale(Vector3::Arg s)
- {
- m_data[0] *= s.x; m_data[1] *= s.x; m_data[2] *= s.x;
- m_data[3] *= s.y; m_data[4] *= s.y; m_data[5] *= s.y;
- m_data[6] *= s.z; m_data[7] *= s.z; m_data[8] *= s.z;
- }
-
- inline float Matrix3::determinant() const
- {
- return
- get(0,0) * get(1,1) * get(2,2) +
- get(0,1) * get(1,2) * get(2,0) +
- get(0,2) * get(1,0) * get(2,1) -
- get(0,2) * get(1,1) * get(2,0) -
- get(0,1) * get(1,0) * get(2,2) -
- get(0,0) * get(1,2) * get(2,1);
- }
-
- // Inverse using Cramer's rule.
- inline Matrix3 inverseCramer(const Matrix3 & m)
- {
- const float det = m.determinant();
- if (equal(det, 0.0f, 0.0f)) {
- return Matrix3(0);
- }
-
- Matrix3 r;
-
- r.data(0) = - m.data(5) * m.data(7) + m.data(4) * m.data(8);
- r.data(1) = + m.data(5) * m.data(6) - m.data(3) * m.data(8);
- r.data(2) = - m.data(4) * m.data(6) + m.data(3) * m.data(7);
-
- r.data(3) = + m.data(2) * m.data(7) - m.data(1) * m.data(8);
- r.data(4) = - m.data(2) * m.data(6) + m.data(0) * m.data(8);
- r.data(5) = + m.data(1) * m.data(6) - m.data(0) * m.data(7);
-
- r.data(6) = - m.data(2) * m.data(4) + m.data(1) * m.data(5);
- r.data(7) = + m.data(2) * m.data(3) - m.data(0) * m.data(5);
- r.data(8) = - m.data(1) * m.data(3) + m.data(0) * m.data(4);
-
- r.scale(1.0f / det);
-
- return r;
- }
-
-
-
- inline Matrix::Matrix()
- {
- }
-
- inline Matrix::Matrix(float f)
- {
- for(int i = 0; i < 16; i++) {
- m_data[i] = 0.0f;
- }
- }
-
- inline Matrix::Matrix(identity_t)
- {
- for(int i = 0; i < 4; i++) {
- for(int j = 0; j < 4; j++) {
- m_data[4*j+i] = (i == j) ? 1.0f : 0.0f;
- }
- }
- }
-
- inline Matrix::Matrix(const Matrix & m)
- {
- for(int i = 0; i < 16; i++) {
- m_data[i] = m.m_data[i];
- }
- }
-
- inline Matrix::Matrix(const Matrix3 & m)
- {
- for(int i = 0; i < 3; i++) {
- for(int j = 0; j < 3; j++) {
- operator()(i, j) = m.get(i, j);
- }
- }
- for(int i = 0; i < 4; i++) {
- operator()(3, i) = 0;
- operator()(i, 3) = 0;
- }
- }
-
- inline Matrix::Matrix(Vector4::Arg v0, Vector4::Arg v1, Vector4::Arg v2, Vector4::Arg v3)
- {
- m_data[ 0] = v0.x; m_data[ 1] = v0.y; m_data[ 2] = v0.z; m_data[ 3] = v0.w;
- m_data[ 4] = v1.x; m_data[ 5] = v1.y; m_data[ 6] = v1.z; m_data[ 7] = v1.w;
- m_data[ 8] = v2.x; m_data[ 9] = v2.y; m_data[10] = v2.z; m_data[11] = v2.w;
- m_data[12] = v3.x; m_data[13] = v3.y; m_data[14] = v3.z; m_data[15] = v3.w;
- }
-
- /*inline Matrix::Matrix(const float m[])
- {
- for(int i = 0; i < 16; i++) {
- m_data[i] = m[i];
- }
- }*/
-
-
- // Accessors
- inline float Matrix::data(uint idx) const
- {
- nvDebugCheck(idx < 16);
- return m_data[idx];
- }
- inline float & Matrix::data(uint idx)
- {
- nvDebugCheck(idx < 16);
- return m_data[idx];
- }
- inline float Matrix::get(uint row, uint col) const
- {
- nvDebugCheck(row < 4 && col < 4);
- return m_data[col * 4 + row];
- }
- inline float Matrix::operator()(uint row, uint col) const
- {
- nvDebugCheck(row < 4 && col < 4);
- return m_data[col * 4 + row];
- }
- inline float & Matrix::operator()(uint row, uint col)
- {
- nvDebugCheck(row < 4 && col < 4);
- return m_data[col * 4 + row];
- }
-
- inline const float * Matrix::ptr() const
- {
- return m_data;
- }
-
- inline Vector4 Matrix::row(uint i) const
- {
- nvDebugCheck(i < 4);
- return Vector4(get(i, 0), get(i, 1), get(i, 2), get(i, 3));
- }
-
- inline Vector4 Matrix::column(uint i) const
- {
- nvDebugCheck(i < 4);
- return Vector4(get(0, i), get(1, i), get(2, i), get(3, i));
- }
-
- inline void Matrix::zero()
- {
- m_data[0] = 0; m_data[1] = 0; m_data[2] = 0; m_data[3] = 0;
- m_data[4] = 0; m_data[5] = 0; m_data[6] = 0; m_data[7] = 0;
- m_data[8] = 0; m_data[9] = 0; m_data[10] = 0; m_data[11] = 0;
- m_data[12] = 0; m_data[13] = 0; m_data[14] = 0; m_data[15] = 0;
- }
-
- inline void Matrix::identity()
- {
- m_data[0] = 1; m_data[1] = 0; m_data[2] = 0; m_data[3] = 0;
- m_data[4] = 0; m_data[5] = 1; m_data[6] = 0; m_data[7] = 0;
- m_data[8] = 0; m_data[9] = 0; m_data[10] = 1; m_data[11] = 0;
- m_data[12] = 0; m_data[13] = 0; m_data[14] = 0; m_data[15] = 1;
- }
-
- // Apply scale.
- inline void Matrix::scale(float s)
- {
- m_data[0] *= s; m_data[1] *= s; m_data[2] *= s; m_data[3] *= s;
- m_data[4] *= s; m_data[5] *= s; m_data[6] *= s; m_data[7] *= s;
- m_data[8] *= s; m_data[9] *= s; m_data[10] *= s; m_data[11] *= s;
- m_data[12] *= s; m_data[13] *= s; m_data[14] *= s; m_data[15] *= s;
- }
-
- // Apply scale.
- inline void Matrix::scale(Vector3::Arg s)
- {
- m_data[0] *= s.x; m_data[1] *= s.x; m_data[2] *= s.x; m_data[3] *= s.x;
- m_data[4] *= s.y; m_data[5] *= s.y; m_data[6] *= s.y; m_data[7] *= s.y;
- m_data[8] *= s.z; m_data[9] *= s.z; m_data[10] *= s.z; m_data[11] *= s.z;
- }
-
- // Apply translation.
- inline void Matrix::translate(Vector3::Arg t)
- {
- m_data[12] = m_data[0] * t.x + m_data[4] * t.y + m_data[8] * t.z + m_data[12];
- m_data[13] = m_data[1] * t.x + m_data[5] * t.y + m_data[9] * t.z + m_data[13];
- m_data[14] = m_data[2] * t.x + m_data[6] * t.y + m_data[10] * t.z + m_data[14];
- m_data[15] = m_data[3] * t.x + m_data[7] * t.y + m_data[11] * t.z + m_data[15];
- }
-
- Matrix rotation(float theta, float v0, float v1, float v2);
-
- // Apply rotation.
- inline void Matrix::rotate(float theta, float v0, float v1, float v2)
- {
- Matrix R(rotation(theta, v0, v1, v2));
- apply(R);
- }
-
- // Apply transform.
- inline void Matrix::apply(Matrix::Arg m)
- {
- nvDebugCheck(this != &m);
-
- for(int i = 0; i < 4; i++) {
- const float ai0 = get(i,0), ai1 = get(i,1), ai2 = get(i,2), ai3 = get(i,3);
- m_data[0 + i] = ai0 * m(0,0) + ai1 * m(1,0) + ai2 * m(2,0) + ai3 * m(3,0);
- m_data[4 + i] = ai0 * m(0,1) + ai1 * m(1,1) + ai2 * m(2,1) + ai3 * m(3,1);
- m_data[8 + i] = ai0 * m(0,2) + ai1 * m(1,2) + ai2 * m(2,2) + ai3 * m(3,2);
- m_data[12+ i] = ai0 * m(0,3) + ai1 * m(1,3) + ai2 * m(2,3) + ai3 * m(3,3);
- }
- }
-
- // Get scale matrix.
- inline Matrix scale(Vector3::Arg s)
- {
- Matrix m(identity);
- m(0,0) = s.x;
- m(1,1) = s.y;
- m(2,2) = s.z;
- return m;
- }
-
- // Get scale matrix.
- inline Matrix scale(float s)
- {
- Matrix m(identity);
- m(0,0) = m(1,1) = m(2,2) = s;
- return m;
- }
-
- // Get translation matrix.
- inline Matrix translation(Vector3::Arg t)
- {
- Matrix m(identity);
- m(0,3) = t.x;
- m(1,3) = t.y;
- m(2,3) = t.z;
- return m;
- }
-
- // Get rotation matrix.
- inline Matrix rotation(float theta, float v0, float v1, float v2)
- {
- float cost = cosf(theta);
- float sint = sinf(theta);
-
- Matrix m(identity);
-
- if( 1 == v0 && 0 == v1 && 0 == v2 ) {
- m(1,1) = cost; m(2,1) = -sint;
- m(1,2) = sint; m(2,2) = cost;
- }
- else if( 0 == v0 && 1 == v1 && 0 == v2 ) {
- m(0,0) = cost; m(2,0) = sint;
- m(1,2) = -sint; m(2,2) = cost;
- }
- else if( 0 == v0 && 0 == v1 && 1 == v2 ) {
- m(0,0) = cost; m(1,0) = -sint;
- m(0,1) = sint; m(1,1) = cost;
- }
- else {
- float a2, b2, c2;
- a2 = v0 * v0;
- b2 = v1 * v1;
- c2 = v2 * v2;
-
- float iscale = 1.0f / sqrtf(a2 + b2 + c2);
- v0 *= iscale;
- v1 *= iscale;
- v2 *= iscale;
-
- float abm, acm, bcm;
- float mcos, asin, bsin, csin;
- mcos = 1.0f - cost;
- abm = v0 * v1 * mcos;
- acm = v0 * v2 * mcos;
- bcm = v1 * v2 * mcos;
- asin = v0 * sint;
- bsin = v1 * sint;
- csin = v2 * sint;
- m(0,0) = a2 * mcos + cost;
- m(1,0) = abm - csin;
- m(2,0) = acm + bsin;
- m(3,0) = abm + csin;
- m(1,1) = b2 * mcos + cost;
- m(2,1) = bcm - asin;
- m(3,1) = acm - bsin;
- m(1,2) = bcm + asin;
- m(2,2) = c2 * mcos + cost;
- }
- return m;
- }
-
- //Matrix rotation(float yaw, float pitch, float roll);
- //Matrix skew(float angle, Vector3::Arg v1, Vector3::Arg v2);
-
- // Get frustum matrix.
- inline Matrix frustum(float xmin, float xmax, float ymin, float ymax, float zNear, float zFar)
- {
- Matrix m(0.0f);
-
- float doubleznear = 2.0f * zNear;
- float one_deltax = 1.0f / (xmax - xmin);
- float one_deltay = 1.0f / (ymax - ymin);
- float one_deltaz = 1.0f / (zFar - zNear);
-
- m(0,0) = doubleznear * one_deltax;
- m(1,1) = doubleznear * one_deltay;
- m(0,2) = (xmax + xmin) * one_deltax;
- m(1,2) = (ymax + ymin) * one_deltay;
- m(2,2) = -(zFar + zNear) * one_deltaz;
- m(3,2) = -1.0f;
- m(2,3) = -(zFar * doubleznear) * one_deltaz;
-
- return m;
- }
-
- // Get inverse frustum matrix.
- inline Matrix frustumInverse(float xmin, float xmax, float ymin, float ymax, float zNear, float zFar)
- {
- Matrix m(0.0f);
-
- float one_doubleznear = 1.0f / (2.0f * zNear);
- float one_doubleznearzfar = 1.0f / (2.0f * zNear * zFar);
-
- m(0,0) = (xmax - xmin) * one_doubleznear;
- m(0,3) = (xmax + xmin) * one_doubleznear;
- m(1,1) = (ymax - ymin) * one_doubleznear;
- m(1,3) = (ymax + ymin) * one_doubleznear;
- m(2,3) = -1;
- m(3,2) = -(zFar - zNear) * one_doubleznearzfar;
- m(3,3) = (zFar + zNear) * one_doubleznearzfar;
-
- return m;
- }
-
- // Get infinite frustum matrix.
- inline Matrix frustum(float xmin, float xmax, float ymin, float ymax, float zNear)
- {
- Matrix m(0.0f);
-
- float doubleznear = 2.0f * zNear;
- float one_deltax = 1.0f / (xmax - xmin);
- float one_deltay = 1.0f / (ymax - ymin);
- float nudge = 1.0; // 0.999;
-
- m(0,0) = doubleznear * one_deltax;
- m(1,1) = doubleznear * one_deltay;
- m(0,2) = (xmax + xmin) * one_deltax;
- m(1,2) = (ymax + ymin) * one_deltay;
- m(2,2) = -1.0f * nudge;
- m(3,2) = -1.0f;
- m(2,3) = -doubleznear * nudge;
-
- return m;
- }
-
- // Get perspective matrix.
- inline Matrix perspective(float fovy, float aspect, float zNear, float zFar)
- {
- float xmax = zNear * tan(fovy / 2);
- float xmin = -xmax;
-
- float ymax = xmax / aspect;
- float ymin = -ymax;
-
- return frustum(xmin, xmax, ymin, ymax, zNear, zFar);
- }
-
- // Get inverse perspective matrix.
- inline Matrix perspectiveInverse(float fovy, float aspect, float zNear, float zFar)
- {
- float xmax = zNear * tan(fovy / 2);
- float xmin = -xmax;
-
- float ymax = xmax / aspect;
- float ymin = -ymax;
-
- return frustumInverse(xmin, xmax, ymin, ymax, zNear, zFar);
- }
-
- // Get infinite perspective matrix.
- inline Matrix perspective(float fovy, float aspect, float zNear)
- {
- float x = zNear * tan(fovy / 2);
- float y = x / aspect;
- return frustum( -x, x, -y, y, zNear );
- }
-
- // Get matrix determinant.
- inline float Matrix::determinant() const
- {
- return
- m_data[3] * m_data[6] * m_data[ 9] * m_data[12] - m_data[2] * m_data[7] * m_data[ 9] * m_data[12] - m_data[3] * m_data[5] * m_data[10] * m_data[12] + m_data[1] * m_data[7] * m_data[10] * m_data[12] +
- m_data[2] * m_data[5] * m_data[11] * m_data[12] - m_data[1] * m_data[6] * m_data[11] * m_data[12] - m_data[3] * m_data[6] * m_data[ 8] * m_data[13] + m_data[2] * m_data[7] * m_data[ 8] * m_data[13] +
- m_data[3] * m_data[4] * m_data[10] * m_data[13] - m_data[0] * m_data[7] * m_data[10] * m_data[13] - m_data[2] * m_data[4] * m_data[11] * m_data[13] + m_data[0] * m_data[6] * m_data[11] * m_data[13] +
- m_data[3] * m_data[5] * m_data[ 8] * m_data[14] - m_data[1] * m_data[7] * m_data[ 8] * m_data[14] - m_data[3] * m_data[4] * m_data[ 9] * m_data[14] + m_data[0] * m_data[7] * m_data[ 9] * m_data[14] +
- m_data[1] * m_data[4] * m_data[11] * m_data[14] - m_data[0] * m_data[5] * m_data[11] * m_data[14] - m_data[2] * m_data[5] * m_data[ 8] * m_data[15] + m_data[1] * m_data[6] * m_data[ 8] * m_data[15] +
- m_data[2] * m_data[4] * m_data[ 9] * m_data[15] - m_data[0] * m_data[6] * m_data[ 9] * m_data[15] - m_data[1] * m_data[4] * m_data[10] * m_data[15] + m_data[0] * m_data[5] * m_data[10] * m_data[15];
- }
-
- inline Matrix transpose(Matrix::Arg m)
- {
- Matrix r;
- for (int i = 0; i < 4; i++)
- {
- for (int j = 0; j < 4; j++)
- {
- r(i, j) = m(j, i);
- }
- }
- return r;
- }
-
- // Inverse using Cramer's rule.
- inline Matrix inverseCramer(Matrix::Arg m)
- {
- Matrix r;
- r.data( 0) = m.data(6)*m.data(11)*m.data(13) - m.data(7)*m.data(10)*m.data(13) + m.data(7)*m.data(9)*m.data(14) - m.data(5)*m.data(11)*m.data(14) - m.data(6)*m.data(9)*m.data(15) + m.data(5)*m.data(10)*m.data(15);
- r.data( 1) = m.data(3)*m.data(10)*m.data(13) - m.data(2)*m.data(11)*m.data(13) - m.data(3)*m.data(9)*m.data(14) + m.data(1)*m.data(11)*m.data(14) + m.data(2)*m.data(9)*m.data(15) - m.data(1)*m.data(10)*m.data(15);
- r.data( 2) = m.data(2)*m.data( 7)*m.data(13) - m.data(3)*m.data( 6)*m.data(13) + m.data(3)*m.data(5)*m.data(14) - m.data(1)*m.data( 7)*m.data(14) - m.data(2)*m.data(5)*m.data(15) + m.data(1)*m.data( 6)*m.data(15);
- r.data( 3) = m.data(3)*m.data( 6)*m.data( 9) - m.data(2)*m.data( 7)*m.data( 9) - m.data(3)*m.data(5)*m.data(10) + m.data(1)*m.data( 7)*m.data(10) + m.data(2)*m.data(5)*m.data(11) - m.data(1)*m.data( 6)*m.data(11);
- r.data( 4) = m.data(7)*m.data(10)*m.data(12) - m.data(6)*m.data(11)*m.data(12) - m.data(7)*m.data(8)*m.data(14) + m.data(4)*m.data(11)*m.data(14) + m.data(6)*m.data(8)*m.data(15) - m.data(4)*m.data(10)*m.data(15);
- r.data( 5) = m.data(2)*m.data(11)*m.data(12) - m.data(3)*m.data(10)*m.data(12) + m.data(3)*m.data(8)*m.data(14) - m.data(0)*m.data(11)*m.data(14) - m.data(2)*m.data(8)*m.data(15) + m.data(0)*m.data(10)*m.data(15);
- r.data( 6) = m.data(3)*m.data( 6)*m.data(12) - m.data(2)*m.data( 7)*m.data(12) - m.data(3)*m.data(4)*m.data(14) + m.data(0)*m.data( 7)*m.data(14) + m.data(2)*m.data(4)*m.data(15) - m.data(0)*m.data( 6)*m.data(15);
- r.data( 7) = m.data(2)*m.data( 7)*m.data( 8) - m.data(3)*m.data( 6)*m.data( 8) + m.data(3)*m.data(4)*m.data(10) - m.data(0)*m.data( 7)*m.data(10) - m.data(2)*m.data(4)*m.data(11) + m.data(0)*m.data( 6)*m.data(11);
- r.data( 8) = m.data(5)*m.data(11)*m.data(12) - m.data(7)*m.data( 9)*m.data(12) + m.data(7)*m.data(8)*m.data(13) - m.data(4)*m.data(11)*m.data(13) - m.data(5)*m.data(8)*m.data(15) + m.data(4)*m.data( 9)*m.data(15);
- r.data( 9) = m.data(3)*m.data( 9)*m.data(12) - m.data(1)*m.data(11)*m.data(12) - m.data(3)*m.data(8)*m.data(13) + m.data(0)*m.data(11)*m.data(13) + m.data(1)*m.data(8)*m.data(15) - m.data(0)*m.data( 9)*m.data(15);
- r.data(10) = m.data(1)*m.data( 7)*m.data(12) - m.data(3)*m.data( 5)*m.data(12) + m.data(3)*m.data(4)*m.data(13) - m.data(0)*m.data( 7)*m.data(13) - m.data(1)*m.data(4)*m.data(15) + m.data(0)*m.data( 5)*m.data(15);
- r.data(11) = m.data(3)*m.data( 5)*m.data( 8) - m.data(1)*m.data( 7)*m.data( 8) - m.data(3)*m.data(4)*m.data( 9) + m.data(0)*m.data( 7)*m.data( 9) + m.data(1)*m.data(4)*m.data(11) - m.data(0)*m.data( 5)*m.data(11);
- r.data(12) = m.data(6)*m.data( 9)*m.data(12) - m.data(5)*m.data(10)*m.data(12) - m.data(6)*m.data(8)*m.data(13) + m.data(4)*m.data(10)*m.data(13) + m.data(5)*m.data(8)*m.data(14) - m.data(4)*m.data( 9)*m.data(14);
- r.data(13) = m.data(1)*m.data(10)*m.data(12) - m.data(2)*m.data( 9)*m.data(12) + m.data(2)*m.data(8)*m.data(13) - m.data(0)*m.data(10)*m.data(13) - m.data(1)*m.data(8)*m.data(14) + m.data(0)*m.data( 9)*m.data(14);
- r.data(14) = m.data(2)*m.data( 5)*m.data(12) - m.data(1)*m.data( 6)*m.data(12) - m.data(2)*m.data(4)*m.data(13) + m.data(0)*m.data( 6)*m.data(13) + m.data(1)*m.data(4)*m.data(14) - m.data(0)*m.data( 5)*m.data(14);
- r.data(15) = m.data(1)*m.data( 6)*m.data( 8) - m.data(2)*m.data( 5)*m.data( 8) + m.data(2)*m.data(4)*m.data( 9) - m.data(0)*m.data( 6)*m.data( 9) - m.data(1)*m.data(4)*m.data(10) + m.data(0)*m.data( 5)*m.data(10);
- r.scale(1.0f / m.determinant());
- return r;
- }
-
- inline Matrix isometryInverse(Matrix::Arg m)
- {
- Matrix r(identity);
-
- // transposed 3x3 upper left matrix
- for (int i = 0; i < 3; i++)
- {
- for (int j = 0; j < 3; j++)
- {
- r(i, j) = m(j, i);
- }
- }
-
- // translate by the negative offsets
- r.translate(-Vector3(m.data(12), m.data(13), m.data(14)));
-
- return r;
- }
-
- // Transform the given 3d point with the given matrix.
- inline Vector3 transformPoint(Matrix::Arg m, Vector3::Arg p)
- {
- return Vector3(
- p.x * m(0,0) + p.y * m(0,1) + p.z * m(0,2) + m(0,3),
- p.x * m(1,0) + p.y * m(1,1) + p.z * m(1,2) + m(1,3),
- p.x * m(2,0) + p.y * m(2,1) + p.z * m(2,2) + m(2,3));
- }
-
- // Transform the given 3d vector with the given matrix.
- inline Vector3 transformVector(Matrix::Arg m, Vector3::Arg p)
- {
- return Vector3(
- p.x * m(0,0) + p.y * m(0,1) + p.z * m(0,2),
- p.x * m(1,0) + p.y * m(1,1) + p.z * m(1,2),
- p.x * m(2,0) + p.y * m(2,1) + p.z * m(2,2));
- }
-
- // Transform the given 4d vector with the given matrix.
- inline Vector4 transform(Matrix::Arg m, Vector4::Arg p)
- {
- return Vector4(
- p.x * m(0,0) + p.y * m(0,1) + p.z * m(0,2) + p.w * m(0,3),
- p.x * m(1,0) + p.y * m(1,1) + p.z * m(1,2) + p.w * m(1,3),
- p.x * m(2,0) + p.y * m(2,1) + p.z * m(2,2) + p.w * m(2,3),
- p.x * m(3,0) + p.y * m(3,1) + p.z * m(3,2) + p.w * m(3,3));
- }
-
- inline Matrix mul(Matrix::Arg a, Matrix::Arg b)
- {
- // @@ Is this the right order? mul(a, b) = b * a
- Matrix m = a;
- m.apply(b);
- return m;
- }
-
- inline void Matrix::operator+=(const Matrix & m)
- {
- for(int i = 0; i < 16; i++) {
- m_data[i] += m.m_data[i];
- }
- }
-
- inline void Matrix::operator-=(const Matrix & m)
- {
- for(int i = 0; i < 16; i++) {
- m_data[i] -= m.m_data[i];
- }
- }
-
- inline Matrix operator+(const Matrix & a, const Matrix & b)
- {
- Matrix m = a;
- m += b;
- return m;
- }
-
- inline Matrix operator-(const Matrix & a, const Matrix & b)
- {
- Matrix m = a;
- m -= b;
- return m;
- }
-
-
-} // nv namespace
-
-
-#if 0 // old code.
-/** @name Special matrices. */
-//@{
-/** Generate a translation matrix. */
-void TranslationMatrix(const Vec3 & v) {
- data[0] = 1; data[1] = 0; data[2] = 0; data[3] = 0;
- data[4] = 0; data[5] = 1; data[6] = 0; data[7] = 0;
- data[8] = 0; data[9] = 0; data[10] = 1; data[11] = 0;
- data[12] = v.x; data[13] = v.y; data[14] = v.z; data[15] = 1;
-}
-
-/** Rotate theta degrees around v. */
-void RotationMatrix( float theta, float v0, float v1, float v2 ) {
- float cost = cos(theta);
- float sint = sin(theta);
-
- if( 1 == v0 && 0 == v1 && 0 == v2 ) {
- data[0] = 1.0f; data[1] = 0.0f; data[2] = 0.0f; data[3] = 0.0f;
- data[4] = 0.0f; data[5] = cost; data[6] = -sint;data[7] = 0.0f;
- data[8] = 0.0f; data[9] = sint; data[10] = cost;data[11] = 0.0f;
- data[12] = 0.0f;data[13] = 0.0f;data[14] = 0.0f;data[15] = 1.0f;
- }
- else if( 0 == v0 && 1 == v1 && 0 == v2 ) {
- data[0] = cost; data[1] = 0.0f; data[2] = sint; data[3] = 0.0f;
- data[4] = 0.0f; data[5] = 1.0f; data[6] = 0.0f; data[7] = 0.0f;
- data[8] = -sint;data[9] = 0.0f;data[10] = cost; data[11] = 0.0f;
- data[12] = 0.0f;data[13] = 0.0f;data[14] = 0.0f;data[15] = 1.0f;
- }
- else if( 0 == v0 && 0 == v1 && 1 == v2 ) {
- data[0] = cost; data[1] = -sint;data[2] = 0.0f; data[3] = 0.0f;
- data[4] = sint; data[5] = cost; data[6] = 0.0f; data[7] = 0.0f;
- data[8] = 0.0f; data[9] = 0.0f; data[10] = 1.0f;data[11] = 0.0f;
- data[12] = 0.0f;data[13] = 0.0f;data[14] = 0.0f;data[15] = 1.0f;
- }
- else {
- //we need scale a,b,c to unit length.
- float a2, b2, c2;
- a2 = v0 * v0;
- b2 = v1 * v1;
- c2 = v2 * v2;
-
- float iscale = 1.0f / sqrtf(a2 + b2 + c2);
- v0 *= iscale;
- v1 *= iscale;
- v2 *= iscale;
-
- float abm, acm, bcm;
- float mcos, asin, bsin, csin;
- mcos = 1.0f - cost;
- abm = v0 * v1 * mcos;
- acm = v0 * v2 * mcos;
- bcm = v1 * v2 * mcos;
- asin = v0 * sint;
- bsin = v1 * sint;
- csin = v2 * sint;
- data[0] = a2 * mcos + cost;
- data[1] = abm - csin;
- data[2] = acm + bsin;
- data[3] = abm + csin;
- data[4] = 0.0f;
- data[5] = b2 * mcos + cost;
- data[6] = bcm - asin;
- data[7] = acm - bsin;
- data[8] = 0.0f;
- data[9] = bcm + asin;
- data[10] = c2 * mcos + cost;
- data[11] = 0.0f;
- data[12] = 0.0f;
- data[13] = 0.0f;
- data[14] = 0.0f;
- data[15] = 1.0f;
- }
-}
-
-/*
-void SkewMatrix(float angle, const Vec3 & v1, const Vec3 & v2) {
-v1.Normalize();
-v2.Normalize();
-
-Vec3 v3;
-v3.Cross(v1, v2);
-v3.Normalize();
-
-// Get skew factor.
-float costheta = Vec3DotProduct(v1, v2);
-float sintheta = Real.Sqrt(1 - costheta * costheta);
-float skew = tan(Trig.DegreesToRadians(angle) + acos(sintheta)) * sintheta - costheta;
-
-// Build orthonormal matrix.
-v1 = FXVector3.Cross(v3, v2);
-v1.Normalize();
-
-Matrix R = Matrix::Identity;
-R[0, 0] = v3.X; // Not sure this is in the correct order...
-R[1, 0] = v3.Y;
-R[2, 0] = v3.Z;
-R[0, 1] = v1.X;
-R[1, 1] = v1.Y;
-R[2, 1] = v1.Z;
-R[0, 2] = v2.X;
-R[1, 2] = v2.Y;
-R[2, 2] = v2.Z;
-
-// Build skew matrix.
-Matrix S = Matrix::Identity;
-S[2, 1] = -skew;
-
-// Return skew transform.
-return R * S * R.Transpose; // Not sure this is in the correct order...
-}
-*/
-
-/**
-* Generate rotation matrix for the euler angles. This is the same as computing
-* 3 rotation matrices and multiplying them together in our custom order.
-*
-* @todo Have to recompute this code for our new convention.
-**/
-void RotationMatrix( float yaw, float pitch, float roll ) {
- float sy = sin(yaw+ToRadian(90));
- float cy = cos(yaw+ToRadian(90));
- float sp = sin(pitch-ToRadian(90));
- float cp = cos(pitch-ToRadian(90));
- float sr = sin(roll);
- float cr = cos(roll);
-
- data[0] = cr*cy + sr*sp*sy;
- data[1] = cp*sy;
- data[2] = -sr*cy + cr*sp*sy;
- data[3] = 0;
-
- data[4] = -cr*sy + sr*sp*cy;
- data[5] = cp*cy;
- data[6] = sr*sy + cr*sp*cy;
- data[7] = 0;
-
- data[8] = sr*cp;
- data[9] = -sp;
- data[10] = cr*cp;
- data[11] = 0;
-
- data[12] = 0;
- data[13] = 0;
- data[14] = 0;
- data[15] = 1;
-}
-
-/** Create a frustum matrix with the far plane at the infinity. */
-void Frustum( float xmin, float xmax, float ymin, float ymax, float zNear, float zFar ) {
- float one_deltax, one_deltay, one_deltaz, doubleznear;
-
- doubleznear = 2.0f * zNear;
- one_deltax = 1.0f / (xmax - xmin);
- one_deltay = 1.0f / (ymax - ymin);
- one_deltaz = 1.0f / (zFar - zNear);
-
- data[0] = (float)(doubleznear * one_deltax);
- data[1] = 0.0f;
- data[2] = 0.0f;
- data[3] = 0.0f;
- data[4] = 0.0f;
- data[5] = (float)(doubleznear * one_deltay);
- data[6] = 0.f;
- data[7] = 0.f;
- data[8] = (float)((xmax + xmin) * one_deltax);
- data[9] = (float)((ymax + ymin) * one_deltay);
- data[10] = (float)(-(zFar + zNear) * one_deltaz);
- data[11] = -1.f;
- data[12] = 0.f;
- data[13] = 0.f;
- data[14] = (float)(-(zFar * doubleznear) * one_deltaz);
- data[15] = 0.f;
-}
-
-/** Create a frustum matrix with the far plane at the infinity. */
-void FrustumInf( float xmin, float xmax, float ymin, float ymax, float zNear ) {
- float one_deltax, one_deltay, doubleznear, nudge;
-
- doubleznear = 2.0f * zNear;
- one_deltax = 1.0f / (xmax - xmin);
- one_deltay = 1.0f / (ymax - ymin);
- nudge = 1.0; // 0.999;
-
- data[0] = doubleznear * one_deltax;
- data[1] = 0.0f;
- data[2] = 0.0f;
- data[3] = 0.0f;
-
- data[4] = 0.0f;
- data[5] = doubleznear * one_deltay;
- data[6] = 0.f;
- data[7] = 0.f;
-
- data[8] = (xmax + xmin) * one_deltax;
- data[9] = (ymax + ymin) * one_deltay;
- data[10] = -1.0f * nudge;
- data[11] = -1.0f;
-
- data[12] = 0.f;
- data[13] = 0.f;
- data[14] = -doubleznear * nudge;
- data[15] = 0.f;
-}
-
-/** Create an inverse frustum matrix with the far plane at the infinity. */
-void FrustumInfInv( float left, float right, float bottom, float top, float zNear ) {
- // this matrix is wrong (not tested floatly) I think it should be transposed.
- data[0] = (right - left) / (2 * zNear);
- data[1] = 0;
- data[2] = 0;
- data[3] = (right + left) / (2 * zNear);
- data[4] = 0;
- data[5] = (top - bottom) / (2 * zNear);
- data[6] = 0;
- data[7] = (top + bottom) / (2 * zNear);
- data[8] = 0;
- data[9] = 0;
- data[10] = 0;
- data[11] = -1;
- data[12] = 0;
- data[13] = 0;
- data[14] = -1 / (2 * zNear);
- data[15] = 1 / (2 * zNear);
-}
-
-/** Create an homogeneous projection matrix. */
-void Perspective( float fov, float aspect, float zNear, float zFar ) {
- float xmin, xmax, ymin, ymax;
-
- xmax = zNear * tan( fov/2 );
- xmin = -xmax;
-
- ymax = xmax / aspect;
- ymin = -ymax;
-
- Frustum(xmin, xmax, ymin, ymax, zNear, zFar);
-}
-
-/** Create a projection matrix with the far plane at the infinity. */
-void PerspectiveInf( float fov, float aspect, float zNear ) {
- float x = zNear * tan( fov/2 );
- float y = x / aspect;
- FrustumInf( -x, x, -y, y, zNear );
-}
-
-/** Create an inverse projection matrix with far plane at the infinity. */
-void PerspectiveInfInv( float fov, float aspect, float zNear ) {
- float x = zNear * tan( fov/2 );
- float y = x / aspect;
- FrustumInfInv( -x, x, -y, y, zNear );
-}
-
-/** Build bone matrix from quatertion and offset. */
-void BoneMatrix(const Quat & q, const Vec3 & offset) {
- float x2, y2, z2, xx, xy, xz, yy, yz, zz, wx, wy, wz;
-
- // calculate coefficients
- x2 = q.x + q.x;
- y2 = q.y + q.y;
- z2 = q.z + q.z;
-
- xx = q.x * x2; xy = q.x * y2; xz = q.x * z2;
- yy = q.y * y2; yz = q.y * z2; zz = q.z * z2;
- wx = q.w * x2; wy = q.w * y2; wz = q.w * z2;
-
- data[0] = 1.0f - (yy + zz);
- data[1] = xy - wz;
- data[2] = xz + wy;
- data[3] = 0.0f;
-
- data[4] = xy + wz;
- data[5] = 1.0f - (xx + zz);
- data[6] = yz - wx;
- data[7] = 0.0f;
-
- data[8] = xz - wy;
- data[9] = yz + wx;
- data[10] = 1.0f - (xx + yy);
- data[11] = 0.0f;
-
- data[12] = offset.x;
- data[13] = offset.y;
- data[14] = offset.z;
- data[15] = 1.0f;
-}
-
-//@}
-
-
-/** @name Transformations: */
-//@{
-
-/** Apply a general scale. */
-void Scale( float x, float y, float z ) {
- data[0] *= x; data[4] *= y; data[8] *= z;
- data[1] *= x; data[5] *= y; data[9] *= z;
- data[2] *= x; data[6] *= y; data[10] *= z;
- data[3] *= x; data[7] *= y; data[11] *= z;
-}
-
-/** Apply a rotation of theta degrees around the axis v*/
-void Rotate( float theta, const Vec3 & v ) {
- Matrix b;
- b.RotationMatrix( theta, v[0], v[1], v[2] );
- Multiply4x3( b );
-}
-
-/** Apply a rotation of theta degrees around the axis v*/
-void Rotate( float theta, float v0, float v1, float v2 ) {
- Matrix b;
- b.RotationMatrix( theta, v0, v1, v2 );
- Multiply4x3( b );
-}
-
-/**
-* Translate the matrix by t. This is the same as multiplying by a
-* translation matrix with the given offset.
-* this = T * this
-*/
-void Translate( const Vec3 &t ) {
- data[12] = data[0] * t.x + data[4] * t.y + data[8] * t.z + data[12];
- data[13] = data[1] * t.x + data[5] * t.y + data[9] * t.z + data[13];
- data[14] = data[2] * t.x + data[6] * t.y + data[10] * t.z + data[14];
- data[15] = data[3] * t.x + data[7] * t.y + data[11] * t.z + data[15];
-}
-
-/**
-* Translate the matrix by x, y, z. This is the same as multiplying by a
-* translation matrix with the given offsets.
-*/
-void Translate( float x, float y, float z ) {
- data[12] = data[0] * x + data[4] * y + data[8] * z + data[12];
- data[13] = data[1] * x + data[5] * y + data[9] * z + data[13];
- data[14] = data[2] * x + data[6] * y + data[10] * z + data[14];
- data[15] = data[3] * x + data[7] * y + data[11] * z + data[15];
-}
-
-/** Compute the transposed matrix. */
-void Transpose() {
- piSwap(data[1], data[4]);
- piSwap(data[2], data[8]);
- piSwap(data[6], data[9]);
- piSwap(data[3], data[12]);
- piSwap(data[7], data[13]);
- piSwap(data[11], data[14]);
-}
-
-/** Compute the inverse of a rigid-body/isometry/orthonormal matrix. */
-void IsometryInverse() {
- // transposed 3x3 upper left matrix
- piSwap(data[1], data[4]);
- piSwap(data[2], data[8]);
- piSwap(data[6], data[9]);
-
- // translate by the negative offsets
- Vec3 v(-data[12], -data[13], -data[14]);
- data[12] = data[13] = data[14] = 0;
- Translate(v);
-}
-
-/** Compute the inverse of the affine portion of this matrix. */
-void AffineInverse() {
- data[12] = data[13] = data[14] = 0;
- Transpose();
-}
-//@}
-
-/** @name Matrix operations: */
-//@{
-
-/** Return the determinant of this matrix. */
-float Determinant() const {
- return data[0] * data[5] * data[10] * data[15] +
- data[1] * data[6] * data[11] * data[12] +
- data[2] * data[7] * data[ 8] * data[13] +
- data[3] * data[4] * data[ 9] * data[14] -
- data[3] * data[6] * data[ 9] * data[12] -
- data[2] * data[5] * data[ 8] * data[15] -
- data[1] * data[4] * data[11] * data[14] -
- data[0] * data[7] * data[10] * data[12];
-}
-
-
-/** Standard matrix product: this *= B. */
-void Multiply4x4( const Matrix & restrict B ) {
- Multiply4x4(*this, B);
-}
-
-/** Standard matrix product: this = A * B. this != B*/
-void Multiply4x4( const Matrix & A, const Matrix & restrict B ) {
- piDebugCheck(this != &B);
-
- for(int i = 0; i < 4; i++) {
- const float ai0 = A(i,0), ai1 = A(i,1), ai2 = A(i,2), ai3 = A(i,3);
- GetElem(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0) + ai3 * B(3,0);
- GetElem(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1) + ai3 * B(3,1);
- GetElem(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2) + ai3 * B(3,2);
- GetElem(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3 * B(3,3);
- }
-
- /* Unrolled but does not allow this == A
- data[0] = A.data[0] * B.data[0] + A.data[4] * B.data[1] + A.data[8] * B.data[2] + A.data[12] * B.data[3];
- data[1] = A.data[1] * B.data[0] + A.data[5] * B.data[1] + A.data[9] * B.data[2] + A.data[13] * B.data[3];
- data[2] = A.data[2] * B.data[0] + A.data[6] * B.data[1] + A.data[10] * B.data[2] + A.data[14] * B.data[3];
- data[3] = A.data[3] * B.data[0] + A.data[7] * B.data[1] + A.data[11] * B.data[2] + A.data[15] * B.data[3];
- data[4] = A.data[0] * B.data[4] + A.data[4] * B.data[5] + A.data[8] * B.data[6] + A.data[12] * B.data[7];
- data[5] = A.data[1] * B.data[4] + A.data[5] * B.data[5] + A.data[9] * B.data[6] + A.data[13] * B.data[7];
- data[6] = A.data[2] * B.data[4] + A.data[6] * B.data[5] + A.data[10] * B.data[6] + A.data[14] * B.data[7];
- data[7] = A.data[3] * B.data[4] + A.data[7] * B.data[5] + A.data[11] * B.data[6] + A.data[15] * B.data[7];
- data[8] = A.data[0] * B.data[8] + A.data[4] * B.data[9] + A.data[8] * B.data[10] + A.data[12] * B.data[11];
- data[9] = A.data[1] * B.data[8] + A.data[5] * B.data[9] + A.data[9] * B.data[10] + A.data[13] * B.data[11];
- data[10]= A.data[2] * B.data[8] + A.data[6] * B.data[9] + A.data[10] * B.data[10] + A.data[14] * B.data[11];
- data[11]= A.data[3] * B.data[8] + A.data[7] * B.data[9] + A.data[11] * B.data[10] + A.data[15] * B.data[11];
- data[12]= A.data[0] * B.data[12] + A.data[4] * B.data[13] + A.data[8] * B.data[14] + A.data[12] * B.data[15];
- data[13]= A.data[1] * B.data[12] + A.data[5] * B.data[13] + A.data[9] * B.data[14] + A.data[13] * B.data[15];
- data[14]= A.data[2] * B.data[12] + A.data[6] * B.data[13] + A.data[10] * B.data[14] + A.data[14] * B.data[15];
- data[15]= A.data[3] * B.data[12] + A.data[7] * B.data[13] + A.data[11] * B.data[14] + A.data[15] * B.data[15];
- */
-}
-
-/** Standard matrix product: this *= B. */
-void Multiply4x3( const Matrix & restrict B ) {
- Multiply4x3(*this, B);
-}
-
-/** Standard product of matrices, where the last row is [0 0 0 1]. */
-void Multiply4x3( const Matrix & A, const Matrix & restrict B ) {
- piDebugCheck(this != &B);
-
- for(int i = 0; i < 3; i++) {
- const float ai0 = A(i,0), ai1 = A(i,1), ai2 = A(i,2), ai3 = A(i,3);
- GetElem(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0) + ai3 * B(3,0);
- GetElem(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1) + ai3 * B(3,1);
- GetElem(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2) + ai3 * B(3,2);
- GetElem(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3 * B(3,3);
- }
- data[3] = 0.0f; data[7] = 0.0f; data[11] = 0.0f; data[15] = 1.0f;
-
- /* Unrolled but does not allow this == A
- data[0] = a.data[0] * b.data[0] + a.data[4] * b.data[1] + a.data[8] * b.data[2] + a.data[12] * b.data[3];
- data[1] = a.data[1] * b.data[0] + a.data[5] * b.data[1] + a.data[9] * b.data[2] + a.data[13] * b.data[3];
- data[2] = a.data[2] * b.data[0] + a.data[6] * b.data[1] + a.data[10] * b.data[2] + a.data[14] * b.data[3];
- data[3] = 0.0f;
- data[4] = a.data[0] * b.data[4] + a.data[4] * b.data[5] + a.data[8] * b.data[6] + a.data[12] * b.data[7];
- data[5] = a.data[1] * b.data[4] + a.data[5] * b.data[5] + a.data[9] * b.data[6] + a.data[13] * b.data[7];
- data[6] = a.data[2] * b.data[4] + a.data[6] * b.data[5] + a.data[10] * b.data[6] + a.data[14] * b.data[7];
- data[7] = 0.0f;
- data[8] = a.data[0] * b.data[8] + a.data[4] * b.data[9] + a.data[8] * b.data[10] + a.data[12] * b.data[11];
- data[9] = a.data[1] * b.data[8] + a.data[5] * b.data[9] + a.data[9] * b.data[10] + a.data[13] * b.data[11];
- data[10]= a.data[2] * b.data[8] + a.data[6] * b.data[9] + a.data[10] * b.data[10] + a.data[14] * b.data[11];
- data[11]= 0.0f;
- data[12]= a.data[0] * b.data[12] + a.data[4] * b.data[13] + a.data[8] * b.data[14] + a.data[12] * b.data[15];
- data[13]= a.data[1] * b.data[12] + a.data[5] * b.data[13] + a.data[9] * b.data[14] + a.data[13] * b.data[15];
- data[14]= a.data[2] * b.data[12] + a.data[6] * b.data[13] + a.data[10] * b.data[14] + a.data[14] * b.data[15];
- data[15]= 1.0f;
- */
-}
-//@}
-
-
-/** @name Vector operations: */
-//@{
-
-/** Transform 3d vector (w=0). */
-void TransformVec3(const Vec3 & restrict orig, Vec3 * restrict dest) const {
- piDebugCheck(&orig != dest);
- dest->x = orig.x * data[0] + orig.y * data[4] + orig.z * data[8];
- dest->y = orig.x * data[1] + orig.y * data[5] + orig.z * data[9];
- dest->z = orig.x * data[2] + orig.y * data[6] + orig.z * data[10];
-}
-/** Transform 3d vector by the transpose (w=0). */
-void TransformVec3T(const Vec3 & restrict orig, Vec3 * restrict dest) const {
- piDebugCheck(&orig != dest);
- dest->x = orig.x * data[0] + orig.y * data[1] + orig.z * data[2];
- dest->y = orig.x * data[4] + orig.y * data[5] + orig.z * data[6];
- dest->z = orig.x * data[8] + orig.y * data[9] + orig.z * data[10];
-}
-
-/** Transform a 3d homogeneous vector, where the fourth coordinate is assumed to be 1. */
-void TransformPoint(const Vec3 & restrict orig, Vec3 * restrict dest) const {
- piDebugCheck(&orig != dest);
- dest->x = orig.x * data[0] + orig.y * data[4] + orig.z * data[8] + data[12];
- dest->y = orig.x * data[1] + orig.y * data[5] + orig.z * data[9] + data[13];
- dest->z = orig.x * data[2] + orig.y * data[6] + orig.z * data[10] + data[14];
-}
-
-/** Transform a point, normalize it, and return w. */
-float TransformPointAndNormalize(const Vec3 & restrict orig, Vec3 * restrict dest) const {
- piDebugCheck(&orig != dest);
- float w;
- dest->x = orig.x * data[0] + orig.y * data[4] + orig.z * data[8] + data[12];
- dest->y = orig.x * data[1] + orig.y * data[5] + orig.z * data[9] + data[13];
- dest->z = orig.x * data[2] + orig.y * data[6] + orig.z * data[10] + data[14];
- w = 1 / (orig.x * data[3] + orig.y * data[7] + orig.z * data[11] + data[15]);
- *dest *= w;
- return w;
-}
-
-/** Transform a point and return w. */
-float TransformPointReturnW(const Vec3 & restrict orig, Vec3 * restrict dest) const {
- piDebugCheck(&orig != dest);
- dest->x = orig.x * data[0] + orig.y * data[4] + orig.z * data[8] + data[12];
- dest->y = orig.x * data[1] + orig.y * data[5] + orig.z * data[9] + data[13];
- dest->z = orig.x * data[2] + orig.y * data[6] + orig.z * data[10] + data[14];
- return orig.x * data[3] + orig.y * data[7] + orig.z * data[11] + data[15];
-}
-
-/** Transform a normalized 3d point by a 4d matrix and return the resulting 4d vector. */
-void TransformVec4(const Vec3 & orig, Vec4 * dest) const {
- dest->x = orig.x * data[0] + orig.y * data[4] + orig.z * data[8] + data[12];
- dest->y = orig.x * data[1] + orig.y * data[5] + orig.z * data[9] + data[13];
- dest->z = orig.x * data[2] + orig.y * data[6] + orig.z * data[10] + data[14];
- dest->w = orig.x * data[3] + orig.y * data[7] + orig.z * data[11] + data[15];
-}
-//@}
-
-/** @name Matrix analysis. */
-//@{
-
-/** Get the ZYZ euler angles from the matrix. Assumes the matrix is orthonormal. */
-void GetEulerAnglesZYZ(float * s, float * t, float * r) const {
- if( GetElem(2,2) < 1.0f ) {
- if( GetElem(2,2) > -1.0f ) {
- // cs*ct*cr-ss*sr -ss*ct*cr-cs*sr st*cr
- // cs*ct*sr+ss*cr -ss*ct*sr+cs*cr st*sr
- // -cs*st ss*st ct
- *s = atan2(GetElem(1,2), -GetElem(0,2));
- *t = acos(GetElem(2,2));
- *r = atan2(GetElem(2,1), GetElem(2,0));
- }
- else {
- // -c(s-r) s(s-r) 0
- // s(s-r) c(s-r) 0
- // 0 0 -1
- *s = atan2(GetElem(0, 1), -GetElem(0, 0)); // = s-r
- *t = PI;
- *r = 0;
- }
- }
- else {
- // c(s+r) -s(s+r) 0
- // s(s+r) c(s+r) 0
- // 0 0 1
- *s = atan2(GetElem(0, 1), GetElem(0, 0)); // = s+r
- *t = 0;
- *r = 0;
- }
-}
-
-//@}
-
-MATHLIB_API friend PiStream & operator<< ( PiStream & s, Matrix & m );
-
-/** Print to debug output. */
-void Print() const {
- piDebug( "[ %5.2f %5.2f %5.2f %5.2f ]\n", data[0], data[4], data[8], data[12] );
- piDebug( "[ %5.2f %5.2f %5.2f %5.2f ]\n", data[1], data[5], data[9], data[13] );
- piDebug( "[ %5.2f %5.2f %5.2f %5.2f ]\n", data[2], data[6], data[10], data[14] );
- piDebug( "[ %5.2f %5.2f %5.2f %5.2f ]\n", data[3], data[7], data[11], data[15] );
-}
-
-
-public:
-
- float data[16];
-
-};
-#endif
-
-
-#endif // NV_MATH_MATRIX_INL
diff --git a/thirdparty/thekla_atlas/nvmath/Morton.h b/thirdparty/thekla_atlas/nvmath/Morton.h
deleted file mode 100644
index 10e0d8152a..0000000000
--- a/thirdparty/thekla_atlas/nvmath/Morton.h
+++ /dev/null
@@ -1,83 +0,0 @@
-
-// Code from ryg:
-// http://fgiesen.wordpress.com/2009/12/13/decoding-morton-codes/
-
-
-// "Insert" a 0 bit after each of the 16 low bits of x
-inline uint32 part1By1(uint32 x)
-{
- x &= 0x0000ffff; // x = ---- ---- ---- ---- fedc ba98 7654 3210
- x = (x ^ (x << 8)) & 0x00ff00ff; // x = ---- ---- fedc ba98 ---- ---- 7654 3210
- x = (x ^ (x << 4)) & 0x0f0f0f0f; // x = ---- fedc ---- ba98 ---- 7654 ---- 3210
- x = (x ^ (x << 2)) & 0x33333333; // x = --fe --dc --ba --98 --76 --54 --32 --10
- x = (x ^ (x << 1)) & 0x55555555; // x = -f-e -d-c -b-a -9-8 -7-6 -5-4 -3-2 -1-0
- return x;
-}
-
-// "Insert" two 0 bits after each of the 10 low bits of x
-inline uint32 part1By2(uint32 x)
-{
- x &= 0x000003ff; // x = ---- ---- ---- ---- ---- --98 7654 3210
- x = (x ^ (x << 16)) & 0xff0000ff; // x = ---- --98 ---- ---- ---- ---- 7654 3210
- x = (x ^ (x << 8)) & 0x0300f00f; // x = ---- --98 ---- ---- 7654 ---- ---- 3210
- x = (x ^ (x << 4)) & 0x030c30c3; // x = ---- --98 ---- 76-- --54 ---- 32-- --10
- x = (x ^ (x << 2)) & 0x09249249; // x = ---- 9--8 --7- -6-- 5--4 --3- -2-- 1--0
- return x;
-}
-
-inline uint32 encodeMorton2(uint32 x, uint32 y)
-{
- return (part1By1(y) << 1) + part1By1(x);
-}
-
-inline uint32 encodeMorton3(uint32 x, uint32 y, uint32 z)
-{
- return (part1By2(z) << 2) + (part1By2(y) << 1) + part1By2(x);
-}
-
-// Inverse of part1By1 - "delete" all odd-indexed bits
-inline uint32 compact1By1(uint32 x)
-{
- x &= 0x55555555; // x = -f-e -d-c -b-a -9-8 -7-6 -5-4 -3-2 -1-0
- x = (x ^ (x >> 1)) & 0x33333333; // x = --fe --dc --ba --98 --76 --54 --32 --10
- x = (x ^ (x >> 2)) & 0x0f0f0f0f; // x = ---- fedc ---- ba98 ---- 7654 ---- 3210
- x = (x ^ (x >> 4)) & 0x00ff00ff; // x = ---- ---- fedc ba98 ---- ---- 7654 3210
- x = (x ^ (x >> 8)) & 0x0000ffff; // x = ---- ---- ---- ---- fedc ba98 7654 3210
- return x;
-}
-
-// Inverse of part1By2 - "delete" all bits not at positions divisible by 3
-inline uint32 compact1By2(uint32 x)
-{
- x &= 0x09249249; // x = ---- 9--8 --7- -6-- 5--4 --3- -2-- 1--0
- x = (x ^ (x >> 2)) & 0x030c30c3; // x = ---- --98 ---- 76-- --54 ---- 32-- --10
- x = (x ^ (x >> 4)) & 0x0300f00f; // x = ---- --98 ---- ---- 7654 ---- ---- 3210
- x = (x ^ (x >> 8)) & 0xff0000ff; // x = ---- --98 ---- ---- ---- ---- 7654 3210
- x = (x ^ (x >> 16)) & 0x000003ff; // x = ---- ---- ---- ---- ---- --98 7654 3210
- return x;
-}
-
-inline uint32 decodeMorton2X(uint32 code)
-{
- return compact1By1(code >> 0);
-}
-
-inline uint32 decodeMorton2Y(uint32 code)
-{
- return compact1By1(code >> 1);
-}
-
-inline uint32 decodeMorton3X(uint32 code)
-{
- return compact1By2(code >> 0);
-}
-
-inline uint32 decodeMorton3Y(uint32 code)
-{
- return compact1By2(code >> 1);
-}
-
-inline uint32 decodeMorton3Z(uint32 code)
-{
- return compact1By2(code >> 2);
-} \ No newline at end of file
diff --git a/thirdparty/thekla_atlas/nvmath/Plane.cpp b/thirdparty/thekla_atlas/nvmath/Plane.cpp
deleted file mode 100644
index 8b54f829ad..0000000000
--- a/thirdparty/thekla_atlas/nvmath/Plane.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-// This code is in the public domain -- castanyo@yahoo.es
-
-#include "Plane.h"
-#include "Plane.inl"
-#include "Matrix.inl"
-
-namespace nv
-{
- Plane transformPlane(const Matrix & m, const Plane & p)
- {
- Vector3 newVec = transformVector(m, p.vector());
-
- Vector3 ptInPlane = p.offset() * p.vector();
- ptInPlane = transformPoint(m, ptInPlane);
-
- return Plane(newVec, ptInPlane);
- }
-
- Vector3 planeIntersection(const Plane & a, const Plane & b, const Plane & c)
- {
- return dot(a.vector(), cross(b.vector(), c.vector())) * (
- a.offset() * cross(b.vector(), c.vector()) +
- c.offset() * cross(a.vector(), b.vector()) +
- b.offset() * cross(c.vector(), a.vector()));
- }
-
-} // nv namespace
diff --git a/thirdparty/thekla_atlas/nvmath/Plane.h b/thirdparty/thekla_atlas/nvmath/Plane.h
deleted file mode 100644
index dc468b28e2..0000000000
--- a/thirdparty/thekla_atlas/nvmath/Plane.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#pragma once
-#ifndef NV_MATH_PLANE_H
-#define NV_MATH_PLANE_H
-
-#include "nvmath.h"
-#include "Vector.h"
-
-namespace nv
-{
- class Matrix;
-
- class NVMATH_CLASS Plane
- {
- public:
- Plane();
- Plane(float x, float y, float z, float w);
- Plane(const Vector4 & v);
- Plane(const Vector3 & v, float d);
- Plane(const Vector3 & normal, const Vector3 & point);
- Plane(const Vector3 & v0, const Vector3 & v1, const Vector3 & v2);
-
- const Plane & operator=(const Plane & v);
-
- Vector3 vector() const;
- float offset() const;
- Vector3 normal() const;
-
- void operator*=(float s);
-
- Vector4 v;
- };
-
- Plane transformPlane(const Matrix &, const Plane &);
-
- Vector3 planeIntersection(const Plane & a, const Plane & b, const Plane & c);
-
-
-} // nv namespace
-
-#endif // NV_MATH_PLANE_H
diff --git a/thirdparty/thekla_atlas/nvmath/Plane.inl b/thirdparty/thekla_atlas/nvmath/Plane.inl
deleted file mode 100644
index 2277e38cd5..0000000000
--- a/thirdparty/thekla_atlas/nvmath/Plane.inl
+++ /dev/null
@@ -1,50 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#pragma once
-#ifndef NV_MATH_PLANE_INL
-#define NV_MATH_PLANE_INL
-
-#include "Plane.h"
-#include "Vector.inl"
-
-namespace nv
-{
- inline Plane::Plane() {}
- inline Plane::Plane(float x, float y, float z, float w) : v(x, y, z, w) {}
- inline Plane::Plane(const Vector4 & v) : v(v) {}
- inline Plane::Plane(const Vector3 & v, float d) : v(v, d) {}
- inline Plane::Plane(const Vector3 & normal, const Vector3 & point) : v(normal, -dot(normal, point)) {}
- inline Plane::Plane(const Vector3 & v0, const Vector3 & v1, const Vector3 & v2) {
- Vector3 n = cross(v1-v0, v2-v0);
- float d = -dot(n, v0);
- v = Vector4(n, d);
- }
-
- inline const Plane & Plane::operator=(const Plane & p) { v = p.v; return *this; }
-
- inline Vector3 Plane::vector() const { return v.xyz(); }
- inline float Plane::offset() const { return v.w; }
- inline Vector3 Plane::normal() const { return normalize(vector(), 0.0f); }
-
- // Normalize plane.
- inline Plane normalize(const Plane & plane, float epsilon = NV_EPSILON)
- {
- const float len = length(plane.vector());
- const float inv = isZero(len, epsilon) ? 0 : 1.0f / len;
- return Plane(plane.v * inv);
- }
-
- // Get the signed distance from the given point to this plane.
- inline float distance(const Plane & plane, const Vector3 & point)
- {
- return dot(plane.vector(), point) + plane.offset();
- }
-
- inline void Plane::operator*=(float s)
- {
- v *= s;
- }
-
-} // nv namespace
-
-#endif // NV_MATH_PLANE_H
diff --git a/thirdparty/thekla_atlas/nvmath/ProximityGrid.cpp b/thirdparty/thekla_atlas/nvmath/ProximityGrid.cpp
deleted file mode 100644
index 3553e48f64..0000000000
--- a/thirdparty/thekla_atlas/nvmath/ProximityGrid.cpp
+++ /dev/null
@@ -1,158 +0,0 @@
-#include "ProximityGrid.h"
-
-#include "Box.inl"
-#include "Morton.h"
-
-
-using namespace nv;
-
-ProximityGrid::ProximityGrid() {
-}
-
-void ProximityGrid::reset() {
- cellArray.clear();
-}
-
-void ProximityGrid::init(const Array<Vector3> & pointArray) {
-
- // Compute bounding box.
- Box box;
- box.clearBounds();
-
- const uint count = pointArray.count();
-
- for (uint i = 0; i < count; i++) {
- box.addPointToBounds(pointArray[i]);
- }
-
- init(box, count);
-
- // Insert all points.
- for (uint i = 0; i < count; i++) {
- add(pointArray[i], i);
- }
-}
-
-
-void ProximityGrid::init(const Box & box, uint count) {
- reset();
-
- // Determine grid size.
- float cellWidth;
-
- Vector3 diagonal = box.extents() * 2.f;
- float volume = box.volume();
-
- if (equal(volume, 0)) {
- // Degenerate box, treat like a quad.
- Vector2 quad;
- if (diagonal.x < diagonal.y && diagonal.x < diagonal.z) {
- quad.x = diagonal.y;
- quad.y = diagonal.z;
- }
- else if (diagonal.y < diagonal.x && diagonal.y < diagonal.z) {
- quad.x = diagonal.x;
- quad.y = diagonal.z;
- }
- else {
- quad.x = diagonal.x;
- quad.y = diagonal.y;
- }
-
- float cellArea = quad.x * quad.y / count;
- cellWidth = sqrtf(cellArea); // pow(cellArea, 1.0f / 2.0f);
- }
- else {
- // Ideally we want one cell per point.
- float cellVolume = volume / count;
- cellWidth = pow(cellVolume, 1.0f / 3.0f);
- }
-
- nvDebugCheck(cellWidth != 0);
-
- sx = max(1, ftoi_ceil(diagonal.x / cellWidth));
- sy = max(1, ftoi_ceil(diagonal.y / cellWidth));
- sz = max(1, ftoi_ceil(diagonal.z / cellWidth));
-
- invCellSize.x = float(sx) / diagonal.x;
- invCellSize.y = float(sy) / diagonal.y;
- invCellSize.z = float(sz) / diagonal.z;
-
- cellArray.resize(sx * sy * sz);
-
- corner = box.minCorner; // @@ Align grid better?
-}
-
-// Gather all points inside the given sphere.
-// Radius is assumed to be small, so we don't bother culling the cells.
-void ProximityGrid::gather(const Vector3 & position, float radius, Array<uint> & indexArray) {
- int x0 = index_x(position.x - radius);
- int x1 = index_x(position.x + radius);
-
- int y0 = index_y(position.y - radius);
- int y1 = index_y(position.y + radius);
-
- int z0 = index_z(position.z - radius);
- int z1 = index_z(position.z + radius);
-
- for (int z = z0; z <= z1; z++) {
- for (int y = y0; y <= y1; y++) {
- for (int x = x0; x <= x1; x++) {
- int idx = index(x, y, z);
- indexArray.append(cellArray[idx].indexArray);
- }
- }
- }
-}
-
-
-uint32 ProximityGrid::mortonCount() const {
- uint64 s = U64(max3(sx, sy, sz));
- s = nextPowerOfTwo(s);
-
- if (s > 1024) {
- return U32(s * s * min3(sx, sy, sz));
- }
-
- return U32(s * s * s);
-}
-
-int ProximityGrid::mortonIndex(uint32 code) const {
- uint32 x, y, z;
-
- uint s = U32(max3(sx, sy, sz));
- if (s > 1024) {
- // Use layered two-dimensional morton order.
- s = nextPowerOfTwo(s);
- uint layer = code / (s * s);
- code = code % (s * s);
-
- uint layer_count = U32(min3(sx, sy, sz));
- if (sx == layer_count) {
- x = layer;
- y = decodeMorton2X(code);
- z = decodeMorton2Y(code);
- }
- else if (sy == layer_count) {
- x = decodeMorton2Y(code);
- y = layer;
- z = decodeMorton2X(code);
- }
- else /*if (sz == layer_count)*/ {
- x = decodeMorton2X(code);
- y = decodeMorton2Y(code);
- z = layer;
- }
- }
- else {
- x = decodeMorton3X(code);
- y = decodeMorton3Y(code);
- z = decodeMorton3Z(code);
- }
-
- if (x >= U32(sx) || y >= U32(sy) || z >= U32(sz)) {
- return -1;
- }
-
- return index(x, y, z);
-}
diff --git a/thirdparty/thekla_atlas/nvmath/ProximityGrid.h b/thirdparty/thekla_atlas/nvmath/ProximityGrid.h
deleted file mode 100644
index a21bb3bd68..0000000000
--- a/thirdparty/thekla_atlas/nvmath/ProximityGrid.h
+++ /dev/null
@@ -1,99 +0,0 @@
-#pragma once
-#ifndef NV_MATH_PROXIMITYGRID_H
-#define NV_MATH_PROXIMITYGRID_H
-
-#include "Vector.h"
-#include "ftoi.h"
-
-#include "nvcore/Array.inl"
-
-
-// A simple, dynamic proximity grid based on Jon's code.
-// Instead of storing pointers here I store indices.
-
-namespace nv {
-
- class Box;
-
- struct Cell {
- Array<uint> indexArray;
- };
-
- struct ProximityGrid {
- ProximityGrid();
-
- void reset();
- void init(const Array<Vector3> & pointArray);
- void init(const Box & box, uint count);
-
- int index_x(float x) const;
- int index_y(float y) const;
- int index_z(float z) const;
- int index(int x, int y, int z) const;
- int index(const Vector3 & pos) const;
-
- uint32 mortonCount() const;
- int mortonIndex(uint32 code) const;
-
- void add(const Vector3 & pos, uint key);
- bool remove(const Vector3 & pos, uint key);
-
- void gather(const Vector3 & pos, float radius, Array<uint> & indices);
-
- Array<Cell> cellArray;
-
- Vector3 corner;
- Vector3 invCellSize;
- int sx, sy, sz;
- };
-
- // For morton traversal, do:
- // for (int code = 0; code < mortonCount(); code++) {
- // int idx = mortonIndex(code);
- // if (idx < 0) continue;
- // }
-
-
-
- inline int ProximityGrid::index_x(float x) const {
- return clamp(ftoi_floor((x - corner.x) * invCellSize.x), 0, sx-1);
- }
-
- inline int ProximityGrid::index_y(float y) const {
- return clamp(ftoi_floor((y - corner.y) * invCellSize.y), 0, sy-1);
- }
-
- inline int ProximityGrid::index_z(float z) const {
- return clamp(ftoi_floor((z - corner.z) * invCellSize.z), 0, sz-1);
- }
-
- inline int ProximityGrid::index(int x, int y, int z) const {
- nvDebugCheck(x >= 0 && x < sx);
- nvDebugCheck(y >= 0 && y < sy);
- nvDebugCheck(z >= 0 && z < sz);
- int idx = (z * sy + y) * sx + x;
- nvDebugCheck(idx >= 0 && uint(idx) < cellArray.count());
- return idx;
- }
-
- inline int ProximityGrid::index(const Vector3 & pos) const {
- int x = index_x(pos.x);
- int y = index_y(pos.y);
- int z = index_z(pos.z);
- return index(x, y, z);
- }
-
-
- inline void ProximityGrid::add(const Vector3 & pos, uint key) {
- uint idx = index(pos);
- cellArray[idx].indexArray.append(key);
- }
-
- inline bool ProximityGrid::remove(const Vector3 & pos, uint key) {
- uint idx = index(pos);
- return cellArray[idx].indexArray.remove(key);
- }
-
-} // nv namespace
-
-#endif // NV_MATH_PROXIMITYGRID_H
diff --git a/thirdparty/thekla_atlas/nvmath/Quaternion.h b/thirdparty/thekla_atlas/nvmath/Quaternion.h
deleted file mode 100644
index dc5219e5e4..0000000000
--- a/thirdparty/thekla_atlas/nvmath/Quaternion.h
+++ /dev/null
@@ -1,213 +0,0 @@
-// This code is in the public domain -- castano@gmail.com
-
-#pragma once
-#ifndef NV_MATH_QUATERNION_H
-#define NV_MATH_QUATERNION_H
-
-#include "nvmath/nvmath.h"
-#include "nvmath/Vector.inl" // @@ Do not include inl files from header files.
-#include "nvmath/Matrix.h"
-
-namespace nv
-{
-
- class NVMATH_CLASS Quaternion
- {
- public:
- typedef Quaternion const & Arg;
-
- Quaternion();
- explicit Quaternion(float f);
- Quaternion(float x, float y, float z, float w);
- Quaternion(Vector4::Arg v);
-
- const Quaternion & operator=(Quaternion::Arg v);
-
- Vector4 asVector() const;
-
- union {
- struct {
- float x, y, z, w;
- };
- float component[4];
- };
- };
-
- inline Quaternion::Quaternion() {}
- inline Quaternion::Quaternion(float f) : x(f), y(f), z(f), w(f) {}
- inline Quaternion::Quaternion(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {}
- inline Quaternion::Quaternion(Vector4::Arg v) : x(v.x), y(v.y), z(v.z), w(v.w) {}
-
- // @@ Move all these to Quaternion.inl!
-
- inline const Quaternion & Quaternion::operator=(Quaternion::Arg v) {
- x = v.x;
- y = v.y;
- z = v.z;
- w = v.w;
- return *this;
- }
-
- inline Vector4 Quaternion::asVector() const { return Vector4(x, y, z, w); }
-
- inline Quaternion mul(Quaternion::Arg a, Quaternion::Arg b)
- {
- return Quaternion(
- + a.x*b.w + a.y*b.z - a.z*b.y + a.w*b.x,
- - a.x*b.z + a.y*b.w + a.z*b.x + a.w*b.y,
- + a.x*b.y - a.y*b.x + a.z*b.w + a.w*b.z,
- - a.x*b.x - a.y*b.y - a.z*b.z + a.w*b.w);
- }
-
- inline Quaternion mul(Quaternion::Arg a, Vector3::Arg b)
- {
- return Quaternion(
- + a.y*b.z - a.z*b.y + a.w*b.x,
- - a.x*b.z + a.z*b.x + a.w*b.y,
- + a.x*b.y - a.y*b.x + a.w*b.z,
- - a.x*b.x - a.y*b.y - a.z*b.z );
- }
-
- inline Quaternion mul(Vector3::Arg a, Quaternion::Arg b)
- {
- return Quaternion(
- + a.x*b.w + a.y*b.z - a.z*b.y,
- - a.x*b.z + a.y*b.w + a.z*b.x,
- + a.x*b.y - a.y*b.x + a.z*b.w,
- - a.x*b.x - a.y*b.y - a.z*b.z);
- }
-
- inline Quaternion operator *(Quaternion::Arg a, Quaternion::Arg b)
- {
- return mul(a, b);
- }
-
- inline Quaternion operator *(Quaternion::Arg a, Vector3::Arg b)
- {
- return mul(a, b);
- }
-
- inline Quaternion operator *(Vector3::Arg a, Quaternion::Arg b)
- {
- return mul(a, b);
- }
-
-
- inline Quaternion scale(Quaternion::Arg q, float s)
- {
- return scale(q.asVector(), s);
- }
- inline Quaternion operator *(Quaternion::Arg q, float s)
- {
- return scale(q, s);
- }
- inline Quaternion operator *(float s, Quaternion::Arg q)
- {
- return scale(q, s);
- }
-
- inline Quaternion scale(Quaternion::Arg q, Vector4::Arg s)
- {
- return scale(q.asVector(), s);
- }
- /*inline Quaternion operator *(Quaternion::Arg q, Vector4::Arg s)
- {
- return scale(q, s);
- }
- inline Quaternion operator *(Vector4::Arg s, Quaternion::Arg q)
- {
- return scale(q, s);
- }*/
-
- inline Quaternion conjugate(Quaternion::Arg q)
- {
- return scale(q, Vector4(-1, -1, -1, 1));
- }
-
- inline float length(Quaternion::Arg q)
- {
- return length(q.asVector());
- }
-
- inline bool isNormalized(Quaternion::Arg q, float epsilon = NV_NORMAL_EPSILON)
- {
- return equal(length(q), 1, epsilon);
- }
-
- inline Quaternion normalize(Quaternion::Arg q, float epsilon = NV_EPSILON)
- {
- float l = length(q);
- nvDebugCheck(!isZero(l, epsilon));
- Quaternion n = scale(q, 1.0f / l);
- nvDebugCheck(isNormalized(n));
- return n;
- }
-
- inline Quaternion inverse(Quaternion::Arg q)
- {
- return conjugate(normalize(q));
- }
-
- /// Create a rotation quaternion for @a angle alpha around normal vector @a v.
- inline Quaternion axisAngle(Vector3::Arg v, float alpha)
- {
- float s = sinf(alpha * 0.5f);
- float c = cosf(alpha * 0.5f);
- return Quaternion(Vector4(v * s, c));
- }
-
- inline Vector3 imag(Quaternion::Arg q)
- {
- return q.asVector().xyz();
- }
-
- inline float real(Quaternion::Arg q)
- {
- return q.w;
- }
-
-
- /// Transform vector.
- inline Vector3 transform(Quaternion::Arg q, Vector3::Arg v)
- {
- //Quaternion t = q * v * conjugate(q);
- //return imag(t);
-
- // Faster method by Fabian Giesen and others:
- // http://molecularmusings.wordpress.com/2013/05/24/a-faster-quaternion-vector-multiplication/
- // http://mollyrocket.com/forums/viewtopic.php?t=833&sid=3a84e00a70ccb046cfc87ac39881a3d0
-
- Vector3 t = 2 * cross(imag(q), v);
- return v + q.w * t + cross(imag(q), t);
- }
-
- // @@ Not tested.
- // From Insomniac's Mike Day:
- // http://www.insomniacgames.com/converting-a-rotation-matrix-to-a-quaternion/
- inline Quaternion fromMatrix(const Matrix & m) {
- if (m(2, 2) < 0) {
- if (m(0, 0) < m(1,1)) {
- float t = 1 - m(0, 0) - m(1, 1) - m(2, 2);
- return Quaternion(t, m(0,1)+m(1,0), m(2,0)+m(0,2), m(1,2)-m(2,1));
- }
- else {
- float t = 1 - m(0, 0) + m(1, 1) - m(2, 2);
- return Quaternion(t, m(0,1) + m(1,0), m(1,2) + m(2,1), m(2,0) - m(0,2));
- }
- }
- else {
- if (m(0, 0) < -m(1, 1)) {
- float t = 1 - m(0, 0) - m(1, 1) + m(2, 2);
- return Quaternion(t, m(2,0) + m(0,2), m(1,2) + m(2,1), m(0,1) - m(1,0));
- }
- else {
- float t = 1 + m(0, 0) + m(1, 1) + m(2, 2);
- return Quaternion(t, m(1,2) - m(2,1), m(2,0) - m(0,2), m(0,1) - m(1,0));
- }
- }
- }
-
-
-} // nv namespace
-
-#endif // NV_MATH_QUATERNION_H
diff --git a/thirdparty/thekla_atlas/nvmath/Random.cpp b/thirdparty/thekla_atlas/nvmath/Random.cpp
deleted file mode 100644
index 1a60e7f5e7..0000000000
--- a/thirdparty/thekla_atlas/nvmath/Random.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-// This code is in the public domain -- castanyo@yahoo.es
-
-#include <nvmath/Random.h>
-#include <time.h>
-
-using namespace nv;
-
-// Statics
-const uint16 Rand48::a0 = 0xE66D;
-const uint16 Rand48::a1 = 0xDEEC;
-const uint16 Rand48::a2 = 0x0005;
-const uint16 Rand48::c0 = 0x000B;
-
-
-/// Get a random seed based on the current time.
-uint Rand::randomSeed()
-{
- return (uint)time(NULL);
-}
-
-
-void MTRand::initialize( uint32 seed )
-{
- // Initialize generator state with seed
- // See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier.
- // In previous versions, most significant bits (MSBs) of the seed affect
- // only MSBs of the state array. Modified 9 Jan 2002 by Makoto Matsumoto.
- uint32 *s = state;
- uint32 *r = state;
- int i = 1;
- *s++ = seed & 0xffffffffUL;
- for( ; i < N; ++i )
- {
- *s++ = ( 1812433253UL * ( *r ^ (*r >> 30) ) + i ) & 0xffffffffUL;
- r++;
- }
-}
-
-
-void MTRand::reload()
-{
- // Generate N new values in state
- // Made clearer and faster by Matthew Bellew (matthew.bellew@home.com)
- uint32 *p = state;
- int i;
- for( i = N - M; i--; ++p )
- *p = twist( p[M], p[0], p[1] );
- for( i = M; --i; ++p )
- *p = twist( p[M-N], p[0], p[1] );
- *p = twist( p[M-N], p[0], state[0] );
-
- left = N, next = state;
-}
-
diff --git a/thirdparty/thekla_atlas/nvmath/Random.h b/thirdparty/thekla_atlas/nvmath/Random.h
deleted file mode 100644
index 223292706a..0000000000
--- a/thirdparty/thekla_atlas/nvmath/Random.h
+++ /dev/null
@@ -1,376 +0,0 @@
-// This code is in the public domain -- castanyo@yahoo.es
-
-#pragma once
-#ifndef NV_MATH_RANDOM_H
-#define NV_MATH_RANDOM_H
-
-#include "nvmath.h"
-#include "nvcore/Utils.h" // nextPowerOfTwo
-
-
-namespace nv
-{
-
- /// Interface of the random number generators.
- class Rand
- {
- public:
-
- virtual ~Rand() {}
-
- enum time_e { Time };
-
- /// Provide a new seed.
- virtual void seed( uint s ) { /* empty */ };
-
- /// Get an integer random number.
- virtual uint get() = 0;
-
- /// Get a random number on [0, max] interval.
- uint getRange( uint max )
- {
- if (max == 0) return 0;
- if (max == NV_UINT32_MAX) return get();
-
- const uint np2 = nextPowerOfTwo( max+1 ); // @@ This fails if max == NV_UINT32_MAX
- const uint mask = np2 - 1;
- uint n;
- do { n = get() & mask; } while( n > max );
- return n;
- }
-
- /// Random number on [0.0, 1.0] interval.
- float getFloat()
- {
- union
- {
- uint32 i;
- float f;
- } pun;
-
- pun.i = 0x3f800000UL | (get() & 0x007fffffUL);
- return pun.f - 1.0f;
- }
-
- float getFloatRange(float min, float max) {
- return getFloat() * (max - min) + min;
- }
-
- /*
- /// Random number on [0.0, 1.0] interval.
- double getReal()
- {
- return double(get()) * (1.0/4294967295.0); // 2^32-1
- }
-
- /// Random number on [0.0, 1.0) interval.
- double getRealExclusive()
- {
- return double(get()) * (1.0/4294967296.0); // 2^32
- }
- */
-
- /// Get the max value of the random number.
- uint max() const { return NV_UINT32_MAX; }
-
- // Get a random seed.
- static uint randomSeed();
-
- };
-
-
- /// Very simple random number generator with low storage requirements.
- class SimpleRand : public Rand
- {
- public:
-
- /// Constructor that uses the current time as the seed.
- SimpleRand( time_e )
- {
- seed(randomSeed());
- }
-
- /// Constructor that uses the given seed.
- SimpleRand( uint s = 0 )
- {
- seed(s);
- }
-
- /// Set the given seed.
- virtual void seed( uint s )
- {
- current = s;
- }
-
- /// Get a random number.
- virtual uint get()
- {
- return current = current * 1103515245 + 12345;
- }
-
- private:
-
- uint current;
-
- };
-
-
- /// Mersenne twister random number generator.
- class MTRand : public Rand
- {
- public:
-
- enum { N = 624 }; // length of state vector
- enum { M = 397 };
-
- /// Constructor that uses the current time as the seed.
- MTRand( time_e )
- {
- seed(randomSeed());
- }
-
- /// Constructor that uses the given seed.
- MTRand( uint s = 0 )
- {
- seed(s);
- }
-
- /// Constructor that uses the given seeds.
- NVMATH_API MTRand( const uint * seed_array, uint length );
-
-
- /// Provide a new seed.
- virtual void seed( uint s )
- {
- initialize(s);
- reload();
- }
-
- /// Get a random number between 0 - 65536.
- virtual uint get()
- {
- // Pull a 32-bit integer from the generator state
- // Every other access function simply transforms the numbers extracted here
- if( left == 0 ) {
- reload();
- }
- left--;
-
- uint s1;
- s1 = *next++;
- s1 ^= (s1 >> 11);
- s1 ^= (s1 << 7) & 0x9d2c5680U;
- s1 ^= (s1 << 15) & 0xefc60000U;
- return ( s1 ^ (s1 >> 18) );
- };
-
-
- private:
-
- NVMATH_API void initialize( uint32 seed );
- NVMATH_API void reload();
-
- uint hiBit( uint u ) const { return u & 0x80000000U; }
- uint loBit( uint u ) const { return u & 0x00000001U; }
- uint loBits( uint u ) const { return u & 0x7fffffffU; }
- uint mixBits( uint u, uint v ) const { return hiBit(u) | loBits(v); }
- uint twist( uint m, uint s0, uint s1 ) const { return m ^ (mixBits(s0,s1)>>1) ^ ((~loBit(s1)+1) & 0x9908b0dfU); }
-
- private:
-
- uint state[N]; // internal state
- uint * next; // next value to get from state
- int left; // number of values left before reload needed
-
- };
-
-
-
- /** George Marsaglia's random number generator.
- * Code based on Thatcher Ulrich public domain source code:
- * http://cvs.sourceforge.net/viewcvs.py/tu-testbed/tu-testbed/base/tu_random.cpp?rev=1.7&view=auto
- *
- * PRNG code adapted from the complimentary-multiply-with-carry
- * code in the article: George Marsaglia, "Seeds for Random Number
- * Generators", Communications of the ACM, May 2003, Vol 46 No 5,
- * pp90-93.
- *
- * The article says:
- *
- * "Any one of the choices for seed table size and multiplier will
- * provide a RNG that has passed extensive tests of randomness,
- * particularly those in [3], yet is simple and fast --
- * approximately 30 million random 32-bit integers per second on a
- * 850MHz PC. The period is a*b^n, where a is the multiplier, n
- * the size of the seed table and b=2^32-1. (a is chosen so that
- * b is a primitive root of the prime a*b^n + 1.)"
- *
- * [3] Marsaglia, G., Zaman, A., and Tsang, W. Toward a universal
- * random number generator. _Statistics and Probability Letters
- * 8_ (1990), 35-39.
- */
- class GMRand : public Rand
- {
- public:
-
- enum { SEED_COUNT = 8 };
-
- // const uint64 a = 123471786; // for SEED_COUNT=1024
- // const uint64 a = 123554632; // for SEED_COUNT=512
- // const uint64 a = 8001634; // for SEED_COUNT=255
- // const uint64 a = 8007626; // for SEED_COUNT=128
- // const uint64 a = 647535442; // for SEED_COUNT=64
- // const uint64 a = 547416522; // for SEED_COUNT=32
- // const uint64 a = 487198574; // for SEED_COUNT=16
- // const uint64 a = 716514398U; // for SEED_COUNT=8
- enum { a = 716514398U };
-
-
- GMRand( time_e )
- {
- seed(randomSeed());
- }
-
- GMRand(uint s = 987654321)
- {
- seed(s);
- }
-
-
- /// Provide a new seed.
- virtual void seed( uint s )
- {
- c = 362436;
- i = SEED_COUNT - 1;
-
- for(int i = 0; i < SEED_COUNT; i++) {
- s = s ^ (s << 13);
- s = s ^ (s >> 17);
- s = s ^ (s << 5);
- Q[i] = s;
- }
- }
-
- /// Get a random number between 0 - 65536.
- virtual uint get()
- {
- const uint32 r = 0xFFFFFFFE;
-
- uint64 t;
- uint32 x;
-
- i = (i + 1) & (SEED_COUNT - 1);
- t = a * Q[i] + c;
- c = uint32(t >> 32);
- x = uint32(t + c);
-
- if( x < c ) {
- x++;
- c++;
- }
-
- uint32 val = r - x;
- Q[i] = val;
- return val;
- };
-
-
- private:
-
- uint32 c;
- uint32 i;
- uint32 Q[8];
-
- };
-
-
- /** Random number implementation from the GNU Sci. Lib. (GSL).
- * Adapted from Nicholas Chapman version:
- *
- * Copyright (C) 1996, 1997, 1998, 1999, 2000 James Theiler, Brian Gough
- * This is the Unix rand48() generator. The generator returns the
- * upper 32 bits from each term of the sequence,
- *
- * x_{n+1} = (a x_n + c) mod m
- *
- * using 48-bit unsigned arithmetic, with a = 0x5DEECE66D , c = 0xB
- * and m = 2^48. The seed specifies the upper 32 bits of the initial
- * value, x_1, with the lower 16 bits set to 0x330E.
- *
- * The theoretical value of x_{10001} is 244131582646046.
- *
- * The period of this generator is ? FIXME (probably around 2^48).
- */
- class Rand48 : public Rand
- {
- public:
-
- Rand48( time_e )
- {
- seed(randomSeed());
- }
-
- Rand48( uint s = 0x1234ABCD )
- {
- seed(s);
- }
-
-
- /** Set the given seed. */
- virtual void seed( uint s ) {
- vstate.x0 = 0x330E;
- vstate.x1 = uint16(s & 0xFFFF);
- vstate.x2 = uint16((s >> 16) & 0xFFFF);
- }
-
- /** Get a random number. */
- virtual uint get() {
-
- advance();
-
- uint x1 = vstate.x1;
- uint x2 = vstate.x2;
- return (x2 << 16) + x1;
- }
-
-
- private:
-
- void advance()
- {
- /* work with unsigned long ints throughout to get correct integer
- promotions of any unsigned short ints */
- const uint32 x0 = vstate.x0;
- const uint32 x1 = vstate.x1;
- const uint32 x2 = vstate.x2;
-
- uint32 a;
- a = a0 * x0 + c0;
-
- vstate.x0 = uint16(a & 0xFFFF);
- a >>= 16;
-
- /* although the next line may overflow we only need the top 16 bits
- in the following stage, so it does not matter */
-
- a += a0 * x1 + a1 * x0;
- vstate.x1 = uint16(a & 0xFFFF);
-
- a >>= 16;
- a += a0 * x2 + a1 * x1 + a2 * x0;
- vstate.x2 = uint16(a & 0xFFFF);
- }
-
-
- private:
- NVMATH_API static const uint16 a0, a1, a2, c0;
-
- struct rand48_state_t {
- uint16 x0, x1, x2;
- } vstate;
-
- };
-
-} // nv namespace
-
-#endif // NV_MATH_RANDOM_H
diff --git a/thirdparty/thekla_atlas/nvmath/Solver.cpp b/thirdparty/thekla_atlas/nvmath/Solver.cpp
deleted file mode 100644
index 191793ee29..0000000000
--- a/thirdparty/thekla_atlas/nvmath/Solver.cpp
+++ /dev/null
@@ -1,744 +0,0 @@
-// This code is in the public domain -- castanyo@yahoo.es
-
-#include "Solver.h"
-#include "Sparse.h"
-
-#include "nvcore/Array.inl"
-
-using namespace nv;
-
-namespace
-{
- class Preconditioner
- {
- public:
- // Virtual dtor.
- virtual ~Preconditioner() { }
-
- // Apply preconditioning step.
- virtual void apply(const FullVector & x, FullVector & y) const = 0;
- };
-
-
- // Jacobi preconditioner.
- class JacobiPreconditioner : public Preconditioner
- {
- public:
-
- JacobiPreconditioner(const SparseMatrix & M, bool symmetric) : m_inverseDiagonal(M.width())
- {
- nvCheck(M.isSquare());
-
- for(uint x = 0; x < M.width(); x++)
- {
- float elem = M.getCoefficient(x, x);
- //nvDebugCheck( elem != 0.0f ); // This can be zero in the presence of zero area triangles.
-
- if (symmetric)
- {
- m_inverseDiagonal[x] = (elem != 0) ? 1.0f / sqrtf(fabsf(elem)) : 1.0f;
- }
- else
- {
- m_inverseDiagonal[x] = (elem != 0) ? 1.0f / elem : 1.0f;
- }
- }
- }
-
- void apply(const FullVector & x, FullVector & y) const
- {
- nvDebugCheck(x.dimension() == m_inverseDiagonal.dimension());
- nvDebugCheck(y.dimension() == m_inverseDiagonal.dimension());
-
- // @@ Wrap vector component-wise product into a separate function.
- const uint D = x.dimension();
- for (uint i = 0; i < D; i++)
- {
- y[i] = m_inverseDiagonal[i] * x[i];
- }
- }
-
- private:
-
- FullVector m_inverseDiagonal;
-
- };
-
-} // namespace
-
-
-static bool ConjugateGradientSolver(const SparseMatrix & A, const FullVector & b, FullVector & x, float epsilon);
-static bool ConjugateGradientSolver(const Preconditioner & preconditioner, const SparseMatrix & A, const FullVector & b, FullVector & x, float epsilon);
-
-
-// Solve the symmetric system: At·A·x = At·b
-bool nv::LeastSquaresSolver(const SparseMatrix & A, const FullVector & b, FullVector & x, float epsilon/*1e-5f*/)
-{
- nvDebugCheck(A.width() == x.dimension());
- nvDebugCheck(A.height() == b.dimension());
- nvDebugCheck(A.height() >= A.width()); // @@ If height == width we could solve it directly...
-
- const uint D = A.width();
-
- SparseMatrix At(A.height(), A.width());
- transpose(A, At);
-
- FullVector Atb(D);
- //mult(Transposed, A, b, Atb);
- mult(At, b, Atb);
-
- SparseMatrix AtA(D);
- //mult(Transposed, A, NoTransposed, A, AtA);
- mult(At, A, AtA);
-
- return SymmetricSolver(AtA, Atb, x, epsilon);
-}
-
-
-// See section 10.4.3 in: Mesh Parameterization: Theory and Practice, Siggraph Course Notes, August 2007
-bool nv::LeastSquaresSolver(const SparseMatrix & A, const FullVector & b, FullVector & x, const uint * lockedParameters, uint lockedCount, float epsilon/*= 1e-5f*/)
-{
- nvDebugCheck(A.width() == x.dimension());
- nvDebugCheck(A.height() == b.dimension());
- nvDebugCheck(A.height() >= A.width() - lockedCount);
-
- // @@ This is not the most efficient way of building a system with reduced degrees of freedom. It would be faster to do it on the fly.
-
- const uint D = A.width() - lockedCount;
- nvDebugCheck(D > 0);
-
- // Compute: b - Al * xl
- FullVector b_Alxl(b);
-
- for (uint y = 0; y < A.height(); y++)
- {
- const uint count = A.getRow(y).count();
- for (uint e = 0; e < count; e++)
- {
- uint column = A.getRow(y)[e].x;
-
- bool isFree = true;
- for (uint i = 0; i < lockedCount; i++)
- {
- isFree &= (lockedParameters[i] != column);
- }
-
- if (!isFree)
- {
- b_Alxl[y] -= x[column] * A.getRow(y)[e].v;
- }
- }
- }
-
- // Remove locked columns from A.
- SparseMatrix Af(D, A.height());
-
- for (uint y = 0; y < A.height(); y++)
- {
- const uint count = A.getRow(y).count();
- for (uint e = 0; e < count; e++)
- {
- uint column = A.getRow(y)[e].x;
- uint ix = column;
-
- bool isFree = true;
- for (uint i = 0; i < lockedCount; i++)
- {
- isFree &= (lockedParameters[i] != column);
- if (column > lockedParameters[i]) ix--; // shift columns
- }
-
- if (isFree)
- {
- Af.setCoefficient(ix, y, A.getRow(y)[e].v);
- }
- }
- }
-
- // Remove elements from x
- FullVector xf(D);
-
- for (uint i = 0, j = 0; i < A.width(); i++)
- {
- bool isFree = true;
- for (uint l = 0; l < lockedCount; l++)
- {
- isFree &= (lockedParameters[l] != i);
- }
-
- if (isFree)
- {
- xf[j++] = x[i];
- }
- }
-
- // Solve reduced system.
- bool result = LeastSquaresSolver(Af, b_Alxl, xf, epsilon);
-
- // Copy results back to x.
- for (uint i = 0, j = 0; i < A.width(); i++)
- {
- bool isFree = true;
- for (uint l = 0; l < lockedCount; l++)
- {
- isFree &= (lockedParameters[l] != i);
- }
-
- if (isFree)
- {
- x[i] = xf[j++];
- }
- }
-
- return result;
-}
-
-
-bool nv::SymmetricSolver(const SparseMatrix & A, const FullVector & b, FullVector & x, float epsilon/*1e-5f*/)
-{
- nvDebugCheck(A.height() == A.width());
- nvDebugCheck(A.height() == b.dimension());
- nvDebugCheck(b.dimension() == x.dimension());
-
- JacobiPreconditioner jacobi(A, true);
- return ConjugateGradientSolver(jacobi, A, b, x, epsilon);
-
- //return ConjugateGradientSolver(A, b, x, epsilon);
-}
-
-
-/**
-* Compute the solution of the sparse linear system Ab=x using the Conjugate
-* Gradient method.
-*
-* Solving sparse linear systems:
-* (1) A·x = b
-*
-* The conjugate gradient algorithm solves (1) only in the case that A is
-* symmetric and positive definite. It is based on the idea of minimizing the
-* function
-*
-* (2) f(x) = 1/2·x·A·x - b·x
-*
-* This function is minimized when its gradient
-*
-* (3) df = A·x - b
-*
-* is zero, which is equivalent to (1). The minimization is carried out by
-* generating a succession of search directions p.k and improved minimizers x.k.
-* At each stage a quantity alfa.k is found that minimizes f(x.k + alfa.k·p.k),
-* and x.k+1 is set equal to the new point x.k + alfa.k·p.k. The p.k and x.k are
-* built up in such a way that x.k+1 is also the minimizer of f over the whole
-* vector space of directions already taken, {p.1, p.2, . . . , p.k}. After N
-* iterations you arrive at the minimizer over the entire vector space, i.e., the
-* solution to (1).
-*
-* For a really good explanation of the method see:
-*
-* "An Introduction to the Conjugate Gradient Method Without the Agonizing Pain",
-* Jonhathan Richard Shewchuk.
-*
-**/
-/*static*/ bool ConjugateGradientSolver(const SparseMatrix & A, const FullVector & b, FullVector & x, float epsilon)
-{
- nvDebugCheck( A.isSquare() );
- nvDebugCheck( A.width() == b.dimension() );
- nvDebugCheck( A.width() == x.dimension() );
-
- int i = 0;
- const int D = A.width();
- const int i_max = 4 * D; // Convergence should be linear, but in some cases, it's not.
-
- FullVector r(D); // residual
- FullVector p(D); // search direction
- FullVector q(D); //
- float delta_0;
- float delta_old;
- float delta_new;
- float alpha;
- float beta;
-
- // r = b - A·x;
- copy(b, r);
- sgemv(-1, A, x, 1, r);
-
- // p = r;
- copy(r, p);
-
- delta_new = dot( r, r );
- delta_0 = delta_new;
-
- while (i < i_max && delta_new > epsilon*epsilon*delta_0)
- {
- i++;
-
- // q = A·p
- mult(A, p, q);
-
- // alpha = delta_new / p·q
- alpha = delta_new / dot( p, q );
-
- // x = alfa·p + x
- saxpy(alpha, p, x);
-
- if ((i & 31) == 0) // recompute r after 32 steps
- {
- // r = b - A·x
- copy(b, r);
- sgemv(-1, A, x, 1, r);
- }
- else
- {
- // r = r - alpha·q
- saxpy(-alpha, q, r);
- }
-
- delta_old = delta_new;
- delta_new = dot( r, r );
-
- beta = delta_new / delta_old;
-
- // p = beta·p + r
- scal(beta, p);
- saxpy(1, r, p);
- }
-
- return delta_new <= epsilon*epsilon*delta_0;
-}
-
-
-// Conjugate gradient with preconditioner.
-/*static*/ bool ConjugateGradientSolver(const Preconditioner & preconditioner, const SparseMatrix & A, const FullVector & b, FullVector & x, float epsilon)
-{
- nvDebugCheck( A.isSquare() );
- nvDebugCheck( A.width() == b.dimension() );
- nvDebugCheck( A.width() == x.dimension() );
-
- int i = 0;
- const int D = A.width();
- const int i_max = 4 * D; // Convergence should be linear, but in some cases, it's not.
-
- FullVector r(D); // residual
- FullVector p(D); // search direction
- FullVector q(D); //
- FullVector s(D); // preconditioned
- float delta_0;
- float delta_old;
- float delta_new;
- float alpha;
- float beta;
-
- // r = b - A·x
- copy(b, r);
- sgemv(-1, A, x, 1, r);
-
-
- // p = M^-1 · r
- preconditioner.apply(r, p);
- //copy(r, p);
-
-
- delta_new = dot(r, p);
- delta_0 = delta_new;
-
- while (i < i_max && delta_new > epsilon*epsilon*delta_0)
- {
- i++;
-
- // q = A·p
- mult(A, p, q);
-
- // alpha = delta_new / p·q
- alpha = delta_new / dot(p, q);
-
- // x = alfa·p + x
- saxpy(alpha, p, x);
-
- if ((i & 31) == 0) // recompute r after 32 steps
- {
- // r = b - A·x
- copy(b, r);
- sgemv(-1, A, x, 1, r);
- }
- else
- {
- // r = r - alfa·q
- saxpy(-alpha, q, r);
- }
-
- // s = M^-1 · r
- preconditioner.apply(r, s);
- //copy(r, s);
-
- delta_old = delta_new;
- delta_new = dot( r, s );
-
- beta = delta_new / delta_old;
-
- // p = s + beta·p
- scal(beta, p);
- saxpy(1, s, p);
- }
-
- return delta_new <= epsilon*epsilon*delta_0;
-}
-
-
-#if 0 // Nonsymmetric solvers
-
-/** Bi-conjugate gradient method. */
-MATHLIB_API int BiConjugateGradientSolve( const SparseMatrix &A, const DenseVector &b, DenseVector &x, float epsilon ) {
- piDebugCheck( A.IsSquare() );
- piDebugCheck( A.Width() == b.Dim() );
- piDebugCheck( A.Width() == x.Dim() );
-
- int i = 0;
- const int D = A.Width();
- const int i_max = 4 * D;
-
- float resid;
- float rho_1 = 0;
- float rho_2 = 0;
- float alpha;
- float beta;
-
- DenseVector r(D);
- DenseVector rtilde(D);
- DenseVector p(D);
- DenseVector ptilde(D);
- DenseVector q(D);
- DenseVector qtilde(D);
- DenseVector tmp(D); // temporal vector.
-
- // r = b - A·x;
- A.Product( x, tmp );
- r.Sub( b, tmp );
-
- // rtilde = r
- rtilde.Set( r );
-
- // p = r;
- p.Set( r );
-
- // ptilde = rtilde
- ptilde.Set( rtilde );
-
-
-
- float normb = b.Norm();
- if( normb == 0.0 ) normb = 1;
-
- // test convergence
- resid = r.Norm() / normb;
- if( resid < epsilon ) {
- // method converges?
- return 0;
- }
-
-
- while( i < i_max ) {
-
- i++;
-
- rho_1 = DenseVectorDotProduct( r, rtilde );
-
- if( rho_1 == 0 ) {
- // method fails.
- return -i;
- }
-
- if (i == 1) {
- p.Set( r );
- ptilde.Set( rtilde );
- }
- else {
- beta = rho_1 / rho_2;
-
- // p = r + beta * p;
- p.Mad( r, p, beta );
-
- // ptilde = ztilde + beta * ptilde;
- ptilde.Mad( rtilde, ptilde, beta );
- }
-
- // q = A * p;
- A.Product( p, q );
-
- // qtilde = A^t * ptilde;
- A.TransProduct( ptilde, qtilde );
-
- alpha = rho_1 / DenseVectorDotProduct( ptilde, q );
-
- // x += alpha * p;
- x.Mad( x, p, alpha );
-
- // r -= alpha * q;
- r.Mad( r, q, -alpha );
-
- // rtilde -= alpha * qtilde;
- rtilde.Mad( rtilde, qtilde, -alpha );
-
- rho_2 = rho_1;
-
- // test convergence
- resid = r.Norm() / normb;
- if( resid < epsilon ) {
- // method converges
- return i;
- }
- }
-
- return i;
-}
-
-
-/** Bi-conjugate gradient stabilized method. */
-int BiCGSTABSolve( const SparseMatrix &A, const DenseVector &b, DenseVector &x, float epsilon ) {
- piDebugCheck( A.IsSquare() );
- piDebugCheck( A.Width() == b.Dim() );
- piDebugCheck( A.Width() == x.Dim() );
-
- int i = 0;
- const int D = A.Width();
- const int i_max = 2 * D;
-
-
- float resid;
- float rho_1 = 0;
- float rho_2 = 0;
- float alpha = 0;
- float beta = 0;
- float omega = 0;
-
- DenseVector p(D);
- DenseVector phat(D);
- DenseVector s(D);
- DenseVector shat(D);
- DenseVector t(D);
- DenseVector v(D);
-
- DenseVector r(D);
- DenseVector rtilde(D);
-
- DenseVector tmp(D);
-
- // r = b - A·x;
- A.Product( x, tmp );
- r.Sub( b, tmp );
-
- // rtilde = r
- rtilde.Set( r );
-
-
- float normb = b.Norm();
- if( normb == 0.0 ) normb = 1;
-
- // test convergence
- resid = r.Norm() / normb;
- if( resid < epsilon ) {
- // method converges?
- return 0;
- }
-
-
- while( i<i_max ) {
-
- i++;
-
- rho_1 = DenseVectorDotProduct( rtilde, r );
- if( rho_1 == 0 ) {
- // method fails
- return -i;
- }
-
-
- if( i == 1 ) {
- p.Set( r );
- }
- else {
- beta = (rho_1 / rho_2) * (alpha / omega);
-
- // p = r + beta * (p - omega * v);
- p.Mad( p, v, -omega );
- p.Mad( r, p, beta );
- }
-
- //phat = M.solve(p);
- phat.Set( p );
- //Precond( &phat, p );
-
- //v = A * phat;
- A.Product( phat, v );
-
- alpha = rho_1 / DenseVectorDotProduct( rtilde, v );
-
- // s = r - alpha * v;
- s.Mad( r, v, -alpha );
-
-
- resid = s.Norm() / normb;
- if( resid < epsilon ) {
- // x += alpha * phat;
- x.Mad( x, phat, alpha );
- return i;
- }
-
- //shat = M.solve(s);
- shat.Set( s );
- //Precond( &shat, s );
-
- //t = A * shat;
- A.Product( shat, t );
-
- omega = DenseVectorDotProduct( t, s ) / DenseVectorDotProduct( t, t );
-
- // x += alpha * phat + omega * shat;
- x.Mad( x, shat, omega );
- x.Mad( x, phat, alpha );
-
- //r = s - omega * t;
- r.Mad( s, t, -omega );
-
- rho_2 = rho_1;
-
- resid = r.Norm() / normb;
- if( resid < epsilon ) {
- return i;
- }
-
- if( omega == 0 ) {
- return -i; // ???
- }
- }
-
- return i;
-}
-
-
-/** Bi-conjugate gradient stabilized method. */
-int BiCGSTABPrecondSolve( const SparseMatrix &A, const DenseVector &b, DenseVector &x, const IPreconditioner &M, float epsilon ) {
- piDebugCheck( A.IsSquare() );
- piDebugCheck( A.Width() == b.Dim() );
- piDebugCheck( A.Width() == x.Dim() );
-
- int i = 0;
- const int D = A.Width();
- const int i_max = D;
- // const int i_max = 1000;
-
-
- float resid;
- float rho_1 = 0;
- float rho_2 = 0;
- float alpha = 0;
- float beta = 0;
- float omega = 0;
-
- DenseVector p(D);
- DenseVector phat(D);
- DenseVector s(D);
- DenseVector shat(D);
- DenseVector t(D);
- DenseVector v(D);
-
- DenseVector r(D);
- DenseVector rtilde(D);
-
- DenseVector tmp(D);
-
- // r = b - A·x;
- A.Product( x, tmp );
- r.Sub( b, tmp );
-
- // rtilde = r
- rtilde.Set( r );
-
-
- float normb = b.Norm();
- if( normb == 0.0 ) normb = 1;
-
- // test convergence
- resid = r.Norm() / normb;
- if( resid < epsilon ) {
- // method converges?
- return 0;
- }
-
-
- while( i<i_max ) {
-
- i++;
-
- rho_1 = DenseVectorDotProduct( rtilde, r );
- if( rho_1 == 0 ) {
- // method fails
- return -i;
- }
-
-
- if( i == 1 ) {
- p.Set( r );
- }
- else {
- beta = (rho_1 / rho_2) * (alpha / omega);
-
- // p = r + beta * (p - omega * v);
- p.Mad( p, v, -omega );
- p.Mad( r, p, beta );
- }
-
- //phat = M.solve(p);
- //phat.Set( p );
- M.Precond( &phat, p );
-
- //v = A * phat;
- A.Product( phat, v );
-
- alpha = rho_1 / DenseVectorDotProduct( rtilde, v );
-
- // s = r - alpha * v;
- s.Mad( r, v, -alpha );
-
-
- resid = s.Norm() / normb;
-
- //printf( "--- Iteration %d: residual = %f\n", i, resid );
-
- if( resid < epsilon ) {
- // x += alpha * phat;
- x.Mad( x, phat, alpha );
- return i;
- }
-
- //shat = M.solve(s);
- //shat.Set( s );
- M.Precond( &shat, s );
-
- //t = A * shat;
- A.Product( shat, t );
-
- omega = DenseVectorDotProduct( t, s ) / DenseVectorDotProduct( t, t );
-
- // x += alpha * phat + omega * shat;
- x.Mad( x, shat, omega );
- x.Mad( x, phat, alpha );
-
- //r = s - omega * t;
- r.Mad( s, t, -omega );
-
- rho_2 = rho_1;
-
- resid = r.Norm() / normb;
- if( resid < epsilon ) {
- return i;
- }
-
- if( omega == 0 ) {
- return -i; // ???
- }
- }
-
- return i;
-}
-
-#endif
diff --git a/thirdparty/thekla_atlas/nvmath/Solver.h b/thirdparty/thekla_atlas/nvmath/Solver.h
deleted file mode 100644
index 2bbf92736a..0000000000
--- a/thirdparty/thekla_atlas/nvmath/Solver.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// This code is in the public domain -- castanyo@yahoo.es
-
-#pragma once
-#ifndef NV_MATH_SOLVER_H
-#define NV_MATH_SOLVER_H
-
-#include "nvmath.h"
-
-namespace nv
-{
- class SparseMatrix;
- class FullVector;
-
-
- // Linear solvers.
- NVMATH_API bool LeastSquaresSolver(const SparseMatrix & A, const FullVector & b, FullVector & x, float epsilon = 1e-5f);
- NVMATH_API bool LeastSquaresSolver(const SparseMatrix & A, const FullVector & b, FullVector & x, const uint * lockedParameters, uint lockedCount, float epsilon = 1e-5f);
- NVMATH_API bool SymmetricSolver(const SparseMatrix & A, const FullVector & b, FullVector & x, float epsilon = 1e-5f);
- //NVMATH_API void NonSymmetricSolver(const SparseMatrix & A, const FullVector & b, FullVector & x, float epsilon = 1e-5f);
-
-} // nv namespace
-
-
-#endif // NV_MATH_SOLVER_H
diff --git a/thirdparty/thekla_atlas/nvmath/Sparse.cpp b/thirdparty/thekla_atlas/nvmath/Sparse.cpp
deleted file mode 100644
index 421e7ee022..0000000000
--- a/thirdparty/thekla_atlas/nvmath/Sparse.cpp
+++ /dev/null
@@ -1,889 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castanyo@yahoo.es>
-
-#include "Sparse.h"
-#include "KahanSum.h"
-
-#include "nvcore/Array.inl"
-
-#define USE_KAHAN_SUM 0
-
-
-using namespace nv;
-
-
-FullVector::FullVector(uint dim)
-{
- m_array.resize(dim);
-}
-
-FullVector::FullVector(const FullVector & v) : m_array(v.m_array)
-{
-}
-
-const FullVector & FullVector::operator=(const FullVector & v)
-{
- nvCheck(dimension() == v.dimension());
-
- m_array = v.m_array;
-
- return *this;
-}
-
-
-void FullVector::fill(float f)
-{
- const uint dim = dimension();
- for (uint i = 0; i < dim; i++)
- {
- m_array[i] = f;
- }
-}
-
-void FullVector::operator+= (const FullVector & v)
-{
- nvDebugCheck(dimension() == v.dimension());
-
- const uint dim = dimension();
- for (uint i = 0; i < dim; i++)
- {
- m_array[i] += v.m_array[i];
- }
-}
-
-void FullVector::operator-= (const FullVector & v)
-{
- nvDebugCheck(dimension() == v.dimension());
-
- const uint dim = dimension();
- for (uint i = 0; i < dim; i++)
- {
- m_array[i] -= v.m_array[i];
- }
-}
-
-void FullVector::operator*= (const FullVector & v)
-{
- nvDebugCheck(dimension() == v.dimension());
-
- const uint dim = dimension();
- for (uint i = 0; i < dim; i++)
- {
- m_array[i] *= v.m_array[i];
- }
-}
-
-void FullVector::operator+= (float f)
-{
- const uint dim = dimension();
- for (uint i = 0; i < dim; i++)
- {
- m_array[i] += f;
- }
-}
-
-void FullVector::operator-= (float f)
-{
- const uint dim = dimension();
- for (uint i = 0; i < dim; i++)
- {
- m_array[i] -= f;
- }
-}
-
-void FullVector::operator*= (float f)
-{
- const uint dim = dimension();
- for (uint i = 0; i < dim; i++)
- {
- m_array[i] *= f;
- }
-}
-
-
-void nv::saxpy(float a, const FullVector & x, FullVector & y)
-{
- nvDebugCheck(x.dimension() == y.dimension());
-
- const uint dim = x.dimension();
- for (uint i = 0; i < dim; i++)
- {
- y[i] += a * x[i];
- }
-}
-
-void nv::copy(const FullVector & x, FullVector & y)
-{
- nvDebugCheck(x.dimension() == y.dimension());
-
- const uint dim = x.dimension();
- for (uint i = 0; i < dim; i++)
- {
- y[i] = x[i];
- }
-}
-
-void nv::scal(float a, FullVector & x)
-{
- const uint dim = x.dimension();
- for (uint i = 0; i < dim; i++)
- {
- x[i] *= a;
- }
-}
-
-float nv::dot(const FullVector & x, const FullVector & y)
-{
- nvDebugCheck(x.dimension() == y.dimension());
-
- const uint dim = x.dimension();
-
-#if USE_KAHAN_SUM
- KahanSum kahan;
- for (uint i = 0; i < dim; i++)
- {
- kahan.add(x[i] * y[i]);
- }
- return kahan.sum();
-#else
- float sum = 0;
- for (uint i = 0; i < dim; i++)
- {
- sum += x[i] * y[i];
- }
- return sum;
-#endif
-}
-
-
-FullMatrix::FullMatrix(uint d) : m_width(d), m_height(d)
-{
- m_array.resize(d*d, 0.0f);
-}
-
-FullMatrix::FullMatrix(uint w, uint h) : m_width(w), m_height(h)
-{
- m_array.resize(w*h, 0.0f);
-}
-
-FullMatrix::FullMatrix(const FullMatrix & m) : m_width(m.m_width), m_height(m.m_height)
-{
- m_array = m.m_array;
-}
-
-const FullMatrix & FullMatrix::operator=(const FullMatrix & m)
-{
- nvCheck(width() == m.width());
- nvCheck(height() == m.height());
-
- m_array = m.m_array;
-
- return *this;
-}
-
-
-float FullMatrix::getCoefficient(uint x, uint y) const
-{
- nvDebugCheck( x < width() );
- nvDebugCheck( y < height() );
-
- return m_array[y * width() + x];
-}
-
-void FullMatrix::setCoefficient(uint x, uint y, float f)
-{
- nvDebugCheck( x < width() );
- nvDebugCheck( y < height() );
-
- m_array[y * width() + x] = f;
-}
-
-void FullMatrix::addCoefficient(uint x, uint y, float f)
-{
- nvDebugCheck( x < width() );
- nvDebugCheck( y < height() );
-
- m_array[y * width() + x] += f;
-}
-
-void FullMatrix::mulCoefficient(uint x, uint y, float f)
-{
- nvDebugCheck( x < width() );
- nvDebugCheck( y < height() );
-
- m_array[y * width() + x] *= f;
-}
-
-float FullMatrix::dotRow(uint y, const FullVector & v) const
-{
- nvDebugCheck( v.dimension() == width() );
- nvDebugCheck( y < height() );
-
- float sum = 0;
-
- const uint count = v.dimension();
- for (uint i = 0; i < count; i++)
- {
- sum += m_array[y * count + i] * v[i];
- }
-
- return sum;
-}
-
-void FullMatrix::madRow(uint y, float alpha, FullVector & v) const
-{
- nvDebugCheck( v.dimension() == width() );
- nvDebugCheck( y < height() );
-
- const uint count = v.dimension();
- for (uint i = 0; i < count; i++)
- {
- v[i] += m_array[y * count + i];
- }
-}
-
-
-// y = M * x
-void nv::mult(const FullMatrix & M, const FullVector & x, FullVector & y)
-{
- mult(NoTransposed, M, x, y);
-}
-
-void nv::mult(Transpose TM, const FullMatrix & M, const FullVector & x, FullVector & y)
-{
- const uint w = M.width();
- const uint h = M.height();
-
- if (TM == Transposed)
- {
- nvDebugCheck( h == x.dimension() );
- nvDebugCheck( w == y.dimension() );
-
- y.fill(0.0f);
-
- for (uint i = 0; i < h; i++)
- {
- M.madRow(i, x[i], y);
- }
- }
- else
- {
- nvDebugCheck( w == x.dimension() );
- nvDebugCheck( h == y.dimension() );
-
- for (uint i = 0; i < h; i++)
- {
- y[i] = M.dotRow(i, x);
- }
- }
-}
-
-// y = alpha*A*x + beta*y
-void nv::sgemv(float alpha, const FullMatrix & A, const FullVector & x, float beta, FullVector & y)
-{
- sgemv(alpha, NoTransposed, A, x, beta, y);
-}
-
-void nv::sgemv(float alpha, Transpose TA, const FullMatrix & A, const FullVector & x, float beta, FullVector & y)
-{
- const uint w = A.width();
- const uint h = A.height();
-
- if (TA == Transposed)
- {
- nvDebugCheck( h == x.dimension() );
- nvDebugCheck( w == y.dimension() );
-
- for (uint i = 0; i < h; i++)
- {
- A.madRow(i, alpha * x[i], y);
- }
- }
- else
- {
- nvDebugCheck( w == x.dimension() );
- nvDebugCheck( h == y.dimension() );
-
- for (uint i = 0; i < h; i++)
- {
- y[i] = alpha * A.dotRow(i, x) + beta * y[i];
- }
- }
-}
-
-
-// Multiply a row of A by a column of B.
-static float dot(uint j, Transpose TA, const FullMatrix & A, uint i, Transpose TB, const FullMatrix & B)
-{
- const uint w = (TA == NoTransposed) ? A.width() : A.height();
- nvDebugCheck(w == ((TB == NoTransposed) ? B.height() : A.width()));
-
- float sum = 0.0f;
-
- for (uint k = 0; k < w; k++)
- {
- const float a = (TA == NoTransposed) ? A.getCoefficient(k, j) : A.getCoefficient(j, k); // @@ Move branches out of the loop?
- const float b = (TB == NoTransposed) ? B.getCoefficient(i, k) : A.getCoefficient(k, i);
- sum += a * b;
- }
-
- return sum;
-}
-
-
-// C = A * B
-void nv::mult(const FullMatrix & A, const FullMatrix & B, FullMatrix & C)
-{
- mult(NoTransposed, A, NoTransposed, B, C);
-}
-
-void nv::mult(Transpose TA, const FullMatrix & A, Transpose TB, const FullMatrix & B, FullMatrix & C)
-{
- sgemm(1.0f, TA, A, TB, B, 0.0f, C);
-}
-
-// C = alpha*A*B + beta*C
-void nv::sgemm(float alpha, const FullMatrix & A, const FullMatrix & B, float beta, FullMatrix & C)
-{
- sgemm(alpha, NoTransposed, A, NoTransposed, B, beta, C);
-}
-
-void nv::sgemm(float alpha, Transpose TA, const FullMatrix & A, Transpose TB, const FullMatrix & B, float beta, FullMatrix & C)
-{
- const uint w = C.width();
- const uint h = C.height();
-
- uint aw = (TA == NoTransposed) ? A.width() : A.height();
- uint ah = (TA == NoTransposed) ? A.height() : A.width();
- uint bw = (TB == NoTransposed) ? B.width() : B.height();
- uint bh = (TB == NoTransposed) ? B.height() : B.width();
-
- nvDebugCheck(aw == bh);
- nvDebugCheck(bw == ah);
- nvDebugCheck(w == bw);
- nvDebugCheck(h == ah);
-
- for (uint y = 0; y < h; y++)
- {
- for (uint x = 0; x < w; x++)
- {
- float c = alpha * ::dot(x, TA, A, y, TB, B) + beta * C.getCoefficient(x, y);
- C.setCoefficient(x, y, c);
- }
- }
-}
-
-
-
-
-
-/// Ctor. Init the size of the sparse matrix.
-SparseMatrix::SparseMatrix(uint d) : m_width(d)
-{
- m_array.resize(d);
-}
-
-/// Ctor. Init the size of the sparse matrix.
-SparseMatrix::SparseMatrix(uint w, uint h) : m_width(w)
-{
- m_array.resize(h);
-}
-
-SparseMatrix::SparseMatrix(const SparseMatrix & m) : m_width(m.m_width)
-{
- m_array = m.m_array;
-}
-
-const SparseMatrix & SparseMatrix::operator=(const SparseMatrix & m)
-{
- nvCheck(width() == m.width());
- nvCheck(height() == m.height());
-
- m_array = m.m_array;
-
- return *this;
-}
-
-
-// x is column, y is row
-float SparseMatrix::getCoefficient(uint x, uint y) const
-{
- nvDebugCheck( x < width() );
- nvDebugCheck( y < height() );
-
- const uint count = m_array[y].count();
- for (uint i = 0; i < count; i++)
- {
- if (m_array[y][i].x == x) return m_array[y][i].v;
- }
-
- return 0.0f;
-}
-
-void SparseMatrix::setCoefficient(uint x, uint y, float f)
-{
- nvDebugCheck( x < width() );
- nvDebugCheck( y < height() );
-
- const uint count = m_array[y].count();
- for (uint i = 0; i < count; i++)
- {
- if (m_array[y][i].x == x)
- {
- m_array[y][i].v = f;
- return;
- }
- }
-
- if (f != 0.0f)
- {
- Coefficient c = { x, f };
- m_array[y].append( c );
- }
-}
-
-void SparseMatrix::addCoefficient(uint x, uint y, float f)
-{
- nvDebugCheck( x < width() );
- nvDebugCheck( y < height() );
-
- if (f != 0.0f)
- {
- const uint count = m_array[y].count();
- for (uint i = 0; i < count; i++)
- {
- if (m_array[y][i].x == x)
- {
- m_array[y][i].v += f;
- return;
- }
- }
-
- Coefficient c = { x, f };
- m_array[y].append( c );
- }
-}
-
-void SparseMatrix::mulCoefficient(uint x, uint y, float f)
-{
- nvDebugCheck( x < width() );
- nvDebugCheck( y < height() );
-
- const uint count = m_array[y].count();
- for (uint i = 0; i < count; i++)
- {
- if (m_array[y][i].x == x)
- {
- m_array[y][i].v *= f;
- return;
- }
- }
-
- if (f != 0.0f)
- {
- Coefficient c = { x, f };
- m_array[y].append( c );
- }
-}
-
-
-float SparseMatrix::sumRow(uint y) const
-{
- nvDebugCheck( y < height() );
-
- const uint count = m_array[y].count();
-
-#if USE_KAHAN_SUM
- KahanSum kahan;
- for (uint i = 0; i < count; i++)
- {
- kahan.add(m_array[y][i].v);
- }
- return kahan.sum();
-#else
- float sum = 0;
- for (uint i = 0; i < count; i++)
- {
- sum += m_array[y][i].v;
- }
- return sum;
-#endif
-}
-
-float SparseMatrix::dotRow(uint y, const FullVector & v) const
-{
- nvDebugCheck( y < height() );
-
- const uint count = m_array[y].count();
-
-#if USE_KAHAN_SUM
- KahanSum kahan;
- for (uint i = 0; i < count; i++)
- {
- kahan.add(m_array[y][i].v * v[m_array[y][i].x]);
- }
- return kahan.sum();
-#else
- float sum = 0;
- for (uint i = 0; i < count; i++)
- {
- sum += m_array[y][i].v * v[m_array[y][i].x];
- }
- return sum;
-#endif
-}
-
-void SparseMatrix::madRow(uint y, float alpha, FullVector & v) const
-{
- nvDebugCheck(y < height());
-
- const uint count = m_array[y].count();
- for (uint i = 0; i < count; i++)
- {
- v[m_array[y][i].x] += alpha * m_array[y][i].v;
- }
-}
-
-
-void SparseMatrix::clearRow(uint y)
-{
- nvDebugCheck( y < height() );
-
- m_array[y].clear();
-}
-
-void SparseMatrix::scaleRow(uint y, float f)
-{
- nvDebugCheck( y < height() );
-
- const uint count = m_array[y].count();
- for (uint i = 0; i < count; i++)
- {
- m_array[y][i].v *= f;
- }
-}
-
-void SparseMatrix::normalizeRow(uint y)
-{
- nvDebugCheck( y < height() );
-
- float norm = 0.0f;
-
- const uint count = m_array[y].count();
- for (uint i = 0; i < count; i++)
- {
- float f = m_array[y][i].v;
- norm += f * f;
- }
-
- scaleRow(y, 1.0f / sqrtf(norm));
-}
-
-
-void SparseMatrix::clearColumn(uint x)
-{
- nvDebugCheck(x < width());
-
- for (uint y = 0; y < height(); y++)
- {
- const uint count = m_array[y].count();
- for (uint e = 0; e < count; e++)
- {
- if (m_array[y][e].x == x)
- {
- m_array[y][e].v = 0.0f;
- break;
- }
- }
- }
-}
-
-void SparseMatrix::scaleColumn(uint x, float f)
-{
- nvDebugCheck(x < width());
-
- for (uint y = 0; y < height(); y++)
- {
- const uint count = m_array[y].count();
- for (uint e = 0; e < count; e++)
- {
- if (m_array[y][e].x == x)
- {
- m_array[y][e].v *= f;
- break;
- }
- }
- }
-}
-
-const Array<SparseMatrix::Coefficient> & SparseMatrix::getRow(uint y) const
-{
- return m_array[y];
-}
-
-
-bool SparseMatrix::isSymmetric() const
-{
- for (uint y = 0; y < height(); y++)
- {
- const uint count = m_array[y].count();
- for (uint e = 0; e < count; e++)
- {
- const uint x = m_array[y][e].x;
- if (x > y) {
- float v = m_array[y][e].v;
-
- if (!equal(getCoefficient(y, x), v)) { // @@ epsilon
- return false;
- }
- }
- }
- }
-
- return true;
-}
-
-
-// y = M * x
-void nv::mult(const SparseMatrix & M, const FullVector & x, FullVector & y)
-{
- mult(NoTransposed, M, x, y);
-}
-
-void nv::mult(Transpose TM, const SparseMatrix & M, const FullVector & x, FullVector & y)
-{
- const uint w = M.width();
- const uint h = M.height();
-
- if (TM == Transposed)
- {
- nvDebugCheck( h == x.dimension() );
- nvDebugCheck( w == y.dimension() );
-
- y.fill(0.0f);
-
- for (uint i = 0; i < h; i++)
- {
- M.madRow(i, x[i], y);
- }
- }
- else
- {
- nvDebugCheck( w == x.dimension() );
- nvDebugCheck( h == y.dimension() );
-
- for (uint i = 0; i < h; i++)
- {
- y[i] = M.dotRow(i, x);
- }
- }
-}
-
-// y = alpha*A*x + beta*y
-void nv::sgemv(float alpha, const SparseMatrix & A, const FullVector & x, float beta, FullVector & y)
-{
- sgemv(alpha, NoTransposed, A, x, beta, y);
-}
-
-void nv::sgemv(float alpha, Transpose TA, const SparseMatrix & A, const FullVector & x, float beta, FullVector & y)
-{
- const uint w = A.width();
- const uint h = A.height();
-
- if (TA == Transposed)
- {
- nvDebugCheck( h == x.dimension() );
- nvDebugCheck( w == y.dimension() );
-
- for (uint i = 0; i < h; i++)
- {
- A.madRow(i, alpha * x[i], y);
- }
- }
- else
- {
- nvDebugCheck( w == x.dimension() );
- nvDebugCheck( h == y.dimension() );
-
- for (uint i = 0; i < h; i++)
- {
- y[i] = alpha * A.dotRow(i, x) + beta * y[i];
- }
- }
-}
-
-
-// dot y-row of A by x-column of B
-static float dotRowColumn(int y, const SparseMatrix & A, int x, const SparseMatrix & B)
-{
- const Array<SparseMatrix::Coefficient> & row = A.getRow(y);
-
- const uint count = row.count();
-
-#if USE_KAHAN_SUM
- KahanSum kahan;
- for (uint i = 0; i < count; i++)
- {
- const SparseMatrix::Coefficient & c = row[i];
- kahan.add(c.v * B.getCoefficient(x, c.x));
- }
- return kahan.sum();
-#else
- float sum = 0.0f;
- for (uint i = 0; i < count; i++)
- {
- const SparseMatrix::Coefficient & c = row[i];
- sum += c.v * B.getCoefficient(x, c.x);
- }
- return sum;
-#endif
-}
-
-// dot y-row of A by x-row of B
-static float dotRowRow(int y, const SparseMatrix & A, int x, const SparseMatrix & B)
-{
- const Array<SparseMatrix::Coefficient> & row = A.getRow(y);
-
- const uint count = row.count();
-
-#if USE_KAHAN_SUM
- KahanSum kahan;
- for (uint i = 0; i < count; i++)
- {
- const SparseMatrix::Coefficient & c = row[i];
- kahan.add(c.v * B.getCoefficient(c.x, x));
- }
- return kahan.sum();
-#else
- float sum = 0.0f;
- for (uint i = 0; i < count; i++)
- {
- const SparseMatrix::Coefficient & c = row[i];
- sum += c.v * B.getCoefficient(c.x, x);
- }
- return sum;
-#endif
-}
-
-// dot y-column of A by x-column of B
-static float dotColumnColumn(int y, const SparseMatrix & A, int x, const SparseMatrix & B)
-{
- nvDebugCheck(A.height() == B.height());
-
- const uint h = A.height();
-
-#if USE_KAHAN_SUM
- KahanSum kahan;
- for (uint i = 0; i < h; i++)
- {
- kahan.add(A.getCoefficient(y, i) * B.getCoefficient(x, i));
- }
- return kahan.sum();
-#else
- float sum = 0.0f;
- for (uint i = 0; i < h; i++)
- {
- sum += A.getCoefficient(y, i) * B.getCoefficient(x, i);
- }
- return sum;
-#endif
-}
-
-
-void nv::transpose(const SparseMatrix & A, SparseMatrix & B)
-{
- nvDebugCheck(A.width() == B.height());
- nvDebugCheck(B.width() == A.height());
-
- const uint w = A.width();
- for (uint x = 0; x < w; x++)
- {
- B.clearRow(x);
- }
-
- const uint h = A.height();
- for (uint y = 0; y < h; y++)
- {
- const Array<SparseMatrix::Coefficient> & row = A.getRow(y);
-
- const uint count = row.count();
- for (uint i = 0; i < count; i++)
- {
- const SparseMatrix::Coefficient & c = row[i];
- nvDebugCheck(c.x < w);
-
- B.setCoefficient(y, c.x, c.v);
- }
- }
-}
-
-// C = A * B
-void nv::mult(const SparseMatrix & A, const SparseMatrix & B, SparseMatrix & C)
-{
- mult(NoTransposed, A, NoTransposed, B, C);
-}
-
-void nv::mult(Transpose TA, const SparseMatrix & A, Transpose TB, const SparseMatrix & B, SparseMatrix & C)
-{
- sgemm(1.0f, TA, A, TB, B, 0.0f, C);
-}
-
-// C = alpha*A*B + beta*C
-void nv::sgemm(float alpha, const SparseMatrix & A, const SparseMatrix & B, float beta, SparseMatrix & C)
-{
- sgemm(alpha, NoTransposed, A, NoTransposed, B, beta, C);
-}
-
-void nv::sgemm(float alpha, Transpose TA, const SparseMatrix & A, Transpose TB, const SparseMatrix & B, float beta, SparseMatrix & C)
-{
- const uint w = C.width();
- const uint h = C.height();
-
- uint aw = (TA == NoTransposed) ? A.width() : A.height();
- uint ah = (TA == NoTransposed) ? A.height() : A.width();
- uint bw = (TB == NoTransposed) ? B.width() : B.height();
- uint bh = (TB == NoTransposed) ? B.height() : B.width();
-
- nvDebugCheck(aw == bh);
- nvDebugCheck(bw == ah);
- nvDebugCheck(w == bw);
- nvDebugCheck(h == ah);
-
-
- for (uint y = 0; y < h; y++)
- {
- for (uint x = 0; x < w; x++)
- {
- float c = beta * C.getCoefficient(x, y);
-
- if (TA == NoTransposed && TB == NoTransposed)
- {
- // dot y-row of A by x-column of B.
- c += alpha * dotRowColumn(y, A, x, B);
- }
- else if (TA == Transposed && TB == Transposed)
- {
- // dot y-column of A by x-row of B.
- c += alpha * dotRowColumn(x, B, y, A);
- }
- else if (TA == Transposed && TB == NoTransposed)
- {
- // dot y-column of A by x-column of B.
- c += alpha * dotColumnColumn(y, A, x, B);
- }
- else if (TA == NoTransposed && TB == Transposed)
- {
- // dot y-row of A by x-row of B.
- c += alpha * dotRowRow(y, A, x, B);
- }
-
- C.setCoefficient(x, y, c);
- }
- }
-}
-
-// C = At * A
-void nv::sqm(const SparseMatrix & A, SparseMatrix & C)
-{
- // This is quite expensive...
- mult(Transposed, A, NoTransposed, A, C);
-}
diff --git a/thirdparty/thekla_atlas/nvmath/Sparse.h b/thirdparty/thekla_atlas/nvmath/Sparse.h
deleted file mode 100644
index 6b03ed51f3..0000000000
--- a/thirdparty/thekla_atlas/nvmath/Sparse.h
+++ /dev/null
@@ -1,204 +0,0 @@
-// This code is in the public domain -- castanyo@yahoo.es
-
-#pragma once
-#ifndef NV_MATH_SPARSE_H
-#define NV_MATH_SPARSE_H
-
-#include "nvmath.h"
-#include "nvcore/Array.h"
-
-
-// Full and sparse vector and matrix classes. BLAS subset.
-
-namespace nv
-{
- class FullVector;
- class FullMatrix;
- class SparseMatrix;
-
-
- /// Fixed size vector class.
- class FullVector
- {
- public:
-
- FullVector(uint dim);
- FullVector(const FullVector & v);
-
- const FullVector & operator=(const FullVector & v);
-
- uint dimension() const { return m_array.count(); }
-
- const float & operator[]( uint index ) const { return m_array[index]; }
- float & operator[] ( uint index ) { return m_array[index]; }
-
- void fill(float f);
-
- void operator+= (const FullVector & v);
- void operator-= (const FullVector & v);
- void operator*= (const FullVector & v);
-
- void operator+= (float f);
- void operator-= (float f);
- void operator*= (float f);
-
-
- private:
-
- Array<float> m_array;
-
- };
-
- // Pseudo-BLAS interface.
- NVMATH_API void saxpy(float a, const FullVector & x, FullVector & y); // y = a * x + y
- NVMATH_API void copy(const FullVector & x, FullVector & y);
- NVMATH_API void scal(float a, FullVector & x);
- NVMATH_API float dot(const FullVector & x, const FullVector & y);
-
-
- enum Transpose
- {
- NoTransposed = 0,
- Transposed = 1
- };
-
- /// Full matrix class.
- class FullMatrix
- {
- public:
-
- FullMatrix(uint d);
- FullMatrix(uint w, uint h);
- FullMatrix(const FullMatrix & m);
-
- const FullMatrix & operator=(const FullMatrix & m);
-
- uint width() const { return m_width; }
- uint height() const { return m_height; }
- bool isSquare() const { return m_width == m_height; }
-
- float getCoefficient(uint x, uint y) const;
-
- void setCoefficient(uint x, uint y, float f);
- void addCoefficient(uint x, uint y, float f);
- void mulCoefficient(uint x, uint y, float f);
-
- float dotRow(uint y, const FullVector & v) const;
- void madRow(uint y, float alpha, FullVector & v) const;
-
- protected:
-
- bool isValid() const {
- return m_array.size() == (m_width * m_height);
- }
-
- private:
-
- const uint m_width;
- const uint m_height;
- Array<float> m_array;
-
- };
-
- NVMATH_API void mult(const FullMatrix & M, const FullVector & x, FullVector & y);
- NVMATH_API void mult(Transpose TM, const FullMatrix & M, const FullVector & x, FullVector & y);
-
- // y = alpha*A*x + beta*y
- NVMATH_API void sgemv(float alpha, const FullMatrix & A, const FullVector & x, float beta, FullVector & y);
- NVMATH_API void sgemv(float alpha, Transpose TA, const FullMatrix & A, const FullVector & x, float beta, FullVector & y);
-
- NVMATH_API void mult(const FullMatrix & A, const FullMatrix & B, FullMatrix & C);
- NVMATH_API void mult(Transpose TA, const FullMatrix & A, Transpose TB, const FullMatrix & B, FullMatrix & C);
-
- // C = alpha*A*B + beta*C
- NVMATH_API void sgemm(float alpha, const FullMatrix & A, const FullMatrix & B, float beta, FullMatrix & C);
- NVMATH_API void sgemm(float alpha, Transpose TA, const FullMatrix & A, Transpose TB, const FullMatrix & B, float beta, FullMatrix & C);
-
-
- /**
- * Sparse matrix class. The matrix is assumed to be sparse and to have
- * very few non-zero elements, for this reason it's stored in indexed
- * format. To multiply column vectors efficiently, the matrix stores
- * the elements in indexed-column order, there is a list of indexed
- * elements for each row of the matrix. As with the FullVector the
- * dimension of the matrix is constant.
- **/
- class SparseMatrix
- {
- friend class FullMatrix;
- public:
-
- // An element of the sparse array.
- struct Coefficient {
- uint x; // column
- float v; // value
- };
-
-
- public:
-
- SparseMatrix(uint d);
- SparseMatrix(uint w, uint h);
- SparseMatrix(const SparseMatrix & m);
-
- const SparseMatrix & operator=(const SparseMatrix & m);
-
-
- uint width() const { return m_width; }
- uint height() const { return m_array.count(); }
- bool isSquare() const { return width() == height(); }
-
- float getCoefficient(uint x, uint y) const; // x is column, y is row
-
- void setCoefficient(uint x, uint y, float f);
- void addCoefficient(uint x, uint y, float f);
- void mulCoefficient(uint x, uint y, float f);
-
- float sumRow(uint y) const;
- float dotRow(uint y, const FullVector & v) const;
- void madRow(uint y, float alpha, FullVector & v) const;
-
- void clearRow(uint y);
- void scaleRow(uint y, float f);
- void normalizeRow(uint y);
-
- void clearColumn(uint x);
- void scaleColumn(uint x, float f);
-
- const Array<Coefficient> & getRow(uint y) const;
-
- bool isSymmetric() const;
-
- private:
-
- /// Number of columns.
- const uint m_width;
-
- /// Array of matrix elements.
- Array< Array<Coefficient> > m_array;
-
- };
-
- NVMATH_API void transpose(const SparseMatrix & A, SparseMatrix & B);
-
- NVMATH_API void mult(const SparseMatrix & M, const FullVector & x, FullVector & y);
- NVMATH_API void mult(Transpose TM, const SparseMatrix & M, const FullVector & x, FullVector & y);
-
- // y = alpha*A*x + beta*y
- NVMATH_API void sgemv(float alpha, const SparseMatrix & A, const FullVector & x, float beta, FullVector & y);
- NVMATH_API void sgemv(float alpha, Transpose TA, const SparseMatrix & A, const FullVector & x, float beta, FullVector & y);
-
- NVMATH_API void mult(const SparseMatrix & A, const SparseMatrix & B, SparseMatrix & C);
- NVMATH_API void mult(Transpose TA, const SparseMatrix & A, Transpose TB, const SparseMatrix & B, SparseMatrix & C);
-
- // C = alpha*A*B + beta*C
- NVMATH_API void sgemm(float alpha, const SparseMatrix & A, const SparseMatrix & B, float beta, SparseMatrix & C);
- NVMATH_API void sgemm(float alpha, Transpose TA, const SparseMatrix & A, Transpose TB, const SparseMatrix & B, float beta, SparseMatrix & C);
-
- // C = At * A
- NVMATH_API void sqm(const SparseMatrix & A, SparseMatrix & C);
-
-} // nv namespace
-
-
-#endif // NV_MATH_SPARSE_H
diff --git a/thirdparty/thekla_atlas/nvmath/Sphere.cpp b/thirdparty/thekla_atlas/nvmath/Sphere.cpp
deleted file mode 100644
index e0c1ad652c..0000000000
--- a/thirdparty/thekla_atlas/nvmath/Sphere.cpp
+++ /dev/null
@@ -1,431 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#include "Sphere.h"
-#include "Vector.inl"
-#include "Box.inl"
-
-#include <float.h> // FLT_MAX
-
-using namespace nv;
-
-const float radiusEpsilon = 1e-4f;
-
-Sphere::Sphere(Vector3::Arg p0, Vector3::Arg p1)
-{
- if (p0 == p1) *this = Sphere(p0);
- else {
- center = (p0 + p1) * 0.5f;
- radius = length(p0 - center) + radiusEpsilon;
-
- float d0 = length(p0 - center);
- float d1 = length(p1 - center);
- nvDebugCheck(equal(d0, radius - radiusEpsilon));
- nvDebugCheck(equal(d1, radius - radiusEpsilon));
- }
-}
-
-Sphere::Sphere(Vector3::Arg p0, Vector3::Arg p1, Vector3::Arg p2)
-{
- if (p0 == p1 || p0 == p2) *this = Sphere(p1, p2);
- else if (p1 == p2) *this = Sphere(p0, p2);
- else {
- Vector3 a = p1 - p0;
- Vector3 b = p2 - p0;
- Vector3 c = cross(a, b);
-
- float denominator = 2.0f * lengthSquared(c);
-
- if (!isZero(denominator)) {
- Vector3 d = (lengthSquared(b) * cross(c, a) + lengthSquared(a) * cross(b, c)) / denominator;
-
- center = p0 + d;
- radius = length(d) + radiusEpsilon;
-
- float d0 = length(p0 - center);
- float d1 = length(p1 - center);
- float d2 = length(p2 - center);
- nvDebugCheck(equal(d0, radius - radiusEpsilon));
- nvDebugCheck(equal(d1, radius - radiusEpsilon));
- nvDebugCheck(equal(d2, radius - radiusEpsilon));
- }
- else {
- // @@ This is a specialization of the code below, but really, the only thing we need to do here is to find the two most distant points.
- // Compute all possible spheres, invalidate those that do not contain the four points, keep the smallest.
- Sphere s0(p1, p2);
- float d0 = distanceSquared(s0, p0);
- if (d0 > 0) s0.radius = NV_FLOAT_MAX;
-
- Sphere s1(p0, p2);
- float d1 = distanceSquared(s1, p1);
- if (d1 > 0) s1.radius = NV_FLOAT_MAX;
-
- Sphere s2(p0, p1);
- float d2 = distanceSquared(s2, p2);
- if (d2 > 0) s1.radius = NV_FLOAT_MAX;
-
- if (s0.radius < s1.radius && s0.radius < s2.radius) {
- center = s0.center;
- radius = s0.radius;
- }
- else if (s1.radius < s2.radius) {
- center = s1.center;
- radius = s1.radius;
- }
- else {
- center = s2.center;
- radius = s2.radius;
- }
- }
- }
-}
-
-Sphere::Sphere(Vector3::Arg p0, Vector3::Arg p1, Vector3::Arg p2, Vector3::Arg p3)
-{
- if (p0 == p1 || p0 == p2 || p0 == p3) *this = Sphere(p1, p2, p3);
- else if (p1 == p2 || p1 == p3) *this = Sphere(p0, p2, p3);
- else if (p2 == p3) *this = Sphere(p0, p1, p2);
- else {
- // @@ This only works if the points are not coplanar!
- Vector3 a = p1 - p0;
- Vector3 b = p2 - p0;
- Vector3 c = p3 - p0;
-
- float denominator = 2.0f * dot(c, cross(a, b)); // triple product.
-
- if (!isZero(denominator)) {
- Vector3 d = (lengthSquared(c) * cross(a, b) + lengthSquared(b) * cross(c, a) + lengthSquared(a) * cross(b, c)) / denominator;
-
- center = p0 + d;
- radius = length(d) + radiusEpsilon;
-
- float d0 = length(p0 - center);
- float d1 = length(p1 - center);
- float d2 = length(p2 - center);
- float d3 = length(p3 - center);
- nvDebugCheck(equal(d0, radius - radiusEpsilon));
- nvDebugCheck(equal(d1, radius - radiusEpsilon));
- nvDebugCheck(equal(d2, radius - radiusEpsilon));
- nvDebugCheck(equal(d3, radius - radiusEpsilon));
- }
- else {
- // Compute all possible spheres, invalidate those that do not contain the four points, keep the smallest.
- Sphere s0(p1, p2, p3);
- float d0 = distanceSquared(s0, p0);
- if (d0 > 0) s0.radius = NV_FLOAT_MAX;
-
- Sphere s1(p0, p2, p3);
- float d1 = distanceSquared(s1, p1);
- if (d1 > 0) s1.radius = NV_FLOAT_MAX;
-
- Sphere s2(p0, p1, p3);
- float d2 = distanceSquared(s2, p2);
- if (d2 > 0) s2.radius = NV_FLOAT_MAX;
-
- Sphere s3(p0, p1, p2);
- float d3 = distanceSquared(s3, p3);
- if (d3 > 0) s2.radius = NV_FLOAT_MAX;
-
- if (s0.radius < s1.radius && s0.radius < s2.radius && s0.radius < s3.radius) {
- center = s0.center;
- radius = s0.radius;
- }
- else if (s1.radius < s2.radius && s1.radius < s3.radius) {
- center = s1.center;
- radius = s1.radius;
- }
- else if (s1.radius < s3.radius) {
- center = s2.center;
- radius = s2.radius;
- }
- else {
- center = s3.center;
- radius = s3.radius;
- }
- }
- }
-}
-
-
-float nv::distanceSquared(const Sphere & sphere, const Vector3 & point)
-{
- return lengthSquared(sphere.center - point) - square(sphere.radius);
-}
-
-
-
-// Implementation of "MiniBall" based on:
-// http://www.flipcode.com/archives/Smallest_Enclosing_Spheres.shtml
-
-static Sphere recurseMini(const Vector3 *P[], uint p, uint b = 0)
-{
- Sphere MB;
-
- switch(b)
- {
- case 0:
- MB = Sphere(*P[0]);
- break;
- case 1:
- MB = Sphere(*P[-1]);
- break;
- case 2:
- MB = Sphere(*P[-1], *P[-2]);
- break;
- case 3:
- MB = Sphere(*P[-1], *P[-2], *P[-3]);
- break;
- case 4:
- MB = Sphere(*P[-1], *P[-2], *P[-3], *P[-4]);
- return MB;
- }
-
- for (uint i = 0; i < p; i++)
- {
- if (distanceSquared(MB, *P[i]) > 0) // Signed square distance to sphere
- {
- for (uint j = i; j > 0; j--)
- {
- swap(P[j], P[j-1]);
- }
-
- MB = recurseMini(P + 1, i, b + 1);
- }
- }
-
- return MB;
-}
-
-static bool allInside(const Sphere & sphere, const Vector3 * pointArray, const uint pointCount) {
- for (uint i = 0; i < pointCount; i++) {
- if (distanceSquared(sphere, pointArray[i]) >= NV_EPSILON) {
- return false;
- }
- }
- return true;
-}
-
-
-Sphere nv::miniBall(const Vector3 * pointArray, const uint pointCount)
-{
- nvDebugCheck(pointArray != NULL);
- nvDebugCheck(pointCount > 0);
-
- const Vector3 **L = new const Vector3*[pointCount];
-
- for (uint i = 0; i < pointCount; i++) {
- L[i] = &pointArray[i];
- }
-
- Sphere sphere = recurseMini(L, pointCount);
-
- delete [] L;
-
- nvDebugCheck(allInside(sphere, pointArray, pointCount));
-
- return sphere;
-}
-
-
-// Approximate bounding sphere, based on "An Efficient Bounding Sphere" by Jack Ritter, from "Graphics Gems"
-Sphere nv::approximateSphere_Ritter(const Vector3 * pointArray, const uint pointCount)
-{
- nvDebugCheck(pointArray != NULL);
- nvDebugCheck(pointCount > 0);
-
- Vector3 xmin, xmax, ymin, ymax, zmin, zmax;
-
- xmin = xmax = ymin = ymax = zmin = zmax = pointArray[0];
-
- // FIRST PASS: find 6 minima/maxima points
- xmin.x = ymin.y = zmin.z = FLT_MAX;
- xmax.x = ymax.y = zmax.z = -FLT_MAX;
-
- for (uint i = 0; i < pointCount; i++)
- {
- const Vector3 & p = pointArray[i];
- if (p.x < xmin.x) xmin = p;
- if (p.x > xmax.x) xmax = p;
- if (p.y < ymin.y) ymin = p;
- if (p.y > ymax.y) ymax = p;
- if (p.z < zmin.z) zmin = p;
- if (p.z > zmax.z) zmax = p;
- }
-
- float xspan = lengthSquared(xmax - xmin);
- float yspan = lengthSquared(ymax - ymin);
- float zspan = lengthSquared(zmax - zmin);
-
- // Set points dia1 & dia2 to the maximally separated pair.
- Vector3 dia1 = xmin;
- Vector3 dia2 = xmax;
- float maxspan = xspan;
- if (yspan > maxspan) {
- maxspan = yspan;
- dia1 = ymin;
- dia2 = ymax;
- }
- if (zspan > maxspan) {
- dia1 = zmin;
- dia2 = zmax;
- }
-
- // |dia1-dia2| is a diameter of initial sphere
-
- // calc initial center
- Sphere sphere;
- sphere.center = (dia1 + dia2) / 2.0f;
-
- // calculate initial radius**2 and radius
- float rad_sq = lengthSquared(dia2 - sphere.center);
- sphere.radius = sqrtf(rad_sq);
-
-
- // SECOND PASS: increment current sphere
- for (uint i = 0; i < pointCount; i++)
- {
- const Vector3 & p = pointArray[i];
-
- float old_to_p_sq = lengthSquared(p - sphere.center);
-
- if (old_to_p_sq > rad_sq) // do r**2 test first
- {
- // this point is outside of current sphere
- float old_to_p = sqrtf(old_to_p_sq);
-
- // calc radius of new sphere
- sphere.radius = (sphere.radius + old_to_p) / 2.0f;
- rad_sq = sphere.radius * sphere.radius; // for next r**2 compare
-
- float old_to_new = old_to_p - sphere.radius;
-
- // calc center of new sphere
- sphere.center = (sphere.radius * sphere.center + old_to_new * p) / old_to_p;
- }
- }
-
- nvDebugCheck(allInside(sphere, pointArray, pointCount));
-
- return sphere;
-}
-
-
-static float computeSphereRadius(const Vector3 & center, const Vector3 * pointArray, const uint pointCount) {
-
- float maxRadius2 = 0;
-
- for (uint i = 0; i < pointCount; i++)
- {
- const Vector3 & p = pointArray[i];
-
- float r2 = lengthSquared(center - p);
-
- if (r2 > maxRadius2) {
- maxRadius2 = r2;
- }
- }
-
- return sqrtf(maxRadius2) + radiusEpsilon;
-}
-
-
-Sphere nv::approximateSphere_AABB(const Vector3 * pointArray, const uint pointCount)
-{
- nvDebugCheck(pointArray != NULL);
- nvDebugCheck(pointCount > 0);
-
- Box box;
- box.clearBounds();
-
- for (uint i = 0; i < pointCount; i++) {
- box.addPointToBounds(pointArray[i]);
- }
-
- Sphere sphere;
- sphere.center = box.center();
- sphere.radius = computeSphereRadius(sphere.center, pointArray, pointCount);
-
- nvDebugCheck(allInside(sphere, pointArray, pointCount));
-
- return sphere;
-}
-
-
-static void computeExtremalPoints(const Vector3 & dir, const Vector3 * pointArray, uint pointCount, Vector3 * minPoint, Vector3 * maxPoint) {
- nvDebugCheck(pointCount > 0);
-
- uint mini = 0;
- uint maxi = 0;
- float minDist = FLT_MAX;
- float maxDist = -FLT_MAX;
-
- for (uint i = 0; i < pointCount; i++) {
- float d = dot(dir, pointArray[i]);
-
- if (d < minDist) {
- minDist = d;
- mini = i;
- }
- if (d > maxDist) {
- maxDist = d;
- maxi = i;
- }
- }
- nvDebugCheck(minDist != FLT_MAX);
- nvDebugCheck(maxDist != -FLT_MAX);
-
- *minPoint = pointArray[mini];
- *maxPoint = pointArray[maxi];
-}
-
-// EPOS algorithm based on:
-// http://www.ep.liu.se/ecp/034/009/ecp083409.pdf
-Sphere nv::approximateSphere_EPOS6(const Vector3 * pointArray, uint pointCount)
-{
- nvDebugCheck(pointArray != NULL);
- nvDebugCheck(pointCount > 0);
-
- Vector3 extremalPoints[6];
-
- // Compute 6 extremal points.
- computeExtremalPoints(Vector3(1, 0, 0), pointArray, pointCount, extremalPoints+0, extremalPoints+1);
- computeExtremalPoints(Vector3(0, 1, 0), pointArray, pointCount, extremalPoints+2, extremalPoints+3);
- computeExtremalPoints(Vector3(0, 0, 1), pointArray, pointCount, extremalPoints+4, extremalPoints+5);
-
- Sphere sphere = miniBall(extremalPoints, 6);
- sphere.radius = computeSphereRadius(sphere.center, pointArray, pointCount);
-
- nvDebugCheck(allInside(sphere, pointArray, pointCount));
-
- return sphere;
-}
-
-Sphere nv::approximateSphere_EPOS14(const Vector3 * pointArray, uint pointCount)
-{
- nvDebugCheck(pointArray != NULL);
- nvDebugCheck(pointCount > 0);
-
- Vector3 extremalPoints[14];
-
- // Compute 14 extremal points.
- computeExtremalPoints(Vector3(1, 0, 0), pointArray, pointCount, extremalPoints+0, extremalPoints+1);
- computeExtremalPoints(Vector3(0, 1, 0), pointArray, pointCount, extremalPoints+2, extremalPoints+3);
- computeExtremalPoints(Vector3(0, 0, 1), pointArray, pointCount, extremalPoints+4, extremalPoints+5);
-
- float d = sqrtf(1.0f/3.0f);
-
- computeExtremalPoints(Vector3(d, d, d), pointArray, pointCount, extremalPoints+6, extremalPoints+7);
- computeExtremalPoints(Vector3(-d, d, d), pointArray, pointCount, extremalPoints+8, extremalPoints+9);
- computeExtremalPoints(Vector3(-d, -d, d), pointArray, pointCount, extremalPoints+10, extremalPoints+11);
- computeExtremalPoints(Vector3(d, -d, d), pointArray, pointCount, extremalPoints+12, extremalPoints+13);
-
-
- Sphere sphere = miniBall(extremalPoints, 14);
- sphere.radius = computeSphereRadius(sphere.center, pointArray, pointCount);
-
- nvDebugCheck(allInside(sphere, pointArray, pointCount));
-
- return sphere;
-}
-
-
-
diff --git a/thirdparty/thekla_atlas/nvmath/Sphere.h b/thirdparty/thekla_atlas/nvmath/Sphere.h
deleted file mode 100644
index 300731af44..0000000000
--- a/thirdparty/thekla_atlas/nvmath/Sphere.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#pragma once
-#ifndef NV_MATH_SPHERE_H
-#define NV_MATH_SPHERE_H
-
-#include "Vector.h"
-
-namespace nv
-{
-
- class Sphere
- {
- public:
- Sphere() {}
- Sphere(Vector3::Arg center, float radius) : center(center), radius(radius) {}
-
- Sphere(Vector3::Arg center) : center(center), radius(0.0f) {}
- Sphere(Vector3::Arg p0, Vector3::Arg p1);
- Sphere(Vector3::Arg p0, Vector3::Arg p1, Vector3::Arg p2);
- Sphere(Vector3::Arg p0, Vector3::Arg p1, Vector3::Arg p2, Vector3::Arg p3);
-
- Vector3 center;
- float radius;
- };
-
- // Returns negative values if point is inside.
- float distanceSquared(const Sphere & sphere, const Vector3 &point);
-
-
- // Welz's algorithm. Fairly slow, recursive implementation uses large stack.
- Sphere miniBall(const Vector3 * pointArray, uint pointCount);
-
- Sphere approximateSphere_Ritter(const Vector3 * pointArray, uint pointCount);
- Sphere approximateSphere_AABB(const Vector3 * pointArray, uint pointCount);
- Sphere approximateSphere_EPOS6(const Vector3 * pointArray, uint pointCount);
- Sphere approximateSphere_EPOS14(const Vector3 * pointArray, uint pointCount);
-
-
-} // nv namespace
-
-
-#endif // NV_MATH_SPHERE_H
diff --git a/thirdparty/thekla_atlas/nvmath/TypeSerialization.cpp b/thirdparty/thekla_atlas/nvmath/TypeSerialization.cpp
deleted file mode 100644
index 72fa678f47..0000000000
--- a/thirdparty/thekla_atlas/nvmath/TypeSerialization.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#include "TypeSerialization.h"
-
-#include "nvcore/Stream.h"
-
-#include "nvmath/Vector.h"
-#include "nvmath/Matrix.h"
-#include "nvmath/Quaternion.h"
-#include "nvmath/Basis.h"
-#include "nvmath/Box.h"
-#include "nvmath/Plane.inl"
-
-using namespace nv;
-
-Stream & nv::operator<< (Stream & s, Vector2 & v)
-{
- return s << v.x << v.y;
-}
-
-Stream & nv::operator<< (Stream & s, Vector3 & v)
-{
- return s << v.x << v.y << v.z;
-}
-
-Stream & nv::operator<< (Stream & s, Vector4 & v)
-{
- return s << v.x << v.y << v.z << v.w;
-}
-
-Stream & nv::operator<< (Stream & s, Matrix & m)
-{
- return s;
-}
-
-Stream & nv::operator<< (Stream & s, Quaternion & q)
-{
- return s << q.x << q.y << q.z << q.w;
-}
-
-Stream & nv::operator<< (Stream & s, Basis & basis)
-{
- return s << basis.tangent << basis.bitangent << basis.normal;
-}
-
-Stream & nv::operator<< (Stream & s, Box & box)
-{
- return s << box.minCorner << box.maxCorner;
-}
-
-Stream & nv::operator<< (Stream & s, Plane & plane)
-{
- return s << plane.v;
-}
diff --git a/thirdparty/thekla_atlas/nvmath/TypeSerialization.h b/thirdparty/thekla_atlas/nvmath/TypeSerialization.h
deleted file mode 100644
index 32d6de827e..0000000000
--- a/thirdparty/thekla_atlas/nvmath/TypeSerialization.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#pragma once
-#ifndef NV_MATH_TYPESERIALIZATION_H
-#define NV_MATH_TYPESERIALIZATION_H
-
-#include "nvmath.h"
-
-namespace nv
-{
- class Stream;
-
- class Vector2;
- class Vector3;
- class Vector4;
-
- class Matrix;
- class Quaternion;
- class Basis;
- class Box;
- class Plane;
-
- NVMATH_API Stream & operator<< (Stream & s, Vector2 & obj);
- NVMATH_API Stream & operator<< (Stream & s, Vector3 & obj);
- NVMATH_API Stream & operator<< (Stream & s, Vector4 & obj);
-
- NVMATH_API Stream & operator<< (Stream & s, Matrix & obj);
- NVMATH_API Stream & operator<< (Stream & s, Quaternion & obj);
- NVMATH_API Stream & operator<< (Stream & s, Basis & obj);
- NVMATH_API Stream & operator<< (Stream & s, Box & obj);
- NVMATH_API Stream & operator<< (Stream & s, Plane & obj);
-
-} // nv namespace
-
-#endif // NV_MATH_TYPESERIALIZATION_H
diff --git a/thirdparty/thekla_atlas/nvmath/Vector.cpp b/thirdparty/thekla_atlas/nvmath/Vector.cpp
deleted file mode 100644
index 9122a1b0e9..0000000000
--- a/thirdparty/thekla_atlas/nvmath/Vector.cpp
+++ /dev/null
@@ -1,4 +0,0 @@
-// This code is in the public domain -- castanyo@yahoo.es
-
-#include "Vector.h"
-#include "Vector.inl"
diff --git a/thirdparty/thekla_atlas/nvmath/Vector.h b/thirdparty/thekla_atlas/nvmath/Vector.h
deleted file mode 100644
index ad18672a8a..0000000000
--- a/thirdparty/thekla_atlas/nvmath/Vector.h
+++ /dev/null
@@ -1,149 +0,0 @@
-// This code is in the public domain -- castanyo@yahoo.es
-
-#pragma once
-#ifndef NV_MATH_VECTOR_H
-#define NV_MATH_VECTOR_H
-
-#include "nvmath.h"
-
-namespace nv
-{
- class NVMATH_CLASS Vector2
- {
- public:
- typedef Vector2 const & Arg;
-
- Vector2();
- explicit Vector2(float f);
- Vector2(float x, float y);
- Vector2(Vector2::Arg v);
-
- //template <typename T> explicit Vector2(const T & v) : x(v.x), y(v.y) {}
- //template <typename T> operator T() const { return T(x, y); }
-
- const Vector2 & operator=(Vector2::Arg v);
-
- const float * ptr() const;
-
- void set(float x, float y);
-
- Vector2 operator-() const;
- void operator+=(Vector2::Arg v);
- void operator-=(Vector2::Arg v);
- void operator*=(float s);
- void operator*=(Vector2::Arg v);
-
- friend bool operator==(Vector2::Arg a, Vector2::Arg b);
- friend bool operator!=(Vector2::Arg a, Vector2::Arg b);
-
- union {
- struct {
- float x, y;
- };
- float component[2];
- };
- };
-
- class NVMATH_CLASS Vector3
- {
- public:
- typedef Vector3 const & Arg;
-
- Vector3();
- explicit Vector3(float x);
- //explicit Vector3(int x) : x(float(x)), y(float(x)), z(float(x)) {}
- Vector3(float x, float y, float z);
- Vector3(Vector2::Arg v, float z);
- Vector3(Vector3::Arg v);
-
- //template <typename T> explicit Vector3(const T & v) : x(v.x), y(v.y), z(v.z) {}
- //template <typename T> operator T() const { return T(x, y, z); }
-
- const Vector3 & operator=(Vector3::Arg v);
-
- Vector2 xy() const;
-
- const float * ptr() const;
-
- void set(float x, float y, float z);
-
- Vector3 operator-() const;
- void operator+=(Vector3::Arg v);
- void operator-=(Vector3::Arg v);
- void operator*=(float s);
- void operator/=(float s);
- void operator*=(Vector3::Arg v);
- void operator/=(Vector3::Arg v);
-
- friend bool operator==(Vector3::Arg a, Vector3::Arg b);
- friend bool operator!=(Vector3::Arg a, Vector3::Arg b);
-
- union {
- struct {
- float x, y, z;
- };
- float component[3];
- };
- };
-
- class NVMATH_CLASS Vector4
- {
- public:
- typedef Vector4 const & Arg;
-
- Vector4();
- explicit Vector4(float x);
- Vector4(float x, float y, float z, float w);
- Vector4(Vector2::Arg v, float z, float w);
- Vector4(Vector2::Arg v, Vector2::Arg u);
- Vector4(Vector3::Arg v, float w);
- Vector4(Vector4::Arg v);
- // Vector4(const Quaternion & v);
-
- //template <typename T> explicit Vector4(const T & v) : x(v.x), y(v.y), z(v.z), w(v.w) {}
- //template <typename T> operator T() const { return T(x, y, z, w); }
-
- const Vector4 & operator=(Vector4::Arg v);
-
- Vector2 xy() const;
- Vector2 zw() const;
- Vector3 xyz() const;
-
- const float * ptr() const;
-
- void set(float x, float y, float z, float w);
-
- Vector4 operator-() const;
- void operator+=(Vector4::Arg v);
- void operator-=(Vector4::Arg v);
- void operator*=(float s);
- void operator/=(float s);
- void operator*=(Vector4::Arg v);
- void operator/=(Vector4::Arg v);
-
- friend bool operator==(Vector4::Arg a, Vector4::Arg b);
- friend bool operator!=(Vector4::Arg a, Vector4::Arg b);
-
- union {
- struct {
- float x, y, z, w;
- };
- float component[4];
- };
- };
-
-} // nv namespace
-
-// If we had these functions, they would be ambiguous, the compiler would not know which one to pick:
-//template <typename T> Vector2 to(const T & v) { return Vector2(v.x, v.y); }
-//template <typename T> Vector3 to(const T & v) { return Vector3(v.x, v.y, v.z); }
-//template <typename T> Vector4 to(const T & v) { return Vector4(v.x, v.y, v.z, v.z); }
-
-// We could use a cast operator so that we could infer the expected type, but that doesn't work the same way in all compilers and produces horrible error messages.
-
-// Instead we simply have explicit casts:
-template <typename T> T to(const nv::Vector2 & v) { NV_COMPILER_CHECK(sizeof(T) == sizeof(nv::Vector2)); return T(v.x, v.y); }
-template <typename T> T to(const nv::Vector3 & v) { NV_COMPILER_CHECK(sizeof(T) == sizeof(nv::Vector3)); return T(v.x, v.y, v.z); }
-template <typename T> T to(const nv::Vector4 & v) { NV_COMPILER_CHECK(sizeof(T) == sizeof(nv::Vector4)); return T(v.x, v.y, v.z, v.w); }
-
-#endif // NV_MATH_VECTOR_H
diff --git a/thirdparty/thekla_atlas/nvmath/Vector.inl b/thirdparty/thekla_atlas/nvmath/Vector.inl
deleted file mode 100644
index bcaec7bf2a..0000000000
--- a/thirdparty/thekla_atlas/nvmath/Vector.inl
+++ /dev/null
@@ -1,919 +0,0 @@
-// This code is in the public domain -- castanyo@yahoo.es
-
-#pragma once
-#ifndef NV_MATH_VECTOR_INL
-#define NV_MATH_VECTOR_INL
-
-#include "Vector.h"
-#include "nvcore/Utils.h" // min, max
-#include "nvcore/Hash.h" // hash
-
-namespace nv
-{
-
- // Helpers to convert vector types. Assume T has x,y members and 2 argument constructor.
- //template <typename T> T to(Vector2::Arg v) { return T(v.x, v.y); }
-
- // Helpers to convert vector types. Assume T has x,y,z members and 3 argument constructor.
- //template <typename T> T to(Vector3::Arg v) { return T(v.x, v.y, v.z); }
-
- // Helpers to convert vector types. Assume T has x,y,z members and 3 argument constructor.
- //template <typename T> T to(Vector4::Arg v) { return T(v.x, v.y, v.z, v.w); }
-
-
- // Vector2
- inline Vector2::Vector2() {}
- inline Vector2::Vector2(float f) : x(f), y(f) {}
- inline Vector2::Vector2(float x, float y) : x(x), y(y) {}
- inline Vector2::Vector2(Vector2::Arg v) : x(v.x), y(v.y) {}
-
- inline const Vector2 & Vector2::operator=(Vector2::Arg v)
- {
- x = v.x;
- y = v.y;
- return *this;
- }
-
- inline const float * Vector2::ptr() const
- {
- return &x;
- }
-
- inline void Vector2::set(float x, float y)
- {
- this->x = x;
- this->y = y;
- }
-
- inline Vector2 Vector2::operator-() const
- {
- return Vector2(-x, -y);
- }
-
- inline void Vector2::operator+=(Vector2::Arg v)
- {
- x += v.x;
- y += v.y;
- }
-
- inline void Vector2::operator-=(Vector2::Arg v)
- {
- x -= v.x;
- y -= v.y;
- }
-
- inline void Vector2::operator*=(float s)
- {
- x *= s;
- y *= s;
- }
-
- inline void Vector2::operator*=(Vector2::Arg v)
- {
- x *= v.x;
- y *= v.y;
- }
-
- inline bool operator==(Vector2::Arg a, Vector2::Arg b)
- {
- return a.x == b.x && a.y == b.y;
- }
- inline bool operator!=(Vector2::Arg a, Vector2::Arg b)
- {
- return a.x != b.x || a.y != b.y;
- }
-
-
- // Vector3
- inline Vector3::Vector3() {}
- inline Vector3::Vector3(float f) : x(f), y(f), z(f) {}
- inline Vector3::Vector3(float x, float y, float z) : x(x), y(y), z(z) {}
- inline Vector3::Vector3(Vector2::Arg v, float z) : x(v.x), y(v.y), z(z) {}
- inline Vector3::Vector3(Vector3::Arg v) : x(v.x), y(v.y), z(v.z) {}
-
- inline const Vector3 & Vector3::operator=(Vector3::Arg v)
- {
- x = v.x;
- y = v.y;
- z = v.z;
- return *this;
- }
-
-
- inline Vector2 Vector3::xy() const
- {
- return Vector2(x, y);
- }
-
- inline const float * Vector3::ptr() const
- {
- return &x;
- }
-
- inline void Vector3::set(float x, float y, float z)
- {
- this->x = x;
- this->y = y;
- this->z = z;
- }
-
- inline Vector3 Vector3::operator-() const
- {
- return Vector3(-x, -y, -z);
- }
-
- inline void Vector3::operator+=(Vector3::Arg v)
- {
- x += v.x;
- y += v.y;
- z += v.z;
- }
-
- inline void Vector3::operator-=(Vector3::Arg v)
- {
- x -= v.x;
- y -= v.y;
- z -= v.z;
- }
-
- inline void Vector3::operator*=(float s)
- {
- x *= s;
- y *= s;
- z *= s;
- }
-
- inline void Vector3::operator/=(float s)
- {
- float is = 1.0f / s;
- x *= is;
- y *= is;
- z *= is;
- }
-
- inline void Vector3::operator*=(Vector3::Arg v)
- {
- x *= v.x;
- y *= v.y;
- z *= v.z;
- }
-
- inline void Vector3::operator/=(Vector3::Arg v)
- {
- x /= v.x;
- y /= v.y;
- z /= v.z;
- }
-
- inline bool operator==(Vector3::Arg a, Vector3::Arg b)
- {
- return a.x == b.x && a.y == b.y && a.z == b.z;
- }
- inline bool operator!=(Vector3::Arg a, Vector3::Arg b)
- {
- return a.x != b.x || a.y != b.y || a.z != b.z;
- }
-
-
- // Vector4
- inline Vector4::Vector4() {}
- inline Vector4::Vector4(float f) : x(f), y(f), z(f), w(f) {}
- inline Vector4::Vector4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {}
- inline Vector4::Vector4(Vector2::Arg v, float z, float w) : x(v.x), y(v.y), z(z), w(w) {}
- inline Vector4::Vector4(Vector2::Arg v, Vector2::Arg u) : x(v.x), y(v.y), z(u.x), w(u.y) {}
- inline Vector4::Vector4(Vector3::Arg v, float w) : x(v.x), y(v.y), z(v.z), w(w) {}
- inline Vector4::Vector4(Vector4::Arg v) : x(v.x), y(v.y), z(v.z), w(v.w) {}
-
- inline const Vector4 & Vector4::operator=(const Vector4 & v)
- {
- x = v.x;
- y = v.y;
- z = v.z;
- w = v.w;
- return *this;
- }
-
- inline Vector2 Vector4::xy() const
- {
- return Vector2(x, y);
- }
-
- inline Vector2 Vector4::zw() const
- {
- return Vector2(z, w);
- }
-
- inline Vector3 Vector4::xyz() const
- {
- return Vector3(x, y, z);
- }
-
- inline const float * Vector4::ptr() const
- {
- return &x;
- }
-
- inline void Vector4::set(float x, float y, float z, float w)
- {
- this->x = x;
- this->y = y;
- this->z = z;
- this->w = w;
- }
-
- inline Vector4 Vector4::operator-() const
- {
- return Vector4(-x, -y, -z, -w);
- }
-
- inline void Vector4::operator+=(Vector4::Arg v)
- {
- x += v.x;
- y += v.y;
- z += v.z;
- w += v.w;
- }
-
- inline void Vector4::operator-=(Vector4::Arg v)
- {
- x -= v.x;
- y -= v.y;
- z -= v.z;
- w -= v.w;
- }
-
- inline void Vector4::operator*=(float s)
- {
- x *= s;
- y *= s;
- z *= s;
- w *= s;
- }
-
- inline void Vector4::operator/=(float s)
- {
- x /= s;
- y /= s;
- z /= s;
- w /= s;
- }
-
- inline void Vector4::operator*=(Vector4::Arg v)
- {
- x *= v.x;
- y *= v.y;
- z *= v.z;
- w *= v.w;
- }
-
- inline void Vector4::operator/=(Vector4::Arg v)
- {
- x /= v.x;
- y /= v.y;
- z /= v.z;
- w /= v.w;
- }
-
- inline bool operator==(Vector4::Arg a, Vector4::Arg b)
- {
- return a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w;
- }
- inline bool operator!=(Vector4::Arg a, Vector4::Arg b)
- {
- return a.x != b.x || a.y != b.y || a.z != b.z || a.w != b.w;
- }
-
-
-
- // Functions
-
-
- // Vector2
-
- inline Vector2 add(Vector2::Arg a, Vector2::Arg b)
- {
- return Vector2(a.x + b.x, a.y + b.y);
- }
- inline Vector2 operator+(Vector2::Arg a, Vector2::Arg b)
- {
- return add(a, b);
- }
-
- inline Vector2 sub(Vector2::Arg a, Vector2::Arg b)
- {
- return Vector2(a.x - b.x, a.y - b.y);
- }
- inline Vector2 operator-(Vector2::Arg a, Vector2::Arg b)
- {
- return sub(a, b);
- }
-
- inline Vector2 scale(Vector2::Arg v, float s)
- {
- return Vector2(v.x * s, v.y * s);
- }
-
- inline Vector2 scale(Vector2::Arg v, Vector2::Arg s)
- {
- return Vector2(v.x * s.x, v.y * s.y);
- }
-
- inline Vector2 operator*(Vector2::Arg v, float s)
- {
- return scale(v, s);
- }
-
- inline Vector2 operator*(Vector2::Arg v1, Vector2::Arg v2)
- {
- return Vector2(v1.x*v2.x, v1.y*v2.y);
- }
-
- inline Vector2 operator*(float s, Vector2::Arg v)
- {
- return scale(v, s);
- }
-
- inline Vector2 operator/(Vector2::Arg v, float s)
- {
- return scale(v, 1.0f/s);
- }
-
- inline Vector2 lerp(Vector2::Arg v1, Vector2::Arg v2, float t)
- {
- const float s = 1.0f - t;
- return Vector2(v1.x * s + t * v2.x, v1.y * s + t * v2.y);
- }
-
- inline float dot(Vector2::Arg a, Vector2::Arg b)
- {
- return a.x * b.x + a.y * b.y;
- }
-
- inline float lengthSquared(Vector2::Arg v)
- {
- return v.x * v.x + v.y * v.y;
- }
-
- inline float length(Vector2::Arg v)
- {
- return sqrtf(lengthSquared(v));
- }
-
- inline float distance(Vector2::Arg a, Vector2::Arg b)
- {
- return length(a - b);
- }
-
- inline float inverseLength(Vector2::Arg v)
- {
- return 1.0f / sqrtf(lengthSquared(v));
- }
-
- inline bool isNormalized(Vector2::Arg v, float epsilon = NV_NORMAL_EPSILON)
- {
- return equal(length(v), 1, epsilon);
- }
-
- inline Vector2 normalize(Vector2::Arg v, float epsilon = NV_EPSILON)
- {
- float l = length(v);
- nvDebugCheck(!isZero(l, epsilon));
- Vector2 n = scale(v, 1.0f / l);
- nvDebugCheck(isNormalized(n));
- return n;
- }
-
- inline Vector2 normalizeSafe(Vector2::Arg v, Vector2::Arg fallback, float epsilon = NV_EPSILON)
- {
- float l = length(v);
- if (isZero(l, epsilon)) {
- return fallback;
- }
- return scale(v, 1.0f / l);
- }
-
- // Safe, branchless normalization from Andy Firth. All error checking ommitted.
- // http://altdevblogaday.com/2011/08/21/practical-flt-point-tricks/
- inline Vector2 normalizeFast(Vector2::Arg v)
- {
- const float very_small_float = 1.0e-037f;
- float l = very_small_float + length(v);
- return scale(v, 1.0f / l);
- }
-
- inline bool equal(Vector2::Arg v1, Vector2::Arg v2, float epsilon = NV_EPSILON)
- {
- return equal(v1.x, v2.x, epsilon) && equal(v1.y, v2.y, epsilon);
- }
-
- inline Vector2 min(Vector2::Arg a, Vector2::Arg b)
- {
- return Vector2(min(a.x, b.x), min(a.y, b.y));
- }
-
- inline Vector2 max(Vector2::Arg a, Vector2::Arg b)
- {
- return Vector2(max(a.x, b.x), max(a.y, b.y));
- }
-
- inline Vector2 clamp(Vector2::Arg v, float min, float max)
- {
- return Vector2(clamp(v.x, min, max), clamp(v.y, min, max));
- }
-
- inline Vector2 saturate(Vector2::Arg v)
- {
- return Vector2(saturate(v.x), saturate(v.y));
- }
-
- inline bool isFinite(Vector2::Arg v)
- {
- return isFinite(v.x) && isFinite(v.y);
- }
-
- inline Vector2 validate(Vector2::Arg v, Vector2::Arg fallback = Vector2(0.0f))
- {
- if (!isFinite(v)) return fallback;
- Vector2 vf = v;
- nv::floatCleanup(vf.component, 2);
- return vf;
- }
-
- // Note, this is the area scaled by 2!
- inline float triangleArea(Vector2::Arg v0, Vector2::Arg v1)
- {
- return (v0.x * v1.y - v0.y * v1.x); // * 0.5f;
- }
- inline float triangleArea(Vector2::Arg a, Vector2::Arg b, Vector2::Arg c)
- {
- // IC: While it may be appealing to use the following expression:
- //return (c.x * a.y + a.x * b.y + b.x * c.y - b.x * a.y - c.x * b.y - a.x * c.y); // * 0.5f;
-
- // That's actually a terrible idea. Small triangles far from the origin can end up producing fairly large floating point
- // numbers and the results becomes very unstable and dependent on the order of the factors.
-
- // Instead, it's preferable to subtract the vertices first, and multiply the resulting small values together. The result
- // in this case is always much more accurate (as long as the triangle is small) and less dependent of the location of
- // the triangle.
-
- //return ((a.x - c.x) * (b.y - c.y) - (a.y - c.y) * (b.x - c.x)); // * 0.5f;
- return triangleArea(a-c, b-c);
- }
-
-
- template <>
- inline uint hash(const Vector2 & v, uint h)
- {
- return sdbmFloatHash(v.component, 2, h);
- }
-
-
-
- // Vector3
-
- inline Vector3 add(Vector3::Arg a, Vector3::Arg b)
- {
- return Vector3(a.x + b.x, a.y + b.y, a.z + b.z);
- }
- inline Vector3 add(Vector3::Arg a, float b)
- {
- return Vector3(a.x + b, a.y + b, a.z + b);
- }
- inline Vector3 operator+(Vector3::Arg a, Vector3::Arg b)
- {
- return add(a, b);
- }
- inline Vector3 operator+(Vector3::Arg a, float b)
- {
- return add(a, b);
- }
-
- inline Vector3 sub(Vector3::Arg a, Vector3::Arg b)
- {
- return Vector3(a.x - b.x, a.y - b.y, a.z - b.z);
- }
- inline Vector3 sub(Vector3::Arg a, float b)
- {
- return Vector3(a.x - b, a.y - b, a.z - b);
- }
- inline Vector3 operator-(Vector3::Arg a, Vector3::Arg b)
- {
- return sub(a, b);
- }
- inline Vector3 operator-(Vector3::Arg a, float b)
- {
- return sub(a, b);
- }
-
- inline Vector3 cross(Vector3::Arg a, Vector3::Arg b)
- {
- return Vector3(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x);
- }
-
- inline Vector3 scale(Vector3::Arg v, float s)
- {
- return Vector3(v.x * s, v.y * s, v.z * s);
- }
-
- inline Vector3 scale(Vector3::Arg v, Vector3::Arg s)
- {
- return Vector3(v.x * s.x, v.y * s.y, v.z * s.z);
- }
-
- inline Vector3 operator*(Vector3::Arg v, float s)
- {
- return scale(v, s);
- }
-
- inline Vector3 operator*(float s, Vector3::Arg v)
- {
- return scale(v, s);
- }
-
- inline Vector3 operator*(Vector3::Arg v, Vector3::Arg s)
- {
- return scale(v, s);
- }
-
- inline Vector3 operator/(Vector3::Arg v, float s)
- {
- return scale(v, 1.0f/s);
- }
-
- /*inline Vector3 add_scaled(Vector3::Arg a, Vector3::Arg b, float s)
- {
- return Vector3(a.x + b.x * s, a.y + b.y * s, a.z + b.z * s);
- }*/
-
- inline Vector3 lerp(Vector3::Arg v1, Vector3::Arg v2, float t)
- {
- const float s = 1.0f - t;
- return Vector3(v1.x * s + t * v2.x, v1.y * s + t * v2.y, v1.z * s + t * v2.z);
- }
-
- inline float dot(Vector3::Arg a, Vector3::Arg b)
- {
- return a.x * b.x + a.y * b.y + a.z * b.z;
- }
-
- inline float lengthSquared(Vector3::Arg v)
- {
- return v.x * v.x + v.y * v.y + v.z * v.z;
- }
-
- inline float length(Vector3::Arg v)
- {
- return sqrtf(lengthSquared(v));
- }
-
- inline float distance(Vector3::Arg a, Vector3::Arg b)
- {
- return length(a - b);
- }
-
- inline float distanceSquared(Vector3::Arg a, Vector3::Arg b)
- {
- return lengthSquared(a - b);
- }
-
- inline float inverseLength(Vector3::Arg v)
- {
- return 1.0f / sqrtf(lengthSquared(v));
- }
-
- inline bool isNormalized(Vector3::Arg v, float epsilon = NV_NORMAL_EPSILON)
- {
- return equal(length(v), 1, epsilon);
- }
-
- inline Vector3 normalize(Vector3::Arg v, float epsilon = NV_EPSILON)
- {
- float l = length(v);
- nvDebugCheck(!isZero(l, epsilon));
- Vector3 n = scale(v, 1.0f / l);
- nvDebugCheck(isNormalized(n));
- return n;
- }
-
- inline Vector3 normalizeSafe(Vector3::Arg v, Vector3::Arg fallback, float epsilon = NV_EPSILON)
- {
- float l = length(v);
- if (isZero(l, epsilon)) {
- return fallback;
- }
- return scale(v, 1.0f / l);
- }
-
- // Safe, branchless normalization from Andy Firth. All error checking ommitted.
- // http://altdevblogaday.com/2011/08/21/practical-flt-point-tricks/
- inline Vector3 normalizeFast(Vector3::Arg v)
- {
- const float very_small_float = 1.0e-037f;
- float l = very_small_float + length(v);
- return scale(v, 1.0f / l);
- }
-
- inline bool equal(Vector3::Arg v1, Vector3::Arg v2, float epsilon = NV_EPSILON)
- {
- return equal(v1.x, v2.x, epsilon) && equal(v1.y, v2.y, epsilon) && equal(v1.z, v2.z, epsilon);
- }
-
- inline Vector3 min(Vector3::Arg a, Vector3::Arg b)
- {
- return Vector3(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z));
- }
-
- inline Vector3 max(Vector3::Arg a, Vector3::Arg b)
- {
- return Vector3(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z));
- }
-
- inline Vector3 clamp(Vector3::Arg v, float min, float max)
- {
- return Vector3(clamp(v.x, min, max), clamp(v.y, min, max), clamp(v.z, min, max));
- }
-
- inline Vector3 saturate(Vector3::Arg v)
- {
- return Vector3(saturate(v.x), saturate(v.y), saturate(v.z));
- }
-
- inline Vector3 floor(Vector3::Arg v)
- {
- return Vector3(floorf(v.x), floorf(v.y), floorf(v.z));
- }
-
- inline Vector3 ceil(Vector3::Arg v)
- {
- return Vector3(ceilf(v.x), ceilf(v.y), ceilf(v.z));
- }
-
- inline bool isFinite(Vector3::Arg v)
- {
- return isFinite(v.x) && isFinite(v.y) && isFinite(v.z);
- }
-
- inline Vector3 validate(Vector3::Arg v, Vector3::Arg fallback = Vector3(0.0f))
- {
- if (!isFinite(v)) return fallback;
- Vector3 vf = v;
- nv::floatCleanup(vf.component, 3);
- return vf;
- }
-
- inline Vector3 reflect(Vector3::Arg v, Vector3::Arg n)
- {
- return v - (2 * dot(v, n)) * n;
- }
-
- template <>
- inline uint hash(const Vector3 & v, uint h)
- {
- return sdbmFloatHash(v.component, 3, h);
- }
-
-
- // Vector4
-
- inline Vector4 add(Vector4::Arg a, Vector4::Arg b)
- {
- return Vector4(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w);
- }
- inline Vector4 operator+(Vector4::Arg a, Vector4::Arg b)
- {
- return add(a, b);
- }
-
- inline Vector4 sub(Vector4::Arg a, Vector4::Arg b)
- {
- return Vector4(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w);
- }
- inline Vector4 operator-(Vector4::Arg a, Vector4::Arg b)
- {
- return sub(a, b);
- }
-
- inline Vector4 scale(Vector4::Arg v, float s)
- {
- return Vector4(v.x * s, v.y * s, v.z * s, v.w * s);
- }
-
- inline Vector4 scale(Vector4::Arg v, Vector4::Arg s)
- {
- return Vector4(v.x * s.x, v.y * s.y, v.z * s.z, v.w * s.w);
- }
-
- inline Vector4 operator*(Vector4::Arg v, float s)
- {
- return scale(v, s);
- }
-
- inline Vector4 operator*(float s, Vector4::Arg v)
- {
- return scale(v, s);
- }
-
- inline Vector4 operator*(Vector4::Arg v, Vector4::Arg s)
- {
- return scale(v, s);
- }
-
- inline Vector4 operator/(Vector4::Arg v, float s)
- {
- return scale(v, 1.0f/s);
- }
-
- /*inline Vector4 add_scaled(Vector4::Arg a, Vector4::Arg b, float s)
- {
- return Vector4(a.x + b.x * s, a.y + b.y * s, a.z + b.z * s, a.w + b.w * s);
- }*/
-
- inline Vector4 lerp(Vector4::Arg v1, Vector4::Arg v2, float t)
- {
- const float s = 1.0f - t;
- return Vector4(v1.x * s + t * v2.x, v1.y * s + t * v2.y, v1.z * s + t * v2.z, v1.w * s + t * v2.w);
- }
-
- inline float dot(Vector4::Arg a, Vector4::Arg b)
- {
- return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
- }
-
- inline float lengthSquared(Vector4::Arg v)
- {
- return v.x * v.x + v.y * v.y + v.z * v.z + v.w * v.w;
- }
-
- inline float length(Vector4::Arg v)
- {
- return sqrtf(lengthSquared(v));
- }
-
- inline float inverseLength(Vector4::Arg v)
- {
- return 1.0f / sqrtf(lengthSquared(v));
- }
-
- inline bool isNormalized(Vector4::Arg v, float epsilon = NV_NORMAL_EPSILON)
- {
- return equal(length(v), 1, epsilon);
- }
-
- inline Vector4 normalize(Vector4::Arg v, float epsilon = NV_EPSILON)
- {
- float l = length(v);
- nvDebugCheck(!isZero(l, epsilon));
- Vector4 n = scale(v, 1.0f / l);
- nvDebugCheck(isNormalized(n));
- return n;
- }
-
- inline Vector4 normalizeSafe(Vector4::Arg v, Vector4::Arg fallback, float epsilon = NV_EPSILON)
- {
- float l = length(v);
- if (isZero(l, epsilon)) {
- return fallback;
- }
- return scale(v, 1.0f / l);
- }
-
- // Safe, branchless normalization from Andy Firth. All error checking ommitted.
- // http://altdevblogaday.com/2011/08/21/practical-flt-point-tricks/
- inline Vector4 normalizeFast(Vector4::Arg v)
- {
- const float very_small_float = 1.0e-037f;
- float l = very_small_float + length(v);
- return scale(v, 1.0f / l);
- }
-
- inline bool equal(Vector4::Arg v1, Vector4::Arg v2, float epsilon = NV_EPSILON)
- {
- return equal(v1.x, v2.x, epsilon) && equal(v1.y, v2.y, epsilon) && equal(v1.z, v2.z, epsilon) && equal(v1.w, v2.w, epsilon);
- }
-
- inline Vector4 min(Vector4::Arg a, Vector4::Arg b)
- {
- return Vector4(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z), min(a.w, b.w));
- }
-
- inline Vector4 max(Vector4::Arg a, Vector4::Arg b)
- {
- return Vector4(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z), max(a.w, b.w));
- }
-
- inline Vector4 clamp(Vector4::Arg v, float min, float max)
- {
- return Vector4(clamp(v.x, min, max), clamp(v.y, min, max), clamp(v.z, min, max), clamp(v.w, min, max));
- }
-
- inline Vector4 saturate(Vector4::Arg v)
- {
- return Vector4(saturate(v.x), saturate(v.y), saturate(v.z), saturate(v.w));
- }
-
- inline bool isFinite(Vector4::Arg v)
- {
- return isFinite(v.x) && isFinite(v.y) && isFinite(v.z) && isFinite(v.w);
- }
-
- inline Vector4 validate(Vector4::Arg v, Vector4::Arg fallback = Vector4(0.0f))
- {
- if (!isFinite(v)) return fallback;
- Vector4 vf = v;
- nv::floatCleanup(vf.component, 4);
- return vf;
- }
-
- template <>
- inline uint hash(const Vector4 & v, uint h)
- {
- return sdbmFloatHash(v.component, 4, h);
- }
-
-
-#if NV_OS_IOS // LLVM is not happy with implicit conversion of immediate constants to float
-
- //int:
-
- inline Vector2 scale(Vector2::Arg v, int s)
- {
- return Vector2(v.x * s, v.y * s);
- }
-
- inline Vector2 operator*(Vector2::Arg v, int s)
- {
- return scale(v, s);
- }
-
- inline Vector2 operator*(int s, Vector2::Arg v)
- {
- return scale(v, s);
- }
-
- inline Vector2 operator/(Vector2::Arg v, int s)
- {
- return scale(v, 1.0f/s);
- }
-
- inline Vector3 scale(Vector3::Arg v, int s)
- {
- return Vector3(v.x * s, v.y * s, v.z * s);
- }
-
- inline Vector3 operator*(Vector3::Arg v, int s)
- {
- return scale(v, s);
- }
-
- inline Vector3 operator*(int s, Vector3::Arg v)
- {
- return scale(v, s);
- }
-
- inline Vector3 operator/(Vector3::Arg v, int s)
- {
- return scale(v, 1.0f/s);
- }
-
- inline Vector4 scale(Vector4::Arg v, int s)
- {
- return Vector4(v.x * s, v.y * s, v.z * s, v.w * s);
- }
-
- inline Vector4 operator*(Vector4::Arg v, int s)
- {
- return scale(v, s);
- }
-
- inline Vector4 operator*(int s, Vector4::Arg v)
- {
- return scale(v, s);
- }
-
- inline Vector4 operator/(Vector4::Arg v, int s)
- {
- return scale(v, 1.0f/s);
- }
-
- //double:
-
- inline Vector3 operator*(Vector3::Arg v, double s)
- {
- return scale(v, (float)s);
- }
-
- inline Vector3 operator*(double s, Vector3::Arg v)
- {
- return scale(v, (float)s);
- }
-
- inline Vector3 operator/(Vector3::Arg v, double s)
- {
- return scale(v, 1.f/((float)s));
- }
-
-#endif //NV_OS_IOS
-
-} // nv namespace
-
-#endif // NV_MATH_VECTOR_INL
diff --git a/thirdparty/thekla_atlas/nvmath/ftoi.h b/thirdparty/thekla_atlas/nvmath/ftoi.h
deleted file mode 100644
index 182c56d1c3..0000000000
--- a/thirdparty/thekla_atlas/nvmath/ftoi.h
+++ /dev/null
@@ -1,261 +0,0 @@
-// This code is in the public domain -- castano@gmail.com
-
-#pragma once
-#ifndef NV_MATH_FTOI_H
-#define NV_MATH_FTOI_H
-
-#include "nvmath/nvmath.h"
-
-#include <math.h>
-
-namespace nv
-{
- // Optimized float to int conversions. See:
- // http://cbloomrants.blogspot.com/2009/01/01-17-09-float-to-int.html
- // http://www.stereopsis.com/sree/fpu2006.html
- // http://assemblyrequired.crashworks.org/2009/01/12/why-you-should-never-cast-floats-to-ints/
- // http://chrishecker.com/Miscellaneous_Technical_Articles#Floating_Point
-
-
- union DoubleAnd64 {
- uint64 i;
- double d;
- };
-
- static const double floatutil_xs_doublemagic = (6755399441055744.0); // 2^52 * 1.5
- static const double floatutil_xs_doublemagicdelta = (1.5e-8); // almost .5f = .5f + 1e^(number of exp bit)
- static const double floatutil_xs_doublemagicroundeps = (0.5f - floatutil_xs_doublemagicdelta); // almost .5f = .5f - 1e^(number of exp bit)
-
- NV_FORCEINLINE int ftoi_round_xs(double val, double magic) {
-#if 1
- DoubleAnd64 dunion;
- dunion.d = val + magic;
- return (int32) dunion.i; // just cast to grab the bottom bits
-#else
- val += magic;
- return ((int*)&val)[0]; // @@ Assumes little endian.
-#endif
- }
-
- NV_FORCEINLINE int ftoi_round_xs(float val) {
- return ftoi_round_xs(val, floatutil_xs_doublemagic);
- }
-
- NV_FORCEINLINE int ftoi_floor_xs(float val) {
- return ftoi_round_xs(val - floatutil_xs_doublemagicroundeps, floatutil_xs_doublemagic);
- }
-
- NV_FORCEINLINE int ftoi_ceil_xs(float val) {
- return ftoi_round_xs(val + floatutil_xs_doublemagicroundeps, floatutil_xs_doublemagic);
- }
-
- NV_FORCEINLINE int ftoi_trunc_xs(float val) {
- return (val<0) ? ftoi_ceil_xs(val) : ftoi_floor_xs(val);
- }
-
-// -- GODOT start --
-//#if NV_CPU_X86 || NV_CPU_X86_64
-#if NV_USE_SSE
-// -- GODOT end --
-
- NV_FORCEINLINE int ftoi_round_sse(float f) {
- return _mm_cvt_ss2si(_mm_set_ss(f));
- }
-
- NV_FORCEINLINE int ftoi_trunc_sse(float f) {
- return _mm_cvtt_ss2si(_mm_set_ss(f));
- }
-
-#endif
-
-
-
-#if NV_USE_SSE
-
- NV_FORCEINLINE int ftoi_round(float val) {
- return ftoi_round_sse(val);
- }
-
- NV_FORCEINLINE int ftoi_trunc(float f) {
- return ftoi_trunc_sse(f);
- }
-
- // We can probably do better than this. See for example:
- // http://dss.stephanierct.com/DevBlog/?p=8
- NV_FORCEINLINE int ftoi_floor(float val) {
- return ftoi_round(floorf(val));
- }
-
- NV_FORCEINLINE int ftoi_ceil(float val) {
- return ftoi_round(ceilf(val));
- }
-
-#else
-
- // In theory this should work with any double floating point math implementation, but it appears that MSVC produces incorrect code
- // when SSE2 is targeted and fast math is enabled (/arch:SSE2 & /fp:fast). These problems go away with /fp:precise, which is the default mode.
-
- NV_FORCEINLINE int ftoi_round(float val) {
- return ftoi_round_xs(val);
- }
-
- NV_FORCEINLINE int ftoi_floor(float val) {
- return ftoi_floor_xs(val);
- }
-
- NV_FORCEINLINE int ftoi_ceil(float val) {
- return ftoi_ceil_xs(val);
- }
-
- NV_FORCEINLINE int ftoi_trunc(float f) {
- return ftoi_trunc_xs(f);
- }
-
-#endif
-
-
- inline void test_ftoi() {
-
- // Round to nearest integer.
- nvCheck(ftoi_round(0.1f) == 0);
- nvCheck(ftoi_round(0.6f) == 1);
- nvCheck(ftoi_round(-0.2f) == 0);
- nvCheck(ftoi_round(-0.7f) == -1);
- nvCheck(ftoi_round(10.1f) == 10);
- nvCheck(ftoi_round(10.6f) == 11);
- nvCheck(ftoi_round(-90.1f) == -90);
- nvCheck(ftoi_round(-90.6f) == -91);
-
- nvCheck(ftoi_round(0) == 0);
- nvCheck(ftoi_round(1) == 1);
- nvCheck(ftoi_round(-1) == -1);
-
- nvCheck(ftoi_round(0.5f) == 0); // How are midpoints rounded? Bankers rounding.
- nvCheck(ftoi_round(1.5f) == 2);
- nvCheck(ftoi_round(2.5f) == 2);
- nvCheck(ftoi_round(3.5f) == 4);
- nvCheck(ftoi_round(4.5f) == 4);
- nvCheck(ftoi_round(-0.5f) == 0);
- nvCheck(ftoi_round(-1.5f) == -2);
-
-
- // Truncation (round down if > 0, round up if < 0).
- nvCheck(ftoi_trunc(0.1f) == 0);
- nvCheck(ftoi_trunc(0.6f) == 0);
- nvCheck(ftoi_trunc(-0.2f) == 0);
- nvCheck(ftoi_trunc(-0.7f) == 0); // @@ When using /arch:SSE2 in Win32, msvc produce wrong code for this one. It is skipping the addition.
- nvCheck(ftoi_trunc(1.99f) == 1);
- nvCheck(ftoi_trunc(-1.2f) == -1);
-
- // Floor (round down).
- nvCheck(ftoi_floor(0.1f) == 0);
- nvCheck(ftoi_floor(0.6f) == 0);
- nvCheck(ftoi_floor(-0.2f) == -1);
- nvCheck(ftoi_floor(-0.7f) == -1);
- nvCheck(ftoi_floor(1.99f) == 1);
- nvCheck(ftoi_floor(-1.2f) == -2);
-
- nvCheck(ftoi_floor(0) == 0);
- nvCheck(ftoi_floor(1) == 1);
- nvCheck(ftoi_floor(-1) == -1);
- nvCheck(ftoi_floor(2) == 2);
- nvCheck(ftoi_floor(-2) == -2);
-
- // Ceil (round up).
- nvCheck(ftoi_ceil(0.1f) == 1);
- nvCheck(ftoi_ceil(0.6f) == 1);
- nvCheck(ftoi_ceil(-0.2f) == 0);
- nvCheck(ftoi_ceil(-0.7f) == 0);
- nvCheck(ftoi_ceil(1.99f) == 2);
- nvCheck(ftoi_ceil(-1.2f) == -1);
-
- nvCheck(ftoi_ceil(0) == 0);
- nvCheck(ftoi_ceil(1) == 1);
- nvCheck(ftoi_ceil(-1) == -1);
- nvCheck(ftoi_ceil(2) == 2);
- nvCheck(ftoi_ceil(-2) == -2);
- }
-
-
-
-
-
- // Safe versions using standard casts.
-
- inline int iround(float f)
- {
- return ftoi_round(f);
- //return int(floorf(f + 0.5f));
- }
-
- inline int iround(double f)
- {
- return int(::floor(f + 0.5));
- }
-
- inline int ifloor(float f)
- {
- return ftoi_floor(f);
- //return int(floorf(f));
- }
-
- inline int iceil(float f)
- {
- return int(ceilf(f));
- }
-
-
-
- // I'm always confused about which quantizer to use. I think we should choose a quantizer based on how the values are expanded later and this is generally using the 'exact endpoints' rule.
- // Some notes from cbloom: http://cbloomrants.blogspot.com/2011/07/07-26-11-pixel-int-to-float-options.html
-
- // Quantize a float in the [0,1] range, using exact end points or uniform bins.
- inline float quantizeFloat(float x, uint bits, bool exactEndPoints = true) {
- nvDebugCheck(bits <= 16);
-
- float range = float(1 << bits);
- if (exactEndPoints) {
- return floorf(x * (range-1) + 0.5f) / (range-1);
- }
- else {
- return (floorf(x * range) + 0.5f) / range;
- }
- }
-
-
- // This is the most common rounding mode:
- //
- // 0 1 2 3
- // |___|_______|_______|___|
- // 0 1
- //
- // You get that if you take the unit floating point number multiply by 'N-1' and round to nearest. That is, `i = round(f * (N-1))`.
- // You reconstruct the original float dividing by 'N-1': `f = i / (N-1)`
-
-
- // 0 1 2 3
- // |_____|_____|_____|_____|
- // 0 1
-
- /*enum BinningMode {
- RoundMode_ExactEndPoints,
- RoundMode_UniformBins,
- };*/
-
- template <int N>
- inline uint unitFloatToFixed(float f) {
- return ftoi_round(f * ((1<<N)-1));
- }
-
- inline uint8 unitFloatToFixed8(float f) {
- return (uint8)unitFloatToFixed<8>(f);
- }
-
- inline uint16 unitFloatToFixed16(float f) {
- return (uint16)unitFloatToFixed<16>(f);
- }
-
-
-} // nv
-
-#endif // NV_MATH_FTOI_H
diff --git a/thirdparty/thekla_atlas/nvmath/nvmath.h b/thirdparty/thekla_atlas/nvmath/nvmath.h
deleted file mode 100644
index a697f9293d..0000000000
--- a/thirdparty/thekla_atlas/nvmath/nvmath.h
+++ /dev/null
@@ -1,342 +0,0 @@
-// This code is in the public domain -- castanyo@yahoo.es
-
-#pragma once
-#ifndef NV_MATH_H
-#define NV_MATH_H
-
-#include "nvcore/nvcore.h"
-#include "nvcore/Debug.h" // nvDebugCheck
-#include "nvcore/Utils.h" // max, clamp
-
-#include <math.h>
-
-#if NV_OS_WIN32 || NV_OS_XBOX || NV_OS_DURANGO
-#include <float.h> // finite, isnan
-#endif
-
-// -- GODOT start --
-//#if NV_CPU_X86 || NV_CPU_X86_64
-// //#include <intrin.h>
-// #include <xmmintrin.h>
-//#endif
-// -- GODOT end --
-
-
-
-// Function linkage
-#if NVMATH_SHARED
-#ifdef NVMATH_EXPORTS
-#define NVMATH_API DLL_EXPORT
-#define NVMATH_CLASS DLL_EXPORT_CLASS
-#else
-#define NVMATH_API DLL_IMPORT
-#define NVMATH_CLASS DLL_IMPORT
-#endif
-#else // NVMATH_SHARED
-#define NVMATH_API
-#define NVMATH_CLASS
-#endif // NVMATH_SHARED
-
-// Set some reasonable defaults.
-#ifndef NV_USE_ALTIVEC
-# define NV_USE_ALTIVEC NV_CPU_PPC
-//# define NV_USE_ALTIVEC defined(__VEC__)
-#endif
-
-#ifndef NV_USE_SSE
-# if NV_CPU_X86_64
- // x64 always supports at least SSE2
-# define NV_USE_SSE 2
-# elif NV_CC_MSVC && defined(_M_IX86_FP)
- // Also on x86 with the /arch:SSE flag in MSVC.
-# define NV_USE_SSE _M_IX86_FP // 1=SSE, 2=SS2
-# elif defined(__SSE__)
-# define NV_USE_SSE 1
-# elif defined(__SSE2__)
-# define NV_USE_SSE 2
-# else
- // Otherwise we assume no SSE.
-# define NV_USE_SSE 0
-# endif
-#endif
-
-
-// Internally set NV_USE_SIMD when either altivec or sse is available.
-#if NV_USE_ALTIVEC && NV_USE_SSE
-# error "Cannot enable both altivec and sse!"
-#endif
-
-
-// -- GODOT start --
-#if NV_USE_SSE
- //#include <intrin.h>
- #include <xmmintrin.h>
-#endif
-// -- GODOT end --
-
-
-#ifndef PI
-#define PI float(3.1415926535897932384626433833)
-#endif
-
-#define NV_EPSILON (0.0001f)
-#define NV_NORMAL_EPSILON (0.001f)
-
-/*
-#define SQ(r) ((r)*(r))
-
-#define SIGN_BITMASK 0x80000000
-
-/// Integer representation of a floating-point value.
-#define IR(x) ((uint32 &)(x))
-
-/// Absolute integer representation of a floating-point value
-#define AIR(x) (IR(x) & 0x7fffffff)
-
-/// Floating-point representation of an integer value.
-#define FR(x) ((float&)(x))
-
-/// Integer-based comparison of a floating point value.
-/// Don't use it blindly, it can be faster or slower than the FPU comparison, depends on the context.
-#define IS_NEGATIVE_FLOAT(x) (IR(x)&SIGN_BITMASK)
-*/
-
-extern "C" inline double sqrt_assert(const double f)
-{
- nvDebugCheck(f >= 0.0f);
- return sqrt(f);
-}
-
-inline float sqrtf_assert(const float f)
-{
- nvDebugCheck(f >= 0.0f);
- return sqrtf(f);
-}
-
-extern "C" inline double acos_assert(const double f)
-{
- nvDebugCheck(f >= -1.0f && f <= 1.0f);
- return acos(f);
-}
-
-inline float acosf_assert(const float f)
-{
- nvDebugCheck(f >= -1.0f && f <= 1.0f);
- return acosf(f);
-}
-
-extern "C" inline double asin_assert(const double f)
-{
- nvDebugCheck(f >= -1.0f && f <= 1.0f);
- return asin(f);
-}
-
-inline float asinf_assert(const float f)
-{
- nvDebugCheck(f >= -1.0f && f <= 1.0f);
- return asinf(f);
-}
-
-// Replace default functions with asserting ones.
-#if !NV_CC_MSVC || (NV_CC_MSVC && (_MSC_VER < 1700)) // IC: Apparently this was causing problems in Visual Studio 2012. See Issue 194: https://code.google.com/p/nvidia-texture-tools/issues/detail?id=194
-#define sqrt sqrt_assert
-#define sqrtf sqrtf_assert
-#define acos acos_assert
-#define acosf acosf_assert
-#define asin asin_assert
-#define asinf asinf_assert
-#endif
-
-#if NV_CC_MSVC
-NV_FORCEINLINE float log2f(float x)
-{
- nvCheck(x >= 0);
- return logf(x) / logf(2.0f);
-}
-NV_FORCEINLINE float exp2f(float x)
-{
- return powf(2.0f, x);
-}
-#endif
-
-namespace nv
-{
- inline float toRadian(float degree) { return degree * (PI / 180.0f); }
- inline float toDegree(float radian) { return radian * (180.0f / PI); }
-
- // Robust floating point comparisons:
- // http://realtimecollisiondetection.net/blog/?p=89
- inline bool equal(const float f0, const float f1, const float epsilon = NV_EPSILON)
- {
- //return fabs(f0-f1) <= epsilon;
- return fabs(f0-f1) <= epsilon * max3(1.0f, fabsf(f0), fabsf(f1));
- }
-
- inline bool isZero(const float f, const float epsilon = NV_EPSILON)
- {
- return fabs(f) <= epsilon;
- }
-
- inline bool isFinite(const float f)
- {
-#if NV_OS_WIN32 || NV_OS_XBOX || NV_OS_DURANGO
- return _finite(f) != 0;
-#elif NV_OS_DARWIN || NV_OS_FREEBSD || NV_OS_OPENBSD || NV_OS_ORBIS || NV_OS_LINUX
- return isfinite(f);
-#else
-# error "isFinite not supported"
-#endif
- //return std::isfinite (f);
- //return finite (f);
- }
-
- inline bool isNan(const float f)
- {
-#if NV_OS_WIN32 || NV_OS_XBOX || NV_OS_DURANGO
- return _isnan(f) != 0;
-#elif NV_OS_DARWIN || NV_OS_FREEBSD || NV_OS_OPENBSD || NV_OS_ORBIS || NV_OS_LINUX
- return isnan(f);
-#else
-# error "isNan not supported"
-#endif
- }
-
- inline uint log2(uint32 i)
- {
- uint32 value = 0;
- while( i >>= 1 ) value++;
- return value;
- }
-
- inline uint log2(uint64 i)
- {
- uint64 value = 0;
- while (i >>= 1) value++;
- return U32(value);
- }
-
- inline float lerp(float f0, float f1, float t)
- {
- const float s = 1.0f - t;
- return f0 * s + f1 * t;
- }
-
- inline float square(float f) { return f * f; }
- inline int square(int i) { return i * i; }
-
- inline float cube(float f) { return f * f * f; }
- inline int cube(int i) { return i * i * i; }
-
- inline float frac(float f)
- {
- return f - floor(f);
- }
-
- inline float floatRound(float f)
- {
- return floorf(f + 0.5f);
- }
-
- // Eliminates negative zeros from a float array.
- inline void floatCleanup(float * fp, int n)
- {
- for (int i = 0; i < n; i++) {
- //nvDebugCheck(isFinite(fp[i]));
- union { float f; uint32 i; } x = { fp[i] };
- if (x.i == 0x80000000) fp[i] = 0.0f;
- }
- }
-
- inline float saturate(float f) {
- return clamp(f, 0.0f, 1.0f);
- }
-
- inline float linearstep(float edge0, float edge1, float x) {
- // Scale, bias and saturate x to 0..1 range
- return saturate((x - edge0) / (edge1 - edge0));
- }
-
- inline float smoothstep(float edge0, float edge1, float x) {
- x = linearstep(edge0, edge1, x);
-
- // Evaluate polynomial
- return x*x*(3 - 2*x);
- }
-
- inline int sign(float a)
- {
- return (a > 0) - (a < 0);
- //if (a > 0.0f) return 1;
- //if (a < 0.0f) return -1;
- //return 0;
- }
-
- union Float754 {
- unsigned int raw;
- float value;
- struct {
- #if NV_BIG_ENDIAN
- unsigned int negative:1;
- unsigned int biasedexponent:8;
- unsigned int mantissa:23;
- #else
- unsigned int mantissa:23;
- unsigned int biasedexponent:8;
- unsigned int negative:1;
- #endif
- } field;
- };
-
- // Return the exponent of x ~ Floor(Log2(x))
- inline int floatExponent(float x)
- {
- Float754 f;
- f.value = x;
- return (f.field.biasedexponent - 127);
- }
-
-
- // FloatRGB9E5
- union Float3SE {
- uint32 v;
- struct {
- #if NV_BIG_ENDIAN
- uint32 e : 5;
- uint32 zm : 9;
- uint32 ym : 9;
- uint32 xm : 9;
- #else
- uint32 xm : 9;
- uint32 ym : 9;
- uint32 zm : 9;
- uint32 e : 5;
- #endif
- };
- };
-
- // FloatR11G11B10
- union Float3PK {
- uint32 v;
- struct {
- #if NV_BIG_ENDIAN
- uint32 ze : 5;
- uint32 zm : 5;
- uint32 ye : 5;
- uint32 ym : 6;
- uint32 xe : 5;
- uint32 xm : 6;
- #else
- uint32 xm : 6;
- uint32 xe : 5;
- uint32 ym : 6;
- uint32 ye : 5;
- uint32 zm : 5;
- uint32 ze : 5;
- #endif
- };
- };
-
-
-} // nv
-
-#endif // NV_MATH_H
diff --git a/thirdparty/thekla_atlas/nvmesh/BaseMesh.cpp b/thirdparty/thekla_atlas/nvmesh/BaseMesh.cpp
deleted file mode 100644
index f17d3b46fd..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/BaseMesh.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#include "BaseMesh.h"
-#include "Stream.h"
-#include "nvmath/TypeSerialization.h"
-
-
-namespace nv
-{
- static Stream & operator<< (Stream & s, BaseMesh::Vertex & vertex)
- {
- return s << vertex.id << vertex.pos << vertex.nor << vertex.tex;
- }
-
- Stream & operator<< (Stream & s, BaseMesh & mesh)
- {
- return s << mesh.m_vertexArray;
- }
-}
diff --git a/thirdparty/thekla_atlas/nvmesh/BaseMesh.h b/thirdparty/thekla_atlas/nvmesh/BaseMesh.h
deleted file mode 100644
index c8559511f1..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/BaseMesh.h
+++ /dev/null
@@ -1,72 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#pragma once
-#ifndef NV_MESH_BASEMESH_H
-#define NV_MESH_BASEMESH_H
-
-#include "nvmesh.h"
-#include "nvmath/Vector.h"
-#include "nvcore/Array.h"
-#include "nvcore/Hash.h"
-
-namespace nv
-{
-
- /// Base mesh without connectivity.
- class BaseMesh
- {
- public:
- struct Vertex;
-
- BaseMesh() {}
-
- BaseMesh(uint vertexNum) :
- m_vertexArray(vertexNum) {}
-
- // Vertex methods.
- uint vertexCount() const { return m_vertexArray.count(); }
- const Vertex & vertexAt(uint i) const { return m_vertexArray[i]; }
- Vertex & vertexAt(uint i) { return m_vertexArray[i]; }
- const Array<Vertex> & vertices() const { return m_vertexArray; }
- Array<Vertex> & vertices() { return m_vertexArray; }
-
- friend Stream & operator<< (Stream & s, BaseMesh & obj);
-
- protected:
-
- Array<Vertex> m_vertexArray;
- };
-
-
- /// BaseMesh vertex.
- struct BaseMesh::Vertex
- {
- Vertex() : id(NIL), pos(0.0f), nor(0.0f), tex(0.0f) {}
-
- uint id; // @@ Vertex should be an index into the vertex data.
- Vector3 pos;
- Vector3 nor;
- Vector2 tex;
- };
-
- inline bool operator==(const BaseMesh::Vertex & a, const BaseMesh::Vertex & b)
- {
- return a.pos == b.pos && a.nor == b.nor && a.tex == b.tex;
- }
-
- inline bool operator!=(const BaseMesh::Vertex & a, const BaseMesh::Vertex & b)
- {
- return a.pos != b.pos && a.nor != b.nor && a.tex != b.tex;
- }
-
- template <> struct Hash<BaseMesh::Vertex>
- {
- uint operator()(const BaseMesh::Vertex & v) const
- {
- return Hash<Vector3>()(v.pos);
- }
- };
-
-} // nv namespace
-
-#endif // NV_MESH_BASEMESH_H
diff --git a/thirdparty/thekla_atlas/nvmesh/MeshBuilder.cpp b/thirdparty/thekla_atlas/nvmesh/MeshBuilder.cpp
deleted file mode 100644
index 24d8ddff89..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/MeshBuilder.cpp
+++ /dev/null
@@ -1,1000 +0,0 @@
-// This code is in the public domain -- castanyo@yahoo.es
-
-#include "nvmesh.h" // pch
-
-#include "MeshBuilder.h"
-#include "TriMesh.h"
-#include "QuadTriMesh.h"
-#include "halfedge/Mesh.h"
-#include "halfedge/Vertex.h"
-#include "halfedge/Face.h"
-
-#include "weld/Weld.h"
-
-#include "nvmath/Box.h"
-#include "nvmath/Vector.inl"
-
-#include "nvcore/StrLib.h"
-#include "nvcore/RadixSort.h"
-#include "nvcore/Ptr.h"
-#include "nvcore/Array.inl"
-#include "nvcore/HashMap.inl"
-
-
-using namespace nv;
-
-/*
-By default the mesh builder creates 3 streams (position, normal, texcoord), I'm planning to add support for extra streams as follows:
-
-enum StreamType { StreamType_Float, StreamType_Vector2, StreamType_Vector3, StreamType_Vector4 };
-
-uint addStream(const char *, uint idx, StreamType);
-
-uint addAttribute(float)
-uint addAttribute(Vector2)
-uint addAttribute(Vector3)
-uint addAttribute(Vector4)
-
-struct Vertex
-{
- uint pos;
- uint nor;
- uint tex;
- uint * attribs; // NULL or NIL terminated array?
-};
-
-All streams must be added before hand, so that you know the size of the attribs array.
-
-The vertex hash function could be kept as is, but the == operator should be extended to test
-the extra atributes when available.
-
-That might require a custom hash implementation, or an extension of the current one. How to
-handle the variable number of attributes in the attribs array?
-
-bool operator()(const Vertex & a, const Vertex & b) const
-{
- if (a.pos != b.pos || a.nor != b.nor || a.tex != b.tex) return false;
- if (a.attribs == NULL && b.attribs == NULL) return true;
- return 0 == memcmp(a.attribs, b.attribs, ???);
-}
-
-We could use a NIL terminated array, or provide custom user data to the equals functor.
-
-vertexMap.setUserData((void *)vertexAttribCount);
-
-bool operator()(const Vertex & a, const Vertex & b, void * userData) const { ... }
-
-*/
-
-
-
-namespace
-{
- struct Material
- {
- Material() : faceCount(0) {}
- Material(const String & str) : name(str), faceCount(0) {}
-
- String name;
- uint faceCount;
- };
-
- struct Vertex
- {
- //Vertex() {}
- //Vertex(uint p, uint n, uint t0, uint t1, uint c) : pos(p), nor(n), tex0(t0), tex1(t1), col(c) {}
-
- friend bool operator==(const Vertex & a, const Vertex & b)
- {
- return a.pos == b.pos && a.nor == b.nor && a.tex[0] == b.tex[0] && a.tex[1] == b.tex[1] && a.col[0] == b.col[0] && a.col[1] == b.col[1] && a.col[2] == b.col[2];
- }
-
- uint pos;
- uint nor;
- uint tex[2];
- uint col[3];
- };
-
- struct Face
- {
- uint id;
- uint firstIndex;
- uint indexCount;
- uint material;
- uint group;
- };
-
-} // namespace
-
-
-namespace nv
-{
- // This is a much better hash than the default and greatly improves performance!
- template <> struct Hash<Vertex>
- {
- uint operator()(const Vertex & v) const { return v.pos + v.nor + v.tex[0]/* + v.col*/; }
- };
-}
-
-struct MeshBuilder::PrivateData
-{
- PrivateData() : currentGroup(NIL), currentMaterial(NIL), maxFaceIndexCount(0) {}
-
- uint pushVertex(uint p, uint n, uint t0, uint t1, uint c0, uint c1, uint c2);
- uint pushVertex(const Vertex & v);
-
- Array<Vector3> posArray;
- Array<Vector3> norArray;
- Array<Vector2> texArray[2];
- Array<Vector4> colArray[3];
-
- Array<Vertex> vertexArray;
- HashMap<Vertex, uint> vertexMap;
-
- HashMap<String, uint> materialMap;
- Array<Material> materialArray;
-
- uint currentGroup;
- uint currentMaterial;
-
- Array<uint> indexArray;
- Array<Face> faceArray;
-
- uint maxFaceIndexCount;
-};
-
-
-uint MeshBuilder::PrivateData::pushVertex(uint p, uint n, uint t0, uint t1, uint c0, uint c1, uint c2)
-{
- Vertex v;
- v.pos = p;
- v.nor = n;
- v.tex[0] = t0;
- v.tex[1] = t1;
- v.col[0] = c0;
- v.col[1] = c1;
- v.col[2] = c2;
- return pushVertex(v);
-}
-
-uint MeshBuilder::PrivateData::pushVertex(const Vertex & v)
-{
- // Lookup vertex v in map.
- uint idx;
- if (vertexMap.get(v, &idx))
- {
- return idx;
- }
-
- idx = vertexArray.count();
- vertexArray.pushBack(v);
- vertexMap.add(v, idx);
-
- return idx;
-}
-
-
-MeshBuilder::MeshBuilder() : d(new PrivateData())
-{
-}
-
-MeshBuilder::~MeshBuilder()
-{
- nvDebugCheck(d != NULL);
- delete d;
-}
-
-
-// Builder methods.
-uint MeshBuilder::addPosition(const Vector3 & v)
-{
- d->posArray.pushBack(validate(v));
- return d->posArray.count() - 1;
-}
-
-uint MeshBuilder::addNormal(const Vector3 & v)
-{
- d->norArray.pushBack(validate(v));
- return d->norArray.count() - 1;
-}
-
-uint MeshBuilder::addTexCoord(const Vector2 & v, uint set/*=0*/)
-{
- d->texArray[set].pushBack(validate(v));
- return d->texArray[set].count() - 1;
-}
-
-uint MeshBuilder::addColor(const Vector4 & v, uint set/*=0*/)
-{
- d->colArray[set].pushBack(validate(v));
- return d->colArray[set].count() - 1;
-}
-
-void MeshBuilder::beginGroup(uint id)
-{
- d->currentGroup = id;
-}
-
-void MeshBuilder::endGroup()
-{
- d->currentGroup = NIL;
-}
-
-// Add named material, check for uniquenes.
-uint MeshBuilder::addMaterial(const char * name)
-{
- uint index;
- if (d->materialMap.get(name, &index)) {
- nvDebugCheck(d->materialArray[index].name == name);
- }
- else {
- index = d->materialArray.count();
- d->materialMap.add(name, index);
-
- Material material(name);
- d->materialArray.append(material);
- }
- return index;
-}
-
-void MeshBuilder::beginMaterial(uint id)
-{
- d->currentMaterial = id;
-}
-
-void MeshBuilder::endMaterial()
-{
- d->currentMaterial = NIL;
-}
-
-void MeshBuilder::beginPolygon(uint id/*=0*/)
-{
- Face face;
- face.id = id;
- face.firstIndex = d->indexArray.count();
- face.indexCount = 0;
- face.material = d->currentMaterial;
- face.group = d->currentGroup;
-
- d->faceArray.pushBack(face);
-}
-
-uint MeshBuilder::addVertex(uint p, uint n/*= NIL*/, uint t0/*= NIL*/, uint t1/*= NIL*/, uint c0/*= NIL*/, uint c1/*= NIL*/, uint c2/*= NIL*/)
-{
- // @@ In theory there's no need to add vertices before faces, but I'm adding this to debug problems in our maya exporter:
- nvDebugCheck(p < d->posArray.count());
- nvDebugCheck(n == NIL || n < d->norArray.count());
- nvDebugCheck(t0 == NIL || t0 < d->texArray[0].count());
- nvDebugCheck(t1 == NIL || t1 < d->texArray[1].count());
- //nvDebugCheck(c0 == NIL || c0 < d->colArray[0].count());
- if (c0 > d->colArray[0].count()) c0 = NIL; // @@ This seems to be happening in loc_swamp_catwalk.mb! No idea why.
- nvDebugCheck(c1 == NIL || c1 < d->colArray[1].count());
- nvDebugCheck(c2 == NIL || c2 < d->colArray[2].count());
-
- uint idx = d->pushVertex(p, n, t0, t1, c0, c1, c2);
- d->indexArray.pushBack(idx);
- d->faceArray.back().indexCount++;
- return idx;
-}
-
-uint MeshBuilder::addVertex(const Vector3 & pos)
-{
- uint p = addPosition(pos);
- return addVertex(p);
-}
-
-#if 0
-uint MeshBuilder::addVertex(const Vector3 & pos, const Vector3 & nor, const Vector2 & tex0, const Vector2 & tex1, const Vector4 & col0, const Vector4 & col1)
-{
- uint p = addPosition(pos);
- uint n = addNormal(nor);
- uint t0 = addTexCoord(tex0, 0);
- uint t1 = addTexCoord(tex1, 1);
- uint c0 = addColor(col0);
- uint c1 = addColor(col1);
- return addVertex(p, n, t0, t1, c0, c1);
-}
-#endif
-
-// Return true if the face is valid and was added to the mesh.
-bool MeshBuilder::endPolygon()
-{
- const Face & face = d->faceArray.back();
- const uint count = face.indexCount;
-
- // Validate polygon here.
- bool invalid = count <= 2;
-
- if (!invalid) {
- // Skip zero area polygons. Or polygons with degenerate edges (which will result in zero-area triangles).
- const uint first = face.firstIndex;
- for (uint j = count - 1, i = 0; i < count; j = i, i++) {
- uint v0 = d->indexArray[first + i];
- uint v1 = d->indexArray[first + j];
-
- uint p0 = d->vertexArray[v0].pos;
- uint p1 = d->vertexArray[v1].pos;
-
- if (p0 == p1) {
- invalid = true;
- break;
- }
-
- if (equal(d->posArray[p0], d->posArray[p1], FLT_EPSILON)) {
- invalid = true;
- break;
- }
- }
-
- uint v0 = d->indexArray[first];
- uint p0 = d->vertexArray[v0].pos;
- Vector3 x0 = d->posArray[p0];
-
- float area = 0.0f;
- for (uint j = 1, i = 2; i < count; j = i, i++) {
- uint v1 = d->indexArray[first + i];
- uint v2 = d->indexArray[first + j];
-
- uint p1 = d->vertexArray[v1].pos;
- uint p2 = d->vertexArray[v2].pos;
-
- Vector3 x1 = d->posArray[p1];
- Vector3 x2 = d->posArray[p2];
-
- area += length(cross(x1-x0, x2-x0));
- }
-
- if (0.5 * area < 1e-6) { // Reduce this threshold if artists have legitimate complains.
- invalid = true;
- }
-
- // @@ This is not complete. We may still get zero area triangles after triangulation.
- // However, our plugin triangulates before building the mesh, so hopefully that's not a problem.
-
- }
-
- if (invalid)
- {
- d->indexArray.resize(d->indexArray.size() - count);
- d->faceArray.popBack();
- return false;
- }
- else
- {
- if (d->currentMaterial != NIL) {
- d->materialArray[d->currentMaterial].faceCount++;
- }
-
- d->maxFaceIndexCount = max(d->maxFaceIndexCount, count);
- return true;
- }
-}
-
-
-uint MeshBuilder::weldPositions()
-{
- Array<uint> xrefs;
- Weld<Vector3> weldVector3;
-
- if (d->posArray.count()) {
- // Weld vertex attributes.
- weldVector3(d->posArray, xrefs);
-
- // Remap vertex indices.
- const uint vertexCount = d->vertexArray.count();
- for (uint v = 0; v < vertexCount; v++)
- {
- Vertex & vertex = d->vertexArray[v];
- if (vertex.pos != NIL) vertex.pos = xrefs[vertex.pos];
- }
- }
-
- return d->posArray.count();
-}
-
-uint MeshBuilder::weldNormals()
-{
- Array<uint> xrefs;
- Weld<Vector3> weldVector3;
-
- if (d->norArray.count()) {
- // Weld vertex attributes.
- weldVector3(d->norArray, xrefs);
-
- // Remap vertex indices.
- const uint vertexCount = d->vertexArray.count();
- for (uint v = 0; v < vertexCount; v++)
- {
- Vertex & vertex = d->vertexArray[v];
- if (vertex.nor != NIL) vertex.nor = xrefs[vertex.nor];
- }
- }
-
- return d->norArray.count();
-}
-
-uint MeshBuilder::weldTexCoords(uint set/*=0*/)
-{
- Array<uint> xrefs;
- Weld<Vector2> weldVector2;
-
- if (d->texArray[set].count()) {
- // Weld vertex attributes.
- weldVector2(d->texArray[set], xrefs);
-
- // Remap vertex indices.
- const uint vertexCount = d->vertexArray.count();
- for (uint v = 0; v < vertexCount; v++)
- {
- Vertex & vertex = d->vertexArray[v];
- if (vertex.tex[set] != NIL) vertex.tex[set] = xrefs[vertex.tex[set]];
- }
- }
-
- return d->texArray[set].count();
-}
-
-uint MeshBuilder::weldColors(uint set/*=0*/)
-{
- Array<uint> xrefs;
- Weld<Vector4> weldVector4;
-
- if (d->colArray[set].count()) {
- // Weld vertex attributes.
- weldVector4(d->colArray[set], xrefs);
-
- // Remap vertex indices.
- const uint vertexCount = d->vertexArray.count();
- for (uint v = 0; v < vertexCount; v++)
- {
- Vertex & vertex = d->vertexArray[v];
- if (vertex.col[set] != NIL) vertex.col[set] = xrefs[vertex.col[set]];
- }
- }
-
- return d->colArray[set].count();
-}
-
-void MeshBuilder::weldVertices() {
-
- if (d->vertexArray.count() == 0) {
- // Nothing to do.
- return;
- }
-
- Array<uint> xrefs;
- Weld<Vertex> weldVertex;
-
- // Weld vertices.
- weldVertex(d->vertexArray, xrefs);
-
- // Remap face indices.
- const uint indexCount = d->indexArray.count();
- for (uint i = 0; i < indexCount; i++)
- {
- d->indexArray[i] = xrefs[d->indexArray[i]];
- }
-
- // Remap vertex map.
- foreach(i, d->vertexMap)
- {
- d->vertexMap[i].value = xrefs[d->vertexMap[i].value];
- }
-}
-
-
-void MeshBuilder::optimize()
-{
- if (d->vertexArray.count() == 0)
- {
- return;
- }
-
- weldPositions();
- weldNormals();
- weldTexCoords(0);
- weldTexCoords(1);
- weldColors();
-
- weldVertices();
-}
-
-
-
-
-
-
-void MeshBuilder::removeUnusedMaterials(Array<uint> & newMaterialId)
-{
- uint materialCount = d->materialArray.count();
-
- // Reset face counts.
- for (uint i = 0; i < materialCount; i++) {
- d->materialArray[i].faceCount = 0;
- }
-
- // Count faces.
- foreach(i, d->faceArray) {
- Face & face = d->faceArray[i];
-
- if (face.material != NIL) {
- nvDebugCheck(face.material < materialCount);
-
- d->materialArray[face.material].faceCount++;
- }
- }
-
- // Remove unused materials.
- newMaterialId.resize(materialCount);
-
- for (uint i = 0, m = 0; i < materialCount; i++)
- {
- if (d->materialArray[m].faceCount > 0)
- {
- newMaterialId[i] = m++;
- }
- else
- {
- newMaterialId[i] = NIL;
- d->materialArray.removeAt(m);
- }
- }
-
- materialCount = d->materialArray.count();
-
- // Update face material ids.
- foreach(i, d->faceArray) {
- Face & face = d->faceArray[i];
-
- if (face.material != NIL) {
- uint id = newMaterialId[face.material];
- nvDebugCheck(id != NIL && id < materialCount);
-
- face.material = id;
- }
- }
-}
-
-void MeshBuilder::sortFacesByGroup()
-{
- const uint faceCount = d->faceArray.count();
-
- Array<uint> faceGroupArray;
- faceGroupArray.resize(faceCount);
-
- for (uint i = 0; i < faceCount; i++) {
- faceGroupArray[i] = d->faceArray[i].group;
- }
-
- RadixSort radix;
- radix.sort(faceGroupArray);
-
- Array<Face> newFaceArray;
- newFaceArray.resize(faceCount);
-
- for (uint i = 0; i < faceCount; i++) {
- newFaceArray[i] = d->faceArray[radix.rank(i)];
- }
-
- swap(newFaceArray, d->faceArray);
-}
-
-void MeshBuilder::sortFacesByMaterial()
-{
- const uint faceCount = d->faceArray.count();
-
- Array<uint> faceMaterialArray;
- faceMaterialArray.resize(faceCount);
-
- for (uint i = 0; i < faceCount; i++) {
- faceMaterialArray[i] = d->faceArray[i].material;
- }
-
- RadixSort radix;
- radix.sort(faceMaterialArray);
-
- Array<Face> newFaceArray;
- newFaceArray.resize(faceCount);
-
- for (uint i = 0; i < faceCount; i++) {
- newFaceArray[i] = d->faceArray[radix.rank(i)];
- }
-
- swap(newFaceArray, d->faceArray);
-}
-
-
-void MeshBuilder::reset()
-{
- nvDebugCheck(d != NULL);
- delete d;
- d = new PrivateData();
-}
-
-void MeshBuilder::done()
-{
- if (d->currentGroup != NIL) {
- endGroup();
- }
-
- if (d->currentMaterial != NIL) {
- endMaterial();
- }
-}
-
-// Hints.
-void MeshBuilder::hintTriangleCount(uint count)
-{
- d->indexArray.reserve(d->indexArray.count() + count * 4);
-}
-
-void MeshBuilder::hintVertexCount(uint count)
-{
- d->vertexArray.reserve(d->vertexArray.count() + count);
- d->vertexMap.resize(d->vertexMap.count() + count);
-}
-
-void MeshBuilder::hintPositionCount(uint count)
-{
- d->posArray.reserve(d->posArray.count() + count);
-}
-
-void MeshBuilder::hintNormalCount(uint count)
-{
- d->norArray.reserve(d->norArray.count() + count);
-}
-
-void MeshBuilder::hintTexCoordCount(uint count, uint set/*=0*/)
-{
- d->texArray[set].reserve(d->texArray[set].count() + count);
-}
-
-void MeshBuilder::hintColorCount(uint count, uint set/*=0*/)
-{
- d->colArray[set].reserve(d->colArray[set].count() + count);
-}
-
-
-// Helpers.
-void MeshBuilder::addTriangle(uint v0, uint v1, uint v2)
-{
- beginPolygon();
- addVertex(v0);
- addVertex(v1);
- addVertex(v2);
- endPolygon();
-}
-
-void MeshBuilder::addQuad(uint v0, uint v1, uint v2, uint v3)
-{
- beginPolygon();
- addVertex(v0);
- addVertex(v1);
- addVertex(v2);
- addVertex(v3);
- endPolygon();
-}
-
-
-// Get tri mesh.
-TriMesh * MeshBuilder::buildTriMesh() const
-{
- const uint faceCount = d->faceArray.count();
- uint triangleCount = 0;
- for (uint f = 0; f < faceCount; f++) {
- triangleCount += d->faceArray[f].indexCount - 2;
- }
-
- const uint vertexCount = d->vertexArray.count();
- TriMesh * mesh = new TriMesh(triangleCount, vertexCount);
-
- // Build faces.
- Array<TriMesh::Face> & faces = mesh->faces();
-
- for(uint f = 0; f < faceCount; f++)
- {
- int firstIndex = d->faceArray[f].firstIndex;
- int indexCount = d->faceArray[f].indexCount;
-
- int v0 = d->indexArray[firstIndex + 0];
- int v1 = d->indexArray[firstIndex + 1];
-
- for(int t = 0; t < indexCount - 2; t++) {
- int v2 = d->indexArray[firstIndex + t + 2];
-
- TriMesh::Face face;
- face.id = faces.count();
- face.v[0] = v0;
- face.v[1] = v1;
- face.v[2] = v2;
- faces.append(face);
-
- v1 = v2;
- }
- }
-
- // Build vertices.
- Array<BaseMesh::Vertex> & vertices = mesh->vertices();
-
- for(uint i = 0; i < vertexCount; i++)
- {
- BaseMesh::Vertex vertex;
- vertex.id = i;
- if (d->vertexArray[i].pos != NIL) vertex.pos = d->posArray[d->vertexArray[i].pos];
- if (d->vertexArray[i].nor != NIL) vertex.nor = d->norArray[d->vertexArray[i].nor];
- if (d->vertexArray[i].tex[0] != NIL) vertex.tex = d->texArray[0][d->vertexArray[i].tex[0]];
-
- vertices.append(vertex);
- }
-
- return mesh;
-}
-
-// Get quad/tri mesh.
-QuadTriMesh * MeshBuilder::buildQuadTriMesh() const
-{
- const uint faceCount = d->faceArray.count();
- const uint vertexCount = d->vertexArray.count();
- QuadTriMesh * mesh = new QuadTriMesh(faceCount, vertexCount);
-
- // Build faces.
- Array<QuadTriMesh::Face> & faces = mesh->faces();
-
- for (uint f = 0; f < faceCount; f++)
- {
- int firstIndex = d->faceArray[f].firstIndex;
- int indexCount = d->faceArray[f].indexCount;
-
- QuadTriMesh::Face face;
- face.id = f;
-
- face.v[0] = d->indexArray[firstIndex + 0];
- face.v[1] = d->indexArray[firstIndex + 1];
- face.v[2] = d->indexArray[firstIndex + 2];
-
- // Only adds triangles and quads. Ignores polygons.
- if (indexCount == 3) {
- face.v[3] = NIL;
- faces.append(face);
- }
- else if (indexCount == 4) {
- face.v[3] = d->indexArray[firstIndex + 3];
- faces.append(face);
- }
- }
-
- // Build vertices.
- Array<BaseMesh::Vertex> & vertices = mesh->vertices();
-
- for(uint i = 0; i < vertexCount; i++)
- {
- BaseMesh::Vertex vertex;
- vertex.id = i;
- if (d->vertexArray[i].pos != NIL) vertex.pos = d->posArray[d->vertexArray[i].pos];
- if (d->vertexArray[i].nor != NIL) vertex.nor = d->norArray[d->vertexArray[i].nor];
- if (d->vertexArray[i].tex[0] != NIL) vertex.tex = d->texArray[0][d->vertexArray[i].tex[0]];
-
- vertices.append(vertex);
- }
-
- return mesh;
-}
-
-// Get half edge mesh.
-HalfEdge::Mesh * MeshBuilder::buildHalfEdgeMesh(bool weldPositions, Error * error/*=NULL*/, Array<uint> * badFaces/*=NULL*/) const
-{
- if (error != NULL) *error = Error_None;
-
- const uint vertexCount = d->vertexArray.count();
- AutoPtr<HalfEdge::Mesh> mesh(new HalfEdge::Mesh());
-
- for(uint v = 0; v < vertexCount; v++)
- {
- HalfEdge::Vertex * vertex = mesh->addVertex(d->posArray[d->vertexArray[v].pos]);
- if (d->vertexArray[v].nor != NIL) vertex->nor = d->norArray[d->vertexArray[v].nor];
- if (d->vertexArray[v].tex[0] != NIL) vertex->tex = Vector2(d->texArray[0][d->vertexArray[v].tex[0]]);
- if (d->vertexArray[v].col[0] != NIL) vertex->col = d->colArray[0][d->vertexArray[v].col[0]];
- }
-
- if (weldPositions) {
- mesh->linkColocals();
- }
- else {
- // Build canonical map from position indices.
- Array<uint> canonicalMap(vertexCount);
-
- foreach (i, d->vertexArray) {
- canonicalMap.append(d->vertexArray[i].pos);
- }
-
- mesh->linkColocalsWithCanonicalMap(canonicalMap);
- }
-
- const uint faceCount = d->faceArray.count();
- for (uint f = 0; f < faceCount; f++)
- {
- const uint firstIndex = d->faceArray[f].firstIndex;
- const uint indexCount = d->faceArray[f].indexCount;
-
- HalfEdge::Face * face = mesh->addFace(d->indexArray, firstIndex, indexCount);
-
- // @@ This is too late, removing the face here will leave the mesh improperly connected.
- /*if (face->area() <= FLT_EPSILON) {
- mesh->remove(face);
- face = NULL;
- }*/
-
- if (face == NULL) {
- // Non manifold mesh.
- if (error != NULL) *error = Error_NonManifoldEdge;
- if (badFaces != NULL) {
- badFaces->append(d->faceArray[f].id);
- }
- //return NULL; // IC: Ignore error and continue building the mesh.
- }
-
- if (face != NULL) {
- face->group = d->faceArray[f].group;
- face->material = d->faceArray[f].material;
- }
- }
-
- mesh->linkBoundary();
-
- // We cannot fix functions here, because this would introduce new vertices and these vertices won't have the corresponding builder data.
-
- // Maybe the builder should perform the search for T-junctions and update the vertex data directly.
-
- // For now, we don't fix T-junctions at export time, but only during parameterization.
-
- //mesh->fixBoundaryJunctions();
-
- //mesh->sewBoundary();
-
- return mesh.release();
-}
-
-
-bool MeshBuilder::buildPositions(Array<Vector3> & positionArray)
-{
- const uint vertexCount = d->vertexArray.count();
- positionArray.resize(vertexCount);
-
- for (uint v = 0; v < vertexCount; v++)
- {
- nvDebugCheck(d->vertexArray[v].pos != NIL);
- positionArray[v] = d->posArray[d->vertexArray[v].pos];
- }
-
- return true;
-}
-
-bool MeshBuilder::buildNormals(Array<Vector3> & normalArray)
-{
- bool anyNormal = false;
-
- const uint vertexCount = d->vertexArray.count();
- normalArray.resize(vertexCount);
-
- for (uint v = 0; v < vertexCount; v++)
- {
- if (d->vertexArray[v].nor == NIL) {
- normalArray[v] = Vector3(0, 0, 1);
- }
- else {
- anyNormal = true;
- normalArray[v] = d->norArray[d->vertexArray[v].nor];
- }
- }
-
- return anyNormal;
-}
-
-bool MeshBuilder::buildTexCoords(Array<Vector2> & texCoordArray, uint set/*=0*/)
-{
- bool anyTexCoord = false;
-
- const uint vertexCount = d->vertexArray.count();
- texCoordArray.resize(vertexCount);
-
- for (uint v = 0; v < vertexCount; v++)
- {
- if (d->vertexArray[v].tex[set] == NIL) {
- texCoordArray[v] = Vector2(0, 0);
- }
- else {
- anyTexCoord = true;
- texCoordArray[v] = d->texArray[set][d->vertexArray[v].tex[set]];
- }
- }
-
- return anyTexCoord;
-}
-
-bool MeshBuilder::buildColors(Array<Vector4> & colorArray, uint set/*=0*/)
-{
- bool anyColor = false;
-
- const uint vertexCount = d->vertexArray.count();
- colorArray.resize(vertexCount);
-
- for (uint v = 0; v < vertexCount; v++)
- {
- if (d->vertexArray[v].col[set] == NIL) {
- colorArray[v] = Vector4(0, 0, 0, 1);
- }
- else {
- anyColor = true;
- colorArray[v] = d->colArray[set][d->vertexArray[v].col[set]];
- }
- }
-
- return anyColor;
-}
-
-void MeshBuilder::buildVertexToPositionMap(Array<int> &map)
-{
- const uint vertexCount = d->vertexArray.count();
- map.resize(vertexCount);
-
- foreach (i, d->vertexArray) {
- map[i] = d->vertexArray[i].pos;
- }
-}
-
-
-
-uint MeshBuilder::vertexCount() const
-{
- return d->vertexArray.count();
-}
-
-
-uint MeshBuilder::positionCount() const
-{
- return d->posArray.count();
-}
-
-uint MeshBuilder::normalCount() const
-{
- return d->norArray.count();
-}
-
-uint MeshBuilder::texCoordCount(uint set/*=0*/) const
-{
- return d->texArray[set].count();
-}
-
-uint MeshBuilder::colorCount(uint set/*=0*/) const
-{
- return d->colArray[set].count();
-}
-
-
-uint MeshBuilder::materialCount() const
-{
- return d->materialArray.count();
-}
-
-const char * MeshBuilder::material(uint i) const
-{
- return d->materialArray[i].name;
-}
-
-
-uint MeshBuilder::positionIndex(uint vertex) const
-{
- return d->vertexArray[vertex].pos;
-}
-uint MeshBuilder::normalIndex(uint vertex) const
-{
- return d->vertexArray[vertex].nor;
-}
-uint MeshBuilder::texCoordIndex(uint vertex, uint set/*=0*/) const
-{
- return d->vertexArray[vertex].tex[set];
-}
-uint MeshBuilder::colorIndex(uint vertex, uint set/*=0*/) const
-{
- return d->vertexArray[vertex].col[set];
-}
diff --git a/thirdparty/thekla_atlas/nvmesh/MeshBuilder.h b/thirdparty/thekla_atlas/nvmesh/MeshBuilder.h
deleted file mode 100644
index 5b3af3fc1d..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/MeshBuilder.h
+++ /dev/null
@@ -1,119 +0,0 @@
-// This code is in the public domain -- castanyo@yahoo.es
-
-#pragma once
-#ifndef NV_MESH_MESHBUILDER_H
-#define NV_MESH_MESHBUILDER_H
-
-#include "nvmesh.h"
-#include "nvcore/Array.h"
-#include "nvmath/Vector.h"
-
-namespace nv
-{
- class String;
- class TriMesh;
- class QuadTriMesh;
- namespace HalfEdge { class Mesh; }
-
-
- /// Mesh builder is a helper class for importers.
- /// Ideally it should handle any vertex data, but for now it only accepts positions,
- /// normals and texcoords.
- class MeshBuilder
- {
- NV_FORBID_COPY(MeshBuilder);
- NV_FORBID_HEAPALLOC();
- public:
- MeshBuilder();
- ~MeshBuilder();
-
- // Builder methods.
- uint addPosition(const Vector3 & v);
- uint addNormal(const Vector3 & v);
- uint addTexCoord(const Vector2 & v, uint set = 0);
- uint addColor(const Vector4 & v, uint set = 0);
-
- void beginGroup(uint id);
- void endGroup();
-
- uint addMaterial(const char * name);
- void beginMaterial(uint id);
- void endMaterial();
-
- void beginPolygon(uint id = 0);
- uint addVertex(uint p, uint n = NIL, uint t0 = NIL, uint t1 = NIL, uint c0 = NIL, uint c1 = NIL, uint c2 = NIL);
- uint addVertex(const Vector3 & p);
- //uint addVertex(const Vector3 & p, const Vector3 & n, const Vector2 & t0 = Vector2(0), const Vector2 & t1 = Vector2(0), const Vector4 & c0 = Vector4(0), const Vector4 & c1 = Vector4(0));
- bool endPolygon();
-
- uint weldPositions();
- uint weldNormals();
- uint weldTexCoords(uint set = 0);
- uint weldColors(uint set = 0);
- void weldVertices();
-
- void optimize(); // eliminate duplicate components and duplicate vertices.
- void removeUnusedMaterials(Array<uint> & newMaterialId);
- void sortFacesByGroup();
- void sortFacesByMaterial();
-
- void done();
- void reset();
-
- // Hints.
- void hintTriangleCount(uint count);
- void hintVertexCount(uint count);
- void hintPositionCount(uint count);
- void hintNormalCount(uint count);
- void hintTexCoordCount(uint count, uint set = 0);
- void hintColorCount(uint count, uint set = 0);
-
- // Helpers.
- void addTriangle(uint v0, uint v1, uint v2);
- void addQuad(uint v0, uint v1, uint v2, uint v3);
-
- // Get result.
- TriMesh * buildTriMesh() const;
- QuadTriMesh * buildQuadTriMesh() const;
-
- enum Error {
- Error_None,
- Error_NonManifoldEdge,
- Error_NonManifoldVertex,
- };
-
- HalfEdge::Mesh * buildHalfEdgeMesh(bool weldPositions, Error * error = NULL, Array<uint> * badFaces = NULL) const;
-
- bool buildPositions(Array<Vector3> & positionArray);
- bool buildNormals(Array<Vector3> & normalArray);
- bool buildTexCoords(Array<Vector2> & texCoordArray, uint set = 0);
- bool buildColors(Array<Vector4> & colorArray, uint set = 0);
- void buildVertexToPositionMap(Array<int> & map);
-
-
- // Expose attribute indices of the unified vertex array.
- uint vertexCount() const;
-
- uint positionCount() const;
- uint normalCount() const;
- uint texCoordCount(uint set = 0) const;
- uint colorCount(uint set = 0) const;
-
- uint materialCount() const;
- const char * material(uint i) const;
-
- uint positionIndex(uint vertex) const;
- uint normalIndex(uint vertex) const;
- uint texCoordIndex(uint vertex, uint set = 0) const;
- uint colorIndex(uint vertex, uint set = 0) const;
-
- private:
-
- struct PrivateData;
- PrivateData * d;
-
- };
-
-} // nv namespace
-
-#endif // NV_MESH_MESHBUILDER_H
diff --git a/thirdparty/thekla_atlas/nvmesh/MeshTopology.cpp b/thirdparty/thekla_atlas/nvmesh/MeshTopology.cpp
deleted file mode 100644
index e7e1dce421..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/MeshTopology.cpp
+++ /dev/null
@@ -1,122 +0,0 @@
-// This code is in the public domain -- castanyo@yahoo.es
-
-#include "nvmesh.h" // pch
-
-#include "nvcore/Array.h"
-#include "nvcore/BitArray.h"
-
-#include "nvmesh/MeshTopology.h"
-#include "nvmesh/halfedge/Mesh.h"
-#include "nvmesh/halfedge/Edge.h"
-#include "nvmesh/halfedge/Face.h"
-
-using namespace nv;
-
-void MeshTopology::buildTopologyInfo(const HalfEdge::Mesh * mesh)
-{
- const uint vertexCount = mesh->colocalVertexCount();
- const uint faceCount = mesh->faceCount();
- const uint edgeCount = mesh->edgeCount();
-
- nvDebug( "--- Building mesh topology:\n" );
-
- Array<uint> stack(faceCount);
-
- BitArray bitFlags(faceCount);
- bitFlags.clearAll();
-
- // Compute connectivity.
- nvDebug( "--- Computing connectivity.\n" );
-
- m_connectedCount = 0;
-
- for(uint f = 0; f < faceCount; f++ ) {
- if( bitFlags.bitAt(f) == false ) {
- m_connectedCount++;
-
- stack.pushBack( f );
- while( !stack.isEmpty() ) {
-
- const uint top = stack.back();
- nvCheck(top != NIL);
- stack.popBack();
-
- if( bitFlags.bitAt(top) == false ) {
- bitFlags.setBitAt(top);
-
- const HalfEdge::Face * face = mesh->faceAt(top);
- const HalfEdge::Edge * firstEdge = face->edge;
- const HalfEdge::Edge * edge = firstEdge;
-
- do {
- const HalfEdge::Face * neighborFace = edge->pair->face;
- if (neighborFace != NULL) {
- stack.pushBack(neighborFace->id);
- }
- edge = edge->next;
- } while(edge != firstEdge);
- }
- }
- }
- }
- nvCheck(stack.isEmpty());
- nvDebug( "--- %d connected components.\n", m_connectedCount );
-
-
- // Count boundary loops.
- nvDebug( "--- Counting boundary loops.\n" );
- m_boundaryCount = 0;
-
- bitFlags.resize(edgeCount);
- bitFlags.clearAll();
-
- // Don't forget to link the boundary otherwise this won't work.
- for (uint e = 0; e < edgeCount; e++)
- {
- const HalfEdge::Edge * startEdge = mesh->edgeAt(e);
- if (startEdge != NULL && startEdge->isBoundary() && bitFlags.bitAt(e) == false)
- {
- nvDebugCheck(startEdge->face != NULL);
- nvDebugCheck(startEdge->pair->face == NULL);
-
- startEdge = startEdge->pair;
-
- m_boundaryCount++;
-
- const HalfEdge::Edge * edge = startEdge;
- do {
- bitFlags.setBitAt(edge->id / 2);
- edge = edge->next;
- } while(startEdge != edge);
- }
- }
- nvDebug("--- %d boundary loops found.\n", m_boundaryCount );
-
-
- // Compute euler number.
- m_eulerNumber = vertexCount - edgeCount + faceCount;
- nvDebug("--- Euler number: %d.\n", m_eulerNumber);
-
-
- // Compute genus. (only valid on closed connected surfaces)
- m_genus = -1;
- if( isClosed() && isConnected() ) {
- m_genus = (2 - m_eulerNumber) / 2;
- nvDebug("--- Genus: %d.\n", m_genus);
- }
-}
-
-
-/*static*/ bool MeshTopology::isQuadOnly(const HalfEdge::Mesh * mesh)
-{
- const uint faceCount = mesh->faceCount();
- for(uint f = 0; f < faceCount; f++)
- {
- const HalfEdge::Face * face = mesh->faceAt(f);
- if (face->edgeCount() != 4) {
- return false;
- }
- }
-
- return true;
-}
diff --git a/thirdparty/thekla_atlas/nvmesh/MeshTopology.h b/thirdparty/thekla_atlas/nvmesh/MeshTopology.h
deleted file mode 100644
index c3d7477b15..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/MeshTopology.h
+++ /dev/null
@@ -1,66 +0,0 @@
-// This code is in the public domain -- castanyo@yahoo.es
-
-#pragma once
-#ifndef NV_MESH_MESHTOPOLOGY_H
-#define NV_MESH_MESHTOPOLOGY_H
-
-#include <nvmesh/nvmesh.h>
-
-namespace nv
-{
- namespace HalfEdge { class Mesh; }
- class MeshAdjacency;
-
- /// Mesh topology information.
- class MeshTopology
- {
- public:
- MeshTopology(const HalfEdge::Mesh * mesh) { buildTopologyInfo(mesh); }
-
- /// Determine if the mesh is connected.
- bool isConnected() const { return m_connectedCount == 1; }
-
- /// Determine if the mesh is closed. (Each edge is shared by two faces)
- bool isClosed() const { return m_boundaryCount == 0; }
-
- /// Return true if the mesh has the topology of a disk.
- bool isDisk() const { return isConnected() && m_boundaryCount == 1/* && m_eulerNumber == 1*/; }
-
- /// Return the number of connected components.
- int connectedCount() const { return m_connectedCount; }
-
- /// Return the number of open holes.
- int holeCount() const { return m_boundaryCount; }
-
- /// Return the genus of the mesh.
- int genus() const { return m_genus; }
-
- /// Return the euler number of the mesh.
- int euler() const { return m_eulerNumber; }
-
-
- static bool isQuadOnly(const HalfEdge::Mesh * mesh);
-
-
- private:
-
- NVMESH_API void buildTopologyInfo(const HalfEdge::Mesh * mesh);
-
- private:
-
- ///< Number of boundary loops.
- int m_boundaryCount;
-
- ///< Number of connected components.
- int m_connectedCount;
-
- ///< Euler number.
- int m_eulerNumber;
-
- /// Mesh genus.
- int m_genus;
- };
-
-} // nv namespace
-
-#endif // NV_MESH_MESHTOPOLOGY_H
diff --git a/thirdparty/thekla_atlas/nvmesh/QuadTriMesh.cpp b/thirdparty/thekla_atlas/nvmesh/QuadTriMesh.cpp
deleted file mode 100644
index 64a071abe9..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/QuadTriMesh.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#include "QuadTriMesh.h"
-#include "Stream.h"
-
-using namespace nv;
-
-
-bool QuadTriMesh::isQuadFace(uint i) const
-{
- return m_faceArray[i].isQuadFace();
-}
-
-const QuadTriMesh::Vertex & QuadTriMesh::faceVertex(uint f, uint v) const
-{
- if (isQuadFace(f)) nvDebugCheck(v < 4);
- else nvDebugCheck(v < 3);
-
- const Face & face = this->faceAt(f);
- return this->vertexAt(face.v[v]);
-}
-
-
-namespace nv
-{
- static Stream & operator<< (Stream & s, QuadTriMesh::Face & face)
- {
- return s << face.id << face.v[0] << face.v[1] << face.v[2] << face.v[3];
- }
-
- Stream & operator<< (Stream & s, QuadTriMesh & mesh)
- {
- return s << mesh.m_faceArray << (BaseMesh &) mesh;
- }
-}
-
diff --git a/thirdparty/thekla_atlas/nvmesh/QuadTriMesh.h b/thirdparty/thekla_atlas/nvmesh/QuadTriMesh.h
deleted file mode 100644
index b8465f2db0..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/QuadTriMesh.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#pragma once
-#ifndef NV_MESH_QUADTRIMESH_H
-#define NV_MESH_QUADTRIMESH_H
-
-#include "nvcore/Array.h"
-#include "nvmath/Vector.h"
-#include "nvmesh/nvmesh.h"
-#include "nvmesh/BaseMesh.h"
-
-namespace nv
-{
- class Stream;
-
- /// Mixed quad/triangle mesh.
- class QuadTriMesh : public BaseMesh
- {
- public:
- struct Face;
- typedef BaseMesh::Vertex Vertex;
-
- QuadTriMesh() {};
- QuadTriMesh(uint faceCount, uint vertexCount) : BaseMesh(vertexCount), m_faceArray(faceCount) {}
-
- // Face methods.
- uint faceCount() const { return m_faceArray.count(); }
-
- const Face & faceAt(uint i) const { return m_faceArray[i]; }
- Face & faceAt(uint i) { return m_faceArray[i]; }
-
- const Array<Face> & faces() const { return m_faceArray; }
- Array<Face> & faces() { return m_faceArray; }
-
- bool isQuadFace(uint i) const;
-
- const Vertex & faceVertex(uint f, uint v) const;
-
- friend Stream & operator<< (Stream & s, QuadTriMesh & obj);
-
- private:
-
- Array<Face> m_faceArray;
-
- };
-
-
- /// QuadTriMesh face.
- struct QuadTriMesh::Face
- {
- uint id;
- uint v[4];
-
- bool isQuadFace() const { return v[3] != NIL; }
- };
-
-} // nv namespace
-
-
-#endif // NV_MESH_QUADTRIMESH_H
diff --git a/thirdparty/thekla_atlas/nvmesh/TriMesh.cpp b/thirdparty/thekla_atlas/nvmesh/TriMesh.cpp
deleted file mode 100644
index bf10a474fb..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/TriMesh.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#include "TriMesh.h"
-
-using namespace nv;
-
-
-/// Triangle mesh.
-Vector3 TriMesh::faceNormal(uint f) const
-{
- const Face & face = this->faceAt(f);
- const Vector3 & p0 = this->vertexAt(face.v[0]).pos;
- const Vector3 & p1 = this->vertexAt(face.v[1]).pos;
- const Vector3 & p2 = this->vertexAt(face.v[2]).pos;
- return normalizeSafe(cross(p1 - p0, p2 - p0), Vector3(0.0f), 0.0f);
-}
-
-/// Get face vertex.
-const TriMesh::Vertex & TriMesh::faceVertex(uint f, uint v) const
-{
- nvDebugCheck(v < 3);
- const Face & face = this->faceAt(f);
- return this->vertexAt(face.v[v]);
-}
-
diff --git a/thirdparty/thekla_atlas/nvmesh/TriMesh.h b/thirdparty/thekla_atlas/nvmesh/TriMesh.h
deleted file mode 100644
index bc5672c1ac..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/TriMesh.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#pragma once
-#ifndef NV_MESH_TRIMESH_H
-#define NV_MESH_TRIMESH_H
-
-#include "nvcore/Array.h"
-#include "nvmath/Vector.inl"
-#include "nvmesh/nvmesh.h"
-#include "nvmesh/BaseMesh.h"
-
-namespace nv
-{
- /// Triangle mesh.
- class TriMesh : public BaseMesh
- {
- public:
- struct Face;
- typedef BaseMesh::Vertex Vertex;
-
- TriMesh(uint faceCount, uint vertexCount) : BaseMesh(vertexCount), m_faceArray(faceCount) {}
-
- // Face methods.
- uint faceCount() const { return m_faceArray.count(); }
- const Face & faceAt(uint i) const { return m_faceArray[i]; }
- Face & faceAt(uint i) { return m_faceArray[i]; }
- const Array<Face> & faces() const { return m_faceArray; }
- Array<Face> & faces() { return m_faceArray; }
-
- NVMESH_API Vector3 faceNormal(uint f) const;
- NVMESH_API const Vertex & faceVertex(uint f, uint v) const;
-
- friend Stream & operator<< (Stream & s, BaseMesh & obj);
-
- private:
-
- Array<Face> m_faceArray;
-
- };
-
-
- /// TriMesh face.
- struct TriMesh::Face
- {
- uint id;
- uint v[3];
- };
-
-} // nv namespace
-
-#endif // NV_MESH_TRIMESH_H
diff --git a/thirdparty/thekla_atlas/nvmesh/geometry/Bounds.cpp b/thirdparty/thekla_atlas/nvmesh/geometry/Bounds.cpp
deleted file mode 100644
index 69fd1deb24..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/geometry/Bounds.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#include "nvmesh.h" // pch
-
-#include "Bounds.h"
-
-#include "nvmesh/BaseMesh.h"
-#include "nvmesh/halfedge/Mesh.h"
-#include "nvmesh/halfedge/Vertex.h"
-
-#include "nvmath/Box.inl"
-
-using namespace nv;
-
-Box MeshBounds::box(const BaseMesh * mesh)
-{
- nvCheck(mesh != NULL);
-
- Box bounds;
- bounds.clearBounds();
-
- const uint vertexCount = mesh->vertexCount();
- for (uint v = 0; v < vertexCount; v++)
- {
- const BaseMesh::Vertex & vertex = mesh->vertexAt(v);
- bounds.addPointToBounds( vertex.pos );
- }
-
- return bounds;
-}
-
-Box MeshBounds::box(const HalfEdge::Mesh * mesh)
-{
- nvCheck(mesh != NULL);
-
- Box bounds;
- bounds.clearBounds();
-
- const uint vertexCount = mesh->vertexCount();
- for (uint v = 0; v < vertexCount; v++)
- {
- const HalfEdge::Vertex * vertex = mesh->vertexAt(v);
- nvDebugCheck(vertex != NULL);
- bounds.addPointToBounds( vertex->pos );
- }
-
- return bounds;
-}
-
-/*Sphere MeshBounds::sphere(const HalfEdge::Mesh * mesh)
-{
- // @@ TODO
- return Sphere();
-}*/
diff --git a/thirdparty/thekla_atlas/nvmesh/geometry/Bounds.h b/thirdparty/thekla_atlas/nvmesh/geometry/Bounds.h
deleted file mode 100644
index 1cb5b7b905..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/geometry/Bounds.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
-
-#pragma once
-#ifndef NV_MESH_MESHBOUNDS_H
-#define NV_MESH_MESHBOUNDS_H
-
-#include <nvmath/Sphere.h>
-#include <nvmath/Box.h>
-
-#include <nvmesh/nvmesh.h>
-
-namespace nv
-{
- class BaseMesh;
- namespace HalfEdge { class Mesh; }
-
- // Bounding volumes computation.
- namespace MeshBounds
- {
- Box box(const BaseMesh * mesh);
- Box box(const HalfEdge::Mesh * mesh);
-
- Sphere sphere(const HalfEdge::Mesh * mesh);
- }
-
-} // nv namespace
-
-#endif // NV_MESH_MESHBOUNDS_H
diff --git a/thirdparty/thekla_atlas/nvmesh/geometry/Measurements.cpp b/thirdparty/thekla_atlas/nvmesh/geometry/Measurements.cpp
deleted file mode 100644
index e0c271663b..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/geometry/Measurements.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-// This code is in the public domain -- castano@gmail.com
-
-#include "nvmesh.h" // pch
-
-#include "Measurements.h"
-#include "nvmesh/halfedge/Mesh.h"
-#include "nvmesh/halfedge/Face.h"
-
-using namespace nv;
-
-float nv::computeSurfaceArea(const HalfEdge::Mesh * mesh)
-{
- float area = 0;
-
- for (HalfEdge::Mesh::ConstFaceIterator it(mesh->faces()); !it.isDone(); it.advance())
- {
- const HalfEdge::Face * face = it.current();
- area += face->area();
- }
- nvDebugCheck(area >= 0);
-
- return area;
-}
-
-float nv::computeParametricArea(const HalfEdge::Mesh * mesh)
-{
- float area = 0;
-
- for (HalfEdge::Mesh::ConstFaceIterator it(mesh->faces()); !it.isDone(); it.advance())
- {
- const HalfEdge::Face * face = it.current();
- area += face->parametricArea();
- }
-
- return area;
-}
diff --git a/thirdparty/thekla_atlas/nvmesh/geometry/Measurements.h b/thirdparty/thekla_atlas/nvmesh/geometry/Measurements.h
deleted file mode 100644
index 0be863b79e..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/geometry/Measurements.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// This code is in the public domain -- castano@gmail.com
-
-#pragma once
-#ifndef NV_MESH_MESHMEASUREMENTS_H
-#define NV_MESH_MESHMEASUREMENTS_H
-
-#include "nvmesh/nvmesh.h"
-
-namespace nv
-{
- namespace HalfEdge { class Mesh; }
-
- float computeSurfaceArea(const HalfEdge::Mesh * mesh);
- float computeParametricArea(const HalfEdge::Mesh * mesh);
-
-} // nv namespace
-
-#endif // NV_MESH_MESHMEASUREMENTS_H
diff --git a/thirdparty/thekla_atlas/nvmesh/halfedge/Edge.cpp b/thirdparty/thekla_atlas/nvmesh/halfedge/Edge.cpp
deleted file mode 100644
index 671650296c..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/halfedge/Edge.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-// This code is in the public domain -- castanyo@yahoo.es
-
-#include "nvmesh.h" // pch
-
-#include "Edge.h"
-#include "Vertex.h"
-
-#include "nvmath/Vector.inl"
-
-using namespace nv;
-using namespace HalfEdge;
-
-Vector3 Edge::midPoint() const
-{
- return (to()->pos + from()->pos) * 0.5f;
-}
-
-float Edge::length() const
-{
- return ::length(to()->pos - from()->pos);
-}
-
-// Return angle between this edge and the previous one.
-float Edge::angle() const {
- Vector3 p = vertex->pos;
- Vector3 a = prev->vertex->pos;
- Vector3 b = next->vertex->pos;
-
- Vector3 v0 = a - p;
- Vector3 v1 = b - p;
-
- return acosf(dot(v0, v1) / (nv::length(v0) * nv::length(v1)));
-}
-
-bool Edge::isValid() const
-{
- // null face is OK.
- if (next == NULL || prev == NULL || pair == NULL || vertex == NULL) return false;
- if (next->prev != this) return false;
- if (prev->next != this) return false;
- if (pair->pair != this) return false;
- return true;
-}
-
-/*
-Edge * Edge::nextBoundary() {
- nvDebugCheck(this->m_pair == NULL);
-
-}
-
-Edge * Edge::prevBoundary() {
- nvDebugCheck(this->m_pair == NULL);
-
-}
-*/
-
-
diff --git a/thirdparty/thekla_atlas/nvmesh/halfedge/Edge.h b/thirdparty/thekla_atlas/nvmesh/halfedge/Edge.h
deleted file mode 100644
index 25c47f4860..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/halfedge/Edge.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// This code is in the public domain -- castanyo@yahoo.es
-
-#pragma once
-#ifndef NV_MESH_HALFEDGE_EDGE_H
-#define NV_MESH_HALFEDGE_EDGE_H
-
-#include "nvmath/Vector.h"
-
-namespace nv
-{
- namespace HalfEdge { class Vertex; class Face; class Edge; }
-
- /// Half edge edge.
- class HalfEdge::Edge
- {
- NV_FORBID_COPY(Edge);
- public:
-
- uint id;
-
- Edge * next;
- Edge * prev; // This is not strictly half-edge, but makes algorithms easier and faster.
- Edge * pair;
- Vertex * vertex;
- Face * face;
-
-
- // Default constructor.
- Edge(uint id) : id(id), next(NULL), prev(NULL), pair(NULL), vertex(NULL), face(NULL)
- {
- }
-
-
- // Vertex queries.
- const Vertex * from() const { return vertex; }
- Vertex * from() { return vertex; }
-
- const Vertex * to() const { return pair->vertex; } // This used to be 'next->vertex', but that changed often when the connectivity of the mesh changes.
- Vertex * to() { return pair->vertex; }
-
-
- // Edge queries.
- void setNext(Edge * e) { next = e; if (e != NULL) e->prev = this; }
- void setPrev(Edge * e) { prev = e; if (e != NULL) e->next = this; }
-
- // @@ Add these helpers:
- //Edge * nextBoundary();
- //Edge * prevBoundary();
-
-
- // @@ It would be more simple to only check m_pair == NULL
- // Face queries.
- bool isBoundary() const { return !(face && pair->face); }
-
- // @@ This is not exactly accurate, we should compare the texture coordinates...
- bool isSeam() const { return vertex != pair->next->vertex || next->vertex != pair->vertex; }
-
- bool isValid() const;
-
- // Geometric queries.
- Vector3 midPoint() const;
- float length() const;
- float angle() const;
-
- };
-
-} // nv namespace
-
-
-#endif // NV_MESH_HALFEDGE_EDGE_H
diff --git a/thirdparty/thekla_atlas/nvmesh/halfedge/Face.cpp b/thirdparty/thekla_atlas/nvmesh/halfedge/Face.cpp
deleted file mode 100644
index 9f6987154e..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/halfedge/Face.cpp
+++ /dev/null
@@ -1,268 +0,0 @@
-// This code is in the public domain -- castanyo@yahoo.es
-
-#include "nvmesh.h" // pch
-
-#include "Face.h"
-#include "Vertex.h"
-
-#include "nvmath/Fitting.h"
-#include "nvmath/Plane.h"
-#include "nvmath/Vector.inl"
-
-#include "nvcore/Array.h"
-
-
-using namespace nv;
-using namespace HalfEdge;
-
-/// Get face area.
-float Face::area() const
-{
- float area = 0;
- const Vector3 & v0 = edge->from()->pos;
-
- for (ConstEdgeIterator it(edges(edge->next)); it.current() != edge->prev; it.advance())
- {
- const Edge * e = it.current();
-
- const Vector3 & v1 = e->vertex->pos;
- const Vector3 & v2 = e->next->vertex->pos;
-
- area += length(cross(v1-v0, v2-v0));
- }
-
- return area * 0.5f;
-}
-
-float Face::parametricArea() const
-{
- float area = 0;
- const Vector2 & v0 = edge->from()->tex;
-
- for (ConstEdgeIterator it(edges(edge->next)); it.current() != edge->prev; it.advance())
- {
- const Edge * e = it.current();
-
- const Vector2 & v1 = e->vertex->tex;
- const Vector2 & v2 = e->next->vertex->tex;
-
- area += triangleArea(v0, v1, v2);
- }
-
- return area * 0.5f;
-}
-
-
-/// Get boundary length.
-float Face::boundaryLength() const
-{
- float bl = 0;
-
- for (ConstEdgeIterator it(edges()); !it.isDone(); it.advance())
- {
- const Edge * edge = it.current();
- bl += edge->length();
- }
-
- return bl;
-}
-
-
-/// Get face normal.
-Vector3 Face::normal() const
-{
- Vector3 n(0);
-
- const Vertex * vertex0 = NULL;
-
- for (ConstEdgeIterator it(edges()); !it.isDone(); it.advance())
- {
- const Edge * edge = it.current();
- nvCheck(edge != NULL);
-
- if (vertex0 == NULL)
- {
- vertex0 = edge->vertex;
- }
- else if (edge->next->vertex != vertex0)
- {
- const HalfEdge::Vertex * vertex1 = edge->from();
- const HalfEdge::Vertex * vertex2 = edge->to();
-
- const Vector3 & p0 = vertex0->pos;
- const Vector3 & p1 = vertex1->pos;
- const Vector3 & p2 = vertex2->pos;
-
- Vector3 v10 = p1 - p0;
- Vector3 v20 = p2 - p0;
-
- n += cross(v10, v20);
- }
- }
-
- return normalizeSafe(n, Vector3(0, 0, 1), 0.0f);
-
-
- // Get face points eliminating duplicates.
- /*Array<Vector3> points(4);
-
- points.append(m_edge->prev()->from()->pos);
-
- for (ConstEdgeIterator it(edges()); !it.isDone(); it.advance())
- {
- const Edge * edge = it.current();
- nvDebugCheck(edge != NULL);
-
- const Vector3 & p = edge->from()->pos;
- if (points.back() != p)
- {
- points.append(edge->from()->pos);
- }
- }
-
- points.popBack();
-
- if (points.count() < 3)
- {
- // Invalid normal.
- return Vector3(0.0f);
- }
- else
- {
- // Compute regular normal.
- Vector3 normal = normalizeSafe(cross(points[1] - points[0], points[2] - points[0]), Vector3(0.0f), 0.0f);
-
-#pragma NV_MESSAGE("TODO: make sure these three points are not colinear")
-
- if (points.count() > 3)
- {
- // Compute best fitting plane to the points.
- Plane plane = Fit::bestPlane(points.count(), points.buffer());
-
- // Adjust normal orientation.
- if (dot(normal, plane.vector()) > 0) {
- normal = plane.vector();
- }
- else {
- normal = -plane.vector();
- }
- }
-
- nvDebugCheck(isNormalized(normal));
- return normal;
- }*/
-}
-
-Vector3 Face::centroid() const
-{
- Vector3 sum(0.0f);
- uint count = 0;
-
- for (ConstEdgeIterator it(edges()); !it.isDone(); it.advance())
- {
- const Edge * edge = it.current();
- sum += edge->from()->pos;
- count++;
- }
-
- return sum / float(count);
-}
-
-
-bool Face::isValid() const
-{
- uint count = 0;
-
- for (ConstEdgeIterator it(edges()); !it.isDone(); it.advance())
- {
- const Edge * edge = it.current();
- if (edge->face != this) return false;
- if (!edge->isValid()) return false;
- if (!edge->pair->isValid()) return false;
- count++;
- }
-
- if (count < 3) return false;
-
- return true;
-}
-
-
-// Determine if this face contains the given edge.
-bool Face::contains(const Edge * e) const
-{
- for (ConstEdgeIterator it(edges()); !it.isDone(); it.advance())
- {
- if(it.current() == e) return true;
- }
- return false;
-}
-
-// Returns index in this face of the given edge.
-uint Face::edgeIndex(const Edge * e) const
-{
- int i = 0;
- for (ConstEdgeIterator it(edges()); !it.isDone(); it.advance(), i++)
- {
- if(it.current() == e) return i;
- }
- return NIL;
-}
-
-
-Edge * Face::edgeAt(uint idx)
-{
- int i = 0;
- for(EdgeIterator it(edges()); !it.isDone(); it.advance(), i++) {
- if (i == idx) return it.current();
- }
- return NULL;
-}
-const Edge * Face::edgeAt(uint idx) const
-{
- int i = 0;
- for(ConstEdgeIterator it(edges()); !it.isDone(); it.advance(), i++) {
- if (i == idx) return it.current();
- }
- return NULL;
-}
-
-
-// Count the number of edges in this face.
-uint Face::edgeCount() const
-{
- uint count = 0;
- for (ConstEdgeIterator it(edges()); !it.isDone(); it.advance()) { ++count; }
- return count;
-}
-
-// Determine if this is a boundary face.
-bool Face::isBoundary() const
-{
- for (ConstEdgeIterator it(edges()); !it.isDone(); it.advance())
- {
- const Edge * edge = it.current();
- nvDebugCheck(edge->pair != NULL);
-
- if (edge->pair->face == NULL) {
- return true;
- }
- }
- return false;
-}
-
-// Count the number of boundary edges in the face.
-uint Face::boundaryCount() const
-{
- uint count = 0;
- for (ConstEdgeIterator it(edges()); !it.isDone(); it.advance())
- {
- const Edge * edge = it.current();
- nvDebugCheck(edge->pair != NULL);
-
- if (edge->pair->face == NULL) {
- count++;
- }
- }
- return count;
-}
diff --git a/thirdparty/thekla_atlas/nvmesh/halfedge/Face.h b/thirdparty/thekla_atlas/nvmesh/halfedge/Face.h
deleted file mode 100644
index 677f8666f0..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/halfedge/Face.h
+++ /dev/null
@@ -1,106 +0,0 @@
-// This code is in the public domain -- castanyo@yahoo.es
-
-#pragma once
-#ifndef NV_MESH_HALFEDGE_FACE_H
-#define NV_MESH_HALFEDGE_FACE_H
-
-#include <nvmesh/halfedge/Edge.h>
-
-namespace nv
-{
- namespace HalfEdge { class Vertex; class Face; class Edge; }
-
- /// Face of a half-edge mesh.
- class HalfEdge::Face
- {
- NV_FORBID_COPY(Face);
- public:
-
- uint id;
- uint16 group;
- uint16 material;
- Edge * edge;
-
-
- Face(uint id) : id(id), group(~0), material(~0), edge(NULL) {}
-
- float area() const;
- float parametricArea() const;
- float boundaryLength() const;
- Vector3 normal() const;
- Vector3 centroid() const;
-
- bool isValid() const;
-
- bool contains(const Edge * e) const;
- uint edgeIndex(const Edge * e) const;
-
- Edge * edgeAt(uint idx);
- const Edge * edgeAt(uint idx) const;
-
- uint edgeCount() const;
- bool isBoundary() const;
- uint boundaryCount() const;
-
-
- // The iterator that visits the edges of this face in clockwise order.
- class EdgeIterator //: public Iterator<Edge *>
- {
- public:
- EdgeIterator(Edge * e) : m_end(NULL), m_current(e) { }
-
- virtual void advance()
- {
- if (m_end == NULL) m_end = m_current;
- m_current = m_current->next;
- }
-
- virtual bool isDone() const { return m_end == m_current; }
- virtual Edge * current() const { return m_current; }
- Vertex * vertex() const { return m_current->vertex; }
-
- private:
- Edge * m_end;
- Edge * m_current;
- };
-
- EdgeIterator edges() { return EdgeIterator(edge); }
- EdgeIterator edges(Edge * e)
- {
- nvDebugCheck(contains(e));
- return EdgeIterator(e);
- }
-
- // The iterator that visits the edges of this face in clockwise order.
- class ConstEdgeIterator //: public Iterator<const Edge *>
- {
- public:
- ConstEdgeIterator(const Edge * e) : m_end(NULL), m_current(e) { }
- ConstEdgeIterator(const EdgeIterator & it) : m_end(NULL), m_current(it.current()) { }
-
- virtual void advance()
- {
- if (m_end == NULL) m_end = m_current;
- m_current = m_current->next;
- }
-
- virtual bool isDone() const { return m_end == m_current; }
- virtual const Edge * current() const { return m_current; }
- const Vertex * vertex() const { return m_current->vertex; }
-
- private:
- const Edge * m_end;
- const Edge * m_current;
- };
-
- ConstEdgeIterator edges() const { return ConstEdgeIterator(edge); }
- ConstEdgeIterator edges(const Edge * e) const
- {
- nvDebugCheck(contains(e));
- return ConstEdgeIterator(e);
- }
- };
-
-} // nv namespace
-
-#endif // NV_MESH_HALFEDGE_FACE_H
diff --git a/thirdparty/thekla_atlas/nvmesh/halfedge/Mesh.cpp b/thirdparty/thekla_atlas/nvmesh/halfedge/Mesh.cpp
deleted file mode 100644
index 0012513bce..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/halfedge/Mesh.cpp
+++ /dev/null
@@ -1,1284 +0,0 @@
-// This code is in the public domain -- castanyo@yahoo.es
-
-#include "nvmesh.h" // pch
-
-#include "Mesh.h"
-#include "Edge.h"
-#include "Vertex.h"
-#include "Face.h"
-
-#include "nvmesh/TriMesh.h"
-#include "nvmesh/QuadTriMesh.h"
-#include "nvmesh/MeshBuilder.h"
-
-#include "nvmath/Vector.inl"
-#include "nvcore/Array.inl"
-#include "nvcore/HashMap.inl"
-
-
-using namespace nv;
-using namespace HalfEdge;
-
-Mesh::Mesh() : m_colocalVertexCount(0)
-{
- errorCount = 0;
-}
-
-Mesh::Mesh(const Mesh * mesh)
-{
- errorCount = 0;
-
- // Copy mesh vertices.
- const uint vertexCount = mesh->vertexCount();
- m_vertexArray.resize(vertexCount);
-
- for (uint v = 0; v < vertexCount; v++)
- {
- const Vertex * vertex = mesh->vertexAt(v);
- nvDebugCheck(vertex->id == v);
-
- m_vertexArray[v] = new Vertex(v);
- m_vertexArray[v]->pos = vertex->pos;
- m_vertexArray[v]->nor = vertex->nor;
- m_vertexArray[v]->tex = vertex->tex;
- }
-
- m_colocalVertexCount = vertexCount;
-
-
- // Copy mesh faces.
- const uint faceCount = mesh->faceCount();
-
- Array<uint> indexArray(3);
-
- for (uint f = 0; f < faceCount; f++)
- {
- const Face * face = mesh->faceAt(f);
-
- for(Face::ConstEdgeIterator it(face->edges()); !it.isDone(); it.advance()) {
- const Vertex * vertex = it.current()->from();
- indexArray.append(vertex->id);
- }
-
- addFace(indexArray);
- indexArray.clear();
- }
-}
-
-Mesh::~Mesh()
-{
- clear();
-}
-
-
-void Mesh::clear()
-{
- deleteAll(m_vertexArray);
- m_vertexArray.clear();
-
- foreach(i, m_edgeMap)
- {
- delete m_edgeMap[i].value;
- }
- //deleteAll(m_edgeArray); // edgeArray only contains 1/2 of the edges!
- m_edgeArray.clear();
- m_edgeMap.clear();
-
- deleteAll(m_faceArray);
- m_faceArray.clear();
-}
-
-
-Vertex * Mesh::addVertex(const Vector3 & pos)
-{
- nvDebugCheck(isFinite(pos));
-
- Vertex * v = new Vertex(m_vertexArray.count());
- v->pos = pos;
- m_vertexArray.append(v);
-
- return v;
-
-// return addVertex(m_vertexArray.count(), pos);
-}
-
-/*Vertex * Mesh::addVertex(uint id, const Vector3 & pos)
-{
- nvDebugCheck(isFinite(pos));
-
- Vertex * v = new Vertex(id);
- v->pos = pos;
- m_vertexArray.append(v);
-
- return v;
-}*/
-
-/*void Mesh::addVertices(const Mesh * mesh)
-{
-nvCheck(mesh != NULL);
-
-// Add mesh vertices
-for (uint v = 0; v < vertexCount; v++)
-{
-const Vertex * vertex = mesh->vertexAt(v);
-nvDebugCheck(vertex != NULL);
-
-Vertex * v = addVertex(vertex->pos());
-nvDebugCheck(v != NULL);
-
-v->setNor(vertex->nor());
-v->setTex(vertex->tex());
-}
-}*/
-
-
-/// Link colocal vertices based on geometric location only.
-void Mesh::linkColocals()
-{
- nvDebug("--- Linking colocals:\n");
-
- const uint vertexCount = this->vertexCount();
- HashMap<Vector3, Vertex *> vertexMap(vertexCount);
-
- for (uint v = 0; v < vertexCount; v++)
- {
- Vertex * vertex = vertexAt(v);
-
- Vertex * colocal;
- if (vertexMap.get(vertex->pos, &colocal))
- {
- colocal->linkColocal(vertex);
- }
- else
- {
- vertexMap.add(vertex->pos, vertex);
- }
- }
-
- m_colocalVertexCount = vertexMap.count();
-
- nvDebug("--- %d vertex positions.\n", m_colocalVertexCount);
-
- // @@ Remove duplicated vertices? or just leave them as colocals?
-}
-
-void Mesh::linkColocalsWithCanonicalMap(const Array<uint> & canonicalMap)
-{
- nvDebug("--- Linking colocals:\n");
-
- uint vertexMapSize = 0;
- foreach(i, canonicalMap) {
- vertexMapSize = max(vertexMapSize, canonicalMap[i] + 1);
- }
-
- Array<Vertex *> vertexMap;
- vertexMap.resize(vertexMapSize, NULL);
-
- m_colocalVertexCount = 0;
-
- const uint vertexCount = this->vertexCount();
- for (uint v = 0; v < vertexCount; v++)
- {
- Vertex * vertex = vertexAt(v);
-
- Vertex * colocal = vertexMap[canonicalMap[v]];
- if (colocal != NULL)
- {
- nvDebugCheck(vertex->pos == colocal->pos);
- colocal->linkColocal(vertex);
- }
- else
- {
- vertexMap[canonicalMap[v]] = vertex;
- m_colocalVertexCount++;
- }
- }
-
- nvDebug("--- %d vertex positions.\n", m_colocalVertexCount);
-}
-
-
-Face * Mesh::addFace()
-{
- Face * f = new Face(m_faceArray.count());
- m_faceArray.append(f);
- return f;
-}
-
-Face * Mesh::addFace(uint v0, uint v1, uint v2)
-{
- Array<uint> indexArray(3);
- indexArray << v0 << v1 << v2;
- return addFace(indexArray, 0, 3);
-}
-
-Face * Mesh::addFace(uint v0, uint v1, uint v2, uint v3)
-{
- Array<uint> indexArray(4);
- indexArray << v0 << v1 << v2 << v3;
- return addFace(indexArray, 0, 4);
-}
-
-Face * Mesh::addFace(const Array<uint> & indexArray)
-{
- return addFace(indexArray, 0, indexArray.count());
-}
-
-
-Face * Mesh::addFace(const Array<uint> & indexArray, uint first, uint num)
-{
- nvDebugCheck(first < indexArray.count());
- nvDebugCheck(num <= indexArray.count()-first);
- nvDebugCheck(num > 2);
-
- if (!canAddFace(indexArray, first, num)) {
- errorCount++;
- return NULL;
- }
-
- Face * f = new Face(m_faceArray.count());
-
- Edge * firstEdge = NULL;
- Edge * last = NULL;
- Edge * current = NULL;
-
- for(uint i = 0; i < num-1; i++)
- {
- current = addEdge(indexArray[first+i], indexArray[first+i+1]);
- nvCheck(current != NULL && current->face == NULL);
-
- current->face = f;
-
- if (last != NULL) last->setNext(current);
- else firstEdge = current;
-
- last = current;
- }
-
- current = addEdge(indexArray[first+num-1], indexArray[first]);
- nvCheck(current != NULL && current->face == NULL);
-
- current->face = f;
-
- last->setNext(current);
- current->setNext(firstEdge);
-
- f->edge = firstEdge;
- m_faceArray.append(f);
-
- return f;
-}
-
-/*void Mesh::addFaces(const Mesh * mesh)
-{
-nvCheck(mesh != NULL);
-
-Array indexArray;
-// Add faces
-
-}*/
-
-
-// Return true if the face can be added to the manifold mesh.
-bool Mesh::canAddFace(const Array<uint> & indexArray, uint first, uint num) const
-{
- for (uint j = num - 1, i = 0; i < num; j = i++) {
- if (!canAddEdge(indexArray[first+j], indexArray[first+i])) {
- errorIndex0 = indexArray[first+j];
- errorIndex1 = indexArray[first+i];
- return false;
- }
- }
-
- // We also have to make sure the face does not have any duplicate edge!
- for (uint i = 0; i < num; i++) {
-
- int i0 = indexArray[first + i + 0];
- int i1 = indexArray[first + (i + 1)%num];
-
- for (uint j = i + 1; j < num; j++) {
- int j0 = indexArray[first + j + 0];
- int j1 = indexArray[first + (j + 1)%num];
-
- if (i0 == j0 && i1 == j1) {
- return false;
- }
- }
- }
-
- return true;
-}
-
-// Return true if the edge doesn't exist or doesn't have any adjacent face.
-bool Mesh::canAddEdge(uint i, uint j) const
-{
- if (i == j) {
- // Skip degenerate edges.
- return false;
- }
-
- // Same check, but taking into account colocal vertices.
- const Vertex * v0 = vertexAt(i);
- const Vertex * v1 = vertexAt(j);
-
- for(Vertex::ConstVertexIterator it(v0->colocals()); !it.isDone(); it.advance())
- {
- if (it.current() == v1)
- {
- // Skip degenerate edges.
- return false;
- }
- }
-
- // Make sure edge has not been added yet.
- Edge * edge = findEdge(i, j);
-
- return edge == NULL || edge->face == NULL; // We ignore edges that don't have an adjacent face yet, since this face could become the edge's face.
-}
-
-Edge * Mesh::addEdge(uint i, uint j)
-{
- nvCheck(i != j);
-
- Edge * edge = findEdge(i, j);
-
- if (edge != NULL) {
- // Edge may already exist, but its face must not be set.
- nvDebugCheck(edge->face == NULL);
-
- // Nothing else to do!
-
- }
- else {
- // Add new edge.
-
- // Lookup pair.
- Edge * pair = findEdge(j, i);
-
- if (pair != NULL)
- {
- // Create edge with same id.
- edge = new Edge(pair->id + 1);
-
- // Link edge pairs.
- edge->pair = pair;
- pair->pair = edge;
-
- // @@ I'm not sure this is necessary!
- pair->vertex->setEdge(pair);
- }
- else
- {
- // Create edge.
- edge = new Edge(2*m_edgeArray.count());
-
- // Add only unpaired edges.
- m_edgeArray.append(edge);
- }
-
- edge->vertex = m_vertexArray[i];
- m_edgeMap.add(Key(i,j), edge);
- }
-
- // Face and Next are set by addFace.
-
- return edge;
-}
-
-
-/// Find edge, test all colocals.
-Edge * Mesh::findEdge(uint i, uint j) const
-{
- Edge * edge = NULL;
-
- const Vertex * v0 = vertexAt(i);
- const Vertex * v1 = vertexAt(j);
-
- // Test all colocal pairs.
- for(Vertex::ConstVertexIterator it0(v0->colocals()); !it0.isDone(); it0.advance())
- {
- for(Vertex::ConstVertexIterator it1(v1->colocals()); !it1.isDone(); it1.advance())
- {
- Key key(it0.current()->id, it1.current()->id);
-
- if (edge == NULL) {
- m_edgeMap.get(key, &edge);
-#if !defined(_DEBUG)
- if (edge != NULL) return edge;
-#endif
- }
- else {
- // Make sure that only one edge is found.
- nvDebugCheck(!m_edgeMap.get(key));
- }
- }
- }
-
- return edge;
-}
-
-/// Link boundary edges once the mesh has been created.
-void Mesh::linkBoundary()
-{
- nvDebug("--- Linking boundaries:\n");
-
- int num = 0;
-
- // Create boundary edges.
- uint edgeCount = this->edgeCount();
- for(uint e = 0; e < edgeCount; e++)
- {
- Edge * edge = edgeAt(e);
- if (edge != NULL && edge->pair == NULL) {
- Edge * pair = new Edge(edge->id + 1);
-
- uint i = edge->from()->id;
- uint j = edge->next->from()->id;
-
- Key key(j,i);
- nvCheck(!m_edgeMap.get(key));
-
- pair->vertex = m_vertexArray[j];
- m_edgeMap.add(key, pair);
-
- edge->pair = pair;
- pair->pair = edge;
-
- num++;
- }
- }
-
- // Link boundary edges.
- for (uint e = 0; e < edgeCount; e++) {
- Edge * edge = edgeAt(e);
- if (edge != NULL && edge->pair->face == NULL) {
- linkBoundaryEdge(edge->pair);
- }
- }
-
- nvDebug("--- %d boundary edges.\n", num);
-}
-
-/// Link this boundary edge.
-void Mesh::linkBoundaryEdge(Edge * edge)
-{
- nvCheck(edge->face == NULL);
-
- // Make sure next pointer has not been set. @@ We want to be able to relink boundary edges after mesh changes.
- //nvCheck(edge->next() == NULL);
-
- Edge * next = edge;
- while(next->pair->face != NULL) {
- // Get pair prev
- Edge * e = next->pair->next;
- while (e->next != next->pair) {
- e = e->next;
- }
- next = e;
- }
- edge->setNext(next->pair);
-
- // Adjust vertex edge, so that it's the boundary edge. (required for isBoundary())
- if (edge->vertex->edge != edge)
- {
- // Multiple boundaries in the same edge.
- //nvCheck( edge->vertex()->edge() == NULL || edge->vertex()->edge()->face() != NULL );
- edge->vertex->edge = edge;
- }
-}
-
-
-/// Convert to tri mesh.
-TriMesh * Mesh::toTriMesh() const
-{
- uint triangleCount = 0;
-
- // Count triangle faces.
- const uint faceCount = this->faceCount();
- for(uint f = 0; f < faceCount; f++)
- {
- const Face * face = faceAt(f);
- triangleCount += face->edgeCount() - 2;
- }
-
- TriMesh * triMesh = new TriMesh(triangleCount, vertexCount());
-
- // Add vertices.
- Array<TriMesh::Vertex> & vertices = triMesh->vertices();
-
- const uint vertexCount = this->vertexCount();
- for(uint v = 0; v < vertexCount; v++)
- {
- const Vertex * vertex = vertexAt(v);
-
- TriMesh::Vertex triVertex;
- triVertex.id = vertices.count();
- triVertex.pos = vertex->pos;
- triVertex.nor = vertex->nor;
- triVertex.tex = vertex->tex;
-
- vertices.append(triVertex);
- }
-
- // Add triangles.
- Array<TriMesh::Face> & triangles = triMesh->faces();
-
- for(uint f = 0; f < faceCount; f++)
- {
- const Face * face = faceAt(f);
-
- // @@ Triangulate arbitrary polygons correctly.
- const uint v0 = face->edge->vertex->id;
- uint v1 = face->edge->next->vertex->id;
-
- for(Face::ConstEdgeIterator it(face->edges()); !it.isDone(); it.advance())
- {
- uint v2 = it.current()->vertex->id;
-
- // Skip the first two vertices.
- if (v2 == v0 || v2 == v1) continue;
-
- TriMesh::Face triangle;
- triangle.id = triangles.count();
- triangle.v[0] = v0;
- triangle.v[1] = v1;
- triangle.v[2] = v2;
-
- v1 = v2;
-
- triangles.append(triangle);
- }
- }
-
- return triMesh;
-}
-
-QuadTriMesh * Mesh::toQuadTriMesh() const
-{
- MeshBuilder builder;
-
- const uint vertexCount = this->vertexCount();
- builder.hintVertexCount(vertexCount);
-
- for(uint v = 0; v < vertexCount; v++)
- {
- const Vertex * vertex = vertexAt(v);
-
- builder.addPosition(vertex->pos);
- builder.addNormal(vertex->nor);
- builder.addTexCoord(vertex->tex);
- }
-
- const uint faceCount = this->faceCount();
- builder.hintTriangleCount(faceCount);
-
- for(uint f = 0; f < faceCount; f++)
- {
- const Face * face = faceAt(f);
-
- builder.beginPolygon();
-
- for(Face::ConstEdgeIterator it(face->edges()); !it.isDone(); it.advance())
- {
- uint v = it.current()->vertex->id;
- builder.addVertex(v, v, v);
- }
-
- builder.endPolygon();
- }
-
- builder.done();
-
- return builder.buildQuadTriMesh();
-}
-
-
-// Triangulate in place.
-void Mesh::triangulate() {
-
- bool all_triangles = true;
-
- const uint faceCount = m_faceArray.count();
- for (uint f = 0; f < faceCount; f++) {
- Face * face = m_faceArray[f];
- if (face->edgeCount() != 3) {
- all_triangles = false;
- break;
- }
- }
-
- if (all_triangles) {
- return;
- }
-
-
- // Do not touch vertices, but rebuild edges and faces.
- Array<Edge *> edgeArray;
- Array<Face *> faceArray;
-
- swap(edgeArray, m_edgeArray);
- swap(faceArray, m_faceArray);
- m_edgeMap.clear();
-
- for (uint f = 0; f < faceCount; f++) {
- Face * face = faceArray[f];
-
- // Trivial fan-like triangulation.
- const uint v0 = face->edge->vertex->id;
- uint v2, v1 = -1;
-
- for (Face::EdgeIterator it(face->edges()); !it.isDone(); it.advance()) {
- Edge * edge = it.current();
- v2 = edge->to()->id;
- if (v2 == v0) break;
- if (v1 != -1) addFace(v0, v1, v2);
- v1 = v2;
- }
- }
-
- nvDebugCheck(m_faceArray.count() > faceCount); // triangle count > face count
-
- linkBoundary();
-
- deleteAll(edgeArray);
- deleteAll(faceArray);
-}
-
-
-/*
-Fixing T-junctions.
-
-- Find T-junctions. Find vertices that are on an edge.
- - This test is approximate.
- - Insert edges on a spatial index to speedup queries.
- - Consider only open edges, that is edges that have no pairs.
- - Consider only vertices on boundaries.
-- Close T-junction.
- - Split edge.
-
-*/
-bool Mesh::splitBoundaryEdges() {
-
- Array<Vertex *> boundaryVertices;
-
- foreach(i, m_vertexArray) {
- Vertex * v = m_vertexArray[i];
- if (v->isBoundary()) {
- boundaryVertices.append(v);
- }
- }
-
- nvDebug("Fixing T-junctions:\n");
-
- int splitCount = 0;
-
- foreach(v, boundaryVertices) {
- Vertex * vertex = boundaryVertices[v];
-
- Vector3 x0 = vertex->pos;
-
- // Find edges that this vertex overlaps with.
- foreach(e, m_edgeArray) {
- //for (uint e = 0; e < m_edgeArray.count(); e++) {
- Edge * edge = m_edgeArray[e];
- if (edge != NULL && edge->isBoundary()) {
-
- if (edge->from() == vertex || edge->to() == vertex) {
- continue;
- }
-
- Vector3 x1 = edge->from()->pos;
- Vector3 x2 = edge->to()->pos;
-
- Vector3 v01 = x0 - x1;
- Vector3 v21 = x2 - x1;
-
- float l = length(v21);
- float d = length(cross(v01, v21)) / l;
-
- if (isZero(d)) {
- float t = dot(v01, v21) / (l * l);
-
- // @@ Snap x0 to x1 or x2, if too close? No, do vertex snapping elsewhere.
- /*if (equal(t, 0.0f, 0.01f)) {
- //vertex->setPos(x1);
- }
- else if (equal(t, 1.0f, 0.01f)) {
- //vertex->setPos(x2);
- }
- else*/
- if (t > 0.0f + NV_EPSILON && t < 1.0f - NV_EPSILON) {
- nvDebugCheck(equal(lerp(x1, x2, t), x0));
-
- Vertex * splitVertex = splitBoundaryEdge(edge, t, x0);
- vertex->linkColocal(splitVertex); // @@ Should we do this here?
- splitCount++;
- }
- }
- }
- }
- }
-
- nvDebug(" - %d edges split.\n", splitCount);
-
- nvDebugCheck(isValid());
-
- return splitCount != 0;
-}
-
-
-// For this to be effective, we have to fix the boundary junctions first.
-Edge * Mesh::sewBoundary(Edge * startEdge) {
- nvDebugCheck(startEdge->face == NULL);
-
- // @@ We may want to be more conservative linking colocals in order to preserve the input topology. One way of doing that is by linking colocals only
- // if the vertices next to them are linked as well. That is, by sewing boundaries after detecting them. If any pair of consecutive edges have their first
- // and last vertex in the same position, then it can be linked.
-
- Edge * lastBoundarySeen = startEdge;
-
- nvDebug("Sewing Boundary:\n");
-
- int count = 0;
- int sewnCount = 0;
-
- Edge * edge = startEdge;
- do {
- nvDebugCheck(edge->face == NULL);
-
- Edge * edge_a = edge;
- Edge * edge_b = edge->prev;
-
- Edge * pair_a = edge_a->pair;
- Edge * pair_b = edge_b->pair;
-
- Vertex * v0a = edge_a->to();
- Vertex * v0b = edge_b->from();
- Vertex * v1a = edge_a->from();
- Vertex * v1b = edge_b->to();
-
- nvDebugCheck(v1a->isColocal(v1b));
-
- /*
- v0b + _+ v0a
- \ /
- b \ / a
- \|/
- v1b + v1a
- */
-
- // @@ This should not happen while sewing, but it may be produced somewhere else.
- nvDebugCheck(edge_a != edge_b);
-
- if (v0a->pos == v0b->pos) {
-
- // Link vertices.
- v0a->linkColocal(v0b);
-
- // Remove edges to be collapsed.
- disconnect(edge_a);
- disconnect(edge_b);
- disconnect(pair_a);
- disconnect(pair_b);
-
- // Link new boundary edges.
- Edge * prevBoundary = edge_b->prev;
- Edge * nextBoundary = edge_a->next;
- if (nextBoundary != NULL) {
- nvDebugCheck(nextBoundary->face == NULL);
- nvDebugCheck(prevBoundary->face == NULL);
- nextBoundary->setPrev(prevBoundary);
-
- // Make sure boundary vertex points to boundary edge.
- v0a->setEdge(nextBoundary); // This updates all colocals.
- }
- lastBoundarySeen = prevBoundary;
-
- // Creat new edge.
- Edge * newEdge_a = addEdge(v0a->id, v1a->id); // pair_a->from()->id, pair_a->to()->id
- Edge * newEdge_b = addEdge(v1b->id, v0b->id);
-
- newEdge_a->pair = newEdge_b;
- newEdge_b->pair = newEdge_a;
-
- newEdge_a->face = pair_a->face;
- newEdge_b->face = pair_b->face;
-
- newEdge_a->setNext(pair_a->next);
- newEdge_a->setPrev(pair_a->prev);
-
- newEdge_b->setNext(pair_b->next);
- newEdge_b->setPrev(pair_b->prev);
-
- delete edge_a;
- delete edge_b;
- delete pair_a;
- delete pair_b;
-
- edge = nextBoundary; // If nextBoundary is NULL we have closed the loop.
- sewnCount++;
- }
- else {
- edge = edge->next;
- }
-
- count++;
- } while(edge != NULL && edge != lastBoundarySeen);
-
- nvDebug(" - Sewn %d out of %d.\n", sewnCount, count);
-
- if (lastBoundarySeen != NULL) {
- nvDebugCheck(lastBoundarySeen->face == NULL);
- }
-
- return lastBoundarySeen;
-}
-
-
-// @@ We must always disconnect edge pairs simultaneously.
-void Mesh::disconnect(Edge * edge) {
- nvDebugCheck(edge != NULL);
-
- // Remove from edge list.
- if ((edge->id & 1) == 0) {
- nvDebugCheck(m_edgeArray[edge->id / 2] == edge);
- m_edgeArray[edge->id / 2] = NULL;
- }
-
- // Remove edge from map. @@ Store map key inside edge?
- nvDebugCheck(edge->from() != NULL && edge->to() != NULL);
- bool removed = m_edgeMap.remove(Key(edge->from()->id, edge->to()->id));
- nvDebugCheck(removed == true);
-
- // Disconnect from vertex.
- if (edge->vertex != NULL) {
- if (edge->vertex->edge == edge) {
- if (edge->prev && edge->prev->pair) {
- edge->vertex->edge = edge->prev->pair;
- }
- else if (edge->pair && edge->pair->next) {
- edge->vertex->edge = edge->pair->next;
- }
- else {
- edge->vertex->edge = NULL;
- // @@ Remove disconnected vertex?
- }
- }
- //edge->setVertex(NULL);
- }
-
- // Disconnect from face.
- if (edge->face != NULL) {
- if (edge->face->edge == edge) {
- if (edge->next != NULL && edge->next != edge) {
- edge->face->edge = edge->next;
- }
- else if (edge->prev != NULL && edge->prev != edge) {
- edge->face->edge = edge->prev;
- }
- else {
- edge->face->edge = NULL;
- // @@ Remove disconnected face?
- }
- }
- //edge->setFace(NULL);
- }
-
- // @@ Hack, we don't disconnect from pair, because pair needs us to remove itself from the map.
- // Disconect from pair.
- /*if (edge->pair != NULL) {
- if (edge->pair->pair == edge) {
- edge->pair->setPair(NULL);
- }
- //edge->setPair(NULL);
- }*/
-
- // Disconnect from previous.
- if (edge->prev) {
- if (edge->prev->next == edge) {
- edge->prev->setNext(NULL);
- }
- //edge->setPrev(NULL);
- }
-
- // Disconnect from next.
- if (edge->next) {
- if (edge->next->prev == edge) {
- edge->next->setPrev(NULL);
- }
- //edge->setNext(NULL);
- }
-}
-
-
-void Mesh::remove(Edge * edge) {
- nvDebugCheck(edge != NULL);
-
- disconnect(edge);
-
- delete edge;
-}
-
-void Mesh::remove(Vertex * vertex) {
- nvDebugCheck(vertex != NULL);
-
- // Remove from vertex list.
- m_vertexArray[vertex->id] = NULL;
-
- // Disconnect from colocals.
- vertex->unlinkColocal();
-
- // Disconnect from edges.
- if (vertex->edge != NULL) {
- // @@ Removing a connected vertex is asking for trouble...
- if (vertex->edge->vertex == vertex) {
- // @@ Connect edge to a colocal?
- vertex->edge->vertex = NULL;
- }
-
- vertex->setEdge(NULL);
- }
-
- delete vertex;
-}
-
-void Mesh::remove(Face * face) {
- nvDebugCheck(face != NULL);
-
- // Remove from face list.
- m_faceArray[face->id] = NULL;
-
- // Disconnect from edges.
- if (face->edge != NULL) {
- nvDebugCheck(face->edge->face == face);
-
- face->edge->face = NULL;
-
- face->edge = NULL;
- }
-
- delete face;
-}
-
-
-void Mesh::compactEdges() {
- const uint edgeCount = m_edgeArray.count();
-
- uint c = 0;
- for (uint i = 0; i < edgeCount; i++) {
- if (m_edgeArray[i] != NULL) {
- if (i != c) {
- m_edgeArray[c] = m_edgeArray[i];
- m_edgeArray[c]->id = 2 * c;
- if (m_edgeArray[c]->pair != NULL) {
- m_edgeArray[c]->pair->id = 2 * c + 1;
- }
- }
- c++;
- }
- }
-
- m_edgeArray.resize(c);
-}
-
-
-void Mesh::compactVertices() {
- const uint vertexCount = m_vertexArray.count();
-
- uint c = 0;
- for (uint i = 0; i < vertexCount; i++) {
- if (m_vertexArray[i] != NULL) {
- if (i != c) {
- m_vertexArray[c] = m_vertexArray[i];
- m_vertexArray[c]->id = c;
- }
- c++;
- }
- }
-
- m_vertexArray.resize(c);
-
- // @@ Generate xref array for external attributes.
-}
-
-
-void Mesh::compactFaces() {
- const uint faceCount = m_faceArray.count();
-
- uint c = 0;
- for (uint i = 0; i < faceCount; i++) {
- if (m_faceArray[i] != NULL) {
- if (i != c) {
- m_faceArray[c] = m_faceArray[i];
- m_faceArray[c]->id = c;
- }
- c++;
- }
- }
-
- m_faceArray.resize(c);
-}
-
-
-Vertex * Mesh::splitBoundaryEdge(Edge * edge, float t, const Vector3 & pos) {
-
- /*
- We want to go from this configuration:
-
- + +
- | ^
- edge |<->| pair
- v |
- + +
-
- To this one:
-
- + +
- | ^
- e0 |<->| p0
- v |
- vertex + +
- | ^
- e1 |<->| p1
- v |
- + +
-
- */
-
-
- Edge * pair = edge->pair;
-
- // Make sure boundaries are linked.
- nvDebugCheck(pair != NULL);
-
- // Make sure edge is a boundary edge.
- nvDebugCheck(pair->face == NULL);
-
- // Add new vertex.
- Vertex * vertex = addVertex(pos);
- vertex->nor = lerp(edge->from()->nor, edge->to()->nor, t);
- vertex->tex = lerp(edge->from()->tex, edge->to()->tex, t);
- vertex->col = lerp(edge->from()->col, edge->to()->col, t);
-
- disconnect(edge);
- disconnect(pair);
-
- // Add edges.
- Edge * e0 = addEdge(edge->from()->id, vertex->id);
- Edge * p0 = addEdge(vertex->id, pair->to()->id);
-
- Edge * e1 = addEdge(vertex->id, edge->to()->id);
- Edge * p1 = addEdge(pair->from()->id, vertex->id);
-
- // Link edges.
- e0->setNext(e1);
- p1->setNext(p0);
-
- e0->setPrev(edge->prev);
- e1->setNext(edge->next);
-
- p1->setPrev(pair->prev);
- p0->setNext(pair->next);
-
- nvDebugCheck(e0->next == e1);
- nvDebugCheck(e1->prev == e0);
-
- nvDebugCheck(p1->next == p0);
- nvDebugCheck(p0->prev == p1);
-
- nvDebugCheck(p0->pair == e0);
- nvDebugCheck(e0->pair == p0);
-
- nvDebugCheck(p1->pair == e1);
- nvDebugCheck(e1->pair == p1);
-
- // Link faces.
- e0->face = edge->face;
- e1->face = edge->face;
-
- // Link vertices.
- edge->from()->setEdge(e0);
- vertex->setEdge(e1);
-
- delete edge;
- delete pair;
-
- return vertex;
-}
-
-#if 0
-// Without introducing new vertices.
-void Mesh::splitBoundaryEdge(Edge * edge, Vertex * vertex) {
-
- /*
- We want to go from this configuration:
-
- | | pn
- + +
- | ^
- | |
- edge |<->| pair
- | |
- v |
- + +
- | | pp
-
- To this one:
- \ /
- \ /
- + +
- | ^
- e0 |<->| p0
- v |
- vertex + +
- | ^
- e1 |<->| p1
- v |
- + +
- / \
- / \
- */
-
-
- Edge * pair = edge->pair;
- Edge * pn = pair->next();
- Edge * pp = pair->prev();
-
- // Make sure boundaries are linked.
- nvDebugCheck(pair != NULL);
-
- // Make sure edge is a boundary edge.
- nvDebugCheck(pair->face() == NULL);
-
- nvDebugCheck(edge->isValid());
- nvDebugCheck(pair->isValid());
-
- disconnect(edge);
- disconnect(pair);
-
- // Add edges.
- Edge * e0 = addEdge(edge->from()->id(), vertex->id());
- Edge * e1 = addEdge(vertex->id(), edge->to()->id());
-
- // Link faces.
- e0->setFace(edge->face());
- e1->setFace(edge->face());
-
- // Link pairs.
- Edge * p0 = findEdge(vertex->id(), pair->to()->id());
- if (p0 == NULL) {
- p0 = addEdge(vertex->id(), pair->to()->id());
- pn->setPrev(p0);
- }
- else {
- nvDebugCheck(p0->face() != NULL);
- if (e0->prev() != NULL) {
- pn->setPrev(e0->prev());
- }
- else {
- nvDebugCheck(pn == e0);
- }
- }
-
- Edge * p1 = findEdge(pair->from()->id(), vertex->id());
- if (p1 == NULL) {
- p1 = addEdge(pair->from()->id(), vertex->id());
- pp->setNext(p1);
- }
- else {
- nvDebugCheck(p1->face() != NULL);
- if (e1->next() != NULL) {
- pp->setPrev(e1->next());
- }
- else {
- nvDebugCheck(pp == e1);
- }
- }
-
- // Link edges.
- e0->setNext(e1); // e1->setPrev(e0)
-
- if (p0->face() == p1->face()) { // can be null
- p1->setNext(p0); // p0->setPrev(p1)
- }
- else {
- //if (p1->face() == NULL) p1->setNext(
- }
-
-
- e0->setPrev(edge->prev());
- e1->setNext(edge->next());
-
- nvDebugCheck(e0->pair == p0);
- nvDebugCheck(e1->pair == p1);
- nvDebugCheck(p0->pair == e0);
- nvDebugCheck(p1->pair == e1);
-
- nvDebugCheck(e0->isValid());
- nvDebugCheck(e1->isValid());
- nvDebugCheck(pp->isValid());
- nvDebugCheck(pn->isValid());
-
- nvDebugCheck(e0->pair->isValid());
- nvDebugCheck(e1->pair->isValid());
- nvDebugCheck(pp->pair->isValid());
- nvDebugCheck(pn->pair->isValid());
-
- nvDebugCheck(edge->face->isValid());
-
- if (pn->pair->face != NULL) {
- nvDebugCheck(pn->pair->face->isValid());
- }
-
- if (pp->pair->face() != NULL) {
- nvDebugCheck(pn->pair->face->isValid());
- }
-
- if (p0->face != NULL) {
- nvDebugCheck(p0->face->isValid());
- }
-
- if (p1->face() != NULL) {
- nvDebugCheck(p1->face()->isValid());
- }
-
- nvDebugCheck(isValid()); // Only for extreme debugging.
-
- // Link vertices.
- edge->from()->setEdge(e0);
- vertex->setEdge(p0);
-
- delete edge;
- delete pair;
-}
-#endif
-
-bool Mesh::isValid() const
-{
- // Make sure all edges are valid.
- const uint edgeCount = m_edgeArray.count();
- for (uint e = 0; e < edgeCount; e++) {
- Edge * edge = m_edgeArray[e];
- if (edge != NULL) {
- if (edge->id != 2*e) {
- return false;
- }
- if (!edge->isValid()) {
- return false;
- }
-
- if (edge->pair->id != 2*e+1) {
- return false;
- }
- if (!edge->pair->isValid()) {
- return false;
- }
- }
- }
-
- // @@ Make sure all faces are valid.
-
- // @@ Make sure all vertices are valid.
-
- return true;
-}
diff --git a/thirdparty/thekla_atlas/nvmesh/halfedge/Mesh.h b/thirdparty/thekla_atlas/nvmesh/halfedge/Mesh.h
deleted file mode 100644
index c202c2ef9a..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/halfedge/Mesh.h
+++ /dev/null
@@ -1,274 +0,0 @@
-// This code is in the public domain -- castanyo@yahoo.es
-
-#pragma once
-#ifndef NV_MESH_HALFEDGE_MESH_H
-#define NV_MESH_HALFEDGE_MESH_H
-
-#include "nvmesh/nvmesh.h"
-#include "nvcore/Array.h"
-#include "nvcore/HashMap.h"
-
-/*
-If I were to redo this again, there are a number of things that I would do differently.
-- Edge map is only useful when importing a mesh to guarantee the result is two-manifold. However, when manipulating the mesh
- it's a pain to maintain the map up to date.
-- Edge array only points to the even vertices. There's no good reason for that. The map becomes required to traverse all edges
- or you have to make sure edges are properly paired.
-- Linked boundaries. It's cleaner to assume a NULL pair means a boundary edge. Makes easier to seal boundaries. The only reason
- why we link boundaries is to simplify traversal, but that could be done with two helper functions (nextBoundary, prevBoundary).
-- Minimize the amount of state that needs to be set in a certain way:
- - boundary vertices point to boundary edge.
-- Remove parenthesis! Make some members public.
-- Remove member functions with side effects:
- - e->setNext(n) modifies e->next and n->prev, instead use "link(e, n)", or "e->next = n, n->prev = e"
-*/
-
-
-namespace nv
-{
- class Vector3;
- class TriMesh;
- class QuadTriMesh;
- //template <typename T> struct Hash<Mesh::Key>;
-
- namespace HalfEdge
- {
- class Edge;
- class Face;
- class Vertex;
-
- /// Simple half edge mesh designed for dynamic mesh manipulation.
- class Mesh
- {
- public:
-
- Mesh();
- Mesh(const Mesh * mesh);
- ~Mesh();
-
- void clear();
-
- Vertex * addVertex(const Vector3 & pos);
- //Vertex * addVertex(uint id, const Vector3 & pos);
- //void addVertices(const Mesh * mesh);
-
- void linkColocals();
- void linkColocalsWithCanonicalMap(const Array<uint> & canonicalMap);
- void resetColocalLinks();
-
- Face * addFace();
- Face * addFace(uint v0, uint v1, uint v2);
- Face * addFace(uint v0, uint v1, uint v2, uint v3);
- Face * addFace(const Array<uint> & indexArray);
- Face * addFace(const Array<uint> & indexArray, uint first, uint num);
- //void addFaces(const Mesh * mesh);
-
- // These functions disconnect the given element from the mesh and delete it.
- void disconnect(Edge * edge);
- void disconnectPair(Edge * edge);
- void disconnect(Vertex * vertex);
- void disconnect(Face * face);
-
- void remove(Edge * edge);
- void remove(Vertex * vertex);
- void remove(Face * face);
-
- // Remove holes from arrays and reassign indices.
- void compactEdges();
- void compactVertices();
- void compactFaces();
-
- void triangulate();
-
- void linkBoundary();
-
- bool splitBoundaryEdges(); // Returns true if any split was made.
-
- // Sew the boundary that starts at the given edge, returns one edge that still belongs to boundary, or NULL if boundary closed.
- HalfEdge::Edge * sewBoundary(Edge * startEdge);
-
-
- // Vertices
- uint vertexCount() const { return m_vertexArray.count(); }
- const Vertex * vertexAt(int i) const { return m_vertexArray[i]; }
- Vertex * vertexAt(int i) { return m_vertexArray[i]; }
-
- uint colocalVertexCount() const { return m_colocalVertexCount; }
-
- // Faces
- uint faceCount() const { return m_faceArray.count(); }
- const Face * faceAt(int i) const { return m_faceArray[i]; }
- Face * faceAt(int i) { return m_faceArray[i]; }
-
- // Edges
- uint edgeCount() const { return m_edgeArray.count(); }
- const Edge * edgeAt(int i) const { return m_edgeArray[i]; }
- Edge * edgeAt(int i) { return m_edgeArray[i]; }
-
- class ConstVertexIterator;
-
- class VertexIterator
- {
- friend class ConstVertexIterator;
- public:
- VertexIterator(Mesh * mesh) : m_mesh(mesh), m_current(0) { }
-
- virtual void advance() { m_current++; }
- virtual bool isDone() const { return m_current == m_mesh->vertexCount(); }
- virtual Vertex * current() const { return m_mesh->vertexAt(m_current); }
-
- private:
- HalfEdge::Mesh * m_mesh;
- uint m_current;
- };
- VertexIterator vertices() { return VertexIterator(this); }
-
- class ConstVertexIterator
- {
- public:
- ConstVertexIterator(const Mesh * mesh) : m_mesh(mesh), m_current(0) { }
- ConstVertexIterator(class VertexIterator & it) : m_mesh(it.m_mesh), m_current(it.m_current) { }
-
- virtual void advance() { m_current++; }
- virtual bool isDone() const { return m_current == m_mesh->vertexCount(); }
- virtual const Vertex * current() const { return m_mesh->vertexAt(m_current); }
-
- private:
- const HalfEdge::Mesh * m_mesh;
- uint m_current;
- };
- ConstVertexIterator vertices() const { return ConstVertexIterator(this); }
-
- class ConstFaceIterator;
-
- class FaceIterator
- {
- friend class ConstFaceIterator;
- public:
- FaceIterator(Mesh * mesh) : m_mesh(mesh), m_current(0) { }
-
- virtual void advance() { m_current++; }
- virtual bool isDone() const { return m_current == m_mesh->faceCount(); }
- virtual Face * current() const { return m_mesh->faceAt(m_current); }
-
- private:
- HalfEdge::Mesh * m_mesh;
- uint m_current;
- };
- FaceIterator faces() { return FaceIterator(this); }
-
- class ConstFaceIterator
- {
- public:
- ConstFaceIterator(const Mesh * mesh) : m_mesh(mesh), m_current(0) { }
- ConstFaceIterator(const FaceIterator & it) : m_mesh(it.m_mesh), m_current(it.m_current) { }
-
- virtual void advance() { m_current++; }
- virtual bool isDone() const { return m_current == m_mesh->faceCount(); }
- virtual const Face * current() const { return m_mesh->faceAt(m_current); }
-
- private:
- const HalfEdge::Mesh * m_mesh;
- uint m_current;
- };
- ConstFaceIterator faces() const { return ConstFaceIterator(this); }
-
- class ConstEdgeIterator;
-
- class EdgeIterator
- {
- friend class ConstEdgeIterator;
- public:
- EdgeIterator(Mesh * mesh) : m_mesh(mesh), m_current(0) { }
-
- virtual void advance() { m_current++; }
- virtual bool isDone() const { return m_current == m_mesh->edgeCount(); }
- virtual Edge * current() const { return m_mesh->edgeAt(m_current); }
-
- private:
- HalfEdge::Mesh * m_mesh;
- uint m_current;
- };
- EdgeIterator edges() { return EdgeIterator(this); }
-
- class ConstEdgeIterator
- {
- public:
- ConstEdgeIterator(const Mesh * mesh) : m_mesh(mesh), m_current(0) { }
- ConstEdgeIterator(const EdgeIterator & it) : m_mesh(it.m_mesh), m_current(it.m_current) { }
-
- virtual void advance() { m_current++; }
- virtual bool isDone() const { return m_current == m_mesh->edgeCount(); }
- virtual const Edge * current() const { return m_mesh->edgeAt(m_current); }
-
- private:
- const HalfEdge::Mesh * m_mesh;
- uint m_current;
- };
- ConstEdgeIterator edges() const { return ConstEdgeIterator(this); }
-
- // @@ Add half-edge iterator.
-
-
-
- // Convert to tri mesh.
- TriMesh * toTriMesh() const;
- QuadTriMesh * toQuadTriMesh() const;
-
- bool isValid() const;
-
- public:
-
- // Error status:
- mutable uint errorCount;
- mutable uint errorIndex0;
- mutable uint errorIndex1;
-
- private:
-
- bool canAddFace(const Array<uint> & indexArray, uint first, uint num) const;
- bool canAddEdge(uint i, uint j) const;
- Edge * addEdge(uint i, uint j);
-
- Edge * findEdge(uint i, uint j) const;
-
- void linkBoundaryEdge(Edge * edge);
- Vertex * splitBoundaryEdge(Edge * edge, float t, const Vector3 & pos);
- void splitBoundaryEdge(Edge * edge, Vertex * vertex);
-
- private:
-
- Array<Vertex *> m_vertexArray;
- Array<Edge *> m_edgeArray;
- Array<Face *> m_faceArray;
-
- struct Key {
- Key() {}
- Key(const Key & k) : p0(k.p0), p1(k.p1) {}
- Key(uint v0, uint v1) : p0(v0), p1(v1) {}
- void operator=(const Key & k) { p0 = k.p0; p1 = k.p1; }
- bool operator==(const Key & k) const { return p0 == k.p0 && p1 == k.p1; }
-
- uint p0;
- uint p1;
- };
- friend struct Hash<Mesh::Key>;
-
- HashMap<Key, Edge *> m_edgeMap;
-
- uint m_colocalVertexCount;
-
- };
- /*
- // This is a much better hash than the default and greatly improves performance!
- template <> struct hash<Mesh::Key>
- {
- uint operator()(const Mesh::Key & k) const { return k.p0 + k.p1; }
- };
- */
-
- } // HalfEdge namespace
-
-} // nv namespace
-
-#endif // NV_MESH_HALFEDGE_MESH_H
diff --git a/thirdparty/thekla_atlas/nvmesh/halfedge/Vertex.cpp b/thirdparty/thekla_atlas/nvmesh/halfedge/Vertex.cpp
deleted file mode 100644
index 66dad69f8a..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/halfedge/Vertex.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-// This code is in the public domain -- castano@gmail.com
-
-#include "nvmesh.h" // pch
-
-#include "Vertex.h"
-
-#include "nvmath/Vector.inl"
-
-using namespace nv;
-using namespace HalfEdge;
-
-
-// Set first edge of all colocals.
-void Vertex::setEdge(Edge * e)
-{
- for (VertexIterator it(colocals()); !it.isDone(); it.advance()) {
- it.current()->edge = e;
- }
-}
-
-// Update position of all colocals.
-void Vertex::setPos(const Vector3 & p)
-{
- for (VertexIterator it(colocals()); !it.isDone(); it.advance()) {
- it.current()->pos = p;
- }
-}
-
-
-uint HalfEdge::Vertex::colocalCount() const
-{
- uint count = 0;
- for (ConstVertexIterator it(colocals()); !it.isDone(); it.advance()) { ++count; }
- return count;
-}
-
-uint HalfEdge::Vertex::valence() const
-{
- uint count = 0;
- for (ConstEdgeIterator it(edges()); !it.isDone(); it.advance()) { ++count; }
- return count;
-}
-
-const HalfEdge::Vertex * HalfEdge::Vertex::firstColocal() const
-{
- uint firstId = id;
- const Vertex * vertex = this;
-
- for (ConstVertexIterator it(colocals()); !it.isDone(); it.advance())
- {
- if (it.current()->id < firstId) {
- firstId = vertex->id;
- vertex = it.current();
- }
- }
-
- return vertex;
-}
-
-HalfEdge::Vertex * HalfEdge::Vertex::firstColocal()
-{
- Vertex * vertex = this;
- uint firstId = id;
-
- for (VertexIterator it(colocals()); !it.isDone(); it.advance())
- {
- if (it.current()->id < firstId) {
- firstId = vertex->id;
- vertex = it.current();
- }
- }
-
- return vertex;
-}
-
-bool HalfEdge::Vertex::isFirstColocal() const
-{
- return firstColocal() == this;
-}
-
-bool HalfEdge::Vertex::isColocal(const Vertex * v) const {
- if (this == v) return true;
- if (pos != v->pos) return false;
-
- for (ConstVertexIterator it(colocals()); !it.isDone(); it.advance())
- {
- if (v == it.current()) {
- return true;
- }
- }
-
- return false;
-}
-
diff --git a/thirdparty/thekla_atlas/nvmesh/halfedge/Vertex.h b/thirdparty/thekla_atlas/nvmesh/halfedge/Vertex.h
deleted file mode 100644
index 1c5c8d7141..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/halfedge/Vertex.h
+++ /dev/null
@@ -1,221 +0,0 @@
-// This code is in the public domain -- castanyo@yahoo.es
-
-#pragma once
-#ifndef NV_MESH_HALFEDGE_VERTEX_H
-#define NV_MESH_HALFEDGE_VERTEX_H
-
-#include "nvmesh/halfedge/Edge.h"
-
-namespace nv
-{
- namespace HalfEdge { class Vertex; class Face; class Edge; }
-
- // Half edge vertex.
- class HalfEdge::Vertex
- {
- NV_FORBID_COPY(Vertex);
- public:
-
- uint id;
-
- Edge * edge;
- Vertex * next;
- Vertex * prev;
-
- Vector3 pos;
- Vector3 nor;
- Vector2 tex;
- Vector4 col;
-
-
- Vertex(uint id) : id(id), edge(NULL), pos(0.0f), nor(0.0f), tex(0.0f), col(0.0f) {
- next = this;
- prev = this;
- }
-
-
- void setEdge(Edge * e);
- void setPos(const Vector3 & p);
-
- uint colocalCount() const;
- uint valence() const;
- bool isFirstColocal() const;
- const Vertex * firstColocal() const;
- Vertex * firstColocal();
-
- bool isColocal(const Vertex * v) const;
-
-
- void linkColocal(Vertex * v) {
- next->prev = v;
- v->next = next;
- next = v;
- v->prev = this;
- }
- void unlinkColocal() {
- next->prev = prev;
- prev->next = next;
- next = this;
- prev = this;
- }
-
-
- // @@ Note: This only works if linkBoundary has been called.
- bool isBoundary() const {
- return (edge && !edge->face);
- }
-
-
- // for(EdgeIterator it(iterator()); !it.isDone(); it.advance()) { ... }
- //
- // EdgeIterator it(iterator());
- // while(!it.isDone()) {
- // ...
- // id.advance();
- // }
-
- // Iterator that visits the edges around this vertex in counterclockwise order.
- class EdgeIterator //: public Iterator<Edge *>
- {
- public:
- EdgeIterator(Edge * e) : m_end(NULL), m_current(e) { }
-
- virtual void advance()
- {
- if (m_end == NULL) m_end = m_current;
- m_current = m_current->pair->next;
- //m_current = m_current->prev->pair;
- }
-
- virtual bool isDone() const { return m_end == m_current; }
- virtual Edge * current() const { return m_current; }
- Vertex * vertex() const { return m_current->vertex; }
-
- private:
- Edge * m_end;
- Edge * m_current;
- };
-
- EdgeIterator edges() { return EdgeIterator(edge); }
- EdgeIterator edges(Edge * e) { return EdgeIterator(e); }
-
- // Iterator that visits the edges around this vertex in counterclockwise order.
- class ConstEdgeIterator //: public Iterator<Edge *>
- {
- public:
- ConstEdgeIterator(const Edge * e) : m_end(NULL), m_current(e) { }
- ConstEdgeIterator(EdgeIterator it) : m_end(NULL), m_current(it.current()) { }
-
- virtual void advance()
- {
- if (m_end == NULL) m_end = m_current;
- m_current = m_current->pair->next;
- //m_current = m_current->prev->pair;
- }
-
- virtual bool isDone() const { return m_end == m_current; }
- virtual const Edge * current() const { return m_current; }
- const Vertex * vertex() const { return m_current->to(); }
-
- private:
- const Edge * m_end;
- const Edge * m_current;
- };
-
- ConstEdgeIterator edges() const { return ConstEdgeIterator(edge); }
- ConstEdgeIterator edges(const Edge * e) const { return ConstEdgeIterator(e); }
-
-
- // Iterator that visits the edges around this vertex in counterclockwise order.
- class ReverseEdgeIterator //: public Iterator<Edge *>
- {
- public:
- ReverseEdgeIterator(Edge * e) : m_end(NULL), m_current(e) { }
-
- virtual void advance()
- {
- if (m_end == NULL) m_end = m_current;
- m_current = m_current->prev->pair;
- }
-
- virtual bool isDone() const { return m_end == m_current; }
- virtual Edge * current() const { return m_current; }
- Vertex * vertex() const { return m_current->vertex; }
-
- private:
- Edge * m_end;
- Edge * m_current;
- };
-
- // Iterator that visits the edges around this vertex in counterclockwise order.
- class ReverseConstEdgeIterator //: public Iterator<Edge *>
- {
- public:
- ReverseConstEdgeIterator(const Edge * e) : m_end(NULL), m_current(e) { }
-
- virtual void advance()
- {
- if (m_end == NULL) m_end = m_current;
- m_current = m_current->prev->pair;
- }
-
- virtual bool isDone() const { return m_end == m_current; }
- virtual const Edge * current() const { return m_current; }
- const Vertex * vertex() const { return m_current->to(); }
-
- private:
- const Edge * m_end;
- const Edge * m_current;
- };
-
-
-
- // Iterator that visits all the colocal vertices.
- class VertexIterator //: public Iterator<Edge *>
- {
- public:
- VertexIterator(Vertex * v) : m_end(NULL), m_current(v) { }
-
- virtual void advance()
- {
- if (m_end == NULL) m_end = m_current;
- m_current = m_current->next;
- }
-
- virtual bool isDone() const { return m_end == m_current; }
- virtual Vertex * current() const { return m_current; }
-
- private:
- Vertex * m_end;
- Vertex * m_current;
- };
-
- VertexIterator colocals() { return VertexIterator(this); }
-
- // Iterator that visits all the colocal vertices.
- class ConstVertexIterator //: public Iterator<Edge *>
- {
- public:
- ConstVertexIterator(const Vertex * v) : m_end(NULL), m_current(v) { }
-
- virtual void advance()
- {
- if (m_end == NULL) m_end = m_current;
- m_current = m_current->next;
- }
-
- virtual bool isDone() const { return m_end == m_current; }
- virtual const Vertex * current() const { return m_current; }
-
- private:
- const Vertex * m_end;
- const Vertex * m_current;
- };
-
- ConstVertexIterator colocals() const { return ConstVertexIterator(this); }
-
- };
-
-} // nv namespace
-
-#endif // NV_MESH_HALFEDGE_VERTEX_H
diff --git a/thirdparty/thekla_atlas/nvmesh/nvmesh.cpp b/thirdparty/thekla_atlas/nvmesh/nvmesh.cpp
deleted file mode 100644
index d007eda332..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/nvmesh.cpp
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "nvmesh.h" // pch
-
diff --git a/thirdparty/thekla_atlas/nvmesh/nvmesh.h b/thirdparty/thekla_atlas/nvmesh/nvmesh.h
deleted file mode 100644
index eb6819675d..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/nvmesh.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// This code is in the public domain -- castanyo@yahoo.es
-
-#pragma once
-#ifndef NV_MESH_H
-#define NV_MESH_H
-
-#include "nvcore/nvcore.h"
-
-// Function linkage
-#if NVMESH_SHARED
-#ifdef NVMESH_EXPORTS
-#define NVMESH_API DLL_EXPORT
-#define NVMESH_CLASS DLL_EXPORT_CLASS
-#else
-#define NVMESH_API DLL_IMPORT
-#define NVMESH_CLASS DLL_IMPORT
-#endif
-#else
-#define NVMESH_API
-#define NVMESH_CLASS
-#endif
-
-#if 1 //USE_PRECOMPILED_HEADERS // If using precompiled headers:
-//#include <string.h> // strlen, strcmp, etc.
-//#include "nvcore/StrLib.h"
-//#include "nvcore/StdStream.h"
-//#include "nvcore/Memory.h"
-//#include "nvcore/Debug.h"
-//#include "nvmath/Vector.h"
-//#include "nvcore/Array.h"
-//#include "nvcore/HashMap.h"
-#endif
-
-#endif // NV_MESH_H
diff --git a/thirdparty/thekla_atlas/nvmesh/param/Atlas.cpp b/thirdparty/thekla_atlas/nvmesh/param/Atlas.cpp
deleted file mode 100644
index 98f92cef96..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/param/Atlas.cpp
+++ /dev/null
@@ -1,1519 +0,0 @@
-// Copyright NVIDIA Corporation 2006 -- Ignacio Castano <icastano@nvidia.com>
-
-#include "nvmesh.h" // pch
-
-#include "Atlas.h"
-#include "Util.h"
-#include "AtlasBuilder.h"
-#include "AtlasPacker.h"
-#include "SingleFaceMap.h"
-#include "OrthogonalProjectionMap.h"
-#include "LeastSquaresConformalMap.h"
-#include "ParameterizationQuality.h"
-
-//#include "nvmesh/export/MeshExportOBJ.h"
-
-#include "nvmesh/halfedge/Mesh.h"
-#include "nvmesh/halfedge/Face.h"
-#include "nvmesh/halfedge/Vertex.h"
-
-#include "nvmesh/MeshBuilder.h"
-#include "nvmesh/MeshTopology.h"
-#include "nvmesh/param/Util.h"
-#include "nvmesh/geometry/Measurements.h"
-
-#include "nvmath/Vector.inl"
-#include "nvmath/Fitting.h"
-#include "nvmath/Box.inl"
-#include "nvmath/ProximityGrid.h"
-#include "nvmath/Morton.h"
-
-#include "nvcore/StrLib.h"
-#include "nvcore/Array.inl"
-#include "nvcore/HashMap.inl"
-
-using namespace nv;
-
-
-/// Ctor.
-Atlas::Atlas()
-{
- failed=false;
-}
-
-// Dtor.
-Atlas::~Atlas()
-{
- deleteAll(m_meshChartsArray);
-}
-
-uint Atlas::chartCount() const
-{
- uint count = 0;
- foreach(c, m_meshChartsArray) {
- count += m_meshChartsArray[c]->chartCount();
- }
- return count;
-}
-
-const Chart * Atlas::chartAt(uint i) const
-{
- foreach(c, m_meshChartsArray) {
- uint count = m_meshChartsArray[c]->chartCount();
-
- if (i < count) {
- return m_meshChartsArray[c]->chartAt(i);
- }
-
- i -= count;
- }
-
- return NULL;
-}
-
-Chart * Atlas::chartAt(uint i)
-{
- foreach(c, m_meshChartsArray) {
- uint count = m_meshChartsArray[c]->chartCount();
-
- if (i < count) {
- return m_meshChartsArray[c]->chartAt(i);
- }
-
- i -= count;
- }
-
- return NULL;
-}
-
-// Extract the charts and add to this atlas.
-void Atlas::addMeshCharts(MeshCharts * meshCharts)
-{
- m_meshChartsArray.append(meshCharts);
-}
-
-void Atlas::extractCharts(const HalfEdge::Mesh * mesh)
-{
- MeshCharts * meshCharts = new MeshCharts(mesh);
- meshCharts->extractCharts();
- addMeshCharts(meshCharts);
-}
-
-void Atlas::computeCharts(const HalfEdge::Mesh * mesh, const SegmentationSettings & settings, const Array<uint> & unchartedMaterialArray)
-{
- failed=false;
- MeshCharts * meshCharts = new MeshCharts(mesh);
- meshCharts->computeCharts(settings, unchartedMaterialArray);
- addMeshCharts(meshCharts);
-}
-
-
-
-
-#if 0
-
-/// Compute a seamless texture atlas.
-bool Atlas::computeSeamlessTextureAtlas(bool groupFaces/*= true*/, bool scaleTiles/*= false*/, uint w/*= 1024*/, uint h/* = 1024*/)
-{
- // Implement seamless texture atlas similar to what ZBrush does. See also:
- // "Meshed Atlases for Real-Time Procedural Solid Texturing"
- // http://graphics.cs.uiuc.edu/~jch/papers/rtpst.pdf
-
- // Other methods that we should experiment with:
- //
- // Seamless Texture Atlases:
- // http://www.cs.jhu.edu/~bpurnomo/STA/index.html
- //
- // Rectangular Multi-Chart Geometry Images:
- // http://graphics.cs.uiuc.edu/~jch/papers/rmcgi.pdf
- //
- // Discrete differential geometry also provide a way of constructing
- // seamless quadrangulations as shown in:
- // http://www.geometry.caltech.edu/pubs/TACD06.pdf
- //
-
-#pragma message(NV_FILE_LINE "TODO: Implement seamless texture atlas.")
-
- if (groupFaces)
- {
- // @@ TODO.
- }
- else
- {
- // @@ Create one atlas per face.
- }
-
- if (scaleTiles)
- {
- // @@ TODO
- }
-
- /*
- if (!isQuadMesh(m_mesh)) {
- // Only handle quads for now.
- return false;
- }
-
- // Each face is a chart.
- const uint faceCount = m_mesh->faceCount();
- m_chartArray.resize(faceCount);
-
- for(uint f = 0; f < faceCount; f++) {
- m_chartArray[f].faceArray.clear();
- m_chartArray[f].faceArray.append(f);
- }
-
- // Map each face to a separate square.
-
- // Determine face layout according to width and height.
- float aspect = float(m_width) / float(m_height);
-
- uint i = 2;
- uint total = (m_width / (i+1)) * (m_height / (i+1));
- while(total > faceCount) {
- i *= 2;
- total = (m_width / (i+1)) * (m_height / (i+1));
- }
-
- uint tileSize = i / 2;
-
- int x = 0;
- int y = 0;
-
- m_result = new HalfEdge::Mesh();
-
- // Once you have that it's just matter of traversing the faces.
- for(uint f = 0; f < faceCount; f++) {
- // Compute texture coordinates.
- Vector2 tex[4];
- tex[0] = Vector2(float(x), float(y));
- tex[1] = Vector2(float(x+tileSize), float(y));
- tex[2] = Vector2(float(x+tileSize), float(y+tileSize));
- tex[3] = Vector2(float(x), float(y+tileSize));
-
- Array<uint> indexArray(4);
-
- const HalfEdge::Face * face = m_mesh->faceAt(f);
-
- int i = 0;
- for(HalfEdge::Face::ConstEdgeIterator it(face->edges()); !it.isDone(); it.advance(), i++) {
- const HalfEdge::Edge * edge = it.current();
- const HalfEdge::Vertex * vertex = edge->from();
-
- HalfEdge::Vertex * newVertex = m_result->addVertex(vertex->id(), vertex->pos());
-
- newVertex->setTex(Vector3(tex[i], 0));
- newVertex->setNor(vertex->nor());
-
- indexArray.append(m_result->vertexCount() + 1);
- }
-
- m_result->addFace(indexArray);
-
- // Move to the next tile.
- x += tileSize + 1;
- if (x + tileSize > m_width) {
- x = 0;
- y += tileSize + 1;
- }
- }
- */
-
- return false;
-}
-
-#endif
-
-
-void Atlas::parameterizeCharts()
-{
- foreach(i, m_meshChartsArray) {
- m_meshChartsArray[i]->parameterizeCharts();
- }
-}
-
-
-float Atlas::packCharts(int quality, float texelsPerUnit, bool blockAlign, bool conservative)
-{
- AtlasPacker packer(this);
- packer.packCharts(quality, texelsPerUnit, blockAlign, conservative);
- if (hasFailed())
- return 0;
- return packer.computeAtlasUtilization();
-}
-
-
-
-
-/// Ctor.
-MeshCharts::MeshCharts(const HalfEdge::Mesh * mesh) : m_mesh(mesh)
-{
-}
-
-// Dtor.
-MeshCharts::~MeshCharts()
-{
- deleteAll(m_chartArray);
-}
-
-
-void MeshCharts::extractCharts()
-{
- const uint faceCount = m_mesh->faceCount();
-
- int first = 0;
- Array<uint> queue(faceCount);
-
- BitArray bitFlags(faceCount);
- bitFlags.clearAll();
-
- for (uint f = 0; f < faceCount; f++)
- {
- if (bitFlags.bitAt(f) == false)
- {
- // Start new patch. Reset queue.
- first = 0;
- queue.clear();
- queue.append(f);
- bitFlags.setBitAt(f);
-
- while (first != queue.count())
- {
- const HalfEdge::Face * face = m_mesh->faceAt(queue[first]);
-
- // Visit face neighbors of queue[first]
- for (HalfEdge::Face::ConstEdgeIterator it(face->edges()); !it.isDone(); it.advance())
- {
- const HalfEdge::Edge * edge = it.current();
- nvDebugCheck(edge->pair != NULL);
-
- if (!edge->isBoundary() && /*!edge->isSeam()*/
- //!(edge->from()->tex() != edge->pair()->to()->tex() || edge->to()->tex() != edge->pair()->from()->tex()))
- !(edge->from() != edge->pair->to() || edge->to() != edge->pair->from())) // Preserve existing seams (not just texture seams).
- {
- const HalfEdge::Face * neighborFace = edge->pair->face;
- nvDebugCheck(neighborFace != NULL);
-
- if (bitFlags.bitAt(neighborFace->id) == false)
- {
- queue.append(neighborFace->id);
- bitFlags.setBitAt(neighborFace->id);
- }
- }
- }
-
- first++;
- }
-
- Chart * chart = new Chart();
- chart->build(m_mesh, queue);
-
- m_chartArray.append(chart);
- }
- }
-}
-
-
-/*
-LSCM:
-- identify sharp features using local dihedral angles.
-- identify seed faces farthest from sharp features.
-- grow charts from these seeds.
-
-MCGIM:
-- phase 1: chart growth
- - grow all charts simultaneously using dijkstra search on the dual graph of the mesh.
- - graph edges are weighted based on planarity metric.
- - metric uses distance to global chart normal.
- - terminate when all faces have been assigned.
-- phase 2: seed computation:
- - place new seed of the chart at the most interior face.
- - most interior is evaluated using distance metric only.
-
-- method repeates the two phases, until the location of the seeds does not change.
- - cycles are detected by recording all the previous seeds and chartification terminates.
-
-D-Charts:
-
-- Uniaxial conic metric:
- - N_c = axis of the generalized cone that best fits the chart. (cone can a be cylinder or a plane).
- - omega_c = angle between the face normals and the axis.
- - Fitting error between chart C and tringle t: F(c,t) = (N_c*n_t - cos(omega_c))^2
-
-- Compactness metrics:
- - Roundness:
- - C(c,t) = pi * D(S_c,t)^2 / A_c
- - S_c = chart seed.
- - D(S_c,t) = length of the shortest path inside the chart betwen S_c and t.
- - A_c = chart area.
- - Straightness:
- - P(c,t) = l_out(c,t) / l_in(c,t)
- - l_out(c,t) = lenght of the edges not shared between C and t.
- - l_in(c,t) = lenght of the edges shared between C and t.
-
-- Combined metric:
- - Cost(c,t) = F(c,t)^alpha + C(c,t)^beta + P(c,t)^gamma
- - alpha = 1, beta = 0.7, gamma = 0.5
-
-
-
-
-Our basic approach:
-- Just one iteration of k-means?
-- Avoid dijkstra by greedily growing charts until a threshold is met. Increase threshold and repeat until no faces left.
-- If distortion metric is too high, split chart, add two seeds.
-- If chart size is low, try removing chart.
-
-
-Postprocess:
-- If topology is not disk:
- - Fill holes, if new faces fit proxy.
- - Find best cut, otherwise.
-- After parameterization:
- - If boundary self-intersects:
- - cut chart along the closest two diametral boundary vertices, repeat parametrization.
- - what if the overlap is on an appendix? How do we find that out and cut appropiately?
- - emphasize roundness metrics to prevent those cases.
- - If interior self-overlaps: preserve boundary parameterization and use mean-value map.
-
-*/
-
-
-SegmentationSettings::SegmentationSettings()
-{
- // Charts have no area or boundary limits right now.
- maxChartArea = NV_FLOAT_MAX;
- maxBoundaryLength = NV_FLOAT_MAX;
-
- proxyFitMetricWeight = 1.0f;
- roundnessMetricWeight = 0.1f;
- straightnessMetricWeight = 0.25f;
- normalSeamMetricWeight = 1.0f;
- textureSeamMetricWeight = 0.1f;
-}
-
-
-
-void MeshCharts::computeCharts(const SegmentationSettings & settings, const Array<uint> & unchartedMaterialArray)
-{
- Chart * vertexMap = NULL;
-
- if (unchartedMaterialArray.count() != 0) {
- vertexMap = new Chart();
- vertexMap->buildVertexMap(m_mesh, unchartedMaterialArray);
-
- if (vertexMap->faceCount() == 0) {
- delete vertexMap;
- vertexMap = NULL;
- }
- }
-
-
- AtlasBuilder builder(m_mesh);
-
- if (vertexMap != NULL) {
- // Mark faces that do not need to be charted.
- builder.markUnchartedFaces(vertexMap->faceArray());
-
- m_chartArray.append(vertexMap);
- }
-
- if (builder.facesLeft != 0) {
-
- // Tweak these values:
- const float maxThreshold = 2;
- const uint growFaceCount = 32;
- const uint maxIterations = 4;
-
- builder.settings = settings;
-
- //builder.settings.proxyFitMetricWeight *= 0.75; // relax proxy fit weight during initial seed placement.
- //builder.settings.roundnessMetricWeight = 0;
- //builder.settings.straightnessMetricWeight = 0;
-
- // This seems a reasonable estimate.
- uint maxSeedCount = max(6U, builder.facesLeft);
-
- // Create initial charts greedely.
- nvDebug("### Placing seeds\n");
- builder.placeSeeds(maxThreshold, maxSeedCount);
- nvDebug("### Placed %d seeds (max = %d)\n", builder.chartCount(), maxSeedCount);
-
- builder.updateProxies();
-
- builder.mergeCharts();
-
- #if 1
- nvDebug("### Relocating seeds\n");
- builder.relocateSeeds();
-
- nvDebug("### Reset charts\n");
- builder.resetCharts();
-
- if (vertexMap != NULL) {
- builder.markUnchartedFaces(vertexMap->faceArray());
- }
-
- builder.settings = settings;
-
- nvDebug("### Growing charts\n");
-
- // Restart process growing charts in parallel.
- uint iteration = 0;
- while (true)
- {
- if (!builder.growCharts(maxThreshold, growFaceCount))
- {
- nvDebug("### Can't grow anymore\n");
-
- // If charts cannot grow more: fill holes, merge charts, relocate seeds and start new iteration.
-
- nvDebug("### Filling holes\n");
- builder.fillHoles(maxThreshold);
- nvDebug("### Using %d charts now\n", builder.chartCount());
-
- builder.updateProxies();
-
- nvDebug("### Merging charts\n");
- builder.mergeCharts();
- nvDebug("### Using %d charts now\n", builder.chartCount());
-
- nvDebug("### Reseeding\n");
- if (!builder.relocateSeeds())
- {
- nvDebug("### Cannot relocate seeds anymore\n");
-
- // Done!
- break;
- }
-
- if (iteration == maxIterations)
- {
- nvDebug("### Reached iteration limit\n");
- break;
- }
- iteration++;
-
- nvDebug("### Reset charts\n");
- builder.resetCharts();
-
- if (vertexMap != NULL) {
- builder.markUnchartedFaces(vertexMap->faceArray());
- }
-
- nvDebug("### Growing charts\n");
- }
- };
- #endif
-
- // Make sure no holes are left!
- nvDebugCheck(builder.facesLeft == 0);
-
- const uint chartCount = builder.chartArray.count();
- for (uint i = 0; i < chartCount; i++)
- {
- Chart * chart = new Chart();
- m_chartArray.append(chart);
-
- chart->build(m_mesh, builder.chartFaces(i));
- }
- }
-
-
- const uint chartCount = m_chartArray.count();
-
- // Build face indices.
- m_faceChart.resize(m_mesh->faceCount());
- m_faceIndex.resize(m_mesh->faceCount());
-
- for (uint i = 0; i < chartCount; i++)
- {
- const Chart * chart = m_chartArray[i];
-
- const uint faceCount = chart->faceCount();
- for (uint f = 0; f < faceCount; f++)
- {
- uint idx = chart->faceAt(f);
- m_faceChart[idx] = i;
- m_faceIndex[idx] = f;
- }
- }
-
- // Build an exclusive prefix sum of the chart vertex counts.
- m_chartVertexCountPrefixSum.resize(chartCount);
-
- if (chartCount > 0)
- {
- m_chartVertexCountPrefixSum[0] = 0;
-
- for (uint i = 1; i < chartCount; i++)
- {
- const Chart * chart = m_chartArray[i-1];
- m_chartVertexCountPrefixSum[i] = m_chartVertexCountPrefixSum[i-1] + chart->vertexCount();
- }
-
- m_totalVertexCount = m_chartVertexCountPrefixSum[chartCount - 1] + m_chartArray[chartCount-1]->vertexCount();
- }
- else
- {
- m_totalVertexCount = 0;
- }
-}
-
-
-void MeshCharts::parameterizeCharts()
-{
- ParameterizationQuality globalParameterizationQuality;
-
- // Parameterize the charts.
- uint diskCount = 0;
- const uint chartCount = m_chartArray.count();
- for (uint i = 0; i < chartCount; i++)\
- {
- Chart * chart = m_chartArray[i];
-
- bool isValid = false;
-
- if (chart->isVertexMapped()) {
- continue;
- }
-
- if (chart->isDisk())
- {
- diskCount++;
-
- ParameterizationQuality chartParameterizationQuality;
-
- if (chart->faceCount() == 1) {
- computeSingleFaceMap(chart->unifiedMesh());
-
- chartParameterizationQuality = ParameterizationQuality(chart->unifiedMesh());
- }
- else {
- computeOrthogonalProjectionMap(chart->unifiedMesh());
- ParameterizationQuality orthogonalQuality(chart->unifiedMesh());
-
- computeLeastSquaresConformalMap(chart->unifiedMesh());
- ParameterizationQuality lscmQuality(chart->unifiedMesh());
-
- // If the orthogonal projection produces better results, just use that.
- // @@ It may be dangerous to do this, because isValid() does not detect self-overlaps.
- // @@ Another problem is that with very thin patches with nearly zero parametric area, the results of our metric are not accurate.
- /*if (orthogonalQuality.isValid() && orthogonalQuality.rmsStretchMetric() < lscmQuality.rmsStretchMetric()) {
- computeOrthogonalProjectionMap(chart->unifiedMesh());
- chartParameterizationQuality = orthogonalQuality;
- }
- else*/ {
- chartParameterizationQuality = lscmQuality;
- }
-
- // If conformal map failed,
-
- // @@ Experiment with other parameterization methods.
- //computeCircularBoundaryMap(chart->unifiedMesh());
- //computeConformalMap(chart->unifiedMesh());
- //computeNaturalConformalMap(chart->unifiedMesh());
- //computeGuidanceGradientMap(chart->unifiedMesh());
- }
-
- //ParameterizationQuality chartParameterizationQuality(chart->unifiedMesh());
-
- isValid = chartParameterizationQuality.isValid();
-
- if (!isValid)
- {
- nvDebug("*** Invalid parameterization.\n");
-#if 0
- // Dump mesh to inspect problem:
- static int pieceCount = 0;
-
- StringBuilder fileName;
- fileName.format("invalid_chart_%d.obj", pieceCount++);
- exportMesh(chart->unifiedMesh(), fileName.str());
-#endif
- }
-
- // @@ Check that parameterization quality is above a certain threshold.
-
- // @@ Detect boundary self-intersections.
-
- globalParameterizationQuality += chartParameterizationQuality;
- }
-
- if (!isValid)
- {
- //nvDebugBreak();
- // @@ Run the builder again, but only on this chart.
- //AtlasBuilder builder(chart->chartMesh());
- }
-
- // Transfer parameterization from unified mesh to chart mesh.
- chart->transferParameterization();
-
- }
-
- nvDebug(" Parameterized %d/%d charts.\n", diskCount, chartCount);
- nvDebug(" RMS stretch metric: %f\n", globalParameterizationQuality.rmsStretchMetric());
- nvDebug(" MAX stretch metric: %f\n", globalParameterizationQuality.maxStretchMetric());
- nvDebug(" RMS conformal metric: %f\n", globalParameterizationQuality.rmsConformalMetric());
- nvDebug(" RMS authalic metric: %f\n", globalParameterizationQuality.maxAuthalicMetric());
-}
-
-
-
-Chart::Chart() : m_chartMesh(NULL), m_unifiedMesh(NULL), m_isDisk(false), m_isVertexMapped(false)
-{
-}
-
-void Chart::build(const HalfEdge::Mesh * originalMesh, const Array<uint> & faceArray)
-{
- // Copy face indices.
- m_faceArray = faceArray;
-
- const uint meshVertexCount = originalMesh->vertexCount();
-
- m_chartMesh = new HalfEdge::Mesh();
- m_unifiedMesh = new HalfEdge::Mesh();
-
- Array<uint> chartMeshIndices;
- chartMeshIndices.resize(meshVertexCount, ~0);
-
- Array<uint> unifiedMeshIndices;
- unifiedMeshIndices.resize(meshVertexCount, ~0);
-
- // Add vertices.
- const uint faceCount = faceArray.count();
- for (uint f = 0; f < faceCount; f++)
- {
- const HalfEdge::Face * face = originalMesh->faceAt(faceArray[f]);
- nvDebugCheck(face != NULL);
-
- for(HalfEdge::Face::ConstEdgeIterator it(face->edges()); !it.isDone(); it.advance())
- {
- const HalfEdge::Vertex * vertex = it.current()->vertex;
- const HalfEdge::Vertex * unifiedVertex = vertex->firstColocal();
-
- if (unifiedMeshIndices[unifiedVertex->id] == ~0)
- {
- unifiedMeshIndices[unifiedVertex->id] = m_unifiedMesh->vertexCount();
-
- nvDebugCheck(vertex->pos == unifiedVertex->pos);
- m_unifiedMesh->addVertex(vertex->pos);
- }
-
- if (chartMeshIndices[vertex->id] == ~0)
- {
- chartMeshIndices[vertex->id] = m_chartMesh->vertexCount();
- m_chartToOriginalMap.append(vertex->id);
- m_chartToUnifiedMap.append(unifiedMeshIndices[unifiedVertex->id]);
-
- HalfEdge::Vertex * v = m_chartMesh->addVertex(vertex->pos);
- v->nor = vertex->nor;
- v->tex = vertex->tex;
- }
- }
- }
-
- // This is ignoring the canonical map:
- // - Is it really necessary to link colocals?
-
- m_chartMesh->linkColocals();
- //m_unifiedMesh->linkColocals(); // Not strictly necessary, no colocals in the unified mesh. # Wrong.
-
- // This check is not valid anymore, if the original mesh vertices were linked with a canonical map, then it might have
- // some colocal vertices that were unlinked. So, the unified mesh might have some duplicate vertices, because firstColocal()
- // is not guaranteed to return the same vertex for two colocal vertices.
- //nvCheck(m_chartMesh->colocalVertexCount() == m_unifiedMesh->vertexCount());
-
- // Is that OK? What happens in meshes were that happens? Does anything break? Apparently not...
-
-
-
- Array<uint> faceIndices(7);
-
- // Add faces.
- for (uint f = 0; f < faceCount; f++)
- {
- const HalfEdge::Face * face = originalMesh->faceAt(faceArray[f]);
- nvDebugCheck(face != NULL);
-
- faceIndices.clear();
-
- for(HalfEdge::Face::ConstEdgeIterator it(face->edges()); !it.isDone(); it.advance())
- {
- const HalfEdge::Vertex * vertex = it.current()->vertex;
- nvDebugCheck(vertex != NULL);
-
- faceIndices.append(chartMeshIndices[vertex->id]);
- }
-
- m_chartMesh->addFace(faceIndices);
-
- faceIndices.clear();
-
- for(HalfEdge::Face::ConstEdgeIterator it(face->edges()); !it.isDone(); it.advance())
- {
- const HalfEdge::Vertex * vertex = it.current()->vertex;
- nvDebugCheck(vertex != NULL);
-
- vertex = vertex->firstColocal();
-
- faceIndices.append(unifiedMeshIndices[vertex->id]);
- }
-
- m_unifiedMesh->addFace(faceIndices);
- }
-
- m_chartMesh->linkBoundary();
- m_unifiedMesh->linkBoundary();
-
- //exportMesh(m_unifiedMesh.ptr(), "debug_input.obj");
-
- if (m_unifiedMesh->splitBoundaryEdges()) {
- m_unifiedMesh = unifyVertices(m_unifiedMesh.ptr());
- }
-
- //exportMesh(m_unifiedMesh.ptr(), "debug_split.obj");
-
- // Closing the holes is not always the best solution and does not fix all the problems.
- // We need to do some analysis of the holes and the genus to:
- // - Find cuts that reduce genus.
- // - Find cuts to connect holes.
- // - Use minimal spanning trees or seamster.
- if (!closeHoles()) {
- /*static int pieceCount = 0;
- StringBuilder fileName;
- fileName.format("debug_hole_%d.obj", pieceCount++);
- exportMesh(m_unifiedMesh.ptr(), fileName.str());*/
- }
-
- m_unifiedMesh = triangulate(m_unifiedMesh.ptr());
-
- //exportMesh(m_unifiedMesh.ptr(), "debug_triangulated.obj");
-
-
- // Analyze chart topology.
- MeshTopology topology(m_unifiedMesh.ptr());
- m_isDisk = topology.isDisk();
-
- // This is sometimes failing, when triangulate fails to add a triangle, it generates a hole in the mesh.
- //nvDebugCheck(m_isDisk);
-
- /*if (!m_isDisk) {
- static int pieceCount = 0;
- StringBuilder fileName;
- fileName.format("debug_hole_%d.obj", pieceCount++);
- exportMesh(m_unifiedMesh.ptr(), fileName.str());
- }*/
-
-
-#if 0
- if (!m_isDisk) {
- nvDebugBreak();
-
- static int pieceCount = 0;
-
- StringBuilder fileName;
- fileName.format("debug_nodisk_%d.obj", pieceCount++);
- exportMesh(m_chartMesh.ptr(), fileName.str());
- }
-#endif
-
-}
-
-
-void Chart::buildVertexMap(const HalfEdge::Mesh * originalMesh, const Array<uint> & unchartedMaterialArray)
-{
- nvCheck(m_chartMesh == NULL && m_unifiedMesh == NULL);
-
- m_isVertexMapped = true;
-
- // Build face indices.
- m_faceArray.clear();
-
- const uint meshFaceCount = originalMesh->faceCount();
- for (uint f = 0; f < meshFaceCount; f++) {
- const HalfEdge::Face * face = originalMesh->faceAt(f);
-
- if (unchartedMaterialArray.contains(face->material)) {
- m_faceArray.append(f);
- }
- }
-
- const uint faceCount = m_faceArray.count();
-
- if (faceCount == 0) {
- return;
- }
-
-
- // @@ The chartMesh construction is basically the same as with regular charts, don't duplicate!
-
- const uint meshVertexCount = originalMesh->vertexCount();
-
- m_chartMesh = new HalfEdge::Mesh();
-
- Array<uint> chartMeshIndices;
- chartMeshIndices.resize(meshVertexCount, ~0);
-
- // Vertex map mesh only has disconnected vertices.
- for (uint f = 0; f < faceCount; f++)
- {
- const HalfEdge::Face * face = originalMesh->faceAt(m_faceArray[f]);
- nvDebugCheck(face != NULL);
-
- for (HalfEdge::Face::ConstEdgeIterator it(face->edges()); !it.isDone(); it.advance())
- {
- const HalfEdge::Vertex * vertex = it.current()->vertex;
-
- if (chartMeshIndices[vertex->id] == ~0)
- {
- chartMeshIndices[vertex->id] = m_chartMesh->vertexCount();
- m_chartToOriginalMap.append(vertex->id);
-
- HalfEdge::Vertex * v = m_chartMesh->addVertex(vertex->pos);
- v->nor = vertex->nor;
- v->tex = vertex->tex; // @@ Not necessary.
- }
- }
- }
-
- // @@ Link colocals using the original mesh canonical map? Build canonical map on the fly? Do we need to link colocals at all for this?
- //m_chartMesh->linkColocals();
-
- Array<uint> faceIndices(7);
-
- // Add faces.
- for (uint f = 0; f < faceCount; f++)
- {
- const HalfEdge::Face * face = originalMesh->faceAt(m_faceArray[f]);
- nvDebugCheck(face != NULL);
-
- faceIndices.clear();
-
- for(HalfEdge::Face::ConstEdgeIterator it(face->edges()); !it.isDone(); it.advance())
- {
- const HalfEdge::Vertex * vertex = it.current()->vertex;
- nvDebugCheck(vertex != NULL);
- nvDebugCheck(chartMeshIndices[vertex->id] != ~0);
-
- faceIndices.append(chartMeshIndices[vertex->id]);
- }
-
- HalfEdge::Face * new_face = m_chartMesh->addFace(faceIndices);
- nvDebugCheck(new_face != NULL);
- }
-
- m_chartMesh->linkBoundary();
-
-
- const uint chartVertexCount = m_chartMesh->vertexCount();
-
- Box bounds;
- bounds.clearBounds();
-
- for (uint i = 0; i < chartVertexCount; i++) {
- HalfEdge::Vertex * vertex = m_chartMesh->vertexAt(i);
- bounds.addPointToBounds(vertex->pos);
- }
-
- ProximityGrid grid;
- grid.init(bounds, chartVertexCount);
-
- for (uint i = 0; i < chartVertexCount; i++) {
- HalfEdge::Vertex * vertex = m_chartMesh->vertexAt(i);
- grid.add(vertex->pos, i);
- }
-
-
-#if 0
- // Arrange vertices in a rectangle.
- vertexMapWidth = ftoi_ceil(sqrtf(float(chartVertexCount)));
- vertexMapHeight = (chartVertexCount + vertexMapWidth - 1) / vertexMapWidth;
- nvDebugCheck(vertexMapWidth >= vertexMapHeight);
-
- int x = 0, y = 0;
- for (uint i = 0; i < chartVertexCount; i++) {
- HalfEdge::Vertex * vertex = m_chartMesh->vertexAt(i);
-
- vertex->tex.x = float(x);
- vertex->tex.y = float(y);
-
- x++;
- if (x == vertexMapWidth) {
- x = 0;
- y++;
- nvCheck(y < vertexMapHeight);
- }
- }
-
-#elif 0
- // Arrange vertices in a rectangle, traversing grid in 3D morton order and laying them down in 2D morton order.
- vertexMapWidth = ftoi_ceil(sqrtf(float(chartVertexCount)));
- vertexMapHeight = (chartVertexCount + vertexMapWidth - 1) / vertexMapWidth;
- nvDebugCheck(vertexMapWidth >= vertexMapHeight);
-
- int n = 0;
- uint32 texelCode = 0;
-
- uint cellsVisited = 0;
-
- const uint32 cellCodeCount = grid.mortonCount();
- for (uint32 cellCode = 0; cellCode < cellCodeCount; cellCode++) {
- int cell = grid.mortonIndex(cellCode);
- if (cell < 0) continue;
-
- cellsVisited++;
-
- const Array<uint> & indexArray = grid.cellArray[cell].indexArray;
-
- foreach(i, indexArray) {
- uint idx = indexArray[i];
- HalfEdge::Vertex * vertex = m_chartMesh->vertexAt(idx);
-
- //vertex->tex.x = float(n % rectangleWidth) + 0.5f;
- //vertex->tex.y = float(n / rectangleWidth) + 0.5f;
-
- // Lay down the points in z order too.
- uint x, y;
- do {
- x = decodeMorton2X(texelCode);
- y = decodeMorton2Y(texelCode);
- texelCode++;
- } while (x >= U32(vertexMapWidth) || y >= U32(vertexMapHeight));
-
- vertex->tex.x = float(x);
- vertex->tex.y = float(y);
-
- n++;
- }
- }
-
- nvDebugCheck(cellsVisited == grid.cellArray.count());
- nvDebugCheck(n == chartVertexCount);
-
-#else
-
- uint texelCount = 0;
-
- const float positionThreshold = 0.01f;
- const float normalThreshold = 0.01f;
-
- uint verticesVisited = 0;
- uint cellsVisited = 0;
-
- Array<int> vertexIndexArray;
- vertexIndexArray.resize(chartVertexCount, -1); // Init all indices to -1.
-
- // Traverse vertices in morton order. @@ It may be more interesting to sort them based on orientation.
- const uint cellCodeCount = grid.mortonCount();
- for (uint cellCode = 0; cellCode < cellCodeCount; cellCode++) {
- int cell = grid.mortonIndex(cellCode);
- if (cell < 0) continue;
-
- cellsVisited++;
-
- const Array<uint> & indexArray = grid.cellArray[cell].indexArray;
-
- foreach(i, indexArray) {
- uint idx = indexArray[i];
- HalfEdge::Vertex * vertex = m_chartMesh->vertexAt(idx);
-
- nvDebugCheck(vertexIndexArray[idx] == -1);
-
- Array<uint> neighbors;
- grid.gather(vertex->pos, positionThreshold, /*ref*/neighbors);
-
- // Compare against all nearby vertices, cluster greedily.
- foreach(j, neighbors) {
- uint otherIdx = neighbors[j];
-
- if (vertexIndexArray[otherIdx] != -1) {
- HalfEdge::Vertex * otherVertex = m_chartMesh->vertexAt(otherIdx);
-
- if (distance(vertex->pos, otherVertex->pos) < positionThreshold &&
- distance(vertex->nor, otherVertex->nor) < normalThreshold)
- {
- vertexIndexArray[idx] = vertexIndexArray[otherIdx];
- break;
- }
- }
- }
-
- // If index not assigned, assign new one.
- if (vertexIndexArray[idx] == -1) {
- vertexIndexArray[idx] = texelCount++;
- }
-
- verticesVisited++;
- }
- }
-
- nvDebugCheck(cellsVisited == grid.cellArray.count());
- nvDebugCheck(verticesVisited == chartVertexCount);
-
- vertexMapWidth = ftoi_ceil(sqrtf(float(texelCount)));
- vertexMapWidth = (vertexMapWidth + 3) & ~3; // Width aligned to 4.
- vertexMapHeight = vertexMapWidth == 0 ? 0 : (texelCount + vertexMapWidth - 1) / vertexMapWidth;
- //vertexMapHeight = (vertexMapHeight + 3) & ~3; // Height aligned to 4.
- nvDebugCheck(vertexMapWidth >= vertexMapHeight);
-
- nvDebug("Reduced vertex count from %d to %d.\n", chartVertexCount, texelCount);
-
-#if 0
- // This lays down the clustered vertices linearly.
- for (uint i = 0; i < chartVertexCount; i++) {
- HalfEdge::Vertex * vertex = m_chartMesh->vertexAt(i);
-
- int idx = vertexIndexArray[i];
-
- vertex->tex.x = float(idx % vertexMapWidth);
- vertex->tex.y = float(idx / vertexMapWidth);
- }
-#else
- // Lay down the clustered vertices in morton order.
-
- Array<uint> texelCodes;
- texelCodes.resize(texelCount);
-
- // For each texel, assign one morton code.
- uint texelCode = 0;
- for (uint i = 0; i < texelCount; i++) {
- uint x, y;
- do {
- x = decodeMorton2X(texelCode);
- y = decodeMorton2Y(texelCode);
- texelCode++;
- } while (x >= U32(vertexMapWidth) || y >= U32(vertexMapHeight));
-
- texelCodes[i] = texelCode - 1;
- }
-
- for (uint i = 0; i < chartVertexCount; i++) {
- HalfEdge::Vertex * vertex = m_chartMesh->vertexAt(i);
-
- int idx = vertexIndexArray[i];
- if (idx != -1) {
- uint texelCode = texelCodes[idx];
- uint x = decodeMorton2X(texelCode);
- uint y = decodeMorton2Y(texelCode);
-
- vertex->tex.x = float(x);
- vertex->tex.y = float(y);
- }
- }
-
-#endif
-
-#endif
-
-}
-
-
-
-static void getBoundaryEdges(HalfEdge::Mesh * mesh, Array<HalfEdge::Edge *> & boundaryEdges)
-{
- nvDebugCheck(mesh != NULL);
-
- const uint edgeCount = mesh->edgeCount();
-
- BitArray bitFlags(edgeCount);
- bitFlags.clearAll();
-
- boundaryEdges.clear();
-
- // Search for boundary edges. Mark all the edges that belong to the same boundary.
- for (uint e = 0; e < edgeCount; e++)
- {
- HalfEdge::Edge * startEdge = mesh->edgeAt(e);
-
- if (startEdge != NULL && startEdge->isBoundary() && bitFlags.bitAt(e) == false)
- {
- nvDebugCheck(startEdge->face != NULL);
- nvDebugCheck(startEdge->pair->face == NULL);
-
- startEdge = startEdge->pair;
-
- const HalfEdge::Edge * edge = startEdge;
- do {
- nvDebugCheck(edge->face == NULL);
- nvDebugCheck(bitFlags.bitAt(edge->id/2) == false);
-
- bitFlags.setBitAt(edge->id / 2);
- edge = edge->next;
- } while(startEdge != edge);
-
- boundaryEdges.append(startEdge);
- }
- }
-}
-
-
-bool Chart::closeLoop(uint start, const Array<HalfEdge::Edge *> & loop)
-{
- const uint vertexCount = loop.count() - start;
-
- nvDebugCheck(vertexCount >= 3);
- if (vertexCount < 3) return false;
-
- nvDebugCheck(loop[start]->vertex->isColocal(loop[start+vertexCount-1]->to()));
-
- // If the hole is planar, then we add a single face that will be properly triangulated later.
- // If the hole is not planar, we add a triangle fan with a vertex at the hole centroid.
- // This is still a bit of a hack. There surely are better hole filling algorithms out there.
-
- Array<Vector3> points;
- points.resize(vertexCount);
- for (uint i = 0; i < vertexCount; i++) {
- points[i] = loop[start+i]->vertex->pos;
- }
-
- bool isPlanar = Fit::isPlanar(vertexCount, points.buffer());
-
- if (isPlanar) {
- // Add face and connect edges.
- HalfEdge::Face * face = m_unifiedMesh->addFace();
- for (uint i = 0; i < vertexCount; i++) {
- HalfEdge::Edge * edge = loop[start + i];
-
- edge->face = face;
- edge->setNext(loop[start + (i + 1) % vertexCount]);
- }
- face->edge = loop[start];
-
- nvDebugCheck(face->isValid());
- }
- else {
- // If the polygon is not planar, we just cross our fingers, and hope this will work:
-
- // Compute boundary centroid:
- Vector3 centroidPos(0);
-
- for (uint i = 0; i < vertexCount; i++) {
- centroidPos += points[i];
- }
-
- centroidPos *= (1.0f / vertexCount);
-
- HalfEdge::Vertex * centroid = m_unifiedMesh->addVertex(centroidPos);
-
- // Add one pair of edges for each boundary vertex.
- for (uint j = vertexCount-1, i = 0; i < vertexCount; j = i++) {
- HalfEdge::Face * face = m_unifiedMesh->addFace(centroid->id, loop[start+j]->vertex->id, loop[start+i]->vertex->id);
- nvDebugCheck(face != NULL);
- }
- }
-
- return true;
-}
-
-
-bool Chart::closeHoles()
-{
- nvDebugCheck(!m_isVertexMapped);
-
- Array<HalfEdge::Edge *> boundaryEdges;
- getBoundaryEdges(m_unifiedMesh.ptr(), boundaryEdges);
-
- uint boundaryCount = boundaryEdges.count();
- if (boundaryCount <= 1)
- {
- // Nothing to close.
- return true;
- }
-
- // Compute lengths and areas.
- Array<float> boundaryLengths;
- //Array<Vector3> boundaryCentroids;
-
- for (uint i = 0; i < boundaryCount; i++)
- {
- const HalfEdge::Edge * startEdge = boundaryEdges[i];
- nvCheck(startEdge->face == NULL);
-
- //float boundaryEdgeCount = 0;
- float boundaryLength = 0.0f;
- //Vector3 boundaryCentroid(zero);
-
- const HalfEdge::Edge * edge = startEdge;
- do {
- Vector3 t0 = edge->from()->pos;
- Vector3 t1 = edge->to()->pos;
-
- //boundaryEdgeCount++;
- boundaryLength += length(t1 - t0);
- //boundaryCentroid += edge->vertex()->pos;
-
- edge = edge->next;
- } while(edge != startEdge);
-
- boundaryLengths.append(boundaryLength);
- //boundaryCentroids.append(boundaryCentroid / boundaryEdgeCount);
- }
-
-
- // Find disk boundary.
- uint diskBoundary = 0;
- float maxLength = boundaryLengths[0];
-
- for (uint i = 1; i < boundaryCount; i++)
- {
- if (boundaryLengths[i] > maxLength)
- {
- maxLength = boundaryLengths[i];
- diskBoundary = i;
- }
- }
-
-
- // Sew holes.
- /*for (uint i = 0; i < boundaryCount; i++)
- {
- if (diskBoundary == i)
- {
- // Skip disk boundary.
- continue;
- }
-
- HalfEdge::Edge * startEdge = boundaryEdges[i];
- nvCheck(startEdge->face() == NULL);
-
- boundaryEdges[i] = m_unifiedMesh->sewBoundary(startEdge);
- }
-
- exportMesh(m_unifiedMesh.ptr(), "debug_sewn.obj");*/
-
- //bool hasNewHoles = false;
-
- // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- // @@ Close loop is wrong, after closing a loop, we do not only have to add the face, but make sure that every edge in he loop is pointing to the right place.
-
- // Close holes.
- for (uint i = 0; i < boundaryCount; i++)
- {
- if (diskBoundary == i)
- {
- // Skip disk boundary.
- continue;
- }
-
- HalfEdge::Edge * startEdge = boundaryEdges[i];
- nvDebugCheck(startEdge != NULL);
- nvDebugCheck(startEdge->face == NULL);
-
-#if 1
- Array<HalfEdge::Vertex *> vertexLoop;
- Array<HalfEdge::Edge *> edgeLoop;
-
- HalfEdge::Edge * edge = startEdge;
- do {
- HalfEdge::Vertex * vertex = edge->next->vertex; // edge->to()
-
- uint i;
- for (i = 0; i < vertexLoop.count(); i++) {
- if (vertex->isColocal(vertexLoop[i])) {
- break;
- }
- }
-
- bool isCrossing = (i != vertexLoop.count());
-
- if (isCrossing) {
-
- HalfEdge::Edge * prev = edgeLoop[i]; // Previous edge before the loop.
- HalfEdge::Edge * next = edge->next; // Next edge after the loop.
-
- nvDebugCheck(prev->to()->isColocal(next->from()));
-
- // Close loop.
- edgeLoop.append(edge);
- closeLoop(i+1, edgeLoop);
-
- // Link boundary loop.
- prev->setNext(next);
- vertex->setEdge(next);
-
- // Start over again.
- vertexLoop.clear();
- edgeLoop.clear();
-
- edge = startEdge;
- vertex = edge->to();
- }
-
- vertexLoop.append(vertex);
- edgeLoop.append(edge);
-
- edge = edge->next;
- } while(edge != startEdge);
-
- closeLoop(0, edgeLoop);
-#endif
-
- /*
-
- // Add face and connect boundary edges.
- HalfEdge::Face * face = m_unifiedMesh->addFace();
- face->setEdge(startEdge);
-
- HalfEdge::Edge * edge = startEdge;
- do {
- edge->setFace(face);
-
- edge = edge->next();
- } while(edge != startEdge);
-
- */
-
-
- /*
- uint edgeCount = 0;
- HalfEdge::Edge * edge = startEdge;
- do {
- edgeCount++;
- edge = edge->next();
- } while(edge != startEdge);
-
-
-
- // Count edges in this boundary.
- uint edgeCount = 0;
- HalfEdge::Edge * edge = startEdge;
- do {
- edgeCount++;
- edge = edge->next();
- } while(edge != startEdge);
-
- // Trivial hole, fill with one triangle. This actually works for all convex boundaries with non colinear vertices.
- if (edgeCount == 3) {
- // Add face and connect boundary edges.
- HalfEdge::Face * face = m_unifiedMesh->addFace();
- face->setEdge(startEdge);
-
- edge = startEdge;
- do {
- edge->setFace(face);
-
- edge = edge->next();
- } while(edge != startEdge);
-
- // @@ Implement the above using addFace, it should now work with existing edges, as long as their face pointers is zero.
-
- }
- else {
- // Ideally we should:
- // - compute best fit plane of boundary vertices.
- // - project boundary polygon onto plane.
- // - triangulate boundary polygon.
- // - add faces of the resulting triangulation.
-
- // I don't have a good triangulator available. A more simple solution that works in more (but not all) cases:
- // - compute boundary centroid.
- // - add vertex centroid.
- // - connect centroid vertex with boundary vertices.
- // - connect radial edges with boundary edges.
-
- // This should work for non-convex boundaries with colinear vertices as long as the kernel of the polygon is not empty.
-
- // Compute boundary centroid:
- Vector3 centroid_pos(0);
- Vector2 centroid_tex(0);
-
- HalfEdge::Edge * edge = startEdge;
- do {
- centroid_pos += edge->vertex()->pos;
- centroid_tex += edge->vertex()->tex;
- edge = edge->next();
- } while(edge != startEdge);
-
- centroid_pos *= (1.0f / edgeCount);
- centroid_tex *= (1.0f / edgeCount);
-
- HalfEdge::Vertex * centroid = m_unifiedMesh->addVertex(centroid_pos);
- centroid->tex = centroid_tex;
-
- // Add one pair of edges for each boundary vertex.
- edge = startEdge;
- do {
- HalfEdge::Edge * next = edge->next();
-
- nvCheck(edge->face() == NULL);
- HalfEdge::Face * face = m_unifiedMesh->addFace(centroid->id(), edge->from()->id(), edge->to()->id());
-
- if (face != NULL) {
- nvCheck(edge->face() == face);
- }
- else {
- hasNewHoles = true;
- }
-
- edge = next;
- } while(edge != startEdge);
- }
- */
- }
-
- /*nvDebugCheck(!hasNewHoles);
-
- if (hasNewHoles) {
- // Link boundary again, in case closeHoles created new holes!
- m_unifiedMesh->linkBoundary();
- }*/
-
- // Because some algorithms do not expect sparse edge buffers.
- //m_unifiedMesh->compactEdges();
-
- // In case we messed up:
- //m_unifiedMesh->linkBoundary();
-
- getBoundaryEdges(m_unifiedMesh.ptr(), boundaryEdges);
-
- boundaryCount = boundaryEdges.count();
- nvDebugCheck(boundaryCount == 1);
-
- //exportMesh(m_unifiedMesh.ptr(), "debug_hole_filled.obj");
-
- return boundaryCount == 1;
-}
-
-
-// Transfer parameterization from unified mesh to chart mesh.
-void Chart::transferParameterization() {
- nvDebugCheck(!m_isVertexMapped);
-
- uint vertexCount = m_chartMesh->vertexCount();
- for (uint v = 0; v < vertexCount; v++) {
- HalfEdge::Vertex * vertex = m_chartMesh->vertexAt(v);
- HalfEdge::Vertex * unifiedVertex = m_unifiedMesh->vertexAt(mapChartVertexToUnifiedVertex(v));
- vertex->tex = unifiedVertex->tex;
- }
-}
-
-float Chart::computeSurfaceArea() const {
- return nv::computeSurfaceArea(m_chartMesh.ptr()) * scale;
-}
-
-float Chart::computeParametricArea() const {
- // This only makes sense in parameterized meshes.
- nvDebugCheck(m_isDisk);
- nvDebugCheck(!m_isVertexMapped);
-
- return nv::computeParametricArea(m_chartMesh.ptr());
-}
-
-Vector2 Chart::computeParametricBounds() const {
- // This only makes sense in parameterized meshes.
- nvDebugCheck(m_isDisk);
- nvDebugCheck(!m_isVertexMapped);
-
- Box bounds;
- bounds.clearBounds();
-
- uint vertexCount = m_chartMesh->vertexCount();
- for (uint v = 0; v < vertexCount; v++) {
- HalfEdge::Vertex * vertex = m_chartMesh->vertexAt(v);
- bounds.addPointToBounds(Vector3(vertex->tex, 0));
- }
-
- return bounds.extents().xy();
-}
diff --git a/thirdparty/thekla_atlas/nvmesh/param/Atlas.h b/thirdparty/thekla_atlas/nvmesh/param/Atlas.h
deleted file mode 100644
index 41cfaea9cb..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/param/Atlas.h
+++ /dev/null
@@ -1,186 +0,0 @@
-// Copyright NVIDIA Corporation 2006 -- Ignacio Castano <icastano@nvidia.com>
-
-#pragma once
-#ifndef NV_MESH_ATLAS_H
-#define NV_MESH_ATLAS_H
-
-#include "nvcore/Array.h"
-#include "nvcore/Ptr.h"
-#include "nvmath/Vector.h"
-#include "nvmesh/nvmesh.h"
-#include "nvmesh/halfedge/Mesh.h"
-
-
-namespace nv
-{
- namespace HalfEdge { class Mesh; }
-
- class Chart;
- class MeshCharts;
- class VertexMap;
-
- struct SegmentationSettings
- {
- SegmentationSettings();
-
- float maxChartArea;
- float maxBoundaryLength;
-
- float proxyFitMetricWeight;
- float roundnessMetricWeight;
- float straightnessMetricWeight;
- float normalSeamMetricWeight;
- float textureSeamMetricWeight;
- };
-
-
- /// An atlas is a set of charts.
- class Atlas
- {
- public:
-
- Atlas();
- ~Atlas();
-
- uint meshCount() const { return m_meshChartsArray.count(); }
- const MeshCharts * meshAt(uint i) const { return m_meshChartsArray[i]; }
- MeshCharts * meshAt(uint i) { return m_meshChartsArray[i]; }
-
- uint chartCount() const;
- const Chart * chartAt(uint i) const;
- Chart * chartAt(uint i);
-
- // Add mesh charts and takes ownership.
- void addMeshCharts(MeshCharts * meshCharts);
-
- void extractCharts(const HalfEdge::Mesh * mesh);
- void computeCharts(const HalfEdge::Mesh * mesh, const SegmentationSettings & settings, const Array<uint> & unchartedMaterialArray);
-
-
- // Compute a trivial seamless texture similar to ZBrush.
- //bool computeSeamlessTextureAtlas(bool groupFaces = true, bool scaleTiles = false, uint w = 1024, uint h = 1024);
-
- void parameterizeCharts();
-
- // Pack charts in the smallest possible rectangle.
- float packCharts(int quality, float texelArea, bool blockAlign, bool conservative);
- void setFailed() { failed = true; }
- bool hasFailed() const { return failed; }
-
- private:
-
- bool failed;
- Array<MeshCharts *> m_meshChartsArray;
-
- };
-
-
- // Set of charts corresponding to a single mesh.
- class MeshCharts
- {
- public:
- MeshCharts(const HalfEdge::Mesh * mesh);
- ~MeshCharts();
-
- uint chartCount() const { return m_chartArray.count(); }
- uint vertexCount () const { return m_totalVertexCount; }
-
- const Chart * chartAt(uint i) const { return m_chartArray[i]; }
- Chart * chartAt(uint i) { return m_chartArray[i]; }
-
- void computeVertexMap(const Array<uint> & unchartedMaterialArray);
-
- // Extract the charts of the input mesh.
- void extractCharts();
-
- // Compute charts using a simple segmentation algorithm.
- void computeCharts(const SegmentationSettings & settings, const Array<uint> & unchartedMaterialArray);
-
- void parameterizeCharts();
-
- uint faceChartAt(uint i) const { return m_faceChart[i]; }
- uint faceIndexWithinChartAt(uint i) const { return m_faceIndex[i]; }
-
- uint vertexCountBeforeChartAt(uint i) const { return m_chartVertexCountPrefixSum[i]; }
-
- private:
-
- const HalfEdge::Mesh * m_mesh;
-
- Array<Chart *> m_chartArray;
-
- Array<uint> m_chartVertexCountPrefixSum;
- uint m_totalVertexCount;
-
- Array<uint> m_faceChart; // the chart of every face of the input mesh.
- Array<uint> m_faceIndex; // the index within the chart for every face of the input mesh.
- };
-
-
- /// A chart is a connected set of faces with a certain topology (usually a disk).
- class Chart
- {
- public:
-
- Chart();
-
- void build(const HalfEdge::Mesh * originalMesh, const Array<uint> & faceArray);
- void buildVertexMap(const HalfEdge::Mesh * originalMesh, const Array<uint> & unchartedMaterialArray);
-
- bool closeHoles();
-
- bool isDisk() const { return m_isDisk; }
- bool isVertexMapped() const { return m_isVertexMapped; }
-
- uint vertexCount() const { return m_chartMesh->vertexCount(); }
- uint colocalVertexCount() const { return m_unifiedMesh->vertexCount(); }
-
- uint faceCount() const { return m_faceArray.count(); }
- uint faceAt(uint i) const { return m_faceArray[i]; }
-
- const HalfEdge::Mesh * chartMesh() const { return m_chartMesh.ptr(); }
- HalfEdge::Mesh * chartMesh() { return m_chartMesh.ptr(); }
- const HalfEdge::Mesh * unifiedMesh() const { return m_unifiedMesh.ptr(); }
- HalfEdge::Mesh * unifiedMesh() { return m_unifiedMesh.ptr(); }
-
- //uint vertexIndex(uint i) const { return m_vertexIndexArray[i]; }
-
- uint mapChartVertexToOriginalVertex(uint i) const { return m_chartToOriginalMap[i]; }
- uint mapChartVertexToUnifiedVertex(uint i) const { return m_chartToUnifiedMap[i]; }
-
- const Array<uint> & faceArray() const { return m_faceArray; }
-
- void transferParameterization();
-
- float computeSurfaceArea() const;
- float computeParametricArea() const;
- Vector2 computeParametricBounds() const;
-
-
- float scale = 1.0f;
- uint vertexMapWidth;
- uint vertexMapHeight;
-
- private:
-
- bool closeLoop(uint start, const Array<HalfEdge::Edge *> & loop);
-
- // Chart mesh.
- AutoPtr<HalfEdge::Mesh> m_chartMesh;
- AutoPtr<HalfEdge::Mesh> m_unifiedMesh;
-
- bool m_isDisk;
- bool m_isVertexMapped;
-
- // List of faces of the original mesh that belong to this chart.
- Array<uint> m_faceArray;
-
- // Map vertices of the chart mesh to vertices of the original mesh.
- Array<uint> m_chartToOriginalMap;
-
- Array<uint> m_chartToUnifiedMap;
- };
-
-} // nv namespace
-
-#endif // NV_MESH_ATLAS_H
diff --git a/thirdparty/thekla_atlas/nvmesh/param/AtlasBuilder.cpp b/thirdparty/thekla_atlas/nvmesh/param/AtlasBuilder.cpp
deleted file mode 100644
index bd2140c2f3..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/param/AtlasBuilder.cpp
+++ /dev/null
@@ -1,1320 +0,0 @@
-// This code is in the public domain -- castano@gmail.com
-
-#include "nvmesh.h" // pch
-
-#include "AtlasBuilder.h"
-#include "Util.h"
-
-#include "nvmesh/halfedge/Mesh.h"
-#include "nvmesh/halfedge/Face.h"
-#include "nvmesh/halfedge/Vertex.h"
-
-#include "nvmath/Matrix.inl"
-#include "nvmath/Vector.inl"
-
-//#include "nvcore/IntroSort.h"
-#include "nvcore/Array.inl"
-
-#include <algorithm> // std::sort
-
-#include <float.h> // FLT_MAX
-#include <limits.h> // UINT_MAX
-
-using namespace nv;
-
-namespace
-{
-
- // Dummy implementation of a priority queue using sort at insertion.
- // - Insertion is o(n)
- // - Smallest element goes at the end, so that popping it is o(1).
- // - Resorting is n*log(n)
- // @@ Number of elements in the queue is usually small, and we'd have to rebalance often. I'm not sure it's worth implementing a heap.
- // @@ Searcing at removal would remove the need for sorting when priorities change.
- struct PriorityQueue
- {
- PriorityQueue(uint size = UINT_MAX) : maxSize(size) {}
-
- void push(float priority, uint face) {
- uint i = 0;
- const uint count = pairs.count();
- for (; i < count; i++) {
- if (pairs[i].priority > priority) break;
- }
-
- Pair p = { priority, face };
- pairs.insertAt(i, p);
-
- if (pairs.count() > maxSize) {
- pairs.removeAt(0);
- }
- }
-
- // push face out of order, to be sorted later.
- void push(uint face) {
- Pair p = { 0.0f, face };
- pairs.append(p);
- }
-
- uint pop() {
- uint f = pairs.back().face;
- pairs.pop_back();
- return f;
- }
-
- void sort() {
- //nv::sort(pairs); // @@ My intro sort appears to be much slower than it should!
- std::sort(pairs.buffer(), pairs.buffer() + pairs.count());
- }
-
- void clear() {
- pairs.clear();
- }
-
- uint count() const { return pairs.count(); }
-
- float firstPriority() const { return pairs.back().priority; }
-
-
- const uint maxSize;
-
- struct Pair {
- bool operator <(const Pair & p) const { return priority > p.priority; } // !! Sort in inverse priority order!
- float priority;
- uint face;
- };
-
-
- Array<Pair> pairs;
- };
-
- static bool isNormalSeam(const HalfEdge::Edge * edge) {
- return (edge->vertex->nor != edge->pair->next->vertex->nor || edge->next->vertex->nor != edge->pair->vertex->nor);
- }
-
- static bool isTextureSeam(const HalfEdge::Edge * edge) {
- return (edge->vertex->tex != edge->pair->next->vertex->tex || edge->next->vertex->tex != edge->pair->vertex->tex);
- }
-
-} // namespace
-
-
-struct nv::ChartBuildData
-{
- ChartBuildData(int id) : id(id) {
- planeNormal = Vector3(0);
- centroid = Vector3(0);
- coneAxis = Vector3(0);
- coneAngle = 0;
- area = 0;
- boundaryLength = 0;
- normalSum = Vector3(0);
- centroidSum = Vector3(0);
- }
-
- int id;
-
- // Proxy info:
- Vector3 planeNormal;
- Vector3 centroid;
- Vector3 coneAxis;
- float coneAngle;
-
- float area;
- float boundaryLength;
- Vector3 normalSum;
- Vector3 centroidSum;
-
- Array<uint> seeds; // @@ These could be a pointers to the HalfEdge faces directly.
- Array<uint> faces;
- PriorityQueue candidates;
-};
-
-
-
-AtlasBuilder::AtlasBuilder(const HalfEdge::Mesh * m) : mesh(m), facesLeft(m->faceCount())
-{
- const uint faceCount = m->faceCount();
- faceChartArray.resize(faceCount, -1);
- faceCandidateArray.resize(faceCount, -1);
-
- // @@ Floyd for the whole mesh is too slow. We could compute floyd progressively per patch as the patch grows. We need a better solution to compute most central faces.
- //computeShortestPaths();
-
- // Precompute edge lengths and face areas.
- uint edgeCount = m->edgeCount();
- edgeLengths.resize(edgeCount);
-
- for (uint i = 0; i < edgeCount; i++) {
- uint id = m->edgeAt(i)->id;
- nvDebugCheck(id / 2 == i);
-
- edgeLengths[i] = m->edgeAt(i)->length();
- }
-
- faceAreas.resize(faceCount);
- for (uint i = 0; i < faceCount; i++) {
- faceAreas[i] = m->faceAt(i)->area();
- }
-}
-
-AtlasBuilder::~AtlasBuilder()
-{
- const uint chartCount = chartArray.count();
- for (uint i = 0; i < chartCount; i++)
- {
- delete chartArray[i];
- }
-}
-
-
-void AtlasBuilder::markUnchartedFaces(const Array<uint> & unchartedFaces)
-{
- const uint unchartedFaceCount = unchartedFaces.count();
- for (uint i = 0; i < unchartedFaceCount; i++){
- uint f = unchartedFaces[i];
- faceChartArray[f] = -2;
- //faceCandidateArray[f] = -2; // @@ ?
-
- removeCandidate(f);
- }
-
- nvDebugCheck(facesLeft >= unchartedFaceCount);
- facesLeft -= unchartedFaceCount;
-}
-
-
-void AtlasBuilder::computeShortestPaths()
-{
- const uint faceCount = mesh->faceCount();
- shortestPaths.resize(faceCount*faceCount, FLT_MAX);
-
- // Fill edges:
- for (uint i = 0; i < faceCount; i++)
- {
- shortestPaths[i*faceCount + i] = 0.0f;
-
- const HalfEdge::Face * face_i = mesh->faceAt(i);
- Vector3 centroid_i = face_i->centroid();
-
- for (HalfEdge::Face::ConstEdgeIterator it(face_i->edges()); !it.isDone(); it.advance())
- {
- const HalfEdge::Edge * edge = it.current();
-
- if (!edge->isBoundary())
- {
- const HalfEdge::Face * face_j = edge->pair->face;
-
- uint j = face_j->id;
- Vector3 centroid_j = face_j->centroid();
-
- shortestPaths[i*faceCount + j] = shortestPaths[j*faceCount + i] = length(centroid_i - centroid_j);
- }
- }
- }
-
- // Use Floyd-Warshall algorithm to compute all paths:
- for (uint k = 0; k < faceCount; k++)
- {
- for (uint i = 0; i < faceCount; i++)
- {
- for (uint j = 0; j < faceCount; j++)
- {
- shortestPaths[i*faceCount + j] = min(shortestPaths[i*faceCount + j], shortestPaths[i*faceCount + k]+shortestPaths[k*faceCount + j]);
- }
- }
- }
-}
-
-
-void AtlasBuilder::placeSeeds(float threshold, uint maxSeedCount)
-{
- // Instead of using a predefiened number of seeds:
- // - Add seeds one by one, growing chart until a certain treshold.
- // - Undo charts and restart growing process.
-
- // @@ How can we give preference to faces far from sharp features as in the LSCM paper?
- // - those points can be found using a simple flood filling algorithm.
- // - how do we weight the probabilities?
-
- for (uint i = 0; i < maxSeedCount; i++)
- {
- if (facesLeft == 0) {
- // No faces left, stop creating seeds.
- break;
- }
-
- createRandomChart(threshold);
- }
-}
-
-
-void AtlasBuilder::createRandomChart(float threshold)
-{
- ChartBuildData * chart = new ChartBuildData(chartArray.count());
- chartArray.append(chart);
-
- // Pick random face that is not used by any chart yet.
- uint randomFaceIdx = rand.getRange(facesLeft - 1);
- uint i = 0;
- for (uint f = 0; f != randomFaceIdx; f++, i++)
- {
- while (faceChartArray[i] != -1) i++;
- }
- while (faceChartArray[i] != -1) i++;
-
- chart->seeds.append(i);
-
- addFaceToChart(chart, i, true);
-
- // Grow the chart as much as possible within the given threshold.
- growChart(chart, threshold * 0.5f, facesLeft);
- //growCharts(threshold - threshold * 0.75f / chartCount(), facesLeft);
-}
-
-void AtlasBuilder::addFaceToChart(ChartBuildData * chart, uint f, bool recomputeProxy)
-{
- // Add face to chart.
- chart->faces.append(f);
-
- nvDebugCheck(faceChartArray[f] == -1);
- faceChartArray[f] = chart->id;
-
- facesLeft--;
-
- // Update area and boundary length.
- chart->area = evaluateChartArea(chart, f);
- chart->boundaryLength = evaluateBoundaryLength(chart, f);
- chart->normalSum = evaluateChartNormalSum(chart, f);
- chart->centroidSum = evaluateChartCentroidSum(chart, f);
-
- if (recomputeProxy) {
- // Update proxy and candidate's priorities.
- updateProxy(chart);
- }
-
- // Update candidates.
- removeCandidate(f);
- updateCandidates(chart, f);
- updatePriorities(chart);
-}
-
-// @@ Get N best candidates in one pass.
-const AtlasBuilder::Candidate & AtlasBuilder::getBestCandidate() const
-{
- uint best = 0;
- float bestCandidateMetric = FLT_MAX;
-
- const uint candidateCount = candidateArray.count();
- nvCheck(candidateCount > 0);
-
- for (uint i = 0; i < candidateCount; i++)
- {
- const Candidate & candidate = candidateArray[i];
-
- if (candidate.metric < bestCandidateMetric) {
- bestCandidateMetric = candidate.metric;
- best = i;
- }
- }
-
- return candidateArray[best];
-}
-
-
-// Returns true if any of the charts can grow more.
-bool AtlasBuilder::growCharts(float threshold, uint faceCount)
-{
-#if 1 // Using one global list.
-
- faceCount = min(faceCount, facesLeft);
-
- for (uint i = 0; i < faceCount; i++)
- {
- const Candidate & candidate = getBestCandidate();
-
- if (candidate.metric > threshold) {
- return false; // Can't grow more.
- }
-
- addFaceToChart(candidate.chart, candidate.face);
- }
-
- return facesLeft != 0; // Can continue growing.
-
-#else // Using one list per chart.
- bool canGrowMore = false;
-
- const uint chartCount = chartArray.count();
- for (uint i = 0; i < chartCount; i++)
- {
- if (growChart(chartArray[i], threshold, faceCount))
- {
- canGrowMore = true;
- }
- }
-
- return canGrowMore;
-#endif
-}
-
-bool AtlasBuilder::growChart(ChartBuildData * chart, float threshold, uint faceCount)
-{
- // Try to add faceCount faces within threshold to chart.
- for (uint i = 0; i < faceCount; )
- {
- if (chart->candidates.count() == 0 || chart->candidates.firstPriority() > threshold)
- {
- return false;
- }
-
- uint f = chart->candidates.pop();
- if (faceChartArray[f] == -1)
- {
- addFaceToChart(chart, f);
- i++;
- }
- }
-
- if (chart->candidates.count() == 0 || chart->candidates.firstPriority() > threshold)
- {
- return false;
- }
-
- return true;
-}
-
-
-void AtlasBuilder::resetCharts()
-{
- const uint faceCount = mesh->faceCount();
- for (uint i = 0; i < faceCount; i++)
- {
- faceChartArray[i] = -1;
- faceCandidateArray[i] = -1;
- }
-
- facesLeft = faceCount;
-
- candidateArray.clear();
-
- const uint chartCount = chartArray.count();
- for (uint i = 0; i < chartCount; i++)
- {
- ChartBuildData * chart = chartArray[i];
-
- const uint seed = chart->seeds.back();
-
- chart->area = 0.0f;
- chart->boundaryLength = 0.0f;
- chart->normalSum = Vector3(0);
- chart->centroidSum = Vector3(0);
-
- chart->faces.clear();
- chart->candidates.clear();
-
- addFaceToChart(chart, seed);
- }
-}
-
-
-void AtlasBuilder::updateCandidates(ChartBuildData * chart, uint f)
-{
- const HalfEdge::Face * face = mesh->faceAt(f);
-
- // Traverse neighboring faces, add the ones that do not belong to any chart yet.
- for (HalfEdge::Face::ConstEdgeIterator it(face->edges()); !it.isDone(); it.advance())
- {
- const HalfEdge::Edge * edge = it.current()->pair;
-
- if (!edge->isBoundary())
- {
- uint f = edge->face->id;
-
- if (faceChartArray[f] == -1)
- {
- chart->candidates.push(f);
- }
- }
- }
-}
-
-
-void AtlasBuilder::updateProxies()
-{
- const uint chartCount = chartArray.count();
- for (uint i = 0; i < chartCount; i++)
- {
- updateProxy(chartArray[i]);
- }
-}
-
-
-namespace {
-
- float absoluteSum(Vector4::Arg v)
- {
- return fabs(v.x) + fabs(v.y) + fabs(v.z) + fabs(v.w);
- }
-
- //#pragma message(NV_FILE_LINE "FIXME: Using the c=cos(teta) substitution, the equation system becomes linear and we can avoid the newton solver.")
-
- struct ConeFitting
- {
- ConeFitting(const HalfEdge::Mesh * m, float g, float tf, float tx) : mesh(m), gamma(g), tolf(tf), tolx(tx), F(0), D(0), H(0) {
- }
-
- void addTerm(Vector3 N, float A)
- {
- const float c = cosf(X.w);
- const float s = sinf(X.w);
- const float tmp = dot(X.xyz(), N) - c;
-
- F += tmp * tmp;
-
- D.x += 2 * X.x * tmp;
- D.y += 2 * X.y * tmp;
- D.z += 2 * X.z * tmp;
- D.w += 2 * s * tmp;
-
- H(0,0) = 2 * X.x * N.x + 2 * tmp;
- H(0,1) = 2 * X.x * N.y;
- H(0,2) = 2 * X.x * N.z;
- H(0,3) = 2 * X.x * s;
-
- H(1,0) = 2 * X.y * N.x;
- H(1,1) = 2 * X.y * N.y + 2 * tmp;
- H(1,2) = 2 * X.y * N.z;
- H(1,3) = 2 * X.y * s;
-
- H(2,0) = 2 * X.z * N.x;
- H(2,1) = 2 * X.z * N.y;
- H(2,2) = 2 * X.z * N.z + 2 * tmp;
- H(2,3) = 2 * X.z * s;
-
- H(3,0) = 2 * s * N.x;
- H(3,1) = 2 * s * N.y;
- H(3,2) = 2 * s * N.z;
- H(3,3) = 2 * s * s + 2 * c * tmp;
- }
-
- Vector4 solve(ChartBuildData * chart, Vector4 start)
- {
- const uint faceCount = chart->faces.count();
-
- X = start;
-
- Vector4 dX;
-
- do {
- for (uint i = 0; i < faceCount; i++)
- {
- const HalfEdge::Face * face = mesh->faceAt(chart->faces[i]);
-
- addTerm(face->normal(), face->area());
- }
-
- Vector4 dX;
- //solveKramer(H, D, &dX);
- solveLU(H, D, &dX);
-
- // @@ Do a full newton step and reduce by half if F doesn't decrease.
- X -= gamma * dX;
-
- // Constrain normal to be normalized.
- X = Vector4(normalize(X.xyz()), X.w);
-
- } while(absoluteSum(D) > tolf || absoluteSum(dX) > tolx);
-
- return X;
- }
-
- HalfEdge::Mesh const * const mesh;
- const float gamma;
- const float tolf;
- const float tolx;
-
- Vector4 X;
-
- float F;
- Vector4 D;
- Matrix H;
- };
-
- // Unnormalized face normal assuming it's a triangle.
- static Vector3 triangleNormal(const HalfEdge::Face * face)
- {
- Vector3 p0 = face->edge->vertex->pos;
- Vector3 p1 = face->edge->next->vertex->pos;
- Vector3 p2 = face->edge->next->next->vertex->pos;
-
- Vector3 e0 = p2 - p0;
- Vector3 e1 = p1 - p0;
-
- return normalizeSafe(cross(e0, e1), Vector3(0), 0.0f);
- }
-
- static Vector3 triangleNormalAreaScaled(const HalfEdge::Face * face)
- {
- Vector3 p0 = face->edge->vertex->pos;
- Vector3 p1 = face->edge->next->vertex->pos;
- Vector3 p2 = face->edge->next->next->vertex->pos;
-
- Vector3 e0 = p2 - p0;
- Vector3 e1 = p1 - p0;
-
- return cross(e0, e1);
- }
-
- // Average of the edge midpoints weighted by the edge length.
- // I want a point inside the triangle, but closer to the cirumcenter.
- static Vector3 triangleCenter(const HalfEdge::Face * face)
- {
- Vector3 p0 = face->edge->vertex->pos;
- Vector3 p1 = face->edge->next->vertex->pos;
- Vector3 p2 = face->edge->next->next->vertex->pos;
-
- float l0 = length(p1 - p0);
- float l1 = length(p2 - p1);
- float l2 = length(p0 - p2);
-
- Vector3 m0 = (p0 + p1) * l0 / (l0 + l1 + l2);
- Vector3 m1 = (p1 + p2) * l1 / (l0 + l1 + l2);
- Vector3 m2 = (p2 + p0) * l2 / (l0 + l1 + l2);
-
- return m0 + m1 + m2;
- }
-
-} // namespace
-
-void AtlasBuilder::updateProxy(ChartBuildData * chart)
-{
- //#pragma message(NV_FILE_LINE "TODO: Use best fit plane instead of average normal.")
-
- chart->planeNormal = normalizeSafe(chart->normalSum, Vector3(0), 0.0f);
- chart->centroid = chart->centroidSum / float(chart->faces.count());
-
- //#pragma message(NV_FILE_LINE "TODO: Experiment with conic fitting.")
-
- // F = (Nc*Nt - cos Oc)^2 = (x*Nt_x + y*Nt_y + z*Nt_z - cos w)^2
- // dF/dx = 2 * x * (x*Nt_x + y*Nt_y + z*Nt_z - cos w)
- // dF/dy = 2 * y * (x*Nt_x + y*Nt_y + z*Nt_z - cos w)
- // dF/dz = 2 * z * (x*Nt_x + y*Nt_y + z*Nt_z - cos w)
- // dF/dw = 2 * sin w * (x*Nt_x + y*Nt_y + z*Nt_z - cos w)
-
- // JacobianMatrix({
- // 2 * x * (x*Nt_x + y*Nt_y + z*Nt_z - Cos(w)),
- // 2 * y * (x*Nt_x + y*Nt_y + z*Nt_z - Cos(w)),
- // 2 * z * (x*Nt_x + y*Nt_y + z*Nt_z - Cos(w)),
- // 2 * Sin(w) * (x*Nt_x + y*Nt_y + z*Nt_z - Cos(w))}, {x,y,z,w})
-
- // H[0,0] = 2 * x * Nt_x + 2 * (x*Nt_x + y*Nt_y + z*Nt_z - cos(w));
- // H[0,1] = 2 * x * Nt_y;
- // H[0,2] = 2 * x * Nt_z;
- // H[0,3] = 2 * x * sin(w);
-
- // H[1,0] = 2 * y * Nt_x;
- // H[1,1] = 2 * y * Nt_y + 2 * (x*Nt_x + y*Nt_y + z*Nt_z - cos(w));
- // H[1,2] = 2 * y * Nt_z;
- // H[1,3] = 2 * y * sin(w);
-
- // H[2,0] = 2 * z * Nt_x;
- // H[2,1] = 2 * z * Nt_y;
- // H[2,2] = 2 * z * Nt_z + 2 * (x*Nt_x + y*Nt_y + z*Nt_z - cos(w));
- // H[2,3] = 2 * z * sin(w);
-
- // H[3,0] = 2 * sin(w) * Nt_x;
- // H[3,1] = 2 * sin(w) * Nt_y;
- // H[3,2] = 2 * sin(w) * Nt_z;
- // H[3,3] = 2 * sin(w) * sin(w) + 2 * cos(w) * (x*Nt_x + y*Nt_y + z*Nt_z - cos(w));
-
- // @@ Cone fitting might be quite slow.
-
- /*ConeFitting coneFitting(mesh, 0.1f, 0.001f, 0.001f);
-
- Vector4 start = Vector4(chart->coneAxis, chart->coneAngle);
- Vector4 solution = coneFitting.solve(chart, start);
-
- chart->coneAxis = solution.xyz();
- chart->coneAngle = solution.w;*/
-}
-
-
-
-bool AtlasBuilder::relocateSeeds()
-{
- bool anySeedChanged = false;
-
- const uint chartCount = chartArray.count();
- for (uint i = 0; i < chartCount; i++)
- {
- if (relocateSeed(chartArray[i]))
- {
- anySeedChanged = true;
- }
- }
-
- return anySeedChanged;
-}
-
-
-bool AtlasBuilder::relocateSeed(ChartBuildData * chart)
-{
- Vector3 centroid = computeChartCentroid(chart);
-
- const uint N = 10; // @@ Hardcoded to 10?
- PriorityQueue bestTriangles(N);
-
- // Find the first N triangles that fit the proxy best.
- const uint faceCount = chart->faces.count();
- for (uint i = 0; i < faceCount; i++)
- {
- float priority = evaluateProxyFitMetric(chart, chart->faces[i]);
- bestTriangles.push(priority, chart->faces[i]);
- }
-
- // Of those, choose the most central triangle.
- uint mostCentral;
- float maxDistance = -1;
-
- const uint bestCount = bestTriangles.count();
- for (uint i = 0; i < bestCount; i++)
- {
- const HalfEdge::Face * face = mesh->faceAt(bestTriangles.pairs[i].face);
- Vector3 faceCentroid = triangleCenter(face);
-
- float distance = length(centroid - faceCentroid);
-
- /*#pragma message(NV_FILE_LINE "TODO: Implement evaluateDistanceToBoundary.")
- float distance = evaluateDistanceToBoundary(chart, bestTriangles.pairs[i].face);*/
-
- if (distance > maxDistance)
- {
- maxDistance = distance;
- mostCentral = bestTriangles.pairs[i].face;
- }
- }
- nvDebugCheck(maxDistance >= 0);
-
- // In order to prevent k-means cyles we record all the previously chosen seeds.
- uint index;
- if (chart->seeds.find(mostCentral, &index))
- {
- // Move new seed to the end of the seed array.
- uint last = chart->seeds.count() - 1;
- swap(chart->seeds[index], chart->seeds[last]);
- return false;
- }
- else
- {
- // Append new seed.
- chart->seeds.append(mostCentral);
- return true;
- }
-}
-
-void AtlasBuilder::removeCandidate(uint f)
-{
- int c = faceCandidateArray[f];
- if (c != -1) {
- faceCandidateArray[f] = -1;
-
- if (c == candidateArray.count() - 1) {
- candidateArray.popBack();
- }
- else {
- candidateArray.replaceWithLast(c);
- faceCandidateArray[candidateArray[c].face] = c;
- }
- }
-}
-
-void AtlasBuilder::updateCandidate(ChartBuildData * chart, uint f, float metric)
-{
- if (faceCandidateArray[f] == -1) {
- const uint index = candidateArray.count();
- faceCandidateArray[f] = index;
- candidateArray.resize(index + 1);
- candidateArray[index].face = f;
- candidateArray[index].chart = chart;
- candidateArray[index].metric = metric;
- }
- else {
- int c = faceCandidateArray[f];
- nvDebugCheck(c != -1);
-
- Candidate & candidate = candidateArray[c];
- nvDebugCheck(candidate.face == f);
-
- if (metric < candidate.metric || chart == candidate.chart) {
- candidate.metric = metric;
- candidate.chart = chart;
- }
- }
-
-}
-
-
-void AtlasBuilder::updatePriorities(ChartBuildData * chart)
-{
- // Re-evaluate candidate priorities.
- uint candidateCount = chart->candidates.count();
- for (uint i = 0; i < candidateCount; i++)
- {
- chart->candidates.pairs[i].priority = evaluatePriority(chart, chart->candidates.pairs[i].face);
-
- if (faceChartArray[chart->candidates.pairs[i].face] == -1)
- {
- updateCandidate(chart, chart->candidates.pairs[i].face, chart->candidates.pairs[i].priority);
- }
- }
-
- // Sort candidates.
- chart->candidates.sort();
-}
-
-
-// Evaluate combined metric.
-float AtlasBuilder::evaluatePriority(ChartBuildData * chart, uint face)
-{
- // Estimate boundary length and area:
- float newBoundaryLength = evaluateBoundaryLength(chart, face);
- float newChartArea = evaluateChartArea(chart, face);
-
- float F = evaluateProxyFitMetric(chart, face);
- float C = evaluateRoundnessMetric(chart, face, newBoundaryLength, newChartArea);
- float P = evaluateStraightnessMetric(chart, face);
-
- // Penalize faces that cross seams, reward faces that close seams or reach boundaries.
- float N = evaluateNormalSeamMetric(chart, face);
- float T = evaluateTextureSeamMetric(chart, face);
-
- //float R = evaluateCompletenessMetric(chart, face);
-
- //float D = evaluateDihedralAngleMetric(chart, face);
- // @@ Add a metric based on local dihedral angle.
-
- // @@ Tweaking the normal and texture seam metrics.
- // - Cause more impedance. Never cross 90 degree edges.
- // -
-
- float cost = float(
- settings.proxyFitMetricWeight * F +
- settings.roundnessMetricWeight * C +
- settings.straightnessMetricWeight * P +
- settings.normalSeamMetricWeight * N +
- settings.textureSeamMetricWeight * T);
-
- /*cost = settings.proxyFitMetricWeight * powf(F, settings.proxyFitMetricExponent);
- cost = max(cost, settings.roundnessMetricWeight * powf(C, settings.roundnessMetricExponent));
- cost = max(cost, settings.straightnessMetricWeight * pow(P, settings.straightnessMetricExponent));
- cost = max(cost, settings.normalSeamMetricWeight * N);
- cost = max(cost, settings.textureSeamMetricWeight * T);*/
-
- // Enforce limits strictly:
- if (newChartArea > settings.maxChartArea) cost = FLT_MAX;
- if (newBoundaryLength > settings.maxBoundaryLength) cost = FLT_MAX;
-
- // Make sure normal seams are fully respected:
- if (settings.normalSeamMetricWeight >= 1000 && N != 0) cost = FLT_MAX;
-
- nvCheck(isFinite(cost));
- return cost;
-}
-
-
-// Returns a value in [0-1].
-float AtlasBuilder::evaluateProxyFitMetric(ChartBuildData * chart, uint f)
-{
- const HalfEdge::Face * face = mesh->faceAt(f);
- Vector3 faceNormal = triangleNormal(face);
- //return square(dot(chart->coneAxis, faceNormal) - cosf(chart->coneAngle));
-
- // Use plane fitting metric for now:
- //return square(1 - dot(faceNormal, chart->planeNormal)); // @@ normal deviations should be weighted by face area
- return 1 - dot(faceNormal, chart->planeNormal); // @@ normal deviations should be weighted by face area
-
- // Find distance to chart.
- /*Vector3 faceCentroid = face->centroid();
-
- float dist = 0;
- int count = 0;
-
- for (HalfEdge::Face::ConstEdgeIterator it(face->edges()); !it.isDone(); it.advance())
- {
- const HalfEdge::Edge * edge = it.current();
-
- if (!edge->isBoundary()) {
- const HalfEdge::Face * neighborFace = edge->pair()->face();
- if (faceChartArray[neighborFace->id()] == chart->id) {
- dist += length(neighborFace->centroid() - faceCentroid);
- count++;
- }
- }
- }
-
- dist /= (count * count);
-
- return (1 - dot(faceNormal, chart->planeNormal)) * dist;*/
-
- //return (1 - dot(faceNormal, chart->planeNormal));
-}
-
-float AtlasBuilder::evaluateDistanceToBoundary(ChartBuildData * chart, uint face)
-{
-//#pragma message(NV_FILE_LINE "TODO: Evaluate distance to boundary metric.")
-
- // @@ This is needed for the seed relocation code.
- // @@ This could provide a better roundness metric.
-
- return 0.0f;
-}
-
-float AtlasBuilder::evaluateDistanceToSeed(ChartBuildData * chart, uint f)
-{
- //const uint seed = chart->seeds.back();
- //const uint faceCount = mesh->faceCount();
- //return shortestPaths[seed * faceCount + f];
-
- const HalfEdge::Face * seed = mesh->faceAt(chart->seeds.back());
- const HalfEdge::Face * face = mesh->faceAt(f);
- return length(triangleCenter(seed) - triangleCenter(face));
-}
-
-
-float AtlasBuilder::evaluateRoundnessMetric(ChartBuildData * chart, uint face, float newBoundaryLength, float newChartArea)
-{
- // @@ D-charts use distance to seed.
- // C(c,t) = pi * D(S_c,t)^2 / A_c
- //return PI * square(evaluateDistanceToSeed(chart, face)) / chart->area;
- //return PI * square(evaluateDistanceToSeed(chart, face)) / chart->area;
- //return 2 * PI * evaluateDistanceToSeed(chart, face) / chart->boundaryLength;
-
- // Garland's Hierarchical Face Clustering paper uses ratio between boundary and area, which is easier to compute and might work as well:
- // roundness = D^2/4*pi*A -> circle = 1, non circle greater than 1
-
- //return square(newBoundaryLength) / (newChartArea * 4 * PI);
- float roundness = square(chart->boundaryLength) / chart->area;
- float newRoundness = square(newBoundaryLength) / newChartArea;
- if (newRoundness > roundness) {
- return square(newBoundaryLength) / (newChartArea * 4 * PI);
- }
- else {
- // Offer no impedance to faces that improve roundness.
- return 0;
- }
-
- //return square(newBoundaryLength) / (4 * PI * newChartArea);
- //return clamp(1 - (4 * PI * newChartArea) / square(newBoundaryLength), 0.0f, 1.0f);
-
- // Use the ratio between the new roundness vs. the previous roundness.
- // - If we use the absolute metric, when the initial face is very long, then it's hard to make any progress.
- //return (square(newBoundaryLength) * chart->area) / (square(chart->boundaryLength) * newChartArea);
- //return (4 * PI * newChartArea) / square(newBoundaryLength) - (4 * PI * chart->area) / square(chart->boundaryLength);
-
- //if (square(newBoundaryLength) * chart->area) / (square(chart->boundaryLength) * newChartArea);
-
-}
-
-float AtlasBuilder::evaluateStraightnessMetric(ChartBuildData * chart, uint f)
-{
- float l_out = 0.0f;
- float l_in = 0.0f;
-
- const HalfEdge::Face * face = mesh->faceAt(f);
- for (HalfEdge::Face::ConstEdgeIterator it(face->edges()); !it.isDone(); it.advance())
- {
- const HalfEdge::Edge * edge = it.current();
-
- //float l = edge->length();
- float l = edgeLengths[edge->id/2];
-
- if (edge->isBoundary())
- {
- l_out += l;
- }
- else
- {
- uint neighborFaceId = edge->pair->face->id;
- if (faceChartArray[neighborFaceId] != chart->id) {
- l_out += l;
- }
- else {
- l_in += l;
- }
- }
- }
- nvDebugCheck(l_in != 0.0f); // Candidate face must be adjacent to chart. @@ This is not true if the input mesh has zero-length edges.
-
- //return l_out / l_in;
- float ratio = (l_out - l_in) / (l_out + l_in);
- //if (ratio < 0) ratio *= 10; // Encourage closing gaps.
- return min(ratio, 0.0f); // Only use the straightness metric to close gaps.
- //return ratio;
-}
-
-
-float AtlasBuilder::evaluateNormalSeamMetric(ChartBuildData * chart, uint f)
-{
- float seamFactor = 0.0f;
- float totalLength = 0.0f;
-
- const HalfEdge::Face * face = mesh->faceAt(f);
- for (HalfEdge::Face::ConstEdgeIterator it(face->edges()); !it.isDone(); it.advance())
- {
- const HalfEdge::Edge * edge = it.current();
-
- if (edge->isBoundary()) {
- continue;
- }
-
- const uint neighborFaceId = edge->pair->face->id;
- if (faceChartArray[neighborFaceId] != chart->id) {
- continue;
- }
-
- //float l = edge->length();
- float l = edgeLengths[edge->id/2];
-
- totalLength += l;
-
- if (!edge->isSeam()) {
- continue;
- }
-
- // Make sure it's a normal seam.
- if (isNormalSeam(edge))
- {
- float d0 = clamp(dot(edge->vertex->nor, edge->pair->next->vertex->nor), 0.0f, 1.0f);
- float d1 = clamp(dot(edge->next->vertex->nor, edge->pair->vertex->nor), 0.0f, 1.0f);
- //float a0 = clamp(acosf(d0) / (PI/2), 0.0f, 1.0f);
- //float a1 = clamp(acosf(d1) / (PI/2), 0.0f, 1.0f);
- //l *= (a0 + a1) * 0.5f;
-
- l *= 1 - (d0 + d1) * 0.5f;
-
- seamFactor += l;
- }
- }
-
- if (seamFactor == 0) return 0.0f;
- return seamFactor / totalLength;
-}
-
-
-float AtlasBuilder::evaluateTextureSeamMetric(ChartBuildData * chart, uint f)
-{
- float seamLength = 0.0f;
- //float newSeamLength = 0.0f;
- //float oldSeamLength = 0.0f;
- float totalLength = 0.0f;
-
- const HalfEdge::Face * face = mesh->faceAt(f);
- for (HalfEdge::Face::ConstEdgeIterator it(face->edges()); !it.isDone(); it.advance())
- {
- const HalfEdge::Edge * edge = it.current();
-
- /*float l = edge->length();
- totalLength += l;
-
- if (edge->isBoundary() || !edge->isSeam()) {
- continue;
- }
-
- // Make sure it's a texture seam.
- if (isTextureSeam(edge))
- {
- uint neighborFaceId = edge->pair()->face()->id();
- if (faceChartArray[neighborFaceId] != chart->id) {
- newSeamLength += l;
- }
- else {
- oldSeamLength += l;
- }
- }*/
-
- if (edge->isBoundary()) {
- continue;
- }
-
- const uint neighborFaceId = edge->pair->face->id;
- if (faceChartArray[neighborFaceId] != chart->id) {
- continue;
- }
-
- //float l = edge->length();
- float l = edgeLengths[edge->id/2];
- totalLength += l;
-
- if (!edge->isSeam()) {
- continue;
- }
-
- // Make sure it's a texture seam.
- if (isTextureSeam(edge))
- {
- seamLength += l;
- }
- }
-
- if (seamLength == 0.0f) {
- return 0.0f; // Avoid division by zero.
- }
-
- return seamLength / totalLength;
-}
-
-
-float AtlasBuilder::evaluateSeamMetric(ChartBuildData * chart, uint f)
-{
- float newSeamLength = 0.0f;
- float oldSeamLength = 0.0f;
- float totalLength = 0.0f;
-
- const HalfEdge::Face * face = mesh->faceAt(f);
- for (HalfEdge::Face::ConstEdgeIterator it(face->edges()); !it.isDone(); it.advance())
- {
- const HalfEdge::Edge * edge = it.current();
-
- //float l = edge->length();
- float l = edgeLengths[edge->id/2];
-
- if (edge->isBoundary())
- {
- newSeamLength += l;
- }
- else
- {
- if (edge->isSeam())
- {
- uint neighborFaceId = edge->pair->face->id;
- if (faceChartArray[neighborFaceId] != chart->id) {
- newSeamLength += l;
- }
- else {
- oldSeamLength += l;
- }
- }
- }
-
- totalLength += l;
- }
-
- return (newSeamLength - oldSeamLength) / totalLength;
-}
-
-
-float AtlasBuilder::evaluateChartArea(ChartBuildData * chart, uint f)
-{
- const HalfEdge::Face * face = mesh->faceAt(f);
- //return chart->area + face->area();
- return chart->area + faceAreas[face->id];
-}
-
-
-float AtlasBuilder::evaluateBoundaryLength(ChartBuildData * chart, uint f)
-{
- float boundaryLength = chart->boundaryLength;
-
- // Add new edges, subtract edges shared with the chart.
- const HalfEdge::Face * face = mesh->faceAt(f);
- for (HalfEdge::Face::ConstEdgeIterator it(face->edges()); !it.isDone(); it.advance())
- {
- const HalfEdge::Edge * edge = it.current();
- //float edgeLength = edge->length();
- float edgeLength = edgeLengths[edge->id/2];
-
- if (edge->isBoundary())
- {
- boundaryLength += edgeLength;
- }
- else
- {
- uint neighborFaceId = edge->pair->face->id;
- if (faceChartArray[neighborFaceId] != chart->id) {
- boundaryLength += edgeLength;
- }
- else {
- boundaryLength -= edgeLength;
- }
- }
- }
- //nvDebugCheck(boundaryLength >= 0);
-
- return max(0.0f, boundaryLength); // @@ Hack!
-}
-
-Vector3 AtlasBuilder::evaluateChartNormalSum(ChartBuildData * chart, uint f)
-{
- const HalfEdge::Face * face = mesh->faceAt(f);
- return chart->normalSum + triangleNormalAreaScaled(face);
-}
-
-Vector3 AtlasBuilder::evaluateChartCentroidSum(ChartBuildData * chart, uint f)
-{
- const HalfEdge::Face * face = mesh->faceAt(f);
- return chart->centroidSum + face->centroid();
-}
-
-
-Vector3 AtlasBuilder::computeChartCentroid(const ChartBuildData * chart)
-{
- Vector3 centroid(0);
-
- const uint faceCount = chart->faces.count();
- for (uint i = 0; i < faceCount; i++)
- {
- const HalfEdge::Face * face = mesh->faceAt(chart->faces[i]);
- centroid += triangleCenter(face);
- }
-
- return centroid / float(faceCount);
-}
-
-
-void AtlasBuilder::fillHoles(float threshold)
-{
- while (facesLeft > 0)
- {
- createRandomChart(threshold);
- }
-}
-
-
-void AtlasBuilder::mergeChart(ChartBuildData * owner, ChartBuildData * chart, float sharedBoundaryLength)
-{
- const uint faceCount = chart->faces.count();
- for (uint i = 0; i < faceCount; i++)
- {
- uint f = chart->faces[i];
-
- nvDebugCheck(faceChartArray[f] == chart->id);
- faceChartArray[f] = owner->id;
-
- owner->faces.append(f);
- }
-
- // Update adjacencies?
-
- owner->area += chart->area;
- owner->boundaryLength += chart->boundaryLength - sharedBoundaryLength;
-
- owner->normalSum += chart->normalSum;
- owner->centroidSum += chart->centroidSum;
-
- updateProxy(owner);
-}
-
-void AtlasBuilder::mergeCharts()
-{
- Array<float> sharedBoundaryLengths;
-
- const uint chartCount = chartArray.count();
- for (int c = chartCount-1; c >= 0; c--)
- {
- sharedBoundaryLengths.clear();
- sharedBoundaryLengths.resize(chartCount, 0.0f);
-
- ChartBuildData * chart = chartArray[c];
-
- float externalBoundary = 0.0f;
-
- const uint faceCount = chart->faces.count();
- for (uint i = 0; i < faceCount; i++)
- {
- uint f = chart->faces[i];
- const HalfEdge::Face * face = mesh->faceAt(f);
-
- for (HalfEdge::Face::ConstEdgeIterator it(face->edges()); !it.isDone(); it.advance())
- {
- const HalfEdge::Edge * edge = it.current();
-
- //float l = edge->length();
- float l = edgeLengths[edge->id/2];
-
- if (edge->isBoundary()) {
- externalBoundary += l;
- }
- else {
- uint neighborFace = edge->pair->face->id;
- uint neighborChart = faceChartArray[neighborFace];
-
- if (neighborChart != c) {
- if ((edge->isSeam() && (isNormalSeam(edge) || isTextureSeam(edge))) || neighborChart == -2) {
- externalBoundary += l;
- }
- else {
- sharedBoundaryLengths[neighborChart] += l;
- }
- }
- }
- }
- }
-
- for (int cc = chartCount-1; cc >= 0; cc--)
- {
- if (cc == c)
- continue;
-
- ChartBuildData * chart2 = chartArray[cc];
- if (chart2 == NULL)
- continue;
-
- if (sharedBoundaryLengths[cc] > 0.8 * max(0.0f, chart->boundaryLength - externalBoundary)) {
-
- // Try to avoid degenerate configurations.
- if (chart2->boundaryLength > sharedBoundaryLengths[cc])
- {
- if (dot(chart2->planeNormal, chart->planeNormal) > -0.25) {
- mergeChart(chart2, chart, sharedBoundaryLengths[cc]);
- delete chart;
- chartArray[c] = NULL;
- break;
- }
- }
- }
-
- if (sharedBoundaryLengths[cc] > 0.20 * max(0.0f, chart->boundaryLength - externalBoundary)) {
-
- // Compare proxies.
- if (dot(chart2->planeNormal, chart->planeNormal) > 0) {
- mergeChart(chart2, chart, sharedBoundaryLengths[cc]);
- delete chart;
- chartArray[c] = NULL;
- break;
- }
- }
- }
- }
-
- // Remove deleted charts.
- for (int c = 0; c < I32(chartArray.count()); /*do not increment if removed*/)
- {
- if (chartArray[c] == NULL) {
- chartArray.removeAt(c);
-
- // Update faceChartArray.
- const uint faceCount = faceChartArray.count();
- for (uint i = 0; i < faceCount; i++) {
- nvDebugCheck (faceChartArray[i] != -1);
- nvDebugCheck (faceChartArray[i] != c);
- nvDebugCheck (faceChartArray[i] <= I32(chartArray.count()));
-
- if (faceChartArray[i] > c) {
- faceChartArray[i]--;
- }
- }
- }
- else {
- chartArray[c]->id = c;
- c++;
- }
- }
-}
-
-
-
-const Array<uint> & AtlasBuilder::chartFaces(uint i) const
-{
- return chartArray[i]->faces;
-}
diff --git a/thirdparty/thekla_atlas/nvmesh/param/AtlasBuilder.h b/thirdparty/thekla_atlas/nvmesh/param/AtlasBuilder.h
deleted file mode 100644
index f25c724f7e..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/param/AtlasBuilder.h
+++ /dev/null
@@ -1,111 +0,0 @@
-// This code is in the public domain -- castano@gmail.com
-
-#pragma once
-#ifndef NV_MESH_ATLASBUILDER_H
-#define NV_MESH_ATLASBUILDER_H
-
-#include "Atlas.h"
-
-#include "nvmath/Vector.h"
-#include "nvmath/Random.h"
-#include "nvmesh/nvmesh.h"
-
-#include "nvcore/Array.h"
-#include "nvcore/BitArray.h"
-
-
-
-namespace nv
-{
- namespace HalfEdge { class Mesh; }
-
- struct ChartBuildData;
-
- struct AtlasBuilder
- {
- AtlasBuilder(const HalfEdge::Mesh * m);
- ~AtlasBuilder();
-
- void markUnchartedFaces(const Array<uint> & unchartedFaces);
-
- void computeShortestPaths();
-
- void placeSeeds(float threshold, uint maxSeedCount);
- void createRandomChart(float threshold);
-
- void addFaceToChart(ChartBuildData * chart, uint f, bool recomputeProxy=false);
-
- bool growCharts(float threshold, uint faceCount);
- bool growChart(ChartBuildData * chart, float threshold, uint faceCount);
-
- void resetCharts();
-
- void updateCandidates(ChartBuildData * chart, uint face);
-
- void updateProxies();
- void updateProxy(ChartBuildData * chart);
-
- bool relocateSeeds();
- bool relocateSeed(ChartBuildData * chart);
-
- void updatePriorities(ChartBuildData * chart);
-
- float evaluatePriority(ChartBuildData * chart, uint face);
- float evaluateProxyFitMetric(ChartBuildData * chart, uint face);
- float evaluateDistanceToBoundary(ChartBuildData * chart, uint face);
- float evaluateDistanceToSeed(ChartBuildData * chart, uint face);
- float evaluateRoundnessMetric(ChartBuildData * chart, uint face, float newBoundaryLength, float newChartArea);
- float evaluateStraightnessMetric(ChartBuildData * chart, uint face);
-
- float evaluateNormalSeamMetric(ChartBuildData * chart, uint f);
- float evaluateTextureSeamMetric(ChartBuildData * chart, uint f);
- float evaluateSeamMetric(ChartBuildData * chart, uint f);
-
- float evaluateChartArea(ChartBuildData * chart, uint f);
- float evaluateBoundaryLength(ChartBuildData * chart, uint f);
- Vector3 evaluateChartNormalSum(ChartBuildData * chart, uint f);
- Vector3 evaluateChartCentroidSum(ChartBuildData * chart, uint f);
-
- Vector3 computeChartCentroid(const ChartBuildData * chart);
-
-
- void fillHoles(float threshold);
- void mergeCharts();
-
- // @@ Cleanup.
- struct Candidate {
- uint face;
- ChartBuildData * chart;
- float metric;
- };
-
- const Candidate & getBestCandidate() const;
- void removeCandidate(uint f);
- void updateCandidate(ChartBuildData * chart, uint f, float metric);
-
- void mergeChart(ChartBuildData * owner, ChartBuildData * chart, float sharedBoundaryLength);
-
-
- uint chartCount() const { return chartArray.count(); }
- const Array<uint> & chartFaces(uint i) const;
-
- const HalfEdge::Mesh * mesh;
- uint facesLeft;
- Array<int> faceChartArray;
- Array<ChartBuildData *> chartArray;
- Array<float> shortestPaths;
-
- Array<float> edgeLengths;
- Array<float> faceAreas;
-
- Array<Candidate> candidateArray; //
- Array<uint> faceCandidateArray; // Map face index to candidate index.
-
- MTRand rand;
-
- SegmentationSettings settings;
- };
-
-} // nv namespace
-
-#endif // NV_MESH_ATLASBUILDER_H
diff --git a/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.cpp b/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.cpp
deleted file mode 100644
index 11e635db17..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.cpp
+++ /dev/null
@@ -1,1401 +0,0 @@
-// This code is in the public domain -- castano@gmail.com
-
-#include "nvmesh.h" // pch
-
-#include "AtlasPacker.h"
-#include "nvmesh/halfedge/Vertex.h"
-#include "nvmesh/halfedge/Face.h"
-#include "nvmesh/param/Atlas.h"
-#include "nvmesh/param/Util.h"
-#include "nvmesh/raster/Raster.h"
-
-#include "nvmath/Vector.inl"
-#include "nvmath/ConvexHull.h"
-#include "nvmath/Color.h"
-#include "nvmath/ftoi.h"
-
-#include "nvcore/StrLib.h" // debug
-#include "nvcore/StdStream.h" // fileOpen
-
-#include <float.h> // FLT_MAX
-#include <limits.h> // UINT_MAX
-
-using namespace nv;
-
-#define DEBUG_OUTPUT 0
-
-#if DEBUG_OUTPUT
-
-#include "nvimage/ImageIO.h"
-
-namespace
-{
- const uint TGA_TYPE_GREY = 3;
- const uint TGA_TYPE_RGB = 2;
- const uint TGA_ORIGIN_UPPER = 0x20;
-
-#pragma pack(push, 1)
- struct TgaHeader {
- uint8 id_length;
- uint8 colormap_type;
- uint8 image_type;
- uint16 colormap_index;
- uint16 colormap_length;
- uint8 colormap_size;
- uint16 x_origin;
- uint16 y_origin;
- uint16 width;
- uint16 height;
- uint8 pixel_size;
- uint8 flags;
-
- enum { Size = 18 }; //const static int SIZE = 18;
- };
-#pragma pack(pop)
-
- static void outputDebugBitmap(const char * fileName, const BitMap & bitmap, int w, int h)
- {
- FILE * fp = fileOpen(fileName, "wb");
- if (fp == NULL) return;
-
- nvStaticCheck(sizeof(TgaHeader) == TgaHeader::Size);
- TgaHeader tga;
- tga.id_length = 0;
- tga.colormap_type = 0;
- tga.image_type = TGA_TYPE_GREY;
-
- tga.colormap_index = 0;
- tga.colormap_length = 0;
- tga.colormap_size = 0;
-
- tga.x_origin = 0;
- tga.y_origin = 0;
- tga.width = w;
- tga.height = h;
- tga.pixel_size = 8;
- tga.flags = TGA_ORIGIN_UPPER;
-
- fwrite(&tga, sizeof(TgaHeader), 1, fp);
-
- for (int j = 0; j < h; j++) {
- for (int i = 0; i < w; i++) {
- uint8 color = bitmap.bitAt(i, j) ? 0xFF : 0x0;
- fwrite(&color, 1, 1, fp);
- }
- }
-
- fclose(fp);
- }
-
- static void outputDebugImage(const char * fileName, const Image & bitmap, int w, int h)
- {
- FILE * fp = fileOpen(fileName, "wb");
- if (fp == NULL) return;
-
- nvStaticCheck(sizeof(TgaHeader) == TgaHeader::Size);
- TgaHeader tga;
- tga.id_length = 0;
- tga.colormap_type = 0;
- tga.image_type = TGA_TYPE_RGB;
-
- tga.colormap_index = 0;
- tga.colormap_length = 0;
- tga.colormap_size = 0;
-
- tga.x_origin = 0;
- tga.y_origin = 0;
- tga.width = w;
- tga.height = h;
- tga.pixel_size = 24;
- tga.flags = TGA_ORIGIN_UPPER;
-
- fwrite(&tga, sizeof(TgaHeader), 1, fp);
-
- for (int j = 0; j < h; j++) {
- for (int i = 0; i < w; i++) {
- Color32 color = bitmap.pixel(i, j);
- fwrite(&color.r, 1, 1, fp);
- fwrite(&color.g, 1, 1, fp);
- fwrite(&color.b, 1, 1, fp);
- }
- }
-
- fclose(fp);
- }
-}
-
-#endif // DEBUG_OUTPUT
-
-inline int align(int x, int a) {
- //return a * ((x + a - 1) / a);
- //return (x + a - 1) & -a;
- return (x + a - 1) & ~(a - 1);
-}
-
-inline bool isAligned(int x, int a) {
- return (x & (a - 1)) == 0;
-}
-
-
-
-AtlasPacker::AtlasPacker(Atlas * atlas) : m_atlas(atlas), m_bitmap(256, 256)
-{
- m_width = 0;
- m_height = 0;
-
- // -- GODOT start --
- //m_debug_bitmap.allocate(256, 256);
- //m_debug_bitmap.fill(Color32(0,0,0,0));
- // -- GODOT end --
-}
-
-AtlasPacker::~AtlasPacker()
-{
-}
-
-// This should compute convex hull and use rotating calipers to find the best box. Currently it uses a brute force method.
-static bool computeBoundingBox(Chart * chart, Vector2 * majorAxis, Vector2 * minorAxis, Vector2 * minCorner, Vector2 * maxCorner)
-{
- // Compute list of boundary points.
- Array<Vector2> points(16);
-
- HalfEdge::Mesh * mesh = chart->chartMesh();
- const uint vertexCount = mesh->vertexCount();
-
- for (uint i = 0; i < vertexCount; i++) {
- HalfEdge::Vertex * vertex = mesh->vertexAt(i);
- if (vertex->isBoundary()) {
- points.append(vertex->tex);
- }
- }
-
- // This is not valid anymore. The chart mesh may have multiple boundaries!
- /*const HalfEdge::Vertex * vertex = findBoundaryVertex(chart->chartMesh());
-
- // Traverse boundary.
- const HalfEdge::Edge * const firstEdge = vertex->edge();
- const HalfEdge::Edge * edge = firstEdge;
- do {
- vertex = edge->vertex();
-
- nvDebugCheck (vertex->isBoundary());
- points.append(vertex->tex);
-
- edge = edge->next();
- } while (edge != firstEdge);*/
-
-#if 1
- Array<Vector2> hull;
- if (points.size()==0) {
- return false;
- }
-
- convexHull(points, hull, 0.00001f);
-
- // @@ Ideally I should use rotating calipers to find the best box. Using brute force for now.
-
- float best_area = FLT_MAX;
- Vector2 best_min;
- Vector2 best_max;
- Vector2 best_axis;
-
- const uint hullCount = hull.count();
- for (uint i = 0, j = hullCount-1; i < hullCount; j = i, i++) {
-
- if (equal(hull[i], hull[j])) {
- continue;
- }
-
- Vector2 axis = normalize(hull[i] - hull[j], 0.0f);
- nvDebugCheck(isFinite(axis));
-
- // Compute bounding box.
- Vector2 box_min(FLT_MAX, FLT_MAX);
- Vector2 box_max(-FLT_MAX, -FLT_MAX);
-
- for (uint v = 0; v < hullCount; v++) {
-
- Vector2 point = hull[v];
-
- float x = dot(axis, point);
- if (x < box_min.x) box_min.x = x;
- if (x > box_max.x) box_max.x = x;
-
- float y = dot(Vector2(-axis.y, axis.x), point);
- if (y < box_min.y) box_min.y = y;
- if (y > box_max.y) box_max.y = y;
- }
-
- // Compute box area.
- float area = (box_max.x - box_min.x) * (box_max.y - box_min.y);
-
- if (area < best_area) {
- best_area = area;
- best_min = box_min;
- best_max = box_max;
- best_axis = axis;
- }
- }
-
- // Make sure the box contains all the input points since the convex hull is not 100% accurate.
- /*const uint pointCount = points.count();
- for (uint v = 0; v < pointCount; v++) {
-
- Vector2 point = points[v];
-
- float x = dot(best_axis, point);
- if (x < best_min.x) best_min.x = x;
-
- float y = dot(Vector2(-best_axis.y, best_axis.x), point);
- if (y < best_min.y) best_min.y = y;
- }*/
-
- // Consider all points, not only boundary points, in case the input chart is malformed.
- for (uint i = 0; i < vertexCount; i++) {
- HalfEdge::Vertex * vertex = mesh->vertexAt(i);
- Vector2 point = vertex->tex;
-
- float x = dot(best_axis, point);
- if (x < best_min.x) best_min.x = x;
- if (x > best_max.x) best_max.x = x;
-
- float y = dot(Vector2(-best_axis.y, best_axis.x), point);
- if (y < best_min.y) best_min.y = y;
- if (y > best_max.y) best_max.y = y;
- }
-
- *majorAxis = best_axis;
- *minorAxis = Vector2(-best_axis.y, best_axis.x);
- *minCorner = best_min;
- *maxCorner = best_max;
-
-#else
- // Approximate implementation: try 16 different directions and keep the best.
-
- const uint N = 16;
- Vector2 axis[N];
-
- float minAngle = 0;
- float maxAngle = PI / 2;
-
- int best;
- Vector2 mins[N];
- Vector2 maxs[N];
-
- const int iterationCount = 1;
- for (int j = 0; j < iterationCount; j++)
- {
- // Init predefined directions.
- for (int i = 0; i < N; i++)
- {
- float angle = lerp(minAngle, maxAngle, float(i)/N);
- axis[i].set(cosf(angle), sinf(angle));
- }
-
- // Compute box for each direction.
- for (int i = 0; i < N; i++)
- {
- mins[i].set(FLT_MAX, FLT_MAX);
- maxs[i].set(-FLT_MAX, -FLT_MAX);
- }
-
- for (uint p = 0; p < points.count(); p++)
- {
- Vector2 point = points[p];
-
- for (int i = 0; i < N; i++)
- {
- float x = dot(axis[i], point);
- if (x < mins[i].x) mins[i].x = x;
- if (x > maxs[i].x) maxs[i].x = x;
-
- float y = dot(Vector2(-axis[i].y, axis[i].x), point);
- if (y < mins[i].y) mins[i].y = y;
- if (y > maxs[i].y) maxs[i].y = y;
- }
- }
-
- // Find box with minimum area.
- best = -1;
- int second_best = -1;
- float best_area = FLT_MAX;
- float second_best_area = FLT_MAX;
-
- for (int i = 0; i < N; i++)
- {
- float area = (maxs[i].x - mins[i].x) * (maxs[i].y - mins[i].y);
-
- if (area < best_area)
- {
- second_best_area = best_area;
- second_best = best;
-
- best_area = area;
- best = i;
- }
- else if (area < second_best_area)
- {
- second_best_area = area;
- second_best = i;
- }
- }
- nvDebugCheck(best != -1);
- nvDebugCheck(second_best != -1);
- nvDebugCheck(best != second_best);
-
- if (j != iterationCount-1)
- {
- // Handle wrap-around during the first iteration.
- if (j == 0) {
- if (best == 0 && second_best == N-1) best = N;
- if (best == N-1 && second_best == 0) second_best = N;
- }
-
- if (best < second_best) swap(best, second_best);
-
- // Update angles.
- float deltaAngle = (maxAngle - minAngle) / N;
- maxAngle = minAngle + (best - 0.5f) * deltaAngle;
- minAngle = minAngle + (second_best + 0.5f) * deltaAngle;
- }
- }
-
- // Compute major and minor axis, and origin.
- *majorAxis = axis[best];
- *minorAxis = Vector2(-axis[best].y, axis[best].x);
- *origin = mins[best];
-
- // @@ If the parameterization is invalid, we could have an interior vertex outside the boundary.
- // @@ In that case the returned bounding box would be incorrect. Compute updated bounds here.
- /*for (uint p = 0; p < points.count(); p++)
- {
- Vector2 point = points[p];
-
- for (int i = 0; i < N; i++)
- {
- float x = dot(*majorAxis, point);
- float y = dot(*minorAxis, point);
- }
- }*/
-#endif
-
- return true;
-}
-
-
-void AtlasPacker::packCharts(int quality, float texelsPerUnit, bool blockAligned, bool conservative)
-{
- const uint chartCount = m_atlas->chartCount();
- if (chartCount == 0) return;
-
- Array<float> chartOrderArray;
- chartOrderArray.resize(chartCount);
-
- Array<Vector2> chartExtents;
- chartExtents.resize(chartCount);
-
- float meshArea = 0;
- for (uint c = 0; c < chartCount; c++)
- {
- Chart * chart = m_atlas->chartAt(c);
-
- if (!chart->isVertexMapped() && !chart->isDisk()) {
- chartOrderArray[c] = 0;
-
- // Skip non-disks.
- continue;
- }
-
- Vector2 extents(0.0f);
-
- if (chart->isVertexMapped()) {
- // Let's assume vertex maps are arranged in a rectangle.
- //HalfEdge::Mesh * mesh = chart->chartMesh();
-
- // Arrange vertices in a rectangle.
- extents.x = float(chart->vertexMapWidth);
- extents.y = float(chart->vertexMapHeight);
- }
- else {
- // Compute surface area to sort charts.
- float chartArea = chart->computeSurfaceArea();
- meshArea += chartArea;
- //chartOrderArray[c] = chartArea;
-
- // Compute chart scale
- float parametricArea = fabs(chart->computeParametricArea()); // @@ There doesn't seem to be anything preventing parametric area to be negative.
- if (parametricArea < NV_EPSILON) {
- // When the parametric area is too small we use a rough approximation to prevent divisions by very small numbers.
- Vector2 bounds = chart->computeParametricBounds();
- parametricArea = bounds.x * bounds.y;
- }
- float scale = (chartArea / parametricArea) * texelsPerUnit;
- if (parametricArea == 0) // < NV_EPSILON)
- {
- scale = 0;
- }
- nvCheck(isFinite(scale));
-
- // Compute bounding box of chart.
- Vector2 majorAxis, minorAxis, origin, end;
- if (!computeBoundingBox(chart, &majorAxis, &minorAxis, &origin, &end)) {
- m_atlas->setFailed();
- return;
- }
-
- nvCheck(isFinite(majorAxis) && isFinite(minorAxis) && isFinite(origin));
-
- // Sort charts by perimeter. @@ This is sometimes producing somewhat unexpected results. Is this right?
- //chartOrderArray[c] = ((end.x - origin.x) + (end.y - origin.y)) * scale;
-
- // Translate, rotate and scale vertices. Compute extents.
- HalfEdge::Mesh * mesh = chart->chartMesh();
- const uint vertexCount = mesh->vertexCount();
- for (uint i = 0; i < vertexCount; i++)
- {
- HalfEdge::Vertex * vertex = mesh->vertexAt(i);
-
- //Vector2 t = vertex->tex - origin;
- Vector2 tmp;
- tmp.x = dot(vertex->tex, majorAxis);
- tmp.y = dot(vertex->tex, minorAxis);
- tmp -= origin;
- tmp *= scale;
- if (tmp.x < 0 || tmp.y < 0) {
- nvDebug("tmp: %f %f\n", tmp.x, tmp.y);
- nvDebug("scale: %f\n", scale);
- nvDebug("origin: %f %f\n", origin.x, origin.y);
- nvDebug("majorAxis: %f %f\n", majorAxis.x, majorAxis.y);
- nvDebug("minorAxis: %f %f\n", minorAxis.x, minorAxis.y);
- // -- GODOT start --
- //nvDebugBreak();
- m_atlas->setFailed();
- return;
- // -- GODOT end --
- }
- //nvCheck(tmp.x >= 0 && tmp.y >= 0);
-
- vertex->tex = tmp;
-
- nvCheck(isFinite(vertex->tex.x) && isFinite(vertex->tex.y));
-
- extents = max(extents, tmp);
- }
- nvDebugCheck(extents.x >= 0 && extents.y >= 0);
-
- // Limit chart size.
- if (extents.x > 1024 || extents.y > 1024) {
- float limit = max(extents.x, extents.y);
-
- scale = 1024 / (limit + 1);
-
- for (uint i = 0; i < vertexCount; i++)
- {
- HalfEdge::Vertex * vertex = mesh->vertexAt(i);
- vertex->tex *= scale;
- }
-
- extents *= scale;
-
- nvDebugCheck(extents.x <= 1024 && extents.y <= 1024);
- }
-
-
- // Scale the charts to use the entire texel area available. So, if the width is 0.1 we could scale it to 1 without increasing the lightmap usage and making a better
- // use of it. In many cases this also improves the look of the seams, since vertices on the chart boundaries have more chances of being aligned with the texel centers.
-
- float scale_x = 1.0f;
- float scale_y = 1.0f;
-
- float divide_x = 1.0f;
- float divide_y = 1.0f;
-
- if (extents.x > 0) {
- int cw = ftoi_ceil(extents.x);
-
- if (blockAligned) {
- // Align all chart extents to 4x4 blocks, but taking padding into account.
- if (conservative) {
- cw = align(cw + 2, 4) - 2;
- }
- else {
- cw = align(cw + 1, 4) - 1;
- }
- }
-
- scale_x = (float(cw) - NV_EPSILON);
- divide_x = extents.x;
- extents.x = float(cw);
- }
-
- if (extents.y > 0) {
- int ch = ftoi_ceil(extents.y);
-
- if (blockAligned) {
- // Align all chart extents to 4x4 blocks, but taking padding into account.
- if (conservative) {
- ch = align(ch + 2, 4) - 2;
- }
- else {
- ch = align(ch + 1, 4) - 1;
- }
- }
-
- scale_y = (float(ch) - NV_EPSILON);
- divide_y = extents.y;
- extents.y = float(ch);
- }
-
- for (uint v = 0; v < vertexCount; v++) {
- HalfEdge::Vertex * vertex = mesh->vertexAt(v);
-
- vertex->tex.x /= divide_x;
- vertex->tex.y /= divide_y;
- vertex->tex.x *= scale_x;
- vertex->tex.y *= scale_y;
-
- nvCheck(isFinite(vertex->tex.x) && isFinite(vertex->tex.y));
- }
- }
-
- chartExtents[c] = extents;
-
- // Sort charts by perimeter.
- chartOrderArray[c] = extents.x + extents.y;
- }
-
- // @@ We can try to improve compression of small charts by sorting them by proximity like we do with vertex samples.
- // @@ How to do that? One idea: compute chart centroid, insert into grid, compute morton index of the cell, sort based on morton index.
- // @@ We would sort by morton index, first, then quantize the chart sizes, so that all small charts have the same size, and sort by size preserving the morton order.
-
- //nvDebug("Sorting charts.\n");
-
- // Sort charts by area.
- m_radix.sort(chartOrderArray);
- const uint32 * ranks = m_radix.ranks();
-
- // Estimate size of the map based on the mesh surface area and given texel scale.
- float texelCount = meshArea * square(texelsPerUnit) / 0.75f; // Assume 75% utilization.
- if (texelCount < 1) texelCount = 1;
- uint approximateExtent = nextPowerOfTwo(uint(sqrtf(texelCount)));
-
- //nvDebug("Init bitmap.\n");
-
- // @@ Pack all charts smaller than a texel into a compact rectangle.
- // @@ Start considering only 1x1 charts. Extend to 1xn charts later.
-
- /*for (uint i = 0; i < chartCount; i++)
- {
- uint c = ranks[chartCount - i - 1]; // largest chart first
-
- Chart * chart = m_atlas->chartAt(c);
-
- if (!chart->isDisk()) continue;
-
- if (iceil(chartExtents[c].x) == 1 && iceil(chartExtents[c].x) == 1) {
- // @@ Add to
- }
- }*/
-
-
-
- // Init bit map.
- m_bitmap.clearAll();
- if (approximateExtent > m_bitmap.width()) {
- m_bitmap.resize(approximateExtent, approximateExtent, false);
- // -- GODOT start --
- //m_debug_bitmap.resize(approximateExtent, approximateExtent);
- //m_debug_bitmap.fill(Color32(0,0,0,0));
- // -- GODOT end --
- }
-
-
- int w = 0;
- int h = 0;
-
-#if 1
- // Add sorted charts to bitmap.
- for (uint i = 0; i < chartCount; i++)
- {
- uint c = ranks[chartCount - i - 1]; // largest chart first
-
- Chart * chart = m_atlas->chartAt(c);
-
- if (!chart->isVertexMapped() && !chart->isDisk()) continue;
-
- //float scale_x = 1;
- //float scale_y = 1;
-
- BitMap chart_bitmap;
-
- if (chart->isVertexMapped()) {
- // Init all bits to 1.
- chart_bitmap.resize(ftoi_ceil(chartExtents[c].x), ftoi_ceil(chartExtents[c].y), /*initValue=*/true);
-
- // @@ Another alternative would be to try to map each vertex to a different texel trying to fill all the available unused texels.
- }
- else {
- // @@ Add special cases for dot and line charts. @@ Lightmap rasterizer also needs to handle these special cases.
- // @@ We could also have a special case for chart quads. If the quad surface <= 4 texels, align vertices with texel centers and do not add padding. May be very useful for foliage.
-
- // @@ In general we could reduce the padding of all charts by one texel by using a rasterizer that takes into account the 2-texel footprint of the tent bilinear filter. For example,
- // if we have a chart that is less than 1 texel wide currently we add one texel to the left and one texel to the right creating a 3-texel-wide bitmap. However, if we know that the
- // chart is only 1 texel wide we could align it so that it only touches the footprint of two texels:
-
- // | | <- Touches texels 0, 1 and 2.
- // | | <- Only touches texels 0 and 1.
- // \ \ / \ / /
- // \ X X /
- // \ / \ / \ /
- // V V V
- // 0 1 2
-
- if (conservative) {
- // Init all bits to 0.
- chart_bitmap.resize(ftoi_ceil(chartExtents[c].x) + 2, ftoi_ceil(chartExtents[c].y) + 2, /*initValue=*/false); // + 2 to add padding on both sides.
-
- // Rasterize chart and dilate.
- drawChartBitmapDilate(chart, &chart_bitmap, /*padding=*/1);
- }
- else {
- // Init all bits to 0.
- chart_bitmap.resize(ftoi_ceil(chartExtents[c].x) + 1, ftoi_ceil(chartExtents[c].y) + 1, /*initValue=*/false); // Add half a texels on each side.
-
- // Rasterize chart and dilate.
- drawChartBitmap(chart, &chart_bitmap, Vector2(1), Vector2(0.5));
- }
- }
-
- int best_x, best_y;
- int best_cw, best_ch; // Includes padding now.
- int best_r;
- findChartLocation(quality, &chart_bitmap, chartExtents[c], w, h, &best_x, &best_y, &best_cw, &best_ch, &best_r);
-
- /*if (w < best_x + best_cw || h < best_y + best_ch)
- {
- nvDebug("Resize extents to (%d, %d).\n", best_x + best_cw, best_y + best_ch);
- }*/
-
- // Update parametric extents.
- w = max(w, best_x + best_cw);
- h = max(h, best_y + best_ch);
-
- w = align(w, 4);
- h = align(h, 4);
-
- // Resize bitmap if necessary.
- if (uint(w) > m_bitmap.width() || uint(h) > m_bitmap.height())
- {
- //nvDebug("Resize bitmap (%d, %d).\n", nextPowerOfTwo(w), nextPowerOfTwo(h));
- m_bitmap.resize(nextPowerOfTwo(U32(w)), nextPowerOfTwo(U32(h)), false);
- // -- GODOT start --
- //m_debug_bitmap.resize(nextPowerOfTwo(U32(w)), nextPowerOfTwo(U32(h)));
- // -- GODOT end --
- }
-
- //nvDebug("Add chart at (%d, %d).\n", best_x, best_y);
-
- addChart(&chart_bitmap, w, h, best_x, best_y, best_r, /*debugOutput=*/NULL);
-
- // -- GODOT start --
- // IC: Output chart again to debug bitmap.
- /*if (chart->isVertexMapped()) {
- addChart(&chart_bitmap, w, h, best_x, best_y, best_r, &m_debug_bitmap);
- }
- else {
- addChart(chart, w, h, best_x, best_y, best_r, &m_debug_bitmap);
- }*/
- // -- GODOT end --
-
- //float best_angle = 2 * PI * best_r;
-
- // Translate and rotate chart texture coordinates.
- HalfEdge::Mesh * mesh = chart->chartMesh();
- const uint vertexCount = mesh->vertexCount();
- for (uint v = 0; v < vertexCount; v++)
- {
- HalfEdge::Vertex * vertex = mesh->vertexAt(v);
-
- Vector2 t = vertex->tex;
- if (best_r) swap(t.x, t.y);
- //vertex->tex.x = best_x + t.x * cosf(best_angle) - t.y * sinf(best_angle);
- //vertex->tex.y = best_y + t.x * sinf(best_angle) + t.y * cosf(best_angle);
-
- vertex->tex.x = best_x + t.x + 0.5f;
- vertex->tex.y = best_y + t.y + 0.5f;
-
- nvCheck(vertex->tex.x >= 0 && vertex->tex.y >= 0);
- nvCheck(isFinite(vertex->tex.x) && isFinite(vertex->tex.y));
- }
-
-#if DEBUG_OUTPUT && 0
- StringBuilder fileName;
- fileName.format("debug_packer_%d.tga", i);
- //outputDebugBitmap(fileName.str(), m_bitmap, w, h);
- outputDebugImage(fileName.str(), m_debug_bitmap, w, h);
-#endif
- }
-
-#else // 0
-
- // Add sorted charts to bitmap.
- for (uint i = 0; i < chartCount; i++)
- {
- uint c = ranks[chartCount - i - 1]; // largest chart first
-
- Chart * chart = m_atlas->chartAt(c);
-
- if (!chart->isDisk()) continue;
-
- Vector2 scale(1, 1);
-
-#if 0 // old method.
- //m_padding_x = 2*padding;
- //m_padding_y = 2*padding;
-#else
- //m_padding_x = 0; //padding;
- //m_padding_y = 0; //padding;
-#endif
-
- int bw = ftoi_ceil(chartExtents[c].x + 1);
- int bh = ftoi_ceil(chartExtents[c].y + 1);
-
- if (chartExtents[c].x < 1.0f) {
- scale.x = 0.01f; // @@ Ideally we would like to scale it to 0, but then our rasterizer would not touch any pixels.
- bw = 1;
- }
- if (chartExtents[c].y < 1.0f) {
- scale.y = 0.01f;
- bh = 1;
- }
-
- //BitMap chart_bitmap(iceil(chartExtents[c].x) + 1 + m_padding_x * 2, iceil(chartExtents[c].y) + 1 + m_padding_y * 2);
- //BitMap chart_bitmap(ftoi_ceil(chartExtents[c].x/2)*2, ftoi_ceil(chartExtents[c].y/2)*2);
- BitMap chart_bitmap(bw, bh);
- chart_bitmap.clearAll();
-
- Vector2 offset;
- offset.x = 0; // (chart_bitmap.width() - chartExtents[c].x) * 0.5f;
- offset.y = 0; // (chart_bitmap.height() - chartExtents[c].y) * 0.5f;
-
- drawChartBitmap(chart, &chart_bitmap, scale, offset);
-
- int best_x, best_y;
- int best_cw, best_ch;
- int best_r;
- findChartLocation(quality, &chart_bitmap, chartExtents[c], w, h, &best_x, &best_y, &best_cw, &best_ch, &best_r);
-
- /*if (w < best_x + best_cw || h < best_y + best_ch)
- {
- nvDebug("Resize extents to (%d, %d).\n", best_x + best_cw, best_y + best_ch);
- }*/
-
- // Update parametric extents.
- w = max(w, best_x + best_cw);
- h = max(h, best_y + best_ch);
-
- // Resize bitmap if necessary.
- if (uint(w) > m_bitmap.width() || uint(h) > m_bitmap.height())
- {
- //nvDebug("Resize bitmap (%d, %d).\n", nextPowerOfTwo(w), nextPowerOfTwo(h));
- m_bitmap.resize(nextPowerOfTwo(w), nextPowerOfTwo(h), false);
- m_debug_bitmap.resize(nextPowerOfTwo(w), nextPowerOfTwo(h));
- }
-
- //nvDebug("Add chart at (%d, %d).\n", best_x, best_y);
-
-#if 0 // old method.
-#if _DEBUG
- checkCanAddChart(chart, w, h, best_x, best_y, best_r);
-#endif
-
- // Add chart.
- addChart(chart, w, h, best_x, best_y, best_r);
-#else
- // Add chart reusing its bitmap.
- addChart(&chart_bitmap, w, h, best_x, best_y, best_r);
-#endif
-
- //float best_angle = 2 * PI * best_r;
-
- // Translate and rotate chart texture coordinates.
- HalfEdge::Mesh * mesh = chart->chartMesh();
- const uint vertexCount = mesh->vertexCount();
- for (uint v = 0; v < vertexCount; v++)
- {
- HalfEdge::Vertex * vertex = mesh->vertexAt(v);
-
- Vector2 t = vertex->tex * scale + offset;
- if (best_r) swap(t.x, t.y);
- //vertex->tex.x = best_x + t.x * cosf(best_angle) - t.y * sinf(best_angle);
- //vertex->tex.y = best_y + t.x * sinf(best_angle) + t.y * cosf(best_angle);
- vertex->tex.x = best_x + t.x + 0.5f;
- vertex->tex.y = best_y + t.y + 0.5f;
-
- nvCheck(vertex->tex.x >= 0 && vertex->tex.y >= 0);
- }
-
-#if DEBUG_OUTPUT && 0
- StringBuilder fileName;
- fileName.format("debug_packer_%d.tga", i);
- //outputDebugBitmap(fileName.str(), m_bitmap, w, h);
- outputDebugImage(fileName.str(), m_debug_bitmap, w, h);
-#endif
- }
-
-#endif // 0
-
- //w -= padding - 1; // Leave one pixel border!
- //h -= padding - 1;
-
- m_width = max(0, w);
- m_height = max(0, h);
-
- nvCheck(isAligned(m_width, 4));
- nvCheck(isAligned(m_height, 4));
-
- // -- GODOT start --
- //m_debug_bitmap.resize(m_width, m_height);
- //m_debug_bitmap.setFormat(Image::Format_ARGB);
- // -- GODOT end --
-
-#if DEBUG_OUTPUT
- //outputDebugBitmap("debug_packer_final.tga", m_bitmap, w, h);
- //outputDebugImage("debug_packer_final.tga", m_debug_bitmap, w, h);
- ImageIO::save("debug_packer_final.tga", &m_debug_bitmap);
-#endif
-}
-
-
-// IC: Brute force is slow, and random may take too much time to converge. We start inserting large charts in a small atlas. Using brute force is lame, because most of the space
-// is occupied at this point. At the end we have many small charts and a large atlas with sparse holes. Finding those holes randomly is slow. A better approach would be to
-// start stacking large charts as if they were tetris pieces. Once charts get small try to place them randomly. It may be interesting to try a intermediate strategy, first try
-// along one axis and then try exhaustively along that axis.
-void AtlasPacker::findChartLocation(int quality, const BitMap * bitmap, Vector2::Arg extents, int w, int h, int * best_x, int * best_y, int * best_w, int * best_h, int * best_r)
-{
- int attempts = 256;
- if (quality == 1) attempts = 4096;
- if (quality == 2) attempts = 2048;
- if (quality == 3) attempts = 1024;
- if (quality == 4) attempts = 512;
-
- if (quality == 0 || w*h < attempts)
- {
- findChartLocation_bruteForce(bitmap, extents, w, h, best_x, best_y, best_w, best_h, best_r);
- }
- else
- {
- findChartLocation_random(bitmap, extents, w, h, best_x, best_y, best_w, best_h, best_r, attempts);
- }
-}
-
-#define BLOCK_SIZE 4
-
-void AtlasPacker::findChartLocation_bruteForce(const BitMap * bitmap, Vector2::Arg extents, int w, int h, int * best_x, int * best_y, int * best_w, int * best_h, int * best_r)
-{
- int best_metric = INT_MAX;
-
- // Try two different orientations.
- for (int r = 0; r < 2; r++)
- {
- int cw = bitmap->width();
- int ch = bitmap->height();
- if (r & 1) swap(cw, ch);
-
- for (int y = 0; y <= h + 1; y += BLOCK_SIZE) // + 1 to extend atlas in case atlas full.
- {
- for (int x = 0; x <= w + 1; x += BLOCK_SIZE) // + 1 not really necessary here.
- {
- // Early out.
- int area = max(w, x+cw) * max(h, y+ch);
- //int perimeter = max(w, x+cw) + max(h, y+ch);
- int extents = max(max(w, x+cw), max(h, y+ch));
-
- int metric = extents*extents + area;
-
- if (metric > best_metric) {
- continue;
- }
- if (metric == best_metric && max(x, y) >= max(*best_x, *best_y)) {
- // If metric is the same, pick the one closest to the origin.
- continue;
- }
-
- if (canAddChart(bitmap, w, h, x, y, r))
- {
- best_metric = metric;
- *best_x = x;
- *best_y = y;
- *best_w = cw;
- *best_h = ch;
- *best_r = r;
-
- if (area == w*h)
- {
- // Chart is completely inside, do not look at any other location.
- goto done;
- }
- }
- }
- }
- }
-
-done:
- nvDebugCheck (best_metric != INT_MAX);
-}
-
-
-void AtlasPacker::findChartLocation_random(const BitMap * bitmap, Vector2::Arg extents, int w, int h, int * best_x, int * best_y, int * best_w, int * best_h, int * best_r, int minTrialCount)
-{
- int best_metric = INT_MAX;
-
- for (int i = 0; i < minTrialCount || best_metric == INT_MAX; i++)
- {
- int r = m_rand.getRange(1);
- int x = m_rand.getRange(w + 1); // + 1 to extend atlas in case atlas full. We may want to use a higher number to increase probability of extending atlas.
- int y = m_rand.getRange(h + 1); // + 1 to extend atlas in case atlas full.
-
- x = align(x, BLOCK_SIZE);
- y = align(y, BLOCK_SIZE);
-
- int cw = bitmap->width();
- int ch = bitmap->height();
- if (r & 1) swap(cw, ch);
-
- // Early out.
- int area = max(w, x+cw) * max(h, y+ch);
- //int perimeter = max(w, x+cw) + max(h, y+ch);
- int extents = max(max(w, x+cw), max(h, y+ch));
-
- int metric = extents*extents + area;
-
- if (metric > best_metric) {
- continue;
- }
- if (metric == best_metric && min(x, y) > min(*best_x, *best_y)) {
- // If metric is the same, pick the one closest to the origin.
- continue;
- }
-
- if (canAddChart(bitmap, w, h, x, y, r))
- {
- best_metric = metric;
- *best_x = x;
- *best_y = y;
- *best_w = cw;
- *best_h = ch;
- *best_r = r;
-
- if (area == w*h)
- {
- // Chart is completely inside, do not look at any other location.
- break;
- }
- }
- }
-}
-
-
-void AtlasPacker::drawChartBitmapDilate(const Chart * chart, BitMap * bitmap, int padding)
-{
- const int w = bitmap->width();
- const int h = bitmap->height();
- const Vector2 extents = Vector2(float(w), float(h));
-
- // Rasterize chart faces, check that all bits are not set.
- const uint faceCount = chart->faceCount();
- for (uint f = 0; f < faceCount; f++)
- {
- const HalfEdge::Face * face = chart->chartMesh()->faceAt(f);
-
- Vector2 vertices[4];
-
- uint edgeCount = 0;
- for (HalfEdge::Face::ConstEdgeIterator it(face->edges()); !it.isDone(); it.advance())
- {
- if (edgeCount < 4)
- {
- vertices[edgeCount] = it.vertex()->tex + Vector2(0.5) + Vector2(float(padding), float(padding));
- }
- edgeCount++;
- }
-
- if (edgeCount == 3)
- {
- Raster::drawTriangle(Raster::Mode_Antialiased, extents, true, vertices, AtlasPacker::setBitsCallback, bitmap);
- }
- else
- {
- Raster::drawQuad(Raster::Mode_Antialiased, extents, true, vertices, AtlasPacker::setBitsCallback, bitmap);
- }
- }
-
- // Expand chart by padding pixels. (dilation)
- BitMap tmp(w, h);
- for (int i = 0; i < padding; i++) {
- tmp.clearAll();
-
- for (int y = 0; y < h; y++) {
- for (int x = 0; x < w; x++) {
- bool b = bitmap->bitAt(x, y);
- if (!b) {
- if (x > 0) {
- b |= bitmap->bitAt(x - 1, y);
- if (y > 0) b |= bitmap->bitAt(x - 1, y - 1);
- if (y < h-1) b |= bitmap->bitAt(x - 1, y + 1);
- }
- if (y > 0) b |= bitmap->bitAt(x, y - 1);
- if (y < h-1) b |= bitmap->bitAt(x, y + 1);
- if (x < w-1) {
- b |= bitmap->bitAt(x + 1, y);
- if (y > 0) b |= bitmap->bitAt(x + 1, y - 1);
- if (y < h-1) b |= bitmap->bitAt(x + 1, y + 1);
- }
- }
- if (b) tmp.setBitAt(x, y);
- }
- }
-
- swap(tmp, *bitmap);
- }
-}
-
-
-void AtlasPacker::drawChartBitmap(const Chart * chart, BitMap * bitmap, const Vector2 & scale, const Vector2 & offset)
-{
- const int w = bitmap->width();
- const int h = bitmap->height();
- const Vector2 extents = Vector2(float(w), float(h));
-
- static const Vector2 pad[4] = {
- Vector2(-0.5, -0.5),
- Vector2(0.5, -0.5),
- Vector2(-0.5, 0.5),
- Vector2(0.5, 0.5)
- };
- /*static const Vector2 pad[4] = {
- Vector2(-1, -1),
- Vector2(1, -1),
- Vector2(-1, 1),
- Vector2(1, 1)
- };*/
-
- // Rasterize 4 times to add proper padding.
- for (int i = 0; i < 4; i++) {
-
- // Rasterize chart faces, check that all bits are not set.
- const uint faceCount = chart->chartMesh()->faceCount();
- for (uint f = 0; f < faceCount; f++)
- {
- const HalfEdge::Face * face = chart->chartMesh()->faceAt(f);
-
- Vector2 vertices[4];
-
- uint edgeCount = 0;
- for (HalfEdge::Face::ConstEdgeIterator it(face->edges()); !it.isDone(); it.advance())
- {
- if (edgeCount < 4)
- {
- vertices[edgeCount] = it.vertex()->tex * scale + offset + pad[i];
- nvCheck(ftoi_ceil(vertices[edgeCount].x) >= 0);
- nvCheck(ftoi_ceil(vertices[edgeCount].y) >= 0);
- nvCheck(ftoi_ceil(vertices[edgeCount].x) <= w);
- nvCheck(ftoi_ceil(vertices[edgeCount].y) <= h);
- }
- edgeCount++;
- }
-
- if (edgeCount == 3)
- {
- Raster::drawTriangle(Raster::Mode_Antialiased, extents, /*enableScissors=*/true, vertices, AtlasPacker::setBitsCallback, bitmap);
- }
- else
- {
- Raster::drawQuad(Raster::Mode_Antialiased, extents, /*enableScissors=*/true, vertices, AtlasPacker::setBitsCallback, bitmap);
- }
- }
- }
-
- // @@ This only allows us to expand the size in texel intervals.
- /*if (m_padding_x != 0 && m_padding_y != 0)*/ {
-
- // Expand chart by padding pixels. (dilation)
- BitMap tmp(w, h);
- //for (int i = 0; i < 1; i++) {
- tmp.clearAll();
-
- for (int y = 0; y < h; y++) {
- for (int x = 0; x < w; x++) {
- bool b = bitmap->bitAt(x, y);
- if (!b) {
- if (x > 0) {
- b |= bitmap->bitAt(x - 1, y);
- if (y > 0) b |= bitmap->bitAt(x - 1, y - 1);
- if (y < h-1) b |= bitmap->bitAt(x - 1, y + 1);
- }
- if (y > 0) b |= bitmap->bitAt(x, y - 1);
- if (y < h-1) b |= bitmap->bitAt(x, y + 1);
- if (x < w-1) {
- b |= bitmap->bitAt(x + 1, y);
- if (y > 0) b |= bitmap->bitAt(x + 1, y - 1);
- if (y < h-1) b |= bitmap->bitAt(x + 1, y + 1);
- }
- }
- if (b) tmp.setBitAt(x, y);
- }
- }
-
- swap(tmp, *bitmap);
- //}
- }
-}
-
-bool AtlasPacker::canAddChart(const BitMap * bitmap, int atlas_w, int atlas_h, int offset_x, int offset_y, int r)
-{
- nvDebugCheck(r == 0 || r == 1);
-
- // Check whether the two bitmaps overlap.
-
- const int w = bitmap->width();
- const int h = bitmap->height();
-
- if (r == 0) {
- for (int y = 0; y < h; y++) {
- int yy = y + offset_y;
- if (yy >= 0) {
- for (int x = 0; x < w; x++) {
- int xx = x + offset_x;
- if (xx >= 0) {
- if (bitmap->bitAt(x, y)) {
- if (xx < atlas_w && yy < atlas_h) {
- if (m_bitmap.bitAt(xx, yy)) return false;
- }
- }
- }
- }
- }
- }
- }
- else if (r == 1) {
- for (int y = 0; y < h; y++) {
- int xx = y + offset_x;
- if (xx >= 0) {
- for (int x = 0; x < w; x++) {
- int yy = x + offset_y;
- if (yy >= 0) {
- if (bitmap->bitAt(x, y)) {
- if (xx < atlas_w && yy < atlas_h) {
- if (m_bitmap.bitAt(xx, yy)) return false;
- }
- }
- }
- }
- }
- }
- }
-
- return true;
-}
-
-#if 0
-void AtlasPacker::checkCanAddChart(const Chart * chart, int w, int h, int x, int y, int r)
-{
- nvDebugCheck(r == 0 || r == 1);
- Vector2 extents = Vector2(float(w), float(h));
- Vector2 offset = Vector2(float(x), float(y));
-
- // Rasterize chart faces, set bits.
- const uint faceCount = chart->faceCount();
- for (uint f = 0; f < faceCount; f++)
- {
- const HalfEdge::Face * face = chart->chartMesh()->faceAt(f);
-
- Vector2 vertices[4];
-
- uint edgeCount = 0;
- for (HalfEdge::Face::ConstEdgeIterator it(face->edges()); !it.isDone(); it.advance())
- {
- if (edgeCount < 4)
- {
- Vector2 t = it.vertex()->tex;
- if (r == 1) swap(t.x, t.y);
- vertices[edgeCount] = t + offset;
- }
- edgeCount++;
- }
-
- if (edgeCount == 3)
- {
- Raster::drawTriangle(Raster::Mode_Antialiased, extents, /*enableScissors=*/true, vertices, AtlasPacker::checkBitsCallback, &m_bitmap);
- }
- else
- {
- Raster::drawQuad(Raster::Mode_Antialiased, extents, /*enableScissors=*/true, vertices, AtlasPacker::checkBitsCallback, &m_bitmap);
- }
- }
-}
-#endif // 0
-
-
-static Color32 chartColor = Color32(0);
-static void selectRandomColor(MTRand & rand) {
- // Pick random color for this chart. @@ Select random hue, but fixed saturation/luminance?
- chartColor.r = 128 + rand.getRange(127);
- chartColor.g = 128 + rand.getRange(127);
- chartColor.b = 128 + rand.getRange(127);
- chartColor.a = 255;
-}
-static bool debugDrawCallback(void * param, int x, int y, Vector3::Arg, Vector3::Arg, Vector3::Arg, float area)
-{
- Image * image = (Image *)param;
-
- if (area > 0.0) {
- Color32 c = image->pixel(x, y);
- c.r = chartColor.r;
- c.g = chartColor.g;
- c.b = chartColor.b;
- c.a += U8(ftoi_round(0.5f * area * 255));
- image->pixel(x, y) = c;
- }
-
- return true;
-}
-
-void AtlasPacker::addChart(const Chart * chart, int w, int h, int x, int y, int r, Image * debugOutput)
-{
- nvDebugCheck(r == 0 || r == 1);
-
- nvDebugCheck(debugOutput != NULL);
- selectRandomColor(m_rand);
-
- Vector2 extents = Vector2(float(w), float(h));
- Vector2 offset = Vector2(float(x), float(y)) + Vector2(0.5);
-
- // Rasterize chart faces, set bits.
- const uint faceCount = chart->faceCount();
- for (uint f = 0; f < faceCount; f++)
- {
- const HalfEdge::Face * face = chart->chartMesh()->faceAt(f);
-
- Vector2 vertices[4];
-
- uint edgeCount = 0;
- for (HalfEdge::Face::ConstEdgeIterator it(face->edges()); !it.isDone(); it.advance())
- {
- if (edgeCount < 4)
- {
- Vector2 t = it.vertex()->tex;
- if (r == 1) swap(t.x, t.y);
- vertices[edgeCount] = t + offset;
- }
- edgeCount++;
- }
-
- if (edgeCount == 3)
- {
- Raster::drawTriangle(Raster::Mode_Antialiased, extents, /*enableScissors=*/true, vertices, debugDrawCallback, debugOutput);
- }
- else
- {
- Raster::drawQuad(Raster::Mode_Antialiased, extents, /*enableScissors=*/true, vertices, debugDrawCallback, debugOutput);
- }
- }
-}
-
-
-void AtlasPacker::addChart(const BitMap * bitmap, int atlas_w, int atlas_h, int offset_x, int offset_y, int r, Image * debugOutput)
-{
- nvDebugCheck(r == 0 || r == 1);
-
- // Check whether the two bitmaps overlap.
-
- const int w = bitmap->width();
- const int h = bitmap->height();
-
- if (debugOutput != NULL) {
- selectRandomColor(m_rand);
- }
-
- if (r == 0) {
- for (int y = 0; y < h; y++) {
- int yy = y + offset_y;
- if (yy >= 0) {
- for (int x = 0; x < w; x++) {
- int xx = x + offset_x;
- if (xx >= 0) {
- if (bitmap->bitAt(x, y)) {
- if (xx < atlas_w && yy < atlas_h) {
- if (debugOutput) debugOutput->pixel(xx, yy) = chartColor;
- else {
- nvDebugCheck(m_bitmap.bitAt(xx, yy) == false);
- m_bitmap.setBitAt(xx, yy);
- }
- }
- }
- }
- }
- }
- }
- }
- else if (r == 1) {
- for (int y = 0; y < h; y++) {
- int xx = y + offset_x;
- if (xx >= 0) {
- for (int x = 0; x < w; x++) {
- int yy = x + offset_y;
- if (yy >= 0) {
- if (bitmap->bitAt(x, y)) {
- if (xx < atlas_w && yy < atlas_h) {
- if (debugOutput) debugOutput->pixel(xx, yy) = chartColor;
- else {
- nvDebugCheck(m_bitmap.bitAt(xx, yy) == false);
- m_bitmap.setBitAt(xx, yy);
- }
- }
- }
- }
- }
- }
- }
- }
-}
-
-
-
-/*static*/ bool AtlasPacker::checkBitsCallback(void * param, int x, int y, Vector3::Arg, Vector3::Arg, Vector3::Arg, float)
-{
- BitMap * bitmap = (BitMap * )param;
-
- nvDebugCheck(bitmap->bitAt(x, y) == false);
-
- return true;
-}
-
-/*static*/ bool AtlasPacker::setBitsCallback(void * param, int x, int y, Vector3::Arg, Vector3::Arg, Vector3::Arg, float area)
-{
- BitMap * bitmap = (BitMap * )param;
-
- if (area > 0.0) {
- bitmap->setBitAt(x, y);
- }
-
- return true;
-}
-
-
-
-float AtlasPacker::computeAtlasUtilization() const {
- const uint w = m_width;
- const uint h = m_height;
- nvDebugCheck(w <= m_bitmap.width());
- nvDebugCheck(h <= m_bitmap.height());
-
- uint count = 0;
- for (uint y = 0; y < h; y++) {
- for (uint x = 0; x < w; x++) {
- count += m_bitmap.bitAt(x, y);
- }
- }
-
- return float(count) / (w * h);
-}
diff --git a/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.h b/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.h
deleted file mode 100644
index 845dbfb6f3..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.h
+++ /dev/null
@@ -1,65 +0,0 @@
-// This code is in the public domain -- castano@gmail.com
-
-#pragma once
-#ifndef NV_MESH_ATLASPACKER_H
-#define NV_MESH_ATLASPACKER_H
-
-#include "nvcore/RadixSort.h"
-#include "nvmath/Vector.h"
-#include "nvmath/Random.h"
-#include "nvimage/BitMap.h"
-#include "nvimage/Image.h"
-
-#include "nvmesh/nvmesh.h"
-
-
-namespace nv
-{
- class Atlas;
- class Chart;
-
- struct AtlasPacker
- {
- AtlasPacker(Atlas * atlas);
- ~AtlasPacker();
-
- void packCharts(int quality, float texelArea, bool blockAligned, bool conservative);
- float computeAtlasUtilization() const;
-
- private:
-
- void findChartLocation(int quality, const BitMap * bitmap, Vector2::Arg extents, int w, int h, int * best_x, int * best_y, int * best_w, int * best_h, int * best_r);
- void findChartLocation_bruteForce(const BitMap * bitmap, Vector2::Arg extents, int w, int h, int * best_x, int * best_y, int * best_w, int * best_h, int * best_r);
- void findChartLocation_random(const BitMap * bitmap, Vector2::Arg extents, int w, int h, int * best_x, int * best_y, int * best_w, int * best_h, int * best_r, int minTrialCount);
-
- void drawChartBitmapDilate(const Chart * chart, BitMap * bitmap, int padding);
- void drawChartBitmap(const Chart * chart, BitMap * bitmap, const Vector2 & scale, const Vector2 & offset);
-
- bool canAddChart(const BitMap * bitmap, int w, int h, int x, int y, int r);
- void addChart(const BitMap * bitmap, int w, int h, int x, int y, int r, Image * debugOutput);
- //void checkCanAddChart(const Chart * chart, int w, int h, int x, int y, int r);
- void addChart(const Chart * chart, int w, int h, int x, int y, int r, Image * debugOutput);
-
-
- static bool checkBitsCallback(void * param, int x, int y, Vector3::Arg bar, Vector3::Arg dx, Vector3::Arg dy, float coverage);
- static bool setBitsCallback(void * param, int x, int y, Vector3::Arg bar, Vector3::Arg dx, Vector3::Arg dy, float coverage);
-
- private:
-
- Atlas * m_atlas;
- BitMap m_bitmap;
- // -- GODOT start --
- //Image m_debug_bitmap;
- // -- GODOT end --
- RadixSort m_radix;
-
- uint m_width;
- uint m_height;
-
- MTRand m_rand;
-
- };
-
-} // nv namespace
-
-#endif // NV_MESH_ATLASPACKER_H
diff --git a/thirdparty/thekla_atlas/nvmesh/param/LeastSquaresConformalMap.cpp b/thirdparty/thekla_atlas/nvmesh/param/LeastSquaresConformalMap.cpp
deleted file mode 100644
index cd1e8bbb7b..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/param/LeastSquaresConformalMap.cpp
+++ /dev/null
@@ -1,483 +0,0 @@
-// Copyright NVIDIA Corporation 2008 -- Ignacio Castano <icastano@nvidia.com>
-
-#include "nvmesh.h" // pch
-
-#include "LeastSquaresConformalMap.h"
-#include "ParameterizationQuality.h"
-#include "Util.h"
-
-#include "nvmesh/halfedge/Mesh.h"
-#include "nvmesh/halfedge/Vertex.h"
-#include "nvmesh/halfedge/Face.h"
-
-#include "nvmath/Sparse.h"
-#include "nvmath/Solver.h"
-#include "nvmath/Vector.inl"
-
-#include "nvcore/Array.inl"
-
-
-using namespace nv;
-using namespace HalfEdge;
-
-namespace
-{
-
- // Test all pairs of vertices in the boundary and check distance.
- static void findDiameterVertices(HalfEdge::Mesh * mesh, HalfEdge::Vertex ** a, HalfEdge::Vertex ** b)
- {
- nvDebugCheck(mesh != NULL);
- nvDebugCheck(a != NULL);
- nvDebugCheck(b != NULL);
-
- const uint vertexCount = mesh->vertexCount();
-
- float maxLength = 0.0f;
-
- for (uint v0 = 1; v0 < vertexCount; v0++)
- {
- HalfEdge::Vertex * vertex0 = mesh->vertexAt(v0);
- nvDebugCheck(vertex0 != NULL);
-
- if (!vertex0->isBoundary()) continue;
-
- for (uint v1 = 0; v1 < v0; v1++)
- {
- HalfEdge::Vertex * vertex1 = mesh->vertexAt(v1);
- nvDebugCheck(vertex1 != NULL);
-
- if (!vertex1->isBoundary()) continue;
-
- float len = length(vertex0->pos - vertex1->pos);
-
- if (len > maxLength)
- {
- maxLength = len;
-
- *a = vertex0;
- *b = vertex1;
- }
- }
- }
-
- nvDebugCheck(*a != NULL && *b != NULL);
- }
-
- // Fast sweep in 3 directions
- static bool findApproximateDiameterVertices(HalfEdge::Mesh * mesh, HalfEdge::Vertex ** a, HalfEdge::Vertex ** b)
- {
- nvDebugCheck(mesh != NULL);
- nvDebugCheck(a != NULL);
- nvDebugCheck(b != NULL);
-
- const uint vertexCount = mesh->vertexCount();
-
- HalfEdge::Vertex * minVertex[3];
- HalfEdge::Vertex * maxVertex[3];
-
- minVertex[0] = minVertex[1] = minVertex[2] = NULL;
- maxVertex[0] = maxVertex[1] = maxVertex[2] = NULL;
-
- for (uint v = 1; v < vertexCount; v++)
- {
- HalfEdge::Vertex * vertex = mesh->vertexAt(v);
- nvDebugCheck(vertex != NULL);
-
- if (vertex->isBoundary())
- {
- minVertex[0] = minVertex[1] = minVertex[2] = vertex;
- maxVertex[0] = maxVertex[1] = maxVertex[2] = vertex;
- break;
- }
- }
-
- if (minVertex[0] == NULL)
- {
- // Input mesh has not boundaries.
- return false;
- }
-
- for (uint v = 1; v < vertexCount; v++)
- {
- HalfEdge::Vertex * vertex = mesh->vertexAt(v);
- nvDebugCheck(vertex != NULL);
-
- if (!vertex->isBoundary())
- {
- // Skip interior vertices.
- continue;
- }
-
- if (vertex->pos.x < minVertex[0]->pos.x) minVertex[0] = vertex;
- else if (vertex->pos.x > maxVertex[0]->pos.x) maxVertex[0] = vertex;
-
- if (vertex->pos.y < minVertex[1]->pos.y) minVertex[1] = vertex;
- else if (vertex->pos.y > maxVertex[1]->pos.y) maxVertex[1] = vertex;
-
- if (vertex->pos.z < minVertex[2]->pos.z) minVertex[2] = vertex;
- else if (vertex->pos.z > maxVertex[2]->pos.z) maxVertex[2] = vertex;
- }
-
- float lengths[3];
- for (int i = 0; i < 3; i++)
- {
- lengths[i] = length(minVertex[i]->pos - maxVertex[i]->pos);
- }
-
- if (lengths[0] > lengths[1] && lengths[0] > lengths[2])
- {
- *a = minVertex[0];
- *b = maxVertex[0];
- }
- else if (lengths[1] > lengths[2])
- {
- *a = minVertex[1];
- *b = maxVertex[1];
- }
- else
- {
- *a = minVertex[2];
- *b = maxVertex[2];
- }
-
- return true;
- }
-
- // Conformal relations from Bruno Levy:
-
- // Computes the coordinates of the vertices of a triangle
- // in a local 2D orthonormal basis of the triangle's plane.
- static void project_triangle(Vector3::Arg p0, Vector3::Arg p1, Vector3::Arg p2, Vector2 * z0, Vector2 * z1, Vector2 * z2)
- {
- Vector3 X = normalize(p1 - p0, 0.0f);
- Vector3 Z = normalize(cross(X, (p2 - p0)), 0.0f);
- Vector3 Y = normalize(cross(Z, X), 0.0f);
-
- float x0 = 0.0f;
- float y0 = 0.0f;
- float x1 = length(p1 - p0);
- float y1 = 0.0f;
- float x2 = dot((p2 - p0), X);
- float y2 = dot((p2 - p0), Y);
-
- *z0 = Vector2(x0, y0);
- *z1 = Vector2(x1, y1);
- *z2 = Vector2(x2, y2);
- }
-
- // LSCM equation, geometric form :
- // (Z1 - Z0)(U2 - U0) = (Z2 - Z0)(U1 - U0)
- // Where Uk = uk + i.vk is the complex number
- // corresponding to (u,v) coords
- // Zk = xk + i.yk is the complex number
- // corresponding to local (x,y) coords
- // cool: no divide with this expression,
- // makes it more numerically stable in
- // the presence of degenerate triangles.
-
- static void setup_conformal_map_relations(SparseMatrix & A, int row, const HalfEdge::Vertex * v0, const HalfEdge::Vertex * v1, const HalfEdge::Vertex * v2)
- {
- int id0 = v0->id;
- int id1 = v1->id;
- int id2 = v2->id;
-
- Vector3 p0 = v0->pos;
- Vector3 p1 = v1->pos;
- Vector3 p2 = v2->pos;
-
- Vector2 z0, z1, z2;
- project_triangle(p0, p1, p2, &z0, &z1, &z2);
-
- Vector2 z01 = z1 - z0;
- Vector2 z02 = z2 - z0;
-
- float a = z01.x;
- float b = z01.y;
- float c = z02.x;
- float d = z02.y;
- nvCheck(b == 0.0f);
-
- // Note : 2*id + 0 --> u
- // 2*id + 1 --> v
- int u0_id = 2 * id0 + 0;
- int v0_id = 2 * id0 + 1;
- int u1_id = 2 * id1 + 0;
- int v1_id = 2 * id1 + 1;
- int u2_id = 2 * id2 + 0;
- int v2_id = 2 * id2 + 1;
-
- // Note : b = 0
-
- // Real part
- A.setCoefficient(u0_id, 2 * row + 0, -a+c);
- A.setCoefficient(v0_id, 2 * row + 0, b-d);
- A.setCoefficient(u1_id, 2 * row + 0, -c);
- A.setCoefficient(v1_id, 2 * row + 0, d);
- A.setCoefficient(u2_id, 2 * row + 0, a);
-
- // Imaginary part
- A.setCoefficient(u0_id, 2 * row + 1, -b+d);
- A.setCoefficient(v0_id, 2 * row + 1, -a+c);
- A.setCoefficient(u1_id, 2 * row + 1, -d);
- A.setCoefficient(v1_id, 2 * row + 1, -c);
- A.setCoefficient(v2_id, 2 * row + 1, a);
- }
-
-
- // Conformal relations from Brecht Van Lommel (based on ABF):
-
- static float vec_angle_cos(Vector3::Arg v1, Vector3::Arg v2, Vector3::Arg v3)
- {
- Vector3 d1 = v1 - v2;
- Vector3 d2 = v3 - v2;
- return clamp(dot(d1, d2) / (length(d1) * length(d2)), -1.0f, 1.0f);
- }
-
- static float vec_angle(Vector3::Arg v1, Vector3::Arg v2, Vector3::Arg v3)
- {
- float dot = vec_angle_cos(v1, v2, v3);
- return acosf(dot);
- }
-
- static void triangle_angles(Vector3::Arg v1, Vector3::Arg v2, Vector3::Arg v3, float *a1, float *a2, float *a3)
- {
- *a1 = vec_angle(v3, v1, v2);
- *a2 = vec_angle(v1, v2, v3);
- *a3 = PI - *a2 - *a1;
- }
-
- static void triangle_cosines(Vector3::Arg v1, Vector3::Arg v2, Vector3::Arg v3, float *a1, float *a2, float *a3)
- {
- *a1 = vec_angle_cos(v3, v1, v2);
- *a2 = vec_angle_cos(v1, v2, v3);
- *a3 = vec_angle_cos(v2, v3, v1);
- }
-
- static void setup_abf_relations(SparseMatrix & A, int row, const HalfEdge::Vertex * v0, const HalfEdge::Vertex * v1, const HalfEdge::Vertex * v2)
- {
- int id0 = v0->id;
- int id1 = v1->id;
- int id2 = v2->id;
-
- Vector3 p0 = v0->pos;
- Vector3 p1 = v1->pos;
- Vector3 p2 = v2->pos;
-
-#if 1
- // @@ IC: Wouldn't it be more accurate to return cos and compute 1-cos^2?
- // It does indeed seem to be a little bit more robust.
- // @@ Need to revisit this more carefully!
-
- float a0, a1, a2;
- triangle_angles(p0, p1, p2, &a0, &a1, &a2);
-
- float s0 = sinf(a0);
- float s1 = sinf(a1);
- float s2 = sinf(a2);
-
- /*// Hack for degenerate triangles.
- if (equal(s0, 0) && equal(s1, 0) && equal(s2, 0)) {
- if (equal(a0, 0)) a0 += 0.001f;
- if (equal(a1, 0)) a1 += 0.001f;
- if (equal(a2, 0)) a2 += 0.001f;
-
- if (equal(a0, PI)) a0 = PI - a1 - a2;
- if (equal(a1, PI)) a1 = PI - a0 - a2;
- if (equal(a2, PI)) a2 = PI - a0 - a1;
-
- s0 = sinf(a0);
- s1 = sinf(a1);
- s2 = sinf(a2);
- }*/
-
- if (s1 > s0 && s1 > s2)
- {
- swap(s1, s2);
- swap(s0, s1);
-
- swap(a1, a2);
- swap(a0, a1);
-
- swap(id1, id2);
- swap(id0, id1);
- }
- else if (s0 > s1 && s0 > s2)
- {
- swap(s0, s2);
- swap(s0, s1);
-
- swap(a0, a2);
- swap(a0, a1);
-
- swap(id0, id2);
- swap(id0, id1);
- }
-
- float c0 = cosf(a0);
-#else
- float c0, c1, c2;
- triangle_cosines(p0, p1, p2, &c0, &c1, &c2);
-
- float s0 = 1 - c0*c0;
- float s1 = 1 - c1*c1;
- float s2 = 1 - c2*c2;
-
- nvDebugCheck(s0 != 0 || s1 != 0 || s2 != 0);
-
- if (s1 > s0 && s1 > s2)
- {
- swap(s1, s2);
- swap(s0, s1);
-
- swap(c1, c2);
- swap(c0, c1);
-
- swap(id1, id2);
- swap(id0, id1);
- }
- else if (s0 > s1 && s0 > s2)
- {
- swap(s0, s2);
- swap(s0, s1);
-
- swap(c0, c2);
- swap(c0, c1);
-
- swap(id0, id2);
- swap(id0, id1);
- }
-#endif
-
- float ratio = (s2 == 0.0f) ? 1.0f: s1/s2;
- float cosine = c0 * ratio;
- float sine = s0 * ratio;
-
- // Note : 2*id + 0 --> u
- // 2*id + 1 --> v
- int u0_id = 2 * id0 + 0;
- int v0_id = 2 * id0 + 1;
- int u1_id = 2 * id1 + 0;
- int v1_id = 2 * id1 + 1;
- int u2_id = 2 * id2 + 0;
- int v2_id = 2 * id2 + 1;
-
- // Real part
- A.setCoefficient(u0_id, 2 * row + 0, cosine - 1.0f);
- A.setCoefficient(v0_id, 2 * row + 0, -sine);
- A.setCoefficient(u1_id, 2 * row + 0, -cosine);
- A.setCoefficient(v1_id, 2 * row + 0, sine);
- A.setCoefficient(u2_id, 2 * row + 0, 1);
-
- // Imaginary part
- A.setCoefficient(u0_id, 2 * row + 1, sine);
- A.setCoefficient(v0_id, 2 * row + 1, cosine - 1.0f);
- A.setCoefficient(u1_id, 2 * row + 1, -sine);
- A.setCoefficient(v1_id, 2 * row + 1, -cosine);
- A.setCoefficient(v2_id, 2 * row + 1, 1);
- }
-
-} // namespace
-
-
-bool nv::computeLeastSquaresConformalMap(HalfEdge::Mesh * mesh)
-{
- nvDebugCheck(mesh != NULL);
-
- // For this to work properly, mesh should not have colocals that have the same
- // attributes, unless you want the vertices to actually have different texcoords.
-
- const uint vertexCount = mesh->vertexCount();
- const uint D = 2 * vertexCount;
- const uint N = 2 * countMeshTriangles(mesh);
-
- // N is the number of equations (one per triangle)
- // D is the number of variables (one per vertex; there are 2 pinned vertices).
- if (N < D - 4) {
- return false;
- }
-
- SparseMatrix A(D, N);
- FullVector b(N);
- FullVector x(D);
-
- // Fill b:
- b.fill(0.0f);
-
- // Fill x:
- HalfEdge::Vertex * v0;
- HalfEdge::Vertex * v1;
- if (!findApproximateDiameterVertices(mesh, &v0, &v1))
- {
- // Mesh has no boundaries.
- return false;
- }
- if (v0->tex == v1->tex)
- {
- // LSCM expects an existing parameterization.
- return false;
- }
-
- for (uint v = 0; v < vertexCount; v++)
- {
- HalfEdge::Vertex * vertex = mesh->vertexAt(v);
- nvDebugCheck(vertex != NULL);
-
- // Initial solution.
- x[2 * v + 0] = vertex->tex.x;
- x[2 * v + 1] = vertex->tex.y;
- }
-
- // Fill A:
- const uint faceCount = mesh->faceCount();
- for (uint f = 0, t = 0; f < faceCount; f++)
- {
- const HalfEdge::Face * face = mesh->faceAt(f);
- nvDebugCheck(face != NULL);
- nvDebugCheck(face->edgeCount() == 3);
-
- const HalfEdge::Vertex * vertex0 = NULL;
-
- for (HalfEdge::Face::ConstEdgeIterator it(face->edges()); !it.isDone(); it.advance())
- {
- const HalfEdge::Edge * edge = it.current();
- nvCheck(edge != NULL);
-
- if (vertex0 == NULL)
- {
- vertex0 = edge->vertex;
- }
- else if (edge->next->vertex != vertex0)
- {
- const HalfEdge::Vertex * vertex1 = edge->from();
- const HalfEdge::Vertex * vertex2 = edge->to();
-
- setup_abf_relations(A, t, vertex0, vertex1, vertex2);
- //setup_conformal_map_relations(A, t, vertex0, vertex1, vertex2);
-
- t++;
- }
- }
- }
-
- const uint lockedParameters[] =
- {
- 2 * v0->id + 0,
- 2 * v0->id + 1,
- 2 * v1->id + 0,
- 2 * v1->id + 1
- };
-
- // Solve
- LeastSquaresSolver(A, b, x, lockedParameters, 4, 0.000001f);
-
- // Map x back to texcoords:
- for (uint v = 0; v < vertexCount; v++)
- {
- HalfEdge::Vertex * vertex = mesh->vertexAt(v);
- nvDebugCheck(vertex != NULL);
-
- vertex->tex = Vector2(x[2 * v + 0], x[2 * v + 1]);
- }
-
- return true;
-}
diff --git a/thirdparty/thekla_atlas/nvmesh/param/LeastSquaresConformalMap.h b/thirdparty/thekla_atlas/nvmesh/param/LeastSquaresConformalMap.h
deleted file mode 100644
index 51fbf193c8..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/param/LeastSquaresConformalMap.h
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright NVIDIA Corporation 2008 -- Ignacio Castano <icastano@nvidia.com>
-
-#pragma once
-#ifndef NV_MESH_LEASTSQUARESCONFORMALMAP_H
-#define NV_MESH_LEASTSQUARESCONFORMALMAP_H
-
-namespace nv
-{
- namespace HalfEdge { class Mesh; }
-
- bool computeLeastSquaresConformalMap(HalfEdge::Mesh * mesh);
-
-} // nv namespace
-
-#endif // NV_MESH_LEASTSQUARESCONFORMALMAP_H
diff --git a/thirdparty/thekla_atlas/nvmesh/param/OrthogonalProjectionMap.cpp b/thirdparty/thekla_atlas/nvmesh/param/OrthogonalProjectionMap.cpp
deleted file mode 100644
index d6e5e30561..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/param/OrthogonalProjectionMap.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-// This code is in the public domain -- castano@gmail.com
-
-#include "nvmesh.h" // pch
-
-#include "OrthogonalProjectionMap.h"
-
-#include "nvcore/Array.inl"
-
-#include "nvmath/Fitting.h"
-#include "nvmath/Vector.inl"
-#include "nvmath/Box.inl"
-#include "nvmath/Plane.inl"
-
-#include "nvmesh/halfedge/Mesh.h"
-#include "nvmesh/halfedge/Vertex.h"
-#include "nvmesh/halfedge/Face.h"
-#include "nvmesh/geometry/Bounds.h"
-
-
-using namespace nv;
-
-bool nv::computeOrthogonalProjectionMap(HalfEdge::Mesh * mesh)
-{
- Vector3 axis[2];
-
-#if 1
-
- uint vertexCount = mesh->vertexCount();
- Array<Vector3> points(vertexCount);
- points.resize(vertexCount);
-
- for (uint i = 0; i < vertexCount; i++)
- {
- points[i] = mesh->vertexAt(i)->pos;
- }
-
-#if 0
- axis[0] = Fit::computePrincipalComponent_EigenSolver(vertexCount, points.buffer());
- axis[0] = normalize(axis[0]);
-
- Plane plane = Fit::bestPlane(vertexCount, points.buffer());
-
- Vector3 n = plane.vector();
-
- axis[1] = cross(axis[0], n);
- axis[1] = normalize(axis[1]);
-#else
- // Avoid redundant computations.
- float matrix[6];
- Fit::computeCovariance(vertexCount, points.buffer(), matrix);
-
- if (matrix[0] == 0 && matrix[3] == 0 && matrix[5] == 0) {
- return false;
- }
-
- float eigenValues[3];
- Vector3 eigenVectors[3];
- if (!nv::Fit::eigenSolveSymmetric3(matrix, eigenValues, eigenVectors)) {
- return false;
- }
-
- axis[0] = normalize(eigenVectors[0]);
- axis[1] = normalize(eigenVectors[1]);
-#endif
-
-
-#else
-
- // IC: I thought this was generally more robust, but turns out it's not even guaranteed to return a valid projection. Imagine a narrow quad perpendicular to one plane, but rotated so that the shortest axis of
- // the bounding box is in the direction of that plane.
-
- // Use the shortest box axis
- Box box = MeshBounds::box(mesh);
- Vector3 dir = box.extents();
-
- if (fabs(dir.x) <= fabs(dir.y) && fabs(dir.x) <= fabs(dir.z)) {
- axis[0] = Vector3(0, 1, 0);
- axis[1] = Vector3(0, 0, 1);
- }
- else if (fabs(dir.y) <= fabs(dir.z)) {
- axis[0] = Vector3(1, 0, 0);
- axis[1] = Vector3(0, 0, 1);
- }
- else {
- axis[0] = Vector3(1, 0, 0);
- axis[1] = Vector3(0, 1, 0);
- }
-#endif
-
- // Project vertices to plane.
- for (HalfEdge::Mesh::VertexIterator it(mesh->vertices()); !it.isDone(); it.advance())
- {
- HalfEdge::Vertex * vertex = it.current();
- vertex->tex.x = dot(axis[0], vertex->pos);
- vertex->tex.y = dot(axis[1], vertex->pos);
- }
-
- return true;
-}
diff --git a/thirdparty/thekla_atlas/nvmesh/param/OrthogonalProjectionMap.h b/thirdparty/thekla_atlas/nvmesh/param/OrthogonalProjectionMap.h
deleted file mode 100644
index 54920413d5..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/param/OrthogonalProjectionMap.h
+++ /dev/null
@@ -1,15 +0,0 @@
-// This code is in the public domain -- castano@gmail.com
-
-#pragma once
-#ifndef NV_MESH_ORTHOGONALPROJECTIONMAP_H
-#define NV_MESH_ORTHOGONALPROJECTIONMAP_H
-
-namespace nv
-{
- namespace HalfEdge { class Mesh; }
-
- bool computeOrthogonalProjectionMap(HalfEdge::Mesh * mesh);
-
-} // nv namespace
-
-#endif // NV_MESH_ORTHOGONALPROJECTIONMAP_H
diff --git a/thirdparty/thekla_atlas/nvmesh/param/ParameterizationQuality.cpp b/thirdparty/thekla_atlas/nvmesh/param/ParameterizationQuality.cpp
deleted file mode 100644
index 683ee603cd..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/param/ParameterizationQuality.cpp
+++ /dev/null
@@ -1,323 +0,0 @@
-// Copyright NVIDIA Corporation 2008 -- Ignacio Castano <icastano@nvidia.com>
-
-#include "nvmesh.h" // pch
-
-#include "ParameterizationQuality.h"
-
-#include "nvmesh/halfedge/Mesh.h"
-#include "nvmesh/halfedge/Face.h"
-#include "nvmesh/halfedge/Vertex.h"
-#include "nvmesh/halfedge/Edge.h"
-
-#include "nvmath/Vector.inl"
-
-#include "nvcore/Debug.h"
-
-#include <float.h>
-
-
-using namespace nv;
-
-#if 0
-/*
-float triangleConformalEnergy(Vector3 q[3], Vector2 p[3])
-{
-const Vector3 v1 = q[0];
-const Vector3 v2 = q[1];
-const Vector3 v3 = q[2];
-
-const Vector2 w1 = p[0];
-const Vector2 w2 = p[1];
-const Vector2 w3 = p[2];
-
-float x1 = v2.x() - v1.x();
-float x2 = v3.x() - v1.x();
-float y1 = v2.y() - v1.y();
-float y2 = v3.y() - v1.y();
-float z1 = v2.z() - v1.z();
-float z2 = v3.z() - v1.z();
-
-float s1 = w2.x() - w1.x();
-float s2 = w3.x() - w1.x();
-float t1 = w2.y() - w1.y();
-float t2 = w3.y() - w1.y();
-
-float r = 1.0f / (s1 * t2 - s2 * t1);
-Vector3 sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
-Vector3 tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);
-
-Vector3 N = cross(v3-v1, v2-v1);
-
-// Rotate 90 around N.
-}
-*/
-
-static float triangleConformalEnergy(Vector3 q[3], Vector2 p[3])
-{
- // Using Denis formulas:
- Vector3 c0 = q[1] - q[2];
- Vector3 c1 = q[2] - q[0];
- Vector3 c2 = q[0] - q[1];
-
- Vector3 N = cross(-c0, c1);
- float T = length(N); // 2T
- N = normalize(N, 0);
-
- float cot_alpha0 = dot(-c1, c2) / length(cross(-c1, c2));
- float cot_alpha1 = dot(-c2, c0) / length(cross(-c2, c0));
- float cot_alpha2 = dot(-c0, c1) / length(cross(-c0, c1));
-
- Vector3 t0 = -cot_alpha1 * c1 + cot_alpha2 * c2;
- Vector3 t1 = -cot_alpha2 * c2 + cot_alpha0 * c0;
- Vector3 t2 = -cot_alpha0 * c0 + cot_alpha1 * c1;
-
- nvCheck(equal(length(t0), length(c0)));
- nvCheck(equal(length(t1), length(c1)));
- nvCheck(equal(length(t2), length(c2)));
- nvCheck(equal(dot(t0, c0), 0));
- nvCheck(equal(dot(t1, c1), 0));
- nvCheck(equal(dot(t2, c2), 0));
-
- // Gradients
- Vector3 grad_u = 1.0f / T * (p[0].x * t0 + p[1].x * t1 + p[2].x * t2);
- Vector3 grad_v = 1.0f / T * (p[0].y * t0 + p[1].y * t1 + p[2].y * t2);
-
- // Rotated gradients
- Vector3 Jgrad_u = 1.0f / T * (p[0].x * c0 + p[1].x * c1 + p[2].x * c2);
- Vector3 Jgrad_v = 1.0f / T * (p[0].y * c0 + p[1].y * c1 + p[2].y * c2);
-
- // Using Lengyel's formulas:
- {
- const Vector3 v1 = q[0];
- const Vector3 v2 = q[1];
- const Vector3 v3 = q[2];
-
- const Vector2 w1 = p[0];
- const Vector2 w2 = p[1];
- const Vector2 w3 = p[2];
-
- float x1 = v2.x - v1.x;
- float x2 = v3.x - v1.x;
- float y1 = v2.y - v1.y;
- float y2 = v3.y - v1.y;
- float z1 = v2.z - v1.z;
- float z2 = v3.z - v1.z;
-
- float s1 = w2.x - w1.x;
- float s2 = w3.x - w1.x;
- float t1 = w2.y - w1.y;
- float t2 = w3.y - w1.y;
-
- float r = 1.0f / (s1 * t2 - s2 * t1);
- Vector3 sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
- Vector3 tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);
-
- Vector3 Jsdir = cross(N, sdir);
- Vector3 Jtdir = cross(N, tdir);
-
- float x = 3;
- }
-
- // check: sdir == grad_u
- // check: tdir == grad_v
-
- return length(grad_u - Jgrad_v);
-}
-#endif // 0
-
-
-ParameterizationQuality::ParameterizationQuality()
-{
- m_totalTriangleCount = 0;
- m_flippedTriangleCount = 0;
- m_zeroAreaTriangleCount = 0;
-
- m_parametricArea = 0.0f;
- m_geometricArea = 0.0f;
-
- m_stretchMetric = 0.0f;
- m_maxStretchMetric = 0.0f;
-
- m_conformalMetric = 0.0f;
- m_authalicMetric = 0.0f;
-}
-
-ParameterizationQuality::ParameterizationQuality(const HalfEdge::Mesh * mesh)
-{
- nvDebugCheck(mesh != NULL);
-
- m_totalTriangleCount = 0;
- m_flippedTriangleCount = 0;
- m_zeroAreaTriangleCount = 0;
-
- m_parametricArea = 0.0f;
- m_geometricArea = 0.0f;
-
- m_stretchMetric = 0.0f;
- m_maxStretchMetric = 0.0f;
-
- m_conformalMetric = 0.0f;
- m_authalicMetric = 0.0f;
-
- const uint faceCount = mesh->faceCount();
- for (uint f = 0; f < faceCount; f++)
- {
- const HalfEdge::Face * face = mesh->faceAt(f);
- const HalfEdge::Vertex * vertex0 = NULL;
-
- Vector3 p[3];
- Vector2 t[3];
-
- for (HalfEdge::Face::ConstEdgeIterator it(face->edges()); !it.isDone(); it.advance())
- {
- const HalfEdge::Edge * edge = it.current();
-
- if (vertex0 == NULL)
- {
- vertex0 = edge->vertex;
-
- p[0] = vertex0->pos;
- t[0] = vertex0->tex;
- }
- else if (edge->to() != vertex0)
- {
- p[1] = edge->from()->pos;
- p[2] = edge->to()->pos;
- t[1] = edge->from()->tex;
- t[2] = edge->to()->tex;
-
- processTriangle(p, t);
- }
- }
- }
-
- if (m_flippedTriangleCount + m_zeroAreaTriangleCount == faceCount)
- {
- // If all triangles are flipped, then none is.
- m_flippedTriangleCount = 0;
- }
-
- nvDebugCheck(isFinite(m_parametricArea) && m_parametricArea >= 0);
- nvDebugCheck(isFinite(m_geometricArea) && m_geometricArea >= 0);
- nvDebugCheck(isFinite(m_stretchMetric));
- nvDebugCheck(isFinite(m_maxStretchMetric));
- nvDebugCheck(isFinite(m_conformalMetric));
- nvDebugCheck(isFinite(m_authalicMetric));
-}
-
-bool ParameterizationQuality::isValid() const
-{
- return m_flippedTriangleCount == 0; // @@ Does not test for self-overlaps.
-}
-
-float ParameterizationQuality::rmsStretchMetric() const
-{
- if (m_geometricArea == 0) return 0.0f;
- float normFactor = sqrtf(m_parametricArea / m_geometricArea);
- return sqrtf(m_stretchMetric / m_geometricArea) * normFactor;
-}
-
-float ParameterizationQuality::maxStretchMetric() const
-{
- if (m_geometricArea == 0) return 0.0f;
- float normFactor = sqrtf(m_parametricArea / m_geometricArea);
- return m_maxStretchMetric * normFactor;
-}
-
-float ParameterizationQuality::rmsConformalMetric() const
-{
- if (m_geometricArea == 0) return 0.0f;
- return sqrtf(m_conformalMetric / m_geometricArea);
-}
-
-float ParameterizationQuality::maxAuthalicMetric() const
-{
- if (m_geometricArea == 0) return 0.0f;
- return sqrtf(m_authalicMetric / m_geometricArea);
-}
-
-void ParameterizationQuality::operator += (const ParameterizationQuality & pq)
-{
- m_totalTriangleCount += pq.m_totalTriangleCount;
- m_flippedTriangleCount += pq.m_flippedTriangleCount;
- m_zeroAreaTriangleCount += pq.m_zeroAreaTriangleCount;
-
- m_parametricArea += pq.m_parametricArea;
- m_geometricArea += pq.m_geometricArea;
-
- m_stretchMetric += pq.m_stretchMetric;
- m_maxStretchMetric = max(m_maxStretchMetric, pq.m_maxStretchMetric);
-
- m_conformalMetric += pq.m_conformalMetric;
- m_authalicMetric += pq.m_authalicMetric;
-}
-
-
-void ParameterizationQuality::processTriangle(Vector3 q[3], Vector2 p[3])
-{
- m_totalTriangleCount++;
-
- // Evaluate texture stretch metric. See:
- // - "Texture Mapping Progressive Meshes", Sander, Snyder, Gortler & Hoppe
- // - "Mesh Parameterization: Theory and Practice", Siggraph'07 Course Notes, Hormann, Levy & Sheffer.
-
- float t1 = p[0].x;
- float s1 = p[0].y;
- float t2 = p[1].x;
- float s2 = p[1].y;
- float t3 = p[2].x;
- float s3 = p[2].y;
-
- float geometricArea = length(cross(q[1] - q[0], q[2] - q[0])) / 2;
- float parametricArea = ((s2 - s1)*(t3 - t1) - (s3 - s1)*(t2 - t1)) / 2;
-
- if (isZero(parametricArea))
- {
- m_zeroAreaTriangleCount++;
- return;
- }
-
- Vector3 Ss = (q[0] * (t2- t3) + q[1] * (t3 - t1) + q[2] * (t1 - t2)) / (2 * parametricArea);
- Vector3 St = (q[0] * (s3- s2) + q[1] * (s1 - s3) + q[2] * (s2 - s1)) / (2 * parametricArea);
-
- float a = dot(Ss, Ss); // E
- float b = dot(Ss, St); // F
- float c = dot(St, St); // G
-
- // Compute eigen-values of the first fundamental form:
- float sigma1 = sqrtf(0.5f * max(0.0f, a + c - sqrtf(square(a - c) + 4 * square(b)))); // gamma uppercase, min eigenvalue.
- float sigma2 = sqrtf(0.5f * max(0.0f, a + c + sqrtf(square(a - c) + 4 * square(b)))); // gamma lowercase, max eigenvalue.
- nvCheck(sigma2 >= sigma1);
-
- // isometric: sigma1 = sigma2 = 1
- // conformal: sigma1 / sigma2 = 1
- // authalic: sigma1 * sigma2 = 1
-
- float rmsStretch = sqrtf((a + c) * 0.5f);
- float rmsStretch2 = sqrtf((square(sigma1) + square(sigma2)) * 0.5f);
- nvDebugCheck(equal(rmsStretch, rmsStretch2, 0.01f));
-
- if (parametricArea < 0.0f)
- {
- // Count flipped triangles.
- m_flippedTriangleCount++;
-
- parametricArea = fabsf(parametricArea);
- }
-
- m_stretchMetric += square(rmsStretch) * geometricArea;
- m_maxStretchMetric = max(m_maxStretchMetric, sigma2);
-
- if (!isZero(sigma1, 0.000001f)) {
- // sigma1 is zero when geometricArea is zero.
- m_conformalMetric += (sigma2 / sigma1) * geometricArea;
- }
- m_authalicMetric += (sigma1 * sigma2) * geometricArea;
-
- // Accumulate total areas.
- m_geometricArea += geometricArea;
- m_parametricArea += parametricArea;
-
-
- //triangleConformalEnergy(q, p);
-}
diff --git a/thirdparty/thekla_atlas/nvmesh/param/ParameterizationQuality.h b/thirdparty/thekla_atlas/nvmesh/param/ParameterizationQuality.h
deleted file mode 100644
index 342e26b889..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/param/ParameterizationQuality.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright NVIDIA Corporation 2008 -- Ignacio Castano <icastano@nvidia.com>
-
-#pragma once
-#ifndef NV_MESH_PARAMETERIZATIONQUALITY_H
-#define NV_MESH_PARAMETERIZATIONQUALITY_H
-
-#include <nvmesh/nvmesh.h>
-
-namespace nv
-{
- class Vector2;
- class Vector3;
-
- namespace HalfEdge { class Mesh; }
-
- // Estimate quality of existing parameterization.
- NVMESH_CLASS class ParameterizationQuality
- {
- public:
- ParameterizationQuality();
- ParameterizationQuality(const HalfEdge::Mesh * mesh);
-
- bool isValid() const;
-
- float rmsStretchMetric() const;
- float maxStretchMetric() const;
-
- float rmsConformalMetric() const;
- float maxAuthalicMetric() const;
-
- void operator += (const ParameterizationQuality & pq);
-
- private:
-
- void processTriangle(Vector3 p[3], Vector2 t[3]);
-
- private:
-
- uint m_totalTriangleCount;
- uint m_flippedTriangleCount;
- uint m_zeroAreaTriangleCount;
-
- float m_parametricArea;
- float m_geometricArea;
-
- float m_stretchMetric;
- float m_maxStretchMetric;
-
- float m_conformalMetric;
- float m_authalicMetric;
-
- };
-
-} // nv namespace
-
-#endif // NV_MESH_PARAMETERIZATIONQUALITY_H
diff --git a/thirdparty/thekla_atlas/nvmesh/param/SingleFaceMap.cpp b/thirdparty/thekla_atlas/nvmesh/param/SingleFaceMap.cpp
deleted file mode 100644
index 4b205de8bf..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/param/SingleFaceMap.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright NVIDIA Corporation 2008 -- Ignacio Castano <icastano@nvidia.com>
-
-#include "nvmesh.h" // pch
-
-#include "SingleFaceMap.h"
-
-#include "nvmesh/halfedge/Mesh.h"
-#include "nvmesh/halfedge/Vertex.h"
-#include "nvmesh/halfedge/Face.h"
-
-#include "nvmath/Vector.inl"
-
-using namespace nv;
-
-
-
-void nv::computeSingleFaceMap(HalfEdge::Mesh * mesh)
-{
- nvDebugCheck(mesh != NULL);
- nvDebugCheck(mesh->faceCount() == 1);
-
- HalfEdge::Face * face = mesh->faceAt(0);
- nvCheck(face != NULL);
-
- Vector3 p0 = face->edge->from()->pos;
- Vector3 p1 = face->edge->to()->pos;
-
- Vector3 X = normalizeSafe(p1 - p0, Vector3(0.0f), 0.0f);
- Vector3 Z = face->normal();
- Vector3 Y = normalizeSafe(cross(Z, X), Vector3(0.0f), 0.0f);
-
- uint i = 0;
- for (HalfEdge::Face::EdgeIterator it(face->edges()); !it.isDone(); it.advance(), i++)
- {
- HalfEdge::Vertex * vertex = it.vertex();
- nvCheck(vertex != NULL);
-
- if (i == 0)
- {
- vertex->tex = Vector2(0);
- }
- else
- {
- Vector3 pn = vertex->pos;
-
- float xn = dot((pn - p0), X);
- float yn = dot((pn - p0), Y);
-
- vertex->tex = Vector2(xn, yn);
- }
- }
-}
-
diff --git a/thirdparty/thekla_atlas/nvmesh/param/SingleFaceMap.h b/thirdparty/thekla_atlas/nvmesh/param/SingleFaceMap.h
deleted file mode 100644
index b70719f5d8..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/param/SingleFaceMap.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright NVIDIA Corporation 2008 -- Ignacio Castano <icastano@nvidia.com>
-
-#pragma once
-#ifndef NV_MESH_SINGLEFACEMAP_H
-#define NV_MESH_SINGLEFACEMAP_H
-
-namespace nv
-{
- namespace HalfEdge
- {
- class Mesh;
- }
-
- void computeSingleFaceMap(HalfEdge::Mesh * mesh);
-
-} // nv namespace
-
-#endif // NV_MESH_SINGLEFACEMAP_H
diff --git a/thirdparty/thekla_atlas/nvmesh/param/Util.cpp b/thirdparty/thekla_atlas/nvmesh/param/Util.cpp
deleted file mode 100644
index fe7b58edf8..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/param/Util.cpp
+++ /dev/null
@@ -1,326 +0,0 @@
-// This code is in the public domain -- castano@gmail.com
-
-#include "nvmesh.h" // pch
-
-#include "Util.h"
-
-#include "nvmesh/halfedge/Mesh.h"
-#include "nvmesh/halfedge/Face.h"
-#include "nvmesh/halfedge/Vertex.h"
-
-#include "nvmath/Vector.inl"
-
-#include "nvcore/Array.inl"
-
-
-using namespace nv;
-
-// Determine if the given mesh is a quad mesh.
-bool nv::isQuadMesh(const HalfEdge::Mesh * mesh)
-{
- nvDebugCheck(mesh != NULL);
-
- const uint faceCount = mesh->faceCount();
- for(uint i = 0; i < faceCount; i++) {
- const HalfEdge::Face * face = mesh->faceAt(i);
- if (face->edgeCount() != 4) {
- return false;
- }
- }
-
- return true;
-}
-
-bool nv::isTriangularMesh(const HalfEdge::Mesh * mesh)
-{
- for (HalfEdge::Mesh::ConstFaceIterator it(mesh->faces()); !it.isDone(); it.advance())
- {
- const HalfEdge::Face * face = it.current();
- if (face->edgeCount() != 3) return false;
- }
- return true;
-}
-
-
-uint nv::countMeshTriangles(const HalfEdge::Mesh * mesh)
-{
- const uint faceCount = mesh->faceCount();
-
- uint triangleCount = 0;
-
- for (uint f = 0; f < faceCount; f++)
- {
- const HalfEdge::Face * face = mesh->faceAt(f);
-
- uint edgeCount = face->edgeCount();
- nvDebugCheck(edgeCount > 2);
-
- triangleCount += edgeCount - 2;
- }
-
- return triangleCount;
-}
-
-const HalfEdge::Vertex * nv::findBoundaryVertex(const HalfEdge::Mesh * mesh)
-{
- const uint vertexCount = mesh->vertexCount();
-
- for (uint v = 0; v < vertexCount; v++)
- {
- const HalfEdge::Vertex * vertex = mesh->vertexAt(v);
- if (vertex->isBoundary()) return vertex;
- }
-
- return NULL;
-}
-
-
-HalfEdge::Mesh * nv::unifyVertices(const HalfEdge::Mesh * inputMesh)
-{
- HalfEdge::Mesh * mesh = new HalfEdge::Mesh;
-
- // Only add the first colocal.
- const uint vertexCount = inputMesh->vertexCount();
- for (uint v = 0; v < vertexCount; v++) {
- const HalfEdge::Vertex * vertex = inputMesh->vertexAt(v);
-
- if (vertex->isFirstColocal()) {
- mesh->addVertex(vertex->pos);
- }
- }
-
- nv::Array<uint> indexArray;
-
- // Add new faces pointing to first colocals.
- uint faceCount = inputMesh->faceCount();
- for (uint f = 0; f < faceCount; f++) {
- const HalfEdge::Face * face = inputMesh->faceAt(f);
-
- indexArray.clear();
-
- for (HalfEdge::Face::ConstEdgeIterator it(face->edges()); !it.isDone(); it.advance()) {
- const HalfEdge::Edge * edge = it.current();
- const HalfEdge::Vertex * vertex = edge->vertex->firstColocal();
-
- indexArray.append(vertex->id);
- }
-
- mesh->addFace(indexArray);
- }
-
- mesh->linkBoundary();
-
- return mesh;
-}
-
-#include "nvmath/Basis.h"
-
-static bool pointInTriangle(const Vector2 & p, const Vector2 & a, const Vector2 & b, const Vector2 & c)
-{
- return triangleArea(a, b, p) >= 0.00001f &&
- triangleArea(b, c, p) >= 0.00001f &&
- triangleArea(c, a, p) >= 0.00001f;
-}
-
-
-// This is doing a simple ear-clipping algorithm that skips invalid triangles. Ideally, we should
-// also sort the ears by angle, start with the ones that have the smallest angle and proceed in order.
-HalfEdge::Mesh * nv::triangulate(const HalfEdge::Mesh * inputMesh)
-{
- HalfEdge::Mesh * mesh = new HalfEdge::Mesh;
-
- // Add all vertices.
- const uint vertexCount = inputMesh->vertexCount();
- for (uint v = 0; v < vertexCount; v++) {
- const HalfEdge::Vertex * vertex = inputMesh->vertexAt(v);
- mesh->addVertex(vertex->pos);
- }
-
- Array<int> polygonVertices;
- Array<float> polygonAngles;
- Array<Vector2> polygonPoints;
-
- const uint faceCount = inputMesh->faceCount();
- for (uint f = 0; f < faceCount; f++)
- {
- const HalfEdge::Face * face = inputMesh->faceAt(f);
- nvDebugCheck(face != NULL);
-
- const uint edgeCount = face->edgeCount();
- nvDebugCheck(edgeCount >= 3);
-
- polygonVertices.clear();
- polygonVertices.reserve(edgeCount);
-
- if (edgeCount == 3) {
- // Simple case for triangles.
- for (HalfEdge::Face::ConstEdgeIterator it(face->edges()); !it.isDone(); it.advance())
- {
- const HalfEdge::Edge * edge = it.current();
- const HalfEdge::Vertex * vertex = edge->vertex;
- polygonVertices.append(vertex->id);
- }
-
- int v0 = polygonVertices[0];
- int v1 = polygonVertices[1];
- int v2 = polygonVertices[2];
-
- mesh->addFace(v0, v1, v2);
- }
- else {
- // Build 2D polygon projecting vertices onto normal plane.
- // Faces are not necesarily planar, this is for example the case, when the face comes from filling a hole. In such cases
- // it's much better to use the best fit plane.
- const Vector3 fn = face->normal();
-
- Basis basis;
- basis.buildFrameForDirection(fn);
-
- polygonPoints.clear();
- polygonPoints.reserve(edgeCount);
- polygonAngles.clear();
- polygonAngles.reserve(edgeCount);
-
- for (HalfEdge::Face::ConstEdgeIterator it(face->edges()); !it.isDone(); it.advance())
- {
- const HalfEdge::Edge * edge = it.current();
- const HalfEdge::Vertex * vertex = edge->vertex;
- polygonVertices.append(vertex->id);
-
- Vector2 p;
- p.x = dot(basis.tangent, vertex->pos);
- p.y = dot(basis.bitangent, vertex->pos);
-
- polygonPoints.append(p);
- }
- polygonAngles.resize(edgeCount);
-
- while (polygonVertices.size() > 2) {
- uint size = polygonVertices.size();
-
- // Update polygon angles. @@ Update only those that have changed.
- float minAngle = 2 * PI;
- uint bestEar = 0; // Use first one if none of them is valid.
- bool bestIsValid = false;
- for (uint i = 0; i < size; i++) {
- uint i0 = i;
- uint i1 = (i+1) % size; // Use Sean's polygon interation trick.
- uint i2 = (i+2) % size;
-
- Vector2 p0 = polygonPoints[i0];
- Vector2 p1 = polygonPoints[i1];
- Vector2 p2 = polygonPoints[i2];
-
- float d = clamp(dot(p0-p1, p2-p1) / (length(p0-p1) * length(p2-p1)), -1.0f, 1.0f);
- float angle = acosf(d);
-
- float area = triangleArea(p0, p1, p2);
- if (area < 0.0f) angle = 2.0f * PI - angle;
-
- polygonAngles[i1] = angle;
-
- if (angle < minAngle || !bestIsValid) {
-
- // Make sure this is a valid ear, if not, skip this point.
- bool valid = true;
- for (uint j = 0; j < size; j++) {
- if (j == i0 || j == i1 || j == i2) continue;
- Vector2 p = polygonPoints[j];
-
- if (pointInTriangle(p, p0, p1, p2)) {
- valid = false;
- break;
- }
- }
-
- if (valid || !bestIsValid) {
- minAngle = angle;
- bestEar = i1;
- bestIsValid = valid;
- }
- }
- }
-
- nvDebugCheck(minAngle <= 2 * PI);
-
- // Clip best ear:
-
- uint i0 = (bestEar+size-1) % size;
- uint i1 = (bestEar+0) % size;
- uint i2 = (bestEar+1) % size;
-
- int v0 = polygonVertices[i0];
- int v1 = polygonVertices[i1];
- int v2 = polygonVertices[i2];
-
- mesh->addFace(v0, v1, v2);
-
- polygonVertices.removeAt(i1);
- polygonPoints.removeAt(i1);
- polygonAngles.removeAt(i1);
- }
- }
-
-#if 0
-
- uint i = 0;
- while (polygonVertices.size() > 2 && i < polygonVertices.size()) {
- uint size = polygonVertices.size();
- uint i0 = (i+0) % size;
- uint i1 = (i+1) % size;
- uint i2 = (i+2) % size;
-
- const HalfEdge::Vertex * v0 = polygonVertices[i0];
- const HalfEdge::Vertex * v1 = polygonVertices[i1];
- const HalfEdge::Vertex * v2 = polygonVertices[i2];
-
- const Vector3 p0 = v0->pos;
- const Vector3 p1 = v1->pos;
- const Vector3 p2 = v2->pos;
-
- const Vector3 e0 = p2 - p1;
- const Vector3 e1 = p0 - p1;
-
- // If this ear forms a valid triangle, setup relations, remove v1 and repeat.
- Vector3 n = cross(e0, e1);
- float len = dot(fn, n); // = sin(angle)
-
- float angle = asin(len);
-
-
- if (len > 0.0f) {
- mesh->addFace(v0->id(), v1->id(), v2->id());
- polygonVertices.removeAt(i1);
- polygonAngles.removeAt(i1);
- if (i2 > i1) i2--;
- // @@ Update angles at i0 and i2
- }
- else {
- i++;
- }
- }
-
- // @@ Create a few degenerate triangles to avoid introducing holes.
- i = 0;
- const uint size = polygonVertices.size();
- while (i < size - 2) {
- uint i0 = (i+0) % size;
- uint i1 = (i+1) % size;
- uint i2 = (i+2) % size;
-
- const HalfEdge::Vertex * v0 = polygonVertices[i0];
- const HalfEdge::Vertex * v1 = polygonVertices[i1];
- const HalfEdge::Vertex * v2 = polygonVertices[i2];
-
- mesh->addFace(v0->id(), v1->id(), v2->id());
- i++;
- }
-#endif
- }
-
- mesh->linkBoundary();
-
- return mesh;
-}
-
-
diff --git a/thirdparty/thekla_atlas/nvmesh/param/Util.h b/thirdparty/thekla_atlas/nvmesh/param/Util.h
deleted file mode 100644
index 774563ac0b..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/param/Util.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// This code is in the public domain -- castano@gmail.com
-
-#include "nvmesh/nvmesh.h"
-
-namespace nv {
-
- namespace HalfEdge { class Mesh; class Vertex; }
-
- bool isQuadMesh(const HalfEdge::Mesh * mesh);
- bool isTriangularMesh(const HalfEdge::Mesh * mesh);
-
- uint countMeshTriangles(const HalfEdge::Mesh * mesh);
- const HalfEdge::Vertex * findBoundaryVertex(const HalfEdge::Mesh * mesh);
-
- HalfEdge::Mesh * unifyVertices(const HalfEdge::Mesh * inputMesh);
- HalfEdge::Mesh * triangulate(const HalfEdge::Mesh * inputMesh);
-
-} // nv namespace
diff --git a/thirdparty/thekla_atlas/nvmesh/raster/ClippedTriangle.h b/thirdparty/thekla_atlas/nvmesh/raster/ClippedTriangle.h
deleted file mode 100644
index 0947d4851c..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/raster/ClippedTriangle.h
+++ /dev/null
@@ -1,159 +0,0 @@
-// Copyright NVIDIA Corporation 2007 -- Denis Kovacs <den.kovacs@gmail.com>
-
-#pragma once
-#ifndef NV_MESH_CLIPPEDTRIANGLE_H
-#define NV_MESH_CLIPPEDTRIANGLE_H
-
-#include <nvmath/Vector.h>
-
-namespace nv
-{
-
- class ClippedTriangle
- {
- public:
- ClippedTriangle(Vector2::Arg a, Vector2::Arg b, Vector2::Arg c)
- {
- m_numVertices = 3;
- m_activeVertexBuffer = 0;
-
- m_verticesA[0]=a;
- m_verticesA[1]=b;
- m_verticesA[2]=c;
-
- m_vertexBuffers[0] = m_verticesA;
- m_vertexBuffers[1] = m_verticesB;
- }
-
- uint vertexCount()
- {
- return m_numVertices;
- }
-
- const Vector2 * vertices()
- {
- return m_vertexBuffers[m_activeVertexBuffer];
- }
-
- inline void clipHorizontalPlane(float offset, float clipdirection)
- {
- Vector2 * v = m_vertexBuffers[m_activeVertexBuffer];
- m_activeVertexBuffer ^= 1;
- Vector2 * v2 = m_vertexBuffers[m_activeVertexBuffer];
-
- v[m_numVertices] = v[0];
-
- float dy2, dy1 = offset - v[0].y;
- int dy2in, dy1in = clipdirection*dy1 >= 0;
- uint p=0;
-
- for (uint k=0; k<m_numVertices; k++)
- {
- dy2 = offset - v[k+1].y;
- dy2in = clipdirection*dy2 >= 0;
-
- if (dy1in) v2[p++] = v[k];
-
- if ( dy1in + dy2in == 1 ) // not both in/out
- {
- float dx = v[k+1].x - v[k].x;
- float dy = v[k+1].y - v[k].y;
- v2[p++] = Vector2(v[k].x + dy1*(dx/dy), offset);
- }
-
- dy1 = dy2; dy1in = dy2in;
- }
- m_numVertices = p;
-
- //for (uint k=0; k<m_numVertices; k++) printf("(%f, %f)\n", v2[k].x, v2[k].y); printf("\n");
- }
-
- inline void clipVerticalPlane(float offset, float clipdirection )
- {
- Vector2 * v = m_vertexBuffers[m_activeVertexBuffer];
- m_activeVertexBuffer ^= 1;
- Vector2 * v2 = m_vertexBuffers[m_activeVertexBuffer];
-
- v[m_numVertices] = v[0];
-
- float dx2, dx1 = offset - v[0].x;
- int dx2in, dx1in = clipdirection*dx1 >= 0;
- uint p=0;
-
- for (uint k=0; k<m_numVertices; k++)
- {
- dx2 = offset - v[k+1].x;
- dx2in = clipdirection*dx2 >= 0;
-
- if (dx1in) v2[p++] = v[k];
-
- if ( dx1in + dx2in == 1 ) // not both in/out
- {
- float dx = v[k+1].x - v[k].x;
- float dy = v[k+1].y - v[k].y;
- v2[p++] = Vector2(offset, v[k].y + dx1*(dy/dx));
- }
-
- dx1 = dx2; dx1in = dx2in;
- }
- m_numVertices = p;
-
- //for (uint k=0; k<m_numVertices; k++) printf("(%f, %f)\n", v2[k].x, v2[k].y); printf("\n");
- }
-
- void computeAreaCentroid()
- {
- Vector2 * v = m_vertexBuffers[m_activeVertexBuffer];
- v[m_numVertices] = v[0];
-
- m_area = 0;
- float centroidx=0, centroidy=0;
- for (uint k=0; k<m_numVertices; k++)
- {
- // http://local.wasp.uwa.edu.au/~pbourke/geometry/polyarea/
- float f = v[k].x*v[k+1].y - v[k+1].x*v[k].y;
- m_area += f;
- centroidx += f * (v[k].x + v[k+1].x);
- centroidy += f * (v[k].y + v[k+1].y);
- }
- m_area = 0.5f * fabs(m_area);
- if (m_area==0) {
- m_centroid = Vector2(0.0f);
- } else {
- m_centroid = Vector2(centroidx/(6*m_area), centroidy/(6*m_area));
- }
- }
-
- void clipAABox(float x0, float y0, float x1, float y1)
- {
- clipVerticalPlane ( x0, -1);
- clipHorizontalPlane( y0, -1);
- clipVerticalPlane ( x1, 1);
- clipHorizontalPlane( y1, 1);
-
- computeAreaCentroid();
- }
-
- Vector2 centroid()
- {
- return m_centroid;
- }
-
- float area()
- {
- return m_area;
- }
-
- private:
- Vector2 m_verticesA[7+1];
- Vector2 m_verticesB[7+1];
- Vector2 * m_vertexBuffers[2];
- uint m_numVertices;
- uint m_activeVertexBuffer;
- float m_area;
- Vector2 m_centroid;
- };
-
-} // nv namespace
-
-#endif // NV_MESH_CLIPPEDTRIANGLE_H
diff --git a/thirdparty/thekla_atlas/nvmesh/raster/Raster.cpp b/thirdparty/thekla_atlas/nvmesh/raster/Raster.cpp
deleted file mode 100644
index d46b34f045..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/raster/Raster.cpp
+++ /dev/null
@@ -1,626 +0,0 @@
-// This code is in the public domain -- castanyo@yahoo.es
-
-/** @file Raster.cpp
- * @brief Triangle rasterization library using affine interpolation. Not
- * specially optimized, but enough for my purposes.
-**/
-
-#include "nvmesh.h" // pch
-
-#include "Raster.h"
-#include "ClippedTriangle.h"
-
-#include "nvcore/Utils.h" // min, max
-
-#include "nvmath/Vector.inl"
-#include "nvmath/ftoi.h"
-
-
-#define RA_EPSILON 0.00001f
-
-using namespace nv;
-using namespace nv::Raster;
-
-namespace
-{
- static inline float delta(float bot, float top, float ih)
- {
- return (bot - top) * ih;
- }
-
- static inline Vector2 delta(Vector2::Arg bot, Vector2::Arg top, float ih)
- {
- return (bot - top) * ih;
- }
-
- static inline Vector3 delta(Vector3::Arg bot, Vector3::Arg top, float ih)
- {
- return (bot - top) * ih;
- }
-
- // @@ The implementation in nvmath.h should be equivalent.
- static inline int iround(float f)
- {
- // @@ Optimize this.
- return int(floorf(f+0.5f));
- //return int(round(f));
- //return int(f);
- }
-
- /// A triangle vertex.
- struct Vertex
- {
- Vector2 pos; // Position.
- Vector3 tex; // Texcoord. (Barycentric coordinate)
- };
-
-
- /// A triangle for rasterization.
- struct Triangle
- {
- Triangle(Vector2::Arg v0, Vector2::Arg v1, Vector2::Arg v2, Vector3::Arg t0, Vector3::Arg t1, Vector3::Arg t2);
-
- bool computeDeltas();
-
- bool draw(const Vector2 & extents, bool enableScissors, SamplingCallback cb, void * param);
- bool drawAA(const Vector2 & extents, bool enableScissors, SamplingCallback cb, void * param);
- bool drawC(const Vector2 & extents, bool enableScissors, SamplingCallback cb, void * param);
- void flipBackface();
- void computeUnitInwardNormals();
-
- // Vertices.
- Vector2 v1, v2, v3;
- Vector2 n1, n2, n3; // unit inward normals
- Vector3 t1, t2, t3;
-
- // Deltas.
- Vector3 dx, dy;
-
- float sign;
- bool valid;
- };
-
-
- /// Triangle ctor.
- Triangle::Triangle(Vector2::Arg v0, Vector2::Arg v1, Vector2::Arg v2,
- Vector3::Arg t0, Vector3::Arg t1, Vector3::Arg t2)
- {
- // Init vertices.
- this->v1 = v0;
- this->v2 = v2;
- this->v3 = v1;
-
- // Set barycentric coordinates.
- this->t1 = t0;
- this->t2 = t2;
- this->t3 = t1;
-
- // make sure every triangle is front facing.
- flipBackface();
-
- // Compute deltas.
- valid = computeDeltas();
-
- computeUnitInwardNormals();
- }
-
-
- /// Compute texture space deltas.
- /// This method takes two edge vectors that form a basis, determines the
- /// coordinates of the canonic vectors in that basis, and computes the
- /// texture gradient that corresponds to those vectors.
- bool Triangle::computeDeltas()
- {
- Vector2 e0 = v3 - v1;
- Vector2 e1 = v2 - v1;
-
- Vector3 de0 = t3 - t1;
- Vector3 de1 = t2 - t1;
-
- float denom = 1.0f / (e0.y * e1.x - e1.y * e0.x);
- if (!isFinite(denom)) {
- return false;
- }
-
- float lambda1 = - e1.y * denom;
- float lambda2 = e0.y * denom;
- float lambda3 = e1.x * denom;
- float lambda4 = - e0.x * denom;
-
- dx = de0 * lambda1 + de1 * lambda2;
- dy = de0 * lambda3 + de1 * lambda4;
-
- return true;
- }
-
- // compute unit inward normals for each edge.
- void Triangle::computeUnitInwardNormals()
- {
- n1 = v1 - v2; n1 = Vector2(-n1.y, n1.x); n1 = n1 * (1.0f/sqrtf(n1.x*n1.x + n1.y*n1.y));
- n2 = v2 - v3; n2 = Vector2(-n2.y, n2.x); n2 = n2 * (1.0f/sqrtf(n2.x*n2.x + n2.y*n2.y));
- n3 = v3 - v1; n3 = Vector2(-n3.y, n3.x); n3 = n3 * (1.0f/sqrtf(n3.x*n3.x + n3.y*n3.y));
- }
-
- void Triangle::flipBackface()
- {
- // check if triangle is backfacing, if so, swap two vertices
- if ( ((v3.x-v1.x)*(v2.y-v1.y) - (v3.y-v1.y)*(v2.x-v1.x)) < 0 ) {
- Vector2 hv=v1; v1=v2; v2=hv; // swap pos
- Vector3 ht=t1; t1=t2; t2=ht; // swap tex
- }
- }
-
- bool Triangle::draw(const Vector2 & extents, bool enableScissors, SamplingCallback cb, void * param)
- {
- // 28.4 fixed-point coordinates
- const int Y1 = iround(16.0f * v1.y);
- const int Y2 = iround(16.0f * v2.y);
- const int Y3 = iround(16.0f * v3.y);
-
- const int X1 = iround(16.0f * v1.x);
- const int X2 = iround(16.0f * v2.x);
- const int X3 = iround(16.0f * v3.x);
-
- // Deltas
- const int DX12 = X1 - X2;
- const int DX23 = X2 - X3;
- const int DX31 = X3 - X1;
-
- const int DY12 = Y1 - Y2;
- const int DY23 = Y2 - Y3;
- const int DY31 = Y3 - Y1;
-
- // Fixed-point deltas
- const int FDX12 = DX12 << 4;
- const int FDX23 = DX23 << 4;
- const int FDX31 = DX31 << 4;
-
- const int FDY12 = DY12 << 4;
- const int FDY23 = DY23 << 4;
- const int FDY31 = DY31 << 4;
-
- int minx, miny, maxx, maxy;
- if (enableScissors) {
- int frustumX0 = 0 << 4;
- int frustumY0 = 0 << 4;
- int frustumX1 = (int)extents.x << 4;
- int frustumY1 = (int)extents.y << 4;
-
- // Bounding rectangle
- minx = (nv::max(min3(X1, X2, X3), frustumX0) + 0xF) >> 4;
- miny = (nv::max(min3(Y1, Y2, Y3), frustumY0) + 0xF) >> 4;
- maxx = (nv::min(max3(X1, X2, X3), frustumX1) + 0xF) >> 4;
- maxy = (nv::min(max3(Y1, Y2, Y3), frustumY1) + 0xF) >> 4;
- }
- else {
- // Bounding rectangle
- minx = (min3(X1, X2, X3) + 0xF) >> 4;
- miny = (min3(Y1, Y2, Y3) + 0xF) >> 4;
- maxx = (max3(X1, X2, X3) + 0xF) >> 4;
- maxy = (max3(Y1, Y2, Y3) + 0xF) >> 4;
- }
-
- // Block size, standard 8x8 (must be power of two)
- const int q = 8;
-
- // @@ This won't work when minx,miny are negative. This code path is not used. Leaving as is for now.
- nvCheck(minx >= 0);
- nvCheck(miny >= 0);
-
- // Start in corner of 8x8 block
- minx &= ~(q - 1);
- miny &= ~(q - 1);
-
- // Half-edge constants
- int C1 = DY12 * X1 - DX12 * Y1;
- int C2 = DY23 * X2 - DX23 * Y2;
- int C3 = DY31 * X3 - DX31 * Y3;
-
- // Correct for fill convention
- if(DY12 < 0 || (DY12 == 0 && DX12 > 0)) C1++;
- if(DY23 < 0 || (DY23 == 0 && DX23 > 0)) C2++;
- if(DY31 < 0 || (DY31 == 0 && DX31 > 0)) C3++;
-
- // Loop through blocks
- for(int y = miny; y < maxy; y += q)
- {
- for(int x = minx; x < maxx; x += q)
- {
- // Corners of block
- int x0 = x << 4;
- int x1 = (x + q - 1) << 4;
- int y0 = y << 4;
- int y1 = (y + q - 1) << 4;
-
- // Evaluate half-space functions
- bool a00 = C1 + DX12 * y0 - DY12 * x0 > 0;
- bool a10 = C1 + DX12 * y0 - DY12 * x1 > 0;
- bool a01 = C1 + DX12 * y1 - DY12 * x0 > 0;
- bool a11 = C1 + DX12 * y1 - DY12 * x1 > 0;
- int a = (a00 << 0) | (a10 << 1) | (a01 << 2) | (a11 << 3);
-
- bool b00 = C2 + DX23 * y0 - DY23 * x0 > 0;
- bool b10 = C2 + DX23 * y0 - DY23 * x1 > 0;
- bool b01 = C2 + DX23 * y1 - DY23 * x0 > 0;
- bool b11 = C2 + DX23 * y1 - DY23 * x1 > 0;
- int b = (b00 << 0) | (b10 << 1) | (b01 << 2) | (b11 << 3);
-
- bool c00 = C3 + DX31 * y0 - DY31 * x0 > 0;
- bool c10 = C3 + DX31 * y0 - DY31 * x1 > 0;
- bool c01 = C3 + DX31 * y1 - DY31 * x0 > 0;
- bool c11 = C3 + DX31 * y1 - DY31 * x1 > 0;
- int c = (c00 << 0) | (c10 << 1) | (c01 << 2) | (c11 << 3);
-
- // Skip block when outside an edge
- if(a == 0x0 || b == 0x0 || c == 0x0) continue;
-
- // Accept whole block when totally covered
- if(a == 0xF && b == 0xF && c == 0xF)
- {
- Vector3 texRow = t1 + dy*(y0 - v1.y) + dx*(x0 - v1.x);
-
- for(int iy = y; iy < y + q; iy++)
- {
- Vector3 tex = texRow;
- for(int ix = x; ix < x + q; ix++)
- {
- //Vector3 tex = t1 + dx * (ix - v1.x) + dy * (iy - v1.y);
- if (!cb(param, ix, iy, tex, dx, dy, 1.0)) {
- // early out.
- return false;
- }
- tex += dx;
- }
- texRow += dy;
- }
- }
- else // Partially covered block
- {
- int CY1 = C1 + DX12 * y0 - DY12 * x0;
- int CY2 = C2 + DX23 * y0 - DY23 * x0;
- int CY3 = C3 + DX31 * y0 - DY31 * x0;
- Vector3 texRow = t1 + dy*(y0 - v1.y) + dx*(x0 - v1.x);
-
- for(int iy = y; iy < y + q; iy++)
- {
- int CX1 = CY1;
- int CX2 = CY2;
- int CX3 = CY3;
- Vector3 tex = texRow;
-
- for(int ix = x; ix < x + q; ix++)
- {
- if(CX1 > 0 && CX2 > 0 && CX3 > 0)
- {
- if (!cb(param, ix, iy, tex, dx, dy, 1.0))
- {
- // early out.
- return false;
- }
- }
-
- CX1 -= FDY12;
- CX2 -= FDY23;
- CX3 -= FDY31;
- tex += dx;
- }
-
- CY1 += FDX12;
- CY2 += FDX23;
- CY3 += FDX31;
- texRow += dy;
- }
- }
- }
- }
-
- return true;
- }
-
-
-#define PX_INSIDE 1.0f/sqrt(2.0f)
-#define PX_OUTSIDE -1.0f/sqrt(2.0f)
-
-#define BK_SIZE 8
-#define BK_INSIDE sqrt(BK_SIZE*BK_SIZE/2.0f)
-#define BK_OUTSIDE -sqrt(BK_SIZE*BK_SIZE/2.0f)
-
- // extents has to be multiple of BK_SIZE!!
- bool Triangle::drawAA(const Vector2 & extents, bool enableScissors, SamplingCallback cb, void * param)
- {
- float minx, miny, maxx, maxy;
- if (enableScissors) {
- // Bounding rectangle
- minx = floorf(max(min3(v1.x, v2.x, v3.x), 0.0f));
- miny = floorf(max(min3(v1.y, v2.y, v3.y), 0.0f));
- maxx = ceilf( min(max3(v1.x, v2.x, v3.x), extents.x-1.0f));
- maxy = ceilf( min(max3(v1.y, v2.y, v3.y), extents.y-1.0f));
- }
- else {
- // Bounding rectangle
- minx = floorf(min3(v1.x, v2.x, v3.x));
- miny = floorf(min3(v1.y, v2.y, v3.y));
- maxx = ceilf( max3(v1.x, v2.x, v3.x));
- maxy = ceilf( max3(v1.y, v2.y, v3.y));
- }
-
- // There's no reason to align the blocks to the viewport, instead we align them to the origin of the triangle bounds.
- minx = floorf(minx);
- miny = floorf(miny);
- //minx = (float)(((int)minx) & (~((int)BK_SIZE - 1))); // align to blocksize (we don't need to worry about blocks partially out of viewport)
- //miny = (float)(((int)miny) & (~((int)BK_SIZE - 1)));
-
- minx += 0.5; miny +=0.5; // sampling at texel centers!
- maxx += 0.5; maxy +=0.5;
-
- // Half-edge constants
- float C1 = n1.x * (-v1.x) + n1.y * (-v1.y);
- float C2 = n2.x * (-v2.x) + n2.y * (-v2.y);
- float C3 = n3.x * (-v3.x) + n3.y * (-v3.y);
-
- // Loop through blocks
- for(float y0 = miny; y0 <= maxy; y0 += BK_SIZE)
- {
- for(float x0 = minx; x0 <= maxx; x0 += BK_SIZE)
- {
- // Corners of block
- float xc = (x0 + (BK_SIZE-1)/2.0f);
- float yc = (y0 + (BK_SIZE-1)/2.0f);
-
- // Evaluate half-space functions
- float aC = C1 + n1.x * xc + n1.y * yc;
- float bC = C2 + n2.x * xc + n2.y * yc;
- float cC = C3 + n3.x * xc + n3.y * yc;
-
- // Skip block when outside an edge
- if( (aC <= BK_OUTSIDE) || (bC <= BK_OUTSIDE) || (cC <= BK_OUTSIDE) ) continue;
-
- // Accept whole block when totally covered
- if( (aC >= BK_INSIDE) && (bC >= BK_INSIDE) && (cC >= BK_INSIDE) )
- {
- Vector3 texRow = t1 + dy*(y0 - v1.y) + dx*(x0 - v1.x);
-
- for (float y = y0; y < y0 + BK_SIZE; y++)
- {
- Vector3 tex = texRow;
- for(float x = x0; x < x0 + BK_SIZE; x++)
- {
- if (!cb(param, (int)x, (int)y, tex, dx, dy, 1.0f))
- {
- return false;
- }
- tex += dx;
- }
- texRow += dy;
- }
- }
- else // Partially covered block
- {
- float CY1 = C1 + n1.x * x0 + n1.y * y0;
- float CY2 = C2 + n2.x * x0 + n2.y * y0;
- float CY3 = C3 + n3.x * x0 + n3.y * y0;
- Vector3 texRow = t1 + dy*(y0 - v1.y) + dx*(x0 - v1.x);
-
- for(float y = y0; y < y0 + BK_SIZE; y++) // @@ This is not clipping to scissor rectangle correctly.
- {
- float CX1 = CY1;
- float CX2 = CY2;
- float CX3 = CY3;
- Vector3 tex = texRow;
-
- for (float x = x0; x < x0 + BK_SIZE; x++) // @@ This is not clipping to scissor rectangle correctly.
- {
- if (CX1 >= PX_INSIDE && CX2 >= PX_INSIDE && CX3 >= PX_INSIDE)
- {
- // pixel completely covered
- Vector3 tex = t1 + dx * (x - v1.x) + dy * (y - v1.y);
- if (!cb(param, (int)x, (int)y, tex, dx, dy, 1.0f))
- {
- return false;
- }
- }
- else if ((CX1 >= PX_OUTSIDE) && (CX2 >= PX_OUTSIDE) && (CX3 >= PX_OUTSIDE))
- {
- // triangle partially covers pixel. do clipping.
- ClippedTriangle ct(v1-Vector2(x,y), v2-Vector2(x,y), v3-Vector2(x,y));
- ct.clipAABox(-0.5, -0.5, 0.5, 0.5);
- Vector2 centroid = ct.centroid();
- float area = ct.area();
- if (area > 0.0f)
- {
- Vector3 texCent = tex - dx*centroid.x - dy*centroid.y;
- //nvCheck(texCent.x >= -0.1f && texCent.x <= 1.1f); // @@ Centroid is not very exact...
- //nvCheck(texCent.y >= -0.1f && texCent.y <= 1.1f);
- //nvCheck(texCent.z >= -0.1f && texCent.z <= 1.1f);
- //Vector3 texCent2 = t1 + dx * (x - v1.x) + dy * (y - v1.y);
- if (!cb(param, (int)x, (int)y, texCent, dx, dy, area))
- {
- return false;
- }
- }
- }
-
- CX1 += n1.x;
- CX2 += n2.x;
- CX3 += n3.x;
- tex += dx;
- }
-
- CY1 += n1.y;
- CY2 += n2.y;
- CY3 += n3.y;
- texRow += dy;
- }
- }
- }
- }
-
- return true;
- }
-
-} // namespace
-
-
-/// Process the given triangle.
-bool nv::Raster::drawTriangle(Mode mode, Vector2::Arg extents, bool enableScissors, const Vector2 v[3], SamplingCallback cb, void * param)
-{
- Triangle tri(v[0], v[1], v[2], Vector3(1, 0, 0), Vector3(0, 1, 0), Vector3(0, 0, 1));
-
- // @@ It would be nice to have a conservative drawing mode that enlarges the triangle extents by one texel and is able to handle degenerate triangles.
- // @@ Maybe the simplest thing to do would be raster triangle edges.
-
- if (tri.valid) {
- if (mode == Mode_Antialiased) {
- return tri.drawAA(extents, enableScissors, cb, param);
- }
- if (mode == Mode_Nearest) {
- return tri.draw(extents, enableScissors, cb, param);
- }
- }
-
- return true;
-}
-
-inline static float triangleArea(Vector2::Arg v1, Vector2::Arg v2, Vector2::Arg v3)
-{
- return 0.5f * (v3.x * v1.y + v1.x * v2.y + v2.x * v3.y - v2.x * v1.y - v3.x * v2.y - v1.x * v3.y);
-}
-
-/// Process the given quad.
-bool nv::Raster::drawQuad(Mode mode, Vector2::Arg extents, bool enableScissors, const Vector2 v[4], SamplingCallback cb, void * param)
-{
- bool sign0 = triangleArea(v[0], v[1], v[2]) > 0.0f;
- bool sign1 = triangleArea(v[0], v[2], v[3]) > 0.0f;
-
- // Divide the quad into two non overlapping triangles.
- if (sign0 == sign1) {
- Triangle tri0(v[0], v[1], v[2], Vector3(0,0,0), Vector3(1,0,0), Vector3(1,1,0));
- Triangle tri1(v[0], v[2], v[3], Vector3(0,0,0), Vector3(1,1,0), Vector3(0,1,0));
-
- if (tri0.valid && tri1.valid) {
- if (mode == Mode_Antialiased) {
- return tri0.drawAA(extents, enableScissors, cb, param) && tri1.drawAA(extents, enableScissors, cb, param);
- } else {
- return tri0.draw(extents, enableScissors, cb, param) && tri1.draw(extents, enableScissors, cb, param);
- }
- }
- }
- else
- {
- Triangle tri0(v[0], v[1], v[3], Vector3(0,0,0), Vector3(1,0,0), Vector3(0,1,0));
- Triangle tri1(v[1], v[2], v[3], Vector3(1,0,0), Vector3(1,1,0), Vector3(0,1,0));
-
- if (tri0.valid && tri1.valid) {
- if (mode == Mode_Antialiased) {
- return tri0.drawAA(extents, enableScissors, cb, param) && tri1.drawAA(extents, enableScissors, cb, param);
- } else {
- return tri0.draw(extents, enableScissors, cb, param) && tri1.draw(extents, enableScissors, cb, param);
- }
- }
- }
-
- return true;
-}
-
-
-static bool drawPoint(const Vector2 & p, const Vector2 v[2], LineSamplingCallback cb, void * param) {
-
- int x = ftoi_round(p.x);
- int y = ftoi_round(p.y);
- Vector2 ip = Vector2(float(x) + 0.5f, float(y) + 0.5f);
-
- float t;
-
- // Return minimum distance between line segment vw and point p
- Vector2 dv = v[1] - v[0];
- const float l2 = nv::lengthSquared(dv); // i.e. |w-v|^2 - avoid a sqrt
- if (l2 == 0.0) {
- t = 0; // v0 == v1 case
- }
- else {
- // Consider the line extending the segment, parameterized as v + t (w - v).
- // We find projection of point p onto the line.
- // It falls where t = [(p-v) . (w-v)] / |w-v|^2
- t = dot(ip - v[0], dv) / l2;
- if (t < 0.0) {
- t = 0; // Beyond the 'v0' end of the segment
- }
- else if (t > 1.0) {
- t = 1; // Beyond the 'v1' end of the segment
- }
- }
-
- Vector2 projection = v[0] + t * dv; // Projection falls on the segment
-
- float d = distance(ip, projection);
-
- return cb(param, x, y, t, saturate(1-d));
-}
-
-
-void nv::Raster::drawLine(bool antialias, Vector2::Arg extents, bool enableScissors, const Vector2 v[2], LineSamplingCallback cb, void * param)
-{
- nvCheck(antialias == true); // @@ Not implemented.
- //nvCheck(enableScissors == false); // @@ Not implemented.
-
- // Very crappy DDA implementation.
-
- Vector2 p = v[0];
- Vector2 dp, dpdy;
-
- float dx = v[1].x - v[0].x;
- float dy = v[1].y - v[0].y;
- int n;
-
- // Degenerate line.
- if (dx == 0 && dy == 0) return;
-
- if (fabsf(dx) >= fabsf(dy)) {
- n = iround(fabsf(dx));
- dp.x = dx / fabsf(dx);
- dp.y = dy / fabsf(dx);
- nvDebugCheck(fabsf(dp.y) <= 1.0f);
- dpdy.x = 0;
- dpdy.y = 1;
- }
- else {
- n = iround(fabs(dy));
- dp.x = dx / fabsf(dy);
- dp.y = dy / fabsf(dy);
- nvDebugCheck(fabsf(dp.x) <= 1.0f);
- dpdy.x = 1;
- dpdy.y = 0;
- }
-
- for (int i = 0; i <= n; i++) {
- drawPoint(p, v, cb, param);
- drawPoint(p + dpdy, v, cb, param);
- drawPoint(p - dpdy, v, cb, param);
- p += dp;
- }
-}
-
-
-// Draw vertical or horizontal segments. For degenerate triangles.
-/*bool nv::Raster::drawSegment(Vector2::Arg extents, bool enableScissors, const Vector2 v[2], LineSamplingCallback cb, void * param)
-{
- nvCheck(enableScissors == false);
-
-
- if (v[0].x == v[1].x) { // Vertical segment.
-
- }
- else if (v[0].y == v[1].y) { // Horizontal segment.
- int y = ftoi_round(v[0].y);
- int x0 = ftoi_floor(v[0].x);
- int x1 = ftoi_floor(v[0].x);
-
- for (int x = x0; x <= x1; x++) {
-
- cb(param, x, y, t,
- }
- }
-
- return false; // Not a valid segment.
-}
-*/
diff --git a/thirdparty/thekla_atlas/nvmesh/raster/Raster.h b/thirdparty/thekla_atlas/nvmesh/raster/Raster.h
deleted file mode 100644
index 05af2ddb00..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/raster/Raster.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// This code is in the public domain -- castanyo@yahoo.es
-
-#pragma once
-#ifndef NV_MESH_RASTER_H
-#define NV_MESH_RASTER_H
-
-/** @file Raster.h
- * @brief Rasterization library.
- *
- * This is just a standard scanline rasterizer that I took from one of my old
- * projects. The perspective correction wasn't necessary so I just removed it.
-**/
-
-#include "nvmath/Vector.h"
-#include "nvmesh/nvmesh.h"
-
-namespace nv
-{
-
- namespace Raster
- {
- enum Mode {
- Mode_Nearest,
- Mode_Antialiased,
- //Mode_Conservative
- };
-
-
- /// A callback to sample the environment. Return false to terminate rasterization.
- typedef bool (NV_CDECL * SamplingCallback)(void * param, int x, int y, Vector3::Arg bar, Vector3::Arg dx, Vector3::Arg dy, float coverage);
-
- // Process the given triangle. Returns false if rasterization was interrupted by the callback.
- NVMESH_API bool drawTriangle(Mode mode, Vector2::Arg extents, bool enableScissors, const Vector2 v[3], SamplingCallback cb, void * param);
-
- // Process the given quad. Returns false if rasterization was interrupted by the callback.
- NVMESH_API bool drawQuad(Mode mode, Vector2::Arg extents, bool enableScissors, const Vector2 v[4], SamplingCallback cb, void * param);
-
- typedef bool (NV_CDECL * LineSamplingCallback)(void * param, int x, int y, float t, float d); // t is the position along the segment, d is the distance to the line.
-
- // Process the given line.
- NVMESH_API void drawLine(bool antialias, Vector2::Arg extents, bool enableScissors, const Vector2 v[2], LineSamplingCallback cb, void * param);
-
- // Draw vertical or horizontal segments. For degenerate triangles.
- //NVMESH_API void drawSegment(Vector2::Arg extents, bool enableScissors, const Vector2 v[2], SamplingCallback cb, void * param);
- }
-}
-
-
-#endif // NV_MESH_RASTER_H
diff --git a/thirdparty/thekla_atlas/nvmesh/weld/Snap.cpp b/thirdparty/thekla_atlas/nvmesh/weld/Snap.cpp
deleted file mode 100644
index b6bff4d83d..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/weld/Snap.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-// This code is in the public domain -- castanyo@yahoo.es
-
-#include <nvcore/RadixSort.h>
-
-#include <nvmesh/weld/Snap.h>
-#include <nvmesh/TriMesh.h>
-#include <nvmesh/geometry/Bounds.h>
-
-using namespace nv;
-
-namespace {
-
- // Snap the given vertices.
- void Snap(TriMesh::Vertex & a, TriMesh::Vertex & b, float texThreshold, float norThreshold)
- {
- a.pos = b.pos = (a.pos + b.pos) * 0.5f;
-
- if (equal(a.tex.x, b.tex.x, texThreshold) && equal(a.tex.y, b.tex.y, texThreshold)) {
- b.tex = a.tex = (a.tex + b.tex) * 0.5f;
- }
-
- if (equal(a.nor.x, b.nor.x, norThreshold) && equal(a.nor.y, b.nor.y, norThreshold) && equal(a.nor.z, b.nor.z, norThreshold)) {
- b.nor = a.nor = (a.nor + b.nor) * 0.5f;
- }
- };
-
-} // nv namespace
-
-uint nv::SnapVertices(TriMesh * mesh, float posThreshold, float texThreshold, float norThreshold)
-{
- nvDebug("--- Snapping vertices.\n");
-
- // Determine largest axis.
- Box box = MeshBounds::box(mesh);
- Vector3 extents = box.extents();
-
- int axis = 2;
- if( extents.x > extents.y ) {
- if( extents.x > extents.z ) {
- axis = 0;
- }
- }
- else if(extents.y > extents.z) {
- axis = 1;
- }
-
- // @@ Use diagonal instead!
-
-
- // Sort vertices according to the largest axis.
- const uint vertexCount = mesh->vertexCount();
- nvCheck(vertexCount > 2); // Must have at least two vertices.
-
- // Get pos channel.
- //PiMesh::Channel * pos_channel = mesh->GetChannel(mesh->FindChannel(VS_POS));
- //nvCheck( pos_channel != NULL );
-
- //const PiArray<Vec4> & pos_array = pos_channel->data;
-
- Array<float> distArray;
- distArray.resize(vertexCount);
-
- for(uint v = 0; v < vertexCount; v++) {
- if (axis == 0) distArray[v] = mesh->vertexAt(v).pos.x;
- else if (axis == 1) distArray[v] = mesh->vertexAt(v).pos.y;
- else distArray[v] = mesh->vertexAt(v).pos.z;
- }
-
- RadixSort radix;
- const uint * xrefs = radix.sort(distArray.buffer(), distArray.count()).ranks();
- nvCheck(xrefs != NULL);
-
- uint snapCount = 0;
- for(uint v = 0; v < vertexCount-1; v++) {
- for(uint n = v+1; n < vertexCount; n++) {
- nvDebugCheck( distArray[xrefs[v]] <= distArray[xrefs[n]] );
-
- if (fabs(distArray[xrefs[n]] - distArray[xrefs[v]]) > posThreshold) {
- break;
- }
-
- TriMesh::Vertex & v0 = mesh->vertexAt(xrefs[v]);
- TriMesh::Vertex & v1 = mesh->vertexAt(xrefs[n]);
-
- const float dist = length(v0.pos - v1.pos);
-
- if (dist <= posThreshold) {
- Snap(v0, v1, texThreshold, norThreshold);
- snapCount++;
- }
- }
- }
-
- // @@ todo: debug, make sure that the distance between vertices is now >= threshold
-
- nvDebug("--- %u vertices snapped\n", snapCount);
-
- return snapCount;
-};
-
diff --git a/thirdparty/thekla_atlas/nvmesh/weld/Snap.h b/thirdparty/thekla_atlas/nvmesh/weld/Snap.h
deleted file mode 100644
index 8e0566cda3..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/weld/Snap.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// This code is in the public domain -- castanyo@yahoo.es
-
-#ifndef NV_MESH_SNAP_H
-#define NV_MESH_SNAP_H
-
-#include <nvmesh/nvmesh.h>
-#include <nvmath/nvmath.h>
-
-namespace nv
-{
- class TriMesh;
-
- NVMESH_API uint SnapVertices(TriMesh * mesh, float posThreshold=NV_EPSILON, float texThreshold=1.0f/1024, float norThreshold=NV_NORMAL_EPSILON);
-
-} // nv namespace
-
-
-#endif // NV_MESH_SNAP_H
diff --git a/thirdparty/thekla_atlas/nvmesh/weld/VertexWeld.cpp b/thirdparty/thekla_atlas/nvmesh/weld/VertexWeld.cpp
deleted file mode 100644
index 2ba4dcae18..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/weld/VertexWeld.cpp
+++ /dev/null
@@ -1,205 +0,0 @@
-// Copyright NVIDIA Corporation 2006 -- Ignacio Castano <icastano@nvidia.com>
-
-#include <nvmesh/TriMesh.h>
-#include <nvmesh/QuadTriMesh.h>
-
-#include <nvmesh/weld/VertexWeld.h>
-#include <nvmesh/weld/Weld.h>
-
-using namespace nv;
-
-// Weld trimesh vertices
-void nv::WeldVertices(TriMesh * mesh)
-{
- nvDebug("--- Welding vertices.\n");
-
- nvCheck(mesh != NULL);
-
- uint count = mesh->vertexCount();
- Array<uint> xrefs;
- Weld<TriMesh::Vertex> weld;
- uint newCount = weld(mesh->vertices(), xrefs);
-
- nvDebug("--- %d vertices welded\n", count - newCount);
-
-
- // Remap faces.
- const uint faceCount = mesh->faceCount();
- for(uint f = 0; f < faceCount; f++)
- {
- TriMesh::Face & face = mesh->faceAt(f);
- face.v[0] = xrefs[face.v[0]];
- face.v[1] = xrefs[face.v[1]];
- face.v[2] = xrefs[face.v[2]];
- }
-}
-
-
-// Weld trimesh vertices
-void nv::WeldVertices(QuadTriMesh * mesh)
-{
- nvDebug("--- Welding vertices.\n");
-
- nvCheck(mesh != NULL);
-
- uint count = mesh->vertexCount();
- Array<uint> xrefs;
- Weld<TriMesh::Vertex> weld;
- uint newCount = weld(mesh->vertices(), xrefs);
-
- nvDebug("--- %d vertices welded\n", count - newCount);
-
- // Remap faces.
- const uint faceCount = mesh->faceCount();
- for(uint f = 0; f < faceCount; f++)
- {
- QuadTriMesh::Face & face = mesh->faceAt(f);
- face.v[0] = xrefs[face.v[0]];
- face.v[1] = xrefs[face.v[1]];
- face.v[2] = xrefs[face.v[2]];
-
- if (face.isQuadFace())
- {
- face.v[3] = xrefs[face.v[3]];
- }
- }
-}
-
-
-
-// OLD code
-
-#if 0
-
-namespace {
-
-struct VertexInfo {
- uint id; ///< Original vertex id.
- uint normal_face_group;
- uint tangent_face_group;
- uint material;
- uint chart;
-};
-
-
-/// VertexInfo hash functor.
-struct VertexHash : public IHashFunctor<VertexInfo> {
- VertexHash(PiMeshPtr m) : mesh(m) {
- uint c = mesh->FindChannel(VS_POS);
- piCheck(c != PI_NULL_INDEX);
- channel = mesh->GetChannel(c);
- piCheck(channel != NULL);
- }
-
- uint32 operator () (const VertexInfo & v) const {
- return channel->data[v.id].GetHash();
- }
-
-private:
- PiMeshPtr mesh;
- PiMesh::Channel * channel;
-};
-
-
-/// VertexInfo comparator.
-struct VertexEqual : public IBinaryPredicate<VertexInfo> {
- VertexEqual(PiMeshPtr m) : mesh(m) {}
-
- bool operator () (const VertexInfo & a, const VertexInfo & b) const {
-
- bool equal = a.normal_face_group == b.normal_face_group &&
- a.tangent_face_group == b.tangent_face_group &&
- a.material == b.material &&
- a.chart == b.chart;
-
- // Split vertex shared by different face types.
- if( !equal ) {
- return false;
- }
-
- // They were the same vertex.
- if( a.id == b.id ) {
- return true;
- }
-
- // Vertex equal if all the channels are equal.
- return mesh->IsVertexEqual(a.id, b.id);
- }
-
-private:
- PiMeshPtr mesh;
-};
-
-} // namespace
-
-
-/// Weld the vertices.
-void PiMeshVertexWeld::WeldVertices(const PiMeshSmoothGroup * mesh_smooth_group,
- const PiMeshMaterial * mesh_material, const PiMeshAtlas * mesh_atlas )
-{
- piDebug( "--- Welding vertices:\n" );
-
- piDebug( "--- Expand mesh vertices.\n" );
- PiArray<VertexInfo> vertex_array;
-
- const uint face_num = mesh->GetFaceNum();
- const uint vertex_max = face_num * 3;
- vertex_array.Resize( vertex_max );
-
- for(uint i = 0; i < vertex_max; i++) {
-
- uint f = i/3;
-
- const PiMesh::Face & face = mesh->GetFace(f);
- vertex_array[i].id = face.v[i%3];
-
- // Reset face attributes.
- vertex_array[i].normal_face_group = PI_NULL_INDEX;
- vertex_array[i].tangent_face_group = PI_NULL_INDEX;
- vertex_array[i].material = PI_NULL_INDEX;
- vertex_array[i].chart = PI_NULL_INDEX;
-
- // Set available attributes.
- if( mesh_smooth_group != NULL ) {
- if( mesh_smooth_group->HasNormalFaceGroups() ) {
- vertex_array[i].normal_face_group = mesh_smooth_group->GetNormalFaceGroup( f );
- }
- if( mesh_smooth_group->HasTangentFaceGroups() ) {
- vertex_array[i].tangent_face_group = mesh_smooth_group->GetTangentFaceGroup( f );
- }
- }
- if( mesh_material != NULL ) {
- vertex_array[i].material = mesh_material->GetFaceMaterial( f );
- }
- if( mesh_atlas != NULL && mesh_atlas->HasCharts() ) {
- vertex_array[i].chart = mesh_atlas->GetFaceChart( f );
- }
- }
- piDebug( "--- %d vertices.\n", vertex_max );
-
- piDebug( "--- Collapse vertices.\n" );
-
- uint * xrefs = new uint[vertex_max];
- VertexHash hash(mesh);
- VertexEqual equal(mesh);
- const uint vertex_num = Weld( vertex_array, xrefs, hash, equal );
- piCheck(vertex_num <= vertex_max);
- piDebug( "--- %d vertices.\n", vertex_num );
-
- // Remap face indices.
- piDebug( "--- Remapping face indices.\n" );
- mesh->RemapFaceIndices(vertex_max, xrefs);
-
-
- // Overwrite xrefs to map new vertices to old vertices.
- for(uint v = 0; v < vertex_num; v++) {
- xrefs[v] = vertex_array[v].id;
- }
-
- // Update vertex order.
- mesh->ReorderVertices(vertex_num, xrefs);
-
- delete [] xrefs;
-}
-
-#endif // 0
diff --git a/thirdparty/thekla_atlas/nvmesh/weld/VertexWeld.h b/thirdparty/thekla_atlas/nvmesh/weld/VertexWeld.h
deleted file mode 100644
index 1dc2e4ba4d..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/weld/VertexWeld.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright NVIDIA Corporation 2006 -- Ignacio Castano <icastano@nvidia.com>
-
-#ifndef NV_MESH_VERTEXWELD_H
-#define NV_MESH_VERTEXWELD_H
-
-#include <nvmesh/nvmesh.h>
-
-namespace nv
-{
- class TriMesh;
- class QuadMesh;
-
- NVMESH_API void WeldVertices(TriMesh * mesh);
- NVMESH_API void WeldVertices(QuadTriMesh * mesh);
-
-} // nv namespace
-
-
-#endif // NV_MESH_VERTEXWELD_H
diff --git a/thirdparty/thekla_atlas/nvmesh/weld/Weld.h b/thirdparty/thekla_atlas/nvmesh/weld/Weld.h
deleted file mode 100644
index e615539461..0000000000
--- a/thirdparty/thekla_atlas/nvmesh/weld/Weld.h
+++ /dev/null
@@ -1,171 +0,0 @@
-// This code is in the public domain -- castanyo@yahoo.es
-
-#ifndef NV_MESH_WELD_H
-#define NV_MESH_WELD_H
-
-#include "nvcore/Array.h"
-#include "nvcore/Hash.h"
-#include "nvcore/Utils.h" // nextPowerOfTwo
-
-#include <string.h> // for memset, memcmp, memcpy
-
-// Weld function to remove array duplicates in linear time using hashing.
-
-namespace nv
-{
-
-/// Generic welding routine. This function welds the elements of the array p
-/// and returns the cross references in the xrefs array. To compare the elements
-/// it uses the given hash and equal functors.
-///
-/// This code is based on the ideas of Ville Miettinen and Pierre Terdiman.
-template <class T, class H=Hash<T>, class E=Equal<T> >
-struct Weld
-{
- // xrefs maps old elements to new elements
- uint operator()(Array<T> & p, Array<uint> & xrefs)
- {
- const uint N = p.size(); // # of input vertices.
- uint outputCount = 0; // # of output vertices
- uint hashSize = nextPowerOfTwo(N); // size of the hash table
- uint * hashTable = new uint[hashSize + N]; // hash table + linked list
- uint * next = hashTable + hashSize; // use bottom part as linked list
-
- xrefs.resize(N);
- memset( hashTable, NIL, hashSize*sizeof(uint) ); // init hash table (NIL = 0xFFFFFFFF so memset works)
-
- H hash;
- E equal;
- for (uint i = 0; i < N; i++)
- {
- const T & e = p[i];
- uint32 hashValue = hash(e) & (hashSize-1);
- uint offset = hashTable[hashValue];
-
- // traverse linked list
- while( offset != NIL && !equal(p[offset], e) )
- {
- offset = next[offset];
- }
-
- xrefs[i] = offset;
-
- // no match found - copy vertex & add to hash
- if( offset == NIL )
- {
- // save xref
- xrefs[i] = outputCount;
-
- // copy element
- p[outputCount] = e;
-
- // link to hash table
- next[outputCount] = hashTable[hashValue];
-
- // update hash heads and increase output counter
- hashTable[hashValue] = outputCount++;
- }
- }
-
- // cleanup
- delete [] hashTable;
-
- p.resize(outputCount);
-
- // number of output vertices
- return outputCount;
- }
-};
-
-
-/// Reorder the given array accoding to the indices given in xrefs.
-template <class T>
-void reorderArray(Array<T> & array, const Array<uint> & xrefs)
-{
- const uint count = xrefs.count();
- Array<T> new_array;
- new_array.resize(count);
-
- for(uint i = 0; i < count; i++) {
- new_array[i] = array[xrefs[i]];
- }
-
- swap(array, new_array);
-}
-
-/// Reverse the given array so that new indices point to old indices.
-inline void reverseXRefs(Array<uint> & xrefs, uint count)
-{
- Array<uint> new_xrefs;
- new_xrefs.resize(count);
-
- for(uint i = 0; i < xrefs.count(); i++) {
- new_xrefs[xrefs[i]] = i;
- }
-
- swap(xrefs, new_xrefs);
-}
-
-
-
-//
-struct WeldN
-{
- uint vertexSize;
-
- WeldN(uint n) : vertexSize(n) {}
-
- // xrefs maps old elements to new elements
- uint operator()(uint8 * ptr, uint N, Array<uint> & xrefs)
- {
- uint outputCount = 0; // # of output vertices
- uint hashSize = nextPowerOfTwo(N); // size of the hash table
- uint * hashTable = new uint[hashSize + N]; // hash table + linked list
- uint * next = hashTable + hashSize; // use bottom part as linked list
-
- xrefs.resize(N);
- memset( hashTable, NIL, hashSize*sizeof(uint) ); // init hash table (NIL = 0xFFFFFFFF so memset works)
-
- for (uint i = 0; i < N; i++)
- {
- const uint8 * vertex = ptr + i * vertexSize;
- uint32 hashValue = sdbmHash(vertex, vertexSize) & (hashSize-1);
- uint offset = hashTable[hashValue];
-
- // traverse linked list
- while (offset != NIL && memcmp(ptr + offset * vertexSize, vertex, vertexSize) != 0)
- {
- offset = next[offset];
- }
-
- xrefs[i] = offset;
-
- // no match found - copy vertex & add to hash
- if (offset == NIL)
- {
- // save xref
- xrefs[i] = outputCount;
-
- // copy element
- memcpy(ptr + outputCount * vertexSize, vertex, vertexSize);
-
- // link to hash table
- next[outputCount] = hashTable[hashValue];
-
- // update hash heads and increase output counter
- hashTable[hashValue] = outputCount++;
- }
- }
-
- // cleanup
- delete [] hashTable;
-
- // number of output vertices
- return outputCount;
- }
-};
-
-
-} // nv namespace
-
-#endif // NV_MESH_WELD_H
diff --git a/thirdparty/thekla_atlas/poshlib/posh.c b/thirdparty/thekla_atlas/poshlib/posh.c
deleted file mode 100644
index bd3fcc66ea..0000000000
--- a/thirdparty/thekla_atlas/poshlib/posh.c
+++ /dev/null
@@ -1,1006 +0,0 @@
-/*
-LICENSE:
-
-Copyright (c) 2004, Brian Hook
-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.
-
- * The names of this package'ss contributors contributors may not
- 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.
-*/
-/**
- @file posh.c
- @author Brian Hook
- @date 2002
- @brief Portable Open Source Harness primary source file
-*/
-#include "posh.h"
-
-#if !defined FORCE_DOXYGEN
-
-#if !defined POSH_NO_FLOAT
-# define POSH_FLOAT_STRING "enabled"
-#else
-# define POSH_FLOAT_STRING "disabled"
-#endif
-
-#if defined POSH_64BIT_INTEGER
-# define POSH_64BIT_INTEGER_STRING "yes"
-#else
-# define POSH_64BIT_INTEGER_STRING "no"
-#endif
-
-#if defined POSH_64BIT_POINTER
-# define POSH_POINTER_STRING "64-bits"
-#else
-# define POSH_POINTER_STRING "32-bits"
-#endif
-
-#if defined POSH_LITTLE_ENDIAN
-# define IS_BIG_ENDIAN 0
-
-# define NATIVE16 POSH_LittleU16
-# define NATIVE32 POSH_LittleU32
-# define NATIVE64 POSH_LittleU64
-# define FOREIGN16 POSH_BigU16
-# define FOREIGN32 POSH_BigU32
-# define FOREIGN64 POSH_BigU64
-#else
-# define IS_BIG_ENDIAN 1
-
-# define NATIVE16 POSH_BigU16
-# define NATIVE32 POSH_BigU32
-# define NATIVE64 POSH_BigU64
-# define FOREIGN16 POSH_LittleU16
-# define FOREIGN32 POSH_LittleU32
-# define FOREIGN64 POSH_LittleU64
-#endif /* POSH_LITTLE_ENDIAN */
-
-static
-int
-s_testBigEndian( void )
-{
- union
- {
- posh_byte_t c[ 4 ];
- posh_u32_t i;
- } u;
-
- u.i= 1;
-
- if ( u.c[ 0 ] == 1 )
- {
- return 0;
- }
- return 1;
-}
-
-static
-const char *
-s_testSerialization( void )
-{
- posh_byte_t serbuf[ 8 ];
- posh_u16_t tmp16;
- posh_u32_t tmp32;
-
- /* 16-bit serialization */
- POSH_WriteU16ToLittle( serbuf, 0xABCD );
- if ( ( tmp16 = POSH_ReadU16FromLittle( serbuf ) ) != 0xABCD )
- {
- return "*ERROR: failed little-endian 16-bit serialization test";
- }
-
- POSH_WriteU16ToBig( serbuf, 0xABCD );
- if ( ( tmp16 = POSH_ReadU16FromBig( serbuf ) ) != 0xABCD )
- {
- return "*ERROR: failed big-endian 16-bit serialization test";
- }
-
- /* 32-bit serialization */
- POSH_WriteU32ToLittle( serbuf, 0xABCD1234L );
- if ( ( tmp32 = POSH_ReadU32FromLittle( serbuf ) ) != 0xABCD1234 )
- {
- return "*ERROR: failed little-endian 32-bit serialization test";
- }
-
- POSH_WriteU32ToBig( serbuf, 0xABCD1234L );
- if ( ( tmp32 = POSH_ReadU32FromBig( serbuf ) ) != 0xABCD1234 )
- {
- return "*ERROR: failed big-endian 32-bit serialization test";
- }
-
-#if defined POSH_64BIT_INTEGER
- {
-#define REF64 POSH_U64(0xFEDCBA9876543210)
-
- posh_u64_t tmp64;
-
- POSH_WriteU64ToLittle( serbuf, REF64 );
-
- if ( ( tmp64 = POSH_ReadU64FromLittle( serbuf ) ) != REF64 )
- {
- return "*ERROR: failed little-endian 64-bit serialization test";
- }
-
- POSH_WriteU64ToBig( serbuf, REF64 );
-
- if ( ( tmp64 = POSH_ReadU64FromBig( serbuf ) ) != REF64 )
- {
- return "*ERROR: failed big-endian 64-bit serialization test";
- }
- }
-#endif
-
- return 0;
-}
-
-#if !defined POSH_NO_FLOAT
-static
-const char *
-s_testFloatingPoint( void )
-{
- float fRef = 10.0f/30.0f;
- double dRef = 10.0/30.0;
- posh_byte_t dbuf[ 8 ];
- float fTmp;
- double dTmp;
-
- fTmp = POSH_FloatFromLittleBits( POSH_LittleFloatBits( fRef ) );
-
- if ( fTmp != fRef )
- {
- return "*ERROR: POSH little endian floating point conversion failed. Please report this to poshlib@poshlib.org!\n";
- }
-
- fTmp = POSH_FloatFromBigBits( POSH_BigFloatBits( fRef ) );
- if ( fTmp != fRef )
- {
- return "*ERROR: POSH big endian floating point conversion failed. Please report this to poshlib@poshlib.org!\n";
- }
-
- POSH_DoubleBits( dRef, dbuf );
-
- dTmp = POSH_DoubleFromBits( dbuf );
-
- if ( dTmp != dRef )
- {
- return "*ERROR: POSH double precision floating point serialization failed. Please report this to poshlib@poshlib.org!\n";
- }
-
- return 0;
-}
-#endif /* !defined POSH_NO_FLOAT */
-
-static
-const char *
-s_testEndianess( void )
-{
- /* check endianess */
- if ( s_testBigEndian() != IS_BIG_ENDIAN )
- {
- return "*ERROR: POSH compile time endianess does not match run-time endianess verification. Please report this to poshlib@poshlib.org!\n";
- }
-
- /* make sure our endian swap routines work */
- if ( ( NATIVE32( 0x11223344L ) != 0x11223344L ) ||
- ( FOREIGN32( 0x11223344L ) != 0x44332211L ) ||
- ( NATIVE16( 0x1234 ) != 0x1234 ) ||
- ( FOREIGN16( 0x1234 ) != 0x3412 ) )
- {
- return "*ERROR: POSH endianess macro selection failed. Please report this to poshlib@poshlib.org!\n";
- }
-
- /* test serialization routines */
-
- return 0;
-}
-#endif /* !defined FORCE_DOXYGEN */
-
-/**
- Returns a string describing this platform's basic attributes.
-
- POSH_GetArchString() reports on an architecture's statically determined
- attributes. In addition, it will perform run-time verification checks
- to make sure the various platform specific functions work. If an error
- occurs, please contact me at poshlib@poshlib.org so we can try to resolve
- what the specific failure case is.
- @returns a string describing this platform on success, or a string in the
- form "*ERROR: [text]" on failure. You can simply check to see if
- the first character returned is '*' to verify an error condition.
-*/
-const char *
-POSH_GetArchString( void )
-{
- const char *err;
- const char *s = "OS:.............."POSH_OS_STRING"\n"
- "CPU:............."POSH_CPU_STRING"\n"
- "endian:.........."POSH_ENDIAN_STRING"\n"
- "ptr size:........"POSH_POINTER_STRING"\n"
- "64-bit ints......"POSH_64BIT_INTEGER_STRING"\n"
- "floating point..."POSH_FLOAT_STRING"\n"
- "compiler........."POSH_COMPILER_STRING"\n";
-
- /* test endianess */
- err = s_testEndianess();
-
- if ( err != 0 )
- {
- return err;
- }
-
- /* test serialization */
- err = s_testSerialization();
-
- if ( err != 0 )
- {
- return err;
- }
-
-#if !defined POSH_NO_FLOAT
- /* check that our floating point support is correct */
- err = s_testFloatingPoint();
-
- if ( err != 0 )
- {
- return err;
- }
-
-#endif
-
- return s;
-}
-
-/* ---------------------------------------------------------------------------*/
-/* BYTE SWAPPING SUPPORT */
-/* ---------------------------------------------------------------------------*/
-/**
- * Byte swaps a 16-bit unsigned value
- *
- @ingroup ByteSwapFunctions
- @param v [in] unsigned 16-bit input value to swap
- @returns a byte swapped version of v
- */
-posh_u16_t
-POSH_SwapU16( posh_u16_t v )
-{
- posh_u16_t swapped;
-
- swapped = v << 8;
- swapped |= v >> 8;
-
- return swapped;
-}
-
-/**
- * Byte swaps a 16-bit signed value
- *
- @ingroup ByteSwapFunctions
- @param v [in] signed 16-bit input value to swap
- @returns a byte swapped version of v
- @remarks This just calls back to the unsigned version, since byte swapping
- is independent of sign. However, we still provide this function to
- avoid signed/unsigned mismatch compiler warnings.
- */
-posh_i16_t
-POSH_SwapI16( posh_i16_t v )
-{
- return ( posh_i16_t ) POSH_SwapU16( v );
-}
-
-/**
- * Byte swaps a 32-bit unsigned value
- *
- @ingroup ByteSwapFunctions
- @param v [in] unsigned 32-bit input value to swap
- @returns a byte swapped version of v
- */
-posh_u32_t
-POSH_SwapU32( posh_u32_t v )
-{
- posh_u32_t swapped;
-
- swapped = ( v & 0xFF ) << 24;
- swapped |= ( v & 0xFF00 ) << 8;
- swapped |= ( v >> 8 ) & 0xFF00;
- swapped |= ( v >> 24 );
-
- return swapped;
-}
-
-/**
- * Byte swaps a 32-bit signed value
- *
- @ingroup ByteSwapFunctions
- @param v [in] signed 32-bit input value to swap
- @returns a byte swapped version of v
- @remarks This just calls back to the unsigned version, since byte swapping
- is independent of sign. However, we still provide this function to
- avoid signed/unsigned mismatch compiler warnings.
- */
-posh_i32_t
-POSH_SwapI32( posh_i32_t v )
-{
- return ( posh_i32_t ) POSH_SwapU32( ( posh_u32_t ) v );
-}
-
-#if defined POSH_64BIT_INTEGER
-/**
- * Byte swaps a 64-bit unsigned value
-
- @param v [in] a 64-bit input value to swap
- @ingroup SixtyFourBit
- @returns a byte swapped version of v
-*/
-posh_u64_t
-POSH_SwapU64( posh_u64_t v )
-{
- posh_byte_t tmp;
- union {
- posh_byte_t bytes[ 8 ];
- posh_u64_t u64;
- } u;
-
- u.u64 = v;
-
- tmp = u.bytes[ 0 ]; u.bytes[ 0 ] = u.bytes[ 7 ]; u.bytes[ 7 ] = tmp;
- tmp = u.bytes[ 1 ]; u.bytes[ 1 ] = u.bytes[ 6 ]; u.bytes[ 6 ] = tmp;
- tmp = u.bytes[ 2 ]; u.bytes[ 2 ] = u.bytes[ 5 ]; u.bytes[ 5 ] = tmp;
- tmp = u.bytes[ 3 ]; u.bytes[ 3 ] = u.bytes[ 4 ]; u.bytes[ 4 ] = tmp;
-
- return u.u64;
-}
-
-/**
- * Byte swaps a 64-bit signed value
-
- @param v [in] a 64-bit input value to swap
- @ingroup SixtyFourBit
- @returns a byte swapped version of v
-*/
-posh_i64_t
-POSH_SwapI64( posh_i64_t v )
-{
- return ( posh_i64_t ) POSH_SwapU64( ( posh_u64_t ) v );
-}
-
-#endif /* defined POSH_64BIT_INTEGER */
-
-/* ---------------------------------------------------------------------------*/
-/* IN-MEMORY SERIALIZATION */
-/* ---------------------------------------------------------------------------*/
-
-/**
- * Writes an unsigned 16-bit value to a little endian buffer
-
- @ingroup MemoryBuffer
- @param dst [out] pointer to the destination buffer, may not be NULL. Alignment doesn't matter.
- @param value [in] host-endian unsigned 16-bit value
- @returns a pointer to the location two bytes after dst
- @remarks does no validation of the inputs
-*/
-posh_u16_t *
-POSH_WriteU16ToLittle( void *dst, posh_u16_t value )
-{
- posh_u16_t *p16 = ( posh_u16_t * ) dst;
- posh_byte_t *p = ( posh_byte_t * ) dst;
-
- p[ 0 ] = value & 0xFF;
- p[ 1 ] = ( value & 0xFF00) >> 8;
-
- return p16 + 1;
-}
-
-/**
- * Writes a signed 16-bit value to a little endian buffer
-
- @ingroup MemoryBuffer
- @param dst [out] pointer to the destination buffer, may not be NULL
- @param value [in] host-endian signed 16-bit value
- @returns a pointer to the location two bytes after dst
- @remarks does no validation of the inputs. This simply calls
- POSH_WriteU16ToLittle() with appropriate casting.
-*/
-posh_i16_t *
-POSH_WriteI16ToLittle( void *dst, posh_i16_t value )
-{
- return ( posh_i16_t * ) POSH_WriteU16ToLittle( dst, ( posh_u16_t ) value );
-}
-
-/**
- * Writes an unsigned 32-bit value to a little endian buffer
-
- @ingroup MemoryBuffer
- @param dst [out] pointer to the destination buffer, may not be NULL
- @param value [in] host-endian signed 32-bit value
- @returns a pointer to the location four bytes after dst
- @remarks does no validation of the inputs.
-*/
-posh_u32_t *
-POSH_WriteU32ToLittle( void *dst, posh_u32_t value )
-{
- posh_u32_t *p32 = ( posh_u32_t * ) dst;
- posh_byte_t *p = ( posh_byte_t * ) dst;
-
- p[ 0 ] = ( value & 0xFF );
- p[ 1 ] = ( value & 0xFF00 ) >> 8;
- p[ 2 ] = ( value & 0xFF0000 ) >> 16;
- p[ 3 ] = ( value & 0xFF000000 ) >> 24;
-
- return p32 + 1;
-}
-
-/**
- * Writes a signed 32-bit value to a little endian buffer
-
- @ingroup MemoryBuffer
- @param dst [out] pointer to the destination buffer, may not be NULL
- @param value [in] host-endian signed 32-bit value
- @returns a pointer to the location four bytes after dst
- @remarks does no validation of the inputs. This simply calls
- POSH_WriteU32ToLittle() with appropriate casting.
-*/
-posh_i32_t *
-POSH_WriteI32ToLittle( void *dst, posh_i32_t value )
-{
- return ( posh_i32_t * ) POSH_WriteU32ToLittle( dst, ( posh_u32_t ) value );
-}
-
-/**
- * Writes an unsigned 16-bit value to a big endian buffer
-
- @ingroup MemoryBuffer
- @param dst [out] pointer to the destination buffer, may not be NULL
- @param value [in] host-endian unsigned 16-bit value
- @returns a pointer to the location two bytes after dst
- @remarks does no validation of the inputs
-*/
-posh_u16_t *
-POSH_WriteU16ToBig( void *dst, posh_u16_t value )
-{
- posh_u16_t *p16 = ( posh_u16_t * ) dst;
- posh_byte_t *p = ( posh_byte_t * ) dst;
-
- p[ 1 ] = ( value & 0xFF );
- p[ 0 ] = ( value & 0xFF00 ) >> 8;
-
- return p16 + 1;
-}
-
-/**
- * Writes a signed 16-bit value to a big endian buffer
-
- @ingroup MemoryBuffer
- @param dst [out] pointer to the destination buffer, may not be NULL
- @param value [in] host-endian signed 16-bit value
- @returns a pointer to the location two bytes after dst
- @remarks does no validation of the inputs. This simply calls
- POSH_WriteU16ToLittle() with appropriate casting.
-*/
-posh_i16_t *
-POSH_WriteI16ToBig( void *dst, posh_i16_t value )
-{
- return ( posh_i16_t * ) POSH_WriteU16ToBig( dst, ( posh_u16_t ) value );
-}
-
-/**
- * Writes an unsigned 32-bit value to a big endian buffer
-
- @ingroup MemoryBuffer
- @param dst [out] pointer to the destination buffer, may not be NULL
- @param value [in] host-endian unsigned 32-bit value
- @returns a pointer to the location four bytes after dst
- @remarks does no validation of the inputs.
-*/
-posh_u32_t *
-POSH_WriteU32ToBig( void *dst, posh_u32_t value )
-{
- posh_u32_t *p32 = ( posh_u32_t * ) dst;
- posh_byte_t *p = ( posh_byte_t * ) dst;
-
- p[ 3 ] = ( value & 0xFF );
- p[ 2 ] = ( value & 0xFF00 ) >> 8;
- p[ 1 ] = ( value & 0xFF0000 ) >> 16;
- p[ 0 ] = ( value & 0xFF000000 ) >> 24;
-
- return p32 + 1;
-}
-
-/**
- * Writes a signed 32-bit value to a big endian buffer
-
- @ingroup MemoryBuffer
- @param dst [out] pointer to the destination buffer, may not be NULL
- @param value [in] host-endian signed 32-bit value
- @returns a pointer to the location four bytes after dst
- @remarks does no validation of the inputs. This simply calls
- POSH_WriteU32ToBig() with appropriate casting.
-*/
-posh_i32_t *
-POSH_WriteI32ToBig( void *dst, posh_i32_t value )
-{
- return ( posh_i32_t * ) POSH_WriteU32ToBig( dst, ( posh_u32_t ) value );
-}
-
-#if defined POSH_64BIT_INTEGER
-/**
- * Writes an unsigned 64-bit value to a little-endian buffer
-
- @ingroup SixtyFourBit
- @param dst [out] pointer to the destination buffer, may not be NULL
- @param value [in] host-endian unsigned 64-bit value
- @returns a pointer to the location eight bytes after dst
- @remarks does no validation of the inputs.
-*/
-posh_u64_t *
-POSH_WriteU64ToLittle( void *dst, posh_u64_t value )
-{
- posh_u64_t *p64 = ( posh_u64_t * ) dst;
- posh_byte_t *p = ( posh_byte_t * ) dst;
- int i;
-
- for ( i = 0; i < 8; i++, value >>= 8 )
- {
- p[ i ] = ( posh_byte_t ) ( value & 0xFF );
- }
-
- return p64 + 1;
-}
-
-/**
- * Writes a signed 64-bit value to a little-endian buffer
-
- @ingroup SixtyFourBit
- @param dst [out] pointer to the destination buffer, may not be NULL
- @param value [in] host-endian unsigned 64-bit value
- @returns a pointer to the location eight bytes after dst
- @remarks does no validation of the inputs.
-*/
-posh_i64_t *
-POSH_WriteI64ToLittle( void *dst, posh_i64_t value )
-{
- return ( posh_i64_t * ) POSH_WriteU64ToLittle( dst, ( posh_u64_t ) value );
-}
-
-/**
- * Writes an unsigned 64-bit value to a big-endian buffer
-
- @ingroup SixtyFourBit
- @param dst [out] pointer to the destination buffer, may not be NULL
- @param value [in] host-endian unsigned 64-bit value
- @returns a pointer to the location eight bytes after dst
- @remarks does no validation of the inputs.
-*/
-posh_u64_t *
-POSH_WriteU64ToBig( void *dst, posh_u64_t value )
-{
- posh_u64_t *p64 = ( posh_u64_t * ) dst;
- posh_byte_t *p = ( posh_byte_t * ) dst;
- int i;
-
- for ( i = 0; i < 8; i++, value >>= 8 )
- {
- p[ 7-i ] = ( posh_byte_t ) ( value & 0xFF );
- }
-
- return p64 + 8;
-}
-
-/**
- * Writes a signed 64-bit value to a big-endian buffer
-
- @ingroup SixtyFourBit
- @param dst [out] pointer to the destination buffer, may not be NULL
- @param value [in] host-endian signed 64-bit value
- @returns a pointer to the location eight bytes after dst
- @remarks does no validation of the inputs.
-*/
-posh_i64_t *
-POSH_WriteI64ToBig( void *dst, posh_i64_t value )
-{
- return ( posh_i64_t * ) POSH_WriteU64ToBig( dst, ( posh_u64_t ) value );
-}
-
-#endif /* POSH_64BIT_INTEGER */
-
-/* ---------------------------------------------------------------------------*/
-/* IN-MEMORY DESERIALIZATION */
-/* ---------------------------------------------------------------------------*/
-
-/**
- * Reads an unsigned 16-bit value from a little-endian buffer
- @ingroup MemoryBuffer
- @param src [in] source buffer
- @returns host-endian unsigned 16-bit value
-*/
-posh_u16_t
-POSH_ReadU16FromLittle( const void *src )
-{
- posh_u16_t v = 0;
- posh_byte_t *p = ( posh_byte_t * ) src;
-
- v |= p[ 0 ];
- v |= ( ( posh_u16_t ) p[ 1 ] ) << 8;
-
- return v;
-}
-
-/**
- * Reads a signed 16-bit value from a little-endian buffer
- @ingroup MemoryBuffer
- @param src [in] source buffer
- @returns host-endian signed 16-bit value
-*/
-posh_i16_t
-POSH_ReadI16FromLittle( const void *src )
-{
- return ( posh_i16_t ) POSH_ReadU16FromLittle( src );
-}
-
-/**
- * Reads an unsigned 32-bit value from a little-endian buffer
- @ingroup MemoryBuffer
- @param src [in] source buffer
- @returns host-endian unsigned 32-bit value
-*/
-posh_u32_t
-POSH_ReadU32FromLittle( const void *src )
-{
- posh_u32_t v = 0;
- posh_byte_t *p = ( posh_byte_t * ) src;
-
- v |= p[ 0 ];
- v |= ( ( posh_u32_t ) p[ 1 ] ) << 8;
- v |= ( ( posh_u32_t ) p[ 2 ] ) << 16;
- v |= ( ( posh_u32_t ) p[ 3 ] ) << 24;
-
- return v;
-}
-
-/**
- * Reads a signed 32-bit value from a little-endian buffer
- @ingroup MemoryBuffer
- @param src [in] source buffer
- @returns host-endian signed 32-bit value
-*/
-posh_i32_t
-POSH_ReadI32FromLittle( const void *src )
-{
- return ( posh_i32_t ) POSH_ReadU32FromLittle( src );
-}
-
-
-/**
- * Reads an unsigned 16-bit value from a big-endian buffer
- @ingroup MemoryBuffer
- @param src [in] source buffer
- @returns host-endian unsigned 16-bit value
-*/
-posh_u16_t
-POSH_ReadU16FromBig( const void *src )
-{
- posh_u16_t v = 0;
- posh_byte_t *p = ( posh_byte_t * ) src;
-
- v |= p[ 1 ];
- v |= ( ( posh_u16_t ) p[ 0 ] ) << 8;
-
- return v;
-}
-
-/**
- * Reads a signed 16-bit value from a big-endian buffer
- @ingroup MemoryBuffer
- @param src [in] source buffer
- @returns host-endian signed 16-bit value
-*/
-posh_i16_t
-POSH_ReadI16FromBig( const void *src )
-{
- return ( posh_i16_t ) POSH_ReadU16FromBig( src );
-}
-
-/**
- * Reads an unsigned 32-bit value from a big-endian buffer
- @ingroup MemoryBuffer
- @param src [in] source buffer
- @returns host-endian unsigned 32-bit value
-*/
-posh_u32_t
-POSH_ReadU32FromBig( const void *src )
-{
- posh_u32_t v = 0;
- posh_byte_t *p = ( posh_byte_t * ) src;
-
- v |= p[ 3 ];
- v |= ( ( posh_u32_t ) p[ 2 ] ) << 8;
- v |= ( ( posh_u32_t ) p[ 1 ] ) << 16;
- v |= ( ( posh_u32_t ) p[ 0 ] ) << 24;
-
- return v;
-}
-
-/**
- * Reads a signed 32-bit value from a big-endian buffer
- @ingroup MemoryBuffer
- @param src [in] source buffer
- @returns host-endian signed 32-bit value
-*/
-posh_i32_t
-POSH_ReadI32FromBig( const void *src )
-{
- return POSH_BigI32( (*(const posh_i32_t*)src ) );
-}
-
-#if defined POSH_64BIT_INTEGER
-
-/**
- * Reads an unsigned 64-bit value from a little-endian buffer
- @param src [in] source buffer
- @returns host-endian unsigned 32-bit value
-*/
-posh_u64_t
-POSH_ReadU64FromLittle( const void *src )
-{
- posh_u64_t v = 0;
- posh_byte_t *p = ( posh_byte_t * ) src;
- int i;
-
- for ( i = 0; i < 8; i++ )
- {
- v |= ( ( posh_u64_t ) p[ i ] ) << (i*8);
- }
-
- return v;
-}
-
-/**
- * Reads a signed 64-bit value from a little-endian buffer
- @param src [in] source buffer
- @returns host-endian signed 32-bit value
-*/
-posh_i64_t
-POSH_ReadI64FromLittle( const void *src )
-{
- return ( posh_i64_t ) POSH_ReadU64FromLittle( src );
-}
-
-/**
- * Reads an unsigned 64-bit value from a big-endian buffer
- @param src [in] source buffer
- @returns host-endian unsigned 32-bit value
-*/
-posh_u64_t
-POSH_ReadU64FromBig( const void *src )
-{
- posh_u64_t v = 0;
- posh_byte_t *p = ( posh_byte_t * ) src;
- int i;
-
- for ( i = 0; i < 8; i++ )
- {
- v |= ( ( posh_u64_t ) p[ 7-i ] ) << (i*8);
- }
-
- return v;
-}
-
-/**
- * Reads an signed 64-bit value from a big-endian buffer
- @param src [in] source buffer
- @returns host-endian signed 32-bit value
-*/
-posh_i64_t
-POSH_ReadI64FromBig( const void *src )
-{
- return ( posh_i64_t ) POSH_ReadU64FromBig( src );
-}
-
-#endif /* POSH_64BIT_INTEGER */
-
-/* ---------------------------------------------------------------------------*/
-/* FLOATING POINT SUPPORT */
-/* ---------------------------------------------------------------------------*/
-
-#if !defined POSH_NO_FLOAT
-
-/** @ingroup FloatingPoint
- @param[in] f floating point value
- @returns a little-endian bit representation of f
- */
-posh_u32_t
-POSH_LittleFloatBits( float f )
-{
- union
- {
- float f32;
- posh_u32_t u32;
- } u;
-
- u.f32 = f;
-
- return POSH_LittleU32( u.u32 );
-}
-
-/**
- * Extracts raw big-endian bits from a 32-bit floating point value
- *
- @ingroup FloatingPoint
- @param f [in] floating point value
- @returns a big-endian bit representation of f
- */
-posh_u32_t
-POSH_BigFloatBits( float f )
-{
- union
- {
- float f32;
- posh_u32_t u32;
- } u;
-
- u.f32 = f;
-
- return POSH_BigU32( u.u32 );
-}
-
-/**
- * Extracts raw, little-endian bit representation from a 64-bit double.
- *
- @param d [in] 64-bit double precision value
- @param dst [out] 8-byte storage buffer
- @ingroup FloatingPoint
- @returns the raw bits used to represent the value 'd', in the form dst[0]=LSB
- */
-void
-POSH_DoubleBits( double d, posh_byte_t dst[ 8 ] )
-{
- union
- {
- double d64;
- posh_byte_t bytes[ 8 ];
- } u;
-
- u.d64 = d;
-
-#if defined POSH_LITTLE_ENDIAN
- dst[ 0 ] = u.bytes[ 0 ];
- dst[ 1 ] = u.bytes[ 1 ];
- dst[ 2 ] = u.bytes[ 2 ];
- dst[ 3 ] = u.bytes[ 3 ];
- dst[ 4 ] = u.bytes[ 4 ];
- dst[ 5 ] = u.bytes[ 5 ];
- dst[ 6 ] = u.bytes[ 6 ];
- dst[ 7 ] = u.bytes[ 7 ];
-#else
- dst[ 0 ] = u.bytes[ 7 ];
- dst[ 1 ] = u.bytes[ 6 ];
- dst[ 2 ] = u.bytes[ 5 ];
- dst[ 3 ] = u.bytes[ 4 ];
- dst[ 4 ] = u.bytes[ 3 ];
- dst[ 5 ] = u.bytes[ 2 ];
- dst[ 6 ] = u.bytes[ 1 ];
- dst[ 7 ] = u.bytes[ 0 ];
-#endif
-}
-
-/**
- * Creates a double-precision, 64-bit floating point value from a set of raw,
- * little-endian bits
-
- @ingroup FloatingPoint
- @param src [in] little-endian byte representation of 64-bit double precision
- floating point value
- @returns double precision floating point representation of the raw bits
- @remarks No error checking is performed, so there are no guarantees that the
- result is a valid number, nor is there any check to ensure that src is
- non-NULL. BE CAREFUL USING THIS.
- */
-double
-POSH_DoubleFromBits( const posh_byte_t src[ 8 ] )
-{
- union
- {
- double d64;
- posh_byte_t bytes[ 8 ];
- } u;
-
-#if defined POSH_LITTLE_ENDIAN
- u.bytes[ 0 ] = src[ 0 ];
- u.bytes[ 1 ] = src[ 1 ];
- u.bytes[ 2 ] = src[ 2 ];
- u.bytes[ 3 ] = src[ 3 ];
- u.bytes[ 4 ] = src[ 4 ];
- u.bytes[ 5 ] = src[ 5 ];
- u.bytes[ 6 ] = src[ 6 ];
- u.bytes[ 7 ] = src[ 7 ];
-#else
- u.bytes[ 0 ] = src[ 7 ];
- u.bytes[ 1 ] = src[ 6 ];
- u.bytes[ 2 ] = src[ 5 ];
- u.bytes[ 3 ] = src[ 4 ];
- u.bytes[ 4 ] = src[ 3 ];
- u.bytes[ 5 ] = src[ 2 ];
- u.bytes[ 6 ] = src[ 1 ];
- u.bytes[ 7 ] = src[ 0 ];
-#endif
-
- return u.d64;
-}
-
-/**
- * Creates a floating point number from little endian bits
- *
- @ingroup FloatingPoint
- @param bits [in] raw floating point bits in little-endian form
- @returns a floating point number based on the given bit representation
- @remarks No error checking is performed, so there are no guarantees that the
- result is a valid number. BE CAREFUL USING THIS.
- */
-float
-POSH_FloatFromLittleBits( posh_u32_t bits )
-{
- union
- {
- float f32;
- posh_u32_t u32;
- } u;
-
- u.u32 = bits;
-#if defined POSH_BIG_ENDIAN
- u.u32 = POSH_SwapU32( u.u32 );
-#endif
-
- return u.f32;
-}
-
-/**
- * Creates a floating point number from big-endian bits
- *
- @ingroup FloatingPoint
- @param bits [in] raw floating point bits in big-endian form
- @returns a floating point number based on the given bit representation
- @remarks No error checking is performed, so there are no guarantees that the
- result is a valid number. BE CAREFUL USING THIS.
- */
-float
-POSH_FloatFromBigBits( posh_u32_t bits )
-{
- union
- {
- float f32;
- posh_u32_t u32;
- } u;
-
- u.u32 = bits;
-#if defined POSH_LITTLE_ENDIAN
- u.u32 = POSH_SwapU32( u.u32 );
-#endif
-
- return u.f32;
-}
-
-#endif /* !defined POSH_NO_FLOAT */
diff --git a/thirdparty/thekla_atlas/poshlib/posh.h b/thirdparty/thekla_atlas/poshlib/posh.h
deleted file mode 100644
index 72acd20ce0..0000000000
--- a/thirdparty/thekla_atlas/poshlib/posh.h
+++ /dev/null
@@ -1,1040 +0,0 @@
-/**
-@file posh.h
-@author Brian Hook
-@version 1.3.001
-
-Header file for POSH, the Portable Open Source Harness project.
-
-NOTE: Unlike most header files, this one is designed to be included
-multiple times, which is why it does not have the @#ifndef/@#define
-preamble.
-
-POSH relies on environment specified preprocessor symbols in order
-to infer as much as possible about the target OS/architecture and
-the host compiler capabilities.
-
-NOTE: POSH is simple and focused. It attempts to provide basic
-functionality and information, but it does NOT attempt to emulate
-missing functionality. I am also not willing to make POSH dirty
-and hackish to support truly ancient and/or outmoded and/or bizarre
-technologies such as non-ANSI compilers, systems with non-IEEE
-floating point formats, segmented 16-bit operating systems, etc.
-
-Please refer to the accompanying HTML documentation or visit
-http://www.poshlib.org for more information on how to use POSH.
-
-LICENSE:
-
-Copyright (c) 2004, Brian Hook
-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.
-
- * The names of this package'ss contributors contributors may not
- 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.
-
-REVISION:
-
-I've been lax about revision histories, so this starts at, um, 1.3.001.
-Sorry for any inconveniences.
-
-1.3.001 - 2/23/2006 - Incorporated fix for bug reported by Bill Cary,
- where I was not detecting Visual Studio
- compilation on x86-64 systems. Added check for
- _M_X64 which should fix that.
-
-*/
-/*
-I have yet to find an authoritative reference on preprocessor
-symbols, but so far this is what I've gleaned:
-
-GNU GCC/G++:
- - __GNUC__: GNU C version
- - __GNUG__: GNU C++ compiler
- - __sun__ : on Sun platforms
- - __svr4__: on Solaris and other SysV R4 platforms
- - __mips__: on MIPS processor platforms
- - __sparc_v9__: on Sparc 64-bit CPUs
- - __sparcv9: 64-bit Solaris
- - __MIPSEL__: mips processor, compiled for little endian
- - __MIPSEB__: mips processor, compiled for big endian
- - _R5900: MIPS/Sony/Toshiba R5900 (PS2)
- - mc68000: 68K
- - m68000: 68K
- - m68k: 68K
- - __palmos__: PalmOS
-
-Intel C/C++ Compiler:
- - __ECC : compiler version, IA64 only
- - __EDG__
- - __ELF__
- - __GXX_ABI_VERSION
- - __i386 : IA-32 only
- - __i386__ : IA-32 only
- - i386 : IA-32 only
- - __ia64 : IA-64 only
- - __ia64__ : IA-64 only
- - ia64 : IA-64 only
- - __ICC : IA-32 only
- - __INTEL_COMPILER : IA-32 or IA-64, newer versions only
-
-Apple's C/C++ Compiler for OS X:
- - __APPLE_CC__
- - __APPLE__
- - __BIG_ENDIAN__
- - __APPLE__
- - __ppc__
- - __MACH__
-
-DJGPP:
- - __MSDOS__
- - __unix__
- - __unix
- - __GNUC__
- - __GO32
- - DJGPP
- - __i386, __i386, i386
-
-Cray's C compiler:
- - _ADDR64: if 64-bit pointers
- - _UNICOS:
- - __unix:
-
-SGI's CC compiler predefines the following (and more) with -ansi:
- - __sgi
- - __unix
- - __host_mips
- - _SYSTYPE_SVR4
- - __mips
- - _MIPSEB
- - anyone know if there is a predefined symbol for the compiler?!
-
-MinGW:
- - as GnuC but also defines _WIN32, __WIN32, WIN32, _X86_, __i386, __i386__, and several others
- - __MINGW32__
-
-Cygwin:
- - as Gnu C, but also
- - __unix__
- - __CYGWIN32__
-
-Microsoft Visual Studio predefines the following:
- - _MSC_VER
- - _WIN32: on Win32
- - _M_IX6 (on x86 systems)
- - _M_X64: on x86-64 systems
- - _M_ALPHA (on DEC AXP systems)
- - _SH3: WinCE, Hitachi SH-3
- - _MIPS: WinCE, MIPS
- - _ARM: WinCE, ARM
-
-Sun's C Compiler:
- - sun and _sun
- - unix and _unix
- - sparc and _sparc (SPARC systems only)
- - i386 and _i386 (x86 systems only)
- - __SVR4 (Solaris only)
- - __sparcv9: 64-bit solaris
- - __SUNPRO_C
- - _LP64: defined in 64-bit LP64 mode, but only if <sys/types.h> is included
-
-Borland C/C++ predefines the following:
- - __BORLANDC__:
-
-DEC/Compaq C/C++ on Alpha:
- - __alpha
- - __arch64__
- - __unix__ (on Tru64 Unix)
- - __osf__
- - __DECC
- - __DECCXX (C++ compilation)
- - __DECC_VER
- - __DECCXX_VER
-
-IBM's AIX compiler:
- - __64BIT__ if 64-bit mode
- - _AIX
- - __IBMC__: C compiler version
- - __IBMCPP__: C++ compiler version
- - _LONG_LONG: compiler allows long long
-
-Watcom:
- - __WATCOMC__
- - __DOS__ : if targeting DOS
- - __386__ : if 32-bit support
- - __WIN32__ : if targetin 32-bit Windows
-
-HP-UX C/C++ Compiler:
- - __hpux
- - __unix
- - __hppa (on PA-RISC)
- - __LP64__: if compiled in 64-bit mode
-
-Metrowerks:
- - __MWERKS__
- - __powerpc__
- - _powerc
- - __MC68K__
- - macintosh when compiling for MacOS
- - __INTEL__ for x86 targets
- - __POWERPC__
-
-*/
-
-/*
-** ----------------------------------------------------------------------------
-** Include <limits.h> optionally
-** ----------------------------------------------------------------------------
-*/
-#ifdef POSH_USE_LIMITS_H
-# include <limits.h>
-#endif
-
-/*
-** ----------------------------------------------------------------------------
-** Determine compilation environment
-** ----------------------------------------------------------------------------
-*/
-#if defined __ECC || defined __ICC || defined __INTEL_COMPILER
-# define POSH_COMPILER_STRING "Intel C/C++"
-# define POSH_COMPILER_INTEL 1
-#endif
-
-#if ( defined __host_mips || defined __sgi ) && !defined __GNUC__
-# define POSH_COMPILER_STRING "MIPSpro C/C++"
-# define POSH_COMPILER_MIPSPRO 1
-#endif
-
-#if defined __hpux && !defined __GNUC__
-# define POSH_COMPILER_STRING "HP-UX CC"
-# define POSH_COMPILER_HPCC 1
-#endif
-
-#if defined __GNUC__ && !defined __clang__
-# define POSH_COMPILER_STRING "Gnu GCC"
-# define POSH_COMPILER_GCC 1
-#endif
-
-#if defined __clang__
-# define POSH_COMPILER_STRING "Clang"
-# define POSH_COMPILER_CLANG 1
-#endif
-
-#if defined __APPLE_CC__
- /* we don't define the compiler string here, let it be GNU */
-# define POSH_COMPILER_APPLECC 1
-#endif
-
-#if defined __IBMC__ || defined __IBMCPP__
-# define POSH_COMPILER_STRING "IBM C/C++"
-# define POSH_COMPILER_IBM 1
-#endif
-
-#if defined _MSC_VER
-# define POSH_COMPILER_STRING "Microsoft Visual C++"
-# define POSH_COMPILER_MSVC 1
-#endif
-
-#if defined __SUNPRO_C
-# define POSH_COMPILER_STRING "Sun Pro"
-# define POSH_COMPILER_SUN 1
-#endif
-
-#if defined __BORLANDC__
-# define POSH_COMPILER_STRING "Borland C/C++"
-# define POSH_COMPILER_BORLAND 1
-#endif
-
-#if defined __MWERKS__
-# define POSH_COMPILER_STRING "MetroWerks CodeWarrior"
-# define POSH_COMPILER_METROWERKS 1
-#endif
-
-#if defined __DECC || defined __DECCXX
-# define POSH_COMPILER_STRING "Compaq/DEC C/C++"
-# define POSH_COMPILER_DEC 1
-#endif
-
-#if defined __WATCOMC__
-# define POSH_COMPILER_STRING "Watcom C/C++"
-# define POSH_COMPILER_WATCOM 1
-#endif
-
-#if !defined POSH_COMPILER_STRING
-# define POSH_COMPILER_STRING "Unknown compiler"
-#endif
-
-/*
-** ----------------------------------------------------------------------------
-** Determine target operating system
-** ----------------------------------------------------------------------------
-*/
-#if defined linux || defined __linux__
-# define POSH_OS_LINUX 1
-# define POSH_OS_STRING "Linux"
-#endif
-
-#if defined __HAIKU__
-# define POSH_OS_HAIKU 1
-# define POSH_OS_STRING "Haiku"
-#endif
-
-#if defined __FreeBSD__
-# define POSH_OS_FREEBSD 1
-# define POSH_OS_STRING "FreeBSD"
-#endif
-
-#if defined __CYGWIN32__
-# define POSH_OS_CYGWIN32 1
-# define POSH_OS_STRING "Cygwin"
-#endif
-
-#if defined GEKKO
-# define POSH_OS_GAMECUBE
-# define __powerpc__
-# define POSH_OS_STRING "GameCube"
-#endif
-
-#if defined __MINGW32__
-# define POSH_OS_MINGW 1
-# define POSH_OS_STRING "MinGW"
-#endif
-
-#if defined GO32 && defined DJGPP && defined __MSDOS__
-# define POSH_OS_GO32 1
-# define POSH_OS_STRING "GO32/MS-DOS"
-#endif
-
-/* NOTE: make sure you use /bt=DOS if compiling for 32-bit DOS,
- otherwise Watcom assumes host=target */
-#if defined __WATCOMC__ && defined __386__ && defined __DOS__
-# define POSH_OS_DOS32 1
-# define POSH_OS_STRING "DOS/32-bit"
-#endif
-
-#if defined _UNICOS
-# define POSH_OS_UNICOS 1
-# define POSH_OS_STRING "UNICOS"
-#endif
-
-//ACS if we're in xcode, look at the target conditionals to figure out if this is ios or osx
-#if defined __APPLE__
-# include "TargetConditionals.h"
-#endif
-#if TARGET_OS_IPHONE
-# define POSH_OS_IOS 1
-# define POSH_OS_STRING "iOS"
-#else
-# if ( defined __MWERKS__ && defined __powerc && !defined macintosh ) || defined __APPLE_CC__ || defined macosx
-# define POSH_OS_OSX 1
-# define POSH_OS_STRING "MacOS X"
-# endif
-#endif
-
-#if defined __sun__ || defined sun || defined __sun || defined __solaris__
-# if defined __SVR4 || defined __svr4__ || defined __solaris__
-# define POSH_OS_STRING "Solaris"
-# define POSH_OS_SOLARIS 1
-# endif
-# if !defined POSH_OS_STRING
-# define POSH_OS_STRING "SunOS"
-# define POSH_OS_SUNOS 1
-# endif
-#endif
-
-#if defined __sgi__ || defined sgi || defined __sgi
-# define POSH_OS_IRIX 1
-# define POSH_OS_STRING "Irix"
-#endif
-
-#if defined __hpux__ || defined __hpux
-# define POSH_OS_HPUX 1
-# define POSH_OS_STRING "HP-UX"
-#endif
-
-#if defined _AIX
-# define POSH_OS_AIX 1
-# define POSH_OS_STRING "AIX"
-#endif
-
-#if ( defined __alpha && defined __osf__ )
-# define POSH_OS_TRU64 1
-# define POSH_OS_STRING "Tru64"
-#endif
-
-#if defined __BEOS__ || defined __beos__
-# define POSH_OS_BEOS 1
-# define POSH_OS_STRING "BeOS"
-#endif
-
-#if defined amiga || defined amigados || defined AMIGA || defined _AMIGA
-# define POSH_OS_AMIGA 1
-# define POSH_OS_STRING "Amiga"
-#endif
-
-#if defined __unix__
-# define POSH_OS_UNIX 1
-# if !defined POSH_OS_STRING
-# define POSH_OS_STRING "Unix-like(generic)"
-# endif
-#endif
-
-#if defined _WIN32_WCE
-# define POSH_OS_WINCE 1
-# define POSH_OS_STRING "Windows CE"
-#endif
-
-#if defined _XBOX || defined _XBOX_VER
-# define POSH_OS_XBOX 1
-# define POSH_OS_STRING "XBOX"
-#endif
-
-#if defined __ORBIS__
-# define POSH_OS_ORBIS
-#endif
-
-#if defined _WIN32 || defined WIN32 || defined __NT__ || defined __WIN32__
-# if !defined POSH_OS_XBOX
-# define POSH_OS_WIN32 1
-# if defined _WIN64
-# define POSH_OS_WIN64 1
-# define POSH_OS_STRING "Win64"
-# else
-# if !defined POSH_OS_STRING
-# define POSH_OS_STRING "Win32"
-# endif
-# endif
-# endif
-#endif
-
-#if defined __palmos__
-# define POSH_OS_PALM 1
-# define POSH_OS_STRING "PalmOS"
-#endif
-
-#if defined THINK_C || defined macintosh
-# define POSH_OS_MACOS 1
-# define POSH_OS_STRING "MacOS"
-#endif
-
-/*
-** -----------------------------------------------------------------------------
-** Determine target CPU
-** -----------------------------------------------------------------------------
-*/
-
-#if defined GEKKO
-# define POSH_CPU_PPC750 1
-# define POSH_CPU_STRING "IBM PowerPC 750 (NGC)"
-#endif
-
-#if defined mc68000 || defined m68k || defined __MC68K__ || defined m68000
-# define POSH_CPU_68K 1
-# define POSH_CPU_STRING "MC68000"
-#endif
-
-#if defined __PPC__ || defined __POWERPC__ || defined powerpc || defined _POWER || defined __ppc__ || defined __powerpc__ || defined _M_PPC
-# define POSH_CPU_PPC 1
-# if !defined POSH_CPU_STRING
-# if defined __powerpc64__
-# define POSH_CPU_STRING "PowerPC64"
-# else
-# define POSH_CPU_STRING "PowerPC"
-# endif
-# endif
-#endif
-
-#if defined _CRAYT3E || defined _CRAYMPP
-# define POSH_CPU_CRAYT3E 1 /* target processor is a DEC Alpha 21164 used in a Cray T3E*/
-# define POSH_CPU_STRING "Cray T3E (Alpha 21164)"
-#endif
-
-#if defined CRAY || defined _CRAY && !defined _CRAYT3E
-# error Non-AXP Cray systems not supported
-#endif
-
-#if defined _SH3
-# define POSH_CPU_SH3 1
-# define POSH_CPU_STRING "Hitachi SH-3"
-#endif
-
-#if defined __sh4__ || defined __SH4__
-# define POSH_CPU_SH3 1
-# define POSH_CPU_SH4 1
-# define POSH_CPU_STRING "Hitachi SH-4"
-#endif
-
-#if defined __sparc__ || defined __sparc
-# if defined __arch64__ || defined __sparcv9 || defined __sparc_v9__
-# define POSH_CPU_SPARC64 1
-# define POSH_CPU_STRING "Sparc/64"
-# else
-# define POSH_CPU_STRING "Sparc/32"
-# endif
-# define POSH_CPU_SPARC 1
-#endif
-
-#if defined ARM || defined __arm__ || defined _ARM
-# define POSH_CPU_STRONGARM 1
-# define POSH_CPU_STRING "ARM"
-#endif
-
-#if defined AARCH64 || defined __aarch64__ || defined _AARCH64
-# define POSH_CPU_STRONGARM 1
-# define POSH_CPU_STRING "AARCH64"
-#endif
-
-#if defined mips || defined __mips__ || defined __MIPS__ || defined _MIPS
-# define POSH_CPU_MIPS 1
-# if defined _R5900
-# define POSH_CPU_STRING "MIPS R5900 (PS2)"
-# else
-# define POSH_CPU_STRING "MIPS"
-# endif
-#endif
-
-#if defined __ia64 || defined _M_IA64 || defined __ia64__
-# define POSH_CPU_IA64 1
-# define POSH_CPU_STRING "IA64"
-#endif
-
-#if defined __X86__ || defined __i386__ || defined i386 || defined _M_IX86 || defined __386__ || defined __x86_64__ || defined _M_X64
-# define POSH_CPU_X86 1
-# if defined __x86_64__ || defined _M_X64
-# define POSH_CPU_X86_64 1
-# endif
-# if defined POSH_CPU_X86_64
-# define POSH_CPU_STRING "AMD x86-64"
-# else
-# define POSH_CPU_STRING "Intel 386+"
-# endif
-#endif
-
-#if defined __alpha || defined alpha || defined _M_ALPHA || defined __alpha__
-# define POSH_CPU_AXP 1
-# define POSH_CPU_STRING "AXP"
-#endif
-
-#if defined __hppa || defined hppa
-# define POSH_CPU_HPPA 1
-# define POSH_CPU_STRING "PA-RISC"
-#endif
-
-#if !defined POSH_CPU_STRING
-# error POSH cannot determine target CPU
-# define POSH_CPU_STRING "Unknown" /* this is here for Doxygen's benefit */
-#endif
-
-/*
-** -----------------------------------------------------------------------------
-** Attempt to autodetect building for embedded on Sony PS2
-** -----------------------------------------------------------------------------
-*/
-#if !defined POSH_OS_STRING
-# if !defined FORCE_DOXYGEN
-# define POSH_OS_EMBEDDED 1
-# endif
-# if defined _R5900
-# define POSH_OS_STRING "Sony PS2(embedded)"
-# else
-# define POSH_OS_STRING "Embedded/Unknown"
-# endif
-#endif
-
-/*
-** ---------------------------------------------------------------------------
-** Handle cdecl, stdcall, fastcall, etc.
-** ---------------------------------------------------------------------------
-*/
-#if defined POSH_CPU_X86 && !defined POSH_CPU_X86_64
-# if defined __GNUC__
-# define POSH_CDECL __attribute__((cdecl))
-# define POSH_STDCALL __attribute__((stdcall))
-# define POSH_FASTCALL __attribute__((fastcall))
-# elif ( defined _MSC_VER || defined __WATCOMC__ || defined __BORLANDC__ || defined __MWERKS__ )
-# define POSH_CDECL __cdecl
-# define POSH_STDCALL __stdcall
-# define POSH_FASTCALL __fastcall
-# endif
-#else
-# define POSH_CDECL
-# define POSH_STDCALL
-# define POSH_FASTCALL
-#endif
-
-/*
-** ---------------------------------------------------------------------------
-** Define POSH_IMPORTEXPORT signature based on POSH_DLL and POSH_BUILDING_LIB
-** ---------------------------------------------------------------------------
-*/
-
-/*
-** We undefine this so that multiple inclusions will work
-*/
-#if defined POSH_IMPORTEXPORT
-# undef POSH_IMPORTEXPORT
-#endif
-
-#if defined POSH_DLL
-# if defined POSH_OS_WIN32
-# if defined _MSC_VER
-# if ( _MSC_VER >= 800 )
-# if defined POSH_BUILDING_LIB
-# define POSH_IMPORTEXPORT __declspec( dllexport )
-# else
-# define POSH_IMPORTEXPORT __declspec( dllimport )
-# endif
-# else
-# if defined POSH_BUILDING_LIB
-# define POSH_IMPORTEXPORT __export
-# else
-# define POSH_IMPORTEXPORT
-# endif
-# endif
-# endif /* defined _MSC_VER */
-# if defined __BORLANDC__
-# if ( __BORLANDC__ >= 0x500 )
-# if defined POSH_BUILDING_LIB
-# define POSH_IMPORTEXPORT __declspec( dllexport )
-# else
-# define POSH_IMPORTEXPORT __declspec( dllimport )
-# endif
-# else
-# if defined POSH_BUILDING_LIB
-# define POSH_IMPORTEXPORT __export
-# else
-# define POSH_IMPORTEXPORT
-# endif
-# endif
-# endif /* defined __BORLANDC__ */
- /* for all other compilers, we're just making a blanket assumption */
-# if defined __GNUC__ || defined __WATCOMC__ || defined __MWERKS__
-# if defined POSH_BUILDING_LIB
-# define POSH_IMPORTEXPORT __declspec( dllexport )
-# else
-# define POSH_IMPORTEXPORT __declspec( dllimport )
-# endif
-# endif /* all other compilers */
-# if !defined POSH_IMPORTEXPORT
-# error Building DLLs not supported on this compiler (poshlib@poshlib.org if you know how)
-# endif
-# endif /* defined POSH_OS_WIN32 */
-#endif
-
-/* On pretty much everything else, we can thankfully just ignore this */
-#if !defined POSH_IMPORTEXPORT
-# define POSH_IMPORTEXPORT
-#endif
-
-#if defined FORCE_DOXYGEN
-# define POSH_DLL
-# define POSH_BUILDING_LIB
-# undef POSH_DLL
-# undef POSH_BUILDING_LIB
-#endif
-
-/*
-** ----------------------------------------------------------------------------
-** (Re)define POSH_PUBLIC_API export signature
-** ----------------------------------------------------------------------------
-*/
-#ifdef POSH_PUBLIC_API
-# undef POSH_PUBLIC_API
-#endif
-
-#if ( ( defined _MSC_VER ) && ( _MSC_VER < 800 ) ) || ( defined __BORLANDC__ && ( __BORLANDC__ < 0x500 ) )
-# define POSH_PUBLIC_API(rtype) extern rtype POSH_IMPORTEXPORT
-#else
-# define POSH_PUBLIC_API(rtype) extern POSH_IMPORTEXPORT rtype
-#endif
-
-/*
-** ----------------------------------------------------------------------------
-** Try to infer endianess. Basically we just go through the CPUs we know are
-** little endian, and assume anything that isn't one of those is big endian.
-** As a sanity check, we also do this with operating systems we know are
-** little endian, such as Windows. Some processors are bi-endian, such as
-** the MIPS series, so we have to be careful about those.
-** ----------------------------------------------------------------------------
-*/
-#if defined POSH_CPU_X86 || defined POSH_CPU_AXP || defined POSH_CPU_STRONGARM || defined POSH_OS_WIN32 || defined POSH_OS_WINCE || defined __MIPSEL__
-# define POSH_ENDIAN_STRING "little"
-# define POSH_LITTLE_ENDIAN 1
-#else
-# define POSH_ENDIAN_STRING "big"
-# define POSH_BIG_ENDIAN 1
-#endif
-
-#if defined FORCE_DOXYGEN
-# define POSH_LITTLE_ENDIAN
-#endif
-
-/*
-** ----------------------------------------------------------------------------
-** Cross-platform compile time assertion macro
-** ----------------------------------------------------------------------------
-*/
-#define POSH_COMPILE_TIME_ASSERT(name, x) typedef int _POSH_dummy_ ## name[(x) ? 1 : -1 ]
-
-/*
-** ----------------------------------------------------------------------------
-** 64-bit Integer
-**
-** We don't require 64-bit support, nor do we emulate its functionality, we
-** simply export it if it's available. Since we can't count on <limits.h>
-** for 64-bit support, we ignore the POSH_USE_LIMITS_H directive.
-** ----------------------------------------------------------------------------
-*/
-#if defined ( __LP64__ ) || defined ( __powerpc64__ ) || defined POSH_CPU_SPARC64
-# define POSH_64BIT_INTEGER 1
-typedef long posh_i64_t;
-typedef unsigned long posh_u64_t;
-# define POSH_I64( x ) ((posh_i64_t)x)
-# define POSH_U64( x ) ((posh_u64_t)x)
-# define POSH_I64_PRINTF_PREFIX "l"
-#elif defined _MSC_VER || defined __BORLANDC__ || defined __WATCOMC__ || ( defined __alpha && defined __DECC )
-# define POSH_64BIT_INTEGER 1
-typedef __int64 posh_i64_t;
-typedef unsigned __int64 posh_u64_t;
-# define POSH_I64( x ) ((posh_i64_t)x)
-# define POSH_U64( x ) ((posh_u64_t)x)
-# define POSH_I64_PRINTF_PREFIX "I64"
-#elif defined __GNUC__ || defined __MWERKS__ || defined __SUNPRO_C || defined __SUNPRO_CC || defined __APPLE_CC__ || defined POSH_OS_IRIX || defined _LONG_LONG || defined _CRAYC
-# define POSH_64BIT_INTEGER 1
-typedef long long posh_i64_t;
-typedef unsigned long long posh_u64_t;
-# define POSH_U64( x ) ((posh_u64_t)(x##LL))
-# define POSH_I64( x ) ((posh_i64_t)(x##LL))
-# define POSH_I64_PRINTF_PREFIX "ll"
-#endif
-
-/* hack */
-/*#ifdef __MINGW32__
-#undef POSH_I64
-#undef POSH_U64
-#undef POSH_I64_PRINTF_PREFIX
-#define POSH_I64( x ) ((posh_i64_t)x)
-#define POSH_U64( x ) ((posh_u64_t)x)
-#define POSH_I64_PRINTF_PREFIX "I64"
-#endif*/
-
-#ifdef FORCE_DOXYGEN
-typedef long long posh_i64_t;
-typedef unsigned long posh_u64_t;
-# define POSH_64BIT_INTEGER
-# define POSH_I64_PRINTF_PREFIX
-# define POSH_I64(x)
-# define POSH_U64(x)
-#endif
-
-/** Minimum value for a 64-bit signed integer */
-#define POSH_I64_MIN POSH_I64(0x8000000000000000)
-/** Maximum value for a 64-bit signed integer */
-#define POSH_I64_MAX POSH_I64(0x7FFFFFFFFFFFFFFF)
-/** Minimum value for a 64-bit unsigned integer */
-#define POSH_U64_MIN POSH_U64(0)
-/** Maximum value for a 64-bit unsigned integer */
-#define POSH_U64_MAX POSH_U64(0xFFFFFFFFFFFFFFFF)
-
-/* ----------------------------------------------------------------------------
-** Basic Sized Types
-**
-** These types are expected to be EXACTLY sized so you can use them for
-** serialization.
-** ----------------------------------------------------------------------------
-*/
-#define POSH_FALSE 0
-#define POSH_TRUE 1
-
-typedef int posh_bool_t;
-typedef unsigned char posh_byte_t;
-
-/* NOTE: These assume that CHAR_BIT is 8!! */
-typedef unsigned char posh_u8_t;
-typedef signed char posh_i8_t;
-
-#if defined POSH_USE_LIMITS_H
-# if CHAR_BITS > 8
-# error This machine uses 9-bit characters. This is a warning, you can comment this out now.
-# endif /* CHAR_BITS > 8 */
-
-/* 16-bit */
-# if ( USHRT_MAX == 65535 )
- typedef unsigned short posh_u16_t;
- typedef short posh_i16_t;
-# else
- /* Yes, in theory there could still be a 16-bit character type and shorts are
- 32-bits in size...if you find such an architecture, let me know =P */
-# error No 16-bit type found
-# endif
-
-/* 32-bit */
-# if ( INT_MAX == 2147483647 )
- typedef unsigned posh_u32_t;
- typedef int posh_i32_t;
-# elif ( LONG_MAX == 2147483647 )
- typedef unsigned long posh_u32_t;
- typedef long posh_i32_t;
-# else
- error No 32-bit type found
-# endif
-
-#else /* POSH_USE_LIMITS_H */
-
- typedef unsigned short posh_u16_t;
- typedef short posh_i16_t;
-
-# if !defined POSH_OS_PALM
- typedef unsigned posh_u32_t;
- typedef int posh_i32_t;
-# else
- typedef unsigned long posh_u32_t;
- typedef long posh_i32_t;
-# endif
-#endif
-
-/** Minimum value for a byte */
-#define POSH_BYTE_MIN 0
-/** Maximum value for an 8-bit unsigned value */
-#define POSH_BYTE_MAX 255
-/** Minimum value for a byte */
-#define POSH_I16_MIN ( ( posh_i16_t ) 0x8000 )
-/** Maximum value for a 16-bit signed value */
-#define POSH_I16_MAX ( ( posh_i16_t ) 0x7FFF )
-/** Minimum value for a 16-bit unsigned value */
-#define POSH_U16_MIN 0
-/** Maximum value for a 16-bit unsigned value */
-#define POSH_U16_MAX ( ( posh_u16_t ) 0xFFFF )
-/** Minimum value for a 32-bit signed value */
-#define POSH_I32_MIN ( ( posh_i32_t ) 0x80000000 )
-/** Maximum value for a 32-bit signed value */
-#define POSH_I32_MAX ( ( posh_i32_t ) 0x7FFFFFFF )
-/** Minimum value for a 32-bit unsigned value */
-#define POSH_U32_MIN 0
-/** Maximum value for a 32-bit unsigned value */
-#define POSH_U32_MAX ( ( posh_u32_t ) 0xFFFFFFFF )
-
-/*
-** ----------------------------------------------------------------------------
-** Sanity checks on expected sizes
-** ----------------------------------------------------------------------------
-*/
-#if !defined FORCE_DOXYGEN
-
-POSH_COMPILE_TIME_ASSERT(posh_byte_t, sizeof(posh_byte_t) == 1);
-POSH_COMPILE_TIME_ASSERT(posh_u8_t, sizeof(posh_u8_t) == 1);
-POSH_COMPILE_TIME_ASSERT(posh_i8_t, sizeof(posh_i8_t) == 1);
-POSH_COMPILE_TIME_ASSERT(posh_u16_t, sizeof(posh_u16_t) == 2);
-POSH_COMPILE_TIME_ASSERT(posh_i16_t, sizeof(posh_i16_t) == 2);
-POSH_COMPILE_TIME_ASSERT(posh_u32_t, sizeof(posh_u32_t) == 4);
-POSH_COMPILE_TIME_ASSERT(posh_i32_t, sizeof(posh_i32_t) == 4);
-
-#if !defined POSH_NO_FLOAT
- POSH_COMPILE_TIME_ASSERT(posh_testfloat_t, sizeof(float)==4 );
- POSH_COMPILE_TIME_ASSERT(posh_testdouble_t, sizeof(double)==8);
-#endif
-
-#if defined POSH_64BIT_INTEGER
- POSH_COMPILE_TIME_ASSERT(posh_u64_t, sizeof(posh_u64_t) == 8);
- POSH_COMPILE_TIME_ASSERT(posh_i64_t, sizeof(posh_i64_t) == 8);
-#endif
-
-#endif
-
-/*
-** ----------------------------------------------------------------------------
-** 64-bit pointer support
-** ----------------------------------------------------------------------------
-*/
-#if defined POSH_CPU_AXP && ( defined POSH_OS_TRU64 || defined POSH_OS_LINUX )
-# define POSH_64BIT_POINTER 1
-#endif
-
-#if defined POSH_CPU_X86_64 && defined POSH_OS_LINUX
-# define POSH_64BIT_POINTER 1
-#endif
-
-#if defined POSH_CPU_SPARC64 || defined POSH_OS_WIN64 || defined __64BIT__ || defined __LP64 || defined _LP64 || defined __LP64__ || defined _ADDR64 || defined _CRAYC
-# define POSH_64BIT_POINTER 1
-#endif
-
-#if defined POSH_64BIT_POINTER
- POSH_COMPILE_TIME_ASSERT( posh_64bit_pointer, sizeof( void * ) == 8 );
-#elif !defined FORCE_DOXYGEN
-/* if this assertion is hit then you're on a system that either has 64-bit
- addressing and we didn't catch it, or you're on a system with 16-bit
- pointers. In the latter case, POSH doesn't actually care, we're just
- triggering this assertion to make sure you're aware of the situation,
- so feel free to delete it.
-
- If this assertion is triggered on a known 32 or 64-bit platform,
- please let us know (poshlib@poshlib.org) */
- POSH_COMPILE_TIME_ASSERT( posh_32bit_pointer, sizeof( void * ) == 4 );
-#endif
-
-#if defined FORCE_DOXYGEN
-# define POSH_64BIT_POINTER
-#endif
-
-/*
-** ----------------------------------------------------------------------------
-** POSH Utility Functions
-**
-** These are optional POSH utility functions that are not required if you don't
-** need anything except static checking of your host and target environment.
-**
-** These functions are NOT wrapped with POSH_PUBLIC_API because I didn't want
-** to enforce their export if your own library is only using them internally.
-** ----------------------------------------------------------------------------
-*/
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-const char *POSH_GetArchString( void );
-
-#if !defined POSH_NO_FLOAT
-
-posh_u32_t POSH_LittleFloatBits( float f );
-posh_u32_t POSH_BigFloatBits( float f );
-float POSH_FloatFromLittleBits( posh_u32_t bits );
-float POSH_FloatFromBigBits( posh_u32_t bits );
-
-void POSH_DoubleBits( double d, posh_byte_t dst[ 8 ] );
-double POSH_DoubleFromBits( const posh_byte_t src[ 8 ] );
-
-/* unimplemented
-float *POSH_WriteFloatToLittle( void *dst, float f );
-float *POSH_WriteFloatToBig( void *dst, float f );
-float POSH_ReadFloatFromLittle( const void *src );
-float POSH_ReadFloatFromBig( const void *src );
-
-double *POSH_WriteDoubleToLittle( void *dst, double d );
-double *POSH_WriteDoubleToBig( void *dst, double d );
-double POSH_ReadDoubleFromLittle( const void *src );
-double POSH_ReadDoubleFromBig( const void *src );
-*/
-#endif /* !defined POSH_NO_FLOAT */
-
-#if defined FORCE_DOXYGEN
-# define POSH_NO_FLOAT
-# undef POSH_NO_FLOAT
-#endif
-
-extern posh_u16_t POSH_SwapU16( posh_u16_t u );
-extern posh_i16_t POSH_SwapI16( posh_i16_t u );
-extern posh_u32_t POSH_SwapU32( posh_u32_t u );
-extern posh_i32_t POSH_SwapI32( posh_i32_t u );
-
-#if defined POSH_64BIT_INTEGER
-
-extern posh_u64_t POSH_SwapU64( posh_u64_t u );
-extern posh_i64_t POSH_SwapI64( posh_i64_t u );
-
-#endif /*POSH_64BIT_INTEGER */
-
-extern posh_u16_t *POSH_WriteU16ToLittle( void *dst, posh_u16_t value );
-extern posh_i16_t *POSH_WriteI16ToLittle( void *dst, posh_i16_t value );
-extern posh_u32_t *POSH_WriteU32ToLittle( void *dst, posh_u32_t value );
-extern posh_i32_t *POSH_WriteI32ToLittle( void *dst, posh_i32_t value );
-
-extern posh_u16_t *POSH_WriteU16ToBig( void *dst, posh_u16_t value );
-extern posh_i16_t *POSH_WriteI16ToBig( void *dst, posh_i16_t value );
-extern posh_u32_t *POSH_WriteU32ToBig( void *dst, posh_u32_t value );
-extern posh_i32_t *POSH_WriteI32ToBig( void *dst, posh_i32_t value );
-
-extern posh_u16_t POSH_ReadU16FromLittle( const void *src );
-extern posh_i16_t POSH_ReadI16FromLittle( const void *src );
-extern posh_u32_t POSH_ReadU32FromLittle( const void *src );
-extern posh_i32_t POSH_ReadI32FromLittle( const void *src );
-
-extern posh_u16_t POSH_ReadU16FromBig( const void *src );
-extern posh_i16_t POSH_ReadI16FromBig( const void *src );
-extern posh_u32_t POSH_ReadU32FromBig( const void *src );
-extern posh_i32_t POSH_ReadI32FromBig( const void *src );
-
-#if defined POSH_64BIT_INTEGER
-extern posh_u64_t *POSH_WriteU64ToLittle( void *dst, posh_u64_t value );
-extern posh_i64_t *POSH_WriteI64ToLittle( void *dst, posh_i64_t value );
-extern posh_u64_t *POSH_WriteU64ToBig( void *dst, posh_u64_t value );
-extern posh_i64_t *POSH_WriteI64ToBig( void *dst, posh_i64_t value );
-
-extern posh_u64_t POSH_ReadU64FromLittle( const void *src );
-extern posh_i64_t POSH_ReadI64FromLittle( const void *src );
-extern posh_u64_t POSH_ReadU64FromBig( const void *src );
-extern posh_i64_t POSH_ReadI64FromBig( const void *src );
-#endif /* POSH_64BIT_INTEGER */
-
-#if defined POSH_LITTLE_ENDIAN
-
-# define POSH_LittleU16(x) (x)
-# define POSH_LittleU32(x) (x)
-# define POSH_LittleI16(x) (x)
-# define POSH_LittleI32(x) (x)
-# if defined POSH_64BIT_INTEGER
-# define POSH_LittleU64(x) (x)
-# define POSH_LittleI64(x) (x)
-# endif /* defined POSH_64BIT_INTEGER */
-
-# define POSH_BigU16(x) POSH_SwapU16(x)
-# define POSH_BigU32(x) POSH_SwapU32(x)
-# define POSH_BigI16(x) POSH_SwapI16(x)
-# define POSH_BigI32(x) POSH_SwapI32(x)
-# if defined POSH_64BIT_INTEGER
-# define POSH_BigU64(x) POSH_SwapU64(x)
-# define POSH_BigI64(x) POSH_SwapI64(x)
-# endif /* defined POSH_64BIT_INTEGER */
-
-#else
-
-# define POSH_BigU16(x) (x)
-# define POSH_BigU32(x) (x)
-# define POSH_BigI16(x) (x)
-# define POSH_BigI32(x) (x)
-
-# if defined POSH_64BIT_INTEGER
-# define POSH_BigU64(x) (x)
-# define POSH_BigI64(x) (x)
-# endif /* POSH_64BIT_INTEGER */
-
-# define POSH_LittleU16(x) POSH_SwapU16(x)
-# define POSH_LittleU32(x) POSH_SwapU32(x)
-# define POSH_LittleI16(x) POSH_SwapI16(x)
-# define POSH_LittleI32(x) POSH_SwapI32(x)
-
-# if defined POSH_64BIT_INTEGER
-# define POSH_LittleU64(x) POSH_SwapU64(x)
-# define POSH_LittleI64(x) POSH_SwapI64(x)
-# endif /* POSH_64BIT_INTEGER */
-
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-
diff --git a/thirdparty/thekla_atlas/thekla/thekla_atlas.cpp b/thirdparty/thekla_atlas/thekla/thekla_atlas.cpp
deleted file mode 100644
index de1953db8a..0000000000
--- a/thirdparty/thekla_atlas/thekla/thekla_atlas.cpp
+++ /dev/null
@@ -1,288 +0,0 @@
-
-#include "thekla_atlas.h"
-
-#include <cfloat>
-// -- GODOT start --
-#include <stdio.h>
-// -- GODOT end --
-
-#include "nvmesh/halfedge/Edge.h"
-#include "nvmesh/halfedge/Mesh.h"
-#include "nvmesh/halfedge/Face.h"
-#include "nvmesh/halfedge/Vertex.h"
-#include "nvmesh/param/Atlas.h"
-
-#include "nvmath/Vector.inl"
-#include "nvmath/ftoi.h"
-
-#include "nvcore/Array.inl"
-
-
-using namespace Thekla;
-using namespace nv;
-
-
-inline Atlas_Output_Mesh * set_error(Atlas_Error * error, Atlas_Error code) {
- if (error) *error = code;
- return NULL;
-}
-
-
-
-static void input_to_mesh(const Atlas_Input_Mesh * input, HalfEdge::Mesh * mesh, Atlas_Error * error) {
-
- Array<uint> canonicalMap;
- canonicalMap.reserve(input->vertex_count);
-
- for (int i = 0; i < input->vertex_count; i++) {
- const Atlas_Input_Vertex & input_vertex = input->vertex_array[i];
- const float * pos = input_vertex.position;
- const float * nor = input_vertex.normal;
- const float * tex = input_vertex.uv;
-
- HalfEdge::Vertex * vertex = mesh->addVertex(Vector3(pos[0], pos[1], pos[2]));
- vertex->nor.set(nor[0], nor[1], nor[2]);
- vertex->tex.set(tex[0], tex[1]);
-
- canonicalMap.append(input_vertex.first_colocal);
- }
-
- mesh->linkColocalsWithCanonicalMap(canonicalMap);
-
-
- const int face_count = input->face_count;
-
- int non_manifold_faces = 0;
- for (int i = 0; i < face_count; i++) {
- const Atlas_Input_Face & input_face = input->face_array[i];
-
- int v0 = input_face.vertex_index[0];
- int v1 = input_face.vertex_index[1];
- int v2 = input_face.vertex_index[2];
-
- HalfEdge::Face * face = mesh->addFace(v0, v1, v2);
- if (face != NULL) {
- face->material = input_face.material_index;
- }
- else {
- non_manifold_faces++;
- }
- }
-
- mesh->linkBoundary();
-
- if (non_manifold_faces != 0 && error != NULL) {
- *error = Atlas_Error_Invalid_Mesh_Non_Manifold;
- }
-}
-
-static Atlas_Output_Mesh * mesh_atlas_to_output(const HalfEdge::Mesh * mesh, const Atlas & atlas, Atlas_Error * error) {
-
- Atlas_Output_Mesh * output = new Atlas_Output_Mesh;
-
- const MeshCharts * charts = atlas.meshAt(0);
-
- // Allocate vertices.
- const int vertex_count = charts->vertexCount();
- output->vertex_count = vertex_count;
- output->vertex_array = new Atlas_Output_Vertex[vertex_count];
-
- int w = 0;
- int h = 0;
-
- // Output vertices.
- const int chart_count = charts->chartCount();
- for (int i = 0; i < chart_count; i++) {
- const Chart * chart = charts->chartAt(i);
- uint vertexOffset = charts->vertexCountBeforeChartAt(i);
-
- const uint chart_vertex_count = chart->vertexCount();
- for (uint v = 0; v < chart_vertex_count; v++) {
- Atlas_Output_Vertex & output_vertex = output->vertex_array[vertexOffset + v];
-
- uint original_vertex = chart->mapChartVertexToOriginalVertex(v);
- output_vertex.xref = original_vertex;
-
- Vector2 uv = chart->chartMesh()->vertexAt(v)->tex;
- output_vertex.uv[0] = uv.x;
- output_vertex.uv[1] = uv.y;
- w = max(w, ftoi_ceil(uv.x));
- h = max(h, ftoi_ceil(uv.y));
- }
- }
-
- const int face_count = mesh->faceCount();
- output->index_count = face_count * 3;
- output->index_array = new int[face_count * 3];
-
- // -- GODOT start --
- int face_ofs = 0;
- // Set face indices.
- for (int f = 0; f < face_count; f++) {
- uint c = charts->faceChartAt(f);
- uint i = charts->faceIndexWithinChartAt(f);
- uint vertexOffset = charts->vertexCountBeforeChartAt(c);
-
- const Chart * chart = charts->chartAt(c);
- nvDebugCheck(chart->faceAt(i) == f);
-
- if (i >= chart->chartMesh()->faceCount()) {
- printf("WARNING: Faces may be missing in the final vertex, which could not be packed\n");
- continue;
- }
-
- const HalfEdge::Face * face = chart->chartMesh()->faceAt(i);
- const HalfEdge::Edge * edge = face->edge;
-
- //output->index_array[3*f+0] = vertexOffset + edge->vertex->id;
- //output->index_array[3*f+1] = vertexOffset + edge->next->vertex->id;
- //output->index_array[3*f+2] = vertexOffset + edge->next->next->vertex->id;
- output->index_array[3 * face_ofs + 0] = vertexOffset + edge->vertex->id;
- output->index_array[3 * face_ofs + 1] = vertexOffset + edge->next->vertex->id;
- output->index_array[3 * face_ofs + 2] = vertexOffset + edge->next->next->vertex->id;
- face_ofs++;
- }
-
- output->index_count = face_ofs * 3;
- // -- GODOT end --
-
- *error = Atlas_Error_Success;
- output->atlas_width = w;
- output->atlas_height = h;
-
- return output;
-}
-
-
-void Thekla::atlas_set_default_options(Atlas_Options * options) {
- if (options != NULL) {
- // These are the default values we use on The Witness.
-
- options->charter = Atlas_Charter_Default;
- options->charter_options.witness.proxy_fit_metric_weight = 2.0f;
- options->charter_options.witness.roundness_metric_weight = 0.01f;
- options->charter_options.witness.straightness_metric_weight = 6.0f;
- options->charter_options.witness.normal_seam_metric_weight = 4.0f;
- options->charter_options.witness.texture_seam_metric_weight = 0.5f;
- options->charter_options.witness.max_chart_area = FLT_MAX;
- options->charter_options.witness.max_boundary_length = FLT_MAX;
-
- options->mapper = Atlas_Mapper_Default;
-
- options->packer = Atlas_Packer_Default;
- options->packer_options.witness.packing_quality = 0;
- options->packer_options.witness.texel_area = 8;
- options->packer_options.witness.block_align = true;
- options->packer_options.witness.conservative = false;
- }
-}
-
-
-Atlas_Output_Mesh * Thekla::atlas_generate(const Atlas_Input_Mesh * input, const Atlas_Options * options, Atlas_Error * error) {
- // Validate args.
- if (input == NULL || options == NULL || error == NULL) return set_error(error, Atlas_Error_Invalid_Args);
-
- // Validate options.
- if (options->charter != Atlas_Charter_Witness) {
- return set_error(error, Atlas_Error_Invalid_Options);
- }
- if (options->charter == Atlas_Charter_Witness) {
- // @@ Validate input options!
- }
-
- if (options->mapper != Atlas_Mapper_LSCM) {
- return set_error(error, Atlas_Error_Invalid_Options);
- }
- if (options->mapper == Atlas_Mapper_LSCM) {
- // No options.
- }
-
- if (options->packer != Atlas_Packer_Witness) {
- return set_error(error, Atlas_Error_Invalid_Options);
- }
- if (options->packer == Atlas_Packer_Witness) {
- // @@ Validate input options!
- }
-
- // Validate input mesh.
- for (int i = 0; i < input->face_count; i++) {
- int v0 = input->face_array[i].vertex_index[0];
- int v1 = input->face_array[i].vertex_index[1];
- int v2 = input->face_array[i].vertex_index[2];
-
- if (v0 < 0 || v0 >= input->vertex_count ||
- v1 < 0 || v1 >= input->vertex_count ||
- v2 < 0 || v2 >= input->vertex_count)
- {
- return set_error(error, Atlas_Error_Invalid_Mesh);
- }
- }
-
-
- // Build half edge mesh.
- AutoPtr<HalfEdge::Mesh> mesh(new HalfEdge::Mesh);
-
- input_to_mesh(input, mesh.ptr(), error);
-
- if (*error == Atlas_Error_Invalid_Mesh) {
- return NULL;
- }
-
- Atlas atlas;
-
- // Charter.
- if (options->charter == Atlas_Charter_Extract) {
- return set_error(error, Atlas_Error_Not_Implemented);
- }
- else if (options->charter == Atlas_Charter_Witness) {
- SegmentationSettings segmentation_settings;
- segmentation_settings.proxyFitMetricWeight = options->charter_options.witness.proxy_fit_metric_weight;
- segmentation_settings.roundnessMetricWeight = options->charter_options.witness.roundness_metric_weight;
- segmentation_settings.straightnessMetricWeight = options->charter_options.witness.straightness_metric_weight;
- segmentation_settings.normalSeamMetricWeight = options->charter_options.witness.normal_seam_metric_weight;
- segmentation_settings.textureSeamMetricWeight = options->charter_options.witness.texture_seam_metric_weight;
- segmentation_settings.maxChartArea = options->charter_options.witness.max_chart_area;
- segmentation_settings.maxBoundaryLength = options->charter_options.witness.max_boundary_length;
-
- Array<uint> uncharted_materials;
- atlas.computeCharts(mesh.ptr(), segmentation_settings, uncharted_materials);
- }
-
- if (atlas.hasFailed())
- return NULL;
-
- // Mapper.
- if (options->mapper == Atlas_Mapper_LSCM) {
- atlas.parameterizeCharts();
- }
-
- if (atlas.hasFailed())
- return NULL;
-
- // Packer.
- if (options->packer == Atlas_Packer_Witness) {
- int packing_quality = options->packer_options.witness.packing_quality;
- float texel_area = options->packer_options.witness.texel_area;
- int block_align = options->packer_options.witness.block_align;
- int conservative = options->packer_options.witness.conservative;
-
- /*float utilization =*/ atlas.packCharts(packing_quality, texel_area, block_align, conservative);
- }
-
- if (atlas.hasFailed())
- return NULL;
-
-
- // Build output mesh.
- return mesh_atlas_to_output(mesh.ptr(), atlas, error);
-}
-
-
-void Thekla::atlas_free(Atlas_Output_Mesh * output) {
- if (output != NULL) {
- delete [] output->vertex_array;
- delete [] output->index_array;
- delete output;
- }
-}
-
diff --git a/thirdparty/thekla_atlas/thekla/thekla_atlas.h b/thirdparty/thekla_atlas/thekla/thekla_atlas.h
deleted file mode 100644
index 1d0716e781..0000000000
--- a/thirdparty/thekla_atlas/thekla/thekla_atlas.h
+++ /dev/null
@@ -1,116 +0,0 @@
-
-// Thekla Atlas Generator
-
-namespace Thekla {
-
-enum Atlas_Charter {
- Atlas_Charter_Witness, // Options: threshold
- Atlas_Charter_Extract, // Options: ---
- Atlas_Charter_Default = Atlas_Charter_Witness
-};
-
-enum Atlas_Mapper {
- Atlas_Mapper_LSCM, // Options: ---
- Atlas_Mapper_Default = Atlas_Mapper_LSCM
-};
-
-enum Atlas_Packer {
- Atlas_Packer_Witness, // Options: texel_area
- Atlas_Packer_Default = Atlas_Packer_Witness
-};
-
-struct Atlas_Options {
- Atlas_Charter charter;
- union {
- struct {
- float proxy_fit_metric_weight;
- float roundness_metric_weight;
- float straightness_metric_weight;
- float normal_seam_metric_weight;
- float texture_seam_metric_weight;
- float max_chart_area;
- float max_boundary_length;
- } witness;
- struct {
- } extract;
- } charter_options;
-
- Atlas_Mapper mapper;
- union {
- } mapper_options;
-
- Atlas_Packer packer;
- union {
- struct {
- int packing_quality;
- float texel_area; // This is not really texel area, but 1 / texel width?
- bool block_align; // Align charts to 4x4 blocks.
- bool conservative; // Pack charts with extra padding.
- } witness;
- } packer_options;
-};
-
-struct Atlas_Input_Vertex {
- float position[3];
- float normal[3];
- float uv[2];
- int first_colocal;
-};
-
-struct Atlas_Input_Face {
- int vertex_index[3];
- int material_index;
-};
-
-struct Atlas_Input_Mesh {
- int vertex_count;
- int face_count;
- Atlas_Input_Vertex * vertex_array;
- Atlas_Input_Face * face_array;
-};
-
-struct Atlas_Output_Vertex {
- float uv[2];
- int xref; // Index of input vertex from which this output vertex originated.
-};
-
-struct Atlas_Output_Mesh {
- int atlas_width;
- int atlas_height;
- int vertex_count;
- int index_count;
- Atlas_Output_Vertex * vertex_array;
- int * index_array;
-};
-
-enum Atlas_Error {
- Atlas_Error_Success,
- Atlas_Error_Invalid_Args,
- Atlas_Error_Invalid_Options,
- Atlas_Error_Invalid_Mesh,
- Atlas_Error_Invalid_Mesh_Non_Manifold,
- Atlas_Error_Not_Implemented,
-};
-
-void atlas_set_default_options(Atlas_Options * options);
-
-Atlas_Output_Mesh * atlas_generate(const Atlas_Input_Mesh * input, const Atlas_Options * options, Atlas_Error * error);
-
-void atlas_free(Atlas_Output_Mesh * output);
-
-
-/*
-
-Should we represent the input mesh with an opaque structure that simply holds pointers to the user data? That would allow us to avoid having to copy attributes to an intermediate representation.
-
-struct Atlas_Input_Mesh;
-
-void mesh_set_vertex_position(Atlas_Input_Mesh * mesh, float * ptr, int stride);
-void mesh_set_vertex_normal(Atlas_Input_Mesh * mesh, float * ptr, int stride);
-void mesh_set_vertex_uv(Mesh * mesh, float * ptr, int stride);
-
-void mesh_set_index(Mesh * mesh, int * ptr);
-*/
-
-} // Thekla namespace
-
diff --git a/thirdparty/tinyexr/tinyexr.h b/thirdparty/tinyexr/tinyexr.h
index b3a7ee00c2..3c19391850 100644
--- a/thirdparty/tinyexr/tinyexr.h
+++ b/thirdparty/tinyexr/tinyexr.h
@@ -274,6 +274,12 @@ extern int LoadEXR(float **out_rgba, int *width, int *height,
const char *filename, const char **err);
// @deprecated { to be removed. }
+// Simple wrapper API for ParseEXRHeaderFromFile.
+// checking given file is a EXR file(by just look up header)
+// @return TINYEXR_SUCCEES for EXR image, TINYEXR_ERROR_INVALID_HEADER for others
+extern int IsEXR(const char *filename);
+
+// @deprecated { to be removed. }
// Saves single-frame OpenEXR image. Assume EXR image contains RGB(A) channels.
// components must be 1(Grayscale), 3(RGB) or 4(RGBA).
// Input image format is: `float x width x height`, or `float x RGB(A) x width x
@@ -6998,6 +7004,10 @@ static void swap2(unsigned short *val) {
#endif
}
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-function"
+#endif
static void cpy4(int *dst_val, const int *src_val) {
unsigned char *dst = reinterpret_cast<unsigned char *>(dst_val);
const unsigned char *src = reinterpret_cast<const unsigned char *>(src_val);
@@ -7028,6 +7038,10 @@ static void cpy4(float *dst_val, const float *src_val) {
dst[3] = src[3];
}
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
static void swap4(unsigned int *val) {
#ifdef MINIZ_LITTLE_ENDIAN
(void)val;
@@ -8840,7 +8854,8 @@ static bool getCode(int po, int rlc, long long &c, int &lc, const char *&in,
if (out + cs > oe) return false;
// Bounds check for safety
- if ((out - 1) <= ob) return false;
+ // Issue 100.
+ if ((out - 1) < ob) return false;
unsigned short s = out[-1];
while (cs-- > 0) *out++ = s;
@@ -10721,6 +10736,15 @@ static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header,
int data_width = exr_header->data_window[2] - exr_header->data_window[0] + 1;
int data_height = exr_header->data_window[3] - exr_header->data_window[1] + 1;
+ if ((data_width < 0) || (data_height < 0)) {
+ if (err) {
+ std::stringstream ss;
+ ss << "Invalid data width or data height: " << data_width << ", " << data_height << std::endl;
+ (*err) += ss.str();
+ }
+ return TINYEXR_ERROR_INVALID_DATA;
+ }
+
size_t num_blocks = offsets.size();
std::vector<size_t> channel_offset_list;
@@ -10816,6 +10840,17 @@ static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header,
}
} else { // scanline format
+ // Don't allow too large image(256GB * pixel_data_size or more). Workaround for #104.
+ size_t data_len = size_t(data_width) * size_t(data_height) * size_t(num_channels);
+ if ((data_len == 0) || (data_len >= 0x4000000000)) {
+ if (err) {
+ std::stringstream ss;
+ ss << "Image data size is zero or too large: width = " << data_width << ", height = " << data_height << ", channels = " << num_channels << std::endl;
+ (*err) += ss.str();
+ }
+ return TINYEXR_ERROR_INVALID_DATA;
+ }
+
exr_image->images = tinyexr::AllocateImage(
num_channels, exr_header->channels, exr_header->requested_pixel_types,
data_width, data_height);
@@ -11155,7 +11190,6 @@ int LoadEXR(float **out_rgba, int *width, int *height, const char *filename,
static_cast<size_t>(exr_image.height)));
if (exr_header.tiled) {
- // todo.implement this
for (int it = 0; it < exr_image.num_tiles; it++) {
for (int j = 0; j < exr_header.tile_size_y; j++) {
@@ -11284,6 +11318,17 @@ int LoadEXR(float **out_rgba, int *width, int *height, const char *filename,
return TINYEXR_SUCCESS;
}
+int IsEXR(const char *filename) {
+ EXRVersion exr_version;
+
+ int ret = ParseEXRVersionFromFile(&exr_version, filename);
+ if (ret != TINYEXR_SUCCESS) {
+ return TINYEXR_ERROR_INVALID_HEADER;
+ }
+
+ return TINYEXR_SUCCESS;
+}
+
int ParseEXRHeaderFromMemory(EXRHeader *exr_header, const EXRVersion *version,
const unsigned char *memory, size_t size,
const char **err) {
@@ -11380,75 +11425,128 @@ int LoadEXRFromMemory(float **out_rgba, int *width, int *height,
}
}
- if (idxR == -1) {
- tinyexr::SetErrorMessage("R channel not found", err);
-
- // @todo { free exr_image }
- return TINYEXR_ERROR_INVALID_DATA;
- }
-
- if (idxG == -1) {
- tinyexr::SetErrorMessage("G channel not found", err);
- // @todo { free exr_image }
- return TINYEXR_ERROR_INVALID_DATA;
- }
+ // TODO(syoyo): Refactor removing same code as used in LoadEXR().
+ if (exr_header.num_channels == 1) {
+ // Grayscale channel only.
- if (idxB == -1) {
- tinyexr::SetErrorMessage("B channel not found", err);
- // @todo { free exr_image }
- return TINYEXR_ERROR_INVALID_DATA;
- }
+ (*out_rgba) = reinterpret_cast<float *>(
+ malloc(4 * sizeof(float) * static_cast<size_t>(exr_image.width) *
+ static_cast<size_t>(exr_image.height)));
- (*out_rgba) = reinterpret_cast<float *>(
- malloc(4 * sizeof(float) * static_cast<size_t>(exr_image.width) *
- static_cast<size_t>(exr_image.height)));
+ if (exr_header.tiled) {
- if (exr_header.tiled) {
- for (int it = 0; it < exr_image.num_tiles; it++) {
- for (int j = 0; j < exr_header.tile_size_y; j++)
- for (int i = 0; i < exr_header.tile_size_x; i++) {
- const int ii =
- exr_image.tiles[it].offset_x * exr_header.tile_size_x + i;
- const int jj =
- exr_image.tiles[it].offset_y * exr_header.tile_size_y + j;
- const int idx = ii + jj * exr_image.width;
+ for (int it = 0; it < exr_image.num_tiles; it++) {
+ for (int j = 0; j < exr_header.tile_size_y; j++) {
+ for (int i = 0; i < exr_header.tile_size_x; i++) {
+ const int ii =
+ exr_image.tiles[it].offset_x * exr_header.tile_size_x + i;
+ const int jj =
+ exr_image.tiles[it].offset_y * exr_header.tile_size_y + j;
+ const int idx = ii + jj * exr_image.width;
- // out of region check.
- if (ii >= exr_image.width) {
- continue;
- }
- if (jj >= exr_image.height) {
- continue;
- }
- const int srcIdx = i + j * exr_header.tile_size_x;
- unsigned char **src = exr_image.tiles[it].images;
- (*out_rgba)[4 * idx + 0] =
- reinterpret_cast<float **>(src)[idxR][srcIdx];
- (*out_rgba)[4 * idx + 1] =
- reinterpret_cast<float **>(src)[idxG][srcIdx];
- (*out_rgba)[4 * idx + 2] =
- reinterpret_cast<float **>(src)[idxB][srcIdx];
- if (idxA != -1) {
+ // out of region check.
+ if (ii >= exr_image.width) {
+ continue;
+ }
+ if (jj >= exr_image.height) {
+ continue;
+ }
+ const int srcIdx = i + j * exr_header.tile_size_x;
+ unsigned char **src = exr_image.tiles[it].images;
+ (*out_rgba)[4 * idx + 0] =
+ reinterpret_cast<float **>(src)[0][srcIdx];
+ (*out_rgba)[4 * idx + 1] =
+ reinterpret_cast<float **>(src)[0][srcIdx];
+ (*out_rgba)[4 * idx + 2] =
+ reinterpret_cast<float **>(src)[0][srcIdx];
(*out_rgba)[4 * idx + 3] =
- reinterpret_cast<float **>(src)[idxA][srcIdx];
- } else {
- (*out_rgba)[4 * idx + 3] = 1.0;
+ reinterpret_cast<float **>(src)[0][srcIdx];
}
}
+ }
+ } else {
+ for (int i = 0; i < exr_image.width * exr_image.height; i++) {
+ const float val = reinterpret_cast<float **>(exr_image.images)[0][i];
+ (*out_rgba)[4 * i + 0] = val;
+ (*out_rgba)[4 * i + 1] = val;
+ (*out_rgba)[4 * i + 2] = val;
+ (*out_rgba)[4 * i + 3] = val;
+ }
}
+
} else {
- for (int i = 0; i < exr_image.width * exr_image.height; i++) {
- (*out_rgba)[4 * i + 0] =
- reinterpret_cast<float **>(exr_image.images)[idxR][i];
- (*out_rgba)[4 * i + 1] =
- reinterpret_cast<float **>(exr_image.images)[idxG][i];
- (*out_rgba)[4 * i + 2] =
- reinterpret_cast<float **>(exr_image.images)[idxB][i];
- if (idxA != -1) {
- (*out_rgba)[4 * i + 3] =
- reinterpret_cast<float **>(exr_image.images)[idxA][i];
- } else {
- (*out_rgba)[4 * i + 3] = 1.0;
+ // TODO(syoyo): Support non RGBA image.
+
+ if (idxR == -1) {
+ tinyexr::SetErrorMessage("R channel not found", err);
+
+ // @todo { free exr_image }
+ return TINYEXR_ERROR_INVALID_DATA;
+ }
+
+ if (idxG == -1) {
+ tinyexr::SetErrorMessage("G channel not found", err);
+ // @todo { free exr_image }
+ return TINYEXR_ERROR_INVALID_DATA;
+ }
+
+ if (idxB == -1) {
+ tinyexr::SetErrorMessage("B channel not found", err);
+ // @todo { free exr_image }
+ return TINYEXR_ERROR_INVALID_DATA;
+ }
+
+ (*out_rgba) = reinterpret_cast<float *>(
+ malloc(4 * sizeof(float) * static_cast<size_t>(exr_image.width) *
+ static_cast<size_t>(exr_image.height)));
+
+ if (exr_header.tiled) {
+ for (int it = 0; it < exr_image.num_tiles; it++) {
+ for (int j = 0; j < exr_header.tile_size_y; j++)
+ for (int i = 0; i < exr_header.tile_size_x; i++) {
+ const int ii =
+ exr_image.tiles[it].offset_x * exr_header.tile_size_x + i;
+ const int jj =
+ exr_image.tiles[it].offset_y * exr_header.tile_size_y + j;
+ const int idx = ii + jj * exr_image.width;
+
+ // out of region check.
+ if (ii >= exr_image.width) {
+ continue;
+ }
+ if (jj >= exr_image.height) {
+ continue;
+ }
+ const int srcIdx = i + j * exr_header.tile_size_x;
+ unsigned char **src = exr_image.tiles[it].images;
+ (*out_rgba)[4 * idx + 0] =
+ reinterpret_cast<float **>(src)[idxR][srcIdx];
+ (*out_rgba)[4 * idx + 1] =
+ reinterpret_cast<float **>(src)[idxG][srcIdx];
+ (*out_rgba)[4 * idx + 2] =
+ reinterpret_cast<float **>(src)[idxB][srcIdx];
+ if (idxA != -1) {
+ (*out_rgba)[4 * idx + 3] =
+ reinterpret_cast<float **>(src)[idxA][srcIdx];
+ } else {
+ (*out_rgba)[4 * idx + 3] = 1.0;
+ }
+ }
+ }
+ } else {
+ for (int i = 0; i < exr_image.width * exr_image.height; i++) {
+ (*out_rgba)[4 * i + 0] =
+ reinterpret_cast<float **>(exr_image.images)[idxR][i];
+ (*out_rgba)[4 * i + 1] =
+ reinterpret_cast<float **>(exr_image.images)[idxG][i];
+ (*out_rgba)[4 * i + 2] =
+ reinterpret_cast<float **>(exr_image.images)[idxB][i];
+ if (idxA != -1) {
+ (*out_rgba)[4 * i + 3] =
+ reinterpret_cast<float **>(exr_image.images)[idxA][i];
+ } else {
+ (*out_rgba)[4 * i + 3] = 1.0;
+ }
}
}
}
diff --git a/thirdparty/vhacd/0001-bullet-namespace.patch b/thirdparty/vhacd/0001-bullet-namespace.patch
new file mode 100644
index 0000000000..cfb1ffeff0
--- /dev/null
+++ b/thirdparty/vhacd/0001-bullet-namespace.patch
@@ -0,0 +1,213 @@
+diff --git a/thirdparty/vhacd/inc/btAlignedAllocator.h b/thirdparty/vhacd/inc/btAlignedAllocator.h
+index 11f6e12dc..94e71d512 100644
+--- a/thirdparty/vhacd/inc/btAlignedAllocator.h
++++ b/thirdparty/vhacd/inc/btAlignedAllocator.h
+@@ -21,6 +21,11 @@ subject to the following restrictions:
+ ///that is better portable and more predictable
+
+ #include "btScalar.h"
++
++// -- GODOT start --
++namespace VHACD {
++// -- GODOT end --
++
+ //#define BT_DEBUG_MEMORY_ALLOCATIONS 1
+ #ifdef BT_DEBUG_MEMORY_ALLOCATIONS
+
+@@ -101,4 +106,8 @@ public:
+ friend bool operator==(const self_type&, const self_type&) { return true; }
+ };
+
++// -- GODOT start --
++}; // namespace VHACD
++// -- GODOT end --
++
+ #endif //BT_ALIGNED_ALLOCATOR
+diff --git a/thirdparty/vhacd/inc/btAlignedObjectArray.h b/thirdparty/vhacd/inc/btAlignedObjectArray.h
+index e6620adf6..1ce03d21b 100644
+--- a/thirdparty/vhacd/inc/btAlignedObjectArray.h
++++ b/thirdparty/vhacd/inc/btAlignedObjectArray.h
+@@ -38,6 +38,10 @@ subject to the following restrictions:
+ #include <new> //for placement new
+ #endif //BT_USE_PLACEMENT_NEW
+
++// -- GODOT start --
++namespace VHACD {
++// -- GODOT end --
++
+ ///The btAlignedObjectArray template class uses a subset of the stl::vector interface for its methods
+ ///It is developed to replace stl::vector to avoid portability issues, including STL alignment issues to add SIMD/SSE data
+ template <typename T>
+@@ -445,4 +449,8 @@ public:
+ }
+ };
+
++// -- GODOT start --
++}; // namespace VHACD
++// -- GODOT end --
++
+ #endif //BT_OBJECT_ARRAY__
+diff --git a/thirdparty/vhacd/inc/btConvexHullComputer.h b/thirdparty/vhacd/inc/btConvexHullComputer.h
+index 3c5075c2c..04bb96f64 100644
+--- a/thirdparty/vhacd/inc/btConvexHullComputer.h
++++ b/thirdparty/vhacd/inc/btConvexHullComputer.h
+@@ -18,6 +18,10 @@ subject to the following restrictions:
+ #include "btAlignedObjectArray.h"
+ #include "btVector3.h"
+
++// -- GODOT start --
++namespace VHACD {
++// -- GODOT end --
++
+ /// Convex hull implementation based on Preparata and Hong
+ /// See http://code.google.com/p/bullet/issues/detail?id=275
+ /// Ole Kniemeyer, MAXON Computer GmbH
+@@ -94,4 +98,8 @@ public:
+ }
+ };
+
++// -- GODOT start --
++}; // namespace VHACD
++// -- GODOT end --
++
+ #endif //BT_CONVEX_HULL_COMPUTER_H
+diff --git a/thirdparty/vhacd/inc/btMinMax.h b/thirdparty/vhacd/inc/btMinMax.h
+index 40b0ceb6e..9bc1e1c77 100644
+--- a/thirdparty/vhacd/inc/btMinMax.h
++++ b/thirdparty/vhacd/inc/btMinMax.h
+@@ -17,6 +17,10 @@ subject to the following restrictions:
+
+ #include "btScalar.h"
+
++// -- GODOT start --
++namespace VHACD {
++// -- GODOT end --
++
+ template <class T>
+ SIMD_FORCE_INLINE const T& btMin(const T& a, const T& b)
+ {
+@@ -62,4 +66,8 @@ SIMD_FORCE_INLINE void btClamp(T& a, const T& lb, const T& ub)
+ }
+ }
+
++// -- GODOT start --
++}; // namespace VHACD
++// -- GODOT end --
++
+ #endif //BT_GEN_MINMAX_H
+diff --git a/thirdparty/vhacd/inc/btScalar.h b/thirdparty/vhacd/inc/btScalar.h
+index b814474bd..617fd7c44 100644
+--- a/thirdparty/vhacd/inc/btScalar.h
++++ b/thirdparty/vhacd/inc/btScalar.h
+@@ -28,11 +28,19 @@ subject to the following restrictions:
+ /* SVN $Revision$ on $Date$ from http://bullet.googlecode.com*/
+ #define BT_BULLET_VERSION 279
+
++// -- GODOT start --
++namespace VHACD {
++// -- GODOT end --
++
+ inline int32_t btGetVersion()
+ {
+ return BT_BULLET_VERSION;
+ }
+
++// -- GODOT start --
++}; // namespace VHACD
++// -- GODOT end --
++
+ #if defined(DEBUG) || defined(_DEBUG)
+ #define BT_DEBUG
+ #endif
+@@ -199,6 +207,10 @@ inline int32_t btGetVersion()
+ #endif //__CELLOS_LV2__
+ #endif
+
++// -- GODOT start --
++namespace VHACD {
++// -- GODOT end --
++
+ ///The btScalar type abstracts floating point numbers, to easily switch between double and single floating point precision.
+ #if defined(BT_USE_DOUBLE_PRECISION)
+ typedef double btScalar;
+@@ -530,4 +542,9 @@ struct btTypedObject {
+ return m_objectType;
+ }
+ };
++
++// -- GODOT start --
++}; // namespace VHACD
++// -- GODOT end --
++
+ #endif //BT_SCALAR_H
+diff --git a/thirdparty/vhacd/inc/btVector3.h b/thirdparty/vhacd/inc/btVector3.h
+index 0f2fefbbd..4ed971673 100644
+--- a/thirdparty/vhacd/inc/btVector3.h
++++ b/thirdparty/vhacd/inc/btVector3.h
+@@ -26,6 +26,10 @@ subject to the following restrictions:
+ #define btVector3DataName "btVector3FloatData"
+ #endif //BT_USE_DOUBLE_PRECISION
+
++// -- GODOT start --
++namespace VHACD {
++// -- GODOT end --
++
+ /**@brief btVector3 can be used to represent 3D points and vectors.
+ * It has an un-used w component to suit 16-byte alignment when btVector3 is stored in containers. This extra component can be used by derived classes (Quaternion?) or by user
+ * Ideally, this class should be replaced by a platform optimized SIMD version that keeps the data in registers
+@@ -712,4 +716,8 @@ SIMD_FORCE_INLINE void btVector3::deSerialize(const struct btVector3Data& dataIn
+ m_floats[i] = dataIn.m_floats[i];
+ }
+
++// -- GODOT start --
++}; // namespace VHACD
++// -- GODOT end --
++
+ #endif //BT_VECTOR3_H
+diff --git a/thirdparty/vhacd/src/btAlignedAllocator.cpp b/thirdparty/vhacd/src/btAlignedAllocator.cpp
+index 11d594f6c..ce0e7f26f 100644
+--- a/thirdparty/vhacd/src/btAlignedAllocator.cpp
++++ b/thirdparty/vhacd/src/btAlignedAllocator.cpp
+@@ -15,6 +15,10 @@ subject to the following restrictions:
+
+ #include "btAlignedAllocator.h"
+
++// -- GODOT start --
++namespace VHACD {
++// -- GODOT end --
++
+ #ifdef _MSC_VER
+ #pragma warning(disable:4311 4302)
+ #endif
+@@ -177,4 +181,8 @@ void btAlignedFreeInternal(void* ptr)
+ sAlignedFreeFunc(ptr);
+ }
+
++// -- GODOT start --
++}; // namespace VHACD
++// -- GODOT end --
++
+ #endif //BT_DEBUG_MEMORY_ALLOCATIONS
+diff --git a/thirdparty/vhacd/src/btConvexHullComputer.cpp b/thirdparty/vhacd/src/btConvexHullComputer.cpp
+index d3d749adb..8ab34af2a 100644
+--- a/thirdparty/vhacd/src/btConvexHullComputer.cpp
++++ b/thirdparty/vhacd/src/btConvexHullComputer.cpp
+@@ -49,6 +49,10 @@ typedef unsigned long long int32_t uint64_t;
+ #include <stdio.h>
+ #endif
+
++// -- GODOT start --
++namespace VHACD {
++// -- GODOT end --
++
+ // Convex hull implementation based on Preparata and Hong
+ // Ole Kniemeyer, MAXON Computer GmbH
+ class btConvexHullInternal {
+@@ -2477,3 +2481,7 @@ btScalar btConvexHullComputer::compute(const void* coords, bool doubleCoords, in
+
+ return shift;
+ }
++
++// -- GODOT start --
++}; // namespace VHACD
++// -- GODOT end --
diff --git a/thirdparty/vhacd/0002-fpermissive-fix.patch b/thirdparty/vhacd/0002-fpermissive-fix.patch
new file mode 100644
index 0000000000..965df2944a
--- /dev/null
+++ b/thirdparty/vhacd/0002-fpermissive-fix.patch
@@ -0,0 +1,53 @@
+diff --git a/thirdparty/vhacd/inc/btScalar.h b/thirdparty/vhacd/inc/btScalar.h
+index 487205062..52297cd78 100644
+--- a/thirdparty/vhacd/inc/btScalar.h
++++ b/thirdparty/vhacd/inc/btScalar.h
+@@ -535,6 +535,29 @@ struct btTypedObject {
+ }
+ };
+
++// -- GODOT start --
++// Cherry-picked from Bullet 2.88 to fix GH-27926
++///align a pointer to the provided alignment, upwards
++template <typename T>
++T *btAlignPointer(T *unalignedPtr, size_t alignment)
++{
++ struct btConvertPointerSizeT
++ {
++ union {
++ T *ptr;
++ size_t integer;
++ };
++ };
++ btConvertPointerSizeT converter;
++
++ const size_t bit_mask = ~(alignment - 1);
++ converter.ptr = unalignedPtr;
++ converter.integer += alignment - 1;
++ converter.integer &= bit_mask;
++ return converter.ptr;
++}
++// -- GODOT end --
++
+ // -- GODOT start --
+ }; // namespace VHACD
+ // -- GODOT end --
+diff --git a/thirdparty/vhacd/src/btAlignedAllocator.cpp b/thirdparty/vhacd/src/btAlignedAllocator.cpp
+index ce0e7f26f..8dee31e7e 100644
+--- a/thirdparty/vhacd/src/btAlignedAllocator.cpp
++++ b/thirdparty/vhacd/src/btAlignedAllocator.cpp
+@@ -72,8 +72,12 @@ static inline void* btAlignedAllocDefault(size_t size, int32_t alignment)
+
+ real = (char*)sAllocFunc(size + sizeof(void*) + (alignment - 1));
+ if (real) {
+- offset = (alignment - (unsigned long)(real + sizeof(void*))) & (alignment - 1);
+- ret = (void*)((real + sizeof(void*)) + offset);
++ // -- GODOT start --
++ // Synced with Bullet 2.88 to fix GH-27926
++ //offset = (alignment - (unsigned long)(real + sizeof(void*))) & (alignment - 1);
++ //ret = (void*)((real + sizeof(void*)) + offset);
++ ret = btAlignPointer(real + sizeof(void *), alignment);
++ // -- GODOT end --
+ *((void**)(ret)-1) = (void*)(real);
+ }
+ else {
diff --git a/thirdparty/vhacd/LICENSE b/thirdparty/vhacd/LICENSE
new file mode 100644
index 0000000000..efc7f64399
--- /dev/null
+++ b/thirdparty/vhacd/LICENSE
@@ -0,0 +1,29 @@
+BSD 3-Clause License
+
+Copyright (c) 2011, Khaled Mamou (kmamou at gmail dot com)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+2. 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.
+
+3. Neither the name of the copyright holder 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.
diff --git a/thirdparty/vhacd/inc/FloatMath.h b/thirdparty/vhacd/inc/FloatMath.h
new file mode 100644
index 0000000000..37b07cb69f
--- /dev/null
+++ b/thirdparty/vhacd/inc/FloatMath.h
@@ -0,0 +1,525 @@
+#ifndef FLOAT_MATH_LIB_H
+
+#define FLOAT_MATH_LIB_H
+
+
+#include <float.h>
+#include <stdint.h>
+
+namespace FLOAT_MATH
+{
+
+enum FM_ClipState
+{
+ FMCS_XMIN = (1<<0),
+ FMCS_XMAX = (1<<1),
+ FMCS_YMIN = (1<<2),
+ FMCS_YMAX = (1<<3),
+ FMCS_ZMIN = (1<<4),
+ FMCS_ZMAX = (1<<5),
+};
+
+enum FM_Axis
+{
+ FM_XAXIS = (1<<0),
+ FM_YAXIS = (1<<1),
+ FM_ZAXIS = (1<<2)
+};
+
+enum LineSegmentType
+{
+ LS_START,
+ LS_MIDDLE,
+ LS_END
+};
+
+
+const float FM_PI = 3.1415926535897932384626433832795028841971693993751f;
+const float FM_DEG_TO_RAD = ((2.0f * FM_PI) / 360.0f);
+const float FM_RAD_TO_DEG = (360.0f / (2.0f * FM_PI));
+
+//***************** Float versions
+//***
+//*** vectors are assumed to be 3 floats or 3 doubles representing X, Y, Z
+//*** quaternions are assumed to be 4 floats or 4 doubles representing X,Y,Z,W
+//*** matrices are assumed to be 16 floats or 16 doubles representing a standard D3D or OpenGL style 4x4 matrix
+//*** bounding volumes are expressed as two sets of 3 floats/double representing bmin(x,y,z) and bmax(x,y,z)
+//*** Plane equations are assumed to be 4 floats or 4 doubles representing Ax,By,Cz,D
+
+FM_Axis fm_getDominantAxis(const float normal[3]);
+FM_Axis fm_getDominantAxis(const double normal[3]);
+
+void fm_decomposeTransform(const float local_transform[16],float trans[3],float rot[4],float scale[3]);
+void fm_decomposeTransform(const double local_transform[16],double trans[3],double rot[4],double scale[3]);
+
+void fm_multiplyTransform(const float *pA,const float *pB,float *pM);
+void fm_multiplyTransform(const double *pA,const double *pB,double *pM);
+
+void fm_inverseTransform(const float matrix[16],float inverse_matrix[16]);
+void fm_inverseTransform(const double matrix[16],double inverse_matrix[16]);
+
+void fm_identity(float matrix[16]); // set 4x4 matrix to identity.
+void fm_identity(double matrix[16]); // set 4x4 matrix to identity.
+
+void fm_inverseRT(const float matrix[16], const float pos[3], float t[3]); // inverse rotate translate the point.
+void fm_inverseRT(const double matrix[16],const double pos[3],double t[3]); // inverse rotate translate the point.
+
+void fm_transform(const float matrix[16], const float pos[3], float t[3]); // rotate and translate this point.
+void fm_transform(const double matrix[16],const double pos[3],double t[3]); // rotate and translate this point.
+
+float fm_getDeterminant(const float matrix[16]);
+double fm_getDeterminant(const double matrix[16]);
+
+void fm_getSubMatrix(int32_t ki,int32_t kj,float pDst[16],const float matrix[16]);
+void fm_getSubMatrix(int32_t ki,int32_t kj,double pDst[16],const float matrix[16]);
+
+void fm_rotate(const float matrix[16],const float pos[3],float t[3]); // only rotate the point by a 4x4 matrix, don't translate.
+void fm_rotate(const double matri[16],const double pos[3],double t[3]); // only rotate the point by a 4x4 matrix, don't translate.
+
+void fm_eulerToMatrix(float ax,float ay,float az,float matrix[16]); // convert euler (in radians) to a dest 4x4 matrix (translation set to zero)
+void fm_eulerToMatrix(double ax,double ay,double az,double matrix[16]); // convert euler (in radians) to a dest 4x4 matrix (translation set to zero)
+
+void fm_getAABB(uint32_t vcount,const float *points,uint32_t pstride,float bmin[3],float bmax[3]);
+void fm_getAABB(uint32_t vcount,const double *points,uint32_t pstride,double bmin[3],double bmax[3]);
+
+void fm_getAABBCenter(const float bmin[3],const float bmax[3],float center[3]);
+void fm_getAABBCenter(const double bmin[3],const double bmax[3],double center[3]);
+
+void fm_transformAABB(const float bmin[3],const float bmax[3],const float matrix[16],float tbmin[3],float tbmax[3]);
+void fm_transformAABB(const double bmin[3],const double bmax[3],const double matrix[16],double tbmin[3],double tbmax[3]);
+
+void fm_eulerToQuat(float x,float y,float z,float quat[4]); // convert euler angles to quaternion.
+void fm_eulerToQuat(double x,double y,double z,double quat[4]); // convert euler angles to quaternion.
+
+void fm_quatToEuler(const float quat[4],float &ax,float &ay,float &az);
+void fm_quatToEuler(const double quat[4],double &ax,double &ay,double &az);
+
+void fm_eulerToQuat(const float euler[3],float quat[4]); // convert euler angles to quaternion. Angles must be radians not degrees!
+void fm_eulerToQuat(const double euler[3],double quat[4]); // convert euler angles to quaternion.
+
+void fm_scale(float x,float y,float z,float matrix[16]); // apply scale to the matrix.
+void fm_scale(double x,double y,double z,double matrix[16]); // apply scale to the matrix.
+
+void fm_eulerToQuatDX(float x,float y,float z,float quat[4]); // convert euler angles to quaternion using the fucked up DirectX method
+void fm_eulerToQuatDX(double x,double y,double z,double quat[4]); // convert euler angles to quaternion using the fucked up DirectX method
+
+void fm_eulerToMatrixDX(float x,float y,float z,float matrix[16]); // convert euler angles to quaternion using the fucked up DirectX method.
+void fm_eulerToMatrixDX(double x,double y,double z,double matrix[16]); // convert euler angles to quaternion using the fucked up DirectX method.
+
+void fm_quatToMatrix(const float quat[4],float matrix[16]); // convert quaterinion rotation to matrix, translation set to zero.
+void fm_quatToMatrix(const double quat[4],double matrix[16]); // convert quaterinion rotation to matrix, translation set to zero.
+
+void fm_quatRotate(const float quat[4],const float v[3],float r[3]); // rotate a vector directly by a quaternion.
+void fm_quatRotate(const double quat[4],const double v[3],double r[3]); // rotate a vector directly by a quaternion.
+
+void fm_getTranslation(const float matrix[16],float t[3]);
+void fm_getTranslation(const double matrix[16],double t[3]);
+
+void fm_setTranslation(const float *translation,float matrix[16]);
+void fm_setTranslation(const double *translation,double matrix[16]);
+
+void fm_multiplyQuat(const float *qa,const float *qb,float *quat);
+void fm_multiplyQuat(const double *qa,const double *qb,double *quat);
+
+void fm_matrixToQuat(const float matrix[16],float quat[4]); // convert the 3x3 portion of a 4x4 matrix into a quaterion as x,y,z,w
+void fm_matrixToQuat(const double matrix[16],double quat[4]); // convert the 3x3 portion of a 4x4 matrix into a quaterion as x,y,z,w
+
+float fm_sphereVolume(float radius); // return's the volume of a sphere of this radius (4/3 PI * R cubed )
+double fm_sphereVolume(double radius); // return's the volume of a sphere of this radius (4/3 PI * R cubed )
+
+float fm_cylinderVolume(float radius,float h);
+double fm_cylinderVolume(double radius,double h);
+
+float fm_capsuleVolume(float radius,float h);
+double fm_capsuleVolume(double radius,double h);
+
+float fm_distance(const float p1[3],const float p2[3]);
+double fm_distance(const double p1[3],const double p2[3]);
+
+float fm_distanceSquared(const float p1[3],const float p2[3]);
+double fm_distanceSquared(const double p1[3],const double p2[3]);
+
+float fm_distanceSquaredXZ(const float p1[3],const float p2[3]);
+double fm_distanceSquaredXZ(const double p1[3],const double p2[3]);
+
+float fm_computePlane(const float p1[3],const float p2[3],const float p3[3],float *n); // return D
+double fm_computePlane(const double p1[3],const double p2[3],const double p3[3],double *n); // return D
+
+float fm_distToPlane(const float plane[4],const float pos[3]); // computes the distance of this point from the plane.
+double fm_distToPlane(const double plane[4],const double pos[3]); // computes the distance of this point from the plane.
+
+float fm_dot(const float p1[3],const float p2[3]);
+double fm_dot(const double p1[3],const double p2[3]);
+
+void fm_cross(float cross[3],const float a[3],const float b[3]);
+void fm_cross(double cross[3],const double a[3],const double b[3]);
+
+float fm_computeNormalVector(float n[3],const float p1[3],const float p2[3]); // as P2-P1 normalized.
+double fm_computeNormalVector(double n[3],const double p1[3],const double p2[3]); // as P2-P1 normalized.
+
+bool fm_computeWindingOrder(const float p1[3],const float p2[3],const float p3[3]); // returns true if the triangle is clockwise.
+bool fm_computeWindingOrder(const double p1[3],const double p2[3],const double p3[3]); // returns true if the triangle is clockwise.
+
+float fm_normalize(float n[3]); // normalize this vector and return the distance
+double fm_normalize(double n[3]); // normalize this vector and return the distance
+
+float fm_normalizeQuat(float n[4]); // normalize this quat
+double fm_normalizeQuat(double n[4]); // normalize this quat
+
+void fm_matrixMultiply(const float A[16],const float B[16],float dest[16]);
+void fm_matrixMultiply(const double A[16],const double B[16],double dest[16]);
+
+void fm_composeTransform(const float position[3],const float quat[4],const float scale[3],float matrix[16]);
+void fm_composeTransform(const double position[3],const double quat[4],const double scale[3],double matrix[16]);
+
+float fm_computeArea(const float p1[3],const float p2[3],const float p3[3]);
+double fm_computeArea(const double p1[3],const double p2[3],const double p3[3]);
+
+void fm_lerp(const float p1[3],const float p2[3],float dest[3],float lerpValue);
+void fm_lerp(const double p1[3],const double p2[3],double dest[3],double lerpValue);
+
+bool fm_insideTriangleXZ(const float test[3],const float p1[3],const float p2[3],const float p3[3]);
+bool fm_insideTriangleXZ(const double test[3],const double p1[3],const double p2[3],const double p3[3]);
+
+bool fm_insideAABB(const float pos[3],const float bmin[3],const float bmax[3]);
+bool fm_insideAABB(const double pos[3],const double bmin[3],const double bmax[3]);
+
+bool fm_insideAABB(const float obmin[3],const float obmax[3],const float tbmin[3],const float tbmax[3]); // test if bounding box tbmin/tmbax is fully inside obmin/obmax
+bool fm_insideAABB(const double obmin[3],const double obmax[3],const double tbmin[3],const double tbmax[3]); // test if bounding box tbmin/tmbax is fully inside obmin/obmax
+
+uint32_t fm_clipTestPoint(const float bmin[3],const float bmax[3],const float pos[3]);
+uint32_t fm_clipTestPoint(const double bmin[3],const double bmax[3],const double pos[3]);
+
+uint32_t fm_clipTestPointXZ(const float bmin[3],const float bmax[3],const float pos[3]); // only tests X and Z, not Y
+uint32_t fm_clipTestPointXZ(const double bmin[3],const double bmax[3],const double pos[3]); // only tests X and Z, not Y
+
+
+uint32_t fm_clipTestAABB(const float bmin[3],const float bmax[3],const float p1[3],const float p2[3],const float p3[3],uint32_t &andCode);
+uint32_t fm_clipTestAABB(const double bmin[3],const double bmax[3],const double p1[3],const double p2[3],const double p3[3],uint32_t &andCode);
+
+
+bool fm_lineTestAABBXZ(const float p1[3],const float p2[3],const float bmin[3],const float bmax[3],float &time);
+bool fm_lineTestAABBXZ(const double p1[3],const double p2[3],const double bmin[3],const double bmax[3],double &time);
+
+bool fm_lineTestAABB(const float p1[3],const float p2[3],const float bmin[3],const float bmax[3],float &time);
+bool fm_lineTestAABB(const double p1[3],const double p2[3],const double bmin[3],const double bmax[3],double &time);
+
+
+void fm_initMinMax(const float p[3],float bmin[3],float bmax[3]);
+void fm_initMinMax(const double p[3],double bmin[3],double bmax[3]);
+
+void fm_initMinMax(float bmin[3],float bmax[3]);
+void fm_initMinMax(double bmin[3],double bmax[3]);
+
+void fm_minmax(const float p[3],float bmin[3],float bmax[3]); // accumulate to a min-max value
+void fm_minmax(const double p[3],double bmin[3],double bmax[3]); // accumulate to a min-max value
+
+// Computes the diagonal length of the bounding box and then inflates the bounding box on all sides
+// by the ratio provided.
+void fm_inflateMinMax(float bmin[3], float bmax[3], float ratio);
+void fm_inflateMinMax(double bmin[3], double bmax[3], double ratio);
+
+float fm_solveX(const float plane[4],float y,float z); // solve for X given this plane equation and the other two components.
+double fm_solveX(const double plane[4],double y,double z); // solve for X given this plane equation and the other two components.
+
+float fm_solveY(const float plane[4],float x,float z); // solve for Y given this plane equation and the other two components.
+double fm_solveY(const double plane[4],double x,double z); // solve for Y given this plane equation and the other two components.
+
+float fm_solveZ(const float plane[4],float x,float y); // solve for Z given this plane equation and the other two components.
+double fm_solveZ(const double plane[4],double x,double y); // solve for Z given this plane equation and the other two components.
+
+bool fm_computeBestFitPlane(uint32_t vcount, // number of input data points
+ const float *points, // starting address of points array.
+ uint32_t vstride, // stride between input points.
+ const float *weights, // *optional point weighting values.
+ uint32_t wstride, // weight stride for each vertex.
+ float plane[4], // Best fit plane equation
+ float center[3]); // Best fit weighted center of input points
+
+bool fm_computeBestFitPlane(uint32_t vcount, // number of input data points
+ const double *points, // starting address of points array.
+ uint32_t vstride, // stride between input points.
+ const double *weights, // *optional point weighting values.
+ uint32_t wstride, // weight stride for each vertex.
+ double plane[4],
+ double center[3]);
+
+// Computes the average center of a set of data points
+bool fm_computeCentroid(uint32_t vcount, // number of input data points
+ const float *points, // starting address of points array.
+ float *center);
+
+bool fm_computeCentroid(uint32_t vcount, // number of input data points
+ const double *points, // starting address of points array.
+ double *center);
+
+// Compute centroid of a triangle mesh; takes area of each triangle into account
+// weighted average
+bool fm_computeCentroid(uint32_t vcount, // number of input data points
+ const float *points, // starting address of points array.
+ uint32_t triangleCount,
+ const uint32_t *indices,
+ float *center);
+
+// Compute centroid of a triangle mesh; takes area of each triangle into account
+// weighted average
+bool fm_computeCentroid(uint32_t vcount, // number of input data points
+ const double *points, // starting address of points array.
+ uint32_t triangleCount,
+ const uint32_t *indices,
+ double *center);
+
+
+float fm_computeBestFitAABB(uint32_t vcount,const float *points,uint32_t pstride,float bmin[3],float bmax[3]); // returns the diagonal distance
+double fm_computeBestFitAABB(uint32_t vcount,const double *points,uint32_t pstride,double bmin[3],double bmax[3]); // returns the diagonal distance
+
+float fm_computeBestFitSphere(uint32_t vcount,const float *points,uint32_t pstride,float center[3]);
+double fm_computeBestFitSphere(uint32_t vcount,const double *points,uint32_t pstride,double center[3]);
+
+bool fm_lineSphereIntersect(const float center[3],float radius,const float p1[3],const float p2[3],float intersect[3]);
+bool fm_lineSphereIntersect(const double center[3],double radius,const double p1[3],const double p2[3],double intersect[3]);
+
+bool fm_intersectRayAABB(const float bmin[3],const float bmax[3],const float pos[3],const float dir[3],float intersect[3]);
+bool fm_intersectLineSegmentAABB(const float bmin[3],const float bmax[3],const float p1[3],const float p2[3],float intersect[3]);
+
+bool fm_lineIntersectsTriangle(const float rayStart[3],const float rayEnd[3],const float p1[3],const float p2[3],const float p3[3],float sect[3]);
+bool fm_lineIntersectsTriangle(const double rayStart[3],const double rayEnd[3],const double p1[3],const double p2[3],const double p3[3],double sect[3]);
+
+bool fm_rayIntersectsTriangle(const float origin[3],const float dir[3],const float v0[3],const float v1[3],const float v2[3],float &t);
+bool fm_rayIntersectsTriangle(const double origin[3],const double dir[3],const double v0[3],const double v1[3],const double v2[3],double &t);
+
+bool fm_raySphereIntersect(const float center[3],float radius,const float pos[3],const float dir[3],float distance,float intersect[3]);
+bool fm_raySphereIntersect(const double center[3],double radius,const double pos[3],const double dir[3],double distance,double intersect[3]);
+
+void fm_catmullRom(float out_vector[3],const float p1[3],const float p2[3],const float p3[3],const float *p4, const float s);
+void fm_catmullRom(double out_vector[3],const double p1[3],const double p2[3],const double p3[3],const double *p4, const double s);
+
+bool fm_intersectAABB(const float bmin1[3],const float bmax1[3],const float bmin2[3],const float bmax2[3]);
+bool fm_intersectAABB(const double bmin1[3],const double bmax1[3],const double bmin2[3],const double bmax2[3]);
+
+
+// computes the rotation quaternion to go from unit-vector v0 to unit-vector v1
+void fm_rotationArc(const float v0[3],const float v1[3],float quat[4]);
+void fm_rotationArc(const double v0[3],const double v1[3],double quat[4]);
+
+float fm_distancePointLineSegment(const float Point[3],const float LineStart[3],const float LineEnd[3],float intersection[3],LineSegmentType &type,float epsilon);
+double fm_distancePointLineSegment(const double Point[3],const double LineStart[3],const double LineEnd[3],double intersection[3],LineSegmentType &type,double epsilon);
+
+
+bool fm_colinear(const double p1[3],const double p2[3],const double p3[3],double epsilon=0.999); // true if these three points in a row are co-linear
+bool fm_colinear(const float p1[3],const float p2[3],const float p3[3],float epsilon=0.999f);
+
+bool fm_colinear(const float a1[3],const float a2[3],const float b1[3],const float b2[3],float epsilon=0.999f); // true if these two line segments are co-linear.
+bool fm_colinear(const double a1[3],const double a2[3],const double b1[3],const double b2[3],double epsilon=0.999); // true if these two line segments are co-linear.
+
+enum IntersectResult
+{
+ IR_DONT_INTERSECT,
+ IR_DO_INTERSECT,
+ IR_COINCIDENT,
+ IR_PARALLEL,
+};
+
+IntersectResult fm_intersectLineSegments2d(const float a1[3], const float a2[3], const float b1[3], const float b2[3], float intersectionPoint[3]);
+IntersectResult fm_intersectLineSegments2d(const double a1[3],const double a2[3],const double b1[3],const double b2[3],double intersectionPoint[3]);
+
+IntersectResult fm_intersectLineSegments2dTime(const float a1[3], const float a2[3], const float b1[3], const float b2[3],float &t1,float &t2);
+IntersectResult fm_intersectLineSegments2dTime(const double a1[3],const double a2[3],const double b1[3],const double b2[3],double &t1,double &t2);
+
+// Plane-Triangle splitting
+
+enum PlaneTriResult
+{
+ PTR_ON_PLANE,
+ PTR_FRONT,
+ PTR_BACK,
+ PTR_SPLIT,
+};
+
+PlaneTriResult fm_planeTriIntersection(const float plane[4], // the plane equation in Ax+By+Cz+D format
+ const float *triangle, // the source triangle.
+ uint32_t tstride, // stride in bytes of the input and output *vertices*
+ float epsilon, // the co-planer epsilon value.
+ float *front, // the triangle in front of the
+ uint32_t &fcount, // number of vertices in the 'front' triangle
+ float *back, // the triangle in back of the plane
+ uint32_t &bcount); // the number of vertices in the 'back' triangle.
+
+
+PlaneTriResult fm_planeTriIntersection(const double plane[4], // the plane equation in Ax+By+Cz+D format
+ const double *triangle, // the source triangle.
+ uint32_t tstride, // stride in bytes of the input and output *vertices*
+ double epsilon, // the co-planer epsilon value.
+ double *front, // the triangle in front of the
+ uint32_t &fcount, // number of vertices in the 'front' triangle
+ double *back, // the triangle in back of the plane
+ uint32_t &bcount); // the number of vertices in the 'back' triangle.
+
+
+bool fm_intersectPointPlane(const float p1[3],const float p2[3],float *split,const float plane[4]);
+bool fm_intersectPointPlane(const double p1[3],const double p2[3],double *split,const double plane[4]);
+
+PlaneTriResult fm_getSidePlane(const float p[3],const float plane[4],float epsilon);
+PlaneTriResult fm_getSidePlane(const double p[3],const double plane[4],double epsilon);
+
+
+void fm_computeBestFitOBB(uint32_t vcount,const float *points,uint32_t pstride,float *sides,float matrix[16],bool bruteForce=true);
+void fm_computeBestFitOBB(uint32_t vcount,const double *points,uint32_t pstride,double *sides,double matrix[16],bool bruteForce=true);
+
+void fm_computeBestFitOBB(uint32_t vcount,const float *points,uint32_t pstride,float *sides,float pos[3],float quat[4],bool bruteForce=true);
+void fm_computeBestFitOBB(uint32_t vcount,const double *points,uint32_t pstride,double *sides,double pos[3],double quat[4],bool bruteForce=true);
+
+void fm_computeBestFitABB(uint32_t vcount,const float *points,uint32_t pstride,float *sides,float pos[3]);
+void fm_computeBestFitABB(uint32_t vcount,const double *points,uint32_t pstride,double *sides,double pos[3]);
+
+
+//** Note, if the returned capsule height is less than zero, then you must represent it is a sphere of size radius.
+void fm_computeBestFitCapsule(uint32_t vcount,const float *points,uint32_t pstride,float &radius,float &height,float matrix[16],bool bruteForce=true);
+void fm_computeBestFitCapsule(uint32_t vcount,const double *points,uint32_t pstride,float &radius,float &height,double matrix[16],bool bruteForce=true);
+
+
+void fm_planeToMatrix(const float plane[4],float matrix[16]); // convert a plane equation to a 4x4 rotation matrix. Reference vector is 0,1,0
+void fm_planeToQuat(const float plane[4],float quat[4],float pos[3]); // convert a plane equation to a quaternion and translation
+
+void fm_planeToMatrix(const double plane[4],double matrix[16]); // convert a plane equation to a 4x4 rotation matrix
+void fm_planeToQuat(const double plane[4],double quat[4],double pos[3]); // convert a plane equation to a quaternion and translation
+
+inline void fm_doubleToFloat3(const double p[3],float t[3]) { t[0] = (float) p[0]; t[1] = (float)p[1]; t[2] = (float)p[2]; };
+inline void fm_floatToDouble3(const float p[3],double t[3]) { t[0] = (double)p[0]; t[1] = (double)p[1]; t[2] = (double)p[2]; };
+
+
+void fm_eulerMatrix(float ax,float ay,float az,float matrix[16]); // convert euler (in radians) to a dest 4x4 matrix (translation set to zero)
+void fm_eulerMatrix(double ax,double ay,double az,double matrix[16]); // convert euler (in radians) to a dest 4x4 matrix (translation set to zero)
+
+
+float fm_computeMeshVolume(const float *vertices,uint32_t tcount,const uint32_t *indices);
+double fm_computeMeshVolume(const double *vertices,uint32_t tcount,const uint32_t *indices);
+
+
+#define FM_DEFAULT_GRANULARITY 0.001f // 1 millimeter is the default granularity
+
+class fm_VertexIndex
+{
+public:
+ virtual uint32_t getIndex(const float pos[3],bool &newPos) = 0; // get welded index for this float vector[3]
+ virtual uint32_t getIndex(const double pos[3],bool &newPos) = 0; // get welded index for this double vector[3]
+ virtual const float * getVerticesFloat(void) const = 0;
+ virtual const double * getVerticesDouble(void) const = 0;
+ virtual const float * getVertexFloat(uint32_t index) const = 0;
+ virtual const double * getVertexDouble(uint32_t index) const = 0;
+ virtual uint32_t getVcount(void) const = 0;
+ virtual bool isDouble(void) const = 0;
+ virtual bool saveAsObj(const char *fname,uint32_t tcount,uint32_t *indices) = 0;
+};
+
+fm_VertexIndex * fm_createVertexIndex(double granularity,bool snapToGrid); // create an indexed vertex system for doubles
+fm_VertexIndex * fm_createVertexIndex(float granularity,bool snapToGrid); // create an indexed vertext system for floats
+void fm_releaseVertexIndex(fm_VertexIndex *vindex);
+
+
+class fm_Triangulate
+{
+public:
+ virtual const double * triangulate3d(uint32_t pcount,
+ const double *points,
+ uint32_t vstride,
+ uint32_t &tcount,
+ bool consolidate,
+ double epsilon) = 0;
+
+ virtual const float * triangulate3d(uint32_t pcount,
+ const float *points,
+ uint32_t vstride,
+ uint32_t &tcount,
+ bool consolidate,
+ float epsilon) = 0;
+};
+
+fm_Triangulate * fm_createTriangulate(void);
+void fm_releaseTriangulate(fm_Triangulate *t);
+
+
+const float * fm_getPoint(const float *points,uint32_t pstride,uint32_t index);
+const double * fm_getPoint(const double *points,uint32_t pstride,uint32_t index);
+
+bool fm_insideTriangle(float Ax, float Ay,float Bx, float By,float Cx, float Cy,float Px, float Py);
+bool fm_insideTriangle(double Ax, double Ay,double Bx, double By,double Cx, double Cy,double Px, double Py);
+float fm_areaPolygon2d(uint32_t pcount,const float *points,uint32_t pstride);
+double fm_areaPolygon2d(uint32_t pcount,const double *points,uint32_t pstride);
+
+bool fm_pointInsidePolygon2d(uint32_t pcount,const float *points,uint32_t pstride,const float *point,uint32_t xindex=0,uint32_t yindex=1);
+bool fm_pointInsidePolygon2d(uint32_t pcount,const double *points,uint32_t pstride,const double *point,uint32_t xindex=0,uint32_t yindex=1);
+
+uint32_t fm_consolidatePolygon(uint32_t pcount,const float *points,uint32_t pstride,float *dest,float epsilon=0.999999f); // collapses co-linear edges.
+uint32_t fm_consolidatePolygon(uint32_t pcount,const double *points,uint32_t pstride,double *dest,double epsilon=0.999999); // collapses co-linear edges.
+
+
+bool fm_computeSplitPlane(uint32_t vcount,const double *vertices,uint32_t tcount,const uint32_t *indices,double *plane);
+bool fm_computeSplitPlane(uint32_t vcount,const float *vertices,uint32_t tcount,const uint32_t *indices,float *plane);
+
+void fm_nearestPointInTriangle(const float *pos,const float *p1,const float *p2,const float *p3,float *nearest);
+void fm_nearestPointInTriangle(const double *pos,const double *p1,const double *p2,const double *p3,double *nearest);
+
+float fm_areaTriangle(const float *p1,const float *p2,const float *p3);
+double fm_areaTriangle(const double *p1,const double *p2,const double *p3);
+
+void fm_subtract(const float *A,const float *B,float *diff); // compute A-B and store the result in 'diff'
+void fm_subtract(const double *A,const double *B,double *diff); // compute A-B and store the result in 'diff'
+
+void fm_multiply(float *A,float scaler);
+void fm_multiply(double *A,double scaler);
+
+void fm_add(const float *A,const float *B,float *sum);
+void fm_add(const double *A,const double *B,double *sum);
+
+void fm_copy3(const float *source,float *dest);
+void fm_copy3(const double *source,double *dest);
+
+// re-indexes an indexed triangle mesh but drops unused vertices. The output_indices can be the same pointer as the input indices.
+// the output_vertices can point to the input vertices if you desire. The output_vertices buffer should be at least the same size
+// is the input buffer. The routine returns the new vertex count after re-indexing.
+uint32_t fm_copyUniqueVertices(uint32_t vcount,const float *input_vertices,float *output_vertices,uint32_t tcount,const uint32_t *input_indices,uint32_t *output_indices);
+uint32_t fm_copyUniqueVertices(uint32_t vcount,const double *input_vertices,double *output_vertices,uint32_t tcount,const uint32_t *input_indices,uint32_t *output_indices);
+
+bool fm_isMeshCoplanar(uint32_t tcount,const uint32_t *indices,const float *vertices,bool doubleSided); // returns true if this collection of indexed triangles are co-planar!
+bool fm_isMeshCoplanar(uint32_t tcount,const uint32_t *indices,const double *vertices,bool doubleSided); // returns true if this collection of indexed triangles are co-planar!
+
+bool fm_samePlane(const float p1[4],const float p2[4],float normalEpsilon=0.01f,float dEpsilon=0.001f,bool doubleSided=false); // returns true if these two plane equations are identical within an epsilon
+bool fm_samePlane(const double p1[4],const double p2[4],double normalEpsilon=0.01,double dEpsilon=0.001,bool doubleSided=false);
+
+void fm_OBBtoAABB(const float obmin[3],const float obmax[3],const float matrix[16],float abmin[3],float abmax[3]);
+
+// a utility class that will tessellate a mesh.
+class fm_Tesselate
+{
+public:
+ virtual const uint32_t * tesselate(fm_VertexIndex *vindex,uint32_t tcount,const uint32_t *indices,float longEdge,uint32_t maxDepth,uint32_t &outcount) = 0;
+};
+
+fm_Tesselate * fm_createTesselate(void);
+void fm_releaseTesselate(fm_Tesselate *t);
+
+void fm_computeMeanNormals(uint32_t vcount, // the number of vertices
+ const float *vertices, // the base address of the vertex position data.
+ uint32_t vstride, // the stride between position data.
+ float *normals, // the base address of the destination for mean vector normals
+ uint32_t nstride, // the stride between normals
+ uint32_t tcount, // the number of triangles
+ const uint32_t *indices); // the triangle indices
+
+void fm_computeMeanNormals(uint32_t vcount, // the number of vertices
+ const double *vertices, // the base address of the vertex position data.
+ uint32_t vstride, // the stride between position data.
+ double *normals, // the base address of the destination for mean vector normals
+ uint32_t nstride, // the stride between normals
+ uint32_t tcount, // the number of triangles
+ const uint32_t *indices); // the triangle indices
+
+
+bool fm_isValidTriangle(const float *p1,const float *p2,const float *p3,float epsilon=0.00001f);
+bool fm_isValidTriangle(const double *p1,const double *p2,const double *p3,double epsilon=0.00001f);
+
+
+}; // end of namespace
+
+#endif
diff --git a/thirdparty/vhacd/inc/btAlignedAllocator.h b/thirdparty/vhacd/inc/btAlignedAllocator.h
new file mode 100644
index 0000000000..94e71d5125
--- /dev/null
+++ b/thirdparty/vhacd/inc/btAlignedAllocator.h
@@ -0,0 +1,113 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_ALIGNED_ALLOCATOR
+#define BT_ALIGNED_ALLOCATOR
+
+///we probably replace this with our own aligned memory allocator
+///so we replace _aligned_malloc and _aligned_free with our own
+///that is better portable and more predictable
+
+#include "btScalar.h"
+
+// -- GODOT start --
+namespace VHACD {
+// -- GODOT end --
+
+//#define BT_DEBUG_MEMORY_ALLOCATIONS 1
+#ifdef BT_DEBUG_MEMORY_ALLOCATIONS
+
+#define btAlignedAlloc(a, b) \
+ btAlignedAllocInternal(a, b, __LINE__, __FILE__)
+
+#define btAlignedFree(ptr) \
+ btAlignedFreeInternal(ptr, __LINE__, __FILE__)
+
+void* btAlignedAllocInternal(size_t size, int32_t alignment, int32_t line, char* filename);
+
+void btAlignedFreeInternal(void* ptr, int32_t line, char* filename);
+
+#else
+void* btAlignedAllocInternal(size_t size, int32_t alignment);
+void btAlignedFreeInternal(void* ptr);
+
+#define btAlignedAlloc(size, alignment) btAlignedAllocInternal(size, alignment)
+#define btAlignedFree(ptr) btAlignedFreeInternal(ptr)
+
+#endif
+typedef int32_t size_type;
+
+typedef void*(btAlignedAllocFunc)(size_t size, int32_t alignment);
+typedef void(btAlignedFreeFunc)(void* memblock);
+typedef void*(btAllocFunc)(size_t size);
+typedef void(btFreeFunc)(void* memblock);
+
+///The developer can let all Bullet memory allocations go through a custom memory allocator, using btAlignedAllocSetCustom
+void btAlignedAllocSetCustom(btAllocFunc* allocFunc, btFreeFunc* freeFunc);
+///If the developer has already an custom aligned allocator, then btAlignedAllocSetCustomAligned can be used. The default aligned allocator pre-allocates extra memory using the non-aligned allocator, and instruments it.
+void btAlignedAllocSetCustomAligned(btAlignedAllocFunc* allocFunc, btAlignedFreeFunc* freeFunc);
+
+///The btAlignedAllocator is a portable class for aligned memory allocations.
+///Default implementations for unaligned and aligned allocations can be overridden by a custom allocator using btAlignedAllocSetCustom and btAlignedAllocSetCustomAligned.
+template <typename T, unsigned Alignment>
+class btAlignedAllocator {
+
+ typedef btAlignedAllocator<T, Alignment> self_type;
+
+public:
+ //just going down a list:
+ btAlignedAllocator() {}
+ /*
+ btAlignedAllocator( const self_type & ) {}
+ */
+
+ template <typename Other>
+ btAlignedAllocator(const btAlignedAllocator<Other, Alignment>&) {}
+
+ typedef const T* const_pointer;
+ typedef const T& const_reference;
+ typedef T* pointer;
+ typedef T& reference;
+ typedef T value_type;
+
+ pointer address(reference ref) const { return &ref; }
+ const_pointer address(const_reference ref) const { return &ref; }
+ pointer allocate(size_type n, const_pointer* hint = 0)
+ {
+ (void)hint;
+ return reinterpret_cast<pointer>(btAlignedAlloc(sizeof(value_type) * n, Alignment));
+ }
+ void construct(pointer ptr, const value_type& value) { new (ptr) value_type(value); }
+ void deallocate(pointer ptr)
+ {
+ btAlignedFree(reinterpret_cast<void*>(ptr));
+ }
+ void destroy(pointer ptr) { ptr->~value_type(); }
+
+ template <typename O>
+ struct rebind {
+ typedef btAlignedAllocator<O, Alignment> other;
+ };
+ template <typename O>
+ self_type& operator=(const btAlignedAllocator<O, Alignment>&) { return *this; }
+
+ friend bool operator==(const self_type&, const self_type&) { return true; }
+};
+
+// -- GODOT start --
+}; // namespace VHACD
+// -- GODOT end --
+
+#endif //BT_ALIGNED_ALLOCATOR
diff --git a/thirdparty/vhacd/inc/btAlignedObjectArray.h b/thirdparty/vhacd/inc/btAlignedObjectArray.h
new file mode 100644
index 0000000000..1ce03d21bc
--- /dev/null
+++ b/thirdparty/vhacd/inc/btAlignedObjectArray.h
@@ -0,0 +1,456 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_OBJECT_ARRAY__
+#define BT_OBJECT_ARRAY__
+
+#include "btAlignedAllocator.h"
+#include "btScalar.h" // has definitions like SIMD_FORCE_INLINE
+
+///If the platform doesn't support placement new, you can disable BT_USE_PLACEMENT_NEW
+///then the btAlignedObjectArray doesn't support objects with virtual methods, and non-trivial constructors/destructors
+///You can enable BT_USE_MEMCPY, then swapping elements in the array will use memcpy instead of operator=
+///see discussion here: http://continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1231 and
+///http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1240
+
+#define BT_USE_PLACEMENT_NEW 1
+//#define BT_USE_MEMCPY 1 //disable, because it is cumbersome to find out for each platform where memcpy is defined. It can be in <memory.h> or <string.h> or otherwise...
+#define BT_ALLOW_ARRAY_COPY_OPERATOR // enabling this can accidently perform deep copies of data if you are not careful
+
+#ifdef BT_USE_MEMCPY
+#include <memory.h>
+#include <string.h>
+#endif //BT_USE_MEMCPY
+
+#ifdef BT_USE_PLACEMENT_NEW
+#include <new> //for placement new
+#endif //BT_USE_PLACEMENT_NEW
+
+// -- GODOT start --
+namespace VHACD {
+// -- GODOT end --
+
+///The btAlignedObjectArray template class uses a subset of the stl::vector interface for its methods
+///It is developed to replace stl::vector to avoid portability issues, including STL alignment issues to add SIMD/SSE data
+template <typename T>
+//template <class T>
+class btAlignedObjectArray {
+ btAlignedAllocator<T, 16> m_allocator;
+
+ int32_t m_size;
+ int32_t m_capacity;
+ T* m_data;
+ //PCK: added this line
+ bool m_ownsMemory;
+
+#ifdef BT_ALLOW_ARRAY_COPY_OPERATOR
+public:
+ SIMD_FORCE_INLINE btAlignedObjectArray<T>& operator=(const btAlignedObjectArray<T>& other)
+ {
+ copyFromArray(other);
+ return *this;
+ }
+#else //BT_ALLOW_ARRAY_COPY_OPERATOR
+private:
+ SIMD_FORCE_INLINE btAlignedObjectArray<T>& operator=(const btAlignedObjectArray<T>& other);
+#endif //BT_ALLOW_ARRAY_COPY_OPERATOR
+
+protected:
+ SIMD_FORCE_INLINE int32_t allocSize(int32_t size)
+ {
+ return (size ? size * 2 : 1);
+ }
+ SIMD_FORCE_INLINE void copy(int32_t start, int32_t end, T* dest) const
+ {
+ int32_t i;
+ for (i = start; i < end; ++i)
+#ifdef BT_USE_PLACEMENT_NEW
+ new (&dest[i]) T(m_data[i]);
+#else
+ dest[i] = m_data[i];
+#endif //BT_USE_PLACEMENT_NEW
+ }
+
+ SIMD_FORCE_INLINE void init()
+ {
+ //PCK: added this line
+ m_ownsMemory = true;
+ m_data = 0;
+ m_size = 0;
+ m_capacity = 0;
+ }
+ SIMD_FORCE_INLINE void destroy(int32_t first, int32_t last)
+ {
+ int32_t i;
+ for (i = first; i < last; i++) {
+ m_data[i].~T();
+ }
+ }
+
+ SIMD_FORCE_INLINE void* allocate(int32_t size)
+ {
+ if (size)
+ return m_allocator.allocate(size);
+ return 0;
+ }
+
+ SIMD_FORCE_INLINE void deallocate()
+ {
+ if (m_data) {
+ //PCK: enclosed the deallocation in this block
+ if (m_ownsMemory) {
+ m_allocator.deallocate(m_data);
+ }
+ m_data = 0;
+ }
+ }
+
+public:
+ btAlignedObjectArray()
+ {
+ init();
+ }
+
+ ~btAlignedObjectArray()
+ {
+ clear();
+ }
+
+ ///Generally it is best to avoid using the copy constructor of an btAlignedObjectArray, and use a (const) reference to the array instead.
+ btAlignedObjectArray(const btAlignedObjectArray& otherArray)
+ {
+ init();
+
+ int32_t otherSize = otherArray.size();
+ resize(otherSize);
+ otherArray.copy(0, otherSize, m_data);
+ }
+
+ /// return the number of elements in the array
+ SIMD_FORCE_INLINE int32_t size() const
+ {
+ return m_size;
+ }
+
+ SIMD_FORCE_INLINE const T& at(int32_t n) const
+ {
+ btAssert(n >= 0);
+ btAssert(n < size());
+ return m_data[n];
+ }
+
+ SIMD_FORCE_INLINE T& at(int32_t n)
+ {
+ btAssert(n >= 0);
+ btAssert(n < size());
+ return m_data[n];
+ }
+
+ SIMD_FORCE_INLINE const T& operator[](int32_t n) const
+ {
+ btAssert(n >= 0);
+ btAssert(n < size());
+ return m_data[n];
+ }
+
+ SIMD_FORCE_INLINE T& operator[](int32_t n)
+ {
+ btAssert(n >= 0);
+ btAssert(n < size());
+ return m_data[n];
+ }
+
+ ///clear the array, deallocated memory. Generally it is better to use array.resize(0), to reduce performance overhead of run-time memory (de)allocations.
+ SIMD_FORCE_INLINE void clear()
+ {
+ destroy(0, size());
+
+ deallocate();
+
+ init();
+ }
+
+ SIMD_FORCE_INLINE void pop_back()
+ {
+ btAssert(m_size > 0);
+ m_size--;
+ m_data[m_size].~T();
+ }
+
+ ///resize changes the number of elements in the array. If the new size is larger, the new elements will be constructed using the optional second argument.
+ ///when the new number of elements is smaller, the destructor will be called, but memory will not be freed, to reduce performance overhead of run-time memory (de)allocations.
+ SIMD_FORCE_INLINE void resize(int32_t newsize, const T& fillData = T())
+ {
+ int32_t curSize = size();
+
+ if (newsize < curSize) {
+ for (int32_t i = newsize; i < curSize; i++) {
+ m_data[i].~T();
+ }
+ }
+ else {
+ if (newsize > size()) {
+ reserve(newsize);
+ }
+#ifdef BT_USE_PLACEMENT_NEW
+ for (int32_t i = curSize; i < newsize; i++) {
+ new (&m_data[i]) T(fillData);
+ }
+#endif //BT_USE_PLACEMENT_NEW
+ }
+
+ m_size = newsize;
+ }
+
+ SIMD_FORCE_INLINE T& expandNonInitializing()
+ {
+ int32_t sz = size();
+ if (sz == capacity()) {
+ reserve(allocSize(size()));
+ }
+ m_size++;
+
+ return m_data[sz];
+ }
+
+ SIMD_FORCE_INLINE T& expand(const T& fillValue = T())
+ {
+ int32_t sz = size();
+ if (sz == capacity()) {
+ reserve(allocSize(size()));
+ }
+ m_size++;
+#ifdef BT_USE_PLACEMENT_NEW
+ new (&m_data[sz]) T(fillValue); //use the in-place new (not really allocating heap memory)
+#endif
+
+ return m_data[sz];
+ }
+
+ SIMD_FORCE_INLINE void push_back(const T& _Val)
+ {
+ int32_t sz = size();
+ if (sz == capacity()) {
+ reserve(allocSize(size()));
+ }
+
+#ifdef BT_USE_PLACEMENT_NEW
+ new (&m_data[m_size]) T(_Val);
+#else
+ m_data[size()] = _Val;
+#endif //BT_USE_PLACEMENT_NEW
+
+ m_size++;
+ }
+
+ /// return the pre-allocated (reserved) elements, this is at least as large as the total number of elements,see size() and reserve()
+ SIMD_FORCE_INLINE int32_t capacity() const
+ {
+ return m_capacity;
+ }
+
+ SIMD_FORCE_INLINE void reserve(int32_t _Count)
+ { // determine new minimum length of allocated storage
+ if (capacity() < _Count) { // not enough room, reallocate
+ T* s = (T*)allocate(_Count);
+
+ copy(0, size(), s);
+
+ destroy(0, size());
+
+ deallocate();
+
+ //PCK: added this line
+ m_ownsMemory = true;
+
+ m_data = s;
+
+ m_capacity = _Count;
+ }
+ }
+
+ class less {
+ public:
+ bool operator()(const T& a, const T& b)
+ {
+ return (a < b);
+ }
+ };
+
+ template <typename L>
+ void quickSortInternal(const L& CompareFunc, int32_t lo, int32_t hi)
+ {
+ // lo is the lower index, hi is the upper index
+ // of the region of array a that is to be sorted
+ int32_t i = lo, j = hi;
+ T x = m_data[(lo + hi) / 2];
+
+ // partition
+ do {
+ while (CompareFunc(m_data[i], x))
+ i++;
+ while (CompareFunc(x, m_data[j]))
+ j--;
+ if (i <= j) {
+ swap(i, j);
+ i++;
+ j--;
+ }
+ } while (i <= j);
+
+ // recursion
+ if (lo < j)
+ quickSortInternal(CompareFunc, lo, j);
+ if (i < hi)
+ quickSortInternal(CompareFunc, i, hi);
+ }
+
+ template <typename L>
+ void quickSort(const L& CompareFunc)
+ {
+ //don't sort 0 or 1 elements
+ if (size() > 1) {
+ quickSortInternal(CompareFunc, 0, size() - 1);
+ }
+ }
+
+ ///heap sort from http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Heap/
+ template <typename L>
+ void downHeap(T* pArr, int32_t k, int32_t n, const L& CompareFunc)
+ {
+ /* PRE: a[k+1..N] is a heap */
+ /* POST: a[k..N] is a heap */
+
+ T temp = pArr[k - 1];
+ /* k has child(s) */
+ while (k <= n / 2) {
+ int32_t child = 2 * k;
+
+ if ((child < n) && CompareFunc(pArr[child - 1], pArr[child])) {
+ child++;
+ }
+ /* pick larger child */
+ if (CompareFunc(temp, pArr[child - 1])) {
+ /* move child up */
+ pArr[k - 1] = pArr[child - 1];
+ k = child;
+ }
+ else {
+ break;
+ }
+ }
+ pArr[k - 1] = temp;
+ } /*downHeap*/
+
+ void swap(int32_t index0, int32_t index1)
+ {
+#ifdef BT_USE_MEMCPY
+ char temp[sizeof(T)];
+ memcpy(temp, &m_data[index0], sizeof(T));
+ memcpy(&m_data[index0], &m_data[index1], sizeof(T));
+ memcpy(&m_data[index1], temp, sizeof(T));
+#else
+ T temp = m_data[index0];
+ m_data[index0] = m_data[index1];
+ m_data[index1] = temp;
+#endif //BT_USE_PLACEMENT_NEW
+ }
+
+ template <typename L>
+ void heapSort(const L& CompareFunc)
+ {
+ /* sort a[0..N-1], N.B. 0 to N-1 */
+ int32_t k;
+ int32_t n = m_size;
+ for (k = n / 2; k > 0; k--) {
+ downHeap(m_data, k, n, CompareFunc);
+ }
+
+ /* a[1..N] is now a heap */
+ while (n >= 1) {
+ swap(0, n - 1); /* largest of a[0..n-1] */
+
+ n = n - 1;
+ /* restore a[1..i-1] heap */
+ downHeap(m_data, 1, n, CompareFunc);
+ }
+ }
+
+ ///non-recursive binary search, assumes sorted array
+ int32_t findBinarySearch(const T& key) const
+ {
+ int32_t first = 0;
+ int32_t last = size() - 1;
+
+ //assume sorted array
+ while (first <= last) {
+ int32_t mid = (first + last) / 2; // compute mid point.
+ if (key > m_data[mid])
+ first = mid + 1; // repeat search in top half.
+ else if (key < m_data[mid])
+ last = mid - 1; // repeat search in bottom half.
+ else
+ return mid; // found it. return position /////
+ }
+ return size(); // failed to find key
+ }
+
+ int32_t findLinearSearch(const T& key) const
+ {
+ int32_t index = size();
+ int32_t i;
+
+ for (i = 0; i < size(); i++) {
+ if (m_data[i] == key) {
+ index = i;
+ break;
+ }
+ }
+ return index;
+ }
+
+ void remove(const T& key)
+ {
+
+ int32_t findIndex = findLinearSearch(key);
+ if (findIndex < size()) {
+ swap(findIndex, size() - 1);
+ pop_back();
+ }
+ }
+
+ //PCK: whole function
+ void initializeFromBuffer(void* buffer, int32_t size, int32_t capacity)
+ {
+ clear();
+ m_ownsMemory = false;
+ m_data = (T*)buffer;
+ m_size = size;
+ m_capacity = capacity;
+ }
+
+ void copyFromArray(const btAlignedObjectArray& otherArray)
+ {
+ int32_t otherSize = otherArray.size();
+ resize(otherSize);
+ otherArray.copy(0, otherSize, m_data);
+ }
+};
+
+// -- GODOT start --
+}; // namespace VHACD
+// -- GODOT end --
+
+#endif //BT_OBJECT_ARRAY__
diff --git a/thirdparty/vhacd/inc/btConvexHullComputer.h b/thirdparty/vhacd/inc/btConvexHullComputer.h
new file mode 100644
index 0000000000..04bb96f64a
--- /dev/null
+++ b/thirdparty/vhacd/inc/btConvexHullComputer.h
@@ -0,0 +1,105 @@
+/*
+Copyright (c) 2011 Ole Kniemeyer, MAXON, www.maxon.net
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_CONVEX_HULL_COMPUTER_H
+#define BT_CONVEX_HULL_COMPUTER_H
+
+#include "btAlignedObjectArray.h"
+#include "btVector3.h"
+
+// -- GODOT start --
+namespace VHACD {
+// -- GODOT end --
+
+/// Convex hull implementation based on Preparata and Hong
+/// See http://code.google.com/p/bullet/issues/detail?id=275
+/// Ole Kniemeyer, MAXON Computer GmbH
+class btConvexHullComputer {
+private:
+ btScalar compute(const void* coords, bool doubleCoords, int32_t stride, int32_t count, btScalar shrink, btScalar shrinkClamp);
+
+public:
+ class Edge {
+ private:
+ int32_t next;
+ int32_t reverse;
+ int32_t targetVertex;
+
+ friend class btConvexHullComputer;
+
+ public:
+ int32_t getSourceVertex() const
+ {
+ return (this + reverse)->targetVertex;
+ }
+
+ int32_t getTargetVertex() const
+ {
+ return targetVertex;
+ }
+
+ const Edge* getNextEdgeOfVertex() const // clockwise list of all edges of a vertex
+ {
+ return this + next;
+ }
+
+ const Edge* getNextEdgeOfFace() const // counter-clockwise list of all edges of a face
+ {
+ return (this + reverse)->getNextEdgeOfVertex();
+ }
+
+ const Edge* getReverseEdge() const
+ {
+ return this + reverse;
+ }
+ };
+
+ // Vertices of the output hull
+ btAlignedObjectArray<btVector3> vertices;
+
+ // Edges of the output hull
+ btAlignedObjectArray<Edge> edges;
+
+ // Faces of the convex hull. Each entry is an index into the "edges" array pointing to an edge of the face. Faces are planar n-gons
+ btAlignedObjectArray<int32_t> faces;
+
+ /*
+ Compute convex hull of "count" vertices stored in "coords". "stride" is the difference in bytes
+ between the addresses of consecutive vertices. If "shrink" is positive, the convex hull is shrunken
+ by that amount (each face is moved by "shrink" length units towards the center along its normal).
+ If "shrinkClamp" is positive, "shrink" is clamped to not exceed "shrinkClamp * innerRadius", where "innerRadius"
+ is the minimum distance of a face to the center of the convex hull.
+
+ The returned value is the amount by which the hull has been shrunken. If it is negative, the amount was so large
+ that the resulting convex hull is empty.
+
+ The output convex hull can be found in the member variables "vertices", "edges", "faces".
+ */
+ btScalar compute(const float* coords, int32_t stride, int32_t count, btScalar shrink, btScalar shrinkClamp)
+ {
+ return compute(coords, false, stride, count, shrink, shrinkClamp);
+ }
+
+ // same as above, but double precision
+ btScalar compute(const double* coords, int32_t stride, int32_t count, btScalar shrink, btScalar shrinkClamp)
+ {
+ return compute(coords, true, stride, count, shrink, shrinkClamp);
+ }
+};
+
+// -- GODOT start --
+}; // namespace VHACD
+// -- GODOT end --
+
+#endif //BT_CONVEX_HULL_COMPUTER_H
diff --git a/thirdparty/vhacd/inc/btMinMax.h b/thirdparty/vhacd/inc/btMinMax.h
new file mode 100644
index 0000000000..9bc1e1c770
--- /dev/null
+++ b/thirdparty/vhacd/inc/btMinMax.h
@@ -0,0 +1,73 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_GEN_MINMAX_H
+#define BT_GEN_MINMAX_H
+
+#include "btScalar.h"
+
+// -- GODOT start --
+namespace VHACD {
+// -- GODOT end --
+
+template <class T>
+SIMD_FORCE_INLINE const T& btMin(const T& a, const T& b)
+{
+ return a < b ? a : b;
+}
+
+template <class T>
+SIMD_FORCE_INLINE const T& btMax(const T& a, const T& b)
+{
+ return a > b ? a : b;
+}
+
+template <class T>
+SIMD_FORCE_INLINE const T& btClamped(const T& a, const T& lb, const T& ub)
+{
+ return a < lb ? lb : (ub < a ? ub : a);
+}
+
+template <class T>
+SIMD_FORCE_INLINE void btSetMin(T& a, const T& b)
+{
+ if (b < a) {
+ a = b;
+ }
+}
+
+template <class T>
+SIMD_FORCE_INLINE void btSetMax(T& a, const T& b)
+{
+ if (a < b) {
+ a = b;
+ }
+}
+
+template <class T>
+SIMD_FORCE_INLINE void btClamp(T& a, const T& lb, const T& ub)
+{
+ if (a < lb) {
+ a = lb;
+ }
+ else if (ub < a) {
+ a = ub;
+ }
+}
+
+// -- GODOT start --
+}; // namespace VHACD
+// -- GODOT end --
+
+#endif //BT_GEN_MINMAX_H
diff --git a/thirdparty/vhacd/inc/btScalar.h b/thirdparty/vhacd/inc/btScalar.h
new file mode 100644
index 0000000000..3999a71521
--- /dev/null
+++ b/thirdparty/vhacd/inc/btScalar.h
@@ -0,0 +1,573 @@
+/*
+Copyright (c) 2003-2009 Erwin Coumans http://bullet.googlecode.com
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SCALAR_H
+#define BT_SCALAR_H
+
+#ifdef BT_MANAGED_CODE
+//Aligned data types not supported in managed code
+#pragma unmanaged
+#endif
+
+#include <float.h>
+#include <math.h>
+#include <stdlib.h> //size_t for MSVC 6.0
+#include <stdint.h>
+
+/* SVN $Revision$ on $Date$ from http://bullet.googlecode.com*/
+#define BT_BULLET_VERSION 279
+
+// -- GODOT start --
+namespace VHACD {
+// -- GODOT end --
+
+inline int32_t btGetVersion()
+{
+ return BT_BULLET_VERSION;
+}
+
+// -- GODOT start --
+}; // namespace VHACD
+// -- GODOT end --
+
+#if defined(DEBUG) || defined(_DEBUG)
+#define BT_DEBUG
+#endif
+
+#ifdef _WIN32
+
+#if defined(__MINGW32__) || defined(__CYGWIN__) || (defined(_MSC_VER) && _MSC_VER < 1300)
+
+#define SIMD_FORCE_INLINE inline
+#define ATTRIBUTE_ALIGNED16(a) a
+#define ATTRIBUTE_ALIGNED64(a) a
+#define ATTRIBUTE_ALIGNED128(a) a
+#else
+//#define BT_HAS_ALIGNED_ALLOCATOR
+#pragma warning(disable : 4324) // disable padding warning
+// #pragma warning(disable:4530) // Disable the exception disable but used in MSCV Stl warning.
+// #pragma warning(disable:4996) //Turn off warnings about deprecated C routines
+// #pragma warning(disable:4786) // Disable the "debug name too long" warning
+
+#define SIMD_FORCE_INLINE __forceinline
+#define ATTRIBUTE_ALIGNED16(a) __declspec(align(16)) a
+#define ATTRIBUTE_ALIGNED64(a) __declspec(align(64)) a
+#define ATTRIBUTE_ALIGNED128(a) __declspec(align(128)) a
+#ifdef _XBOX
+#define BT_USE_VMX128
+
+#include <ppcintrinsics.h>
+#define BT_HAVE_NATIVE_FSEL
+#define btFsel(a, b, c) __fsel((a), (b), (c))
+#else
+
+#if (defined(_WIN32) && (_MSC_VER) && _MSC_VER >= 1400) && (!defined(BT_USE_DOUBLE_PRECISION))
+#define BT_USE_SSE
+#include <emmintrin.h>
+#endif
+
+#endif //_XBOX
+
+#endif //__MINGW32__
+
+#include <assert.h>
+#ifdef BT_DEBUG
+#define btAssert assert
+#else
+#define btAssert(x)
+#endif
+//btFullAssert is optional, slows down a lot
+#define btFullAssert(x)
+
+#define btLikely(_c) _c
+#define btUnlikely(_c) _c
+
+#else
+
+#if defined(__CELLOS_LV2__)
+#define SIMD_FORCE_INLINE inline __attribute__((always_inline))
+#define ATTRIBUTE_ALIGNED16(a) a __attribute__((aligned(16)))
+#define ATTRIBUTE_ALIGNED64(a) a __attribute__((aligned(64)))
+#define ATTRIBUTE_ALIGNED128(a) a __attribute__((aligned(128)))
+#ifndef assert
+#include <assert.h>
+#endif
+#ifdef BT_DEBUG
+#ifdef __SPU__
+#include <spu_printf.h>
+#define printf spu_printf
+#define btAssert(x) \
+ { \
+ if (!(x)) { \
+ printf("Assert " __FILE__ ":%u (" #x ")\n", __LINE__); \
+ spu_hcmpeq(0, 0); \
+ } \
+ }
+#else
+#define btAssert assert
+#endif
+
+#else
+#define btAssert(x)
+#endif
+//btFullAssert is optional, slows down a lot
+#define btFullAssert(x)
+
+#define btLikely(_c) _c
+#define btUnlikely(_c) _c
+
+#else
+
+#ifdef USE_LIBSPE2
+
+#define SIMD_FORCE_INLINE __inline
+#define ATTRIBUTE_ALIGNED16(a) a __attribute__((aligned(16)))
+#define ATTRIBUTE_ALIGNED64(a) a __attribute__((aligned(64)))
+#define ATTRIBUTE_ALIGNED128(a) a __attribute__((aligned(128)))
+#ifndef assert
+#include <assert.h>
+#endif
+#ifdef BT_DEBUG
+#define btAssert assert
+#else
+#define btAssert(x)
+#endif
+//btFullAssert is optional, slows down a lot
+#define btFullAssert(x)
+
+#define btLikely(_c) __builtin_expect((_c), 1)
+#define btUnlikely(_c) __builtin_expect((_c), 0)
+
+#else
+//non-windows systems
+
+#if (defined(__APPLE__) && defined(__i386__) && (!defined(BT_USE_DOUBLE_PRECISION)))
+#define BT_USE_SSE
+#include <emmintrin.h>
+
+#define SIMD_FORCE_INLINE inline
+///@todo: check out alignment methods for other platforms/compilers
+#define ATTRIBUTE_ALIGNED16(a) a __attribute__((aligned(16)))
+#define ATTRIBUTE_ALIGNED64(a) a __attribute__((aligned(64)))
+#define ATTRIBUTE_ALIGNED128(a) a __attribute__((aligned(128)))
+#ifndef assert
+#include <assert.h>
+#endif
+
+#if defined(DEBUG) || defined(_DEBUG)
+#define btAssert assert
+#else
+#define btAssert(x)
+#endif
+
+//btFullAssert is optional, slows down a lot
+#define btFullAssert(x)
+#define btLikely(_c) _c
+#define btUnlikely(_c) _c
+
+#else
+
+#define SIMD_FORCE_INLINE inline
+///@todo: check out alignment methods for other platforms/compilers
+///#define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16)))
+///#define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64)))
+///#define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128)))
+#define ATTRIBUTE_ALIGNED16(a) a
+#define ATTRIBUTE_ALIGNED64(a) a
+#define ATTRIBUTE_ALIGNED128(a) a
+#ifndef assert
+#include <assert.h>
+#endif
+
+#if defined(DEBUG) || defined(_DEBUG)
+#define btAssert assert
+#else
+#define btAssert(x)
+#endif
+
+//btFullAssert is optional, slows down a lot
+#define btFullAssert(x)
+#define btLikely(_c) _c
+#define btUnlikely(_c) _c
+#endif //__APPLE__
+
+#endif // LIBSPE2
+
+#endif //__CELLOS_LV2__
+#endif
+
+// -- GODOT start --
+namespace VHACD {
+// -- GODOT end --
+
+///The btScalar type abstracts floating point numbers, to easily switch between double and single floating point precision.
+#if defined(BT_USE_DOUBLE_PRECISION)
+typedef double btScalar;
+//this number could be bigger in double precision
+#define BT_LARGE_FLOAT 1e30
+#else
+typedef float btScalar;
+//keep BT_LARGE_FLOAT*BT_LARGE_FLOAT < FLT_MAX
+#define BT_LARGE_FLOAT 1e18f
+#endif
+
+#define BT_DECLARE_ALIGNED_ALLOCATOR() \
+ SIMD_FORCE_INLINE void* operator new(size_t sizeInBytes) { return btAlignedAlloc(sizeInBytes, 16); } \
+ SIMD_FORCE_INLINE void operator delete(void* ptr) { btAlignedFree(ptr); } \
+ SIMD_FORCE_INLINE void* operator new(size_t, void* ptr) { return ptr; } \
+ SIMD_FORCE_INLINE void operator delete(void*, void*) {} \
+ SIMD_FORCE_INLINE void* operator new[](size_t sizeInBytes) { return btAlignedAlloc(sizeInBytes, 16); } \
+ SIMD_FORCE_INLINE void operator delete[](void* ptr) { btAlignedFree(ptr); } \
+ SIMD_FORCE_INLINE void* operator new[](size_t, void* ptr) { return ptr; } \
+ SIMD_FORCE_INLINE void operator delete[](void*, void*) {}
+
+#if defined(BT_USE_DOUBLE_PRECISION) || defined(BT_FORCE_DOUBLE_FUNCTIONS)
+
+SIMD_FORCE_INLINE btScalar btSqrt(btScalar x)
+{
+ return sqrt(x);
+}
+SIMD_FORCE_INLINE btScalar btFabs(btScalar x) { return fabs(x); }
+SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cos(x); }
+SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sin(x); }
+SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tan(x); }
+SIMD_FORCE_INLINE btScalar btAcos(btScalar x)
+{
+ if (x < btScalar(-1))
+ x = btScalar(-1);
+ if (x > btScalar(1))
+ x = btScalar(1);
+ return acos(x);
+}
+SIMD_FORCE_INLINE btScalar btAsin(btScalar x)
+{
+ if (x < btScalar(-1))
+ x = btScalar(-1);
+ if (x > btScalar(1))
+ x = btScalar(1);
+ return asin(x);
+}
+SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atan(x); }
+SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2(x, y); }
+SIMD_FORCE_INLINE btScalar btExp(btScalar x) { return exp(x); }
+SIMD_FORCE_INLINE btScalar btLog(btScalar x) { return log(x); }
+SIMD_FORCE_INLINE btScalar btPow(btScalar x, btScalar y) { return pow(x, y); }
+SIMD_FORCE_INLINE btScalar btFmod(btScalar x, btScalar y) { return fmod(x, y); }
+
+#else
+
+SIMD_FORCE_INLINE btScalar btSqrt(btScalar y)
+{
+#ifdef USE_APPROXIMATION
+ double x, z, tempf;
+ unsigned long* tfptr = ((unsigned long*)&tempf) + 1;
+
+ tempf = y;
+ *tfptr = (0xbfcdd90a - *tfptr) >> 1; /* estimate of 1/sqrt(y) */
+ x = tempf;
+ z = y * btScalar(0.5);
+ x = (btScalar(1.5) * x) - (x * x) * (x * z); /* iteration formula */
+ x = (btScalar(1.5) * x) - (x * x) * (x * z);
+ x = (btScalar(1.5) * x) - (x * x) * (x * z);
+ x = (btScalar(1.5) * x) - (x * x) * (x * z);
+ x = (btScalar(1.5) * x) - (x * x) * (x * z);
+ return x * y;
+#else
+ return sqrtf(y);
+#endif
+}
+SIMD_FORCE_INLINE btScalar btFabs(btScalar x) { return fabsf(x); }
+SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cosf(x); }
+SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sinf(x); }
+SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tanf(x); }
+SIMD_FORCE_INLINE btScalar btAcos(btScalar x)
+{
+ if (x < btScalar(-1))
+ x = btScalar(-1);
+ if (x > btScalar(1))
+ x = btScalar(1);
+ return acosf(x);
+}
+SIMD_FORCE_INLINE btScalar btAsin(btScalar x)
+{
+ if (x < btScalar(-1))
+ x = btScalar(-1);
+ if (x > btScalar(1))
+ x = btScalar(1);
+ return asinf(x);
+}
+SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atanf(x); }
+SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2f(x, y); }
+SIMD_FORCE_INLINE btScalar btExp(btScalar x) { return expf(x); }
+SIMD_FORCE_INLINE btScalar btLog(btScalar x) { return logf(x); }
+SIMD_FORCE_INLINE btScalar btPow(btScalar x, btScalar y) { return powf(x, y); }
+SIMD_FORCE_INLINE btScalar btFmod(btScalar x, btScalar y) { return fmodf(x, y); }
+
+#endif
+
+#define SIMD_2_PI btScalar(6.283185307179586232)
+#define SIMD_PI (SIMD_2_PI * btScalar(0.5))
+#define SIMD_HALF_PI (SIMD_2_PI * btScalar(0.25))
+#define SIMD_RADS_PER_DEG (SIMD_2_PI / btScalar(360.0))
+#define SIMD_DEGS_PER_RAD (btScalar(360.0) / SIMD_2_PI)
+#define SIMDSQRT12 btScalar(0.7071067811865475244008443621048490)
+
+#define btRecipSqrt(x) ((btScalar)(btScalar(1.0) / btSqrt(btScalar(x)))) /* reciprocal square root */
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define SIMD_EPSILON DBL_EPSILON
+#define SIMD_INFINITY DBL_MAX
+#else
+#define SIMD_EPSILON FLT_EPSILON
+#define SIMD_INFINITY FLT_MAX
+#endif
+
+SIMD_FORCE_INLINE btScalar btAtan2Fast(btScalar y, btScalar x)
+{
+ btScalar coeff_1 = SIMD_PI / 4.0f;
+ btScalar coeff_2 = 3.0f * coeff_1;
+ btScalar abs_y = btFabs(y);
+ btScalar angle;
+ if (x >= 0.0f) {
+ btScalar r = (x - abs_y) / (x + abs_y);
+ angle = coeff_1 - coeff_1 * r;
+ }
+ else {
+ btScalar r = (x + abs_y) / (abs_y - x);
+ angle = coeff_2 - coeff_1 * r;
+ }
+ return (y < 0.0f) ? -angle : angle;
+}
+
+SIMD_FORCE_INLINE bool btFuzzyZero(btScalar x) { return btFabs(x) < SIMD_EPSILON; }
+
+SIMD_FORCE_INLINE bool btEqual(btScalar a, btScalar eps)
+{
+ return (((a) <= eps) && !((a) < -eps));
+}
+SIMD_FORCE_INLINE bool btGreaterEqual(btScalar a, btScalar eps)
+{
+ return (!((a) <= eps));
+}
+
+SIMD_FORCE_INLINE int32_t btIsNegative(btScalar x)
+{
+ return x < btScalar(0.0) ? 1 : 0;
+}
+
+SIMD_FORCE_INLINE btScalar btRadians(btScalar x) { return x * SIMD_RADS_PER_DEG; }
+SIMD_FORCE_INLINE btScalar btDegrees(btScalar x) { return x * SIMD_DEGS_PER_RAD; }
+
+#define BT_DECLARE_HANDLE(name) \
+ typedef struct name##__ { \
+ int32_t unused; \
+ } * name
+
+#ifndef btFsel
+SIMD_FORCE_INLINE btScalar btFsel(btScalar a, btScalar b, btScalar c)
+{
+ return a >= 0 ? b : c;
+}
+#endif
+#define btFsels(a, b, c) (btScalar) btFsel(a, b, c)
+
+SIMD_FORCE_INLINE bool btMachineIsLittleEndian()
+{
+ long int i = 1;
+ const char* p = (const char*)&i;
+ if (p[0] == 1) // Lowest address contains the least significant byte
+ return true;
+ else
+ return false;
+}
+
+///btSelect avoids branches, which makes performance much better for consoles like Playstation 3 and XBox 360
+///Thanks Phil Knight. See also http://www.cellperformance.com/articles/2006/04/more_techniques_for_eliminatin_1.html
+SIMD_FORCE_INLINE unsigned btSelect(unsigned condition, unsigned valueIfConditionNonZero, unsigned valueIfConditionZero)
+{
+ // Set testNz to 0xFFFFFFFF if condition is nonzero, 0x00000000 if condition is zero
+ // Rely on positive value or'ed with its negative having sign bit on
+ // and zero value or'ed with its negative (which is still zero) having sign bit off
+ // Use arithmetic shift right, shifting the sign bit through all 32 bits
+ unsigned testNz = (unsigned)(((int32_t)condition | -(int32_t)condition) >> 31);
+ unsigned testEqz = ~testNz;
+ return ((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz));
+}
+SIMD_FORCE_INLINE int32_t btSelect(unsigned condition, int32_t valueIfConditionNonZero, int32_t valueIfConditionZero)
+{
+ unsigned testNz = (unsigned)(((int32_t)condition | -(int32_t)condition) >> 31);
+ unsigned testEqz = ~testNz;
+ return static_cast<int32_t>((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz));
+}
+SIMD_FORCE_INLINE float btSelect(unsigned condition, float valueIfConditionNonZero, float valueIfConditionZero)
+{
+#ifdef BT_HAVE_NATIVE_FSEL
+ return (float)btFsel((btScalar)condition - btScalar(1.0f), valueIfConditionNonZero, valueIfConditionZero);
+#else
+ return (condition != 0) ? valueIfConditionNonZero : valueIfConditionZero;
+#endif
+}
+
+template <typename T>
+SIMD_FORCE_INLINE void btSwap(T& a, T& b)
+{
+ T tmp = a;
+ a = b;
+ b = tmp;
+}
+
+//PCK: endian swapping functions
+SIMD_FORCE_INLINE unsigned btSwapEndian(unsigned val)
+{
+ return (((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24));
+}
+
+SIMD_FORCE_INLINE unsigned short btSwapEndian(unsigned short val)
+{
+ return static_cast<unsigned short>(((val & 0xff00) >> 8) | ((val & 0x00ff) << 8));
+}
+
+SIMD_FORCE_INLINE unsigned btSwapEndian(int32_t val)
+{
+ return btSwapEndian((unsigned)val);
+}
+
+SIMD_FORCE_INLINE unsigned short btSwapEndian(short val)
+{
+ return btSwapEndian((unsigned short)val);
+}
+
+///btSwapFloat uses using char pointers to swap the endianness
+////btSwapFloat/btSwapDouble will NOT return a float, because the machine might 'correct' invalid floating point values
+///Not all values of sign/exponent/mantissa are valid floating point numbers according to IEEE 754.
+///When a floating point unit is faced with an invalid value, it may actually change the value, or worse, throw an exception.
+///In most systems, running user mode code, you wouldn't get an exception, but instead the hardware/os/runtime will 'fix' the number for you.
+///so instead of returning a float/double, we return integer/long long integer
+SIMD_FORCE_INLINE uint32_t btSwapEndianFloat(float d)
+{
+ uint32_t a = 0;
+ unsigned char* dst = (unsigned char*)&a;
+ unsigned char* src = (unsigned char*)&d;
+
+ dst[0] = src[3];
+ dst[1] = src[2];
+ dst[2] = src[1];
+ dst[3] = src[0];
+ return a;
+}
+
+// unswap using char pointers
+SIMD_FORCE_INLINE float btUnswapEndianFloat(uint32_t a)
+{
+ float d = 0.0f;
+ unsigned char* src = (unsigned char*)&a;
+ unsigned char* dst = (unsigned char*)&d;
+
+ dst[0] = src[3];
+ dst[1] = src[2];
+ dst[2] = src[1];
+ dst[3] = src[0];
+
+ return d;
+}
+
+// swap using char pointers
+SIMD_FORCE_INLINE void btSwapEndianDouble(double d, unsigned char* dst)
+{
+ unsigned char* src = (unsigned char*)&d;
+
+ dst[0] = src[7];
+ dst[1] = src[6];
+ dst[2] = src[5];
+ dst[3] = src[4];
+ dst[4] = src[3];
+ dst[5] = src[2];
+ dst[6] = src[1];
+ dst[7] = src[0];
+}
+
+// unswap using char pointers
+SIMD_FORCE_INLINE double btUnswapEndianDouble(const unsigned char* src)
+{
+ double d = 0.0;
+ unsigned char* dst = (unsigned char*)&d;
+
+ dst[0] = src[7];
+ dst[1] = src[6];
+ dst[2] = src[5];
+ dst[3] = src[4];
+ dst[4] = src[3];
+ dst[5] = src[2];
+ dst[6] = src[1];
+ dst[7] = src[0];
+
+ return d;
+}
+
+// returns normalized value in range [-SIMD_PI, SIMD_PI]
+SIMD_FORCE_INLINE btScalar btNormalizeAngle(btScalar angleInRadians)
+{
+ angleInRadians = btFmod(angleInRadians, SIMD_2_PI);
+ if (angleInRadians < -SIMD_PI) {
+ return angleInRadians + SIMD_2_PI;
+ }
+ else if (angleInRadians > SIMD_PI) {
+ return angleInRadians - SIMD_2_PI;
+ }
+ else {
+ return angleInRadians;
+ }
+}
+
+///rudimentary class to provide type info
+struct btTypedObject {
+ btTypedObject(int32_t objectType)
+ : m_objectType(objectType)
+ {
+ }
+ int32_t m_objectType;
+ inline int32_t getObjectType() const
+ {
+ return m_objectType;
+ }
+};
+
+// -- GODOT start --
+// Cherry-picked from Bullet 2.88 to fix GH-27926
+///align a pointer to the provided alignment, upwards
+template <typename T>
+T *btAlignPointer(T *unalignedPtr, size_t alignment)
+{
+ struct btConvertPointerSizeT
+ {
+ union {
+ T *ptr;
+ size_t integer;
+ };
+ };
+ btConvertPointerSizeT converter;
+
+ const size_t bit_mask = ~(alignment - 1);
+ converter.ptr = unalignedPtr;
+ converter.integer += alignment - 1;
+ converter.integer &= bit_mask;
+ return converter.ptr;
+}
+// -- GODOT end --
+
+// -- GODOT start --
+}; // namespace VHACD
+// -- GODOT end --
+
+#endif //BT_SCALAR_H
diff --git a/thirdparty/vhacd/inc/btVector3.h b/thirdparty/vhacd/inc/btVector3.h
new file mode 100644
index 0000000000..4ed9716734
--- /dev/null
+++ b/thirdparty/vhacd/inc/btVector3.h
@@ -0,0 +1,723 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_VECTOR3_H
+#define BT_VECTOR3_H
+
+#include "btMinMax.h"
+#include "btScalar.h"
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btVector3Data btVector3DoubleData
+#define btVector3DataName "btVector3DoubleData"
+#else
+#define btVector3Data btVector3FloatData
+#define btVector3DataName "btVector3FloatData"
+#endif //BT_USE_DOUBLE_PRECISION
+
+// -- GODOT start --
+namespace VHACD {
+// -- GODOT end --
+
+/**@brief btVector3 can be used to represent 3D points and vectors.
+ * It has an un-used w component to suit 16-byte alignment when btVector3 is stored in containers. This extra component can be used by derived classes (Quaternion?) or by user
+ * Ideally, this class should be replaced by a platform optimized SIMD version that keeps the data in registers
+ */
+ATTRIBUTE_ALIGNED16(class)
+btVector3
+{
+public:
+#if defined(__SPU__) && defined(__CELLOS_LV2__)
+ btScalar m_floats[4];
+
+public:
+ SIMD_FORCE_INLINE const vec_float4& get128() const
+ {
+ return *((const vec_float4*)&m_floats[0]);
+ }
+
+public:
+#else //__CELLOS_LV2__ __SPU__
+#ifdef BT_USE_SSE // _WIN32
+ union {
+ __m128 mVec128;
+ btScalar m_floats[4];
+ };
+ SIMD_FORCE_INLINE __m128 get128() const
+ {
+ return mVec128;
+ }
+ SIMD_FORCE_INLINE void set128(__m128 v128)
+ {
+ mVec128 = v128;
+ }
+#else
+ btScalar m_floats[4];
+#endif
+#endif //__CELLOS_LV2__ __SPU__
+
+public:
+ /**@brief No initialization constructor */
+ SIMD_FORCE_INLINE btVector3() {}
+
+ /**@brief Constructor from scalars
+ * @param x X value
+ * @param y Y value
+ * @param z Z value
+ */
+ SIMD_FORCE_INLINE btVector3(const btScalar& x, const btScalar& y, const btScalar& z)
+ {
+ m_floats[0] = x;
+ m_floats[1] = y;
+ m_floats[2] = z;
+ m_floats[3] = btScalar(0.);
+ }
+
+ /**@brief Add a vector to this one
+ * @param The vector to add to this one */
+ SIMD_FORCE_INLINE btVector3& operator+=(const btVector3& v)
+ {
+
+ m_floats[0] += v.m_floats[0];
+ m_floats[1] += v.m_floats[1];
+ m_floats[2] += v.m_floats[2];
+ return *this;
+ }
+
+ /**@brief Subtract a vector from this one
+ * @param The vector to subtract */
+ SIMD_FORCE_INLINE btVector3& operator-=(const btVector3& v)
+ {
+ m_floats[0] -= v.m_floats[0];
+ m_floats[1] -= v.m_floats[1];
+ m_floats[2] -= v.m_floats[2];
+ return *this;
+ }
+ /**@brief Scale the vector
+ * @param s Scale factor */
+ SIMD_FORCE_INLINE btVector3& operator*=(const btScalar& s)
+ {
+ m_floats[0] *= s;
+ m_floats[1] *= s;
+ m_floats[2] *= s;
+ return *this;
+ }
+
+ /**@brief Inversely scale the vector
+ * @param s Scale factor to divide by */
+ SIMD_FORCE_INLINE btVector3& operator/=(const btScalar& s)
+ {
+ btFullAssert(s != btScalar(0.0));
+ return * this *= btScalar(1.0) / s;
+ }
+
+ /**@brief Return the dot product
+ * @param v The other vector in the dot product */
+ SIMD_FORCE_INLINE btScalar dot(const btVector3& v) const
+ {
+ return m_floats[0] * v.m_floats[0] + m_floats[1] * v.m_floats[1] + m_floats[2] * v.m_floats[2];
+ }
+
+ /**@brief Return the length of the vector squared */
+ SIMD_FORCE_INLINE btScalar length2() const
+ {
+ return dot(*this);
+ }
+
+ /**@brief Return the length of the vector */
+ SIMD_FORCE_INLINE btScalar length() const
+ {
+ return btSqrt(length2());
+ }
+
+ /**@brief Return the distance squared between the ends of this and another vector
+ * This is symantically treating the vector like a point */
+ SIMD_FORCE_INLINE btScalar distance2(const btVector3& v) const;
+
+ /**@brief Return the distance between the ends of this and another vector
+ * This is symantically treating the vector like a point */
+ SIMD_FORCE_INLINE btScalar distance(const btVector3& v) const;
+
+ SIMD_FORCE_INLINE btVector3& safeNormalize()
+ {
+ btVector3 absVec = this->absolute();
+ int32_t maxIndex = absVec.maxAxis();
+ if (absVec[maxIndex] > 0) {
+ *this /= absVec[maxIndex];
+ return * this /= length();
+ }
+ setValue(1, 0, 0);
+ return *this;
+ }
+
+ /**@brief Normalize this vector
+ * x^2 + y^2 + z^2 = 1 */
+ SIMD_FORCE_INLINE btVector3& normalize()
+ {
+ return * this /= length();
+ }
+
+ /**@brief Return a normalized version of this vector */
+ SIMD_FORCE_INLINE btVector3 normalized() const;
+
+ /**@brief Return a rotated version of this vector
+ * @param wAxis The axis to rotate about
+ * @param angle The angle to rotate by */
+ SIMD_FORCE_INLINE btVector3 rotate(const btVector3& wAxis, const btScalar angle) const;
+
+ /**@brief Return the angle between this and another vector
+ * @param v The other vector */
+ SIMD_FORCE_INLINE btScalar angle(const btVector3& v) const
+ {
+ btScalar s = btSqrt(length2() * v.length2());
+ btFullAssert(s != btScalar(0.0));
+ return btAcos(dot(v) / s);
+ }
+ /**@brief Return a vector will the absolute values of each element */
+ SIMD_FORCE_INLINE btVector3 absolute() const
+ {
+ return btVector3(
+ btFabs(m_floats[0]),
+ btFabs(m_floats[1]),
+ btFabs(m_floats[2]));
+ }
+ /**@brief Return the cross product between this and another vector
+ * @param v The other vector */
+ SIMD_FORCE_INLINE btVector3 cross(const btVector3& v) const
+ {
+ return btVector3(
+ m_floats[1] * v.m_floats[2] - m_floats[2] * v.m_floats[1],
+ m_floats[2] * v.m_floats[0] - m_floats[0] * v.m_floats[2],
+ m_floats[0] * v.m_floats[1] - m_floats[1] * v.m_floats[0]);
+ }
+
+ SIMD_FORCE_INLINE btScalar triple(const btVector3& v1, const btVector3& v2) const
+ {
+ return m_floats[0] * (v1.m_floats[1] * v2.m_floats[2] - v1.m_floats[2] * v2.m_floats[1]) + m_floats[1] * (v1.m_floats[2] * v2.m_floats[0] - v1.m_floats[0] * v2.m_floats[2]) + m_floats[2] * (v1.m_floats[0] * v2.m_floats[1] - v1.m_floats[1] * v2.m_floats[0]);
+ }
+
+ /**@brief Return the axis with the smallest value
+ * Note return values are 0,1,2 for x, y, or z */
+ SIMD_FORCE_INLINE int32_t minAxis() const
+ {
+ return m_floats[0] < m_floats[1] ? (m_floats[0] < m_floats[2] ? 0 : 2) : (m_floats[1] < m_floats[2] ? 1 : 2);
+ }
+
+ /**@brief Return the axis with the largest value
+ * Note return values are 0,1,2 for x, y, or z */
+ SIMD_FORCE_INLINE int32_t maxAxis() const
+ {
+ return m_floats[0] < m_floats[1] ? (m_floats[1] < m_floats[2] ? 2 : 1) : (m_floats[0] < m_floats[2] ? 2 : 0);
+ }
+
+ SIMD_FORCE_INLINE int32_t furthestAxis() const
+ {
+ return absolute().minAxis();
+ }
+
+ SIMD_FORCE_INLINE int32_t closestAxis() const
+ {
+ return absolute().maxAxis();
+ }
+
+ SIMD_FORCE_INLINE void setInterpolate3(const btVector3& v0, const btVector3& v1, btScalar rt)
+ {
+ btScalar s = btScalar(1.0) - rt;
+ m_floats[0] = s * v0.m_floats[0] + rt * v1.m_floats[0];
+ m_floats[1] = s * v0.m_floats[1] + rt * v1.m_floats[1];
+ m_floats[2] = s * v0.m_floats[2] + rt * v1.m_floats[2];
+ //don't do the unused w component
+ // m_co[3] = s * v0[3] + rt * v1[3];
+ }
+
+ /**@brief Return the linear interpolation between this and another vector
+ * @param v The other vector
+ * @param t The ration of this to v (t = 0 => return this, t=1 => return other) */
+ SIMD_FORCE_INLINE btVector3 lerp(const btVector3& v, const btScalar& t) const
+ {
+ return btVector3(m_floats[0] + (v.m_floats[0] - m_floats[0]) * t,
+ m_floats[1] + (v.m_floats[1] - m_floats[1]) * t,
+ m_floats[2] + (v.m_floats[2] - m_floats[2]) * t);
+ }
+
+ /**@brief Elementwise multiply this vector by the other
+ * @param v The other vector */
+ SIMD_FORCE_INLINE btVector3& operator*=(const btVector3& v)
+ {
+ m_floats[0] *= v.m_floats[0];
+ m_floats[1] *= v.m_floats[1];
+ m_floats[2] *= v.m_floats[2];
+ return *this;
+ }
+
+ /**@brief Return the x value */
+ SIMD_FORCE_INLINE const btScalar& getX() const { return m_floats[0]; }
+ /**@brief Return the y value */
+ SIMD_FORCE_INLINE const btScalar& getY() const { return m_floats[1]; }
+ /**@brief Return the z value */
+ SIMD_FORCE_INLINE const btScalar& getZ() const { return m_floats[2]; }
+ /**@brief Set the x value */
+ SIMD_FORCE_INLINE void setX(btScalar x) { m_floats[0] = x; };
+ /**@brief Set the y value */
+ SIMD_FORCE_INLINE void setY(btScalar y) { m_floats[1] = y; };
+ /**@brief Set the z value */
+ SIMD_FORCE_INLINE void setZ(btScalar z) { m_floats[2] = z; };
+ /**@brief Set the w value */
+ SIMD_FORCE_INLINE void setW(btScalar w) { m_floats[3] = w; };
+ /**@brief Return the x value */
+ SIMD_FORCE_INLINE const btScalar& x() const { return m_floats[0]; }
+ /**@brief Return the y value */
+ SIMD_FORCE_INLINE const btScalar& y() const { return m_floats[1]; }
+ /**@brief Return the z value */
+ SIMD_FORCE_INLINE const btScalar& z() const { return m_floats[2]; }
+ /**@brief Return the w value */
+ SIMD_FORCE_INLINE const btScalar& w() const { return m_floats[3]; }
+
+ //SIMD_FORCE_INLINE btScalar& operator[](int32_t i) { return (&m_floats[0])[i]; }
+ //SIMD_FORCE_INLINE const btScalar& operator[](int32_t i) const { return (&m_floats[0])[i]; }
+ ///operator btScalar*() replaces operator[], using implicit conversion. We added operator != and operator == to avoid pointer comparisons.
+ SIMD_FORCE_INLINE operator btScalar*() { return &m_floats[0]; }
+ SIMD_FORCE_INLINE operator const btScalar*() const { return &m_floats[0]; }
+
+ SIMD_FORCE_INLINE bool operator==(const btVector3& other) const
+ {
+ return ((m_floats[3] == other.m_floats[3]) && (m_floats[2] == other.m_floats[2]) && (m_floats[1] == other.m_floats[1]) && (m_floats[0] == other.m_floats[0]));
+ }
+
+ SIMD_FORCE_INLINE bool operator!=(const btVector3& other) const
+ {
+ return !(*this == other);
+ }
+
+ /**@brief Set each element to the max of the current values and the values of another btVector3
+ * @param other The other btVector3 to compare with
+ */
+ SIMD_FORCE_INLINE void setMax(const btVector3& other)
+ {
+ btSetMax(m_floats[0], other.m_floats[0]);
+ btSetMax(m_floats[1], other.m_floats[1]);
+ btSetMax(m_floats[2], other.m_floats[2]);
+ btSetMax(m_floats[3], other.w());
+ }
+ /**@brief Set each element to the min of the current values and the values of another btVector3
+ * @param other The other btVector3 to compare with
+ */
+ SIMD_FORCE_INLINE void setMin(const btVector3& other)
+ {
+ btSetMin(m_floats[0], other.m_floats[0]);
+ btSetMin(m_floats[1], other.m_floats[1]);
+ btSetMin(m_floats[2], other.m_floats[2]);
+ btSetMin(m_floats[3], other.w());
+ }
+
+ SIMD_FORCE_INLINE void setValue(const btScalar& x, const btScalar& y, const btScalar& z)
+ {
+ m_floats[0] = x;
+ m_floats[1] = y;
+ m_floats[2] = z;
+ m_floats[3] = btScalar(0.);
+ }
+
+ void getSkewSymmetricMatrix(btVector3 * v0, btVector3 * v1, btVector3 * v2) const
+ {
+ v0->setValue(0., -z(), y());
+ v1->setValue(z(), 0., -x());
+ v2->setValue(-y(), x(), 0.);
+ }
+
+ void setZero()
+ {
+ setValue(btScalar(0.), btScalar(0.), btScalar(0.));
+ }
+
+ SIMD_FORCE_INLINE bool isZero() const
+ {
+ return m_floats[0] == btScalar(0) && m_floats[1] == btScalar(0) && m_floats[2] == btScalar(0);
+ }
+
+ SIMD_FORCE_INLINE bool fuzzyZero() const
+ {
+ return length2() < SIMD_EPSILON;
+ }
+
+ SIMD_FORCE_INLINE void serialize(struct btVector3Data & dataOut) const;
+
+ SIMD_FORCE_INLINE void deSerialize(const struct btVector3Data& dataIn);
+
+ SIMD_FORCE_INLINE void serializeFloat(struct btVector3FloatData & dataOut) const;
+
+ SIMD_FORCE_INLINE void deSerializeFloat(const struct btVector3FloatData& dataIn);
+
+ SIMD_FORCE_INLINE void serializeDouble(struct btVector3DoubleData & dataOut) const;
+
+ SIMD_FORCE_INLINE void deSerializeDouble(const struct btVector3DoubleData& dataIn);
+};
+
+/**@brief Return the sum of two vectors (Point symantics)*/
+SIMD_FORCE_INLINE btVector3
+operator+(const btVector3& v1, const btVector3& v2)
+{
+ return btVector3(v1.m_floats[0] + v2.m_floats[0], v1.m_floats[1] + v2.m_floats[1], v1.m_floats[2] + v2.m_floats[2]);
+}
+
+/**@brief Return the elementwise product of two vectors */
+SIMD_FORCE_INLINE btVector3
+operator*(const btVector3& v1, const btVector3& v2)
+{
+ return btVector3(v1.m_floats[0] * v2.m_floats[0], v1.m_floats[1] * v2.m_floats[1], v1.m_floats[2] * v2.m_floats[2]);
+}
+
+/**@brief Return the difference between two vectors */
+SIMD_FORCE_INLINE btVector3
+operator-(const btVector3& v1, const btVector3& v2)
+{
+ return btVector3(v1.m_floats[0] - v2.m_floats[0], v1.m_floats[1] - v2.m_floats[1], v1.m_floats[2] - v2.m_floats[2]);
+}
+/**@brief Return the negative of the vector */
+SIMD_FORCE_INLINE btVector3
+operator-(const btVector3& v)
+{
+ return btVector3(-v.m_floats[0], -v.m_floats[1], -v.m_floats[2]);
+}
+
+/**@brief Return the vector scaled by s */
+SIMD_FORCE_INLINE btVector3
+operator*(const btVector3& v, const btScalar& s)
+{
+ return btVector3(v.m_floats[0] * s, v.m_floats[1] * s, v.m_floats[2] * s);
+}
+
+/**@brief Return the vector scaled by s */
+SIMD_FORCE_INLINE btVector3
+operator*(const btScalar& s, const btVector3& v)
+{
+ return v * s;
+}
+
+/**@brief Return the vector inversely scaled by s */
+SIMD_FORCE_INLINE btVector3
+operator/(const btVector3& v, const btScalar& s)
+{
+ btFullAssert(s != btScalar(0.0));
+ return v * (btScalar(1.0) / s);
+}
+
+/**@brief Return the vector inversely scaled by s */
+SIMD_FORCE_INLINE btVector3
+operator/(const btVector3& v1, const btVector3& v2)
+{
+ return btVector3(v1.m_floats[0] / v2.m_floats[0], v1.m_floats[1] / v2.m_floats[1], v1.m_floats[2] / v2.m_floats[2]);
+}
+
+/**@brief Return the dot product between two vectors */
+SIMD_FORCE_INLINE btScalar
+btDot(const btVector3& v1, const btVector3& v2)
+{
+ return v1.dot(v2);
+}
+
+/**@brief Return the distance squared between two vectors */
+SIMD_FORCE_INLINE btScalar
+btDistance2(const btVector3& v1, const btVector3& v2)
+{
+ return v1.distance2(v2);
+}
+
+/**@brief Return the distance between two vectors */
+SIMD_FORCE_INLINE btScalar
+btDistance(const btVector3& v1, const btVector3& v2)
+{
+ return v1.distance(v2);
+}
+
+/**@brief Return the angle between two vectors */
+SIMD_FORCE_INLINE btScalar
+btAngle(const btVector3& v1, const btVector3& v2)
+{
+ return v1.angle(v2);
+}
+
+/**@brief Return the cross product of two vectors */
+SIMD_FORCE_INLINE btVector3
+btCross(const btVector3& v1, const btVector3& v2)
+{
+ return v1.cross(v2);
+}
+
+SIMD_FORCE_INLINE btScalar
+btTriple(const btVector3& v1, const btVector3& v2, const btVector3& v3)
+{
+ return v1.triple(v2, v3);
+}
+
+/**@brief Return the linear interpolation between two vectors
+ * @param v1 One vector
+ * @param v2 The other vector
+ * @param t The ration of this to v (t = 0 => return v1, t=1 => return v2) */
+SIMD_FORCE_INLINE btVector3
+lerp(const btVector3& v1, const btVector3& v2, const btScalar& t)
+{
+ return v1.lerp(v2, t);
+}
+
+SIMD_FORCE_INLINE btScalar btVector3::distance2(const btVector3& v) const
+{
+ return (v - *this).length2();
+}
+
+SIMD_FORCE_INLINE btScalar btVector3::distance(const btVector3& v) const
+{
+ return (v - *this).length();
+}
+
+SIMD_FORCE_INLINE btVector3 btVector3::normalized() const
+{
+ return *this / length();
+}
+
+SIMD_FORCE_INLINE btVector3 btVector3::rotate(const btVector3& wAxis, const btScalar angle) const
+{
+ // wAxis must be a unit lenght vector
+
+ btVector3 o = wAxis * wAxis.dot(*this);
+ btVector3 x = *this - o;
+ btVector3 y;
+
+ y = wAxis.cross(*this);
+
+ return (o + x * btCos(angle) + y * btSin(angle));
+}
+
+class btVector4 : public btVector3 {
+public:
+ SIMD_FORCE_INLINE btVector4() {}
+
+ SIMD_FORCE_INLINE btVector4(const btScalar& x, const btScalar& y, const btScalar& z, const btScalar& w)
+ : btVector3(x, y, z)
+ {
+ m_floats[3] = w;
+ }
+
+ SIMD_FORCE_INLINE btVector4 absolute4() const
+ {
+ return btVector4(
+ btFabs(m_floats[0]),
+ btFabs(m_floats[1]),
+ btFabs(m_floats[2]),
+ btFabs(m_floats[3]));
+ }
+
+ btScalar getW() const { return m_floats[3]; }
+
+ SIMD_FORCE_INLINE int32_t maxAxis4() const
+ {
+ int32_t maxIndex = -1;
+ btScalar maxVal = btScalar(-BT_LARGE_FLOAT);
+ if (m_floats[0] > maxVal) {
+ maxIndex = 0;
+ maxVal = m_floats[0];
+ }
+ if (m_floats[1] > maxVal) {
+ maxIndex = 1;
+ maxVal = m_floats[1];
+ }
+ if (m_floats[2] > maxVal) {
+ maxIndex = 2;
+ maxVal = m_floats[2];
+ }
+ if (m_floats[3] > maxVal) {
+ maxIndex = 3;
+ }
+ return maxIndex;
+ }
+
+ SIMD_FORCE_INLINE int32_t minAxis4() const
+ {
+ int32_t minIndex = -1;
+ btScalar minVal = btScalar(BT_LARGE_FLOAT);
+ if (m_floats[0] < minVal) {
+ minIndex = 0;
+ minVal = m_floats[0];
+ }
+ if (m_floats[1] < minVal) {
+ minIndex = 1;
+ minVal = m_floats[1];
+ }
+ if (m_floats[2] < minVal) {
+ minIndex = 2;
+ minVal = m_floats[2];
+ }
+ if (m_floats[3] < minVal) {
+ minIndex = 3;
+ }
+
+ return minIndex;
+ }
+
+ SIMD_FORCE_INLINE int32_t closestAxis4() const
+ {
+ return absolute4().maxAxis4();
+ }
+
+ /**@brief Set x,y,z and zero w
+ * @param x Value of x
+ * @param y Value of y
+ * @param z Value of z
+ */
+
+ /* void getValue(btScalar *m) const
+ {
+ m[0] = m_floats[0];
+ m[1] = m_floats[1];
+ m[2] =m_floats[2];
+ }
+*/
+ /**@brief Set the values
+ * @param x Value of x
+ * @param y Value of y
+ * @param z Value of z
+ * @param w Value of w
+ */
+ SIMD_FORCE_INLINE void setValue(const btScalar& x, const btScalar& y, const btScalar& z, const btScalar& w)
+ {
+ m_floats[0] = x;
+ m_floats[1] = y;
+ m_floats[2] = z;
+ m_floats[3] = w;
+ }
+};
+
+///btSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization
+SIMD_FORCE_INLINE void btSwapScalarEndian(const btScalar& sourceVal, btScalar& destVal)
+{
+#ifdef BT_USE_DOUBLE_PRECISION
+ unsigned char* dest = (unsigned char*)&destVal;
+ unsigned char* src = (unsigned char*)&sourceVal;
+ dest[0] = src[7];
+ dest[1] = src[6];
+ dest[2] = src[5];
+ dest[3] = src[4];
+ dest[4] = src[3];
+ dest[5] = src[2];
+ dest[6] = src[1];
+ dest[7] = src[0];
+#else
+ unsigned char* dest = (unsigned char*)&destVal;
+ unsigned char* src = (unsigned char*)&sourceVal;
+ dest[0] = src[3];
+ dest[1] = src[2];
+ dest[2] = src[1];
+ dest[3] = src[0];
+#endif //BT_USE_DOUBLE_PRECISION
+}
+///btSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization
+SIMD_FORCE_INLINE void btSwapVector3Endian(const btVector3& sourceVec, btVector3& destVec)
+{
+ for (int32_t i = 0; i < 4; i++) {
+ btSwapScalarEndian(sourceVec[i], destVec[i]);
+ }
+}
+
+///btUnSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization
+SIMD_FORCE_INLINE void btUnSwapVector3Endian(btVector3& vector)
+{
+
+ btVector3 swappedVec;
+ for (int32_t i = 0; i < 4; i++) {
+ btSwapScalarEndian(vector[i], swappedVec[i]);
+ }
+ vector = swappedVec;
+}
+
+template <class T>
+SIMD_FORCE_INLINE void btPlaneSpace1(const T& n, T& p, T& q)
+{
+ if (btFabs(n[2]) > SIMDSQRT12) {
+ // choose p in y-z plane
+ btScalar a = n[1] * n[1] + n[2] * n[2];
+ btScalar k = btRecipSqrt(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
+ btScalar a = n[0] * n[0] + n[1] * n[1];
+ btScalar k = btRecipSqrt(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;
+ }
+}
+
+struct btVector3FloatData {
+ float m_floats[4];
+};
+
+struct btVector3DoubleData {
+ double m_floats[4];
+};
+
+SIMD_FORCE_INLINE void btVector3::serializeFloat(struct btVector3FloatData& dataOut) const
+{
+ ///could also do a memcpy, check if it is worth it
+ for (int32_t i = 0; i < 4; i++)
+ dataOut.m_floats[i] = float(m_floats[i]);
+}
+
+SIMD_FORCE_INLINE void btVector3::deSerializeFloat(const struct btVector3FloatData& dataIn)
+{
+ for (int32_t i = 0; i < 4; i++)
+ m_floats[i] = btScalar(dataIn.m_floats[i]);
+}
+
+SIMD_FORCE_INLINE void btVector3::serializeDouble(struct btVector3DoubleData& dataOut) const
+{
+ ///could also do a memcpy, check if it is worth it
+ for (int32_t i = 0; i < 4; i++)
+ dataOut.m_floats[i] = double(m_floats[i]);
+}
+
+SIMD_FORCE_INLINE void btVector3::deSerializeDouble(const struct btVector3DoubleData& dataIn)
+{
+ for (int32_t i = 0; i < 4; i++)
+ m_floats[i] = btScalar(dataIn.m_floats[i]);
+}
+
+SIMD_FORCE_INLINE void btVector3::serialize(struct btVector3Data& dataOut) const
+{
+ ///could also do a memcpy, check if it is worth it
+ for (int32_t i = 0; i < 4; i++)
+ dataOut.m_floats[i] = m_floats[i];
+}
+
+SIMD_FORCE_INLINE void btVector3::deSerialize(const struct btVector3Data& dataIn)
+{
+ for (int32_t i = 0; i < 4; i++)
+ m_floats[i] = dataIn.m_floats[i];
+}
+
+// -- GODOT start --
+}; // namespace VHACD
+// -- GODOT end --
+
+#endif //BT_VECTOR3_H
diff --git a/thirdparty/vhacd/inc/vhacdCircularList.h b/thirdparty/vhacd/inc/vhacdCircularList.h
new file mode 100644
index 0000000000..0f5ddf9ecf
--- /dev/null
+++ b/thirdparty/vhacd/inc/vhacdCircularList.h
@@ -0,0 +1,79 @@
+/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
+ All rights reserved.
+
+
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+ 2. 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.
+
+ 3. The names of the contributors may not 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.
+ */
+#pragma once
+#ifndef VHACD_CIRCULAR_LIST_H
+#define VHACD_CIRCULAR_LIST_H
+#include <stdlib.h>
+namespace VHACD {
+//! CircularListElement class.
+template <typename T>
+class CircularListElement {
+public:
+ T& GetData() { return m_data; }
+ const T& GetData() const { return m_data; }
+ CircularListElement<T>*& GetNext() { return m_next; }
+ CircularListElement<T>*& GetPrev() { return m_prev; }
+ const CircularListElement<T>*& GetNext() const { return m_next; }
+ const CircularListElement<T>*& GetPrev() const { return m_prev; }
+ //! Constructor
+ CircularListElement(const T& data) { m_data = data; }
+ CircularListElement(void) {}
+ //! Destructor
+ ~CircularListElement(void) {}
+private:
+ T m_data;
+ CircularListElement<T>* m_next;
+ CircularListElement<T>* m_prev;
+
+ CircularListElement(const CircularListElement& rhs);
+};
+//! CircularList class.
+template <typename T>
+class CircularList {
+public:
+ CircularListElement<T>*& GetHead() { return m_head; }
+ const CircularListElement<T>* GetHead() const { return m_head; }
+ bool IsEmpty() const { return (m_size == 0); }
+ size_t GetSize() const { return m_size; }
+ const T& GetData() const { return m_head->GetData(); }
+ T& GetData() { return m_head->GetData(); }
+ bool Delete();
+ bool Delete(CircularListElement<T>* element);
+ CircularListElement<T>* Add(const T* data = 0);
+ CircularListElement<T>* Add(const T& data);
+ bool Next();
+ bool Prev();
+ void Clear()
+ {
+ while (Delete())
+ ;
+ };
+ const CircularList& operator=(const CircularList& rhs);
+ //! Constructor
+ CircularList()
+ {
+ m_head = 0;
+ m_size = 0;
+ }
+ CircularList(const CircularList& rhs);
+ //! Destructor
+ ~CircularList(void) { Clear(); };
+private:
+ CircularListElement<T>* m_head; //!< a pointer to the head of the circular list
+ size_t m_size; //!< number of element in the circular list
+};
+}
+#include "vhacdCircularList.inl"
+#endif // VHACD_CIRCULAR_LIST_H \ No newline at end of file
diff --git a/thirdparty/vhacd/inc/vhacdCircularList.inl b/thirdparty/vhacd/inc/vhacdCircularList.inl
new file mode 100644
index 0000000000..2be5180524
--- /dev/null
+++ b/thirdparty/vhacd/inc/vhacdCircularList.inl
@@ -0,0 +1,161 @@
+#pragma once
+#ifndef HACD_CIRCULAR_LIST_INL
+#define HACD_CIRCULAR_LIST_INL
+namespace VHACD
+{
+ template < typename T >
+ inline bool CircularList<T>::Delete(CircularListElement<T> * element)
+ {
+ if (!element)
+ {
+ return false;
+ }
+ if (m_size > 1)
+ {
+ CircularListElement<T> * next = element->GetNext();
+ CircularListElement<T> * prev = element->GetPrev();
+ delete element;
+ m_size--;
+ if (element == m_head)
+ {
+ m_head = next;
+ }
+ next->GetPrev() = prev;
+ prev->GetNext() = next;
+ return true;
+ }
+ else if (m_size == 1)
+ {
+ delete m_head;
+ m_size--;
+ m_head = 0;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ template < typename T >
+ inline bool CircularList<T>::Delete()
+ {
+ if (m_size > 1)
+ {
+ CircularListElement<T> * next = m_head->GetNext();
+ CircularListElement<T> * prev = m_head->GetPrev();
+ delete m_head;
+ m_size--;
+ m_head = next;
+ next->GetPrev() = prev;
+ prev->GetNext() = next;
+ return true;
+ }
+ else if (m_size == 1)
+ {
+ delete m_head;
+ m_size--;
+ m_head = 0;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ template < typename T >
+ inline CircularListElement<T> * CircularList<T>::Add(const T * data)
+ {
+ if (m_size == 0)
+ {
+ if (data)
+ {
+ m_head = new CircularListElement<T>(*data);
+ }
+ else
+ {
+ m_head = new CircularListElement<T>();
+ }
+ m_head->GetNext() = m_head->GetPrev() = m_head;
+ }
+ else
+ {
+ CircularListElement<T> * next = m_head->GetNext();
+ CircularListElement<T> * element = m_head;
+ if (data)
+ {
+ m_head = new CircularListElement<T>(*data);
+ }
+ else
+ {
+ m_head = new CircularListElement<T>();
+ }
+ m_head->GetNext() = next;
+ m_head->GetPrev() = element;
+ element->GetNext() = m_head;
+ next->GetPrev() = m_head;
+ }
+ m_size++;
+ return m_head;
+ }
+ template < typename T >
+ inline CircularListElement<T> * CircularList<T>::Add(const T & data)
+ {
+ const T * pData = &data;
+ return Add(pData);
+ }
+ template < typename T >
+ inline bool CircularList<T>::Next()
+ {
+ if (m_size == 0)
+ {
+ return false;
+ }
+ m_head = m_head->GetNext();
+ return true;
+ }
+ template < typename T >
+ inline bool CircularList<T>::Prev()
+ {
+ if (m_size == 0)
+ {
+ return false;
+ }
+ m_head = m_head->GetPrev();
+ return true;
+ }
+ template < typename T >
+ inline CircularList<T>::CircularList(const CircularList& rhs)
+ {
+ if (rhs.m_size > 0)
+ {
+ CircularListElement<T> * current = rhs.m_head;
+ do
+ {
+ current = current->GetNext();
+ Add(current->GetData());
+ }
+ while ( current != rhs.m_head );
+ }
+ }
+ template < typename T >
+ inline const CircularList<T>& CircularList<T>::operator=(const CircularList& rhs)
+ {
+ if (&rhs != this)
+ {
+ Clear();
+ if (rhs.m_size > 0)
+ {
+ CircularListElement<T> * current = rhs.m_head;
+ do
+ {
+ current = current->GetNext();
+ Add(current->GetData());
+ }
+ while ( current != rhs.m_head );
+ }
+ }
+ return (*this);
+ }
+}
+#endif \ No newline at end of file
diff --git a/thirdparty/vhacd/inc/vhacdICHull.h b/thirdparty/vhacd/inc/vhacdICHull.h
new file mode 100644
index 0000000000..132bdcfb3e
--- /dev/null
+++ b/thirdparty/vhacd/inc/vhacdICHull.h
@@ -0,0 +1,98 @@
+/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
+ All rights reserved.
+
+
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+ 2. 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.
+
+ 3. The names of the contributors may not 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.
+ */
+#pragma once
+#ifndef VHACD_ICHULL_H
+#define VHACD_ICHULL_H
+#include "vhacdManifoldMesh.h"
+#include "vhacdVector.h"
+
+namespace VHACD {
+//! Incremental Convex Hull algorithm (cf. http://cs.smith.edu/~orourke/books/ftp.html ).
+enum ICHullError {
+ ICHullErrorOK = 0,
+ ICHullErrorCoplanarPoints,
+ ICHullErrorNoVolume,
+ ICHullErrorInconsistent,
+ ICHullErrorNotEnoughPoints
+};
+class ICHull {
+public:
+ static const double sc_eps;
+ //!
+ bool IsFlat() { return m_isFlat; }
+ //! Returns the computed mesh
+ TMMesh& GetMesh() { return m_mesh; }
+ //! Add one point to the convex-hull
+ bool AddPoint(const Vec3<double>& point) { return AddPoints(&point, 1); }
+ //! Add one point to the convex-hull
+ bool AddPoint(const Vec3<double>& point, int32_t id);
+ //! Add points to the convex-hull
+ bool AddPoints(const Vec3<double>* points, size_t nPoints);
+ //!
+ ICHullError Process();
+ //!
+ ICHullError Process(const uint32_t nPointsCH, const double minVolume = 0.0);
+ //!
+ bool IsInside(const Vec3<double>& pt0, const double eps = 0.0);
+ //!
+ const ICHull& operator=(ICHull& rhs);
+
+ //! Constructor
+ ICHull();
+ //! Destructor
+ ~ICHull(void){};
+
+private:
+ //! DoubleTriangle builds the initial double triangle. It first finds 3 noncollinear points and makes two faces out of them, in opposite order. It then finds a fourth point that is not coplanar with that face. The vertices are stored in the face structure in counterclockwise order so that the volume between the face and the point is negative. Lastly, the 3 newfaces to the fourth point are constructed and the data structures are cleaned up.
+ ICHullError DoubleTriangle();
+ //! MakeFace creates a new face structure from three vertices (in ccw order). It returns a pointer to the face.
+ CircularListElement<TMMTriangle>* MakeFace(CircularListElement<TMMVertex>* v0,
+ CircularListElement<TMMVertex>* v1,
+ CircularListElement<TMMVertex>* v2,
+ CircularListElement<TMMTriangle>* fold);
+ //!
+ CircularListElement<TMMTriangle>* MakeConeFace(CircularListElement<TMMEdge>* e, CircularListElement<TMMVertex>* v);
+ //!
+ bool ProcessPoint();
+ //!
+ bool ComputePointVolume(double& totalVolume, bool markVisibleFaces);
+ //!
+ bool FindMaxVolumePoint(const double minVolume = 0.0);
+ //!
+ bool CleanEdges();
+ //!
+ bool CleanVertices(uint32_t& addedPoints);
+ //!
+ bool CleanTriangles();
+ //!
+ bool CleanUp(uint32_t& addedPoints);
+ //!
+ bool MakeCCW(CircularListElement<TMMTriangle>* f,
+ CircularListElement<TMMEdge>* e,
+ CircularListElement<TMMVertex>* v);
+ void Clear();
+
+private:
+ static const int32_t sc_dummyIndex;
+ TMMesh m_mesh;
+ SArray<CircularListElement<TMMEdge>*> m_edgesToDelete;
+ SArray<CircularListElement<TMMEdge>*> m_edgesToUpdate;
+ SArray<CircularListElement<TMMTriangle>*> m_trianglesToDelete;
+ Vec3<double> m_normal;
+ bool m_isFlat;
+ ICHull(const ICHull& rhs);
+};
+}
+#endif // VHACD_ICHULL_H
diff --git a/thirdparty/vhacd/inc/vhacdManifoldMesh.h b/thirdparty/vhacd/inc/vhacdManifoldMesh.h
new file mode 100644
index 0000000000..a48f53c5c5
--- /dev/null
+++ b/thirdparty/vhacd/inc/vhacdManifoldMesh.h
@@ -0,0 +1,142 @@
+/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
+All rights reserved.
+
+
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+ 2. 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.
+
+ 3. The names of the contributors may not 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.
+*/
+#pragma once
+#ifndef VHACD_MANIFOLD_MESH_H
+#define VHACD_MANIFOLD_MESH_H
+#include "vhacdCircularList.h"
+#include "vhacdSArray.h"
+#include "vhacdVector.h"
+namespace VHACD {
+class TMMTriangle;
+class TMMEdge;
+class TMMesh;
+class ICHull;
+
+//! Vertex data structure used in a triangular manifold mesh (TMM).
+class TMMVertex {
+public:
+ void Initialize();
+ TMMVertex(void);
+ ~TMMVertex(void);
+
+private:
+ Vec3<double> m_pos;
+ int32_t m_name;
+ size_t m_id;
+ CircularListElement<TMMEdge>* m_duplicate; // pointer to incident cone edge (or NULL)
+ bool m_onHull;
+ bool m_tag;
+ TMMVertex(const TMMVertex& rhs);
+ friend class ICHull;
+ friend class TMMesh;
+ friend class TMMTriangle;
+ friend class TMMEdge;
+};
+
+//! Edge data structure used in a triangular manifold mesh (TMM).
+class TMMEdge {
+public:
+ void Initialize();
+ TMMEdge(void);
+ ~TMMEdge(void);
+
+private:
+ size_t m_id;
+ CircularListElement<TMMTriangle>* m_triangles[2];
+ CircularListElement<TMMVertex>* m_vertices[2];
+ CircularListElement<TMMTriangle>* m_newFace;
+ TMMEdge(const TMMEdge& rhs);
+ friend class ICHull;
+ friend class TMMTriangle;
+ friend class TMMVertex;
+ friend class TMMesh;
+};
+
+//! Triangle data structure used in a triangular manifold mesh (TMM).
+class TMMTriangle {
+public:
+ void Initialize();
+ TMMTriangle(void);
+ ~TMMTriangle(void);
+
+private:
+ size_t m_id;
+ CircularListElement<TMMEdge>* m_edges[3];
+ CircularListElement<TMMVertex>* m_vertices[3];
+ bool m_visible;
+
+ TMMTriangle(const TMMTriangle& rhs);
+ friend class ICHull;
+ friend class TMMesh;
+ friend class TMMVertex;
+ friend class TMMEdge;
+};
+//! triangular manifold mesh data structure.
+class TMMesh {
+public:
+ //! Returns the number of vertices>
+ inline size_t GetNVertices() const { return m_vertices.GetSize(); }
+ //! Returns the number of edges
+ inline size_t GetNEdges() const { return m_edges.GetSize(); }
+ //! Returns the number of triangles
+ inline size_t GetNTriangles() const { return m_triangles.GetSize(); }
+ //! Returns the vertices circular list
+ inline const CircularList<TMMVertex>& GetVertices() const { return m_vertices; }
+ //! Returns the edges circular list
+ inline const CircularList<TMMEdge>& GetEdges() const { return m_edges; }
+ //! Returns the triangles circular list
+ inline const CircularList<TMMTriangle>& GetTriangles() const { return m_triangles; }
+ //! Returns the vertices circular list
+ inline CircularList<TMMVertex>& GetVertices() { return m_vertices; }
+ //! Returns the edges circular list
+ inline CircularList<TMMEdge>& GetEdges() { return m_edges; }
+ //! Returns the triangles circular list
+ inline CircularList<TMMTriangle>& GetTriangles() { return m_triangles; }
+ //! Add vertex to the mesh
+ CircularListElement<TMMVertex>* AddVertex() { return m_vertices.Add(); }
+ //! Add vertex to the mesh
+ CircularListElement<TMMEdge>* AddEdge() { return m_edges.Add(); }
+ //! Add vertex to the mesh
+ CircularListElement<TMMTriangle>* AddTriangle() { return m_triangles.Add(); }
+ //! Print mesh information
+ void Print();
+ //!
+ void GetIFS(Vec3<double>* const points, Vec3<int32_t>* const triangles);
+ //!
+ void Clear();
+ //!
+ void Copy(TMMesh& mesh);
+ //!
+ bool CheckConsistancy();
+ //!
+ bool Normalize();
+ //!
+ bool Denormalize();
+ //! Constructor
+ TMMesh();
+ //! Destructor
+ virtual ~TMMesh(void);
+
+private:
+ CircularList<TMMVertex> m_vertices;
+ CircularList<TMMEdge> m_edges;
+ CircularList<TMMTriangle> m_triangles;
+
+ // not defined
+ TMMesh(const TMMesh& rhs);
+ friend class ICHull;
+};
+}
+#endif // VHACD_MANIFOLD_MESH_H \ No newline at end of file
diff --git a/thirdparty/vhacd/inc/vhacdMesh.h b/thirdparty/vhacd/inc/vhacdMesh.h
new file mode 100644
index 0000000000..a282e2b4fb
--- /dev/null
+++ b/thirdparty/vhacd/inc/vhacdMesh.h
@@ -0,0 +1,130 @@
+/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
+ All rights reserved.
+
+
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+ 2. 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.
+
+ 3. The names of the contributors may not 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.
+ */
+#pragma once
+#ifndef VHACD_MESH_H
+#define VHACD_MESH_H
+#include "vhacdSArray.h"
+#include "vhacdVector.h"
+
+#define VHACD_DEBUG_MESH
+
+namespace VHACD {
+enum AXIS {
+ AXIS_X = 0,
+ AXIS_Y = 1,
+ AXIS_Z = 2
+};
+struct Plane {
+ double m_a;
+ double m_b;
+ double m_c;
+ double m_d;
+ AXIS m_axis;
+ short m_index;
+};
+#ifdef VHACD_DEBUG_MESH
+struct Material {
+
+ Vec3<double> m_diffuseColor;
+ double m_ambientIntensity;
+ Vec3<double> m_specularColor;
+ Vec3<double> m_emissiveColor;
+ double m_shininess;
+ double m_transparency;
+ Material(void)
+ {
+ m_diffuseColor.X() = 0.5;
+ m_diffuseColor.Y() = 0.5;
+ m_diffuseColor.Z() = 0.5;
+ m_specularColor.X() = 0.5;
+ m_specularColor.Y() = 0.5;
+ m_specularColor.Z() = 0.5;
+ m_ambientIntensity = 0.4;
+ m_emissiveColor.X() = 0.0;
+ m_emissiveColor.Y() = 0.0;
+ m_emissiveColor.Z() = 0.0;
+ m_shininess = 0.4;
+ m_transparency = 0.0;
+ };
+};
+#endif // VHACD_DEBUG_MESH
+
+//! Triangular mesh data structure
+class Mesh {
+public:
+ void AddPoint(const Vec3<double>& pt) { m_points.PushBack(pt); };
+ void SetPoint(size_t index, const Vec3<double>& pt) { m_points[index] = pt; };
+ const Vec3<double>& GetPoint(size_t index) const { return m_points[index]; };
+ Vec3<double>& GetPoint(size_t index) { return m_points[index]; };
+ size_t GetNPoints() const { return m_points.Size(); };
+ double* GetPoints() { return (double*)m_points.Data(); } // ugly
+ const double* const GetPoints() const { return (double*)m_points.Data(); } // ugly
+ const Vec3<double>* const GetPointsBuffer() const { return m_points.Data(); } //
+ Vec3<double>* const GetPointsBuffer() { return m_points.Data(); } //
+ void AddTriangle(const Vec3<int32_t>& tri) { m_triangles.PushBack(tri); };
+ void SetTriangle(size_t index, const Vec3<int32_t>& tri) { m_triangles[index] = tri; };
+ const Vec3<int32_t>& GetTriangle(size_t index) const { return m_triangles[index]; };
+ Vec3<int32_t>& GetTriangle(size_t index) { return m_triangles[index]; };
+ size_t GetNTriangles() const { return m_triangles.Size(); };
+ int32_t* GetTriangles() { return (int32_t*)m_triangles.Data(); } // ugly
+ const int32_t* const GetTriangles() const { return (int32_t*)m_triangles.Data(); } // ugly
+ const Vec3<int32_t>* const GetTrianglesBuffer() const { return m_triangles.Data(); }
+ Vec3<int32_t>* const GetTrianglesBuffer() { return m_triangles.Data(); }
+ const Vec3<double>& GetCenter() const { return m_center; }
+ const Vec3<double>& GetMinBB() const { return m_minBB; }
+ const Vec3<double>& GetMaxBB() const { return m_maxBB; }
+ void ClearPoints() { m_points.Clear(); }
+ void ClearTriangles() { m_triangles.Clear(); }
+ void Clear()
+ {
+ ClearPoints();
+ ClearTriangles();
+ }
+ void ResizePoints(size_t nPts) { m_points.Resize(nPts); }
+ void ResizeTriangles(size_t nTri) { m_triangles.Resize(nTri); }
+ void CopyPoints(SArray<Vec3<double> >& points) const { points = m_points; }
+ double GetDiagBB() const { return m_diag; }
+ double ComputeVolume() const;
+ void ComputeConvexHull(const double* const pts,
+ const size_t nPts);
+ void Clip(const Plane& plane,
+ SArray<Vec3<double> >& positivePart,
+ SArray<Vec3<double> >& negativePart) const;
+ bool IsInside(const Vec3<double>& pt) const;
+ double ComputeDiagBB();
+ Vec3<double> &ComputeCenter(void);
+
+#ifdef VHACD_DEBUG_MESH
+ bool LoadOFF(const std::string& fileName, bool invert);
+ bool SaveVRML2(const std::string& fileName) const;
+ bool SaveVRML2(std::ofstream& fout, const Material& material) const;
+ bool SaveOFF(const std::string& fileName) const;
+#endif // VHACD_DEBUG_MESH
+
+ //! Constructor.
+ Mesh();
+ //! Destructor.
+ ~Mesh(void);
+
+private:
+ SArray<Vec3<double> > m_points;
+ SArray<Vec3<int32_t> > m_triangles;
+ Vec3<double> m_minBB;
+ Vec3<double> m_maxBB;
+ Vec3<double> m_center;
+ double m_diag;
+};
+}
+#endif \ No newline at end of file
diff --git a/thirdparty/vhacd/inc/vhacdMutex.h b/thirdparty/vhacd/inc/vhacdMutex.h
new file mode 100644
index 0000000000..6b09259200
--- /dev/null
+++ b/thirdparty/vhacd/inc/vhacdMutex.h
@@ -0,0 +1,148 @@
+/*!
+**
+** Copyright (c) 2009 by John W. Ratcliff mailto:jratcliffscarab@gmail.com
+**
+** Portions of this source has been released with the PhysXViewer application, as well as
+** Rocket, CreateDynamics, ODF, and as a number of sample code snippets.
+**
+** If you find this code useful or you are feeling particularily generous I would
+** ask that you please go to http://www.amillionpixels.us and make a donation
+** to Troy DeMolay.
+**
+** DeMolay is a youth group for young men between the ages of 12 and 21.
+** It teaches strong moral principles, as well as leadership skills and
+** public speaking. The donations page uses the 'pay for pixels' paradigm
+** where, in this case, a pixel is only a single penny. Donations can be
+** made for as small as $4 or as high as a $100 block. Each person who donates
+** will get a link to their own site as well as acknowledgement on the
+** donations blog located here http://www.amillionpixels.blogspot.com/
+**
+** If you wish to contact me you can use the following methods:
+**
+** Skype ID: jratcliff63367
+** Yahoo: jratcliff63367
+** AOL: jratcliff1961
+** email: jratcliffscarab@gmail.com
+**
+**
+** The MIT license:
+**
+** 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.
+
+*/
+
+#pragma once
+#ifndef VHACD_MUTEX_H
+#define VHACD_MUTEX_H
+
+#if defined(WIN32)
+
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x400
+#endif
+#include <windows.h>
+#pragma comment(lib, "winmm.lib")
+#endif
+
+#if defined(__linux__)
+//#include <sys/time.h>
+#include <errno.h>
+#include <time.h>
+#include <unistd.h>
+#define __stdcall
+#endif
+
+#if defined(__APPLE__) || defined(__linux__)
+#include <pthread.h>
+#endif
+
+#if defined(__APPLE__)
+#define PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE
+#endif
+
+#define VHACD_DEBUG
+
+//#define VHACD_NDEBUG
+#ifdef VHACD_NDEBUG
+#define VHACD_VERIFY(x) (x)
+#else
+#define VHACD_VERIFY(x) assert((x))
+#endif
+
+namespace VHACD {
+class Mutex {
+public:
+ Mutex(void)
+ {
+#if defined(WIN32) || defined(_XBOX)
+ InitializeCriticalSection(&m_mutex);
+#elif defined(__APPLE__) || defined(__linux__)
+ pthread_mutexattr_t mutexAttr; // Mutex Attribute
+ VHACD_VERIFY(pthread_mutexattr_init(&mutexAttr) == 0);
+ VHACD_VERIFY(pthread_mutexattr_settype(&mutexAttr, PTHREAD_MUTEX_RECURSIVE_NP) == 0);
+ VHACD_VERIFY(pthread_mutex_init(&m_mutex, &mutexAttr) == 0);
+ VHACD_VERIFY(pthread_mutexattr_destroy(&mutexAttr) == 0);
+#endif
+ }
+ ~Mutex(void)
+ {
+#if defined(WIN32) || defined(_XBOX)
+ DeleteCriticalSection(&m_mutex);
+#elif defined(__APPLE__) || defined(__linux__)
+ VHACD_VERIFY(pthread_mutex_destroy(&m_mutex) == 0);
+#endif
+ }
+ void Lock(void)
+ {
+#if defined(WIN32) || defined(_XBOX)
+ EnterCriticalSection(&m_mutex);
+#elif defined(__APPLE__) || defined(__linux__)
+ VHACD_VERIFY(pthread_mutex_lock(&m_mutex) == 0);
+#endif
+ }
+ bool TryLock(void)
+ {
+#if defined(WIN32) || defined(_XBOX)
+ bool bRet = false;
+ //assert(("TryEnterCriticalSection seems to not work on XP???", 0));
+ bRet = TryEnterCriticalSection(&m_mutex) ? true : false;
+ return bRet;
+#elif defined(__APPLE__) || defined(__linux__)
+ int32_t result = pthread_mutex_trylock(&m_mutex);
+ return (result == 0);
+#endif
+ }
+
+ void Unlock(void)
+ {
+#if defined(WIN32) || defined(_XBOX)
+ LeaveCriticalSection(&m_mutex);
+#elif defined(__APPLE__) || defined(__linux__)
+ VHACD_VERIFY(pthread_mutex_unlock(&m_mutex) == 0);
+#endif
+ }
+
+private:
+#if defined(WIN32) || defined(_XBOX)
+ CRITICAL_SECTION m_mutex;
+#elif defined(__APPLE__) || defined(__linux__)
+ pthread_mutex_t m_mutex;
+#endif
+};
+}
+#endif // VHACD_MUTEX_H
diff --git a/thirdparty/vhacd/inc/vhacdRaycastMesh.h b/thirdparty/vhacd/inc/vhacdRaycastMesh.h
new file mode 100644
index 0000000000..93bf299c07
--- /dev/null
+++ b/thirdparty/vhacd/inc/vhacdRaycastMesh.h
@@ -0,0 +1,39 @@
+#ifndef RAYCAST_MESH_H
+
+#define RAYCAST_MESH_H
+
+#include <stdint.h>
+
+namespace VHACD
+{
+
+ // Very simple brute force raycast against a triangle mesh. Tests every triangle; no hierachy.
+ // Does a deep copy, always does calculations with full double float precision
+ class RaycastMesh
+ {
+ public:
+ static RaycastMesh * createRaycastMesh(uint32_t vcount, // The number of vertices in the source triangle mesh
+ const double *vertices, // The array of vertex positions in the format x1,y1,z1..x2,y2,z2.. etc.
+ uint32_t tcount, // The number of triangles in the source triangle mesh
+ const uint32_t *indices); // The triangle indices in the format of i1,i2,i3 ... i4,i5,i6, ...
+
+ static RaycastMesh * createRaycastMesh(uint32_t vcount, // The number of vertices in the source triangle mesh
+ const float *vertices, // The array of vertex positions in the format x1,y1,z1..x2,y2,z2.. etc.
+ uint32_t tcount, // The number of triangles in the source triangle mesh
+ const uint32_t *indices); // The triangle indices in the format of i1,i2,i3 ... i4,i5,i6, ...
+
+
+ virtual bool raycast(const double *from, // The starting point of the raycast
+ const double *to, // The ending point of the raycast
+ const double *closestToPoint, // The point to match the nearest hit location (can just be the 'from' location of no specific point)
+ double *hitLocation, // The point where the ray hit nearest to the 'closestToPoint' location
+ double *hitDistance) = 0; // The distance the ray traveled to the hit location
+
+ virtual void release(void) = 0;
+ protected:
+ virtual ~RaycastMesh(void) { };
+ };
+
+} // end of VHACD namespace
+
+#endif
diff --git a/thirdparty/vhacd/inc/vhacdSArray.h b/thirdparty/vhacd/inc/vhacdSArray.h
new file mode 100644
index 0000000000..4d84d1ae26
--- /dev/null
+++ b/thirdparty/vhacd/inc/vhacdSArray.h
@@ -0,0 +1,158 @@
+/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
+ All rights reserved.
+
+
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+ 2. 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.
+
+ 3. The names of the contributors may not 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.
+ */
+#pragma once
+#ifndef VHACD_SARRAY_H
+#define VHACD_SARRAY_H
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define SARRAY_DEFAULT_MIN_SIZE 16
+
+namespace VHACD {
+//! SArray.
+template <typename T, size_t N = 64>
+class SArray {
+public:
+ T& operator[](size_t i)
+ {
+ T* const data = Data();
+ return data[i];
+ }
+ const T& operator[](size_t i) const
+ {
+ const T* const data = Data();
+ return data[i];
+ }
+ size_t Size() const
+ {
+ return m_size;
+ }
+ T* const Data()
+ {
+ return (m_maxSize == N) ? m_data0 : m_data;
+ }
+ const T* const Data() const
+ {
+ return (m_maxSize == N) ? m_data0 : m_data;
+ }
+ void Clear()
+ {
+ m_size = 0;
+ delete[] m_data;
+ m_data = 0;
+ m_maxSize = N;
+ }
+ void PopBack()
+ {
+ --m_size;
+ }
+ void Allocate(size_t size)
+ {
+ if (size > m_maxSize) {
+ T* temp = new T[size];
+ memcpy(temp, Data(), m_size * sizeof(T));
+ delete[] m_data;
+ m_data = temp;
+ m_maxSize = size;
+ }
+ }
+ void Resize(size_t size)
+ {
+ Allocate(size);
+ m_size = size;
+ }
+
+ void PushBack(const T& value)
+ {
+ if (m_size == m_maxSize) {
+ size_t maxSize = (m_maxSize << 1);
+ T* temp = new T[maxSize];
+ memcpy(temp, Data(), m_maxSize * sizeof(T));
+ delete[] m_data;
+ m_data = temp;
+ m_maxSize = maxSize;
+ }
+ T* const data = Data();
+ data[m_size++] = value;
+ }
+ bool Find(const T& value, size_t& pos)
+ {
+ T* const data = Data();
+ for (pos = 0; pos < m_size; ++pos)
+ if (value == data[pos])
+ return true;
+ return false;
+ }
+ bool Insert(const T& value)
+ {
+ size_t pos;
+ if (Find(value, pos))
+ return false;
+ PushBack(value);
+ return true;
+ }
+ bool Erase(const T& value)
+ {
+ size_t pos;
+ T* const data = Data();
+ if (Find(value, pos)) {
+ for (size_t j = pos + 1; j < m_size; ++j)
+ data[j - 1] = data[j];
+ --m_size;
+ return true;
+ }
+ return false;
+ }
+ void operator=(const SArray& rhs)
+ {
+ if (m_maxSize < rhs.m_size) {
+ delete[] m_data;
+ m_maxSize = rhs.m_maxSize;
+ m_data = new T[m_maxSize];
+ }
+ m_size = rhs.m_size;
+ memcpy(Data(), rhs.Data(), m_size * sizeof(T));
+ }
+ void Initialize()
+ {
+ m_data = 0;
+ m_size = 0;
+ m_maxSize = N;
+ }
+ SArray(const SArray& rhs)
+ {
+ m_data = 0;
+ m_size = 0;
+ m_maxSize = N;
+ *this = rhs;
+ }
+ SArray()
+ {
+ Initialize();
+ }
+ ~SArray()
+ {
+ delete[] m_data;
+ }
+
+private:
+ T m_data0[N];
+ T* m_data;
+ size_t m_size;
+ size_t m_maxSize;
+};
+}
+#endif \ No newline at end of file
diff --git a/thirdparty/vhacd/inc/vhacdTimer.h b/thirdparty/vhacd/inc/vhacdTimer.h
new file mode 100644
index 0000000000..ba0e2c3364
--- /dev/null
+++ b/thirdparty/vhacd/inc/vhacdTimer.h
@@ -0,0 +1,121 @@
+/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
+ All rights reserved.
+
+
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+ 2. 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.
+
+ 3. The names of the contributors may not 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.
+ */
+#pragma once
+#ifndef VHACD_TIMER_H
+#define VHACD_TIMER_H
+
+#ifdef _WIN32
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+#endif
+#include <windows.h>
+#elif __MACH__
+#include <mach/clock.h>
+#include <mach/mach.h>
+#else
+#include <sys/time.h>
+#include <time.h>
+#endif
+
+namespace VHACD {
+#ifdef _WIN32
+class Timer {
+public:
+ Timer(void)
+ {
+ m_start.QuadPart = 0;
+ m_stop.QuadPart = 0;
+ QueryPerformanceFrequency(&m_freq);
+ };
+ ~Timer(void){};
+ void Tic()
+ {
+ QueryPerformanceCounter(&m_start);
+ }
+ void Toc()
+ {
+ QueryPerformanceCounter(&m_stop);
+ }
+ double GetElapsedTime() // in ms
+ {
+ LARGE_INTEGER delta;
+ delta.QuadPart = m_stop.QuadPart - m_start.QuadPart;
+ return (1000.0 * delta.QuadPart) / (double)m_freq.QuadPart;
+ }
+
+private:
+ LARGE_INTEGER m_start;
+ LARGE_INTEGER m_stop;
+ LARGE_INTEGER m_freq;
+};
+
+#elif __MACH__
+class Timer {
+public:
+ Timer(void)
+ {
+ memset(this, 0, sizeof(Timer));
+ host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &m_cclock);
+ };
+ ~Timer(void)
+ {
+ mach_port_deallocate(mach_task_self(), m_cclock);
+ };
+ void Tic()
+ {
+ clock_get_time(m_cclock, &m_start);
+ }
+ void Toc()
+ {
+ clock_get_time(m_cclock, &m_stop);
+ }
+ double GetElapsedTime() // in ms
+ {
+ return 1000.0 * (m_stop.tv_sec - m_start.tv_sec + (1.0E-9) * (m_stop.tv_nsec - m_start.tv_nsec));
+ }
+
+private:
+ clock_serv_t m_cclock;
+ mach_timespec_t m_start;
+ mach_timespec_t m_stop;
+};
+#else
+class Timer {
+public:
+ Timer(void)
+ {
+ memset(this, 0, sizeof(Timer));
+ };
+ ~Timer(void){};
+ void Tic()
+ {
+ clock_gettime(CLOCK_REALTIME, &m_start);
+ }
+ void Toc()
+ {
+ clock_gettime(CLOCK_REALTIME, &m_stop);
+ }
+ double GetElapsedTime() // in ms
+ {
+ return 1000.0 * (m_stop.tv_sec - m_start.tv_sec + (1.0E-9) * (m_stop.tv_nsec - m_start.tv_nsec));
+ }
+
+private:
+ struct timespec m_start;
+ struct timespec m_stop;
+};
+#endif
+}
+#endif // VHACD_TIMER_H
diff --git a/thirdparty/vhacd/inc/vhacdVHACD.h b/thirdparty/vhacd/inc/vhacdVHACD.h
new file mode 100644
index 0000000000..d67b107642
--- /dev/null
+++ b/thirdparty/vhacd/inc/vhacdVHACD.h
@@ -0,0 +1,371 @@
+/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
+All rights reserved.
+
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. 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.
+
+3. The names of the contributors may not 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.
+*/
+#pragma once
+#ifndef VHACD_VHACD_H
+#define VHACD_VHACD_H
+
+#ifdef OPENCL_FOUND
+#ifdef __MACH__
+#include <OpenCL/cl.h>
+#else
+#include <CL/cl.h>
+#endif
+#endif //OPENCL_FOUND
+
+#include "vhacdMutex.h"
+#include "vhacdVolume.h"
+#include "vhacdRaycastMesh.h"
+#include <vector>
+
+#define USE_THREAD 1
+#define OCL_MIN_NUM_PRIMITIVES 4096
+#define CH_APP_MIN_NUM_PRIMITIVES 64000
+namespace VHACD {
+class VHACD : public IVHACD {
+public:
+ //! Constructor.
+ VHACD()
+ {
+#if USE_THREAD == 1 && _OPENMP
+ m_ompNumProcessors = 2 * omp_get_num_procs();
+ omp_set_num_threads(m_ompNumProcessors);
+#else //USE_THREAD == 1 && _OPENMP
+ m_ompNumProcessors = 1;
+#endif //USE_THREAD == 1 && _OPENMP
+#ifdef CL_VERSION_1_1
+ m_oclWorkGroupSize = 0;
+ m_oclDevice = 0;
+ m_oclQueue = 0;
+ m_oclKernelComputePartialVolumes = 0;
+ m_oclKernelComputeSum = 0;
+#endif //CL_VERSION_1_1
+ Init();
+ }
+ //! Destructor.
+ ~VHACD(void)
+ {
+ }
+ uint32_t GetNConvexHulls() const
+ {
+ return (uint32_t)m_convexHulls.Size();
+ }
+ void Cancel()
+ {
+ SetCancel(true);
+ }
+ void GetConvexHull(const uint32_t index, ConvexHull& ch) const
+ {
+ Mesh* mesh = m_convexHulls[index];
+ ch.m_nPoints = (uint32_t)mesh->GetNPoints();
+ ch.m_nTriangles = (uint32_t)mesh->GetNTriangles();
+ ch.m_points = mesh->GetPoints();
+ ch.m_triangles = (uint32_t *)mesh->GetTriangles();
+ ch.m_volume = mesh->ComputeVolume();
+ Vec3<double> &center = mesh->ComputeCenter();
+ ch.m_center[0] = center.X();
+ ch.m_center[1] = center.Y();
+ ch.m_center[2] = center.Z();
+ }
+ void Clean(void)
+ {
+ if (mRaycastMesh)
+ {
+ mRaycastMesh->release();
+ mRaycastMesh = nullptr;
+ }
+ delete m_volume;
+ delete m_pset;
+ size_t nCH = m_convexHulls.Size();
+ for (size_t p = 0; p < nCH; ++p) {
+ delete m_convexHulls[p];
+ }
+ m_convexHulls.Clear();
+ Init();
+ }
+ void Release(void)
+ {
+ delete this;
+ }
+ bool Compute(const float* const points,
+ const uint32_t nPoints,
+ const uint32_t* const triangles,
+ const uint32_t nTriangles,
+ const Parameters& params);
+ bool Compute(const double* const points,
+ const uint32_t nPoints,
+ const uint32_t* const triangles,
+ const uint32_t nTriangles,
+ const Parameters& params);
+ bool OCLInit(void* const oclDevice,
+ IUserLogger* const logger = 0);
+ bool OCLRelease(IUserLogger* const logger = 0);
+
+ virtual bool ComputeCenterOfMass(double centerOfMass[3]) const;
+
+private:
+ void SetCancel(bool cancel)
+ {
+ m_cancelMutex.Lock();
+ m_cancel = cancel;
+ m_cancelMutex.Unlock();
+ }
+ bool GetCancel()
+ {
+
+ m_cancelMutex.Lock();
+ bool cancel = m_cancel;
+ m_cancelMutex.Unlock();
+ return cancel;
+ }
+ void Update(const double stageProgress,
+ const double operationProgress,
+ const Parameters& params)
+ {
+ m_stageProgress = stageProgress;
+ m_operationProgress = operationProgress;
+ if (params.m_callback) {
+ params.m_callback->Update(m_overallProgress,
+ m_stageProgress,
+ m_operationProgress,
+ m_stage.c_str(),
+ m_operation.c_str());
+ }
+ }
+ void Init()
+ {
+ if (mRaycastMesh)
+ {
+ mRaycastMesh->release();
+ mRaycastMesh = nullptr;
+ }
+ memset(m_rot, 0, sizeof(double) * 9);
+ m_dim = 64;
+ m_volume = 0;
+ m_volumeCH0 = 0.0;
+ m_pset = 0;
+ m_overallProgress = 0.0;
+ m_stageProgress = 0.0;
+ m_operationProgress = 0.0;
+ m_stage = "";
+ m_operation = "";
+ m_barycenter[0] = m_barycenter[1] = m_barycenter[2] = 0.0;
+ m_rot[0][0] = m_rot[1][1] = m_rot[2][2] = 1.0;
+ SetCancel(false);
+ }
+ void ComputePrimitiveSet(const Parameters& params);
+ void ComputeACD(const Parameters& params);
+ void MergeConvexHulls(const Parameters& params);
+ void SimplifyConvexHull(Mesh* const ch, const size_t nvertices, const double minVolume);
+ void SimplifyConvexHulls(const Parameters& params);
+ void ComputeBestClippingPlane(const PrimitiveSet* inputPSet,
+ const double volume,
+ const SArray<Plane>& planes,
+ const Vec3<double>& preferredCuttingDirection,
+ const double w,
+ const double alpha,
+ const double beta,
+ const int32_t convexhullDownsampling,
+ const double progress0,
+ const double progress1,
+ Plane& bestPlane,
+ double& minConcavity,
+ const Parameters& params);
+ template <class T>
+ void AlignMesh(const T* const points,
+ const uint32_t stridePoints,
+ const uint32_t nPoints,
+ const int32_t* const triangles,
+ const uint32_t strideTriangles,
+ const uint32_t nTriangles,
+ const Parameters& params)
+ {
+ if (GetCancel() || !params.m_pca) {
+ return;
+ }
+ m_timer.Tic();
+
+ m_stage = "Align mesh";
+ m_operation = "Voxelization";
+
+ std::ostringstream msg;
+ if (params.m_logger) {
+ msg << "+ " << m_stage << std::endl;
+ params.m_logger->Log(msg.str().c_str());
+ }
+
+ Update(0.0, 0.0, params);
+ if (GetCancel()) {
+ return;
+ }
+ m_dim = (size_t)(pow((double)params.m_resolution, 1.0 / 3.0) + 0.5);
+ Volume volume;
+ volume.Voxelize(points, stridePoints, nPoints,
+ triangles, strideTriangles, nTriangles,
+ m_dim, m_barycenter, m_rot);
+ size_t n = volume.GetNPrimitivesOnSurf() + volume.GetNPrimitivesInsideSurf();
+ Update(50.0, 100.0, params);
+
+ if (params.m_logger) {
+ msg.str("");
+ msg << "\t dim = " << m_dim << "\t-> " << n << " voxels" << std::endl;
+ params.m_logger->Log(msg.str().c_str());
+ }
+ if (GetCancel()) {
+ return;
+ }
+ m_operation = "PCA";
+ Update(50.0, 0.0, params);
+ volume.AlignToPrincipalAxes(m_rot);
+ m_overallProgress = 1.0;
+ Update(100.0, 100.0, params);
+
+ m_timer.Toc();
+ if (params.m_logger) {
+ msg.str("");
+ msg << "\t time " << m_timer.GetElapsedTime() / 1000.0 << "s" << std::endl;
+ params.m_logger->Log(msg.str().c_str());
+ }
+ }
+ template <class T>
+ void VoxelizeMesh(const T* const points,
+ const uint32_t stridePoints,
+ const uint32_t nPoints,
+ const int32_t* const triangles,
+ const uint32_t strideTriangles,
+ const uint32_t nTriangles,
+ const Parameters& params)
+ {
+ if (GetCancel()) {
+ return;
+ }
+
+ m_timer.Tic();
+ m_stage = "Voxelization";
+
+ std::ostringstream msg;
+ if (params.m_logger) {
+ msg << "+ " << m_stage << std::endl;
+ params.m_logger->Log(msg.str().c_str());
+ }
+
+ delete m_volume;
+ m_volume = 0;
+ int32_t iteration = 0;
+ const int32_t maxIteration = 5;
+ double progress = 0.0;
+ while (iteration++ < maxIteration && !m_cancel) {
+ msg.str("");
+ msg << "Iteration " << iteration;
+ m_operation = msg.str();
+
+ progress = iteration * 100.0 / maxIteration;
+ Update(progress, 0.0, params);
+
+ m_volume = new Volume;
+ m_volume->Voxelize(points, stridePoints, nPoints,
+ triangles, strideTriangles, nTriangles,
+ m_dim, m_barycenter, m_rot);
+
+ Update(progress, 100.0, params);
+
+ size_t n = m_volume->GetNPrimitivesOnSurf() + m_volume->GetNPrimitivesInsideSurf();
+ if (params.m_logger) {
+ msg.str("");
+ msg << "\t dim = " << m_dim << "\t-> " << n << " voxels" << std::endl;
+ params.m_logger->Log(msg.str().c_str());
+ }
+
+ double a = pow((double)(params.m_resolution) / n, 0.33);
+ size_t dim_next = (size_t)(m_dim * a + 0.5);
+ if (n < params.m_resolution && iteration < maxIteration && m_volume->GetNPrimitivesOnSurf() < params.m_resolution / 8 && m_dim != dim_next) {
+ delete m_volume;
+ m_volume = 0;
+ m_dim = dim_next;
+ }
+ else {
+ break;
+ }
+ }
+ m_overallProgress = 10.0;
+ Update(100.0, 100.0, params);
+
+ m_timer.Toc();
+ if (params.m_logger) {
+ msg.str("");
+ msg << "\t time " << m_timer.GetElapsedTime() / 1000.0 << "s" << std::endl;
+ params.m_logger->Log(msg.str().c_str());
+ }
+ }
+ template <class T>
+ bool ComputeACD(const T* const points,
+ const uint32_t nPoints,
+ const uint32_t* const triangles,
+ const uint32_t nTriangles,
+ const Parameters& params)
+ {
+ Init();
+ if (params.m_projectHullVertices)
+ {
+ mRaycastMesh = RaycastMesh::createRaycastMesh(nPoints, points, nTriangles, (const uint32_t *)triangles);
+ }
+ if (params.m_oclAcceleration) {
+ // build kernels
+ }
+ AlignMesh(points, 3, nPoints, (int32_t *)triangles, 3, nTriangles, params);
+ VoxelizeMesh(points, 3, nPoints, (int32_t *)triangles, 3, nTriangles, params);
+ ComputePrimitiveSet(params);
+ ComputeACD(params);
+ MergeConvexHulls(params);
+ SimplifyConvexHulls(params);
+ if (params.m_oclAcceleration) {
+ // Release kernels
+ }
+ if (GetCancel()) {
+ Clean();
+ return false;
+ }
+ return true;
+ }
+
+private:
+ RaycastMesh *mRaycastMesh{ nullptr };
+ SArray<Mesh*> m_convexHulls;
+ std::string m_stage;
+ std::string m_operation;
+ double m_overallProgress;
+ double m_stageProgress;
+ double m_operationProgress;
+ double m_rot[3][3];
+ double m_volumeCH0;
+ Vec3<double> m_barycenter;
+ Timer m_timer;
+ size_t m_dim;
+ Volume* m_volume;
+ PrimitiveSet* m_pset;
+ Mutex m_cancelMutex;
+ bool m_cancel;
+ int32_t m_ompNumProcessors;
+#ifdef CL_VERSION_1_1
+ cl_device_id* m_oclDevice;
+ cl_context m_oclContext;
+ cl_program m_oclProgram;
+ cl_command_queue* m_oclQueue;
+ cl_kernel* m_oclKernelComputePartialVolumes;
+ cl_kernel* m_oclKernelComputeSum;
+ size_t m_oclWorkGroupSize;
+#endif //CL_VERSION_1_1
+};
+}
+#endif // VHACD_VHACD_H
diff --git a/thirdparty/vhacd/inc/vhacdVector.h b/thirdparty/vhacd/inc/vhacdVector.h
new file mode 100644
index 0000000000..efcfcf6ad7
--- /dev/null
+++ b/thirdparty/vhacd/inc/vhacdVector.h
@@ -0,0 +1,168 @@
+/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
+ All rights reserved.
+
+
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+ 2. 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.
+
+ 3. The names of the contributors may not 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.
+ */
+#pragma once
+#ifndef VHACD_VECTOR_H
+#define VHACD_VECTOR_H
+#include <iostream>
+#include <math.h>
+
+namespace VHACD {
+//! Vector dim 3.
+template <typename T>
+class Vec3 {
+public:
+ T& operator[](size_t i) { return m_data[i]; }
+ const T& operator[](size_t i) const { return m_data[i]; }
+ T& X();
+ T& Y();
+ T& Z();
+ const T& X() const;
+ const T& Y() const;
+ const T& Z() const;
+ void Normalize();
+ T GetNorm() const;
+ void operator=(const Vec3& rhs);
+ void operator+=(const Vec3& rhs);
+ void operator-=(const Vec3& rhs);
+ void operator-=(T a);
+ void operator+=(T a);
+ void operator/=(T a);
+ void operator*=(T a);
+ Vec3 operator^(const Vec3& rhs) const;
+ T operator*(const Vec3& rhs) const;
+ Vec3 operator+(const Vec3& rhs) const;
+ Vec3 operator-(const Vec3& rhs) const;
+ Vec3 operator-() const;
+ Vec3 operator*(T rhs) const;
+ Vec3 operator/(T rhs) const;
+ bool operator<(const Vec3& rhs) const;
+ bool operator>(const Vec3& rhs) const;
+ Vec3();
+ Vec3(T a);
+ Vec3(T x, T y, T z);
+ Vec3(const Vec3& rhs);
+ /*virtual*/ ~Vec3(void);
+
+ // Compute the center of this bounding box and return the diagonal length
+ T GetCenter(const Vec3 &bmin, const Vec3 &bmax)
+ {
+ X() = (bmin.X() + bmax.X())*0.5;
+ Y() = (bmin.Y() + bmax.Y())*0.5;
+ Z() = (bmin.Z() + bmax.Z())*0.5;
+ T dx = bmax.X() - bmin.X();
+ T dy = bmax.Y() - bmin.Y();
+ T dz = bmax.Z() - bmin.Z();
+ T diagonal = T(sqrt(dx*dx + dy*dy + dz*dz));
+ return diagonal;
+ }
+
+ // Update the min/max values relative to this point
+ void UpdateMinMax(Vec3 &bmin,Vec3 &bmax) const
+ {
+ if (X() < bmin.X())
+ {
+ bmin.X() = X();
+ }
+ if (Y() < bmin.Y())
+ {
+ bmin.Y() = Y();
+ }
+ if (Z() < bmin.Z())
+ {
+ bmin.Z() = Z();
+ }
+ if (X() > bmax.X())
+ {
+ bmax.X() = X();
+ }
+ if (X() > bmax.X())
+ {
+ bmax.X() = X();
+ }
+ if (Y() > bmax.Y())
+ {
+ bmax.Y() = Y();
+ }
+ if (Z() > bmax.Z())
+ {
+ bmax.Z() = Z();
+ }
+ }
+
+ // Returns the squared distance between these two points
+ T GetDistanceSquared(const Vec3 &p) const
+ {
+ T dx = X() - p.X();
+ T dy = Y() - p.Y();
+ T dz = Z() - p.Z();
+ return dx*dx + dy*dy + dz*dz;
+ }
+
+ T GetDistance(const Vec3 &p) const
+ {
+ return sqrt(GetDistanceSquared(p));
+ }
+
+ // Returns the raw vector data as a pointer
+ T* GetData(void)
+ {
+ return m_data;
+ }
+private:
+ T m_data[3];
+};
+//! Vector dim 2.
+template <typename T>
+class Vec2 {
+public:
+ T& operator[](size_t i) { return m_data[i]; }
+ const T& operator[](size_t i) const { return m_data[i]; }
+ T& X();
+ T& Y();
+ const T& X() const;
+ const T& Y() const;
+ void Normalize();
+ T GetNorm() const;
+ void operator=(const Vec2& rhs);
+ void operator+=(const Vec2& rhs);
+ void operator-=(const Vec2& rhs);
+ void operator-=(T a);
+ void operator+=(T a);
+ void operator/=(T a);
+ void operator*=(T a);
+ T operator^(const Vec2& rhs) const;
+ T operator*(const Vec2& rhs) const;
+ Vec2 operator+(const Vec2& rhs) const;
+ Vec2 operator-(const Vec2& rhs) const;
+ Vec2 operator-() const;
+ Vec2 operator*(T rhs) const;
+ Vec2 operator/(T rhs) const;
+ Vec2();
+ Vec2(T a);
+ Vec2(T x, T y);
+ Vec2(const Vec2& rhs);
+ /*virtual*/ ~Vec2(void);
+
+private:
+ T m_data[2];
+};
+
+template <typename T>
+const bool Colinear(const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c);
+template <typename T>
+const T ComputeVolume4(const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c, const Vec3<T>& d);
+}
+#include "vhacdVector.inl" // template implementation
+#endif \ No newline at end of file
diff --git a/thirdparty/vhacd/inc/vhacdVector.inl b/thirdparty/vhacd/inc/vhacdVector.inl
new file mode 100644
index 0000000000..223c2ef173
--- /dev/null
+++ b/thirdparty/vhacd/inc/vhacdVector.inl
@@ -0,0 +1,362 @@
+#pragma once
+#ifndef VHACD_VECTOR_INL
+#define VHACD_VECTOR_INL
+namespace VHACD
+{
+ template <typename T>
+ inline Vec3<T> operator*(T lhs, const Vec3<T> & rhs)
+ {
+ return Vec3<T>(lhs * rhs.X(), lhs * rhs.Y(), lhs * rhs.Z());
+ }
+ template <typename T>
+ inline T & Vec3<T>::X()
+ {
+ return m_data[0];
+ }
+ template <typename T>
+ inline T & Vec3<T>::Y()
+ {
+ return m_data[1];
+ }
+ template <typename T>
+ inline T & Vec3<T>::Z()
+ {
+ return m_data[2];
+ }
+ template <typename T>
+ inline const T & Vec3<T>::X() const
+ {
+ return m_data[0];
+ }
+ template <typename T>
+ inline const T & Vec3<T>::Y() const
+ {
+ return m_data[1];
+ }
+ template <typename T>
+ inline const T & Vec3<T>::Z() const
+ {
+ return m_data[2];
+ }
+ template <typename T>
+ inline void Vec3<T>::Normalize()
+ {
+ T n = sqrt(m_data[0]*m_data[0]+m_data[1]*m_data[1]+m_data[2]*m_data[2]);
+ if (n != 0.0) (*this) /= n;
+ }
+ template <typename T>
+ inline T Vec3<T>::GetNorm() const
+ {
+ return sqrt(m_data[0]*m_data[0]+m_data[1]*m_data[1]+m_data[2]*m_data[2]);
+ }
+ template <typename T>
+ inline void Vec3<T>::operator= (const Vec3 & rhs)
+ {
+ this->m_data[0] = rhs.m_data[0];
+ this->m_data[1] = rhs.m_data[1];
+ this->m_data[2] = rhs.m_data[2];
+ }
+ template <typename T>
+ inline void Vec3<T>::operator+=(const Vec3 & rhs)
+ {
+ this->m_data[0] += rhs.m_data[0];
+ this->m_data[1] += rhs.m_data[1];
+ this->m_data[2] += rhs.m_data[2];
+ }
+ template <typename T>
+ inline void Vec3<T>::operator-=(const Vec3 & rhs)
+ {
+ this->m_data[0] -= rhs.m_data[0];
+ this->m_data[1] -= rhs.m_data[1];
+ this->m_data[2] -= rhs.m_data[2];
+ }
+ template <typename T>
+ inline void Vec3<T>::operator-=(T a)
+ {
+ this->m_data[0] -= a;
+ this->m_data[1] -= a;
+ this->m_data[2] -= a;
+ }
+ template <typename T>
+ inline void Vec3<T>::operator+=(T a)
+ {
+ this->m_data[0] += a;
+ this->m_data[1] += a;
+ this->m_data[2] += a;
+ }
+ template <typename T>
+ inline void Vec3<T>::operator/=(T a)
+ {
+ this->m_data[0] /= a;
+ this->m_data[1] /= a;
+ this->m_data[2] /= a;
+ }
+ template <typename T>
+ inline void Vec3<T>::operator*=(T a)
+ {
+ this->m_data[0] *= a;
+ this->m_data[1] *= a;
+ this->m_data[2] *= a;
+ }
+ template <typename T>
+ inline Vec3<T> Vec3<T>::operator^ (const Vec3<T> & rhs) const
+ {
+ return Vec3<T>(m_data[1] * rhs.m_data[2] - m_data[2] * rhs.m_data[1],
+ m_data[2] * rhs.m_data[0] - m_data[0] * rhs.m_data[2],
+ m_data[0] * rhs.m_data[1] - m_data[1] * rhs.m_data[0]);
+ }
+ template <typename T>
+ inline T Vec3<T>::operator*(const Vec3<T> & rhs) const
+ {
+ return (m_data[0] * rhs.m_data[0] + m_data[1] * rhs.m_data[1] + m_data[2] * rhs.m_data[2]);
+ }
+ template <typename T>
+ inline Vec3<T> Vec3<T>::operator+(const Vec3<T> & rhs) const
+ {
+ return Vec3<T>(m_data[0] + rhs.m_data[0],m_data[1] + rhs.m_data[1],m_data[2] + rhs.m_data[2]);
+ }
+ template <typename T>
+ inline Vec3<T> Vec3<T>::operator-(const Vec3<T> & rhs) const
+ {
+ return Vec3<T>(m_data[0] - rhs.m_data[0],m_data[1] - rhs.m_data[1],m_data[2] - rhs.m_data[2]) ;
+ }
+ template <typename T>
+ inline Vec3<T> Vec3<T>::operator-() const
+ {
+ return Vec3<T>(-m_data[0],-m_data[1],-m_data[2]) ;
+ }
+
+ template <typename T>
+ inline Vec3<T> Vec3<T>::operator*(T rhs) const
+ {
+ return Vec3<T>(rhs * this->m_data[0], rhs * this->m_data[1], rhs * this->m_data[2]);
+ }
+ template <typename T>
+ inline Vec3<T> Vec3<T>::operator/ (T rhs) const
+ {
+ return Vec3<T>(m_data[0] / rhs, m_data[1] / rhs, m_data[2] / rhs);
+ }
+ template <typename T>
+ inline Vec3<T>::Vec3(T a)
+ {
+ m_data[0] = m_data[1] = m_data[2] = a;
+ }
+ template <typename T>
+ inline Vec3<T>::Vec3(T x, T y, T z)
+ {
+ m_data[0] = x;
+ m_data[1] = y;
+ m_data[2] = z;
+ }
+ template <typename T>
+ inline Vec3<T>::Vec3(const Vec3 & rhs)
+ {
+ m_data[0] = rhs.m_data[0];
+ m_data[1] = rhs.m_data[1];
+ m_data[2] = rhs.m_data[2];
+ }
+ template <typename T>
+ inline Vec3<T>::~Vec3(void){};
+
+ template <typename T>
+ inline Vec3<T>::Vec3() {}
+
+ template<typename T>
+ inline const bool Colinear(const Vec3<T> & a, const Vec3<T> & b, const Vec3<T> & c)
+ {
+ return ((c.Z() - a.Z()) * (b.Y() - a.Y()) - (b.Z() - a.Z()) * (c.Y() - a.Y()) == 0.0 /*EPS*/) &&
+ ((b.Z() - a.Z()) * (c.X() - a.X()) - (b.X() - a.X()) * (c.Z() - a.Z()) == 0.0 /*EPS*/) &&
+ ((b.X() - a.X()) * (c.Y() - a.Y()) - (b.Y() - a.Y()) * (c.X() - a.X()) == 0.0 /*EPS*/);
+ }
+
+ template<typename T>
+ inline const T ComputeVolume4(const Vec3<T> & a, const Vec3<T> & b, const Vec3<T> & c, const Vec3<T> & d)
+ {
+ return (a-d) * ((b-d) ^ (c-d));
+ }
+
+ template <typename T>
+ inline bool Vec3<T>::operator<(const Vec3 & rhs) const
+ {
+ if (X() == rhs[0])
+ {
+ if (Y() == rhs[1])
+ {
+ return (Z()<rhs[2]);
+ }
+ return (Y()<rhs[1]);
+ }
+ return (X()<rhs[0]);
+ }
+ template <typename T>
+ inline bool Vec3<T>::operator>(const Vec3 & rhs) const
+ {
+ if (X() == rhs[0])
+ {
+ if (Y() == rhs[1])
+ {
+ return (Z()>rhs[2]);
+ }
+ return (Y()>rhs[1]);
+ }
+ return (X()>rhs[0]);
+ }
+ template <typename T>
+ inline Vec2<T> operator*(T lhs, const Vec2<T> & rhs)
+ {
+ return Vec2<T>(lhs * rhs.X(), lhs * rhs.Y());
+ }
+ template <typename T>
+ inline T & Vec2<T>::X()
+ {
+ return m_data[0];
+ }
+ template <typename T>
+ inline T & Vec2<T>::Y()
+ {
+ return m_data[1];
+ }
+ template <typename T>
+ inline const T & Vec2<T>::X() const
+ {
+ return m_data[0];
+ }
+ template <typename T>
+ inline const T & Vec2<T>::Y() const
+ {
+ return m_data[1];
+ }
+ template <typename T>
+ inline void Vec2<T>::Normalize()
+ {
+ T n = sqrt(m_data[0]*m_data[0]+m_data[1]*m_data[1]);
+ if (n != 0.0) (*this) /= n;
+ }
+ template <typename T>
+ inline T Vec2<T>::GetNorm() const
+ {
+ return sqrt(m_data[0]*m_data[0]+m_data[1]*m_data[1]);
+ }
+ template <typename T>
+ inline void Vec2<T>::operator= (const Vec2 & rhs)
+ {
+ this->m_data[0] = rhs.m_data[0];
+ this->m_data[1] = rhs.m_data[1];
+ }
+ template <typename T>
+ inline void Vec2<T>::operator+=(const Vec2 & rhs)
+ {
+ this->m_data[0] += rhs.m_data[0];
+ this->m_data[1] += rhs.m_data[1];
+ }
+ template <typename T>
+ inline void Vec2<T>::operator-=(const Vec2 & rhs)
+ {
+ this->m_data[0] -= rhs.m_data[0];
+ this->m_data[1] -= rhs.m_data[1];
+ }
+ template <typename T>
+ inline void Vec2<T>::operator-=(T a)
+ {
+ this->m_data[0] -= a;
+ this->m_data[1] -= a;
+ }
+ template <typename T>
+ inline void Vec2<T>::operator+=(T a)
+ {
+ this->m_data[0] += a;
+ this->m_data[1] += a;
+ }
+ template <typename T>
+ inline void Vec2<T>::operator/=(T a)
+ {
+ this->m_data[0] /= a;
+ this->m_data[1] /= a;
+ }
+ template <typename T>
+ inline void Vec2<T>::operator*=(T a)
+ {
+ this->m_data[0] *= a;
+ this->m_data[1] *= a;
+ }
+ template <typename T>
+ inline T Vec2<T>::operator^ (const Vec2<T> & rhs) const
+ {
+ return m_data[0] * rhs.m_data[1] - m_data[1] * rhs.m_data[0];
+ }
+ template <typename T>
+ inline T Vec2<T>::operator*(const Vec2<T> & rhs) const
+ {
+ return (m_data[0] * rhs.m_data[0] + m_data[1] * rhs.m_data[1]);
+ }
+ template <typename T>
+ inline Vec2<T> Vec2<T>::operator+(const Vec2<T> & rhs) const
+ {
+ return Vec2<T>(m_data[0] + rhs.m_data[0],m_data[1] + rhs.m_data[1]);
+ }
+ template <typename T>
+ inline Vec2<T> Vec2<T>::operator-(const Vec2<T> & rhs) const
+ {
+ return Vec2<T>(m_data[0] - rhs.m_data[0],m_data[1] - rhs.m_data[1]);
+ }
+ template <typename T>
+ inline Vec2<T> Vec2<T>::operator-() const
+ {
+ return Vec2<T>(-m_data[0],-m_data[1]) ;
+ }
+
+ template <typename T>
+ inline Vec2<T> Vec2<T>::operator*(T rhs) const
+ {
+ return Vec2<T>(rhs * this->m_data[0], rhs * this->m_data[1]);
+ }
+ template <typename T>
+ inline Vec2<T> Vec2<T>::operator/ (T rhs) const
+ {
+ return Vec2<T>(m_data[0] / rhs, m_data[1] / rhs);
+ }
+ template <typename T>
+ inline Vec2<T>::Vec2(T a)
+ {
+ m_data[0] = m_data[1] = a;
+ }
+ template <typename T>
+ inline Vec2<T>::Vec2(T x, T y)
+ {
+ m_data[0] = x;
+ m_data[1] = y;
+ }
+ template <typename T>
+ inline Vec2<T>::Vec2(const Vec2 & rhs)
+ {
+ m_data[0] = rhs.m_data[0];
+ m_data[1] = rhs.m_data[1];
+ }
+ template <typename T>
+ inline Vec2<T>::~Vec2(void){};
+
+ template <typename T>
+ inline Vec2<T>::Vec2() {}
+
+ /*
+ InsideTriangle decides if a point P is Inside of the triangle
+ defined by A, B, C.
+ */
+ template<typename T>
+ inline const bool InsideTriangle(const Vec2<T> & a, const Vec2<T> & b, const Vec2<T> & c, const Vec2<T> & p)
+ {
+ T ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy;
+ T cCROSSap, bCROSScp, aCROSSbp;
+ ax = c.X() - b.X(); ay = c.Y() - b.Y();
+ bx = a.X() - c.X(); by = a.Y() - c.Y();
+ cx = b.X() - a.X(); cy = b.Y() - a.Y();
+ apx= p.X() - a.X(); apy= p.Y() - a.Y();
+ bpx= p.X() - b.X(); bpy= p.Y() - b.Y();
+ cpx= p.X() - c.X(); cpy= p.Y() - c.Y();
+ aCROSSbp = ax*bpy - ay*bpx;
+ cCROSSap = cx*apy - cy*apx;
+ bCROSScp = bx*cpy - by*cpx;
+ return ((aCROSSbp >= 0.0) && (bCROSScp >= 0.0) && (cCROSSap >= 0.0));
+ }
+}
+#endif //VHACD_VECTOR_INL \ No newline at end of file
diff --git a/thirdparty/vhacd/inc/vhacdVolume.h b/thirdparty/vhacd/inc/vhacdVolume.h
new file mode 100644
index 0000000000..8c47fa1e2c
--- /dev/null
+++ b/thirdparty/vhacd/inc/vhacdVolume.h
@@ -0,0 +1,430 @@
+/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
+ All rights reserved.
+
+
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+ 2. 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.
+
+ 3. The names of the contributors may not 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.
+ */
+#pragma once
+#ifndef VHACD_VOLUME_H
+#define VHACD_VOLUME_H
+#include "vhacdMesh.h"
+#include "vhacdVector.h"
+#include <assert.h>
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable:4456 4701)
+#endif
+
+namespace VHACD {
+
+enum VOXEL_VALUE {
+ PRIMITIVE_UNDEFINED = 0,
+ PRIMITIVE_OUTSIDE_SURFACE = 1,
+ PRIMITIVE_INSIDE_SURFACE = 2,
+ PRIMITIVE_ON_SURFACE = 3
+};
+
+struct Voxel {
+public:
+ short m_coord[3];
+ short m_data;
+};
+
+class PrimitiveSet {
+public:
+ virtual ~PrimitiveSet(){};
+ virtual PrimitiveSet* Create() const = 0;
+ virtual const size_t GetNPrimitives() const = 0;
+ virtual const size_t GetNPrimitivesOnSurf() const = 0;
+ virtual const size_t GetNPrimitivesInsideSurf() const = 0;
+ virtual const double GetEigenValue(AXIS axis) const = 0;
+ virtual const double ComputeMaxVolumeError() const = 0;
+ virtual const double ComputeVolume() const = 0;
+ virtual void Clip(const Plane& plane, PrimitiveSet* const positivePart,
+ PrimitiveSet* const negativePart) const = 0;
+ virtual void Intersect(const Plane& plane, SArray<Vec3<double> >* const positivePts,
+ SArray<Vec3<double> >* const negativePts, const size_t sampling) const = 0;
+ virtual void ComputeExteriorPoints(const Plane& plane, const Mesh& mesh,
+ SArray<Vec3<double> >* const exteriorPts) const = 0;
+ virtual void ComputeClippedVolumes(const Plane& plane, double& positiveVolume,
+ double& negativeVolume) const = 0;
+ virtual void SelectOnSurface(PrimitiveSet* const onSurfP) const = 0;
+ virtual void ComputeConvexHull(Mesh& meshCH, const size_t sampling = 1) const = 0;
+ virtual void ComputeBB() = 0;
+ virtual void ComputePrincipalAxes() = 0;
+ virtual void AlignToPrincipalAxes() = 0;
+ virtual void RevertAlignToPrincipalAxes() = 0;
+ virtual void Convert(Mesh& mesh, const VOXEL_VALUE value) const = 0;
+ const Mesh& GetConvexHull() const { return m_convexHull; };
+ Mesh& GetConvexHull() { return m_convexHull; };
+private:
+ Mesh m_convexHull;
+};
+
+//!
+class VoxelSet : public PrimitiveSet {
+ friend class Volume;
+
+public:
+ //! Destructor.
+ ~VoxelSet(void);
+ //! Constructor.
+ VoxelSet();
+
+ const size_t GetNPrimitives() const { return m_voxels.Size(); }
+ const size_t GetNPrimitivesOnSurf() const { return m_numVoxelsOnSurface; }
+ const size_t GetNPrimitivesInsideSurf() const { return m_numVoxelsInsideSurface; }
+ const double GetEigenValue(AXIS axis) const { return m_D[axis][axis]; }
+ const double ComputeVolume() const { return m_unitVolume * m_voxels.Size(); }
+ const double ComputeMaxVolumeError() const { return m_unitVolume * m_numVoxelsOnSurface; }
+ const Vec3<short>& GetMinBBVoxels() const { return m_minBBVoxels; }
+ const Vec3<short>& GetMaxBBVoxels() const { return m_maxBBVoxels; }
+ const Vec3<double>& GetMinBB() const { return m_minBB; }
+ const double& GetScale() const { return m_scale; }
+ const double& GetUnitVolume() const { return m_unitVolume; }
+ Vec3<double> GetPoint(Vec3<short> voxel) const
+ {
+ return Vec3<double>(voxel[0] * m_scale + m_minBB[0],
+ voxel[1] * m_scale + m_minBB[1],
+ voxel[2] * m_scale + m_minBB[2]);
+ }
+ Vec3<double> GetPoint(const Voxel& voxel) const
+ {
+ return Vec3<double>(voxel.m_coord[0] * m_scale + m_minBB[0],
+ voxel.m_coord[1] * m_scale + m_minBB[1],
+ voxel.m_coord[2] * m_scale + m_minBB[2]);
+ }
+ Vec3<double> GetPoint(Vec3<double> voxel) const
+ {
+ return Vec3<double>(voxel[0] * m_scale + m_minBB[0],
+ voxel[1] * m_scale + m_minBB[1],
+ voxel[2] * m_scale + m_minBB[2]);
+ }
+ void GetPoints(const Voxel& voxel, Vec3<double>* const pts) const;
+ void ComputeConvexHull(Mesh& meshCH, const size_t sampling = 1) const;
+ void Clip(const Plane& plane, PrimitiveSet* const positivePart, PrimitiveSet* const negativePart) const;
+ void Intersect(const Plane& plane, SArray<Vec3<double> >* const positivePts,
+ SArray<Vec3<double> >* const negativePts, const size_t sampling) const;
+ void ComputeExteriorPoints(const Plane& plane, const Mesh& mesh,
+ SArray<Vec3<double> >* const exteriorPts) const;
+ void ComputeClippedVolumes(const Plane& plane, double& positiveVolume, double& negativeVolume) const;
+ void SelectOnSurface(PrimitiveSet* const onSurfP) const;
+ void ComputeBB();
+ void Convert(Mesh& mesh, const VOXEL_VALUE value) const;
+ void ComputePrincipalAxes();
+ PrimitiveSet* Create() const
+ {
+ return new VoxelSet();
+ }
+ void AlignToPrincipalAxes(){};
+ void RevertAlignToPrincipalAxes(){};
+ Voxel* const GetVoxels() { return m_voxels.Data(); }
+ const Voxel* const GetVoxels() const { return m_voxels.Data(); }
+
+private:
+ size_t m_numVoxelsOnSurface;
+ size_t m_numVoxelsInsideSurface;
+ Vec3<double> m_minBB;
+ double m_scale;
+ SArray<Voxel, 8> m_voxels;
+ double m_unitVolume;
+ Vec3<double> m_minBBPts;
+ Vec3<double> m_maxBBPts;
+ Vec3<short> m_minBBVoxels;
+ Vec3<short> m_maxBBVoxels;
+ Vec3<short> m_barycenter;
+ double m_Q[3][3];
+ double m_D[3][3];
+ Vec3<double> m_barycenterPCA;
+};
+
+struct Tetrahedron {
+public:
+ Vec3<double> m_pts[4];
+ unsigned char m_data;
+};
+
+//!
+class TetrahedronSet : public PrimitiveSet {
+ friend class Volume;
+
+public:
+ //! Destructor.
+ ~TetrahedronSet(void);
+ //! Constructor.
+ TetrahedronSet();
+
+ const size_t GetNPrimitives() const { return m_tetrahedra.Size(); }
+ const size_t GetNPrimitivesOnSurf() const { return m_numTetrahedraOnSurface; }
+ const size_t GetNPrimitivesInsideSurf() const { return m_numTetrahedraInsideSurface; }
+ const Vec3<double>& GetMinBB() const { return m_minBB; }
+ const Vec3<double>& GetMaxBB() const { return m_maxBB; }
+ const Vec3<double>& GetBarycenter() const { return m_barycenter; }
+ const double GetEigenValue(AXIS axis) const { return m_D[axis][axis]; }
+ const double GetSacle() const { return m_scale; }
+ const double ComputeVolume() const;
+ const double ComputeMaxVolumeError() const;
+ void ComputeConvexHull(Mesh& meshCH, const size_t sampling = 1) const;
+ void ComputePrincipalAxes();
+ void AlignToPrincipalAxes();
+ void RevertAlignToPrincipalAxes();
+ void Clip(const Plane& plane, PrimitiveSet* const positivePart, PrimitiveSet* const negativePart) const;
+ void Intersect(const Plane& plane, SArray<Vec3<double> >* const positivePts,
+ SArray<Vec3<double> >* const negativePts, const size_t sampling) const;
+ void ComputeExteriorPoints(const Plane& plane, const Mesh& mesh,
+ SArray<Vec3<double> >* const exteriorPts) const;
+ void ComputeClippedVolumes(const Plane& plane, double& positiveVolume, double& negativeVolume) const;
+ void SelectOnSurface(PrimitiveSet* const onSurfP) const;
+ void ComputeBB();
+ void Convert(Mesh& mesh, const VOXEL_VALUE value) const;
+ inline bool Add(Tetrahedron& tetrahedron);
+ PrimitiveSet* Create() const
+ {
+ return new TetrahedronSet();
+ }
+ static const double EPS;
+
+private:
+ void AddClippedTetrahedra(const Vec3<double> (&pts)[10], const int32_t nPts);
+
+ size_t m_numTetrahedraOnSurface;
+ size_t m_numTetrahedraInsideSurface;
+ double m_scale;
+ Vec3<double> m_minBB;
+ Vec3<double> m_maxBB;
+ Vec3<double> m_barycenter;
+ SArray<Tetrahedron, 8> m_tetrahedra;
+ double m_Q[3][3];
+ double m_D[3][3];
+};
+
+//!
+class Volume {
+public:
+ //! Destructor.
+ ~Volume(void);
+
+ //! Constructor.
+ Volume();
+
+ //! Voxelize
+ template <class T>
+ void Voxelize(const T* const points, const uint32_t stridePoints, const uint32_t nPoints,
+ const int32_t* const triangles, const uint32_t strideTriangles, const uint32_t nTriangles,
+ const size_t dim, const Vec3<double>& barycenter, const double (&rot)[3][3]);
+ unsigned char& GetVoxel(const size_t i, const size_t j, const size_t k)
+ {
+ assert(i < m_dim[0] || i >= 0);
+ assert(j < m_dim[0] || j >= 0);
+ assert(k < m_dim[0] || k >= 0);
+ return m_data[i + j * m_dim[0] + k * m_dim[0] * m_dim[1]];
+ }
+ const unsigned char& GetVoxel(const size_t i, const size_t j, const size_t k) const
+ {
+ assert(i < m_dim[0] || i >= 0);
+ assert(j < m_dim[0] || j >= 0);
+ assert(k < m_dim[0] || k >= 0);
+ return m_data[i + j * m_dim[0] + k * m_dim[0] * m_dim[1]];
+ }
+ const size_t GetNPrimitivesOnSurf() const { return m_numVoxelsOnSurface; }
+ const size_t GetNPrimitivesInsideSurf() const { return m_numVoxelsInsideSurface; }
+ void Convert(Mesh& mesh, const VOXEL_VALUE value) const;
+ void Convert(VoxelSet& vset) const;
+ void Convert(TetrahedronSet& tset) const;
+ void AlignToPrincipalAxes(double (&rot)[3][3]) const;
+
+private:
+ void FillOutsideSurface(const size_t i0, const size_t j0, const size_t k0, const size_t i1,
+ const size_t j1, const size_t k1);
+ void FillInsideSurface();
+ template <class T>
+ void ComputeBB(const T* const points, const uint32_t stridePoints, const uint32_t nPoints,
+ const Vec3<double>& barycenter, const double (&rot)[3][3]);
+ void Allocate();
+ void Free();
+
+ Vec3<double> m_minBB;
+ Vec3<double> m_maxBB;
+ double m_scale;
+ size_t m_dim[3]; //>! dim
+ size_t m_numVoxelsOnSurface;
+ size_t m_numVoxelsInsideSurface;
+ size_t m_numVoxelsOutsideSurface;
+ unsigned char* m_data;
+};
+int32_t TriBoxOverlap(const Vec3<double>& boxcenter, const Vec3<double>& boxhalfsize, const Vec3<double>& triver0,
+ const Vec3<double>& triver1, const Vec3<double>& triver2);
+template <class T>
+inline void ComputeAlignedPoint(const T* const points, const uint32_t idx, const Vec3<double>& barycenter,
+ const double (&rot)[3][3], Vec3<double>& pt){};
+template <>
+inline void ComputeAlignedPoint<float>(const float* const points, const uint32_t idx, const Vec3<double>& barycenter, const double (&rot)[3][3], Vec3<double>& pt)
+{
+ double x = points[idx + 0] - barycenter[0];
+ double y = points[idx + 1] - barycenter[1];
+ double z = points[idx + 2] - barycenter[2];
+ pt[0] = rot[0][0] * x + rot[1][0] * y + rot[2][0] * z;
+ pt[1] = rot[0][1] * x + rot[1][1] * y + rot[2][1] * z;
+ pt[2] = rot[0][2] * x + rot[1][2] * y + rot[2][2] * z;
+}
+template <>
+inline void ComputeAlignedPoint<double>(const double* const points, const uint32_t idx, const Vec3<double>& barycenter, const double (&rot)[3][3], Vec3<double>& pt)
+{
+ double x = points[idx + 0] - barycenter[0];
+ double y = points[idx + 1] - barycenter[1];
+ double z = points[idx + 2] - barycenter[2];
+ pt[0] = rot[0][0] * x + rot[1][0] * y + rot[2][0] * z;
+ pt[1] = rot[0][1] * x + rot[1][1] * y + rot[2][1] * z;
+ pt[2] = rot[0][2] * x + rot[1][2] * y + rot[2][2] * z;
+}
+template <class T>
+void Volume::ComputeBB(const T* const points, const uint32_t stridePoints, const uint32_t nPoints,
+ const Vec3<double>& barycenter, const double (&rot)[3][3])
+{
+ Vec3<double> pt;
+ ComputeAlignedPoint(points, 0, barycenter, rot, pt);
+ m_maxBB = pt;
+ m_minBB = pt;
+ for (uint32_t v = 1; v < nPoints; ++v) {
+ ComputeAlignedPoint(points, v * stridePoints, barycenter, rot, pt);
+ for (int32_t i = 0; i < 3; ++i) {
+ if (pt[i] < m_minBB[i])
+ m_minBB[i] = pt[i];
+ else if (pt[i] > m_maxBB[i])
+ m_maxBB[i] = pt[i];
+ }
+ }
+}
+template <class T>
+void Volume::Voxelize(const T* const points, const uint32_t stridePoints, const uint32_t nPoints,
+ const int32_t* const triangles, const uint32_t strideTriangles, const uint32_t nTriangles,
+ const size_t dim, const Vec3<double>& barycenter, const double (&rot)[3][3])
+{
+ if (nPoints == 0) {
+ return;
+ }
+ ComputeBB(points, stridePoints, nPoints, barycenter, rot);
+
+ double d[3] = { m_maxBB[0] - m_minBB[0], m_maxBB[1] - m_minBB[1], m_maxBB[2] - m_minBB[2] };
+ double r;
+ if (d[0] > d[1] && d[0] > d[2]) {
+ r = d[0];
+ m_dim[0] = dim;
+ m_dim[1] = 2 + static_cast<size_t>(dim * d[1] / d[0]);
+ m_dim[2] = 2 + static_cast<size_t>(dim * d[2] / d[0]);
+ }
+ else if (d[1] > d[0] && d[1] > d[2]) {
+ r = d[1];
+ m_dim[1] = dim;
+ m_dim[0] = 2 + static_cast<size_t>(dim * d[0] / d[1]);
+ m_dim[2] = 2 + static_cast<size_t>(dim * d[2] / d[1]);
+ }
+ else {
+ r = d[2];
+ m_dim[2] = dim;
+ m_dim[0] = 2 + static_cast<size_t>(dim * d[0] / d[2]);
+ m_dim[1] = 2 + static_cast<size_t>(dim * d[1] / d[2]);
+ }
+
+ m_scale = r / (dim - 1);
+ double invScale = (dim - 1) / r;
+
+ Allocate();
+ m_numVoxelsOnSurface = 0;
+ m_numVoxelsInsideSurface = 0;
+ m_numVoxelsOutsideSurface = 0;
+
+ Vec3<double> p[3];
+ size_t i, j, k;
+ size_t i0, j0, k0;
+ size_t i1, j1, k1;
+ Vec3<double> boxcenter;
+ Vec3<double> pt;
+ const Vec3<double> boxhalfsize(0.5, 0.5, 0.5);
+ for (size_t t = 0, ti = 0; t < nTriangles; ++t, ti += strideTriangles) {
+ Vec3<int32_t> tri(triangles[ti + 0],
+ triangles[ti + 1],
+ triangles[ti + 2]);
+ for (int32_t c = 0; c < 3; ++c) {
+ ComputeAlignedPoint(points, tri[c] * stridePoints, barycenter, rot, pt);
+ p[c][0] = (pt[0] - m_minBB[0]) * invScale;
+ p[c][1] = (pt[1] - m_minBB[1]) * invScale;
+ p[c][2] = (pt[2] - m_minBB[2]) * invScale;
+ i = static_cast<size_t>(p[c][0] + 0.5);
+ j = static_cast<size_t>(p[c][1] + 0.5);
+ k = static_cast<size_t>(p[c][2] + 0.5);
+ assert(i < m_dim[0] && i >= 0 && j < m_dim[1] && j >= 0 && k < m_dim[2] && k >= 0);
+
+ if (c == 0) {
+ i0 = i1 = i;
+ j0 = j1 = j;
+ k0 = k1 = k;
+ }
+ else {
+ if (i < i0)
+ i0 = i;
+ if (j < j0)
+ j0 = j;
+ if (k < k0)
+ k0 = k;
+ if (i > i1)
+ i1 = i;
+ if (j > j1)
+ j1 = j;
+ if (k > k1)
+ k1 = k;
+ }
+ }
+ if (i0 > 0)
+ --i0;
+ if (j0 > 0)
+ --j0;
+ if (k0 > 0)
+ --k0;
+ if (i1 < m_dim[0])
+ ++i1;
+ if (j1 < m_dim[1])
+ ++j1;
+ if (k1 < m_dim[2])
+ ++k1;
+ for (size_t i = i0; i < i1; ++i) {
+ boxcenter[0] = (double)i;
+ for (size_t j = j0; j < j1; ++j) {
+ boxcenter[1] = (double)j;
+ for (size_t k = k0; k < k1; ++k) {
+ boxcenter[2] = (double)k;
+ int32_t res = TriBoxOverlap(boxcenter, boxhalfsize, p[0], p[1], p[2]);
+ unsigned char& value = GetVoxel(i, j, k);
+ if (res == 1 && value == PRIMITIVE_UNDEFINED) {
+ value = PRIMITIVE_ON_SURFACE;
+ ++m_numVoxelsOnSurface;
+ }
+ }
+ }
+ }
+ }
+ FillOutsideSurface(0, 0, 0, m_dim[0], m_dim[1], 1);
+ FillOutsideSurface(0, 0, m_dim[2] - 1, m_dim[0], m_dim[1], m_dim[2]);
+ FillOutsideSurface(0, 0, 0, m_dim[0], 1, m_dim[2]);
+ FillOutsideSurface(0, m_dim[1] - 1, 0, m_dim[0], m_dim[1], m_dim[2]);
+ FillOutsideSurface(0, 0, 0, 1, m_dim[1], m_dim[2]);
+ FillOutsideSurface(m_dim[0] - 1, 0, 0, m_dim[0], m_dim[1], m_dim[2]);
+ FillInsideSurface();
+}
+}
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+
+#endif // VHACD_VOLUME_H
diff --git a/thirdparty/vhacd/public/VHACD.h b/thirdparty/vhacd/public/VHACD.h
new file mode 100644
index 0000000000..863aeda9de
--- /dev/null
+++ b/thirdparty/vhacd/public/VHACD.h
@@ -0,0 +1,153 @@
+/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
+ All rights reserved.
+
+
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+ 2. 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.
+
+ 3. The names of the contributors may not 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.
+ */
+#pragma once
+#ifndef VHACD_H
+#define VHACD_H
+
+#define VHACD_VERSION_MAJOR 2
+#define VHACD_VERSION_MINOR 3
+
+// Changes for version 2.3
+//
+// m_gamma : Has been removed. This used to control the error metric to merge convex hulls. Now it uses the 'm_maxConvexHulls' value instead.
+// m_maxConvexHulls : This is the maximum number of convex hulls to produce from the merge operation; replaces 'm_gamma'.
+//
+// Note that decomposition depth is no longer a user provided value. It is now derived from the
+// maximum number of hulls requested.
+//
+// As a convenience to the user, each convex hull produced now includes the volume of the hull as well as it's center.
+//
+// This version supports a convenience method to automatically make V-HACD run asynchronously in a background thread.
+// To get a fully asynchronous version, call 'CreateVHACD_ASYNC' instead of 'CreateVHACD'. You get the same interface however,
+// now when computing convex hulls, it is no longer a blocking operation. All callback messages are still returned
+// in the application's thread so you don't need to worry about mutex locks or anything in that case.
+// To tell if the operation is complete, the application should call 'IsReady'. This will return true if
+// the last approximation operation is complete and will dispatch any pending messages.
+// If you call 'Compute' while a previous operation was still running, it will automatically cancel the last request
+// and begin a new one. To cancel a currently running approximation just call 'Cancel'.
+#include <stdint.h>
+
+namespace VHACD {
+class IVHACD {
+public:
+ class IUserCallback {
+ public:
+ virtual ~IUserCallback(){};
+ virtual void Update(const double overallProgress,
+ const double stageProgress,
+ const double operationProgress,
+ const char* const stage,
+ const char* const operation)
+ = 0;
+ };
+
+ class IUserLogger {
+ public:
+ virtual ~IUserLogger(){};
+ virtual void Log(const char* const msg) = 0;
+ };
+
+ class ConvexHull {
+ public:
+ double* m_points;
+ uint32_t* m_triangles;
+ uint32_t m_nPoints;
+ uint32_t m_nTriangles;
+ double m_volume;
+ double m_center[3];
+ };
+
+ class Parameters {
+ public:
+ Parameters(void) { Init(); }
+ void Init(void)
+ {
+ m_resolution = 100000;
+ m_concavity = 0.001;
+ m_planeDownsampling = 4;
+ m_convexhullDownsampling = 4;
+ m_alpha = 0.05;
+ m_beta = 0.05;
+ m_pca = 0;
+ m_mode = 0; // 0: voxel-based (recommended), 1: tetrahedron-based
+ m_maxNumVerticesPerCH = 64;
+ m_minVolumePerCH = 0.0001;
+ m_callback = 0;
+ m_logger = 0;
+ m_convexhullApproximation = true;
+ m_oclAcceleration = true;
+ m_maxConvexHulls = 1024;
+ m_projectHullVertices = true; // This will project the output convex hull vertices onto the original source mesh to increase the floating point accuracy of the results
+ }
+ double m_concavity;
+ double m_alpha;
+ double m_beta;
+ double m_minVolumePerCH;
+ IUserCallback* m_callback;
+ IUserLogger* m_logger;
+ uint32_t m_resolution;
+ uint32_t m_maxNumVerticesPerCH;
+ uint32_t m_planeDownsampling;
+ uint32_t m_convexhullDownsampling;
+ uint32_t m_pca;
+ uint32_t m_mode;
+ uint32_t m_convexhullApproximation;
+ uint32_t m_oclAcceleration;
+ uint32_t m_maxConvexHulls;
+ bool m_projectHullVertices;
+ };
+
+ virtual void Cancel() = 0;
+ virtual bool Compute(const float* const points,
+ const uint32_t countPoints,
+ const uint32_t* const triangles,
+ const uint32_t countTriangles,
+ const Parameters& params)
+ = 0;
+ virtual bool Compute(const double* const points,
+ const uint32_t countPoints,
+ const uint32_t* const triangles,
+ const uint32_t countTriangles,
+ const Parameters& params)
+ = 0;
+ virtual uint32_t GetNConvexHulls() const = 0;
+ virtual void GetConvexHull(const uint32_t index, ConvexHull& ch) const = 0;
+ virtual void Clean(void) = 0; // release internally allocated memory
+ virtual void Release(void) = 0; // release IVHACD
+ virtual bool OCLInit(void* const oclDevice,
+ IUserLogger* const logger = 0)
+ = 0;
+ virtual bool OCLRelease(IUserLogger* const logger = 0) = 0;
+
+ // Will compute the center of mass of the convex hull decomposition results and return it
+ // in 'centerOfMass'. Returns false if the center of mass could not be computed.
+ virtual bool ComputeCenterOfMass(double centerOfMass[3]) const = 0;
+
+ // In synchronous mode (non-multi-threaded) the state is always 'ready'
+ // In asynchronous mode, this returns true if the background thread is not still actively computing
+ // a new solution. In an asynchronous config the 'IsReady' call will report any update or log
+ // messages in the caller's current thread.
+ virtual bool IsReady(void) const
+ {
+ return true;
+ }
+
+protected:
+ virtual ~IVHACD(void) {}
+};
+IVHACD* CreateVHACD(void);
+IVHACD* CreateVHACD_ASYNC(void);
+}
+#endif // VHACD_H
diff --git a/thirdparty/vhacd/src/FloatMath.cpp b/thirdparty/vhacd/src/FloatMath.cpp
new file mode 100644
index 0000000000..481e875104
--- /dev/null
+++ b/thirdparty/vhacd/src/FloatMath.cpp
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <math.h>
+#include <float.h>
+#include "FloatMath.h"
+#include <vector>
+
+#define REAL float
+
+#include "FloatMath.inl"
+
+#undef REAL
+#define REAL double
+
+#include "FloatMath.inl"
diff --git a/thirdparty/vhacd/src/FloatMath.inl b/thirdparty/vhacd/src/FloatMath.inl
new file mode 100644
index 0000000000..ce529e6f71
--- /dev/null
+++ b/thirdparty/vhacd/src/FloatMath.inl
@@ -0,0 +1,5276 @@
+// a set of routines that let you do common 3d math
+// operations without any vector, matrix, or quaternion
+// classes or templates.
+//
+// a vector (or point) is a 'float *' to 3 floating point numbers.
+// a matrix is a 'float *' to an array of 16 floating point numbers representing a 4x4 transformation matrix compatible with D3D or OGL
+// a quaternion is a 'float *' to 4 floats representing a quaternion x,y,z,w
+//
+
+namespace FLOAT_MATH
+{
+
+void fm_inverseRT(const REAL matrix[16],const REAL pos[3],REAL t[3]) // inverse rotate translate the point.
+{
+
+ REAL _x = pos[0] - matrix[3*4+0];
+ REAL _y = pos[1] - matrix[3*4+1];
+ REAL _z = pos[2] - matrix[3*4+2];
+
+ // Multiply inverse-translated source vector by inverted rotation transform
+
+ t[0] = (matrix[0*4+0] * _x) + (matrix[0*4+1] * _y) + (matrix[0*4+2] * _z);
+ t[1] = (matrix[1*4+0] * _x) + (matrix[1*4+1] * _y) + (matrix[1*4+2] * _z);
+ t[2] = (matrix[2*4+0] * _x) + (matrix[2*4+1] * _y) + (matrix[2*4+2] * _z);
+
+}
+
+REAL fm_getDeterminant(const REAL matrix[16])
+{
+ REAL tempv[3];
+ REAL p0[3];
+ REAL p1[3];
+ REAL p2[3];
+
+
+ p0[0] = matrix[0*4+0];
+ p0[1] = matrix[0*4+1];
+ p0[2] = matrix[0*4+2];
+
+ p1[0] = matrix[1*4+0];
+ p1[1] = matrix[1*4+1];
+ p1[2] = matrix[1*4+2];
+
+ p2[0] = matrix[2*4+0];
+ p2[1] = matrix[2*4+1];
+ p2[2] = matrix[2*4+2];
+
+ fm_cross(tempv,p1,p2);
+
+ return fm_dot(p0,tempv);
+
+}
+
+REAL fm_squared(REAL x) { return x*x; };
+
+void fm_decomposeTransform(const REAL local_transform[16],REAL trans[3],REAL rot[4],REAL scale[3])
+{
+
+ trans[0] = local_transform[12];
+ trans[1] = local_transform[13];
+ trans[2] = local_transform[14];
+
+ scale[0] = (REAL)sqrt(fm_squared(local_transform[0*4+0]) + fm_squared(local_transform[0*4+1]) + fm_squared(local_transform[0*4+2]));
+ scale[1] = (REAL)sqrt(fm_squared(local_transform[1*4+0]) + fm_squared(local_transform[1*4+1]) + fm_squared(local_transform[1*4+2]));
+ scale[2] = (REAL)sqrt(fm_squared(local_transform[2*4+0]) + fm_squared(local_transform[2*4+1]) + fm_squared(local_transform[2*4+2]));
+
+ REAL m[16];
+ memcpy(m,local_transform,sizeof(REAL)*16);
+
+ REAL sx = 1.0f / scale[0];
+ REAL sy = 1.0f / scale[1];
+ REAL sz = 1.0f / scale[2];
+
+ m[0*4+0]*=sx;
+ m[0*4+1]*=sx;
+ m[0*4+2]*=sx;
+
+ m[1*4+0]*=sy;
+ m[1*4+1]*=sy;
+ m[1*4+2]*=sy;
+
+ m[2*4+0]*=sz;
+ m[2*4+1]*=sz;
+ m[2*4+2]*=sz;
+
+ fm_matrixToQuat(m,rot);
+
+}
+
+void fm_getSubMatrix(int32_t ki,int32_t kj,REAL pDst[16],const REAL matrix[16])
+{
+ int32_t row, col;
+ int32_t dstCol = 0, dstRow = 0;
+
+ for ( col = 0; col < 4; col++ )
+ {
+ if ( col == kj )
+ {
+ continue;
+ }
+ for ( dstRow = 0, row = 0; row < 4; row++ )
+ {
+ if ( row == ki )
+ {
+ continue;
+ }
+ pDst[dstCol*4+dstRow] = matrix[col*4+row];
+ dstRow++;
+ }
+ dstCol++;
+ }
+}
+
+void fm_inverseTransform(const REAL matrix[16],REAL inverse_matrix[16])
+{
+ REAL determinant = fm_getDeterminant(matrix);
+ determinant = 1.0f / determinant;
+ for (int32_t i = 0; i < 4; i++ )
+ {
+ for (int32_t j = 0; j < 4; j++ )
+ {
+ int32_t sign = 1 - ( ( i + j ) % 2 ) * 2;
+ REAL subMat[16];
+ fm_identity(subMat);
+ fm_getSubMatrix( i, j, subMat, matrix );
+ REAL subDeterminant = fm_getDeterminant(subMat);
+ inverse_matrix[i*4+j] = ( subDeterminant * sign ) * determinant;
+ }
+ }
+}
+
+void fm_identity(REAL matrix[16]) // set 4x4 matrix to identity.
+{
+ matrix[0*4+0] = 1;
+ matrix[1*4+1] = 1;
+ matrix[2*4+2] = 1;
+ matrix[3*4+3] = 1;
+
+ matrix[1*4+0] = 0;
+ matrix[2*4+0] = 0;
+ matrix[3*4+0] = 0;
+
+ matrix[0*4+1] = 0;
+ matrix[2*4+1] = 0;
+ matrix[3*4+1] = 0;
+
+ matrix[0*4+2] = 0;
+ matrix[1*4+2] = 0;
+ matrix[3*4+2] = 0;
+
+ matrix[0*4+3] = 0;
+ matrix[1*4+3] = 0;
+ matrix[2*4+3] = 0;
+
+}
+
+void fm_quatToEuler(const REAL quat[4],REAL &ax,REAL &ay,REAL &az)
+{
+ REAL x = quat[0];
+ REAL y = quat[1];
+ REAL z = quat[2];
+ REAL w = quat[3];
+
+ REAL sint = (2.0f * w * y) - (2.0f * x * z);
+ REAL cost_temp = 1.0f - (sint * sint);
+ REAL cost = 0;
+
+ if ( (REAL)fabs(cost_temp) > 0.001f )
+ {
+ cost = (REAL)sqrt( cost_temp );
+ }
+
+ REAL sinv, cosv, sinf, cosf;
+ if ( (REAL)fabs(cost) > 0.001f )
+ {
+ cost = 1.0f / cost;
+ sinv = ((2.0f * y * z) + (2.0f * w * x)) * cost;
+ cosv = (1.0f - (2.0f * x * x) - (2.0f * y * y)) * cost;
+ sinf = ((2.0f * x * y) + (2.0f * w * z)) * cost;
+ cosf = (1.0f - (2.0f * y * y) - (2.0f * z * z)) * cost;
+ }
+ else
+ {
+ sinv = (2.0f * w * x) - (2.0f * y * z);
+ cosv = 1.0f - (2.0f * x * x) - (2.0f * z * z);
+ sinf = 0;
+ cosf = 1.0f;
+ }
+
+ // compute output rotations
+ ax = (REAL)atan2( sinv, cosv );
+ ay = (REAL)atan2( sint, cost );
+ az = (REAL)atan2( sinf, cosf );
+
+}
+
+void fm_eulerToMatrix(REAL ax,REAL ay,REAL az,REAL *matrix) // convert euler (in radians) to a dest 4x4 matrix (translation set to zero)
+{
+ REAL quat[4];
+ fm_eulerToQuat(ax,ay,az,quat);
+ fm_quatToMatrix(quat,matrix);
+}
+
+void fm_getAABB(uint32_t vcount,const REAL *points,uint32_t pstride,REAL *bmin,REAL *bmax)
+{
+
+ const uint8_t *source = (const uint8_t *) points;
+
+ bmin[0] = points[0];
+ bmin[1] = points[1];
+ bmin[2] = points[2];
+
+ bmax[0] = points[0];
+ bmax[1] = points[1];
+ bmax[2] = points[2];
+
+
+ for (uint32_t i=1; i<vcount; i++)
+ {
+ source+=pstride;
+ const REAL *p = (const REAL *) source;
+
+ if ( p[0] < bmin[0] ) bmin[0] = p[0];
+ if ( p[1] < bmin[1] ) bmin[1] = p[1];
+ if ( p[2] < bmin[2] ) bmin[2] = p[2];
+
+ if ( p[0] > bmax[0] ) bmax[0] = p[0];
+ if ( p[1] > bmax[1] ) bmax[1] = p[1];
+ if ( p[2] > bmax[2] ) bmax[2] = p[2];
+
+ }
+}
+
+void fm_eulerToQuat(const REAL *euler,REAL *quat) // convert euler angles to quaternion.
+{
+ fm_eulerToQuat(euler[0],euler[1],euler[2],quat);
+}
+
+void fm_eulerToQuat(REAL roll,REAL pitch,REAL yaw,REAL *quat) // convert euler angles to quaternion.
+{
+ roll *= 0.5f;
+ pitch *= 0.5f;
+ yaw *= 0.5f;
+
+ REAL cr = (REAL)cos(roll);
+ REAL cp = (REAL)cos(pitch);
+ REAL cy = (REAL)cos(yaw);
+
+ REAL sr = (REAL)sin(roll);
+ REAL sp = (REAL)sin(pitch);
+ REAL sy = (REAL)sin(yaw);
+
+ REAL cpcy = cp * cy;
+ REAL spsy = sp * sy;
+ REAL spcy = sp * cy;
+ REAL cpsy = cp * sy;
+
+ quat[0] = ( sr * cpcy - cr * spsy);
+ quat[1] = ( cr * spcy + sr * cpsy);
+ quat[2] = ( cr * cpsy - sr * spcy);
+ quat[3] = cr * cpcy + sr * spsy;
+}
+
+void fm_quatToMatrix(const REAL *quat,REAL *matrix) // convert quaterinion rotation to matrix, zeros out the translation component.
+{
+
+ REAL xx = quat[0]*quat[0];
+ REAL yy = quat[1]*quat[1];
+ REAL zz = quat[2]*quat[2];
+ REAL xy = quat[0]*quat[1];
+ REAL xz = quat[0]*quat[2];
+ REAL yz = quat[1]*quat[2];
+ REAL wx = quat[3]*quat[0];
+ REAL wy = quat[3]*quat[1];
+ REAL wz = quat[3]*quat[2];
+
+ matrix[0*4+0] = 1 - 2 * ( yy + zz );
+ matrix[1*4+0] = 2 * ( xy - wz );
+ matrix[2*4+0] = 2 * ( xz + wy );
+
+ matrix[0*4+1] = 2 * ( xy + wz );
+ matrix[1*4+1] = 1 - 2 * ( xx + zz );
+ matrix[2*4+1] = 2 * ( yz - wx );
+
+ matrix[0*4+2] = 2 * ( xz - wy );
+ matrix[1*4+2] = 2 * ( yz + wx );
+ matrix[2*4+2] = 1 - 2 * ( xx + yy );
+
+ matrix[3*4+0] = matrix[3*4+1] = matrix[3*4+2] = (REAL) 0.0f;
+ matrix[0*4+3] = matrix[1*4+3] = matrix[2*4+3] = (REAL) 0.0f;
+ matrix[3*4+3] =(REAL) 1.0f;
+
+}
+
+
+void fm_quatRotate(const REAL *quat,const REAL *v,REAL *r) // rotate a vector directly by a quaternion.
+{
+ REAL left[4];
+
+ left[0] = quat[3]*v[0] + quat[1]*v[2] - v[1]*quat[2];
+ left[1] = quat[3]*v[1] + quat[2]*v[0] - v[2]*quat[0];
+ left[2] = quat[3]*v[2] + quat[0]*v[1] - v[0]*quat[1];
+ left[3] = - quat[0]*v[0] - quat[1]*v[1] - quat[2]*v[2];
+
+ r[0] = (left[3]*-quat[0]) + (quat[3]*left[0]) + (left[1]*-quat[2]) - (-quat[1]*left[2]);
+ r[1] = (left[3]*-quat[1]) + (quat[3]*left[1]) + (left[2]*-quat[0]) - (-quat[2]*left[0]);
+ r[2] = (left[3]*-quat[2]) + (quat[3]*left[2]) + (left[0]*-quat[1]) - (-quat[0]*left[1]);
+
+}
+
+
+void fm_getTranslation(const REAL *matrix,REAL *t)
+{
+ t[0] = matrix[3*4+0];
+ t[1] = matrix[3*4+1];
+ t[2] = matrix[3*4+2];
+}
+
+void fm_matrixToQuat(const REAL *matrix,REAL *quat) // convert the 3x3 portion of a 4x4 matrix into a quaterion as x,y,z,w
+{
+
+ REAL tr = matrix[0*4+0] + matrix[1*4+1] + matrix[2*4+2];
+
+ // check the diagonal
+
+ if (tr > 0.0f )
+ {
+ REAL s = (REAL) sqrt ( (double) (tr + 1.0f) );
+ quat[3] = s * 0.5f;
+ s = 0.5f / s;
+ quat[0] = (matrix[1*4+2] - matrix[2*4+1]) * s;
+ quat[1] = (matrix[2*4+0] - matrix[0*4+2]) * s;
+ quat[2] = (matrix[0*4+1] - matrix[1*4+0]) * s;
+
+ }
+ else
+ {
+ // diagonal is negative
+ int32_t nxt[3] = {1, 2, 0};
+ REAL qa[4];
+
+ int32_t i = 0;
+
+ if (matrix[1*4+1] > matrix[0*4+0]) i = 1;
+ if (matrix[2*4+2] > matrix[i*4+i]) i = 2;
+
+ int32_t j = nxt[i];
+ int32_t k = nxt[j];
+
+ REAL s = (REAL)sqrt ( ((matrix[i*4+i] - (matrix[j*4+j] + matrix[k*4+k])) + 1.0f) );
+
+ qa[i] = s * 0.5f;
+
+ if (s != 0.0f ) s = 0.5f / s;
+
+ qa[3] = (matrix[j*4+k] - matrix[k*4+j]) * s;
+ qa[j] = (matrix[i*4+j] + matrix[j*4+i]) * s;
+ qa[k] = (matrix[i*4+k] + matrix[k*4+i]) * s;
+
+ quat[0] = qa[0];
+ quat[1] = qa[1];
+ quat[2] = qa[2];
+ quat[3] = qa[3];
+ }
+// fm_normalizeQuat(quat);
+}
+
+
+REAL fm_sphereVolume(REAL radius) // return's the volume of a sphere of this radius (4/3 PI * R cubed )
+{
+ return (4.0f / 3.0f ) * FM_PI * radius * radius * radius;
+}
+
+
+REAL fm_cylinderVolume(REAL radius,REAL h)
+{
+ return FM_PI * radius * radius *h;
+}
+
+REAL fm_capsuleVolume(REAL radius,REAL h)
+{
+ REAL volume = fm_sphereVolume(radius); // volume of the sphere portion.
+ REAL ch = h-radius*2; // this is the cylinder length
+ if ( ch > 0 )
+ {
+ volume+=fm_cylinderVolume(radius,ch);
+ }
+ return volume;
+}
+
+void fm_transform(const REAL matrix[16],const REAL v[3],REAL t[3]) // rotate and translate this point
+{
+ if ( matrix )
+ {
+ REAL tx = (matrix[0*4+0] * v[0]) + (matrix[1*4+0] * v[1]) + (matrix[2*4+0] * v[2]) + matrix[3*4+0];
+ REAL ty = (matrix[0*4+1] * v[0]) + (matrix[1*4+1] * v[1]) + (matrix[2*4+1] * v[2]) + matrix[3*4+1];
+ REAL tz = (matrix[0*4+2] * v[0]) + (matrix[1*4+2] * v[1]) + (matrix[2*4+2] * v[2]) + matrix[3*4+2];
+ t[0] = tx;
+ t[1] = ty;
+ t[2] = tz;
+ }
+ else
+ {
+ t[0] = v[0];
+ t[1] = v[1];
+ t[2] = v[2];
+ }
+}
+
+void fm_rotate(const REAL matrix[16],const REAL v[3],REAL t[3]) // rotate and translate this point
+{
+ if ( matrix )
+ {
+ REAL tx = (matrix[0*4+0] * v[0]) + (matrix[1*4+0] * v[1]) + (matrix[2*4+0] * v[2]);
+ REAL ty = (matrix[0*4+1] * v[0]) + (matrix[1*4+1] * v[1]) + (matrix[2*4+1] * v[2]);
+ REAL tz = (matrix[0*4+2] * v[0]) + (matrix[1*4+2] * v[1]) + (matrix[2*4+2] * v[2]);
+ t[0] = tx;
+ t[1] = ty;
+ t[2] = tz;
+ }
+ else
+ {
+ t[0] = v[0];
+ t[1] = v[1];
+ t[2] = v[2];
+ }
+}
+
+
+REAL fm_distance(const REAL *p1,const REAL *p2)
+{
+ REAL dx = p1[0] - p2[0];
+ REAL dy = p1[1] - p2[1];
+ REAL dz = p1[2] - p2[2];
+
+ return (REAL)sqrt( dx*dx + dy*dy + dz *dz );
+}
+
+REAL fm_distanceSquared(const REAL *p1,const REAL *p2)
+{
+ REAL dx = p1[0] - p2[0];
+ REAL dy = p1[1] - p2[1];
+ REAL dz = p1[2] - p2[2];
+
+ return dx*dx + dy*dy + dz *dz;
+}
+
+
+REAL fm_distanceSquaredXZ(const REAL *p1,const REAL *p2)
+{
+ REAL dx = p1[0] - p2[0];
+ REAL dz = p1[2] - p2[2];
+
+ return dx*dx + dz *dz;
+}
+
+
+REAL fm_computePlane(const REAL *A,const REAL *B,const REAL *C,REAL *n) // returns D
+{
+ REAL vx = (B[0] - C[0]);
+ REAL vy = (B[1] - C[1]);
+ REAL vz = (B[2] - C[2]);
+
+ REAL wx = (A[0] - B[0]);
+ REAL wy = (A[1] - B[1]);
+ REAL wz = (A[2] - B[2]);
+
+ REAL vw_x = vy * wz - vz * wy;
+ REAL vw_y = vz * wx - vx * wz;
+ REAL vw_z = vx * wy - vy * wx;
+
+ REAL mag = (REAL)sqrt((vw_x * vw_x) + (vw_y * vw_y) + (vw_z * vw_z));
+
+ if ( mag < 0.000001f )
+ {
+ mag = 0;
+ }
+ else
+ {
+ mag = 1.0f/mag;
+ }
+
+ REAL x = vw_x * mag;
+ REAL y = vw_y * mag;
+ REAL z = vw_z * mag;
+
+
+ REAL D = 0.0f - ((x*A[0])+(y*A[1])+(z*A[2]));
+
+ n[0] = x;
+ n[1] = y;
+ n[2] = z;
+
+ return D;
+}
+
+REAL fm_distToPlane(const REAL *plane,const REAL *p) // computes the distance of this point from the plane.
+{
+ return p[0]*plane[0]+p[1]*plane[1]+p[2]*plane[2]+plane[3];
+}
+
+REAL fm_dot(const REAL *p1,const REAL *p2)
+{
+ return p1[0]*p2[0]+p1[1]*p2[1]+p1[2]*p2[2];
+}
+
+void fm_cross(REAL *cross,const REAL *a,const REAL *b)
+{
+ cross[0] = a[1]*b[2] - a[2]*b[1];
+ cross[1] = a[2]*b[0] - a[0]*b[2];
+ cross[2] = a[0]*b[1] - a[1]*b[0];
+}
+
+REAL fm_computeNormalVector(REAL *n,const REAL *p1,const REAL *p2)
+{
+ n[0] = p2[0] - p1[0];
+ n[1] = p2[1] - p1[1];
+ n[2] = p2[2] - p1[2];
+ return fm_normalize(n);
+}
+
+bool fm_computeWindingOrder(const REAL *p1,const REAL *p2,const REAL *p3) // returns true if the triangle is clockwise.
+{
+ bool ret = false;
+
+ REAL v1[3];
+ REAL v2[3];
+
+ fm_computeNormalVector(v1,p1,p2); // p2-p1 (as vector) and then normalized
+ fm_computeNormalVector(v2,p1,p3); // p3-p1 (as vector) and then normalized
+
+ REAL cross[3];
+
+ fm_cross(cross, v1, v2 );
+ REAL ref[3] = { 1, 0, 0 };
+
+ REAL d = fm_dot( cross, ref );
+
+
+ if ( d <= 0 )
+ ret = false;
+ else
+ ret = true;
+
+ return ret;
+}
+
+REAL fm_normalize(REAL *n) // normalize this vector
+{
+ REAL dist = (REAL)sqrt(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]);
+ if ( dist > 0.0000001f )
+ {
+ REAL mag = 1.0f / dist;
+ n[0]*=mag;
+ n[1]*=mag;
+ n[2]*=mag;
+ }
+ else
+ {
+ n[0] = 1;
+ n[1] = 0;
+ n[2] = 0;
+ }
+
+ return dist;
+}
+
+
+void fm_matrixMultiply(const REAL *pA,const REAL *pB,REAL *pM)
+{
+#if 1
+
+ REAL a = pA[0*4+0] * pB[0*4+0] + pA[0*4+1] * pB[1*4+0] + pA[0*4+2] * pB[2*4+0] + pA[0*4+3] * pB[3*4+0];
+ REAL b = pA[0*4+0] * pB[0*4+1] + pA[0*4+1] * pB[1*4+1] + pA[0*4+2] * pB[2*4+1] + pA[0*4+3] * pB[3*4+1];
+ REAL c = pA[0*4+0] * pB[0*4+2] + pA[0*4+1] * pB[1*4+2] + pA[0*4+2] * pB[2*4+2] + pA[0*4+3] * pB[3*4+2];
+ REAL d = pA[0*4+0] * pB[0*4+3] + pA[0*4+1] * pB[1*4+3] + pA[0*4+2] * pB[2*4+3] + pA[0*4+3] * pB[3*4+3];
+
+ REAL e = pA[1*4+0] * pB[0*4+0] + pA[1*4+1] * pB[1*4+0] + pA[1*4+2] * pB[2*4+0] + pA[1*4+3] * pB[3*4+0];
+ REAL f = pA[1*4+0] * pB[0*4+1] + pA[1*4+1] * pB[1*4+1] + pA[1*4+2] * pB[2*4+1] + pA[1*4+3] * pB[3*4+1];
+ REAL g = pA[1*4+0] * pB[0*4+2] + pA[1*4+1] * pB[1*4+2] + pA[1*4+2] * pB[2*4+2] + pA[1*4+3] * pB[3*4+2];
+ REAL h = pA[1*4+0] * pB[0*4+3] + pA[1*4+1] * pB[1*4+3] + pA[1*4+2] * pB[2*4+3] + pA[1*4+3] * pB[3*4+3];
+
+ REAL i = pA[2*4+0] * pB[0*4+0] + pA[2*4+1] * pB[1*4+0] + pA[2*4+2] * pB[2*4+0] + pA[2*4+3] * pB[3*4+0];
+ REAL j = pA[2*4+0] * pB[0*4+1] + pA[2*4+1] * pB[1*4+1] + pA[2*4+2] * pB[2*4+1] + pA[2*4+3] * pB[3*4+1];
+ REAL k = pA[2*4+0] * pB[0*4+2] + pA[2*4+1] * pB[1*4+2] + pA[2*4+2] * pB[2*4+2] + pA[2*4+3] * pB[3*4+2];
+ REAL l = pA[2*4+0] * pB[0*4+3] + pA[2*4+1] * pB[1*4+3] + pA[2*4+2] * pB[2*4+3] + pA[2*4+3] * pB[3*4+3];
+
+ REAL m = pA[3*4+0] * pB[0*4+0] + pA[3*4+1] * pB[1*4+0] + pA[3*4+2] * pB[2*4+0] + pA[3*4+3] * pB[3*4+0];
+ REAL n = pA[3*4+0] * pB[0*4+1] + pA[3*4+1] * pB[1*4+1] + pA[3*4+2] * pB[2*4+1] + pA[3*4+3] * pB[3*4+1];
+ REAL o = pA[3*4+0] * pB[0*4+2] + pA[3*4+1] * pB[1*4+2] + pA[3*4+2] * pB[2*4+2] + pA[3*4+3] * pB[3*4+2];
+ REAL p = pA[3*4+0] * pB[0*4+3] + pA[3*4+1] * pB[1*4+3] + pA[3*4+2] * pB[2*4+3] + pA[3*4+3] * pB[3*4+3];
+
+ pM[0] = a;
+ pM[1] = b;
+ pM[2] = c;
+ pM[3] = d;
+
+ pM[4] = e;
+ pM[5] = f;
+ pM[6] = g;
+ pM[7] = h;
+
+ pM[8] = i;
+ pM[9] = j;
+ pM[10] = k;
+ pM[11] = l;
+
+ pM[12] = m;
+ pM[13] = n;
+ pM[14] = o;
+ pM[15] = p;
+
+
+#else
+ memset(pM, 0, sizeof(REAL)*16);
+ for(int32_t i=0; i<4; i++ )
+ for(int32_t j=0; j<4; j++ )
+ for(int32_t k=0; k<4; k++ )
+ pM[4*i+j] += pA[4*i+k] * pB[4*k+j];
+#endif
+}
+
+
+void fm_eulerToQuatDX(REAL x,REAL y,REAL z,REAL *quat) // convert euler angles to quaternion using the fucked up DirectX method
+{
+ REAL matrix[16];
+ fm_eulerToMatrix(x,y,z,matrix);
+ fm_matrixToQuat(matrix,quat);
+}
+
+// implementation copied from: http://blogs.msdn.com/mikepelton/archive/2004/10/29/249501.aspx
+void fm_eulerToMatrixDX(REAL x,REAL y,REAL z,REAL *matrix) // convert euler angles to quaternion using the fucked up DirectX method.
+{
+ fm_identity(matrix);
+ matrix[0*4+0] = (REAL)(cos(z)*cos(y) + sin(z)*sin(x)*sin(y));
+ matrix[0*4+1] = (REAL)(sin(z)*cos(x));
+ matrix[0*4+2] = (REAL)(cos(z)*-sin(y) + sin(z)*sin(x)*cos(y));
+
+ matrix[1*4+0] = (REAL)(-sin(z)*cos(y)+cos(z)*sin(x)*sin(y));
+ matrix[1*4+1] = (REAL)(cos(z)*cos(x));
+ matrix[1*4+2] = (REAL)(sin(z)*sin(y) +cos(z)*sin(x)*cos(y));
+
+ matrix[2*4+0] = (REAL)(cos(x)*sin(y));
+ matrix[2*4+1] = (REAL)(-sin(x));
+ matrix[2*4+2] = (REAL)(cos(x)*cos(y));
+}
+
+
+void fm_scale(REAL x,REAL y,REAL z,REAL *fscale) // apply scale to the matrix.
+{
+ fscale[0*4+0] = x;
+ fscale[1*4+1] = y;
+ fscale[2*4+2] = z;
+}
+
+
+void fm_composeTransform(const REAL *position,const REAL *quat,const REAL *scale,REAL *matrix)
+{
+ fm_identity(matrix);
+ fm_quatToMatrix(quat,matrix);
+
+ if ( scale && ( scale[0] != 1 || scale[1] != 1 || scale[2] != 1 ) )
+ {
+ REAL work[16];
+ memcpy(work,matrix,sizeof(REAL)*16);
+ REAL mscale[16];
+ fm_identity(mscale);
+ fm_scale(scale[0],scale[1],scale[2],mscale);
+ fm_matrixMultiply(work,mscale,matrix);
+ }
+
+ matrix[12] = position[0];
+ matrix[13] = position[1];
+ matrix[14] = position[2];
+}
+
+
+void fm_setTranslation(const REAL *translation,REAL *matrix)
+{
+ matrix[12] = translation[0];
+ matrix[13] = translation[1];
+ matrix[14] = translation[2];
+}
+
+static REAL enorm0_3d ( REAL x0, REAL y0, REAL z0, REAL x1, REAL y1, REAL z1 )
+
+/**********************************************************************/
+
+/*
+Purpose:
+
+ENORM0_3D computes the Euclidean norm of (P1-P0) in 3D.
+
+Modified:
+
+18 April 1999
+
+Author:
+
+John Burkardt
+
+Parameters:
+
+Input, REAL X0, Y0, Z0, X1, Y1, Z1, the coordinates of the points
+P0 and P1.
+
+Output, REAL ENORM0_3D, the Euclidean norm of (P1-P0).
+*/
+{
+ REAL value;
+
+ value = (REAL)sqrt (
+ ( x1 - x0 ) * ( x1 - x0 ) +
+ ( y1 - y0 ) * ( y1 - y0 ) +
+ ( z1 - z0 ) * ( z1 - z0 ) );
+
+ return value;
+}
+
+
+static REAL triangle_area_3d ( REAL x1, REAL y1, REAL z1, REAL x2,REAL y2, REAL z2, REAL x3, REAL y3, REAL z3 )
+
+ /**********************************************************************/
+
+ /*
+ Purpose:
+
+ TRIANGLE_AREA_3D computes the area of a triangle in 3D.
+
+ Modified:
+
+ 22 April 1999
+
+ Author:
+
+ John Burkardt
+
+ Parameters:
+
+ Input, REAL X1, Y1, Z1, X2, Y2, Z2, X3, Y3, Z3, the (X,Y,Z)
+ coordinates of the corners of the triangle.
+
+ Output, REAL TRIANGLE_AREA_3D, the area of the triangle.
+ */
+{
+ REAL a;
+ REAL alpha;
+ REAL area;
+ REAL b;
+ REAL base;
+ REAL c;
+ REAL dot;
+ REAL height;
+ /*
+ Find the projection of (P3-P1) onto (P2-P1).
+ */
+ dot =
+ ( x2 - x1 ) * ( x3 - x1 ) +
+ ( y2 - y1 ) * ( y3 - y1 ) +
+ ( z2 - z1 ) * ( z3 - z1 );
+
+ base = enorm0_3d ( x1, y1, z1, x2, y2, z2 );
+ /*
+ The height of the triangle is the length of (P3-P1) after its
+ projection onto (P2-P1) has been subtracted.
+ */
+ if ( base == 0.0 ) {
+
+ height = 0.0;
+
+ }
+ else {
+
+ alpha = dot / ( base * base );
+
+ a = x3 - x1 - alpha * ( x2 - x1 );
+ b = y3 - y1 - alpha * ( y2 - y1 );
+ c = z3 - z1 - alpha * ( z2 - z1 );
+
+ height = (REAL)sqrt ( a * a + b * b + c * c );
+
+ }
+
+ area = 0.5f * base * height;
+
+ return area;
+}
+
+
+REAL fm_computeArea(const REAL *p1,const REAL *p2,const REAL *p3)
+{
+ REAL ret = 0;
+
+ ret = triangle_area_3d(p1[0],p1[1],p1[2],p2[0],p2[1],p2[2],p3[0],p3[1],p3[2]);
+
+ return ret;
+}
+
+
+void fm_lerp(const REAL *p1,const REAL *p2,REAL *dest,REAL lerpValue)
+{
+ dest[0] = ((p2[0] - p1[0])*lerpValue) + p1[0];
+ dest[1] = ((p2[1] - p1[1])*lerpValue) + p1[1];
+ dest[2] = ((p2[2] - p1[2])*lerpValue) + p1[2];
+}
+
+bool fm_pointTestXZ(const REAL *p,const REAL *i,const REAL *j)
+{
+ bool ret = false;
+
+ if (((( i[2] <= p[2] ) && ( p[2] < j[2] )) || (( j[2] <= p[2] ) && ( p[2] < i[2] ))) && ( p[0] < (j[0] - i[0]) * (p[2] - i[2]) / (j[2] - i[2]) + i[0]))
+ ret = true;
+
+ return ret;
+};
+
+
+bool fm_insideTriangleXZ(const REAL *p,const REAL *p1,const REAL *p2,const REAL *p3)
+{
+ bool ret = false;
+
+ int32_t c = 0;
+ if ( fm_pointTestXZ(p,p1,p2) ) c = !c;
+ if ( fm_pointTestXZ(p,p2,p3) ) c = !c;
+ if ( fm_pointTestXZ(p,p3,p1) ) c = !c;
+ if ( c ) ret = true;
+
+ return ret;
+}
+
+bool fm_insideAABB(const REAL *pos,const REAL *bmin,const REAL *bmax)
+{
+ bool ret = false;
+
+ if ( pos[0] >= bmin[0] && pos[0] <= bmax[0] &&
+ pos[1] >= bmin[1] && pos[1] <= bmax[1] &&
+ pos[2] >= bmin[2] && pos[2] <= bmax[2] )
+ ret = true;
+
+ return ret;
+}
+
+
+uint32_t fm_clipTestPoint(const REAL *bmin,const REAL *bmax,const REAL *pos)
+{
+ uint32_t ret = 0;
+
+ if ( pos[0] < bmin[0] )
+ ret|=FMCS_XMIN;
+ else if ( pos[0] > bmax[0] )
+ ret|=FMCS_XMAX;
+
+ if ( pos[1] < bmin[1] )
+ ret|=FMCS_YMIN;
+ else if ( pos[1] > bmax[1] )
+ ret|=FMCS_YMAX;
+
+ if ( pos[2] < bmin[2] )
+ ret|=FMCS_ZMIN;
+ else if ( pos[2] > bmax[2] )
+ ret|=FMCS_ZMAX;
+
+ return ret;
+}
+
+uint32_t fm_clipTestPointXZ(const REAL *bmin,const REAL *bmax,const REAL *pos) // only tests X and Z, not Y
+{
+ uint32_t ret = 0;
+
+ if ( pos[0] < bmin[0] )
+ ret|=FMCS_XMIN;
+ else if ( pos[0] > bmax[0] )
+ ret|=FMCS_XMAX;
+
+ if ( pos[2] < bmin[2] )
+ ret|=FMCS_ZMIN;
+ else if ( pos[2] > bmax[2] )
+ ret|=FMCS_ZMAX;
+
+ return ret;
+}
+
+uint32_t fm_clipTestAABB(const REAL *bmin,const REAL *bmax,const REAL *p1,const REAL *p2,const REAL *p3,uint32_t &andCode)
+{
+ uint32_t orCode = 0;
+
+ andCode = FMCS_XMIN | FMCS_XMAX | FMCS_YMIN | FMCS_YMAX | FMCS_ZMIN | FMCS_ZMAX;
+
+ uint32_t c = fm_clipTestPoint(bmin,bmax,p1);
+ orCode|=c;
+ andCode&=c;
+
+ c = fm_clipTestPoint(bmin,bmax,p2);
+ orCode|=c;
+ andCode&=c;
+
+ c = fm_clipTestPoint(bmin,bmax,p3);
+ orCode|=c;
+ andCode&=c;
+
+ return orCode;
+}
+
+bool intersect(const REAL *si,const REAL *ei,const REAL *bmin,const REAL *bmax,REAL *time)
+{
+ REAL st,et,fst = 0,fet = 1;
+
+ for (int32_t i = 0; i < 3; i++)
+ {
+ if (*si < *ei)
+ {
+ if (*si > *bmax || *ei < *bmin)
+ return false;
+ REAL di = *ei - *si;
+ st = (*si < *bmin)? (*bmin - *si) / di: 0;
+ et = (*ei > *bmax)? (*bmax - *si) / di: 1;
+ }
+ else
+ {
+ if (*ei > *bmax || *si < *bmin)
+ return false;
+ REAL di = *ei - *si;
+ st = (*si > *bmax)? (*bmax - *si) / di: 0;
+ et = (*ei < *bmin)? (*bmin - *si) / di: 1;
+ }
+
+ if (st > fst) fst = st;
+ if (et < fet) fet = et;
+ if (fet < fst)
+ return false;
+ bmin++; bmax++;
+ si++; ei++;
+ }
+
+ *time = fst;
+ return true;
+}
+
+
+
+bool fm_lineTestAABB(const REAL *p1,const REAL *p2,const REAL *bmin,const REAL *bmax,REAL &time)
+{
+ bool sect = intersect(p1,p2,bmin,bmax,&time);
+ return sect;
+}
+
+
+bool fm_lineTestAABBXZ(const REAL *p1,const REAL *p2,const REAL *bmin,const REAL *bmax,REAL &time)
+{
+ REAL _bmin[3];
+ REAL _bmax[3];
+
+ _bmin[0] = bmin[0];
+ _bmin[1] = -1e9;
+ _bmin[2] = bmin[2];
+
+ _bmax[0] = bmax[0];
+ _bmax[1] = 1e9;
+ _bmax[2] = bmax[2];
+
+ bool sect = intersect(p1,p2,_bmin,_bmax,&time);
+
+ return sect;
+}
+
+void fm_minmax(const REAL *p,REAL *bmin,REAL *bmax) // accmulate to a min-max value
+{
+
+ if ( p[0] < bmin[0] ) bmin[0] = p[0];
+ if ( p[1] < bmin[1] ) bmin[1] = p[1];
+ if ( p[2] < bmin[2] ) bmin[2] = p[2];
+
+ if ( p[0] > bmax[0] ) bmax[0] = p[0];
+ if ( p[1] > bmax[1] ) bmax[1] = p[1];
+ if ( p[2] > bmax[2] ) bmax[2] = p[2];
+
+}
+
+REAL fm_solveX(const REAL *plane,REAL y,REAL z) // solve for X given this plane equation and the other two components.
+{
+ REAL x = (y*plane[1]+z*plane[2]+plane[3]) / -plane[0];
+ return x;
+}
+
+REAL fm_solveY(const REAL *plane,REAL x,REAL z) // solve for Y given this plane equation and the other two components.
+{
+ REAL y = (x*plane[0]+z*plane[2]+plane[3]) / -plane[1];
+ return y;
+}
+
+
+REAL fm_solveZ(const REAL *plane,REAL x,REAL y) // solve for Y given this plane equation and the other two components.
+{
+ REAL z = (x*plane[0]+y*plane[1]+plane[3]) / -plane[2];
+ return z;
+}
+
+
+void fm_getAABBCenter(const REAL *bmin,const REAL *bmax,REAL *center)
+{
+ center[0] = (bmax[0]-bmin[0])*0.5f+bmin[0];
+ center[1] = (bmax[1]-bmin[1])*0.5f+bmin[1];
+ center[2] = (bmax[2]-bmin[2])*0.5f+bmin[2];
+}
+
+FM_Axis fm_getDominantAxis(const REAL normal[3])
+{
+ FM_Axis ret = FM_XAXIS;
+
+ REAL x = (REAL)fabs(normal[0]);
+ REAL y = (REAL)fabs(normal[1]);
+ REAL z = (REAL)fabs(normal[2]);
+
+ if ( y > x && y > z )
+ ret = FM_YAXIS;
+ else if ( z > x && z > y )
+ ret = FM_ZAXIS;
+
+ return ret;
+}
+
+
+bool fm_lineSphereIntersect(const REAL *center,REAL radius,const REAL *p1,const REAL *p2,REAL *intersect)
+{
+ bool ret = false;
+
+ REAL dir[3];
+
+ dir[0] = p2[0]-p1[0];
+ dir[1] = p2[1]-p1[1];
+ dir[2] = p2[2]-p1[2];
+
+ REAL distance = (REAL)sqrt( dir[0]*dir[0]+dir[1]*dir[1]+dir[2]*dir[2]);
+
+ if ( distance > 0 )
+ {
+ REAL recip = 1.0f / distance;
+ dir[0]*=recip;
+ dir[1]*=recip;
+ dir[2]*=recip;
+ ret = fm_raySphereIntersect(center,radius,p1,dir,distance,intersect);
+ }
+ else
+ {
+ dir[0] = center[0]-p1[0];
+ dir[1] = center[1]-p1[1];
+ dir[2] = center[2]-p1[2];
+ REAL d2 = dir[0]*dir[0]+dir[1]*dir[1]+dir[2]*dir[2];
+ REAL r2 = radius*radius;
+ if ( d2 < r2 )
+ {
+ ret = true;
+ if ( intersect )
+ {
+ intersect[0] = p1[0];
+ intersect[1] = p1[1];
+ intersect[2] = p1[2];
+ }
+ }
+ }
+ return ret;
+}
+
+#define DOT(p1,p2) (p1[0]*p2[0]+p1[1]*p2[1]+p1[2]*p2[2])
+
+bool fm_raySphereIntersect(const REAL *center,REAL radius,const REAL *pos,const REAL *dir,REAL distance,REAL *intersect)
+{
+ bool ret = false;
+
+ REAL E0[3];
+
+ E0[0] = center[0] - pos[0];
+ E0[1] = center[1] - pos[1];
+ E0[2] = center[2] - pos[2];
+
+ REAL V[3];
+
+ V[0] = dir[0];
+ V[1] = dir[1];
+ V[2] = dir[2];
+
+
+ REAL dist2 = E0[0]*E0[0] + E0[1]*E0[1] + E0[2] * E0[2];
+ REAL radius2 = radius*radius; // radius squared..
+
+ // Bug Fix For Gem, if origin is *inside* the sphere, invert the
+ // direction vector so that we get a valid intersection location.
+ if ( dist2 < radius2 )
+ {
+ V[0]*=-1;
+ V[1]*=-1;
+ V[2]*=-1;
+ }
+
+
+ REAL v = DOT(E0,V);
+
+ REAL disc = radius2 - (dist2 - v*v);
+
+ if (disc > 0.0f)
+ {
+ if ( intersect )
+ {
+ REAL d = (REAL)sqrt(disc);
+ REAL diff = v-d;
+ if ( diff < distance )
+ {
+ intersect[0] = pos[0]+V[0]*diff;
+ intersect[1] = pos[1]+V[1]*diff;
+ intersect[2] = pos[2]+V[2]*diff;
+ ret = true;
+ }
+ }
+ }
+
+ return ret;
+}
+
+
+void fm_catmullRom(REAL *out_vector,const REAL *p1,const REAL *p2,const REAL *p3,const REAL *p4, const REAL s)
+{
+ REAL s_squared = s * s;
+ REAL s_cubed = s_squared * s;
+
+ REAL coefficient_p1 = -s_cubed + 2*s_squared - s;
+ REAL coefficient_p2 = 3 * s_cubed - 5 * s_squared + 2;
+ REAL coefficient_p3 = -3 * s_cubed +4 * s_squared + s;
+ REAL coefficient_p4 = s_cubed - s_squared;
+
+ out_vector[0] = (coefficient_p1 * p1[0] + coefficient_p2 * p2[0] + coefficient_p3 * p3[0] + coefficient_p4 * p4[0])*0.5f;
+ out_vector[1] = (coefficient_p1 * p1[1] + coefficient_p2 * p2[1] + coefficient_p3 * p3[1] + coefficient_p4 * p4[1])*0.5f;
+ out_vector[2] = (coefficient_p1 * p1[2] + coefficient_p2 * p2[2] + coefficient_p3 * p3[2] + coefficient_p4 * p4[2])*0.5f;
+}
+
+bool fm_intersectAABB(const REAL *bmin1,const REAL *bmax1,const REAL *bmin2,const REAL *bmax2)
+{
+ if ((bmin1[0] > bmax2[0]) || (bmin2[0] > bmax1[0])) return false;
+ if ((bmin1[1] > bmax2[1]) || (bmin2[1] > bmax1[1])) return false;
+ if ((bmin1[2] > bmax2[2]) || (bmin2[2] > bmax1[2])) return false;
+ return true;
+
+}
+
+bool fm_insideAABB(const REAL *obmin,const REAL *obmax,const REAL *tbmin,const REAL *tbmax) // test if bounding box tbmin/tmbax is fully inside obmin/obmax
+{
+ bool ret = false;
+
+ if ( tbmax[0] <= obmax[0] &&
+ tbmax[1] <= obmax[1] &&
+ tbmax[2] <= obmax[2] &&
+ tbmin[0] >= obmin[0] &&
+ tbmin[1] >= obmin[1] &&
+ tbmin[2] >= obmin[2] ) ret = true;
+
+ return ret;
+}
+
+
+// Reference, from Stan Melax in Game Gems I
+// Quaternion q;
+// vector3 c = CrossProduct(v0,v1);
+// REAL d = DotProduct(v0,v1);
+// REAL s = (REAL)sqrt((1+d)*2);
+// q.x = c.x / s;
+// q.y = c.y / s;
+// q.z = c.z / s;
+// q.w = s /2.0f;
+// return q;
+void fm_rotationArc(const REAL *v0,const REAL *v1,REAL *quat)
+{
+ REAL cross[3];
+
+ fm_cross(cross,v0,v1);
+ REAL d = fm_dot(v0,v1);
+
+ if( d<= -0.99999f ) // 180 about x axis
+ {
+ if ( fabsf((float)v0[0]) < 0.1f )
+ {
+ quat[0] = 0;
+ quat[1] = v0[2];
+ quat[2] = -v0[1];
+ quat[3] = 0;
+ }
+ else
+ {
+ quat[0] = v0[1];
+ quat[1] = -v0[0];
+ quat[2] = 0;
+ quat[3] = 0;
+ }
+ REAL magnitudeSquared = quat[0]*quat[0] + quat[1]*quat[1] + quat[2]*quat[2] + quat[3]*quat[3];
+ REAL magnitude = sqrtf((float)magnitudeSquared);
+ REAL recip = 1.0f / magnitude;
+ quat[0]*=recip;
+ quat[1]*=recip;
+ quat[2]*=recip;
+ quat[3]*=recip;
+ }
+ else
+ {
+ REAL s = (REAL)sqrt((1+d)*2);
+ REAL recip = 1.0f / s;
+
+ quat[0] = cross[0] * recip;
+ quat[1] = cross[1] * recip;
+ quat[2] = cross[2] * recip;
+ quat[3] = s * 0.5f;
+ }
+}
+
+
+REAL fm_distancePointLineSegment(const REAL *Point,const REAL *LineStart,const REAL *LineEnd,REAL *intersection,LineSegmentType &type,REAL epsilon)
+{
+ REAL ret;
+
+ REAL LineMag = fm_distance( LineEnd, LineStart );
+
+ if ( LineMag > 0 )
+ {
+ REAL U = ( ( ( Point[0] - LineStart[0] ) * ( LineEnd[0] - LineStart[0] ) ) + ( ( Point[1] - LineStart[1] ) * ( LineEnd[1] - LineStart[1] ) ) + ( ( Point[2] - LineStart[2] ) * ( LineEnd[2] - LineStart[2] ) ) ) / ( LineMag * LineMag );
+ if( U < 0.0f || U > 1.0f )
+ {
+ REAL d1 = fm_distanceSquared(Point,LineStart);
+ REAL d2 = fm_distanceSquared(Point,LineEnd);
+ if ( d1 <= d2 )
+ {
+ ret = (REAL)sqrt(d1);
+ intersection[0] = LineStart[0];
+ intersection[1] = LineStart[1];
+ intersection[2] = LineStart[2];
+ type = LS_START;
+ }
+ else
+ {
+ ret = (REAL)sqrt(d2);
+ intersection[0] = LineEnd[0];
+ intersection[1] = LineEnd[1];
+ intersection[2] = LineEnd[2];
+ type = LS_END;
+ }
+ }
+ else
+ {
+ intersection[0] = LineStart[0] + U * ( LineEnd[0] - LineStart[0] );
+ intersection[1] = LineStart[1] + U * ( LineEnd[1] - LineStart[1] );
+ intersection[2] = LineStart[2] + U * ( LineEnd[2] - LineStart[2] );
+
+ ret = fm_distance(Point,intersection);
+
+ REAL d1 = fm_distanceSquared(intersection,LineStart);
+ REAL d2 = fm_distanceSquared(intersection,LineEnd);
+ REAL mag = (epsilon*2)*(epsilon*2);
+
+ if ( d1 < mag ) // if less than 1/100th the total distance, treat is as the 'start'
+ {
+ type = LS_START;
+ }
+ else if ( d2 < mag )
+ {
+ type = LS_END;
+ }
+ else
+ {
+ type = LS_MIDDLE;
+ }
+
+ }
+ }
+ else
+ {
+ ret = LineMag;
+ intersection[0] = LineEnd[0];
+ intersection[1] = LineEnd[1];
+ intersection[2] = LineEnd[2];
+ type = LS_END;
+ }
+
+ return ret;
+}
+
+
+#ifndef BEST_FIT_PLANE_H
+
+#define BEST_FIT_PLANE_H
+
+template <class Type> class Eigen
+{
+public:
+
+
+ void DecrSortEigenStuff(void)
+ {
+ Tridiagonal(); //diagonalize the matrix.
+ QLAlgorithm(); //
+ DecreasingSort();
+ GuaranteeRotation();
+ }
+
+ void Tridiagonal(void)
+ {
+ Type fM00 = mElement[0][0];
+ Type fM01 = mElement[0][1];
+ Type fM02 = mElement[0][2];
+ Type fM11 = mElement[1][1];
+ Type fM12 = mElement[1][2];
+ Type fM22 = mElement[2][2];
+
+ m_afDiag[0] = fM00;
+ m_afSubd[2] = 0;
+ if (fM02 != (Type)0.0)
+ {
+ Type fLength = (REAL)sqrt(fM01*fM01+fM02*fM02);
+ Type fInvLength = ((Type)1.0)/fLength;
+ fM01 *= fInvLength;
+ fM02 *= fInvLength;
+ Type fQ = ((Type)2.0)*fM01*fM12+fM02*(fM22-fM11);
+ m_afDiag[1] = fM11+fM02*fQ;
+ m_afDiag[2] = fM22-fM02*fQ;
+ m_afSubd[0] = fLength;
+ m_afSubd[1] = fM12-fM01*fQ;
+ mElement[0][0] = (Type)1.0;
+ mElement[0][1] = (Type)0.0;
+ mElement[0][2] = (Type)0.0;
+ mElement[1][0] = (Type)0.0;
+ mElement[1][1] = fM01;
+ mElement[1][2] = fM02;
+ mElement[2][0] = (Type)0.0;
+ mElement[2][1] = fM02;
+ mElement[2][2] = -fM01;
+ m_bIsRotation = false;
+ }
+ else
+ {
+ m_afDiag[1] = fM11;
+ m_afDiag[2] = fM22;
+ m_afSubd[0] = fM01;
+ m_afSubd[1] = fM12;
+ mElement[0][0] = (Type)1.0;
+ mElement[0][1] = (Type)0.0;
+ mElement[0][2] = (Type)0.0;
+ mElement[1][0] = (Type)0.0;
+ mElement[1][1] = (Type)1.0;
+ mElement[1][2] = (Type)0.0;
+ mElement[2][0] = (Type)0.0;
+ mElement[2][1] = (Type)0.0;
+ mElement[2][2] = (Type)1.0;
+ m_bIsRotation = true;
+ }
+ }
+
+ bool QLAlgorithm(void)
+ {
+ const int32_t iMaxIter = 32;
+
+ for (int32_t i0 = 0; i0 <3; i0++)
+ {
+ int32_t i1;
+ for (i1 = 0; i1 < iMaxIter; i1++)
+ {
+ int32_t i2;
+ for (i2 = i0; i2 <= (3-2); i2++)
+ {
+ Type fTmp = fabs(m_afDiag[i2]) + fabs(m_afDiag[i2+1]);
+ if ( fabs(m_afSubd[i2]) + fTmp == fTmp )
+ break;
+ }
+ if (i2 == i0)
+ {
+ break;
+ }
+
+ Type fG = (m_afDiag[i0+1] - m_afDiag[i0])/(((Type)2.0) * m_afSubd[i0]);
+ Type fR = (REAL)sqrt(fG*fG+(Type)1.0);
+ if (fG < (Type)0.0)
+ {
+ fG = m_afDiag[i2]-m_afDiag[i0]+m_afSubd[i0]/(fG-fR);
+ }
+ else
+ {
+ fG = m_afDiag[i2]-m_afDiag[i0]+m_afSubd[i0]/(fG+fR);
+ }
+ Type fSin = (Type)1.0, fCos = (Type)1.0, fP = (Type)0.0;
+ for (int32_t i3 = i2-1; i3 >= i0; i3--)
+ {
+ Type fF = fSin*m_afSubd[i3];
+ Type fB = fCos*m_afSubd[i3];
+ if (fabs(fF) >= fabs(fG))
+ {
+ fCos = fG/fF;
+ fR = (REAL)sqrt(fCos*fCos+(Type)1.0);
+ m_afSubd[i3+1] = fF*fR;
+ fSin = ((Type)1.0)/fR;
+ fCos *= fSin;
+ }
+ else
+ {
+ fSin = fF/fG;
+ fR = (REAL)sqrt(fSin*fSin+(Type)1.0);
+ m_afSubd[i3+1] = fG*fR;
+ fCos = ((Type)1.0)/fR;
+ fSin *= fCos;
+ }
+ fG = m_afDiag[i3+1]-fP;
+ fR = (m_afDiag[i3]-fG)*fSin+((Type)2.0)*fB*fCos;
+ fP = fSin*fR;
+ m_afDiag[i3+1] = fG+fP;
+ fG = fCos*fR-fB;
+ for (int32_t i4 = 0; i4 < 3; i4++)
+ {
+ fF = mElement[i4][i3+1];
+ mElement[i4][i3+1] = fSin*mElement[i4][i3]+fCos*fF;
+ mElement[i4][i3] = fCos*mElement[i4][i3]-fSin*fF;
+ }
+ }
+ m_afDiag[i0] -= fP;
+ m_afSubd[i0] = fG;
+ m_afSubd[i2] = (Type)0.0;
+ }
+ if (i1 == iMaxIter)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ void DecreasingSort(void)
+ {
+ //sort eigenvalues in decreasing order, e[0] >= ... >= e[iSize-1]
+ for (int32_t i0 = 0, i1; i0 <= 3-2; i0++)
+ {
+ // locate maximum eigenvalue
+ i1 = i0;
+ Type fMax = m_afDiag[i1];
+ int32_t i2;
+ for (i2 = i0+1; i2 < 3; i2++)
+ {
+ if (m_afDiag[i2] > fMax)
+ {
+ i1 = i2;
+ fMax = m_afDiag[i1];
+ }
+ }
+
+ if (i1 != i0)
+ {
+ // swap eigenvalues
+ m_afDiag[i1] = m_afDiag[i0];
+ m_afDiag[i0] = fMax;
+ // swap eigenvectors
+ for (i2 = 0; i2 < 3; i2++)
+ {
+ Type fTmp = mElement[i2][i0];
+ mElement[i2][i0] = mElement[i2][i1];
+ mElement[i2][i1] = fTmp;
+ m_bIsRotation = !m_bIsRotation;
+ }
+ }
+ }
+ }
+
+
+ void GuaranteeRotation(void)
+ {
+ if (!m_bIsRotation)
+ {
+ // change sign on the first column
+ for (int32_t iRow = 0; iRow <3; iRow++)
+ {
+ mElement[iRow][0] = -mElement[iRow][0];
+ }
+ }
+ }
+
+ Type mElement[3][3];
+ Type m_afDiag[3];
+ Type m_afSubd[3];
+ bool m_bIsRotation;
+};
+
+#endif
+
+bool fm_computeBestFitPlane(uint32_t vcount,
+ const REAL *points,
+ uint32_t vstride,
+ const REAL *weights,
+ uint32_t wstride,
+ REAL *plane,
+ REAL *center)
+{
+ bool ret = false;
+
+ REAL kOrigin[3] = { 0, 0, 0 };
+
+ REAL wtotal = 0;
+
+ {
+ const char *source = (const char *) points;
+ const char *wsource = (const char *) weights;
+
+ for (uint32_t i=0; i<vcount; i++)
+ {
+
+ const REAL *p = (const REAL *) source;
+
+ REAL w = 1;
+
+ if ( wsource )
+ {
+ const REAL *ws = (const REAL *) wsource;
+ w = *ws; //
+ wsource+=wstride;
+ }
+
+ kOrigin[0]+=p[0]*w;
+ kOrigin[1]+=p[1]*w;
+ kOrigin[2]+=p[2]*w;
+
+ wtotal+=w;
+
+ source+=vstride;
+ }
+ }
+
+ REAL recip = 1.0f / wtotal; // reciprocol of total weighting
+
+ kOrigin[0]*=recip;
+ kOrigin[1]*=recip;
+ kOrigin[2]*=recip;
+
+ center[0] = kOrigin[0];
+ center[1] = kOrigin[1];
+ center[2] = kOrigin[2];
+
+
+ REAL fSumXX=0;
+ REAL fSumXY=0;
+ REAL fSumXZ=0;
+
+ REAL fSumYY=0;
+ REAL fSumYZ=0;
+ REAL fSumZZ=0;
+
+
+ {
+ const char *source = (const char *) points;
+ const char *wsource = (const char *) weights;
+
+ for (uint32_t i=0; i<vcount; i++)
+ {
+
+ const REAL *p = (const REAL *) source;
+
+ REAL w = 1;
+
+ if ( wsource )
+ {
+ const REAL *ws = (const REAL *) wsource;
+ w = *ws; //
+ wsource+=wstride;
+ }
+
+ REAL kDiff[3];
+
+ kDiff[0] = w*(p[0] - kOrigin[0]); // apply vertex weighting!
+ kDiff[1] = w*(p[1] - kOrigin[1]);
+ kDiff[2] = w*(p[2] - kOrigin[2]);
+
+ fSumXX+= kDiff[0] * kDiff[0]; // sume of the squares of the differences.
+ fSumXY+= kDiff[0] * kDiff[1]; // sume of the squares of the differences.
+ fSumXZ+= kDiff[0] * kDiff[2]; // sume of the squares of the differences.
+
+ fSumYY+= kDiff[1] * kDiff[1];
+ fSumYZ+= kDiff[1] * kDiff[2];
+ fSumZZ+= kDiff[2] * kDiff[2];
+
+
+ source+=vstride;
+ }
+ }
+
+ fSumXX *= recip;
+ fSumXY *= recip;
+ fSumXZ *= recip;
+ fSumYY *= recip;
+ fSumYZ *= recip;
+ fSumZZ *= recip;
+
+ // setup the eigensolver
+ Eigen<REAL> kES;
+
+ kES.mElement[0][0] = fSumXX;
+ kES.mElement[0][1] = fSumXY;
+ kES.mElement[0][2] = fSumXZ;
+
+ kES.mElement[1][0] = fSumXY;
+ kES.mElement[1][1] = fSumYY;
+ kES.mElement[1][2] = fSumYZ;
+
+ kES.mElement[2][0] = fSumXZ;
+ kES.mElement[2][1] = fSumYZ;
+ kES.mElement[2][2] = fSumZZ;
+
+ // compute eigenstuff, smallest eigenvalue is in last position
+ kES.DecrSortEigenStuff();
+
+ REAL kNormal[3];
+
+ kNormal[0] = kES.mElement[0][2];
+ kNormal[1] = kES.mElement[1][2];
+ kNormal[2] = kES.mElement[2][2];
+
+ // the minimum energy
+ plane[0] = kNormal[0];
+ plane[1] = kNormal[1];
+ plane[2] = kNormal[2];
+
+ plane[3] = 0 - fm_dot(kNormal,kOrigin);
+
+ ret = true;
+
+ return ret;
+}
+
+
+bool fm_colinear(const REAL a1[3],const REAL a2[3],const REAL b1[3],const REAL b2[3],REAL epsilon) // true if these two line segments are co-linear.
+{
+ bool ret = false;
+
+ REAL dir1[3];
+ REAL dir2[3];
+
+ dir1[0] = (a2[0] - a1[0]);
+ dir1[1] = (a2[1] - a1[1]);
+ dir1[2] = (a2[2] - a1[2]);
+
+ dir2[0] = (b2[0]-a1[0]) - (b1[0]-a1[0]);
+ dir2[1] = (b2[1]-a1[1]) - (b1[1]-a1[1]);
+ dir2[2] = (b2[2]-a2[2]) - (b1[2]-a2[2]);
+
+ fm_normalize(dir1);
+ fm_normalize(dir2);
+
+ REAL dot = fm_dot(dir1,dir2);
+
+ if ( dot >= epsilon )
+ {
+ ret = true;
+ }
+
+
+ return ret;
+}
+
+bool fm_colinear(const REAL *p1,const REAL *p2,const REAL *p3,REAL epsilon)
+{
+ bool ret = false;
+
+ REAL dir1[3];
+ REAL dir2[3];
+
+ dir1[0] = p2[0] - p1[0];
+ dir1[1] = p2[1] - p1[1];
+ dir1[2] = p2[2] - p1[2];
+
+ dir2[0] = p3[0] - p2[0];
+ dir2[1] = p3[1] - p2[1];
+ dir2[2] = p3[2] - p2[2];
+
+ fm_normalize(dir1);
+ fm_normalize(dir2);
+
+ REAL dot = fm_dot(dir1,dir2);
+
+ if ( dot >= epsilon )
+ {
+ ret = true;
+ }
+
+
+ return ret;
+}
+
+void fm_initMinMax(const REAL *p,REAL *bmin,REAL *bmax)
+{
+ bmax[0] = bmin[0] = p[0];
+ bmax[1] = bmin[1] = p[1];
+ bmax[2] = bmin[2] = p[2];
+}
+
+IntersectResult fm_intersectLineSegments2d(const REAL *a1,const REAL *a2,const REAL *b1,const REAL *b2,REAL *intersection)
+{
+ IntersectResult ret;
+
+ REAL denom = ((b2[1] - b1[1])*(a2[0] - a1[0])) - ((b2[0] - b1[0])*(a2[1] - a1[1]));
+ REAL nume_a = ((b2[0] - b1[0])*(a1[1] - b1[1])) - ((b2[1] - b1[1])*(a1[0] - b1[0]));
+ REAL nume_b = ((a2[0] - a1[0])*(a1[1] - b1[1])) - ((a2[1] - a1[1])*(a1[0] - b1[0]));
+ if (denom == 0 )
+ {
+ if(nume_a == 0 && nume_b == 0)
+ {
+ ret = IR_COINCIDENT;
+ }
+ else
+ {
+ ret = IR_PARALLEL;
+ }
+ }
+ else
+ {
+
+ REAL recip = 1 / denom;
+ REAL ua = nume_a * recip;
+ REAL ub = nume_b * recip;
+
+ if(ua >= 0 && ua <= 1 && ub >= 0 && ub <= 1 )
+ {
+ // Get the intersection point.
+ intersection[0] = a1[0] + ua*(a2[0] - a1[0]);
+ intersection[1] = a1[1] + ua*(a2[1] - a1[1]);
+ ret = IR_DO_INTERSECT;
+ }
+ else
+ {
+ ret = IR_DONT_INTERSECT;
+ }
+ }
+ return ret;
+}
+
+IntersectResult fm_intersectLineSegments2dTime(const REAL *a1,const REAL *a2,const REAL *b1,const REAL *b2,REAL &t1,REAL &t2)
+{
+ IntersectResult ret;
+
+ REAL denom = ((b2[1] - b1[1])*(a2[0] - a1[0])) - ((b2[0] - b1[0])*(a2[1] - a1[1]));
+ REAL nume_a = ((b2[0] - b1[0])*(a1[1] - b1[1])) - ((b2[1] - b1[1])*(a1[0] - b1[0]));
+ REAL nume_b = ((a2[0] - a1[0])*(a1[1] - b1[1])) - ((a2[1] - a1[1])*(a1[0] - b1[0]));
+ if (denom == 0 )
+ {
+ if(nume_a == 0 && nume_b == 0)
+ {
+ ret = IR_COINCIDENT;
+ }
+ else
+ {
+ ret = IR_PARALLEL;
+ }
+ }
+ else
+ {
+
+ REAL recip = 1 / denom;
+ REAL ua = nume_a * recip;
+ REAL ub = nume_b * recip;
+
+ if(ua >= 0 && ua <= 1 && ub >= 0 && ub <= 1 )
+ {
+ t1 = ua;
+ t2 = ub;
+ ret = IR_DO_INTERSECT;
+ }
+ else
+ {
+ ret = IR_DONT_INTERSECT;
+ }
+ }
+ return ret;
+}
+
+//**** Plane Triangle Intersection
+
+
+
+
+
+// assumes that the points are on opposite sides of the plane!
+bool fm_intersectPointPlane(const REAL *p1,const REAL *p2,REAL *split,const REAL *plane)
+{
+
+ REAL dp1 = fm_distToPlane(plane,p1);
+ REAL dp2 = fm_distToPlane(plane, p2);
+ if (dp1 <= 0 && dp2 <= 0)
+ {
+ return false;
+ }
+ if (dp1 >= 0 && dp2 >= 0)
+ {
+ return false;
+ }
+
+ REAL dir[3];
+
+ dir[0] = p2[0] - p1[0];
+ dir[1] = p2[1] - p1[1];
+ dir[2] = p2[2] - p1[2];
+
+ REAL dot1 = dir[0]*plane[0] + dir[1]*plane[1] + dir[2]*plane[2];
+ REAL dot2 = dp1 - plane[3];
+
+ REAL t = -(plane[3] + dot2 ) / dot1;
+
+ split[0] = (dir[0]*t)+p1[0];
+ split[1] = (dir[1]*t)+p1[1];
+ split[2] = (dir[2]*t)+p1[2];
+
+ return true;
+}
+
+PlaneTriResult fm_getSidePlane(const REAL *p,const REAL *plane,REAL epsilon)
+{
+ PlaneTriResult ret = PTR_ON_PLANE;
+
+ REAL d = fm_distToPlane(plane,p);
+
+ if ( d < -epsilon || d > epsilon )
+ {
+ if ( d > 0 )
+ ret = PTR_FRONT; // it is 'in front' within the provided epsilon value.
+ else
+ ret = PTR_BACK;
+ }
+
+ return ret;
+}
+
+
+
+#ifndef PLANE_TRIANGLE_INTERSECTION_H
+
+#define PLANE_TRIANGLE_INTERSECTION_H
+
+#define MAXPTS 256
+
+template <class Type> class point
+{
+public:
+
+ void set(const Type *p)
+ {
+ x = p[0];
+ y = p[1];
+ z = p[2];
+ }
+
+ Type x;
+ Type y;
+ Type z;
+};
+
+template <class Type> class plane
+{
+public:
+ plane(const Type *p)
+ {
+ normal.x = p[0];
+ normal.y = p[1];
+ normal.z = p[2];
+ D = p[3];
+ }
+
+ Type Classify_Point(const point<Type> &p)
+ {
+ return p.x*normal.x + p.y*normal.y + p.z*normal.z + D;
+ }
+
+ point<Type> normal;
+ Type D;
+};
+
+template <class Type> class polygon
+{
+public:
+ polygon(void)
+ {
+ mVcount = 0;
+ }
+
+ polygon(const Type *p1,const Type *p2,const Type *p3)
+ {
+ mVcount = 3;
+ mVertices[0].set(p1);
+ mVertices[1].set(p2);
+ mVertices[2].set(p3);
+ }
+
+
+ int32_t NumVertices(void) const { return mVcount; };
+
+ const point<Type>& Vertex(int32_t index)
+ {
+ if ( index < 0 ) index+=mVcount;
+ return mVertices[index];
+ };
+
+
+ void set(const point<Type> *pts,int32_t count)
+ {
+ for (int32_t i=0; i<count; i++)
+ {
+ mVertices[i] = pts[i];
+ }
+ mVcount = count;
+ }
+
+
+ void Split_Polygon(polygon<Type> *poly,plane<Type> *part, polygon<Type> &front, polygon<Type> &back)
+ {
+ int32_t count = poly->NumVertices ();
+ int32_t out_c = 0, in_c = 0;
+ point<Type> ptA, ptB,outpts[MAXPTS],inpts[MAXPTS];
+ Type sideA, sideB;
+ ptA = poly->Vertex (count - 1);
+ sideA = part->Classify_Point (ptA);
+ for (int32_t i = -1; ++i < count;)
+ {
+ ptB = poly->Vertex(i);
+ sideB = part->Classify_Point(ptB);
+ if (sideB > 0)
+ {
+ if (sideA < 0)
+ {
+ point<Type> v;
+ fm_intersectPointPlane(&ptB.x, &ptA.x, &v.x, &part->normal.x );
+ outpts[out_c++] = inpts[in_c++] = v;
+ }
+ outpts[out_c++] = ptB;
+ }
+ else if (sideB < 0)
+ {
+ if (sideA > 0)
+ {
+ point<Type> v;
+ fm_intersectPointPlane(&ptB.x, &ptA.x, &v.x, &part->normal.x );
+ outpts[out_c++] = inpts[in_c++] = v;
+ }
+ inpts[in_c++] = ptB;
+ }
+ else
+ outpts[out_c++] = inpts[in_c++] = ptB;
+ ptA = ptB;
+ sideA = sideB;
+ }
+
+ front.set(&outpts[0], out_c);
+ back.set(&inpts[0], in_c);
+ }
+
+ int32_t mVcount;
+ point<Type> mVertices[MAXPTS];
+};
+
+
+
+#endif
+
+static inline void add(const REAL *p,REAL *dest,uint32_t tstride,uint32_t &pcount)
+{
+ char *d = (char *) dest;
+ d = d + pcount*tstride;
+ dest = (REAL *) d;
+ dest[0] = p[0];
+ dest[1] = p[1];
+ dest[2] = p[2];
+ pcount++;
+ assert( pcount <= 4 );
+}
+
+
+PlaneTriResult fm_planeTriIntersection(const REAL *_plane, // the plane equation in Ax+By+Cz+D format
+ const REAL *triangle, // the source triangle.
+ uint32_t tstride, // stride in bytes of the input and output *vertices*
+ REAL epsilon, // the co-planar epsilon value.
+ REAL *front, // the triangle in front of the
+ uint32_t &fcount, // number of vertices in the 'front' triangle
+ REAL *back, // the triangle in back of the plane
+ uint32_t &bcount) // the number of vertices in the 'back' triangle.
+{
+
+ fcount = 0;
+ bcount = 0;
+
+ const char *tsource = (const char *) triangle;
+
+ // get the three vertices of the triangle.
+ const REAL *p1 = (const REAL *) (tsource);
+ const REAL *p2 = (const REAL *) (tsource+tstride);
+ const REAL *p3 = (const REAL *) (tsource+tstride*2);
+
+
+ PlaneTriResult r1 = fm_getSidePlane(p1,_plane,epsilon); // compute the side of the plane each vertex is on
+ PlaneTriResult r2 = fm_getSidePlane(p2,_plane,epsilon);
+ PlaneTriResult r3 = fm_getSidePlane(p3,_plane,epsilon);
+
+ // If any of the points lay right *on* the plane....
+ if ( r1 == PTR_ON_PLANE || r2 == PTR_ON_PLANE || r3 == PTR_ON_PLANE )
+ {
+ // If the triangle is completely co-planar, then just treat it as 'front' and return!
+ if ( r1 == PTR_ON_PLANE && r2 == PTR_ON_PLANE && r3 == PTR_ON_PLANE )
+ {
+ add(p1,front,tstride,fcount);
+ add(p2,front,tstride,fcount);
+ add(p3,front,tstride,fcount);
+ return PTR_FRONT;
+ }
+ // Decide to place the co-planar points on the same side as the co-planar point.
+ PlaneTriResult r= PTR_ON_PLANE;
+ if ( r1 != PTR_ON_PLANE )
+ r = r1;
+ else if ( r2 != PTR_ON_PLANE )
+ r = r2;
+ else if ( r3 != PTR_ON_PLANE )
+ r = r3;
+
+ if ( r1 == PTR_ON_PLANE ) r1 = r;
+ if ( r2 == PTR_ON_PLANE ) r2 = r;
+ if ( r3 == PTR_ON_PLANE ) r3 = r;
+
+ }
+
+ if ( r1 == r2 && r1 == r3 ) // if all three vertices are on the same side of the plane.
+ {
+ if ( r1 == PTR_FRONT ) // if all three are in front of the plane, then copy to the 'front' output triangle.
+ {
+ add(p1,front,tstride,fcount);
+ add(p2,front,tstride,fcount);
+ add(p3,front,tstride,fcount);
+ }
+ else
+ {
+ add(p1,back,tstride,bcount); // if all three are in 'back' then copy to the 'back' output triangle.
+ add(p2,back,tstride,bcount);
+ add(p3,back,tstride,bcount);
+ }
+ return r1; // if all three points are on the same side of the plane return result
+ }
+
+
+ polygon<REAL> pi(p1,p2,p3);
+ polygon<REAL> pfront,pback;
+
+ plane<REAL> part(_plane);
+
+ pi.Split_Polygon(&pi,&part,pfront,pback);
+
+ for (int32_t i=0; i<pfront.mVcount; i++)
+ {
+ add( &pfront.mVertices[i].x, front, tstride, fcount );
+ }
+
+ for (int32_t i=0; i<pback.mVcount; i++)
+ {
+ add( &pback.mVertices[i].x, back, tstride, bcount );
+ }
+
+ PlaneTriResult ret = PTR_SPLIT;
+
+ if ( fcount < 3 ) fcount = 0;
+ if ( bcount < 3 ) bcount = 0;
+
+ if ( fcount == 0 && bcount )
+ ret = PTR_BACK;
+
+ if ( bcount == 0 && fcount )
+ ret = PTR_FRONT;
+
+
+ return ret;
+}
+
+// computes the OBB for this set of points relative to this transform matrix.
+void computeOBB(uint32_t vcount,const REAL *points,uint32_t pstride,REAL *sides,REAL *matrix)
+{
+ const char *src = (const char *) points;
+
+ REAL bmin[3] = { 1e9, 1e9, 1e9 };
+ REAL bmax[3] = { -1e9, -1e9, -1e9 };
+
+ for (uint32_t i=0; i<vcount; i++)
+ {
+ const REAL *p = (const REAL *) src;
+ REAL t[3];
+
+ fm_inverseRT(matrix, p, t ); // inverse rotate translate
+
+ if ( t[0] < bmin[0] ) bmin[0] = t[0];
+ if ( t[1] < bmin[1] ) bmin[1] = t[1];
+ if ( t[2] < bmin[2] ) bmin[2] = t[2];
+
+ if ( t[0] > bmax[0] ) bmax[0] = t[0];
+ if ( t[1] > bmax[1] ) bmax[1] = t[1];
+ if ( t[2] > bmax[2] ) bmax[2] = t[2];
+
+ src+=pstride;
+ }
+
+ REAL center[3];
+
+ sides[0] = bmax[0]-bmin[0];
+ sides[1] = bmax[1]-bmin[1];
+ sides[2] = bmax[2]-bmin[2];
+
+ center[0] = sides[0]*0.5f+bmin[0];
+ center[1] = sides[1]*0.5f+bmin[1];
+ center[2] = sides[2]*0.5f+bmin[2];
+
+ REAL ocenter[3];
+
+ fm_rotate(matrix,center,ocenter);
+
+ matrix[12]+=ocenter[0];
+ matrix[13]+=ocenter[1];
+ matrix[14]+=ocenter[2];
+
+}
+
+void fm_computeBestFitOBB(uint32_t vcount,const REAL *points,uint32_t pstride,REAL *sides,REAL *matrix,bool bruteForce)
+{
+ REAL plane[4];
+ REAL center[3];
+ fm_computeBestFitPlane(vcount,points,pstride,0,0,plane,center);
+ fm_planeToMatrix(plane,matrix);
+ computeOBB( vcount, points, pstride, sides, matrix );
+
+ REAL refmatrix[16];
+ memcpy(refmatrix,matrix,16*sizeof(REAL));
+
+ REAL volume = sides[0]*sides[1]*sides[2];
+ if ( bruteForce )
+ {
+ for (REAL a=10; a<180; a+=10)
+ {
+ REAL quat[4];
+ fm_eulerToQuat(0,a*FM_DEG_TO_RAD,0,quat);
+ REAL temp[16];
+ REAL pmatrix[16];
+ fm_quatToMatrix(quat,temp);
+ fm_matrixMultiply(temp,refmatrix,pmatrix);
+ REAL psides[3];
+ computeOBB( vcount, points, pstride, psides, pmatrix );
+ REAL v = psides[0]*psides[1]*psides[2];
+ if ( v < volume )
+ {
+ volume = v;
+ memcpy(matrix,pmatrix,sizeof(REAL)*16);
+ sides[0] = psides[0];
+ sides[1] = psides[1];
+ sides[2] = psides[2];
+ }
+ }
+ }
+}
+
+void fm_computeBestFitOBB(uint32_t vcount,const REAL *points,uint32_t pstride,REAL *sides,REAL *pos,REAL *quat,bool bruteForce)
+{
+ REAL matrix[16];
+ fm_computeBestFitOBB(vcount,points,pstride,sides,matrix,bruteForce);
+ fm_getTranslation(matrix,pos);
+ fm_matrixToQuat(matrix,quat);
+}
+
+void fm_computeBestFitABB(uint32_t vcount,const REAL *points,uint32_t pstride,REAL *sides,REAL *pos)
+{
+ REAL bmin[3];
+ REAL bmax[3];
+
+ bmin[0] = points[0];
+ bmin[1] = points[1];
+ bmin[2] = points[2];
+
+ bmax[0] = points[0];
+ bmax[1] = points[1];
+ bmax[2] = points[2];
+
+ const char *cp = (const char *) points;
+ for (uint32_t i=0; i<vcount; i++)
+ {
+ const REAL *p = (const REAL *) cp;
+
+ if ( p[0] < bmin[0] ) bmin[0] = p[0];
+ if ( p[1] < bmin[1] ) bmin[1] = p[1];
+ if ( p[2] < bmin[2] ) bmin[2] = p[2];
+
+ if ( p[0] > bmax[0] ) bmax[0] = p[0];
+ if ( p[1] > bmax[1] ) bmax[1] = p[1];
+ if ( p[2] > bmax[2] ) bmax[2] = p[2];
+
+ cp+=pstride;
+ }
+
+
+ sides[0] = bmax[0] - bmin[0];
+ sides[1] = bmax[1] - bmin[1];
+ sides[2] = bmax[2] - bmin[2];
+
+ pos[0] = bmin[0]+sides[0]*0.5f;
+ pos[1] = bmin[1]+sides[1]*0.5f;
+ pos[2] = bmin[2]+sides[2]*0.5f;
+
+}
+
+
+void fm_planeToMatrix(const REAL *plane,REAL *matrix) // convert a plane equation to a 4x4 rotation matrix
+{
+ REAL ref[3] = { 0, 1, 0 };
+ REAL quat[4];
+ fm_rotationArc(ref,plane,quat);
+ fm_quatToMatrix(quat,matrix);
+ REAL origin[3] = { 0, -plane[3], 0 };
+ REAL center[3];
+ fm_transform(matrix,origin,center);
+ fm_setTranslation(center,matrix);
+}
+
+void fm_planeToQuat(const REAL *plane,REAL *quat,REAL *pos) // convert a plane equation to a quaternion and translation
+{
+ REAL ref[3] = { 0, 1, 0 };
+ REAL matrix[16];
+ fm_rotationArc(ref,plane,quat);
+ fm_quatToMatrix(quat,matrix);
+ REAL origin[3] = { 0, plane[3], 0 };
+ fm_transform(matrix,origin,pos);
+}
+
+void fm_eulerMatrix(REAL ax,REAL ay,REAL az,REAL *matrix) // convert euler (in radians) to a dest 4x4 matrix (translation set to zero)
+{
+ REAL quat[4];
+ fm_eulerToQuat(ax,ay,az,quat);
+ fm_quatToMatrix(quat,matrix);
+}
+
+
+//**********************************************************
+//**********************************************************
+//**** Vertex Welding
+//**********************************************************
+//**********************************************************
+
+#ifndef VERTEX_INDEX_H
+
+#define VERTEX_INDEX_H
+
+namespace VERTEX_INDEX
+{
+
+class KdTreeNode;
+
+typedef std::vector< KdTreeNode * > KdTreeNodeVector;
+
+enum Axes
+{
+ X_AXIS = 0,
+ Y_AXIS = 1,
+ Z_AXIS = 2
+};
+
+class KdTreeFindNode
+{
+public:
+ KdTreeFindNode(void)
+ {
+ mNode = 0;
+ mDistance = 0;
+ }
+ KdTreeNode *mNode;
+ double mDistance;
+};
+
+class KdTreeInterface
+{
+public:
+ virtual const double * getPositionDouble(uint32_t index) const = 0;
+ virtual const float * getPositionFloat(uint32_t index) const = 0;
+};
+
+class KdTreeNode
+{
+public:
+ KdTreeNode(void)
+ {
+ mIndex = 0;
+ mLeft = 0;
+ mRight = 0;
+ }
+
+ KdTreeNode(uint32_t index)
+ {
+ mIndex = index;
+ mLeft = 0;
+ mRight = 0;
+ };
+
+ ~KdTreeNode(void)
+ {
+ }
+
+
+ void addDouble(KdTreeNode *node,Axes dim,const KdTreeInterface *iface)
+ {
+ const double *nodePosition = iface->getPositionDouble( node->mIndex );
+ const double *position = iface->getPositionDouble( mIndex );
+ switch ( dim )
+ {
+ case X_AXIS:
+ if ( nodePosition[0] <= position[0] )
+ {
+ if ( mLeft )
+ mLeft->addDouble(node,Y_AXIS,iface);
+ else
+ mLeft = node;
+ }
+ else
+ {
+ if ( mRight )
+ mRight->addDouble(node,Y_AXIS,iface);
+ else
+ mRight = node;
+ }
+ break;
+ case Y_AXIS:
+ if ( nodePosition[1] <= position[1] )
+ {
+ if ( mLeft )
+ mLeft->addDouble(node,Z_AXIS,iface);
+ else
+ mLeft = node;
+ }
+ else
+ {
+ if ( mRight )
+ mRight->addDouble(node,Z_AXIS,iface);
+ else
+ mRight = node;
+ }
+ break;
+ case Z_AXIS:
+ if ( nodePosition[2] <= position[2] )
+ {
+ if ( mLeft )
+ mLeft->addDouble(node,X_AXIS,iface);
+ else
+ mLeft = node;
+ }
+ else
+ {
+ if ( mRight )
+ mRight->addDouble(node,X_AXIS,iface);
+ else
+ mRight = node;
+ }
+ break;
+ }
+
+ }
+
+
+ void addFloat(KdTreeNode *node,Axes dim,const KdTreeInterface *iface)
+ {
+ const float *nodePosition = iface->getPositionFloat( node->mIndex );
+ const float *position = iface->getPositionFloat( mIndex );
+ switch ( dim )
+ {
+ case X_AXIS:
+ if ( nodePosition[0] <= position[0] )
+ {
+ if ( mLeft )
+ mLeft->addFloat(node,Y_AXIS,iface);
+ else
+ mLeft = node;
+ }
+ else
+ {
+ if ( mRight )
+ mRight->addFloat(node,Y_AXIS,iface);
+ else
+ mRight = node;
+ }
+ break;
+ case Y_AXIS:
+ if ( nodePosition[1] <= position[1] )
+ {
+ if ( mLeft )
+ mLeft->addFloat(node,Z_AXIS,iface);
+ else
+ mLeft = node;
+ }
+ else
+ {
+ if ( mRight )
+ mRight->addFloat(node,Z_AXIS,iface);
+ else
+ mRight = node;
+ }
+ break;
+ case Z_AXIS:
+ if ( nodePosition[2] <= position[2] )
+ {
+ if ( mLeft )
+ mLeft->addFloat(node,X_AXIS,iface);
+ else
+ mLeft = node;
+ }
+ else
+ {
+ if ( mRight )
+ mRight->addFloat(node,X_AXIS,iface);
+ else
+ mRight = node;
+ }
+ break;
+ }
+
+ }
+
+
+ uint32_t getIndex(void) const { return mIndex; };
+
+ void search(Axes axis,const double *pos,double radius,uint32_t &count,uint32_t maxObjects,KdTreeFindNode *found,const KdTreeInterface *iface)
+ {
+
+ const double *position = iface->getPositionDouble(mIndex);
+
+ double dx = pos[0] - position[0];
+ double dy = pos[1] - position[1];
+ double dz = pos[2] - position[2];
+
+ KdTreeNode *search1 = 0;
+ KdTreeNode *search2 = 0;
+
+ switch ( axis )
+ {
+ case X_AXIS:
+ if ( dx <= 0 ) // JWR if we are to the left
+ {
+ search1 = mLeft; // JWR then search to the left
+ if ( -dx < radius ) // JWR if distance to the right is less than our search radius, continue on the right as well.
+ search2 = mRight;
+ }
+ else
+ {
+ search1 = mRight; // JWR ok, we go down the left tree
+ if ( dx < radius ) // JWR if the distance from the right is less than our search radius
+ search2 = mLeft;
+ }
+ axis = Y_AXIS;
+ break;
+ case Y_AXIS:
+ if ( dy <= 0 )
+ {
+ search1 = mLeft;
+ if ( -dy < radius )
+ search2 = mRight;
+ }
+ else
+ {
+ search1 = mRight;
+ if ( dy < radius )
+ search2 = mLeft;
+ }
+ axis = Z_AXIS;
+ break;
+ case Z_AXIS:
+ if ( dz <= 0 )
+ {
+ search1 = mLeft;
+ if ( -dz < radius )
+ search2 = mRight;
+ }
+ else
+ {
+ search1 = mRight;
+ if ( dz < radius )
+ search2 = mLeft;
+ }
+ axis = X_AXIS;
+ break;
+ }
+
+ double r2 = radius*radius;
+ double m = dx*dx+dy*dy+dz*dz;
+
+ if ( m < r2 )
+ {
+ switch ( count )
+ {
+ case 0:
+ found[count].mNode = this;
+ found[count].mDistance = m;
+ break;
+ case 1:
+ if ( m < found[0].mDistance )
+ {
+ if ( maxObjects == 1 )
+ {
+ found[0].mNode = this;
+ found[0].mDistance = m;
+ }
+ else
+ {
+ found[1] = found[0];
+ found[0].mNode = this;
+ found[0].mDistance = m;
+ }
+ }
+ else if ( maxObjects > 1)
+ {
+ found[1].mNode = this;
+ found[1].mDistance = m;
+ }
+ break;
+ default:
+ {
+ bool inserted = false;
+
+ for (uint32_t i=0; i<count; i++)
+ {
+ if ( m < found[i].mDistance ) // if this one is closer than a pre-existing one...
+ {
+ // insertion sort...
+ uint32_t scan = count;
+ if ( scan >= maxObjects ) scan=maxObjects-1;
+ for (uint32_t j=scan; j>i; j--)
+ {
+ found[j] = found[j-1];
+ }
+ found[i].mNode = this;
+ found[i].mDistance = m;
+ inserted = true;
+ break;
+ }
+ }
+
+ if ( !inserted && count < maxObjects )
+ {
+ found[count].mNode = this;
+ found[count].mDistance = m;
+ }
+ }
+ break;
+ }
+ count++;
+ if ( count > maxObjects )
+ {
+ count = maxObjects;
+ }
+ }
+
+
+ if ( search1 )
+ search1->search( axis, pos,radius, count, maxObjects, found, iface);
+
+ if ( search2 )
+ search2->search( axis, pos,radius, count, maxObjects, found, iface);
+
+ }
+
+ void search(Axes axis,const float *pos,float radius,uint32_t &count,uint32_t maxObjects,KdTreeFindNode *found,const KdTreeInterface *iface)
+ {
+
+ const float *position = iface->getPositionFloat(mIndex);
+
+ float dx = pos[0] - position[0];
+ float dy = pos[1] - position[1];
+ float dz = pos[2] - position[2];
+
+ KdTreeNode *search1 = 0;
+ KdTreeNode *search2 = 0;
+
+ switch ( axis )
+ {
+ case X_AXIS:
+ if ( dx <= 0 ) // JWR if we are to the left
+ {
+ search1 = mLeft; // JWR then search to the left
+ if ( -dx < radius ) // JWR if distance to the right is less than our search radius, continue on the right as well.
+ search2 = mRight;
+ }
+ else
+ {
+ search1 = mRight; // JWR ok, we go down the left tree
+ if ( dx < radius ) // JWR if the distance from the right is less than our search radius
+ search2 = mLeft;
+ }
+ axis = Y_AXIS;
+ break;
+ case Y_AXIS:
+ if ( dy <= 0 )
+ {
+ search1 = mLeft;
+ if ( -dy < radius )
+ search2 = mRight;
+ }
+ else
+ {
+ search1 = mRight;
+ if ( dy < radius )
+ search2 = mLeft;
+ }
+ axis = Z_AXIS;
+ break;
+ case Z_AXIS:
+ if ( dz <= 0 )
+ {
+ search1 = mLeft;
+ if ( -dz < radius )
+ search2 = mRight;
+ }
+ else
+ {
+ search1 = mRight;
+ if ( dz < radius )
+ search2 = mLeft;
+ }
+ axis = X_AXIS;
+ break;
+ }
+
+ float r2 = radius*radius;
+ float m = dx*dx+dy*dy+dz*dz;
+
+ if ( m < r2 )
+ {
+ switch ( count )
+ {
+ case 0:
+ found[count].mNode = this;
+ found[count].mDistance = m;
+ break;
+ case 1:
+ if ( m < found[0].mDistance )
+ {
+ if ( maxObjects == 1 )
+ {
+ found[0].mNode = this;
+ found[0].mDistance = m;
+ }
+ else
+ {
+ found[1] = found[0];
+ found[0].mNode = this;
+ found[0].mDistance = m;
+ }
+ }
+ else if ( maxObjects > 1)
+ {
+ found[1].mNode = this;
+ found[1].mDistance = m;
+ }
+ break;
+ default:
+ {
+ bool inserted = false;
+
+ for (uint32_t i=0; i<count; i++)
+ {
+ if ( m < found[i].mDistance ) // if this one is closer than a pre-existing one...
+ {
+ // insertion sort...
+ uint32_t scan = count;
+ if ( scan >= maxObjects ) scan=maxObjects-1;
+ for (uint32_t j=scan; j>i; j--)
+ {
+ found[j] = found[j-1];
+ }
+ found[i].mNode = this;
+ found[i].mDistance = m;
+ inserted = true;
+ break;
+ }
+ }
+
+ if ( !inserted && count < maxObjects )
+ {
+ found[count].mNode = this;
+ found[count].mDistance = m;
+ }
+ }
+ break;
+ }
+ count++;
+ if ( count > maxObjects )
+ {
+ count = maxObjects;
+ }
+ }
+
+
+ if ( search1 )
+ search1->search( axis, pos,radius, count, maxObjects, found, iface);
+
+ if ( search2 )
+ search2->search( axis, pos,radius, count, maxObjects, found, iface);
+
+ }
+
+private:
+
+ void setLeft(KdTreeNode *left) { mLeft = left; };
+ void setRight(KdTreeNode *right) { mRight = right; };
+
+ KdTreeNode *getLeft(void) { return mLeft; }
+ KdTreeNode *getRight(void) { return mRight; }
+
+ uint32_t mIndex;
+ KdTreeNode *mLeft;
+ KdTreeNode *mRight;
+};
+
+
+#define MAX_BUNDLE_SIZE 1024 // 1024 nodes at a time, to minimize memory allocation and guarantee that pointers are persistent.
+
+class KdTreeNodeBundle
+{
+public:
+
+ KdTreeNodeBundle(void)
+ {
+ mNext = 0;
+ mIndex = 0;
+ }
+
+ bool isFull(void) const
+ {
+ return (bool)( mIndex == MAX_BUNDLE_SIZE );
+ }
+
+ KdTreeNode * getNextNode(void)
+ {
+ assert(mIndex<MAX_BUNDLE_SIZE);
+ KdTreeNode *ret = &mNodes[mIndex];
+ mIndex++;
+ return ret;
+ }
+
+ KdTreeNodeBundle *mNext;
+ uint32_t mIndex;
+ KdTreeNode mNodes[MAX_BUNDLE_SIZE];
+};
+
+
+typedef std::vector< double > DoubleVector;
+typedef std::vector< float > FloatVector;
+
+class KdTree : public KdTreeInterface
+{
+public:
+ KdTree(void)
+ {
+ mRoot = 0;
+ mBundle = 0;
+ mVcount = 0;
+ mUseDouble = false;
+ }
+
+ virtual ~KdTree(void)
+ {
+ reset();
+ }
+
+ const double * getPositionDouble(uint32_t index) const
+ {
+ assert( mUseDouble );
+ assert ( index < mVcount );
+ return &mVerticesDouble[index*3];
+ }
+
+ const float * getPositionFloat(uint32_t index) const
+ {
+ assert( !mUseDouble );
+ assert ( index < mVcount );
+ return &mVerticesFloat[index*3];
+ }
+
+ uint32_t search(const double *pos,double radius,uint32_t maxObjects,KdTreeFindNode *found) const
+ {
+ assert( mUseDouble );
+ if ( !mRoot ) return 0;
+ uint32_t count = 0;
+ mRoot->search(X_AXIS,pos,radius,count,maxObjects,found,this);
+ return count;
+ }
+
+ uint32_t search(const float *pos,float radius,uint32_t maxObjects,KdTreeFindNode *found) const
+ {
+ assert( !mUseDouble );
+ if ( !mRoot ) return 0;
+ uint32_t count = 0;
+ mRoot->search(X_AXIS,pos,radius,count,maxObjects,found,this);
+ return count;
+ }
+
+ void reset(void)
+ {
+ mRoot = 0;
+ mVerticesDouble.clear();
+ mVerticesFloat.clear();
+ KdTreeNodeBundle *bundle = mBundle;
+ while ( bundle )
+ {
+ KdTreeNodeBundle *next = bundle->mNext;
+ delete bundle;
+ bundle = next;
+ }
+ mBundle = 0;
+ mVcount = 0;
+ }
+
+ uint32_t add(double x,double y,double z)
+ {
+ assert(mUseDouble);
+ uint32_t ret = mVcount;
+ mVerticesDouble.push_back(x);
+ mVerticesDouble.push_back(y);
+ mVerticesDouble.push_back(z);
+ mVcount++;
+ KdTreeNode *node = getNewNode(ret);
+ if ( mRoot )
+ {
+ mRoot->addDouble(node,X_AXIS,this);
+ }
+ else
+ {
+ mRoot = node;
+ }
+ return ret;
+ }
+
+ uint32_t add(float x,float y,float z)
+ {
+ assert(!mUseDouble);
+ uint32_t ret = mVcount;
+ mVerticesFloat.push_back(x);
+ mVerticesFloat.push_back(y);
+ mVerticesFloat.push_back(z);
+ mVcount++;
+ KdTreeNode *node = getNewNode(ret);
+ if ( mRoot )
+ {
+ mRoot->addFloat(node,X_AXIS,this);
+ }
+ else
+ {
+ mRoot = node;
+ }
+ return ret;
+ }
+
+ KdTreeNode * getNewNode(uint32_t index)
+ {
+ if ( mBundle == 0 )
+ {
+ mBundle = new KdTreeNodeBundle;
+ }
+ if ( mBundle->isFull() )
+ {
+ KdTreeNodeBundle *bundle = new KdTreeNodeBundle;
+ mBundle->mNext = bundle;
+ mBundle = bundle;
+ }
+ KdTreeNode *node = mBundle->getNextNode();
+ new ( node ) KdTreeNode(index);
+ return node;
+ }
+
+ uint32_t getNearest(const double *pos,double radius,bool &_found) const // returns the nearest possible neighbor's index.
+ {
+ assert( mUseDouble );
+ uint32_t ret = 0;
+
+ _found = false;
+ KdTreeFindNode found[1];
+ uint32_t count = search(pos,radius,1,found);
+ if ( count )
+ {
+ KdTreeNode *node = found[0].mNode;
+ ret = node->getIndex();
+ _found = true;
+ }
+ return ret;
+ }
+
+ uint32_t getNearest(const float *pos,float radius,bool &_found) const // returns the nearest possible neighbor's index.
+ {
+ assert( !mUseDouble );
+ uint32_t ret = 0;
+
+ _found = false;
+ KdTreeFindNode found[1];
+ uint32_t count = search(pos,radius,1,found);
+ if ( count )
+ {
+ KdTreeNode *node = found[0].mNode;
+ ret = node->getIndex();
+ _found = true;
+ }
+ return ret;
+ }
+
+ const double * getVerticesDouble(void) const
+ {
+ assert( mUseDouble );
+ const double *ret = 0;
+ if ( !mVerticesDouble.empty() )
+ {
+ ret = &mVerticesDouble[0];
+ }
+ return ret;
+ }
+
+ const float * getVerticesFloat(void) const
+ {
+ assert( !mUseDouble );
+ const float * ret = 0;
+ if ( !mVerticesFloat.empty() )
+ {
+ ret = &mVerticesFloat[0];
+ }
+ return ret;
+ }
+
+ uint32_t getVcount(void) const { return mVcount; };
+
+ void setUseDouble(bool useDouble)
+ {
+ mUseDouble = useDouble;
+ }
+
+private:
+ bool mUseDouble;
+ KdTreeNode *mRoot;
+ KdTreeNodeBundle *mBundle;
+ uint32_t mVcount;
+ DoubleVector mVerticesDouble;
+ FloatVector mVerticesFloat;
+};
+
+}; // end of namespace VERTEX_INDEX
+
+class MyVertexIndex : public fm_VertexIndex
+{
+public:
+ MyVertexIndex(double granularity,bool snapToGrid)
+ {
+ mDoubleGranularity = granularity;
+ mFloatGranularity = (float)granularity;
+ mSnapToGrid = snapToGrid;
+ mUseDouble = true;
+ mKdTree.setUseDouble(true);
+ }
+
+ MyVertexIndex(float granularity,bool snapToGrid)
+ {
+ mDoubleGranularity = granularity;
+ mFloatGranularity = (float)granularity;
+ mSnapToGrid = snapToGrid;
+ mUseDouble = false;
+ mKdTree.setUseDouble(false);
+ }
+
+ virtual ~MyVertexIndex(void)
+ {
+
+ }
+
+
+ double snapToGrid(double p)
+ {
+ double m = fmod(p,mDoubleGranularity);
+ p-=m;
+ return p;
+ }
+
+ float snapToGrid(float p)
+ {
+ float m = fmodf(p,mFloatGranularity);
+ p-=m;
+ return p;
+ }
+
+ uint32_t getIndex(const float *_p,bool &newPos) // get index for a vector float
+ {
+ uint32_t ret;
+
+ if ( mUseDouble )
+ {
+ double p[3];
+ p[0] = _p[0];
+ p[1] = _p[1];
+ p[2] = _p[2];
+ return getIndex(p,newPos);
+ }
+
+ newPos = false;
+
+ float p[3];
+
+ if ( mSnapToGrid )
+ {
+ p[0] = snapToGrid(_p[0]);
+ p[1] = snapToGrid(_p[1]);
+ p[2] = snapToGrid(_p[2]);
+ }
+ else
+ {
+ p[0] = _p[0];
+ p[1] = _p[1];
+ p[2] = _p[2];
+ }
+
+ bool found;
+ ret = mKdTree.getNearest(p,mFloatGranularity,found);
+ if ( !found )
+ {
+ newPos = true;
+ ret = mKdTree.add(p[0],p[1],p[2]);
+ }
+
+
+ return ret;
+ }
+
+ uint32_t getIndex(const double *_p,bool &newPos) // get index for a vector double
+ {
+ uint32_t ret;
+
+ if ( !mUseDouble )
+ {
+ float p[3];
+ p[0] = (float)_p[0];
+ p[1] = (float)_p[1];
+ p[2] = (float)_p[2];
+ return getIndex(p,newPos);
+ }
+
+ newPos = false;
+
+ double p[3];
+
+ if ( mSnapToGrid )
+ {
+ p[0] = snapToGrid(_p[0]);
+ p[1] = snapToGrid(_p[1]);
+ p[2] = snapToGrid(_p[2]);
+ }
+ else
+ {
+ p[0] = _p[0];
+ p[1] = _p[1];
+ p[2] = _p[2];
+ }
+
+ bool found;
+ ret = mKdTree.getNearest(p,mDoubleGranularity,found);
+ if ( !found )
+ {
+ newPos = true;
+ ret = mKdTree.add(p[0],p[1],p[2]);
+ }
+
+
+ return ret;
+ }
+
+ const float * getVerticesFloat(void) const
+ {
+ const float * ret = 0;
+
+ assert( !mUseDouble );
+
+ ret = mKdTree.getVerticesFloat();
+
+ return ret;
+ }
+
+ const double * getVerticesDouble(void) const
+ {
+ const double * ret = 0;
+
+ assert( mUseDouble );
+
+ ret = mKdTree.getVerticesDouble();
+
+ return ret;
+ }
+
+ const float * getVertexFloat(uint32_t index) const
+ {
+ const float * ret = 0;
+ assert( !mUseDouble );
+#ifdef _DEBUG
+ uint32_t vcount = mKdTree.getVcount();
+ assert( index < vcount );
+#endif
+ ret = mKdTree.getVerticesFloat();
+ ret = &ret[index*3];
+ return ret;
+ }
+
+ const double * getVertexDouble(uint32_t index) const
+ {
+ const double * ret = 0;
+ assert( mUseDouble );
+#ifdef _DEBUG
+ uint32_t vcount = mKdTree.getVcount();
+ assert( index < vcount );
+#endif
+ ret = mKdTree.getVerticesDouble();
+ ret = &ret[index*3];
+
+ return ret;
+ }
+
+ uint32_t getVcount(void) const
+ {
+ return mKdTree.getVcount();
+ }
+
+ bool isDouble(void) const
+ {
+ return mUseDouble;
+ }
+
+
+ bool saveAsObj(const char *fname,uint32_t tcount,uint32_t *indices)
+ {
+ bool ret = false;
+
+
+ FILE *fph = fopen(fname,"wb");
+ if ( fph )
+ {
+ ret = true;
+
+ uint32_t vcount = getVcount();
+ if ( mUseDouble )
+ {
+ const double *v = getVerticesDouble();
+ for (uint32_t i=0; i<vcount; i++)
+ {
+ fprintf(fph,"v %0.9f %0.9f %0.9f\r\n", (float)v[0], (float)v[1], (float)v[2] );
+ v+=3;
+ }
+ }
+ else
+ {
+ const float *v = getVerticesFloat();
+ for (uint32_t i=0; i<vcount; i++)
+ {
+ fprintf(fph,"v %0.9f %0.9f %0.9f\r\n", v[0], v[1], v[2] );
+ v+=3;
+ }
+ }
+
+ for (uint32_t i=0; i<tcount; i++)
+ {
+ uint32_t i1 = *indices++;
+ uint32_t i2 = *indices++;
+ uint32_t i3 = *indices++;
+ fprintf(fph,"f %d %d %d\r\n", i1+1, i2+1, i3+1 );
+ }
+ fclose(fph);
+ }
+
+ return ret;
+ }
+
+private:
+ bool mUseDouble:1;
+ bool mSnapToGrid:1;
+ double mDoubleGranularity;
+ float mFloatGranularity;
+ VERTEX_INDEX::KdTree mKdTree;
+};
+
+fm_VertexIndex * fm_createVertexIndex(double granularity,bool snapToGrid) // create an indexed vertex system for doubles
+{
+ MyVertexIndex *ret = new MyVertexIndex(granularity,snapToGrid);
+ return static_cast< fm_VertexIndex *>(ret);
+}
+
+fm_VertexIndex * fm_createVertexIndex(float granularity,bool snapToGrid) // create an indexed vertext system for floats
+{
+ MyVertexIndex *ret = new MyVertexIndex(granularity,snapToGrid);
+ return static_cast< fm_VertexIndex *>(ret);
+}
+
+void fm_releaseVertexIndex(fm_VertexIndex *vindex)
+{
+ MyVertexIndex *m = static_cast< MyVertexIndex *>(vindex);
+ delete m;
+}
+
+#endif // END OF VERTEX WELDING CODE
+
+
+REAL fm_computeBestFitAABB(uint32_t vcount,const REAL *points,uint32_t pstride,REAL *bmin,REAL *bmax) // returns the diagonal distance
+{
+
+ const uint8_t *source = (const uint8_t *) points;
+
+ bmin[0] = points[0];
+ bmin[1] = points[1];
+ bmin[2] = points[2];
+
+ bmax[0] = points[0];
+ bmax[1] = points[1];
+ bmax[2] = points[2];
+
+
+ for (uint32_t i=1; i<vcount; i++)
+ {
+ source+=pstride;
+ const REAL *p = (const REAL *) source;
+
+ if ( p[0] < bmin[0] ) bmin[0] = p[0];
+ if ( p[1] < bmin[1] ) bmin[1] = p[1];
+ if ( p[2] < bmin[2] ) bmin[2] = p[2];
+
+ if ( p[0] > bmax[0] ) bmax[0] = p[0];
+ if ( p[1] > bmax[1] ) bmax[1] = p[1];
+ if ( p[2] > bmax[2] ) bmax[2] = p[2];
+
+ }
+
+ REAL dx = bmax[0] - bmin[0];
+ REAL dy = bmax[1] - bmin[1];
+ REAL dz = bmax[2] - bmin[2];
+
+ return (REAL) sqrt( dx*dx + dy*dy + dz*dz );
+
+}
+
+
+
+/* a = b - c */
+#define vector(a,b,c) \
+ (a)[0] = (b)[0] - (c)[0]; \
+ (a)[1] = (b)[1] - (c)[1]; \
+ (a)[2] = (b)[2] - (c)[2];
+
+
+
+#define innerProduct(v,q) \
+ ((v)[0] * (q)[0] + \
+ (v)[1] * (q)[1] + \
+ (v)[2] * (q)[2])
+
+#define crossProduct(a,b,c) \
+ (a)[0] = (b)[1] * (c)[2] - (c)[1] * (b)[2]; \
+ (a)[1] = (b)[2] * (c)[0] - (c)[2] * (b)[0]; \
+ (a)[2] = (b)[0] * (c)[1] - (c)[0] * (b)[1];
+
+
+bool fm_lineIntersectsTriangle(const REAL *rayStart,const REAL *rayEnd,const REAL *p1,const REAL *p2,const REAL *p3,REAL *sect)
+{
+ REAL dir[3];
+
+ dir[0] = rayEnd[0] - rayStart[0];
+ dir[1] = rayEnd[1] - rayStart[1];
+ dir[2] = rayEnd[2] - rayStart[2];
+
+ REAL d = (REAL)sqrt(dir[0]*dir[0] + dir[1]*dir[1] + dir[2]*dir[2]);
+ REAL r = 1.0f / d;
+
+ dir[0]*=r;
+ dir[1]*=r;
+ dir[2]*=r;
+
+
+ REAL t;
+
+ bool ret = fm_rayIntersectsTriangle(rayStart, dir, p1, p2, p3, t );
+
+ if ( ret )
+ {
+ if ( t > d )
+ {
+ sect[0] = rayStart[0] + dir[0]*t;
+ sect[1] = rayStart[1] + dir[1]*t;
+ sect[2] = rayStart[2] + dir[2]*t;
+ }
+ else
+ {
+ ret = false;
+ }
+ }
+
+ return ret;
+}
+
+
+
+bool fm_rayIntersectsTriangle(const REAL *p,const REAL *d,const REAL *v0,const REAL *v1,const REAL *v2,REAL &t)
+{
+ REAL e1[3],e2[3],h[3],s[3],q[3];
+ REAL a,f,u,v;
+
+ vector(e1,v1,v0);
+ vector(e2,v2,v0);
+ crossProduct(h,d,e2);
+ a = innerProduct(e1,h);
+
+ if (a > -0.00001 && a < 0.00001)
+ return(false);
+
+ f = 1/a;
+ vector(s,p,v0);
+ u = f * (innerProduct(s,h));
+
+ if (u < 0.0 || u > 1.0)
+ return(false);
+
+ crossProduct(q,s,e1);
+ v = f * innerProduct(d,q);
+ if (v < 0.0 || u + v > 1.0)
+ return(false);
+ // at this stage we can compute t to find out where
+ // the intersection point is on the line
+ t = f * innerProduct(e2,q);
+ if (t > 0) // ray intersection
+ return(true);
+ else // this means that there is a line intersection
+ // but not a ray intersection
+ return (false);
+}
+
+
+inline REAL det(const REAL *p1,const REAL *p2,const REAL *p3)
+{
+ return p1[0]*p2[1]*p3[2] + p2[0]*p3[1]*p1[2] + p3[0]*p1[1]*p2[2] -p1[0]*p3[1]*p2[2] - p2[0]*p1[1]*p3[2] - p3[0]*p2[1]*p1[2];
+}
+
+
+REAL fm_computeMeshVolume(const REAL *vertices,uint32_t tcount,const uint32_t *indices)
+{
+ REAL volume = 0;
+
+ for (uint32_t i=0; i<tcount; i++,indices+=3)
+ {
+ const REAL *p1 = &vertices[ indices[0]*3 ];
+ const REAL *p2 = &vertices[ indices[1]*3 ];
+ const REAL *p3 = &vertices[ indices[2]*3 ];
+ volume+=det(p1,p2,p3); // compute the volume of the tetrahedran relative to the origin.
+ }
+
+ volume*=(1.0f/6.0f);
+ if ( volume < 0 )
+ volume*=-1;
+ return volume;
+}
+
+
+const REAL * fm_getPoint(const REAL *points,uint32_t pstride,uint32_t index)
+{
+ const uint8_t *scan = (const uint8_t *)points;
+ scan+=(index*pstride);
+ return (REAL *)scan;
+}
+
+
+bool fm_insideTriangle(REAL Ax, REAL Ay,
+ REAL Bx, REAL By,
+ REAL Cx, REAL Cy,
+ REAL Px, REAL Py)
+
+{
+ REAL ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy;
+ REAL cCROSSap, bCROSScp, aCROSSbp;
+
+ ax = Cx - Bx; ay = Cy - By;
+ bx = Ax - Cx; by = Ay - Cy;
+ cx = Bx - Ax; cy = By - Ay;
+ apx= Px - Ax; apy= Py - Ay;
+ bpx= Px - Bx; bpy= Py - By;
+ cpx= Px - Cx; cpy= Py - Cy;
+
+ aCROSSbp = ax*bpy - ay*bpx;
+ cCROSSap = cx*apy - cy*apx;
+ bCROSScp = bx*cpy - by*cpx;
+
+ return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f));
+}
+
+
+REAL fm_areaPolygon2d(uint32_t pcount,const REAL *points,uint32_t pstride)
+{
+ int32_t n = (int32_t)pcount;
+
+ REAL A=0.0f;
+ for(int32_t p=n-1,q=0; q<n; p=q++)
+ {
+ const REAL *p1 = fm_getPoint(points,pstride,p);
+ const REAL *p2 = fm_getPoint(points,pstride,q);
+ A+= p1[0]*p2[1] - p2[0]*p1[1];
+ }
+ return A*0.5f;
+}
+
+
+bool fm_pointInsidePolygon2d(uint32_t pcount,const REAL *points,uint32_t pstride,const REAL *point,uint32_t xindex,uint32_t yindex)
+{
+ uint32_t j = pcount-1;
+ int32_t oddNodes = 0;
+
+ REAL x = point[xindex];
+ REAL y = point[yindex];
+
+ for (uint32_t i=0; i<pcount; i++)
+ {
+ const REAL *p1 = fm_getPoint(points,pstride,i);
+ const REAL *p2 = fm_getPoint(points,pstride,j);
+
+ REAL x1 = p1[xindex];
+ REAL y1 = p1[yindex];
+
+ REAL x2 = p2[xindex];
+ REAL y2 = p2[yindex];
+
+ if ( (y1 < y && y2 >= y) || (y2 < y && y1 >= y) )
+ {
+ if (x1+(y-y1)/(y2-y1)*(x2-x1)<x)
+ {
+ oddNodes = 1-oddNodes;
+ }
+ }
+ j = i;
+ }
+
+ return oddNodes ? true : false;
+}
+
+
+uint32_t fm_consolidatePolygon(uint32_t pcount,const REAL *points,uint32_t pstride,REAL *_dest,REAL epsilon) // collapses co-linear edges.
+{
+ uint32_t ret = 0;
+
+
+ if ( pcount >= 3 )
+ {
+ const REAL *prev = fm_getPoint(points,pstride,pcount-1);
+ const REAL *current = points;
+ const REAL *next = fm_getPoint(points,pstride,1);
+ REAL *dest = _dest;
+
+ for (uint32_t i=0; i<pcount; i++)
+ {
+
+ next = (i+1)==pcount ? points : next;
+
+ if ( !fm_colinear(prev,current,next,epsilon) )
+ {
+ dest[0] = current[0];
+ dest[1] = current[1];
+ dest[2] = current[2];
+
+ dest+=3;
+ ret++;
+ }
+
+ prev = current;
+ current+=3;
+ next+=3;
+
+ }
+ }
+
+ return ret;
+}
+
+
+#ifndef RECT3D_TEMPLATE
+
+#define RECT3D_TEMPLATE
+
+template <class T> class Rect3d
+{
+public:
+ Rect3d(void) { };
+
+ Rect3d(const T *bmin,const T *bmax)
+ {
+
+ mMin[0] = bmin[0];
+ mMin[1] = bmin[1];
+ mMin[2] = bmin[2];
+
+ mMax[0] = bmax[0];
+ mMax[1] = bmax[1];
+ mMax[2] = bmax[2];
+
+ }
+
+ void SetMin(const T *bmin)
+ {
+ mMin[0] = bmin[0];
+ mMin[1] = bmin[1];
+ mMin[2] = bmin[2];
+ }
+
+ void SetMax(const T *bmax)
+ {
+ mMax[0] = bmax[0];
+ mMax[1] = bmax[1];
+ mMax[2] = bmax[2];
+ }
+
+ void SetMin(T x,T y,T z)
+ {
+ mMin[0] = x;
+ mMin[1] = y;
+ mMin[2] = z;
+ }
+
+ void SetMax(T x,T y,T z)
+ {
+ mMax[0] = x;
+ mMax[1] = y;
+ mMax[2] = z;
+ }
+
+ T mMin[3];
+ T mMax[3];
+};
+
+#endif
+
+void splitRect(uint32_t axis,
+ const Rect3d<REAL> &source,
+ Rect3d<REAL> &b1,
+ Rect3d<REAL> &b2,
+ const REAL *midpoint)
+{
+ switch ( axis )
+ {
+ case 0:
+ b1.SetMin(source.mMin);
+ b1.SetMax( midpoint[0], source.mMax[1], source.mMax[2] );
+
+ b2.SetMin( midpoint[0], source.mMin[1], source.mMin[2] );
+ b2.SetMax(source.mMax);
+
+ break;
+ case 1:
+ b1.SetMin(source.mMin);
+ b1.SetMax( source.mMax[0], midpoint[1], source.mMax[2] );
+
+ b2.SetMin( source.mMin[0], midpoint[1], source.mMin[2] );
+ b2.SetMax(source.mMax);
+
+ break;
+ case 2:
+ b1.SetMin(source.mMin);
+ b1.SetMax( source.mMax[0], source.mMax[1], midpoint[2] );
+
+ b2.SetMin( source.mMin[0], source.mMin[1], midpoint[2] );
+ b2.SetMax(source.mMax);
+
+ break;
+ }
+}
+
+bool fm_computeSplitPlane(uint32_t vcount,
+ const REAL *vertices,
+ uint32_t /* tcount */,
+ const uint32_t * /* indices */,
+ REAL *plane)
+{
+
+ REAL sides[3];
+ REAL matrix[16];
+
+ fm_computeBestFitOBB( vcount, vertices, sizeof(REAL)*3, sides, matrix );
+
+ REAL bmax[3];
+ REAL bmin[3];
+
+ bmax[0] = sides[0]*0.5f;
+ bmax[1] = sides[1]*0.5f;
+ bmax[2] = sides[2]*0.5f;
+
+ bmin[0] = -bmax[0];
+ bmin[1] = -bmax[1];
+ bmin[2] = -bmax[2];
+
+
+ REAL dx = sides[0];
+ REAL dy = sides[1];
+ REAL dz = sides[2];
+
+
+ uint32_t axis = 0;
+
+ if ( dy > dx )
+ {
+ axis = 1;
+ }
+
+ if ( dz > dx && dz > dy )
+ {
+ axis = 2;
+ }
+
+ REAL p1[3];
+ REAL p2[3];
+ REAL p3[3];
+
+ p3[0] = p2[0] = p1[0] = bmin[0] + dx*0.5f;
+ p3[1] = p2[1] = p1[1] = bmin[1] + dy*0.5f;
+ p3[2] = p2[2] = p1[2] = bmin[2] + dz*0.5f;
+
+ Rect3d<REAL> b(bmin,bmax);
+
+ Rect3d<REAL> b1,b2;
+
+ splitRect(axis,b,b1,b2,p1);
+
+
+ switch ( axis )
+ {
+ case 0:
+ p2[1] = bmin[1];
+ p2[2] = bmin[2];
+
+ if ( dz > dy )
+ {
+ p3[1] = bmax[1];
+ p3[2] = bmin[2];
+ }
+ else
+ {
+ p3[1] = bmin[1];
+ p3[2] = bmax[2];
+ }
+
+ break;
+ case 1:
+ p2[0] = bmin[0];
+ p2[2] = bmin[2];
+
+ if ( dx > dz )
+ {
+ p3[0] = bmax[0];
+ p3[2] = bmin[2];
+ }
+ else
+ {
+ p3[0] = bmin[0];
+ p3[2] = bmax[2];
+ }
+
+ break;
+ case 2:
+ p2[0] = bmin[0];
+ p2[1] = bmin[1];
+
+ if ( dx > dy )
+ {
+ p3[0] = bmax[0];
+ p3[1] = bmin[1];
+ }
+ else
+ {
+ p3[0] = bmin[0];
+ p3[1] = bmax[1];
+ }
+
+ break;
+ }
+
+ REAL tp1[3];
+ REAL tp2[3];
+ REAL tp3[3];
+
+ fm_transform(matrix,p1,tp1);
+ fm_transform(matrix,p2,tp2);
+ fm_transform(matrix,p3,tp3);
+
+ plane[3] = fm_computePlane(tp1,tp2,tp3,plane);
+
+ return true;
+
+}
+
+#pragma warning(disable:4100)
+
+void fm_nearestPointInTriangle(const REAL * /*nearestPoint*/,const REAL * /*p1*/,const REAL * /*p2*/,const REAL * /*p3*/,REAL * /*nearest*/)
+{
+
+}
+
+static REAL Partial(const REAL *a,const REAL *p)
+{
+ return (a[0]*p[1]) - (p[0]*a[1]);
+}
+
+REAL fm_areaTriangle(const REAL *p0,const REAL *p1,const REAL *p2)
+{
+ REAL A = Partial(p0,p1);
+ A+= Partial(p1,p2);
+ A+= Partial(p2,p0);
+ return A*0.5f;
+}
+
+void fm_subtract(const REAL *A,const REAL *B,REAL *diff) // compute A-B and store the result in 'diff'
+{
+ diff[0] = A[0]-B[0];
+ diff[1] = A[1]-B[1];
+ diff[2] = A[2]-B[2];
+}
+
+
+void fm_multiplyTransform(const REAL *pA,const REAL *pB,REAL *pM)
+{
+
+ REAL a = pA[0*4+0] * pB[0*4+0] + pA[0*4+1] * pB[1*4+0] + pA[0*4+2] * pB[2*4+0] + pA[0*4+3] * pB[3*4+0];
+ REAL b = pA[0*4+0] * pB[0*4+1] + pA[0*4+1] * pB[1*4+1] + pA[0*4+2] * pB[2*4+1] + pA[0*4+3] * pB[3*4+1];
+ REAL c = pA[0*4+0] * pB[0*4+2] + pA[0*4+1] * pB[1*4+2] + pA[0*4+2] * pB[2*4+2] + pA[0*4+3] * pB[3*4+2];
+ REAL d = pA[0*4+0] * pB[0*4+3] + pA[0*4+1] * pB[1*4+3] + pA[0*4+2] * pB[2*4+3] + pA[0*4+3] * pB[3*4+3];
+
+ REAL e = pA[1*4+0] * pB[0*4+0] + pA[1*4+1] * pB[1*4+0] + pA[1*4+2] * pB[2*4+0] + pA[1*4+3] * pB[3*4+0];
+ REAL f = pA[1*4+0] * pB[0*4+1] + pA[1*4+1] * pB[1*4+1] + pA[1*4+2] * pB[2*4+1] + pA[1*4+3] * pB[3*4+1];
+ REAL g = pA[1*4+0] * pB[0*4+2] + pA[1*4+1] * pB[1*4+2] + pA[1*4+2] * pB[2*4+2] + pA[1*4+3] * pB[3*4+2];
+ REAL h = pA[1*4+0] * pB[0*4+3] + pA[1*4+1] * pB[1*4+3] + pA[1*4+2] * pB[2*4+3] + pA[1*4+3] * pB[3*4+3];
+
+ REAL i = pA[2*4+0] * pB[0*4+0] + pA[2*4+1] * pB[1*4+0] + pA[2*4+2] * pB[2*4+0] + pA[2*4+3] * pB[3*4+0];
+ REAL j = pA[2*4+0] * pB[0*4+1] + pA[2*4+1] * pB[1*4+1] + pA[2*4+2] * pB[2*4+1] + pA[2*4+3] * pB[3*4+1];
+ REAL k = pA[2*4+0] * pB[0*4+2] + pA[2*4+1] * pB[1*4+2] + pA[2*4+2] * pB[2*4+2] + pA[2*4+3] * pB[3*4+2];
+ REAL l = pA[2*4+0] * pB[0*4+3] + pA[2*4+1] * pB[1*4+3] + pA[2*4+2] * pB[2*4+3] + pA[2*4+3] * pB[3*4+3];
+
+ REAL m = pA[3*4+0] * pB[0*4+0] + pA[3*4+1] * pB[1*4+0] + pA[3*4+2] * pB[2*4+0] + pA[3*4+3] * pB[3*4+0];
+ REAL n = pA[3*4+0] * pB[0*4+1] + pA[3*4+1] * pB[1*4+1] + pA[3*4+2] * pB[2*4+1] + pA[3*4+3] * pB[3*4+1];
+ REAL o = pA[3*4+0] * pB[0*4+2] + pA[3*4+1] * pB[1*4+2] + pA[3*4+2] * pB[2*4+2] + pA[3*4+3] * pB[3*4+2];
+ REAL p = pA[3*4+0] * pB[0*4+3] + pA[3*4+1] * pB[1*4+3] + pA[3*4+2] * pB[2*4+3] + pA[3*4+3] * pB[3*4+3];
+
+ pM[0] = a; pM[1] = b; pM[2] = c; pM[3] = d;
+
+ pM[4] = e; pM[5] = f; pM[6] = g; pM[7] = h;
+
+ pM[8] = i; pM[9] = j; pM[10] = k; pM[11] = l;
+
+ pM[12] = m; pM[13] = n; pM[14] = o; pM[15] = p;
+}
+
+void fm_multiply(REAL *A,REAL scaler)
+{
+ A[0]*=scaler;
+ A[1]*=scaler;
+ A[2]*=scaler;
+}
+
+void fm_add(const REAL *A,const REAL *B,REAL *sum)
+{
+ sum[0] = A[0]+B[0];
+ sum[1] = A[1]+B[1];
+ sum[2] = A[2]+B[2];
+}
+
+void fm_copy3(const REAL *source,REAL *dest)
+{
+ dest[0] = source[0];
+ dest[1] = source[1];
+ dest[2] = source[2];
+}
+
+
+uint32_t fm_copyUniqueVertices(uint32_t vcount,const REAL *input_vertices,REAL *output_vertices,uint32_t tcount,const uint32_t *input_indices,uint32_t *output_indices)
+{
+ uint32_t ret = 0;
+
+ REAL *vertices = (REAL *)malloc(sizeof(REAL)*vcount*3);
+ memcpy(vertices,input_vertices,sizeof(REAL)*vcount*3);
+ REAL *dest = output_vertices;
+
+ uint32_t *reindex = (uint32_t *)malloc(sizeof(uint32_t)*vcount);
+ memset(reindex,0xFF,sizeof(uint32_t)*vcount);
+
+ uint32_t icount = tcount*3;
+
+ for (uint32_t i=0; i<icount; i++)
+ {
+ uint32_t index = *input_indices++;
+
+ assert( index < vcount );
+
+ if ( reindex[index] == 0xFFFFFFFF )
+ {
+ *output_indices++ = ret;
+ reindex[index] = ret;
+ const REAL *pos = &vertices[index*3];
+ dest[0] = pos[0];
+ dest[1] = pos[1];
+ dest[2] = pos[2];
+ dest+=3;
+ ret++;
+ }
+ else
+ {
+ *output_indices++ = reindex[index];
+ }
+ }
+ free(vertices);
+ free(reindex);
+ return ret;
+}
+
+bool fm_isMeshCoplanar(uint32_t tcount,const uint32_t *indices,const REAL *vertices,bool doubleSided) // returns true if this collection of indexed triangles are co-planar!
+{
+ bool ret = true;
+
+ if ( tcount > 0 )
+ {
+ uint32_t i1 = indices[0];
+ uint32_t i2 = indices[1];
+ uint32_t i3 = indices[2];
+ const REAL *p1 = &vertices[i1*3];
+ const REAL *p2 = &vertices[i2*3];
+ const REAL *p3 = &vertices[i3*3];
+ REAL plane[4];
+ plane[3] = fm_computePlane(p1,p2,p3,plane);
+ const uint32_t *scan = &indices[3];
+ for (uint32_t i=1; i<tcount; i++)
+ {
+ i1 = *scan++;
+ i2 = *scan++;
+ i3 = *scan++;
+ p1 = &vertices[i1*3];
+ p2 = &vertices[i2*3];
+ p3 = &vertices[i3*3];
+ REAL _plane[4];
+ _plane[3] = fm_computePlane(p1,p2,p3,_plane);
+ if ( !fm_samePlane(plane,_plane,0.01f,0.001f,doubleSided) )
+ {
+ ret = false;
+ break;
+ }
+ }
+ }
+ return ret;
+}
+
+
+bool fm_samePlane(const REAL p1[4],const REAL p2[4],REAL normalEpsilon,REAL dEpsilon,bool doubleSided)
+{
+ bool ret = false;
+
+#if 0
+ if (p1[0] == p2[0] &&
+ p1[1] == p2[1] &&
+ p1[2] == p2[2] &&
+ p1[3] == p2[3])
+ {
+ ret = true;
+ }
+#else
+ REAL diff = (REAL) fabs(p1[3]-p2[3]);
+ if ( diff < dEpsilon ) // if the plane -d co-efficient is within our epsilon
+ {
+ REAL dot = fm_dot(p1,p2); // compute the dot-product of the vector normals.
+ if ( doubleSided ) dot = (REAL)fabs(dot);
+ REAL dmin = 1 - normalEpsilon;
+ REAL dmax = 1 + normalEpsilon;
+ if ( dot >= dmin && dot <= dmax )
+ {
+ ret = true; // then the plane equation is for practical purposes identical.
+ }
+ }
+#endif
+ return ret;
+}
+
+
+void fm_initMinMax(REAL bmin[3],REAL bmax[3])
+{
+ bmin[0] = FLT_MAX;
+ bmin[1] = FLT_MAX;
+ bmin[2] = FLT_MAX;
+
+ bmax[0] = -FLT_MAX;
+ bmax[1] = -FLT_MAX;
+ bmax[2] = -FLT_MAX;
+}
+
+void fm_inflateMinMax(REAL bmin[3], REAL bmax[3], REAL ratio)
+{
+ REAL inflate = fm_distance(bmin, bmax)*0.5f*ratio;
+
+ bmin[0] -= inflate;
+ bmin[1] -= inflate;
+ bmin[2] -= inflate;
+
+ bmax[0] += inflate;
+ bmax[1] += inflate;
+ bmax[2] += inflate;
+}
+
+#ifndef TESSELATE_H
+
+#define TESSELATE_H
+
+typedef std::vector< uint32_t > UintVector;
+
+class Myfm_Tesselate : public fm_Tesselate
+{
+public:
+ virtual ~Myfm_Tesselate(void)
+ {
+
+ }
+
+ const uint32_t * tesselate(fm_VertexIndex *vindex,uint32_t tcount,const uint32_t *indices,float longEdge,uint32_t maxDepth,uint32_t &outcount)
+ {
+ const uint32_t *ret = 0;
+
+ mMaxDepth = maxDepth;
+ mLongEdge = longEdge*longEdge;
+ mLongEdgeD = mLongEdge;
+ mVertices = vindex;
+
+ if ( mVertices->isDouble() )
+ {
+ uint32_t vcount = mVertices->getVcount();
+ double *vertices = (double *)malloc(sizeof(double)*vcount*3);
+ memcpy(vertices,mVertices->getVerticesDouble(),sizeof(double)*vcount*3);
+
+ for (uint32_t i=0; i<tcount; i++)
+ {
+ uint32_t i1 = *indices++;
+ uint32_t i2 = *indices++;
+ uint32_t i3 = *indices++;
+
+ const double *p1 = &vertices[i1*3];
+ const double *p2 = &vertices[i2*3];
+ const double *p3 = &vertices[i3*3];
+
+ tesselate(p1,p2,p3,0);
+
+ }
+ free(vertices);
+ }
+ else
+ {
+ uint32_t vcount = mVertices->getVcount();
+ float *vertices = (float *)malloc(sizeof(float)*vcount*3);
+ memcpy(vertices,mVertices->getVerticesFloat(),sizeof(float)*vcount*3);
+
+
+ for (uint32_t i=0; i<tcount; i++)
+ {
+ uint32_t i1 = *indices++;
+ uint32_t i2 = *indices++;
+ uint32_t i3 = *indices++;
+
+ const float *p1 = &vertices[i1*3];
+ const float *p2 = &vertices[i2*3];
+ const float *p3 = &vertices[i3*3];
+
+ tesselate(p1,p2,p3,0);
+
+ }
+ free(vertices);
+ }
+
+ outcount = (uint32_t)(mIndices.size()/3);
+ ret = &mIndices[0];
+
+
+ return ret;
+ }
+
+ void tesselate(const float *p1,const float *p2,const float *p3,uint32_t recurse)
+ {
+ bool split = false;
+ float l1,l2,l3;
+
+ l1 = l2 = l3 = 0;
+
+ if ( recurse < mMaxDepth )
+ {
+ l1 = fm_distanceSquared(p1,p2);
+ l2 = fm_distanceSquared(p2,p3);
+ l3 = fm_distanceSquared(p3,p1);
+
+ if ( l1 > mLongEdge || l2 > mLongEdge || l3 > mLongEdge )
+ split = true;
+
+ }
+
+ if ( split )
+ {
+ uint32_t edge;
+
+ if ( l1 >= l2 && l1 >= l3 )
+ edge = 0;
+ else if ( l2 >= l1 && l2 >= l3 )
+ edge = 1;
+ else
+ edge = 2;
+
+ float splits[3];
+
+ switch ( edge )
+ {
+ case 0:
+ {
+ fm_lerp(p1,p2,splits,0.5f);
+ tesselate(p1,splits,p3, recurse+1 );
+ tesselate(splits,p2,p3, recurse+1 );
+ }
+ break;
+ case 1:
+ {
+ fm_lerp(p2,p3,splits,0.5f);
+ tesselate(p1,p2,splits, recurse+1 );
+ tesselate(p1,splits,p3, recurse+1 );
+ }
+ break;
+ case 2:
+ {
+ fm_lerp(p3,p1,splits,0.5f);
+ tesselate(p1,p2,splits, recurse+1 );
+ tesselate(splits,p2,p3, recurse+1 );
+ }
+ break;
+ }
+ }
+ else
+ {
+ bool newp;
+
+ uint32_t i1 = mVertices->getIndex(p1,newp);
+ uint32_t i2 = mVertices->getIndex(p2,newp);
+ uint32_t i3 = mVertices->getIndex(p3,newp);
+
+ mIndices.push_back(i1);
+ mIndices.push_back(i2);
+ mIndices.push_back(i3);
+ }
+
+ }
+
+ void tesselate(const double *p1,const double *p2,const double *p3,uint32_t recurse)
+ {
+ bool split = false;
+ double l1,l2,l3;
+
+ l1 = l2 = l3 = 0;
+
+ if ( recurse < mMaxDepth )
+ {
+ l1 = fm_distanceSquared(p1,p2);
+ l2 = fm_distanceSquared(p2,p3);
+ l3 = fm_distanceSquared(p3,p1);
+
+ if ( l1 > mLongEdgeD || l2 > mLongEdgeD || l3 > mLongEdgeD )
+ split = true;
+
+ }
+
+ if ( split )
+ {
+ uint32_t edge;
+
+ if ( l1 >= l2 && l1 >= l3 )
+ edge = 0;
+ else if ( l2 >= l1 && l2 >= l3 )
+ edge = 1;
+ else
+ edge = 2;
+
+ double splits[3];
+
+ switch ( edge )
+ {
+ case 0:
+ {
+ fm_lerp(p1,p2,splits,0.5);
+ tesselate(p1,splits,p3, recurse+1 );
+ tesselate(splits,p2,p3, recurse+1 );
+ }
+ break;
+ case 1:
+ {
+ fm_lerp(p2,p3,splits,0.5);
+ tesselate(p1,p2,splits, recurse+1 );
+ tesselate(p1,splits,p3, recurse+1 );
+ }
+ break;
+ case 2:
+ {
+ fm_lerp(p3,p1,splits,0.5);
+ tesselate(p1,p2,splits, recurse+1 );
+ tesselate(splits,p2,p3, recurse+1 );
+ }
+ break;
+ }
+ }
+ else
+ {
+ bool newp;
+
+ uint32_t i1 = mVertices->getIndex(p1,newp);
+ uint32_t i2 = mVertices->getIndex(p2,newp);
+ uint32_t i3 = mVertices->getIndex(p3,newp);
+
+ mIndices.push_back(i1);
+ mIndices.push_back(i2);
+ mIndices.push_back(i3);
+ }
+
+ }
+
+private:
+ float mLongEdge;
+ double mLongEdgeD;
+ fm_VertexIndex *mVertices;
+ UintVector mIndices;
+ uint32_t mMaxDepth;
+};
+
+fm_Tesselate * fm_createTesselate(void)
+{
+ Myfm_Tesselate *m = new Myfm_Tesselate;
+ return static_cast< fm_Tesselate * >(m);
+}
+
+void fm_releaseTesselate(fm_Tesselate *t)
+{
+ Myfm_Tesselate *m = static_cast< Myfm_Tesselate *>(t);
+ delete m;
+}
+
+#endif
+
+
+#ifndef RAY_ABB_INTERSECT
+
+#define RAY_ABB_INTERSECT
+
+//! Integer representation of a floating-point value.
+#define IR(x) ((uint32_t&)x)
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+* A method to compute a ray-AABB intersection.
+* Original code by Andrew Woo, from "Graphics Gems", Academic Press, 1990
+* Optimized code by Pierre Terdiman, 2000 (~20-30% faster on my Celeron 500)
+* Epsilon value added by Klaus Hartmann. (discarding it saves a few cycles only)
+*
+* Hence this version is faster as well as more robust than the original one.
+*
+* Should work provided:
+* 1) the integer representation of 0.0f is 0x00000000
+* 2) the sign bit of the float is the most significant one
+*
+* Report bugs: p.terdiman@codercorner.com
+*
+* \param aabb [in] the axis-aligned bounding box
+* \param origin [in] ray origin
+* \param dir [in] ray direction
+* \param coord [out] impact coordinates
+* \return true if ray intersects AABB
+*/
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#define RAYAABB_EPSILON 0.00001f
+bool fm_intersectRayAABB(const float MinB[3],const float MaxB[3],const float origin[3],const float dir[3],float coord[3])
+{
+ bool Inside = true;
+ float MaxT[3];
+ MaxT[0]=MaxT[1]=MaxT[2]=-1.0f;
+
+ // Find candidate planes.
+ for(uint32_t i=0;i<3;i++)
+ {
+ if(origin[i] < MinB[i])
+ {
+ coord[i] = MinB[i];
+ Inside = false;
+
+ // Calculate T distances to candidate planes
+ if(IR(dir[i])) MaxT[i] = (MinB[i] - origin[i]) / dir[i];
+ }
+ else if(origin[i] > MaxB[i])
+ {
+ coord[i] = MaxB[i];
+ Inside = false;
+
+ // Calculate T distances to candidate planes
+ if(IR(dir[i])) MaxT[i] = (MaxB[i] - origin[i]) / dir[i];
+ }
+ }
+
+ // Ray origin inside bounding box
+ if(Inside)
+ {
+ coord[0] = origin[0];
+ coord[1] = origin[1];
+ coord[2] = origin[2];
+ return true;
+ }
+
+ // Get largest of the maxT's for final choice of intersection
+ uint32_t WhichPlane = 0;
+ if(MaxT[1] > MaxT[WhichPlane]) WhichPlane = 1;
+ if(MaxT[2] > MaxT[WhichPlane]) WhichPlane = 2;
+
+ // Check final candidate actually inside box
+ if(IR(MaxT[WhichPlane])&0x80000000) return false;
+
+ for(uint32_t i=0;i<3;i++)
+ {
+ if(i!=WhichPlane)
+ {
+ coord[i] = origin[i] + MaxT[WhichPlane] * dir[i];
+#ifdef RAYAABB_EPSILON
+ if(coord[i] < MinB[i] - RAYAABB_EPSILON || coord[i] > MaxB[i] + RAYAABB_EPSILON) return false;
+#else
+ if(coord[i] < MinB[i] || coord[i] > MaxB[i]) return false;
+#endif
+ }
+ }
+ return true; // ray hits box
+}
+
+bool fm_intersectLineSegmentAABB(const float bmin[3],const float bmax[3],const float p1[3],const float p2[3],float intersect[3])
+{
+ bool ret = false;
+
+ float dir[3];
+ dir[0] = p2[0] - p1[0];
+ dir[1] = p2[1] - p1[1];
+ dir[2] = p2[2] - p1[2];
+ float dist = fm_normalize(dir);
+ if ( dist > RAYAABB_EPSILON )
+ {
+ ret = fm_intersectRayAABB(bmin,bmax,p1,dir,intersect);
+ if ( ret )
+ {
+ float d = fm_distanceSquared(p1,intersect);
+ if ( d > (dist*dist) )
+ {
+ ret = false;
+ }
+ }
+ }
+ return ret;
+}
+
+#endif
+
+#ifndef OBB_TO_AABB
+
+#define OBB_TO_AABB
+
+#pragma warning(disable:4100)
+
+void fm_OBBtoAABB(const float /*obmin*/[3],const float /*obmax*/[3],const float /*matrix*/[16],float /*abmin*/[3],float /*abmax*/[3])
+{
+ assert(0); // not yet implemented.
+}
+
+
+const REAL * computePos(uint32_t index,const REAL *vertices,uint32_t vstride)
+{
+ const char *tmp = (const char *)vertices;
+ tmp+=(index*vstride);
+ return (const REAL*)tmp;
+}
+
+void computeNormal(uint32_t index,REAL *normals,uint32_t nstride,const REAL *normal)
+{
+ char *tmp = (char *)normals;
+ tmp+=(index*nstride);
+ REAL *dest = (REAL *)tmp;
+ dest[0]+=normal[0];
+ dest[1]+=normal[1];
+ dest[2]+=normal[2];
+}
+
+void fm_computeMeanNormals(uint32_t vcount, // the number of vertices
+ const REAL *vertices, // the base address of the vertex position data.
+ uint32_t vstride, // the stride between position data.
+ REAL *normals, // the base address of the destination for mean vector normals
+ uint32_t nstride, // the stride between normals
+ uint32_t tcount, // the number of triangles
+ const uint32_t *indices) // the triangle indices
+{
+
+ // Step #1 : Zero out the vertex normals
+ char *dest = (char *)normals;
+ for (uint32_t i=0; i<vcount; i++)
+ {
+ REAL *n = (REAL *)dest;
+ n[0] = 0;
+ n[1] = 0;
+ n[2] = 0;
+ dest+=nstride;
+ }
+
+ // Step #2 : Compute the face normals and accumulate them
+ const uint32_t *scan = indices;
+ for (uint32_t i=0; i<tcount; i++)
+ {
+
+ uint32_t i1 = *scan++;
+ uint32_t i2 = *scan++;
+ uint32_t i3 = *scan++;
+
+ const REAL *p1 = computePos(i1,vertices,vstride);
+ const REAL *p2 = computePos(i2,vertices,vstride);
+ const REAL *p3 = computePos(i3,vertices,vstride);
+
+ REAL normal[3];
+ fm_computePlane(p3,p2,p1,normal);
+
+ computeNormal(i1,normals,nstride,normal);
+ computeNormal(i2,normals,nstride,normal);
+ computeNormal(i3,normals,nstride,normal);
+ }
+
+
+ // Normalize the accumulated normals
+ dest = (char *)normals;
+ for (uint32_t i=0; i<vcount; i++)
+ {
+ REAL *n = (REAL *)dest;
+ fm_normalize(n);
+ dest+=nstride;
+ }
+
+}
+
+#endif
+
+
+#define BIGNUMBER 100000000.0 /* hundred million */
+
+static inline void Set(REAL *n,REAL x,REAL y,REAL z)
+{
+ n[0] = x;
+ n[1] = y;
+ n[2] = z;
+};
+
+static inline void Copy(REAL *dest,const REAL *source)
+{
+ dest[0] = source[0];
+ dest[1] = source[1];
+ dest[2] = source[2];
+}
+
+
+REAL fm_computeBestFitSphere(uint32_t vcount,const REAL *points,uint32_t pstride,REAL *center)
+{
+ REAL radius;
+ REAL radius2;
+
+ REAL xmin[3];
+ REAL xmax[3];
+ REAL ymin[3];
+ REAL ymax[3];
+ REAL zmin[3];
+ REAL zmax[3];
+ REAL dia1[3];
+ REAL dia2[3];
+
+ /* FIRST PASS: find 6 minima/maxima points */
+ Set(xmin,BIGNUMBER,BIGNUMBER,BIGNUMBER);
+ Set(xmax,-BIGNUMBER,-BIGNUMBER,-BIGNUMBER);
+ Set(ymin,BIGNUMBER,BIGNUMBER,BIGNUMBER);
+ Set(ymax,-BIGNUMBER,-BIGNUMBER,-BIGNUMBER);
+ Set(zmin,BIGNUMBER,BIGNUMBER,BIGNUMBER);
+ Set(zmax,-BIGNUMBER,-BIGNUMBER,-BIGNUMBER);
+
+ {
+ const char *scan = (const char *)points;
+ for (uint32_t i=0; i<vcount; i++)
+ {
+ const REAL *caller_p = (const REAL *)scan;
+ if (caller_p[0]<xmin[0])
+ Copy(xmin,caller_p); /* New xminimum point */
+ if (caller_p[0]>xmax[0])
+ Copy(xmax,caller_p);
+ if (caller_p[1]<ymin[1])
+ Copy(ymin,caller_p);
+ if (caller_p[1]>ymax[1])
+ Copy(ymax,caller_p);
+ if (caller_p[2]<zmin[2])
+ Copy(zmin,caller_p);
+ if (caller_p[2]>zmax[2])
+ Copy(zmax,caller_p);
+ scan+=pstride;
+ }
+ }
+
+ /* Set xspan = distance between the 2 points xmin & xmax (squared) */
+ REAL dx = xmax[0] - xmin[0];
+ REAL dy = xmax[1] - xmin[1];
+ REAL dz = xmax[2] - xmin[2];
+ REAL xspan = dx*dx + dy*dy + dz*dz;
+
+/* Same for y & z spans */
+ dx = ymax[0] - ymin[0];
+ dy = ymax[1] - ymin[1];
+ dz = ymax[2] - ymin[2];
+ REAL yspan = dx*dx + dy*dy + dz*dz;
+
+ dx = zmax[0] - zmin[0];
+ dy = zmax[1] - zmin[1];
+ dz = zmax[2] - zmin[2];
+ REAL zspan = dx*dx + dy*dy + dz*dz;
+
+ /* Set points dia1 & dia2 to the maximally separated pair */
+ Copy(dia1,xmin);
+ Copy(dia2,xmax); /* assume xspan biggest */
+ REAL maxspan = xspan;
+
+ if (yspan>maxspan)
+ {
+ maxspan = yspan;
+ Copy(dia1,ymin);
+ Copy(dia2,ymax);
+ }
+
+ if (zspan>maxspan)
+ {
+ maxspan = zspan;
+ Copy(dia1,zmin);
+ Copy(dia2,zmax);
+ }
+
+
+ /* dia1,dia2 is a diameter of initial sphere */
+ /* calc initial center */
+ center[0] = (dia1[0]+dia2[0])*0.5f;
+ center[1] = (dia1[1]+dia2[1])*0.5f;
+ center[2] = (dia1[2]+dia2[2])*0.5f;
+
+ /* calculate initial radius**2 and radius */
+
+ dx = dia2[0]-center[0]; /* x component of radius vector */
+ dy = dia2[1]-center[1]; /* y component of radius vector */
+ dz = dia2[2]-center[2]; /* z component of radius vector */
+
+ radius2 = dx*dx + dy*dy + dz*dz;
+ radius = REAL(sqrt(radius2));
+
+ /* SECOND PASS: increment current sphere */
+ {
+ const char *scan = (const char *)points;
+ for (uint32_t i=0; i<vcount; i++)
+ {
+ const REAL *caller_p = (const REAL *)scan;
+ dx = caller_p[0]-center[0];
+ dy = caller_p[1]-center[1];
+ dz = caller_p[2]-center[2];
+ REAL old_to_p_sq = dx*dx + dy*dy + dz*dz;
+ if (old_to_p_sq > radius2) /* do r**2 test first */
+ { /* this point is outside of current sphere */
+ REAL old_to_p = REAL(sqrt(old_to_p_sq));
+ /* calc radius of new sphere */
+ radius = (radius + old_to_p) * 0.5f;
+ radius2 = radius*radius; /* for next r**2 compare */
+ REAL old_to_new = old_to_p - radius;
+ /* calc center of new sphere */
+ REAL recip = 1.0f /old_to_p;
+ REAL cx = (radius*center[0] + old_to_new*caller_p[0]) * recip;
+ REAL cy = (radius*center[1] + old_to_new*caller_p[1]) * recip;
+ REAL cz = (radius*center[2] + old_to_new*caller_p[2]) * recip;
+ Set(center,cx,cy,cz);
+ scan+=pstride;
+ }
+ }
+ }
+ return radius;
+}
+
+
+void fm_computeBestFitCapsule(uint32_t vcount,const REAL *points,uint32_t pstride,REAL &radius,REAL &height,REAL matrix[16],bool bruteForce)
+{
+ REAL sides[3];
+ REAL omatrix[16];
+ fm_computeBestFitOBB(vcount,points,pstride,sides,omatrix,bruteForce);
+
+ int32_t axis = 0;
+ if ( sides[0] > sides[1] && sides[0] > sides[2] )
+ axis = 0;
+ else if ( sides[1] > sides[0] && sides[1] > sides[2] )
+ axis = 1;
+ else
+ axis = 2;
+
+ REAL localTransform[16];
+
+ REAL maxDist = 0;
+ REAL maxLen = 0;
+
+ switch ( axis )
+ {
+ case 0:
+ {
+ fm_eulerMatrix(0,0,FM_PI/2,localTransform);
+ fm_matrixMultiply(localTransform,omatrix,matrix);
+
+ const uint8_t *scan = (const uint8_t *)points;
+ for (uint32_t i=0; i<vcount; i++)
+ {
+ const REAL *p = (const REAL *)scan;
+ REAL t[3];
+ fm_inverseRT(omatrix,p,t);
+ REAL dist = t[1]*t[1]+t[2]*t[2];
+ if ( dist > maxDist )
+ {
+ maxDist = dist;
+ }
+ REAL l = (REAL) fabs(t[0]);
+ if ( l > maxLen )
+ {
+ maxLen = l;
+ }
+ scan+=pstride;
+ }
+ }
+ height = sides[0];
+ break;
+ case 1:
+ {
+ fm_eulerMatrix(0,FM_PI/2,0,localTransform);
+ fm_matrixMultiply(localTransform,omatrix,matrix);
+
+ const uint8_t *scan = (const uint8_t *)points;
+ for (uint32_t i=0; i<vcount; i++)
+ {
+ const REAL *p = (const REAL *)scan;
+ REAL t[3];
+ fm_inverseRT(omatrix,p,t);
+ REAL dist = t[0]*t[0]+t[2]*t[2];
+ if ( dist > maxDist )
+ {
+ maxDist = dist;
+ }
+ REAL l = (REAL) fabs(t[1]);
+ if ( l > maxLen )
+ {
+ maxLen = l;
+ }
+ scan+=pstride;
+ }
+ }
+ height = sides[1];
+ break;
+ case 2:
+ {
+ fm_eulerMatrix(FM_PI/2,0,0,localTransform);
+ fm_matrixMultiply(localTransform,omatrix,matrix);
+
+ const uint8_t *scan = (const uint8_t *)points;
+ for (uint32_t i=0; i<vcount; i++)
+ {
+ const REAL *p = (const REAL *)scan;
+ REAL t[3];
+ fm_inverseRT(omatrix,p,t);
+ REAL dist = t[0]*t[0]+t[1]*t[1];
+ if ( dist > maxDist )
+ {
+ maxDist = dist;
+ }
+ REAL l = (REAL) fabs(t[2]);
+ if ( l > maxLen )
+ {
+ maxLen = l;
+ }
+ scan+=pstride;
+ }
+ }
+ height = sides[2];
+ break;
+ }
+ radius = (REAL)sqrt(maxDist);
+ height = (maxLen*2)-(radius*2);
+}
+
+
+//************* Triangulation
+
+#ifndef TRIANGULATE_H
+
+#define TRIANGULATE_H
+
+typedef uint32_t TU32;
+
+class TVec
+{
+public:
+ TVec(double _x,double _y,double _z) { x = _x; y = _y; z = _z; };
+ TVec(void) { };
+
+ double x;
+ double y;
+ double z;
+};
+
+typedef std::vector< TVec > TVecVector;
+typedef std::vector< TU32 > TU32Vector;
+
+class CTriangulator
+{
+public:
+ /// Default constructor
+ CTriangulator();
+
+ /// Default destructor
+ virtual ~CTriangulator();
+
+ /// Triangulates the contour
+ void triangulate(TU32Vector &indices);
+
+ /// Returns the given point in the triangulator array
+ inline TVec get(const TU32 id) { return mPoints[id]; }
+
+ virtual void reset(void)
+ {
+ mInputPoints.clear();
+ mPoints.clear();
+ mIndices.clear();
+ }
+
+ virtual void addPoint(double x,double y,double z)
+ {
+ TVec v(x,y,z);
+ // update bounding box...
+ if ( mInputPoints.empty() )
+ {
+ mMin = v;
+ mMax = v;
+ }
+ else
+ {
+ if ( x < mMin.x ) mMin.x = x;
+ if ( y < mMin.y ) mMin.y = y;
+ if ( z < mMin.z ) mMin.z = z;
+
+ if ( x > mMax.x ) mMax.x = x;
+ if ( y > mMax.y ) mMax.y = y;
+ if ( z > mMax.z ) mMax.z = z;
+ }
+ mInputPoints.push_back(v);
+ }
+
+ // Triangulation happens in 2d. We could inverse transform the polygon around the normal direction, or we just use the two most signficant axes
+ // Here we find the two longest axes and use them to triangulate. Inverse transforming them would introduce more doubleing point error and isn't worth it.
+ virtual uint32_t * triangulate(uint32_t &tcount,double epsilon)
+ {
+ uint32_t *ret = 0;
+ tcount = 0;
+ mEpsilon = epsilon;
+
+ if ( !mInputPoints.empty() )
+ {
+ mPoints.clear();
+
+ double dx = mMax.x - mMin.x; // locate the first, second and third longest edges and store them in i1, i2, i3
+ double dy = mMax.y - mMin.y;
+ double dz = mMax.z - mMin.z;
+
+ uint32_t i1,i2,i3;
+
+ if ( dx > dy && dx > dz )
+ {
+ i1 = 0;
+ if ( dy > dz )
+ {
+ i2 = 1;
+ i3 = 2;
+ }
+ else
+ {
+ i2 = 2;
+ i3 = 1;
+ }
+ }
+ else if ( dy > dx && dy > dz )
+ {
+ i1 = 1;
+ if ( dx > dz )
+ {
+ i2 = 0;
+ i3 = 2;
+ }
+ else
+ {
+ i2 = 2;
+ i3 = 0;
+ }
+ }
+ else
+ {
+ i1 = 2;
+ if ( dx > dy )
+ {
+ i2 = 0;
+ i3 = 1;
+ }
+ else
+ {
+ i2 = 1;
+ i3 = 0;
+ }
+ }
+
+ uint32_t pcount = (uint32_t)mInputPoints.size();
+ const double *points = &mInputPoints[0].x;
+ for (uint32_t i=0; i<pcount; i++)
+ {
+ TVec v( points[i1], points[i2], points[i3] );
+ mPoints.push_back(v);
+ points+=3;
+ }
+
+ mIndices.clear();
+ triangulate(mIndices);
+ tcount = (uint32_t)mIndices.size()/3;
+ if ( tcount )
+ {
+ ret = &mIndices[0];
+ }
+ }
+ return ret;
+ }
+
+ virtual const double * getPoint(uint32_t index)
+ {
+ return &mInputPoints[index].x;
+ }
+
+
+private:
+ double mEpsilon;
+ TVec mMin;
+ TVec mMax;
+ TVecVector mInputPoints;
+ TVecVector mPoints;
+ TU32Vector mIndices;
+
+ /// Tests if a point is inside the given triangle
+ bool _insideTriangle(const TVec& A, const TVec& B, const TVec& C,const TVec& P);
+
+ /// Returns the area of the contour
+ double _area();
+
+ bool _snip(int32_t u, int32_t v, int32_t w, int32_t n, int32_t *V);
+
+ /// Processes the triangulation
+ void _process(TU32Vector &indices);
+
+};
+
+/// Default constructor
+CTriangulator::CTriangulator(void)
+{
+}
+
+/// Default destructor
+CTriangulator::~CTriangulator()
+{
+}
+
+/// Triangulates the contour
+void CTriangulator::triangulate(TU32Vector &indices)
+{
+ _process(indices);
+}
+
+/// Processes the triangulation
+void CTriangulator::_process(TU32Vector &indices)
+{
+ const int32_t n = (const int32_t)mPoints.size();
+ if (n < 3)
+ return;
+ int32_t *V = (int32_t *)malloc(sizeof(int32_t)*n);
+
+ bool flipped = false;
+
+ if (0.0f < _area())
+ {
+ for (int32_t v = 0; v < n; v++)
+ V[v] = v;
+ }
+ else
+ {
+ flipped = true;
+ for (int32_t v = 0; v < n; v++)
+ V[v] = (n - 1) - v;
+ }
+
+ int32_t nv = n;
+ int32_t count = 2 * nv;
+ for (int32_t m = 0, v = nv - 1; nv > 2;)
+ {
+ if (0 >= (count--))
+ return;
+
+ int32_t u = v;
+ if (nv <= u)
+ u = 0;
+ v = u + 1;
+ if (nv <= v)
+ v = 0;
+ int32_t w = v + 1;
+ if (nv <= w)
+ w = 0;
+
+ if (_snip(u, v, w, nv, V))
+ {
+ int32_t a, b, c, s, t;
+ a = V[u];
+ b = V[v];
+ c = V[w];
+ if ( flipped )
+ {
+ indices.push_back(a);
+ indices.push_back(b);
+ indices.push_back(c);
+ }
+ else
+ {
+ indices.push_back(c);
+ indices.push_back(b);
+ indices.push_back(a);
+ }
+ m++;
+ for (s = v, t = v + 1; t < nv; s++, t++)
+ V[s] = V[t];
+ nv--;
+ count = 2 * nv;
+ }
+ }
+
+ free(V);
+}
+
+/// Returns the area of the contour
+double CTriangulator::_area()
+{
+ int32_t n = (uint32_t)mPoints.size();
+ double A = 0.0f;
+ for (int32_t p = n - 1, q = 0; q < n; p = q++)
+ {
+ const TVec &pval = mPoints[p];
+ const TVec &qval = mPoints[q];
+ A += pval.x * qval.y - qval.x * pval.y;
+ }
+ A*=0.5f;
+ return A;
+}
+
+bool CTriangulator::_snip(int32_t u, int32_t v, int32_t w, int32_t n, int32_t *V)
+{
+ int32_t p;
+
+ const TVec &A = mPoints[ V[u] ];
+ const TVec &B = mPoints[ V[v] ];
+ const TVec &C = mPoints[ V[w] ];
+
+ if (mEpsilon > (((B.x - A.x) * (C.y - A.y)) - ((B.y - A.y) * (C.x - A.x))) )
+ return false;
+
+ for (p = 0; p < n; p++)
+ {
+ if ((p == u) || (p == v) || (p == w))
+ continue;
+ const TVec &P = mPoints[ V[p] ];
+ if (_insideTriangle(A, B, C, P))
+ return false;
+ }
+ return true;
+}
+
+/// Tests if a point is inside the given triangle
+bool CTriangulator::_insideTriangle(const TVec& A, const TVec& B, const TVec& C,const TVec& P)
+{
+ double ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy;
+ double cCROSSap, bCROSScp, aCROSSbp;
+
+ ax = C.x - B.x; ay = C.y - B.y;
+ bx = A.x - C.x; by = A.y - C.y;
+ cx = B.x - A.x; cy = B.y - A.y;
+ apx = P.x - A.x; apy = P.y - A.y;
+ bpx = P.x - B.x; bpy = P.y - B.y;
+ cpx = P.x - C.x; cpy = P.y - C.y;
+
+ aCROSSbp = ax * bpy - ay * bpx;
+ cCROSSap = cx * apy - cy * apx;
+ bCROSScp = bx * cpy - by * cpx;
+
+ return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f));
+}
+
+class Triangulate : public fm_Triangulate
+{
+public:
+ Triangulate(void)
+ {
+ mPointsFloat = 0;
+ mPointsDouble = 0;
+ }
+
+ virtual ~Triangulate(void)
+ {
+ reset();
+ }
+ void reset(void)
+ {
+ free(mPointsFloat);
+ free(mPointsDouble);
+ mPointsFloat = 0;
+ mPointsDouble = 0;
+ }
+
+ virtual const double * triangulate3d(uint32_t pcount,
+ const double *_points,
+ uint32_t vstride,
+ uint32_t &tcount,
+ bool consolidate,
+ double epsilon)
+ {
+ reset();
+
+ double *points = (double *)malloc(sizeof(double)*pcount*3);
+ if ( consolidate )
+ {
+ pcount = fm_consolidatePolygon(pcount,_points,vstride,points,1-epsilon);
+ }
+ else
+ {
+ double *dest = points;
+ for (uint32_t i=0; i<pcount; i++)
+ {
+ const double *src = fm_getPoint(_points,vstride,i);
+ dest[0] = src[0];
+ dest[1] = src[1];
+ dest[2] = src[2];
+ dest+=3;
+ }
+ vstride = sizeof(double)*3;
+ }
+
+ if ( pcount >= 3 )
+ {
+ CTriangulator ct;
+ for (uint32_t i=0; i<pcount; i++)
+ {
+ const double *src = fm_getPoint(points,vstride,i);
+ ct.addPoint( src[0], src[1], src[2] );
+ }
+ uint32_t _tcount;
+ uint32_t *indices = ct.triangulate(_tcount,epsilon);
+ if ( indices )
+ {
+ tcount = _tcount;
+ mPointsDouble = (double *)malloc(sizeof(double)*tcount*3*3);
+ double *dest = mPointsDouble;
+ for (uint32_t i=0; i<tcount; i++)
+ {
+ uint32_t i1 = indices[i*3+0];
+ uint32_t i2 = indices[i*3+1];
+ uint32_t i3 = indices[i*3+2];
+ const double *p1 = ct.getPoint(i1);
+ const double *p2 = ct.getPoint(i2);
+ const double *p3 = ct.getPoint(i3);
+
+ dest[0] = p1[0];
+ dest[1] = p1[1];
+ dest[2] = p1[2];
+
+ dest[3] = p2[0];
+ dest[4] = p2[1];
+ dest[5] = p2[2];
+
+ dest[6] = p3[0];
+ dest[7] = p3[1];
+ dest[8] = p3[2];
+ dest+=9;
+ }
+ }
+ }
+ free(points);
+
+ return mPointsDouble;
+ }
+
+ virtual const float * triangulate3d(uint32_t pcount,
+ const float *points,
+ uint32_t vstride,
+ uint32_t &tcount,
+ bool consolidate,
+ float epsilon)
+ {
+ reset();
+
+ double *temp = (double *)malloc(sizeof(double)*pcount*3);
+ double *dest = temp;
+ for (uint32_t i=0; i<pcount; i++)
+ {
+ const float *p = fm_getPoint(points,vstride,i);
+ dest[0] = p[0];
+ dest[1] = p[1];
+ dest[2] = p[2];
+ dest+=3;
+ }
+ const double *results = triangulate3d(pcount,temp,sizeof(double)*3,tcount,consolidate,epsilon);
+ if ( results )
+ {
+ uint32_t fcount = tcount*3*3;
+ mPointsFloat = (float *)malloc(sizeof(float)*tcount*3*3);
+ for (uint32_t i=0; i<fcount; i++)
+ {
+ mPointsFloat[i] = (float) results[i];
+ }
+ free(mPointsDouble);
+ mPointsDouble = 0;
+ }
+ free(temp);
+
+ return mPointsFloat;
+ }
+
+private:
+ float *mPointsFloat;
+ double *mPointsDouble;
+};
+
+fm_Triangulate * fm_createTriangulate(void)
+{
+ Triangulate *t = new Triangulate;
+ return static_cast< fm_Triangulate *>(t);
+}
+
+void fm_releaseTriangulate(fm_Triangulate *t)
+{
+ Triangulate *tt = static_cast< Triangulate *>(t);
+ delete tt;
+}
+
+#endif
+
+bool validDistance(const REAL *p1,const REAL *p2,REAL epsilon)
+{
+ bool ret = true;
+
+ REAL dx = p1[0] - p2[0];
+ REAL dy = p1[1] - p2[1];
+ REAL dz = p1[2] - p2[2];
+ REAL dist = dx*dx+dy*dy+dz*dz;
+ if ( dist < (epsilon*epsilon) )
+ {
+ ret = false;
+ }
+ return ret;
+}
+
+bool fm_isValidTriangle(const REAL *p1,const REAL *p2,const REAL *p3,REAL epsilon)
+{
+ bool ret = false;
+
+ if ( validDistance(p1,p2,epsilon) &&
+ validDistance(p1,p3,epsilon) &&
+ validDistance(p2,p3,epsilon) )
+ {
+
+ REAL area = fm_computeArea(p1,p2,p3);
+ if ( area > epsilon )
+ {
+ REAL _vertices[3*3],vertices[64*3];
+
+ _vertices[0] = p1[0];
+ _vertices[1] = p1[1];
+ _vertices[2] = p1[2];
+
+ _vertices[3] = p2[0];
+ _vertices[4] = p2[1];
+ _vertices[5] = p2[2];
+
+ _vertices[6] = p3[0];
+ _vertices[7] = p3[1];
+ _vertices[8] = p3[2];
+
+ uint32_t pcount = fm_consolidatePolygon(3,_vertices,sizeof(REAL)*3,vertices,1-epsilon);
+ if ( pcount == 3 )
+ {
+ ret = true;
+ }
+ }
+ }
+ return ret;
+}
+
+
+void fm_multiplyQuat(const REAL *left,const REAL *right,REAL *quat)
+{
+ REAL a,b,c,d;
+
+ a = left[3]*right[3] - left[0]*right[0] - left[1]*right[1] - left[2]*right[2];
+ b = left[3]*right[0] + right[3]*left[0] + left[1]*right[2] - right[1]*left[2];
+ c = left[3]*right[1] + right[3]*left[1] + left[2]*right[0] - right[2]*left[0];
+ d = left[3]*right[2] + right[3]*left[2] + left[0]*right[1] - right[0]*left[1];
+
+ quat[3] = a;
+ quat[0] = b;
+ quat[1] = c;
+ quat[2] = d;
+}
+
+bool fm_computeCentroid(uint32_t vcount, // number of input data points
+ const REAL *points, // starting address of points array.
+ REAL *center)
+
+{
+ bool ret = false;
+ if ( vcount )
+ {
+ center[0] = 0;
+ center[1] = 0;
+ center[2] = 0;
+ const REAL *p = points;
+ for (uint32_t i=0; i<vcount; i++)
+ {
+ center[0]+=p[0];
+ center[1]+=p[1];
+ center[2]+=p[2];
+ p += 3;
+ }
+ REAL recip = 1.0f / (REAL)vcount;
+ center[0]*=recip;
+ center[1]*=recip;
+ center[2]*=recip;
+ ret = true;
+ }
+ return ret;
+}
+
+bool fm_computeCentroid(uint32_t vcount, // number of input data points
+ const REAL *points, // starting address of points array.
+ uint32_t triCount,
+ const uint32_t *indices,
+ REAL *center)
+
+{
+ bool ret = false;
+ if (vcount)
+ {
+ center[0] = 0;
+ center[1] = 0;
+ center[2] = 0;
+
+ REAL numerator[3] = { 0, 0, 0 };
+ REAL denomintaor = 0;
+
+ for (uint32_t i = 0; i < triCount; i++)
+ {
+ uint32_t i1 = indices[i * 3 + 0];
+ uint32_t i2 = indices[i * 3 + 1];
+ uint32_t i3 = indices[i * 3 + 2];
+
+ const REAL *p1 = &points[i1 * 3];
+ const REAL *p2 = &points[i2 * 3];
+ const REAL *p3 = &points[i3 * 3];
+
+ // Compute the sum of the three positions
+ REAL sum[3];
+ sum[0] = p1[0] + p2[0] + p3[0];
+ sum[1] = p1[1] + p2[1] + p3[1];
+ sum[2] = p1[2] + p2[2] + p3[2];
+
+ // Compute the average of the three positions
+ sum[0] = sum[0] / 3;
+ sum[1] = sum[1] / 3;
+ sum[2] = sum[2] / 3;
+
+ // Compute the area of this triangle
+ REAL area = fm_computeArea(p1, p2, p3);
+
+ numerator[0]+= (sum[0] * area);
+ numerator[1]+= (sum[1] * area);
+ numerator[2]+= (sum[2] * area);
+
+ denomintaor += area;
+
+ }
+ REAL recip = 1 / denomintaor;
+ center[0] = numerator[0] * recip;
+ center[1] = numerator[1] * recip;
+ center[2] = numerator[2] * recip;
+ ret = true;
+ }
+ return ret;
+}
+
+
+#ifndef TEMPLATE_VEC3
+#define TEMPLATE_VEC3
+template <class Type> class Vec3
+{
+public:
+ Vec3(void)
+ {
+
+ }
+ Vec3(Type _x,Type _y,Type _z)
+ {
+ x = _x;
+ y = _y;
+ z = _z;
+ }
+ Type x;
+ Type y;
+ Type z;
+};
+#endif
+
+void fm_transformAABB(const REAL bmin[3],const REAL bmax[3],const REAL matrix[16],REAL tbmin[3],REAL tbmax[3])
+{
+ Vec3<REAL> box[8];
+ box[0] = Vec3< REAL >( bmin[0], bmin[1], bmin[2] );
+ box[1] = Vec3< REAL >( bmax[0], bmin[1], bmin[2] );
+ box[2] = Vec3< REAL >( bmax[0], bmax[1], bmin[2] );
+ box[3] = Vec3< REAL >( bmin[0], bmax[1], bmin[2] );
+ box[4] = Vec3< REAL >( bmin[0], bmin[1], bmax[2] );
+ box[5] = Vec3< REAL >( bmax[0], bmin[1], bmax[2] );
+ box[6] = Vec3< REAL >( bmax[0], bmax[1], bmax[2] );
+ box[7] = Vec3< REAL >( bmin[0], bmax[1], bmax[2] );
+ // transform all 8 corners of the box and then recompute a new AABB
+ for (unsigned int i=0; i<8; i++)
+ {
+ Vec3< REAL > &p = box[i];
+ fm_transform(matrix,&p.x,&p.x);
+ if ( i == 0 )
+ {
+ tbmin[0] = tbmax[0] = p.x;
+ tbmin[1] = tbmax[1] = p.y;
+ tbmin[2] = tbmax[2] = p.z;
+ }
+ else
+ {
+ if ( p.x < tbmin[0] ) tbmin[0] = p.x;
+ if ( p.y < tbmin[1] ) tbmin[1] = p.y;
+ if ( p.z < tbmin[2] ) tbmin[2] = p.z;
+ if ( p.x > tbmax[0] ) tbmax[0] = p.x;
+ if ( p.y > tbmax[1] ) tbmax[1] = p.y;
+ if ( p.z > tbmax[2] ) tbmax[2] = p.z;
+ }
+ }
+}
+
+REAL fm_normalizeQuat(REAL n[4]) // normalize this quat
+{
+ REAL dx = n[0]*n[0];
+ REAL dy = n[1]*n[1];
+ REAL dz = n[2]*n[2];
+ REAL dw = n[3]*n[3];
+
+ REAL dist = dx*dx+dy*dy+dz*dz+dw*dw;
+
+ dist = (REAL)sqrt(dist);
+
+ REAL recip = 1.0f / dist;
+
+ n[0]*=recip;
+ n[1]*=recip;
+ n[2]*=recip;
+ n[3]*=recip;
+
+ return dist;
+}
+
+
+}; // end of namespace
diff --git a/thirdparty/vhacd/src/VHACD-ASYNC.cpp b/thirdparty/vhacd/src/VHACD-ASYNC.cpp
new file mode 100644
index 0000000000..baf309d6a1
--- /dev/null
+++ b/thirdparty/vhacd/src/VHACD-ASYNC.cpp
@@ -0,0 +1,334 @@
+#include "../public/VHACD.h"
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <thread>
+#include <atomic>
+#include <mutex>
+#include <string>
+#include <float.h>
+
+#define ENABLE_ASYNC 1
+
+#define HACD_ALLOC(x) malloc(x)
+#define HACD_FREE(x) free(x)
+#define HACD_ASSERT(x) assert(x)
+
+namespace VHACD
+{
+
+class MyHACD_API : public VHACD::IVHACD, public VHACD::IVHACD::IUserCallback, VHACD::IVHACD::IUserLogger
+{
+public:
+ MyHACD_API(void)
+ {
+ mVHACD = VHACD::CreateVHACD();
+ }
+
+ virtual ~MyHACD_API(void)
+ {
+ releaseHACD();
+ Cancel();
+ mVHACD->Release();
+ }
+
+
+ virtual bool Compute(const double* const _points,
+ const uint32_t countPoints,
+ const uint32_t* const _triangles,
+ const uint32_t countTriangles,
+ const Parameters& _desc) final
+ {
+#if ENABLE_ASYNC
+ Cancel(); // if we previously had a solution running; cancel it.
+ releaseHACD();
+
+ // We need to copy the input vertices and triangles into our own buffers so we can operate
+ // on them safely from the background thread.
+ mVertices = (double *)HACD_ALLOC(sizeof(double)*countPoints * 3);
+ mIndices = (uint32_t *)HACD_ALLOC(sizeof(uint32_t)*countTriangles * 3);
+ memcpy(mVertices, _points, sizeof(double)*countPoints * 3);
+ memcpy(mIndices, _triangles, sizeof(uint32_t)*countTriangles * 3);
+ mRunning = true;
+ mThread = new std::thread([this, countPoints, countTriangles, _desc]()
+ {
+ ComputeNow(mVertices, countPoints, mIndices, countTriangles, _desc);
+ mRunning = false;
+ });
+#else
+ releaseHACD();
+ ComputeNow(_points, countPoints, _triangles, countTriangles, _desc);
+#endif
+ return true;
+ }
+
+ bool ComputeNow(const double* const points,
+ const uint32_t countPoints,
+ const uint32_t* const triangles,
+ const uint32_t countTriangles,
+ const Parameters& _desc)
+ {
+ uint32_t ret = 0;
+
+ mHullCount = 0;
+ mCallback = _desc.m_callback;
+ mLogger = _desc.m_logger;
+
+ IVHACD::Parameters desc = _desc;
+ // Set our intercepting callback interfaces if non-null
+ desc.m_callback = desc.m_callback ? this : nullptr;
+ desc.m_logger = desc.m_logger ? this : nullptr;
+
+ if ( countPoints )
+ {
+ bool ok = mVHACD->Compute(points, countPoints, triangles, countTriangles, desc);
+ if (ok)
+ {
+ ret = mVHACD->GetNConvexHulls();
+ mHulls = new IVHACD::ConvexHull[ret];
+ for (uint32_t i = 0; i < ret; i++)
+ {
+ VHACD::IVHACD::ConvexHull vhull;
+ mVHACD->GetConvexHull(i, vhull);
+ VHACD::IVHACD::ConvexHull h;
+ h.m_nPoints = vhull.m_nPoints;
+ h.m_points = (double *)HACD_ALLOC(sizeof(double) * 3 * h.m_nPoints);
+ memcpy(h.m_points, vhull.m_points, sizeof(double) * 3 * h.m_nPoints);
+ h.m_nTriangles = vhull.m_nTriangles;
+ h.m_triangles = (uint32_t *)HACD_ALLOC(sizeof(uint32_t) * 3 * h.m_nTriangles);
+ memcpy(h.m_triangles, vhull.m_triangles, sizeof(uint32_t) * 3 * h.m_nTriangles);
+ h.m_volume = vhull.m_volume;
+ h.m_center[0] = vhull.m_center[0];
+ h.m_center[1] = vhull.m_center[1];
+ h.m_center[2] = vhull.m_center[2];
+ mHulls[i] = h;
+ if (mCancel)
+ {
+ ret = 0;
+ break;
+ }
+ }
+ }
+ }
+
+ mHullCount = ret;
+ return ret ? true : false;
+ }
+
+ void releaseHull(VHACD::IVHACD::ConvexHull &h)
+ {
+ HACD_FREE((void *)h.m_triangles);
+ HACD_FREE((void *)h.m_points);
+ h.m_triangles = nullptr;
+ h.m_points = nullptr;
+ }
+
+ virtual void GetConvexHull(const uint32_t index, VHACD::IVHACD::ConvexHull& ch) const final
+ {
+ if ( index < mHullCount )
+ {
+ ch = mHulls[index];
+ }
+ }
+
+ void releaseHACD(void) // release memory associated with the last HACD request
+ {
+ for (uint32_t i=0; i<mHullCount; i++)
+ {
+ releaseHull(mHulls[i]);
+ }
+ delete[]mHulls;
+ mHulls = nullptr;
+ mHullCount = 0;
+ HACD_FREE(mVertices);
+ mVertices = nullptr;
+ HACD_FREE(mIndices);
+ mIndices = nullptr;
+ }
+
+
+ virtual void release(void) // release the HACD_API interface
+ {
+ delete this;
+ }
+
+ virtual uint32_t getHullCount(void)
+ {
+ return mHullCount;
+ }
+
+ virtual void Cancel() final
+ {
+ if (mRunning)
+ {
+ mVHACD->Cancel(); // Set the cancel signal to the base VHACD
+ }
+ if (mThread)
+ {
+ mThread->join(); // Wait for the thread to fully exit before we delete the instance
+ delete mThread;
+ mThread = nullptr;
+ Log("Convex Decomposition thread canceled\n");
+ }
+ mCancel = false; // clear the cancel semaphore
+ }
+
+ virtual bool Compute(const float* const points,
+ const uint32_t countPoints,
+ const uint32_t* const triangles,
+ const uint32_t countTriangles,
+ const Parameters& params) final
+ {
+
+ double *vertices = (double *)HACD_ALLOC(sizeof(double)*countPoints * 3);
+ const float *source = points;
+ double *dest = vertices;
+ for (uint32_t i = 0; i < countPoints; i++)
+ {
+ dest[0] = source[0];
+ dest[1] = source[1];
+ dest[2] = source[2];
+ dest += 3;
+ source += 3;
+ }
+
+ bool ret = Compute(vertices, countPoints, triangles, countTriangles, params);
+ HACD_FREE(vertices);
+ return ret;
+ }
+
+ virtual uint32_t GetNConvexHulls() const final
+ {
+ processPendingMessages();
+ return mHullCount;
+ }
+
+ virtual void Clean(void) final // release internally allocated memory
+ {
+ Cancel();
+ releaseHACD();
+ mVHACD->Clean();
+ }
+
+ virtual void Release(void) final // release IVHACD
+ {
+ delete this;
+ }
+
+ virtual bool OCLInit(void* const oclDevice,
+ IVHACD::IUserLogger* const logger = 0) final
+ {
+ return mVHACD->OCLInit(oclDevice, logger);
+ }
+
+ virtual bool OCLRelease(IVHACD::IUserLogger* const logger = 0) final
+ {
+ return mVHACD->OCLRelease(logger);
+ }
+
+ virtual void Update(const double overallProgress,
+ const double stageProgress,
+ const double operationProgress,
+ const char* const stage,
+ const char* const operation) final
+ {
+ mMessageMutex.lock();
+ mHaveUpdateMessage = true;
+ mOverallProgress = overallProgress;
+ mStageProgress = stageProgress;
+ mOperationProgress = operationProgress;
+ mStage = std::string(stage);
+ mOperation = std::string(operation);
+ mMessageMutex.unlock();
+ }
+
+ virtual void Log(const char* const msg) final
+ {
+ mMessageMutex.lock();
+ mHaveLogMessage = true;
+ mMessage = std::string(msg);
+ mMessageMutex.unlock();
+ }
+
+ virtual bool IsReady(void) const final
+ {
+ processPendingMessages();
+ return !mRunning;
+ }
+
+ // As a convenience for the calling application we only send it update and log messages from it's own main
+ // thread. This reduces the complexity burden on the caller by making sure it only has to deal with log
+ // messages in it's main application thread.
+ void processPendingMessages(void) const
+ {
+ // If we have a new update message and the user has specified a callback we send the message and clear the semaphore
+ if (mHaveUpdateMessage && mCallback)
+ {
+ mMessageMutex.lock();
+ mCallback->Update(mOverallProgress, mStageProgress, mOperationProgress, mStage.c_str(), mOperation.c_str());
+ mHaveUpdateMessage = false;
+ mMessageMutex.unlock();
+ }
+ // If we have a new log message and the user has specified a callback we send the message and clear the semaphore
+ if (mHaveLogMessage && mLogger)
+ {
+ mMessageMutex.lock();
+ mLogger->Log(mMessage.c_str());
+ mHaveLogMessage = false;
+ mMessageMutex.unlock();
+ }
+ }
+
+ // Will compute the center of mass of the convex hull decomposition results and return it
+ // in 'centerOfMass'. Returns false if the center of mass could not be computed.
+ virtual bool ComputeCenterOfMass(double centerOfMass[3]) const
+ {
+ bool ret = false;
+
+ centerOfMass[0] = 0;
+ centerOfMass[1] = 0;
+ centerOfMass[2] = 0;
+
+ if (mVHACD && IsReady() )
+ {
+ ret = mVHACD->ComputeCenterOfMass(centerOfMass);
+ }
+ return ret;
+ }
+
+private:
+ double *mVertices{ nullptr };
+ uint32_t *mIndices{ nullptr };
+ std::atomic< uint32_t> mHullCount{ 0 };
+ VHACD::IVHACD::ConvexHull *mHulls{ nullptr };
+ VHACD::IVHACD::IUserCallback *mCallback{ nullptr };
+ VHACD::IVHACD::IUserLogger *mLogger{ nullptr };
+ VHACD::IVHACD *mVHACD{ nullptr };
+ std::thread *mThread{ nullptr };
+ std::atomic< bool > mRunning{ false };
+ std::atomic<bool> mCancel{ false };
+
+ // Thread safe caching mechanism for messages and update status.
+ // This is so that caller always gets messages in his own thread
+ // Member variables are marked as 'mutable' since the message dispatch function
+ // is called from const query methods.
+ mutable std::mutex mMessageMutex;
+ mutable std::atomic< bool > mHaveUpdateMessage{ false };
+ mutable std::atomic< bool > mHaveLogMessage{ false };
+ mutable double mOverallProgress{ 0 };
+ mutable double mStageProgress{ 0 };
+ mutable double mOperationProgress{ 0 };
+ mutable std::string mStage;
+ mutable std::string mOperation;
+ mutable std::string mMessage;
+};
+
+IVHACD* CreateVHACD_ASYNC(void)
+{
+ MyHACD_API *m = new MyHACD_API;
+ return static_cast<IVHACD *>(m);
+}
+
+
+}; // end of VHACD namespace
+
diff --git a/thirdparty/vhacd/src/VHACD.cpp b/thirdparty/vhacd/src/VHACD.cpp
new file mode 100644
index 0000000000..54cc6e3761
--- /dev/null
+++ b/thirdparty/vhacd/src/VHACD.cpp
@@ -0,0 +1,1589 @@
+/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
+ All rights reserved.
+
+
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+ 2. 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.
+
+ 3. The names of the contributors may not 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.
+ */
+
+#ifndef _CRT_SECURE_NO_WARNINGS
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#include <algorithm>
+#include <fstream>
+#include <iomanip>
+#include <limits>
+#include <sstream>
+#if _OPENMP
+#include <omp.h>
+#endif // _OPENMP
+
+#include "../public/VHACD.h"
+#include "btConvexHullComputer.h"
+#include "vhacdICHull.h"
+#include "vhacdMesh.h"
+#include "vhacdSArray.h"
+#include "vhacdTimer.h"
+#include "vhacdVHACD.h"
+#include "vhacdVector.h"
+#include "vhacdVolume.h"
+#include "FloatMath.h"
+
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#define ABS(a) (((a) < 0) ? -(a) : (a))
+#define ZSGN(a) (((a) < 0) ? -1 : (a) > 0 ? 1 : 0)
+#define MAX_DOUBLE (1.79769e+308)
+
+#ifdef _MSC_VER
+#pragma warning(disable:4267 4100 4244 4456)
+#endif
+
+#ifdef USE_SSE
+#include <immintrin.h>
+
+const int32_t SIMD_WIDTH = 4;
+inline int32_t FindMinimumElement(const float* const d, float* const _, const int32_t n)
+{
+ // Min within vectors
+ __m128 min_i = _mm_set1_ps(-1.0f);
+ __m128 min_v = _mm_set1_ps(std::numeric_limits<float>::max());
+ for (int32_t i = 0; i <= n - SIMD_WIDTH; i += SIMD_WIDTH) {
+ const __m128 data = _mm_load_ps(&d[i]);
+ const __m128 pred = _mm_cmplt_ps(data, min_v);
+
+ min_i = _mm_blendv_ps(min_i, _mm_set1_ps(i), pred);
+ min_v = _mm_min_ps(data, min_v);
+ }
+
+ /* Min within vector */
+ const __m128 min1 = _mm_shuffle_ps(min_v, min_v, _MM_SHUFFLE(1, 0, 3, 2));
+ const __m128 min2 = _mm_min_ps(min_v, min1);
+ const __m128 min3 = _mm_shuffle_ps(min2, min2, _MM_SHUFFLE(0, 1, 0, 1));
+ const __m128 min4 = _mm_min_ps(min2, min3);
+ float min_d = _mm_cvtss_f32(min4);
+
+ // Min index
+ const int32_t min_idx = __builtin_ctz(_mm_movemask_ps(_mm_cmpeq_ps(min_v, min4)));
+ int32_t ret = min_i[min_idx] + min_idx;
+
+ // Trailing elements
+ for (int32_t i = (n & ~(SIMD_WIDTH - 1)); i < n; ++i) {
+ if (d[i] < min_d) {
+ min_d = d[i];
+ ret = i;
+ }
+ }
+
+ *m = min_d;
+ return ret;
+}
+
+inline int32_t FindMinimumElement(const float* const d, float* const m, const int32_t begin, const int32_t end)
+{
+ // Leading elements
+ int32_t min_i = -1;
+ float min_d = std::numeric_limits<float>::max();
+ const int32_t aligned = (begin & ~(SIMD_WIDTH - 1)) + ((begin & (SIMD_WIDTH - 1)) ? SIMD_WIDTH : 0);
+ for (int32_t i = begin; i < std::min(end, aligned); ++i) {
+ if (d[i] < min_d) {
+ min_d = d[i];
+ min_i = i;
+ }
+ }
+
+ // Middle and trailing elements
+ float r_m = std::numeric_limits<float>::max();
+ const int32_t n = end - aligned;
+ const int32_t r_i = (n > 0) ? FindMinimumElement(&d[aligned], &r_m, n) : 0;
+
+ // Pick the lowest
+ if (r_m < min_d) {
+ *m = r_m;
+ return r_i + aligned;
+ }
+ else {
+ *m = min_d;
+ return min_i;
+ }
+}
+#else
+inline int32_t FindMinimumElement(const float* const d, float* const m, const int32_t begin, const int32_t end)
+{
+ int32_t idx = -1;
+ float min = (std::numeric_limits<float>::max)();
+ for (size_t i = begin; i < size_t(end); ++i) {
+ if (d[i] < min) {
+ idx = i;
+ min = d[i];
+ }
+ }
+
+ *m = min;
+ return idx;
+}
+#endif
+
+//#define OCL_SOURCE_FROM_FILE
+#ifndef OCL_SOURCE_FROM_FILE
+const char* oclProgramSource = "\
+__kernel void ComputePartialVolumes(__global short4 * voxels, \
+ const int numVoxels, \
+ const float4 plane, \
+ const float4 minBB, \
+ const float4 scale, \
+ __local uint4 * localPartialVolumes, \
+ __global uint4 * partialVolumes) \
+{ \
+ int localId = get_local_id(0); \
+ int groupSize = get_local_size(0); \
+ int i0 = get_global_id(0) << 2; \
+ float4 voxel; \
+ uint4 v; \
+ voxel = convert_float4(voxels[i0]); \
+ v.s0 = (dot(plane, mad(scale, voxel, minBB)) >= 0.0f) * (i0 < numVoxels);\
+ voxel = convert_float4(voxels[i0 + 1]); \
+ v.s1 = (dot(plane, mad(scale, voxel, minBB)) >= 0.0f) * (i0 + 1 < numVoxels);\
+ voxel = convert_float4(voxels[i0 + 2]); \
+ v.s2 = (dot(plane, mad(scale, voxel, minBB)) >= 0.0f) * (i0 + 2 < numVoxels);\
+ voxel = convert_float4(voxels[i0 + 3]); \
+ v.s3 = (dot(plane, mad(scale, voxel, minBB)) >= 0.0f) * (i0 + 3 < numVoxels);\
+ localPartialVolumes[localId] = v; \
+ barrier(CLK_LOCAL_MEM_FENCE); \
+ for (int i = groupSize >> 1; i > 0; i >>= 1) \
+ { \
+ if (localId < i) \
+ { \
+ localPartialVolumes[localId] += localPartialVolumes[localId + i]; \
+ } \
+ barrier(CLK_LOCAL_MEM_FENCE); \
+ } \
+ if (localId == 0) \
+ { \
+ partialVolumes[get_group_id(0)] = localPartialVolumes[0]; \
+ } \
+} \
+__kernel void ComputePartialSums(__global uint4 * data, \
+ const int dataSize, \
+ __local uint4 * partialSums) \
+{ \
+ int globalId = get_global_id(0); \
+ int localId = get_local_id(0); \
+ int groupSize = get_local_size(0); \
+ int i; \
+ if (globalId < dataSize) \
+ { \
+ partialSums[localId] = data[globalId]; \
+ } \
+ else \
+ { \
+ partialSums[localId] = (0, 0, 0, 0); \
+ } \
+ barrier(CLK_LOCAL_MEM_FENCE); \
+ for (i = groupSize >> 1; i > 0; i >>= 1) \
+ { \
+ if (localId < i) \
+ { \
+ partialSums[localId] += partialSums[localId + i]; \
+ } \
+ barrier(CLK_LOCAL_MEM_FENCE); \
+ } \
+ if (localId == 0) \
+ { \
+ data[get_group_id(0)] = partialSums[0]; \
+ } \
+}";
+#endif //OCL_SOURCE_FROM_FILE
+
+namespace VHACD {
+IVHACD* CreateVHACD(void)
+{
+ return new VHACD();
+}
+bool VHACD::OCLInit(void* const oclDevice, IUserLogger* const logger)
+{
+#ifdef CL_VERSION_1_1
+ m_oclDevice = (cl_device_id*)oclDevice;
+ cl_int error;
+ m_oclContext = clCreateContext(NULL, 1, m_oclDevice, NULL, NULL, &error);
+ if (error != CL_SUCCESS) {
+ if (logger) {
+ logger->Log("Couldn't create context\n");
+ }
+ return false;
+ }
+
+#ifdef OCL_SOURCE_FROM_FILE
+ std::string cl_files = OPENCL_CL_FILES;
+// read kernal from file
+#ifdef _WIN32
+ std::replace(cl_files.begin(), cl_files.end(), '/', '\\');
+#endif // _WIN32
+
+ FILE* program_handle = fopen(cl_files.c_str(), "rb");
+ fseek(program_handle, 0, SEEK_END);
+ size_t program_size = ftell(program_handle);
+ rewind(program_handle);
+ char* program_buffer = new char[program_size + 1];
+ program_buffer[program_size] = '\0';
+ fread(program_buffer, sizeof(char), program_size, program_handle);
+ fclose(program_handle);
+ // create program
+ m_oclProgram = clCreateProgramWithSource(m_oclContext, 1, (const char**)&program_buffer, &program_size, &error);
+ delete[] program_buffer;
+#else
+ size_t program_size = strlen(oclProgramSource);
+ m_oclProgram = clCreateProgramWithSource(m_oclContext, 1, (const char**)&oclProgramSource, &program_size, &error);
+#endif
+ if (error != CL_SUCCESS) {
+ if (logger) {
+ logger->Log("Couldn't create program\n");
+ }
+ return false;
+ }
+
+ /* Build program */
+ error = clBuildProgram(m_oclProgram, 1, m_oclDevice, "-cl-denorms-are-zero", NULL, NULL);
+ if (error != CL_SUCCESS) {
+ size_t log_size;
+ /* Find Size of log and print to std output */
+ clGetProgramBuildInfo(m_oclProgram, *m_oclDevice, CL_PROGRAM_BUILD_LOG, 0, NULL, &log_size);
+ char* program_log = new char[log_size + 2];
+ program_log[log_size] = '\n';
+ program_log[log_size + 1] = '\0';
+ clGetProgramBuildInfo(m_oclProgram, *m_oclDevice, CL_PROGRAM_BUILD_LOG, log_size + 1, program_log, NULL);
+ if (logger) {
+ logger->Log("Couldn't build program\n");
+ logger->Log(program_log);
+ }
+ delete[] program_log;
+ return false;
+ }
+
+ delete[] m_oclQueue;
+ delete[] m_oclKernelComputePartialVolumes;
+ delete[] m_oclKernelComputeSum;
+ m_oclQueue = new cl_command_queue[m_ompNumProcessors];
+ m_oclKernelComputePartialVolumes = new cl_kernel[m_ompNumProcessors];
+ m_oclKernelComputeSum = new cl_kernel[m_ompNumProcessors];
+
+ const char nameKernelComputePartialVolumes[] = "ComputePartialVolumes";
+ const char nameKernelComputeSum[] = "ComputePartialSums";
+ for (int32_t k = 0; k < m_ompNumProcessors; ++k) {
+ m_oclKernelComputePartialVolumes[k] = clCreateKernel(m_oclProgram, nameKernelComputePartialVolumes, &error);
+ if (error != CL_SUCCESS) {
+ if (logger) {
+ logger->Log("Couldn't create kernel\n");
+ }
+ return false;
+ }
+ m_oclKernelComputeSum[k] = clCreateKernel(m_oclProgram, nameKernelComputeSum, &error);
+ if (error != CL_SUCCESS) {
+ if (logger) {
+ logger->Log("Couldn't create kernel\n");
+ }
+ return false;
+ }
+ }
+
+ error = clGetKernelWorkGroupInfo(m_oclKernelComputePartialVolumes[0],
+ *m_oclDevice,
+ CL_KERNEL_WORK_GROUP_SIZE,
+ sizeof(size_t),
+ &m_oclWorkGroupSize,
+ NULL);
+ size_t workGroupSize = 0;
+ error = clGetKernelWorkGroupInfo(m_oclKernelComputeSum[0],
+ *m_oclDevice,
+ CL_KERNEL_WORK_GROUP_SIZE,
+ sizeof(size_t),
+ &workGroupSize,
+ NULL);
+ if (error != CL_SUCCESS) {
+ if (logger) {
+ logger->Log("Couldn't query work group info\n");
+ }
+ return false;
+ }
+
+ if (workGroupSize < m_oclWorkGroupSize) {
+ m_oclWorkGroupSize = workGroupSize;
+ }
+
+ for (int32_t k = 0; k < m_ompNumProcessors; ++k) {
+ m_oclQueue[k] = clCreateCommandQueue(m_oclContext, *m_oclDevice, 0 /*CL_QUEUE_PROFILING_ENABLE*/, &error);
+ if (error != CL_SUCCESS) {
+ if (logger) {
+ logger->Log("Couldn't create queue\n");
+ }
+ return false;
+ }
+ }
+ return true;
+#else //CL_VERSION_1_1
+ return false;
+#endif //CL_VERSION_1_1
+}
+bool VHACD::OCLRelease(IUserLogger* const logger)
+{
+#ifdef CL_VERSION_1_1
+ cl_int error;
+ if (m_oclKernelComputePartialVolumes) {
+ for (int32_t k = 0; k < m_ompNumProcessors; ++k) {
+ error = clReleaseKernel(m_oclKernelComputePartialVolumes[k]);
+ if (error != CL_SUCCESS) {
+ if (logger) {
+ logger->Log("Couldn't release kernal\n");
+ }
+ return false;
+ }
+ }
+ delete[] m_oclKernelComputePartialVolumes;
+ }
+ if (m_oclKernelComputeSum) {
+ for (int32_t k = 0; k < m_ompNumProcessors; ++k) {
+ error = clReleaseKernel(m_oclKernelComputeSum[k]);
+ if (error != CL_SUCCESS) {
+ if (logger) {
+ logger->Log("Couldn't release kernal\n");
+ }
+ return false;
+ }
+ }
+ delete[] m_oclKernelComputeSum;
+ }
+ if (m_oclQueue) {
+ for (int32_t k = 0; k < m_ompNumProcessors; ++k) {
+ error = clReleaseCommandQueue(m_oclQueue[k]);
+ if (error != CL_SUCCESS) {
+ if (logger) {
+ logger->Log("Couldn't release queue\n");
+ }
+ return false;
+ }
+ }
+ delete[] m_oclQueue;
+ }
+ error = clReleaseProgram(m_oclProgram);
+ if (error != CL_SUCCESS) {
+ if (logger) {
+ logger->Log("Couldn't release program\n");
+ }
+ return false;
+ }
+ error = clReleaseContext(m_oclContext);
+ if (error != CL_SUCCESS) {
+ if (logger) {
+ logger->Log("Couldn't release context\n");
+ }
+ return false;
+ }
+
+ return true;
+#else //CL_VERSION_1_1
+ return false;
+#endif //CL_VERSION_1_1
+}
+void VHACD::ComputePrimitiveSet(const Parameters& params)
+{
+ if (GetCancel()) {
+ return;
+ }
+ m_timer.Tic();
+
+ m_stage = "Compute primitive set";
+ m_operation = "Convert volume to pset";
+
+ std::ostringstream msg;
+ if (params.m_logger) {
+ msg << "+ " << m_stage << std::endl;
+ params.m_logger->Log(msg.str().c_str());
+ }
+
+ Update(0.0, 0.0, params);
+ if (params.m_mode == 0) {
+ VoxelSet* vset = new VoxelSet;
+ m_volume->Convert(*vset);
+ m_pset = vset;
+ }
+ else {
+ TetrahedronSet* tset = new TetrahedronSet;
+ m_volume->Convert(*tset);
+ m_pset = tset;
+ }
+
+ delete m_volume;
+ m_volume = 0;
+
+ if (params.m_logger) {
+ msg.str("");
+ msg << "\t # primitives " << m_pset->GetNPrimitives() << std::endl;
+ msg << "\t # inside surface " << m_pset->GetNPrimitivesInsideSurf() << std::endl;
+ msg << "\t # on surface " << m_pset->GetNPrimitivesOnSurf() << std::endl;
+ params.m_logger->Log(msg.str().c_str());
+ }
+
+ m_overallProgress = 15.0;
+ Update(100.0, 100.0, params);
+ m_timer.Toc();
+ if (params.m_logger) {
+ msg.str("");
+ msg << "\t time " << m_timer.GetElapsedTime() / 1000.0 << "s" << std::endl;
+ params.m_logger->Log(msg.str().c_str());
+ }
+}
+bool VHACD::Compute(const double* const points, const uint32_t nPoints,
+ const uint32_t* const triangles,const uint32_t nTriangles, const Parameters& params)
+{
+ return ComputeACD(points, nPoints, triangles, nTriangles, params);
+}
+bool VHACD::Compute(const float* const points,const uint32_t nPoints,
+ const uint32_t* const triangles,const uint32_t nTriangles, const Parameters& params)
+{
+ return ComputeACD(points, nPoints, triangles, nTriangles, params);
+}
+double ComputePreferredCuttingDirection(const PrimitiveSet* const tset, Vec3<double>& dir)
+{
+ double ex = tset->GetEigenValue(AXIS_X);
+ double ey = tset->GetEigenValue(AXIS_Y);
+ double ez = tset->GetEigenValue(AXIS_Z);
+ double vx = (ey - ez) * (ey - ez);
+ double vy = (ex - ez) * (ex - ez);
+ double vz = (ex - ey) * (ex - ey);
+ if (vx < vy && vx < vz) {
+ double e = ey * ey + ez * ez;
+ dir[0] = 1.0;
+ dir[1] = 0.0;
+ dir[2] = 0.0;
+ return (e == 0.0) ? 0.0 : 1.0 - vx / e;
+ }
+ else if (vy < vx && vy < vz) {
+ double e = ex * ex + ez * ez;
+ dir[0] = 0.0;
+ dir[1] = 1.0;
+ dir[2] = 0.0;
+ return (e == 0.0) ? 0.0 : 1.0 - vy / e;
+ }
+ else {
+ double e = ex * ex + ey * ey;
+ dir[0] = 0.0;
+ dir[1] = 0.0;
+ dir[2] = 1.0;
+ return (e == 0.0) ? 0.0 : 1.0 - vz / e;
+ }
+}
+void ComputeAxesAlignedClippingPlanes(const VoxelSet& vset, const short downsampling, SArray<Plane>& planes)
+{
+ const Vec3<short> minV = vset.GetMinBBVoxels();
+ const Vec3<short> maxV = vset.GetMaxBBVoxels();
+ Vec3<double> pt;
+ Plane plane;
+ const short i0 = minV[0];
+ const short i1 = maxV[0];
+ plane.m_a = 1.0;
+ plane.m_b = 0.0;
+ plane.m_c = 0.0;
+ plane.m_axis = AXIS_X;
+ for (short i = i0; i <= i1; i += downsampling) {
+ pt = vset.GetPoint(Vec3<double>(i + 0.5, 0.0, 0.0));
+ plane.m_d = -pt[0];
+ plane.m_index = i;
+ planes.PushBack(plane);
+ }
+ const short j0 = minV[1];
+ const short j1 = maxV[1];
+ plane.m_a = 0.0;
+ plane.m_b = 1.0;
+ plane.m_c = 0.0;
+ plane.m_axis = AXIS_Y;
+ for (short j = j0; j <= j1; j += downsampling) {
+ pt = vset.GetPoint(Vec3<double>(0.0, j + 0.5, 0.0));
+ plane.m_d = -pt[1];
+ plane.m_index = j;
+ planes.PushBack(plane);
+ }
+ const short k0 = minV[2];
+ const short k1 = maxV[2];
+ plane.m_a = 0.0;
+ plane.m_b = 0.0;
+ plane.m_c = 1.0;
+ plane.m_axis = AXIS_Z;
+ for (short k = k0; k <= k1; k += downsampling) {
+ pt = vset.GetPoint(Vec3<double>(0.0, 0.0, k + 0.5));
+ plane.m_d = -pt[2];
+ plane.m_index = k;
+ planes.PushBack(plane);
+ }
+}
+void ComputeAxesAlignedClippingPlanes(const TetrahedronSet& tset, const short downsampling, SArray<Plane>& planes)
+{
+ const Vec3<double> minV = tset.GetMinBB();
+ const Vec3<double> maxV = tset.GetMaxBB();
+ const double scale = tset.GetSacle();
+ const short i0 = 0;
+ const short j0 = 0;
+ const short k0 = 0;
+ const short i1 = static_cast<short>((maxV[0] - minV[0]) / scale + 0.5);
+ const short j1 = static_cast<short>((maxV[1] - minV[1]) / scale + 0.5);
+ const short k1 = static_cast<short>((maxV[2] - minV[2]) / scale + 0.5);
+
+ Plane plane;
+ plane.m_a = 1.0;
+ plane.m_b = 0.0;
+ plane.m_c = 0.0;
+ plane.m_axis = AXIS_X;
+ for (short i = i0; i <= i1; i += downsampling) {
+ double x = minV[0] + scale * i;
+ plane.m_d = -x;
+ plane.m_index = i;
+ planes.PushBack(plane);
+ }
+ plane.m_a = 0.0;
+ plane.m_b = 1.0;
+ plane.m_c = 0.0;
+ plane.m_axis = AXIS_Y;
+ for (short j = j0; j <= j1; j += downsampling) {
+ double y = minV[1] + scale * j;
+ plane.m_d = -y;
+ plane.m_index = j;
+ planes.PushBack(plane);
+ }
+ plane.m_a = 0.0;
+ plane.m_b = 0.0;
+ plane.m_c = 1.0;
+ plane.m_axis = AXIS_Z;
+ for (short k = k0; k <= k1; k += downsampling) {
+ double z = minV[2] + scale * k;
+ plane.m_d = -z;
+ plane.m_index = k;
+ planes.PushBack(plane);
+ }
+}
+void RefineAxesAlignedClippingPlanes(const VoxelSet& vset, const Plane& bestPlane, const short downsampling,
+ SArray<Plane>& planes)
+{
+ const Vec3<short> minV = vset.GetMinBBVoxels();
+ const Vec3<short> maxV = vset.GetMaxBBVoxels();
+ Vec3<double> pt;
+ Plane plane;
+
+ if (bestPlane.m_axis == AXIS_X) {
+ const short i0 = MAX(minV[0], bestPlane.m_index - downsampling);
+ const short i1 = MIN(maxV[0], bestPlane.m_index + downsampling);
+ plane.m_a = 1.0;
+ plane.m_b = 0.0;
+ plane.m_c = 0.0;
+ plane.m_axis = AXIS_X;
+ for (short i = i0; i <= i1; ++i) {
+ pt = vset.GetPoint(Vec3<double>(i + 0.5, 0.0, 0.0));
+ plane.m_d = -pt[0];
+ plane.m_index = i;
+ planes.PushBack(plane);
+ }
+ }
+ else if (bestPlane.m_axis == AXIS_Y) {
+ const short j0 = MAX(minV[1], bestPlane.m_index - downsampling);
+ const short j1 = MIN(maxV[1], bestPlane.m_index + downsampling);
+ plane.m_a = 0.0;
+ plane.m_b = 1.0;
+ plane.m_c = 0.0;
+ plane.m_axis = AXIS_Y;
+ for (short j = j0; j <= j1; ++j) {
+ pt = vset.GetPoint(Vec3<double>(0.0, j + 0.5, 0.0));
+ plane.m_d = -pt[1];
+ plane.m_index = j;
+ planes.PushBack(plane);
+ }
+ }
+ else {
+ const short k0 = MAX(minV[2], bestPlane.m_index - downsampling);
+ const short k1 = MIN(maxV[2], bestPlane.m_index + downsampling);
+ plane.m_a = 0.0;
+ plane.m_b = 0.0;
+ plane.m_c = 1.0;
+ plane.m_axis = AXIS_Z;
+ for (short k = k0; k <= k1; ++k) {
+ pt = vset.GetPoint(Vec3<double>(0.0, 0.0, k + 0.5));
+ plane.m_d = -pt[2];
+ plane.m_index = k;
+ planes.PushBack(plane);
+ }
+ }
+}
+void RefineAxesAlignedClippingPlanes(const TetrahedronSet& tset, const Plane& bestPlane, const short downsampling,
+ SArray<Plane>& planes)
+{
+ const Vec3<double> minV = tset.GetMinBB();
+ const Vec3<double> maxV = tset.GetMaxBB();
+ const double scale = tset.GetSacle();
+ Plane plane;
+
+ if (bestPlane.m_axis == AXIS_X) {
+ const short i0 = MAX(0, bestPlane.m_index - downsampling);
+ const short i1 = static_cast<short>(MIN((maxV[0] - minV[0]) / scale + 0.5, bestPlane.m_index + downsampling));
+ plane.m_a = 1.0;
+ plane.m_b = 0.0;
+ plane.m_c = 0.0;
+ plane.m_axis = AXIS_X;
+ for (short i = i0; i <= i1; ++i) {
+ double x = minV[0] + scale * i;
+ plane.m_d = -x;
+ plane.m_index = i;
+ planes.PushBack(plane);
+ }
+ }
+ else if (bestPlane.m_axis == AXIS_Y) {
+ const short j0 = MAX(0, bestPlane.m_index - downsampling);
+ const short j1 = static_cast<short>(MIN((maxV[1] - minV[1]) / scale + 0.5, bestPlane.m_index + downsampling));
+ plane.m_a = 0.0;
+ plane.m_b = 1.0;
+ plane.m_c = 0.0;
+ plane.m_axis = AXIS_Y;
+ for (short j = j0; j <= j1; ++j) {
+ double y = minV[1] + scale * j;
+ plane.m_d = -y;
+ plane.m_index = j;
+ planes.PushBack(plane);
+ }
+ }
+ else {
+ const short k0 = MAX(0, bestPlane.m_index - downsampling);
+ const short k1 = static_cast<short>(MIN((maxV[2] - minV[2]) / scale + 0.5, bestPlane.m_index + downsampling));
+ plane.m_a = 0.0;
+ plane.m_b = 0.0;
+ plane.m_c = 1.0;
+ plane.m_axis = AXIS_Z;
+ for (short k = k0; k <= k1; ++k) {
+ double z = minV[2] + scale * k;
+ plane.m_d = -z;
+ plane.m_index = k;
+ planes.PushBack(plane);
+ }
+ }
+}
+inline double ComputeLocalConcavity(const double volume, const double volumeCH)
+{
+ return fabs(volumeCH - volume) / volumeCH;
+}
+inline double ComputeConcavity(const double volume, const double volumeCH, const double volume0)
+{
+ return fabs(volumeCH - volume) / volume0;
+}
+
+//#define DEBUG_TEMP
+void VHACD::ComputeBestClippingPlane(const PrimitiveSet* inputPSet, const double volume, const SArray<Plane>& planes,
+ const Vec3<double>& preferredCuttingDirection, const double w, const double alpha, const double beta,
+ const int32_t convexhullDownsampling, const double progress0, const double progress1, Plane& bestPlane,
+ double& minConcavity, const Parameters& params)
+{
+ if (GetCancel()) {
+ return;
+ }
+ char msg[256];
+ size_t nPrimitives = inputPSet->GetNPrimitives();
+ bool oclAcceleration = (nPrimitives > OCL_MIN_NUM_PRIMITIVES && params.m_oclAcceleration && params.m_mode == 0) ? true : false;
+ int32_t iBest = -1;
+ int32_t nPlanes = static_cast<int32_t>(planes.Size());
+ bool cancel = false;
+ int32_t done = 0;
+ double minTotal = MAX_DOUBLE;
+ double minBalance = MAX_DOUBLE;
+ double minSymmetry = MAX_DOUBLE;
+ minConcavity = MAX_DOUBLE;
+
+ SArray<Vec3<double> >* chPts = new SArray<Vec3<double> >[2 * m_ompNumProcessors];
+ Mesh* chs = new Mesh[2 * m_ompNumProcessors];
+ PrimitiveSet* onSurfacePSet = inputPSet->Create();
+ inputPSet->SelectOnSurface(onSurfacePSet);
+
+ PrimitiveSet** psets = 0;
+ if (!params.m_convexhullApproximation) {
+ psets = new PrimitiveSet*[2 * m_ompNumProcessors];
+ for (int32_t i = 0; i < 2 * m_ompNumProcessors; ++i) {
+ psets[i] = inputPSet->Create();
+ }
+ }
+
+#ifdef CL_VERSION_1_1
+ // allocate OpenCL data structures
+ cl_mem voxels;
+ cl_mem* partialVolumes = 0;
+ size_t globalSize = 0;
+ size_t nWorkGroups = 0;
+ double unitVolume = 0.0;
+ if (oclAcceleration) {
+ VoxelSet* vset = (VoxelSet*)inputPSet;
+ const Vec3<double> minBB = vset->GetMinBB();
+ const float fMinBB[4] = { (float)minBB[0], (float)minBB[1], (float)minBB[2], 1.0f };
+ const float fSclae[4] = { (float)vset->GetScale(), (float)vset->GetScale(), (float)vset->GetScale(), 0.0f };
+ const int32_t nVoxels = (int32_t)nPrimitives;
+ unitVolume = vset->GetUnitVolume();
+ nWorkGroups = (nPrimitives + 4 * m_oclWorkGroupSize - 1) / (4 * m_oclWorkGroupSize);
+ globalSize = nWorkGroups * m_oclWorkGroupSize;
+ cl_int error;
+ voxels = clCreateBuffer(m_oclContext,
+ CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
+ sizeof(Voxel) * nPrimitives,
+ vset->GetVoxels(),
+ &error);
+ if (error != CL_SUCCESS) {
+ if (params.m_logger) {
+ params.m_logger->Log("Couldn't create buffer\n");
+ }
+ SetCancel(true);
+ }
+
+ partialVolumes = new cl_mem[m_ompNumProcessors];
+ for (int32_t i = 0; i < m_ompNumProcessors; ++i) {
+ partialVolumes[i] = clCreateBuffer(m_oclContext,
+ CL_MEM_WRITE_ONLY,
+ sizeof(uint32_t) * 4 * nWorkGroups,
+ NULL,
+ &error);
+ if (error != CL_SUCCESS) {
+ if (params.m_logger) {
+ params.m_logger->Log("Couldn't create buffer\n");
+ }
+ SetCancel(true);
+ break;
+ }
+ error = clSetKernelArg(m_oclKernelComputePartialVolumes[i], 0, sizeof(cl_mem), &voxels);
+ error |= clSetKernelArg(m_oclKernelComputePartialVolumes[i], 1, sizeof(uint32_t), &nVoxels);
+ error |= clSetKernelArg(m_oclKernelComputePartialVolumes[i], 3, sizeof(float) * 4, fMinBB);
+ error |= clSetKernelArg(m_oclKernelComputePartialVolumes[i], 4, sizeof(float) * 4, &fSclae);
+ error |= clSetKernelArg(m_oclKernelComputePartialVolumes[i], 5, sizeof(uint32_t) * 4 * m_oclWorkGroupSize, NULL);
+ error |= clSetKernelArg(m_oclKernelComputePartialVolumes[i], 6, sizeof(cl_mem), &(partialVolumes[i]));
+ error |= clSetKernelArg(m_oclKernelComputeSum[i], 0, sizeof(cl_mem), &(partialVolumes[i]));
+ error |= clSetKernelArg(m_oclKernelComputeSum[i], 2, sizeof(uint32_t) * 4 * m_oclWorkGroupSize, NULL);
+ if (error != CL_SUCCESS) {
+ if (params.m_logger) {
+ params.m_logger->Log("Couldn't kernel arguments \n");
+ }
+ SetCancel(true);
+ }
+ }
+ }
+#else // CL_VERSION_1_1
+ oclAcceleration = false;
+#endif // CL_VERSION_1_1
+
+#ifdef DEBUG_TEMP
+ Timer timerComputeCost;
+ timerComputeCost.Tic();
+#endif // DEBUG_TEMP
+
+#if USE_THREAD == 1 && _OPENMP
+#pragma omp parallel for
+#endif
+ for (int32_t x = 0; x < nPlanes; ++x) {
+ int32_t threadID = 0;
+#if USE_THREAD == 1 && _OPENMP
+ threadID = omp_get_thread_num();
+#pragma omp flush(cancel)
+#endif
+ if (!cancel) {
+ //Update progress
+ if (GetCancel()) {
+ cancel = true;
+#if USE_THREAD == 1 && _OPENMP
+#pragma omp flush(cancel)
+#endif
+ }
+ Plane plane = planes[x];
+
+ if (oclAcceleration) {
+#ifdef CL_VERSION_1_1
+ const float fPlane[4] = { (float)plane.m_a, (float)plane.m_b, (float)plane.m_c, (float)plane.m_d };
+ cl_int error = clSetKernelArg(m_oclKernelComputePartialVolumes[threadID], 2, sizeof(float) * 4, fPlane);
+ if (error != CL_SUCCESS) {
+ if (params.m_logger) {
+ params.m_logger->Log("Couldn't kernel atguments \n");
+ }
+ SetCancel(true);
+ }
+
+ error = clEnqueueNDRangeKernel(m_oclQueue[threadID], m_oclKernelComputePartialVolumes[threadID],
+ 1, NULL, &globalSize, &m_oclWorkGroupSize, 0, NULL, NULL);
+ if (error != CL_SUCCESS) {
+ if (params.m_logger) {
+ params.m_logger->Log("Couldn't run kernel \n");
+ }
+ SetCancel(true);
+ }
+ int32_t nValues = (int32_t)nWorkGroups;
+ while (nValues > 1) {
+ error = clSetKernelArg(m_oclKernelComputeSum[threadID], 1, sizeof(int32_t), &nValues);
+ if (error != CL_SUCCESS) {
+ if (params.m_logger) {
+ params.m_logger->Log("Couldn't kernel atguments \n");
+ }
+ SetCancel(true);
+ }
+ size_t nWorkGroups = (nValues + m_oclWorkGroupSize - 1) / m_oclWorkGroupSize;
+ size_t globalSize = nWorkGroups * m_oclWorkGroupSize;
+ error = clEnqueueNDRangeKernel(m_oclQueue[threadID], m_oclKernelComputeSum[threadID],
+ 1, NULL, &globalSize, &m_oclWorkGroupSize, 0, NULL, NULL);
+ if (error != CL_SUCCESS) {
+ if (params.m_logger) {
+ params.m_logger->Log("Couldn't run kernel \n");
+ }
+ SetCancel(true);
+ }
+ nValues = (int32_t)nWorkGroups;
+ }
+#endif // CL_VERSION_1_1
+ }
+
+ Mesh& leftCH = chs[threadID];
+ Mesh& rightCH = chs[threadID + m_ompNumProcessors];
+ rightCH.ResizePoints(0);
+ leftCH.ResizePoints(0);
+ rightCH.ResizeTriangles(0);
+ leftCH.ResizeTriangles(0);
+
+// compute convex-hulls
+#ifdef TEST_APPROX_CH
+ double volumeLeftCH1;
+ double volumeRightCH1;
+#endif //TEST_APPROX_CH
+ if (params.m_convexhullApproximation) {
+ SArray<Vec3<double> >& leftCHPts = chPts[threadID];
+ SArray<Vec3<double> >& rightCHPts = chPts[threadID + m_ompNumProcessors];
+ rightCHPts.Resize(0);
+ leftCHPts.Resize(0);
+ onSurfacePSet->Intersect(plane, &rightCHPts, &leftCHPts, convexhullDownsampling * 32);
+ inputPSet->GetConvexHull().Clip(plane, rightCHPts, leftCHPts);
+ rightCH.ComputeConvexHull((double*)rightCHPts.Data(), rightCHPts.Size());
+ leftCH.ComputeConvexHull((double*)leftCHPts.Data(), leftCHPts.Size());
+#ifdef TEST_APPROX_CH
+ Mesh leftCH1;
+ Mesh rightCH1;
+ VoxelSet right;
+ VoxelSet left;
+ onSurfacePSet->Clip(plane, &right, &left);
+ right.ComputeConvexHull(rightCH1, convexhullDownsampling);
+ left.ComputeConvexHull(leftCH1, convexhullDownsampling);
+
+ volumeLeftCH1 = leftCH1.ComputeVolume();
+ volumeRightCH1 = rightCH1.ComputeVolume();
+#endif //TEST_APPROX_CH
+ }
+ else {
+ PrimitiveSet* const right = psets[threadID];
+ PrimitiveSet* const left = psets[threadID + m_ompNumProcessors];
+ onSurfacePSet->Clip(plane, right, left);
+ right->ComputeConvexHull(rightCH, convexhullDownsampling);
+ left->ComputeConvexHull(leftCH, convexhullDownsampling);
+ }
+ double volumeLeftCH = leftCH.ComputeVolume();
+ double volumeRightCH = rightCH.ComputeVolume();
+
+ // compute clipped volumes
+ double volumeLeft = 0.0;
+ double volumeRight = 0.0;
+ if (oclAcceleration) {
+#ifdef CL_VERSION_1_1
+ uint32_t volumes[4];
+ cl_int error = clEnqueueReadBuffer(m_oclQueue[threadID], partialVolumes[threadID], CL_TRUE,
+ 0, sizeof(uint32_t) * 4, volumes, 0, NULL, NULL);
+ size_t nPrimitivesRight = volumes[0] + volumes[1] + volumes[2] + volumes[3];
+ size_t nPrimitivesLeft = nPrimitives - nPrimitivesRight;
+ volumeRight = nPrimitivesRight * unitVolume;
+ volumeLeft = nPrimitivesLeft * unitVolume;
+ if (error != CL_SUCCESS) {
+ if (params.m_logger) {
+ params.m_logger->Log("Couldn't read buffer \n");
+ }
+ SetCancel(true);
+ }
+#endif // CL_VERSION_1_1
+ }
+ else {
+ inputPSet->ComputeClippedVolumes(plane, volumeRight, volumeLeft);
+ }
+ double concavityLeft = ComputeConcavity(volumeLeft, volumeLeftCH, m_volumeCH0);
+ double concavityRight = ComputeConcavity(volumeRight, volumeRightCH, m_volumeCH0);
+ double concavity = (concavityLeft + concavityRight);
+
+ // compute cost
+ double balance = alpha * fabs(volumeLeft - volumeRight) / m_volumeCH0;
+ double d = w * (preferredCuttingDirection[0] * plane.m_a + preferredCuttingDirection[1] * plane.m_b + preferredCuttingDirection[2] * plane.m_c);
+ double symmetry = beta * d;
+ double total = concavity + balance + symmetry;
+
+#if USE_THREAD == 1 && _OPENMP
+#pragma omp critical
+#endif
+ {
+ if (total < minTotal || (total == minTotal && x < iBest)) {
+ minConcavity = concavity;
+ minBalance = balance;
+ minSymmetry = symmetry;
+ bestPlane = plane;
+ minTotal = total;
+ iBest = x;
+ }
+ ++done;
+ if (!(done & 127)) // reduce update frequency
+ {
+ double progress = done * (progress1 - progress0) / nPlanes + progress0;
+ Update(m_stageProgress, progress, params);
+ }
+ }
+ }
+ }
+
+#ifdef DEBUG_TEMP
+ timerComputeCost.Toc();
+ printf_s("Cost[%i] = %f\n", nPlanes, timerComputeCost.GetElapsedTime());
+#endif // DEBUG_TEMP
+
+#ifdef CL_VERSION_1_1
+ if (oclAcceleration) {
+ clReleaseMemObject(voxels);
+ for (int32_t i = 0; i < m_ompNumProcessors; ++i) {
+ clReleaseMemObject(partialVolumes[i]);
+ }
+ delete[] partialVolumes;
+ }
+#endif // CL_VERSION_1_1
+
+ if (psets) {
+ for (int32_t i = 0; i < 2 * m_ompNumProcessors; ++i) {
+ delete psets[i];
+ }
+ delete[] psets;
+ }
+ delete onSurfacePSet;
+ delete[] chPts;
+ delete[] chs;
+ if (params.m_logger) {
+ sprintf(msg, "\n\t\t\t Best %04i T=%2.6f C=%2.6f B=%2.6f S=%2.6f (%1.1f, %1.1f, %1.1f, %3.3f)\n\n", iBest, minTotal, minConcavity, minBalance, minSymmetry, bestPlane.m_a, bestPlane.m_b, bestPlane.m_c, bestPlane.m_d);
+ params.m_logger->Log(msg);
+ }
+}
+void VHACD::ComputeACD(const Parameters& params)
+{
+ if (GetCancel()) {
+ return;
+ }
+ m_timer.Tic();
+
+ m_stage = "Approximate Convex Decomposition";
+ m_stageProgress = 0.0;
+ std::ostringstream msg;
+ if (params.m_logger) {
+ msg << "+ " << m_stage << std::endl;
+ params.m_logger->Log(msg.str().c_str());
+ }
+
+ SArray<PrimitiveSet*> parts;
+ SArray<PrimitiveSet*> inputParts;
+ SArray<PrimitiveSet*> temp;
+ inputParts.PushBack(m_pset);
+ m_pset = 0;
+ SArray<Plane> planes;
+ SArray<Plane> planesRef;
+ uint32_t sub = 0;
+ bool firstIteration = true;
+ m_volumeCH0 = 1.0;
+
+ // Compute the decomposition depth based on the number of convex hulls being requested..
+ uint32_t hullCount = 2;
+ uint32_t depth = 1;
+ while (params.m_maxConvexHulls > hullCount)
+ {
+ depth++;
+ hullCount *= 2;
+ }
+ // We must always increment the decomposition depth one higher than the maximum number of hulls requested.
+ // The reason for this is as follows.
+ // Say, for example, the user requests 32 convex hulls exactly. This would be a decomposition depth of 5.
+ // However, when we do that, we do *not* necessarily get 32 hulls as a result. This is because, during
+ // the recursive descent of the binary tree, one or more of the leaf nodes may have no concavity and
+ // will not be split. So, in this way, even with a decomposition depth of 5, you can produce fewer than
+ // 32 hulls. So, in this case, we would set the decomposition depth to 6 (producing up to as high as 64 convex hulls).
+ // Then, the merge step which combines over-described hulls down to the user requested amount, we will end up
+ // getting exactly 32 convex hulls as a result.
+ // We could just allow the artist to directly control the decomposition depth directly, but this would be a bit
+ // too complex and the preference is simply to let them specify how many hulls they want and derive the solution
+ // from that.
+ depth++;
+
+
+ while (sub++ < depth && inputParts.Size() > 0 && !m_cancel) {
+ msg.str("");
+ msg << "Subdivision level " << sub;
+ m_operation = msg.str();
+
+ if (params.m_logger) {
+ msg.str("");
+ msg << "\t Subdivision level " << sub << std::endl;
+ params.m_logger->Log(msg.str().c_str());
+ }
+
+ double maxConcavity = 0.0;
+ const size_t nInputParts = inputParts.Size();
+ Update(m_stageProgress, 0.0, params);
+ for (size_t p = 0; p < nInputParts && !m_cancel; ++p) {
+ const double progress0 = p * 100.0 / nInputParts;
+ const double progress1 = (p + 0.75) * 100.0 / nInputParts;
+ const double progress2 = (p + 1.00) * 100.0 / nInputParts;
+
+ Update(m_stageProgress, progress0, params);
+
+ PrimitiveSet* pset = inputParts[p];
+ inputParts[p] = 0;
+ double volume = pset->ComputeVolume();
+ pset->ComputeBB();
+ pset->ComputePrincipalAxes();
+ if (params.m_pca) {
+ pset->AlignToPrincipalAxes();
+ }
+
+ pset->ComputeConvexHull(pset->GetConvexHull());
+ double volumeCH = fabs(pset->GetConvexHull().ComputeVolume());
+ if (firstIteration) {
+ m_volumeCH0 = volumeCH;
+ }
+
+ double concavity = ComputeConcavity(volume, volumeCH, m_volumeCH0);
+ double error = 1.01 * pset->ComputeMaxVolumeError() / m_volumeCH0;
+
+ if (firstIteration) {
+ firstIteration = false;
+ }
+
+ if (params.m_logger) {
+ msg.str("");
+ msg << "\t -> Part[" << p
+ << "] C = " << concavity
+ << ", E = " << error
+ << ", VS = " << pset->GetNPrimitivesOnSurf()
+ << ", VI = " << pset->GetNPrimitivesInsideSurf()
+ << std::endl;
+ params.m_logger->Log(msg.str().c_str());
+ }
+
+ if (concavity > params.m_concavity && concavity > error) {
+ Vec3<double> preferredCuttingDirection;
+ double w = ComputePreferredCuttingDirection(pset, preferredCuttingDirection);
+ planes.Resize(0);
+ if (params.m_mode == 0) {
+ VoxelSet* vset = (VoxelSet*)pset;
+ ComputeAxesAlignedClippingPlanes(*vset, params.m_planeDownsampling, planes);
+ }
+ else {
+ TetrahedronSet* tset = (TetrahedronSet*)pset;
+ ComputeAxesAlignedClippingPlanes(*tset, params.m_planeDownsampling, planes);
+ }
+
+ if (params.m_logger) {
+ msg.str("");
+ msg << "\t\t [Regular sampling] Number of clipping planes " << planes.Size() << std::endl;
+ params.m_logger->Log(msg.str().c_str());
+ }
+
+ Plane bestPlane;
+ double minConcavity = MAX_DOUBLE;
+ ComputeBestClippingPlane(pset,
+ volume,
+ planes,
+ preferredCuttingDirection,
+ w,
+ concavity * params.m_alpha,
+ concavity * params.m_beta,
+ params.m_convexhullDownsampling,
+ progress0,
+ progress1,
+ bestPlane,
+ minConcavity,
+ params);
+ if (!m_cancel && (params.m_planeDownsampling > 1 || params.m_convexhullDownsampling > 1)) {
+ planesRef.Resize(0);
+
+ if (params.m_mode == 0) {
+ VoxelSet* vset = (VoxelSet*)pset;
+ RefineAxesAlignedClippingPlanes(*vset, bestPlane, params.m_planeDownsampling, planesRef);
+ }
+ else {
+ TetrahedronSet* tset = (TetrahedronSet*)pset;
+ RefineAxesAlignedClippingPlanes(*tset, bestPlane, params.m_planeDownsampling, planesRef);
+ }
+
+ if (params.m_logger) {
+ msg.str("");
+ msg << "\t\t [Refining] Number of clipping planes " << planesRef.Size() << std::endl;
+ params.m_logger->Log(msg.str().c_str());
+ }
+ ComputeBestClippingPlane(pset,
+ volume,
+ planesRef,
+ preferredCuttingDirection,
+ w,
+ concavity * params.m_alpha,
+ concavity * params.m_beta,
+ 1, // convexhullDownsampling = 1
+ progress1,
+ progress2,
+ bestPlane,
+ minConcavity,
+ params);
+ }
+ if (GetCancel()) {
+ delete pset; // clean up
+ break;
+ }
+ else {
+ if (maxConcavity < minConcavity) {
+ maxConcavity = minConcavity;
+ }
+ PrimitiveSet* bestLeft = pset->Create();
+ PrimitiveSet* bestRight = pset->Create();
+ temp.PushBack(bestLeft);
+ temp.PushBack(bestRight);
+ pset->Clip(bestPlane, bestRight, bestLeft);
+ if (params.m_pca) {
+ bestRight->RevertAlignToPrincipalAxes();
+ bestLeft->RevertAlignToPrincipalAxes();
+ }
+ delete pset;
+ }
+ }
+ else {
+ if (params.m_pca) {
+ pset->RevertAlignToPrincipalAxes();
+ }
+ parts.PushBack(pset);
+ }
+ }
+
+ Update(95.0 * (1.0 - maxConcavity) / (1.0 - params.m_concavity), 100.0, params);
+ if (GetCancel()) {
+ const size_t nTempParts = temp.Size();
+ for (size_t p = 0; p < nTempParts; ++p) {
+ delete temp[p];
+ }
+ temp.Resize(0);
+ }
+ else {
+ inputParts = temp;
+ temp.Resize(0);
+ }
+ }
+ const size_t nInputParts = inputParts.Size();
+ for (size_t p = 0; p < nInputParts; ++p) {
+ parts.PushBack(inputParts[p]);
+ }
+
+ if (GetCancel()) {
+ const size_t nParts = parts.Size();
+ for (size_t p = 0; p < nParts; ++p) {
+ delete parts[p];
+ }
+ return;
+ }
+
+ m_overallProgress = 90.0;
+ Update(m_stageProgress, 100.0, params);
+
+ msg.str("");
+ msg << "Generate convex-hulls";
+ m_operation = msg.str();
+ size_t nConvexHulls = parts.Size();
+ if (params.m_logger) {
+ msg.str("");
+ msg << "+ Generate " << nConvexHulls << " convex-hulls " << std::endl;
+ params.m_logger->Log(msg.str().c_str());
+ }
+
+ Update(m_stageProgress, 0.0, params);
+ m_convexHulls.Resize(0);
+ for (size_t p = 0; p < nConvexHulls && !m_cancel; ++p) {
+ Update(m_stageProgress, p * 100.0 / nConvexHulls, params);
+ m_convexHulls.PushBack(new Mesh);
+ parts[p]->ComputeConvexHull(*m_convexHulls[p]);
+ size_t nv = m_convexHulls[p]->GetNPoints();
+ double x, y, z;
+ for (size_t i = 0; i < nv; ++i) {
+ Vec3<double>& pt = m_convexHulls[p]->GetPoint(i);
+ x = pt[0];
+ y = pt[1];
+ z = pt[2];
+ pt[0] = m_rot[0][0] * x + m_rot[0][1] * y + m_rot[0][2] * z + m_barycenter[0];
+ pt[1] = m_rot[1][0] * x + m_rot[1][1] * y + m_rot[1][2] * z + m_barycenter[1];
+ pt[2] = m_rot[2][0] * x + m_rot[2][1] * y + m_rot[2][2] * z + m_barycenter[2];
+ }
+ }
+
+ const size_t nParts = parts.Size();
+ for (size_t p = 0; p < nParts; ++p) {
+ delete parts[p];
+ parts[p] = 0;
+ }
+ parts.Resize(0);
+
+ if (GetCancel()) {
+ const size_t nConvexHulls = m_convexHulls.Size();
+ for (size_t p = 0; p < nConvexHulls; ++p) {
+ delete m_convexHulls[p];
+ }
+ m_convexHulls.Clear();
+ return;
+ }
+
+ m_overallProgress = 95.0;
+ Update(100.0, 100.0, params);
+ m_timer.Toc();
+ if (params.m_logger) {
+ msg.str("");
+ msg << "\t time " << m_timer.GetElapsedTime() / 1000.0 << "s" << std::endl;
+ params.m_logger->Log(msg.str().c_str());
+ }
+}
+void AddPoints(const Mesh* const mesh, SArray<Vec3<double> >& pts)
+{
+ const int32_t n = (int32_t)mesh->GetNPoints();
+ for (int32_t i = 0; i < n; ++i) {
+ pts.PushBack(mesh->GetPoint(i));
+ }
+}
+void ComputeConvexHull(const Mesh* const ch1, const Mesh* const ch2, SArray<Vec3<double> >& pts, Mesh* const combinedCH)
+{
+ pts.Resize(0);
+ AddPoints(ch1, pts);
+ AddPoints(ch2, pts);
+
+ btConvexHullComputer ch;
+ ch.compute((double*)pts.Data(), 3 * sizeof(double), (int32_t)pts.Size(), -1.0, -1.0);
+ combinedCH->ResizePoints(0);
+ combinedCH->ResizeTriangles(0);
+ for (int32_t v = 0; v < ch.vertices.size(); v++) {
+ combinedCH->AddPoint(Vec3<double>(ch.vertices[v].getX(), ch.vertices[v].getY(), ch.vertices[v].getZ()));
+ }
+ const int32_t nt = ch.faces.size();
+ for (int32_t t = 0; t < nt; ++t) {
+ const btConvexHullComputer::Edge* sourceEdge = &(ch.edges[ch.faces[t]]);
+ int32_t a = sourceEdge->getSourceVertex();
+ int32_t b = sourceEdge->getTargetVertex();
+ const btConvexHullComputer::Edge* edge = sourceEdge->getNextEdgeOfFace();
+ int32_t c = edge->getTargetVertex();
+ while (c != a) {
+ combinedCH->AddTriangle(Vec3<int32_t>(a, b, c));
+ edge = edge->getNextEdgeOfFace();
+ b = c;
+ c = edge->getTargetVertex();
+ }
+ }
+}
+void VHACD::MergeConvexHulls(const Parameters& params)
+{
+ if (GetCancel()) {
+ return;
+ }
+ m_timer.Tic();
+
+ m_stage = "Merge Convex Hulls";
+
+ std::ostringstream msg;
+ if (params.m_logger) {
+ msg << "+ " << m_stage << std::endl;
+ params.m_logger->Log(msg.str().c_str());
+ }
+
+ // Get the current number of convex hulls
+ size_t nConvexHulls = m_convexHulls.Size();
+ // Iteration counter
+ int32_t iteration = 0;
+ // While we have more than at least one convex hull and the user has not asked us to cancel the operation
+ if (nConvexHulls > 1 && !m_cancel)
+ {
+ // Get the gamma error threshold for when to exit
+ SArray<Vec3<double> > pts;
+ Mesh combinedCH;
+
+ // Populate the cost matrix
+ size_t idx = 0;
+ SArray<float> costMatrix;
+ costMatrix.Resize(((nConvexHulls * nConvexHulls) - nConvexHulls) >> 1);
+ for (size_t p1 = 1; p1 < nConvexHulls; ++p1)
+ {
+ const float volume1 = m_convexHulls[p1]->ComputeVolume();
+ for (size_t p2 = 0; p2 < p1; ++p2)
+ {
+ ComputeConvexHull(m_convexHulls[p1], m_convexHulls[p2], pts, &combinedCH);
+ costMatrix[idx++] = ComputeConcavity(volume1 + m_convexHulls[p2]->ComputeVolume(), combinedCH.ComputeVolume(), m_volumeCH0);
+ }
+ }
+
+ // Until we cant merge below the maximum cost
+ size_t costSize = m_convexHulls.Size();
+ while (!m_cancel)
+ {
+ msg.str("");
+ msg << "Iteration " << iteration++;
+ m_operation = msg.str();
+
+ // Search for lowest cost
+ float bestCost = (std::numeric_limits<float>::max)();
+ const size_t addr = FindMinimumElement(costMatrix.Data(), &bestCost, 0, costMatrix.Size());
+ if ( (costSize-1) < params.m_maxConvexHulls)
+ {
+ break;
+ }
+ const size_t addrI = (static_cast<int32_t>(sqrt(1 + (8 * addr))) - 1) >> 1;
+ const size_t p1 = addrI + 1;
+ const size_t p2 = addr - ((addrI * (addrI + 1)) >> 1);
+ assert(p1 >= 0);
+ assert(p2 >= 0);
+ assert(p1 < costSize);
+ assert(p2 < costSize);
+
+ if (params.m_logger)
+ {
+ msg.str("");
+ msg << "\t\t Merging (" << p1 << ", " << p2 << ") " << bestCost << std::endl
+ << std::endl;
+ params.m_logger->Log(msg.str().c_str());
+ }
+
+ // Make the lowest cost row and column into a new hull
+ Mesh* cch = new Mesh;
+ ComputeConvexHull(m_convexHulls[p1], m_convexHulls[p2], pts, cch);
+ delete m_convexHulls[p2];
+ m_convexHulls[p2] = cch;
+
+ delete m_convexHulls[p1];
+ std::swap(m_convexHulls[p1], m_convexHulls[m_convexHulls.Size() - 1]);
+ m_convexHulls.PopBack();
+
+ costSize = costSize - 1;
+
+ // Calculate costs versus the new hull
+ size_t rowIdx = ((p2 - 1) * p2) >> 1;
+ const float volume1 = m_convexHulls[p2]->ComputeVolume();
+ for (size_t i = 0; (i < p2) && (!m_cancel); ++i)
+ {
+ ComputeConvexHull(m_convexHulls[p2], m_convexHulls[i], pts, &combinedCH);
+ costMatrix[rowIdx++] = ComputeConcavity(volume1 + m_convexHulls[i]->ComputeVolume(), combinedCH.ComputeVolume(), m_volumeCH0);
+ }
+
+ rowIdx += p2;
+ for (size_t i = p2 + 1; (i < costSize) && (!m_cancel); ++i)
+ {
+ ComputeConvexHull(m_convexHulls[p2], m_convexHulls[i], pts, &combinedCH);
+ costMatrix[rowIdx] = ComputeConcavity(volume1 + m_convexHulls[i]->ComputeVolume(), combinedCH.ComputeVolume(), m_volumeCH0);
+ rowIdx += i;
+ assert(rowIdx >= 0);
+ }
+
+ // Move the top column in to replace its space
+ const size_t erase_idx = ((costSize - 1) * costSize) >> 1;
+ if (p1 < costSize) {
+ rowIdx = (addrI * p1) >> 1;
+ size_t top_row = erase_idx;
+ for (size_t i = 0; i < p1; ++i) {
+ if (i != p2) {
+ costMatrix[rowIdx] = costMatrix[top_row];
+ }
+ ++rowIdx;
+ ++top_row;
+ }
+
+ ++top_row;
+ rowIdx += p1;
+ for (size_t i = p1 + 1; i < (costSize + 1); ++i) {
+ costMatrix[rowIdx] = costMatrix[top_row++];
+ rowIdx += i;
+ assert(rowIdx >= 0);
+ }
+ }
+ costMatrix.Resize(erase_idx);
+ }
+ }
+ m_overallProgress = 99.0;
+ Update(100.0, 100.0, params);
+ m_timer.Toc();
+ if (params.m_logger) {
+ msg.str("");
+ msg << "\t time " << m_timer.GetElapsedTime() / 1000.0 << "s" << std::endl;
+ params.m_logger->Log(msg.str().c_str());
+ }
+}
+void VHACD::SimplifyConvexHull(Mesh* const ch, const size_t nvertices, const double minVolume)
+{
+ if (nvertices <= 4) {
+ return;
+ }
+ ICHull icHull;
+ if (mRaycastMesh)
+ {
+ // We project these points onto the original source mesh to increase precision
+ // The voxelization process drops floating point precision so returned data points are not exactly lying on the
+ // surface of the original source mesh.
+ // The first step is we need to compute the bounding box of the mesh we are trying to build a convex hull for.
+ // From this bounding box, we compute the length of the diagonal to get a relative size and center for point projection
+ uint32_t nPoints = ch->GetNPoints();
+ Vec3<double> *inputPoints = ch->GetPointsBuffer();
+ Vec3<double> bmin(inputPoints[0]);
+ Vec3<double> bmax(inputPoints[1]);
+ for (uint32_t i = 1; i < nPoints; i++)
+ {
+ const Vec3<double> &p = inputPoints[i];
+ p.UpdateMinMax(bmin, bmax);
+ }
+ Vec3<double> center;
+ double diagonalLength = center.GetCenter(bmin, bmax); // Get the center of the bounding box
+ // This is the error threshold for determining if we should use the raycast result data point vs. the voxelized result.
+ double pointDistanceThreshold = diagonalLength * 0.05;
+ // If a new point is within 1/100th the diagonal length of the bounding volume we do not add it. To do so would create a
+ // thin sliver in the resulting convex hull
+ double snapDistanceThreshold = diagonalLength * 0.01;
+ double snapDistanceThresholdSquared = snapDistanceThreshold*snapDistanceThreshold;
+
+ // Allocate buffer for projected vertices
+ Vec3<double> *outputPoints = new Vec3<double>[nPoints];
+ uint32_t outCount = 0;
+ for (uint32_t i = 0; i < nPoints; i++)
+ {
+ Vec3<double> &inputPoint = inputPoints[i];
+ Vec3<double> &outputPoint = outputPoints[outCount];
+ // Compute the direction vector from the center of this mesh to the vertex
+ Vec3<double> dir = inputPoint - center;
+ // Normalize the direction vector.
+ dir.Normalize();
+ // Multiply times the diagonal length of the mesh
+ dir *= diagonalLength;
+ // Add the center back in again to get the destination point
+ dir += center;
+ // By default the output point is equal to the input point
+ outputPoint = inputPoint;
+ double pointDistance;
+ if (mRaycastMesh->raycast(center.GetData(), dir.GetData(), inputPoint.GetData(), outputPoint.GetData(),&pointDistance) )
+ {
+ // If the nearest intersection point is too far away, we keep the original source data point.
+ // Not all points lie directly on the original mesh surface
+ if (pointDistance > pointDistanceThreshold)
+ {
+ outputPoint = inputPoint;
+ }
+ }
+ // Ok, before we add this point, we do not want to create points which are extremely close to each other.
+ // This will result in tiny sliver triangles which are really bad for collision detection.
+ bool foundNearbyPoint = false;
+ for (uint32_t j = 0; j < outCount; j++)
+ {
+ // If this new point is extremely close to an existing point, we do not add it!
+ double squaredDistance = outputPoints[j].GetDistanceSquared(outputPoint);
+ if (squaredDistance < snapDistanceThresholdSquared )
+ {
+ foundNearbyPoint = true;
+ break;
+ }
+ }
+ if (!foundNearbyPoint)
+ {
+ outCount++;
+ }
+ }
+ icHull.AddPoints(outputPoints, outCount);
+ delete[]outputPoints;
+ }
+ else
+ {
+ icHull.AddPoints(ch->GetPointsBuffer(), ch->GetNPoints());
+ }
+ icHull.Process((uint32_t)nvertices, minVolume);
+ TMMesh& mesh = icHull.GetMesh();
+ const size_t nT = mesh.GetNTriangles();
+ const size_t nV = mesh.GetNVertices();
+ ch->ResizePoints(nV);
+ ch->ResizeTriangles(nT);
+ mesh.GetIFS(ch->GetPointsBuffer(), ch->GetTrianglesBuffer());
+}
+void VHACD::SimplifyConvexHulls(const Parameters& params)
+{
+ if (m_cancel || params.m_maxNumVerticesPerCH < 4) {
+ return;
+ }
+ m_timer.Tic();
+
+ m_stage = "Simplify convex-hulls";
+ m_operation = "Simplify convex-hulls";
+
+ std::ostringstream msg;
+ const size_t nConvexHulls = m_convexHulls.Size();
+ if (params.m_logger) {
+ msg << "+ Simplify " << nConvexHulls << " convex-hulls " << std::endl;
+ params.m_logger->Log(msg.str().c_str());
+ }
+
+ Update(0.0, 0.0, params);
+ for (size_t i = 0; i < nConvexHulls && !m_cancel; ++i) {
+ if (params.m_logger) {
+ msg.str("");
+ msg << "\t\t Simplify CH[" << std::setfill('0') << std::setw(5) << i << "] " << m_convexHulls[i]->GetNPoints() << " V, " << m_convexHulls[i]->GetNTriangles() << " T" << std::endl;
+ params.m_logger->Log(msg.str().c_str());
+ }
+ SimplifyConvexHull(m_convexHulls[i], params.m_maxNumVerticesPerCH, m_volumeCH0 * params.m_minVolumePerCH);
+ }
+
+ m_overallProgress = 100.0;
+ Update(100.0, 100.0, params);
+ m_timer.Toc();
+ if (params.m_logger) {
+ msg.str("");
+ msg << "\t time " << m_timer.GetElapsedTime() / 1000.0 << "s" << std::endl;
+ params.m_logger->Log(msg.str().c_str());
+ }
+}
+
+bool VHACD::ComputeCenterOfMass(double centerOfMass[3]) const
+{
+ bool ret = false;
+
+ centerOfMass[0] = 0;
+ centerOfMass[1] = 0;
+ centerOfMass[2] = 0;
+ // Get number of convex hulls in the result
+ uint32_t hullCount = GetNConvexHulls();
+ if (hullCount) // if we have results
+ {
+ ret = true;
+ double totalVolume = 0;
+ // Initialize the center of mass to zero
+ centerOfMass[0] = 0;
+ centerOfMass[1] = 0;
+ centerOfMass[2] = 0;
+ // Compute the total volume of all convex hulls
+ for (uint32_t i = 0; i < hullCount; i++)
+ {
+ ConvexHull ch;
+ GetConvexHull(i, ch);
+ totalVolume += ch.m_volume;
+ }
+ // compute the reciprocal of the total volume
+ double recipVolume = 1.0 / totalVolume;
+ // Add in the weighted by volume average of the center point of each convex hull
+ for (uint32_t i = 0; i < hullCount; i++)
+ {
+ ConvexHull ch;
+ GetConvexHull(i, ch);
+ double ratio = ch.m_volume*recipVolume;
+ centerOfMass[0] += ch.m_center[0] * ratio;
+ centerOfMass[1] += ch.m_center[1] * ratio;
+ centerOfMass[2] += ch.m_center[2] * ratio;
+ }
+ }
+ return ret;
+}
+
+} // end of VHACD namespace
diff --git a/thirdparty/vhacd/src/btAlignedAllocator.cpp b/thirdparty/vhacd/src/btAlignedAllocator.cpp
new file mode 100644
index 0000000000..8dee31e7e3
--- /dev/null
+++ b/thirdparty/vhacd/src/btAlignedAllocator.cpp
@@ -0,0 +1,192 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btAlignedAllocator.h"
+
+// -- GODOT start --
+namespace VHACD {
+// -- GODOT end --
+
+#ifdef _MSC_VER
+#pragma warning(disable:4311 4302)
+#endif
+
+int32_t gNumAlignedAllocs = 0;
+int32_t gNumAlignedFree = 0;
+int32_t gTotalBytesAlignedAllocs = 0; //detect memory leaks
+
+static void* btAllocDefault(size_t size)
+{
+ return malloc(size);
+}
+
+static void btFreeDefault(void* ptr)
+{
+ free(ptr);
+}
+
+static btAllocFunc* sAllocFunc = btAllocDefault;
+static btFreeFunc* sFreeFunc = btFreeDefault;
+
+#if defined(BT_HAS_ALIGNED_ALLOCATOR)
+#include <malloc.h>
+static void* btAlignedAllocDefault(size_t size, int32_t alignment)
+{
+ return _aligned_malloc(size, (size_t)alignment);
+}
+
+static void btAlignedFreeDefault(void* ptr)
+{
+ _aligned_free(ptr);
+}
+#elif defined(__CELLOS_LV2__)
+#include <stdlib.h>
+
+static inline void* btAlignedAllocDefault(size_t size, int32_t alignment)
+{
+ return memalign(alignment, size);
+}
+
+static inline void btAlignedFreeDefault(void* ptr)
+{
+ free(ptr);
+}
+#else
+static inline void* btAlignedAllocDefault(size_t size, int32_t alignment)
+{
+ void* ret;
+ char* real;
+ unsigned long offset;
+
+ real = (char*)sAllocFunc(size + sizeof(void*) + (alignment - 1));
+ if (real) {
+ // -- GODOT start --
+ // Synced with Bullet 2.88 to fix GH-27926
+ //offset = (alignment - (unsigned long)(real + sizeof(void*))) & (alignment - 1);
+ //ret = (void*)((real + sizeof(void*)) + offset);
+ ret = btAlignPointer(real + sizeof(void *), alignment);
+ // -- GODOT end --
+ *((void**)(ret)-1) = (void*)(real);
+ }
+ else {
+ ret = (void*)(real);
+ }
+ return (ret);
+}
+
+static inline void btAlignedFreeDefault(void* ptr)
+{
+ void* real;
+
+ if (ptr) {
+ real = *((void**)(ptr)-1);
+ sFreeFunc(real);
+ }
+}
+#endif
+
+static btAlignedAllocFunc* sAlignedAllocFunc = btAlignedAllocDefault;
+static btAlignedFreeFunc* sAlignedFreeFunc = btAlignedFreeDefault;
+
+void btAlignedAllocSetCustomAligned(btAlignedAllocFunc* allocFunc, btAlignedFreeFunc* freeFunc)
+{
+ sAlignedAllocFunc = allocFunc ? allocFunc : btAlignedAllocDefault;
+ sAlignedFreeFunc = freeFunc ? freeFunc : btAlignedFreeDefault;
+}
+
+void btAlignedAllocSetCustom(btAllocFunc* allocFunc, btFreeFunc* freeFunc)
+{
+ sAllocFunc = allocFunc ? allocFunc : btAllocDefault;
+ sFreeFunc = freeFunc ? freeFunc : btFreeDefault;
+}
+
+#ifdef BT_DEBUG_MEMORY_ALLOCATIONS
+//this generic allocator provides the total allocated number of bytes
+#include <stdio.h>
+
+void* btAlignedAllocInternal(size_t size, int32_t alignment, int32_t line, char* filename)
+{
+ void* ret;
+ char* real;
+ unsigned long offset;
+
+ gTotalBytesAlignedAllocs += size;
+ gNumAlignedAllocs++;
+
+ real = (char*)sAllocFunc(size + 2 * sizeof(void*) + (alignment - 1));
+ if (real) {
+ offset = (alignment - (unsigned long)(real + 2 * sizeof(void*))) & (alignment - 1);
+ ret = (void*)((real + 2 * sizeof(void*)) + offset);
+ *((void**)(ret)-1) = (void*)(real);
+ *((int32_t*)(ret)-2) = size;
+ }
+ else {
+ ret = (void*)(real); //??
+ }
+
+ printf("allocation#%d at address %x, from %s,line %d, size %d\n", gNumAlignedAllocs, real, filename, line, size);
+
+ int32_t* ptr = (int32_t*)ret;
+ *ptr = 12;
+ return (ret);
+}
+
+void btAlignedFreeInternal(void* ptr, int32_t line, char* filename)
+{
+
+ void* real;
+ gNumAlignedFree++;
+
+ if (ptr) {
+ real = *((void**)(ptr)-1);
+ int32_t size = *((int32_t*)(ptr)-2);
+ gTotalBytesAlignedAllocs -= size;
+
+ printf("free #%d at address %x, from %s,line %d, size %d\n", gNumAlignedFree, real, filename, line, size);
+
+ sFreeFunc(real);
+ }
+ else {
+ printf("NULL ptr\n");
+ }
+}
+
+#else //BT_DEBUG_MEMORY_ALLOCATIONS
+
+void* btAlignedAllocInternal(size_t size, int32_t alignment)
+{
+ gNumAlignedAllocs++;
+ void* ptr;
+ ptr = sAlignedAllocFunc(size, alignment);
+ // printf("btAlignedAllocInternal %d, %x\n",size,ptr);
+ return ptr;
+}
+
+void btAlignedFreeInternal(void* ptr)
+{
+ if (!ptr) {
+ return;
+ }
+
+ gNumAlignedFree++;
+ // printf("btAlignedFreeInternal %x\n",ptr);
+ sAlignedFreeFunc(ptr);
+}
+
+// -- GODOT start --
+}; // namespace VHACD
+// -- GODOT end --
+
+#endif //BT_DEBUG_MEMORY_ALLOCATIONS
diff --git a/thirdparty/vhacd/src/btConvexHullComputer.cpp b/thirdparty/vhacd/src/btConvexHullComputer.cpp
new file mode 100644
index 0000000000..8ab34af2ab
--- /dev/null
+++ b/thirdparty/vhacd/src/btConvexHullComputer.cpp
@@ -0,0 +1,2487 @@
+/*
+Copyright (c) 2011 Ole Kniemeyer, MAXON, www.maxon.net
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include <string.h>
+
+#include "btAlignedObjectArray.h"
+#include "btConvexHullComputer.h"
+#include "btMinMax.h"
+#include "btVector3.h"
+
+#ifdef __GNUC__
+#include <stdint.h>
+#elif defined(_MSC_VER)
+typedef __int32 int32_t;
+typedef __int64 int64_t;
+typedef unsigned __int32 uint32_t;
+typedef unsigned __int64 uint64_t;
+#else
+typedef int32_t int32_t;
+typedef long long int32_t int64_t;
+typedef uint32_t uint32_t;
+typedef unsigned long long int32_t uint64_t;
+#endif
+
+#ifdef _MSC_VER
+#pragma warning(disable:4458)
+#endif
+
+//The definition of USE_X86_64_ASM is moved into the build system. You can enable it manually by commenting out the following lines
+//#if (defined(__GNUC__) && defined(__x86_64__) && !defined(__ICL)) // || (defined(__ICL) && defined(_M_X64)) bug in Intel compiler, disable inline assembly
+// #define USE_X86_64_ASM
+//#endif
+
+//#define DEBUG_CONVEX_HULL
+//#define SHOW_ITERATIONS
+
+#if defined(DEBUG_CONVEX_HULL) || defined(SHOW_ITERATIONS)
+#include <stdio.h>
+#endif
+
+// -- GODOT start --
+namespace VHACD {
+// -- GODOT end --
+
+// Convex hull implementation based on Preparata and Hong
+// Ole Kniemeyer, MAXON Computer GmbH
+class btConvexHullInternal {
+public:
+ class Point64 {
+ public:
+ int64_t x;
+ int64_t y;
+ int64_t z;
+
+ Point64(int64_t x, int64_t y, int64_t z)
+ : x(x)
+ , y(y)
+ , z(z)
+ {
+ }
+
+ bool isZero()
+ {
+ return (x == 0) && (y == 0) && (z == 0);
+ }
+
+ int64_t dot(const Point64& b) const
+ {
+ return x * b.x + y * b.y + z * b.z;
+ }
+ };
+
+ class Point32 {
+ public:
+ int32_t x;
+ int32_t y;
+ int32_t z;
+ int32_t index;
+
+ Point32()
+ {
+ }
+
+ Point32(int32_t x, int32_t y, int32_t z)
+ : x(x)
+ , y(y)
+ , z(z)
+ , index(-1)
+ {
+ }
+
+ bool operator==(const Point32& b) const
+ {
+ return (x == b.x) && (y == b.y) && (z == b.z);
+ }
+
+ bool operator!=(const Point32& b) const
+ {
+ return (x != b.x) || (y != b.y) || (z != b.z);
+ }
+
+ bool isZero()
+ {
+ return (x == 0) && (y == 0) && (z == 0);
+ }
+
+ Point64 cross(const Point32& b) const
+ {
+ return Point64(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x);
+ }
+
+ Point64 cross(const Point64& b) const
+ {
+ return Point64(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x);
+ }
+
+ int64_t dot(const Point32& b) const
+ {
+ return x * b.x + y * b.y + z * b.z;
+ }
+
+ int64_t dot(const Point64& b) const
+ {
+ return x * b.x + y * b.y + z * b.z;
+ }
+
+ Point32 operator+(const Point32& b) const
+ {
+ return Point32(x + b.x, y + b.y, z + b.z);
+ }
+
+ Point32 operator-(const Point32& b) const
+ {
+ return Point32(x - b.x, y - b.y, z - b.z);
+ }
+ };
+
+ class Int128 {
+ public:
+ uint64_t low;
+ uint64_t high;
+
+ Int128()
+ {
+ }
+
+ Int128(uint64_t low, uint64_t high)
+ : low(low)
+ , high(high)
+ {
+ }
+
+ Int128(uint64_t low)
+ : low(low)
+ , high(0)
+ {
+ }
+
+ Int128(int64_t value)
+ : low(value)
+ , high((value >= 0) ? 0 : (uint64_t)-1LL)
+ {
+ }
+
+ static Int128 mul(int64_t a, int64_t b);
+
+ static Int128 mul(uint64_t a, uint64_t b);
+
+ Int128 operator-() const
+ {
+ return Int128((uint64_t) - (int64_t)low, ~high + (low == 0));
+ }
+
+ Int128 operator+(const Int128& b) const
+ {
+#ifdef USE_X86_64_ASM
+ Int128 result;
+ __asm__("addq %[bl], %[rl]\n\t"
+ "adcq %[bh], %[rh]\n\t"
+ : [rl] "=r"(result.low), [rh] "=r"(result.high)
+ : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
+ : "cc");
+ return result;
+#else
+ uint64_t lo = low + b.low;
+ return Int128(lo, high + b.high + (lo < low));
+#endif
+ }
+
+ Int128 operator-(const Int128& b) const
+ {
+#ifdef USE_X86_64_ASM
+ Int128 result;
+ __asm__("subq %[bl], %[rl]\n\t"
+ "sbbq %[bh], %[rh]\n\t"
+ : [rl] "=r"(result.low), [rh] "=r"(result.high)
+ : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
+ : "cc");
+ return result;
+#else
+ return *this + -b;
+#endif
+ }
+
+ Int128& operator+=(const Int128& b)
+ {
+#ifdef USE_X86_64_ASM
+ __asm__("addq %[bl], %[rl]\n\t"
+ "adcq %[bh], %[rh]\n\t"
+ : [rl] "=r"(low), [rh] "=r"(high)
+ : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
+ : "cc");
+#else
+ uint64_t lo = low + b.low;
+ if (lo < low) {
+ ++high;
+ }
+ low = lo;
+ high += b.high;
+#endif
+ return *this;
+ }
+
+ Int128& operator++()
+ {
+ if (++low == 0) {
+ ++high;
+ }
+ return *this;
+ }
+
+ Int128 operator*(int64_t b) const;
+
+ btScalar toScalar() const
+ {
+ return ((int64_t)high >= 0) ? btScalar(high) * (btScalar(0x100000000LL) * btScalar(0x100000000LL)) + btScalar(low)
+ : -(-*this).toScalar();
+ }
+
+ int32_t getSign() const
+ {
+ return ((int64_t)high < 0) ? -1 : (high || low) ? 1 : 0;
+ }
+
+ bool operator<(const Int128& b) const
+ {
+ return (high < b.high) || ((high == b.high) && (low < b.low));
+ }
+
+ int32_t ucmp(const Int128& b) const
+ {
+ if (high < b.high) {
+ return -1;
+ }
+ if (high > b.high) {
+ return 1;
+ }
+ if (low < b.low) {
+ return -1;
+ }
+ if (low > b.low) {
+ return 1;
+ }
+ return 0;
+ }
+ };
+
+ class Rational64 {
+ private:
+ uint64_t m_numerator;
+ uint64_t m_denominator;
+ int32_t sign;
+
+ public:
+ Rational64(int64_t numerator, int64_t denominator)
+ {
+ if (numerator > 0) {
+ sign = 1;
+ m_numerator = (uint64_t)numerator;
+ }
+ else if (numerator < 0) {
+ sign = -1;
+ m_numerator = (uint64_t)-numerator;
+ }
+ else {
+ sign = 0;
+ m_numerator = 0;
+ }
+ if (denominator > 0) {
+ m_denominator = (uint64_t)denominator;
+ }
+ else if (denominator < 0) {
+ sign = -sign;
+ m_denominator = (uint64_t)-denominator;
+ }
+ else {
+ m_denominator = 0;
+ }
+ }
+
+ bool isNegativeInfinity() const
+ {
+ return (sign < 0) && (m_denominator == 0);
+ }
+
+ bool isNaN() const
+ {
+ return (sign == 0) && (m_denominator == 0);
+ }
+
+ int32_t compare(const Rational64& b) const;
+
+ btScalar toScalar() const
+ {
+ return sign * ((m_denominator == 0) ? SIMD_INFINITY : (btScalar)m_numerator / m_denominator);
+ }
+ };
+
+ class Rational128 {
+ private:
+ Int128 numerator;
+ Int128 denominator;
+ int32_t sign;
+ bool isInt64;
+
+ public:
+ Rational128(int64_t value)
+ {
+ if (value > 0) {
+ sign = 1;
+ this->numerator = value;
+ }
+ else if (value < 0) {
+ sign = -1;
+ this->numerator = -value;
+ }
+ else {
+ sign = 0;
+ this->numerator = (uint64_t)0;
+ }
+ this->denominator = (uint64_t)1;
+ isInt64 = true;
+ }
+
+ Rational128(const Int128& numerator, const Int128& denominator)
+ {
+ sign = numerator.getSign();
+ if (sign >= 0) {
+ this->numerator = numerator;
+ }
+ else {
+ this->numerator = -numerator;
+ }
+ int32_t dsign = denominator.getSign();
+ if (dsign >= 0) {
+ this->denominator = denominator;
+ }
+ else {
+ sign = -sign;
+ this->denominator = -denominator;
+ }
+ isInt64 = false;
+ }
+
+ int32_t compare(const Rational128& b) const;
+
+ int32_t compare(int64_t b) const;
+
+ btScalar toScalar() const
+ {
+ return sign * ((denominator.getSign() == 0) ? SIMD_INFINITY : numerator.toScalar() / denominator.toScalar());
+ }
+ };
+
+ class PointR128 {
+ public:
+ Int128 x;
+ Int128 y;
+ Int128 z;
+ Int128 denominator;
+
+ PointR128()
+ {
+ }
+
+ PointR128(Int128 x, Int128 y, Int128 z, Int128 denominator)
+ : x(x)
+ , y(y)
+ , z(z)
+ , denominator(denominator)
+ {
+ }
+
+ btScalar xvalue() const
+ {
+ return x.toScalar() / denominator.toScalar();
+ }
+
+ btScalar yvalue() const
+ {
+ return y.toScalar() / denominator.toScalar();
+ }
+
+ btScalar zvalue() const
+ {
+ return z.toScalar() / denominator.toScalar();
+ }
+ };
+
+ class Edge;
+ class Face;
+
+ class Vertex {
+ public:
+ Vertex* next;
+ Vertex* prev;
+ Edge* edges;
+ Face* firstNearbyFace;
+ Face* lastNearbyFace;
+ PointR128 point128;
+ Point32 point;
+ int32_t copy;
+
+ Vertex()
+ : next(NULL)
+ , prev(NULL)
+ , edges(NULL)
+ , firstNearbyFace(NULL)
+ , lastNearbyFace(NULL)
+ , copy(-1)
+ {
+ }
+
+#ifdef DEBUG_CONVEX_HULL
+ void print()
+ {
+ printf("V%d (%d, %d, %d)", point.index, point.x, point.y, point.z);
+ }
+
+ void printGraph();
+#endif
+
+ Point32 operator-(const Vertex& b) const
+ {
+ return point - b.point;
+ }
+
+ Rational128 dot(const Point64& b) const
+ {
+ return (point.index >= 0) ? Rational128(point.dot(b))
+ : Rational128(point128.x * b.x + point128.y * b.y + point128.z * b.z, point128.denominator);
+ }
+
+ btScalar xvalue() const
+ {
+ return (point.index >= 0) ? btScalar(point.x) : point128.xvalue();
+ }
+
+ btScalar yvalue() const
+ {
+ return (point.index >= 0) ? btScalar(point.y) : point128.yvalue();
+ }
+
+ btScalar zvalue() const
+ {
+ return (point.index >= 0) ? btScalar(point.z) : point128.zvalue();
+ }
+
+ void receiveNearbyFaces(Vertex* src)
+ {
+ if (lastNearbyFace) {
+ lastNearbyFace->nextWithSameNearbyVertex = src->firstNearbyFace;
+ }
+ else {
+ firstNearbyFace = src->firstNearbyFace;
+ }
+ if (src->lastNearbyFace) {
+ lastNearbyFace = src->lastNearbyFace;
+ }
+ for (Face* f = src->firstNearbyFace; f; f = f->nextWithSameNearbyVertex) {
+ btAssert(f->nearbyVertex == src);
+ f->nearbyVertex = this;
+ }
+ src->firstNearbyFace = NULL;
+ src->lastNearbyFace = NULL;
+ }
+ };
+
+ class Edge {
+ public:
+ Edge* next;
+ Edge* prev;
+ Edge* reverse;
+ Vertex* target;
+ Face* face;
+ int32_t copy;
+
+ ~Edge()
+ {
+ next = NULL;
+ prev = NULL;
+ reverse = NULL;
+ target = NULL;
+ face = NULL;
+ }
+
+ void link(Edge* n)
+ {
+ btAssert(reverse->target == n->reverse->target);
+ next = n;
+ n->prev = this;
+ }
+
+#ifdef DEBUG_CONVEX_HULL
+ void print()
+ {
+ printf("E%p : %d -> %d, n=%p p=%p (0 %d\t%d\t%d) -> (%d %d %d)", this, reverse->target->point.index, target->point.index, next, prev,
+ reverse->target->point.x, reverse->target->point.y, reverse->target->point.z, target->point.x, target->point.y, target->point.z);
+ }
+#endif
+ };
+
+ class Face {
+ public:
+ Face* next;
+ Vertex* nearbyVertex;
+ Face* nextWithSameNearbyVertex;
+ Point32 origin;
+ Point32 dir0;
+ Point32 dir1;
+
+ Face()
+ : next(NULL)
+ , nearbyVertex(NULL)
+ , nextWithSameNearbyVertex(NULL)
+ {
+ }
+
+ void init(Vertex* a, Vertex* b, Vertex* c)
+ {
+ nearbyVertex = a;
+ origin = a->point;
+ dir0 = *b - *a;
+ dir1 = *c - *a;
+ if (a->lastNearbyFace) {
+ a->lastNearbyFace->nextWithSameNearbyVertex = this;
+ }
+ else {
+ a->firstNearbyFace = this;
+ }
+ a->lastNearbyFace = this;
+ }
+
+ Point64 getNormal()
+ {
+ return dir0.cross(dir1);
+ }
+ };
+
+ template <typename UWord, typename UHWord>
+ class DMul {
+ private:
+ static uint32_t high(uint64_t value)
+ {
+ return (uint32_t)(value >> 32);
+ }
+
+ static uint32_t low(uint64_t value)
+ {
+ return (uint32_t)value;
+ }
+
+ static uint64_t mul(uint32_t a, uint32_t b)
+ {
+ return (uint64_t)a * (uint64_t)b;
+ }
+
+ static void shlHalf(uint64_t& value)
+ {
+ value <<= 32;
+ }
+
+ static uint64_t high(Int128 value)
+ {
+ return value.high;
+ }
+
+ static uint64_t low(Int128 value)
+ {
+ return value.low;
+ }
+
+ static Int128 mul(uint64_t a, uint64_t b)
+ {
+ return Int128::mul(a, b);
+ }
+
+ static void shlHalf(Int128& value)
+ {
+ value.high = value.low;
+ value.low = 0;
+ }
+
+ public:
+ static void mul(UWord a, UWord b, UWord& resLow, UWord& resHigh)
+ {
+ UWord p00 = mul(low(a), low(b));
+ UWord p01 = mul(low(a), high(b));
+ UWord p10 = mul(high(a), low(b));
+ UWord p11 = mul(high(a), high(b));
+ UWord p0110 = UWord(low(p01)) + UWord(low(p10));
+ p11 += high(p01);
+ p11 += high(p10);
+ p11 += high(p0110);
+ shlHalf(p0110);
+ p00 += p0110;
+ if (p00 < p0110) {
+ ++p11;
+ }
+ resLow = p00;
+ resHigh = p11;
+ }
+ };
+
+private:
+ class IntermediateHull {
+ public:
+ Vertex* minXy;
+ Vertex* maxXy;
+ Vertex* minYx;
+ Vertex* maxYx;
+
+ IntermediateHull()
+ : minXy(NULL)
+ , maxXy(NULL)
+ , minYx(NULL)
+ , maxYx(NULL)
+ {
+ }
+
+ void print();
+ };
+
+ enum Orientation { NONE,
+ CLOCKWISE,
+ COUNTER_CLOCKWISE };
+
+ template <typename T>
+ class PoolArray {
+ private:
+ T* array;
+ int32_t size;
+
+ public:
+ PoolArray<T>* next;
+
+ PoolArray(int32_t size)
+ : size(size)
+ , next(NULL)
+ {
+ array = (T*)btAlignedAlloc(sizeof(T) * size, 16);
+ }
+
+ ~PoolArray()
+ {
+ btAlignedFree(array);
+ }
+
+ T* init()
+ {
+ T* o = array;
+ for (int32_t i = 0; i < size; i++, o++) {
+ o->next = (i + 1 < size) ? o + 1 : NULL;
+ }
+ return array;
+ }
+ };
+
+ template <typename T>
+ class Pool {
+ private:
+ PoolArray<T>* arrays;
+ PoolArray<T>* nextArray;
+ T* freeObjects;
+ int32_t arraySize;
+
+ public:
+ Pool()
+ : arrays(NULL)
+ , nextArray(NULL)
+ , freeObjects(NULL)
+ , arraySize(256)
+ {
+ }
+
+ ~Pool()
+ {
+ while (arrays) {
+ PoolArray<T>* p = arrays;
+ arrays = p->next;
+ p->~PoolArray<T>();
+ btAlignedFree(p);
+ }
+ }
+
+ void reset()
+ {
+ nextArray = arrays;
+ freeObjects = NULL;
+ }
+
+ void setArraySize(int32_t arraySize)
+ {
+ this->arraySize = arraySize;
+ }
+
+ T* newObject()
+ {
+ T* o = freeObjects;
+ if (!o) {
+ PoolArray<T>* p = nextArray;
+ if (p) {
+ nextArray = p->next;
+ }
+ else {
+ p = new (btAlignedAlloc(sizeof(PoolArray<T>), 16)) PoolArray<T>(arraySize);
+ p->next = arrays;
+ arrays = p;
+ }
+ o = p->init();
+ }
+ freeObjects = o->next;
+ return new (o) T();
+ };
+
+ void freeObject(T* object)
+ {
+ object->~T();
+ object->next = freeObjects;
+ freeObjects = object;
+ }
+ };
+
+ btVector3 scaling;
+ btVector3 center;
+ Pool<Vertex> vertexPool;
+ Pool<Edge> edgePool;
+ Pool<Face> facePool;
+ btAlignedObjectArray<Vertex*> originalVertices;
+ int32_t mergeStamp;
+ int32_t minAxis;
+ int32_t medAxis;
+ int32_t maxAxis;
+ int32_t usedEdgePairs;
+ int32_t maxUsedEdgePairs;
+
+ static Orientation getOrientation(const Edge* prev, const Edge* next, const Point32& s, const Point32& t);
+ Edge* findMaxAngle(bool ccw, const Vertex* start, const Point32& s, const Point64& rxs, const Point64& sxrxs, Rational64& minCot);
+ void findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge*& e0, Edge*& e1, Vertex* stop0, Vertex* stop1);
+
+ Edge* newEdgePair(Vertex* from, Vertex* to);
+
+ void removeEdgePair(Edge* edge)
+ {
+ Edge* n = edge->next;
+ Edge* r = edge->reverse;
+
+ btAssert(edge->target && r->target);
+
+ if (n != edge) {
+ n->prev = edge->prev;
+ edge->prev->next = n;
+ r->target->edges = n;
+ }
+ else {
+ r->target->edges = NULL;
+ }
+
+ n = r->next;
+
+ if (n != r) {
+ n->prev = r->prev;
+ r->prev->next = n;
+ edge->target->edges = n;
+ }
+ else {
+ edge->target->edges = NULL;
+ }
+
+ edgePool.freeObject(edge);
+ edgePool.freeObject(r);
+ usedEdgePairs--;
+ }
+
+ void computeInternal(int32_t start, int32_t end, IntermediateHull& result);
+
+ bool mergeProjection(IntermediateHull& h0, IntermediateHull& h1, Vertex*& c0, Vertex*& c1);
+
+ void merge(IntermediateHull& h0, IntermediateHull& h1);
+
+ btVector3 toBtVector(const Point32& v);
+
+ btVector3 getBtNormal(Face* face);
+
+ bool shiftFace(Face* face, btScalar amount, btAlignedObjectArray<Vertex*> stack);
+
+public:
+ Vertex* vertexList;
+
+ void compute(const void* coords, bool doubleCoords, int32_t stride, int32_t count);
+
+ btVector3 getCoordinates(const Vertex* v);
+
+ btScalar shrink(btScalar amount, btScalar clampAmount);
+};
+
+btConvexHullInternal::Int128 btConvexHullInternal::Int128::operator*(int64_t b) const
+{
+ bool negative = (int64_t)high < 0;
+ Int128 a = negative ? -*this : *this;
+ if (b < 0) {
+ negative = !negative;
+ b = -b;
+ }
+ Int128 result = mul(a.low, (uint64_t)b);
+ result.high += a.high * (uint64_t)b;
+ return negative ? -result : result;
+}
+
+btConvexHullInternal::Int128 btConvexHullInternal::Int128::mul(int64_t a, int64_t b)
+{
+ Int128 result;
+
+#ifdef USE_X86_64_ASM
+ __asm__("imulq %[b]"
+ : "=a"(result.low), "=d"(result.high)
+ : "0"(a), [b] "r"(b)
+ : "cc");
+ return result;
+
+#else
+ bool negative = a < 0;
+ if (negative) {
+ a = -a;
+ }
+ if (b < 0) {
+ negative = !negative;
+ b = -b;
+ }
+ DMul<uint64_t, uint32_t>::mul((uint64_t)a, (uint64_t)b, result.low, result.high);
+ return negative ? -result : result;
+#endif
+}
+
+btConvexHullInternal::Int128 btConvexHullInternal::Int128::mul(uint64_t a, uint64_t b)
+{
+ Int128 result;
+
+#ifdef USE_X86_64_ASM
+ __asm__("mulq %[b]"
+ : "=a"(result.low), "=d"(result.high)
+ : "0"(a), [b] "r"(b)
+ : "cc");
+
+#else
+ DMul<uint64_t, uint32_t>::mul(a, b, result.low, result.high);
+#endif
+
+ return result;
+}
+
+int32_t btConvexHullInternal::Rational64::compare(const Rational64& b) const
+{
+ if (sign != b.sign) {
+ return sign - b.sign;
+ }
+ else if (sign == 0) {
+ return 0;
+ }
+
+// return (numerator * b.denominator > b.numerator * denominator) ? sign : (numerator * b.denominator < b.numerator * denominator) ? -sign : 0;
+
+#ifdef USE_X86_64_ASM
+
+ int32_t result;
+ int64_t tmp;
+ int64_t dummy;
+ __asm__("mulq %[bn]\n\t"
+ "movq %%rax, %[tmp]\n\t"
+ "movq %%rdx, %%rbx\n\t"
+ "movq %[tn], %%rax\n\t"
+ "mulq %[bd]\n\t"
+ "subq %[tmp], %%rax\n\t"
+ "sbbq %%rbx, %%rdx\n\t" // rdx:rax contains 128-bit-difference "numerator*b.denominator - b.numerator*denominator"
+ "setnsb %%bh\n\t" // bh=1 if difference is non-negative, bh=0 otherwise
+ "orq %%rdx, %%rax\n\t"
+ "setnzb %%bl\n\t" // bl=1 if difference if non-zero, bl=0 if it is zero
+ "decb %%bh\n\t" // now bx=0x0000 if difference is zero, 0xff01 if it is negative, 0x0001 if it is positive (i.e., same sign as difference)
+ "shll $16, %%ebx\n\t" // ebx has same sign as difference
+ : "=&b"(result), [tmp] "=&r"(tmp), "=a"(dummy)
+ : "a"(denominator), [bn] "g"(b.numerator), [tn] "g"(numerator), [bd] "g"(b.denominator)
+ : "%rdx", "cc");
+ return result ? result ^ sign // if sign is +1, only bit 0 of result is inverted, which does not change the sign of result (and cannot result in zero)
+ // if sign is -1, all bits of result are inverted, which changes the sign of result (and again cannot result in zero)
+ : 0;
+
+#else
+
+ return sign * Int128::mul(m_numerator, b.m_denominator).ucmp(Int128::mul(m_denominator, b.m_numerator));
+
+#endif
+}
+
+int32_t btConvexHullInternal::Rational128::compare(const Rational128& b) const
+{
+ if (sign != b.sign) {
+ return sign - b.sign;
+ }
+ else if (sign == 0) {
+ return 0;
+ }
+ if (isInt64) {
+ return -b.compare(sign * (int64_t)numerator.low);
+ }
+
+ Int128 nbdLow, nbdHigh, dbnLow, dbnHigh;
+ DMul<Int128, uint64_t>::mul(numerator, b.denominator, nbdLow, nbdHigh);
+ DMul<Int128, uint64_t>::mul(denominator, b.numerator, dbnLow, dbnHigh);
+
+ int32_t cmp = nbdHigh.ucmp(dbnHigh);
+ if (cmp) {
+ return cmp * sign;
+ }
+ return nbdLow.ucmp(dbnLow) * sign;
+}
+
+int32_t btConvexHullInternal::Rational128::compare(int64_t b) const
+{
+ if (isInt64) {
+ int64_t a = sign * (int64_t)numerator.low;
+ return (a > b) ? 1 : (a < b) ? -1 : 0;
+ }
+ if (b > 0) {
+ if (sign <= 0) {
+ return -1;
+ }
+ }
+ else if (b < 0) {
+ if (sign >= 0) {
+ return 1;
+ }
+ b = -b;
+ }
+ else {
+ return sign;
+ }
+
+ return numerator.ucmp(denominator * b) * sign;
+}
+
+btConvexHullInternal::Edge* btConvexHullInternal::newEdgePair(Vertex* from, Vertex* to)
+{
+ btAssert(from && to);
+ Edge* e = edgePool.newObject();
+ Edge* r = edgePool.newObject();
+ e->reverse = r;
+ r->reverse = e;
+ e->copy = mergeStamp;
+ r->copy = mergeStamp;
+ e->target = to;
+ r->target = from;
+ e->face = NULL;
+ r->face = NULL;
+ usedEdgePairs++;
+ if (usedEdgePairs > maxUsedEdgePairs) {
+ maxUsedEdgePairs = usedEdgePairs;
+ }
+ return e;
+}
+
+bool btConvexHullInternal::mergeProjection(IntermediateHull& h0, IntermediateHull& h1, Vertex*& c0, Vertex*& c1)
+{
+ Vertex* v0 = h0.maxYx;
+ Vertex* v1 = h1.minYx;
+ if ((v0->point.x == v1->point.x) && (v0->point.y == v1->point.y)) {
+ btAssert(v0->point.z < v1->point.z);
+ Vertex* v1p = v1->prev;
+ if (v1p == v1) {
+ c0 = v0;
+ if (v1->edges) {
+ btAssert(v1->edges->next == v1->edges);
+ v1 = v1->edges->target;
+ btAssert(v1->edges->next == v1->edges);
+ }
+ c1 = v1;
+ return false;
+ }
+ Vertex* v1n = v1->next;
+ v1p->next = v1n;
+ v1n->prev = v1p;
+ if (v1 == h1.minXy) {
+ if ((v1n->point.x < v1p->point.x) || ((v1n->point.x == v1p->point.x) && (v1n->point.y < v1p->point.y))) {
+ h1.minXy = v1n;
+ }
+ else {
+ h1.minXy = v1p;
+ }
+ }
+ if (v1 == h1.maxXy) {
+ if ((v1n->point.x > v1p->point.x) || ((v1n->point.x == v1p->point.x) && (v1n->point.y > v1p->point.y))) {
+ h1.maxXy = v1n;
+ }
+ else {
+ h1.maxXy = v1p;
+ }
+ }
+ }
+
+ v0 = h0.maxXy;
+ v1 = h1.maxXy;
+ Vertex* v00 = NULL;
+ Vertex* v10 = NULL;
+ int32_t sign = 1;
+
+ for (int32_t side = 0; side <= 1; side++) {
+ int32_t dx = (v1->point.x - v0->point.x) * sign;
+ if (dx > 0) {
+ while (true) {
+ int32_t dy = v1->point.y - v0->point.y;
+
+ Vertex* w0 = side ? v0->next : v0->prev;
+ if (w0 != v0) {
+ int32_t dx0 = (w0->point.x - v0->point.x) * sign;
+ int32_t dy0 = w0->point.y - v0->point.y;
+ if ((dy0 <= 0) && ((dx0 == 0) || ((dx0 < 0) && (dy0 * dx <= dy * dx0)))) {
+ v0 = w0;
+ dx = (v1->point.x - v0->point.x) * sign;
+ continue;
+ }
+ }
+
+ Vertex* w1 = side ? v1->next : v1->prev;
+ if (w1 != v1) {
+ int32_t dx1 = (w1->point.x - v1->point.x) * sign;
+ int32_t dy1 = w1->point.y - v1->point.y;
+ int32_t dxn = (w1->point.x - v0->point.x) * sign;
+ if ((dxn > 0) && (dy1 < 0) && ((dx1 == 0) || ((dx1 < 0) && (dy1 * dx < dy * dx1)))) {
+ v1 = w1;
+ dx = dxn;
+ continue;
+ }
+ }
+
+ break;
+ }
+ }
+ else if (dx < 0) {
+ while (true) {
+ int32_t dy = v1->point.y - v0->point.y;
+
+ Vertex* w1 = side ? v1->prev : v1->next;
+ if (w1 != v1) {
+ int32_t dx1 = (w1->point.x - v1->point.x) * sign;
+ int32_t dy1 = w1->point.y - v1->point.y;
+ if ((dy1 >= 0) && ((dx1 == 0) || ((dx1 < 0) && (dy1 * dx <= dy * dx1)))) {
+ v1 = w1;
+ dx = (v1->point.x - v0->point.x) * sign;
+ continue;
+ }
+ }
+
+ Vertex* w0 = side ? v0->prev : v0->next;
+ if (w0 != v0) {
+ int32_t dx0 = (w0->point.x - v0->point.x) * sign;
+ int32_t dy0 = w0->point.y - v0->point.y;
+ int32_t dxn = (v1->point.x - w0->point.x) * sign;
+ if ((dxn < 0) && (dy0 > 0) && ((dx0 == 0) || ((dx0 < 0) && (dy0 * dx < dy * dx0)))) {
+ v0 = w0;
+ dx = dxn;
+ continue;
+ }
+ }
+
+ break;
+ }
+ }
+ else {
+ int32_t x = v0->point.x;
+ int32_t y0 = v0->point.y;
+ Vertex* w0 = v0;
+ Vertex* t;
+ while (((t = side ? w0->next : w0->prev) != v0) && (t->point.x == x) && (t->point.y <= y0)) {
+ w0 = t;
+ y0 = t->point.y;
+ }
+ v0 = w0;
+
+ int32_t y1 = v1->point.y;
+ Vertex* w1 = v1;
+ while (((t = side ? w1->prev : w1->next) != v1) && (t->point.x == x) && (t->point.y >= y1)) {
+ w1 = t;
+ y1 = t->point.y;
+ }
+ v1 = w1;
+ }
+
+ if (side == 0) {
+ v00 = v0;
+ v10 = v1;
+
+ v0 = h0.minXy;
+ v1 = h1.minXy;
+ sign = -1;
+ }
+ }
+
+ v0->prev = v1;
+ v1->next = v0;
+
+ v00->next = v10;
+ v10->prev = v00;
+
+ if (h1.minXy->point.x < h0.minXy->point.x) {
+ h0.minXy = h1.minXy;
+ }
+ if (h1.maxXy->point.x >= h0.maxXy->point.x) {
+ h0.maxXy = h1.maxXy;
+ }
+
+ h0.maxYx = h1.maxYx;
+
+ c0 = v00;
+ c1 = v10;
+
+ return true;
+}
+
+void btConvexHullInternal::computeInternal(int32_t start, int32_t end, IntermediateHull& result)
+{
+ int32_t n = end - start;
+ switch (n) {
+ case 0:
+ result.minXy = NULL;
+ result.maxXy = NULL;
+ result.minYx = NULL;
+ result.maxYx = NULL;
+ return;
+ case 2: {
+ Vertex* v = originalVertices[start];
+ Vertex* w = v + 1;
+ if (v->point != w->point) {
+ int32_t dx = v->point.x - w->point.x;
+ int32_t dy = v->point.y - w->point.y;
+
+ if ((dx == 0) && (dy == 0)) {
+ if (v->point.z > w->point.z) {
+ Vertex* t = w;
+ w = v;
+ v = t;
+ }
+ btAssert(v->point.z < w->point.z);
+ v->next = v;
+ v->prev = v;
+ result.minXy = v;
+ result.maxXy = v;
+ result.minYx = v;
+ result.maxYx = v;
+ }
+ else {
+ v->next = w;
+ v->prev = w;
+ w->next = v;
+ w->prev = v;
+
+ if ((dx < 0) || ((dx == 0) && (dy < 0))) {
+ result.minXy = v;
+ result.maxXy = w;
+ }
+ else {
+ result.minXy = w;
+ result.maxXy = v;
+ }
+
+ if ((dy < 0) || ((dy == 0) && (dx < 0))) {
+ result.minYx = v;
+ result.maxYx = w;
+ }
+ else {
+ result.minYx = w;
+ result.maxYx = v;
+ }
+ }
+
+ Edge* e = newEdgePair(v, w);
+ e->link(e);
+ v->edges = e;
+
+ e = e->reverse;
+ e->link(e);
+ w->edges = e;
+
+ return;
+ }
+ }
+ // lint -fallthrough
+ case 1: {
+ Vertex* v = originalVertices[start];
+ v->edges = NULL;
+ v->next = v;
+ v->prev = v;
+
+ result.minXy = v;
+ result.maxXy = v;
+ result.minYx = v;
+ result.maxYx = v;
+
+ return;
+ }
+ }
+
+ int32_t split0 = start + n / 2;
+ Point32 p = originalVertices[split0 - 1]->point;
+ int32_t split1 = split0;
+ while ((split1 < end) && (originalVertices[split1]->point == p)) {
+ split1++;
+ }
+ computeInternal(start, split0, result);
+ IntermediateHull hull1;
+ computeInternal(split1, end, hull1);
+#ifdef DEBUG_CONVEX_HULL
+ printf("\n\nMerge\n");
+ result.print();
+ hull1.print();
+#endif
+ merge(result, hull1);
+#ifdef DEBUG_CONVEX_HULL
+ printf("\n Result\n");
+ result.print();
+#endif
+}
+
+#ifdef DEBUG_CONVEX_HULL
+void btConvexHullInternal::IntermediateHull::print()
+{
+ printf(" Hull\n");
+ for (Vertex* v = minXy; v;) {
+ printf(" ");
+ v->print();
+ if (v == maxXy) {
+ printf(" maxXy");
+ }
+ if (v == minYx) {
+ printf(" minYx");
+ }
+ if (v == maxYx) {
+ printf(" maxYx");
+ }
+ if (v->next->prev != v) {
+ printf(" Inconsistency");
+ }
+ printf("\n");
+ v = v->next;
+ if (v == minXy) {
+ break;
+ }
+ }
+ if (minXy) {
+ minXy->copy = (minXy->copy == -1) ? -2 : -1;
+ minXy->printGraph();
+ }
+}
+
+void btConvexHullInternal::Vertex::printGraph()
+{
+ print();
+ printf("\nEdges\n");
+ Edge* e = edges;
+ if (e) {
+ do {
+ e->print();
+ printf("\n");
+ e = e->next;
+ } while (e != edges);
+ do {
+ Vertex* v = e->target;
+ if (v->copy != copy) {
+ v->copy = copy;
+ v->printGraph();
+ }
+ e = e->next;
+ } while (e != edges);
+ }
+}
+#endif
+
+btConvexHullInternal::Orientation btConvexHullInternal::getOrientation(const Edge* prev, const Edge* next, const Point32& s, const Point32& t)
+{
+ btAssert(prev->reverse->target == next->reverse->target);
+ if (prev->next == next) {
+ if (prev->prev == next) {
+ Point64 n = t.cross(s);
+ Point64 m = (*prev->target - *next->reverse->target).cross(*next->target - *next->reverse->target);
+ btAssert(!m.isZero());
+ int64_t dot = n.dot(m);
+ btAssert(dot != 0);
+ return (dot > 0) ? COUNTER_CLOCKWISE : CLOCKWISE;
+ }
+ return COUNTER_CLOCKWISE;
+ }
+ else if (prev->prev == next) {
+ return CLOCKWISE;
+ }
+ else {
+ return NONE;
+ }
+}
+
+btConvexHullInternal::Edge* btConvexHullInternal::findMaxAngle(bool ccw, const Vertex* start, const Point32& s, const Point64& rxs, const Point64& sxrxs, Rational64& minCot)
+{
+ Edge* minEdge = NULL;
+
+#ifdef DEBUG_CONVEX_HULL
+ printf("find max edge for %d\n", start->point.index);
+#endif
+ Edge* e = start->edges;
+ if (e) {
+ do {
+ if (e->copy > mergeStamp) {
+ Point32 t = *e->target - *start;
+ Rational64 cot(t.dot(sxrxs), t.dot(rxs));
+#ifdef DEBUG_CONVEX_HULL
+ printf(" Angle is %f (%d) for ", (float)btAtan(cot.toScalar()), (int32_t)cot.isNaN());
+ e->print();
+#endif
+ if (cot.isNaN()) {
+ btAssert(ccw ? (t.dot(s) < 0) : (t.dot(s) > 0));
+ }
+ else {
+ int32_t cmp;
+ if (minEdge == NULL) {
+ minCot = cot;
+ minEdge = e;
+ }
+ else if ((cmp = cot.compare(minCot)) < 0) {
+ minCot = cot;
+ minEdge = e;
+ }
+ else if ((cmp == 0) && (ccw == (getOrientation(minEdge, e, s, t) == COUNTER_CLOCKWISE))) {
+ minEdge = e;
+ }
+ }
+#ifdef DEBUG_CONVEX_HULL
+ printf("\n");
+#endif
+ }
+ e = e->next;
+ } while (e != start->edges);
+ }
+ return minEdge;
+}
+
+void btConvexHullInternal::findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge*& e0, Edge*& e1, Vertex* stop0, Vertex* stop1)
+{
+ Edge* start0 = e0;
+ Edge* start1 = e1;
+ Point32 et0 = start0 ? start0->target->point : c0->point;
+ Point32 et1 = start1 ? start1->target->point : c1->point;
+ Point32 s = c1->point - c0->point;
+ Point64 normal = ((start0 ? start0 : start1)->target->point - c0->point).cross(s);
+ int64_t dist = c0->point.dot(normal);
+ btAssert(!start1 || (start1->target->point.dot(normal) == dist));
+ Point64 perp = s.cross(normal);
+ btAssert(!perp.isZero());
+
+#ifdef DEBUG_CONVEX_HULL
+ printf(" Advancing %d %d (%p %p, %d %d)\n", c0->point.index, c1->point.index, start0, start1, start0 ? start0->target->point.index : -1, start1 ? start1->target->point.index : -1);
+#endif
+
+ int64_t maxDot0 = et0.dot(perp);
+ if (e0) {
+ while (e0->target != stop0) {
+ Edge* e = e0->reverse->prev;
+ if (e->target->point.dot(normal) < dist) {
+ break;
+ }
+ btAssert(e->target->point.dot(normal) == dist);
+ if (e->copy == mergeStamp) {
+ break;
+ }
+ int64_t dot = e->target->point.dot(perp);
+ if (dot <= maxDot0) {
+ break;
+ }
+ maxDot0 = dot;
+ e0 = e;
+ et0 = e->target->point;
+ }
+ }
+
+ int64_t maxDot1 = et1.dot(perp);
+ if (e1) {
+ while (e1->target != stop1) {
+ Edge* e = e1->reverse->next;
+ if (e->target->point.dot(normal) < dist) {
+ break;
+ }
+ btAssert(e->target->point.dot(normal) == dist);
+ if (e->copy == mergeStamp) {
+ break;
+ }
+ int64_t dot = e->target->point.dot(perp);
+ if (dot <= maxDot1) {
+ break;
+ }
+ maxDot1 = dot;
+ e1 = e;
+ et1 = e->target->point;
+ }
+ }
+
+#ifdef DEBUG_CONVEX_HULL
+ printf(" Starting at %d %d\n", et0.index, et1.index);
+#endif
+
+ int64_t dx = maxDot1 - maxDot0;
+ if (dx > 0) {
+ while (true) {
+ int64_t dy = (et1 - et0).dot(s);
+
+ if (e0 && (e0->target != stop0)) {
+ Edge* f0 = e0->next->reverse;
+ if (f0->copy > mergeStamp) {
+ int64_t dx0 = (f0->target->point - et0).dot(perp);
+ int64_t dy0 = (f0->target->point - et0).dot(s);
+ if ((dx0 == 0) ? (dy0 < 0) : ((dx0 < 0) && (Rational64(dy0, dx0).compare(Rational64(dy, dx)) >= 0))) {
+ et0 = f0->target->point;
+ dx = (et1 - et0).dot(perp);
+ e0 = (e0 == start0) ? NULL : f0;
+ continue;
+ }
+ }
+ }
+
+ if (e1 && (e1->target != stop1)) {
+ Edge* f1 = e1->reverse->next;
+ if (f1->copy > mergeStamp) {
+ Point32 d1 = f1->target->point - et1;
+ if (d1.dot(normal) == 0) {
+ int64_t dx1 = d1.dot(perp);
+ int64_t dy1 = d1.dot(s);
+ int64_t dxn = (f1->target->point - et0).dot(perp);
+ if ((dxn > 0) && ((dx1 == 0) ? (dy1 < 0) : ((dx1 < 0) && (Rational64(dy1, dx1).compare(Rational64(dy, dx)) > 0)))) {
+ e1 = f1;
+ et1 = e1->target->point;
+ dx = dxn;
+ continue;
+ }
+ }
+ else {
+ btAssert((e1 == start1) && (d1.dot(normal) < 0));
+ }
+ }
+ }
+
+ break;
+ }
+ }
+ else if (dx < 0) {
+ while (true) {
+ int64_t dy = (et1 - et0).dot(s);
+
+ if (e1 && (e1->target != stop1)) {
+ Edge* f1 = e1->prev->reverse;
+ if (f1->copy > mergeStamp) {
+ int64_t dx1 = (f1->target->point - et1).dot(perp);
+ int64_t dy1 = (f1->target->point - et1).dot(s);
+ if ((dx1 == 0) ? (dy1 > 0) : ((dx1 < 0) && (Rational64(dy1, dx1).compare(Rational64(dy, dx)) <= 0))) {
+ et1 = f1->target->point;
+ dx = (et1 - et0).dot(perp);
+ e1 = (e1 == start1) ? NULL : f1;
+ continue;
+ }
+ }
+ }
+
+ if (e0 && (e0->target != stop0)) {
+ Edge* f0 = e0->reverse->prev;
+ if (f0->copy > mergeStamp) {
+ Point32 d0 = f0->target->point - et0;
+ if (d0.dot(normal) == 0) {
+ int64_t dx0 = d0.dot(perp);
+ int64_t dy0 = d0.dot(s);
+ int64_t dxn = (et1 - f0->target->point).dot(perp);
+ if ((dxn < 0) && ((dx0 == 0) ? (dy0 > 0) : ((dx0 < 0) && (Rational64(dy0, dx0).compare(Rational64(dy, dx)) < 0)))) {
+ e0 = f0;
+ et0 = e0->target->point;
+ dx = dxn;
+ continue;
+ }
+ }
+ else {
+ btAssert((e0 == start0) && (d0.dot(normal) < 0));
+ }
+ }
+ }
+
+ break;
+ }
+ }
+#ifdef DEBUG_CONVEX_HULL
+ printf(" Advanced edges to %d %d\n", et0.index, et1.index);
+#endif
+}
+
+void btConvexHullInternal::merge(IntermediateHull& h0, IntermediateHull& h1)
+{
+ if (!h1.maxXy) {
+ return;
+ }
+ if (!h0.maxXy) {
+ h0 = h1;
+ return;
+ }
+
+ mergeStamp--;
+
+ Vertex* c0 = NULL;
+ Edge* toPrev0 = NULL;
+ Edge* firstNew0 = NULL;
+ Edge* pendingHead0 = NULL;
+ Edge* pendingTail0 = NULL;
+ Vertex* c1 = NULL;
+ Edge* toPrev1 = NULL;
+ Edge* firstNew1 = NULL;
+ Edge* pendingHead1 = NULL;
+ Edge* pendingTail1 = NULL;
+ Point32 prevPoint;
+
+ if (mergeProjection(h0, h1, c0, c1)) {
+ Point32 s = *c1 - *c0;
+ Point64 normal = Point32(0, 0, -1).cross(s);
+ Point64 t = s.cross(normal);
+ btAssert(!t.isZero());
+
+ Edge* e = c0->edges;
+ Edge* start0 = NULL;
+ if (e) {
+ do {
+ int64_t dot = (*e->target - *c0).dot(normal);
+ btAssert(dot <= 0);
+ if ((dot == 0) && ((*e->target - *c0).dot(t) > 0)) {
+ if (!start0 || (getOrientation(start0, e, s, Point32(0, 0, -1)) == CLOCKWISE)) {
+ start0 = e;
+ }
+ }
+ e = e->next;
+ } while (e != c0->edges);
+ }
+
+ e = c1->edges;
+ Edge* start1 = NULL;
+ if (e) {
+ do {
+ int64_t dot = (*e->target - *c1).dot(normal);
+ btAssert(dot <= 0);
+ if ((dot == 0) && ((*e->target - *c1).dot(t) > 0)) {
+ if (!start1 || (getOrientation(start1, e, s, Point32(0, 0, -1)) == COUNTER_CLOCKWISE)) {
+ start1 = e;
+ }
+ }
+ e = e->next;
+ } while (e != c1->edges);
+ }
+
+ if (start0 || start1) {
+ findEdgeForCoplanarFaces(c0, c1, start0, start1, NULL, NULL);
+ if (start0) {
+ c0 = start0->target;
+ }
+ if (start1) {
+ c1 = start1->target;
+ }
+ }
+
+ prevPoint = c1->point;
+ prevPoint.z++;
+ }
+ else {
+ prevPoint = c1->point;
+ prevPoint.x++;
+ }
+
+ Vertex* first0 = c0;
+ Vertex* first1 = c1;
+ bool firstRun = true;
+
+ while (true) {
+ Point32 s = *c1 - *c0;
+ Point32 r = prevPoint - c0->point;
+ Point64 rxs = r.cross(s);
+ Point64 sxrxs = s.cross(rxs);
+
+#ifdef DEBUG_CONVEX_HULL
+ printf("\n Checking %d %d\n", c0->point.index, c1->point.index);
+#endif
+ Rational64 minCot0(0, 0);
+ Edge* min0 = findMaxAngle(false, c0, s, rxs, sxrxs, minCot0);
+ Rational64 minCot1(0, 0);
+ Edge* min1 = findMaxAngle(true, c1, s, rxs, sxrxs, minCot1);
+ if (!min0 && !min1) {
+ Edge* e = newEdgePair(c0, c1);
+ e->link(e);
+ c0->edges = e;
+
+ e = e->reverse;
+ e->link(e);
+ c1->edges = e;
+ return;
+ }
+ else {
+ int32_t cmp = !min0 ? 1 : !min1 ? -1 : minCot0.compare(minCot1);
+#ifdef DEBUG_CONVEX_HULL
+ printf(" -> Result %d\n", cmp);
+#endif
+ if (firstRun || ((cmp >= 0) ? !minCot1.isNegativeInfinity() : !minCot0.isNegativeInfinity())) {
+ Edge* e = newEdgePair(c0, c1);
+ if (pendingTail0) {
+ pendingTail0->prev = e;
+ }
+ else {
+ pendingHead0 = e;
+ }
+ e->next = pendingTail0;
+ pendingTail0 = e;
+
+ e = e->reverse;
+ if (pendingTail1) {
+ pendingTail1->next = e;
+ }
+ else {
+ pendingHead1 = e;
+ }
+ e->prev = pendingTail1;
+ pendingTail1 = e;
+ }
+
+ Edge* e0 = min0;
+ Edge* e1 = min1;
+
+#ifdef DEBUG_CONVEX_HULL
+ printf(" Found min edges to %d %d\n", e0 ? e0->target->point.index : -1, e1 ? e1->target->point.index : -1);
+#endif
+
+ if (cmp == 0) {
+ findEdgeForCoplanarFaces(c0, c1, e0, e1, NULL, NULL);
+ }
+
+ if ((cmp >= 0) && e1) {
+ if (toPrev1) {
+ for (Edge *e = toPrev1->next, *n = NULL; e != min1; e = n) {
+ n = e->next;
+ removeEdgePair(e);
+ }
+ }
+
+ if (pendingTail1) {
+ if (toPrev1) {
+ toPrev1->link(pendingHead1);
+ }
+ else {
+ min1->prev->link(pendingHead1);
+ firstNew1 = pendingHead1;
+ }
+ pendingTail1->link(min1);
+ pendingHead1 = NULL;
+ pendingTail1 = NULL;
+ }
+ else if (!toPrev1) {
+ firstNew1 = min1;
+ }
+
+ prevPoint = c1->point;
+ c1 = e1->target;
+ toPrev1 = e1->reverse;
+ }
+
+ if ((cmp <= 0) && e0) {
+ if (toPrev0) {
+ for (Edge *e = toPrev0->prev, *n = NULL; e != min0; e = n) {
+ n = e->prev;
+ removeEdgePair(e);
+ }
+ }
+
+ if (pendingTail0) {
+ if (toPrev0) {
+ pendingHead0->link(toPrev0);
+ }
+ else {
+ pendingHead0->link(min0->next);
+ firstNew0 = pendingHead0;
+ }
+ min0->link(pendingTail0);
+ pendingHead0 = NULL;
+ pendingTail0 = NULL;
+ }
+ else if (!toPrev0) {
+ firstNew0 = min0;
+ }
+
+ prevPoint = c0->point;
+ c0 = e0->target;
+ toPrev0 = e0->reverse;
+ }
+ }
+
+ if ((c0 == first0) && (c1 == first1)) {
+ if (toPrev0 == NULL) {
+ pendingHead0->link(pendingTail0);
+ c0->edges = pendingTail0;
+ }
+ else {
+ for (Edge *e = toPrev0->prev, *n = NULL; e != firstNew0; e = n) {
+ n = e->prev;
+ removeEdgePair(e);
+ }
+ if (pendingTail0) {
+ pendingHead0->link(toPrev0);
+ firstNew0->link(pendingTail0);
+ }
+ }
+
+ if (toPrev1 == NULL) {
+ pendingTail1->link(pendingHead1);
+ c1->edges = pendingTail1;
+ }
+ else {
+ for (Edge *e = toPrev1->next, *n = NULL; e != firstNew1; e = n) {
+ n = e->next;
+ removeEdgePair(e);
+ }
+ if (pendingTail1) {
+ toPrev1->link(pendingHead1);
+ pendingTail1->link(firstNew1);
+ }
+ }
+
+ return;
+ }
+
+ firstRun = false;
+ }
+}
+
+static bool pointCmp(const btConvexHullInternal::Point32& p, const btConvexHullInternal::Point32& q)
+{
+ return (p.y < q.y) || ((p.y == q.y) && ((p.x < q.x) || ((p.x == q.x) && (p.z < q.z))));
+}
+
+void btConvexHullInternal::compute(const void* coords, bool doubleCoords, int32_t stride, int32_t count)
+{
+ btVector3 min(btScalar(1e30), btScalar(1e30), btScalar(1e30)), max(btScalar(-1e30), btScalar(-1e30), btScalar(-1e30));
+ const char* ptr = (const char*)coords;
+ if (doubleCoords) {
+ for (int32_t i = 0; i < count; i++) {
+ const double* v = (const double*)ptr;
+ btVector3 p((btScalar)v[0], (btScalar)v[1], (btScalar)v[2]);
+ ptr += stride;
+ min.setMin(p);
+ max.setMax(p);
+ }
+ }
+ else {
+ for (int32_t i = 0; i < count; i++) {
+ const float* v = (const float*)ptr;
+ btVector3 p(v[0], v[1], v[2]);
+ ptr += stride;
+ min.setMin(p);
+ max.setMax(p);
+ }
+ }
+
+ btVector3 s = max - min;
+ maxAxis = s.maxAxis();
+ minAxis = s.minAxis();
+ if (minAxis == maxAxis) {
+ minAxis = (maxAxis + 1) % 3;
+ }
+ medAxis = 3 - maxAxis - minAxis;
+
+ s /= btScalar(10216);
+ if (((medAxis + 1) % 3) != maxAxis) {
+ s *= -1;
+ }
+ scaling = s;
+
+ if (s[0] != 0) {
+ s[0] = btScalar(1) / s[0];
+ }
+ if (s[1] != 0) {
+ s[1] = btScalar(1) / s[1];
+ }
+ if (s[2] != 0) {
+ s[2] = btScalar(1) / s[2];
+ }
+
+ center = (min + max) * btScalar(0.5);
+
+ btAlignedObjectArray<Point32> points;
+ points.resize(count);
+ ptr = (const char*)coords;
+ if (doubleCoords) {
+ for (int32_t i = 0; i < count; i++) {
+ const double* v = (const double*)ptr;
+ btVector3 p((btScalar)v[0], (btScalar)v[1], (btScalar)v[2]);
+ ptr += stride;
+ p = (p - center) * s;
+ points[i].x = (int32_t)p[medAxis];
+ points[i].y = (int32_t)p[maxAxis];
+ points[i].z = (int32_t)p[minAxis];
+ points[i].index = i;
+ }
+ }
+ else {
+ for (int32_t i = 0; i < count; i++) {
+ const float* v = (const float*)ptr;
+ btVector3 p(v[0], v[1], v[2]);
+ ptr += stride;
+ p = (p - center) * s;
+ points[i].x = (int32_t)p[medAxis];
+ points[i].y = (int32_t)p[maxAxis];
+ points[i].z = (int32_t)p[minAxis];
+ points[i].index = i;
+ }
+ }
+ points.quickSort(pointCmp);
+
+ vertexPool.reset();
+ vertexPool.setArraySize(count);
+ originalVertices.resize(count);
+ for (int32_t i = 0; i < count; i++) {
+ Vertex* v = vertexPool.newObject();
+ v->edges = NULL;
+ v->point = points[i];
+ v->copy = -1;
+ originalVertices[i] = v;
+ }
+
+ points.clear();
+
+ edgePool.reset();
+ edgePool.setArraySize(6 * count);
+
+ usedEdgePairs = 0;
+ maxUsedEdgePairs = 0;
+
+ mergeStamp = -3;
+
+ IntermediateHull hull;
+ computeInternal(0, count, hull);
+ vertexList = hull.minXy;
+#ifdef DEBUG_CONVEX_HULL
+ printf("max. edges %d (3v = %d)", maxUsedEdgePairs, 3 * count);
+#endif
+}
+
+btVector3 btConvexHullInternal::toBtVector(const Point32& v)
+{
+ btVector3 p;
+ p[medAxis] = btScalar(v.x);
+ p[maxAxis] = btScalar(v.y);
+ p[minAxis] = btScalar(v.z);
+ return p * scaling;
+}
+
+btVector3 btConvexHullInternal::getBtNormal(Face* face)
+{
+ return toBtVector(face->dir0).cross(toBtVector(face->dir1)).normalized();
+}
+
+btVector3 btConvexHullInternal::getCoordinates(const Vertex* v)
+{
+ btVector3 p;
+ p[medAxis] = v->xvalue();
+ p[maxAxis] = v->yvalue();
+ p[minAxis] = v->zvalue();
+ return p * scaling + center;
+}
+
+btScalar btConvexHullInternal::shrink(btScalar amount, btScalar clampAmount)
+{
+ if (!vertexList) {
+ return 0;
+ }
+ int32_t stamp = --mergeStamp;
+ btAlignedObjectArray<Vertex*> stack;
+ vertexList->copy = stamp;
+ stack.push_back(vertexList);
+ btAlignedObjectArray<Face*> faces;
+
+ Point32 ref = vertexList->point;
+ Int128 hullCenterX(0, 0);
+ Int128 hullCenterY(0, 0);
+ Int128 hullCenterZ(0, 0);
+ Int128 volume(0, 0);
+
+ while (stack.size() > 0) {
+ Vertex* v = stack[stack.size() - 1];
+ stack.pop_back();
+ Edge* e = v->edges;
+ if (e) {
+ do {
+ if (e->target->copy != stamp) {
+ e->target->copy = stamp;
+ stack.push_back(e->target);
+ }
+ if (e->copy != stamp) {
+ Face* face = facePool.newObject();
+ face->init(e->target, e->reverse->prev->target, v);
+ faces.push_back(face);
+ Edge* f = e;
+
+ Vertex* a = NULL;
+ Vertex* b = NULL;
+ do {
+ if (a && b) {
+ int64_t vol = (v->point - ref).dot((a->point - ref).cross(b->point - ref));
+ btAssert(vol >= 0);
+ Point32 c = v->point + a->point + b->point + ref;
+ hullCenterX += vol * c.x;
+ hullCenterY += vol * c.y;
+ hullCenterZ += vol * c.z;
+ volume += vol;
+ }
+
+ btAssert(f->copy != stamp);
+ f->copy = stamp;
+ f->face = face;
+
+ a = b;
+ b = f->target;
+
+ f = f->reverse->prev;
+ } while (f != e);
+ }
+ e = e->next;
+ } while (e != v->edges);
+ }
+ }
+
+ if (volume.getSign() <= 0) {
+ return 0;
+ }
+
+ btVector3 hullCenter;
+ hullCenter[medAxis] = hullCenterX.toScalar();
+ hullCenter[maxAxis] = hullCenterY.toScalar();
+ hullCenter[minAxis] = hullCenterZ.toScalar();
+ hullCenter /= 4 * volume.toScalar();
+ hullCenter *= scaling;
+
+ int32_t faceCount = faces.size();
+
+ if (clampAmount > 0) {
+ btScalar minDist = SIMD_INFINITY;
+ for (int32_t i = 0; i < faceCount; i++) {
+ btVector3 normal = getBtNormal(faces[i]);
+ btScalar dist = normal.dot(toBtVector(faces[i]->origin) - hullCenter);
+ if (dist < minDist) {
+ minDist = dist;
+ }
+ }
+
+ if (minDist <= 0) {
+ return 0;
+ }
+
+ amount = btMin(amount, minDist * clampAmount);
+ }
+
+ uint32_t seed = 243703;
+ for (int32_t i = 0; i < faceCount; i++, seed = 1664525 * seed + 1013904223) {
+ btSwap(faces[i], faces[seed % faceCount]);
+ }
+
+ for (int32_t i = 0; i < faceCount; i++) {
+ if (!shiftFace(faces[i], amount, stack)) {
+ return -amount;
+ }
+ }
+
+ return amount;
+}
+
+bool btConvexHullInternal::shiftFace(Face* face, btScalar amount, btAlignedObjectArray<Vertex*> stack)
+{
+ btVector3 origShift = getBtNormal(face) * -amount;
+ if (scaling[0] != 0) {
+ origShift[0] /= scaling[0];
+ }
+ if (scaling[1] != 0) {
+ origShift[1] /= scaling[1];
+ }
+ if (scaling[2] != 0) {
+ origShift[2] /= scaling[2];
+ }
+ Point32 shift((int32_t)origShift[medAxis], (int32_t)origShift[maxAxis], (int32_t)origShift[minAxis]);
+ if (shift.isZero()) {
+ return true;
+ }
+ Point64 normal = face->getNormal();
+#ifdef DEBUG_CONVEX_HULL
+ printf("\nShrinking face (%d %d %d) (%d %d %d) (%d %d %d) by (%d %d %d)\n",
+ face->origin.x, face->origin.y, face->origin.z, face->dir0.x, face->dir0.y, face->dir0.z, face->dir1.x, face->dir1.y, face->dir1.z, shift.x, shift.y, shift.z);
+#endif
+ int64_t origDot = face->origin.dot(normal);
+ Point32 shiftedOrigin = face->origin + shift;
+ int64_t shiftedDot = shiftedOrigin.dot(normal);
+ btAssert(shiftedDot <= origDot);
+ if (shiftedDot >= origDot) {
+ return false;
+ }
+
+ Edge* intersection = NULL;
+
+ Edge* startEdge = face->nearbyVertex->edges;
+#ifdef DEBUG_CONVEX_HULL
+ printf("Start edge is ");
+ startEdge->print();
+ printf(", normal is (%lld %lld %lld), shifted dot is %lld\n", normal.x, normal.y, normal.z, shiftedDot);
+#endif
+ Rational128 optDot = face->nearbyVertex->dot(normal);
+ int32_t cmp = optDot.compare(shiftedDot);
+#ifdef SHOW_ITERATIONS
+ int32_t n = 0;
+#endif
+ if (cmp >= 0) {
+ Edge* e = startEdge;
+ do {
+#ifdef SHOW_ITERATIONS
+ n++;
+#endif
+ Rational128 dot = e->target->dot(normal);
+ btAssert(dot.compare(origDot) <= 0);
+#ifdef DEBUG_CONVEX_HULL
+ printf("Moving downwards, edge is ");
+ e->print();
+ printf(", dot is %f (%f %lld)\n", (float)dot.toScalar(), (float)optDot.toScalar(), shiftedDot);
+#endif
+ if (dot.compare(optDot) < 0) {
+ int32_t c = dot.compare(shiftedDot);
+ optDot = dot;
+ e = e->reverse;
+ startEdge = e;
+ if (c < 0) {
+ intersection = e;
+ break;
+ }
+ cmp = c;
+ }
+ e = e->prev;
+ } while (e != startEdge);
+
+ if (!intersection) {
+ return false;
+ }
+ }
+ else {
+ Edge* e = startEdge;
+ do {
+#ifdef SHOW_ITERATIONS
+ n++;
+#endif
+ Rational128 dot = e->target->dot(normal);
+ btAssert(dot.compare(origDot) <= 0);
+#ifdef DEBUG_CONVEX_HULL
+ printf("Moving upwards, edge is ");
+ e->print();
+ printf(", dot is %f (%f %lld)\n", (float)dot.toScalar(), (float)optDot.toScalar(), shiftedDot);
+#endif
+ if (dot.compare(optDot) > 0) {
+ cmp = dot.compare(shiftedDot);
+ if (cmp >= 0) {
+ intersection = e;
+ break;
+ }
+ optDot = dot;
+ e = e->reverse;
+ startEdge = e;
+ }
+ e = e->prev;
+ } while (e != startEdge);
+
+ if (!intersection) {
+ return true;
+ }
+ }
+
+#ifdef SHOW_ITERATIONS
+ printf("Needed %d iterations to find initial intersection\n", n);
+#endif
+
+ if (cmp == 0) {
+ Edge* e = intersection->reverse->next;
+#ifdef SHOW_ITERATIONS
+ n = 0;
+#endif
+ while (e->target->dot(normal).compare(shiftedDot) <= 0) {
+#ifdef SHOW_ITERATIONS
+ n++;
+#endif
+ e = e->next;
+ if (e == intersection->reverse) {
+ return true;
+ }
+#ifdef DEBUG_CONVEX_HULL
+ printf("Checking for outwards edge, current edge is ");
+ e->print();
+ printf("\n");
+#endif
+ }
+#ifdef SHOW_ITERATIONS
+ printf("Needed %d iterations to check for complete containment\n", n);
+#endif
+ }
+
+ Edge* firstIntersection = NULL;
+ Edge* faceEdge = NULL;
+ Edge* firstFaceEdge = NULL;
+
+#ifdef SHOW_ITERATIONS
+ int32_t m = 0;
+#endif
+ while (true) {
+#ifdef SHOW_ITERATIONS
+ m++;
+#endif
+#ifdef DEBUG_CONVEX_HULL
+ printf("Intersecting edge is ");
+ intersection->print();
+ printf("\n");
+#endif
+ if (cmp == 0) {
+ Edge* e = intersection->reverse->next;
+ startEdge = e;
+#ifdef SHOW_ITERATIONS
+ n = 0;
+#endif
+ while (true) {
+#ifdef SHOW_ITERATIONS
+ n++;
+#endif
+ if (e->target->dot(normal).compare(shiftedDot) >= 0) {
+ break;
+ }
+ intersection = e->reverse;
+ e = e->next;
+ if (e == startEdge) {
+ return true;
+ }
+ }
+#ifdef SHOW_ITERATIONS
+ printf("Needed %d iterations to advance intersection\n", n);
+#endif
+ }
+
+#ifdef DEBUG_CONVEX_HULL
+ printf("Advanced intersecting edge to ");
+ intersection->print();
+ printf(", cmp = %d\n", cmp);
+#endif
+
+ if (!firstIntersection) {
+ firstIntersection = intersection;
+ }
+ else if (intersection == firstIntersection) {
+ break;
+ }
+
+ int32_t prevCmp = cmp;
+ Edge* prevIntersection = intersection;
+ Edge* prevFaceEdge = faceEdge;
+
+ Edge* e = intersection->reverse;
+#ifdef SHOW_ITERATIONS
+ n = 0;
+#endif
+ while (true) {
+#ifdef SHOW_ITERATIONS
+ n++;
+#endif
+ e = e->reverse->prev;
+ btAssert(e != intersection->reverse);
+ cmp = e->target->dot(normal).compare(shiftedDot);
+#ifdef DEBUG_CONVEX_HULL
+ printf("Testing edge ");
+ e->print();
+ printf(" -> cmp = %d\n", cmp);
+#endif
+ if (cmp >= 0) {
+ intersection = e;
+ break;
+ }
+ }
+#ifdef SHOW_ITERATIONS
+ printf("Needed %d iterations to find other intersection of face\n", n);
+#endif
+
+ if (cmp > 0) {
+ Vertex* removed = intersection->target;
+ e = intersection->reverse;
+ if (e->prev == e) {
+ removed->edges = NULL;
+ }
+ else {
+ removed->edges = e->prev;
+ e->prev->link(e->next);
+ e->link(e);
+ }
+#ifdef DEBUG_CONVEX_HULL
+ printf("1: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z);
+#endif
+
+ Point64 n0 = intersection->face->getNormal();
+ Point64 n1 = intersection->reverse->face->getNormal();
+ int64_t m00 = face->dir0.dot(n0);
+ int64_t m01 = face->dir1.dot(n0);
+ int64_t m10 = face->dir0.dot(n1);
+ int64_t m11 = face->dir1.dot(n1);
+ int64_t r0 = (intersection->face->origin - shiftedOrigin).dot(n0);
+ int64_t r1 = (intersection->reverse->face->origin - shiftedOrigin).dot(n1);
+ Int128 det = Int128::mul(m00, m11) - Int128::mul(m01, m10);
+ btAssert(det.getSign() != 0);
+ Vertex* v = vertexPool.newObject();
+ v->point.index = -1;
+ v->copy = -1;
+ v->point128 = PointR128(Int128::mul(face->dir0.x * r0, m11) - Int128::mul(face->dir0.x * r1, m01)
+ + Int128::mul(face->dir1.x * r1, m00) - Int128::mul(face->dir1.x * r0, m10) + det * shiftedOrigin.x,
+ Int128::mul(face->dir0.y * r0, m11) - Int128::mul(face->dir0.y * r1, m01)
+ + Int128::mul(face->dir1.y * r1, m00) - Int128::mul(face->dir1.y * r0, m10) + det * shiftedOrigin.y,
+ Int128::mul(face->dir0.z * r0, m11) - Int128::mul(face->dir0.z * r1, m01)
+ + Int128::mul(face->dir1.z * r1, m00) - Int128::mul(face->dir1.z * r0, m10) + det * shiftedOrigin.z,
+ det);
+ v->point.x = (int32_t)v->point128.xvalue();
+ v->point.y = (int32_t)v->point128.yvalue();
+ v->point.z = (int32_t)v->point128.zvalue();
+ intersection->target = v;
+ v->edges = e;
+
+ stack.push_back(v);
+ stack.push_back(removed);
+ stack.push_back(NULL);
+ }
+
+ if (cmp || prevCmp || (prevIntersection->reverse->next->target != intersection->target)) {
+ faceEdge = newEdgePair(prevIntersection->target, intersection->target);
+ if (prevCmp == 0) {
+ faceEdge->link(prevIntersection->reverse->next);
+ }
+ if ((prevCmp == 0) || prevFaceEdge) {
+ prevIntersection->reverse->link(faceEdge);
+ }
+ if (cmp == 0) {
+ intersection->reverse->prev->link(faceEdge->reverse);
+ }
+ faceEdge->reverse->link(intersection->reverse);
+ }
+ else {
+ faceEdge = prevIntersection->reverse->next;
+ }
+
+ if (prevFaceEdge) {
+ if (prevCmp > 0) {
+ faceEdge->link(prevFaceEdge->reverse);
+ }
+ else if (faceEdge != prevFaceEdge->reverse) {
+ stack.push_back(prevFaceEdge->target);
+ while (faceEdge->next != prevFaceEdge->reverse) {
+ Vertex* removed = faceEdge->next->target;
+ removeEdgePair(faceEdge->next);
+ stack.push_back(removed);
+#ifdef DEBUG_CONVEX_HULL
+ printf("2: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z);
+#endif
+ }
+ stack.push_back(NULL);
+ }
+ }
+ faceEdge->face = face;
+ faceEdge->reverse->face = intersection->face;
+
+ if (!firstFaceEdge) {
+ firstFaceEdge = faceEdge;
+ }
+ }
+#ifdef SHOW_ITERATIONS
+ printf("Needed %d iterations to process all intersections\n", m);
+#endif
+
+ if (cmp > 0) {
+ firstFaceEdge->reverse->target = faceEdge->target;
+ firstIntersection->reverse->link(firstFaceEdge);
+ firstFaceEdge->link(faceEdge->reverse);
+ }
+ else if (firstFaceEdge != faceEdge->reverse) {
+ stack.push_back(faceEdge->target);
+ while (firstFaceEdge->next != faceEdge->reverse) {
+ Vertex* removed = firstFaceEdge->next->target;
+ removeEdgePair(firstFaceEdge->next);
+ stack.push_back(removed);
+#ifdef DEBUG_CONVEX_HULL
+ printf("3: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z);
+#endif
+ }
+ stack.push_back(NULL);
+ }
+
+ btAssert(stack.size() > 0);
+ vertexList = stack[0];
+
+#ifdef DEBUG_CONVEX_HULL
+ printf("Removing part\n");
+#endif
+#ifdef SHOW_ITERATIONS
+ n = 0;
+#endif
+ int32_t pos = 0;
+ while (pos < stack.size()) {
+ int32_t end = stack.size();
+ while (pos < end) {
+ Vertex* kept = stack[pos++];
+#ifdef DEBUG_CONVEX_HULL
+ kept->print();
+#endif
+ bool deeper = false;
+ Vertex* removed;
+ while ((removed = stack[pos++]) != NULL) {
+#ifdef SHOW_ITERATIONS
+ n++;
+#endif
+ kept->receiveNearbyFaces(removed);
+ while (removed->edges) {
+ if (!deeper) {
+ deeper = true;
+ stack.push_back(kept);
+ }
+ stack.push_back(removed->edges->target);
+ removeEdgePair(removed->edges);
+ }
+ }
+ if (deeper) {
+ stack.push_back(NULL);
+ }
+ }
+ }
+#ifdef SHOW_ITERATIONS
+ printf("Needed %d iterations to remove part\n", n);
+#endif
+
+ stack.resize(0);
+ face->origin = shiftedOrigin;
+
+ return true;
+}
+
+static int32_t getVertexCopy(btConvexHullInternal::Vertex* vertex, btAlignedObjectArray<btConvexHullInternal::Vertex*>& vertices)
+{
+ int32_t index = vertex->copy;
+ if (index < 0) {
+ index = vertices.size();
+ vertex->copy = index;
+ vertices.push_back(vertex);
+#ifdef DEBUG_CONVEX_HULL
+ printf("Vertex %d gets index *%d\n", vertex->point.index, index);
+#endif
+ }
+ return index;
+}
+
+btScalar btConvexHullComputer::compute(const void* coords, bool doubleCoords, int32_t stride, int32_t count, btScalar shrink, btScalar shrinkClamp)
+{
+ if (count <= 0) {
+ vertices.clear();
+ edges.clear();
+ faces.clear();
+ return 0;
+ }
+
+ btConvexHullInternal hull;
+ hull.compute(coords, doubleCoords, stride, count);
+
+ btScalar shift = 0;
+ if ((shrink > 0) && ((shift = hull.shrink(shrink, shrinkClamp)) < 0)) {
+ vertices.clear();
+ edges.clear();
+ faces.clear();
+ return shift;
+ }
+
+ vertices.resize(0);
+ edges.resize(0);
+ faces.resize(0);
+
+ btAlignedObjectArray<btConvexHullInternal::Vertex*> oldVertices;
+ getVertexCopy(hull.vertexList, oldVertices);
+ int32_t copied = 0;
+ while (copied < oldVertices.size()) {
+ btConvexHullInternal::Vertex* v = oldVertices[copied];
+ vertices.push_back(hull.getCoordinates(v));
+ btConvexHullInternal::Edge* firstEdge = v->edges;
+ if (firstEdge) {
+ int32_t firstCopy = -1;
+ int32_t prevCopy = -1;
+ btConvexHullInternal::Edge* e = firstEdge;
+ do {
+ if (e->copy < 0) {
+ int32_t s = edges.size();
+ edges.push_back(Edge());
+ edges.push_back(Edge());
+ Edge* c = &edges[s];
+ Edge* r = &edges[s + 1];
+ e->copy = s;
+ e->reverse->copy = s + 1;
+ c->reverse = 1;
+ r->reverse = -1;
+ c->targetVertex = getVertexCopy(e->target, oldVertices);
+ r->targetVertex = copied;
+#ifdef DEBUG_CONVEX_HULL
+ printf(" CREATE: Vertex *%d has edge to *%d\n", copied, c->getTargetVertex());
+#endif
+ }
+ if (prevCopy >= 0) {
+ edges[e->copy].next = prevCopy - e->copy;
+ }
+ else {
+ firstCopy = e->copy;
+ }
+ prevCopy = e->copy;
+ e = e->next;
+ } while (e != firstEdge);
+ edges[firstCopy].next = prevCopy - firstCopy;
+ }
+ copied++;
+ }
+
+ for (int32_t i = 0; i < copied; i++) {
+ btConvexHullInternal::Vertex* v = oldVertices[i];
+ btConvexHullInternal::Edge* firstEdge = v->edges;
+ if (firstEdge) {
+ btConvexHullInternal::Edge* e = firstEdge;
+ do {
+ if (e->copy >= 0) {
+#ifdef DEBUG_CONVEX_HULL
+ printf("Vertex *%d has edge to *%d\n", i, edges[e->copy].getTargetVertex());
+#endif
+ faces.push_back(e->copy);
+ btConvexHullInternal::Edge* f = e;
+ do {
+#ifdef DEBUG_CONVEX_HULL
+ printf(" Face *%d\n", edges[f->copy].getTargetVertex());
+#endif
+ f->copy = -1;
+ f = f->reverse->prev;
+ } while (f != e);
+ }
+ e = e->next;
+ } while (e != firstEdge);
+ }
+ }
+
+ return shift;
+}
+
+// -- GODOT start --
+}; // namespace VHACD
+// -- GODOT end --
diff --git a/thirdparty/vhacd/src/vhacdICHull.cpp b/thirdparty/vhacd/src/vhacdICHull.cpp
new file mode 100644
index 0000000000..989587c124
--- /dev/null
+++ b/thirdparty/vhacd/src/vhacdICHull.cpp
@@ -0,0 +1,731 @@
+/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
+ All rights reserved.
+
+
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+ 2. 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.
+
+ 3. The names of the contributors may not 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.
+ */
+#include "vhacdICHull.h"
+#include <limits>
+
+#ifdef _MSC_VER
+#pragma warning(disable:4456 4706)
+#endif
+
+
+namespace VHACD {
+const double ICHull::sc_eps = 1.0e-15;
+const int32_t ICHull::sc_dummyIndex = std::numeric_limits<int32_t>::max();
+ICHull::ICHull()
+{
+ m_isFlat = false;
+}
+bool ICHull::AddPoints(const Vec3<double>* points, size_t nPoints)
+{
+ if (!points) {
+ return false;
+ }
+ CircularListElement<TMMVertex>* vertex = NULL;
+ for (size_t i = 0; i < nPoints; i++) {
+ vertex = m_mesh.AddVertex();
+ vertex->GetData().m_pos.X() = points[i].X();
+ vertex->GetData().m_pos.Y() = points[i].Y();
+ vertex->GetData().m_pos.Z() = points[i].Z();
+ vertex->GetData().m_name = static_cast<int32_t>(i);
+ }
+ return true;
+}
+bool ICHull::AddPoint(const Vec3<double>& point, int32_t id)
+{
+ if (AddPoints(&point, 1)) {
+ m_mesh.m_vertices.GetData().m_name = id;
+ return true;
+ }
+ return false;
+}
+
+ICHullError ICHull::Process()
+{
+ uint32_t addedPoints = 0;
+ if (m_mesh.GetNVertices() < 3) {
+ return ICHullErrorNotEnoughPoints;
+ }
+ if (m_mesh.GetNVertices() == 3) {
+ m_isFlat = true;
+ CircularListElement<TMMTriangle>* t1 = m_mesh.AddTriangle();
+ CircularListElement<TMMTriangle>* t2 = m_mesh.AddTriangle();
+ CircularListElement<TMMVertex>* v0 = m_mesh.m_vertices.GetHead();
+ CircularListElement<TMMVertex>* v1 = v0->GetNext();
+ CircularListElement<TMMVertex>* v2 = v1->GetNext();
+ // Compute the normal to the plane
+ Vec3<double> p0 = v0->GetData().m_pos;
+ Vec3<double> p1 = v1->GetData().m_pos;
+ Vec3<double> p2 = v2->GetData().m_pos;
+ m_normal = (p1 - p0) ^ (p2 - p0);
+ m_normal.Normalize();
+ t1->GetData().m_vertices[0] = v0;
+ t1->GetData().m_vertices[1] = v1;
+ t1->GetData().m_vertices[2] = v2;
+ t2->GetData().m_vertices[0] = v1;
+ t2->GetData().m_vertices[1] = v2;
+ t2->GetData().m_vertices[2] = v2;
+ return ICHullErrorOK;
+ }
+ if (m_isFlat) {
+ m_mesh.m_edges.Clear();
+ m_mesh.m_triangles.Clear();
+ m_isFlat = false;
+ }
+ if (m_mesh.GetNTriangles() == 0) // we have to create the first polyhedron
+ {
+ ICHullError res = DoubleTriangle();
+ if (res != ICHullErrorOK) {
+ return res;
+ }
+ else {
+ addedPoints += 3;
+ }
+ }
+ CircularList<TMMVertex>& vertices = m_mesh.GetVertices();
+ // go to the first added and not processed vertex
+ while (!(vertices.GetHead()->GetPrev()->GetData().m_tag)) {
+ vertices.Prev();
+ }
+ while (!vertices.GetData().m_tag) // not processed
+ {
+ vertices.GetData().m_tag = true;
+ if (ProcessPoint()) {
+ addedPoints++;
+ CleanUp(addedPoints);
+ vertices.Next();
+ if (!GetMesh().CheckConsistancy()) {
+ size_t nV = m_mesh.GetNVertices();
+ CircularList<TMMVertex>& vertices = m_mesh.GetVertices();
+ for (size_t v = 0; v < nV; ++v) {
+ if (vertices.GetData().m_name == sc_dummyIndex) {
+ vertices.Delete();
+ break;
+ }
+ vertices.Next();
+ }
+ return ICHullErrorInconsistent;
+ }
+ }
+ }
+ if (m_isFlat) {
+ SArray<CircularListElement<TMMTriangle>*> trianglesToDuplicate;
+ size_t nT = m_mesh.GetNTriangles();
+ for (size_t f = 0; f < nT; f++) {
+ TMMTriangle& currentTriangle = m_mesh.m_triangles.GetHead()->GetData();
+ if (currentTriangle.m_vertices[0]->GetData().m_name == sc_dummyIndex || currentTriangle.m_vertices[1]->GetData().m_name == sc_dummyIndex || currentTriangle.m_vertices[2]->GetData().m_name == sc_dummyIndex) {
+ m_trianglesToDelete.PushBack(m_mesh.m_triangles.GetHead());
+ for (int32_t k = 0; k < 3; k++) {
+ for (int32_t h = 0; h < 2; h++) {
+ if (currentTriangle.m_edges[k]->GetData().m_triangles[h] == m_mesh.m_triangles.GetHead()) {
+ currentTriangle.m_edges[k]->GetData().m_triangles[h] = 0;
+ break;
+ }
+ }
+ }
+ }
+ else {
+ trianglesToDuplicate.PushBack(m_mesh.m_triangles.GetHead());
+ }
+ m_mesh.m_triangles.Next();
+ }
+ size_t nE = m_mesh.GetNEdges();
+ for (size_t e = 0; e < nE; e++) {
+ TMMEdge& currentEdge = m_mesh.m_edges.GetHead()->GetData();
+ if (currentEdge.m_triangles[0] == 0 && currentEdge.m_triangles[1] == 0) {
+ m_edgesToDelete.PushBack(m_mesh.m_edges.GetHead());
+ }
+ m_mesh.m_edges.Next();
+ }
+ size_t nV = m_mesh.GetNVertices();
+ CircularList<TMMVertex>& vertices = m_mesh.GetVertices();
+ for (size_t v = 0; v < nV; ++v) {
+ if (vertices.GetData().m_name == sc_dummyIndex) {
+ vertices.Delete();
+ }
+ else {
+ vertices.GetData().m_tag = false;
+ vertices.Next();
+ }
+ }
+ CleanEdges();
+ CleanTriangles();
+ CircularListElement<TMMTriangle>* newTriangle;
+ for (size_t t = 0; t < trianglesToDuplicate.Size(); t++) {
+ newTriangle = m_mesh.AddTriangle();
+ newTriangle->GetData().m_vertices[0] = trianglesToDuplicate[t]->GetData().m_vertices[1];
+ newTriangle->GetData().m_vertices[1] = trianglesToDuplicate[t]->GetData().m_vertices[0];
+ newTriangle->GetData().m_vertices[2] = trianglesToDuplicate[t]->GetData().m_vertices[2];
+ }
+ }
+ return ICHullErrorOK;
+}
+ICHullError ICHull::Process(const uint32_t nPointsCH,
+ const double minVolume)
+{
+ uint32_t addedPoints = 0;
+ if (nPointsCH < 3 || m_mesh.GetNVertices() < 3) {
+ return ICHullErrorNotEnoughPoints;
+ }
+ if (m_mesh.GetNVertices() == 3) {
+ m_isFlat = true;
+ CircularListElement<TMMTriangle>* t1 = m_mesh.AddTriangle();
+ CircularListElement<TMMTriangle>* t2 = m_mesh.AddTriangle();
+ CircularListElement<TMMVertex>* v0 = m_mesh.m_vertices.GetHead();
+ CircularListElement<TMMVertex>* v1 = v0->GetNext();
+ CircularListElement<TMMVertex>* v2 = v1->GetNext();
+ // Compute the normal to the plane
+ Vec3<double> p0 = v0->GetData().m_pos;
+ Vec3<double> p1 = v1->GetData().m_pos;
+ Vec3<double> p2 = v2->GetData().m_pos;
+ m_normal = (p1 - p0) ^ (p2 - p0);
+ m_normal.Normalize();
+ t1->GetData().m_vertices[0] = v0;
+ t1->GetData().m_vertices[1] = v1;
+ t1->GetData().m_vertices[2] = v2;
+ t2->GetData().m_vertices[0] = v1;
+ t2->GetData().m_vertices[1] = v0;
+ t2->GetData().m_vertices[2] = v2;
+ return ICHullErrorOK;
+ }
+
+ if (m_isFlat) {
+ m_mesh.m_triangles.Clear();
+ m_mesh.m_edges.Clear();
+ m_isFlat = false;
+ }
+
+ if (m_mesh.GetNTriangles() == 0) // we have to create the first polyhedron
+ {
+ ICHullError res = DoubleTriangle();
+ if (res != ICHullErrorOK) {
+ return res;
+ }
+ else {
+ addedPoints += 3;
+ }
+ }
+ CircularList<TMMVertex>& vertices = m_mesh.GetVertices();
+ while (!vertices.GetData().m_tag && addedPoints < nPointsCH) // not processed
+ {
+ if (!FindMaxVolumePoint((addedPoints > 4) ? minVolume : 0.0)) {
+ break;
+ }
+ vertices.GetData().m_tag = true;
+ if (ProcessPoint()) {
+ addedPoints++;
+ CleanUp(addedPoints);
+ if (!GetMesh().CheckConsistancy()) {
+ size_t nV = m_mesh.GetNVertices();
+ CircularList<TMMVertex>& vertices = m_mesh.GetVertices();
+ for (size_t v = 0; v < nV; ++v) {
+ if (vertices.GetData().m_name == sc_dummyIndex) {
+ vertices.Delete();
+ break;
+ }
+ vertices.Next();
+ }
+ return ICHullErrorInconsistent;
+ }
+ vertices.Next();
+ }
+ }
+ // delete remaining points
+ while (!vertices.GetData().m_tag) {
+ vertices.Delete();
+ }
+ if (m_isFlat) {
+ SArray<CircularListElement<TMMTriangle>*> trianglesToDuplicate;
+ size_t nT = m_mesh.GetNTriangles();
+ for (size_t f = 0; f < nT; f++) {
+ TMMTriangle& currentTriangle = m_mesh.m_triangles.GetHead()->GetData();
+ if (currentTriangle.m_vertices[0]->GetData().m_name == sc_dummyIndex || currentTriangle.m_vertices[1]->GetData().m_name == sc_dummyIndex || currentTriangle.m_vertices[2]->GetData().m_name == sc_dummyIndex) {
+ m_trianglesToDelete.PushBack(m_mesh.m_triangles.GetHead());
+ for (int32_t k = 0; k < 3; k++) {
+ for (int32_t h = 0; h < 2; h++) {
+ if (currentTriangle.m_edges[k]->GetData().m_triangles[h] == m_mesh.m_triangles.GetHead()) {
+ currentTriangle.m_edges[k]->GetData().m_triangles[h] = 0;
+ break;
+ }
+ }
+ }
+ }
+ else {
+ trianglesToDuplicate.PushBack(m_mesh.m_triangles.GetHead());
+ }
+ m_mesh.m_triangles.Next();
+ }
+ size_t nE = m_mesh.GetNEdges();
+ for (size_t e = 0; e < nE; e++) {
+ TMMEdge& currentEdge = m_mesh.m_edges.GetHead()->GetData();
+ if (currentEdge.m_triangles[0] == 0 && currentEdge.m_triangles[1] == 0) {
+ m_edgesToDelete.PushBack(m_mesh.m_edges.GetHead());
+ }
+ m_mesh.m_edges.Next();
+ }
+ size_t nV = m_mesh.GetNVertices();
+ CircularList<TMMVertex>& vertices = m_mesh.GetVertices();
+ for (size_t v = 0; v < nV; ++v) {
+ if (vertices.GetData().m_name == sc_dummyIndex) {
+ vertices.Delete();
+ }
+ else {
+ vertices.GetData().m_tag = false;
+ vertices.Next();
+ }
+ }
+ CleanEdges();
+ CleanTriangles();
+ CircularListElement<TMMTriangle>* newTriangle;
+ for (size_t t = 0; t < trianglesToDuplicate.Size(); t++) {
+ newTriangle = m_mesh.AddTriangle();
+ newTriangle->GetData().m_vertices[0] = trianglesToDuplicate[t]->GetData().m_vertices[1];
+ newTriangle->GetData().m_vertices[1] = trianglesToDuplicate[t]->GetData().m_vertices[0];
+ newTriangle->GetData().m_vertices[2] = trianglesToDuplicate[t]->GetData().m_vertices[2];
+ }
+ }
+ return ICHullErrorOK;
+}
+bool ICHull::FindMaxVolumePoint(const double minVolume)
+{
+ CircularList<TMMVertex>& vertices = m_mesh.GetVertices();
+ CircularListElement<TMMVertex>* vMaxVolume = 0;
+ CircularListElement<TMMVertex>* vHeadPrev = vertices.GetHead()->GetPrev();
+
+ double maxVolume = minVolume;
+ double volume = 0.0;
+ while (!vertices.GetData().m_tag) // not processed
+ {
+ if (ComputePointVolume(volume, false)) {
+ if (maxVolume < volume) {
+ maxVolume = volume;
+ vMaxVolume = vertices.GetHead();
+ }
+ vertices.Next();
+ }
+ }
+ CircularListElement<TMMVertex>* vHead = vHeadPrev->GetNext();
+ vertices.GetHead() = vHead;
+ if (!vMaxVolume) {
+ return false;
+ }
+ if (vMaxVolume != vHead) {
+ Vec3<double> pos = vHead->GetData().m_pos;
+ int32_t id = vHead->GetData().m_name;
+ vHead->GetData().m_pos = vMaxVolume->GetData().m_pos;
+ vHead->GetData().m_name = vMaxVolume->GetData().m_name;
+ vMaxVolume->GetData().m_pos = pos;
+ vHead->GetData().m_name = id;
+ }
+ return true;
+}
+ICHullError ICHull::DoubleTriangle()
+{
+ // find three non colinear points
+ m_isFlat = false;
+ CircularList<TMMVertex>& vertices = m_mesh.GetVertices();
+ CircularListElement<TMMVertex>* v0 = vertices.GetHead();
+ while (Colinear(v0->GetData().m_pos,
+ v0->GetNext()->GetData().m_pos,
+ v0->GetNext()->GetNext()->GetData().m_pos)) {
+ if ((v0 = v0->GetNext()) == vertices.GetHead()) {
+ return ICHullErrorCoplanarPoints;
+ }
+ }
+ CircularListElement<TMMVertex>* v1 = v0->GetNext();
+ CircularListElement<TMMVertex>* v2 = v1->GetNext();
+ // mark points as processed
+ v0->GetData().m_tag = v1->GetData().m_tag = v2->GetData().m_tag = true;
+
+ // create two triangles
+ CircularListElement<TMMTriangle>* f0 = MakeFace(v0, v1, v2, 0);
+ MakeFace(v2, v1, v0, f0);
+
+ // find a fourth non-coplanar point to form tetrahedron
+ CircularListElement<TMMVertex>* v3 = v2->GetNext();
+ vertices.GetHead() = v3;
+
+ double vol = ComputeVolume4(v0->GetData().m_pos, v1->GetData().m_pos, v2->GetData().m_pos, v3->GetData().m_pos);
+ while (fabs(vol) < sc_eps && !v3->GetNext()->GetData().m_tag) {
+ v3 = v3->GetNext();
+ vol = ComputeVolume4(v0->GetData().m_pos, v1->GetData().m_pos, v2->GetData().m_pos, v3->GetData().m_pos);
+ }
+ if (fabs(vol) < sc_eps) {
+ // compute the barycenter
+ Vec3<double> bary(0.0, 0.0, 0.0);
+ CircularListElement<TMMVertex>* vBary = v0;
+ do {
+ bary += vBary->GetData().m_pos;
+ } while ((vBary = vBary->GetNext()) != v0);
+ bary /= static_cast<double>(vertices.GetSize());
+
+ // Compute the normal to the plane
+ Vec3<double> p0 = v0->GetData().m_pos;
+ Vec3<double> p1 = v1->GetData().m_pos;
+ Vec3<double> p2 = v2->GetData().m_pos;
+ m_normal = (p1 - p0) ^ (p2 - p0);
+ m_normal.Normalize();
+ // add dummy vertex placed at (bary + normal)
+ vertices.GetHead() = v2;
+ Vec3<double> newPt = bary + m_normal;
+ AddPoint(newPt, sc_dummyIndex);
+ m_isFlat = true;
+ return ICHullErrorOK;
+ }
+ else if (v3 != vertices.GetHead()) {
+ TMMVertex temp;
+ temp.m_name = v3->GetData().m_name;
+ temp.m_pos = v3->GetData().m_pos;
+ v3->GetData().m_name = vertices.GetHead()->GetData().m_name;
+ v3->GetData().m_pos = vertices.GetHead()->GetData().m_pos;
+ vertices.GetHead()->GetData().m_name = temp.m_name;
+ vertices.GetHead()->GetData().m_pos = temp.m_pos;
+ }
+ return ICHullErrorOK;
+}
+CircularListElement<TMMTriangle>* ICHull::MakeFace(CircularListElement<TMMVertex>* v0,
+ CircularListElement<TMMVertex>* v1,
+ CircularListElement<TMMVertex>* v2,
+ CircularListElement<TMMTriangle>* fold)
+{
+ CircularListElement<TMMEdge>* e0;
+ CircularListElement<TMMEdge>* e1;
+ CircularListElement<TMMEdge>* e2;
+ int32_t index = 0;
+ if (!fold) // if first face to be created
+ {
+ e0 = m_mesh.AddEdge(); // create the three edges
+ e1 = m_mesh.AddEdge();
+ e2 = m_mesh.AddEdge();
+ }
+ else // otherwise re-use existing edges (in reverse order)
+ {
+ e0 = fold->GetData().m_edges[2];
+ e1 = fold->GetData().m_edges[1];
+ e2 = fold->GetData().m_edges[0];
+ index = 1;
+ }
+ e0->GetData().m_vertices[0] = v0;
+ e0->GetData().m_vertices[1] = v1;
+ e1->GetData().m_vertices[0] = v1;
+ e1->GetData().m_vertices[1] = v2;
+ e2->GetData().m_vertices[0] = v2;
+ e2->GetData().m_vertices[1] = v0;
+ // create the new face
+ CircularListElement<TMMTriangle>* f = m_mesh.AddTriangle();
+ f->GetData().m_edges[0] = e0;
+ f->GetData().m_edges[1] = e1;
+ f->GetData().m_edges[2] = e2;
+ f->GetData().m_vertices[0] = v0;
+ f->GetData().m_vertices[1] = v1;
+ f->GetData().m_vertices[2] = v2;
+ // link edges to face f
+ e0->GetData().m_triangles[index] = e1->GetData().m_triangles[index] = e2->GetData().m_triangles[index] = f;
+ return f;
+}
+CircularListElement<TMMTriangle>* ICHull::MakeConeFace(CircularListElement<TMMEdge>* e, CircularListElement<TMMVertex>* p)
+{
+ // create two new edges if they don't already exist
+ CircularListElement<TMMEdge>* newEdges[2];
+ for (int32_t i = 0; i < 2; ++i) {
+ if (!(newEdges[i] = e->GetData().m_vertices[i]->GetData().m_duplicate)) { // if the edge doesn't exits add it and mark the vertex as duplicated
+ newEdges[i] = m_mesh.AddEdge();
+ newEdges[i]->GetData().m_vertices[0] = e->GetData().m_vertices[i];
+ newEdges[i]->GetData().m_vertices[1] = p;
+ e->GetData().m_vertices[i]->GetData().m_duplicate = newEdges[i];
+ }
+ }
+ // make the new face
+ CircularListElement<TMMTriangle>* newFace = m_mesh.AddTriangle();
+ newFace->GetData().m_edges[0] = e;
+ newFace->GetData().m_edges[1] = newEdges[0];
+ newFace->GetData().m_edges[2] = newEdges[1];
+ MakeCCW(newFace, e, p);
+ for (int32_t i = 0; i < 2; ++i) {
+ for (int32_t j = 0; j < 2; ++j) {
+ if (!newEdges[i]->GetData().m_triangles[j]) {
+ newEdges[i]->GetData().m_triangles[j] = newFace;
+ break;
+ }
+ }
+ }
+ return newFace;
+}
+bool ICHull::ComputePointVolume(double& totalVolume, bool markVisibleFaces)
+{
+ // mark visible faces
+ CircularListElement<TMMTriangle>* fHead = m_mesh.GetTriangles().GetHead();
+ CircularListElement<TMMTriangle>* f = fHead;
+ CircularList<TMMVertex>& vertices = m_mesh.GetVertices();
+ CircularListElement<TMMVertex>* vertex0 = vertices.GetHead();
+ bool visible = false;
+ Vec3<double> pos0 = Vec3<double>(vertex0->GetData().m_pos.X(),
+ vertex0->GetData().m_pos.Y(),
+ vertex0->GetData().m_pos.Z());
+ double vol = 0.0;
+ totalVolume = 0.0;
+ Vec3<double> ver0, ver1, ver2;
+ do {
+ ver0.X() = f->GetData().m_vertices[0]->GetData().m_pos.X();
+ ver0.Y() = f->GetData().m_vertices[0]->GetData().m_pos.Y();
+ ver0.Z() = f->GetData().m_vertices[0]->GetData().m_pos.Z();
+ ver1.X() = f->GetData().m_vertices[1]->GetData().m_pos.X();
+ ver1.Y() = f->GetData().m_vertices[1]->GetData().m_pos.Y();
+ ver1.Z() = f->GetData().m_vertices[1]->GetData().m_pos.Z();
+ ver2.X() = f->GetData().m_vertices[2]->GetData().m_pos.X();
+ ver2.Y() = f->GetData().m_vertices[2]->GetData().m_pos.Y();
+ ver2.Z() = f->GetData().m_vertices[2]->GetData().m_pos.Z();
+ vol = ComputeVolume4(ver0, ver1, ver2, pos0);
+ if (vol < -sc_eps) {
+ vol = fabs(vol);
+ totalVolume += vol;
+ if (markVisibleFaces) {
+ f->GetData().m_visible = true;
+ m_trianglesToDelete.PushBack(f);
+ }
+ visible = true;
+ }
+ f = f->GetNext();
+ } while (f != fHead);
+
+ if (m_trianglesToDelete.Size() == m_mesh.m_triangles.GetSize()) {
+ for (size_t i = 0; i < m_trianglesToDelete.Size(); i++) {
+ m_trianglesToDelete[i]->GetData().m_visible = false;
+ }
+ visible = false;
+ }
+ // if no faces visible from p then p is inside the hull
+ if (!visible && markVisibleFaces) {
+ vertices.Delete();
+ m_trianglesToDelete.Resize(0);
+ return false;
+ }
+ return true;
+}
+bool ICHull::ProcessPoint()
+{
+ double totalVolume = 0.0;
+ if (!ComputePointVolume(totalVolume, true)) {
+ return false;
+ }
+ // Mark edges in interior of visible region for deletion.
+ // Create a new face based on each border edge
+ CircularListElement<TMMVertex>* v0 = m_mesh.GetVertices().GetHead();
+ CircularListElement<TMMEdge>* eHead = m_mesh.GetEdges().GetHead();
+ CircularListElement<TMMEdge>* e = eHead;
+ CircularListElement<TMMEdge>* tmp = 0;
+ int32_t nvisible = 0;
+ m_edgesToDelete.Resize(0);
+ m_edgesToUpdate.Resize(0);
+ do {
+ tmp = e->GetNext();
+ nvisible = 0;
+ for (int32_t k = 0; k < 2; k++) {
+ if (e->GetData().m_triangles[k]->GetData().m_visible) {
+ nvisible++;
+ }
+ }
+ if (nvisible == 2) {
+ m_edgesToDelete.PushBack(e);
+ }
+ else if (nvisible == 1) {
+ e->GetData().m_newFace = MakeConeFace(e, v0);
+ m_edgesToUpdate.PushBack(e);
+ }
+ e = tmp;
+ } while (e != eHead);
+ return true;
+}
+bool ICHull::MakeCCW(CircularListElement<TMMTriangle>* f,
+ CircularListElement<TMMEdge>* e,
+ CircularListElement<TMMVertex>* v)
+{
+ // the visible face adjacent to e
+ CircularListElement<TMMTriangle>* fv;
+ if (e->GetData().m_triangles[0]->GetData().m_visible) {
+ fv = e->GetData().m_triangles[0];
+ }
+ else {
+ fv = e->GetData().m_triangles[1];
+ }
+
+ // set vertex[0] and vertex[1] to have the same orientation as the corresponding vertices of fv.
+ int32_t i; // index of e->m_vertices[0] in fv
+ CircularListElement<TMMVertex>* v0 = e->GetData().m_vertices[0];
+ CircularListElement<TMMVertex>* v1 = e->GetData().m_vertices[1];
+ for (i = 0; fv->GetData().m_vertices[i] != v0; i++)
+ ;
+
+ if (fv->GetData().m_vertices[(i + 1) % 3] != e->GetData().m_vertices[1]) {
+ f->GetData().m_vertices[0] = v1;
+ f->GetData().m_vertices[1] = v0;
+ }
+ else {
+ f->GetData().m_vertices[0] = v0;
+ f->GetData().m_vertices[1] = v1;
+ // swap edges
+ CircularListElement<TMMEdge>* tmp = f->GetData().m_edges[0];
+ f->GetData().m_edges[0] = f->GetData().m_edges[1];
+ f->GetData().m_edges[1] = tmp;
+ }
+ f->GetData().m_vertices[2] = v;
+ return true;
+}
+bool ICHull::CleanUp(uint32_t& addedPoints)
+{
+ bool r0 = CleanEdges();
+ bool r1 = CleanTriangles();
+ bool r2 = CleanVertices(addedPoints);
+ return r0 && r1 && r2;
+}
+bool ICHull::CleanEdges()
+{
+ // integrate the new faces into the data structure
+ CircularListElement<TMMEdge>* e;
+ const size_t ne_update = m_edgesToUpdate.Size();
+ for (size_t i = 0; i < ne_update; ++i) {
+ e = m_edgesToUpdate[i];
+ if (e->GetData().m_newFace) {
+ if (e->GetData().m_triangles[0]->GetData().m_visible) {
+ e->GetData().m_triangles[0] = e->GetData().m_newFace;
+ }
+ else {
+ e->GetData().m_triangles[1] = e->GetData().m_newFace;
+ }
+ e->GetData().m_newFace = 0;
+ }
+ }
+ // delete edges maked for deletion
+ CircularList<TMMEdge>& edges = m_mesh.GetEdges();
+ const size_t ne_delete = m_edgesToDelete.Size();
+ for (size_t i = 0; i < ne_delete; ++i) {
+ edges.Delete(m_edgesToDelete[i]);
+ }
+ m_edgesToDelete.Resize(0);
+ m_edgesToUpdate.Resize(0);
+ return true;
+}
+bool ICHull::CleanTriangles()
+{
+ CircularList<TMMTriangle>& triangles = m_mesh.GetTriangles();
+ const size_t nt_delete = m_trianglesToDelete.Size();
+ for (size_t i = 0; i < nt_delete; ++i) {
+ triangles.Delete(m_trianglesToDelete[i]);
+ }
+ m_trianglesToDelete.Resize(0);
+ return true;
+}
+bool ICHull::CleanVertices(uint32_t& addedPoints)
+{
+ // mark all vertices incident to some undeleted edge as on the hull
+ CircularList<TMMEdge>& edges = m_mesh.GetEdges();
+ CircularListElement<TMMEdge>* e = edges.GetHead();
+ size_t nE = edges.GetSize();
+ for (size_t i = 0; i < nE; i++) {
+ e->GetData().m_vertices[0]->GetData().m_onHull = true;
+ e->GetData().m_vertices[1]->GetData().m_onHull = true;
+ e = e->GetNext();
+ }
+ // delete all the vertices that have been processed but are not on the hull
+ CircularList<TMMVertex>& vertices = m_mesh.GetVertices();
+ CircularListElement<TMMVertex>* vHead = vertices.GetHead();
+ CircularListElement<TMMVertex>* v = vHead;
+ v = v->GetPrev();
+ do {
+ if (v->GetData().m_tag && !v->GetData().m_onHull) {
+ CircularListElement<TMMVertex>* tmp = v->GetPrev();
+ vertices.Delete(v);
+ v = tmp;
+ addedPoints--;
+ }
+ else {
+ v->GetData().m_duplicate = 0;
+ v->GetData().m_onHull = false;
+ v = v->GetPrev();
+ }
+ } while (v->GetData().m_tag && v != vHead);
+ return true;
+}
+void ICHull::Clear()
+{
+ m_mesh.Clear();
+ m_edgesToDelete.Resize(0);
+ m_edgesToUpdate.Resize(0);
+ m_trianglesToDelete.Resize(0);
+ m_isFlat = false;
+}
+const ICHull& ICHull::operator=(ICHull& rhs)
+{
+ if (&rhs != this) {
+ m_mesh.Copy(rhs.m_mesh);
+ m_edgesToDelete = rhs.m_edgesToDelete;
+ m_edgesToUpdate = rhs.m_edgesToUpdate;
+ m_trianglesToDelete = rhs.m_trianglesToDelete;
+ m_isFlat = rhs.m_isFlat;
+ }
+ return (*this);
+}
+bool ICHull::IsInside(const Vec3<double>& pt0, const double eps)
+{
+ const Vec3<double> pt(pt0.X(), pt0.Y(), pt0.Z());
+ if (m_isFlat) {
+ size_t nT = m_mesh.m_triangles.GetSize();
+ Vec3<double> ver0, ver1, ver2, a, b, c;
+ double u, v;
+ for (size_t t = 0; t < nT; t++) {
+ ver0.X() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[0]->GetData().m_pos.X();
+ ver0.Y() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[0]->GetData().m_pos.Y();
+ ver0.Z() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[0]->GetData().m_pos.Z();
+ ver1.X() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[1]->GetData().m_pos.X();
+ ver1.Y() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[1]->GetData().m_pos.Y();
+ ver1.Z() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[1]->GetData().m_pos.Z();
+ ver2.X() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[2]->GetData().m_pos.X();
+ ver2.Y() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[2]->GetData().m_pos.Y();
+ ver2.Z() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[2]->GetData().m_pos.Z();
+ a = ver1 - ver0;
+ b = ver2 - ver0;
+ c = pt - ver0;
+ u = c * a;
+ v = c * b;
+ if (u >= 0.0 && u <= 1.0 && v >= 0.0 && u + v <= 1.0) {
+ return true;
+ }
+ m_mesh.m_triangles.Next();
+ }
+ return false;
+ }
+ else {
+ size_t nT = m_mesh.m_triangles.GetSize();
+ Vec3<double> ver0, ver1, ver2;
+ double vol;
+ for (size_t t = 0; t < nT; t++) {
+ ver0.X() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[0]->GetData().m_pos.X();
+ ver0.Y() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[0]->GetData().m_pos.Y();
+ ver0.Z() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[0]->GetData().m_pos.Z();
+ ver1.X() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[1]->GetData().m_pos.X();
+ ver1.Y() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[1]->GetData().m_pos.Y();
+ ver1.Z() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[1]->GetData().m_pos.Z();
+ ver2.X() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[2]->GetData().m_pos.X();
+ ver2.Y() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[2]->GetData().m_pos.Y();
+ ver2.Z() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[2]->GetData().m_pos.Z();
+ vol = ComputeVolume4(ver0, ver1, ver2, pt);
+ if (vol < eps) {
+ return false;
+ }
+ m_mesh.m_triangles.Next();
+ }
+ return true;
+ }
+}
+}
diff --git a/thirdparty/vhacd/src/vhacdManifoldMesh.cpp b/thirdparty/vhacd/src/vhacdManifoldMesh.cpp
new file mode 100644
index 0000000000..7aac9c0d17
--- /dev/null
+++ b/thirdparty/vhacd/src/vhacdManifoldMesh.cpp
@@ -0,0 +1,202 @@
+/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
+ All rights reserved.
+
+
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+ 2. 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.
+
+ 3. The names of the contributors may not 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.
+ */
+#include "vhacdManifoldMesh.h"
+namespace VHACD {
+TMMVertex::TMMVertex(void)
+{
+ Initialize();
+}
+void TMMVertex::Initialize()
+{
+ m_name = 0;
+ m_id = 0;
+ m_duplicate = 0;
+ m_onHull = false;
+ m_tag = false;
+}
+
+TMMVertex::~TMMVertex(void)
+{
+}
+TMMEdge::TMMEdge(void)
+{
+ Initialize();
+}
+void TMMEdge::Initialize()
+{
+ m_id = 0;
+ m_triangles[0] = m_triangles[1] = m_newFace = 0;
+ m_vertices[0] = m_vertices[1] = 0;
+}
+TMMEdge::~TMMEdge(void)
+{
+}
+void TMMTriangle::Initialize()
+{
+ m_id = 0;
+ for (int32_t i = 0; i < 3; i++) {
+ m_edges[i] = 0;
+ m_vertices[0] = 0;
+ }
+ m_visible = false;
+}
+TMMTriangle::TMMTriangle(void)
+{
+ Initialize();
+}
+TMMTriangle::~TMMTriangle(void)
+{
+}
+TMMesh::TMMesh()
+{
+}
+TMMesh::~TMMesh(void)
+{
+}
+void TMMesh::GetIFS(Vec3<double>* const points, Vec3<int32_t>* const triangles)
+{
+ size_t nV = m_vertices.GetSize();
+ size_t nT = m_triangles.GetSize();
+
+ for (size_t v = 0; v < nV; v++) {
+ points[v] = m_vertices.GetData().m_pos;
+ m_vertices.GetData().m_id = v;
+ m_vertices.Next();
+ }
+ for (size_t f = 0; f < nT; f++) {
+ TMMTriangle& currentTriangle = m_triangles.GetData();
+ triangles[f].X() = static_cast<int32_t>(currentTriangle.m_vertices[0]->GetData().m_id);
+ triangles[f].Y() = static_cast<int32_t>(currentTriangle.m_vertices[1]->GetData().m_id);
+ triangles[f].Z() = static_cast<int32_t>(currentTriangle.m_vertices[2]->GetData().m_id);
+ m_triangles.Next();
+ }
+}
+void TMMesh::Clear()
+{
+ m_vertices.Clear();
+ m_edges.Clear();
+ m_triangles.Clear();
+}
+void TMMesh::Copy(TMMesh& mesh)
+{
+ Clear();
+ // updating the id's
+ size_t nV = mesh.m_vertices.GetSize();
+ size_t nE = mesh.m_edges.GetSize();
+ size_t nT = mesh.m_triangles.GetSize();
+ for (size_t v = 0; v < nV; v++) {
+ mesh.m_vertices.GetData().m_id = v;
+ mesh.m_vertices.Next();
+ }
+ for (size_t e = 0; e < nE; e++) {
+ mesh.m_edges.GetData().m_id = e;
+ mesh.m_edges.Next();
+ }
+ for (size_t f = 0; f < nT; f++) {
+ mesh.m_triangles.GetData().m_id = f;
+ mesh.m_triangles.Next();
+ }
+ // copying data
+ m_vertices = mesh.m_vertices;
+ m_edges = mesh.m_edges;
+ m_triangles = mesh.m_triangles;
+
+ // generate mapping
+ CircularListElement<TMMVertex>** vertexMap = new CircularListElement<TMMVertex>*[nV];
+ CircularListElement<TMMEdge>** edgeMap = new CircularListElement<TMMEdge>*[nE];
+ CircularListElement<TMMTriangle>** triangleMap = new CircularListElement<TMMTriangle>*[nT];
+ for (size_t v = 0; v < nV; v++) {
+ vertexMap[v] = m_vertices.GetHead();
+ m_vertices.Next();
+ }
+ for (size_t e = 0; e < nE; e++) {
+ edgeMap[e] = m_edges.GetHead();
+ m_edges.Next();
+ }
+ for (size_t f = 0; f < nT; f++) {
+ triangleMap[f] = m_triangles.GetHead();
+ m_triangles.Next();
+ }
+
+ // updating pointers
+ for (size_t v = 0; v < nV; v++) {
+ if (vertexMap[v]->GetData().m_duplicate) {
+ vertexMap[v]->GetData().m_duplicate = edgeMap[vertexMap[v]->GetData().m_duplicate->GetData().m_id];
+ }
+ }
+ for (size_t e = 0; e < nE; e++) {
+ if (edgeMap[e]->GetData().m_newFace) {
+ edgeMap[e]->GetData().m_newFace = triangleMap[edgeMap[e]->GetData().m_newFace->GetData().m_id];
+ }
+ if (nT > 0) {
+ for (int32_t f = 0; f < 2; f++) {
+ if (edgeMap[e]->GetData().m_triangles[f]) {
+ edgeMap[e]->GetData().m_triangles[f] = triangleMap[edgeMap[e]->GetData().m_triangles[f]->GetData().m_id];
+ }
+ }
+ }
+ for (int32_t v = 0; v < 2; v++) {
+ if (edgeMap[e]->GetData().m_vertices[v]) {
+ edgeMap[e]->GetData().m_vertices[v] = vertexMap[edgeMap[e]->GetData().m_vertices[v]->GetData().m_id];
+ }
+ }
+ }
+ for (size_t f = 0; f < nT; f++) {
+ if (nE > 0) {
+ for (int32_t e = 0; e < 3; e++) {
+ if (triangleMap[f]->GetData().m_edges[e]) {
+ triangleMap[f]->GetData().m_edges[e] = edgeMap[triangleMap[f]->GetData().m_edges[e]->GetData().m_id];
+ }
+ }
+ }
+ for (int32_t v = 0; v < 3; v++) {
+ if (triangleMap[f]->GetData().m_vertices[v]) {
+ triangleMap[f]->GetData().m_vertices[v] = vertexMap[triangleMap[f]->GetData().m_vertices[v]->GetData().m_id];
+ }
+ }
+ }
+ delete[] vertexMap;
+ delete[] edgeMap;
+ delete[] triangleMap;
+}
+bool TMMesh::CheckConsistancy()
+{
+ size_t nE = m_edges.GetSize();
+ size_t nT = m_triangles.GetSize();
+ for (size_t e = 0; e < nE; e++) {
+ for (int32_t f = 0; f < 2; f++) {
+ if (!m_edges.GetHead()->GetData().m_triangles[f]) {
+ return false;
+ }
+ }
+ m_edges.Next();
+ }
+ for (size_t f = 0; f < nT; f++) {
+ for (int32_t e = 0; e < 3; e++) {
+ int32_t found = 0;
+ for (int32_t k = 0; k < 2; k++) {
+ if (m_triangles.GetHead()->GetData().m_edges[e]->GetData().m_triangles[k] == m_triangles.GetHead()) {
+ found++;
+ }
+ }
+ if (found != 1) {
+ return false;
+ }
+ }
+ m_triangles.Next();
+ }
+ return true;
+}
+} \ No newline at end of file
diff --git a/thirdparty/vhacd/src/vhacdMesh.cpp b/thirdparty/vhacd/src/vhacdMesh.cpp
new file mode 100644
index 0000000000..5d03989fda
--- /dev/null
+++ b/thirdparty/vhacd/src/vhacdMesh.cpp
@@ -0,0 +1,376 @@
+/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
+ All rights reserved.
+
+
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+ 2. 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.
+
+ 3. The names of the contributors may not 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.
+ */
+
+#ifndef _CRT_SECURE_NO_WARNINGS
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#include "btConvexHullComputer.h"
+#include "vhacdMesh.h"
+#include "FloatMath.h"
+#include <fstream>
+#include <iosfwd>
+#include <iostream>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string>
+
+namespace VHACD {
+Mesh::Mesh()
+{
+ m_diag = 1.0;
+}
+Mesh::~Mesh()
+{
+}
+
+Vec3<double>& Mesh::ComputeCenter(void)
+{
+ const size_t nV = GetNPoints();
+ if (nV)
+ {
+ double center[3];
+ uint32_t pcount = uint32_t(GetNPoints());
+ const double *points = GetPoints();
+ uint32_t tcount = uint32_t(GetNTriangles());
+ const uint32_t *indices = (const uint32_t *)GetTriangles();
+ FLOAT_MATH::fm_computeCentroid(pcount, points, tcount, indices, center);
+ m_center.X() = center[0];
+ m_center.Y() = center[1];
+ m_center.Z() = center[2];
+ m_minBB = GetPoint(0);
+ m_maxBB = GetPoint(0);
+ for (size_t v = 1; v < nV; v++)
+ {
+ Vec3<double> p = GetPoint(v);
+ if (p.X() < m_minBB.X())
+ {
+ m_minBB.X() = p.X();
+ }
+ if (p.Y() < m_minBB.Y())
+ {
+ m_minBB.Y() = p.Y();
+ }
+ if (p.Z() < m_minBB.Z())
+ {
+ m_minBB.Z() = p.Z();
+ }
+ if (p.X() > m_maxBB.X())
+ {
+ m_maxBB.X() = p.X();
+ }
+ if (p.Y() > m_maxBB.Y())
+ {
+ m_maxBB.Y() = p.Y();
+ }
+ if (p.Z() > m_maxBB.Z())
+ {
+ m_maxBB.Z() = p.Z();
+ }
+ }
+ }
+ return m_center;
+}
+
+double Mesh::ComputeVolume() const
+{
+ const size_t nV = GetNPoints();
+ const size_t nT = GetNTriangles();
+ if (nV == 0 || nT == 0) {
+ return 0.0;
+ }
+
+ Vec3<double> bary(0.0, 0.0, 0.0);
+ for (size_t v = 0; v < nV; v++) {
+ bary += GetPoint(v);
+ }
+ bary /= static_cast<double>(nV);
+
+ Vec3<double> ver0, ver1, ver2;
+ double totalVolume = 0.0;
+ for (int32_t t = 0; t < int32_t(nT); t++) {
+ const Vec3<int32_t>& tri = GetTriangle(t);
+ ver0 = GetPoint(tri[0]);
+ ver1 = GetPoint(tri[1]);
+ ver2 = GetPoint(tri[2]);
+ totalVolume += ComputeVolume4(ver0, ver1, ver2, bary);
+ }
+ return totalVolume / 6.0;
+}
+
+void Mesh::ComputeConvexHull(const double* const pts,
+ const size_t nPts)
+{
+ ResizePoints(0);
+ ResizeTriangles(0);
+ btConvexHullComputer ch;
+ ch.compute(pts, 3 * sizeof(double), (int32_t)nPts, -1.0, -1.0);
+ for (int32_t v = 0; v < ch.vertices.size(); v++) {
+ AddPoint(Vec3<double>(ch.vertices[v].getX(), ch.vertices[v].getY(), ch.vertices[v].getZ()));
+ }
+ const int32_t nt = ch.faces.size();
+ for (int32_t t = 0; t < nt; ++t) {
+ const btConvexHullComputer::Edge* sourceEdge = &(ch.edges[ch.faces[t]]);
+ int32_t a = sourceEdge->getSourceVertex();
+ int32_t b = sourceEdge->getTargetVertex();
+ const btConvexHullComputer::Edge* edge = sourceEdge->getNextEdgeOfFace();
+ int32_t c = edge->getTargetVertex();
+ while (c != a) {
+ AddTriangle(Vec3<int32_t>(a, b, c));
+ edge = edge->getNextEdgeOfFace();
+ b = c;
+ c = edge->getTargetVertex();
+ }
+ }
+}
+void Mesh::Clip(const Plane& plane,
+ SArray<Vec3<double> >& positivePart,
+ SArray<Vec3<double> >& negativePart) const
+{
+ const size_t nV = GetNPoints();
+ if (nV == 0) {
+ return;
+ }
+ double d;
+ for (size_t v = 0; v < nV; v++) {
+ const Vec3<double>& pt = GetPoint(v);
+ d = plane.m_a * pt[0] + plane.m_b * pt[1] + plane.m_c * pt[2] + plane.m_d;
+ if (d > 0.0) {
+ positivePart.PushBack(pt);
+ }
+ else if (d < 0.0) {
+ negativePart.PushBack(pt);
+ }
+ else {
+ positivePart.PushBack(pt);
+ negativePart.PushBack(pt);
+ }
+ }
+}
+bool Mesh::IsInside(const Vec3<double>& pt) const
+{
+ const size_t nV = GetNPoints();
+ const size_t nT = GetNTriangles();
+ if (nV == 0 || nT == 0) {
+ return false;
+ }
+ Vec3<double> ver0, ver1, ver2;
+ double volume;
+ for (int32_t t = 0; t < int32_t(nT); t++) {
+ const Vec3<int32_t>& tri = GetTriangle(t);
+ ver0 = GetPoint(tri[0]);
+ ver1 = GetPoint(tri[1]);
+ ver2 = GetPoint(tri[2]);
+ volume = ComputeVolume4(ver0, ver1, ver2, pt);
+ if (volume < 0.0) {
+ return false;
+ }
+ }
+ return true;
+}
+double Mesh::ComputeDiagBB()
+{
+ const size_t nPoints = GetNPoints();
+ if (nPoints == 0)
+ return 0.0;
+ Vec3<double> minBB = m_points[0];
+ Vec3<double> maxBB = m_points[0];
+ double x, y, z;
+ for (size_t v = 1; v < nPoints; v++) {
+ x = m_points[v][0];
+ y = m_points[v][1];
+ z = m_points[v][2];
+ if (x < minBB[0])
+ minBB[0] = x;
+ else if (x > maxBB[0])
+ maxBB[0] = x;
+ if (y < minBB[1])
+ minBB[1] = y;
+ else if (y > maxBB[1])
+ maxBB[1] = y;
+ if (z < minBB[2])
+ minBB[2] = z;
+ else if (z > maxBB[2])
+ maxBB[2] = z;
+ }
+ return (m_diag = (maxBB - minBB).GetNorm());
+}
+
+#ifdef VHACD_DEBUG_MESH
+bool Mesh::SaveVRML2(const std::string& fileName) const
+{
+ std::ofstream fout(fileName.c_str());
+ if (fout.is_open()) {
+ const Material material;
+
+ if (SaveVRML2(fout, material)) {
+ fout.close();
+ return true;
+ }
+ return false;
+ }
+ return false;
+}
+bool Mesh::SaveVRML2(std::ofstream& fout, const Material& material) const
+{
+ if (fout.is_open()) {
+ fout.setf(std::ios::fixed, std::ios::floatfield);
+ fout.setf(std::ios::showpoint);
+ fout.precision(6);
+ size_t nV = m_points.Size();
+ size_t nT = m_triangles.Size();
+ fout << "#VRML V2.0 utf8" << std::endl;
+ fout << "" << std::endl;
+ fout << "# Vertices: " << nV << std::endl;
+ fout << "# Triangles: " << nT << std::endl;
+ fout << "" << std::endl;
+ fout << "Group {" << std::endl;
+ fout << " children [" << std::endl;
+ fout << " Shape {" << std::endl;
+ fout << " appearance Appearance {" << std::endl;
+ fout << " material Material {" << std::endl;
+ fout << " diffuseColor " << material.m_diffuseColor[0] << " "
+ << material.m_diffuseColor[1] << " "
+ << material.m_diffuseColor[2] << std::endl;
+ fout << " ambientIntensity " << material.m_ambientIntensity << std::endl;
+ fout << " specularColor " << material.m_specularColor[0] << " "
+ << material.m_specularColor[1] << " "
+ << material.m_specularColor[2] << std::endl;
+ fout << " emissiveColor " << material.m_emissiveColor[0] << " "
+ << material.m_emissiveColor[1] << " "
+ << material.m_emissiveColor[2] << std::endl;
+ fout << " shininess " << material.m_shininess << std::endl;
+ fout << " transparency " << material.m_transparency << std::endl;
+ fout << " }" << std::endl;
+ fout << " }" << std::endl;
+ fout << " geometry IndexedFaceSet {" << std::endl;
+ fout << " ccw TRUE" << std::endl;
+ fout << " solid TRUE" << std::endl;
+ fout << " convex TRUE" << std::endl;
+ if (nV > 0) {
+ fout << " coord DEF co Coordinate {" << std::endl;
+ fout << " point [" << std::endl;
+ for (size_t v = 0; v < nV; v++) {
+ fout << " " << m_points[v][0] << " "
+ << m_points[v][1] << " "
+ << m_points[v][2] << "," << std::endl;
+ }
+ fout << " ]" << std::endl;
+ fout << " }" << std::endl;
+ }
+ if (nT > 0) {
+ fout << " coordIndex [ " << std::endl;
+ for (size_t f = 0; f < nT; f++) {
+ fout << " " << m_triangles[f][0] << ", "
+ << m_triangles[f][1] << ", "
+ << m_triangles[f][2] << ", -1," << std::endl;
+ }
+ fout << " ]" << std::endl;
+ }
+ fout << " }" << std::endl;
+ fout << " }" << std::endl;
+ fout << " ]" << std::endl;
+ fout << "}" << std::endl;
+ return true;
+ }
+ return false;
+}
+bool Mesh::SaveOFF(const std::string& fileName) const
+{
+ std::ofstream fout(fileName.c_str());
+ if (fout.is_open()) {
+ size_t nV = m_points.Size();
+ size_t nT = m_triangles.Size();
+ fout << "OFF" << std::endl;
+ fout << nV << " " << nT << " " << 0 << std::endl;
+ for (size_t v = 0; v < nV; v++) {
+ fout << m_points[v][0] << " "
+ << m_points[v][1] << " "
+ << m_points[v][2] << std::endl;
+ }
+ for (size_t f = 0; f < nT; f++) {
+ fout << "3 " << m_triangles[f][0] << " "
+ << m_triangles[f][1] << " "
+ << m_triangles[f][2] << std::endl;
+ }
+ fout.close();
+ return true;
+ }
+ return false;
+}
+
+bool Mesh::LoadOFF(const std::string& fileName, bool invert)
+{
+ FILE* fid = fopen(fileName.c_str(), "r");
+ if (fid) {
+ const std::string strOFF("OFF");
+ char temp[1024];
+ fscanf(fid, "%s", temp);
+ if (std::string(temp) != strOFF) {
+ fclose(fid);
+ return false;
+ }
+ else {
+ int32_t nv = 0;
+ int32_t nf = 0;
+ int32_t ne = 0;
+ fscanf(fid, "%i", &nv);
+ fscanf(fid, "%i", &nf);
+ fscanf(fid, "%i", &ne);
+ m_points.Resize(nv);
+ m_triangles.Resize(nf);
+ Vec3<double> coord;
+ float x, y, z;
+ for (int32_t p = 0; p < nv; p++) {
+ fscanf(fid, "%f", &x);
+ fscanf(fid, "%f", &y);
+ fscanf(fid, "%f", &z);
+ m_points[p][0] = x;
+ m_points[p][1] = y;
+ m_points[p][2] = z;
+ }
+ int32_t i, j, k, s;
+ for (int32_t t = 0; t < nf; ++t) {
+ fscanf(fid, "%i", &s);
+ if (s == 3) {
+ fscanf(fid, "%i", &i);
+ fscanf(fid, "%i", &j);
+ fscanf(fid, "%i", &k);
+ m_triangles[t][0] = i;
+ if (invert) {
+ m_triangles[t][1] = k;
+ m_triangles[t][2] = j;
+ }
+ else {
+ m_triangles[t][1] = j;
+ m_triangles[t][2] = k;
+ }
+ }
+ else // Fix me: support only triangular meshes
+ {
+ for (int32_t h = 0; h < s; ++h)
+ fscanf(fid, "%i", &s);
+ }
+ }
+ fclose(fid);
+ }
+ }
+ else {
+ return false;
+ }
+ return true;
+}
+#endif // VHACD_DEBUG_MESH
+}
diff --git a/thirdparty/vhacd/src/vhacdRaycastMesh.cpp b/thirdparty/vhacd/src/vhacdRaycastMesh.cpp
new file mode 100644
index 0000000000..e8b9435d5f
--- /dev/null
+++ b/thirdparty/vhacd/src/vhacdRaycastMesh.cpp
@@ -0,0 +1,208 @@
+#include "vhacdRaycastMesh.h"
+#include <math.h>
+#include <assert.h>
+
+namespace RAYCAST_MESH
+{
+
+/* a = b - c */
+#define vector(a,b,c) \
+ (a)[0] = (b)[0] - (c)[0]; \
+ (a)[1] = (b)[1] - (c)[1]; \
+ (a)[2] = (b)[2] - (c)[2];
+
+#define innerProduct(v,q) \
+ ((v)[0] * (q)[0] + \
+ (v)[1] * (q)[1] + \
+ (v)[2] * (q)[2])
+
+#define crossProduct(a,b,c) \
+ (a)[0] = (b)[1] * (c)[2] - (c)[1] * (b)[2]; \
+ (a)[1] = (b)[2] * (c)[0] - (c)[2] * (b)[0]; \
+ (a)[2] = (b)[0] * (c)[1] - (c)[0] * (b)[1];
+
+
+static inline bool rayIntersectsTriangle(const double *p,const double *d,const double *v0,const double *v1,const double *v2,double &t)
+{
+ double e1[3],e2[3],h[3],s[3],q[3];
+ double a,f,u,v;
+
+ vector(e1,v1,v0);
+ vector(e2,v2,v0);
+ crossProduct(h,d,e2);
+ a = innerProduct(e1,h);
+
+ if (a > -0.00001 && a < 0.00001)
+ return(false);
+
+ f = 1/a;
+ vector(s,p,v0);
+ u = f * (innerProduct(s,h));
+
+ if (u < 0.0 || u > 1.0)
+ return(false);
+
+ crossProduct(q,s,e1);
+ v = f * innerProduct(d,q);
+ if (v < 0.0 || u + v > 1.0)
+ return(false);
+ // at this stage we can compute t to find out where
+ // the intersection point is on the line
+ t = f * innerProduct(e2,q);
+ if (t > 0) // ray intersection
+ return(true);
+ else // this means that there is a line intersection
+ // but not a ray intersection
+ return (false);
+}
+
+static double getPointDistance(const double *p1, const double *p2)
+{
+ double dx = p1[0] - p2[0];
+ double dy = p1[1] - p2[1];
+ double dz = p1[2] - p2[2];
+ return sqrt(dx*dx + dy*dy + dz*dz);
+}
+
+class MyRaycastMesh : public VHACD::RaycastMesh
+{
+public:
+
+ template <class T>
+ MyRaycastMesh(uint32_t vcount,
+ const T *vertices,
+ uint32_t tcount,
+ const uint32_t *indices)
+ {
+ mVcount = vcount;
+ mVertices = new double[mVcount * 3];
+ for (uint32_t i = 0; i < mVcount; i++)
+ {
+ mVertices[i * 3 + 0] = vertices[0];
+ mVertices[i * 3 + 1] = vertices[1];
+ mVertices[i * 3 + 2] = vertices[2];
+ vertices += 3;
+ }
+ mTcount = tcount;
+ mIndices = new uint32_t[mTcount * 3];
+ for (uint32_t i = 0; i < mTcount; i++)
+ {
+ mIndices[i * 3 + 0] = indices[0];
+ mIndices[i * 3 + 1] = indices[1];
+ mIndices[i * 3 + 2] = indices[2];
+ indices += 3;
+ }
+ }
+
+
+ ~MyRaycastMesh(void)
+ {
+ delete[]mVertices;
+ delete[]mIndices;
+ }
+
+ virtual void release(void)
+ {
+ delete this;
+ }
+
+ virtual bool raycast(const double *from, // The starting point of the raycast
+ const double *to, // The ending point of the raycast
+ const double *closestToPoint, // The point to match the nearest hit location (can just be the 'from' location of no specific point)
+ double *hitLocation, // The point where the ray hit nearest to the 'closestToPoint' location
+ double *hitDistance) final // The distance the ray traveled to the hit location
+ {
+ bool ret = false;
+
+ double dir[3];
+
+ dir[0] = to[0] - from[0];
+ dir[1] = to[1] - from[1];
+ dir[2] = to[2] - from[2];
+
+ double distance = sqrt( dir[0]*dir[0] + dir[1]*dir[1]+dir[2]*dir[2] );
+ if ( distance < 0.0000000001f ) return false;
+ double recipDistance = 1.0f / distance;
+ dir[0]*=recipDistance;
+ dir[1]*=recipDistance;
+ dir[2]*=recipDistance;
+ const uint32_t *indices = mIndices;
+ const double *vertices = mVertices;
+ double nearestDistance = distance;
+
+ for (uint32_t tri=0; tri<mTcount; tri++)
+ {
+ uint32_t i1 = indices[tri*3+0];
+ uint32_t i2 = indices[tri*3+1];
+ uint32_t i3 = indices[tri*3+2];
+
+ const double *p1 = &vertices[i1*3];
+ const double *p2 = &vertices[i2*3];
+ const double *p3 = &vertices[i3*3];
+
+ double t;
+ if ( rayIntersectsTriangle(from,dir,p1,p2,p3,t))
+ {
+ double hitPos[3];
+
+ hitPos[0] = from[0] + dir[0] * t;
+ hitPos[1] = from[1] + dir[1] * t;
+ hitPos[2] = from[2] + dir[2] * t;
+
+ double pointDistance = getPointDistance(hitPos, closestToPoint);
+
+ if (pointDistance < nearestDistance )
+ {
+ nearestDistance = pointDistance;
+ if ( hitLocation )
+ {
+ hitLocation[0] = hitPos[0];
+ hitLocation[1] = hitPos[1];
+ hitLocation[2] = hitPos[2];
+ }
+ if ( hitDistance )
+ {
+ *hitDistance = pointDistance;
+ }
+ ret = true;
+ }
+ }
+ }
+ return ret;
+ }
+
+ uint32_t mVcount;
+ double *mVertices;
+ uint32_t mTcount;
+ uint32_t *mIndices;
+};
+
+};
+
+
+
+using namespace RAYCAST_MESH;
+
+namespace VHACD
+{
+
+ RaycastMesh * RaycastMesh::createRaycastMesh(uint32_t vcount, // The number of vertices in the source triangle mesh
+ const double *vertices, // The array of vertex positions in the format x1,y1,z1..x2,y2,z2.. etc.
+ uint32_t tcount, // The number of triangles in the source triangle mesh
+ const uint32_t *indices) // The triangle indices in the format of i1,i2,i3 ... i4,i5,i6, ...
+ {
+ MyRaycastMesh *m = new MyRaycastMesh(vcount, vertices, tcount, indices);
+ return static_cast<RaycastMesh *>(m);
+ }
+
+ RaycastMesh * RaycastMesh::createRaycastMesh(uint32_t vcount, // The number of vertices in the source triangle mesh
+ const float *vertices, // The array of vertex positions in the format x1,y1,z1..x2,y2,z2.. etc.
+ uint32_t tcount, // The number of triangles in the source triangle mesh
+ const uint32_t *indices) // The triangle indices in the format of i1,i2,i3 ... i4,i5,i6, ...
+ {
+ MyRaycastMesh *m = new MyRaycastMesh(vcount, vertices, tcount, indices);
+ return static_cast<RaycastMesh *>(m);
+ }
+
+
+} // end of VHACD namespace \ No newline at end of file
diff --git a/thirdparty/vhacd/src/vhacdVolume.cpp b/thirdparty/vhacd/src/vhacdVolume.cpp
new file mode 100644
index 0000000000..a250e5acaa
--- /dev/null
+++ b/thirdparty/vhacd/src/vhacdVolume.cpp
@@ -0,0 +1,1626 @@
+/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
+ All rights reserved.
+
+
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+ 2. 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.
+
+ 3. The names of the contributors may not 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.
+ */
+
+#ifndef _CRT_SECURE_NO_WARNINGS
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#include "btConvexHullComputer.h"
+#include "vhacdVolume.h"
+#include <algorithm>
+#include <float.h>
+#include <math.h>
+#include <queue>
+#include <string.h>
+
+#ifdef _MSC_VER
+#pragma warning(disable:4458 4100)
+#endif
+
+
+namespace VHACD {
+/********************************************************/
+/* AABB-triangle overlap test code */
+/* by Tomas Akenine-M�ller */
+/* Function: int32_t triBoxOverlap(float boxcenter[3], */
+/* float boxhalfsize[3],float triverts[3][3]); */
+/* History: */
+/* 2001-03-05: released the code in its first version */
+/* 2001-06-18: changed the order of the tests, faster */
+/* */
+/* Acknowledgement: Many thanks to Pierre Terdiman for */
+/* suggestions and discussions on how to optimize code. */
+/* Thanks to David Hunt for finding a ">="-bug! */
+/********************************************************/
+
+#define X 0
+#define Y 1
+#define Z 2
+#define FINDMINMAX(x0, x1, x2, min, max) \
+ min = max = x0; \
+ if (x1 < min) \
+ min = x1; \
+ if (x1 > max) \
+ max = x1; \
+ if (x2 < min) \
+ min = x2; \
+ if (x2 > max) \
+ max = x2;
+
+#define AXISTEST_X01(a, b, fa, fb) \
+ p0 = a * v0[Y] - b * v0[Z]; \
+ p2 = a * v2[Y] - b * v2[Z]; \
+ if (p0 < p2) { \
+ min = p0; \
+ max = p2; \
+ } \
+ else { \
+ min = p2; \
+ max = p0; \
+ } \
+ rad = fa * boxhalfsize[Y] + fb * boxhalfsize[Z]; \
+ if (min > rad || max < -rad) \
+ return 0;
+
+#define AXISTEST_X2(a, b, fa, fb) \
+ p0 = a * v0[Y] - b * v0[Z]; \
+ p1 = a * v1[Y] - b * v1[Z]; \
+ if (p0 < p1) { \
+ min = p0; \
+ max = p1; \
+ } \
+ else { \
+ min = p1; \
+ max = p0; \
+ } \
+ rad = fa * boxhalfsize[Y] + fb * boxhalfsize[Z]; \
+ if (min > rad || max < -rad) \
+ return 0;
+
+#define AXISTEST_Y02(a, b, fa, fb) \
+ p0 = -a * v0[X] + b * v0[Z]; \
+ p2 = -a * v2[X] + b * v2[Z]; \
+ if (p0 < p2) { \
+ min = p0; \
+ max = p2; \
+ } \
+ else { \
+ min = p2; \
+ max = p0; \
+ } \
+ rad = fa * boxhalfsize[X] + fb * boxhalfsize[Z]; \
+ if (min > rad || max < -rad) \
+ return 0;
+
+#define AXISTEST_Y1(a, b, fa, fb) \
+ p0 = -a * v0[X] + b * v0[Z]; \
+ p1 = -a * v1[X] + b * v1[Z]; \
+ if (p0 < p1) { \
+ min = p0; \
+ max = p1; \
+ } \
+ else { \
+ min = p1; \
+ max = p0; \
+ } \
+ rad = fa * boxhalfsize[X] + fb * boxhalfsize[Z]; \
+ if (min > rad || max < -rad) \
+ return 0;
+
+#define AXISTEST_Z12(a, b, fa, fb) \
+ p1 = a * v1[X] - b * v1[Y]; \
+ p2 = a * v2[X] - b * v2[Y]; \
+ if (p2 < p1) { \
+ min = p2; \
+ max = p1; \
+ } \
+ else { \
+ min = p1; \
+ max = p2; \
+ } \
+ rad = fa * boxhalfsize[X] + fb * boxhalfsize[Y]; \
+ if (min > rad || max < -rad) \
+ return 0;
+
+#define AXISTEST_Z0(a, b, fa, fb) \
+ p0 = a * v0[X] - b * v0[Y]; \
+ p1 = a * v1[X] - b * v1[Y]; \
+ if (p0 < p1) { \
+ min = p0; \
+ max = p1; \
+ } \
+ else { \
+ min = p1; \
+ max = p0; \
+ } \
+ rad = fa * boxhalfsize[X] + fb * boxhalfsize[Y]; \
+ if (min > rad || max < -rad) \
+ return 0;
+
+int32_t PlaneBoxOverlap(const Vec3<double>& normal,
+ const Vec3<double>& vert,
+ const Vec3<double>& maxbox)
+{
+ int32_t q;
+ Vec3<double> vmin, vmax;
+ double v;
+ for (q = X; q <= Z; q++) {
+ v = vert[q];
+ if (normal[q] > 0.0) {
+ vmin[q] = -maxbox[q] - v;
+ vmax[q] = maxbox[q] - v;
+ }
+ else {
+ vmin[q] = maxbox[q] - v;
+ vmax[q] = -maxbox[q] - v;
+ }
+ }
+ if (normal * vmin > 0.0)
+ return 0;
+ if (normal * vmax >= 0.0)
+ return 1;
+ return 0;
+}
+
+int32_t TriBoxOverlap(const Vec3<double>& boxcenter,
+ const Vec3<double>& boxhalfsize,
+ const Vec3<double>& triver0,
+ const Vec3<double>& triver1,
+ const Vec3<double>& triver2)
+{
+ /* 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 */
+
+ Vec3<double> v0, v1, v2;
+ double min, max, p0, p1, p2, rad, fex, fey, fez; // -NJMP- "d" local variable removed
+ Vec3<double> normal, e0, e1, e2;
+
+ /* This is the fastest branch on Sun */
+ /* move everything so that the boxcenter is in (0,0,0) */
+
+ v0 = triver0 - boxcenter;
+ v1 = triver1 - boxcenter;
+ v2 = triver2 - boxcenter;
+
+ /* compute triangle edges */
+ e0 = v1 - v0; /* tri edge 0 */
+ e1 = v2 - v1; /* tri edge 1 */
+ e2 = v0 - v2; /* tri edge 2 */
+
+ /* Bullet 3: */
+ /* test the 9 tests first (this was faster) */
+ fex = fabs(e0[X]);
+ fey = fabs(e0[Y]);
+ fez = fabs(e0[Z]);
+
+ AXISTEST_X01(e0[Z], e0[Y], fez, fey);
+ AXISTEST_Y02(e0[Z], e0[X], fez, fex);
+ AXISTEST_Z12(e0[Y], e0[X], fey, fex);
+
+ fex = fabs(e1[X]);
+ fey = fabs(e1[Y]);
+ fez = fabs(e1[Z]);
+
+ AXISTEST_X01(e1[Z], e1[Y], fez, fey);
+ AXISTEST_Y02(e1[Z], e1[X], fez, fex);
+ AXISTEST_Z0(e1[Y], e1[X], fey, fex);
+
+ fex = fabs(e2[X]);
+ fey = fabs(e2[Y]);
+ fez = fabs(e2[Z]);
+
+ AXISTEST_X2(e2[Z], e2[Y], fez, fey);
+ AXISTEST_Y1(e2[Z], e2[X], fez, fex);
+ AXISTEST_Z12(e2[Y], e2[X], fey, fex);
+
+ /* Bullet 1: */
+ /* first test overlap in the {x,y,z}-directions */
+ /* find min, max of the triangle each direction, and test for overlap in */
+ /* that direction -- this is equivalent to testing a minimal AABB around */
+ /* the triangle against the AABB */
+
+ /* test in X-direction */
+ FINDMINMAX(v0[X], v1[X], v2[X], min, max);
+ if (min > boxhalfsize[X] || max < -boxhalfsize[X])
+ return 0;
+
+ /* test in Y-direction */
+ FINDMINMAX(v0[Y], v1[Y], v2[Y], min, max);
+ if (min > boxhalfsize[Y] || max < -boxhalfsize[Y])
+ return 0;
+
+ /* test in Z-direction */
+ FINDMINMAX(v0[Z], v1[Z], v2[Z], min, max);
+ if (min > boxhalfsize[Z] || max < -boxhalfsize[Z])
+ return 0;
+
+ /* Bullet 2: */
+ /* test if the box intersects the plane of the triangle */
+ /* compute plane equation of triangle: normal*x+d=0 */
+ normal = e0 ^ e1;
+
+ if (!PlaneBoxOverlap(normal, v0, boxhalfsize))
+ return 0;
+ return 1; /* box and triangle overlaps */
+}
+
+// Slightly modified version of Stan Melax's code for 3x3 matrix diagonalization (Thanks Stan!)
+// source: http://www.melax.com/diag.html?attredirects=0
+void Diagonalize(const double (&A)[3][3], double (&Q)[3][3], double (&D)[3][3])
+{
+ // A must be a symmetric matrix.
+ // returns Q and D such that
+ // Diagonal matrix D = QT * A * Q; and A = Q*D*QT
+ const int32_t maxsteps = 24; // certainly wont need that many.
+ int32_t k0, k1, k2;
+ double o[3], m[3];
+ double q[4] = { 0.0, 0.0, 0.0, 1.0 };
+ double jr[4];
+ double sqw, sqx, sqy, sqz;
+ double tmp1, tmp2, mq;
+ double AQ[3][3];
+ double thet, sgn, t, c;
+ for (int32_t i = 0; i < maxsteps; ++i) {
+ // quat to matrix
+ sqx = q[0] * q[0];
+ sqy = q[1] * q[1];
+ sqz = q[2] * q[2];
+ sqw = q[3] * q[3];
+ Q[0][0] = (sqx - sqy - sqz + sqw);
+ Q[1][1] = (-sqx + sqy - sqz + sqw);
+ Q[2][2] = (-sqx - sqy + sqz + sqw);
+ tmp1 = q[0] * q[1];
+ tmp2 = q[2] * q[3];
+ Q[1][0] = 2.0 * (tmp1 + tmp2);
+ Q[0][1] = 2.0 * (tmp1 - tmp2);
+ tmp1 = q[0] * q[2];
+ tmp2 = q[1] * q[3];
+ Q[2][0] = 2.0 * (tmp1 - tmp2);
+ Q[0][2] = 2.0 * (tmp1 + tmp2);
+ tmp1 = q[1] * q[2];
+ tmp2 = q[0] * q[3];
+ Q[2][1] = 2.0 * (tmp1 + tmp2);
+ Q[1][2] = 2.0 * (tmp1 - tmp2);
+
+ // AQ = A * Q
+ AQ[0][0] = Q[0][0] * A[0][0] + Q[1][0] * A[0][1] + Q[2][0] * A[0][2];
+ AQ[0][1] = Q[0][1] * A[0][0] + Q[1][1] * A[0][1] + Q[2][1] * A[0][2];
+ AQ[0][2] = Q[0][2] * A[0][0] + Q[1][2] * A[0][1] + Q[2][2] * A[0][2];
+ AQ[1][0] = Q[0][0] * A[0][1] + Q[1][0] * A[1][1] + Q[2][0] * A[1][2];
+ AQ[1][1] = Q[0][1] * A[0][1] + Q[1][1] * A[1][1] + Q[2][1] * A[1][2];
+ AQ[1][2] = Q[0][2] * A[0][1] + Q[1][2] * A[1][1] + Q[2][2] * A[1][2];
+ AQ[2][0] = Q[0][0] * A[0][2] + Q[1][0] * A[1][2] + Q[2][0] * A[2][2];
+ AQ[2][1] = Q[0][1] * A[0][2] + Q[1][1] * A[1][2] + Q[2][1] * A[2][2];
+ AQ[2][2] = Q[0][2] * A[0][2] + Q[1][2] * A[1][2] + Q[2][2] * A[2][2];
+ // D = Qt * AQ
+ D[0][0] = AQ[0][0] * Q[0][0] + AQ[1][0] * Q[1][0] + AQ[2][0] * Q[2][0];
+ D[0][1] = AQ[0][0] * Q[0][1] + AQ[1][0] * Q[1][1] + AQ[2][0] * Q[2][1];
+ D[0][2] = AQ[0][0] * Q[0][2] + AQ[1][0] * Q[1][2] + AQ[2][0] * Q[2][2];
+ D[1][0] = AQ[0][1] * Q[0][0] + AQ[1][1] * Q[1][0] + AQ[2][1] * Q[2][0];
+ D[1][1] = AQ[0][1] * Q[0][1] + AQ[1][1] * Q[1][1] + AQ[2][1] * Q[2][1];
+ D[1][2] = AQ[0][1] * Q[0][2] + AQ[1][1] * Q[1][2] + AQ[2][1] * Q[2][2];
+ D[2][0] = AQ[0][2] * Q[0][0] + AQ[1][2] * Q[1][0] + AQ[2][2] * Q[2][0];
+ D[2][1] = AQ[0][2] * Q[0][1] + AQ[1][2] * Q[1][1] + AQ[2][2] * Q[2][1];
+ D[2][2] = AQ[0][2] * Q[0][2] + AQ[1][2] * Q[1][2] + AQ[2][2] * Q[2][2];
+ o[0] = D[1][2];
+ o[1] = D[0][2];
+ o[2] = D[0][1];
+ m[0] = fabs(o[0]);
+ m[1] = fabs(o[1]);
+ m[2] = fabs(o[2]);
+
+ k0 = (m[0] > m[1] && m[0] > m[2]) ? 0 : (m[1] > m[2]) ? 1 : 2; // index of largest element of offdiag
+ k1 = (k0 + 1) % 3;
+ k2 = (k0 + 2) % 3;
+ if (o[k0] == 0.0) {
+ break; // diagonal already
+ }
+ thet = (D[k2][k2] - D[k1][k1]) / (2.0 * o[k0]);
+ sgn = (thet > 0.0) ? 1.0 : -1.0;
+ thet *= sgn; // make it positive
+ t = sgn / (thet + ((thet < 1.E6) ? sqrt(thet * thet + 1.0) : thet)); // sign(T)/(|T|+sqrt(T^2+1))
+ c = 1.0 / sqrt(t * t + 1.0); // c= 1/(t^2+1) , t=s/c
+ if (c == 1.0) {
+ break; // no room for improvement - reached machine precision.
+ }
+ jr[0] = jr[1] = jr[2] = jr[3] = 0.0;
+ jr[k0] = sgn * sqrt((1.0 - c) / 2.0); // using 1/2 angle identity sin(a/2) = sqrt((1-cos(a))/2)
+ jr[k0] *= -1.0; // since our quat-to-matrix convention was for v*M instead of M*v
+ jr[3] = sqrt(1.0 - jr[k0] * jr[k0]);
+ if (jr[3] == 1.0) {
+ break; // reached limits of floating point precision
+ }
+ q[0] = (q[3] * jr[0] + q[0] * jr[3] + q[1] * jr[2] - q[2] * jr[1]);
+ q[1] = (q[3] * jr[1] - q[0] * jr[2] + q[1] * jr[3] + q[2] * jr[0]);
+ q[2] = (q[3] * jr[2] + q[0] * jr[1] - q[1] * jr[0] + q[2] * jr[3]);
+ q[3] = (q[3] * jr[3] - q[0] * jr[0] - q[1] * jr[1] - q[2] * jr[2]);
+ mq = sqrt(q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]);
+ q[0] /= mq;
+ q[1] /= mq;
+ q[2] /= mq;
+ q[3] /= mq;
+ }
+}
+const double TetrahedronSet::EPS = 0.0000000000001;
+VoxelSet::VoxelSet()
+{
+ m_minBB[0] = m_minBB[1] = m_minBB[2] = 0.0;
+ m_minBBVoxels[0] = m_minBBVoxels[1] = m_minBBVoxels[2] = 0;
+ m_maxBBVoxels[0] = m_maxBBVoxels[1] = m_maxBBVoxels[2] = 1;
+ m_minBBPts[0] = m_minBBPts[1] = m_minBBPts[2] = 0;
+ m_maxBBPts[0] = m_maxBBPts[1] = m_maxBBPts[2] = 1;
+ m_barycenter[0] = m_barycenter[1] = m_barycenter[2] = 0;
+ m_barycenterPCA[0] = m_barycenterPCA[1] = m_barycenterPCA[2] = 0.0;
+ m_scale = 1.0;
+ m_unitVolume = 1.0;
+ m_numVoxelsOnSurface = 0;
+ m_numVoxelsInsideSurface = 0;
+ memset(m_Q, 0, sizeof(double) * 9);
+ memset(m_D, 0, sizeof(double) * 9);
+}
+VoxelSet::~VoxelSet(void)
+{
+}
+void VoxelSet::ComputeBB()
+{
+ const size_t nVoxels = m_voxels.Size();
+ if (nVoxels == 0)
+ return;
+ for (int32_t h = 0; h < 3; ++h) {
+ m_minBBVoxels[h] = m_voxels[0].m_coord[h];
+ m_maxBBVoxels[h] = m_voxels[0].m_coord[h];
+ }
+ Vec3<double> bary(0.0);
+ for (size_t p = 0; p < nVoxels; ++p) {
+ for (int32_t h = 0; h < 3; ++h) {
+ bary[h] += m_voxels[p].m_coord[h];
+ if (m_minBBVoxels[h] > m_voxels[p].m_coord[h])
+ m_minBBVoxels[h] = m_voxels[p].m_coord[h];
+ if (m_maxBBVoxels[h] < m_voxels[p].m_coord[h])
+ m_maxBBVoxels[h] = m_voxels[p].m_coord[h];
+ }
+ }
+ bary /= (double)nVoxels;
+ for (int32_t h = 0; h < 3; ++h) {
+ m_minBBPts[h] = m_minBBVoxels[h] * m_scale + m_minBB[h];
+ m_maxBBPts[h] = m_maxBBVoxels[h] * m_scale + m_minBB[h];
+ m_barycenter[h] = (short)(bary[h] + 0.5);
+ }
+}
+void VoxelSet::ComputeConvexHull(Mesh& meshCH, const size_t sampling) const
+{
+ const size_t CLUSTER_SIZE = 65536;
+ const size_t nVoxels = m_voxels.Size();
+ if (nVoxels == 0)
+ return;
+
+ SArray<Vec3<double> > cpoints;
+
+ Vec3<double>* points = new Vec3<double>[CLUSTER_SIZE];
+ size_t p = 0;
+ size_t s = 0;
+ short i, j, k;
+ while (p < nVoxels) {
+ size_t q = 0;
+ while (q < CLUSTER_SIZE && p < nVoxels) {
+ if (m_voxels[p].m_data == PRIMITIVE_ON_SURFACE) {
+ ++s;
+ if (s == sampling) {
+ s = 0;
+ i = m_voxels[p].m_coord[0];
+ j = m_voxels[p].m_coord[1];
+ k = m_voxels[p].m_coord[2];
+ Vec3<double> p0((i - 0.5) * m_scale, (j - 0.5) * m_scale, (k - 0.5) * m_scale);
+ Vec3<double> p1((i + 0.5) * m_scale, (j - 0.5) * m_scale, (k - 0.5) * m_scale);
+ Vec3<double> p2((i + 0.5) * m_scale, (j + 0.5) * m_scale, (k - 0.5) * m_scale);
+ Vec3<double> p3((i - 0.5) * m_scale, (j + 0.5) * m_scale, (k - 0.5) * m_scale);
+ Vec3<double> p4((i - 0.5) * m_scale, (j - 0.5) * m_scale, (k + 0.5) * m_scale);
+ Vec3<double> p5((i + 0.5) * m_scale, (j - 0.5) * m_scale, (k + 0.5) * m_scale);
+ Vec3<double> p6((i + 0.5) * m_scale, (j + 0.5) * m_scale, (k + 0.5) * m_scale);
+ Vec3<double> p7((i - 0.5) * m_scale, (j + 0.5) * m_scale, (k + 0.5) * m_scale);
+ points[q++] = p0 + m_minBB;
+ points[q++] = p1 + m_minBB;
+ points[q++] = p2 + m_minBB;
+ points[q++] = p3 + m_minBB;
+ points[q++] = p4 + m_minBB;
+ points[q++] = p5 + m_minBB;
+ points[q++] = p6 + m_minBB;
+ points[q++] = p7 + m_minBB;
+ }
+ }
+ ++p;
+ }
+ btConvexHullComputer ch;
+ ch.compute((double*)points, 3 * sizeof(double), (int32_t)q, -1.0, -1.0);
+ for (int32_t v = 0; v < ch.vertices.size(); v++) {
+ cpoints.PushBack(Vec3<double>(ch.vertices[v].getX(), ch.vertices[v].getY(), ch.vertices[v].getZ()));
+ }
+ }
+ delete[] points;
+
+ points = cpoints.Data();
+ btConvexHullComputer ch;
+ ch.compute((double*)points, 3 * sizeof(double), (int32_t)cpoints.Size(), -1.0, -1.0);
+ meshCH.ResizePoints(0);
+ meshCH.ResizeTriangles(0);
+ for (int32_t v = 0; v < ch.vertices.size(); v++) {
+ meshCH.AddPoint(Vec3<double>(ch.vertices[v].getX(), ch.vertices[v].getY(), ch.vertices[v].getZ()));
+ }
+ const int32_t nt = ch.faces.size();
+ for (int32_t t = 0; t < nt; ++t) {
+ const btConvexHullComputer::Edge* sourceEdge = &(ch.edges[ch.faces[t]]);
+ int32_t a = sourceEdge->getSourceVertex();
+ int32_t b = sourceEdge->getTargetVertex();
+ const btConvexHullComputer::Edge* edge = sourceEdge->getNextEdgeOfFace();
+ int32_t c = edge->getTargetVertex();
+ while (c != a) {
+ meshCH.AddTriangle(Vec3<int32_t>(a, b, c));
+ edge = edge->getNextEdgeOfFace();
+ b = c;
+ c = edge->getTargetVertex();
+ }
+ }
+}
+void VoxelSet::GetPoints(const Voxel& voxel,
+ Vec3<double>* const pts) const
+{
+ short i = voxel.m_coord[0];
+ short j = voxel.m_coord[1];
+ short k = voxel.m_coord[2];
+ pts[0][0] = (i - 0.5) * m_scale + m_minBB[0];
+ pts[1][0] = (i + 0.5) * m_scale + m_minBB[0];
+ pts[2][0] = (i + 0.5) * m_scale + m_minBB[0];
+ pts[3][0] = (i - 0.5) * m_scale + m_minBB[0];
+ pts[4][0] = (i - 0.5) * m_scale + m_minBB[0];
+ pts[5][0] = (i + 0.5) * m_scale + m_minBB[0];
+ pts[6][0] = (i + 0.5) * m_scale + m_minBB[0];
+ pts[7][0] = (i - 0.5) * m_scale + m_minBB[0];
+ pts[0][1] = (j - 0.5) * m_scale + m_minBB[1];
+ pts[1][1] = (j - 0.5) * m_scale + m_minBB[1];
+ pts[2][1] = (j + 0.5) * m_scale + m_minBB[1];
+ pts[3][1] = (j + 0.5) * m_scale + m_minBB[1];
+ pts[4][1] = (j - 0.5) * m_scale + m_minBB[1];
+ pts[5][1] = (j - 0.5) * m_scale + m_minBB[1];
+ pts[6][1] = (j + 0.5) * m_scale + m_minBB[1];
+ pts[7][1] = (j + 0.5) * m_scale + m_minBB[1];
+ pts[0][2] = (k - 0.5) * m_scale + m_minBB[2];
+ pts[1][2] = (k - 0.5) * m_scale + m_minBB[2];
+ pts[2][2] = (k - 0.5) * m_scale + m_minBB[2];
+ pts[3][2] = (k - 0.5) * m_scale + m_minBB[2];
+ pts[4][2] = (k + 0.5) * m_scale + m_minBB[2];
+ pts[5][2] = (k + 0.5) * m_scale + m_minBB[2];
+ pts[6][2] = (k + 0.5) * m_scale + m_minBB[2];
+ pts[7][2] = (k + 0.5) * m_scale + m_minBB[2];
+}
+void VoxelSet::Intersect(const Plane& plane,
+ SArray<Vec3<double> >* const positivePts,
+ SArray<Vec3<double> >* const negativePts,
+ const size_t sampling) const
+{
+ const size_t nVoxels = m_voxels.Size();
+ if (nVoxels == 0)
+ return;
+ const double d0 = m_scale;
+ double d;
+ Vec3<double> pts[8];
+ Vec3<double> pt;
+ Voxel voxel;
+ size_t sp = 0;
+ size_t sn = 0;
+ for (size_t v = 0; v < nVoxels; ++v) {
+ voxel = m_voxels[v];
+ pt = GetPoint(voxel);
+ d = plane.m_a * pt[0] + plane.m_b * pt[1] + plane.m_c * pt[2] + plane.m_d;
+ // if (d >= 0.0 && d <= d0) positivePts->PushBack(pt);
+ // else if (d < 0.0 && -d <= d0) negativePts->PushBack(pt);
+ if (d >= 0.0) {
+ if (d <= d0) {
+ GetPoints(voxel, pts);
+ for (int32_t k = 0; k < 8; ++k) {
+ positivePts->PushBack(pts[k]);
+ }
+ }
+ else {
+ if (++sp == sampling) {
+ // positivePts->PushBack(pt);
+ GetPoints(voxel, pts);
+ for (int32_t k = 0; k < 8; ++k) {
+ positivePts->PushBack(pts[k]);
+ }
+ sp = 0;
+ }
+ }
+ }
+ else {
+ if (-d <= d0) {
+ GetPoints(voxel, pts);
+ for (int32_t k = 0; k < 8; ++k) {
+ negativePts->PushBack(pts[k]);
+ }
+ }
+ else {
+ if (++sn == sampling) {
+ // negativePts->PushBack(pt);
+ GetPoints(voxel, pts);
+ for (int32_t k = 0; k < 8; ++k) {
+ negativePts->PushBack(pts[k]);
+ }
+ sn = 0;
+ }
+ }
+ }
+ }
+}
+void VoxelSet::ComputeExteriorPoints(const Plane& plane,
+ const Mesh& mesh,
+ SArray<Vec3<double> >* const exteriorPts) const
+{
+ const size_t nVoxels = m_voxels.Size();
+ if (nVoxels == 0)
+ return;
+ double d;
+ Vec3<double> pt;
+ Vec3<double> pts[8];
+ Voxel voxel;
+ for (size_t v = 0; v < nVoxels; ++v) {
+ voxel = m_voxels[v];
+ pt = GetPoint(voxel);
+ d = plane.m_a * pt[0] + plane.m_b * pt[1] + plane.m_c * pt[2] + plane.m_d;
+ if (d >= 0.0) {
+ if (!mesh.IsInside(pt)) {
+ GetPoints(voxel, pts);
+ for (int32_t k = 0; k < 8; ++k) {
+ exteriorPts->PushBack(pts[k]);
+ }
+ }
+ }
+ }
+}
+void VoxelSet::ComputeClippedVolumes(const Plane& plane,
+ double& positiveVolume,
+ double& negativeVolume) const
+{
+ negativeVolume = 0.0;
+ positiveVolume = 0.0;
+ const size_t nVoxels = m_voxels.Size();
+ if (nVoxels == 0)
+ return;
+ double d;
+ Vec3<double> pt;
+ size_t nPositiveVoxels = 0;
+ for (size_t v = 0; v < nVoxels; ++v) {
+ pt = GetPoint(m_voxels[v]);
+ d = plane.m_a * pt[0] + plane.m_b * pt[1] + plane.m_c * pt[2] + plane.m_d;
+ nPositiveVoxels += (d >= 0.0);
+ }
+ size_t nNegativeVoxels = nVoxels - nPositiveVoxels;
+ positiveVolume = m_unitVolume * nPositiveVoxels;
+ negativeVolume = m_unitVolume * nNegativeVoxels;
+}
+void VoxelSet::SelectOnSurface(PrimitiveSet* const onSurfP) const
+{
+ VoxelSet* const onSurf = (VoxelSet*)onSurfP;
+ const size_t nVoxels = m_voxels.Size();
+ if (nVoxels == 0)
+ return;
+
+ for (int32_t h = 0; h < 3; ++h) {
+ onSurf->m_minBB[h] = m_minBB[h];
+ }
+ onSurf->m_voxels.Resize(0);
+ onSurf->m_scale = m_scale;
+ onSurf->m_unitVolume = m_unitVolume;
+ onSurf->m_numVoxelsOnSurface = 0;
+ onSurf->m_numVoxelsInsideSurface = 0;
+ Voxel voxel;
+ for (size_t v = 0; v < nVoxels; ++v) {
+ voxel = m_voxels[v];
+ if (voxel.m_data == PRIMITIVE_ON_SURFACE) {
+ onSurf->m_voxels.PushBack(voxel);
+ ++onSurf->m_numVoxelsOnSurface;
+ }
+ }
+}
+void VoxelSet::Clip(const Plane& plane,
+ PrimitiveSet* const positivePartP,
+ PrimitiveSet* const negativePartP) const
+{
+ VoxelSet* const positivePart = (VoxelSet*)positivePartP;
+ VoxelSet* const negativePart = (VoxelSet*)negativePartP;
+ const size_t nVoxels = m_voxels.Size();
+ if (nVoxels == 0)
+ return;
+
+ for (int32_t h = 0; h < 3; ++h) {
+ negativePart->m_minBB[h] = positivePart->m_minBB[h] = m_minBB[h];
+ }
+ positivePart->m_voxels.Resize(0);
+ negativePart->m_voxels.Resize(0);
+ positivePart->m_voxels.Allocate(nVoxels);
+ negativePart->m_voxels.Allocate(nVoxels);
+ negativePart->m_scale = positivePart->m_scale = m_scale;
+ negativePart->m_unitVolume = positivePart->m_unitVolume = m_unitVolume;
+ negativePart->m_numVoxelsOnSurface = positivePart->m_numVoxelsOnSurface = 0;
+ negativePart->m_numVoxelsInsideSurface = positivePart->m_numVoxelsInsideSurface = 0;
+
+ double d;
+ Vec3<double> pt;
+ Voxel voxel;
+ const double d0 = m_scale;
+ for (size_t v = 0; v < nVoxels; ++v) {
+ voxel = m_voxels[v];
+ pt = GetPoint(voxel);
+ d = plane.m_a * pt[0] + plane.m_b * pt[1] + plane.m_c * pt[2] + plane.m_d;
+ if (d >= 0.0) {
+ if (voxel.m_data == PRIMITIVE_ON_SURFACE || d <= d0) {
+ voxel.m_data = PRIMITIVE_ON_SURFACE;
+ positivePart->m_voxels.PushBack(voxel);
+ ++positivePart->m_numVoxelsOnSurface;
+ }
+ else {
+ positivePart->m_voxels.PushBack(voxel);
+ ++positivePart->m_numVoxelsInsideSurface;
+ }
+ }
+ else {
+ if (voxel.m_data == PRIMITIVE_ON_SURFACE || -d <= d0) {
+ voxel.m_data = PRIMITIVE_ON_SURFACE;
+ negativePart->m_voxels.PushBack(voxel);
+ ++negativePart->m_numVoxelsOnSurface;
+ }
+ else {
+ negativePart->m_voxels.PushBack(voxel);
+ ++negativePart->m_numVoxelsInsideSurface;
+ }
+ }
+ }
+}
+void VoxelSet::Convert(Mesh& mesh, const VOXEL_VALUE value) const
+{
+ const size_t nVoxels = m_voxels.Size();
+ if (nVoxels == 0)
+ return;
+ Voxel voxel;
+ Vec3<double> pts[8];
+ for (size_t v = 0; v < nVoxels; ++v) {
+ voxel = m_voxels[v];
+ if (voxel.m_data == value) {
+ GetPoints(voxel, pts);
+ int32_t s = (int32_t)mesh.GetNPoints();
+ for (int32_t k = 0; k < 8; ++k) {
+ mesh.AddPoint(pts[k]);
+ }
+ mesh.AddTriangle(Vec3<int32_t>(s + 0, s + 2, s + 1));
+ mesh.AddTriangle(Vec3<int32_t>(s + 0, s + 3, s + 2));
+ mesh.AddTriangle(Vec3<int32_t>(s + 4, s + 5, s + 6));
+ mesh.AddTriangle(Vec3<int32_t>(s + 4, s + 6, s + 7));
+ mesh.AddTriangle(Vec3<int32_t>(s + 7, s + 6, s + 2));
+ mesh.AddTriangle(Vec3<int32_t>(s + 7, s + 2, s + 3));
+ mesh.AddTriangle(Vec3<int32_t>(s + 4, s + 1, s + 5));
+ mesh.AddTriangle(Vec3<int32_t>(s + 4, s + 0, s + 1));
+ mesh.AddTriangle(Vec3<int32_t>(s + 6, s + 5, s + 1));
+ mesh.AddTriangle(Vec3<int32_t>(s + 6, s + 1, s + 2));
+ mesh.AddTriangle(Vec3<int32_t>(s + 7, s + 0, s + 4));
+ mesh.AddTriangle(Vec3<int32_t>(s + 7, s + 3, s + 0));
+ }
+ }
+}
+void VoxelSet::ComputePrincipalAxes()
+{
+ const size_t nVoxels = m_voxels.Size();
+ if (nVoxels == 0)
+ return;
+ m_barycenterPCA[0] = m_barycenterPCA[1] = m_barycenterPCA[2] = 0.0;
+ for (size_t v = 0; v < nVoxels; ++v) {
+ Voxel& voxel = m_voxels[v];
+ m_barycenterPCA[0] += voxel.m_coord[0];
+ m_barycenterPCA[1] += voxel.m_coord[1];
+ m_barycenterPCA[2] += voxel.m_coord[2];
+ }
+ m_barycenterPCA /= (double)nVoxels;
+
+ double covMat[3][3] = { { 0.0, 0.0, 0.0 },
+ { 0.0, 0.0, 0.0 },
+ { 0.0, 0.0, 0.0 } };
+ double x, y, z;
+ for (size_t v = 0; v < nVoxels; ++v) {
+ Voxel& voxel = m_voxels[v];
+ x = voxel.m_coord[0] - m_barycenter[0];
+ y = voxel.m_coord[1] - m_barycenter[1];
+ z = voxel.m_coord[2] - m_barycenter[2];
+ covMat[0][0] += x * x;
+ covMat[1][1] += y * y;
+ covMat[2][2] += z * z;
+ covMat[0][1] += x * y;
+ covMat[0][2] += x * z;
+ covMat[1][2] += y * z;
+ }
+ covMat[0][0] /= nVoxels;
+ covMat[1][1] /= nVoxels;
+ covMat[2][2] /= nVoxels;
+ covMat[0][1] /= nVoxels;
+ covMat[0][2] /= nVoxels;
+ covMat[1][2] /= nVoxels;
+ covMat[1][0] = covMat[0][1];
+ covMat[2][0] = covMat[0][2];
+ covMat[2][1] = covMat[1][2];
+ Diagonalize(covMat, m_Q, m_D);
+}
+Volume::Volume()
+{
+ m_dim[0] = m_dim[1] = m_dim[2] = 0;
+ m_minBB[0] = m_minBB[1] = m_minBB[2] = 0.0;
+ m_maxBB[0] = m_maxBB[1] = m_maxBB[2] = 1.0;
+ m_numVoxelsOnSurface = 0;
+ m_numVoxelsInsideSurface = 0;
+ m_numVoxelsOutsideSurface = 0;
+ m_scale = 1.0;
+ m_data = 0;
+}
+Volume::~Volume(void)
+{
+ delete[] m_data;
+}
+void Volume::Allocate()
+{
+ delete[] m_data;
+ size_t size = m_dim[0] * m_dim[1] * m_dim[2];
+ m_data = new unsigned char[size];
+ memset(m_data, PRIMITIVE_UNDEFINED, sizeof(unsigned char) * size);
+}
+void Volume::Free()
+{
+ delete[] m_data;
+ m_data = 0;
+}
+void Volume::FillOutsideSurface(const size_t i0,
+ const size_t j0,
+ const size_t k0,
+ const size_t i1,
+ const size_t j1,
+ const size_t k1)
+{
+ const short neighbours[6][3] = { { 1, 0, 0 },
+ { 0, 1, 0 },
+ { 0, 0, 1 },
+ { -1, 0, 0 },
+ { 0, -1, 0 },
+ { 0, 0, -1 } };
+ std::queue<Vec3<short> > fifo;
+ Vec3<short> current;
+ short a, b, c;
+ for (size_t i = i0; i < i1; ++i) {
+ for (size_t j = j0; j < j1; ++j) {
+ for (size_t k = k0; k < k1; ++k) {
+
+ if (GetVoxel(i, j, k) == PRIMITIVE_UNDEFINED) {
+ current[0] = (short)i;
+ current[1] = (short)j;
+ current[2] = (short)k;
+ fifo.push(current);
+ GetVoxel(current[0], current[1], current[2]) = PRIMITIVE_OUTSIDE_SURFACE;
+ ++m_numVoxelsOutsideSurface;
+ while (fifo.size() > 0) {
+ current = fifo.front();
+ fifo.pop();
+ for (int32_t h = 0; h < 6; ++h) {
+ a = current[0] + neighbours[h][0];
+ b = current[1] + neighbours[h][1];
+ c = current[2] + neighbours[h][2];
+ if (a < 0 || a >= (int32_t)m_dim[0] || b < 0 || b >= (int32_t)m_dim[1] || c < 0 || c >= (int32_t)m_dim[2]) {
+ continue;
+ }
+ unsigned char& v = GetVoxel(a, b, c);
+ if (v == PRIMITIVE_UNDEFINED) {
+ v = PRIMITIVE_OUTSIDE_SURFACE;
+ ++m_numVoxelsOutsideSurface;
+ fifo.push(Vec3<short>(a, b, c));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+void Volume::FillInsideSurface()
+{
+ const size_t i0 = m_dim[0];
+ const size_t j0 = m_dim[1];
+ const size_t k0 = m_dim[2];
+ for (size_t i = 0; i < i0; ++i) {
+ for (size_t j = 0; j < j0; ++j) {
+ for (size_t k = 0; k < k0; ++k) {
+ unsigned char& v = GetVoxel(i, j, k);
+ if (v == PRIMITIVE_UNDEFINED) {
+ v = PRIMITIVE_INSIDE_SURFACE;
+ ++m_numVoxelsInsideSurface;
+ }
+ }
+ }
+ }
+}
+void Volume::Convert(Mesh& mesh, const VOXEL_VALUE value) const
+{
+ const size_t i0 = m_dim[0];
+ const size_t j0 = m_dim[1];
+ const size_t k0 = m_dim[2];
+ for (size_t i = 0; i < i0; ++i) {
+ for (size_t j = 0; j < j0; ++j) {
+ for (size_t k = 0; k < k0; ++k) {
+ const unsigned char& voxel = GetVoxel(i, j, k);
+ if (voxel == value) {
+ Vec3<double> p0((i - 0.5) * m_scale, (j - 0.5) * m_scale, (k - 0.5) * m_scale);
+ Vec3<double> p1((i + 0.5) * m_scale, (j - 0.5) * m_scale, (k - 0.5) * m_scale);
+ Vec3<double> p2((i + 0.5) * m_scale, (j + 0.5) * m_scale, (k - 0.5) * m_scale);
+ Vec3<double> p3((i - 0.5) * m_scale, (j + 0.5) * m_scale, (k - 0.5) * m_scale);
+ Vec3<double> p4((i - 0.5) * m_scale, (j - 0.5) * m_scale, (k + 0.5) * m_scale);
+ Vec3<double> p5((i + 0.5) * m_scale, (j - 0.5) * m_scale, (k + 0.5) * m_scale);
+ Vec3<double> p6((i + 0.5) * m_scale, (j + 0.5) * m_scale, (k + 0.5) * m_scale);
+ Vec3<double> p7((i - 0.5) * m_scale, (j + 0.5) * m_scale, (k + 0.5) * m_scale);
+ int32_t s = (int32_t)mesh.GetNPoints();
+ mesh.AddPoint(p0 + m_minBB);
+ mesh.AddPoint(p1 + m_minBB);
+ mesh.AddPoint(p2 + m_minBB);
+ mesh.AddPoint(p3 + m_minBB);
+ mesh.AddPoint(p4 + m_minBB);
+ mesh.AddPoint(p5 + m_minBB);
+ mesh.AddPoint(p6 + m_minBB);
+ mesh.AddPoint(p7 + m_minBB);
+ mesh.AddTriangle(Vec3<int32_t>(s + 0, s + 2, s + 1));
+ mesh.AddTriangle(Vec3<int32_t>(s + 0, s + 3, s + 2));
+ mesh.AddTriangle(Vec3<int32_t>(s + 4, s + 5, s + 6));
+ mesh.AddTriangle(Vec3<int32_t>(s + 4, s + 6, s + 7));
+ mesh.AddTriangle(Vec3<int32_t>(s + 7, s + 6, s + 2));
+ mesh.AddTriangle(Vec3<int32_t>(s + 7, s + 2, s + 3));
+ mesh.AddTriangle(Vec3<int32_t>(s + 4, s + 1, s + 5));
+ mesh.AddTriangle(Vec3<int32_t>(s + 4, s + 0, s + 1));
+ mesh.AddTriangle(Vec3<int32_t>(s + 6, s + 5, s + 1));
+ mesh.AddTriangle(Vec3<int32_t>(s + 6, s + 1, s + 2));
+ mesh.AddTriangle(Vec3<int32_t>(s + 7, s + 0, s + 4));
+ mesh.AddTriangle(Vec3<int32_t>(s + 7, s + 3, s + 0));
+ }
+ }
+ }
+ }
+}
+void Volume::Convert(VoxelSet& vset) const
+{
+ for (int32_t h = 0; h < 3; ++h) {
+ vset.m_minBB[h] = m_minBB[h];
+ }
+ vset.m_voxels.Allocate(m_numVoxelsInsideSurface + m_numVoxelsOnSurface);
+ vset.m_scale = m_scale;
+ vset.m_unitVolume = m_scale * m_scale * m_scale;
+ const short i0 = (short)m_dim[0];
+ const short j0 = (short)m_dim[1];
+ const short k0 = (short)m_dim[2];
+ Voxel voxel;
+ vset.m_numVoxelsOnSurface = 0;
+ vset.m_numVoxelsInsideSurface = 0;
+ for (short i = 0; i < i0; ++i) {
+ for (short j = 0; j < j0; ++j) {
+ for (short k = 0; k < k0; ++k) {
+ const unsigned char& value = GetVoxel(i, j, k);
+ if (value == PRIMITIVE_INSIDE_SURFACE) {
+ voxel.m_coord[0] = i;
+ voxel.m_coord[1] = j;
+ voxel.m_coord[2] = k;
+ voxel.m_data = PRIMITIVE_INSIDE_SURFACE;
+ vset.m_voxels.PushBack(voxel);
+ ++vset.m_numVoxelsInsideSurface;
+ }
+ else if (value == PRIMITIVE_ON_SURFACE) {
+ voxel.m_coord[0] = i;
+ voxel.m_coord[1] = j;
+ voxel.m_coord[2] = k;
+ voxel.m_data = PRIMITIVE_ON_SURFACE;
+ vset.m_voxels.PushBack(voxel);
+ ++vset.m_numVoxelsOnSurface;
+ }
+ }
+ }
+ }
+}
+
+void Volume::Convert(TetrahedronSet& tset) const
+{
+ tset.m_tetrahedra.Allocate(5 * (m_numVoxelsInsideSurface + m_numVoxelsOnSurface));
+ tset.m_scale = m_scale;
+ const short i0 = (short)m_dim[0];
+ const short j0 = (short)m_dim[1];
+ const short k0 = (short)m_dim[2];
+ tset.m_numTetrahedraOnSurface = 0;
+ tset.m_numTetrahedraInsideSurface = 0;
+ Tetrahedron tetrahedron;
+ for (short i = 0; i < i0; ++i) {
+ for (short j = 0; j < j0; ++j) {
+ for (short k = 0; k < k0; ++k) {
+ const unsigned char& value = GetVoxel(i, j, k);
+ if (value == PRIMITIVE_INSIDE_SURFACE || value == PRIMITIVE_ON_SURFACE) {
+ tetrahedron.m_data = value;
+ Vec3<double> p1((i - 0.5) * m_scale + m_minBB[0], (j - 0.5) * m_scale + m_minBB[1], (k - 0.5) * m_scale + m_minBB[2]);
+ Vec3<double> p2((i + 0.5) * m_scale + m_minBB[0], (j - 0.5) * m_scale + m_minBB[1], (k - 0.5) * m_scale + m_minBB[2]);
+ Vec3<double> p3((i + 0.5) * m_scale + m_minBB[0], (j + 0.5) * m_scale + m_minBB[1], (k - 0.5) * m_scale + m_minBB[2]);
+ Vec3<double> p4((i - 0.5) * m_scale + m_minBB[0], (j + 0.5) * m_scale + m_minBB[1], (k - 0.5) * m_scale + m_minBB[2]);
+ Vec3<double> p5((i - 0.5) * m_scale + m_minBB[0], (j - 0.5) * m_scale + m_minBB[1], (k + 0.5) * m_scale + m_minBB[2]);
+ Vec3<double> p6((i + 0.5) * m_scale + m_minBB[0], (j - 0.5) * m_scale + m_minBB[1], (k + 0.5) * m_scale + m_minBB[2]);
+ Vec3<double> p7((i + 0.5) * m_scale + m_minBB[0], (j + 0.5) * m_scale + m_minBB[1], (k + 0.5) * m_scale + m_minBB[2]);
+ Vec3<double> p8((i - 0.5) * m_scale + m_minBB[0], (j + 0.5) * m_scale + m_minBB[1], (k + 0.5) * m_scale + m_minBB[2]);
+
+ tetrahedron.m_pts[0] = p2;
+ tetrahedron.m_pts[1] = p4;
+ tetrahedron.m_pts[2] = p7;
+ tetrahedron.m_pts[3] = p5;
+ tset.m_tetrahedra.PushBack(tetrahedron);
+
+ tetrahedron.m_pts[0] = p6;
+ tetrahedron.m_pts[1] = p2;
+ tetrahedron.m_pts[2] = p7;
+ tetrahedron.m_pts[3] = p5;
+ tset.m_tetrahedra.PushBack(tetrahedron);
+
+ tetrahedron.m_pts[0] = p3;
+ tetrahedron.m_pts[1] = p4;
+ tetrahedron.m_pts[2] = p7;
+ tetrahedron.m_pts[3] = p2;
+ tset.m_tetrahedra.PushBack(tetrahedron);
+
+ tetrahedron.m_pts[0] = p1;
+ tetrahedron.m_pts[1] = p4;
+ tetrahedron.m_pts[2] = p2;
+ tetrahedron.m_pts[3] = p5;
+ tset.m_tetrahedra.PushBack(tetrahedron);
+
+ tetrahedron.m_pts[0] = p8;
+ tetrahedron.m_pts[1] = p5;
+ tetrahedron.m_pts[2] = p7;
+ tetrahedron.m_pts[3] = p4;
+ tset.m_tetrahedra.PushBack(tetrahedron);
+ if (value == PRIMITIVE_INSIDE_SURFACE) {
+ tset.m_numTetrahedraInsideSurface += 5;
+ }
+ else {
+ tset.m_numTetrahedraOnSurface += 5;
+ }
+ }
+ }
+ }
+ }
+}
+
+void Volume::AlignToPrincipalAxes(double (&rot)[3][3]) const
+{
+ const short i0 = (short)m_dim[0];
+ const short j0 = (short)m_dim[1];
+ const short k0 = (short)m_dim[2];
+ Vec3<double> barycenter(0.0);
+ size_t nVoxels = 0;
+ for (short i = 0; i < i0; ++i) {
+ for (short j = 0; j < j0; ++j) {
+ for (short k = 0; k < k0; ++k) {
+ const unsigned char& value = GetVoxel(i, j, k);
+ if (value == PRIMITIVE_INSIDE_SURFACE || value == PRIMITIVE_ON_SURFACE) {
+ barycenter[0] += i;
+ barycenter[1] += j;
+ barycenter[2] += k;
+ ++nVoxels;
+ }
+ }
+ }
+ }
+ barycenter /= (double)nVoxels;
+
+ double covMat[3][3] = { { 0.0, 0.0, 0.0 },
+ { 0.0, 0.0, 0.0 },
+ { 0.0, 0.0, 0.0 } };
+ double x, y, z;
+ for (short i = 0; i < i0; ++i) {
+ for (short j = 0; j < j0; ++j) {
+ for (short k = 0; k < k0; ++k) {
+ const unsigned char& value = GetVoxel(i, j, k);
+ if (value == PRIMITIVE_INSIDE_SURFACE || value == PRIMITIVE_ON_SURFACE) {
+ x = i - barycenter[0];
+ y = j - barycenter[1];
+ z = k - barycenter[2];
+ covMat[0][0] += x * x;
+ covMat[1][1] += y * y;
+ covMat[2][2] += z * z;
+ covMat[0][1] += x * y;
+ covMat[0][2] += x * z;
+ covMat[1][2] += y * z;
+ }
+ }
+ }
+ }
+ covMat[1][0] = covMat[0][1];
+ covMat[2][0] = covMat[0][2];
+ covMat[2][1] = covMat[1][2];
+ double D[3][3];
+ Diagonalize(covMat, rot, D);
+}
+TetrahedronSet::TetrahedronSet()
+{
+ m_minBB[0] = m_minBB[1] = m_minBB[2] = 0.0;
+ m_maxBB[0] = m_maxBB[1] = m_maxBB[2] = 1.0;
+ m_barycenter[0] = m_barycenter[1] = m_barycenter[2] = 0.0;
+ m_scale = 1.0;
+ m_numTetrahedraOnSurface = 0;
+ m_numTetrahedraInsideSurface = 0;
+ memset(m_Q, 0, sizeof(double) * 9);
+ memset(m_D, 0, sizeof(double) * 9);
+}
+TetrahedronSet::~TetrahedronSet(void)
+{
+}
+void TetrahedronSet::ComputeBB()
+{
+ const size_t nTetrahedra = m_tetrahedra.Size();
+ if (nTetrahedra == 0)
+ return;
+
+ for (int32_t h = 0; h < 3; ++h) {
+ m_minBB[h] = m_maxBB[h] = m_tetrahedra[0].m_pts[0][h];
+ m_barycenter[h] = 0.0;
+ }
+ for (size_t p = 0; p < nTetrahedra; ++p) {
+ for (int32_t i = 0; i < 4; ++i) {
+ for (int32_t h = 0; h < 3; ++h) {
+ if (m_minBB[h] > m_tetrahedra[p].m_pts[i][h])
+ m_minBB[h] = m_tetrahedra[p].m_pts[i][h];
+ if (m_maxBB[h] < m_tetrahedra[p].m_pts[i][h])
+ m_maxBB[h] = m_tetrahedra[p].m_pts[i][h];
+ m_barycenter[h] += m_tetrahedra[p].m_pts[i][h];
+ }
+ }
+ }
+ m_barycenter /= (double)(4 * nTetrahedra);
+}
+void TetrahedronSet::ComputeConvexHull(Mesh& meshCH, const size_t sampling) const
+{
+ const size_t CLUSTER_SIZE = 65536;
+ const size_t nTetrahedra = m_tetrahedra.Size();
+ if (nTetrahedra == 0)
+ return;
+
+ SArray<Vec3<double> > cpoints;
+
+ Vec3<double>* points = new Vec3<double>[CLUSTER_SIZE];
+ size_t p = 0;
+ while (p < nTetrahedra) {
+ size_t q = 0;
+ size_t s = 0;
+ while (q < CLUSTER_SIZE && p < nTetrahedra) {
+ if (m_tetrahedra[p].m_data == PRIMITIVE_ON_SURFACE) {
+ ++s;
+ if (s == sampling) {
+ s = 0;
+ for (int32_t a = 0; a < 4; ++a) {
+ points[q++] = m_tetrahedra[p].m_pts[a];
+ for (int32_t xx = 0; xx < 3; ++xx) {
+ assert(m_tetrahedra[p].m_pts[a][xx] + EPS >= m_minBB[xx]);
+ assert(m_tetrahedra[p].m_pts[a][xx] <= m_maxBB[xx] + EPS);
+ }
+ }
+ }
+ }
+ ++p;
+ }
+ btConvexHullComputer ch;
+ ch.compute((double*)points, 3 * sizeof(double), (int32_t)q, -1.0, -1.0);
+ for (int32_t v = 0; v < ch.vertices.size(); v++) {
+ cpoints.PushBack(Vec3<double>(ch.vertices[v].getX(), ch.vertices[v].getY(), ch.vertices[v].getZ()));
+ }
+ }
+ delete[] points;
+
+ points = cpoints.Data();
+ btConvexHullComputer ch;
+ ch.compute((double*)points, 3 * sizeof(double), (int32_t)cpoints.Size(), -1.0, -1.0);
+ meshCH.ResizePoints(0);
+ meshCH.ResizeTriangles(0);
+ for (int32_t v = 0; v < ch.vertices.size(); v++) {
+ meshCH.AddPoint(Vec3<double>(ch.vertices[v].getX(), ch.vertices[v].getY(), ch.vertices[v].getZ()));
+ }
+ const int32_t nt = ch.faces.size();
+ for (int32_t t = 0; t < nt; ++t) {
+ const btConvexHullComputer::Edge* sourceEdge = &(ch.edges[ch.faces[t]]);
+ int32_t a = sourceEdge->getSourceVertex();
+ int32_t b = sourceEdge->getTargetVertex();
+ const btConvexHullComputer::Edge* edge = sourceEdge->getNextEdgeOfFace();
+ int32_t c = edge->getTargetVertex();
+ while (c != a) {
+ meshCH.AddTriangle(Vec3<int32_t>(a, b, c));
+ edge = edge->getNextEdgeOfFace();
+ b = c;
+ c = edge->getTargetVertex();
+ }
+ }
+}
+inline bool TetrahedronSet::Add(Tetrahedron& tetrahedron)
+{
+ double v = ComputeVolume4(tetrahedron.m_pts[0], tetrahedron.m_pts[1], tetrahedron.m_pts[2], tetrahedron.m_pts[3]);
+
+ const double EPS = 0.0000000001;
+ if (fabs(v) < EPS) {
+ return false;
+ }
+ else if (v < 0.0) {
+ Vec3<double> tmp = tetrahedron.m_pts[0];
+ tetrahedron.m_pts[0] = tetrahedron.m_pts[1];
+ tetrahedron.m_pts[1] = tmp;
+ }
+
+ for (int32_t a = 0; a < 4; ++a) {
+ for (int32_t xx = 0; xx < 3; ++xx) {
+ assert(tetrahedron.m_pts[a][xx] + EPS >= m_minBB[xx]);
+ assert(tetrahedron.m_pts[a][xx] <= m_maxBB[xx] + EPS);
+ }
+ }
+ m_tetrahedra.PushBack(tetrahedron);
+ return true;
+}
+
+void TetrahedronSet::AddClippedTetrahedra(const Vec3<double> (&pts)[10], const int32_t nPts)
+{
+ const int32_t tetF[4][3] = { { 0, 1, 2 }, { 2, 1, 3 }, { 3, 1, 0 }, { 3, 0, 2 } };
+ if (nPts < 4) {
+ return;
+ }
+ else if (nPts == 4) {
+ Tetrahedron tetrahedron;
+ tetrahedron.m_data = PRIMITIVE_ON_SURFACE;
+ tetrahedron.m_pts[0] = pts[0];
+ tetrahedron.m_pts[1] = pts[1];
+ tetrahedron.m_pts[2] = pts[2];
+ tetrahedron.m_pts[3] = pts[3];
+ if (Add(tetrahedron)) {
+ ++m_numTetrahedraOnSurface;
+ }
+ }
+ else if (nPts == 5) {
+ const int32_t tet[15][4] = {
+ { 0, 1, 2, 3 }, { 1, 2, 3, 4 }, { 0, 2, 3, 4 }, { 0, 1, 3, 4 }, { 0, 1, 2, 4 },
+ };
+ const int32_t rem[5] = { 4, 0, 1, 2, 3 };
+ double maxVol = 0.0;
+ int32_t h0 = -1;
+ Tetrahedron tetrahedron0;
+ tetrahedron0.m_data = PRIMITIVE_ON_SURFACE;
+ for (int32_t h = 0; h < 5; ++h) {
+ double v = ComputeVolume4(pts[tet[h][0]], pts[tet[h][1]], pts[tet[h][2]], pts[tet[h][3]]);
+ if (v > maxVol) {
+ h0 = h;
+ tetrahedron0.m_pts[0] = pts[tet[h][0]];
+ tetrahedron0.m_pts[1] = pts[tet[h][1]];
+ tetrahedron0.m_pts[2] = pts[tet[h][2]];
+ tetrahedron0.m_pts[3] = pts[tet[h][3]];
+ maxVol = v;
+ }
+ else if (-v > maxVol) {
+ h0 = h;
+ tetrahedron0.m_pts[0] = pts[tet[h][1]];
+ tetrahedron0.m_pts[1] = pts[tet[h][0]];
+ tetrahedron0.m_pts[2] = pts[tet[h][2]];
+ tetrahedron0.m_pts[3] = pts[tet[h][3]];
+ maxVol = -v;
+ }
+ }
+ if (h0 == -1)
+ return;
+ if (Add(tetrahedron0)) {
+ ++m_numTetrahedraOnSurface;
+ }
+ else {
+ return;
+ }
+ int32_t a = rem[h0];
+ maxVol = 0.0;
+ int32_t h1 = -1;
+ Tetrahedron tetrahedron1;
+ tetrahedron1.m_data = PRIMITIVE_ON_SURFACE;
+ for (int32_t h = 0; h < 4; ++h) {
+ double v = ComputeVolume4(pts[a], tetrahedron0.m_pts[tetF[h][0]], tetrahedron0.m_pts[tetF[h][1]], tetrahedron0.m_pts[tetF[h][2]]);
+ if (v > maxVol) {
+ h1 = h;
+ tetrahedron1.m_pts[0] = pts[a];
+ tetrahedron1.m_pts[1] = tetrahedron0.m_pts[tetF[h][0]];
+ tetrahedron1.m_pts[2] = tetrahedron0.m_pts[tetF[h][1]];
+ tetrahedron1.m_pts[3] = tetrahedron0.m_pts[tetF[h][2]];
+ maxVol = v;
+ }
+ }
+ if (h1 == -1 && Add(tetrahedron1)) {
+ ++m_numTetrahedraOnSurface;
+ }
+ }
+ else if (nPts == 6) {
+
+ const int32_t tet[15][4] = { { 2, 3, 4, 5 }, { 1, 3, 4, 5 }, { 1, 2, 4, 5 }, { 1, 2, 3, 5 }, { 1, 2, 3, 4 },
+ { 0, 3, 4, 5 }, { 0, 2, 4, 5 }, { 0, 2, 3, 5 }, { 0, 2, 3, 4 }, { 0, 1, 4, 5 },
+ { 0, 1, 3, 5 }, { 0, 1, 3, 4 }, { 0, 1, 2, 5 }, { 0, 1, 2, 4 }, { 0, 1, 2, 3 } };
+ const int32_t rem[15][2] = { { 0, 1 }, { 0, 2 }, { 0, 3 }, { 0, 4 }, { 0, 5 },
+ { 1, 2 }, { 1, 3 }, { 1, 4 }, { 1, 5 }, { 2, 3 },
+ { 2, 4 }, { 2, 5 }, { 3, 4 }, { 3, 5 }, { 4, 5 } };
+ double maxVol = 0.0;
+ int32_t h0 = -1;
+ Tetrahedron tetrahedron0;
+ tetrahedron0.m_data = PRIMITIVE_ON_SURFACE;
+ for (int32_t h = 0; h < 15; ++h) {
+ double v = ComputeVolume4(pts[tet[h][0]], pts[tet[h][1]], pts[tet[h][2]], pts[tet[h][3]]);
+ if (v > maxVol) {
+ h0 = h;
+ tetrahedron0.m_pts[0] = pts[tet[h][0]];
+ tetrahedron0.m_pts[1] = pts[tet[h][1]];
+ tetrahedron0.m_pts[2] = pts[tet[h][2]];
+ tetrahedron0.m_pts[3] = pts[tet[h][3]];
+ maxVol = v;
+ }
+ else if (-v > maxVol) {
+ h0 = h;
+ tetrahedron0.m_pts[0] = pts[tet[h][1]];
+ tetrahedron0.m_pts[1] = pts[tet[h][0]];
+ tetrahedron0.m_pts[2] = pts[tet[h][2]];
+ tetrahedron0.m_pts[3] = pts[tet[h][3]];
+ maxVol = -v;
+ }
+ }
+ if (h0 == -1)
+ return;
+ if (Add(tetrahedron0)) {
+ ++m_numTetrahedraOnSurface;
+ }
+ else {
+ return;
+ }
+
+ int32_t a0 = rem[h0][0];
+ int32_t a1 = rem[h0][1];
+ int32_t h1 = -1;
+ Tetrahedron tetrahedron1;
+ tetrahedron1.m_data = PRIMITIVE_ON_SURFACE;
+ maxVol = 0.0;
+ for (int32_t h = 0; h < 4; ++h) {
+ double v = ComputeVolume4(pts[a0], tetrahedron0.m_pts[tetF[h][0]], tetrahedron0.m_pts[tetF[h][1]], tetrahedron0.m_pts[tetF[h][2]]);
+ if (v > maxVol) {
+ h1 = h;
+ tetrahedron1.m_pts[0] = pts[a0];
+ tetrahedron1.m_pts[1] = tetrahedron0.m_pts[tetF[h][0]];
+ tetrahedron1.m_pts[2] = tetrahedron0.m_pts[tetF[h][1]];
+ tetrahedron1.m_pts[3] = tetrahedron0.m_pts[tetF[h][2]];
+ maxVol = v;
+ }
+ }
+ if (h1 != -1 && Add(tetrahedron1)) {
+ ++m_numTetrahedraOnSurface;
+ }
+ else {
+ h1 = -1;
+ }
+ maxVol = 0.0;
+ int32_t h2 = -1;
+ Tetrahedron tetrahedron2;
+ tetrahedron2.m_data = PRIMITIVE_ON_SURFACE;
+ for (int32_t h = 0; h < 4; ++h) {
+ double v = ComputeVolume4(pts[a0], tetrahedron0.m_pts[tetF[h][0]], tetrahedron0.m_pts[tetF[h][1]], tetrahedron0.m_pts[tetF[h][2]]);
+ if (h == h1)
+ continue;
+ if (v > maxVol) {
+ h2 = h;
+ tetrahedron2.m_pts[0] = pts[a1];
+ tetrahedron2.m_pts[1] = tetrahedron0.m_pts[tetF[h][0]];
+ tetrahedron2.m_pts[2] = tetrahedron0.m_pts[tetF[h][1]];
+ tetrahedron2.m_pts[3] = tetrahedron0.m_pts[tetF[h][2]];
+ maxVol = v;
+ }
+ }
+ if (h1 != -1) {
+ for (int32_t h = 0; h < 4; ++h) {
+ double v = ComputeVolume4(pts[a1], tetrahedron1.m_pts[tetF[h][0]], tetrahedron1.m_pts[tetF[h][1]], tetrahedron1.m_pts[tetF[h][2]]);
+ if (h == 1)
+ continue;
+ if (v > maxVol) {
+ h2 = h;
+ tetrahedron2.m_pts[0] = pts[a1];
+ tetrahedron2.m_pts[1] = tetrahedron1.m_pts[tetF[h][0]];
+ tetrahedron2.m_pts[2] = tetrahedron1.m_pts[tetF[h][1]];
+ tetrahedron2.m_pts[3] = tetrahedron1.m_pts[tetF[h][2]];
+ maxVol = v;
+ }
+ }
+ }
+ if (h2 != -1 && Add(tetrahedron2)) {
+ ++m_numTetrahedraOnSurface;
+ }
+ }
+ else {
+ assert(0);
+ }
+}
+
+void TetrahedronSet::Intersect(const Plane& plane,
+ SArray<Vec3<double> >* const positivePts,
+ SArray<Vec3<double> >* const negativePts,
+ const size_t sampling) const
+{
+ const size_t nTetrahedra = m_tetrahedra.Size();
+ if (nTetrahedra == 0)
+ return;
+}
+void TetrahedronSet::ComputeExteriorPoints(const Plane& plane,
+ const Mesh& mesh,
+ SArray<Vec3<double> >* const exteriorPts) const
+{
+}
+void TetrahedronSet::ComputeClippedVolumes(const Plane& plane,
+ double& positiveVolume,
+ double& negativeVolume) const
+{
+ const size_t nTetrahedra = m_tetrahedra.Size();
+ if (nTetrahedra == 0)
+ return;
+}
+
+void TetrahedronSet::SelectOnSurface(PrimitiveSet* const onSurfP) const
+{
+ TetrahedronSet* const onSurf = (TetrahedronSet*)onSurfP;
+ const size_t nTetrahedra = m_tetrahedra.Size();
+ if (nTetrahedra == 0)
+ return;
+ onSurf->m_tetrahedra.Resize(0);
+ onSurf->m_scale = m_scale;
+ onSurf->m_numTetrahedraOnSurface = 0;
+ onSurf->m_numTetrahedraInsideSurface = 0;
+ onSurf->m_barycenter = m_barycenter;
+ onSurf->m_minBB = m_minBB;
+ onSurf->m_maxBB = m_maxBB;
+ for (int32_t i = 0; i < 3; ++i) {
+ for (int32_t j = 0; j < 3; ++j) {
+ onSurf->m_Q[i][j] = m_Q[i][j];
+ onSurf->m_D[i][j] = m_D[i][j];
+ }
+ }
+ Tetrahedron tetrahedron;
+ for (size_t v = 0; v < nTetrahedra; ++v) {
+ tetrahedron = m_tetrahedra[v];
+ if (tetrahedron.m_data == PRIMITIVE_ON_SURFACE) {
+ onSurf->m_tetrahedra.PushBack(tetrahedron);
+ ++onSurf->m_numTetrahedraOnSurface;
+ }
+ }
+}
+void TetrahedronSet::Clip(const Plane& plane,
+ PrimitiveSet* const positivePartP,
+ PrimitiveSet* const negativePartP) const
+{
+ TetrahedronSet* const positivePart = (TetrahedronSet*)positivePartP;
+ TetrahedronSet* const negativePart = (TetrahedronSet*)negativePartP;
+ const size_t nTetrahedra = m_tetrahedra.Size();
+ if (nTetrahedra == 0)
+ return;
+ positivePart->m_tetrahedra.Resize(0);
+ negativePart->m_tetrahedra.Resize(0);
+ positivePart->m_tetrahedra.Allocate(nTetrahedra);
+ negativePart->m_tetrahedra.Allocate(nTetrahedra);
+ negativePart->m_scale = positivePart->m_scale = m_scale;
+ negativePart->m_numTetrahedraOnSurface = positivePart->m_numTetrahedraOnSurface = 0;
+ negativePart->m_numTetrahedraInsideSurface = positivePart->m_numTetrahedraInsideSurface = 0;
+ negativePart->m_barycenter = m_barycenter;
+ positivePart->m_barycenter = m_barycenter;
+ negativePart->m_minBB = m_minBB;
+ positivePart->m_minBB = m_minBB;
+ negativePart->m_maxBB = m_maxBB;
+ positivePart->m_maxBB = m_maxBB;
+ for (int32_t i = 0; i < 3; ++i) {
+ for (int32_t j = 0; j < 3; ++j) {
+ negativePart->m_Q[i][j] = positivePart->m_Q[i][j] = m_Q[i][j];
+ negativePart->m_D[i][j] = positivePart->m_D[i][j] = m_D[i][j];
+ }
+ }
+
+ Tetrahedron tetrahedron;
+ double delta, alpha;
+ int32_t sign[4];
+ int32_t npos, nneg;
+ Vec3<double> posPts[10];
+ Vec3<double> negPts[10];
+ Vec3<double> P0, P1, M;
+ const Vec3<double> n(plane.m_a, plane.m_b, plane.m_c);
+ const int32_t edges[6][2] = { { 0, 1 }, { 0, 2 }, { 0, 3 }, { 1, 2 }, { 1, 3 }, { 2, 3 } };
+ double dist;
+ for (size_t v = 0; v < nTetrahedra; ++v) {
+ tetrahedron = m_tetrahedra[v];
+ npos = nneg = 0;
+ for (int32_t i = 0; i < 4; ++i) {
+ dist = plane.m_a * tetrahedron.m_pts[i][0] + plane.m_b * tetrahedron.m_pts[i][1] + plane.m_c * tetrahedron.m_pts[i][2] + plane.m_d;
+ if (dist > 0.0) {
+ sign[i] = 1;
+ posPts[npos] = tetrahedron.m_pts[i];
+ ++npos;
+ }
+ else {
+ sign[i] = -1;
+ negPts[nneg] = tetrahedron.m_pts[i];
+ ++nneg;
+ }
+ }
+
+ if (npos == 4) {
+ positivePart->Add(tetrahedron);
+ if (tetrahedron.m_data == PRIMITIVE_ON_SURFACE) {
+ ++positivePart->m_numTetrahedraOnSurface;
+ }
+ else {
+ ++positivePart->m_numTetrahedraInsideSurface;
+ }
+ }
+ else if (nneg == 4) {
+ negativePart->Add(tetrahedron);
+ if (tetrahedron.m_data == PRIMITIVE_ON_SURFACE) {
+ ++negativePart->m_numTetrahedraOnSurface;
+ }
+ else {
+ ++negativePart->m_numTetrahedraInsideSurface;
+ }
+ }
+ else {
+ int32_t nnew = 0;
+ for (int32_t j = 0; j < 6; ++j) {
+ if (sign[edges[j][0]] * sign[edges[j][1]] == -1) {
+ P0 = tetrahedron.m_pts[edges[j][0]];
+ P1 = tetrahedron.m_pts[edges[j][1]];
+ delta = (P0 - P1) * n;
+ alpha = -(plane.m_d + (n * P1)) / delta;
+ assert(alpha >= 0.0 && alpha <= 1.0);
+ M = alpha * P0 + (1 - alpha) * P1;
+ for (int32_t xx = 0; xx < 3; ++xx) {
+ assert(M[xx] + EPS >= m_minBB[xx]);
+ assert(M[xx] <= m_maxBB[xx] + EPS);
+ }
+ posPts[npos++] = M;
+ negPts[nneg++] = M;
+ ++nnew;
+ }
+ }
+ negativePart->AddClippedTetrahedra(negPts, nneg);
+ positivePart->AddClippedTetrahedra(posPts, npos);
+ }
+ }
+}
+void TetrahedronSet::Convert(Mesh& mesh, const VOXEL_VALUE value) const
+{
+ const size_t nTetrahedra = m_tetrahedra.Size();
+ if (nTetrahedra == 0)
+ return;
+ for (size_t v = 0; v < nTetrahedra; ++v) {
+ const Tetrahedron& tetrahedron = m_tetrahedra[v];
+ if (tetrahedron.m_data == value) {
+ int32_t s = (int32_t)mesh.GetNPoints();
+ mesh.AddPoint(tetrahedron.m_pts[0]);
+ mesh.AddPoint(tetrahedron.m_pts[1]);
+ mesh.AddPoint(tetrahedron.m_pts[2]);
+ mesh.AddPoint(tetrahedron.m_pts[3]);
+ mesh.AddTriangle(Vec3<int32_t>(s + 0, s + 1, s + 2));
+ mesh.AddTriangle(Vec3<int32_t>(s + 2, s + 1, s + 3));
+ mesh.AddTriangle(Vec3<int32_t>(s + 3, s + 1, s + 0));
+ mesh.AddTriangle(Vec3<int32_t>(s + 3, s + 0, s + 2));
+ }
+ }
+}
+const double TetrahedronSet::ComputeVolume() const
+{
+ const size_t nTetrahedra = m_tetrahedra.Size();
+ if (nTetrahedra == 0)
+ return 0.0;
+ double volume = 0.0;
+ for (size_t v = 0; v < nTetrahedra; ++v) {
+ const Tetrahedron& tetrahedron = m_tetrahedra[v];
+ volume += fabs(ComputeVolume4(tetrahedron.m_pts[0], tetrahedron.m_pts[1], tetrahedron.m_pts[2], tetrahedron.m_pts[3]));
+ }
+ return volume / 6.0;
+}
+const double TetrahedronSet::ComputeMaxVolumeError() const
+{
+ const size_t nTetrahedra = m_tetrahedra.Size();
+ if (nTetrahedra == 0)
+ return 0.0;
+ double volume = 0.0;
+ for (size_t v = 0; v < nTetrahedra; ++v) {
+ const Tetrahedron& tetrahedron = m_tetrahedra[v];
+ if (tetrahedron.m_data == PRIMITIVE_ON_SURFACE) {
+ volume += fabs(ComputeVolume4(tetrahedron.m_pts[0], tetrahedron.m_pts[1], tetrahedron.m_pts[2], tetrahedron.m_pts[3]));
+ }
+ }
+ return volume / 6.0;
+}
+void TetrahedronSet::RevertAlignToPrincipalAxes()
+{
+ const size_t nTetrahedra = m_tetrahedra.Size();
+ if (nTetrahedra == 0)
+ return;
+ double x, y, z;
+ for (size_t v = 0; v < nTetrahedra; ++v) {
+ Tetrahedron& tetrahedron = m_tetrahedra[v];
+ for (int32_t i = 0; i < 4; ++i) {
+ x = tetrahedron.m_pts[i][0] - m_barycenter[0];
+ y = tetrahedron.m_pts[i][1] - m_barycenter[1];
+ z = tetrahedron.m_pts[i][2] - m_barycenter[2];
+ tetrahedron.m_pts[i][0] = m_Q[0][0] * x + m_Q[0][1] * y + m_Q[0][2] * z + m_barycenter[0];
+ tetrahedron.m_pts[i][1] = m_Q[1][0] * x + m_Q[1][1] * y + m_Q[1][2] * z + m_barycenter[1];
+ tetrahedron.m_pts[i][2] = m_Q[2][0] * x + m_Q[2][1] * y + m_Q[2][2] * z + m_barycenter[2];
+ }
+ }
+ ComputeBB();
+}
+void TetrahedronSet::ComputePrincipalAxes()
+{
+ const size_t nTetrahedra = m_tetrahedra.Size();
+ if (nTetrahedra == 0)
+ return;
+ double covMat[3][3] = { { 0.0, 0.0, 0.0 },
+ { 0.0, 0.0, 0.0 },
+ { 0.0, 0.0, 0.0 } };
+ double x, y, z;
+ for (size_t v = 0; v < nTetrahedra; ++v) {
+ Tetrahedron& tetrahedron = m_tetrahedra[v];
+ for (int32_t i = 0; i < 4; ++i) {
+ x = tetrahedron.m_pts[i][0] - m_barycenter[0];
+ y = tetrahedron.m_pts[i][1] - m_barycenter[1];
+ z = tetrahedron.m_pts[i][2] - m_barycenter[2];
+ covMat[0][0] += x * x;
+ covMat[1][1] += y * y;
+ covMat[2][2] += z * z;
+ covMat[0][1] += x * y;
+ covMat[0][2] += x * z;
+ covMat[1][2] += y * z;
+ }
+ }
+ double n = nTetrahedra * 4.0;
+ covMat[0][0] /= n;
+ covMat[1][1] /= n;
+ covMat[2][2] /= n;
+ covMat[0][1] /= n;
+ covMat[0][2] /= n;
+ covMat[1][2] /= n;
+ covMat[1][0] = covMat[0][1];
+ covMat[2][0] = covMat[0][2];
+ covMat[2][1] = covMat[1][2];
+ Diagonalize(covMat, m_Q, m_D);
+}
+void TetrahedronSet::AlignToPrincipalAxes()
+{
+ const size_t nTetrahedra = m_tetrahedra.Size();
+ if (nTetrahedra == 0)
+ return;
+ double x, y, z;
+ for (size_t v = 0; v < nTetrahedra; ++v) {
+ Tetrahedron& tetrahedron = m_tetrahedra[v];
+ for (int32_t i = 0; i < 4; ++i) {
+ x = tetrahedron.m_pts[i][0] - m_barycenter[0];
+ y = tetrahedron.m_pts[i][1] - m_barycenter[1];
+ z = tetrahedron.m_pts[i][2] - m_barycenter[2];
+ tetrahedron.m_pts[i][0] = m_Q[0][0] * x + m_Q[1][0] * y + m_Q[2][0] * z + m_barycenter[0];
+ tetrahedron.m_pts[i][1] = m_Q[0][1] * x + m_Q[1][1] * y + m_Q[2][1] * z + m_barycenter[1];
+ tetrahedron.m_pts[i][2] = m_Q[0][2] * x + m_Q[1][2] * y + m_Q[2][2] * z + m_barycenter[2];
+ }
+ }
+ ComputeBB();
+}
+}
diff --git a/thirdparty/thekla_atlas/LICENSE b/thirdparty/xatlas/LICENSE
index 164e7d3a2b..94d0c60485 100644
--- a/thirdparty/thekla_atlas/LICENSE
+++ b/thirdparty/xatlas/LICENSE
@@ -1,5 +1,11 @@
-Copyright (c) 2013 Thekla, Inc
+xatlas
+https://github.com/jpcy/xatlas
+Copyright (c) 2018 Jonathan Young
+thekla_atlas
+https://github.com/Thekla/thekla_atlas
+Copyright (c) 2013 Thekla, Inc
+Copyright NVIDIA Corporation 2006 -- Ignacio Castano <icastano@nvidia.com>
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:
diff --git a/thirdparty/xatlas/avoid-failing-on-bad-geometry.patch b/thirdparty/xatlas/avoid-failing-on-bad-geometry.patch
new file mode 100644
index 0000000000..a28cd9f82b
--- /dev/null
+++ b/thirdparty/xatlas/avoid-failing-on-bad-geometry.patch
@@ -0,0 +1,157 @@
+diff --git a/thirdparty/xatlas/xatlas.cpp b/thirdparty/xatlas/xatlas.cpp
+index df5ef94db..eb0824a51 100644
+--- a/thirdparty/xatlas/xatlas.cpp
++++ b/thirdparty/xatlas/xatlas.cpp
+@@ -1276,6 +1276,9 @@ class Vertex
+ {
+ public:
+ uint32_t id;
++ // -- GODOT start --
++ uint32_t original_id;
++ // -- GODOT end --
+ Edge *edge;
+ Vertex *next;
+ Vertex *prev;
+@@ -1283,7 +1286,10 @@ public:
+ Vector3 nor;
+ Vector2 tex;
+
+- Vertex(uint32_t id) : id(id), edge(NULL), pos(0.0f), nor(0.0f), tex(0.0f)
++ // -- GODOT start --
++ //Vertex(uint32_t id) : id(id), edge(NULL), pos(0.0f), nor(0.0f), tex(0.0f)
++ Vertex(uint32_t id) : id(id), original_id(id), edge(NULL), pos(0.0f), nor(0.0f), tex(0.0f)
++ // -- GODOT end --
+ {
+ next = this;
+ prev = this;
+@@ -1934,6 +1940,64 @@ public:
+ return f;
+ }
+
++ // -- GODOT start --
++ Face *addUniqueFace(uint32_t v0, uint32_t v1, uint32_t v2) {
++
++ int base_vertex = m_vertexArray.size();
++
++ uint32_t ids[3] = { v0, v1, v2 };
++
++ Vector3 base[3] = {
++ m_vertexArray[v0]->pos,
++ m_vertexArray[v1]->pos,
++ m_vertexArray[v2]->pos,
++ };
++
++ //make sure its not a degenerate
++ bool degenerate = distanceSquared(base[0], base[1]) < NV_EPSILON || distanceSquared(base[0], base[2]) < NV_EPSILON || distanceSquared(base[1], base[2]) < NV_EPSILON;
++ xaDebugAssert(!degenerate);
++
++ float min_x = 0;
++
++ for (int i = 0; i < 3; i++) {
++ if (i == 0 || m_vertexArray[v0]->pos.x < min_x) {
++ min_x = m_vertexArray[v0]->pos.x;
++ }
++ }
++
++ float max_x = 0;
++
++ for (int j = 0; j < m_vertexArray.size(); j++) {
++ if (j == 0 || m_vertexArray[j]->pos.x > max_x) { //vertex already exists
++ max_x = m_vertexArray[j]->pos.x;
++ }
++ }
++
++ //separate from everything else, in x axis
++ for (int i = 0; i < 3; i++) {
++
++ base[i].x -= min_x;
++ base[i].x += max_x + 10.0;
++ }
++
++ for (int i = 0; i < 3; i++) {
++ Vertex *v = new Vertex(m_vertexArray.size());
++ v->pos = base[i];
++ v->nor = m_vertexArray[ids[i]]->nor,
++ v->tex = m_vertexArray[ids[i]]->tex,
++
++ v->original_id = ids[i];
++ m_vertexArray.push_back(v);
++ }
++
++ uint32_t indexArray[3];
++ indexArray[0] = base_vertex + 0;
++ indexArray[1] = base_vertex + 1;
++ indexArray[2] = base_vertex + 2;
++ return addFace(indexArray, 3, 0, 3);
++ }
++ // -- GODOT end --
++
+ // These functions disconnect the given element from the mesh and delete it.
+
+ // @@ We must always disconnect edge pairs simultaneously.
+@@ -2915,6 +2979,14 @@ Mesh *triangulate(const Mesh *inputMesh)
+ Vector2 p0 = polygonPoints[i0];
+ Vector2 p1 = polygonPoints[i1];
+ Vector2 p2 = polygonPoints[i2];
++
++ // -- GODOT start --
++ bool degenerate = distance(p0, p1) < NV_EPSILON || distance(p0, p2) < NV_EPSILON || distance(p1, p2) < NV_EPSILON;
++ if (degenerate) {
++ continue;
++ }
++ // -- GODOT end --
++
+ float d = clamp(dot(p0 - p1, p2 - p1) / (length(p0 - p1) * length(p2 - p1)), -1.0f, 1.0f);
+ float angle = acosf(d);
+ float area = triangleArea(p0, p1, p2);
+@@ -2938,6 +3010,11 @@ Mesh *triangulate(const Mesh *inputMesh)
+ }
+ }
+ }
++ // -- GODOT start --
++ if (!bestIsValid)
++ break;
++ // -- GODOT end --
++
+ xaDebugAssert(minAngle <= 2 * PI);
+ // Clip best ear:
+ uint32_t i0 = (bestEar + size - 1) % size;
+@@ -5606,7 +5683,10 @@ public:
+ }
+ if (chartMeshIndices[vertex->id] == ~0) {
+ chartMeshIndices[vertex->id] = m_chartMesh->vertexCount();
+- m_chartToOriginalMap.push_back(vertex->id);
++ // -- GODOT start --
++ //m_chartToOriginalMap.push_back(vertex->id);
++ m_chartToOriginalMap.push_back(vertex->original_id);
++ // -- GODOT end --
+ m_chartToUnifiedMap.push_back(unifiedMeshIndices[unifiedVertex->id]);
+ halfedge::Vertex *v = m_chartMesh->addVertex(vertex->pos);
+ v->nor = vertex->nor;
+@@ -5699,7 +5779,10 @@ public:
+ const halfedge::Vertex *vertex = it.current()->vertex;
+ if (chartMeshIndices[vertex->id] == ~0) {
+ chartMeshIndices[vertex->id] = m_chartMesh->vertexCount();
+- m_chartToOriginalMap.push_back(vertex->id);
++ // -- GODOT start --
++ //m_chartToOriginalMap.push_back(vertex->id);
++ m_chartToOriginalMap.push_back(vertex->original_id);
++ // -- GODOT end --
+ halfedge::Vertex *v = m_chartMesh->addVertex(vertex->pos);
+ v->nor = vertex->nor;
+ v->tex = vertex->tex; // @@ Not necessary.
+@@ -7573,6 +7656,14 @@ AddMeshError AddMesh(Atlas *atlas, const InputMesh &mesh, bool useColocalVertice
+ }
+ }
+ internal::halfedge::Face *face = heMesh->addFace(tri[0], tri[1], tri[2]);
++
++ // -- GODOT start --
++ if (!face && heMesh->errorCode == internal::halfedge::Mesh::ErrorCode::AlreadyAddedEdge) {
++ //there is still hope for this, no reason to not add, at least add as separate
++ face = heMesh->addUniqueFace(tri[0], tri[1], tri[2]);
++ }
++ // -- GODOT end --
++
+ if (!face) {
+ if (heMesh->errorCode == internal::halfedge::Mesh::ErrorCode::AlreadyAddedEdge)
+ error.code = AddMeshErrorCode::AlreadyAddedEdge;
diff --git a/thirdparty/xatlas/build-fix-limits.patch b/thirdparty/xatlas/build-fix-limits.patch
new file mode 100644
index 0000000000..00d07371c0
--- /dev/null
+++ b/thirdparty/xatlas/build-fix-limits.patch
@@ -0,0 +1,14 @@
+diff --git a/thirdparty/xatlas/xatlas.h b/thirdparty/xatlas/xatlas.h
+index 7e556c6c3..dbf8ca08c 100644
+--- a/thirdparty/xatlas/xatlas.h
++++ b/thirdparty/xatlas/xatlas.h
+@@ -3,6 +3,9 @@
+ #ifndef XATLAS_H
+ #define XATLAS_H
+ #include <float.h> // FLT_MAX
++// -- GODOT start --
++#include <limits.h> // INT_MAX, UINT_MAX
++// -- GODOT end --
+
+ namespace xatlas {
+
diff --git a/thirdparty/xatlas/xatlas.cpp b/thirdparty/xatlas/xatlas.cpp
index f6a9ce64dc..2cc2905eee 100644
--- a/thirdparty/xatlas/xatlas.cpp
+++ b/thirdparty/xatlas/xatlas.cpp
@@ -1,5 +1,9 @@
// This code is in the public domain -- castanyo@yahoo.es
-#include "xatlas.h"
+#include <algorithm>
+#include <cmath>
+#include <memory>
+#include <unordered_map>
+#include <vector>
#include <assert.h>
#include <float.h>
#include <math.h>
@@ -8,29 +12,19 @@
#include <stdio.h>
#include <string.h>
#include <time.h>
-#include <algorithm>
-#include <cmath>
-#include <memory>
-#include <unordered_map>
-#include <vector>
+#include "xatlas.h"
#undef min
#undef max
#ifndef xaAssert
-#define xaAssert(exp) \
- if (!(exp)) { \
- xaPrint("%s %s %s\n", #exp, __FILE__, __LINE__); \
- }
+#define xaAssert(exp) if (!(exp)) { xaPrint("%s %s %s\n", #exp, __FILE__, __LINE__); }
#endif
#ifndef xaDebugAssert
#define xaDebugAssert(exp) assert(exp)
#endif
#ifndef xaPrint
-#define xaPrint(...) \
- if (xatlas::internal::s_print) { \
- xatlas::internal::s_print(__VA_ARGS__); \
- }
+#define xaPrint(...) if (xatlas::internal::s_print) { xatlas::internal::s_print(__VA_ARGS__); }
#endif
#ifdef _MSC_VER
@@ -43,87 +37,101 @@
#define NV_FORCEINLINE __forceinline
#else
#define restrict __restrict__
-#define NV_FORCEINLINE __attribute__((always_inline)) inline
+#define NV_FORCEINLINE __attribute__((always_inline)) inline
#endif
-#define NV_UINT32_MAX 0xffffffff
-#define NV_FLOAT_MAX 3.402823466e+38F
+#define NV_UINT32_MAX 0xffffffff
+#define NV_FLOAT_MAX 3.402823466e+38F
#ifndef PI
-#define PI float(3.1415926535897932384626433833)
+#define PI float(3.1415926535897932384626433833)
#endif
-#define NV_EPSILON (0.0001f)
-#define NV_NORMAL_EPSILON (0.001f)
+#define NV_EPSILON (0.0001f)
+#define NV_NORMAL_EPSILON (0.001f)
namespace xatlas {
namespace internal {
static PrintFunc s_print = NULL;
-static int align(int x, int a) {
+static int align(int x, int a)
+{
return (x + a - 1) & ~(a - 1);
}
-static bool isAligned(int x, int a) {
+static bool isAligned(int x, int a)
+{
return (x & (a - 1)) == 0;
}
/// Return the maximum of the three arguments.
template <typename T>
-static T max3(const T &a, const T &b, const T &c) {
+static T max3(const T &a, const T &b, const T &c)
+{
return std::max(a, std::max(b, c));
}
/// Return the maximum of the three arguments.
template <typename T>
-static T min3(const T &a, const T &b, const T &c) {
+static T min3(const T &a, const T &b, const T &c)
+{
return std::min(a, std::min(b, c));
}
/// Clamp between two values.
template <typename T>
-static T clamp(const T &x, const T &a, const T &b) {
+static T clamp(const T &x, const T &a, const T &b)
+{
return std::min(std::max(x, a), b);
}
-static float saturate(float f) {
+static float saturate(float f)
+{
return clamp(f, 0.0f, 1.0f);
}
// Robust floating point comparisons:
// http://realtimecollisiondetection.net/blog/?p=89
-static bool equal(const float f0, const float f1, const float epsilon = NV_EPSILON) {
+static bool equal(const float f0, const float f1, const float epsilon = NV_EPSILON)
+{
//return fabs(f0-f1) <= epsilon;
return fabs(f0 - f1) <= epsilon * max3(1.0f, fabsf(f0), fabsf(f1));
}
-NV_FORCEINLINE static int ftoi_floor(float val) {
+NV_FORCEINLINE static int ftoi_floor(float val)
+{
return (int)val;
}
-NV_FORCEINLINE static int ftoi_ceil(float val) {
+NV_FORCEINLINE static int ftoi_ceil(float val)
+{
return (int)ceilf(val);
}
-NV_FORCEINLINE static int ftoi_round(float f) {
+NV_FORCEINLINE static int ftoi_round(float f)
+{
return int(floorf(f + 0.5f));
}
-static bool isZero(const float f, const float epsilon = NV_EPSILON) {
+static bool isZero(const float f, const float epsilon = NV_EPSILON)
+{
return fabs(f) <= epsilon;
}
-static float lerp(float f0, float f1, float t) {
+static float lerp(float f0, float f1, float t)
+{
const float s = 1.0f - t;
return f0 * s + f1 * t;
}
-static float square(float f) {
+static float square(float f)
+{
return f * f;
}
-static int square(int i) {
+static int square(int i)
+{
return i * i;
}
@@ -133,8 +141,9 @@ static int square(int i) {
* @note isPowerOfTwo(x) == true -> nextPowerOfTwo(x) == x
* @note nextPowerOfTwo(x) = 2 << log2(x-1)
*/
-static uint32_t nextPowerOfTwo(uint32_t x) {
- xaDebugAssert(x != 0);
+static uint32_t nextPowerOfTwo(uint32_t x)
+{
+ xaDebugAssert( x != 0 );
// On modern CPUs this is supposed to be as fast as using the bsr instruction.
x--;
x |= x >> 1;
@@ -145,7 +154,8 @@ static uint32_t nextPowerOfTwo(uint32_t x) {
return x + 1;
}
-static uint64_t nextPowerOfTwo(uint64_t x) {
+static uint64_t nextPowerOfTwo(uint64_t x)
+{
xaDebugAssert(x != 0);
uint32_t p = 1;
while (x > p) {
@@ -154,17 +164,19 @@ static uint64_t nextPowerOfTwo(uint64_t x) {
return p;
}
-static uint32_t sdbmHash(const void *data_in, uint32_t size, uint32_t h = 5381) {
- const uint8_t *data = (const uint8_t *)data_in;
+static uint32_t sdbmHash(const void *data_in, uint32_t size, uint32_t h = 5381)
+{
+ const uint8_t *data = (const uint8_t *) data_in;
uint32_t i = 0;
while (i < size) {
- h = (h << 16) + (h << 6) - h + (uint32_t)data[i++];
+ h = (h << 16) + (h << 6) - h + (uint32_t ) data[i++];
}
return h;
}
// Note that this hash does not handle NaN properly.
-static uint32_t sdbmFloatHash(const float *f, uint32_t count, uint32_t h = 5381) {
+static uint32_t sdbmFloatHash(const float *f, uint32_t count, uint32_t h = 5381)
+{
for (uint32_t i = 0; i < count; i++) {
union {
float f;
@@ -177,85 +189,93 @@ static uint32_t sdbmFloatHash(const float *f, uint32_t count, uint32_t h = 5381)
}
template <typename T>
-static uint32_t hash(const T &t, uint32_t h = 5381) {
+static uint32_t hash(const T &t, uint32_t h = 5381)
+{
return sdbmHash(&t, sizeof(T), h);
}
-static uint32_t hash(const float &f, uint32_t h) {
+static uint32_t hash(const float &f, uint32_t h)
+{
return sdbmFloatHash(&f, 1, h);
}
// Functors for hash table:
-template <typename Key>
-struct Hash {
+template <typename Key> struct Hash
+{
uint32_t operator()(const Key &k) const { return hash(k); }
};
-template <typename Key>
-struct Equal {
+template <typename Key> struct Equal
+{
bool operator()(const Key &k0, const Key &k1) const { return k0 == k1; }
};
-class Vector2 {
+class Vector2
+{
public:
typedef Vector2 const &Arg;
Vector2() {}
- explicit Vector2(float f) :
- x(f),
- y(f) {}
- Vector2(float x, float y) :
- x(x),
- y(y) {}
- Vector2(Vector2::Arg v) :
- x(v.x),
- y(v.y) {}
-
- const Vector2 &operator=(Vector2::Arg v) {
+ explicit Vector2(float f) : x(f), y(f) {}
+ Vector2(float x, float y): x(x), y(y) {}
+ Vector2(Vector2::Arg v) : x(v.x), y(v.y) {}
+
+ const Vector2 &operator=(Vector2::Arg v)
+ {
x = v.x;
y = v.y;
- return *this;
+ return
+ *this;
}
const float *ptr() const { return &x; }
- void set(float _x, float _y) {
+ void set(float _x, float _y)
+ {
x = _x;
y = _y;
}
- Vector2 operator-() const {
+ Vector2 operator-() const
+ {
return Vector2(-x, -y);
}
- void operator+=(Vector2::Arg v) {
+ void operator+=(Vector2::Arg v)
+ {
x += v.x;
y += v.y;
}
- void operator-=(Vector2::Arg v) {
+ void operator-=(Vector2::Arg v)
+ {
x -= v.x;
y -= v.y;
}
- void operator*=(float s) {
+ void operator*=(float s)
+ {
x *= s;
y *= s;
}
- void operator*=(Vector2::Arg v) {
+ void operator*=(Vector2::Arg v)
+ {
x *= v.x;
y *= v.y;
}
- friend bool operator==(Vector2::Arg a, Vector2::Arg b) {
+ friend bool operator==(Vector2::Arg a, Vector2::Arg b)
+ {
return a.x == b.x && a.y == b.y;
}
- friend bool operator!=(Vector2::Arg a, Vector2::Arg b) {
+ friend bool operator!=(Vector2::Arg a, Vector2::Arg b)
+ {
return a.x != b.x || a.y != b.y;
}
- union {
+ union
+ {
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4201)
@@ -272,52 +292,64 @@ public:
};
};
-Vector2 operator+(Vector2::Arg a, Vector2::Arg b) {
+Vector2 operator+(Vector2::Arg a, Vector2::Arg b)
+{
return Vector2(a.x + b.x, a.y + b.y);
}
-Vector2 operator-(Vector2::Arg a, Vector2::Arg b) {
+Vector2 operator-(Vector2::Arg a, Vector2::Arg b)
+{
return Vector2(a.x - b.x, a.y - b.y);
}
-Vector2 operator*(Vector2::Arg v, float s) {
+Vector2 operator*(Vector2::Arg v, float s)
+{
return Vector2(v.x * s, v.y * s);
}
-Vector2 operator*(Vector2::Arg v1, Vector2::Arg v2) {
+Vector2 operator*(Vector2::Arg v1, Vector2::Arg v2)
+{
return Vector2(v1.x * v2.x, v1.y * v2.y);
}
-Vector2 operator/(Vector2::Arg v, float s) {
+Vector2 operator/(Vector2::Arg v, float s)
+{
return Vector2(v.x / s, v.y / s);
}
-Vector2 lerp(Vector2::Arg v1, Vector2::Arg v2, float t) {
+Vector2 lerp(Vector2::Arg v1, Vector2::Arg v2, float t)
+{
const float s = 1.0f - t;
return Vector2(v1.x * s + t * v2.x, v1.y * s + t * v2.y);
}
-float dot(Vector2::Arg a, Vector2::Arg b) {
+float dot(Vector2::Arg a, Vector2::Arg b)
+{
return a.x * b.x + a.y * b.y;
}
-float lengthSquared(Vector2::Arg v) {
+float lengthSquared(Vector2::Arg v)
+{
return v.x * v.x + v.y * v.y;
}
-float length(Vector2::Arg v) {
+float length(Vector2::Arg v)
+{
return sqrtf(lengthSquared(v));
}
-float distance(Vector2::Arg a, Vector2::Arg b) {
+float distance(Vector2::Arg a, Vector2::Arg b)
+{
return length(a - b);
}
-bool isNormalized(Vector2::Arg v, float epsilon = NV_NORMAL_EPSILON) {
+bool isNormalized(Vector2::Arg v, float epsilon = NV_NORMAL_EPSILON)
+{
return equal(length(v), 1, epsilon);
}
-Vector2 normalize(Vector2::Arg v, float epsilon = NV_EPSILON) {
+Vector2 normalize(Vector2::Arg v, float epsilon = NV_EPSILON)
+{
float l = length(v);
xaDebugAssert(!isZero(l, epsilon));
#ifdef NDEBUG
@@ -328,7 +360,8 @@ Vector2 normalize(Vector2::Arg v, float epsilon = NV_EPSILON) {
return n;
}
-Vector2 normalizeSafe(Vector2::Arg v, Vector2::Arg fallback, float epsilon = NV_EPSILON) {
+Vector2 normalizeSafe(Vector2::Arg v, Vector2::Arg fallback, float epsilon = NV_EPSILON)
+{
float l = length(v);
if (isZero(l, epsilon)) {
return fallback;
@@ -336,23 +369,28 @@ Vector2 normalizeSafe(Vector2::Arg v, Vector2::Arg fallback, float epsilon = NV_
return v * (1.0f / l);
}
-bool equal(Vector2::Arg v1, Vector2::Arg v2, float epsilon = NV_EPSILON) {
+bool equal(Vector2::Arg v1, Vector2::Arg v2, float epsilon = NV_EPSILON)
+{
return equal(v1.x, v2.x, epsilon) && equal(v1.y, v2.y, epsilon);
}
-Vector2 max(Vector2::Arg a, Vector2::Arg b) {
+Vector2 max(Vector2::Arg a, Vector2::Arg b)
+{
return Vector2(std::max(a.x, b.x), std::max(a.y, b.y));
}
-bool isFinite(Vector2::Arg v) {
+bool isFinite(Vector2::Arg v)
+{
return std::isfinite(v.x) && std::isfinite(v.y);
}
// Note, this is the area scaled by 2!
-float triangleArea(Vector2::Arg v0, Vector2::Arg v1) {
+float triangleArea(Vector2::Arg v0, Vector2::Arg v1)
+{
return (v0.x * v1.y - v0.y * v1.x); // * 0.5f;
}
-float triangleArea(Vector2::Arg a, Vector2::Arg b, Vector2::Arg c) {
+float triangleArea(Vector2::Arg a, Vector2::Arg b, Vector2::Arg c)
+{
// IC: While it may be appealing to use the following expression:
//return (c.x * a.y + a.x * b.y + b.x * c.y - b.x * a.y - c.x * b.y - a.x * c.y); // * 0.5f;
// That's actually a terrible idea. Small triangles far from the origin can end up producing fairly large floating point
@@ -364,105 +402,109 @@ float triangleArea(Vector2::Arg a, Vector2::Arg b, Vector2::Arg c) {
return triangleArea(a - c, b - c);
}
-float triangleArea2(Vector2::Arg v1, Vector2::Arg v2, Vector2::Arg v3) {
+float triangleArea2(Vector2::Arg v1, Vector2::Arg v2, Vector2::Arg v3)
+{
return 0.5f * (v3.x * v1.y + v1.x * v2.y + v2.x * v3.y - v2.x * v1.y - v3.x * v2.y - v1.x * v3.y);
}
-static uint32_t hash(const Vector2 &v, uint32_t h) {
+static uint32_t hash(const Vector2 &v, uint32_t h)
+{
return sdbmFloatHash(v.component, 2, h);
}
-class Vector3 {
+class Vector3
+{
public:
typedef Vector3 const &Arg;
Vector3() {}
- explicit Vector3(float f) :
- x(f),
- y(f),
- z(f) {}
- Vector3(float x, float y, float z) :
- x(x),
- y(y),
- z(z) {}
- Vector3(Vector2::Arg v, float z) :
- x(v.x),
- y(v.y),
- z(z) {}
- Vector3(Vector3::Arg v) :
- x(v.x),
- y(v.y),
- z(v.z) {}
-
- const Vector3 &operator=(Vector3::Arg v) {
+ explicit Vector3(float f) : x(f), y(f), z(f) {}
+ Vector3(float x, float y, float z) : x(x), y(y), z(z) {}
+ Vector3(Vector2::Arg v, float z) : x(v.x), y(v.y), z(z) {}
+ Vector3(Vector3::Arg v) : x(v.x), y(v.y), z(v.z) {}
+
+ const Vector3 &operator=(Vector3::Arg v)
+ {
x = v.x;
y = v.y;
z = v.z;
return *this;
}
- Vector2 xy() const {
+ Vector2 xy() const
+ {
return Vector2(x, y);
}
const float *ptr() const { return &x; }
- void set(float _x, float _y, float _z) {
+ void set(float _x, float _y, float _z)
+ {
x = _x;
y = _y;
z = _z;
}
- Vector3 operator-() const {
+ Vector3 operator-() const
+ {
return Vector3(-x, -y, -z);
}
- void operator+=(Vector3::Arg v) {
+ void operator+=(Vector3::Arg v)
+ {
x += v.x;
y += v.y;
z += v.z;
}
- void operator-=(Vector3::Arg v) {
+ void operator-=(Vector3::Arg v)
+ {
x -= v.x;
y -= v.y;
z -= v.z;
}
- void operator*=(float s) {
+ void operator*=(float s)
+ {
x *= s;
y *= s;
z *= s;
}
- void operator/=(float s) {
+ void operator/=(float s)
+ {
float is = 1.0f / s;
x *= is;
y *= is;
z *= is;
}
- void operator*=(Vector3::Arg v) {
+ void operator*=(Vector3::Arg v)
+ {
x *= v.x;
y *= v.y;
z *= v.z;
}
- void operator/=(Vector3::Arg v) {
+ void operator/=(Vector3::Arg v)
+ {
x /= v.x;
y /= v.y;
z /= v.z;
}
- friend bool operator==(Vector3::Arg a, Vector3::Arg b) {
+ friend bool operator==(Vector3::Arg a, Vector3::Arg b)
+ {
return a.x == b.x && a.y == b.y && a.z == b.z;
}
- friend bool operator!=(Vector3::Arg a, Vector3::Arg b) {
+ friend bool operator!=(Vector3::Arg a, Vector3::Arg b)
+ {
return a.x != b.x || a.y != b.y || a.z != b.z;
}
- union {
+ union
+ {
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4201)
@@ -479,85 +521,106 @@ public:
};
};
-Vector3 add(Vector3::Arg a, Vector3::Arg b) {
+Vector3 add(Vector3::Arg a, Vector3::Arg b)
+{
return Vector3(a.x + b.x, a.y + b.y, a.z + b.z);
}
-Vector3 add(Vector3::Arg a, float b) {
+Vector3 add(Vector3::Arg a, float b)
+{
return Vector3(a.x + b, a.y + b, a.z + b);
}
-Vector3 operator+(Vector3::Arg a, Vector3::Arg b) {
+Vector3 operator+(Vector3::Arg a, Vector3::Arg b)
+{
return add(a, b);
}
-Vector3 operator+(Vector3::Arg a, float b) {
+Vector3 operator+(Vector3::Arg a, float b)
+{
return add(a, b);
}
-Vector3 sub(Vector3::Arg a, Vector3::Arg b) {
+Vector3 sub(Vector3::Arg a, Vector3::Arg b)
+{
return Vector3(a.x - b.x, a.y - b.y, a.z - b.z);
}
-Vector3 sub(Vector3::Arg a, float b) {
+Vector3 sub(Vector3::Arg a, float b)
+{
return Vector3(a.x - b, a.y - b, a.z - b);
}
-Vector3 operator-(Vector3::Arg a, Vector3::Arg b) {
+Vector3 operator-(Vector3::Arg a, Vector3::Arg b)
+{
return sub(a, b);
}
-Vector3 operator-(Vector3::Arg a, float b) {
+Vector3 operator-(Vector3::Arg a, float b)
+{
return sub(a, b);
}
-Vector3 cross(Vector3::Arg a, Vector3::Arg b) {
+Vector3 cross(Vector3::Arg a, Vector3::Arg b)
+{
return Vector3(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x);
}
-Vector3 operator*(Vector3::Arg v, float s) {
+Vector3 operator*(Vector3::Arg v, float s)
+{
return Vector3(v.x * s, v.y * s, v.z * s);
}
-Vector3 operator*(float s, Vector3::Arg v) {
+Vector3 operator*(float s, Vector3::Arg v)
+{
return Vector3(v.x * s, v.y * s, v.z * s);
}
-Vector3 operator*(Vector3::Arg v, Vector3::Arg s) {
+Vector3 operator*(Vector3::Arg v, Vector3::Arg s)
+{
return Vector3(v.x * s.x, v.y * s.y, v.z * s.z);
}
-Vector3 operator/(Vector3::Arg v, float s) {
+Vector3 operator/(Vector3::Arg v, float s)
+{
return v * (1.0f / s);
}
-Vector3 lerp(Vector3::Arg v1, Vector3::Arg v2, float t) {
+Vector3 lerp(Vector3::Arg v1, Vector3::Arg v2, float t)
+{
const float s = 1.0f - t;
return Vector3(v1.x * s + t * v2.x, v1.y * s + t * v2.y, v1.z * s + t * v2.z);
}
-float dot(Vector3::Arg a, Vector3::Arg b) {
+float dot(Vector3::Arg a, Vector3::Arg b)
+{
return a.x * b.x + a.y * b.y + a.z * b.z;
}
-float lengthSquared(Vector3::Arg v) {
+float lengthSquared(Vector3::Arg v)
+{
return v.x * v.x + v.y * v.y + v.z * v.z;
}
-float length(Vector3::Arg v) {
+float length(Vector3::Arg v)
+{
return sqrtf(lengthSquared(v));
}
-float distance(Vector3::Arg a, Vector3::Arg b) {
+float distance(Vector3::Arg a, Vector3::Arg b)
+{
return length(a - b);
}
-float distanceSquared(Vector3::Arg a, Vector3::Arg b) {
+float distanceSquared(Vector3::Arg a, Vector3::Arg b)
+{
return lengthSquared(a - b);
}
-bool isNormalized(Vector3::Arg v, float epsilon = NV_NORMAL_EPSILON) {
+bool isNormalized(Vector3::Arg v, float epsilon = NV_NORMAL_EPSILON)
+{
return equal(length(v), 1, epsilon);
}
-Vector3 normalize(Vector3::Arg v, float epsilon = NV_EPSILON) {
+Vector3 normalize(Vector3::Arg v, float epsilon = NV_EPSILON)
+{
float l = length(v);
xaDebugAssert(!isZero(l, epsilon));
#ifdef NDEBUG
@@ -568,7 +631,8 @@ Vector3 normalize(Vector3::Arg v, float epsilon = NV_EPSILON) {
return n;
}
-Vector3 normalizeSafe(Vector3::Arg v, Vector3::Arg fallback, float epsilon = NV_EPSILON) {
+Vector3 normalizeSafe(Vector3::Arg v, Vector3::Arg fallback, float epsilon = NV_EPSILON)
+{
float l = length(v);
if (isZero(l, epsilon)) {
return fallback;
@@ -576,49 +640,56 @@ Vector3 normalizeSafe(Vector3::Arg v, Vector3::Arg fallback, float epsilon = NV_
return v * (1.0f / l);
}
-bool equal(Vector3::Arg v1, Vector3::Arg v2, float epsilon = NV_EPSILON) {
+bool equal(Vector3::Arg v1, Vector3::Arg v2, float epsilon = NV_EPSILON)
+{
return equal(v1.x, v2.x, epsilon) && equal(v1.y, v2.y, epsilon) && equal(v1.z, v2.z, epsilon);
}
-Vector3 min(Vector3::Arg a, Vector3::Arg b) {
+Vector3 min(Vector3::Arg a, Vector3::Arg b)
+{
return Vector3(std::min(a.x, b.x), std::min(a.y, b.y), std::min(a.z, b.z));
}
-Vector3 max(Vector3::Arg a, Vector3::Arg b) {
+Vector3 max(Vector3::Arg a, Vector3::Arg b)
+{
return Vector3(std::max(a.x, b.x), std::max(a.y, b.y), std::max(a.z, b.z));
}
-Vector3 clamp(Vector3::Arg v, float min, float max) {
+Vector3 clamp(Vector3::Arg v, float min, float max)
+{
return Vector3(clamp(v.x, min, max), clamp(v.y, min, max), clamp(v.z, min, max));
}
-Vector3 saturate(Vector3::Arg v) {
+Vector3 saturate(Vector3::Arg v)
+{
return Vector3(saturate(v.x), saturate(v.y), saturate(v.z));
}
-Vector3 floor(Vector3::Arg v) {
+Vector3 floor(Vector3::Arg v)
+{
return Vector3(floorf(v.x), floorf(v.y), floorf(v.z));
}
-bool isFinite(Vector3::Arg v) {
+bool isFinite(Vector3::Arg v)
+{
return std::isfinite(v.x) && std::isfinite(v.y) && std::isfinite(v.z);
}
-static uint32_t hash(const Vector3 &v, uint32_t h) {
+static uint32_t hash(const Vector3 &v, uint32_t h)
+{
return sdbmFloatHash(v.component, 3, h);
}
/// Basis class to compute tangent space basis, ortogonalizations and to
/// transform vectors from one space to another.
-class Basis {
+class Basis
+{
public:
/// Create a null basis.
- Basis() :
- tangent(0, 0, 0),
- bitangent(0, 0, 0),
- normal(0, 0, 0) {}
+ Basis() : tangent(0, 0, 0), bitangent(0, 0, 0), normal(0, 0, 0) {}
- void buildFrameForDirection(Vector3::Arg d, float angle = 0) {
+ void buildFrameForDirection(Vector3::Arg d, float angle = 0)
+ {
xaAssert(isNormalized(d));
normal = d;
// Choose minimum axis.
@@ -649,65 +720,76 @@ public:
};
// Simple bit array.
-class BitArray {
+class BitArray
+{
public:
- BitArray() :
- m_size(0) {}
- BitArray(uint32_t sz) {
+ BitArray() : m_size(0) {}
+ BitArray(uint32_t sz)
+ {
resize(sz);
}
- uint32_t size() const {
+ uint32_t size() const
+ {
return m_size;
}
- void clear() {
+ void clear()
+ {
resize(0);
}
- void resize(uint32_t new_size) {
+ void resize(uint32_t new_size)
+ {
m_size = new_size;
- m_wordArray.resize((m_size + 31) >> 5);
+ m_wordArray.resize( (m_size + 31) >> 5 );
}
/// Get bit.
- bool bitAt(uint32_t b) const {
- xaDebugAssert(b < m_size);
+ bool bitAt(uint32_t b) const
+ {
+ xaDebugAssert( b < m_size );
return (m_wordArray[b >> 5] & (1 << (b & 31))) != 0;
}
// Set a bit.
- void setBitAt(uint32_t idx) {
+ void setBitAt(uint32_t idx)
+ {
xaDebugAssert(idx < m_size);
- m_wordArray[idx >> 5] |= (1 << (idx & 31));
+ m_wordArray[idx >> 5] |= (1 << (idx & 31));
}
// Toggle a bit.
- void toggleBitAt(uint32_t idx) {
+ void toggleBitAt(uint32_t idx)
+ {
xaDebugAssert(idx < m_size);
m_wordArray[idx >> 5] ^= (1 << (idx & 31));
}
// Set a bit to the given value. @@ Rename modifyBitAt?
- void setBitAt(uint32_t idx, bool b) {
+ void setBitAt(uint32_t idx, bool b)
+ {
xaDebugAssert(idx < m_size);
m_wordArray[idx >> 5] = setBits(m_wordArray[idx >> 5], 1 << (idx & 31), b);
xaDebugAssert(bitAt(idx) == b);
}
// Clear all the bits.
- void clearAll() {
- memset(m_wordArray.data(), 0, m_wordArray.size() * sizeof(uint32_t));
+ void clearAll()
+ {
+ memset(m_wordArray.data(), 0, m_wordArray.size() * sizeof(uint32_t ));
}
// Set all the bits.
- void setAll() {
- memset(m_wordArray.data(), 0xFF, m_wordArray.size() * sizeof(uint32_t));
+ void setAll()
+ {
+ memset(m_wordArray.data(), 0xFF, m_wordArray.size() * sizeof(uint32_t ));
}
private:
// See "Conditionally set or clear bits without branching" at http://graphics.stanford.edu/~seander/bithacks.html
- uint32_t setBits(uint32_t w, uint32_t m, bool b) {
+ uint32_t setBits(uint32_t w, uint32_t m, bool b)
+ {
return (w & ~m) | (-int(b) & m);
}
@@ -719,29 +801,26 @@ private:
};
/// Bit map. This should probably be called BitImage.
-class BitMap {
+class BitMap
+{
public:
- BitMap() :
- m_width(0),
- m_height(0) {}
- BitMap(uint32_t w, uint32_t h) :
- m_width(w),
- m_height(h),
- m_bitArray(w * h) {}
-
- uint32_t width() const {
+ BitMap() : m_width(0), m_height(0) {}
+ BitMap(uint32_t w, uint32_t h) : m_width(w), m_height(h), m_bitArray(w * h) {}
+
+ uint32_t width() const
+ {
return m_width;
}
- uint32_t height() const {
+ uint32_t height() const
+ {
return m_height;
}
- void resize(uint32_t w, uint32_t h, bool initValue) {
+ void resize(uint32_t w, uint32_t h, bool initValue)
+ {
BitArray tmp(w * h);
- if (initValue)
- tmp.setAll();
- else
- tmp.clearAll();
+ if (initValue) tmp.setAll();
+ else tmp.clearAll();
// @@ Copying one bit at a time. This could be much faster.
for (uint32_t y = 0; y < m_height; y++) {
for (uint32_t x = 0; x < m_width; x++) {
@@ -754,17 +833,20 @@ public:
m_height = h;
}
- bool bitAt(uint32_t x, uint32_t y) const {
+ bool bitAt(uint32_t x, uint32_t y) const
+ {
xaDebugAssert(x < m_width && y < m_height);
return m_bitArray.bitAt(y * m_width + x);
}
- void setBitAt(uint32_t x, uint32_t y) {
+ void setBitAt(uint32_t x, uint32_t y)
+ {
xaDebugAssert(x < m_width && y < m_height);
m_bitArray.setBitAt(y * m_width + x);
}
- void clearAll() {
+ void clearAll()
+ {
m_bitArray.clearAll();
}
@@ -775,39 +857,41 @@ private:
};
// Axis Aligned Bounding Box.
-class Box {
+class Box
+{
public:
Box() {}
- Box(const Box &b) :
- minCorner(b.minCorner),
- maxCorner(b.maxCorner) {}
- Box(const Vector3 &mins, const Vector3 &maxs) :
- minCorner(mins),
- maxCorner(maxs) {}
-
- operator const float *() const {
+ Box(const Box &b) : minCorner(b.minCorner), maxCorner(b.maxCorner) {}
+ Box(const Vector3 &mins, const Vector3 &maxs) : minCorner(mins), maxCorner(maxs) {}
+
+ operator const float *() const
+ {
return reinterpret_cast<const float *>(this);
}
// Clear the bounds.
- void clearBounds() {
+ void clearBounds()
+ {
minCorner.set(FLT_MAX, FLT_MAX, FLT_MAX);
maxCorner.set(-FLT_MAX, -FLT_MAX, -FLT_MAX);
}
// Return extents of the box.
- Vector3 extents() const {
+ Vector3 extents() const
+ {
return (maxCorner - minCorner) * 0.5f;
}
// Add a point to this box.
- void addPointToBounds(const Vector3 &p) {
+ void addPointToBounds(const Vector3 &p)
+ {
minCorner = min(minCorner, p);
maxCorner = max(maxCorner, p);
}
// Get the volume of the box.
- float volume() const {
+ float volume() const
+ {
Vector3 d = extents();
return 8.0f * (d.x * d.y * d.z);
}
@@ -816,9 +900,11 @@ public:
Vector3 maxCorner;
};
-class Fit {
+class Fit
+{
public:
- static Vector3 computeCentroid(int n, const Vector3 *__restrict points) {
+ static Vector3 computeCentroid(int n, const Vector3 *__restrict points)
+ {
Vector3 centroid(0.0f);
for (int i = 0; i < n; i++) {
centroid += points[i];
@@ -827,7 +913,8 @@ public:
return centroid;
}
- static Vector3 computeCovariance(int n, const Vector3 *__restrict points, float *__restrict covariance) {
+ static Vector3 computeCovariance(int n, const Vector3 *__restrict points, float *__restrict covariance)
+ {
// compute the centroid
Vector3 centroid = computeCentroid(n, points);
// compute covariance matrix
@@ -846,7 +933,8 @@ public:
return centroid;
}
- static bool isPlanar(int n, const Vector3 *points, float epsilon = NV_EPSILON) {
+ static bool isPlanar(int n, const Vector3 *points, float epsilon = NV_EPSILON)
+ {
// compute the centroid and covariance
float matrix[6];
computeCovariance(n, points, matrix);
@@ -861,7 +949,8 @@ public:
// Tridiagonal solver from Charles Bloom.
// Householder transforms followed by QL decomposition.
// Seems to be based on the code from Numerical Recipes in C.
- static bool eigenSolveSymmetric3(const float matrix[6], float eigenValues[3], Vector3 eigenVectors[3]) {
+ static bool eigenSolveSymmetric3(const float matrix[6], float eigenValues[3], Vector3 eigenVectors[3])
+ {
xaDebugAssert(matrix != NULL && eigenValues != NULL && eigenVectors != NULL);
float subd[3];
float diag[3];
@@ -886,7 +975,7 @@ public:
// eigenvectors are the columns; make them the rows :
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
- eigenVectors[j].component[i] = (float)work[i][j];
+ eigenVectors[j].component[i] = (float) work[i][j];
}
}
// shuffle to sort by singular value :
@@ -908,7 +997,8 @@ public:
}
private:
- static void EigenSolver3_Tridiagonal(float mat[3][3], float *diag, float *subd) {
+ static void EigenSolver3_Tridiagonal(float mat[3][3], float *diag, float *subd)
+ {
// Householder reduction T = Q^t M Q
// Input:
// mat, symmetric 3x3 matrix M
@@ -960,7 +1050,8 @@ private:
}
}
- static bool EigenSolver3_QLAlgorithm(float mat[3][3], float *diag, float *subd) {
+ static bool EigenSolver3_QLAlgorithm(float mat[3][3], float *diag, float *subd)
+ {
// QL iteration with implicit shifting to reduce matrix from tridiagonal
// to diagonal
const int maxiter = 32;
@@ -970,21 +1061,21 @@ private:
int m;
for (m = ell; m <= 1; m++) {
float dd = fabsf(diag[m]) + fabsf(diag[m + 1]);
- if (fabsf(subd[m]) + dd == dd)
+ if ( fabsf(subd[m]) + dd == dd )
break;
}
- if (m == ell)
+ if ( m == ell )
break;
float g = (diag[ell + 1] - diag[ell]) / (2 * subd[ell]);
float r = sqrtf(g * g + 1);
- if (g < 0)
+ if ( g < 0 )
g = diag[m] - diag[ell] + subd[ell] / (g - r);
else
g = diag[m] - diag[ell] + subd[ell] / (g + r);
float s = 1, c = 1, p = 0;
for (int i = m - 1; i >= ell; i--) {
float f = s * subd[i], b = c * subd[i];
- if (fabsf(f) >= fabsf(g)) {
+ if ( fabsf(f) >= fabsf(g) ) {
c = g / f;
r = sqrtf(c * c + 1);
subd[i + 1] = f * r;
@@ -1010,7 +1101,7 @@ private:
subd[ell] = g;
subd[m] = 0;
}
- if (iter == maxiter)
+ if ( iter == maxiter )
// should not get here under normal circumstances
return false;
}
@@ -1019,30 +1110,33 @@ private:
};
/// Fixed size vector class.
-class FullVector {
+class FullVector
+{
public:
FullVector(uint32_t dim) { m_array.resize(dim); }
- FullVector(const FullVector &v) :
- m_array(v.m_array) {}
+ FullVector(const FullVector &v) : m_array(v.m_array) {}
- const FullVector &operator=(const FullVector &v) {
+ const FullVector &operator=(const FullVector &v)
+ {
xaAssert(dimension() == v.dimension());
m_array = v.m_array;
return *this;
}
uint32_t dimension() const { return m_array.size(); }
- const float &operator[](uint32_t index) const { return m_array[index]; }
- float &operator[](uint32_t index) { return m_array[index]; }
+ const float &operator[]( uint32_t index ) const { return m_array[index]; }
+ float &operator[] ( uint32_t index ) { return m_array[index]; }
- void fill(float f) {
+ void fill(float f)
+ {
const uint32_t dim = dimension();
for (uint32_t i = 0; i < dim; i++) {
m_array[i] = f;
}
}
- void operator+=(const FullVector &v) {
+ void operator+=(const FullVector &v)
+ {
xaDebugAssert(dimension() == v.dimension());
const uint32_t dim = dimension();
for (uint32_t i = 0; i < dim; i++) {
@@ -1050,7 +1144,8 @@ public:
}
}
- void operator-=(const FullVector &v) {
+ void operator-=(const FullVector &v)
+ {
xaDebugAssert(dimension() == v.dimension());
const uint32_t dim = dimension();
for (uint32_t i = 0; i < dim; i++) {
@@ -1058,7 +1153,8 @@ public:
}
}
- void operator*=(const FullVector &v) {
+ void operator*=(const FullVector &v)
+ {
xaDebugAssert(dimension() == v.dimension());
const uint32_t dim = dimension();
for (uint32_t i = 0; i < dim; i++) {
@@ -1066,21 +1162,24 @@ public:
}
}
- void operator+=(float f) {
+ void operator+=(float f)
+ {
const uint32_t dim = dimension();
for (uint32_t i = 0; i < dim; i++) {
m_array[i] += f;
}
}
- void operator-=(float f) {
+ void operator-=(float f)
+ {
const uint32_t dim = dimension();
for (uint32_t i = 0; i < dim; i++) {
m_array[i] -= f;
}
}
- void operator*=(float f) {
+ void operator*=(float f)
+ {
const uint32_t dim = dimension();
for (uint32_t i = 0; i < dim; i++) {
m_array[i] *= f;
@@ -1095,66 +1194,70 @@ namespace halfedge {
class Face;
class Vertex;
-class Edge {
+class Edge
+{
public:
uint32_t id;
Edge *next;
- Edge *prev; // This is not strictly half-edge, but makes algorithms easier and faster.
+ Edge *prev; // This is not strictly half-edge, but makes algorithms easier and faster.
Edge *pair;
Vertex *vertex;
Face *face;
// Default constructor.
- Edge(uint32_t id) :
- id(id),
- next(NULL),
- prev(NULL),
- pair(NULL),
- vertex(NULL),
- face(NULL) {}
+ Edge(uint32_t id) : id(id), next(NULL), prev(NULL), pair(NULL), vertex(NULL), face(NULL) {}
// Vertex queries.
- const Vertex *from() const {
+ const Vertex *from() const
+ {
return vertex;
}
- Vertex *from() {
+ Vertex *from()
+ {
return vertex;
}
- const Vertex *to() const {
- return pair->vertex; // This used to be 'next->vertex', but that changed often when the connectivity of the mesh changes.
+ const Vertex *to() const
+ {
+ return pair->vertex; // This used to be 'next->vertex', but that changed often when the connectivity of the mesh changes.
}
- Vertex *to() {
+ Vertex *to()
+ {
return pair->vertex;
}
// Edge queries.
- void setNext(Edge *e) {
+ void setNext(Edge *e)
+ {
next = e;
if (e != NULL) e->prev = this;
}
- void setPrev(Edge *e) {
+ void setPrev(Edge *e)
+ {
prev = e;
if (e != NULL) e->next = this;
}
// @@ It would be more simple to only check m_pair == NULL
// Face queries.
- bool isBoundary() const {
+ bool isBoundary() const
+ {
return !(face && pair->face);
}
// @@ This is not exactly accurate, we should compare the texture coordinates...
- bool isSeam() const {
+ bool isSeam() const
+ {
return vertex != pair->next->vertex || next->vertex != pair->vertex;
}
bool isNormalSeam() const;
bool isTextureSeam() const;
- bool isValid() const {
+ bool isValid() const
+ {
// null face is OK.
if (next == NULL || prev == NULL || pair == NULL || vertex == NULL) return false;
if (next->prev != this) return false;
@@ -1169,10 +1272,13 @@ public:
float angle() const;
};
-class Vertex {
+class Vertex
+{
public:
uint32_t id;
+ // -- GODOT start --
uint32_t original_id;
+ // -- GODOT end --
Edge *edge;
Vertex *next;
Vertex *prev;
@@ -1180,36 +1286,38 @@ public:
Vector3 nor;
Vector2 tex;
- Vertex(uint32_t id) :
- id(id),
- original_id(id),
- edge(NULL),
- pos(0.0f),
- nor(0.0f),
- tex(0.0f) {
+ // -- GODOT start --
+ //Vertex(uint32_t id) : id(id), edge(NULL), pos(0.0f), nor(0.0f), tex(0.0f)
+ Vertex(uint32_t id) : id(id), original_id(id), edge(NULL), pos(0.0f), nor(0.0f), tex(0.0f)
+ // -- GODOT end --
+ {
next = this;
prev = this;
}
// Set first edge of all colocals.
- void setEdge(Edge *e) {
+ void setEdge(Edge *e)
+ {
for (VertexIterator it(colocals()); !it.isDone(); it.advance()) {
it.current()->edge = e;
}
}
// Update position of all colocals.
- void setPos(const Vector3 &p) {
+ void setPos(const Vector3 &p)
+ {
for (VertexIterator it(colocals()); !it.isDone(); it.advance()) {
it.current()->pos = p;
}
}
- bool isFirstColocal() const {
+ bool isFirstColocal() const
+ {
return firstColocal() == this;
}
- const Vertex *firstColocal() const {
+ const Vertex *firstColocal() const
+ {
uint32_t firstId = id;
const Vertex *vertex = this;
for (ConstVertexIterator it(colocals()); !it.isDone(); it.advance()) {
@@ -1221,7 +1329,8 @@ public:
return vertex;
}
- Vertex *firstColocal() {
+ Vertex *firstColocal()
+ {
Vertex *vertex = this;
uint32_t firstId = id;
for (VertexIterator it(colocals()); !it.isDone(); it.advance()) {
@@ -1233,7 +1342,8 @@ public:
return vertex;
}
- bool isColocal(const Vertex *v) const {
+ bool isColocal(const Vertex *v) const
+ {
if (this == v) return true;
if (pos != v->pos) return false;
for (ConstVertexIterator it(colocals()); !it.isDone(); it.advance()) {
@@ -1244,13 +1354,15 @@ public:
return false;
}
- void linkColocal(Vertex *v) {
+ void linkColocal(Vertex *v)
+ {
next->prev = v;
v->next = next;
next = v;
v->prev = this;
}
- void unlinkColocal() {
+ void unlinkColocal()
+ {
next->prev = prev;
prev->next = next;
next = this;
@@ -1258,7 +1370,8 @@ public:
}
// @@ Note: This only works if linkBoundary has been called.
- bool isBoundary() const {
+ bool isBoundary() const
+ {
return (edge && !edge->face);
}
@@ -1266,23 +1379,25 @@ public:
class EdgeIterator //: public Iterator<Edge *>
{
public:
- EdgeIterator(Edge *e) :
- m_end(NULL),
- m_current(e) {}
+ EdgeIterator(Edge *e) : m_end(NULL), m_current(e) { }
- virtual void advance() {
+ virtual void advance()
+ {
if (m_end == NULL) m_end = m_current;
m_current = m_current->pair->next;
//m_current = m_current->prev->pair;
}
- virtual bool isDone() const {
+ virtual bool isDone() const
+ {
return m_end == m_current;
}
- virtual Edge *current() const {
+ virtual Edge *current() const
+ {
return m_current;
}
- Vertex *vertex() const {
+ Vertex *vertex() const
+ {
return m_current->vertex;
}
@@ -1291,10 +1406,12 @@ public:
Edge *m_current;
};
- EdgeIterator edges() {
+ EdgeIterator edges()
+ {
return EdgeIterator(edge);
}
- EdgeIterator edges(Edge *e) {
+ EdgeIterator edges(Edge *e)
+ {
return EdgeIterator(e);
}
@@ -1302,26 +1419,26 @@ public:
class ConstEdgeIterator //: public Iterator<Edge *>
{
public:
- ConstEdgeIterator(const Edge *e) :
- m_end(NULL),
- m_current(e) {}
- ConstEdgeIterator(EdgeIterator it) :
- m_end(NULL),
- m_current(it.current()) {}
-
- virtual void advance() {
+ ConstEdgeIterator(const Edge *e) : m_end(NULL), m_current(e) { }
+ ConstEdgeIterator(EdgeIterator it) : m_end(NULL), m_current(it.current()) { }
+
+ virtual void advance()
+ {
if (m_end == NULL) m_end = m_current;
m_current = m_current->pair->next;
//m_current = m_current->prev->pair;
}
- virtual bool isDone() const {
+ virtual bool isDone() const
+ {
return m_end == m_current;
}
- virtual const Edge *current() const {
+ virtual const Edge *current() const
+ {
return m_current;
}
- const Vertex *vertex() const {
+ const Vertex *vertex() const
+ {
return m_current->to();
}
@@ -1330,10 +1447,12 @@ public:
const Edge *m_current;
};
- ConstEdgeIterator edges() const {
+ ConstEdgeIterator edges() const
+ {
return ConstEdgeIterator(edge);
}
- ConstEdgeIterator edges(const Edge *e) const {
+ ConstEdgeIterator edges(const Edge *e) const
+ {
return ConstEdgeIterator(e);
}
@@ -1341,19 +1460,20 @@ public:
class VertexIterator //: public Iterator<Edge *>
{
public:
- VertexIterator(Vertex *v) :
- m_end(NULL),
- m_current(v) {}
+ VertexIterator(Vertex *v) : m_end(NULL), m_current(v) { }
- virtual void advance() {
+ virtual void advance()
+ {
if (m_end == NULL) m_end = m_current;
m_current = m_current->next;
}
- virtual bool isDone() const {
+ virtual bool isDone() const
+ {
return m_end == m_current;
}
- virtual Vertex *current() const {
+ virtual Vertex *current() const
+ {
return m_current;
}
@@ -1362,7 +1482,8 @@ public:
Vertex *m_current;
};
- VertexIterator colocals() {
+ VertexIterator colocals()
+ {
return VertexIterator(this);
}
@@ -1370,19 +1491,20 @@ public:
class ConstVertexIterator //: public Iterator<Edge *>
{
public:
- ConstVertexIterator(const Vertex *v) :
- m_end(NULL),
- m_current(v) {}
+ ConstVertexIterator(const Vertex *v) : m_end(NULL), m_current(v) { }
- virtual void advance() {
+ virtual void advance()
+ {
if (m_end == NULL) m_end = m_current;
m_current = m_current->next;
}
- virtual bool isDone() const {
+ virtual bool isDone() const
+ {
return m_end == m_current;
}
- virtual const Vertex *current() const {
+ virtual const Vertex *current() const
+ {
return m_current;
}
@@ -1391,24 +1513,29 @@ public:
const Vertex *m_current;
};
- ConstVertexIterator colocals() const {
+ ConstVertexIterator colocals() const
+ {
return ConstVertexIterator(this);
}
};
-bool Edge::isNormalSeam() const {
+bool Edge::isNormalSeam() const
+{
return (vertex->nor != pair->next->vertex->nor || next->vertex->nor != pair->vertex->nor);
}
-bool Edge::isTextureSeam() const {
+bool Edge::isTextureSeam() const
+{
return (vertex->tex != pair->next->vertex->tex || next->vertex->tex != pair->vertex->tex);
}
-float Edge::length() const {
+float Edge::length() const
+{
return internal::length(to()->pos - from()->pos);
}
-float Edge::angle() const {
+float Edge::angle() const
+{
Vector3 p = vertex->pos;
Vector3 a = prev->vertex->pos;
Vector3 b = next->vertex->pos;
@@ -1417,20 +1544,18 @@ float Edge::angle() const {
return acosf(dot(v0, v1) / (internal::length(v0) * internal::length(v1)));
}
-class Face {
+class Face
+{
public:
uint32_t id;
uint16_t group;
uint16_t material;
Edge *edge;
- Face(uint32_t id) :
- id(id),
- group(uint16_t(~0)),
- material(uint16_t(~0)),
- edge(NULL) {}
+ Face(uint32_t id) : id(id), group(uint16_t(~0)), material(uint16_t(~0)), edge(NULL) {}
- float area() const {
+ float area() const
+ {
float area = 0;
const Vector3 &v0 = edge->from()->pos;
for (ConstEdgeIterator it(edges(edge->next)); it.current() != edge->prev; it.advance()) {
@@ -1442,7 +1567,8 @@ public:
return area * 0.5f;
}
- float parametricArea() const {
+ float parametricArea() const
+ {
float area = 0;
const Vector2 &v0 = edge->from()->tex;
for (ConstEdgeIterator it(edges(edge->next)); it.current() != edge->prev; it.advance()) {
@@ -1454,7 +1580,8 @@ public:
return area * 0.5f;
}
- Vector3 normal() const {
+ Vector3 normal() const
+ {
Vector3 n(0);
const Vertex *vertex0 = NULL;
for (ConstEdgeIterator it(edges()); !it.isDone(); it.advance()) {
@@ -1476,7 +1603,8 @@ public:
return normalizeSafe(n, Vector3(0, 0, 1), 0.0f);
}
- Vector3 centroid() const {
+ Vector3 centroid() const
+ {
Vector3 sum(0.0f);
uint32_t count = 0;
for (ConstEdgeIterator it(edges()); !it.isDone(); it.advance()) {
@@ -1488,7 +1616,8 @@ public:
}
// Unnormalized face normal assuming it's a triangle.
- Vector3 triangleNormal() const {
+ Vector3 triangleNormal() const
+ {
Vector3 p0 = edge->vertex->pos;
Vector3 p1 = edge->next->vertex->pos;
Vector3 p2 = edge->next->next->vertex->pos;
@@ -1497,7 +1626,8 @@ public:
return normalizeSafe(cross(e0, e1), Vector3(0), 0.0f);
}
- Vector3 triangleNormalAreaScaled() const {
+ Vector3 triangleNormalAreaScaled() const
+ {
Vector3 p0 = edge->vertex->pos;
Vector3 p1 = edge->next->vertex->pos;
Vector3 p2 = edge->next->next->vertex->pos;
@@ -1508,7 +1638,8 @@ public:
// Average of the edge midpoints weighted by the edge length.
// I want a point inside the triangle, but closer to the cirumcenter.
- Vector3 triangleCenter() const {
+ Vector3 triangleCenter() const
+ {
Vector3 p0 = edge->vertex->pos;
Vector3 p1 = edge->next->vertex->pos;
Vector3 p2 = edge->next->next->vertex->pos;
@@ -1521,7 +1652,8 @@ public:
return m0 + m1 + m2;
}
- bool isValid() const {
+ bool isValid() const
+ {
uint32_t count = 0;
for (ConstEdgeIterator it(edges()); !it.isDone(); it.advance()) {
const Edge *e = it.current();
@@ -1534,14 +1666,16 @@ public:
return true;
}
- bool contains(const Edge *e) const {
+ bool contains(const Edge *e) const
+ {
for (ConstEdgeIterator it(edges()); !it.isDone(); it.advance()) {
if (it.current() == e) return true;
}
return false;
}
- uint32_t edgeCount() const {
+ uint32_t edgeCount() const
+ {
uint32_t count = 0;
for (ConstEdgeIterator it(edges()); !it.isDone(); it.advance()) {
++count;
@@ -1553,22 +1687,24 @@ public:
class EdgeIterator //: public Iterator<Edge *>
{
public:
- EdgeIterator(Edge *e) :
- m_end(NULL),
- m_current(e) {}
+ EdgeIterator(Edge *e) : m_end(NULL), m_current(e) { }
- virtual void advance() {
+ virtual void advance()
+ {
if (m_end == NULL) m_end = m_current;
m_current = m_current->next;
}
- virtual bool isDone() const {
+ virtual bool isDone() const
+ {
return m_end == m_current;
}
- virtual Edge *current() const {
+ virtual Edge *current() const
+ {
return m_current;
}
- Vertex *vertex() const {
+ Vertex *vertex() const
+ {
return m_current->vertex;
}
@@ -1577,10 +1713,12 @@ public:
Edge *m_current;
};
- EdgeIterator edges() {
+ EdgeIterator edges()
+ {
return EdgeIterator(edge);
}
- EdgeIterator edges(Edge *e) {
+ EdgeIterator edges(Edge *e)
+ {
xaDebugAssert(contains(e));
return EdgeIterator(e);
}
@@ -1589,25 +1727,25 @@ public:
class ConstEdgeIterator //: public Iterator<const Edge *>
{
public:
- ConstEdgeIterator(const Edge *e) :
- m_end(NULL),
- m_current(e) {}
- ConstEdgeIterator(const EdgeIterator &it) :
- m_end(NULL),
- m_current(it.current()) {}
-
- virtual void advance() {
+ ConstEdgeIterator(const Edge *e) : m_end(NULL), m_current(e) { }
+ ConstEdgeIterator(const EdgeIterator &it) : m_end(NULL), m_current(it.current()) { }
+
+ virtual void advance()
+ {
if (m_end == NULL) m_end = m_current;
m_current = m_current->next;
}
- virtual bool isDone() const {
+ virtual bool isDone() const
+ {
return m_end == m_current;
}
- virtual const Edge *current() const {
+ virtual const Edge *current() const
+ {
return m_current;
}
- const Vertex *vertex() const {
+ const Vertex *vertex() const
+ {
return m_current->vertex;
}
@@ -1616,22 +1754,25 @@ public:
const Edge *m_current;
};
- ConstEdgeIterator edges() const {
+ ConstEdgeIterator edges() const
+ {
return ConstEdgeIterator(edge);
}
- ConstEdgeIterator edges(const Edge *e) const {
+ ConstEdgeIterator edges(const Edge *e) const
+ {
xaDebugAssert(contains(e));
return ConstEdgeIterator(e);
}
};
/// Simple half edge mesh designed for dynamic mesh manipulation.
-class Mesh {
+class Mesh
+{
public:
- Mesh() :
- m_colocalVertexCount(0) {}
+ Mesh() : m_colocalVertexCount(0) {}
- Mesh(const Mesh *mesh) {
+ Mesh(const Mesh *mesh)
+ {
// Copy mesh vertices.
const uint32_t vertexCount = mesh->vertexCount();
m_vertexArray.resize(vertexCount);
@@ -1659,11 +1800,13 @@ public:
}
}
- ~Mesh() {
+ ~Mesh()
+ {
clear();
}
- void clear() {
+ void clear()
+ {
for (size_t i = 0; i < m_vertexArray.size(); i++)
delete m_vertexArray[i];
m_vertexArray.clear();
@@ -1676,7 +1819,8 @@ public:
m_faceArray.clear();
}
- Vertex *addVertex(const Vector3 &pos) {
+ Vertex *addVertex(const Vector3 &pos)
+ {
xaDebugAssert(isFinite(pos));
Vertex *v = new Vertex(m_vertexArray.size());
v->pos = pos;
@@ -1685,7 +1829,8 @@ public:
}
/// Link colocal vertices based on geometric location only.
- void linkColocals() {
+ void linkColocals()
+ {
xaPrint("--- Linking colocals:\n");
const uint32_t vertexCount = this->vertexCount();
std::unordered_map<Vector3, Vertex *, Hash<Vector3>, Equal<Vector3> > vertexMap;
@@ -1704,7 +1849,8 @@ public:
// @@ Remove duplicated vertices? or just leave them as colocals?
}
- void linkColocalsWithCanonicalMap(const std::vector<uint32_t> &canonicalMap) {
+ void linkColocalsWithCanonicalMap(const std::vector<uint32_t> &canonicalMap)
+ {
xaPrint("--- Linking colocals:\n");
uint32_t vertexMapSize = 0;
for (uint32_t i = 0; i < canonicalMap.size(); i++) {
@@ -1728,13 +1874,15 @@ public:
xaPrint("--- %d vertex positions.\n", m_colocalVertexCount);
}
- Face *addFace() {
+ Face *addFace()
+ {
Face *f = new Face(m_faceArray.size());
m_faceArray.push_back(f);
return f;
}
- Face *addFace(uint32_t v0, uint32_t v1, uint32_t v2) {
+ Face *addFace(uint32_t v0, uint32_t v1, uint32_t v2)
+ {
uint32_t indexArray[3];
indexArray[0] = v0;
indexArray[1] = v1;
@@ -1742,6 +1890,57 @@ public:
return addFace(indexArray, 3, 0, 3);
}
+ Face *addFace(uint32_t v0, uint32_t v1, uint32_t v2, uint32_t v3)
+ {
+ uint32_t indexArray[4];
+ indexArray[0] = v0;
+ indexArray[1] = v1;
+ indexArray[2] = v2;
+ indexArray[3] = v3;
+ return addFace(indexArray, 4, 0, 4);
+ }
+
+ Face *addFace(const std::vector<uint32_t> &indexArray)
+ {
+ return addFace(indexArray, 0, indexArray.size());
+ }
+
+ Face *addFace(const std::vector<uint32_t> &indexArray, uint32_t first, uint32_t num)
+ {
+ return addFace(indexArray.data(), (uint32_t)indexArray.size(), first, num);
+ }
+
+ Face *addFace(const uint32_t *indexArray, uint32_t indexCount, uint32_t first, uint32_t num)
+ {
+ xaDebugAssert(first < indexCount);
+ xaDebugAssert(num <= indexCount - first);
+ xaDebugAssert(num > 2);
+ if (!canAddFace(indexArray, first, num)) {
+ return NULL;
+ }
+ Face *f = new Face(m_faceArray.size());
+ Edge *firstEdge = NULL;
+ Edge *last = NULL;
+ Edge *current = NULL;
+ for (uint32_t i = 0; i < num - 1; i++) {
+ current = addEdge(indexArray[first + i], indexArray[first + i + 1]);
+ xaAssert(current != NULL && current->face == NULL);
+ current->face = f;
+ if (last != NULL) last->setNext(current);
+ else firstEdge = current;
+ last = current;
+ }
+ current = addEdge(indexArray[first + num - 1], indexArray[first]);
+ xaAssert(current != NULL && current->face == NULL);
+ current->face = f;
+ last->setNext(current);
+ current->setNext(firstEdge);
+ f->edge = firstEdge;
+ m_faceArray.push_back(f);
+ return f;
+ }
+
+ // -- GODOT start --
Face *addUniqueFace(uint32_t v0, uint32_t v1, uint32_t v2) {
int base_vertex = m_vertexArray.size();
@@ -1797,59 +1996,13 @@ public:
indexArray[2] = base_vertex + 2;
return addFace(indexArray, 3, 0, 3);
}
-
- Face *addFace(uint32_t v0, uint32_t v1, uint32_t v2, uint32_t v3) {
- uint32_t indexArray[4];
- indexArray[0] = v0;
- indexArray[1] = v1;
- indexArray[2] = v2;
- indexArray[3] = v3;
- return addFace(indexArray, 4, 0, 4);
- }
-
- Face *addFace(const std::vector<uint32_t> &indexArray) {
- return addFace(indexArray, 0, indexArray.size());
- }
-
- Face *addFace(const std::vector<uint32_t> &indexArray, uint32_t first, uint32_t num) {
- return addFace(indexArray.data(), (uint32_t)indexArray.size(), first, num);
- }
-
- Face *addFace(const uint32_t *indexArray, uint32_t indexCount, uint32_t first, uint32_t num) {
- xaDebugAssert(first < indexCount);
- xaDebugAssert(num <= indexCount - first);
- xaDebugAssert(num > 2);
- if (!canAddFace(indexArray, first, num)) {
- return NULL;
- }
- Face *f = new Face(m_faceArray.size());
- Edge *firstEdge = NULL;
- Edge *last = NULL;
- Edge *current = NULL;
- for (uint32_t i = 0; i < num - 1; i++) {
- current = addEdge(indexArray[first + i], indexArray[first + i + 1]);
- xaAssert(current != NULL && current->face == NULL);
- current->face = f;
- if (last != NULL)
- last->setNext(current);
- else
- firstEdge = current;
- last = current;
- }
- current = addEdge(indexArray[first + num - 1], indexArray[first]);
- xaAssert(current != NULL && current->face == NULL);
- current->face = f;
- last->setNext(current);
- current->setNext(firstEdge);
- f->edge = firstEdge;
- m_faceArray.push_back(f);
- return f;
- }
+ // -- GODOT end --
// These functions disconnect the given element from the mesh and delete it.
// @@ We must always disconnect edge pairs simultaneously.
- void disconnect(Edge *edge) {
+ void disconnect(Edge *edge)
+ {
xaDebugAssert(edge != NULL);
// Remove from edge list.
if ((edge->id & 1) == 0) {
@@ -1905,13 +2058,15 @@ public:
}
}
- void remove(Edge *edge) {
+ void remove(Edge *edge)
+ {
xaDebugAssert(edge != NULL);
disconnect(edge);
delete edge;
}
- void remove(Vertex *vertex) {
+ void remove(Vertex *vertex)
+ {
xaDebugAssert(vertex != NULL);
// Remove from vertex list.
m_vertexArray[vertex->id] = NULL;
@@ -1929,7 +2084,8 @@ public:
delete vertex;
}
- void remove(Face *face) {
+ void remove(Face *face)
+ {
xaDebugAssert(face != NULL);
// Remove from face list.
m_faceArray[face->id] = NULL;
@@ -1943,7 +2099,8 @@ public:
}
// Triangulate in place.
- void triangulate() {
+ void triangulate()
+ {
bool all_triangles = true;
const uint32_t faceCount = m_faceArray.size();
for (uint32_t f = 0; f < faceCount; f++) {
@@ -1984,7 +2141,8 @@ public:
}
/// Link boundary edges once the mesh has been created.
- void linkBoundary() {
+ void linkBoundary()
+ {
xaPrint("--- Linking boundaries:\n");
int num = 0;
// Create boundary edges.
@@ -2058,7 +2216,7 @@ public:
if (t > 0.0f + NV_EPSILON && t < 1.0f - NV_EPSILON) {
xaDebugAssert(equal(lerp(x1, x2, t), x0));
Vertex *splitVertex = splitBoundaryEdge(edge, t, x0);
- vertex->linkColocal(splitVertex); // @@ Should we do this here?
+ vertex->linkColocal(splitVertex); // @@ Should we do this here?
splitCount++;
}
}
@@ -2071,59 +2229,70 @@ public:
}
// Vertices
- uint32_t vertexCount() const {
+ uint32_t vertexCount() const
+ {
return m_vertexArray.size();
}
- const Vertex *vertexAt(int i) const {
+ const Vertex *vertexAt(int i) const
+ {
return m_vertexArray[i];
}
- Vertex *vertexAt(int i) {
+ Vertex *vertexAt(int i)
+ {
return m_vertexArray[i];
}
- uint32_t colocalVertexCount() const {
+ uint32_t colocalVertexCount() const
+ {
return m_colocalVertexCount;
}
// Faces
- uint32_t faceCount() const {
+ uint32_t faceCount() const
+ {
return m_faceArray.size();
}
- const Face *faceAt(int i) const {
+ const Face *faceAt(int i) const
+ {
return m_faceArray[i];
}
- Face *faceAt(int i) {
+ Face *faceAt(int i)
+ {
return m_faceArray[i];
}
// Edges
- uint32_t edgeCount() const {
+ uint32_t edgeCount() const
+ {
return m_edgeArray.size();
}
- const Edge *edgeAt(int i) const {
+ const Edge *edgeAt(int i) const
+ {
return m_edgeArray[i];
}
- Edge *edgeAt(int i) {
+ Edge *edgeAt(int i)
+ {
return m_edgeArray[i];
}
class ConstVertexIterator;
- class VertexIterator {
+ class VertexIterator
+ {
friend class ConstVertexIterator;
-
public:
- VertexIterator(Mesh *mesh) :
- m_mesh(mesh),
- m_current(0) {}
+ VertexIterator(Mesh *mesh) : m_mesh(mesh), m_current(0) { }
- virtual void advance() {
+ virtual void advance()
+ {
m_current++;
}
- virtual bool isDone() const {
+ virtual bool isDone() const
+ {
return m_current == m_mesh->vertexCount();
}
- virtual Vertex *current() const {
+ virtual Vertex *current() const
+ {
return m_mesh->vertexAt(m_current);
}
@@ -2131,26 +2300,27 @@ public:
halfedge::Mesh *m_mesh;
uint32_t m_current;
};
- VertexIterator vertices() {
+ VertexIterator vertices()
+ {
return VertexIterator(this);
}
- class ConstVertexIterator {
+ class ConstVertexIterator
+ {
public:
- ConstVertexIterator(const Mesh *mesh) :
- m_mesh(mesh),
- m_current(0) {}
- ConstVertexIterator(class VertexIterator &it) :
- m_mesh(it.m_mesh),
- m_current(it.m_current) {}
-
- virtual void advance() {
+ ConstVertexIterator(const Mesh *mesh) : m_mesh(mesh), m_current(0) { }
+ ConstVertexIterator(class VertexIterator &it) : m_mesh(it.m_mesh), m_current(it.m_current) { }
+
+ virtual void advance()
+ {
m_current++;
}
- virtual bool isDone() const {
+ virtual bool isDone() const
+ {
return m_current == m_mesh->vertexCount();
}
- virtual const Vertex *current() const {
+ virtual const Vertex *current() const
+ {
return m_mesh->vertexAt(m_current);
}
@@ -2158,27 +2328,29 @@ public:
const halfedge::Mesh *m_mesh;
uint32_t m_current;
};
- ConstVertexIterator vertices() const {
+ ConstVertexIterator vertices() const
+ {
return ConstVertexIterator(this);
}
class ConstFaceIterator;
- class FaceIterator {
+ class FaceIterator
+ {
friend class ConstFaceIterator;
-
public:
- FaceIterator(Mesh *mesh) :
- m_mesh(mesh),
- m_current(0) {}
+ FaceIterator(Mesh *mesh) : m_mesh(mesh), m_current(0) { }
- virtual void advance() {
+ virtual void advance()
+ {
m_current++;
}
- virtual bool isDone() const {
+ virtual bool isDone() const
+ {
return m_current == m_mesh->faceCount();
}
- virtual Face *current() const {
+ virtual Face *current() const
+ {
return m_mesh->faceAt(m_current);
}
@@ -2186,26 +2358,27 @@ public:
halfedge::Mesh *m_mesh;
uint32_t m_current;
};
- FaceIterator faces() {
+ FaceIterator faces()
+ {
return FaceIterator(this);
}
- class ConstFaceIterator {
+ class ConstFaceIterator
+ {
public:
- ConstFaceIterator(const Mesh *mesh) :
- m_mesh(mesh),
- m_current(0) {}
- ConstFaceIterator(const FaceIterator &it) :
- m_mesh(it.m_mesh),
- m_current(it.m_current) {}
-
- virtual void advance() {
+ ConstFaceIterator(const Mesh *mesh) : m_mesh(mesh), m_current(0) { }
+ ConstFaceIterator(const FaceIterator &it) : m_mesh(it.m_mesh), m_current(it.m_current) { }
+
+ virtual void advance()
+ {
m_current++;
}
- virtual bool isDone() const {
+ virtual bool isDone() const
+ {
return m_current == m_mesh->faceCount();
}
- virtual const Face *current() const {
+ virtual const Face *current() const
+ {
return m_mesh->faceAt(m_current);
}
@@ -2213,27 +2386,29 @@ public:
const halfedge::Mesh *m_mesh;
uint32_t m_current;
};
- ConstFaceIterator faces() const {
+ ConstFaceIterator faces() const
+ {
return ConstFaceIterator(this);
}
class ConstEdgeIterator;
- class EdgeIterator {
+ class EdgeIterator
+ {
friend class ConstEdgeIterator;
-
public:
- EdgeIterator(Mesh *mesh) :
- m_mesh(mesh),
- m_current(0) {}
+ EdgeIterator(Mesh *mesh) : m_mesh(mesh), m_current(0) { }
- virtual void advance() {
+ virtual void advance()
+ {
m_current++;
}
- virtual bool isDone() const {
+ virtual bool isDone() const
+ {
return m_current == m_mesh->edgeCount();
}
- virtual Edge *current() const {
+ virtual Edge *current() const
+ {
return m_mesh->edgeAt(m_current);
}
@@ -2241,26 +2416,27 @@ public:
halfedge::Mesh *m_mesh;
uint32_t m_current;
};
- EdgeIterator edges() {
+ EdgeIterator edges()
+ {
return EdgeIterator(this);
}
- class ConstEdgeIterator {
+ class ConstEdgeIterator
+ {
public:
- ConstEdgeIterator(const Mesh *mesh) :
- m_mesh(mesh),
- m_current(0) {}
- ConstEdgeIterator(const EdgeIterator &it) :
- m_mesh(it.m_mesh),
- m_current(it.m_current) {}
-
- virtual void advance() {
+ ConstEdgeIterator(const Mesh *mesh) : m_mesh(mesh), m_current(0) { }
+ ConstEdgeIterator(const EdgeIterator &it) : m_mesh(it.m_mesh), m_current(it.m_current) { }
+
+ virtual void advance()
+ {
m_current++;
}
- virtual bool isDone() const {
+ virtual bool isDone() const
+ {
return m_current == m_mesh->edgeCount();
}
- virtual const Edge *current() const {
+ virtual const Edge *current() const
+ {
return m_mesh->edgeAt(m_current);
}
@@ -2268,13 +2444,15 @@ public:
const halfedge::Mesh *m_mesh;
uint32_t m_current;
};
- ConstEdgeIterator edges() const {
+ ConstEdgeIterator edges() const
+ {
return ConstEdgeIterator(this);
}
// @@ Add half-edge iterator.
- bool isValid() const {
+ bool isValid() const
+ {
// Make sure all edges are valid.
const uint32_t edgeCount = m_edgeArray.size();
for (uint32_t e = 0; e < edgeCount; e++) {
@@ -2300,9 +2478,11 @@ public:
}
// Error status:
-
- struct ErrorCode {
- enum Enum {
+
+ struct ErrorCode
+ {
+ enum Enum
+ {
AlreadyAddedEdge,
DegenerateColocalEdge,
DegenerateEdge,
@@ -2316,11 +2496,13 @@ public:
private:
// Return true if the face can be added to the manifold mesh.
- bool canAddFace(const std::vector<uint32_t> &indexArray, uint32_t first, uint32_t num) const {
+ bool canAddFace(const std::vector<uint32_t> &indexArray, uint32_t first, uint32_t num) const
+ {
return canAddFace(indexArray.data(), first, num);
}
- bool canAddFace(const uint32_t *indexArray, uint32_t first, uint32_t num) const {
+ bool canAddFace(const uint32_t *indexArray, uint32_t first, uint32_t num) const
+ {
for (uint32_t j = num - 1, i = 0; i < num; j = i++) {
if (!canAddEdge(indexArray[first + j], indexArray[first + i])) {
errorIndex0 = indexArray[first + j];
@@ -2347,7 +2529,8 @@ private:
}
// Return true if the edge doesn't exist or doesn't have any adjacent face.
- bool canAddEdge(uint32_t i, uint32_t j) const {
+ bool canAddEdge(uint32_t i, uint32_t j) const
+ {
if (i == j) {
// Skip degenerate edges.
errorCode = ErrorCode::DegenerateEdge;
@@ -2373,7 +2556,8 @@ private:
return true;
}
- Edge *addEdge(uint32_t i, uint32_t j) {
+ Edge *addEdge(uint32_t i, uint32_t j)
+ {
xaAssert(i != j);
Edge *edge = findEdge(i, j);
if (edge != NULL) {
@@ -2406,7 +2590,8 @@ private:
}
/// Find edge, test all colocals.
- Edge *findEdge(uint32_t i, uint32_t j) const {
+ Edge *findEdge(uint32_t i, uint32_t j) const
+ {
Edge *edge = NULL;
const Vertex *v0 = vertexAt(i);
const Vertex *v1 = vertexAt(j);
@@ -2418,9 +2603,9 @@ private:
auto edgeIt = m_edgeMap.find(key);
if (edgeIt != m_edgeMap.end())
edge = (*edgeIt).second;
-#if !defined(_DEBUG)
+ #if !defined(_DEBUG)
if (edge != NULL) return edge;
-#endif
+ #endif
} else {
// Make sure that only one edge is found.
xaDebugAssert(m_edgeMap.find(key) == m_edgeMap.end());
@@ -2431,7 +2616,8 @@ private:
}
/// Link this boundary edge.
- void linkBoundaryEdge(Edge *edge) {
+ void linkBoundaryEdge(Edge *edge)
+ {
xaAssert(edge->face == NULL);
// Make sure next pointer has not been set. @@ We want to be able to relink boundary edges after mesh changes.
Edge *next = edge;
@@ -2451,7 +2637,8 @@ private:
}
}
- Vertex *splitBoundaryEdge(Edge *edge, float t, const Vector3 &pos) {
+ Vertex *splitBoundaryEdge(Edge *edge, float t, const Vector3 &pos)
+ {
/*
We want to go from this configuration:
@@ -2521,19 +2708,18 @@ private:
std::vector<Edge *> m_edgeArray;
std::vector<Face *> m_faceArray;
- struct Key {
+ struct Key
+ {
Key() {}
- Key(const Key &k) :
- p0(k.p0),
- p1(k.p1) {}
- Key(uint32_t v0, uint32_t v1) :
- p0(v0),
- p1(v1) {}
- void operator=(const Key &k) {
+ Key(const Key &k) : p0(k.p0), p1(k.p1) {}
+ Key(uint32_t v0, uint32_t v1) : p0(v0), p1(v1) {}
+ void operator=(const Key &k)
+ {
p0 = k.p0;
p1 = k.p1;
}
- bool operator==(const Key &k) const {
+ bool operator==(const Key &k) const
+ {
return p0 == k.p0 && p1 == k.p1;
}
@@ -2546,48 +2732,54 @@ private:
uint32_t m_colocalVertexCount;
};
-class MeshTopology {
+class MeshTopology
+{
public:
- MeshTopology(const Mesh *mesh) {
+ MeshTopology(const Mesh *mesh)
+ {
buildTopologyInfo(mesh);
}
/// Determine if the mesh is connected.
- bool isConnected() const {
+ bool isConnected() const
+ {
return m_connectedCount == 1;
}
/// Determine if the mesh is closed. (Each edge is shared by two faces)
- bool isClosed() const {
+ bool isClosed() const
+ {
return m_boundaryCount == 0;
}
/// Return true if the mesh has the topology of a disk.
- bool isDisk() const {
- return isConnected() && m_boundaryCount == 1 /* && m_eulerNumber == 1*/;
+ bool isDisk() const
+ {
+ return isConnected() && m_boundaryCount == 1/* && m_eulerNumber == 1*/;
}
private:
- void buildTopologyInfo(const Mesh *mesh) {
+ void buildTopologyInfo(const Mesh *mesh)
+ {
const uint32_t vertexCount = mesh->colocalVertexCount();
const uint32_t faceCount = mesh->faceCount();
const uint32_t edgeCount = mesh->edgeCount();
- xaPrint("--- Building mesh topology:\n");
+ xaPrint( "--- Building mesh topology:\n" );
std::vector<uint32_t> stack(faceCount);
BitArray bitFlags(faceCount);
bitFlags.clearAll();
// Compute connectivity.
- xaPrint("--- Computing connectivity.\n");
+ xaPrint( "--- Computing connectivity.\n" );
m_connectedCount = 0;
- for (uint32_t f = 0; f < faceCount; f++) {
- if (bitFlags.bitAt(f) == false) {
+ for (uint32_t f = 0; f < faceCount; f++ ) {
+ if ( bitFlags.bitAt(f) == false ) {
m_connectedCount++;
- stack.push_back(f);
- while (!stack.empty()) {
+ stack.push_back( f );
+ while ( !stack.empty() ) {
const uint32_t top = stack.back();
xaAssert(top != uint32_t(~0));
stack.pop_back();
- if (bitFlags.bitAt(top) == false) {
+ if ( bitFlags.bitAt(top) == false ) {
bitFlags.setBitAt(top);
const Face *face = mesh->faceAt(top);
const Edge *firstEdge = face->edge;
@@ -2604,9 +2796,9 @@ private:
}
}
xaAssert(stack.empty());
- xaPrint("--- %d connected components.\n", m_connectedCount);
+ xaPrint( "--- %d connected components.\n", m_connectedCount );
// Count boundary loops.
- xaPrint("--- Counting boundary loops.\n");
+ xaPrint( "--- Counting boundary loops.\n" );
m_boundaryCount = 0;
bitFlags.resize(edgeCount);
bitFlags.clearAll();
@@ -2625,13 +2817,13 @@ private:
} while (startEdge != edge);
}
}
- xaPrint("--- %d boundary loops found.\n", m_boundaryCount);
+ xaPrint("--- %d boundary loops found.\n", m_boundaryCount );
// Compute euler number.
m_eulerNumber = vertexCount - edgeCount + faceCount;
xaPrint("--- Euler number: %d.\n", m_eulerNumber);
// Compute genus. (only valid on closed connected surfaces)
m_genus = -1;
- if (isClosed() && isConnected()) {
+ if ( isClosed() && isConnected() ) {
m_genus = (2 - m_eulerNumber) / 2;
xaPrint("--- Genus: %d.\n", m_genus);
}
@@ -2651,7 +2843,8 @@ private:
int m_genus;
};
-float computeSurfaceArea(const halfedge::Mesh *mesh) {
+float computeSurfaceArea(const halfedge::Mesh *mesh)
+{
float area = 0;
for (halfedge::Mesh::ConstFaceIterator it(mesh->faces()); !it.isDone(); it.advance()) {
const halfedge::Face *face = it.current();
@@ -2661,7 +2854,8 @@ float computeSurfaceArea(const halfedge::Mesh *mesh) {
return area;
}
-float computeParametricArea(const halfedge::Mesh *mesh) {
+float computeParametricArea(const halfedge::Mesh *mesh)
+{
float area = 0;
for (halfedge::Mesh::ConstFaceIterator it(mesh->faces()); !it.isDone(); it.advance()) {
const halfedge::Face *face = it.current();
@@ -2670,7 +2864,8 @@ float computeParametricArea(const halfedge::Mesh *mesh) {
return area;
}
-uint32_t countMeshTriangles(const Mesh *mesh) {
+uint32_t countMeshTriangles(const Mesh *mesh)
+{
const uint32_t faceCount = mesh->faceCount();
uint32_t triangleCount = 0;
for (uint32_t f = 0; f < faceCount; f++) {
@@ -2682,7 +2877,8 @@ uint32_t countMeshTriangles(const Mesh *mesh) {
return triangleCount;
}
-Mesh *unifyVertices(const Mesh *inputMesh) {
+Mesh *unifyVertices(const Mesh *inputMesh)
+{
Mesh *mesh = new Mesh;
// Only add the first colocal.
const uint32_t vertexCount = inputMesh->vertexCount();
@@ -2709,15 +2905,17 @@ Mesh *unifyVertices(const Mesh *inputMesh) {
return mesh;
}
-static bool pointInTriangle(const Vector2 &p, const Vector2 &a, const Vector2 &b, const Vector2 &c) {
+static bool pointInTriangle(const Vector2 &p, const Vector2 &a, const Vector2 &b, const Vector2 &c)
+{
return triangleArea(a, b, p) >= 0.00001f &&
- triangleArea(b, c, p) >= 0.00001f &&
- triangleArea(c, a, p) >= 0.00001f;
+ triangleArea(b, c, p) >= 0.00001f &&
+ triangleArea(c, a, p) >= 0.00001f;
}
// This is doing a simple ear-clipping algorithm that skips invalid triangles. Ideally, we should
// also sort the ears by angle, start with the ones that have the smallest angle and proceed in order.
-Mesh *triangulate(const Mesh *inputMesh) {
+Mesh *triangulate(const Mesh *inputMesh)
+{
Mesh *mesh = new Mesh;
// Add all vertices.
const uint32_t vertexCount = inputMesh->vertexCount();
@@ -2782,10 +2980,12 @@ Mesh *triangulate(const Mesh *inputMesh) {
Vector2 p1 = polygonPoints[i1];
Vector2 p2 = polygonPoints[i2];
+ // -- GODOT start --
bool degenerate = distance(p0, p1) < NV_EPSILON || distance(p0, p2) < NV_EPSILON || distance(p1, p2) < NV_EPSILON;
if (degenerate) {
continue;
}
+ // -- GODOT end --
float d = clamp(dot(p0 - p1, p2 - p1) / (length(p0 - p1) * length(p2 - p1)), -1.0f, 1.0f);
float angle = acosf(d);
@@ -2810,8 +3010,10 @@ Mesh *triangulate(const Mesh *inputMesh) {
}
}
}
+ // -- GODOT start --
if (!bestIsValid)
break;
+ // -- GODOT end --
xaDebugAssert(minAngle <= 2 * PI);
// Clip best ear:
@@ -2835,59 +3037,66 @@ Mesh *triangulate(const Mesh *inputMesh) {
} // namespace halfedge
/// Mersenne twister random number generator.
-class MTRand {
+class MTRand
+{
public:
enum time_e { Time };
- enum { N = 624 }; // length of state vector
+ enum { N = 624 }; // length of state vector
enum { M = 397 };
/// Constructor that uses the current time as the seed.
- MTRand(time_e) {
- seed((uint32_t)time(NULL));
+ MTRand( time_e )
+ {
+ seed((uint32_t )time(NULL));
}
/// Constructor that uses the given seed.
- MTRand(uint32_t s = 0) {
+ MTRand( uint32_t s = 0 )
+ {
seed(s);
}
/// Provide a new seed.
- void seed(uint32_t s) {
+ void seed( uint32_t s )
+ {
initialize(s);
reload();
}
/// Get a random number between 0 - 65536.
- uint32_t get() {
+ uint32_t get()
+ {
// Pull a 32-bit integer from the generator state
// Every other access function simply transforms the numbers extracted here
- if (left == 0) {
+ if ( left == 0 ) {
reload();
}
left--;
uint32_t s1;
s1 = *next++;
s1 ^= (s1 >> 11);
- s1 ^= (s1 << 7) & 0x9d2c5680U;
+ s1 ^= (s1 << 7) & 0x9d2c5680U;
s1 ^= (s1 << 15) & 0xefc60000U;
- return (s1 ^ (s1 >> 18));
+ return ( s1 ^ (s1 >> 18) );
};
/// Get a random number on [0, max] interval.
- uint32_t getRange(uint32_t max) {
+ uint32_t getRange( uint32_t max )
+ {
if (max == 0) return 0;
if (max == NV_UINT32_MAX) return get();
- const uint32_t np2 = nextPowerOfTwo(max + 1); // @@ This fails if max == NV_UINT32_MAX
+ const uint32_t np2 = nextPowerOfTwo( max + 1 ); // @@ This fails if max == NV_UINT32_MAX
const uint32_t mask = np2 - 1;
uint32_t n;
do {
n = get() & mask;
- } while (n > max);
+ } while ( n > max );
return n;
}
private:
- void initialize(uint32_t seed) {
+ void initialize( uint32_t seed )
+ {
// Initialize generator state with seed
// See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier.
// In previous versions, most significant bits (MSBs) of the seed affect
@@ -2896,44 +3105,50 @@ private:
uint32_t *r = state;
int i = 1;
*s++ = seed & 0xffffffffUL;
- for (; i < N; ++i) {
- *s++ = (1812433253UL * (*r ^ (*r >> 30)) + i) & 0xffffffffUL;
+ for ( ; i < N; ++i ) {
+ *s++ = ( 1812433253UL * ( *r ^ (*r >> 30) ) + i ) & 0xffffffffUL;
r++;
}
}
- void reload() {
+ void reload()
+ {
// Generate N new values in state
// Made clearer and faster by Matthew Bellew (matthew.bellew@home.com)
uint32_t *p = state;
int i;
- for (i = N - M; i--; ++p)
- *p = twist(p[M], p[0], p[1]);
- for (i = M; --i; ++p)
- *p = twist(p[M - N], p[0], p[1]);
- *p = twist(p[M - N], p[0], state[0]);
+ for ( i = N - M; i--; ++p )
+ *p = twist( p[M], p[0], p[1] );
+ for ( i = M; --i; ++p )
+ *p = twist( p[M - N], p[0], p[1] );
+ *p = twist( p[M - N], p[0], state[0] );
left = N, next = state;
}
- uint32_t hiBit(uint32_t u) const {
+ uint32_t hiBit( uint32_t u ) const
+ {
return u & 0x80000000U;
}
- uint32_t loBit(uint32_t u) const {
+ uint32_t loBit( uint32_t u ) const
+ {
return u & 0x00000001U;
}
- uint32_t loBits(uint32_t u) const {
+ uint32_t loBits( uint32_t u ) const
+ {
return u & 0x7fffffffU;
}
- uint32_t mixBits(uint32_t u, uint32_t v) const {
+ uint32_t mixBits( uint32_t u, uint32_t v ) const
+ {
return hiBit(u) | loBits(v);
}
- uint32_t twist(uint32_t m, uint32_t s0, uint32_t s1) const {
+ uint32_t twist( uint32_t m, uint32_t s0, uint32_t s1 ) const
+ {
return m ^ (mixBits(s0, s1) >> 1) ^ ((~loBit(s1) + 1) & 0x9908b0dfU);
}
- uint32_t state[N]; // internal state
- uint32_t *next; // next value to get from state
- int left; // number of values left before reload needed
+ uint32_t state[N]; // internal state
+ uint32_t *next; // next value to get from state
+ int left; // number of values left before reload needed
};
namespace morton {
@@ -2941,50 +3156,59 @@ namespace morton {
// http://fgiesen.wordpress.com/2009/12/13/decoding-morton-codes/
// Inverse of part1By1 - "delete" all odd-indexed bits
-uint32_t compact1By1(uint32_t x) {
- x &= 0x55555555; // x = -f-e -d-c -b-a -9-8 -7-6 -5-4 -3-2 -1-0
- x = (x ^ (x >> 1)) & 0x33333333; // x = --fe --dc --ba --98 --76 --54 --32 --10
- x = (x ^ (x >> 2)) & 0x0f0f0f0f; // x = ---- fedc ---- ba98 ---- 7654 ---- 3210
- x = (x ^ (x >> 4)) & 0x00ff00ff; // x = ---- ---- fedc ba98 ---- ---- 7654 3210
- x = (x ^ (x >> 8)) & 0x0000ffff; // x = ---- ---- ---- ---- fedc ba98 7654 3210
+uint32_t compact1By1(uint32_t x)
+{
+ x &= 0x55555555; // x = -f-e -d-c -b-a -9-8 -7-6 -5-4 -3-2 -1-0
+ x = (x ^ (x >> 1)) & 0x33333333; // x = --fe --dc --ba --98 --76 --54 --32 --10
+ x = (x ^ (x >> 2)) & 0x0f0f0f0f; // x = ---- fedc ---- ba98 ---- 7654 ---- 3210
+ x = (x ^ (x >> 4)) & 0x00ff00ff; // x = ---- ---- fedc ba98 ---- ---- 7654 3210
+ x = (x ^ (x >> 8)) & 0x0000ffff; // x = ---- ---- ---- ---- fedc ba98 7654 3210
return x;
}
// Inverse of part1By2 - "delete" all bits not at positions divisible by 3
-uint32_t compact1By2(uint32_t x) {
- x &= 0x09249249; // x = ---- 9--8 --7- -6-- 5--4 --3- -2-- 1--0
- x = (x ^ (x >> 2)) & 0x030c30c3; // x = ---- --98 ---- 76-- --54 ---- 32-- --10
- x = (x ^ (x >> 4)) & 0x0300f00f; // x = ---- --98 ---- ---- 7654 ---- ---- 3210
- x = (x ^ (x >> 8)) & 0xff0000ff; // x = ---- --98 ---- ---- ---- ---- 7654 3210
+uint32_t compact1By2(uint32_t x)
+{
+ x &= 0x09249249; // x = ---- 9--8 --7- -6-- 5--4 --3- -2-- 1--0
+ x = (x ^ (x >> 2)) & 0x030c30c3; // x = ---- --98 ---- 76-- --54 ---- 32-- --10
+ x = (x ^ (x >> 4)) & 0x0300f00f; // x = ---- --98 ---- ---- 7654 ---- ---- 3210
+ x = (x ^ (x >> 8)) & 0xff0000ff; // x = ---- --98 ---- ---- ---- ---- 7654 3210
x = (x ^ (x >> 16)) & 0x000003ff; // x = ---- ---- ---- ---- ---- --98 7654 3210
return x;
}
-uint32_t decodeMorton2X(uint32_t code) {
+uint32_t decodeMorton2X(uint32_t code)
+{
return compact1By1(code >> 0);
}
-uint32_t decodeMorton2Y(uint32_t code) {
+uint32_t decodeMorton2Y(uint32_t code)
+{
return compact1By1(code >> 1);
}
-uint32_t decodeMorton3X(uint32_t code) {
+uint32_t decodeMorton3X(uint32_t code)
+{
return compact1By2(code >> 0);
}
-uint32_t decodeMorton3Y(uint32_t code) {
+uint32_t decodeMorton3Y(uint32_t code)
+{
return compact1By2(code >> 1);
}
-uint32_t decodeMorton3Z(uint32_t code) {
+uint32_t decodeMorton3Z(uint32_t code)
+{
return compact1By2(code >> 2);
}
} // namespace morton
// A simple, dynamic proximity grid based on Jon's code.
// Instead of storing pointers here I store indices.
-struct ProximityGrid {
- void init(const Box &box, uint32_t count) {
+struct ProximityGrid
+{
+ void init(const Box &box, uint32_t count)
+ {
cellArray.clear();
// Determine grid size.
float cellWidth;
@@ -3021,19 +3245,23 @@ struct ProximityGrid {
corner = box.minCorner; // @@ Align grid better?
}
- int index_x(float x) const {
- return clamp(ftoi_floor((x - corner.x) * invCellSize.x), 0, sx - 1);
+ int index_x(float x) const
+ {
+ return clamp(ftoi_floor((x - corner.x) * invCellSize.x), 0, sx - 1);
}
- int index_y(float y) const {
- return clamp(ftoi_floor((y - corner.y) * invCellSize.y), 0, sy - 1);
+ int index_y(float y) const
+ {
+ return clamp(ftoi_floor((y - corner.y) * invCellSize.y), 0, sy - 1);
}
- int index_z(float z) const {
- return clamp(ftoi_floor((z - corner.z) * invCellSize.z), 0, sz - 1);
+ int index_z(float z) const
+ {
+ return clamp(ftoi_floor((z - corner.z) * invCellSize.z), 0, sz - 1);
}
- int index(int x, int y, int z) const {
+ int index(int x, int y, int z) const
+ {
xaDebugAssert(x >= 0 && x < sx);
xaDebugAssert(y >= 0 && y < sy);
xaDebugAssert(z >= 0 && z < sz);
@@ -3042,7 +3270,8 @@ struct ProximityGrid {
return idx;
}
- uint32_t mortonCount() const {
+ uint32_t mortonCount() const
+ {
uint64_t s = uint64_t(max3(sx, sy, sz));
s = nextPowerOfTwo(s);
if (s > 1024) {
@@ -3051,7 +3280,8 @@ struct ProximityGrid {
return uint32_t(s * s * s);
}
- int mortonIndex(uint32_t code) const {
+ int mortonIndex(uint32_t code) const
+ {
uint32_t x, y, z;
uint32_t s = uint32_t(max3(sx, sy, sz));
if (s > 1024) {
@@ -3084,7 +3314,8 @@ struct ProximityGrid {
return index(x, y, z);
}
- void add(const Vector3 &pos, uint32_t key) {
+ void add(const Vector3 &pos, uint32_t key)
+ {
int x = index_x(pos.x);
int y = index_y(pos.y);
int z = index_z(pos.z);
@@ -3094,7 +3325,8 @@ struct ProximityGrid {
// Gather all points inside the given sphere.
// Radius is assumed to be small, so we don't bother culling the cells.
- void gather(const Vector3 &position, float radius, std::vector<uint32_t> &indexArray) {
+ void gather(const Vector3 &position, float radius, std::vector<uint32_t> &indexArray)
+ {
int x0 = index_x(position.x - radius);
int x1 = index_x(position.x + radius);
int y0 = index_y(position.y - radius);
@@ -3125,26 +3357,25 @@ struct ProximityGrid {
// Based on Pierre Terdiman's and Michael Herf's source code.
// http://www.codercorner.com/RadixSortRevisited.htm
// http://www.stereopsis.com/radix.html
-class RadixSort {
+class RadixSort
+{
public:
- RadixSort() :
- m_size(0),
- m_ranks(NULL),
- m_ranks2(NULL),
- m_validRanks(false) {}
- ~RadixSort() {
+ RadixSort() : m_size(0), m_ranks(NULL), m_ranks2(NULL), m_validRanks(false) {}
+ ~RadixSort()
+ {
// Release everything
free(m_ranks2);
free(m_ranks);
}
- RadixSort &sort(const float *input, uint32_t count) {
+ RadixSort &sort(const float *input, uint32_t count)
+ {
if (input == NULL || count == 0) return *this;
// Resize lists if needed
if (count != m_size) {
if (count > m_size) {
- m_ranks2 = (uint32_t *)realloc(m_ranks2, sizeof(uint32_t) * count);
- m_ranks = (uint32_t *)realloc(m_ranks, sizeof(uint32_t) * count);
+ m_ranks2 = (uint32_t *)realloc(m_ranks2, sizeof(uint32_t ) * count);
+ m_ranks = (uint32_t *)realloc(m_ranks, sizeof(uint32_t ) * count);
}
m_size = count;
m_validRanks = false;
@@ -3164,16 +3395,19 @@ public:
return *this;
}
- RadixSort &sort(const std::vector<float> &input) {
+ RadixSort &sort(const std::vector<float> &input)
+ {
return sort(input.data(), input.size());
}
// Access to results. m_ranks is a list of indices in sorted order, i.e. in the order you may further process your data
- const uint32_t *ranks() const {
+ const uint32_t *ranks() const
+ {
xaDebugAssert(m_validRanks);
return m_ranks;
}
- uint32_t *ranks() {
+ uint32_t *ranks()
+ {
xaDebugAssert(m_validRanks);
return m_ranks;
}
@@ -3184,18 +3418,21 @@ private:
uint32_t *m_ranks2;
bool m_validRanks;
- void FloatFlip(uint32_t &f) {
+ void FloatFlip(uint32_t &f)
+ {
int32_t mask = (int32_t(f) >> 31) | 0x80000000; // Warren Hunt, Manchor Ko.
f ^= mask;
}
- void IFloatFlip(uint32_t &f) {
+ void IFloatFlip(uint32_t &f)
+ {
uint32_t mask = ((f >> 31) - 1) | 0x80000000; // Michael Herf.
f ^= mask;
}
- template <typename T>
- void createHistograms(const T *buffer, uint32_t count, uint32_t *histogram) {
+ template<typename T>
+ void createHistograms(const T *buffer, uint32_t count, uint32_t *histogram)
+ {
const uint32_t bucketCount = sizeof(T); // (8 * sizeof(T)) / log2(radix)
// Init bucket pointers.
uint32_t *h[bucketCount];
@@ -3203,10 +3440,10 @@ private:
h[i] = histogram + 256 * i;
}
// Clear histograms.
- memset(histogram, 0, 256 * bucketCount * sizeof(uint32_t));
+ memset(histogram, 0, 256 * bucketCount * sizeof(uint32_t ));
// @@ Add support for signed integers.
// Build histograms.
- const uint8_t *p = (const uint8_t *)buffer; // @@ Does this break aliasing rules?
+ const uint8_t *p = (const uint8_t *)buffer; // @@ Does this break aliasing rules?
const uint8_t *pe = p + count * sizeof(T);
while (p != pe) {
h[0][*p++]++, h[1][*p++]++, h[2][*p++]++, h[3][*p++]++;
@@ -3221,8 +3458,8 @@ private:
}
}
- template <typename T>
- void insertionSort(const T *input, uint32_t count) {
+ template <typename T> void insertionSort(const T *input, uint32_t count)
+ {
if (!m_validRanks) {
m_ranks[0] = 0;
for (uint32_t i = 1; i != count; ++i) {
@@ -3252,8 +3489,8 @@ private:
}
}
- template <typename T>
- void radixSort(const T *input, uint32_t count) {
+ template <typename T> void radixSort(const T *input, uint32_t count)
+ {
const uint32_t P = sizeof(T); // pass count
// Allocate histograms & offsets on the stack
uint32_t histogram[256 * P];
@@ -3271,8 +3508,7 @@ private:
}
// Create offsets
link[0] = m_ranks2;
- for (uint32_t i = 1; i < 256; i++)
- link[i] = link[i - 1] + h[i - 1];
+ for (uint32_t i = 1; i < 256; i++) link[i] = link[i - 1] + h[i - 1];
// Perform Radix Sort
if (!m_validRanks) {
for (uint32_t i = 0; i < count; i++) {
@@ -3299,9 +3535,11 @@ private:
};
namespace raster {
-class ClippedTriangle {
+class ClippedTriangle
+{
public:
- ClippedTriangle(Vector2::Arg a, Vector2::Arg b, Vector2::Arg c) {
+ ClippedTriangle(Vector2::Arg a, Vector2::Arg b, Vector2::Arg c)
+ {
m_numVertices = 3;
m_activeVertexBuffer = 0;
m_verticesA[0] = a;
@@ -3311,27 +3549,30 @@ public:
m_vertexBuffers[1] = m_verticesB;
}
- uint32_t vertexCount() {
+ uint32_t vertexCount()
+ {
return m_numVertices;
}
- const Vector2 *vertices() {
+ const Vector2 *vertices()
+ {
return m_vertexBuffers[m_activeVertexBuffer];
}
- void clipHorizontalPlane(float offset, float clipdirection) {
- Vector2 *v = m_vertexBuffers[m_activeVertexBuffer];
+ void clipHorizontalPlane(float offset, float clipdirection)
+ {
+ Vector2 *v = m_vertexBuffers[m_activeVertexBuffer];
m_activeVertexBuffer ^= 1;
Vector2 *v2 = m_vertexBuffers[m_activeVertexBuffer];
v[m_numVertices] = v[0];
- float dy2, dy1 = offset - v[0].y;
- int dy2in, dy1in = clipdirection * dy1 >= 0;
- uint32_t p = 0;
+ float dy2, dy1 = offset - v[0].y;
+ int dy2in, dy1in = clipdirection * dy1 >= 0;
+ uint32_t p = 0;
for (uint32_t k = 0; k < m_numVertices; k++) {
- dy2 = offset - v[k + 1].y;
+ dy2 = offset - v[k + 1].y;
dy2in = clipdirection * dy2 >= 0;
if (dy1in) v2[p++] = v[k];
- if (dy1in + dy2in == 1) { // not both in/out
+ if ( dy1in + dy2in == 1 ) { // not both in/out
float dx = v[k + 1].x - v[k].x;
float dy = v[k + 1].y - v[k].y;
v2[p++] = Vector2(v[k].x + dy1 * (dx / dy), offset);
@@ -3343,19 +3584,20 @@ public:
//for (uint32_t k=0; k<m_numVertices; k++) printf("(%f, %f)\n", v2[k].x, v2[k].y); printf("\n");
}
- void clipVerticalPlane(float offset, float clipdirection) {
- Vector2 *v = m_vertexBuffers[m_activeVertexBuffer];
+ void clipVerticalPlane(float offset, float clipdirection )
+ {
+ Vector2 *v = m_vertexBuffers[m_activeVertexBuffer];
m_activeVertexBuffer ^= 1;
Vector2 *v2 = m_vertexBuffers[m_activeVertexBuffer];
v[m_numVertices] = v[0];
- float dx2, dx1 = offset - v[0].x;
- int dx2in, dx1in = clipdirection * dx1 >= 0;
- uint32_t p = 0;
+ float dx2, dx1 = offset - v[0].x;
+ int dx2in, dx1in = clipdirection * dx1 >= 0;
+ uint32_t p = 0;
for (uint32_t k = 0; k < m_numVertices; k++) {
dx2 = offset - v[k + 1].x;
dx2in = clipdirection * dx2 >= 0;
if (dx1in) v2[p++] = v[k];
- if (dx1in + dx2in == 1) { // not both in/out
+ if ( dx1in + dx2in == 1 ) { // not both in/out
float dx = v[k + 1].x - v[k].x;
float dy = v[k + 1].y - v[k].y;
v2[p++] = Vector2(offset, v[k].y + dx1 * (dy / dx));
@@ -3366,8 +3608,9 @@ public:
m_numVertices = p;
}
- void computeAreaCentroid() {
- Vector2 *v = m_vertexBuffers[m_activeVertexBuffer];
+ void computeAreaCentroid()
+ {
+ Vector2 *v = m_vertexBuffers[m_activeVertexBuffer];
v[m_numVertices] = v[0];
m_area = 0;
float centroidx = 0, centroidy = 0;
@@ -3386,19 +3629,22 @@ public:
}
}
- void clipAABox(float x0, float y0, float x1, float y1) {
- clipVerticalPlane(x0, -1);
- clipHorizontalPlane(y0, -1);
- clipVerticalPlane(x1, 1);
- clipHorizontalPlane(y1, 1);
+ void clipAABox(float x0, float y0, float x1, float y1)
+ {
+ clipVerticalPlane ( x0, -1);
+ clipHorizontalPlane( y0, -1);
+ clipVerticalPlane ( x1, 1);
+ clipHorizontalPlane( y1, 1);
computeAreaCentroid();
}
- Vector2 centroid() {
+ Vector2 centroid()
+ {
return m_centroid;
}
- float area() {
+ float area()
+ {
return m_area;
}
@@ -3406,18 +3652,20 @@ private:
Vector2 m_verticesA[7 + 1];
Vector2 m_verticesB[7 + 1];
Vector2 *m_vertexBuffers[2];
- uint32_t m_numVertices;
- uint32_t m_activeVertexBuffer;
- float m_area;
+ uint32_t m_numVertices;
+ uint32_t m_activeVertexBuffer;
+ float m_area;
Vector2 m_centroid;
};
/// A callback to sample the environment. Return false to terminate rasterization.
-typedef bool (*SamplingCallback)(void *param, int x, int y, Vector3::Arg bar, Vector3::Arg dx, Vector3::Arg dy, float coverage);
+typedef bool (* SamplingCallback)(void *param, int x, int y, Vector3::Arg bar, Vector3::Arg dx, Vector3::Arg dy, float coverage);
/// A triangle for rasterization.
-struct Triangle {
- Triangle(Vector2::Arg v0, Vector2::Arg v1, Vector2::Arg v2, Vector3::Arg t0, Vector3::Arg t1, Vector3::Arg t2) {
+struct Triangle
+{
+ Triangle(Vector2::Arg v0, Vector2::Arg v1, Vector2::Arg v2, Vector3::Arg t0, Vector3::Arg t1, Vector3::Arg t2)
+ {
// Init vertices.
this->v1 = v0;
this->v2 = v2;
@@ -3437,7 +3685,8 @@ struct Triangle {
/// This method takes two edge vectors that form a basis, determines the
/// coordinates of the canonic vectors in that basis, and computes the
/// texture gradient that corresponds to those vectors.
- bool computeDeltas() {
+ bool computeDeltas()
+ {
Vector2 e0 = v3 - v1;
Vector2 e1 = v2 - v1;
Vector3 de0 = t3 - t1;
@@ -3446,16 +3695,17 @@ struct Triangle {
if (!std::isfinite(denom)) {
return false;
}
- float lambda1 = -e1.y * denom;
+ float lambda1 = - e1.y * denom;
float lambda2 = e0.y * denom;
float lambda3 = e1.x * denom;
- float lambda4 = -e0.x * denom;
+ float lambda4 = - e0.x * denom;
dx = de0 * lambda1 + de1 * lambda2;
dy = de0 * lambda3 + de1 * lambda4;
return true;
}
- bool draw(const Vector2 &extents, bool enableScissors, SamplingCallback cb, void *param) {
+ bool draw(const Vector2 &extents, bool enableScissors, SamplingCallback cb, void *param)
+ {
// 28.4 fixed-point coordinates
const int Y1 = ftoi_round(16.0f * v1.y);
const int Y2 = ftoi_round(16.0f * v2.y);
@@ -3479,10 +3729,10 @@ struct Triangle {
const int FDY31 = DY31 << 4;
int minx, miny, maxx, maxy;
if (enableScissors) {
- int frustumX0 = 0 << 4;
- int frustumY0 = 0 << 4;
- int frustumX1 = (int)extents.x << 4;
- int frustumY1 = (int)extents.y << 4;
+ int frustumX0 = 0 << 4;
+ int frustumY0 = 0 << 4;
+ int frustumX1 = (int)extents.x << 4;
+ int frustumY1 = (int)extents.y << 4;
// Bounding rectangle
minx = (std::max(min3(X1, X2, X3), frustumX0) + 0xF) >> 4;
miny = (std::max(min3(Y1, Y2, Y3), frustumY0) + 0xF) >> 4;
@@ -3586,26 +3836,27 @@ struct Triangle {
}
// extents has to be multiple of BK_SIZE!!
- bool drawAA(const Vector2 &extents, bool enableScissors, SamplingCallback cb, void *param) {
- const float PX_INSIDE = 1.0f / sqrt(2.0f);
- const float PX_OUTSIDE = -1.0f / sqrt(2.0f);
+ bool drawAA(const Vector2 &extents, bool enableScissors, SamplingCallback cb, void *param)
+ {
+ const float PX_INSIDE = 1.0f/sqrt(2.0f);
+ const float PX_OUTSIDE = -1.0f/sqrt(2.0f);
const float BK_SIZE = 8;
- const float BK_INSIDE = sqrt(BK_SIZE * BK_SIZE / 2.0f);
- const float BK_OUTSIDE = -sqrt(BK_SIZE * BK_SIZE / 2.0f);
+ const float BK_INSIDE = sqrt(BK_SIZE*BK_SIZE/2.0f);
+ const float BK_OUTSIDE = -sqrt(BK_SIZE*BK_SIZE/2.0f);
float minx, miny, maxx, maxy;
if (enableScissors) {
// Bounding rectangle
minx = floorf(std::max(min3(v1.x, v2.x, v3.x), 0.0f));
miny = floorf(std::max(min3(v1.y, v2.y, v3.y), 0.0f));
- maxx = ceilf(std::min(max3(v1.x, v2.x, v3.x), extents.x - 1.0f));
- maxy = ceilf(std::min(max3(v1.y, v2.y, v3.y), extents.y - 1.0f));
+ maxx = ceilf( std::min(max3(v1.x, v2.x, v3.x), extents.x - 1.0f));
+ maxy = ceilf( std::min(max3(v1.y, v2.y, v3.y), extents.y - 1.0f));
} else {
// Bounding rectangle
minx = floorf(min3(v1.x, v2.x, v3.x));
miny = floorf(min3(v1.y, v2.y, v3.y));
- maxx = ceilf(max3(v1.x, v2.x, v3.x));
- maxy = ceilf(max3(v1.y, v2.y, v3.y));
+ maxx = ceilf( max3(v1.x, v2.x, v3.x));
+ maxy = ceilf( max3(v1.y, v2.y, v3.y));
}
// There's no reason to align the blocks to the viewport, instead we align them to the origin of the triangle bounds.
minx = floorf(minx);
@@ -3631,9 +3882,9 @@ struct Triangle {
float bC = C2 + n2.x * xc + n2.y * yc;
float cC = C3 + n3.x * xc + n3.y * yc;
// Skip block when outside an edge
- if ((aC <= BK_OUTSIDE) || (bC <= BK_OUTSIDE) || (cC <= BK_OUTSIDE)) continue;
+ if ( (aC <= BK_OUTSIDE) || (bC <= BK_OUTSIDE) || (cC <= BK_OUTSIDE) ) continue;
// Accept whole block when totally covered
- if ((aC >= BK_INSIDE) && (bC >= BK_INSIDE) && (cC >= BK_INSIDE)) {
+ if ( (aC >= BK_INSIDE) && (bC >= BK_INSIDE) && (cC >= BK_INSIDE) ) {
Vector3 texRow = t1 + dy * (y0 - v1.y) + dx * (x0 - v1.x);
for (float y = y0; y < y0 + BK_SIZE; y++) {
Vector3 tex = texRow;
@@ -3695,9 +3946,10 @@ struct Triangle {
return true;
}
- void flipBackface() {
+ void flipBackface()
+ {
// check if triangle is backfacing, if so, swap two vertices
- if (((v3.x - v1.x) * (v2.y - v1.y) - (v3.y - v1.y) * (v2.x - v1.x)) < 0) {
+ if ( ((v3.x - v1.x) * (v2.y - v1.y) - (v3.y - v1.y) * (v2.x - v1.x)) < 0 ) {
Vector2 hv = v1;
v1 = v2;
v2 = hv; // swap pos
@@ -3708,7 +3960,8 @@ struct Triangle {
}
// compute unit inward normals for each edge.
- void computeUnitInwardNormals() {
+ void computeUnitInwardNormals()
+ {
n1 = v1 - v2;
n1 = Vector2(-n1.y, n1.x);
n1 = n1 * (1.0f / sqrtf(n1.x * n1.x + n1.y * n1.y));
@@ -3732,13 +3985,15 @@ struct Triangle {
bool valid;
};
-enum Mode {
+enum Mode
+{
Mode_Nearest,
Mode_Antialiased
};
// Process the given triangle. Returns false if rasterization was interrupted by the callback.
-static bool drawTriangle(Mode mode, Vector2::Arg extents, bool enableScissors, const Vector2 v[3], SamplingCallback cb, void *param) {
+static bool drawTriangle(Mode mode, Vector2::Arg extents, bool enableScissors, const Vector2 v[3], SamplingCallback cb, void *param)
+{
Triangle tri(v[0], v[1], v[2], Vector3(1, 0, 0), Vector3(0, 1, 0), Vector3(0, 0, 1));
// @@ It would be nice to have a conservative drawing mode that enlarges the triangle extents by one texel and is able to handle degenerate triangles.
// @@ Maybe the simplest thing to do would be raster triangle edges.
@@ -3754,7 +4009,8 @@ static bool drawTriangle(Mode mode, Vector2::Arg extents, bool enableScissors, c
}
// Process the given quad. Returns false if rasterization was interrupted by the callback.
-static bool drawQuad(Mode mode, Vector2::Arg extents, bool enableScissors, const Vector2 v[4], SamplingCallback cb, void *param) {
+static bool drawQuad(Mode mode, Vector2::Arg extents, bool enableScissors, const Vector2 v[4], SamplingCallback cb, void *param)
+{
bool sign0 = triangleArea2(v[0], v[1], v[2]) > 0.0f;
bool sign1 = triangleArea2(v[0], v[2], v[3]) > 0.0f;
// Divide the quad into two non overlapping triangles.
@@ -3786,7 +4042,8 @@ static bool drawQuad(Mode mode, Vector2::Arg extents, bool enableScissors, const
// Full and sparse vector and matrix classes. BLAS subset.
// Pseudo-BLAS interface.
namespace sparse {
-enum Transpose {
+enum Transpose
+{
NoTransposed = 0,
Transposed = 1
};
@@ -3799,22 +4056,22 @@ enum Transpose {
* elements for each row of the matrix. As with the FullVector the
* dimension of the matrix is constant.
**/
-class Matrix {
+class Matrix
+{
public:
// An element of the sparse array.
- struct Coefficient {
- uint32_t x; // column
+ struct Coefficient
+ {
+ uint32_t x; // column
float v; // value
};
- Matrix(uint32_t d) :
- m_width(d) { m_array.resize(d); }
- Matrix(uint32_t w, uint32_t h) :
- m_width(w) { m_array.resize(h); }
- Matrix(const Matrix &m) :
- m_width(m.m_width) { m_array = m.m_array; }
+ Matrix(uint32_t d) : m_width(d) { m_array.resize(d); }
+ Matrix(uint32_t w, uint32_t h) : m_width(w) { m_array.resize(h); }
+ Matrix(const Matrix &m) : m_width(m.m_width) { m_array = m.m_array; }
- const Matrix &operator=(const Matrix &m) {
+ const Matrix &operator=(const Matrix &m)
+ {
xaAssert(width() == m.width());
xaAssert(height() == m.height());
m_array = m.m_array;
@@ -3826,9 +4083,10 @@ public:
bool isSquare() const { return width() == height(); }
// x is column, y is row
- float getCoefficient(uint32_t x, uint32_t y) const {
- xaDebugAssert(x < width());
- xaDebugAssert(y < height());
+ float getCoefficient(uint32_t x, uint32_t y) const
+ {
+ xaDebugAssert( x < width() );
+ xaDebugAssert( y < height() );
const uint32_t count = m_array[y].size();
for (uint32_t i = 0; i < count; i++) {
if (m_array[y][i].x == x) return m_array[y][i].v;
@@ -3836,9 +4094,10 @@ public:
return 0.0f;
}
- void setCoefficient(uint32_t x, uint32_t y, float f) {
- xaDebugAssert(x < width());
- xaDebugAssert(y < height());
+ void setCoefficient(uint32_t x, uint32_t y, float f)
+ {
+ xaDebugAssert( x < width() );
+ xaDebugAssert( y < height() );
const uint32_t count = m_array[y].size();
for (uint32_t i = 0; i < count; i++) {
if (m_array[y][i].x == x) {
@@ -3848,12 +4107,13 @@ public:
}
if (f != 0.0f) {
Coefficient c = { x, f };
- m_array[y].push_back(c);
+ m_array[y].push_back( c );
}
}
- float dotRow(uint32_t y, const FullVector &v) const {
- xaDebugAssert(y < height());
+ float dotRow(uint32_t y, const FullVector &v) const
+ {
+ xaDebugAssert( y < height() );
const uint32_t count = m_array[y].size();
float sum = 0;
for (uint32_t i = 0; i < count; i++) {
@@ -3862,7 +4122,8 @@ public:
return sum;
}
- void madRow(uint32_t y, float alpha, FullVector &v) const {
+ void madRow(uint32_t y, float alpha, FullVector &v) const
+ {
xaDebugAssert(y < height());
const uint32_t count = m_array[y].size();
for (uint32_t i = 0; i < count; i++) {
@@ -3870,13 +4131,15 @@ public:
}
}
- void clearRow(uint32_t y) {
- xaDebugAssert(y < height());
+ void clearRow(uint32_t y)
+ {
+ xaDebugAssert( y < height() );
m_array[y].clear();
}
- void scaleRow(uint32_t y, float f) {
- xaDebugAssert(y < height());
+ void scaleRow(uint32_t y, float f)
+ {
+ xaDebugAssert( y < height() );
const uint32_t count = m_array[y].size();
for (uint32_t i = 0; i < count; i++) {
m_array[y][i].v *= f;
@@ -3890,11 +4153,12 @@ private:
const uint32_t m_width;
/// Array of matrix elements.
- std::vector<std::vector<Coefficient> > m_array;
+ std::vector< std::vector<Coefficient> > m_array;
};
// y = a * x + y
-static void saxpy(float a, const FullVector &x, FullVector &y) {
+static void saxpy(float a, const FullVector &x, FullVector &y)
+{
xaDebugAssert(x.dimension() == y.dimension());
const uint32_t dim = x.dimension();
for (uint32_t i = 0; i < dim; i++) {
@@ -3902,7 +4166,8 @@ static void saxpy(float a, const FullVector &x, FullVector &y) {
}
}
-static void copy(const FullVector &x, FullVector &y) {
+static void copy(const FullVector &x, FullVector &y)
+{
xaDebugAssert(x.dimension() == y.dimension());
const uint32_t dim = x.dimension();
for (uint32_t i = 0; i < dim; i++) {
@@ -3910,14 +4175,16 @@ static void copy(const FullVector &x, FullVector &y) {
}
}
-static void scal(float a, FullVector &x) {
+static void scal(float a, FullVector &x)
+{
const uint32_t dim = x.dimension();
for (uint32_t i = 0; i < dim; i++) {
x[i] *= a;
}
}
-static float dot(const FullVector &x, const FullVector &y) {
+static float dot(const FullVector &x, const FullVector &y)
+{
xaDebugAssert(x.dimension() == y.dimension());
const uint32_t dim = x.dimension();
float sum = 0;
@@ -3927,19 +4194,20 @@ static float dot(const FullVector &x, const FullVector &y) {
return sum;
}
-static void mult(Transpose TM, const Matrix &M, const FullVector &x, FullVector &y) {
+static void mult(Transpose TM, const Matrix &M, const FullVector &x, FullVector &y)
+{
const uint32_t w = M.width();
const uint32_t h = M.height();
if (TM == Transposed) {
- xaDebugAssert(h == x.dimension());
- xaDebugAssert(w == y.dimension());
+ xaDebugAssert( h == x.dimension() );
+ xaDebugAssert( w == y.dimension() );
y.fill(0.0f);
for (uint32_t i = 0; i < h; i++) {
M.madRow(i, x[i], y);
}
} else {
- xaDebugAssert(w == x.dimension());
- xaDebugAssert(h == y.dimension());
+ xaDebugAssert( w == x.dimension() );
+ xaDebugAssert( h == y.dimension() );
for (uint32_t i = 0; i < h; i++) {
y[i] = M.dotRow(i, x);
}
@@ -3947,22 +4215,24 @@ static void mult(Transpose TM, const Matrix &M, const FullVector &x, FullVector
}
// y = M * x
-static void mult(const Matrix &M, const FullVector &x, FullVector &y) {
+static void mult(const Matrix &M, const FullVector &x, FullVector &y)
+{
mult(NoTransposed, M, x, y);
}
-static void sgemv(float alpha, Transpose TA, const Matrix &A, const FullVector &x, float beta, FullVector &y) {
+static void sgemv(float alpha, Transpose TA, const Matrix &A, const FullVector &x, float beta, FullVector &y)
+{
const uint32_t w = A.width();
const uint32_t h = A.height();
if (TA == Transposed) {
- xaDebugAssert(h == x.dimension());
- xaDebugAssert(w == y.dimension());
+ xaDebugAssert( h == x.dimension() );
+ xaDebugAssert( w == y.dimension() );
for (uint32_t i = 0; i < h; i++) {
A.madRow(i, alpha * x[i], y);
}
} else {
- xaDebugAssert(w == x.dimension());
- xaDebugAssert(h == y.dimension());
+ xaDebugAssert( w == x.dimension() );
+ xaDebugAssert( h == y.dimension() );
for (uint32_t i = 0; i < h; i++) {
y[i] = alpha * A.dotRow(i, x) + beta * y[i];
}
@@ -3970,12 +4240,14 @@ static void sgemv(float alpha, Transpose TA, const Matrix &A, const FullVector &
}
// y = alpha*A*x + beta*y
-static void sgemv(float alpha, const Matrix &A, const FullVector &x, float beta, FullVector &y) {
+static void sgemv(float alpha, const Matrix &A, const FullVector &x, float beta, FullVector &y)
+{
sgemv(alpha, NoTransposed, A, x, beta, y);
}
// dot y-row of A by x-column of B
-static float dotRowColumn(int y, const Matrix &A, int x, const Matrix &B) {
+static float dotRowColumn(int y, const Matrix &A, int x, const Matrix &B)
+{
const std::vector<Matrix::Coefficient> &row = A.getRow(y);
const uint32_t count = row.size();
float sum = 0.0f;
@@ -3987,7 +4259,8 @@ static float dotRowColumn(int y, const Matrix &A, int x, const Matrix &B) {
}
// dot y-row of A by x-row of B
-static float dotRowRow(int y, const Matrix &A, int x, const Matrix &B) {
+static float dotRowRow(int y, const Matrix &A, int x, const Matrix &B)
+{
const std::vector<Matrix::Coefficient> &row = A.getRow(y);
const uint32_t count = row.size();
float sum = 0.0f;
@@ -3999,7 +4272,8 @@ static float dotRowRow(int y, const Matrix &A, int x, const Matrix &B) {
}
// dot y-column of A by x-column of B
-static float dotColumnColumn(int y, const Matrix &A, int x, const Matrix &B) {
+static float dotColumnColumn(int y, const Matrix &A, int x, const Matrix &B)
+{
xaDebugAssert(A.height() == B.height());
const uint32_t h = A.height();
float sum = 0.0f;
@@ -4009,7 +4283,8 @@ static float dotColumnColumn(int y, const Matrix &A, int x, const Matrix &B) {
return sum;
}
-static void transpose(const Matrix &A, Matrix &B) {
+static void transpose(const Matrix &A, Matrix &B)
+{
xaDebugAssert(A.width() == B.height());
xaDebugAssert(B.width() == A.height());
const uint32_t w = A.width();
@@ -4028,7 +4303,8 @@ static void transpose(const Matrix &A, Matrix &B) {
}
}
-static void sgemm(float alpha, Transpose TA, const Matrix &A, Transpose TB, const Matrix &B, float beta, Matrix &C) {
+static void sgemm(float alpha, Transpose TA, const Matrix &A, Transpose TB, const Matrix &B, float beta, Matrix &C)
+{
const uint32_t w = C.width();
const uint32_t h = C.height();
uint32_t aw = (TA == NoTransposed) ? A.width() : A.height();
@@ -4063,21 +4339,24 @@ static void sgemm(float alpha, Transpose TA, const Matrix &A, Transpose TB, cons
}
}
-static void mult(Transpose TA, const Matrix &A, Transpose TB, const Matrix &B, Matrix &C) {
+static void mult(Transpose TA, const Matrix &A, Transpose TB, const Matrix &B, Matrix &C)
+{
sgemm(1.0f, TA, A, TB, B, 0.0f, C);
}
// C = A * B
-static void mult(const Matrix &A, const Matrix &B, Matrix &C) {
+static void mult(const Matrix &A, const Matrix &B, Matrix &C)
+{
mult(NoTransposed, A, NoTransposed, B, C);
}
} // namespace sparse
-class JacobiPreconditioner {
+class JacobiPreconditioner
+{
public:
- JacobiPreconditioner(const sparse::Matrix &M, bool symmetric) :
- m_inverseDiagonal(M.width()) {
+ JacobiPreconditioner(const sparse::Matrix &M, bool symmetric) : m_inverseDiagonal(M.width())
+ {
xaAssert(M.isSquare());
for (uint32_t x = 0; x < M.width(); x++) {
float elem = M.getCoefficient(x, x);
@@ -4090,7 +4369,8 @@ public:
}
}
- void apply(const FullVector &x, FullVector &y) const {
+ void apply(const FullVector &x, FullVector &y) const
+ {
xaDebugAssert(x.dimension() == m_inverseDiagonal.dimension());
xaDebugAssert(y.dimension() == m_inverseDiagonal.dimension());
// @@ Wrap vector component-wise product into a separate function.
@@ -4105,10 +4385,12 @@ private:
};
// Linear solvers.
-class Solver {
+class Solver
+{
public:
- // Solve the symmetric system: At·A·x = At·b
- static bool LeastSquaresSolver(const sparse::Matrix &A, const FullVector &b, FullVector &x, float epsilon = 1e-5f) {
+ // Solve the symmetric system: At·A·x = At·b
+ static bool LeastSquaresSolver(const sparse::Matrix &A, const FullVector &b, FullVector &x, float epsilon = 1e-5f)
+ {
xaDebugAssert(A.width() == x.dimension());
xaDebugAssert(A.height() == b.dimension());
xaDebugAssert(A.height() >= A.width()); // @@ If height == width we could solve it directly...
@@ -4123,7 +4405,8 @@ public:
}
// See section 10.4.3 in: Mesh Parameterization: Theory and Practice, Siggraph Course Notes, August 2007
- static bool LeastSquaresSolver(const sparse::Matrix &A, const FullVector &b, FullVector &x, const uint32_t *lockedParameters, uint32_t lockedCount, float epsilon = 1e-5f) {
+ static bool LeastSquaresSolver(const sparse::Matrix &A, const FullVector &b, FullVector &x, const uint32_t *lockedParameters, uint32_t lockedCount, float epsilon = 1e-5f)
+ {
xaDebugAssert(A.width() == x.dimension());
xaDebugAssert(A.height() == b.dimension());
xaDebugAssert(A.height() >= A.width() - lockedCount);
@@ -4194,22 +4477,22 @@ private:
* Gradient method.
*
* Solving sparse linear systems:
- * (1) A·x = b
+ * (1) A·x = b
*
* The conjugate gradient algorithm solves (1) only in the case that A is
* symmetric and positive definite. It is based on the idea of minimizing the
* function
*
- * (2) f(x) = 1/2·x·A·x - b·x
+ * (2) f(x) = 1/2·x·A·x - b·x
*
* This function is minimized when its gradient
*
- * (3) df = A·x - b
+ * (3) df = A·x - b
*
* is zero, which is equivalent to (1). The minimization is carried out by
* generating a succession of search directions p.k and improved minimizers x.k.
- * At each stage a quantity alfa.k is found that minimizes f(x.k + alfa.k·p.k),
- * and x.k+1 is set equal to the new point x.k + alfa.k·p.k. The p.k and x.k are
+ * At each stage a quantity alfa.k is found that minimizes f(x.k + alfa.k·p.k),
+ * and x.k+1 is set equal to the new point x.k + alfa.k·p.k. The p.k and x.k are
* built up in such a way that x.k+1 is also the minimizer of f over the whole
* vector space of directions already taken, {p.1, p.2, . . . , p.k}. After N
* iterations you arrive at the minimizer over the entire vector space, i.e., the
@@ -4221,107 +4504,111 @@ private:
* Jonhathan Richard Shewchuk.
*
**/
- static bool ConjugateGradientSolver(const sparse::Matrix &A, const FullVector &b, FullVector &x, float epsilon) {
- xaDebugAssert(A.isSquare());
- xaDebugAssert(A.width() == b.dimension());
- xaDebugAssert(A.width() == x.dimension());
+ static bool ConjugateGradientSolver(const sparse::Matrix &A, const FullVector &b, FullVector &x, float epsilon)
+ {
+ xaDebugAssert( A.isSquare() );
+ xaDebugAssert( A.width() == b.dimension() );
+ xaDebugAssert( A.width() == x.dimension() );
int i = 0;
const int D = A.width();
- const int i_max = 4 * D; // Convergence should be linear, but in some cases, it's not.
- FullVector r(D); // residual
- FullVector p(D); // search direction
- FullVector q(D); //
+ const int i_max = 4 * D; // Convergence should be linear, but in some cases, it's not.
+ FullVector r(D); // residual
+ FullVector p(D); // search direction
+ FullVector q(D); //
float delta_0;
float delta_old;
float delta_new;
float alpha;
float beta;
- // r = b - A·x;
+ // r = b - A·x;
sparse::copy(b, r);
sparse::sgemv(-1, A, x, 1, r);
// p = r;
sparse::copy(r, p);
- delta_new = sparse::dot(r, r);
+ delta_new = sparse::dot( r, r );
delta_0 = delta_new;
while (i < i_max && delta_new > epsilon * epsilon * delta_0) {
i++;
- // q = A·p
+ // q = A·p
mult(A, p, q);
- // alpha = delta_new / p·q
- alpha = delta_new / sparse::dot(p, q);
- // x = alfa·p + x
+ // alpha = delta_new / p·q
+ alpha = delta_new / sparse::dot( p, q );
+ // x = alfa·p + x
sparse::saxpy(alpha, p, x);
if ((i & 31) == 0) { // recompute r after 32 steps
- // r = b - A·x
+ // r = b - A·x
sparse::copy(b, r);
sparse::sgemv(-1, A, x, 1, r);
} else {
- // r = r - alpha·q
+ // r = r - alpha·q
sparse::saxpy(-alpha, q, r);
}
delta_old = delta_new;
- delta_new = sparse::dot(r, r);
+ delta_new = sparse::dot( r, r );
beta = delta_new / delta_old;
- // p = beta·p + r
+ // p = beta·p + r
sparse::scal(beta, p);
sparse::saxpy(1, r, p);
}
return delta_new <= epsilon * epsilon * delta_0;
}
+
// Conjugate gradient with preconditioner.
- static bool ConjugateGradientSolver(const JacobiPreconditioner &preconditioner, const sparse::Matrix &A, const FullVector &b, FullVector &x, float epsilon) {
- xaDebugAssert(A.isSquare());
- xaDebugAssert(A.width() == b.dimension());
- xaDebugAssert(A.width() == x.dimension());
+ static bool ConjugateGradientSolver(const JacobiPreconditioner &preconditioner, const sparse::Matrix &A, const FullVector &b, FullVector &x, float epsilon)
+ {
+ xaDebugAssert( A.isSquare() );
+ xaDebugAssert( A.width() == b.dimension() );
+ xaDebugAssert( A.width() == x.dimension() );
int i = 0;
const int D = A.width();
- const int i_max = 4 * D; // Convergence should be linear, but in some cases, it's not.
- FullVector r(D); // residual
- FullVector p(D); // search direction
- FullVector q(D); //
- FullVector s(D); // preconditioned
+ const int i_max = 4 * D; // Convergence should be linear, but in some cases, it's not.
+ FullVector r(D); // residual
+ FullVector p(D); // search direction
+ FullVector q(D); //
+ FullVector s(D); // preconditioned
float delta_0;
float delta_old;
float delta_new;
float alpha;
float beta;
- // r = b - A·x
+ // r = b - A·x
sparse::copy(b, r);
sparse::sgemv(-1, A, x, 1, r);
- // p = M^-1 · r
+ // p = M^-1 · r
preconditioner.apply(r, p);
delta_new = sparse::dot(r, p);
delta_0 = delta_new;
while (i < i_max && delta_new > epsilon * epsilon * delta_0) {
i++;
- // q = A·p
+ // q = A·p
mult(A, p, q);
- // alpha = delta_new / p·q
+ // alpha = delta_new / p·q
alpha = delta_new / sparse::dot(p, q);
- // x = alfa·p + x
+ // x = alfa·p + x
sparse::saxpy(alpha, p, x);
if ((i & 31) == 0) { // recompute r after 32 steps
- // r = b - A·x
+ // r = b - A·x
sparse::copy(b, r);
sparse::sgemv(-1, A, x, 1, r);
} else {
- // r = r - alfa·q
+ // r = r - alfa·q
sparse::saxpy(-alpha, q, r);
}
- // s = M^-1 · r
+ // s = M^-1 · r
preconditioner.apply(r, s);
delta_old = delta_new;
- delta_new = sparse::dot(r, s);
+ delta_new = sparse::dot( r, s );
beta = delta_new / delta_old;
- // p = s + beta·p
+ // p = s + beta·p
sparse::scal(beta, p);
sparse::saxpy(1, s, p);
}
return delta_new <= epsilon * epsilon * delta_0;
}
- static bool SymmetricSolver(const sparse::Matrix &A, const FullVector &b, FullVector &x, float epsilon = 1e-5f) {
+ static bool SymmetricSolver(const sparse::Matrix &A, const FullVector &b, FullVector &x, float epsilon = 1e-5f)
+ {
xaDebugAssert(A.height() == A.width());
xaDebugAssert(A.height() == b.dimension());
xaDebugAssert(b.dimension() == x.dimension());
@@ -4335,7 +4622,8 @@ class Atlas;
class Chart;
// Fast sweep in 3 directions
-static bool findApproximateDiameterVertices(halfedge::Mesh *mesh, halfedge::Vertex **a, halfedge::Vertex **b) {
+static bool findApproximateDiameterVertices(halfedge::Mesh *mesh, halfedge::Vertex **a, halfedge::Vertex **b)
+{
xaDebugAssert(mesh != NULL);
xaDebugAssert(a != NULL);
xaDebugAssert(b != NULL);
@@ -4364,18 +4652,12 @@ static bool findApproximateDiameterVertices(halfedge::Mesh *mesh, halfedge::Vert
// Skip interior vertices.
continue;
}
- if (vertex->pos.x < minVertex[0]->pos.x)
- minVertex[0] = vertex;
- else if (vertex->pos.x > maxVertex[0]->pos.x)
- maxVertex[0] = vertex;
- if (vertex->pos.y < minVertex[1]->pos.y)
- minVertex[1] = vertex;
- else if (vertex->pos.y > maxVertex[1]->pos.y)
- maxVertex[1] = vertex;
- if (vertex->pos.z < minVertex[2]->pos.z)
- minVertex[2] = vertex;
- else if (vertex->pos.z > maxVertex[2]->pos.z)
- maxVertex[2] = vertex;
+ if (vertex->pos.x < minVertex[0]->pos.x) minVertex[0] = vertex;
+ else if (vertex->pos.x > maxVertex[0]->pos.x) maxVertex[0] = vertex;
+ if (vertex->pos.y < minVertex[1]->pos.y) minVertex[1] = vertex;
+ else if (vertex->pos.y > maxVertex[1]->pos.y) maxVertex[1] = vertex;
+ if (vertex->pos.z < minVertex[2]->pos.z) minVertex[2] = vertex;
+ else if (vertex->pos.z > maxVertex[2]->pos.z) maxVertex[2] = vertex;
}
float lengths[3];
for (int i = 0; i < 3; i++) {
@@ -4396,24 +4678,28 @@ static bool findApproximateDiameterVertices(halfedge::Mesh *mesh, halfedge::Vert
// Conformal relations from Brecht Van Lommel (based on ABF):
-static float vec_angle_cos(Vector3::Arg v1, Vector3::Arg v2, Vector3::Arg v3) {
+static float vec_angle_cos(Vector3::Arg v1, Vector3::Arg v2, Vector3::Arg v3)
+{
Vector3 d1 = v1 - v2;
Vector3 d2 = v3 - v2;
return clamp(dot(d1, d2) / (length(d1) * length(d2)), -1.0f, 1.0f);
}
-static float vec_angle(Vector3::Arg v1, Vector3::Arg v2, Vector3::Arg v3) {
+static float vec_angle(Vector3::Arg v1, Vector3::Arg v2, Vector3::Arg v3)
+{
float dot = vec_angle_cos(v1, v2, v3);
return acosf(dot);
}
-static void triangle_angles(Vector3::Arg v1, Vector3::Arg v2, Vector3::Arg v3, float *a1, float *a2, float *a3) {
+static void triangle_angles(Vector3::Arg v1, Vector3::Arg v2, Vector3::Arg v3, float *a1, float *a2, float *a3)
+{
*a1 = vec_angle(v3, v1, v2);
*a2 = vec_angle(v1, v2, v3);
*a3 = PI - *a2 - *a1;
}
-static void setup_abf_relations(sparse::Matrix &A, int row, const halfedge::Vertex *v0, const halfedge::Vertex *v1, const halfedge::Vertex *v2) {
+static void setup_abf_relations(sparse::Matrix &A, int row, const halfedge::Vertex *v0, const halfedge::Vertex *v1, const halfedge::Vertex *v2)
+{
int id0 = v0->id;
int id1 = v1->id;
int id2 = v2->id;
@@ -4469,7 +4755,8 @@ static void setup_abf_relations(sparse::Matrix &A, int row, const halfedge::Vert
A.setCoefficient(v2_id, 2 * row + 1, 1);
}
-bool computeLeastSquaresConformalMap(halfedge::Mesh *mesh) {
+bool computeLeastSquaresConformalMap(halfedge::Mesh *mesh)
+{
xaDebugAssert(mesh != NULL);
// For this to work properly, mesh should not have colocals that have the same
// attributes, unless you want the vertices to actually have different texcoords.
@@ -4542,7 +4829,8 @@ bool computeLeastSquaresConformalMap(halfedge::Mesh *mesh) {
return true;
}
-bool computeOrthogonalProjectionMap(halfedge::Mesh *mesh) {
+bool computeOrthogonalProjectionMap(halfedge::Mesh *mesh)
+{
Vector3 axis[2];
uint32_t vertexCount = mesh->vertexCount();
std::vector<Vector3> points(vertexCount);
@@ -4572,7 +4860,8 @@ bool computeOrthogonalProjectionMap(halfedge::Mesh *mesh) {
return true;
}
-void computeSingleFaceMap(halfedge::Mesh *mesh) {
+void computeSingleFaceMap(halfedge::Mesh *mesh)
+{
xaDebugAssert(mesh != NULL);
xaDebugAssert(mesh->faceCount() == 1);
halfedge::Face *face = mesh->faceAt(0);
@@ -4603,11 +4892,12 @@ void computeSingleFaceMap(halfedge::Mesh *mesh) {
// - Resorting is n*log(n)
// @@ Number of elements in the queue is usually small, and we'd have to rebalance often. I'm not sure it's worth implementing a heap.
// @@ Searcing at removal would remove the need for sorting when priorities change.
-struct PriorityQueue {
- PriorityQueue(uint32_t size = UINT_MAX) :
- maxSize(size) {}
+struct PriorityQueue
+{
+ PriorityQueue(uint32_t size = UINT_MAX) : maxSize(size) {}
- void push(float priority, uint32_t face) {
+ void push(float priority, uint32_t face)
+ {
uint32_t i = 0;
const uint32_t count = pairs.size();
for (; i < count; i++) {
@@ -4621,39 +4911,47 @@ struct PriorityQueue {
}
// push face out of order, to be sorted later.
- void push(uint32_t face) {
+ void push(uint32_t face)
+ {
Pair p = { 0.0f, face };
pairs.push_back(p);
}
- uint32_t pop() {
+ uint32_t pop()
+ {
uint32_t f = pairs.back().face;
pairs.pop_back();
return f;
}
- void sort() {
+ void sort()
+ {
//sort(pairs); // @@ My intro sort appears to be much slower than it should!
std::sort(pairs.begin(), pairs.end());
}
- void clear() {
+ void clear()
+ {
pairs.clear();
}
- uint32_t count() const {
+ uint32_t count() const
+ {
return pairs.size();
}
- float firstPriority() const {
+ float firstPriority() const
+ {
return pairs.back().priority;
}
const uint32_t maxSize;
- struct Pair {
- bool operator<(const Pair &p) const {
- return priority > p.priority; // !! Sort in inverse priority order!
+ struct Pair
+ {
+ bool operator <(const Pair &p) const
+ {
+ return priority > p.priority; // !! Sort in inverse priority order!
}
float priority;
@@ -4663,9 +4961,10 @@ struct PriorityQueue {
std::vector<Pair> pairs;
};
-struct ChartBuildData {
- ChartBuildData(int p_id) :
- id(p_id) {
+struct ChartBuildData
+{
+ ChartBuildData(int id) : id(id)
+ {
planeNormal = Vector3(0);
centroid = Vector3(0);
coneAxis = Vector3(0);
@@ -4689,15 +4988,15 @@ struct ChartBuildData {
Vector3 normalSum;
Vector3 centroidSum;
- std::vector<uint32_t> seeds; // @@ These could be a pointers to the halfedge faces directly.
+ std::vector<uint32_t> seeds; // @@ These could be a pointers to the halfedge faces directly.
std::vector<uint32_t> faces;
PriorityQueue candidates;
};
-struct AtlasBuilder {
- AtlasBuilder(const halfedge::Mesh *m) :
- mesh(m),
- facesLeft(m->faceCount()) {
+struct AtlasBuilder
+{
+ AtlasBuilder(const halfedge::Mesh *m) : mesh(m), facesLeft(m->faceCount())
+ {
const uint32_t faceCount = m->faceCount();
faceChartArray.resize(faceCount, -1);
faceCandidateArray.resize(faceCount, (uint32_t)-1);
@@ -4720,14 +5019,16 @@ struct AtlasBuilder {
}
}
- ~AtlasBuilder() {
+ ~AtlasBuilder()
+ {
const uint32_t chartCount = chartArray.size();
for (uint32_t i = 0; i < chartCount; i++) {
delete chartArray[i];
}
}
- void markUnchartedFaces(const std::vector<uint32_t> &unchartedFaces) {
+ void markUnchartedFaces(const std::vector<uint32_t> &unchartedFaces)
+ {
const uint32_t unchartedFaceCount = unchartedFaces.size();
for (uint32_t i = 0; i < unchartedFaceCount; i++) {
uint32_t f = unchartedFaces[i];
@@ -4739,7 +5040,8 @@ struct AtlasBuilder {
facesLeft -= unchartedFaceCount;
}
- void computeShortestPaths() {
+ void computeShortestPaths()
+ {
const uint32_t faceCount = mesh->faceCount();
shortestPaths.resize(faceCount * faceCount, FLT_MAX);
// Fill edges:
@@ -4767,7 +5069,8 @@ struct AtlasBuilder {
}
}
- void placeSeeds(float threshold, uint32_t maxSeedCount) {
+ void placeSeeds(float threshold, uint32_t maxSeedCount)
+ {
// Instead of using a predefiened number of seeds:
// - Add seeds one by one, growing chart until a certain treshold.
// - Undo charts and restart growing process.
@@ -4783,18 +5086,17 @@ struct AtlasBuilder {
}
}
- void createRandomChart(float threshold) {
+ void createRandomChart(float threshold)
+ {
ChartBuildData *chart = new ChartBuildData(chartArray.size());
chartArray.push_back(chart);
// Pick random face that is not used by any chart yet.
uint32_t randomFaceIdx = rand.getRange(facesLeft - 1);
uint32_t i = 0;
for (uint32_t f = 0; f != randomFaceIdx; f++, i++) {
- while (faceChartArray[i] != -1)
- i++;
+ while (faceChartArray[i] != -1) i++;
}
- while (faceChartArray[i] != -1)
- i++;
+ while (faceChartArray[i] != -1) i++;
chart->seeds.push_back(i);
addFaceToChart(chart, i, true);
// Grow the chart as much as possible within the given threshold.
@@ -4802,7 +5104,8 @@ struct AtlasBuilder {
//growCharts(threshold - threshold * 0.75f / chartCount(), facesLeft);
}
- void addFaceToChart(ChartBuildData *chart, uint32_t f, bool recomputeProxy = false) {
+ void addFaceToChart(ChartBuildData *chart, uint32_t f, bool recomputeProxy = false)
+ {
// Add face to chart.
chart->faces.push_back(f);
xaDebugAssert(faceChartArray[f] == -1);
@@ -4824,7 +5127,8 @@ struct AtlasBuilder {
}
// Returns true if any of the charts can grow more.
- bool growCharts(float threshold, uint32_t faceCount) {
+ bool growCharts(float threshold, uint32_t faceCount)
+ {
// Using one global list.
faceCount = std::min(faceCount, facesLeft);
for (uint32_t i = 0; i < faceCount; i++) {
@@ -4837,9 +5141,10 @@ struct AtlasBuilder {
return facesLeft != 0; // Can continue growing.
}
- bool growChart(ChartBuildData *chart, float threshold, uint32_t faceCount) {
+ bool growChart(ChartBuildData *chart, float threshold, uint32_t faceCount)
+ {
// Try to add faceCount faces within threshold to chart.
- for (uint32_t i = 0; i < faceCount;) {
+ for (uint32_t i = 0; i < faceCount; ) {
if (chart->candidates.count() == 0 || chart->candidates.firstPriority() > threshold) {
return false;
}
@@ -4855,7 +5160,8 @@ struct AtlasBuilder {
return true;
}
- void resetCharts() {
+ void resetCharts()
+ {
const uint32_t faceCount = mesh->faceCount();
for (uint32_t i = 0; i < faceCount; i++) {
faceChartArray[i] = -1;
@@ -4877,7 +5183,8 @@ struct AtlasBuilder {
}
}
- void updateCandidates(ChartBuildData *chart, uint32_t f) {
+ void updateCandidates(ChartBuildData *chart, uint32_t f)
+ {
const halfedge::Face *face = mesh->faceAt(f);
// Traverse neighboring faces, add the ones that do not belong to any chart yet.
for (halfedge::Face::ConstEdgeIterator it(face->edges()); !it.isDone(); it.advance()) {
@@ -4891,20 +5198,23 @@ struct AtlasBuilder {
}
}
- void updateProxies() {
+ void updateProxies()
+ {
const uint32_t chartCount = chartArray.size();
for (uint32_t i = 0; i < chartCount; i++) {
updateProxy(chartArray[i]);
}
}
- void updateProxy(ChartBuildData *chart) {
+ void updateProxy(ChartBuildData *chart)
+ {
//#pragma message(NV_FILE_LINE "TODO: Use best fit plane instead of average normal.")
chart->planeNormal = normalizeSafe(chart->normalSum, Vector3(0), 0.0f);
chart->centroid = chart->centroidSum / float(chart->faces.size());
}
- bool relocateSeeds() {
+ bool relocateSeeds()
+ {
bool anySeedChanged = false;
const uint32_t chartCount = chartArray.size();
for (uint32_t i = 0; i < chartCount; i++) {
@@ -4915,9 +5225,10 @@ struct AtlasBuilder {
return anySeedChanged;
}
- bool relocateSeed(ChartBuildData *chart) {
+ bool relocateSeed(ChartBuildData *chart)
+ {
Vector3 centroid = computeChartCentroid(chart);
- const uint32_t N = 10; // @@ Hardcoded to 10?
+ const uint32_t N = 10; // @@ Hardcoded to 10?
PriorityQueue bestTriangles(N);
// Find the first N triangles that fit the proxy best.
const uint32_t faceCount = chart->faces.size();
@@ -4953,7 +5264,8 @@ struct AtlasBuilder {
}
}
- void updatePriorities(ChartBuildData *chart) {
+ void updatePriorities(ChartBuildData *chart)
+ {
// Re-evaluate candidate priorities.
uint32_t candidateCount = chart->candidates.count();
for (uint32_t i = 0; i < candidateCount; i++) {
@@ -4967,7 +5279,8 @@ struct AtlasBuilder {
}
// Evaluate combined metric.
- float evaluatePriority(ChartBuildData *chart, uint32_t face) {
+ float evaluatePriority(ChartBuildData *chart, uint32_t face)
+ {
// Estimate boundary length and area:
float newBoundaryLength = evaluateBoundaryLength(chart, face);
float newChartArea = evaluateChartArea(chart, face);
@@ -4984,11 +5297,11 @@ struct AtlasBuilder {
// - Cause more impedance. Never cross 90 degree edges.
// -
float cost = float(
- options.proxyFitMetricWeight * F +
- options.roundnessMetricWeight * C +
- options.straightnessMetricWeight * P +
- options.normalSeamMetricWeight * N +
- options.textureSeamMetricWeight * T);
+ options.proxyFitMetricWeight * F +
+ options.roundnessMetricWeight * C +
+ options.straightnessMetricWeight * P +
+ options.normalSeamMetricWeight * N +
+ options.textureSeamMetricWeight * T);
// Enforce limits strictly:
if (newChartArea > options.maxChartArea) cost = FLT_MAX;
if (newBoundaryLength > options.maxBoundaryLength) cost = FLT_MAX;
@@ -4999,14 +5312,16 @@ struct AtlasBuilder {
}
// Returns a value in [0-1].
- float evaluateProxyFitMetric(ChartBuildData *chart, uint32_t f) {
+ float evaluateProxyFitMetric(ChartBuildData *chart, uint32_t f)
+ {
const halfedge::Face *face = mesh->faceAt(f);
Vector3 faceNormal = face->triangleNormal();
// Use plane fitting metric for now:
return 1 - dot(faceNormal, chart->planeNormal); // @@ normal deviations should be weighted by face area
}
- float evaluateRoundnessMetric(ChartBuildData *chart, uint32_t /*face*/, float newBoundaryLength, float newChartArea) {
+ float evaluateRoundnessMetric(ChartBuildData *chart, uint32_t /*face*/, float newBoundaryLength, float newChartArea)
+ {
float roundness = square(chart->boundaryLength) / chart->area;
float newRoundness = square(newBoundaryLength) / newChartArea;
if (newRoundness > roundness) {
@@ -5017,7 +5332,8 @@ struct AtlasBuilder {
}
}
- float evaluateStraightnessMetric(ChartBuildData *chart, uint32_t f) {
+ float evaluateStraightnessMetric(ChartBuildData *chart, uint32_t f)
+ {
float l_out = 0.0f;
float l_in = 0.0f;
const halfedge::Face *face = mesh->faceAt(f);
@@ -5040,7 +5356,8 @@ struct AtlasBuilder {
return std::min(ratio, 0.0f); // Only use the straightness metric to close gaps.
}
- float evaluateNormalSeamMetric(ChartBuildData *chart, uint32_t f) {
+ float evaluateNormalSeamMetric(ChartBuildData *chart, uint32_t f)
+ {
float seamFactor = 0.0f;
float totalLength = 0.0f;
const halfedge::Face *face = mesh->faceAt(f);
@@ -5071,7 +5388,8 @@ struct AtlasBuilder {
return seamFactor / totalLength;
}
- float evaluateTextureSeamMetric(ChartBuildData *chart, uint32_t f) {
+ float evaluateTextureSeamMetric(ChartBuildData *chart, uint32_t f)
+ {
float seamLength = 0.0f;
float totalLength = 0.0f;
const halfedge::Face *face = mesh->faceAt(f);
@@ -5101,12 +5419,14 @@ struct AtlasBuilder {
return seamLength / totalLength;
}
- float evaluateChartArea(ChartBuildData *chart, uint32_t f) {
+ float evaluateChartArea(ChartBuildData *chart, uint32_t f)
+ {
const halfedge::Face *face = mesh->faceAt(f);
return chart->area + faceAreas[face->id];
}
- float evaluateBoundaryLength(ChartBuildData *chart, uint32_t f) {
+ float evaluateBoundaryLength(ChartBuildData *chart, uint32_t f)
+ {
float boundaryLength = chart->boundaryLength;
// Add new edges, subtract edges shared with the chart.
const halfedge::Face *face = mesh->faceAt(f);
@@ -5125,20 +5445,23 @@ struct AtlasBuilder {
}
}
}
- return std::max(0.0f, boundaryLength); // @@ Hack!
+ return std::max(0.0f, boundaryLength); // @@ Hack!
}
- Vector3 evaluateChartNormalSum(ChartBuildData *chart, uint32_t f) {
+ Vector3 evaluateChartNormalSum(ChartBuildData *chart, uint32_t f)
+ {
const halfedge::Face *face = mesh->faceAt(f);
return chart->normalSum + face->triangleNormalAreaScaled();
}
- Vector3 evaluateChartCentroidSum(ChartBuildData *chart, uint32_t f) {
+ Vector3 evaluateChartCentroidSum(ChartBuildData *chart, uint32_t f)
+ {
const halfedge::Face *face = mesh->faceAt(f);
return chart->centroidSum + face->centroid();
}
- Vector3 computeChartCentroid(const ChartBuildData *chart) {
+ Vector3 computeChartCentroid(const ChartBuildData *chart)
+ {
Vector3 centroid(0);
const uint32_t faceCount = chart->faces.size();
for (uint32_t i = 0; i < faceCount; i++) {
@@ -5148,12 +5471,14 @@ struct AtlasBuilder {
return centroid / float(faceCount);
}
- void fillHoles(float threshold) {
+ void fillHoles(float threshold)
+ {
while (facesLeft > 0)
createRandomChart(threshold);
}
- void mergeCharts() {
+ void mergeCharts()
+ {
std::vector<float> sharedBoundaryLengths;
const uint32_t chartCount = chartArray.size();
for (int c = chartCount - 1; c >= 0; c--) {
@@ -5219,9 +5544,9 @@ struct AtlasBuilder {
// Update faceChartArray.
const uint32_t faceCount = faceChartArray.size();
for (uint32_t i = 0; i < faceCount; i++) {
- xaDebugAssert(faceChartArray[i] != -1);
- xaDebugAssert(faceChartArray[i] != c);
- xaDebugAssert(faceChartArray[i] <= int32_t(chartArray.size()));
+ xaDebugAssert (faceChartArray[i] != -1);
+ xaDebugAssert (faceChartArray[i] != c);
+ xaDebugAssert (faceChartArray[i] <= int32_t(chartArray.size()));
if (faceChartArray[i] > c) {
faceChartArray[i]--;
}
@@ -5241,7 +5566,8 @@ struct AtlasBuilder {
};
// @@ Get N best candidates in one pass.
- const Candidate &getBestCandidate() const {
+ const Candidate &getBestCandidate() const
+ {
uint32_t best = 0;
float bestCandidateMetric = FLT_MAX;
const uint32_t candidateCount = candidateArray.size();
@@ -5256,7 +5582,8 @@ struct AtlasBuilder {
return candidateArray[best];
}
- void removeCandidate(uint32_t f) {
+ void removeCandidate(uint32_t f)
+ {
int c = faceCandidateArray[f];
if (c != -1) {
faceCandidateArray[f] = (uint32_t)-1;
@@ -5271,7 +5598,8 @@ struct AtlasBuilder {
}
}
- void updateCandidate(ChartBuildData *chart, uint32_t f, float metric) {
+ void updateCandidate(ChartBuildData *chart, uint32_t f, float metric)
+ {
if (faceCandidateArray[f] == -1) {
const uint32_t index = candidateArray.size();
faceCandidateArray[f] = index;
@@ -5291,7 +5619,8 @@ struct AtlasBuilder {
}
}
- void mergeChart(ChartBuildData *owner, ChartBuildData *chart, float sharedBoundaryLength) {
+ void mergeChart(ChartBuildData *owner, ChartBuildData *chart, float sharedBoundaryLength)
+ {
const uint32_t faceCount = chart->faces.size();
for (uint32_t i = 0; i < faceCount; i++) {
uint32_t f = chart->faces[i];
@@ -5307,6 +5636,7 @@ struct AtlasBuilder {
updateProxy(owner);
}
+
uint32_t chartCount() const { return chartArray.size(); }
const std::vector<uint32_t> &chartFaces(uint32_t i) const { return chartArray[i]->faces; }
@@ -5324,13 +5654,13 @@ struct AtlasBuilder {
};
/// A chart is a connected set of faces with a certain topology (usually a disk).
-class Chart {
+class Chart
+{
public:
- Chart() :
- m_isDisk(false),
- m_isVertexMapped(false) {}
+ Chart() : m_isDisk(false), m_isVertexMapped(false) {}
- void build(const halfedge::Mesh *originalMesh, const std::vector<uint32_t> &faceArray) {
+ void build(const halfedge::Mesh *originalMesh, const std::vector<uint32_t> &faceArray)
+ {
// Copy face indices.
m_faceArray = faceArray;
const uint32_t meshVertexCount = originalMesh->vertexCount();
@@ -5353,7 +5683,10 @@ public:
}
if (chartMeshIndices[vertex->id] == ~0) {
chartMeshIndices[vertex->id] = m_chartMesh->vertexCount();
+ // -- GODOT start --
+ //m_chartToOriginalMap.push_back(vertex->id);
m_chartToOriginalMap.push_back(vertex->original_id);
+ // -- GODOT end --
m_chartToUnifiedMap.push_back(unifiedMeshIndices[unifiedVertex->id]);
halfedge::Vertex *v = m_chartMesh->addVertex(vertex->pos);
v->nor = vertex->nor;
@@ -5417,7 +5750,8 @@ public:
m_isDisk = topology.isDisk();
}
- void buildVertexMap(const halfedge::Mesh *originalMesh, const std::vector<uint32_t> &unchartedMaterialArray) {
+ void buildVertexMap(const halfedge::Mesh *originalMesh, const std::vector<uint32_t> &unchartedMaterialArray)
+ {
xaAssert(m_chartMesh.get() == NULL && m_unifiedMesh.get() == NULL);
m_isVertexMapped = true;
// Build face indices.
@@ -5445,7 +5779,10 @@ public:
const halfedge::Vertex *vertex = it.current()->vertex;
if (chartMeshIndices[vertex->id] == ~0) {
chartMeshIndices[vertex->id] = m_chartMesh->vertexCount();
+ // -- GODOT start --
+ //m_chartToOriginalMap.push_back(vertex->id);
m_chartToOriginalMap.push_back(vertex->original_id);
+ // -- GODOT end --
halfedge::Vertex *v = m_chartMesh->addVertex(vertex->pos);
v->nor = vertex->nor;
v->tex = vertex->tex; // @@ Not necessary.
@@ -5505,7 +5842,7 @@ public:
halfedge::Vertex *vertex = m_chartMesh->vertexAt(idx);
xaDebugAssert(vertexIndexArray[idx] == -1);
std::vector<uint32_t> neighbors;
- grid.gather(vertex->pos, positionThreshold, /*ref*/ neighbors);
+ grid.gather(vertex->pos, positionThreshold, /*ref*/neighbors);
// Compare against all nearby vertices, cluster greedily.
for (uint32_t j = 0; j < neighbors.size(); j++) {
uint32_t otherIdx = neighbors[j];
@@ -5528,7 +5865,7 @@ public:
xaDebugAssert(cellsVisited == grid.cellArray.size());
xaDebugAssert(verticesVisited == chartVertexCount);
vertexMapWidth = ftoi_ceil(sqrtf(float(texelCount)));
- vertexMapWidth = (vertexMapWidth + 3) & ~3; // Width aligned to 4.
+ vertexMapWidth = (vertexMapWidth + 3) & ~3; // Width aligned to 4.
vertexMapHeight = vertexMapWidth == 0 ? 0 : (texelCount + vertexMapWidth - 1) / vertexMapWidth;
//vertexMapHeight = (vertexMapHeight + 3) & ~3; // Height aligned to 4.
xaDebugAssert(vertexMapWidth >= vertexMapHeight);
@@ -5559,7 +5896,8 @@ public:
}
}
- bool closeHoles() {
+ bool closeHoles()
+ {
xaDebugAssert(!m_isVertexMapped);
std::vector<halfedge::Edge *> boundaryEdges;
getBoundaryEdges(m_unifiedMesh.get(), boundaryEdges);
@@ -5610,7 +5948,7 @@ public:
std::vector<halfedge::Edge *> edgeLoop;
halfedge::Edge *edge = startEdge;
do {
- halfedge::Vertex *vertex = edge->next->vertex; // edge->to()
+ halfedge::Vertex *vertex = edge->next->vertex; // edge->to()
uint32_t j;
for (j = 0; j < vertexLoop.size(); j++) {
if (vertex->isColocal(vertexLoop[j])) {
@@ -5619,8 +5957,8 @@ public:
}
bool isCrossing = (j != vertexLoop.size());
if (isCrossing) {
- halfedge::Edge *prev = edgeLoop[j]; // Previous edge before the loop.
- halfedge::Edge *next = edge->next; // Next edge after the loop.
+ halfedge::Edge *prev = edgeLoop[j]; // Previous edge before the loop.
+ halfedge::Edge *next = edge->next; // Next edge after the loop.
xaDebugAssert(prev->to()->isColocal(next->from()));
// Close loop.
edgeLoop.push_back(edge);
@@ -5646,55 +5984,69 @@ public:
return boundaryCount == 1;
}
- bool isDisk() const {
+ bool isDisk() const
+ {
return m_isDisk;
}
- bool isVertexMapped() const {
+ bool isVertexMapped() const
+ {
return m_isVertexMapped;
}
- uint32_t vertexCount() const {
+ uint32_t vertexCount() const
+ {
return m_chartMesh->vertexCount();
}
- uint32_t colocalVertexCount() const {
+ uint32_t colocalVertexCount() const
+ {
return m_unifiedMesh->vertexCount();
}
- uint32_t faceCount() const {
+ uint32_t faceCount() const
+ {
return m_faceArray.size();
}
- uint32_t faceAt(uint32_t i) const {
+ uint32_t faceAt(uint32_t i) const
+ {
return m_faceArray[i];
}
- const halfedge::Mesh *chartMesh() const {
+ const halfedge::Mesh *chartMesh() const
+ {
return m_chartMesh.get();
}
- halfedge::Mesh *chartMesh() {
+ halfedge::Mesh *chartMesh()
+ {
return m_chartMesh.get();
}
- const halfedge::Mesh *unifiedMesh() const {
+ const halfedge::Mesh *unifiedMesh() const
+ {
return m_unifiedMesh.get();
}
- halfedge::Mesh *unifiedMesh() {
+ halfedge::Mesh *unifiedMesh()
+ {
return m_unifiedMesh.get();
}
//uint32_t vertexIndex(uint32_t i) const { return m_vertexIndexArray[i]; }
- uint32_t mapChartVertexToOriginalVertex(uint32_t i) const {
+ uint32_t mapChartVertexToOriginalVertex(uint32_t i) const
+ {
return m_chartToOriginalMap[i];
}
- uint32_t mapChartVertexToUnifiedVertex(uint32_t i) const {
+ uint32_t mapChartVertexToUnifiedVertex(uint32_t i) const
+ {
return m_chartToUnifiedMap[i];
}
- const std::vector<uint32_t> &faceArray() const {
+ const std::vector<uint32_t> &faceArray() const
+ {
return m_faceArray;
}
// Transfer parameterization from unified mesh to chart mesh.
- void transferParameterization() {
+ void transferParameterization()
+ {
xaDebugAssert(!m_isVertexMapped);
uint32_t vertexCount = m_chartMesh->vertexCount();
for (uint32_t v = 0; v < vertexCount; v++) {
@@ -5704,18 +6056,21 @@ public:
}
}
- float computeSurfaceArea() const {
+ float computeSurfaceArea() const
+ {
return halfedge::computeSurfaceArea(m_chartMesh.get()) * scale;
}
- float computeParametricArea() const {
+ float computeParametricArea() const
+ {
// This only makes sense in parameterized meshes.
xaDebugAssert(m_isDisk);
xaDebugAssert(!m_isVertexMapped);
return halfedge::computeParametricArea(m_chartMesh.get());
}
- Vector2 computeParametricBounds() const {
+ Vector2 computeParametricBounds() const
+ {
// This only makes sense in parameterized meshes.
xaDebugAssert(m_isDisk);
xaDebugAssert(!m_isVertexMapped);
@@ -5735,7 +6090,8 @@ public:
bool blockAligned = true;
private:
- bool closeLoop(uint32_t start, const std::vector<halfedge::Edge *> &loop) {
+ bool closeLoop(uint32_t start, const std::vector<halfedge::Edge *> &loop)
+ {
const uint32_t vertexCount = loop.size() - start;
xaDebugAssert(vertexCount >= 3);
if (vertexCount < 3) return false;
@@ -5779,7 +6135,8 @@ private:
return true;
}
- static void getBoundaryEdges(halfedge::Mesh *mesh, std::vector<halfedge::Edge *> &boundaryEdges) {
+ static void getBoundaryEdges(halfedge::Mesh *mesh, std::vector<halfedge::Edge *> &boundaryEdges)
+ {
xaDebugAssert(mesh != NULL);
const uint32_t edgeCount = mesh->edgeCount();
BitArray bitFlags(edgeCount);
@@ -5810,7 +6167,7 @@ private:
std::auto_ptr<halfedge::Mesh> m_unifiedMesh;
bool m_isDisk;
bool m_isVertexMapped;
-
+
// List of faces of the original mesh that belong to this chart.
std::vector<uint32_t> m_faceArray;
@@ -5821,9 +6178,11 @@ private:
};
// Estimate quality of existing parameterization.
-class ParameterizationQuality {
+class ParameterizationQuality
+{
public:
- ParameterizationQuality() {
+ ParameterizationQuality()
+ {
m_totalTriangleCount = 0;
m_flippedTriangleCount = 0;
m_zeroAreaTriangleCount = 0;
@@ -5835,7 +6194,8 @@ public:
m_authalicMetric = 0.0f;
}
- ParameterizationQuality(const halfedge::Mesh *mesh) {
+ ParameterizationQuality(const halfedge::Mesh *mesh)
+ {
xaDebugAssert(mesh != NULL);
m_totalTriangleCount = 0;
m_flippedTriangleCount = 0;
@@ -5879,33 +6239,39 @@ public:
xaDebugAssert(std::isfinite(m_authalicMetric));
}
- bool isValid() const {
+ bool isValid() const
+ {
return m_flippedTriangleCount == 0; // @@ Does not test for self-overlaps.
}
- float rmsStretchMetric() const {
+ float rmsStretchMetric() const
+ {
if (m_geometricArea == 0) return 0.0f;
float normFactor = sqrtf(m_parametricArea / m_geometricArea);
return sqrtf(m_stretchMetric / m_geometricArea) * normFactor;
}
- float maxStretchMetric() const {
+ float maxStretchMetric() const
+ {
if (m_geometricArea == 0) return 0.0f;
float normFactor = sqrtf(m_parametricArea / m_geometricArea);
return m_maxStretchMetric * normFactor;
}
- float rmsConformalMetric() const {
+ float rmsConformalMetric() const
+ {
if (m_geometricArea == 0) return 0.0f;
return sqrtf(m_conformalMetric / m_geometricArea);
}
- float maxAuthalicMetric() const {
+ float maxAuthalicMetric() const
+ {
if (m_geometricArea == 0) return 0.0f;
return sqrtf(m_authalicMetric / m_geometricArea);
}
- void operator+=(const ParameterizationQuality &pq) {
+ void operator+=(const ParameterizationQuality &pq)
+ {
m_totalTriangleCount += pq.m_totalTriangleCount;
m_flippedTriangleCount += pq.m_flippedTriangleCount;
m_zeroAreaTriangleCount += pq.m_zeroAreaTriangleCount;
@@ -5918,7 +6284,8 @@ public:
}
private:
- void processTriangle(Vector3 q[3], Vector2 p[3]) {
+ void processTriangle(Vector3 q[3], Vector2 p[3])
+ {
m_totalTriangleCount++;
// Evaluate texture stretch metric. See:
// - "Texture Mapping Progressive Meshes", Sander, Snyder, Gortler & Hoppe
@@ -5983,32 +6350,38 @@ private:
};
// Set of charts corresponding to a single mesh.
-class MeshCharts {
+class MeshCharts
+{
public:
- MeshCharts(const halfedge::Mesh *mesh) :
- m_mesh(mesh) {}
+ MeshCharts(const halfedge::Mesh *mesh) : m_mesh(mesh) {}
- ~MeshCharts() {
+ ~MeshCharts()
+ {
for (size_t i = 0; i < m_chartArray.size(); i++)
delete m_chartArray[i];
}
- uint32_t chartCount() const {
+ uint32_t chartCount() const
+ {
return m_chartArray.size();
}
- uint32_t vertexCount() const {
+ uint32_t vertexCount () const
+ {
return m_totalVertexCount;
}
- const Chart *chartAt(uint32_t i) const {
+ const Chart *chartAt(uint32_t i) const
+ {
return m_chartArray[i];
}
- Chart *chartAt(uint32_t i) {
+ Chart *chartAt(uint32_t i)
+ {
return m_chartArray[i];
}
// Extract the charts of the input mesh.
- void extractCharts() {
+ void extractCharts()
+ {
const uint32_t faceCount = m_mesh->faceCount();
int first = 0;
std::vector<uint32_t> queue;
@@ -6108,7 +6481,8 @@ public:
- emphasize roundness metrics to prevent those cases.
- If interior self-overlaps: preserve boundary parameterization and use mean-value map.
*/
- void computeCharts(const CharterOptions &options, const std::vector<uint32_t> &unchartedMaterialArray) {
+ void computeCharts(const CharterOptions &options, const std::vector<uint32_t> &unchartedMaterialArray)
+ {
Chart *vertexMap = NULL;
if (unchartedMaterialArray.size() != 0) {
vertexMap = new Chart();
@@ -6141,7 +6515,7 @@ public:
xaPrint("### Placed %d seeds (max = %d)\n", builder.chartCount(), maxSeedCount);
builder.updateProxies();
builder.mergeCharts();
-#if 1
+ #if 1
xaPrint("### Relocating seeds\n");
builder.relocateSeeds();
xaPrint("### Reset charts\n");
@@ -6183,7 +6557,7 @@ public:
xaPrint("### Growing charts\n");
}
};
-#endif
+ #endif
// Make sure no holes are left!
xaDebugAssert(builder.facesLeft == 0);
const uint32_t chartCount = builder.chartArray.size();
@@ -6220,21 +6594,25 @@ public:
}
}
- void parameterizeCharts() {
+ void parameterizeCharts()
+ {
ParameterizationQuality globalParameterizationQuality;
// Parameterize the charts.
uint32_t diskCount = 0;
const uint32_t chartCount = m_chartArray.size();
- for (uint32_t i = 0; i < chartCount; i++) {
+ for (uint32_t i = 0; i < chartCount; i++)
+ {
Chart *chart = m_chartArray[i];
bool isValid = false;
- if (chart->isVertexMapped()) {
+ if (chart->isVertexMapped())
+ {
continue;
}
- if (chart->isDisk()) {
+ if (chart->isDisk())
+ {
diskCount++;
ParameterizationQuality chartParameterizationQuality;
if (chart->faceCount() == 1) {
@@ -6258,6 +6636,7 @@ public:
// Transfer parameterization from unified mesh to chart mesh.
chart->transferParameterization();
+
}
xaPrint(" Parameterized %d/%d charts.\n", diskCount, chartCount);
xaPrint(" RMS stretch metric: %f\n", globalParameterizationQuality.rmsStretchMetric());
@@ -6266,18 +6645,22 @@ public:
xaPrint(" RMS authalic metric: %f\n", globalParameterizationQuality.maxAuthalicMetric());
}
- uint32_t faceChartAt(uint32_t i) const {
+ uint32_t faceChartAt(uint32_t i) const
+ {
return m_faceChart[i];
}
- uint32_t faceIndexWithinChartAt(uint32_t i) const {
+ uint32_t faceIndexWithinChartAt(uint32_t i) const
+ {
return m_faceIndex[i];
}
- uint32_t vertexCountBeforeChartAt(uint32_t i) const {
+ uint32_t vertexCountBeforeChartAt(uint32_t i) const
+ {
return m_chartVertexCountPrefixSum[i];
}
private:
+
const halfedge::Mesh *m_mesh;
std::vector<Chart *> m_chartArray;
@@ -6290,26 +6673,32 @@ private:
};
/// An atlas is a set of charts.
-class Atlas {
+class Atlas
+{
public:
- ~Atlas() {
+ ~Atlas()
+ {
for (size_t i = 0; i < m_meshChartsArray.size(); i++)
delete m_meshChartsArray[i];
}
- uint32_t meshCount() const {
+ uint32_t meshCount() const
+ {
return m_meshChartsArray.size();
}
- const MeshCharts *meshAt(uint32_t i) const {
+ const MeshCharts *meshAt(uint32_t i) const
+ {
return m_meshChartsArray[i];
}
- MeshCharts *meshAt(uint32_t i) {
+ MeshCharts *meshAt(uint32_t i)
+ {
return m_meshChartsArray[i];
}
- uint32_t chartCount() const {
+ uint32_t chartCount() const
+ {
uint32_t count = 0;
for (uint32_t c = 0; c < m_meshChartsArray.size(); c++) {
count += m_meshChartsArray[c]->chartCount();
@@ -6317,7 +6706,8 @@ public:
return count;
}
- const Chart *chartAt(uint32_t i) const {
+ const Chart *chartAt(uint32_t i) const
+ {
for (uint32_t c = 0; c < m_meshChartsArray.size(); c++) {
uint32_t count = m_meshChartsArray[c]->chartCount();
if (i < count) {
@@ -6328,7 +6718,8 @@ public:
return NULL;
}
- Chart *chartAt(uint32_t i) {
+ Chart *chartAt(uint32_t i)
+ {
for (uint32_t c = 0; c < m_meshChartsArray.size(); c++) {
uint32_t count = m_meshChartsArray[c]->chartCount();
if (i < count) {
@@ -6341,23 +6732,27 @@ public:
// Add mesh charts and takes ownership.
// Extract the charts and add to this atlas.
- void addMeshCharts(MeshCharts *meshCharts) {
+ void addMeshCharts(MeshCharts *meshCharts)
+ {
m_meshChartsArray.push_back(meshCharts);
}
- void extractCharts(const halfedge::Mesh *mesh) {
+ void extractCharts(const halfedge::Mesh *mesh)
+ {
MeshCharts *meshCharts = new MeshCharts(mesh);
meshCharts->extractCharts();
addMeshCharts(meshCharts);
}
- void computeCharts(const halfedge::Mesh *mesh, const CharterOptions &options, const std::vector<uint32_t> &unchartedMaterialArray) {
+ void computeCharts(const halfedge::Mesh *mesh, const CharterOptions &options, const std::vector<uint32_t> &unchartedMaterialArray)
+ {
MeshCharts *meshCharts = new MeshCharts(mesh);
meshCharts->computeCharts(options, unchartedMaterialArray);
addMeshCharts(meshCharts);
}
- void parameterizeCharts() {
+ void parameterizeCharts()
+ {
for (uint32_t i = 0; i < m_meshChartsArray.size(); i++) {
m_meshChartsArray[i]->parameterizeCharts();
}
@@ -6367,11 +6762,10 @@ private:
std::vector<MeshCharts *> m_meshChartsArray;
};
-struct AtlasPacker {
- AtlasPacker(Atlas *atlas) :
- m_atlas(atlas),
- m_width(0),
- m_height(0) {
+struct AtlasPacker
+{
+ AtlasPacker(Atlas *atlas) : m_atlas(atlas), m_width(0), m_height(0)
+ {
// Save the original uvs.
m_originalChartUvs.resize(m_atlas->chartCount());
for (uint32_t i = 0; i < m_atlas->chartCount(); i++) {
@@ -6386,7 +6780,8 @@ struct AtlasPacker {
uint32_t getHeight() const { return m_height; }
// Pack charts in the smallest possible rectangle.
- void packCharts(const PackerOptions &options) {
+ void packCharts(const PackerOptions &options)
+ {
const uint32_t chartCount = m_atlas->chartCount();
if (chartCount == 0) return;
float texelsPerUnit = 1;
@@ -6415,7 +6810,7 @@ struct AtlasPacker {
meshArea += chartArea;
//chartOrderArray[c] = chartArea;
// Compute chart scale
- float parametricArea = fabsf(chart->computeParametricArea()); // @@ There doesn't seem to be anything preventing parametric area to be negative.
+ float parametricArea = fabsf(chart->computeParametricArea()); // @@ There doesn't seem to be anything preventing parametric area to be negative.
if (parametricArea < NV_EPSILON) {
// When the parametric area is too small we use a rough approximation to prevent divisions by very small numbers.
Vector2 bounds = chart->computeParametricBounds();
@@ -6564,18 +6959,18 @@ struct AtlasPacker {
// 0 1 2
if (options.conservative) {
// Init all bits to 0.
- chart_bitmap.resize(ftoi_ceil(chartExtents[c].x) + 1 + options.padding, ftoi_ceil(chartExtents[c].y) + 1 + options.padding, /*initValue=*/false); // + 2 to add padding on both sides.
+ chart_bitmap.resize(ftoi_ceil(chartExtents[c].x) + 1 + options.padding, ftoi_ceil(chartExtents[c].y) + 1 + options.padding, /*initValue=*/false); // + 2 to add padding on both sides.
// Rasterize chart and dilate.
drawChartBitmapDilate(chart, &chart_bitmap, options.padding);
} else {
// Init all bits to 0.
- chart_bitmap.resize(ftoi_ceil(chartExtents[c].x) + 1, ftoi_ceil(chartExtents[c].y) + 1, /*initValue=*/false); // Add half a texels on each side.
+ chart_bitmap.resize(ftoi_ceil(chartExtents[c].x) + 1, ftoi_ceil(chartExtents[c].y) + 1, /*initValue=*/false); // Add half a texels on each side.
// Rasterize chart and dilate.
drawChartBitmap(chart, &chart_bitmap, Vector2(1), Vector2(0.5));
}
}
int best_x, best_y;
- int best_cw, best_ch; // Includes padding now.
+ int best_cw, best_ch; // Includes padding now.
int best_r;
findChartLocation(options.quality, &chart_bitmap, chartExtents[c], w, h, &best_x, &best_y, &best_cw, &best_ch, &best_r, chart->blockAligned);
/*if (w < best_x + best_cw || h < best_y + best_ch)
@@ -6629,7 +7024,8 @@ struct AtlasPacker {
}
}
- float computeAtlasUtilization() const {
+ float computeAtlasUtilization() const
+ {
const uint32_t w = m_width;
const uint32_t h = m_height;
xaDebugAssert(w <= m_bitmap.width());
@@ -6644,7 +7040,8 @@ struct AtlasPacker {
}
private:
- void resetUvs() {
+ void resetUvs()
+ {
for (uint32_t i = 0; i < m_atlas->chartCount(); i++) {
halfedge::Mesh *mesh = m_atlas->chartAt(i)->chartMesh();
for (uint32_t j = 0; j < mesh->vertexCount(); j++)
@@ -6656,7 +7053,8 @@ private:
// is occupied at this point. At the end we have many small charts and a large atlas with sparse holes. Finding those holes randomly is slow. A better approach would be to
// start stacking large charts as if they were tetris pieces. Once charts get small try to place them randomly. It may be interesting to try a intermediate strategy, first try
// along one axis and then try exhaustively along that axis.
- void findChartLocation(int quality, const BitMap *bitmap, Vector2::Arg extents, int w, int h, int *best_x, int *best_y, int *best_w, int *best_h, int *best_r, bool blockAligned) {
+ void findChartLocation(int quality, const BitMap *bitmap, Vector2::Arg extents, int w, int h, int *best_x, int *best_y, int *best_w, int *best_h, int *best_r, bool blockAligned)
+ {
int attempts = 256;
if (quality == 1) attempts = 4096;
if (quality == 2) attempts = 2048;
@@ -6669,7 +7067,8 @@ private:
}
}
- void findChartLocation_bruteForce(const BitMap *bitmap, Vector2::Arg /*extents*/, int w, int h, int *best_x, int *best_y, int *best_w, int *best_h, int *best_r, bool blockAligned) {
+ void findChartLocation_bruteForce(const BitMap *bitmap, Vector2::Arg /*extents*/, int w, int h, int *best_x, int *best_y, int *best_w, int *best_h, int *best_r, bool blockAligned)
+ {
const int BLOCK_SIZE = 4;
int best_metric = INT_MAX;
int step_size = blockAligned ? BLOCK_SIZE : 1;
@@ -6708,10 +7107,11 @@ private:
}
}
done:
- xaDebugAssert(best_metric != INT_MAX);
+ xaDebugAssert (best_metric != INT_MAX);
}
- void findChartLocation_random(const BitMap *bitmap, Vector2::Arg /*extents*/, int w, int h, int *best_x, int *best_y, int *best_w, int *best_h, int *best_r, int minTrialCount, bool blockAligned) {
+ void findChartLocation_random(const BitMap *bitmap, Vector2::Arg /*extents*/, int w, int h, int *best_x, int *best_y, int *best_w, int *best_h, int *best_r, int minTrialCount, bool blockAligned)
+ {
const int BLOCK_SIZE = 4;
int best_metric = INT_MAX;
for (int i = 0; i < minTrialCount || best_metric == INT_MAX; i++) {
@@ -6752,7 +7152,8 @@ private:
}
}
- void drawChartBitmapDilate(const Chart *chart, BitMap *bitmap, int padding) {
+ void drawChartBitmapDilate(const Chart *chart, BitMap *bitmap, int padding)
+ {
const int w = bitmap->width();
const int h = bitmap->height();
const Vector2 extents = Vector2(float(w), float(h));
@@ -6802,7 +7203,8 @@ private:
}
}
- void drawChartBitmap(const Chart *chart, BitMap *bitmap, const Vector2 &scale, const Vector2 &offset) {
+ void drawChartBitmap(const Chart *chart, BitMap *bitmap, const Vector2 &scale, const Vector2 &offset)
+ {
const int w = bitmap->width();
const int h = bitmap->height();
const Vector2 extents = Vector2(float(w), float(h));
@@ -6863,7 +7265,8 @@ private:
std::swap(tmp, *bitmap);
}
- bool canAddChart(const BitMap *bitmap, int atlas_w, int atlas_h, int offset_x, int offset_y, int r) {
+ bool canAddChart(const BitMap *bitmap, int atlas_w, int atlas_h, int offset_x, int offset_y, int r)
+ {
xaDebugAssert(r == 0 || r == 1);
// Check whether the two bitmaps overlap.
const int w = bitmap->width();
@@ -6904,7 +7307,8 @@ private:
return true;
}
- void addChart(const BitMap *bitmap, int atlas_w, int atlas_h, int offset_x, int offset_y, int r) {
+ void addChart(const BitMap *bitmap, int atlas_w, int atlas_h, int offset_x, int offset_y, int r)
+ {
xaDebugAssert(r == 0 || r == 1);
// Check whether the two bitmaps overlap.
const int w = bitmap->width();
@@ -6946,8 +7350,9 @@ private:
}
}
- static bool setBitsCallback(void *param, int x, int y, Vector3::Arg, Vector3::Arg, Vector3::Arg, float area) {
- BitMap *bitmap = (BitMap *)param;
+ static bool setBitsCallback(void *param, int x, int y, Vector3::Arg, Vector3::Arg, Vector3::Arg, float area)
+ {
+ BitMap *bitmap = (BitMap * )param;
if (area > 0.0) {
bitmap->setBitAt(x, y);
}
@@ -6955,7 +7360,8 @@ private:
}
// Compute the convex hull using Graham Scan.
- static void convexHull(const std::vector<Vector2> &input, std::vector<Vector2> &output, float epsilon) {
+ static void convexHull(const std::vector<Vector2> &input, std::vector<Vector2> &output, float epsilon)
+ {
const uint32_t inputCount = input.size();
std::vector<float> coords(inputCount);
for (uint32_t i = 0; i < inputCount; i++) {
@@ -6984,7 +7390,7 @@ private:
output.clear();
output.push_back(top[0]);
output.push_back(top[1]);
- for (uint32_t i = 2; i < top.size();) {
+ for (uint32_t i = 2; i < top.size(); ) {
Vector2 a = output[output.size() - 2];
Vector2 b = output[output.size() - 1];
Vector2 c = top[i];
@@ -7000,7 +7406,7 @@ private:
uint32_t top_count = output.size();
output.push_back(bottom[1]);
// Filter bottom list.
- for (uint32_t i = 2; i < bottom.size();) {
+ for (uint32_t i = 2; i < bottom.size(); ) {
Vector2 a = output[output.size() - 2];
Vector2 b = output[output.size() - 1];
Vector2 c = bottom[i];
@@ -7019,7 +7425,8 @@ private:
}
// This should compute convex hull and use rotating calipers to find the best box. Currently it uses a brute force method.
- static void computeBoundingBox(Chart *chart, Vector2 *majorAxis, Vector2 *minorAxis, Vector2 *minCorner, Vector2 *maxCorner) {
+ static void computeBoundingBox(Chart *chart, Vector2 *majorAxis, Vector2 *minorAxis, Vector2 *minCorner, Vector2 *maxCorner)
+ {
// Compute list of boundary points.
std::vector<Vector2> points;
points.reserve(16);
@@ -7096,7 +7503,8 @@ private:
} // namespace param
} // namespace internal
-struct Atlas {
+struct Atlas
+{
internal::param::Atlas atlas;
std::vector<internal::halfedge::Mesh *> heMeshes;
uint32_t width = 0;
@@ -7104,65 +7512,75 @@ struct Atlas {
OutputMesh **outputMeshes = NULL;
};
-void SetPrint(PrintFunc print) {
+void SetPrint(PrintFunc print)
+{
internal::s_print = print;
}
-Atlas *Create() {
+Atlas *Create()
+{
Atlas *atlas = new Atlas();
return atlas;
}
-void Destroy(Atlas *atlas) {
+void Destroy(Atlas *atlas)
+{
xaAssert(atlas);
for (int i = 0; i < (int)atlas->heMeshes.size(); i++) {
delete atlas->heMeshes[i];
if (atlas->outputMeshes) {
OutputMesh *outputMesh = atlas->outputMeshes[i];
for (uint32_t j = 0; j < outputMesh->chartCount; j++)
- delete[] outputMesh->chartArray[j].indexArray;
- delete[] outputMesh->chartArray;
- delete[] outputMesh->vertexArray;
- delete[] outputMesh->indexArray;
+ delete [] outputMesh->chartArray[j].indexArray;
+ delete [] outputMesh->chartArray;
+ delete [] outputMesh->vertexArray;
+ delete [] outputMesh->indexArray;
delete outputMesh;
}
}
- delete[] atlas->outputMeshes;
+ delete [] atlas->outputMeshes;
delete atlas;
}
-static internal::Vector3 DecodePosition(const InputMesh &mesh, uint32_t index) {
+static internal::Vector3 DecodePosition(const InputMesh &mesh, uint32_t index)
+{
xaAssert(mesh.vertexPositionData);
return *((const internal::Vector3 *)&((const uint8_t *)mesh.vertexPositionData)[mesh.vertexPositionStride * index]);
}
-static internal::Vector3 DecodeNormal(const InputMesh &mesh, uint32_t index) {
+static internal::Vector3 DecodeNormal(const InputMesh &mesh, uint32_t index)
+{
xaAssert(mesh.vertexNormalData);
return *((const internal::Vector3 *)&((const uint8_t *)mesh.vertexNormalData)[mesh.vertexNormalStride * index]);
}
-static internal::Vector2 DecodeUv(const InputMesh &mesh, uint32_t index) {
+static internal::Vector2 DecodeUv(const InputMesh &mesh, uint32_t index)
+{
xaAssert(mesh.vertexUvData);
return *((const internal::Vector2 *)&((const uint8_t *)mesh.vertexUvData)[mesh.vertexUvStride * index]);
}
-static uint32_t DecodeIndex(IndexFormat::Enum format, const void *indexData, uint32_t i) {
+static uint32_t DecodeIndex(IndexFormat::Enum format, const void *indexData, uint32_t i)
+{
if (format == IndexFormat::HalfFloat)
return (uint32_t)((const uint16_t *)indexData)[i];
return ((const uint32_t *)indexData)[i];
}
-static float EdgeLength(internal::Vector3 pos1, internal::Vector3 pos2) {
+static float EdgeLength(internal::Vector3 pos1, internal::Vector3 pos2)
+{
return internal::length(pos2 - pos1);
}
-AddMeshError AddMesh(Atlas *atlas, const InputMesh &mesh, bool useColocalVertices) {
+AddMeshError AddMesh(Atlas *atlas, const InputMesh &mesh, bool useColocalVertices)
+{
xaAssert(atlas);
AddMeshError error;
error.code = AddMeshErrorCode::Success;
error.face = error.index0 = error.index1 = UINT32_MAX;
// Expecting triangle faces.
- if ((mesh.indexCount % 3) != 0) {
+ if ((mesh.indexCount % 3) != 0)
+ {
error.code = AddMeshErrorCode::InvalidIndexCount;
return error;
}
@@ -7239,23 +7657,22 @@ AddMeshError AddMesh(Atlas *atlas, const InputMesh &mesh, bool useColocalVertice
}
internal::halfedge::Face *face = heMesh->addFace(tri[0], tri[1], tri[2]);
+ // -- GODOT start --
if (!face && heMesh->errorCode == internal::halfedge::Mesh::ErrorCode::AlreadyAddedEdge) {
//there is still hope for this, no reason to not add, at least add as separate
face = heMesh->addUniqueFace(tri[0], tri[1], tri[2]);
}
+ // -- GODOT end --
if (!face) {
- //continue;
-
- if (heMesh->errorCode == internal::halfedge::Mesh::ErrorCode::AlreadyAddedEdge) {
+ if (heMesh->errorCode == internal::halfedge::Mesh::ErrorCode::AlreadyAddedEdge)
error.code = AddMeshErrorCode::AlreadyAddedEdge;
- } else if (heMesh->errorCode == internal::halfedge::Mesh::ErrorCode::DegenerateColocalEdge) {
+ else if (heMesh->errorCode == internal::halfedge::Mesh::ErrorCode::DegenerateColocalEdge)
error.code = AddMeshErrorCode::DegenerateColocalEdge;
- } else if (heMesh->errorCode == internal::halfedge::Mesh::ErrorCode::DegenerateEdge) {
+ else if (heMesh->errorCode == internal::halfedge::Mesh::ErrorCode::DegenerateEdge)
error.code = AddMeshErrorCode::DegenerateEdge;
- } else if (heMesh->errorCode == internal::halfedge::Mesh::ErrorCode::DuplicateEdge) {
+ else if (heMesh->errorCode == internal::halfedge::Mesh::ErrorCode::DuplicateEdge)
error.code = AddMeshErrorCode::DuplicateEdge;
- }
error.face = i;
error.index0 = heMesh->errorIndex0;
error.index1 = heMesh->errorIndex1;
@@ -7270,7 +7687,8 @@ AddMeshError AddMesh(Atlas *atlas, const InputMesh &mesh, bool useColocalVertice
return error;
}
-void Generate(Atlas *atlas, CharterOptions charterOptions, PackerOptions packerOptions) {
+void Generate(Atlas *atlas, CharterOptions charterOptions, PackerOptions packerOptions)
+{
xaAssert(atlas);
xaAssert(packerOptions.texelArea > 0);
// Chart meshes.
@@ -7285,7 +7703,7 @@ void Generate(Atlas *atlas, CharterOptions charterOptions, PackerOptions packerO
atlas->width = packer.getWidth();
atlas->height = packer.getHeight();
// Build output meshes.
- atlas->outputMeshes = new OutputMesh *[atlas->heMeshes.size()];
+ atlas->outputMeshes = new OutputMesh*[atlas->heMeshes.size()];
for (int i = 0; i < (int)atlas->heMeshes.size(); i++) {
const internal::halfedge::Mesh *heMesh = atlas->heMeshes[i];
OutputMesh *outputMesh = atlas->outputMeshes[i] = new OutputMesh;
@@ -7341,27 +7759,32 @@ void Generate(Atlas *atlas, CharterOptions charterOptions, PackerOptions packerO
}
}
-uint32_t GetWidth(const Atlas *atlas) {
+uint32_t GetWidth(const Atlas *atlas)
+{
xaAssert(atlas);
return atlas->width;
}
-uint32_t GetHeight(const Atlas *atlas) {
+uint32_t GetHeight(const Atlas *atlas)
+{
xaAssert(atlas);
return atlas->height;
}
-uint32_t GetNumCharts(const Atlas *atlas) {
+uint32_t GetNumCharts(const Atlas *atlas)
+{
xaAssert(atlas);
return atlas->atlas.chartCount();
}
-const OutputMesh *const *GetOutputMeshes(const Atlas *atlas) {
+const OutputMesh * const *GetOutputMeshes(const Atlas *atlas)
+{
xaAssert(atlas);
return atlas->outputMeshes;
}
-const char *StringForEnum(AddMeshErrorCode::Enum error) {
+const char *StringForEnum(AddMeshErrorCode::Enum error)
+{
if (error == AddMeshErrorCode::AlreadyAddedEdge)
return "already added edge";
if (error == AddMeshErrorCode::DegenerateColocalEdge)
diff --git a/thirdparty/xatlas/xatlas.h b/thirdparty/xatlas/xatlas.h
index 4140429fee..dbf8ca08c7 100644
--- a/thirdparty/xatlas/xatlas.h
+++ b/thirdparty/xatlas/xatlas.h
@@ -3,15 +3,18 @@
#ifndef XATLAS_H
#define XATLAS_H
#include <float.h> // FLT_MAX
-#include <limits.h>
-#include <stdint.h>
+// -- GODOT start --
+#include <limits.h> // INT_MAX, UINT_MAX
+// -- GODOT end --
+
namespace xatlas {
typedef void (*PrintFunc)(const char *, ...);
struct Atlas;
-struct CharterOptions {
+struct CharterOptions
+{
float proxyFitMetricWeight;
float roundnessMetricWeight;
float straightnessMetricWeight;
@@ -20,7 +23,8 @@ struct CharterOptions {
float maxChartArea;
float maxBoundaryLength;
- CharterOptions() {
+ CharterOptions()
+ {
// These are the default values we use on The Witness.
proxyFitMetricWeight = 2.0f;
roundnessMetricWeight = 0.01f;
@@ -39,15 +43,18 @@ struct CharterOptions {
}
};
-struct PackMethod {
- enum Enum {
+struct PackMethod
+{
+ enum Enum
+ {
TexelArea, // texel_area determines resolution
ApproximateResolution, // guess texel_area to approximately match desired resolution
ExactResolution // run the packer multiple times to exactly match the desired resolution (slow)
};
};
-struct PackerOptions {
+struct PackerOptions
+{
PackMethod::Enum method;
// 0 - brute force
@@ -59,13 +66,14 @@ struct PackerOptions {
// Avoid brute force packing, since it can be unusably slow in some situations.
int quality;
- float texelArea; // This is not really texel area, but 1 / texel width?
+ float texelArea; // This is not really texel area, but 1 / texel width?
uint32_t resolution;
- bool blockAlign; // Align charts to 4x4 blocks.
- bool conservative; // Pack charts with extra padding.
+ bool blockAlign; // Align charts to 4x4 blocks.
+ bool conservative; // Pack charts with extra padding.
int padding;
- PackerOptions() {
+ PackerOptions()
+ {
method = PackMethod::ApproximateResolution;
quality = 1;
texelArea = 8;
@@ -76,8 +84,10 @@ struct PackerOptions {
}
};
-struct AddMeshErrorCode {
- enum Enum {
+struct AddMeshErrorCode
+{
+ enum Enum
+ {
Success,
AlreadyAddedEdge, // index0 and index1 are the edge indices
DegenerateColocalEdge, // index0 and index1 are the edge indices
@@ -90,20 +100,24 @@ struct AddMeshErrorCode {
};
};
-struct AddMeshError {
+struct AddMeshError
+{
AddMeshErrorCode::Enum code;
uint32_t face;
uint32_t index0, index1;
};
-struct IndexFormat {
- enum Enum {
+struct IndexFormat
+{
+ enum Enum
+ {
HalfFloat,
Float
};
};
-struct InputMesh {
+struct InputMesh
+{
uint32_t vertexCount;
const void *vertexPositionData;
uint32_t vertexPositionStride;
@@ -124,17 +138,20 @@ struct InputMesh {
const uint16_t *faceMaterialData;
};
-struct OutputChart {
+struct OutputChart
+{
uint32_t *indexArray;
uint32_t indexCount;
};
-struct OutputVertex {
+struct OutputVertex
+{
float uv[2];
- uint32_t xref; // Index of input vertex from which this output vertex originated.
+ uint32_t xref; // Index of input vertex from which this output vertex originated.
};
-struct OutputMesh {
+struct OutputMesh
+{
OutputChart *chartArray;
uint32_t chartCount;
uint32_t *indexArray;
@@ -152,7 +169,7 @@ void Generate(Atlas *atlas, CharterOptions charterOptions = CharterOptions(), Pa
uint32_t GetWidth(const Atlas *atlas);
uint32_t GetHeight(const Atlas *atlas);
uint32_t GetNumCharts(const Atlas *atlas);
-const OutputMesh *const *GetOutputMeshes(const Atlas *atlas);
+const OutputMesh * const *GetOutputMeshes(const Atlas *atlas);
const char *StringForEnum(AddMeshErrorCode::Enum error);
} // namespace xatlas
diff --git a/thirdparty/zstd/1314.diff b/thirdparty/zstd/1314.diff
deleted file mode 100644
index c9f4efadbf..0000000000
--- a/thirdparty/zstd/1314.diff
+++ /dev/null
@@ -1,13 +0,0 @@
-diff --git a/common/cpu.h b/common/cpu.h
-index 88e0ebf44..eeb428ad5 100644
---- a/common/cpu.h
-+++ b/common/cpu.h
-@@ -36,7 +36,7 @@ MEM_STATIC ZSTD_cpuid_t ZSTD_cpuid(void) {
- U32 f1d = 0;
- U32 f7b = 0;
- U32 f7c = 0;
--#ifdef _MSC_VER
-+#if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86))
- int reg[4];
- __cpuid((int*)reg, 0);
- {
diff --git a/thirdparty/zstd/common/bitstream.h b/thirdparty/zstd/common/bitstream.h
index f7f389fe0f..d955bd677b 100644
--- a/thirdparty/zstd/common/bitstream.h
+++ b/thirdparty/zstd/common/bitstream.h
@@ -1,8 +1,7 @@
/* ******************************************************************
bitstream
Part of FSE library
- header file (to include)
- Copyright (C) 2013-2017, Yann Collet.
+ Copyright (C) 2013-present, Yann Collet.
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
@@ -49,21 +48,10 @@ extern "C" {
* Dependencies
******************************************/
#include "mem.h" /* unaligned access routines */
+#include "debug.h" /* assert(), DEBUGLOG(), RAWLOG() */
#include "error_private.h" /* error codes and messages */
-/*-*************************************
-* Debug
-***************************************/
-#if defined(BIT_DEBUG) && (BIT_DEBUG>=1)
-# include <assert.h>
-#else
-# ifndef assert
-# define assert(condition) ((void)0)
-# endif
-#endif
-
-
/*=========================================
* Target specific
=========================================*/
@@ -83,8 +71,7 @@ extern "C" {
* A critical property of these streams is that they encode and decode in **reverse** direction.
* So the first bit sequence you add will be the last to be read, like a LIFO stack.
*/
-typedef struct
-{
+typedef struct {
size_t bitContainer;
unsigned bitPos;
char* startPtr;
@@ -118,8 +105,7 @@ MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC);
/*-********************************************
* bitStream decoding API (read backward)
**********************************************/
-typedef struct
-{
+typedef struct {
size_t bitContainer;
unsigned bitsConsumed;
const char* ptr;
@@ -236,7 +222,8 @@ MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC,
}
/*! BIT_addBitsFast() :
- * works only if `value` is _clean_, meaning all high bits above nbBits are 0 */
+ * works only if `value` is _clean_,
+ * meaning all high bits above nbBits are 0 */
MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC,
size_t value, unsigned nbBits)
{
@@ -352,17 +339,10 @@ MEM_STATIC size_t BIT_getUpperBits(size_t bitContainer, U32 const start)
MEM_STATIC size_t BIT_getMiddleBits(size_t bitContainer, U32 const start, U32 const nbBits)
{
-#if defined(__BMI__) && defined(__GNUC__) && __GNUC__*1000+__GNUC_MINOR__ >= 4008 /* experimental */
-# if defined(__x86_64__)
- if (sizeof(bitContainer)==8)
- return _bextr_u64(bitContainer, start, nbBits);
- else
-# endif
- return _bextr_u32(bitContainer, start, nbBits);
-#else
+ U32 const regMask = sizeof(bitContainer)*8 - 1;
+ /* if start > regMask, bitstream is corrupted, and result is undefined */
assert(nbBits < BIT_MASK_SIZE);
- return (bitContainer >> start) & BIT_mask[nbBits];
-#endif
+ return (bitContainer >> (start & regMask)) & BIT_mask[nbBits];
}
MEM_STATIC size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits)
@@ -379,9 +359,13 @@ MEM_STATIC size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits)
* @return : value extracted */
MEM_STATIC size_t BIT_lookBits(const BIT_DStream_t* bitD, U32 nbBits)
{
-#if defined(__BMI__) && defined(__GNUC__) /* experimental; fails if bitD->bitsConsumed + nbBits > sizeof(bitD->bitContainer)*8 */
+ /* arbitrate between double-shift and shift+mask */
+#if 1
+ /* if bitD->bitsConsumed + nbBits > sizeof(bitD->bitContainer)*8,
+ * bitstream is likely corrupted, and result is undefined */
return BIT_getMiddleBits(bitD->bitContainer, (sizeof(bitD->bitContainer)*8) - bitD->bitsConsumed - nbBits, nbBits);
#else
+ /* this code path is slower on my os-x laptop */
U32 const regMask = sizeof(bitD->bitContainer)*8 - 1;
return ((bitD->bitContainer << (bitD->bitsConsumed & regMask)) >> 1) >> ((regMask-nbBits) & regMask);
#endif
@@ -405,7 +389,7 @@ MEM_STATIC void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits)
* Read (consume) next n bits from local register and update.
* Pay attention to not read more than nbBits contained into local register.
* @return : extracted value. */
-MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, U32 nbBits)
+MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits)
{
size_t const value = BIT_lookBits(bitD, nbBits);
BIT_skipBits(bitD, nbBits);
@@ -414,7 +398,7 @@ MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, U32 nbBits)
/*! BIT_readBitsFast() :
* unsafe version; only works only if nbBits >= 1 */
-MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, U32 nbBits)
+MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits)
{
size_t const value = BIT_lookBitsFast(bitD, nbBits);
assert(nbBits >= 1);
diff --git a/thirdparty/zstd/common/compiler.h b/thirdparty/zstd/common/compiler.h
index e90a3bcde3..0836e3ed27 100644
--- a/thirdparty/zstd/common/compiler.h
+++ b/thirdparty/zstd/common/compiler.h
@@ -15,6 +15,8 @@
* Compiler specifics
*********************************************************/
/* force inlining */
+
+#if !defined(ZSTD_NO_INLINE)
#if defined (__GNUC__) || defined(__cplusplus) || defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */
# define INLINE_KEYWORD inline
#else
@@ -29,9 +31,16 @@
# define FORCE_INLINE_ATTR
#endif
+#else
+
+#define INLINE_KEYWORD
+#define FORCE_INLINE_ATTR
+
+#endif
+
/**
* FORCE_INLINE_TEMPLATE is used to define C "templates", which take constant
- * parameters. They must be inlined for the compiler to elimininate the constant
+ * parameters. They must be inlined for the compiler to eliminate the constant
* branches.
*/
#define FORCE_INLINE_TEMPLATE static INLINE_KEYWORD FORCE_INLINE_ATTR
@@ -77,9 +86,9 @@
* Enabled for clang & gcc >=4.8 on x86 when BMI2 isn't enabled by default.
*/
#ifndef DYNAMIC_BMI2
- #if (defined(__clang__) && __has_attribute(__target__)) \
+ #if ((defined(__clang__) && __has_attribute(__target__)) \
|| (defined(__GNUC__) \
- && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) \
+ && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)))) \
&& (defined(__x86_64__) || defined(_M_X86)) \
&& !defined(__BMI2__)
# define DYNAMIC_BMI2 1
@@ -88,15 +97,35 @@
#endif
#endif
-/* prefetch */
-#if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_I86)) /* _mm_prefetch() is not defined outside of x86/x64 */
-# include <mmintrin.h> /* https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx */
-# define PREFETCH(ptr) _mm_prefetch((const char*)ptr, _MM_HINT_T0)
-#elif defined(__GNUC__)
-# define PREFETCH(ptr) __builtin_prefetch(ptr, 0, 0)
+/* prefetch
+ * can be disabled, by declaring NO_PREFETCH build macro */
+#if defined(NO_PREFETCH)
+# define PREFETCH_L1(ptr) (void)(ptr) /* disabled */
+# define PREFETCH_L2(ptr) (void)(ptr) /* disabled */
#else
-# define PREFETCH(ptr) /* disabled */
-#endif
+# if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_I86)) /* _mm_prefetch() is not defined outside of x86/x64 */
+# include <mmintrin.h> /* https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx */
+# define PREFETCH_L1(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T0)
+# define PREFETCH_L2(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T1)
+# elif defined(__GNUC__) && ( (__GNUC__ >= 4) || ( (__GNUC__ == 3) && (__GNUC_MINOR__ >= 1) ) )
+# define PREFETCH_L1(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 3 /* locality */)
+# define PREFETCH_L2(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 2 /* locality */)
+# else
+# define PREFETCH_L1(ptr) (void)(ptr) /* disabled */
+# define PREFETCH_L2(ptr) (void)(ptr) /* disabled */
+# endif
+#endif /* NO_PREFETCH */
+
+#define CACHELINE_SIZE 64
+
+#define PREFETCH_AREA(p, s) { \
+ const char* const _ptr = (const char*)(p); \
+ size_t const _size = (size_t)(s); \
+ size_t _pos; \
+ for (_pos=0; _pos<_size; _pos+=CACHELINE_SIZE) { \
+ PREFETCH_L2(_ptr + _pos); \
+ } \
+}
/* disable warnings */
#ifdef _MSC_VER /* Visual Studio */
diff --git a/thirdparty/zstd/common/cpu.h b/thirdparty/zstd/common/cpu.h
index a109520a33..5f0923fc92 100644
--- a/thirdparty/zstd/common/cpu.h
+++ b/thirdparty/zstd/common/cpu.h
@@ -72,14 +72,13 @@ MEM_STATIC ZSTD_cpuid_t ZSTD_cpuid(void) {
"cpuid\n\t"
"popl %%ebx\n\t"
: "=a"(f1a), "=c"(f1c), "=d"(f1d)
- : "a"(1)
- :);
+ : "a"(1));
}
if (n >= 7) {
__asm__(
"pushl %%ebx\n\t"
"cpuid\n\t"
- "movl %%ebx, %%eax\n\r"
+ "movl %%ebx, %%eax\n\t"
"popl %%ebx"
: "=a"(f7b), "=c"(f7c)
: "a"(7), "c"(0)
diff --git a/thirdparty/zstd/common/debug.c b/thirdparty/zstd/common/debug.c
new file mode 100644
index 0000000000..3ebdd1cb15
--- /dev/null
+++ b/thirdparty/zstd/common/debug.c
@@ -0,0 +1,44 @@
+/* ******************************************************************
+ debug
+ Part of FSE library
+ Copyright (C) 2013-present, Yann Collet.
+
+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
+
+ 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.
+
+ 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.
+
+ You can contact the author at :
+ - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
+****************************************************************** */
+
+
+/*
+ * This module only hosts one global variable
+ * which can be used to dynamically influence the verbosity of traces,
+ * such as DEBUGLOG and RAWLOG
+ */
+
+#include "debug.h"
+
+int g_debuglevel = DEBUGLEVEL;
diff --git a/thirdparty/zstd/common/debug.h b/thirdparty/zstd/common/debug.h
new file mode 100644
index 0000000000..b4fc89d497
--- /dev/null
+++ b/thirdparty/zstd/common/debug.h
@@ -0,0 +1,134 @@
+/* ******************************************************************
+ debug
+ Part of FSE library
+ Copyright (C) 2013-present, Yann Collet.
+
+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
+
+ 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.
+
+ 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.
+
+ You can contact the author at :
+ - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
+****************************************************************** */
+
+
+/*
+ * The purpose of this header is to enable debug functions.
+ * They regroup assert(), DEBUGLOG() and RAWLOG() for run-time,
+ * and DEBUG_STATIC_ASSERT() for compile-time.
+ *
+ * By default, DEBUGLEVEL==0, which means run-time debug is disabled.
+ *
+ * Level 1 enables assert() only.
+ * Starting level 2, traces can be generated and pushed to stderr.
+ * The higher the level, the more verbose the traces.
+ *
+ * It's possible to dynamically adjust level using variable g_debug_level,
+ * which is only declared if DEBUGLEVEL>=2,
+ * and is a global variable, not multi-thread protected (use with care)
+ */
+
+#ifndef DEBUG_H_12987983217
+#define DEBUG_H_12987983217
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+
+/* static assert is triggered at compile time, leaving no runtime artefact.
+ * static assert only works with compile-time constants.
+ * Also, this variant can only be used inside a function. */
+#define DEBUG_STATIC_ASSERT(c) (void)sizeof(char[(c) ? 1 : -1])
+
+
+/* DEBUGLEVEL is expected to be defined externally,
+ * typically through compiler command line.
+ * Value must be a number. */
+#ifndef DEBUGLEVEL
+# define DEBUGLEVEL 0
+#endif
+
+
+/* DEBUGFILE can be defined externally,
+ * typically through compiler command line.
+ * note : currently useless.
+ * Value must be stderr or stdout */
+#ifndef DEBUGFILE
+# define DEBUGFILE stderr
+#endif
+
+
+/* recommended values for DEBUGLEVEL :
+ * 0 : release mode, no debug, all run-time checks disabled
+ * 1 : enables assert() only, no display
+ * 2 : reserved, for currently active debug path
+ * 3 : events once per object lifetime (CCtx, CDict, etc.)
+ * 4 : events once per frame
+ * 5 : events once per block
+ * 6 : events once per sequence (verbose)
+ * 7+: events at every position (*very* verbose)
+ *
+ * It's generally inconvenient to output traces > 5.
+ * In which case, it's possible to selectively trigger high verbosity levels
+ * by modifying g_debug_level.
+ */
+
+#if (DEBUGLEVEL>=1)
+# include <assert.h>
+#else
+# ifndef assert /* assert may be already defined, due to prior #include <assert.h> */
+# define assert(condition) ((void)0) /* disable assert (default) */
+# endif
+#endif
+
+#if (DEBUGLEVEL>=2)
+# include <stdio.h>
+extern int g_debuglevel; /* the variable is only declared,
+ it actually lives in debug.c,
+ and is shared by the whole process.
+ It's not thread-safe.
+ It's useful when enabling very verbose levels
+ on selective conditions (such as position in src) */
+
+# define RAWLOG(l, ...) { \
+ if (l<=g_debuglevel) { \
+ fprintf(stderr, __VA_ARGS__); \
+ } }
+# define DEBUGLOG(l, ...) { \
+ if (l<=g_debuglevel) { \
+ fprintf(stderr, __FILE__ ": " __VA_ARGS__); \
+ fprintf(stderr, " \n"); \
+ } }
+#else
+# define RAWLOG(l, ...) {} /* disabled */
+# define DEBUGLOG(l, ...) {} /* disabled */
+#endif
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* DEBUG_H_12987983217 */
diff --git a/thirdparty/zstd/common/entropy_common.c b/thirdparty/zstd/common/entropy_common.c
index b37a082fee..b12944e1de 100644
--- a/thirdparty/zstd/common/entropy_common.c
+++ b/thirdparty/zstd/common/entropy_common.c
@@ -72,7 +72,21 @@ size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* t
unsigned charnum = 0;
int previous0 = 0;
- if (hbSize < 4) return ERROR(srcSize_wrong);
+ if (hbSize < 4) {
+ /* This function only works when hbSize >= 4 */
+ char buffer[4];
+ memset(buffer, 0, sizeof(buffer));
+ memcpy(buffer, headerBuffer, hbSize);
+ { size_t const countSize = FSE_readNCount(normalizedCounter, maxSVPtr, tableLogPtr,
+ buffer, sizeof(buffer));
+ if (FSE_isError(countSize)) return countSize;
+ if (countSize > hbSize) return ERROR(corruption_detected);
+ return countSize;
+ } }
+ assert(hbSize >= 4);
+
+ /* init */
+ memset(normalizedCounter, 0, (*maxSVPtr+1) * sizeof(normalizedCounter[0])); /* all symbols not present in NCount have a frequency of 0 */
bitStream = MEM_readLE32(ip);
nbBits = (bitStream & 0xF) + FSE_MIN_TABLELOG; /* extract tableLog */
if (nbBits > FSE_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge);
@@ -105,6 +119,7 @@ size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* t
if (n0 > *maxSVPtr) return ERROR(maxSymbolValue_tooSmall);
while (charnum < n0) normalizedCounter[charnum++] = 0;
if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {
+ assert((bitCount >> 3) <= 3); /* For first condition to work */
ip += bitCount>>3;
bitCount &= 7;
bitStream = MEM_readLE32(ip) >> bitCount;
diff --git a/thirdparty/zstd/common/error_private.c b/thirdparty/zstd/common/error_private.c
index d004ee636c..7c1bb67a23 100644
--- a/thirdparty/zstd/common/error_private.c
+++ b/thirdparty/zstd/common/error_private.c
@@ -14,6 +14,10 @@
const char* ERR_getErrorString(ERR_enum code)
{
+#ifdef ZSTD_STRIP_ERROR_STRINGS
+ (void)code;
+ return "Error strings stripped";
+#else
static const char* const notErrorCode = "Unspecified error code";
switch( code )
{
@@ -39,10 +43,12 @@ const char* ERR_getErrorString(ERR_enum code)
case PREFIX(dictionaryCreation_failed): return "Cannot create Dictionary from provided samples";
case PREFIX(dstSize_tooSmall): return "Destination buffer is too small";
case PREFIX(srcSize_wrong): return "Src size is incorrect";
+ case PREFIX(dstBuffer_null): return "Operation on NULL destination buffer";
/* following error codes are not stable and may be removed or changed in a future version */
case PREFIX(frameIndex_tooLarge): return "Frame index is too large";
case PREFIX(seekableIO): return "An I/O error occurred when reading/seeking";
case PREFIX(maxCode):
default: return notErrorCode;
}
+#endif
}
diff --git a/thirdparty/zstd/common/fse.h b/thirdparty/zstd/common/fse.h
index 6a1d272be5..811c670bdd 100644
--- a/thirdparty/zstd/common/fse.h
+++ b/thirdparty/zstd/common/fse.h
@@ -72,6 +72,7 @@ extern "C" {
#define FSE_VERSION_NUMBER (FSE_VERSION_MAJOR *100*100 + FSE_VERSION_MINOR *100 + FSE_VERSION_RELEASE)
FSE_PUBLIC_API unsigned FSE_versionNumber(void); /**< library version number; to be used when checking dll version */
+
/*-****************************************
* FSE simple functions
******************************************/
@@ -129,7 +130,7 @@ FSE_PUBLIC_API size_t FSE_compress2 (void* dst, size_t dstSize, const void* src,
******************************************/
/*!
FSE_compress() does the following:
-1. count symbol occurrence from source[] into table count[]
+1. count symbol occurrence from source[] into table count[] (see hist.h)
2. normalize counters so that sum(count[]) == Power_of_2 (2^tableLog)
3. save normalized counters to memory buffer using writeNCount()
4. build encoding table 'CTable' from normalized counters
@@ -147,15 +148,6 @@ or to save and provide normalized distribution using external method.
/* *** COMPRESSION *** */
-/*! FSE_count():
- Provides the precise count of each byte within a table 'count'.
- 'count' is a table of unsigned int, of minimum size (*maxSymbolValuePtr+1).
- *maxSymbolValuePtr will be updated if detected smaller than initial value.
- @return : the count of the most frequent symbol (which is not identified).
- if return == srcSize, there is only one symbol.
- Can also return an error code, which can be tested with FSE_isError(). */
-FSE_PUBLIC_API size_t FSE_count(unsigned* count, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize);
-
/*! FSE_optimalTableLog():
dynamically downsize 'tableLog' when conditions are met.
It saves CPU time, by using smaller tables, while preserving or even improving compression ratio.
@@ -167,7 +159,8 @@ FSE_PUBLIC_API unsigned FSE_optimalTableLog(unsigned maxTableLog, size_t srcSize
'normalizedCounter' is a table of short, of minimum size (maxSymbolValue+1).
@return : tableLog,
or an errorCode, which can be tested using FSE_isError() */
-FSE_PUBLIC_API size_t FSE_normalizeCount(short* normalizedCounter, unsigned tableLog, const unsigned* count, size_t srcSize, unsigned maxSymbolValue);
+FSE_PUBLIC_API size_t FSE_normalizeCount(short* normalizedCounter, unsigned tableLog,
+ const unsigned* count, size_t srcSize, unsigned maxSymbolValue);
/*! FSE_NCountWriteBound():
Provides the maximum possible size of an FSE normalized table, given 'maxSymbolValue' and 'tableLog'.
@@ -178,8 +171,9 @@ FSE_PUBLIC_API size_t FSE_NCountWriteBound(unsigned maxSymbolValue, unsigned tab
Compactly save 'normalizedCounter' into 'buffer'.
@return : size of the compressed table,
or an errorCode, which can be tested using FSE_isError(). */
-FSE_PUBLIC_API size_t FSE_writeNCount (void* buffer, size_t bufferSize, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);
-
+FSE_PUBLIC_API size_t FSE_writeNCount (void* buffer, size_t bufferSize,
+ const short* normalizedCounter,
+ unsigned maxSymbolValue, unsigned tableLog);
/*! Constructor and Destructor of FSE_CTable.
Note that FSE_CTable size depends on 'tableLog' and 'maxSymbolValue' */
@@ -250,7 +244,9 @@ If there is an error, the function will return an ErrorCode (which can be tested
@return : size read from 'rBuffer',
or an errorCode, which can be tested using FSE_isError().
maxSymbolValuePtr[0] and tableLogPtr[0] will also be updated with their respective values */
-FSE_PUBLIC_API size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSymbolValuePtr, unsigned* tableLogPtr, const void* rBuffer, size_t rBuffSize);
+FSE_PUBLIC_API size_t FSE_readNCount (short* normalizedCounter,
+ unsigned* maxSymbolValuePtr, unsigned* tableLogPtr,
+ const void* rBuffer, size_t rBuffSize);
/*! Constructor and Destructor of FSE_DTable.
Note that its size depends on 'tableLog' */
@@ -325,33 +321,8 @@ If there is an error, the function will return an error code, which can be teste
/* *****************************************
-* FSE advanced API
-*******************************************/
-/* FSE_count_wksp() :
- * Same as FSE_count(), but using an externally provided scratch buffer.
- * `workSpace` size must be table of >= `1024` unsigned
- */
-size_t FSE_count_wksp(unsigned* count, unsigned* maxSymbolValuePtr,
- const void* source, size_t sourceSize, unsigned* workSpace);
-
-/** FSE_countFast() :
- * same as FSE_count(), but blindly trusts that all byte values within src are <= *maxSymbolValuePtr
- */
-size_t FSE_countFast(unsigned* count, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize);
-
-/* FSE_countFast_wksp() :
- * Same as FSE_countFast(), but using an externally provided scratch buffer.
- * `workSpace` must be a table of minimum `1024` unsigned
- */
-size_t FSE_countFast_wksp(unsigned* count, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize, unsigned* workSpace);
-
-/*! FSE_count_simple() :
- * Same as FSE_countFast(), but does not use any additional memory (not even on stack).
- * This function is unsafe, and will segfault if any value within `src` is `> *maxSymbolValuePtr` (presuming it's also the size of `count`).
-*/
-size_t FSE_count_simple(unsigned* count, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize);
-
-
+ * FSE advanced API
+ ***************************************** */
unsigned FSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, unsigned minus);
/**< same as FSE_optimalTableLog(), which used `minus==2` */
@@ -387,7 +358,7 @@ size_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size
typedef enum {
FSE_repeat_none, /**< Cannot use the previous table */
FSE_repeat_check, /**< Can use the previous table but it must be checked */
- FSE_repeat_valid /**< Can use the previous table and it is asumed to be valid */
+ FSE_repeat_valid /**< Can use the previous table and it is assumed to be valid */
} FSE_repeat;
/* *****************************************
@@ -541,7 +512,7 @@ MEM_STATIC void FSE_initCState(FSE_CState_t* statePtr, const FSE_CTable* ct)
const U32 tableLog = MEM_read16(ptr);
statePtr->value = (ptrdiff_t)1<<tableLog;
statePtr->stateTable = u16ptr+2;
- statePtr->symbolTT = ((const U32*)ct + 1 + (tableLog ? (1<<(tableLog-1)) : 1));
+ statePtr->symbolTT = ct + 1 + (tableLog ? (1<<(tableLog-1)) : 1);
statePtr->stateLog = tableLog;
}
@@ -560,7 +531,7 @@ MEM_STATIC void FSE_initCState2(FSE_CState_t* statePtr, const FSE_CTable* ct, U3
}
}
-MEM_STATIC void FSE_encodeSymbol(BIT_CStream_t* bitC, FSE_CState_t* statePtr, U32 symbol)
+MEM_STATIC void FSE_encodeSymbol(BIT_CStream_t* bitC, FSE_CState_t* statePtr, unsigned symbol)
{
FSE_symbolCompressionTransform const symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol];
const U16* const stateTable = (const U16*)(statePtr->stateTable);
@@ -576,6 +547,39 @@ MEM_STATIC void FSE_flushCState(BIT_CStream_t* bitC, const FSE_CState_t* statePt
}
+/* FSE_getMaxNbBits() :
+ * Approximate maximum cost of a symbol, in bits.
+ * Fractional get rounded up (i.e : a symbol with a normalized frequency of 3 gives the same result as a frequency of 2)
+ * note 1 : assume symbolValue is valid (<= maxSymbolValue)
+ * note 2 : if freq[symbolValue]==0, @return a fake cost of tableLog+1 bits */
+MEM_STATIC U32 FSE_getMaxNbBits(const void* symbolTTPtr, U32 symbolValue)
+{
+ const FSE_symbolCompressionTransform* symbolTT = (const FSE_symbolCompressionTransform*) symbolTTPtr;
+ return (symbolTT[symbolValue].deltaNbBits + ((1<<16)-1)) >> 16;
+}
+
+/* FSE_bitCost() :
+ * Approximate symbol cost, as fractional value, using fixed-point format (accuracyLog fractional bits)
+ * note 1 : assume symbolValue is valid (<= maxSymbolValue)
+ * note 2 : if freq[symbolValue]==0, @return a fake cost of tableLog+1 bits */
+MEM_STATIC U32 FSE_bitCost(const void* symbolTTPtr, U32 tableLog, U32 symbolValue, U32 accuracyLog)
+{
+ const FSE_symbolCompressionTransform* symbolTT = (const FSE_symbolCompressionTransform*) symbolTTPtr;
+ U32 const minNbBits = symbolTT[symbolValue].deltaNbBits >> 16;
+ U32 const threshold = (minNbBits+1) << 16;
+ assert(tableLog < 16);
+ assert(accuracyLog < 31-tableLog); /* ensure enough room for renormalization double shift */
+ { U32 const tableSize = 1 << tableLog;
+ U32 const deltaFromThreshold = threshold - (symbolTT[symbolValue].deltaNbBits + tableSize);
+ U32 const normalizedDeltaFromThreshold = (deltaFromThreshold << accuracyLog) >> tableLog; /* linear interpolation (very approximate) */
+ U32 const bitMultiplier = 1 << accuracyLog;
+ assert(symbolTT[symbolValue].deltaNbBits + tableSize <= threshold);
+ assert(normalizedDeltaFromThreshold <= bitMultiplier);
+ return (minNbBits+1)*bitMultiplier - normalizedDeltaFromThreshold;
+ }
+}
+
+
/* ====== Decompression ====== */
typedef struct {
diff --git a/thirdparty/zstd/common/fse_decompress.c b/thirdparty/zstd/common/fse_decompress.c
index 4c66c3b774..72bbead5be 100644
--- a/thirdparty/zstd/common/fse_decompress.c
+++ b/thirdparty/zstd/common/fse_decompress.c
@@ -49,7 +49,7 @@
* Error Management
****************************************************************/
#define FSE_isError ERR_isError
-#define FSE_STATIC_ASSERT(c) { enum { FSE_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */
+#define FSE_STATIC_ASSERT(c) DEBUG_STATIC_ASSERT(c) /* use only *after* variable declarations */
/* check and forward error code */
#define CHECK_F(f) { size_t const e = f; if (FSE_isError(e)) return e; }
diff --git a/thirdparty/zstd/common/huf.h b/thirdparty/zstd/common/huf.h
index b4645b4e51..6b572c448d 100644
--- a/thirdparty/zstd/common/huf.h
+++ b/thirdparty/zstd/common/huf.h
@@ -1,7 +1,7 @@
/* ******************************************************************
- Huffman coder, part of New Generation Entropy library
- header file
- Copyright (C) 2013-2016, Yann Collet.
+ huff0 huffman codec,
+ part of Finite State Entropy library
+ Copyright (C) 2013-present, Yann Collet.
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
@@ -163,25 +163,29 @@ HUF_PUBLIC_API size_t HUF_compress4X_wksp (void* dst, size_t dstCapacity,
/* static allocation of HUF's DTable */
typedef U32 HUF_DTable;
#define HUF_DTABLE_SIZE(maxTableLog) (1 + (1<<(maxTableLog)))
-#define HUF_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) \
+#define HUF_CREATE_STATIC_DTABLEX1(DTable, maxTableLog) \
HUF_DTable DTable[HUF_DTABLE_SIZE((maxTableLog)-1)] = { ((U32)((maxTableLog)-1) * 0x01000001) }
-#define HUF_CREATE_STATIC_DTABLEX4(DTable, maxTableLog) \
+#define HUF_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) \
HUF_DTable DTable[HUF_DTABLE_SIZE(maxTableLog)] = { ((U32)(maxTableLog) * 0x01000001) }
/* ****************************************
* Advanced decompression functions
******************************************/
-size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< single-symbol decoder */
-size_t HUF_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< double-symbols decoder */
+size_t HUF_decompress4X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< single-symbol decoder */
+#ifndef HUF_FORCE_DECOMPRESS_X1
+size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< double-symbols decoder */
+#endif
size_t HUF_decompress4X_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< decodes RLE and uncompressed */
size_t HUF_decompress4X_hufOnly(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< considers RLE and uncompressed as errors */
size_t HUF_decompress4X_hufOnly_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< considers RLE and uncompressed as errors */
-size_t HUF_decompress4X2_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< single-symbol decoder */
-size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< single-symbol decoder */
-size_t HUF_decompress4X4_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< double-symbols decoder */
-size_t HUF_decompress4X4_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< double-symbols decoder */
+size_t HUF_decompress4X1_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< single-symbol decoder */
+size_t HUF_decompress4X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< single-symbol decoder */
+#ifndef HUF_FORCE_DECOMPRESS_X1
+size_t HUF_decompress4X2_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< double-symbols decoder */
+size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< double-symbols decoder */
+#endif
/* ****************************************
@@ -208,7 +212,7 @@ size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, si
typedef enum {
HUF_repeat_none, /**< Cannot use the previous table */
HUF_repeat_check, /**< Can use the previous table but it must be checked. Note : The previous table must have been constructed by HUF_compress{1, 4}X_repeat */
- HUF_repeat_valid /**< Can use the previous table and it is asumed to be valid */
+ HUF_repeat_valid /**< Can use the previous table and it is assumed to be valid */
} HUF_repeat;
/** HUF_compress4X_repeat() :
* Same as HUF_compress4X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none.
@@ -227,7 +231,9 @@ size_t HUF_compress4X_repeat(void* dst, size_t dstSize,
*/
#define HUF_CTABLE_WORKSPACE_SIZE_U32 (2*HUF_SYMBOLVALUE_MAX +1 +1)
#define HUF_CTABLE_WORKSPACE_SIZE (HUF_CTABLE_WORKSPACE_SIZE_U32 * sizeof(unsigned))
-size_t HUF_buildCTable_wksp (HUF_CElt* tree, const U32* count, U32 maxSymbolValue, U32 maxNbBits, void* workSpace, size_t wkspSize);
+size_t HUF_buildCTable_wksp (HUF_CElt* tree,
+ const unsigned* count, U32 maxSymbolValue, U32 maxNbBits,
+ void* workSpace, size_t wkspSize);
/*! HUF_readStats() :
* Read compact Huffman tree, saved by HUF_writeCTable().
@@ -242,10 +248,15 @@ size_t HUF_readStats(BYTE* huffWeight, size_t hwSize,
* Loading a CTable saved with HUF_writeCTable() */
size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize);
+/** HUF_getNbBits() :
+ * Read nbBits from CTable symbolTable, for symbol `symbolValue` presumed <= HUF_SYMBOLVALUE_MAX
+ * Note 1 : is not inlined, as HUF_CElt definition is private
+ * Note 2 : const void* used, so that it can provide a statically allocated table as argument (which uses type U32) */
+U32 HUF_getNbBits(const void* symbolTable, U32 symbolValue);
/*
* HUF_decompress() does the following:
- * 1. select the decompression algorithm (X2, X4) based on pre-computed heuristics
+ * 1. select the decompression algorithm (X1, X2) based on pre-computed heuristics
* 2. build Huffman table from save, using HUF_readDTableX?()
* 3. decode 1 or 4 segments in parallel using HUF_decompress?X?_usingDTable()
*/
@@ -253,13 +264,13 @@ size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void
/** HUF_selectDecoder() :
* Tells which decoder is likely to decode faster,
* based on a set of pre-computed metrics.
- * @return : 0==HUF_decompress4X2, 1==HUF_decompress4X4 .
+ * @return : 0==HUF_decompress4X1, 1==HUF_decompress4X2 .
* Assumption : 0 < dstSize <= 128 KB */
U32 HUF_selectDecoder (size_t dstSize, size_t cSrcSize);
/**
* The minimum workspace size for the `workSpace` used in
- * HUF_readDTableX2_wksp() and HUF_readDTableX4_wksp().
+ * HUF_readDTableX1_wksp() and HUF_readDTableX2_wksp().
*
* The space used depends on HUF_TABLELOG_MAX, ranging from ~1500 bytes when
* HUF_TABLE_LOG_MAX=12 to ~1850 bytes when HUF_TABLE_LOG_MAX=15.
@@ -270,14 +281,22 @@ U32 HUF_selectDecoder (size_t dstSize, size_t cSrcSize);
#define HUF_DECOMPRESS_WORKSPACE_SIZE (2 << 10)
#define HUF_DECOMPRESS_WORKSPACE_SIZE_U32 (HUF_DECOMPRESS_WORKSPACE_SIZE / sizeof(U32))
+#ifndef HUF_FORCE_DECOMPRESS_X2
+size_t HUF_readDTableX1 (HUF_DTable* DTable, const void* src, size_t srcSize);
+size_t HUF_readDTableX1_wksp (HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize);
+#endif
+#ifndef HUF_FORCE_DECOMPRESS_X1
size_t HUF_readDTableX2 (HUF_DTable* DTable, const void* src, size_t srcSize);
size_t HUF_readDTableX2_wksp (HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize);
-size_t HUF_readDTableX4 (HUF_DTable* DTable, const void* src, size_t srcSize);
-size_t HUF_readDTableX4_wksp (HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize);
+#endif
size_t HUF_decompress4X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);
+#ifndef HUF_FORCE_DECOMPRESS_X2
+size_t HUF_decompress4X1_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);
+#endif
+#ifndef HUF_FORCE_DECOMPRESS_X1
size_t HUF_decompress4X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);
-size_t HUF_decompress4X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);
+#endif
/* ====================== */
@@ -298,25 +317,37 @@ size_t HUF_compress1X_repeat(void* dst, size_t dstSize,
void* workSpace, size_t wkspSize, /**< `workSpace` must be aligned on 4-bytes boundaries, `wkspSize` must be >= HUF_WORKSPACE_SIZE */
HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2);
-size_t HUF_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* single-symbol decoder */
-size_t HUF_decompress1X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* double-symbol decoder */
+size_t HUF_decompress1X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* single-symbol decoder */
+#ifndef HUF_FORCE_DECOMPRESS_X1
+size_t HUF_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* double-symbol decoder */
+#endif
size_t HUF_decompress1X_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);
size_t HUF_decompress1X_DCtx_wksp (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize);
-size_t HUF_decompress1X2_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< single-symbol decoder */
-size_t HUF_decompress1X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< single-symbol decoder */
-size_t HUF_decompress1X4_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< double-symbols decoder */
-size_t HUF_decompress1X4_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< double-symbols decoder */
+#ifndef HUF_FORCE_DECOMPRESS_X2
+size_t HUF_decompress1X1_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< single-symbol decoder */
+size_t HUF_decompress1X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< single-symbol decoder */
+#endif
+#ifndef HUF_FORCE_DECOMPRESS_X1
+size_t HUF_decompress1X2_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< double-symbols decoder */
+size_t HUF_decompress1X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< double-symbols decoder */
+#endif
size_t HUF_decompress1X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable); /**< automatic selection of sing or double symbol decoder, based on DTable */
+#ifndef HUF_FORCE_DECOMPRESS_X2
+size_t HUF_decompress1X1_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);
+#endif
+#ifndef HUF_FORCE_DECOMPRESS_X1
size_t HUF_decompress1X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);
-size_t HUF_decompress1X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);
+#endif
/* BMI2 variants.
* If the CPU has BMI2 support, pass bmi2=1, otherwise pass bmi2=0.
*/
size_t HUF_decompress1X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2);
-size_t HUF_decompress1X2_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2);
+#ifndef HUF_FORCE_DECOMPRESS_X2
+size_t HUF_decompress1X1_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2);
+#endif
size_t HUF_decompress4X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2);
size_t HUF_decompress4X_hufOnly_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2);
diff --git a/thirdparty/zstd/common/mem.h b/thirdparty/zstd/common/mem.h
index 47d2300177..5da248756f 100644
--- a/thirdparty/zstd/common/mem.h
+++ b/thirdparty/zstd/common/mem.h
@@ -39,6 +39,10 @@ extern "C" {
# define MEM_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */
#endif
+#ifndef __has_builtin
+# define __has_builtin(x) 0 /* compat. with non-clang compilers */
+#endif
+
/* code only tested on 32 and 64 bits systems */
#define MEM_STATIC_ASSERT(c) { enum { MEM_static_assert = 1/(int)(!!(c)) }; }
MEM_STATIC void MEM_check(void) { MEM_STATIC_ASSERT((sizeof(size_t)==4) || (sizeof(size_t)==8)); }
@@ -57,11 +61,23 @@ MEM_STATIC void MEM_check(void) { MEM_STATIC_ASSERT((sizeof(size_t)==4) || (size
typedef uint64_t U64;
typedef int64_t S64;
#else
+# include <limits.h>
+#if CHAR_BIT != 8
+# error "this implementation requires char to be exactly 8-bit type"
+#endif
typedef unsigned char BYTE;
+#if USHRT_MAX != 65535
+# error "this implementation requires short to be exactly 16-bit type"
+#endif
typedef unsigned short U16;
typedef signed short S16;
+#if UINT_MAX != 4294967295
+# error "this implementation requires int to be exactly 32-bit type"
+#endif
typedef unsigned int U32;
typedef signed int S32;
+/* note : there are no limits defined for long long type in C90.
+ * limits exist in C99, however, in such case, <stdint.h> is preferred */
typedef unsigned long long U64;
typedef signed long long S64;
#endif
@@ -186,7 +202,8 @@ MEM_STATIC U32 MEM_swap32(U32 in)
{
#if defined(_MSC_VER) /* Visual Studio */
return _byteswap_ulong(in);
-#elif defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)
+#elif (defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)) \
+ || (defined(__clang__) && __has_builtin(__builtin_bswap32))
return __builtin_bswap32(in);
#else
return ((in << 24) & 0xff000000 ) |
@@ -200,7 +217,8 @@ MEM_STATIC U64 MEM_swap64(U64 in)
{
#if defined(_MSC_VER) /* Visual Studio */
return _byteswap_uint64(in);
-#elif defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)
+#elif (defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)) \
+ || (defined(__clang__) && __has_builtin(__builtin_bswap64))
return __builtin_bswap64(in);
#else
return ((in << 56) & 0xff00000000000000ULL) |
diff --git a/thirdparty/zstd/common/pool.c b/thirdparty/zstd/common/pool.c
index 773488b072..7a82945432 100644
--- a/thirdparty/zstd/common/pool.c
+++ b/thirdparty/zstd/common/pool.c
@@ -10,9 +10,10 @@
/* ====== Dependencies ======= */
-#include <stddef.h> /* size_t */
-#include "pool.h"
+#include <stddef.h> /* size_t */
+#include "debug.h" /* assert */
#include "zstd_internal.h" /* ZSTD_malloc, ZSTD_free */
+#include "pool.h"
/* ====== Compiler specifics ====== */
#if defined(_MSC_VER)
@@ -33,8 +34,9 @@ typedef struct POOL_job_s {
struct POOL_ctx_s {
ZSTD_customMem customMem;
/* Keep track of the threads */
- ZSTD_pthread_t *threads;
- size_t numThreads;
+ ZSTD_pthread_t* threads;
+ size_t threadCapacity;
+ size_t threadLimit;
/* The queue is a circular buffer */
POOL_job *queue;
@@ -58,10 +60,10 @@ struct POOL_ctx_s {
};
/* POOL_thread() :
- Work thread for the thread pool.
- Waits for jobs and executes them.
- @returns : NULL on failure else non-null.
-*/
+ * Work thread for the thread pool.
+ * Waits for jobs and executes them.
+ * @returns : NULL on failure else non-null.
+ */
static void* POOL_thread(void* opaque) {
POOL_ctx* const ctx = (POOL_ctx*)opaque;
if (!ctx) { return NULL; }
@@ -69,50 +71,55 @@ static void* POOL_thread(void* opaque) {
/* Lock the mutex and wait for a non-empty queue or until shutdown */
ZSTD_pthread_mutex_lock(&ctx->queueMutex);
- while (ctx->queueEmpty && !ctx->shutdown) {
+ while ( ctx->queueEmpty
+ || (ctx->numThreadsBusy >= ctx->threadLimit) ) {
+ if (ctx->shutdown) {
+ /* even if !queueEmpty, (possible if numThreadsBusy >= threadLimit),
+ * a few threads will be shutdown while !queueEmpty,
+ * but enough threads will remain active to finish the queue */
+ ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
+ return opaque;
+ }
ZSTD_pthread_cond_wait(&ctx->queuePopCond, &ctx->queueMutex);
}
- /* empty => shutting down: so stop */
- if (ctx->queueEmpty) {
- ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
- return opaque;
- }
/* Pop a job off the queue */
{ POOL_job const job = ctx->queue[ctx->queueHead];
ctx->queueHead = (ctx->queueHead + 1) % ctx->queueSize;
ctx->numThreadsBusy++;
ctx->queueEmpty = ctx->queueHead == ctx->queueTail;
/* Unlock the mutex, signal a pusher, and run the job */
- ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
ZSTD_pthread_cond_signal(&ctx->queuePushCond);
+ ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
job.function(job.opaque);
/* If the intended queue size was 0, signal after finishing job */
+ ZSTD_pthread_mutex_lock(&ctx->queueMutex);
+ ctx->numThreadsBusy--;
if (ctx->queueSize == 1) {
- ZSTD_pthread_mutex_lock(&ctx->queueMutex);
- ctx->numThreadsBusy--;
- ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
ZSTD_pthread_cond_signal(&ctx->queuePushCond);
- } }
+ }
+ ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
+ }
} /* for (;;) */
- /* Unreachable */
+ assert(0); /* Unreachable */
}
POOL_ctx* POOL_create(size_t numThreads, size_t queueSize) {
return POOL_create_advanced(numThreads, queueSize, ZSTD_defaultCMem);
}
-POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize, ZSTD_customMem customMem) {
+POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize,
+ ZSTD_customMem customMem) {
POOL_ctx* ctx;
- /* Check the parameters */
+ /* Check parameters */
if (!numThreads) { return NULL; }
/* Allocate the context and zero initialize */
ctx = (POOL_ctx*)ZSTD_calloc(sizeof(POOL_ctx), customMem);
if (!ctx) { return NULL; }
/* Initialize the job queue.
- * It needs one extra space since one space is wasted to differentiate empty
- * and full queues.
+ * It needs one extra space since one space is wasted to differentiate
+ * empty and full queues.
*/
ctx->queueSize = queueSize + 1;
ctx->queue = (POOL_job*)ZSTD_malloc(ctx->queueSize * sizeof(POOL_job), customMem);
@@ -126,7 +133,7 @@ POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize, ZSTD_customM
ctx->shutdown = 0;
/* Allocate space for the thread handles */
ctx->threads = (ZSTD_pthread_t*)ZSTD_malloc(numThreads * sizeof(ZSTD_pthread_t), customMem);
- ctx->numThreads = 0;
+ ctx->threadCapacity = 0;
ctx->customMem = customMem;
/* Check for errors */
if (!ctx->threads || !ctx->queue) { POOL_free(ctx); return NULL; }
@@ -134,11 +141,12 @@ POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize, ZSTD_customM
{ size_t i;
for (i = 0; i < numThreads; ++i) {
if (ZSTD_pthread_create(&ctx->threads[i], NULL, &POOL_thread, ctx)) {
- ctx->numThreads = i;
+ ctx->threadCapacity = i;
POOL_free(ctx);
return NULL;
} }
- ctx->numThreads = numThreads;
+ ctx->threadCapacity = numThreads;
+ ctx->threadLimit = numThreads;
}
return ctx;
}
@@ -156,8 +164,8 @@ static void POOL_join(POOL_ctx* ctx) {
ZSTD_pthread_cond_broadcast(&ctx->queuePopCond);
/* Join all of the threads */
{ size_t i;
- for (i = 0; i < ctx->numThreads; ++i) {
- ZSTD_pthread_join(ctx->threads[i], NULL);
+ for (i = 0; i < ctx->threadCapacity; ++i) {
+ ZSTD_pthread_join(ctx->threads[i], NULL); /* note : could fail */
} }
}
@@ -172,24 +180,68 @@ void POOL_free(POOL_ctx *ctx) {
ZSTD_free(ctx, ctx->customMem);
}
+
+
size_t POOL_sizeof(POOL_ctx *ctx) {
if (ctx==NULL) return 0; /* supports sizeof NULL */
return sizeof(*ctx)
+ ctx->queueSize * sizeof(POOL_job)
- + ctx->numThreads * sizeof(ZSTD_pthread_t);
+ + ctx->threadCapacity * sizeof(ZSTD_pthread_t);
+}
+
+
+/* @return : 0 on success, 1 on error */
+static int POOL_resize_internal(POOL_ctx* ctx, size_t numThreads)
+{
+ if (numThreads <= ctx->threadCapacity) {
+ if (!numThreads) return 1;
+ ctx->threadLimit = numThreads;
+ return 0;
+ }
+ /* numThreads > threadCapacity */
+ { ZSTD_pthread_t* const threadPool = (ZSTD_pthread_t*)ZSTD_malloc(numThreads * sizeof(ZSTD_pthread_t), ctx->customMem);
+ if (!threadPool) return 1;
+ /* replace existing thread pool */
+ memcpy(threadPool, ctx->threads, ctx->threadCapacity * sizeof(*threadPool));
+ ZSTD_free(ctx->threads, ctx->customMem);
+ ctx->threads = threadPool;
+ /* Initialize additional threads */
+ { size_t threadId;
+ for (threadId = ctx->threadCapacity; threadId < numThreads; ++threadId) {
+ if (ZSTD_pthread_create(&threadPool[threadId], NULL, &POOL_thread, ctx)) {
+ ctx->threadCapacity = threadId;
+ return 1;
+ } }
+ } }
+ /* successfully expanded */
+ ctx->threadCapacity = numThreads;
+ ctx->threadLimit = numThreads;
+ return 0;
+}
+
+/* @return : 0 on success, 1 on error */
+int POOL_resize(POOL_ctx* ctx, size_t numThreads)
+{
+ int result;
+ if (ctx==NULL) return 1;
+ ZSTD_pthread_mutex_lock(&ctx->queueMutex);
+ result = POOL_resize_internal(ctx, numThreads);
+ ZSTD_pthread_cond_broadcast(&ctx->queuePopCond);
+ ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
+ return result;
}
/**
* Returns 1 if the queue is full and 0 otherwise.
*
- * If the queueSize is 1 (the pool was created with an intended queueSize of 0),
- * then a queue is empty if there is a thread free and no job is waiting.
+ * When queueSize is 1 (pool was created with an intended queueSize of 0),
+ * then a queue is empty if there is a thread free _and_ no job is waiting.
*/
static int isQueueFull(POOL_ctx const* ctx) {
if (ctx->queueSize > 1) {
return ctx->queueHead == ((ctx->queueTail + 1) % ctx->queueSize);
} else {
- return ctx->numThreadsBusy == ctx->numThreads ||
+ return (ctx->numThreadsBusy == ctx->threadLimit) ||
!ctx->queueEmpty;
}
}
@@ -263,6 +315,11 @@ void POOL_free(POOL_ctx* ctx) {
(void)ctx;
}
+int POOL_resize(POOL_ctx* ctx, size_t numThreads) {
+ (void)ctx; (void)numThreads;
+ return 0;
+}
+
void POOL_add(POOL_ctx* ctx, POOL_function function, void* opaque) {
(void)ctx;
function(opaque);
diff --git a/thirdparty/zstd/common/pool.h b/thirdparty/zstd/common/pool.h
index a57e9b4fab..458d37f13c 100644
--- a/thirdparty/zstd/common/pool.h
+++ b/thirdparty/zstd/common/pool.h
@@ -30,40 +30,50 @@ typedef struct POOL_ctx_s POOL_ctx;
*/
POOL_ctx* POOL_create(size_t numThreads, size_t queueSize);
-POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize, ZSTD_customMem customMem);
+POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize,
+ ZSTD_customMem customMem);
/*! POOL_free() :
- Free a thread pool returned by POOL_create().
-*/
+ * Free a thread pool returned by POOL_create().
+ */
void POOL_free(POOL_ctx* ctx);
+/*! POOL_resize() :
+ * Expands or shrinks pool's number of threads.
+ * This is more efficient than releasing + creating a new context,
+ * since it tries to preserve and re-use existing threads.
+ * `numThreads` must be at least 1.
+ * @return : 0 when resize was successful,
+ * !0 (typically 1) if there is an error.
+ * note : only numThreads can be resized, queueSize remains unchanged.
+ */
+int POOL_resize(POOL_ctx* ctx, size_t numThreads);
+
/*! POOL_sizeof() :
- return memory usage of pool returned by POOL_create().
-*/
+ * @return threadpool memory usage
+ * note : compatible with NULL (returns 0 in this case)
+ */
size_t POOL_sizeof(POOL_ctx* ctx);
/*! POOL_function :
- The function type that can be added to a thread pool.
-*/
+ * The function type that can be added to a thread pool.
+ */
typedef void (*POOL_function)(void*);
-/*! POOL_add_function :
- The function type for a generic thread pool add function.
-*/
-typedef void (*POOL_add_function)(void*, POOL_function, void*);
/*! POOL_add() :
- Add the job `function(opaque)` to the thread pool. `ctx` must be valid.
- Possibly blocks until there is room in the queue.
- Note : The function may be executed asynchronously, so `opaque` must live until the function has been completed.
-*/
+ * Add the job `function(opaque)` to the thread pool. `ctx` must be valid.
+ * Possibly blocks until there is room in the queue.
+ * Note : The function may be executed asynchronously,
+ * therefore, `opaque` must live until function has been completed.
+ */
void POOL_add(POOL_ctx* ctx, POOL_function function, void* opaque);
/*! POOL_tryAdd() :
- Add the job `function(opaque)` to the thread pool if a worker is available.
- return immediately otherwise.
- @return : 1 if successful, 0 if not.
-*/
+ * Add the job `function(opaque)` to thread pool _if_ a worker is available.
+ * Returns immediately even if not (does not block).
+ * @return : 1 if successful, 0 if not.
+ */
int POOL_tryAdd(POOL_ctx* ctx, POOL_function function, void* opaque);
diff --git a/thirdparty/zstd/common/threading.c b/thirdparty/zstd/common/threading.c
index 8be8c8da94..f3d4fa8418 100644
--- a/thirdparty/zstd/common/threading.c
+++ b/thirdparty/zstd/common/threading.c
@@ -14,8 +14,8 @@
* This file will hold wrapper for systems, which do not support pthreads
*/
-/* create fake symbol to avoid empty trnaslation unit warning */
-int g_ZSTD_threading_useles_symbol;
+/* create fake symbol to avoid empty translation unit warning */
+int g_ZSTD_threading_useless_symbol;
#if defined(ZSTD_MULTITHREAD) && defined(_WIN32)
diff --git a/thirdparty/zstd/common/xxhash.c b/thirdparty/zstd/common/xxhash.c
index 9d9c0e963c..30599aaae4 100644
--- a/thirdparty/zstd/common/xxhash.c
+++ b/thirdparty/zstd/common/xxhash.c
@@ -66,10 +66,10 @@
/* #define XXH_ACCEPT_NULL_INPUT_POINTER 1 */
/*!XXH_FORCE_NATIVE_FORMAT :
- * By default, xxHash library provides endian-independant Hash values, based on little-endian convention.
+ * By default, xxHash library provides endian-independent Hash values, based on little-endian convention.
* Results are therefore identical for little-endian and big-endian CPU.
* This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format.
- * Should endian-independance be of no importance for your application, you may set the #define below to 1,
+ * Should endian-independence be of no importance for your application, you may set the #define below to 1,
* to improve speed for Big-endian CPU.
* This option has no impact on Little_Endian CPU.
*/
@@ -98,6 +98,7 @@
/* Modify the local functions below should you wish to use some other memory routines */
/* for malloc(), free() */
#include <stdlib.h>
+#include <stddef.h> /* size_t */
static void* XXH_malloc(size_t s) { return malloc(s); }
static void XXH_free (void* p) { free(p); }
/* for memcpy() */
diff --git a/thirdparty/zstd/common/zstd_common.c b/thirdparty/zstd/common/zstd_common.c
index bccc948892..667f4a27fc 100644
--- a/thirdparty/zstd/common/zstd_common.c
+++ b/thirdparty/zstd/common/zstd_common.c
@@ -30,8 +30,10 @@ const char* ZSTD_versionString(void) { return ZSTD_VERSION_STRING; }
/*-****************************************
* ZSTD Error Management
******************************************/
+#undef ZSTD_isError /* defined within zstd_internal.h */
/*! ZSTD_isError() :
- * tells if a return value is an error code */
+ * tells if a return value is an error code
+ * symbol is required for external callers */
unsigned ZSTD_isError(size_t code) { return ERR_isError(code); }
/*! ZSTD_getErrorName() :
@@ -46,11 +48,6 @@ ZSTD_ErrorCode ZSTD_getErrorCode(size_t code) { return ERR_getErrorCode(code); }
* provides error code string from enum */
const char* ZSTD_getErrorString(ZSTD_ErrorCode code) { return ERR_getErrorString(code); }
-/*! g_debuglog_enable :
- * turn on/off debug traces (global switch) */
-#if defined(ZSTD_DEBUG) && (ZSTD_DEBUG >= 2)
-int g_debuglog_enable = 1;
-#endif
/*=**************************************************************
diff --git a/thirdparty/zstd/common/zstd_errors.h b/thirdparty/zstd/common/zstd_errors.h
index 57533f2869..92a3433896 100644
--- a/thirdparty/zstd/common/zstd_errors.h
+++ b/thirdparty/zstd/common/zstd_errors.h
@@ -72,6 +72,7 @@ typedef enum {
ZSTD_error_workSpace_tooSmall= 66,
ZSTD_error_dstSize_tooSmall = 70,
ZSTD_error_srcSize_wrong = 72,
+ ZSTD_error_dstBuffer_null = 74,
/* following error codes are __NOT STABLE__, they can be removed or changed in future versions */
ZSTD_error_frameIndex_tooLarge = 100,
ZSTD_error_seekableIO = 102,
diff --git a/thirdparty/zstd/common/zstd_internal.h b/thirdparty/zstd/common/zstd_internal.h
index 65c08a8257..31f756ab58 100644
--- a/thirdparty/zstd/common/zstd_internal.h
+++ b/thirdparty/zstd/common/zstd_internal.h
@@ -21,6 +21,7 @@
***************************************/
#include "compiler.h"
#include "mem.h"
+#include "debug.h" /* assert, DEBUGLOG, RAWLOG, g_debuglevel */
#include "error_private.h"
#define ZSTD_STATIC_LINKING_ONLY
#include "zstd.h"
@@ -38,43 +39,11 @@
extern "C" {
#endif
-
-/*-*************************************
-* Debug
-***************************************/
-#if defined(ZSTD_DEBUG) && (ZSTD_DEBUG>=1)
-# include <assert.h>
-#else
-# ifndef assert
-# define assert(condition) ((void)0)
-# endif
-#endif
-
-#define ZSTD_STATIC_ASSERT(c) { enum { ZSTD_static_assert = 1/(int)(!!(c)) }; }
-
-#if defined(ZSTD_DEBUG) && (ZSTD_DEBUG>=2)
-# include <stdio.h>
-extern int g_debuglog_enable;
-/* recommended values for ZSTD_DEBUG display levels :
- * 1 : no display, enables assert() only
- * 2 : reserved for currently active debug path
- * 3 : events once per object lifetime (CCtx, CDict, etc.)
- * 4 : events once per frame
- * 5 : events once per block
- * 6 : events once per sequence (*very* verbose) */
-# define RAWLOG(l, ...) { \
- if ((g_debuglog_enable) & (l<=ZSTD_DEBUG)) { \
- fprintf(stderr, __VA_ARGS__); \
- } }
-# define DEBUGLOG(l, ...) { \
- if ((g_debuglog_enable) & (l<=ZSTD_DEBUG)) { \
- fprintf(stderr, __FILE__ ": " __VA_ARGS__); \
- fprintf(stderr, " \n"); \
- } }
-#else
-# define RAWLOG(l, ...) {} /* disabled */
-# define DEBUGLOG(l, ...) {} /* disabled */
-#endif
+/* ---- static assert (debug) --- */
+#define ZSTD_STATIC_ASSERT(c) DEBUG_STATIC_ASSERT(c)
+#define ZSTD_isError ERR_isError /* for inlining */
+#define FSE_isError ERR_isError
+#define HUF_isError ERR_isError
/*-*************************************
@@ -84,8 +53,50 @@ extern int g_debuglog_enable;
#undef MAX
#define MIN(a,b) ((a)<(b) ? (a) : (b))
#define MAX(a,b) ((a)>(b) ? (a) : (b))
-#define CHECK_F(f) { size_t const errcod = f; if (ERR_isError(errcod)) return errcod; } /* check and Forward error code */
-#define CHECK_E(f, e) { size_t const errcod = f; if (ERR_isError(errcod)) return ERROR(e); } /* check and send Error code */
+
+/**
+ * Return the specified error if the condition evaluates to true.
+ *
+ * In debug modes, prints additional information. In order to do that
+ * (particularly, printing the conditional that failed), this can't just wrap
+ * RETURN_ERROR().
+ */
+#define RETURN_ERROR_IF(cond, err, ...) \
+ if (cond) { \
+ RAWLOG(3, "%s:%d: ERROR!: check %s failed, returning %s", __FILE__, __LINE__, ZSTD_QUOTE(cond), ZSTD_QUOTE(ERROR(err))); \
+ RAWLOG(3, ": " __VA_ARGS__); \
+ RAWLOG(3, "\n"); \
+ return ERROR(err); \
+ }
+
+/**
+ * Unconditionally return the specified error.
+ *
+ * In debug modes, prints additional information.
+ */
+#define RETURN_ERROR(err, ...) \
+ do { \
+ RAWLOG(3, "%s:%d: ERROR!: unconditional check failed, returning %s", __FILE__, __LINE__, ZSTD_QUOTE(ERROR(err))); \
+ RAWLOG(3, ": " __VA_ARGS__); \
+ RAWLOG(3, "\n"); \
+ return ERROR(err); \
+ } while(0);
+
+/**
+ * If the provided expression evaluates to an error code, returns that error code.
+ *
+ * In debug modes, prints additional information.
+ */
+#define FORWARD_IF_ERROR(err, ...) \
+ do { \
+ size_t const err_code = (err); \
+ if (ERR_isError(err_code)) { \
+ RAWLOG(3, "%s:%d: ERROR!: forwarding error in %s: %s", __FILE__, __LINE__, ZSTD_QUOTE(err), ERR_getErrorName(err_code)); \
+ RAWLOG(3, ": " __VA_ARGS__); \
+ RAWLOG(3, "\n"); \
+ return err_code; \
+ } \
+ } while(0);
/*-*************************************
@@ -109,12 +120,10 @@ static const U32 repStartValue[ZSTD_REP_NUM] = { 1, 4, 8 };
#define BIT0 1
#define ZSTD_WINDOWLOG_ABSOLUTEMIN 10
-#define ZSTD_WINDOWLOG_DEFAULTMAX 27 /* Default maximum allowed window log */
static const size_t ZSTD_fcs_fieldSize[4] = { 0, 2, 4, 8 };
static const size_t ZSTD_did_fieldSize[4] = { 0, 1, 2, 4 };
-#define ZSTD_FRAMEIDSIZE 4
-static const size_t ZSTD_frameIdSize = ZSTD_FRAMEIDSIZE; /* magic number size */
+#define ZSTD_FRAMEIDSIZE 4 /* magic number size */
#define ZSTD_BLOCKHEADERSIZE 3 /* C standard doesn't allow `static const` variable to be init using another `static const` variable */
static const size_t ZSTD_blockHeaderSize = ZSTD_BLOCKHEADERSIZE;
@@ -227,10 +236,23 @@ typedef struct {
BYTE* llCode;
BYTE* mlCode;
BYTE* ofCode;
+ size_t maxNbSeq;
+ size_t maxNbLit;
U32 longLengthID; /* 0 == no longLength; 1 == Lit.longLength; 2 == Match.longLength; */
U32 longLengthPos;
} seqStore_t;
+/**
+ * Contains the compressed frame size and an upper-bound for the decompressed frame size.
+ * Note: before using `compressedSize`, check for errors using ZSTD_isError().
+ * similarly, before using `decompressedBound`, check for errors using:
+ * `decompressedBound != ZSTD_CONTENTSIZE_ERROR`
+ */
+typedef struct {
+ size_t compressedSize;
+ unsigned long long decompressedBound;
+} ZSTD_frameSizeInfo; /* decompress & legacy */
+
const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx); /* compress & dictBuilder */
void ZSTD_seqToCodes(const seqStore_t* seqStorePtr); /* compress, dictBuilder, decodeCorpus (shouldn't get its definition from here) */
@@ -275,7 +297,7 @@ typedef struct {
blockType_e blockType;
U32 lastBlock;
U32 origSize;
-} blockProperties_t;
+} blockProperties_t; /* declared here for decompress and fullbench */
/*! ZSTD_getcBlockSize() :
* Provides the size of compressed block from block header `src` */
@@ -283,6 +305,13 @@ typedef struct {
size_t ZSTD_getcBlockSize(const void* src, size_t srcSize,
blockProperties_t* bpPtr);
+/*! ZSTD_decodeSeqHeaders() :
+ * decode sequence header from src */
+/* Used by: decompress, fullbench (does not get its definition from here) */
+size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
+ const void* src, size_t srcSize);
+
+
#if defined (__cplusplus)
}
#endif
diff --git a/thirdparty/zstd/compress/fse_compress.c b/thirdparty/zstd/compress/fse_compress.c
index cb8f1fa323..68b47e1093 100644
--- a/thirdparty/zstd/compress/fse_compress.c
+++ b/thirdparty/zstd/compress/fse_compress.c
@@ -1,6 +1,6 @@
/* ******************************************************************
FSE : Finite State Entropy encoder
- Copyright (C) 2013-2015, Yann Collet.
+ Copyright (C) 2013-present, Yann Collet.
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
@@ -37,9 +37,11 @@
****************************************************************/
#include <stdlib.h> /* malloc, free, qsort */
#include <string.h> /* memcpy, memset */
-#include <stdio.h> /* printf (debug) */
-#include "bitstream.h"
#include "compiler.h"
+#include "mem.h" /* U32, U16, etc. */
+#include "debug.h" /* assert, DEBUGLOG */
+#include "hist.h" /* HIST_count_wksp */
+#include "bitstream.h"
#define FSE_STATIC_LINKING_ONLY
#include "fse.h"
#include "error_private.h"
@@ -49,7 +51,6 @@
* Error Management
****************************************************************/
#define FSE_isError ERR_isError
-#define FSE_STATIC_ASSERT(c) { enum { FSE_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */
/* **************************************************************
@@ -82,7 +83,9 @@
* wkspSize should be sized to handle worst case situation, which is `1<<max_tableLog * sizeof(FSE_FUNCTION_TYPE)`
* workSpace must also be properly aligned with FSE_FUNCTION_TYPE requirements
*/
-size_t FSE_buildCTable_wksp(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize)
+size_t FSE_buildCTable_wksp(FSE_CTable* ct,
+ const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog,
+ void* workSpace, size_t wkspSize)
{
U32 const tableSize = 1 << tableLog;
U32 const tableMask = tableSize - 1;
@@ -100,14 +103,19 @@ size_t FSE_buildCTable_wksp(FSE_CTable* ct, const short* normalizedCounter, unsi
if (((size_t)1 << tableLog) * sizeof(FSE_FUNCTION_TYPE) > wkspSize) return ERROR(tableLog_tooLarge);
tableU16[-2] = (U16) tableLog;
tableU16[-1] = (U16) maxSymbolValue;
+ assert(tableLog < 16); /* required for threshold strategy to work */
/* For explanations on how to distribute symbol values over the table :
- * http://fastcompression.blogspot.fr/2014/02/fse-distributing-symbol-values.html */
+ * http://fastcompression.blogspot.fr/2014/02/fse-distributing-symbol-values.html */
+
+ #ifdef __clang_analyzer__
+ memset(tableSymbol, 0, sizeof(*tableSymbol) * tableSize); /* useless initialization, just to keep scan-build happy */
+ #endif
/* symbol start positions */
{ U32 u;
cumul[0] = 0;
- for (u=1; u<=maxSymbolValue+1; u++) {
+ for (u=1; u <= maxSymbolValue+1; u++) {
if (normalizedCounter[u-1]==-1) { /* Low proba symbol */
cumul[u] = cumul[u-1] + 1;
tableSymbol[highThreshold--] = (FSE_FUNCTION_TYPE)(u-1);
@@ -121,14 +129,16 @@ size_t FSE_buildCTable_wksp(FSE_CTable* ct, const short* normalizedCounter, unsi
{ U32 position = 0;
U32 symbol;
for (symbol=0; symbol<=maxSymbolValue; symbol++) {
- int nbOccurences;
- for (nbOccurences=0; nbOccurences<normalizedCounter[symbol]; nbOccurences++) {
+ int nbOccurrences;
+ int const freq = normalizedCounter[symbol];
+ for (nbOccurrences=0; nbOccurrences<freq; nbOccurrences++) {
tableSymbol[position] = (FSE_FUNCTION_TYPE)symbol;
position = (position + step) & tableMask;
- while (position > highThreshold) position = (position + step) & tableMask; /* Low proba area */
+ while (position > highThreshold)
+ position = (position + step) & tableMask; /* Low proba area */
} }
- if (position!=0) return ERROR(GENERIC); /* Must have gone through all positions */
+ assert(position==0); /* Must have initialized all positions */
}
/* Build table */
@@ -143,7 +153,10 @@ size_t FSE_buildCTable_wksp(FSE_CTable* ct, const short* normalizedCounter, unsi
for (s=0; s<=maxSymbolValue; s++) {
switch (normalizedCounter[s])
{
- case 0: break;
+ case 0:
+ /* filling nonetheless, for compatibility with FSE_getMaxNbBits() */
+ symbolTT[s].deltaNbBits = ((tableLog+1) << 16) - (1<<tableLog);
+ break;
case -1:
case 1:
@@ -160,6 +173,18 @@ size_t FSE_buildCTable_wksp(FSE_CTable* ct, const short* normalizedCounter, unsi
total += normalizedCounter[s];
} } } }
+#if 0 /* debug : symbol costs */
+ DEBUGLOG(5, "\n --- table statistics : ");
+ { U32 symbol;
+ for (symbol=0; symbol<=maxSymbolValue; symbol++) {
+ DEBUGLOG(5, "%3u: w=%3i, maxBits=%u, fracBits=%.2f",
+ symbol, normalizedCounter[symbol],
+ FSE_getMaxNbBits(symbolTT, symbol),
+ (double)FSE_bitCost(symbolTT, tableLog, symbol, 8) / 256);
+ }
+ }
+#endif
+
return 0;
}
@@ -174,8 +199,9 @@ size_t FSE_buildCTable(FSE_CTable* ct, const short* normalizedCounter, unsigned
#ifndef FSE_COMMONDEFS_ONLY
+
/*-**************************************************************
-* FSE NCount encoding-decoding
+* FSE NCount encoding
****************************************************************/
size_t FSE_NCountWriteBound(unsigned maxSymbolValue, unsigned tableLog)
{
@@ -183,9 +209,10 @@ size_t FSE_NCountWriteBound(unsigned maxSymbolValue, unsigned tableLog)
return maxSymbolValue ? maxHeaderSize : FSE_NCOUNTBOUND; /* maxSymbolValue==0 ? use default */
}
-static size_t FSE_writeNCount_generic (void* header, size_t headerBufferSize,
- const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog,
- unsigned writeIsSafe)
+static size_t
+FSE_writeNCount_generic (void* header, size_t headerBufferSize,
+ const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog,
+ unsigned writeIsSafe)
{
BYTE* const ostart = (BYTE*) header;
BYTE* out = ostart;
@@ -194,13 +221,12 @@ static size_t FSE_writeNCount_generic (void* header, size_t headerBufferSize,
const int tableSize = 1 << tableLog;
int remaining;
int threshold;
- U32 bitStream;
- int bitCount;
- unsigned charnum = 0;
- int previous0 = 0;
+ U32 bitStream = 0;
+ int bitCount = 0;
+ unsigned symbol = 0;
+ unsigned const alphabetSize = maxSymbolValue + 1;
+ int previousIs0 = 0;
- bitStream = 0;
- bitCount = 0;
/* Table Size */
bitStream += (tableLog-FSE_MIN_TABLELOG) << bitCount;
bitCount += 4;
@@ -210,48 +236,53 @@ static size_t FSE_writeNCount_generic (void* header, size_t headerBufferSize,
threshold = tableSize;
nbBits = tableLog+1;
- while (remaining>1) { /* stops at 1 */
- if (previous0) {
- unsigned start = charnum;
- while (!normalizedCounter[charnum]) charnum++;
- while (charnum >= start+24) {
+ while ((symbol < alphabetSize) && (remaining>1)) { /* stops at 1 */
+ if (previousIs0) {
+ unsigned start = symbol;
+ while ((symbol < alphabetSize) && !normalizedCounter[symbol]) symbol++;
+ if (symbol == alphabetSize) break; /* incorrect distribution */
+ while (symbol >= start+24) {
start+=24;
bitStream += 0xFFFFU << bitCount;
- if ((!writeIsSafe) && (out > oend-2)) return ERROR(dstSize_tooSmall); /* Buffer overflow */
+ if ((!writeIsSafe) && (out > oend-2))
+ return ERROR(dstSize_tooSmall); /* Buffer overflow */
out[0] = (BYTE) bitStream;
out[1] = (BYTE)(bitStream>>8);
out+=2;
bitStream>>=16;
}
- while (charnum >= start+3) {
+ while (symbol >= start+3) {
start+=3;
bitStream += 3 << bitCount;
bitCount += 2;
}
- bitStream += (charnum-start) << bitCount;
+ bitStream += (symbol-start) << bitCount;
bitCount += 2;
if (bitCount>16) {
- if ((!writeIsSafe) && (out > oend - 2)) return ERROR(dstSize_tooSmall); /* Buffer overflow */
+ if ((!writeIsSafe) && (out > oend - 2))
+ return ERROR(dstSize_tooSmall); /* Buffer overflow */
out[0] = (BYTE)bitStream;
out[1] = (BYTE)(bitStream>>8);
out += 2;
bitStream >>= 16;
bitCount -= 16;
} }
- { int count = normalizedCounter[charnum++];
- int const max = (2*threshold-1)-remaining;
+ { int count = normalizedCounter[symbol++];
+ int const max = (2*threshold-1) - remaining;
remaining -= count < 0 ? -count : count;
count++; /* +1 for extra accuracy */
- if (count>=threshold) count += max; /* [0..max[ [max..threshold[ (...) [threshold+max 2*threshold[ */
+ if (count>=threshold)
+ count += max; /* [0..max[ [max..threshold[ (...) [threshold+max 2*threshold[ */
bitStream += count << bitCount;
bitCount += nbBits;
bitCount -= (count<max);
- previous0 = (count==1);
+ previousIs0 = (count==1);
if (remaining<1) return ERROR(GENERIC);
while (remaining<threshold) { nbBits--; threshold>>=1; }
}
if (bitCount>16) {
- if ((!writeIsSafe) && (out > oend - 2)) return ERROR(dstSize_tooSmall); /* Buffer overflow */
+ if ((!writeIsSafe) && (out > oend - 2))
+ return ERROR(dstSize_tooSmall); /* Buffer overflow */
out[0] = (BYTE)bitStream;
out[1] = (BYTE)(bitStream>>8);
out += 2;
@@ -259,19 +290,23 @@ static size_t FSE_writeNCount_generic (void* header, size_t headerBufferSize,
bitCount -= 16;
} }
+ if (remaining != 1)
+ return ERROR(GENERIC); /* incorrect normalized distribution */
+ assert(symbol <= alphabetSize);
+
/* flush remaining bitStream */
- if ((!writeIsSafe) && (out > oend - 2)) return ERROR(dstSize_tooSmall); /* Buffer overflow */
+ if ((!writeIsSafe) && (out > oend - 2))
+ return ERROR(dstSize_tooSmall); /* Buffer overflow */
out[0] = (BYTE)bitStream;
out[1] = (BYTE)(bitStream>>8);
out+= (bitCount+7) /8;
- if (charnum > maxSymbolValue + 1) return ERROR(GENERIC);
-
return (out-ostart);
}
-size_t FSE_writeNCount (void* buffer, size_t bufferSize, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)
+size_t FSE_writeNCount (void* buffer, size_t bufferSize,
+ const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)
{
if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge); /* Unsupported */
if (tableLog < FSE_MIN_TABLELOG) return ERROR(GENERIC); /* Unsupported */
@@ -279,179 +314,13 @@ size_t FSE_writeNCount (void* buffer, size_t bufferSize, const short* normalized
if (bufferSize < FSE_NCountWriteBound(maxSymbolValue, tableLog))
return FSE_writeNCount_generic(buffer, bufferSize, normalizedCounter, maxSymbolValue, tableLog, 0);
- return FSE_writeNCount_generic(buffer, bufferSize, normalizedCounter, maxSymbolValue, tableLog, 1);
-}
-
-
-
-/*-**************************************************************
-* Counting histogram
-****************************************************************/
-/*! FSE_count_simple
- This function counts byte values within `src`, and store the histogram into table `count`.
- It doesn't use any additional memory.
- But this function is unsafe : it doesn't check that all values within `src` can fit into `count`.
- For this reason, prefer using a table `count` with 256 elements.
- @return : count of most numerous element.
-*/
-size_t FSE_count_simple(unsigned* count, unsigned* maxSymbolValuePtr,
- const void* src, size_t srcSize)
-{
- const BYTE* ip = (const BYTE*)src;
- const BYTE* const end = ip + srcSize;
- unsigned maxSymbolValue = *maxSymbolValuePtr;
- unsigned max=0;
-
- memset(count, 0, (maxSymbolValue+1)*sizeof(*count));
- if (srcSize==0) { *maxSymbolValuePtr = 0; return 0; }
-
- while (ip<end) {
- assert(*ip <= maxSymbolValue);
- count[*ip++]++;
- }
-
- while (!count[maxSymbolValue]) maxSymbolValue--;
- *maxSymbolValuePtr = maxSymbolValue;
-
- { U32 s; for (s=0; s<=maxSymbolValue; s++) if (count[s] > max) max = count[s]; }
-
- return (size_t)max;
-}
-
-
-/* FSE_count_parallel_wksp() :
- * Same as FSE_count_parallel(), but using an externally provided scratch buffer.
- * `workSpace` size must be a minimum of `1024 * sizeof(unsigned)`.
- * @return : largest histogram frequency, or an error code (notably when histogram would be larger than *maxSymbolValuePtr). */
-static size_t FSE_count_parallel_wksp(
- unsigned* count, unsigned* maxSymbolValuePtr,
- const void* source, size_t sourceSize,
- unsigned checkMax, unsigned* const workSpace)
-{
- const BYTE* ip = (const BYTE*)source;
- const BYTE* const iend = ip+sourceSize;
- unsigned maxSymbolValue = *maxSymbolValuePtr;
- unsigned max=0;
- U32* const Counting1 = workSpace;
- U32* const Counting2 = Counting1 + 256;
- U32* const Counting3 = Counting2 + 256;
- U32* const Counting4 = Counting3 + 256;
-
- memset(workSpace, 0, 4*256*sizeof(unsigned));
-
- /* safety checks */
- if (!sourceSize) {
- memset(count, 0, maxSymbolValue + 1);
- *maxSymbolValuePtr = 0;
- return 0;
- }
- if (!maxSymbolValue) maxSymbolValue = 255; /* 0 == default */
-
- /* by stripes of 16 bytes */
- { U32 cached = MEM_read32(ip); ip += 4;
- while (ip < iend-15) {
- U32 c = cached; cached = MEM_read32(ip); ip += 4;
- Counting1[(BYTE) c ]++;
- Counting2[(BYTE)(c>>8) ]++;
- Counting3[(BYTE)(c>>16)]++;
- Counting4[ c>>24 ]++;
- c = cached; cached = MEM_read32(ip); ip += 4;
- Counting1[(BYTE) c ]++;
- Counting2[(BYTE)(c>>8) ]++;
- Counting3[(BYTE)(c>>16)]++;
- Counting4[ c>>24 ]++;
- c = cached; cached = MEM_read32(ip); ip += 4;
- Counting1[(BYTE) c ]++;
- Counting2[(BYTE)(c>>8) ]++;
- Counting3[(BYTE)(c>>16)]++;
- Counting4[ c>>24 ]++;
- c = cached; cached = MEM_read32(ip); ip += 4;
- Counting1[(BYTE) c ]++;
- Counting2[(BYTE)(c>>8) ]++;
- Counting3[(BYTE)(c>>16)]++;
- Counting4[ c>>24 ]++;
- }
- ip-=4;
- }
-
- /* finish last symbols */
- while (ip<iend) Counting1[*ip++]++;
-
- if (checkMax) { /* verify stats will fit into destination table */
- U32 s; for (s=255; s>maxSymbolValue; s--) {
- Counting1[s] += Counting2[s] + Counting3[s] + Counting4[s];
- if (Counting1[s]) return ERROR(maxSymbolValue_tooSmall);
- } }
-
- { U32 s;
- if (maxSymbolValue > 255) maxSymbolValue = 255;
- for (s=0; s<=maxSymbolValue; s++) {
- count[s] = Counting1[s] + Counting2[s] + Counting3[s] + Counting4[s];
- if (count[s] > max) max = count[s];
- } }
-
- while (!count[maxSymbolValue]) maxSymbolValue--;
- *maxSymbolValuePtr = maxSymbolValue;
- return (size_t)max;
-}
-
-/* FSE_countFast_wksp() :
- * Same as FSE_countFast(), but using an externally provided scratch buffer.
- * `workSpace` size must be table of >= `1024` unsigned */
-size_t FSE_countFast_wksp(unsigned* count, unsigned* maxSymbolValuePtr,
- const void* source, size_t sourceSize,
- unsigned* workSpace)
-{
- if (sourceSize < 1500) /* heuristic threshold */
- return FSE_count_simple(count, maxSymbolValuePtr, source, sourceSize);
- return FSE_count_parallel_wksp(count, maxSymbolValuePtr, source, sourceSize, 0, workSpace);
-}
-
-/* fast variant (unsafe : won't check if src contains values beyond count[] limit) */
-size_t FSE_countFast(unsigned* count, unsigned* maxSymbolValuePtr,
- const void* source, size_t sourceSize)
-{
- unsigned tmpCounters[1024];
- return FSE_countFast_wksp(count, maxSymbolValuePtr, source, sourceSize, tmpCounters);
-}
-
-/* FSE_count_wksp() :
- * Same as FSE_count(), but using an externally provided scratch buffer.
- * `workSpace` size must be table of >= `1024` unsigned */
-size_t FSE_count_wksp(unsigned* count, unsigned* maxSymbolValuePtr,
- const void* source, size_t sourceSize, unsigned* workSpace)
-{
- if (*maxSymbolValuePtr < 255)
- return FSE_count_parallel_wksp(count, maxSymbolValuePtr, source, sourceSize, 1, workSpace);
- *maxSymbolValuePtr = 255;
- return FSE_countFast_wksp(count, maxSymbolValuePtr, source, sourceSize, workSpace);
-}
-
-size_t FSE_count(unsigned* count, unsigned* maxSymbolValuePtr,
- const void* src, size_t srcSize)
-{
- unsigned tmpCounters[1024];
- return FSE_count_wksp(count, maxSymbolValuePtr, src, srcSize, tmpCounters);
+ return FSE_writeNCount_generic(buffer, bufferSize, normalizedCounter, maxSymbolValue, tableLog, 1 /* write in buffer is safe */);
}
-
/*-**************************************************************
* FSE Compression Code
****************************************************************/
-/*! FSE_sizeof_CTable() :
- FSE_CTable is a variable size structure which contains :
- `U16 tableLog;`
- `U16 maxSymbolValue;`
- `U16 nextStateNumber[1 << tableLog];` // This size is variable
- `FSE_symbolCompressionTransform symbolTT[maxSymbolValue+1];` // This size is variable
-Allocation is manual (C standard does not support variable-size structures).
-*/
-size_t FSE_sizeof_CTable (unsigned maxSymbolValue, unsigned tableLog)
-{
- if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge);
- return FSE_CTABLE_SIZE_U32 (tableLog, maxSymbolValue) * sizeof(U32);
-}
FSE_CTable* FSE_createCTable (unsigned maxSymbolValue, unsigned tableLog)
{
@@ -466,7 +335,7 @@ void FSE_freeCTable (FSE_CTable* ct) { free(ct); }
/* provides the minimum logSize to safely represent a distribution */
static unsigned FSE_minTableLog(size_t srcSize, unsigned maxSymbolValue)
{
- U32 minBitsSrc = BIT_highbit32((U32)(srcSize - 1)) + 1;
+ U32 minBitsSrc = BIT_highbit32((U32)(srcSize)) + 1;
U32 minBitsSymbols = BIT_highbit32(maxSymbolValue) + 2;
U32 minBits = minBitsSrc < minBitsSymbols ? minBitsSrc : minBitsSymbols;
assert(srcSize > 1); /* Not supported, RLE should be used instead */
@@ -529,6 +398,9 @@ static size_t FSE_normalizeM2(short* norm, U32 tableLog, const unsigned* count,
}
ToDistribute = (1 << tableLog) - distributed;
+ if (ToDistribute == 0)
+ return 0;
+
if ((total / ToDistribute) > lowOne) {
/* risk of rounding to zero */
lowOne = (U32)((total * 3) / (ToDistribute * 2));
@@ -629,11 +501,11 @@ size_t FSE_normalizeCount (short* normalizedCounter, unsigned tableLog,
U32 s;
U32 nTotal = 0;
for (s=0; s<=maxSymbolValue; s++)
- printf("%3i: %4i \n", s, normalizedCounter[s]);
+ RAWLOG(2, "%3i: %4i \n", s, normalizedCounter[s]);
for (s=0; s<=maxSymbolValue; s++)
nTotal += abs(normalizedCounter[s]);
if (nTotal != (1U<<tableLog))
- printf("Warning !!! Total == %u != %u !!!", nTotal, 1U<<tableLog);
+ RAWLOG(2, "Warning !!! Total == %u != %u !!!", nTotal, 1U<<tableLog);
getchar();
}
#endif
@@ -786,7 +658,7 @@ size_t FSE_compress_wksp (void* dst, size_t dstSize, const void* src, size_t src
BYTE* op = ostart;
BYTE* const oend = ostart + dstSize;
- U32 count[FSE_MAX_SYMBOL_VALUE+1];
+ unsigned count[FSE_MAX_SYMBOL_VALUE+1];
S16 norm[FSE_MAX_SYMBOL_VALUE+1];
FSE_CTable* CTable = (FSE_CTable*)workSpace;
size_t const CTableSize = FSE_CTABLE_SIZE_U32(tableLog, maxSymbolValue);
@@ -800,7 +672,7 @@ size_t FSE_compress_wksp (void* dst, size_t dstSize, const void* src, size_t src
if (!tableLog) tableLog = FSE_DEFAULT_TABLELOG;
/* Scan input and build symbol stats */
- { CHECK_V_F(maxCount, FSE_count_wksp(count, &maxSymbolValue, src, srcSize, (unsigned*)scratchBuffer) );
+ { CHECK_V_F(maxCount, HIST_count_wksp(count, &maxSymbolValue, src, srcSize, scratchBuffer, scratchBufferSize) );
if (maxCount == srcSize) return 1; /* only a single symbol in src : rle */
if (maxCount == 1) return 0; /* each symbol present maximum once => not compressible */
if (maxCount < (srcSize >> 7)) return 0; /* Heuristic : not compressible enough */
@@ -835,7 +707,7 @@ typedef struct {
size_t FSE_compress2 (void* dst, size_t dstCapacity, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog)
{
fseWkspMax_t scratchBuffer;
- FSE_STATIC_ASSERT(sizeof(scratchBuffer) >= FSE_WKSP_SIZE_U32(FSE_MAX_TABLELOG, FSE_MAX_SYMBOL_VALUE)); /* compilation failures here means scratchBuffer is not large enough */
+ DEBUG_STATIC_ASSERT(sizeof(scratchBuffer) >= FSE_WKSP_SIZE_U32(FSE_MAX_TABLELOG, FSE_MAX_SYMBOL_VALUE)); /* compilation failures here means scratchBuffer is not large enough */
if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge);
return FSE_compress_wksp(dst, dstCapacity, src, srcSize, maxSymbolValue, tableLog, &scratchBuffer, sizeof(scratchBuffer));
}
diff --git a/thirdparty/zstd/compress/hist.c b/thirdparty/zstd/compress/hist.c
new file mode 100644
index 0000000000..45b7babc1e
--- /dev/null
+++ b/thirdparty/zstd/compress/hist.c
@@ -0,0 +1,203 @@
+/* ******************************************************************
+ hist : Histogram functions
+ part of Finite State Entropy project
+ Copyright (C) 2013-present, Yann Collet.
+
+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
+
+ 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.
+
+ 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.
+
+ You can contact the author at :
+ - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy
+ - Public forum : https://groups.google.com/forum/#!forum/lz4c
+****************************************************************** */
+
+/* --- dependencies --- */
+#include "mem.h" /* U32, BYTE, etc. */
+#include "debug.h" /* assert, DEBUGLOG */
+#include "error_private.h" /* ERROR */
+#include "hist.h"
+
+
+/* --- Error management --- */
+unsigned HIST_isError(size_t code) { return ERR_isError(code); }
+
+/*-**************************************************************
+ * Histogram functions
+ ****************************************************************/
+unsigned HIST_count_simple(unsigned* count, unsigned* maxSymbolValuePtr,
+ const void* src, size_t srcSize)
+{
+ const BYTE* ip = (const BYTE*)src;
+ const BYTE* const end = ip + srcSize;
+ unsigned maxSymbolValue = *maxSymbolValuePtr;
+ unsigned largestCount=0;
+
+ memset(count, 0, (maxSymbolValue+1) * sizeof(*count));
+ if (srcSize==0) { *maxSymbolValuePtr = 0; return 0; }
+
+ while (ip<end) {
+ assert(*ip <= maxSymbolValue);
+ count[*ip++]++;
+ }
+
+ while (!count[maxSymbolValue]) maxSymbolValue--;
+ *maxSymbolValuePtr = maxSymbolValue;
+
+ { U32 s;
+ for (s=0; s<=maxSymbolValue; s++)
+ if (count[s] > largestCount) largestCount = count[s];
+ }
+
+ return largestCount;
+}
+
+typedef enum { trustInput, checkMaxSymbolValue } HIST_checkInput_e;
+
+/* HIST_count_parallel_wksp() :
+ * store histogram into 4 intermediate tables, recombined at the end.
+ * this design makes better use of OoO cpus,
+ * and is noticeably faster when some values are heavily repeated.
+ * But it needs some additional workspace for intermediate tables.
+ * `workSpace` size must be a table of size >= HIST_WKSP_SIZE_U32.
+ * @return : largest histogram frequency,
+ * or an error code (notably when histogram would be larger than *maxSymbolValuePtr). */
+static size_t HIST_count_parallel_wksp(
+ unsigned* count, unsigned* maxSymbolValuePtr,
+ const void* source, size_t sourceSize,
+ HIST_checkInput_e check,
+ U32* const workSpace)
+{
+ const BYTE* ip = (const BYTE*)source;
+ const BYTE* const iend = ip+sourceSize;
+ unsigned maxSymbolValue = *maxSymbolValuePtr;
+ unsigned max=0;
+ U32* const Counting1 = workSpace;
+ U32* const Counting2 = Counting1 + 256;
+ U32* const Counting3 = Counting2 + 256;
+ U32* const Counting4 = Counting3 + 256;
+
+ memset(workSpace, 0, 4*256*sizeof(unsigned));
+
+ /* safety checks */
+ if (!sourceSize) {
+ memset(count, 0, maxSymbolValue + 1);
+ *maxSymbolValuePtr = 0;
+ return 0;
+ }
+ if (!maxSymbolValue) maxSymbolValue = 255; /* 0 == default */
+
+ /* by stripes of 16 bytes */
+ { U32 cached = MEM_read32(ip); ip += 4;
+ while (ip < iend-15) {
+ U32 c = cached; cached = MEM_read32(ip); ip += 4;
+ Counting1[(BYTE) c ]++;
+ Counting2[(BYTE)(c>>8) ]++;
+ Counting3[(BYTE)(c>>16)]++;
+ Counting4[ c>>24 ]++;
+ c = cached; cached = MEM_read32(ip); ip += 4;
+ Counting1[(BYTE) c ]++;
+ Counting2[(BYTE)(c>>8) ]++;
+ Counting3[(BYTE)(c>>16)]++;
+ Counting4[ c>>24 ]++;
+ c = cached; cached = MEM_read32(ip); ip += 4;
+ Counting1[(BYTE) c ]++;
+ Counting2[(BYTE)(c>>8) ]++;
+ Counting3[(BYTE)(c>>16)]++;
+ Counting4[ c>>24 ]++;
+ c = cached; cached = MEM_read32(ip); ip += 4;
+ Counting1[(BYTE) c ]++;
+ Counting2[(BYTE)(c>>8) ]++;
+ Counting3[(BYTE)(c>>16)]++;
+ Counting4[ c>>24 ]++;
+ }
+ ip-=4;
+ }
+
+ /* finish last symbols */
+ while (ip<iend) Counting1[*ip++]++;
+
+ if (check) { /* verify stats will fit into destination table */
+ U32 s; for (s=255; s>maxSymbolValue; s--) {
+ Counting1[s] += Counting2[s] + Counting3[s] + Counting4[s];
+ if (Counting1[s]) return ERROR(maxSymbolValue_tooSmall);
+ } }
+
+ { U32 s;
+ if (maxSymbolValue > 255) maxSymbolValue = 255;
+ for (s=0; s<=maxSymbolValue; s++) {
+ count[s] = Counting1[s] + Counting2[s] + Counting3[s] + Counting4[s];
+ if (count[s] > max) max = count[s];
+ } }
+
+ while (!count[maxSymbolValue]) maxSymbolValue--;
+ *maxSymbolValuePtr = maxSymbolValue;
+ return (size_t)max;
+}
+
+/* HIST_countFast_wksp() :
+ * Same as HIST_countFast(), but using an externally provided scratch buffer.
+ * `workSpace` is a writable buffer which must be 4-bytes aligned,
+ * `workSpaceSize` must be >= HIST_WKSP_SIZE
+ */
+size_t HIST_countFast_wksp(unsigned* count, unsigned* maxSymbolValuePtr,
+ const void* source, size_t sourceSize,
+ void* workSpace, size_t workSpaceSize)
+{
+ if (sourceSize < 1500) /* heuristic threshold */
+ return HIST_count_simple(count, maxSymbolValuePtr, source, sourceSize);
+ if ((size_t)workSpace & 3) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */
+ if (workSpaceSize < HIST_WKSP_SIZE) return ERROR(workSpace_tooSmall);
+ return HIST_count_parallel_wksp(count, maxSymbolValuePtr, source, sourceSize, trustInput, (U32*)workSpace);
+}
+
+/* fast variant (unsafe : won't check if src contains values beyond count[] limit) */
+size_t HIST_countFast(unsigned* count, unsigned* maxSymbolValuePtr,
+ const void* source, size_t sourceSize)
+{
+ unsigned tmpCounters[HIST_WKSP_SIZE_U32];
+ return HIST_countFast_wksp(count, maxSymbolValuePtr, source, sourceSize, tmpCounters, sizeof(tmpCounters));
+}
+
+/* HIST_count_wksp() :
+ * Same as HIST_count(), but using an externally provided scratch buffer.
+ * `workSpace` size must be table of >= HIST_WKSP_SIZE_U32 unsigned */
+size_t HIST_count_wksp(unsigned* count, unsigned* maxSymbolValuePtr,
+ const void* source, size_t sourceSize,
+ void* workSpace, size_t workSpaceSize)
+{
+ if ((size_t)workSpace & 3) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */
+ if (workSpaceSize < HIST_WKSP_SIZE) return ERROR(workSpace_tooSmall);
+ if (*maxSymbolValuePtr < 255)
+ return HIST_count_parallel_wksp(count, maxSymbolValuePtr, source, sourceSize, checkMaxSymbolValue, (U32*)workSpace);
+ *maxSymbolValuePtr = 255;
+ return HIST_countFast_wksp(count, maxSymbolValuePtr, source, sourceSize, workSpace, workSpaceSize);
+}
+
+size_t HIST_count(unsigned* count, unsigned* maxSymbolValuePtr,
+ const void* src, size_t srcSize)
+{
+ unsigned tmpCounters[HIST_WKSP_SIZE_U32];
+ return HIST_count_wksp(count, maxSymbolValuePtr, src, srcSize, tmpCounters, sizeof(tmpCounters));
+}
diff --git a/thirdparty/zstd/compress/hist.h b/thirdparty/zstd/compress/hist.h
new file mode 100644
index 0000000000..8b389358dc
--- /dev/null
+++ b/thirdparty/zstd/compress/hist.h
@@ -0,0 +1,95 @@
+/* ******************************************************************
+ hist : Histogram functions
+ part of Finite State Entropy project
+ Copyright (C) 2013-present, Yann Collet.
+
+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
+
+ 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.
+
+ 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.
+
+ You can contact the author at :
+ - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy
+ - Public forum : https://groups.google.com/forum/#!forum/lz4c
+****************************************************************** */
+
+/* --- dependencies --- */
+#include <stddef.h> /* size_t */
+
+
+/* --- simple histogram functions --- */
+
+/*! HIST_count():
+ * Provides the precise count of each byte within a table 'count'.
+ * 'count' is a table of unsigned int, of minimum size (*maxSymbolValuePtr+1).
+ * Updates *maxSymbolValuePtr with actual largest symbol value detected.
+ * @return : count of the most frequent symbol (which isn't identified).
+ * or an error code, which can be tested using HIST_isError().
+ * note : if return == srcSize, there is only one symbol.
+ */
+size_t HIST_count(unsigned* count, unsigned* maxSymbolValuePtr,
+ const void* src, size_t srcSize);
+
+unsigned HIST_isError(size_t code); /**< tells if a return value is an error code */
+
+
+/* --- advanced histogram functions --- */
+
+#define HIST_WKSP_SIZE_U32 1024
+#define HIST_WKSP_SIZE (HIST_WKSP_SIZE_U32 * sizeof(unsigned))
+/** HIST_count_wksp() :
+ * Same as HIST_count(), but using an externally provided scratch buffer.
+ * Benefit is this function will use very little stack space.
+ * `workSpace` is a writable buffer which must be 4-bytes aligned,
+ * `workSpaceSize` must be >= HIST_WKSP_SIZE
+ */
+size_t HIST_count_wksp(unsigned* count, unsigned* maxSymbolValuePtr,
+ const void* src, size_t srcSize,
+ void* workSpace, size_t workSpaceSize);
+
+/** HIST_countFast() :
+ * same as HIST_count(), but blindly trusts that all byte values within src are <= *maxSymbolValuePtr.
+ * This function is unsafe, and will segfault if any value within `src` is `> *maxSymbolValuePtr`
+ */
+size_t HIST_countFast(unsigned* count, unsigned* maxSymbolValuePtr,
+ const void* src, size_t srcSize);
+
+/** HIST_countFast_wksp() :
+ * Same as HIST_countFast(), but using an externally provided scratch buffer.
+ * `workSpace` is a writable buffer which must be 4-bytes aligned,
+ * `workSpaceSize` must be >= HIST_WKSP_SIZE
+ */
+size_t HIST_countFast_wksp(unsigned* count, unsigned* maxSymbolValuePtr,
+ const void* src, size_t srcSize,
+ void* workSpace, size_t workSpaceSize);
+
+/*! HIST_count_simple() :
+ * Same as HIST_countFast(), this function is unsafe,
+ * and will segfault if any value within `src` is `> *maxSymbolValuePtr`.
+ * It is also a bit slower for large inputs.
+ * However, it does not need any additional memory (not even on stack).
+ * @return : count of the most frequent symbol.
+ * Note this function doesn't produce any error (i.e. it must succeed).
+ */
+unsigned HIST_count_simple(unsigned* count, unsigned* maxSymbolValuePtr,
+ const void* src, size_t srcSize);
diff --git a/thirdparty/zstd/compress/huf_compress.c b/thirdparty/zstd/compress/huf_compress.c
index 83230b415f..f074f1e0a9 100644
--- a/thirdparty/zstd/compress/huf_compress.c
+++ b/thirdparty/zstd/compress/huf_compress.c
@@ -45,8 +45,9 @@
****************************************************************/
#include <string.h> /* memcpy, memset */
#include <stdio.h> /* printf (debug) */
-#include "bitstream.h"
#include "compiler.h"
+#include "bitstream.h"
+#include "hist.h"
#define FSE_STATIC_LINKING_ONLY /* FSE_optimalTableLog_internal */
#include "fse.h" /* header compression */
#define HUF_STATIC_LINKING_ONLY
@@ -58,7 +59,7 @@
* Error Management
****************************************************************/
#define HUF_isError ERR_isError
-#define HUF_STATIC_ASSERT(c) { enum { HUF_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */
+#define HUF_STATIC_ASSERT(c) DEBUG_STATIC_ASSERT(c) /* use only *after* variable declarations */
#define CHECK_V_F(e, f) size_t const e = f; if (ERR_isError(e)) return e
#define CHECK_F(f) { CHECK_V_F(_var_err__, f); }
@@ -81,28 +82,28 @@ unsigned HUF_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxS
* Note : all elements within weightTable are supposed to be <= HUF_TABLELOG_MAX.
*/
#define MAX_FSE_TABLELOG_FOR_HUFF_HEADER 6
-size_t HUF_compressWeights (void* dst, size_t dstSize, const void* weightTable, size_t wtSize)
+static size_t HUF_compressWeights (void* dst, size_t dstSize, const void* weightTable, size_t wtSize)
{
BYTE* const ostart = (BYTE*) dst;
BYTE* op = ostart;
BYTE* const oend = ostart + dstSize;
- U32 maxSymbolValue = HUF_TABLELOG_MAX;
+ unsigned maxSymbolValue = HUF_TABLELOG_MAX;
U32 tableLog = MAX_FSE_TABLELOG_FOR_HUFF_HEADER;
FSE_CTable CTable[FSE_CTABLE_SIZE_U32(MAX_FSE_TABLELOG_FOR_HUFF_HEADER, HUF_TABLELOG_MAX)];
BYTE scratchBuffer[1<<MAX_FSE_TABLELOG_FOR_HUFF_HEADER];
- U32 count[HUF_TABLELOG_MAX+1];
+ unsigned count[HUF_TABLELOG_MAX+1];
S16 norm[HUF_TABLELOG_MAX+1];
/* init conditions */
if (wtSize <= 1) return 0; /* Not compressible */
/* Scan input and build symbol stats */
- { CHECK_V_F(maxCount, FSE_count_simple(count, &maxSymbolValue, weightTable, wtSize) );
+ { unsigned const maxCount = HIST_count_simple(count, &maxSymbolValue, weightTable, wtSize); /* never fails */
if (maxCount == wtSize) return 1; /* only a single symbol in src : rle */
- if (maxCount == 1) return 0; /* each symbol present maximum once => not compressible */
+ if (maxCount == 1) return 0; /* each symbol present maximum once => not compressible */
}
tableLog = FSE_optimalTableLog(tableLog, wtSize, maxSymbolValue);
@@ -133,7 +134,7 @@ struct HUF_CElt_s {
`CTable` : Huffman tree to save, using huf representation.
@return : size of saved CTable */
size_t HUF_writeCTable (void* dst, size_t maxDstSize,
- const HUF_CElt* CTable, U32 maxSymbolValue, U32 huffLog)
+ const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog)
{
BYTE bitsToWeight[HUF_TABLELOG_MAX + 1]; /* precomputed conversion table */
BYTE huffWeight[HUF_SYMBOLVALUE_MAX];
@@ -168,7 +169,7 @@ size_t HUF_writeCTable (void* dst, size_t maxDstSize,
}
-size_t HUF_readCTable (HUF_CElt* CTable, U32* maxSymbolValuePtr, const void* src, size_t srcSize)
+size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize)
{
BYTE huffWeight[HUF_SYMBOLVALUE_MAX + 1]; /* init not required, even though some static analyzer may complain */
U32 rankVal[HUF_TABLELOG_ABSOLUTEMAX + 1]; /* large enough for values from 0 to 16 */
@@ -216,6 +217,13 @@ size_t HUF_readCTable (HUF_CElt* CTable, U32* maxSymbolValuePtr, const void* src
return readSize;
}
+U32 HUF_getNbBits(const void* symbolTable, U32 symbolValue)
+{
+ const HUF_CElt* table = (const HUF_CElt*)symbolTable;
+ assert(symbolValue <= HUF_SYMBOLVALUE_MAX);
+ return table[symbolValue].nbBits;
+}
+
typedef struct nodeElt_s {
U32 count;
@@ -307,7 +315,7 @@ typedef struct {
U32 current;
} rankPos;
-static void HUF_sort(nodeElt* huffNode, const U32* count, U32 maxSymbolValue)
+static void HUF_sort(nodeElt* huffNode, const unsigned* count, U32 maxSymbolValue)
{
rankPos rank[32];
U32 n;
@@ -339,7 +347,7 @@ static void HUF_sort(nodeElt* huffNode, const U32* count, U32 maxSymbolValue)
*/
#define STARTNODE (HUF_SYMBOLVALUE_MAX+1)
typedef nodeElt huffNodeTable[HUF_CTABLE_WORKSPACE_SIZE_U32];
-size_t HUF_buildCTable_wksp (HUF_CElt* tree, const U32* count, U32 maxSymbolValue, U32 maxNbBits, void* workSpace, size_t wkspSize)
+size_t HUF_buildCTable_wksp (HUF_CElt* tree, const unsigned* count, U32 maxSymbolValue, U32 maxNbBits, void* workSpace, size_t wkspSize)
{
nodeElt* const huffNode0 = (nodeElt*)workSpace;
nodeElt* const huffNode = huffNode0+1;
@@ -413,7 +421,7 @@ size_t HUF_buildCTable_wksp (HUF_CElt* tree, const U32* count, U32 maxSymbolValu
* @return : maxNbBits
* Note : count is used before tree is written, so they can safely overlap
*/
-size_t HUF_buildCTable (HUF_CElt* tree, const U32* count, U32 maxSymbolValue, U32 maxNbBits)
+size_t HUF_buildCTable (HUF_CElt* tree, const unsigned* count, unsigned maxSymbolValue, unsigned maxNbBits)
{
huffNodeTable nodeTable;
return HUF_buildCTable_wksp(tree, count, maxSymbolValue, maxNbBits, nodeTable, sizeof(nodeTable));
@@ -602,13 +610,14 @@ size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, si
return HUF_compress4X_usingCTable_internal(dst, dstSize, src, srcSize, CTable, /* bmi2 */ 0);
}
+typedef enum { HUF_singleStream, HUF_fourStreams } HUF_nbStreams_e;
static size_t HUF_compressCTable_internal(
BYTE* const ostart, BYTE* op, BYTE* const oend,
const void* src, size_t srcSize,
- unsigned singleStream, const HUF_CElt* CTable, const int bmi2)
+ HUF_nbStreams_e nbStreams, const HUF_CElt* CTable, const int bmi2)
{
- size_t const cSize = singleStream ?
+ size_t const cSize = (nbStreams==HUF_singleStream) ?
HUF_compress1X_usingCTable_internal(op, oend - op, src, srcSize, CTable, bmi2) :
HUF_compress4X_usingCTable_internal(op, oend - op, src, srcSize, CTable, bmi2);
if (HUF_isError(cSize)) { return cSize; }
@@ -620,21 +629,21 @@ static size_t HUF_compressCTable_internal(
}
typedef struct {
- U32 count[HUF_SYMBOLVALUE_MAX + 1];
+ unsigned count[HUF_SYMBOLVALUE_MAX + 1];
HUF_CElt CTable[HUF_SYMBOLVALUE_MAX + 1];
huffNodeTable nodeTable;
} HUF_compress_tables_t;
/* HUF_compress_internal() :
* `workSpace` must a table of at least HUF_WORKSPACE_SIZE_U32 unsigned */
-static size_t HUF_compress_internal (
- void* dst, size_t dstSize,
- const void* src, size_t srcSize,
- unsigned maxSymbolValue, unsigned huffLog,
- unsigned singleStream,
- void* workSpace, size_t wkspSize,
- HUF_CElt* oldHufTable, HUF_repeat* repeat, int preferRepeat,
- const int bmi2)
+static size_t
+HUF_compress_internal (void* dst, size_t dstSize,
+ const void* src, size_t srcSize,
+ unsigned maxSymbolValue, unsigned huffLog,
+ HUF_nbStreams_e nbStreams,
+ void* workSpace, size_t wkspSize,
+ HUF_CElt* oldHufTable, HUF_repeat* repeat, int preferRepeat,
+ const int bmi2)
{
HUF_compress_tables_t* const table = (HUF_compress_tables_t*)workSpace;
BYTE* const ostart = (BYTE*)dst;
@@ -643,7 +652,7 @@ static size_t HUF_compress_internal (
/* checks & inits */
if (((size_t)workSpace & 3) != 0) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */
- if (wkspSize < sizeof(*table)) return ERROR(workSpace_tooSmall);
+ if (wkspSize < HUF_WORKSPACE_SIZE) return ERROR(workSpace_tooSmall);
if (!srcSize) return 0; /* Uncompressed */
if (!dstSize) return 0; /* cannot fit anything within dst budget */
if (srcSize > HUF_BLOCKSIZE_MAX) return ERROR(srcSize_wrong); /* current block size limit */
@@ -656,13 +665,13 @@ static size_t HUF_compress_internal (
if (preferRepeat && repeat && *repeat == HUF_repeat_valid) {
return HUF_compressCTable_internal(ostart, op, oend,
src, srcSize,
- singleStream, oldHufTable, bmi2);
+ nbStreams, oldHufTable, bmi2);
}
/* Scan input and build symbol stats */
- { CHECK_V_F(largest, FSE_count_wksp (table->count, &maxSymbolValue, (const BYTE*)src, srcSize, table->count) );
+ { CHECK_V_F(largest, HIST_count_wksp (table->count, &maxSymbolValue, (const BYTE*)src, srcSize, workSpace, wkspSize) );
if (largest == srcSize) { *ostart = ((const BYTE*)src)[0]; return 1; } /* single symbol, rle */
- if (largest <= (srcSize >> 7)+1) return 0; /* heuristic : probably not compressible enough */
+ if (largest <= (srcSize >> 7)+4) return 0; /* heuristic : probably not compressible enough */
}
/* Check validity of previous table */
@@ -675,14 +684,15 @@ static size_t HUF_compress_internal (
if (preferRepeat && repeat && *repeat != HUF_repeat_none) {
return HUF_compressCTable_internal(ostart, op, oend,
src, srcSize,
- singleStream, oldHufTable, bmi2);
+ nbStreams, oldHufTable, bmi2);
}
/* Build Huffman Tree */
huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue);
- { CHECK_V_F(maxBits, HUF_buildCTable_wksp(table->CTable, table->count,
- maxSymbolValue, huffLog,
- table->nodeTable, sizeof(table->nodeTable)) );
+ { size_t const maxBits = HUF_buildCTable_wksp(table->CTable, table->count,
+ maxSymbolValue, huffLog,
+ table->nodeTable, sizeof(table->nodeTable));
+ CHECK_F(maxBits);
huffLog = (U32)maxBits;
/* Zero unused symbols in CTable, so we can check it for validity */
memset(table->CTable + (maxSymbolValue + 1), 0,
@@ -698,7 +708,7 @@ static size_t HUF_compress_internal (
if (oldSize <= hSize + newSize || hSize + 12 >= srcSize) {
return HUF_compressCTable_internal(ostart, op, oend,
src, srcSize,
- singleStream, oldHufTable, bmi2);
+ nbStreams, oldHufTable, bmi2);
} }
/* Use the new huffman table */
@@ -710,7 +720,7 @@ static size_t HUF_compress_internal (
}
return HUF_compressCTable_internal(ostart, op, oend,
src, srcSize,
- singleStream, table->CTable, bmi2);
+ nbStreams, table->CTable, bmi2);
}
@@ -720,7 +730,7 @@ size_t HUF_compress1X_wksp (void* dst, size_t dstSize,
void* workSpace, size_t wkspSize)
{
return HUF_compress_internal(dst, dstSize, src, srcSize,
- maxSymbolValue, huffLog, 1 /*single stream*/,
+ maxSymbolValue, huffLog, HUF_singleStream,
workSpace, wkspSize,
NULL, NULL, 0, 0 /*bmi2*/);
}
@@ -732,7 +742,7 @@ size_t HUF_compress1X_repeat (void* dst, size_t dstSize,
HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2)
{
return HUF_compress_internal(dst, dstSize, src, srcSize,
- maxSymbolValue, huffLog, 1 /*single stream*/,
+ maxSymbolValue, huffLog, HUF_singleStream,
workSpace, wkspSize, hufTable,
repeat, preferRepeat, bmi2);
}
@@ -754,7 +764,7 @@ size_t HUF_compress4X_wksp (void* dst, size_t dstSize,
void* workSpace, size_t wkspSize)
{
return HUF_compress_internal(dst, dstSize, src, srcSize,
- maxSymbolValue, huffLog, 0 /*4 streams*/,
+ maxSymbolValue, huffLog, HUF_fourStreams,
workSpace, wkspSize,
NULL, NULL, 0, 0 /*bmi2*/);
}
@@ -769,7 +779,7 @@ size_t HUF_compress4X_repeat (void* dst, size_t dstSize,
HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2)
{
return HUF_compress_internal(dst, dstSize, src, srcSize,
- maxSymbolValue, huffLog, 0 /* 4 streams */,
+ maxSymbolValue, huffLog, HUF_fourStreams,
workSpace, wkspSize,
hufTable, repeat, preferRepeat, bmi2);
}
diff --git a/thirdparty/zstd/compress/zstd_compress.c b/thirdparty/zstd/compress/zstd_compress.c
index 2aa26da4cd..2e163c8bf3 100644
--- a/thirdparty/zstd/compress/zstd_compress.c
+++ b/thirdparty/zstd/compress/zstd_compress.c
@@ -8,21 +8,14 @@
* You may select, at your option, one of the above-listed licenses.
*/
-
-/*-*************************************
-* Tuning parameters
-***************************************/
-#ifndef ZSTD_CLEVEL_DEFAULT
-# define ZSTD_CLEVEL_DEFAULT 3
-#endif
-
-
/*-*************************************
* Dependencies
***************************************/
+#include <limits.h> /* INT_MAX */
#include <string.h> /* memset */
#include "cpu.h"
#include "mem.h"
+#include "hist.h" /* HIST_countFast_wksp */
#define FSE_STATIC_LINKING_ONLY /* FSE_encodeSymbol */
#include "fse.h"
#define HUF_STATIC_LINKING_ONLY
@@ -54,7 +47,6 @@ struct ZSTD_CDict_s {
size_t workspaceSize;
ZSTD_matchState_t matchState;
ZSTD_compressedBlockState_t cBlockState;
- ZSTD_compressionParameters cParams;
ZSTD_customMem customMem;
U32 dictID;
}; /* typedef'd to ZSTD_CDict within "zstd.h" */
@@ -64,17 +56,26 @@ ZSTD_CCtx* ZSTD_createCCtx(void)
return ZSTD_createCCtx_advanced(ZSTD_defaultCMem);
}
+static void ZSTD_initCCtx(ZSTD_CCtx* cctx, ZSTD_customMem memManager)
+{
+ assert(cctx != NULL);
+ memset(cctx, 0, sizeof(*cctx));
+ cctx->customMem = memManager;
+ cctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
+ { size_t const err = ZSTD_CCtx_reset(cctx, ZSTD_reset_parameters);
+ assert(!ZSTD_isError(err));
+ (void)err;
+ }
+}
+
ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem)
{
ZSTD_STATIC_ASSERT(zcss_init==0);
ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN==(0ULL - 1));
if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
- { ZSTD_CCtx* const cctx = (ZSTD_CCtx*)ZSTD_calloc(sizeof(ZSTD_CCtx), customMem);
+ { ZSTD_CCtx* const cctx = (ZSTD_CCtx*)ZSTD_malloc(sizeof(ZSTD_CCtx), customMem);
if (!cctx) return NULL;
- cctx->customMem = customMem;
- cctx->requestedParams.compressionLevel = ZSTD_CLEVEL_DEFAULT;
- cctx->requestedParams.fParams.contentSizeFlag = 1;
- cctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
+ ZSTD_initCCtx(cctx, customMem);
return cctx;
}
}
@@ -102,17 +103,44 @@ ZSTD_CCtx* ZSTD_initStaticCCtx(void *workspace, size_t workspaceSize)
return cctx;
}
-size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
+/**
+ * Clears and frees all of the dictionaries in the CCtx.
+ */
+static void ZSTD_clearAllDicts(ZSTD_CCtx* cctx)
{
- if (cctx==NULL) return 0; /* support free on NULL */
- if (cctx->staticSize) return ERROR(memory_allocation); /* not compatible with static CCtx */
+ ZSTD_free(cctx->localDict.dictBuffer, cctx->customMem);
+ ZSTD_freeCDict(cctx->localDict.cdict);
+ memset(&cctx->localDict, 0, sizeof(cctx->localDict));
+ memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict));
+ cctx->cdict = NULL;
+}
+
+static size_t ZSTD_sizeof_localDict(ZSTD_localDict dict)
+{
+ size_t const bufferSize = dict.dictBuffer != NULL ? dict.dictSize : 0;
+ size_t const cdictSize = ZSTD_sizeof_CDict(dict.cdict);
+ return bufferSize + cdictSize;
+}
+
+static void ZSTD_freeCCtxContent(ZSTD_CCtx* cctx)
+{
+ assert(cctx != NULL);
+ assert(cctx->staticSize == 0);
ZSTD_free(cctx->workSpace, cctx->customMem); cctx->workSpace = NULL;
- ZSTD_freeCDict(cctx->cdictLocal); cctx->cdictLocal = NULL;
+ ZSTD_clearAllDicts(cctx);
#ifdef ZSTD_MULTITHREAD
ZSTDMT_freeCCtx(cctx->mtctx); cctx->mtctx = NULL;
#endif
+}
+
+size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
+{
+ if (cctx==NULL) return 0; /* support free on NULL */
+ RETURN_ERROR_IF(cctx->staticSize, memory_allocation,
+ "not compatible with static CCtx");
+ ZSTD_freeCCtxContent(cctx);
ZSTD_free(cctx, cctx->customMem);
- return 0; /* reserved as a potential error code in the future */
+ return 0;
}
@@ -121,7 +149,7 @@ static size_t ZSTD_sizeof_mtctx(const ZSTD_CCtx* cctx)
#ifdef ZSTD_MULTITHREAD
return ZSTDMT_sizeof_CCtx(cctx->mtctx);
#else
- (void) cctx;
+ (void)cctx;
return 0;
#endif
}
@@ -131,7 +159,7 @@ size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx)
{
if (cctx==NULL) return 0; /* support sizeof on NULL */
return sizeof(*cctx) + cctx->workSpaceSize
- + ZSTD_sizeof_CDict(cctx->cdictLocal)
+ + ZSTD_sizeof_localDict(cctx->localDict)
+ ZSTD_sizeof_mtctx(cctx);
}
@@ -143,21 +171,6 @@ size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs)
/* private API call, for dictBuilder only */
const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx) { return &(ctx->seqStore); }
-ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
- const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize)
-{
- ZSTD_compressionParameters cParams = ZSTD_getCParams(CCtxParams->compressionLevel, srcSizeHint, dictSize);
- if (CCtxParams->ldmParams.enableLdm) cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG;
- if (CCtxParams->cParams.windowLog) cParams.windowLog = CCtxParams->cParams.windowLog;
- if (CCtxParams->cParams.hashLog) cParams.hashLog = CCtxParams->cParams.hashLog;
- if (CCtxParams->cParams.chainLog) cParams.chainLog = CCtxParams->cParams.chainLog;
- if (CCtxParams->cParams.searchLog) cParams.searchLog = CCtxParams->cParams.searchLog;
- if (CCtxParams->cParams.searchLength) cParams.searchLength = CCtxParams->cParams.searchLength;
- if (CCtxParams->cParams.targetLength) cParams.targetLength = CCtxParams->cParams.targetLength;
- if (CCtxParams->cParams.strategy) cParams.strategy = CCtxParams->cParams.strategy;
- return cParams;
-}
-
static ZSTD_CCtx_params ZSTD_makeCCtxParamsFromCParams(
ZSTD_compressionParameters cParams)
{
@@ -202,7 +215,7 @@ size_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params)
}
size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel) {
- if (!cctxParams) { return ERROR(GENERIC); }
+ RETURN_ERROR_IF(!cctxParams, GENERIC);
memset(cctxParams, 0, sizeof(*cctxParams));
cctxParams->compressionLevel = compressionLevel;
cctxParams->fParams.contentSizeFlag = 1;
@@ -211,8 +224,8 @@ size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel)
size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params)
{
- if (!cctxParams) { return ERROR(GENERIC); }
- CHECK_F( ZSTD_checkCParams(params.cParams) );
+ RETURN_ERROR_IF(!cctxParams, GENERIC);
+ FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) );
memset(cctxParams, 0, sizeof(*cctxParams));
cctxParams->cParams = params.cParams;
cctxParams->fParams = params.fParams;
@@ -234,247 +247,535 @@ static ZSTD_CCtx_params ZSTD_assignParamsToCCtxParams(
return ret;
}
-#define CLAMPCHECK(val,min,max) { \
- if (((val)<(min)) | ((val)>(max))) { \
- return ERROR(parameter_outOfBound); \
-} }
+ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param)
+{
+ ZSTD_bounds bounds = { 0, 0, 0 };
+
+ switch(param)
+ {
+ case ZSTD_c_compressionLevel:
+ bounds.lowerBound = ZSTD_minCLevel();
+ bounds.upperBound = ZSTD_maxCLevel();
+ return bounds;
+
+ case ZSTD_c_windowLog:
+ bounds.lowerBound = ZSTD_WINDOWLOG_MIN;
+ bounds.upperBound = ZSTD_WINDOWLOG_MAX;
+ return bounds;
+
+ case ZSTD_c_hashLog:
+ bounds.lowerBound = ZSTD_HASHLOG_MIN;
+ bounds.upperBound = ZSTD_HASHLOG_MAX;
+ return bounds;
+
+ case ZSTD_c_chainLog:
+ bounds.lowerBound = ZSTD_CHAINLOG_MIN;
+ bounds.upperBound = ZSTD_CHAINLOG_MAX;
+ return bounds;
+
+ case ZSTD_c_searchLog:
+ bounds.lowerBound = ZSTD_SEARCHLOG_MIN;
+ bounds.upperBound = ZSTD_SEARCHLOG_MAX;
+ return bounds;
+
+ case ZSTD_c_minMatch:
+ bounds.lowerBound = ZSTD_MINMATCH_MIN;
+ bounds.upperBound = ZSTD_MINMATCH_MAX;
+ return bounds;
+
+ case ZSTD_c_targetLength:
+ bounds.lowerBound = ZSTD_TARGETLENGTH_MIN;
+ bounds.upperBound = ZSTD_TARGETLENGTH_MAX;
+ return bounds;
+
+ case ZSTD_c_strategy:
+ bounds.lowerBound = ZSTD_STRATEGY_MIN;
+ bounds.upperBound = ZSTD_STRATEGY_MAX;
+ return bounds;
+
+ case ZSTD_c_contentSizeFlag:
+ bounds.lowerBound = 0;
+ bounds.upperBound = 1;
+ return bounds;
+
+ case ZSTD_c_checksumFlag:
+ bounds.lowerBound = 0;
+ bounds.upperBound = 1;
+ return bounds;
+
+ case ZSTD_c_dictIDFlag:
+ bounds.lowerBound = 0;
+ bounds.upperBound = 1;
+ return bounds;
+
+ case ZSTD_c_nbWorkers:
+ bounds.lowerBound = 0;
+#ifdef ZSTD_MULTITHREAD
+ bounds.upperBound = ZSTDMT_NBWORKERS_MAX;
+#else
+ bounds.upperBound = 0;
+#endif
+ return bounds;
+
+ case ZSTD_c_jobSize:
+ bounds.lowerBound = 0;
+#ifdef ZSTD_MULTITHREAD
+ bounds.upperBound = ZSTDMT_JOBSIZE_MAX;
+#else
+ bounds.upperBound = 0;
+#endif
+ return bounds;
+
+ case ZSTD_c_overlapLog:
+ bounds.lowerBound = ZSTD_OVERLAPLOG_MIN;
+ bounds.upperBound = ZSTD_OVERLAPLOG_MAX;
+ return bounds;
+
+ case ZSTD_c_enableLongDistanceMatching:
+ bounds.lowerBound = 0;
+ bounds.upperBound = 1;
+ return bounds;
+
+ case ZSTD_c_ldmHashLog:
+ bounds.lowerBound = ZSTD_LDM_HASHLOG_MIN;
+ bounds.upperBound = ZSTD_LDM_HASHLOG_MAX;
+ return bounds;
+
+ case ZSTD_c_ldmMinMatch:
+ bounds.lowerBound = ZSTD_LDM_MINMATCH_MIN;
+ bounds.upperBound = ZSTD_LDM_MINMATCH_MAX;
+ return bounds;
+
+ case ZSTD_c_ldmBucketSizeLog:
+ bounds.lowerBound = ZSTD_LDM_BUCKETSIZELOG_MIN;
+ bounds.upperBound = ZSTD_LDM_BUCKETSIZELOG_MAX;
+ return bounds;
+
+ case ZSTD_c_ldmHashRateLog:
+ bounds.lowerBound = ZSTD_LDM_HASHRATELOG_MIN;
+ bounds.upperBound = ZSTD_LDM_HASHRATELOG_MAX;
+ return bounds;
+
+ /* experimental parameters */
+ case ZSTD_c_rsyncable:
+ bounds.lowerBound = 0;
+ bounds.upperBound = 1;
+ return bounds;
+
+ case ZSTD_c_forceMaxWindow :
+ bounds.lowerBound = 0;
+ bounds.upperBound = 1;
+ return bounds;
+
+ case ZSTD_c_format:
+ ZSTD_STATIC_ASSERT(ZSTD_f_zstd1 < ZSTD_f_zstd1_magicless);
+ bounds.lowerBound = ZSTD_f_zstd1;
+ bounds.upperBound = ZSTD_f_zstd1_magicless; /* note : how to ensure at compile time that this is the highest value enum ? */
+ return bounds;
+
+ case ZSTD_c_forceAttachDict:
+ ZSTD_STATIC_ASSERT(ZSTD_dictDefaultAttach < ZSTD_dictForceCopy);
+ bounds.lowerBound = ZSTD_dictDefaultAttach;
+ bounds.upperBound = ZSTD_dictForceCopy; /* note : how to ensure at compile time that this is the highest value enum ? */
+ return bounds;
+
+ case ZSTD_c_literalCompressionMode:
+ ZSTD_STATIC_ASSERT(ZSTD_lcm_auto < ZSTD_lcm_huffman && ZSTD_lcm_huffman < ZSTD_lcm_uncompressed);
+ bounds.lowerBound = ZSTD_lcm_auto;
+ bounds.upperBound = ZSTD_lcm_uncompressed;
+ return bounds;
+
+ default:
+ { ZSTD_bounds const boundError = { ERROR(parameter_unsupported), 0, 0 };
+ return boundError;
+ }
+ }
+}
+
+/* ZSTD_cParam_withinBounds:
+ * @return 1 if value is within cParam bounds,
+ * 0 otherwise */
+static int ZSTD_cParam_withinBounds(ZSTD_cParameter cParam, int value)
+{
+ ZSTD_bounds const bounds = ZSTD_cParam_getBounds(cParam);
+ if (ZSTD_isError(bounds.error)) return 0;
+ if (value < bounds.lowerBound) return 0;
+ if (value > bounds.upperBound) return 0;
+ return 1;
+}
+
+/* ZSTD_cParam_clampBounds:
+ * Clamps the value into the bounded range.
+ */
+static size_t ZSTD_cParam_clampBounds(ZSTD_cParameter cParam, int* value)
+{
+ ZSTD_bounds const bounds = ZSTD_cParam_getBounds(cParam);
+ if (ZSTD_isError(bounds.error)) return bounds.error;
+ if (*value < bounds.lowerBound) *value = bounds.lowerBound;
+ if (*value > bounds.upperBound) *value = bounds.upperBound;
+ return 0;
+}
+
+#define BOUNDCHECK(cParam, val) { \
+ RETURN_ERROR_IF(!ZSTD_cParam_withinBounds(cParam,val), \
+ parameter_outOfBound); \
+}
static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param)
{
switch(param)
{
- case ZSTD_p_compressionLevel:
- case ZSTD_p_hashLog:
- case ZSTD_p_chainLog:
- case ZSTD_p_searchLog:
- case ZSTD_p_minMatch:
- case ZSTD_p_targetLength:
- case ZSTD_p_compressionStrategy:
- case ZSTD_p_compressLiterals:
+ case ZSTD_c_compressionLevel:
+ case ZSTD_c_hashLog:
+ case ZSTD_c_chainLog:
+ case ZSTD_c_searchLog:
+ case ZSTD_c_minMatch:
+ case ZSTD_c_targetLength:
+ case ZSTD_c_strategy:
return 1;
- case ZSTD_p_format:
- case ZSTD_p_windowLog:
- case ZSTD_p_contentSizeFlag:
- case ZSTD_p_checksumFlag:
- case ZSTD_p_dictIDFlag:
- case ZSTD_p_forceMaxWindow :
- case ZSTD_p_nbWorkers:
- case ZSTD_p_jobSize:
- case ZSTD_p_overlapSizeLog:
- case ZSTD_p_enableLongDistanceMatching:
- case ZSTD_p_ldmHashLog:
- case ZSTD_p_ldmMinMatch:
- case ZSTD_p_ldmBucketSizeLog:
- case ZSTD_p_ldmHashEveryLog:
+ case ZSTD_c_format:
+ case ZSTD_c_windowLog:
+ case ZSTD_c_contentSizeFlag:
+ case ZSTD_c_checksumFlag:
+ case ZSTD_c_dictIDFlag:
+ case ZSTD_c_forceMaxWindow :
+ case ZSTD_c_nbWorkers:
+ case ZSTD_c_jobSize:
+ case ZSTD_c_overlapLog:
+ case ZSTD_c_rsyncable:
+ case ZSTD_c_enableLongDistanceMatching:
+ case ZSTD_c_ldmHashLog:
+ case ZSTD_c_ldmMinMatch:
+ case ZSTD_c_ldmBucketSizeLog:
+ case ZSTD_c_ldmHashRateLog:
+ case ZSTD_c_forceAttachDict:
+ case ZSTD_c_literalCompressionMode:
default:
return 0;
}
}
-size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, unsigned value)
+size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value)
{
- DEBUGLOG(4, "ZSTD_CCtx_setParameter (%u, %u)", (U32)param, value);
+ DEBUGLOG(4, "ZSTD_CCtx_setParameter (%i, %i)", (int)param, value);
if (cctx->streamStage != zcss_init) {
if (ZSTD_isUpdateAuthorized(param)) {
cctx->cParamsChanged = 1;
} else {
- return ERROR(stage_wrong);
+ RETURN_ERROR(stage_wrong);
} }
switch(param)
{
- case ZSTD_p_format :
- return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
-
- case ZSTD_p_compressionLevel:
- if (cctx->cdict) return ERROR(stage_wrong);
- return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
-
- case ZSTD_p_windowLog:
- case ZSTD_p_hashLog:
- case ZSTD_p_chainLog:
- case ZSTD_p_searchLog:
- case ZSTD_p_minMatch:
- case ZSTD_p_targetLength:
- case ZSTD_p_compressionStrategy:
- if (cctx->cdict) return ERROR(stage_wrong);
- return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
-
- case ZSTD_p_compressLiterals:
- case ZSTD_p_contentSizeFlag:
- case ZSTD_p_checksumFlag:
- case ZSTD_p_dictIDFlag:
- return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
-
- case ZSTD_p_forceMaxWindow : /* Force back-references to remain < windowSize,
- * even when referencing into Dictionary content.
- * default : 0 when using a CDict, 1 when using a Prefix */
- return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
-
- case ZSTD_p_nbWorkers:
- if ((value>0) && cctx->staticSize) {
- return ERROR(parameter_unsupported); /* MT not compatible with static alloc */
- }
- return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
-
- case ZSTD_p_jobSize:
- case ZSTD_p_overlapSizeLog:
- return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
+ case ZSTD_c_nbWorkers:
+ RETURN_ERROR_IF((value!=0) && cctx->staticSize, parameter_unsupported,
+ "MT not compatible with static alloc");
+ break;
- case ZSTD_p_enableLongDistanceMatching:
- case ZSTD_p_ldmHashLog:
- case ZSTD_p_ldmMinMatch:
- case ZSTD_p_ldmBucketSizeLog:
- case ZSTD_p_ldmHashEveryLog:
- if (cctx->cdict) return ERROR(stage_wrong);
- return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
+ case ZSTD_c_compressionLevel:
+ case ZSTD_c_windowLog:
+ case ZSTD_c_hashLog:
+ case ZSTD_c_chainLog:
+ case ZSTD_c_searchLog:
+ case ZSTD_c_minMatch:
+ case ZSTD_c_targetLength:
+ case ZSTD_c_strategy:
+ case ZSTD_c_ldmHashRateLog:
+ case ZSTD_c_format:
+ case ZSTD_c_contentSizeFlag:
+ case ZSTD_c_checksumFlag:
+ case ZSTD_c_dictIDFlag:
+ case ZSTD_c_forceMaxWindow:
+ case ZSTD_c_forceAttachDict:
+ case ZSTD_c_literalCompressionMode:
+ case ZSTD_c_jobSize:
+ case ZSTD_c_overlapLog:
+ case ZSTD_c_rsyncable:
+ case ZSTD_c_enableLongDistanceMatching:
+ case ZSTD_c_ldmHashLog:
+ case ZSTD_c_ldmMinMatch:
+ case ZSTD_c_ldmBucketSizeLog:
+ break;
- default: return ERROR(parameter_unsupported);
+ default: RETURN_ERROR(parameter_unsupported);
}
+ return ZSTD_CCtxParams_setParameter(&cctx->requestedParams, param, value);
}
-size_t ZSTD_CCtxParam_setParameter(
- ZSTD_CCtx_params* CCtxParams, ZSTD_cParameter param, unsigned value)
+size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
+ ZSTD_cParameter param, int value)
{
- DEBUGLOG(4, "ZSTD_CCtxParam_setParameter (%u, %u)", (U32)param, value);
+ DEBUGLOG(4, "ZSTD_CCtxParams_setParameter (%i, %i)", (int)param, value);
switch(param)
{
- case ZSTD_p_format :
- if (value > (unsigned)ZSTD_f_zstd1_magicless)
- return ERROR(parameter_unsupported);
+ case ZSTD_c_format :
+ BOUNDCHECK(ZSTD_c_format, value);
CCtxParams->format = (ZSTD_format_e)value;
return (size_t)CCtxParams->format;
- case ZSTD_p_compressionLevel : {
- int cLevel = (int)value; /* cast expected to restore negative sign */
- if (cLevel > ZSTD_maxCLevel()) cLevel = ZSTD_maxCLevel();
- if (cLevel) { /* 0 : does not change current level */
- CCtxParams->disableLiteralCompression = (cLevel<0); /* negative levels disable huffman */
- CCtxParams->compressionLevel = cLevel;
+ case ZSTD_c_compressionLevel : {
+ FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value));
+ if (value) { /* 0 : does not change current level */
+ CCtxParams->compressionLevel = value;
}
if (CCtxParams->compressionLevel >= 0) return CCtxParams->compressionLevel;
return 0; /* return type (size_t) cannot represent negative values */
}
- case ZSTD_p_windowLog :
- if (value>0) /* 0 => use default */
- CLAMPCHECK(value, ZSTD_WINDOWLOG_MIN, ZSTD_WINDOWLOG_MAX);
+ case ZSTD_c_windowLog :
+ if (value!=0) /* 0 => use default */
+ BOUNDCHECK(ZSTD_c_windowLog, value);
CCtxParams->cParams.windowLog = value;
return CCtxParams->cParams.windowLog;
- case ZSTD_p_hashLog :
- if (value>0) /* 0 => use default */
- CLAMPCHECK(value, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
+ case ZSTD_c_hashLog :
+ if (value!=0) /* 0 => use default */
+ BOUNDCHECK(ZSTD_c_hashLog, value);
CCtxParams->cParams.hashLog = value;
return CCtxParams->cParams.hashLog;
- case ZSTD_p_chainLog :
- if (value>0) /* 0 => use default */
- CLAMPCHECK(value, ZSTD_CHAINLOG_MIN, ZSTD_CHAINLOG_MAX);
+ case ZSTD_c_chainLog :
+ if (value!=0) /* 0 => use default */
+ BOUNDCHECK(ZSTD_c_chainLog, value);
CCtxParams->cParams.chainLog = value;
return CCtxParams->cParams.chainLog;
- case ZSTD_p_searchLog :
- if (value>0) /* 0 => use default */
- CLAMPCHECK(value, ZSTD_SEARCHLOG_MIN, ZSTD_SEARCHLOG_MAX);
+ case ZSTD_c_searchLog :
+ if (value!=0) /* 0 => use default */
+ BOUNDCHECK(ZSTD_c_searchLog, value);
CCtxParams->cParams.searchLog = value;
return value;
- case ZSTD_p_minMatch :
- if (value>0) /* 0 => use default */
- CLAMPCHECK(value, ZSTD_SEARCHLENGTH_MIN, ZSTD_SEARCHLENGTH_MAX);
- CCtxParams->cParams.searchLength = value;
- return CCtxParams->cParams.searchLength;
+ case ZSTD_c_minMatch :
+ if (value!=0) /* 0 => use default */
+ BOUNDCHECK(ZSTD_c_minMatch, value);
+ CCtxParams->cParams.minMatch = value;
+ return CCtxParams->cParams.minMatch;
- case ZSTD_p_targetLength :
- /* all values are valid. 0 => use default */
+ case ZSTD_c_targetLength :
+ BOUNDCHECK(ZSTD_c_targetLength, value);
CCtxParams->cParams.targetLength = value;
return CCtxParams->cParams.targetLength;
- case ZSTD_p_compressionStrategy :
- if (value>0) /* 0 => use default */
- CLAMPCHECK(value, (unsigned)ZSTD_fast, (unsigned)ZSTD_btultra);
+ case ZSTD_c_strategy :
+ if (value!=0) /* 0 => use default */
+ BOUNDCHECK(ZSTD_c_strategy, value);
CCtxParams->cParams.strategy = (ZSTD_strategy)value;
return (size_t)CCtxParams->cParams.strategy;
- case ZSTD_p_compressLiterals:
- CCtxParams->disableLiteralCompression = !value;
- return !CCtxParams->disableLiteralCompression;
-
- case ZSTD_p_contentSizeFlag :
+ case ZSTD_c_contentSizeFlag :
/* Content size written in frame header _when known_ (default:1) */
- DEBUGLOG(4, "set content size flag = %u", (value>0));
- CCtxParams->fParams.contentSizeFlag = value > 0;
+ DEBUGLOG(4, "set content size flag = %u", (value!=0));
+ CCtxParams->fParams.contentSizeFlag = value != 0;
return CCtxParams->fParams.contentSizeFlag;
- case ZSTD_p_checksumFlag :
+ case ZSTD_c_checksumFlag :
/* A 32-bits content checksum will be calculated and written at end of frame (default:0) */
- CCtxParams->fParams.checksumFlag = value > 0;
+ CCtxParams->fParams.checksumFlag = value != 0;
return CCtxParams->fParams.checksumFlag;
- case ZSTD_p_dictIDFlag : /* When applicable, dictionary's dictID is provided in frame header (default:1) */
- DEBUGLOG(4, "set dictIDFlag = %u", (value>0));
+ case ZSTD_c_dictIDFlag : /* When applicable, dictionary's dictID is provided in frame header (default:1) */
+ DEBUGLOG(4, "set dictIDFlag = %u", (value!=0));
CCtxParams->fParams.noDictIDFlag = !value;
return !CCtxParams->fParams.noDictIDFlag;
- case ZSTD_p_forceMaxWindow :
- CCtxParams->forceWindow = (value > 0);
+ case ZSTD_c_forceMaxWindow :
+ CCtxParams->forceWindow = (value != 0);
return CCtxParams->forceWindow;
- case ZSTD_p_nbWorkers :
+ case ZSTD_c_forceAttachDict : {
+ const ZSTD_dictAttachPref_e pref = (ZSTD_dictAttachPref_e)value;
+ BOUNDCHECK(ZSTD_c_forceAttachDict, pref);
+ CCtxParams->attachDictPref = pref;
+ return CCtxParams->attachDictPref;
+ }
+
+ case ZSTD_c_literalCompressionMode : {
+ const ZSTD_literalCompressionMode_e lcm = (ZSTD_literalCompressionMode_e)value;
+ BOUNDCHECK(ZSTD_c_literalCompressionMode, lcm);
+ CCtxParams->literalCompressionMode = lcm;
+ return CCtxParams->literalCompressionMode;
+ }
+
+ case ZSTD_c_nbWorkers :
#ifndef ZSTD_MULTITHREAD
- if (value>0) return ERROR(parameter_unsupported);
+ RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading");
return 0;
#else
- return ZSTDMT_CCtxParam_setNbWorkers(CCtxParams, value);
+ FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value));
+ CCtxParams->nbWorkers = value;
+ return CCtxParams->nbWorkers;
#endif
- case ZSTD_p_jobSize :
+ case ZSTD_c_jobSize :
#ifndef ZSTD_MULTITHREAD
- return ERROR(parameter_unsupported);
+ RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading");
+ return 0;
#else
- return ZSTDMT_CCtxParam_setMTCtxParameter(CCtxParams, ZSTDMT_p_jobSize, value);
+ /* Adjust to the minimum non-default value. */
+ if (value != 0 && value < ZSTDMT_JOBSIZE_MIN)
+ value = ZSTDMT_JOBSIZE_MIN;
+ FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value));
+ assert(value >= 0);
+ CCtxParams->jobSize = value;
+ return CCtxParams->jobSize;
#endif
- case ZSTD_p_overlapSizeLog :
+ case ZSTD_c_overlapLog :
#ifndef ZSTD_MULTITHREAD
- return ERROR(parameter_unsupported);
+ RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading");
+ return 0;
#else
- return ZSTDMT_CCtxParam_setMTCtxParameter(CCtxParams, ZSTDMT_p_overlapSectionLog, value);
+ FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(ZSTD_c_overlapLog, &value));
+ CCtxParams->overlapLog = value;
+ return CCtxParams->overlapLog;
#endif
- case ZSTD_p_enableLongDistanceMatching :
- CCtxParams->ldmParams.enableLdm = (value>0);
+ case ZSTD_c_rsyncable :
+#ifndef ZSTD_MULTITHREAD
+ RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading");
+ return 0;
+#else
+ FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(ZSTD_c_overlapLog, &value));
+ CCtxParams->rsyncable = value;
+ return CCtxParams->rsyncable;
+#endif
+
+ case ZSTD_c_enableLongDistanceMatching :
+ CCtxParams->ldmParams.enableLdm = (value!=0);
return CCtxParams->ldmParams.enableLdm;
- case ZSTD_p_ldmHashLog :
- if (value>0) /* 0 ==> auto */
- CLAMPCHECK(value, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
+ case ZSTD_c_ldmHashLog :
+ if (value!=0) /* 0 ==> auto */
+ BOUNDCHECK(ZSTD_c_ldmHashLog, value);
CCtxParams->ldmParams.hashLog = value;
return CCtxParams->ldmParams.hashLog;
- case ZSTD_p_ldmMinMatch :
- if (value>0) /* 0 ==> default */
- CLAMPCHECK(value, ZSTD_LDM_MINMATCH_MIN, ZSTD_LDM_MINMATCH_MAX);
+ case ZSTD_c_ldmMinMatch :
+ if (value!=0) /* 0 ==> default */
+ BOUNDCHECK(ZSTD_c_ldmMinMatch, value);
CCtxParams->ldmParams.minMatchLength = value;
return CCtxParams->ldmParams.minMatchLength;
- case ZSTD_p_ldmBucketSizeLog :
- if (value > ZSTD_LDM_BUCKETSIZELOG_MAX)
- return ERROR(parameter_outOfBound);
+ case ZSTD_c_ldmBucketSizeLog :
+ if (value!=0) /* 0 ==> default */
+ BOUNDCHECK(ZSTD_c_ldmBucketSizeLog, value);
CCtxParams->ldmParams.bucketSizeLog = value;
return CCtxParams->ldmParams.bucketSizeLog;
- case ZSTD_p_ldmHashEveryLog :
- if (value > ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN)
- return ERROR(parameter_outOfBound);
- CCtxParams->ldmParams.hashEveryLog = value;
- return CCtxParams->ldmParams.hashEveryLog;
+ case ZSTD_c_ldmHashRateLog :
+ RETURN_ERROR_IF(value > ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN,
+ parameter_outOfBound);
+ CCtxParams->ldmParams.hashRateLog = value;
+ return CCtxParams->ldmParams.hashRateLog;
+
+ default: RETURN_ERROR(parameter_unsupported, "unknown parameter");
+ }
+}
- default: return ERROR(parameter_unsupported);
+size_t ZSTD_CCtx_getParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int* value)
+{
+ return ZSTD_CCtxParams_getParameter(&cctx->requestedParams, param, value);
+}
+
+size_t ZSTD_CCtxParams_getParameter(
+ ZSTD_CCtx_params* CCtxParams, ZSTD_cParameter param, int* value)
+{
+ switch(param)
+ {
+ case ZSTD_c_format :
+ *value = CCtxParams->format;
+ break;
+ case ZSTD_c_compressionLevel :
+ *value = CCtxParams->compressionLevel;
+ break;
+ case ZSTD_c_windowLog :
+ *value = CCtxParams->cParams.windowLog;
+ break;
+ case ZSTD_c_hashLog :
+ *value = CCtxParams->cParams.hashLog;
+ break;
+ case ZSTD_c_chainLog :
+ *value = CCtxParams->cParams.chainLog;
+ break;
+ case ZSTD_c_searchLog :
+ *value = CCtxParams->cParams.searchLog;
+ break;
+ case ZSTD_c_minMatch :
+ *value = CCtxParams->cParams.minMatch;
+ break;
+ case ZSTD_c_targetLength :
+ *value = CCtxParams->cParams.targetLength;
+ break;
+ case ZSTD_c_strategy :
+ *value = (unsigned)CCtxParams->cParams.strategy;
+ break;
+ case ZSTD_c_contentSizeFlag :
+ *value = CCtxParams->fParams.contentSizeFlag;
+ break;
+ case ZSTD_c_checksumFlag :
+ *value = CCtxParams->fParams.checksumFlag;
+ break;
+ case ZSTD_c_dictIDFlag :
+ *value = !CCtxParams->fParams.noDictIDFlag;
+ break;
+ case ZSTD_c_forceMaxWindow :
+ *value = CCtxParams->forceWindow;
+ break;
+ case ZSTD_c_forceAttachDict :
+ *value = CCtxParams->attachDictPref;
+ break;
+ case ZSTD_c_literalCompressionMode :
+ *value = CCtxParams->literalCompressionMode;
+ break;
+ case ZSTD_c_nbWorkers :
+#ifndef ZSTD_MULTITHREAD
+ assert(CCtxParams->nbWorkers == 0);
+#endif
+ *value = CCtxParams->nbWorkers;
+ break;
+ case ZSTD_c_jobSize :
+#ifndef ZSTD_MULTITHREAD
+ RETURN_ERROR(parameter_unsupported, "not compiled with multithreading");
+#else
+ assert(CCtxParams->jobSize <= INT_MAX);
+ *value = (int)CCtxParams->jobSize;
+ break;
+#endif
+ case ZSTD_c_overlapLog :
+#ifndef ZSTD_MULTITHREAD
+ RETURN_ERROR(parameter_unsupported, "not compiled with multithreading");
+#else
+ *value = CCtxParams->overlapLog;
+ break;
+#endif
+ case ZSTD_c_rsyncable :
+#ifndef ZSTD_MULTITHREAD
+ RETURN_ERROR(parameter_unsupported, "not compiled with multithreading");
+#else
+ *value = CCtxParams->rsyncable;
+ break;
+#endif
+ case ZSTD_c_enableLongDistanceMatching :
+ *value = CCtxParams->ldmParams.enableLdm;
+ break;
+ case ZSTD_c_ldmHashLog :
+ *value = CCtxParams->ldmParams.hashLog;
+ break;
+ case ZSTD_c_ldmMinMatch :
+ *value = CCtxParams->ldmParams.minMatchLength;
+ break;
+ case ZSTD_c_ldmBucketSizeLog :
+ *value = CCtxParams->ldmParams.bucketSizeLog;
+ break;
+ case ZSTD_c_ldmHashRateLog :
+ *value = CCtxParams->ldmParams.hashRateLog;
+ break;
+ default: RETURN_ERROR(parameter_unsupported, "unknown parameter");
}
+ return 0;
}
/** ZSTD_CCtx_setParametersUsingCCtxParams() :
@@ -487,8 +788,9 @@ size_t ZSTD_CCtxParam_setParameter(
size_t ZSTD_CCtx_setParametersUsingCCtxParams(
ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params)
{
- if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
- if (cctx->cdict) return ERROR(stage_wrong);
+ DEBUGLOG(4, "ZSTD_CCtx_setParametersUsingCCtxParams");
+ RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong);
+ RETURN_ERROR_IF(cctx->cdict, stage_wrong);
cctx->requestedParams = *params;
return 0;
@@ -497,33 +799,71 @@ size_t ZSTD_CCtx_setParametersUsingCCtxParams(
ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize)
{
DEBUGLOG(4, "ZSTD_CCtx_setPledgedSrcSize to %u bytes", (U32)pledgedSrcSize);
- if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
+ RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong);
cctx->pledgedSrcSizePlusOne = pledgedSrcSize+1;
return 0;
}
+/**
+ * Initializes the local dict using the requested parameters.
+ * NOTE: This does not use the pledged src size, because it may be used for more
+ * than one compression.
+ */
+static size_t ZSTD_initLocalDict(ZSTD_CCtx* cctx)
+{
+ ZSTD_localDict* const dl = &cctx->localDict;
+ ZSTD_compressionParameters const cParams = ZSTD_getCParamsFromCCtxParams(
+ &cctx->requestedParams, 0, dl->dictSize);
+ if (dl->dict == NULL) {
+ /* No local dictionary. */
+ assert(dl->dictBuffer == NULL);
+ assert(dl->cdict == NULL);
+ assert(dl->dictSize == 0);
+ return 0;
+ }
+ if (dl->cdict != NULL) {
+ assert(cctx->cdict == dl->cdict);
+ /* Local dictionary already initialized. */
+ return 0;
+ }
+ assert(dl->dictSize > 0);
+ assert(cctx->cdict == NULL);
+ assert(cctx->prefixDict.dict == NULL);
+
+ dl->cdict = ZSTD_createCDict_advanced(
+ dl->dict,
+ dl->dictSize,
+ ZSTD_dlm_byRef,
+ dl->dictContentType,
+ cParams,
+ cctx->customMem);
+ RETURN_ERROR_IF(!dl->cdict, memory_allocation);
+ cctx->cdict = dl->cdict;
+ return 0;
+}
+
size_t ZSTD_CCtx_loadDictionary_advanced(
ZSTD_CCtx* cctx, const void* dict, size_t dictSize,
ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType)
{
- if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
- if (cctx->staticSize) return ERROR(memory_allocation); /* no malloc for static CCtx */
+ RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong);
+ RETURN_ERROR_IF(cctx->staticSize, memory_allocation,
+ "no malloc for static CCtx");
DEBUGLOG(4, "ZSTD_CCtx_loadDictionary_advanced (size: %u)", (U32)dictSize);
- ZSTD_freeCDict(cctx->cdictLocal); /* in case one already exists */
- if (dict==NULL || dictSize==0) { /* no dictionary mode */
- cctx->cdictLocal = NULL;
- cctx->cdict = NULL;
+ ZSTD_clearAllDicts(cctx); /* in case one already exists */
+ if (dict == NULL || dictSize == 0) /* no dictionary mode */
+ return 0;
+ if (dictLoadMethod == ZSTD_dlm_byRef) {
+ cctx->localDict.dict = dict;
} else {
- ZSTD_compressionParameters const cParams =
- ZSTD_getCParamsFromCCtxParams(&cctx->requestedParams, cctx->pledgedSrcSizePlusOne-1, dictSize);
- cctx->cdictLocal = ZSTD_createCDict_advanced(
- dict, dictSize,
- dictLoadMethod, dictContentType,
- cParams, cctx->customMem);
- cctx->cdict = cctx->cdictLocal;
- if (cctx->cdictLocal == NULL)
- return ERROR(memory_allocation);
+ void* dictBuffer = ZSTD_malloc(dictSize, cctx->customMem);
+ RETURN_ERROR_IF(!dictBuffer, memory_allocation);
+ memcpy(dictBuffer, dict, dictSize);
+ cctx->localDict.dictBuffer = dictBuffer;
+ cctx->localDict.dict = dictBuffer;
}
+ cctx->localDict.dictSize = dictSize;
+ cctx->localDict.dictContentType = dictContentType;
return 0;
}
@@ -543,9 +883,10 @@ ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, s
size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict)
{
- if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
+ RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong);
+ /* Free the existing local cdict (if any) to save memory. */
+ ZSTD_clearAllDicts(cctx);
cctx->cdict = cdict;
- memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); /* exclusive */
return 0;
}
@@ -557,61 +898,67 @@ size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSiz
size_t ZSTD_CCtx_refPrefix_advanced(
ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType)
{
- if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
- cctx->cdict = NULL; /* prefix discards any prior cdict */
+ RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong);
+ ZSTD_clearAllDicts(cctx);
cctx->prefixDict.dict = prefix;
cctx->prefixDict.dictSize = prefixSize;
cctx->prefixDict.dictContentType = dictContentType;
return 0;
}
-static void ZSTD_startNewCompression(ZSTD_CCtx* cctx)
-{
- cctx->streamStage = zcss_init;
- cctx->pledgedSrcSizePlusOne = 0;
-}
-
/*! ZSTD_CCtx_reset() :
* Also dumps dictionary */
-void ZSTD_CCtx_reset(ZSTD_CCtx* cctx)
+size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset)
{
- ZSTD_startNewCompression(cctx);
- cctx->cdict = NULL;
+ if ( (reset == ZSTD_reset_session_only)
+ || (reset == ZSTD_reset_session_and_parameters) ) {
+ cctx->streamStage = zcss_init;
+ cctx->pledgedSrcSizePlusOne = 0;
+ }
+ if ( (reset == ZSTD_reset_parameters)
+ || (reset == ZSTD_reset_session_and_parameters) ) {
+ RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong);
+ ZSTD_clearAllDicts(cctx);
+ return ZSTD_CCtxParams_reset(&cctx->requestedParams);
+ }
+ return 0;
}
+
/** ZSTD_checkCParams() :
control CParam values remain within authorized range.
@return : 0, or an error code if one value is beyond authorized range */
size_t ZSTD_checkCParams(ZSTD_compressionParameters cParams)
{
- CLAMPCHECK(cParams.windowLog, ZSTD_WINDOWLOG_MIN, ZSTD_WINDOWLOG_MAX);
- CLAMPCHECK(cParams.chainLog, ZSTD_CHAINLOG_MIN, ZSTD_CHAINLOG_MAX);
- CLAMPCHECK(cParams.hashLog, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
- CLAMPCHECK(cParams.searchLog, ZSTD_SEARCHLOG_MIN, ZSTD_SEARCHLOG_MAX);
- CLAMPCHECK(cParams.searchLength, ZSTD_SEARCHLENGTH_MIN, ZSTD_SEARCHLENGTH_MAX);
- if ((U32)(cParams.targetLength) < ZSTD_TARGETLENGTH_MIN)
- return ERROR(parameter_unsupported);
- if ((U32)(cParams.strategy) > (U32)ZSTD_btultra)
- return ERROR(parameter_unsupported);
+ BOUNDCHECK(ZSTD_c_windowLog, cParams.windowLog);
+ BOUNDCHECK(ZSTD_c_chainLog, cParams.chainLog);
+ BOUNDCHECK(ZSTD_c_hashLog, cParams.hashLog);
+ BOUNDCHECK(ZSTD_c_searchLog, cParams.searchLog);
+ BOUNDCHECK(ZSTD_c_minMatch, cParams.minMatch);
+ BOUNDCHECK(ZSTD_c_targetLength,cParams.targetLength);
+ BOUNDCHECK(ZSTD_c_strategy, cParams.strategy);
return 0;
}
/** ZSTD_clampCParams() :
* make CParam values within valid range.
* @return : valid CParams */
-static ZSTD_compressionParameters ZSTD_clampCParams(ZSTD_compressionParameters cParams)
-{
-# define CLAMP(val,min,max) { \
- if (val<min) val=min; \
- else if (val>max) val=max; \
- }
- CLAMP(cParams.windowLog, ZSTD_WINDOWLOG_MIN, ZSTD_WINDOWLOG_MAX);
- CLAMP(cParams.chainLog, ZSTD_CHAINLOG_MIN, ZSTD_CHAINLOG_MAX);
- CLAMP(cParams.hashLog, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
- CLAMP(cParams.searchLog, ZSTD_SEARCHLOG_MIN, ZSTD_SEARCHLOG_MAX);
- CLAMP(cParams.searchLength, ZSTD_SEARCHLENGTH_MIN, ZSTD_SEARCHLENGTH_MAX);
- if ((U32)(cParams.targetLength) < ZSTD_TARGETLENGTH_MIN) cParams.targetLength = ZSTD_TARGETLENGTH_MIN;
- if ((U32)(cParams.strategy) > (U32)ZSTD_btultra) cParams.strategy = ZSTD_btultra;
+static ZSTD_compressionParameters
+ZSTD_clampCParams(ZSTD_compressionParameters cParams)
+{
+# define CLAMP_TYPE(cParam, val, type) { \
+ ZSTD_bounds const bounds = ZSTD_cParam_getBounds(cParam); \
+ if ((int)val<bounds.lowerBound) val=(type)bounds.lowerBound; \
+ else if ((int)val>bounds.upperBound) val=(type)bounds.upperBound; \
+ }
+# define CLAMP(cParam, val) CLAMP_TYPE(cParam, val, int)
+ CLAMP(ZSTD_c_windowLog, cParams.windowLog);
+ CLAMP(ZSTD_c_chainLog, cParams.chainLog);
+ CLAMP(ZSTD_c_hashLog, cParams.hashLog);
+ CLAMP(ZSTD_c_searchLog, cParams.searchLog);
+ CLAMP(ZSTD_c_minMatch, cParams.minMatch);
+ CLAMP(ZSTD_c_targetLength,cParams.targetLength);
+ CLAMP_TYPE(ZSTD_c_strategy,cParams.strategy, ZSTD_strategy);
return cParams;
}
@@ -624,17 +971,21 @@ static U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat)
}
/** ZSTD_adjustCParams_internal() :
- optimize `cPar` for a given input (`srcSize` and `dictSize`).
- mostly downsizing to reduce memory consumption and initialization latency.
- Both `srcSize` and `dictSize` are optional (use 0 if unknown).
- Note : cPar is considered validated at this stage. Use ZSTD_checkCParams() to ensure that condition. */
-ZSTD_compressionParameters ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize)
+ * optimize `cPar` for a specified input (`srcSize` and `dictSize`).
+ * mostly downsize to reduce memory consumption and initialization latency.
+ * `srcSize` can be ZSTD_CONTENTSIZE_UNKNOWN when not known.
+ * note : for the time being, `srcSize==0` means "unknown" too, for compatibility with older convention.
+ * condition : cPar is presumed validated (can be checked using ZSTD_checkCParams()). */
+static ZSTD_compressionParameters
+ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar,
+ unsigned long long srcSize,
+ size_t dictSize)
{
static const U64 minSrcSize = 513; /* (1<<9) + 1 */
static const U64 maxWindowResize = 1ULL << (ZSTD_WINDOWLOG_MAX-1);
assert(ZSTD_checkCParams(cPar)==0);
- if (dictSize && (srcSize+1<2) /* srcSize unknown */ )
+ if (dictSize && (srcSize+1<2) /* ZSTD_CONTENTSIZE_UNKNOWN and 0 mean "unknown" */ )
srcSize = minSrcSize; /* presumed small when there is a dictionary */
else if (srcSize == 0)
srcSize = ZSTD_CONTENTSIZE_UNKNOWN; /* 0 == unknown : presumed large */
@@ -648,35 +999,55 @@ ZSTD_compressionParameters ZSTD_adjustCParams_internal(ZSTD_compressionParameter
ZSTD_highbit32(tSize-1) + 1;
if (cPar.windowLog > srcLog) cPar.windowLog = srcLog;
}
- if (cPar.hashLog > cPar.windowLog) cPar.hashLog = cPar.windowLog;
+ if (cPar.hashLog > cPar.windowLog+1) cPar.hashLog = cPar.windowLog+1;
{ U32 const cycleLog = ZSTD_cycleLog(cPar.chainLog, cPar.strategy);
if (cycleLog > cPar.windowLog)
cPar.chainLog -= (cycleLog - cPar.windowLog);
}
if (cPar.windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN)
- cPar.windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN; /* required for frame header */
+ cPar.windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN; /* minimum wlog required for valid frame header */
return cPar;
}
-ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize)
+ZSTD_compressionParameters
+ZSTD_adjustCParams(ZSTD_compressionParameters cPar,
+ unsigned long long srcSize,
+ size_t dictSize)
{
- cPar = ZSTD_clampCParams(cPar);
+ cPar = ZSTD_clampCParams(cPar); /* resulting cPar is necessarily valid (all parameters within range) */
return ZSTD_adjustCParams_internal(cPar, srcSize, dictSize);
}
-static size_t ZSTD_sizeof_matchState(ZSTD_compressionParameters const* cParams, const U32 forCCtx)
+ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
+ const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize)
+{
+ ZSTD_compressionParameters cParams = ZSTD_getCParams(CCtxParams->compressionLevel, srcSizeHint, dictSize);
+ if (CCtxParams->ldmParams.enableLdm) cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG;
+ if (CCtxParams->cParams.windowLog) cParams.windowLog = CCtxParams->cParams.windowLog;
+ if (CCtxParams->cParams.hashLog) cParams.hashLog = CCtxParams->cParams.hashLog;
+ if (CCtxParams->cParams.chainLog) cParams.chainLog = CCtxParams->cParams.chainLog;
+ if (CCtxParams->cParams.searchLog) cParams.searchLog = CCtxParams->cParams.searchLog;
+ if (CCtxParams->cParams.minMatch) cParams.minMatch = CCtxParams->cParams.minMatch;
+ if (CCtxParams->cParams.targetLength) cParams.targetLength = CCtxParams->cParams.targetLength;
+ if (CCtxParams->cParams.strategy) cParams.strategy = CCtxParams->cParams.strategy;
+ assert(!ZSTD_checkCParams(cParams));
+ return ZSTD_adjustCParams_internal(cParams, srcSizeHint, dictSize);
+}
+
+static size_t
+ZSTD_sizeof_matchState(const ZSTD_compressionParameters* const cParams,
+ const U32 forCCtx)
{
size_t const chainSize = (cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cParams->chainLog);
size_t const hSize = ((size_t)1) << cParams->hashLog;
- U32 const hashLog3 = (forCCtx && cParams->searchLength==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0;
+ U32 const hashLog3 = (forCCtx && cParams->minMatch==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0;
size_t const h3Size = ((size_t)1) << hashLog3;
size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
size_t const optPotentialSpace = ((MaxML+1) + (MaxLL+1) + (MaxOff+1) + (1<<Litbits)) * sizeof(U32)
+ (ZSTD_OPT_NUM+1) * (sizeof(ZSTD_match_t)+sizeof(ZSTD_optimal_t));
- size_t const optSpace = (forCCtx && ((cParams->strategy == ZSTD_btopt) ||
- (cParams->strategy == ZSTD_btultra)))
+ size_t const optSpace = (forCCtx && (cParams->strategy >= ZSTD_btopt))
? optPotentialSpace
: 0;
DEBUGLOG(4, "chainSize: %u - hSize: %u - h3Size: %u",
@@ -686,14 +1057,13 @@ static size_t ZSTD_sizeof_matchState(ZSTD_compressionParameters const* cParams,
size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params)
{
- /* Estimate CCtx size is supported for single-threaded compression only. */
- if (params->nbWorkers > 0) { return ERROR(GENERIC); }
+ RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only.");
{ ZSTD_compressionParameters const cParams =
ZSTD_getCParamsFromCCtxParams(params, 0, 0);
size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog);
- U32 const divider = (cParams.searchLength==3) ? 3 : 4;
+ U32 const divider = (cParams.minMatch==3) ? 3 : 4;
size_t const maxNbSeq = blockSize / divider;
- size_t const tokenSpace = blockSize + 11*maxNbSeq;
+ size_t const tokenSpace = WILDCOPY_OVERLENGTH + blockSize + 11*maxNbSeq;
size_t const entropySpace = HUF_WORKSPACE_SIZE;
size_t const blockStateSpace = 2 * sizeof(ZSTD_compressedBlockState_t);
size_t const matchStateSize = ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 1);
@@ -726,7 +1096,7 @@ size_t ZSTD_estimateCCtxSize(int compressionLevel)
{
int level;
size_t memBudget = 0;
- for (level=1; level<=compressionLevel; level++) {
+ for (level=MIN(compressionLevel, 1); level<=compressionLevel; level++) {
size_t const newMB = ZSTD_estimateCCtxSize_internal(level);
if (newMB > memBudget) memBudget = newMB;
}
@@ -735,10 +1105,12 @@ size_t ZSTD_estimateCCtxSize(int compressionLevel)
size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params)
{
- if (params->nbWorkers > 0) { return ERROR(GENERIC); }
- { size_t const CCtxSize = ZSTD_estimateCCtxSize_usingCCtxParams(params);
- size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << params->cParams.windowLog);
- size_t const inBuffSize = ((size_t)1 << params->cParams.windowLog) + blockSize;
+ RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only.");
+ { ZSTD_compressionParameters const cParams =
+ ZSTD_getCParamsFromCCtxParams(params, 0, 0);
+ size_t const CCtxSize = ZSTD_estimateCCtxSize_usingCCtxParams(params);
+ size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog);
+ size_t const inBuffSize = ((size_t)1 << cParams.windowLog) + blockSize;
size_t const outBuffSize = ZSTD_compressBound(blockSize) + 1;
size_t const streamingSize = inBuffSize + outBuffSize;
@@ -752,15 +1124,17 @@ size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams)
return ZSTD_estimateCStreamSize_usingCCtxParams(&params);
}
-static size_t ZSTD_estimateCStreamSize_internal(int compressionLevel) {
+static size_t ZSTD_estimateCStreamSize_internal(int compressionLevel)
+{
ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, 0, 0);
return ZSTD_estimateCStreamSize_usingCParams(cParams);
}
-size_t ZSTD_estimateCStreamSize(int compressionLevel) {
+size_t ZSTD_estimateCStreamSize(int compressionLevel)
+{
int level;
size_t memBudget = 0;
- for (level=1; level<=compressionLevel; level++) {
+ for (level=MIN(compressionLevel, 1); level<=compressionLevel; level++) {
size_t const newMB = ZSTD_estimateCStreamSize_internal(level);
if (newMB > memBudget) memBudget = newMB;
}
@@ -786,9 +1160,27 @@ ZSTD_frameProgression ZSTD_getFrameProgression(const ZSTD_CCtx* cctx)
fp.ingested = cctx->consumedSrcSize + buffered;
fp.consumed = cctx->consumedSrcSize;
fp.produced = cctx->producedCSize;
+ fp.flushed = cctx->producedCSize; /* simplified; some data might still be left within streaming output buffer */
+ fp.currentJobID = 0;
+ fp.nbActiveWorkers = 0;
return fp;
} }
+/*! ZSTD_toFlushNow()
+ * Only useful for multithreading scenarios currently (nbWorkers >= 1).
+ */
+size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx)
+{
+#ifdef ZSTD_MULTITHREAD
+ if (cctx->appliedParams.nbWorkers > 0) {
+ return ZSTDMT_toFlushNow(cctx->mtctx);
+ }
+#endif
+ (void)cctx;
+ return 0; /* over-simplification; could also check if context is currently running in streaming mode, and in which case, report how many bytes are left to be flushed within output buffer */
+}
+
+
static U32 ZSTD_equivalentCParams(ZSTD_compressionParameters cParams1,
ZSTD_compressionParameters cParams2)
@@ -796,7 +1188,21 @@ static U32 ZSTD_equivalentCParams(ZSTD_compressionParameters cParams1,
return (cParams1.hashLog == cParams2.hashLog)
& (cParams1.chainLog == cParams2.chainLog)
& (cParams1.strategy == cParams2.strategy) /* opt parser space */
- & ((cParams1.searchLength==3) == (cParams2.searchLength==3)); /* hashlog3 space */
+ & ((cParams1.minMatch==3) == (cParams2.minMatch==3)); /* hashlog3 space */
+}
+
+static void ZSTD_assertEqualCParams(ZSTD_compressionParameters cParams1,
+ ZSTD_compressionParameters cParams2)
+{
+ (void)cParams1;
+ (void)cParams2;
+ assert(cParams1.windowLog == cParams2.windowLog);
+ assert(cParams1.chainLog == cParams2.chainLog);
+ assert(cParams1.hashLog == cParams2.hashLog);
+ assert(cParams1.searchLog == cParams2.searchLog);
+ assert(cParams1.minMatch == cParams2.minMatch);
+ assert(cParams1.targetLength == cParams2.targetLength);
+ assert(cParams1.strategy == cParams2.strategy);
}
/** The parameters are equivalent if ldm is not enabled in both sets or
@@ -809,7 +1215,7 @@ static U32 ZSTD_equivalentLdmParams(ldmParams_t ldmParams1,
ldmParams1.hashLog == ldmParams2.hashLog &&
ldmParams1.bucketSizeLog == ldmParams2.bucketSizeLog &&
ldmParams1.minMatchLength == ldmParams2.minMatchLength &&
- ldmParams1.hashEveryLog == ldmParams2.hashEveryLog);
+ ldmParams1.hashRateLog == ldmParams2.hashRateLog);
}
typedef enum { ZSTDb_not_buffered, ZSTDb_buffered } ZSTD_buffered_policy_e;
@@ -817,33 +1223,51 @@ typedef enum { ZSTDb_not_buffered, ZSTDb_buffered } ZSTD_buffered_policy_e;
/* ZSTD_sufficientBuff() :
* check internal buffers exist for streaming if buffPol == ZSTDb_buffered .
* Note : they are assumed to be correctly sized if ZSTD_equivalentCParams()==1 */
-static U32 ZSTD_sufficientBuff(size_t bufferSize1, size_t blockSize1,
+static U32 ZSTD_sufficientBuff(size_t bufferSize1, size_t maxNbSeq1,
+ size_t maxNbLit1,
ZSTD_buffered_policy_e buffPol2,
ZSTD_compressionParameters cParams2,
U64 pledgedSrcSize)
{
size_t const windowSize2 = MAX(1, (size_t)MIN(((U64)1 << cParams2.windowLog), pledgedSrcSize));
size_t const blockSize2 = MIN(ZSTD_BLOCKSIZE_MAX, windowSize2);
+ size_t const maxNbSeq2 = blockSize2 / ((cParams2.minMatch == 3) ? 3 : 4);
+ size_t const maxNbLit2 = blockSize2;
size_t const neededBufferSize2 = (buffPol2==ZSTDb_buffered) ? windowSize2 + blockSize2 : 0;
- DEBUGLOG(4, "ZSTD_sufficientBuff: is windowSize2=%u <= wlog1=%u",
- (U32)windowSize2, cParams2.windowLog);
- DEBUGLOG(4, "ZSTD_sufficientBuff: is blockSize2=%u <= blockSize1=%u",
- (U32)blockSize2, (U32)blockSize1);
- return (blockSize2 <= blockSize1) /* seqStore space depends on blockSize */
+ DEBUGLOG(4, "ZSTD_sufficientBuff: is neededBufferSize2=%u <= bufferSize1=%u",
+ (U32)neededBufferSize2, (U32)bufferSize1);
+ DEBUGLOG(4, "ZSTD_sufficientBuff: is maxNbSeq2=%u <= maxNbSeq1=%u",
+ (U32)maxNbSeq2, (U32)maxNbSeq1);
+ DEBUGLOG(4, "ZSTD_sufficientBuff: is maxNbLit2=%u <= maxNbLit1=%u",
+ (U32)maxNbLit2, (U32)maxNbLit1);
+ return (maxNbLit2 <= maxNbLit1)
+ & (maxNbSeq2 <= maxNbSeq1)
& (neededBufferSize2 <= bufferSize1);
}
/** Equivalence for resetCCtx purposes */
static U32 ZSTD_equivalentParams(ZSTD_CCtx_params params1,
ZSTD_CCtx_params params2,
- size_t buffSize1, size_t blockSize1,
+ size_t buffSize1,
+ size_t maxNbSeq1, size_t maxNbLit1,
ZSTD_buffered_policy_e buffPol2,
U64 pledgedSrcSize)
{
DEBUGLOG(4, "ZSTD_equivalentParams: pledgedSrcSize=%u", (U32)pledgedSrcSize);
- return ZSTD_equivalentCParams(params1.cParams, params2.cParams) &&
- ZSTD_equivalentLdmParams(params1.ldmParams, params2.ldmParams) &&
- ZSTD_sufficientBuff(buffSize1, blockSize1, buffPol2, params2.cParams, pledgedSrcSize);
+ if (!ZSTD_equivalentCParams(params1.cParams, params2.cParams)) {
+ DEBUGLOG(4, "ZSTD_equivalentCParams() == 0");
+ return 0;
+ }
+ if (!ZSTD_equivalentLdmParams(params1.ldmParams, params2.ldmParams)) {
+ DEBUGLOG(4, "ZSTD_equivalentLdmParams() == 0");
+ return 0;
+ }
+ if (!ZSTD_sufficientBuff(buffSize1, maxNbSeq1, maxNbLit1, buffPol2,
+ params2.cParams, pledgedSrcSize)) {
+ DEBUGLOG(4, "ZSTD_sufficientBuff() == 0");
+ return 0;
+ }
+ return 1;
}
static void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs)
@@ -851,10 +1275,10 @@ static void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs)
int i;
for (i = 0; i < ZSTD_REP_NUM; ++i)
bs->rep[i] = repStartValue[i];
- bs->entropy.hufCTable_repeatMode = HUF_repeat_none;
- bs->entropy.offcode_repeatMode = FSE_repeat_none;
- bs->entropy.matchlength_repeatMode = FSE_repeat_none;
- bs->entropy.litlength_repeatMode = FSE_repeat_none;
+ bs->entropy.huf.repeatMode = HUF_repeat_none;
+ bs->entropy.fse.offcode_repeatMode = FSE_repeat_none;
+ bs->entropy.fse.matchlength_repeatMode = FSE_repeat_none;
+ bs->entropy.fse.litlength_repeatMode = FSE_repeat_none;
}
/*! ZSTD_invalidateMatchState()
@@ -865,9 +1289,11 @@ static void ZSTD_invalidateMatchState(ZSTD_matchState_t* ms)
{
ZSTD_window_clear(&ms->window);
- ms->nextToUpdate = ms->window.dictLimit + 1;
+ ms->nextToUpdate = ms->window.dictLimit;
+ ms->nextToUpdate3 = ms->window.dictLimit;
ms->loadedDictEnd = 0;
ms->opt.litLengthSum = 0; /* force reset of btopt stats */
+ ms->dictMatchState = NULL;
}
/*! ZSTD_continueCCtx() :
@@ -880,6 +1306,7 @@ static size_t ZSTD_continueCCtx(ZSTD_CCtx* cctx, ZSTD_CCtx_params params, U64 pl
cctx->blockSize = blockSize; /* previous block size could be different even for same windowLog, due to pledgedSrcSize */
cctx->appliedParams = params;
+ cctx->blockState.matchState.cParams = params.cParams;
cctx->pledgedSrcSizePlusOne = pledgedSrcSize+1;
cctx->consumedSrcSize = 0;
cctx->producedCSize = 0;
@@ -900,11 +1327,15 @@ static size_t ZSTD_continueCCtx(ZSTD_CCtx* cctx, ZSTD_CCtx_params params, U64 pl
typedef enum { ZSTDcrp_continue, ZSTDcrp_noMemset } ZSTD_compResetPolicy_e;
-static void* ZSTD_reset_matchState(ZSTD_matchState_t* ms, void* ptr, ZSTD_compressionParameters const* cParams, ZSTD_compResetPolicy_e const crp, U32 const forCCtx)
+static void*
+ZSTD_reset_matchState(ZSTD_matchState_t* ms,
+ void* ptr,
+ const ZSTD_compressionParameters* cParams,
+ ZSTD_compResetPolicy_e const crp, U32 const forCCtx)
{
size_t const chainSize = (cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cParams->chainLog);
size_t const hSize = ((size_t)1) << cParams->hashLog;
- U32 const hashLog3 = (forCCtx && cParams->searchLength==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0;
+ U32 const hashLog3 = (forCCtx && cParams->minMatch==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0;
size_t const h3Size = ((size_t)1) << hashLog3;
size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
@@ -912,12 +1343,15 @@ static void* ZSTD_reset_matchState(ZSTD_matchState_t* ms, void* ptr, ZSTD_compre
ms->hashLog3 = hashLog3;
memset(&ms->window, 0, sizeof(ms->window));
+ ms->window.dictLimit = 1; /* start from 1, so that 1st position is valid */
+ ms->window.lowLimit = 1; /* it ensures first and later CCtx usages compress the same */
+ ms->window.nextSrc = ms->window.base + 1; /* see issue #1241 */
ZSTD_invalidateMatchState(ms);
/* opt parser space */
- if (forCCtx && ((cParams->strategy == ZSTD_btopt) | (cParams->strategy == ZSTD_btultra))) {
+ if (forCCtx && (cParams->strategy >= ZSTD_btopt)) {
DEBUGLOG(4, "reserving optimal parser space");
- ms->opt.litFreq = (U32*)ptr;
+ ms->opt.litFreq = (unsigned*)ptr;
ms->opt.litLengthFreq = ms->opt.litFreq + (1<<Litbits);
ms->opt.matchLengthFreq = ms->opt.litLengthFreq + (MaxLL+1);
ms->opt.offCodeFreq = ms->opt.matchLengthFreq + (MaxML+1);
@@ -937,14 +1371,24 @@ static void* ZSTD_reset_matchState(ZSTD_matchState_t* ms, void* ptr, ZSTD_compre
ms->hashTable3 = ms->chainTable + chainSize;
ptr = ms->hashTable3 + h3Size;
+ ms->cParams = *cParams;
+
assert(((size_t)ptr & 3) == 0);
return ptr;
}
+#define ZSTD_WORKSPACETOOLARGE_FACTOR 3 /* define "workspace is too large" as this number of times larger than needed */
+#define ZSTD_WORKSPACETOOLARGE_MAXDURATION 128 /* when workspace is continuously too large
+ * during at least this number of times,
+ * context's memory usage is considered wasteful,
+ * because it's sized to handle a worst case scenario which rarely happens.
+ * In which case, resize it down to free some memory */
+
/*! ZSTD_resetCCtx_internal() :
note : `params` are assumed fully validated at this stage */
static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
- ZSTD_CCtx_params params, U64 pledgedSrcSize,
+ ZSTD_CCtx_params params,
+ U64 pledgedSrcSize,
ZSTD_compResetPolicy_e const crp,
ZSTD_buffered_policy_e const zbuff)
{
@@ -954,34 +1398,35 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
if (crp == ZSTDcrp_continue) {
if (ZSTD_equivalentParams(zc->appliedParams, params,
- zc->inBuffSize, zc->blockSize,
- zbuff, pledgedSrcSize)) {
- DEBUGLOG(4, "ZSTD_equivalentParams()==1 -> continue mode (wLog1=%u, blockSize1=%u)",
- zc->appliedParams.cParams.windowLog, (U32)zc->blockSize);
- return ZSTD_continueCCtx(zc, params, pledgedSrcSize);
+ zc->inBuffSize,
+ zc->seqStore.maxNbSeq, zc->seqStore.maxNbLit,
+ zbuff, pledgedSrcSize)) {
+ DEBUGLOG(4, "ZSTD_equivalentParams()==1 -> continue mode (wLog1=%u, blockSize1=%zu)",
+ zc->appliedParams.cParams.windowLog, zc->blockSize);
+ zc->workSpaceOversizedDuration += (zc->workSpaceOversizedDuration > 0); /* if it was too large, it still is */
+ if (zc->workSpaceOversizedDuration <= ZSTD_WORKSPACETOOLARGE_MAXDURATION)
+ return ZSTD_continueCCtx(zc, params, pledgedSrcSize);
} }
DEBUGLOG(4, "ZSTD_equivalentParams()==0 -> reset CCtx");
if (params.ldmParams.enableLdm) {
/* Adjust long distance matching parameters */
- params.ldmParams.windowLog = params.cParams.windowLog;
ZSTD_ldm_adjustParameters(&params.ldmParams, &params.cParams);
assert(params.ldmParams.hashLog >= params.ldmParams.bucketSizeLog);
- assert(params.ldmParams.hashEveryLog < 32);
- zc->ldmState.hashPower =
- ZSTD_ldm_getHashPower(params.ldmParams.minMatchLength);
+ assert(params.ldmParams.hashRateLog < 32);
+ zc->ldmState.hashPower = ZSTD_rollingHash_primePower(params.ldmParams.minMatchLength);
}
{ size_t const windowSize = MAX(1, (size_t)MIN(((U64)1 << params.cParams.windowLog), pledgedSrcSize));
size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, windowSize);
- U32 const divider = (params.cParams.searchLength==3) ? 3 : 4;
+ U32 const divider = (params.cParams.minMatch==3) ? 3 : 4;
size_t const maxNbSeq = blockSize / divider;
- size_t const tokenSpace = blockSize + 11*maxNbSeq;
+ size_t const tokenSpace = WILDCOPY_OVERLENGTH + blockSize + 11*maxNbSeq;
size_t const buffOutSize = (zbuff==ZSTDb_buffered) ? ZSTD_compressBound(blockSize)+1 : 0;
size_t const buffInSize = (zbuff==ZSTDb_buffered) ? windowSize + blockSize : 0;
size_t const matchStateSize = ZSTD_sizeof_matchState(&params.cParams, /* forCCtx */ 1);
size_t const maxNbLdmSeq = ZSTD_ldm_getMaxNbSeq(params.ldmParams, blockSize);
- void* ptr;
+ void* ptr; /* used to partition workSpace */
/* Check if workSpace is large enough, alloc a new one if needed */
{ size_t const entropySpace = HUF_WORKSPACE_SIZE;
@@ -993,25 +1438,33 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
size_t const neededSpace = entropySpace + blockStateSpace + ldmSpace +
ldmSeqSpace + matchStateSize + tokenSpace +
bufferSpace;
- DEBUGLOG(4, "Need %uKB workspace, including %uKB for match state, and %uKB for buffers",
- (U32)(neededSpace>>10), (U32)(matchStateSize>>10), (U32)(bufferSpace>>10));
- DEBUGLOG(4, "windowSize: %u - blockSize: %u", (U32)windowSize, (U32)blockSize);
- if (zc->workSpaceSize < neededSpace) { /* too small : resize */
- DEBUGLOG(4, "Need to update workSpaceSize from %uK to %uK",
- (unsigned)(zc->workSpaceSize>>10),
- (unsigned)(neededSpace>>10));
- /* static cctx : no resize, error out */
- if (zc->staticSize) return ERROR(memory_allocation);
+ int const workSpaceTooSmall = zc->workSpaceSize < neededSpace;
+ int const workSpaceTooLarge = zc->workSpaceSize > ZSTD_WORKSPACETOOLARGE_FACTOR * neededSpace;
+ int const workSpaceWasteful = workSpaceTooLarge && (zc->workSpaceOversizedDuration > ZSTD_WORKSPACETOOLARGE_MAXDURATION);
+ zc->workSpaceOversizedDuration = workSpaceTooLarge ? zc->workSpaceOversizedDuration+1 : 0;
+
+ DEBUGLOG(4, "Need %zuKB workspace, including %zuKB for match state, and %zuKB for buffers",
+ neededSpace>>10, matchStateSize>>10, bufferSpace>>10);
+ DEBUGLOG(4, "windowSize: %zu - blockSize: %zu", windowSize, blockSize);
+
+ if (workSpaceTooSmall || workSpaceWasteful) {
+ DEBUGLOG(4, "Need to resize workSpaceSize from %zuKB to %zuKB",
+ zc->workSpaceSize >> 10,
+ neededSpace >> 10);
+
+ RETURN_ERROR_IF(zc->staticSize, memory_allocation, "static cctx : no resize");
zc->workSpaceSize = 0;
ZSTD_free(zc->workSpace, zc->customMem);
zc->workSpace = ZSTD_malloc(neededSpace, zc->customMem);
- if (zc->workSpace == NULL) return ERROR(memory_allocation);
+ RETURN_ERROR_IF(zc->workSpace == NULL, memory_allocation);
zc->workSpaceSize = neededSpace;
- ptr = zc->workSpace;
+ zc->workSpaceOversizedDuration = 0;
- /* Statically sized space. entropyWorkspace never moves (but prev/next block swap places) */
+ /* Statically sized space.
+ * entropyWorkspace never moves,
+ * though prev/next block swap places */
assert(((size_t)zc->workSpace & 3) == 0); /* ensure correct alignment */
assert(zc->workSpaceSize >= 2 * sizeof(ZSTD_compressedBlockState_t));
zc->blockState.prevCBlock = (ZSTD_compressedBlockState_t*)zc->workSpace;
@@ -1022,13 +1475,14 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
/* init params */
zc->appliedParams = params;
+ zc->blockState.matchState.cParams = params.cParams;
zc->pledgedSrcSizePlusOne = pledgedSrcSize+1;
zc->consumedSrcSize = 0;
zc->producedCSize = 0;
if (pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN)
zc->appliedParams.fParams.contentSizeFlag = 0;
DEBUGLOG(4, "pledged content size : %u ; flag : %u",
- (U32)pledgedSrcSize, zc->appliedParams.fParams.contentSizeFlag);
+ (unsigned)pledgedSrcSize, zc->appliedParams.fParams.contentSizeFlag);
zc->blockSize = blockSize;
XXH64_reset(&zc->xxhState, 0);
@@ -1058,13 +1512,18 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
ptr = ZSTD_reset_matchState(&zc->blockState.matchState, ptr, &params.cParams, crp, /* forCCtx */ 1);
/* sequences storage */
+ zc->seqStore.maxNbSeq = maxNbSeq;
zc->seqStore.sequencesStart = (seqDef*)ptr;
ptr = zc->seqStore.sequencesStart + maxNbSeq;
zc->seqStore.llCode = (BYTE*) ptr;
zc->seqStore.mlCode = zc->seqStore.llCode + maxNbSeq;
zc->seqStore.ofCode = zc->seqStore.mlCode + maxNbSeq;
zc->seqStore.litStart = zc->seqStore.ofCode + maxNbSeq;
- ptr = zc->seqStore.litStart + blockSize;
+ /* ZSTD_wildcopy() is used to copy into the literals buffer,
+ * so we have to oversize the buffer by WILDCOPY_OVERLENGTH bytes.
+ */
+ zc->seqStore.maxNbLit = blockSize;
+ ptr = zc->seqStore.litStart + blockSize + WILDCOPY_OVERLENGTH;
/* ldm bucketOffsets table */
if (params.ldmParams.enableLdm) {
@@ -1098,28 +1557,111 @@ void ZSTD_invalidateRepCodes(ZSTD_CCtx* cctx) {
assert(!ZSTD_window_hasExtDict(cctx->blockState.matchState.window));
}
-static size_t ZSTD_resetCCtx_usingCDict(ZSTD_CCtx* cctx,
+/* These are the approximate sizes for each strategy past which copying the
+ * dictionary tables into the working context is faster than using them
+ * in-place.
+ */
+static const size_t attachDictSizeCutoffs[ZSTD_STRATEGY_MAX+1] = {
+ 8 KB, /* unused */
+ 8 KB, /* ZSTD_fast */
+ 16 KB, /* ZSTD_dfast */
+ 32 KB, /* ZSTD_greedy */
+ 32 KB, /* ZSTD_lazy */
+ 32 KB, /* ZSTD_lazy2 */
+ 32 KB, /* ZSTD_btlazy2 */
+ 32 KB, /* ZSTD_btopt */
+ 8 KB, /* ZSTD_btultra */
+ 8 KB /* ZSTD_btultra2 */
+};
+
+static int ZSTD_shouldAttachDict(const ZSTD_CDict* cdict,
+ ZSTD_CCtx_params params,
+ U64 pledgedSrcSize)
+{
+ size_t cutoff = attachDictSizeCutoffs[cdict->matchState.cParams.strategy];
+ return ( pledgedSrcSize <= cutoff
+ || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN
+ || params.attachDictPref == ZSTD_dictForceAttach )
+ && params.attachDictPref != ZSTD_dictForceCopy
+ && !params.forceWindow; /* dictMatchState isn't correctly
+ * handled in _enforceMaxDist */
+}
+
+static size_t ZSTD_resetCCtx_byAttachingCDict(
+ ZSTD_CCtx* cctx,
+ const ZSTD_CDict* cdict,
+ ZSTD_CCtx_params params,
+ U64 pledgedSrcSize,
+ ZSTD_buffered_policy_e zbuff)
+{
+ {
+ const ZSTD_compressionParameters *cdict_cParams = &cdict->matchState.cParams;
+ unsigned const windowLog = params.cParams.windowLog;
+ assert(windowLog != 0);
+ /* Resize working context table params for input only, since the dict
+ * has its own tables. */
+ params.cParams = ZSTD_adjustCParams_internal(*cdict_cParams, pledgedSrcSize, 0);
+ params.cParams.windowLog = windowLog;
+ ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
+ ZSTDcrp_continue, zbuff);
+ assert(cctx->appliedParams.cParams.strategy == cdict_cParams->strategy);
+ }
+
+ {
+ const U32 cdictEnd = (U32)( cdict->matchState.window.nextSrc
+ - cdict->matchState.window.base);
+ const U32 cdictLen = cdictEnd - cdict->matchState.window.dictLimit;
+ if (cdictLen == 0) {
+ /* don't even attach dictionaries with no contents */
+ DEBUGLOG(4, "skipping attaching empty dictionary");
+ } else {
+ DEBUGLOG(4, "attaching dictionary into context");
+ cctx->blockState.matchState.dictMatchState = &cdict->matchState;
+
+ /* prep working match state so dict matches never have negative indices
+ * when they are translated to the working context's index space. */
+ if (cctx->blockState.matchState.window.dictLimit < cdictEnd) {
+ cctx->blockState.matchState.window.nextSrc =
+ cctx->blockState.matchState.window.base + cdictEnd;
+ ZSTD_window_clear(&cctx->blockState.matchState.window);
+ }
+ cctx->blockState.matchState.loadedDictEnd = cctx->blockState.matchState.window.dictLimit;
+ }
+ }
+
+ cctx->dictID = cdict->dictID;
+
+ /* copy block state */
+ memcpy(cctx->blockState.prevCBlock, &cdict->cBlockState, sizeof(cdict->cBlockState));
+
+ return 0;
+}
+
+static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx,
const ZSTD_CDict* cdict,
- unsigned windowLog,
- ZSTD_frameParameters fParams,
+ ZSTD_CCtx_params params,
U64 pledgedSrcSize,
ZSTD_buffered_policy_e zbuff)
{
- { ZSTD_CCtx_params params = cctx->requestedParams;
+ const ZSTD_compressionParameters *cdict_cParams = &cdict->matchState.cParams;
+
+ DEBUGLOG(4, "copying dictionary into context");
+
+ { unsigned const windowLog = params.cParams.windowLog;
+ assert(windowLog != 0);
/* Copy only compression parameters related to tables. */
- params.cParams = cdict->cParams;
- if (windowLog) params.cParams.windowLog = windowLog;
- params.fParams = fParams;
+ params.cParams = *cdict_cParams;
+ params.cParams.windowLog = windowLog;
ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
ZSTDcrp_noMemset, zbuff);
- assert(cctx->appliedParams.cParams.strategy == cdict->cParams.strategy);
- assert(cctx->appliedParams.cParams.hashLog == cdict->cParams.hashLog);
- assert(cctx->appliedParams.cParams.chainLog == cdict->cParams.chainLog);
+ assert(cctx->appliedParams.cParams.strategy == cdict_cParams->strategy);
+ assert(cctx->appliedParams.cParams.hashLog == cdict_cParams->hashLog);
+ assert(cctx->appliedParams.cParams.chainLog == cdict_cParams->chainLog);
}
/* copy tables */
- { size_t const chainSize = (cdict->cParams.strategy == ZSTD_fast) ? 0 : ((size_t)1 << cdict->cParams.chainLog);
- size_t const hSize = (size_t)1 << cdict->cParams.hashLog;
+ { size_t const chainSize = (cdict_cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cdict_cParams->chainLog);
+ size_t const hSize = (size_t)1 << cdict_cParams->hashLog;
size_t const tableSpace = (chainSize + hSize) * sizeof(U32);
assert((U32*)cctx->blockState.matchState.chainTable == (U32*)cctx->blockState.matchState.hashTable + hSize); /* chainTable must follow hashTable */
assert((U32*)cctx->blockState.matchState.hashTable3 == (U32*)cctx->blockState.matchState.chainTable + chainSize);
@@ -1127,6 +1669,7 @@ static size_t ZSTD_resetCCtx_usingCDict(ZSTD_CCtx* cctx,
assert((U32*)cdict->matchState.hashTable3 == (U32*)cdict->matchState.chainTable + chainSize);
memcpy(cctx->blockState.matchState.hashTable, cdict->matchState.hashTable, tableSpace); /* presumes all tables follow each other */
}
+
/* Zero the hashTable3, since the cdict never fills it */
{ size_t const h3Size = (size_t)1 << cctx->blockState.matchState.hashLog3;
assert(cdict->matchState.hashLog3 == 0);
@@ -1134,14 +1677,14 @@ static size_t ZSTD_resetCCtx_usingCDict(ZSTD_CCtx* cctx,
}
/* copy dictionary offsets */
- {
- ZSTD_matchState_t const* srcMatchState = &cdict->matchState;
+ { ZSTD_matchState_t const* srcMatchState = &cdict->matchState;
ZSTD_matchState_t* dstMatchState = &cctx->blockState.matchState;
dstMatchState->window = srcMatchState->window;
dstMatchState->nextToUpdate = srcMatchState->nextToUpdate;
dstMatchState->nextToUpdate3= srcMatchState->nextToUpdate3;
dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd;
}
+
cctx->dictID = cdict->dictID;
/* copy block state */
@@ -1150,6 +1693,28 @@ static size_t ZSTD_resetCCtx_usingCDict(ZSTD_CCtx* cctx,
return 0;
}
+/* We have a choice between copying the dictionary context into the working
+ * context, or referencing the dictionary context from the working context
+ * in-place. We decide here which strategy to use. */
+static size_t ZSTD_resetCCtx_usingCDict(ZSTD_CCtx* cctx,
+ const ZSTD_CDict* cdict,
+ ZSTD_CCtx_params params,
+ U64 pledgedSrcSize,
+ ZSTD_buffered_policy_e zbuff)
+{
+
+ DEBUGLOG(4, "ZSTD_resetCCtx_usingCDict (pledgedSrcSize=%u)",
+ (unsigned)pledgedSrcSize);
+
+ if (ZSTD_shouldAttachDict(cdict, params, pledgedSrcSize)) {
+ return ZSTD_resetCCtx_byAttachingCDict(
+ cctx, cdict, params, pledgedSrcSize, zbuff);
+ } else {
+ return ZSTD_resetCCtx_byCopyingCDict(
+ cctx, cdict, params, pledgedSrcSize, zbuff);
+ }
+}
+
/*! ZSTD_copyCCtx_internal() :
* Duplicate an existing context `srcCCtx` into another one `dstCCtx`.
* Only works during stage ZSTDcs_init (i.e. after creation, but before first call to ZSTD_compressContinue()).
@@ -1164,7 +1729,7 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
ZSTD_buffered_policy_e zbuff)
{
DEBUGLOG(5, "ZSTD_copyCCtx_internal");
- if (srcCCtx->stage!=ZSTDcs_init) return ERROR(stage_wrong);
+ RETURN_ERROR_IF(srcCCtx->stage!=ZSTDcs_init, stage_wrong);
memcpy(&dstCCtx->customMem, &srcCCtx->customMem, sizeof(ZSTD_customMem));
{ ZSTD_CCtx_params params = dstCCtx->requestedParams;
@@ -1192,7 +1757,7 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
/* copy dictionary offsets */
{
- ZSTD_matchState_t const* srcMatchState = &srcCCtx->blockState.matchState;
+ const ZSTD_matchState_t* srcMatchState = &srcCCtx->blockState.matchState;
ZSTD_matchState_t* dstMatchState = &dstCCtx->blockState.matchState;
dstMatchState->window = srcMatchState->window;
dstMatchState->nextToUpdate = srcMatchState->nextToUpdate;
@@ -1294,21 +1859,22 @@ static void ZSTD_reduceIndex (ZSTD_CCtx* zc, const U32 reducerValue)
/* See doc/zstd_compression_format.md for detailed format description */
-size_t ZSTD_noCompressBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize)
+static size_t ZSTD_noCompressBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize, U32 lastBlock)
{
- if (srcSize + ZSTD_blockHeaderSize > dstCapacity) return ERROR(dstSize_tooSmall);
+ U32 const cBlockHeader24 = lastBlock + (((U32)bt_raw)<<1) + (U32)(srcSize << 3);
+ RETURN_ERROR_IF(srcSize + ZSTD_blockHeaderSize > dstCapacity,
+ dstSize_tooSmall);
+ MEM_writeLE24(dst, cBlockHeader24);
memcpy((BYTE*)dst + ZSTD_blockHeaderSize, src, srcSize);
- MEM_writeLE24(dst, (U32)(srcSize << 2) + (U32)bt_raw);
- return ZSTD_blockHeaderSize+srcSize;
+ return ZSTD_blockHeaderSize + srcSize;
}
-
static size_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void* src, size_t srcSize)
{
BYTE* const ostart = (BYTE* const)dst;
U32 const flSize = 1 + (srcSize>31) + (srcSize>4095);
- if (srcSize + flSize > dstCapacity) return ERROR(dstSize_tooSmall);
+ RETURN_ERROR_IF(srcSize + flSize > dstCapacity, dstSize_tooSmall);
switch(flSize)
{
@@ -1356,16 +1922,27 @@ static size_t ZSTD_compressRleLiteralsBlock (void* dst, size_t dstCapacity, cons
}
-static size_t ZSTD_minGain(size_t srcSize) { return (srcSize >> 6) + 2; }
+/* ZSTD_minGain() :
+ * minimum compression required
+ * to generate a compress block or a compressed literals section.
+ * note : use same formula for both situations */
+static size_t ZSTD_minGain(size_t srcSize, ZSTD_strategy strat)
+{
+ U32 const minlog = (strat>=ZSTD_btultra) ? (U32)(strat) - 1 : 6;
+ ZSTD_STATIC_ASSERT(ZSTD_btultra == 8);
+ assert(ZSTD_cParam_withinBounds(ZSTD_c_strategy, strat));
+ return (srcSize >> minlog) + 2;
+}
-static size_t ZSTD_compressLiterals (ZSTD_entropyCTables_t const* prevEntropy,
- ZSTD_entropyCTables_t* nextEntropy,
+static size_t ZSTD_compressLiterals (ZSTD_hufCTables_t const* prevHuf,
+ ZSTD_hufCTables_t* nextHuf,
ZSTD_strategy strategy, int disableLiteralCompression,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
- U32* workspace, const int bmi2)
+ void* workspace, size_t wkspSize,
+ const int bmi2)
{
- size_t const minGain = ZSTD_minGain(srcSize);
+ size_t const minGain = ZSTD_minGain(srcSize, strategy);
size_t const lhSize = 3 + (srcSize >= 1 KB) + (srcSize >= 16 KB);
BYTE* const ostart = (BYTE*)dst;
U32 singleStream = srcSize < 256;
@@ -1376,27 +1953,25 @@ static size_t ZSTD_compressLiterals (ZSTD_entropyCTables_t const* prevEntropy,
disableLiteralCompression);
/* Prepare nextEntropy assuming reusing the existing table */
- nextEntropy->hufCTable_repeatMode = prevEntropy->hufCTable_repeatMode;
- memcpy(nextEntropy->hufCTable, prevEntropy->hufCTable,
- sizeof(prevEntropy->hufCTable));
+ memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
if (disableLiteralCompression)
return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
/* small ? don't even attempt compression (speed opt) */
# define COMPRESS_LITERALS_SIZE_MIN 63
- { size_t const minLitSize = (prevEntropy->hufCTable_repeatMode == HUF_repeat_valid) ? 6 : COMPRESS_LITERALS_SIZE_MIN;
+ { size_t const minLitSize = (prevHuf->repeatMode == HUF_repeat_valid) ? 6 : COMPRESS_LITERALS_SIZE_MIN;
if (srcSize <= minLitSize) return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
}
- if (dstCapacity < lhSize+1) return ERROR(dstSize_tooSmall); /* not enough space for compression */
- { HUF_repeat repeat = prevEntropy->hufCTable_repeatMode;
+ RETURN_ERROR_IF(dstCapacity < lhSize+1, dstSize_tooSmall, "not enough space for compression");
+ { HUF_repeat repeat = prevHuf->repeatMode;
int const preferRepeat = strategy < ZSTD_lazy ? srcSize <= 1024 : 0;
if (repeat == HUF_repeat_valid && lhSize == 3) singleStream = 1;
cLitSize = singleStream ? HUF_compress1X_repeat(ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 11,
- workspace, HUF_WORKSPACE_SIZE, (HUF_CElt*)nextEntropy->hufCTable, &repeat, preferRepeat, bmi2)
+ workspace, wkspSize, (HUF_CElt*)nextHuf->CTable, &repeat, preferRepeat, bmi2)
: HUF_compress4X_repeat(ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 11,
- workspace, HUF_WORKSPACE_SIZE, (HUF_CElt*)nextEntropy->hufCTable, &repeat, preferRepeat, bmi2);
+ workspace, wkspSize, (HUF_CElt*)nextHuf->CTable, &repeat, preferRepeat, bmi2);
if (repeat != HUF_repeat_none) {
/* reused the existing table */
hType = set_repeat;
@@ -1404,17 +1979,17 @@ static size_t ZSTD_compressLiterals (ZSTD_entropyCTables_t const* prevEntropy,
}
if ((cLitSize==0) | (cLitSize >= srcSize - minGain) | ERR_isError(cLitSize)) {
- memcpy(nextEntropy->hufCTable, prevEntropy->hufCTable, sizeof(prevEntropy->hufCTable));
+ memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
}
if (cLitSize==1) {
- memcpy(nextEntropy->hufCTable, prevEntropy->hufCTable, sizeof(prevEntropy->hufCTable));
+ memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
return ZSTD_compressRleLiteralsBlock(dst, dstCapacity, src, srcSize);
}
if (hType == set_compressed) {
/* using a newly constructed table */
- nextEntropy->hufCTable_repeatMode = HUF_repeat_check;
+ nextHuf->repeatMode = HUF_repeat_check;
}
/* Build header */
@@ -1451,6 +2026,7 @@ void ZSTD_seqToCodes(const seqStore_t* seqStorePtr)
BYTE* const mlCodeTable = seqStorePtr->mlCode;
U32 const nbSeq = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
U32 u;
+ assert(nbSeq <= seqStorePtr->maxNbSeq);
for (u=0; u<nbSeq; u++) {
U32 const llv = sequences[u].litLength;
U32 const mlv = sequences[u].matchLength;
@@ -1464,72 +2040,243 @@ void ZSTD_seqToCodes(const seqStore_t* seqStorePtr)
mlCodeTable[seqStorePtr->longLengthPos] = MaxML;
}
+
+/**
+ * -log2(x / 256) lookup table for x in [0, 256).
+ * If x == 0: Return 0
+ * Else: Return floor(-log2(x / 256) * 256)
+ */
+static unsigned const kInverseProbabilityLog256[256] = {
+ 0, 2048, 1792, 1642, 1536, 1453, 1386, 1329, 1280, 1236, 1197, 1162,
+ 1130, 1100, 1073, 1047, 1024, 1001, 980, 960, 941, 923, 906, 889,
+ 874, 859, 844, 830, 817, 804, 791, 779, 768, 756, 745, 734,
+ 724, 714, 704, 694, 685, 676, 667, 658, 650, 642, 633, 626,
+ 618, 610, 603, 595, 588, 581, 574, 567, 561, 554, 548, 542,
+ 535, 529, 523, 517, 512, 506, 500, 495, 489, 484, 478, 473,
+ 468, 463, 458, 453, 448, 443, 438, 434, 429, 424, 420, 415,
+ 411, 407, 402, 398, 394, 390, 386, 382, 377, 373, 370, 366,
+ 362, 358, 354, 350, 347, 343, 339, 336, 332, 329, 325, 322,
+ 318, 315, 311, 308, 305, 302, 298, 295, 292, 289, 286, 282,
+ 279, 276, 273, 270, 267, 264, 261, 258, 256, 253, 250, 247,
+ 244, 241, 239, 236, 233, 230, 228, 225, 222, 220, 217, 215,
+ 212, 209, 207, 204, 202, 199, 197, 194, 192, 190, 187, 185,
+ 182, 180, 178, 175, 173, 171, 168, 166, 164, 162, 159, 157,
+ 155, 153, 151, 149, 146, 144, 142, 140, 138, 136, 134, 132,
+ 130, 128, 126, 123, 121, 119, 117, 115, 114, 112, 110, 108,
+ 106, 104, 102, 100, 98, 96, 94, 93, 91, 89, 87, 85,
+ 83, 82, 80, 78, 76, 74, 73, 71, 69, 67, 66, 64,
+ 62, 61, 59, 57, 55, 54, 52, 50, 49, 47, 46, 44,
+ 42, 41, 39, 37, 36, 34, 33, 31, 30, 28, 26, 25,
+ 23, 22, 20, 19, 17, 16, 14, 13, 11, 10, 8, 7,
+ 5, 4, 2, 1,
+};
+
+
+/**
+ * Returns the cost in bits of encoding the distribution described by count
+ * using the entropy bound.
+ */
+static size_t ZSTD_entropyCost(unsigned const* count, unsigned const max, size_t const total)
+{
+ unsigned cost = 0;
+ unsigned s;
+ for (s = 0; s <= max; ++s) {
+ unsigned norm = (unsigned)((256 * count[s]) / total);
+ if (count[s] != 0 && norm == 0)
+ norm = 1;
+ assert(count[s] < total);
+ cost += count[s] * kInverseProbabilityLog256[norm];
+ }
+ return cost >> 8;
+}
+
+
+/**
+ * Returns the cost in bits of encoding the distribution in count using the
+ * table described by norm. The max symbol support by norm is assumed >= max.
+ * norm must be valid for every symbol with non-zero probability in count.
+ */
+static size_t ZSTD_crossEntropyCost(short const* norm, unsigned accuracyLog,
+ unsigned const* count, unsigned const max)
+{
+ unsigned const shift = 8 - accuracyLog;
+ size_t cost = 0;
+ unsigned s;
+ assert(accuracyLog <= 8);
+ for (s = 0; s <= max; ++s) {
+ unsigned const normAcc = norm[s] != -1 ? norm[s] : 1;
+ unsigned const norm256 = normAcc << shift;
+ assert(norm256 > 0);
+ assert(norm256 < 256);
+ cost += count[s] * kInverseProbabilityLog256[norm256];
+ }
+ return cost >> 8;
+}
+
+
+static unsigned ZSTD_getFSEMaxSymbolValue(FSE_CTable const* ctable) {
+ void const* ptr = ctable;
+ U16 const* u16ptr = (U16 const*)ptr;
+ U32 const maxSymbolValue = MEM_read16(u16ptr + 1);
+ return maxSymbolValue;
+}
+
+
+/**
+ * Returns the cost in bits of encoding the distribution in count using ctable.
+ * Returns an error if ctable cannot represent all the symbols in count.
+ */
+static size_t ZSTD_fseBitCost(
+ FSE_CTable const* ctable,
+ unsigned const* count,
+ unsigned const max)
+{
+ unsigned const kAccuracyLog = 8;
+ size_t cost = 0;
+ unsigned s;
+ FSE_CState_t cstate;
+ FSE_initCState(&cstate, ctable);
+ RETURN_ERROR_IF(ZSTD_getFSEMaxSymbolValue(ctable) < max, GENERIC,
+ "Repeat FSE_CTable has maxSymbolValue %u < %u",
+ ZSTD_getFSEMaxSymbolValue(ctable), max);
+ for (s = 0; s <= max; ++s) {
+ unsigned const tableLog = cstate.stateLog;
+ unsigned const badCost = (tableLog + 1) << kAccuracyLog;
+ unsigned const bitCost = FSE_bitCost(cstate.symbolTT, tableLog, s, kAccuracyLog);
+ if (count[s] == 0)
+ continue;
+ RETURN_ERROR_IF(bitCost >= badCost, GENERIC,
+ "Repeat FSE_CTable has Prob[%u] == 0", s);
+ cost += count[s] * bitCost;
+ }
+ return cost >> kAccuracyLog;
+}
+
+/**
+ * Returns the cost in bytes of encoding the normalized count header.
+ * Returns an error if any of the helper functions return an error.
+ */
+static size_t ZSTD_NCountCost(unsigned const* count, unsigned const max,
+ size_t const nbSeq, unsigned const FSELog)
+{
+ BYTE wksp[FSE_NCOUNTBOUND];
+ S16 norm[MaxSeq + 1];
+ const U32 tableLog = FSE_optimalTableLog(FSELog, nbSeq, max);
+ FORWARD_IF_ERROR(FSE_normalizeCount(norm, tableLog, count, nbSeq, max));
+ return FSE_writeNCount(wksp, sizeof(wksp), norm, max, tableLog);
+}
+
+
typedef enum {
ZSTD_defaultDisallowed = 0,
ZSTD_defaultAllowed = 1
} ZSTD_defaultPolicy_e;
-MEM_STATIC
-symbolEncodingType_e ZSTD_selectEncodingType(
- FSE_repeat* repeatMode, size_t const mostFrequent, size_t nbSeq,
- U32 defaultNormLog, ZSTD_defaultPolicy_e const isDefaultAllowed)
+MEM_STATIC symbolEncodingType_e
+ZSTD_selectEncodingType(
+ FSE_repeat* repeatMode, unsigned const* count, unsigned const max,
+ size_t const mostFrequent, size_t nbSeq, unsigned const FSELog,
+ FSE_CTable const* prevCTable,
+ short const* defaultNorm, U32 defaultNormLog,
+ ZSTD_defaultPolicy_e const isDefaultAllowed,
+ ZSTD_strategy const strategy)
{
-#define MIN_SEQ_FOR_DYNAMIC_FSE 64
-#define MAX_SEQ_FOR_STATIC_FSE 1000
ZSTD_STATIC_ASSERT(ZSTD_defaultDisallowed == 0 && ZSTD_defaultAllowed != 0);
- if ((mostFrequent == nbSeq) && (!isDefaultAllowed || nbSeq > 2)) {
+ if (mostFrequent == nbSeq) {
+ *repeatMode = FSE_repeat_none;
+ if (isDefaultAllowed && nbSeq <= 2) {
+ /* Prefer set_basic over set_rle when there are 2 or less symbols,
+ * since RLE uses 1 byte, but set_basic uses 5-6 bits per symbol.
+ * If basic encoding isn't possible, always choose RLE.
+ */
+ DEBUGLOG(5, "Selected set_basic");
+ return set_basic;
+ }
DEBUGLOG(5, "Selected set_rle");
- /* Prefer set_basic over set_rle when there are 2 or less symbols,
- * since RLE uses 1 byte, but set_basic uses 5-6 bits per symbol.
- * If basic encoding isn't possible, always choose RLE.
- */
- *repeatMode = FSE_repeat_check;
return set_rle;
}
- if ( isDefaultAllowed
- && (*repeatMode == FSE_repeat_valid) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
- DEBUGLOG(5, "Selected set_repeat");
- return set_repeat;
- }
- if ( isDefaultAllowed
- && ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (defaultNormLog-1)))) ) {
- DEBUGLOG(5, "Selected set_basic");
- /* The format allows default tables to be repeated, but it isn't useful.
- * When using simple heuristics to select encoding type, we don't want
- * to confuse these tables with dictionaries. When running more careful
- * analysis, we don't need to waste time checking both repeating tables
- * and default tables.
- */
- *repeatMode = FSE_repeat_none;
- return set_basic;
+ if (strategy < ZSTD_lazy) {
+ if (isDefaultAllowed) {
+ size_t const staticFse_nbSeq_max = 1000;
+ size_t const mult = 10 - strategy;
+ size_t const baseLog = 3;
+ size_t const dynamicFse_nbSeq_min = (((size_t)1 << defaultNormLog) * mult) >> baseLog; /* 28-36 for offset, 56-72 for lengths */
+ assert(defaultNormLog >= 5 && defaultNormLog <= 6); /* xx_DEFAULTNORMLOG */
+ assert(mult <= 9 && mult >= 7);
+ if ( (*repeatMode == FSE_repeat_valid)
+ && (nbSeq < staticFse_nbSeq_max) ) {
+ DEBUGLOG(5, "Selected set_repeat");
+ return set_repeat;
+ }
+ if ( (nbSeq < dynamicFse_nbSeq_min)
+ || (mostFrequent < (nbSeq >> (defaultNormLog-1))) ) {
+ DEBUGLOG(5, "Selected set_basic");
+ /* The format allows default tables to be repeated, but it isn't useful.
+ * When using simple heuristics to select encoding type, we don't want
+ * to confuse these tables with dictionaries. When running more careful
+ * analysis, we don't need to waste time checking both repeating tables
+ * and default tables.
+ */
+ *repeatMode = FSE_repeat_none;
+ return set_basic;
+ }
+ }
+ } else {
+ size_t const basicCost = isDefaultAllowed ? ZSTD_crossEntropyCost(defaultNorm, defaultNormLog, count, max) : ERROR(GENERIC);
+ size_t const repeatCost = *repeatMode != FSE_repeat_none ? ZSTD_fseBitCost(prevCTable, count, max) : ERROR(GENERIC);
+ size_t const NCountCost = ZSTD_NCountCost(count, max, nbSeq, FSELog);
+ size_t const compressedCost = (NCountCost << 3) + ZSTD_entropyCost(count, max, nbSeq);
+
+ if (isDefaultAllowed) {
+ assert(!ZSTD_isError(basicCost));
+ assert(!(*repeatMode == FSE_repeat_valid && ZSTD_isError(repeatCost)));
+ }
+ assert(!ZSTD_isError(NCountCost));
+ assert(compressedCost < ERROR(maxCode));
+ DEBUGLOG(5, "Estimated bit costs: basic=%u\trepeat=%u\tcompressed=%u",
+ (unsigned)basicCost, (unsigned)repeatCost, (unsigned)compressedCost);
+ if (basicCost <= repeatCost && basicCost <= compressedCost) {
+ DEBUGLOG(5, "Selected set_basic");
+ assert(isDefaultAllowed);
+ *repeatMode = FSE_repeat_none;
+ return set_basic;
+ }
+ if (repeatCost <= compressedCost) {
+ DEBUGLOG(5, "Selected set_repeat");
+ assert(!ZSTD_isError(repeatCost));
+ return set_repeat;
+ }
+ assert(compressedCost < basicCost && compressedCost < repeatCost);
}
DEBUGLOG(5, "Selected set_compressed");
*repeatMode = FSE_repeat_check;
return set_compressed;
}
-MEM_STATIC
-size_t ZSTD_buildCTable(void* dst, size_t dstCapacity,
- FSE_CTable* nextCTable, U32 FSELog, symbolEncodingType_e type,
- U32* count, U32 max,
- BYTE const* codeTable, size_t nbSeq,
- S16 const* defaultNorm, U32 defaultNormLog, U32 defaultMax,
- FSE_CTable const* prevCTable, size_t prevCTableSize,
- void* workspace, size_t workspaceSize)
+MEM_STATIC size_t
+ZSTD_buildCTable(void* dst, size_t dstCapacity,
+ FSE_CTable* nextCTable, U32 FSELog, symbolEncodingType_e type,
+ unsigned* count, U32 max,
+ const BYTE* codeTable, size_t nbSeq,
+ const S16* defaultNorm, U32 defaultNormLog, U32 defaultMax,
+ const FSE_CTable* prevCTable, size_t prevCTableSize,
+ void* workspace, size_t workspaceSize)
{
BYTE* op = (BYTE*)dst;
- BYTE const* const oend = op + dstCapacity;
+ const BYTE* const oend = op + dstCapacity;
+ DEBUGLOG(6, "ZSTD_buildCTable (dstCapacity=%u)", (unsigned)dstCapacity);
switch (type) {
case set_rle:
+ FORWARD_IF_ERROR(FSE_buildCTable_rle(nextCTable, (BYTE)max));
+ RETURN_ERROR_IF(dstCapacity==0, dstSize_tooSmall);
*op = codeTable[0];
- CHECK_F(FSE_buildCTable_rle(nextCTable, (BYTE)max));
return 1;
case set_repeat:
memcpy(nextCTable, prevCTable, prevCTableSize);
return 0;
case set_basic:
- CHECK_F(FSE_buildCTable_wksp(nextCTable, defaultNorm, defaultMax, defaultNormLog, workspace, workspaceSize)); /* note : could be pre-calculated */
+ FORWARD_IF_ERROR(FSE_buildCTable_wksp(nextCTable, defaultNorm, defaultMax, defaultNormLog, workspace, workspaceSize)); /* note : could be pre-calculated */
return 0;
case set_compressed: {
S16 norm[MaxSeq + 1];
@@ -1540,14 +2287,14 @@ size_t ZSTD_buildCTable(void* dst, size_t dstCapacity,
nbSeq_1--;
}
assert(nbSeq_1 > 1);
- CHECK_F(FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max));
+ FORWARD_IF_ERROR(FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max));
{ size_t const NCountSize = FSE_writeNCount(op, oend - op, norm, max, tableLog); /* overflow protected */
- if (FSE_isError(NCountSize)) return NCountSize;
- CHECK_F(FSE_buildCTable_wksp(nextCTable, norm, max, tableLog, workspace, workspaceSize));
+ FORWARD_IF_ERROR(NCountSize);
+ FORWARD_IF_ERROR(FSE_buildCTable_wksp(nextCTable, norm, max, tableLog, workspace, workspaceSize));
return NCountSize;
}
}
- default: return assert(0), ERROR(GENERIC);
+ default: assert(0); RETURN_ERROR(GENERIC);
}
}
@@ -1564,7 +2311,12 @@ ZSTD_encodeSequences_body(
FSE_CState_t stateOffsetBits;
FSE_CState_t stateLitLength;
- CHECK_E(BIT_initCStream(&blockStream, dst, dstCapacity), dstSize_tooSmall); /* not enough space remaining */
+ RETURN_ERROR_IF(
+ ERR_isError(BIT_initCStream(&blockStream, dst, dstCapacity)),
+ dstSize_tooSmall, "not enough space remaining");
+ DEBUGLOG(6, "available space for bitstream : %i (dstCapacity=%u)",
+ (int)(blockStream.endPtr - blockStream.startPtr),
+ (unsigned)dstCapacity);
/* first symbols */
FSE_initCState2(&stateMatchLength, CTable_MatchLength, mlCodeTable[nbSeq-1]);
@@ -1597,9 +2349,9 @@ ZSTD_encodeSequences_body(
U32 const ofBits = ofCode;
U32 const mlBits = ML_bits[mlCode];
DEBUGLOG(6, "encoding: litlen:%2u - matchlen:%2u - offCode:%7u",
- sequences[n].litLength,
- sequences[n].matchLength + MINMATCH,
- sequences[n].offset);
+ (unsigned)sequences[n].litLength,
+ (unsigned)sequences[n].matchLength + MINMATCH,
+ (unsigned)sequences[n].offset);
/* 32b*/ /* 64b*/
/* (7)*/ /* (7)*/
FSE_encodeSymbol(&blockStream, &stateOffsetBits, ofCode); /* 15 */ /* 15 */
@@ -1624,6 +2376,7 @@ ZSTD_encodeSequences_body(
BIT_addBits(&blockStream, sequences[n].offset, ofBits); /* 31 */
}
BIT_flushBits(&blockStream); /* (7)*/
+ DEBUGLOG(7, "remaining space : %i", (int)(blockStream.endPtr - blockStream.ptr));
} }
DEBUGLOG(6, "ZSTD_encodeSequences: flushing ML state with %u bits", stateMatchLength.stateLog);
@@ -1634,7 +2387,7 @@ ZSTD_encodeSequences_body(
FSE_flushCState(&blockStream, &stateLitLength);
{ size_t const streamSize = BIT_closeCStream(&blockStream);
- if (streamSize==0) return ERROR(dstSize_tooSmall); /* not enough space */
+ RETURN_ERROR_IF(streamSize==0, dstSize_tooSmall, "not enough space");
return streamSize;
}
}
@@ -1674,13 +2427,14 @@ ZSTD_encodeSequences_bmi2(
#endif
-size_t ZSTD_encodeSequences(
+static size_t ZSTD_encodeSequences(
void* dst, size_t dstCapacity,
FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,
FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,
FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,
seqDef const* sequences, size_t nbSeq, int longOffsets, int bmi2)
{
+ DEBUGLOG(5, "ZSTD_encodeSequences: dstCapacity = %u", (unsigned)dstCapacity);
#if DYNAMIC_BMI2
if (bmi2) {
return ZSTD_encodeSequences_bmi2(dst, dstCapacity,
@@ -1698,18 +2452,38 @@ size_t ZSTD_encodeSequences(
sequences, nbSeq, longOffsets);
}
-MEM_STATIC size_t ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
- ZSTD_entropyCTables_t const* prevEntropy,
- ZSTD_entropyCTables_t* nextEntropy,
- ZSTD_CCtx_params const* cctxParams,
- void* dst, size_t dstCapacity, U32* workspace,
- const int bmi2)
+static int ZSTD_disableLiteralsCompression(const ZSTD_CCtx_params* cctxParams)
+{
+ switch (cctxParams->literalCompressionMode) {
+ case ZSTD_lcm_huffman:
+ return 0;
+ case ZSTD_lcm_uncompressed:
+ return 1;
+ default:
+ assert(0 /* impossible: pre-validated */);
+ /* fall-through */
+ case ZSTD_lcm_auto:
+ return (cctxParams->cParams.strategy == ZSTD_fast) && (cctxParams->cParams.targetLength > 0);
+ }
+}
+
+/* ZSTD_compressSequences_internal():
+ * actually compresses both literals and sequences */
+MEM_STATIC size_t
+ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
+ const ZSTD_entropyCTables_t* prevEntropy,
+ ZSTD_entropyCTables_t* nextEntropy,
+ const ZSTD_CCtx_params* cctxParams,
+ void* dst, size_t dstCapacity,
+ void* workspace, size_t wkspSize,
+ const int bmi2)
{
const int longOffsets = cctxParams->cParams.windowLog > STREAM_ACCUMULATOR_MIN;
- U32 count[MaxSeq+1];
- FSE_CTable* CTable_LitLength = nextEntropy->litlengthCTable;
- FSE_CTable* CTable_OffsetBits = nextEntropy->offcodeCTable;
- FSE_CTable* CTable_MatchLength = nextEntropy->matchlengthCTable;
+ ZSTD_strategy const strategy = cctxParams->cParams.strategy;
+ unsigned count[MaxSeq+1];
+ FSE_CTable* CTable_LitLength = nextEntropy->fse.litlengthCTable;
+ FSE_CTable* CTable_OffsetBits = nextEntropy->fse.offcodeCTable;
+ FSE_CTable* CTable_MatchLength = nextEntropy->fse.matchlengthCTable;
U32 LLtype, Offtype, MLtype; /* compressed, raw or rle */
const seqDef* const sequences = seqStorePtr->sequencesStart;
const BYTE* const ofCodeTable = seqStorePtr->ofCode;
@@ -1720,26 +2494,30 @@ MEM_STATIC size_t ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
BYTE* op = ostart;
size_t const nbSeq = seqStorePtr->sequences - seqStorePtr->sequencesStart;
BYTE* seqHead;
+ BYTE* lastNCount = NULL;
ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<<MAX(MLFSELog,LLFSELog)));
+ DEBUGLOG(5, "ZSTD_compressSequences_internal");
/* Compress literals */
{ const BYTE* const literals = seqStorePtr->litStart;
size_t const litSize = seqStorePtr->lit - literals;
size_t const cSize = ZSTD_compressLiterals(
- prevEntropy, nextEntropy,
- cctxParams->cParams.strategy, cctxParams->disableLiteralCompression,
+ &prevEntropy->huf, &nextEntropy->huf,
+ cctxParams->cParams.strategy,
+ ZSTD_disableLiteralsCompression(cctxParams),
op, dstCapacity,
literals, litSize,
- workspace, bmi2);
- if (ZSTD_isError(cSize))
- return cSize;
+ workspace, wkspSize,
+ bmi2);
+ FORWARD_IF_ERROR(cSize);
assert(cSize <= dstCapacity);
op += cSize;
}
/* Sequences Header */
- if ((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead*/) return ERROR(dstSize_tooSmall);
+ RETURN_ERROR_IF((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead*/,
+ dstSize_tooSmall);
if (nbSeq < 0x7F)
*op++ = (BYTE)nbSeq;
else if (nbSeq < LONGNBSEQ)
@@ -1747,13 +2525,9 @@ MEM_STATIC size_t ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
else
op[0]=0xFF, MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ)), op+=3;
if (nbSeq==0) {
- memcpy(nextEntropy->litlengthCTable, prevEntropy->litlengthCTable, sizeof(prevEntropy->litlengthCTable));
- nextEntropy->litlength_repeatMode = prevEntropy->litlength_repeatMode;
- memcpy(nextEntropy->offcodeCTable, prevEntropy->offcodeCTable, sizeof(prevEntropy->offcodeCTable));
- nextEntropy->offcode_repeatMode = prevEntropy->offcode_repeatMode;
- memcpy(nextEntropy->matchlengthCTable, prevEntropy->matchlengthCTable, sizeof(prevEntropy->matchlengthCTable));
- nextEntropy->matchlength_repeatMode = prevEntropy->matchlength_repeatMode;
- return op - ostart;
+ /* Copy the old tables over as if we repeated them */
+ memcpy(&nextEntropy->fse, &prevEntropy->fse, sizeof(prevEntropy->fse));
+ return op - ostart;
}
/* seqHead : flags for FSE encoding type */
@@ -1762,44 +2536,66 @@ MEM_STATIC size_t ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
/* convert length/distances into codes */
ZSTD_seqToCodes(seqStorePtr);
/* build CTable for Literal Lengths */
- { U32 max = MaxLL;
- size_t const mostFrequent = FSE_countFast_wksp(count, &max, llCodeTable, nbSeq, workspace);
+ { unsigned max = MaxLL;
+ size_t const mostFrequent = HIST_countFast_wksp(count, &max, llCodeTable, nbSeq, workspace, wkspSize); /* can't fail */
DEBUGLOG(5, "Building LL table");
- nextEntropy->litlength_repeatMode = prevEntropy->litlength_repeatMode;
- LLtype = ZSTD_selectEncodingType(&nextEntropy->litlength_repeatMode, mostFrequent, nbSeq, LL_defaultNormLog, ZSTD_defaultAllowed);
+ nextEntropy->fse.litlength_repeatMode = prevEntropy->fse.litlength_repeatMode;
+ LLtype = ZSTD_selectEncodingType(&nextEntropy->fse.litlength_repeatMode,
+ count, max, mostFrequent, nbSeq,
+ LLFSELog, prevEntropy->fse.litlengthCTable,
+ LL_defaultNorm, LL_defaultNormLog,
+ ZSTD_defaultAllowed, strategy);
+ assert(set_basic < set_compressed && set_rle < set_compressed);
+ assert(!(LLtype < set_compressed && nextEntropy->fse.litlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */
{ size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_LitLength, LLFSELog, (symbolEncodingType_e)LLtype,
- count, max, llCodeTable, nbSeq, LL_defaultNorm, LL_defaultNormLog, MaxLL,
- prevEntropy->litlengthCTable, sizeof(prevEntropy->litlengthCTable),
- workspace, HUF_WORKSPACE_SIZE);
- if (ZSTD_isError(countSize)) return countSize;
+ count, max, llCodeTable, nbSeq, LL_defaultNorm, LL_defaultNormLog, MaxLL,
+ prevEntropy->fse.litlengthCTable, sizeof(prevEntropy->fse.litlengthCTable),
+ workspace, wkspSize);
+ FORWARD_IF_ERROR(countSize);
+ if (LLtype == set_compressed)
+ lastNCount = op;
op += countSize;
} }
/* build CTable for Offsets */
- { U32 max = MaxOff;
- size_t const mostFrequent = FSE_countFast_wksp(count, &max, ofCodeTable, nbSeq, workspace);
+ { unsigned max = MaxOff;
+ size_t const mostFrequent = HIST_countFast_wksp(count, &max, ofCodeTable, nbSeq, workspace, wkspSize); /* can't fail */
/* We can only use the basic table if max <= DefaultMaxOff, otherwise the offsets are too large */
ZSTD_defaultPolicy_e const defaultPolicy = (max <= DefaultMaxOff) ? ZSTD_defaultAllowed : ZSTD_defaultDisallowed;
DEBUGLOG(5, "Building OF table");
- nextEntropy->offcode_repeatMode = prevEntropy->offcode_repeatMode;
- Offtype = ZSTD_selectEncodingType(&nextEntropy->offcode_repeatMode, mostFrequent, nbSeq, OF_defaultNormLog, defaultPolicy);
+ nextEntropy->fse.offcode_repeatMode = prevEntropy->fse.offcode_repeatMode;
+ Offtype = ZSTD_selectEncodingType(&nextEntropy->fse.offcode_repeatMode,
+ count, max, mostFrequent, nbSeq,
+ OffFSELog, prevEntropy->fse.offcodeCTable,
+ OF_defaultNorm, OF_defaultNormLog,
+ defaultPolicy, strategy);
+ assert(!(Offtype < set_compressed && nextEntropy->fse.offcode_repeatMode != FSE_repeat_none)); /* We don't copy tables */
{ size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_OffsetBits, OffFSELog, (symbolEncodingType_e)Offtype,
- count, max, ofCodeTable, nbSeq, OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
- prevEntropy->offcodeCTable, sizeof(prevEntropy->offcodeCTable),
- workspace, HUF_WORKSPACE_SIZE);
- if (ZSTD_isError(countSize)) return countSize;
+ count, max, ofCodeTable, nbSeq, OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
+ prevEntropy->fse.offcodeCTable, sizeof(prevEntropy->fse.offcodeCTable),
+ workspace, wkspSize);
+ FORWARD_IF_ERROR(countSize);
+ if (Offtype == set_compressed)
+ lastNCount = op;
op += countSize;
} }
/* build CTable for MatchLengths */
- { U32 max = MaxML;
- size_t const mostFrequent = FSE_countFast_wksp(count, &max, mlCodeTable, nbSeq, workspace);
- DEBUGLOG(5, "Building ML table");
- nextEntropy->matchlength_repeatMode = prevEntropy->matchlength_repeatMode;
- MLtype = ZSTD_selectEncodingType(&nextEntropy->matchlength_repeatMode, mostFrequent, nbSeq, ML_defaultNormLog, ZSTD_defaultAllowed);
+ { unsigned max = MaxML;
+ size_t const mostFrequent = HIST_countFast_wksp(count, &max, mlCodeTable, nbSeq, workspace, wkspSize); /* can't fail */
+ DEBUGLOG(5, "Building ML table (remaining space : %i)", (int)(oend-op));
+ nextEntropy->fse.matchlength_repeatMode = prevEntropy->fse.matchlength_repeatMode;
+ MLtype = ZSTD_selectEncodingType(&nextEntropy->fse.matchlength_repeatMode,
+ count, max, mostFrequent, nbSeq,
+ MLFSELog, prevEntropy->fse.matchlengthCTable,
+ ML_defaultNorm, ML_defaultNormLog,
+ ZSTD_defaultAllowed, strategy);
+ assert(!(MLtype < set_compressed && nextEntropy->fse.matchlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */
{ size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_MatchLength, MLFSELog, (symbolEncodingType_e)MLtype,
- count, max, mlCodeTable, nbSeq, ML_defaultNorm, ML_defaultNormLog, MaxML,
- prevEntropy->matchlengthCTable, sizeof(prevEntropy->matchlengthCTable),
- workspace, HUF_WORKSPACE_SIZE);
- if (ZSTD_isError(countSize)) return countSize;
+ count, max, mlCodeTable, nbSeq, ML_defaultNorm, ML_defaultNormLog, MaxML,
+ prevEntropy->fse.matchlengthCTable, sizeof(prevEntropy->fse.matchlengthCTable),
+ workspace, wkspSize);
+ FORWARD_IF_ERROR(countSize);
+ if (MLtype == set_compressed)
+ lastNCount = op;
op += countSize;
} }
@@ -1812,65 +2608,103 @@ MEM_STATIC size_t ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
CTable_LitLength, llCodeTable,
sequences, nbSeq,
longOffsets, bmi2);
- if (ZSTD_isError(bitstreamSize)) return bitstreamSize;
+ FORWARD_IF_ERROR(bitstreamSize);
op += bitstreamSize;
+ /* zstd versions <= 1.3.4 mistakenly report corruption when
+ * FSE_readNCount() receives a buffer < 4 bytes.
+ * Fixed by https://github.com/facebook/zstd/pull/1146.
+ * This can happen when the last set_compressed table present is 2
+ * bytes and the bitstream is only one byte.
+ * In this exceedingly rare case, we will simply emit an uncompressed
+ * block, since it isn't worth optimizing.
+ */
+ if (lastNCount && (op - lastNCount) < 4) {
+ /* NCountSize >= 2 && bitstreamSize > 0 ==> lastCountSize == 3 */
+ assert(op - lastNCount == 3);
+ DEBUGLOG(5, "Avoiding bug in zstd decoder in versions <= 1.3.4 by "
+ "emitting an uncompressed block.");
+ return 0;
+ }
}
+ DEBUGLOG(5, "compressed block size : %u", (unsigned)(op - ostart));
return op - ostart;
}
-MEM_STATIC size_t ZSTD_compressSequences(seqStore_t* seqStorePtr,
- ZSTD_entropyCTables_t const* prevEntropy,
- ZSTD_entropyCTables_t* nextEntropy,
- ZSTD_CCtx_params const* cctxParams,
- void* dst, size_t dstCapacity,
- size_t srcSize, U32* workspace, int bmi2)
+MEM_STATIC size_t
+ZSTD_compressSequences(seqStore_t* seqStorePtr,
+ const ZSTD_entropyCTables_t* prevEntropy,
+ ZSTD_entropyCTables_t* nextEntropy,
+ const ZSTD_CCtx_params* cctxParams,
+ void* dst, size_t dstCapacity,
+ size_t srcSize,
+ void* workspace, size_t wkspSize,
+ int bmi2)
{
size_t const cSize = ZSTD_compressSequences_internal(
- seqStorePtr, prevEntropy, nextEntropy, cctxParams, dst, dstCapacity,
- workspace, bmi2);
+ seqStorePtr, prevEntropy, nextEntropy, cctxParams,
+ dst, dstCapacity,
+ workspace, wkspSize, bmi2);
+ if (cSize == 0) return 0;
/* When srcSize <= dstCapacity, there is enough space to write a raw uncompressed block.
* Since we ran out of space, block must be not compressible, so fall back to raw uncompressed block.
*/
if ((cSize == ERROR(dstSize_tooSmall)) & (srcSize <= dstCapacity))
return 0; /* block not compressed */
- if (ZSTD_isError(cSize)) return cSize;
+ FORWARD_IF_ERROR(cSize);
/* Check compressibility */
- { size_t const maxCSize = srcSize - ZSTD_minGain(srcSize); /* note : fixed formula, maybe should depend on compression level, or strategy */
+ { size_t const maxCSize = srcSize - ZSTD_minGain(srcSize, cctxParams->cParams.strategy);
if (cSize >= maxCSize) return 0; /* block not compressed */
}
- /* We check that dictionaries have offset codes available for the first
- * block. After the first block, the offcode table might not have large
- * enough codes to represent the offsets in the data.
- */
- if (nextEntropy->offcode_repeatMode == FSE_repeat_valid)
- nextEntropy->offcode_repeatMode = FSE_repeat_check;
-
return cSize;
}
/* ZSTD_selectBlockCompressor() :
* Not static, but internal use only (used by long distance matcher)
* assumption : strat is a valid strategy */
-ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, int extDict)
+ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_dictMode_e dictMode)
{
- static const ZSTD_blockCompressor blockCompressor[2][(unsigned)ZSTD_btultra+1] = {
+ static const ZSTD_blockCompressor blockCompressor[3][ZSTD_STRATEGY_MAX+1] = {
{ ZSTD_compressBlock_fast /* default for 0 */,
- ZSTD_compressBlock_fast, ZSTD_compressBlock_doubleFast, ZSTD_compressBlock_greedy,
- ZSTD_compressBlock_lazy, ZSTD_compressBlock_lazy2, ZSTD_compressBlock_btlazy2,
- ZSTD_compressBlock_btopt, ZSTD_compressBlock_btultra },
+ ZSTD_compressBlock_fast,
+ ZSTD_compressBlock_doubleFast,
+ ZSTD_compressBlock_greedy,
+ ZSTD_compressBlock_lazy,
+ ZSTD_compressBlock_lazy2,
+ ZSTD_compressBlock_btlazy2,
+ ZSTD_compressBlock_btopt,
+ ZSTD_compressBlock_btultra,
+ ZSTD_compressBlock_btultra2 },
{ ZSTD_compressBlock_fast_extDict /* default for 0 */,
- ZSTD_compressBlock_fast_extDict, ZSTD_compressBlock_doubleFast_extDict, ZSTD_compressBlock_greedy_extDict,
- ZSTD_compressBlock_lazy_extDict,ZSTD_compressBlock_lazy2_extDict, ZSTD_compressBlock_btlazy2_extDict,
- ZSTD_compressBlock_btopt_extDict, ZSTD_compressBlock_btultra_extDict }
+ ZSTD_compressBlock_fast_extDict,
+ ZSTD_compressBlock_doubleFast_extDict,
+ ZSTD_compressBlock_greedy_extDict,
+ ZSTD_compressBlock_lazy_extDict,
+ ZSTD_compressBlock_lazy2_extDict,
+ ZSTD_compressBlock_btlazy2_extDict,
+ ZSTD_compressBlock_btopt_extDict,
+ ZSTD_compressBlock_btultra_extDict,
+ ZSTD_compressBlock_btultra_extDict },
+ { ZSTD_compressBlock_fast_dictMatchState /* default for 0 */,
+ ZSTD_compressBlock_fast_dictMatchState,
+ ZSTD_compressBlock_doubleFast_dictMatchState,
+ ZSTD_compressBlock_greedy_dictMatchState,
+ ZSTD_compressBlock_lazy_dictMatchState,
+ ZSTD_compressBlock_lazy2_dictMatchState,
+ ZSTD_compressBlock_btlazy2_dictMatchState,
+ ZSTD_compressBlock_btopt_dictMatchState,
+ ZSTD_compressBlock_btultra_dictMatchState,
+ ZSTD_compressBlock_btultra_dictMatchState }
};
+ ZSTD_blockCompressor selectedCompressor;
ZSTD_STATIC_ASSERT((unsigned)ZSTD_fast == 1);
- assert((U32)strat >= (U32)ZSTD_fast);
- assert((U32)strat <= (U32)ZSTD_btultra);
- return blockCompressor[extDict!=0][(U32)strat];
+ assert(ZSTD_cParam_withinBounds(ZSTD_c_strategy, strat));
+ selectedCompressor = blockCompressor[(int)dictMode][(int)strat];
+ assert(selectedCompressor != NULL);
+ return selectedCompressor;
}
static void ZSTD_storeLastLiterals(seqStore_t* seqStorePtr,
@@ -1880,7 +2714,7 @@ static void ZSTD_storeLastLiterals(seqStore_t* seqStorePtr,
seqStorePtr->lit += lastLLSize;
}
-static void ZSTD_resetSeqStore(seqStore_t* ssPtr)
+void ZSTD_resetSeqStore(seqStore_t* ssPtr)
{
ssPtr->lit = ssPtr->litStart;
ssPtr->sequences = ssPtr->sequencesStart;
@@ -1892,24 +2726,41 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
const void* src, size_t srcSize)
{
ZSTD_matchState_t* const ms = &zc->blockState.matchState;
+ size_t cSize;
DEBUGLOG(5, "ZSTD_compressBlock_internal (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u)",
- (U32)dstCapacity, ms->window.dictLimit, ms->nextToUpdate);
+ (unsigned)dstCapacity, (unsigned)ms->window.dictLimit, (unsigned)ms->nextToUpdate);
+ assert(srcSize <= ZSTD_BLOCKSIZE_MAX);
+
+ /* Assert that we have correctly flushed the ctx params into the ms's copy */
+ ZSTD_assertEqualCParams(zc->appliedParams.cParams, ms->cParams);
+
if (srcSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1) {
- ZSTD_ldm_skipSequences(&zc->externSeqStore, srcSize, zc->appliedParams.cParams.searchLength);
- return 0; /* don't even attempt compression below a certain srcSize */
+ ZSTD_ldm_skipSequences(&zc->externSeqStore, srcSize, zc->appliedParams.cParams.minMatch);
+ cSize = 0;
+ goto out; /* don't even attempt compression below a certain srcSize */
}
ZSTD_resetSeqStore(&(zc->seqStore));
+ /* required for optimal parser to read stats from dictionary */
+ ms->opt.symbolCosts = &zc->blockState.prevCBlock->entropy;
+ /* tell the optimal parser how we expect to compress literals */
+ ms->opt.literalCompressionMode = zc->appliedParams.literalCompressionMode;
+
+ /* a gap between an attached dict and the current window is not safe,
+ * they must remain adjacent,
+ * and when that stops being the case, the dict must be unset */
+ assert(ms->dictMatchState == NULL || ms->loadedDictEnd == ms->window.dictLimit);
/* limited update after a very long match */
{ const BYTE* const base = ms->window.base;
const BYTE* const istart = (const BYTE*)src;
const U32 current = (U32)(istart-base);
+ if (sizeof(ptrdiff_t)==8) assert(istart - base < (ptrdiff_t)(U32)(-1)); /* ensure no overflow */
if (current > ms->nextToUpdate + 384)
ms->nextToUpdate = current - MIN(192, (U32)(current - ms->nextToUpdate - 384));
}
/* select and store sequences */
- { U32 const extDict = ZSTD_window_hasExtDict(ms->window);
+ { ZSTD_dictMode_e const dictMode = ZSTD_matchState_dictMode(ms);
size_t lastLLSize;
{ int i;
for (i = 0; i < ZSTD_REP_NUM; ++i)
@@ -1922,8 +2773,7 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
ZSTD_ldm_blockCompress(&zc->externSeqStore,
ms, &zc->seqStore,
zc->blockState.nextCBlock->rep,
- &zc->appliedParams.cParams,
- src, srcSize, extDict);
+ src, srcSize);
assert(zc->externSeqStore.pos <= zc->externSeqStore.size);
} else if (zc->appliedParams.ldmParams.enableLdm) {
rawSeqStore_t ldmSeqStore = {NULL, 0, 0, 0};
@@ -1931,7 +2781,7 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
ldmSeqStore.seq = zc->ldmSequences;
ldmSeqStore.capacity = zc->maxNbLdmSequences;
/* Updates ldmSeqStore.size */
- CHECK_F(ZSTD_ldm_generateSequences(&zc->ldmState, &ldmSeqStore,
+ FORWARD_IF_ERROR(ZSTD_ldm_generateSequences(&zc->ldmState, &ldmSeqStore,
&zc->appliedParams.ldmParams,
src, srcSize));
/* Updates ldmSeqStore.pos */
@@ -1939,31 +2789,40 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
ZSTD_ldm_blockCompress(&ldmSeqStore,
ms, &zc->seqStore,
zc->blockState.nextCBlock->rep,
- &zc->appliedParams.cParams,
- src, srcSize, extDict);
+ src, srcSize);
assert(ldmSeqStore.pos == ldmSeqStore.size);
} else { /* not long range mode */
- ZSTD_blockCompressor const blockCompressor = ZSTD_selectBlockCompressor(zc->appliedParams.cParams.strategy, extDict);
- lastLLSize = blockCompressor(ms, &zc->seqStore, zc->blockState.nextCBlock->rep, &zc->appliedParams.cParams, src, srcSize);
+ ZSTD_blockCompressor const blockCompressor = ZSTD_selectBlockCompressor(zc->appliedParams.cParams.strategy, dictMode);
+ lastLLSize = blockCompressor(ms, &zc->seqStore, zc->blockState.nextCBlock->rep, src, srcSize);
}
{ const BYTE* const lastLiterals = (const BYTE*)src + srcSize - lastLLSize;
ZSTD_storeLastLiterals(&zc->seqStore, lastLiterals, lastLLSize);
} }
/* encode sequences and literals */
- { size_t const cSize = ZSTD_compressSequences(&zc->seqStore,
- &zc->blockState.prevCBlock->entropy, &zc->blockState.nextCBlock->entropy,
- &zc->appliedParams,
- dst, dstCapacity,
- srcSize, zc->entropyWorkspace, zc->bmi2);
- if (ZSTD_isError(cSize) || cSize == 0) return cSize;
- /* confirm repcodes and entropy tables */
- { ZSTD_compressedBlockState_t* const tmp = zc->blockState.prevCBlock;
- zc->blockState.prevCBlock = zc->blockState.nextCBlock;
- zc->blockState.nextCBlock = tmp;
- }
- return cSize;
+ cSize = ZSTD_compressSequences(&zc->seqStore,
+ &zc->blockState.prevCBlock->entropy, &zc->blockState.nextCBlock->entropy,
+ &zc->appliedParams,
+ dst, dstCapacity,
+ srcSize,
+ zc->entropyWorkspace, HUF_WORKSPACE_SIZE /* statically allocated in resetCCtx */,
+ zc->bmi2);
+
+out:
+ if (!ZSTD_isError(cSize) && cSize != 0) {
+ /* confirm repcodes and entropy tables when emitting a compressed block */
+ ZSTD_compressedBlockState_t* const tmp = zc->blockState.prevCBlock;
+ zc->blockState.prevCBlock = zc->blockState.nextCBlock;
+ zc->blockState.nextCBlock = tmp;
}
+ /* We check that dictionaries have offset codes available for the first
+ * block. After the first block, the offcode table might not have large
+ * enough codes to represent the offsets in the data.
+ */
+ if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid)
+ zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check;
+
+ return cSize;
}
@@ -1987,7 +2846,7 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
U32 const maxDist = (U32)1 << cctx->appliedParams.cParams.windowLog;
assert(cctx->appliedParams.cParams.windowLog <= 31);
- DEBUGLOG(5, "ZSTD_compress_frameChunk (blockSize=%u)", (U32)blockSize);
+ DEBUGLOG(5, "ZSTD_compress_frameChunk (blockSize=%u)", (unsigned)blockSize);
if (cctx->appliedParams.fParams.checksumFlag && srcSize)
XXH64_update(&cctx->xxhState, src, srcSize);
@@ -1995,8 +2854,9 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
ZSTD_matchState_t* const ms = &cctx->blockState.matchState;
U32 const lastBlock = lastFrameChunk & (blockSize >= remaining);
- if (dstCapacity < ZSTD_blockHeaderSize + MIN_CBLOCK_SIZE)
- return ERROR(dstSize_tooSmall); /* not enough space to store compressed block */
+ RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize + MIN_CBLOCK_SIZE,
+ dstSize_tooSmall,
+ "not enough space to store compressed block");
if (remaining < blockSize) blockSize = remaining;
if (ZSTD_window_needOverflowCorrection(ms->window, ip + blockSize)) {
@@ -2005,26 +2865,23 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30);
ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30);
ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31);
-
ZSTD_reduceIndex(cctx, correction);
if (ms->nextToUpdate < correction) ms->nextToUpdate = 0;
else ms->nextToUpdate -= correction;
ms->loadedDictEnd = 0;
+ ms->dictMatchState = NULL;
}
- ZSTD_window_enforceMaxDist(&ms->window, ip + blockSize, maxDist, &ms->loadedDictEnd);
+ ZSTD_window_enforceMaxDist(&ms->window, ip + blockSize, maxDist, &ms->loadedDictEnd, &ms->dictMatchState);
if (ms->nextToUpdate < ms->window.lowLimit) ms->nextToUpdate = ms->window.lowLimit;
{ size_t cSize = ZSTD_compressBlock_internal(cctx,
op+ZSTD_blockHeaderSize, dstCapacity-ZSTD_blockHeaderSize,
ip, blockSize);
- if (ZSTD_isError(cSize)) return cSize;
+ FORWARD_IF_ERROR(cSize);
if (cSize == 0) { /* block is not compressible */
- U32 const cBlockHeader24 = lastBlock + (((U32)bt_raw)<<1) + (U32)(blockSize << 3);
- if (blockSize + ZSTD_blockHeaderSize > dstCapacity) return ERROR(dstSize_tooSmall);
- MEM_writeLE32(op, cBlockHeader24); /* 4th byte will be overwritten */
- memcpy(op + ZSTD_blockHeaderSize, ip, blockSize);
- cSize = ZSTD_blockHeaderSize + blockSize;
+ cSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock);
+ FORWARD_IF_ERROR(cSize);
} else {
U32 const cBlockHeader24 = lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3);
MEM_writeLE24(op, cBlockHeader24);
@@ -2038,7 +2895,7 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
assert(dstCapacity >= cSize);
dstCapacity -= cSize;
DEBUGLOG(5, "ZSTD_compress_frameChunk: adding a block of size %u",
- (U32)cSize);
+ (unsigned)cSize);
} }
if (lastFrameChunk && (op>ostart)) cctx->stage = ZSTDcs_ending;
@@ -2057,18 +2914,19 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
BYTE const windowLogByte = (BYTE)((params.cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3);
U32 const fcsCode = params.fParams.contentSizeFlag ?
(pledgedSrcSize>=256) + (pledgedSrcSize>=65536+256) + (pledgedSrcSize>=0xFFFFFFFFU) : 0; /* 0-3 */
- BYTE const frameHeaderDecriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag<<2) + (singleSegment<<5) + (fcsCode<<6) );
+ BYTE const frameHeaderDescriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag<<2) + (singleSegment<<5) + (fcsCode<<6) );
size_t pos=0;
- if (dstCapacity < ZSTD_frameHeaderSize_max) return ERROR(dstSize_tooSmall);
+ assert(!(params.fParams.contentSizeFlag && pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN));
+ RETURN_ERROR_IF(dstCapacity < ZSTD_FRAMEHEADERSIZE_MAX, dstSize_tooSmall);
DEBUGLOG(4, "ZSTD_writeFrameHeader : dictIDFlag : %u ; dictID : %u ; dictIDSizeCode : %u",
- !params.fParams.noDictIDFlag, dictID, dictIDSizeCode);
+ !params.fParams.noDictIDFlag, (unsigned)dictID, (unsigned)dictIDSizeCode);
if (params.format == ZSTD_f_zstd1) {
MEM_writeLE32(dst, ZSTD_MAGICNUMBER);
pos = 4;
}
- op[pos++] = frameHeaderDecriptionByte;
+ op[pos++] = frameHeaderDescriptionByte;
if (!singleSegment) op[pos++] = windowLogByte;
switch(dictIDSizeCode)
{
@@ -2092,11 +2950,11 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
/* ZSTD_writeLastEmptyBlock() :
* output an empty Block with end-of-frame mark to complete a frame
* @return : size of data written into `dst` (== ZSTD_blockHeaderSize (defined in zstd_internal.h))
- * or an error code if `dstCapcity` is too small (<ZSTD_blockHeaderSize)
+ * or an error code if `dstCapacity` is too small (<ZSTD_blockHeaderSize)
*/
size_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity)
{
- if (dstCapacity < ZSTD_blockHeaderSize) return ERROR(dstSize_tooSmall);
+ RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize, dstSize_tooSmall);
{ U32 const cBlockHeader24 = 1 /*lastBlock*/ + (((U32)bt_raw)<<1); /* 0 size */
MEM_writeLE24(dst, cBlockHeader24);
return ZSTD_blockHeaderSize;
@@ -2105,10 +2963,9 @@ size_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity)
size_t ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSeq)
{
- if (cctx->stage != ZSTDcs_init)
- return ERROR(stage_wrong);
- if (cctx->appliedParams.ldmParams.enableLdm)
- return ERROR(parameter_unsupported);
+ RETURN_ERROR_IF(cctx->stage != ZSTDcs_init, stage_wrong);
+ RETURN_ERROR_IF(cctx->appliedParams.ldmParams.enableLdm,
+ parameter_unsupported);
cctx->externSeqStore.seq = seq;
cctx->externSeqStore.size = nbSeq;
cctx->externSeqStore.capacity = nbSeq;
@@ -2122,17 +2979,18 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
const void* src, size_t srcSize,
U32 frame, U32 lastFrameChunk)
{
- ZSTD_matchState_t* ms = &cctx->blockState.matchState;
+ ZSTD_matchState_t* const ms = &cctx->blockState.matchState;
size_t fhSize = 0;
DEBUGLOG(5, "ZSTD_compressContinue_internal, stage: %u, srcSize: %u",
- cctx->stage, (U32)srcSize);
- if (cctx->stage==ZSTDcs_created) return ERROR(stage_wrong); /* missing init (ZSTD_compressBegin) */
+ cctx->stage, (unsigned)srcSize);
+ RETURN_ERROR_IF(cctx->stage==ZSTDcs_created, stage_wrong,
+ "missing init (ZSTD_compressBegin)");
if (frame && (cctx->stage==ZSTDcs_init)) {
fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, cctx->appliedParams,
cctx->pledgedSrcSizePlusOne-1, cctx->dictID);
- if (ZSTD_isError(fhSize)) return fhSize;
+ FORWARD_IF_ERROR(fhSize);
dstCapacity -= fhSize;
dst = (char*)dst + fhSize;
cctx->stage = ZSTDcs_ongoing;
@@ -2143,22 +3001,42 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
if (!ZSTD_window_update(&ms->window, src, srcSize)) {
ms->nextToUpdate = ms->window.dictLimit;
}
- if (cctx->appliedParams.ldmParams.enableLdm)
+ if (cctx->appliedParams.ldmParams.enableLdm) {
ZSTD_window_update(&cctx->ldmState.window, src, srcSize);
+ }
- DEBUGLOG(5, "ZSTD_compressContinue_internal (blockSize=%u)", (U32)cctx->blockSize);
+ if (!frame) {
+ /* overflow check and correction for block mode */
+ if (ZSTD_window_needOverflowCorrection(ms->window, (const char*)src + srcSize)) {
+ U32 const cycleLog = ZSTD_cycleLog(cctx->appliedParams.cParams.chainLog, cctx->appliedParams.cParams.strategy);
+ U32 const correction = ZSTD_window_correctOverflow(&ms->window, cycleLog, 1 << cctx->appliedParams.cParams.windowLog, src);
+ ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30);
+ ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30);
+ ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31);
+ ZSTD_reduceIndex(cctx, correction);
+ if (ms->nextToUpdate < correction) ms->nextToUpdate = 0;
+ else ms->nextToUpdate -= correction;
+ ms->loadedDictEnd = 0;
+ ms->dictMatchState = NULL;
+ }
+ }
+
+ DEBUGLOG(5, "ZSTD_compressContinue_internal (blockSize=%u)", (unsigned)cctx->blockSize);
{ size_t const cSize = frame ?
ZSTD_compress_frameChunk (cctx, dst, dstCapacity, src, srcSize, lastFrameChunk) :
ZSTD_compressBlock_internal (cctx, dst, dstCapacity, src, srcSize);
- if (ZSTD_isError(cSize)) return cSize;
+ FORWARD_IF_ERROR(cSize);
cctx->consumedSrcSize += srcSize;
cctx->producedCSize += (cSize + fhSize);
- if (cctx->appliedParams.fParams.contentSizeFlag) { /* control src size */
- if (cctx->consumedSrcSize+1 > cctx->pledgedSrcSizePlusOne) {
- DEBUGLOG(4, "error : pledgedSrcSize = %u, while realSrcSize >= %u",
- (U32)cctx->pledgedSrcSizePlusOne-1, (U32)cctx->consumedSrcSize);
- return ERROR(srcSize_wrong);
- }
+ assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0));
+ if (cctx->pledgedSrcSizePlusOne != 0) { /* control src size */
+ ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN == (unsigned long long)-1);
+ RETURN_ERROR_IF(
+ cctx->consumedSrcSize+1 > cctx->pledgedSrcSizePlusOne,
+ srcSize_wrong,
+ "error : pledgedSrcSize = %u, while realSrcSize >= %u",
+ (unsigned)cctx->pledgedSrcSizePlusOne-1,
+ (unsigned)cctx->consumedSrcSize);
}
return cSize + fhSize;
}
@@ -2168,7 +3046,7 @@ size_t ZSTD_compressContinue (ZSTD_CCtx* cctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize)
{
- DEBUGLOG(5, "ZSTD_compressContinue (srcSize=%u)", (U32)srcSize);
+ DEBUGLOG(5, "ZSTD_compressContinue (srcSize=%u)", (unsigned)srcSize);
return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 1 /* frame mode */, 0 /* last chunk */);
}
@@ -2183,45 +3061,52 @@ size_t ZSTD_getBlockSize(const ZSTD_CCtx* cctx)
size_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
{
size_t const blockSizeMax = ZSTD_getBlockSize(cctx);
- if (srcSize > blockSizeMax) return ERROR(srcSize_wrong);
+ RETURN_ERROR_IF(srcSize > blockSizeMax, srcSize_wrong);
+
return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 0 /* frame mode */, 0 /* last chunk */);
}
/*! ZSTD_loadDictionaryContent() :
* @return : 0, or an error code
*/
-static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms, ZSTD_CCtx_params const* params, const void* src, size_t srcSize)
+static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms,
+ ZSTD_CCtx_params const* params,
+ const void* src, size_t srcSize,
+ ZSTD_dictTableLoadMethod_e dtlm)
{
const BYTE* const ip = (const BYTE*) src;
const BYTE* const iend = ip + srcSize;
- ZSTD_compressionParameters const* cParams = &params->cParams;
ZSTD_window_update(&ms->window, src, srcSize);
ms->loadedDictEnd = params->forceWindow ? 0 : (U32)(iend - ms->window.base);
+ /* Assert that we the ms params match the params we're being given */
+ ZSTD_assertEqualCParams(params->cParams, ms->cParams);
+
if (srcSize <= HASH_READ_SIZE) return 0;
switch(params->cParams.strategy)
{
case ZSTD_fast:
- ZSTD_fillHashTable(ms, cParams, iend);
+ ZSTD_fillHashTable(ms, iend, dtlm);
break;
case ZSTD_dfast:
- ZSTD_fillDoubleHashTable(ms, cParams, iend);
+ ZSTD_fillDoubleHashTable(ms, iend, dtlm);
break;
case ZSTD_greedy:
case ZSTD_lazy:
case ZSTD_lazy2:
if (srcSize >= HASH_READ_SIZE)
- ZSTD_insertAndFindFirstIndex(ms, cParams, iend-HASH_READ_SIZE);
+ ZSTD_insertAndFindFirstIndex(ms, iend-HASH_READ_SIZE);
break;
case ZSTD_btlazy2: /* we want the dictionary table fully sorted */
case ZSTD_btopt:
case ZSTD_btultra:
+ case ZSTD_btultra2:
if (srcSize >= HASH_READ_SIZE)
- ZSTD_updateTree(ms, cParams, iend-HASH_READ_SIZE, iend);
+ ZSTD_updateTree(ms, iend-HASH_READ_SIZE, iend);
break;
default:
@@ -2239,9 +3124,9 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms, ZSTD_CCtx_params
NOTE: This behavior is not standard and could be improved in the future. */
static size_t ZSTD_checkDictNCount(short* normalizedCounter, unsigned dictMaxSymbolValue, unsigned maxSymbolValue) {
U32 s;
- if (dictMaxSymbolValue < maxSymbolValue) return ERROR(dictionary_corrupted);
+ RETURN_ERROR_IF(dictMaxSymbolValue < maxSymbolValue, dictionary_corrupted);
for (s = 0; s <= maxSymbolValue; ++s) {
- if (normalizedCounter[s] == 0) return ERROR(dictionary_corrupted);
+ RETURN_ERROR_IF(normalizedCounter[s] == 0, dictionary_corrupted);
}
return 0;
}
@@ -2256,7 +3141,12 @@ static size_t ZSTD_checkDictNCount(short* normalizedCounter, unsigned dictMaxSym
* assumptions : magic number supposed already checked
* dictSize supposed > 8
*/
-static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs, ZSTD_matchState_t* ms, ZSTD_CCtx_params const* params, const void* dict, size_t dictSize, void* workspace)
+static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs,
+ ZSTD_matchState_t* ms,
+ ZSTD_CCtx_params const* params,
+ const void* dict, size_t dictSize,
+ ZSTD_dictTableLoadMethod_e dtlm,
+ void* workspace)
{
const BYTE* dictPtr = (const BYTE*)dict;
const BYTE* const dictEnd = dictPtr + dictSize;
@@ -2265,53 +3155,65 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs, ZSTD_matc
size_t dictID;
ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<<MAX(MLFSELog,LLFSELog)));
+ assert(dictSize > 8);
+ assert(MEM_readLE32(dictPtr) == ZSTD_MAGIC_DICTIONARY);
dictPtr += 4; /* skip magic number */
dictID = params->fParams.noDictIDFlag ? 0 : MEM_readLE32(dictPtr);
dictPtr += 4;
{ unsigned maxSymbolValue = 255;
- size_t const hufHeaderSize = HUF_readCTable((HUF_CElt*)bs->entropy.hufCTable, &maxSymbolValue, dictPtr, dictEnd-dictPtr);
- if (HUF_isError(hufHeaderSize)) return ERROR(dictionary_corrupted);
- if (maxSymbolValue < 255) return ERROR(dictionary_corrupted);
+ size_t const hufHeaderSize = HUF_readCTable((HUF_CElt*)bs->entropy.huf.CTable, &maxSymbolValue, dictPtr, dictEnd-dictPtr);
+ RETURN_ERROR_IF(HUF_isError(hufHeaderSize), dictionary_corrupted);
+ RETURN_ERROR_IF(maxSymbolValue < 255, dictionary_corrupted);
dictPtr += hufHeaderSize;
}
{ unsigned offcodeLog;
size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
- if (FSE_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);
- if (offcodeLog > OffFSELog) return ERROR(dictionary_corrupted);
+ RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted);
+ RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted);
/* Defer checking offcodeMaxValue because we need to know the size of the dictionary content */
- CHECK_E( FSE_buildCTable_wksp(bs->entropy.offcodeCTable, offcodeNCount, offcodeMaxValue, offcodeLog, workspace, HUF_WORKSPACE_SIZE),
- dictionary_corrupted);
+ /* fill all offset symbols to avoid garbage at end of table */
+ RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(
+ bs->entropy.fse.offcodeCTable,
+ offcodeNCount, MaxOff, offcodeLog,
+ workspace, HUF_WORKSPACE_SIZE)),
+ dictionary_corrupted);
dictPtr += offcodeHeaderSize;
}
{ short matchlengthNCount[MaxML+1];
unsigned matchlengthMaxValue = MaxML, matchlengthLog;
size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
- if (FSE_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted);
- if (matchlengthLog > MLFSELog) return ERROR(dictionary_corrupted);
+ RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted);
+ RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted);
/* Every match length code must have non-zero probability */
- CHECK_F( ZSTD_checkDictNCount(matchlengthNCount, matchlengthMaxValue, MaxML));
- CHECK_E( FSE_buildCTable_wksp(bs->entropy.matchlengthCTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog, workspace, HUF_WORKSPACE_SIZE),
- dictionary_corrupted);
+ FORWARD_IF_ERROR( ZSTD_checkDictNCount(matchlengthNCount, matchlengthMaxValue, MaxML));
+ RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(
+ bs->entropy.fse.matchlengthCTable,
+ matchlengthNCount, matchlengthMaxValue, matchlengthLog,
+ workspace, HUF_WORKSPACE_SIZE)),
+ dictionary_corrupted);
dictPtr += matchlengthHeaderSize;
}
{ short litlengthNCount[MaxLL+1];
unsigned litlengthMaxValue = MaxLL, litlengthLog;
size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
- if (FSE_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted);
- if (litlengthLog > LLFSELog) return ERROR(dictionary_corrupted);
+ RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted);
+ RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted);
/* Every literal length code must have non-zero probability */
- CHECK_F( ZSTD_checkDictNCount(litlengthNCount, litlengthMaxValue, MaxLL));
- CHECK_E( FSE_buildCTable_wksp(bs->entropy.litlengthCTable, litlengthNCount, litlengthMaxValue, litlengthLog, workspace, HUF_WORKSPACE_SIZE),
- dictionary_corrupted);
+ FORWARD_IF_ERROR( ZSTD_checkDictNCount(litlengthNCount, litlengthMaxValue, MaxLL));
+ RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(
+ bs->entropy.fse.litlengthCTable,
+ litlengthNCount, litlengthMaxValue, litlengthLog,
+ workspace, HUF_WORKSPACE_SIZE)),
+ dictionary_corrupted);
dictPtr += litlengthHeaderSize;
}
- if (dictPtr+12 > dictEnd) return ERROR(dictionary_corrupted);
+ RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted);
bs->rep[0] = MEM_readLE32(dictPtr+0);
bs->rep[1] = MEM_readLE32(dictPtr+4);
bs->rep[2] = MEM_readLE32(dictPtr+8);
@@ -2324,30 +3226,33 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs, ZSTD_matc
offcodeMax = ZSTD_highbit32(maxOffset); /* Calculate minimum offset code required to represent maxOffset */
}
/* All offset values <= dictContentSize + 128 KB must be representable */
- CHECK_F (ZSTD_checkDictNCount(offcodeNCount, offcodeMaxValue, MIN(offcodeMax, MaxOff)));
+ FORWARD_IF_ERROR(ZSTD_checkDictNCount(offcodeNCount, offcodeMaxValue, MIN(offcodeMax, MaxOff)));
/* All repCodes must be <= dictContentSize and != 0*/
{ U32 u;
for (u=0; u<3; u++) {
- if (bs->rep[u] == 0) return ERROR(dictionary_corrupted);
- if (bs->rep[u] > dictContentSize) return ERROR(dictionary_corrupted);
+ RETURN_ERROR_IF(bs->rep[u] == 0, dictionary_corrupted);
+ RETURN_ERROR_IF(bs->rep[u] > dictContentSize, dictionary_corrupted);
} }
- bs->entropy.hufCTable_repeatMode = HUF_repeat_valid;
- bs->entropy.offcode_repeatMode = FSE_repeat_valid;
- bs->entropy.matchlength_repeatMode = FSE_repeat_valid;
- bs->entropy.litlength_repeatMode = FSE_repeat_valid;
- CHECK_F(ZSTD_loadDictionaryContent(ms, params, dictPtr, dictContentSize));
+ bs->entropy.huf.repeatMode = HUF_repeat_valid;
+ bs->entropy.fse.offcode_repeatMode = FSE_repeat_valid;
+ bs->entropy.fse.matchlength_repeatMode = FSE_repeat_valid;
+ bs->entropy.fse.litlength_repeatMode = FSE_repeat_valid;
+ FORWARD_IF_ERROR(ZSTD_loadDictionaryContent(ms, params, dictPtr, dictContentSize, dtlm));
return dictID;
}
}
/** ZSTD_compress_insertDictionary() :
* @return : dictID, or an error code */
-static size_t ZSTD_compress_insertDictionary(ZSTD_compressedBlockState_t* bs, ZSTD_matchState_t* ms,
- ZSTD_CCtx_params const* params,
- const void* dict, size_t dictSize,
- ZSTD_dictContentType_e dictContentType,
- void* workspace)
+static size_t
+ZSTD_compress_insertDictionary(ZSTD_compressedBlockState_t* bs,
+ ZSTD_matchState_t* ms,
+ const ZSTD_CCtx_params* params,
+ const void* dict, size_t dictSize,
+ ZSTD_dictContentType_e dictContentType,
+ ZSTD_dictTableLoadMethod_e dtlm,
+ void* workspace)
{
DEBUGLOG(4, "ZSTD_compress_insertDictionary (dictSize=%u)", (U32)dictSize);
if ((dict==NULL) || (dictSize<=8)) return 0;
@@ -2356,30 +3261,30 @@ static size_t ZSTD_compress_insertDictionary(ZSTD_compressedBlockState_t* bs, ZS
/* dict restricted modes */
if (dictContentType == ZSTD_dct_rawContent)
- return ZSTD_loadDictionaryContent(ms, params, dict, dictSize);
+ return ZSTD_loadDictionaryContent(ms, params, dict, dictSize, dtlm);
if (MEM_readLE32(dict) != ZSTD_MAGIC_DICTIONARY) {
if (dictContentType == ZSTD_dct_auto) {
DEBUGLOG(4, "raw content dictionary detected");
- return ZSTD_loadDictionaryContent(ms, params, dict, dictSize);
+ return ZSTD_loadDictionaryContent(ms, params, dict, dictSize, dtlm);
}
- if (dictContentType == ZSTD_dct_fullDict)
- return ERROR(dictionary_wrong);
+ RETURN_ERROR_IF(dictContentType == ZSTD_dct_fullDict, dictionary_wrong);
assert(0); /* impossible */
}
/* dict as full zstd dictionary */
- return ZSTD_loadZstdDictionary(bs, ms, params, dict, dictSize, workspace);
+ return ZSTD_loadZstdDictionary(bs, ms, params, dict, dictSize, dtlm, workspace);
}
/*! ZSTD_compressBegin_internal() :
* @return : 0, or an error code */
-size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
- const void* dict, size_t dictSize,
- ZSTD_dictContentType_e dictContentType,
- const ZSTD_CDict* cdict,
- ZSTD_CCtx_params params, U64 pledgedSrcSize,
- ZSTD_buffered_policy_e zbuff)
+static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
+ const void* dict, size_t dictSize,
+ ZSTD_dictContentType_e dictContentType,
+ ZSTD_dictTableLoadMethod_e dtlm,
+ const ZSTD_CDict* cdict,
+ ZSTD_CCtx_params params, U64 pledgedSrcSize,
+ ZSTD_buffered_policy_e zbuff)
{
DEBUGLOG(4, "ZSTD_compressBegin_internal: wlog=%u", params.cParams.windowLog);
/* params are supposed to be fully validated at this point */
@@ -2387,18 +3292,16 @@ size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
assert(!((dict) && (cdict))); /* either dict or cdict, not both */
if (cdict && cdict->dictContentSize>0) {
- cctx->requestedParams = params;
- return ZSTD_resetCCtx_usingCDict(cctx, cdict, params.cParams.windowLog,
- params.fParams, pledgedSrcSize, zbuff);
+ return ZSTD_resetCCtx_usingCDict(cctx, cdict, params, pledgedSrcSize, zbuff);
}
- CHECK_F( ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
+ FORWARD_IF_ERROR( ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
ZSTDcrp_continue, zbuff) );
{
size_t const dictID = ZSTD_compress_insertDictionary(
cctx->blockState.prevCBlock, &cctx->blockState.matchState,
- &params, dict, dictSize, dictContentType, cctx->entropyWorkspace);
- if (ZSTD_isError(dictID)) return dictID;
+ &params, dict, dictSize, dictContentType, dtlm, cctx->entropyWorkspace);
+ FORWARD_IF_ERROR(dictID);
assert(dictID <= (size_t)(U32)-1);
cctx->dictID = (U32)dictID;
}
@@ -2408,15 +3311,16 @@ size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
size_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx,
const void* dict, size_t dictSize,
ZSTD_dictContentType_e dictContentType,
+ ZSTD_dictTableLoadMethod_e dtlm,
const ZSTD_CDict* cdict,
ZSTD_CCtx_params params,
unsigned long long pledgedSrcSize)
{
DEBUGLOG(4, "ZSTD_compressBegin_advanced_internal: wlog=%u", params.cParams.windowLog);
/* compression parameters verification and optimization */
- CHECK_F( ZSTD_checkCParams(params.cParams) );
+ FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) );
return ZSTD_compressBegin_internal(cctx,
- dict, dictSize, dictContentType,
+ dict, dictSize, dictContentType, dtlm,
cdict,
params, pledgedSrcSize,
ZSTDb_not_buffered);
@@ -2431,7 +3335,7 @@ size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx,
ZSTD_CCtx_params const cctxParams =
ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
return ZSTD_compressBegin_advanced_internal(cctx,
- dict, dictSize, ZSTD_dct_auto,
+ dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast,
NULL /*cdict*/,
cctxParams, pledgedSrcSize);
}
@@ -2441,8 +3345,8 @@ size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t di
ZSTD_parameters const params = ZSTD_getParams(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize);
ZSTD_CCtx_params const cctxParams =
ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
- DEBUGLOG(4, "ZSTD_compressBegin_usingDict (dictSize=%u)", (U32)dictSize);
- return ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dct_auto, NULL,
+ DEBUGLOG(4, "ZSTD_compressBegin_usingDict (dictSize=%u)", (unsigned)dictSize);
+ return ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, NULL,
cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, ZSTDb_not_buffered);
}
@@ -2462,12 +3366,12 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
size_t fhSize = 0;
DEBUGLOG(4, "ZSTD_writeEpilogue");
- if (cctx->stage == ZSTDcs_created) return ERROR(stage_wrong); /* init missing */
+ RETURN_ERROR_IF(cctx->stage == ZSTDcs_created, stage_wrong, "init missing");
/* special case : empty frame */
if (cctx->stage == ZSTDcs_init) {
fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, cctx->appliedParams, 0, 0);
- if (ZSTD_isError(fhSize)) return fhSize;
+ FORWARD_IF_ERROR(fhSize);
dstCapacity -= fhSize;
op += fhSize;
cctx->stage = ZSTDcs_ongoing;
@@ -2476,7 +3380,7 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
if (cctx->stage != ZSTDcs_ending) {
/* write one last empty block, make it the "last" block */
U32 const cBlockHeader24 = 1 /* last block */ + (((U32)bt_raw)<<1) + 0;
- if (dstCapacity<4) return ERROR(dstSize_tooSmall);
+ RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall);
MEM_writeLE32(op, cBlockHeader24);
op += ZSTD_blockHeaderSize;
dstCapacity -= ZSTD_blockHeaderSize;
@@ -2484,8 +3388,8 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
if (cctx->appliedParams.fParams.checksumFlag) {
U32 const checksum = (U32) XXH64_digest(&cctx->xxhState);
- if (dstCapacity<4) return ERROR(dstSize_tooSmall);
- DEBUGLOG(4, "ZSTD_writeEpilogue: write checksum : %08X", checksum);
+ RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall);
+ DEBUGLOG(4, "ZSTD_writeEpilogue: write checksum : %08X", (unsigned)checksum);
MEM_writeLE32(op, checksum);
op += 4;
}
@@ -2502,45 +3406,53 @@ size_t ZSTD_compressEnd (ZSTD_CCtx* cctx,
size_t const cSize = ZSTD_compressContinue_internal(cctx,
dst, dstCapacity, src, srcSize,
1 /* frame mode */, 1 /* last chunk */);
- if (ZSTD_isError(cSize)) return cSize;
+ FORWARD_IF_ERROR(cSize);
endResult = ZSTD_writeEpilogue(cctx, (char*)dst + cSize, dstCapacity-cSize);
- if (ZSTD_isError(endResult)) return endResult;
- if (cctx->appliedParams.fParams.contentSizeFlag) { /* control src size */
+ FORWARD_IF_ERROR(endResult);
+ assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0));
+ if (cctx->pledgedSrcSizePlusOne != 0) { /* control src size */
+ ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN == (unsigned long long)-1);
DEBUGLOG(4, "end of frame : controlling src size");
- if (cctx->pledgedSrcSizePlusOne != cctx->consumedSrcSize+1) {
- DEBUGLOG(4, "error : pledgedSrcSize = %u, while realSrcSize = %u",
- (U32)cctx->pledgedSrcSizePlusOne-1, (U32)cctx->consumedSrcSize);
- return ERROR(srcSize_wrong);
- } }
+ RETURN_ERROR_IF(
+ cctx->pledgedSrcSizePlusOne != cctx->consumedSrcSize+1,
+ srcSize_wrong,
+ "error : pledgedSrcSize = %u, while realSrcSize = %u",
+ (unsigned)cctx->pledgedSrcSizePlusOne-1,
+ (unsigned)cctx->consumedSrcSize);
+ }
return cSize + endResult;
}
static size_t ZSTD_compress_internal (ZSTD_CCtx* cctx,
- void* dst, size_t dstCapacity,
- const void* src, size_t srcSize,
- const void* dict,size_t dictSize,
- ZSTD_parameters params)
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize,
+ const void* dict,size_t dictSize,
+ ZSTD_parameters params)
{
ZSTD_CCtx_params const cctxParams =
ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
DEBUGLOG(4, "ZSTD_compress_internal");
return ZSTD_compress_advanced_internal(cctx,
- dst, dstCapacity,
- src, srcSize,
- dict, dictSize,
- cctxParams);
+ dst, dstCapacity,
+ src, srcSize,
+ dict, dictSize,
+ cctxParams);
}
-size_t ZSTD_compress_advanced (ZSTD_CCtx* ctx,
+size_t ZSTD_compress_advanced (ZSTD_CCtx* cctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
const void* dict,size_t dictSize,
ZSTD_parameters params)
{
DEBUGLOG(4, "ZSTD_compress_advanced");
- CHECK_F(ZSTD_checkCParams(params.cParams));
- return ZSTD_compress_internal(ctx, dst, dstCapacity, src, srcSize, dict, dictSize, params);
+ FORWARD_IF_ERROR(ZSTD_checkCParams(params.cParams));
+ return ZSTD_compress_internal(cctx,
+ dst, dstCapacity,
+ src, srcSize,
+ dict, dictSize,
+ params);
}
/* Internal */
@@ -2551,37 +3463,44 @@ size_t ZSTD_compress_advanced_internal(
const void* dict,size_t dictSize,
ZSTD_CCtx_params params)
{
- DEBUGLOG(4, "ZSTD_compress_advanced_internal (srcSize:%u)",
- (U32)srcSize);
- CHECK_F( ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dct_auto, NULL,
- params, srcSize, ZSTDb_not_buffered) );
+ DEBUGLOG(4, "ZSTD_compress_advanced_internal (srcSize:%u)", (unsigned)srcSize);
+ FORWARD_IF_ERROR( ZSTD_compressBegin_internal(cctx,
+ dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, NULL,
+ params, srcSize, ZSTDb_not_buffered) );
return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize);
}
-size_t ZSTD_compress_usingDict(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize,
- const void* dict, size_t dictSize, int compressionLevel)
+size_t ZSTD_compress_usingDict(ZSTD_CCtx* cctx,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize,
+ const void* dict, size_t dictSize,
+ int compressionLevel)
{
- ZSTD_parameters const params = ZSTD_getParams(compressionLevel, srcSize ? srcSize : 1, dict ? dictSize : 0);
+ ZSTD_parameters const params = ZSTD_getParams(compressionLevel, srcSize + (!srcSize), dict ? dictSize : 0);
ZSTD_CCtx_params cctxParams = ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
assert(params.fParams.contentSizeFlag == 1);
- ZSTD_CCtxParam_setParameter(&cctxParams, ZSTD_p_compressLiterals, compressionLevel>=0);
return ZSTD_compress_advanced_internal(cctx, dst, dstCapacity, src, srcSize, dict, dictSize, cctxParams);
}
-size_t ZSTD_compressCCtx (ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize, int compressionLevel)
+size_t ZSTD_compressCCtx(ZSTD_CCtx* cctx,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize,
+ int compressionLevel)
{
- DEBUGLOG(4, "ZSTD_compressCCtx (srcSize=%u)", (U32)srcSize);
+ DEBUGLOG(4, "ZSTD_compressCCtx (srcSize=%u)", (unsigned)srcSize);
+ assert(cctx != NULL);
return ZSTD_compress_usingDict(cctx, dst, dstCapacity, src, srcSize, NULL, 0, compressionLevel);
}
-size_t ZSTD_compress(void* dst, size_t dstCapacity, const void* src, size_t srcSize, int compressionLevel)
+size_t ZSTD_compress(void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize,
+ int compressionLevel)
{
size_t result;
ZSTD_CCtx ctxBody;
- memset(&ctxBody, 0, sizeof(ctxBody));
- ctxBody.customMem = ZSTD_defaultCMem;
+ ZSTD_initCCtx(&ctxBody, ZSTD_defaultCMem);
result = ZSTD_compressCCtx(&ctxBody, dst, dstCapacity, src, srcSize, compressionLevel);
- ZSTD_free(ctxBody.workSpace, ZSTD_defaultCMem); /* can't free ctxBody itself, as it's on stack; free only heap content */
+ ZSTD_freeCCtxContent(&ctxBody); /* can't free ctxBody itself, as it's on stack; free only heap content */
return result;
}
@@ -2594,7 +3513,7 @@ size_t ZSTD_estimateCDictSize_advanced(
size_t dictSize, ZSTD_compressionParameters cParams,
ZSTD_dictLoadMethod_e dictLoadMethod)
{
- DEBUGLOG(5, "sizeof(ZSTD_CDict) : %u", (U32)sizeof(ZSTD_CDict));
+ DEBUGLOG(5, "sizeof(ZSTD_CDict) : %u", (unsigned)sizeof(ZSTD_CDict));
return sizeof(ZSTD_CDict) + HUF_WORKSPACE_SIZE + ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 0)
+ (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize);
}
@@ -2608,7 +3527,7 @@ size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel)
size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict)
{
if (cdict==NULL) return 0; /* support sizeof on NULL */
- DEBUGLOG(5, "sizeof(*cdict) : %u", (U32)sizeof(*cdict));
+ DEBUGLOG(5, "sizeof(*cdict) : %u", (unsigned)sizeof(*cdict));
return cdict->workspaceSize + (cdict->dictBuffer ? cdict->dictContentSize : 0) + sizeof(*cdict);
}
@@ -2619,9 +3538,9 @@ static size_t ZSTD_initCDict_internal(
ZSTD_dictContentType_e dictContentType,
ZSTD_compressionParameters cParams)
{
- DEBUGLOG(3, "ZSTD_initCDict_internal, dictContentType %u", (U32)dictContentType);
+ DEBUGLOG(3, "ZSTD_initCDict_internal (dictContentType:%u)", (unsigned)dictContentType);
assert(!ZSTD_checkCParams(cParams));
- cdict->cParams = cParams;
+ cdict->matchState.cParams = cParams;
if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dictBuffer) || (!dictSize)) {
cdict->dictBuffer = NULL;
cdict->dictContent = dictBuffer;
@@ -2629,7 +3548,7 @@ static size_t ZSTD_initCDict_internal(
void* const internalBuffer = ZSTD_malloc(dictSize, cdict->customMem);
cdict->dictBuffer = internalBuffer;
cdict->dictContent = internalBuffer;
- if (!internalBuffer) return ERROR(memory_allocation);
+ RETURN_ERROR_IF(!internalBuffer, memory_allocation);
memcpy(internalBuffer, dictBuffer, dictSize);
}
cdict->dictContentSize = dictSize;
@@ -2654,8 +3573,8 @@ static size_t ZSTD_initCDict_internal(
{ size_t const dictID = ZSTD_compress_insertDictionary(
&cdict->cBlockState, &cdict->matchState, &params,
cdict->dictContent, cdict->dictContentSize,
- dictContentType, cdict->workspace);
- if (ZSTD_isError(dictID)) return dictID;
+ dictContentType, ZSTD_dtlm_full, cdict->workspace);
+ FORWARD_IF_ERROR(dictID);
assert(dictID <= (size_t)(U32)-1);
cdict->dictID = (U32)dictID;
}
@@ -2669,7 +3588,7 @@ ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize,
ZSTD_dictContentType_e dictContentType,
ZSTD_compressionParameters cParams, ZSTD_customMem customMem)
{
- DEBUGLOG(3, "ZSTD_createCDict_advanced, mode %u", (U32)dictContentType);
+ DEBUGLOG(3, "ZSTD_createCDict_advanced, mode %u", (unsigned)dictContentType);
if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
{ ZSTD_CDict* const cdict = (ZSTD_CDict*)ZSTD_malloc(sizeof(ZSTD_CDict), customMem);
@@ -2750,7 +3669,7 @@ const ZSTD_CDict* ZSTD_initStaticCDict(
void* ptr;
if ((size_t)workspace & 7) return NULL; /* 8-aligned */
DEBUGLOG(4, "(workspaceSize < neededSize) : (%u < %u) => %u",
- (U32)workspaceSize, (U32)neededSize, (U32)(workspaceSize < neededSize));
+ (unsigned)workspaceSize, (unsigned)neededSize, (unsigned)(workspaceSize < neededSize));
if (workspaceSize < neededSize) return NULL;
if (dictLoadMethod == ZSTD_dlm_byCopy) {
@@ -2775,7 +3694,7 @@ const ZSTD_CDict* ZSTD_initStaticCDict(
ZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict)
{
assert(cdict != NULL);
- return cdict->cParams;
+ return cdict->matchState.cParams;
}
/* ZSTD_compressBegin_usingCDict_advanced() :
@@ -2785,7 +3704,7 @@ size_t ZSTD_compressBegin_usingCDict_advanced(
ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize)
{
DEBUGLOG(4, "ZSTD_compressBegin_usingCDict_advanced");
- if (cdict==NULL) return ERROR(dictionary_wrong);
+ RETURN_ERROR_IF(cdict==NULL, dictionary_wrong);
{ ZSTD_CCtx_params params = cctx->requestedParams;
params.cParams = ZSTD_getCParamsFromCDict(cdict);
/* Increase window log to fit the entire dictionary and source if the
@@ -2799,7 +3718,7 @@ size_t ZSTD_compressBegin_usingCDict_advanced(
}
params.fParams = fParams;
return ZSTD_compressBegin_internal(cctx,
- NULL, 0, ZSTD_dct_auto,
+ NULL, 0, ZSTD_dct_auto, ZSTD_dtlm_fast,
cdict,
params, pledgedSrcSize,
ZSTDb_not_buffered);
@@ -2813,7 +3732,7 @@ size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict)
{
ZSTD_frameParameters const fParams = { 0 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ };
DEBUGLOG(4, "ZSTD_compressBegin_usingCDict : dictIDFlag == %u", !fParams.noDictIDFlag);
- return ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, 0);
+ return ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, ZSTD_CONTENTSIZE_UNKNOWN);
}
size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx,
@@ -2821,7 +3740,7 @@ size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx,
const void* src, size_t srcSize,
const ZSTD_CDict* cdict, ZSTD_frameParameters fParams)
{
- CHECK_F (ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, srcSize)); /* will check if cdict != NULL */
+ FORWARD_IF_ERROR(ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, srcSize)); /* will check if cdict != NULL */
return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize);
}
@@ -2880,16 +3799,17 @@ size_t ZSTD_CStreamOutSize(void)
static size_t ZSTD_resetCStream_internal(ZSTD_CStream* cctx,
const void* const dict, size_t const dictSize, ZSTD_dictContentType_e const dictContentType,
const ZSTD_CDict* const cdict,
- ZSTD_CCtx_params const params, unsigned long long const pledgedSrcSize)
+ ZSTD_CCtx_params params, unsigned long long const pledgedSrcSize)
{
- DEBUGLOG(4, "ZSTD_resetCStream_internal (disableLiteralCompression=%i)",
- params.disableLiteralCompression);
+ DEBUGLOG(4, "ZSTD_resetCStream_internal");
+ /* Finalize the compression parameters */
+ params.cParams = ZSTD_getCParamsFromCCtxParams(&params, pledgedSrcSize, dictSize);
/* params are supposed to be fully validated at this point */
assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
assert(!((dict) && (cdict))); /* either dict or cdict, not both */
- CHECK_F( ZSTD_compressBegin_internal(cctx,
- dict, dictSize, dictContentType,
+ FORWARD_IF_ERROR( ZSTD_compressBegin_internal(cctx,
+ dict, dictSize, dictContentType, ZSTD_dtlm_fast,
cdict,
params, pledgedSrcSize,
ZSTDb_buffered) );
@@ -2906,14 +3826,17 @@ static size_t ZSTD_resetCStream_internal(ZSTD_CStream* cctx,
/* ZSTD_resetCStream():
* pledgedSrcSize == 0 means "unknown" */
-size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize)
+size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pss)
{
- ZSTD_CCtx_params params = zcs->requestedParams;
- DEBUGLOG(4, "ZSTD_resetCStream: pledgedSrcSize = %u", (U32)pledgedSrcSize);
- if (pledgedSrcSize==0) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN;
- params.fParams.contentSizeFlag = 1;
- params.cParams = ZSTD_getCParamsFromCCtxParams(&params, pledgedSrcSize, 0);
- return ZSTD_resetCStream_internal(zcs, NULL, 0, ZSTD_dct_auto, zcs->cdict, params, pledgedSrcSize);
+ /* temporary : 0 interpreted as "unknown" during transition period.
+ * Users willing to specify "unknown" **must** use ZSTD_CONTENTSIZE_UNKNOWN.
+ * 0 will be interpreted as "empty" in the future.
+ */
+ U64 const pledgedSrcSize = (pss==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss;
+ DEBUGLOG(4, "ZSTD_resetCStream: pledgedSrcSize = %u", (unsigned)pledgedSrcSize);
+ FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
+ FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) );
+ return 0;
}
/*! ZSTD_initCStream_internal() :
@@ -2925,31 +3848,18 @@ size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
ZSTD_CCtx_params params, unsigned long long pledgedSrcSize)
{
DEBUGLOG(4, "ZSTD_initCStream_internal");
+ FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
+ FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) );
assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
+ zcs->requestedParams = params;
assert(!((dict) && (cdict))); /* either dict or cdict, not both */
-
- if (dict && dictSize >= 8) {
- DEBUGLOG(4, "loading dictionary of size %u", (U32)dictSize);
- if (zcs->staticSize) { /* static CCtx : never uses malloc */
- /* incompatible with internal cdict creation */
- return ERROR(memory_allocation);
- }
- ZSTD_freeCDict(zcs->cdictLocal);
- zcs->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize,
- ZSTD_dlm_byCopy, ZSTD_dct_auto,
- params.cParams, zcs->customMem);
- zcs->cdict = zcs->cdictLocal;
- if (zcs->cdictLocal == NULL) return ERROR(memory_allocation);
+ if (dict) {
+ FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) );
} else {
- if (cdict) {
- params.cParams = ZSTD_getCParamsFromCDict(cdict); /* cParams are enforced from cdict; it includes windowLog */
- }
- ZSTD_freeCDict(zcs->cdictLocal);
- zcs->cdictLocal = NULL;
- zcs->cdict = cdict;
+ /* Dictionary is cleared if !cdict */
+ FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) );
}
-
- return ZSTD_resetCStream_internal(zcs, NULL, 0, ZSTD_dct_auto, zcs->cdict, params, pledgedSrcSize);
+ return 0;
}
/* ZSTD_initCStream_usingCDict_advanced() :
@@ -2960,22 +3870,20 @@ size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs,
unsigned long long pledgedSrcSize)
{
DEBUGLOG(4, "ZSTD_initCStream_usingCDict_advanced");
- if (!cdict) return ERROR(dictionary_wrong); /* cannot handle NULL cdict (does not know what to do) */
- { ZSTD_CCtx_params params = zcs->requestedParams;
- params.cParams = ZSTD_getCParamsFromCDict(cdict);
- params.fParams = fParams;
- return ZSTD_initCStream_internal(zcs,
- NULL, 0, cdict,
- params, pledgedSrcSize);
- }
+ FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
+ FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) );
+ zcs->requestedParams.fParams = fParams;
+ FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) );
+ return 0;
}
/* note : cdict must outlive compression session */
size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict)
{
- ZSTD_frameParameters const fParams = { 0 /* contentSizeFlag */, 0 /* checksum */, 0 /* hideDictID */ };
DEBUGLOG(4, "ZSTD_initCStream_usingCDict");
- return ZSTD_initCStream_usingCDict_advanced(zcs, cdict, fParams, ZSTD_CONTENTSIZE_UNKNOWN); /* note : will check that cdict != NULL */
+ FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
+ FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) );
+ return 0;
}
@@ -2985,43 +3893,66 @@ size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict)
* dict is loaded with default parameters ZSTD_dm_auto and ZSTD_dlm_byCopy. */
size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,
const void* dict, size_t dictSize,
- ZSTD_parameters params, unsigned long long pledgedSrcSize)
+ ZSTD_parameters params, unsigned long long pss)
{
- DEBUGLOG(4, "ZSTD_initCStream_advanced: pledgedSrcSize=%u, flag=%u",
- (U32)pledgedSrcSize, params.fParams.contentSizeFlag);
- CHECK_F( ZSTD_checkCParams(params.cParams) );
- if ((pledgedSrcSize==0) && (params.fParams.contentSizeFlag==0)) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN; /* for compatibility with older programs relying on this behavior. Users should now specify ZSTD_CONTENTSIZE_UNKNOWN. This line will be removed in the future. */
- { ZSTD_CCtx_params const cctxParams = ZSTD_assignParamsToCCtxParams(zcs->requestedParams, params);
- return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL /*cdict*/, cctxParams, pledgedSrcSize);
- }
+ /* for compatibility with older programs relying on this behavior.
+ * Users should now specify ZSTD_CONTENTSIZE_UNKNOWN.
+ * This line will be removed in the future.
+ */
+ U64 const pledgedSrcSize = (pss==0 && params.fParams.contentSizeFlag==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss;
+ DEBUGLOG(4, "ZSTD_initCStream_advanced");
+ FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
+ FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) );
+ FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) );
+ zcs->requestedParams = ZSTD_assignParamsToCCtxParams(zcs->requestedParams, params);
+ FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) );
+ return 0;
}
size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel)
{
- ZSTD_parameters const params = ZSTD_getParams(compressionLevel, 0, dictSize);
- ZSTD_CCtx_params const cctxParams =
- ZSTD_assignParamsToCCtxParams(zcs->requestedParams, params);
- return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL, cctxParams, ZSTD_CONTENTSIZE_UNKNOWN);
+ DEBUGLOG(4, "ZSTD_initCStream_usingDict");
+ FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
+ FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) );
+ FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) );
+ return 0;
}
size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pss)
{
- U64 const pledgedSrcSize = (pss==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss; /* temporary : 0 interpreted as "unknown" during transition period. Users willing to specify "unknown" **must** use ZSTD_CONTENTSIZE_UNKNOWN. `0` will be interpreted as "empty" in the future */
- ZSTD_parameters const params = ZSTD_getParams(compressionLevel, pledgedSrcSize, 0);
- ZSTD_CCtx_params const cctxParams = ZSTD_assignParamsToCCtxParams(zcs->requestedParams, params);
- return ZSTD_initCStream_internal(zcs, NULL, 0, NULL, cctxParams, pledgedSrcSize);
+ /* temporary : 0 interpreted as "unknown" during transition period.
+ * Users willing to specify "unknown" **must** use ZSTD_CONTENTSIZE_UNKNOWN.
+ * 0 will be interpreted as "empty" in the future.
+ */
+ U64 const pledgedSrcSize = (pss==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss;
+ DEBUGLOG(4, "ZSTD_initCStream_srcSize");
+ FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
+ FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, NULL) );
+ FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) );
+ FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) );
+ return 0;
}
size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel)
{
DEBUGLOG(4, "ZSTD_initCStream");
- return ZSTD_initCStream_srcSize(zcs, compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN);
+ FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
+ FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, NULL) );
+ FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) );
+ return 0;
}
/*====== Compression ======*/
-MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity,
- const void* src, size_t srcSize)
+static size_t ZSTD_nextInputSizeHint(const ZSTD_CCtx* cctx)
+{
+ size_t hintInSize = cctx->inBuffTarget - cctx->inBuffPos;
+ if (hintInSize==0) hintInSize = cctx->blockSize;
+ return hintInSize;
+}
+
+static size_t ZSTD_limitCopy(void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize)
{
size_t const length = MIN(dstCapacity, srcSize);
if (length) memcpy(dst, src, length);
@@ -3029,13 +3960,13 @@ MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity,
}
/** ZSTD_compressStream_generic():
- * internal function for all *compressStream*() variants and *compress_generic()
+ * internal function for all *compressStream*() variants
* non-static, because can be called from zstdmt_compress.c
* @return : hint size for next input */
-size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
- ZSTD_outBuffer* output,
- ZSTD_inBuffer* input,
- ZSTD_EndDirective const flushMode)
+static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
+ ZSTD_outBuffer* output,
+ ZSTD_inBuffer* input,
+ ZSTD_EndDirective const flushMode)
{
const char* const istart = (const char*)input->src;
const char* const iend = istart + input->size;
@@ -3046,7 +3977,7 @@ size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
U32 someMoreWork = 1;
/* check expectations */
- DEBUGLOG(5, "ZSTD_compressStream_generic, flush=%u", (U32)flushMode);
+ DEBUGLOG(5, "ZSTD_compressStream_generic, flush=%u", (unsigned)flushMode);
assert(zcs->inBuff != NULL);
assert(zcs->inBuffSize > 0);
assert(zcs->outBuff != NULL);
@@ -3058,8 +3989,7 @@ size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
switch(zcs->streamStage)
{
case zcss_init:
- /* call ZSTD_initCStream() first ! */
- return ERROR(init_missing);
+ RETURN_ERROR(init_missing, "call ZSTD_initCStream() first!");
case zcss_load:
if ( (flushMode == ZSTD_e_end)
@@ -3068,12 +3998,12 @@ size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
/* shortcut to compression pass directly into output buffer */
size_t const cSize = ZSTD_compressEnd(zcs,
op, oend-op, ip, iend-ip);
- DEBUGLOG(4, "ZSTD_compressEnd : %u", (U32)cSize);
- if (ZSTD_isError(cSize)) return cSize;
+ DEBUGLOG(4, "ZSTD_compressEnd : cSize=%u", (unsigned)cSize);
+ FORWARD_IF_ERROR(cSize);
ip = iend;
op += cSize;
zcs->frameEnded = 1;
- ZSTD_startNewCompression(zcs);
+ ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
someMoreWork = 0; break;
}
/* complete loading into inBuffer */
@@ -3110,14 +4040,14 @@ size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
zcs->inBuff + zcs->inToCompress, iSize) :
ZSTD_compressContinue(zcs, cDst, oSize,
zcs->inBuff + zcs->inToCompress, iSize);
- if (ZSTD_isError(cSize)) return cSize;
+ FORWARD_IF_ERROR(cSize);
zcs->frameEnded = lastBlock;
/* prepare next block */
zcs->inBuffTarget = zcs->inBuffPos + zcs->blockSize;
if (zcs->inBuffTarget > zcs->inBuffSize)
zcs->inBuffPos = 0, zcs->inBuffTarget = zcs->blockSize;
DEBUGLOG(5, "inBuffTarget:%u / inBuffSize:%u",
- (U32)zcs->inBuffTarget, (U32)zcs->inBuffSize);
+ (unsigned)zcs->inBuffTarget, (unsigned)zcs->inBuffSize);
if (!lastBlock)
assert(zcs->inBuffTarget <= zcs->inBuffSize);
zcs->inToCompress = zcs->inBuffPos;
@@ -3126,7 +4056,7 @@ size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
if (zcs->frameEnded) {
DEBUGLOG(5, "Frame completed directly in outBuffer");
someMoreWork = 0;
- ZSTD_startNewCompression(zcs);
+ ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
}
break;
}
@@ -3141,7 +4071,7 @@ size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
size_t const flushed = ZSTD_limitCopy(op, oend-op,
zcs->outBuff + zcs->outBuffFlushedSize, toFlush);
DEBUGLOG(5, "toFlush: %u into %u ==> flushed: %u",
- (U32)toFlush, (U32)(oend-op), (U32)flushed);
+ (unsigned)toFlush, (unsigned)(oend-op), (unsigned)flushed);
op += flushed;
zcs->outBuffFlushedSize += flushed;
if (toFlush!=flushed) {
@@ -3154,7 +4084,7 @@ size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
if (zcs->frameEnded) {
DEBUGLOG(5, "Frame completed on flush");
someMoreWork = 0;
- ZSTD_startNewCompression(zcs);
+ ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
break;
}
zcs->streamStage = zcss_load;
@@ -3169,63 +4099,67 @@ size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
input->pos = ip - istart;
output->pos = op - ostart;
if (zcs->frameEnded) return 0;
- { size_t hintInSize = zcs->inBuffTarget - zcs->inBuffPos;
- if (hintInSize==0) hintInSize = zcs->blockSize;
- return hintInSize;
+ return ZSTD_nextInputSizeHint(zcs);
+}
+
+static size_t ZSTD_nextInputSizeHint_MTorST(const ZSTD_CCtx* cctx)
+{
+#ifdef ZSTD_MULTITHREAD
+ if (cctx->appliedParams.nbWorkers >= 1) {
+ assert(cctx->mtctx != NULL);
+ return ZSTDMT_nextInputSizeHint(cctx->mtctx);
}
+#endif
+ return ZSTD_nextInputSizeHint(cctx);
+
}
size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
{
- /* check conditions */
- if (output->pos > output->size) return ERROR(GENERIC);
- if (input->pos > input->size) return ERROR(GENERIC);
-
- return ZSTD_compressStream_generic(zcs, output, input, ZSTD_e_continue);
+ FORWARD_IF_ERROR( ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue) );
+ return ZSTD_nextInputSizeHint_MTorST(zcs);
}
-size_t ZSTD_compress_generic (ZSTD_CCtx* cctx,
- ZSTD_outBuffer* output,
- ZSTD_inBuffer* input,
- ZSTD_EndDirective endOp)
+size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
+ ZSTD_outBuffer* output,
+ ZSTD_inBuffer* input,
+ ZSTD_EndDirective endOp)
{
- DEBUGLOG(5, "ZSTD_compress_generic, endOp=%u ", (U32)endOp);
+ DEBUGLOG(5, "ZSTD_compressStream2, endOp=%u ", (unsigned)endOp);
/* check conditions */
- if (output->pos > output->size) return ERROR(GENERIC);
- if (input->pos > input->size) return ERROR(GENERIC);
+ RETURN_ERROR_IF(output->pos > output->size, GENERIC);
+ RETURN_ERROR_IF(input->pos > input->size, GENERIC);
assert(cctx!=NULL);
/* transparent initialization stage */
if (cctx->streamStage == zcss_init) {
ZSTD_CCtx_params params = cctx->requestedParams;
ZSTD_prefixDict const prefixDict = cctx->prefixDict;
- memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); /* single usage */
- assert(prefixDict.dict==NULL || cctx->cdict==NULL); /* only one can be set */
- DEBUGLOG(4, "ZSTD_compress_generic : transparent init stage");
+ FORWARD_IF_ERROR( ZSTD_initLocalDict(cctx) ); /* Init the local dict if present. */
+ memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); /* single usage */
+ assert(prefixDict.dict==NULL || cctx->cdict==NULL); /* only one can be set */
+ DEBUGLOG(4, "ZSTD_compressStream2 : transparent init stage");
if (endOp == ZSTD_e_end) cctx->pledgedSrcSizePlusOne = input->size + 1; /* auto-fix pledgedSrcSize */
params.cParams = ZSTD_getCParamsFromCCtxParams(
&cctx->requestedParams, cctx->pledgedSrcSizePlusOne-1, 0 /*dictSize*/);
+
#ifdef ZSTD_MULTITHREAD
if ((cctx->pledgedSrcSizePlusOne-1) <= ZSTDMT_JOBSIZE_MIN) {
params.nbWorkers = 0; /* do not invoke multi-threading when src size is too small */
}
if (params.nbWorkers > 0) {
/* mt context creation */
- if (cctx->mtctx == NULL || (params.nbWorkers != ZSTDMT_getNbWorkers(cctx->mtctx))) {
- DEBUGLOG(4, "ZSTD_compress_generic: creating new mtctx for nbWorkers=%u",
+ if (cctx->mtctx == NULL) {
+ DEBUGLOG(4, "ZSTD_compressStream2: creating new mtctx for nbWorkers=%u",
params.nbWorkers);
- if (cctx->mtctx != NULL)
- DEBUGLOG(4, "ZSTD_compress_generic: previous nbWorkers was %u",
- ZSTDMT_getNbWorkers(cctx->mtctx));
- ZSTDMT_freeCCtx(cctx->mtctx);
cctx->mtctx = ZSTDMT_createCCtx_advanced(params.nbWorkers, cctx->customMem);
- if (cctx->mtctx == NULL) return ERROR(memory_allocation);
+ RETURN_ERROR_IF(cctx->mtctx == NULL, memory_allocation);
}
/* mt compression */
DEBUGLOG(4, "call ZSTDMT_initCStream_internal as nbWorkers=%u", params.nbWorkers);
- CHECK_F( ZSTDMT_initCStream_internal(
+ FORWARD_IF_ERROR( ZSTDMT_initCStream_internal(
cctx->mtctx,
prefixDict.dict, prefixDict.dictSize, ZSTD_dct_rawContent,
cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) );
@@ -3233,35 +4167,47 @@ size_t ZSTD_compress_generic (ZSTD_CCtx* cctx,
cctx->appliedParams.nbWorkers = params.nbWorkers;
} else
#endif
- { CHECK_F( ZSTD_resetCStream_internal(cctx,
+ { FORWARD_IF_ERROR( ZSTD_resetCStream_internal(cctx,
prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType,
cctx->cdict,
params, cctx->pledgedSrcSizePlusOne-1) );
assert(cctx->streamStage == zcss_load);
assert(cctx->appliedParams.nbWorkers == 0);
} }
+ /* end of transparent initialization stage */
/* compression stage */
#ifdef ZSTD_MULTITHREAD
if (cctx->appliedParams.nbWorkers > 0) {
+ int const forceMaxProgress = (endOp == ZSTD_e_flush || endOp == ZSTD_e_end);
+ size_t flushMin;
+ assert(forceMaxProgress || endOp == ZSTD_e_continue /* Protection for a new flush type */);
if (cctx->cParamsChanged) {
ZSTDMT_updateCParams_whileCompressing(cctx->mtctx, &cctx->requestedParams);
cctx->cParamsChanged = 0;
}
- { size_t const flushMin = ZSTDMT_compressStream_generic(cctx->mtctx, output, input, endOp);
+ do {
+ flushMin = ZSTDMT_compressStream_generic(cctx->mtctx, output, input, endOp);
if ( ZSTD_isError(flushMin)
|| (endOp == ZSTD_e_end && flushMin == 0) ) { /* compression completed */
- ZSTD_startNewCompression(cctx);
+ ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);
}
- return flushMin;
- } }
+ FORWARD_IF_ERROR(flushMin);
+ } while (forceMaxProgress && flushMin != 0 && output->pos < output->size);
+ DEBUGLOG(5, "completed ZSTD_compressStream2 delegating to ZSTDMT_compressStream_generic");
+ /* Either we don't require maximum forward progress, we've finished the
+ * flush, or we are out of output space.
+ */
+ assert(!forceMaxProgress || flushMin == 0 || output->pos == output->size);
+ return flushMin;
+ }
#endif
- CHECK_F( ZSTD_compressStream_generic(cctx, output, input, endOp) );
- DEBUGLOG(5, "completed ZSTD_compress_generic");
+ FORWARD_IF_ERROR( ZSTD_compressStream_generic(cctx, output, input, endOp) );
+ DEBUGLOG(5, "completed ZSTD_compressStream2");
return cctx->outBuffContentSize - cctx->outBuffFlushedSize; /* remaining to flush */
}
-size_t ZSTD_compress_generic_simpleArgs (
+size_t ZSTD_compressStream2_simpleArgs (
ZSTD_CCtx* cctx,
void* dst, size_t dstCapacity, size_t* dstPos,
const void* src, size_t srcSize, size_t* srcPos,
@@ -3269,13 +4215,33 @@ size_t ZSTD_compress_generic_simpleArgs (
{
ZSTD_outBuffer output = { dst, dstCapacity, *dstPos };
ZSTD_inBuffer input = { src, srcSize, *srcPos };
- /* ZSTD_compress_generic() will check validity of dstPos and srcPos */
- size_t const cErr = ZSTD_compress_generic(cctx, &output, &input, endOp);
+ /* ZSTD_compressStream2() will check validity of dstPos and srcPos */
+ size_t const cErr = ZSTD_compressStream2(cctx, &output, &input, endOp);
*dstPos = output.pos;
*srcPos = input.pos;
return cErr;
}
+size_t ZSTD_compress2(ZSTD_CCtx* cctx,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize)
+{
+ ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);
+ { size_t oPos = 0;
+ size_t iPos = 0;
+ size_t const result = ZSTD_compressStream2_simpleArgs(cctx,
+ dst, dstCapacity, &oPos,
+ src, srcSize, &iPos,
+ ZSTD_e_end);
+ FORWARD_IF_ERROR(result);
+ if (result != 0) { /* compression not completed, due to lack of output space */
+ assert(oPos == dstCapacity);
+ RETURN_ERROR(dstSize_tooSmall);
+ }
+ assert(iPos == srcSize); /* all input is expected consumed */
+ return oPos;
+ }
+}
/*====== Finalize ======*/
@@ -3284,21 +4250,21 @@ size_t ZSTD_compress_generic_simpleArgs (
size_t ZSTD_flushStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output)
{
ZSTD_inBuffer input = { NULL, 0, 0 };
- if (output->pos > output->size) return ERROR(GENERIC);
- CHECK_F( ZSTD_compressStream_generic(zcs, output, &input, ZSTD_e_flush) );
- return zcs->outBuffContentSize - zcs->outBuffFlushedSize; /* remaining to flush */
+ return ZSTD_compressStream2(zcs, output, &input, ZSTD_e_flush);
}
size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output)
{
ZSTD_inBuffer input = { NULL, 0, 0 };
- if (output->pos > output->size) return ERROR(GENERIC);
- CHECK_F( ZSTD_compressStream_generic(zcs, output, &input, ZSTD_e_end) );
+ size_t const remainingToFlush = ZSTD_compressStream2(zcs, output, &input, ZSTD_e_end);
+ FORWARD_IF_ERROR( remainingToFlush );
+ if (zcs->appliedParams.nbWorkers > 0) return remainingToFlush; /* minimal estimation */
+ /* single thread mode : attempt to calculate remaining to flush more precisely */
{ size_t const lastBlockSize = zcs->frameEnded ? 0 : ZSTD_BLOCKHEADERSIZE;
size_t const checksumSize = zcs->frameEnded ? 0 : zcs->appliedParams.fParams.checksumFlag * 4;
- size_t const toFlush = zcs->outBuffContentSize - zcs->outBuffFlushedSize + lastBlockSize + checksumSize;
- DEBUGLOG(4, "ZSTD_endStream : remaining to flush : %u", (U32)toFlush);
+ size_t const toFlush = remainingToFlush + lastBlockSize + checksumSize;
+ DEBUGLOG(4, "ZSTD_endStream : remaining to flush : %u", (unsigned)toFlush);
return toFlush;
}
}
@@ -3308,122 +4274,123 @@ size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output)
#define ZSTD_MAX_CLEVEL 22
int ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; }
+int ZSTD_minCLevel(void) { return (int)-ZSTD_TARGETLENGTH_MAX; }
static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = {
-{ /* "default" - guarantees a monotonically increasing memory budget */
+{ /* "default" - for any srcSize > 256 KB */
/* W, C, H, S, L, TL, strat */
{ 19, 12, 13, 1, 6, 1, ZSTD_fast }, /* base for negative levels */
- { 19, 13, 14, 1, 7, 1, ZSTD_fast }, /* level 1 */
- { 19, 15, 16, 1, 6, 1, ZSTD_fast }, /* level 2 */
- { 20, 16, 17, 1, 5, 8, ZSTD_dfast }, /* level 3 */
- { 20, 17, 18, 1, 5, 8, ZSTD_dfast }, /* level 4 */
- { 20, 17, 18, 2, 5, 16, ZSTD_greedy }, /* level 5 */
- { 21, 17, 19, 2, 5, 16, ZSTD_lazy }, /* level 6 */
- { 21, 18, 19, 3, 5, 16, ZSTD_lazy }, /* level 7 */
- { 21, 18, 20, 3, 5, 16, ZSTD_lazy2 }, /* level 8 */
- { 21, 19, 20, 3, 5, 16, ZSTD_lazy2 }, /* level 9 */
- { 21, 19, 21, 4, 5, 16, ZSTD_lazy2 }, /* level 10 */
- { 22, 20, 22, 4, 5, 16, ZSTD_lazy2 }, /* level 11 */
- { 22, 20, 22, 5, 5, 16, ZSTD_lazy2 }, /* level 12 */
- { 22, 21, 22, 4, 5, 32, ZSTD_btlazy2 }, /* level 13 */
- { 22, 21, 22, 5, 5, 32, ZSTD_btlazy2 }, /* level 14 */
- { 22, 22, 22, 6, 5, 32, ZSTD_btlazy2 }, /* level 15 */
- { 22, 21, 22, 4, 5, 48, ZSTD_btopt }, /* level 16 */
- { 23, 22, 22, 4, 4, 48, ZSTD_btopt }, /* level 17 */
- { 23, 22, 22, 5, 3, 64, ZSTD_btopt }, /* level 18 */
- { 23, 23, 22, 7, 3,128, ZSTD_btopt }, /* level 19 */
- { 25, 25, 23, 7, 3,128, ZSTD_btultra }, /* level 20 */
- { 26, 26, 24, 7, 3,256, ZSTD_btultra }, /* level 21 */
- { 27, 27, 25, 9, 3,512, ZSTD_btultra }, /* level 22 */
+ { 19, 13, 14, 1, 7, 0, ZSTD_fast }, /* level 1 */
+ { 20, 15, 16, 1, 6, 0, ZSTD_fast }, /* level 2 */
+ { 21, 16, 17, 1, 5, 1, ZSTD_dfast }, /* level 3 */
+ { 21, 18, 18, 1, 5, 1, ZSTD_dfast }, /* level 4 */
+ { 21, 18, 19, 2, 5, 2, ZSTD_greedy }, /* level 5 */
+ { 21, 19, 19, 3, 5, 4, ZSTD_greedy }, /* level 6 */
+ { 21, 19, 19, 3, 5, 8, ZSTD_lazy }, /* level 7 */
+ { 21, 19, 19, 3, 5, 16, ZSTD_lazy2 }, /* level 8 */
+ { 21, 19, 20, 4, 5, 16, ZSTD_lazy2 }, /* level 9 */
+ { 22, 20, 21, 4, 5, 16, ZSTD_lazy2 }, /* level 10 */
+ { 22, 21, 22, 4, 5, 16, ZSTD_lazy2 }, /* level 11 */
+ { 22, 21, 22, 5, 5, 16, ZSTD_lazy2 }, /* level 12 */
+ { 22, 21, 22, 5, 5, 32, ZSTD_btlazy2 }, /* level 13 */
+ { 22, 22, 23, 5, 5, 32, ZSTD_btlazy2 }, /* level 14 */
+ { 22, 23, 23, 6, 5, 32, ZSTD_btlazy2 }, /* level 15 */
+ { 22, 22, 22, 5, 5, 48, ZSTD_btopt }, /* level 16 */
+ { 23, 23, 22, 5, 4, 64, ZSTD_btopt }, /* level 17 */
+ { 23, 23, 22, 6, 3, 64, ZSTD_btultra }, /* level 18 */
+ { 23, 24, 22, 7, 3,256, ZSTD_btultra2}, /* level 19 */
+ { 25, 25, 23, 7, 3,256, ZSTD_btultra2}, /* level 20 */
+ { 26, 26, 24, 7, 3,512, ZSTD_btultra2}, /* level 21 */
+ { 27, 27, 25, 9, 3,999, ZSTD_btultra2}, /* level 22 */
},
{ /* for srcSize <= 256 KB */
/* W, C, H, S, L, T, strat */
{ 18, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */
- { 18, 13, 14, 1, 6, 1, ZSTD_fast }, /* level 1 */
- { 18, 14, 13, 1, 5, 8, ZSTD_dfast }, /* level 2 */
- { 18, 16, 15, 1, 5, 8, ZSTD_dfast }, /* level 3 */
- { 18, 15, 17, 1, 5, 8, ZSTD_greedy }, /* level 4.*/
- { 18, 16, 17, 4, 5, 8, ZSTD_greedy }, /* level 5.*/
- { 18, 16, 17, 3, 5, 8, ZSTD_lazy }, /* level 6.*/
- { 18, 17, 17, 4, 4, 8, ZSTD_lazy }, /* level 7 */
- { 18, 17, 17, 4, 4, 8, ZSTD_lazy2 }, /* level 8 */
- { 18, 17, 17, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */
- { 18, 17, 17, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */
- { 18, 18, 17, 6, 4, 8, ZSTD_lazy2 }, /* level 11.*/
- { 18, 18, 17, 5, 4, 8, ZSTD_btlazy2 }, /* level 12.*/
- { 18, 19, 17, 7, 4, 8, ZSTD_btlazy2 }, /* level 13 */
- { 18, 18, 18, 4, 4, 16, ZSTD_btopt }, /* level 14.*/
- { 18, 18, 18, 4, 3, 16, ZSTD_btopt }, /* level 15.*/
- { 18, 19, 18, 6, 3, 32, ZSTD_btopt }, /* level 16.*/
- { 18, 19, 18, 8, 3, 64, ZSTD_btopt }, /* level 17.*/
- { 18, 19, 18, 9, 3,128, ZSTD_btopt }, /* level 18.*/
- { 18, 19, 18, 10, 3,256, ZSTD_btopt }, /* level 19.*/
- { 18, 19, 18, 11, 3,512, ZSTD_btultra }, /* level 20.*/
- { 18, 19, 18, 12, 3,512, ZSTD_btultra }, /* level 21.*/
- { 18, 19, 18, 13, 3,512, ZSTD_btultra }, /* level 22.*/
+ { 18, 13, 14, 1, 6, 0, ZSTD_fast }, /* level 1 */
+ { 18, 14, 14, 1, 5, 1, ZSTD_dfast }, /* level 2 */
+ { 18, 16, 16, 1, 4, 1, ZSTD_dfast }, /* level 3 */
+ { 18, 16, 17, 2, 5, 2, ZSTD_greedy }, /* level 4.*/
+ { 18, 18, 18, 3, 5, 2, ZSTD_greedy }, /* level 5.*/
+ { 18, 18, 19, 3, 5, 4, ZSTD_lazy }, /* level 6.*/
+ { 18, 18, 19, 4, 4, 4, ZSTD_lazy }, /* level 7 */
+ { 18, 18, 19, 4, 4, 8, ZSTD_lazy2 }, /* level 8 */
+ { 18, 18, 19, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */
+ { 18, 18, 19, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */
+ { 18, 18, 19, 5, 4, 12, ZSTD_btlazy2 }, /* level 11.*/
+ { 18, 19, 19, 7, 4, 12, ZSTD_btlazy2 }, /* level 12.*/
+ { 18, 18, 19, 4, 4, 16, ZSTD_btopt }, /* level 13 */
+ { 18, 18, 19, 4, 3, 32, ZSTD_btopt }, /* level 14.*/
+ { 18, 18, 19, 6, 3,128, ZSTD_btopt }, /* level 15.*/
+ { 18, 19, 19, 6, 3,128, ZSTD_btultra }, /* level 16.*/
+ { 18, 19, 19, 8, 3,256, ZSTD_btultra }, /* level 17.*/
+ { 18, 19, 19, 6, 3,128, ZSTD_btultra2}, /* level 18.*/
+ { 18, 19, 19, 8, 3,256, ZSTD_btultra2}, /* level 19.*/
+ { 18, 19, 19, 10, 3,512, ZSTD_btultra2}, /* level 20.*/
+ { 18, 19, 19, 12, 3,512, ZSTD_btultra2}, /* level 21.*/
+ { 18, 19, 19, 13, 3,999, ZSTD_btultra2}, /* level 22.*/
},
{ /* for srcSize <= 128 KB */
/* W, C, H, S, L, T, strat */
- { 17, 12, 12, 1, 5, 1, ZSTD_fast }, /* level 0 - not used */
- { 17, 12, 13, 1, 6, 1, ZSTD_fast }, /* level 1 */
- { 17, 13, 16, 1, 5, 1, ZSTD_fast }, /* level 2 */
- { 17, 16, 16, 2, 5, 8, ZSTD_dfast }, /* level 3 */
- { 17, 13, 15, 3, 4, 8, ZSTD_greedy }, /* level 4 */
- { 17, 15, 17, 4, 4, 8, ZSTD_greedy }, /* level 5 */
- { 17, 16, 17, 3, 4, 8, ZSTD_lazy }, /* level 6 */
- { 17, 15, 17, 4, 4, 8, ZSTD_lazy2 }, /* level 7 */
+ { 17, 12, 12, 1, 5, 1, ZSTD_fast }, /* base for negative levels */
+ { 17, 12, 13, 1, 6, 0, ZSTD_fast }, /* level 1 */
+ { 17, 13, 15, 1, 5, 0, ZSTD_fast }, /* level 2 */
+ { 17, 15, 16, 2, 5, 1, ZSTD_dfast }, /* level 3 */
+ { 17, 17, 17, 2, 4, 1, ZSTD_dfast }, /* level 4 */
+ { 17, 16, 17, 3, 4, 2, ZSTD_greedy }, /* level 5 */
+ { 17, 17, 17, 3, 4, 4, ZSTD_lazy }, /* level 6 */
+ { 17, 17, 17, 3, 4, 8, ZSTD_lazy2 }, /* level 7 */
{ 17, 17, 17, 4, 4, 8, ZSTD_lazy2 }, /* level 8 */
{ 17, 17, 17, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */
{ 17, 17, 17, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */
- { 17, 17, 17, 7, 4, 8, ZSTD_lazy2 }, /* level 11 */
- { 17, 17, 17, 8, 4, 8, ZSTD_lazy2 }, /* level 12 */
- { 17, 18, 17, 6, 4, 8, ZSTD_btlazy2 }, /* level 13.*/
- { 17, 17, 17, 7, 3, 8, ZSTD_btopt }, /* level 14.*/
- { 17, 17, 17, 7, 3, 16, ZSTD_btopt }, /* level 15.*/
- { 17, 18, 17, 7, 3, 32, ZSTD_btopt }, /* level 16.*/
- { 17, 18, 17, 7, 3, 64, ZSTD_btopt }, /* level 17.*/
- { 17, 18, 17, 7, 3,256, ZSTD_btopt }, /* level 18.*/
- { 17, 18, 17, 8, 3,256, ZSTD_btopt }, /* level 19.*/
- { 17, 18, 17, 9, 3,256, ZSTD_btultra }, /* level 20.*/
- { 17, 18, 17, 10, 3,256, ZSTD_btultra }, /* level 21.*/
- { 17, 18, 17, 11, 3,512, ZSTD_btultra }, /* level 22.*/
+ { 17, 17, 17, 5, 4, 8, ZSTD_btlazy2 }, /* level 11 */
+ { 17, 18, 17, 7, 4, 12, ZSTD_btlazy2 }, /* level 12 */
+ { 17, 18, 17, 3, 4, 12, ZSTD_btopt }, /* level 13.*/
+ { 17, 18, 17, 4, 3, 32, ZSTD_btopt }, /* level 14.*/
+ { 17, 18, 17, 6, 3,256, ZSTD_btopt }, /* level 15.*/
+ { 17, 18, 17, 6, 3,128, ZSTD_btultra }, /* level 16.*/
+ { 17, 18, 17, 8, 3,256, ZSTD_btultra }, /* level 17.*/
+ { 17, 18, 17, 10, 3,512, ZSTD_btultra }, /* level 18.*/
+ { 17, 18, 17, 5, 3,256, ZSTD_btultra2}, /* level 19.*/
+ { 17, 18, 17, 7, 3,512, ZSTD_btultra2}, /* level 20.*/
+ { 17, 18, 17, 9, 3,512, ZSTD_btultra2}, /* level 21.*/
+ { 17, 18, 17, 11, 3,999, ZSTD_btultra2}, /* level 22.*/
},
{ /* for srcSize <= 16 KB */
/* W, C, H, S, L, T, strat */
{ 14, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */
- { 14, 14, 14, 1, 6, 1, ZSTD_fast }, /* level 1 */
- { 14, 14, 14, 1, 4, 1, ZSTD_fast }, /* level 2 */
- { 14, 14, 14, 1, 4, 6, ZSTD_dfast }, /* level 3.*/
- { 14, 14, 14, 4, 4, 6, ZSTD_greedy }, /* level 4.*/
- { 14, 14, 14, 3, 4, 6, ZSTD_lazy }, /* level 5.*/
- { 14, 14, 14, 4, 4, 6, ZSTD_lazy2 }, /* level 6 */
- { 14, 14, 14, 5, 4, 6, ZSTD_lazy2 }, /* level 7 */
- { 14, 14, 14, 6, 4, 6, ZSTD_lazy2 }, /* level 8.*/
- { 14, 15, 14, 6, 4, 6, ZSTD_btlazy2 }, /* level 9.*/
- { 14, 15, 14, 3, 3, 6, ZSTD_btopt }, /* level 10.*/
- { 14, 15, 14, 6, 3, 8, ZSTD_btopt }, /* level 11.*/
- { 14, 15, 14, 6, 3, 16, ZSTD_btopt }, /* level 12.*/
- { 14, 15, 14, 6, 3, 24, ZSTD_btopt }, /* level 13.*/
- { 14, 15, 15, 6, 3, 48, ZSTD_btopt }, /* level 14.*/
- { 14, 15, 15, 6, 3, 64, ZSTD_btopt }, /* level 15.*/
- { 14, 15, 15, 6, 3, 96, ZSTD_btopt }, /* level 16.*/
- { 14, 15, 15, 6, 3,128, ZSTD_btopt }, /* level 17.*/
- { 14, 15, 15, 6, 3,256, ZSTD_btopt }, /* level 18.*/
- { 14, 15, 15, 7, 3,256, ZSTD_btopt }, /* level 19.*/
- { 14, 15, 15, 8, 3,256, ZSTD_btultra }, /* level 20.*/
- { 14, 15, 15, 9, 3,256, ZSTD_btultra }, /* level 21.*/
- { 14, 15, 15, 10, 3,256, ZSTD_btultra }, /* level 22.*/
+ { 14, 14, 15, 1, 5, 0, ZSTD_fast }, /* level 1 */
+ { 14, 14, 15, 1, 4, 0, ZSTD_fast }, /* level 2 */
+ { 14, 14, 15, 2, 4, 1, ZSTD_dfast }, /* level 3 */
+ { 14, 14, 14, 4, 4, 2, ZSTD_greedy }, /* level 4 */
+ { 14, 14, 14, 3, 4, 4, ZSTD_lazy }, /* level 5.*/
+ { 14, 14, 14, 4, 4, 8, ZSTD_lazy2 }, /* level 6 */
+ { 14, 14, 14, 6, 4, 8, ZSTD_lazy2 }, /* level 7 */
+ { 14, 14, 14, 8, 4, 8, ZSTD_lazy2 }, /* level 8.*/
+ { 14, 15, 14, 5, 4, 8, ZSTD_btlazy2 }, /* level 9.*/
+ { 14, 15, 14, 9, 4, 8, ZSTD_btlazy2 }, /* level 10.*/
+ { 14, 15, 14, 3, 4, 12, ZSTD_btopt }, /* level 11.*/
+ { 14, 15, 14, 4, 3, 24, ZSTD_btopt }, /* level 12.*/
+ { 14, 15, 14, 5, 3, 32, ZSTD_btultra }, /* level 13.*/
+ { 14, 15, 15, 6, 3, 64, ZSTD_btultra }, /* level 14.*/
+ { 14, 15, 15, 7, 3,256, ZSTD_btultra }, /* level 15.*/
+ { 14, 15, 15, 5, 3, 48, ZSTD_btultra2}, /* level 16.*/
+ { 14, 15, 15, 6, 3,128, ZSTD_btultra2}, /* level 17.*/
+ { 14, 15, 15, 7, 3,256, ZSTD_btultra2}, /* level 18.*/
+ { 14, 15, 15, 8, 3,256, ZSTD_btultra2}, /* level 19.*/
+ { 14, 15, 15, 8, 3,512, ZSTD_btultra2}, /* level 20.*/
+ { 14, 15, 15, 9, 3,512, ZSTD_btultra2}, /* level 21.*/
+ { 14, 15, 15, 10, 3,999, ZSTD_btultra2}, /* level 22.*/
},
};
/*! ZSTD_getCParams() :
-* @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize.
-* Size values are optional, provide 0 if not known or unused */
+ * @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize.
+ * Size values are optional, provide 0 if not known or unused */
ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize)
{
size_t const addedSize = srcSizeHint ? 0 : 500;
- U64 const rSize = srcSizeHint+dictSize ? srcSizeHint+dictSize+addedSize : (U64)-1;
- U32 const tableID = (rSize <= 256 KB) + (rSize <= 128 KB) + (rSize <= 16 KB); /* intentional underflow for srcSizeHint == 0 */
+ U64 const rSize = srcSizeHint+dictSize ? srcSizeHint+dictSize+addedSize : ZSTD_CONTENTSIZE_UNKNOWN; /* intentional overflow for srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN */
+ U32 const tableID = (rSize <= 256 KB) + (rSize <= 128 KB) + (rSize <= 16 KB);
int row = compressionLevel;
DEBUGLOG(5, "ZSTD_getCParams (cLevel=%i)", compressionLevel);
if (compressionLevel == 0) row = ZSTD_CLEVEL_DEFAULT; /* 0 == default */
@@ -3431,13 +4398,14 @@ ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long l
if (compressionLevel > ZSTD_MAX_CLEVEL) row = ZSTD_MAX_CLEVEL;
{ ZSTD_compressionParameters cp = ZSTD_defaultCParameters[tableID][row];
if (compressionLevel < 0) cp.targetLength = (unsigned)(-compressionLevel); /* acceleration factor */
- return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize); }
-
+ return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize); /* refine parameters based on srcSize & dictSize */
+ }
}
/*! ZSTD_getParams() :
-* same as ZSTD_getCParams(), but @return a `ZSTD_parameters` object (instead of `ZSTD_compressionParameters`).
-* All fields of `ZSTD_frameParameters` are set to default (0) */
+ * same idea as ZSTD_getCParams()
+ * @return a `ZSTD_parameters` structure (instead of `ZSTD_compressionParameters`).
+ * Fields of `ZSTD_frameParameters` are set to default values */
ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) {
ZSTD_parameters params;
ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, srcSizeHint, dictSize);
diff --git a/thirdparty/zstd/compress/zstd_compress_internal.h b/thirdparty/zstd/compress/zstd_compress_internal.h
index 81f12ca6df..cc3cbb9da9 100644
--- a/thirdparty/zstd/compress/zstd_compress_internal.h
+++ b/thirdparty/zstd/compress/zstd_compress_internal.h
@@ -27,6 +27,7 @@
extern "C" {
#endif
+
/*-*************************************
* Constants
***************************************/
@@ -35,9 +36,10 @@ extern "C" {
#define ZSTD_DUBT_UNSORTED_MARK 1 /* For btlazy2 strategy, index 1 now means "unsorted".
It could be confused for a real successor at index "1", if sorted as larger than its predecessor.
It's not a big deal though : candidate will just be sorted again.
- Additionnally, candidate position 1 will be lost.
+ Additionally, candidate position 1 will be lost.
But candidate 1 cannot hide a large tree of candidates, so it's a minimal loss.
- The benefit is that ZSTD_DUBT_UNSORTED_MARK cannot be misdhandled after table re-use with a different strategy */
+ The benefit is that ZSTD_DUBT_UNSORTED_MARK cannot be mishandled after table re-use with a different strategy
+ Constant required by ZSTD_compressBlock_btlazy2() and ZSTD_reduceTable_internal() */
/*-*************************************
@@ -53,14 +55,30 @@ typedef struct ZSTD_prefixDict_s {
} ZSTD_prefixDict;
typedef struct {
- U32 hufCTable[HUF_CTABLE_SIZE_U32(255)];
+ void* dictBuffer;
+ void const* dict;
+ size_t dictSize;
+ ZSTD_dictContentType_e dictContentType;
+ ZSTD_CDict* cdict;
+} ZSTD_localDict;
+
+typedef struct {
+ U32 CTable[HUF_CTABLE_SIZE_U32(255)];
+ HUF_repeat repeatMode;
+} ZSTD_hufCTables_t;
+
+typedef struct {
FSE_CTable offcodeCTable[FSE_CTABLE_SIZE_U32(OffFSELog, MaxOff)];
FSE_CTable matchlengthCTable[FSE_CTABLE_SIZE_U32(MLFSELog, MaxML)];
FSE_CTable litlengthCTable[FSE_CTABLE_SIZE_U32(LLFSELog, MaxLL)];
- HUF_repeat hufCTable_repeatMode;
FSE_repeat offcode_repeatMode;
FSE_repeat matchlength_repeatMode;
FSE_repeat litlength_repeatMode;
+} ZSTD_fseCTables_t;
+
+typedef struct {
+ ZSTD_hufCTables_t huf;
+ ZSTD_fseCTables_t fse;
} ZSTD_entropyCTables_t;
typedef struct {
@@ -76,26 +94,28 @@ typedef struct {
U32 rep[ZSTD_REP_NUM];
} ZSTD_optimal_t;
+typedef enum { zop_dynamic=0, zop_predef } ZSTD_OptPrice_e;
+
typedef struct {
/* All tables are allocated inside cctx->workspace by ZSTD_resetCCtx_internal() */
- U32* litFreq; /* table of literals statistics, of size 256 */
- U32* litLengthFreq; /* table of litLength statistics, of size (MaxLL+1) */
- U32* matchLengthFreq; /* table of matchLength statistics, of size (MaxML+1) */
- U32* offCodeFreq; /* table of offCode statistics, of size (MaxOff+1) */
- ZSTD_match_t* matchTable; /* list of found matches, of size ZSTD_OPT_NUM+1 */
- ZSTD_optimal_t* priceTable; /* All positions tracked by optimal parser, of size ZSTD_OPT_NUM+1 */
+ unsigned* litFreq; /* table of literals statistics, of size 256 */
+ unsigned* litLengthFreq; /* table of litLength statistics, of size (MaxLL+1) */
+ unsigned* matchLengthFreq; /* table of matchLength statistics, of size (MaxML+1) */
+ unsigned* offCodeFreq; /* table of offCode statistics, of size (MaxOff+1) */
+ ZSTD_match_t* matchTable; /* list of found matches, of size ZSTD_OPT_NUM+1 */
+ ZSTD_optimal_t* priceTable; /* All positions tracked by optimal parser, of size ZSTD_OPT_NUM+1 */
U32 litSum; /* nb of literals */
U32 litLengthSum; /* nb of litLength codes */
U32 matchLengthSum; /* nb of matchLength codes */
U32 offCodeSum; /* nb of offset codes */
- /* begin updated by ZSTD_setLog2Prices */
- U32 log2litSum; /* pow2 to compare log2(litfreq) to */
- U32 log2litLengthSum; /* pow2 to compare log2(llfreq) to */
- U32 log2matchLengthSum; /* pow2 to compare log2(mlfreq) to */
- U32 log2offCodeSum; /* pow2 to compare log2(offreq) to */
- /* end : updated by ZSTD_setLog2Prices */
- U32 staticPrices; /* prices follow a pre-defined cost structure, statistics are irrelevant */
+ U32 litSumBasePrice; /* to compare to log2(litfreq) */
+ U32 litLengthSumBasePrice; /* to compare to log2(llfreq) */
+ U32 matchLengthSumBasePrice;/* to compare to log2(mlfreq) */
+ U32 offCodeSumBasePrice; /* to compare to log2(offreq) */
+ ZSTD_OptPrice_e priceType; /* prices can be determined dynamically, or follow a pre-defined cost structure */
+ const ZSTD_entropyCTables_t* symbolCosts; /* pre-calculated dictionary statistics */
+ ZSTD_literalCompressionMode_e literalCompressionMode;
} optState_t;
typedef struct {
@@ -111,17 +131,20 @@ typedef struct {
U32 lowLimit; /* below that point, no more data */
} ZSTD_window_t;
-typedef struct {
- ZSTD_window_t window; /* State for window round buffer management */
- U32 loadedDictEnd; /* index of end of dictionary */
- U32 nextToUpdate; /* index from which to continue table update */
- U32 nextToUpdate3; /* index from which to continue table update */
- U32 hashLog3; /* dispatch table : larger == faster, more memory */
+typedef struct ZSTD_matchState_t ZSTD_matchState_t;
+struct ZSTD_matchState_t {
+ ZSTD_window_t window; /* State for window round buffer management */
+ U32 loadedDictEnd; /* index of end of dictionary */
+ U32 nextToUpdate; /* index from which to continue table update */
+ U32 nextToUpdate3; /* index from which to continue table update */
+ U32 hashLog3; /* dispatch table : larger == faster, more memory */
U32* hashTable;
U32* hashTable3;
U32* chainTable;
optState_t opt; /* optimal parser state */
-} ZSTD_matchState_t;
+ const ZSTD_matchState_t * dictMatchState;
+ ZSTD_compressionParameters cParams;
+};
typedef struct {
ZSTD_compressedBlockState_t* prevCBlock;
@@ -147,7 +170,7 @@ typedef struct {
U32 hashLog; /* Log size of hashTable */
U32 bucketSizeLog; /* Log bucket size for collision resolution, at most 8 */
U32 minMatchLength; /* Minimum match length */
- U32 hashEveryLog; /* Log number of entries to skip */
+ U32 hashRateLog; /* Log number of entries to skip */
U32 windowLog; /* Window log for the LDM */
} ldmParams_t;
@@ -161,7 +184,7 @@ typedef struct {
rawSeq* seq; /* The start of the sequences */
size_t pos; /* The position where reading stopped. <= size. */
size_t size; /* The number of sequences. <= capacity. */
- size_t capacity; /* The capacity of the `seq` pointer */
+ size_t capacity; /* The capacity starting from `seq` pointer */
} rawSeqStore_t;
struct ZSTD_CCtx_params_s {
@@ -170,14 +193,17 @@ struct ZSTD_CCtx_params_s {
ZSTD_frameParameters fParams;
int compressionLevel;
- int disableLiteralCompression;
int forceWindow; /* force back-references to respect limit of
* 1<<wLog, even for dictionary */
+ ZSTD_dictAttachPref_e attachDictPref;
+ ZSTD_literalCompressionMode_e literalCompressionMode;
+
/* Multithreading: used to pass parameters to mtctx */
- unsigned nbWorkers;
- unsigned jobSize;
- unsigned overlapSizeLog;
+ int nbWorkers;
+ size_t jobSize;
+ int overlapLog;
+ int rsyncable;
/* Long distance matching parameters */
ldmParams_t ldmParams;
@@ -193,6 +219,8 @@ struct ZSTD_CCtx_s {
ZSTD_CCtx_params requestedParams;
ZSTD_CCtx_params appliedParams;
U32 dictID;
+
+ int workSpaceOversizedDuration;
void* workSpace;
size_t workSpaceSize;
size_t blockSize;
@@ -225,7 +253,7 @@ struct ZSTD_CCtx_s {
U32 frameEnded;
/* Dictionary */
- ZSTD_CDict* cdictLocal;
+ ZSTD_localDict localDict;
const ZSTD_CDict* cdict;
ZSTD_prefixDict prefixDict; /* single-usage dictionary */
@@ -235,11 +263,15 @@ struct ZSTD_CCtx_s {
#endif
};
+typedef enum { ZSTD_dtlm_fast, ZSTD_dtlm_full } ZSTD_dictTableLoadMethod_e;
+
+typedef enum { ZSTD_noDict = 0, ZSTD_extDict = 1, ZSTD_dictMatchState = 2 } ZSTD_dictMode_e;
+
typedef size_t (*ZSTD_blockCompressor) (
ZSTD_matchState_t* bs, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
-ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, int extDict);
+ void const* src, size_t srcSize);
+ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_dictMode_e dictMode);
MEM_STATIC U32 ZSTD_LLcode(U32 litLength)
@@ -280,16 +312,18 @@ MEM_STATIC U32 ZSTD_MLcode(U32 mlBase)
*/
MEM_STATIC void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const void* literals, U32 offsetCode, size_t mlBase)
{
-#if defined(ZSTD_DEBUG) && (ZSTD_DEBUG >= 6)
+#if defined(DEBUGLEVEL) && (DEBUGLEVEL >= 6)
static const BYTE* g_start = NULL;
if (g_start==NULL) g_start = (const BYTE*)literals; /* note : index only works for compression within a single segment */
{ U32 const pos = (U32)((const BYTE*)literals - g_start);
- DEBUGLOG(6, "Cpos%7u :%3u literals, match%3u bytes at dist.code%7u",
+ DEBUGLOG(6, "Cpos%7u :%3u literals, match%4u bytes at offCode%7u",
pos, (U32)litLength, (U32)mlBase+MINMATCH, (U32)offsetCode);
}
#endif
+ assert((size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart) < seqStorePtr->maxNbSeq);
/* copy Literals */
- assert(seqStorePtr->lit + litLength <= seqStorePtr->litStart + 128 KB);
+ assert(seqStorePtr->maxNbLit <= 128 KB);
+ assert(seqStorePtr->lit + litLength <= seqStorePtr->litStart + seqStorePtr->maxNbLit);
ZSTD_wildcopy(seqStorePtr->lit, literals, litLength);
seqStorePtr->lit += litLength;
@@ -420,6 +454,11 @@ ZSTD_count_2segments(const BYTE* ip, const BYTE* match,
const BYTE* const vEnd = MIN( ip + (mEnd - match), iEnd);
size_t const matchLength = ZSTD_count(ip, match, vEnd);
if (match + matchLength != mEnd) return matchLength;
+ DEBUGLOG(7, "ZSTD_count_2segments: found a 2-parts match (current length==%zu)", matchLength);
+ DEBUGLOG(7, "distance from match beginning to end dictionary = %zi", mEnd - match);
+ DEBUGLOG(7, "distance from current pos to end buffer = %zi", iEnd - ip);
+ DEBUGLOG(7, "next byte : ip==%02X, istart==%02X", ip[matchLength], *iStart);
+ DEBUGLOG(7, "final match length = %zu", matchLength + ZSTD_count(ip+matchLength, iStart, iEnd));
return matchLength + ZSTD_count(ip+matchLength, iStart, iEnd);
}
@@ -464,6 +503,64 @@ MEM_STATIC size_t ZSTD_hashPtr(const void* p, U32 hBits, U32 mls)
}
}
+/** ZSTD_ipow() :
+ * Return base^exponent.
+ */
+static U64 ZSTD_ipow(U64 base, U64 exponent)
+{
+ U64 power = 1;
+ while (exponent) {
+ if (exponent & 1) power *= base;
+ exponent >>= 1;
+ base *= base;
+ }
+ return power;
+}
+
+#define ZSTD_ROLL_HASH_CHAR_OFFSET 10
+
+/** ZSTD_rollingHash_append() :
+ * Add the buffer to the hash value.
+ */
+static U64 ZSTD_rollingHash_append(U64 hash, void const* buf, size_t size)
+{
+ BYTE const* istart = (BYTE const*)buf;
+ size_t pos;
+ for (pos = 0; pos < size; ++pos) {
+ hash *= prime8bytes;
+ hash += istart[pos] + ZSTD_ROLL_HASH_CHAR_OFFSET;
+ }
+ return hash;
+}
+
+/** ZSTD_rollingHash_compute() :
+ * Compute the rolling hash value of the buffer.
+ */
+MEM_STATIC U64 ZSTD_rollingHash_compute(void const* buf, size_t size)
+{
+ return ZSTD_rollingHash_append(0, buf, size);
+}
+
+/** ZSTD_rollingHash_primePower() :
+ * Compute the primePower to be passed to ZSTD_rollingHash_rotate() for a hash
+ * over a window of length bytes.
+ */
+MEM_STATIC U64 ZSTD_rollingHash_primePower(U32 length)
+{
+ return ZSTD_ipow(prime8bytes, length - 1);
+}
+
+/** ZSTD_rollingHash_rotate() :
+ * Rotate the rolling hash by one byte.
+ */
+MEM_STATIC U64 ZSTD_rollingHash_rotate(U64 hash, BYTE toRemove, BYTE toAdd, U64 primePower)
+{
+ hash -= (toRemove + ZSTD_ROLL_HASH_CHAR_OFFSET) * primePower;
+ hash *= prime8bytes;
+ hash += toAdd + ZSTD_ROLL_HASH_CHAR_OFFSET;
+ return hash;
+}
+
/*-*************************************
* Round buffer management
***************************************/
@@ -497,6 +594,20 @@ MEM_STATIC U32 ZSTD_window_hasExtDict(ZSTD_window_t const window)
}
/**
+ * ZSTD_matchState_dictMode():
+ * Inspects the provided matchState and figures out what dictMode should be
+ * passed to the compressor.
+ */
+MEM_STATIC ZSTD_dictMode_e ZSTD_matchState_dictMode(const ZSTD_matchState_t *ms)
+{
+ return ZSTD_window_hasExtDict(ms->window) ?
+ ZSTD_extDict :
+ ms->dictMatchState != NULL ?
+ ZSTD_dictMatchState :
+ ZSTD_noDict;
+}
+
+/**
* ZSTD_window_needOverflowCorrection():
* Returns non-zero if the indices are getting too large and need overflow
* protection.
@@ -563,31 +674,44 @@ MEM_STATIC U32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog,
* ZSTD_window_enforceMaxDist():
* Updates lowLimit so that:
* (srcEnd - base) - lowLimit == maxDist + loadedDictEnd
+ *
* This allows a simple check that index >= lowLimit to see if index is valid.
* This must be called before a block compression call, with srcEnd as the block
* source end.
+ *
* If loadedDictEndPtr is not NULL, we set it to zero once we update lowLimit.
* This is because dictionaries are allowed to be referenced as long as the last
* byte of the dictionary is in the window, but once they are out of range,
* they cannot be referenced. If loadedDictEndPtr is NULL, we use
* loadedDictEnd == 0.
+ *
+ * In normal dict mode, the dict is between lowLimit and dictLimit. In
+ * dictMatchState mode, lowLimit and dictLimit are the same, and the dictionary
+ * is below them. forceWindow and dictMatchState are therefore incompatible.
*/
-MEM_STATIC void ZSTD_window_enforceMaxDist(ZSTD_window_t* window,
- void const* srcEnd, U32 maxDist,
- U32* loadedDictEndPtr)
+MEM_STATIC void
+ZSTD_window_enforceMaxDist(ZSTD_window_t* window,
+ void const* srcEnd,
+ U32 maxDist,
+ U32* loadedDictEndPtr,
+ const ZSTD_matchState_t** dictMatchStatePtr)
{
- U32 const current = (U32)((BYTE const*)srcEnd - window->base);
- U32 loadedDictEnd = loadedDictEndPtr != NULL ? *loadedDictEndPtr : 0;
- if (current > maxDist + loadedDictEnd) {
- U32 const newLowLimit = current - maxDist;
+ U32 const blockEndIdx = (U32)((BYTE const*)srcEnd - window->base);
+ U32 loadedDictEnd = (loadedDictEndPtr != NULL) ? *loadedDictEndPtr : 0;
+ DEBUGLOG(5, "ZSTD_window_enforceMaxDist: blockEndIdx=%u, maxDist=%u",
+ (unsigned)blockEndIdx, (unsigned)maxDist);
+ if (blockEndIdx > maxDist + loadedDictEnd) {
+ U32 const newLowLimit = blockEndIdx - maxDist;
if (window->lowLimit < newLowLimit) window->lowLimit = newLowLimit;
if (window->dictLimit < window->lowLimit) {
- DEBUGLOG(5, "Update dictLimit from %u to %u", window->dictLimit,
- window->lowLimit);
+ DEBUGLOG(5, "Update dictLimit to match lowLimit, from %u to %u",
+ (unsigned)window->dictLimit, (unsigned)window->lowLimit);
window->dictLimit = window->lowLimit;
}
if (loadedDictEndPtr)
*loadedDictEndPtr = 0;
+ if (dictMatchStatePtr)
+ *dictMatchStatePtr = NULL;
}
}
@@ -603,12 +727,12 @@ MEM_STATIC U32 ZSTD_window_update(ZSTD_window_t* window,
{
BYTE const* const ip = (BYTE const*)src;
U32 contiguous = 1;
+ DEBUGLOG(5, "ZSTD_window_update");
/* Check if blocks follow each other */
if (src != window->nextSrc) {
/* not contiguous */
size_t const distanceFromBase = (size_t)(window->nextSrc - window->base);
- DEBUGLOG(5, "Non contiguous blocks, new segment starts at %u",
- window->dictLimit);
+ DEBUGLOG(5, "Non contiguous blocks, new segment starts at %u", window->dictLimit);
window->lowLimit = window->dictLimit;
assert(distanceFromBase == (size_t)(U32)distanceFromBase); /* should never overflow */
window->dictLimit = (U32)distanceFromBase;
@@ -625,10 +749,44 @@ MEM_STATIC U32 ZSTD_window_update(ZSTD_window_t* window,
ptrdiff_t const highInputIdx = (ip + srcSize) - window->dictBase;
U32 const lowLimitMax = (highInputIdx > (ptrdiff_t)window->dictLimit) ? window->dictLimit : (U32)highInputIdx;
window->lowLimit = lowLimitMax;
+ DEBUGLOG(5, "Overlapping extDict and input : new lowLimit = %u", window->lowLimit);
}
return contiguous;
}
+
+/* debug functions */
+#if (DEBUGLEVEL>=2)
+
+MEM_STATIC double ZSTD_fWeight(U32 rawStat)
+{
+ U32 const fp_accuracy = 8;
+ U32 const fp_multiplier = (1 << fp_accuracy);
+ U32 const newStat = rawStat + 1;
+ U32 const hb = ZSTD_highbit32(newStat);
+ U32 const BWeight = hb * fp_multiplier;
+ U32 const FWeight = (newStat << fp_accuracy) >> hb;
+ U32 const weight = BWeight + FWeight;
+ assert(hb + fp_accuracy < 31);
+ return (double)weight / fp_multiplier;
+}
+
+/* display a table content,
+ * listing each element, its frequency, and its predicted bit cost */
+MEM_STATIC void ZSTD_debugTable(const U32* table, U32 max)
+{
+ unsigned u, sum;
+ for (u=0, sum=0; u<=max; u++) sum += table[u];
+ DEBUGLOG(2, "total nb elts: %u", sum);
+ for (u=0; u<=max; u++) {
+ DEBUGLOG(2, "%2u: %5u (%.2f)",
+ u, table[u], ZSTD_fWeight(sum) - ZSTD_fWeight(table[u]) );
+ }
+}
+
+#endif
+
+
#if defined (__cplusplus)
}
#endif
@@ -640,7 +798,7 @@ MEM_STATIC U32 ZSTD_window_update(ZSTD_window_t* window,
* ============================================================== */
/* ZSTD_getCParamsFromCCtxParams() :
- * cParams are built depending on compressionLevel, src size hints,
+ * cParams are built depending on compressionLevel, src size hints,
* LDM and manually set compression parameters.
*/
ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
@@ -656,12 +814,7 @@ size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
const ZSTD_CDict* cdict,
ZSTD_CCtx_params params, unsigned long long pledgedSrcSize);
-/*! ZSTD_compressStream_generic() :
- * Private use only. To be called from zstdmt_compress.c in single-thread mode. */
-size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
- ZSTD_outBuffer* output,
- ZSTD_inBuffer* input,
- ZSTD_EndDirective const flushMode);
+void ZSTD_resetSeqStore(seqStore_t* ssPtr);
/*! ZSTD_getCParamsFromCDict() :
* as the name implies */
@@ -672,6 +825,7 @@ ZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict);
size_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx,
const void* dict, size_t dictSize,
ZSTD_dictContentType_e dictContentType,
+ ZSTD_dictTableLoadMethod_e dtlm,
const ZSTD_CDict* cdict,
ZSTD_CCtx_params params,
unsigned long long pledgedSrcSize);
@@ -688,7 +842,7 @@ size_t ZSTD_compress_advanced_internal(ZSTD_CCtx* cctx,
/* ZSTD_writeLastEmptyBlock() :
* output an empty Block with end-of-frame mark to complete a frame
* @return : size of data written into `dst` (== ZSTD_blockHeaderSize (defined in zstd_internal.h))
- * or an error code if `dstCapcity` is too small (<ZSTD_blockHeaderSize)
+ * or an error code if `dstCapacity` is too small (<ZSTD_blockHeaderSize)
*/
size_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity);
diff --git a/thirdparty/zstd/compress/zstd_double_fast.c b/thirdparty/zstd/compress/zstd_double_fast.c
index 86e6b39621..47faf6d641 100644
--- a/thirdparty/zstd/compress/zstd_double_fast.c
+++ b/thirdparty/zstd/compress/zstd_double_fast.c
@@ -13,12 +13,12 @@
void ZSTD_fillDoubleHashTable(ZSTD_matchState_t* ms,
- ZSTD_compressionParameters const* cParams,
- void const* end)
+ void const* end, ZSTD_dictTableLoadMethod_e dtlm)
{
+ const ZSTD_compressionParameters* const cParams = &ms->cParams;
U32* const hashLarge = ms->hashTable;
U32 const hBitsL = cParams->hashLog;
- U32 const mls = cParams->searchLength;
+ U32 const mls = cParams->minMatch;
U32* const hashSmall = ms->chainTable;
U32 const hBitsS = cParams->chainLog;
const BYTE* const base = ms->window.base;
@@ -40,6 +40,9 @@ void ZSTD_fillDoubleHashTable(ZSTD_matchState_t* ms,
hashSmall[smHash] = current + i;
if (i == 0 || hashLarge[lgHash] == 0)
hashLarge[lgHash] = current + i;
+ /* Only load extra positions for ZSTD_dtlm_full */
+ if (dtlm == ZSTD_dtlm_fast)
+ break;
}
}
}
@@ -48,9 +51,10 @@ void ZSTD_fillDoubleHashTable(ZSTD_matchState_t* ms,
FORCE_INLINE_TEMPLATE
size_t ZSTD_compressBlock_doubleFast_generic(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize,
- U32 const mls /* template */)
+ void const* src, size_t srcSize,
+ U32 const mls /* template */, ZSTD_dictMode_e const dictMode)
{
+ ZSTD_compressionParameters const* cParams = &ms->cParams;
U32* const hashLong = ms->hashTable;
const U32 hBitsL = cParams->hashLog;
U32* const hashSmall = ms->chainTable;
@@ -59,70 +63,188 @@ size_t ZSTD_compressBlock_doubleFast_generic(
const BYTE* const istart = (const BYTE*)src;
const BYTE* ip = istart;
const BYTE* anchor = istart;
- const U32 lowestIndex = ms->window.dictLimit;
- const BYTE* const lowest = base + lowestIndex;
+ const U32 prefixLowestIndex = ms->window.dictLimit;
+ const BYTE* const prefixLowest = base + prefixLowestIndex;
const BYTE* const iend = istart + srcSize;
const BYTE* const ilimit = iend - HASH_READ_SIZE;
U32 offset_1=rep[0], offset_2=rep[1];
U32 offsetSaved = 0;
+ const ZSTD_matchState_t* const dms = ms->dictMatchState;
+ const ZSTD_compressionParameters* const dictCParams =
+ dictMode == ZSTD_dictMatchState ?
+ &dms->cParams : NULL;
+ const U32* const dictHashLong = dictMode == ZSTD_dictMatchState ?
+ dms->hashTable : NULL;
+ const U32* const dictHashSmall = dictMode == ZSTD_dictMatchState ?
+ dms->chainTable : NULL;
+ const U32 dictStartIndex = dictMode == ZSTD_dictMatchState ?
+ dms->window.dictLimit : 0;
+ const BYTE* const dictBase = dictMode == ZSTD_dictMatchState ?
+ dms->window.base : NULL;
+ const BYTE* const dictStart = dictMode == ZSTD_dictMatchState ?
+ dictBase + dictStartIndex : NULL;
+ const BYTE* const dictEnd = dictMode == ZSTD_dictMatchState ?
+ dms->window.nextSrc : NULL;
+ const U32 dictIndexDelta = dictMode == ZSTD_dictMatchState ?
+ prefixLowestIndex - (U32)(dictEnd - dictBase) :
+ 0;
+ const U32 dictHBitsL = dictMode == ZSTD_dictMatchState ?
+ dictCParams->hashLog : hBitsL;
+ const U32 dictHBitsS = dictMode == ZSTD_dictMatchState ?
+ dictCParams->chainLog : hBitsS;
+ const U32 dictAndPrefixLength = (U32)(ip - prefixLowest + dictEnd - dictStart);
+
+ assert(dictMode == ZSTD_noDict || dictMode == ZSTD_dictMatchState);
+
/* init */
- ip += (ip==lowest);
- { U32 const maxRep = (U32)(ip-lowest);
+ ip += (dictAndPrefixLength == 0);
+ if (dictMode == ZSTD_noDict) {
+ U32 const maxRep = (U32)(ip - prefixLowest);
if (offset_2 > maxRep) offsetSaved = offset_2, offset_2 = 0;
if (offset_1 > maxRep) offsetSaved = offset_1, offset_1 = 0;
}
+ if (dictMode == ZSTD_dictMatchState) {
+ /* dictMatchState repCode checks don't currently handle repCode == 0
+ * disabling. */
+ assert(offset_1 <= dictAndPrefixLength);
+ assert(offset_2 <= dictAndPrefixLength);
+ }
/* Main Search Loop */
while (ip < ilimit) { /* < instead of <=, because repcode check at (ip+1) */
size_t mLength;
+ U32 offset;
size_t const h2 = ZSTD_hashPtr(ip, hBitsL, 8);
size_t const h = ZSTD_hashPtr(ip, hBitsS, mls);
+ size_t const dictHL = ZSTD_hashPtr(ip, dictHBitsL, 8);
+ size_t const dictHS = ZSTD_hashPtr(ip, dictHBitsS, mls);
U32 const current = (U32)(ip-base);
U32 const matchIndexL = hashLong[h2];
- U32 const matchIndexS = hashSmall[h];
+ U32 matchIndexS = hashSmall[h];
const BYTE* matchLong = base + matchIndexL;
const BYTE* match = base + matchIndexS;
+ const U32 repIndex = current + 1 - offset_1;
+ const BYTE* repMatch = (dictMode == ZSTD_dictMatchState
+ && repIndex < prefixLowestIndex) ?
+ dictBase + (repIndex - dictIndexDelta) :
+ base + repIndex;
hashLong[h2] = hashSmall[h] = current; /* update hash tables */
- assert(offset_1 <= current); /* supposed guaranteed by construction */
- if ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1))) {
- /* favor repcode */
+ /* check dictMatchState repcode */
+ if (dictMode == ZSTD_dictMatchState
+ && ((U32)((prefixLowestIndex-1) - repIndex) >= 3 /* intentional underflow */)
+ && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
+ const BYTE* repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend;
+ mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixLowest) + 4;
+ ip++;
+ ZSTD_storeSeq(seqStore, ip-anchor, anchor, 0, mLength-MINMATCH);
+ goto _match_stored;
+ }
+
+ /* check noDict repcode */
+ if ( dictMode == ZSTD_noDict
+ && ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1)))) {
mLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;
ip++;
ZSTD_storeSeq(seqStore, ip-anchor, anchor, 0, mLength-MINMATCH);
- } else {
- U32 offset;
- if ( (matchIndexL > lowestIndex) && (MEM_read64(matchLong) == MEM_read64(ip)) ) {
+ goto _match_stored;
+ }
+
+ if (matchIndexL > prefixLowestIndex) {
+ /* check prefix long match */
+ if (MEM_read64(matchLong) == MEM_read64(ip)) {
mLength = ZSTD_count(ip+8, matchLong+8, iend) + 8;
offset = (U32)(ip-matchLong);
- while (((ip>anchor) & (matchLong>lowest)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } /* catch up */
- } else if ( (matchIndexS > lowestIndex) && (MEM_read32(match) == MEM_read32(ip)) ) {
- size_t const hl3 = ZSTD_hashPtr(ip+1, hBitsL, 8);
- U32 const matchIndexL3 = hashLong[hl3];
- const BYTE* matchL3 = base + matchIndexL3;
- hashLong[hl3] = current + 1;
- if ( (matchIndexL3 > lowestIndex) && (MEM_read64(matchL3) == MEM_read64(ip+1)) ) {
+ while (((ip>anchor) & (matchLong>prefixLowest)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } /* catch up */
+ goto _match_found;
+ }
+ } else if (dictMode == ZSTD_dictMatchState) {
+ /* check dictMatchState long match */
+ U32 const dictMatchIndexL = dictHashLong[dictHL];
+ const BYTE* dictMatchL = dictBase + dictMatchIndexL;
+ assert(dictMatchL < dictEnd);
+
+ if (dictMatchL > dictStart && MEM_read64(dictMatchL) == MEM_read64(ip)) {
+ mLength = ZSTD_count_2segments(ip+8, dictMatchL+8, iend, dictEnd, prefixLowest) + 8;
+ offset = (U32)(current - dictMatchIndexL - dictIndexDelta);
+ while (((ip>anchor) & (dictMatchL>dictStart)) && (ip[-1] == dictMatchL[-1])) { ip--; dictMatchL--; mLength++; } /* catch up */
+ goto _match_found;
+ }
+ }
+
+ if (matchIndexS > prefixLowestIndex) {
+ /* check prefix short match */
+ if (MEM_read32(match) == MEM_read32(ip)) {
+ goto _search_next_long;
+ }
+ } else if (dictMode == ZSTD_dictMatchState) {
+ /* check dictMatchState short match */
+ U32 const dictMatchIndexS = dictHashSmall[dictHS];
+ match = dictBase + dictMatchIndexS;
+ matchIndexS = dictMatchIndexS + dictIndexDelta;
+
+ if (match > dictStart && MEM_read32(match) == MEM_read32(ip)) {
+ goto _search_next_long;
+ }
+ }
+
+ ip += ((ip-anchor) >> kSearchStrength) + 1;
+ continue;
+
+_search_next_long:
+
+ {
+ size_t const hl3 = ZSTD_hashPtr(ip+1, hBitsL, 8);
+ size_t const dictHLNext = ZSTD_hashPtr(ip+1, dictHBitsL, 8);
+ U32 const matchIndexL3 = hashLong[hl3];
+ const BYTE* matchL3 = base + matchIndexL3;
+ hashLong[hl3] = current + 1;
+
+ /* check prefix long +1 match */
+ if (matchIndexL3 > prefixLowestIndex) {
+ if (MEM_read64(matchL3) == MEM_read64(ip+1)) {
mLength = ZSTD_count(ip+9, matchL3+8, iend) + 8;
ip++;
offset = (U32)(ip-matchL3);
- while (((ip>anchor) & (matchL3>lowest)) && (ip[-1] == matchL3[-1])) { ip--; matchL3--; mLength++; } /* catch up */
- } else {
- mLength = ZSTD_count(ip+4, match+4, iend) + 4;
- offset = (U32)(ip-match);
- while (((ip>anchor) & (match>lowest)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
+ while (((ip>anchor) & (matchL3>prefixLowest)) && (ip[-1] == matchL3[-1])) { ip--; matchL3--; mLength++; } /* catch up */
+ goto _match_found;
+ }
+ } else if (dictMode == ZSTD_dictMatchState) {
+ /* check dict long +1 match */
+ U32 const dictMatchIndexL3 = dictHashLong[dictHLNext];
+ const BYTE* dictMatchL3 = dictBase + dictMatchIndexL3;
+ assert(dictMatchL3 < dictEnd);
+ if (dictMatchL3 > dictStart && MEM_read64(dictMatchL3) == MEM_read64(ip+1)) {
+ mLength = ZSTD_count_2segments(ip+1+8, dictMatchL3+8, iend, dictEnd, prefixLowest) + 8;
+ ip++;
+ offset = (U32)(current + 1 - dictMatchIndexL3 - dictIndexDelta);
+ while (((ip>anchor) & (dictMatchL3>dictStart)) && (ip[-1] == dictMatchL3[-1])) { ip--; dictMatchL3--; mLength++; } /* catch up */
+ goto _match_found;
}
- } else {
- ip += ((ip-anchor) >> kSearchStrength) + 1;
- continue;
}
+ }
- offset_2 = offset_1;
- offset_1 = offset;
-
- ZSTD_storeSeq(seqStore, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
+ /* if no long +1 match, explore the short match we found */
+ if (dictMode == ZSTD_dictMatchState && matchIndexS < prefixLowestIndex) {
+ mLength = ZSTD_count_2segments(ip+4, match+4, iend, dictEnd, prefixLowest) + 4;
+ offset = (U32)(current - matchIndexS);
+ while (((ip>anchor) & (match>dictStart)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
+ } else {
+ mLength = ZSTD_count(ip+4, match+4, iend) + 4;
+ offset = (U32)(ip - match);
+ while (((ip>anchor) & (match>prefixLowest)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
}
+ /* fall-through */
+
+_match_found:
+ offset_2 = offset_1;
+ offset_1 = offset;
+
+ ZSTD_storeSeq(seqStore, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
+
+_match_stored:
/* match found */
ip += mLength;
anchor = ip;
@@ -135,19 +257,44 @@ size_t ZSTD_compressBlock_doubleFast_generic(
hashSmall[ZSTD_hashPtr(ip-2, hBitsS, mls)] = (U32)(ip-2-base);
/* check immediate repcode */
- while ( (ip <= ilimit)
- && ( (offset_2>0)
- & (MEM_read32(ip) == MEM_read32(ip - offset_2)) )) {
- /* store sequence */
- size_t const rLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;
- { U32 const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; } /* swap offset_2 <=> offset_1 */
- hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = (U32)(ip-base);
- hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = (U32)(ip-base);
- ZSTD_storeSeq(seqStore, 0, anchor, 0, rLength-MINMATCH);
- ip += rLength;
- anchor = ip;
- continue; /* faster when present ... (?) */
- } } }
+ if (dictMode == ZSTD_dictMatchState) {
+ while (ip <= ilimit) {
+ U32 const current2 = (U32)(ip-base);
+ U32 const repIndex2 = current2 - offset_2;
+ const BYTE* repMatch2 = dictMode == ZSTD_dictMatchState
+ && repIndex2 < prefixLowestIndex ?
+ dictBase - dictIndexDelta + repIndex2 :
+ base + repIndex2;
+ if ( ((U32)((prefixLowestIndex-1) - (U32)repIndex2) >= 3 /* intentional overflow */)
+ && (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
+ const BYTE* const repEnd2 = repIndex2 < prefixLowestIndex ? dictEnd : iend;
+ size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixLowest) + 4;
+ U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
+ ZSTD_storeSeq(seqStore, 0, anchor, 0, repLength2-MINMATCH);
+ hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = current2;
+ hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = current2;
+ ip += repLength2;
+ anchor = ip;
+ continue;
+ }
+ break;
+ }
+ }
+
+ if (dictMode == ZSTD_noDict) {
+ while ( (ip <= ilimit)
+ && ( (offset_2>0)
+ & (MEM_read32(ip) == MEM_read32(ip - offset_2)) )) {
+ /* store sequence */
+ size_t const rLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;
+ U32 const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; /* swap offset_2 <=> offset_1 */
+ hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = (U32)(ip-base);
+ hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = (U32)(ip-base);
+ ZSTD_storeSeq(seqStore, 0, anchor, 0, rLength-MINMATCH);
+ ip += rLength;
+ anchor = ip;
+ continue; /* faster when present ... (?) */
+ } } } }
/* save reps for next block */
rep[0] = offset_1 ? offset_1 : offsetSaved;
@@ -160,102 +307,126 @@ size_t ZSTD_compressBlock_doubleFast_generic(
size_t ZSTD_compressBlock_doubleFast(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize)
+ void const* src, size_t srcSize)
+{
+ const U32 mls = ms->cParams.minMatch;
+ switch(mls)
+ {
+ default: /* includes case 3 */
+ case 4 :
+ return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 4, ZSTD_noDict);
+ case 5 :
+ return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 5, ZSTD_noDict);
+ case 6 :
+ return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 6, ZSTD_noDict);
+ case 7 :
+ return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 7, ZSTD_noDict);
+ }
+}
+
+
+size_t ZSTD_compressBlock_doubleFast_dictMatchState(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize)
{
- const U32 mls = cParams->searchLength;
+ const U32 mls = ms->cParams.minMatch;
switch(mls)
{
default: /* includes case 3 */
case 4 :
- return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, cParams, src, srcSize, 4);
+ return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 4, ZSTD_dictMatchState);
case 5 :
- return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, cParams, src, srcSize, 5);
+ return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 5, ZSTD_dictMatchState);
case 6 :
- return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, cParams, src, srcSize, 6);
+ return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 6, ZSTD_dictMatchState);
case 7 :
- return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, cParams, src, srcSize, 7);
+ return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 7, ZSTD_dictMatchState);
}
}
static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize,
+ void const* src, size_t srcSize,
U32 const mls /* template */)
{
+ ZSTD_compressionParameters const* cParams = &ms->cParams;
U32* const hashLong = ms->hashTable;
U32 const hBitsL = cParams->hashLog;
U32* const hashSmall = ms->chainTable;
U32 const hBitsS = cParams->chainLog;
- const BYTE* const base = ms->window.base;
- const BYTE* const dictBase = ms->window.dictBase;
const BYTE* const istart = (const BYTE*)src;
const BYTE* ip = istart;
const BYTE* anchor = istart;
- const U32 lowestIndex = ms->window.lowLimit;
- const BYTE* const dictStart = dictBase + lowestIndex;
- const U32 dictLimit = ms->window.dictLimit;
- const BYTE* const lowPrefixPtr = base + dictLimit;
- const BYTE* const dictEnd = dictBase + dictLimit;
const BYTE* const iend = istart + srcSize;
const BYTE* const ilimit = iend - 8;
+ const U32 prefixStartIndex = ms->window.dictLimit;
+ const BYTE* const base = ms->window.base;
+ const BYTE* const prefixStart = base + prefixStartIndex;
+ const U32 dictStartIndex = ms->window.lowLimit;
+ const BYTE* const dictBase = ms->window.dictBase;
+ const BYTE* const dictStart = dictBase + dictStartIndex;
+ const BYTE* const dictEnd = dictBase + prefixStartIndex;
U32 offset_1=rep[0], offset_2=rep[1];
+ DEBUGLOG(5, "ZSTD_compressBlock_doubleFast_extDict_generic (srcSize=%zu)", srcSize);
+
/* Search Loop */
while (ip < ilimit) { /* < instead of <=, because (ip+1) */
const size_t hSmall = ZSTD_hashPtr(ip, hBitsS, mls);
const U32 matchIndex = hashSmall[hSmall];
- const BYTE* matchBase = matchIndex < dictLimit ? dictBase : base;
+ const BYTE* const matchBase = matchIndex < prefixStartIndex ? dictBase : base;
const BYTE* match = matchBase + matchIndex;
const size_t hLong = ZSTD_hashPtr(ip, hBitsL, 8);
const U32 matchLongIndex = hashLong[hLong];
- const BYTE* matchLongBase = matchLongIndex < dictLimit ? dictBase : base;
+ const BYTE* const matchLongBase = matchLongIndex < prefixStartIndex ? dictBase : base;
const BYTE* matchLong = matchLongBase + matchLongIndex;
const U32 current = (U32)(ip-base);
const U32 repIndex = current + 1 - offset_1; /* offset_1 expected <= current +1 */
- const BYTE* repBase = repIndex < dictLimit ? dictBase : base;
- const BYTE* repMatch = repBase + repIndex;
+ const BYTE* const repBase = repIndex < prefixStartIndex ? dictBase : base;
+ const BYTE* const repMatch = repBase + repIndex;
size_t mLength;
hashSmall[hSmall] = hashLong[hLong] = current; /* update hash table */
- if ( (((U32)((dictLimit-1) - repIndex) >= 3) /* intentional underflow */ & (repIndex > lowestIndex))
- && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
- const BYTE* repMatchEnd = repIndex < dictLimit ? dictEnd : iend;
- mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, lowPrefixPtr) + 4;
+ if ((((U32)((prefixStartIndex-1) - repIndex) >= 3) /* intentional underflow : ensure repIndex doesn't overlap dict + prefix */
+ & (repIndex > dictStartIndex))
+ && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
+ const BYTE* repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend;
+ mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixStart) + 4;
ip++;
ZSTD_storeSeq(seqStore, ip-anchor, anchor, 0, mLength-MINMATCH);
} else {
- if ((matchLongIndex > lowestIndex) && (MEM_read64(matchLong) == MEM_read64(ip))) {
- const BYTE* matchEnd = matchLongIndex < dictLimit ? dictEnd : iend;
- const BYTE* lowMatchPtr = matchLongIndex < dictLimit ? dictStart : lowPrefixPtr;
+ if ((matchLongIndex > dictStartIndex) && (MEM_read64(matchLong) == MEM_read64(ip))) {
+ const BYTE* const matchEnd = matchLongIndex < prefixStartIndex ? dictEnd : iend;
+ const BYTE* const lowMatchPtr = matchLongIndex < prefixStartIndex ? dictStart : prefixStart;
U32 offset;
- mLength = ZSTD_count_2segments(ip+8, matchLong+8, iend, matchEnd, lowPrefixPtr) + 8;
+ mLength = ZSTD_count_2segments(ip+8, matchLong+8, iend, matchEnd, prefixStart) + 8;
offset = current - matchLongIndex;
while (((ip>anchor) & (matchLong>lowMatchPtr)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } /* catch up */
offset_2 = offset_1;
offset_1 = offset;
ZSTD_storeSeq(seqStore, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
- } else if ((matchIndex > lowestIndex) && (MEM_read32(match) == MEM_read32(ip))) {
+ } else if ((matchIndex > dictStartIndex) && (MEM_read32(match) == MEM_read32(ip))) {
size_t const h3 = ZSTD_hashPtr(ip+1, hBitsL, 8);
U32 const matchIndex3 = hashLong[h3];
- const BYTE* const match3Base = matchIndex3 < dictLimit ? dictBase : base;
+ const BYTE* const match3Base = matchIndex3 < prefixStartIndex ? dictBase : base;
const BYTE* match3 = match3Base + matchIndex3;
U32 offset;
hashLong[h3] = current + 1;
- if ( (matchIndex3 > lowestIndex) && (MEM_read64(match3) == MEM_read64(ip+1)) ) {
- const BYTE* matchEnd = matchIndex3 < dictLimit ? dictEnd : iend;
- const BYTE* lowMatchPtr = matchIndex3 < dictLimit ? dictStart : lowPrefixPtr;
- mLength = ZSTD_count_2segments(ip+9, match3+8, iend, matchEnd, lowPrefixPtr) + 8;
+ if ( (matchIndex3 > dictStartIndex) && (MEM_read64(match3) == MEM_read64(ip+1)) ) {
+ const BYTE* const matchEnd = matchIndex3 < prefixStartIndex ? dictEnd : iend;
+ const BYTE* const lowMatchPtr = matchIndex3 < prefixStartIndex ? dictStart : prefixStart;
+ mLength = ZSTD_count_2segments(ip+9, match3+8, iend, matchEnd, prefixStart) + 8;
ip++;
offset = current+1 - matchIndex3;
while (((ip>anchor) & (match3>lowMatchPtr)) && (ip[-1] == match3[-1])) { ip--; match3--; mLength++; } /* catch up */
} else {
- const BYTE* matchEnd = matchIndex < dictLimit ? dictEnd : iend;
- const BYTE* lowMatchPtr = matchIndex < dictLimit ? dictStart : lowPrefixPtr;
- mLength = ZSTD_count_2segments(ip+4, match+4, iend, matchEnd, lowPrefixPtr) + 4;
+ const BYTE* const matchEnd = matchIndex < prefixStartIndex ? dictEnd : iend;
+ const BYTE* const lowMatchPtr = matchIndex < prefixStartIndex ? dictStart : prefixStart;
+ mLength = ZSTD_count_2segments(ip+4, match+4, iend, matchEnd, prefixStart) + 4;
offset = current - matchIndex;
while (((ip>anchor) & (match>lowMatchPtr)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
}
@@ -282,12 +453,13 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
while (ip <= ilimit) {
U32 const current2 = (U32)(ip-base);
U32 const repIndex2 = current2 - offset_2;
- const BYTE* repMatch2 = repIndex2 < dictLimit ? dictBase + repIndex2 : base + repIndex2;
- if ( (((U32)((dictLimit-1) - repIndex2) >= 3) & (repIndex2 > lowestIndex)) /* intentional overflow */
- && (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
- const BYTE* const repEnd2 = repIndex2 < dictLimit ? dictEnd : iend;
- size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, lowPrefixPtr) + 4;
- U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
+ const BYTE* repMatch2 = repIndex2 < prefixStartIndex ? dictBase + repIndex2 : base + repIndex2;
+ if ( (((U32)((prefixStartIndex-1) - repIndex2) >= 3) /* intentional overflow : ensure repIndex2 doesn't overlap dict + prefix */
+ & (repIndex2 > dictStartIndex))
+ && (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
+ const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend;
+ size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixStart) + 4;
+ U32 const tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
ZSTD_storeSeq(seqStore, 0, anchor, 0, repLength2-MINMATCH);
hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = current2;
hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = current2;
@@ -309,19 +481,19 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
size_t ZSTD_compressBlock_doubleFast_extDict(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize)
+ void const* src, size_t srcSize)
{
- U32 const mls = cParams->searchLength;
+ U32 const mls = ms->cParams.minMatch;
switch(mls)
{
default: /* includes case 3 */
case 4 :
- return ZSTD_compressBlock_doubleFast_extDict_generic(ms, seqStore, rep, cParams, src, srcSize, 4);
+ return ZSTD_compressBlock_doubleFast_extDict_generic(ms, seqStore, rep, src, srcSize, 4);
case 5 :
- return ZSTD_compressBlock_doubleFast_extDict_generic(ms, seqStore, rep, cParams, src, srcSize, 5);
+ return ZSTD_compressBlock_doubleFast_extDict_generic(ms, seqStore, rep, src, srcSize, 5);
case 6 :
- return ZSTD_compressBlock_doubleFast_extDict_generic(ms, seqStore, rep, cParams, src, srcSize, 6);
+ return ZSTD_compressBlock_doubleFast_extDict_generic(ms, seqStore, rep, src, srcSize, 6);
case 7 :
- return ZSTD_compressBlock_doubleFast_extDict_generic(ms, seqStore, rep, cParams, src, srcSize, 7);
+ return ZSTD_compressBlock_doubleFast_extDict_generic(ms, seqStore, rep, src, srcSize, 7);
}
}
diff --git a/thirdparty/zstd/compress/zstd_double_fast.h b/thirdparty/zstd/compress/zstd_double_fast.h
index 6d80b2774c..4fa31acfc0 100644
--- a/thirdparty/zstd/compress/zstd_double_fast.h
+++ b/thirdparty/zstd/compress/zstd_double_fast.h
@@ -19,14 +19,16 @@ extern "C" {
#include "zstd_compress_internal.h" /* ZSTD_CCtx, size_t */
void ZSTD_fillDoubleHashTable(ZSTD_matchState_t* ms,
- ZSTD_compressionParameters const* cParams,
- void const* end);
+ void const* end, ZSTD_dictTableLoadMethod_e dtlm);
size_t ZSTD_compressBlock_doubleFast(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
+ void const* src, size_t srcSize);
+size_t ZSTD_compressBlock_doubleFast_dictMatchState(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize);
size_t ZSTD_compressBlock_doubleFast_extDict(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
+ void const* src, size_t srcSize);
#if defined (__cplusplus)
diff --git a/thirdparty/zstd/compress/zstd_fast.c b/thirdparty/zstd/compress/zstd_fast.c
index df4d28b340..ed997b441c 100644
--- a/thirdparty/zstd/compress/zstd_fast.c
+++ b/thirdparty/zstd/compress/zstd_fast.c
@@ -13,12 +13,12 @@
void ZSTD_fillHashTable(ZSTD_matchState_t* ms,
- ZSTD_compressionParameters const* cParams,
- void const* end)
+ void const* end, ZSTD_dictTableLoadMethod_e dtlm)
{
+ const ZSTD_compressionParameters* const cParams = &ms->cParams;
U32* const hashTable = ms->hashTable;
U32 const hBits = cParams->hashLog;
- U32 const mls = cParams->searchLength;
+ U32 const mls = cParams->minMatch;
const BYTE* const base = ms->window.base;
const BYTE* ip = base + ms->nextToUpdate;
const BYTE* const iend = ((const BYTE*)end) - HASH_READ_SIZE;
@@ -27,69 +27,267 @@ void ZSTD_fillHashTable(ZSTD_matchState_t* ms,
/* Always insert every fastHashFillStep position into the hash table.
* Insert the other positions if their hash entry is empty.
*/
- for (; ip + fastHashFillStep - 1 <= iend; ip += fastHashFillStep) {
+ for ( ; ip + fastHashFillStep < iend + 2; ip += fastHashFillStep) {
U32 const current = (U32)(ip - base);
- U32 i;
- for (i = 0; i < fastHashFillStep; ++i) {
- size_t const hash = ZSTD_hashPtr(ip + i, hBits, mls);
- if (i == 0 || hashTable[hash] == 0)
- hashTable[hash] = current + i;
- }
- }
+ size_t const hash0 = ZSTD_hashPtr(ip, hBits, mls);
+ hashTable[hash0] = current;
+ if (dtlm == ZSTD_dtlm_fast) continue;
+ /* Only load extra positions for ZSTD_dtlm_full */
+ { U32 p;
+ for (p = 1; p < fastHashFillStep; ++p) {
+ size_t const hash = ZSTD_hashPtr(ip + p, hBits, mls);
+ if (hashTable[hash] == 0) { /* not yet filled */
+ hashTable[hash] = current + p;
+ } } } }
}
FORCE_INLINE_TEMPLATE
size_t ZSTD_compressBlock_fast_generic(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
void const* src, size_t srcSize,
- U32 const hlog, U32 const stepSize, U32 const mls)
+ U32 const mls)
{
+ const ZSTD_compressionParameters* const cParams = &ms->cParams;
U32* const hashTable = ms->hashTable;
+ U32 const hlog = cParams->hashLog;
+ /* support stepSize of 0 */
+ size_t const stepSize = cParams->targetLength + !(cParams->targetLength) + 1;
const BYTE* const base = ms->window.base;
const BYTE* const istart = (const BYTE*)src;
- const BYTE* ip = istart;
+ /* We check ip0 (ip + 0) and ip1 (ip + 1) each loop */
+ const BYTE* ip0 = istart;
+ const BYTE* ip1;
const BYTE* anchor = istart;
- const U32 lowestIndex = ms->window.dictLimit;
- const BYTE* const lowest = base + lowestIndex;
+ const U32 prefixStartIndex = ms->window.dictLimit;
+ const BYTE* const prefixStart = base + prefixStartIndex;
const BYTE* const iend = istart + srcSize;
const BYTE* const ilimit = iend - HASH_READ_SIZE;
U32 offset_1=rep[0], offset_2=rep[1];
U32 offsetSaved = 0;
/* init */
- ip += (ip==lowest);
- { U32 const maxRep = (U32)(ip-lowest);
+ ip0 += (ip0 == prefixStart);
+ ip1 = ip0 + 1;
+ {
+ U32 const maxRep = (U32)(ip0 - prefixStart);
if (offset_2 > maxRep) offsetSaved = offset_2, offset_2 = 0;
if (offset_1 > maxRep) offsetSaved = offset_1, offset_1 = 0;
}
/* Main Search Loop */
+ while (ip1 < ilimit) { /* < instead of <=, because check at ip0+2 */
+ size_t mLength;
+ BYTE const* ip2 = ip0 + 2;
+ size_t const h0 = ZSTD_hashPtr(ip0, hlog, mls);
+ U32 const val0 = MEM_read32(ip0);
+ size_t const h1 = ZSTD_hashPtr(ip1, hlog, mls);
+ U32 const val1 = MEM_read32(ip1);
+ U32 const current0 = (U32)(ip0-base);
+ U32 const current1 = (U32)(ip1-base);
+ U32 const matchIndex0 = hashTable[h0];
+ U32 const matchIndex1 = hashTable[h1];
+ BYTE const* repMatch = ip2-offset_1;
+ const BYTE* match0 = base + matchIndex0;
+ const BYTE* match1 = base + matchIndex1;
+ U32 offcode;
+ hashTable[h0] = current0; /* update hash table */
+ hashTable[h1] = current1; /* update hash table */
+
+ assert(ip0 + 1 == ip1);
+
+ if ((offset_1 > 0) & (MEM_read32(repMatch) == MEM_read32(ip2))) {
+ mLength = ip2[-1] == repMatch[-1] ? 1 : 0;
+ ip0 = ip2 - mLength;
+ match0 = repMatch - mLength;
+ offcode = 0;
+ goto _match;
+ }
+ if ((matchIndex0 > prefixStartIndex) && MEM_read32(match0) == val0) {
+ /* found a regular match */
+ goto _offset;
+ }
+ if ((matchIndex1 > prefixStartIndex) && MEM_read32(match1) == val1) {
+ /* found a regular match after one literal */
+ ip0 = ip1;
+ match0 = match1;
+ goto _offset;
+ }
+ {
+ size_t const step = ((ip0-anchor) >> (kSearchStrength - 1)) + stepSize;
+ assert(step >= 2);
+ ip0 += step;
+ ip1 += step;
+ continue;
+ }
+_offset: /* Requires: ip0, match0 */
+ /* Compute the offset code */
+ offset_2 = offset_1;
+ offset_1 = (U32)(ip0-match0);
+ offcode = offset_1 + ZSTD_REP_MOVE;
+ mLength = 0;
+ /* Count the backwards match length */
+ while (((ip0>anchor) & (match0>prefixStart))
+ && (ip0[-1] == match0[-1])) { ip0--; match0--; mLength++; } /* catch up */
+
+_match: /* Requires: ip0, match0, offcode */
+ /* Count the forward length */
+ mLength += ZSTD_count(ip0+mLength+4, match0+mLength+4, iend) + 4;
+ ZSTD_storeSeq(seqStore, ip0-anchor, anchor, offcode, mLength-MINMATCH);
+ /* match found */
+ ip0 += mLength;
+ anchor = ip0;
+ ip1 = ip0 + 1;
+
+ if (ip0 <= ilimit) {
+ /* Fill Table */
+ assert(base+current0+2 > istart); /* check base overflow */
+ hashTable[ZSTD_hashPtr(base+current0+2, hlog, mls)] = current0+2; /* here because current+2 could be > iend-8 */
+ hashTable[ZSTD_hashPtr(ip0-2, hlog, mls)] = (U32)(ip0-2-base);
+
+ while ( (ip0 <= ilimit)
+ && ( (offset_2>0)
+ & (MEM_read32(ip0) == MEM_read32(ip0 - offset_2)) )) {
+ /* store sequence */
+ size_t const rLength = ZSTD_count(ip0+4, ip0+4-offset_2, iend) + 4;
+ U32 const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; /* swap offset_2 <=> offset_1 */
+ hashTable[ZSTD_hashPtr(ip0, hlog, mls)] = (U32)(ip0-base);
+ ip0 += rLength;
+ ip1 = ip0 + 1;
+ ZSTD_storeSeq(seqStore, 0, anchor, 0, rLength-MINMATCH);
+ anchor = ip0;
+ continue; /* faster when present (confirmed on gcc-8) ... (?) */
+ }
+ }
+ }
+
+ /* save reps for next block */
+ rep[0] = offset_1 ? offset_1 : offsetSaved;
+ rep[1] = offset_2 ? offset_2 : offsetSaved;
+
+ /* Return the last literals size */
+ return iend - anchor;
+}
+
+
+size_t ZSTD_compressBlock_fast(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize)
+{
+ ZSTD_compressionParameters const* cParams = &ms->cParams;
+ U32 const mls = cParams->minMatch;
+ assert(ms->dictMatchState == NULL);
+ switch(mls)
+ {
+ default: /* includes case 3 */
+ case 4 :
+ return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 4);
+ case 5 :
+ return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 5);
+ case 6 :
+ return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 6);
+ case 7 :
+ return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 7);
+ }
+}
+
+FORCE_INLINE_TEMPLATE
+size_t ZSTD_compressBlock_fast_dictMatchState_generic(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize, U32 const mls)
+{
+ const ZSTD_compressionParameters* const cParams = &ms->cParams;
+ U32* const hashTable = ms->hashTable;
+ U32 const hlog = cParams->hashLog;
+ /* support stepSize of 0 */
+ U32 const stepSize = cParams->targetLength + !(cParams->targetLength);
+ const BYTE* const base = ms->window.base;
+ const BYTE* const istart = (const BYTE*)src;
+ const BYTE* ip = istart;
+ const BYTE* anchor = istart;
+ const U32 prefixStartIndex = ms->window.dictLimit;
+ const BYTE* const prefixStart = base + prefixStartIndex;
+ const BYTE* const iend = istart + srcSize;
+ const BYTE* const ilimit = iend - HASH_READ_SIZE;
+ U32 offset_1=rep[0], offset_2=rep[1];
+ U32 offsetSaved = 0;
+
+ const ZSTD_matchState_t* const dms = ms->dictMatchState;
+ const ZSTD_compressionParameters* const dictCParams = &dms->cParams ;
+ const U32* const dictHashTable = dms->hashTable;
+ const U32 dictStartIndex = dms->window.dictLimit;
+ const BYTE* const dictBase = dms->window.base;
+ const BYTE* const dictStart = dictBase + dictStartIndex;
+ const BYTE* const dictEnd = dms->window.nextSrc;
+ const U32 dictIndexDelta = prefixStartIndex - (U32)(dictEnd - dictBase);
+ const U32 dictAndPrefixLength = (U32)(ip - prefixStart + dictEnd - dictStart);
+ const U32 dictHLog = dictCParams->hashLog;
+
+ /* otherwise, we would get index underflow when translating a dict index
+ * into a local index */
+ assert(prefixStartIndex >= (U32)(dictEnd - dictBase));
+
+ /* init */
+ ip += (dictAndPrefixLength == 0);
+ /* dictMatchState repCode checks don't currently handle repCode == 0
+ * disabling. */
+ assert(offset_1 <= dictAndPrefixLength);
+ assert(offset_2 <= dictAndPrefixLength);
+
+ /* Main Search Loop */
while (ip < ilimit) { /* < instead of <=, because repcode check at (ip+1) */
size_t mLength;
size_t const h = ZSTD_hashPtr(ip, hlog, mls);
U32 const current = (U32)(ip-base);
U32 const matchIndex = hashTable[h];
const BYTE* match = base + matchIndex;
+ const U32 repIndex = current + 1 - offset_1;
+ const BYTE* repMatch = (repIndex < prefixStartIndex) ?
+ dictBase + (repIndex - dictIndexDelta) :
+ base + repIndex;
hashTable[h] = current; /* update hash table */
- if ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1))) {
- mLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;
+ if ( ((U32)((prefixStartIndex-1) - repIndex) >= 3) /* intentional underflow : ensure repIndex isn't overlapping dict + prefix */
+ && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
+ const BYTE* const repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend;
+ mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixStart) + 4;
ip++;
ZSTD_storeSeq(seqStore, ip-anchor, anchor, 0, mLength-MINMATCH);
- } else {
- if ( (matchIndex <= lowestIndex)
- || (MEM_read32(match) != MEM_read32(ip)) ) {
+ } else if ( (matchIndex <= prefixStartIndex) ) {
+ size_t const dictHash = ZSTD_hashPtr(ip, dictHLog, mls);
+ U32 const dictMatchIndex = dictHashTable[dictHash];
+ const BYTE* dictMatch = dictBase + dictMatchIndex;
+ if (dictMatchIndex <= dictStartIndex ||
+ MEM_read32(dictMatch) != MEM_read32(ip)) {
assert(stepSize >= 1);
ip += ((ip-anchor) >> kSearchStrength) + stepSize;
continue;
- }
- mLength = ZSTD_count(ip+4, match+4, iend) + 4;
- { U32 const offset = (U32)(ip-match);
- while (((ip>anchor) & (match>lowest)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
+ } else {
+ /* found a dict match */
+ U32 const offset = (U32)(current-dictMatchIndex-dictIndexDelta);
+ mLength = ZSTD_count_2segments(ip+4, dictMatch+4, iend, dictEnd, prefixStart) + 4;
+ while (((ip>anchor) & (dictMatch>dictStart))
+ && (ip[-1] == dictMatch[-1])) {
+ ip--; dictMatch--; mLength++;
+ } /* catch up */
offset_2 = offset_1;
offset_1 = offset;
ZSTD_storeSeq(seqStore, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
- } }
+ }
+ } else if (MEM_read32(match) != MEM_read32(ip)) {
+ /* it's not a match, and we're not going to check the dictionary */
+ assert(stepSize >= 1);
+ ip += ((ip-anchor) >> kSearchStrength) + stepSize;
+ continue;
+ } else {
+ /* found a regular match */
+ U32 const offset = (U32)(ip-match);
+ mLength = ZSTD_count(ip+4, match+4, iend) + 4;
+ while (((ip>anchor) & (match>prefixStart))
+ && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
+ offset_2 = offset_1;
+ offset_1 = offset;
+ ZSTD_storeSeq(seqStore, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
+ }
/* match found */
ip += mLength;
@@ -97,21 +295,32 @@ size_t ZSTD_compressBlock_fast_generic(
if (ip <= ilimit) {
/* Fill Table */
+ assert(base+current+2 > istart); /* check base overflow */
hashTable[ZSTD_hashPtr(base+current+2, hlog, mls)] = current+2; /* here because current+2 could be > iend-8 */
hashTable[ZSTD_hashPtr(ip-2, hlog, mls)] = (U32)(ip-2-base);
+
/* check immediate repcode */
- while ( (ip <= ilimit)
- && ( (offset_2>0)
- & (MEM_read32(ip) == MEM_read32(ip - offset_2)) )) {
- /* store sequence */
- size_t const rLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;
- { U32 const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; } /* swap offset_2 <=> offset_1 */
- hashTable[ZSTD_hashPtr(ip, hlog, mls)] = (U32)(ip-base);
- ZSTD_storeSeq(seqStore, 0, anchor, 0, rLength-MINMATCH);
- ip += rLength;
- anchor = ip;
- continue; /* faster when present ... (?) */
- } } }
+ while (ip <= ilimit) {
+ U32 const current2 = (U32)(ip-base);
+ U32 const repIndex2 = current2 - offset_2;
+ const BYTE* repMatch2 = repIndex2 < prefixStartIndex ?
+ dictBase - dictIndexDelta + repIndex2 :
+ base + repIndex2;
+ if ( ((U32)((prefixStartIndex-1) - (U32)repIndex2) >= 3 /* intentional overflow */)
+ && (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
+ const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend;
+ size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixStart) + 4;
+ U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
+ ZSTD_storeSeq(seqStore, 0, anchor, 0, repLength2-MINMATCH);
+ hashTable[ZSTD_hashPtr(ip, hlog, mls)] = current2;
+ ip += repLength2;
+ anchor = ip;
+ continue;
+ }
+ break;
+ }
+ }
+ }
/* save reps for next block */
rep[0] = offset_1 ? offset_1 : offsetSaved;
@@ -121,45 +330,47 @@ size_t ZSTD_compressBlock_fast_generic(
return iend - anchor;
}
-
-size_t ZSTD_compressBlock_fast(
+size_t ZSTD_compressBlock_fast_dictMatchState(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize)
+ void const* src, size_t srcSize)
{
- U32 const hlog = cParams->hashLog;
- U32 const mls = cParams->searchLength;
- U32 const stepSize = cParams->targetLength;
+ ZSTD_compressionParameters const* cParams = &ms->cParams;
+ U32 const mls = cParams->minMatch;
+ assert(ms->dictMatchState != NULL);
switch(mls)
{
default: /* includes case 3 */
case 4 :
- return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, hlog, stepSize, 4);
+ return ZSTD_compressBlock_fast_dictMatchState_generic(ms, seqStore, rep, src, srcSize, 4);
case 5 :
- return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, hlog, stepSize, 5);
+ return ZSTD_compressBlock_fast_dictMatchState_generic(ms, seqStore, rep, src, srcSize, 5);
case 6 :
- return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, hlog, stepSize, 6);
+ return ZSTD_compressBlock_fast_dictMatchState_generic(ms, seqStore, rep, src, srcSize, 6);
case 7 :
- return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, hlog, stepSize, 7);
+ return ZSTD_compressBlock_fast_dictMatchState_generic(ms, seqStore, rep, src, srcSize, 7);
}
}
static size_t ZSTD_compressBlock_fast_extDict_generic(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- void const* src, size_t srcSize,
- U32 const hlog, U32 const stepSize, U32 const mls)
+ void const* src, size_t srcSize, U32 const mls)
{
- U32* hashTable = ms->hashTable;
+ const ZSTD_compressionParameters* const cParams = &ms->cParams;
+ U32* const hashTable = ms->hashTable;
+ U32 const hlog = cParams->hashLog;
+ /* support stepSize of 0 */
+ U32 const stepSize = cParams->targetLength + !(cParams->targetLength);
const BYTE* const base = ms->window.base;
const BYTE* const dictBase = ms->window.dictBase;
const BYTE* const istart = (const BYTE*)src;
const BYTE* ip = istart;
const BYTE* anchor = istart;
- const U32 lowestIndex = ms->window.lowLimit;
- const BYTE* const dictStart = dictBase + lowestIndex;
- const U32 dictLimit = ms->window.dictLimit;
- const BYTE* const lowPrefixPtr = base + dictLimit;
- const BYTE* const dictEnd = dictBase + dictLimit;
+ const U32 dictStartIndex = ms->window.lowLimit;
+ const BYTE* const dictStart = dictBase + dictStartIndex;
+ const U32 prefixStartIndex = ms->window.dictLimit;
+ const BYTE* const prefixStart = base + prefixStartIndex;
+ const BYTE* const dictEnd = dictBase + prefixStartIndex;
const BYTE* const iend = istart + srcSize;
const BYTE* const ilimit = iend - 8;
U32 offset_1=rep[0], offset_2=rep[1];
@@ -167,33 +378,34 @@ static size_t ZSTD_compressBlock_fast_extDict_generic(
/* Search Loop */
while (ip < ilimit) { /* < instead of <=, because (ip+1) */
const size_t h = ZSTD_hashPtr(ip, hlog, mls);
- const U32 matchIndex = hashTable[h];
- const BYTE* matchBase = matchIndex < dictLimit ? dictBase : base;
- const BYTE* match = matchBase + matchIndex;
- const U32 current = (U32)(ip-base);
- const U32 repIndex = current + 1 - offset_1; /* offset_1 expected <= current +1 */
- const BYTE* repBase = repIndex < dictLimit ? dictBase : base;
- const BYTE* repMatch = repBase + repIndex;
+ const U32 matchIndex = hashTable[h];
+ const BYTE* const matchBase = matchIndex < prefixStartIndex ? dictBase : base;
+ const BYTE* match = matchBase + matchIndex;
+ const U32 current = (U32)(ip-base);
+ const U32 repIndex = current + 1 - offset_1;
+ const BYTE* const repBase = repIndex < prefixStartIndex ? dictBase : base;
+ const BYTE* const repMatch = repBase + repIndex;
size_t mLength;
hashTable[h] = current; /* update hash table */
+ assert(offset_1 <= current +1); /* check repIndex */
- if ( (((U32)((dictLimit-1) - repIndex) >= 3) /* intentional underflow */ & (repIndex > lowestIndex))
+ if ( (((U32)((prefixStartIndex-1) - repIndex) >= 3) /* intentional underflow */ & (repIndex > dictStartIndex))
&& (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
- const BYTE* repMatchEnd = repIndex < dictLimit ? dictEnd : iend;
- mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, lowPrefixPtr) + 4;
+ const BYTE* repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend;
+ mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixStart) + 4;
ip++;
ZSTD_storeSeq(seqStore, ip-anchor, anchor, 0, mLength-MINMATCH);
} else {
- if ( (matchIndex < lowestIndex) ||
+ if ( (matchIndex < dictStartIndex) ||
(MEM_read32(match) != MEM_read32(ip)) ) {
assert(stepSize >= 1);
ip += ((ip-anchor) >> kSearchStrength) + stepSize;
continue;
}
- { const BYTE* matchEnd = matchIndex < dictLimit ? dictEnd : iend;
- const BYTE* lowMatchPtr = matchIndex < dictLimit ? dictStart : lowPrefixPtr;
+ { const BYTE* matchEnd = matchIndex < prefixStartIndex ? dictEnd : iend;
+ const BYTE* lowMatchPtr = matchIndex < prefixStartIndex ? dictStart : prefixStart;
U32 offset;
- mLength = ZSTD_count_2segments(ip+4, match+4, iend, matchEnd, lowPrefixPtr) + 4;
+ mLength = ZSTD_count_2segments(ip+4, match+4, iend, matchEnd, prefixStart) + 4;
while (((ip>anchor) & (match>lowMatchPtr)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
offset = current - matchIndex;
offset_2 = offset_1;
@@ -213,11 +425,11 @@ static size_t ZSTD_compressBlock_fast_extDict_generic(
while (ip <= ilimit) {
U32 const current2 = (U32)(ip-base);
U32 const repIndex2 = current2 - offset_2;
- const BYTE* repMatch2 = repIndex2 < dictLimit ? dictBase + repIndex2 : base + repIndex2;
- if ( (((U32)((dictLimit-1) - repIndex2) >= 3) & (repIndex2 > lowestIndex)) /* intentional overflow */
+ const BYTE* repMatch2 = repIndex2 < prefixStartIndex ? dictBase + repIndex2 : base + repIndex2;
+ if ( (((U32)((prefixStartIndex-1) - repIndex2) >= 3) & (repIndex2 > dictStartIndex)) /* intentional overflow */
&& (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
- const BYTE* const repEnd2 = repIndex2 < dictLimit ? dictEnd : iend;
- size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, lowPrefixPtr) + 4;
+ const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend;
+ size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixStart) + 4;
U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
ZSTD_storeSeq(seqStore, 0, anchor, 0, repLength2-MINMATCH);
hashTable[ZSTD_hashPtr(ip, hlog, mls)] = current2;
@@ -239,21 +451,20 @@ static size_t ZSTD_compressBlock_fast_extDict_generic(
size_t ZSTD_compressBlock_fast_extDict(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize)
+ void const* src, size_t srcSize)
{
- U32 const hlog = cParams->hashLog;
- U32 const mls = cParams->searchLength;
- U32 const stepSize = cParams->targetLength;
+ ZSTD_compressionParameters const* cParams = &ms->cParams;
+ U32 const mls = cParams->minMatch;
switch(mls)
{
default: /* includes case 3 */
case 4 :
- return ZSTD_compressBlock_fast_extDict_generic(ms, seqStore, rep, src, srcSize, hlog, stepSize, 4);
+ return ZSTD_compressBlock_fast_extDict_generic(ms, seqStore, rep, src, srcSize, 4);
case 5 :
- return ZSTD_compressBlock_fast_extDict_generic(ms, seqStore, rep, src, srcSize, hlog, stepSize, 5);
+ return ZSTD_compressBlock_fast_extDict_generic(ms, seqStore, rep, src, srcSize, 5);
case 6 :
- return ZSTD_compressBlock_fast_extDict_generic(ms, seqStore, rep, src, srcSize, hlog, stepSize, 6);
+ return ZSTD_compressBlock_fast_extDict_generic(ms, seqStore, rep, src, srcSize, 6);
case 7 :
- return ZSTD_compressBlock_fast_extDict_generic(ms, seqStore, rep, src, srcSize, hlog, stepSize, 7);
+ return ZSTD_compressBlock_fast_extDict_generic(ms, seqStore, rep, src, srcSize, 7);
}
}
diff --git a/thirdparty/zstd/compress/zstd_fast.h b/thirdparty/zstd/compress/zstd_fast.h
index f0438ad5b4..b74a88c57c 100644
--- a/thirdparty/zstd/compress/zstd_fast.h
+++ b/thirdparty/zstd/compress/zstd_fast.h
@@ -19,14 +19,16 @@ extern "C" {
#include "zstd_compress_internal.h"
void ZSTD_fillHashTable(ZSTD_matchState_t* ms,
- ZSTD_compressionParameters const* cParams,
- void const* end);
+ void const* end, ZSTD_dictTableLoadMethod_e dtlm);
size_t ZSTD_compressBlock_fast(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
+ void const* src, size_t srcSize);
+size_t ZSTD_compressBlock_fast_dictMatchState(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize);
size_t ZSTD_compressBlock_fast_extDict(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
+ void const* src, size_t srcSize);
#if defined (__cplusplus)
}
diff --git a/thirdparty/zstd/compress/zstd_lazy.c b/thirdparty/zstd/compress/zstd_lazy.c
index 9f158123f0..53f998a437 100644
--- a/thirdparty/zstd/compress/zstd_lazy.c
+++ b/thirdparty/zstd/compress/zstd_lazy.c
@@ -16,11 +16,12 @@
* Binary Tree search
***************************************/
-void ZSTD_updateDUBT(
- ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
+static void
+ZSTD_updateDUBT(ZSTD_matchState_t* ms,
const BYTE* ip, const BYTE* iend,
U32 mls)
{
+ const ZSTD_compressionParameters* const cParams = &ms->cParams;
U32* const hashTable = ms->hashTable;
U32 const hashLog = cParams->hashLog;
@@ -59,14 +60,16 @@ void ZSTD_updateDUBT(
* sort one already inserted but unsorted position
* assumption : current >= btlow == (current - btmask)
* doesn't fail */
-static void ZSTD_insertDUBT1(
- ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
+static void
+ZSTD_insertDUBT1(ZSTD_matchState_t* ms,
U32 current, const BYTE* inputEnd,
- U32 nbCompares, U32 btLow, int extDict)
+ U32 nbCompares, U32 btLow,
+ const ZSTD_dictMode_e dictMode)
{
- U32* const bt = ms->chainTable;
- U32 const btLog = cParams->chainLog - 1;
- U32 const btMask = (1 << btLog) - 1;
+ const ZSTD_compressionParameters* const cParams = &ms->cParams;
+ U32* const bt = ms->chainTable;
+ U32 const btLog = cParams->chainLog - 1;
+ U32 const btMask = (1 << btLog) - 1;
size_t commonLengthSmaller=0, commonLengthLarger=0;
const BYTE* const base = ms->window.base;
const BYTE* const dictBase = ms->window.dictBase;
@@ -78,7 +81,7 @@ static void ZSTD_insertDUBT1(
const BYTE* match;
U32* smallerPtr = bt + 2*(current&btMask);
U32* largerPtr = smallerPtr + 1;
- U32 matchIndex = *smallerPtr;
+ U32 matchIndex = *smallerPtr; /* this candidate is unsorted : next sorted candidate is reached through *smallerPtr, while *largerPtr contains previous unsorted candidate (which is already saved and can be overwritten) */
U32 dummy32; /* to be nullified at the end */
U32 const windowLow = ms->window.lowLimit;
@@ -91,11 +94,16 @@ static void ZSTD_insertDUBT1(
U32* const nextPtr = bt + 2*(matchIndex & btMask);
size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
assert(matchIndex < current);
+ /* note : all candidates are now supposed sorted,
+ * but it's still possible to have nextPtr[1] == ZSTD_DUBT_UNSORTED_MARK
+ * when a real index has the same value as ZSTD_DUBT_UNSORTED_MARK */
- if ( (!extDict)
+ if ( (dictMode != ZSTD_extDict)
|| (matchIndex+matchLength >= dictLimit) /* both in current segment*/
|| (current < dictLimit) /* both in extDict */) {
- const BYTE* const mBase = !extDict || ((matchIndex+matchLength) >= dictLimit) ? base : dictBase;
+ const BYTE* const mBase = ( (dictMode != ZSTD_extDict)
+ || (matchIndex+matchLength >= dictLimit)) ?
+ base : dictBase;
assert( (matchIndex+matchLength >= dictLimit) /* might be wrong if extDict is incorrectly set to 0 */
|| (current < dictLimit) );
match = mBase + matchIndex;
@@ -104,7 +112,7 @@ static void ZSTD_insertDUBT1(
match = dictBase + matchIndex;
matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart);
if (matchIndex+matchLength >= dictLimit)
- match = base + matchIndex; /* to prepare for next usage of match[matchLength] */
+ match = base + matchIndex; /* preparation for next read of match[matchLength] */
}
DEBUGLOG(8, "ZSTD_insertDUBT1: comparing %u with %u : found %u common bytes ",
@@ -138,13 +146,92 @@ static void ZSTD_insertDUBT1(
}
-static size_t ZSTD_DUBT_findBestMatch (
- ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
- const BYTE* const ip, const BYTE* const iend,
- size_t* offsetPtr,
- U32 const mls,
- U32 const extDict)
+static size_t
+ZSTD_DUBT_findBetterDictMatch (
+ ZSTD_matchState_t* ms,
+ const BYTE* const ip, const BYTE* const iend,
+ size_t* offsetPtr,
+ size_t bestLength,
+ U32 nbCompares,
+ U32 const mls,
+ const ZSTD_dictMode_e dictMode)
+{
+ const ZSTD_matchState_t * const dms = ms->dictMatchState;
+ const ZSTD_compressionParameters* const dmsCParams = &dms->cParams;
+ const U32 * const dictHashTable = dms->hashTable;
+ U32 const hashLog = dmsCParams->hashLog;
+ size_t const h = ZSTD_hashPtr(ip, hashLog, mls);
+ U32 dictMatchIndex = dictHashTable[h];
+
+ const BYTE* const base = ms->window.base;
+ const BYTE* const prefixStart = base + ms->window.dictLimit;
+ U32 const current = (U32)(ip-base);
+ const BYTE* const dictBase = dms->window.base;
+ const BYTE* const dictEnd = dms->window.nextSrc;
+ U32 const dictHighLimit = (U32)(dms->window.nextSrc - dms->window.base);
+ U32 const dictLowLimit = dms->window.lowLimit;
+ U32 const dictIndexDelta = ms->window.lowLimit - dictHighLimit;
+
+ U32* const dictBt = dms->chainTable;
+ U32 const btLog = dmsCParams->chainLog - 1;
+ U32 const btMask = (1 << btLog) - 1;
+ U32 const btLow = (btMask >= dictHighLimit - dictLowLimit) ? dictLowLimit : dictHighLimit - btMask;
+
+ size_t commonLengthSmaller=0, commonLengthLarger=0;
+
+ (void)dictMode;
+ assert(dictMode == ZSTD_dictMatchState);
+
+ while (nbCompares-- && (dictMatchIndex > dictLowLimit)) {
+ U32* const nextPtr = dictBt + 2*(dictMatchIndex & btMask);
+ size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
+ const BYTE* match = dictBase + dictMatchIndex;
+ matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart);
+ if (dictMatchIndex+matchLength >= dictHighLimit)
+ match = base + dictMatchIndex + dictIndexDelta; /* to prepare for next usage of match[matchLength] */
+
+ if (matchLength > bestLength) {
+ U32 matchIndex = dictMatchIndex + dictIndexDelta;
+ if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit32(current-matchIndex+1) - ZSTD_highbit32((U32)offsetPtr[0]+1)) ) {
+ DEBUGLOG(9, "ZSTD_DUBT_findBetterDictMatch(%u) : found better match length %u -> %u and offsetCode %u -> %u (dictMatchIndex %u, matchIndex %u)",
+ current, (U32)bestLength, (U32)matchLength, (U32)*offsetPtr, ZSTD_REP_MOVE + current - matchIndex, dictMatchIndex, matchIndex);
+ bestLength = matchLength, *offsetPtr = ZSTD_REP_MOVE + current - matchIndex;
+ }
+ if (ip+matchLength == iend) { /* reached end of input : ip[matchLength] is not valid, no way to know if it's larger or smaller than match */
+ break; /* drop, to guarantee consistency (miss a little bit of compression) */
+ }
+ }
+
+ if (match[matchLength] < ip[matchLength]) {
+ if (dictMatchIndex <= btLow) { break; } /* beyond tree size, stop the search */
+ commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */
+ dictMatchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
+ } else {
+ /* match is larger than current */
+ if (dictMatchIndex <= btLow) { break; } /* beyond tree size, stop the search */
+ commonLengthLarger = matchLength;
+ dictMatchIndex = nextPtr[0];
+ }
+ }
+
+ if (bestLength >= MINMATCH) {
+ U32 const mIndex = current - ((U32)*offsetPtr - ZSTD_REP_MOVE); (void)mIndex;
+ DEBUGLOG(8, "ZSTD_DUBT_findBetterDictMatch(%u) : found match of length %u and offsetCode %u (pos %u)",
+ current, (U32)bestLength, (U32)*offsetPtr, mIndex);
+ }
+ return bestLength;
+
+}
+
+
+static size_t
+ZSTD_DUBT_findBestMatch(ZSTD_matchState_t* ms,
+ const BYTE* const ip, const BYTE* const iend,
+ size_t* offsetPtr,
+ U32 const mls,
+ const ZSTD_dictMode_e dictMode)
{
+ const ZSTD_compressionParameters* const cParams = &ms->cParams;
U32* const hashTable = ms->hashTable;
U32 const hashLog = cParams->hashLog;
size_t const h = ZSTD_hashPtr(ip, hashLog, mls);
@@ -175,7 +262,7 @@ static size_t ZSTD_DUBT_findBestMatch (
&& (nbCandidates > 1) ) {
DEBUGLOG(8, "ZSTD_DUBT_findBestMatch: candidate %u is unsorted",
matchIndex);
- *unsortedMark = previousCandidate;
+ *unsortedMark = previousCandidate; /* the unsortedMark becomes a reversed chain, to move up back to original position */
previousCandidate = matchIndex;
matchIndex = *nextCandidate;
nextCandidate = bt + 2*(matchIndex&btMask);
@@ -183,11 +270,13 @@ static size_t ZSTD_DUBT_findBestMatch (
nbCandidates --;
}
+ /* nullify last candidate if it's still unsorted
+ * simplification, detrimental to compression ratio, beneficial for speed */
if ( (matchIndex > unsortLimit)
&& (*unsortedMark==ZSTD_DUBT_UNSORTED_MARK) ) {
DEBUGLOG(7, "ZSTD_DUBT_findBestMatch: nullify last unsorted candidate %u",
matchIndex);
- *nextCandidate = *unsortedMark = 0; /* nullify next candidate if it's still unsorted (note : simplification, detrimental to compression ratio, beneficial for speed) */
+ *nextCandidate = *unsortedMark = 0;
}
/* batch sort stacked candidates */
@@ -195,21 +284,21 @@ static size_t ZSTD_DUBT_findBestMatch (
while (matchIndex) { /* will end on matchIndex == 0 */
U32* const nextCandidateIdxPtr = bt + 2*(matchIndex&btMask) + 1;
U32 const nextCandidateIdx = *nextCandidateIdxPtr;
- ZSTD_insertDUBT1(ms, cParams, matchIndex, iend,
- nbCandidates, unsortLimit, extDict);
+ ZSTD_insertDUBT1(ms, matchIndex, iend,
+ nbCandidates, unsortLimit, dictMode);
matchIndex = nextCandidateIdx;
nbCandidates++;
}
/* find longest match */
- { size_t commonLengthSmaller=0, commonLengthLarger=0;
+ { size_t commonLengthSmaller = 0, commonLengthLarger = 0;
const BYTE* const dictBase = ms->window.dictBase;
const U32 dictLimit = ms->window.dictLimit;
const BYTE* const dictEnd = dictBase + dictLimit;
const BYTE* const prefixStart = base + dictLimit;
U32* smallerPtr = bt + 2*(current&btMask);
U32* largerPtr = bt + 2*(current&btMask) + 1;
- U32 matchEndIdx = current+8+1;
+ U32 matchEndIdx = current + 8 + 1;
U32 dummy32; /* to be nullified at the end */
size_t bestLength = 0;
@@ -221,7 +310,7 @@ static size_t ZSTD_DUBT_findBestMatch (
size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
const BYTE* match;
- if ((!extDict) || (matchIndex+matchLength >= dictLimit)) {
+ if ((dictMode != ZSTD_extDict) || (matchIndex+matchLength >= dictLimit)) {
match = base + matchIndex;
matchLength += ZSTD_count(ip+matchLength, match+matchLength, iend);
} else {
@@ -237,6 +326,11 @@ static size_t ZSTD_DUBT_findBestMatch (
if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit32(current-matchIndex+1) - ZSTD_highbit32((U32)offsetPtr[0]+1)) )
bestLength = matchLength, *offsetPtr = ZSTD_REP_MOVE + current - matchIndex;
if (ip+matchLength == iend) { /* equal : no way to know if inf or sup */
+ if (dictMode == ZSTD_dictMatchState) {
+ nbCompares = 0; /* in addition to avoiding checking any
+ * further in this loop, make sure we
+ * skip checking in the dictionary. */
+ }
break; /* drop, to guarantee consistency (miss a little bit of compression) */
}
}
@@ -259,6 +353,13 @@ static size_t ZSTD_DUBT_findBestMatch (
*smallerPtr = *largerPtr = 0;
+ if (dictMode == ZSTD_dictMatchState && nbCompares) {
+ bestLength = ZSTD_DUBT_findBetterDictMatch(
+ ms, ip, iend,
+ offsetPtr, bestLength, nbCompares,
+ mls, dictMode);
+ }
+
assert(matchEndIdx > current+8); /* ensure nextToUpdate is increased */
ms->nextToUpdate = matchEndIdx - 8; /* skip repetitive patterns */
if (bestLength >= MINMATCH) {
@@ -272,61 +373,64 @@ static size_t ZSTD_DUBT_findBestMatch (
/** ZSTD_BtFindBestMatch() : Tree updater, providing best match */
-static size_t ZSTD_BtFindBestMatch (
- ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
- const BYTE* const ip, const BYTE* const iLimit,
- size_t* offsetPtr,
- const U32 mls /* template */)
+FORCE_INLINE_TEMPLATE size_t
+ZSTD_BtFindBestMatch( ZSTD_matchState_t* ms,
+ const BYTE* const ip, const BYTE* const iLimit,
+ size_t* offsetPtr,
+ const U32 mls /* template */,
+ const ZSTD_dictMode_e dictMode)
{
DEBUGLOG(7, "ZSTD_BtFindBestMatch");
if (ip < ms->window.base + ms->nextToUpdate) return 0; /* skipped area */
- ZSTD_updateDUBT(ms, cParams, ip, iLimit, mls);
- return ZSTD_DUBT_findBestMatch(ms, cParams, ip, iLimit, offsetPtr, mls, 0);
+ ZSTD_updateDUBT(ms, ip, iLimit, mls);
+ return ZSTD_DUBT_findBestMatch(ms, ip, iLimit, offsetPtr, mls, dictMode);
}
-static size_t ZSTD_BtFindBestMatch_selectMLS (
- ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
- const BYTE* ip, const BYTE* const iLimit,
- size_t* offsetPtr)
+static size_t
+ZSTD_BtFindBestMatch_selectMLS ( ZSTD_matchState_t* ms,
+ const BYTE* ip, const BYTE* const iLimit,
+ size_t* offsetPtr)
{
- switch(cParams->searchLength)
+ switch(ms->cParams.minMatch)
{
default : /* includes case 3 */
- case 4 : return ZSTD_BtFindBestMatch(ms, cParams, ip, iLimit, offsetPtr, 4);
- case 5 : return ZSTD_BtFindBestMatch(ms, cParams, ip, iLimit, offsetPtr, 5);
+ case 4 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 4, ZSTD_noDict);
+ case 5 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 5, ZSTD_noDict);
case 7 :
- case 6 : return ZSTD_BtFindBestMatch(ms, cParams, ip, iLimit, offsetPtr, 6);
+ case 6 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 6, ZSTD_noDict);
}
}
-/** Tree updater, providing best match */
-static size_t ZSTD_BtFindBestMatch_extDict (
- ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
- const BYTE* const ip, const BYTE* const iLimit,
- size_t* offsetPtr,
- const U32 mls)
+static size_t ZSTD_BtFindBestMatch_dictMatchState_selectMLS (
+ ZSTD_matchState_t* ms,
+ const BYTE* ip, const BYTE* const iLimit,
+ size_t* offsetPtr)
{
- DEBUGLOG(7, "ZSTD_BtFindBestMatch_extDict");
- if (ip < ms->window.base + ms->nextToUpdate) return 0; /* skipped area */
- ZSTD_updateDUBT(ms, cParams, ip, iLimit, mls);
- return ZSTD_DUBT_findBestMatch(ms, cParams, ip, iLimit, offsetPtr, mls, 1);
+ switch(ms->cParams.minMatch)
+ {
+ default : /* includes case 3 */
+ case 4 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 4, ZSTD_dictMatchState);
+ case 5 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 5, ZSTD_dictMatchState);
+ case 7 :
+ case 6 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 6, ZSTD_dictMatchState);
+ }
}
-static size_t ZSTD_BtFindBestMatch_selectMLS_extDict (
- ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
+static size_t ZSTD_BtFindBestMatch_extDict_selectMLS (
+ ZSTD_matchState_t* ms,
const BYTE* ip, const BYTE* const iLimit,
size_t* offsetPtr)
{
- switch(cParams->searchLength)
+ switch(ms->cParams.minMatch)
{
default : /* includes case 3 */
- case 4 : return ZSTD_BtFindBestMatch_extDict(ms, cParams, ip, iLimit, offsetPtr, 4);
- case 5 : return ZSTD_BtFindBestMatch_extDict(ms, cParams, ip, iLimit, offsetPtr, 5);
+ case 4 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 4, ZSTD_extDict);
+ case 5 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 5, ZSTD_extDict);
case 7 :
- case 6 : return ZSTD_BtFindBestMatch_extDict(ms, cParams, ip, iLimit, offsetPtr, 6);
+ case 6 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 6, ZSTD_extDict);
}
}
@@ -335,12 +439,13 @@ static size_t ZSTD_BtFindBestMatch_selectMLS_extDict (
/* *********************************
* Hash Chain
***********************************/
-#define NEXT_IN_CHAIN(d, mask) chainTable[(d) & mask]
+#define NEXT_IN_CHAIN(d, mask) chainTable[(d) & (mask)]
/* Update chains up to ip (excluded)
Assumption : always within prefix (i.e. not within extDict) */
static U32 ZSTD_insertAndFindFirstIndex_internal(
- ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
+ ZSTD_matchState_t* ms,
+ const ZSTD_compressionParameters* const cParams,
const BYTE* ip, U32 const mls)
{
U32* const hashTable = ms->hashTable;
@@ -362,22 +467,21 @@ static U32 ZSTD_insertAndFindFirstIndex_internal(
return hashTable[ZSTD_hashPtr(ip, hashLog, mls)];
}
-U32 ZSTD_insertAndFindFirstIndex(
- ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
- const BYTE* ip)
-{
- return ZSTD_insertAndFindFirstIndex_internal(ms, cParams, ip, cParams->searchLength);
+U32 ZSTD_insertAndFindFirstIndex(ZSTD_matchState_t* ms, const BYTE* ip) {
+ const ZSTD_compressionParameters* const cParams = &ms->cParams;
+ return ZSTD_insertAndFindFirstIndex_internal(ms, cParams, ip, ms->cParams.minMatch);
}
/* inlining is important to hardwire a hot branch (template emulation) */
FORCE_INLINE_TEMPLATE
size_t ZSTD_HcFindBestMatch_generic (
- ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
+ ZSTD_matchState_t* ms,
const BYTE* const ip, const BYTE* const iLimit,
size_t* offsetPtr,
- const U32 mls, const U32 extDict)
+ const U32 mls, const ZSTD_dictMode_e dictMode)
{
+ const ZSTD_compressionParameters* const cParams = &ms->cParams;
U32* const chainTable = ms->chainTable;
const U32 chainSize = (1 << cParams->chainLog);
const U32 chainMask = chainSize-1;
@@ -397,8 +501,9 @@ size_t ZSTD_HcFindBestMatch_generic (
for ( ; (matchIndex>lowLimit) & (nbAttempts>0) ; nbAttempts--) {
size_t currentMl=0;
- if ((!extDict) || matchIndex >= dictLimit) {
+ if ((dictMode != ZSTD_extDict) || matchIndex >= dictLimit) {
const BYTE* const match = base + matchIndex;
+ assert(matchIndex >= dictLimit); /* ensures this is true if dictMode != ZSTD_extDict */
if (match[ml] == ip[ml]) /* potentially better */
currentMl = ZSTD_count(ip, match, iLimit);
} else {
@@ -419,38 +524,87 @@ size_t ZSTD_HcFindBestMatch_generic (
matchIndex = NEXT_IN_CHAIN(matchIndex, chainMask);
}
+ if (dictMode == ZSTD_dictMatchState) {
+ const ZSTD_matchState_t* const dms = ms->dictMatchState;
+ const U32* const dmsChainTable = dms->chainTable;
+ const U32 dmsChainSize = (1 << dms->cParams.chainLog);
+ const U32 dmsChainMask = dmsChainSize - 1;
+ const U32 dmsLowestIndex = dms->window.dictLimit;
+ const BYTE* const dmsBase = dms->window.base;
+ const BYTE* const dmsEnd = dms->window.nextSrc;
+ const U32 dmsSize = (U32)(dmsEnd - dmsBase);
+ const U32 dmsIndexDelta = dictLimit - dmsSize;
+ const U32 dmsMinChain = dmsSize > dmsChainSize ? dmsSize - dmsChainSize : 0;
+
+ matchIndex = dms->hashTable[ZSTD_hashPtr(ip, dms->cParams.hashLog, mls)];
+
+ for ( ; (matchIndex>dmsLowestIndex) & (nbAttempts>0) ; nbAttempts--) {
+ size_t currentMl=0;
+ const BYTE* const match = dmsBase + matchIndex;
+ assert(match+4 <= dmsEnd);
+ if (MEM_read32(match) == MEM_read32(ip)) /* assumption : matchIndex <= dictLimit-4 (by table construction) */
+ currentMl = ZSTD_count_2segments(ip+4, match+4, iLimit, dmsEnd, prefixStart) + 4;
+
+ /* save best solution */
+ if (currentMl > ml) {
+ ml = currentMl;
+ *offsetPtr = current - (matchIndex + dmsIndexDelta) + ZSTD_REP_MOVE;
+ if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */
+ }
+
+ if (matchIndex <= dmsMinChain) break;
+ matchIndex = dmsChainTable[matchIndex & dmsChainMask];
+ }
+ }
+
return ml;
}
FORCE_INLINE_TEMPLATE size_t ZSTD_HcFindBestMatch_selectMLS (
- ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
+ ZSTD_matchState_t* ms,
const BYTE* ip, const BYTE* const iLimit,
size_t* offsetPtr)
{
- switch(cParams->searchLength)
+ switch(ms->cParams.minMatch)
{
default : /* includes case 3 */
- case 4 : return ZSTD_HcFindBestMatch_generic(ms, cParams, ip, iLimit, offsetPtr, 4, 0);
- case 5 : return ZSTD_HcFindBestMatch_generic(ms, cParams, ip, iLimit, offsetPtr, 5, 0);
+ case 4 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 4, ZSTD_noDict);
+ case 5 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 5, ZSTD_noDict);
case 7 :
- case 6 : return ZSTD_HcFindBestMatch_generic(ms, cParams, ip, iLimit, offsetPtr, 6, 0);
+ case 6 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 6, ZSTD_noDict);
+ }
+}
+
+
+static size_t ZSTD_HcFindBestMatch_dictMatchState_selectMLS (
+ ZSTD_matchState_t* ms,
+ const BYTE* ip, const BYTE* const iLimit,
+ size_t* offsetPtr)
+{
+ switch(ms->cParams.minMatch)
+ {
+ default : /* includes case 3 */
+ case 4 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 4, ZSTD_dictMatchState);
+ case 5 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 5, ZSTD_dictMatchState);
+ case 7 :
+ case 6 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 6, ZSTD_dictMatchState);
}
}
FORCE_INLINE_TEMPLATE size_t ZSTD_HcFindBestMatch_extDict_selectMLS (
- ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
+ ZSTD_matchState_t* ms,
const BYTE* ip, const BYTE* const iLimit,
- size_t* const offsetPtr)
+ size_t* offsetPtr)
{
- switch(cParams->searchLength)
+ switch(ms->cParams.minMatch)
{
default : /* includes case 3 */
- case 4 : return ZSTD_HcFindBestMatch_generic(ms, cParams, ip, iLimit, offsetPtr, 4, 1);
- case 5 : return ZSTD_HcFindBestMatch_generic(ms, cParams, ip, iLimit, offsetPtr, 5, 1);
+ case 4 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 4, ZSTD_extDict);
+ case 5 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 5, ZSTD_extDict);
case 7 :
- case 6 : return ZSTD_HcFindBestMatch_generic(ms, cParams, ip, iLimit, offsetPtr, 6, 1);
+ case 6 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 6, ZSTD_extDict);
}
}
@@ -462,30 +616,55 @@ FORCE_INLINE_TEMPLATE
size_t ZSTD_compressBlock_lazy_generic(
ZSTD_matchState_t* ms, seqStore_t* seqStore,
U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams,
const void* src, size_t srcSize,
- const U32 searchMethod, const U32 depth)
+ const U32 searchMethod, const U32 depth,
+ ZSTD_dictMode_e const dictMode)
{
const BYTE* const istart = (const BYTE*)src;
const BYTE* ip = istart;
const BYTE* anchor = istart;
const BYTE* const iend = istart + srcSize;
const BYTE* const ilimit = iend - 8;
- const BYTE* const base = ms->window.base + ms->window.dictLimit;
+ const BYTE* const base = ms->window.base;
+ const U32 prefixLowestIndex = ms->window.dictLimit;
+ const BYTE* const prefixLowest = base + prefixLowestIndex;
typedef size_t (*searchMax_f)(
- ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
+ ZSTD_matchState_t* ms,
const BYTE* ip, const BYTE* iLimit, size_t* offsetPtr);
- searchMax_f const searchMax = searchMethod ? ZSTD_BtFindBestMatch_selectMLS : ZSTD_HcFindBestMatch_selectMLS;
+ searchMax_f const searchMax = dictMode == ZSTD_dictMatchState ?
+ (searchMethod ? ZSTD_BtFindBestMatch_dictMatchState_selectMLS : ZSTD_HcFindBestMatch_dictMatchState_selectMLS) :
+ (searchMethod ? ZSTD_BtFindBestMatch_selectMLS : ZSTD_HcFindBestMatch_selectMLS);
U32 offset_1 = rep[0], offset_2 = rep[1], savedOffset=0;
+ const ZSTD_matchState_t* const dms = ms->dictMatchState;
+ const U32 dictLowestIndex = dictMode == ZSTD_dictMatchState ?
+ dms->window.dictLimit : 0;
+ const BYTE* const dictBase = dictMode == ZSTD_dictMatchState ?
+ dms->window.base : NULL;
+ const BYTE* const dictLowest = dictMode == ZSTD_dictMatchState ?
+ dictBase + dictLowestIndex : NULL;
+ const BYTE* const dictEnd = dictMode == ZSTD_dictMatchState ?
+ dms->window.nextSrc : NULL;
+ const U32 dictIndexDelta = dictMode == ZSTD_dictMatchState ?
+ prefixLowestIndex - (U32)(dictEnd - dictBase) :
+ 0;
+ const U32 dictAndPrefixLength = (U32)(ip - prefixLowest + dictEnd - dictLowest);
+
/* init */
- ip += (ip==base);
+ ip += (dictAndPrefixLength == 0);
ms->nextToUpdate3 = ms->nextToUpdate;
- { U32 const maxRep = (U32)(ip-base);
+ if (dictMode == ZSTD_noDict) {
+ U32 const maxRep = (U32)(ip - prefixLowest);
if (offset_2 > maxRep) savedOffset = offset_2, offset_2 = 0;
if (offset_1 > maxRep) savedOffset = offset_1, offset_1 = 0;
}
+ if (dictMode == ZSTD_dictMatchState) {
+ /* dictMatchState repCode checks don't currently handle repCode == 0
+ * disabling. */
+ assert(offset_1 <= dictAndPrefixLength);
+ assert(offset_2 <= dictAndPrefixLength);
+ }
/* Match Loop */
while (ip < ilimit) {
@@ -494,15 +673,28 @@ size_t ZSTD_compressBlock_lazy_generic(
const BYTE* start=ip+1;
/* check repCode */
- if ((offset_1>0) & (MEM_read32(ip+1) == MEM_read32(ip+1 - offset_1))) {
- /* repcode : we take it */
+ if (dictMode == ZSTD_dictMatchState) {
+ const U32 repIndex = (U32)(ip - base) + 1 - offset_1;
+ const BYTE* repMatch = (dictMode == ZSTD_dictMatchState
+ && repIndex < prefixLowestIndex) ?
+ dictBase + (repIndex - dictIndexDelta) :
+ base + repIndex;
+ if (((U32)((prefixLowestIndex-1) - repIndex) >= 3 /* intentional underflow */)
+ && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
+ const BYTE* repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend;
+ matchLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixLowest) + 4;
+ if (depth==0) goto _storeSequence;
+ }
+ }
+ if ( dictMode == ZSTD_noDict
+ && ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1)))) {
matchLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;
if (depth==0) goto _storeSequence;
}
/* first search (depth 0) */
- { size_t offsetFound = 99999999;
- size_t const ml2 = searchMax(ms, cParams, ip, iend, &offsetFound);
+ { size_t offsetFound = 999999999;
+ size_t const ml2 = searchMax(ms, ip, iend, &offsetFound);
if (ml2 > matchLength)
matchLength = ml2, start = ip, offset=offsetFound;
}
@@ -516,15 +708,31 @@ size_t ZSTD_compressBlock_lazy_generic(
if (depth>=1)
while (ip<ilimit) {
ip ++;
- if ((offset) && ((offset_1>0) & (MEM_read32(ip) == MEM_read32(ip - offset_1)))) {
+ if ( (dictMode == ZSTD_noDict)
+ && (offset) && ((offset_1>0) & (MEM_read32(ip) == MEM_read32(ip - offset_1)))) {
size_t const mlRep = ZSTD_count(ip+4, ip+4-offset_1, iend) + 4;
int const gain2 = (int)(mlRep * 3);
int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)offset+1) + 1);
if ((mlRep >= 4) && (gain2 > gain1))
matchLength = mlRep, offset = 0, start = ip;
}
- { size_t offset2=99999999;
- size_t const ml2 = searchMax(ms, cParams, ip, iend, &offset2);
+ if (dictMode == ZSTD_dictMatchState) {
+ const U32 repIndex = (U32)(ip - base) - offset_1;
+ const BYTE* repMatch = repIndex < prefixLowestIndex ?
+ dictBase + (repIndex - dictIndexDelta) :
+ base + repIndex;
+ if (((U32)((prefixLowestIndex-1) - repIndex) >= 3 /* intentional underflow */)
+ && (MEM_read32(repMatch) == MEM_read32(ip)) ) {
+ const BYTE* repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend;
+ size_t const mlRep = ZSTD_count_2segments(ip+4, repMatch+4, iend, repMatchEnd, prefixLowest) + 4;
+ int const gain2 = (int)(mlRep * 3);
+ int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)offset+1) + 1);
+ if ((mlRep >= 4) && (gain2 > gain1))
+ matchLength = mlRep, offset = 0, start = ip;
+ }
+ }
+ { size_t offset2=999999999;
+ size_t const ml2 = searchMax(ms, ip, iend, &offset2);
int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 4);
if ((ml2 >= 4) && (gain2 > gain1)) {
@@ -535,15 +743,31 @@ size_t ZSTD_compressBlock_lazy_generic(
/* let's find an even better one */
if ((depth==2) && (ip<ilimit)) {
ip ++;
- if ((offset) && ((offset_1>0) & (MEM_read32(ip) == MEM_read32(ip - offset_1)))) {
- size_t const ml2 = ZSTD_count(ip+4, ip+4-offset_1, iend) + 4;
- int const gain2 = (int)(ml2 * 4);
+ if ( (dictMode == ZSTD_noDict)
+ && (offset) && ((offset_1>0) & (MEM_read32(ip) == MEM_read32(ip - offset_1)))) {
+ size_t const mlRep = ZSTD_count(ip+4, ip+4-offset_1, iend) + 4;
+ int const gain2 = (int)(mlRep * 4);
int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 1);
- if ((ml2 >= 4) && (gain2 > gain1))
- matchLength = ml2, offset = 0, start = ip;
+ if ((mlRep >= 4) && (gain2 > gain1))
+ matchLength = mlRep, offset = 0, start = ip;
}
- { size_t offset2=99999999;
- size_t const ml2 = searchMax(ms, cParams, ip, iend, &offset2);
+ if (dictMode == ZSTD_dictMatchState) {
+ const U32 repIndex = (U32)(ip - base) - offset_1;
+ const BYTE* repMatch = repIndex < prefixLowestIndex ?
+ dictBase + (repIndex - dictIndexDelta) :
+ base + repIndex;
+ if (((U32)((prefixLowestIndex-1) - repIndex) >= 3 /* intentional underflow */)
+ && (MEM_read32(repMatch) == MEM_read32(ip)) ) {
+ const BYTE* repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend;
+ size_t const mlRep = ZSTD_count_2segments(ip+4, repMatch+4, iend, repMatchEnd, prefixLowest) + 4;
+ int const gain2 = (int)(mlRep * 4);
+ int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 1);
+ if ((mlRep >= 4) && (gain2 > gain1))
+ matchLength = mlRep, offset = 0, start = ip;
+ }
+ }
+ { size_t offset2=999999999;
+ size_t const ml2 = searchMax(ms, ip, iend, &offset2);
int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 7);
if ((ml2 >= 4) && (gain2 > gain1)) {
@@ -560,9 +784,17 @@ size_t ZSTD_compressBlock_lazy_generic(
*/
/* catch up */
if (offset) {
- while ( ((start > anchor) & (start - (offset-ZSTD_REP_MOVE) > base))
- && (start[-1] == (start-(offset-ZSTD_REP_MOVE))[-1]) ) /* only search for offset within prefix */
- { start--; matchLength++; }
+ if (dictMode == ZSTD_noDict) {
+ while ( ((start > anchor) & (start - (offset-ZSTD_REP_MOVE) > prefixLowest))
+ && (start[-1] == (start-(offset-ZSTD_REP_MOVE))[-1]) ) /* only search for offset within prefix */
+ { start--; matchLength++; }
+ }
+ if (dictMode == ZSTD_dictMatchState) {
+ U32 const matchIndex = (U32)((start-base) - (offset - ZSTD_REP_MOVE));
+ const BYTE* match = (matchIndex < prefixLowestIndex) ? dictBase + matchIndex - dictIndexDelta : base + matchIndex;
+ const BYTE* const mStart = (matchIndex < prefixLowestIndex) ? dictLowest : prefixLowest;
+ while ((start>anchor) && (match>mStart) && (start[-1] == match[-1])) { start--; match--; matchLength++; } /* catch up */
+ }
offset_2 = offset_1; offset_1 = (U32)(offset - ZSTD_REP_MOVE);
}
/* store sequence */
@@ -573,16 +805,39 @@ _storeSequence:
}
/* check immediate repcode */
- while ( ((ip <= ilimit) & (offset_2>0))
- && (MEM_read32(ip) == MEM_read32(ip - offset_2)) ) {
- /* store sequence */
- matchLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;
- offset = offset_2; offset_2 = offset_1; offset_1 = (U32)offset; /* swap repcodes */
- ZSTD_storeSeq(seqStore, 0, anchor, 0, matchLength-MINMATCH);
- ip += matchLength;
- anchor = ip;
- continue; /* faster when present ... (?) */
- } }
+ if (dictMode == ZSTD_dictMatchState) {
+ while (ip <= ilimit) {
+ U32 const current2 = (U32)(ip-base);
+ U32 const repIndex = current2 - offset_2;
+ const BYTE* repMatch = dictMode == ZSTD_dictMatchState
+ && repIndex < prefixLowestIndex ?
+ dictBase - dictIndexDelta + repIndex :
+ base + repIndex;
+ if ( ((U32)((prefixLowestIndex-1) - (U32)repIndex) >= 3 /* intentional overflow */)
+ && (MEM_read32(repMatch) == MEM_read32(ip)) ) {
+ const BYTE* const repEnd2 = repIndex < prefixLowestIndex ? dictEnd : iend;
+ matchLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd2, prefixLowest) + 4;
+ offset = offset_2; offset_2 = offset_1; offset_1 = (U32)offset; /* swap offset_2 <=> offset_1 */
+ ZSTD_storeSeq(seqStore, 0, anchor, 0, matchLength-MINMATCH);
+ ip += matchLength;
+ anchor = ip;
+ continue;
+ }
+ break;
+ }
+ }
+
+ if (dictMode == ZSTD_noDict) {
+ while ( ((ip <= ilimit) & (offset_2>0))
+ && (MEM_read32(ip) == MEM_read32(ip - offset_2)) ) {
+ /* store sequence */
+ matchLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;
+ offset = offset_2; offset_2 = offset_1; offset_1 = (U32)offset; /* swap repcodes */
+ ZSTD_storeSeq(seqStore, 0, anchor, 0, matchLength-MINMATCH);
+ ip += matchLength;
+ anchor = ip;
+ continue; /* faster when present ... (?) */
+ } } }
/* Save reps for next block */
rep[0] = offset_1 ? offset_1 : savedOffset;
@@ -595,30 +850,58 @@ _storeSequence:
size_t ZSTD_compressBlock_btlazy2(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize)
+ void const* src, size_t srcSize)
{
- return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, cParams, src, srcSize, 1, 2);
+ return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, 1, 2, ZSTD_noDict);
}
size_t ZSTD_compressBlock_lazy2(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize)
+ void const* src, size_t srcSize)
{
- return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, cParams, src, srcSize, 0, 2);
+ return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, 0, 2, ZSTD_noDict);
}
size_t ZSTD_compressBlock_lazy(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize)
+ void const* src, size_t srcSize)
{
- return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, cParams, src, srcSize, 0, 1);
+ return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, 0, 1, ZSTD_noDict);
}
size_t ZSTD_compressBlock_greedy(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize)
+ void const* src, size_t srcSize)
+{
+ return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, 0, 0, ZSTD_noDict);
+}
+
+size_t ZSTD_compressBlock_btlazy2_dictMatchState(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize)
+{
+ return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, 1, 2, ZSTD_dictMatchState);
+}
+
+size_t ZSTD_compressBlock_lazy2_dictMatchState(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize)
+{
+ return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, 0, 2, ZSTD_dictMatchState);
+}
+
+size_t ZSTD_compressBlock_lazy_dictMatchState(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize)
+{
+ return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, 0, 1, ZSTD_dictMatchState);
+}
+
+size_t ZSTD_compressBlock_greedy_dictMatchState(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize)
{
- return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, cParams, src, srcSize, 0, 0);
+ return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, 0, 0, ZSTD_dictMatchState);
}
@@ -626,7 +909,6 @@ FORCE_INLINE_TEMPLATE
size_t ZSTD_compressBlock_lazy_extDict_generic(
ZSTD_matchState_t* ms, seqStore_t* seqStore,
U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams,
const void* src, size_t srcSize,
const U32 searchMethod, const U32 depth)
{
@@ -644,9 +926,9 @@ size_t ZSTD_compressBlock_lazy_extDict_generic(
const BYTE* const dictStart = dictBase + lowestIndex;
typedef size_t (*searchMax_f)(
- ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
+ ZSTD_matchState_t* ms,
const BYTE* ip, const BYTE* iLimit, size_t* offsetPtr);
- searchMax_f searchMax = searchMethod ? ZSTD_BtFindBestMatch_selectMLS_extDict : ZSTD_HcFindBestMatch_extDict_selectMLS;
+ searchMax_f searchMax = searchMethod ? ZSTD_BtFindBestMatch_extDict_selectMLS : ZSTD_HcFindBestMatch_extDict_selectMLS;
U32 offset_1 = rep[0], offset_2 = rep[1];
@@ -674,8 +956,8 @@ size_t ZSTD_compressBlock_lazy_extDict_generic(
} }
/* first search (depth 0) */
- { size_t offsetFound = 99999999;
- size_t const ml2 = searchMax(ms, cParams, ip, iend, &offsetFound);
+ { size_t offsetFound = 999999999;
+ size_t const ml2 = searchMax(ms, ip, iend, &offsetFound);
if (ml2 > matchLength)
matchLength = ml2, start = ip, offset=offsetFound;
}
@@ -707,8 +989,8 @@ size_t ZSTD_compressBlock_lazy_extDict_generic(
} }
/* search match, depth 1 */
- { size_t offset2=99999999;
- size_t const ml2 = searchMax(ms, cParams, ip, iend, &offset2);
+ { size_t offset2=999999999;
+ size_t const ml2 = searchMax(ms, ip, iend, &offset2);
int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 4);
if ((ml2 >= 4) && (gain2 > gain1)) {
@@ -737,8 +1019,8 @@ size_t ZSTD_compressBlock_lazy_extDict_generic(
} }
/* search match, depth 2 */
- { size_t offset2=99999999;
- size_t const ml2 = searchMax(ms, cParams, ip, iend, &offset2);
+ { size_t offset2=999999999;
+ size_t const ml2 = searchMax(ms, ip, iend, &offset2);
int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 7);
if ((ml2 >= 4) && (gain2 > gain1)) {
@@ -794,31 +1076,31 @@ _storeSequence:
size_t ZSTD_compressBlock_greedy_extDict(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize)
+ void const* src, size_t srcSize)
{
- return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, cParams, src, srcSize, 0, 0);
+ return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, 0, 0);
}
size_t ZSTD_compressBlock_lazy_extDict(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize)
+ void const* src, size_t srcSize)
{
- return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, cParams, src, srcSize, 0, 1);
+ return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, 0, 1);
}
size_t ZSTD_compressBlock_lazy2_extDict(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize)
+ void const* src, size_t srcSize)
{
- return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, cParams, src, srcSize, 0, 2);
+ return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, 0, 2);
}
size_t ZSTD_compressBlock_btlazy2_extDict(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize)
+ void const* src, size_t srcSize)
{
- return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, cParams, src, srcSize, 1, 2);
+ return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, 1, 2);
}
diff --git a/thirdparty/zstd/compress/zstd_lazy.h b/thirdparty/zstd/compress/zstd_lazy.h
index bda064f199..bb1763069f 100644
--- a/thirdparty/zstd/compress/zstd_lazy.h
+++ b/thirdparty/zstd/compress/zstd_lazy.h
@@ -17,37 +17,48 @@ extern "C" {
#include "zstd_compress_internal.h"
-U32 ZSTD_insertAndFindFirstIndex(
- ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
- const BYTE* ip);
+U32 ZSTD_insertAndFindFirstIndex(ZSTD_matchState_t* ms, const BYTE* ip);
-void ZSTD_preserveUnsortedMark (U32* const table, U32 const size, U32 const reducerValue); /*! used in ZSTD_reduceIndex(). pre-emptively increase value of ZSTD_DUBT_UNSORTED_MARK */
+void ZSTD_preserveUnsortedMark (U32* const table, U32 const size, U32 const reducerValue); /*! used in ZSTD_reduceIndex(). preemptively increase value of ZSTD_DUBT_UNSORTED_MARK */
size_t ZSTD_compressBlock_btlazy2(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
+ void const* src, size_t srcSize);
size_t ZSTD_compressBlock_lazy2(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
+ void const* src, size_t srcSize);
size_t ZSTD_compressBlock_lazy(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
+ void const* src, size_t srcSize);
size_t ZSTD_compressBlock_greedy(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
+ void const* src, size_t srcSize);
+
+size_t ZSTD_compressBlock_btlazy2_dictMatchState(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize);
+size_t ZSTD_compressBlock_lazy2_dictMatchState(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize);
+size_t ZSTD_compressBlock_lazy_dictMatchState(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize);
+size_t ZSTD_compressBlock_greedy_dictMatchState(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize);
size_t ZSTD_compressBlock_greedy_extDict(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
+ void const* src, size_t srcSize);
size_t ZSTD_compressBlock_lazy_extDict(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
+ void const* src, size_t srcSize);
size_t ZSTD_compressBlock_lazy2_extDict(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
+ void const* src, size_t srcSize);
size_t ZSTD_compressBlock_btlazy2_extDict(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
+ void const* src, size_t srcSize);
#if defined (__cplusplus)
}
diff --git a/thirdparty/zstd/compress/zstd_ldm.c b/thirdparty/zstd/compress/zstd_ldm.c
index bffd8a3dfa..784d20f3ab 100644
--- a/thirdparty/zstd/compress/zstd_ldm.c
+++ b/thirdparty/zstd/compress/zstd_ldm.c
@@ -9,6 +9,7 @@
#include "zstd_ldm.h"
+#include "debug.h"
#include "zstd_fast.h" /* ZSTD_fillHashTable() */
#include "zstd_double_fast.h" /* ZSTD_fillDoubleHashTable() */
@@ -20,7 +21,7 @@
void ZSTD_ldm_adjustParameters(ldmParams_t* params,
ZSTD_compressionParameters const* cParams)
{
- U32 const windowLog = cParams->windowLog;
+ params->windowLog = cParams->windowLog;
ZSTD_STATIC_ASSERT(LDM_BUCKET_SIZE_LOG <= ZSTD_LDM_BUCKETSIZELOG_MAX);
DEBUGLOG(4, "ZSTD_ldm_adjustParameters");
if (!params->bucketSizeLog) params->bucketSizeLog = LDM_BUCKET_SIZE_LOG;
@@ -33,12 +34,13 @@ void ZSTD_ldm_adjustParameters(ldmParams_t* params,
params->minMatchLength = minMatch;
}
if (params->hashLog == 0) {
- params->hashLog = MAX(ZSTD_HASHLOG_MIN, windowLog - LDM_HASH_RLOG);
+ params->hashLog = MAX(ZSTD_HASHLOG_MIN, params->windowLog - LDM_HASH_RLOG);
assert(params->hashLog <= ZSTD_HASHLOG_MAX);
}
- if (params->hashEveryLog == 0) {
- params->hashEveryLog =
- windowLog < params->hashLog ? 0 : windowLog - params->hashLog;
+ if (params->hashRateLog == 0) {
+ params->hashRateLog = params->windowLog < params->hashLog
+ ? 0
+ : params->windowLog - params->hashLog;
}
params->bucketSizeLog = MIN(params->bucketSizeLog, params->hashLog);
}
@@ -117,20 +119,20 @@ static void ZSTD_ldm_insertEntry(ldmState_t* ldmState,
*
* Gets the small hash, checksum, and tag from the rollingHash.
*
- * If the tag matches (1 << ldmParams.hashEveryLog)-1, then
+ * If the tag matches (1 << ldmParams.hashRateLog)-1, then
* creates an ldmEntry from the offset, and inserts it into the hash table.
*
* hBits is the length of the small hash, which is the most significant hBits
* of rollingHash. The checksum is the next 32 most significant bits, followed
- * by ldmParams.hashEveryLog bits that make up the tag. */
+ * by ldmParams.hashRateLog bits that make up the tag. */
static void ZSTD_ldm_makeEntryAndInsertByTag(ldmState_t* ldmState,
U64 const rollingHash,
U32 const hBits,
U32 const offset,
ldmParams_t const ldmParams)
{
- U32 const tag = ZSTD_ldm_getTag(rollingHash, hBits, ldmParams.hashEveryLog);
- U32 const tagMask = ((U32)1 << ldmParams.hashEveryLog) - 1;
+ U32 const tag = ZSTD_ldm_getTag(rollingHash, hBits, ldmParams.hashRateLog);
+ U32 const tagMask = ((U32)1 << ldmParams.hashRateLog) - 1;
if (tag == tagMask) {
U32 const hash = ZSTD_ldm_getSmallHash(rollingHash, hBits);
U32 const checksum = ZSTD_ldm_getChecksum(rollingHash, hBits);
@@ -141,56 +143,6 @@ static void ZSTD_ldm_makeEntryAndInsertByTag(ldmState_t* ldmState,
}
}
-/** ZSTD_ldm_getRollingHash() :
- * Get a 64-bit hash using the first len bytes from buf.
- *
- * Giving bytes s = s_1, s_2, ... s_k, the hash is defined to be
- * H(s) = s_1*(a^(k-1)) + s_2*(a^(k-2)) + ... + s_k*(a^0)
- *
- * where the constant a is defined to be prime8bytes.
- *
- * The implementation adds an offset to each byte, so
- * H(s) = (s_1 + HASH_CHAR_OFFSET)*(a^(k-1)) + ... */
-static U64 ZSTD_ldm_getRollingHash(const BYTE* buf, U32 len)
-{
- U64 ret = 0;
- U32 i;
- for (i = 0; i < len; i++) {
- ret *= prime8bytes;
- ret += buf[i] + LDM_HASH_CHAR_OFFSET;
- }
- return ret;
-}
-
-/** ZSTD_ldm_ipow() :
- * Return base^exp. */
-static U64 ZSTD_ldm_ipow(U64 base, U64 exp)
-{
- U64 ret = 1;
- while (exp) {
- if (exp & 1) { ret *= base; }
- exp >>= 1;
- base *= base;
- }
- return ret;
-}
-
-U64 ZSTD_ldm_getHashPower(U32 minMatchLength) {
- DEBUGLOG(4, "ZSTD_ldm_getHashPower: mml=%u", minMatchLength);
- assert(minMatchLength >= ZSTD_LDM_MINMATCH_MIN);
- return ZSTD_ldm_ipow(prime8bytes, minMatchLength - 1);
-}
-
-/** ZSTD_ldm_updateHash() :
- * Updates hash by removing toRemove and adding toAdd. */
-static U64 ZSTD_ldm_updateHash(U64 hash, BYTE toRemove, BYTE toAdd, U64 hashPower)
-{
- hash -= ((toRemove + LDM_HASH_CHAR_OFFSET) * hashPower);
- hash *= prime8bytes;
- hash += toAdd + LDM_HASH_CHAR_OFFSET;
- return hash;
-}
-
/** ZSTD_ldm_countBackwardsMatch() :
* Returns the number of bytes that match backwards before pIn and pMatch.
*
@@ -216,21 +168,18 @@ static size_t ZSTD_ldm_countBackwardsMatch(
* The tables for the other strategies are filled within their
* block compressors. */
static size_t ZSTD_ldm_fillFastTables(ZSTD_matchState_t* ms,
- ZSTD_compressionParameters const* cParams,
void const* end)
{
const BYTE* const iend = (const BYTE*)end;
- switch(cParams->strategy)
+ switch(ms->cParams.strategy)
{
case ZSTD_fast:
- ZSTD_fillHashTable(ms, cParams, iend);
- ms->nextToUpdate = (U32)(iend - ms->window.base);
+ ZSTD_fillHashTable(ms, iend, ZSTD_dtlm_fast);
break;
case ZSTD_dfast:
- ZSTD_fillDoubleHashTable(ms, cParams, iend);
- ms->nextToUpdate = (U32)(iend - ms->window.base);
+ ZSTD_fillDoubleHashTable(ms, iend, ZSTD_dtlm_fast);
break;
case ZSTD_greedy:
@@ -239,6 +188,7 @@ static size_t ZSTD_ldm_fillFastTables(ZSTD_matchState_t* ms,
case ZSTD_btlazy2:
case ZSTD_btopt:
case ZSTD_btultra:
+ case ZSTD_btultra2:
break;
default:
assert(0); /* not possible : not a valid strategy id */
@@ -262,9 +212,9 @@ static U64 ZSTD_ldm_fillLdmHashTable(ldmState_t* state,
const BYTE* cur = lastHashed + 1;
while (cur < iend) {
- rollingHash = ZSTD_ldm_updateHash(rollingHash, cur[-1],
- cur[ldmParams.minMatchLength-1],
- state->hashPower);
+ rollingHash = ZSTD_rollingHash_rotate(rollingHash, cur[-1],
+ cur[ldmParams.minMatchLength-1],
+ state->hashPower);
ZSTD_ldm_makeEntryAndInsertByTag(state,
rollingHash, hBits,
(U32)(cur - base), ldmParams);
@@ -298,8 +248,8 @@ static size_t ZSTD_ldm_generateSequences_internal(
U64 const hashPower = ldmState->hashPower;
U32 const hBits = params->hashLog - params->bucketSizeLog;
U32 const ldmBucketSize = 1U << params->bucketSizeLog;
- U32 const hashEveryLog = params->hashEveryLog;
- U32 const ldmTagMask = (1U << params->hashEveryLog) - 1;
+ U32 const hashRateLog = params->hashRateLog;
+ U32 const ldmTagMask = (1U << params->hashRateLog) - 1;
/* Prefix and extDict parameters */
U32 const dictLimit = ldmState->window.dictLimit;
U32 const lowestIndex = extDict ? ldmState->window.lowLimit : dictLimit;
@@ -325,16 +275,16 @@ static size_t ZSTD_ldm_generateSequences_internal(
size_t forwardMatchLength = 0, backwardMatchLength = 0;
ldmEntry_t* bestEntry = NULL;
if (ip != istart) {
- rollingHash = ZSTD_ldm_updateHash(rollingHash, lastHashed[0],
- lastHashed[minMatchLength],
- hashPower);
+ rollingHash = ZSTD_rollingHash_rotate(rollingHash, lastHashed[0],
+ lastHashed[minMatchLength],
+ hashPower);
} else {
- rollingHash = ZSTD_ldm_getRollingHash(ip, minMatchLength);
+ rollingHash = ZSTD_rollingHash_compute(ip, minMatchLength);
}
lastHashed = ip;
/* Do not insert and do not look for a match */
- if (ZSTD_ldm_getTag(rollingHash, hBits, hashEveryLog) != ldmTagMask) {
+ if (ZSTD_ldm_getTag(rollingHash, hBits, hashRateLog) != ldmTagMask) {
ip++;
continue;
}
@@ -479,7 +429,7 @@ size_t ZSTD_ldm_generateSequences(
*/
assert(ldmState->window.nextSrc >= (BYTE const*)src + srcSize);
/* The input could be very large (in zstdmt), so it must be broken up into
- * chunks to enforce the maximmum distance and handle overflow correction.
+ * chunks to enforce the maximum distance and handle overflow correction.
*/
assert(sequences->pos <= sequences->size);
assert(sequences->size <= sequences->capacity);
@@ -508,7 +458,7 @@ size_t ZSTD_ldm_generateSequences(
* * Try invalidation after the sequence generation and test the
* the offset against maxDist directly.
*/
- ZSTD_window_enforceMaxDist(&ldmState->window, chunkEnd, maxDist, NULL);
+ ZSTD_window_enforceMaxDist(&ldmState->window, chunkEnd, maxDist, NULL, NULL);
/* 3. Generate the sequences for the chunk, and get newLeftoverSize. */
newLeftoverSize = ZSTD_ldm_generateSequences_internal(
ldmState, sequences, params, chunkStart, chunkSize);
@@ -591,19 +541,19 @@ static rawSeq maybeSplitSequence(rawSeqStore_t* rawSeqStore,
size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize,
- int const extDict)
+ void const* src, size_t srcSize)
{
- unsigned const minMatch = cParams->searchLength;
+ const ZSTD_compressionParameters* const cParams = &ms->cParams;
+ unsigned const minMatch = cParams->minMatch;
ZSTD_blockCompressor const blockCompressor =
- ZSTD_selectBlockCompressor(cParams->strategy, extDict);
- BYTE const* const base = ms->window.base;
+ ZSTD_selectBlockCompressor(cParams->strategy, ZSTD_matchState_dictMode(ms));
/* Input bounds */
BYTE const* const istart = (BYTE const*)src;
BYTE const* const iend = istart + srcSize;
/* Input positions */
BYTE const* ip = istart;
+ DEBUGLOG(5, "ZSTD_ldm_blockCompress: srcSize=%zu", srcSize);
assert(rawSeqStore->pos <= rawSeqStore->size);
assert(rawSeqStore->size <= rawSeqStore->capacity);
/* Loop through each sequence and apply the block compressor to the lits */
@@ -621,14 +571,13 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
/* Fill tables for block compressor */
ZSTD_ldm_limitTableUpdate(ms, ip);
- ZSTD_ldm_fillFastTables(ms, cParams, ip);
+ ZSTD_ldm_fillFastTables(ms, ip);
/* Run the block compressor */
+ DEBUGLOG(5, "calling block compressor on segment of size %u", sequence.litLength);
{
size_t const newLitLength =
- blockCompressor(ms, seqStore, rep, cParams, ip,
- sequence.litLength);
+ blockCompressor(ms, seqStore, rep, ip, sequence.litLength);
ip += sequence.litLength;
- ms->nextToUpdate = (U32)(ip - base);
/* Update the repcodes */
for (i = ZSTD_REP_NUM - 1; i > 0; i--)
rep[i] = rep[i-1];
@@ -642,12 +591,7 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
}
/* Fill the tables for the block compressor */
ZSTD_ldm_limitTableUpdate(ms, ip);
- ZSTD_ldm_fillFastTables(ms, cParams, ip);
+ ZSTD_ldm_fillFastTables(ms, ip);
/* Compress the last literals */
- {
- size_t const lastLiterals = blockCompressor(ms, seqStore, rep, cParams,
- ip, iend - ip);
- ms->nextToUpdate = (U32)(iend - base);
- return lastLiterals;
- }
+ return blockCompressor(ms, seqStore, rep, ip, iend - ip);
}
diff --git a/thirdparty/zstd/compress/zstd_ldm.h b/thirdparty/zstd/compress/zstd_ldm.h
index 0c3789ff13..a47846128b 100644
--- a/thirdparty/zstd/compress/zstd_ldm.h
+++ b/thirdparty/zstd/compress/zstd_ldm.h
@@ -21,7 +21,7 @@ extern "C" {
* Long distance matching
***************************************/
-#define ZSTD_LDM_DEFAULT_WINDOW_LOG ZSTD_WINDOWLOG_DEFAULTMAX
+#define ZSTD_LDM_DEFAULT_WINDOW_LOG ZSTD_WINDOWLOG_LIMIT_DEFAULT
/**
* ZSTD_ldm_generateSequences():
@@ -61,9 +61,7 @@ size_t ZSTD_ldm_generateSequences(
*/
size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams,
- void const* src, size_t srcSize,
- int const extDict);
+ void const* src, size_t srcSize);
/**
* ZSTD_ldm_skipSequences():
@@ -88,12 +86,8 @@ size_t ZSTD_ldm_getTableSize(ldmParams_t params);
*/
size_t ZSTD_ldm_getMaxNbSeq(ldmParams_t params, size_t maxChunkSize);
-/** ZSTD_ldm_getTableSize() :
- * Return prime8bytes^(minMatchLength-1) */
-U64 ZSTD_ldm_getHashPower(U32 minMatchLength);
-
/** ZSTD_ldm_adjustParameters() :
- * If the params->hashEveryLog is not set, set it to its default value based on
+ * If the params->hashRateLog is not set, set it to its default value based on
* windowLog and params->hashLog.
*
* Ensures that params->bucketSizeLog is <= params->hashLog (setting it to
diff --git a/thirdparty/zstd/compress/zstd_opt.c b/thirdparty/zstd/compress/zstd_opt.c
index f63f0c5852..efb69d3267 100644
--- a/thirdparty/zstd/compress/zstd_opt.c
+++ b/thirdparty/zstd/compress/zstd_opt.c
@@ -9,139 +9,259 @@
*/
#include "zstd_compress_internal.h"
+#include "hist.h"
#include "zstd_opt.h"
-#define ZSTD_LITFREQ_ADD 2 /* scaling factor for litFreq, so that frequencies adapt faster to new stats. Also used for matchSum (?) */
+#define ZSTD_LITFREQ_ADD 2 /* scaling factor for litFreq, so that frequencies adapt faster to new stats */
#define ZSTD_FREQ_DIV 4 /* log factor when using previous stats to init next stats */
#define ZSTD_MAX_PRICE (1<<30)
+#define ZSTD_PREDEF_THRESHOLD 1024 /* if srcSize < ZSTD_PREDEF_THRESHOLD, symbols' cost is assumed static, directly determined by pre-defined distributions */
+
/*-*************************************
* Price functions for optimal parser
***************************************/
-static void ZSTD_setLog2Prices(optState_t* optPtr)
+
+#if 0 /* approximation at bit level */
+# define BITCOST_ACCURACY 0
+# define BITCOST_MULTIPLIER (1 << BITCOST_ACCURACY)
+# define WEIGHT(stat) ((void)opt, ZSTD_bitWeight(stat))
+#elif 0 /* fractional bit accuracy */
+# define BITCOST_ACCURACY 8
+# define BITCOST_MULTIPLIER (1 << BITCOST_ACCURACY)
+# define WEIGHT(stat,opt) ((void)opt, ZSTD_fracWeight(stat))
+#else /* opt==approx, ultra==accurate */
+# define BITCOST_ACCURACY 8
+# define BITCOST_MULTIPLIER (1 << BITCOST_ACCURACY)
+# define WEIGHT(stat,opt) (opt ? ZSTD_fracWeight(stat) : ZSTD_bitWeight(stat))
+#endif
+
+MEM_STATIC U32 ZSTD_bitWeight(U32 stat)
{
- optPtr->log2litSum = ZSTD_highbit32(optPtr->litSum+1);
- optPtr->log2litLengthSum = ZSTD_highbit32(optPtr->litLengthSum+1);
- optPtr->log2matchLengthSum = ZSTD_highbit32(optPtr->matchLengthSum+1);
- optPtr->log2offCodeSum = ZSTD_highbit32(optPtr->offCodeSum+1);
+ return (ZSTD_highbit32(stat+1) * BITCOST_MULTIPLIER);
}
+MEM_STATIC U32 ZSTD_fracWeight(U32 rawStat)
+{
+ U32 const stat = rawStat + 1;
+ U32 const hb = ZSTD_highbit32(stat);
+ U32 const BWeight = hb * BITCOST_MULTIPLIER;
+ U32 const FWeight = (stat << BITCOST_ACCURACY) >> hb;
+ U32 const weight = BWeight + FWeight;
+ assert(hb + BITCOST_ACCURACY < 31);
+ return weight;
+}
-static void ZSTD_rescaleFreqs(optState_t* const optPtr,
- const BYTE* const src, size_t const srcSize)
+#if (DEBUGLEVEL>=2)
+/* debugging function,
+ * @return price in bytes as fractional value
+ * for debug messages only */
+MEM_STATIC double ZSTD_fCost(U32 price)
{
- optPtr->staticPrices = 0;
+ return (double)price / (BITCOST_MULTIPLIER*8);
+}
+#endif
- if (optPtr->litLengthSum == 0) { /* first init */
- unsigned u;
- if (srcSize <= 1024) optPtr->staticPrices = 1;
+static int ZSTD_compressedLiterals(optState_t const* const optPtr)
+{
+ return optPtr->literalCompressionMode != ZSTD_lcm_uncompressed;
+}
- assert(optPtr->litFreq!=NULL);
- for (u=0; u<=MaxLit; u++)
- optPtr->litFreq[u] = 0;
- for (u=0; u<srcSize; u++)
- optPtr->litFreq[src[u]]++;
- optPtr->litSum = 0;
- for (u=0; u<=MaxLit; u++) {
- optPtr->litFreq[u] = 1 + (optPtr->litFreq[u] >> ZSTD_FREQ_DIV);
- optPtr->litSum += optPtr->litFreq[u];
- }
+static void ZSTD_setBasePrices(optState_t* optPtr, int optLevel)
+{
+ if (ZSTD_compressedLiterals(optPtr))
+ optPtr->litSumBasePrice = WEIGHT(optPtr->litSum, optLevel);
+ optPtr->litLengthSumBasePrice = WEIGHT(optPtr->litLengthSum, optLevel);
+ optPtr->matchLengthSumBasePrice = WEIGHT(optPtr->matchLengthSum, optLevel);
+ optPtr->offCodeSumBasePrice = WEIGHT(optPtr->offCodeSum, optLevel);
+}
- for (u=0; u<=MaxLL; u++)
- optPtr->litLengthFreq[u] = 1;
- optPtr->litLengthSum = MaxLL+1;
- for (u=0; u<=MaxML; u++)
- optPtr->matchLengthFreq[u] = 1;
- optPtr->matchLengthSum = MaxML+1;
- for (u=0; u<=MaxOff; u++)
- optPtr->offCodeFreq[u] = 1;
- optPtr->offCodeSum = (MaxOff+1);
-
- } else {
- unsigned u;
-
- optPtr->litSum = 0;
- for (u=0; u<=MaxLit; u++) {
- optPtr->litFreq[u] = 1 + (optPtr->litFreq[u] >> (ZSTD_FREQ_DIV+1));
- optPtr->litSum += optPtr->litFreq[u];
- }
- optPtr->litLengthSum = 0;
- for (u=0; u<=MaxLL; u++) {
- optPtr->litLengthFreq[u] = 1 + (optPtr->litLengthFreq[u]>>(ZSTD_FREQ_DIV+1));
- optPtr->litLengthSum += optPtr->litLengthFreq[u];
- }
- optPtr->matchLengthSum = 0;
- for (u=0; u<=MaxML; u++) {
- optPtr->matchLengthFreq[u] = 1 + (optPtr->matchLengthFreq[u]>>ZSTD_FREQ_DIV);
- optPtr->matchLengthSum += optPtr->matchLengthFreq[u];
+
+/* ZSTD_downscaleStat() :
+ * reduce all elements in table by a factor 2^(ZSTD_FREQ_DIV+malus)
+ * return the resulting sum of elements */
+static U32 ZSTD_downscaleStat(unsigned* table, U32 lastEltIndex, int malus)
+{
+ U32 s, sum=0;
+ DEBUGLOG(5, "ZSTD_downscaleStat (nbElts=%u)", (unsigned)lastEltIndex+1);
+ assert(ZSTD_FREQ_DIV+malus > 0 && ZSTD_FREQ_DIV+malus < 31);
+ for (s=0; s<lastEltIndex+1; s++) {
+ table[s] = 1 + (table[s] >> (ZSTD_FREQ_DIV+malus));
+ sum += table[s];
+ }
+ return sum;
+}
+
+/* ZSTD_rescaleFreqs() :
+ * if first block (detected by optPtr->litLengthSum == 0) : init statistics
+ * take hints from dictionary if there is one
+ * or init from zero, using src for literals stats, or flat 1 for match symbols
+ * otherwise downscale existing stats, to be used as seed for next block.
+ */
+static void
+ZSTD_rescaleFreqs(optState_t* const optPtr,
+ const BYTE* const src, size_t const srcSize,
+ int const optLevel)
+{
+ int const compressedLiterals = ZSTD_compressedLiterals(optPtr);
+ DEBUGLOG(5, "ZSTD_rescaleFreqs (srcSize=%u)", (unsigned)srcSize);
+ optPtr->priceType = zop_dynamic;
+
+ if (optPtr->litLengthSum == 0) { /* first block : init */
+ if (srcSize <= ZSTD_PREDEF_THRESHOLD) { /* heuristic */
+ DEBUGLOG(5, "(srcSize <= ZSTD_PREDEF_THRESHOLD) => zop_predef");
+ optPtr->priceType = zop_predef;
}
- optPtr->offCodeSum = 0;
- for (u=0; u<=MaxOff; u++) {
- optPtr->offCodeFreq[u] = 1 + (optPtr->offCodeFreq[u]>>ZSTD_FREQ_DIV);
- optPtr->offCodeSum += optPtr->offCodeFreq[u];
+
+ assert(optPtr->symbolCosts != NULL);
+ if (optPtr->symbolCosts->huf.repeatMode == HUF_repeat_valid) {
+ /* huffman table presumed generated by dictionary */
+ optPtr->priceType = zop_dynamic;
+
+ if (compressedLiterals) {
+ unsigned lit;
+ assert(optPtr->litFreq != NULL);
+ optPtr->litSum = 0;
+ for (lit=0; lit<=MaxLit; lit++) {
+ U32 const scaleLog = 11; /* scale to 2K */
+ U32 const bitCost = HUF_getNbBits(optPtr->symbolCosts->huf.CTable, lit);
+ assert(bitCost <= scaleLog);
+ optPtr->litFreq[lit] = bitCost ? 1 << (scaleLog-bitCost) : 1 /*minimum to calculate cost*/;
+ optPtr->litSum += optPtr->litFreq[lit];
+ } }
+
+ { unsigned ll;
+ FSE_CState_t llstate;
+ FSE_initCState(&llstate, optPtr->symbolCosts->fse.litlengthCTable);
+ optPtr->litLengthSum = 0;
+ for (ll=0; ll<=MaxLL; ll++) {
+ U32 const scaleLog = 10; /* scale to 1K */
+ U32 const bitCost = FSE_getMaxNbBits(llstate.symbolTT, ll);
+ assert(bitCost < scaleLog);
+ optPtr->litLengthFreq[ll] = bitCost ? 1 << (scaleLog-bitCost) : 1 /*minimum to calculate cost*/;
+ optPtr->litLengthSum += optPtr->litLengthFreq[ll];
+ } }
+
+ { unsigned ml;
+ FSE_CState_t mlstate;
+ FSE_initCState(&mlstate, optPtr->symbolCosts->fse.matchlengthCTable);
+ optPtr->matchLengthSum = 0;
+ for (ml=0; ml<=MaxML; ml++) {
+ U32 const scaleLog = 10;
+ U32 const bitCost = FSE_getMaxNbBits(mlstate.symbolTT, ml);
+ assert(bitCost < scaleLog);
+ optPtr->matchLengthFreq[ml] = bitCost ? 1 << (scaleLog-bitCost) : 1 /*minimum to calculate cost*/;
+ optPtr->matchLengthSum += optPtr->matchLengthFreq[ml];
+ } }
+
+ { unsigned of;
+ FSE_CState_t ofstate;
+ FSE_initCState(&ofstate, optPtr->symbolCosts->fse.offcodeCTable);
+ optPtr->offCodeSum = 0;
+ for (of=0; of<=MaxOff; of++) {
+ U32 const scaleLog = 10;
+ U32 const bitCost = FSE_getMaxNbBits(ofstate.symbolTT, of);
+ assert(bitCost < scaleLog);
+ optPtr->offCodeFreq[of] = bitCost ? 1 << (scaleLog-bitCost) : 1 /*minimum to calculate cost*/;
+ optPtr->offCodeSum += optPtr->offCodeFreq[of];
+ } }
+
+ } else { /* not a dictionary */
+
+ assert(optPtr->litFreq != NULL);
+ if (compressedLiterals) {
+ unsigned lit = MaxLit;
+ HIST_count_simple(optPtr->litFreq, &lit, src, srcSize); /* use raw first block to init statistics */
+ optPtr->litSum = ZSTD_downscaleStat(optPtr->litFreq, MaxLit, 1);
+ }
+
+ { unsigned ll;
+ for (ll=0; ll<=MaxLL; ll++)
+ optPtr->litLengthFreq[ll] = 1;
+ }
+ optPtr->litLengthSum = MaxLL+1;
+
+ { unsigned ml;
+ for (ml=0; ml<=MaxML; ml++)
+ optPtr->matchLengthFreq[ml] = 1;
+ }
+ optPtr->matchLengthSum = MaxML+1;
+
+ { unsigned of;
+ for (of=0; of<=MaxOff; of++)
+ optPtr->offCodeFreq[of] = 1;
+ }
+ optPtr->offCodeSum = MaxOff+1;
+
}
+
+ } else { /* new block : re-use previous statistics, scaled down */
+
+ if (compressedLiterals)
+ optPtr->litSum = ZSTD_downscaleStat(optPtr->litFreq, MaxLit, 1);
+ optPtr->litLengthSum = ZSTD_downscaleStat(optPtr->litLengthFreq, MaxLL, 0);
+ optPtr->matchLengthSum = ZSTD_downscaleStat(optPtr->matchLengthFreq, MaxML, 0);
+ optPtr->offCodeSum = ZSTD_downscaleStat(optPtr->offCodeFreq, MaxOff, 0);
}
- ZSTD_setLog2Prices(optPtr);
+ ZSTD_setBasePrices(optPtr, optLevel);
}
-
/* ZSTD_rawLiteralsCost() :
- * cost of literals (only) in given segment (which length can be null)
- * does not include cost of literalLength symbol */
+ * price of literals (only) in specified segment (which length can be 0).
+ * does not include price of literalLength symbol */
static U32 ZSTD_rawLiteralsCost(const BYTE* const literals, U32 const litLength,
- const optState_t* const optPtr)
+ const optState_t* const optPtr,
+ int optLevel)
{
- if (optPtr->staticPrices) return (litLength*6); /* 6 bit per literal - no statistic used */
if (litLength == 0) return 0;
- /* literals */
- { U32 u;
- U32 cost = litLength * optPtr->log2litSum;
- for (u=0; u < litLength; u++)
- cost -= ZSTD_highbit32(optPtr->litFreq[literals[u]]+1);
- return cost;
+ if (!ZSTD_compressedLiterals(optPtr))
+ return (litLength << 3) * BITCOST_MULTIPLIER; /* Uncompressed - 8 bytes per literal. */
+
+ if (optPtr->priceType == zop_predef)
+ return (litLength*6) * BITCOST_MULTIPLIER; /* 6 bit per literal - no statistic used */
+
+ /* dynamic statistics */
+ { U32 price = litLength * optPtr->litSumBasePrice;
+ U32 u;
+ for (u=0; u < litLength; u++) {
+ assert(WEIGHT(optPtr->litFreq[literals[u]], optLevel) <= optPtr->litSumBasePrice); /* literal cost should never be negative */
+ price -= WEIGHT(optPtr->litFreq[literals[u]], optLevel);
+ }
+ return price;
}
}
/* ZSTD_litLengthPrice() :
* cost of literalLength symbol */
-static U32 ZSTD_litLengthPrice(U32 const litLength, const optState_t* const optPtr)
+static U32 ZSTD_litLengthPrice(U32 const litLength, const optState_t* const optPtr, int optLevel)
{
- if (optPtr->staticPrices) return ZSTD_highbit32((U32)litLength+1);
+ if (optPtr->priceType == zop_predef) return WEIGHT(litLength, optLevel);
- /* literal Length */
+ /* dynamic statistics */
{ U32 const llCode = ZSTD_LLcode(litLength);
- U32 const price = LL_bits[llCode] + optPtr->log2litLengthSum - ZSTD_highbit32(optPtr->litLengthFreq[llCode]+1);
- return price;
+ return (LL_bits[llCode] * BITCOST_MULTIPLIER)
+ + optPtr->litLengthSumBasePrice
+ - WEIGHT(optPtr->litLengthFreq[llCode], optLevel);
}
}
-/* ZSTD_litLengthPrice() :
- * cost of the literal part of a sequence,
- * including literals themselves, and literalLength symbol */
-static U32 ZSTD_fullLiteralsCost(const BYTE* const literals, U32 const litLength,
- const optState_t* const optPtr)
-{
- return ZSTD_rawLiteralsCost(literals, litLength, optPtr)
- + ZSTD_litLengthPrice(litLength, optPtr);
-}
-
/* ZSTD_litLengthContribution() :
* @return ( cost(litlength) - cost(0) )
* this value can then be added to rawLiteralsCost()
* to provide a cost which is directly comparable to a match ending at same position */
-static int ZSTD_litLengthContribution(U32 const litLength, const optState_t* const optPtr)
+static int ZSTD_litLengthContribution(U32 const litLength, const optState_t* const optPtr, int optLevel)
{
- if (optPtr->staticPrices) return ZSTD_highbit32(litLength+1);
+ if (optPtr->priceType >= zop_predef) return WEIGHT(litLength, optLevel);
- /* literal Length */
+ /* dynamic statistics */
{ U32 const llCode = ZSTD_LLcode(litLength);
- int const contribution = LL_bits[llCode]
- + ZSTD_highbit32(optPtr->litLengthFreq[0]+1)
- - ZSTD_highbit32(optPtr->litLengthFreq[llCode]+1);
+ int const contribution = (LL_bits[llCode] * BITCOST_MULTIPLIER)
+ + WEIGHT(optPtr->litLengthFreq[0], optLevel) /* note: log2litLengthSum cancel out */
+ - WEIGHT(optPtr->litLengthFreq[llCode], optLevel);
#if 1
return contribution;
#else
@@ -155,10 +275,11 @@ static int ZSTD_litLengthContribution(U32 const litLength, const optState_t* con
* which can be compared to the ending cost of a match
* should a new match start at this position */
static int ZSTD_literalsContribution(const BYTE* const literals, U32 const litLength,
- const optState_t* const optPtr)
+ const optState_t* const optPtr,
+ int optLevel)
{
- int const contribution = ZSTD_rawLiteralsCost(literals, litLength, optPtr)
- + ZSTD_litLengthContribution(litLength, optPtr);
+ int const contribution = ZSTD_rawLiteralsCost(literals, litLength, optPtr, optLevel)
+ + ZSTD_litLengthContribution(litLength, optPtr, optLevel);
return contribution;
}
@@ -166,37 +287,45 @@ static int ZSTD_literalsContribution(const BYTE* const literals, U32 const litLe
* Provides the cost of the match part (offset + matchLength) of a sequence
* Must be combined with ZSTD_fullLiteralsCost() to get the full cost of a sequence.
* optLevel: when <2, favors small offset for decompression speed (improved cache efficiency) */
-FORCE_INLINE_TEMPLATE U32 ZSTD_getMatchPrice(
- U32 const offset, U32 const matchLength,
- const optState_t* const optPtr,
- int const optLevel)
+FORCE_INLINE_TEMPLATE U32
+ZSTD_getMatchPrice(U32 const offset,
+ U32 const matchLength,
+ const optState_t* const optPtr,
+ int const optLevel)
{
U32 price;
U32 const offCode = ZSTD_highbit32(offset+1);
U32 const mlBase = matchLength - MINMATCH;
assert(matchLength >= MINMATCH);
- if (optPtr->staticPrices) /* fixed scheme, do not use statistics */
- return ZSTD_highbit32((U32)mlBase+1) + 16 + offCode;
+ if (optPtr->priceType == zop_predef) /* fixed scheme, do not use statistics */
+ return WEIGHT(mlBase, optLevel) + ((16 + offCode) * BITCOST_MULTIPLIER);
- price = offCode + optPtr->log2offCodeSum - ZSTD_highbit32(optPtr->offCodeFreq[offCode]+1);
- if ((optLevel<2) /*static*/ && offCode >= 20) price += (offCode-19)*2; /* handicap for long distance offsets, favor decompression speed */
+ /* dynamic statistics */
+ price = (offCode * BITCOST_MULTIPLIER) + (optPtr->offCodeSumBasePrice - WEIGHT(optPtr->offCodeFreq[offCode], optLevel));
+ if ((optLevel<2) /*static*/ && offCode >= 20)
+ price += (offCode-19)*2 * BITCOST_MULTIPLIER; /* handicap for long distance offsets, favor decompression speed */
/* match Length */
{ U32 const mlCode = ZSTD_MLcode(mlBase);
- price += ML_bits[mlCode] + optPtr->log2matchLengthSum - ZSTD_highbit32(optPtr->matchLengthFreq[mlCode]+1);
+ price += (ML_bits[mlCode] * BITCOST_MULTIPLIER) + (optPtr->matchLengthSumBasePrice - WEIGHT(optPtr->matchLengthFreq[mlCode], optLevel));
}
+ price += BITCOST_MULTIPLIER / 5; /* heuristic : make matches a bit more costly to favor less sequences -> faster decompression speed */
+
DEBUGLOG(8, "ZSTD_getMatchPrice(ml:%u) = %u", matchLength, price);
return price;
}
+/* ZSTD_updateStats() :
+ * assumption : literals + litLengtn <= iend */
static void ZSTD_updateStats(optState_t* const optPtr,
U32 litLength, const BYTE* literals,
U32 offsetCode, U32 matchLength)
{
/* literals */
- { U32 u;
+ if (ZSTD_compressedLiterals(optPtr)) {
+ U32 u;
for (u=0; u < litLength; u++)
optPtr->litFreq[literals[u]] += ZSTD_LITFREQ_ADD;
optPtr->litSum += litLength*ZSTD_LITFREQ_ADD;
@@ -269,10 +398,11 @@ static U32 ZSTD_insertAndFindFirstIndexHash3 (ZSTD_matchState_t* ms, const BYTE*
* ip : assumed <= iend-8 .
* @return : nb of positions added */
static U32 ZSTD_insertBt1(
- ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
+ ZSTD_matchState_t* ms,
const BYTE* const ip, const BYTE* const iend,
- U32 const mls, U32 const extDict)
+ U32 const mls, const int extDict)
{
+ const ZSTD_compressionParameters* const cParams = &ms->cParams;
U32* const hashTable = ms->hashTable;
U32 const hashLog = cParams->hashLog;
size_t const h = ZSTD_hashPtr(ip, hashLog, mls);
@@ -308,7 +438,8 @@ static U32 ZSTD_insertBt1(
assert(ip <= iend-8); /* required for h calculation */
hashTable[h] = current; /* Update Hash Table */
- while (nbCompares-- && (matchIndex > windowLow)) {
+ assert(windowLow > 0);
+ while (nbCompares-- && (matchIndex >= windowLow)) {
U32* const nextPtr = bt + 2*(matchIndex & btMask);
size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
assert(matchIndex < current);
@@ -334,8 +465,8 @@ static U32 ZSTD_insertBt1(
}
#endif
- if ((!extDict) || (matchIndex+matchLength >= dictLimit)) {
- assert(matchIndex+matchLength >= dictLimit); /* might be wrong if extDict is incorrectly set to 0 */
+ if (!extDict || (matchIndex+matchLength >= dictLimit)) {
+ assert(matchIndex+matchLength >= dictLimit); /* might be wrong if actually extDict */
match = base + matchIndex;
matchLength += ZSTD_count(ip+matchLength, match+matchLength, iend);
} else {
@@ -379,35 +510,36 @@ static U32 ZSTD_insertBt1(
FORCE_INLINE_TEMPLATE
void ZSTD_updateTree_internal(
- ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
+ ZSTD_matchState_t* ms,
const BYTE* const ip, const BYTE* const iend,
- const U32 mls, const U32 extDict)
+ const U32 mls, const ZSTD_dictMode_e dictMode)
{
const BYTE* const base = ms->window.base;
U32 const target = (U32)(ip - base);
U32 idx = ms->nextToUpdate;
- DEBUGLOG(7, "ZSTD_updateTree_internal, from %u to %u (extDict:%u)",
- idx, target, extDict);
+ DEBUGLOG(6, "ZSTD_updateTree_internal, from %u to %u (dictMode:%u)",
+ idx, target, dictMode);
while(idx < target)
- idx += ZSTD_insertBt1(ms, cParams, base+idx, iend, mls, extDict);
+ idx += ZSTD_insertBt1(ms, base+idx, iend, mls, dictMode == ZSTD_extDict);
ms->nextToUpdate = target;
}
-void ZSTD_updateTree(
- ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
- const BYTE* ip, const BYTE* iend)
-{
- ZSTD_updateTree_internal(ms, cParams, ip, iend, cParams->searchLength, 0 /*extDict*/);
+void ZSTD_updateTree(ZSTD_matchState_t* ms, const BYTE* ip, const BYTE* iend) {
+ ZSTD_updateTree_internal(ms, ip, iend, ms->cParams.minMatch, ZSTD_noDict);
}
FORCE_INLINE_TEMPLATE
U32 ZSTD_insertBtAndGetAllMatches (
- ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
- const BYTE* const ip, const BYTE* const iLimit, int const extDict,
- U32 rep[ZSTD_REP_NUM], U32 const ll0,
- ZSTD_match_t* matches, const U32 lengthToBeat, U32 const mls /* template */)
+ ZSTD_matchState_t* ms,
+ const BYTE* const ip, const BYTE* const iLimit, const ZSTD_dictMode_e dictMode,
+ U32 rep[ZSTD_REP_NUM],
+ U32 const ll0, /* tells if associated literal length is 0 or not. This value must be 0 or 1 */
+ ZSTD_match_t* matches,
+ const U32 lengthToBeat,
+ U32 const mls /* template */)
{
+ const ZSTD_compressionParameters* const cParams = &ms->cParams;
U32 const sufficient_len = MIN(cParams->targetLength, ZSTD_OPT_NUM -1);
const BYTE* const base = ms->window.base;
U32 const current = (U32)(ip-base);
@@ -426,6 +558,7 @@ U32 ZSTD_insertBtAndGetAllMatches (
const BYTE* const prefixStart = base + dictLimit;
U32 const btLow = btMask >= current ? 0 : current - btMask;
U32 const windowLow = ms->window.lowLimit;
+ U32 const matchLow = windowLow ? windowLow : 1;
U32* smallerPtr = bt + 2*(current&btMask);
U32* largerPtr = bt + 2*(current&btMask) + 1;
U32 matchEndIdx = current+8+1; /* farthest referenced position of any match => detects repetitive patterns */
@@ -433,10 +566,24 @@ U32 ZSTD_insertBtAndGetAllMatches (
U32 mnum = 0;
U32 nbCompares = 1U << cParams->searchLog;
+ const ZSTD_matchState_t* dms = dictMode == ZSTD_dictMatchState ? ms->dictMatchState : NULL;
+ const ZSTD_compressionParameters* const dmsCParams =
+ dictMode == ZSTD_dictMatchState ? &dms->cParams : NULL;
+ const BYTE* const dmsBase = dictMode == ZSTD_dictMatchState ? dms->window.base : NULL;
+ const BYTE* const dmsEnd = dictMode == ZSTD_dictMatchState ? dms->window.nextSrc : NULL;
+ U32 const dmsHighLimit = dictMode == ZSTD_dictMatchState ? (U32)(dmsEnd - dmsBase) : 0;
+ U32 const dmsLowLimit = dictMode == ZSTD_dictMatchState ? dms->window.lowLimit : 0;
+ U32 const dmsIndexDelta = dictMode == ZSTD_dictMatchState ? windowLow - dmsHighLimit : 0;
+ U32 const dmsHashLog = dictMode == ZSTD_dictMatchState ? dmsCParams->hashLog : hashLog;
+ U32 const dmsBtLog = dictMode == ZSTD_dictMatchState ? dmsCParams->chainLog - 1 : btLog;
+ U32 const dmsBtMask = dictMode == ZSTD_dictMatchState ? (1U << dmsBtLog) - 1 : 0;
+ U32 const dmsBtLow = dictMode == ZSTD_dictMatchState && dmsBtMask < dmsHighLimit - dmsLowLimit ? dmsHighLimit - dmsBtMask : dmsLowLimit;
+
size_t bestLength = lengthToBeat-1;
- DEBUGLOG(7, "ZSTD_insertBtAndGetAllMatches");
+ DEBUGLOG(8, "ZSTD_insertBtAndGetAllMatches: current=%u", current);
/* check repCode */
+ assert(ll0 <= 1); /* necessarily 1 or 0 */
{ U32 const lastR = ZSTD_REP_NUM + ll0;
U32 repCode;
for (repCode = ll0; repCode < lastR; repCode++) {
@@ -449,18 +596,26 @@ U32 ZSTD_insertBtAndGetAllMatches (
repLen = (U32)ZSTD_count(ip+minMatch, ip+minMatch-repOffset, iLimit) + minMatch;
}
} else { /* repIndex < dictLimit || repIndex >= current */
- const BYTE* const repMatch = dictBase + repIndex;
+ const BYTE* const repMatch = dictMode == ZSTD_dictMatchState ?
+ dmsBase + repIndex - dmsIndexDelta :
+ dictBase + repIndex;
assert(current >= windowLow);
- if ( extDict /* this case only valid in extDict mode */
+ if ( dictMode == ZSTD_extDict
&& ( ((repOffset-1) /*intentional overflow*/ < current - windowLow) /* equivalent to `current > repIndex >= windowLow` */
& (((U32)((dictLimit-1) - repIndex) >= 3) ) /* intentional overflow : do not test positions overlapping 2 memory segments */)
&& (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(repMatch, minMatch)) ) {
repLen = (U32)ZSTD_count_2segments(ip+minMatch, repMatch+minMatch, iLimit, dictEnd, prefixStart) + minMatch;
+ }
+ if (dictMode == ZSTD_dictMatchState
+ && ( ((repOffset-1) /*intentional overflow*/ < current - (dmsLowLimit + dmsIndexDelta)) /* equivalent to `current > repIndex >= dmsLowLimit` */
+ & ((U32)((dictLimit-1) - repIndex) >= 3) ) /* intentional overflow : do not test positions overlapping 2 memory segments */
+ && (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(repMatch, minMatch)) ) {
+ repLen = (U32)ZSTD_count_2segments(ip+minMatch, repMatch+minMatch, iLimit, dmsEnd, prefixStart) + minMatch;
} }
/* save longer solution */
if (repLen > bestLength) {
- DEBUGLOG(8, "found rep-match %u of length %u",
- repCode - ll0, (U32)repLen);
+ DEBUGLOG(8, "found repCode %u (ll0:%u, offset:%u) of length %u",
+ repCode, ll0, repOffset, repLen);
bestLength = repLen;
matches[mnum].off = repCode - ll0;
matches[mnum].len = (U32)repLen;
@@ -473,10 +628,10 @@ U32 ZSTD_insertBtAndGetAllMatches (
/* HC3 match finder */
if ((mls == 3) /*static*/ && (bestLength < mls)) {
U32 const matchIndex3 = ZSTD_insertAndFindFirstIndexHash3(ms, ip);
- if ((matchIndex3 > windowLow)
+ if ((matchIndex3 >= matchLow)
& (current - matchIndex3 < (1<<18)) /*heuristic : longer distance likely too expensive*/ ) {
size_t mlen;
- if ((!extDict) /*static*/ || (matchIndex3 >= dictLimit)) {
+ if ((dictMode == ZSTD_noDict) /*static*/ || (dictMode == ZSTD_dictMatchState) /*static*/ || (matchIndex3 >= dictLimit)) {
const BYTE* const match = base + matchIndex3;
mlen = ZSTD_count(ip, match, iLimit);
} else {
@@ -498,17 +653,21 @@ U32 ZSTD_insertBtAndGetAllMatches (
(ip+mlen == iLimit) ) { /* best possible length */
ms->nextToUpdate = current+1; /* skip insertion */
return 1;
- } } } }
+ }
+ }
+ }
+ /* no dictMatchState lookup: dicts don't have a populated HC3 table */
+ }
hashTable[h] = current; /* Update Hash Table */
- while (nbCompares-- && (matchIndex > windowLow)) {
+ while (nbCompares-- && (matchIndex >= matchLow)) {
U32* const nextPtr = bt + 2*(matchIndex & btMask);
size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
const BYTE* match;
assert(current > matchIndex);
- if ((!extDict) || (matchIndex+matchLength >= dictLimit)) {
+ if ((dictMode == ZSTD_noDict) || (dictMode == ZSTD_dictMatchState) || (matchIndex+matchLength >= dictLimit)) {
assert(matchIndex+matchLength >= dictLimit); /* ensure the condition is correct when !extDict */
match = base + matchIndex;
matchLength += ZSTD_count(ip+matchLength, match+matchLength, iLimit);
@@ -520,8 +679,8 @@ U32 ZSTD_insertBtAndGetAllMatches (
}
if (matchLength > bestLength) {
- DEBUGLOG(8, "found match of length %u at distance %u",
- (U32)matchLength, current - matchIndex);
+ DEBUGLOG(8, "found match of length %u at distance %u (offCode=%u)",
+ (U32)matchLength, current - matchIndex, current - matchIndex + ZSTD_REP_MOVE);
assert(matchEndIdx > matchIndex);
if (matchLength > matchEndIdx - matchIndex)
matchEndIdx = matchIndex + (U32)matchLength;
@@ -529,9 +688,10 @@ U32 ZSTD_insertBtAndGetAllMatches (
matches[mnum].off = (current - matchIndex) + ZSTD_REP_MOVE;
matches[mnum].len = (U32)matchLength;
mnum++;
- if (matchLength > ZSTD_OPT_NUM) break;
- if (ip+matchLength == iLimit) { /* equal : no way to know if inf or sup */
- break; /* drop, to preserve bt consistency (miss a little bit of compression) */
+ if ( (matchLength > ZSTD_OPT_NUM)
+ | (ip+matchLength == iLimit) /* equal : no way to know if inf or sup */) {
+ if (dictMode == ZSTD_dictMatchState) nbCompares = 0; /* break should also skip searching dms */
+ break; /* drop, to preserve bt consistency (miss a little bit of compression) */
}
}
@@ -552,6 +712,47 @@ U32 ZSTD_insertBtAndGetAllMatches (
*smallerPtr = *largerPtr = 0;
+ if (dictMode == ZSTD_dictMatchState && nbCompares) {
+ size_t const dmsH = ZSTD_hashPtr(ip, dmsHashLog, mls);
+ U32 dictMatchIndex = dms->hashTable[dmsH];
+ const U32* const dmsBt = dms->chainTable;
+ commonLengthSmaller = commonLengthLarger = 0;
+ while (nbCompares-- && (dictMatchIndex > dmsLowLimit)) {
+ const U32* const nextPtr = dmsBt + 2*(dictMatchIndex & dmsBtMask);
+ size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
+ const BYTE* match = dmsBase + dictMatchIndex;
+ matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iLimit, dmsEnd, prefixStart);
+ if (dictMatchIndex+matchLength >= dmsHighLimit)
+ match = base + dictMatchIndex + dmsIndexDelta; /* to prepare for next usage of match[matchLength] */
+
+ if (matchLength > bestLength) {
+ matchIndex = dictMatchIndex + dmsIndexDelta;
+ DEBUGLOG(8, "found dms match of length %u at distance %u (offCode=%u)",
+ (U32)matchLength, current - matchIndex, current - matchIndex + ZSTD_REP_MOVE);
+ if (matchLength > matchEndIdx - matchIndex)
+ matchEndIdx = matchIndex + (U32)matchLength;
+ bestLength = matchLength;
+ matches[mnum].off = (current - matchIndex) + ZSTD_REP_MOVE;
+ matches[mnum].len = (U32)matchLength;
+ mnum++;
+ if ( (matchLength > ZSTD_OPT_NUM)
+ | (ip+matchLength == iLimit) /* equal : no way to know if inf or sup */) {
+ break; /* drop, to guarantee consistency (miss a little bit of compression) */
+ }
+ }
+
+ if (dictMatchIndex <= dmsBtLow) { break; } /* beyond tree size, stop the search */
+ if (match[matchLength] < ip[matchLength]) {
+ commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */
+ dictMatchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
+ } else {
+ /* match is larger than current */
+ commonLengthLarger = matchLength;
+ dictMatchIndex = nextPtr[0];
+ }
+ }
+ }
+
assert(matchEndIdx > current+8);
ms->nextToUpdate = matchEndIdx - 8; /* skip repetitive patterns */
return mnum;
@@ -559,23 +760,24 @@ U32 ZSTD_insertBtAndGetAllMatches (
FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
- ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
- const BYTE* ip, const BYTE* const iHighLimit, int const extDict,
+ ZSTD_matchState_t* ms,
+ const BYTE* ip, const BYTE* const iHighLimit, const ZSTD_dictMode_e dictMode,
U32 rep[ZSTD_REP_NUM], U32 const ll0,
ZSTD_match_t* matches, U32 const lengthToBeat)
{
- U32 const matchLengthSearch = cParams->searchLength;
- DEBUGLOG(7, "ZSTD_BtGetAllMatches");
+ const ZSTD_compressionParameters* const cParams = &ms->cParams;
+ U32 const matchLengthSearch = cParams->minMatch;
+ DEBUGLOG(8, "ZSTD_BtGetAllMatches");
if (ip < ms->window.base + ms->nextToUpdate) return 0; /* skipped area */
- ZSTD_updateTree_internal(ms, cParams, ip, iHighLimit, matchLengthSearch, extDict);
+ ZSTD_updateTree_internal(ms, ip, iHighLimit, matchLengthSearch, dictMode);
switch(matchLengthSearch)
{
- case 3 : return ZSTD_insertBtAndGetAllMatches(ms, cParams, ip, iHighLimit, extDict, rep, ll0, matches, lengthToBeat, 3);
+ case 3 : return ZSTD_insertBtAndGetAllMatches(ms, ip, iHighLimit, dictMode, rep, ll0, matches, lengthToBeat, 3);
default :
- case 4 : return ZSTD_insertBtAndGetAllMatches(ms, cParams, ip, iHighLimit, extDict, rep, ll0, matches, lengthToBeat, 4);
- case 5 : return ZSTD_insertBtAndGetAllMatches(ms, cParams, ip, iHighLimit, extDict, rep, ll0, matches, lengthToBeat, 5);
+ case 4 : return ZSTD_insertBtAndGetAllMatches(ms, ip, iHighLimit, dictMode, rep, ll0, matches, lengthToBeat, 4);
+ case 5 : return ZSTD_insertBtAndGetAllMatches(ms, ip, iHighLimit, dictMode, rep, ll0, matches, lengthToBeat, 5);
case 7 :
- case 6 : return ZSTD_insertBtAndGetAllMatches(ms, cParams, ip, iHighLimit, extDict, rep, ll0, matches, lengthToBeat, 6);
+ case 6 : return ZSTD_insertBtAndGetAllMatches(ms, ip, iHighLimit, dictMode, rep, ll0, matches, lengthToBeat, 6);
}
}
@@ -587,7 +789,7 @@ typedef struct repcodes_s {
U32 rep[3];
} repcodes_t;
-repcodes_t ZSTD_updateRep(U32 const rep[3], U32 const offset, U32 const ll0)
+static repcodes_t ZSTD_updateRep(U32 const rep[3], U32 const offset, U32 const ll0)
{
repcodes_t newReps;
if (offset >= ZSTD_REP_NUM) { /* full offset */
@@ -609,65 +811,35 @@ repcodes_t ZSTD_updateRep(U32 const rep[3], U32 const offset, U32 const ll0)
}
-typedef struct {
- const BYTE* anchor;
- U32 litlen;
- U32 rawLitCost;
-} cachedLiteralPrice_t;
-
-static U32 ZSTD_rawLiteralsCost_cached(
- cachedLiteralPrice_t* const cachedLitPrice,
- const BYTE* const anchor, U32 const litlen,
- const optState_t* const optStatePtr)
+static U32 ZSTD_totalLen(ZSTD_optimal_t sol)
{
- U32 startCost;
- U32 remainingLength;
- const BYTE* startPosition;
-
- if (anchor == cachedLitPrice->anchor) {
- startCost = cachedLitPrice->rawLitCost;
- startPosition = anchor + cachedLitPrice->litlen;
- assert(litlen >= cachedLitPrice->litlen);
- remainingLength = litlen - cachedLitPrice->litlen;
- } else {
- startCost = 0;
- startPosition = anchor;
- remainingLength = litlen;
- }
-
- { U32 const rawLitCost = startCost + ZSTD_rawLiteralsCost(startPosition, remainingLength, optStatePtr);
- cachedLitPrice->anchor = anchor;
- cachedLitPrice->litlen = litlen;
- cachedLitPrice->rawLitCost = rawLitCost;
- return rawLitCost;
- }
+ return sol.litlen + sol.mlen;
}
-static U32 ZSTD_fullLiteralsCost_cached(
- cachedLiteralPrice_t* const cachedLitPrice,
- const BYTE* const anchor, U32 const litlen,
- const optState_t* const optStatePtr)
-{
- return ZSTD_rawLiteralsCost_cached(cachedLitPrice, anchor, litlen, optStatePtr)
- + ZSTD_litLengthPrice(litlen, optStatePtr);
-}
+#if 0 /* debug */
-static int ZSTD_literalsContribution_cached(
- cachedLiteralPrice_t* const cachedLitPrice,
- const BYTE* const anchor, U32 const litlen,
- const optState_t* const optStatePtr)
+static void
+listStats(const U32* table, int lastEltID)
{
- int const contribution = ZSTD_rawLiteralsCost_cached(cachedLitPrice, anchor, litlen, optStatePtr)
- + ZSTD_litLengthContribution(litlen, optStatePtr);
- return contribution;
+ int const nbElts = lastEltID + 1;
+ int enb;
+ for (enb=0; enb < nbElts; enb++) {
+ (void)table;
+ //RAWLOG(2, "%3i:%3i, ", enb, table[enb]);
+ RAWLOG(2, "%4i,", table[enb]);
+ }
+ RAWLOG(2, " \n");
}
-FORCE_INLINE_TEMPLATE
-size_t ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,seqStore_t* seqStore,
- U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams,
- const void* src, size_t srcSize,
- const int optLevel, const int extDict)
+#endif
+
+FORCE_INLINE_TEMPLATE size_t
+ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
+ seqStore_t* seqStore,
+ U32 rep[ZSTD_REP_NUM],
+ const void* src, size_t srcSize,
+ const int optLevel,
+ const ZSTD_dictMode_e dictMode)
{
optState_t* const optStatePtr = &ms->opt;
const BYTE* const istart = (const BYTE*)src;
@@ -677,72 +849,77 @@ size_t ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,seqStore_t* seqStore
const BYTE* const ilimit = iend - 8;
const BYTE* const base = ms->window.base;
const BYTE* const prefixStart = base + ms->window.dictLimit;
+ const ZSTD_compressionParameters* const cParams = &ms->cParams;
U32 const sufficient_len = MIN(cParams->targetLength, ZSTD_OPT_NUM -1);
- U32 const minMatch = (cParams->searchLength == 3) ? 3 : 4;
+ U32 const minMatch = (cParams->minMatch == 3) ? 3 : 4;
ZSTD_optimal_t* const opt = optStatePtr->priceTable;
ZSTD_match_t* const matches = optStatePtr->matchTable;
- cachedLiteralPrice_t cachedLitPrice;
+ ZSTD_optimal_t lastSequence;
/* init */
- DEBUGLOG(5, "ZSTD_compressBlock_opt_generic");
+ DEBUGLOG(5, "ZSTD_compressBlock_opt_generic: current=%u, prefix=%u, nextToUpdate=%u",
+ (U32)(ip - base), ms->window.dictLimit, ms->nextToUpdate);
+ assert(optLevel <= 2);
ms->nextToUpdate3 = ms->nextToUpdate;
- ZSTD_rescaleFreqs(optStatePtr, (const BYTE*)src, srcSize);
+ ZSTD_rescaleFreqs(optStatePtr, (const BYTE*)src, srcSize, optLevel);
ip += (ip==prefixStart);
- memset(&cachedLitPrice, 0, sizeof(cachedLitPrice));
/* Match Loop */
while (ip < ilimit) {
U32 cur, last_pos = 0;
- U32 best_mlen, best_off;
/* find first match */
{ U32 const litlen = (U32)(ip - anchor);
U32 const ll0 = !litlen;
- U32 const nbMatches = ZSTD_BtGetAllMatches(ms, cParams, ip, iend, extDict, rep, ll0, matches, minMatch);
+ U32 const nbMatches = ZSTD_BtGetAllMatches(ms, ip, iend, dictMode, rep, ll0, matches, minMatch);
if (!nbMatches) { ip++; continue; }
/* initialize opt[0] */
{ U32 i ; for (i=0; i<ZSTD_REP_NUM; i++) opt[0].rep[i] = rep[i]; }
- opt[0].mlen = 1;
+ opt[0].mlen = 0; /* means is_a_literal */
opt[0].litlen = litlen;
+ opt[0].price = ZSTD_literalsContribution(anchor, litlen, optStatePtr, optLevel);
/* large match -> immediate encoding */
{ U32 const maxML = matches[nbMatches-1].len;
- DEBUGLOG(7, "found %u matches of maxLength=%u and offset=%u at cPos=%u => start new serie",
- nbMatches, maxML, matches[nbMatches-1].off, (U32)(ip-prefixStart));
+ U32 const maxOffset = matches[nbMatches-1].off;
+ DEBUGLOG(6, "found %u matches of maxLength=%u and maxOffCode=%u at cPos=%u => start new series",
+ nbMatches, maxML, maxOffset, (U32)(ip-prefixStart));
if (maxML > sufficient_len) {
- best_mlen = maxML;
- best_off = matches[nbMatches-1].off;
- DEBUGLOG(7, "large match (%u>%u), immediate encoding",
- best_mlen, sufficient_len);
+ lastSequence.litlen = litlen;
+ lastSequence.mlen = maxML;
+ lastSequence.off = maxOffset;
+ DEBUGLOG(6, "large match (%u>%u), immediate encoding",
+ maxML, sufficient_len);
cur = 0;
- last_pos = 1;
+ last_pos = ZSTD_totalLen(lastSequence);
goto _shortestPath;
} }
/* set prices for first matches starting position == 0 */
- { U32 const literalsPrice = ZSTD_fullLiteralsCost_cached(&cachedLitPrice, anchor, litlen, optStatePtr);
+ { U32 const literalsPrice = opt[0].price + ZSTD_litLengthPrice(0, optStatePtr, optLevel);
U32 pos;
U32 matchNb;
- for (pos = 0; pos < minMatch; pos++) {
- opt[pos].mlen = 1;
- opt[pos].price = ZSTD_MAX_PRICE;
+ for (pos = 1; pos < minMatch; pos++) {
+ opt[pos].price = ZSTD_MAX_PRICE; /* mlen, litlen and price will be fixed during forward scanning */
}
for (matchNb = 0; matchNb < nbMatches; matchNb++) {
U32 const offset = matches[matchNb].off;
U32 const end = matches[matchNb].len;
repcodes_t const repHistory = ZSTD_updateRep(rep, offset, ll0);
for ( ; pos <= end ; pos++ ) {
- U32 const matchPrice = literalsPrice + ZSTD_getMatchPrice(offset, pos, optStatePtr, optLevel);
- DEBUGLOG(7, "rPos:%u => set initial price : %u",
- pos, matchPrice);
+ U32 const matchPrice = ZSTD_getMatchPrice(offset, pos, optStatePtr, optLevel);
+ U32 const sequencePrice = literalsPrice + matchPrice;
+ DEBUGLOG(7, "rPos:%u => set initial price : %.2f",
+ pos, ZSTD_fCost(sequencePrice));
opt[pos].mlen = pos;
opt[pos].off = offset;
opt[pos].litlen = litlen;
- opt[pos].price = matchPrice;
+ opt[pos].price = sequencePrice;
+ ZSTD_STATIC_ASSERT(sizeof(opt[pos].rep) == sizeof(repHistory));
memcpy(opt[pos].rep, &repHistory, sizeof(repHistory));
} }
last_pos = pos-1;
@@ -753,55 +930,67 @@ size_t ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,seqStore_t* seqStore
for (cur = 1; cur <= last_pos; cur++) {
const BYTE* const inr = ip + cur;
assert(cur < ZSTD_OPT_NUM);
+ DEBUGLOG(7, "cPos:%zi==rPos:%u", inr-istart, cur)
/* Fix current position with one literal if cheaper */
- { U32 const litlen = (opt[cur-1].mlen == 1) ? opt[cur-1].litlen + 1 : 1;
- int price; /* note : contribution can be negative */
- if (cur > litlen) {
- price = opt[cur - litlen].price + ZSTD_literalsContribution(inr-litlen, litlen, optStatePtr);
- } else {
- price = ZSTD_literalsContribution_cached(&cachedLitPrice, anchor, litlen, optStatePtr);
- }
+ { U32 const litlen = (opt[cur-1].mlen == 0) ? opt[cur-1].litlen + 1 : 1;
+ int const price = opt[cur-1].price
+ + ZSTD_rawLiteralsCost(ip+cur-1, 1, optStatePtr, optLevel)
+ + ZSTD_litLengthPrice(litlen, optStatePtr, optLevel)
+ - ZSTD_litLengthPrice(litlen-1, optStatePtr, optLevel);
assert(price < 1000000000); /* overflow check */
if (price <= opt[cur].price) {
- DEBUGLOG(7, "rPos:%u : better price (%u<%u) using literal",
- cur, price, opt[cur].price);
- opt[cur].mlen = 1;
+ DEBUGLOG(7, "cPos:%zi==rPos:%u : better price (%.2f<=%.2f) using literal (ll==%u) (hist:%u,%u,%u)",
+ inr-istart, cur, ZSTD_fCost(price), ZSTD_fCost(opt[cur].price), litlen,
+ opt[cur-1].rep[0], opt[cur-1].rep[1], opt[cur-1].rep[2]);
+ opt[cur].mlen = 0;
opt[cur].off = 0;
opt[cur].litlen = litlen;
opt[cur].price = price;
memcpy(opt[cur].rep, opt[cur-1].rep, sizeof(opt[cur].rep));
- } }
+ } else {
+ DEBUGLOG(7, "cPos:%zi==rPos:%u : literal would cost more (%.2f>%.2f) (hist:%u,%u,%u)",
+ inr-istart, cur, ZSTD_fCost(price), ZSTD_fCost(opt[cur].price),
+ opt[cur].rep[0], opt[cur].rep[1], opt[cur].rep[2]);
+ }
+ }
/* last match must start at a minimum distance of 8 from oend */
if (inr > ilimit) continue;
if (cur == last_pos) break;
- if ( (optLevel==0) /*static*/
- && (opt[cur+1].price <= opt[cur].price) )
+ if ( (optLevel==0) /*static_test*/
+ && (opt[cur+1].price <= opt[cur].price + (BITCOST_MULTIPLIER/2)) ) {
+ DEBUGLOG(7, "move to next rPos:%u : price is <=", cur+1);
continue; /* skip unpromising positions; about ~+6% speed, -0.01 ratio */
+ }
- { U32 const ll0 = (opt[cur].mlen != 1);
- U32 const litlen = (opt[cur].mlen == 1) ? opt[cur].litlen : 0;
- U32 const previousPrice = (cur > litlen) ? opt[cur-litlen].price : 0;
- U32 const basePrice = previousPrice + ZSTD_fullLiteralsCost(inr-litlen, litlen, optStatePtr);
- U32 const nbMatches = ZSTD_BtGetAllMatches(ms, cParams, inr, iend, extDict, opt[cur].rep, ll0, matches, minMatch);
+ { U32 const ll0 = (opt[cur].mlen != 0);
+ U32 const litlen = (opt[cur].mlen == 0) ? opt[cur].litlen : 0;
+ U32 const previousPrice = opt[cur].price;
+ U32 const basePrice = previousPrice + ZSTD_litLengthPrice(0, optStatePtr, optLevel);
+ U32 const nbMatches = ZSTD_BtGetAllMatches(ms, inr, iend, dictMode, opt[cur].rep, ll0, matches, minMatch);
U32 matchNb;
- if (!nbMatches) continue;
+ if (!nbMatches) {
+ DEBUGLOG(7, "rPos:%u : no match found", cur);
+ continue;
+ }
{ U32 const maxML = matches[nbMatches-1].len;
- DEBUGLOG(7, "rPos:%u, found %u matches, of maxLength=%u",
- cur, nbMatches, maxML);
+ DEBUGLOG(7, "cPos:%zi==rPos:%u, found %u matches, of maxLength=%u",
+ inr-istart, cur, nbMatches, maxML);
if ( (maxML > sufficient_len)
- | (cur + maxML >= ZSTD_OPT_NUM) ) {
- best_mlen = maxML;
- best_off = matches[nbMatches-1].off;
- last_pos = cur + 1;
+ || (cur + maxML >= ZSTD_OPT_NUM) ) {
+ lastSequence.mlen = maxML;
+ lastSequence.off = matches[nbMatches-1].off;
+ lastSequence.litlen = litlen;
+ cur -= (opt[cur].mlen==0) ? opt[cur].litlen : 0; /* last sequence is actually only literals, fix cur to last match - note : may underflow, in which case, it's first sequence, and it's okay */
+ last_pos = cur + ZSTD_totalLen(lastSequence);
+ if (cur > ZSTD_OPT_NUM) cur = 0; /* underflow => first match */
goto _shortestPath;
- }
- }
+ } }
/* set prices using matches found at position == cur */
for (matchNb = 0; matchNb < nbMatches; matchNb++) {
@@ -811,81 +1000,97 @@ size_t ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,seqStore_t* seqStore
U32 const startML = (matchNb>0) ? matches[matchNb-1].len+1 : minMatch;
U32 mlen;
- DEBUGLOG(7, "testing match %u => offCode=%u, mlen=%u, llen=%u",
+ DEBUGLOG(7, "testing match %u => offCode=%4u, mlen=%2u, llen=%2u",
matchNb, matches[matchNb].off, lastML, litlen);
- for (mlen = lastML; mlen >= startML; mlen--) {
+ for (mlen = lastML; mlen >= startML; mlen--) { /* scan downward */
U32 const pos = cur + mlen;
int const price = basePrice + ZSTD_getMatchPrice(offset, mlen, optStatePtr, optLevel);
if ((pos > last_pos) || (price < opt[pos].price)) {
- DEBUGLOG(7, "rPos:%u => new better price (%u<%u)",
- pos, price, opt[pos].price);
- while (last_pos < pos) { opt[last_pos+1].price = ZSTD_MAX_PRICE; last_pos++; }
+ DEBUGLOG(7, "rPos:%u (ml=%2u) => new better price (%.2f<%.2f)",
+ pos, mlen, ZSTD_fCost(price), ZSTD_fCost(opt[pos].price));
+ while (last_pos < pos) { opt[last_pos+1].price = ZSTD_MAX_PRICE; last_pos++; } /* fill empty positions */
opt[pos].mlen = mlen;
opt[pos].off = offset;
opt[pos].litlen = litlen;
opt[pos].price = price;
+ ZSTD_STATIC_ASSERT(sizeof(opt[pos].rep) == sizeof(repHistory));
memcpy(opt[pos].rep, &repHistory, sizeof(repHistory));
} else {
- if (optLevel==0) break; /* gets ~+10% speed for about -0.01 ratio loss */
+ DEBUGLOG(7, "rPos:%u (ml=%2u) => new price is worse (%.2f>=%.2f)",
+ pos, mlen, ZSTD_fCost(price), ZSTD_fCost(opt[pos].price));
+ if (optLevel==0) break; /* early update abort; gets ~+10% speed for about -0.01 ratio loss */
}
} } }
} /* for (cur = 1; cur <= last_pos; cur++) */
- best_mlen = opt[last_pos].mlen;
- best_off = opt[last_pos].off;
- cur = last_pos - best_mlen;
+ lastSequence = opt[last_pos];
+ cur = last_pos > ZSTD_totalLen(lastSequence) ? last_pos - ZSTD_totalLen(lastSequence) : 0; /* single sequence, and it starts before `ip` */
+ assert(cur < ZSTD_OPT_NUM); /* control overflow*/
_shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
- assert(opt[0].mlen == 1);
-
- /* reverse traversal */
- DEBUGLOG(7, "start reverse traversal (last_pos:%u, cur:%u)",
- last_pos, cur);
- { U32 selectedMatchLength = best_mlen;
- U32 selectedOffset = best_off;
- U32 pos = cur;
- while (1) {
- U32 const mlen = opt[pos].mlen;
- U32 const off = opt[pos].off;
- opt[pos].mlen = selectedMatchLength;
- opt[pos].off = selectedOffset;
- selectedMatchLength = mlen;
- selectedOffset = off;
- if (mlen > pos) break;
- pos -= mlen;
- } }
-
- /* save sequences */
- { U32 pos;
- for (pos=0; pos < last_pos; ) {
- U32 const llen = (U32)(ip - anchor);
- U32 const mlen = opt[pos].mlen;
- U32 const offset = opt[pos].off;
- if (mlen == 1) { ip++; pos++; continue; } /* literal position => move on */
- pos += mlen; ip += mlen;
-
- /* repcodes update : like ZSTD_updateRep(), but update in place */
- if (offset >= ZSTD_REP_NUM) { /* full offset */
- rep[2] = rep[1];
- rep[1] = rep[0];
- rep[0] = offset - ZSTD_REP_MOVE;
- } else { /* repcode */
- U32 const repCode = offset + (llen==0);
- if (repCode) { /* note : if repCode==0, no change */
- U32 const currentOffset = (repCode==ZSTD_REP_NUM) ? (rep[0] - 1) : rep[repCode];
- if (repCode >= 2) rep[2] = rep[1];
- rep[1] = rep[0];
- rep[0] = currentOffset;
+ assert(opt[0].mlen == 0);
+
+ { U32 const storeEnd = cur + 1;
+ U32 storeStart = storeEnd;
+ U32 seqPos = cur;
+
+ DEBUGLOG(6, "start reverse traversal (last_pos:%u, cur:%u)",
+ last_pos, cur); (void)last_pos;
+ assert(storeEnd < ZSTD_OPT_NUM);
+ DEBUGLOG(6, "last sequence copied into pos=%u (llen=%u,mlen=%u,ofc=%u)",
+ storeEnd, lastSequence.litlen, lastSequence.mlen, lastSequence.off);
+ opt[storeEnd] = lastSequence;
+ while (seqPos > 0) {
+ U32 const backDist = ZSTD_totalLen(opt[seqPos]);
+ storeStart--;
+ DEBUGLOG(6, "sequence from rPos=%u copied into pos=%u (llen=%u,mlen=%u,ofc=%u)",
+ seqPos, storeStart, opt[seqPos].litlen, opt[seqPos].mlen, opt[seqPos].off);
+ opt[storeStart] = opt[seqPos];
+ seqPos = (seqPos > backDist) ? seqPos - backDist : 0;
+ }
+
+ /* save sequences */
+ DEBUGLOG(6, "sending selected sequences into seqStore")
+ { U32 storePos;
+ for (storePos=storeStart; storePos <= storeEnd; storePos++) {
+ U32 const llen = opt[storePos].litlen;
+ U32 const mlen = opt[storePos].mlen;
+ U32 const offCode = opt[storePos].off;
+ U32 const advance = llen + mlen;
+ DEBUGLOG(6, "considering seq starting at %zi, llen=%u, mlen=%u",
+ anchor - istart, (unsigned)llen, (unsigned)mlen);
+
+ if (mlen==0) { /* only literals => must be last "sequence", actually starting a new stream of sequences */
+ assert(storePos == storeEnd); /* must be last sequence */
+ ip = anchor + llen; /* last "sequence" is a bunch of literals => don't progress anchor */
+ continue; /* will finish */
}
- }
- ZSTD_updateStats(optStatePtr, llen, anchor, offset, mlen);
- ZSTD_storeSeq(seqStore, llen, anchor, offset, mlen-MINMATCH);
- anchor = ip;
- } }
- ZSTD_setLog2Prices(optStatePtr);
+ /* repcodes update : like ZSTD_updateRep(), but update in place */
+ if (offCode >= ZSTD_REP_NUM) { /* full offset */
+ rep[2] = rep[1];
+ rep[1] = rep[0];
+ rep[0] = offCode - ZSTD_REP_MOVE;
+ } else { /* repcode */
+ U32 const repCode = offCode + (llen==0);
+ if (repCode) { /* note : if repCode==0, no change */
+ U32 const currentOffset = (repCode==ZSTD_REP_NUM) ? (rep[0] - 1) : rep[repCode];
+ if (repCode >= 2) rep[2] = rep[1];
+ rep[1] = rep[0];
+ rep[0] = currentOffset;
+ } }
+
+ assert(anchor + llen <= iend);
+ ZSTD_updateStats(optStatePtr, llen, anchor, offCode, mlen);
+ ZSTD_storeSeq(seqStore, llen, anchor, offCode, mlen-MINMATCH);
+ anchor += advance;
+ ip = anchor;
+ } }
+ ZSTD_setBasePrices(optStatePtr, optLevel);
+ }
+
} /* while (ip < ilimit) */
/* Return the last literals size */
@@ -895,29 +1100,134 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
size_t ZSTD_compressBlock_btopt(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize)
+ const void* src, size_t srcSize)
{
DEBUGLOG(5, "ZSTD_compressBlock_btopt");
- return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, cParams, src, srcSize, 0 /*optLevel*/, 0 /*extDict*/);
+ return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 0 /*optLevel*/, ZSTD_noDict);
+}
+
+
+/* used in 2-pass strategy */
+static U32 ZSTD_upscaleStat(unsigned* table, U32 lastEltIndex, int bonus)
+{
+ U32 s, sum=0;
+ assert(ZSTD_FREQ_DIV+bonus >= 0);
+ for (s=0; s<lastEltIndex+1; s++) {
+ table[s] <<= ZSTD_FREQ_DIV+bonus;
+ table[s]--;
+ sum += table[s];
+ }
+ return sum;
+}
+
+/* used in 2-pass strategy */
+MEM_STATIC void ZSTD_upscaleStats(optState_t* optPtr)
+{
+ if (ZSTD_compressedLiterals(optPtr))
+ optPtr->litSum = ZSTD_upscaleStat(optPtr->litFreq, MaxLit, 0);
+ optPtr->litLengthSum = ZSTD_upscaleStat(optPtr->litLengthFreq, MaxLL, 0);
+ optPtr->matchLengthSum = ZSTD_upscaleStat(optPtr->matchLengthFreq, MaxML, 0);
+ optPtr->offCodeSum = ZSTD_upscaleStat(optPtr->offCodeFreq, MaxOff, 0);
+}
+
+/* ZSTD_initStats_ultra():
+ * make a first compression pass, just to seed stats with more accurate starting values.
+ * only works on first block, with no dictionary and no ldm.
+ * this function cannot error, hence its contract must be respected.
+ */
+static void
+ZSTD_initStats_ultra(ZSTD_matchState_t* ms,
+ seqStore_t* seqStore,
+ U32 rep[ZSTD_REP_NUM],
+ const void* src, size_t srcSize)
+{
+ U32 tmpRep[ZSTD_REP_NUM]; /* updated rep codes will sink here */
+ memcpy(tmpRep, rep, sizeof(tmpRep));
+
+ DEBUGLOG(4, "ZSTD_initStats_ultra (srcSize=%zu)", srcSize);
+ assert(ms->opt.litLengthSum == 0); /* first block */
+ assert(seqStore->sequences == seqStore->sequencesStart); /* no ldm */
+ assert(ms->window.dictLimit == ms->window.lowLimit); /* no dictionary */
+ assert(ms->window.dictLimit - ms->nextToUpdate <= 1); /* no prefix (note: intentional overflow, defined as 2-complement) */
+
+ ZSTD_compressBlock_opt_generic(ms, seqStore, tmpRep, src, srcSize, 2 /*optLevel*/, ZSTD_noDict); /* generate stats into ms->opt*/
+
+ /* invalidate first scan from history */
+ ZSTD_resetSeqStore(seqStore);
+ ms->window.base -= srcSize;
+ ms->window.dictLimit += (U32)srcSize;
+ ms->window.lowLimit = ms->window.dictLimit;
+ ms->nextToUpdate = ms->window.dictLimit;
+ ms->nextToUpdate3 = ms->window.dictLimit;
+
+ /* re-inforce weight of collected statistics */
+ ZSTD_upscaleStats(&ms->opt);
}
size_t ZSTD_compressBlock_btultra(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize)
+ const void* src, size_t srcSize)
+{
+ DEBUGLOG(5, "ZSTD_compressBlock_btultra (srcSize=%zu)", srcSize);
+ return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 2 /*optLevel*/, ZSTD_noDict);
+}
+
+size_t ZSTD_compressBlock_btultra2(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ const void* src, size_t srcSize)
+{
+ U32 const current = (U32)((const BYTE*)src - ms->window.base);
+ DEBUGLOG(5, "ZSTD_compressBlock_btultra2 (srcSize=%zu)", srcSize);
+
+ /* 2-pass strategy:
+ * this strategy makes a first pass over first block to collect statistics
+ * and seed next round's statistics with it.
+ * After 1st pass, function forgets everything, and starts a new block.
+ * Consequently, this can only work if no data has been previously loaded in tables,
+ * aka, no dictionary, no prefix, no ldm preprocessing.
+ * The compression ratio gain is generally small (~0.5% on first block),
+ * the cost is 2x cpu time on first block. */
+ assert(srcSize <= ZSTD_BLOCKSIZE_MAX);
+ if ( (ms->opt.litLengthSum==0) /* first block */
+ && (seqStore->sequences == seqStore->sequencesStart) /* no ldm */
+ && (ms->window.dictLimit == ms->window.lowLimit) /* no dictionary */
+ && (current == ms->window.dictLimit) /* start of frame, nothing already loaded nor skipped */
+ && (srcSize > ZSTD_PREDEF_THRESHOLD)
+ ) {
+ ZSTD_initStats_ultra(ms, seqStore, rep, src, srcSize);
+ }
+
+ return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 2 /*optLevel*/, ZSTD_noDict);
+}
+
+size_t ZSTD_compressBlock_btopt_dictMatchState(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ const void* src, size_t srcSize)
+{
+ return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 0 /*optLevel*/, ZSTD_dictMatchState);
+}
+
+size_t ZSTD_compressBlock_btultra_dictMatchState(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ const void* src, size_t srcSize)
{
- return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, cParams, src, srcSize, 2 /*optLevel*/, 0 /*extDict*/);
+ return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 2 /*optLevel*/, ZSTD_dictMatchState);
}
size_t ZSTD_compressBlock_btopt_extDict(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize)
+ const void* src, size_t srcSize)
{
- return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, cParams, src, srcSize, 0 /*optLevel*/, 1 /*extDict*/);
+ return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 0 /*optLevel*/, ZSTD_extDict);
}
size_t ZSTD_compressBlock_btultra_extDict(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize)
+ const void* src, size_t srcSize)
{
- return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, cParams, src, srcSize, 2 /*optLevel*/, 1 /*extDict*/);
+ return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 2 /*optLevel*/, ZSTD_extDict);
}
+
+/* note : no btultra2 variant for extDict nor dictMatchState,
+ * because btultra2 is not meant to work with dictionaries
+ * and is only specific for the first block (no prefix) */
diff --git a/thirdparty/zstd/compress/zstd_opt.h b/thirdparty/zstd/compress/zstd_opt.h
index b8dc389f31..094f747665 100644
--- a/thirdparty/zstd/compress/zstd_opt.h
+++ b/thirdparty/zstd/compress/zstd_opt.h
@@ -17,23 +17,37 @@ extern "C" {
#include "zstd_compress_internal.h"
-void ZSTD_updateTree(
- ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
- const BYTE* ip, const BYTE* iend); /* used in ZSTD_loadDictionaryContent() */
+/* used in ZSTD_loadDictionaryContent() */
+void ZSTD_updateTree(ZSTD_matchState_t* ms, const BYTE* ip, const BYTE* iend);
size_t ZSTD_compressBlock_btopt(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
+ void const* src, size_t srcSize);
size_t ZSTD_compressBlock_btultra(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
+ void const* src, size_t srcSize);
+size_t ZSTD_compressBlock_btultra2(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize);
+
+
+size_t ZSTD_compressBlock_btopt_dictMatchState(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize);
+size_t ZSTD_compressBlock_btultra_dictMatchState(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize);
size_t ZSTD_compressBlock_btopt_extDict(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
+ void const* src, size_t srcSize);
size_t ZSTD_compressBlock_btultra_extDict(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
+ void const* src, size_t srcSize);
+
+ /* note : no btultra2 variant for extDict nor dictMatchState,
+ * because btultra2 is not meant to work with dictionaries
+ * and is only specific for the first block (no prefix) */
#if defined (__cplusplus)
}
diff --git a/thirdparty/zstd/compress/zstdmt_compress.c b/thirdparty/zstd/compress/zstdmt_compress.c
index c7a205d8c7..38fbb90768 100644
--- a/thirdparty/zstd/compress/zstdmt_compress.c
+++ b/thirdparty/zstd/compress/zstdmt_compress.c
@@ -9,21 +9,20 @@
*/
-/* ====== Tuning parameters ====== */
-#define ZSTDMT_NBWORKERS_MAX 200
-#define ZSTDMT_JOBSIZE_MAX (MEM_32bits() ? (512 MB) : (2 GB)) /* note : limited by `jobSize` type, which is `unsigned` */
-#define ZSTDMT_OVERLAPLOG_DEFAULT 6
-
-
/* ====== Compiler specifics ====== */
#if defined(_MSC_VER)
# pragma warning(disable : 4204) /* disable: C4204: non-constant aggregate initializer */
#endif
+/* ====== Constants ====== */
+#define ZSTDMT_OVERLAPLOG_DEFAULT 0
+
+
/* ====== Dependencies ====== */
#include <string.h> /* memcpy, memset */
-#include <limits.h> /* INT_MAX */
+#include <limits.h> /* INT_MAX, UINT_MAX */
+#include "mem.h" /* MEM_STATIC */
#include "pool.h" /* threadpool */
#include "threading.h" /* mutex */
#include "zstd_compress_internal.h" /* MIN, ERROR, ZSTD_*, ZSTD_highbit32 */
@@ -37,18 +36,19 @@
#define ZSTD_RESIZE_SEQPOOL 0
/* ====== Debug ====== */
-#if defined(ZSTD_DEBUG) && (ZSTD_DEBUG>=2)
+#if defined(DEBUGLEVEL) && (DEBUGLEVEL>=2) \
+ && !defined(_MSC_VER) \
+ && !defined(__MINGW32__)
# include <stdio.h>
# include <unistd.h>
# include <sys/times.h>
-# define DEBUGLOGRAW(l, ...) if (l<=ZSTD_DEBUG) { fprintf(stderr, __VA_ARGS__); }
# define DEBUG_PRINTHEX(l,p,n) { \
unsigned debug_u; \
for (debug_u=0; debug_u<(n); debug_u++) \
- DEBUGLOGRAW(l, "%02X ", ((const unsigned char*)(p))[debug_u]); \
- DEBUGLOGRAW(l, " \n"); \
+ RAWLOG(l, "%02X ", ((const unsigned char*)(p))[debug_u]); \
+ RAWLOG(l, " \n"); \
}
static unsigned long long GetCurrentClockTimeMicroseconds(void)
@@ -56,13 +56,13 @@ static unsigned long long GetCurrentClockTimeMicroseconds(void)
static clock_t _ticksPerSecond = 0;
if (_ticksPerSecond <= 0) _ticksPerSecond = sysconf(_SC_CLK_TCK);
- { struct tms junk; clock_t newTicks = (clock_t) times(&junk);
- return ((((unsigned long long)newTicks)*(1000000))/_ticksPerSecond); }
-}
+ { struct tms junk; clock_t newTicks = (clock_t) times(&junk);
+ return ((((unsigned long long)newTicks)*(1000000))/_ticksPerSecond);
+} }
#define MUTEX_WAIT_TIME_DLEVEL 6
#define ZSTD_PTHREAD_MUTEX_LOCK(mutex) { \
- if (ZSTD_DEBUG >= MUTEX_WAIT_TIME_DLEVEL) { \
+ if (DEBUGLEVEL >= MUTEX_WAIT_TIME_DLEVEL) { \
unsigned long long const beforeTime = GetCurrentClockTimeMicroseconds(); \
ZSTD_pthread_mutex_lock(mutex); \
{ unsigned long long const afterTime = GetCurrentClockTimeMicroseconds(); \
@@ -160,6 +160,25 @@ static void ZSTDMT_setBufferSize(ZSTDMT_bufferPool* const bufPool, size_t const
ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);
}
+
+static ZSTDMT_bufferPool* ZSTDMT_expandBufferPool(ZSTDMT_bufferPool* srcBufPool, U32 nbWorkers)
+{
+ unsigned const maxNbBuffers = 2*nbWorkers + 3;
+ if (srcBufPool==NULL) return NULL;
+ if (srcBufPool->totalBuffers >= maxNbBuffers) /* good enough */
+ return srcBufPool;
+ /* need a larger buffer pool */
+ { ZSTD_customMem const cMem = srcBufPool->cMem;
+ size_t const bSize = srcBufPool->bufferSize; /* forward parameters */
+ ZSTDMT_bufferPool* newBufPool;
+ ZSTDMT_freeBufferPool(srcBufPool);
+ newBufPool = ZSTDMT_createBufferPool(nbWorkers, cMem);
+ if (newBufPool==NULL) return newBufPool;
+ ZSTDMT_setBufferSize(newBufPool, bSize);
+ return newBufPool;
+ }
+}
+
/** ZSTDMT_getBuffer() :
* assumption : bufPool must be valid
* @return : a buffer, with start pointer and size
@@ -229,8 +248,8 @@ static buffer_t ZSTDMT_resizeBuffer(ZSTDMT_bufferPool* bufPool, buffer_t buffer)
/* store buffer for later re-use, up to pool capacity */
static void ZSTDMT_releaseBuffer(ZSTDMT_bufferPool* bufPool, buffer_t buf)
{
- if (buf.start == NULL) return; /* compatible with release on NULL */
DEBUGLOG(5, "ZSTDMT_releaseBuffer");
+ if (buf.start == NULL) return; /* compatible with release on NULL */
ZSTD_pthread_mutex_lock(&bufPool->poolMutex);
if (bufPool->nbBuffers < bufPool->totalBuffers) {
bufPool->bTable[bufPool->nbBuffers++] = buf; /* stored for later use */
@@ -300,7 +319,8 @@ static void ZSTDMT_setNbSeq(ZSTDMT_seqPool* const seqPool, size_t const nbSeq)
static ZSTDMT_seqPool* ZSTDMT_createSeqPool(unsigned nbWorkers, ZSTD_customMem cMem)
{
- ZSTDMT_seqPool* seqPool = ZSTDMT_createBufferPool(nbWorkers, cMem);
+ ZSTDMT_seqPool* const seqPool = ZSTDMT_createBufferPool(nbWorkers, cMem);
+ if (seqPool == NULL) return NULL;
ZSTDMT_setNbSeq(seqPool, 0);
return seqPool;
}
@@ -310,6 +330,10 @@ static void ZSTDMT_freeSeqPool(ZSTDMT_seqPool* seqPool)
ZSTDMT_freeBufferPool(seqPool);
}
+static ZSTDMT_seqPool* ZSTDMT_expandSeqPool(ZSTDMT_seqPool* pool, U32 nbWorkers)
+{
+ return ZSTDMT_expandBufferPool(pool, nbWorkers);
+}
/* ===== CCtx Pool ===== */
@@ -317,8 +341,8 @@ static void ZSTDMT_freeSeqPool(ZSTDMT_seqPool* seqPool)
typedef struct {
ZSTD_pthread_mutex_t poolMutex;
- unsigned totalCCtx;
- unsigned availCCtx;
+ int totalCCtx;
+ int availCCtx;
ZSTD_customMem cMem;
ZSTD_CCtx* cctx[1]; /* variable size */
} ZSTDMT_CCtxPool;
@@ -326,16 +350,16 @@ typedef struct {
/* note : all CCtx borrowed from the pool should be released back to the pool _before_ freeing the pool */
static void ZSTDMT_freeCCtxPool(ZSTDMT_CCtxPool* pool)
{
- unsigned u;
- for (u=0; u<pool->totalCCtx; u++)
- ZSTD_freeCCtx(pool->cctx[u]); /* note : compatible with free on NULL */
+ int cid;
+ for (cid=0; cid<pool->totalCCtx; cid++)
+ ZSTD_freeCCtx(pool->cctx[cid]); /* note : compatible with free on NULL */
ZSTD_pthread_mutex_destroy(&pool->poolMutex);
ZSTD_free(pool, pool->cMem);
}
/* ZSTDMT_createCCtxPool() :
* implies nbWorkers >= 1 , checked by caller ZSTDMT_createCCtx() */
-static ZSTDMT_CCtxPool* ZSTDMT_createCCtxPool(unsigned nbWorkers,
+static ZSTDMT_CCtxPool* ZSTDMT_createCCtxPool(int nbWorkers,
ZSTD_customMem cMem)
{
ZSTDMT_CCtxPool* const cctxPool = (ZSTDMT_CCtxPool*) ZSTD_calloc(
@@ -355,6 +379,18 @@ static ZSTDMT_CCtxPool* ZSTDMT_createCCtxPool(unsigned nbWorkers,
return cctxPool;
}
+static ZSTDMT_CCtxPool* ZSTDMT_expandCCtxPool(ZSTDMT_CCtxPool* srcPool,
+ int nbWorkers)
+{
+ if (srcPool==NULL) return NULL;
+ if (nbWorkers <= srcPool->totalCCtx) return srcPool; /* good enough */
+ /* need a larger cctx pool */
+ { ZSTD_customMem const cMem = srcPool->cMem;
+ ZSTDMT_freeCCtxPool(srcPool);
+ return ZSTDMT_createCCtxPool(nbWorkers, cMem);
+ }
+}
+
/* only works during initialization phase, not during compression */
static size_t ZSTDMT_sizeof_CCtxPool(ZSTDMT_CCtxPool* cctxPool)
{
@@ -421,21 +457,20 @@ typedef struct {
* Must be acquired after the main mutex when acquiring both.
*/
ZSTD_pthread_mutex_t ldmWindowMutex;
- ZSTD_pthread_cond_t ldmWindowCond; /* Signaled when ldmWindow is udpated */
+ ZSTD_pthread_cond_t ldmWindowCond; /* Signaled when ldmWindow is updated */
ZSTD_window_t ldmWindow; /* A thread-safe copy of ldmState.window */
} serialState_t;
-static int ZSTDMT_serialState_reset(serialState_t* serialState, ZSTDMT_seqPool* seqPool, ZSTD_CCtx_params params)
+static int ZSTDMT_serialState_reset(serialState_t* serialState, ZSTDMT_seqPool* seqPool, ZSTD_CCtx_params params, size_t jobSize)
{
/* Adjust parameters */
if (params.ldmParams.enableLdm) {
DEBUGLOG(4, "LDM window size = %u KB", (1U << params.cParams.windowLog) >> 10);
- params.ldmParams.windowLog = params.cParams.windowLog;
ZSTD_ldm_adjustParameters(&params.ldmParams, &params.cParams);
assert(params.ldmParams.hashLog >= params.ldmParams.bucketSizeLog);
- assert(params.ldmParams.hashEveryLog < 32);
+ assert(params.ldmParams.hashRateLog < 32);
serialState->ldmState.hashPower =
- ZSTD_ldm_getHashPower(params.ldmParams.minMatchLength);
+ ZSTD_rollingHash_primePower(params.ldmParams.minMatchLength);
} else {
memset(&params.ldmParams, 0, sizeof(params.ldmParams));
}
@@ -453,7 +488,7 @@ static int ZSTDMT_serialState_reset(serialState_t* serialState, ZSTDMT_seqPool*
serialState->params.ldmParams.hashLog -
serialState->params.ldmParams.bucketSizeLog;
/* Size the seq pool tables */
- ZSTDMT_setNbSeq(seqPool, ZSTD_ldm_getMaxNbSeq(params.ldmParams, params.jobSize));
+ ZSTDMT_setNbSeq(seqPool, ZSTD_ldm_getMaxNbSeq(params.ldmParams, jobSize));
/* Reset the window */
ZSTD_window_clear(&serialState->ldmState.window);
serialState->ldmWindow = serialState->ldmState.window;
@@ -473,6 +508,7 @@ static int ZSTDMT_serialState_reset(serialState_t* serialState, ZSTDMT_seqPool*
memset(serialState->ldmState.bucketOffsets, 0, bucketSize);
}
serialState->params = params;
+ serialState->params.jobSize = (U32)jobSize;
return 0;
}
@@ -505,6 +541,7 @@ static void ZSTDMT_serialState_update(serialState_t* serialState,
/* Wait for our turn */
ZSTD_PTHREAD_MUTEX_LOCK(&serialState->mutex);
while (serialState->nextJobID < jobID) {
+ DEBUGLOG(5, "wait for serialState->cond");
ZSTD_pthread_cond_wait(&serialState->cond, &serialState->mutex);
}
/* A future job may error and skip our job */
@@ -514,6 +551,7 @@ static void ZSTDMT_serialState_update(serialState_t* serialState,
size_t error;
assert(seqStore.seq != NULL && seqStore.pos == 0 &&
seqStore.size == 0 && seqStore.capacity > 0);
+ assert(src.size <= serialState->params.jobSize);
ZSTD_window_update(&serialState->ldmState.window, src.start, src.size);
error = ZSTD_ldm_generateSequences(
&serialState->ldmState, &seqStore,
@@ -593,14 +631,32 @@ typedef struct {
unsigned frameChecksumNeeded; /* used only by mtctx */
} ZSTDMT_jobDescription;
+#define JOB_ERROR(e) { \
+ ZSTD_PTHREAD_MUTEX_LOCK(&job->job_mutex); \
+ job->cSize = e; \
+ ZSTD_pthread_mutex_unlock(&job->job_mutex); \
+ goto _endJob; \
+}
+
/* ZSTDMT_compressionJob() is a POOL_function type */
-void ZSTDMT_compressionJob(void* jobDescription)
+static void ZSTDMT_compressionJob(void* jobDescription)
{
ZSTDMT_jobDescription* const job = (ZSTDMT_jobDescription*)jobDescription;
ZSTD_CCtx_params jobParams = job->params; /* do not modify job->params ! copy it, modify the copy */
ZSTD_CCtx* const cctx = ZSTDMT_getCCtx(job->cctxPool);
rawSeqStore_t rawSeqStore = ZSTDMT_getSeq(job->seqPool);
buffer_t dstBuff = job->dstBuff;
+ size_t lastCBlockSize = 0;
+
+ /* resources */
+ if (cctx==NULL) JOB_ERROR(ERROR(memory_allocation));
+ if (dstBuff.start == NULL) { /* streaming job : doesn't provide a dstBuffer */
+ dstBuff = ZSTDMT_getBuffer(job->bufPool);
+ if (dstBuff.start==NULL) JOB_ERROR(ERROR(memory_allocation));
+ job->dstBuff = dstBuff; /* this value can be read in ZSTDMT_flush, when it copies the whole job */
+ }
+ if (jobParams.ldmParams.enableLdm && rawSeqStore.seq == NULL)
+ JOB_ERROR(ERROR(memory_allocation));
/* Don't compute the checksum for chunks, since we compute it externally,
* but write it in the header.
@@ -609,47 +665,31 @@ void ZSTDMT_compressionJob(void* jobDescription)
/* Don't run LDM for the chunks, since we handle it externally */
jobParams.ldmParams.enableLdm = 0;
- /* ressources */
- if (cctx==NULL) {
- job->cSize = ERROR(memory_allocation);
- goto _endJob;
- }
- if (dstBuff.start == NULL) { /* streaming job : doesn't provide a dstBuffer */
- dstBuff = ZSTDMT_getBuffer(job->bufPool);
- if (dstBuff.start==NULL) {
- job->cSize = ERROR(memory_allocation);
- goto _endJob;
- }
- job->dstBuff = dstBuff; /* this value can be read in ZSTDMT_flush, when it copies the whole job */
- }
/* init */
if (job->cdict) {
- size_t const initError = ZSTD_compressBegin_advanced_internal(cctx, NULL, 0, ZSTD_dct_auto, job->cdict, jobParams, job->fullFrameSize);
+ size_t const initError = ZSTD_compressBegin_advanced_internal(cctx, NULL, 0, ZSTD_dct_auto, ZSTD_dtlm_fast, job->cdict, jobParams, job->fullFrameSize);
assert(job->firstJob); /* only allowed for first job */
- if (ZSTD_isError(initError)) { job->cSize = initError; goto _endJob; }
+ if (ZSTD_isError(initError)) JOB_ERROR(initError);
} else { /* srcStart points at reloaded section */
U64 const pledgedSrcSize = job->firstJob ? job->fullFrameSize : job->src.size;
- { size_t const forceWindowError = ZSTD_CCtxParam_setParameter(&jobParams, ZSTD_p_forceMaxWindow, !job->firstJob);
- if (ZSTD_isError(forceWindowError)) {
- job->cSize = forceWindowError;
- goto _endJob;
- } }
+ { size_t const forceWindowError = ZSTD_CCtxParams_setParameter(&jobParams, ZSTD_c_forceMaxWindow, !job->firstJob);
+ if (ZSTD_isError(forceWindowError)) JOB_ERROR(forceWindowError);
+ }
{ size_t const initError = ZSTD_compressBegin_advanced_internal(cctx,
job->prefix.start, job->prefix.size, ZSTD_dct_rawContent, /* load dictionary in "content-only" mode (no header analysis) */
+ ZSTD_dtlm_fast,
NULL, /*cdict*/
jobParams, pledgedSrcSize);
- if (ZSTD_isError(initError)) {
- job->cSize = initError;
- goto _endJob;
- } } }
+ if (ZSTD_isError(initError)) JOB_ERROR(initError);
+ } }
/* Perform serial step as early as possible, but after CCtx initialization */
ZSTDMT_serialState_update(job->serial, cctx, rawSeqStore, job->src, job->jobID);
if (!job->firstJob) { /* flush and overwrite frame header when it's not first job */
size_t const hSize = ZSTD_compressContinue(cctx, dstBuff.start, dstBuff.capacity, job->src.start, 0);
- if (ZSTD_isError(hSize)) { job->cSize = hSize; /* save error code */ goto _endJob; }
+ if (ZSTD_isError(hSize)) JOB_ERROR(hSize);
DEBUGLOG(5, "ZSTDMT_compressionJob: flush and overwrite %u bytes of frame header (not first job)", (U32)hSize);
ZSTD_invalidateRepCodes(cctx);
}
@@ -667,7 +707,7 @@ void ZSTDMT_compressionJob(void* jobDescription)
assert(job->cSize == 0);
for (chunkNb = 1; chunkNb < nbChunks; chunkNb++) {
size_t const cSize = ZSTD_compressContinue(cctx, op, oend-op, ip, chunkSize);
- if (ZSTD_isError(cSize)) { job->cSize = cSize; goto _endJob; }
+ if (ZSTD_isError(cSize)) JOB_ERROR(cSize);
ip += chunkSize;
op += cSize; assert(op < oend);
/* stats */
@@ -680,18 +720,16 @@ void ZSTDMT_compressionJob(void* jobDescription)
ZSTD_pthread_mutex_unlock(&job->job_mutex);
}
/* last block */
- assert(chunkSize > 0); assert((chunkSize & (chunkSize - 1)) == 0); /* chunkSize must be power of 2 for mask==(chunkSize-1) to work */
+ assert(chunkSize > 0);
+ assert((chunkSize & (chunkSize - 1)) == 0); /* chunkSize must be power of 2 for mask==(chunkSize-1) to work */
if ((nbChunks > 0) | job->lastJob /*must output a "last block" flag*/ ) {
size_t const lastBlockSize1 = job->src.size & (chunkSize-1);
size_t const lastBlockSize = ((lastBlockSize1==0) & (job->src.size>=chunkSize)) ? chunkSize : lastBlockSize1;
size_t const cSize = (job->lastJob) ?
ZSTD_compressEnd (cctx, op, oend-op, ip, lastBlockSize) :
ZSTD_compressContinue(cctx, op, oend-op, ip, lastBlockSize);
- if (ZSTD_isError(cSize)) { job->cSize = cSize; goto _endJob; }
- /* stats */
- ZSTD_PTHREAD_MUTEX_LOCK(&job->job_mutex);
- job->cSize += cSize;
- ZSTD_pthread_mutex_unlock(&job->job_mutex);
+ if (ZSTD_isError(cSize)) JOB_ERROR(cSize);
+ lastCBlockSize = cSize;
} }
_endJob:
@@ -704,7 +742,9 @@ _endJob:
ZSTDMT_releaseCCtx(job->cctxPool, cctx);
/* report */
ZSTD_PTHREAD_MUTEX_LOCK(&job->job_mutex);
- job->consumed = job->src.size;
+ if (ZSTD_isError(job->cSize)) assert(lastCBlockSize == 0);
+ job->cSize += lastCBlockSize;
+ job->consumed = job->src.size; /* when job->consumed == job->src.size , compression job is presumed completed */
ZSTD_pthread_cond_signal(&job->job_cond);
ZSTD_pthread_mutex_unlock(&job->job_mutex);
}
@@ -736,6 +776,14 @@ typedef struct {
static const roundBuff_t kNullRoundBuff = {NULL, 0, 0};
+#define RSYNC_LENGTH 32
+
+typedef struct {
+ U64 hash;
+ U64 hitMask;
+ U64 primePower;
+} rsyncState_t;
+
struct ZSTDMT_CCtx_s {
POOL_ctx* factory;
ZSTDMT_jobDescription* jobs;
@@ -745,10 +793,11 @@ struct ZSTDMT_CCtx_s {
ZSTD_CCtx_params params;
size_t targetSectionSize;
size_t targetPrefixSize;
- roundBuff_t roundBuff;
+ int jobReady; /* 1 => one job is already prepared, but pool has shortage of workers. Don't create a new job. */
inBuff_t inBuff;
- int jobReady; /* 1 => one job is already prepared, but pool has shortage of workers. Don't create another one. */
+ roundBuff_t roundBuff;
serialState_t serial;
+ rsyncState_t rsync;
unsigned singleBlockingThread;
unsigned jobIDMask;
unsigned doneJobID;
@@ -798,18 +847,28 @@ static ZSTDMT_jobDescription* ZSTDMT_createJobsTable(U32* nbJobsPtr, ZSTD_custom
return jobTable;
}
+static size_t ZSTDMT_expandJobsTable (ZSTDMT_CCtx* mtctx, U32 nbWorkers) {
+ U32 nbJobs = nbWorkers + 2;
+ if (nbJobs > mtctx->jobIDMask+1) { /* need more job capacity */
+ ZSTDMT_freeJobsTable(mtctx->jobs, mtctx->jobIDMask+1, mtctx->cMem);
+ mtctx->jobIDMask = 0;
+ mtctx->jobs = ZSTDMT_createJobsTable(&nbJobs, mtctx->cMem);
+ if (mtctx->jobs==NULL) return ERROR(memory_allocation);
+ assert((nbJobs != 0) && ((nbJobs & (nbJobs - 1)) == 0)); /* ensure nbJobs is a power of 2 */
+ mtctx->jobIDMask = nbJobs - 1;
+ }
+ return 0;
+}
+
+
/* ZSTDMT_CCtxParam_setNbWorkers():
* Internal use only */
size_t ZSTDMT_CCtxParam_setNbWorkers(ZSTD_CCtx_params* params, unsigned nbWorkers)
{
- if (nbWorkers > ZSTDMT_NBWORKERS_MAX) nbWorkers = ZSTDMT_NBWORKERS_MAX;
- params->nbWorkers = nbWorkers;
- params->overlapSizeLog = ZSTDMT_OVERLAPLOG_DEFAULT;
- params->jobSize = 0;
- return nbWorkers;
+ return ZSTD_CCtxParams_setParameter(params, ZSTD_c_nbWorkers, (int)nbWorkers);
}
-ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers, ZSTD_customMem cMem)
+MEM_STATIC ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced_internal(unsigned nbWorkers, ZSTD_customMem cMem)
{
ZSTDMT_CCtx* mtctx;
U32 nbJobs = nbWorkers + 2;
@@ -844,6 +903,17 @@ ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers, ZSTD_customMem cMem)
return mtctx;
}
+ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers, ZSTD_customMem cMem)
+{
+#ifdef ZSTD_MULTITHREAD
+ return ZSTDMT_createCCtx_advanced_internal(nbWorkers, cMem);
+#else
+ (void)nbWorkers;
+ (void)cMem;
+ return NULL;
+#endif
+}
+
ZSTDMT_CCtx* ZSTDMT_createCCtx(unsigned nbWorkers)
{
return ZSTDMT_createCCtx_advanced(nbWorkers, ZSTD_defaultCMem);
@@ -875,7 +945,7 @@ static void ZSTDMT_waitForAllJobsCompleted(ZSTDMT_CCtx* mtctx)
unsigned const jobID = mtctx->doneJobID & mtctx->jobIDMask;
ZSTD_PTHREAD_MUTEX_LOCK(&mtctx->jobs[jobID].job_mutex);
while (mtctx->jobs[jobID].consumed < mtctx->jobs[jobID].src.size) {
- DEBUGLOG(5, "waiting for jobCompleted signal from job %u", mtctx->doneJobID); /* we want to block when waiting for data to flush */
+ DEBUGLOG(4, "waiting for jobCompleted signal from job %u", mtctx->doneJobID); /* we want to block when waiting for data to flush */
ZSTD_pthread_cond_wait(&mtctx->jobs[jobID].job_cond, &mtctx->jobs[jobID].job_mutex);
}
ZSTD_pthread_mutex_unlock(&mtctx->jobs[jobID].job_mutex);
@@ -914,38 +984,44 @@ size_t ZSTDMT_sizeof_CCtx(ZSTDMT_CCtx* mtctx)
}
/* Internal only */
-size_t ZSTDMT_CCtxParam_setMTCtxParameter(ZSTD_CCtx_params* params,
- ZSTDMT_parameter parameter, unsigned value) {
+size_t
+ZSTDMT_CCtxParam_setMTCtxParameter(ZSTD_CCtx_params* params,
+ ZSTDMT_parameter parameter,
+ int value)
+{
DEBUGLOG(4, "ZSTDMT_CCtxParam_setMTCtxParameter");
switch(parameter)
{
case ZSTDMT_p_jobSize :
- DEBUGLOG(4, "ZSTDMT_CCtxParam_setMTCtxParameter : set jobSize to %u", value);
- if ( (value > 0) /* value==0 => automatic job size */
- & (value < ZSTDMT_JOBSIZE_MIN) )
- value = ZSTDMT_JOBSIZE_MIN;
- params->jobSize = value;
- return value;
- case ZSTDMT_p_overlapSectionLog :
- if (value > 9) value = 9;
- DEBUGLOG(4, "ZSTDMT_p_overlapSectionLog : %u", value);
- params->overlapSizeLog = (value >= 9) ? 9 : value;
- return value;
+ DEBUGLOG(4, "ZSTDMT_CCtxParam_setMTCtxParameter : set jobSize to %i", value);
+ return ZSTD_CCtxParams_setParameter(params, ZSTD_c_jobSize, value);
+ case ZSTDMT_p_overlapLog :
+ DEBUGLOG(4, "ZSTDMT_p_overlapLog : %i", value);
+ return ZSTD_CCtxParams_setParameter(params, ZSTD_c_overlapLog, value);
+ case ZSTDMT_p_rsyncable :
+ DEBUGLOG(4, "ZSTD_p_rsyncable : %i", value);
+ return ZSTD_CCtxParams_setParameter(params, ZSTD_c_rsyncable, value);
default :
return ERROR(parameter_unsupported);
}
}
-size_t ZSTDMT_setMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, unsigned value)
+size_t ZSTDMT_setMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, int value)
{
DEBUGLOG(4, "ZSTDMT_setMTCtxParameter");
- switch(parameter)
- {
- case ZSTDMT_p_jobSize :
- return ZSTDMT_CCtxParam_setMTCtxParameter(&mtctx->params, parameter, value);
- case ZSTDMT_p_overlapSectionLog :
- return ZSTDMT_CCtxParam_setMTCtxParameter(&mtctx->params, parameter, value);
- default :
+ return ZSTDMT_CCtxParam_setMTCtxParameter(&mtctx->params, parameter, value);
+}
+
+size_t ZSTDMT_getMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, int* value)
+{
+ switch (parameter) {
+ case ZSTDMT_p_jobSize:
+ return ZSTD_CCtxParams_getParameter(&mtctx->params, ZSTD_c_jobSize, value);
+ case ZSTDMT_p_overlapLog:
+ return ZSTD_CCtxParams_getParameter(&mtctx->params, ZSTD_c_overlapLog, value);
+ case ZSTDMT_p_rsyncable:
+ return ZSTD_CCtxParams_getParameter(&mtctx->params, ZSTD_c_rsyncable, value);
+ default:
return ERROR(parameter_unsupported);
}
}
@@ -954,19 +1030,38 @@ size_t ZSTDMT_setMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter,
* initializing others to default values. */
static ZSTD_CCtx_params ZSTDMT_initJobCCtxParams(ZSTD_CCtx_params const params)
{
- ZSTD_CCtx_params jobParams;
- memset(&jobParams, 0, sizeof(jobParams));
+ ZSTD_CCtx_params jobParams = params;
+ /* Clear parameters related to multithreading */
+ jobParams.forceWindow = 0;
+ jobParams.nbWorkers = 0;
+ jobParams.jobSize = 0;
+ jobParams.overlapLog = 0;
+ jobParams.rsyncable = 0;
+ memset(&jobParams.ldmParams, 0, sizeof(ldmParams_t));
+ memset(&jobParams.customMem, 0, sizeof(ZSTD_customMem));
+ return jobParams;
+}
- jobParams.cParams = params.cParams;
- jobParams.fParams = params.fParams;
- jobParams.compressionLevel = params.compressionLevel;
- jobParams.disableLiteralCompression = params.disableLiteralCompression;
- return jobParams;
+/* ZSTDMT_resize() :
+ * @return : error code if fails, 0 on success */
+static size_t ZSTDMT_resize(ZSTDMT_CCtx* mtctx, unsigned nbWorkers)
+{
+ if (POOL_resize(mtctx->factory, nbWorkers)) return ERROR(memory_allocation);
+ FORWARD_IF_ERROR( ZSTDMT_expandJobsTable(mtctx, nbWorkers) );
+ mtctx->bufPool = ZSTDMT_expandBufferPool(mtctx->bufPool, nbWorkers);
+ if (mtctx->bufPool == NULL) return ERROR(memory_allocation);
+ mtctx->cctxPool = ZSTDMT_expandCCtxPool(mtctx->cctxPool, nbWorkers);
+ if (mtctx->cctxPool == NULL) return ERROR(memory_allocation);
+ mtctx->seqPool = ZSTDMT_expandSeqPool(mtctx->seqPool, nbWorkers);
+ if (mtctx->seqPool == NULL) return ERROR(memory_allocation);
+ ZSTDMT_CCtxParam_setNbWorkers(&mtctx->params, nbWorkers);
+ return 0;
}
+
/*! ZSTDMT_updateCParams_whileCompressing() :
- * Updates only a selected set of compression parameters, to remain compatible with current frame.
+ * Updates a selected set of compression parameters, remaining compatible with currently active frame.
* New parameters will be applied to next compression job. */
void ZSTDMT_updateCParams_whileCompressing(ZSTDMT_CCtx* mtctx, const ZSTD_CCtx_params* cctxParams)
{
@@ -981,38 +1076,36 @@ void ZSTDMT_updateCParams_whileCompressing(ZSTDMT_CCtx* mtctx, const ZSTD_CCtx_p
}
}
-/* ZSTDMT_getNbWorkers():
- * @return nb threads currently active in mtctx.
- * mtctx must be valid */
-unsigned ZSTDMT_getNbWorkers(const ZSTDMT_CCtx* mtctx)
-{
- assert(mtctx != NULL);
- return mtctx->params.nbWorkers;
-}
-
/* ZSTDMT_getFrameProgression():
* tells how much data has been consumed (input) and produced (output) for current frame.
* able to count progression inside worker threads.
- * Note : mutex will be acquired during statistics collection. */
+ * Note : mutex will be acquired during statistics collection inside workers. */
ZSTD_frameProgression ZSTDMT_getFrameProgression(ZSTDMT_CCtx* mtctx)
{
ZSTD_frameProgression fps;
- DEBUGLOG(6, "ZSTDMT_getFrameProgression");
- fps.consumed = mtctx->consumed;
- fps.produced = mtctx->produced;
+ DEBUGLOG(5, "ZSTDMT_getFrameProgression");
fps.ingested = mtctx->consumed + mtctx->inBuff.filled;
+ fps.consumed = mtctx->consumed;
+ fps.produced = fps.flushed = mtctx->produced;
+ fps.currentJobID = mtctx->nextJobID;
+ fps.nbActiveWorkers = 0;
{ unsigned jobNb;
unsigned lastJobNb = mtctx->nextJobID + mtctx->jobReady; assert(mtctx->jobReady <= 1);
DEBUGLOG(6, "ZSTDMT_getFrameProgression: jobs: from %u to <%u (jobReady:%u)",
mtctx->doneJobID, lastJobNb, mtctx->jobReady)
for (jobNb = mtctx->doneJobID ; jobNb < lastJobNb ; jobNb++) {
unsigned const wJobID = jobNb & mtctx->jobIDMask;
- ZSTD_pthread_mutex_lock(&mtctx->jobs[wJobID].job_mutex);
- { size_t const cResult = mtctx->jobs[wJobID].cSize;
+ ZSTDMT_jobDescription* jobPtr = &mtctx->jobs[wJobID];
+ ZSTD_pthread_mutex_lock(&jobPtr->job_mutex);
+ { size_t const cResult = jobPtr->cSize;
size_t const produced = ZSTD_isError(cResult) ? 0 : cResult;
- fps.consumed += mtctx->jobs[wJobID].consumed;
- fps.ingested += mtctx->jobs[wJobID].src.size;
+ size_t const flushed = ZSTD_isError(cResult) ? 0 : jobPtr->dstFlushed;
+ assert(flushed <= produced);
+ fps.ingested += jobPtr->src.size;
+ fps.consumed += jobPtr->consumed;
fps.produced += produced;
+ fps.flushed += flushed;
+ fps.nbActiveWorkers += (jobPtr->consumed < jobPtr->src.size);
}
ZSTD_pthread_mutex_unlock(&mtctx->jobs[wJobID].job_mutex);
}
@@ -1021,26 +1114,98 @@ ZSTD_frameProgression ZSTDMT_getFrameProgression(ZSTDMT_CCtx* mtctx)
}
+size_t ZSTDMT_toFlushNow(ZSTDMT_CCtx* mtctx)
+{
+ size_t toFlush;
+ unsigned const jobID = mtctx->doneJobID;
+ assert(jobID <= mtctx->nextJobID);
+ if (jobID == mtctx->nextJobID) return 0; /* no active job => nothing to flush */
+
+ /* look into oldest non-fully-flushed job */
+ { unsigned const wJobID = jobID & mtctx->jobIDMask;
+ ZSTDMT_jobDescription* const jobPtr = &mtctx->jobs[wJobID];
+ ZSTD_pthread_mutex_lock(&jobPtr->job_mutex);
+ { size_t const cResult = jobPtr->cSize;
+ size_t const produced = ZSTD_isError(cResult) ? 0 : cResult;
+ size_t const flushed = ZSTD_isError(cResult) ? 0 : jobPtr->dstFlushed;
+ assert(flushed <= produced);
+ toFlush = produced - flushed;
+ if (toFlush==0 && (jobPtr->consumed >= jobPtr->src.size)) {
+ /* doneJobID is not-fully-flushed, but toFlush==0 : doneJobID should be compressing some more data */
+ assert(jobPtr->consumed < jobPtr->src.size);
+ }
+ }
+ ZSTD_pthread_mutex_unlock(&mtctx->jobs[wJobID].job_mutex);
+ }
+
+ return toFlush;
+}
+
+
/* ------------------------------------------ */
/* ===== Multi-threaded compression ===== */
/* ------------------------------------------ */
-static size_t ZSTDMT_computeTargetJobLog(ZSTD_CCtx_params const params)
+static unsigned ZSTDMT_computeTargetJobLog(ZSTD_CCtx_params const params)
{
if (params.ldmParams.enableLdm)
+ /* In Long Range Mode, the windowLog is typically oversized.
+ * In which case, it's preferable to determine the jobSize
+ * based on chainLog instead. */
return MAX(21, params.cParams.chainLog + 4);
return MAX(20, params.cParams.windowLog + 2);
}
-static size_t ZSTDMT_computeOverlapLog(ZSTD_CCtx_params const params)
+static int ZSTDMT_overlapLog_default(ZSTD_strategy strat)
{
- unsigned const overlapRLog = (params.overlapSizeLog>9) ? 0 : 9-params.overlapSizeLog;
- if (params.ldmParams.enableLdm)
- return (MIN(params.cParams.windowLog, ZSTDMT_computeTargetJobLog(params) - 2) - overlapRLog);
- return overlapRLog >= 9 ? 0 : (params.cParams.windowLog - overlapRLog);
+ switch(strat)
+ {
+ case ZSTD_btultra2:
+ return 9;
+ case ZSTD_btultra:
+ case ZSTD_btopt:
+ return 8;
+ case ZSTD_btlazy2:
+ case ZSTD_lazy2:
+ return 7;
+ case ZSTD_lazy:
+ case ZSTD_greedy:
+ case ZSTD_dfast:
+ case ZSTD_fast:
+ default:;
+ }
+ return 6;
+}
+
+static int ZSTDMT_overlapLog(int ovlog, ZSTD_strategy strat)
+{
+ assert(0 <= ovlog && ovlog <= 9);
+ if (ovlog == 0) return ZSTDMT_overlapLog_default(strat);
+ return ovlog;
+}
+
+static size_t ZSTDMT_computeOverlapSize(ZSTD_CCtx_params const params)
+{
+ int const overlapRLog = 9 - ZSTDMT_overlapLog(params.overlapLog, params.cParams.strategy);
+ int ovLog = (overlapRLog >= 8) ? 0 : (params.cParams.windowLog - overlapRLog);
+ assert(0 <= overlapRLog && overlapRLog <= 8);
+ if (params.ldmParams.enableLdm) {
+ /* In Long Range Mode, the windowLog is typically oversized.
+ * In which case, it's preferable to determine the jobSize
+ * based on chainLog instead.
+ * Then, ovLog becomes a fraction of the jobSize, rather than windowSize */
+ ovLog = MIN(params.cParams.windowLog, ZSTDMT_computeTargetJobLog(params) - 2)
+ - overlapRLog;
+ }
+ assert(0 <= ovLog && ovLog <= 30);
+ DEBUGLOG(4, "overlapLog : %i", params.overlapLog);
+ DEBUGLOG(4, "overlap size : %i", 1 << ovLog);
+ return (ovLog==0) ? 0 : (size_t)1 << ovLog;
}
-static unsigned ZSTDMT_computeNbJobs(ZSTD_CCtx_params params, size_t srcSize, unsigned nbWorkers) {
+static unsigned
+ZSTDMT_computeNbJobs(ZSTD_CCtx_params params, size_t srcSize, unsigned nbWorkers)
+{
assert(nbWorkers>0);
{ size_t const jobSizeTarget = (size_t)1 << ZSTDMT_computeTargetJobLog(params);
size_t const jobMaxSize = jobSizeTarget << 2;
@@ -1063,7 +1228,7 @@ static size_t ZSTDMT_compress_advanced_internal(
ZSTD_CCtx_params params)
{
ZSTD_CCtx_params const jobParams = ZSTDMT_initJobCCtxParams(params);
- size_t const overlapSize = (size_t)1 << ZSTDMT_computeOverlapLog(params);
+ size_t const overlapSize = ZSTDMT_computeOverlapSize(params);
unsigned const nbJobs = ZSTDMT_computeNbJobs(params, srcSize, params.nbWorkers);
size_t const proposedJobSize = (srcSize + (nbJobs-1)) / nbJobs;
size_t const avgJobSize = (((proposedJobSize-1) & 0x1FFFF) < 0x7FFF) ? proposedJobSize + 0xFFFF : proposedJobSize; /* avoid too small last block */
@@ -1087,18 +1252,10 @@ static size_t ZSTDMT_compress_advanced_internal(
assert(avgJobSize >= 256 KB); /* condition for ZSTD_compressBound(A) + ZSTD_compressBound(B) <= ZSTD_compressBound(A+B), required to compress directly into Dst (no additional buffer) */
ZSTDMT_setBufferSize(mtctx->bufPool, ZSTD_compressBound(avgJobSize) );
- if (ZSTDMT_serialState_reset(&mtctx->serial, mtctx->seqPool, params))
+ if (ZSTDMT_serialState_reset(&mtctx->serial, mtctx->seqPool, params, avgJobSize))
return ERROR(memory_allocation);
- if (nbJobs > mtctx->jobIDMask+1) { /* enlarge job table */
- U32 jobsTableSize = nbJobs;
- ZSTDMT_freeJobsTable(mtctx->jobs, mtctx->jobIDMask+1, mtctx->cMem);
- mtctx->jobIDMask = 0;
- mtctx->jobs = ZSTDMT_createJobsTable(&jobsTableSize, mtctx->cMem);
- if (mtctx->jobs==NULL) return ERROR(memory_allocation);
- assert((jobsTableSize != 0) && ((jobsTableSize & (jobsTableSize - 1)) == 0)); /* ensure jobsTableSize is a power of 2 */
- mtctx->jobIDMask = jobsTableSize - 1;
- }
+ FORWARD_IF_ERROR( ZSTDMT_expandJobsTable(mtctx, nbJobs) ); /* only expands if necessary */
{ unsigned u;
for (u=0; u<nbJobs; u++) {
@@ -1182,16 +1339,17 @@ static size_t ZSTDMT_compress_advanced_internal(
}
size_t ZSTDMT_compress_advanced(ZSTDMT_CCtx* mtctx,
- void* dst, size_t dstCapacity,
- const void* src, size_t srcSize,
- const ZSTD_CDict* cdict,
- ZSTD_parameters params,
- unsigned overlapLog)
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize,
+ const ZSTD_CDict* cdict,
+ ZSTD_parameters params,
+ int overlapLog)
{
ZSTD_CCtx_params cctxParams = mtctx->params;
cctxParams.cParams = params.cParams;
cctxParams.fParams = params.fParams;
- cctxParams.overlapSizeLog = overlapLog;
+ assert(ZSTD_OVERLAPLOG_MIN <= overlapLog && overlapLog <= ZSTD_OVERLAPLOG_MAX);
+ cctxParams.overlapLog = overlapLog;
return ZSTDMT_compress_advanced_internal(mtctx,
dst, dstCapacity,
src, srcSize,
@@ -1204,8 +1362,8 @@ size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
const void* src, size_t srcSize,
int compressionLevel)
{
- U32 const overlapLog = (compressionLevel >= ZSTD_maxCLevel()) ? 9 : ZSTDMT_OVERLAPLOG_DEFAULT;
ZSTD_parameters params = ZSTD_getParams(compressionLevel, srcSize, 0);
+ int const overlapLog = ZSTDMT_overlapLog_default(params.cParams.strategy);
params.fParams.contentSizeFlag = 1;
return ZSTDMT_compress_advanced(mtctx, dst, dstCapacity, src, srcSize, NULL, params, overlapLog);
}
@@ -1221,18 +1379,19 @@ size_t ZSTDMT_initCStream_internal(
const ZSTD_CDict* cdict, ZSTD_CCtx_params params,
unsigned long long pledgedSrcSize)
{
- DEBUGLOG(4, "ZSTDMT_initCStream_internal (pledgedSrcSize=%u, nbWorkers=%u, cctxPool=%u, disableLiteralCompression=%i)",
- (U32)pledgedSrcSize, params.nbWorkers, mtctx->cctxPool->totalCCtx, params.disableLiteralCompression);
- /* params are supposed to be fully validated at this point */
+ DEBUGLOG(4, "ZSTDMT_initCStream_internal (pledgedSrcSize=%u, nbWorkers=%u, cctxPool=%u)",
+ (U32)pledgedSrcSize, params.nbWorkers, mtctx->cctxPool->totalCCtx);
+
+ /* params supposed partially fully validated at this point */
assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
assert(!((dict) && (cdict))); /* either dict or cdict, not both */
- assert(mtctx->cctxPool->totalCCtx == params.nbWorkers);
/* init */
- if (params.jobSize == 0) {
- params.jobSize = 1U << ZSTDMT_computeTargetJobLog(params);
- }
- if (params.jobSize > ZSTDMT_JOBSIZE_MAX) params.jobSize = ZSTDMT_JOBSIZE_MAX;
+ if (params.nbWorkers != mtctx->params.nbWorkers)
+ FORWARD_IF_ERROR( ZSTDMT_resize(mtctx, params.nbWorkers) );
+
+ if (params.jobSize != 0 && params.jobSize < ZSTDMT_JOBSIZE_MIN) params.jobSize = ZSTDMT_JOBSIZE_MIN;
+ if (params.jobSize > (size_t)ZSTDMT_JOBSIZE_MAX) params.jobSize = ZSTDMT_JOBSIZE_MAX;
mtctx->singleBlockingThread = (pledgedSrcSize <= ZSTDMT_JOBSIZE_MIN); /* do not trigger multi-threading when srcSize is too small */
if (mtctx->singleBlockingThread) {
@@ -1267,12 +1426,24 @@ size_t ZSTDMT_initCStream_internal(
mtctx->cdict = cdict;
}
- mtctx->targetPrefixSize = (size_t)1 << ZSTDMT_computeOverlapLog(params);
- DEBUGLOG(4, "overlapLog=%u => %u KB", params.overlapSizeLog, (U32)(mtctx->targetPrefixSize>>10));
+ mtctx->targetPrefixSize = ZSTDMT_computeOverlapSize(params);
+ DEBUGLOG(4, "overlapLog=%i => %u KB", params.overlapLog, (U32)(mtctx->targetPrefixSize>>10));
mtctx->targetSectionSize = params.jobSize;
- if (mtctx->targetSectionSize < ZSTDMT_JOBSIZE_MIN) mtctx->targetSectionSize = ZSTDMT_JOBSIZE_MIN;
+ if (mtctx->targetSectionSize == 0) {
+ mtctx->targetSectionSize = 1ULL << ZSTDMT_computeTargetJobLog(params);
+ }
+ if (params.rsyncable) {
+ /* Aim for the targetsectionSize as the average job size. */
+ U32 const jobSizeMB = (U32)(mtctx->targetSectionSize >> 20);
+ U32 const rsyncBits = ZSTD_highbit32(jobSizeMB) + 20;
+ assert(jobSizeMB >= 1);
+ DEBUGLOG(4, "rsyncLog = %u", rsyncBits);
+ mtctx->rsync.hash = 0;
+ mtctx->rsync.hitMask = (1ULL << rsyncBits) - 1;
+ mtctx->rsync.primePower = ZSTD_rollingHash_primePower(RSYNC_LENGTH);
+ }
if (mtctx->targetSectionSize < mtctx->targetPrefixSize) mtctx->targetSectionSize = mtctx->targetPrefixSize; /* job size must be >= overlap size */
- DEBUGLOG(4, "Job Size : %u KB (note : set to %u)", (U32)(mtctx->targetSectionSize>>10), params.jobSize);
+ DEBUGLOG(4, "Job Size : %u KB (note : set to %u)", (U32)(mtctx->targetSectionSize>>10), (U32)params.jobSize);
DEBUGLOG(4, "inBuff Size : %u KB", (U32)(mtctx->targetSectionSize>>10));
ZSTDMT_setBufferSize(mtctx->bufPool, ZSTD_compressBound(mtctx->targetSectionSize));
{
@@ -1312,7 +1483,7 @@ size_t ZSTDMT_initCStream_internal(
mtctx->allJobsCompleted = 0;
mtctx->consumed = 0;
mtctx->produced = 0;
- if (ZSTDMT_serialState_reset(&mtctx->serial, mtctx->seqPool, params))
+ if (ZSTDMT_serialState_reset(&mtctx->serial, mtctx->seqPool, params, mtctx->targetSectionSize))
return ERROR(memory_allocation);
return 0;
}
@@ -1368,7 +1539,7 @@ size_t ZSTDMT_initCStream(ZSTDMT_CCtx* mtctx, int compressionLevel) {
/* ZSTDMT_writeLastEmptyBlock()
* Write a single empty block with an end-of-frame to finish a frame.
* Job must be created from streaming variant.
- * This function is always successfull if expected conditions are fulfilled.
+ * This function is always successful if expected conditions are fulfilled.
*/
static void ZSTDMT_writeLastEmptyBlock(ZSTDMT_jobDescription* job)
{
@@ -1420,7 +1591,7 @@ static size_t ZSTDMT_createCompressionJob(ZSTDMT_CCtx* mtctx, size_t srcSize, ZS
mtctx->jobs[jobID].jobID = mtctx->nextJobID;
mtctx->jobs[jobID].firstJob = (mtctx->nextJobID==0);
mtctx->jobs[jobID].lastJob = endFrame;
- mtctx->jobs[jobID].frameChecksumNeeded = endFrame && (mtctx->nextJobID>0) && mtctx->params.fParams.checksumFlag;
+ mtctx->jobs[jobID].frameChecksumNeeded = mtctx->params.fParams.checksumFlag && endFrame && (mtctx->nextJobID>0);
mtctx->jobs[jobID].dstFlushed = 0;
/* Update the round buffer pos and clear the input buffer to be reset */
@@ -1468,6 +1639,8 @@ static size_t ZSTDMT_createCompressionJob(ZSTDMT_CCtx* mtctx, size_t srcSize, ZS
/*! ZSTDMT_flushProduced() :
+ * flush whatever data has been produced but not yet flushed in current job.
+ * move to next job if current one is fully flushed.
* `output` : `pos` will be updated with amount of data flushed .
* `blockToFlush` : if >0, the function will block and wait if there is no data available to flush .
* @return : amount of data remaining within internal buffer, 0 if no more, 1 if unknown but > 0, or an error code */
@@ -1496,7 +1669,7 @@ static size_t ZSTDMT_flushProduced(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, u
/* try to flush something */
{ size_t cSize = mtctx->jobs[wJobID].cSize; /* shared */
size_t const srcConsumed = mtctx->jobs[wJobID].consumed; /* shared */
- size_t const srcSize = mtctx->jobs[wJobID].src.size; /* read-only, could be done after mutex lock, but no-declaration-after-statement */
+ size_t const srcSize = mtctx->jobs[wJobID].src.size; /* read-only, could be done after mutex lock, but no-declaration-after-statement */
ZSTD_pthread_mutex_unlock(&mtctx->jobs[wJobID].job_mutex);
if (ZSTD_isError(cSize)) {
DEBUGLOG(5, "ZSTDMT_flushProduced: job %u : compression error detected : %s",
@@ -1516,6 +1689,7 @@ static size_t ZSTDMT_flushProduced(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, u
mtctx->jobs[wJobID].cSize += 4; /* can write this shared value, as worker is no longer active */
mtctx->jobs[wJobID].frameChecksumNeeded = 0;
}
+
if (cSize > 0) { /* compression is ongoing or completed */
size_t const toFlush = MIN(cSize - mtctx->jobs[wJobID].dstFlushed, output->size - output->pos);
DEBUGLOG(5, "ZSTDMT_flushProduced: Flushing %u bytes from job %u (completion:%u/%u, generated:%u)",
@@ -1529,11 +1703,12 @@ static size_t ZSTDMT_flushProduced(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, u
output->pos += toFlush;
mtctx->jobs[wJobID].dstFlushed += toFlush; /* can write : this value is only used by mtctx */
- if ( (srcConsumed == srcSize) /* job completed */
+ if ( (srcConsumed == srcSize) /* job is completed */
&& (mtctx->jobs[wJobID].dstFlushed == cSize) ) { /* output buffer fully flushed => free this job position */
DEBUGLOG(5, "Job %u completed (%u bytes), moving to next one",
mtctx->doneJobID, (U32)mtctx->jobs[wJobID].dstFlushed);
ZSTDMT_releaseBuffer(mtctx->bufPool, mtctx->jobs[wJobID].dstBuff);
+ DEBUGLOG(5, "dstBuffer released");
mtctx->jobs[wJobID].dstBuff = g_nullBuffer;
mtctx->jobs[wJobID].cSize = 0; /* ensure this job slot is considered "not started" in future check */
mtctx->consumed += srcSize;
@@ -1610,6 +1785,7 @@ static int ZSTDMT_doesOverlapWindow(buffer_t buffer, ZSTD_window_t window)
range_t extDict;
range_t prefix;
+ DEBUGLOG(5, "ZSTDMT_doesOverlapWindow");
extDict.start = window.dictBase + window.lowLimit;
extDict.size = window.dictLimit - window.lowLimit;
@@ -1630,12 +1806,13 @@ static void ZSTDMT_waitForLdmComplete(ZSTDMT_CCtx* mtctx, buffer_t buffer)
{
if (mtctx->params.ldmParams.enableLdm) {
ZSTD_pthread_mutex_t* mutex = &mtctx->serial.ldmWindowMutex;
+ DEBUGLOG(5, "ZSTDMT_waitForLdmComplete");
DEBUGLOG(5, "source [0x%zx, 0x%zx)",
(size_t)buffer.start,
(size_t)buffer.start + buffer.capacity);
ZSTD_PTHREAD_MUTEX_LOCK(mutex);
while (ZSTDMT_doesOverlapWindow(buffer, mtctx->serial.ldmWindow)) {
- DEBUGLOG(6, "Waiting for LDM to finish...");
+ DEBUGLOG(5, "Waiting for LDM to finish...");
ZSTD_pthread_cond_wait(&mtctx->serial.ldmWindowCond, mutex);
}
DEBUGLOG(6, "Done waiting for LDM to finish");
@@ -1655,6 +1832,7 @@ static int ZSTDMT_tryGetInputRange(ZSTDMT_CCtx* mtctx)
size_t const target = mtctx->targetSectionSize;
buffer_t buffer;
+ DEBUGLOG(5, "ZSTDMT_tryGetInputRange");
assert(mtctx->inBuff.buffer.start == NULL);
assert(mtctx->roundBuff.capacity >= target);
@@ -1668,7 +1846,7 @@ static int ZSTDMT_tryGetInputRange(ZSTDMT_CCtx* mtctx)
buffer.start = start;
buffer.capacity = prefixSize;
if (ZSTDMT_isOverlapped(buffer, inUse)) {
- DEBUGLOG(6, "Waiting for buffer...");
+ DEBUGLOG(5, "Waiting for buffer...");
return 0;
}
ZSTDMT_waitForLdmComplete(mtctx, buffer);
@@ -1680,7 +1858,7 @@ static int ZSTDMT_tryGetInputRange(ZSTDMT_CCtx* mtctx)
buffer.capacity = target;
if (ZSTDMT_isOverlapped(buffer, inUse)) {
- DEBUGLOG(6, "Waiting for buffer...");
+ DEBUGLOG(5, "Waiting for buffer...");
return 0;
}
assert(!ZSTDMT_isOverlapped(buffer, mtctx->inBuff.prefix));
@@ -1701,6 +1879,89 @@ static int ZSTDMT_tryGetInputRange(ZSTDMT_CCtx* mtctx)
return 1;
}
+typedef struct {
+ size_t toLoad; /* The number of bytes to load from the input. */
+ int flush; /* Boolean declaring if we must flush because we found a synchronization point. */
+} syncPoint_t;
+
+/**
+ * Searches through the input for a synchronization point. If one is found, we
+ * will instruct the caller to flush, and return the number of bytes to load.
+ * Otherwise, we will load as many bytes as possible and instruct the caller
+ * to continue as normal.
+ */
+static syncPoint_t
+findSynchronizationPoint(ZSTDMT_CCtx const* mtctx, ZSTD_inBuffer const input)
+{
+ BYTE const* const istart = (BYTE const*)input.src + input.pos;
+ U64 const primePower = mtctx->rsync.primePower;
+ U64 const hitMask = mtctx->rsync.hitMask;
+
+ syncPoint_t syncPoint;
+ U64 hash;
+ BYTE const* prev;
+ size_t pos;
+
+ syncPoint.toLoad = MIN(input.size - input.pos, mtctx->targetSectionSize - mtctx->inBuff.filled);
+ syncPoint.flush = 0;
+ if (!mtctx->params.rsyncable)
+ /* Rsync is disabled. */
+ return syncPoint;
+ if (mtctx->inBuff.filled + syncPoint.toLoad < RSYNC_LENGTH)
+ /* Not enough to compute the hash.
+ * We will miss any synchronization points in this RSYNC_LENGTH byte
+ * window. However, since it depends only in the internal buffers, if the
+ * state is already synchronized, we will remain synchronized.
+ * Additionally, the probability that we miss a synchronization point is
+ * low: RSYNC_LENGTH / targetSectionSize.
+ */
+ return syncPoint;
+ /* Initialize the loop variables. */
+ if (mtctx->inBuff.filled >= RSYNC_LENGTH) {
+ /* We have enough bytes buffered to initialize the hash.
+ * Start scanning at the beginning of the input.
+ */
+ pos = 0;
+ prev = (BYTE const*)mtctx->inBuff.buffer.start + mtctx->inBuff.filled - RSYNC_LENGTH;
+ hash = ZSTD_rollingHash_compute(prev, RSYNC_LENGTH);
+ } else {
+ /* We don't have enough bytes buffered to initialize the hash, but
+ * we know we have at least RSYNC_LENGTH bytes total.
+ * Start scanning after the first RSYNC_LENGTH bytes less the bytes
+ * already buffered.
+ */
+ pos = RSYNC_LENGTH - mtctx->inBuff.filled;
+ prev = (BYTE const*)mtctx->inBuff.buffer.start - pos;
+ hash = ZSTD_rollingHash_compute(mtctx->inBuff.buffer.start, mtctx->inBuff.filled);
+ hash = ZSTD_rollingHash_append(hash, istart, pos);
+ }
+ /* Starting with the hash of the previous RSYNC_LENGTH bytes, roll
+ * through the input. If we hit a synchronization point, then cut the
+ * job off, and tell the compressor to flush the job. Otherwise, load
+ * all the bytes and continue as normal.
+ * If we go too long without a synchronization point (targetSectionSize)
+ * then a block will be emitted anyways, but this is okay, since if we
+ * are already synchronized we will remain synchronized.
+ */
+ for (; pos < syncPoint.toLoad; ++pos) {
+ BYTE const toRemove = pos < RSYNC_LENGTH ? prev[pos] : istart[pos - RSYNC_LENGTH];
+ /* if (pos >= RSYNC_LENGTH) assert(ZSTD_rollingHash_compute(istart + pos - RSYNC_LENGTH, RSYNC_LENGTH) == hash); */
+ hash = ZSTD_rollingHash_rotate(hash, toRemove, istart[pos], primePower);
+ if ((hash & hitMask) == hitMask) {
+ syncPoint.toLoad = pos + 1;
+ syncPoint.flush = 1;
+ break;
+ }
+ }
+ return syncPoint;
+}
+
+size_t ZSTDMT_nextInputSizeHint(const ZSTDMT_CCtx* mtctx)
+{
+ size_t hintInSize = mtctx->targetSectionSize - mtctx->inBuff.filled;
+ if (hintInSize==0) hintInSize = mtctx->targetSectionSize;
+ return hintInSize;
+}
/** ZSTDMT_compressStream_generic() :
* internal use only - exposed to be invoked from zstd_compress.c
@@ -1718,7 +1979,7 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
assert(input->pos <= input->size);
if (mtctx->singleBlockingThread) { /* delegate to single-thread (synchronous) */
- return ZSTD_compressStream_generic(mtctx->cctxPool->cctx[0], output, input, endOp);
+ return ZSTD_compressStream2(mtctx->cctxPool->cctx[0], output, input, endOp);
}
if ((mtctx->frameEnded) && (endOp==ZSTD_e_continue)) {
@@ -1727,7 +1988,8 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
}
/* single-pass shortcut (note : synchronous-mode) */
- if ( (mtctx->nextJobID == 0) /* just started */
+ if ( (!mtctx->params.rsyncable) /* rsyncable mode is disabled */
+ && (mtctx->nextJobID == 0) /* just started */
&& (mtctx->inBuff.filled == 0) /* nothing buffered */
&& (!mtctx->jobReady) /* no job already created */
&& (endOp == ZSTD_e_end) /* end order */
@@ -1753,18 +2015,23 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
/* It is only possible for this operation to fail if there are
* still compression jobs ongoing.
*/
+ DEBUGLOG(5, "ZSTDMT_tryGetInputRange failed");
assert(mtctx->doneJobID != mtctx->nextJobID);
- }
+ } else
+ DEBUGLOG(5, "ZSTDMT_tryGetInputRange completed successfully : mtctx->inBuff.buffer.start = %p", mtctx->inBuff.buffer.start);
}
if (mtctx->inBuff.buffer.start != NULL) {
- size_t const toLoad = MIN(input->size - input->pos, mtctx->targetSectionSize - mtctx->inBuff.filled);
+ syncPoint_t const syncPoint = findSynchronizationPoint(mtctx, *input);
+ if (syncPoint.flush && endOp == ZSTD_e_continue) {
+ endOp = ZSTD_e_flush;
+ }
assert(mtctx->inBuff.buffer.capacity >= mtctx->targetSectionSize);
DEBUGLOG(5, "ZSTDMT_compressStream_generic: adding %u bytes on top of %u to buffer of size %u",
- (U32)toLoad, (U32)mtctx->inBuff.filled, (U32)mtctx->targetSectionSize);
- memcpy((char*)mtctx->inBuff.buffer.start + mtctx->inBuff.filled, (const char*)input->src + input->pos, toLoad);
- input->pos += toLoad;
- mtctx->inBuff.filled += toLoad;
- forwardInputProgress = toLoad>0;
+ (U32)syncPoint.toLoad, (U32)mtctx->inBuff.filled, (U32)mtctx->targetSectionSize);
+ memcpy((char*)mtctx->inBuff.buffer.start + mtctx->inBuff.filled, (const char*)input->src + input->pos, syncPoint.toLoad);
+ input->pos += syncPoint.toLoad;
+ mtctx->inBuff.filled += syncPoint.toLoad;
+ forwardInputProgress = syncPoint.toLoad>0;
}
if ((input->pos < input->size) && (endOp == ZSTD_e_end))
endOp = ZSTD_e_flush; /* can't end now : not all input consumed */
@@ -1776,12 +2043,13 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
|| ((endOp == ZSTD_e_end) && (!mtctx->frameEnded)) ) { /* must finish the frame with a zero-size block */
size_t const jobSize = mtctx->inBuff.filled;
assert(mtctx->inBuff.filled <= mtctx->targetSectionSize);
- CHECK_F( ZSTDMT_createCompressionJob(mtctx, jobSize, endOp) );
+ FORWARD_IF_ERROR( ZSTDMT_createCompressionJob(mtctx, jobSize, endOp) );
}
/* check for potential compressed data ready to be flushed */
{ size_t const remainingToFlush = ZSTDMT_flushProduced(mtctx, output, !forwardInputProgress, endOp); /* block if there was no forward input progress */
if (input->pos < input->size) return MAX(remainingToFlush, 1); /* input not consumed : do not end flush yet */
+ DEBUGLOG(5, "end of ZSTDMT_compressStream_generic: remainingToFlush = %u", (U32)remainingToFlush);
return remainingToFlush;
}
}
@@ -1789,7 +2057,7 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
size_t ZSTDMT_compressStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
{
- CHECK_F( ZSTDMT_compressStream_generic(mtctx, output, input, ZSTD_e_continue) );
+ FORWARD_IF_ERROR( ZSTDMT_compressStream_generic(mtctx, output, input, ZSTD_e_continue) );
/* recommended next input size : fill current input buffer */
return mtctx->targetSectionSize - mtctx->inBuff.filled; /* note : could be zero when input buffer is fully filled and no more availability to create new job */
@@ -1806,7 +2074,7 @@ static size_t ZSTDMT_flushStream_internal(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* ou
|| ((endFrame==ZSTD_e_end) && !mtctx->frameEnded)) { /* need a last 0-size block to end frame */
DEBUGLOG(5, "ZSTDMT_flushStream_internal : create a new job (%u bytes, end:%u)",
(U32)srcSize, (U32)endFrame);
- CHECK_F( ZSTDMT_createCompressionJob(mtctx, srcSize, endFrame) );
+ FORWARD_IF_ERROR( ZSTDMT_createCompressionJob(mtctx, srcSize, endFrame) );
}
/* check if there is any data available to flush */
diff --git a/thirdparty/zstd/compress/zstdmt_compress.h b/thirdparty/zstd/compress/zstdmt_compress.h
index f79e3b4418..12e6bcb3a3 100644
--- a/thirdparty/zstd/compress/zstdmt_compress.h
+++ b/thirdparty/zstd/compress/zstdmt_compress.h
@@ -17,10 +17,25 @@
/* Note : This is an internal API.
- * Some methods are still exposed (ZSTDLIB_API),
+ * These APIs used to be exposed with ZSTDLIB_API,
* because it used to be the only way to invoke MT compression.
- * Now, it's recommended to use ZSTD_compress_generic() instead.
- * These methods will stop being exposed in a future version */
+ * Now, it's recommended to use ZSTD_compress2 and ZSTD_compressStream2()
+ * instead.
+ *
+ * If you depend on these APIs and can't switch, then define
+ * ZSTD_LEGACY_MULTITHREADED_API when making the dynamic library.
+ * However, we may completely remove these functions in a future
+ * release, so please switch soon.
+ *
+ * This API requires ZSTD_MULTITHREAD to be defined during compilation,
+ * otherwise ZSTDMT_createCCtx*() will fail.
+ */
+
+#ifdef ZSTD_LEGACY_MULTITHREADED_API
+# define ZSTDMT_API ZSTDLIB_API
+#else
+# define ZSTDMT_API
+#endif
/* === Dependencies === */
#include <stddef.h> /* size_t */
@@ -28,19 +43,31 @@
#include "zstd.h" /* ZSTD_inBuffer, ZSTD_outBuffer, ZSTDLIB_API */
+/* === Constants === */
+#ifndef ZSTDMT_NBWORKERS_MAX
+# define ZSTDMT_NBWORKERS_MAX 200
+#endif
+#ifndef ZSTDMT_JOBSIZE_MIN
+# define ZSTDMT_JOBSIZE_MIN (1 MB)
+#endif
+#define ZSTDMT_JOBSIZE_MAX (MEM_32bits() ? (512 MB) : (1024 MB))
+
+
/* === Memory management === */
typedef struct ZSTDMT_CCtx_s ZSTDMT_CCtx;
-ZSTDLIB_API ZSTDMT_CCtx* ZSTDMT_createCCtx(unsigned nbWorkers);
-ZSTDLIB_API ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers,
+/* Requires ZSTD_MULTITHREAD to be defined during compilation, otherwise it will return NULL. */
+ZSTDMT_API ZSTDMT_CCtx* ZSTDMT_createCCtx(unsigned nbWorkers);
+/* Requires ZSTD_MULTITHREAD to be defined during compilation, otherwise it will return NULL. */
+ZSTDMT_API ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers,
ZSTD_customMem cMem);
-ZSTDLIB_API size_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx);
+ZSTDMT_API size_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx);
-ZSTDLIB_API size_t ZSTDMT_sizeof_CCtx(ZSTDMT_CCtx* mtctx);
+ZSTDMT_API size_t ZSTDMT_sizeof_CCtx(ZSTDMT_CCtx* mtctx);
/* === Simple one-pass compression function === */
-ZSTDLIB_API size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
+ZSTDMT_API size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
int compressionLevel);
@@ -49,34 +76,31 @@ ZSTDLIB_API size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
/* === Streaming functions === */
-ZSTDLIB_API size_t ZSTDMT_initCStream(ZSTDMT_CCtx* mtctx, int compressionLevel);
-ZSTDLIB_API size_t ZSTDMT_resetCStream(ZSTDMT_CCtx* mtctx, unsigned long long pledgedSrcSize); /**< if srcSize is not known at reset time, use ZSTD_CONTENTSIZE_UNKNOWN. Note: for compatibility with older programs, 0 means the same as ZSTD_CONTENTSIZE_UNKNOWN, but it will change in the future to mean "empty" */
+ZSTDMT_API size_t ZSTDMT_initCStream(ZSTDMT_CCtx* mtctx, int compressionLevel);
+ZSTDMT_API size_t ZSTDMT_resetCStream(ZSTDMT_CCtx* mtctx, unsigned long long pledgedSrcSize); /**< if srcSize is not known at reset time, use ZSTD_CONTENTSIZE_UNKNOWN. Note: for compatibility with older programs, 0 means the same as ZSTD_CONTENTSIZE_UNKNOWN, but it will change in the future to mean "empty" */
-ZSTDLIB_API size_t ZSTDMT_compressStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
+ZSTDMT_API size_t ZSTDMT_nextInputSizeHint(const ZSTDMT_CCtx* mtctx);
+ZSTDMT_API size_t ZSTDMT_compressStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
-ZSTDLIB_API size_t ZSTDMT_flushStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output); /**< @return : 0 == all flushed; >0 : still some data to be flushed; or an error code (ZSTD_isError()) */
-ZSTDLIB_API size_t ZSTDMT_endStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output); /**< @return : 0 == all flushed; >0 : still some data to be flushed; or an error code (ZSTD_isError()) */
+ZSTDMT_API size_t ZSTDMT_flushStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output); /**< @return : 0 == all flushed; >0 : still some data to be flushed; or an error code (ZSTD_isError()) */
+ZSTDMT_API size_t ZSTDMT_endStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output); /**< @return : 0 == all flushed; >0 : still some data to be flushed; or an error code (ZSTD_isError()) */
/* === Advanced functions and parameters === */
-#ifndef ZSTDMT_JOBSIZE_MIN
-# define ZSTDMT_JOBSIZE_MIN (1U << 20) /* 1 MB - Minimum size of each compression job */
-#endif
-
-ZSTDLIB_API size_t ZSTDMT_compress_advanced(ZSTDMT_CCtx* mtctx,
- void* dst, size_t dstCapacity,
- const void* src, size_t srcSize,
- const ZSTD_CDict* cdict,
- ZSTD_parameters params,
- unsigned overlapLog);
+ZSTDMT_API size_t ZSTDMT_compress_advanced(ZSTDMT_CCtx* mtctx,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize,
+ const ZSTD_CDict* cdict,
+ ZSTD_parameters params,
+ int overlapLog);
-ZSTDLIB_API size_t ZSTDMT_initCStream_advanced(ZSTDMT_CCtx* mtctx,
+ZSTDMT_API size_t ZSTDMT_initCStream_advanced(ZSTDMT_CCtx* mtctx,
const void* dict, size_t dictSize, /* dict can be released after init, a local copy is preserved within zcs */
ZSTD_parameters params,
unsigned long long pledgedSrcSize); /* pledgedSrcSize is optional and can be zero == unknown */
-ZSTDLIB_API size_t ZSTDMT_initCStream_usingCDict(ZSTDMT_CCtx* mtctx,
+ZSTDMT_API size_t ZSTDMT_initCStream_usingCDict(ZSTDMT_CCtx* mtctx,
const ZSTD_CDict* cdict,
ZSTD_frameParameters fparams,
unsigned long long pledgedSrcSize); /* note : zero means empty */
@@ -84,8 +108,9 @@ ZSTDLIB_API size_t ZSTDMT_initCStream_usingCDict(ZSTDMT_CCtx* mtctx,
/* ZSTDMT_parameter :
* List of parameters that can be set using ZSTDMT_setMTCtxParameter() */
typedef enum {
- ZSTDMT_p_jobSize, /* Each job is compressed in parallel. By default, this value is dynamically determined depending on compression parameters. Can be set explicitly here. */
- ZSTDMT_p_overlapSectionLog /* Each job may reload a part of previous job to enhance compressionr ratio; 0 == no overlap, 6(default) == use 1/8th of window, >=9 == use full window. This is a "sticky" parameter : its value will be re-used on next compression job */
+ ZSTDMT_p_jobSize, /* Each job is compressed in parallel. By default, this value is dynamically determined depending on compression parameters. Can be set explicitly here. */
+ ZSTDMT_p_overlapLog, /* Each job may reload a part of previous job to enhance compression ratio; 0 == no overlap, 6(default) == use 1/8th of window, >=9 == use full window. This is a "sticky" parameter : its value will be re-used on next compression job */
+ ZSTDMT_p_rsyncable /* Enables rsyncable mode. */
} ZSTDMT_parameter;
/* ZSTDMT_setMTCtxParameter() :
@@ -93,7 +118,12 @@ typedef enum {
* The function must be called typically after ZSTD_createCCtx() but __before ZSTDMT_init*() !__
* Parameters not explicitly reset by ZSTDMT_init*() remain the same in consecutive compression sessions.
* @return : 0, or an error code (which can be tested using ZSTD_isError()) */
-ZSTDLIB_API size_t ZSTDMT_setMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, unsigned value);
+ZSTDMT_API size_t ZSTDMT_setMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, int value);
+
+/* ZSTDMT_getMTCtxParameter() :
+ * Query the ZSTDMT_CCtx for a parameter value.
+ * @return : 0, or an error code (which can be tested using ZSTD_isError()) */
+ZSTDMT_API size_t ZSTDMT_getMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, int* value);
/*! ZSTDMT_compressStream_generic() :
@@ -103,7 +133,7 @@ ZSTDLIB_API size_t ZSTDMT_setMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter
* 0 if fully flushed
* or an error code
* note : needs to be init using any ZSTD_initCStream*() variant */
-ZSTDLIB_API size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
+ZSTDMT_API size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
ZSTD_outBuffer* output,
ZSTD_inBuffer* input,
ZSTD_EndDirective endOp);
@@ -114,11 +144,21 @@ ZSTDLIB_API size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
* === Not exposed in libzstd. Never invoke directly ===
* ======================================================== */
-size_t ZSTDMT_CCtxParam_setMTCtxParameter(ZSTD_CCtx_params* params, ZSTDMT_parameter parameter, unsigned value);
-
-/* ZSTDMT_CCtxParam_setNbWorkers()
- * Set nbWorkers, and clamp it.
- * Also reset jobSize and overlapLog */
+ /*! ZSTDMT_toFlushNow()
+ * Tell how many bytes are ready to be flushed immediately.
+ * Probe the oldest active job (not yet entirely flushed) and check its output buffer.
+ * If return 0, it means there is no active job,
+ * or, it means oldest job is still active, but everything produced has been flushed so far,
+ * therefore flushing is limited by speed of oldest job. */
+size_t ZSTDMT_toFlushNow(ZSTDMT_CCtx* mtctx);
+
+/*! ZSTDMT_CCtxParam_setMTCtxParameter()
+ * like ZSTDMT_setMTCtxParameter(), but into a ZSTD_CCtx_Params */
+size_t ZSTDMT_CCtxParam_setMTCtxParameter(ZSTD_CCtx_params* params, ZSTDMT_parameter parameter, int value);
+
+/*! ZSTDMT_CCtxParam_setNbWorkers()
+ * Set nbWorkers, and clamp it.
+ * Also reset jobSize and overlapLog */
size_t ZSTDMT_CCtxParam_setNbWorkers(ZSTD_CCtx_params* params, unsigned nbWorkers);
/*! ZSTDMT_updateCParams_whileCompressing() :
@@ -126,14 +166,9 @@ size_t ZSTDMT_CCtxParam_setNbWorkers(ZSTD_CCtx_params* params, unsigned nbWorker
* New parameters will be applied to next compression job. */
void ZSTDMT_updateCParams_whileCompressing(ZSTDMT_CCtx* mtctx, const ZSTD_CCtx_params* cctxParams);
-/* ZSTDMT_getNbWorkers():
- * @return nb threads currently active in mtctx.
- * mtctx must be valid */
-unsigned ZSTDMT_getNbWorkers(const ZSTDMT_CCtx* mtctx);
-
-/* ZSTDMT_getFrameProgression():
- * tells how much data has been consumed (input) and produced (output) for current frame.
- * able to count progression inside worker threads.
+/*! ZSTDMT_getFrameProgression():
+ * tells how much data has been consumed (input) and produced (output) for current frame.
+ * able to count progression inside worker threads.
*/
ZSTD_frameProgression ZSTDMT_getFrameProgression(ZSTDMT_CCtx* mtctx);
diff --git a/thirdparty/zstd/decompress/huf_decompress.c b/thirdparty/zstd/decompress/huf_decompress.c
index 73f5c46c06..3f8bd29732 100644
--- a/thirdparty/zstd/decompress/huf_decompress.c
+++ b/thirdparty/zstd/decompress/huf_decompress.c
@@ -1,6 +1,7 @@
/* ******************************************************************
- Huffman decoder, part of New Generation Entropy library
- Copyright (C) 2013-2016, Yann Collet.
+ huff0 huffman decoder,
+ part of Finite State Entropy library
+ Copyright (C) 2013-present, Yann Collet.
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
@@ -29,26 +30,37 @@
You can contact the author at :
- FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy
- - Public forum : https://groups.google.com/forum/#!forum/lz4c
****************************************************************** */
/* **************************************************************
* Dependencies
****************************************************************/
#include <string.h> /* memcpy, memset */
-#include "bitstream.h" /* BIT_* */
#include "compiler.h"
-#include "fse.h" /* header compression */
+#include "bitstream.h" /* BIT_* */
+#include "fse.h" /* to compress headers */
#define HUF_STATIC_LINKING_ONLY
#include "huf.h"
#include "error_private.h"
+/* **************************************************************
+* Macros
+****************************************************************/
+
+/* These two optional macros force the use one way or another of the two
+ * Huffman decompression implementations. You can't force in both directions
+ * at the same time.
+ */
+#if defined(HUF_FORCE_DECOMPRESS_X1) && \
+ defined(HUF_FORCE_DECOMPRESS_X2)
+#error "Cannot force the use of the X1 and X2 decoders at the same time!"
+#endif
+
/* **************************************************************
* Error Management
****************************************************************/
#define HUF_isError ERR_isError
-#define HUF_STATIC_ASSERT(c) { enum { HUF_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */
#define CHECK_F(f) { size_t const err_ = (f); if (HUF_isError(err_)) return err_; }
@@ -59,6 +71,51 @@
#define HUF_ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))
+/* **************************************************************
+* BMI2 Variant Wrappers
+****************************************************************/
+#if DYNAMIC_BMI2
+
+#define HUF_DGEN(fn) \
+ \
+ static size_t fn##_default( \
+ void* dst, size_t dstSize, \
+ const void* cSrc, size_t cSrcSize, \
+ const HUF_DTable* DTable) \
+ { \
+ return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable); \
+ } \
+ \
+ static TARGET_ATTRIBUTE("bmi2") size_t fn##_bmi2( \
+ void* dst, size_t dstSize, \
+ const void* cSrc, size_t cSrcSize, \
+ const HUF_DTable* DTable) \
+ { \
+ return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable); \
+ } \
+ \
+ static size_t fn(void* dst, size_t dstSize, void const* cSrc, \
+ size_t cSrcSize, HUF_DTable const* DTable, int bmi2) \
+ { \
+ if (bmi2) { \
+ return fn##_bmi2(dst, dstSize, cSrc, cSrcSize, DTable); \
+ } \
+ return fn##_default(dst, dstSize, cSrc, cSrcSize, DTable); \
+ }
+
+#else
+
+#define HUF_DGEN(fn) \
+ static size_t fn(void* dst, size_t dstSize, void const* cSrc, \
+ size_t cSrcSize, HUF_DTable const* DTable, int bmi2) \
+ { \
+ (void)bmi2; \
+ return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable); \
+ }
+
+#endif
+
+
/*-***************************/
/* generic DTableDesc */
/*-***************************/
@@ -72,18 +129,20 @@ static DTableDesc HUF_getDTableDesc(const HUF_DTable* table)
}
+#ifndef HUF_FORCE_DECOMPRESS_X2
+
/*-***************************/
/* single-symbol decoding */
/*-***************************/
-typedef struct { BYTE byte; BYTE nbBits; } HUF_DEltX2; /* single-symbol decoding */
+typedef struct { BYTE byte; BYTE nbBits; } HUF_DEltX1; /* single-symbol decoding */
-size_t HUF_readDTableX2_wksp(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize)
+size_t HUF_readDTableX1_wksp(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize)
{
U32 tableLog = 0;
U32 nbSymbols = 0;
size_t iSize;
void* const dtPtr = DTable + 1;
- HUF_DEltX2* const dt = (HUF_DEltX2*)dtPtr;
+ HUF_DEltX1* const dt = (HUF_DEltX1*)dtPtr;
U32* rankVal;
BYTE* huffWeight;
@@ -96,7 +155,7 @@ size_t HUF_readDTableX2_wksp(HUF_DTable* DTable, const void* src, size_t srcSize
if ((spaceUsed32 << 2) > wkspSize) return ERROR(tableLog_tooLarge);
- HUF_STATIC_ASSERT(sizeof(DTableDesc) == sizeof(HUF_DTable));
+ DEBUG_STATIC_ASSERT(sizeof(DTableDesc) == sizeof(HUF_DTable));
/* memset(huffWeight, 0, sizeof(huffWeight)); */ /* is not necessary, even though some analyzer complain ... */
iSize = HUF_readStats(huffWeight, HUF_SYMBOLVALUE_MAX + 1, rankVal, &nbSymbols, &tableLog, src, srcSize);
@@ -124,7 +183,7 @@ size_t HUF_readDTableX2_wksp(HUF_DTable* DTable, const void* src, size_t srcSize
U32 const w = huffWeight[n];
U32 const length = (1 << w) >> 1;
U32 u;
- HUF_DEltX2 D;
+ HUF_DEltX1 D;
D.byte = (BYTE)n; D.nbBits = (BYTE)(tableLog + 1 - w);
for (u = rankVal[w]; u < rankVal[w] + length; u++)
dt[u] = D;
@@ -134,17 +193,15 @@ size_t HUF_readDTableX2_wksp(HUF_DTable* DTable, const void* src, size_t srcSize
return iSize;
}
-size_t HUF_readDTableX2(HUF_DTable* DTable, const void* src, size_t srcSize)
+size_t HUF_readDTableX1(HUF_DTable* DTable, const void* src, size_t srcSize)
{
U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
- return HUF_readDTableX2_wksp(DTable, src, srcSize,
+ return HUF_readDTableX1_wksp(DTable, src, srcSize,
workSpace, sizeof(workSpace));
}
-typedef struct { U16 sequence; BYTE nbBits; BYTE length; } HUF_DEltX4; /* double-symbols decoding */
-
FORCE_INLINE_TEMPLATE BYTE
-HUF_decodeSymbolX2(BIT_DStream_t* Dstream, const HUF_DEltX2* dt, const U32 dtLog)
+HUF_decodeSymbolX1(BIT_DStream_t* Dstream, const HUF_DEltX1* dt, const U32 dtLog)
{
size_t const val = BIT_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */
BYTE const c = dt[val].byte;
@@ -152,44 +209,44 @@ HUF_decodeSymbolX2(BIT_DStream_t* Dstream, const HUF_DEltX2* dt, const U32 dtLog
return c;
}
-#define HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \
- *ptr++ = HUF_decodeSymbolX2(DStreamPtr, dt, dtLog)
+#define HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr) \
+ *ptr++ = HUF_decodeSymbolX1(DStreamPtr, dt, dtLog)
-#define HUF_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \
+#define HUF_DECODE_SYMBOLX1_1(ptr, DStreamPtr) \
if (MEM_64bits() || (HUF_TABLELOG_MAX<=12)) \
- HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr)
+ HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr)
-#define HUF_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \
+#define HUF_DECODE_SYMBOLX1_2(ptr, DStreamPtr) \
if (MEM_64bits()) \
- HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr)
+ HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr)
HINT_INLINE size_t
-HUF_decodeStreamX2(BYTE* p, BIT_DStream_t* const bitDPtr, BYTE* const pEnd, const HUF_DEltX2* const dt, const U32 dtLog)
+HUF_decodeStreamX1(BYTE* p, BIT_DStream_t* const bitDPtr, BYTE* const pEnd, const HUF_DEltX1* const dt, const U32 dtLog)
{
BYTE* const pStart = p;
/* up to 4 symbols at a time */
while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-3)) {
- HUF_DECODE_SYMBOLX2_2(p, bitDPtr);
- HUF_DECODE_SYMBOLX2_1(p, bitDPtr);
- HUF_DECODE_SYMBOLX2_2(p, bitDPtr);
- HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
+ HUF_DECODE_SYMBOLX1_2(p, bitDPtr);
+ HUF_DECODE_SYMBOLX1_1(p, bitDPtr);
+ HUF_DECODE_SYMBOLX1_2(p, bitDPtr);
+ HUF_DECODE_SYMBOLX1_0(p, bitDPtr);
}
/* [0-3] symbols remaining */
if (MEM_32bits())
while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd))
- HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
+ HUF_DECODE_SYMBOLX1_0(p, bitDPtr);
/* no more data to retrieve from bitstream, no need to reload */
while (p < pEnd)
- HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
+ HUF_DECODE_SYMBOLX1_0(p, bitDPtr);
return pEnd-pStart;
}
FORCE_INLINE_TEMPLATE size_t
-HUF_decompress1X2_usingDTable_internal_body(
+HUF_decompress1X1_usingDTable_internal_body(
void* dst, size_t dstSize,
const void* cSrc, size_t cSrcSize,
const HUF_DTable* DTable)
@@ -197,14 +254,14 @@ HUF_decompress1X2_usingDTable_internal_body(
BYTE* op = (BYTE*)dst;
BYTE* const oend = op + dstSize;
const void* dtPtr = DTable + 1;
- const HUF_DEltX2* const dt = (const HUF_DEltX2*)dtPtr;
+ const HUF_DEltX1* const dt = (const HUF_DEltX1*)dtPtr;
BIT_DStream_t bitD;
DTableDesc const dtd = HUF_getDTableDesc(DTable);
U32 const dtLog = dtd.tableLog;
CHECK_F( BIT_initDStream(&bitD, cSrc, cSrcSize) );
- HUF_decodeStreamX2(op, &bitD, oend, dt, dtLog);
+ HUF_decodeStreamX1(op, &bitD, oend, dt, dtLog);
if (!BIT_endOfDStream(&bitD)) return ERROR(corruption_detected);
@@ -212,7 +269,7 @@ HUF_decompress1X2_usingDTable_internal_body(
}
FORCE_INLINE_TEMPLATE size_t
-HUF_decompress4X2_usingDTable_internal_body(
+HUF_decompress4X1_usingDTable_internal_body(
void* dst, size_t dstSize,
const void* cSrc, size_t cSrcSize,
const HUF_DTable* DTable)
@@ -224,7 +281,7 @@ HUF_decompress4X2_usingDTable_internal_body(
BYTE* const ostart = (BYTE*) dst;
BYTE* const oend = ostart + dstSize;
const void* const dtPtr = DTable + 1;
- const HUF_DEltX2* const dt = (const HUF_DEltX2*)dtPtr;
+ const HUF_DEltX1* const dt = (const HUF_DEltX1*)dtPtr;
/* Init */
BIT_DStream_t bitD1;
@@ -260,22 +317,22 @@ HUF_decompress4X2_usingDTable_internal_body(
/* up to 16 symbols per loop (4 symbols per stream) in 64-bit mode */
endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
while ( (endSignal==BIT_DStream_unfinished) && (op4<(oend-3)) ) {
- HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
- HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
- HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
- HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
- HUF_DECODE_SYMBOLX2_1(op1, &bitD1);
- HUF_DECODE_SYMBOLX2_1(op2, &bitD2);
- HUF_DECODE_SYMBOLX2_1(op3, &bitD3);
- HUF_DECODE_SYMBOLX2_1(op4, &bitD4);
- HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
- HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
- HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
- HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
- HUF_DECODE_SYMBOLX2_0(op1, &bitD1);
- HUF_DECODE_SYMBOLX2_0(op2, &bitD2);
- HUF_DECODE_SYMBOLX2_0(op3, &bitD3);
- HUF_DECODE_SYMBOLX2_0(op4, &bitD4);
+ HUF_DECODE_SYMBOLX1_2(op1, &bitD1);
+ HUF_DECODE_SYMBOLX1_2(op2, &bitD2);
+ HUF_DECODE_SYMBOLX1_2(op3, &bitD3);
+ HUF_DECODE_SYMBOLX1_2(op4, &bitD4);
+ HUF_DECODE_SYMBOLX1_1(op1, &bitD1);
+ HUF_DECODE_SYMBOLX1_1(op2, &bitD2);
+ HUF_DECODE_SYMBOLX1_1(op3, &bitD3);
+ HUF_DECODE_SYMBOLX1_1(op4, &bitD4);
+ HUF_DECODE_SYMBOLX1_2(op1, &bitD1);
+ HUF_DECODE_SYMBOLX1_2(op2, &bitD2);
+ HUF_DECODE_SYMBOLX1_2(op3, &bitD3);
+ HUF_DECODE_SYMBOLX1_2(op4, &bitD4);
+ HUF_DECODE_SYMBOLX1_0(op1, &bitD1);
+ HUF_DECODE_SYMBOLX1_0(op2, &bitD2);
+ HUF_DECODE_SYMBOLX1_0(op3, &bitD3);
+ HUF_DECODE_SYMBOLX1_0(op4, &bitD4);
BIT_reloadDStream(&bitD1);
BIT_reloadDStream(&bitD2);
BIT_reloadDStream(&bitD3);
@@ -291,191 +348,10 @@ HUF_decompress4X2_usingDTable_internal_body(
/* note : op4 supposed already verified within main loop */
/* finish bitStreams one by one */
- HUF_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog);
- HUF_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog);
- HUF_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog);
- HUF_decodeStreamX2(op4, &bitD4, oend, dt, dtLog);
-
- /* check */
- { U32 const endCheck = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);
- if (!endCheck) return ERROR(corruption_detected); }
-
- /* decoded size */
- return dstSize;
- }
-}
-
-
-FORCE_INLINE_TEMPLATE U32
-HUF_decodeSymbolX4(void* op, BIT_DStream_t* DStream, const HUF_DEltX4* dt, const U32 dtLog)
-{
- size_t const val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */
- memcpy(op, dt+val, 2);
- BIT_skipBits(DStream, dt[val].nbBits);
- return dt[val].length;
-}
-
-FORCE_INLINE_TEMPLATE U32
-HUF_decodeLastSymbolX4(void* op, BIT_DStream_t* DStream, const HUF_DEltX4* dt, const U32 dtLog)
-{
- size_t const val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */
- memcpy(op, dt+val, 1);
- if (dt[val].length==1) BIT_skipBits(DStream, dt[val].nbBits);
- else {
- if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8)) {
- BIT_skipBits(DStream, dt[val].nbBits);
- if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8))
- /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */
- DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8);
- } }
- return 1;
-}
-
-#define HUF_DECODE_SYMBOLX4_0(ptr, DStreamPtr) \
- ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)
-
-#define HUF_DECODE_SYMBOLX4_1(ptr, DStreamPtr) \
- if (MEM_64bits() || (HUF_TABLELOG_MAX<=12)) \
- ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)
-
-#define HUF_DECODE_SYMBOLX4_2(ptr, DStreamPtr) \
- if (MEM_64bits()) \
- ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)
-
-HINT_INLINE size_t
-HUF_decodeStreamX4(BYTE* p, BIT_DStream_t* bitDPtr, BYTE* const pEnd,
- const HUF_DEltX4* const dt, const U32 dtLog)
-{
- BYTE* const pStart = p;
-
- /* up to 8 symbols at a time */
- while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-(sizeof(bitDPtr->bitContainer)-1))) {
- HUF_DECODE_SYMBOLX4_2(p, bitDPtr);
- HUF_DECODE_SYMBOLX4_1(p, bitDPtr);
- HUF_DECODE_SYMBOLX4_2(p, bitDPtr);
- HUF_DECODE_SYMBOLX4_0(p, bitDPtr);
- }
-
- /* closer to end : up to 2 symbols at a time */
- while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p <= pEnd-2))
- HUF_DECODE_SYMBOLX4_0(p, bitDPtr);
-
- while (p <= pEnd-2)
- HUF_DECODE_SYMBOLX4_0(p, bitDPtr); /* no need to reload : reached the end of DStream */
-
- if (p < pEnd)
- p += HUF_decodeLastSymbolX4(p, bitDPtr, dt, dtLog);
-
- return p-pStart;
-}
-
-FORCE_INLINE_TEMPLATE size_t
-HUF_decompress1X4_usingDTable_internal_body(
- void* dst, size_t dstSize,
- const void* cSrc, size_t cSrcSize,
- const HUF_DTable* DTable)
-{
- BIT_DStream_t bitD;
-
- /* Init */
- CHECK_F( BIT_initDStream(&bitD, cSrc, cSrcSize) );
-
- /* decode */
- { BYTE* const ostart = (BYTE*) dst;
- BYTE* const oend = ostart + dstSize;
- const void* const dtPtr = DTable+1; /* force compiler to not use strict-aliasing */
- const HUF_DEltX4* const dt = (const HUF_DEltX4*)dtPtr;
- DTableDesc const dtd = HUF_getDTableDesc(DTable);
- HUF_decodeStreamX4(ostart, &bitD, oend, dt, dtd.tableLog);
- }
-
- /* check */
- if (!BIT_endOfDStream(&bitD)) return ERROR(corruption_detected);
-
- /* decoded size */
- return dstSize;
-}
-
-
-FORCE_INLINE_TEMPLATE size_t
-HUF_decompress4X4_usingDTable_internal_body(
- void* dst, size_t dstSize,
- const void* cSrc, size_t cSrcSize,
- const HUF_DTable* DTable)
-{
- if (cSrcSize < 10) return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */
-
- { const BYTE* const istart = (const BYTE*) cSrc;
- BYTE* const ostart = (BYTE*) dst;
- BYTE* const oend = ostart + dstSize;
- const void* const dtPtr = DTable+1;
- const HUF_DEltX4* const dt = (const HUF_DEltX4*)dtPtr;
-
- /* Init */
- BIT_DStream_t bitD1;
- BIT_DStream_t bitD2;
- BIT_DStream_t bitD3;
- BIT_DStream_t bitD4;
- size_t const length1 = MEM_readLE16(istart);
- size_t const length2 = MEM_readLE16(istart+2);
- size_t const length3 = MEM_readLE16(istart+4);
- size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);
- const BYTE* const istart1 = istart + 6; /* jumpTable */
- const BYTE* const istart2 = istart1 + length1;
- const BYTE* const istart3 = istart2 + length2;
- const BYTE* const istart4 = istart3 + length3;
- size_t const segmentSize = (dstSize+3) / 4;
- BYTE* const opStart2 = ostart + segmentSize;
- BYTE* const opStart3 = opStart2 + segmentSize;
- BYTE* const opStart4 = opStart3 + segmentSize;
- BYTE* op1 = ostart;
- BYTE* op2 = opStart2;
- BYTE* op3 = opStart3;
- BYTE* op4 = opStart4;
- U32 endSignal;
- DTableDesc const dtd = HUF_getDTableDesc(DTable);
- U32 const dtLog = dtd.tableLog;
-
- if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */
- CHECK_F( BIT_initDStream(&bitD1, istart1, length1) );
- CHECK_F( BIT_initDStream(&bitD2, istart2, length2) );
- CHECK_F( BIT_initDStream(&bitD3, istart3, length3) );
- CHECK_F( BIT_initDStream(&bitD4, istart4, length4) );
-
- /* 16-32 symbols per loop (4-8 symbols per stream) */
- endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
- for ( ; (endSignal==BIT_DStream_unfinished) & (op4<(oend-(sizeof(bitD4.bitContainer)-1))) ; ) {
- HUF_DECODE_SYMBOLX4_2(op1, &bitD1);
- HUF_DECODE_SYMBOLX4_2(op2, &bitD2);
- HUF_DECODE_SYMBOLX4_2(op3, &bitD3);
- HUF_DECODE_SYMBOLX4_2(op4, &bitD4);
- HUF_DECODE_SYMBOLX4_1(op1, &bitD1);
- HUF_DECODE_SYMBOLX4_1(op2, &bitD2);
- HUF_DECODE_SYMBOLX4_1(op3, &bitD3);
- HUF_DECODE_SYMBOLX4_1(op4, &bitD4);
- HUF_DECODE_SYMBOLX4_2(op1, &bitD1);
- HUF_DECODE_SYMBOLX4_2(op2, &bitD2);
- HUF_DECODE_SYMBOLX4_2(op3, &bitD3);
- HUF_DECODE_SYMBOLX4_2(op4, &bitD4);
- HUF_DECODE_SYMBOLX4_0(op1, &bitD1);
- HUF_DECODE_SYMBOLX4_0(op2, &bitD2);
- HUF_DECODE_SYMBOLX4_0(op3, &bitD3);
- HUF_DECODE_SYMBOLX4_0(op4, &bitD4);
-
- endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
- }
-
- /* check corruption */
- if (op1 > opStart2) return ERROR(corruption_detected);
- if (op2 > opStart3) return ERROR(corruption_detected);
- if (op3 > opStart4) return ERROR(corruption_detected);
- /* note : op4 already verified within main loop */
-
- /* finish bitStreams one by one */
- HUF_decodeStreamX4(op1, &bitD1, opStart2, dt, dtLog);
- HUF_decodeStreamX4(op2, &bitD2, opStart3, dt, dtLog);
- HUF_decodeStreamX4(op3, &bitD3, opStart4, dt, dtLog);
- HUF_decodeStreamX4(op4, &bitD4, oend, dt, dtLog);
+ HUF_decodeStreamX1(op1, &bitD1, opStart2, dt, dtLog);
+ HUF_decodeStreamX1(op2, &bitD2, opStart3, dt, dtLog);
+ HUF_decodeStreamX1(op3, &bitD3, opStart4, dt, dtLog);
+ HUF_decodeStreamX1(op4, &bitD4, oend, dt, dtLog);
/* check */
{ U32 const endCheck = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);
@@ -491,153 +367,119 @@ typedef size_t (*HUF_decompress_usingDTable_t)(void *dst, size_t dstSize,
const void *cSrc,
size_t cSrcSize,
const HUF_DTable *DTable);
-#if DYNAMIC_BMI2
-
-#define X(fn) \
- \
- static size_t fn##_default( \
- void* dst, size_t dstSize, \
- const void* cSrc, size_t cSrcSize, \
- const HUF_DTable* DTable) \
- { \
- return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable); \
- } \
- \
- static TARGET_ATTRIBUTE("bmi2") size_t fn##_bmi2( \
- void* dst, size_t dstSize, \
- const void* cSrc, size_t cSrcSize, \
- const HUF_DTable* DTable) \
- { \
- return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable); \
- } \
- \
- static size_t fn(void* dst, size_t dstSize, void const* cSrc, \
- size_t cSrcSize, HUF_DTable const* DTable, int bmi2) \
- { \
- if (bmi2) { \
- return fn##_bmi2(dst, dstSize, cSrc, cSrcSize, DTable); \
- } \
- return fn##_default(dst, dstSize, cSrc, cSrcSize, DTable); \
- }
-
-#else
-
-#define X(fn) \
- static size_t fn(void* dst, size_t dstSize, void const* cSrc, \
- size_t cSrcSize, HUF_DTable const* DTable, int bmi2) \
- { \
- (void)bmi2; \
- return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable); \
- }
-
-#endif
-X(HUF_decompress1X2_usingDTable_internal)
-X(HUF_decompress4X2_usingDTable_internal)
-X(HUF_decompress1X4_usingDTable_internal)
-X(HUF_decompress4X4_usingDTable_internal)
+HUF_DGEN(HUF_decompress1X1_usingDTable_internal)
+HUF_DGEN(HUF_decompress4X1_usingDTable_internal)
-#undef X
-size_t HUF_decompress1X2_usingDTable(
+size_t HUF_decompress1X1_usingDTable(
void* dst, size_t dstSize,
const void* cSrc, size_t cSrcSize,
const HUF_DTable* DTable)
{
DTableDesc dtd = HUF_getDTableDesc(DTable);
if (dtd.tableType != 0) return ERROR(GENERIC);
- return HUF_decompress1X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
+ return HUF_decompress1X1_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
}
-size_t HUF_decompress1X2_DCtx_wksp(HUF_DTable* DCtx, void* dst, size_t dstSize,
+size_t HUF_decompress1X1_DCtx_wksp(HUF_DTable* DCtx, void* dst, size_t dstSize,
const void* cSrc, size_t cSrcSize,
void* workSpace, size_t wkspSize)
{
const BYTE* ip = (const BYTE*) cSrc;
- size_t const hSize = HUF_readDTableX2_wksp(DCtx, cSrc, cSrcSize, workSpace, wkspSize);
+ size_t const hSize = HUF_readDTableX1_wksp(DCtx, cSrc, cSrcSize, workSpace, wkspSize);
if (HUF_isError(hSize)) return hSize;
if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
ip += hSize; cSrcSize -= hSize;
- return HUF_decompress1X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, DCtx, /* bmi2 */ 0);
+ return HUF_decompress1X1_usingDTable_internal(dst, dstSize, ip, cSrcSize, DCtx, /* bmi2 */ 0);
}
-size_t HUF_decompress1X2_DCtx(HUF_DTable* DCtx, void* dst, size_t dstSize,
+size_t HUF_decompress1X1_DCtx(HUF_DTable* DCtx, void* dst, size_t dstSize,
const void* cSrc, size_t cSrcSize)
{
U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
- return HUF_decompress1X2_DCtx_wksp(DCtx, dst, dstSize, cSrc, cSrcSize,
+ return HUF_decompress1X1_DCtx_wksp(DCtx, dst, dstSize, cSrc, cSrcSize,
workSpace, sizeof(workSpace));
}
-size_t HUF_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
+size_t HUF_decompress1X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
{
- HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_TABLELOG_MAX);
- return HUF_decompress1X2_DCtx (DTable, dst, dstSize, cSrc, cSrcSize);
+ HUF_CREATE_STATIC_DTABLEX1(DTable, HUF_TABLELOG_MAX);
+ return HUF_decompress1X1_DCtx (DTable, dst, dstSize, cSrc, cSrcSize);
}
-size_t HUF_decompress4X2_usingDTable(
+size_t HUF_decompress4X1_usingDTable(
void* dst, size_t dstSize,
const void* cSrc, size_t cSrcSize,
const HUF_DTable* DTable)
{
DTableDesc dtd = HUF_getDTableDesc(DTable);
if (dtd.tableType != 0) return ERROR(GENERIC);
- return HUF_decompress4X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
+ return HUF_decompress4X1_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
}
-static size_t HUF_decompress4X2_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize,
+static size_t HUF_decompress4X1_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize,
const void* cSrc, size_t cSrcSize,
void* workSpace, size_t wkspSize, int bmi2)
{
const BYTE* ip = (const BYTE*) cSrc;
- size_t const hSize = HUF_readDTableX2_wksp (dctx, cSrc, cSrcSize,
+ size_t const hSize = HUF_readDTableX1_wksp (dctx, cSrc, cSrcSize,
workSpace, wkspSize);
if (HUF_isError(hSize)) return hSize;
if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
ip += hSize; cSrcSize -= hSize;
- return HUF_decompress4X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, bmi2);
+ return HUF_decompress4X1_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, bmi2);
}
-size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,
+size_t HUF_decompress4X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,
const void* cSrc, size_t cSrcSize,
void* workSpace, size_t wkspSize)
{
- return HUF_decompress4X2_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, 0);
+ return HUF_decompress4X1_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, 0);
}
-size_t HUF_decompress4X2_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
+size_t HUF_decompress4X1_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
{
U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
- return HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize,
+ return HUF_decompress4X1_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize,
workSpace, sizeof(workSpace));
}
-size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
+size_t HUF_decompress4X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
{
- HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_TABLELOG_MAX);
- return HUF_decompress4X2_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);
+ HUF_CREATE_STATIC_DTABLEX1(DTable, HUF_TABLELOG_MAX);
+ return HUF_decompress4X1_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);
}
+#endif /* HUF_FORCE_DECOMPRESS_X2 */
+
+
+#ifndef HUF_FORCE_DECOMPRESS_X1
/* *************************/
/* double-symbols decoding */
/* *************************/
+
+typedef struct { U16 sequence; BYTE nbBits; BYTE length; } HUF_DEltX2; /* double-symbols decoding */
typedef struct { BYTE symbol; BYTE weight; } sortedSymbol_t;
+typedef U32 rankValCol_t[HUF_TABLELOG_MAX + 1];
+typedef rankValCol_t rankVal_t[HUF_TABLELOG_MAX];
-/* HUF_fillDTableX4Level2() :
+
+/* HUF_fillDTableX2Level2() :
* `rankValOrigin` must be a table of at least (HUF_TABLELOG_MAX + 1) U32 */
-static void HUF_fillDTableX4Level2(HUF_DEltX4* DTable, U32 sizeLog, const U32 consumed,
+static void HUF_fillDTableX2Level2(HUF_DEltX2* DTable, U32 sizeLog, const U32 consumed,
const U32* rankValOrigin, const int minWeight,
const sortedSymbol_t* sortedSymbols, const U32 sortedListSize,
U32 nbBitsBaseline, U16 baseSeq)
{
- HUF_DEltX4 DElt;
+ HUF_DEltX2 DElt;
U32 rankVal[HUF_TABLELOG_MAX + 1];
/* get pre-calculated rankVal */
@@ -672,10 +514,8 @@ static void HUF_fillDTableX4Level2(HUF_DEltX4* DTable, U32 sizeLog, const U32 co
} }
}
-typedef U32 rankValCol_t[HUF_TABLELOG_MAX + 1];
-typedef rankValCol_t rankVal_t[HUF_TABLELOG_MAX];
-static void HUF_fillDTableX4(HUF_DEltX4* DTable, const U32 targetLog,
+static void HUF_fillDTableX2(HUF_DEltX2* DTable, const U32 targetLog,
const sortedSymbol_t* sortedList, const U32 sortedListSize,
const U32* rankStart, rankVal_t rankValOrigin, const U32 maxWeight,
const U32 nbBitsBaseline)
@@ -700,12 +540,12 @@ static void HUF_fillDTableX4(HUF_DEltX4* DTable, const U32 targetLog,
int minWeight = nbBits + scaleLog;
if (minWeight < 1) minWeight = 1;
sortedRank = rankStart[minWeight];
- HUF_fillDTableX4Level2(DTable+start, targetLog-nbBits, nbBits,
+ HUF_fillDTableX2Level2(DTable+start, targetLog-nbBits, nbBits,
rankValOrigin[nbBits], minWeight,
sortedList+sortedRank, sortedListSize-sortedRank,
nbBitsBaseline, symbol);
} else {
- HUF_DEltX4 DElt;
+ HUF_DEltX2 DElt;
MEM_writeLE16(&(DElt.sequence), symbol);
DElt.nbBits = (BYTE)(nbBits);
DElt.length = 1;
@@ -717,16 +557,16 @@ static void HUF_fillDTableX4(HUF_DEltX4* DTable, const U32 targetLog,
}
}
-size_t HUF_readDTableX4_wksp(HUF_DTable* DTable, const void* src,
- size_t srcSize, void* workSpace,
- size_t wkspSize)
+size_t HUF_readDTableX2_wksp(HUF_DTable* DTable,
+ const void* src, size_t srcSize,
+ void* workSpace, size_t wkspSize)
{
U32 tableLog, maxW, sizeOfSort, nbSymbols;
DTableDesc dtd = HUF_getDTableDesc(DTable);
U32 const maxTableLog = dtd.maxTableLog;
size_t iSize;
void* dtPtr = DTable+1; /* force compiler to avoid strict-aliasing */
- HUF_DEltX4* const dt = (HUF_DEltX4*)dtPtr;
+ HUF_DEltX2* const dt = (HUF_DEltX2*)dtPtr;
U32 *rankStart;
rankValCol_t* rankVal;
@@ -752,7 +592,7 @@ size_t HUF_readDTableX4_wksp(HUF_DTable* DTable, const void* src,
rankStart = rankStart0 + 1;
memset(rankStats, 0, sizeof(U32) * (2 * HUF_TABLELOG_MAX + 2 + 1));
- HUF_STATIC_ASSERT(sizeof(HUF_DEltX4) == sizeof(HUF_DTable)); /* if compiler fails here, assertion is wrong */
+ DEBUG_STATIC_ASSERT(sizeof(HUF_DEltX2) == sizeof(HUF_DTable)); /* if compiler fails here, assertion is wrong */
if (maxTableLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge);
/* memset(weightList, 0, sizeof(weightList)); */ /* is not necessary, even though some analyzer complain ... */
@@ -806,7 +646,7 @@ size_t HUF_readDTableX4_wksp(HUF_DTable* DTable, const void* src,
rankValPtr[w] = rankVal0[w] >> consumed;
} } } }
- HUF_fillDTableX4(dt, maxTableLog,
+ HUF_fillDTableX2(dt, maxTableLog,
sortedSymbol, sizeOfSort,
rankStart0, rankVal, maxW,
tableLog+1);
@@ -817,112 +657,308 @@ size_t HUF_readDTableX4_wksp(HUF_DTable* DTable, const void* src,
return iSize;
}
-size_t HUF_readDTableX4(HUF_DTable* DTable, const void* src, size_t srcSize)
+size_t HUF_readDTableX2(HUF_DTable* DTable, const void* src, size_t srcSize)
{
U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
- return HUF_readDTableX4_wksp(DTable, src, srcSize,
+ return HUF_readDTableX2_wksp(DTable, src, srcSize,
workSpace, sizeof(workSpace));
}
-size_t HUF_decompress1X4_usingDTable(
+
+FORCE_INLINE_TEMPLATE U32
+HUF_decodeSymbolX2(void* op, BIT_DStream_t* DStream, const HUF_DEltX2* dt, const U32 dtLog)
+{
+ size_t const val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */
+ memcpy(op, dt+val, 2);
+ BIT_skipBits(DStream, dt[val].nbBits);
+ return dt[val].length;
+}
+
+FORCE_INLINE_TEMPLATE U32
+HUF_decodeLastSymbolX2(void* op, BIT_DStream_t* DStream, const HUF_DEltX2* dt, const U32 dtLog)
+{
+ size_t const val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */
+ memcpy(op, dt+val, 1);
+ if (dt[val].length==1) BIT_skipBits(DStream, dt[val].nbBits);
+ else {
+ if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8)) {
+ BIT_skipBits(DStream, dt[val].nbBits);
+ if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8))
+ /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */
+ DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8);
+ } }
+ return 1;
+}
+
+#define HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \
+ ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog)
+
+#define HUF_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \
+ if (MEM_64bits() || (HUF_TABLELOG_MAX<=12)) \
+ ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog)
+
+#define HUF_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \
+ if (MEM_64bits()) \
+ ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog)
+
+HINT_INLINE size_t
+HUF_decodeStreamX2(BYTE* p, BIT_DStream_t* bitDPtr, BYTE* const pEnd,
+ const HUF_DEltX2* const dt, const U32 dtLog)
+{
+ BYTE* const pStart = p;
+
+ /* up to 8 symbols at a time */
+ while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-(sizeof(bitDPtr->bitContainer)-1))) {
+ HUF_DECODE_SYMBOLX2_2(p, bitDPtr);
+ HUF_DECODE_SYMBOLX2_1(p, bitDPtr);
+ HUF_DECODE_SYMBOLX2_2(p, bitDPtr);
+ HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
+ }
+
+ /* closer to end : up to 2 symbols at a time */
+ while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p <= pEnd-2))
+ HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
+
+ while (p <= pEnd-2)
+ HUF_DECODE_SYMBOLX2_0(p, bitDPtr); /* no need to reload : reached the end of DStream */
+
+ if (p < pEnd)
+ p += HUF_decodeLastSymbolX2(p, bitDPtr, dt, dtLog);
+
+ return p-pStart;
+}
+
+FORCE_INLINE_TEMPLATE size_t
+HUF_decompress1X2_usingDTable_internal_body(
+ void* dst, size_t dstSize,
+ const void* cSrc, size_t cSrcSize,
+ const HUF_DTable* DTable)
+{
+ BIT_DStream_t bitD;
+
+ /* Init */
+ CHECK_F( BIT_initDStream(&bitD, cSrc, cSrcSize) );
+
+ /* decode */
+ { BYTE* const ostart = (BYTE*) dst;
+ BYTE* const oend = ostart + dstSize;
+ const void* const dtPtr = DTable+1; /* force compiler to not use strict-aliasing */
+ const HUF_DEltX2* const dt = (const HUF_DEltX2*)dtPtr;
+ DTableDesc const dtd = HUF_getDTableDesc(DTable);
+ HUF_decodeStreamX2(ostart, &bitD, oend, dt, dtd.tableLog);
+ }
+
+ /* check */
+ if (!BIT_endOfDStream(&bitD)) return ERROR(corruption_detected);
+
+ /* decoded size */
+ return dstSize;
+}
+
+
+FORCE_INLINE_TEMPLATE size_t
+HUF_decompress4X2_usingDTable_internal_body(
+ void* dst, size_t dstSize,
+ const void* cSrc, size_t cSrcSize,
+ const HUF_DTable* DTable)
+{
+ if (cSrcSize < 10) return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */
+
+ { const BYTE* const istart = (const BYTE*) cSrc;
+ BYTE* const ostart = (BYTE*) dst;
+ BYTE* const oend = ostart + dstSize;
+ const void* const dtPtr = DTable+1;
+ const HUF_DEltX2* const dt = (const HUF_DEltX2*)dtPtr;
+
+ /* Init */
+ BIT_DStream_t bitD1;
+ BIT_DStream_t bitD2;
+ BIT_DStream_t bitD3;
+ BIT_DStream_t bitD4;
+ size_t const length1 = MEM_readLE16(istart);
+ size_t const length2 = MEM_readLE16(istart+2);
+ size_t const length3 = MEM_readLE16(istart+4);
+ size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);
+ const BYTE* const istart1 = istart + 6; /* jumpTable */
+ const BYTE* const istart2 = istart1 + length1;
+ const BYTE* const istart3 = istart2 + length2;
+ const BYTE* const istart4 = istart3 + length3;
+ size_t const segmentSize = (dstSize+3) / 4;
+ BYTE* const opStart2 = ostart + segmentSize;
+ BYTE* const opStart3 = opStart2 + segmentSize;
+ BYTE* const opStart4 = opStart3 + segmentSize;
+ BYTE* op1 = ostart;
+ BYTE* op2 = opStart2;
+ BYTE* op3 = opStart3;
+ BYTE* op4 = opStart4;
+ U32 endSignal;
+ DTableDesc const dtd = HUF_getDTableDesc(DTable);
+ U32 const dtLog = dtd.tableLog;
+
+ if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */
+ CHECK_F( BIT_initDStream(&bitD1, istart1, length1) );
+ CHECK_F( BIT_initDStream(&bitD2, istart2, length2) );
+ CHECK_F( BIT_initDStream(&bitD3, istart3, length3) );
+ CHECK_F( BIT_initDStream(&bitD4, istart4, length4) );
+
+ /* 16-32 symbols per loop (4-8 symbols per stream) */
+ endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
+ for ( ; (endSignal==BIT_DStream_unfinished) & (op4<(oend-(sizeof(bitD4.bitContainer)-1))) ; ) {
+ HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
+ HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
+ HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
+ HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
+ HUF_DECODE_SYMBOLX2_1(op1, &bitD1);
+ HUF_DECODE_SYMBOLX2_1(op2, &bitD2);
+ HUF_DECODE_SYMBOLX2_1(op3, &bitD3);
+ HUF_DECODE_SYMBOLX2_1(op4, &bitD4);
+ HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
+ HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
+ HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
+ HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
+ HUF_DECODE_SYMBOLX2_0(op1, &bitD1);
+ HUF_DECODE_SYMBOLX2_0(op2, &bitD2);
+ HUF_DECODE_SYMBOLX2_0(op3, &bitD3);
+ HUF_DECODE_SYMBOLX2_0(op4, &bitD4);
+
+ endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
+ }
+
+ /* check corruption */
+ if (op1 > opStart2) return ERROR(corruption_detected);
+ if (op2 > opStart3) return ERROR(corruption_detected);
+ if (op3 > opStart4) return ERROR(corruption_detected);
+ /* note : op4 already verified within main loop */
+
+ /* finish bitStreams one by one */
+ HUF_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog);
+ HUF_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog);
+ HUF_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog);
+ HUF_decodeStreamX2(op4, &bitD4, oend, dt, dtLog);
+
+ /* check */
+ { U32 const endCheck = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);
+ if (!endCheck) return ERROR(corruption_detected); }
+
+ /* decoded size */
+ return dstSize;
+ }
+}
+
+HUF_DGEN(HUF_decompress1X2_usingDTable_internal)
+HUF_DGEN(HUF_decompress4X2_usingDTable_internal)
+
+size_t HUF_decompress1X2_usingDTable(
void* dst, size_t dstSize,
const void* cSrc, size_t cSrcSize,
const HUF_DTable* DTable)
{
DTableDesc dtd = HUF_getDTableDesc(DTable);
if (dtd.tableType != 1) return ERROR(GENERIC);
- return HUF_decompress1X4_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
+ return HUF_decompress1X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
}
-size_t HUF_decompress1X4_DCtx_wksp(HUF_DTable* DCtx, void* dst, size_t dstSize,
+size_t HUF_decompress1X2_DCtx_wksp(HUF_DTable* DCtx, void* dst, size_t dstSize,
const void* cSrc, size_t cSrcSize,
void* workSpace, size_t wkspSize)
{
const BYTE* ip = (const BYTE*) cSrc;
- size_t const hSize = HUF_readDTableX4_wksp(DCtx, cSrc, cSrcSize,
+ size_t const hSize = HUF_readDTableX2_wksp(DCtx, cSrc, cSrcSize,
workSpace, wkspSize);
if (HUF_isError(hSize)) return hSize;
if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
ip += hSize; cSrcSize -= hSize;
- return HUF_decompress1X4_usingDTable_internal(dst, dstSize, ip, cSrcSize, DCtx, /* bmi2 */ 0);
+ return HUF_decompress1X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, DCtx, /* bmi2 */ 0);
}
-size_t HUF_decompress1X4_DCtx(HUF_DTable* DCtx, void* dst, size_t dstSize,
+size_t HUF_decompress1X2_DCtx(HUF_DTable* DCtx, void* dst, size_t dstSize,
const void* cSrc, size_t cSrcSize)
{
U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
- return HUF_decompress1X4_DCtx_wksp(DCtx, dst, dstSize, cSrc, cSrcSize,
+ return HUF_decompress1X2_DCtx_wksp(DCtx, dst, dstSize, cSrc, cSrcSize,
workSpace, sizeof(workSpace));
}
-size_t HUF_decompress1X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
+size_t HUF_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
{
- HUF_CREATE_STATIC_DTABLEX4(DTable, HUF_TABLELOG_MAX);
- return HUF_decompress1X4_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);
+ HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_TABLELOG_MAX);
+ return HUF_decompress1X2_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);
}
-size_t HUF_decompress4X4_usingDTable(
+size_t HUF_decompress4X2_usingDTable(
void* dst, size_t dstSize,
const void* cSrc, size_t cSrcSize,
const HUF_DTable* DTable)
{
DTableDesc dtd = HUF_getDTableDesc(DTable);
if (dtd.tableType != 1) return ERROR(GENERIC);
- return HUF_decompress4X4_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
+ return HUF_decompress4X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
}
-static size_t HUF_decompress4X4_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize,
+static size_t HUF_decompress4X2_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize,
const void* cSrc, size_t cSrcSize,
void* workSpace, size_t wkspSize, int bmi2)
{
const BYTE* ip = (const BYTE*) cSrc;
- size_t hSize = HUF_readDTableX4_wksp(dctx, cSrc, cSrcSize,
+ size_t hSize = HUF_readDTableX2_wksp(dctx, cSrc, cSrcSize,
workSpace, wkspSize);
if (HUF_isError(hSize)) return hSize;
if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
ip += hSize; cSrcSize -= hSize;
- return HUF_decompress4X4_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, bmi2);
+ return HUF_decompress4X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, bmi2);
}
-size_t HUF_decompress4X4_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,
+size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,
const void* cSrc, size_t cSrcSize,
void* workSpace, size_t wkspSize)
{
- return HUF_decompress4X4_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, /* bmi2 */ 0);
+ return HUF_decompress4X2_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, /* bmi2 */ 0);
}
-size_t HUF_decompress4X4_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize,
+size_t HUF_decompress4X2_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize,
const void* cSrc, size_t cSrcSize)
{
U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
- return HUF_decompress4X4_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize,
+ return HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize,
workSpace, sizeof(workSpace));
}
-size_t HUF_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
+size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
{
- HUF_CREATE_STATIC_DTABLEX4(DTable, HUF_TABLELOG_MAX);
- return HUF_decompress4X4_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);
+ HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_TABLELOG_MAX);
+ return HUF_decompress4X2_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);
}
+#endif /* HUF_FORCE_DECOMPRESS_X1 */
-/* ********************************/
-/* Generic decompression selector */
-/* ********************************/
+
+/* ***********************************/
+/* Universal decompression selectors */
+/* ***********************************/
size_t HUF_decompress1X_usingDTable(void* dst, size_t maxDstSize,
const void* cSrc, size_t cSrcSize,
const HUF_DTable* DTable)
{
DTableDesc const dtd = HUF_getDTableDesc(DTable);
- return dtd.tableType ? HUF_decompress1X4_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0) :
- HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
+#if defined(HUF_FORCE_DECOMPRESS_X1)
+ (void)dtd;
+ assert(dtd.tableType == 0);
+ return HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
+#elif defined(HUF_FORCE_DECOMPRESS_X2)
+ (void)dtd;
+ assert(dtd.tableType == 1);
+ return HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
+#else
+ return dtd.tableType ? HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0) :
+ HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
+#endif
}
size_t HUF_decompress4X_usingDTable(void* dst, size_t maxDstSize,
@@ -930,11 +966,22 @@ size_t HUF_decompress4X_usingDTable(void* dst, size_t maxDstSize,
const HUF_DTable* DTable)
{
DTableDesc const dtd = HUF_getDTableDesc(DTable);
- return dtd.tableType ? HUF_decompress4X4_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0) :
- HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
+#if defined(HUF_FORCE_DECOMPRESS_X1)
+ (void)dtd;
+ assert(dtd.tableType == 0);
+ return HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
+#elif defined(HUF_FORCE_DECOMPRESS_X2)
+ (void)dtd;
+ assert(dtd.tableType == 1);
+ return HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
+#else
+ return dtd.tableType ? HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0) :
+ HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
+#endif
}
+#if !defined(HUF_FORCE_DECOMPRESS_X1) && !defined(HUF_FORCE_DECOMPRESS_X2)
typedef struct { U32 tableTime; U32 decode256Time; } algo_time_t;
static const algo_time_t algoTime[16 /* Quantization */][3 /* single, double, quad */] =
{
@@ -956,16 +1003,26 @@ static const algo_time_t algoTime[16 /* Quantization */][3 /* single, double, qu
{{1455,128}, {2422,124}, {4174,124}}, /* Q ==14 : 87-93% */
{{ 722,128}, {1891,145}, {1936,146}}, /* Q ==15 : 93-99% */
};
+#endif
/** HUF_selectDecoder() :
* Tells which decoder is likely to decode faster,
* based on a set of pre-computed metrics.
- * @return : 0==HUF_decompress4X2, 1==HUF_decompress4X4 .
+ * @return : 0==HUF_decompress4X1, 1==HUF_decompress4X2 .
* Assumption : 0 < dstSize <= 128 KB */
U32 HUF_selectDecoder (size_t dstSize, size_t cSrcSize)
{
assert(dstSize > 0);
- assert(dstSize <= 128 KB);
+ assert(dstSize <= 128*1024);
+#if defined(HUF_FORCE_DECOMPRESS_X1)
+ (void)dstSize;
+ (void)cSrcSize;
+ return 0;
+#elif defined(HUF_FORCE_DECOMPRESS_X2)
+ (void)dstSize;
+ (void)cSrcSize;
+ return 1;
+#else
/* decoder timing evaluation */
{ U32 const Q = (cSrcSize >= dstSize) ? 15 : (U32)(cSrcSize * 16 / dstSize); /* Q < 16 */
U32 const D256 = (U32)(dstSize >> 8);
@@ -973,14 +1030,18 @@ U32 HUF_selectDecoder (size_t dstSize, size_t cSrcSize)
U32 DTime1 = algoTime[Q][1].tableTime + (algoTime[Q][1].decode256Time * D256);
DTime1 += DTime1 >> 3; /* advantage to algorithm using less memory, to reduce cache eviction */
return DTime1 < DTime0;
-} }
+ }
+#endif
+}
typedef size_t (*decompressionAlgo)(void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);
size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
{
- static const decompressionAlgo decompress[2] = { HUF_decompress4X2, HUF_decompress4X4 };
+#if !defined(HUF_FORCE_DECOMPRESS_X1) && !defined(HUF_FORCE_DECOMPRESS_X2)
+ static const decompressionAlgo decompress[2] = { HUF_decompress4X1, HUF_decompress4X2 };
+#endif
/* validation checks */
if (dstSize == 0) return ERROR(dstSize_tooSmall);
@@ -989,7 +1050,17 @@ size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcS
if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */
{ U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
+#if defined(HUF_FORCE_DECOMPRESS_X1)
+ (void)algoNb;
+ assert(algoNb == 0);
+ return HUF_decompress4X1(dst, dstSize, cSrc, cSrcSize);
+#elif defined(HUF_FORCE_DECOMPRESS_X2)
+ (void)algoNb;
+ assert(algoNb == 1);
+ return HUF_decompress4X2(dst, dstSize, cSrc, cSrcSize);
+#else
return decompress[algoNb](dst, dstSize, cSrc, cSrcSize);
+#endif
}
}
@@ -1002,8 +1073,18 @@ size_t HUF_decompress4X_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const
if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */
{ U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
- return algoNb ? HUF_decompress4X4_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) :
- HUF_decompress4X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) ;
+#if defined(HUF_FORCE_DECOMPRESS_X1)
+ (void)algoNb;
+ assert(algoNb == 0);
+ return HUF_decompress4X1_DCtx(dctx, dst, dstSize, cSrc, cSrcSize);
+#elif defined(HUF_FORCE_DECOMPRESS_X2)
+ (void)algoNb;
+ assert(algoNb == 1);
+ return HUF_decompress4X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize);
+#else
+ return algoNb ? HUF_decompress4X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) :
+ HUF_decompress4X1_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) ;
+#endif
}
}
@@ -1025,8 +1106,19 @@ size_t HUF_decompress4X_hufOnly_wksp(HUF_DTable* dctx, void* dst,
if (cSrcSize == 0) return ERROR(corruption_detected);
{ U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
- return algoNb ? HUF_decompress4X4_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize):
- HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize);
+#if defined(HUF_FORCE_DECOMPRESS_X1)
+ (void)algoNb;
+ assert(algoNb == 0);
+ return HUF_decompress4X1_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize);
+#elif defined(HUF_FORCE_DECOMPRESS_X2)
+ (void)algoNb;
+ assert(algoNb == 1);
+ return HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize);
+#else
+ return algoNb ? HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc,
+ cSrcSize, workSpace, wkspSize):
+ HUF_decompress4X1_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize);
+#endif
}
}
@@ -1041,10 +1133,22 @@ size_t HUF_decompress1X_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,
if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */
{ U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
- return algoNb ? HUF_decompress1X4_DCtx_wksp(dctx, dst, dstSize, cSrc,
+#if defined(HUF_FORCE_DECOMPRESS_X1)
+ (void)algoNb;
+ assert(algoNb == 0);
+ return HUF_decompress1X1_DCtx_wksp(dctx, dst, dstSize, cSrc,
+ cSrcSize, workSpace, wkspSize);
+#elif defined(HUF_FORCE_DECOMPRESS_X2)
+ (void)algoNb;
+ assert(algoNb == 1);
+ return HUF_decompress1X2_DCtx_wksp(dctx, dst, dstSize, cSrc,
+ cSrcSize, workSpace, wkspSize);
+#else
+ return algoNb ? HUF_decompress1X2_DCtx_wksp(dctx, dst, dstSize, cSrc,
cSrcSize, workSpace, wkspSize):
- HUF_decompress1X2_DCtx_wksp(dctx, dst, dstSize, cSrc,
+ HUF_decompress1X1_DCtx_wksp(dctx, dst, dstSize, cSrc,
cSrcSize, workSpace, wkspSize);
+#endif
}
}
@@ -1060,27 +1164,49 @@ size_t HUF_decompress1X_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize,
size_t HUF_decompress1X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2)
{
DTableDesc const dtd = HUF_getDTableDesc(DTable);
- return dtd.tableType ? HUF_decompress1X4_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2) :
- HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2);
+#if defined(HUF_FORCE_DECOMPRESS_X1)
+ (void)dtd;
+ assert(dtd.tableType == 0);
+ return HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2);
+#elif defined(HUF_FORCE_DECOMPRESS_X2)
+ (void)dtd;
+ assert(dtd.tableType == 1);
+ return HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2);
+#else
+ return dtd.tableType ? HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2) :
+ HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2);
+#endif
}
-size_t HUF_decompress1X2_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2)
+#ifndef HUF_FORCE_DECOMPRESS_X2
+size_t HUF_decompress1X1_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2)
{
const BYTE* ip = (const BYTE*) cSrc;
- size_t const hSize = HUF_readDTableX2_wksp(dctx, cSrc, cSrcSize, workSpace, wkspSize);
+ size_t const hSize = HUF_readDTableX1_wksp(dctx, cSrc, cSrcSize, workSpace, wkspSize);
if (HUF_isError(hSize)) return hSize;
if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
ip += hSize; cSrcSize -= hSize;
- return HUF_decompress1X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, bmi2);
+ return HUF_decompress1X1_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, bmi2);
}
+#endif
size_t HUF_decompress4X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2)
{
DTableDesc const dtd = HUF_getDTableDesc(DTable);
- return dtd.tableType ? HUF_decompress4X4_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2) :
- HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2);
+#if defined(HUF_FORCE_DECOMPRESS_X1)
+ (void)dtd;
+ assert(dtd.tableType == 0);
+ return HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2);
+#elif defined(HUF_FORCE_DECOMPRESS_X2)
+ (void)dtd;
+ assert(dtd.tableType == 1);
+ return HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2);
+#else
+ return dtd.tableType ? HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2) :
+ HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2);
+#endif
}
size_t HUF_decompress4X_hufOnly_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2)
@@ -1090,7 +1216,17 @@ size_t HUF_decompress4X_hufOnly_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t ds
if (cSrcSize == 0) return ERROR(corruption_detected);
{ U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
- return algoNb ? HUF_decompress4X4_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, bmi2) :
- HUF_decompress4X2_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, bmi2);
+#if defined(HUF_FORCE_DECOMPRESS_X1)
+ (void)algoNb;
+ assert(algoNb == 0);
+ return HUF_decompress4X1_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, bmi2);
+#elif defined(HUF_FORCE_DECOMPRESS_X2)
+ (void)algoNb;
+ assert(algoNb == 1);
+ return HUF_decompress4X2_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, bmi2);
+#else
+ return algoNb ? HUF_decompress4X2_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, bmi2) :
+ HUF_decompress4X1_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, bmi2);
+#endif
}
}
diff --git a/thirdparty/zstd/decompress/zstd_ddict.c b/thirdparty/zstd/decompress/zstd_ddict.c
new file mode 100644
index 0000000000..0af3d23bfe
--- /dev/null
+++ b/thirdparty/zstd/decompress/zstd_ddict.c
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+/* zstd_ddict.c :
+ * concentrates all logic that needs to know the internals of ZSTD_DDict object */
+
+/*-*******************************************************
+* Dependencies
+*********************************************************/
+#include <string.h> /* memcpy, memmove, memset */
+#include "cpu.h" /* bmi2 */
+#include "mem.h" /* low level memory routines */
+#define FSE_STATIC_LINKING_ONLY
+#include "fse.h"
+#define HUF_STATIC_LINKING_ONLY
+#include "huf.h"
+#include "zstd_decompress_internal.h"
+#include "zstd_ddict.h"
+
+#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
+# include "zstd_legacy.h"
+#endif
+
+
+
+/*-*******************************************************
+* Types
+*********************************************************/
+struct ZSTD_DDict_s {
+ void* dictBuffer;
+ const void* dictContent;
+ size_t dictSize;
+ ZSTD_entropyDTables_t entropy;
+ U32 dictID;
+ U32 entropyPresent;
+ ZSTD_customMem cMem;
+}; /* typedef'd to ZSTD_DDict within "zstd.h" */
+
+const void* ZSTD_DDict_dictContent(const ZSTD_DDict* ddict)
+{
+ assert(ddict != NULL);
+ return ddict->dictContent;
+}
+
+size_t ZSTD_DDict_dictSize(const ZSTD_DDict* ddict)
+{
+ assert(ddict != NULL);
+ return ddict->dictSize;
+}
+
+void ZSTD_copyDDictParameters(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
+{
+ DEBUGLOG(4, "ZSTD_copyDDictParameters");
+ assert(dctx != NULL);
+ assert(ddict != NULL);
+ dctx->dictID = ddict->dictID;
+ dctx->prefixStart = ddict->dictContent;
+ dctx->virtualStart = ddict->dictContent;
+ dctx->dictEnd = (const BYTE*)ddict->dictContent + ddict->dictSize;
+ dctx->previousDstEnd = dctx->dictEnd;
+ if (ddict->entropyPresent) {
+ dctx->litEntropy = 1;
+ dctx->fseEntropy = 1;
+ dctx->LLTptr = ddict->entropy.LLTable;
+ dctx->MLTptr = ddict->entropy.MLTable;
+ dctx->OFTptr = ddict->entropy.OFTable;
+ dctx->HUFptr = ddict->entropy.hufTable;
+ dctx->entropy.rep[0] = ddict->entropy.rep[0];
+ dctx->entropy.rep[1] = ddict->entropy.rep[1];
+ dctx->entropy.rep[2] = ddict->entropy.rep[2];
+ } else {
+ dctx->litEntropy = 0;
+ dctx->fseEntropy = 0;
+ }
+}
+
+
+static size_t
+ZSTD_loadEntropy_intoDDict(ZSTD_DDict* ddict,
+ ZSTD_dictContentType_e dictContentType)
+{
+ ddict->dictID = 0;
+ ddict->entropyPresent = 0;
+ if (dictContentType == ZSTD_dct_rawContent) return 0;
+
+ if (ddict->dictSize < 8) {
+ if (dictContentType == ZSTD_dct_fullDict)
+ return ERROR(dictionary_corrupted); /* only accept specified dictionaries */
+ return 0; /* pure content mode */
+ }
+ { U32 const magic = MEM_readLE32(ddict->dictContent);
+ if (magic != ZSTD_MAGIC_DICTIONARY) {
+ if (dictContentType == ZSTD_dct_fullDict)
+ return ERROR(dictionary_corrupted); /* only accept specified dictionaries */
+ return 0; /* pure content mode */
+ }
+ }
+ ddict->dictID = MEM_readLE32((const char*)ddict->dictContent + ZSTD_FRAMEIDSIZE);
+
+ /* load entropy tables */
+ RETURN_ERROR_IF(ZSTD_isError(ZSTD_loadDEntropy(
+ &ddict->entropy, ddict->dictContent, ddict->dictSize)),
+ dictionary_corrupted);
+ ddict->entropyPresent = 1;
+ return 0;
+}
+
+
+static size_t ZSTD_initDDict_internal(ZSTD_DDict* ddict,
+ const void* dict, size_t dictSize,
+ ZSTD_dictLoadMethod_e dictLoadMethod,
+ ZSTD_dictContentType_e dictContentType)
+{
+ if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dict) || (!dictSize)) {
+ ddict->dictBuffer = NULL;
+ ddict->dictContent = dict;
+ if (!dict) dictSize = 0;
+ } else {
+ void* const internalBuffer = ZSTD_malloc(dictSize, ddict->cMem);
+ ddict->dictBuffer = internalBuffer;
+ ddict->dictContent = internalBuffer;
+ if (!internalBuffer) return ERROR(memory_allocation);
+ memcpy(internalBuffer, dict, dictSize);
+ }
+ ddict->dictSize = dictSize;
+ ddict->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
+
+ /* parse dictionary content */
+ FORWARD_IF_ERROR( ZSTD_loadEntropy_intoDDict(ddict, dictContentType) );
+
+ return 0;
+}
+
+ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize,
+ ZSTD_dictLoadMethod_e dictLoadMethod,
+ ZSTD_dictContentType_e dictContentType,
+ ZSTD_customMem customMem)
+{
+ if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
+
+ { ZSTD_DDict* const ddict = (ZSTD_DDict*) ZSTD_malloc(sizeof(ZSTD_DDict), customMem);
+ if (ddict == NULL) return NULL;
+ ddict->cMem = customMem;
+ { size_t const initResult = ZSTD_initDDict_internal(ddict,
+ dict, dictSize,
+ dictLoadMethod, dictContentType);
+ if (ZSTD_isError(initResult)) {
+ ZSTD_freeDDict(ddict);
+ return NULL;
+ } }
+ return ddict;
+ }
+}
+
+/*! ZSTD_createDDict() :
+* Create a digested dictionary, to start decompression without startup delay.
+* `dict` content is copied inside DDict.
+* Consequently, `dict` can be released after `ZSTD_DDict` creation */
+ZSTD_DDict* ZSTD_createDDict(const void* dict, size_t dictSize)
+{
+ ZSTD_customMem const allocator = { NULL, NULL, NULL };
+ return ZSTD_createDDict_advanced(dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto, allocator);
+}
+
+/*! ZSTD_createDDict_byReference() :
+ * Create a digested dictionary, to start decompression without startup delay.
+ * Dictionary content is simply referenced, it will be accessed during decompression.
+ * Warning : dictBuffer must outlive DDict (DDict must be freed before dictBuffer) */
+ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize)
+{
+ ZSTD_customMem const allocator = { NULL, NULL, NULL };
+ return ZSTD_createDDict_advanced(dictBuffer, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto, allocator);
+}
+
+
+const ZSTD_DDict* ZSTD_initStaticDDict(
+ void* sBuffer, size_t sBufferSize,
+ const void* dict, size_t dictSize,
+ ZSTD_dictLoadMethod_e dictLoadMethod,
+ ZSTD_dictContentType_e dictContentType)
+{
+ size_t const neededSpace = sizeof(ZSTD_DDict)
+ + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize);
+ ZSTD_DDict* const ddict = (ZSTD_DDict*)sBuffer;
+ assert(sBuffer != NULL);
+ assert(dict != NULL);
+ if ((size_t)sBuffer & 7) return NULL; /* 8-aligned */
+ if (sBufferSize < neededSpace) return NULL;
+ if (dictLoadMethod == ZSTD_dlm_byCopy) {
+ memcpy(ddict+1, dict, dictSize); /* local copy */
+ dict = ddict+1;
+ }
+ if (ZSTD_isError( ZSTD_initDDict_internal(ddict,
+ dict, dictSize,
+ ZSTD_dlm_byRef, dictContentType) ))
+ return NULL;
+ return ddict;
+}
+
+
+size_t ZSTD_freeDDict(ZSTD_DDict* ddict)
+{
+ if (ddict==NULL) return 0; /* support free on NULL */
+ { ZSTD_customMem const cMem = ddict->cMem;
+ ZSTD_free(ddict->dictBuffer, cMem);
+ ZSTD_free(ddict, cMem);
+ return 0;
+ }
+}
+
+/*! ZSTD_estimateDDictSize() :
+ * Estimate amount of memory that will be needed to create a dictionary for decompression.
+ * Note : dictionary created by reference using ZSTD_dlm_byRef are smaller */
+size_t ZSTD_estimateDDictSize(size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod)
+{
+ return sizeof(ZSTD_DDict) + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize);
+}
+
+size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict)
+{
+ if (ddict==NULL) return 0; /* support sizeof on NULL */
+ return sizeof(*ddict) + (ddict->dictBuffer ? ddict->dictSize : 0) ;
+}
+
+/*! ZSTD_getDictID_fromDDict() :
+ * Provides the dictID of the dictionary loaded into `ddict`.
+ * If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.
+ * Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */
+unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict)
+{
+ if (ddict==NULL) return 0;
+ return ZSTD_getDictID_fromDict(ddict->dictContent, ddict->dictSize);
+}
diff --git a/thirdparty/zstd/decompress/zstd_ddict.h b/thirdparty/zstd/decompress/zstd_ddict.h
new file mode 100644
index 0000000000..0479d11bb0
--- /dev/null
+++ b/thirdparty/zstd/decompress/zstd_ddict.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+
+#ifndef ZSTD_DDICT_H
+#define ZSTD_DDICT_H
+
+/*-*******************************************************
+ * Dependencies
+ *********************************************************/
+#include <stddef.h> /* size_t */
+#include "zstd.h" /* ZSTD_DDict, and several public functions */
+
+
+/*-*******************************************************
+ * Interface
+ *********************************************************/
+
+/* note: several prototypes are already published in `zstd.h` :
+ * ZSTD_createDDict()
+ * ZSTD_createDDict_byReference()
+ * ZSTD_createDDict_advanced()
+ * ZSTD_freeDDict()
+ * ZSTD_initStaticDDict()
+ * ZSTD_sizeof_DDict()
+ * ZSTD_estimateDDictSize()
+ * ZSTD_getDictID_fromDict()
+ */
+
+const void* ZSTD_DDict_dictContent(const ZSTD_DDict* ddict);
+size_t ZSTD_DDict_dictSize(const ZSTD_DDict* ddict);
+
+void ZSTD_copyDDictParameters(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict);
+
+
+
+#endif /* ZSTD_DDICT_H */
diff --git a/thirdparty/zstd/decompress/zstd_decompress.c b/thirdparty/zstd/decompress/zstd_decompress.c
index 3ec6a1cb32..675596f5aa 100644
--- a/thirdparty/zstd/decompress/zstd_decompress.c
+++ b/thirdparty/zstd/decompress/zstd_decompress.c
@@ -37,7 +37,18 @@
* It's possible to set a different limit using ZSTD_DCtx_setMaxWindowSize().
*/
#ifndef ZSTD_MAXWINDOWSIZE_DEFAULT
-# define ZSTD_MAXWINDOWSIZE_DEFAULT (((U32)1 << ZSTD_WINDOWLOG_DEFAULTMAX) + 1)
+# define ZSTD_MAXWINDOWSIZE_DEFAULT (((U32)1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT) + 1)
+#endif
+
+/*!
+ * NO_FORWARD_PROGRESS_MAX :
+ * maximum allowed nb of calls to ZSTD_decompressStream()
+ * without any forward progress
+ * (defined as: no byte read from input, and no byte flushed to output)
+ * before triggering an error.
+ */
+#ifndef ZSTD_NO_FORWARD_PROGRESS_MAX
+# define ZSTD_NO_FORWARD_PROGRESS_MAX 16
#endif
@@ -45,120 +56,25 @@
* Dependencies
*********************************************************/
#include <string.h> /* memcpy, memmove, memset */
-#include "cpu.h"
+#include "cpu.h" /* bmi2 */
#include "mem.h" /* low level memory routines */
#define FSE_STATIC_LINKING_ONLY
#include "fse.h"
#define HUF_STATIC_LINKING_ONLY
#include "huf.h"
-#include "zstd_internal.h"
+#include "zstd_internal.h" /* blockProperties_t */
+#include "zstd_decompress_internal.h" /* ZSTD_DCtx */
+#include "zstd_ddict.h" /* ZSTD_DDictDictContent */
+#include "zstd_decompress_block.h" /* ZSTD_decompressBlock_internal */
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
# include "zstd_legacy.h"
#endif
-/*-*************************************
-* Errors
-***************************************/
-#define ZSTD_isError ERR_isError /* for inlining */
-#define FSE_isError ERR_isError
-#define HUF_isError ERR_isError
-
-
-/*_*******************************************************
-* Memory operations
-**********************************************************/
-static void ZSTD_copy4(void* dst, const void* src) { memcpy(dst, src, 4); }
-
-
/*-*************************************************************
* Context management
***************************************************************/
-typedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader,
- ZSTDds_decodeBlockHeader, ZSTDds_decompressBlock,
- ZSTDds_decompressLastBlock, ZSTDds_checkChecksum,
- ZSTDds_decodeSkippableHeader, ZSTDds_skipFrame } ZSTD_dStage;
-
-typedef enum { zdss_init=0, zdss_loadHeader,
- zdss_read, zdss_load, zdss_flush } ZSTD_dStreamStage;
-
-
-typedef struct {
- U32 fastMode;
- U32 tableLog;
-} ZSTD_seqSymbol_header;
-
-typedef struct {
- U16 nextState;
- BYTE nbAdditionalBits;
- BYTE nbBits;
- U32 baseValue;
-} ZSTD_seqSymbol;
-
-#define SEQSYMBOL_TABLE_SIZE(log) (1 + (1 << (log)))
-
-typedef struct {
- ZSTD_seqSymbol LLTable[SEQSYMBOL_TABLE_SIZE(LLFSELog)];
- ZSTD_seqSymbol OFTable[SEQSYMBOL_TABLE_SIZE(OffFSELog)];
- ZSTD_seqSymbol MLTable[SEQSYMBOL_TABLE_SIZE(MLFSELog)];
- HUF_DTable hufTable[HUF_DTABLE_SIZE(HufLog)]; /* can accommodate HUF_decompress4X */
- U32 workspace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
- U32 rep[ZSTD_REP_NUM];
-} ZSTD_entropyDTables_t;
-
-struct ZSTD_DCtx_s
-{
- const ZSTD_seqSymbol* LLTptr;
- const ZSTD_seqSymbol* MLTptr;
- const ZSTD_seqSymbol* OFTptr;
- const HUF_DTable* HUFptr;
- ZSTD_entropyDTables_t entropy;
- const void* previousDstEnd; /* detect continuity */
- const void* base; /* start of current segment */
- const void* vBase; /* virtual start of previous segment if it was just before current one */
- const void* dictEnd; /* end of previous segment */
- size_t expected;
- ZSTD_frameHeader fParams;
- U64 decodedSize;
- blockType_e bType; /* used in ZSTD_decompressContinue(), store blockType between block header decoding and block decompression stages */
- ZSTD_dStage stage;
- U32 litEntropy;
- U32 fseEntropy;
- XXH64_state_t xxhState;
- size_t headerSize;
- U32 dictID;
- ZSTD_format_e format;
- const BYTE* litPtr;
- ZSTD_customMem customMem;
- size_t litSize;
- size_t rleSize;
- size_t staticSize;
- int bmi2; /* == 1 if the CPU supports BMI2 and 0 otherwise. CPU support is determined dynamically once per context lifetime. */
-
- /* streaming */
- ZSTD_DDict* ddictLocal;
- const ZSTD_DDict* ddict;
- ZSTD_dStreamStage streamStage;
- char* inBuff;
- size_t inBuffSize;
- size_t inPos;
- size_t maxWindowSize;
- char* outBuff;
- size_t outBuffSize;
- size_t outStart;
- size_t outEnd;
- size_t lhSize;
- void* legacyContext;
- U32 previousLegacyVersion;
- U32 legacyVersion;
- U32 hostageByte;
-
- /* workspace */
- BYTE litBuffer[ZSTD_BLOCKSIZE_MAX + WILDCOPY_OVERLENGTH];
- BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX];
-}; /* typedef'd to ZSTD_DCtx within "zstd.h" */
-
size_t ZSTD_sizeof_DCtx (const ZSTD_DCtx* dctx)
{
if (dctx==NULL) return 0; /* support sizeof NULL */
@@ -173,8 +89,8 @@ size_t ZSTD_estimateDCtxSize(void) { return sizeof(ZSTD_DCtx); }
static size_t ZSTD_startingInputLength(ZSTD_format_e format)
{
size_t const startingInputLength = (format==ZSTD_f_zstd1_magicless) ?
- ZSTD_frameHeaderSize_prefix - ZSTD_frameIdSize :
- ZSTD_frameHeaderSize_prefix;
+ ZSTD_FRAMEHEADERSIZE_PREFIX - ZSTD_FRAMEIDSIZE :
+ ZSTD_FRAMEHEADERSIZE_PREFIX;
ZSTD_STATIC_ASSERT(ZSTD_FRAMEHEADERSIZE_PREFIX >= ZSTD_FRAMEIDSIZE);
/* only supports formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless */
assert( (format == ZSTD_f_zstd1) || (format == ZSTD_f_zstd1_magicless) );
@@ -188,10 +104,16 @@ static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
dctx->ddict = NULL;
dctx->ddictLocal = NULL;
+ dctx->dictEnd = NULL;
+ dctx->ddictIsCold = 0;
+ dctx->dictUses = ZSTD_dont_use;
dctx->inBuff = NULL;
dctx->inBuffSize = 0;
dctx->outBuffSize = 0;
dctx->streamStage = zdss_init;
+ dctx->legacyContext = NULL;
+ dctx->previousLegacyVersion = 0;
+ dctx->noForwardProgress = 0;
dctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
}
@@ -215,8 +137,6 @@ ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
{ ZSTD_DCtx* const dctx = (ZSTD_DCtx*)ZSTD_malloc(sizeof(*dctx), customMem);
if (!dctx) return NULL;
dctx->customMem = customMem;
- dctx->legacyContext = NULL;
- dctx->previousLegacyVersion = 0;
ZSTD_initDCtx_internal(dctx);
return dctx;
}
@@ -228,13 +148,20 @@ ZSTD_DCtx* ZSTD_createDCtx(void)
return ZSTD_createDCtx_advanced(ZSTD_defaultCMem);
}
+static void ZSTD_clearDict(ZSTD_DCtx* dctx)
+{
+ ZSTD_freeDDict(dctx->ddictLocal);
+ dctx->ddictLocal = NULL;
+ dctx->ddict = NULL;
+ dctx->dictUses = ZSTD_dont_use;
+}
+
size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
{
if (dctx==NULL) return 0; /* support free on NULL */
- if (dctx->staticSize) return ERROR(memory_allocation); /* not compatible with static DCtx */
+ RETURN_ERROR_IF(dctx->staticSize, memory_allocation, "not compatible with static DCtx");
{ ZSTD_customMem const cMem = dctx->customMem;
- ZSTD_freeDDict(dctx->ddictLocal);
- dctx->ddictLocal = NULL;
+ ZSTD_clearDict(dctx);
ZSTD_free(dctx->inBuff, cMem);
dctx->inBuff = NULL;
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
@@ -265,10 +192,10 @@ void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
* Note 3 : Skippable Frame Identifiers are considered valid. */
unsigned ZSTD_isFrame(const void* buffer, size_t size)
{
- if (size < ZSTD_frameIdSize) return 0;
+ if (size < ZSTD_FRAMEIDSIZE) return 0;
{ U32 const magic = MEM_readLE32(buffer);
if (magic == ZSTD_MAGICNUMBER) return 1;
- if ((magic & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) return 1;
+ if ((magic & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) return 1;
}
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
if (ZSTD_isLegacy(buffer, size)) return 1;
@@ -284,7 +211,7 @@ unsigned ZSTD_isFrame(const void* buffer, size_t size)
static size_t ZSTD_frameHeaderSize_internal(const void* src, size_t srcSize, ZSTD_format_e format)
{
size_t const minInputSize = ZSTD_startingInputLength(format);
- if (srcSize < minInputSize) return ERROR(srcSize_wrong);
+ RETURN_ERROR_IF(srcSize < minInputSize, srcSize_wrong);
{ BYTE const fhd = ((const BYTE*)src)[minInputSize-1];
U32 const dictID= fhd & 3;
@@ -298,38 +225,41 @@ static size_t ZSTD_frameHeaderSize_internal(const void* src, size_t srcSize, ZST
/** ZSTD_frameHeaderSize() :
* srcSize must be >= ZSTD_frameHeaderSize_prefix.
- * @return : size of the Frame Header */
+ * @return : size of the Frame Header,
+ * or an error code (if srcSize is too small) */
size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize)
{
return ZSTD_frameHeaderSize_internal(src, srcSize, ZSTD_f_zstd1);
}
-/** ZSTD_getFrameHeader_internal() :
+/** ZSTD_getFrameHeader_advanced() :
* decode Frame Header, or require larger `srcSize`.
* note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless
* @return : 0, `zfhPtr` is correctly filled,
* >0, `srcSize` is too small, value is wanted `srcSize` amount,
* or an error code, which can be tested using ZSTD_isError() */
-static size_t ZSTD_getFrameHeader_internal(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format)
+size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format)
{
const BYTE* ip = (const BYTE*)src;
size_t const minInputSize = ZSTD_startingInputLength(format);
+ memset(zfhPtr, 0, sizeof(*zfhPtr)); /* not strictly necessary, but static analyzer do not understand that zfhPtr is only going to be read only if return value is zero, since they are 2 different signals */
if (srcSize < minInputSize) return minInputSize;
+ RETURN_ERROR_IF(src==NULL, GENERIC, "invalid parameter");
if ( (format != ZSTD_f_zstd1_magicless)
&& (MEM_readLE32(src) != ZSTD_MAGICNUMBER) ) {
- if ((MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
+ if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
/* skippable frame */
- if (srcSize < ZSTD_skippableHeaderSize)
- return ZSTD_skippableHeaderSize; /* magic number + frame length */
+ if (srcSize < ZSTD_SKIPPABLEHEADERSIZE)
+ return ZSTD_SKIPPABLEHEADERSIZE; /* magic number + frame length */
memset(zfhPtr, 0, sizeof(*zfhPtr));
- zfhPtr->frameContentSize = MEM_readLE32((const char *)src + ZSTD_frameIdSize);
+ zfhPtr->frameContentSize = MEM_readLE32((const char *)src + ZSTD_FRAMEIDSIZE);
zfhPtr->frameType = ZSTD_skippableFrame;
return 0;
}
- return ERROR(prefix_unknown);
+ RETURN_ERROR(prefix_unknown);
}
/* ensure there is enough `srcSize` to fully read/decode frame header */
@@ -347,14 +277,13 @@ static size_t ZSTD_getFrameHeader_internal(ZSTD_frameHeader* zfhPtr, const void*
U64 windowSize = 0;
U32 dictID = 0;
U64 frameContentSize = ZSTD_CONTENTSIZE_UNKNOWN;
- if ((fhdByte & 0x08) != 0)
- return ERROR(frameParameter_unsupported); /* reserved bits, must be zero */
+ RETURN_ERROR_IF((fhdByte & 0x08) != 0, frameParameter_unsupported,
+ "reserved bits, must be zero");
if (!singleSegment) {
BYTE const wlByte = ip[pos++];
U32 const windowLog = (wlByte >> 3) + ZSTD_WINDOWLOG_ABSOLUTEMIN;
- if (windowLog > ZSTD_WINDOWLOG_MAX)
- return ERROR(frameParameter_windowTooLarge);
+ RETURN_ERROR_IF(windowLog > ZSTD_WINDOWLOG_MAX, frameParameter_windowTooLarge);
windowSize = (1ULL << windowLog);
windowSize += (windowSize >> 3) * (wlByte&7);
}
@@ -394,7 +323,7 @@ static size_t ZSTD_getFrameHeader_internal(ZSTD_frameHeader* zfhPtr, const void*
* or an error code, which can be tested using ZSTD_isError() */
size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize)
{
- return ZSTD_getFrameHeader_internal(zfhPtr, src, srcSize, ZSTD_f_zstd1);
+ return ZSTD_getFrameHeader_advanced(zfhPtr, src, srcSize, ZSTD_f_zstd1);
}
@@ -421,6 +350,20 @@ unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize)
} }
}
+static size_t readSkippableFrameSize(void const* src, size_t srcSize)
+{
+ size_t const skippableHeaderSize = ZSTD_SKIPPABLEHEADERSIZE;
+ U32 sizeU32;
+
+ RETURN_ERROR_IF(srcSize < ZSTD_SKIPPABLEHEADERSIZE, srcSize_wrong);
+
+ sizeU32 = MEM_readLE32((BYTE const*)src + ZSTD_FRAMEIDSIZE);
+ RETURN_ERROR_IF((U32)(sizeU32 + ZSTD_SKIPPABLEHEADERSIZE) < sizeU32,
+ frameParameter_unsupported);
+
+ return skippableHeaderSize + sizeU32;
+}
+
/** ZSTD_findDecompressedSize() :
* compatible with legacy mode
* `srcSize` must be the exact length of some number of ZSTD compressed and/or
@@ -430,15 +373,13 @@ unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
{
unsigned long long totalDstSize = 0;
- while (srcSize >= ZSTD_frameHeaderSize_prefix) {
+ while (srcSize >= ZSTD_FRAMEHEADERSIZE_PREFIX) {
U32 const magicNumber = MEM_readLE32(src);
- if ((magicNumber & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
- size_t skippableSize;
- if (srcSize < ZSTD_skippableHeaderSize)
- return ERROR(srcSize_wrong);
- skippableSize = MEM_readLE32((const BYTE *)src + ZSTD_frameIdSize)
- + ZSTD_skippableHeaderSize;
+ if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
+ size_t const skippableSize = readSkippableFrameSize(src, srcSize);
+ if (ZSTD_isError(skippableSize))
+ return skippableSize;
if (srcSize < skippableSize) {
return ZSTD_CONTENTSIZE_ERROR;
}
@@ -471,9 +412,9 @@ unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
}
/** ZSTD_getDecompressedSize() :
-* compatible with legacy mode
-* @return : decompressed size if known, 0 otherwise
- note : 0 can mean any of the following :
+ * compatible with legacy mode
+ * @return : decompressed size if known, 0 otherwise
+ note : 0 can mean any of the following :
- frame content is empty
- decompressed size field is not present in frame header
- frame header unknown / not supported
@@ -487,1241 +428,150 @@ unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize)
/** ZSTD_decodeFrameHeader() :
-* `headerSize` must be the size provided by ZSTD_frameHeaderSize().
-* @return : 0 if success, or an error code, which can be tested using ZSTD_isError() */
+ * `headerSize` must be the size provided by ZSTD_frameHeaderSize().
+ * @return : 0 if success, or an error code, which can be tested using ZSTD_isError() */
static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t headerSize)
{
- size_t const result = ZSTD_getFrameHeader_internal(&(dctx->fParams), src, headerSize, dctx->format);
+ size_t const result = ZSTD_getFrameHeader_advanced(&(dctx->fParams), src, headerSize, dctx->format);
if (ZSTD_isError(result)) return result; /* invalid header */
- if (result>0) return ERROR(srcSize_wrong); /* headerSize too small */
- if (dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID))
- return ERROR(dictionary_wrong);
+ RETURN_ERROR_IF(result>0, srcSize_wrong, "headerSize too small");
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ /* Skip the dictID check in fuzzing mode, because it makes the search
+ * harder.
+ */
+ RETURN_ERROR_IF(dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID),
+ dictionary_wrong);
+#endif
if (dctx->fParams.checksumFlag) XXH64_reset(&dctx->xxhState, 0);
return 0;
}
-
-/*-*************************************************************
- * Block decoding
- ***************************************************************/
-
-/*! ZSTD_getcBlockSize() :
-* Provides the size of compressed block from block header `src` */
-size_t ZSTD_getcBlockSize(const void* src, size_t srcSize,
- blockProperties_t* bpPtr)
-{
- if (srcSize < ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
- { U32 const cBlockHeader = MEM_readLE24(src);
- U32 const cSize = cBlockHeader >> 3;
- bpPtr->lastBlock = cBlockHeader & 1;
- bpPtr->blockType = (blockType_e)((cBlockHeader >> 1) & 3);
- bpPtr->origSize = cSize; /* only useful for RLE */
- if (bpPtr->blockType == bt_rle) return 1;
- if (bpPtr->blockType == bt_reserved) return ERROR(corruption_detected);
- return cSize;
- }
-}
-
-
-static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity,
- const void* src, size_t srcSize)
-{
- if (srcSize > dstCapacity) return ERROR(dstSize_tooSmall);
- memcpy(dst, src, srcSize);
- return srcSize;
-}
-
-
-static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity,
- const void* src, size_t srcSize,
- size_t regenSize)
-{
- if (srcSize != 1) return ERROR(srcSize_wrong);
- if (regenSize > dstCapacity) return ERROR(dstSize_tooSmall);
- memset(dst, *(const BYTE*)src, regenSize);
- return regenSize;
-}
-
-/*! ZSTD_decodeLiteralsBlock() :
- * @return : nb of bytes read from src (< srcSize )
- * note : symbol not declared but exposed for fullbench */
-size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
- const void* src, size_t srcSize) /* note : srcSize < BLOCKSIZE */
-{
- if (srcSize < MIN_CBLOCK_SIZE) return ERROR(corruption_detected);
-
- { const BYTE* const istart = (const BYTE*) src;
- symbolEncodingType_e const litEncType = (symbolEncodingType_e)(istart[0] & 3);
-
- switch(litEncType)
- {
- case set_repeat:
- if (dctx->litEntropy==0) return ERROR(dictionary_corrupted);
- /* fall-through */
- case set_compressed:
- if (srcSize < 5) return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for case 3 */
- { size_t lhSize, litSize, litCSize;
- U32 singleStream=0;
- U32 const lhlCode = (istart[0] >> 2) & 3;
- U32 const lhc = MEM_readLE32(istart);
- switch(lhlCode)
- {
- case 0: case 1: default: /* note : default is impossible, since lhlCode into [0..3] */
- /* 2 - 2 - 10 - 10 */
- singleStream = !lhlCode;
- lhSize = 3;
- litSize = (lhc >> 4) & 0x3FF;
- litCSize = (lhc >> 14) & 0x3FF;
- break;
- case 2:
- /* 2 - 2 - 14 - 14 */
- lhSize = 4;
- litSize = (lhc >> 4) & 0x3FFF;
- litCSize = lhc >> 18;
- break;
- case 3:
- /* 2 - 2 - 18 - 18 */
- lhSize = 5;
- litSize = (lhc >> 4) & 0x3FFFF;
- litCSize = (lhc >> 22) + (istart[4] << 10);
- break;
- }
- if (litSize > ZSTD_BLOCKSIZE_MAX) return ERROR(corruption_detected);
- if (litCSize + lhSize > srcSize) return ERROR(corruption_detected);
-
- if (HUF_isError((litEncType==set_repeat) ?
- ( singleStream ?
- HUF_decompress1X_usingDTable_bmi2(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->HUFptr, dctx->bmi2) :
- HUF_decompress4X_usingDTable_bmi2(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->HUFptr, dctx->bmi2) ) :
- ( singleStream ?
- HUF_decompress1X2_DCtx_wksp_bmi2(dctx->entropy.hufTable, dctx->litBuffer, litSize, istart+lhSize, litCSize,
- dctx->entropy.workspace, sizeof(dctx->entropy.workspace), dctx->bmi2) :
- HUF_decompress4X_hufOnly_wksp_bmi2(dctx->entropy.hufTable, dctx->litBuffer, litSize, istart+lhSize, litCSize,
- dctx->entropy.workspace, sizeof(dctx->entropy.workspace), dctx->bmi2))))
- return ERROR(corruption_detected);
-
- dctx->litPtr = dctx->litBuffer;
- dctx->litSize = litSize;
- dctx->litEntropy = 1;
- if (litEncType==set_compressed) dctx->HUFptr = dctx->entropy.hufTable;
- memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);
- return litCSize + lhSize;
- }
-
- case set_basic:
- { size_t litSize, lhSize;
- U32 const lhlCode = ((istart[0]) >> 2) & 3;
- switch(lhlCode)
- {
- case 0: case 2: default: /* note : default is impossible, since lhlCode into [0..3] */
- lhSize = 1;
- litSize = istart[0] >> 3;
- break;
- case 1:
- lhSize = 2;
- litSize = MEM_readLE16(istart) >> 4;
- break;
- case 3:
- lhSize = 3;
- litSize = MEM_readLE24(istart) >> 4;
- break;
- }
-
- if (lhSize+litSize+WILDCOPY_OVERLENGTH > srcSize) { /* risk reading beyond src buffer with wildcopy */
- if (litSize+lhSize > srcSize) return ERROR(corruption_detected);
- memcpy(dctx->litBuffer, istart+lhSize, litSize);
- dctx->litPtr = dctx->litBuffer;
- dctx->litSize = litSize;
- memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);
- return lhSize+litSize;
- }
- /* direct reference into compressed stream */
- dctx->litPtr = istart+lhSize;
- dctx->litSize = litSize;
- return lhSize+litSize;
- }
-
- case set_rle:
- { U32 const lhlCode = ((istart[0]) >> 2) & 3;
- size_t litSize, lhSize;
- switch(lhlCode)
- {
- case 0: case 2: default: /* note : default is impossible, since lhlCode into [0..3] */
- lhSize = 1;
- litSize = istart[0] >> 3;
- break;
- case 1:
- lhSize = 2;
- litSize = MEM_readLE16(istart) >> 4;
- break;
- case 3:
- lhSize = 3;
- litSize = MEM_readLE24(istart) >> 4;
- if (srcSize<4) return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4 */
- break;
- }
- if (litSize > ZSTD_BLOCKSIZE_MAX) return ERROR(corruption_detected);
- memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH);
- dctx->litPtr = dctx->litBuffer;
- dctx->litSize = litSize;
- return lhSize+1;
- }
- default:
- return ERROR(corruption_detected); /* impossible */
- }
- }
-}
-
-/* Default FSE distribution tables.
- * These are pre-calculated FSE decoding tables using default distributions as defined in specification :
- * https://github.com/facebook/zstd/blob/master/doc/zstd_compression_format.md#default-distributions
- * They were generated programmatically with following method :
- * - start from default distributions, present in /lib/common/zstd_internal.h
- * - generate tables normally, using ZSTD_buildFSETable()
- * - printout the content of tables
- * - pretify output, report below, test with fuzzer to ensure it's correct */
-
-/* Default FSE distribution table for Literal Lengths */
-static const ZSTD_seqSymbol LL_defaultDTable[(1<<LL_DEFAULTNORMLOG)+1] = {
- { 1, 1, 1, LL_DEFAULTNORMLOG}, /* header : fastMode, tableLog */
- /* nextState, nbAddBits, nbBits, baseVal */
- { 0, 0, 4, 0}, { 16, 0, 4, 0},
- { 32, 0, 5, 1}, { 0, 0, 5, 3},
- { 0, 0, 5, 4}, { 0, 0, 5, 6},
- { 0, 0, 5, 7}, { 0, 0, 5, 9},
- { 0, 0, 5, 10}, { 0, 0, 5, 12},
- { 0, 0, 6, 14}, { 0, 1, 5, 16},
- { 0, 1, 5, 20}, { 0, 1, 5, 22},
- { 0, 2, 5, 28}, { 0, 3, 5, 32},
- { 0, 4, 5, 48}, { 32, 6, 5, 64},
- { 0, 7, 5, 128}, { 0, 8, 6, 256},
- { 0, 10, 6, 1024}, { 0, 12, 6, 4096},
- { 32, 0, 4, 0}, { 0, 0, 4, 1},
- { 0, 0, 5, 2}, { 32, 0, 5, 4},
- { 0, 0, 5, 5}, { 32, 0, 5, 7},
- { 0, 0, 5, 8}, { 32, 0, 5, 10},
- { 0, 0, 5, 11}, { 0, 0, 6, 13},
- { 32, 1, 5, 16}, { 0, 1, 5, 18},
- { 32, 1, 5, 22}, { 0, 2, 5, 24},
- { 32, 3, 5, 32}, { 0, 3, 5, 40},
- { 0, 6, 4, 64}, { 16, 6, 4, 64},
- { 32, 7, 5, 128}, { 0, 9, 6, 512},
- { 0, 11, 6, 2048}, { 48, 0, 4, 0},
- { 16, 0, 4, 1}, { 32, 0, 5, 2},
- { 32, 0, 5, 3}, { 32, 0, 5, 5},
- { 32, 0, 5, 6}, { 32, 0, 5, 8},
- { 32, 0, 5, 9}, { 32, 0, 5, 11},
- { 32, 0, 5, 12}, { 0, 0, 6, 15},
- { 32, 1, 5, 18}, { 32, 1, 5, 20},
- { 32, 2, 5, 24}, { 32, 2, 5, 28},
- { 32, 3, 5, 40}, { 32, 4, 5, 48},
- { 0, 16, 6,65536}, { 0, 15, 6,32768},
- { 0, 14, 6,16384}, { 0, 13, 6, 8192},
-}; /* LL_defaultDTable */
-
-/* Default FSE distribution table for Offset Codes */
-static const ZSTD_seqSymbol OF_defaultDTable[(1<<OF_DEFAULTNORMLOG)+1] = {
- { 1, 1, 1, OF_DEFAULTNORMLOG}, /* header : fastMode, tableLog */
- /* nextState, nbAddBits, nbBits, baseVal */
- { 0, 0, 5, 0}, { 0, 6, 4, 61},
- { 0, 9, 5, 509}, { 0, 15, 5,32765},
- { 0, 21, 5,2097149}, { 0, 3, 5, 5},
- { 0, 7, 4, 125}, { 0, 12, 5, 4093},
- { 0, 18, 5,262141}, { 0, 23, 5,8388605},
- { 0, 5, 5, 29}, { 0, 8, 4, 253},
- { 0, 14, 5,16381}, { 0, 20, 5,1048573},
- { 0, 2, 5, 1}, { 16, 7, 4, 125},
- { 0, 11, 5, 2045}, { 0, 17, 5,131069},
- { 0, 22, 5,4194301}, { 0, 4, 5, 13},
- { 16, 8, 4, 253}, { 0, 13, 5, 8189},
- { 0, 19, 5,524285}, { 0, 1, 5, 1},
- { 16, 6, 4, 61}, { 0, 10, 5, 1021},
- { 0, 16, 5,65533}, { 0, 28, 5,268435453},
- { 0, 27, 5,134217725}, { 0, 26, 5,67108861},
- { 0, 25, 5,33554429}, { 0, 24, 5,16777213},
-}; /* OF_defaultDTable */
-
-
-/* Default FSE distribution table for Match Lengths */
-static const ZSTD_seqSymbol ML_defaultDTable[(1<<ML_DEFAULTNORMLOG)+1] = {
- { 1, 1, 1, ML_DEFAULTNORMLOG}, /* header : fastMode, tableLog */
- /* nextState, nbAddBits, nbBits, baseVal */
- { 0, 0, 6, 3}, { 0, 0, 4, 4},
- { 32, 0, 5, 5}, { 0, 0, 5, 6},
- { 0, 0, 5, 8}, { 0, 0, 5, 9},
- { 0, 0, 5, 11}, { 0, 0, 6, 13},
- { 0, 0, 6, 16}, { 0, 0, 6, 19},
- { 0, 0, 6, 22}, { 0, 0, 6, 25},
- { 0, 0, 6, 28}, { 0, 0, 6, 31},
- { 0, 0, 6, 34}, { 0, 1, 6, 37},
- { 0, 1, 6, 41}, { 0, 2, 6, 47},
- { 0, 3, 6, 59}, { 0, 4, 6, 83},
- { 0, 7, 6, 131}, { 0, 9, 6, 515},
- { 16, 0, 4, 4}, { 0, 0, 4, 5},
- { 32, 0, 5, 6}, { 0, 0, 5, 7},
- { 32, 0, 5, 9}, { 0, 0, 5, 10},
- { 0, 0, 6, 12}, { 0, 0, 6, 15},
- { 0, 0, 6, 18}, { 0, 0, 6, 21},
- { 0, 0, 6, 24}, { 0, 0, 6, 27},
- { 0, 0, 6, 30}, { 0, 0, 6, 33},
- { 0, 1, 6, 35}, { 0, 1, 6, 39},
- { 0, 2, 6, 43}, { 0, 3, 6, 51},
- { 0, 4, 6, 67}, { 0, 5, 6, 99},
- { 0, 8, 6, 259}, { 32, 0, 4, 4},
- { 48, 0, 4, 4}, { 16, 0, 4, 5},
- { 32, 0, 5, 7}, { 32, 0, 5, 8},
- { 32, 0, 5, 10}, { 32, 0, 5, 11},
- { 0, 0, 6, 14}, { 0, 0, 6, 17},
- { 0, 0, 6, 20}, { 0, 0, 6, 23},
- { 0, 0, 6, 26}, { 0, 0, 6, 29},
- { 0, 0, 6, 32}, { 0, 16, 6,65539},
- { 0, 15, 6,32771}, { 0, 14, 6,16387},
- { 0, 13, 6, 8195}, { 0, 12, 6, 4099},
- { 0, 11, 6, 2051}, { 0, 10, 6, 1027},
-}; /* ML_defaultDTable */
-
-
-static void ZSTD_buildSeqTable_rle(ZSTD_seqSymbol* dt, U32 baseValue, U32 nbAddBits)
-{
- void* ptr = dt;
- ZSTD_seqSymbol_header* const DTableH = (ZSTD_seqSymbol_header*)ptr;
- ZSTD_seqSymbol* const cell = dt + 1;
-
- DTableH->tableLog = 0;
- DTableH->fastMode = 0;
-
- cell->nbBits = 0;
- cell->nextState = 0;
- assert(nbAddBits < 255);
- cell->nbAdditionalBits = (BYTE)nbAddBits;
- cell->baseValue = baseValue;
-}
-
-
-/* ZSTD_buildFSETable() :
- * generate FSE decoding table for one symbol (ll, ml or off) */
-static void
-ZSTD_buildFSETable(ZSTD_seqSymbol* dt,
- const short* normalizedCounter, unsigned maxSymbolValue,
- const U32* baseValue, const U32* nbAdditionalBits,
- unsigned tableLog)
-{
- ZSTD_seqSymbol* const tableDecode = dt+1;
- U16 symbolNext[MaxSeq+1];
-
- U32 const maxSV1 = maxSymbolValue + 1;
- U32 const tableSize = 1 << tableLog;
- U32 highThreshold = tableSize-1;
-
- /* Sanity Checks */
- assert(maxSymbolValue <= MaxSeq);
- assert(tableLog <= MaxFSELog);
-
- /* Init, lay down lowprob symbols */
- { ZSTD_seqSymbol_header DTableH;
- DTableH.tableLog = tableLog;
- DTableH.fastMode = 1;
- { S16 const largeLimit= (S16)(1 << (tableLog-1));
- U32 s;
- for (s=0; s<maxSV1; s++) {
- if (normalizedCounter[s]==-1) {
- tableDecode[highThreshold--].baseValue = s;
- symbolNext[s] = 1;
- } else {
- if (normalizedCounter[s] >= largeLimit) DTableH.fastMode=0;
- symbolNext[s] = normalizedCounter[s];
- } } }
- memcpy(dt, &DTableH, sizeof(DTableH));
- }
-
- /* Spread symbols */
- { U32 const tableMask = tableSize-1;
- U32 const step = FSE_TABLESTEP(tableSize);
- U32 s, position = 0;
- for (s=0; s<maxSV1; s++) {
- int i;
- for (i=0; i<normalizedCounter[s]; i++) {
- tableDecode[position].baseValue = s;
- position = (position + step) & tableMask;
- while (position > highThreshold) position = (position + step) & tableMask; /* lowprob area */
- } }
- assert(position == 0); /* position must reach all cells once, otherwise normalizedCounter is incorrect */
- }
-
- /* Build Decoding table */
- { U32 u;
- for (u=0; u<tableSize; u++) {
- U32 const symbol = tableDecode[u].baseValue;
- U32 const nextState = symbolNext[symbol]++;
- tableDecode[u].nbBits = (BYTE) (tableLog - BIT_highbit32(nextState) );
- tableDecode[u].nextState = (U16) ( (nextState << tableDecode[u].nbBits) - tableSize);
- assert(nbAdditionalBits[symbol] < 255);
- tableDecode[u].nbAdditionalBits = (BYTE)nbAdditionalBits[symbol];
- tableDecode[u].baseValue = baseValue[symbol];
- } }
-}
-
-
-/*! ZSTD_buildSeqTable() :
- * @return : nb bytes read from src,
- * or an error code if it fails */
-static size_t ZSTD_buildSeqTable(ZSTD_seqSymbol* DTableSpace, const ZSTD_seqSymbol** DTablePtr,
- symbolEncodingType_e type, U32 max, U32 maxLog,
- const void* src, size_t srcSize,
- const U32* baseValue, const U32* nbAdditionalBits,
- const ZSTD_seqSymbol* defaultTable, U32 flagRepeatTable)
-{
- switch(type)
- {
- case set_rle :
- if (!srcSize) return ERROR(srcSize_wrong);
- if ( (*(const BYTE*)src) > max) return ERROR(corruption_detected);
- { U32 const symbol = *(const BYTE*)src;
- U32 const baseline = baseValue[symbol];
- U32 const nbBits = nbAdditionalBits[symbol];
- ZSTD_buildSeqTable_rle(DTableSpace, baseline, nbBits);
- }
- *DTablePtr = DTableSpace;
- return 1;
- case set_basic :
- *DTablePtr = defaultTable;
- return 0;
- case set_repeat:
- if (!flagRepeatTable) return ERROR(corruption_detected);
- return 0;
- case set_compressed :
- { U32 tableLog;
- S16 norm[MaxSeq+1];
- size_t const headerSize = FSE_readNCount(norm, &max, &tableLog, src, srcSize);
- if (FSE_isError(headerSize)) return ERROR(corruption_detected);
- if (tableLog > maxLog) return ERROR(corruption_detected);
- ZSTD_buildFSETable(DTableSpace, norm, max, baseValue, nbAdditionalBits, tableLog);
- *DTablePtr = DTableSpace;
- return headerSize;
- }
- default : /* impossible */
- assert(0);
- return ERROR(GENERIC);
- }
-}
-
-static const U32 LL_base[MaxLL+1] = {
- 0, 1, 2, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 18, 20, 22, 24, 28, 32, 40,
- 48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000,
- 0x2000, 0x4000, 0x8000, 0x10000 };
-
-static const U32 OF_base[MaxOff+1] = {
- 0, 1, 1, 5, 0xD, 0x1D, 0x3D, 0x7D,
- 0xFD, 0x1FD, 0x3FD, 0x7FD, 0xFFD, 0x1FFD, 0x3FFD, 0x7FFD,
- 0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD,
- 0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD, 0x1FFFFFFD, 0x3FFFFFFD, 0x7FFFFFFD };
-
-static const U32 OF_bits[MaxOff+1] = {
- 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 };
-
-static const U32 ML_base[MaxML+1] = {
- 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, 37, 39, 41, 43, 47, 51, 59,
- 67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803,
- 0x1003, 0x2003, 0x4003, 0x8003, 0x10003 };
-
-
-size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
- const void* src, size_t srcSize)
-{
- const BYTE* const istart = (const BYTE* const)src;
- const BYTE* const iend = istart + srcSize;
- const BYTE* ip = istart;
- DEBUGLOG(5, "ZSTD_decodeSeqHeaders");
-
- /* check */
- if (srcSize < MIN_SEQUENCES_SIZE) return ERROR(srcSize_wrong);
-
- /* SeqHead */
- { int nbSeq = *ip++;
- if (!nbSeq) { *nbSeqPtr=0; return 1; }
- if (nbSeq > 0x7F) {
- if (nbSeq == 0xFF) {
- if (ip+2 > iend) return ERROR(srcSize_wrong);
- nbSeq = MEM_readLE16(ip) + LONGNBSEQ, ip+=2;
- } else {
- if (ip >= iend) return ERROR(srcSize_wrong);
- nbSeq = ((nbSeq-0x80)<<8) + *ip++;
- }
- }
- *nbSeqPtr = nbSeq;
- }
-
- /* FSE table descriptors */
- if (ip+4 > iend) return ERROR(srcSize_wrong); /* minimum possible size */
- { symbolEncodingType_e const LLtype = (symbolEncodingType_e)(*ip >> 6);
- symbolEncodingType_e const OFtype = (symbolEncodingType_e)((*ip >> 4) & 3);
- symbolEncodingType_e const MLtype = (symbolEncodingType_e)((*ip >> 2) & 3);
- ip++;
-
- /* Build DTables */
- { size_t const llhSize = ZSTD_buildSeqTable(dctx->entropy.LLTable, &dctx->LLTptr,
- LLtype, MaxLL, LLFSELog,
- ip, iend-ip,
- LL_base, LL_bits,
- LL_defaultDTable, dctx->fseEntropy);
- if (ZSTD_isError(llhSize)) return ERROR(corruption_detected);
- ip += llhSize;
- }
-
- { size_t const ofhSize = ZSTD_buildSeqTable(dctx->entropy.OFTable, &dctx->OFTptr,
- OFtype, MaxOff, OffFSELog,
- ip, iend-ip,
- OF_base, OF_bits,
- OF_defaultDTable, dctx->fseEntropy);
- if (ZSTD_isError(ofhSize)) return ERROR(corruption_detected);
- ip += ofhSize;
- }
-
- { size_t const mlhSize = ZSTD_buildSeqTable(dctx->entropy.MLTable, &dctx->MLTptr,
- MLtype, MaxML, MLFSELog,
- ip, iend-ip,
- ML_base, ML_bits,
- ML_defaultDTable, dctx->fseEntropy);
- if (ZSTD_isError(mlhSize)) return ERROR(corruption_detected);
- ip += mlhSize;
- }
- }
-
- return ip-istart;
-}
-
-
-typedef struct {
- size_t litLength;
- size_t matchLength;
- size_t offset;
- const BYTE* match;
-} seq_t;
-
-typedef struct {
- size_t state;
- const ZSTD_seqSymbol* table;
-} ZSTD_fseState;
-
-typedef struct {
- BIT_DStream_t DStream;
- ZSTD_fseState stateLL;
- ZSTD_fseState stateOffb;
- ZSTD_fseState stateML;
- size_t prevOffset[ZSTD_REP_NUM];
- const BYTE* prefixStart;
- const BYTE* dictEnd;
- size_t pos;
-} seqState_t;
-
-
-FORCE_NOINLINE
-size_t ZSTD_execSequenceLast7(BYTE* op,
- BYTE* const oend, seq_t sequence,
- const BYTE** litPtr, const BYTE* const litLimit,
- const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)
-{
- BYTE* const oLitEnd = op + sequence.litLength;
- size_t const sequenceLength = sequence.litLength + sequence.matchLength;
- BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
- BYTE* const oend_w = oend - WILDCOPY_OVERLENGTH;
- const BYTE* const iLitEnd = *litPtr + sequence.litLength;
- const BYTE* match = oLitEnd - sequence.offset;
-
- /* check */
- if (oMatchEnd>oend) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */
- if (iLitEnd > litLimit) return ERROR(corruption_detected); /* over-read beyond lit buffer */
- if (oLitEnd <= oend_w) return ERROR(GENERIC); /* Precondition */
-
- /* copy literals */
- if (op < oend_w) {
- ZSTD_wildcopy(op, *litPtr, oend_w - op);
- *litPtr += oend_w - op;
- op = oend_w;
- }
- while (op < oLitEnd) *op++ = *(*litPtr)++;
-
- /* copy Match */
- if (sequence.offset > (size_t)(oLitEnd - base)) {
- /* offset beyond prefix */
- if (sequence.offset > (size_t)(oLitEnd - vBase)) return ERROR(corruption_detected);
- match = dictEnd - (base-match);
- if (match + sequence.matchLength <= dictEnd) {
- memmove(oLitEnd, match, sequence.matchLength);
- return sequenceLength;
- }
- /* span extDict & currentPrefixSegment */
- { size_t const length1 = dictEnd - match;
- memmove(oLitEnd, match, length1);
- op = oLitEnd + length1;
- sequence.matchLength -= length1;
- match = base;
- } }
- while (op < oMatchEnd) *op++ = *match++;
- return sequenceLength;
-}
-
-
-HINT_INLINE
-size_t ZSTD_execSequence(BYTE* op,
- BYTE* const oend, seq_t sequence,
- const BYTE** litPtr, const BYTE* const litLimit,
- const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)
+static ZSTD_frameSizeInfo ZSTD_errorFrameSizeInfo(size_t ret)
{
- BYTE* const oLitEnd = op + sequence.litLength;
- size_t const sequenceLength = sequence.litLength + sequence.matchLength;
- BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
- BYTE* const oend_w = oend - WILDCOPY_OVERLENGTH;
- const BYTE* const iLitEnd = *litPtr + sequence.litLength;
- const BYTE* match = oLitEnd - sequence.offset;
-
- /* check */
- if (oMatchEnd>oend) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */
- if (iLitEnd > litLimit) return ERROR(corruption_detected); /* over-read beyond lit buffer */
- if (oLitEnd>oend_w) return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit, base, vBase, dictEnd);
-
- /* copy Literals */
- ZSTD_copy8(op, *litPtr);
- if (sequence.litLength > 8)
- ZSTD_wildcopy(op+8, (*litPtr)+8, sequence.litLength - 8); /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */
- op = oLitEnd;
- *litPtr = iLitEnd; /* update for next sequence */
-
- /* copy Match */
- if (sequence.offset > (size_t)(oLitEnd - base)) {
- /* offset beyond prefix -> go into extDict */
- if (sequence.offset > (size_t)(oLitEnd - vBase))
- return ERROR(corruption_detected);
- match = dictEnd + (match - base);
- if (match + sequence.matchLength <= dictEnd) {
- memmove(oLitEnd, match, sequence.matchLength);
- return sequenceLength;
- }
- /* span extDict & currentPrefixSegment */
- { size_t const length1 = dictEnd - match;
- memmove(oLitEnd, match, length1);
- op = oLitEnd + length1;
- sequence.matchLength -= length1;
- match = base;
- if (op > oend_w || sequence.matchLength < MINMATCH) {
- U32 i;
- for (i = 0; i < sequence.matchLength; ++i) op[i] = match[i];
- return sequenceLength;
- }
- } }
- /* Requirement: op <= oend_w && sequence.matchLength >= MINMATCH */
-
- /* match within prefix */
- if (sequence.offset < 8) {
- /* close range match, overlap */
- static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
- static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* subtracted */
- int const sub2 = dec64table[sequence.offset];
- op[0] = match[0];
- op[1] = match[1];
- op[2] = match[2];
- op[3] = match[3];
- match += dec32table[sequence.offset];
- ZSTD_copy4(op+4, match);
- match -= sub2;
- } else {
- ZSTD_copy8(op, match);
- }
- op += 8; match += 8;
-
- if (oMatchEnd > oend-(16-MINMATCH)) {
- if (op < oend_w) {
- ZSTD_wildcopy(op, match, oend_w - op);
- match += oend_w - op;
- op = oend_w;
- }
- while (op < oMatchEnd) *op++ = *match++;
- } else {
- ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8); /* works even if matchLength < 8 */
- }
- return sequenceLength;
+ ZSTD_frameSizeInfo frameSizeInfo;
+ frameSizeInfo.compressedSize = ret;
+ frameSizeInfo.decompressedBound = ZSTD_CONTENTSIZE_ERROR;
+ return frameSizeInfo;
}
-
-HINT_INLINE
-size_t ZSTD_execSequenceLong(BYTE* op,
- BYTE* const oend, seq_t sequence,
- const BYTE** litPtr, const BYTE* const litLimit,
- const BYTE* const prefixStart, const BYTE* const dictStart, const BYTE* const dictEnd)
+static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize)
{
- BYTE* const oLitEnd = op + sequence.litLength;
- size_t const sequenceLength = sequence.litLength + sequence.matchLength;
- BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
- BYTE* const oend_w = oend - WILDCOPY_OVERLENGTH;
- const BYTE* const iLitEnd = *litPtr + sequence.litLength;
- const BYTE* match = sequence.match;
+ ZSTD_frameSizeInfo frameSizeInfo;
+ memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo));
- /* check */
- if (oMatchEnd > oend) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */
- if (iLitEnd > litLimit) return ERROR(corruption_detected); /* over-read beyond lit buffer */
- if (oLitEnd > oend_w) return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit, prefixStart, dictStart, dictEnd);
-
- /* copy Literals */
- ZSTD_copy8(op, *litPtr); /* note : op <= oLitEnd <= oend_w == oend - 8 */
- if (sequence.litLength > 8)
- ZSTD_wildcopy(op+8, (*litPtr)+8, sequence.litLength - 8); /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */
- op = oLitEnd;
- *litPtr = iLitEnd; /* update for next sequence */
-
- /* copy Match */
- if (sequence.offset > (size_t)(oLitEnd - prefixStart)) {
- /* offset beyond prefix */
- if (sequence.offset > (size_t)(oLitEnd - dictStart)) return ERROR(corruption_detected);
- if (match + sequence.matchLength <= dictEnd) {
- memmove(oLitEnd, match, sequence.matchLength);
- return sequenceLength;
- }
- /* span extDict & currentPrefixSegment */
- { size_t const length1 = dictEnd - match;
- memmove(oLitEnd, match, length1);
- op = oLitEnd + length1;
- sequence.matchLength -= length1;
- match = prefixStart;
- if (op > oend_w || sequence.matchLength < MINMATCH) {
- U32 i;
- for (i = 0; i < sequence.matchLength; ++i) op[i] = match[i];
- return sequenceLength;
- }
- } }
- assert(op <= oend_w);
- assert(sequence.matchLength >= MINMATCH);
-
- /* match within prefix */
- if (sequence.offset < 8) {
- /* close range match, overlap */
- static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
- static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* subtracted */
- int const sub2 = dec64table[sequence.offset];
- op[0] = match[0];
- op[1] = match[1];
- op[2] = match[2];
- op[3] = match[3];
- match += dec32table[sequence.offset];
- ZSTD_copy4(op+4, match);
- match -= sub2;
- } else {
- ZSTD_copy8(op, match);
- }
- op += 8; match += 8;
+#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
+ if (ZSTD_isLegacy(src, srcSize))
+ return ZSTD_findFrameSizeInfoLegacy(src, srcSize);
+#endif
- if (oMatchEnd > oend-(16-MINMATCH)) {
- if (op < oend_w) {
- ZSTD_wildcopy(op, match, oend_w - op);
- match += oend_w - op;
- op = oend_w;
- }
- while (op < oMatchEnd) *op++ = *match++;
+ if ((srcSize >= ZSTD_SKIPPABLEHEADERSIZE)
+ && (MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
+ frameSizeInfo.compressedSize = readSkippableFrameSize(src, srcSize);
+ return frameSizeInfo;
} else {
- ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8); /* works even if matchLength < 8 */
- }
- return sequenceLength;
-}
-
-static void
-ZSTD_initFseState(ZSTD_fseState* DStatePtr, BIT_DStream_t* bitD, const ZSTD_seqSymbol* dt)
-{
- const void* ptr = dt;
- const ZSTD_seqSymbol_header* const DTableH = (const ZSTD_seqSymbol_header*)ptr;
- DStatePtr->state = BIT_readBits(bitD, DTableH->tableLog);
- DEBUGLOG(6, "ZSTD_initFseState : val=%u using %u bits",
- (U32)DStatePtr->state, DTableH->tableLog);
- BIT_reloadDStream(bitD);
- DStatePtr->table = dt + 1;
-}
-
-FORCE_INLINE_TEMPLATE void
-ZSTD_updateFseState(ZSTD_fseState* DStatePtr, BIT_DStream_t* bitD)
-{
- ZSTD_seqSymbol const DInfo = DStatePtr->table[DStatePtr->state];
- U32 const nbBits = DInfo.nbBits;
- size_t const lowBits = BIT_readBits(bitD, nbBits);
- DStatePtr->state = DInfo.nextState + lowBits;
-}
-
-/* We need to add at most (ZSTD_WINDOWLOG_MAX_32 - 1) bits to read the maximum
- * offset bits. But we can only read at most (STREAM_ACCUMULATOR_MIN_32 - 1)
- * bits before reloading. This value is the maximum number of bytes we read
- * after reloading when we are decoding long offets.
- */
-#define LONG_OFFSETS_MAX_EXTRA_BITS_32 \
- (ZSTD_WINDOWLOG_MAX_32 > STREAM_ACCUMULATOR_MIN_32 \
- ? ZSTD_WINDOWLOG_MAX_32 - STREAM_ACCUMULATOR_MIN_32 \
- : 0)
-
-typedef enum { ZSTD_lo_isRegularOffset, ZSTD_lo_isLongOffset=1 } ZSTD_longOffset_e;
-
-FORCE_INLINE_TEMPLATE seq_t
-ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets)
-{
- seq_t seq;
- U32 const llBits = seqState->stateLL.table[seqState->stateLL.state].nbAdditionalBits;
- U32 const mlBits = seqState->stateML.table[seqState->stateML.state].nbAdditionalBits;
- U32 const ofBits = seqState->stateOffb.table[seqState->stateOffb.state].nbAdditionalBits;
- U32 const totalBits = llBits+mlBits+ofBits;
- U32 const llBase = seqState->stateLL.table[seqState->stateLL.state].baseValue;
- U32 const mlBase = seqState->stateML.table[seqState->stateML.state].baseValue;
- U32 const ofBase = seqState->stateOffb.table[seqState->stateOffb.state].baseValue;
-
- /* sequence */
- { size_t offset;
- if (!ofBits)
- offset = 0;
- else {
- ZSTD_STATIC_ASSERT(ZSTD_lo_isLongOffset == 1);
- ZSTD_STATIC_ASSERT(LONG_OFFSETS_MAX_EXTRA_BITS_32 == 5);
- assert(ofBits <= MaxOff);
- if (MEM_32bits() && longOffsets && (ofBits >= STREAM_ACCUMULATOR_MIN_32)) {
- U32 const extraBits = ofBits - MIN(ofBits, 32 - seqState->DStream.bitsConsumed);
- offset = ofBase + (BIT_readBitsFast(&seqState->DStream, ofBits - extraBits) << extraBits);
- BIT_reloadDStream(&seqState->DStream);
- if (extraBits) offset += BIT_readBitsFast(&seqState->DStream, extraBits);
- assert(extraBits <= LONG_OFFSETS_MAX_EXTRA_BITS_32); /* to avoid another reload */
- } else {
- offset = ofBase + BIT_readBitsFast(&seqState->DStream, ofBits/*>0*/); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */
- if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream);
- }
- }
+ const BYTE* ip = (const BYTE*)src;
+ const BYTE* const ipstart = ip;
+ size_t remainingSize = srcSize;
+ size_t nbBlocks = 0;
+ ZSTD_frameHeader zfh;
- if (ofBits <= 1) {
- offset += (llBase==0);
- if (offset) {
- size_t temp = (offset==3) ? seqState->prevOffset[0] - 1 : seqState->prevOffset[offset];
- temp += !temp; /* 0 is not valid; input is corrupted; force offset to 1 */
- if (offset != 1) seqState->prevOffset[2] = seqState->prevOffset[1];
- seqState->prevOffset[1] = seqState->prevOffset[0];
- seqState->prevOffset[0] = offset = temp;
- } else { /* offset == 0 */
- offset = seqState->prevOffset[0];
- }
- } else {
- seqState->prevOffset[2] = seqState->prevOffset[1];
- seqState->prevOffset[1] = seqState->prevOffset[0];
- seqState->prevOffset[0] = offset;
+ /* Extract Frame Header */
+ { size_t const ret = ZSTD_getFrameHeader(&zfh, src, srcSize);
+ if (ZSTD_isError(ret))
+ return ZSTD_errorFrameSizeInfo(ret);
+ if (ret > 0)
+ return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));
}
- seq.offset = offset;
- }
-
- seq.matchLength = mlBase
- + ((mlBits>0) ? BIT_readBitsFast(&seqState->DStream, mlBits/*>0*/) : 0); /* <= 16 bits */
- if (MEM_32bits() && (mlBits+llBits >= STREAM_ACCUMULATOR_MIN_32-LONG_OFFSETS_MAX_EXTRA_BITS_32))
- BIT_reloadDStream(&seqState->DStream);
- if (MEM_64bits() && (totalBits >= STREAM_ACCUMULATOR_MIN_64-(LLFSELog+MLFSELog+OffFSELog)))
- BIT_reloadDStream(&seqState->DStream);
- /* Ensure there are enough bits to read the rest of data in 64-bit mode. */
- ZSTD_STATIC_ASSERT(16+LLFSELog+MLFSELog+OffFSELog < STREAM_ACCUMULATOR_MIN_64);
-
- seq.litLength = llBase
- + ((llBits>0) ? BIT_readBitsFast(&seqState->DStream, llBits/*>0*/) : 0); /* <= 16 bits */
- if (MEM_32bits())
- BIT_reloadDStream(&seqState->DStream);
-
- DEBUGLOG(6, "seq: litL=%u, matchL=%u, offset=%u",
- (U32)seq.litLength, (U32)seq.matchLength, (U32)seq.offset);
-
- /* ANS state update */
- ZSTD_updateFseState(&seqState->stateLL, &seqState->DStream); /* <= 9 bits */
- ZSTD_updateFseState(&seqState->stateML, &seqState->DStream); /* <= 9 bits */
- if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream); /* <= 18 bits */
- ZSTD_updateFseState(&seqState->stateOffb, &seqState->DStream); /* <= 8 bits */
-
- return seq;
-}
-
-FORCE_INLINE_TEMPLATE size_t
-ZSTD_decompressSequences_body( ZSTD_DCtx* dctx,
- void* dst, size_t maxDstSize,
- const void* seqStart, size_t seqSize, int nbSeq,
- const ZSTD_longOffset_e isLongOffset)
-{
- const BYTE* ip = (const BYTE*)seqStart;
- const BYTE* const iend = ip + seqSize;
- BYTE* const ostart = (BYTE* const)dst;
- BYTE* const oend = ostart + maxDstSize;
- BYTE* op = ostart;
- const BYTE* litPtr = dctx->litPtr;
- const BYTE* const litEnd = litPtr + dctx->litSize;
- const BYTE* const base = (const BYTE*) (dctx->base);
- const BYTE* const vBase = (const BYTE*) (dctx->vBase);
- const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);
- DEBUGLOG(5, "ZSTD_decompressSequences");
-
- /* Regen sequences */
- if (nbSeq) {
- seqState_t seqState;
- dctx->fseEntropy = 1;
- { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }
- CHECK_E(BIT_initDStream(&seqState.DStream, ip, iend-ip), corruption_detected);
- ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
- ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
- ZSTD_initFseState(&seqState.stateML, &seqState.DStream, dctx->MLTptr);
-
- for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && nbSeq ; ) {
- nbSeq--;
- { seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset);
- size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litEnd, base, vBase, dictEnd);
- DEBUGLOG(6, "regenerated sequence size : %u", (U32)oneSeqSize);
- if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
- op += oneSeqSize;
- } }
-
- /* check if reached exact end */
- DEBUGLOG(5, "ZSTD_decompressSequences: after decode loop, remaining nbSeq : %i", nbSeq);
- if (nbSeq) return ERROR(corruption_detected);
- /* save reps for next block */
- { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]); }
- }
-
- /* last literal segment */
- { size_t const lastLLSize = litEnd - litPtr;
- if (lastLLSize > (size_t)(oend-op)) return ERROR(dstSize_tooSmall);
- memcpy(op, litPtr, lastLLSize);
- op += lastLLSize;
- }
- return op-ostart;
-}
-
-static size_t
-ZSTD_decompressSequences_default(ZSTD_DCtx* dctx,
- void* dst, size_t maxDstSize,
- const void* seqStart, size_t seqSize, int nbSeq,
- const ZSTD_longOffset_e isLongOffset)
-{
- return ZSTD_decompressSequences_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);
-}
+ ip += zfh.headerSize;
+ remainingSize -= zfh.headerSize;
+ /* Iterate over each block */
+ while (1) {
+ blockProperties_t blockProperties;
+ size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
+ if (ZSTD_isError(cBlockSize))
+ return ZSTD_errorFrameSizeInfo(cBlockSize);
+ if (ZSTD_blockHeaderSize + cBlockSize > remainingSize)
+ return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));
-FORCE_INLINE_TEMPLATE seq_t
-ZSTD_decodeSequenceLong(seqState_t* seqState, ZSTD_longOffset_e const longOffsets)
-{
- seq_t seq;
- U32 const llBits = seqState->stateLL.table[seqState->stateLL.state].nbAdditionalBits;
- U32 const mlBits = seqState->stateML.table[seqState->stateML.state].nbAdditionalBits;
- U32 const ofBits = seqState->stateOffb.table[seqState->stateOffb.state].nbAdditionalBits;
- U32 const totalBits = llBits+mlBits+ofBits;
- U32 const llBase = seqState->stateLL.table[seqState->stateLL.state].baseValue;
- U32 const mlBase = seqState->stateML.table[seqState->stateML.state].baseValue;
- U32 const ofBase = seqState->stateOffb.table[seqState->stateOffb.state].baseValue;
+ ip += ZSTD_blockHeaderSize + cBlockSize;
+ remainingSize -= ZSTD_blockHeaderSize + cBlockSize;
+ nbBlocks++;
- /* sequence */
- { size_t offset;
- if (!ofBits)
- offset = 0;
- else {
- ZSTD_STATIC_ASSERT(ZSTD_lo_isLongOffset == 1);
- ZSTD_STATIC_ASSERT(LONG_OFFSETS_MAX_EXTRA_BITS_32 == 5);
- assert(ofBits <= MaxOff);
- if (MEM_32bits() && longOffsets) {
- U32 const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN_32-1);
- offset = ofBase + (BIT_readBitsFast(&seqState->DStream, ofBits - extraBits) << extraBits);
- if (MEM_32bits() || extraBits) BIT_reloadDStream(&seqState->DStream);
- if (extraBits) offset += BIT_readBitsFast(&seqState->DStream, extraBits);
- } else {
- offset = ofBase + BIT_readBitsFast(&seqState->DStream, ofBits); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */
- if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream);
- }
+ if (blockProperties.lastBlock) break;
}
- if (ofBits <= 1) {
- offset += (llBase==0);
- if (offset) {
- size_t temp = (offset==3) ? seqState->prevOffset[0] - 1 : seqState->prevOffset[offset];
- temp += !temp; /* 0 is not valid; input is corrupted; force offset to 1 */
- if (offset != 1) seqState->prevOffset[2] = seqState->prevOffset[1];
- seqState->prevOffset[1] = seqState->prevOffset[0];
- seqState->prevOffset[0] = offset = temp;
- } else {
- offset = seqState->prevOffset[0];
- }
- } else {
- seqState->prevOffset[2] = seqState->prevOffset[1];
- seqState->prevOffset[1] = seqState->prevOffset[0];
- seqState->prevOffset[0] = offset;
+ /* Final frame content checksum */
+ if (zfh.checksumFlag) {
+ if (remainingSize < 4)
+ return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));
+ ip += 4;
}
- seq.offset = offset;
- }
- seq.matchLength = mlBase + ((mlBits>0) ? BIT_readBitsFast(&seqState->DStream, mlBits) : 0); /* <= 16 bits */
- if (MEM_32bits() && (mlBits+llBits >= STREAM_ACCUMULATOR_MIN_32-LONG_OFFSETS_MAX_EXTRA_BITS_32))
- BIT_reloadDStream(&seqState->DStream);
- if (MEM_64bits() && (totalBits >= STREAM_ACCUMULATOR_MIN_64-(LLFSELog+MLFSELog+OffFSELog)))
- BIT_reloadDStream(&seqState->DStream);
- /* Verify that there is enough bits to read the rest of the data in 64-bit mode. */
- ZSTD_STATIC_ASSERT(16+LLFSELog+MLFSELog+OffFSELog < STREAM_ACCUMULATOR_MIN_64);
-
- seq.litLength = llBase + ((llBits>0) ? BIT_readBitsFast(&seqState->DStream, llBits) : 0); /* <= 16 bits */
- if (MEM_32bits())
- BIT_reloadDStream(&seqState->DStream);
-
- { size_t const pos = seqState->pos + seq.litLength;
- const BYTE* const matchBase = (seq.offset > pos) ? seqState->dictEnd : seqState->prefixStart;
- seq.match = matchBase + pos - seq.offset; /* note : this operation can overflow when seq.offset is really too large, which can only happen when input is corrupted.
- * No consequence though : no memory access will occur, overly large offset will be detected in ZSTD_execSequenceLong() */
- seqState->pos = pos + seq.matchLength;
+ frameSizeInfo.compressedSize = ip - ipstart;
+ frameSizeInfo.decompressedBound = (zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN)
+ ? zfh.frameContentSize
+ : nbBlocks * zfh.blockSizeMax;
+ return frameSizeInfo;
}
-
- /* ANS state update */
- ZSTD_updateFseState(&seqState->stateLL, &seqState->DStream); /* <= 9 bits */
- ZSTD_updateFseState(&seqState->stateML, &seqState->DStream); /* <= 9 bits */
- if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream); /* <= 18 bits */
- ZSTD_updateFseState(&seqState->stateOffb, &seqState->DStream); /* <= 8 bits */
-
- return seq;
}
-FORCE_INLINE_TEMPLATE size_t
-ZSTD_decompressSequencesLong_body(
- ZSTD_DCtx* dctx,
- void* dst, size_t maxDstSize,
- const void* seqStart, size_t seqSize, int nbSeq,
- const ZSTD_longOffset_e isLongOffset)
-{
- const BYTE* ip = (const BYTE*)seqStart;
- const BYTE* const iend = ip + seqSize;
- BYTE* const ostart = (BYTE* const)dst;
- BYTE* const oend = ostart + maxDstSize;
- BYTE* op = ostart;
- const BYTE* litPtr = dctx->litPtr;
- const BYTE* const litEnd = litPtr + dctx->litSize;
- const BYTE* const prefixStart = (const BYTE*) (dctx->base);
- const BYTE* const dictStart = (const BYTE*) (dctx->vBase);
- const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);
-
- /* Regen sequences */
- if (nbSeq) {
-#define STORED_SEQS 4
-#define STOSEQ_MASK (STORED_SEQS-1)
-#define ADVANCED_SEQS 4
- seq_t sequences[STORED_SEQS];
- int const seqAdvance = MIN(nbSeq, ADVANCED_SEQS);
- seqState_t seqState;
- int seqNb;
- dctx->fseEntropy = 1;
- { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }
- seqState.prefixStart = prefixStart;
- seqState.pos = (size_t)(op-prefixStart);
- seqState.dictEnd = dictEnd;
- CHECK_E(BIT_initDStream(&seqState.DStream, ip, iend-ip), corruption_detected);
- ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
- ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
- ZSTD_initFseState(&seqState.stateML, &seqState.DStream, dctx->MLTptr);
-
- /* prepare in advance */
- for (seqNb=0; (BIT_reloadDStream(&seqState.DStream) <= BIT_DStream_completed) && (seqNb<seqAdvance); seqNb++) {
- sequences[seqNb] = ZSTD_decodeSequenceLong(&seqState, isLongOffset);
- }
- if (seqNb<seqAdvance) return ERROR(corruption_detected);
-
- /* decode and decompress */
- for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && (seqNb<nbSeq) ; seqNb++) {
- seq_t const sequence = ZSTD_decodeSequenceLong(&seqState, isLongOffset);
- size_t const oneSeqSize = ZSTD_execSequenceLong(op, oend, sequences[(seqNb-ADVANCED_SEQS) & STOSEQ_MASK], &litPtr, litEnd, prefixStart, dictStart, dictEnd);
- if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
- PREFETCH(sequence.match); /* note : it's safe to invoke PREFETCH() on any memory address, including invalid ones */
- sequences[seqNb&STOSEQ_MASK] = sequence;
- op += oneSeqSize;
- }
- if (seqNb<nbSeq) return ERROR(corruption_detected);
-
- /* finish queue */
- seqNb -= seqAdvance;
- for ( ; seqNb<nbSeq ; seqNb++) {
- size_t const oneSeqSize = ZSTD_execSequenceLong(op, oend, sequences[seqNb&STOSEQ_MASK], &litPtr, litEnd, prefixStart, dictStart, dictEnd);
- if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
- op += oneSeqSize;
- }
-
- /* save reps for next block */
- { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]); }
-#undef STORED_SEQS
-#undef STOSEQ_MASK
-#undef ADVANCED_SEQS
- }
-
- /* last literal segment */
- { size_t const lastLLSize = litEnd - litPtr;
- if (lastLLSize > (size_t)(oend-op)) return ERROR(dstSize_tooSmall);
- memcpy(op, litPtr, lastLLSize);
- op += lastLLSize;
- }
-
- return op-ostart;
-}
-
-static size_t
-ZSTD_decompressSequencesLong_default(ZSTD_DCtx* dctx,
- void* dst, size_t maxDstSize,
- const void* seqStart, size_t seqSize, int nbSeq,
- const ZSTD_longOffset_e isLongOffset)
-{
- return ZSTD_decompressSequencesLong_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);
-}
-
-
-
-#if DYNAMIC_BMI2
-
-static TARGET_ATTRIBUTE("bmi2") size_t
-ZSTD_decompressSequences_bmi2(ZSTD_DCtx* dctx,
- void* dst, size_t maxDstSize,
- const void* seqStart, size_t seqSize, int nbSeq,
- const ZSTD_longOffset_e isLongOffset)
-{
- return ZSTD_decompressSequences_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);
-}
-
-static TARGET_ATTRIBUTE("bmi2") size_t
-ZSTD_decompressSequencesLong_bmi2(ZSTD_DCtx* dctx,
- void* dst, size_t maxDstSize,
- const void* seqStart, size_t seqSize, int nbSeq,
- const ZSTD_longOffset_e isLongOffset)
+/** ZSTD_findFrameCompressedSize() :
+ * compatible with legacy mode
+ * `src` must point to the start of a ZSTD frame, ZSTD legacy frame, or skippable frame
+ * `srcSize` must be at least as large as the frame contained
+ * @return : the compressed size of the frame starting at `src` */
+size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
{
- return ZSTD_decompressSequencesLong_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);
+ ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize);
+ return frameSizeInfo.compressedSize;
}
-#endif
-
-typedef size_t (*ZSTD_decompressSequences_t)(
- ZSTD_DCtx *dctx, void *dst, size_t maxDstSize,
- const void *seqStart, size_t seqSize, int nbSeq,
- const ZSTD_longOffset_e isLongOffset);
-static size_t ZSTD_decompressSequences(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize,
- const void* seqStart, size_t seqSize, int nbSeq,
- const ZSTD_longOffset_e isLongOffset)
-{
- DEBUGLOG(5, "ZSTD_decompressSequences");
-#if DYNAMIC_BMI2
- if (dctx->bmi2) {
- return ZSTD_decompressSequences_bmi2(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);
- }
-#endif
- return ZSTD_decompressSequences_default(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);
-}
-
-static size_t ZSTD_decompressSequencesLong(ZSTD_DCtx* dctx,
- void* dst, size_t maxDstSize,
- const void* seqStart, size_t seqSize, int nbSeq,
- const ZSTD_longOffset_e isLongOffset)
-{
- DEBUGLOG(5, "ZSTD_decompressSequencesLong");
-#if DYNAMIC_BMI2
- if (dctx->bmi2) {
- return ZSTD_decompressSequencesLong_bmi2(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);
- }
-#endif
- return ZSTD_decompressSequencesLong_default(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);
-}
-
-/* ZSTD_getLongOffsetsShare() :
- * condition : offTable must be valid
- * @return : "share" of long offsets (arbitrarily defined as > (1<<23))
- * compared to maximum possible of (1<<OffFSELog) */
-static unsigned
-ZSTD_getLongOffsetsShare(const ZSTD_seqSymbol* offTable)
-{
- const void* ptr = offTable;
- U32 const tableLog = ((const ZSTD_seqSymbol_header*)ptr)[0].tableLog;
- const ZSTD_seqSymbol* table = offTable + 1;
- U32 const max = 1 << tableLog;
- U32 u, total = 0;
- DEBUGLOG(5, "ZSTD_getLongOffsetsShare: (tableLog=%u)", tableLog);
-
- assert(max <= (1 << OffFSELog)); /* max not too large */
- for (u=0; u<max; u++) {
- if (table[u].nbAdditionalBits > 22) total += 1;
+/** ZSTD_decompressBound() :
+ * compatible with legacy mode
+ * `src` must point to the start of a ZSTD frame or a skippeable frame
+ * `srcSize` must be at least as large as the frame contained
+ * @return : the maximum decompressed size of the compressed source
+ */
+unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)
+{
+ unsigned long long bound = 0;
+ /* Iterate over each frame */
+ while (srcSize > 0) {
+ ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize);
+ size_t const compressedSize = frameSizeInfo.compressedSize;
+ unsigned long long const decompressedBound = frameSizeInfo.decompressedBound;
+ if (ZSTD_isError(compressedSize) || decompressedBound == ZSTD_CONTENTSIZE_ERROR)
+ return ZSTD_CONTENTSIZE_ERROR;
+ src = (const BYTE*)src + compressedSize;
+ srcSize -= compressedSize;
+ bound += decompressedBound;
}
-
- assert(tableLog <= OffFSELog);
- total <<= (OffFSELog - tableLog); /* scale to OffFSELog */
-
- return total;
+ return bound;
}
-static size_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
- void* dst, size_t dstCapacity,
- const void* src, size_t srcSize, const int frame)
-{ /* blockType == blockCompressed */
- const BYTE* ip = (const BYTE*)src;
- /* isLongOffset must be true if there are long offsets.
- * Offsets are long if they are larger than 2^STREAM_ACCUMULATOR_MIN.
- * We don't expect that to be the case in 64-bit mode.
- * In block mode, window size is not known, so we have to be conservative. (note: but it could be evaluated from current-lowLimit)
- */
- ZSTD_longOffset_e const isLongOffset = (ZSTD_longOffset_e)(MEM_32bits() && (!frame || dctx->fParams.windowSize > (1ULL << STREAM_ACCUMULATOR_MIN)));
- DEBUGLOG(5, "ZSTD_decompressBlock_internal (size : %u)", (U32)srcSize);
-
- if (srcSize >= ZSTD_BLOCKSIZE_MAX) return ERROR(srcSize_wrong);
-
- /* Decode literals section */
- { size_t const litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize);
- DEBUGLOG(5, "ZSTD_decodeLiteralsBlock : %u", (U32)litCSize);
- if (ZSTD_isError(litCSize)) return litCSize;
- ip += litCSize;
- srcSize -= litCSize;
- }
-
- /* Build Decoding Tables */
- { int nbSeq;
- size_t const seqHSize = ZSTD_decodeSeqHeaders(dctx, &nbSeq, ip, srcSize);
- if (ZSTD_isError(seqHSize)) return seqHSize;
- ip += seqHSize;
- srcSize -= seqHSize;
-
- if ( (!frame || dctx->fParams.windowSize > (1<<24))
- && (nbSeq>0) ) { /* could probably use a larger nbSeq limit */
- U32 const shareLongOffsets = ZSTD_getLongOffsetsShare(dctx->OFTptr);
- U32 const minShare = MEM_64bits() ? 7 : 20; /* heuristic values, correspond to 2.73% and 7.81% */
- if (shareLongOffsets >= minShare)
- return ZSTD_decompressSequencesLong(dctx, dst, dstCapacity, ip, srcSize, nbSeq, isLongOffset);
- }
-
- return ZSTD_decompressSequences(dctx, dst, dstCapacity, ip, srcSize, nbSeq, isLongOffset);
- }
-}
+/*-*************************************************************
+ * Frame decoding
+ ***************************************************************/
-static void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst)
+void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst)
{
if (dst != dctx->previousDstEnd) { /* not contiguous */
dctx->dictEnd = dctx->previousDstEnd;
- dctx->vBase = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->base));
- dctx->base = dst;
+ dctx->virtualStart = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart));
+ dctx->prefixStart = dst;
dctx->previousDstEnd = dst;
}
}
-size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx,
- void* dst, size_t dstCapacity,
- const void* src, size_t srcSize)
-{
- size_t dSize;
- ZSTD_checkContinuity(dctx, dst);
- dSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 0);
- dctx->previousDstEnd = (char*)dst + dSize;
- return dSize;
-}
-
-
/** ZSTD_insertBlock() :
insert `src` block into `dctx` history. Useful to track uncompressed blocks. */
-ZSTDLIB_API size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize)
+size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize)
{
ZSTD_checkContinuity(dctx, blockStart);
dctx->previousDstEnd = (const char*)blockStart + blockSize;
@@ -1729,69 +579,37 @@ ZSTDLIB_API size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, siz
}
-static size_t ZSTD_generateNxBytes(void* dst, size_t dstCapacity, BYTE byte, size_t length)
+static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize)
{
- if (length > dstCapacity) return ERROR(dstSize_tooSmall);
- memset(dst, byte, length);
- return length;
+ DEBUGLOG(5, "ZSTD_copyRawBlock");
+ if (dst == NULL) {
+ if (srcSize == 0) return 0;
+ RETURN_ERROR(dstBuffer_null);
+ }
+ RETURN_ERROR_IF(srcSize > dstCapacity, dstSize_tooSmall);
+ memcpy(dst, src, srcSize);
+ return srcSize;
}
-/** ZSTD_findFrameCompressedSize() :
- * compatible with legacy mode
- * `src` must point to the start of a ZSTD frame, ZSTD legacy frame, or skippable frame
- * `srcSize` must be at least as large as the frame contained
- * @return : the compressed size of the frame starting at `src` */
-size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
+static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity,
+ BYTE b,
+ size_t regenSize)
{
-#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
- if (ZSTD_isLegacy(src, srcSize))
- return ZSTD_findFrameCompressedSizeLegacy(src, srcSize);
-#endif
- if ( (srcSize >= ZSTD_skippableHeaderSize)
- && (MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START ) {
- return ZSTD_skippableHeaderSize + MEM_readLE32((const BYTE*)src + ZSTD_frameIdSize);
- } else {
- const BYTE* ip = (const BYTE*)src;
- const BYTE* const ipstart = ip;
- size_t remainingSize = srcSize;
- ZSTD_frameHeader zfh;
-
- /* Extract Frame Header */
- { size_t const ret = ZSTD_getFrameHeader(&zfh, src, srcSize);
- if (ZSTD_isError(ret)) return ret;
- if (ret > 0) return ERROR(srcSize_wrong);
- }
-
- ip += zfh.headerSize;
- remainingSize -= zfh.headerSize;
-
- /* Loop on each block */
- while (1) {
- blockProperties_t blockProperties;
- size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
- if (ZSTD_isError(cBlockSize)) return cBlockSize;
-
- if (ZSTD_blockHeaderSize + cBlockSize > remainingSize)
- return ERROR(srcSize_wrong);
-
- ip += ZSTD_blockHeaderSize + cBlockSize;
- remainingSize -= ZSTD_blockHeaderSize + cBlockSize;
-
- if (blockProperties.lastBlock) break;
- }
-
- if (zfh.checksumFlag) { /* Final frame content checksum */
- if (remainingSize < 4) return ERROR(srcSize_wrong);
- ip += 4;
- remainingSize -= 4;
- }
-
- return ip - ipstart;
+ if (dst == NULL) {
+ if (regenSize == 0) return 0;
+ RETURN_ERROR(dstBuffer_null);
}
+ RETURN_ERROR_IF(regenSize > dstCapacity, dstSize_tooSmall);
+ memset(dst, b, regenSize);
+ return regenSize;
}
+
/*! ZSTD_decompressFrame() :
-* @dctx must be properly initialized */
+ * @dctx must be properly initialized
+ * will update *srcPtr and *srcSizePtr,
+ * to make *srcPtr progress by one frame. */
static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
void* dst, size_t dstCapacity,
const void** srcPtr, size_t *srcSizePtr)
@@ -1800,31 +618,34 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
BYTE* const ostart = (BYTE* const)dst;
BYTE* const oend = ostart + dstCapacity;
BYTE* op = ostart;
- size_t remainingSize = *srcSizePtr;
+ size_t remainingSrcSize = *srcSizePtr;
+
+ DEBUGLOG(4, "ZSTD_decompressFrame (srcSize:%i)", (int)*srcSizePtr);
/* check */
- if (remainingSize < ZSTD_frameHeaderSize_min+ZSTD_blockHeaderSize)
- return ERROR(srcSize_wrong);
+ RETURN_ERROR_IF(
+ remainingSrcSize < ZSTD_FRAMEHEADERSIZE_MIN+ZSTD_blockHeaderSize,
+ srcSize_wrong);
/* Frame Header */
- { size_t const frameHeaderSize = ZSTD_frameHeaderSize(ip, ZSTD_frameHeaderSize_prefix);
+ { size_t const frameHeaderSize = ZSTD_frameHeaderSize(ip, ZSTD_FRAMEHEADERSIZE_PREFIX);
if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;
- if (remainingSize < frameHeaderSize+ZSTD_blockHeaderSize)
- return ERROR(srcSize_wrong);
- CHECK_F( ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize) );
- ip += frameHeaderSize; remainingSize -= frameHeaderSize;
+ RETURN_ERROR_IF(remainingSrcSize < frameHeaderSize+ZSTD_blockHeaderSize,
+ srcSize_wrong);
+ FORWARD_IF_ERROR( ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize) );
+ ip += frameHeaderSize; remainingSrcSize -= frameHeaderSize;
}
/* Loop on each block */
while (1) {
size_t decodedSize;
blockProperties_t blockProperties;
- size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
+ size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSrcSize, &blockProperties);
if (ZSTD_isError(cBlockSize)) return cBlockSize;
ip += ZSTD_blockHeaderSize;
- remainingSize -= ZSTD_blockHeaderSize;
- if (cBlockSize > remainingSize) return ERROR(srcSize_wrong);
+ remainingSrcSize -= ZSTD_blockHeaderSize;
+ RETURN_ERROR_IF(cBlockSize > remainingSrcSize, srcSize_wrong);
switch(blockProperties.blockType)
{
@@ -1835,11 +656,11 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
decodedSize = ZSTD_copyRawBlock(op, oend-op, ip, cBlockSize);
break;
case bt_rle :
- decodedSize = ZSTD_generateNxBytes(op, oend-op, *ip, blockProperties.origSize);
+ decodedSize = ZSTD_setRleBlock(op, oend-op, *ip, blockProperties.origSize);
break;
case bt_reserved :
default:
- return ERROR(corruption_detected);
+ RETURN_ERROR(corruption_detected);
}
if (ZSTD_isError(decodedSize)) return decodedSize;
@@ -1847,33 +668,30 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
XXH64_update(&dctx->xxhState, op, decodedSize);
op += decodedSize;
ip += cBlockSize;
- remainingSize -= cBlockSize;
+ remainingSrcSize -= cBlockSize;
if (blockProperties.lastBlock) break;
}
if (dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) {
- if ((U64)(op-ostart) != dctx->fParams.frameContentSize) {
- return ERROR(corruption_detected);
- } }
+ RETURN_ERROR_IF((U64)(op-ostart) != dctx->fParams.frameContentSize,
+ corruption_detected);
+ }
if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */
U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState);
U32 checkRead;
- if (remainingSize<4) return ERROR(checksum_wrong);
+ RETURN_ERROR_IF(remainingSrcSize<4, checksum_wrong);
checkRead = MEM_readLE32(ip);
- if (checkRead != checkCalc) return ERROR(checksum_wrong);
+ RETURN_ERROR_IF(checkRead != checkCalc, checksum_wrong);
ip += 4;
- remainingSize -= 4;
+ remainingSrcSize -= 4;
}
/* Allow caller to get size read */
*srcPtr = ip;
- *srcSizePtr = remainingSize;
+ *srcSizePtr = remainingSrcSize;
return op-ostart;
}
-static const void* ZSTD_DDictDictContent(const ZSTD_DDict* ddict);
-static size_t ZSTD_DDictDictSize(const ZSTD_DDict* ddict);
-
static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
@@ -1881,26 +699,30 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
const ZSTD_DDict* ddict)
{
void* const dststart = dst;
+ int moreThan1Frame = 0;
+
+ DEBUGLOG(5, "ZSTD_decompressMultiFrame");
assert(dict==NULL || ddict==NULL); /* either dict or ddict set, not both */
if (ddict) {
- dict = ZSTD_DDictDictContent(ddict);
- dictSize = ZSTD_DDictDictSize(ddict);
+ dict = ZSTD_DDict_dictContent(ddict);
+ dictSize = ZSTD_DDict_dictSize(ddict);
}
- while (srcSize >= ZSTD_frameHeaderSize_prefix) {
- U32 magicNumber;
+ while (srcSize >= ZSTD_FRAMEHEADERSIZE_PREFIX) {
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
if (ZSTD_isLegacy(src, srcSize)) {
size_t decodedSize;
size_t const frameSize = ZSTD_findFrameCompressedSizeLegacy(src, srcSize);
if (ZSTD_isError(frameSize)) return frameSize;
- /* legacy support is not compatible with static dctx */
- if (dctx->staticSize) return ERROR(memory_allocation);
+ RETURN_ERROR_IF(dctx->staticSize, memory_allocation,
+ "legacy support is not compatible with static dctx");
decodedSize = ZSTD_decompressLegacy(dst, dstCapacity, src, frameSize, dict, dictSize);
+ if (ZSTD_isError(decodedSize)) return decodedSize;
+ assert(decodedSize <=- dstCapacity);
dst = (BYTE*)dst + decodedSize;
dstCapacity -= decodedSize;
@@ -1911,45 +733,54 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
}
#endif
- magicNumber = MEM_readLE32(src);
- DEBUGLOG(4, "reading magic number %08X (expecting %08X)",
- (U32)magicNumber, (U32)ZSTD_MAGICNUMBER);
- if (magicNumber != ZSTD_MAGICNUMBER) {
- if ((magicNumber & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
- size_t skippableSize;
- if (srcSize < ZSTD_skippableHeaderSize)
- return ERROR(srcSize_wrong);
- skippableSize = MEM_readLE32((const BYTE*)src + ZSTD_frameIdSize)
- + ZSTD_skippableHeaderSize;
- if (srcSize < skippableSize) return ERROR(srcSize_wrong);
+ { U32 const magicNumber = MEM_readLE32(src);
+ DEBUGLOG(4, "reading magic number %08X (expecting %08X)",
+ (unsigned)magicNumber, ZSTD_MAGICNUMBER);
+ if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
+ size_t const skippableSize = readSkippableFrameSize(src, srcSize);
+ if (ZSTD_isError(skippableSize))
+ return skippableSize;
+ RETURN_ERROR_IF(srcSize < skippableSize, srcSize_wrong);
src = (const BYTE *)src + skippableSize;
srcSize -= skippableSize;
continue;
- }
- return ERROR(prefix_unknown);
- }
+ } }
if (ddict) {
/* we were called from ZSTD_decompress_usingDDict */
- CHECK_F(ZSTD_decompressBegin_usingDDict(dctx, ddict));
+ FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(dctx, ddict));
} else {
/* this will initialize correctly with no dict if dict == NULL, so
* use this in all cases but ddict */
- CHECK_F(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize));
+ FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize));
}
ZSTD_checkContinuity(dctx, dst);
{ const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity,
&src, &srcSize);
+ RETURN_ERROR_IF(
+ (ZSTD_getErrorCode(res) == ZSTD_error_prefix_unknown)
+ && (moreThan1Frame==1),
+ srcSize_wrong,
+ "at least one frame successfully completed, but following "
+ "bytes are garbage: it's more likely to be a srcSize error, "
+ "specifying more bytes than compressed size of frame(s). This "
+ "error message replaces ERROR(prefix_unknown), which would be "
+ "confusing, as the first header is actually correct. Note that "
+ "one could be unlucky, it might be a corruption error instead, "
+ "happening right at the place where we expect zstd magic "
+ "bytes. But this is _much_ less likely than a srcSize field "
+ "error.");
if (ZSTD_isError(res)) return res;
- /* no need to bound check, ZSTD_decompressFrame already has */
+ assert(res <= dstCapacity);
dst = (BYTE*)dst + res;
dstCapacity -= res;
}
+ moreThan1Frame = 1;
} /* while (srcSize >= ZSTD_frameHeaderSize_prefix) */
- if (srcSize) return ERROR(srcSize_wrong); /* input not entirely consumed */
+ RETURN_ERROR_IF(srcSize, srcSize_wrong, "input not entirely consumed");
return (BYTE*)dst - (BYTE*)dststart;
}
@@ -1963,9 +794,26 @@ size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
}
+static ZSTD_DDict const* ZSTD_getDDict(ZSTD_DCtx* dctx)
+{
+ switch (dctx->dictUses) {
+ default:
+ assert(0 /* Impossible */);
+ /* fall-through */
+ case ZSTD_dont_use:
+ ZSTD_clearDict(dctx);
+ return NULL;
+ case ZSTD_use_indefinitely:
+ return dctx->ddict;
+ case ZSTD_use_once:
+ dctx->dictUses = ZSTD_dont_use;
+ return dctx->ddict;
+ }
+}
+
size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
{
- return ZSTD_decompress_usingDict(dctx, dst, dstCapacity, src, srcSize, NULL, 0);
+ return ZSTD_decompress_usingDDict(dctx, dst, dstCapacity, src, srcSize, ZSTD_getDDict(dctx));
}
@@ -1974,12 +822,13 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr
#if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE>=1)
size_t regenSize;
ZSTD_DCtx* const dctx = ZSTD_createDCtx();
- if (dctx==NULL) return ERROR(memory_allocation);
+ RETURN_ERROR_IF(dctx==NULL, memory_allocation);
regenSize = ZSTD_decompressDCtx(dctx, dst, dstCapacity, src, srcSize);
ZSTD_freeDCtx(dctx);
return regenSize;
#else /* stack mode */
ZSTD_DCtx dctx;
+ ZSTD_initDCtx_internal(&dctx);
return ZSTD_decompressDCtx(&dctx, dst, dstCapacity, src, srcSize);
#endif
}
@@ -2021,9 +870,9 @@ static int ZSTD_isSkipFrame(ZSTD_DCtx* dctx) { return dctx->stage == ZSTDds_skip
* or an error code, which can be tested using ZSTD_isError() */
size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
{
- DEBUGLOG(5, "ZSTD_decompressContinue (srcSize:%u)", (U32)srcSize);
+ DEBUGLOG(5, "ZSTD_decompressContinue (srcSize:%u)", (unsigned)srcSize);
/* Sanity check */
- if (srcSize != dctx->expected) return ERROR(srcSize_wrong); /* not allowed */
+ RETURN_ERROR_IF(srcSize != dctx->expected, srcSize_wrong, "not allowed");
if (dstCapacity) ZSTD_checkContinuity(dctx, dst);
switch (dctx->stage)
@@ -2031,10 +880,10 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
case ZSTDds_getFrameHeaderSize :
assert(src != NULL);
if (dctx->format == ZSTD_f_zstd1) { /* allows header */
- assert(srcSize >= ZSTD_frameIdSize); /* to read skippable magic number */
- if ((MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
+ assert(srcSize >= ZSTD_FRAMEIDSIZE); /* to read skippable magic number */
+ if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
memcpy(dctx->headerBuffer, src, srcSize);
- dctx->expected = ZSTD_skippableHeaderSize - srcSize; /* remaining to load to get full skippable frame header */
+ dctx->expected = ZSTD_SKIPPABLEHEADERSIZE - srcSize; /* remaining to load to get full skippable frame header */
dctx->stage = ZSTDds_decodeSkippableHeader;
return 0;
} }
@@ -2048,7 +897,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
case ZSTDds_decodeFrameHeader:
assert(src != NULL);
memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize);
- CHECK_F(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize));
+ FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize));
dctx->expected = ZSTD_blockHeaderSize;
dctx->stage = ZSTDds_decodeBlockHeader;
return 0;
@@ -2094,23 +943,23 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
rSize = ZSTD_copyRawBlock(dst, dstCapacity, src, srcSize);
break;
case bt_rle :
- rSize = ZSTD_setRleBlock(dst, dstCapacity, src, srcSize, dctx->rleSize);
+ rSize = ZSTD_setRleBlock(dst, dstCapacity, *(const BYTE*)src, dctx->rleSize);
break;
case bt_reserved : /* should never happen */
default:
- return ERROR(corruption_detected);
+ RETURN_ERROR(corruption_detected);
}
if (ZSTD_isError(rSize)) return rSize;
- DEBUGLOG(5, "ZSTD_decompressContinue: decoded size from block : %u", (U32)rSize);
+ DEBUGLOG(5, "ZSTD_decompressContinue: decoded size from block : %u", (unsigned)rSize);
dctx->decodedSize += rSize;
if (dctx->fParams.checksumFlag) XXH64_update(&dctx->xxhState, dst, rSize);
if (dctx->stage == ZSTDds_decompressLastBlock) { /* end of frame */
- DEBUGLOG(4, "ZSTD_decompressContinue: decoded size from frame : %u", (U32)dctx->decodedSize);
- if (dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) {
- if (dctx->decodedSize != dctx->fParams.frameContentSize) {
- return ERROR(corruption_detected);
- } }
+ DEBUGLOG(4, "ZSTD_decompressContinue: decoded size from frame : %u", (unsigned)dctx->decodedSize);
+ RETURN_ERROR_IF(
+ dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
+ && dctx->decodedSize != dctx->fParams.frameContentSize,
+ corruption_detected);
if (dctx->fParams.checksumFlag) { /* another round for frame checksum */
dctx->expected = 4;
dctx->stage = ZSTDds_checkChecksum;
@@ -2130,8 +979,8 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
assert(srcSize == 4); /* guaranteed by dctx->expected */
{ U32 const h32 = (U32)XXH64_digest(&dctx->xxhState);
U32 const check32 = MEM_readLE32(src);
- DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", h32, check32);
- if (check32 != h32) return ERROR(checksum_wrong);
+ DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32);
+ RETURN_ERROR_IF(check32 != h32, checksum_wrong);
dctx->expected = 0;
dctx->stage = ZSTDds_getFrameHeaderSize;
return 0;
@@ -2139,9 +988,9 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
case ZSTDds_decodeSkippableHeader:
assert(src != NULL);
- assert(srcSize <= ZSTD_skippableHeaderSize);
- memcpy(dctx->headerBuffer + (ZSTD_skippableHeaderSize - srcSize), src, srcSize); /* complete skippable header */
- dctx->expected = MEM_readLE32(dctx->headerBuffer + ZSTD_frameIdSize); /* note : dctx->expected can grow seriously large, beyond local buffer size */
+ assert(srcSize <= ZSTD_SKIPPABLEHEADERSIZE);
+ memcpy(dctx->headerBuffer + (ZSTD_SKIPPABLEHEADERSIZE - srcSize), src, srcSize); /* complete skippable header */
+ dctx->expected = MEM_readLE32(dctx->headerBuffer + ZSTD_FRAMEIDSIZE); /* note : dctx->expected can grow seriously large, beyond local buffer size */
dctx->stage = ZSTDds_skipFrame;
return 0;
@@ -2151,7 +1000,8 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
return 0;
default:
- return ERROR(GENERIC); /* impossible */
+ assert(0); /* impossible */
+ RETURN_ERROR(GENERIC); /* some compiler require default to do something */
}
}
@@ -2159,38 +1009,52 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
static size_t ZSTD_refDictContent(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
{
dctx->dictEnd = dctx->previousDstEnd;
- dctx->vBase = (const char*)dict - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->base));
- dctx->base = dict;
+ dctx->virtualStart = (const char*)dict - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart));
+ dctx->prefixStart = dict;
dctx->previousDstEnd = (const char*)dict + dictSize;
return 0;
}
-/* ZSTD_loadEntropy() :
- * dict : must point at beginning of a valid zstd dictionary
+/*! ZSTD_loadDEntropy() :
+ * dict : must point at beginning of a valid zstd dictionary.
* @return : size of entropy tables read */
-static size_t ZSTD_loadEntropy(ZSTD_entropyDTables_t* entropy, const void* const dict, size_t const dictSize)
+size_t
+ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
+ const void* const dict, size_t const dictSize)
{
const BYTE* dictPtr = (const BYTE*)dict;
const BYTE* const dictEnd = dictPtr + dictSize;
- if (dictSize <= 8) return ERROR(dictionary_corrupted);
+ RETURN_ERROR_IF(dictSize <= 8, dictionary_corrupted);
+ assert(MEM_readLE32(dict) == ZSTD_MAGIC_DICTIONARY); /* dict must be valid */
dictPtr += 8; /* skip header = magic + dictID */
-
- { size_t const hSize = HUF_readDTableX4_wksp(
- entropy->hufTable, dictPtr, dictEnd - dictPtr,
- entropy->workspace, sizeof(entropy->workspace));
- if (HUF_isError(hSize)) return ERROR(dictionary_corrupted);
+ ZSTD_STATIC_ASSERT(offsetof(ZSTD_entropyDTables_t, OFTable) == offsetof(ZSTD_entropyDTables_t, LLTable) + sizeof(entropy->LLTable));
+ ZSTD_STATIC_ASSERT(offsetof(ZSTD_entropyDTables_t, MLTable) == offsetof(ZSTD_entropyDTables_t, OFTable) + sizeof(entropy->OFTable));
+ ZSTD_STATIC_ASSERT(sizeof(entropy->LLTable) + sizeof(entropy->OFTable) + sizeof(entropy->MLTable) >= HUF_DECOMPRESS_WORKSPACE_SIZE);
+ { void* const workspace = &entropy->LLTable; /* use fse tables as temporary workspace; implies fse tables are grouped together */
+ size_t const workspaceSize = sizeof(entropy->LLTable) + sizeof(entropy->OFTable) + sizeof(entropy->MLTable);
+#ifdef HUF_FORCE_DECOMPRESS_X1
+ /* in minimal huffman, we always use X1 variants */
+ size_t const hSize = HUF_readDTableX1_wksp(entropy->hufTable,
+ dictPtr, dictEnd - dictPtr,
+ workspace, workspaceSize);
+#else
+ size_t const hSize = HUF_readDTableX2_wksp(entropy->hufTable,
+ dictPtr, dictEnd - dictPtr,
+ workspace, workspaceSize);
+#endif
+ RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted);
dictPtr += hSize;
}
{ short offcodeNCount[MaxOff+1];
- U32 offcodeMaxValue = MaxOff, offcodeLog;
+ unsigned offcodeMaxValue = MaxOff, offcodeLog;
size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
- if (FSE_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);
- if (offcodeMaxValue > MaxOff) return ERROR(dictionary_corrupted);
- if (offcodeLog > OffFSELog) return ERROR(dictionary_corrupted);
- ZSTD_buildFSETable(entropy->OFTable,
+ RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted);
+ RETURN_ERROR_IF(offcodeMaxValue > MaxOff, dictionary_corrupted);
+ RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted);
+ ZSTD_buildFSETable( entropy->OFTable,
offcodeNCount, offcodeMaxValue,
OF_base, OF_bits,
offcodeLog);
@@ -2200,10 +1064,10 @@ static size_t ZSTD_loadEntropy(ZSTD_entropyDTables_t* entropy, const void* const
{ short matchlengthNCount[MaxML+1];
unsigned matchlengthMaxValue = MaxML, matchlengthLog;
size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
- if (FSE_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted);
- if (matchlengthMaxValue > MaxML) return ERROR(dictionary_corrupted);
- if (matchlengthLog > MLFSELog) return ERROR(dictionary_corrupted);
- ZSTD_buildFSETable(entropy->MLTable,
+ RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted);
+ RETURN_ERROR_IF(matchlengthMaxValue > MaxML, dictionary_corrupted);
+ RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted);
+ ZSTD_buildFSETable( entropy->MLTable,
matchlengthNCount, matchlengthMaxValue,
ML_base, ML_bits,
matchlengthLog);
@@ -2213,22 +1077,23 @@ static size_t ZSTD_loadEntropy(ZSTD_entropyDTables_t* entropy, const void* const
{ short litlengthNCount[MaxLL+1];
unsigned litlengthMaxValue = MaxLL, litlengthLog;
size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
- if (FSE_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted);
- if (litlengthMaxValue > MaxLL) return ERROR(dictionary_corrupted);
- if (litlengthLog > LLFSELog) return ERROR(dictionary_corrupted);
- ZSTD_buildFSETable(entropy->LLTable,
+ RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted);
+ RETURN_ERROR_IF(litlengthMaxValue > MaxLL, dictionary_corrupted);
+ RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted);
+ ZSTD_buildFSETable( entropy->LLTable,
litlengthNCount, litlengthMaxValue,
LL_base, LL_bits,
litlengthLog);
dictPtr += litlengthHeaderSize;
}
- if (dictPtr+12 > dictEnd) return ERROR(dictionary_corrupted);
+ RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted);
{ int i;
size_t const dictContentSize = (size_t)(dictEnd - (dictPtr+12));
for (i=0; i<3; i++) {
U32 const rep = MEM_readLE32(dictPtr); dictPtr += 4;
- if (rep==0 || rep >= dictContentSize) return ERROR(dictionary_corrupted);
+ RETURN_ERROR_IF(rep==0 || rep >= dictContentSize,
+ dictionary_corrupted);
entropy->rep[i] = rep;
} }
@@ -2242,11 +1107,11 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
if (magic != ZSTD_MAGIC_DICTIONARY) {
return ZSTD_refDictContent(dctx, dict, dictSize); /* pure content mode */
} }
- dctx->dictID = MEM_readLE32((const char*)dict + ZSTD_frameIdSize);
+ dctx->dictID = MEM_readLE32((const char*)dict + ZSTD_FRAMEIDSIZE);
/* load entropy tables */
- { size_t const eSize = ZSTD_loadEntropy(&dctx->entropy, dict, dictSize);
- if (ZSTD_isError(eSize)) return ERROR(dictionary_corrupted);
+ { size_t const eSize = ZSTD_loadDEntropy(&dctx->entropy, dict, dictSize);
+ RETURN_ERROR_IF(ZSTD_isError(eSize), dictionary_corrupted);
dict = (const char*)dict + eSize;
dictSize -= eSize;
}
@@ -2256,7 +1121,6 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
return ZSTD_refDictContent(dctx, dict, dictSize);
}
-/* Note : this function cannot fail */
size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
{
assert(dctx != NULL);
@@ -2264,8 +1128,8 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
dctx->stage = ZSTDds_getFrameHeaderSize;
dctx->decodedSize = 0;
dctx->previousDstEnd = NULL;
- dctx->base = NULL;
- dctx->vBase = NULL;
+ dctx->prefixStart = NULL;
+ dctx->virtualStart = NULL;
dctx->dictEnd = NULL;
dctx->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
dctx->litEntropy = dctx->fseEntropy = 0;
@@ -2281,201 +1145,36 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
{
- CHECK_F( ZSTD_decompressBegin(dctx) );
+ FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) );
if (dict && dictSize)
- CHECK_E(ZSTD_decompress_insertDictionary(dctx, dict, dictSize), dictionary_corrupted);
+ RETURN_ERROR_IF(
+ ZSTD_isError(ZSTD_decompress_insertDictionary(dctx, dict, dictSize)),
+ dictionary_corrupted);
return 0;
}
/* ====== ZSTD_DDict ====== */
-struct ZSTD_DDict_s {
- void* dictBuffer;
- const void* dictContent;
- size_t dictSize;
- ZSTD_entropyDTables_t entropy;
- U32 dictID;
- U32 entropyPresent;
- ZSTD_customMem cMem;
-}; /* typedef'd to ZSTD_DDict within "zstd.h" */
-
-static const void* ZSTD_DDictDictContent(const ZSTD_DDict* ddict)
-{
- return ddict->dictContent;
-}
-
-static size_t ZSTD_DDictDictSize(const ZSTD_DDict* ddict)
-{
- return ddict->dictSize;
-}
-
-size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dstDCtx, const ZSTD_DDict* ddict)
-{
- CHECK_F( ZSTD_decompressBegin(dstDCtx) );
- if (ddict) { /* support begin on NULL */
- dstDCtx->dictID = ddict->dictID;
- dstDCtx->base = ddict->dictContent;
- dstDCtx->vBase = ddict->dictContent;
- dstDCtx->dictEnd = (const BYTE*)ddict->dictContent + ddict->dictSize;
- dstDCtx->previousDstEnd = dstDCtx->dictEnd;
- if (ddict->entropyPresent) {
- dstDCtx->litEntropy = 1;
- dstDCtx->fseEntropy = 1;
- dstDCtx->LLTptr = ddict->entropy.LLTable;
- dstDCtx->MLTptr = ddict->entropy.MLTable;
- dstDCtx->OFTptr = ddict->entropy.OFTable;
- dstDCtx->HUFptr = ddict->entropy.hufTable;
- dstDCtx->entropy.rep[0] = ddict->entropy.rep[0];
- dstDCtx->entropy.rep[1] = ddict->entropy.rep[1];
- dstDCtx->entropy.rep[2] = ddict->entropy.rep[2];
- } else {
- dstDCtx->litEntropy = 0;
- dstDCtx->fseEntropy = 0;
- }
- }
- return 0;
-}
-
-static size_t ZSTD_loadEntropy_inDDict(ZSTD_DDict* ddict, ZSTD_dictContentType_e dictContentType)
+size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
{
- ddict->dictID = 0;
- ddict->entropyPresent = 0;
- if (dictContentType == ZSTD_dct_rawContent) return 0;
-
- if (ddict->dictSize < 8) {
- if (dictContentType == ZSTD_dct_fullDict)
- return ERROR(dictionary_corrupted); /* only accept specified dictionaries */
- return 0; /* pure content mode */
- }
- { U32 const magic = MEM_readLE32(ddict->dictContent);
- if (magic != ZSTD_MAGIC_DICTIONARY) {
- if (dictContentType == ZSTD_dct_fullDict)
- return ERROR(dictionary_corrupted); /* only accept specified dictionaries */
- return 0; /* pure content mode */
- }
+ DEBUGLOG(4, "ZSTD_decompressBegin_usingDDict");
+ assert(dctx != NULL);
+ if (ddict) {
+ const char* const dictStart = (const char*)ZSTD_DDict_dictContent(ddict);
+ size_t const dictSize = ZSTD_DDict_dictSize(ddict);
+ const void* const dictEnd = dictStart + dictSize;
+ dctx->ddictIsCold = (dctx->dictEnd != dictEnd);
+ DEBUGLOG(4, "DDict is %s",
+ dctx->ddictIsCold ? "~cold~" : "hot!");
}
- ddict->dictID = MEM_readLE32((const char*)ddict->dictContent + ZSTD_frameIdSize);
-
- /* load entropy tables */
- CHECK_E( ZSTD_loadEntropy(&ddict->entropy, ddict->dictContent, ddict->dictSize), dictionary_corrupted );
- ddict->entropyPresent = 1;
- return 0;
-}
-
-
-static size_t ZSTD_initDDict_internal(ZSTD_DDict* ddict,
- const void* dict, size_t dictSize,
- ZSTD_dictLoadMethod_e dictLoadMethod,
- ZSTD_dictContentType_e dictContentType)
-{
- if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dict) || (!dictSize)) {
- ddict->dictBuffer = NULL;
- ddict->dictContent = dict;
- } else {
- void* const internalBuffer = ZSTD_malloc(dictSize, ddict->cMem);
- ddict->dictBuffer = internalBuffer;
- ddict->dictContent = internalBuffer;
- if (!internalBuffer) return ERROR(memory_allocation);
- memcpy(internalBuffer, dict, dictSize);
+ FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) );
+ if (ddict) { /* NULL ddict is equivalent to no dictionary */
+ ZSTD_copyDDictParameters(dctx, ddict);
}
- ddict->dictSize = dictSize;
- ddict->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
-
- /* parse dictionary content */
- CHECK_F( ZSTD_loadEntropy_inDDict(ddict, dictContentType) );
-
return 0;
}
-ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize,
- ZSTD_dictLoadMethod_e dictLoadMethod,
- ZSTD_dictContentType_e dictContentType,
- ZSTD_customMem customMem)
-{
- if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
-
- { ZSTD_DDict* const ddict = (ZSTD_DDict*) ZSTD_malloc(sizeof(ZSTD_DDict), customMem);
- if (!ddict) return NULL;
- ddict->cMem = customMem;
-
- if (ZSTD_isError( ZSTD_initDDict_internal(ddict, dict, dictSize, dictLoadMethod, dictContentType) )) {
- ZSTD_freeDDict(ddict);
- return NULL;
- }
-
- return ddict;
- }
-}
-
-/*! ZSTD_createDDict() :
-* Create a digested dictionary, to start decompression without startup delay.
-* `dict` content is copied inside DDict.
-* Consequently, `dict` can be released after `ZSTD_DDict` creation */
-ZSTD_DDict* ZSTD_createDDict(const void* dict, size_t dictSize)
-{
- ZSTD_customMem const allocator = { NULL, NULL, NULL };
- return ZSTD_createDDict_advanced(dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto, allocator);
-}
-
-/*! ZSTD_createDDict_byReference() :
- * Create a digested dictionary, to start decompression without startup delay.
- * Dictionary content is simply referenced, it will be accessed during decompression.
- * Warning : dictBuffer must outlive DDict (DDict must be freed before dictBuffer) */
-ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize)
-{
- ZSTD_customMem const allocator = { NULL, NULL, NULL };
- return ZSTD_createDDict_advanced(dictBuffer, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto, allocator);
-}
-
-
-const ZSTD_DDict* ZSTD_initStaticDDict(
- void* workspace, size_t workspaceSize,
- const void* dict, size_t dictSize,
- ZSTD_dictLoadMethod_e dictLoadMethod,
- ZSTD_dictContentType_e dictContentType)
-{
- size_t const neededSpace =
- sizeof(ZSTD_DDict) + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize);
- ZSTD_DDict* const ddict = (ZSTD_DDict*)workspace;
- assert(workspace != NULL);
- assert(dict != NULL);
- if ((size_t)workspace & 7) return NULL; /* 8-aligned */
- if (workspaceSize < neededSpace) return NULL;
- if (dictLoadMethod == ZSTD_dlm_byCopy) {
- memcpy(ddict+1, dict, dictSize); /* local copy */
- dict = ddict+1;
- }
- if (ZSTD_isError( ZSTD_initDDict_internal(ddict, dict, dictSize, ZSTD_dlm_byRef, dictContentType) ))
- return NULL;
- return ddict;
-}
-
-
-size_t ZSTD_freeDDict(ZSTD_DDict* ddict)
-{
- if (ddict==NULL) return 0; /* support free on NULL */
- { ZSTD_customMem const cMem = ddict->cMem;
- ZSTD_free(ddict->dictBuffer, cMem);
- ZSTD_free(ddict, cMem);
- return 0;
- }
-}
-
-/*! ZSTD_estimateDDictSize() :
- * Estimate amount of memory that will be needed to create a dictionary for decompression.
- * Note : dictionary created by reference using ZSTD_dlm_byRef are smaller */
-size_t ZSTD_estimateDDictSize(size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod)
-{
- return sizeof(ZSTD_DDict) + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize);
-}
-
-size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict)
-{
- if (ddict==NULL) return 0; /* support sizeof on NULL */
- return sizeof(*ddict) + (ddict->dictBuffer ? ddict->dictSize : 0) ;
-}
-
/*! ZSTD_getDictID_fromDict() :
* Provides the dictID stored within dictionary.
* if @return == 0, the dictionary is not conformant with Zstandard specification.
@@ -2484,21 +1183,11 @@ unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize)
{
if (dictSize < 8) return 0;
if (MEM_readLE32(dict) != ZSTD_MAGIC_DICTIONARY) return 0;
- return MEM_readLE32((const char*)dict + ZSTD_frameIdSize);
-}
-
-/*! ZSTD_getDictID_fromDDict() :
- * Provides the dictID of the dictionary loaded into `ddict`.
- * If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.
- * Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */
-unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict)
-{
- if (ddict==NULL) return 0;
- return ZSTD_getDictID_fromDict(ddict->dictContent, ddict->dictSize);
+ return MEM_readLE32((const char*)dict + ZSTD_FRAMEIDSIZE);
}
/*! ZSTD_getDictID_fromFrame() :
- * Provides the dictID required to decompresse frame stored within `src`.
+ * Provides the dictID required to decompress frame stored within `src`.
* If @return == 0, the dictID could not be decoded.
* This could for one of the following reasons :
* - The frame does not require a dictionary (most common case).
@@ -2560,22 +1249,24 @@ size_t ZSTD_freeDStream(ZSTD_DStream* zds)
}
-/* *** Initialization *** */
+/* *** Initialization *** */
size_t ZSTD_DStreamInSize(void) { return ZSTD_BLOCKSIZE_MAX + ZSTD_blockHeaderSize; }
size_t ZSTD_DStreamOutSize(void) { return ZSTD_BLOCKSIZE_MAX; }
-size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType)
+size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx,
+ const void* dict, size_t dictSize,
+ ZSTD_dictLoadMethod_e dictLoadMethod,
+ ZSTD_dictContentType_e dictContentType)
{
- if (dctx->streamStage != zdss_init) return ERROR(stage_wrong);
- ZSTD_freeDDict(dctx->ddictLocal);
+ RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
+ ZSTD_clearDict(dctx);
if (dict && dictSize >= 8) {
dctx->ddictLocal = ZSTD_createDDict_advanced(dict, dictSize, dictLoadMethod, dictContentType, dctx->customMem);
- if (dctx->ddictLocal == NULL) return ERROR(memory_allocation);
- } else {
- dctx->ddictLocal = NULL;
+ RETURN_ERROR_IF(dctx->ddictLocal == NULL, memory_allocation);
+ dctx->ddict = dctx->ddictLocal;
+ dctx->dictUses = ZSTD_use_indefinitely;
}
- dctx->ddict = dctx->ddictLocal;
return 0;
}
@@ -2591,7 +1282,9 @@ size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSi
size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType)
{
- return ZSTD_DCtx_loadDictionary_advanced(dctx, prefix, prefixSize, ZSTD_dlm_byRef, dictContentType);
+ FORWARD_IF_ERROR(ZSTD_DCtx_loadDictionary_advanced(dctx, prefix, prefixSize, ZSTD_dlm_byRef, dictContentType));
+ dctx->dictUses = ZSTD_use_once;
+ return 0;
}
size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize)
@@ -2601,28 +1294,21 @@ size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSiz
/* ZSTD_initDStream_usingDict() :
- * return : expected size, aka ZSTD_frameHeaderSize_prefix.
+ * return : expected size, aka ZSTD_FRAMEHEADERSIZE_PREFIX.
* this function cannot fail */
size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize)
{
DEBUGLOG(4, "ZSTD_initDStream_usingDict");
- zds->streamStage = zdss_init;
- CHECK_F( ZSTD_DCtx_loadDictionary(zds, dict, dictSize) );
- return ZSTD_frameHeaderSize_prefix;
+ FORWARD_IF_ERROR( ZSTD_DCtx_reset(zds, ZSTD_reset_session_only) );
+ FORWARD_IF_ERROR( ZSTD_DCtx_loadDictionary(zds, dict, dictSize) );
+ return ZSTD_FRAMEHEADERSIZE_PREFIX;
}
/* note : this variant can't fail */
size_t ZSTD_initDStream(ZSTD_DStream* zds)
{
DEBUGLOG(4, "ZSTD_initDStream");
- return ZSTD_initDStream_usingDict(zds, NULL, 0);
-}
-
-size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
-{
- if (dctx->streamStage != zdss_init) return ERROR(stage_wrong);
- dctx->ddict = ddict;
- return 0;
+ return ZSTD_initDStream_usingDDict(zds, NULL);
}
/* ZSTD_initDStream_usingDDict() :
@@ -2630,51 +1316,119 @@ size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
* this function cannot fail */
size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
{
- size_t const initResult = ZSTD_initDStream(dctx);
- dctx->ddict = ddict;
- return initResult;
+ FORWARD_IF_ERROR( ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only) );
+ FORWARD_IF_ERROR( ZSTD_DCtx_refDDict(dctx, ddict) );
+ return ZSTD_FRAMEHEADERSIZE_PREFIX;
}
/* ZSTD_resetDStream() :
- * return : expected size, aka ZSTD_frameHeaderSize_prefix.
+ * return : expected size, aka ZSTD_FRAMEHEADERSIZE_PREFIX.
* this function cannot fail */
size_t ZSTD_resetDStream(ZSTD_DStream* dctx)
{
- DEBUGLOG(4, "ZSTD_resetDStream");
- dctx->streamStage = zdss_loadHeader;
- dctx->lhSize = dctx->inPos = dctx->outStart = dctx->outEnd = 0;
- dctx->legacyVersion = 0;
- dctx->hostageByte = 0;
- return ZSTD_frameHeaderSize_prefix;
+ FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only));
+ return ZSTD_FRAMEHEADERSIZE_PREFIX;
}
-size_t ZSTD_setDStreamParameter(ZSTD_DStream* dctx,
- ZSTD_DStreamParameter_e paramType, unsigned paramValue)
+
+size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
{
- if (dctx->streamStage != zdss_init) return ERROR(stage_wrong);
- switch(paramType)
- {
- default : return ERROR(parameter_unsupported);
- case DStream_p_maxWindowSize :
- DEBUGLOG(4, "setting maxWindowSize = %u KB", paramValue >> 10);
- dctx->maxWindowSize = paramValue ? paramValue : (U32)(-1);
- break;
+ RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
+ ZSTD_clearDict(dctx);
+ if (ddict) {
+ dctx->ddict = ddict;
+ dctx->dictUses = ZSTD_use_indefinitely;
}
return 0;
}
+/* ZSTD_DCtx_setMaxWindowSize() :
+ * note : no direct equivalence in ZSTD_DCtx_setParameter,
+ * since this version sets windowSize, and the other sets windowLog */
size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize)
{
- if (dctx->streamStage != zdss_init) return ERROR(stage_wrong);
+ ZSTD_bounds const bounds = ZSTD_dParam_getBounds(ZSTD_d_windowLogMax);
+ size_t const min = (size_t)1 << bounds.lowerBound;
+ size_t const max = (size_t)1 << bounds.upperBound;
+ RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
+ RETURN_ERROR_IF(maxWindowSize < min, parameter_outOfBound);
+ RETURN_ERROR_IF(maxWindowSize > max, parameter_outOfBound);
dctx->maxWindowSize = maxWindowSize;
return 0;
}
size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format)
{
- DEBUGLOG(4, "ZSTD_DCtx_setFormat : %u", (unsigned)format);
- if (dctx->streamStage != zdss_init) return ERROR(stage_wrong);
- dctx->format = format;
+ return ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, format);
+}
+
+ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
+{
+ ZSTD_bounds bounds = { 0, 0, 0 };
+ switch(dParam) {
+ case ZSTD_d_windowLogMax:
+ bounds.lowerBound = ZSTD_WINDOWLOG_ABSOLUTEMIN;
+ bounds.upperBound = ZSTD_WINDOWLOG_MAX;
+ return bounds;
+ case ZSTD_d_format:
+ bounds.lowerBound = (int)ZSTD_f_zstd1;
+ bounds.upperBound = (int)ZSTD_f_zstd1_magicless;
+ ZSTD_STATIC_ASSERT(ZSTD_f_zstd1 < ZSTD_f_zstd1_magicless);
+ return bounds;
+ default:;
+ }
+ bounds.error = ERROR(parameter_unsupported);
+ return bounds;
+}
+
+/* ZSTD_dParam_withinBounds:
+ * @return 1 if value is within dParam bounds,
+ * 0 otherwise */
+static int ZSTD_dParam_withinBounds(ZSTD_dParameter dParam, int value)
+{
+ ZSTD_bounds const bounds = ZSTD_dParam_getBounds(dParam);
+ if (ZSTD_isError(bounds.error)) return 0;
+ if (value < bounds.lowerBound) return 0;
+ if (value > bounds.upperBound) return 0;
+ return 1;
+}
+
+#define CHECK_DBOUNDS(p,v) { \
+ RETURN_ERROR_IF(!ZSTD_dParam_withinBounds(p, v), parameter_outOfBound); \
+}
+
+size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value)
+{
+ RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
+ switch(dParam) {
+ case ZSTD_d_windowLogMax:
+ if (value == 0) value = ZSTD_WINDOWLOG_LIMIT_DEFAULT;
+ CHECK_DBOUNDS(ZSTD_d_windowLogMax, value);
+ dctx->maxWindowSize = ((size_t)1) << value;
+ return 0;
+ case ZSTD_d_format:
+ CHECK_DBOUNDS(ZSTD_d_format, value);
+ dctx->format = (ZSTD_format_e)value;
+ return 0;
+ default:;
+ }
+ RETURN_ERROR(parameter_unsupported);
+}
+
+size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset)
+{
+ if ( (reset == ZSTD_reset_session_only)
+ || (reset == ZSTD_reset_session_and_parameters) ) {
+ dctx->streamStage = zdss_init;
+ dctx->noForwardProgress = 0;
+ }
+ if ( (reset == ZSTD_reset_parameters)
+ || (reset == ZSTD_reset_session_and_parameters) ) {
+ RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
+ ZSTD_clearDict(dctx);
+ dctx->format = ZSTD_f_zstd1;
+ dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
+ }
return 0;
}
@@ -2690,7 +1444,8 @@ size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long
unsigned long long const neededRBSize = windowSize + blockSize + (WILDCOPY_OVERLENGTH * 2);
unsigned long long const neededSize = MIN(frameContentSize, neededRBSize);
size_t const minRBSize = (size_t) neededSize;
- if ((unsigned long long)minRBSize != neededSize) return ERROR(frameParameter_windowTooLarge);
+ RETURN_ERROR_IF((unsigned long long)minRBSize != neededSize,
+ frameParameter_windowTooLarge);
return minRBSize;
}
@@ -2704,13 +1459,13 @@ size_t ZSTD_estimateDStreamSize(size_t windowSize)
size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize)
{
- U32 const windowSizeMax = 1U << ZSTD_WINDOWLOG_MAX; /* note : should be user-selectable */
+ U32 const windowSizeMax = 1U << ZSTD_WINDOWLOG_MAX; /* note : should be user-selectable, but requires an additional parameter (or a dctx) */
ZSTD_frameHeader zfh;
size_t const err = ZSTD_getFrameHeader(&zfh, src, srcSize);
if (ZSTD_isError(err)) return err;
- if (err>0) return ERROR(srcSize_wrong);
- if (zfh.windowSize > windowSizeMax)
- return ERROR(frameParameter_windowTooLarge);
+ RETURN_ERROR_IF(err>0, srcSize_wrong);
+ RETURN_ERROR_IF(zfh.windowSize > windowSizeMax,
+ frameParameter_windowTooLarge);
return ZSTD_estimateDStreamSize((size_t)zfh.windowSize);
}
@@ -2736,16 +1491,16 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
U32 someMoreWork = 1;
DEBUGLOG(5, "ZSTD_decompressStream");
- if (input->pos > input->size) { /* forbidden */
- DEBUGLOG(5, "in: pos: %u vs size: %u",
- (U32)input->pos, (U32)input->size);
- return ERROR(srcSize_wrong);
- }
- if (output->pos > output->size) { /* forbidden */
- DEBUGLOG(5, "out: pos: %u vs size: %u",
- (U32)output->pos, (U32)output->size);
- return ERROR(dstSize_tooSmall);
- }
+ RETURN_ERROR_IF(
+ input->pos > input->size,
+ srcSize_wrong,
+ "forbidden. in: pos: %u vs size: %u",
+ (U32)input->pos, (U32)input->size);
+ RETURN_ERROR_IF(
+ output->pos > output->size,
+ dstSize_tooSmall,
+ "forbidden. out: pos: %u vs size: %u",
+ (U32)output->pos, (U32)output->size);
DEBUGLOG(5, "input size : %u", (U32)(input->size - input->pos));
while (someMoreWork) {
@@ -2753,32 +1508,36 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
{
case zdss_init :
DEBUGLOG(5, "stage zdss_init => transparent reset ");
- ZSTD_resetDStream(zds); /* transparent reset on starting decoding a new frame */
+ zds->streamStage = zdss_loadHeader;
+ zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
+ zds->legacyVersion = 0;
+ zds->hostageByte = 0;
/* fall-through */
case zdss_loadHeader :
DEBUGLOG(5, "stage zdss_loadHeader (srcSize : %u)", (U32)(iend - ip));
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
if (zds->legacyVersion) {
- /* legacy support is incompatible with static dctx */
- if (zds->staticSize) return ERROR(memory_allocation);
+ RETURN_ERROR_IF(zds->staticSize, memory_allocation,
+ "legacy support is incompatible with static dctx");
{ size_t const hint = ZSTD_decompressLegacyStream(zds->legacyContext, zds->legacyVersion, output, input);
if (hint==0) zds->streamStage = zdss_init;
return hint;
} }
#endif
- { size_t const hSize = ZSTD_getFrameHeader_internal(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format);
+ { size_t const hSize = ZSTD_getFrameHeader_advanced(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format);
DEBUGLOG(5, "header size : %u", (U32)hSize);
if (ZSTD_isError(hSize)) {
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
U32 const legacyVersion = ZSTD_isLegacy(istart, iend-istart);
if (legacyVersion) {
- const void* const dict = zds->ddict ? zds->ddict->dictContent : NULL;
- size_t const dictSize = zds->ddict ? zds->ddict->dictSize : 0;
+ ZSTD_DDict const* const ddict = ZSTD_getDDict(zds);
+ const void* const dict = ddict ? ZSTD_DDict_dictContent(ddict) : NULL;
+ size_t const dictSize = ddict ? ZSTD_DDict_dictSize(ddict) : 0;
DEBUGLOG(5, "ZSTD_decompressStream: detected legacy version v0.%u", legacyVersion);
- /* legacy support is incompatible with static dctx */
- if (zds->staticSize) return ERROR(memory_allocation);
- CHECK_F(ZSTD_initLegacyStream(&zds->legacyContext,
+ RETURN_ERROR_IF(zds->staticSize, memory_allocation,
+ "legacy support is incompatible with static dctx");
+ FORWARD_IF_ERROR(ZSTD_initLegacyStream(&zds->legacyContext,
zds->previousLegacyVersion, legacyVersion,
dict, dictSize));
zds->legacyVersion = zds->previousLegacyVersion = legacyVersion;
@@ -2799,7 +1558,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
zds->lhSize += remainingInput;
}
input->pos = input->size;
- return (MAX(ZSTD_frameHeaderSize_min, hSize) - zds->lhSize) + ZSTD_blockHeaderSize; /* remaining header bytes + next block header */
+ return (MAX(ZSTD_FRAMEHEADERSIZE_MIN, hSize) - zds->lhSize) + ZSTD_blockHeaderSize; /* remaining header bytes + next block header */
}
assert(ip != NULL);
memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad); zds->lhSize = hSize; ip += toLoad;
@@ -2812,7 +1571,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
size_t const cSize = ZSTD_findFrameCompressedSize(istart, iend-istart);
if (cSize <= (size_t)(iend-istart)) {
/* shortcut : using single-pass mode */
- size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, oend-op, istart, cSize, zds->ddict);
+ size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, oend-op, istart, cSize, ZSTD_getDDict(zds));
if (ZSTD_isError(decompressedSize)) return decompressedSize;
DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()")
ip = istart + cSize;
@@ -2825,13 +1584,13 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
/* Consume header (see ZSTDds_decodeFrameHeader) */
DEBUGLOG(4, "Consume header");
- CHECK_F(ZSTD_decompressBegin_usingDDict(zds, zds->ddict));
+ FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(zds, ZSTD_getDDict(zds)));
- if ((MEM_readLE32(zds->headerBuffer) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
- zds->expected = MEM_readLE32(zds->headerBuffer + ZSTD_frameIdSize);
+ if ((MEM_readLE32(zds->headerBuffer) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
+ zds->expected = MEM_readLE32(zds->headerBuffer + ZSTD_FRAMEIDSIZE);
zds->stage = ZSTDds_skipFrame;
} else {
- CHECK_F(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize));
+ FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize));
zds->expected = ZSTD_blockHeaderSize;
zds->stage = ZSTDds_decodeBlockHeader;
}
@@ -2841,7 +1600,8 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
(U32)(zds->fParams.windowSize >>10),
(U32)(zds->maxWindowSize >> 10) );
zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN);
- if (zds->fParams.windowSize > zds->maxWindowSize) return ERROR(frameParameter_windowTooLarge);
+ RETURN_ERROR_IF(zds->fParams.windowSize > zds->maxWindowSize,
+ frameParameter_windowTooLarge);
/* Adapt buffer sizes to frame header instructions */
{ size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */);
@@ -2855,14 +1615,15 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
if (zds->staticSize) { /* static DCtx */
DEBUGLOG(4, "staticSize : %u", (U32)zds->staticSize);
assert(zds->staticSize >= sizeof(ZSTD_DCtx)); /* controlled at init */
- if (bufferSize > zds->staticSize - sizeof(ZSTD_DCtx))
- return ERROR(memory_allocation);
+ RETURN_ERROR_IF(
+ bufferSize > zds->staticSize - sizeof(ZSTD_DCtx),
+ memory_allocation);
} else {
ZSTD_free(zds->inBuff, zds->customMem);
zds->inBuffSize = 0;
zds->outBuffSize = 0;
zds->inBuff = (char*)ZSTD_malloc(bufferSize, zds->customMem);
- if (zds->inBuff == NULL) return ERROR(memory_allocation);
+ RETURN_ERROR_IF(zds->inBuff == NULL, memory_allocation);
}
zds->inBuffSize = neededInBuffSize;
zds->outBuff = zds->inBuff + zds->inBuffSize;
@@ -2904,7 +1665,9 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
if (isSkipFrame) {
loadedSize = MIN(toLoad, (size_t)(iend-ip));
} else {
- if (toLoad > zds->inBuffSize - zds->inPos) return ERROR(corruption_detected); /* should never happen */
+ RETURN_ERROR_IF(toLoad > zds->inBuffSize - zds->inPos,
+ corruption_detected,
+ "should never happen");
loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, iend-ip);
}
ip += loadedSize;
@@ -2943,12 +1706,24 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
someMoreWork = 0;
break;
- default: return ERROR(GENERIC); /* impossible */
+ default:
+ assert(0); /* impossible */
+ RETURN_ERROR(GENERIC); /* some compiler require default to do something */
} }
/* result */
- input->pos += (size_t)(ip-istart);
- output->pos += (size_t)(op-ostart);
+ input->pos = (size_t)(ip - (const char*)(input->src));
+ output->pos = (size_t)(op - (char*)(output->dst));
+ if ((ip==istart) && (op==ostart)) { /* no forward progress */
+ zds->noForwardProgress ++;
+ if (zds->noForwardProgress >= ZSTD_NO_FORWARD_PROGRESS_MAX) {
+ RETURN_ERROR_IF(op==oend, dstSize_tooSmall);
+ RETURN_ERROR_IF(ip==iend, srcSize_wrong);
+ assert(0);
+ }
+ } else {
+ zds->noForwardProgress = 0;
+ }
{ size_t nextSrcSizeHint = ZSTD_nextSrcSizeToDecompress(zds);
if (!nextSrcSizeHint) { /* frame fully decoded */
if (zds->outEnd == zds->outStart) { /* output fully flushed */
@@ -2975,13 +1750,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
}
}
-
-size_t ZSTD_decompress_generic(ZSTD_DCtx* dctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
-{
- return ZSTD_decompressStream(dctx, output, input);
-}
-
-size_t ZSTD_decompress_generic_simpleArgs (
+size_t ZSTD_decompressStream_simpleArgs (
ZSTD_DCtx* dctx,
void* dst, size_t dstCapacity, size_t* dstPos,
const void* src, size_t srcSize, size_t* srcPos)
@@ -2989,15 +1758,8 @@ size_t ZSTD_decompress_generic_simpleArgs (
ZSTD_outBuffer output = { dst, dstCapacity, *dstPos };
ZSTD_inBuffer input = { src, srcSize, *srcPos };
/* ZSTD_compress_generic() will check validity of dstPos and srcPos */
- size_t const cErr = ZSTD_decompress_generic(dctx, &output, &input);
+ size_t const cErr = ZSTD_decompressStream(dctx, &output, &input);
*dstPos = output.pos;
*srcPos = input.pos;
return cErr;
}
-
-void ZSTD_DCtx_reset(ZSTD_DCtx* dctx)
-{
- (void)ZSTD_initDStream(dctx);
- dctx->format = ZSTD_f_zstd1;
- dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
-}
diff --git a/thirdparty/zstd/decompress/zstd_decompress_block.c b/thirdparty/zstd/decompress/zstd_decompress_block.c
new file mode 100644
index 0000000000..a2a7eedcf2
--- /dev/null
+++ b/thirdparty/zstd/decompress/zstd_decompress_block.c
@@ -0,0 +1,1311 @@
+/*
+ * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+/* zstd_decompress_block :
+ * this module takes care of decompressing _compressed_ block */
+
+/*-*******************************************************
+* Dependencies
+*********************************************************/
+#include <string.h> /* memcpy, memmove, memset */
+#include "compiler.h" /* prefetch */
+#include "cpu.h" /* bmi2 */
+#include "mem.h" /* low level memory routines */
+#define FSE_STATIC_LINKING_ONLY
+#include "fse.h"
+#define HUF_STATIC_LINKING_ONLY
+#include "huf.h"
+#include "zstd_internal.h"
+#include "zstd_decompress_internal.h" /* ZSTD_DCtx */
+#include "zstd_ddict.h" /* ZSTD_DDictDictContent */
+#include "zstd_decompress_block.h"
+
+/*_*******************************************************
+* Macros
+**********************************************************/
+
+/* These two optional macros force the use one way or another of the two
+ * ZSTD_decompressSequences implementations. You can't force in both directions
+ * at the same time.
+ */
+#if defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT) && \
+ defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG)
+#error "Cannot force the use of the short and the long ZSTD_decompressSequences variants!"
+#endif
+
+
+/*_*******************************************************
+* Memory operations
+**********************************************************/
+static void ZSTD_copy4(void* dst, const void* src) { memcpy(dst, src, 4); }
+
+
+/*-*************************************************************
+ * Block decoding
+ ***************************************************************/
+
+/*! ZSTD_getcBlockSize() :
+ * Provides the size of compressed block from block header `src` */
+size_t ZSTD_getcBlockSize(const void* src, size_t srcSize,
+ blockProperties_t* bpPtr)
+{
+ RETURN_ERROR_IF(srcSize < ZSTD_blockHeaderSize, srcSize_wrong);
+
+ { U32 const cBlockHeader = MEM_readLE24(src);
+ U32 const cSize = cBlockHeader >> 3;
+ bpPtr->lastBlock = cBlockHeader & 1;
+ bpPtr->blockType = (blockType_e)((cBlockHeader >> 1) & 3);
+ bpPtr->origSize = cSize; /* only useful for RLE */
+ if (bpPtr->blockType == bt_rle) return 1;
+ RETURN_ERROR_IF(bpPtr->blockType == bt_reserved, corruption_detected);
+ return cSize;
+ }
+}
+
+
+/* Hidden declaration for fullbench */
+size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
+ const void* src, size_t srcSize);
+/*! ZSTD_decodeLiteralsBlock() :
+ * @return : nb of bytes read from src (< srcSize )
+ * note : symbol not declared but exposed for fullbench */
+size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
+ const void* src, size_t srcSize) /* note : srcSize < BLOCKSIZE */
+{
+ RETURN_ERROR_IF(srcSize < MIN_CBLOCK_SIZE, corruption_detected);
+
+ { const BYTE* const istart = (const BYTE*) src;
+ symbolEncodingType_e const litEncType = (symbolEncodingType_e)(istart[0] & 3);
+
+ switch(litEncType)
+ {
+ case set_repeat:
+ RETURN_ERROR_IF(dctx->litEntropy==0, dictionary_corrupted);
+ /* fall-through */
+
+ case set_compressed:
+ RETURN_ERROR_IF(srcSize < 5, corruption_detected, "srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for case 3");
+ { size_t lhSize, litSize, litCSize;
+ U32 singleStream=0;
+ U32 const lhlCode = (istart[0] >> 2) & 3;
+ U32 const lhc = MEM_readLE32(istart);
+ size_t hufSuccess;
+ switch(lhlCode)
+ {
+ case 0: case 1: default: /* note : default is impossible, since lhlCode into [0..3] */
+ /* 2 - 2 - 10 - 10 */
+ singleStream = !lhlCode;
+ lhSize = 3;
+ litSize = (lhc >> 4) & 0x3FF;
+ litCSize = (lhc >> 14) & 0x3FF;
+ break;
+ case 2:
+ /* 2 - 2 - 14 - 14 */
+ lhSize = 4;
+ litSize = (lhc >> 4) & 0x3FFF;
+ litCSize = lhc >> 18;
+ break;
+ case 3:
+ /* 2 - 2 - 18 - 18 */
+ lhSize = 5;
+ litSize = (lhc >> 4) & 0x3FFFF;
+ litCSize = (lhc >> 22) + (istart[4] << 10);
+ break;
+ }
+ RETURN_ERROR_IF(litSize > ZSTD_BLOCKSIZE_MAX, corruption_detected);
+ RETURN_ERROR_IF(litCSize + lhSize > srcSize, corruption_detected);
+
+ /* prefetch huffman table if cold */
+ if (dctx->ddictIsCold && (litSize > 768 /* heuristic */)) {
+ PREFETCH_AREA(dctx->HUFptr, sizeof(dctx->entropy.hufTable));
+ }
+
+ if (litEncType==set_repeat) {
+ if (singleStream) {
+ hufSuccess = HUF_decompress1X_usingDTable_bmi2(
+ dctx->litBuffer, litSize, istart+lhSize, litCSize,
+ dctx->HUFptr, dctx->bmi2);
+ } else {
+ hufSuccess = HUF_decompress4X_usingDTable_bmi2(
+ dctx->litBuffer, litSize, istart+lhSize, litCSize,
+ dctx->HUFptr, dctx->bmi2);
+ }
+ } else {
+ if (singleStream) {
+#if defined(HUF_FORCE_DECOMPRESS_X2)
+ hufSuccess = HUF_decompress1X_DCtx_wksp(
+ dctx->entropy.hufTable, dctx->litBuffer, litSize,
+ istart+lhSize, litCSize, dctx->workspace,
+ sizeof(dctx->workspace));
+#else
+ hufSuccess = HUF_decompress1X1_DCtx_wksp_bmi2(
+ dctx->entropy.hufTable, dctx->litBuffer, litSize,
+ istart+lhSize, litCSize, dctx->workspace,
+ sizeof(dctx->workspace), dctx->bmi2);
+#endif
+ } else {
+ hufSuccess = HUF_decompress4X_hufOnly_wksp_bmi2(
+ dctx->entropy.hufTable, dctx->litBuffer, litSize,
+ istart+lhSize, litCSize, dctx->workspace,
+ sizeof(dctx->workspace), dctx->bmi2);
+ }
+ }
+
+ RETURN_ERROR_IF(HUF_isError(hufSuccess), corruption_detected);
+
+ dctx->litPtr = dctx->litBuffer;
+ dctx->litSize = litSize;
+ dctx->litEntropy = 1;
+ if (litEncType==set_compressed) dctx->HUFptr = dctx->entropy.hufTable;
+ memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);
+ return litCSize + lhSize;
+ }
+
+ case set_basic:
+ { size_t litSize, lhSize;
+ U32 const lhlCode = ((istart[0]) >> 2) & 3;
+ switch(lhlCode)
+ {
+ case 0: case 2: default: /* note : default is impossible, since lhlCode into [0..3] */
+ lhSize = 1;
+ litSize = istart[0] >> 3;
+ break;
+ case 1:
+ lhSize = 2;
+ litSize = MEM_readLE16(istart) >> 4;
+ break;
+ case 3:
+ lhSize = 3;
+ litSize = MEM_readLE24(istart) >> 4;
+ break;
+ }
+
+ if (lhSize+litSize+WILDCOPY_OVERLENGTH > srcSize) { /* risk reading beyond src buffer with wildcopy */
+ RETURN_ERROR_IF(litSize+lhSize > srcSize, corruption_detected);
+ memcpy(dctx->litBuffer, istart+lhSize, litSize);
+ dctx->litPtr = dctx->litBuffer;
+ dctx->litSize = litSize;
+ memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);
+ return lhSize+litSize;
+ }
+ /* direct reference into compressed stream */
+ dctx->litPtr = istart+lhSize;
+ dctx->litSize = litSize;
+ return lhSize+litSize;
+ }
+
+ case set_rle:
+ { U32 const lhlCode = ((istart[0]) >> 2) & 3;
+ size_t litSize, lhSize;
+ switch(lhlCode)
+ {
+ case 0: case 2: default: /* note : default is impossible, since lhlCode into [0..3] */
+ lhSize = 1;
+ litSize = istart[0] >> 3;
+ break;
+ case 1:
+ lhSize = 2;
+ litSize = MEM_readLE16(istart) >> 4;
+ break;
+ case 3:
+ lhSize = 3;
+ litSize = MEM_readLE24(istart) >> 4;
+ RETURN_ERROR_IF(srcSize<4, corruption_detected, "srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4");
+ break;
+ }
+ RETURN_ERROR_IF(litSize > ZSTD_BLOCKSIZE_MAX, corruption_detected);
+ memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH);
+ dctx->litPtr = dctx->litBuffer;
+ dctx->litSize = litSize;
+ return lhSize+1;
+ }
+ default:
+ RETURN_ERROR(corruption_detected, "impossible");
+ }
+ }
+}
+
+/* Default FSE distribution tables.
+ * These are pre-calculated FSE decoding tables using default distributions as defined in specification :
+ * https://github.com/facebook/zstd/blob/master/doc/zstd_compression_format.md#default-distributions
+ * They were generated programmatically with following method :
+ * - start from default distributions, present in /lib/common/zstd_internal.h
+ * - generate tables normally, using ZSTD_buildFSETable()
+ * - printout the content of tables
+ * - pretify output, report below, test with fuzzer to ensure it's correct */
+
+/* Default FSE distribution table for Literal Lengths */
+static const ZSTD_seqSymbol LL_defaultDTable[(1<<LL_DEFAULTNORMLOG)+1] = {
+ { 1, 1, 1, LL_DEFAULTNORMLOG}, /* header : fastMode, tableLog */
+ /* nextState, nbAddBits, nbBits, baseVal */
+ { 0, 0, 4, 0}, { 16, 0, 4, 0},
+ { 32, 0, 5, 1}, { 0, 0, 5, 3},
+ { 0, 0, 5, 4}, { 0, 0, 5, 6},
+ { 0, 0, 5, 7}, { 0, 0, 5, 9},
+ { 0, 0, 5, 10}, { 0, 0, 5, 12},
+ { 0, 0, 6, 14}, { 0, 1, 5, 16},
+ { 0, 1, 5, 20}, { 0, 1, 5, 22},
+ { 0, 2, 5, 28}, { 0, 3, 5, 32},
+ { 0, 4, 5, 48}, { 32, 6, 5, 64},
+ { 0, 7, 5, 128}, { 0, 8, 6, 256},
+ { 0, 10, 6, 1024}, { 0, 12, 6, 4096},
+ { 32, 0, 4, 0}, { 0, 0, 4, 1},
+ { 0, 0, 5, 2}, { 32, 0, 5, 4},
+ { 0, 0, 5, 5}, { 32, 0, 5, 7},
+ { 0, 0, 5, 8}, { 32, 0, 5, 10},
+ { 0, 0, 5, 11}, { 0, 0, 6, 13},
+ { 32, 1, 5, 16}, { 0, 1, 5, 18},
+ { 32, 1, 5, 22}, { 0, 2, 5, 24},
+ { 32, 3, 5, 32}, { 0, 3, 5, 40},
+ { 0, 6, 4, 64}, { 16, 6, 4, 64},
+ { 32, 7, 5, 128}, { 0, 9, 6, 512},
+ { 0, 11, 6, 2048}, { 48, 0, 4, 0},
+ { 16, 0, 4, 1}, { 32, 0, 5, 2},
+ { 32, 0, 5, 3}, { 32, 0, 5, 5},
+ { 32, 0, 5, 6}, { 32, 0, 5, 8},
+ { 32, 0, 5, 9}, { 32, 0, 5, 11},
+ { 32, 0, 5, 12}, { 0, 0, 6, 15},
+ { 32, 1, 5, 18}, { 32, 1, 5, 20},
+ { 32, 2, 5, 24}, { 32, 2, 5, 28},
+ { 32, 3, 5, 40}, { 32, 4, 5, 48},
+ { 0, 16, 6,65536}, { 0, 15, 6,32768},
+ { 0, 14, 6,16384}, { 0, 13, 6, 8192},
+}; /* LL_defaultDTable */
+
+/* Default FSE distribution table for Offset Codes */
+static const ZSTD_seqSymbol OF_defaultDTable[(1<<OF_DEFAULTNORMLOG)+1] = {
+ { 1, 1, 1, OF_DEFAULTNORMLOG}, /* header : fastMode, tableLog */
+ /* nextState, nbAddBits, nbBits, baseVal */
+ { 0, 0, 5, 0}, { 0, 6, 4, 61},
+ { 0, 9, 5, 509}, { 0, 15, 5,32765},
+ { 0, 21, 5,2097149}, { 0, 3, 5, 5},
+ { 0, 7, 4, 125}, { 0, 12, 5, 4093},
+ { 0, 18, 5,262141}, { 0, 23, 5,8388605},
+ { 0, 5, 5, 29}, { 0, 8, 4, 253},
+ { 0, 14, 5,16381}, { 0, 20, 5,1048573},
+ { 0, 2, 5, 1}, { 16, 7, 4, 125},
+ { 0, 11, 5, 2045}, { 0, 17, 5,131069},
+ { 0, 22, 5,4194301}, { 0, 4, 5, 13},
+ { 16, 8, 4, 253}, { 0, 13, 5, 8189},
+ { 0, 19, 5,524285}, { 0, 1, 5, 1},
+ { 16, 6, 4, 61}, { 0, 10, 5, 1021},
+ { 0, 16, 5,65533}, { 0, 28, 5,268435453},
+ { 0, 27, 5,134217725}, { 0, 26, 5,67108861},
+ { 0, 25, 5,33554429}, { 0, 24, 5,16777213},
+}; /* OF_defaultDTable */
+
+
+/* Default FSE distribution table for Match Lengths */
+static const ZSTD_seqSymbol ML_defaultDTable[(1<<ML_DEFAULTNORMLOG)+1] = {
+ { 1, 1, 1, ML_DEFAULTNORMLOG}, /* header : fastMode, tableLog */
+ /* nextState, nbAddBits, nbBits, baseVal */
+ { 0, 0, 6, 3}, { 0, 0, 4, 4},
+ { 32, 0, 5, 5}, { 0, 0, 5, 6},
+ { 0, 0, 5, 8}, { 0, 0, 5, 9},
+ { 0, 0, 5, 11}, { 0, 0, 6, 13},
+ { 0, 0, 6, 16}, { 0, 0, 6, 19},
+ { 0, 0, 6, 22}, { 0, 0, 6, 25},
+ { 0, 0, 6, 28}, { 0, 0, 6, 31},
+ { 0, 0, 6, 34}, { 0, 1, 6, 37},
+ { 0, 1, 6, 41}, { 0, 2, 6, 47},
+ { 0, 3, 6, 59}, { 0, 4, 6, 83},
+ { 0, 7, 6, 131}, { 0, 9, 6, 515},
+ { 16, 0, 4, 4}, { 0, 0, 4, 5},
+ { 32, 0, 5, 6}, { 0, 0, 5, 7},
+ { 32, 0, 5, 9}, { 0, 0, 5, 10},
+ { 0, 0, 6, 12}, { 0, 0, 6, 15},
+ { 0, 0, 6, 18}, { 0, 0, 6, 21},
+ { 0, 0, 6, 24}, { 0, 0, 6, 27},
+ { 0, 0, 6, 30}, { 0, 0, 6, 33},
+ { 0, 1, 6, 35}, { 0, 1, 6, 39},
+ { 0, 2, 6, 43}, { 0, 3, 6, 51},
+ { 0, 4, 6, 67}, { 0, 5, 6, 99},
+ { 0, 8, 6, 259}, { 32, 0, 4, 4},
+ { 48, 0, 4, 4}, { 16, 0, 4, 5},
+ { 32, 0, 5, 7}, { 32, 0, 5, 8},
+ { 32, 0, 5, 10}, { 32, 0, 5, 11},
+ { 0, 0, 6, 14}, { 0, 0, 6, 17},
+ { 0, 0, 6, 20}, { 0, 0, 6, 23},
+ { 0, 0, 6, 26}, { 0, 0, 6, 29},
+ { 0, 0, 6, 32}, { 0, 16, 6,65539},
+ { 0, 15, 6,32771}, { 0, 14, 6,16387},
+ { 0, 13, 6, 8195}, { 0, 12, 6, 4099},
+ { 0, 11, 6, 2051}, { 0, 10, 6, 1027},
+}; /* ML_defaultDTable */
+
+
+static void ZSTD_buildSeqTable_rle(ZSTD_seqSymbol* dt, U32 baseValue, U32 nbAddBits)
+{
+ void* ptr = dt;
+ ZSTD_seqSymbol_header* const DTableH = (ZSTD_seqSymbol_header*)ptr;
+ ZSTD_seqSymbol* const cell = dt + 1;
+
+ DTableH->tableLog = 0;
+ DTableH->fastMode = 0;
+
+ cell->nbBits = 0;
+ cell->nextState = 0;
+ assert(nbAddBits < 255);
+ cell->nbAdditionalBits = (BYTE)nbAddBits;
+ cell->baseValue = baseValue;
+}
+
+
+/* ZSTD_buildFSETable() :
+ * generate FSE decoding table for one symbol (ll, ml or off)
+ * cannot fail if input is valid =>
+ * all inputs are presumed validated at this stage */
+void
+ZSTD_buildFSETable(ZSTD_seqSymbol* dt,
+ const short* normalizedCounter, unsigned maxSymbolValue,
+ const U32* baseValue, const U32* nbAdditionalBits,
+ unsigned tableLog)
+{
+ ZSTD_seqSymbol* const tableDecode = dt+1;
+ U16 symbolNext[MaxSeq+1];
+
+ U32 const maxSV1 = maxSymbolValue + 1;
+ U32 const tableSize = 1 << tableLog;
+ U32 highThreshold = tableSize-1;
+
+ /* Sanity Checks */
+ assert(maxSymbolValue <= MaxSeq);
+ assert(tableLog <= MaxFSELog);
+
+ /* Init, lay down lowprob symbols */
+ { ZSTD_seqSymbol_header DTableH;
+ DTableH.tableLog = tableLog;
+ DTableH.fastMode = 1;
+ { S16 const largeLimit= (S16)(1 << (tableLog-1));
+ U32 s;
+ for (s=0; s<maxSV1; s++) {
+ if (normalizedCounter[s]==-1) {
+ tableDecode[highThreshold--].baseValue = s;
+ symbolNext[s] = 1;
+ } else {
+ if (normalizedCounter[s] >= largeLimit) DTableH.fastMode=0;
+ symbolNext[s] = normalizedCounter[s];
+ } } }
+ memcpy(dt, &DTableH, sizeof(DTableH));
+ }
+
+ /* Spread symbols */
+ { U32 const tableMask = tableSize-1;
+ U32 const step = FSE_TABLESTEP(tableSize);
+ U32 s, position = 0;
+ for (s=0; s<maxSV1; s++) {
+ int i;
+ for (i=0; i<normalizedCounter[s]; i++) {
+ tableDecode[position].baseValue = s;
+ position = (position + step) & tableMask;
+ while (position > highThreshold) position = (position + step) & tableMask; /* lowprob area */
+ } }
+ assert(position == 0); /* position must reach all cells once, otherwise normalizedCounter is incorrect */
+ }
+
+ /* Build Decoding table */
+ { U32 u;
+ for (u=0; u<tableSize; u++) {
+ U32 const symbol = tableDecode[u].baseValue;
+ U32 const nextState = symbolNext[symbol]++;
+ tableDecode[u].nbBits = (BYTE) (tableLog - BIT_highbit32(nextState) );
+ tableDecode[u].nextState = (U16) ( (nextState << tableDecode[u].nbBits) - tableSize);
+ assert(nbAdditionalBits[symbol] < 255);
+ tableDecode[u].nbAdditionalBits = (BYTE)nbAdditionalBits[symbol];
+ tableDecode[u].baseValue = baseValue[symbol];
+ } }
+}
+
+
+/*! ZSTD_buildSeqTable() :
+ * @return : nb bytes read from src,
+ * or an error code if it fails */
+static size_t ZSTD_buildSeqTable(ZSTD_seqSymbol* DTableSpace, const ZSTD_seqSymbol** DTablePtr,
+ symbolEncodingType_e type, unsigned max, U32 maxLog,
+ const void* src, size_t srcSize,
+ const U32* baseValue, const U32* nbAdditionalBits,
+ const ZSTD_seqSymbol* defaultTable, U32 flagRepeatTable,
+ int ddictIsCold, int nbSeq)
+{
+ switch(type)
+ {
+ case set_rle :
+ RETURN_ERROR_IF(!srcSize, srcSize_wrong);
+ RETURN_ERROR_IF((*(const BYTE*)src) > max, corruption_detected);
+ { U32 const symbol = *(const BYTE*)src;
+ U32 const baseline = baseValue[symbol];
+ U32 const nbBits = nbAdditionalBits[symbol];
+ ZSTD_buildSeqTable_rle(DTableSpace, baseline, nbBits);
+ }
+ *DTablePtr = DTableSpace;
+ return 1;
+ case set_basic :
+ *DTablePtr = defaultTable;
+ return 0;
+ case set_repeat:
+ RETURN_ERROR_IF(!flagRepeatTable, corruption_detected);
+ /* prefetch FSE table if used */
+ if (ddictIsCold && (nbSeq > 24 /* heuristic */)) {
+ const void* const pStart = *DTablePtr;
+ size_t const pSize = sizeof(ZSTD_seqSymbol) * (SEQSYMBOL_TABLE_SIZE(maxLog));
+ PREFETCH_AREA(pStart, pSize);
+ }
+ return 0;
+ case set_compressed :
+ { unsigned tableLog;
+ S16 norm[MaxSeq+1];
+ size_t const headerSize = FSE_readNCount(norm, &max, &tableLog, src, srcSize);
+ RETURN_ERROR_IF(FSE_isError(headerSize), corruption_detected);
+ RETURN_ERROR_IF(tableLog > maxLog, corruption_detected);
+ ZSTD_buildFSETable(DTableSpace, norm, max, baseValue, nbAdditionalBits, tableLog);
+ *DTablePtr = DTableSpace;
+ return headerSize;
+ }
+ default :
+ assert(0);
+ RETURN_ERROR(GENERIC, "impossible");
+ }
+}
+
+size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
+ const void* src, size_t srcSize)
+{
+ const BYTE* const istart = (const BYTE* const)src;
+ const BYTE* const iend = istart + srcSize;
+ const BYTE* ip = istart;
+ int nbSeq;
+ DEBUGLOG(5, "ZSTD_decodeSeqHeaders");
+
+ /* check */
+ RETURN_ERROR_IF(srcSize < MIN_SEQUENCES_SIZE, srcSize_wrong);
+
+ /* SeqHead */
+ nbSeq = *ip++;
+ if (!nbSeq) {
+ *nbSeqPtr=0;
+ RETURN_ERROR_IF(srcSize != 1, srcSize_wrong);
+ return 1;
+ }
+ if (nbSeq > 0x7F) {
+ if (nbSeq == 0xFF) {
+ RETURN_ERROR_IF(ip+2 > iend, srcSize_wrong);
+ nbSeq = MEM_readLE16(ip) + LONGNBSEQ, ip+=2;
+ } else {
+ RETURN_ERROR_IF(ip >= iend, srcSize_wrong);
+ nbSeq = ((nbSeq-0x80)<<8) + *ip++;
+ }
+ }
+ *nbSeqPtr = nbSeq;
+
+ /* FSE table descriptors */
+ RETURN_ERROR_IF(ip+4 > iend, srcSize_wrong); /* minimum possible size */
+ { symbolEncodingType_e const LLtype = (symbolEncodingType_e)(*ip >> 6);
+ symbolEncodingType_e const OFtype = (symbolEncodingType_e)((*ip >> 4) & 3);
+ symbolEncodingType_e const MLtype = (symbolEncodingType_e)((*ip >> 2) & 3);
+ ip++;
+
+ /* Build DTables */
+ { size_t const llhSize = ZSTD_buildSeqTable(dctx->entropy.LLTable, &dctx->LLTptr,
+ LLtype, MaxLL, LLFSELog,
+ ip, iend-ip,
+ LL_base, LL_bits,
+ LL_defaultDTable, dctx->fseEntropy,
+ dctx->ddictIsCold, nbSeq);
+ RETURN_ERROR_IF(ZSTD_isError(llhSize), corruption_detected);
+ ip += llhSize;
+ }
+
+ { size_t const ofhSize = ZSTD_buildSeqTable(dctx->entropy.OFTable, &dctx->OFTptr,
+ OFtype, MaxOff, OffFSELog,
+ ip, iend-ip,
+ OF_base, OF_bits,
+ OF_defaultDTable, dctx->fseEntropy,
+ dctx->ddictIsCold, nbSeq);
+ RETURN_ERROR_IF(ZSTD_isError(ofhSize), corruption_detected);
+ ip += ofhSize;
+ }
+
+ { size_t const mlhSize = ZSTD_buildSeqTable(dctx->entropy.MLTable, &dctx->MLTptr,
+ MLtype, MaxML, MLFSELog,
+ ip, iend-ip,
+ ML_base, ML_bits,
+ ML_defaultDTable, dctx->fseEntropy,
+ dctx->ddictIsCold, nbSeq);
+ RETURN_ERROR_IF(ZSTD_isError(mlhSize), corruption_detected);
+ ip += mlhSize;
+ }
+ }
+
+ return ip-istart;
+}
+
+
+typedef struct {
+ size_t litLength;
+ size_t matchLength;
+ size_t offset;
+ const BYTE* match;
+} seq_t;
+
+typedef struct {
+ size_t state;
+ const ZSTD_seqSymbol* table;
+} ZSTD_fseState;
+
+typedef struct {
+ BIT_DStream_t DStream;
+ ZSTD_fseState stateLL;
+ ZSTD_fseState stateOffb;
+ ZSTD_fseState stateML;
+ size_t prevOffset[ZSTD_REP_NUM];
+ const BYTE* prefixStart;
+ const BYTE* dictEnd;
+ size_t pos;
+} seqState_t;
+
+
+/* ZSTD_execSequenceLast7():
+ * exceptional case : decompress a match starting within last 7 bytes of output buffer.
+ * requires more careful checks, to ensure there is no overflow.
+ * performance does not matter though.
+ * note : this case is supposed to be never generated "naturally" by reference encoder,
+ * since in most cases it needs at least 8 bytes to look for a match.
+ * but it's allowed by the specification. */
+FORCE_NOINLINE
+size_t ZSTD_execSequenceLast7(BYTE* op,
+ BYTE* const oend, seq_t sequence,
+ const BYTE** litPtr, const BYTE* const litLimit,
+ const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)
+{
+ BYTE* const oLitEnd = op + sequence.litLength;
+ size_t const sequenceLength = sequence.litLength + sequence.matchLength;
+ BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
+ const BYTE* const iLitEnd = *litPtr + sequence.litLength;
+ const BYTE* match = oLitEnd - sequence.offset;
+
+ /* check */
+ RETURN_ERROR_IF(oMatchEnd>oend, dstSize_tooSmall, "last match must fit within dstBuffer");
+ RETURN_ERROR_IF(iLitEnd > litLimit, corruption_detected, "try to read beyond literal buffer");
+
+ /* copy literals */
+ while (op < oLitEnd) *op++ = *(*litPtr)++;
+
+ /* copy Match */
+ if (sequence.offset > (size_t)(oLitEnd - base)) {
+ /* offset beyond prefix */
+ RETURN_ERROR_IF(sequence.offset > (size_t)(oLitEnd - vBase),corruption_detected);
+ match = dictEnd - (base-match);
+ if (match + sequence.matchLength <= dictEnd) {
+ memmove(oLitEnd, match, sequence.matchLength);
+ return sequenceLength;
+ }
+ /* span extDict & currentPrefixSegment */
+ { size_t const length1 = dictEnd - match;
+ memmove(oLitEnd, match, length1);
+ op = oLitEnd + length1;
+ sequence.matchLength -= length1;
+ match = base;
+ } }
+ while (op < oMatchEnd) *op++ = *match++;
+ return sequenceLength;
+}
+
+
+HINT_INLINE
+size_t ZSTD_execSequence(BYTE* op,
+ BYTE* const oend, seq_t sequence,
+ const BYTE** litPtr, const BYTE* const litLimit,
+ const BYTE* const prefixStart, const BYTE* const virtualStart, const BYTE* const dictEnd)
+{
+ BYTE* const oLitEnd = op + sequence.litLength;
+ size_t const sequenceLength = sequence.litLength + sequence.matchLength;
+ BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
+ BYTE* const oend_w = oend - WILDCOPY_OVERLENGTH;
+ const BYTE* const iLitEnd = *litPtr + sequence.litLength;
+ const BYTE* match = oLitEnd - sequence.offset;
+
+ /* check */
+ RETURN_ERROR_IF(oMatchEnd>oend, dstSize_tooSmall, "last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend");
+ RETURN_ERROR_IF(iLitEnd > litLimit, corruption_detected, "over-read beyond lit buffer");
+ if (oLitEnd>oend_w) return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit, prefixStart, virtualStart, dictEnd);
+
+ /* copy Literals */
+ ZSTD_copy8(op, *litPtr);
+ if (sequence.litLength > 8)
+ ZSTD_wildcopy(op+8, (*litPtr)+8, sequence.litLength - 8); /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */
+ op = oLitEnd;
+ *litPtr = iLitEnd; /* update for next sequence */
+
+ /* copy Match */
+ if (sequence.offset > (size_t)(oLitEnd - prefixStart)) {
+ /* offset beyond prefix -> go into extDict */
+ RETURN_ERROR_IF(sequence.offset > (size_t)(oLitEnd - virtualStart), corruption_detected);
+ match = dictEnd + (match - prefixStart);
+ if (match + sequence.matchLength <= dictEnd) {
+ memmove(oLitEnd, match, sequence.matchLength);
+ return sequenceLength;
+ }
+ /* span extDict & currentPrefixSegment */
+ { size_t const length1 = dictEnd - match;
+ memmove(oLitEnd, match, length1);
+ op = oLitEnd + length1;
+ sequence.matchLength -= length1;
+ match = prefixStart;
+ if (op > oend_w || sequence.matchLength < MINMATCH) {
+ U32 i;
+ for (i = 0; i < sequence.matchLength; ++i) op[i] = match[i];
+ return sequenceLength;
+ }
+ } }
+ /* Requirement: op <= oend_w && sequence.matchLength >= MINMATCH */
+
+ /* match within prefix */
+ if (sequence.offset < 8) {
+ /* close range match, overlap */
+ static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
+ static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* subtracted */
+ int const sub2 = dec64table[sequence.offset];
+ op[0] = match[0];
+ op[1] = match[1];
+ op[2] = match[2];
+ op[3] = match[3];
+ match += dec32table[sequence.offset];
+ ZSTD_copy4(op+4, match);
+ match -= sub2;
+ } else {
+ ZSTD_copy8(op, match);
+ }
+ op += 8; match += 8;
+
+ if (oMatchEnd > oend-(16-MINMATCH)) {
+ if (op < oend_w) {
+ ZSTD_wildcopy(op, match, oend_w - op);
+ match += oend_w - op;
+ op = oend_w;
+ }
+ while (op < oMatchEnd) *op++ = *match++;
+ } else {
+ ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8); /* works even if matchLength < 8 */
+ }
+ return sequenceLength;
+}
+
+
+HINT_INLINE
+size_t ZSTD_execSequenceLong(BYTE* op,
+ BYTE* const oend, seq_t sequence,
+ const BYTE** litPtr, const BYTE* const litLimit,
+ const BYTE* const prefixStart, const BYTE* const dictStart, const BYTE* const dictEnd)
+{
+ BYTE* const oLitEnd = op + sequence.litLength;
+ size_t const sequenceLength = sequence.litLength + sequence.matchLength;
+ BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
+ BYTE* const oend_w = oend - WILDCOPY_OVERLENGTH;
+ const BYTE* const iLitEnd = *litPtr + sequence.litLength;
+ const BYTE* match = sequence.match;
+
+ /* check */
+ RETURN_ERROR_IF(oMatchEnd > oend, dstSize_tooSmall, "last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend");
+ RETURN_ERROR_IF(iLitEnd > litLimit, corruption_detected, "over-read beyond lit buffer");
+ if (oLitEnd > oend_w) return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit, prefixStart, dictStart, dictEnd);
+
+ /* copy Literals */
+ ZSTD_copy8(op, *litPtr); /* note : op <= oLitEnd <= oend_w == oend - 8 */
+ if (sequence.litLength > 8)
+ ZSTD_wildcopy(op+8, (*litPtr)+8, sequence.litLength - 8); /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */
+ op = oLitEnd;
+ *litPtr = iLitEnd; /* update for next sequence */
+
+ /* copy Match */
+ if (sequence.offset > (size_t)(oLitEnd - prefixStart)) {
+ /* offset beyond prefix */
+ RETURN_ERROR_IF(sequence.offset > (size_t)(oLitEnd - dictStart), corruption_detected);
+ if (match + sequence.matchLength <= dictEnd) {
+ memmove(oLitEnd, match, sequence.matchLength);
+ return sequenceLength;
+ }
+ /* span extDict & currentPrefixSegment */
+ { size_t const length1 = dictEnd - match;
+ memmove(oLitEnd, match, length1);
+ op = oLitEnd + length1;
+ sequence.matchLength -= length1;
+ match = prefixStart;
+ if (op > oend_w || sequence.matchLength < MINMATCH) {
+ U32 i;
+ for (i = 0; i < sequence.matchLength; ++i) op[i] = match[i];
+ return sequenceLength;
+ }
+ } }
+ assert(op <= oend_w);
+ assert(sequence.matchLength >= MINMATCH);
+
+ /* match within prefix */
+ if (sequence.offset < 8) {
+ /* close range match, overlap */
+ static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
+ static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* subtracted */
+ int const sub2 = dec64table[sequence.offset];
+ op[0] = match[0];
+ op[1] = match[1];
+ op[2] = match[2];
+ op[3] = match[3];
+ match += dec32table[sequence.offset];
+ ZSTD_copy4(op+4, match);
+ match -= sub2;
+ } else {
+ ZSTD_copy8(op, match);
+ }
+ op += 8; match += 8;
+
+ if (oMatchEnd > oend-(16-MINMATCH)) {
+ if (op < oend_w) {
+ ZSTD_wildcopy(op, match, oend_w - op);
+ match += oend_w - op;
+ op = oend_w;
+ }
+ while (op < oMatchEnd) *op++ = *match++;
+ } else {
+ ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8); /* works even if matchLength < 8 */
+ }
+ return sequenceLength;
+}
+
+static void
+ZSTD_initFseState(ZSTD_fseState* DStatePtr, BIT_DStream_t* bitD, const ZSTD_seqSymbol* dt)
+{
+ const void* ptr = dt;
+ const ZSTD_seqSymbol_header* const DTableH = (const ZSTD_seqSymbol_header*)ptr;
+ DStatePtr->state = BIT_readBits(bitD, DTableH->tableLog);
+ DEBUGLOG(6, "ZSTD_initFseState : val=%u using %u bits",
+ (U32)DStatePtr->state, DTableH->tableLog);
+ BIT_reloadDStream(bitD);
+ DStatePtr->table = dt + 1;
+}
+
+FORCE_INLINE_TEMPLATE void
+ZSTD_updateFseState(ZSTD_fseState* DStatePtr, BIT_DStream_t* bitD)
+{
+ ZSTD_seqSymbol const DInfo = DStatePtr->table[DStatePtr->state];
+ U32 const nbBits = DInfo.nbBits;
+ size_t const lowBits = BIT_readBits(bitD, nbBits);
+ DStatePtr->state = DInfo.nextState + lowBits;
+}
+
+/* We need to add at most (ZSTD_WINDOWLOG_MAX_32 - 1) bits to read the maximum
+ * offset bits. But we can only read at most (STREAM_ACCUMULATOR_MIN_32 - 1)
+ * bits before reloading. This value is the maximum number of bytes we read
+ * after reloading when we are decoding long offsets.
+ */
+#define LONG_OFFSETS_MAX_EXTRA_BITS_32 \
+ (ZSTD_WINDOWLOG_MAX_32 > STREAM_ACCUMULATOR_MIN_32 \
+ ? ZSTD_WINDOWLOG_MAX_32 - STREAM_ACCUMULATOR_MIN_32 \
+ : 0)
+
+typedef enum { ZSTD_lo_isRegularOffset, ZSTD_lo_isLongOffset=1 } ZSTD_longOffset_e;
+
+#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG
+FORCE_INLINE_TEMPLATE seq_t
+ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets)
+{
+ seq_t seq;
+ U32 const llBits = seqState->stateLL.table[seqState->stateLL.state].nbAdditionalBits;
+ U32 const mlBits = seqState->stateML.table[seqState->stateML.state].nbAdditionalBits;
+ U32 const ofBits = seqState->stateOffb.table[seqState->stateOffb.state].nbAdditionalBits;
+ U32 const totalBits = llBits+mlBits+ofBits;
+ U32 const llBase = seqState->stateLL.table[seqState->stateLL.state].baseValue;
+ U32 const mlBase = seqState->stateML.table[seqState->stateML.state].baseValue;
+ U32 const ofBase = seqState->stateOffb.table[seqState->stateOffb.state].baseValue;
+
+ /* sequence */
+ { size_t offset;
+ if (!ofBits)
+ offset = 0;
+ else {
+ ZSTD_STATIC_ASSERT(ZSTD_lo_isLongOffset == 1);
+ ZSTD_STATIC_ASSERT(LONG_OFFSETS_MAX_EXTRA_BITS_32 == 5);
+ assert(ofBits <= MaxOff);
+ if (MEM_32bits() && longOffsets && (ofBits >= STREAM_ACCUMULATOR_MIN_32)) {
+ U32 const extraBits = ofBits - MIN(ofBits, 32 - seqState->DStream.bitsConsumed);
+ offset = ofBase + (BIT_readBitsFast(&seqState->DStream, ofBits - extraBits) << extraBits);
+ BIT_reloadDStream(&seqState->DStream);
+ if (extraBits) offset += BIT_readBitsFast(&seqState->DStream, extraBits);
+ assert(extraBits <= LONG_OFFSETS_MAX_EXTRA_BITS_32); /* to avoid another reload */
+ } else {
+ offset = ofBase + BIT_readBitsFast(&seqState->DStream, ofBits/*>0*/); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */
+ if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream);
+ }
+ }
+
+ if (ofBits <= 1) {
+ offset += (llBase==0);
+ if (offset) {
+ size_t temp = (offset==3) ? seqState->prevOffset[0] - 1 : seqState->prevOffset[offset];
+ temp += !temp; /* 0 is not valid; input is corrupted; force offset to 1 */
+ if (offset != 1) seqState->prevOffset[2] = seqState->prevOffset[1];
+ seqState->prevOffset[1] = seqState->prevOffset[0];
+ seqState->prevOffset[0] = offset = temp;
+ } else { /* offset == 0 */
+ offset = seqState->prevOffset[0];
+ }
+ } else {
+ seqState->prevOffset[2] = seqState->prevOffset[1];
+ seqState->prevOffset[1] = seqState->prevOffset[0];
+ seqState->prevOffset[0] = offset;
+ }
+ seq.offset = offset;
+ }
+
+ seq.matchLength = mlBase
+ + ((mlBits>0) ? BIT_readBitsFast(&seqState->DStream, mlBits/*>0*/) : 0); /* <= 16 bits */
+ if (MEM_32bits() && (mlBits+llBits >= STREAM_ACCUMULATOR_MIN_32-LONG_OFFSETS_MAX_EXTRA_BITS_32))
+ BIT_reloadDStream(&seqState->DStream);
+ if (MEM_64bits() && (totalBits >= STREAM_ACCUMULATOR_MIN_64-(LLFSELog+MLFSELog+OffFSELog)))
+ BIT_reloadDStream(&seqState->DStream);
+ /* Ensure there are enough bits to read the rest of data in 64-bit mode. */
+ ZSTD_STATIC_ASSERT(16+LLFSELog+MLFSELog+OffFSELog < STREAM_ACCUMULATOR_MIN_64);
+
+ seq.litLength = llBase
+ + ((llBits>0) ? BIT_readBitsFast(&seqState->DStream, llBits/*>0*/) : 0); /* <= 16 bits */
+ if (MEM_32bits())
+ BIT_reloadDStream(&seqState->DStream);
+
+ DEBUGLOG(6, "seq: litL=%u, matchL=%u, offset=%u",
+ (U32)seq.litLength, (U32)seq.matchLength, (U32)seq.offset);
+
+ /* ANS state update */
+ ZSTD_updateFseState(&seqState->stateLL, &seqState->DStream); /* <= 9 bits */
+ ZSTD_updateFseState(&seqState->stateML, &seqState->DStream); /* <= 9 bits */
+ if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream); /* <= 18 bits */
+ ZSTD_updateFseState(&seqState->stateOffb, &seqState->DStream); /* <= 8 bits */
+
+ return seq;
+}
+
+FORCE_INLINE_TEMPLATE size_t
+ZSTD_decompressSequences_body( ZSTD_DCtx* dctx,
+ void* dst, size_t maxDstSize,
+ const void* seqStart, size_t seqSize, int nbSeq,
+ const ZSTD_longOffset_e isLongOffset)
+{
+ const BYTE* ip = (const BYTE*)seqStart;
+ const BYTE* const iend = ip + seqSize;
+ BYTE* const ostart = (BYTE* const)dst;
+ BYTE* const oend = ostart + maxDstSize;
+ BYTE* op = ostart;
+ const BYTE* litPtr = dctx->litPtr;
+ const BYTE* const litEnd = litPtr + dctx->litSize;
+ const BYTE* const prefixStart = (const BYTE*) (dctx->prefixStart);
+ const BYTE* const vBase = (const BYTE*) (dctx->virtualStart);
+ const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);
+ DEBUGLOG(5, "ZSTD_decompressSequences_body");
+
+ /* Regen sequences */
+ if (nbSeq) {
+ seqState_t seqState;
+ dctx->fseEntropy = 1;
+ { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }
+ RETURN_ERROR_IF(
+ ERR_isError(BIT_initDStream(&seqState.DStream, ip, iend-ip)),
+ corruption_detected);
+ ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
+ ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
+ ZSTD_initFseState(&seqState.stateML, &seqState.DStream, dctx->MLTptr);
+
+ for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && nbSeq ; ) {
+ nbSeq--;
+ { seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset);
+ size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litEnd, prefixStart, vBase, dictEnd);
+ DEBUGLOG(6, "regenerated sequence size : %u", (U32)oneSeqSize);
+ if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
+ op += oneSeqSize;
+ } }
+
+ /* check if reached exact end */
+ DEBUGLOG(5, "ZSTD_decompressSequences_body: after decode loop, remaining nbSeq : %i", nbSeq);
+ RETURN_ERROR_IF(nbSeq, corruption_detected);
+ /* save reps for next block */
+ { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]); }
+ }
+
+ /* last literal segment */
+ { size_t const lastLLSize = litEnd - litPtr;
+ RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall);
+ memcpy(op, litPtr, lastLLSize);
+ op += lastLLSize;
+ }
+
+ return op-ostart;
+}
+
+static size_t
+ZSTD_decompressSequences_default(ZSTD_DCtx* dctx,
+ void* dst, size_t maxDstSize,
+ const void* seqStart, size_t seqSize, int nbSeq,
+ const ZSTD_longOffset_e isLongOffset)
+{
+ return ZSTD_decompressSequences_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);
+}
+#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG */
+
+
+
+#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT
+FORCE_INLINE_TEMPLATE seq_t
+ZSTD_decodeSequenceLong(seqState_t* seqState, ZSTD_longOffset_e const longOffsets)
+{
+ seq_t seq;
+ U32 const llBits = seqState->stateLL.table[seqState->stateLL.state].nbAdditionalBits;
+ U32 const mlBits = seqState->stateML.table[seqState->stateML.state].nbAdditionalBits;
+ U32 const ofBits = seqState->stateOffb.table[seqState->stateOffb.state].nbAdditionalBits;
+ U32 const totalBits = llBits+mlBits+ofBits;
+ U32 const llBase = seqState->stateLL.table[seqState->stateLL.state].baseValue;
+ U32 const mlBase = seqState->stateML.table[seqState->stateML.state].baseValue;
+ U32 const ofBase = seqState->stateOffb.table[seqState->stateOffb.state].baseValue;
+
+ /* sequence */
+ { size_t offset;
+ if (!ofBits)
+ offset = 0;
+ else {
+ ZSTD_STATIC_ASSERT(ZSTD_lo_isLongOffset == 1);
+ ZSTD_STATIC_ASSERT(LONG_OFFSETS_MAX_EXTRA_BITS_32 == 5);
+ assert(ofBits <= MaxOff);
+ if (MEM_32bits() && longOffsets) {
+ U32 const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN_32-1);
+ offset = ofBase + (BIT_readBitsFast(&seqState->DStream, ofBits - extraBits) << extraBits);
+ if (MEM_32bits() || extraBits) BIT_reloadDStream(&seqState->DStream);
+ if (extraBits) offset += BIT_readBitsFast(&seqState->DStream, extraBits);
+ } else {
+ offset = ofBase + BIT_readBitsFast(&seqState->DStream, ofBits); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */
+ if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream);
+ }
+ }
+
+ if (ofBits <= 1) {
+ offset += (llBase==0);
+ if (offset) {
+ size_t temp = (offset==3) ? seqState->prevOffset[0] - 1 : seqState->prevOffset[offset];
+ temp += !temp; /* 0 is not valid; input is corrupted; force offset to 1 */
+ if (offset != 1) seqState->prevOffset[2] = seqState->prevOffset[1];
+ seqState->prevOffset[1] = seqState->prevOffset[0];
+ seqState->prevOffset[0] = offset = temp;
+ } else {
+ offset = seqState->prevOffset[0];
+ }
+ } else {
+ seqState->prevOffset[2] = seqState->prevOffset[1];
+ seqState->prevOffset[1] = seqState->prevOffset[0];
+ seqState->prevOffset[0] = offset;
+ }
+ seq.offset = offset;
+ }
+
+ seq.matchLength = mlBase + ((mlBits>0) ? BIT_readBitsFast(&seqState->DStream, mlBits) : 0); /* <= 16 bits */
+ if (MEM_32bits() && (mlBits+llBits >= STREAM_ACCUMULATOR_MIN_32-LONG_OFFSETS_MAX_EXTRA_BITS_32))
+ BIT_reloadDStream(&seqState->DStream);
+ if (MEM_64bits() && (totalBits >= STREAM_ACCUMULATOR_MIN_64-(LLFSELog+MLFSELog+OffFSELog)))
+ BIT_reloadDStream(&seqState->DStream);
+ /* Verify that there is enough bits to read the rest of the data in 64-bit mode. */
+ ZSTD_STATIC_ASSERT(16+LLFSELog+MLFSELog+OffFSELog < STREAM_ACCUMULATOR_MIN_64);
+
+ seq.litLength = llBase + ((llBits>0) ? BIT_readBitsFast(&seqState->DStream, llBits) : 0); /* <= 16 bits */
+ if (MEM_32bits())
+ BIT_reloadDStream(&seqState->DStream);
+
+ { size_t const pos = seqState->pos + seq.litLength;
+ const BYTE* const matchBase = (seq.offset > pos) ? seqState->dictEnd : seqState->prefixStart;
+ seq.match = matchBase + pos - seq.offset; /* note : this operation can overflow when seq.offset is really too large, which can only happen when input is corrupted.
+ * No consequence though : no memory access will occur, overly large offset will be detected in ZSTD_execSequenceLong() */
+ seqState->pos = pos + seq.matchLength;
+ }
+
+ /* ANS state update */
+ ZSTD_updateFseState(&seqState->stateLL, &seqState->DStream); /* <= 9 bits */
+ ZSTD_updateFseState(&seqState->stateML, &seqState->DStream); /* <= 9 bits */
+ if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream); /* <= 18 bits */
+ ZSTD_updateFseState(&seqState->stateOffb, &seqState->DStream); /* <= 8 bits */
+
+ return seq;
+}
+
+FORCE_INLINE_TEMPLATE size_t
+ZSTD_decompressSequencesLong_body(
+ ZSTD_DCtx* dctx,
+ void* dst, size_t maxDstSize,
+ const void* seqStart, size_t seqSize, int nbSeq,
+ const ZSTD_longOffset_e isLongOffset)
+{
+ const BYTE* ip = (const BYTE*)seqStart;
+ const BYTE* const iend = ip + seqSize;
+ BYTE* const ostart = (BYTE* const)dst;
+ BYTE* const oend = ostart + maxDstSize;
+ BYTE* op = ostart;
+ const BYTE* litPtr = dctx->litPtr;
+ const BYTE* const litEnd = litPtr + dctx->litSize;
+ const BYTE* const prefixStart = (const BYTE*) (dctx->prefixStart);
+ const BYTE* const dictStart = (const BYTE*) (dctx->virtualStart);
+ const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);
+
+ /* Regen sequences */
+ if (nbSeq) {
+#define STORED_SEQS 4
+#define STORED_SEQS_MASK (STORED_SEQS-1)
+#define ADVANCED_SEQS 4
+ seq_t sequences[STORED_SEQS];
+ int const seqAdvance = MIN(nbSeq, ADVANCED_SEQS);
+ seqState_t seqState;
+ int seqNb;
+ dctx->fseEntropy = 1;
+ { int i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }
+ seqState.prefixStart = prefixStart;
+ seqState.pos = (size_t)(op-prefixStart);
+ seqState.dictEnd = dictEnd;
+ assert(iend >= ip);
+ RETURN_ERROR_IF(
+ ERR_isError(BIT_initDStream(&seqState.DStream, ip, iend-ip)),
+ corruption_detected);
+ ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
+ ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
+ ZSTD_initFseState(&seqState.stateML, &seqState.DStream, dctx->MLTptr);
+
+ /* prepare in advance */
+ for (seqNb=0; (BIT_reloadDStream(&seqState.DStream) <= BIT_DStream_completed) && (seqNb<seqAdvance); seqNb++) {
+ sequences[seqNb] = ZSTD_decodeSequenceLong(&seqState, isLongOffset);
+ PREFETCH_L1(sequences[seqNb].match); PREFETCH_L1(sequences[seqNb].match + sequences[seqNb].matchLength - 1); /* note : it's safe to invoke PREFETCH() on any memory address, including invalid ones */
+ }
+ RETURN_ERROR_IF(seqNb<seqAdvance, corruption_detected);
+
+ /* decode and decompress */
+ for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && (seqNb<nbSeq) ; seqNb++) {
+ seq_t const sequence = ZSTD_decodeSequenceLong(&seqState, isLongOffset);
+ size_t const oneSeqSize = ZSTD_execSequenceLong(op, oend, sequences[(seqNb-ADVANCED_SEQS) & STORED_SEQS_MASK], &litPtr, litEnd, prefixStart, dictStart, dictEnd);
+ if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
+ PREFETCH_L1(sequence.match); PREFETCH_L1(sequence.match + sequence.matchLength - 1); /* note : it's safe to invoke PREFETCH() on any memory address, including invalid ones */
+ sequences[seqNb & STORED_SEQS_MASK] = sequence;
+ op += oneSeqSize;
+ }
+ RETURN_ERROR_IF(seqNb<nbSeq, corruption_detected);
+
+ /* finish queue */
+ seqNb -= seqAdvance;
+ for ( ; seqNb<nbSeq ; seqNb++) {
+ size_t const oneSeqSize = ZSTD_execSequenceLong(op, oend, sequences[seqNb&STORED_SEQS_MASK], &litPtr, litEnd, prefixStart, dictStart, dictEnd);
+ if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
+ op += oneSeqSize;
+ }
+
+ /* save reps for next block */
+ { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]); }
+ }
+
+ /* last literal segment */
+ { size_t const lastLLSize = litEnd - litPtr;
+ RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall);
+ memcpy(op, litPtr, lastLLSize);
+ op += lastLLSize;
+ }
+
+ return op-ostart;
+}
+
+static size_t
+ZSTD_decompressSequencesLong_default(ZSTD_DCtx* dctx,
+ void* dst, size_t maxDstSize,
+ const void* seqStart, size_t seqSize, int nbSeq,
+ const ZSTD_longOffset_e isLongOffset)
+{
+ return ZSTD_decompressSequencesLong_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);
+}
+#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT */
+
+
+
+#if DYNAMIC_BMI2
+
+#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG
+static TARGET_ATTRIBUTE("bmi2") size_t
+ZSTD_decompressSequences_bmi2(ZSTD_DCtx* dctx,
+ void* dst, size_t maxDstSize,
+ const void* seqStart, size_t seqSize, int nbSeq,
+ const ZSTD_longOffset_e isLongOffset)
+{
+ return ZSTD_decompressSequences_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);
+}
+#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG */
+
+#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT
+static TARGET_ATTRIBUTE("bmi2") size_t
+ZSTD_decompressSequencesLong_bmi2(ZSTD_DCtx* dctx,
+ void* dst, size_t maxDstSize,
+ const void* seqStart, size_t seqSize, int nbSeq,
+ const ZSTD_longOffset_e isLongOffset)
+{
+ return ZSTD_decompressSequencesLong_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);
+}
+#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT */
+
+#endif /* DYNAMIC_BMI2 */
+
+typedef size_t (*ZSTD_decompressSequences_t)(
+ ZSTD_DCtx* dctx,
+ void* dst, size_t maxDstSize,
+ const void* seqStart, size_t seqSize, int nbSeq,
+ const ZSTD_longOffset_e isLongOffset);
+
+#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG
+static size_t
+ZSTD_decompressSequences(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize,
+ const void* seqStart, size_t seqSize, int nbSeq,
+ const ZSTD_longOffset_e isLongOffset)
+{
+ DEBUGLOG(5, "ZSTD_decompressSequences");
+#if DYNAMIC_BMI2
+ if (dctx->bmi2) {
+ return ZSTD_decompressSequences_bmi2(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);
+ }
+#endif
+ return ZSTD_decompressSequences_default(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);
+}
+#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG */
+
+
+#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT
+/* ZSTD_decompressSequencesLong() :
+ * decompression function triggered when a minimum share of offsets is considered "long",
+ * aka out of cache.
+ * note : "long" definition seems overloaded here, sometimes meaning "wider than bitstream register", and sometimes meaning "farther than memory cache distance".
+ * This function will try to mitigate main memory latency through the use of prefetching */
+static size_t
+ZSTD_decompressSequencesLong(ZSTD_DCtx* dctx,
+ void* dst, size_t maxDstSize,
+ const void* seqStart, size_t seqSize, int nbSeq,
+ const ZSTD_longOffset_e isLongOffset)
+{
+ DEBUGLOG(5, "ZSTD_decompressSequencesLong");
+#if DYNAMIC_BMI2
+ if (dctx->bmi2) {
+ return ZSTD_decompressSequencesLong_bmi2(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);
+ }
+#endif
+ return ZSTD_decompressSequencesLong_default(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);
+}
+#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT */
+
+
+
+#if !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT) && \
+ !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG)
+/* ZSTD_getLongOffsetsShare() :
+ * condition : offTable must be valid
+ * @return : "share" of long offsets (arbitrarily defined as > (1<<23))
+ * compared to maximum possible of (1<<OffFSELog) */
+static unsigned
+ZSTD_getLongOffsetsShare(const ZSTD_seqSymbol* offTable)
+{
+ const void* ptr = offTable;
+ U32 const tableLog = ((const ZSTD_seqSymbol_header*)ptr)[0].tableLog;
+ const ZSTD_seqSymbol* table = offTable + 1;
+ U32 const max = 1 << tableLog;
+ U32 u, total = 0;
+ DEBUGLOG(5, "ZSTD_getLongOffsetsShare: (tableLog=%u)", tableLog);
+
+ assert(max <= (1 << OffFSELog)); /* max not too large */
+ for (u=0; u<max; u++) {
+ if (table[u].nbAdditionalBits > 22) total += 1;
+ }
+
+ assert(tableLog <= OffFSELog);
+ total <<= (OffFSELog - tableLog); /* scale to OffFSELog */
+
+ return total;
+}
+#endif
+
+
+size_t
+ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize, const int frame)
+{ /* blockType == blockCompressed */
+ const BYTE* ip = (const BYTE*)src;
+ /* isLongOffset must be true if there are long offsets.
+ * Offsets are long if they are larger than 2^STREAM_ACCUMULATOR_MIN.
+ * We don't expect that to be the case in 64-bit mode.
+ * In block mode, window size is not known, so we have to be conservative.
+ * (note: but it could be evaluated from current-lowLimit)
+ */
+ ZSTD_longOffset_e const isLongOffset = (ZSTD_longOffset_e)(MEM_32bits() && (!frame || (dctx->fParams.windowSize > (1ULL << STREAM_ACCUMULATOR_MIN))));
+ DEBUGLOG(5, "ZSTD_decompressBlock_internal (size : %u)", (U32)srcSize);
+
+ RETURN_ERROR_IF(srcSize >= ZSTD_BLOCKSIZE_MAX, srcSize_wrong);
+
+ /* Decode literals section */
+ { size_t const litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize);
+ DEBUGLOG(5, "ZSTD_decodeLiteralsBlock : %u", (U32)litCSize);
+ if (ZSTD_isError(litCSize)) return litCSize;
+ ip += litCSize;
+ srcSize -= litCSize;
+ }
+
+ /* Build Decoding Tables */
+ {
+ /* These macros control at build-time which decompressor implementation
+ * we use. If neither is defined, we do some inspection and dispatch at
+ * runtime.
+ */
+#if !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT) && \
+ !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG)
+ int usePrefetchDecoder = dctx->ddictIsCold;
+#endif
+ int nbSeq;
+ size_t const seqHSize = ZSTD_decodeSeqHeaders(dctx, &nbSeq, ip, srcSize);
+ if (ZSTD_isError(seqHSize)) return seqHSize;
+ ip += seqHSize;
+ srcSize -= seqHSize;
+
+#if !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT) && \
+ !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG)
+ if ( !usePrefetchDecoder
+ && (!frame || (dctx->fParams.windowSize > (1<<24)))
+ && (nbSeq>ADVANCED_SEQS) ) { /* could probably use a larger nbSeq limit */
+ U32 const shareLongOffsets = ZSTD_getLongOffsetsShare(dctx->OFTptr);
+ U32 const minShare = MEM_64bits() ? 7 : 20; /* heuristic values, correspond to 2.73% and 7.81% */
+ usePrefetchDecoder = (shareLongOffsets >= minShare);
+ }
+#endif
+
+ dctx->ddictIsCold = 0;
+
+#if !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT) && \
+ !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG)
+ if (usePrefetchDecoder)
+#endif
+#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT
+ return ZSTD_decompressSequencesLong(dctx, dst, dstCapacity, ip, srcSize, nbSeq, isLongOffset);
+#endif
+
+#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG
+ /* else */
+ return ZSTD_decompressSequences(dctx, dst, dstCapacity, ip, srcSize, nbSeq, isLongOffset);
+#endif
+ }
+}
+
+
+size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize)
+{
+ size_t dSize;
+ ZSTD_checkContinuity(dctx, dst);
+ dSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 0);
+ dctx->previousDstEnd = (char*)dst + dSize;
+ return dSize;
+}
diff --git a/thirdparty/zstd/decompress/zstd_decompress_block.h b/thirdparty/zstd/decompress/zstd_decompress_block.h
new file mode 100644
index 0000000000..7e92960410
--- /dev/null
+++ b/thirdparty/zstd/decompress/zstd_decompress_block.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+
+#ifndef ZSTD_DEC_BLOCK_H
+#define ZSTD_DEC_BLOCK_H
+
+/*-*******************************************************
+ * Dependencies
+ *********************************************************/
+#include <stddef.h> /* size_t */
+#include "zstd.h" /* DCtx, and some public functions */
+#include "zstd_internal.h" /* blockProperties_t, and some public functions */
+#include "zstd_decompress_internal.h" /* ZSTD_seqSymbol */
+
+
+/* === Prototypes === */
+
+/* note: prototypes already published within `zstd.h` :
+ * ZSTD_decompressBlock()
+ */
+
+/* note: prototypes already published within `zstd_internal.h` :
+ * ZSTD_getcBlockSize()
+ * ZSTD_decodeSeqHeaders()
+ */
+
+
+/* ZSTD_decompressBlock_internal() :
+ * decompress block, starting at `src`,
+ * into destination buffer `dst`.
+ * @return : decompressed block size,
+ * or an error code (which can be tested using ZSTD_isError())
+ */
+size_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize, const int frame);
+
+/* ZSTD_buildFSETable() :
+ * generate FSE decoding table for one symbol (ll, ml or off)
+ * this function must be called with valid parameters only
+ * (dt is large enough, normalizedCounter distribution total is a power of 2, max is within range, etc.)
+ * in which case it cannot fail.
+ * Internal use only.
+ */
+void ZSTD_buildFSETable(ZSTD_seqSymbol* dt,
+ const short* normalizedCounter, unsigned maxSymbolValue,
+ const U32* baseValue, const U32* nbAdditionalBits,
+ unsigned tableLog);
+
+
+#endif /* ZSTD_DEC_BLOCK_H */
diff --git a/thirdparty/zstd/decompress/zstd_decompress_internal.h b/thirdparty/zstd/decompress/zstd_decompress_internal.h
new file mode 100644
index 0000000000..ccbdfa090f
--- /dev/null
+++ b/thirdparty/zstd/decompress/zstd_decompress_internal.h
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+
+/* zstd_decompress_internal:
+ * objects and definitions shared within lib/decompress modules */
+
+ #ifndef ZSTD_DECOMPRESS_INTERNAL_H
+ #define ZSTD_DECOMPRESS_INTERNAL_H
+
+
+/*-*******************************************************
+ * Dependencies
+ *********************************************************/
+#include "mem.h" /* BYTE, U16, U32 */
+#include "zstd_internal.h" /* ZSTD_seqSymbol */
+
+
+
+/*-*******************************************************
+ * Constants
+ *********************************************************/
+static const U32 LL_base[MaxLL+1] = {
+ 0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 18, 20, 22, 24, 28, 32, 40,
+ 48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000,
+ 0x2000, 0x4000, 0x8000, 0x10000 };
+
+static const U32 OF_base[MaxOff+1] = {
+ 0, 1, 1, 5, 0xD, 0x1D, 0x3D, 0x7D,
+ 0xFD, 0x1FD, 0x3FD, 0x7FD, 0xFFD, 0x1FFD, 0x3FFD, 0x7FFD,
+ 0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD,
+ 0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD, 0x1FFFFFFD, 0x3FFFFFFD, 0x7FFFFFFD };
+
+static const U32 OF_bits[MaxOff+1] = {
+ 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 };
+
+static const U32 ML_base[MaxML+1] = {
+ 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, 37, 39, 41, 43, 47, 51, 59,
+ 67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803,
+ 0x1003, 0x2003, 0x4003, 0x8003, 0x10003 };
+
+
+/*-*******************************************************
+ * Decompression types
+ *********************************************************/
+ typedef struct {
+ U32 fastMode;
+ U32 tableLog;
+ } ZSTD_seqSymbol_header;
+
+ typedef struct {
+ U16 nextState;
+ BYTE nbAdditionalBits;
+ BYTE nbBits;
+ U32 baseValue;
+ } ZSTD_seqSymbol;
+
+ #define SEQSYMBOL_TABLE_SIZE(log) (1 + (1 << (log)))
+
+typedef struct {
+ ZSTD_seqSymbol LLTable[SEQSYMBOL_TABLE_SIZE(LLFSELog)]; /* Note : Space reserved for FSE Tables */
+ ZSTD_seqSymbol OFTable[SEQSYMBOL_TABLE_SIZE(OffFSELog)]; /* is also used as temporary workspace while building hufTable during DDict creation */
+ ZSTD_seqSymbol MLTable[SEQSYMBOL_TABLE_SIZE(MLFSELog)]; /* and therefore must be at least HUF_DECOMPRESS_WORKSPACE_SIZE large */
+ HUF_DTable hufTable[HUF_DTABLE_SIZE(HufLog)]; /* can accommodate HUF_decompress4X */
+ U32 rep[ZSTD_REP_NUM];
+} ZSTD_entropyDTables_t;
+
+typedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader,
+ ZSTDds_decodeBlockHeader, ZSTDds_decompressBlock,
+ ZSTDds_decompressLastBlock, ZSTDds_checkChecksum,
+ ZSTDds_decodeSkippableHeader, ZSTDds_skipFrame } ZSTD_dStage;
+
+typedef enum { zdss_init=0, zdss_loadHeader,
+ zdss_read, zdss_load, zdss_flush } ZSTD_dStreamStage;
+
+typedef enum {
+ ZSTD_use_indefinitely = -1, /* Use the dictionary indefinitely */
+ ZSTD_dont_use = 0, /* Do not use the dictionary (if one exists free it) */
+ ZSTD_use_once = 1 /* Use the dictionary once and set to ZSTD_dont_use */
+} ZSTD_dictUses_e;
+
+struct ZSTD_DCtx_s
+{
+ const ZSTD_seqSymbol* LLTptr;
+ const ZSTD_seqSymbol* MLTptr;
+ const ZSTD_seqSymbol* OFTptr;
+ const HUF_DTable* HUFptr;
+ ZSTD_entropyDTables_t entropy;
+ U32 workspace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; /* space needed when building huffman tables */
+ const void* previousDstEnd; /* detect continuity */
+ const void* prefixStart; /* start of current segment */
+ const void* virtualStart; /* virtual start of previous segment if it was just before current one */
+ const void* dictEnd; /* end of previous segment */
+ size_t expected;
+ ZSTD_frameHeader fParams;
+ U64 decodedSize;
+ blockType_e bType; /* used in ZSTD_decompressContinue(), store blockType between block header decoding and block decompression stages */
+ ZSTD_dStage stage;
+ U32 litEntropy;
+ U32 fseEntropy;
+ XXH64_state_t xxhState;
+ size_t headerSize;
+ ZSTD_format_e format;
+ const BYTE* litPtr;
+ ZSTD_customMem customMem;
+ size_t litSize;
+ size_t rleSize;
+ size_t staticSize;
+ int bmi2; /* == 1 if the CPU supports BMI2 and 0 otherwise. CPU support is determined dynamically once per context lifetime. */
+
+ /* dictionary */
+ ZSTD_DDict* ddictLocal;
+ const ZSTD_DDict* ddict; /* set by ZSTD_initDStream_usingDDict(), or ZSTD_DCtx_refDDict() */
+ U32 dictID;
+ int ddictIsCold; /* if == 1 : dictionary is "new" for working context, and presumed "cold" (not in cpu cache) */
+ ZSTD_dictUses_e dictUses;
+
+ /* streaming */
+ ZSTD_dStreamStage streamStage;
+ char* inBuff;
+ size_t inBuffSize;
+ size_t inPos;
+ size_t maxWindowSize;
+ char* outBuff;
+ size_t outBuffSize;
+ size_t outStart;
+ size_t outEnd;
+ size_t lhSize;
+ void* legacyContext;
+ U32 previousLegacyVersion;
+ U32 legacyVersion;
+ U32 hostageByte;
+ int noForwardProgress;
+
+ /* workspace */
+ BYTE litBuffer[ZSTD_BLOCKSIZE_MAX + WILDCOPY_OVERLENGTH];
+ BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX];
+}; /* typedef'd to ZSTD_DCtx within "zstd.h" */
+
+
+/*-*******************************************************
+ * Shared internal functions
+ *********************************************************/
+
+/*! ZSTD_loadDEntropy() :
+ * dict : must point at beginning of a valid zstd dictionary.
+ * @return : size of entropy tables read */
+size_t ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
+ const void* const dict, size_t const dictSize);
+
+/*! ZSTD_checkContinuity() :
+ * check if next `dst` follows previous position, where decompression ended.
+ * If yes, do nothing (continue on current segment).
+ * If not, classify previous segment as "external dictionary", and start a new segment.
+ * This function cannot fail. */
+void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst);
+
+
+#endif /* ZSTD_DECOMPRESS_INTERNAL_H */
diff --git a/thirdparty/zstd/zstd.h b/thirdparty/zstd/zstd.h
index 6405da602e..53470c18f3 100644
--- a/thirdparty/zstd/zstd.h
+++ b/thirdparty/zstd/zstd.h
@@ -35,40 +35,73 @@ extern "C" {
#endif
-/*******************************************************************************************************
+/*******************************************************************************
Introduction
- zstd, short for Zstandard, is a fast lossless compression algorithm,
- targeting real-time compression scenarios at zlib-level and better compression ratios.
- The zstd compression library provides in-memory compression and decompression functions.
- The library supports compression levels from 1 up to ZSTD_maxCLevel() which is currently 22.
- Levels >= 20, labeled `--ultra`, should be used with caution, as they require more memory.
+ zstd, short for Zstandard, is a fast lossless compression algorithm, targeting
+ real-time compression scenarios at zlib-level and better compression ratios.
+ The zstd compression library provides in-memory compression and decompression
+ functions.
+
+ The library supports regular compression levels from 1 up to ZSTD_maxCLevel(),
+ which is currently 22. Levels >= 20, labeled `--ultra`, should be used with
+ caution, as they require more memory. The library also offers negative
+ compression levels, which extend the range of speed vs. ratio preferences.
+ The lower the level, the faster the speed (at the cost of compression).
+
Compression can be done in:
- a single step (described as Simple API)
- a single step, reusing a context (described as Explicit context)
- unbounded multiple steps (described as Streaming compression)
- The compression ratio achievable on small data can be highly improved using a dictionary in:
+
+ The compression ratio achievable on small data can be highly improved using
+ a dictionary. Dictionary compression can be performed in:
- a single step (described as Simple dictionary API)
- - a single step, reusing a dictionary (described as Bulk-processing dictionary API)
+ - a single step, reusing a dictionary (described as Bulk-processing
+ dictionary API)
+
+ Advanced experimental functions can be accessed using
+ `#define ZSTD_STATIC_LINKING_ONLY` before including zstd.h.
- Advanced experimental functions can be accessed using #define ZSTD_STATIC_LINKING_ONLY before including zstd.h.
- Advanced experimental APIs shall never be used with a dynamic library.
- They are not "stable", their definition may change in the future. Only static linking is allowed.
-*********************************************************************************************************/
+ Advanced experimental APIs should never be used with a dynamically-linked
+ library. They are not "stable"; their definitions or signatures may change in
+ the future. Only static linking is allowed.
+*******************************************************************************/
/*------ Version ------*/
#define ZSTD_VERSION_MAJOR 1
-#define ZSTD_VERSION_MINOR 3
-#define ZSTD_VERSION_RELEASE 4
+#define ZSTD_VERSION_MINOR 4
+#define ZSTD_VERSION_RELEASE 0
#define ZSTD_VERSION_NUMBER (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE)
-ZSTDLIB_API unsigned ZSTD_versionNumber(void); /**< useful to check dll version */
+ZSTDLIB_API unsigned ZSTD_versionNumber(void); /**< to check runtime library version */
#define ZSTD_LIB_VERSION ZSTD_VERSION_MAJOR.ZSTD_VERSION_MINOR.ZSTD_VERSION_RELEASE
#define ZSTD_QUOTE(str) #str
#define ZSTD_EXPAND_AND_QUOTE(str) ZSTD_QUOTE(str)
#define ZSTD_VERSION_STRING ZSTD_EXPAND_AND_QUOTE(ZSTD_LIB_VERSION)
-ZSTDLIB_API const char* ZSTD_versionString(void); /* added in v1.3.0 */
+ZSTDLIB_API const char* ZSTD_versionString(void); /* requires v1.3.0+ */
+
+/***************************************
+* Default constant
+***************************************/
+#ifndef ZSTD_CLEVEL_DEFAULT
+# define ZSTD_CLEVEL_DEFAULT 3
+#endif
+
+/***************************************
+* Constants
+***************************************/
+
+/* All magic numbers are supposed read/written to/from files/memory using little-endian convention */
+#define ZSTD_MAGICNUMBER 0xFD2FB528 /* valid since v0.8.0 */
+#define ZSTD_MAGIC_DICTIONARY 0xEC30A437 /* valid since v0.7.0 */
+#define ZSTD_MAGIC_SKIPPABLE_START 0x184D2A50 /* all 16 values, from 0x184D2A50 to 0x184D2A5F, signal the beginning of a skippable frame */
+#define ZSTD_MAGIC_SKIPPABLE_MASK 0xFFFFFFF0
+
+#define ZSTD_BLOCKSIZELOG_MAX 17
+#define ZSTD_BLOCKSIZE_MAX (1<<ZSTD_BLOCKSIZELOG_MAX)
+
/***************************************
@@ -92,11 +125,11 @@ ZSTDLIB_API size_t ZSTD_compress( void* dst, size_t dstCapacity,
ZSTDLIB_API size_t ZSTD_decompress( void* dst, size_t dstCapacity,
const void* src, size_t compressedSize);
-/*! ZSTD_getFrameContentSize() : added in v1.3.0
+/*! ZSTD_getFrameContentSize() : requires v1.3.0+
* `src` should point to the start of a ZSTD encoded frame.
* `srcSize` must be at least as large as the frame header.
* hint : any size >= `ZSTD_frameHeaderSize_max` is large enough.
- * @return : - decompressed size of the frame in `src`, if known
+ * @return : - decompressed size of `src` frame content, if known
* - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined
* - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small)
* note 1 : a 0 return value means the frame is valid but "empty".
@@ -106,7 +139,8 @@ ZSTDLIB_API size_t ZSTD_decompress( void* dst, size_t dstCapacity,
* Optionally, application can rely on some implicit limit,
* as ZSTD_decompress() only needs an upper bound of decompressed size.
* (For example, data could be necessarily cut into blocks <= 16 KB).
- * note 3 : decompressed size is always present when compression is done with ZSTD_compress()
+ * note 3 : decompressed size is always present when compression is completed using single-pass functions,
+ * such as ZSTD_compress(), ZSTD_compressCCtx() ZSTD_compress_usingDict() or ZSTD_compress_usingCDict().
* note 4 : decompressed size can be very large (64-bits value),
* potentially larger than what local system can handle as a single memory segment.
* In which case, it's necessary to use streaming mode to decompress data.
@@ -123,16 +157,24 @@ ZSTDLIB_API unsigned long long ZSTD_getFrameContentSize(const void *src, size_t
* Both functions work the same way, but ZSTD_getDecompressedSize() blends
* "empty", "unknown" and "error" results to the same return value (0),
* while ZSTD_getFrameContentSize() gives them separate return values.
- * `src` is the start of a zstd compressed frame.
- * @return : content size to be decompressed, as a 64-bits value _if known and not empty_, 0 otherwise. */
+ * @return : decompressed size of `src` frame content _if known and not empty_, 0 otherwise. */
ZSTDLIB_API unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize);
+/*! ZSTD_findFrameCompressedSize() :
+ * `src` should point to the start of a ZSTD frame or skippable frame.
+ * `srcSize` must be >= first frame size
+ * @return : the compressed size of the first frame starting at `src`,
+ * suitable to pass as `srcSize` to `ZSTD_decompress` or similar,
+ * or an error code if input is invalid */
+ZSTDLIB_API size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize);
+
/*====== Helper functions ======*/
#define ZSTD_COMPRESSBOUND(srcSize) ((srcSize) + ((srcSize)>>8) + (((srcSize) < (128<<10)) ? (((128<<10) - (srcSize)) >> 11) /* margin, from 64 to 0 */ : 0)) /* this formula ensures that bound(A) + bound(B) <= bound(A+B) as long as A and B >= 128 KB */
ZSTDLIB_API size_t ZSTD_compressBound(size_t srcSize); /*!< maximum compressed size in worst case single-pass scenario */
ZSTDLIB_API unsigned ZSTD_isError(size_t code); /*!< tells if a `size_t` function result is an error code */
ZSTDLIB_API const char* ZSTD_getErrorName(size_t code); /*!< provides readable string from an error code */
+ZSTDLIB_API int ZSTD_minCLevel(void); /*!< minimum negative compression level allowed */
ZSTDLIB_API int ZSTD_maxCLevel(void); /*!< maximum compression level available */
@@ -149,8 +191,10 @@ ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx(void);
ZSTDLIB_API size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx);
/*! ZSTD_compressCCtx() :
- * Same as ZSTD_compress(), requires an allocated ZSTD_CCtx (see ZSTD_createCCtx()). */
-ZSTDLIB_API size_t ZSTD_compressCCtx(ZSTD_CCtx* ctx,
+ * Same as ZSTD_compress(), using an explicit ZSTD_CCtx
+ * The function will compress at requested compression level,
+ * ignoring any other parameter */
+ZSTDLIB_API size_t ZSTD_compressCCtx(ZSTD_CCtx* cctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
int compressionLevel);
@@ -166,82 +210,326 @@ ZSTDLIB_API ZSTD_DCtx* ZSTD_createDCtx(void);
ZSTDLIB_API size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx);
/*! ZSTD_decompressDCtx() :
- * Same as ZSTD_decompress(), requires an allocated ZSTD_DCtx (see ZSTD_createDCtx()) */
-ZSTDLIB_API size_t ZSTD_decompressDCtx(ZSTD_DCtx* ctx,
+ * Same as ZSTD_decompress(),
+ * requires an allocated ZSTD_DCtx.
+ * Compatible with sticky parameters.
+ */
+ZSTDLIB_API size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize);
-/**************************
-* Simple dictionary API
-***************************/
-/*! ZSTD_compress_usingDict() :
- * Compression using a predefined Dictionary (see dictBuilder/zdict.h).
- * Note : This function loads the dictionary, resulting in significant startup delay.
- * Note : When `dict == NULL || dictSize < 8` no dictionary is used. */
-ZSTDLIB_API size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx,
- void* dst, size_t dstCapacity,
- const void* src, size_t srcSize,
- const void* dict,size_t dictSize,
- int compressionLevel);
+/***************************************
+* Advanced compression API
+***************************************/
-/*! ZSTD_decompress_usingDict() :
- * Decompression using a predefined Dictionary (see dictBuilder/zdict.h).
- * Dictionary must be identical to the one used during compression.
- * Note : This function loads the dictionary, resulting in significant startup delay.
- * Note : When `dict == NULL || dictSize < 8` no dictionary is used. */
-ZSTDLIB_API size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
- void* dst, size_t dstCapacity,
- const void* src, size_t srcSize,
- const void* dict,size_t dictSize);
+/* API design :
+ * Parameters are pushed one by one into an existing context,
+ * using ZSTD_CCtx_set*() functions.
+ * Pushed parameters are sticky : they are valid for next compressed frame, and any subsequent frame.
+ * "sticky" parameters are applicable to `ZSTD_compress2()` and `ZSTD_compressStream*()` !
+ * They do not apply to "simple" one-shot variants such as ZSTD_compressCCtx()
+ *
+ * It's possible to reset all parameters to "default" using ZSTD_CCtx_reset().
+ *
+ * This API supercedes all other "advanced" API entry points in the experimental section.
+ * In the future, we expect to remove from experimental API entry points which are redundant with this API.
+ */
-/**********************************
- * Bulk processing dictionary API
- *********************************/
-typedef struct ZSTD_CDict_s ZSTD_CDict;
+/* Compression strategies, listed from fastest to strongest */
+typedef enum { ZSTD_fast=1,
+ ZSTD_dfast=2,
+ ZSTD_greedy=3,
+ ZSTD_lazy=4,
+ ZSTD_lazy2=5,
+ ZSTD_btlazy2=6,
+ ZSTD_btopt=7,
+ ZSTD_btultra=8,
+ ZSTD_btultra2=9
+ /* note : new strategies _might_ be added in the future.
+ Only the order (from fast to strong) is guaranteed */
+} ZSTD_strategy;
-/*! ZSTD_createCDict() :
- * When compressing multiple messages / blocks with the same dictionary, it's recommended to load it just once.
- * ZSTD_createCDict() will create a digested dictionary, ready to start future compression operations without startup delay.
- * ZSTD_CDict can be created once and shared by multiple threads concurrently, since its usage is read-only.
- * `dictBuffer` can be released after ZSTD_CDict creation, since its content is copied within CDict */
-ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict(const void* dictBuffer, size_t dictSize,
- int compressionLevel);
-/*! ZSTD_freeCDict() :
- * Function frees memory allocated by ZSTD_createCDict(). */
-ZSTDLIB_API size_t ZSTD_freeCDict(ZSTD_CDict* CDict);
+typedef enum {
-/*! ZSTD_compress_usingCDict() :
- * Compression using a digested Dictionary.
- * Faster startup than ZSTD_compress_usingDict(), recommended when same dictionary is used multiple times.
- * Note that compression level is decided during dictionary creation.
- * Frame parameters are hardcoded (dictID=yes, contentSize=yes, checksum=no) */
-ZSTDLIB_API size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx,
- void* dst, size_t dstCapacity,
- const void* src, size_t srcSize,
- const ZSTD_CDict* cdict);
+ /* compression parameters
+ * Note: When compressing with a ZSTD_CDict these parameters are superseded
+ * by the parameters used to construct the ZSTD_CDict. See ZSTD_CCtx_refCDict()
+ * for more info (superseded-by-cdict). */
+ ZSTD_c_compressionLevel=100, /* Update all compression parameters according to pre-defined cLevel table
+ * Default level is ZSTD_CLEVEL_DEFAULT==3.
+ * Special: value 0 means default, which is controlled by ZSTD_CLEVEL_DEFAULT.
+ * Note 1 : it's possible to pass a negative compression level.
+ * Note 2 : setting a level sets all default values of other compression parameters */
+ ZSTD_c_windowLog=101, /* Maximum allowed back-reference distance, expressed as power of 2.
+ * Must be clamped between ZSTD_WINDOWLOG_MIN and ZSTD_WINDOWLOG_MAX.
+ * Special: value 0 means "use default windowLog".
+ * Note: Using a windowLog greater than ZSTD_WINDOWLOG_LIMIT_DEFAULT
+ * requires explicitly allowing such window size at decompression stage if using streaming. */
+ ZSTD_c_hashLog=102, /* Size of the initial probe table, as a power of 2.
+ * Resulting memory usage is (1 << (hashLog+2)).
+ * Must be clamped between ZSTD_HASHLOG_MIN and ZSTD_HASHLOG_MAX.
+ * Larger tables improve compression ratio of strategies <= dFast,
+ * and improve speed of strategies > dFast.
+ * Special: value 0 means "use default hashLog". */
+ ZSTD_c_chainLog=103, /* Size of the multi-probe search table, as a power of 2.
+ * Resulting memory usage is (1 << (chainLog+2)).
+ * Must be clamped between ZSTD_CHAINLOG_MIN and ZSTD_CHAINLOG_MAX.
+ * Larger tables result in better and slower compression.
+ * This parameter is useless when using "fast" strategy.
+ * It's still useful when using "dfast" strategy,
+ * in which case it defines a secondary probe table.
+ * Special: value 0 means "use default chainLog". */
+ ZSTD_c_searchLog=104, /* Number of search attempts, as a power of 2.
+ * More attempts result in better and slower compression.
+ * This parameter is useless when using "fast" and "dFast" strategies.
+ * Special: value 0 means "use default searchLog". */
+ ZSTD_c_minMatch=105, /* Minimum size of searched matches.
+ * Note that Zstandard can still find matches of smaller size,
+ * it just tweaks its search algorithm to look for this size and larger.
+ * Larger values increase compression and decompression speed, but decrease ratio.
+ * Must be clamped between ZSTD_MINMATCH_MIN and ZSTD_MINMATCH_MAX.
+ * Note that currently, for all strategies < btopt, effective minimum is 4.
+ * , for all strategies > fast, effective maximum is 6.
+ * Special: value 0 means "use default minMatchLength". */
+ ZSTD_c_targetLength=106, /* Impact of this field depends on strategy.
+ * For strategies btopt, btultra & btultra2:
+ * Length of Match considered "good enough" to stop search.
+ * Larger values make compression stronger, and slower.
+ * For strategy fast:
+ * Distance between match sampling.
+ * Larger values make compression faster, and weaker.
+ * Special: value 0 means "use default targetLength". */
+ ZSTD_c_strategy=107, /* See ZSTD_strategy enum definition.
+ * The higher the value of selected strategy, the more complex it is,
+ * resulting in stronger and slower compression.
+ * Special: value 0 means "use default strategy". */
+ /* LDM mode parameters */
+ ZSTD_c_enableLongDistanceMatching=160, /* Enable long distance matching.
+ * This parameter is designed to improve compression ratio
+ * for large inputs, by finding large matches at long distance.
+ * It increases memory usage and window size.
+ * Note: enabling this parameter increases default ZSTD_c_windowLog to 128 MB
+ * except when expressly set to a different value. */
+ ZSTD_c_ldmHashLog=161, /* Size of the table for long distance matching, as a power of 2.
+ * Larger values increase memory usage and compression ratio,
+ * but decrease compression speed.
+ * Must be clamped between ZSTD_HASHLOG_MIN and ZSTD_HASHLOG_MAX
+ * default: windowlog - 7.
+ * Special: value 0 means "automatically determine hashlog". */
+ ZSTD_c_ldmMinMatch=162, /* Minimum match size for long distance matcher.
+ * Larger/too small values usually decrease compression ratio.
+ * Must be clamped between ZSTD_LDM_MINMATCH_MIN and ZSTD_LDM_MINMATCH_MAX.
+ * Special: value 0 means "use default value" (default: 64). */
+ ZSTD_c_ldmBucketSizeLog=163, /* Log size of each bucket in the LDM hash table for collision resolution.
+ * Larger values improve collision resolution but decrease compression speed.
+ * The maximum value is ZSTD_LDM_BUCKETSIZELOG_MAX.
+ * Special: value 0 means "use default value" (default: 3). */
+ ZSTD_c_ldmHashRateLog=164, /* Frequency of inserting/looking up entries into the LDM hash table.
+ * Must be clamped between 0 and (ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN).
+ * Default is MAX(0, (windowLog - ldmHashLog)), optimizing hash table usage.
+ * Larger values improve compression speed.
+ * Deviating far from default value will likely result in a compression ratio decrease.
+ * Special: value 0 means "automatically determine hashRateLog". */
-typedef struct ZSTD_DDict_s ZSTD_DDict;
+ /* frame parameters */
+ ZSTD_c_contentSizeFlag=200, /* Content size will be written into frame header _whenever known_ (default:1)
+ * Content size must be known at the beginning of compression.
+ * This is automatically the case when using ZSTD_compress2(),
+ * For streaming variants, content size must be provided with ZSTD_CCtx_setPledgedSrcSize() */
+ ZSTD_c_checksumFlag=201, /* A 32-bits checksum of content is written at end of frame (default:0) */
+ ZSTD_c_dictIDFlag=202, /* When applicable, dictionary's ID is written into frame header (default:1) */
-/*! ZSTD_createDDict() :
- * Create a digested dictionary, ready to start decompression operation without startup delay.
- * dictBuffer can be released after DDict creation, as its content is copied inside DDict */
-ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict(const void* dictBuffer, size_t dictSize);
+ /* multi-threading parameters */
+ /* These parameters are only useful if multi-threading is enabled (compiled with build macro ZSTD_MULTITHREAD).
+ * They return an error otherwise. */
+ ZSTD_c_nbWorkers=400, /* Select how many threads will be spawned to compress in parallel.
+ * When nbWorkers >= 1, triggers asynchronous mode when used with ZSTD_compressStream*() :
+ * ZSTD_compressStream*() consumes input and flush output if possible, but immediately gives back control to caller,
+ * while compression work is performed in parallel, within worker threads.
+ * (note : a strong exception to this rule is when first invocation of ZSTD_compressStream2() sets ZSTD_e_end :
+ * in which case, ZSTD_compressStream2() delegates to ZSTD_compress2(), which is always a blocking call).
+ * More workers improve speed, but also increase memory usage.
+ * Default value is `0`, aka "single-threaded mode" : no worker is spawned, compression is performed inside Caller's thread, all invocations are blocking */
+ ZSTD_c_jobSize=401, /* Size of a compression job. This value is enforced only when nbWorkers >= 1.
+ * Each compression job is completed in parallel, so this value can indirectly impact the nb of active threads.
+ * 0 means default, which is dynamically determined based on compression parameters.
+ * Job size must be a minimum of overlap size, or 1 MB, whichever is largest.
+ * The minimum size is automatically and transparently enforced */
+ ZSTD_c_overlapLog=402, /* Control the overlap size, as a fraction of window size.
+ * The overlap size is an amount of data reloaded from previous job at the beginning of a new job.
+ * It helps preserve compression ratio, while each job is compressed in parallel.
+ * This value is enforced only when nbWorkers >= 1.
+ * Larger values increase compression ratio, but decrease speed.
+ * Possible values range from 0 to 9 :
+ * - 0 means "default" : value will be determined by the library, depending on strategy
+ * - 1 means "no overlap"
+ * - 9 means "full overlap", using a full window size.
+ * Each intermediate rank increases/decreases load size by a factor 2 :
+ * 9: full window; 8: w/2; 7: w/4; 6: w/8; 5:w/16; 4: w/32; 3:w/64; 2:w/128; 1:no overlap; 0:default
+ * default value varies between 6 and 9, depending on strategy */
+
+ /* note : additional experimental parameters are also available
+ * within the experimental section of the API.
+ * At the time of this writing, they include :
+ * ZSTD_c_rsyncable
+ * ZSTD_c_format
+ * ZSTD_c_forceMaxWindow
+ * ZSTD_c_forceAttachDict
+ * ZSTD_c_literalCompressionMode
+ * Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.
+ * note : never ever use experimentalParam? names directly;
+ * also, the enums values themselves are unstable and can still change.
+ */
+ ZSTD_c_experimentalParam1=500,
+ ZSTD_c_experimentalParam2=10,
+ ZSTD_c_experimentalParam3=1000,
+ ZSTD_c_experimentalParam4=1001,
+ ZSTD_c_experimentalParam5=1002,
+} ZSTD_cParameter;
-/*! ZSTD_freeDDict() :
- * Function frees memory allocated with ZSTD_createDDict() */
-ZSTDLIB_API size_t ZSTD_freeDDict(ZSTD_DDict* ddict);
+typedef struct {
+ size_t error;
+ int lowerBound;
+ int upperBound;
+} ZSTD_bounds;
+
+/*! ZSTD_cParam_getBounds() :
+ * All parameters must belong to an interval with lower and upper bounds,
+ * otherwise they will either trigger an error or be automatically clamped.
+ * @return : a structure, ZSTD_bounds, which contains
+ * - an error status field, which must be tested using ZSTD_isError()
+ * - lower and upper bounds, both inclusive
+ */
+ZSTDLIB_API ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter cParam);
-/*! ZSTD_decompress_usingDDict() :
- * Decompression using a digested Dictionary.
- * Faster startup than ZSTD_decompress_usingDict(), recommended when same dictionary is used multiple times. */
-ZSTDLIB_API size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
- void* dst, size_t dstCapacity,
- const void* src, size_t srcSize,
- const ZSTD_DDict* ddict);
+/*! ZSTD_CCtx_setParameter() :
+ * Set one compression parameter, selected by enum ZSTD_cParameter.
+ * All parameters have valid bounds. Bounds can be queried using ZSTD_cParam_getBounds().
+ * Providing a value beyond bound will either clamp it, or trigger an error (depending on parameter).
+ * Setting a parameter is generally only possible during frame initialization (before starting compression).
+ * Exception : when using multi-threading mode (nbWorkers >= 1),
+ * the following parameters can be updated _during_ compression (within same frame):
+ * => compressionLevel, hashLog, chainLog, searchLog, minMatch, targetLength and strategy.
+ * new parameters will be active for next job only (after a flush()).
+ * @return : an error code (which can be tested using ZSTD_isError()).
+ */
+ZSTDLIB_API size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value);
+
+/*! ZSTD_CCtx_setPledgedSrcSize() :
+ * Total input data size to be compressed as a single frame.
+ * Value will be written in frame header, unless if explicitly forbidden using ZSTD_c_contentSizeFlag.
+ * This value will also be controlled at end of frame, and trigger an error if not respected.
+ * @result : 0, or an error code (which can be tested with ZSTD_isError()).
+ * Note 1 : pledgedSrcSize==0 actually means zero, aka an empty frame.
+ * In order to mean "unknown content size", pass constant ZSTD_CONTENTSIZE_UNKNOWN.
+ * ZSTD_CONTENTSIZE_UNKNOWN is default value for any new frame.
+ * Note 2 : pledgedSrcSize is only valid once, for the next frame.
+ * It's discarded at the end of the frame, and replaced by ZSTD_CONTENTSIZE_UNKNOWN.
+ * Note 3 : Whenever all input data is provided and consumed in a single round,
+ * for example with ZSTD_compress2(),
+ * or invoking immediately ZSTD_compressStream2(,,,ZSTD_e_end),
+ * this value is automatically overridden by srcSize instead.
+ */
+ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize);
+
+typedef enum {
+ ZSTD_reset_session_only = 1,
+ ZSTD_reset_parameters = 2,
+ ZSTD_reset_session_and_parameters = 3
+} ZSTD_ResetDirective;
+
+/*! ZSTD_CCtx_reset() :
+ * There are 2 different things that can be reset, independently or jointly :
+ * - The session : will stop compressing current frame, and make CCtx ready to start a new one.
+ * Useful after an error, or to interrupt any ongoing compression.
+ * Any internal data not yet flushed is cancelled.
+ * Compression parameters and dictionary remain unchanged.
+ * They will be used to compress next frame.
+ * Resetting session never fails.
+ * - The parameters : changes all parameters back to "default".
+ * This removes any reference to any dictionary too.
+ * Parameters can only be changed between 2 sessions (i.e. no compression is currently ongoing)
+ * otherwise the reset fails, and function returns an error value (which can be tested using ZSTD_isError())
+ * - Both : similar to resetting the session, followed by resetting parameters.
+ */
+ZSTDLIB_API size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset);
+
+/*! ZSTD_compress2() :
+ * Behave the same as ZSTD_compressCCtx(), but compression parameters are set using the advanced API.
+ * ZSTD_compress2() always starts a new frame.
+ * Should cctx hold data from a previously unfinished frame, everything about it is forgotten.
+ * - Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_set*()
+ * - The function is always blocking, returns when compression is completed.
+ * Hint : compression runs faster if `dstCapacity` >= `ZSTD_compressBound(srcSize)`.
+ * @return : compressed size written into `dst` (<= `dstCapacity),
+ * or an error code if it fails (which can be tested using ZSTD_isError()).
+ */
+ZSTDLIB_API size_t ZSTD_compress2( ZSTD_CCtx* cctx,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize);
+
+
+/***************************************
+* Advanced decompression API
+***************************************/
+
+/* The advanced API pushes parameters one by one into an existing DCtx context.
+ * Parameters are sticky, and remain valid for all following frames
+ * using the same DCtx context.
+ * It's possible to reset parameters to default values using ZSTD_DCtx_reset().
+ * Note : This API is compatible with existing ZSTD_decompressDCtx() and ZSTD_decompressStream().
+ * Therefore, no new decompression function is necessary.
+ */
+
+typedef enum {
+
+ ZSTD_d_windowLogMax=100, /* Select a size limit (in power of 2) beyond which
+ * the streaming API will refuse to allocate memory buffer
+ * in order to protect the host from unreasonable memory requirements.
+ * This parameter is only useful in streaming mode, since no internal buffer is allocated in single-pass mode.
+ * By default, a decompression context accepts window sizes <= (1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT).
+ * Special: value 0 means "use default maximum windowLog". */
+
+ /* note : additional experimental parameters are also available
+ * within the experimental section of the API.
+ * At the time of this writing, they include :
+ * ZSTD_c_format
+ * Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.
+ * note : never ever use experimentalParam? names directly
+ */
+ ZSTD_d_experimentalParam1=1000
+
+} ZSTD_dParameter;
+
+/*! ZSTD_dParam_getBounds() :
+ * All parameters must belong to an interval with lower and upper bounds,
+ * otherwise they will either trigger an error or be automatically clamped.
+ * @return : a structure, ZSTD_bounds, which contains
+ * - an error status field, which must be tested using ZSTD_isError()
+ * - both lower and upper bounds, inclusive
+ */
+ZSTDLIB_API ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam);
+
+/*! ZSTD_DCtx_setParameter() :
+ * Set one compression parameter, selected by enum ZSTD_dParameter.
+ * All parameters have valid bounds. Bounds can be queried using ZSTD_dParam_getBounds().
+ * Providing a value beyond bound will either clamp it, or trigger an error (depending on parameter).
+ * Setting a parameter is only possible during frame initialization (before starting decompression).
+ * @return : 0, or an error code (which can be tested using ZSTD_isError()).
+ */
+ZSTDLIB_API size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int value);
+
+/*! ZSTD_DCtx_reset() :
+ * Return a DCtx to clean state.
+ * Session and parameters can be reset jointly or separately.
+ * Parameters can only be reset when no active frame is being decompressed.
+ * @return : 0, or an error code, which can be tested with ZSTD_isError()
+ */
+ZSTDLIB_API size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset);
/****************************
@@ -268,56 +556,136 @@ typedef struct ZSTD_outBuffer_s {
* A ZSTD_CStream object is required to track streaming operation.
* Use ZSTD_createCStream() and ZSTD_freeCStream() to create/release resources.
* ZSTD_CStream objects can be reused multiple times on consecutive compression operations.
-* It is recommended to re-use ZSTD_CStream in situations where many streaming operations will be achieved consecutively,
-* since it will play nicer with system's memory, by re-using already allocated memory.
-* Use one separate ZSTD_CStream per thread for parallel execution.
+* It is recommended to re-use ZSTD_CStream since it will play nicer with system's memory, by re-using already allocated memory.
*
-* Start a new compression by initializing ZSTD_CStream.
-* Use ZSTD_initCStream() to start a new compression operation.
-* Use ZSTD_initCStream_usingDict() or ZSTD_initCStream_usingCDict() for a compression which requires a dictionary (experimental section)
+* For parallel execution, use one separate ZSTD_CStream per thread.
*
-* Use ZSTD_compressStream() repetitively to consume input stream.
-* The function will automatically update both `pos` fields.
-* Note that it may not consume the entire input, in which case `pos < size`,
-* and it's up to the caller to present again remaining data.
-* @return : a size hint, preferred nb of bytes to use as input for next function call
-* or an error code, which can be tested using ZSTD_isError().
-* Note 1 : it's just a hint, to help latency a little, any other value will work fine.
-* Note 2 : size hint is guaranteed to be <= ZSTD_CStreamInSize()
+* note : since v1.3.0, ZSTD_CStream and ZSTD_CCtx are the same thing.
+*
+* Parameters are sticky : when starting a new compression on the same context,
+* it will re-use the same sticky parameters as previous compression session.
+* When in doubt, it's recommended to fully initialize the context before usage.
+* Use ZSTD_CCtx_reset() to reset the context and ZSTD_CCtx_setParameter(),
+* ZSTD_CCtx_setPledgedSrcSize(), or ZSTD_CCtx_loadDictionary() and friends to
+* set more specific parameters, the pledged source size, or load a dictionary.
+*
+* Use ZSTD_compressStream2() with ZSTD_e_continue as many times as necessary to
+* consume input stream. The function will automatically update both `pos`
+* fields within `input` and `output`.
+* Note that the function may not consume the entire input, for example, because
+* the output buffer is already full, in which case `input.pos < input.size`.
+* The caller must check if input has been entirely consumed.
+* If not, the caller must make some room to receive more compressed data,
+* and then present again remaining input data.
+* note: ZSTD_e_continue is guaranteed to make some forward progress when called,
+* but doesn't guarantee maximal forward progress. This is especially relevant
+* when compressing with multiple threads. The call won't block if it can
+* consume some input, but if it can't it will wait for some, but not all,
+* output to be flushed.
+* @return : provides a minimum amount of data remaining to be flushed from internal buffers
+* or an error code, which can be tested using ZSTD_isError().
*
-* At any moment, it's possible to flush whatever data remains within internal buffer, using ZSTD_flushStream().
-* `output->pos` will be updated.
-* Note that some content might still be left within internal buffer if `output->size` is too small.
-* @return : nb of bytes still present within internal buffer (0 if it's empty)
+* At any moment, it's possible to flush whatever data might remain stuck within internal buffer,
+* using ZSTD_compressStream2() with ZSTD_e_flush. `output->pos` will be updated.
+* Note that, if `output->size` is too small, a single invocation with ZSTD_e_flush might not be enough (return code > 0).
+* In which case, make some room to receive more compressed data, and call again ZSTD_compressStream2() with ZSTD_e_flush.
+* You must continue calling ZSTD_compressStream2() with ZSTD_e_flush until it returns 0, at which point you can change the
+* operation.
+* note: ZSTD_e_flush will flush as much output as possible, meaning when compressing with multiple threads, it will
+* block until the flush is complete or the output buffer is full.
+* @return : 0 if internal buffers are entirely flushed,
+* >0 if some data still present within internal buffer (the value is minimal estimation of remaining size),
* or an error code, which can be tested using ZSTD_isError().
*
-* ZSTD_endStream() instructs to finish a frame.
+* Calling ZSTD_compressStream2() with ZSTD_e_end instructs to finish a frame.
* It will perform a flush and write frame epilogue.
* The epilogue is required for decoders to consider a frame completed.
-* ZSTD_endStream() may not be able to flush full data if `output->size` is too small.
-* In which case, call again ZSTD_endStream() to complete the flush.
+* flush operation is the same, and follows same rules as calling ZSTD_compressStream2() with ZSTD_e_flush.
+* You must continue calling ZSTD_compressStream2() with ZSTD_e_end until it returns 0, at which point you are free to
+* start a new frame.
+* note: ZSTD_e_end will flush as much output as possible, meaning when compressing with multiple threads, it will
+* block until the flush is complete or the output buffer is full.
* @return : 0 if frame fully completed and fully flushed,
- or >0 if some data is still present within internal buffer
- (value is minimum size estimation for remaining data to flush, but it could be more)
+* >0 if some data still present within internal buffer (the value is minimal estimation of remaining size),
* or an error code, which can be tested using ZSTD_isError().
*
* *******************************************************************/
typedef ZSTD_CCtx ZSTD_CStream; /**< CCtx and CStream are now effectively same object (>= v1.3.0) */
- /* Continue to distinguish them for compatibility with versions <= v1.2.0 */
+ /* Continue to distinguish them for compatibility with older versions <= v1.2.0 */
/*===== ZSTD_CStream management functions =====*/
ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream(void);
ZSTDLIB_API size_t ZSTD_freeCStream(ZSTD_CStream* zcs);
/*===== Streaming compression functions =====*/
-ZSTDLIB_API size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel);
-ZSTDLIB_API size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
-ZSTDLIB_API size_t ZSTD_flushStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output);
-ZSTDLIB_API size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output);
+typedef enum {
+ ZSTD_e_continue=0, /* collect more data, encoder decides when to output compressed result, for optimal compression ratio */
+ ZSTD_e_flush=1, /* flush any data provided so far,
+ * it creates (at least) one new block, that can be decoded immediately on reception;
+ * frame will continue: any future data can still reference previously compressed data, improving compression.
+ * note : multithreaded compression will block to flush as much output as possible. */
+ ZSTD_e_end=2 /* flush any remaining data _and_ close current frame.
+ * note that frame is only closed after compressed data is fully flushed (return value == 0).
+ * After that point, any additional data starts a new frame.
+ * note : each frame is independent (does not reference any content from previous frame).
+ : note : multithreaded compression will block to flush as much output as possible. */
+} ZSTD_EndDirective;
+
+/*! ZSTD_compressStream2() :
+ * Behaves about the same as ZSTD_compressStream, with additional control on end directive.
+ * - Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_set*()
+ * - Compression parameters cannot be changed once compression is started (save a list of exceptions in multi-threading mode)
+ * - output->pos must be <= dstCapacity, input->pos must be <= srcSize
+ * - output->pos and input->pos will be updated. They are guaranteed to remain below their respective limit.
+ * - When nbWorkers==0 (default), function is blocking : it completes its job before returning to caller.
+ * - When nbWorkers>=1, function is non-blocking : it just acquires a copy of input, and distributes jobs to internal worker threads, flush whatever is available,
+ * and then immediately returns, just indicating that there is some data remaining to be flushed.
+ * The function nonetheless guarantees forward progress : it will return only after it reads or write at least 1+ byte.
+ * - Exception : if the first call requests a ZSTD_e_end directive and provides enough dstCapacity, the function delegates to ZSTD_compress2() which is always blocking.
+ * - @return provides a minimum amount of data remaining to be flushed from internal buffers
+ * or an error code, which can be tested using ZSTD_isError().
+ * if @return != 0, flush is not fully completed, there is still some data left within internal buffers.
+ * This is useful for ZSTD_e_flush, since in this case more flushes are necessary to empty all buffers.
+ * For ZSTD_e_end, @return == 0 when internal buffers are fully flushed and frame is completed.
+ * - after a ZSTD_e_end directive, if internal buffer is not fully flushed (@return != 0),
+ * only ZSTD_e_end or ZSTD_e_flush operations are allowed.
+ * Before starting a new compression job, or changing compression parameters,
+ * it is required to fully flush internal buffers.
+ */
+ZSTDLIB_API size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
+ ZSTD_outBuffer* output,
+ ZSTD_inBuffer* input,
+ ZSTD_EndDirective endOp);
ZSTDLIB_API size_t ZSTD_CStreamInSize(void); /**< recommended size for input buffer */
ZSTDLIB_API size_t ZSTD_CStreamOutSize(void); /**< recommended size for output buffer. Guarantee to successfully flush at least one complete compressed block in all circumstances. */
+/*******************************************************************************
+ * This is a legacy streaming API, and can be replaced by ZSTD_CCtx_reset() and
+ * ZSTD_compressStream2(). It is redundant, but is still fully supported.
+ * Advanced parameters and dictionary compression can only be used through the
+ * new API.
+ ******************************************************************************/
+
+/**
+ * Equivalent to:
+ *
+ * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
+ * ZSTD_CCtx_refCDict(zcs, NULL); // clear the dictionary (if any)
+ * ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel);
+ */
+ZSTDLIB_API size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel);
+/**
+ * Alternative for ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue).
+ * NOTE: The return value is different. ZSTD_compressStream() returns a hint for
+ * the next read size (if non-zero and not an error). ZSTD_compressStream2()
+ * returns the number of bytes left to flush (if non-zero and not an error).
+ */
+ZSTDLIB_API size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
+/** Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_flush). */
+ZSTDLIB_API size_t ZSTD_flushStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output);
+/** Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_end). */
+ZSTDLIB_API size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output);
/*-***************************************************************************
@@ -327,101 +695,370 @@ ZSTDLIB_API size_t ZSTD_CStreamOutSize(void); /**< recommended size for output
* Use ZSTD_createDStream() and ZSTD_freeDStream() to create/release resources.
* ZSTD_DStream objects can be re-used multiple times.
*
-* Use ZSTD_initDStream() to start a new decompression operation,
-* or ZSTD_initDStream_usingDict() if decompression requires a dictionary.
-* @return : recommended first input size
+* Use ZSTD_initDStream() to start a new decompression operation.
+* @return : recommended first input size
+* Alternatively, use advanced API to set specific properties.
*
* Use ZSTD_decompressStream() repetitively to consume your input.
* The function will update both `pos` fields.
* If `input.pos < input.size`, some input has not been consumed.
* It's up to the caller to present again remaining data.
+* The function tries to flush all data decoded immediately, respecting output buffer size.
* If `output.pos < output.size`, decoder has flushed everything it could.
-* @return : 0 when a frame is completely decoded and fully flushed,
-* an error code, which can be tested using ZSTD_isError(),
-* any other value > 0, which means there is still some decoding to do to complete current frame.
-* The return value is a suggested next input size (a hint to improve latency) that will never load more than the current frame.
+* But if `output.pos == output.size`, there might be some data left within internal buffers.,
+* In which case, call ZSTD_decompressStream() again to flush whatever remains in the buffer.
+* Note : with no additional input provided, amount of data flushed is necessarily <= ZSTD_BLOCKSIZE_MAX.
+* @return : 0 when a frame is completely decoded and fully flushed,
+* or an error code, which can be tested using ZSTD_isError(),
+* or any other value > 0, which means there is still some decoding or flushing to do to complete current frame :
+* the return value is a suggested next input size (just a hint for better latency)
+* that will never request more than the remaining frame size.
* *******************************************************************************/
typedef ZSTD_DCtx ZSTD_DStream; /**< DCtx and DStream are now effectively same object (>= v1.3.0) */
- /* For compatibility with versions <= v1.2.0, continue to consider them separated. */
+ /* For compatibility with versions <= v1.2.0, prefer differentiating them. */
/*===== ZSTD_DStream management functions =====*/
ZSTDLIB_API ZSTD_DStream* ZSTD_createDStream(void);
ZSTDLIB_API size_t ZSTD_freeDStream(ZSTD_DStream* zds);
/*===== Streaming decompression functions =====*/
+
+/* This function is redundant with the advanced API and equivalent to:
+ *
+ * ZSTD_DCtx_reset(zds);
+ * ZSTD_DCtx_refDDict(zds, NULL);
+ */
ZSTDLIB_API size_t ZSTD_initDStream(ZSTD_DStream* zds);
+
ZSTDLIB_API size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
ZSTDLIB_API size_t ZSTD_DStreamInSize(void); /*!< recommended size for input buffer */
ZSTDLIB_API size_t ZSTD_DStreamOutSize(void); /*!< recommended size for output buffer. Guarantee to successfully flush at least one complete block in all circumstances. */
-#endif /* ZSTD_H_235446 */
+/**************************
+* Simple dictionary API
+***************************/
+/*! ZSTD_compress_usingDict() :
+ * Compression at an explicit compression level using a Dictionary.
+ * A dictionary can be any arbitrary data segment (also called a prefix),
+ * or a buffer with specified information (see dictBuilder/zdict.h).
+ * Note : This function loads the dictionary, resulting in significant startup delay.
+ * It's intended for a dictionary used only once.
+ * Note 2 : When `dict == NULL || dictSize < 8` no dictionary is used. */
+ZSTDLIB_API size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize,
+ const void* dict,size_t dictSize,
+ int compressionLevel);
+
+/*! ZSTD_decompress_usingDict() :
+ * Decompression using a known Dictionary.
+ * Dictionary must be identical to the one used during compression.
+ * Note : This function loads the dictionary, resulting in significant startup delay.
+ * It's intended for a dictionary used only once.
+ * Note : When `dict == NULL || dictSize < 8` no dictionary is used. */
+ZSTDLIB_API size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize,
+ const void* dict,size_t dictSize);
+
+
+/***********************************
+ * Bulk processing dictionary API
+ **********************************/
+typedef struct ZSTD_CDict_s ZSTD_CDict;
+
+/*! ZSTD_createCDict() :
+ * When compressing multiple messages / blocks using the same dictionary, it's recommended to load it only once.
+ * ZSTD_createCDict() will create a digested dictionary, ready to start future compression operations without startup cost.
+ * ZSTD_CDict can be created once and shared by multiple threads concurrently, since its usage is read-only.
+ * `dictBuffer` can be released after ZSTD_CDict creation, because its content is copied within CDict.
+ * Consider experimental function `ZSTD_createCDict_byReference()` if you prefer to not duplicate `dictBuffer` content.
+ * Note : A ZSTD_CDict can be created from an empty dictBuffer, but it is inefficient when used to compress small data. */
+ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict(const void* dictBuffer, size_t dictSize,
+ int compressionLevel);
+
+/*! ZSTD_freeCDict() :
+ * Function frees memory allocated by ZSTD_createCDict(). */
+ZSTDLIB_API size_t ZSTD_freeCDict(ZSTD_CDict* CDict);
+
+/*! ZSTD_compress_usingCDict() :
+ * Compression using a digested Dictionary.
+ * Recommended when same dictionary is used multiple times.
+ * Note : compression level is _decided at dictionary creation time_,
+ * and frame parameters are hardcoded (dictID=yes, contentSize=yes, checksum=no) */
+ZSTDLIB_API size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize,
+ const ZSTD_CDict* cdict);
+
+
+typedef struct ZSTD_DDict_s ZSTD_DDict;
+
+/*! ZSTD_createDDict() :
+ * Create a digested dictionary, ready to start decompression operation without startup delay.
+ * dictBuffer can be released after DDict creation, as its content is copied inside DDict. */
+ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict(const void* dictBuffer, size_t dictSize);
+
+/*! ZSTD_freeDDict() :
+ * Function frees memory allocated with ZSTD_createDDict() */
+ZSTDLIB_API size_t ZSTD_freeDDict(ZSTD_DDict* ddict);
+
+/*! ZSTD_decompress_usingDDict() :
+ * Decompression using a digested Dictionary.
+ * Recommended when same dictionary is used multiple times. */
+ZSTDLIB_API size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize,
+ const ZSTD_DDict* ddict);
+
+
+/********************************
+ * Dictionary helper functions
+ *******************************/
+
+/*! ZSTD_getDictID_fromDict() :
+ * Provides the dictID stored within dictionary.
+ * if @return == 0, the dictionary is not conformant with Zstandard specification.
+ * It can still be loaded, but as a content-only dictionary. */
+ZSTDLIB_API unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize);
+
+/*! ZSTD_getDictID_fromDDict() :
+ * Provides the dictID of the dictionary loaded into `ddict`.
+ * If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.
+ * Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */
+ZSTDLIB_API unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict);
+
+/*! ZSTD_getDictID_fromFrame() :
+ * Provides the dictID required to decompressed the frame stored within `src`.
+ * If @return == 0, the dictID could not be decoded.
+ * This could for one of the following reasons :
+ * - The frame does not require a dictionary to be decoded (most common case).
+ * - The frame was built with dictID intentionally removed. Whatever dictionary is necessary is a hidden information.
+ * Note : this use case also happens when using a non-conformant dictionary.
+ * - `srcSize` is too small, and as a result, the frame header could not be decoded (only possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`).
+ * - This is not a Zstandard frame.
+ * When identifying the exact failure cause, it's possible to use ZSTD_getFrameHeader(), which will provide a more precise error code. */
+ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize);
+
+
+/*******************************************************************************
+ * Advanced dictionary and prefix API
+ *
+ * This API allows dictionaries to be used with ZSTD_compress2(),
+ * ZSTD_compressStream2(), and ZSTD_decompress(). Dictionaries are sticky, and
+ * only reset with the context is reset with ZSTD_reset_parameters or
+ * ZSTD_reset_session_and_parameters. Prefixes are single-use.
+ ******************************************************************************/
+
+
+/*! ZSTD_CCtx_loadDictionary() :
+ * Create an internal CDict from `dict` buffer.
+ * Decompression will have to use same dictionary.
+ * @result : 0, or an error code (which can be tested with ZSTD_isError()).
+ * Special: Loading a NULL (or 0-size) dictionary invalidates previous dictionary,
+ * meaning "return to no-dictionary mode".
+ * Note 1 : Dictionary is sticky, it will be used for all future compressed frames.
+ * To return to "no-dictionary" situation, load a NULL dictionary (or reset parameters).
+ * Note 2 : Loading a dictionary involves building tables.
+ * It's also a CPU consuming operation, with non-negligible impact on latency.
+ * Tables are dependent on compression parameters, and for this reason,
+ * compression parameters can no longer be changed after loading a dictionary.
+ * Note 3 :`dict` content will be copied internally.
+ * Use experimental ZSTD_CCtx_loadDictionary_byReference() to reference content instead.
+ * In such a case, dictionary buffer must outlive its users.
+ * Note 4 : Use ZSTD_CCtx_loadDictionary_advanced()
+ * to precisely select how dictionary content must be interpreted. */
+ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize);
+
+/*! ZSTD_CCtx_refCDict() :
+ * Reference a prepared dictionary, to be used for all next compressed frames.
+ * Note that compression parameters are enforced from within CDict,
+ * and supersede any compression parameter previously set within CCtx.
+ * The parameters ignored are labled as "superseded-by-cdict" in the ZSTD_cParameter enum docs.
+ * The ignored parameters will be used again if the CCtx is returned to no-dictionary mode.
+ * The dictionary will remain valid for future compressed frames using same CCtx.
+ * @result : 0, or an error code (which can be tested with ZSTD_isError()).
+ * Special : Referencing a NULL CDict means "return to no-dictionary mode".
+ * Note 1 : Currently, only one dictionary can be managed.
+ * Referencing a new dictionary effectively "discards" any previous one.
+ * Note 2 : CDict is just referenced, its lifetime must outlive its usage within CCtx. */
+ZSTDLIB_API size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict);
+
+/*! ZSTD_CCtx_refPrefix() :
+ * Reference a prefix (single-usage dictionary) for next compressed frame.
+ * A prefix is **only used once**. Tables are discarded at end of frame (ZSTD_e_end).
+ * Decompression will need same prefix to properly regenerate data.
+ * Compressing with a prefix is similar in outcome as performing a diff and compressing it,
+ * but performs much faster, especially during decompression (compression speed is tunable with compression level).
+ * @result : 0, or an error code (which can be tested with ZSTD_isError()).
+ * Special: Adding any prefix (including NULL) invalidates any previous prefix or dictionary
+ * Note 1 : Prefix buffer is referenced. It **must** outlive compression.
+ * Its content must remain unmodified during compression.
+ * Note 2 : If the intention is to diff some large src data blob with some prior version of itself,
+ * ensure that the window size is large enough to contain the entire source.
+ * See ZSTD_c_windowLog.
+ * Note 3 : Referencing a prefix involves building tables, which are dependent on compression parameters.
+ * It's a CPU consuming operation, with non-negligible impact on latency.
+ * If there is a need to use the same prefix multiple times, consider loadDictionary instead.
+ * Note 4 : By default, the prefix is interpreted as raw content (ZSTD_dm_rawContent).
+ * Use experimental ZSTD_CCtx_refPrefix_advanced() to alter dictionary interpretation. */
+ZSTDLIB_API size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx,
+ const void* prefix, size_t prefixSize);
+
+/*! ZSTD_DCtx_loadDictionary() :
+ * Create an internal DDict from dict buffer,
+ * to be used to decompress next frames.
+ * The dictionary remains valid for all future frames, until explicitly invalidated.
+ * @result : 0, or an error code (which can be tested with ZSTD_isError()).
+ * Special : Adding a NULL (or 0-size) dictionary invalidates any previous dictionary,
+ * meaning "return to no-dictionary mode".
+ * Note 1 : Loading a dictionary involves building tables,
+ * which has a non-negligible impact on CPU usage and latency.
+ * It's recommended to "load once, use many times", to amortize the cost
+ * Note 2 :`dict` content will be copied internally, so `dict` can be released after loading.
+ * Use ZSTD_DCtx_loadDictionary_byReference() to reference dictionary content instead.
+ * Note 3 : Use ZSTD_DCtx_loadDictionary_advanced() to take control of
+ * how dictionary content is loaded and interpreted.
+ */
+ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize);
+
+/*! ZSTD_DCtx_refDDict() :
+ * Reference a prepared dictionary, to be used to decompress next frames.
+ * The dictionary remains active for decompression of future frames using same DCtx.
+ * @result : 0, or an error code (which can be tested with ZSTD_isError()).
+ * Note 1 : Currently, only one dictionary can be managed.
+ * Referencing a new dictionary effectively "discards" any previous one.
+ * Special: referencing a NULL DDict means "return to no-dictionary mode".
+ * Note 2 : DDict is just referenced, its lifetime must outlive its usage from DCtx.
+ */
+ZSTDLIB_API size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict);
+
+/*! ZSTD_DCtx_refPrefix() :
+ * Reference a prefix (single-usage dictionary) to decompress next frame.
+ * This is the reverse operation of ZSTD_CCtx_refPrefix(),
+ * and must use the same prefix as the one used during compression.
+ * Prefix is **only used once**. Reference is discarded at end of frame.
+ * End of frame is reached when ZSTD_decompressStream() returns 0.
+ * @result : 0, or an error code (which can be tested with ZSTD_isError()).
+ * Note 1 : Adding any prefix (including NULL) invalidates any previously set prefix or dictionary
+ * Note 2 : Prefix buffer is referenced. It **must** outlive decompression.
+ * Prefix buffer must remain unmodified up to the end of frame,
+ * reached when ZSTD_decompressStream() returns 0.
+ * Note 3 : By default, the prefix is treated as raw content (ZSTD_dm_rawContent).
+ * Use ZSTD_CCtx_refPrefix_advanced() to alter dictMode (Experimental section)
+ * Note 4 : Referencing a raw content prefix has almost no cpu nor memory cost.
+ * A full dictionary is more costly, as it requires building tables.
+ */
+ZSTDLIB_API size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx,
+ const void* prefix, size_t prefixSize);
+
+/* === Memory management === */
+
+/*! ZSTD_sizeof_*() :
+ * These functions give the _current_ memory usage of selected object.
+ * Note that object memory usage can evolve (increase or decrease) over time. */
+ZSTDLIB_API size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx);
+ZSTDLIB_API size_t ZSTD_sizeof_DCtx(const ZSTD_DCtx* dctx);
+ZSTDLIB_API size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs);
+ZSTDLIB_API size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds);
+ZSTDLIB_API size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict);
+ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
+
+#endif /* ZSTD_H_235446 */
/****************************************************************************************
- * START OF ADVANCED AND EXPERIMENTAL FUNCTIONS
- * The definitions in this section are considered experimental.
- * They should never be used with a dynamic library, as prototypes may change in the future.
+ * ADVANCED AND EXPERIMENTAL FUNCTIONS
+ ****************************************************************************************
+ * The definitions in the following section are considered experimental.
* They are provided for advanced scenarios.
+ * They should never be used with a dynamic library, as prototypes may change in the future.
* Use them only in association with static linking.
* ***************************************************************************************/
#if defined(ZSTD_STATIC_LINKING_ONLY) && !defined(ZSTD_H_ZSTD_STATIC_LINKING_ONLY)
#define ZSTD_H_ZSTD_STATIC_LINKING_ONLY
-/* --- Constants ---*/
-#define ZSTD_MAGICNUMBER 0xFD2FB528 /* >= v0.8.0 */
-#define ZSTD_MAGIC_SKIPPABLE_START 0x184D2A50U
-#define ZSTD_MAGIC_DICTIONARY 0xEC30A437 /* >= v0.7.0 */
-
-#define ZSTD_WINDOWLOG_MAX_32 30
-#define ZSTD_WINDOWLOG_MAX_64 31
-#define ZSTD_WINDOWLOG_MAX ((unsigned)(sizeof(size_t) == 4 ? ZSTD_WINDOWLOG_MAX_32 : ZSTD_WINDOWLOG_MAX_64))
-#define ZSTD_WINDOWLOG_MIN 10
-#define ZSTD_HASHLOG_MAX ((ZSTD_WINDOWLOG_MAX < 30) ? ZSTD_WINDOWLOG_MAX : 30)
-#define ZSTD_HASHLOG_MIN 6
-#define ZSTD_CHAINLOG_MAX_32 29
-#define ZSTD_CHAINLOG_MAX_64 30
-#define ZSTD_CHAINLOG_MAX ((unsigned)(sizeof(size_t) == 4 ? ZSTD_CHAINLOG_MAX_32 : ZSTD_CHAINLOG_MAX_64))
-#define ZSTD_CHAINLOG_MIN ZSTD_HASHLOG_MIN
-#define ZSTD_HASHLOG3_MAX 17
-#define ZSTD_SEARCHLOG_MAX (ZSTD_WINDOWLOG_MAX-1)
-#define ZSTD_SEARCHLOG_MIN 1
-#define ZSTD_SEARCHLENGTH_MAX 7 /* only for ZSTD_fast, other strategies are limited to 6 */
-#define ZSTD_SEARCHLENGTH_MIN 3 /* only for ZSTD_btopt, other strategies are limited to 4 */
-#define ZSTD_TARGETLENGTH_MIN 1 /* only used by btopt, btultra and btfast */
-#define ZSTD_LDM_MINMATCH_MIN 4
-#define ZSTD_LDM_MINMATCH_MAX 4096
-#define ZSTD_LDM_BUCKETSIZELOG_MAX 8
-
-#define ZSTD_FRAMEHEADERSIZE_PREFIX 5 /* minimum input size to know frame header size */
-#define ZSTD_FRAMEHEADERSIZE_MIN 6
-#define ZSTD_FRAMEHEADERSIZE_MAX 18 /* for static allocation */
-static const size_t ZSTD_frameHeaderSize_prefix = ZSTD_FRAMEHEADERSIZE_PREFIX;
-static const size_t ZSTD_frameHeaderSize_min = ZSTD_FRAMEHEADERSIZE_MIN;
-static const size_t ZSTD_frameHeaderSize_max = ZSTD_FRAMEHEADERSIZE_MAX;
-static const size_t ZSTD_skippableHeaderSize = 8; /* magic number + skippable frame length */
+/****************************************************************************************
+ * experimental API (static linking only)
+ ****************************************************************************************
+ * The following symbols and constants
+ * are not planned to join "stable API" status in the near future.
+ * They can still change in future versions.
+ * Some of them are planned to remain in the static_only section indefinitely.
+ * Some of them might be removed in the future (especially when redundant with existing stable functions)
+ * ***************************************************************************************/
+#define ZSTD_FRAMEHEADERSIZE_PREFIX 5 /* minimum input size required to query frame header size */
+#define ZSTD_FRAMEHEADERSIZE_MIN 6
+#define ZSTD_FRAMEHEADERSIZE_MAX 18 /* can be useful for static allocation */
+#define ZSTD_SKIPPABLEHEADERSIZE 8
+
+/* compression parameter bounds */
+#define ZSTD_WINDOWLOG_MAX_32 30
+#define ZSTD_WINDOWLOG_MAX_64 31
+#define ZSTD_WINDOWLOG_MAX ((int)(sizeof(size_t) == 4 ? ZSTD_WINDOWLOG_MAX_32 : ZSTD_WINDOWLOG_MAX_64))
+#define ZSTD_WINDOWLOG_MIN 10
+#define ZSTD_HASHLOG_MAX ((ZSTD_WINDOWLOG_MAX < 30) ? ZSTD_WINDOWLOG_MAX : 30)
+#define ZSTD_HASHLOG_MIN 6
+#define ZSTD_CHAINLOG_MAX_32 29
+#define ZSTD_CHAINLOG_MAX_64 30
+#define ZSTD_CHAINLOG_MAX ((int)(sizeof(size_t) == 4 ? ZSTD_CHAINLOG_MAX_32 : ZSTD_CHAINLOG_MAX_64))
+#define ZSTD_CHAINLOG_MIN ZSTD_HASHLOG_MIN
+#define ZSTD_SEARCHLOG_MAX (ZSTD_WINDOWLOG_MAX-1)
+#define ZSTD_SEARCHLOG_MIN 1
+#define ZSTD_MINMATCH_MAX 7 /* only for ZSTD_fast, other strategies are limited to 6 */
+#define ZSTD_MINMATCH_MIN 3 /* only for ZSTD_btopt+, faster strategies are limited to 4 */
+#define ZSTD_TARGETLENGTH_MAX ZSTD_BLOCKSIZE_MAX
+#define ZSTD_TARGETLENGTH_MIN 0 /* note : comparing this constant to an unsigned results in a tautological test */
+#define ZSTD_STRATEGY_MIN ZSTD_fast
+#define ZSTD_STRATEGY_MAX ZSTD_btultra2
+
+
+#define ZSTD_OVERLAPLOG_MIN 0
+#define ZSTD_OVERLAPLOG_MAX 9
+
+#define ZSTD_WINDOWLOG_LIMIT_DEFAULT 27 /* by default, the streaming decoder will refuse any frame
+ * requiring larger than (1<<ZSTD_WINDOWLOG_LIMIT_DEFAULT) window size,
+ * to preserve host's memory from unreasonable requirements.
+ * This limit can be overridden using ZSTD_DCtx_setParameter(,ZSTD_d_windowLogMax,).
+ * The limit does not apply for one-pass decoders (such as ZSTD_decompress()), since no additional memory is allocated */
+
+
+/* LDM parameter bounds */
+#define ZSTD_LDM_HASHLOG_MIN ZSTD_HASHLOG_MIN
+#define ZSTD_LDM_HASHLOG_MAX ZSTD_HASHLOG_MAX
+#define ZSTD_LDM_MINMATCH_MIN 4
+#define ZSTD_LDM_MINMATCH_MAX 4096
+#define ZSTD_LDM_BUCKETSIZELOG_MIN 1
+#define ZSTD_LDM_BUCKETSIZELOG_MAX 8
+#define ZSTD_LDM_HASHRATELOG_MIN 0
+#define ZSTD_LDM_HASHRATELOG_MAX (ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN)
+
+/* internal */
+#define ZSTD_HASHLOG3_MAX 17
+
+
+/* --- Advanced types --- */
-/*--- Advanced types ---*/
-typedef enum { ZSTD_fast=1, ZSTD_dfast, ZSTD_greedy, ZSTD_lazy, ZSTD_lazy2,
- ZSTD_btlazy2, ZSTD_btopt, ZSTD_btultra } ZSTD_strategy; /* from faster to stronger */
+typedef struct ZSTD_CCtx_params_s ZSTD_CCtx_params;
typedef struct {
- unsigned windowLog; /**< largest match distance : larger == more compression, more memory needed during decompression */
- unsigned chainLog; /**< fully searched segment : larger == more compression, slower, more memory (useless for fast) */
- unsigned hashLog; /**< dispatch table : larger == faster, more memory */
- unsigned searchLog; /**< nb of searches : larger == more compression, slower */
- unsigned searchLength; /**< match length searched : larger == faster decompression, sometimes less compression */
- unsigned targetLength; /**< acceptable match size for optimal parser (only) : larger == more compression, slower */
- ZSTD_strategy strategy;
+ unsigned windowLog; /**< largest match distance : larger == more compression, more memory needed during decompression */
+ unsigned chainLog; /**< fully searched segment : larger == more compression, slower, more memory (useless for fast) */
+ unsigned hashLog; /**< dispatch table : larger == faster, more memory */
+ unsigned searchLog; /**< nb of searches : larger == more compression, slower */
+ unsigned minMatch; /**< match length searched : larger == faster decompression, sometimes less compression */
+ unsigned targetLength; /**< acceptable match size for optimal parser (only) : larger == more compression, slower */
+ ZSTD_strategy strategy; /**< see ZSTD_strategy definition above */
} ZSTD_compressionParameters;
typedef struct {
- unsigned contentSizeFlag; /**< 1: content size will be in frame header (when known) */
- unsigned checksumFlag; /**< 1: generate a 32-bits checksum at end of frame, for error detection */
- unsigned noDictIDFlag; /**< 1: no dictID will be saved into frame header (if dictionary compression) */
+ int contentSizeFlag; /**< 1: content size will be in frame header (when known) */
+ int checksumFlag; /**< 1: generate a 32-bits checksum using XXH64 algorithm at end of frame, for error detection */
+ int noDictIDFlag; /**< 1: no dictID will be saved into frame header (dictID is only useful for dictionary compression) */
} ZSTD_frameParameters;
typedef struct {
@@ -429,37 +1066,83 @@ typedef struct {
ZSTD_frameParameters fParams;
} ZSTD_parameters;
-typedef struct ZSTD_CCtx_params_s ZSTD_CCtx_params;
-
typedef enum {
- ZSTD_dct_auto=0, /* dictionary is "full" when starting with ZSTD_MAGIC_DICTIONARY, otherwise it is "rawContent" */
- ZSTD_dct_rawContent, /* ensures dictionary is always loaded as rawContent, even if it starts with ZSTD_MAGIC_DICTIONARY */
- ZSTD_dct_fullDict /* refuses to load a dictionary if it does not respect Zstandard's specification */
+ ZSTD_dct_auto = 0, /* dictionary is "full" when starting with ZSTD_MAGIC_DICTIONARY, otherwise it is "rawContent" */
+ ZSTD_dct_rawContent = 1, /* ensures dictionary is always loaded as rawContent, even if it starts with ZSTD_MAGIC_DICTIONARY */
+ ZSTD_dct_fullDict = 2 /* refuses to load a dictionary if it does not respect Zstandard's specification, starting with ZSTD_MAGIC_DICTIONARY */
} ZSTD_dictContentType_e;
typedef enum {
- ZSTD_dlm_byCopy = 0, /**< Copy dictionary content internally */
- ZSTD_dlm_byRef, /**< Reference dictionary content -- the dictionary buffer must outlive its users. */
+ ZSTD_dlm_byCopy = 0, /**< Copy dictionary content internally */
+ ZSTD_dlm_byRef = 1, /**< Reference dictionary content -- the dictionary buffer must outlive its users. */
} ZSTD_dictLoadMethod_e;
+typedef enum {
+ /* Opened question : should we have a format ZSTD_f_auto ?
+ * Today, it would mean exactly the same as ZSTD_f_zstd1.
+ * But, in the future, should several formats become supported,
+ * on the compression side, it would mean "default format".
+ * On the decompression side, it would mean "automatic format detection",
+ * so that ZSTD_f_zstd1 would mean "accept *only* zstd frames".
+ * Since meaning is a little different, another option could be to define different enums for compression and decompression.
+ * This question could be kept for later, when there are actually multiple formats to support,
+ * but there is also the question of pinning enum values, and pinning value `0` is especially important */
+ ZSTD_f_zstd1 = 0, /* zstd frame format, specified in zstd_compression_format.md (default) */
+ ZSTD_f_zstd1_magicless = 1, /* Variant of zstd frame format, without initial 4-bytes magic number.
+ * Useful to save 4 bytes per generated frame.
+ * Decoder cannot recognise automatically this format, requiring this instruction. */
+} ZSTD_format_e;
+
+typedef enum {
+ /* Note: this enum and the behavior it controls are effectively internal
+ * implementation details of the compressor. They are expected to continue
+ * to evolve and should be considered only in the context of extremely
+ * advanced performance tuning.
+ *
+ * Zstd currently supports the use of a CDict in two ways:
+ *
+ * - The contents of the CDict can be copied into the working context. This
+ * means that the compression can search both the dictionary and input
+ * while operating on a single set of internal tables. This makes
+ * the compression faster per-byte of input. However, the initial copy of
+ * the CDict's tables incurs a fixed cost at the beginning of the
+ * compression. For small compressions (< 8 KB), that copy can dominate
+ * the cost of the compression.
+ *
+ * - The CDict's tables can be used in-place. In this model, compression is
+ * slower per input byte, because the compressor has to search two sets of
+ * tables. However, this model incurs no start-up cost (as long as the
+ * working context's tables can be reused). For small inputs, this can be
+ * faster than copying the CDict's tables.
+ *
+ * Zstd has a simple internal heuristic that selects which strategy to use
+ * at the beginning of a compression. However, if experimentation shows that
+ * Zstd is making poor choices, it is possible to override that choice with
+ * this enum.
+ */
+ ZSTD_dictDefaultAttach = 0, /* Use the default heuristic. */
+ ZSTD_dictForceAttach = 1, /* Never copy the dictionary. */
+ ZSTD_dictForceCopy = 2, /* Always copy the dictionary. */
+} ZSTD_dictAttachPref_e;
+
+typedef enum {
+ ZSTD_lcm_auto = 0, /**< Automatically determine the compression mode based on the compression level.
+ * Negative compression levels will be uncompressed, and positive compression
+ * levels will be compressed. */
+ ZSTD_lcm_huffman = 1, /**< Always attempt Huffman compression. Uncompressed literals will still be
+ * emitted if Huffman compression is not profitable. */
+ ZSTD_lcm_uncompressed = 2, /**< Always emit uncompressed literals. */
+} ZSTD_literalCompressionMode_e;
/***************************************
* Frame size functions
***************************************/
-/*! ZSTD_findFrameCompressedSize() :
- * `src` should point to the start of a ZSTD encoded frame or skippable frame
- * `srcSize` must be >= first frame size
- * @return : the compressed size of the first frame starting at `src`,
- * suitable to pass to `ZSTD_decompress` or similar,
- * or an error code if input is invalid */
-ZSTDLIB_API size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize);
-
/*! ZSTD_findDecompressedSize() :
- * `src` should point the start of a series of ZSTD encoded and/or skippable frames
+ * `src` should point to the start of a series of ZSTD encoded and/or skippable frames
* `srcSize` must be the _exact_ size of this series
- * (i.e. there should be a frame boundary exactly at `srcSize` bytes after `src`)
+ * (i.e. there should be a frame boundary at `src + srcSize`)
* @return : - decompressed size of all data in all successive frames
* - if the decompressed size cannot be determined: ZSTD_CONTENTSIZE_UNKNOWN
* - if an error occurred: ZSTD_CONTENTSIZE_ERROR
@@ -479,10 +1162,25 @@ ZSTDLIB_API size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize)
* however it does mean that all frame data must be present and valid. */
ZSTDLIB_API unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize);
+/** ZSTD_decompressBound() :
+ * `src` should point to the start of a series of ZSTD encoded and/or skippable frames
+ * `srcSize` must be the _exact_ size of this series
+ * (i.e. there should be a frame boundary at `src + srcSize`)
+ * @return : - upper-bound for the decompressed size of all data in all successive frames
+ * - if an error occured: ZSTD_CONTENTSIZE_ERROR
+ *
+ * note 1 : an error can occur if `src` contains an invalid or incorrectly formatted frame.
+ * note 2 : the upper-bound is exact when the decompressed size field is available in every ZSTD encoded frame of `src`.
+ * in this case, `ZSTD_findDecompressedSize` and `ZSTD_decompressBound` return the same value.
+ * note 3 : when the decompressed size field isn't available, the upper-bound for that frame is calculated by:
+ * upper-bound = # blocks * min(128 KB, Window_Size)
+ */
+ZSTDLIB_API unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize);
+
/*! ZSTD_frameHeaderSize() :
-* `src` should point to the start of a ZSTD frame
-* `srcSize` must be >= ZSTD_frameHeaderSize_prefix.
-* @return : size of the Frame Header */
+ * srcSize must be >= ZSTD_FRAMEHEADERSIZE_PREFIX.
+ * @return : size of the Frame Header,
+ * or an error code (if srcSize is too small) */
ZSTDLIB_API size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize);
@@ -490,16 +1188,6 @@ ZSTDLIB_API size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize);
* Memory management
***************************************/
-/*! ZSTD_sizeof_*() :
- * These functions give the current memory usage of selected object.
- * Object memory usage can evolve when re-used. */
-ZSTDLIB_API size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx);
-ZSTDLIB_API size_t ZSTD_sizeof_DCtx(const ZSTD_DCtx* dctx);
-ZSTDLIB_API size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs);
-ZSTDLIB_API size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds);
-ZSTDLIB_API size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict);
-ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
-
/*! ZSTD_estimate*() :
* These functions make it possible to estimate memory usage
* of a future {D,C}Ctx, before its creation.
@@ -507,7 +1195,7 @@ ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
* It will also consider src size to be arbitrarily "large", which is worst case.
* If srcSize is known to always be small, ZSTD_estimateCCtxSize_usingCParams() can provide a tighter estimation.
* ZSTD_estimateCCtxSize_usingCParams() can be used in tandem with ZSTD_getCParams() to create cParams from compressionLevel.
- * ZSTD_estimateCCtxSize_usingCCtxParams() can be used in tandem with ZSTD_CCtxParam_setParameter(). Only single-threaded compression is supported. This function will return an error code if ZSTD_p_nbWorkers is >= 1.
+ * ZSTD_estimateCCtxSize_usingCCtxParams() can be used in tandem with ZSTD_CCtxParams_setParameter(). Only single-threaded compression is supported. This function will return an error code if ZSTD_c_nbWorkers is >= 1.
* Note : CCtx size estimation is only correct for single-threaded compression. */
ZSTDLIB_API size_t ZSTD_estimateCCtxSize(int compressionLevel);
ZSTDLIB_API size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams);
@@ -519,7 +1207,7 @@ ZSTDLIB_API size_t ZSTD_estimateDCtxSize(void);
* It will also consider src size to be arbitrarily "large", which is worst case.
* If srcSize is known to always be small, ZSTD_estimateCStreamSize_usingCParams() can provide a tighter estimation.
* ZSTD_estimateCStreamSize_usingCParams() can be used in tandem with ZSTD_getCParams() to create cParams from compressionLevel.
- * ZSTD_estimateCStreamSize_usingCCtxParams() can be used in tandem with ZSTD_CCtxParam_setParameter(). Only single-threaded compression is supported. This function will return an error code if ZSTD_p_nbWorkers is >= 1.
+ * ZSTD_estimateCStreamSize_usingCCtxParams() can be used in tandem with ZSTD_CCtxParams_setParameter(). Only single-threaded compression is supported. This function will return an error code if ZSTD_c_nbWorkers is >= 1.
* Note : CStream size estimation is only correct for single-threaded compression.
* ZSTD_DStream memory budget depends on window Size.
* This information can be passed manually, using ZSTD_estimateDStreamSize,
@@ -582,6 +1270,7 @@ ZSTDLIB_API const ZSTD_DDict* ZSTD_initStaticDDict(
ZSTD_dictLoadMethod_e dictLoadMethod,
ZSTD_dictContentType_e dictContentType);
+
/*! Custom memory allocation :
* These prototypes make it possible to pass your own allocation/free functions.
* ZSTD_customMem is provided at creation time, using ZSTD_create*_advanced() variants listed below.
@@ -616,46 +1305,196 @@ ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictS
/*! ZSTD_createCDict_byReference() :
* Create a digested dictionary for compression
- * Dictionary content is simply referenced, and therefore stays in dictBuffer.
- * It is important that dictBuffer outlives CDict, it must remain read accessible throughout the lifetime of CDict */
+ * Dictionary content is just referenced, not duplicated.
+ * As a consequence, `dictBuffer` **must** outlive CDict,
+ * and its content must remain unmodified throughout the lifetime of CDict. */
ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, size_t dictSize, int compressionLevel);
/*! ZSTD_getCParams() :
-* @return ZSTD_compressionParameters structure for a selected compression level and estimated srcSize.
-* `estimatedSrcSize` value is optional, select 0 if not known */
+ * @return ZSTD_compressionParameters structure for a selected compression level and estimated srcSize.
+ * `estimatedSrcSize` value is optional, select 0 if not known */
ZSTDLIB_API ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize);
/*! ZSTD_getParams() :
-* same as ZSTD_getCParams(), but @return a full `ZSTD_parameters` object instead of sub-component `ZSTD_compressionParameters`.
-* All fields of `ZSTD_frameParameters` are set to default : contentSize=1, checksum=0, noDictID=0 */
+ * same as ZSTD_getCParams(), but @return a full `ZSTD_parameters` object instead of sub-component `ZSTD_compressionParameters`.
+ * All fields of `ZSTD_frameParameters` are set to default : contentSize=1, checksum=0, noDictID=0 */
ZSTDLIB_API ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize);
/*! ZSTD_checkCParams() :
-* Ensure param values remain within authorized range */
+ * Ensure param values remain within authorized range.
+ * @return 0 on success, or an error code (can be checked with ZSTD_isError()) */
ZSTDLIB_API size_t ZSTD_checkCParams(ZSTD_compressionParameters params);
/*! ZSTD_adjustCParams() :
* optimize params for a given `srcSize` and `dictSize`.
- * both values are optional, select `0` if unknown. */
+ * `srcSize` can be unknown, in which case use ZSTD_CONTENTSIZE_UNKNOWN.
+ * `dictSize` must be `0` when there is no dictionary.
+ * cPar can be invalid : all parameters will be clamped within valid range in the @return struct.
+ * This function never fails (wide contract) */
ZSTDLIB_API ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize);
/*! ZSTD_compress_advanced() :
-* Same as ZSTD_compress_usingDict(), with fine-tune control over each compression parameter */
-ZSTDLIB_API size_t ZSTD_compress_advanced (ZSTD_CCtx* cctx,
- void* dst, size_t dstCapacity,
- const void* src, size_t srcSize,
- const void* dict,size_t dictSize,
- ZSTD_parameters params);
+ * Same as ZSTD_compress_usingDict(), with fine-tune control over compression parameters (by structure) */
+ZSTDLIB_API size_t ZSTD_compress_advanced(ZSTD_CCtx* cctx,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize,
+ const void* dict,size_t dictSize,
+ ZSTD_parameters params);
/*! ZSTD_compress_usingCDict_advanced() :
-* Same as ZSTD_compress_usingCDict(), with fine-tune control over frame parameters */
+ * Same as ZSTD_compress_usingCDict(), with fine-tune control over frame parameters */
ZSTDLIB_API size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx,
- void* dst, size_t dstCapacity,
- const void* src, size_t srcSize,
- const ZSTD_CDict* cdict, ZSTD_frameParameters fParams);
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize,
+ const ZSTD_CDict* cdict,
+ ZSTD_frameParameters fParams);
+
+
+/*! ZSTD_CCtx_loadDictionary_byReference() :
+ * Same as ZSTD_CCtx_loadDictionary(), but dictionary content is referenced, instead of being copied into CCtx.
+ * It saves some memory, but also requires that `dict` outlives its usage within `cctx` */
+ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary_byReference(ZSTD_CCtx* cctx, const void* dict, size_t dictSize);
+
+/*! ZSTD_CCtx_loadDictionary_advanced() :
+ * Same as ZSTD_CCtx_loadDictionary(), but gives finer control over
+ * how to load the dictionary (by copy ? by reference ?)
+ * and how to interpret it (automatic ? force raw mode ? full mode only ?) */
+ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType);
+
+/*! ZSTD_CCtx_refPrefix_advanced() :
+ * Same as ZSTD_CCtx_refPrefix(), but gives finer control over
+ * how to interpret prefix content (automatic ? force raw mode (default) ? full mode only ?) */
+ZSTDLIB_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType);
+
+/* === experimental parameters === */
+/* these parameters can be used with ZSTD_setParameter()
+ * they are not guaranteed to remain supported in the future */
+
+ /* Enables rsyncable mode,
+ * which makes compressed files more rsync friendly
+ * by adding periodic synchronization points to the compressed data.
+ * The target average block size is ZSTD_c_jobSize / 2.
+ * It's possible to modify the job size to increase or decrease
+ * the granularity of the synchronization point.
+ * Once the jobSize is smaller than the window size,
+ * it will result in compression ratio degradation.
+ * NOTE 1: rsyncable mode only works when multithreading is enabled.
+ * NOTE 2: rsyncable performs poorly in combination with long range mode,
+ * since it will decrease the effectiveness of synchronization points,
+ * though mileage may vary.
+ * NOTE 3: Rsyncable mode limits maximum compression speed to ~400 MB/s.
+ * If the selected compression level is already running significantly slower,
+ * the overall speed won't be significantly impacted.
+ */
+ #define ZSTD_c_rsyncable ZSTD_c_experimentalParam1
+
+/* Select a compression format.
+ * The value must be of type ZSTD_format_e.
+ * See ZSTD_format_e enum definition for details */
+#define ZSTD_c_format ZSTD_c_experimentalParam2
+
+/* Force back-reference distances to remain < windowSize,
+ * even when referencing into Dictionary content (default:0) */
+#define ZSTD_c_forceMaxWindow ZSTD_c_experimentalParam3
+
+/* Controls whether the contents of a CDict
+ * are used in place, or copied into the working context.
+ * Accepts values from the ZSTD_dictAttachPref_e enum.
+ * See the comments on that enum for an explanation of the feature. */
+#define ZSTD_c_forceAttachDict ZSTD_c_experimentalParam4
+
+/* Controls how the literals are compressed (default is auto).
+ * The value must be of type ZSTD_literalCompressionMode_e.
+ * See ZSTD_literalCompressionMode_t enum definition for details.
+ */
+#define ZSTD_c_literalCompressionMode ZSTD_c_experimentalParam5
+
+/*! ZSTD_CCtx_getParameter() :
+ * Get the requested compression parameter value, selected by enum ZSTD_cParameter,
+ * and store it into int* value.
+ * @return : 0, or an error code (which can be tested with ZSTD_isError()).
+ */
+ZSTDLIB_API size_t ZSTD_CCtx_getParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int* value);
+
+
+/*! ZSTD_CCtx_params :
+ * Quick howto :
+ * - ZSTD_createCCtxParams() : Create a ZSTD_CCtx_params structure
+ * - ZSTD_CCtxParams_setParameter() : Push parameters one by one into
+ * an existing ZSTD_CCtx_params structure.
+ * This is similar to
+ * ZSTD_CCtx_setParameter().
+ * - ZSTD_CCtx_setParametersUsingCCtxParams() : Apply parameters to
+ * an existing CCtx.
+ * These parameters will be applied to
+ * all subsequent frames.
+ * - ZSTD_compressStream2() : Do compression using the CCtx.
+ * - ZSTD_freeCCtxParams() : Free the memory.
+ *
+ * This can be used with ZSTD_estimateCCtxSize_advanced_usingCCtxParams()
+ * for static allocation of CCtx for single-threaded compression.
+ */
+ZSTDLIB_API ZSTD_CCtx_params* ZSTD_createCCtxParams(void);
+ZSTDLIB_API size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params);
+
+/*! ZSTD_CCtxParams_reset() :
+ * Reset params to default values.
+ */
+ZSTDLIB_API size_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params);
+
+/*! ZSTD_CCtxParams_init() :
+ * Initializes the compression parameters of cctxParams according to
+ * compression level. All other parameters are reset to their default values.
+ */
+ZSTDLIB_API size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel);
+/*! ZSTD_CCtxParams_init_advanced() :
+ * Initializes the compression and frame parameters of cctxParams according to
+ * params. All other parameters are reset to their default values.
+ */
+ZSTDLIB_API size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params);
-/*--- Advanced decompression functions ---*/
+/*! ZSTD_CCtxParams_setParameter() :
+ * Similar to ZSTD_CCtx_setParameter.
+ * Set one compression parameter, selected by enum ZSTD_cParameter.
+ * Parameters must be applied to a ZSTD_CCtx using ZSTD_CCtx_setParametersUsingCCtxParams().
+ * @result : 0, or an error code (which can be tested with ZSTD_isError()).
+ */
+ZSTDLIB_API size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int value);
+
+/*! ZSTD_CCtxParams_getParameter() :
+ * Similar to ZSTD_CCtx_getParameter.
+ * Get the requested value of one compression parameter, selected by enum ZSTD_cParameter.
+ * @result : 0, or an error code (which can be tested with ZSTD_isError()).
+ */
+ZSTDLIB_API size_t ZSTD_CCtxParams_getParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int* value);
+
+/*! ZSTD_CCtx_setParametersUsingCCtxParams() :
+ * Apply a set of ZSTD_CCtx_params to the compression context.
+ * This can be done even after compression is started,
+ * if nbWorkers==0, this will have no impact until a new compression is started.
+ * if nbWorkers>=1, new parameters will be picked up at next job,
+ * with a few restrictions (windowLog, pledgedSrcSize, nbWorkers, jobSize, and overlapLog are not updated).
+ */
+ZSTDLIB_API size_t ZSTD_CCtx_setParametersUsingCCtxParams(
+ ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params);
+
+/*! ZSTD_compressStream2_simpleArgs() :
+ * Same as ZSTD_compressStream2(),
+ * but using only integral types as arguments.
+ * This variant might be helpful for binders from dynamic languages
+ * which have troubles handling structures containing memory pointers.
+ */
+ZSTDLIB_API size_t ZSTD_compressStream2_simpleArgs (
+ ZSTD_CCtx* cctx,
+ void* dst, size_t dstCapacity, size_t* dstPos,
+ const void* src, size_t srcSize, size_t* srcPos,
+ ZSTD_EndDirective endOp);
+
+
+/***************************************
+* Advanced decompression functions
+***************************************/
/*! ZSTD_isFrame() :
* Tells if the content of `buffer` starts with a valid Frame Identifier.
@@ -671,78 +1510,201 @@ ZSTDLIB_API unsigned ZSTD_isFrame(const void* buffer, size_t size);
* it must remain read accessible throughout the lifetime of DDict */
ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize);
+/*! ZSTD_DCtx_loadDictionary_byReference() :
+ * Same as ZSTD_DCtx_loadDictionary(),
+ * but references `dict` content instead of copying it into `dctx`.
+ * This saves memory if `dict` remains around.,
+ * However, it's imperative that `dict` remains accessible (and unmodified) while being used, so it must outlive decompression. */
+ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx* dctx, const void* dict, size_t dictSize);
-/*! ZSTD_getDictID_fromDict() :
- * Provides the dictID stored within dictionary.
- * if @return == 0, the dictionary is not conformant with Zstandard specification.
- * It can still be loaded, but as a content-only dictionary. */
-ZSTDLIB_API unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize);
+/*! ZSTD_DCtx_loadDictionary_advanced() :
+ * Same as ZSTD_DCtx_loadDictionary(),
+ * but gives direct control over
+ * how to load the dictionary (by copy ? by reference ?)
+ * and how to interpret it (automatic ? force raw mode ? full mode only ?). */
+ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType);
-/*! ZSTD_getDictID_fromDDict() :
- * Provides the dictID of the dictionary loaded into `ddict`.
- * If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.
- * Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */
-ZSTDLIB_API unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict);
+/*! ZSTD_DCtx_refPrefix_advanced() :
+ * Same as ZSTD_DCtx_refPrefix(), but gives finer control over
+ * how to interpret prefix content (automatic ? force raw mode (default) ? full mode only ?) */
+ZSTDLIB_API size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType);
-/*! ZSTD_getDictID_fromFrame() :
- * Provides the dictID required to decompressed the frame stored within `src`.
- * If @return == 0, the dictID could not be decoded.
- * This could for one of the following reasons :
- * - The frame does not require a dictionary to be decoded (most common case).
- * - The frame was built with dictID intentionally removed. Whatever dictionary is necessary is a hidden information.
- * Note : this use case also happens when using a non-conformant dictionary.
- * - `srcSize` is too small, and as a result, the frame header could not be decoded (only possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`).
- * - This is not a Zstandard frame.
- * When identifying the exact failure cause, it's possible to use ZSTD_getFrameHeader(), which will provide a more precise error code. */
-ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize);
+/*! ZSTD_DCtx_setMaxWindowSize() :
+ * Refuses allocating internal buffers for frames requiring a window size larger than provided limit.
+ * This protects a decoder context from reserving too much memory for itself (potential attack scenario).
+ * This parameter is only useful in streaming mode, since no internal buffer is allocated in single-pass mode.
+ * By default, a decompression context accepts all window sizes <= (1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT)
+ * @return : 0, or an error code (which can be tested using ZSTD_isError()).
+ */
+ZSTDLIB_API size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize);
+
+/* ZSTD_d_format
+ * experimental parameter,
+ * allowing selection between ZSTD_format_e input compression formats
+ */
+#define ZSTD_d_format ZSTD_d_experimentalParam1
+
+/*! ZSTD_DCtx_setFormat() :
+ * Instruct the decoder context about what kind of data to decode next.
+ * This instruction is mandatory to decode data without a fully-formed header,
+ * such ZSTD_f_zstd1_magicless for example.
+ * @return : 0, or an error code (which can be tested using ZSTD_isError()). */
+ZSTDLIB_API size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format);
+
+/*! ZSTD_decompressStream_simpleArgs() :
+ * Same as ZSTD_decompressStream(),
+ * but using only integral types as arguments.
+ * This can be helpful for binders from dynamic languages
+ * which have troubles handling structures containing memory pointers.
+ */
+ZSTDLIB_API size_t ZSTD_decompressStream_simpleArgs (
+ ZSTD_DCtx* dctx,
+ void* dst, size_t dstCapacity, size_t* dstPos,
+ const void* src, size_t srcSize, size_t* srcPos);
/********************************************************************
* Advanced streaming functions
+* Warning : most of these functions are now redundant with the Advanced API.
+* Once Advanced API reaches "stable" status,
+* redundant functions will be deprecated, and then at some point removed.
********************************************************************/
/*===== Advanced Streaming compression functions =====*/
-ZSTDLIB_API size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize); /**< pledgedSrcSize must be correct. If it is not known at init time, use ZSTD_CONTENTSIZE_UNKNOWN. Note that, for compatibility with older programs, "0" also disables frame content size field. It may be enabled in the future. */
-ZSTDLIB_API size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel); /**< creates of an internal CDict (incompatible with static CCtx), except if dict == NULL or dictSize < 8, in which case no dict is used. Note: dict is loaded with ZSTD_dm_auto (treated as a full zstd dictionary if it begins with ZSTD_MAGIC_DICTIONARY, else as raw content) and ZSTD_dlm_byCopy.*/
+/**! ZSTD_initCStream_srcSize() :
+ * This function is deprecated, and equivalent to:
+ * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
+ * ZSTD_CCtx_refCDict(zcs, NULL); // clear the dictionary (if any)
+ * ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel);
+ * ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);
+ *
+ * pledgedSrcSize must be correct. If it is not known at init time, use
+ * ZSTD_CONTENTSIZE_UNKNOWN. Note that, for compatibility with older programs,
+ * "0" also disables frame content size field. It may be enabled in the future.
+ */
+ZSTDLIB_API size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize);
+/**! ZSTD_initCStream_usingDict() :
+ * This function is deprecated, and is equivalent to:
+ * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
+ * ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel);
+ * ZSTD_CCtx_loadDictionary(zcs, dict, dictSize);
+ *
+ * Creates of an internal CDict (incompatible with static CCtx), except if
+ * dict == NULL or dictSize < 8, in which case no dict is used.
+ * Note: dict is loaded with ZSTD_dm_auto (treated as a full zstd dictionary if
+ * it begins with ZSTD_MAGIC_DICTIONARY, else as raw content) and ZSTD_dlm_byCopy.
+ */
+ZSTDLIB_API size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel);
+/**! ZSTD_initCStream_advanced() :
+ * This function is deprecated, and is approximately equivalent to:
+ * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
+ * ZSTD_CCtx_setZstdParams(zcs, params); // Set the zstd params and leave the rest as-is
+ * ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);
+ * ZSTD_CCtx_loadDictionary(zcs, dict, dictSize);
+ *
+ * pledgedSrcSize must be correct. If srcSize is not known at init time, use
+ * value ZSTD_CONTENTSIZE_UNKNOWN. dict is loaded with ZSTD_dm_auto and ZSTD_dlm_byCopy.
+ */
ZSTDLIB_API size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs, const void* dict, size_t dictSize,
- ZSTD_parameters params, unsigned long long pledgedSrcSize); /**< pledgedSrcSize must be correct. If srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN. dict is loaded with ZSTD_dm_auto and ZSTD_dlm_byCopy. */
-ZSTDLIB_API size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict); /**< note : cdict will just be referenced, and must outlive compression session */
-ZSTDLIB_API size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs, const ZSTD_CDict* cdict, ZSTD_frameParameters fParams, unsigned long long pledgedSrcSize); /**< same as ZSTD_initCStream_usingCDict(), with control over frame parameters. pledgedSrcSize must be correct. If srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN. */
+ ZSTD_parameters params, unsigned long long pledgedSrcSize);
+/**! ZSTD_initCStream_usingCDict() :
+ * This function is deprecated, and equivalent to:
+ * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
+ * ZSTD_CCtx_refCDict(zcs, cdict);
+ *
+ * note : cdict will just be referenced, and must outlive compression session
+ */
+ZSTDLIB_API size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict);
+/**! ZSTD_initCStream_usingCDict_advanced() :
+ * This function is deprecated, and is approximately equivalent to:
+ * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
+ * ZSTD_CCtx_setZstdFrameParams(zcs, fParams); // Set the zstd frame params and leave the rest as-is
+ * ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);
+ * ZSTD_CCtx_refCDict(zcs, cdict);
+ *
+ * same as ZSTD_initCStream_usingCDict(), with control over frame parameters.
+ * pledgedSrcSize must be correct. If srcSize is not known at init time, use
+ * value ZSTD_CONTENTSIZE_UNKNOWN.
+ */
+ZSTDLIB_API size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs, const ZSTD_CDict* cdict, ZSTD_frameParameters fParams, unsigned long long pledgedSrcSize);
/*! ZSTD_resetCStream() :
- * start a new compression job, using same parameters from previous job.
- * This is typically useful to skip dictionary loading stage, since it will re-use it in-place..
+ * This function is deprecated, and is equivalent to:
+ * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
+ * ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);
+ *
+ * start a new frame, using same parameters from previous frame.
+ * This is typically useful to skip dictionary loading stage, since it will re-use it in-place.
* Note that zcs must be init at least once before using ZSTD_resetCStream().
* If pledgedSrcSize is not known at reset time, use macro ZSTD_CONTENTSIZE_UNKNOWN.
* If pledgedSrcSize > 0, its value must be correct, as it will be written in header, and controlled at the end.
* For the time being, pledgedSrcSize==0 is interpreted as "srcSize unknown" for compatibility with older programs,
* but it will change to mean "empty" in future version, so use macro ZSTD_CONTENTSIZE_UNKNOWN instead.
- * @return : 0, or an error code (which can be tested using ZSTD_isError()) */
+ * @return : 0, or an error code (which can be tested using ZSTD_isError())
+ */
ZSTDLIB_API size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize);
typedef struct {
- unsigned long long ingested;
- unsigned long long consumed;
- unsigned long long produced;
+ unsigned long long ingested; /* nb input bytes read and buffered */
+ unsigned long long consumed; /* nb input bytes actually compressed */
+ unsigned long long produced; /* nb of compressed bytes generated and buffered */
+ unsigned long long flushed; /* nb of compressed bytes flushed : not provided; can be tracked from caller side */
+ unsigned currentJobID; /* MT only : latest started job nb */
+ unsigned nbActiveWorkers; /* MT only : nb of workers actively compressing at probe time */
} ZSTD_frameProgression;
-/* ZSTD_getFrameProgression():
+/* ZSTD_getFrameProgression() :
* tells how much data has been ingested (read from input)
* consumed (input actually compressed) and produced (output) for current frame.
- * Therefore, (ingested - consumed) is amount of input data buffered internally, not yet compressed.
- * Can report progression inside worker threads (multi-threading and non-blocking mode).
+ * Note : (ingested - consumed) is amount of input data buffered internally, not yet compressed.
+ * Aggregates progression inside active worker threads.
*/
-ZSTD_frameProgression ZSTD_getFrameProgression(const ZSTD_CCtx* cctx);
-
+ZSTDLIB_API ZSTD_frameProgression ZSTD_getFrameProgression(const ZSTD_CCtx* cctx);
+
+/*! ZSTD_toFlushNow() :
+ * Tell how many bytes are ready to be flushed immediately.
+ * Useful for multithreading scenarios (nbWorkers >= 1).
+ * Probe the oldest active job, defined as oldest job not yet entirely flushed,
+ * and check its output buffer.
+ * @return : amount of data stored in oldest job and ready to be flushed immediately.
+ * if @return == 0, it means either :
+ * + there is no active job (could be checked with ZSTD_frameProgression()), or
+ * + oldest job is still actively compressing data,
+ * but everything it has produced has also been flushed so far,
+ * therefore flush speed is limited by production speed of oldest job
+ * irrespective of the speed of concurrent (and newer) jobs.
+ */
+ZSTDLIB_API size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx);
/*===== Advanced Streaming decompression functions =====*/
-typedef enum { DStream_p_maxWindowSize } ZSTD_DStreamParameter_e;
-ZSTDLIB_API size_t ZSTD_setDStreamParameter(ZSTD_DStream* zds, ZSTD_DStreamParameter_e paramType, unsigned paramValue); /* obsolete : this API will be removed in a future version */
-ZSTDLIB_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize); /**< note: no dictionary will be used if dict == NULL or dictSize < 8 */
-ZSTDLIB_API size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict); /**< note : ddict is referenced, it must outlive decompression session */
-ZSTDLIB_API size_t ZSTD_resetDStream(ZSTD_DStream* zds); /**< re-use decompression parameters from previous init; saves dictionary loading */
+/**
+ * This function is deprecated, and is equivalent to:
+ *
+ * ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);
+ * ZSTD_DCtx_loadDictionary(zds, dict, dictSize);
+ *
+ * note: no dictionary will be used if dict == NULL or dictSize < 8
+ */
+ZSTDLIB_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize);
+/**
+ * This function is deprecated, and is equivalent to:
+ *
+ * ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);
+ * ZSTD_DCtx_refDDict(zds, ddict);
+ *
+ * note : ddict is referenced, it must outlive decompression session
+ */
+ZSTDLIB_API size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict);
+/**
+ * This function is deprecated, and is equivalent to:
+ *
+ * ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);
+ *
+ * re-use decompression parameters from previous init; saves dictionary loading
+ */
+ZSTDLIB_API size_t ZSTD_resetDStream(ZSTD_DStream* zds);
/*********************************************************************
@@ -880,7 +1842,17 @@ typedef struct {
unsigned dictID;
unsigned checksumFlag;
} ZSTD_frameHeader;
+
+/** ZSTD_getFrameHeader() :
+ * decode Frame Header, or requires larger `srcSize`.
+ * @return : 0, `zfhPtr` is correctly filled,
+ * >0, `srcSize` is too small, value is wanted `srcSize` amount,
+ * or an error code, which can be tested using ZSTD_isError() */
ZSTDLIB_API size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize); /**< doesn't consume input */
+/*! ZSTD_getFrameHeader_advanced() :
+ * same as ZSTD_getFrameHeader(),
+ * with added capability to select a format (like ZSTD_f_zstd1_magicless) */
+ZSTDLIB_API size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format);
ZSTDLIB_API size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize); /**< when frame content size is not known, pass in frameContentSize == ZSTD_CONTENTSIZE_UNKNOWN */
ZSTDLIB_API size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx);
@@ -897,462 +1869,6 @@ ZSTDLIB_API ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx);
-/* ============================================ */
-/** New advanced API (experimental) */
-/* ============================================ */
-
-/* notes on API design :
- * In this proposal, parameters are pushed one by one into an existing context,
- * and then applied on all subsequent compression jobs.
- * When no parameter is ever provided, CCtx is created with compression level ZSTD_CLEVEL_DEFAULT.
- *
- * This API is intended to replace all others advanced / experimental API entry points.
- * But it stands a reasonable chance to become "stable", after a reasonable testing period.
- */
-
-/* note on naming convention :
- * Initially, the API favored names like ZSTD_setCCtxParameter() .
- * In this proposal, convention is changed towards ZSTD_CCtx_setParameter() .
- * The main driver is that it identifies more clearly the target object type.
- * It feels clearer when considering multiple targets :
- * ZSTD_CDict_setParameter() (rather than ZSTD_setCDictParameter())
- * ZSTD_CCtxParams_setParameter() (rather than ZSTD_setCCtxParamsParameter() )
- * etc...
- */
-
-/* note on enum design :
- * All enum will be pinned to explicit values before reaching "stable API" status */
-
-typedef enum {
- /* Opened question : should we have a format ZSTD_f_auto ?
- * Today, it would mean exactly the same as ZSTD_f_zstd1.
- * But, in the future, should several formats become supported,
- * on the compression side, it would mean "default format".
- * On the decompression side, it would mean "automatic format detection",
- * so that ZSTD_f_zstd1 would mean "accept *only* zstd frames".
- * Since meaning is a little different, another option could be to define different enums for compression and decompression.
- * This question could be kept for later, when there are actually multiple formats to support,
- * but there is also the question of pinning enum values, and pinning value `0` is especially important */
- ZSTD_f_zstd1 = 0, /* zstd frame format, specified in zstd_compression_format.md (default) */
- ZSTD_f_zstd1_magicless, /* Variant of zstd frame format, without initial 4-bytes magic number.
- * Useful to save 4 bytes per generated frame.
- * Decoder cannot recognise automatically this format, requiring instructions. */
-} ZSTD_format_e;
-
-typedef enum {
- /* compression format */
- ZSTD_p_format = 10, /* See ZSTD_format_e enum definition.
- * Cast selected format as unsigned for ZSTD_CCtx_setParameter() compatibility. */
-
- /* compression parameters */
- ZSTD_p_compressionLevel=100, /* Update all compression parameters according to pre-defined cLevel table
- * Default level is ZSTD_CLEVEL_DEFAULT==3.
- * Special: value 0 means "do not change cLevel".
- * Note 1 : it's possible to pass a negative compression level by casting it to unsigned type.
- * Note 2 : setting a level sets all default values of other compression parameters.
- * Note 3 : setting compressionLevel automatically updates ZSTD_p_compressLiterals. */
- ZSTD_p_windowLog, /* Maximum allowed back-reference distance, expressed as power of 2.
- * Must be clamped between ZSTD_WINDOWLOG_MIN and ZSTD_WINDOWLOG_MAX.
- * Special: value 0 means "use default windowLog".
- * Note: Using a window size greater than ZSTD_MAXWINDOWSIZE_DEFAULT (default: 2^27)
- * requires explicitly allowing such window size during decompression stage. */
- ZSTD_p_hashLog, /* Size of the probe table, as a power of 2.
- * Resulting table size is (1 << (hashLog+2)).
- * Must be clamped between ZSTD_HASHLOG_MIN and ZSTD_HASHLOG_MAX.
- * Larger tables improve compression ratio of strategies <= dFast,
- * and improve speed of strategies > dFast.
- * Special: value 0 means "use default hashLog". */
- ZSTD_p_chainLog, /* Size of the full-search table, as a power of 2.
- * Resulting table size is (1 << (chainLog+2)).
- * Larger tables result in better and slower compression.
- * This parameter is useless when using "fast" strategy.
- * Special: value 0 means "use default chainLog". */
- ZSTD_p_searchLog, /* Number of search attempts, as a power of 2.
- * More attempts result in better and slower compression.
- * This parameter is useless when using "fast" and "dFast" strategies.
- * Special: value 0 means "use default searchLog". */
- ZSTD_p_minMatch, /* Minimum size of searched matches (note : repCode matches can be smaller).
- * Larger values make faster compression and decompression, but decrease ratio.
- * Must be clamped between ZSTD_SEARCHLENGTH_MIN and ZSTD_SEARCHLENGTH_MAX.
- * Note that currently, for all strategies < btopt, effective minimum is 4.
- * , for all strategies > fast, effective maximum is 6.
- * Special: value 0 means "use default minMatchLength". */
- ZSTD_p_targetLength, /* Impact of this field depends on strategy.
- * For strategies btopt & btultra:
- * Length of Match considered "good enough" to stop search.
- * Larger values make compression stronger, and slower.
- * For strategy fast:
- * Distance between match sampling.
- * Larger values make compression faster, and weaker.
- * Special: value 0 means "use default targetLength". */
- ZSTD_p_compressionStrategy, /* See ZSTD_strategy enum definition.
- * Cast selected strategy as unsigned for ZSTD_CCtx_setParameter() compatibility.
- * The higher the value of selected strategy, the more complex it is,
- * resulting in stronger and slower compression.
- * Special: value 0 means "use default strategy". */
-
- ZSTD_p_enableLongDistanceMatching=160, /* Enable long distance matching.
- * This parameter is designed to improve compression ratio
- * for large inputs, by finding large matches at long distance.
- * It increases memory usage and window size.
- * Note: enabling this parameter increases ZSTD_p_windowLog to 128 MB
- * except when expressly set to a different value. */
- ZSTD_p_ldmHashLog, /* Size of the table for long distance matching, as a power of 2.
- * Larger values increase memory usage and compression ratio,
- * but decrease compression speed.
- * Must be clamped between ZSTD_HASHLOG_MIN and ZSTD_HASHLOG_MAX
- * default: windowlog - 7.
- * Special: value 0 means "automatically determine hashlog". */
- ZSTD_p_ldmMinMatch, /* Minimum match size for long distance matcher.
- * Larger/too small values usually decrease compression ratio.
- * Must be clamped between ZSTD_LDM_MINMATCH_MIN and ZSTD_LDM_MINMATCH_MAX.
- * Special: value 0 means "use default value" (default: 64). */
- ZSTD_p_ldmBucketSizeLog, /* Log size of each bucket in the LDM hash table for collision resolution.
- * Larger values improve collision resolution but decrease compression speed.
- * The maximum value is ZSTD_LDM_BUCKETSIZELOG_MAX .
- * Special: value 0 means "use default value" (default: 3). */
- ZSTD_p_ldmHashEveryLog, /* Frequency of inserting/looking up entries in the LDM hash table.
- * Must be clamped between 0 and (ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN).
- * Default is MAX(0, (windowLog - ldmHashLog)), optimizing hash table usage.
- * Larger values improve compression speed.
- * Deviating far from default value will likely result in a compression ratio decrease.
- * Special: value 0 means "automatically determine hashEveryLog". */
-
- /* frame parameters */
- ZSTD_p_contentSizeFlag=200, /* Content size will be written into frame header _whenever known_ (default:1)
- * Content size must be known at the beginning of compression,
- * it is provided using ZSTD_CCtx_setPledgedSrcSize() */
- ZSTD_p_checksumFlag, /* A 32-bits checksum of content is written at end of frame (default:0) */
- ZSTD_p_dictIDFlag, /* When applicable, dictionary's ID is written into frame header (default:1) */
-
- /* multi-threading parameters */
- /* These parameters are only useful if multi-threading is enabled (ZSTD_MULTITHREAD).
- * They return an error otherwise. */
- ZSTD_p_nbWorkers=400, /* Select how many threads will be spawned to compress in parallel.
- * When nbWorkers >= 1, triggers asynchronous mode :
- * ZSTD_compress_generic() consumes some input, flush some output if possible, and immediately gives back control to caller,
- * while compression work is performed in parallel, within worker threads.
- * (note : a strong exception to this rule is when first invocation sets ZSTD_e_end : it becomes a blocking call).
- * More workers improve speed, but also increase memory usage.
- * Default value is `0`, aka "single-threaded mode" : no worker is spawned, compression is performed inside Caller's thread, all invocations are blocking */
- ZSTD_p_jobSize, /* Size of a compression job. This value is enforced only in non-blocking mode.
- * Each compression job is completed in parallel, so this value indirectly controls the nb of active threads.
- * 0 means default, which is dynamically determined based on compression parameters.
- * Job size must be a minimum of overlapSize, or 1 MB, whichever is largest.
- * The minimum size is automatically and transparently enforced */
- ZSTD_p_overlapSizeLog, /* Size of previous input reloaded at the beginning of each job.
- * 0 => no overlap, 6(default) => use 1/8th of windowSize, >=9 => use full windowSize */
-
- /* =================================================================== */
- /* experimental parameters - no stability guaranteed */
- /* =================================================================== */
-
- ZSTD_p_compressLiterals=1000, /* control huffman compression of literals (enabled) by default.
- * disabling it improves speed and decreases compression ratio by a large amount.
- * note : this setting is automatically updated when changing compression level.
- * positive compression levels set ZSTD_p_compressLiterals to 1.
- * negative compression levels set ZSTD_p_compressLiterals to 0. */
-
- ZSTD_p_forceMaxWindow=1100, /* Force back-reference distances to remain < windowSize,
- * even when referencing into Dictionary content (default:0) */
-
-} ZSTD_cParameter;
-
-
-/*! ZSTD_CCtx_setParameter() :
- * Set one compression parameter, selected by enum ZSTD_cParameter.
- * Setting a parameter is generally only possible during frame initialization (before starting compression),
- * except for a few exceptions which can be updated during compression: compressionLevel, hashLog, chainLog, searchLog, minMatch, targetLength and strategy.
- * Note : when `value` is an enum, cast it to unsigned for proper type checking.
- * @result : informational value (typically, value being set clamped correctly),
- * or an error code (which can be tested with ZSTD_isError()). */
-ZSTDLIB_API size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, unsigned value);
-
-/*! ZSTD_CCtx_setPledgedSrcSize() :
- * Total input data size to be compressed as a single frame.
- * This value will be controlled at the end, and result in error if not respected.
- * @result : 0, or an error code (which can be tested with ZSTD_isError()).
- * Note 1 : 0 means zero, empty.
- * In order to mean "unknown content size", pass constant ZSTD_CONTENTSIZE_UNKNOWN.
- * ZSTD_CONTENTSIZE_UNKNOWN is default value for any new compression job.
- * Note 2 : If all data is provided and consumed in a single round,
- * this value is overriden by srcSize instead. */
-ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize);
-
-/*! ZSTD_CCtx_loadDictionary() :
- * Create an internal CDict from `dict` buffer.
- * Decompression will have to use same dictionary.
- * @result : 0, or an error code (which can be tested with ZSTD_isError()).
- * Special: Adding a NULL (or 0-size) dictionary invalidates previous dictionary,
- * meaning "return to no-dictionary mode".
- * Note 1 : Dictionary will be used for all future compression jobs.
- * To return to "no-dictionary" situation, load a NULL dictionary
- * Note 2 : Loading a dictionary involves building tables, which are dependent on compression parameters.
- * For this reason, compression parameters cannot be changed anymore after loading a dictionary.
- * It's also a CPU consuming operation, with non-negligible impact on latency.
- * Note 3 :`dict` content will be copied internally.
- * Use ZSTD_CCtx_loadDictionary_byReference() to reference dictionary content instead.
- * In such a case, dictionary buffer must outlive its users.
- * Note 4 : Use ZSTD_CCtx_loadDictionary_advanced()
- * to precisely select how dictionary content must be interpreted. */
-ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize);
-ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary_byReference(ZSTD_CCtx* cctx, const void* dict, size_t dictSize);
-ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType);
-
-
-/*! ZSTD_CCtx_refCDict() :
- * Reference a prepared dictionary, to be used for all next compression jobs.
- * Note that compression parameters are enforced from within CDict,
- * and supercede any compression parameter previously set within CCtx.
- * The dictionary will remain valid for future compression jobs using same CCtx.
- * @result : 0, or an error code (which can be tested with ZSTD_isError()).
- * Special : adding a NULL CDict means "return to no-dictionary mode".
- * Note 1 : Currently, only one dictionary can be managed.
- * Adding a new dictionary effectively "discards" any previous one.
- * Note 2 : CDict is just referenced, its lifetime must outlive CCtx. */
-ZSTDLIB_API size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict);
-
-/*! ZSTD_CCtx_refPrefix() :
- * Reference a prefix (single-usage dictionary) for next compression job.
- * Decompression need same prefix to properly regenerate data.
- * Prefix is **only used once**. Tables are discarded at end of compression job.
- * Subsequent compression jobs will be done without prefix (if none is explicitly referenced).
- * If there is a need to use same prefix multiple times, consider embedding it into a ZSTD_CDict instead.
- * @result : 0, or an error code (which can be tested with ZSTD_isError()).
- * Special: Adding any prefix (including NULL) invalidates any previous prefix or dictionary
- * Note 1 : Prefix buffer is referenced. It must outlive compression job.
- * Note 2 : Referencing a prefix involves building tables, which are dependent on compression parameters.
- * It's a CPU consuming operation, with non-negligible impact on latency.
- * Note 3 : By default, the prefix is treated as raw content (ZSTD_dm_rawContent).
- * Use ZSTD_CCtx_refPrefix_advanced() to alter dictMode. */
-ZSTDLIB_API size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize);
-ZSTDLIB_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType);
-
-/*! ZSTD_CCtx_reset() :
- * Return a CCtx to clean state.
- * Useful after an error, or to interrupt an ongoing compression job and start a new one.
- * Any internal data not yet flushed is cancelled.
- * Dictionary (if any) is dropped.
- * All parameters are back to default values.
- * It's possible to modify compression parameters after a reset.
- */
-ZSTDLIB_API void ZSTD_CCtx_reset(ZSTD_CCtx* cctx);
-
-
-
-typedef enum {
- ZSTD_e_continue=0, /* collect more data, encoder decides when to output compressed result, for optimal conditions */
- ZSTD_e_flush, /* flush any data provided so far - frame will continue, future data can still reference previous data for better compression */
- ZSTD_e_end /* flush any remaining data and close current frame. Any additional data starts a new frame. */
-} ZSTD_EndDirective;
-
-/*! ZSTD_compress_generic() :
- * Behave about the same as ZSTD_compressStream. To note :
- * - Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_setParameter()
- * - Compression parameters cannot be changed once compression is started.
- * - outpot->pos must be <= dstCapacity, input->pos must be <= srcSize
- * - outpot->pos and input->pos will be updated. They are guaranteed to remain below their respective limit.
- * - In single-thread mode (default), function is blocking : it completed its job before returning to caller.
- * - In multi-thread mode, function is non-blocking : it just acquires a copy of input, and distribute job to internal worker threads,
- * and then immediately returns, just indicating that there is some data remaining to be flushed.
- * The function nonetheless guarantees forward progress : it will return only after it reads or write at least 1+ byte.
- * - Exception : in multi-threading mode, if the first call requests a ZSTD_e_end directive, it is blocking : it will complete compression before giving back control to caller.
- * - @return provides a minimum amount of data remaining to be flushed from internal buffers
- * or an error code, which can be tested using ZSTD_isError().
- * if @return != 0, flush is not fully completed, there is still some data left within internal buffers.
- * This is useful for ZSTD_e_flush, since in this case more flushes are necessary to empty all buffers.
- * For ZSTD_e_end, @return == 0 when internal buffers are fully flushed and frame is completed.
- * - after a ZSTD_e_end directive, if internal buffer is not fully flushed (@return != 0),
- * only ZSTD_e_end or ZSTD_e_flush operations are allowed.
- * Before starting a new compression job, or changing compression parameters,
- * it is required to fully flush internal buffers.
- */
-ZSTDLIB_API size_t ZSTD_compress_generic (ZSTD_CCtx* cctx,
- ZSTD_outBuffer* output,
- ZSTD_inBuffer* input,
- ZSTD_EndDirective endOp);
-
-
-/*! ZSTD_compress_generic_simpleArgs() :
- * Same as ZSTD_compress_generic(),
- * but using only integral types as arguments.
- * Argument list is larger than ZSTD_{in,out}Buffer,
- * but can be helpful for binders from dynamic languages
- * which have troubles handling structures containing memory pointers.
- */
-ZSTDLIB_API size_t ZSTD_compress_generic_simpleArgs (
- ZSTD_CCtx* cctx,
- void* dst, size_t dstCapacity, size_t* dstPos,
- const void* src, size_t srcSize, size_t* srcPos,
- ZSTD_EndDirective endOp);
-
-
-/*! ZSTD_CCtx_params :
- * Quick howto :
- * - ZSTD_createCCtxParams() : Create a ZSTD_CCtx_params structure
- * - ZSTD_CCtxParam_setParameter() : Push parameters one by one into
- * an existing ZSTD_CCtx_params structure.
- * This is similar to
- * ZSTD_CCtx_setParameter().
- * - ZSTD_CCtx_setParametersUsingCCtxParams() : Apply parameters to
- * an existing CCtx.
- * These parameters will be applied to
- * all subsequent compression jobs.
- * - ZSTD_compress_generic() : Do compression using the CCtx.
- * - ZSTD_freeCCtxParams() : Free the memory.
- *
- * This can be used with ZSTD_estimateCCtxSize_advanced_usingCCtxParams()
- * for static allocation for single-threaded compression.
- */
-ZSTDLIB_API ZSTD_CCtx_params* ZSTD_createCCtxParams(void);
-ZSTDLIB_API size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params);
-
-
-/*! ZSTD_CCtxParams_reset() :
- * Reset params to default values.
- */
-ZSTDLIB_API size_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params);
-
-/*! ZSTD_CCtxParams_init() :
- * Initializes the compression parameters of cctxParams according to
- * compression level. All other parameters are reset to their default values.
- */
-ZSTDLIB_API size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel);
-
-/*! ZSTD_CCtxParams_init_advanced() :
- * Initializes the compression and frame parameters of cctxParams according to
- * params. All other parameters are reset to their default values.
- */
-ZSTDLIB_API size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params);
-
-
-/*! ZSTD_CCtxParam_setParameter() :
- * Similar to ZSTD_CCtx_setParameter.
- * Set one compression parameter, selected by enum ZSTD_cParameter.
- * Parameters must be applied to a ZSTD_CCtx using ZSTD_CCtx_setParametersUsingCCtxParams().
- * Note : when `value` is an enum, cast it to unsigned for proper type checking.
- * @result : 0, or an error code (which can be tested with ZSTD_isError()).
- */
-ZSTDLIB_API size_t ZSTD_CCtxParam_setParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, unsigned value);
-
-/*! ZSTD_CCtx_setParametersUsingCCtxParams() :
- * Apply a set of ZSTD_CCtx_params to the compression context.
- * This can be done even after compression is started,
- * if nbWorkers==0, this will have no impact until a new compression is started.
- * if nbWorkers>=1, new parameters will be picked up at next job,
- * with a few restrictions (windowLog, pledgedSrcSize, nbWorkers, jobSize, and overlapLog are not updated).
- */
-ZSTDLIB_API size_t ZSTD_CCtx_setParametersUsingCCtxParams(
- ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params);
-
-
-/*=== Advanced parameters for decompression API ===*/
-
-/* The following parameters must be set after creating a ZSTD_DCtx* (or ZSTD_DStream*) object,
- * but before starting decompression of a frame.
- */
-
-/*! ZSTD_DCtx_loadDictionary() :
- * Create an internal DDict from dict buffer,
- * to be used to decompress next frames.
- * @result : 0, or an error code (which can be tested with ZSTD_isError()).
- * Special : Adding a NULL (or 0-size) dictionary invalidates any previous dictionary,
- * meaning "return to no-dictionary mode".
- * Note 1 : `dict` content will be copied internally.
- * Use ZSTD_DCtx_loadDictionary_byReference()
- * to reference dictionary content instead.
- * In which case, the dictionary buffer must outlive its users.
- * Note 2 : Loading a dictionary involves building tables,
- * which has a non-negligible impact on CPU usage and latency.
- * Note 3 : Use ZSTD_DCtx_loadDictionary_advanced() to select
- * how dictionary content will be interpreted and loaded.
- */
-ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize);
-ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx* dctx, const void* dict, size_t dictSize);
-ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType);
-
-
-/*! ZSTD_DCtx_refDDict() :
- * Reference a prepared dictionary, to be used to decompress next frames.
- * The dictionary remains active for decompression of future frames using same DCtx.
- * @result : 0, or an error code (which can be tested with ZSTD_isError()).
- * Note 1 : Currently, only one dictionary can be managed.
- * Referencing a new dictionary effectively "discards" any previous one.
- * Special : adding a NULL DDict means "return to no-dictionary mode".
- * Note 2 : DDict is just referenced, its lifetime must outlive its usage from DCtx.
- */
-ZSTDLIB_API size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict);
-
-
-/*! ZSTD_DCtx_refPrefix() :
- * Reference a prefix (single-usage dictionary) for next compression job.
- * Prefix is **only used once**. It must be explicitly referenced before each frame.
- * If there is a need to use same prefix multiple times, consider embedding it into a ZSTD_DDict instead.
- * @result : 0, or an error code (which can be tested with ZSTD_isError()).
- * Note 1 : Adding any prefix (including NULL) invalidates any previously set prefix or dictionary
- * Note 2 : Prefix buffer is referenced. It must outlive compression job.
- * Note 3 : By default, the prefix is treated as raw content (ZSTD_dm_rawContent).
- * Use ZSTD_CCtx_refPrefix_advanced() to alter dictMode.
- * Note 4 : Referencing a raw content prefix has almost no cpu nor memory cost.
- */
-ZSTDLIB_API size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize);
-ZSTDLIB_API size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType);
-
-
-/*! ZSTD_DCtx_setMaxWindowSize() :
- * Refuses allocating internal buffers for frames requiring a window size larger than provided limit.
- * This is useful to prevent a decoder context from reserving too much memory for itself (potential attack scenario).
- * This parameter is only useful in streaming mode, since no internal buffer is allocated in direct mode.
- * By default, a decompression context accepts all window sizes <= (1 << ZSTD_WINDOWLOG_MAX)
- * @return : 0, or an error code (which can be tested using ZSTD_isError()).
- */
-ZSTDLIB_API size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize);
-
-
-/*! ZSTD_DCtx_setFormat() :
- * Instruct the decoder context about what kind of data to decode next.
- * This instruction is mandatory to decode data without a fully-formed header,
- * such ZSTD_f_zstd1_magicless for example.
- * @return : 0, or an error code (which can be tested using ZSTD_isError()).
- */
-ZSTDLIB_API size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format);
-
-
-/*! ZSTD_decompress_generic() :
- * Behave the same as ZSTD_decompressStream.
- * Decompression parameters cannot be changed once decompression is started.
- * @return : an error code, which can be tested using ZSTD_isError()
- * if >0, a hint, nb of expected input bytes for next invocation.
- * `0` means : a frame has just been fully decoded and flushed.
- */
-ZSTDLIB_API size_t ZSTD_decompress_generic(ZSTD_DCtx* dctx,
- ZSTD_outBuffer* output,
- ZSTD_inBuffer* input);
-
-
-/*! ZSTD_decompress_generic_simpleArgs() :
- * Same as ZSTD_decompress_generic(),
- * but using only integral types as arguments.
- * Argument list is larger than ZSTD_{in,out}Buffer,
- * but can be helpful for binders from dynamic languages
- * which have troubles handling structures containing memory pointers.
- */
-ZSTDLIB_API size_t ZSTD_decompress_generic_simpleArgs (
- ZSTD_DCtx* dctx,
- void* dst, size_t dstCapacity, size_t* dstPos,
- const void* src, size_t srcSize, size_t* srcPos);
-
-
-/*! ZSTD_DCtx_reset() :
- * Return a DCtx to clean state.
- * If a decompression was ongoing, any internal data not yet flushed is cancelled.
- * All parameters are back to default values, including sticky ones.
- * Dictionary (if any) is dropped.
- * Parameters can be modified again after a reset.
- */
-ZSTDLIB_API void ZSTD_DCtx_reset(ZSTD_DCtx* dctx);
-
-
/* ============================ */
/** Block level API */
@@ -1372,10 +1888,10 @@ ZSTDLIB_API void ZSTD_DCtx_reset(ZSTD_DCtx* dctx);
+ copyCCtx() and copyDCtx() can be used too
- Block size is limited, it must be <= ZSTD_getBlockSize() <= ZSTD_BLOCKSIZE_MAX == 128 KB
+ If input is larger than a block size, it's necessary to split input data into multiple blocks
- + For inputs larger than a single block size, consider using the regular ZSTD_compress() instead.
+ + For inputs larger than a single block, really consider using regular ZSTD_compress() instead.
Frame metadata is not that costly, and quickly becomes negligible as source size grows larger.
- When a block is considered not compressible enough, ZSTD_compressBlock() result will be zero.
- In which case, nothing is produced into `dst`.
+ In which case, nothing is produced into `dst` !
+ User must test for such outcome and deal directly with uncompressed data
+ ZSTD_decompressBlock() doesn't accept uncompressed data as input !!!
+ In case of multiple successive blocks, should some of them be uncompressed,
@@ -1383,8 +1899,6 @@ ZSTDLIB_API void ZSTD_DCtx_reset(ZSTD_DCtx* dctx);
Use ZSTD_insertBlock() for such a case.
*/
-#define ZSTD_BLOCKSIZELOG_MAX 17
-#define ZSTD_BLOCKSIZE_MAX (1<<ZSTD_BLOCKSIZELOG_MAX) /* define, for static allocation */
/*===== Raw zstd block functions =====*/
ZSTDLIB_API size_t ZSTD_getBlockSize (const ZSTD_CCtx* cctx);
ZSTDLIB_API size_t ZSTD_compressBlock (ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);